diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/include/asm/io.h linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/io.h
--- linux-libre-3.16-gnu/arch/alpha/include/asm/io.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/io.h	2014-09-28 17:29:07.000000000 -0400
@@ -500,10 +500,14 @@ extern inline void writeq(u64 b, volatil
 #define outb_p		outb
 #define outw_p		outw
 #define outl_p		outl
-#define readb_relaxed(addr) __raw_readb(addr)
-#define readw_relaxed(addr) __raw_readw(addr)
-#define readl_relaxed(addr) __raw_readl(addr)
-#define readq_relaxed(addr) __raw_readq(addr)
+#define readb_relaxed(addr)	__raw_readb(addr)
+#define readw_relaxed(addr)	__raw_readw(addr)
+#define readl_relaxed(addr)	__raw_readl(addr)
+#define readq_relaxed(addr)	__raw_readq(addr)
+#define writeb_relaxed(b, addr)	__raw_writeb(b, addr)
+#define writew_relaxed(b, addr)	__raw_writew(b, addr)
+#define writel_relaxed(b, addr)	__raw_writel(b, addr)
+#define writeq_relaxed(b, addr)	__raw_writeq(b, addr)
 
 #define mmiowb()
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/alpha/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -6,4 +6,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/alpha/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -57,6 +57,7 @@ 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-3.16-gnu/arch/alpha/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/alpha/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ALPHA_SCATTERLIST_H
-#define _ALPHA_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_ALPHA_SCATTERLIST_H) */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/alpha/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <uapi/asm/unistd.h>
 
-#define NR_SYSCALLS			508
+#define NR_SYSCALLS			511
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/alpha/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/alpha/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -469,5 +469,8 @@
 #define __NR_process_vm_writev		505
 #define __NR_kcmp			506
 #define __NR_finit_module		507
+#define __NR_sched_setattr		508
+#define __NR_sched_getattr		509
+#define __NR_renameat2			510
 
 #endif /* _UAPI_ALPHA_UNISTD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/alpha/kernel/systbls.S linux-libre-3.17-rc7-gnu/arch/alpha/kernel/systbls.S
--- linux-libre-3.16-gnu/arch/alpha/kernel/systbls.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/alpha/kernel/systbls.S	2014-09-28 17:29:07.000000000 -0400
@@ -526,6 +526,9 @@ sys_call_table:
 	.quad sys_process_vm_writev		/* 505 */
 	.quad sys_kcmp
 	.quad sys_finit_module
+	.quad sys_sched_setattr
+	.quad sys_sched_getattr
+	.quad sys_renameat2			/* 510 */
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/boot/dts/angel4.dts linux-libre-3.17-rc7-gnu/arch/arc/boot/dts/angel4.dts
--- linux-libre-3.16-gnu/arch/arc/boot/dts/angel4.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/boot/dts/angel4.dts	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,7 @@
 	interrupt-parent = <&intc>;
 
 	chosen {
-		bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
+		bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
 	};
 
 	aliases {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/include/asm/arcregs.h linux-libre-3.17-rc7-gnu/arch/arc/include/asm/arcregs.h
--- linux-libre-3.16-gnu/arch/arc/include/asm/arcregs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/include/asm/arcregs.h	2014-09-28 17:29:07.000000000 -0400
@@ -296,7 +296,7 @@ struct cpuinfo_arc_mmu {
 };
 
 struct cpuinfo_arc_cache {
-	unsigned int sz, line_len, assoc, ver;
+	unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
 };
 
 struct cpuinfo_arc_ccm {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/include/asm/irqflags.h linux-libre-3.17-rc7-gnu/arch/arc/include/asm/irqflags.h
--- linux-libre-3.16-gnu/arch/arc/include/asm/irqflags.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/include/asm/irqflags.h	2014-09-28 17:29:07.000000000 -0400
@@ -131,24 +131,6 @@ static inline int arch_irqs_disabled(voi
 	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-static inline void arch_mask_irq(unsigned int irq)
-{
-	unsigned int ienb;
-
-	ienb = read_aux_reg(AUX_IENABLE);
-	ienb &= ~(1 << irq);
-	write_aux_reg(AUX_IENABLE, ienb);
-}
-
-static inline void arch_unmask_irq(unsigned int irq)
-{
-	unsigned int ienb;
-
-	ienb = read_aux_reg(AUX_IENABLE);
-	ienb |= (1 << irq);
-	write_aux_reg(AUX_IENABLE, ienb);
-}
-
 #else
 
 #ifdef CONFIG_TRACE_IRQFLAGS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/include/asm/irq.h linux-libre-3.17-rc7-gnu/arch/arc/include/asm/irq.h
--- linux-libre-3.16-gnu/arch/arc/include/asm/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/include/asm/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,9 +16,13 @@
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
 
+#include <linux/interrupt.h>
 #include <asm-generic/irq.h>
 
 extern void arc_init_IRQ(void);
 void arc_local_timer_setup(void);
+void arc_request_percpu_irq(int irq, int cpu,
+                            irqreturn_t (*isr)(int irq, void *dev),
+                            const char *irq_nm, void *percpu_dev);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/arc/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/arc/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,6 +62,8 @@ unsigned long thread_saved_pc(struct tas
 #define cpu_relax()	do { } while (0)
 #endif
 
+#define cpu_relax_lowlatency() cpu_relax()
+
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/arc/kernel/irq.c
--- linux-libre-3.16-gnu/arch/arc/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,21 +19,16 @@
 
 /*
  * Early Hardware specific Interrupt setup
+ * -Platform independent, needed for each CPU (not foldable into init_IRQ)
  * -Called very early (start_kernel -> setup_arch -> setup_processor)
- * -Platform Independent (must for any ARC700)
- * -Needed for each CPU (hence not foldable into init_IRQ)
  *
  * what it does ?
- * -Disable all IRQs (on CPU side)
  * -Optionally, setup the High priority Interrupts as Level 2 IRQs
  */
 void arc_init_IRQ(void)
 {
 	int level_mask = 0;
 
-	/* Disable all IRQs: enable them as devices request */
-	write_aux_reg(AUX_IENABLE, 0);
-
        /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
 	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
 	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
@@ -60,20 +55,28 @@ void arc_init_IRQ(void)
  * below, per IRQ.
  */
 
-static void arc_mask_irq(struct irq_data *data)
+static void arc_irq_mask(struct irq_data *data)
 {
-	arch_mask_irq(data->irq);
+	unsigned int ienb;
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb &= ~(1 << data->irq);
+	write_aux_reg(AUX_IENABLE, ienb);
 }
 
-static void arc_unmask_irq(struct irq_data *data)
+static void arc_irq_unmask(struct irq_data *data)
 {
-	arch_unmask_irq(data->irq);
+	unsigned int ienb;
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb |= (1 << data->irq);
+	write_aux_reg(AUX_IENABLE, ienb);
 }
 
 static struct irq_chip onchip_intc = {
 	.name           = "ARC In-core Intc",
-	.irq_mask	= arc_mask_irq,
-	.irq_unmask	= arc_unmask_irq,
+	.irq_mask	= arc_irq_mask,
+	.irq_unmask	= arc_irq_unmask,
 };
 
 static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
@@ -150,6 +153,32 @@ void arch_do_IRQ(unsigned int irq, struc
 	set_irq_regs(old_regs);
 }
 
+void arc_request_percpu_irq(int irq, int cpu,
+                            irqreturn_t (*isr)(int irq, void *dev),
+                            const char *irq_nm,
+                            void *percpu_dev)
+{
+	/* Boot cpu calls request, all call enable */
+	if (!cpu) {
+		int rc;
+
+		/*
+		 * These 2 calls are essential to making percpu IRQ APIs work
+		 * Ideally these details could be hidden in irq chip map function
+		 * but the issue is IPIs IRQs being static (non-DT) and platform
+		 * specific, so we can't identify them there.
+		 */
+		irq_set_percpu_devid(irq);
+		irq_modify_status(irq, IRQ_NOAUTOEN, 0);  /* @irq, @clr, @set */
+
+		rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev);
+		if (rc)
+			panic("Percpu IRQ request failed for %d\n", irq);
+	}
+
+	enable_percpu_irq(irq, 0);
+}
+
 /*
  * arch_local_irq_enable - Enable interrupts.
  *
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/kernel/perf_event.c linux-libre-3.17-rc7-gnu/arch/arc/kernel/perf_event.c
--- linux-libre-3.16-gnu/arch/arc/kernel/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/kernel/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,10 +99,6 @@ static int arc_pmu_event_init(struct per
 	struct hw_perf_event *hwc = &event->hw;
 	int ret;
 
-	/* ARC 700 PMU does not support sampling events */
-	if (is_sampling_event(event))
-		return -ENOENT;
-
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
 		if (event->attr.config >= PERF_COUNT_HW_MAX)
@@ -298,6 +294,9 @@ static int arc_pmu_device_probe(struct p
 		.read		= arc_pmu_read,
 	};
 
+	/* ARC 700 PMU does not support sampling events */
+	arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/arc/kernel/signal.c
--- linux-libre-3.16-gnu/arch/arc/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,17 +141,13 @@ badframe:
 /*
  * Determine which stack to use..
  */
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
 					struct pt_regs *regs,
 					unsigned long framesize)
 {
-	unsigned long sp = regs->sp;
+	unsigned long sp = sigsp(regs->sp, ksig);
 	void __user *frame;
 
-	/* This is the X/Open sanctioned signal stack switching */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
 	/* No matter what happens, 'sp' must be word
 	 * aligned otherwise nasty things could happen
 	 */
@@ -179,14 +175,13 @@ static inline int map_sig(int sig)
 }
 
 static int
-setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *sf;
 	unsigned int magic = 0;
 	int err = 0;
 
-	sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+	sf = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
 	if (!sf)
 		return 1;
 
@@ -205,8 +200,8 @@ setup_rt_frame(int signo, struct k_sigac
 	 *  #2: struct siginfo
 	 *  #3: struct ucontext (completely populated)
 	 */
-	if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) {
-		err |= copy_siginfo_to_user(&sf->info, info);
+	if (unlikely(ksig->ka.sa.sa_flags & SA_SIGINFO)) {
+		err |= copy_siginfo_to_user(&sf->info, &ksig->info);
 		err |= __put_user(0, &sf->uc.uc_flags);
 		err |= __put_user(NULL, &sf->uc.uc_link);
 		err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
@@ -227,16 +222,16 @@ setup_rt_frame(int signo, struct k_sigac
 		return err;
 
 	/* #1 arg to the user Signal handler */
-	regs->r0 = map_sig(signo);
+	regs->r0 = map_sig(ksig->sig);
 
 	/* setup PC of user space signal handler */
-	regs->ret = (unsigned long)ka->sa.sa_handler;
+	regs->ret = (unsigned long)ksig->ka.sa.sa_handler;
 
 	/*
 	 * handler returns using sigreturn stub provided already by userpsace
 	 */
-	BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
-	regs->blink = (unsigned long)ka->sa.sa_restorer;
+	BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER));
+	regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
 
 	/* User Stack for signal handler will be above the frame just carved */
 	regs->sp = (unsigned long)sf;
@@ -298,38 +293,30 @@ static void arc_restart_syscall(struct k
  * OK, we're invoking a handler
  */
 static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 
 	/* Set up the stack frame */
-	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	ret = setup_rt_frame(ksig, oldset, regs);
 
-	if (ret)
-		force_sigsegv(sig, current);
-	else
-		signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 void do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 	int restart_scall;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
 	restart_scall = in_syscall(regs) && syscall_restartable(regs);
 
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		if (restart_scall) {
-			arc_restart_syscall(&ka, regs);
+			arc_restart_syscall(&ksig.ka, regs);
 			syscall_wont_restart(regs);	/* No more restarts */
 		}
-		handle_signal(signr, &ka, &info, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/arc/kernel/smp.c
--- linux-libre-3.16-gnu/arch/arc/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,23 +12,15 @@
  *    -- Initial Write (Borrowed heavily from ARM)
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/profile.h>
-#include <linux/errno.h>
-#include <linux/err.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
-#include <linux/smp.h>
 #include <linux/irq.h>
-#include <linux/delay.h>
 #include <linux/atomic.h>
-#include <linux/percpu.h>
 #include <linux/cpumask.h>
-#include <linux/spinlock_types.h>
 #include <linux/reboot.h>
 #include <asm/processor.h>
 #include <asm/setup.h>
@@ -136,7 +128,7 @@ void start_kernel_secondary(void)
 	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
 	if (machine_desc->init_smp)
-		machine_desc->init_smp(smp_processor_id());
+		machine_desc->init_smp(cpu);
 
 	arc_local_timer_setup();
 
@@ -338,18 +330,11 @@ irqreturn_t do_IPI(int irq, void *dev_id
  */
 static DEFINE_PER_CPU(int, ipi_dev);
 
-static struct irqaction arc_ipi_irq = {
-        .name    = "IPI Interrupt",
-        .flags   = IRQF_PERCPU,
-        .handler = do_IPI,
-};
-
 int smp_ipi_irq_setup(int cpu, int irq)
 {
-	if (!cpu)
-		return setup_irq(irq, &arc_ipi_irq);
-	else
-		arch_unmask_irq(irq);
+	int *dev = per_cpu_ptr(&ipi_dev, cpu);
+
+	arc_request_percpu_irq(irq, cpu, do_IPI, "IPI Interrupt", dev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/kernel/time.c linux-libre-3.17-rc7-gnu/arch/arc/kernel/time.c
--- linux-libre-3.16-gnu/arch/arc/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -144,12 +144,12 @@ static struct clocksource arc_counter =
 /********** Clock Event Device *********/
 
 /*
- * Arm the timer to interrupt after @limit cycles
+ * 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 limit)
+static void arc_timer_event_setup(unsigned int cycles)
 {
-	write_aux_reg(ARC_REG_TIMER0_LIMIT, limit);
+	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);
@@ -168,6 +168,10 @@ static void arc_clkevent_set_mode(enum c
 {
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
+                /*
+                 * At X Hz, 1 sec = 1000ms -> X cycles;
+                 *                    10ms -> X / 100 cycles
+                 */
 		arc_timer_event_setup(arc_get_core_freq() / HZ);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -210,12 +214,6 @@ static irqreturn_t timer_irq_handler(int
 	return IRQ_HANDLED;
 }
 
-static struct irqaction arc_timer_irq = {
-	.name    = "Timer0 (clock-evt-dev)",
-	.flags   = IRQF_TIMER | IRQF_PERCPU,
-	.handler = timer_irq_handler,
-};
-
 /*
  * Setup the local event timer for @cpu
  */
@@ -228,15 +226,9 @@ void arc_local_timer_setup()
 	clockevents_config_and_register(evt, arc_get_core_freq(),
 					0, ARC_TIMER_MAX);
 
-	/*
-	 * setup the per-cpu timer IRQ handler - for all cpus
-	 * For non boot CPU explicitly unmask at intc
-	 * setup_irq() -> .. -> irq_startup() already does this on boot-cpu
-	 */
-	if (!cpu)
-		setup_irq(TIMER0_IRQ, &arc_timer_irq);
-	else
-		arch_unmask_irq(TIMER0_IRQ);
+	/* setup the per-cpu timer IRQ handler - for all cpus */
+	arc_request_percpu_irq(TIMER0_IRQ, cpu, timer_irq_handler,
+			       "Timer0 (per-cpu-tick)", evt);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/mm/cache_arc700.c linux-libre-3.17-rc7-gnu/arch/arc/mm/cache_arc700.c
--- linux-libre-3.16-gnu/arch/arc/mm/cache_arc700.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/mm/cache_arc700.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,21 +77,19 @@ char *arc_cache_mumbojumbo(int c, char *
 {
 	int n = 0;
 
-#define PR_CACHE(p, enb, str)						\
-{									\
+#define PR_CACHE(p, cfg, str)						\
 	if (!(p)->ver)							\
 		n += scnprintf(buf + n, len - n, str"\t\t: N/A\n");	\
 	else								\
 		n += scnprintf(buf + n, len - n,			\
-			str"\t\t: (%uK) VIPT, %dway set-asc, %ub Line %s\n", \
-			TO_KB((p)->sz), (p)->assoc, (p)->line_len,	\
-			enb ?  "" : "DISABLED (kernel-build)");		\
-}
+			str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n",	\
+			(p)->sz_k, (p)->assoc, (p)->line_len,		\
+			(p)->vipt ? "VIPT" : "PIPT",			\
+			(p)->alias ? " aliasing" : "",			\
+			IS_ENABLED(cfg) ? "" : " (not used)");
 
-	PR_CACHE(&cpuinfo_arc700[c].icache, IS_ENABLED(CONFIG_ARC_HAS_ICACHE),
-			"I-Cache");
-	PR_CACHE(&cpuinfo_arc700[c].dcache, IS_ENABLED(CONFIG_ARC_HAS_DCACHE),
-			"D-Cache");
+	PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
+	PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
 
 	return buf;
 }
@@ -116,20 +114,31 @@ void read_decode_cache_bcr(void)
 	p_ic = &cpuinfo_arc700[cpu].icache;
 	READ_BCR(ARC_REG_IC_BCR, ibcr);
 
+	if (!ibcr.ver)
+		goto dc_chk;
+
 	BUG_ON(ibcr.config != 3);
 	p_ic->assoc = 2;		/* Fixed to 2w set assoc */
 	p_ic->line_len = 8 << ibcr.line_len;
-	p_ic->sz = 0x200 << ibcr.sz;
+	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;
 
+dc_chk:
 	p_dc = &cpuinfo_arc700[cpu].dcache;
 	READ_BCR(ARC_REG_DC_BCR, dbcr);
 
+	if (!dbcr.ver)
+		return;
+
 	BUG_ON(dbcr.config != 2);
 	p_dc->assoc = 4;		/* Fixed to 4w set assoc */
 	p_dc->line_len = 16 << dbcr.line_len;
-	p_dc->sz = 0x200 << dbcr.sz;
+	p_dc->sz_k = 1 << (dbcr.sz - 1);
 	p_dc->ver = dbcr.ver;
+	p_dc->vipt = 1;
+	p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
 }
 
 /*
@@ -142,14 +151,16 @@ void read_decode_cache_bcr(void)
 void arc_cache_init(void)
 {
 	unsigned int __maybe_unused cpu = smp_processor_id();
-	struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc;
 	char str[256];
 
 	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
 
-#ifdef CONFIG_ARC_HAS_ICACHE
-	ic = &cpuinfo_arc700[cpu].icache;
-	if (ic->ver) {
+	if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
+		struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
+
+		if (!ic->ver)
+			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);
@@ -158,26 +169,26 @@ void arc_cache_init(void)
 			panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
 			      ic->ver, CONFIG_ARC_MMU_VER);
 	}
-#endif
 
-#ifdef CONFIG_ARC_HAS_DCACHE
-	dc = &cpuinfo_arc700[cpu].dcache;
-	if (dc->ver) {
-		unsigned int dcache_does_alias;
+	if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
+		struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
+		int handled;
+
+		if (!dc->ver)
+			panic("cache support enabled but non-existent cache\n");
 
 		if (dc->line_len != L1_CACHE_BYTES)
 			panic("DCache line [%d] != kernel Config [%d]",
 			      dc->line_len, L1_CACHE_BYTES);
 
 		/* check for D-Cache aliasing */
-		dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE;
+		handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
 
-		if (dcache_does_alias && !cache_is_vipt_aliasing())
+		if (dc->alias && !handled)
 			panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-		else if (!dcache_does_alias && cache_is_vipt_aliasing())
+		else if (!dc->alias && handled)
 			panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n");
 	}
-#endif
 }
 
 #define OP_INV		0x1
@@ -255,10 +266,32 @@ static inline void __cache_line_loop(uns
  * Machine specific helpers for Entire D-Cache or Per Line ops
  */
 
-static inline void wait_for_flush(void)
+static unsigned int __before_dc_op(const int op)
 {
-	while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
-		;
+	unsigned int reg = reg;
+
+	if (op == OP_FLUSH_N_INV) {
+		/* Dcache provides 2 cmd: FLUSH or INV
+		 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
+		 * flush-n-inv is achieved by INV cmd but with IM=1
+		 * So toggle INV sub-mode depending on op request and default
+		 */
+		reg = read_aux_reg(ARC_REG_DC_CTRL);
+		write_aux_reg(ARC_REG_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH)
+			;
+	}
+
+	return reg;
+}
+
+static void __after_dc_op(const int op, unsigned int reg)
+{
+	if (op & OP_FLUSH)	/* flush / flush-n-inv both wait */
+		while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
+
+	/* Switch back to default Invalidate mode */
+	if (op == OP_FLUSH_N_INV)
+		write_aux_reg(ARC_REG_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
 }
 
 /*
@@ -269,18 +302,10 @@ static inline void wait_for_flush(void)
  */
 static inline void __dc_entire_op(const int cacheop)
 {
-	unsigned int tmp = tmp;
+	unsigned int ctrl_reg;
 	int aux;
 
-	if (cacheop == OP_FLUSH_N_INV) {
-		/* Dcache provides 2 cmd: FLUSH or INV
-		 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
-		 * flush-n-inv is achieved by INV cmd but with IM=1
-		 * Default INV sub-mode is DISCARD, which needs to be toggled
-		 */
-		tmp = read_aux_reg(ARC_REG_DC_CTRL);
-		write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
-	}
+	ctrl_reg = __before_dc_op(cacheop);
 
 	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
 		aux = ARC_REG_DC_IVDC;
@@ -289,12 +314,7 @@ static inline void __dc_entire_op(const
 
 	write_aux_reg(aux, 0x1);
 
-	if (cacheop & OP_FLUSH)	/* flush / flush-n-inv both wait */
-		wait_for_flush();
-
-	/* Switch back the DISCARD ONLY Invalidate mode */
-	if (cacheop == OP_FLUSH_N_INV)
-		write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+	__after_dc_op(cacheop, ctrl_reg);
 }
 
 /* For kernel mappings cache operation: index is same as paddr */
@@ -306,29 +326,16 @@ static inline void __dc_entire_op(const
 static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
 				unsigned long sz, const int cacheop)
 {
-	unsigned long flags, tmp = tmp;
+	unsigned long flags;
+	unsigned int ctrl_reg;
 
 	local_irq_save(flags);
 
-	if (cacheop == OP_FLUSH_N_INV) {
-		/*
-		 * Dcache provides 2 cmd: FLUSH or INV
-		 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
-		 * flush-n-inv is achieved by INV cmd but with IM=1
-		 * Default INV sub-mode is DISCARD, which needs to be toggled
-		 */
-		tmp = read_aux_reg(ARC_REG_DC_CTRL);
-		write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
-	}
+	ctrl_reg = __before_dc_op(cacheop);
 
 	__cache_line_loop(paddr, vaddr, sz, cacheop);
 
-	if (cacheop & OP_FLUSH)	/* flush / flush-n-inv both wait */
-		wait_for_flush();
-
-	/* Switch back the DISCARD ONLY Invalidate mode */
-	if (cacheop == OP_FLUSH_N_INV)
-		write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+	__after_dc_op(cacheop, ctrl_reg);
 
 	local_irq_restore(flags);
 }
@@ -389,8 +396,16 @@ static inline void __dc_line_op(unsigned
 /***********************************************************
  * Machine specific helper for per line I-Cache invalidate.
  */
-static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
-				unsigned long sz)
+
+static inline void __ic_entire_inv(void)
+{
+	write_aux_reg(ARC_REG_IC_IVIC, 1);
+	read_aux_reg(ARC_REG_IC_CTRL);	/* blocks */
+}
+
+static inline void
+__ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
+			  unsigned long sz)
 {
 	unsigned long flags;
 
@@ -399,30 +414,39 @@ static void __ic_line_inv_vaddr_local(un
 	local_irq_restore(flags);
 }
 
-static inline void __ic_entire_inv(void)
-{
-	write_aux_reg(ARC_REG_IC_IVIC, 1);
-	read_aux_reg(ARC_REG_IC_CTRL);	/* blocks */
-}
+#ifndef CONFIG_SMP
 
-struct ic_line_inv_vaddr_ipi {
+#define __ic_line_inv_vaddr(p, v, s)	__ic_line_inv_vaddr_local(p, v, s)
+
+#else
+
+struct ic_inv_args {
 	unsigned long paddr, vaddr;
 	int sz;
 };
 
 static void __ic_line_inv_vaddr_helper(void *info)
 {
-        struct ic_line_inv_vaddr_ipi *ic_inv = (struct ic_line_inv_vaddr_ipi*) info;
+        struct ic_inv_args *ic_inv = info;
+
         __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
 }
 
 static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
 				unsigned long sz)
 {
-	struct ic_line_inv_vaddr_ipi ic_inv = { paddr, vaddr , sz};
+	struct ic_inv_args ic_inv = {
+		.paddr = paddr,
+		.vaddr = vaddr,
+		.sz    = sz
+	};
+
 	on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1);
 }
-#else
+
+#endif	/* CONFIG_SMP */
+
+#else	/* !CONFIG_ARC_HAS_ICACHE */
 
 #define __ic_entire_inv()
 #define __ic_line_inv_vaddr(pstart, vstart, sz)
@@ -557,6 +581,7 @@ void flush_icache_range(unsigned long ks
 		tot_sz -= sz;
 	}
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 /*
  * General purpose helper to make I and D cache lines consistent.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/mm/fault.c linux-libre-3.17-rc7-gnu/arch/arc/mm/fault.c
--- linux-libre-3.16-gnu/arch/arc/mm/fault.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/mm/fault.c	2014-09-28 17:29:07.000000000 -0400
@@ -159,7 +159,6 @@ good_area:
 		return;
 	}
 
-	/* TBD: switch to pagefault_out_of_memory() */
 	if (fault & VM_FAULT_OOM)
 		goto out_of_memory;
 	else if (fault & VM_FAULT_SIGBUS)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/mm/tlbex.S linux-libre-3.17-rc7-gnu/arch/arc/mm/tlbex.S
--- linux-libre-3.16-gnu/arch/arc/mm/tlbex.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/mm/tlbex.S	2014-09-28 17:29:07.000000000 -0400
@@ -220,9 +220,9 @@ ex_saved_reg1:
 
 .macro CONV_PTE_TO_TLB
 	and    r3, r0, PTE_BITS_RWX	;       r w x
-	lsl    r2, r3, 3		; r w x 0 0 0
+	lsl    r2, r3, 3		; r w x 0 0 0 (GLOBAL, kernel only)
 	and.f  0,  r0, _PAGE_GLOBAL
-	or.z   r2, r2, r3		; r w x r w x
+	or.z   r2, r2, r3		; r w x r w x (!GLOBAL, user page)
 
 	and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE
 	or  r3, r3, r2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/plat-arcfpga/include/plat/irq.h linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/include/plat/irq.h
--- linux-libre-3.16-gnu/arch/arc/plat-arcfpga/include/plat/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/include/plat/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,4 @@
 #define IDU_INTERRUPT_0 16
 #endif
 
-extern void __init plat_fpga_init_IRQ(void);
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/plat-arcfpga/irq.c linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/irq.c
--- linux-libre-3.16-gnu/arch/arc/plat-arcfpga/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/*
- * ARC FPGA Platform IRQ hookups
- *
- * Copyright (C) 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.
- */
-
-#include <linux/interrupt.h>
-#include <plat/irq.h>
-
-void __init plat_fpga_init_IRQ(void)
-{
-	/*
-	 * SMP Hack because UART IRQ hardwired to cpu0 (boot-cpu) but if the
-	 * request_irq() comes from any other CPU, the low level IRQ unamsking
-	 * essential for getting Interrupts won't be enabled on cpu0, locking
-	 * up the UART state machine.
-	 */
-#ifdef CONFIG_SMP
-	arch_unmask_irq(UART0_IRQ);
-#endif
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/plat-arcfpga/Kconfig linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/Kconfig
--- linux-libre-3.16-gnu/arch/arc/plat-arcfpga/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,4 @@ config ISS_SMP_EXTN
 	  -XTL (To enable CPU start/stop/set-PC for another CPU)
 	  It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
 
-config ARC_SERIAL_BAUD
-	int "UART Baud rate"
-	default "115200"
-	depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
-	help
-	  Baud rate for the ARC UART
-
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/plat-arcfpga/Makefile linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/Makefile
--- linux-libre-3.16-gnu/arch/arc/plat-arcfpga/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,5 +8,5 @@
 
 KBUILD_CFLAGS	+= -Iarch/arc/plat-arcfpga/include
 
-obj-y := platform.o irq.o
+obj-y := platform.o
 obj-$(CONFIG_ISS_SMP_EXTN)		+= smp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arc/plat-arcfpga/platform.c linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/platform.c
--- linux-libre-3.16-gnu/arch/arc/plat-arcfpga/platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arc/plat-arcfpga/platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,115 +22,22 @@
 #include <plat/smp.h>
 #include <plat/irq.h>
 
-/*----------------------- Platform Devices -----------------------------*/
-
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-static unsigned long arc_uart_info[] = {
-	0,	/* uart->is_emulated (runtime @running_on_hw) */
-	0,	/* uart->port.uartclk */
-	0,	/* uart->baud */
-	0
-};
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-/*
- * static platform data - but only for early serial
- * TBD: derive this from a special DT node
- */
-static struct resource arc_uart0_res[] = {
-	{
-		.start = UART0_BASE,
-		.end   = UART0_BASE + 0xFF,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = UART0_IRQ,
-		.end   = UART0_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device arc_uart0_dev = {
-	.name = "arc-uart",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(arc_uart0_res),
-	.resource = arc_uart0_res,
-	.dev = {
-		.platform_data = &arc_uart_info,
-	},
-};
-
-static struct platform_device *fpga_early_devs[] __initdata = {
-	&arc_uart0_dev,
-};
-#endif	/* CONFIG_SERIAL_ARC_CONSOLE */
-
-static void arc_fpga_serial_init(void)
-{
-	/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
-	arc_uart_info[0] = !running_on_hw;
-
-	arc_uart_info[1] = arc_get_core_freq();
-
-	arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-	early_platform_add_devices(fpga_early_devs,
-				   ARRAY_SIZE(fpga_early_devs));
-
-	/*
-	 * ARC console driver registers (build time) as an early platform driver
-	 * of class "earlyprintk". However it needs explicit cmdline toggle
-	 * "earlyprintk=ttyARC0" to be successfuly runtime registered.
-	 * Otherwise the early probe below fails to find the driver
-	 */
-	early_platform_driver_probe("earlyprintk", 1, 0);
-
-	/*
-	 * This is to make sure that arc uart would be preferred console
-	 * despite one/more of following:
-	 *   -command line lacked "console=ttyARC0" or
-	 *   -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
-	 * Note that this needs to be done after above early console is reg,
-	 * otherwise the early console never gets a chance to run.
-	 */
-	add_preferred_console("ttyARC", 0, "115200");
-#endif	/* CONFIG_SERIAL_ARC_CONSOLE */
-}
-#else	/* !IS_ENABLED(CONFIG_SERIAL_ARC) */
-static void arc_fpga_serial_init(void)
-{
-}
-#endif
-
 static void __init plat_fpga_early_init(void)
 {
 	pr_info("[plat-arcfpga]: registering early dev resources\n");
 
-	arc_fpga_serial_init();
-
 #ifdef CONFIG_ISS_SMP_EXTN
 	iss_model_init_early_smp();
 #endif
 }
 
-static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-	OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
-#endif
-	{}
-};
-
 static void __init plat_fpga_populate_dev(void)
 {
-	pr_info("[plat-arcfpga]: registering device resources\n");
-
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
-	 * complete with their resources
+	 * (if any) complete with their resources
 	 */
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     plat_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 /*----------------------- Machine Descriptions ------------------------------
@@ -150,7 +57,6 @@ MACHINE_START(ANGEL4, "angel4")
 	.dt_compat	= aa4_compat,
 	.init_early	= plat_fpga_early_init,
 	.init_machine	= plat_fpga_populate_dev,
-	.init_irq	= plat_fpga_init_IRQ,
 #ifdef CONFIG_ISS_SMP_EXTN
 	.init_smp	= iss_model_init_smp,
 #endif
@@ -165,7 +71,6 @@ MACHINE_START(ML509, "ml509")
 	.dt_compat	= ml509_compat,
 	.init_early	= plat_fpga_early_init,
 	.init_machine	= plat_fpga_populate_dev,
-	.init_irq	= plat_fpga_init_IRQ,
 #ifdef CONFIG_SMP
 	.init_smp	= iss_model_init_smp,
 #endif
@@ -180,5 +85,4 @@ MACHINE_START(NSIMOSCI, "nsimosci")
 	.dt_compat	= nsimosci_compat,
 	.init_early	= NULL,
 	.init_machine	= plat_fpga_populate_dev,
-	.init_irq	= NULL,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/compressed/head.S linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/head.S
--- linux-libre-3.16-gnu/arch/arm/boot/compressed/head.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/head.S	2014-09-28 17:29:07.000000000 -0400
@@ -125,9 +125,11 @@ start:
  THUMB(		adr	r12, BSYM(1f)	)
  THUMB(		bx	r12		)
 
-		.word	0x016f2818		@ Magic numbers to help the loader
-		.word	start			@ absolute load/run zImage address
-		.word	_edata			@ zImage end address
+		.word	_magic_sig	@ Magic numbers to help the loader
+		.word	_magic_start	@ absolute load/run zImage address
+		.word	_magic_end	@ zImage end address
+		.word	0x04030201	@ endianness flag
+
  THUMB(		.thumb			)
 1:
  ARM_BE8(	setend	be )			@ go BE8 if compiled for BE8
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/compressed/Makefile linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/Makefile
--- linux-libre-3.16-gnu/arch/arm/boot/compressed/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -81,7 +81,7 @@ ZTEXTADDR	:= 0
 ZBSSADDR	:= ALIGN(8)
 endif
 
-SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
+CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
 
 suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
@@ -199,8 +199,5 @@ CFLAGS_font.o := -Dstatic=
 $(obj)/font.c: $(FONTC)
 	$(call cmd,shipped)
 
-$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
-	@sed "$(SEDFLAGS)" < $< > $@
-
 $(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
 	$(call cmd,shipped)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/compressed/vmlinux.lds.in linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-libre-3.16-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/vmlinux.lds.in	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- *  linux/arch/arm/boot/compressed/vmlinux.lds.in
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-  /DISCARD/ : {
-    *(.ARM.exidx*)
-    *(.ARM.extab*)
-    /*
-     * Discard any r/w data - this produces a link error if we have any,
-     * which is required for PIC decompression.  Local data generates
-     * GOTOFF relocations, which prevents it being relocated independently
-     * of the text/got segments.
-     */
-    *(.data)
-  }
-
-  . = TEXT_START;
-  _text = .;
-
-  .text : {
-    _start = .;
-    *(.start)
-    *(.text)
-    *(.text.*)
-    *(.fixup)
-    *(.gnu.warning)
-    *(.glue_7t)
-    *(.glue_7)
-  }
-  .rodata : {
-    *(.rodata)
-    *(.rodata.*)
-  }
-  .piggydata : {
-    *(.piggydata)
-  }
-
-  . = ALIGN(4);
-  _etext = .;
-
-  .got.plt		: { *(.got.plt) }
-  _got_start = .;
-  .got			: { *(.got) }
-  _got_end = .;
-
-  /* ensure the zImage file size is always a multiple of 64 bits */
-  /* (without a dummy byte, ld just ignores the empty section) */
-  .pad			: { BYTE(0); . = ALIGN(8); }
-  _edata = .;
-
-  . = BSS_START;
-  __bss_start = .;
-  .bss			: { *(.bss) }
-  _end = .;
-
-  . = ALIGN(8);		/* the stack must be 64-bit aligned */
-  .stack		: { *(.stack) }
-
-  .stab 0		: { *(.stab) }
-  .stabstr 0		: { *(.stabstr) }
-  .stab.excl 0		: { *(.stab.excl) }
-  .stab.exclstr 0	: { *(.stab.exclstr) }
-  .stab.index 0		: { *(.stab.index) }
-  .stab.indexstr 0	: { *(.stab.indexstr) }
-  .comment 0		: { *(.comment) }
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/compressed/vmlinux.lds.S linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/vmlinux.lds.S
--- linux-libre-3.16-gnu/arch/arm/boot/compressed/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/compressed/vmlinux.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define ZIMAGE_MAGIC(x) ( (((x) >> 24) & 0x000000ff) | \
+			  (((x) >>  8) & 0x0000ff00) | \
+			  (((x) <<  8) & 0x00ff0000) | \
+			  (((x) << 24) & 0xff000000) )
+#else
+#define ZIMAGE_MAGIC(x) (x)
+#endif
+
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  /DISCARD/ : {
+    *(.ARM.exidx*)
+    *(.ARM.extab*)
+    /*
+     * Discard any r/w data - this produces a link error if we have any,
+     * which is required for PIC decompression.  Local data generates
+     * GOTOFF relocations, which prevents it being relocated independently
+     * of the text/got segments.
+     */
+    *(.data)
+  }
+
+  . = TEXT_START;
+  _text = .;
+
+  .text : {
+    _start = .;
+    *(.start)
+    *(.text)
+    *(.text.*)
+    *(.fixup)
+    *(.gnu.warning)
+    *(.glue_7t)
+    *(.glue_7)
+  }
+  .rodata : {
+    *(.rodata)
+    *(.rodata.*)
+  }
+  .piggydata : {
+    *(.piggydata)
+  }
+
+  . = ALIGN(4);
+  _etext = .;
+
+  .got.plt		: { *(.got.plt) }
+  _got_start = .;
+  .got			: { *(.got) }
+  _got_end = .;
+
+  /* ensure the zImage file size is always a multiple of 64 bits */
+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad			: { BYTE(0); . = ALIGN(8); }
+  _edata = .;
+
+  _magic_sig = ZIMAGE_MAGIC(0x016f2818);
+  _magic_start = ZIMAGE_MAGIC(_start);
+  _magic_end = ZIMAGE_MAGIC(_edata);
+
+  . = BSS_START;
+  __bss_start = .;
+  .bss			: { *(.bss) }
+  _end = .;
+
+  . = ALIGN(8);		/* the stack must be 64-bit aligned */
+  .stack		: { *(.stack) }
+
+  .stab 0		: { *(.stab) }
+  .stabstr 0		: { *(.stabstr) }
+  .stab.excl 0		: { *(.stab.excl) }
+  .stab.exclstr 0	: { *(.stab.exclstr) }
+  .stab.index 0		: { *(.stab.index) }
+  .stab.indexstr 0	: { *(.stab.indexstr) }
+  .comment 0		: { *(.comment) }
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/aks-cdu.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/aks-cdu.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/aks-cdu.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/aks-cdu.dts	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,12 @@
 		bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
 	};
 
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+	};
+
 	ahb {
 		apb {
 			usart0: serial@fffb0000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am335x-evmsk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am335x-evmsk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am335x-evmsk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am335x-evmsk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -149,12 +149,113 @@
 			"Headphone Jack",       "HPLOUT",
 			"Headphone Jack",       "HPROUT";
 	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&lcd_pins_default>;
+		pinctrl-1 = <&lcd_pins_sleep>;
+		status = "okay";
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <32>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+		display-timings {
+			480x272 {
+				hactive         = <480>;
+				vactive         = <272>;
+				hback-porch     = <43>;
+				hfront-porch    = <8>;
+				hsync-len       = <4>;
+				vback-porch     = <12>;
+				vfront-porch    = <4>;
+				vsync-len       = <10>;
+				clock-frequency = <9000000>;
+				hsync-active    = <0>;
+				vsync-active    = <0>;
+			};
+		};
+	};
 };
 
 &am33xx_pinmux {
 	pinctrl-names = "default";
 	pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
 
+	lcd_pins_default: lcd_pins_default {
+		pinctrl-single,pins = <
+			0x20 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad8.lcd_data23 */
+			0x24 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad9.lcd_data22 */
+			0x28 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad10.lcd_data21 */
+			0x2c (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad11.lcd_data20 */
+			0x30 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad12.lcd_data19 */
+			0x34 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad13.lcd_data18 */
+			0x38 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad14.lcd_data17 */
+			0x3c (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad15.lcd_data16 */
+			0xa0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data0.lcd_data0 */
+			0xa4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data1.lcd_data1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data2.lcd_data2 */
+			0xac (PIN_OUTPUT | MUX_MODE0)	/* lcd_data3.lcd_data3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data4.lcd_data4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data5.lcd_data5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data6.lcd_data6 */
+			0xbc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data7.lcd_data7 */
+			0xc0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data8.lcd_data8 */
+			0xc4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data9.lcd_data9 */
+			0xc8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data10.lcd_data10 */
+			0xcc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data11.lcd_data11 */
+			0xd0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data12.lcd_data12 */
+			0xd4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data13.lcd_data13 */
+			0xd8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data14.lcd_data14 */
+			0xdc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data15.lcd_data15 */
+			0xe0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_pclk.lcd_pclk */
+			0xec (PIN_OUTPUT | MUX_MODE0)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	lcd_pins_sleep: lcd_pins_sleep {
+		pinctrl-single,pins = <
+			0x20 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad8.lcd_data23 */
+			0x24 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad9.lcd_data22 */
+			0x28 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad10.lcd_data21 */
+			0x2c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad11.lcd_data20 */
+			0x30 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad12.lcd_data19 */
+			0x34 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad13.lcd_data18 */
+			0x38 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad14.lcd_data17 */
+			0x3c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad15.lcd_data16 */
+			0xa0 (PULL_DISABLE | MUX_MODE7)	/* lcd_data0.lcd_data0 */
+			0xa4 (PULL_DISABLE | MUX_MODE7)	/* lcd_data1.lcd_data1 */
+			0xa8 (PULL_DISABLE | MUX_MODE7)	/* lcd_data2.lcd_data2 */
+			0xac (PULL_DISABLE | MUX_MODE7)	/* lcd_data3.lcd_data3 */
+			0xb0 (PULL_DISABLE | MUX_MODE7)	/* lcd_data4.lcd_data4 */
+			0xb4 (PULL_DISABLE | MUX_MODE7)	/* lcd_data5.lcd_data5 */
+			0xb8 (PULL_DISABLE | MUX_MODE7)	/* lcd_data6.lcd_data6 */
+			0xbc (PULL_DISABLE | MUX_MODE7)	/* lcd_data7.lcd_data7 */
+			0xc0 (PULL_DISABLE | MUX_MODE7)	/* lcd_data8.lcd_data8 */
+			0xc4 (PULL_DISABLE | MUX_MODE7)	/* lcd_data9.lcd_data9 */
+			0xc8 (PULL_DISABLE | MUX_MODE7)	/* lcd_data10.lcd_data10 */
+			0xcc (PULL_DISABLE | MUX_MODE7)	/* lcd_data11.lcd_data11 */
+			0xd0 (PULL_DISABLE | MUX_MODE7)	/* lcd_data12.lcd_data12 */
+			0xd4 (PULL_DISABLE | MUX_MODE7)	/* lcd_data13.lcd_data13 */
+			0xd8 (PULL_DISABLE | MUX_MODE7)	/* lcd_data14.lcd_data14 */
+			0xdc (PULL_DISABLE | MUX_MODE7)	/* lcd_data15.lcd_data15 */
+			0xe0 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_pclk.lcd_pclk */
+			0xec (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+
 	user_leds_s0: user_leds_s0 {
 		pinctrl-single,pins = <
 			0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad4.gpio1_4 */
@@ -573,3 +674,7 @@
 		ti,wire-config = <0x00 0x11 0x22 0x33>;
 	};
 };
+
+&lcdc {
+      status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am335x-pepper.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am335x-pepper.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am335x-pepper.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am335x-pepper.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2014 Gumstix, Inc. - https://www.gumstix.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 <dt-bindings/input/input.h>
+#include "am33xx.dtsi"
+
+/ {
+	model = "Gumstix Pepper";
+	compatible = "gumstix,am335x-pepper", "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc3_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	buttons: user_buttons {
+		compatible = "gpio-keys";
+	};
+
+	leds: user_leds {
+		compatible = "gpio-leds";
+	};
+
+	panel: lcd_panel {
+		compatible = "ti,tilcdc,panel";
+	};
+
+	sound: sound_iface {
+		compatible = "ti,da830-evm-audio";
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+	};
+
+	v3v3c_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+	};
+
+	vdd5_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+	};
+};
+
+/* I2C Busses */
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	clock-frequency = <400000>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	eeprom: eeprom@50 {
+		compatible = "at,24c256";
+		reg = <0x50>;
+	};
+
+	audio_codec: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+	};
+
+	accel: lis331dlh@1d {
+		compatible = "st,lis3lv02d";
+		reg = <0x1d>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <400000>;
+};
+
+&am33xx_pinmux {
+	i2c0_pins: pinmux_i2c0 {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+	i2c1_pins: pinmux_i2c1 {
+		pinctrl-single,pins = <
+			0x10C (PIN_INPUT_PULLUP | MUX_MODE3)	/* mii1_crs,i2c1_sda */
+			0x110 (PIN_INPUT_PULLUP | MUX_MODE3)	/* mii1_rxerr,i2c1_scl */
+		>;
+	};
+};
+
+/* Accelerometer */
+&accel {
+	pinctrl-names = "default";
+	pinctrl-0 = <&accel_pins>;
+
+	Vdd-supply = <&ldo3_reg>;
+	Vdd_IO-supply = <&ldo3_reg>;
+	st,irq1-click;
+	st,wakeup-x-lo;
+	st,wakeup-x-hi;
+	st,wakeup-y-lo;
+	st,wakeup-y-hi;
+	st,wakeup-z-lo;
+	st,wakeup-z-hi;
+	st,min-limit-x = <92>;
+	st,max-limit-x = <14>;
+	st,min-limit-y = <14>;
+	st,max-limit-y = <92>;
+	st,min-limit-z = <92>;
+	st,max-limit-z = <14>;
+};
+
+&am33xx_pinmux {
+	accel_pins: pinmux_accel {
+		pinctrl-single,pins = <
+			0x98 (PIN_INPUT | MUX_MODE7)   /* gpmc_wen.gpio2_4 */
+		>;
+	};
+};
+
+/* Audio */
+&audio_codec {
+	status = "okay";
+
+	gpio-reset = <&gpio1 16 GPIO_ACTIVE_LOW>;
+	AVDD-supply = <&ldo3_reg>;
+	IOVDD-supply = <&ldo3_reg>;
+	DRVDD-supply = <&ldo3_reg>;
+	DVDD-supply = <&dcdc1_reg>;
+};
+
+&sound {
+	ti,model = "AM335x-EVM";
+	ti,audio-codec = <&audio_codec>;
+	ti,mcasp-controller = <&mcasp0>;
+	ti,codec-clock-rate = <12000000>;
+	ti,audio-routing =
+		"Headphone Jack",	"HPLOUT",
+		"Headphone Jack",	"HPROUT",
+		"LINE1L",		"Line In";
+};
+
+&mcasp0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&audio_pins>;
+
+	op-mode = <0>;	/* MCASP_ISS_MODE */
+	tdm-slots = <2>;
+	serial-dir = <
+		1 2 0 0
+		0 0 0 0
+		0 0 0 0
+		0 0 0 0
+	>;
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+};
+
+&am33xx_pinmux {
+	audio_pins: pinmux_audio {
+		pinctrl-single,pins = <
+			0x1AC (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_ahcklx.mcasp0_ahclkx */
+			0x194 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_fsx.mcasp0_fsx */
+			0x190 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_aclkx.mcasp0_aclkx */
+			0x198 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_axr0.mcasp0_axr0 */
+			0x1A8 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_axr1.mcasp0_axr1 */
+			0x40 (PIN_OUTPUT | MUX_MODE7)	/* gpmc_a0.gpio1_16 */
+		>;
+	};
+};
+
+/* Display: 24-bit LCD Screen */
+&panel {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_pins>;
+	panel-info {
+		ac-bias = <255>;
+		ac-bias-intrpt = <0>;
+		dma-burst-sz = <16>;
+		bpp = <32>;
+		fdd = <0x80>;
+		sync-edge = <0>;
+		sync-ctrl = <1>;
+		raster-order = <0>;
+		fifo-th = <0>;
+	};
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 480x272 {
+			clock-frequency = <18400000>;
+			hactive = <480>;
+			vactive = <272>;
+			hfront-porch = <8>;
+			hback-porch = <4>;
+			hsync-len = <41>;
+			vfront-porch = <4>;
+			vback-porch = <2>;
+			vsync-len = <10>;
+			hsync-active = <1>;
+			vsync-active = <1>;
+		};
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	lcd_pins: pinmux_lcd {
+		pinctrl-single,pins = <
+			0xa0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data0.lcd_data0 */
+			0xa4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data1.lcd_data1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data2.lcd_data2 */
+			0xac (PIN_OUTPUT | MUX_MODE0)	/* lcd_data3.lcd_data3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data4.lcd_data4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data5.lcd_data5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data6.lcd_data6 */
+			0xbc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data7.lcd_data7 */
+			0xc0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data8.lcd_data8 */
+			0xc4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data9.lcd_data9 */
+			0xc8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data10.lcd_data10 */
+			0xcc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data11.lcd_data11 */
+			0xd0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data12.lcd_data12 */
+			0xd4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data13.lcd_data13 */
+			0xd8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_data14.lcd_data14 */
+			0xdc (PIN_OUTPUT | MUX_MODE0)	/* lcd_data15.lcd_data15 */
+			0x20 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad8.lcd_data16 */
+			0x24 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad9.lcd_data17 */
+			0x28 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad10.lcd_data18 */
+			0x2c (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad11.lcd_data19 */
+			0x30 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad12.lcd_data20 */
+			0x34 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad13.lcd_data21 */
+			0x38 (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad14.lcd_data22 */
+			0x3c (PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad15.lcd_data23 */
+			0xe0 (PIN_OUTPUT | MUX_MODE0)	/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_OUTPUT | MUX_MODE0)	/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_OUTPUT | MUX_MODE0)	/* lcd_pclk.lcd_pclk */
+			0xec (PIN_OUTPUT | MUX_MODE0)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+			/* Display Enable */
+			0x6c (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a11.gpio1_27 */
+		>;
+	};
+};
+
+/* Ethernet */
+&cpsw_emac0 {
+	status = "okay";
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii";
+};
+
+&cpsw_emac1 {
+	status = "okay";
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii";
+};
+
+&davinci_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins>;
+};
+
+&mac {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ethernet_pins>;
+};
+
+
+&am33xx_pinmux {
+	ethernet_pins: pinmux_ethernet {
+		pinctrl-single,pins = <
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x12c (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			0x130 (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			0x134 (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd3.rgmii1_rxd3 */
+			0x138 (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd2.rgmii1_rxd2 */
+			0x13c (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd1.rgmii1_rxd1 */
+			0x140 (PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd0.rgmii1_rxd0 */
+			/* ethernet interrupt */
+			0x144 (PIN_INPUT_PULLUP | MUX_MODE7)	/* rmii2_refclk.gpio0_29 */
+			/* ethernet PHY nReset */
+			0x108 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* mii1_col.gpio3_0 */
+		>;
+	};
+
+	mdio_pins: pinmux_mdio {
+		pinctrl-single,pins = <
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+};
+
+/* MMC */
+&mmc1 {
+	/* Bootable SD card slot */
+	status = "okay";
+	vmmc-supply = <&ldo3_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&mmc2 {
+	/* eMMC (not populated) on MMC #2 */
+	status = "disabled";
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	vmmc-supply = <&ldo3_reg>;
+	bus-width = <8>;
+	ti,non-removable;
+};
+
+&edma {
+	/* Map eDMA MMC2 Events from Crossbar */
+	ti,edma-xbar-event-map = /bits/ 16 <1 12
+                                            2 13>;
+};
+
+
+&mmc3 {
+	/* Wifi & Bluetooth on MMC #3 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wireless_pins>;
+	vmmmc-supply = <&v3v3c_reg>;
+	bus-width = <4>;
+	ti,non-removable;
+	dmas = <&edma 12
+		&edma 13>;
+	dma-names = "tx", "rx";
+};
+
+
+&am33xx_pinmux {
+	sd_pins: pinmux_sd_card {
+		pinctrl-single,pins = <
+			0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0.mmc0_dat0 */
+			0xf4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1.mmc0_dat1 */
+			0xf8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2.mmc0_dat2 */
+			0xfc (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3.mmc0_dat3 */
+			0x100 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk.mmc0_clk */
+			0x104 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd.mmc0_cmd */
+			0x160 (PIN_INPUT | MUX_MODE7)		/* spi0_cs1.gpio0_6 */
+		>;
+	};
+	emmc_pins: pinmux_emmc {
+		pinctrl-single,pins = <
+			0x80 (PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn1.mmc1_clk */
+			0x84 (PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn2.mmc1_cmd */
+			0x00 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad0.mmc1_dat0 */
+			0x04 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad1.mmc1_dat1 */
+			0x08 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad2.mmc1_dat2 */
+			0x0c (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad3.mmc1_dat3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad4.mmc1_dat4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad5.mmc1_dat5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad6.mmc1_dat6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad7.mmc1_dat7 */
+			/* EMMC nReset */
+			0x74 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_31 */
+		>;
+	};
+	wireless_pins: pinmux_wireless {
+		pinctrl-single,pins = <
+			0x44 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a1.mmc2_dat0 */
+			0x48 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a2.mmc2_dat1 */
+			0x4c (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a3.mmc2_dat2 */
+			0x78 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_ben1.mmc2_dat3 */
+			0x88 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_csn3.mmc2_cmd */
+			0x8c (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_clk.mmc1_clk */
+			/* WLAN nReset */
+			0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+			/* WLAN nPower down */
+			0x70 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_wait0.gpio0_30 */
+			/* 32kHz Clock */
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+};
+
+/* Power */
+&vbat {
+	regulator-name = "vbat";
+	regulator-min-microvolt = <5000000>;
+	regulator-max-microvolt = <5000000>;
+};
+
+&v3v3c_reg {
+	regulator-name = "v3v3c_reg";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	vin-supply = <&vbat>;
+};
+
+&vdd5_reg {
+	regulator-name = "vdd5_reg";
+	regulator-min-microvolt = <5000000>;
+	regulator-max-microvolt = <5000000>;
+	vin-supply = <&vbat>;
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	backlight {
+		isel = <1>; /* ISET1 */
+		fdim = <200>; /* TPS65217_BL_FDIM_200HZ */
+		default-brightness = <80>;
+	};
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			/* VDD_1V8 system supply */
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			/* VRTC 1.8V always-on supply */
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			/* 3.3V rail */
+		};
+
+		ldo3_reg: regulator@5 {
+			/* VDD_3V3A 3.3V rail */
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+
+		ldo4_reg: regulator@6 {
+			/* VDD_3V3B 3.3V rail */
+		};
+	};
+};
+
+/* SPI Busses */
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+};
+
+&am33xx_pinmux {
+	spi0_pins: pinmux_spi0 {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
+			0x15C (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
+			0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
+			0x158 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+		>;
+	};
+};
+
+/* Touch Screen */
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+/* UARTs */
+&uart0 {
+	/* Serial Console */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+};
+
+&uart1 {
+	/* Broken out to J6 header */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&am33xx_pinmux {
+	uart0_pins: pinmux_uart0 {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+	uart1_pins: pinmux_uart1 {
+		pinctrl-single,pins = <
+			0x178 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_ctsn.uart1_ctsn */
+			0x17C (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_rtsn.uart1_rtsn */
+			0x180 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			0x184 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+		>;
+	};
+};
+
+/* USB */
+&usb {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb_pins>;
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+        dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+        dr_mode = "host";
+};
+
+&cppi41dma {
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	usb_pins: pinmux_usb {
+		pinctrl-single,pins = <
+			/* USB0 Over-Current (active low) */
+			0x64 (PIN_INPUT | MUX_MODE7)	/* gpmc_a9.gpio1_25 */
+			/* USB1 Over-Current (active low) */
+			0x68 (PIN_INPUT | MUX_MODE7)	/* gpmc_a10.gpio1_26 */
+		>;
+	};
+};
+
+/* User IO */
+&leds {
+	pinctrl-names = "default";
+	pinctrl-0 = <&user_leds_pins>;
+
+	led@0 {
+		label = "pepper:user0:blue";
+		gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
+		linux,default-trigger = "none";
+		default-state = "off";
+	};
+
+	led@1 {
+		label = "pepper:user1:red";
+		gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+		linux,default-trigger = "none";
+		default-state = "off";
+	};
+};
+
+&buttons {
+	pinctrl-names = "default";
+	pinctrl-0 = <&user_buttons_pins>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	button@0 {
+		label = "home";
+		linux,code = <KEY_HOME>;
+		gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+		gpio-key,wakeup;
+	};
+
+	button@1 {
+		label = "menu";
+		linux,code = <KEY_MENU>;
+		gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+		gpio-key,wakeup;
+	};
+
+	buttons@2 {
+		label = "power";
+		linux,code = <KEY_POWER>;
+		gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
+		gpio-key,wakeup;
+	};
+};
+
+&am33xx_pinmux {
+	user_leds_pins: pinmux_user_leds {
+		pinctrl-single,pins = <
+			0x50 (PIN_OUTPUT | MUX_MODE7)	/* gpmc_a4.gpio1_20 */
+			0x54 (PIN_OUTPUT | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+		>;
+	};
+
+	user_buttons_pins: pinmux_user_buttons {
+		pinctrl-single,pins = <
+			0x58 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			0x5C (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a7.gpio1_21 */
+			0x164 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio0_7 */
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am33xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am33xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am33xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am33xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -347,6 +347,15 @@
 			status = "disabled";
 		};
 
+		mailbox: mailbox@480C8000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x480C8000 0x200>;
+			interrupts = <77>;
+			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <8>;
+		};
+
 		timer1: timer@44e31000 {
 			compatible = "ti,am335x-timer-1ms";
 			reg = <0x44e31000 0x400>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am4372.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am4372.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am4372.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am4372.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		cpu@0 {
+		cpu: cpu@0 {
 			compatible = "arm,cortex-a9";
 			device_type = "cpu";
 			reg = <0>;
@@ -168,9 +168,6 @@
 			ti,hwmods = "mailbox";
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <8>;
-			ti,mbox-names = "wkup_m3";
-			ti,mbox-data = <0 0 0 0>;
-			status = "disabled";
 		};
 
 		timer1: timer@44e31000 {
@@ -270,7 +267,7 @@
 			ti,hwmods = "counter_32k";
 		};
 
-		rtc@44e3e000 {
+		rtc: rtc@44e3e000 {
 			compatible = "ti,am4372-rtc","ti,da830-rtc";
 			reg = <0x44e3e000 0x1000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
@@ -279,7 +276,7 @@
 			status = "disabled";
 		};
 
-		wdt@44e35000 {
+		wdt: wdt@44e35000 {
 			compatible = "ti,am4372-wdt","ti,omap3-wdt";
 			reg = <0x44e35000 0x1000>;
 			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
@@ -807,7 +804,7 @@
 
 			usb1: usb@48390000 {
 				compatible = "synopsys,dwc3";
-				reg = <0x48390000 0x17000>;
+				reg = <0x48390000 0x10000>;
 				interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usb2_phy1>;
 				phy-names = "usb2-phy";
@@ -829,7 +826,7 @@
 
 			usb2: usb@483d0000 {
 				compatible = "synopsys,dwc3";
-				reg = <0x483d0000 0x17000>;
+				reg = <0x483d0000 0x10000>;
 				interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usb2_phy2>;
 				phy-names = "usb2-phy";
@@ -871,7 +868,7 @@
 			#size-cells = <1>;
 			ranges;
 
-			dispc@4832a400 {
+			dispc: dispc@4832a400 {
 				compatible = "ti,omap3-dispc";
 				reg = <0x4832a400 0x400>;
 				interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am437x-gp-evm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am437x-gp-evm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am437x-gp-evm.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am437x-gp-evm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -257,16 +257,73 @@
 };
 
 &i2c0 {
-        status = "okay";
-        pinctrl-names = "default";
-        pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <100000>;
+
+	tps65218: tps65218@24 {
+		reg = <0x24>;
+		compatible = "ti,tps65218";
+		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdcdc3";
+			regulator-min-microvolt = <1350000>;
+			regulator-max-microvolt = <1350000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+		dcdc5: regulator-dcdc5 {
+			compatible = "ti,tps65218-dcdc5";
+			regulator-name = "v1_0bat";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+		};
+
+		dcdc6: regulator-dcdc6 {
+			compatible = "ti,tps65218-dcdc6";
+			regulator-name = "v1_8bat";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
 };
 
 &i2c1 {
-        status = "okay";
-        pinctrl-names = "default";
-        pinctrl-0 = <&i2c1_pins>;
-
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
 	pixcir_ts@5c {
 		compatible = "pixcir,pixcir_tangoc";
 		pinctrl-names = "default";
@@ -277,8 +334,8 @@
 
 		attb-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
 
-		x-size = <1024>;
-		y-size = <600>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
 	};
 };
 
@@ -367,7 +424,7 @@
 	ranges = <0 0 0 0x01000000>;	/* minimum GPMC partition = 16MB */
 	nand@0,0 {
 		reg = <0 0 4>;		/* device IO registers */
-		ti,nand-ecc-opt = "bch8";
+		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
 		gpmc,device-width = <1>;
@@ -386,8 +443,6 @@
 		gpmc,rd-cycle-ns = <40>;
 		gpmc,wr-cycle-ns = <40>;
 		gpmc,wait-pin = <0>;
-		gpmc,wait-on-read;
-		gpmc,wait-on-write;
 		gpmc,bus-turnaround-ns = <0>;
 		gpmc,cycle2cycle-delay-ns = <0>;
 		gpmc,clk-activation-ns = <0>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am437x-sk-evm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am437x-sk-evm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am437x-sk-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am437x-sk-evm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,613 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+/* AM437x SK EVM */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "TI AM437x SK EVM";
+	compatible = "ti,am437x-sk-evm","ti,am4372","ti,am43";
+
+	aliases {
+		display0 = &lcd0;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM437x-SK-EVM";
+		ti,audio-codec = <&tlv320aic3106>;
+		ti,mcasp-controller = <&mcasp1>;
+		ti,codec-clock-rate = <24000000>;
+		ti,audio-routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT";
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&matrix_keypad_pins>;
+
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <1500>;
+
+		row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH		/* Bank5, pin5 */
+				&gpio5 6 GPIO_ACTIVE_HIGH>;	/* Bank5, pin6 */
+
+		col-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH		/* Bank5, pin13 */
+				&gpio5 4 GPIO_ACTIVE_HIGH>;	/* Bank5, pin4 */
+
+		linux,keymap = <
+				MATRIX_KEY(0, 0, KEY_DOWN)
+				MATRIX_KEY(0, 1, KEY_RIGHT)
+				MATRIX_KEY(1, 0, KEY_LEFT)
+				MATRIX_KEY(1, 1, KEY_UP)
+			>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+
+		led@0 {
+			label = "am437x-sk:red:heartbeat";
+			gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 0 */
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led@1 {
+			label = "am437x-sk:green:mmc1";
+			gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 1 */
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "am437x-sk:blue:cpu0";
+			gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 2 */
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "am437x-sk:blue:usr3";
+			gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 3 */
+			default-state = "off";
+		};
+	};
+
+	lcd0: display {
+		compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+		label = "lcd";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins>;
+
+		enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+
+		panel-timing {
+			clock-frequency = <9000000>;
+			hactive = <480>;
+			vactive = <272>;
+			hfront-porch = <8>;
+			hback-porch = <43>;
+			hsync-len = <4>;
+			vback-porch = <12>;
+			vfront-porch = <4>;
+			vsync-len = <10>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+	};
+};
+
+&am43xx_pinmux {
+	matrix_keypad_pins: matrix_keypad_pins {
+		pinctrl-single,pins = <
+			0x24c (PIN_OUTPUT | MUX_MODE7)	/* gpio5_13.gpio5_13 */
+			0x250 (PIN_OUTPUT | MUX_MODE7)	/* spi4_sclk.gpio5_4 */
+			0x254 (PIN_INPUT | MUX_MODE7)	/* spi4_d0.gpio5_5 */
+			0x258 (PIN_INPUT | MUX_MODE7)	/* spi4_d1.gpio5_5 */
+		>;
+	};
+
+	leds_pins: leds_pins {
+		pinctrl-single,pins = <
+			0x228 (PIN_OUTPUT | MUX_MODE7)	/* uart3_rxd.gpio5_2 */
+			0x22c (PIN_OUTPUT | MUX_MODE7)	/* uart3_txd.gpio5_3 */
+			0x230 (PIN_OUTPUT | MUX_MODE7)	/* uart3_ctsn.gpio5_0 */
+			0x234 (PIN_OUTPUT | MUX_MODE7)	/* uart3_rtsn.gpio5_1 */
+		>;
+	};
+
+	i2c0_pins: i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: i2c1_pins {
+		pinctrl-single,pins = <
+			0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_cs0.i2c1_scl */
+			0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_d1.i2c1_sda  */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	ecap0_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x164 (PIN_OUTPUT | MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
+		>;
+	};
+
+	edt_ft5306_ts_pins: edt_ft5306_ts_pins {
+		pinctrl-single,pins = <
+			0x74 (PIN_INPUT | MUX_MODE7)	/* gpmc_wpn.gpio0_31 */
+			0x78 (PIN_OUTPUT | MUX_MODE7)	/* gpmc_be1n.gpio1_28 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rmii1_tclk */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td2 */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td3 */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rmii1_rclk */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd2 */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd3 */
+
+			/* Slave 2 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rtcl */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value */
+			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	dss_pins: dss_pins {
+		pinctrl-single,pins = <
+			0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1)	/* gpmc ad 8 -> DSS DATA 23 */
+			0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x02c (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x03c (PIN_OUTPUT_PULLUP | MUX_MODE1)	/* gpmc ad 15 -> DSS DATA 16 */
+			0x0a0 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS DATA 0 */
+			0x0a4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0a8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0ac (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0bc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0cc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0dc (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS DATA 15 */
+			0x0e0 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS VSYNC */
+			0x0e4 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS HSYNC */
+			0x0e8 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS PCLK */
+			0x0ec (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* DSS AC BIAS EN */
+
+		>;
+	};
+
+	qspi_pins: qspi_pins {
+		pinctrl-single,pins = <
+			0x7c (PIN_OUTPUT_PULLUP | MUX_MODE3)	/* gpmc_csn0.qspi_csn */
+			0x88 (PIN_OUTPUT | MUX_MODE2)		/* gpmc_csn3.qspi_clk */
+			0x90 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_advn_ale.qspi_d0 */
+			0x94 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_oen_ren.qspi_d1 */
+			0x98 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_wen.qspi_d2 */
+			0x9c (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_be0n_cle.qspi_d3 */
+		>;
+	};
+
+	mcasp1_pins: mcasp1_pins {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* mii1_crs.mcasp1_aclkx */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* mii1_rxerr.mcasp1_fsx */
+			0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4)	/* mii1_col.mcasp1_axr2 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+
+	lcd_pins: lcd_pins {
+		pinctrl-single,pins = <
+			/* GPIO 5_8 to select LCD / HDMI */
+			0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7)
+		>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+
+	tps@24 {
+		compatible = "ti,tps65218";
+		reg = <0x24>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			/* VDD_CORE limits min of OPP50 and max of OPP100 */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			/* VDD_MPU limits min of OPP50 and max of OPP_NITRO */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdds_ddr";
+			regulator-min-microvolt = <1350000>;
+			regulator-max-microvolt = <1350000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc4: regulator-dcdc4 {
+			compatible = "ti,tps65218-dcdc4";
+			regulator-name = "v3_3d";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-name = "v1_8d";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+	};
+
+	at24@50 {
+		compatible = "at24,24c256";
+		pagesize = <64>;
+		reg = <0x50>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <400000>;
+
+	edt-ft5306@38 {
+		status = "okay";
+		compatible = "edt,edt-ft5306", "edt,edt-ft5x06";
+		pinctrl-names = "default";
+		pinctrl-0 = <&edt_ft5306_ts_pins>;
+
+		reg = <0x38>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <31 0>;
+
+		wake-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+
+		touchscreen-size-x = <480>;
+		touchscreen-size-y = <272>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&dcdc4>;
+		IOVDD-supply = <&dcdc4>;
+		DRVDD-supply = <&dcdc4>;
+		DVDD-supply = <&ldo1>;
+	};
+
+	lis331dlh@18 {
+		compatible = "st,lis331dlh";
+		reg = <0x18>;
+		status = "okay";
+
+		Vdd-supply = <&dcdc4>;
+		Vdd_IO-supply = <&dcdc4>;
+		interrupts-extended = <&gpio1 6 0>, <&gpio2 1 0>;
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ecap0_pins>;
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+
+	vmmc-supply = <&dcdc4>;
+	bus-width = <4>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+};
+
+&usb2_phy1 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usb2_phy2 {
+	status = "okay";
+};
+
+&usb2 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&qspi {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi_pins>;
+
+	spi-max-frequency = <48000000>;
+	m25p80@0 {
+		compatible = "mx66l51235l";
+		spi-max-frequency = <48000000>;
+		reg = <0>;
+		spi-cpol;
+		spi-cpha;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first 512KiB
+		 * for a valid file to boot(XIP).
+		 */
+		partition@0 {
+			label = "QSPI.U_BOOT";
+			reg = <0x00000000 0x000080000>;
+		};
+		partition@1 {
+			label = "QSPI.U_BOOT.backup";
+			reg = <0x00080000 0x00080000>;
+		};
+		partition@2 {
+			label = "QSPI.U-BOOT-SPL_OS";
+			reg = <0x00100000 0x00010000>;
+		};
+		partition@3 {
+			label = "QSPI.U_BOOT_ENV";
+			reg = <0x00110000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.U-BOOT-ENV.backup";
+			reg = <0x00120000 0x00010000>;
+		};
+		partition@5 {
+			label = "QSPI.KERNEL";
+			reg = <0x00130000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.FILESYSTEM";
+			reg = <0x00930000 0x36D0000>;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <4>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <5>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&elm {
+	status = "okay";
+};
+
+&mcasp1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp1_pins>;
+
+	status = "okay";
+
+	op-mode = <0>;
+	tdm-slots = <2>;
+	serial-dir = <
+		0 0 1 2
+	>;
+
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+};
+
+&dss {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_pins>;
+
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/am43x-epos-evm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am43x-epos-evm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/am43x-epos-evm.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/am43x-epos-evm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -327,6 +327,65 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+
+	tps65218: tps65218@24 {
+		reg = <0x24>;
+		compatible = "ti,tps65218";
+		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdcdc3";
+			regulator-min-microvolt = <1350000>;
+			regulator-max-microvolt = <1350000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc5: regulator-dcdc5 {
+			compatible = "ti,tps65218-dcdc5";
+			regulator-name = "v1_0bat";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+		};
+
+		dcdc6: regulator-dcdc6 {
+			compatible = "ti,tps65218-dcdc6";
+			regulator-name = "v1_8bat";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
 
 	at24@50 {
 		compatible = "at24,24c256";
@@ -344,8 +403,8 @@
 
 		attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
 
-		x-size = <1024>;
-		y-size = <600>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
 	};
 };
 
@@ -376,13 +435,13 @@
 };
 
 &gpmc {
-	status = "okay";
+	status = "okay";	/* Disable QSPI when enabling GPMC (NAND) */
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_flash_x8>;
 	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
 	nand@0,0 {
 		reg = <0 0 0>; /* CS0, offset 0 */
-		ti,nand-ecc-opt = "bch8";
+		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
 		gpmc,device-width = <1>;
@@ -400,8 +459,7 @@
 		gpmc,access-ns = <30>; /* tCEA + 4*/
 		gpmc,rd-cycle-ns = <40>;
 		gpmc,wr-cycle-ns = <40>;
-		gpmc,wait-on-read = "true";
-		gpmc,wait-on-write = "true";
+		gpmc,wait-pin = <0>;
 		gpmc,bus-turnaround-ns = <0>;
 		gpmc,cycle2cycle-delay-ns = <0>;
 		gpmc,clk-activation-ns = <0>;
@@ -498,7 +556,7 @@
 };
 
 &qspi {
-	status = "okay";
+	status = "disabled";	/* Disable GPMC (NAND) when enabling QSPI */
 	pinctrl-names = "default";
 	pinctrl-0 = <&qspi1_default>;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/animeo_ip.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/animeo_ip.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/animeo_ip.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/animeo_ip.dts	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-375-db.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-375-db.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-375-db.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-375-db.dts	2014-09-28 17:29:07.000000000 -0400
@@ -123,6 +123,32 @@
 				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@f0000 {
+				status = "okay";
+
+				eth0@c4000 {
+					status = "okay";
+					phy = <&phy0>;
+					phy-mode = "rgmii-id";
+				};
+
+				eth1@c5000 {
+					status = "okay";
+					phy = <&phy3>;
+					phy-mode = "gmii";
+				};
+			};
 		};
 
 		pcie-controller {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-375.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-375.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-375.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-375.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,8 @@
 		gpio0 = &gpio0;
 		gpio1 = &gpio1;
 		gpio2 = &gpio2;
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
 	};
 
 	clocks {
@@ -151,6 +153,38 @@
 				      <0xc100 0x100>;
 			};
 
+			mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0xc0054 0x4>;
+				clocks = <&gateclk 19>;
+			};
+
+			/* Network controller */
+			ethernet@f0000 {
+				compatible = "marvell,armada-375-pp2";
+				reg = <0xf0000 0xa000>, /* Packet Processor regs */
+				      <0xc0000 0x3060>, /* LMS regs */
+				      <0xc4000 0x100>,  /* eth0 regs */
+				      <0xc5000 0x100>;  /* eth1 regs */
+				clocks = <&gateclk 3>, <&gateclk 19>;
+				clock-names = "pp_clk", "gop_clk";
+				status = "disabled";
+
+				eth0: eth0@c4000 {
+					interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+					port-id = <0>;
+					status = "disabled";
+				};
+
+				eth1: eth1@c5000 {
+					interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+					port-id = <1>;
+					status = "disabled";
+				};
+			};
+
 			spi0: spi@10600 {
 				compatible = "marvell,orion-spi";
 				reg = <0x10600 0x50>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-38x.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-38x.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-38x.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-38x.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -286,6 +286,11 @@
 				reg = <0x20800 0x10>;
 			};
 
+			mpcore-soc-ctrl@20d20 {
+				compatible = "marvell,armada-380-mpcore-soc-ctrl";
+				reg = <0x20d20 0x6c>;
+			};
+
 			coherency-fabric@21010 {
 				compatible = "marvell,armada-380-coherency-fabric";
 				reg = <0x21010 0x1c>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@
 			cpuclk: clock-complex@18700 {
 				#clock-cells = <1>;
 				compatible = "marvell,armada-xp-cpu-clock";
-				reg = <0x18700 0xA0>;
+				reg = <0x18700 0xA0>, <0x1c054 0x10>;
 				clocks = <&coreclk 1>;
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+ * Device Tree file for Lenovo Iomega ix4-300d
+ *
+ * Copyright (C) 2014, Benoit Masson <yahoo@perenite.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+	model = "Lenovo Iomega ix4-300d";
+	compatible = "lenovo,ix4-300d", "marvell,armadaxp-mv78230",
+		     "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+		stdout-path = "/soc/internal-regs/serial@12000";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x00000000 0 0x20000000>; /* 512MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+			MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+		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 {
+			pinctrl {
+				poweroff_pin: poweroff-pin {
+					marvell,pins = "mpp24";
+					marvell,function = "gpio";
+				};
+
+				power_button_pin: power-button-pin {
+					marvell,pins = "mpp44";
+					marvell,function = "gpio";
+				};
+
+				reset_button_pin: reset-button-pin {
+					marvell,pins = "mpp45";
+					marvell,function = "gpio";
+				};
+				select_button_pin: select-button-pin {
+					marvell,pins = "mpp41";
+					marvell,function = "gpio";
+				};
+
+				scroll_button_pin: scroll-button-pin {
+					marvell,pins = "mpp42";
+					marvell,function = "gpio";
+				};
+
+				hdd_led_pin: hdd-led-pin {
+					marvell,pins = "mpp26";
+					marvell,function = "gpio";
+				};
+			};
+
+			serial@12000 {
+				status = "okay";
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+					reg = <1>;
+				};
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+
+			ethernet@74000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "rgmii-id";
+			};
+
+			usb@50000 {
+				status = "okay";
+			};
+
+			usb@51000 {
+				status = "okay";
+			};
+
+			i2c@11000 {
+				clock-frequency = <400000>;
+				status = "okay";
+
+				adt7473@2e {
+					compatible = "adi,adt7473";
+					reg = <0x2e>;
+				};
+
+				pcf8563@51 {
+					compatible = "nxp,pcf8563";
+					reg = <0x51>;
+				};
+
+			};
+
+			nand@d0000 {
+				status = "okay";
+				num-cs = <1>;
+				marvell,nand-keep-config;
+				marvell,nand-enable-arbiter;
+				nand-on-flash-bbt;
+
+				partition@0 {
+					label = "u-boot";
+					reg = <0x0000000 0xe0000>;
+					read-only;
+				};
+
+				partition@e0000 {
+					label = "u-boot-env";
+					reg = <0xe0000 0x20000>;
+					read-only;
+				};
+
+				partition@100000 {
+					label = "u-boot-env2";
+					reg = <0x100000 0x20000>;
+					read-only;
+				};
+
+				partition@120000 {
+					label = "zImage";
+					reg = <0x120000 0x400000>;
+				};
+
+				partition@520000 {
+					label = "initrd";
+					reg = <0x520000 0x400000>;
+				};
+
+				partition@xE00000 {
+					label = "boot";
+					reg = <0xE00000 0x3F200000>;
+				};
+
+				partition@flash {
+					label = "flash";
+					reg = <0x0 0x40000000>;
+				};
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&power_button_pin &reset_button_pin
+			&select_button_pin &scroll_button_pin>;
+		pinctrl-names = "default";
+
+		power-button {
+			label = "Power Button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		};
+
+		reset-button {
+			label = "Reset Button";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+		};
+
+		select-button {
+			label = "Select Button";
+			linux,code = <BTN_SELECT>;
+			gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+		};
+
+		scroll-button {
+			label = "Scroll Button";
+			linux,code = <KEY_SCROLLDOWN>;
+			gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	spi3 {
+		compatible = "spi-gpio";
+		status = "okay";
+		gpio-sck = <&gpio0 25 GPIO_ACTIVE_LOW>;
+		gpio-mosi = <&gpio1 15 GPIO_ACTIVE_LOW>; /*gpio 47*/
+		cs-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
+		num-chipselects = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio_spi: gpio_spi@0 {
+			compatible = "fairchild,74hc595";
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0>;
+			registers-number = <2>;
+			spi-max-frequency = <100000>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&hdd_led_pin>;
+		pinctrl-names = "default";
+
+		hdd-led {
+			label = "ix4-300d:hdd:blue";
+			gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		power-led {
+			label = "ix4-300d:power:white";
+			gpios = <&gpio_spi 1 GPIO_ACTIVE_LOW>;
+			/* init blinking while booting */
+			linux,default-trigger = "timer";
+			default-state = "on";
+		};
+
+		sysfail-led {
+			label = "ix4-300d:sysfail:red";
+			gpios = <&gpio_spi 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		sys-led {
+			label = "ix4-300d:sys:blue";
+			gpios = <&gpio_spi 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		hddfail-led {
+			label = "ix4-300d:hddfail:red";
+			gpios = <&gpio_spi 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+	};
+
+	/*
+	 * Warning: you need both eth1 & 0 PHY initialized (i.e having
+	 * them up does the tweak) for poweroff to shutdown otherwise it
+	 * reboots
+	 */
+	gpio-poweroff {
+		compatible = "gpio-poweroff";
+		pinctrl-0 = <&poweroff_pin>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <0>;
 			clocks = <&cpuclk 0>;
+			clock-latency = <1000000>;
 		};
 
 		cpu@1 {
@@ -41,6 +42,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <1>;
 			clocks = <&cpuclk 1>;
+			clock-latency = <1000000>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <0>;
 			clocks = <&cpuclk 0>;
+			clock-latency = <1000000>;
 		};
 
 		cpu@1 {
@@ -43,6 +44,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <1>;
 			clocks = <&cpuclk 1>;
+			clock-latency = <1000000>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <0>;
 			clocks = <&cpuclk 0>;
+			clock-latency = <1000000>;
 		};
 
 		cpu@1 {
@@ -44,6 +45,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <1>;
 			clocks = <&cpuclk 1>;
+			clock-latency = <1000000>;
 		};
 
 		cpu@2 {
@@ -51,6 +53,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <2>;
 			clocks = <&cpuclk 2>;
+			clock-latency = <1000000>;
 		};
 
 		cpu@3 {
@@ -58,6 +61,7 @@
 			compatible = "marvell,sheeva-v7";
 			reg = <3>;
 			clocks = <&cpuclk 3>;
+			clock-latency = <1000000>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91-ariag25.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-ariag25.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91-ariag25.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-ariag25.dts	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91-cosino.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-cosino.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91-cosino.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-cosino.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91-foxg20.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-foxg20.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91-foxg20.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-foxg20.dts	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91-qil_a9260.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-qil_a9260.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91-qil_a9260.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-qil_a9260.dts	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91rm9200.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91rm9200.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91rm9200.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91rm9200.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
 	model = "Atmel AT91RM9200 family SoC";
@@ -51,6 +52,20 @@
 		reg = <0x20000000 0x04000000>;
 	};
 
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
 	ahb {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -79,6 +94,260 @@
 			pmc: pmc@fffffc00 {
 				compatible = "atmel,at91rm9200-pmc";
 				reg = <0xfffffc00 0x100>;
+				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+
+				main_osc: main_osc {
+					compatible = "atmel,at91rm9200-clk-main-osc";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+					clocks = <&main_xtal>;
+				};
+
+				main: mainck {
+					compatible = "atmel,at91rm9200-clk-main";
+					#clock-cells = <0>;
+					clocks = <&main_osc>;
+				};
+
+				plla: pllack {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+					clocks = <&main>;
+					reg = <0>;
+					atmel,clk-input-range = <1000000 32000000>;
+					#atmel,pll-clk-output-range-cells = <3>;
+					atmel,pll-clk-output-ranges = <80000000 160000000 0>,
+								<150000000 180000000 2>;
+				};
+
+				pllb: pllbck {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+					clocks = <&main>;
+					reg = <1>;
+					atmel,clk-input-range = <1000000 32000000>;
+					#atmel,pll-clk-output-range-cells = <3>;
+					atmel,pll-clk-output-ranges = <80000000 160000000 0>,
+								<150000000 180000000 2>;
+				};
+
+				mck: masterck {
+					compatible = "atmel,at91rm9200-clk-master";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+					clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+					atmel,clk-output-range = <0 80000000>;
+					atmel,clk-divisors = <1 2 3 4>;
+				};
+
+				usb: usbck {
+					compatible = "atmel,at91rm9200-clk-usb";
+					#clock-cells = <0>;
+					atmel,clk-divisors = <1 2 0 0>;
+					clocks = <&pllb>;
+				};
+
+				prog: progck {
+					compatible = "atmel,at91rm9200-clk-programmable";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+
+					prog0: prog0 {
+						#clock-cells = <0>;
+						reg = <0>;
+						interrupts = <AT91_PMC_PCKRDY(0)>;
+					};
+
+					prog1: prog1 {
+						#clock-cells = <0>;
+						reg = <1>;
+						interrupts = <AT91_PMC_PCKRDY(1)>;
+					};
+
+					prog2: prog2 {
+						#clock-cells = <0>;
+						reg = <2>;
+						interrupts = <AT91_PMC_PCKRDY(2)>;
+					};
+
+					prog3: prog3 {
+						#clock-cells = <0>;
+						reg = <3>;
+						interrupts = <AT91_PMC_PCKRDY(3)>;
+					};
+				};
+
+				systemck {
+					compatible = "atmel,at91rm9200-clk-system";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					udpck: udpck {
+						#clock-cells = <0>;
+						reg = <2>;
+						clocks = <&usb>;
+					};
+
+					uhpck: uhpck {
+						#clock-cells = <0>;
+						reg = <4>;
+						clocks = <&usb>;
+					};
+
+					pck0: pck0 {
+						#clock-cells = <0>;
+						reg = <8>;
+						clocks = <&prog0>;
+					};
+
+					pck1: pck1 {
+						#clock-cells = <0>;
+						reg = <9>;
+						clocks = <&prog1>;
+					};
+
+					pck2: pck2 {
+						#clock-cells = <0>;
+						reg = <10>;
+						clocks = <&prog2>;
+					};
+
+					pck3: pck3 {
+						#clock-cells = <0>;
+						reg = <11>;
+						clocks = <&prog3>;
+					};
+				};
+
+				periphck {
+					compatible = "atmel,at91rm9200-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&mck>;
+
+					pioA_clk: pioA_clk {
+						#clock-cells = <0>;
+						reg = <2>;
+					};
+
+					pioB_clk: pioB_clk {
+						#clock-cells = <0>;
+						reg = <3>;
+					};
+
+					pioC_clk: pioC_clk {
+						#clock-cells = <0>;
+						reg = <4>;
+					};
+
+					pioD_clk: pioD_clk {
+						#clock-cells = <0>;
+						reg = <5>;
+					};
+
+					usart0_clk: usart0_clk {
+						#clock-cells = <0>;
+						reg = <6>;
+					};
+
+					usart1_clk: usart1_clk {
+						#clock-cells = <0>;
+						reg = <7>;
+					};
+
+					usart2_clk: usart2_clk {
+						#clock-cells = <0>;
+						reg = <8>;
+					};
+
+					usart3_clk: usart3_clk {
+						#clock-cells = <0>;
+						reg = <9>;
+					};
+
+					mci0_clk: mci0_clk {
+						#clock-cells = <0>;
+						reg = <10>;
+					};
+
+					udc_clk: udc_clk {
+						#clock-cells = <0>;
+						reg = <11>;
+					};
+
+					twi0_clk: twi0_clk {
+						reg = <12>;
+						#clock-cells = <0>;
+					};
+
+					spi0_clk: spi0_clk {
+						#clock-cells = <0>;
+						reg = <13>;
+					};
+
+					ssc0_clk: ssc0_clk {
+						#clock-cells = <0>;
+						reg = <14>;
+					};
+
+					ssc1_clk: ssc1_clk {
+						#clock-cells = <0>;
+						reg = <15>;
+					};
+
+					ssc2_clk: ssc2_clk {
+						#clock-cells = <0>;
+						reg = <16>;
+					};
+
+					tc0_clk: tc0_clk {
+						#clock-cells = <0>;
+						reg = <17>;
+					};
+
+					tc1_clk: tc1_clk {
+						#clock-cells = <0>;
+						reg = <18>;
+					};
+
+					tc2_clk: tc2_clk {
+						#clock-cells = <0>;
+						reg = <19>;
+					};
+
+					tc3_clk: tc3_clk {
+						#clock-cells = <0>;
+						reg = <20>;
+					};
+
+					tc4_clk: tc4_clk {
+						#clock-cells = <0>;
+						reg = <21>;
+					};
+
+					tc5_clk: tc5_clk {
+						#clock-cells = <0>;
+						reg = <22>;
+					};
+
+					ohci_clk: ohci_clk {
+						#clock-cells = <0>;
+						reg = <23>;
+					};
+
+					macb0_clk: macb0_clk {
+						#clock-cells = <0>;
+						reg = <24>;
+					};
+				};
 			};
 
 			st: timer@fffffd00 {
@@ -93,6 +362,8 @@
 				interrupts = <17 IRQ_TYPE_LEVEL_HIGH 0
 					      18 IRQ_TYPE_LEVEL_HIGH 0
 					      19 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tc0_clk>, <&tc1_clk>, <&tc2_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			tcb1: timer@fffa4000 {
@@ -101,6 +372,8 @@
 				interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0
 					      21 IRQ_TYPE_LEVEL_HIGH 0
 					      22 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tc3_clk>, <&tc4_clk>, <&tc5_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			i2c0: i2c@fffb8000 {
@@ -109,6 +382,7 @@
 				interrupts = <12 IRQ_TYPE_LEVEL_HIGH 6>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_twi>;
+				clocks = <&twi0_clk>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				status = "disabled";
@@ -118,6 +392,8 @@
 				compatible = "atmel,hsmci";
 				reg = <0xfffb4000 0x4000>;
 				interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&mci0_clk>;
+				clock-names = "mci_clk";
 				#address-cells = <1>;
 				#size-cells = <0>;
 				pinctrl-names = "default";
@@ -130,6 +406,8 @@
 				interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				clocks = <&ssc0_clk>;
+				clock-names = "pclk";
 				status = "disable";
 			};
 
@@ -139,6 +417,8 @@
 				interrupts = <15 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+				clocks = <&ssc1_clk>;
+				clock-names = "pclk";
 				status = "disable";
 			};
 
@@ -148,6 +428,8 @@
 				interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc2_tx &pinctrl_ssc2_rx>;
+				clocks = <&ssc2_clk>;
+				clock-names = "pclk";
 				status = "disable";
 			};
 
@@ -158,6 +440,8 @@
 				phy-mode = "rmii";
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_macb_rmii>;
+				clocks = <&macb0_clk>;
+				clock-names = "ether_clk";
 				status = "disabled";
 			};
 
@@ -496,6 +780,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioA_clk>;
 				};
 
 				pioB: gpio@fffff600 {
@@ -506,6 +791,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioB_clk>;
 				};
 
 				pioC: gpio@fffff800 {
@@ -516,6 +802,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioC_clk>;
 				};
 
 				pioD: gpio@fffffa00 {
@@ -526,6 +813,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioD_clk>;
 				};
 			};
 
@@ -535,6 +823,8 @@
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_dbgu>;
+				clocks = <&mck>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -546,6 +836,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart0>;
+				clocks = <&usart0_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -557,6 +849,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart1>;
+				clocks = <&usart1_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -568,6 +862,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart2>;
+				clocks = <&usart2_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -579,6 +875,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart3>;
+				clocks = <&usart3_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -586,6 +884,8 @@
 				compatible = "atmel,at91rm9200-udc";
 				reg = <0xfffb0000 0x4000>;
 				interrupts = <11 IRQ_TYPE_LEVEL_HIGH 2>;
+				clocks = <&udc_clk>, <&udpck>;
+				clock-names = "pclk", "hclk";
 				status = "disabled";
 			};
 
@@ -597,6 +897,8 @@
 				interrupts = <13 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi0>;
+				clocks = <&spi0_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 		};
@@ -622,6 +924,8 @@
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00300000 0x100000>;
 			interrupts = <23 IRQ_TYPE_LEVEL_HIGH 2>;
+			clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+			clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91rm9200ek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91rm9200ek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91rm9200ek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91rm9200ek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9260.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9260.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9260.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9260.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
 	model = "Atmel AT91SAM9260 family SoC";
@@ -48,6 +49,26 @@
 		reg = <0x20000000 0x04000000>;
 	};
 
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		adc_op_clk: adc_op_clk{
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <5000000>;
+		};
+	};
+
 	ahb {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -74,8 +95,260 @@
 			};
 
 			pmc: pmc@fffffc00 {
-				compatible = "atmel,at91rm9200-pmc";
+				compatible = "atmel,at91sam9260-pmc";
 				reg = <0xfffffc00 0x100>;
+				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+
+				main_osc: main_osc {
+					compatible = "atmel,at91rm9200-clk-main-osc";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+					clocks = <&main_xtal>;
+				};
+
+				main: mainck {
+					compatible = "atmel,at91rm9200-clk-main";
+					#clock-cells = <0>;
+					clocks = <&main_osc>;
+				};
+
+				slow_rc_osc: slow_rc_osc {
+					compatible = "fixed-clock";
+					#clock-cells = <0>;
+					clock-frequency = <32768>;
+					clock-accuracy = <50000000>;
+				};
+
+				clk32k: slck {
+					compatible = "atmel,at91sam9260-clk-slow";
+					#clock-cells = <0>;
+					clocks = <&slow_rc_osc>, <&slow_xtal>;
+				};
+
+				plla: pllack {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+					clocks = <&main>;
+					reg = <0>;
+					atmel,clk-input-range = <1000000 32000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <80000000 160000000 0 1>,
+								<150000000 240000000 2 1>;
+				};
+
+				pllb: pllbck {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+					clocks = <&main>;
+					reg = <1>;
+					atmel,clk-input-range = <1000000 5000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
+				};
+
+				mck: masterck {
+					compatible = "atmel,at91rm9200-clk-master";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+					clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+					atmel,clk-output-range = <0 105000000>;
+					atmel,clk-divisors = <1 2 4 0>;
+				};
+
+				usb: usbck {
+					compatible = "atmel,at91rm9200-clk-usb";
+					#clock-cells = <0>;
+					atmel,clk-divisors = <1 2 4 0>;
+					clocks = <&pllb>;
+				};
+
+				prog: progck {
+					compatible = "atmel,at91rm9200-clk-programmable";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+
+					prog0: prog0 {
+						#clock-cells = <0>;
+						reg = <0>;
+						interrupts = <AT91_PMC_PCKRDY(0)>;
+					};
+
+					prog1: prog1 {
+						#clock-cells = <0>;
+						reg = <1>;
+						interrupts = <AT91_PMC_PCKRDY(1)>;
+					};
+				};
+
+				systemck {
+					compatible = "atmel,at91rm9200-clk-system";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					uhpck: uhpck {
+						#clock-cells = <0>;
+						reg = <6>;
+						clocks = <&usb>;
+					};
+
+					udpck: udpck {
+						#clock-cells = <0>;
+						reg = <7>;
+						clocks = <&usb>;
+					};
+
+					pck0: pck0 {
+						#clock-cells = <0>;
+						reg = <8>;
+						clocks = <&prog0>;
+					};
+
+					pck1: pck1 {
+						#clock-cells = <0>;
+						reg = <9>;
+						clocks = <&prog1>;
+					};
+				};
+
+				periphck {
+					compatible = "atmel,at91rm9200-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&mck>;
+
+					pioA_clk: pioA_clk {
+						#clock-cells = <0>;
+						reg = <2>;
+					};
+
+					pioB_clk: pioB_clk {
+						#clock-cells = <0>;
+						reg = <3>;
+					};
+
+					pioC_clk: pioC_clk {
+						#clock-cells = <0>;
+						reg = <4>;
+					};
+
+					adc_clk: adc_clk {
+						#clock-cells = <0>;
+						reg = <5>;
+					};
+
+					usart0_clk: usart0_clk {
+						#clock-cells = <0>;
+						reg = <6>;
+					};
+
+					usart1_clk: usart1_clk {
+						#clock-cells = <0>;
+						reg = <7>;
+					};
+
+					usart2_clk: usart2_clk {
+						#clock-cells = <0>;
+						reg = <8>;
+					};
+
+					mci0_clk: mci0_clk {
+						#clock-cells = <0>;
+						reg = <9>;
+					};
+
+					udc_clk: udc_clk {
+						#clock-cells = <0>;
+						reg = <10>;
+					};
+
+					twi0_clk: twi0_clk {
+						reg = <11>;
+						#clock-cells = <0>;
+					};
+
+					spi0_clk: spi0_clk {
+						#clock-cells = <0>;
+						reg = <12>;
+					};
+
+					spi1_clk: spi1_clk {
+						#clock-cells = <0>;
+						reg = <13>;
+					};
+
+					ssc0_clk: ssc0_clk {
+						#clock-cells = <0>;
+						reg = <14>;
+					};
+
+					tc0_clk: tc0_clk {
+						#clock-cells = <0>;
+						reg = <17>;
+					};
+
+					tc1_clk: tc1_clk {
+						#clock-cells = <0>;
+						reg = <18>;
+					};
+
+					tc2_clk: tc2_clk {
+						#clock-cells = <0>;
+						reg = <19>;
+					};
+
+					ohci_clk: ohci_clk {
+						#clock-cells = <0>;
+						reg = <20>;
+					};
+
+					macb0_clk: macb0_clk {
+						#clock-cells = <0>;
+						reg = <21>;
+					};
+
+					isi_clk: isi_clk {
+						#clock-cells = <0>;
+						reg = <22>;
+					};
+
+					usart3_clk: usart3_clk {
+						#clock-cells = <0>;
+						reg = <23>;
+					};
+
+					uart0_clk: uart0_clk {
+						#clock-cells = <0>;
+						reg = <24>;
+					};
+
+					uart1_clk: uart1_clk {
+						#clock-cells = <0>;
+						reg = <25>;
+					};
+
+					tc3_clk: tc3_clk {
+						#clock-cells = <0>;
+						reg = <26>;
+					};
+
+					tc4_clk: tc4_clk {
+						#clock-cells = <0>;
+						reg = <27>;
+					};
+
+					tc5_clk: tc5_clk {
+						#clock-cells = <0>;
+						reg = <28>;
+					};
+				};
 			};
 
 			rstc@fffffd00 {
@@ -92,6 +365,7 @@
 				compatible = "atmel,at91sam9260-pit";
 				reg = <0xfffffd30 0xf>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				clocks = <&mck>;
 			};
 
 			tcb0: timer@fffa0000 {
@@ -100,6 +374,8 @@
 				interrupts = <17 IRQ_TYPE_LEVEL_HIGH 0
 					      18 IRQ_TYPE_LEVEL_HIGH 0
 					      19 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tc0_clk>, <&tc1_clk>, <&tc2_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			tcb1: timer@fffdc000 {
@@ -108,6 +384,8 @@
 				interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0
 					      27 IRQ_TYPE_LEVEL_HIGH 0
 					      28 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tc3_clk>, <&tc4_clk>, <&tc5_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			pinctrl@fffff400 {
@@ -443,6 +721,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioA_clk>;
 				};
 
 				pioB: gpio@fffff600 {
@@ -453,6 +732,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioB_clk>;
 				};
 
 				pioC: gpio@fffff800 {
@@ -463,6 +743,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioC_clk>;
 				};
 			};
 
@@ -472,6 +753,8 @@
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_dbgu>;
+				clocks = <&mck>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -483,6 +766,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart0>;
+				clocks = <&usart0_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -494,6 +779,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart1>;
+				clocks = <&usart1_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -505,6 +792,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart2>;
+				clocks = <&usart2_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -516,6 +805,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart3>;
+				clocks = <&usart3_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -527,6 +818,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart0>;
+				clocks = <&uart0_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -538,6 +831,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart1>;
+				clocks = <&uart1_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -547,6 +842,8 @@
 				interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_macb_rmii>;
+				clocks = <&macb0_clk>, <&macb0_clk>;
+				clock-names = "hclk", "pclk";
 				status = "disabled";
 			};
 
@@ -554,6 +851,8 @@
 				compatible = "atmel,at91rm9200-udc";
 				reg = <0xfffa4000 0x4000>;
 				interrupts = <10 IRQ_TYPE_LEVEL_HIGH 2>;
+				clocks = <&udc_clk>, <&udpck>;
+				clock-names = "pclk", "hclk";
 				status = "disabled";
 			};
 
@@ -563,6 +862,7 @@
 				interrupts = <11 IRQ_TYPE_LEVEL_HIGH 6>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&twi0_clk>;
 				status = "disabled";
 			};
 
@@ -573,6 +873,8 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				pinctrl-names = "default";
+				clocks = <&mci0_clk>;
+				clock-names = "mci_clk";
 				status = "disabled";
 			};
 
@@ -582,6 +884,8 @@
 				interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				clocks = <&ssc0_clk>;
+				clock-names = "pclk";
 				status = "disabled";
 			};
 
@@ -593,6 +897,8 @@
 				interrupts = <12 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi0>;
+				clocks = <&spi0_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -604,6 +910,8 @@
 				interrupts = <13 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi1>;
+				clocks = <&spi1_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -613,6 +921,8 @@
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffe0000 0x100>;
 				interrupts = <5 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&adc_clk>, <&adc_op_clk>;
+				clock-names = "adc_clk", "adc_op_clk";
 				atmel,adc-use-external-triggers;
 				atmel,adc-channels-used = <0xf>;
 				atmel,adc-vref = <3300>;
@@ -680,6 +990,8 @@
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00500000 0x100000>;
 			interrupts = <20 IRQ_TYPE_LEVEL_HIGH 2>;
+			clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+			clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9261.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9261.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9261.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9261.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -46,16 +46,18 @@
 		reg = <0x20000000 0x08000000>;
 	};
 
-	main_xtal: main_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+	clocks {
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	slow_xtal: slow_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9261ek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9261ek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9261ek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9261ek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -20,14 +20,6 @@
 		reg = <0x20000000 0x4000000>;
 	};
 
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
-
-	main_xtal {
-		clock-frequency = <18432000>;
-	};
-
 	clocks {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -37,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9263.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9263.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9263.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9263.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
 	model = "Atmel AT91SAM9263 family SoC";
@@ -32,6 +33,7 @@
 		ssc1 = &ssc1;
 		pwm0 = &pwm0;
 	};
+
 	cpus {
 		#address-cells = <0>;
 		#size-cells = <0>;
@@ -46,6 +48,20 @@
 		reg = <0x20000000 0x08000000>;
 	};
 
+	clocks {
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
 	ahb {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -69,6 +85,264 @@
 			pmc: pmc@fffffc00 {
 				compatible = "atmel,at91rm9200-pmc";
 				reg = <0xfffffc00 0x100>;
+				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+
+				main_osc: main_osc {
+					compatible = "atmel,at91rm9200-clk-main-osc";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+					clocks = <&main_xtal>;
+				};
+
+				main: mainck {
+					compatible = "atmel,at91rm9200-clk-main";
+					#clock-cells = <0>;
+					clocks = <&main_osc>;
+				};
+
+				plla: pllack {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+					clocks = <&main>;
+					reg = <0>;
+					atmel,clk-input-range = <1000000 32000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <80000000 200000000 0 1>,
+								<190000000 240000000 2 1>;
+				};
+
+				pllb: pllbck {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+					clocks = <&main>;
+					reg = <1>;
+					atmel,clk-input-range = <1000000 5000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
+				};
+
+				mck: masterck {
+					compatible = "atmel,at91rm9200-clk-master";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+					clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+					atmel,clk-output-range = <0 120000000>;
+					atmel,clk-divisors = <1 2 4 0>;
+				};
+
+				usb: usbck {
+					compatible = "atmel,at91rm9200-clk-usb";
+					#clock-cells = <0>;
+					atmel,clk-divisors = <1 2 4 0>;
+					clocks = <&pllb>;
+				};
+
+				prog: progck {
+					compatible = "atmel,at91rm9200-clk-programmable";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+
+					prog0: prog0 {
+						#clock-cells = <0>;
+						reg = <0>;
+						interrupts = <AT91_PMC_PCKRDY(0)>;
+					};
+
+					prog1: prog1 {
+						#clock-cells = <0>;
+						reg = <1>;
+						interrupts = <AT91_PMC_PCKRDY(1)>;
+					};
+
+					prog2: prog2 {
+						#clock-cells = <0>;
+						reg = <2>;
+						interrupts = <AT91_PMC_PCKRDY(2)>;
+					};
+
+					prog3: prog3 {
+						#clock-cells = <0>;
+						reg = <3>;
+						interrupts = <AT91_PMC_PCKRDY(3)>;
+					};
+				};
+
+				systemck {
+					compatible = "atmel,at91rm9200-clk-system";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					uhpck: uhpck {
+						#clock-cells = <0>;
+						reg = <6>;
+						clocks = <&usb>;
+					};
+
+					udpck: udpck {
+						#clock-cells = <0>;
+						reg = <7>;
+						clocks = <&usb>;
+					};
+
+					pck0: pck0 {
+						#clock-cells = <0>;
+						reg = <8>;
+						clocks = <&prog0>;
+					};
+
+					pck1: pck1 {
+						#clock-cells = <0>;
+						reg = <9>;
+						clocks = <&prog1>;
+					};
+
+					pck2: pck2 {
+						#clock-cells = <0>;
+						reg = <10>;
+						clocks = <&prog2>;
+					};
+
+					pck3: pck3 {
+						#clock-cells = <0>;
+						reg = <11>;
+						clocks = <&prog3>;
+					};
+				};
+
+				periphck {
+					compatible = "atmel,at91rm9200-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&mck>;
+
+					pioA_clk: pioA_clk {
+						#clock-cells = <0>;
+						reg = <2>;
+					};
+
+					pioB_clk: pioB_clk {
+						#clock-cells = <0>;
+						reg = <3>;
+					};
+
+					pioCDE_clk: pioCDE_clk {
+						#clock-cells = <0>;
+						reg = <4>;
+					};
+
+					usart0_clk: usart0_clk {
+						#clock-cells = <0>;
+						reg = <7>;
+					};
+
+					usart1_clk: usart1_clk {
+						#clock-cells = <0>;
+						reg = <8>;
+					};
+
+					usart2_clk: usart2_clk {
+						#clock-cells = <0>;
+						reg = <9>;
+					};
+
+					mci0_clk: mci0_clk {
+						#clock-cells = <0>;
+						reg = <10>;
+					};
+
+					mci1_clk: mci1_clk {
+						#clock-cells = <0>;
+						reg = <11>;
+					};
+
+					can_clk: can_clk {
+						#clock-cells = <0>;
+						reg = <12>;
+					};
+
+					twi0_clk: twi0_clk {
+						#clock-cells = <0>;
+						reg = <13>;
+					};
+
+					spi0_clk: spi0_clk {
+						#clock-cells = <0>;
+						reg = <14>;
+					};
+
+					spi1_clk: spi1_clk {
+						#clock-cells = <0>;
+						reg = <15>;
+					};
+
+					ssc0_clk: ssc0_clk {
+						#clock-cells = <0>;
+						reg = <16>;
+					};
+
+					ssc1_clk: ssc1_clk {
+						#clock-cells = <0>;
+						reg = <17>;
+					};
+
+					ac91_clk: ac97_clk {
+						#clock-cells = <0>;
+						reg = <18>;
+					};
+
+					tcb_clk: tcb_clk {
+						#clock-cells = <0>;
+						reg = <19>;
+					};
+
+					pwm_clk: pwm_clk {
+						#clock-cells = <0>;
+						reg = <20>;
+					};
+
+					macb0_clk: macb0_clk {
+						#clock-cells = <0>;
+						reg = <21>;
+					};
+
+					g2de_clk: g2de_clk {
+						#clock-cells = <0>;
+						reg = <23>;
+					};
+
+					udc_clk: udc_clk {
+						#clock-cells = <0>;
+						reg = <24>;
+					};
+
+					isi_clk: isi_clk {
+						#clock-cells = <0>;
+						reg = <25>;
+					};
+
+					lcd_clk: lcd_clk {
+						#clock-cells = <0>;
+						reg = <26>;
+					};
+
+					dma_clk: dma_clk {
+						#clock-cells = <0>;
+						reg = <27>;
+					};
+
+					ohci_clk: ohci_clk {
+						#clock-cells = <0>;
+						reg = <29>;
+					};
+				};
 			};
 
 			ramc: ramc@ffffe200 {
@@ -81,12 +355,15 @@
 				compatible = "atmel,at91sam9260-pit";
 				reg = <0xfffffd30 0xf>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				clocks = <&mck>;
 			};
 
 			tcb0: timer@fff7c000 {
 				compatible = "atmel,at91rm9200-tcb";
 				reg = <0xfff7c000 0x100>;
 				interrupts = <19 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tcb_clk>;
+				clock-names = "t0_clk";
 			};
 
 			rstc@fffffd00 {
@@ -403,6 +680,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioA_clk>;
 				};
 
 				pioB: gpio@fffff400 {
@@ -413,6 +691,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioB_clk>;
 				};
 
 				pioC: gpio@fffff600 {
@@ -423,6 +702,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioCDE_clk>;
 				};
 
 				pioD: gpio@fffff800 {
@@ -433,6 +713,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioCDE_clk>;
 				};
 
 				pioE: gpio@fffffa00 {
@@ -443,6 +724,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioCDE_clk>;
 				};
 			};
 
@@ -452,6 +734,8 @@
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_dbgu>;
+				clocks = <&mck>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -463,6 +747,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart0>;
+				clocks = <&usart0_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -474,6 +760,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart1>;
+				clocks = <&usart1_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -485,6 +773,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart2>;
+				clocks = <&usart2_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -494,6 +784,8 @@
 				interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				clocks = <&ssc0_clk>;
+				clock-names = "pclk";
 				status = "disabled";
 			};
 
@@ -503,6 +795,8 @@
 				interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+				clocks = <&ssc1_clk>;
+				clock-names = "pclk";
 				status = "disabled";
 			};
 
@@ -512,6 +806,8 @@
 				interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_macb_rmii>;
+				clocks = <&macb0_clk>, <&macb0_clk>;
+				clock-names = "hclk", "pclk";
 				status = "disabled";
 			};
 
@@ -519,6 +815,8 @@
 				compatible = "atmel,at91rm9200-udc";
 				reg = <0xfff78000 0x4000>;
 				interrupts = <24 IRQ_TYPE_LEVEL_HIGH 2>;
+				clocks = <&udc_clk>, <&udpck>;
+				clock-names = "pclk", "hclk";
 				status = "disabled";
 			};
 
@@ -528,6 +826,7 @@
 				interrupts = <13 IRQ_TYPE_LEVEL_HIGH 6>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&twi0_clk>;
 				status = "disabled";
 			};
 
@@ -537,6 +836,8 @@
 				interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&mci0_clk>;
+				clock-names = "mci_clk";
 				status = "disabled";
 			};
 
@@ -546,6 +847,8 @@
 				interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&mci1_clk>;
+				clock-names = "mci_clk";
 				status = "disabled";
 			};
 
@@ -568,6 +871,8 @@
 				interrupts = <14 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi0>;
+				clocks = <&spi0_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -579,6 +884,8 @@
 				interrupts = <15 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi1>;
+				clocks = <&spi1_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -587,6 +894,8 @@
 				reg = <0xfffb8000 0x300>;
 				interrupts = <20 IRQ_TYPE_LEVEL_HIGH 4>;
 				#pwm-cells = <3>;
+				clocks = <&pwm_clk>;
+				clock-names = "pwm_clk";
 				status = "disabled";
 			};
 		};
@@ -622,6 +931,8 @@
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00a00000 0x100000>;
 			interrupts = <29 IRQ_TYPE_LEVEL_HIGH 2>;
+			clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+			clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9263ek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9263ek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9263ek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9263ek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <16367660>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <16367660>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g20.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g20.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g20.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g20.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,31 @@
 			adc0: adc@fffe0000 {
 				atmel,adc-startup-time = <40>;
 			};
+
+			pmc: pmc@fffffc00 {
+				plla: pllack {
+					atmel,clk-input-range = <2000000 32000000>;
+					atmel,pll-clk-output-ranges = <745000000 800000000 0 0>,
+								<695000000 750000000 1 0>,
+								<645000000 700000000 2 0>,
+								<595000000 650000000 3 0>,
+								<545000000 600000000 0 1>,
+								<495000000 550000000 1 1>,
+								<445000000 500000000 2 1>,
+								<400000000 450000000 3 1>;
+				};
+
+				pllb: pllbck {
+					compatible = "atmel,at91sam9g20-clk-pllb";
+					atmel,clk-input-range = <2000000 32000000>;
+					atmel,pll-clk-output-ranges = <30000000 100000000 0 0>;
+				};
+
+				mck: masterck {
+					atmel,clk-output-range = <0 133000000>;
+					atmel,clk-divisors = <1 2 4 6>;
+				};
+			};
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g20ek_common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g20ek_common.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g20ek_common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g45.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
 	model = "Atmel AT91SAM9G45 family SoC";
@@ -53,6 +54,26 @@
 		reg = <0x70000000 0x10000000>;
 	};
 
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		adc_op_clk: adc_op_clk{
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <300000>;
+		};
+	};
+
 	ahb {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -77,11 +98,279 @@
 				compatible = "atmel,at91sam9g45-ddramc";
 				reg = <0xffffe400 0x200
 				       0xffffe600 0x200>;
+				clocks = <&ddrck>;
+				clock-names = "ddrck";
 			};
 
 			pmc: pmc@fffffc00 {
-				compatible = "atmel,at91rm9200-pmc";
+				compatible = "atmel,at91sam9g45-pmc";
 				reg = <0xfffffc00 0x100>;
+				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+
+				main_osc: main_osc {
+					compatible = "atmel,at91rm9200-clk-main-osc";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+					clocks = <&main_xtal>;
+				};
+
+				main: mainck {
+					compatible = "atmel,at91rm9200-clk-main";
+					#clock-cells = <0>;
+					clocks = <&main_osc>;
+				};
+
+				plla: pllack {
+					compatible = "atmel,at91rm9200-clk-pll";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+					clocks = <&main>;
+					reg = <0>;
+					atmel,clk-input-range = <2000000 32000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <745000000 800000000 0 0
+								       695000000 750000000 1 0
+								       645000000 700000000 2 0
+								       595000000 650000000 3 0
+								       545000000 600000000 0 1
+								       495000000 555000000 1 1
+								       445000000 500000000 2 1
+								       400000000 450000000 3 1>;
+				};
+
+				plladiv: plladivck {
+					compatible = "atmel,at91sam9x5-clk-plldiv";
+					#clock-cells = <0>;
+					clocks = <&plla>;
+				};
+
+				utmi: utmick {
+					compatible = "atmel,at91sam9x5-clk-utmi";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_LOCKU>;
+					clocks = <&main>;
+				};
+
+				mck: masterck {
+					compatible = "atmel,at91rm9200-clk-master";
+					#clock-cells = <0>;
+					interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+					clocks = <&slow_xtal>, <&main>, <&plladiv>, <&utmi>;
+					atmel,clk-output-range = <0 133333333>;
+					atmel,clk-divisors = <1 2 4 3>;
+				};
+
+				usb: usbck {
+					compatible = "atmel,at91sam9x5-clk-usb";
+					#clock-cells = <0>;
+					clocks = <&plladiv>, <&utmi>;
+				};
+
+				prog: progck {
+					compatible = "atmel,at91sam9g45-clk-programmable";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&slow_xtal>, <&main>, <&plladiv>, <&utmi>, <&mck>;
+
+					prog0: prog0 {
+						#clock-cells = <0>;
+						reg = <0>;
+						interrupts = <AT91_PMC_PCKRDY(0)>;
+					};
+
+					prog1: prog1 {
+						#clock-cells = <0>;
+						reg = <1>;
+						interrupts = <AT91_PMC_PCKRDY(1)>;
+					};
+				};
+
+				systemck {
+					compatible = "atmel,at91rm9200-clk-system";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					ddrck: ddrck {
+						#clock-cells = <0>;
+						reg = <2>;
+						clocks = <&mck>;
+					};
+
+					uhpck: uhpck {
+						#clock-cells = <0>;
+						reg = <6>;
+						clocks = <&usb>;
+					};
+
+					pck0: pck0 {
+						#clock-cells = <0>;
+						reg = <8>;
+						clocks = <&prog0>;
+					};
+
+					pck1: pck1 {
+						#clock-cells = <0>;
+						reg = <9>;
+						clocks = <&prog1>;
+					};
+				};
+
+				periphck {
+					compatible = "atmel,at91rm9200-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&mck>;
+
+					pioA_clk: pioA_clk {
+						#clock-cells = <0>;
+						reg = <2>;
+					};
+
+					pioB_clk: pioB_clk {
+						#clock-cells = <0>;
+						reg = <3>;
+					};
+
+					pioC_clk: pioC_clk {
+						#clock-cells = <0>;
+						reg = <4>;
+					};
+
+					pioDE_clk: pioDE_clk {
+						#clock-cells = <0>;
+						reg = <5>;
+					};
+
+					trng_clk: trng_clk {
+						#clock-cells = <0>;
+						reg = <6>;
+					};
+
+					usart0_clk: usart0_clk {
+						#clock-cells = <0>;
+						reg = <7>;
+					};
+
+					usart1_clk: usart1_clk {
+						#clock-cells = <0>;
+						reg = <8>;
+					};
+
+					usart2_clk: usart2_clk {
+						#clock-cells = <0>;
+						reg = <9>;
+					};
+
+					usart3_clk: usart3_clk {
+						#clock-cells = <0>;
+						reg = <10>;
+					};
+
+					mci0_clk: mci0_clk {
+						#clock-cells = <0>;
+						reg = <11>;
+					};
+
+					twi0_clk: twi0_clk {
+						#clock-cells = <0>;
+						reg = <12>;
+					};
+
+					twi1_clk: twi1_clk {
+						#clock-cells = <0>;
+						reg = <13>;
+					};
+
+					spi0_clk: spi0_clk {
+						#clock-cells = <0>;
+						reg = <14>;
+					};
+
+					spi1_clk: spi1_clk {
+						#clock-cells = <0>;
+						reg = <15>;
+					};
+
+					ssc0_clk: ssc0_clk {
+						#clock-cells = <0>;
+						reg = <16>;
+					};
+
+					ssc1_clk: ssc1_clk {
+						#clock-cells = <0>;
+						reg = <17>;
+					};
+
+					tcb0_clk: tcb0_clk {
+						#clock-cells = <0>;
+						reg = <18>;
+					};
+
+					pwm_clk: pwm_clk {
+						#clock-cells = <0>;
+						reg = <19>;
+					};
+
+					adc_clk: adc_clk {
+						#clock-cells = <0>;
+						reg = <20>;
+					};
+
+					dma0_clk: dma0_clk {
+						#clock-cells = <0>;
+						reg = <21>;
+					};
+
+					uhphs_clk: uhphs_clk {
+						#clock-cells = <0>;
+						reg = <22>;
+					};
+
+					lcd_clk: lcd_clk {
+						#clock-cells = <0>;
+						reg = <23>;
+					};
+
+					ac97_clk: ac97_clk {
+						#clock-cells = <0>;
+						reg = <24>;
+					};
+
+					macb0_clk: macb0_clk {
+						#clock-cells = <0>;
+						reg = <25>;
+					};
+
+					isi_clk: isi_clk {
+						#clock-cells = <0>;
+						reg = <26>;
+					};
+
+					udphs_clk: udphs_clk {
+						#clock-cells = <0>;
+						reg = <27>;
+					};
+
+					aestdessha_clk: aestdessha_clk {
+						#clock-cells = <0>;
+						reg = <28>;
+					};
+
+					mci1_clk: mci1_clk {
+						#clock-cells = <0>;
+						reg = <29>;
+					};
+
+					vdec_clk: vdec_clk {
+						#clock-cells = <0>;
+						reg = <30>;
+					};
+				};
 			};
 
 			rstc@fffffd00 {
@@ -93,6 +382,7 @@
 				compatible = "atmel,at91sam9260-pit";
 				reg = <0xfffffd30 0xf>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+				clocks = <&mck>;
 			};
 
 
@@ -105,12 +395,16 @@
 				compatible = "atmel,at91rm9200-tcb";
 				reg = <0xfff7c000 0x100>;
 				interrupts = <18 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tcb0_clk>, <&tcb0_clk>, <&tcb0_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			tcb1: timer@fffd4000 {
 				compatible = "atmel,at91rm9200-tcb";
 				reg = <0xfffd4000 0x100>;
 				interrupts = <18 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&tcb0_clk>, <&tcb0_clk>, <&tcb0_clk>;
+				clock-names = "t0_clk", "t1_clk", "t2_clk";
 			};
 
 			dma: dma-controller@ffffec00 {
@@ -118,6 +412,8 @@
 				reg = <0xffffec00 0x200>;
 				interrupts = <21 IRQ_TYPE_LEVEL_HIGH 0>;
 				#dma-cells = <2>;
+				clocks = <&dma0_clk>;
+				clock-names = "dma_clk";
 			};
 
 			pinctrl@fffff200 {
@@ -516,6 +812,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioA_clk>;
 				};
 
 				pioB: gpio@fffff400 {
@@ -526,6 +823,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioB_clk>;
 				};
 
 				pioC: gpio@fffff600 {
@@ -536,6 +834,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioC_clk>;
 				};
 
 				pioD: gpio@fffff800 {
@@ -546,6 +845,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioDE_clk>;
 				};
 
 				pioE: gpio@fffffa00 {
@@ -556,6 +856,7 @@
 					gpio-controller;
 					interrupt-controller;
 					#interrupt-cells = <2>;
+					clocks = <&pioDE_clk>;
 				};
 			};
 
@@ -565,6 +866,8 @@
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_dbgu>;
+				clocks = <&mck>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -576,6 +879,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart0>;
+				clocks = <&usart0_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -587,6 +892,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart1>;
+				clocks = <&usart1_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -598,6 +905,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart2>;
+				clocks = <&usart2_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -609,6 +918,8 @@
 				atmel,use-dma-tx;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_usart3>;
+				clocks = <&usart3_clk>;
+				clock-names = "usart";
 				status = "disabled";
 			};
 
@@ -618,6 +929,8 @@
 				interrupts = <25 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_macb_rmii>;
+				clocks = <&macb0_clk>, <&macb0_clk>;
+				clock-names = "hclk", "pclk";
 				status = "disabled";
 			};
 
@@ -629,6 +942,7 @@
 				pinctrl-0 = <&pinctrl_i2c0>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&twi0_clk>;
 				status = "disabled";
 			};
 
@@ -640,6 +954,7 @@
 				pinctrl-0 = <&pinctrl_i2c1>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&twi1_clk>;
 				status = "disabled";
 			};
 
@@ -649,6 +964,8 @@
 				interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				clocks = <&ssc0_clk>;
+				clock-names = "pclk";
 				status = "disabled";
 			};
 
@@ -658,6 +975,8 @@
 				interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+				clocks = <&ssc1_clk>;
+				clock-names = "pclk";
 				status = "disabled";
 			};
 
@@ -667,6 +986,8 @@
 				compatible = "atmel,at91sam9g45-adc";
 				reg = <0xfffb0000 0x100>;
 				interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&adc_clk>, <&adc_op_clk>;
+				clock-names = "adc_clk", "adc_op_clk";
 				atmel,adc-channels-used = <0xff>;
 				atmel,adc-vref = <3300>;
 				atmel,adc-startup-time = <40>;
@@ -706,6 +1027,7 @@
 				reg = <0xfffb8000 0x300>;
 				interrupts = <19 IRQ_TYPE_LEVEL_HIGH 4>;
 				#pwm-cells = <3>;
+				clocks = <&pwm_clk>;
 				status = "disabled";
 			};
 
@@ -718,6 +1040,8 @@
 				dma-names = "rxtx";
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&mci0_clk>;
+				clock-names = "mci_clk";
 				status = "disabled";
 			};
 
@@ -730,6 +1054,8 @@
 				dma-names = "rxtx";
 				#address-cells = <1>;
 				#size-cells = <0>;
+				clocks = <&mci1_clk>;
+				clock-names = "mci_clk";
 				status = "disabled";
 			};
 
@@ -752,6 +1078,8 @@
 				interrupts = <14 4 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi0>;
+				clocks = <&spi0_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -763,6 +1091,8 @@
 				interrupts = <15 4 3>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_spi1>;
+				clocks = <&spi1_clk>;
+				clock-names = "spi_clk";
 				status = "disabled";
 			};
 
@@ -773,6 +1103,8 @@
 				reg = <0x00600000 0x80000
 				       0xfff78000 0x400>;
 				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&udphs_clk>, <&utmi>;
+				clock-names = "pclk", "hclk";
 				status = "disabled";
 
 				ep0 {
@@ -835,6 +1167,8 @@
 			interrupts = <23 IRQ_TYPE_LEVEL_HIGH 3>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_fb>;
+			clocks = <&lcd_clk>, <&lcd_clk>;
+			clock-names = "hclk", "lcdc_clk";
 			status = "disabled";
 		};
 
@@ -861,6 +1195,9 @@
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00700000 0x100000>;
 			interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
+			//TODO
+			clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
+			clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
 			status = "disabled";
 		};
 
@@ -868,6 +1205,9 @@
 			compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
 			reg = <0x00800000 0x100000>;
 			interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
+			//TODO
+			clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
+			clock-names = "usb_clk", "ehci_clk", "hclk", "uhpck";
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+		      clock-frequency = <32768>;
+		};
+
+		main_xtal {
+		      clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9n12.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9n12.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9n12.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9n12.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -50,16 +50,18 @@
 		reg = <0x20000000 0x10000000>;
 	};
 
-	slow_xtal: slow_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	main_xtal: main_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9n12ek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9n12ek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9n12ek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9n12ek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -21,14 +21,6 @@
 		reg = <0x20000000 0x8000000>;
 	};
 
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
-
-	main_xtal {
-		clock-frequency = <16000000>;
-	};
-
 	clocks {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -38,6 +30,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <16000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <16000000>;
+		};
 	};
 
 	ahb {
@@ -56,6 +56,8 @@
 				wm8904: codec@1a {
 					compatible = "wm8904";
 					reg = <0x1a>;
+					clocks = <&pck0>;
+					clock-names = "mclk";
 				};
 
 				qt1070: keyboard@1b {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9rl.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9rl.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9rl.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9rl.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -50,19 +50,19 @@
 		reg = <0x20000000 0x04000000>;
 	};
 
-	slow_xtal: slow_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	main_xtal: main_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	clocks {
 		adc_op_clk: adc_op_clk{
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
@@ -95,6 +95,7 @@
 			      <0xffffe800 0x200>;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			atmel,nand-has-dma;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioD 17 GPIO_ACTIVE_HIGH>,
@@ -348,6 +349,15 @@
 				};
 			};
 
+			dma0: dma-controller@ffffe600 {
+				compatible = "atmel,at91sam9rl-dma";
+				reg = <0xffffe600 0x200>;
+				interrupts = <21 IRQ_TYPE_LEVEL_HIGH 0>;
+				#dma-cells = <2>;
+				clocks = <&dma0_clk>;
+				clock-names = "dma_clk";
+			};
+
 			ramc0: ramc@ffffea00 {
 				compatible = "atmel,at91sam9260-sdramc";
 				reg = <0xffffea00 0x200>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9rlek.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9rlek.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9rlek.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9rlek.dts	2014-09-28 17:29:07.000000000 -0400
@@ -20,15 +20,6 @@
 		reg = <0x20000000 0x4000000>;
 	};
 
-
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
-
-	main_xtal {
-		clock-frequency = <12000000>;
-	};
-
 	clocks {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -38,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9x5cm.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9x5cm.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9x5cm.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9x5cm.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -23,12 +23,14 @@
 		};
 	};
 
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
 
-	main_xtal {
-		clock-frequency = <12000000>;
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9x5.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9x5.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91sam9x5.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91sam9x5.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -52,22 +52,24 @@
 		reg = <0x20000000 0x10000000>;
 	};
 
-	slow_xtal: slow_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	main_xtal: main_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	adc_op_clk: adc_op_clk{
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <5000000>;
+		adc_op_clk: adc_op_clk{
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <5000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts	2014-09-28 17:29:07.000000000 -0400
@@ -21,12 +21,14 @@
 		reg = <0x20000000 0x10000000>;
 	};
 
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
 
-	main_xtal {
-		clock-frequency = <12000000>;
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/bcm11351.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm11351.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/bcm11351.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm11351.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,25 @@
 		bootargs = "console=ttyS0,115200n8";
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "brcm,bcm11351-cpu-method";
+		secondary-boot-reg = <0x3500417c>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
 	gic: interrupt-controller@3ff00100 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/bcm21664.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm21664.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/bcm21664.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm21664.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,25 @@
 		bootargs = "console=ttyS0,115200n8";
 	};
 
+       cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "brcm,bcm11351-cpu-method";
+		secondary-boot-reg = <0x35004178>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
 	gic: interrupt-controller@3ff00100 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+/dts-v1/;
+#include "bcm7445.dtsi"
+
+/ {
+	model = "Broadcom STB (bcm7445), SVMB reference board";
+	compatible = "brcm,bcm7445", "brcm,brcmstb";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00 0x00000000 0x00 0x40000000>,
+		      <0x00 0x40000000 0x00 0x40000000>,
+		      <0x00 0x80000000 0x00 0x40000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/bcm7445.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm7445.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/bcm7445.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/bcm7445.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,111 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "Broadcom STB (bcm7445)";
+	compatible = "brcm,bcm7445", "brcm,brcmstb";
+	interrupt-parent = <&gic>;
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "brcm,brahma-b15";
+			device_type = "cpu";
+			enable-method = "brcm,brahma-b15";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "brcm,brahma-b15";
+			device_type = "cpu";
+			enable-method = "brcm,brahma-b15";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "brcm,brahma-b15";
+			device_type = "cpu";
+			enable-method = "brcm,brahma-b15";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "brcm,brahma-b15";
+			device_type = "cpu";
+			enable-method = "brcm,brahma-b15";
+			reg = <3>;
+		};
+	};
+
+	gic: interrupt-controller@ffd00000 {
+		compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic";
+		reg = <0x00 0xffd01000 0x00 0x1000>,
+		      <0x00 0xffd02000 0x00 0x2000>,
+		      <0x00 0xffd04000 0x00 0x2000>,
+		      <0x00 0xffd06000 0x00 0x2000>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	rdb {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0 0x00 0xf0000000 0x1000000>;
+
+		serial@40ab00 {
+			compatible = "ns16550a";
+			reg = <0x40ab00 0x20>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			clock-frequency = <0x4d3f640>;
+		};
+
+		sun_top_ctrl: syscon@404000 {
+			compatible = "brcm,bcm7445-sun-top-ctrl",
+				     "syscon";
+			reg = <0x404000 0x51c>;
+		};
+
+		hif_cpubiuctrl: syscon@3e2400 {
+			compatible = "brcm,bcm7445-hif-cpubiuctrl",
+				     "syscon";
+			reg = <0x3e2400 0x5b4>;
+		};
+
+		hif_continuation: syscon@452000 {
+			compatible = "brcm,bcm7445-hif-continuation",
+				     "syscon";
+			reg = <0x452000 0x100>;
+		};
+	};
+
+	smpboot {
+		compatible = "brcm,brcmstb-smpboot";
+		syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+		syscon-cont = <&hif_continuation>;
+	};
+
+	reboot {
+		compatible = "brcm,brcmstb-reboot";
+		syscon = <&sun_top_ctrl 0x304 0x308>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
+		enable-method = "marvell,berlin-smp";
 
 		cpu@0 {
 			compatible = "marvell,pj4b";
@@ -78,6 +79,11 @@
 			clocks = <&chip CLKID_TWD>;
 		};
 
+		cpu-ctrl@dd0000 {
+			compatible = "marvell,berlin-cpu-ctrl";
+			reg = <0xdd0000 0x10000>;
+		};
+
 		apb@e80000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2q.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2q.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2q.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2q.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
+		enable-method = "marvell,berlin-smp";
 
 		cpu@0 {
 			compatible = "arm,cortex-a9";
@@ -90,6 +91,8 @@
 			compatible = "arm,pl310-cache";
 			reg = <0xac0000 0x1000>;
 			cache-level = <2>;
+			arm,data-latency = <2 2 2>;
+			arm,tag-latency = <2 2 2>;
 		};
 
 		scu: snoop-control-unit@ad0000 {
@@ -111,6 +114,11 @@
 			#interrupt-cells = <3>;
 		};
 
+		cpu-ctrl@dd0000 {
+			compatible = "marvell,berlin-cpu-ctrl";
+			reg = <0xdd0000 0x10000>;
+		};
+
 		apb@e80000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -191,6 +199,32 @@
 				};
 			};
 
+			i2c0: i2c@1400 {
+				compatible = "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x1400 0x100>;
+				interrupt-parent = <&aic>;
+				interrupts = <4>;
+				clocks = <&chip CLKID_CFG>;
+				pinctrl-0 = <&twsi0_pmux>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			i2c1: i2c@1800 {
+				compatible = "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x1800 0x100>;
+				interrupt-parent = <&aic>;
+				interrupts = <5>;
+				clocks = <&chip CLKID_CFG>;
+				pinctrl-0 = <&twsi1_pmux>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
 			timer0: timer@2c00 {
 				compatible = "snps,dw-apb-timer";
 				reg = <0x2c00 0x14>;
@@ -301,6 +335,16 @@
 			reg = <0xea0000 0x400>, <0xdd0170 0x10>;
 			clocks = <&refclk>;
 			clock-names = "refclk";
+
+			twsi0_pmux: twsi0-pmux {
+				groups = "G6";
+				function = "twsi0";
+			};
+
+			twsi1_pmux: twsi1-pmux {
+				groups = "G7";
+				function = "twsi1";
+			};
 		};
 
 		apb@fc0000 {
@@ -311,6 +355,32 @@
 			ranges = <0 0xfc0000 0x10000>;
 			interrupt-parent = <&sic>;
 
+			i2c2: i2c@7000 {
+				compatible = "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x7000 0x100>;
+				interrupt-parent = <&sic>;
+				interrupts = <6>;
+				clocks = <&refclk>;
+				pinctrl-0 = <&twsi2_pmux>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			i2c3: i2c@8000 {
+				compatible = "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x8000 0x100>;
+				interrupt-parent = <&sic>;
+				interrupts = <7>;
+				clocks = <&refclk>;
+				pinctrl-0 = <&twsi3_pmux>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
 			uart0: uart@9000 {
 				compatible = "snps,dw-apb-uart";
 				reg = <0x9000 0x100>;
@@ -348,6 +418,16 @@
 					groups = "GSM14";
 					function = "uart1";
 				};
+
+				twsi2_pmux: twsi2-pmux {
+					groups = "GSM13";
+					function = "twsi2";
+				};
+
+				twsi3_pmux: twsi3-pmux {
+					groups = "GSM14";
+					function = "twsi3";
+				};
 			};
 
 			sic: interrupt-controller@e000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,14 @@
 	status = "okay";
 };
 
+&i2c0 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/cros-ec-keyboard.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/cros-ec-keyboard.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/cros-ec-keyboard.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/cros-ec-keyboard.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * Keyboard dts fragment for devices that use cros-ec-keyboard
+ *
+ * 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.
+*/
+
+#include <dt-bindings/input/input.h>
+
+&cros_ec {
+	keyboard-controller {
+		compatible = "google,cros-ec-keyb";
+		keypad,num-rows = <8>;
+		keypad,num-columns = <13>;
+		google,needs-ghost-filter;
+
+		linux,keymap = <
+			MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
+			MATRIX_KEY(0x00, 0x02, KEY_F1)
+			MATRIX_KEY(0x00, 0x03, KEY_B)
+			MATRIX_KEY(0x00, 0x04, KEY_F10)
+			MATRIX_KEY(0x00, 0x06, KEY_N)
+			MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
+			MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
+
+			MATRIX_KEY(0x01, 0x01, KEY_ESC)
+			MATRIX_KEY(0x01, 0x02, KEY_F4)
+			MATRIX_KEY(0x01, 0x03, KEY_G)
+			MATRIX_KEY(0x01, 0x04, KEY_F7)
+			MATRIX_KEY(0x01, 0x06, KEY_H)
+			MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
+			MATRIX_KEY(0x01, 0x09, KEY_F9)
+			MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
+
+			MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
+			MATRIX_KEY(0x02, 0x01, KEY_TAB)
+			MATRIX_KEY(0x02, 0x02, KEY_F3)
+			MATRIX_KEY(0x02, 0x03, KEY_T)
+			MATRIX_KEY(0x02, 0x04, KEY_F6)
+			MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
+			MATRIX_KEY(0x02, 0x06, KEY_Y)
+			MATRIX_KEY(0x02, 0x07, KEY_102ND)
+			MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
+			MATRIX_KEY(0x02, 0x09, KEY_F8)
+
+			MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
+			MATRIX_KEY(0x03, 0x02, KEY_F2)
+			MATRIX_KEY(0x03, 0x03, KEY_5)
+			MATRIX_KEY(0x03, 0x04, KEY_F5)
+			MATRIX_KEY(0x03, 0x06, KEY_6)
+			MATRIX_KEY(0x03, 0x08, KEY_MINUS)
+			MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
+
+			MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
+			MATRIX_KEY(0x04, 0x01, KEY_A)
+			MATRIX_KEY(0x04, 0x02, KEY_D)
+			MATRIX_KEY(0x04, 0x03, KEY_F)
+			MATRIX_KEY(0x04, 0x04, KEY_S)
+			MATRIX_KEY(0x04, 0x05, KEY_K)
+			MATRIX_KEY(0x04, 0x06, KEY_J)
+			MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
+			MATRIX_KEY(0x04, 0x09, KEY_L)
+			MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+			MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
+
+			MATRIX_KEY(0x05, 0x01, KEY_Z)
+			MATRIX_KEY(0x05, 0x02, KEY_C)
+			MATRIX_KEY(0x05, 0x03, KEY_V)
+			MATRIX_KEY(0x05, 0x04, KEY_X)
+			MATRIX_KEY(0x05, 0x05, KEY_COMMA)
+			MATRIX_KEY(0x05, 0x06, KEY_M)
+			MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
+			MATRIX_KEY(0x05, 0x08, KEY_SLASH)
+			MATRIX_KEY(0x05, 0x09, KEY_DOT)
+			MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
+
+			MATRIX_KEY(0x06, 0x01, KEY_1)
+			MATRIX_KEY(0x06, 0x02, KEY_3)
+			MATRIX_KEY(0x06, 0x03, KEY_4)
+			MATRIX_KEY(0x06, 0x04, KEY_2)
+			MATRIX_KEY(0x06, 0x05, KEY_8)
+			MATRIX_KEY(0x06, 0x06, KEY_7)
+			MATRIX_KEY(0x06, 0x08, KEY_0)
+			MATRIX_KEY(0x06, 0x09, KEY_9)
+			MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
+			MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
+			MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
+
+			MATRIX_KEY(0x07, 0x01, KEY_Q)
+			MATRIX_KEY(0x07, 0x02, KEY_E)
+			MATRIX_KEY(0x07, 0x03, KEY_R)
+			MATRIX_KEY(0x07, 0x04, KEY_W)
+			MATRIX_KEY(0x07, 0x05, KEY_I)
+			MATRIX_KEY(0x07, 0x06, KEY_U)
+			MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
+			MATRIX_KEY(0x07, 0x08, KEY_P)
+			MATRIX_KEY(0x07, 0x09, KEY_O)
+			MATRIX_KEY(0x07, 0x0b, KEY_UP)
+			MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dove-cubox.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove-cubox.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dove-cubox.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove-cubox.dts	2014-09-28 17:29:07.000000000 -0400
@@ -111,9 +111,6 @@
 
 &sdio0 {
 	status = "okay";
-	/* sdio0 card detect is connected to wrong pin on CuBox */
-	cd-gpios = <&gpio0 12 1>;
-	pinctrl-0 = <&pmx_sdio0 &pmx_gpio_12>;
 };
 
 &spi0 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dove-cubox-es.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove-cubox-es.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dove-cubox-es.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove-cubox-es.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,12 @@
+#include "dove-cubox.dts"
+
+/ {
+	model = "SolidRun CuBox (Engineering Sample)";
+	compatible = "solidrun,cubox-es", "solidrun,cubox", "marvell,dove";
+};
+
+&sdio0 {
+	/* sdio0 card detect is connected to wrong pin on CuBox ES */
+	cd-gpios = <&gpio0 12 1>;
+	pinctrl-0 = <&pmx_sdio0 &pmx_gpio_12>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dove.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dove.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dove.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -630,6 +630,20 @@
 				reg = <0xe8400 0x0c>;
 				ngpios = <8>;
 			};
+
+			lcd1: lcd-controller@810000 {
+				compatible = "marvell,dove-lcd";
+				reg = <0x810000 0x1000>;
+				interrupts = <46>;
+				status = "disabled";
+			};
+
+			lcd0: lcd-controller@820000 {
+				compatible = "marvell,dove-lcd";
+				reg = <0x820000 0x1000>;
+				interrupts = <47>;
+				status = "disabled";
+			};
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dra7.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dra7.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,9 @@
 
 #include "skeleton.dtsi"
 
+#define MAX_SOURCES 400
+#define DIRECT_IRQ(irq) (MAX_SOURCES + irq)
+
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -45,6 +48,7 @@
 		compatible = "arm,cortex-a15-gic";
 		interrupt-controller;
 		#interrupt-cells = <3>;
+		arm,routable-irqs = <192>;
 		reg = <0x48211000 0x1000>,
 		      <0x48212000 0x1000>,
 		      <0x48214000 0x2000>,
@@ -79,8 +83,8 @@
 		ti,hwmods = "l3_main_1", "l3_main_2";
 		reg = <0x44000000 0x1000000>,
 		      <0x45000000 0x1000>;
-		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
 
 		prm: prm@4ae06000 {
 			compatible = "ti,dra7-prm";
@@ -95,6 +99,75 @@
 			};
 		};
 
+		axi@0 {
+			compatible = "simple-bus";
+			#size-cells = <1>;
+			#address-cells = <1>;
+			ranges = <0x51000000 0x51000000 0x3000
+				  0x0	     0x20000000 0x10000000>;
+			pcie@51000000 {
+				compatible = "ti,dra7-pcie";
+				reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
+				reg-names = "rc_dbics", "ti_conf", "config";
+				interrupts = <0 232 0x4>, <0 233 0x4>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				device_type = "pci";
+				ranges = <0x81000000 0 0          0x03000 0 0x00010000
+					  0x82000000 0 0x20013000 0x13000 0 0xffed000>;
+				#interrupt-cells = <1>;
+				num-lanes = <1>;
+				ti,hwmods = "pcie1";
+				phys = <&pcie1_phy>;
+				phy-names = "pcie-phy0";
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie1_intc 1>,
+						<0 0 0 2 &pcie1_intc 2>,
+						<0 0 0 3 &pcie1_intc 3>,
+						<0 0 0 4 &pcie1_intc 4>;
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#address-cells = <0>;
+					#interrupt-cells = <1>;
+				};
+			};
+		};
+
+		axi@1 {
+			compatible = "simple-bus";
+			#size-cells = <1>;
+			#address-cells = <1>;
+			ranges = <0x51800000 0x51800000 0x3000
+				  0x0	     0x30000000 0x10000000>;
+			status = "disabled";
+			pcie@51000000 {
+				compatible = "ti,dra7-pcie";
+				reg = <0x51800000 0x2000>, <0x51802000 0x14c>, <0x1000 0x2000>;
+				reg-names = "rc_dbics", "ti_conf", "config";
+				interrupts = <0 355 0x4>, <0 356 0x4>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				device_type = "pci";
+				ranges = <0x81000000 0 0          0x03000 0 0x00010000
+					  0x82000000 0 0x30013000 0x13000 0 0xffed000>;
+				#interrupt-cells = <1>;
+				num-lanes = <1>;
+				ti,hwmods = "pcie2";
+				phys = <&pcie2_phy>;
+				phy-names = "pcie-phy0";
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie2_intc 1>,
+						<0 0 0 2 &pcie2_intc 2>,
+						<0 0 0 3 &pcie2_intc 3>,
+						<0 0 0 4 &pcie2_intc 4>;
+				pcie2_intc: interrupt-controller {
+					interrupt-controller;
+					#address-cells = <0>;
+					#interrupt-cells = <1>;
+				};
+			};
+		};
+
 		cm_core_aon: cm_core_aon@4a005000 {
 			compatible = "ti,dra7-cm-core-aon";
 			reg = <0x4a005000 0x2000>;
@@ -155,10 +228,10 @@
 		sdma: dma-controller@4a056000 {
 			compatible = "ti,omap4430-sdma";
 			reg = <0x4a056000 0x1000>;
-			interrupts = <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>;
+			interrupts = <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>;
 			#dma-cells = <1>;
 			#dma-channels = <32>;
 			#dma-requests = <127>;
@@ -167,95 +240,95 @@
 		gpio1: gpio@4ae10000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x4ae10000 0x200>;
-			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio1";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio2: gpio@48055000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x48055000 0x200>;
-			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio2";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio3: gpio@48057000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x48057000 0x200>;
-			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio3";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio4: gpio@48059000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x48059000 0x200>;
-			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio4";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio5: gpio@4805b000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x4805b000 0x200>;
-			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio5";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio6: gpio@4805d000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x4805d000 0x200>;
-			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio6";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio7: gpio@48051000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x48051000 0x200>;
-			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio7";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		gpio8: gpio@48053000 {
 			compatible = "ti,omap4-gpio";
 			reg = <0x48053000 0x200>;
-			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "gpio8";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 		};
 
 		uart1: serial@4806a000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806a000 0x100>;
-			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -264,7 +337,7 @@
 		uart2: serial@4806c000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806c000 0x100>;
-			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -273,7 +346,7 @@
 		uart3: serial@48020000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48020000 0x100>;
-			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -282,7 +355,7 @@
 		uart4: serial@4806e000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806e000 0x100>;
-			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
                         status = "disabled";
@@ -291,7 +364,7 @@
 		uart5: serial@48066000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48066000 0x100>;
-			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -300,7 +373,7 @@
 		uart6: serial@48068000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48068000 0x100>;
-			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -309,6 +382,7 @@
 		uart7: serial@48420000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48420000 0x100>;
+			interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart7";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -317,6 +391,7 @@
 		uart8: serial@48422000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48422000 0x100>;
+			interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart8";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -325,6 +400,7 @@
 		uart9: serial@48424000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48424000 0x100>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart9";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -333,15 +409,133 @@
 		uart10: serial@4ae2b000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4ae2b000 0x100>;
+			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart10";
 			clock-frequency = <48000000>;
 			status = "disabled";
 		};
 
+		mailbox1: mailbox@4a0f4000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4a0f4000 0x200>;
+			ti,hwmods = "mailbox1";
+			ti,mbox-num-users = <3>;
+			ti,mbox-num-fifos = <8>;
+			status = "disabled";
+		};
+
+		mailbox2: mailbox@4883a000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4883a000 0x200>;
+			ti,hwmods = "mailbox2";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox3: mailbox@4883c000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4883c000 0x200>;
+			ti,hwmods = "mailbox3";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox4: mailbox@4883e000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4883e000 0x200>;
+			ti,hwmods = "mailbox4";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox5: mailbox@48840000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48840000 0x200>;
+			ti,hwmods = "mailbox5";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox6: mailbox@48842000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48842000 0x200>;
+			ti,hwmods = "mailbox6";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox7: mailbox@48844000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48844000 0x200>;
+			ti,hwmods = "mailbox7";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox8: mailbox@48846000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48846000 0x200>;
+			ti,hwmods = "mailbox8";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox9: mailbox@4885e000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4885e000 0x200>;
+			ti,hwmods = "mailbox9";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox10: mailbox@48860000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48860000 0x200>;
+			ti,hwmods = "mailbox10";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox11: mailbox@48862000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48862000 0x200>;
+			ti,hwmods = "mailbox11";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox12: mailbox@48864000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48864000 0x200>;
+			ti,hwmods = "mailbox12";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
+		mailbox13: mailbox@48802000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x48802000 0x200>;
+			ti,hwmods = "mailbox13";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <12>;
+			status = "disabled";
+		};
+
 		timer1: timer@4ae18000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x4ae18000 0x80>;
-			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer1";
 			ti,timer-alwon;
 		};
@@ -349,28 +543,28 @@
 		timer2: timer@48032000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48032000 0x80>;
-			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer2";
 		};
 
 		timer3: timer@48034000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48034000 0x80>;
-			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer3";
 		};
 
 		timer4: timer@48036000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48036000 0x80>;
-			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer4";
 		};
 
 		timer5: timer@48820000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48820000 0x80>;
-			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer5";
 			ti,timer-dsp;
 		};
@@ -378,7 +572,7 @@
 		timer6: timer@48822000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48822000 0x80>;
-			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer6";
 			ti,timer-dsp;
 			ti,timer-pwm;
@@ -387,7 +581,7 @@
 		timer7: timer@48824000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48824000 0x80>;
-			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer7";
 			ti,timer-dsp;
 		};
@@ -395,7 +589,7 @@
 		timer8: timer@48826000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48826000 0x80>;
-			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer8";
 			ti,timer-dsp;
 			ti,timer-pwm;
@@ -404,21 +598,21 @@
 		timer9: timer@4803e000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x4803e000 0x80>;
-			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer9";
 		};
 
 		timer10: timer@48086000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48086000 0x80>;
-			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer10";
 		};
 
 		timer11: timer@48088000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48088000 0x80>;
-			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer11";
 			ti,timer-pwm;
 		};
@@ -426,6 +620,7 @@
 		timer13: timer@48828000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48828000 0x80>;
+			interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer13";
 			status = "disabled";
 		};
@@ -433,6 +628,7 @@
 		timer14: timer@4882a000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x4882a000 0x80>;
+			interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer14";
 			status = "disabled";
 		};
@@ -440,6 +636,7 @@
 		timer15: timer@4882c000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x4882c000 0x80>;
+			interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer15";
 			status = "disabled";
 		};
@@ -447,6 +644,7 @@
 		timer16: timer@4882e000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x4882e000 0x80>;
+			interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer16";
 			status = "disabled";
 		};
@@ -454,7 +652,7 @@
 		wdt2: wdt@4ae14000 {
 			compatible = "ti,omap4-wdt";
 			reg = <0x4ae14000 0x80>;
-			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "wd_timer2";
 		};
 
@@ -468,14 +666,14 @@
 		dmm@4e000000 {
 			compatible = "ti,omap5-dmm";
 			reg = <0x4e000000 0x800>;
-			interrupts = <0 113 0x4>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "dmm";
 		};
 
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x48070000 0x100>;
-			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
@@ -485,7 +683,7 @@
 		i2c2: i2c@48072000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x48072000 0x100>;
-			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
@@ -495,7 +693,7 @@
 		i2c3: i2c@48060000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x48060000 0x100>;
-			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
@@ -505,7 +703,7 @@
 		i2c4: i2c@4807a000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x4807a000 0x100>;
-			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c4";
@@ -515,7 +713,7 @@
 		i2c5: i2c@4807c000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x4807c000 0x100>;
-			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c5";
@@ -525,7 +723,7 @@
 		mmc1: mmc@4809c000 {
 			compatible = "ti,omap4-hsmmc";
 			reg = <0x4809c000 0x400>;
-			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
@@ -538,7 +736,7 @@
 		mmc2: mmc@480b4000 {
 			compatible = "ti,omap4-hsmmc";
 			reg = <0x480b4000 0x400>;
-			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
 			dmas = <&sdma 47>, <&sdma 48>;
@@ -549,7 +747,7 @@
 		mmc3: mmc@480ad000 {
 			compatible = "ti,omap4-hsmmc";
 			reg = <0x480ad000 0x400>;
-			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc3";
 			ti,needs-special-reset;
 			dmas = <&sdma 77>, <&sdma 78>;
@@ -560,7 +758,7 @@
 		mmc4: mmc@480d1000 {
 			compatible = "ti,omap4-hsmmc";
 			reg = <0x480d1000 0x400>;
-			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc4";
 			ti,needs-special-reset;
 			dmas = <&sdma 57>, <&sdma 58>;
@@ -703,7 +901,7 @@
 		mcspi1: spi@48098000 {
 			compatible = "ti,omap4-mcspi";
 			reg = <0x48098000 0x200>;
-			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi1";
@@ -724,7 +922,7 @@
 		mcspi2: spi@4809a000 {
 			compatible = "ti,omap4-mcspi";
 			reg = <0x4809a000 0x200>;
-			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi2";
@@ -740,7 +938,7 @@
 		mcspi3: spi@480b8000 {
 			compatible = "ti,omap4-mcspi";
 			reg = <0x480b8000 0x200>;
-			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi3";
@@ -753,7 +951,7 @@
 		mcspi4: spi@480ba000 {
 			compatible = "ti,omap4-mcspi";
 			reg = <0x480ba000 0x200>;
-			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi4";
@@ -773,6 +971,7 @@
 			clocks = <&qspi_gfclk_div>;
 			clock-names = "fck";
 			num-cs = <4>;
+			interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
@@ -803,18 +1002,76 @@
 				clock-names = "sysclk";
 				#phy-cells = <0>;
 			};
+
+			pcie1_phy: pciephy@4a094000 {
+				compatible = "ti,phy-pipe3-pcie";
+				reg = <0x4a094000 0x80>, /* phy_rx */
+				      <0x4a094400 0x64>; /* phy_tx */
+				reg-names = "phy_rx", "phy_tx";
+				ctrl-module = <&omap_control_pcie1phy>;
+				clocks = <&dpll_pcie_ref_ck>,
+					 <&dpll_pcie_ref_m2ldo_ck>,
+					 <&optfclk_pciephy1_32khz>,
+					 <&optfclk_pciephy1_clk>,
+					 <&optfclk_pciephy1_div_clk>,
+					 <&optfclk_pciephy_div>;
+				clock-names = "dpll_ref", "dpll_ref_m2",
+					      "wkupclk", "refclk",
+					      "div-clk", "phy-div";
+				#phy-cells = <0>;
+				id = <1>;
+				ti,hwmods = "pcie1-phy";
+			};
+
+			pcie2_phy: pciephy@4a095000 {
+				compatible = "ti,phy-pipe3-pcie";
+				reg = <0x4a095000 0x80>, /* phy_rx */
+				      <0x4a095400 0x64>; /* phy_tx */
+				reg-names = "phy_rx", "phy_tx";
+				ctrl-module = <&omap_control_pcie2phy>;
+				clocks = <&dpll_pcie_ref_ck>,
+					 <&dpll_pcie_ref_m2ldo_ck>,
+					 <&optfclk_pciephy2_32khz>,
+					 <&optfclk_pciephy2_clk>,
+					 <&optfclk_pciephy2_div_clk>,
+					 <&optfclk_pciephy_div>;
+				clock-names = "dpll_ref", "dpll_ref_m2",
+					      "wkupclk", "refclk",
+					      "div-clk", "phy-div";
+				#phy-cells = <0>;
+				ti,hwmods = "pcie2-phy";
+				id = <2>;
+				status = "disabled";
+			};
 		};
 
 		sata: sata@4a141100 {
 			compatible = "snps,dwc-ahci";
 			reg = <0x4a140000 0x1100>, <0x4a141100 0x7>;
-			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&sata_phy>;
 			phy-names = "sata-phy";
 			clocks = <&sata_ref_clk>;
 			ti,hwmods = "sata";
 		};
 
+		omap_control_pcie1phy: control-phy@0x4a003c40 {
+			compatible = "ti,control-phy-pcie";
+			reg = <0x4a003c40 0x4>, <0x4a003c14 0x4>, <0x4a003c34 0x4>;
+			reg-names = "power", "control_sma", "pcie_pcs";
+			clocks = <&sys_clkin1>;
+			clock-names = "sysclk";
+		};
+
+		omap_control_pcie2phy: control-pcie@0x4a003c44 {
+			compatible = "ti,control-phy-pcie";
+			reg = <0x4a003c44 0x4>, <0x4a003c14 0x4>, <0x4a003c34 0x4>;
+			reg-names = "power", "control_sma", "pcie_pcs";
+			clocks = <&sys_clkin1>;
+			clock-names = "sysclk";
+			status = "disabled";
+		};
+
 		omap_control_usb2phy1: control-phy@4a002300 {
 			compatible = "ti,control-phy-usb2";
 			reg = <0x4a002300 0x4>;
@@ -885,7 +1142,7 @@
 			compatible = "ti,dwc3";
 			ti,hwmods = "usb_otg_ss1";
 			reg = <0x48880000 0x10000>;
-			interrupts = <0 77 4>;
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			utmi-mode = <2>;
@@ -893,7 +1150,7 @@
 			usb1: usb@48890000 {
 				compatible = "snps,dwc3";
 				reg = <0x48890000 0x17000>;
-				interrupts = <0 76 4>;
+				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usb2_phy1>, <&usb3_phy1>;
 				phy-names = "usb2-phy", "usb3-phy";
 				tx-fifo-resize;
@@ -906,7 +1163,7 @@
 			compatible = "ti,dwc3";
 			ti,hwmods = "usb_otg_ss2";
 			reg = <0x488c0000 0x10000>;
-			interrupts = <0 92 4>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			utmi-mode = <2>;
@@ -914,7 +1171,7 @@
 			usb2: usb@488d0000 {
 				compatible = "snps,dwc3";
 				reg = <0x488d0000 0x17000>;
-				interrupts = <0 78 4>;
+				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usb2_phy2>;
 				phy-names = "usb2-phy";
 				tx-fifo-resize;
@@ -928,7 +1185,7 @@
 			compatible = "ti,dwc3";
 			ti,hwmods = "usb_otg_ss3";
 			reg = <0x48900000 0x10000>;
-		/*	interrupts = <0 TBD 4>; */
+			interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			utmi-mode = <2>;
@@ -937,7 +1194,7 @@
 			usb3: usb@48910000 {
 				compatible = "snps,dwc3";
 				reg = <0x48910000 0x17000>;
-		/*		interrupts = <0 93 4>; */
+				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
 				tx-fifo-resize;
 				maximum-speed = "high-speed";
 				dr_mode = "otg";
@@ -948,7 +1205,7 @@
 			compatible = "ti,dwc3";
 			ti,hwmods = "usb_otg_ss4";
 			reg = <0x48940000 0x10000>;
-		/*	interrupts = <0 TBD 4>; */
+			interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			utmi-mode = <2>;
@@ -957,7 +1214,7 @@
 			usb4: usb@48950000 {
 				compatible = "snps,dwc3";
 				reg = <0x48950000 0x17000>;
-		/*		interrupts = <0 TBD 4>; */
+				interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>;
 				tx-fifo-resize;
 				maximum-speed = "high-speed";
 				dr_mode = "otg";
@@ -967,7 +1224,7 @@
 		elm: elm@48078000 {
 			compatible = "ti,am3352-elm";
 			reg = <0x48078000 0xfc0>;      /* device IO registers */
-			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "elm";
 			status = "disabled";
 		};
@@ -976,7 +1233,7 @@
 			compatible = "ti,am3352-gpmc";
 			ti,hwmods = "gpmc";
 			reg = <0x50000000 0x37c>;      /* device IO registers */
-			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <2>;
 			#address-cells = <2>;
@@ -994,6 +1251,17 @@
 			clock-names = "fck";
 			status = "disabled";
 		};
+
+		crossbar_mpu: crossbar@4a020000 {
+			compatible = "ti,irq-crossbar";
+			reg = <0x4a002a48 0x130>;
+			ti,max-irqs = <160>;
+			ti,max-crossbar-sources = <MAX_SOURCES>;
+			ti,reg-size = <2>;
+			ti,irqs-reserved = <0 1 2 3 5 6 131 132>;
+			ti,irqs-skip = <10 133 139 140>;
+			ti,irqs-safe-map = <0>;
+		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dra7-evm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7-evm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dra7-evm.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7-evm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 #include "dra74x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "TI DRA742";
@@ -24,9 +25,29 @@
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 	};
+
+	vtt_fixed: fixedregulator-vtt {
+		compatible = "regulator-fixed";
+		regulator-name = "vtt_fixed";
+		regulator-min-microvolt = <1350000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &dra7_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <&vtt_pin>;
+
+	vtt_pin: pinmux_vtt_pin {
+		pinctrl-single,pins = <
+			0x3b4 (PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */
+		>;
+	};
+
 	i2c1_pins: pinmux_i2c1_pins {
 		pinctrl-single,pins = <
 			0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */
@@ -43,20 +64,19 @@
 
 	i2c3_pins: pinmux_i2c3_pins {
 		pinctrl-single,pins = <
-			0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */
-			0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */
+			0x288 (PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */
+			0x28c (PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */
 		>;
 	};
 
 	mcspi1_pins: pinmux_mcspi1_pins {
 		pinctrl-single,pins = <
-			0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */
-			0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */
-			0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */
-			0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
-			0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */
-			0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */
-			0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */
+			0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */
+			0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */
+			0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */
+			0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */
+			0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */
+			0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */
 		>;
 	};
 
@@ -284,7 +304,7 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c3_pins>;
-	clock-frequency = <3400000>;
+	clock-frequency = <400000>;
 };
 
 &mcspi1 {
@@ -427,22 +447,19 @@
 		gpmc,device-width = <2>;
 		gpmc,sync-clk-ps = <0>;
 		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <40>;
-		gpmc,cs-wr-off-ns = <40>;
+		gpmc,cs-rd-off-ns = <80>;
+		gpmc,cs-wr-off-ns = <80>;
 		gpmc,adv-on-ns = <0>;
-		gpmc,adv-rd-off-ns = <30>;
-		gpmc,adv-wr-off-ns = <30>;
-		gpmc,we-on-ns = <5>;
-		gpmc,we-off-ns = <25>;
-		gpmc,oe-on-ns = <2>;
-		gpmc,oe-off-ns = <20>;
-		gpmc,access-ns = <20>;
-		gpmc,wr-access-ns = <40>;
-		gpmc,rd-cycle-ns = <40>;
-		gpmc,wr-cycle-ns = <40>;
-		gpmc,wait-pin = <0>;
-		gpmc,wait-on-read;
-		gpmc,wait-on-write;
+		gpmc,adv-rd-off-ns = <60>;
+		gpmc,adv-wr-off-ns = <60>;
+		gpmc,we-on-ns = <10>;
+		gpmc,we-off-ns = <50>;
+		gpmc,oe-on-ns = <4>;
+		gpmc,oe-off-ns = <40>;
+		gpmc,access-ns = <40>;
+		gpmc,wr-access-ns = <80>;
+		gpmc,rd-cycle-ns = <80>;
+		gpmc,wr-cycle-ns = <80>;
 		gpmc,bus-turnaround-ns = <0>;
 		gpmc,cycle2cycle-delay-ns = <0>;
 		gpmc,clk-activation-ns = <0>;
@@ -483,7 +500,7 @@
 			reg = <0x001c0000 0x00020000>;
 		};
 		partition@7 {
-			label = "NAND.u-boot-env";
+			label = "NAND.u-boot-env.backup1";
 			reg = <0x001e0000 0x00020000>;
 		};
 		partition@8 {
@@ -496,3 +513,16 @@
 		};
 	};
 };
+
+&usb2_phy1 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&gpio7 {
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -1154,7 +1154,7 @@
 
 	apll_pcie_in_clk_mux: apll_pcie_in_clk_mux@4ae06118 {
 		compatible = "ti,mux-clock";
-		clocks = <&dpll_pcie_ref_ck>, <&pciesref_acs_clk_ck>;
+		clocks = <&dpll_pcie_ref_m2ldo_ck>, <&pciesref_acs_clk_ck>;
 		#clock-cells = <0>;
 		reg = <0x021c 0x4>;
 		ti,bit-shift = <7>;
@@ -1167,16 +1167,33 @@
 		reg = <0x021c>, <0x0220>;
 	};
 
+	optfclk_pciephy1_32khz: optfclk_pciephy1_32khz@4a0093b0 {
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		#clock-cells = <0>;
+		reg = <0x13b0>;
+		ti,bit-shift = <8>;
+	};
+
+	optfclk_pciephy2_32khz: optfclk_pciephy2_32khz@4a0093b8 {
+		compatible = "ti,gate-clock";
+		clocks = <&sys_32k_ck>;
+		#clock-cells = <0>;
+		reg = <0x13b8>;
+		ti,bit-shift = <8>;
+	};
+
 	optfclk_pciephy_div: optfclk_pciephy_div@4a00821c {
 		compatible = "ti,divider-clock";
 		clocks = <&apll_pcie_ck>;
 		#clock-cells = <0>;
 		reg = <0x021c>;
+		ti,dividers = <2>, <1>;
 		ti,bit-shift = <8>;
 		ti,max-div = <2>;
 	};
 
-	optfclk_pciephy_clk: optfclk_pciephy_clk@4a0093b0 {
+	optfclk_pciephy1_clk: optfclk_pciephy1_clk@4a0093b0 {
 		compatible = "ti,gate-clock";
 		clocks = <&apll_pcie_ck>;
 		#clock-cells = <0>;
@@ -1184,7 +1201,15 @@
 		ti,bit-shift = <9>;
 	};
 
-	optfclk_pciephy_div_clk: optfclk_pciephy_div_clk@4a0093b0 {
+	optfclk_pciephy2_clk: optfclk_pciephy2_clk@4a0093b8 {
+		compatible = "ti,gate-clock";
+		clocks = <&apll_pcie_ck>;
+		#clock-cells = <0>;
+		reg = <0x13b8>;
+		ti,bit-shift = <9>;
+	};
+
+	optfclk_pciephy1_div_clk: optfclk_pciephy1_div_clk@4a0093b0 {
 		compatible = "ti,gate-clock";
 		clocks = <&optfclk_pciephy_div>;
 		#clock-cells = <0>;
@@ -1192,6 +1217,14 @@
 		ti,bit-shift = <10>;
 	};
 
+	optfclk_pciephy2_div_clk: optfclk_pciephy2_div_clk@4a0093b8 {
+		compatible = "ti,gate-clock";
+		clocks = <&optfclk_pciephy_div>;
+		#clock-cells = <0>;
+		reg = <0x13b8>;
+		ti,bit-shift = <10>;
+	};
+
 	apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
 		#clock-cells = <0>;
 		compatible = "fixed-factor-clock";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/emev2.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/emev2.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/emev2.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/emev2.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,11 +31,13 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clock-frequency = <533000000>;
 		};
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clock-frequency = <533000000>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ethernut5.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ethernut5.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ethernut5.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ethernut5.dts	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,16 @@
 		reg = <0x20000000 0x08000000>;
 	};
 
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	};
+
 	ahb {
 		apb {
 			dbgu: serial@fffff200 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/evk-pro3.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/evk-pro3.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/evk-pro3.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/evk-pro3.dts	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,12 @@
 	model = "Telit EVK-PRO3 for Telit GE863-PRO3";
 	compatible = "telit,evk-pro3", "atmel,at91sam9260", "atmel,at91sam9";
 
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+	};
+
 	ahb {
 		apb {
 			macb0: ethernet@fffc4000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos3250.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos3250.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos3250.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos3250.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,8 @@
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
+		serial0 = &serial_0;
+		serial1 = &serial_1;
 	};
 
 	cpus {
@@ -168,6 +170,15 @@
 			status = "disabled";
 		};
 
+		tmu: tmu@100C0000 {
+			compatible = "samsung,exynos3250-tmu";
+			reg = <0x100C0000 0x100>;
+			interrupts = <0 216 0>;
+			clocks = <&cmu CLK_TMU_APBIF>;
+			clock-names = "tmu_apbif";
+			status = "disabled";
+		};
+
 		gic: interrupt-controller@10481000 {
 			compatible = "arm,cortex-a15-gic";
 			#interrupt-cells = <3>;
@@ -195,7 +206,6 @@
 
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
-				interrupt-parent = <&gic>;
 				interrupts = <0 48 0>;
 			};
 		};
@@ -234,7 +244,6 @@
 			compatible = "arm,amba-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
-			interrupt-parent = <&gic>;
 			ranges;
 
 			pdma0: pdma@12680000 {
@@ -261,10 +270,11 @@
 		};
 
 		adc: adc@126C0000 {
-			compatible = "samsung,exynos-adc-v3";
+			compatible = "samsung,exynos3250-adc",
+				     "samsung,exynos-adc-v2";
 			reg = <0x126C0000 0x100>, <0x10020718 0x4>;
 			interrupts = <0 137 0>;
-			clock-names = "adc", "sclk_tsadc";
+			clock-names = "adc", "sclk";
 			clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
 			#io-channel-cells = <1>;
 			io-channel-ranges;
@@ -277,6 +287,8 @@
 			interrupts = <0 109 0>;
 			clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
 			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_data &uart0_fctl>;
 			status = "disabled";
 		};
 
@@ -286,6 +298,8 @@
 			interrupts = <0 110 0>;
 			clocks = <&cmu CLK_UART1>, <&cmu CLK_SCLK_UART1>;
 			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1_data>;
 			status = "disabled";
 		};
 
@@ -425,6 +439,19 @@
 			status = "disabled";
 		};
 
+		i2s2: i2s@13970000 {
+			compatible = "samsung,s3c6410-i2s";
+			reg = <0x13970000 0x100>;
+			interrupts = <0 126 0>;
+			clocks = <&cmu CLK_I2S>, <&cmu CLK_SCLK_I2S>;
+			clock-names = "iis", "i2s_opclk0";
+			dmas = <&pdma0 14>, <&pdma0 13>;
+			dma-names = "tx", "rx";
+			pinctrl-0 = <&i2s2_bus>;
+			pinctrl-names = "default";
+			status = "disabled";
+		};
+
 		pwm: pwm@139D0000 {
 			compatible = "samsung,exynos4210-pwm";
 			reg = <0x139D0000 0x1000>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4210.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4210.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4210.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4210.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,16 @@
 		pinctrl2 = &pinctrl_2;
 	};
 
+	pmu_system_controller: system-controller@10020000 {
+		clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+				"clkout4", "clkout8", "clkout9";
+		clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+			<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+			<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+			<&clock CLK_XUSBXTI>;
+		#clock-cells = <1>;
+	};
+
 	sysram@02020000 {
 		compatible = "mmio-sram";
 		reg = <0x02020000 0x20000>;
@@ -93,12 +103,6 @@
 		#clock-cells = <1>;
 	};
 
-	pmu {
-		compatible = "arm,cortex-a9-pmu";
-		interrupt-parent = <&combiner>;
-		interrupts = <2 2>, <3 2>;
-	};
-
 	pinctrl_0: pinctrl@11400000 {
 		compatible = "samsung,exynos4210-pinctrl";
 		reg = <0x11400000 0x1000>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4210-smdkv310.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4210-smdkv310.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4210-smdkv310.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4210-smdkv310.dts	2014-09-28 17:29:07.000000000 -0400
@@ -168,6 +168,7 @@
 	};
 
 	spi_2: spi@13940000 {
+		cs-gpios = <&gpc1 2 0>;
 		status = "okay";
 
 		w25x80@0 {
@@ -178,7 +179,6 @@
 			spi-max-frequency = <1000000>;
 
 			controller-data {
-				cs-gpio = <&gpc1 2 0>;
 				samsung,spi-feedback-delay = <0>;
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,10 @@
 		samsung,combiner-nr = <20>;
 	};
 
+	pmu {
+		interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
+	};
+
 	gic: interrupt-controller@10490000 {
 		cpu-offset = <0x4000>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,384 @@
+/*
+ * Common definition for Hardkernel's Exynos4412 based ODROID-X/X2/U2/U3 boards
+ * device tree source
+ *
+ * This program is free software; you can redistribute 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/input/input.h>
+#include "exynos4412.dtsi"
+
+/ {
+	firmware@0204F000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x0204F000 0x1000>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_power_key>;
+
+		power_key {
+			interrupt-parent = <&gpx1>;
+			interrupts = <3 0>;
+			gpios = <&gpx1 3 1>;
+			linux,code = <KEY_POWER>;
+			label = "power key";
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+	};
+
+	i2s0: i2s@03830000 {
+		pinctrl-0 = <&i2s0_bus>;
+		pinctrl-names = "default";
+		status = "okay";
+		clocks = <&clock_audss EXYNOS_I2S_BUS>,
+			 <&clock_audss EXYNOS_DOUT_AUD_BUS>;
+		clock-names = "iis", "i2s_opclk0";
+	};
+
+	sound: sound {
+		compatible = "samsung,odroidx2-audio";
+		samsung,i2s-controller = <&i2s0>;
+		samsung,audio-codec = <&max98090>;
+	};
+
+	mmc@12550000 {
+		pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+		pinctrl-names = "default";
+		vmmc-supply = <&ldo20_reg &buck8_reg>;
+		status = "okay";
+
+		num-slots = <1>;
+		supports-highspeed;
+		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>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
+
+	watchdog@10060000 {
+		status = "okay";
+	};
+
+	rtc@10070000 {
+		status = "okay";
+	};
+
+	g2d@10800000 {
+		status = "okay";
+	};
+
+	camera {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <>;
+
+		fimc_0: fimc@11800000 {
+			status = "okay";
+		};
+
+		fimc_1: fimc@11810000 {
+			status = "okay";
+		};
+
+		fimc_2: fimc@11820000 {
+			status = "okay";
+		};
+
+		fimc_3: fimc@11830000 {
+			status = "okay";
+		};
+	};
+
+	sdhci@12530000 {
+		bus-width = <4>;
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+		pinctrl-names = "default";
+		vmmc-supply = <&ldo4_reg &ldo21_reg>;
+		cd-gpios = <&gpk2 2 0>;
+		cd-inverted;
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	i2c@13860000 {
+		pinctrl-0 = <&i2c0_bus>;
+		pinctrl-names = "default";
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <400000>;
+		status = "okay";
+
+		usb3503: usb3503@08 {
+			compatible = "smsc,usb3503";
+			reg = <0x08>;
+
+			intn-gpios = <&gpx3 0 0>;
+			connect-gpios = <&gpx3 4 0>;
+			reset-gpios = <&gpx3 5 0>;
+			initial-mode = <1>;
+		};
+
+		max77686: pmic@09 {
+			compatible = "maxim,max77686";
+			interrupt-parent = <&gpx3>;
+			interrupts = <2 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&max77686_irq>;
+			reg = <0x09>;
+			#clock-cells = <1>;
+
+			voltage-regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "VDD_ALIVE_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "VDDQ_M1_2_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "VDDQ_EXT_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "VDDQ_MMC2_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "VDDQ_MMC1_3_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "VDD10_MPLL_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "VDD10_XPLL_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "VDD18_ABB1_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "VDD33_USB_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "VDDQ_C2C_W_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "VDD18_ABB0_2_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "VDD10_HSIC_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "VDD18_HSIC_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo20_reg: LDO20 {
+					regulator-name = "LDO20_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-boot-on;
+				};
+
+				ldo21_reg: LDO21 {
+					regulator-name = "LDO21_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo25_reg: LDO25 {
+					regulator-name = "VDDQ_LCD_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-microvolt-offset = <50000>;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "VDDQ_CKEM1_2_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck6_reg: BUCK6 {
+					regulator-name = "BUCK6_1.35V";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck7_reg: BUCK7 {
+					regulator-name = "BUCK7_2.0V";
+					regulator-min-microvolt = <2000000>;
+					regulator-max-microvolt = <2000000>;
+					regulator-always-on;
+				};
+
+				buck8_reg: BUCK8 {
+					regulator-name = "BUCK8_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+			};
+		};
+	};
+
+	i2c@13870000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_bus>;
+		status = "okay";
+		max98090: max98090@10 {
+			compatible = "maxim,max98090";
+			reg = <0x10>;
+			interrupt-parent = <&gpx0>;
+			interrupts = <0 0>;
+		};
+	};
+
+	exynos-usbphy@125B0000 {
+		status = "okay";
+	};
+
+	hsotg@12480000 {
+		status = "okay";
+		vusb_d-supply = <&ldo15_reg>;
+		vusb_a-supply = <&ldo12_reg>;
+	};
+
+	ehci: ehci@12580000 {
+		status = "okay";
+	};
+};
+
+&pinctrl_1 {
+	gpio_power_key: power_key {
+		samsung,pins = "gpx1-3";
+		samsung,pin-pud = <0>;
+	};
+
+	max77686_irq: max77686-irq {
+		samsung,pins = "gpx3-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidu3.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidu3.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidu3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidu3.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-U3 board device tree source
+ *
+ * Copyright (c) 2014 Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-U3 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 "exynos4412-odroid-common.dtsi"
+
+/ {
+	model = "Hardkernel ODROID-U3 board based on Exynos4412";
+	compatible = "hardkernel,odroid-u3", "samsung,exynos4412", "samsung,exynos4";
+
+	memory {
+		reg = <0x40000000 0x7FF00000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led1 {
+			label = "led1:heart";
+			gpios = <&gpc1 0 1>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&usb3503 {
+	clock-names = "refclk";
+	clocks = <&pmu_system_controller 0>;
+	refclk-frequency = <24000000>;
+};
+
+&ehci {
+	port@1 {
+		status = "okay";
+	};
+	port@2 {
+		status = "okay";
+	};
+};
+
+&sound {
+	compatible = "samsung,odroidu3-audio";
+	samsung,model = "Odroid-U3";
+	samsung,audio-routing =
+		"Headphone Jack", "HPL",
+		"Headphone Jack", "HPR",
+		"Headphone Jack", "MICBIAS",
+		"IN1", "Headphone Jack",
+		"Speakers", "SPKL",
+		"Speakers", "SPKR";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidx2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidx2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidx2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidx2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-X2 board device tree source
+ *
+ * Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-X2 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 "exynos4412-odroidx.dts"
+
+/ {
+	model = "Hardkernel ODROID-X2 board based on Exynos4412";
+	compatible = "hardkernel,odroid-x2", "samsung,exynos4412", "samsung,exynos4";
+
+	memory {
+		reg = <0x40000000 0x7FF00000>;
+	};
+};
+
+&sound {
+	samsung,model = "Odroid-X2";
+	samsung,audio-routing =
+		"Headphone Jack", "HPL",
+		"Headphone Jack", "HPR",
+		"IN1", "Mic Jack",
+		"Mic Jack", "MICBIAS";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -3,8 +3,8 @@
  *
  * Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
  *
- * Device tree source file for Hardkernel's ODROID-X board which is based on
- * Samsung's Exynos4412 SoC.
+ * Device tree source file for Hardkernel's ODROID-X 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
@@ -12,14 +12,14 @@
 */
 
 /dts-v1/;
-#include "exynos4412.dtsi"
+#include "exynos4412-odroid-common.dtsi"
 
 / {
 	model = "Hardkernel ODROID-X board based on Exynos4412";
 	compatible = "hardkernel,odroid-x", "samsung,exynos4412", "samsung,exynos4";
 
 	memory {
-		reg = <0x40000000 0x40000000>;
+		reg = <0x40000000 0x3FF00000>;
 	};
 
 	leds {
@@ -38,23 +38,25 @@
 		};
 	};
 
-	mmc@12550000 {
-		pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
-		pinctrl-names = "default";
-		vmmc-supply = <&ldo20_reg &buck8_reg>;
+	serial@13820000 {
 		status = "okay";
+	};
 
-		num-slots = <1>;
-		supports-highspeed;
-		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>;
+	serial@13830000 {
+		status = "okay";
+	};
 
-		slot@0 {
-			reg = <0>;
-			bus-width = <8>;
+	gpio_keys {
+		pinctrl-0 = <&gpio_power_key &gpio_home_key>;
+
+		home_key {
+			interrupt-parent = <&gpx2>;
+			interrupts = <2 0>;
+			gpios = <&gpx2 2 0>;
+			linux,code = <KEY_HOME>;
+			label = "home key";
+			debounce-interval = <10>;
+			gpio-key,wakeup;
 		};
 	};
 
@@ -65,242 +67,19 @@
 		regulator-max-microvolt = <3300000>;
 		gpio = <&gpa1 1 1>;
 		enable-active-high;
-		regulator-boot-on;
-	};
-
-	rtc@10070000 {
-		status = "okay";
-	};
-
-	sdhci@12530000 {
-		bus-width = <4>;
-		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
-		pinctrl-names = "default";
-		vmmc-supply = <&ldo4_reg &ldo21_reg>;
-		status = "okay";
-	};
-
-	serial@13800000 {
-		status = "okay";
-	};
-
-	serial@13810000 {
-		status = "okay";
-	};
-
-	serial@13820000 {
-		status = "okay";
+		regulator-always-on;
 	};
+};
 
-	serial@13830000 {
+&ehci {
+	port@1 {
 		status = "okay";
 	};
+};
 
-	fixed-rate-clocks {
-		xxti {
-			compatible = "samsung,clock-xxti";
-			clock-frequency = <0>;
-		};
-
-		xusbxti {
-			compatible = "samsung,clock-xusbxti";
-			clock-frequency = <24000000>;
-		};
-	};
-
-	i2c@13860000 {
-		pinctrl-0 = <&i2c0_bus>;
-		pinctrl-names = "default";
-		status = "okay";
-
-		max77686: pmic@09 {
-			compatible = "maxim,max77686";
-			reg = <0x09>;
-			#clock-cells = <1>;
-
-			voltage-regulators {
-				ldo1_reg: LDO1 {
-					regulator-name = "VDD_ALIVE_1.0V";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo2_reg: LDO2 {
-					regulator-name = "VDDQ_M1_2_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo3_reg: LDO3 {
-					regulator-name = "VDDQ_EXT_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo4_reg: LDO4 {
-					regulator-name = "VDDQ_MMC2_2.8V";
-					regulator-min-microvolt = <2800000>;
-					regulator-max-microvolt = <2800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo5_reg: LDO5 {
-					regulator-name = "VDDQ_MMC1_3_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo6_reg: LDO6 {
-					regulator-name = "VDD10_MPLL_1.0V";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo7_reg: LDO7 {
-					regulator-name = "VDD10_XPLL_1.0V";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo11_reg: LDO11 {
-					regulator-name = "VDD18_ABB1_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo12_reg: LDO12 {
-					regulator-name = "VDD33_USB_3.3V";
-					regulator-min-microvolt = <3300000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo13_reg: LDO13 {
-					regulator-name = "VDDQ_C2C_W_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo14_reg: LDO14 {
-					regulator-name = "VDD18_ABB0_2_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo15_reg: LDO15 {
-					regulator-name = "VDD10_HSIC_1.0V";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo16_reg: LDO16 {
-					regulator-name = "VDD18_HSIC_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo20_reg: LDO20 {
-					regulator-name = "LDO20_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-boot-on;
-				};
-
-				ldo21_reg: LDO21 {
-					regulator-name = "LDO21_3.3V";
-					regulator-min-microvolt = <3300000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo25_reg: LDO25 {
-					regulator-name = "VDDQ_LCD_1.8V";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck1_reg: BUCK1 {
-					regulator-name = "vdd_mif";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck2_reg: BUCK2 {
-					regulator-name = "vdd_arm";
-					regulator-min-microvolt = <900000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck3_reg: BUCK3 {
-					regulator-name = "vdd_int";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck4_reg: BUCK4 {
-					regulator-name = "vdd_g3d";
-					regulator-min-microvolt = <900000>;
-					regulator-max-microvolt = <1100000>;
-					regulator-microvolt-offset = <50000>;
-				};
-
-				buck5_reg: BUCK5 {
-					regulator-name = "VDDQ_CKEM1_2_1.2V";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck6_reg: BUCK6 {
-					regulator-name = "BUCK6_1.35V";
-					regulator-min-microvolt = <1350000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck7_reg: BUCK7 {
-					regulator-name = "BUCK7_2.0V";
-					regulator-min-microvolt = <2000000>;
-					regulator-max-microvolt = <2000000>;
-					regulator-always-on;
-				};
-
-				buck8_reg: BUCK8 {
-					regulator-name = "BUCK8_2.8V";
-					regulator-min-microvolt = <2800000>;
-					regulator-max-microvolt = <2800000>;
-					regulator-always-on;
-				};
-			};
-		};
+&pinctrl_1 {
+	gpio_home_key: home_key {
+		samsung,pins = "gpx2-2";
+		samsung,pin-pud = <0>;
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-trats2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-trats2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4412-trats2.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4412-trats2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -589,6 +589,7 @@
 	spi_1: spi@13930000 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi1_bus>;
+		cs-gpios = <&gpb 5 0>;
 		status = "okay";
 
 		s5c73m3_spi: s5c73m3 {
@@ -596,7 +597,6 @@
 			spi-max-frequency = <50000000>;
 			reg = <0>;
 			controller-data {
-				cs-gpio = <&gpb 5 0>;
 				samsung,spi-feedback-delay = <2>;
 			};
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,10 @@
 		fimc1 = &fimc_1;
 		fimc2 = &fimc_2;
 		fimc3 = &fimc_3;
+		serial0 = &serial_0;
+		serial1 = &serial_1;
+		serial2 = &serial_2;
+		serial3 = &serial_3;
 	};
 
 	clock_audss: clock-controller@03810000 {
@@ -123,6 +127,12 @@
 		reg = <0x10440000 0x1000>;
 	};
 
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupt-parent = <&combiner>;
+		interrupts = <2 2>, <3 2>;
+	};
+
 	sys_reg: syscon@10010000 {
 		compatible = "samsung,exynos4-sysreg", "syscon";
 		reg = <0x10010000 0x400>;
@@ -322,6 +332,23 @@
 		clocks = <&clock CLK_USB_HOST>;
 		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@12590000 {
@@ -331,6 +358,13 @@
 		clocks = <&clock CLK_USB_HOST>;
 		clock-names = "usbhost";
 		status = "disabled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		port@0 {
+		    reg = <0>;
+		    phys = <&exynos_usbphy 1>;
+		    status = "disabled";
+		};
 	};
 
 	i2s1: i2s@13960000 {
@@ -363,7 +397,7 @@
 		status = "disabled";
 	};
 
-	serial@13800000 {
+	serial_0: serial@13800000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
 		interrupts = <0 52 0>;
@@ -372,7 +406,7 @@
 		status = "disabled";
 	};
 
-	serial@13810000 {
+	serial_1: serial@13810000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
 		interrupts = <0 53 0>;
@@ -381,7 +415,7 @@
 		status = "disabled";
 	};
 
-	serial@13820000 {
+	serial_2: serial@13820000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
 		interrupts = <0 54 0>;
@@ -390,7 +424,7 @@
 		status = "disabled";
 	};
 
-	serial@13830000 {
+	serial_3: serial@13830000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
 		interrupts = <0 55 0>;
@@ -608,6 +642,7 @@
 		clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
 		clock-names = "sclk_fimd", "fimd";
 		samsung,power-domain = <&pd_lcd0>;
+		samsung,sysreg = <&sys_reg>;
 		status = "disabled";
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4x12.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4x12.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,12 +31,6 @@
 		mshc0 = &mshc_0;
 	};
 
-	pmu {
-		compatible = "arm,cortex-a9-pmu";
-		interrupt-parent = <&combiner>;
-		interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
-	};
-
 	sysram@02020000 {
 		compatible = "mmio-sram";
 		reg = <0x02020000 0x40000>;
@@ -139,6 +133,13 @@
 
 	pmu_system_controller: system-controller@10020000 {
 		compatible = "samsung,exynos4212-pmu", "syscon";
+		clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+				"clkout4", "clkout8", "clkout9";
+		clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+			<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+			<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+			<&clock CLK_XUSBXTI>;
+		#clock-cells = <1>;
 	};
 
 	g2d@10800000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-cros-common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-cros-common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-cros-common.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-cros-common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -27,177 +27,18 @@
 		i2c2_bus: i2c2-bus {
 			samsung,pin-pud = <0>;
 		};
-
-		max77686_irq: max77686-irq {
-			samsung,pins = "gpx3-2";
-			samsung,pin-function = <0>;
-			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
-		};
 	};
 
 	i2c@12C60000 {
 		status = "okay";
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <378000>;
-
-		max77686@09 {
-			compatible = "maxim,max77686";
-			interrupt-parent = <&gpx3>;
-			interrupts = <2 0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&max77686_irq>;
-			wakeup-source;
-			reg = <0x09>;
-			#clock-cells = <1>;
-
-			voltage-regulators {
-				ldo1_reg: LDO1 {
-					regulator-name = "P1.0V_LDO_OUT1";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo2_reg: LDO2 {
-					regulator-name = "P1.8V_LDO_OUT2";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo3_reg: LDO3 {
-					regulator-name = "P1.8V_LDO_OUT3";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo7_reg: LDO7 {
-					regulator-name = "P1.1V_LDO_OUT7";
-					regulator-min-microvolt = <1100000>;
-					regulator-max-microvolt = <1100000>;
-					regulator-always-on;
-				};
-
-				ldo8_reg: LDO8 {
-					regulator-name = "P1.0V_LDO_OUT8";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo10_reg: LDO10 {
-					regulator-name = "P1.8V_LDO_OUT10";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo12_reg: LDO12 {
-					regulator-name = "P3.0V_LDO_OUT12";
-					regulator-min-microvolt = <3000000>;
-					regulator-max-microvolt = <3000000>;
-					regulator-always-on;
-				};
-
-				ldo14_reg: LDO14 {
-					regulator-name = "P1.8V_LDO_OUT14";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				ldo15_reg: LDO15 {
-					regulator-name = "P1.0V_LDO_OUT15";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
-					regulator-always-on;
-				};
-
-				ldo16_reg: LDO16 {
-					regulator-name = "P1.8V_LDO_OUT16";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-				};
-
-				buck1_reg: BUCK1 {
-					regulator-name = "vdd_mif";
-					regulator-min-microvolt = <950000>;
-					regulator-max-microvolt = <1300000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck2_reg: BUCK2 {
-					regulator-name = "vdd_arm";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck3_reg: BUCK3 {
-					regulator-name = "vdd_int";
-					regulator-min-microvolt = <900000>;
-					regulator-max-microvolt = <1200000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck4_reg: BUCK4 {
-					regulator-name = "vdd_g3d";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1300000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck5_reg: BUCK5 {
-					regulator-name = "P1.8V_BUCK_OUT5";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				buck6_reg: BUCK6 {
-					regulator-name = "P1.35V_BUCK_OUT6";
-					regulator-min-microvolt = <1350000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-always-on;
-				};
-
-				buck7_reg: BUCK7 {
-					regulator-name = "P2.0V_BUCK_OUT7";
-					regulator-min-microvolt = <2000000>;
-					regulator-max-microvolt = <2000000>;
-					regulator-always-on;
-				};
-
-				buck8_reg: BUCK8 {
-					regulator-name = "P2.85V_BUCK_OUT8";
-					regulator-min-microvolt = <2850000>;
-					regulator-max-microvolt = <2850000>;
-					regulator-always-on;
-				};
-			};
-		};
 	};
 
 	i2c@12C70000 {
 		status = "okay";
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <378000>;
-
-		trackpad {
-			reg = <0x67>;
-			compatible = "cypress,cyapa";
-			interrupts = <2 0>;
-			interrupt-parent = <&gpx1>;
-			wakeup-source;
-		};
 	};
 
 	i2c@12C80000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -191,6 +191,9 @@
 	pmu_system_controller: system-controller@10040000 {
 		compatible = "samsung,exynos5250-pmu", "syscon";
 		reg = <0x10040000 0x5000>;
+		clock-names = "clkout16";
+		clocks = <&clock CLK_FIN_PLL>;
+		#clock-cells = <1>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,8 @@
 		max77686@09 {
 			compatible = "maxim,max77686";
 			reg = <0x09>;
+			interrupt-parent = <&gpx3>;
+			interrupts = <2 0>;
 
 			voltage-regulators {
 				ldo1_reg: LDO1 {
@@ -316,6 +318,7 @@
 	};
 
 	spi_1: spi@12d30000 {
+		cs-gpios = <&gpa2 5 0>;
 		status = "okay";
 
 		w25q80bw@0 {
@@ -326,7 +329,6 @@
 			spi-max-frequency = <1000000>;
 
 			controller-data {
-				cs-gpio = <&gpa2 5 0>;
 				samsung,spi-feedback-delay = <0>;
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-snow.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-snow.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5250-snow.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5250-snow.dts	2014-09-28 17:29:07.000000000 -0400
@@ -137,7 +137,7 @@
 				sbs,poll-retry-count = <1>;
 			};
 
-			ec: embedded-controller {
+			cros_ec: embedded-controller {
 				compatible = "google,cros-ec-i2c";
 				reg = <0x1e>;
 				interrupts = <6 0>;
@@ -145,95 +145,6 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&ec_irq>;
 				wakeup-source;
-
-				keyboard-controller {
-				        compatible = "google,cros-ec-keyb";
-				        keypad,num-rows = <8>;
-				        keypad,num-columns = <13>;
-				        google,needs-ghost-filter;
-					linux,keymap = <0x0001007d	/* L_META */
-							0x0002003b	/* F1 */
-							0x00030030	/* B */
-							0x00040044	/* F10 */
-							0x00060031	/* N */
-							0x0008000d	/* = */
-							0x000a0064	/* R_ALT */
-
-							0x01010001	/* ESC */
-							0x0102003e	/* F4 */
-							0x01030022	/* G */
-							0x01040041	/* F7 */
-							0x01060023	/* H */
-							0x01080028	/* ' */
-							0x01090043	/* F9 */
-							0x010b000e	/* BKSPACE */
-
-							0x0200001d	/* L_CTRL */
-							0x0201000f	/* TAB */
-							0x0202003d	/* F3 */
-							0x02030014	/* T */
-							0x02040040	/* F6 */
-							0x0205001b	/* ] */
-							0x02060015	/* Y */
-							0x02070056	/* 102ND */
-							0x0208001a	/* [ */
-							0x02090042	/* F8 */
-
-							0x03010029	/* GRAVE */
-							0x0302003c	/* F2 */
-							0x03030006	/* 5 */
-							0x0304003f	/* F5 */
-							0x03060007	/* 6 */
-							0x0308000c	/* - */
-							0x030b002b	/* \ */
-
-							0x04000061	/* R_CTRL */
-							0x0401001e	/* A */
-							0x04020020	/* D */
-							0x04030021	/* F */
-							0x0404001f	/* S */
-							0x04050025	/* K */
-							0x04060024	/* J */
-							0x04080027	/* ; */
-							0x04090026	/* L */
-							0x040a002b	/* \ */
-							0x040b001c	/* ENTER */
-
-							0x0501002c	/* Z */
-							0x0502002e	/* C */
-							0x0503002f	/* V */
-							0x0504002d	/* X */
-							0x05050033	/* , */
-							0x05060032	/* M */
-							0x0507002a	/* L_SHIFT */
-							0x05080035	/* / */
-							0x05090034	/* . */
-							0x050B0039	/* SPACE */
-
-							0x06010002	/* 1 */
-							0x06020004	/* 3 */
-							0x06030005	/* 4 */
-							0x06040003	/* 2 */
-							0x06050009	/* 8 */
-							0x06060008	/* 7 */
-							0x0608000b	/* 0 */
-							0x0609000a	/* 9 */
-							0x060a0038	/* L_ALT */
-							0x060b006c	/* DOWN */
-							0x060c006a	/* RIGHT */
-
-							0x07010010	/* Q */
-							0x07020012	/* E */
-							0x07030013	/* R */
-							0x07040011	/* W */
-							0x07050017	/* I */
-							0x07060016	/* U */
-							0x07070036	/* R_SHIFT */
-							0x07080019	/* P */
-							0x07090018	/* O */
-							0x070b0067	/* UP */
-							0x070c0069>;	/* LEFT */
-				};
 			};
 
 			power-regulator {
@@ -351,6 +262,7 @@
 	sound {
 		compatible = "google,snow-audio-max98095";
 
+		samsung,model = "Snow-I2S-MAX98095";
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&max98095>;
 	};
@@ -431,3 +343,170 @@
 		};
 	};
 };
+
+&i2c_0 {
+	max77686@09 {
+		compatible = "maxim,max77686";
+		interrupt-parent = <&gpx3>;
+		interrupts = <2 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&max77686_irq>;
+		wakeup-source;
+		reg = <0x09>;
+		#clock-cells = <1>;
+
+		voltage-regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "P1.0V_LDO_OUT1";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "P1.8V_LDO_OUT2";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "P1.8V_LDO_OUT3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo7_reg: LDO7 {
+				regulator-name = "P1.1V_LDO_OUT7";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+			};
+
+			ldo8_reg: LDO8 {
+				regulator-name = "P1.0V_LDO_OUT8";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo10_reg: LDO10 {
+				regulator-name = "P1.8V_LDO_OUT10";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo12_reg: LDO12 {
+				regulator-name = "P3.0V_LDO_OUT12";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			ldo14_reg: LDO14 {
+				regulator-name = "P1.8V_LDO_OUT14";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo15_reg: LDO15 {
+				regulator-name = "P1.0V_LDO_OUT15";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo16_reg: LDO16 {
+				regulator-name = "P1.8V_LDO_OUT16";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "vdd_mif";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck3_reg: BUCK3 {
+				regulator-name = "vdd_int";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "vdd_g3d";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "P1.8V_BUCK_OUT5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck6_reg: BUCK6 {
+				regulator-name = "P1.35V_BUCK_OUT6";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			buck7_reg: BUCK7 {
+				regulator-name = "P2.0V_BUCK_OUT7";
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+			};
+
+			buck8_reg: BUCK8 {
+				regulator-name = "P2.85V_BUCK_OUT8";
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <2850000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c_1 {
+	trackpad {
+		reg = <0x67>;
+		compatible = "cypress,cyapa";
+		interrupts = <2 0>;
+		interrupt-parent = <&gpx1>;
+		wakeup-source;
+	};
+};
+
+&pinctrl_0 {
+	max77686_irq: max77686-irq {
+		samsung,pins = "gpx3-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+#include "cros-ec-keyboard.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5260.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5260.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5260.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5260.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,10 @@
 		pinctrl0 = &pinctrl_0;
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
 	};
 
 	cpus {
@@ -227,6 +231,11 @@
 			interrupts = <0 243 0>;
 		};
 
+		pmu_system_controller: system-controller@10D50000 {
+			compatible = "samsung,exynos5260-pmu", "syscon";
+			reg = <0x10D50000 0x10000>;
+		};
+
 		uart0: serial@12C00000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C00000 0x100>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5410.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5410.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5410.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5410.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,12 @@
 	compatible = "samsung,exynos5410", "samsung,exynos5";
 	interrupt-parent = <&gic>;
 
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -28,24 +34,28 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			clock-frequency = <1600000000>;
 		};
 
 		CPU1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
+			clock-frequency = <1600000000>;
 		};
 
 		CPU2: cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
+			clock-frequency = <1600000000>;
 		};
 
 		CPU3: cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
+			clock-frequency = <1600000000>;
 		};
 	};
 
@@ -87,6 +97,11 @@
 			reg = <0x10000000 0x100>;
 		};
 
+		pmu_system_controller: system-controller@10040000 {
+			compatible = "samsung,exynos5410-pmu", "syscon";
+			reg = <0x10040000 0x5000>;
+		};
+
 		mct: mct@101C0000 {
 			compatible = "samsung,exynos4210-mct";
 			reg = <0x101C0000 0xB00>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5420.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5420.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5420.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5420.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -265,11 +265,6 @@
 		clock-names = "oscclk", "pclk0", "clk0";
 	};
 
-	disp_pd: power-domain@100440C0 {
-		compatible = "samsung,exynos4210-pd";
-		reg = <0x100440C0 0x20>;
-	};
-
 	msc_pd: power-domain@10044120 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10044120 0x20>;
@@ -520,8 +515,26 @@
 		phy-names = "dp";
 	};
 
+	mipi_phy: video-phy@10040714 {
+		compatible = "samsung,s5pv210-mipi-video-phy";
+		reg = <0x10040714 12>;
+		#phy-cells = <1>;
+	};
+
+	dsi@14500000 {
+		compatible = "samsung,exynos5410-mipi-dsi";
+		reg = <0x14500000 0x10000>;
+		interrupts = <0 82 0>;
+		phys = <&mipi_phy 1>;
+		phy-names = "dsim";
+		clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
+		clock-names = "bus_clk", "pll_clk";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	fimd: fimd@14400000 {
-		samsung,power-domain = <&disp_pd>;
 		clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
 		clock-names = "sclk_fimd", "fimd";
 	};
@@ -727,6 +740,9 @@
 	pmu_system_controller: system-controller@10040000 {
 		compatible = "samsung,exynos5420-pmu", "syscon";
 		reg = <0x10040000 0x5000>;
+		clock-names = "clkout16";
+		clocks = <&clock CLK_FIN_PLL>;
+		#clock-cells = <1>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2014-09-28 17:29:07.000000000 -0400
@@ -25,8 +25,18 @@
 		"google,pit", "google,peach","samsung,exynos5420",
 		"samsung,exynos5";
 
-	memory {
-		reg = <0x20000000 0x80000000>;
+	aliases {
+		/* Assign 20 so we don't get confused w/ builtin ones */
+		i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 1000000 0>;
+		brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
+		default-brightness-level = <7>;
+		pinctrl-0 = <&pwm0_out>;
+		pinctrl-names = "default";
 	};
 
 	fixed-rate-clocks {
@@ -50,18 +60,14 @@
 		};
 	};
 
-	backlight {
-		compatible = "pwm-backlight";
-		pwms = <&pwm 0 1000000 0>;
-		brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
-		default-brightness-level = <7>;
-		pinctrl-0 = <&pwm0_out>;
-		pinctrl-names = "default";
+	memory {
+		reg = <0x20000000 0x80000000>;
 	};
 
 	sound {
 		compatible = "google,snow-audio-max98090";
 
+		samsung,model = "Peach-Pit-I2S-MAX98090";
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&max98090>;
 	};
@@ -87,66 +93,92 @@
 		pinctrl-0 = <&usb301_vbus_en>;
 		enable-active-high;
 	};
-};
 
-&pinctrl_0 {
-	max98090_irq: max98090-irq {
-		samsung,pins = "gpx0-2";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+	vbat: fixed-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat-supply";
+		regulator-boot-on;
+		regulator-always-on;
 	};
+};
 
-	tpm_irq: tpm-irq {
-		samsung,pins = "gpx1-0";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
-	};
+&dp {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp_hpd_gpio>;
+	samsung,color-space = <0>;
+	samsung,dynamic-range = <0>;
+	samsung,ycbcr-coeff = <0>;
+	samsung,color-depth = <1>;
+	samsung,link-rate = <0x06>;
+	samsung,lane-count = <2>;
+	samsung,hpd-gpio = <&gpx2 6 0>;
 
-	power_key_irq: power-key-irq {
-		samsung,pins = "gpx1-2";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
-	};
+	display-timings {
+		native-mode = <&timing1>;
 
-	hdmi_hpd_irq: hdmi-hpd-irq {
-		samsung,pins = "gpx3-7";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <1>;
-		samsung,pin-drv = <0>;
+		timing1: timing@1 {
+			clock-frequency = <70589280>;
+			hactive = <1366>;
+			vactive = <768>;
+			hfront-porch = <40>;
+			hback-porch = <40>;
+			hsync-len = <32>;
+			vback-porch = <10>;
+			vfront-porch = <12>;
+			vsync-len = <6>;
+		};
 	};
+};
 
-	dp_hpd_gpio: dp_hpd_gpio {
-		samsung,pins = "gpx2-6";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <3>;
-		samsung,pin-drv = <0>;
-	};
+&fimd {
+	status = "okay";
+	samsung,invert-vclk;
 };
 
-&pinctrl_3 {
-	usb300_vbus_en: usb300-vbus-en {
-		samsung,pins = "gph0-0";
-		samsung,pin-function = <1>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+&hdmi {
+	status = "okay";
+	hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_hpd_irq>;
+	ddc = <&i2c_2>;
+};
+
+&hsi2c_7 {
+	status = "okay";
+
+	max98090: codec@10 {
+		compatible = "maxim,max98090";
+		reg = <0x10>;
+		interrupts = <2 0>;
+		interrupt-parent = <&gpx0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&max98090_irq>;
 	};
+};
 
-	usb301_vbus_en: usb301-vbus-en {
-		samsung,pins = "gph0-1";
-		samsung,pin-function = <1>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+&hsi2c_9 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tpm@20 {
+		compatible = "infineon,slb9645tt";
+		reg = <0x20>;
+
+		/* Unused irq; but still need to configure the pins */
+		pinctrl-names = "default";
+		pinctrl-0 = <&tpm_irq>;
 	};
 };
 
-&rtc {
+&i2c_2 {
 	status = "okay";
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <66000>;
+	samsung,i2c-slave-addr = <0x50>;
 };
 
-&uart_3 {
+&i2s0 {
 	status = "okay";
 };
 
@@ -189,46 +221,210 @@
 	};
 };
 
-&hsi2c_7 {
-	status = "okay";
 
-	max98090: codec@10 {
-		compatible = "maxim,max98090";
-		reg = <0x10>;
-		interrupts = <2 0>;
-		interrupt-parent = <&gpx0>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&max98090_irq>;
+&pinctrl_0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mask_tpm_reset>;
+
+	max98090_irq: max98090-irq {
+		samsung,pins = "gpx0-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	/* We need GPX0_6 to be low at sleep time; just keep it low always */
+	mask_tpm_reset: mask-tpm-reset {
+		samsung,pins = "gpx0-6";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+		samsung,pin-val = <0>;
+	};
+
+	tpm_irq: tpm-irq {
+		samsung,pins = "gpx1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	power_key_irq: power-key-irq {
+		samsung,pins = "gpx1-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	ec_irq: ec-irq {
+		samsung,pins = "gpx1-5";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	tps65090_irq: tps65090-irq {
+		samsung,pins = "gpx2-5";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	dp_hpd_gpio: dp_hpd_gpio {
+		samsung,pins = "gpx2-6";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hdmi_hpd_irq: hdmi-hpd-irq {
+		samsung,pins = "gpx3-7";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
 	};
 };
 
-&hsi2c_9 {
-	status = "okay";
-	clock-frequency = <400000>;
+&pinctrl_3 {
+	/* Drive SPI lines at x2 for better integrity */
+	spi2-bus {
+		samsung,pin-drv = <2>;
+	};
 
-	tpm@20 {
-		compatible = "infineon,slb9645tt";
-		reg = <0x20>;
+	/* Drive SPI chip select at x2 for better integrity */
+	ec_spi_cs: ec-spi-cs {
+		samsung,pins = "gpb1-2";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <2>;
+	};
 
-		/* Unused irq; but still need to configure the pins */
-		pinctrl-names = "default";
-		pinctrl-0 = <&tpm_irq>;
+	usb300_vbus_en: usb300-vbus-en {
+		samsung,pins = "gph0-0";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	usb301_vbus_en: usb301-vbus-en {
+		samsung,pins = "gph0-1";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
 	};
 };
 
-&i2c_2	{
+&rtc {
 	status = "okay";
-	samsung,i2c-sda-delay = <100>;
-	samsung,i2c-max-bus-freq = <66000>;
-	samsung,i2c-slave-addr = <0x50>;
 };
 
-&hdmi {
+&spi_2 {
+	status = "okay";
+	num-cs = <1>;
+	samsung,spi-src-clk = <0>;
+	cs-gpios = <&gpb1 2 0>;
+
+	cros_ec: cros-ec@0 {
+		compatible = "google,cros-ec-spi";
+		interrupt-parent = <&gpx1>;
+		interrupts = <5 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ec_spi_cs &ec_irq>;
+		reg = <0>;
+		spi-max-frequency = <3125000>;
+
+		controller-data {
+			samsung,spi-feedback-delay = <1>;
+		};
+
+		i2c-tunnel {
+			compatible = "google,cros-ec-i2c-tunnel";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			google,remote-bus = <0>;
+
+			battery: sbs-battery@b {
+				compatible = "sbs,sbs-battery";
+				reg = <0xb>;
+				sbs,poll-retry-count = <1>;
+				sbs,i2c-retry-count = <2>;
+			};
+
+			power-regulator@48 {
+				compatible = "ti,tps65090";
+				reg = <0x48>;
+
+				/*
+				 * Config irq to disable internal pulls
+				 * even though we run in polling mode.
+				 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&tps65090_irq>;
+
+				vsys1-supply = <&vbat>;
+				vsys2-supply = <&vbat>;
+				vsys3-supply = <&vbat>;
+				infet1-supply = <&vbat>;
+				infet2-supply = <&vbat>;
+				infet3-supply = <&vbat>;
+				infet4-supply = <&vbat>;
+				infet5-supply = <&vbat>;
+				infet6-supply = <&vbat>;
+				infet7-supply = <&vbat>;
+				vsys-l1-supply = <&vbat>;
+				vsys-l2-supply = <&vbat>;
+
+				regulators {
+					tps65090_dcdc1: dcdc1 {
+						ti,enable-ext-control;
+					};
+					tps65090_dcdc2: dcdc2 {
+						ti,enable-ext-control;
+					};
+					tps65090_dcdc3: dcdc3 {
+						ti,enable-ext-control;
+					};
+					tps65090_fet1: fet1 {
+						regulator-name = "vcd_led";
+					};
+					tps65090_fet2: fet2 {
+						regulator-name = "video_mid";
+						regulator-always-on;
+					};
+					tps65090_fet3: fet3 {
+						regulator-name = "wwan_r";
+						regulator-always-on;
+					};
+					tps65090_fet4: fet4 {
+						regulator-name = "sdcard";
+						regulator-always-on;
+					};
+					tps65090_fet5: fet5 {
+						regulator-name = "camout";
+					};
+					tps65090_fet6: fet6 {
+						regulator-name = "lcd_vdd";
+					};
+					tps65090_fet7: fet7 {
+						regulator-name = "video_mid_1a";
+						regulator-always-on;
+					};
+					tps65090_ldo1: ldo1 {
+					};
+					tps65090_ldo2: ldo2 {
+					};
+				};
+
+				charger {
+					compatible = "ti,tps65090-charger";
+				};
+			};
+		};
+	};
+};
+
+&uart_3 {
 	status = "okay";
-	hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&hdmi_hpd_irq>;
-	ddc = <&i2c_2>;
 };
 
 &usbdrd_phy0 {
@@ -248,40 +444,4 @@
 	timeout-sec = <32>;
 };
 
-&i2s0 {
-	status = "okay";
-};
-
-&fimd {
-	status = "okay";
-	samsung,invert-vclk;
-};
-
-&dp {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&dp_hpd_gpio>;
-	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
-	samsung,color-depth = <1>;
-	samsung,link-rate = <0x06>;
-	samsung,lane-count = <2>;
-	samsung,hpd-gpio = <&gpx2 6 0>;
-
-	display-timings {
-		native-mode = <&timing1>;
-
-		timing1: timing@1 {
-			clock-frequency = <70589280>;
-			hactive = <1366>;
-			vactive = <768>;
-			hfront-porch = <40>;
-			hback-porch = <40>;
-			hsync-len = <32>;
-			vback-porch = <10>;
-			vfront-porch = <12>;
-			vsync-len = <6>;
-		};
-	};
-};
+#include "cros-ec-keyboard.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5440.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5440.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5440.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5440.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,8 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		serial0 = &serial_0;
+		serial1 = &serial_1;
 		spi0 = &spi_0;
 		tmuctrl0 = &tmuctrl_0;
 		tmuctrl1 = &tmuctrl_1;
@@ -102,7 +104,7 @@
 		>;
 	};
 
-	serial@B0000 {
+	serial_0: serial@B0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xB0000 0x1000>;
 		interrupts = <0 2 0>;
@@ -110,7 +112,7 @@
 		clock-names = "uart", "clk_uart_baud0";
 	};
 
-	serial@C0000 {
+	serial_1: serial@C0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xC0000 0x1000>;
 		interrupts = <0 3 0>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,18 @@
 		"google,pi", "google,peach", "samsung,exynos5800",
 		"samsung,exynos5";
 
-	memory {
-		reg = <0x20000000 0x80000000>;
+	aliases {
+		/* Assign 20 so we don't get confused w/ builtin ones */
+		i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 1000000 0>;
+		brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
+		default-brightness-level = <7>;
+		pinctrl-0 = <&pwm0_out>;
+		pinctrl-names = "default";
 	};
 
 	fixed-rate-clocks {
@@ -48,13 +58,16 @@
 		};
 	};
 
-	backlight {
-		compatible = "pwm-backlight";
-		pwms = <&pwm 0 1000000 0>;
-		brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
-		default-brightness-level = <7>;
-		pinctrl-0 = <&pwm0_out>;
-		pinctrl-names = "default";
+	memory {
+		reg = <0x20000000 0x80000000>;
+	};
+
+	sound {
+		compatible = "google,snow-audio-max98091";
+
+		samsung,model = "Peach-Pi-I2S-MAX98091";
+		samsung,i2s-controller = <&i2s0>;
+		samsung,audio-codec = <&max98091>;
 	};
 
 	usb300_vbus_reg: regulator-usb300 {
@@ -78,59 +91,92 @@
 		pinctrl-0 = <&usb301_vbus_en>;
 		enable-active-high;
 	};
-};
 
-&pinctrl_0 {
-	tpm_irq: tpm-irq {
-		samsung,pins = "gpx1-0";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+	vbat: fixed-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat-supply";
+		regulator-boot-on;
+		regulator-always-on;
 	};
+};
 
-	power_key_irq: power-key-irq {
-		samsung,pins = "gpx1-2";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
-	};
+&dp {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp_hpd_gpio>;
+	samsung,color-space = <0>;
+	samsung,dynamic-range = <0>;
+	samsung,ycbcr-coeff = <0>;
+	samsung,color-depth = <1>;
+	samsung,link-rate = <0x0a>;
+	samsung,lane-count = <2>;
+	samsung,hpd-gpio = <&gpx2 6 0>;
 
-	dp_hpd_gpio: dp_hpd_gpio {
-		samsung,pins = "gpx2-6";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <3>;
-		samsung,pin-drv = <0>;
-	};
+	display-timings {
+		native-mode = <&timing1>;
 
-	hdmi_hpd_irq: hdmi-hpd-irq {
-		samsung,pins = "gpx3-7";
-		samsung,pin-function = <0>;
-		samsung,pin-pud = <1>;
-		samsung,pin-drv = <0>;
+		timing1: timing@1 {
+			clock-frequency = <150660000>;
+			hactive = <1920>;
+			vactive = <1080>;
+			hfront-porch = <60>;
+			hback-porch = <172>;
+			hsync-len = <80>;
+			vback-porch = <25>;
+			vfront-porch = <10>;
+			vsync-len = <10>;
+		};
 	};
 };
 
-&pinctrl_3 {
-	usb300_vbus_en: usb300-vbus-en {
-		samsung,pins = "gph0-0";
-		samsung,pin-function = <1>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+&fimd {
+	status = "okay";
+	samsung,invert-vclk;
+};
+
+&hdmi {
+	status = "okay";
+	hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_hpd_irq>;
+	ddc = <&i2c_2>;
+};
+
+&hsi2c_7 {
+	status = "okay";
+
+	max98091: codec@10 {
+		compatible = "maxim,max98091";
+		reg = <0x10>;
+		interrupts = <2 0>;
+		interrupt-parent = <&gpx0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&max98091_irq>;
 	};
+};
 
-	usb301_vbus_en: usb301-vbus-en {
-		samsung,pins = "gph0-1";
-		samsung,pin-function = <1>;
-		samsung,pin-pud = <0>;
-		samsung,pin-drv = <0>;
+&hsi2c_9 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tpm@20 {
+		compatible = "infineon,slb9645tt";
+		reg = <0x20>;
+
+		/* Unused irq; but still need to configure the pins */
+		pinctrl-names = "default";
+		pinctrl-0 = <&tpm_irq>;
 	};
 };
 
-&rtc {
+&i2c_2 {
 	status = "okay";
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <66000>;
+	samsung,i2c-slave-addr = <0x50>;
 };
 
-&uart_3 {
+&i2s0 {
 	status = "okay";
 };
 
@@ -173,66 +219,210 @@
 	};
 };
 
-&dp {
-	status = "okay";
+
+&pinctrl_0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&dp_hpd_gpio>;
-	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
-	samsung,color-depth = <1>;
-	samsung,link-rate = <0x0a>;
-	samsung,lane-count = <2>;
-	samsung,hpd-gpio = <&gpx2 6 0>;
+	pinctrl-0 = <&mask_tpm_reset>;
 
-	display-timings {
-		native-mode = <&timing1>;
+	max98091_irq: max98091-irq {
+		samsung,pins = "gpx0-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
 
-		timing1: timing@1 {
-			clock-frequency = <150660000>;
-			hactive = <1920>;
-			vactive = <1080>;
-			hfront-porch = <60>;
-			hback-porch = <172>;
-			hsync-len = <80>;
-			vback-porch = <25>;
-			vfront-porch = <10>;
-			vsync-len = <10>;
-		};
+	/* We need GPX0_6 to be low at sleep time; just keep it low always */
+	mask_tpm_reset: mask-tpm-reset {
+		samsung,pins = "gpx0-6";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+		samsung,pin-val = <0>;
+	};
+
+	tpm_irq: tpm-irq {
+		samsung,pins = "gpx1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	power_key_irq: power-key-irq {
+		samsung,pins = "gpx1-2";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	ec_irq: ec-irq {
+		samsung,pins = "gpx1-5";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	tps65090_irq: tps65090-irq {
+		samsung,pins = "gpx2-5";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	dp_hpd_gpio: dp_hpd_gpio {
+		samsung,pins = "gpx2-6";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hdmi_hpd_irq: hdmi-hpd-irq {
+		samsung,pins = "gpx3-7";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
 	};
 };
 
-&fimd {
+&pinctrl_3 {
+	/* Drive SPI lines at x2 for better integrity */
+	spi2-bus {
+		samsung,pin-drv = <2>;
+	};
+
+	/* Drive SPI chip select at x2 for better integrity */
+	ec_spi_cs: ec-spi-cs {
+		samsung,pins = "gpb1-2";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <2>;
+	};
+
+	usb300_vbus_en: usb300-vbus-en {
+		samsung,pins = "gph0-0";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	usb301_vbus_en: usb301-vbus-en {
+		samsung,pins = "gph0-1";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&rtc {
 	status = "okay";
-	samsung,invert-vclk;
 };
 
-&hsi2c_9 {
+&spi_2 {
 	status = "okay";
-	clock-frequency = <400000>;
+	num-cs = <1>;
+	samsung,spi-src-clk = <0>;
+	cs-gpios = <&gpb1 2 0>;
 
-	tpm@20 {
-		compatible = "infineon,slb9645tt";
-		reg = <0x20>;
-		/* Unused irq; but still need to configure the pins */
+	cros_ec: cros-ec@0 {
+		compatible = "google,cros-ec-spi";
+		interrupt-parent = <&gpx1>;
+		interrupts = <5 0>;
 		pinctrl-names = "default";
-		pinctrl-0 = <&tpm_irq>;
-	};
-};
+		pinctrl-0 = <&ec_spi_cs &ec_irq>;
+		reg = <0>;
+		spi-max-frequency = <3125000>;
 
-&i2c_2 {
-	status = "okay";
-	samsung,i2c-sda-delay = <100>;
-	samsung,i2c-max-bus-freq = <66000>;
-	samsung,i2c-slave-addr = <0x50>;
+		controller-data {
+			samsung,spi-feedback-delay = <1>;
+		};
+
+		i2c-tunnel {
+			compatible = "google,cros-ec-i2c-tunnel";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			google,remote-bus = <0>;
+
+			battery: sbs-battery@b {
+				compatible = "sbs,sbs-battery";
+				reg = <0xb>;
+				sbs,poll-retry-count = <1>;
+				sbs,i2c-retry-count = <2>;
+			};
+
+			power-regulator@48 {
+				compatible = "ti,tps65090";
+				reg = <0x48>;
+
+				/*
+				 * Config irq to disable internal pulls
+				 * even though we run in polling mode.
+				 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&tps65090_irq>;
+
+				vsys1-supply = <&vbat>;
+				vsys2-supply = <&vbat>;
+				vsys3-supply = <&vbat>;
+				infet1-supply = <&vbat>;
+				infet2-supply = <&vbat>;
+				infet3-supply = <&vbat>;
+				infet4-supply = <&vbat>;
+				infet5-supply = <&vbat>;
+				infet6-supply = <&vbat>;
+				infet7-supply = <&vbat>;
+				vsys-l1-supply = <&vbat>;
+				vsys-l2-supply = <&vbat>;
+
+				regulators {
+					tps65090_dcdc1: dcdc1 {
+						ti,enable-ext-control;
+					};
+					tps65090_dcdc2: dcdc2 {
+						ti,enable-ext-control;
+					};
+					tps65090_dcdc3: dcdc3 {
+						ti,enable-ext-control;
+					};
+					tps65090_fet1: fet1 {
+						regulator-name = "vcd_led";
+					};
+					tps65090_fet2: fet2 {
+						regulator-name = "video_mid";
+						regulator-always-on;
+					};
+					tps65090_fet3: fet3 {
+						regulator-name = "wwan_r";
+						regulator-always-on;
+					};
+					tps65090_fet4: fet4 {
+						regulator-name = "sdcard";
+						regulator-always-on;
+					};
+					tps65090_fet5: fet5 {
+						regulator-name = "camout";
+					};
+					tps65090_fet6: fet6 {
+						regulator-name = "lcd_vdd";
+					};
+					tps65090_fet7: fet7 {
+						regulator-name = "video_mid_1a";
+						regulator-always-on;
+					};
+					tps65090_ldo1: ldo1 {
+					};
+					tps65090_ldo2: ldo2 {
+					};
+				};
+
+				charger {
+					compatible = "ti,tps65090-charger";
+				};
+			};
+		};
+	};
 };
 
-&hdmi {
+&uart_3 {
 	status = "okay";
-	hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&hdmi_hpd_irq>;
-	ddc = <&i2c_2>;
 };
 
 &usbdrd_phy0 {
@@ -251,3 +441,5 @@
 &watchdog {
 	timeout-sec = <32>;
 };
+
+#include "cros-ec-keyboard.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/exynos5.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/exynos5.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,13 @@
 / {
 	interrupt-parent = <&gic>;
 
+	aliases {
+		serial0 = &serial_0;
+		serial1 = &serial_1;
+		serial2 = &serial_2;
+		serial3 = &serial_3;
+	};
+
 	chipid@10000000 {
 		compatible = "samsung,exynos4210-chipid";
 		reg = <0x10000000 0x100>;
@@ -50,25 +57,25 @@
 		interrupts = <1 9 0xf04>;
 	};
 
-	serial@12C00000 {
+	serial_0: serial@12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
 		interrupts = <0 51 0>;
 	};
 
-	serial@12C10000 {
+	serial_1: serial@12C10000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C10000 0x100>;
 		interrupts = <0 52 0>;
 	};
 
-	serial@12C20000 {
+	serial_2: serial@12C20000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C20000 0x100>;
 		interrupts = <0 53 0>;
 	};
 
-	serial@12C30000 {
+	serial_3: serial@12C30000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C30000 0x100>;
 		interrupts = <0 54 0>;
@@ -87,6 +94,7 @@
 		reg = <0x14400000 0x40000>;
 		interrupt-names = "fifo", "vsync", "lcd_sys";
 		interrupts = <18 4>, <18 5>, <18 6>;
+		samsung,sysreg = <&sysreg_system_controller>;
 		status = "disabled";
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ge863-pro3.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ge863-pro3.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ge863-pro3.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ge863-pro3.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,10 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <6000000>;
 		};
+
+		main_xtal {
+			clock-frequency = <6000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/hi3620.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hi3620.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/hi3620.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hi3620.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
+		enable-method = "hisilicon,hi3620-smp";
 
 		cpu@0 {
 			device_type = "cpu";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/hisi-x5hd2-dkb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hisi-x5hd2-dkb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/hisi-x5hd2-dkb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hisi-x5hd2-dkb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013-2014 Linaro Ltd.
+ * Copyright (c) 2013-2014 Hisilicon 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.
+ */
+
+/dts-v1/;
+#include "hisi-x5hd2.dtsi"
+
+/ {
+	model = "Hisilicon HIX5HD2 Development Board";
+	compatible = "hisilicon,hix5hd2";
+
+	chosen {
+		bootargs = "console=ttyAMA0,115200 earlyprintk";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "hisilicon,hix5hd2-smp";
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&l2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&l2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>;
+	};
+};
+
+&timer0 {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013-2014 Linaro Ltd.
+ * Copyright (c) 2013-2014 Hisilicon 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.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/hix5hd2-clock.h>
+
+/ {
+	aliases {
+		serial0 = &uart0;
+	};
+
+	gic: interrupt-controller@f8a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		/* gic dist base, gic cpu base */
+		reg = <0xf8a01000 0x1000>, <0xf8a00100 0x100>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges = <0 0xf8000000 0x8000000>;
+
+		amba {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "arm,amba-bus";
+			ranges;
+
+			timer0: timer@00002000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x00002000 0x1000>;
+				/* timer00 & timer01 */
+				interrupts = <0 24 4>;
+				clocks = <&clock HIX5HD2_FIXED_24M>;
+				status = "disabled";
+			};
+
+			timer1: timer@00a29000 {
+				/*
+				 * Only used in NORMAL state, not available ins
+				 * SLOW or DOZE state.
+				 * The rate is fixed in 24MHz.
+				 */
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x00a29000 0x1000>;
+				/* timer10 & timer11 */
+				interrupts = <0 25 4>;
+				clocks = <&clock HIX5HD2_FIXED_24M>;
+				status = "disabled";
+			};
+
+			timer2: timer@00a2a000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x00a2a000 0x1000>;
+				/* timer20 & timer21 */
+				interrupts = <0 26 4>;
+				clocks = <&clock HIX5HD2_FIXED_24M>;
+				status = "disabled";
+			};
+
+			timer3: timer@00a2b000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x00a2b000 0x1000>;
+				/* timer30 & timer31 */
+				interrupts = <0 27 4>;
+				clocks = <&clock HIX5HD2_FIXED_24M>;
+				status = "disabled";
+			};
+
+			timer4: timer@00a81000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x00a81000 0x1000>;
+				/* timer30 & timer31 */
+				interrupts = <0 28 4>;
+				clocks = <&clock HIX5HD2_FIXED_24M>;
+				status = "disabled";
+			};
+
+			uart0: uart@00b00000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x00b00000 0x1000>;
+				interrupts = <0 49 4>;
+				clocks = <&clock HIX5HD2_FIXED_83M>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart1: uart@00006000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x00006000 0x1000>;
+				interrupts = <0 50 4>;
+				clocks = <&clock HIX5HD2_FIXED_83M>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart2: uart@00b02000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x00b02000 0x1000>;
+				interrupts = <0 51 4>;
+				clocks = <&clock HIX5HD2_FIXED_83M>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart3: uart@00b03000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x00b03000 0x1000>;
+				interrupts = <0 52 4>;
+				clocks = <&clock HIX5HD2_FIXED_83M>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+
+			uart4: uart@00b04000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0xb04000 0x1000>;
+				interrupts = <0 53 4>;
+				clocks = <&clock HIX5HD2_FIXED_83M>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+		};
+
+		local_timer@00a00600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x00a00600 0x20>;
+			interrupts = <1 13 0xf01>;
+		};
+
+		l2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a10000 0x100000>;
+			interrupts = <0 15 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		sysctrl: system-controller@00000000 {
+			compatible = "hisilicon,sysctrl";
+			reg = <0x00000000 0x1000>;
+			reboot-offset = <0x4>;
+		};
+
+		cpuctrl@00a22000 {
+			compatible = "hisilicon,cpuctrl";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x00a22000 0x2000>;
+			ranges = <0 0x00a22000 0x2000>;
+
+			clock: clock@0 {
+				compatible = "hisilicon,hix5hd2-clock";
+				reg = <0 0x2000>;
+				#clock-cells = <1>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25.dtsi	2014-08-07 04:46:53.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25.dtsi	2014-09-28 21:27:29.000000000 -0400
@@ -312,7 +312,7 @@
 			gpt4: timer@53f84000 {
 				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
 				reg = <0x53f84000 0x4000>;
-				clocks = <&clks 9>, <&clks 45>;
+				clocks = <&clks 95>, <&clks 47>;
 				clock-names = "ipg", "per";
 				interrupts = <1>;
 			};
@@ -320,7 +320,7 @@
 			gpt3: timer@53f88000 {
 				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
 				reg = <0x53f88000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
+				clocks = <&clks 94>, <&clks 47>;
 				clock-names = "ipg", "per";
 				interrupts = <29>;
 			};
@@ -328,7 +328,7 @@
 			gpt2: timer@53f8c000 {
 				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
 				reg = <0x53f8c000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
+				clocks = <&clks 93>, <&clks 47>;
 				clock-names = "ipg", "per";
 				interrupts = <53>;
 			};
@@ -336,7 +336,7 @@
 			gpt1: timer@53f90000 {
 				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
 				reg = <0x53f90000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
+				clocks = <&clks 92>, <&clks 47>;
 				clock-names = "ipg", "per";
 				interrupts = <54>;
 			};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 EukrÃ©a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the CMO-QVGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-cmo-qvga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	cmo_qvga: display {
+		model = "CMO-QVGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xcad08b80>;
+		bus-width = <18>;
+		native-mode = <&qvga_timings>;
+		display-timings {
+			qvga_timings: 320x240 {
+				clock-frequency = <6500000>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <30>;
+				hfront-porch = <38>;
+				vback-porch = <20>;
+				vfront-porch = <3>;
+				hsync-len = <15>;
+				vsync-len = <4>;
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_lcd_3v3: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_reg_lcd_3v3>;
+			regulator-name = "lcd-3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+};
+
+&iomuxc {
+	imx25-eukrea-mbimxsd25-baseboard-cmo-qvga {
+		pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
+			fsl,pins = <MX25_PAD_PWM__GPIO_1_26 0x80000000>;
+		};
+	};
+};
+
+&lcdc {
+	display = <&cmo_qvga>;
+	fsl,lpccr = <0x00a903ff>;
+	lcd-supply = <&reg_lcd_3v3>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -155,7 +155,6 @@
 
 &ssi1 {
 	codec-handle = <&tlv320aic23>;
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 EukrÃ©a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the DVI-SVGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-dvi-svga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	dvi_svga: display {
+		model = "DVI-SVGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xfa208b80>;
+		bus-width = <18>;
+		native-mode = <&dvi_svga_timings>;
+		display-timings {
+			dvi_svga_timings: 800x600 {
+				clock-frequency = <40000000>;
+				hactive = <800>;
+				vactive = <600>;
+				hback-porch = <75>;
+				hfront-porch = <75>;
+				vback-porch = <7>;
+				vfront-porch = <75>;
+				hsync-len = <7>;
+				vsync-len = <7>;
+			};
+		};
+	};
+};
+
+&lcdc {
+	display = <&dvi_svga>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 EukrÃ©a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the DVI-VGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-dvi-vga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	dvi_vga: display {
+		model = "DVI-VGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xfa208b80>;
+		bus-width = <18>;
+		native-mode = <&dvi_vga_timings>;
+		display-timings {
+			dvi_vga_timings: 640x480 {
+				clock-frequency = <31250000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <100>;
+				hfront-porch = <100>;
+				vback-porch = <7>;
+				vfront-porch = <100>;
+				hsync-len = <7>;
+				vsync-len = <7>;
+			};
+		};
+	};
+};
+
+&lcdc {
+	display = <&dvi_vga>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-pdk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-pdk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx25-pdk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx25-pdk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -233,7 +233,6 @@
 
 &ssi1 {
 	codec-handle = <&codec>;
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
@@ -249,3 +248,10 @@
 	dr_mode = "host";
 	status = "okay";
 };
+
+&usbotg {
+	phy_type = "utmi";
+	dr_mode = "otg";
+	external-vbus-divider;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -11,9 +11,11 @@
 
 #include "skeleton.dtsi"
 #include "imx27-pinfunc.h"
+
+#include <dt-bindings/clock/imx27-clock.h>
+#include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/gpio/gpio.h>
 
 / {
 	aliases {
@@ -68,7 +70,7 @@
 				399000 1450000
 			>;
 			clock-latency = <62500>;
-			clocks = <&clks 18>;
+			clocks = <&clks IMX27_CLK_CPU_DIV>;
 			voltage-tolerance = <5>;
 		};
 	};
@@ -91,7 +93,8 @@
 				compatible = "fsl,imx27-dma";
 				reg = <0x10001000 0x1000>;
 				interrupts = <32>;
-				clocks = <&clks 50>, <&clks 70>;
+				clocks = <&clks IMX27_CLK_DMA_IPG_GATE>,
+					 <&clks IMX27_CLK_DMA_AHB_GATE>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <1>;
 				#dma-channels = <16>;
@@ -101,14 +104,15 @@
 				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
 				reg = <0x10002000 0x1000>;
 				interrupts = <27>;
-				clocks = <&clks 74>;
+				clocks = <&clks IMX27_CLK_WDOG_IPG_GATE>;
 			};
 
 			gpt1: timer@10003000 {
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x10003000 0x1000>;
 				interrupts = <26>;
-				clocks = <&clks 46>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT1_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -116,7 +120,8 @@
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x10004000 0x1000>;
 				interrupts = <25>;
-				clocks = <&clks 45>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT2_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -124,7 +129,8 @@
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x10005000 0x1000>;
 				interrupts = <24>;
-				clocks = <&clks 44>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT3_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -133,7 +139,8 @@
 				compatible = "fsl,imx27-pwm";
 				reg = <0x10006000 0x1000>;
 				interrupts = <23>;
-				clocks = <&clks 34>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_PWM_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -141,14 +148,14 @@
 				compatible = "fsl,imx27-kpp", "fsl,imx21-kpp";
 				reg = <0x10008000 0x1000>;
 				interrupts = <21>;
-				clocks = <&clks 37>;
+				clocks = <&clks IMX27_CLK_KPP_IPG_GATE>;
 				status = "disabled";
 			};
 
 			owire: owire@10009000 {
 				compatible = "fsl,imx27-owire", "fsl,imx21-owire";
 				reg = <0x10009000 0x1000>;
-				clocks = <&clks 35>;
+				clocks = <&clks IMX27_CLK_OWIRE_IPG_GATE>;
 				status = "disabled";
 			};
 
@@ -156,7 +163,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1000a000 0x1000>;
 				interrupts = <20>;
-				clocks = <&clks 81>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART1_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -165,7 +173,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1000b000 0x1000>;
 				interrupts = <19>;
-				clocks = <&clks 80>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART2_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -174,7 +183,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1000c000 0x1000>;
 				interrupts = <18>;
-				clocks = <&clks 79>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART3_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -183,7 +193,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1000d000 0x1000>;
 				interrupts = <17>;
-				clocks = <&clks 78>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART4_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -194,7 +205,8 @@
 				compatible = "fsl,imx27-cspi";
 				reg = <0x1000e000 0x1000>;
 				interrupts = <16>;
-				clocks = <&clks 53>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_CSPI1_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -205,7 +217,8 @@
 				compatible = "fsl,imx27-cspi";
 				reg = <0x1000f000 0x1000>;
 				interrupts = <15>;
-				clocks = <&clks 52>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_CSPI2_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -215,7 +228,7 @@
 				compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
 				reg = <0x10010000 0x1000>;
 				interrupts = <14>;
-				clocks = <&clks 26>;
+				clocks = <&clks IMX27_CLK_SSI1_IPG_GATE>;
 				dmas = <&dma 12>, <&dma 13>, <&dma 14>, <&dma 15>;
 				dma-names = "rx0", "tx0", "rx1", "tx1";
 				fsl,fifo-depth = <8>;
@@ -227,7 +240,7 @@
 				compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
 				reg = <0x10011000 0x1000>;
 				interrupts = <13>;
-				clocks = <&clks 25>;
+				clocks = <&clks IMX27_CLK_SSI2_IPG_GATE>;
 				dmas = <&dma 8>, <&dma 9>, <&dma 10>, <&dma 11>;
 				dma-names = "rx0", "tx0", "rx1", "tx1";
 				fsl,fifo-depth = <8>;
@@ -240,7 +253,7 @@
 				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
 				reg = <0x10012000 0x1000>;
 				interrupts = <12>;
-				clocks = <&clks 40>;
+				clocks = <&clks IMX27_CLK_I2C1_IPG_GATE>;
 				status = "disabled";
 			};
 
@@ -248,7 +261,8 @@
 				compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
 				reg = <0x10013000 0x1000>;
 				interrupts = <11>;
-				clocks = <&clks 30>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_SDHC1_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&dma 7>;
 				dma-names = "rx-tx";
@@ -259,7 +273,8 @@
 				compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
 				reg = <0x10014000 0x1000>;
 				interrupts = <10>;
-				clocks = <&clks 29>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_SDHC2_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&dma 6>;
 				dma-names = "rx-tx";
@@ -276,6 +291,7 @@
 				gpio1: gpio@10015000 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015000 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -286,6 +302,7 @@
 				gpio2: gpio@10015100 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015100 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -296,6 +313,7 @@
 				gpio3: gpio@10015200 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015200 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -306,6 +324,7 @@
 				gpio4: gpio@10015300 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015300 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -316,6 +335,7 @@
 				gpio5: gpio@10015400 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015400 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -326,6 +346,7 @@
 				gpio6: gpio@10015500 {
 					compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
 					reg = <0x10015500 0x100>;
+					clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
 					interrupts = <8>;
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -337,7 +358,7 @@
 			audmux: audmux@10016000 {
 				compatible = "fsl,imx27-audmux", "fsl,imx21-audmux";
 				reg = <0x10016000 0x1000>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX27_CLK_DUMMY>;
 				clock-names = "audmux";
 				status = "disabled";
 			};
@@ -348,7 +369,8 @@
 				compatible = "fsl,imx27-cspi";
 				reg = <0x10017000 0x1000>;
 				interrupts = <6>;
-				clocks = <&clks 51>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_CSPI3_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -357,7 +379,8 @@
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x10019000 0x1000>;
 				interrupts = <4>;
-				clocks = <&clks 43>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT4_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -365,7 +388,8 @@
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x1001a000 0x1000>;
 				interrupts = <3>;
-				clocks = <&clks 42>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT5_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -373,7 +397,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1001b000 0x1000>;
 				interrupts = <49>;
-				clocks = <&clks 77>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART5_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -382,7 +407,8 @@
 				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
 				reg = <0x1001c000 0x1000>;
 				interrupts = <48>;
-				clocks = <&clks 78>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_UART6_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -393,7 +419,7 @@
 				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
 				reg = <0x1001d000 0x1000>;
 				interrupts = <1>;
-				clocks = <&clks 39>;
+				clocks = <&clks IMX27_CLK_I2C2_IPG_GATE>;
 				status = "disabled";
 			};
 
@@ -401,7 +427,8 @@
 				compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
 				reg = <0x1001e000 0x1000>;
 				interrupts = <9>;
-				clocks = <&clks 28>, <&clks 60>;
+				clocks = <&clks IMX27_CLK_SDHC3_IPG_GATE>,
+					 <&clks IMX27_CLK_PER2_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&dma 36>;
 				dma-names = "rx-tx";
@@ -412,7 +439,8 @@
 				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
 				reg = <0x1001f000 0x1000>;
 				interrupts = <2>;
-				clocks = <&clks 41>, <&clks 61>;
+				clocks = <&clks IMX27_CLK_GPT6_IPG_GATE>,
+					 <&clks IMX27_CLK_PER1_GATE>;
 				clock-names = "ipg", "per";
 			};
 		};
@@ -428,7 +456,9 @@
 				compatible = "fsl,imx27-fb", "fsl,imx21-fb";
 				interrupts = <61>;
 				reg = <0x10021000 0x1000>;
-				clocks = <&clks 36>, <&clks 65>, <&clks 59>;
+				clocks = <&clks IMX27_CLK_LCDC_IPG_GATE>,
+					 <&clks IMX27_CLK_LCDC_AHB_GATE>,
+					 <&clks IMX27_CLK_PER3_GATE>;
 				clock-names = "ipg", "ahb", "per";
 				status = "disabled";
 			};
@@ -437,7 +467,8 @@
 				compatible = "fsl,imx27-vpu";
 				reg = <0x10023000 0x0200>;
 				interrupts = <53>;
-				clocks = <&clks 57>, <&clks 66>;
+				clocks = <&clks IMX27_CLK_VPU_BAUD_GATE>,
+					 <&clks IMX27_CLK_VPU_AHB_GATE>;
 				clock-names = "per", "ahb";
 				iram = <&iram>;
 			};
@@ -446,7 +477,7 @@
 				compatible = "fsl,imx27-usb";
 				reg = <0x10024000 0x200>;
 				interrupts = <56>;
-				clocks = <&clks 75>;
+				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
 				fsl,usbmisc = <&usbmisc 0>;
 				status = "disabled";
 			};
@@ -455,7 +486,7 @@
 				compatible = "fsl,imx27-usb";
 				reg = <0x10024200 0x200>;
 				interrupts = <54>;
-				clocks = <&clks 75>;
+				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
 				fsl,usbmisc = <&usbmisc 1>;
 				status = "disabled";
 			};
@@ -464,7 +495,7 @@
 				compatible = "fsl,imx27-usb";
 				reg = <0x10024400 0x200>;
 				interrupts = <55>;
-				clocks = <&clks 75>;
+				clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
 			};
@@ -473,14 +504,15 @@
 				#index-cells = <1>;
 				compatible = "fsl,imx27-usbmisc";
 				reg = <0x10024600 0x200>;
-				clocks = <&clks 62>;
+				clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
 			};
 
 			sahara2: sahara@10025000 {
 				compatible = "fsl,imx27-sahara";
 				reg = <0x10025000 0x1000>;
 				interrupts = <59>;
-				clocks = <&clks 32>, <&clks 64>;
+				clocks = <&clks IMX27_CLK_SAHARA_IPG_GATE>,
+					 <&clks IMX27_CLK_SAHARA_AHB_GATE>;
 				clock-names = "ipg", "ahb";
 			};
 
@@ -494,14 +526,15 @@
 				compatible = "fsl,imx27-iim";
 				reg = <0x10028000 0x1000>;
 				interrupts = <62>;
-				clocks = <&clks 38>;
+				clocks = <&clks IMX27_CLK_IIM_IPG_GATE>;
 			};
 
 			fec: ethernet@1002b000 {
 				compatible = "fsl,imx27-fec";
 				reg = <0x1002b000 0x4000>;
 				interrupts = <50>;
-				clocks = <&clks 48>, <&clks 67>;
+				clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
+					 <&clks IMX27_CLK_FEC_AHB_GATE>;
 				clock-names = "ipg", "ahb";
 				status = "disabled";
 			};
@@ -513,7 +546,7 @@
 			compatible = "fsl,imx27-nand";
 			reg = <0xd8000000 0x1000>;
 			interrupts = <29>;
-			clocks = <&clks 54>;
+			clocks = <&clks IMX27_CLK_NFC_BAUD_GATE>;
 			status = "disabled";
 		};
 
@@ -522,7 +555,7 @@
 			#size-cells = <1>;
 			compatible = "fsl,imx27-weim";
 			reg = <0xd8002000 0x1000>;
-			clocks = <&clks 0>;
+			clocks = <&clks IMX27_CLK_EMI_AHB_GATE>;
 			ranges = <
 				0 0 0xc0000000 0x08000000
 				1 0 0xc8000000 0x08000000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx27.dtsi"
+
+/ {
+	model = "Eukrea CPUIMX27";
+	compatible = "eukrea,cpuimx27", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x04000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "simple-bus";
+
+		clk14745600: clock@0 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <14745600>;
+			reg = <0>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pcf8563@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nfc>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
+
+&owire {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_owire>;
+	status = "okay";
+};
+
+&sdhci2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc2>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbh2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh2>;
+	dr_mode = "host";
+	phy_type = "ulpi";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	phy_type = "ulpi";
+	disable-over-current;
+	status = "okay";
+};
+
+&weim {
+	status = "okay";
+
+	nor: nor@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cfi-flash";
+		reg = <0 0x00000000 0x04000000>;
+		bank-width = <2>;
+		linux,mtd-name = "physmap-flash.0";
+		fsl,weim-cs-timing = <0x00008f03 0xa0330d01 0x002208c0>;
+	};
+
+	uart8250@3,200000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart8250_1>;
+		compatible = "ns8250";
+		clocks = <&clk14745600>;
+		fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+		interrupts = <&gpio2 23 IRQ_TYPE_LEVEL_LOW>;
+		reg = <3 0x200000 0x1000>;
+		reg-shift = <1>;
+		reg-io-width = <1>;
+		no-loopback-test;
+	};
+
+	uart8250@3,400000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart8250_2>;
+		compatible = "ns8250";
+		clocks = <&clk14745600>;
+		fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+		interrupts = <&gpio2 22 IRQ_TYPE_LEVEL_LOW>;
+		reg = <3 0x400000 0x1000>;
+		reg-shift = <1>;
+		reg-io-width = <1>;
+		no-loopback-test;
+	};
+
+	uart8250@3,800000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart8250_3>;
+		compatible = "ns8250";
+		clocks = <&clk14745600>;
+		fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+		interrupts = <&gpio2 27 IRQ_TYPE_LEVEL_LOW>;
+		reg = <3 0x800000 0x1000>;
+		reg-shift = <1>;
+		reg-io-width = <1>;
+		no-loopback-test;
+	};
+
+	uart8250@3,1000000 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart8250_4>;
+		compatible = "ns8250";
+		clocks = <&clk14745600>;
+		fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+		interrupts = <&gpio2 30 IRQ_TYPE_LEVEL_LOW>;
+		reg = <3 0x1000000 0x1000>;
+		reg-shift = <1>;
+		reg-io-width = <1>;
+		no-loopback-test;
+	};
+};
+
+&iomuxc {
+	imx27-eukrea-cpuimx27 {
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX27_PAD_SD3_CMD__FEC_TXD0		0x0
+				MX27_PAD_SD3_CLK__FEC_TXD1		0x0
+				MX27_PAD_ATA_DATA0__FEC_TXD2		0x0
+				MX27_PAD_ATA_DATA1__FEC_TXD3		0x0
+				MX27_PAD_ATA_DATA2__FEC_RX_ER		0x0
+				MX27_PAD_ATA_DATA3__FEC_RXD1		0x0
+				MX27_PAD_ATA_DATA4__FEC_RXD2		0x0
+				MX27_PAD_ATA_DATA5__FEC_RXD3		0x0
+				MX27_PAD_ATA_DATA6__FEC_MDIO		0x0
+				MX27_PAD_ATA_DATA7__FEC_MDC		0x0
+				MX27_PAD_ATA_DATA8__FEC_CRS		0x0
+				MX27_PAD_ATA_DATA9__FEC_TX_CLK		0x0
+				MX27_PAD_ATA_DATA10__FEC_RXD0		0x0
+				MX27_PAD_ATA_DATA11__FEC_RX_DV		0x0
+				MX27_PAD_ATA_DATA12__FEC_RX_CLK		0x0
+				MX27_PAD_ATA_DATA13__FEC_COL		0x0
+				MX27_PAD_ATA_DATA14__FEC_TX_ER		0x0
+				MX27_PAD_ATA_DATA15__FEC_TX_EN		0x0
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX27_PAD_I2C_DATA__I2C_DATA		0x0
+				MX27_PAD_I2C_CLK__I2C_CLK		0x0
+			>;
+		};
+
+		pinctrl_nfc: nfcgrp {
+			fsl,pins = <
+				MX27_PAD_NFRB__NFRB			0x0
+				MX27_PAD_NFCLE__NFCLE			0x0
+				MX27_PAD_NFWP_B__NFWP_B			0x0
+				MX27_PAD_NFCE_B__NFCE_B			0x0
+				MX27_PAD_NFALE__NFALE			0x0
+				MX27_PAD_NFRE_B__NFRE_B			0x0
+				MX27_PAD_NFWE_B__NFWE_B			0x0
+			>;
+		};
+
+		pinctrl_owire: owiregrp {
+			fsl,pins = <
+				MX27_PAD_RTCK__OWIRE			0x0
+			>;
+		};
+
+		pinctrl_sdhc2: sdhc2grp {
+			fsl,pins = <
+				MX27_PAD_SD2_CLK__SD2_CLK		0x0
+				MX27_PAD_SD2_CMD__SD2_CMD		0x0
+				MX27_PAD_SD2_D0__SD2_D0			0x0
+				MX27_PAD_SD2_D1__SD2_D1			0x0
+				MX27_PAD_SD2_D2__SD2_D2			0x0
+				MX27_PAD_SD2_D3__SD2_D3			0x0
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX27_PAD_USBH1_TXDM__UART4_TXD		0x0
+				MX27_PAD_USBH1_RXDP__UART4_RXD		0x0
+				MX27_PAD_USBH1_TXDP__UART4_CTS		0x0
+				MX27_PAD_USBH1_FS__UART4_RTS		0x0
+			>;
+		};
+
+		pinctrl_uart8250_1: uart82501grp {
+			fsl,pins = <
+				MX27_PAD_USB_PWR__GPIO2_23		0x0
+			>;
+		};
+
+		pinctrl_uart8250_2: uart82502grp {
+			fsl,pins = <
+				MX27_PAD_USBH1_SUSP__GPIO2_22		0x0
+			>;
+		};
+
+		pinctrl_uart8250_3: uart82503grp {
+			fsl,pins = <
+				MX27_PAD_USBH1_OE_B__GPIO2_27		0x0
+			>;
+		};
+
+		pinctrl_uart8250_4: uart82504grp {
+			fsl,pins = <
+				MX27_PAD_USBH1_RXDM__GPIO2_30		0x0
+			>;
+		};
+
+		pinctrl_usbh2: usbh2grp {
+			fsl,pins = <
+				MX27_PAD_USBH2_CLK__USBH2_CLK		0x0
+				MX27_PAD_USBH2_DIR__USBH2_DIR		0x0
+				MX27_PAD_USBH2_NXT__USBH2_NXT		0x0
+				MX27_PAD_USBH2_STP__USBH2_STP		0x0
+				MX27_PAD_CSPI2_SCLK__USBH2_DATA0	0x0
+				MX27_PAD_CSPI2_MOSI__USBH2_DATA1	0x0
+				MX27_PAD_CSPI2_MISO__USBH2_DATA2	0x0
+				MX27_PAD_CSPI2_SS1__USBH2_DATA3		0x0
+				MX27_PAD_CSPI2_SS2__USBH2_DATA4		0x0
+				MX27_PAD_CSPI1_SS2__USBH2_DATA5		0x0
+				MX27_PAD_CSPI2_SS0__USBH2_DATA6		0x0
+				MX27_PAD_USBH2_DATA7__USBH2_DATA7	0x0
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX27_PAD_USBOTG_CLK__USBOTG_CLK		0x0
+				MX27_PAD_USBOTG_DIR__USBOTG_DIR		0x0
+				MX27_PAD_USBOTG_NXT__USBOTG_NXT		0x0
+				MX27_PAD_USBOTG_STP__USBOTG_STP		0x0
+				MX27_PAD_USBOTG_DATA0__USBOTG_DATA0	0x0
+				MX27_PAD_USBOTG_DATA1__USBOTG_DATA1	0x0
+				MX27_PAD_USBOTG_DATA2__USBOTG_DATA2	0x0
+				MX27_PAD_USBOTG_DATA3__USBOTG_DATA3	0x0
+				MX27_PAD_USBOTG_DATA4__USBOTG_DATA4	0x0
+				MX27_PAD_USBOTG_DATA5__USBOTG_DATA5	0x0
+				MX27_PAD_USBOTG_DATA6__USBOTG_DATA6	0x0
+				MX27_PAD_USBOTG_DATA7__USBOTG_DATA7	0x0
+			>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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 "imx27-eukrea-cpuimx27.dtsi"
+
+/ {
+	model = "Eukrea MBIMXSD27";
+	compatible = "eukrea,mbimxsd27-baseboard", "eukrea,cpuimx27", "fsl,imx27";
+
+	display0: CMO-QVGA {
+		model = "CMO-QVGA";
+		native-mode = <&timing0>;
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xfad08b80>;
+
+		display-timings {
+			timing0: 320x240 {
+				clock-frequency = <6500000>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <20>;
+				hsync-len = <30>;
+				hfront-porch = <38>;
+				vback-porch = <4>;
+				vsync-len = <3>;
+				vfront-porch = <15>;
+			};
+		};
+	};
+
+	backlight {
+		compatible = "gpio-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight>;
+		gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioleds>;
+
+		led1 {
+			label = "system::live";
+			gpios = <&gpio6 16 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led2 {
+			label = "system::user";
+			gpios = <&gpio6 19 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	regulators {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "simple-bus";
+
+		reg_lcd: regulator@0 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_lcdreg>;
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "LCD";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+};
+
+&cspi1 {
+	pinctrl-0 = <&pinctrl_cspi1>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	ads7846 {
+		compatible = "ti,ads7846";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touch>;
+		reg = <0>;
+		interrupts = <&gpio4 25 IRQ_TYPE_LEVEL_LOW>;
+		spi-cpol;
+		spi-max-frequency = <1500000>;
+		ti,keep-vref-on;
+	};
+};
+
+&fb {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_imxfb>;
+	display = <&display0>;
+	lcd-supply = <&reg_lcd>;
+	fsl,dmacr = <0x00040060>;
+	fsl,lscr1 = <0x00120300>;
+	fsl,lpccr = <0x00a903ff>;
+	status = "okay";
+};
+
+&i2c1 {
+	codec: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+	};
+};
+
+&kpp {
+	linux,keymap = <
+		MATRIX_KEY(0, 0, KEY_UP)
+		MATRIX_KEY(0, 1, KEY_DOWN)
+		MATRIX_KEY(1, 0, KEY_RIGHT)
+		MATRIX_KEY(1, 1, KEY_LEFT)
+	>;
+	status = "okay";
+};
+
+&sdhci1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhc1>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ssi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ssi1>;
+	codec-handle = <&codec>;
+	status = "okay";
+};
+
+&uart1 {
+	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx27-eukrea-cpuimx27-baseboard {
+		pinctrl_cspi1: cspi1grp {
+			fsl,pins = <
+				MX27_PAD_CSPI1_MISO__CSPI1_MISO	0x0
+				MX27_PAD_CSPI1_MOSI__CSPI1_MOSI	0x0
+				MX27_PAD_CSPI1_SCLK__CSPI1_SCLK	0x0
+				MX27_PAD_CSPI1_SS0__GPIO4_28	0x0 /* CS0 */
+			>;
+		};
+
+		pinctrl_backlight: backlightgrp {
+			fsl,pins = <
+				MX27_PAD_PWMO__GPIO5_5		0x0
+			>;
+		};
+
+		pinctrl_gpioleds: gpioledsgrp {
+			fsl,pins = <
+				MX27_PAD_PC_PWRON__GPIO6_16	0x0
+				MX27_PAD_PC_CD2_B__GPIO6_19	0x0
+			>;
+		};
+
+		pinctrl_imxfb: imxfbgrp {
+			fsl,pins = <
+				MX27_PAD_LD0__LD0		0x0
+				MX27_PAD_LD1__LD1		0x0
+				MX27_PAD_LD2__LD2		0x0
+				MX27_PAD_LD3__LD3		0x0
+				MX27_PAD_LD4__LD4		0x0
+				MX27_PAD_LD5__LD5		0x0
+				MX27_PAD_LD6__LD6		0x0
+				MX27_PAD_LD7__LD7		0x0
+				MX27_PAD_LD8__LD8		0x0
+				MX27_PAD_LD9__LD9		0x0
+				MX27_PAD_LD10__LD10		0x0
+				MX27_PAD_LD11__LD11		0x0
+				MX27_PAD_LD12__LD12		0x0
+				MX27_PAD_LD13__LD13		0x0
+				MX27_PAD_LD14__LD14		0x0
+				MX27_PAD_LD15__LD15		0x0
+				MX27_PAD_LD16__LD16		0x0
+				MX27_PAD_LD17__LD17		0x0
+				MX27_PAD_CONTRAST__CONTRAST	0x0
+				MX27_PAD_OE_ACD__OE_ACD		0x0
+				MX27_PAD_HSYNC__HSYNC		0x0
+				MX27_PAD_VSYNC__VSYNC		0x0
+			>;
+		};
+
+		pinctrl_lcdreg: lcdreggrp {
+			fsl,pins = <
+				MX27_PAD_CLS__GPIO1_25		0x0
+			>;
+		};
+
+		pinctrl_sdhc1: sdhc1grp {
+			fsl,pins = <
+				MX27_PAD_SD1_CLK__SD1_CLK	0x0
+				MX27_PAD_SD1_CMD__SD1_CMD	0x0
+				MX27_PAD_SD1_D0__SD1_D0		0x0
+				MX27_PAD_SD1_D1__SD1_D1		0x0
+				MX27_PAD_SD1_D2__SD1_D2		0x0
+				MX27_PAD_SD1_D3__SD1_D3		0x0
+			>;
+		};
+
+		pinctrl_ssi1: ssi1grp {
+			fsl,pins = <
+				MX27_PAD_SSI4_CLK__SSI4_CLK	0x0
+				MX27_PAD_SSI4_FS__SSI4_FS	0x0
+				MX27_PAD_SSI4_RXDAT__SSI4_RXDAT	0x1
+				MX27_PAD_SSI4_TXDAT__SSI4_TXDAT	0x1
+			>;
+		};
+
+		pinctrl_touch: touchgrp {
+			fsl,pins = <
+				MX27_PAD_CSPI1_RDY__GPIO4_25	0x0 /* IRQ */
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX27_PAD_UART1_TXD__UART1_TXD	0x0
+				MX27_PAD_UART1_RXD__UART1_RXD	0x0
+				MX27_PAD_UART1_CTS__UART1_CTS	0x0
+				MX27_PAD_UART1_RTS__UART1_RTS	0x0
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX27_PAD_UART2_TXD__UART2_TXD	0x0
+				MX27_PAD_UART2_RXD__UART2_RXD	0x0
+				MX27_PAD_UART2_CTS__UART2_CTS	0x0
+				MX27_PAD_UART2_RTS__UART2_RTS	0x0
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX27_PAD_UART3_TXD__UART3_TXD	0x0
+				MX27_PAD_UART3_RXD__UART3_RXD	0x0
+				MX27_PAD_UART3_CTS__UART3_CTS	0x0
+				MX27_PAD_UART3_RTS__UART3_RTS	0x0
+			>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-pdk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-pdk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-pdk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-pdk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 		usbphy0: usbphy@0 {
 			compatible = "usb-nop-xceiv";
 			reg = <0>;
-			clocks = <&clks 0>;
+			clocks = <&clks IMX27_CLK_DUMMY>;
 			clock-names = "main_clk";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@
 			compatible = "usb-nop-xceiv";
 			reg = <2>;
 			vcc-supply = <&reg_5v0>;
-			clocks = <&clks 0>;
+			clocks = <&clks IMX27_CLK_DUMMY>;
 			clock-names = "main_clk";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@
 			compatible = "usb-nop-xceiv";
 			reg = <0>;
 			vcc-supply = <&sw3_reg>;
-			clocks = <&clks 0>;
+			clocks = <&clks IMX27_CLK_DUMMY>;
 			clock-names = "main_clk";
 		};
 	};
@@ -310,7 +310,6 @@
 &ssi1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_ssi1>;
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-pinfunc.h linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-pinfunc.h
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx27-pinfunc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx27-pinfunc.h	2014-09-28 17:29:07.000000000 -0400
@@ -101,14 +101,6 @@
 #define MX27_PAD_CONTRAST__GPIO1_30                        0x1e 0x032
 #define MX27_PAD_OE_ACD__OE_ACD                            0x1f 0x004
 #define MX27_PAD_OE_ACD__GPIO1_31                          0x1f 0x032
-#define MX27_PAD_UNUSED0__UNUSED0                          0x20 0x004
-#define MX27_PAD_UNUSED0__GPIO2_0                          0x20 0x032
-#define MX27_PAD_UNUSED1__UNUSED1                          0x21 0x004
-#define MX27_PAD_UNUSED1__GPIO2_1                          0x21 0x032
-#define MX27_PAD_UNUSED2__UNUSED2                          0x22 0x004
-#define MX27_PAD_UNUSED2__GPIO2_2                          0x22 0x032
-#define MX27_PAD_UNUSED3__UNUSED3                          0x23 0x004
-#define MX27_PAD_UNUSED3__GPIO2_3                          0x23 0x032
 #define MX27_PAD_SD2_D0__SD2_D0                            0x24 0x004
 #define MX27_PAD_SD2_D0__MSHC_DATA0                        0x24 0x005
 #define MX27_PAD_SD2_D0__GPIO2_4                           0x24 0x032
@@ -183,16 +175,6 @@
 #define MX27_PAD_USBH1_RXDP__USBH1_RXDP                    0x3f 0x004
 #define MX27_PAD_USBH1_RXDP__UART4_RXD                     0x3f 0x001
 #define MX27_PAD_USBH1_RXDP__GPIO2_31                      0x3f 0x032
-#define MX27_PAD_UNUSED4__UNUSED4                          0x40 0x004
-#define MX27_PAD_UNUSED4__GPIO3_0                          0x40 0x032
-#define MX27_PAD_UNUSED5__UNUSED5                          0x41 0x004
-#define MX27_PAD_UNUSED5__GPIO3_1                          0x41 0x032
-#define MX27_PAD_UNUSED6__UNUSED6                          0x42 0x004
-#define MX27_PAD_UNUSED6__GPIO3_2                          0x42 0x032
-#define MX27_PAD_UNUSED7__UNUSED7                          0x43 0x004
-#define MX27_PAD_UNUSED7__GPIO3_3                          0x43 0x032
-#define MX27_PAD_UNUSED8__UNUSED8                          0x44 0x004
-#define MX27_PAD_UNUSED8__GPIO3_4                          0x44 0x032
 #define MX27_PAD_I2C2_SDA__I2C2_SDA                        0x45 0x004
 #define MX27_PAD_I2C2_SDA__GPIO3_5                         0x45 0x032
 #define MX27_PAD_I2C2_SCL__I2C2_SCL                        0x46 0x004
@@ -422,18 +404,6 @@
 #define MX27_PAD_USBOTG_CLK__GPIO5_24                      0x98 0x032
 #define MX27_PAD_USBOTG_DATA7__USBOTG_DATA7                0x99 0x004
 #define MX27_PAD_USBOTG_DATA7__GPIO5_25                    0x99 0x032
-#define MX27_PAD_UNUSED9__UNUSED9                          0x9a 0x004
-#define MX27_PAD_UNUSED9__GPIO5_26                         0x9a 0x032
-#define MX27_PAD_UNUSED10__UNUSED10                        0x9b 0x004
-#define MX27_PAD_UNUSED10__GPIO5_27                        0x9b 0x032
-#define MX27_PAD_UNUSED11__UNUSED11                        0x9c 0x004
-#define MX27_PAD_UNUSED11__GPIO5_28                        0x9c 0x032
-#define MX27_PAD_UNUSED12__UNUSED12                        0x9d 0x004
-#define MX27_PAD_UNUSED12__GPIO5_29                        0x9d 0x032
-#define MX27_PAD_UNUSED13__UNUSED13                        0x9e 0x004
-#define MX27_PAD_UNUSED13__GPIO5_30                        0x9e 0x032
-#define MX27_PAD_UNUSED14__UNUSED14                        0x9f 0x004
-#define MX27_PAD_UNUSED14__GPIO5_31                        0x9f 0x032
 #define MX27_PAD_NFRB__NFRB                                0xa0 0x000
 #define MX27_PAD_NFRB__ETMTRACEPKT3                        0xa0 0x005
 #define MX27_PAD_NFRB__GPIO6_0                             0xa0 0x032
@@ -506,21 +476,5 @@
 #define MX27_PAD_ATA_DATA15__ETMTRACEPKT4                  0xb7 0x005
 #define MX27_PAD_ATA_DATA15__FEC_TX_EN                     0xb7 0x006
 #define MX27_PAD_ATA_DATA15__GPIO6_23                      0xb7 0x032
-#define MX27_PAD_UNUSED15__UNUSED15                        0xb8 0x004
-#define MX27_PAD_UNUSED15__GPIO6_24                        0xb8 0x032
-#define MX27_PAD_UNUSED16__UNUSED16                        0xb9 0x004
-#define MX27_PAD_UNUSED16__GPIO6_25                        0xb9 0x032
-#define MX27_PAD_UNUSED17__UNUSED17                        0xba 0x004
-#define MX27_PAD_UNUSED17__GPIO6_26                        0xba 0x032
-#define MX27_PAD_UNUSED18__UNUSED18                        0xbb 0x004
-#define MX27_PAD_UNUSED18__GPIO6_27                        0xbb 0x032
-#define MX27_PAD_UNUSED19__UNUSED19                        0xbc 0x004
-#define MX27_PAD_UNUSED19__GPIO6_28                        0xbc 0x032
-#define MX27_PAD_UNUSED20__UNUSED20                        0xbd 0x004
-#define MX27_PAD_UNUSED20__GPIO6_29                        0xbd 0x032
-#define MX27_PAD_UNUSED21__UNUSED21                        0xbe 0x004
-#define MX27_PAD_UNUSED21__GPIO6_30                        0xbe 0x032
-#define MX27_PAD_UNUSED22__UNUSED22                        0xbf 0x004
-#define MX27_PAD_UNUSED22__GPIO6_31                        0xbf 0x032
 
 #endif /* __DTS_IMX27_PINFUNC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-cfa10036.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-cfa10036.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-cfa10036.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-cfa10036.dts	2014-09-28 17:29:07.000000000 -0400
@@ -53,6 +53,17 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				mmc_pwr_cfa10036: mmc_pwr_cfa10036@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31c3 /*
+						MX28_PAD_PWM3__GPIO_3_28 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 			};
 
 			ssp0: ssp@80010000 {
@@ -60,6 +71,7 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&mmc0_4bit_pins_a
 					&mmc0_cd_cfg &mmc0_sck_cfg>;
+				vmmc-supply = <&reg_vddio_sd0>;
 				bus-width = <4>;
 				status = "okay";
 			};
@@ -116,4 +128,14 @@
 			default-state = "on";
 		};
 	};
+
+	reg_vddio_sd0: vddio-sd0 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&mmc_pwr_cfa10036>;
+		regulator-name = "vddio-sd0";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio3 28 0>;
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-m28.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-m28.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-m28.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-m28.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * 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 "imx28.dtsi"
+
+/ {
+	model = "DENX M28";
+	compatible = "denx,m28", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			gpmi-nand@8000c000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+				status = "okay";
+
+				partition@0 {
+					label = "bootloader";
+					reg = <0x00000000 0x00300000>;
+					read-only;
+				};
+
+				partition@1 {
+					label = "environment";
+					reg = <0x00300000 0x00080000>;
+				};
+
+				partition@2 {
+					label = "redundant-environment";
+					reg = <0x00380000 0x00080000>;
+				};
+
+				partition@3 {
+					label = "kernel";
+					reg = <0x00400000 0x00400000>;
+				};
+
+				partition@4 {
+					label = "filesystem";
+					reg = <0x00800000 0x0f800000>;
+				};
+			};
+		};
+
+		apbx@80040000 {
+			i2c0: i2c@80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins_a>;
+				status = "okay";
+
+				rtc: rtc@68 {
+					compatible = "stm,m41t62";
+					reg = <0x68>;
+				};
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-m28evk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-m28evk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx28-m28evk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx28-m28evk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -10,52 +10,14 @@
  */
 
 /dts-v1/;
-#include "imx28.dtsi"
+#include "imx28-m28.dtsi"
 
 / {
 	model = "DENX M28EVK";
 	compatible = "denx,m28evk", "fsl,imx28";
 
-	memory {
-		reg = <0x40000000 0x08000000>;
-	};
-
 	apb@80000000 {
 		apbh@80000000 {
-			gpmi-nand@8000c000 {
-				#address-cells = <1>;
-				#size-cells = <1>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
-				status = "okay";
-
-				partition@0 {
-					label = "bootloader";
-					reg = <0x00000000 0x00300000>;
-					read-only;
-				};
-
-				partition@1 {
-					label = "environment";
-					reg = <0x00300000 0x00080000>;
-				};
-
-				partition@2 {
-					label = "redundant-environment";
-					reg = <0x00380000 0x00080000>;
-				};
-
-				partition@3 {
-					label = "kernel";
-					reg = <0x00400000 0x00400000>;
-				};
-
-				partition@4 {
-					label = "filesystem";
-					reg = <0x00800000 0x0f800000>;
-				};
-			};
-
 			ssp0: ssp@80010000 {
 				compatible = "fsl,imx28-mmc";
 				pinctrl-names = "default";
@@ -175,10 +137,6 @@
 			};
 
 			i2c0: i2c@80058000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&i2c0_pins_a>;
-				status = "okay";
-
 				sgtl5000: codec@0a {
 					compatible = "fsl,sgtl5000";
 					reg = <0x0a>;
@@ -192,11 +150,6 @@
 					reg = <0x51>;
 					pagesize = <32>;
 				};
-
-				rtc: rtc@68 {
-					compatible = "stm,m41t62";
-					reg = <0x68>;
-				};
 			};
 
 			lradc@80050000 {
@@ -284,19 +237,6 @@
 	};
 
 	regulators {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		reg_3p3v: regulator@0 {
-			compatible = "regulator-fixed";
-			reg = <0>;
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
 		reg_vddio_sd0: regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx35.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx35.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx35.dtsi	2014-08-07 04:46:55.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx35.dtsi	2014-09-28 21:27:32.000000000 -0400
@@ -193,6 +193,14 @@
 				#clock-cells = <1>;
 			};
 
+			gpt: timer@53f90000 {
+				compatible = "fsl,imx35-gpt", "fsl,imx31-gpt";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <29>;
+				clocks = <&clks 9>, <&clks 50>;
+				clock-names = "ipg", "per";
+			};
+
 			gpio3: gpio@53fa4000 {
 				compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
 				reg = <0x53fa4000 0x4000>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -133,7 +133,6 @@
 
 &ssi1 {
 	codec-handle = <&tlv320aic23>;
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx50.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx50.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx50.dtsi	2014-08-07 04:46:57.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx50.dtsi	2014-09-28 21:27:34.000000000 -0400
@@ -151,8 +151,10 @@
 					reg = <0x50014000 0x4000>;
 					interrupts = <30>;
 					clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+					dmas = <&sdma 24 1 0>,
+					       <&sdma 25 1 0>;
+					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
 				};
 
@@ -457,8 +459,10 @@
 				reg = <0x63fcc000 0x4000>;
 				interrupts = <29>;
 				clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+				dmas = <&sdma 28 0 0>,
+				       <&sdma 29 0 0>;
+				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx51-babbage.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51-babbage.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx51-babbage.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51-babbage.dts	2014-09-28 17:29:07.000000000 -0400
@@ -203,6 +203,7 @@
 		reg = <0>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+		fsl,mc13xxx-uses-rtc;
 
 		regulators {
 			sw1_reg: sw1 {
@@ -392,7 +393,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx51.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx51.dtsi	2014-08-07 04:46:59.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51.dtsi	2014-09-28 21:27:36.000000000 -0400
@@ -218,7 +218,6 @@
 					       <&sdma 25 1 0>;
 					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
 				};
 
@@ -508,7 +507,6 @@
 				       <&sdma 29 0 0>;
 				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
@@ -564,7 +562,6 @@
 				       <&sdma 47 0 0>;
 				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -255,7 +255,6 @@
 
 &ssi2 {
 	codec-handle = <&tlv320aic23>;
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53.dtsi	2014-08-07 04:47:01.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53.dtsi	2014-09-28 21:27:38.000000000 -0400
@@ -108,7 +108,7 @@
 			clocks = <&clks IMX5_CLK_SATA_GATE>,
 				 <&clks IMX5_CLK_SATA_REF>,
 				 <&clks IMX5_CLK_AHB>;
-			clock-names = "sata_gate", "sata_ref", "ahb";
+			clock-names = "sata", "sata_ref", "ahb";
 			status = "disabled";
 		};
 
@@ -231,7 +231,6 @@
 					       <&sdma 25 1 0>;
 					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
 				};
 
@@ -260,6 +259,11 @@
 				};
 			};
 
+			aipstz1: bridge@53f00000 {
+				compatible = "fsl,imx53-aipstz";
+				reg = <0x53f00000 0x60>;
+			};
+
 			usbphy0: usbphy@0 {
 				compatible = "usb-nop-xceiv";
 				clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
@@ -419,10 +423,14 @@
 				status = "disabled";
 
 				lvds-channel@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
 					reg = <0>;
 					status = "disabled";
 
-					port {
+					port@0 {
+						reg = <0>;
+
 						lvds0_in: endpoint {
 							remote-endpoint = <&ipu_di0_lvds0>;
 						};
@@ -430,10 +438,14 @@
 				};
 
 				lvds-channel@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
 					reg = <1>;
 					status = "disabled";
 
-					port {
+					port@1 {
+						reg = <1>;
+
 						lvds1_in: endpoint {
 							remote-endpoint = <&ipu_di1_lvds1>;
 						};
@@ -572,6 +584,11 @@
 			reg = <0x60000000 0x10000000>;
 			ranges;
 
+			aipstz2: bridge@63f00000 {
+				compatible = "fsl,imx53-aipstz";
+				reg = <0x63f00000 0x60>;
+			};
+
 			iim: iim@63f98000 {
 				compatible = "fsl,imx53-iim", "fsl,imx27-iim";
 				reg = <0x63f98000 0x4000>;
@@ -661,7 +678,6 @@
 				       <&sdma 29 0 0>;
 				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
@@ -689,7 +705,6 @@
 				       <&sdma 47 0 0>;
 				dma-names = "rx", "tx";
 				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
@@ -724,7 +739,7 @@
 				compatible = "fsl,imx53-vpu";
 				reg = <0x63ff4000 0x1000>;
 				interrupts = <9>;
-				clocks = <&clks IMX5_CLK_VPU_GATE>,
+				clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>,
 				         <&clks IMX5_CLK_VPU_GATE>;
 				clock-names = "per", "ahb";
 				resets = <&src 1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-m53.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-m53.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-m53.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-m53.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * 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 "imx53.dtsi"
+
+/ {
+	model = "DENX M53";
+	compatible = "denx,imx53-m53", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x20000000>,
+		      <0xb0000000 0x20000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p2v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P2V";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
+
+		reg_backlight: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "lcd-supply";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	stmpe610@41 {
+		compatible = "st,stmpe610";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x41>;
+		id = <0>;
+		blocks = <0x5>;
+		interrupts = <6 0x0>;
+		interrupt-parent = <&gpio7>;
+		irq-trigger = <0x1>;
+
+		stmpe_touchscreen {
+			compatible = "st,stmpe-ts";
+			reg = <0>;
+			st,sample-time = <4>;
+			st,mod-12b = <1>;
+			st,ref-sel = <0>;
+			st,adc-freq = <1>;
+			st,ave-ctrl = <3>;
+			st,touch-det-delay = <3>;
+			st,settling = <4>;
+			st,fraction-z = <7>;
+			st,i-drive = <1>;
+		};
+	};
+
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c128";
+		reg = <0x50>;
+		pagesize = <32>;
+	};
+
+	rtc: rtc@68 {
+		compatible = "stm,m41t62";
+		reg = <0x68>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx53-m53evk {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	0x80000000
+				MX53_PAD_EIM_EB3__GPIO2_31		0x80000000
+				MX53_PAD_PATA_DA_0__GPIO7_6		0x80000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX53_PAD_EIM_D16__I2C2_SDA		0xc0000000
+				MX53_PAD_EIM_EB2__I2C2_SCL		0xc0000000
+			>;
+		};
+
+		pinctrl_nand: nandgrp {
+			fsl,pins = <
+				MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
+				MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
+				MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
+				MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
+				MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
+				MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
+				MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
+				MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	0xa4
+				MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	0xa4
+				MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	0xa4
+				MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	0xa4
+				MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	0xa4
+				MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	0xa4
+				MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	0xa4
+				MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	0xa4
+			>;
+		};
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nand>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-m53evk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-m53evk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -10,17 +10,12 @@
  */
 
 /dts-v1/;
-#include "imx53.dtsi"
+#include "imx53-m53.dtsi"
 
 / {
 	model = "DENX M53EVK";
 	compatible = "denx,imx53-m53evk", "fsl,imx53";
 
-	memory {
-		reg = <0x70000000 0x20000000>,
-		      <0xb0000000 0x20000000>;
-	};
-
 	display1: display@di1 {
 		compatible = "fsl,imx-parallel-display";
 		interface-pix-fmt = "bgr666";
@@ -81,25 +76,6 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		reg_3p2v: regulator@0 {
-			compatible = "regulator-fixed";
-			reg = <0>;
-			regulator-name = "3P2V";
-			regulator-min-microvolt = <3200000>;
-			regulator-max-microvolt = <3200000>;
-			regulator-always-on;
-		};
-
-
-		reg_backlight: regulator@1 {
-			compatible = "regulator-fixed";
-			reg = <1>;
-			regulator-name = "lcd-supply";
-			regulator-min-microvolt = <3200000>;
-			regulator-max-microvolt = <3200000>;
-			regulator-always-on;
-		};
-
 		reg_usbh1_vbus: regulator@3 {
 			compatible = "regulator-fixed";
 			reg = <3>;
@@ -174,50 +150,6 @@
 	};
 };
 
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2>;
-	clock-frequency = <400000>;
-	status = "okay";
-
-	stmpe610@41 {
-		compatible = "st,stmpe610";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reg = <0x41>;
-		id = <0>;
-		blocks = <0x5>;
-		interrupts = <6 0x0>;
-		interrupt-parent = <&gpio7>;
-		irq-trigger = <0x1>;
-
-		stmpe_touchscreen {
-			compatible = "st,stmpe-ts";
-			reg = <0>;
-			st,sample-time = <4>;
-			st,mod-12b = <1>;
-			st,ref-sel = <0>;
-			st,adc-freq = <1>;
-			st,ave-ctrl = <3>;
-			st,touch-det-delay = <3>;
-			st,settling = <4>;
-			st,fraction-z = <7>;
-			st,i-drive = <1>;
-		};
-	};
-
-	eeprom: eeprom@50 {
-		compatible = "atmel,24c128";
-		reg = <0x50>;
-		pagesize = <32>;
-	};
-
-	rtc: rtc@68 {
-		compatible = "stm,m41t62";
-		reg = <0x68>;
-	};
-};
-
 &i2c3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_i2c3>;
@@ -229,11 +161,8 @@
 	pinctrl-0 = <&pinctrl_hog>;
 
 	imx53-m53evk {
-		pinctrl_hog: hoggrp {
+		pinctrl_usb: usbgrp {
 			fsl,pins = <
-				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	0x80000000
-				MX53_PAD_EIM_EB3__GPIO2_31		0x80000000
-				MX53_PAD_PATA_DA_0__GPIO7_6		0x80000000
 				MX53_PAD_GPIO_2__GPIO1_2		0x80000000
 				MX53_PAD_GPIO_3__USBOH3_USBH1_OC	0x80000000
 			>;
@@ -302,13 +231,6 @@
 			>;
 		};
 
-		pinctrl_i2c2: i2c2grp {
-			fsl,pins = <
-				MX53_PAD_EIM_D16__I2C2_SDA		0xc0000000
-				MX53_PAD_EIM_EB2__I2C2_SCL		0xc0000000
-			>;
-		};
-
 		pinctrl_i2c3: i2c3grp {
 			fsl,pins = <
 				MX53_PAD_GPIO_6__I2C3_SDA		0xc0000000
@@ -353,26 +275,6 @@
 			>;
 		};
 
-		pinctrl_nand: nandgrp {
-			fsl,pins = <
-				MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	0x4
-				MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	0x4
-				MX53_PAD_NANDF_CLE__EMI_NANDF_CLE	0x4
-				MX53_PAD_NANDF_ALE__EMI_NANDF_ALE	0x4
-				MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	0xe0
-				MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	0xe0
-				MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	0x4
-				MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	0xa4
-				MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	0xa4
-				MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	0xa4
-				MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	0xa4
-				MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	0xa4
-				MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	0xa4
-				MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	0xa4
-				MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	0xa4
-			>;
-		};
-
 		pinctrl_pwm1: pwm1grp {
 			fsl,pins = <
 				MX53_PAD_DISP0_DAT8__PWM1_PWMO		0x5
@@ -408,14 +310,6 @@
 	remote-endpoint = <&display1_in>;
 };
 
-&nfc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_nand>;
-	nand-bus-width = <8>;
-	nand-ecc-mode = "hw";
-	status = "okay";
-};
-
 &pwm1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_pwm1>;
@@ -427,7 +321,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
@@ -450,6 +343,8 @@
 };
 
 &usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb>;
 	vbus-supply = <&reg_usbh1_vbus>;
 	phy_type = "utmi";
 	status = "okay";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-mba53.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-mba53.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-mba53.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-mba53.dts	2014-09-28 17:29:07.000000000 -0400
@@ -225,7 +225,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-qsb-common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-qsb-common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-qsb-common.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-qsb-common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -141,7 +141,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-qsrb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-qsrb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-qsrb.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-qsrb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,12 @@
 				MX53_PAD_CSI0_DAT9__I2C1_SCL      0x400001ec
 			>;
 		};
+
+		pinctrl_pmic: pmicgrp {
+			fsl,pins = <
+				MX53_PAD_CSI0_DAT5__GPIO5_23	0x1e4 /* IRQ */
+			>;
+		};
 	};
 };
 
@@ -38,6 +44,8 @@
 
 	pmic: mc34708@8 {
 		compatible = "fsl,mc34708";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
 		reg = <0x08>;
 		interrupt-parent = <&gpio5>;
 		interrupts = <23 0x8>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-tx53.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-tx53.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-tx53.dtsi	2014-08-07 04:47:04.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-tx53.dtsi	2014-09-28 21:27:41.000000000 -0400
@@ -502,7 +502,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	codec-handle = <&sgtl5000>;
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-voipac-bsb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-voipac-bsb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx53-voipac-bsb.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx53-voipac-bsb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -154,6 +154,5 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-aristainetos_4.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-aristainetos_4.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-aristainetos_4.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-aristainetos.dtsi"
+
+/ {
+	model = "aristainetos i.MX6 Dual Lite Board 4";
+	compatible = "fsl,imx6dl";
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		enable-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight>;
+		status = "okay";
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	soc {
+		display0: display@di0 {
+			compatible = "fsl,imx-parallel-display";
+			interface-pix-fmt = "rgb24";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_ipu_disp>;
+			status = "okay";
+
+			display-timings {
+				480x800p60 {
+					native-mode;
+					clock-frequency = <30000000>;
+					hactive = <480>;
+					vactive = <800>;
+					hfront-porch = <59>;
+					hback-porch = <10>;
+					hsync-len = <10>;
+					vback-porch = <15>;
+					vfront-porch = <15>;
+					vsync-len = <15>;
+					hsync-active = <1>;
+					vsync-active = <1>;
+				};
+			};
+
+			port {
+				display0_in: endpoint {
+					remote-endpoint = <&ipu1_di0_disp0>;
+				};
+			};
+		};
+	};
+};
+
+&ecspi2 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-aristainetos_7.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-aristainetos_7.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-aristainetos_7.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-aristainetos.dtsi"
+
+/ {
+	model = "aristainetos i.MX6 Dual Lite Board 7";
+	compatible = "fsl,imx6dl";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	soc {
+		display0: display@di0 {
+			compatible = "fsl,imx-parallel-display";
+			interface-pix-fmt = "rgb24";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_ipu_disp>;
+			status = "okay";
+
+			display-timings {
+				800x480p60 {
+					native-mode;
+					clock-frequency = <33246000>;
+					hactive = <800>;
+					vactive = <480>;
+					hfront-porch = <88>;
+					hback-porch = <88>;
+					hsync-len = <80>;
+					vback-porch = <10>;
+					vfront-porch = <10>;
+					vsync-len = <25>;
+					vsync-active = <1>;
+				};
+			};
+
+			port {
+				display0_in: endpoint {
+					remote-endpoint = <&ipu1_di0_disp0>;
+				};
+			};
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm3 0 3000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,11 @@
 				396000	1175000
 			>;
 			clock-latency = <61036>; /* two CLK32 periods */
-			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
-				 <&clks 17>, <&clks 170>;
+			clocks = <&clks IMX6QDL_CLK_ARM>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+				 <&clks IMX6QDL_CLK_STEP>,
+				 <&clks IMX6QDL_CLK_PLL1_SW>,
+				 <&clks IMX6QDL_CLK_PLL1_SYS>;
 			clock-names = "arm", "pll2_pfd2_396m", "step",
 				      "pll1_sw", "pll1_sys";
 			arm-supply = <&reg_arm>;
@@ -56,7 +59,7 @@
 		ocram: sram@00900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
-			clocks = <&clks 142>;
+			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
 		aips1: aips-bus@02000000 {
@@ -87,7 +90,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021f8000 0x4000>;
 				interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 116>;
+				clocks = <&clks IMX6DL_CLK_I2C4>;
 				status = "disabled";
 			};
 		};
@@ -104,9 +107,9 @@
 };
 
 &ldb {
-	clocks = <&clks 33>, <&clks 34>,
-		 <&clks 39>, <&clks 40>,
-		 <&clks 135>, <&clks 136>;
+	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_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
 	clock-names = "di0_pll", "di1_pll",
 		      "di0_sel", "di1_sel",
 		      "di0", "di1";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw51xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw51xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw51xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw51xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@
 #include "imx6qdl-gw51xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 DualLite GW51XX";
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW51XX";
 	compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw52xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw52xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw52xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw52xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@
 #include "imx6qdl-gw52xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 DualLite GW52XX";
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW52XX";
 	compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw53xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw53xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw53xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw53xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@
 #include "imx6qdl-gw53xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 DualLite GW53XX";
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW53XX";
 	compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw54xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw54xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-gw54xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-gw54xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@
 #include "imx6qdl-gw54xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 DualLite GW54XX";
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW54XX";
 	compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-hummingboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-hummingboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@
 
 	sound-spdif {
 		compatible = "fsl,imx-audio-spdif";
-		model = "imx-spdif";
+		model = "On-board SPDIF";
 		/* IMX6 doesn't implement this yet */
 		spdif-controller = <&spdif>;
 		spdif-out;
@@ -181,11 +181,13 @@
 };
 
 &usbh1 {
+	disable-over-current;
 	vbus-supply = <&reg_usbh1_vbus>;
 	status = "okay";
 };
 
 &usbotg {
+	disable-over-current;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
 	vbus-supply = <&reg_usbotg_vbus>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-rex-basic.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-rex-basic.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-rex-basic.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-rex-basic.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@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.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-rex.dtsi"
+
+/ {
+	model = "Rex Basic i.MX6 Dual Lite Board";
+	compatible = "rex,imx6dl-rex-basic", "fsl,imx6dl";
+
+	memory {
+		reg = <0x10000000 0x20000000>;
+	};
+};
+
+&ecspi3 {
+	flash: m25p80@0 {
+		compatible = "sst,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -254,7 +254,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
@@ -335,10 +334,10 @@
 	imx6-riotboard {
 		pinctrl_audmux: audmuxgrp {
 			fsl,pins = <
-				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x8000000
-				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x8000000
-				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x8000000
-				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x8000000
+				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
 				MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0		/* CAM_MCLK */
 			>;
 		};
@@ -376,7 +375,7 @@
 			fsl,pins = <
 				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
 				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
-				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x80000000
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
 				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
 				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
 				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
@@ -389,9 +388,9 @@
 				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0		/* AR8035 pin strapping: MODE#1: pull up */
 				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0		/* 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	0xc0000000	/* GPIO16 -> AR8035 25MHz */
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8	/* GPIO16 -> AR8035 25MHz */
 			        MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0		/* RGMII_nRST */
-				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x80000000	/* AR8035 interrupt */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x180b0		/* AR8035 interrupt */
 				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
 			>;
 		};
@@ -426,8 +425,8 @@
 
 		pinctrl_led: ledgrp {
 			fsl,pins = <
-				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x80000000	/* user led0 */
-				MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x80000000	/* user led1 */
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1	/* user led0 */
+				MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x1b0b1	/* user led1 */
 			>;
 		};
 
@@ -493,8 +492,8 @@
 		pinctrl_usbotg: usbotggrp {
 			fsl,pins = <
 				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
-				MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x80000000	/* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
-				MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x80000000
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x000b0	/* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
+				MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x1b0b0
 			>;
 		};
 
@@ -506,8 +505,8 @@
 				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
 				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
-				MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x80000000	/* SD2 CD */
-				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x80000000	/* SD2 WP */
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0	/* SD2 CD */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1f0b0	/* SD2 WP */
 			>;
 		};
 
@@ -519,8 +518,8 @@
 				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
 				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
 				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
-				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x80000000	/* SD3 CD */
-				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x80000000	/* SD3 WP */
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0	/* SD3 CD */
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1f0b0	/* SD3 WP */
 			>;
 		};
 
@@ -532,7 +531,7 @@
 				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
 				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
 				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
-				MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x80000000	/* SD4 RST (eMMC) */
+				MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x17059	/* SD4 RST (eMMC) */
 			>;
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6DL Module on CoMpact TFT";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&ET070001DM6>;
+
+			ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+        };
+};
+
+&can1 {
+	status = "disabled";
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+	status = "disabled";
+};
+
+&reg_can_xcvr {
+	status = "disabled";
+};
+
+&touchscreen {
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6U-801x Module";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+        };
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6U-811x Module";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &lvds0;
+		lvds0 = &lvds0;
+		lvds1 = &lvds1;
+	};
+
+	backlight0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_lcd0_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	backlight1: backlight1 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 500000 0>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+};
+
+&i2c3 {
+	polytouch2: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <22 0>;
+		wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		linux,wakeup;
+	};
+};
+
+&iomuxc {
+	imx6dl-tx6u-811x {
+		pinctrl_eeti: eetigrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+			>;
+		};
+	};
+};
+
+&kpp {
+	status = "disabled"; /* pad conflict with backlight1 PWM */
+};
+
+&ldb {
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds_timing0>;
+			lvds_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "disabled";
+
+		display-timings {
+			native-mode = <&lvds_timing1>;
+			lvds_timing1: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-wandboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-wandboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-wandboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-wandboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@
  */
 /dts-v1/;
 #include "imx6dl.dtsi"
-#include "imx6qdl-wandboard.dtsi"
+#include "imx6qdl-wandboard-revc1.dtsi"
 
 / {
 	model = "Wandboard i.MX6 Dual Lite Board";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-wandboard-revb1.dtsi"
+
+/ {
+	model = "Wandboard i.MX6 Dual Lite Board";
+	compatible = "wand,imx6dl-wandboard", "fsl,imx6dl";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-cubox-i.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-cubox-i.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-09-28 17:29:07.000000000 -0400
@@ -13,4 +13,8 @@
 
 &sata {
 	status = "okay";
+	fsl,transmit-level-mV = <1104>;
+	fsl,transmit-boost-mdB = <0>;
+	fsl,transmit-atten-16ths = <9>;
+	fsl,no-spread-spectrum;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,418 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_2p5v: regulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usbh1_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			enable-active-high;
+			gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_aristainetos_usbh1_vbus>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+
+		reg_usbotg_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			enable-active-high;
+			gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_aristainetos_usbotg_vbus>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	tmp103: tmp103@71 {
+		compatible = "ti,tmp103";
+		reg = <0x71>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	rtc@68 {
+		compatible = "dallas,m41t00";
+		reg = <0x68>;
+	};
+};
+
+&ecspi4 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 20 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi4>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "micron,n25q128a11";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&pcie {
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usbotg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	vmmc-supply = <&reg_3p3v>;
+	cd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	vmmc-supply = <&reg_3p3v>;
+	cd-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog &pinctrl_gpio>;
+
+	imx6qdl-aristainetos {
+		pinctrl_aristainetos_usbh1_vbus: aristainetos-usbh1-vbus {
+			fsl,pins = <MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0>;
+		};
+
+		pinctrl_aristainetos_usbotg_vbus: aristainetos-usbotg-vbus {
+			fsl,pins = <MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD  0x1b0b0
+				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC  0x1b0b0
+				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD  0x1b0b0
+				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x1b0b0
+			>;
+		};
+
+		pinctrl_backlight: backlightgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_9__PWM1_OUT	0x1b0b0
+				MX6QDL_PAD_SD4_DAT1__PWM3_OUT	0x1b0b0
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02	0x1b0b0
+			>;
+		};
+
+		pinctrl_ecspi2: ecspi2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
+				MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
+				MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
+				MX6QDL_PAD_EIM_D24__GPIO3_IO24  0x100b1
+			>;
+		};
+
+		pinctrl_ecspi4: ecspi4grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
+				MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x100b1
+				MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
+				MX6QDL_PAD_EIM_D20__GPIO3_IO20  0x100b1
+				MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 /* WP pin */
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO  0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC    0x1b0b0
+				MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+				MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+				MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN   0x1b0b0
+				MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER   0x1b0b0
+				MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+				MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+				MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN  0x1b0b0
+			>;
+		};
+
+		pinctrl_flexcan1: flexcan1grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b0
+				MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b0
+			>;
+		};
+
+		pinctrl_flexcan2: flexcan2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX	0x1b0b0
+				MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX	0x1b0b0
+				>;
+		};
+
+		pinctrl_gpio: gpiogrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT2__GPIO2_IO10	0x1b0b0
+				MX6QDL_PAD_SD4_DAT3__GPIO2_IO11	0x1b0b0
+				MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
+				MX6QDL_PAD_SD4_DAT5__GPIO2_IO13	0x1b0b0
+				MX6QDL_PAD_GPIO_3__GPIO1_IO03	0x1b0b0
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04	0x1b0b0
+				MX6QDL_PAD_GPIO_5__GPIO1_IO05	0x1b0b0
+				MX6QDL_PAD_GPIO_6__GPIO1_IO06	0x1b0b0
+				MX6QDL_PAD_GPIO_7__GPIO1_IO07	0x1b0b0
+				MX6QDL_PAD_GPIO_8__GPIO1_IO08	0x1b0b0
+				MX6QDL_PAD_KEY_COL0__GPIO4_IO06	0x1b0b0
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			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_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29   0x10
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+				MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 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_EIM_D17__I2C3_SCL 0x4001b8b1
+				MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_ipu_disp: ipudisp1grp {
+			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_DI0_PIN4__GPIO4_IO20			0x20000
+				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_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+				MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+				MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
+				MX6QDL_PAD_CSI0_DAT15__UART5_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    0x17059
+				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+				MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+				MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x1b0b0
+			>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@
 
 	sound-spdif {
 		compatible = "fsl,imx-audio-spdif";
-		model = "imx-spdif";
+		model = "Integrated SPDIF";
 		/* IMX6 doesn't implement this yet */
 		spdif-controller = <&spdif>;
 		spdif-out;
@@ -130,16 +130,23 @@
 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
 		};
 
+		pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
+			fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
+		};
+
 		pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
 			fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
 		};
 
-		pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id {
+		pinctrl_cubox_i_usbotg: cubox-i-usbotg {
 			/*
-			 * The Cubox-i pulls this low, but as it's pointless
+			 * The Cubox-i pulls ID low, but as it's pointless
 			 * leaving it as a pull-up, even if it is just 10uA.
 			 */
-			fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
+				MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+			>;
 		};
 
 		pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
@@ -173,13 +180,15 @@
 };
 
 &usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
 	vbus-supply = <&reg_usbh1_vbus>;
 	status = "okay";
 };
 
 &usbotg {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>;
+	pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
 	vbus-supply = <&reg_usbotg_vbus>;
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2014-08-07 04:47:06.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2014-09-28 21:27:43.000000000 -0400
@@ -10,6 +10,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/clock/imx6qdl-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #include "skeleton.dtsi"
@@ -94,7 +95,7 @@
 			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
 			#dma-cells = <1>;
 			dma-channels = <4>;
-			clocks = <&clks 106>;
+			clocks = <&clks IMX6QDL_CLK_APBH_DMA>;
 		};
 
 		gpmi: gpmi-nand@00112000 {
@@ -105,8 +106,11 @@
 			reg-names = "gpmi-nand", "bch";
 			interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "bch";
-			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
-				 <&clks 150>, <&clks 149>;
+			clocks = <&clks IMX6QDL_CLK_GPMI_IO>,
+				 <&clks IMX6QDL_CLK_GPMI_APB>,
+				 <&clks IMX6QDL_CLK_GPMI_BCH>,
+				 <&clks IMX6QDL_CLK_GPMI_BCH_APB>,
+				 <&clks IMX6QDL_CLK_PER1_BCH>;
 			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
 				      "gpmi_bch_apb", "per1_bch";
 			dmas = <&dma_apbh 0>;
@@ -118,7 +122,7 @@
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0x00a00600 0x20>;
 			interrupts = <1 13 0xf01>;
-			clocks = <&clks 15>;
+			clocks = <&clks IMX6QDL_CLK_TWD>;
 		};
 
 		L2: l2-cache@00a02000 {
@@ -149,7 +153,9 @@
 			                <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
 			                <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
 			                <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clks 144>, <&clks 206>, <&clks 189>;
+			clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
+				 <&clks IMX6QDL_CLK_LVDS1_GATE>,
+				 <&clks IMX6QDL_CLK_PCIE_REF_125M>;
 			clock-names = "pcie", "pcie_bus", "pcie_phy";
 			status = "disabled";
 		};
@@ -180,11 +186,11 @@
 					dmas = <&sdma 14 18 0>,
 					       <&sdma 15 18 0>;
 					dma-names = "rx", "tx";
-					clocks = <&clks 197>, <&clks 3>,
-						 <&clks 197>, <&clks 107>,
-						 <&clks 0>,   <&clks 118>,
-						 <&clks 0>,  <&clks 139>,
-						 <&clks 0>;
+					clocks = <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_OSC>,
+						 <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_DUMMY>,
+						 <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>,
+						 <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>,
+						 <&clks IMX6QDL_CLK_DUMMY>;
 					clock-names = "core",  "rxtx0",
 						      "rxtx1", "rxtx2",
 						      "rxtx3", "rxtx4",
@@ -199,7 +205,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02008000 0x4000>;
 					interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 112>, <&clks 112>;
+					clocks = <&clks IMX6QDL_CLK_ECSPI1>,
+						 <&clks IMX6QDL_CLK_ECSPI1>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
 					dma-names = "rx", "tx";
@@ -212,7 +219,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x0200c000 0x4000>;
 					interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 113>, <&clks 113>;
+					clocks = <&clks IMX6QDL_CLK_ECSPI2>,
+						 <&clks IMX6QDL_CLK_ECSPI2>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
 					dma-names = "rx", "tx";
@@ -225,7 +233,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02010000 0x4000>;
 					interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 114>, <&clks 114>;
+					clocks = <&clks IMX6QDL_CLK_ECSPI3>,
+						 <&clks IMX6QDL_CLK_ECSPI3>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
 					dma-names = "rx", "tx";
@@ -238,7 +247,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02014000 0x4000>;
 					interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 115>, <&clks 115>;
+					clocks = <&clks IMX6QDL_CLK_ECSPI4>,
+						 <&clks IMX6QDL_CLK_ECSPI4>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
 					dma-names = "rx", "tx";
@@ -249,7 +259,8 @@
 					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02020000 0x4000>;
 					interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 160>, <&clks 161>;
+					clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+						 <&clks IMX6QDL_CLK_UART_SERIAL>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
 					dma-names = "rx", "tx";
@@ -263,46 +274,40 @@
 
 				ssi1: ssi@02028000 {
 					compatible = "fsl,imx6q-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x02028000 0x4000>;
 					interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 178>;
+					clocks = <&clks IMX6QDL_CLK_SSI1_IPG>;
 					dmas = <&sdma 37 1 0>,
 					       <&sdma 38 1 0>;
 					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <38 37>;
 					status = "disabled";
 				};
 
 				ssi2: ssi@0202c000 {
 					compatible = "fsl,imx6q-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x0202c000 0x4000>;
 					interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 179>;
+					clocks = <&clks IMX6QDL_CLK_SSI2_IPG>;
 					dmas = <&sdma 41 1 0>,
 					       <&sdma 42 1 0>;
 					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <42 41>;
 					status = "disabled";
 				};
 
 				ssi3: ssi@02030000 {
 					compatible = "fsl,imx6q-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x02030000 0x4000>;
 					interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 180>;
+					clocks = <&clks IMX6QDL_CLK_SSI3_IPG>;
 					dmas = <&sdma 45 1 0>,
 					       <&sdma 46 1 0>;
 					dma-names = "rx", "tx";
 					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <46 45>;
 					status = "disabled";
 				};
 
@@ -331,7 +336,8 @@
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02080000 0x4000>;
 				interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 62>, <&clks 145>;
+				clocks = <&clks IMX6QDL_CLK_IPG>,
+					 <&clks IMX6QDL_CLK_PWM1>;
 				clock-names = "ipg", "per";
 			};
 
@@ -340,7 +346,8 @@
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02084000 0x4000>;
 				interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 62>, <&clks 146>;
+				clocks = <&clks IMX6QDL_CLK_IPG>,
+					 <&clks IMX6QDL_CLK_PWM2>;
 				clock-names = "ipg", "per";
 			};
 
@@ -349,7 +356,8 @@
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02088000 0x4000>;
 				interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 62>, <&clks 147>;
+				clocks = <&clks IMX6QDL_CLK_IPG>,
+					 <&clks IMX6QDL_CLK_PWM3>;
 				clock-names = "ipg", "per";
 			};
 
@@ -358,7 +366,8 @@
 				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x0208c000 0x4000>;
 				interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 62>, <&clks 148>;
+				clocks = <&clks IMX6QDL_CLK_IPG>,
+					 <&clks IMX6QDL_CLK_PWM4>;
 				clock-names = "ipg", "per";
 			};
 
@@ -366,7 +375,8 @@
 				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02090000 0x4000>;
 				interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 108>, <&clks 109>;
+				clocks = <&clks IMX6QDL_CLK_CAN1_IPG>,
+					 <&clks IMX6QDL_CLK_CAN1_SERIAL>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -375,7 +385,8 @@
 				compatible = "fsl,imx6q-flexcan";
 				reg = <0x02094000 0x4000>;
 				interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 110>, <&clks 111>;
+				clocks = <&clks IMX6QDL_CLK_CAN2_IPG>,
+					 <&clks IMX6QDL_CLK_CAN2_SERIAL>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -384,7 +395,8 @@
 				compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 119>, <&clks 120>;
+				clocks = <&clks IMX6QDL_CLK_GPT_IPG>,
+					 <&clks IMX6QDL_CLK_GPT_IPG_PER>;
 				clock-names = "ipg", "per";
 			};
 
@@ -466,22 +478,25 @@
 			};
 
 			kpp: kpp@020b8000 {
+				compatible = "fsl,imx6q-kpp", "fsl,imx21-kpp";
 				reg = <0x020b8000 0x4000>;
 				interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6QDL_CLK_IPG>;
+				status = "disabled";
 			};
 
 			wdog1: wdog@020bc000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020bc000 0x4000>;
 				interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX6QDL_CLK_DUMMY>;
 			};
 
 			wdog2: wdog@020c0000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020c0000 0x4000>;
 				interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 0>;
+				clocks = <&clks IMX6QDL_CLK_DUMMY>;
 				status = "disabled";
 			};
 
@@ -599,14 +614,14 @@
 				interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
 				fsl,tempmon = <&anatop>;
 				fsl,tempmon-data = <&ocotp>;
-				clocks = <&clks 172>;
+				clocks = <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
 			};
 
 			usbphy1: usbphy@020c9000 {
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020c9000 0x1000>;
 				interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 182>;
+				clocks = <&clks IMX6QDL_CLK_USBPHY1>;
 				fsl,anatop = <&anatop>;
 			};
 
@@ -614,7 +629,7 @@
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020ca000 0x1000>;
 				interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 183>;
+				clocks = <&clks IMX6QDL_CLK_USBPHY2>;
 				fsl,anatop = <&anatop>;
 			};
 
@@ -727,7 +742,8 @@
 				reg = <0x00120000 0x9000>;
 				interrupts = <0 115 0x04>;
 				gpr = <&gpr>;
-				clocks = <&clks 123>, <&clks 124>;
+				clocks = <&clks IMX6QDL_CLK_HDMI_IAHB>,
+					 <&clks IMX6QDL_CLK_HDMI_ISFR>;
 				clock-names = "iahb", "isfr";
 				status = "disabled";
 
@@ -762,7 +778,8 @@
 				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
 				reg = <0x020ec000 0x4000>;
 				interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 155>, <&clks 155>;
+				clocks = <&clks IMX6QDL_CLK_SDMA>,
+					 <&clks IMX6QDL_CLK_SDMA>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
@@ -790,7 +807,7 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184000 0x200>;
 				interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 162>;
+				clocks = <&clks IMX6QDL_CLK_USBOH3>;
 				fsl,usbphy = <&usbphy1>;
 				fsl,usbmisc = <&usbmisc 0>;
 				status = "disabled";
@@ -800,7 +817,7 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
 				interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 162>;
+				clocks = <&clks IMX6QDL_CLK_USBOH3>;
 				fsl,usbphy = <&usbphy2>;
 				fsl,usbmisc = <&usbmisc 1>;
 				status = "disabled";
@@ -810,7 +827,7 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
 				interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 162>;
+				clocks = <&clks IMX6QDL_CLK_USBOH3>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
 			};
@@ -819,7 +836,7 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184600 0x200>;
 				interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 162>;
+				clocks = <&clks IMX6QDL_CLK_USBOH3>;
 				fsl,usbmisc = <&usbmisc 3>;
 				status = "disabled";
 			};
@@ -828,7 +845,7 @@
 				#index-cells = <1>;
 				compatible = "fsl,imx6q-usbmisc";
 				reg = <0x02184800 0x200>;
-				clocks = <&clks 162>;
+				clocks = <&clks IMX6QDL_CLK_USBOH3>;
 			};
 
 			fec: ethernet@02188000 {
@@ -837,7 +854,9 @@
 				interrupts-extended =
 					<&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
 					<&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 117>, <&clks 117>, <&clks 190>;
+				clocks = <&clks IMX6QDL_CLK_ENET>,
+					 <&clks IMX6QDL_CLK_ENET>,
+					 <&clks IMX6QDL_CLK_ENET_REF>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
@@ -853,7 +872,9 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02190000 0x4000>;
 				interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
+				clocks = <&clks IMX6QDL_CLK_USDHC1>,
+					 <&clks IMX6QDL_CLK_USDHC1>,
+					 <&clks IMX6QDL_CLK_USDHC1>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
 				status = "disabled";
@@ -863,7 +884,9 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02194000 0x4000>;
 				interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
+				clocks = <&clks IMX6QDL_CLK_USDHC2>,
+					 <&clks IMX6QDL_CLK_USDHC2>,
+					 <&clks IMX6QDL_CLK_USDHC2>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
 				status = "disabled";
@@ -873,7 +896,9 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02198000 0x4000>;
 				interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
+				clocks = <&clks IMX6QDL_CLK_USDHC3>,
+					 <&clks IMX6QDL_CLK_USDHC3>,
+					 <&clks IMX6QDL_CLK_USDHC3>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
 				status = "disabled";
@@ -883,7 +908,9 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x0219c000 0x4000>;
 				interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
+				clocks = <&clks IMX6QDL_CLK_USDHC4>,
+					 <&clks IMX6QDL_CLK_USDHC4>,
+					 <&clks IMX6QDL_CLK_USDHC4>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
 				status = "disabled";
@@ -895,7 +922,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a0000 0x4000>;
 				interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 125>;
+				clocks = <&clks IMX6QDL_CLK_I2C1>;
 				status = "disabled";
 			};
 
@@ -905,7 +932,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a4000 0x4000>;
 				interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 126>;
+				clocks = <&clks IMX6QDL_CLK_I2C2>;
 				status = "disabled";
 			};
 
@@ -915,7 +942,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a8000 0x4000>;
 				interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 127>;
+				clocks = <&clks IMX6QDL_CLK_I2C3>;
 				status = "disabled";
 			};
 
@@ -936,7 +963,7 @@
 				compatible = "fsl,imx6q-weim";
 				reg = <0x021b8000 0x4000>;
 				interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 196>;
+				clocks = <&clks IMX6QDL_CLK_EIM_SLOW>;
 			};
 
 			ocotp: ocotp@021bc000 {
@@ -996,7 +1023,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021e8000 0x4000>;
 				interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 160>, <&clks 161>;
+				clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+					 <&clks IMX6QDL_CLK_UART_SERIAL>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
 				dma-names = "rx", "tx";
@@ -1007,7 +1035,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021ec000 0x4000>;
 				interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 160>, <&clks 161>;
+				clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+					 <&clks IMX6QDL_CLK_UART_SERIAL>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
 				dma-names = "rx", "tx";
@@ -1018,7 +1047,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f0000 0x4000>;
 				interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 160>, <&clks 161>;
+				clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+					 <&clks IMX6QDL_CLK_UART_SERIAL>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
 				dma-names = "rx", "tx";
@@ -1029,7 +1059,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f4000 0x4000>;
 				interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks 160>, <&clks 161>;
+				clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+					 <&clks IMX6QDL_CLK_UART_SERIAL>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
 				dma-names = "rx", "tx";
@@ -1044,10 +1075,20 @@
 			reg = <0x02400000 0x400000>;
 			interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
 				     <0 5 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clks 130>, <&clks 131>, <&clks 132>;
+			clocks = <&clks IMX6QDL_CLK_IPU1>,
+				 <&clks IMX6QDL_CLK_IPU1_DI0>,
+				 <&clks IMX6QDL_CLK_IPU1_DI1>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
 
+			ipu1_csi0: port@0 {
+				reg = <0>;
+			};
+
+			ipu1_csi1: port@1 {
+				reg = <1>;
+			};
+
 			ipu1_di0: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -121,9 +121,9 @@
 	};
 
 	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+		compatible = "fsl,imx6q-ventana-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-sgtl5000";
+		model = "sgtl5000-audio";
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -489,7 +489,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -124,9 +124,9 @@
 	};
 
 	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+		compatible = "fsl,imx6q-ventana-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-sgtl5000";
+		model = "sgtl5000-audio";
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -533,7 +533,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -114,9 +114,9 @@
 	};
 
 	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+		compatible = "fsl,imx6q-ventana-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-sgtl5000";
+		model = "sgtl5000-audio";
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -555,12 +555,10 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,7 @@
 	enet {
 		pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 {
 			fsl,pins = <
-				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b8b0
 				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
 				/* AR8035 reset */
 				MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x130b0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -381,7 +381,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -301,6 +301,7 @@
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
 	phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+	phy-supply = <&vdd_eth_io_reg>;
 	status = "disabled";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3p3v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usbh1_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbh1>;
+			regulator-name = "usbh1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usb_otg_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbotg>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		led0: usr {
+			label = "usr";
+			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6-rex-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6-rex-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";
+};
+
+&ecspi2 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2>;
+	status = "okay";
+};
+
+&ecspi3 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+	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";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	eeprom@57 {
+		compatible = "at,24c02";
+		reg = <0x57>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-rex {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* SGTL5000 sys_mclk */
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x030b0
+			>;
+		};
+
+		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_ecspi2: ecspi2grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+				/* CS */
+				MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26	0x000b1
+			>;
+		};
+
+		pinctrl_ecspi3: ecspi3grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK	0x100b1
+				/* CS */
+				MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	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		0x1b0b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+				/* Phy reset */
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25	0x000b0
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT8__I2C1_SDA		0x4001b8b1
+				MX6QDL_PAD_CSI0_DAT9__I2C1_SCL		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_EIM_D17__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D18__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_led: ledgrp {
+			fsl,pins = <
+				/* user led */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x80000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				/* power enable, high active */
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x10b0
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+				MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x1b0b0
+				/* power enable, high active */
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x10b0
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+				/* CD */
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+				/* WP */
+				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1f0b0
+			>;
+		};
+
+		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
+				/* CD */
+				MX6QDL_PAD_NANDF_D0__GPIO2_IO00		0x1b0b0
+				/* WP */
+				MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1f0b0
+			>;
+		};
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -381,7 +381,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -340,6 +340,7 @@
 				MX6QDL_PAD_KEY_COL1__ECSPI1_MISO	0x100b1
 				MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI	0x100b1
 				MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK	0x100b1
+				MX6QDL_PAD_KEY_ROW1__GPIO4_IO09		0x1b0b0
 			>;
 		};
 
@@ -512,7 +513,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,696 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	aliases {
+		can0 = &can2;
+		can1 = &can1;
+		ethernet0 = &fec;
+		lcdif_23bit_pins_a = &pinctrl_disp0_1;
+		lcdif_24bit_pins_a = &pinctrl_disp0_2;
+		pwm0 = &pwm1;
+		pwm1 = &pwm2;
+		reg_can_xcvr = &reg_can_xcvr;
+		stk5led = &user_led;
+		usbotg = &usbotg;
+		sdhc0 = &usdhc1;
+		sdhc1 = &usdhc2;
+	};
+
+	memory {
+		reg = <0 0>; /* will be filled by U-Boot */
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mclk: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <27000000>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+			linux,code = <KEY_POWER>;
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user_led: user {
+			label = "Heartbeat";
+			gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_3v3_etn: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "3V3_ETN";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_etnphy_power>;
+			gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_2v5: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "2V5";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3v3: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_can_xcvr: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "CAN XCVR";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_flexcan_xcvr>;
+			gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+			enable-active-low;
+		};
+
+		reg_lcd0_pwr: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "LCD0 POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_lcd0_pwr>;
+			gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		reg_lcd1_pwr: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "LCD1 POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_lcd1_pwr>;
+			gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		reg_usbh1_vbus: regulator@6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "usbh1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbh1_vbus>;
+			gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usbotg_vbus: regulator@7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "usbotg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usbotg_vbus>;
+			gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "karo,imx6qdl-tx6qdl-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "sgtl5000-audio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_audmux>;
+		ssi-controller = <&ssi1>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <5>;
+	};
+};
+
+&audmux {
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <
+		&gpio2 30 GPIO_ACTIVE_HIGH
+		&gpio3 19 GPIO_ACTIVE_HIGH
+	>;
+	status = "okay";
+
+	spidev0: spi@0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <54000000>;
+	};
+
+	spidev1: spi@1 {
+		compatible = "spidev";
+		reg = <1>;
+		spi-max-frequency = <54000000>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>;
+	phy-supply = <&reg_3v3_etn>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	fsl,no-blockmark-swap;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	ds1339: rtc@68 {
+		compatible = "dallas,ds1339";
+		reg = <0x68>;
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	sgtl5000: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_2v5>;
+		VDDIO-supply = <&reg_3v3>;
+		clocks = <&mclk>;
+	};
+
+	polytouch: edt-ft5x06@38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_edt_ft5x06>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <15 0>;
+		reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+		wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+		linux,wakeup;
+	};
+
+	touchscreen: tsc2007@48 {
+		compatible = "ti,tsc2007";
+		reg = <0x48>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2007>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <26 0>;
+		gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;
+		ti,x-plate-ohms = <660>;
+		linux,wakeup;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-tx6 {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A18__GPIO2_IO20		0x1b0b1 /* LED */
+				MX6QDL_PAD_SD3_DAT2__GPIO7_IO06		0x1b0b1 /* ETN PHY RESET */
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b1 /* ETN PHY INT */
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1 /* PWR BTN */
+			>;
+		};
+
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW1__AUD5_RXD		0x130b0 /* SSI1_RXD */
+				MX6QDL_PAD_KEY_ROW0__AUD5_TXD		0x110b0 /* SSI1_TXD */
+				MX6QDL_PAD_KEY_COL0__AUD5_TXC		0x130b0 /* SSI1_CLK */
+				MX6QDL_PAD_KEY_COL1__AUD5_TXFS		0x130b0 /* SSI1_FS */
+			>;
+		};
+
+		pinctrl_disp0_1: disp0grp-1 {
+			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
+				/* PAD DISP0_DAT0 is used for the Flexcan transceiver control */
+				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_disp0_2: disp0grp-2 {
+			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_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x0b0b0
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x0b0b0
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x0b0b0
+				MX6QDL_PAD_GPIO_19__ECSPI1_RDY		0x0b0b0
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x0b0b0 /* SPI CS0 */
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x0b0b0 /* SPI CS1 */
+			>;
+		};
+
+		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 */
+			>;
+		};
+
+		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
+			>;
+		};
+
+		pinctrl_etnphy_power: etnphy-pwrgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D20__GPIO3_IO20		0x1b0b1 /* ETN PHY POWER */
+			>;
+		};
+
+		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_flexcan_xcvr: flexcan-xcvrgrp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21	0x1b0b0 /* Flexcan XCVR enable */
+			>;
+		};
+
+		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_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
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_kpp: kppgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_9__KEY_COL6		0x1b0b1
+				MX6QDL_PAD_GPIO_4__KEY_COL7		0x1b0b1
+				MX6QDL_PAD_KEY_COL2__KEY_COL2		0x1b0b1
+				MX6QDL_PAD_KEY_COL3__KEY_COL3		0x1b0b1
+				MX6QDL_PAD_GPIO_2__KEY_ROW6		0x1b0b1
+				MX6QDL_PAD_GPIO_5__KEY_ROW7		0x1b0b1
+				MX6QDL_PAD_KEY_ROW2__KEY_ROW2		0x1b0b1
+				MX6QDL_PAD_KEY_ROW3__KEY_ROW3		0x1b0b1
+			>;
+		};
+
+		pinctrl_lcd0_pwr: lcd0-pwrgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x1b0b1 /* LCD Reset */
+			>;
+		};
+
+		pinctrl_lcd1_pwr: lcd1-pwrgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_EB3__GPIO2_IO31		0x1b0b1 /* LCD Power Enable */
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm2: pwm2grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__PWM2_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_tsc2007: tsc2007grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__GPIO3_IO26		0x1b0b0 /* Interrupt */
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart1_rtscts: uart1_rtsctsgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT1__UART1_RTS_B	0x1b0b1
+				MX6QDL_PAD_SD3_DAT0__UART1_CTS_B	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2_rtscts: uart2_rtsctsgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B	0x1b0b1
+				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart3_rtscts: uart3_rtsctsgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT3__UART3_CTS_B	0x1b0b1
+				MX6QDL_PAD_SD3_RST__UART3_RTS_B		0x1b0b1
+			>;
+		};
+
+		pinctrl_usbh1_vbus: usbh1-vbusgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x1b0b0 /* USBH1_VBUSEN */
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23		0x17059
+			>;
+		};
+
+		pinctrl_usbotg_vbus: usbotg-vbusgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_7__GPIO1_IO07		0x1b0b0 /* USBOTG_VBUSEN */
+			>;
+		};
+
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x070b1
+				MX6QDL_PAD_SD1_CLK__SD1_CLK		0x070b1
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x070b1
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x070b1
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x070b1
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x070b1
+				MX6QDL_PAD_SD3_CMD__GPIO7_IO02		0x170b0 /* SD1 CD */
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x070b1
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x070b1
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x070b1
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x070b1
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x070b1
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x070b1
+				MX6QDL_PAD_SD3_CLK__GPIO7_IO03		0x170b0 /* SD2 CD */
+			>;
+		};
+	};
+};
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp>;
+	/* sample keymap */
+	/* row/col 0,1 are mapped to KPP row/col 6,7 */
+	linux,keymap = <
+		MATRIX_KEY(6, 6, KEY_POWER) /* 0x06060074 */
+		MATRIX_KEY(6, 7, KEY_KP0) /* 0x06070052 */
+		MATRIX_KEY(6, 2, KEY_KP1) /* 0x0602004f */
+		MATRIX_KEY(6, 3, KEY_KP2) /* 0x06030050 */
+		MATRIX_KEY(7, 6, KEY_KP3) /* 0x07060051 */
+		MATRIX_KEY(7, 7, KEY_KP4) /* 0x0707004b */
+		MATRIX_KEY(7, 2, KEY_KP5) /* 0x0702004c */
+		MATRIX_KEY(7, 3, KEY_KP6) /* 0x0703004d */
+		MATRIX_KEY(2, 6, KEY_KP7) /* 0x02060047 */
+		MATRIX_KEY(2, 7, KEY_KP8) /* 0x02070048 */
+		MATRIX_KEY(2, 2, KEY_KP9) /* 0x02020049 */
+	>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	#pwm-cells = <3>;
+	status = "disabled";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	#pwm-cells = <3>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usbotg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "peripheral";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	bus-width = <4>;
+	no-1-8-v;
+	cd-gpios = <&gpio7 2 0>;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	no-1-8-v;
+	cd-gpios = <&gpio7 3 0>;
+	fsl,wp-controller;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -91,22 +91,8 @@
 
 &iomuxc {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
 
 	imx6qdl-wandboard {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_0__CCM_CLKO1 	 0x130b0
-				MX6QDL_PAD_GPIO_2__GPIO1_IO02	 0x80000000
-				MX6QDL_PAD_EIM_DA9__GPIO3_IO09	 0x80000000
-				MX6QDL_PAD_EIM_EB1__GPIO2_IO29   0x80000000 /* WL_REF_ON */
-				MX6QDL_PAD_EIM_A25__GPIO5_IO02   0x80000000 /* WL_RST_N */
-				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* WL_REG_ON */
-				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
-				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
-				MX6QDL_PAD_EIM_D29__GPIO3_IO29   0x80000000
-			>;
-		};
 
 		pinctrl_audmux: audmuxgrp {
 			fsl,pins = <
@@ -233,7 +219,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
@@ -269,13 +254,6 @@
 	status = "okay";
 };
 
-&usdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2>;
-	non-removable;
-	status = "okay";
-};
-
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include "imx6qdl-wandboard.dtsi"
+
+&iomuxc {
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-wandboard {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0		/* GPIO_0_CLKO */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x80000000	/* uSDHC1 CD */
+				MX6QDL_PAD_EIM_DA9__GPIO3_IO09		0x80000000	/* uSDHC3 CD */
+				MX6QDL_PAD_EIM_EB1__GPIO2_IO29		0x0f0b0		/* WL_REF_ON */
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x0f0b0		/* WL_RST_N */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x000b0		/* WL_REG_ON */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x80000000	/* WL_HOST_WAKE */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x80000000	/* WL_WAKE */
+				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 */				
+			>;
+		};
+	};
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	non-removable;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include "imx6qdl-wandboard.dtsi"
+
+&iomuxc {
+	pinctrl-0 = <&pinctrl_hog>;
+
+	imx6qdl-wandboard {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0		/* GPIO_0_CLKO */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x80000000	/* uSDHC1 CD */
+				MX6QDL_PAD_EIM_DA9__GPIO3_IO09		0x80000000	/* uSDHC3 CD */
+				MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00	0x0f0b0		/* WIFI_ON (reset, active low) */
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x000b0		/* WL_REG_ON (unused) */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x80000000	/* WL_HOST_WAKE, input */
+				MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31	0x0f0b0		/* GPIO5_IO31 (Wifi Power Enable) */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x80000000	/* WL_WAKE (unused) */
+				MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21	0x80000000	/* BT_ON */
+				MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30	0x80000000	/* BT_WAKE */
+				MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20	0x80000000	/* BT_HOST_WAKE */
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x80000000	/* RGMII_nRST */
+			>;
+		};
+	};
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts	2014-09-28 17:29:07.000000000 -0400
@@ -95,6 +95,12 @@
 	};
 };
 
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	status = "okay";
+};
+
 &ecspi5 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_ecspi5>;
@@ -113,11 +119,18 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio3 23 0>;
+	phy-reset-gpios = <&gpio1 25 0>;
 	phy-supply = <&vgen2_1v2_eth>;
 	status = "okay";
 };
 
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+};
+
 &i2c2 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
@@ -274,6 +287,13 @@
 	};
 };
 
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -286,6 +306,13 @@
 			>;
 		};
 
+		pinctrl_can1: can1grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b0
+				MX6QDL_PAD_GPIO_7__FLEXCAN1_TX		0x1b0b0
+			>;
+		};
+
 		pinctrl_ecspi5: ecspi5rp-1 {
 			fsl,pins = <
 				MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO	0x80000000
@@ -312,10 +339,18 @@
 				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_ENET_CRS_DV__GPIO1_IO25	0x1b0b0
 				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
 			>;
 		};
 
+		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
@@ -323,6 +358,19 @@
 			>;
 		};
 
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_pcie: pciegrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__GPIO4_IO08		0x100b1
+			>;
+		};
+
 		pinctrl_pfuze: pfuze100grp1 {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D20__GPIO3_IO20		0x80000000
@@ -385,6 +433,13 @@
 	};
 };
 
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio4 8 0>;
+	status = "okay";
+};
+
 &sata {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -43,8 +43,11 @@
 				396000	1175000
 			>;
 			clock-latency = <61036>; /* two CLK32 periods */
-			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
-				 <&clks 17>, <&clks 170>;
+			clocks = <&clks IMX6QDL_CLK_ARM>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+				 <&clks IMX6QDL_CLK_STEP>,
+				 <&clks IMX6QDL_CLK_PLL1_SW>,
+				 <&clks IMX6QDL_CLK_PLL1_SYS>;
 			clock-names = "arm", "pll2_pfd2_396m", "step",
 				      "pll1_sw", "pll1_sys";
 			arm-supply = <&reg_arm>;
@@ -78,7 +81,7 @@
 		ocram: sram@00900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x40000>;
-			clocks = <&clks 142>;
+			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
 		aips-bus@02000000 { /* AIPS1 */
@@ -89,7 +92,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02018000 0x4000>;
 					interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
-					clocks = <&clks 116>, <&clks 116>;
+					clocks = <&clks IMX6Q_CLK_ECSPI5>,
+						 <&clks IMX6Q_CLK_ECSPI5>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -140,7 +144,9 @@
 			compatible = "fsl,imx6q-ahci";
 			reg = <0x02200000 0x4000>;
 			interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
-			clocks =  <&clks 154>, <&clks 187>, <&clks 105>;
+			clocks = <&clks IMX6QDL_CLK_SATA>,
+				 <&clks IMX6QDL_CLK_SATA_REF_100M>,
+				 <&clks IMX6QDL_CLK_AHB>;
 			clock-names = "sata", "sata_ref", "ahb";
 			status = "disabled";
 		};
@@ -152,10 +158,20 @@
 			reg = <0x02800000 0x400000>;
 			interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
 				     <0 7 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clks 133>, <&clks 134>, <&clks 137>;
+			clocks = <&clks IMX6QDL_CLK_IPU2>,
+				 <&clks IMX6QDL_CLK_IPU2_DI0>,
+				 <&clks IMX6QDL_CLK_IPU2_DI1>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 4>;
 
+			ipu2_csi0: port@0 {
+				reg = <0>;
+			};
+
+			ipu2_csi1: port@1 {
+				reg = <1>;
+			};
+
 			ipu2_di0: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -230,9 +246,10 @@
 };
 
 &ldb {
-	clocks = <&clks 33>, <&clks 34>,
-		 <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
-		 <&clks 135>, <&clks 136>;
+	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>, <&clks IMX6QDL_CLK_LDB_DI1>;
 	clock-names = "di0_pll", "di1_pll",
 		      "di0_sel", "di1_sel", "di2_sel", "di3_sel",
 		      "di0", "di1";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw51xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw51xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw51xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw51xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@
 #include "imx6qdl-gw51xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 Quad GW51XX";
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW51XX";
 	compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw52xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw52xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw52xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw52xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,7 @@
 #include "imx6qdl-gw52xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 Quad GW52XX";
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW52XX";
 	compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw53xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw53xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw53xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw53xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,7 @@
 #include "imx6qdl-gw53xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 Quad GW53XX";
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW53XX";
 	compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts	2014-09-28 17:29:07.000000000 -0400
@@ -115,9 +115,9 @@
 	};
 
 	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+		compatible = "fsl,imx6q-ventana-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-sgtl5000";
+		model = "sgtl5000-audio";
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -504,7 +504,6 @@
 };
 
 &ssi1 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw54xx.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw54xx.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-gw54xx.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-gw54xx.dts	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,7 @@
 #include "imx6qdl-gw54xx.dtsi"
 
 / {
-	model = "Gateworks Ventana i.MX6 Quad GW54XX";
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW54XX";
 	compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-rex-pro.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-rex-pro.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-rex-pro.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-rex-pro.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@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.
+ *
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-rex.dtsi"
+
+/ {
+	model = "Rex Pro i.MX6 Quad Board";
+	compatible = "rex,imx6q-rex-pro", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+};
+
+&ecspi3 {
+	flash: m25p80@0 {
+		compatible = "sst,sst25vf032b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&sata {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1010 Module on CoMpact TFT";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&ET070001DM6>;
+
+			ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+        };
+};
+
+&can1 {
+	status = "disabled";
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+	status = "disabled";
+};
+
+&reg_can_xcvr {
+	status = "disabled";
+};
+
+&touchscreen {
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1010 Module";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+        };
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1020 Module on CoMpact TFT";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&ET070001DM6>;
+
+			ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+        };
+};
+
+&can1 {
+	status = "disabled";
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&iomuxc {
+	imx6qdl-tx6 {
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+				MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+			>;
+		};
+	};
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+	status = "disabled";
+};
+
+&reg_can_xcvr {
+	status = "disabled";
+};
+
+&touchscreen {
+	status = "disabled";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	no-1-8-v;
+	fsl,wp-controller;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1020 Module";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_3v3>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_1>;
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+        };
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&iomuxc {
+	imx6qdl-tx6 {
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+				MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+			>;
+		};
+	};
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	no-1-8-v;
+	fsl,wp-controller;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2014 Lothar WaÃŸmann <LW@KARO-electronics.de>
+ *
+ * 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 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1110 Module";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &lvds0;
+		lvds0 = &lvds0;
+		lvds1 = &lvds1;
+	};
+
+	backlight0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 0>;
+		power-supply = <&reg_lcd0_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+
+	backlight1: backlight1 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 500000 0>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		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>;
+		default-brightness-level = <50>;
+	};
+};
+
+&i2c3 {
+	polytouch1: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <22 0>;
+		wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		linux,wakeup;
+	};
+};
+
+&iomuxc {
+	imx6q-tx6q-1110 {
+		pinctrl_eeti: eetigrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+			>;
+		};
+	};
+};
+
+&kpp {
+	status = "disabled"; /* pad conflict with backlight1 PWM */
+};
+
+&ldb {
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds_timing0>;
+			lvds_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "disabled";
+
+		display-timings {
+			native-mode = <&lvds_timing1>;
+			lvds_timing1: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-udoo.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-udoo.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-udoo.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-udoo.dts	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,23 @@
 	memory {
 		reg = <0x10000000 0x40000000>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_h1_vbus: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
+			gpio = <&gpio7 12 0>;
+		};
+	};
 };
 
 &fec {
@@ -81,6 +98,13 @@
 			>;
 		};
 
+		pinctrl_usbh: usbhgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+				MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+			>;
+		};
+
 		pinctrl_usdhc3: usdhc3grp {
 			fsl,pins = <
 				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
@@ -104,6 +128,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh>;
+	vbus-supply = <&reg_usb_h1_vbus>;
+	clocks = <&clks 201>;
+	status = "okay";
+};
+
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-wandboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-wandboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-wandboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-wandboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@
  */
 /dts-v1/;
 #include "imx6q.dtsi"
-#include "imx6qdl-wandboard.dtsi"
+#include "imx6qdl-wandboard-revc1.dtsi"
 
 / {
 	model = "Wandboard i.MX6 Quad Board";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-wandboard-revb1.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6q-wandboard-revb1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6q-wandboard-revb1.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-wandboard-revb1.dtsi"
+
+/ {
+	model = "Wandboard i.MX6 Quad Board";
+	compatible = "wand,imx6q-wandboard", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+};
+
+&sata {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sl.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sl.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sl.dtsi	2014-08-07 04:47:09.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sl.dtsi	2014-09-28 21:27:46.000000000 -0400
@@ -227,8 +227,7 @@
 
 				ssi1: ssi@02028000 {
 					compatible = "fsl,imx6sl-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x02028000 0x4000>;
 					interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI1>;
@@ -241,8 +240,7 @@
 
 				ssi2: ssi@0202c000 {
 					compatible = "fsl,imx6sl-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x0202c000 0x4000>;
 					interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI2>;
@@ -255,8 +253,7 @@
 
 				ssi3: ssi@02030000 {
 					compatible = "fsl,imx6sl-ssi",
-							"fsl,imx51-ssi",
-							"fsl,imx21-ssi";
+							"fsl,imx51-ssi";
 					reg = <0x02030000 0x4000>;
 					interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
 					clocks = <&clks IMX6SL_CLK_SSI3>;
@@ -403,6 +400,7 @@
 				reg = <0x020b8000 0x4000>;
 				interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_DUMMY>;
+				status = "disabled";
 			};
 
 			wdog1: wdog@020bc000 {
@@ -607,7 +605,7 @@
 			};
 
 			sdma: sdma@020ec000 {
-				compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma";
+				compatible = "fsl,imx6sl-sdma", "fsl,imx6q-sdma";
 				reg = <0x020ec000 0x4000>;
 				interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SL_CLK_SDMA>,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sl-evk.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sl-evk.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sl-evk.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sl-evk.dts	2014-09-28 17:29:07.000000000 -0400
@@ -116,8 +116,9 @@
 };
 
 &fec {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&pinctrl_fec>;
+	pinctrl-1 = <&pinctrl_fec_sleep>;
 	phy-mode = "rmii";
 	status = "okay";
 };
@@ -300,6 +301,19 @@
 			>;
 		};
 
+		pinctrl_fec_sleep: fecgrp-sleep {
+			fsl,pins = <
+				MX6SL_PAD_FEC_MDC__GPIO4_IO23      0x3080
+				MX6SL_PAD_FEC_CRS_DV__GPIO4_IO25   0x3080
+				MX6SL_PAD_FEC_RXD0__GPIO4_IO17     0x3080
+				MX6SL_PAD_FEC_RXD1__GPIO4_IO18     0x3080
+				MX6SL_PAD_FEC_TX_EN__GPIO4_IO22    0x3080
+				MX6SL_PAD_FEC_TXD0__GPIO4_IO24     0x3080
+				MX6SL_PAD_FEC_TXD1__GPIO4_IO16     0x3080
+				MX6SL_PAD_FEC_REF_CLK__GPIO4_IO26  0x3080
+			>;
+		};
+
 		pinctrl_i2c1: i2c1grp {
 			fsl,pins = <
 				MX6SL_PAD_I2C1_SCL__I2C1_SCL	0x4001b8b1
@@ -475,7 +489,6 @@
 };
 
 &ssi2 {
-	fsl,mode = "i2s-slave";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx.dtsi	2014-09-28 21:27:48.000000000 -0400
@@ -0,0 +1,1208 @@
+/*
+ * Copyright 2014 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.
+ */
+
+#include <dt-bindings/clock/imx6sx-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6sx-pinfunc.h"
+#include "skeleton.dtsi"
+
+/ {
+	aliases {
+		can0 = &flexcan1;
+		can1 = &flexcan2;
+		ethernet0 = &fec1;
+		ethernet1 = &fec2;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		gpio5 = &gpio6;
+		gpio6 = &gpio7;
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		i2c3 = &i2c4;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		mmc2 = &usdhc3;
+		mmc3 = &usdhc4;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &uart6;
+		spi0 = &ecspi1;
+		spi1 = &ecspi2;
+		spi2 = &ecspi3;
+		spi3 = &ecspi4;
+		spi4 = &ecspi5;
+		usbphy0 = &usbphy1;
+		usbphy1 = &usbphy2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				996000  1250000
+				792000  1175000
+				396000  1075000
+			>;
+			fsl,soc-operating-points = <
+				/* ARM kHz  SOC uV */
+				996000      1175000
+				792000      1175000
+				396000      1175000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			clocks = <&clks IMX6SX_CLK_ARM>,
+				 <&clks IMX6SX_CLK_PLL2_PFD2>,
+				 <&clks IMX6SX_CLK_STEP>,
+				 <&clks IMX6SX_CLK_PLL1_SW>,
+				 <&clks IMX6SX_CLK_PLL1_SYS>;
+			clock-names = "arm", "pll2_pfd2_396m", "step",
+				      "pll1_sw", "pll1_sys";
+			arm-supply = <&reg_arm>;
+			soc-supply = <&reg_soc>;
+		};
+	};
+
+	intc: interrupt-controller@00a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x00a01000 0x1000>,
+		      <0x00a00100 0x100>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "ckil";
+		};
+
+		osc: clock@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+			clock-output-names = "osc";
+		};
+
+		ipp_di0: clock@2 {
+			compatible = "fixed-clock";
+			reg = <2>;
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "ipp_di0";
+		};
+
+		ipp_di1: clock@3 {
+			compatible = "fixed-clock";
+			reg = <3>;
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "ipp_di1";
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		ocram: sram@00900000 {
+			compatible = "mmio-sram";
+			reg = <0x00900000 0x20000>;
+			clocks = <&clks IMX6SX_CLK_OCRAM>;
+		};
+
+		L2: l2-cache@00a02000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a02000 0x1000>;
+			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+			cache-unified;
+			cache-level = <2>;
+			arm,tag-latency = <4 2 3>;
+			arm,data-latency = <4 2 3>;
+		};
+
+		dma_apbh: dma-apbh@01804000 {
+			compatible = "fsl,imx6sx-dma-apbh", "fsl,imx28-dma-apbh";
+			reg = <0x01804000 0x2000>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&clks IMX6SX_CLK_APBH_DMA>;
+		};
+
+		gpmi: gpmi-nand@01806000{
+			compatible = "fsl,imx6sx-gpmi-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
+			reg-names = "gpmi-nand", "bch";
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "bch";
+			clocks = <&clks IMX6SX_CLK_GPMI_IO>,
+				 <&clks IMX6SX_CLK_GPMI_APB>,
+				 <&clks IMX6SX_CLK_GPMI_BCH>,
+				 <&clks IMX6SX_CLK_GPMI_BCH_APB>,
+				 <&clks IMX6SX_CLK_PER1_BCH>;
+			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
+				      "gpmi_bch_apb", "per1_bch";
+			dmas = <&dma_apbh 0>;
+			dma-names = "rx-tx";
+			status = "disabled";
+		};
+
+		aips1: aips-bus@02000000 {
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02000000 0x100000>;
+			ranges;
+
+			spba-bus@02000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02000000 0x40000>;
+				ranges;
+
+				spdif: spdif@02004000 {
+					compatible = "fsl,imx6sx-spdif", "fsl,imx35-spdif";
+					reg = <0x02004000 0x4000>;
+					interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&sdma 14 18 0>,
+					       <&sdma 15 18 0>;
+					dma-names = "rx", "tx";
+					clocks = <&clks IMX6SX_CLK_SPDIF>,
+						 <&clks IMX6SX_CLK_OSC>,
+						 <&clks IMX6SX_CLK_SPDIF>,
+						 <&clks 0>, <&clks 0>, <&clks 0>,
+						 <&clks IMX6SX_CLK_IPG>,
+						 <&clks 0>, <&clks 0>,
+						 <&clks IMX6SX_CLK_SPBA>;
+					clock-names = "core", "rxtx0",
+						      "rxtx1", "rxtx2",
+						      "rxtx3", "rxtx4",
+						      "rxtx5", "rxtx6",
+						      "rxtx7", "dma";
+					status = "disabled";
+				};
+
+				ecspi1: ecspi@02008000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02008000 0x4000>;
+					interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ECSPI1>,
+						 <&clks IMX6SX_CLK_ECSPI1>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi2: ecspi@0200c000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+					reg = <0x0200c000 0x4000>;
+					interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ECSPI2>,
+						 <&clks IMX6SX_CLK_ECSPI2>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi3: ecspi@02010000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02010000 0x4000>;
+					interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ECSPI3>,
+						 <&clks IMX6SX_CLK_ECSPI3>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi4: ecspi@02014000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02014000 0x4000>;
+					interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ECSPI4>,
+						 <&clks IMX6SX_CLK_ECSPI4>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				uart1: serial@02020000 {
+					compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+					reg = <0x02020000 0x4000>;
+					interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_UART_IPG>,
+						 <&clks IMX6SX_CLK_UART_SERIAL>;
+					clock-names = "ipg", "per";
+					dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+					dma-names = "rx", "tx";
+					status = "disabled";
+				};
+
+				esai: esai@02024000 {
+					reg = <0x02024000 0x4000>;
+					interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ESAI_IPG>,
+						 <&clks IMX6SX_CLK_ESAI_MEM>,
+						 <&clks IMX6SX_CLK_ESAI_EXTAL>,
+						 <&clks IMX6SX_CLK_ESAI_IPG>,
+						 <&clks IMX6SX_CLK_SPBA>;
+					clock-names = "core", "mem", "extal",
+						      "fsys", "dma";
+					status = "disabled";
+				};
+
+				ssi1: ssi@02028000 {
+					compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+					reg = <0x02028000 0x4000>;
+					interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_SSI1_IPG>,
+						 <&clks IMX6SX_CLK_SSI1>;
+					clock-names = "ipg", "baud";
+					dmas = <&sdma 37 1 0>, <&sdma 38 1 0>;
+					dma-names = "rx", "tx";
+					fsl,fifo-depth = <15>;
+					status = "disabled";
+				};
+
+				ssi2: ssi@0202c000 {
+					compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+					reg = <0x0202c000 0x4000>;
+					interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_SSI2_IPG>,
+						 <&clks IMX6SX_CLK_SSI2>;
+					clock-names = "ipg", "baud";
+					dmas = <&sdma 41 1 0>, <&sdma 42 1 0>;
+					dma-names = "rx", "tx";
+					fsl,fifo-depth = <15>;
+					status = "disabled";
+				};
+
+				ssi3: ssi@02030000 {
+					compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+					reg = <0x02030000 0x4000>;
+					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_SSI3_IPG>,
+						 <&clks IMX6SX_CLK_SSI3>;
+					clock-names = "ipg", "baud";
+					dmas = <&sdma 45 1 0>, <&sdma 46 1 0>;
+					dma-names = "rx", "tx";
+					fsl,fifo-depth = <15>;
+					status = "disabled";
+				};
+
+				asrc: asrc@02034000 {
+					reg = <0x02034000 0x4000>;
+					interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_ASRC_MEM>,
+						 <&clks IMX6SX_CLK_ASRC_IPG>,
+						 <&clks IMX6SX_CLK_SPDIF>,
+						 <&clks IMX6SX_CLK_SPBA>;
+					clock-names = "mem", "ipg", "asrck", "dma";
+					dmas = <&sdma 17 20 1>, <&sdma 18 20 1>,
+					       <&sdma 19 20 1>, <&sdma 20 20 1>,
+					       <&sdma 21 20 1>, <&sdma 22 20 1>;
+					dma-names = "rxa", "rxb", "rxc",
+						    "txa", "txb", "txc";
+					status = "okay";
+				};
+			};
+
+			pwm1: pwm@02080000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x02080000 0x4000>;
+				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM1>,
+					 <&clks IMX6SX_CLK_PWM1>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm2: pwm@02084000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x02084000 0x4000>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM2>,
+					 <&clks IMX6SX_CLK_PWM2>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm3: pwm@02088000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x02088000 0x4000>;
+				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM3>,
+					 <&clks IMX6SX_CLK_PWM3>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm4: pwm@0208c000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x0208c000 0x4000>;
+				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM4>,
+					 <&clks IMX6SX_CLK_PWM4>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			flexcan1: can@02090000 {
+				compatible = "fsl,imx6sx-flexcan", "fsl,imx6q-flexcan";
+				reg = <0x02090000 0x4000>;
+				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_CAN1_IPG>,
+					 <&clks IMX6SX_CLK_CAN1_SERIAL>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			flexcan2: can@02094000 {
+				compatible = "fsl,imx6sx-flexcan", "fsl,imx6q-flexcan";
+				reg = <0x02094000 0x4000>;
+				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_CAN2_IPG>,
+					 <&clks IMX6SX_CLK_CAN2_SERIAL>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			gpt: gpt@02098000 {
+				compatible = "fsl,imx6sx-gpt", "fsl,imx31-gpt";
+				reg = <0x02098000 0x4000>;
+				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_GPT_BUS>,
+					 <&clks IMX6SX_CLK_GPT_SERIAL>;
+				clock-names = "ipg", "per";
+			};
+
+			gpio1: gpio@0209c000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x0209c000 0x4000>;
+				interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@020a0000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020a0000 0x4000>;
+				interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@020a4000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020a4000 0x4000>;
+				interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@020a8000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020a8000 0x4000>;
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio5: gpio@020ac000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020ac000 0x4000>;
+				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio6: gpio@020b0000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020b0000 0x4000>;
+				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio7: gpio@020b4000 {
+				compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+				reg = <0x020b4000 0x4000>;
+				interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			kpp: kpp@020b8000 {
+				compatible = "fsl,imx6sx-kpp", "fsl,imx21-kpp";
+				reg = <0x020b8000 0x4000>;
+				interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_DUMMY>;
+				status = "disabled";
+			};
+
+			wdog1: wdog@020bc000 {
+				compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+				reg = <0x020bc000 0x4000>;
+				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_DUMMY>;
+			};
+
+			wdog2: wdog@020c0000 {
+				compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+				reg = <0x020c0000 0x4000>;
+				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_DUMMY>;
+				status = "disabled";
+			};
+
+			clks: ccm@020c4000 {
+				compatible = "fsl,imx6sx-ccm";
+				reg = <0x020c4000 0x4000>;
+				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+				#clock-cells = <1>;
+				clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+				clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+			};
+
+			anatop: anatop@020c8000 {
+				compatible = "fsl,imx6sx-anatop", "fsl,imx6q-anatop",
+					     "syscon", "simple-bus";
+				reg = <0x020c8000 0x1000>;
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+
+				regulator-1p1@110 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd1p1";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1375000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x110>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <4>;
+					anatop-min-voltage = <800000>;
+					anatop-max-voltage = <1375000>;
+				};
+
+				regulator-3p0@120 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd3p0";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <3150000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x120>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <0>;
+					anatop-min-voltage = <2625000>;
+					anatop-max-voltage = <3400000>;
+				};
+
+				regulator-2p5@130 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd2p5";
+					regulator-min-microvolt = <2100000>;
+					regulator-max-microvolt = <2875000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x130>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <0>;
+					anatop-min-voltage = <2100000>;
+					anatop-max-voltage = <2875000>;
+				};
+
+				reg_arm: regulator-vddcore@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vddarm";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <0>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <24>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+
+				reg_pcie: regulator-vddpcie@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vddpcie";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <9>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <26>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+
+				reg_soc: regulator-vddsoc@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vddsoc";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <18>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <28>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+			};
+
+			tempmon: tempmon {
+				compatible = "fsl,imx6sx-tempmon", "fsl,imx6q-tempmon";
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+				fsl,tempmon = <&anatop>;
+				fsl,tempmon-data = <&ocotp>;
+				clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>;
+			};
+
+			usbphy1: usbphy@020c9000 {
+				compatible = "fsl,imx6sx-usbphy", "fsl,imx23-usbphy";
+				reg = <0x020c9000 0x1000>;
+				interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USBPHY1>;
+				fsl,anatop = <&anatop>;
+			};
+
+			usbphy2: usbphy@020ca000 {
+				compatible = "fsl,imx6sx-usbphy", "fsl,imx23-usbphy";
+				reg = <0x020ca000 0x1000>;
+				interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USBPHY2>;
+				fsl,anatop = <&anatop>;
+			};
+
+			snvs: snvs@020cc000 {
+				compatible = "fsl,sec-v4.0-mon", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x020cc000 0x4000>;
+
+				snvs-rtc-lp@34 {
+					compatible = "fsl,sec-v4.0-mon-rtc-lp";
+					reg = <0x34 0x58>;
+					interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+				};
+			};
+
+			epit1: epit@020d0000 {
+				reg = <0x020d0000 0x4000>;
+				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			epit2: epit@020d4000 {
+				reg = <0x020d4000 0x4000>;
+				interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			src: src@020d8000 {
+				compatible = "fsl,imx6sx-src", "fsl,imx51-src";
+				reg = <0x020d8000 0x4000>;
+				interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+				#reset-cells = <1>;
+			};
+
+			gpc: gpc@020dc000 {
+				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
+				reg = <0x020dc000 0x4000>;
+				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			iomuxc: iomuxc@020e0000 {
+				compatible = "fsl,imx6sx-iomuxc";
+				reg = <0x020e0000 0x4000>;
+			};
+
+			gpr: iomuxc-gpr@020e4000 {
+				compatible = "fsl,imx6sx-iomuxc-gpr",
+					     "fsl,imx6q-iomuxc-gpr", "syscon";
+				reg = <0x020e4000 0x4000>;
+			};
+
+			sdma: sdma@020ec000 {
+				compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma";
+				reg = <0x020ec000 0x4000>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_SDMA>,
+					 <&clks IMX6SX_CLK_SDMA>;
+				clock-names = "ipg", "ahb";
+				#dma-cells = <3>;
+				/* imx6sx reuses imx6q sdma firmware */
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+		};
+
+		aips2: aips-bus@02100000 {
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02100000 0x100000>;
+			ranges;
+
+			usbotg1: usb@02184000 {
+				compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+				reg = <0x02184000 0x200>;
+				interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USBOH3>;
+				fsl,usbphy = <&usbphy1>;
+				fsl,usbmisc = <&usbmisc 0>;
+				fsl,anatop = <&anatop>;
+				status = "disabled";
+			};
+
+			usbotg2: usb@02184200 {
+				compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+				reg = <0x02184200 0x200>;
+				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USBOH3>;
+				fsl,usbphy = <&usbphy2>;
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbh: usb@02184400 {
+				compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+				reg = <0x02184400 0x200>;
+				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USBOH3>;
+				fsl,usbmisc = <&usbmisc 2>;
+				phy_type = "hsic";
+				fsl,anatop = <&anatop>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc@02184800 {
+				#index-cells = <1>;
+				compatible = "fsl,imx6sx-usbmisc", "fsl,imx6q-usbmisc";
+				reg = <0x02184800 0x200>;
+				clocks = <&clks IMX6SX_CLK_USBOH3>;
+			};
+
+			fec1: ethernet@02188000 {
+				compatible = "fsl,imx6sx-fec", "fsl,imx6q-fec";
+				reg = <0x02188000 0x4000>;
+				interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_ENET>,
+					 <&clks IMX6SX_CLK_ENET_AHB>,
+					 <&clks IMX6SX_CLK_ENET_PTP>,
+					 <&clks IMX6SX_CLK_ENET_REF>,
+					 <&clks IMX6SX_CLK_ENET_PTP>;
+				clock-names = "ipg", "ahb", "ptp",
+					      "enet_clk_ref", "enet_out";
+				status = "disabled";
+                        };
+
+			mlb: mlb@0218c000 {
+				reg = <0x0218c000 0x4000>;
+				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_MLB>;
+				status = "disabled";
+			};
+
+			usdhc1: usdhc@02190000 {
+				compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+				reg = <0x02190000 0x4000>;
+				interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USDHC1>,
+					 <&clks IMX6SX_CLK_USDHC1>,
+					 <&clks IMX6SX_CLK_USDHC1>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc2: usdhc@02194000 {
+				compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+				reg = <0x02194000 0x4000>;
+				interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USDHC2>,
+					 <&clks IMX6SX_CLK_USDHC2>,
+					 <&clks IMX6SX_CLK_USDHC2>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc3: usdhc@02198000 {
+				compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+				reg = <0x02198000 0x4000>;
+				interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USDHC3>,
+					 <&clks IMX6SX_CLK_USDHC3>,
+					 <&clks IMX6SX_CLK_USDHC3>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc4: usdhc@0219c000 {
+				compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+				reg = <0x0219c000 0x4000>;
+				interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_USDHC4>,
+					 <&clks IMX6SX_CLK_USDHC4>,
+					 <&clks IMX6SX_CLK_USDHC4>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@021a0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+				reg = <0x021a0000 0x4000>;
+				interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_I2C1>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@021a4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+				reg = <0x021a4000 0x4000>;
+				interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_I2C2>;
+				status = "disabled";
+			};
+
+			i2c3: i2c@021a8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+				reg = <0x021a8000 0x4000>;
+				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_I2C3>;
+				status = "disabled";
+			};
+
+			mmdc: mmdc@021b0000 {
+				compatible = "fsl,imx6sx-mmdc", "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+
+			fec2: ethernet@021b4000 {
+				compatible = "fsl,imx6sx-fec";
+				reg = <0x021b4000 0x4000>;
+				interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_ENET>,
+					 <&clks IMX6SX_CLK_ENET_AHB>,
+					 <&clks IMX6SX_CLK_ENET_PTP>,
+					 <&clks IMX6SX_CLK_ENET2_REF_125M>,
+					 <&clks IMX6SX_CLK_ENET_PTP>;
+				clock-names = "ipg", "ahb", "ptp",
+					      "enet_clk_ref", "enet_out";
+				status = "disabled";
+			};
+
+			weim: weim@021b8000 {
+				compatible = "fsl,imx6sx-weim", "fsl,imx6q-weim";
+				reg = <0x021b8000 0x4000>;
+				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_EIM_SLOW>;
+			};
+
+			ocotp: ocotp@021bc000 {
+				compatible = "fsl,imx6sx-ocotp", "syscon";
+				reg = <0x021bc000 0x4000>;
+				clocks = <&clks IMX6SX_CLK_OCOTP>;
+			};
+
+			sai1: sai@021d4000 {
+				compatible = "fsl,imx6sx-sai";
+				reg = <0x021d4000 0x4000>;
+				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_SAI1_IPG>,
+					 <&clks IMX6SX_CLK_SAI1>,
+					 <&clks 0>, <&clks 0>;
+				clock-names = "bus", "mclk1", "mclk2", "mclk3";
+				dma-names = "rx", "tx";
+				dmas = <&sdma 31 23 0>, <&sdma 32 23 0>;
+				dma-source = <&gpr 0 15 0 16>;
+				status = "disabled";
+			};
+
+			audmux: audmux@021d8000 {
+				compatible = "fsl,imx6sx-audmux", "fsl,imx31-audmux";
+				reg = <0x021d8000 0x4000>;
+				status = "disabled";
+			};
+
+			sai2: sai@021dc000 {
+				compatible = "fsl,imx6sx-sai";
+				reg = <0x021dc000 0x4000>;
+				interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_SAI2_IPG>,
+					 <&clks IMX6SX_CLK_SAI2>,
+					 <&clks 0>, <&clks 0>;
+				clock-names = "bus", "mclk1", "mclk2", "mclk3";
+				dma-names = "rx", "tx";
+				dmas = <&sdma 33 23 0>, <&sdma 34 23 0>;
+				dma-source = <&gpr 0 17 0 18>;
+				status = "disabled";
+			};
+
+			qspi1: qspi@021e0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-qspi";
+				reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>;
+				reg-names = "QuadSPI", "QuadSPI-memory";
+				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_QSPI1>,
+					 <&clks IMX6SX_CLK_QSPI1>;
+				clock-names = "qspi_en", "qspi";
+				status = "disabled";
+			};
+
+			qspi2: qspi@021e4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-qspi";
+				reg = <0x021e4000 0x4000>, <0x70000000 0x10000000>;
+				reg-names = "QuadSPI", "QuadSPI-memory";
+				interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_QSPI2>,
+					 <&clks IMX6SX_CLK_QSPI2>;
+				clock-names = "qspi_en", "qspi";
+				status = "disabled";
+			};
+
+			uart2: serial@021e8000 {
+				compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+				reg = <0x021e8000 0x4000>;
+				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_UART_IPG>,
+					 <&clks IMX6SX_CLK_UART_SERIAL>;
+				clock-names = "ipg", "per";
+				dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+				dma-names = "rx", "tx";
+				status = "disabled";
+			};
+
+			uart3: serial@021ec000 {
+				compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+				reg = <0x021ec000 0x4000>;
+				interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_UART_IPG>,
+					 <&clks IMX6SX_CLK_UART_SERIAL>;
+				clock-names = "ipg", "per";
+				dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+				dma-names = "rx", "tx";
+				status = "disabled";
+			};
+
+			uart4: serial@021f0000 {
+				compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+				reg = <0x021f0000 0x4000>;
+				interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_UART_IPG>,
+					 <&clks IMX6SX_CLK_UART_SERIAL>;
+				clock-names = "ipg", "per";
+				dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+				dma-names = "rx", "tx";
+				status = "disabled";
+			};
+
+			uart5: serial@021f4000 {
+				compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+				reg = <0x021f4000 0x4000>;
+				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_UART_IPG>,
+					 <&clks IMX6SX_CLK_UART_SERIAL>;
+				clock-names = "ipg", "per";
+				dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+				dma-names = "rx", "tx";
+				status = "disabled";
+			};
+
+			i2c4: i2c@021f8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+				reg = <0x021f8000 0x4000>;
+				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_I2C4>;
+				status = "disabled";
+			};
+		};
+
+		aips3: aips-bus@02200000 {
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02200000 0x100000>;
+			ranges;
+
+			spba-bus@02200000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02240000 0x40000>;
+				ranges;
+
+				csi1: csi@02214000 {
+					reg = <0x02214000 0x4000>;
+					interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
+						 <&clks IMX6SX_CLK_CSI>,
+						 <&clks IMX6SX_CLK_DCIC1>;
+					clock-names = "disp-axi", "csi_mclk", "dcic";
+					status = "disabled";
+				};
+
+				pxp: pxp@02218000 {
+					reg = <0x02218000 0x4000>;
+					interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_PXP_AXI>,
+						 <&clks IMX6SX_CLK_DISPLAY_AXI>;
+					clock-names = "pxp-axi", "disp-axi";
+					status = "disabled";
+				};
+
+				csi2: csi@0221c000 {
+					reg = <0x0221c000 0x4000>;
+					interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
+						 <&clks IMX6SX_CLK_CSI>,
+						 <&clks IMX6SX_CLK_DCIC2>;
+					clock-names = "disp-axi", "csi_mclk", "dcic";
+					status = "disabled";
+				};
+
+				lcdif1: lcdif@02220000 {
+					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";
+					status = "disabled";
+				};
+
+				lcdif2: lcdif@02224000 {
+					reg = <0x02224000 0x4000>;
+					interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+					clocks = <&clks IMX6SX_CLK_LCDIF2_PIX>,
+						 <&clks IMX6SX_CLK_LCDIF_APB>,
+						 <&clks IMX6SX_CLK_DISPLAY_AXI>;
+					clock-names = "pix", "axi", "disp_axi";
+					status = "disabled";
+				};
+
+				vadc: vadc@02228000 {
+					reg = <0x02228000 0x4000>, <0x0222c000 0x4000>;
+					reg-names = "vadc-vafe", "vadc-vdec";
+					clocks = <&clks IMX6SX_CLK_VADC>,
+						 <&clks IMX6SX_CLK_CSI>;
+					clock-names = "vadc", "csi";
+					status = "disabled";
+				};
+			};
+
+			adc1: adc@02280000 {
+				compatible = "fsl,imx6sx-adc", "fsl,vf610-adc";
+				reg = <0x02280000 0x4000>;
+				interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_IPG>;
+				clock-names = "adc";
+				status = "disabled";
+                        };
+
+			adc2: adc@02284000 {
+				compatible = "fsl,imx6sx-adc", "fsl,vf610-adc";
+				reg = <0x02284000 0x4000>;
+				interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_IPG>;
+				clock-names = "adc";
+				status = "disabled";
+                        };
+
+			wdog3: wdog@02288000 {
+				compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+				reg = <0x02288000 0x4000>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_DUMMY>;
+				status = "disabled";
+			};
+
+			ecspi5: ecspi@0228c000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+				reg = <0x0228c000 0x4000>;
+				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_ECSPI5>,
+					 <&clks IMX6SX_CLK_ECSPI5>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart6: serial@022a0000 {
+				compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+				reg = <0x022a0000 0x4000>;
+				interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_UART_IPG>,
+					 <&clks IMX6SX_CLK_UART_SERIAL>;
+				clock-names = "ipg", "per";
+				dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
+				dma-names = "rx", "tx";
+				status = "disabled";
+			};
+
+			pwm5: pwm@022a4000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x022a4000 0x4000>;
+				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM5>,
+					 <&clks IMX6SX_CLK_PWM5>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm6: pwm@022a8000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x022a8000 0x4000>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM6>,
+					 <&clks IMX6SX_CLK_PWM6>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm7: pwm@022ac000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x022ac000 0x4000>;
+				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM7>,
+					 <&clks IMX6SX_CLK_PWM7>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+
+			pwm8: pwm@0022b0000 {
+				compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+				reg = <0x0022b0000 0x4000>;
+				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SX_CLK_PWM8>,
+					 <&clks IMX6SX_CLK_PWM8>;
+				clock-names = "ipg", "per";
+				#pwm-cells = <2>;
+			};
+		};
+
+		pcie: pcie@0x08000000 {
+			compatible = "fsl,imx6sx-pcie", "snps,dw-pcie";
+			reg = <0x08ffc000 0x4000>; /* DBI */
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+				  /* configuration space */
+			ranges = <0x00000800 0 0x08f00000 0x08f00000 0 0x00080000
+				  /* downstream I/O */
+				  0x81000000 0 0          0x08f80000 0 0x00010000
+				  /* non-prefetchable memory */
+				  0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
+			num-lanes = <1>;
+			interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
+				 <&clks IMX6SX_CLK_PCIE_AXI>,
+				 <&clks IMX6SX_CLK_LVDS1_OUT>,
+				 <&clks IMX6SX_CLK_DISPLAY_AXI>;
+			clock-names = "pcie_ref_125m", "pcie_axi",
+				      "lvds_gate", "display_axi";
+			status = "disabled";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx-pinfunc.h linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx-pinfunc.h
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx-pinfunc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx-pinfunc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1544 @@
+/*
+ * Copyright 2014 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_IMX6SX_PINFUNC_H
+#define __DTS_IMX6SX_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SX_PAD_GPIO1_IO00__I2C1_SCL                            0x0014 0x035C 0x07A8 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO00__USDHC1_VSELECT                      0x0014 0x035C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO00__SPDIF_LOCK                          0x0014 0x035C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO00__CCM_WAIT                            0x0014 0x035C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO00__WDOG1_WDOG_ANY                      0x0014 0x035C 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO00__GPIO1_IO_0                          0x0014 0x035C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO00__SNVS_HP_WRAPPER_VIO_5               0x0014 0x035C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO00__PHY_DTB_1                           0x0014 0x035C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO01__I2C1_SDA                            0x0018 0x0360 0x07AC 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO01__USDHC1_RESET_B                      0x0018 0x0360 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO01__SPDIF_SR_CLK                        0x0018 0x0360 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO01__CCM_STOP                            0x0018 0x0360 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO01__WDOG3_WDOG_B                        0x0018 0x0360 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO01__GPIO1_IO_1                          0x0018 0x0360 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO01__SNVS_HP_WRAPPER_VIO_5_CTL           0x0018 0x0360 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO01__PHY_DTB_0                           0x0018 0x0360 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO02__I2C2_SCL                            0x001C 0x0364 0x07B0 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO02__USDHC1_CD_B                         0x001C 0x0364 0x0864 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO02__CSI2_MCLK                           0x001C 0x0364 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO02__CCM_DI0_EXT_CLK                     0x001C 0x0364 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO02__WDOG1_WDOG_B                        0x001C 0x0364 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO02__GPIO1_IO_2                          0x001C 0x0364 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO02__CCM_REF_EN_B                        0x001C 0x0364 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO02__PHY_TDI                             0x001C 0x0364 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO03__I2C2_SDA                            0x0020 0x0368 0x07B4 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO03__USDHC1_WP                           0x0020 0x0368 0x0868 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO03__ENET1_REF_CLK_25M                   0x0020 0x0368 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO03__CCM_DI1_EXT_CLK                     0x0020 0x0368 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO03__WDOG2_WDOG_B                        0x0020 0x0368 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO03__GPIO1_IO_3                          0x0020 0x0368 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO03__CCM_PLL3_BYP                        0x0020 0x0368 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO03__PHY_TCK                             0x0020 0x0368 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO04__UART1_RX                            0x0024 0x036C 0x0830 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO04__UART1_TX                            0x0024 0x036C 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO04__USDHC2_RESET_B                      0x0024 0x036C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO04__ENET1_MDC                           0x0024 0x036C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO04__OSC32K_32K_OUT                      0x0024 0x036C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO04__ENET2_REF_CLK2                      0x0024 0x036C 0x076C 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO04__GPIO1_IO_4                          0x0024 0x036C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO04__CCM_PLL2_BYP                        0x0024 0x036C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO04__PHY_TMS                             0x0024 0x036C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO05__UART1_RX                            0x0028 0x0370 0x0830 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO05__UART1_TX                            0x0028 0x0370 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO05__USDHC2_VSELECT                      0x0028 0x0370 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO05__ENET1_MDIO                          0x0028 0x0370 0x0764 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO05__ASRC_ASRC_EXT_CLK                   0x0028 0x0370 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO05__ENET1_REF_CLK1                      0x0028 0x0370 0x0760 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO05__GPIO1_IO_5                          0x0028 0x0370 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO05__SRC_TESTER_ACK                      0x0028 0x0370 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO05__PHY_TDO                             0x0028 0x0370 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART2_RX                            0x002C 0x0374 0x0838 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART2_TX                            0x002C 0x0374 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO06__USDHC2_CD_B                         0x002C 0x0374 0x086C 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO06__ENET2_MDC                           0x002C 0x0374 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO06__CSI1_MCLK                           0x002C 0x0374 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART1_RTS_B                         0x002C 0x0374 0x082C 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO06__GPIO1_IO_6                          0x002C 0x0374 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO06__SRC_ANY_PU_RESET                    0x002C 0x0374 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO06__OCOTP_CTRL_WRAPPER_FUSE_LATCHED     0x002C 0x0374 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO07__UART2_RX                            0x0030 0x0378 0x0838 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO07__UART2_TX                            0x0030 0x0378 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO07__USDHC2_WP                           0x0030 0x0378 0x0870 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO07__ENET2_MDIO                          0x0030 0x0378 0x0770 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO07__AUDMUX_MCLK                         0x0030 0x0378 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO07__UART1_CTS_B                         0x0030 0x0378 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO07__GPIO1_IO_7                          0x0030 0x0378 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO07__SRC_EARLY_RESET                     0x0030 0x0378 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO07__DCIC2_OUT                           0x0030 0x0378 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO07__VDEC_DEBUG_44                       0x0030 0x0378 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO08__USB_OTG1_OC                         0x0034 0x037C 0x0860 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO08__WDOG1_WDOG_B                        0x0034 0x037C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO08__SDMA_EXT_EVENT_0                    0x0034 0x037C 0x081C 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO08__CCM_PMIC_RDY                        0x0034 0x037C 0x069C 0x3 0x1
+#define MX6SX_PAD_GPIO1_IO08__UART2_RTS_B                         0x0034 0x037C 0x0834 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO08__GPIO1_IO_8                          0x0034 0x037C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO08__SRC_SYSTEM_RESET                    0x0034 0x037C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO08__DCIC1_OUT                           0x0034 0x037C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO08__VDEC_DEBUG_43                       0x0034 0x037C 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO09__USB_OTG1_PWR                        0x0038 0x0380 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO09__WDOG2_WDOG_B                        0x0038 0x0380 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO09__SDMA_EXT_EVENT_1                    0x0038 0x0380 0x0820 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO09__CCM_OUT0                            0x0038 0x0380 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO09__UART2_CTS_B                         0x0038 0x0380 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9                          0x0038 0x0380 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO09__SRC_INT_BOOT                        0x0038 0x0380 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO09__OBSERVE_MUX_OUT_4                   0x0038 0x0380 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO09__VDEC_DEBUG_42                       0x0038 0x0380 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID                      0x003C 0x0384 0x0624 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO10__SPDIF_EXT_CLK                       0x003C 0x0384 0x0828 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO10__PWM1_OUT                            0x003C 0x0384 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO10__CCM_OUT1                            0x003C 0x0384 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO10__CSI1_FIELD                          0x003C 0x0384 0x070C 0x4 0x1
+#define MX6SX_PAD_GPIO1_IO10__GPIO1_IO_10                         0x003C 0x0384 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO10__CSU_CSU_INT_DEB                     0x003C 0x0384 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO10__OBSERVE_MUX_OUT_3                   0x003C 0x0384 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO10__VDEC_DEBUG_41                       0x003C 0x0384 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO11__USB_OTG2_OC                         0x0040 0x0388 0x085C 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO11__SPDIF_IN                            0x0040 0x0388 0x0824 0x1 0x2
+#define MX6SX_PAD_GPIO1_IO11__PWM2_OUT                            0x0040 0x0388 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO11__CCM_CLKO1                           0x0040 0x0388 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO11__MLB_DATA                            0x0040 0x0388 0x07EC 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO11__GPIO1_IO_11                         0x0040 0x0388 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO11__CSU_CSU_ALARM_AUT_0                 0x0040 0x0388 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO11__OBSERVE_MUX_OUT_2                   0x0040 0x0388 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO11__VDEC_DEBUG_40                       0x0040 0x0388 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO12__USB_OTG2_PWR                        0x0044 0x038C 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO12__SPDIF_OUT                           0x0044 0x038C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO12__PWM3_OUT                            0x0044 0x038C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO12__CCM_CLKO2                           0x0044 0x038C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO12__MLB_CLK                             0x0044 0x038C 0x07E8 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12                         0x0044 0x038C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO12__CSU_CSU_ALARM_AUT_1                 0x0044 0x038C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO12__OBSERVE_MUX_OUT_1                   0x0044 0x038C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO12__VDEC_DEBUG_39                       0x0044 0x038C 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY                      0x0048 0x0390 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO13__ANATOP_OTG2_ID                      0x0048 0x0390 0x0628 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO13__PWM4_OUT                            0x0048 0x0390 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO13__CCM_OUT2                            0x0048 0x0390 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO13__MLB_SIG                             0x0048 0x0390 0x07F0 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO13__GPIO1_IO_13                         0x0048 0x0390 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO13__CSU_CSU_ALARM_AUT_2                 0x0048 0x0390 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO13__OBSERVE_MUX_OUT_0                   0x0048 0x0390 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO13__VDEC_DEBUG_38                       0x0048 0x0390 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA00__CSI1_DATA_2                         0x004C 0x0394 0x06A8 0x0 0x0
+#define MX6SX_PAD_CSI_DATA00__ESAI_TX_CLK                         0x004C 0x0394 0x078C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC                     0x004C 0x0394 0x0684 0x2 0x1
+#define MX6SX_PAD_CSI_DATA00__I2C1_SCL                            0x004C 0x0394 0x07A8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA00__UART6_RI_B                          0x004C 0x0394 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA00__GPIO1_IO_14                         0x004C 0x0394 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA00__WEIM_DATA_23                        0x004C 0x0394 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK                        0x004C 0x0394 0x0800 0x7 0x0
+#define MX6SX_PAD_CSI_DATA00__VADC_DATA_4                         0x004C 0x0394 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA00__MMDC_DEBUG_37                       0x004C 0x0394 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA01__CSI1_DATA_3                         0x0050 0x0398 0x06AC 0x0 0x0
+#define MX6SX_PAD_CSI_DATA01__ESAI_TX_FS                          0x0050 0x0398 0x077C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS                    0x0050 0x0398 0x0688 0x2 0x1
+#define MX6SX_PAD_CSI_DATA01__I2C1_SDA                            0x0050 0x0398 0x07AC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA01__UART6_DSR_B                         0x0050 0x0398 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA01__GPIO1_IO_15                         0x0050 0x0398 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA01__WEIM_DATA_22                        0x0050 0x0398 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC                        0x0050 0x0398 0x0804 0x7 0x0
+#define MX6SX_PAD_CSI_DATA01__VADC_DATA_5                         0x0050 0x0398 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA01__MMDC_DEBUG_38                       0x0050 0x0398 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA02__CSI1_DATA_4                         0x0054 0x039C 0x06B0 0x0 0x0
+#define MX6SX_PAD_CSI_DATA02__ESAI_RX_CLK                         0x0054 0x039C 0x0788 0x1 0x1
+#define MX6SX_PAD_CSI_DATA02__AUDMUX_AUD6_RXC                     0x0054 0x039C 0x067C 0x2 0x1
+#define MX6SX_PAD_CSI_DATA02__KPP_COL_5                           0x0054 0x039C 0x07C8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA02__UART6_DTR_B                         0x0054 0x039C 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA02__GPIO1_IO_16                         0x0054 0x039C 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA02__WEIM_DATA_21                        0x0054 0x039C 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA02__SAI1_RX_BCLK                        0x0054 0x039C 0x07F4 0x7 0x0
+#define MX6SX_PAD_CSI_DATA02__VADC_DATA_6                         0x0054 0x039C 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA02__MMDC_DEBUG_39                       0x0054 0x039C 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA03__CSI1_DATA_5                         0x0058 0x03A0 0x06B4 0x0 0x0
+#define MX6SX_PAD_CSI_DATA03__ESAI_RX_FS                          0x0058 0x03A0 0x0778 0x1 0x1
+#define MX6SX_PAD_CSI_DATA03__AUDMUX_AUD6_RXFS                    0x0058 0x03A0 0x0680 0x2 0x1
+#define MX6SX_PAD_CSI_DATA03__KPP_ROW_5                           0x0058 0x03A0 0x07D4 0x3 0x0
+#define MX6SX_PAD_CSI_DATA03__UART6_DCD_B                         0x0058 0x03A0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA03__GPIO1_IO_17                         0x0058 0x03A0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA03__WEIM_DATA_20                        0x0058 0x03A0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA03__SAI1_RX_SYNC                        0x0058 0x03A0 0x07FC 0x7 0x0
+#define MX6SX_PAD_CSI_DATA03__VADC_DATA_7                         0x0058 0x03A0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA03__MMDC_DEBUG_40                       0x0058 0x03A0 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA04__CSI1_DATA_6                         0x005C 0x03A4 0x06B8 0x0 0x0
+#define MX6SX_PAD_CSI_DATA04__ESAI_TX1                            0x005C 0x03A4 0x0794 0x1 0x1
+#define MX6SX_PAD_CSI_DATA04__SPDIF_OUT                           0x005C 0x03A4 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_DATA04__KPP_COL_6                           0x005C 0x03A4 0x07CC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA04__UART6_RX                            0x005C 0x03A4 0x0858 0x4 0x0
+#define MX6SX_PAD_CSI_DATA04__UART6_TX                            0x005C 0x03A4 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA04__GPIO1_IO_18                         0x005C 0x03A4 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA04__WEIM_DATA_19                        0x005C 0x03A4 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA04__PWM5_OUT                            0x005C 0x03A4 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA04__VADC_DATA_8                         0x005C 0x03A4 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA04__MMDC_DEBUG_41                       0x005C 0x03A4 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA05__CSI1_DATA_7                         0x0060 0x03A8 0x06BC 0x0 0x0
+#define MX6SX_PAD_CSI_DATA05__ESAI_TX4_RX1                        0x0060 0x03A8 0x07A0 0x1 0x1
+#define MX6SX_PAD_CSI_DATA05__SPDIF_IN                            0x0060 0x03A8 0x0824 0x2 0x1
+#define MX6SX_PAD_CSI_DATA05__KPP_ROW_6                           0x0060 0x03A8 0x07D8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA05__UART6_RX                            0x0060 0x03A8 0x0858 0x4 0x1
+#define MX6SX_PAD_CSI_DATA05__UART6_TX                            0x0060 0x03A8 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA05__GPIO1_IO_19                         0x0060 0x03A8 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA05__WEIM_DATA_18                        0x0060 0x03A8 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA05__PWM6_OUT                            0x0060 0x03A8 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA05__VADC_DATA_9                         0x0060 0x03A8 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA05__MMDC_DEBUG_42                       0x0060 0x03A8 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA06__CSI1_DATA_8                         0x0064 0x03AC 0x06C0 0x0 0x0
+#define MX6SX_PAD_CSI_DATA06__ESAI_TX2_RX3                        0x0064 0x03AC 0x0798 0x1 0x1
+#define MX6SX_PAD_CSI_DATA06__I2C4_SCL                            0x0064 0x03AC 0x07C0 0x2 0x2
+#define MX6SX_PAD_CSI_DATA06__KPP_COL_7                           0x0064 0x03AC 0x07D0 0x3 0x0
+#define MX6SX_PAD_CSI_DATA06__UART6_RTS_B                         0x0064 0x03AC 0x0854 0x4 0x0
+#define MX6SX_PAD_CSI_DATA06__GPIO1_IO_20                         0x0064 0x03AC 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA06__WEIM_DATA_17                        0x0064 0x03AC 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA06__DCIC2_OUT                           0x0064 0x03AC 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA06__VADC_DATA_10                        0x0064 0x03AC 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA06__MMDC_DEBUG_43                       0x0064 0x03AC 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA07__CSI1_DATA_9                         0x0068 0x03B0 0x06C4 0x0 0x0
+#define MX6SX_PAD_CSI_DATA07__ESAI_TX3_RX2                        0x0068 0x03B0 0x079C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA07__I2C4_SDA                            0x0068 0x03B0 0x07C4 0x2 0x2
+#define MX6SX_PAD_CSI_DATA07__KPP_ROW_7                           0x0068 0x03B0 0x07DC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA07__UART6_CTS_B                         0x0068 0x03B0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA07__GPIO1_IO_21                         0x0068 0x03B0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA07__WEIM_DATA_16                        0x0068 0x03B0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA07__DCIC1_OUT                           0x0068 0x03B0 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA07__VADC_DATA_11                        0x0068 0x03B0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA07__MMDC_DEBUG_44                       0x0068 0x03B0 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_HSYNC__CSI1_HSYNC                           0x006C 0x03B4 0x0700 0x0 0x0
+#define MX6SX_PAD_CSI_HSYNC__ESAI_TX0                             0x006C 0x03B4 0x0790 0x1 0x1
+#define MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD                      0x006C 0x03B4 0x0678 0x2 0x1
+#define MX6SX_PAD_CSI_HSYNC__UART4_RTS_B                          0x006C 0x03B4 0x0844 0x3 0x2
+#define MX6SX_PAD_CSI_HSYNC__MQS_LEFT                             0x006C 0x03B4 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_HSYNC__GPIO1_IO_22                          0x006C 0x03B4 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_HSYNC__WEIM_DATA_25                         0x006C 0x03B4 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0                       0x006C 0x03B4 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_HSYNC__VADC_DATA_2                          0x006C 0x03B4 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_HSYNC__MMDC_DEBUG_35                        0x006C 0x03B4 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_MCLK__CSI1_MCLK                             0x0070 0x03B8 0x0000 0x0 0x0
+#define MX6SX_PAD_CSI_MCLK__ESAI_TX_HF_CLK                        0x0070 0x03B8 0x0784 0x1 0x1
+#define MX6SX_PAD_CSI_MCLK__OSC32K_32K_OUT                        0x0070 0x03B8 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_MCLK__UART4_RX                              0x0070 0x03B8 0x0848 0x3 0x2
+#define MX6SX_PAD_CSI_MCLK__UART4_TX                              0x0070 0x03B8 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_MCLK__ANATOP_32K_OUT                        0x0070 0x03B8 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_MCLK__GPIO1_IO_23                           0x0070 0x03B8 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_MCLK__WEIM_DATA_26                          0x0070 0x03B8 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_MCLK__CSI1_FIELD                            0x0070 0x03B8 0x070C 0x7 0x0
+#define MX6SX_PAD_CSI_MCLK__VADC_DATA_1                           0x0070 0x03B8 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_MCLK__MMDC_DEBUG_34                         0x0070 0x03B8 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_PIXCLK__CSI1_PIXCLK                         0x0074 0x03BC 0x0704 0x0 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ESAI_RX_HF_CLK                      0x0074 0x03BC 0x0780 0x1 0x1
+#define MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK                         0x0074 0x03BC 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_PIXCLK__UART4_RX                            0x0074 0x03BC 0x0848 0x3 0x3
+#define MX6SX_PAD_CSI_PIXCLK__UART4_TX                            0x0074 0x03BC 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ANATOP_24M_OUT                      0x0074 0x03BC 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_PIXCLK__GPIO1_IO_24                         0x0074 0x03BC 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_PIXCLK__WEIM_DATA_27                        0x0074 0x03BC 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ESAI_TX_HF_CLK                      0x0074 0x03BC 0x0784 0x7 0x2
+#define MX6SX_PAD_CSI_PIXCLK__VADC_CLK                            0x0074 0x03BC 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_PIXCLK__MMDC_DEBUG_33                       0x0074 0x03BC 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_VSYNC__CSI1_VSYNC                           0x0078 0x03C0 0x0708 0x0 0x0
+#define MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0                         0x0078 0x03C0 0x07A4 0x1 0x1
+#define MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD                      0x0078 0x03C0 0x0674 0x2 0x1
+#define MX6SX_PAD_CSI_VSYNC__UART4_CTS_B                          0x0078 0x03C0 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_VSYNC__MQS_RIGHT                            0x0078 0x03C0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_VSYNC__GPIO1_IO_25                          0x0078 0x03C0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_VSYNC__WEIM_DATA_24                         0x0078 0x03C0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0                       0x0078 0x03C0 0x07F8 0x7 0x0
+#define MX6SX_PAD_CSI_VSYNC__VADC_DATA_3                          0x0078 0x03C0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_VSYNC__MMDC_DEBUG_36                        0x0078 0x03C0 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_COL__ENET1_COL                            0x007C 0x03C4 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_COL__ENET2_MDC                            0x007C 0x03C4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_COL__AUDMUX_AUD4_TXC                      0x007C 0x03C4 0x0654 0x2 0x1
+#define MX6SX_PAD_ENET1_COL__UART1_RI_B                           0x007C 0x03C4 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_COL__SPDIF_EXT_CLK                        0x007C 0x03C4 0x0828 0x4 0x1
+#define MX6SX_PAD_ENET1_COL__GPIO2_IO_0                           0x007C 0x03C4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_COL__CSI2_DATA_23                         0x007C 0x03C4 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_COL__LCDIF2_DATA_16                       0x007C 0x03C4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_COL__VDEC_DEBUG_37                        0x007C 0x03C4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_COL__PCIE_CTRL_DEBUG_31                   0x007C 0x03C4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_CRS__ENET1_CRS                            0x0080 0x03C8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_CRS__ENET2_MDIO                           0x0080 0x03C8 0x0770 0x1 0x1
+#define MX6SX_PAD_ENET1_CRS__AUDMUX_AUD4_TXD                      0x0080 0x03C8 0x0648 0x2 0x1
+#define MX6SX_PAD_ENET1_CRS__UART1_DCD_B                          0x0080 0x03C8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_CRS__SPDIF_LOCK                           0x0080 0x03C8 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_CRS__GPIO2_IO_1                           0x0080 0x03C8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_CRS__CSI2_DATA_22                         0x0080 0x03C8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_CRS__LCDIF2_DATA_17                       0x0080 0x03C8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_CRS__VDEC_DEBUG_36                        0x0080 0x03C8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_CRS__PCIE_CTRL_DEBUG_30                   0x0080 0x03C8 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_MDC__ENET1_MDC                            0x0084 0x03CC 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_MDC__ENET2_MDC                            0x0084 0x03CC 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_MDC__AUDMUX_AUD3_RXFS                     0x0084 0x03CC 0x0638 0x2 0x1
+#define MX6SX_PAD_ENET1_MDC__ANATOP_24M_OUT                       0x0084 0x03CC 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_MDC__EPIT2_OUT                            0x0084 0x03CC 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_MDC__GPIO2_IO_2                           0x0084 0x03CC 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_MDC__USB_OTG1_PWR                         0x0084 0x03CC 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_MDC__PWM7_OUT                             0x0084 0x03CC 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_MDIO__ENET1_MDIO                          0x0088 0x03D0 0x0764 0x0 0x1
+#define MX6SX_PAD_ENET1_MDIO__ENET2_MDIO                          0x0088 0x03D0 0x0770 0x1 0x2
+#define MX6SX_PAD_ENET1_MDIO__AUDMUX_MCLK                         0x0088 0x03D0 0x0000 0x2 0x0
+#define MX6SX_PAD_ENET1_MDIO__OSC32K_32K_OUT                      0x0088 0x03D0 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_MDIO__EPIT1_OUT                           0x0088 0x03D0 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_MDIO__GPIO2_IO_3                          0x0088 0x03D0 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_MDIO__USB_OTG1_OC                         0x0088 0x03D0 0x0860 0x6 0x1
+#define MX6SX_PAD_ENET1_MDIO__PWM8_OUT                            0x0088 0x03D0 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__ENET1_RX_CLK                      0x008C 0x03D4 0x0768 0x0 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__ENET1_REF_CLK_25M                 0x008C 0x03D4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__AUDMUX_AUD4_TXFS                  0x008C 0x03D4 0x0658 0x2 0x1
+#define MX6SX_PAD_ENET1_RX_CLK__UART1_DSR_B                       0x008C 0x03D4 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__SPDIF_OUT                         0x008C 0x03D4 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__GPIO2_IO_4                        0x008C 0x03D4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__CSI2_DATA_21                      0x008C 0x03D4 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__LCDIF2_DATA_18                    0x008C 0x03D4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__VDEC_DEBUG_35                     0x008C 0x03D4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__PCIE_CTRL_DEBUG_29                0x008C 0x03D4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK                      0x0090 0x03D8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                    0x0090 0x03D8 0x0760 0x1 0x1
+#define MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD                   0x0090 0x03D8 0x0644 0x2 0x1
+#define MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B                       0x0090 0x03D8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__SPDIF_SR_CLK                      0x0090 0x03D8 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__GPIO2_IO_5                        0x0090 0x03D8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__CSI2_DATA_20                      0x0090 0x03D8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__LCDIF2_DATA_19                    0x0090 0x03D8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__VDEC_DEBUG_34                     0x0090 0x03D8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__PCIE_CTRL_DEBUG_28                0x0090 0x03D8 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_COL__ENET2_COL                            0x0094 0x03DC 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_COL__ENET1_MDC                            0x0094 0x03DC 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET2_COL__AUDMUX_AUD4_RXC                      0x0094 0x03DC 0x064C 0x2 0x1
+#define MX6SX_PAD_ENET2_COL__UART1_RX                             0x0094 0x03DC 0x0830 0x3 0x2
+#define MX6SX_PAD_ENET2_COL__UART1_TX                             0x0094 0x03DC 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_COL__SPDIF_IN                             0x0094 0x03DC 0x0824 0x4 0x3
+#define MX6SX_PAD_ENET2_COL__GPIO2_IO_6                           0x0094 0x03DC 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_COL__ANATOP_OTG1_ID                       0x0094 0x03DC 0x0624 0x6 0x1
+#define MX6SX_PAD_ENET2_COL__LCDIF2_DATA_20                       0x0094 0x03DC 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_COL__VDEC_DEBUG_33                        0x0094 0x03DC 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_COL__PCIE_CTRL_DEBUG_27                   0x0094 0x03DC 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_CRS__ENET2_CRS                            0x0098 0x03E0 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_CRS__ENET1_MDIO                           0x0098 0x03E0 0x0764 0x1 0x2
+#define MX6SX_PAD_ENET2_CRS__AUDMUX_AUD4_RXFS                     0x0098 0x03E0 0x0650 0x2 0x1
+#define MX6SX_PAD_ENET2_CRS__UART1_RX                             0x0098 0x03E0 0x0830 0x3 0x3
+#define MX6SX_PAD_ENET2_CRS__UART1_TX                             0x0098 0x03E0 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_CRS__MLB_SIG                              0x0098 0x03E0 0x07F0 0x4 0x1
+#define MX6SX_PAD_ENET2_CRS__GPIO2_IO_7                           0x0098 0x03E0 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_CRS__ANATOP_OTG2_ID                       0x0098 0x03E0 0x0628 0x6 0x1
+#define MX6SX_PAD_ENET2_CRS__LCDIF2_DATA_21                       0x0098 0x03E0 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_CRS__VDEC_DEBUG_32                        0x0098 0x03E0 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_CRS__PCIE_CTRL_DEBUG_26                   0x0098 0x03E0 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK                      0x009C 0x03E4 0x0774 0x0 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M                 0x009C 0x03E4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__I2C3_SCL                          0x009C 0x03E4 0x07B8 0x2 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__UART1_RTS_B                       0x009C 0x03E4 0x082C 0x3 0x2
+#define MX6SX_PAD_ENET2_RX_CLK__MLB_DATA                          0x009C 0x03E4 0x07EC 0x4 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8                        0x009C 0x03E4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__USB_OTG2_OC                       0x009C 0x03E4 0x085C 0x6 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__LCDIF2_DATA_22                    0x009C 0x03E4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__VDEC_DEBUG_31                     0x009C 0x03E4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__PCIE_CTRL_DEBUG_25                0x009C 0x03E4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__ENET2_TX_CLK                      0x00A0 0x03E8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2                    0x00A0 0x03E8 0x076C 0x1 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA                          0x00A0 0x03E8 0x07BC 0x2 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__UART1_CTS_B                       0x00A0 0x03E8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__MLB_CLK                           0x00A0 0x03E8 0x07E8 0x4 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9                        0x00A0 0x03E8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__USB_OTG2_PWR                      0x00A0 0x03E8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__LCDIF2_DATA_23                    0x00A0 0x03E8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__VDEC_DEBUG_30                     0x00A0 0x03E8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__PCIE_CTRL_DEBUG_24                0x00A0 0x03E8 0x0000 0x9 0x0
+#define MX6SX_PAD_KEY_COL0__KPP_COL_0                             0x00A4 0x03EC 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL0__USDHC3_CD_B                           0x00A4 0x03EC 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL0__UART6_RTS_B                           0x00A4 0x03EC 0x0854 0x2 0x2
+#define MX6SX_PAD_KEY_COL0__ECSPI1_SCLK                           0x00A4 0x03EC 0x0710 0x3 0x0
+#define MX6SX_PAD_KEY_COL0__AUDMUX_AUD5_TXC                       0x00A4 0x03EC 0x066C 0x4 0x0
+#define MX6SX_PAD_KEY_COL0__GPIO2_IO_10                           0x00A4 0x03EC 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL0__SDMA_EXT_EVENT_1                      0x00A4 0x03EC 0x0820 0x6 0x1
+#define MX6SX_PAD_KEY_COL0__SAI2_TX_BCLK                          0x00A4 0x03EC 0x0814 0x7 0x0
+#define MX6SX_PAD_KEY_COL0__VADC_DATA_0                           0x00A4 0x03EC 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_COL1__KPP_COL_1                             0x00A8 0x03F0 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL1__USDHC3_RESET_B                        0x00A8 0x03F0 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL1__UART6_RX                              0x00A8 0x03F0 0x0858 0x2 0x2
+#define MX6SX_PAD_KEY_COL1__UART6_TX                              0x00A8 0x03F0 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_COL1__ECSPI1_MISO                           0x00A8 0x03F0 0x0714 0x3 0x0
+#define MX6SX_PAD_KEY_COL1__AUDMUX_AUD5_TXFS                      0x00A8 0x03F0 0x0670 0x4 0x0
+#define MX6SX_PAD_KEY_COL1__GPIO2_IO_11                           0x00A8 0x03F0 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL1__USDHC3_RESET                          0x00A8 0x03F0 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL1__SAI2_TX_SYNC                          0x00A8 0x03F0 0x0818 0x7 0x0
+#define MX6SX_PAD_KEY_COL2__KPP_COL_2                             0x00AC 0x03F4 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL2__USDHC4_CD_B                           0x00AC 0x03F4 0x0874 0x1 0x1
+#define MX6SX_PAD_KEY_COL2__UART5_RTS_B                           0x00AC 0x03F4 0x084C 0x2 0x2
+#define MX6SX_PAD_KEY_COL2__CAN1_TX                               0x00AC 0x03F4 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL2__CANFD_TX1                             0x00AC 0x03F4 0x0000 0x4 0x0
+#define MX6SX_PAD_KEY_COL2__GPIO2_IO_12                           0x00AC 0x03F4 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL2__WEIM_DATA_30                          0x00AC 0x03F4 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL2__ECSPI1_RDY                            0x00AC 0x03F4 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_COL3__KPP_COL_3                             0x00B0 0x03F8 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL3__USDHC4_LCTL                           0x00B0 0x03F8 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL3__UART5_RX                              0x00B0 0x03F8 0x0850 0x2 0x2
+#define MX6SX_PAD_KEY_COL3__UART5_TX                              0x00B0 0x03F8 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_COL3__CAN2_TX                               0x00B0 0x03F8 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL3__CANFD_TX2                             0x00B0 0x03F8 0x0000 0x4 0x0
+#define MX6SX_PAD_KEY_COL3__GPIO2_IO_13                           0x00B0 0x03F8 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL3__WEIM_DATA_28                          0x00B0 0x03F8 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL3__ECSPI1_SS2                            0x00B0 0x03F8 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_COL4__KPP_COL_4                             0x00B4 0x03FC 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL4__ENET2_MDC                             0x00B4 0x03FC 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL4__I2C3_SCL                              0x00B4 0x03FC 0x07B8 0x2 0x2
+#define MX6SX_PAD_KEY_COL4__USDHC2_LCTL                           0x00B4 0x03FC 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL4__AUDMUX_AUD5_RXC                       0x00B4 0x03FC 0x0664 0x4 0x0
+#define MX6SX_PAD_KEY_COL4__GPIO2_IO_14                           0x00B4 0x03FC 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL4__WEIM_CRE                              0x00B4 0x03FC 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL4__SAI2_RX_BCLK                          0x00B4 0x03FC 0x0808 0x7 0x0
+#define MX6SX_PAD_KEY_ROW0__KPP_ROW_0                             0x00B8 0x0400 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW0__USDHC3_WP                             0x00B8 0x0400 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW0__UART6_CTS_B                           0x00B8 0x0400 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI                           0x00B8 0x0400 0x0718 0x3 0x0
+#define MX6SX_PAD_KEY_ROW0__AUDMUX_AUD5_TXD                       0x00B8 0x0400 0x0660 0x4 0x0
+#define MX6SX_PAD_KEY_ROW0__GPIO2_IO_15                           0x00B8 0x0400 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW0__SDMA_EXT_EVENT_0                      0x00B8 0x0400 0x081C 0x6 0x1
+#define MX6SX_PAD_KEY_ROW0__SAI2_TX_DATA_0                        0x00B8 0x0400 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW0__GPU_IDLE                              0x00B8 0x0400 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_ROW1__KPP_ROW_1                             0x00BC 0x0404 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW1__USDHC4_VSELECT                        0x00BC 0x0404 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW1__UART6_RX                              0x00BC 0x0404 0x0858 0x2 0x3
+#define MX6SX_PAD_KEY_ROW1__UART6_TX                              0x00BC 0x0404 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW1__ECSPI1_SS0                            0x00BC 0x0404 0x071C 0x3 0x0
+#define MX6SX_PAD_KEY_ROW1__AUDMUX_AUD5_RXD                       0x00BC 0x0404 0x065C 0x4 0x0
+#define MX6SX_PAD_KEY_ROW1__GPIO2_IO_16                           0x00BC 0x0404 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW1__WEIM_DATA_31                          0x00BC 0x0404 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW1__SAI2_RX_DATA_0                        0x00BC 0x0404 0x080C 0x7 0x0
+#define MX6SX_PAD_KEY_ROW1__M4_NMI                                0x00BC 0x0404 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_ROW2__KPP_ROW_2                             0x00C0 0x0408 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW2__USDHC4_WP                             0x00C0 0x0408 0x0878 0x1 0x1
+#define MX6SX_PAD_KEY_ROW2__UART5_CTS_B                           0x00C0 0x0408 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW2__CAN1_RX                               0x00C0 0x0408 0x068C 0x3 0x1
+#define MX6SX_PAD_KEY_ROW2__CANFD_RX1                             0x00C0 0x0408 0x0694 0x4 0x1
+#define MX6SX_PAD_KEY_ROW2__GPIO2_IO_17                           0x00C0 0x0408 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW2__WEIM_DATA_29                          0x00C0 0x0408 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW2__ECSPI1_SS3                            0x00C0 0x0408 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW3__KPP_ROW_3                             0x00C4 0x040C 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW3__USDHC3_LCTL                           0x00C4 0x040C 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW3__UART5_RX                              0x00C4 0x040C 0x0850 0x2 0x3
+#define MX6SX_PAD_KEY_ROW3__UART5_TX                              0x00C4 0x040C 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW3__CAN2_RX                               0x00C4 0x040C 0x0690 0x3 0x1
+#define MX6SX_PAD_KEY_ROW3__CANFD_RX2                             0x00C4 0x040C 0x0698 0x4 0x1
+#define MX6SX_PAD_KEY_ROW3__GPIO2_IO_18                           0x00C4 0x040C 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW3__WEIM_DTACK_B                          0x00C4 0x040C 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW3__ECSPI1_SS1                            0x00C4 0x040C 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW4__KPP_ROW_4                             0x00C8 0x0410 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW4__ENET2_MDIO                            0x00C8 0x0410 0x0770 0x1 0x3
+#define MX6SX_PAD_KEY_ROW4__I2C3_SDA                              0x00C8 0x0410 0x07BC 0x2 0x2
+#define MX6SX_PAD_KEY_ROW4__USDHC1_LCTL                           0x00C8 0x0410 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_ROW4__AUDMUX_AUD5_RXFS                      0x00C8 0x0410 0x0668 0x4 0x0
+#define MX6SX_PAD_KEY_ROW4__GPIO2_IO_19                           0x00C8 0x0410 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW4__WEIM_ACLK_FREERUN                     0x00C8 0x0410 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW4__SAI2_RX_SYNC                          0x00C8 0x0410 0x0810 0x7 0x0
+#define MX6SX_PAD_LCD1_CLK__LCDIF1_CLK                            0x00CC 0x0414 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_CLK__LCDIF1_WR_RWN                         0x00CC 0x0414 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_CLK__AUDMUX_AUD3_RXC                       0x00CC 0x0414 0x0634 0x2 0x1
+#define MX6SX_PAD_LCD1_CLK__ENET1_1588_EVENT2_IN                  0x00CC 0x0414 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_CLK__CSI1_DATA_16                          0x00CC 0x0414 0x06DC 0x4 0x0
+#define MX6SX_PAD_LCD1_CLK__GPIO3_IO_0                            0x00CC 0x0414 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_CLK__USDHC1_WP                             0x00CC 0x0414 0x0868 0x6 0x0
+#define MX6SX_PAD_LCD1_CLK__SIM_M_HADDR_16                        0x00CC 0x0414 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_CLK__VADC_TEST_0                           0x00CC 0x0414 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_CLK__MMDC_DEBUG_0                          0x00CC 0x0414 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0                      0x00D0 0x0418 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA00__WEIM_CS1_B                         0x00D0 0x0418 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA00__M4_TRACE_0                         0x00D0 0x0418 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA00__KITTEN_TRACE_0                     0x00D0 0x0418 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA00__CSI1_DATA_20                       0x00D0 0x0418 0x06EC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA00__GPIO3_IO_1                         0x00D0 0x0418 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA00__SRC_BT_CFG_0                       0x00D0 0x0418 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA00__SIM_M_HADDR_21                     0x00D0 0x0418 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA00__VADC_TEST_5                        0x00D0 0x0418 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA00__MMDC_DEBUG_5                       0x00D0 0x0418 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1                      0x00D4 0x041C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA01__WEIM_CS2_B                         0x00D4 0x041C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA01__M4_TRACE_1                         0x00D4 0x041C 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA01__KITTEN_TRACE_1                     0x00D4 0x041C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA01__CSI1_DATA_21                       0x00D4 0x041C 0x06F0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA01__GPIO3_IO_2                         0x00D4 0x041C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA01__SRC_BT_CFG_1                       0x00D4 0x041C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA01__SIM_M_HADDR_22                     0x00D4 0x041C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA01__VADC_TEST_6                        0x00D4 0x041C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA01__MMDC_DEBUG_6                       0x00D4 0x041C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2                      0x00D8 0x0420 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA02__WEIM_CS3_B                         0x00D8 0x0420 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA02__M4_TRACE_2                         0x00D8 0x0420 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA02__KITTEN_TRACE_2                     0x00D8 0x0420 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA02__CSI1_DATA_22                       0x00D8 0x0420 0x06F4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA02__GPIO3_IO_3                         0x00D8 0x0420 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA02__SRC_BT_CFG_2                       0x00D8 0x0420 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA02__SIM_M_HADDR_23                     0x00D8 0x0420 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA02__VADC_TEST_7                        0x00D8 0x0420 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA02__MMDC_DEBUG_7                       0x00D8 0x0420 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3                      0x00DC 0x0424 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA03__WEIM_ADDR_24                       0x00DC 0x0424 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA03__M4_TRACE_3                         0x00DC 0x0424 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA03__KITTEN_TRACE_3                     0x00DC 0x0424 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA03__CSI1_DATA_23                       0x00DC 0x0424 0x06F8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA03__GPIO3_IO_4                         0x00DC 0x0424 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA03__SRC_BT_CFG_3                       0x00DC 0x0424 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA03__SIM_M_HADDR_24                     0x00DC 0x0424 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA03__VADC_TEST_8                        0x00DC 0x0424 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA03__MMDC_DEBUG_8                       0x00DC 0x0424 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4                      0x00E0 0x0428 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA04__WEIM_ADDR_25                       0x00E0 0x0428 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA04__KITTEN_TRACE_4                     0x00E0 0x0428 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA04__CSI1_VSYNC                         0x00E0 0x0428 0x0708 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA04__GPIO3_IO_5                         0x00E0 0x0428 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA04__SRC_BT_CFG_4                       0x00E0 0x0428 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA04__SIM_M_HADDR_25                     0x00E0 0x0428 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA04__VADC_TEST_9                        0x00E0 0x0428 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA04__MMDC_DEBUG_9                       0x00E0 0x0428 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5                      0x00E4 0x042C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA05__WEIM_ADDR_26                       0x00E4 0x042C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA05__KITTEN_TRACE_5                     0x00E4 0x042C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA05__CSI1_HSYNC                         0x00E4 0x042C 0x0700 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA05__GPIO3_IO_6                         0x00E4 0x042C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA05__SRC_BT_CFG_5                       0x00E4 0x042C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA05__SIM_M_HADDR_26                     0x00E4 0x042C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA05__VADC_TEST_10                       0x00E4 0x042C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA05__MMDC_DEBUG_10                      0x00E4 0x042C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6                      0x00E8 0x0430 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA06__WEIM_EB_B_2                        0x00E8 0x0430 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA06__KITTEN_TRACE_6                     0x00E8 0x0430 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA06__CSI1_PIXCLK                        0x00E8 0x0430 0x0704 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA06__GPIO3_IO_7                         0x00E8 0x0430 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA06__SRC_BT_CFG_6                       0x00E8 0x0430 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA06__SIM_M_HADDR_27                     0x00E8 0x0430 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA06__VADC_TEST_11                       0x00E8 0x0430 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA06__MMDC_DEBUG_11                      0x00E8 0x0430 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7                      0x00EC 0x0434 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA07__WEIM_EB_B_3                        0x00EC 0x0434 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA07__KITTEN_TRACE_7                     0x00EC 0x0434 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA07__CSI1_MCLK                          0x00EC 0x0434 0x0000 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA07__GPIO3_IO_8                         0x00EC 0x0434 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA07__SRC_BT_CFG_7                       0x00EC 0x0434 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA07__SIM_M_HADDR_28                     0x00EC 0x0434 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA07__VADC_TEST_12                       0x00EC 0x0434 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA07__MMDC_DEBUG_12                      0x00EC 0x0434 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8                      0x00F0 0x0438 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA08__WEIM_AD_8                          0x00F0 0x0438 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA08__KITTEN_TRACE_8                     0x00F0 0x0438 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA08__CSI1_DATA_9                        0x00F0 0x0438 0x06C4 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA08__GPIO3_IO_9                         0x00F0 0x0438 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA08__SRC_BT_CFG_8                       0x00F0 0x0438 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA08__SIM_M_HADDR_29                     0x00F0 0x0438 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA08__VADC_TEST_13                       0x00F0 0x0438 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA08__MMDC_DEBUG_13                      0x00F0 0x0438 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9                      0x00F4 0x043C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA09__WEIM_AD_9                          0x00F4 0x043C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA09__KITTEN_TRACE_9                     0x00F4 0x043C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA09__CSI1_DATA_8                        0x00F4 0x043C 0x06C0 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA09__GPIO3_IO_10                        0x00F4 0x043C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA09__SRC_BT_CFG_9                       0x00F4 0x043C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA09__SIM_M_HADDR_30                     0x00F4 0x043C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA09__VADC_TEST_14                       0x00F4 0x043C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA09__MMDC_DEBUG_14                      0x00F4 0x043C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10                     0x00F8 0x0440 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA10__WEIM_AD_10                         0x00F8 0x0440 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA10__KITTEN_TRACE_10                    0x00F8 0x0440 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA10__CSI1_DATA_7                        0x00F8 0x0440 0x06BC 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA10__GPIO3_IO_11                        0x00F8 0x0440 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA10__SRC_BT_CFG_10                      0x00F8 0x0440 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA10__SIM_M_HADDR_31                     0x00F8 0x0440 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA10__VADC_TEST_15                       0x00F8 0x0440 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA10__MMDC_DEBUG_15                      0x00F8 0x0440 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11                     0x00FC 0x0444 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA11__WEIM_AD_11                         0x00FC 0x0444 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA11__KITTEN_TRACE_11                    0x00FC 0x0444 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA11__CSI1_DATA_6                        0x00FC 0x0444 0x06B8 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA11__GPIO3_IO_12                        0x00FC 0x0444 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA11__SRC_BT_CFG_11                      0x00FC 0x0444 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA11__SIM_M_HBURST_0                     0x00FC 0x0444 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA11__VADC_TEST_16                       0x00FC 0x0444 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA11__MMDC_DEBUG_16                      0x00FC 0x0444 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12                     0x0100 0x0448 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA12__WEIM_AD_12                         0x0100 0x0448 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA12__KITTEN_TRACE_12                    0x0100 0x0448 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA12__CSI1_DATA_5                        0x0100 0x0448 0x06B4 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA12__GPIO3_IO_13                        0x0100 0x0448 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA12__SRC_BT_CFG_12                      0x0100 0x0448 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA12__SIM_M_HBURST_1                     0x0100 0x0448 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA12__VADC_TEST_17                       0x0100 0x0448 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA12__MMDC_DEBUG_17                      0x0100 0x0448 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13                     0x0104 0x044C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA13__WEIM_AD_13                         0x0104 0x044C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA13__KITTEN_TRACE_13                    0x0104 0x044C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA13__CSI1_DATA_4                        0x0104 0x044C 0x06B0 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA13__GPIO3_IO_14                        0x0104 0x044C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA13__SRC_BT_CFG_13                      0x0104 0x044C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA13__SIM_M_HBURST_2                     0x0104 0x044C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA13__VADC_TEST_18                       0x0104 0x044C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA13__MMDC_DEBUG_18                      0x0104 0x044C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14                     0x0108 0x0450 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA14__WEIM_AD_14                         0x0108 0x0450 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA14__KITTEN_TRACE_14                    0x0108 0x0450 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA14__CSI1_DATA_3                        0x0108 0x0450 0x06AC 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA14__GPIO3_IO_15                        0x0108 0x0450 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA14__SRC_BT_CFG_14                      0x0108 0x0450 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA14__SIM_M_HMASTLOCK                    0x0108 0x0450 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA14__VADC_TEST_19                       0x0108 0x0450 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA14__MMDC_DEBUG_19                      0x0108 0x0450 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15                     0x010C 0x0454 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA15__WEIM_AD_15                         0x010C 0x0454 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA15__KITTEN_TRACE_15                    0x010C 0x0454 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA15__CSI1_DATA_2                        0x010C 0x0454 0x06A8 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA15__GPIO3_IO_16                        0x010C 0x0454 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA15__SRC_BT_CFG_15                      0x010C 0x0454 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA15__SIM_M_HPROT_0                      0x010C 0x0454 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA15__VDEC_DEBUG_0                       0x010C 0x0454 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA15__MMDC_DEBUG_20                      0x010C 0x0454 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16                     0x0110 0x0458 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA16__WEIM_ADDR_16                       0x0110 0x0458 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA16__M4_TRACE_CLK                       0x0110 0x0458 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA16__KITTEN_TRACE_CLK                   0x0110 0x0458 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA16__CSI1_DATA_1                        0x0110 0x0458 0x06A4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA16__GPIO3_IO_17                        0x0110 0x0458 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA16__SRC_BT_CFG_24                      0x0110 0x0458 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA16__SIM_M_HPROT_1                      0x0110 0x0458 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA16__VDEC_DEBUG_1                       0x0110 0x0458 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA16__MMDC_DEBUG_21                      0x0110 0x0458 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17                     0x0114 0x045C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA17__WEIM_ADDR_17                       0x0114 0x045C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA17__KITTEN_TRACE_CTL                   0x0114 0x045C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA17__CSI1_DATA_0                        0x0114 0x045C 0x06A0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA17__GPIO3_IO_18                        0x0114 0x045C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA17__SRC_BT_CFG_25                      0x0114 0x045C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA17__SIM_M_HPROT_2                      0x0114 0x045C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA17__VDEC_DEBUG_2                       0x0114 0x045C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA17__MMDC_DEBUG_22                      0x0114 0x045C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18                     0x0118 0x0460 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA18__WEIM_ADDR_18                       0x0118 0x0460 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA18__M4_EVENTO                          0x0118 0x0460 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA18__KITTEN_EVENTO                      0x0118 0x0460 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA18__CSI1_DATA_15                       0x0118 0x0460 0x06D8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA18__GPIO3_IO_19                        0x0118 0x0460 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA18__SRC_BT_CFG_26                      0x0118 0x0460 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA18__SIM_M_HPROT_3                      0x0118 0x0460 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA18__VDEC_DEBUG_3                       0x0118 0x0460 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA18__MMDC_DEBUG_23                      0x0118 0x0460 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19                     0x011C 0x0464 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA19__WEIM_ADDR_19                       0x011C 0x0464 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA19__M4_TRACE_SWO                       0x011C 0x0464 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA19__CSI1_DATA_14                       0x011C 0x0464 0x06D4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA19__GPIO3_IO_20                        0x011C 0x0464 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA19__SRC_BT_CFG_27                      0x011C 0x0464 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA19__SIM_M_HREADYOUT                    0x011C 0x0464 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA19__VDEC_DEBUG_4                       0x011C 0x0464 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA19__MMDC_DEBUG_24                      0x011C 0x0464 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20                     0x0120 0x0468 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA20__WEIM_ADDR_20                       0x0120 0x0468 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA20__PWM8_OUT                           0x0120 0x0468 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA20__ENET1_1588_EVENT2_OUT              0x0120 0x0468 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA20__CSI1_DATA_13                       0x0120 0x0468 0x06D0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA20__GPIO3_IO_21                        0x0120 0x0468 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA20__SRC_BT_CFG_28                      0x0120 0x0468 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA20__SIM_M_HRESP                        0x0120 0x0468 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA20__VDEC_DEBUG_5                       0x0120 0x0468 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA20__MMDC_DEBUG_25                      0x0120 0x0468 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21                     0x0124 0x046C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA21__WEIM_ADDR_21                       0x0124 0x046C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA21__PWM7_OUT                           0x0124 0x046C 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA21__ENET1_1588_EVENT3_OUT              0x0124 0x046C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA21__CSI1_DATA_12                       0x0124 0x046C 0x06CC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA21__GPIO3_IO_22                        0x0124 0x046C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA21__SRC_BT_CFG_29                      0x0124 0x046C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA21__SIM_M_HSIZE_0                      0x0124 0x046C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA21__VDEC_DEBUG_6                       0x0124 0x046C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA21__MMDC_DEBUG_26                      0x0124 0x046C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22                     0x0128 0x0470 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA22__WEIM_ADDR_22                       0x0128 0x0470 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA22__PWM6_OUT                           0x0128 0x0470 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA22__ENET2_1588_EVENT2_OUT              0x0128 0x0470 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA22__CSI1_DATA_11                       0x0128 0x0470 0x06C8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA22__GPIO3_IO_23                        0x0128 0x0470 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA22__SRC_BT_CFG_30                      0x0128 0x0470 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA22__SIM_M_HSIZE_1                      0x0128 0x0470 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA22__VDEC_DEBUG_7                       0x0128 0x0470 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA22__MMDC_DEBUG_27                      0x0128 0x0470 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23                     0x012C 0x0474 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA23__WEIM_ADDR_23                       0x012C 0x0474 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA23__PWM5_OUT                           0x012C 0x0474 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA23__ENET2_1588_EVENT3_OUT              0x012C 0x0474 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA23__CSI1_DATA_10                       0x012C 0x0474 0x06FC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA23__GPIO3_IO_24                        0x012C 0x0474 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA23__SRC_BT_CFG_31                      0x012C 0x0474 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA23__SIM_M_HSIZE_2                      0x012C 0x0474 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA23__VDEC_DEBUG_8                       0x012C 0x0474 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA23__MMDC_DEBUG_28                      0x012C 0x0474 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE                      0x0130 0x0478 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_ENABLE__LCDIF1_RD_E                        0x0130 0x0478 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_ENABLE__AUDMUX_AUD3_TXC                    0x0130 0x0478 0x063C 0x2 0x1
+#define MX6SX_PAD_LCD1_ENABLE__ENET1_1588_EVENT3_IN               0x0130 0x0478 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_ENABLE__CSI1_DATA_17                       0x0130 0x0478 0x06E0 0x4 0x0
+#define MX6SX_PAD_LCD1_ENABLE__GPIO3_IO_25                        0x0130 0x0478 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_ENABLE__USDHC1_CD_B                        0x0130 0x0478 0x0864 0x6 0x0
+#define MX6SX_PAD_LCD1_ENABLE__SIM_M_HADDR_17                     0x0130 0x0478 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_ENABLE__VADC_TEST_1                        0x0130 0x0478 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_ENABLE__MMDC_DEBUG_1                       0x0130 0x0478 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC                        0x0134 0x047C 0x07E0 0x0 0x0
+#define MX6SX_PAD_LCD1_HSYNC__LCDIF1_RS                           0x0134 0x047C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_HSYNC__AUDMUX_AUD3_TXD                     0x0134 0x047C 0x0630 0x2 0x1
+#define MX6SX_PAD_LCD1_HSYNC__ENET2_1588_EVENT2_IN                0x0134 0x047C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_HSYNC__CSI1_DATA_18                        0x0134 0x047C 0x06E4 0x4 0x0
+#define MX6SX_PAD_LCD1_HSYNC__GPIO3_IO_26                         0x0134 0x047C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_HSYNC__USDHC2_WP                           0x0134 0x047C 0x0870 0x6 0x0
+#define MX6SX_PAD_LCD1_HSYNC__SIM_M_HADDR_18                      0x0134 0x047C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_HSYNC__VADC_TEST_2                         0x0134 0x047C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_HSYNC__MMDC_DEBUG_2                        0x0134 0x047C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_RESET__LCDIF1_RESET                        0x0138 0x0480 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_RESET__LCDIF1_CS                           0x0138 0x0480 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_RESET__AUDMUX_AUD3_RXD                     0x0138 0x0480 0x062C 0x2 0x1
+#define MX6SX_PAD_LCD1_RESET__KITTEN_EVENTI                       0x0138 0x0480 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_RESET__M4_EVENTI                           0x0138 0x0480 0x0000 0x4 0x0
+#define MX6SX_PAD_LCD1_RESET__GPIO3_IO_27                         0x0138 0x0480 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_RESET__CCM_PMIC_RDY                        0x0138 0x0480 0x069C 0x6 0x0
+#define MX6SX_PAD_LCD1_RESET__SIM_M_HADDR_20                      0x0138 0x0480 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_RESET__VADC_TEST_4                         0x0138 0x0480 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_RESET__MMDC_DEBUG_4                        0x0138 0x0480 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC                        0x013C 0x0484 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_VSYNC__LCDIF1_BUSY                         0x013C 0x0484 0x07E0 0x1 0x1
+#define MX6SX_PAD_LCD1_VSYNC__AUDMUX_AUD3_TXFS                    0x013C 0x0484 0x0640 0x2 0x1
+#define MX6SX_PAD_LCD1_VSYNC__ENET2_1588_EVENT3_IN                0x013C 0x0484 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_VSYNC__CSI1_DATA_19                        0x013C 0x0484 0x06E8 0x4 0x0
+#define MX6SX_PAD_LCD1_VSYNC__GPIO3_IO_28                         0x013C 0x0484 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_VSYNC__USDHC2_CD_B                         0x013C 0x0484 0x086C 0x6 0x0
+#define MX6SX_PAD_LCD1_VSYNC__SIM_M_HADDR_19                      0x013C 0x0484 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_VSYNC__VADC_TEST_3                         0x013C 0x0484 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_VSYNC__MMDC_DEBUG_3                        0x013C 0x0484 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_ALE__RAWNAND_ALE                           0x0140 0x0488 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_ALE__I2C3_SDA                              0x0140 0x0488 0x07BC 0x1 0x0
+#define MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B                         0x0140 0x0488 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_ALE__ECSPI2_SS0                            0x0140 0x0488 0x072C 0x3 0x0
+#define MX6SX_PAD_NAND_ALE__ESAI_TX3_RX2                          0x0140 0x0488 0x079C 0x4 0x0
+#define MX6SX_PAD_NAND_ALE__GPIO4_IO_0                            0x0140 0x0488 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_ALE__WEIM_CS0_B                            0x0140 0x0488 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_ALE__TPSMP_HDATA_0                         0x0140 0x0488 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_ALE__ANATOP_USBPHY1_TSTI_TX_EN             0x0140 0x0488 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_ALE__SDMA_DEBUG_PC_12                      0x0140 0x0488 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CE0_B__RAWNAND_CE0_B                       0x0144 0x048C 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CE0_B__USDHC2_VSELECT                      0x0144 0x048C 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2                      0x0144 0x048C 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CE0_B__AUDMUX_AUD4_TXC                     0x0144 0x048C 0x0654 0x3 0x0
+#define MX6SX_PAD_NAND_CE0_B__ESAI_TX_CLK                         0x0144 0x048C 0x078C 0x4 0x0
+#define MX6SX_PAD_NAND_CE0_B__GPIO4_IO_1                          0x0144 0x048C 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CE0_B__WEIM_LBA_B                          0x0144 0x048C 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CE0_B__TPSMP_HDATA_3                       0x0144 0x048C 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CE0_B__ANATOP_USBPHY1_TSTI_TX_HIZ          0x0144 0x048C 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CE0_B__SDMA_DEBUG_PC_9                     0x0144 0x048C 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CE1_B__RAWNAND_CE1_B                       0x0148 0x0490 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CE1_B__USDHC3_RESET_B                      0x0148 0x0490 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3                      0x0148 0x0490 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CE1_B__AUDMUX_AUD4_TXD                     0x0148 0x0490 0x0648 0x3 0x0
+#define MX6SX_PAD_NAND_CE1_B__ESAI_TX0                            0x0148 0x0490 0x0790 0x4 0x0
+#define MX6SX_PAD_NAND_CE1_B__GPIO4_IO_2                          0x0148 0x0490 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CE1_B__WEIM_OE                             0x0148 0x0490 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CE1_B__TPSMP_HDATA_4                       0x0148 0x0490 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CE1_B__ANATOP_USBPHY1_TSTI_TX_LS_MODE      0x0148 0x0490 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CE1_B__SDMA_DEBUG_PC_8                     0x0148 0x0490 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CLE__RAWNAND_CLE                           0x014C 0x0494 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CLE__I2C3_SCL                              0x014C 0x0494 0x07B8 0x1 0x0
+#define MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK                          0x014C 0x0494 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CLE__ECSPI2_SCLK                           0x014C 0x0494 0x0720 0x3 0x0
+#define MX6SX_PAD_NAND_CLE__ESAI_TX2_RX3                          0x014C 0x0494 0x0798 0x4 0x0
+#define MX6SX_PAD_NAND_CLE__GPIO4_IO_3                            0x014C 0x0494 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CLE__WEIM_BCLK                             0x014C 0x0494 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CLE__TPSMP_CLK                             0x014C 0x0494 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CLE__ANATOP_USBPHY1_TSTI_TX_DP             0x014C 0x0494 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CLE__SDMA_DEBUG_PC_13                      0x014C 0x0494 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA00__RAWNAND_DATA00                     0x0150 0x0498 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA00__USDHC1_DATA4                       0x0150 0x0498 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1                     0x0150 0x0498 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA00__ECSPI5_MISO                        0x0150 0x0498 0x0754 0x3 0x0
+#define MX6SX_PAD_NAND_DATA00__ESAI_RX_CLK                        0x0150 0x0498 0x0788 0x4 0x0
+#define MX6SX_PAD_NAND_DATA00__GPIO4_IO_4                         0x0150 0x0498 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA00__WEIM_AD_0                          0x0150 0x0498 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA00__TPSMP_HDATA_7                      0x0150 0x0498 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA00__ANATOP_USBPHY1_TSTO_RX_DISCON_DET  0x0150 0x0498 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA00__SDMA_DEBUG_EVT_CHN_LINES_5         0x0150 0x0498 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA01__RAWNAND_DATA01                     0x0154 0x049C 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA01__USDHC1_DATA5                       0x0154 0x049C 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0                     0x0154 0x049C 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA01__ECSPI5_MOSI                        0x0154 0x049C 0x0758 0x3 0x0
+#define MX6SX_PAD_NAND_DATA01__ESAI_RX_FS                         0x0154 0x049C 0x0778 0x4 0x0
+#define MX6SX_PAD_NAND_DATA01__GPIO4_IO_5                         0x0154 0x049C 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA01__WEIM_AD_1                          0x0154 0x049C 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA01__TPSMP_HDATA_8                      0x0154 0x049C 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA01__ANATOP_USBPHY1_TSTO_RX_HS_RXD      0x0154 0x049C 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA01__SDMA_DEBUG_EVT_CHN_LINES_4         0x0154 0x049C 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA02__RAWNAND_DATA02                     0x0158 0x04A0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA02__USDHC1_DATA6                       0x0158 0x04A0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK                       0x0158 0x04A0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA02__ECSPI5_SCLK                        0x0158 0x04A0 0x0750 0x3 0x0
+#define MX6SX_PAD_NAND_DATA02__ESAI_TX_HF_CLK                     0x0158 0x04A0 0x0784 0x4 0x0
+#define MX6SX_PAD_NAND_DATA02__GPIO4_IO_6                         0x0158 0x04A0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA02__WEIM_AD_2                          0x0158 0x04A0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA02__TPSMP_HDATA_9                      0x0158 0x04A0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA02__ANATOP_USBPHY2_TSTO_PLL_CLK20DIV   0x0158 0x04A0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA02__SDMA_DEBUG_EVT_CHN_LINES_3         0x0158 0x04A0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA03__RAWNAND_DATA03                     0x015C 0x04A4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA03__USDHC1_DATA7                       0x015C 0x04A4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B                      0x015C 0x04A4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA03__ECSPI5_SS0                         0x015C 0x04A4 0x075C 0x3 0x0
+#define MX6SX_PAD_NAND_DATA03__ESAI_RX_HF_CLK                     0x015C 0x04A4 0x0780 0x4 0x0
+#define MX6SX_PAD_NAND_DATA03__GPIO4_IO_7                         0x015C 0x04A4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA03__WEIM_AD_3                          0x015C 0x04A4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA03__TPSMP_HDATA_10                     0x015C 0x04A4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA03__ANATOP_USBPHY1_TSTO_RX_SQUELCH     0x015C 0x04A4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA03__SDMA_DEBUG_EVT_CHN_LINES_6         0x015C 0x04A4 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA04__RAWNAND_DATA04                     0x0160 0x04A8 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA04__USDHC2_DATA4                       0x0160 0x04A8 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA04__QSPI2_B_SS1_B                      0x0160 0x04A8 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA04__UART3_RTS_B                        0x0160 0x04A8 0x083C 0x3 0x0
+#define MX6SX_PAD_NAND_DATA04__AUDMUX_AUD4_RXFS                   0x0160 0x04A8 0x0650 0x4 0x0
+#define MX6SX_PAD_NAND_DATA04__GPIO4_IO_8                         0x0160 0x04A8 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA04__WEIM_AD_4                          0x0160 0x04A8 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA04__TPSMP_HDATA_11                     0x0160 0x04A8 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA04__ANATOP_USBPHY2_TSTO_RX_SQUELCH     0x0160 0x04A8 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA04__SDMA_DEBUG_CORE_STATE_0            0x0160 0x04A8 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA05__RAWNAND_DATA05                     0x0164 0x04AC 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA05__USDHC2_DATA5                       0x0164 0x04AC 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA05__QSPI2_B_DQS                        0x0164 0x04AC 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA05__UART3_CTS_B                        0x0164 0x04AC 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA05__AUDMUX_AUD4_RXC                    0x0164 0x04AC 0x064C 0x4 0x0
+#define MX6SX_PAD_NAND_DATA05__GPIO4_IO_9                         0x0164 0x04AC 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA05__WEIM_AD_5                          0x0164 0x04AC 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA05__TPSMP_HDATA_12                     0x0164 0x04AC 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA05__ANATOP_USBPHY2_TSTO_RX_DISCON_DET  0x0164 0x04AC 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA05__SDMA_DEBUG_CORE_STATE_1            0x0164 0x04AC 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA06__RAWNAND_DATA06                     0x0168 0x04B0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA06__USDHC2_DATA6                       0x0168 0x04B0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA06__QSPI2_A_SS1_B                      0x0168 0x04B0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA06__UART3_RX                           0x0168 0x04B0 0x0840 0x3 0x0
+#define MX6SX_PAD_NAND_DATA06__UART3_TX                           0x0168 0x04B0 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA06__PWM3_OUT                           0x0168 0x04B0 0x0000 0x4 0x0
+#define MX6SX_PAD_NAND_DATA06__GPIO4_IO_10                        0x0168 0x04B0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA06__WEIM_AD_6                          0x0168 0x04B0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA06__TPSMP_HDATA_13                     0x0168 0x04B0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA06__ANATOP_USBPHY2_TSTO_RX_FS_RXD      0x0168 0x04B0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA06__SDMA_DEBUG_CORE_STATE_2            0x0168 0x04B0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA07__RAWNAND_DATA07                     0x016C 0x04B4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA07__USDHC2_DATA7                       0x016C 0x04B4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA07__QSPI2_A_DQS                        0x016C 0x04B4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA07__UART3_RX                           0x016C 0x04B4 0x0840 0x3 0x1
+#define MX6SX_PAD_NAND_DATA07__UART3_TX                           0x016C 0x04B4 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA07__PWM4_OUT                           0x016C 0x04B4 0x0000 0x4 0x0
+#define MX6SX_PAD_NAND_DATA07__GPIO4_IO_11                        0x016C 0x04B4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA07__WEIM_AD_7                          0x016C 0x04B4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA07__TPSMP_HDATA_14                     0x016C 0x04B4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA07__ANATOP_USBPHY1_TSTO_RX_FS_RXD      0x016C 0x04B4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA07__SDMA_DEBUG_CORE_STATE_3            0x016C 0x04B4 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_RE_B__RAWNAND_RE_B                         0x0170 0x04B8 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_RE_B__USDHC2_RESET_B                       0x0170 0x04B8 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3                       0x0170 0x04B8 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_RE_B__AUDMUX_AUD4_TXFS                     0x0170 0x04B8 0x0658 0x3 0x0
+#define MX6SX_PAD_NAND_RE_B__ESAI_TX_FS                           0x0170 0x04B8 0x077C 0x4 0x0
+#define MX6SX_PAD_NAND_RE_B__GPIO4_IO_12                          0x0170 0x04B8 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_RE_B__WEIM_RW                              0x0170 0x04B8 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_RE_B__TPSMP_HDATA_5                        0x0170 0x04B8 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_RE_B__ANATOP_USBPHY2_TSTO_RX_HS_RXD        0x0170 0x04B8 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_RE_B__SDMA_DEBUG_PC_7                      0x0170 0x04B8 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_READY_B__RAWNAND_READY_B                   0x0174 0x04BC 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_READY_B__USDHC1_VSELECT                    0x0174 0x04BC 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1                    0x0174 0x04BC 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_READY_B__ECSPI2_MISO                       0x0174 0x04BC 0x0724 0x3 0x0
+#define MX6SX_PAD_NAND_READY_B__ESAI_TX1                          0x0174 0x04BC 0x0794 0x4 0x0
+#define MX6SX_PAD_NAND_READY_B__GPIO4_IO_13                       0x0174 0x04BC 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_READY_B__WEIM_EB_B_1                       0x0174 0x04BC 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_READY_B__TPSMP_HDATA_2                     0x0174 0x04BC 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_READY_B__ANATOP_USBPHY1_TSTI_TX_DN         0x0174 0x04BC 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_READY_B__SDMA_DEBUG_PC_10                  0x0174 0x04BC 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_WE_B__RAWNAND_WE_B                         0x0178 0x04C0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_WE_B__USDHC4_VSELECT                       0x0178 0x04C0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2                       0x0178 0x04C0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_WE_B__AUDMUX_AUD4_RXD                      0x0178 0x04C0 0x0644 0x3 0x0
+#define MX6SX_PAD_NAND_WE_B__ESAI_TX5_RX0                         0x0178 0x04C0 0x07A4 0x4 0x0
+#define MX6SX_PAD_NAND_WE_B__GPIO4_IO_14                          0x0178 0x04C0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_WE_B__WEIM_WAIT                            0x0178 0x04C0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_WE_B__TPSMP_HDATA_6                        0x0178 0x04C0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_WE_B__ANATOP_USBPHY1_TSTO_PLL_CLK20DIV     0x0178 0x04C0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_WE_B__SDMA_DEBUG_PC_6                      0x0178 0x04C0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_WP_B__RAWNAND_WP_B                         0x017C 0x04C4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_WP_B__USDHC1_RESET_B                       0x017C 0x04C4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0                       0x017C 0x04C4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_WP_B__ECSPI2_MOSI                          0x017C 0x04C4 0x0728 0x3 0x0
+#define MX6SX_PAD_NAND_WP_B__ESAI_TX4_RX1                         0x017C 0x04C4 0x07A0 0x4 0x0
+#define MX6SX_PAD_NAND_WP_B__GPIO4_IO_15                          0x017C 0x04C4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_WP_B__WEIM_EB_B_0                          0x017C 0x04C4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_WP_B__TPSMP_HDATA_1                        0x017C 0x04C4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_WP_B__ANATOP_USBPHY1_TSTI_TX_HS_MODE       0x017C 0x04C4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_WP_B__SDMA_DEBUG_PC_11                     0x017C 0x04C4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__QSPI1_A_DATA_0                    0x0180 0x04C8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__USB_OTG2_OC                       0x0180 0x04C8 0x085C 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA0__ECSPI1_MOSI                       0x0180 0x04C8 0x0718 0x2 0x1
+#define MX6SX_PAD_QSPI1A_DATA0__ESAI_TX4_RX1                      0x0180 0x04C8 0x07A0 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA0__CSI1_DATA_14                      0x0180 0x04C8 0x06D4 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16                       0x0180 0x04C8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__WEIM_DATA_6                       0x0180 0x04C8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__SIM_M_HADDR_3                     0x0180 0x04C8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__SDMA_DEBUG_BUS_DEVICE_3           0x0180 0x04C8 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__QSPI1_A_DATA_1                    0x0184 0x04CC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__ANATOP_OTG1_ID                    0x0184 0x04CC 0x0624 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA1__ECSPI1_MISO                       0x0184 0x04CC 0x0714 0x2 0x1
+#define MX6SX_PAD_QSPI1A_DATA1__ESAI_TX1                          0x0184 0x04CC 0x0794 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA1__CSI1_DATA_13                      0x0184 0x04CC 0x06D0 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA1__GPIO4_IO_17                       0x0184 0x04CC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__WEIM_DATA_5                       0x0184 0x04CC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__SIM_M_HADDR_4                     0x0184 0x04CC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__SDMA_DEBUG_PC_0                   0x0184 0x04CC 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__QSPI1_A_DATA_2                    0x0188 0x04D0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__USB_OTG1_PWR                      0x0188 0x04D0 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__ECSPI5_SS1                        0x0188 0x04D0 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__ESAI_TX_CLK                       0x0188 0x04D0 0x078C 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA2__CSI1_DATA_12                      0x0188 0x04D0 0x06CC 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA2__GPIO4_IO_18                       0x0188 0x04D0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__WEIM_DATA_4                       0x0188 0x04D0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__SIM_M_HADDR_6                     0x0188 0x04D0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__SDMA_DEBUG_PC_1                   0x0188 0x04D0 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__QSPI1_A_DATA_3                    0x018C 0x04D4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__USB_OTG1_OC                       0x018C 0x04D4 0x0860 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA3__ECSPI5_SS2                        0x018C 0x04D4 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__ESAI_TX0                          0x018C 0x04D4 0x0790 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA3__CSI1_DATA_11                      0x018C 0x04D4 0x06C8 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA3__GPIO4_IO_19                       0x018C 0x04D4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__WEIM_DATA_3                       0x018C 0x04D4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__SIM_M_HADDR_7                     0x018C 0x04D4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__SDMA_DEBUG_PC_2                   0x018C 0x04D4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DQS__QSPI1_A_DQS                         0x0190 0x04D8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DQS__CAN2_TX                             0x0190 0x04D8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_DQS__CANFD_TX2                           0x0190 0x04D8 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DQS__ECSPI5_MOSI                         0x0190 0x04D8 0x0758 0x3 0x1
+#define MX6SX_PAD_QSPI1A_DQS__CSI1_DATA_15                        0x0190 0x04D8 0x06D8 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DQS__GPIO4_IO_20                         0x0190 0x04D8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DQS__WEIM_DATA_7                         0x0190 0x04D8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DQS__SIM_M_HADDR_13                      0x0190 0x04D8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DQS__SDMA_DEBUG_BUS_DEVICE_4             0x0190 0x04D8 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__QSPI1_A_SCLK                       0x0194 0x04DC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__ANATOP_OTG2_ID                     0x0194 0x04DC 0x0628 0x1 0x2
+#define MX6SX_PAD_QSPI1A_SCLK__ECSPI1_SCLK                        0x0194 0x04DC 0x0710 0x2 0x1
+#define MX6SX_PAD_QSPI1A_SCLK__ESAI_TX2_RX3                       0x0194 0x04DC 0x0798 0x3 0x2
+#define MX6SX_PAD_QSPI1A_SCLK__CSI1_DATA_1                        0x0194 0x04DC 0x06A4 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SCLK__GPIO4_IO_21                        0x0194 0x04DC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__WEIM_DATA_0                        0x0194 0x04DC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__SIM_M_HADDR_0                      0x0194 0x04DC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__SDMA_DEBUG_PC_5                    0x0194 0x04DC 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__QSPI1_A_SS0_B                     0x0198 0x04E0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__USB_OTG2_PWR                      0x0198 0x04E0 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__ECSPI1_SS0                        0x0198 0x04E0 0x071C 0x2 0x1
+#define MX6SX_PAD_QSPI1A_SS0_B__ESAI_TX3_RX2                      0x0198 0x04E0 0x079C 0x3 0x2
+#define MX6SX_PAD_QSPI1A_SS0_B__CSI1_DATA_0                       0x0198 0x04E0 0x06A0 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22                       0x0198 0x04E0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__WEIM_DATA_1                       0x0198 0x04E0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__SIM_M_HADDR_1                     0x0198 0x04E0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__SDMA_DEBUG_PC_4                   0x0198 0x04E0 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__QSPI1_A_SS1_B                     0x019C 0x04E4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX                           0x019C 0x04E4 0x068C 0x1 0x2
+#define MX6SX_PAD_QSPI1A_SS1_B__CANFD_RX1                         0x019C 0x04E4 0x0694 0x2 0x2
+#define MX6SX_PAD_QSPI1A_SS1_B__ECSPI5_MISO                       0x019C 0x04E4 0x0754 0x3 0x1
+#define MX6SX_PAD_QSPI1A_SS1_B__CSI1_DATA_10                      0x019C 0x04E4 0x06FC 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SS1_B__GPIO4_IO_23                       0x019C 0x04E4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__WEIM_DATA_2                       0x019C 0x04E4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__SIM_M_HADDR_12                    0x019C 0x04E4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__SDMA_DEBUG_PC_3                   0x019C 0x04E4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0                    0x01A0 0x04E8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__UART3_CTS_B                       0x01A0 0x04E8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__ECSPI3_MOSI                       0x01A0 0x04E8 0x0738 0x2 0x1
+#define MX6SX_PAD_QSPI1B_DATA0__ESAI_RX_FS                        0x01A0 0x04E8 0x0778 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA0__CSI1_DATA_22                      0x01A0 0x04E8 0x06F4 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA0__GPIO4_IO_24                       0x01A0 0x04E8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__WEIM_DATA_14                      0x01A0 0x04E8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__SIM_M_HADDR_9                     0x01A0 0x04E8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1                    0x01A4 0x04EC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__UART3_RTS_B                       0x01A4 0x04EC 0x083C 0x1 0x5
+#define MX6SX_PAD_QSPI1B_DATA1__ECSPI3_MISO                       0x01A4 0x04EC 0x0734 0x2 0x1
+#define MX6SX_PAD_QSPI1B_DATA1__ESAI_RX_CLK                       0x01A4 0x04EC 0x0788 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA1__CSI1_DATA_21                      0x01A4 0x04EC 0x06F0 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25                       0x01A4 0x04EC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__WEIM_DATA_13                      0x01A4 0x04EC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__SIM_M_HADDR_8                     0x01A4 0x04EC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__QSPI1_B_DATA_2                    0x01A8 0x04F0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__I2C2_SDA                          0x01A8 0x04F0 0x07B4 0x1 0x2
+#define MX6SX_PAD_QSPI1B_DATA2__ECSPI5_RDY                        0x01A8 0x04F0 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__ESAI_TX5_RX0                      0x01A8 0x04F0 0x07A4 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA2__CSI1_DATA_20                      0x01A8 0x04F0 0x06EC 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA2__GPIO4_IO_26                       0x01A8 0x04F0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__WEIM_DATA_12                      0x01A8 0x04F0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__SIM_M_HADDR_5                     0x01A8 0x04F0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__QSPI1_B_DATA_3                    0x01AC 0x04F4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__I2C2_SCL                          0x01AC 0x04F4 0x07B0 0x1 0x2
+#define MX6SX_PAD_QSPI1B_DATA3__ECSPI5_SS3                        0x01AC 0x04F4 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__ESAI_TX_FS                        0x01AC 0x04F4 0x077C 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA3__CSI1_DATA_19                      0x01AC 0x04F4 0x06E8 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27                       0x01AC 0x04F4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__WEIM_DATA_11                      0x01AC 0x04F4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__SIM_M_HADDR_2                     0x01AC 0x04F4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DQS__QSPI1_B_DQS                         0x01B0 0x04F8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DQS__CAN1_TX                             0x01B0 0x04F8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_DQS__CANFD_TX1                           0x01B0 0x04F8 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DQS__ECSPI5_SS0                          0x01B0 0x04F8 0x075C 0x3 0x1
+#define MX6SX_PAD_QSPI1B_DQS__CSI1_DATA_23                        0x01B0 0x04F8 0x06F8 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DQS__GPIO4_IO_28                         0x01B0 0x04F8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DQS__WEIM_DATA_15                        0x01B0 0x04F8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DQS__SIM_M_HADDR_15                      0x01B0 0x04F8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__QSPI1_B_SCLK                       0x01B4 0x04FC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__UART3_RX                           0x01B4 0x04FC 0x0840 0x1 0x4
+#define MX6SX_PAD_QSPI1B_SCLK__UART3_TX                           0x01B4 0x04FC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__ECSPI3_SCLK                        0x01B4 0x04FC 0x0730 0x2 0x1
+#define MX6SX_PAD_QSPI1B_SCLK__ESAI_RX_HF_CLK                     0x01B4 0x04FC 0x0780 0x3 0x2
+#define MX6SX_PAD_QSPI1B_SCLK__CSI1_DATA_16                       0x01B4 0x04FC 0x06DC 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SCLK__GPIO4_IO_29                        0x01B4 0x04FC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__WEIM_DATA_8                        0x01B4 0x04FC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__SIM_M_HADDR_11                     0x01B4 0x04FC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__QSPI1_B_SS0_B                     0x01B8 0x0500 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__UART3_RX                          0x01B8 0x0500 0x0840 0x1 0x5
+#define MX6SX_PAD_QSPI1B_SS0_B__UART3_TX                          0x01B8 0x0500 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__ECSPI3_SS0                        0x01B8 0x0500 0x073C 0x2 0x1
+#define MX6SX_PAD_QSPI1B_SS0_B__ESAI_TX_HF_CLK                    0x01B8 0x0500 0x0784 0x3 0x3
+#define MX6SX_PAD_QSPI1B_SS0_B__CSI1_DATA_17                      0x01B8 0x0500 0x06E0 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SS0_B__GPIO4_IO_30                       0x01B8 0x0500 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__WEIM_DATA_9                       0x01B8 0x0500 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__SIM_M_HADDR_10                    0x01B8 0x0500 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__QSPI1_B_SS1_B                     0x01BC 0x0504 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX                           0x01BC 0x0504 0x0690 0x1 0x2
+#define MX6SX_PAD_QSPI1B_SS1_B__CANFD_RX2                         0x01BC 0x0504 0x0698 0x2 0x2
+#define MX6SX_PAD_QSPI1B_SS1_B__ECSPI5_SCLK                       0x01BC 0x0504 0x0750 0x3 0x1
+#define MX6SX_PAD_QSPI1B_SS1_B__CSI1_DATA_18                      0x01BC 0x0504 0x06E4 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SS1_B__GPIO4_IO_31                       0x01BC 0x0504 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__WEIM_DATA_10                      0x01BC 0x0504 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__SIM_M_HADDR_14                    0x01BC 0x0504 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0                     0x01C0 0x0508 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD0__GPIO5_IO_0                          0x01C0 0x0508 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD0__CSI2_DATA_10                        0x01C0 0x0508 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD0__ANATOP_TESTI_0                      0x01C0 0x0508 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD0__RAWNAND_TESTER_TRIGGER              0x01C0 0x0508 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD0__PCIE_CTRL_DEBUG_0                   0x01C0 0x0508 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1                     0x01C4 0x050C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD1__GPIO5_IO_1                          0x01C4 0x050C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD1__CSI2_DATA_11                        0x01C4 0x050C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD1__ANATOP_TESTI_1                      0x01C4 0x050C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD1__USDHC1_TESTER_TRIGGER               0x01C4 0x050C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD1__PCIE_CTRL_DEBUG_1                   0x01C4 0x050C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2                     0x01C8 0x0510 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD2__GPIO5_IO_2                          0x01C8 0x0510 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD2__CSI2_DATA_12                        0x01C8 0x0510 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD2__ANATOP_TESTI_2                      0x01C8 0x0510 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD2__USDHC2_TESTER_TRIGGER               0x01C8 0x0510 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD2__PCIE_CTRL_DEBUG_2                   0x01C8 0x0510 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3                     0x01CC 0x0514 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD3__GPIO5_IO_3                          0x01CC 0x0514 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD3__CSI2_DATA_13                        0x01CC 0x0514 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD3__ANATOP_TESTI_3                      0x01CC 0x0514 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD3__USDHC3_TESTER_TRIGGER               0x01CC 0x0514 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD3__PCIE_CTRL_DEBUG_3                   0x01CC 0x0514 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN                      0x01D0 0x0518 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__GPIO5_IO_4                       0x01D0 0x0518 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__CSI2_DATA_14                     0x01D0 0x0518 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__ANATOP_TESTO_0                   0x01D0 0x0518 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__USDHC4_TESTER_TRIGGER            0x01D0 0x0518 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__PCIE_CTRL_DEBUG_4                0x01D0 0x0518 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK                        0x01D4 0x051C 0x0768 0x0 0x1
+#define MX6SX_PAD_RGMII1_RXC__ENET1_RX_ER                         0x01D4 0x051C 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII1_RXC__GPIO5_IO_5                          0x01D4 0x051C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RXC__CSI2_DATA_15                        0x01D4 0x051C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RXC__ANATOP_TESTO_1                      0x01D4 0x051C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RXC__ECSPI1_TESTER_TRIGGER               0x01D4 0x051C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RXC__PCIE_CTRL_DEBUG_5                   0x01D4 0x051C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0                     0x01D8 0x0520 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD0__SAI2_RX_SYNC                        0x01D8 0x0520 0x0810 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD0__GPIO5_IO_6                          0x01D8 0x0520 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD0__CSI2_DATA_16                        0x01D8 0x0520 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD0__ANATOP_TESTO_2                      0x01D8 0x0520 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD0__ECSPI2_TESTER_TRIGGER               0x01D8 0x0520 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD0__PCIE_CTRL_DEBUG_6                   0x01D8 0x0520 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1                     0x01DC 0x0524 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD1__SAI2_RX_BCLK                        0x01DC 0x0524 0x0808 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD1__GPIO5_IO_7                          0x01DC 0x0524 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD1__CSI2_DATA_17                        0x01DC 0x0524 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD1__ANATOP_TESTO_3                      0x01DC 0x0524 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD1__ECSPI3_TESTER_TRIGGER               0x01DC 0x0524 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD1__PCIE_CTRL_DEBUG_7                   0x01DC 0x0524 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2                     0x01E0 0x0528 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD2__SAI2_TX_SYNC                        0x01E0 0x0528 0x0818 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD2__GPIO5_IO_8                          0x01E0 0x0528 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD2__CSI2_DATA_18                        0x01E0 0x0528 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD2__ANATOP_TESTO_4                      0x01E0 0x0528 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD2__ECSPI4_TESTER_TRIGGER               0x01E0 0x0528 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD2__PCIE_CTRL_DEBUG_8                   0x01E0 0x0528 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3                     0x01E4 0x052C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD3__SAI2_TX_BCLK                        0x01E4 0x052C 0x0814 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD3__GPIO5_IO_9                          0x01E4 0x052C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD3__CSI2_DATA_19                        0x01E4 0x052C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD3__ANATOP_TESTO_5                      0x01E4 0x052C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD3__ECSPI5_TESTER_TRIGGER               0x01E4 0x052C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD3__PCIE_CTRL_DEBUG_9                   0x01E4 0x052C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN                      0x01E8 0x0530 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__SAI2_RX_DATA_0                   0x01E8 0x0530 0x080C 0x2 0x1
+#define MX6SX_PAD_RGMII1_TX_CTL__GPIO5_IO_10                      0x01E8 0x0530 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__CSI2_DATA_0                      0x01E8 0x0530 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__ANATOP_TESTO_6                   0x01E8 0x0530 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__QSPI1_TESTER_TRIGGER             0x01E8 0x0530 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__PCIE_CTRL_DEBUG_10               0x01E8 0x0530 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC                     0x01EC 0x0534 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TXC__ENET1_TX_ER                         0x01EC 0x0534 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII1_TXC__SAI2_TX_DATA_0                      0x01EC 0x0534 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII1_TXC__GPIO5_IO_11                         0x01EC 0x0534 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TXC__CSI2_DATA_1                         0x01EC 0x0534 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TXC__ANATOP_TESTO_7                      0x01EC 0x0534 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TXC__QSPI2_TESTER_TRIGGER                0x01EC 0x0534 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TXC__PCIE_CTRL_DEBUG_11                  0x01EC 0x0534 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0                     0x01F0 0x0538 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD0__PWM4_OUT                            0x01F0 0x0538 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD0__GPIO5_IO_12                         0x01F0 0x0538 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD0__CSI2_DATA_2                         0x01F0 0x0538 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD0__ANATOP_TESTO_8                      0x01F0 0x0538 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD0__VDEC_DEBUG_18                       0x01F0 0x0538 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD0__PCIE_CTRL_DEBUG_12                  0x01F0 0x0538 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1                     0x01F4 0x053C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD1__PWM3_OUT                            0x01F4 0x053C 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD1__GPIO5_IO_13                         0x01F4 0x053C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD1__CSI2_DATA_3                         0x01F4 0x053C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD1__ANATOP_TESTO_9                      0x01F4 0x053C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD1__VDEC_DEBUG_19                       0x01F4 0x053C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD1__PCIE_CTRL_DEBUG_13                  0x01F4 0x053C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2                     0x01F8 0x0540 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD2__PWM2_OUT                            0x01F8 0x0540 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD2__GPIO5_IO_14                         0x01F8 0x0540 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD2__CSI2_DATA_4                         0x01F8 0x0540 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD2__ANATOP_TESTO_10                     0x01F8 0x0540 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD2__VDEC_DEBUG_20                       0x01F8 0x0540 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD2__PCIE_CTRL_DEBUG_14                  0x01F8 0x0540 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3                     0x01FC 0x0544 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD3__PWM1_OUT                            0x01FC 0x0544 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD3__GPIO5_IO_15                         0x01FC 0x0544 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD3__CSI2_DATA_5                         0x01FC 0x0544 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD3__ANATOP_TESTO_11                     0x01FC 0x0544 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD3__VDEC_DEBUG_21                       0x01FC 0x0544 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD3__PCIE_CTRL_DEBUG_15                  0x01FC 0x0544 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN                      0x0200 0x0548 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__GPIO5_IO_16                      0x0200 0x0548 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__CSI2_DATA_6                      0x0200 0x0548 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__ANATOP_TESTO_12                  0x0200 0x0548 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__VDEC_DEBUG_22                    0x0200 0x0548 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__PCIE_CTRL_DEBUG_16               0x0200 0x0548 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK                        0x0204 0x054C 0x0774 0x0 0x1
+#define MX6SX_PAD_RGMII2_RXC__ENET2_RX_ER                         0x0204 0x054C 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII2_RXC__GPIO5_IO_17                         0x0204 0x054C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RXC__CSI2_DATA_7                         0x0204 0x054C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RXC__ANATOP_TESTO_13                     0x0204 0x054C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RXC__VDEC_DEBUG_23                       0x0204 0x054C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RXC__PCIE_CTRL_DEBUG_17                  0x0204 0x054C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0                     0x0208 0x0550 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD0__SAI1_RX_SYNC                        0x0208 0x0550 0x07FC 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD0__PWM8_OUT                            0x0208 0x0550 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD0__GPIO5_IO_18                         0x0208 0x0550 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD0__CSI2_DATA_8                         0x0208 0x0550 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD0__ANATOP_TESTO_14                     0x0208 0x0550 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD0__VDEC_DEBUG_24                       0x0208 0x0550 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD0__PCIE_CTRL_DEBUG_18                  0x0208 0x0550 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1                     0x020C 0x0554 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD1__SAI1_RX_BCLK                        0x020C 0x0554 0x07F4 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD1__PWM7_OUT                            0x020C 0x0554 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD1__GPIO5_IO_19                         0x020C 0x0554 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD1__CSI2_DATA_9                         0x020C 0x0554 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD1__ANATOP_TESTO_15                     0x020C 0x0554 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD1__VDEC_DEBUG_25                       0x020C 0x0554 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD1__PCIE_CTRL_DEBUG_19                  0x020C 0x0554 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2                     0x0210 0x0558 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD2__SAI1_TX_SYNC                        0x0210 0x0558 0x0804 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD2__PWM6_OUT                            0x0210 0x0558 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD2__GPIO5_IO_20                         0x0210 0x0558 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD2__CSI2_VSYNC                          0x0210 0x0558 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD2__SJC_FAIL                            0x0210 0x0558 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD2__VDEC_DEBUG_26                       0x0210 0x0558 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD2__PCIE_CTRL_DEBUG_20                  0x0210 0x0558 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3                     0x0214 0x055C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD3__SAI1_TX_BCLK                        0x0214 0x055C 0x0800 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD3__PWM5_OUT                            0x0214 0x055C 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD3__GPIO5_IO_21                         0x0214 0x055C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD3__CSI2_HSYNC                          0x0214 0x055C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD3__SJC_JTAG_ACT                        0x0214 0x055C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD3__VDEC_DEBUG_27                       0x0214 0x055C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD3__PCIE_CTRL_DEBUG_21                  0x0214 0x055C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN                      0x0218 0x0560 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__SAI1_RX_DATA_0                   0x0218 0x0560 0x07F8 0x2 0x1
+#define MX6SX_PAD_RGMII2_TX_CTL__GPIO5_IO_22                      0x0218 0x0560 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__CSI2_FIELD                       0x0218 0x0560 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__SJC_DE_B                         0x0218 0x0560 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__VDEC_DEBUG_28                    0x0218 0x0560 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__PCIE_CTRL_DEBUG_22               0x0218 0x0560 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC                     0x021C 0x0564 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TXC__ENET2_TX_ER                         0x021C 0x0564 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII2_TXC__SAI1_TX_DATA_0                      0x021C 0x0564 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_TXC__GPIO5_IO_23                         0x021C 0x0564 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TXC__CSI2_PIXCLK                         0x021C 0x0564 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TXC__SJC_DONE                            0x021C 0x0564 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TXC__VDEC_DEBUG_29                       0x021C 0x0564 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TXC__PCIE_CTRL_DEBUG_23                  0x021C 0x0564 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_CLK__USDHC1_CLK                             0x0220 0x0568 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_CLK__AUDMUX_AUD5_RXFS                       0x0220 0x0568 0x0668 0x1 0x1
+#define MX6SX_PAD_SD1_CLK__WDOG2_WDOG_B                           0x0220 0x0568 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_CLK__GPT_CLK                                0x0220 0x0568 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_CLK__WDOG2_WDOG_RST_B_DEB                   0x0220 0x0568 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_CLK__GPIO6_IO_0                             0x0220 0x0568 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_CLK__ENET2_1588_EVENT1_OUT                  0x0220 0x0568 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_CLK__CCM_OUT1                               0x0220 0x0568 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_CLK__VADC_ADC_PROC_CLK                      0x0220 0x0568 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_CLK__MMDC_DEBUG_45                          0x0220 0x0568 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_CMD__USDHC1_CMD                             0x0224 0x056C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_CMD__AUDMUX_AUD5_RXC                        0x0224 0x056C 0x0664 0x1 0x1
+#define MX6SX_PAD_SD1_CMD__WDOG1_WDOG_B                           0x0224 0x056C 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_CMD__GPT_COMPARE1                           0x0224 0x056C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_CMD__WDOG1_WDOG_RST_B_DEB                   0x0224 0x056C 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_CMD__GPIO6_IO_1                             0x0224 0x056C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_CMD__ENET2_1588_EVENT1_IN                   0x0224 0x056C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_CMD__CCM_CLKO1                              0x0224 0x056C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_CMD__VADC_EXT_SYSCLK                        0x0224 0x056C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_CMD__MMDC_DEBUG_46                          0x0224 0x056C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA0__USDHC1_DATA0                         0x0228 0x0570 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA0__AUDMUX_AUD5_RXD                      0x0228 0x0570 0x065C 0x1 0x1
+#define MX6SX_PAD_SD1_DATA0__CAAM_WRAPPER_RNG_OSC_OBS             0x0228 0x0570 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA0__GPT_CAPTURE1                         0x0228 0x0570 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA0__UART2_RX                             0x0228 0x0570 0x0838 0x4 0x2
+#define MX6SX_PAD_SD1_DATA0__UART2_TX                             0x0228 0x0570 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA0__GPIO6_IO_2                           0x0228 0x0570 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA0__ENET1_1588_EVENT1_IN                 0x0228 0x0570 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA0__CCM_OUT2                             0x0228 0x0570 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA0__VADC_CLAMP_UP                        0x0228 0x0570 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA0__MMDC_DEBUG_48                        0x0228 0x0570 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA1__USDHC1_DATA1                         0x022C 0x0574 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA1__AUDMUX_AUD5_TXC                      0x022C 0x0574 0x066C 0x1 0x1
+#define MX6SX_PAD_SD1_DATA1__PWM4_OUT                             0x022C 0x0574 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA1__GPT_CAPTURE2                         0x022C 0x0574 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA1__UART2_RX                             0x022C 0x0574 0x0838 0x4 0x3
+#define MX6SX_PAD_SD1_DATA1__UART2_TX                             0x022C 0x0574 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA1__GPIO6_IO_3                           0x022C 0x0574 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA1__ENET1_1588_EVENT1_OUT                0x022C 0x0574 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA1__CCM_CLKO2                            0x022C 0x0574 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA1__VADC_CLAMP_DOWN                      0x022C 0x0574 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA1__MMDC_DEBUG_47                        0x022C 0x0574 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA2__USDHC1_DATA2                         0x0230 0x0578 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA2__AUDMUX_AUD5_TXFS                     0x0230 0x0578 0x0670 0x1 0x1
+#define MX6SX_PAD_SD1_DATA2__PWM3_OUT                             0x0230 0x0578 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA2__GPT_COMPARE2                         0x0230 0x0578 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA2__UART2_CTS_B                          0x0230 0x0578 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA2__GPIO6_IO_4                           0x0230 0x0578 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA2__ECSPI4_RDY                           0x0230 0x0578 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA2__CCM_OUT0                             0x0230 0x0578 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA2__VADC_EXT_PD_N                        0x0230 0x0578 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA3__USDHC1_DATA3                         0x0234 0x057C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_TXD                      0x0234 0x057C 0x0660 0x1 0x1
+#define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD                      0x0234 0x057C 0x065C 0x2 0x2
+#define MX6SX_PAD_SD1_DATA3__GPT_COMPARE3                         0x0234 0x057C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA3__UART2_RTS_B                          0x0234 0x057C 0x0834 0x4 0x3
+#define MX6SX_PAD_SD1_DATA3__GPIO6_IO_5                           0x0234 0x057C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA3__ECSPI4_SS1                           0x0234 0x057C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA3__CCM_PMIC_RDY                         0x0234 0x057C 0x069C 0x7 0x2
+#define MX6SX_PAD_SD1_DATA3__VADC_RST_N                           0x0234 0x057C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CLK__USDHC2_CLK                             0x0238 0x0580 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_CLK__AUDMUX_AUD6_RXFS                       0x0238 0x0580 0x0680 0x1 0x2
+#define MX6SX_PAD_SD2_CLK__KPP_COL_5                              0x0238 0x0580 0x07C8 0x2 0x1
+#define MX6SX_PAD_SD2_CLK__ECSPI4_SCLK                            0x0238 0x0580 0x0740 0x3 0x1
+#define MX6SX_PAD_SD2_CLK__MLB_SIG                                0x0238 0x0580 0x07F0 0x4 0x2
+#define MX6SX_PAD_SD2_CLK__GPIO6_IO_6                             0x0238 0x0580 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_CLK__MQS_RIGHT                              0x0238 0x0580 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_CLK__WDOG1_WDOG_ANY                         0x0238 0x0580 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_CLK__VADC_CLAMP_CURRENT_5                   0x0238 0x0580 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CLK__MMDC_DEBUG_29                          0x0238 0x0580 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_CMD__USDHC2_CMD                             0x023C 0x0584 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_CMD__AUDMUX_AUD6_RXC                        0x023C 0x0584 0x067C 0x1 0x2
+#define MX6SX_PAD_SD2_CMD__KPP_ROW_5                              0x023C 0x0584 0x07D4 0x2 0x1
+#define MX6SX_PAD_SD2_CMD__ECSPI4_MOSI                            0x023C 0x0584 0x0748 0x3 0x1
+#define MX6SX_PAD_SD2_CMD__MLB_CLK                                0x023C 0x0584 0x07E8 0x4 0x2
+#define MX6SX_PAD_SD2_CMD__GPIO6_IO_7                             0x023C 0x0584 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_CMD__MQS_LEFT                               0x023C 0x0584 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_CMD__WDOG3_WDOG_B                           0x023C 0x0584 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_CMD__VADC_CLAMP_CURRENT_4                   0x023C 0x0584 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CMD__MMDC_DEBUG_30                          0x023C 0x0584 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA0__USDHC2_DATA0                         0x0240 0x0588 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA0__AUDMUX_AUD6_RXD                      0x0240 0x0588 0x0674 0x1 0x2
+#define MX6SX_PAD_SD2_DATA0__KPP_ROW_7                            0x0240 0x0588 0x07DC 0x2 0x1
+#define MX6SX_PAD_SD2_DATA0__PWM1_OUT                             0x0240 0x0588 0x0000 0x3 0x0
+#define MX6SX_PAD_SD2_DATA0__I2C4_SDA                             0x0240 0x0588 0x07C4 0x4 0x3
+#define MX6SX_PAD_SD2_DATA0__GPIO6_IO_8                           0x0240 0x0588 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA0__ECSPI4_SS3                           0x0240 0x0588 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA0__UART4_RX                             0x0240 0x0588 0x0848 0x7 0x4
+#define MX6SX_PAD_SD2_DATA0__UART4_TX                             0x0240 0x0588 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA0__VADC_CLAMP_CURRENT_0                 0x0240 0x0588 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA0__MMDC_DEBUG_50                        0x0240 0x0588 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA1__USDHC2_DATA1                         0x0244 0x058C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA1__AUDMUX_AUD6_TXC                      0x0244 0x058C 0x0684 0x1 0x2
+#define MX6SX_PAD_SD2_DATA1__KPP_COL_7                            0x0244 0x058C 0x07D0 0x2 0x1
+#define MX6SX_PAD_SD2_DATA1__PWM2_OUT                             0x0244 0x058C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD2_DATA1__I2C4_SCL                             0x0244 0x058C 0x07C0 0x4 0x3
+#define MX6SX_PAD_SD2_DATA1__GPIO6_IO_9                           0x0244 0x058C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA1__ECSPI4_SS2                           0x0244 0x058C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA1__UART4_RX                             0x0244 0x058C 0x0848 0x7 0x5
+#define MX6SX_PAD_SD2_DATA1__UART4_TX                             0x0244 0x058C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA1__VADC_CLAMP_CURRENT_1                 0x0244 0x058C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA1__MMDC_DEBUG_49                        0x0244 0x058C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA2__USDHC2_DATA2                         0x0248 0x0590 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA2__AUDMUX_AUD6_TXFS                     0x0248 0x0590 0x0688 0x1 0x2
+#define MX6SX_PAD_SD2_DATA2__KPP_ROW_6                            0x0248 0x0590 0x07D8 0x2 0x1
+#define MX6SX_PAD_SD2_DATA2__ECSPI4_SS0                           0x0248 0x0590 0x074C 0x3 0x1
+#define MX6SX_PAD_SD2_DATA2__SDMA_EXT_EVENT_0                     0x0248 0x0590 0x081C 0x4 0x2
+#define MX6SX_PAD_SD2_DATA2__GPIO6_IO_10                          0x0248 0x0590 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA2__SPDIF_OUT                            0x0248 0x0590 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA2__UART6_RX                             0x0248 0x0590 0x0858 0x7 0x4
+#define MX6SX_PAD_SD2_DATA2__UART6_TX                             0x0248 0x0590 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA2__VADC_CLAMP_CURRENT_2                 0x0248 0x0590 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA2__MMDC_DEBUG_32                        0x0248 0x0590 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA3__USDHC2_DATA3                         0x024C 0x0594 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA3__AUDMUX_AUD6_TXD                      0x024C 0x0594 0x0678 0x1 0x2
+#define MX6SX_PAD_SD2_DATA3__KPP_COL_6                            0x024C 0x0594 0x07CC 0x2 0x1
+#define MX6SX_PAD_SD2_DATA3__ECSPI4_MISO                          0x024C 0x0594 0x0744 0x3 0x1
+#define MX6SX_PAD_SD2_DATA3__MLB_DATA                             0x024C 0x0594 0x07EC 0x4 0x2
+#define MX6SX_PAD_SD2_DATA3__GPIO6_IO_11                          0x024C 0x0594 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA3__SPDIF_IN                             0x024C 0x0594 0x0824 0x6 0x4
+#define MX6SX_PAD_SD2_DATA3__UART6_RX                             0x024C 0x0594 0x0858 0x7 0x5
+#define MX6SX_PAD_SD2_DATA3__UART6_TX                             0x024C 0x0594 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA3__VADC_CLAMP_CURRENT_3                 0x024C 0x0594 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA3__MMDC_DEBUG_31                        0x024C 0x0594 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_CLK__USDHC3_CLK                             0x0250 0x0598 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_CLK__UART4_CTS_B                            0x0250 0x0598 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_CLK__ECSPI4_SCLK                            0x0250 0x0598 0x0740 0x2 0x0
+#define MX6SX_PAD_SD3_CLK__AUDMUX_AUD6_RXFS                       0x0250 0x0598 0x0680 0x3 0x0
+#define MX6SX_PAD_SD3_CLK__LCDIF2_VSYNC                           0x0250 0x0598 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_CLK__GPIO7_IO_0                             0x0250 0x0598 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_CLK__LCDIF2_BUSY                            0x0250 0x0598 0x07E4 0x6 0x0
+#define MX6SX_PAD_SD3_CLK__TPSMP_HDATA_29                         0x0250 0x0598 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_CLK__SDMA_DEBUG_EVENT_CHANNEL_5             0x0250 0x0598 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_CMD__USDHC3_CMD                             0x0254 0x059C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_CMD__UART4_RX                               0x0254 0x059C 0x0848 0x1 0x0
+#define MX6SX_PAD_SD3_CMD__UART4_TX                               0x0254 0x059C 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_CMD__ECSPI4_MOSI                            0x0254 0x059C 0x0748 0x2 0x0
+#define MX6SX_PAD_SD3_CMD__AUDMUX_AUD6_RXC                        0x0254 0x059C 0x067C 0x3 0x0
+#define MX6SX_PAD_SD3_CMD__LCDIF2_HSYNC                           0x0254 0x059C 0x07E4 0x4 0x1
+#define MX6SX_PAD_SD3_CMD__GPIO7_IO_1                             0x0254 0x059C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_CMD__LCDIF2_RS                              0x0254 0x059C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_CMD__TPSMP_HDATA_28                         0x0254 0x059C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_CMD__SDMA_DEBUG_EVENT_CHANNEL_4             0x0254 0x059C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA0__USDHC3_DATA0                         0x0258 0x05A0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA0__I2C4_SCL                             0x0258 0x05A0 0x07C0 0x1 0x0
+#define MX6SX_PAD_SD3_DATA0__ECSPI2_SS1                           0x0258 0x05A0 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA0__AUDMUX_AUD6_RXD                      0x0258 0x05A0 0x0674 0x3 0x0
+#define MX6SX_PAD_SD3_DATA0__LCDIF2_DATA_1                        0x0258 0x05A0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA0__GPIO7_IO_2                           0x0258 0x05A0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA0__DCIC1_OUT                            0x0258 0x05A0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA0__TPSMP_HDATA_30                       0x0258 0x05A0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA0__GPU_DEBUG_0                          0x0258 0x05A0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA0__SDMA_DEBUG_EVT_CHN_LINES_0           0x0258 0x05A0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA1__USDHC3_DATA1                         0x025C 0x05A4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA1__I2C4_SDA                             0x025C 0x05A4 0x07C4 0x1 0x0
+#define MX6SX_PAD_SD3_DATA1__ECSPI2_SS2                           0x025C 0x05A4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA1__AUDMUX_AUD6_TXC                      0x025C 0x05A4 0x0684 0x3 0x0
+#define MX6SX_PAD_SD3_DATA1__LCDIF2_DATA_0                        0x025C 0x05A4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA1__GPIO7_IO_3                           0x025C 0x05A4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA1__DCIC2_OUT                            0x025C 0x05A4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA1__TPSMP_HDATA_31                       0x025C 0x05A4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA1__GPU_DEBUG_1                          0x025C 0x05A4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA1__SDMA_DEBUG_EVT_CHN_LINES_1           0x025C 0x05A4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA2__USDHC3_DATA2                         0x0260 0x05A8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA2__UART4_RTS_B                          0x0260 0x05A8 0x0844 0x1 0x1
+#define MX6SX_PAD_SD3_DATA2__ECSPI4_SS0                           0x0260 0x05A8 0x074C 0x2 0x0
+#define MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS                     0x0260 0x05A8 0x0688 0x3 0x0
+#define MX6SX_PAD_SD3_DATA2__LCDIF2_CLK                           0x0260 0x05A8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA2__GPIO7_IO_4                           0x0260 0x05A8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA2__LCDIF2_WR_RWN                        0x0260 0x05A8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA2__TPSMP_HDATA_26                       0x0260 0x05A8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA2__GPU_DEBUG_2                          0x0260 0x05A8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA2__SDMA_DEBUG_EVENT_CHANNEL_2           0x0260 0x05A8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA3__USDHC3_DATA3                         0x0264 0x05AC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA3__UART4_RX                             0x0264 0x05AC 0x0848 0x1 0x1
+#define MX6SX_PAD_SD3_DATA3__UART4_TX                             0x0264 0x05AC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA3__ECSPI4_MISO                          0x0264 0x05AC 0x0744 0x2 0x0
+#define MX6SX_PAD_SD3_DATA3__AUDMUX_AUD6_TXD                      0x0264 0x05AC 0x0678 0x3 0x0
+#define MX6SX_PAD_SD3_DATA3__LCDIF2_ENABLE                        0x0264 0x05AC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA3__GPIO7_IO_5                           0x0264 0x05AC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA3__LCDIF2_RD_E                          0x0264 0x05AC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA3__TPSMP_HDATA_27                       0x0264 0x05AC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA3__GPU_DEBUG_3                          0x0264 0x05AC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA3__SDMA_DEBUG_EVENT_CHANNEL_3           0x0264 0x05AC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA4__USDHC3_DATA4                         0x0268 0x05B0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA4__CAN2_RX                              0x0268 0x05B0 0x0690 0x1 0x0
+#define MX6SX_PAD_SD3_DATA4__CANFD_RX2                            0x0268 0x05B0 0x0698 0x2 0x0
+#define MX6SX_PAD_SD3_DATA4__UART3_RX                             0x0268 0x05B0 0x0840 0x3 0x2
+#define MX6SX_PAD_SD3_DATA4__UART3_TX                             0x0268 0x05B0 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA4__LCDIF2_DATA_3                        0x0268 0x05B0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA4__GPIO7_IO_6                           0x0268 0x05B0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA4__ENET2_1588_EVENT0_IN                 0x0268 0x05B0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA4__TPSMP_HTRANS_1                       0x0268 0x05B0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA4__GPU_DEBUG_4                          0x0268 0x05B0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA4__SDMA_DEBUG_BUS_DEVICE_0              0x0268 0x05B0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA5__USDHC3_DATA5                         0x026C 0x05B4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA5__CAN1_TX                              0x026C 0x05B4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA5__CANFD_TX1                            0x026C 0x05B4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA5__UART3_RX                             0x026C 0x05B4 0x0840 0x3 0x3
+#define MX6SX_PAD_SD3_DATA5__UART3_TX                             0x026C 0x05B4 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA5__LCDIF2_DATA_2                        0x026C 0x05B4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA5__GPIO7_IO_7                           0x026C 0x05B4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA5__ENET2_1588_EVENT0_OUT                0x026C 0x05B4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA5__SIM_M_HWRITE                         0x026C 0x05B4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA5__GPU_DEBUG_5                          0x026C 0x05B4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA5__SDMA_DEBUG_BUS_DEVICE_1              0x026C 0x05B4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA6__USDHC3_DATA6                         0x0270 0x05B8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA6__CAN2_TX                              0x0270 0x05B8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA6__CANFD_TX2                            0x0270 0x05B8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA6__UART3_RTS_B                          0x0270 0x05B8 0x083C 0x3 0x2
+#define MX6SX_PAD_SD3_DATA6__LCDIF2_DATA_4                        0x0270 0x05B8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA6__GPIO7_IO_8                           0x0270 0x05B8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA6__ENET1_1588_EVENT0_OUT                0x0270 0x05B8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA6__TPSMP_HTRANS_0                       0x0270 0x05B8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA6__GPU_DEBUG_7                          0x0270 0x05B8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA6__SDMA_DEBUG_EVT_CHN_LINES_7           0x0270 0x05B8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA7__USDHC3_DATA7                         0x0274 0x05BC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA7__CAN1_RX                              0x0274 0x05BC 0x068C 0x1 0x0
+#define MX6SX_PAD_SD3_DATA7__CANFD_RX1                            0x0274 0x05BC 0x0694 0x2 0x0
+#define MX6SX_PAD_SD3_DATA7__UART3_CTS_B                          0x0274 0x05BC 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA7__LCDIF2_DATA_5                        0x0274 0x05BC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA7__GPIO7_IO_9                           0x0274 0x05BC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA7__ENET1_1588_EVENT0_IN                 0x0274 0x05BC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA7__TPSMP_HDATA_DIR                      0x0274 0x05BC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA7__GPU_DEBUG_6                          0x0274 0x05BC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA7__SDMA_DEBUG_EVT_CHN_LINES_2           0x0274 0x05BC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_CLK__USDHC4_CLK                             0x0278 0x05C0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_CLK__RAWNAND_DATA15                         0x0278 0x05C0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_CLK__ECSPI2_MISO                            0x0278 0x05C0 0x0724 0x2 0x1
+#define MX6SX_PAD_SD4_CLK__AUDMUX_AUD3_RXFS                       0x0278 0x05C0 0x0638 0x3 0x0
+#define MX6SX_PAD_SD4_CLK__LCDIF2_DATA_13                         0x0278 0x05C0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_CLK__GPIO6_IO_12                            0x0278 0x05C0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_CLK__ECSPI3_SS2                             0x0278 0x05C0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_CLK__TPSMP_HDATA_20                         0x0278 0x05C0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_CLK__VDEC_DEBUG_12                          0x0278 0x05C0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_CLK__SDMA_DEBUG_EVENT_CHANNEL_SEL           0x0278 0x05C0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_CMD__USDHC4_CMD                             0x027C 0x05C4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_CMD__RAWNAND_DATA14                         0x027C 0x05C4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_CMD__ECSPI2_MOSI                            0x027C 0x05C4 0x0728 0x2 0x1
+#define MX6SX_PAD_SD4_CMD__AUDMUX_AUD3_RXC                        0x027C 0x05C4 0x0634 0x3 0x0
+#define MX6SX_PAD_SD4_CMD__LCDIF2_DATA_14                         0x027C 0x05C4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_CMD__GPIO6_IO_13                            0x027C 0x05C4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_CMD__ECSPI3_SS1                             0x027C 0x05C4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_CMD__TPSMP_HDATA_19                         0x027C 0x05C4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_CMD__VDEC_DEBUG_11                          0x027C 0x05C4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_CMD__SDMA_DEBUG_CORE_RUN                    0x027C 0x05C4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA0__USDHC4_DATA0                         0x0280 0x05C8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA0__RAWNAND_DATA10                       0x0280 0x05C8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA0__ECSPI2_SS0                           0x0280 0x05C8 0x072C 0x2 0x1
+#define MX6SX_PAD_SD4_DATA0__AUDMUX_AUD3_RXD                      0x0280 0x05C8 0x062C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA0__LCDIF2_DATA_12                       0x0280 0x05C8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA0__GPIO6_IO_14                          0x0280 0x05C8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA0__ECSPI3_SS3                           0x0280 0x05C8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA0__TPSMP_HDATA_21                       0x0280 0x05C8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA0__VDEC_DEBUG_13                        0x0280 0x05C8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA0__SDMA_DEBUG_MODE                      0x0280 0x05C8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA1__USDHC4_DATA1                         0x0284 0x05CC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA1__RAWNAND_DATA11                       0x0284 0x05CC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA1__ECSPI2_SCLK                          0x0284 0x05CC 0x0720 0x2 0x1
+#define MX6SX_PAD_SD4_DATA1__AUDMUX_AUD3_TXC                      0x0284 0x05CC 0x063C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA1__LCDIF2_DATA_11                       0x0284 0x05CC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA1__GPIO6_IO_15                          0x0284 0x05CC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA1__ECSPI3_RDY                           0x0284 0x05CC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA1__TPSMP_HDATA_22                       0x0284 0x05CC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA1__VDEC_DEBUG_14                        0x0284 0x05CC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA1__SDMA_DEBUG_BUS_ERROR                 0x0284 0x05CC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA2__USDHC4_DATA2                         0x0288 0x05D0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA2__RAWNAND_DATA12                       0x0288 0x05D0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA2__I2C2_SDA                             0x0288 0x05D0 0x07B4 0x2 0x0
+#define MX6SX_PAD_SD4_DATA2__AUDMUX_AUD3_TXFS                     0x0288 0x05D0 0x0640 0x3 0x0
+#define MX6SX_PAD_SD4_DATA2__LCDIF2_DATA_10                       0x0288 0x05D0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA2__GPIO6_IO_16                          0x0288 0x05D0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA2__ECSPI2_SS3                           0x0288 0x05D0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA2__TPSMP_HDATA_23                       0x0288 0x05D0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA2__VDEC_DEBUG_15                        0x0288 0x05D0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA2__SDMA_DEBUG_BUS_RWB                   0x0288 0x05D0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA3__USDHC4_DATA3                         0x028C 0x05D4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA3__RAWNAND_DATA13                       0x028C 0x05D4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA3__I2C2_SCL                             0x028C 0x05D4 0x07B0 0x2 0x0
+#define MX6SX_PAD_SD4_DATA3__AUDMUX_AUD3_TXD                      0x028C 0x05D4 0x0630 0x3 0x0
+#define MX6SX_PAD_SD4_DATA3__LCDIF2_DATA_9                        0x028C 0x05D4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA3__GPIO6_IO_17                          0x028C 0x05D4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA3__ECSPI2_RDY                           0x028C 0x05D4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA3__TPSMP_HDATA_24                       0x028C 0x05D4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA3__VDEC_DEBUG_16                        0x028C 0x05D4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA3__SDMA_DEBUG_MATCHED_DMBUS             0x028C 0x05D4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA4__USDHC4_DATA4                         0x0290 0x05D8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA4__RAWNAND_DATA09                       0x0290 0x05D8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA4__UART5_RX                             0x0290 0x05D8 0x0850 0x2 0x0
+#define MX6SX_PAD_SD4_DATA4__UART5_TX                             0x0290 0x05D8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA4__ECSPI3_SCLK                          0x0290 0x05D8 0x0730 0x3 0x0
+#define MX6SX_PAD_SD4_DATA4__LCDIF2_DATA_8                        0x0290 0x05D8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA4__GPIO6_IO_18                          0x0290 0x05D8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA4__SPDIF_OUT                            0x0290 0x05D8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA4__TPSMP_HDATA_16                       0x0290 0x05D8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA4__USB_OTG_HOST_MODE                    0x0290 0x05D8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA4__SDMA_DEBUG_RTBUFFER_WRITE            0x0290 0x05D8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA5__USDHC4_DATA5                         0x0294 0x05DC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA5__RAWNAND_CE2_B                        0x0294 0x05DC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA5__UART5_RX                             0x0294 0x05DC 0x0850 0x2 0x1
+#define MX6SX_PAD_SD4_DATA5__UART5_TX                             0x0294 0x05DC 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA5__ECSPI3_MOSI                          0x0294 0x05DC 0x0738 0x3 0x0
+#define MX6SX_PAD_SD4_DATA5__LCDIF2_DATA_7                        0x0294 0x05DC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA5__GPIO6_IO_19                          0x0294 0x05DC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA5__SPDIF_IN                             0x0294 0x05DC 0x0824 0x6 0x0
+#define MX6SX_PAD_SD4_DATA5__TPSMP_HDATA_17                       0x0294 0x05DC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA5__VDEC_DEBUG_9                         0x0294 0x05DC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA5__SDMA_DEBUG_EVENT_CHANNEL_0           0x0294 0x05DC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA6__USDHC4_DATA6                         0x0298 0x05E0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA6__RAWNAND_CE3_B                        0x0298 0x05E0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA6__UART5_RTS_B                          0x0298 0x05E0 0x084C 0x2 0x0
+#define MX6SX_PAD_SD4_DATA6__ECSPI3_MISO                          0x0298 0x05E0 0x0734 0x3 0x0
+#define MX6SX_PAD_SD4_DATA6__LCDIF2_DATA_6                        0x0298 0x05E0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA6__GPIO6_IO_20                          0x0298 0x05E0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA6__USDHC4_WP                            0x0298 0x05E0 0x0878 0x6 0x0
+#define MX6SX_PAD_SD4_DATA6__TPSMP_HDATA_18                       0x0298 0x05E0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA6__VDEC_DEBUG_10                        0x0298 0x05E0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA6__SDMA_DEBUG_EVENT_CHANNEL_1           0x0298 0x05E0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA7__USDHC4_DATA7                         0x029C 0x05E4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA7__RAWNAND_DATA08                       0x029C 0x05E4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA7__UART5_CTS_B                          0x029C 0x05E4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA7__ECSPI3_SS0                           0x029C 0x05E4 0x073C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA7__LCDIF2_DATA_15                       0x029C 0x05E4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA7__GPIO6_IO_21                          0x029C 0x05E4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA7__USDHC4_CD_B                          0x029C 0x05E4 0x0874 0x6 0x0
+#define MX6SX_PAD_SD4_DATA7__TPSMP_HDATA_15                       0x029C 0x05E4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA7__USB_OTG_PWR_WAKE                     0x029C 0x05E4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA7__SDMA_DEBUG_YIELD                     0x029C 0x05E4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_RESET_B__USDHC4_RESET_B                     0x02A0 0x05E8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_RESET_B__RAWNAND_DQS                        0x02A0 0x05E8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_RESET_B__USDHC4_RESET                       0x02A0 0x05E8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_RESET_B__AUDMUX_MCLK                        0x02A0 0x05E8 0x0000 0x3 0x0
+#define MX6SX_PAD_SD4_RESET_B__LCDIF2_RESET                       0x02A0 0x05E8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_RESET_B__GPIO6_IO_22                        0x02A0 0x05E8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_RESET_B__LCDIF2_CS                          0x02A0 0x05E8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_RESET_B__TPSMP_HDATA_25                     0x02A0 0x05E8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_RESET_B__VDEC_DEBUG_17                      0x02A0 0x05E8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_RESET_B__SDMA_DEBUG_BUS_DEVICE_2            0x02A0 0x05E8 0x0000 0x9 0x0
+#define MX6SX_PAD_USB_H_DATA__USB_H_DATA                          0x02A4 0x05EC 0x0000 0x0 0x0
+#define MX6SX_PAD_USB_H_DATA__PWM2_OUT                            0x02A4 0x05EC 0x0000 0x1 0x0
+#define MX6SX_PAD_USB_H_DATA__ANATOP_24M_OUT                      0x02A4 0x05EC 0x0000 0x2 0x0
+#define MX6SX_PAD_USB_H_DATA__I2C4_SDA                            0x02A4 0x05EC 0x07C4 0x3 0x1
+#define MX6SX_PAD_USB_H_DATA__WDOG3_WDOG_B                        0x02A4 0x05EC 0x0000 0x4 0x0
+#define MX6SX_PAD_USB_H_DATA__GPIO7_IO_10                         0x02A4 0x05EC 0x0000 0x5 0x0
+#define MX6SX_PAD_USB_H_STROBE__USB_H_STROBE                      0x02A8 0x05F0 0x0000 0x0 0x0
+#define MX6SX_PAD_USB_H_STROBE__PWM1_OUT                          0x02A8 0x05F0 0x0000 0x1 0x0
+#define MX6SX_PAD_USB_H_STROBE__ANATOP_32K_OUT                    0x02A8 0x05F0 0x0000 0x2 0x0
+#define MX6SX_PAD_USB_H_STROBE__I2C4_SCL                          0x02A8 0x05F0 0x07C0 0x3 0x1
+#define MX6SX_PAD_USB_H_STROBE__WDOG3_WDOG_RST_B_DEB              0x02A8 0x05F0 0x0000 0x4 0x0
+#define MX6SX_PAD_USB_H_STROBE__GPIO7_IO_11                       0x02A8 0x05F0 0x0000 0x5 0x0
+
+#endif /* __DTS_IMX6SX_PINFUNC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx-sdb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx-sdb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/imx6sx-sdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/imx6sx-sdb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sx.dtsi"
+
+/ {
+	model = "Freescale i.MX6 SoloX SDB Board";
+	compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vcc_sd3: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_vcc_sd3>;
+			regulator-name = "VCC_SD3";
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usb_otg1_vbus: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_otg1>;
+			regulator-name = "usb_otg1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_usb_otg2_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_otg2>;
+			regulator-name = "usb_otg2_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+
+		reg_psu_5v: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "PSU-5V0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
+		model = "wm8962-audio";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"Ext Spk", "SPKOUTL",
+			"Ext Spk", "SPKOUTR",
+			"AMIC", "MICBIAS",
+			"IN3R", "AMIC";
+		mux-int-port = <2>;
+		mux-ext-port = <6>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&i2c1 {
+        clock-frequency = <100000>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_i2c1>;
+        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>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			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: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c4 {
+        clock-frequency = <100000>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_i2c4>;
+        status = "okay";
+
+	codec: wm8962@1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		clocks = <&clks IMX6SX_CLK_AUDIO>;
+		DCVDD-supply = <&vgen4_reg>;
+		DBVDD-supply = <&vgen4_reg>;
+		AVDD-supply = <&vgen4_reg>;
+		CPVDD-supply = <&vgen4_reg>;
+		MICVDD-supply = <&vgen3_reg>;
+		PLLVDD-supply = <&vgen4_reg>;
+		SPKVDD1-supply = <&reg_psu_5v>;
+		SPKVDD2-supply = <&reg_psu_5v>;
+	};
+};
+
+&ssi2 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb_otg1_id>;
+	status = "okay";
+};
+
+&usbotg2 {
+	vbus-supply = <&reg_usb_otg2_vbus>;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	non-removable;
+	no-1-8-v;
+	keep-power-in-suspend;
+	enable-sdio-wakeup;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	bus-width = <8>;
+	cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+	wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
+	keep-power-in-suspend;
+	enable-sdio-wakeup;
+	vmmc-supply = <&vcc_sd3>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+	wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx6x-sdb {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC	0x130b0
+				MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS	0x130b0
+				MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD	0x120b0
+				MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD	0x130b0
+				MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK	0x130b0
+			>;
+		};
+
+		pinctrl_enet1: enet1grp {
+			fsl,pins = <
+				MX6SX_PAD_ENET1_MDIO__ENET1_MDIO	0xa0b1
+				MX6SX_PAD_ENET1_MDC__ENET1_MDC		0xa0b1
+				MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC	0xa0b1
+				MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0	0xa0b1
+				MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1	0xa0b1
+				MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2	0xa0b1
+				MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3	0xa0b1
+				MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN	0xa0b1
+				MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK	0x3081
+				MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0	0x3081
+				MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1	0x3081
+				MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2	0x3081
+				MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3	0x3081
+				MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN	0x3081
+			>;
+		};
+
+		pinctrl_gpio_keys: gpio_keysgrp {
+			fsl,pins = <
+				MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+				MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6SX_PAD_GPIO1_IO01__I2C1_SDA		0x4001b8b1
+				MX6SX_PAD_GPIO1_IO00__I2C1_SCL		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c4: i2c4grp {
+			fsl,pins = <
+				MX6SX_PAD_CSI_DATA07__I2C4_SDA		0x4001b8b1
+				MX6SX_PAD_CSI_DATA06__I2C4_SCL		0x4001b8b1
+			>;
+		};
+
+		pinctrl_vcc_sd3: vccsd3grp {
+			fsl,pins = <
+				MX6SX_PAD_KEY_COL1__GPIO2_IO_11		0x17059
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6SX_PAD_GPIO1_IO04__UART1_TX		0x1b0b1
+				MX6SX_PAD_GPIO1_IO05__UART1_RX		0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6SX_PAD_KEY_ROW3__UART5_RX		0x1b0b1
+				MX6SX_PAD_KEY_COL3__UART5_TX		0x1b0b1
+				MX6SX_PAD_KEY_ROW2__UART5_CTS_B		0x1b0b1
+				MX6SX_PAD_KEY_COL2__UART5_RTS_B		0x1b0b1
+			>;
+		};
+
+		pinctrl_usb_otg1: usbotg1grp {
+			fsl,pins = <
+				MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9	0x10b0
+			>;
+		};
+
+		pinctrl_usb_otg1_id: usbotg1idgrp {
+			fsl,pins = <
+				MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID	0x17059
+			>;
+		};
+
+		pinctrl_usb_otg2: usbot2ggrp {
+			fsl,pins = <
+				MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12	0x10b0
+			>;
+		};
+
+		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
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6SX_PAD_SD3_CMD__USDHC3_CMD		0x17059
+				MX6SX_PAD_SD3_CLK__USDHC3_CLK		0x10059
+				MX6SX_PAD_SD3_DATA0__USDHC3_DATA0	0x17059
+				MX6SX_PAD_SD3_DATA1__USDHC3_DATA1	0x17059
+				MX6SX_PAD_SD3_DATA2__USDHC3_DATA2	0x17059
+				MX6SX_PAD_SD3_DATA3__USDHC3_DATA3	0x17059
+				MX6SX_PAD_SD3_DATA4__USDHC3_DATA4	0x17059
+				MX6SX_PAD_SD3_DATA5__USDHC3_DATA5	0x17059
+				MX6SX_PAD_SD3_DATA6__USDHC3_DATA6	0x17059
+				MX6SX_PAD_SD3_DATA7__USDHC3_DATA7	0x17059
+				MX6SX_PAD_KEY_COL0__GPIO2_IO_10		0x17059 /* CD */
+				MX6SX_PAD_KEY_ROW0__GPIO2_IO_15		0x17059 /* WP */
+			>;
+		};
+
+		pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+			fsl,pins = <
+				MX6SX_PAD_SD3_CMD__USDHC3_CMD		0x170b9
+				MX6SX_PAD_SD3_CLK__USDHC3_CLK		0x100b9
+				MX6SX_PAD_SD3_DATA0__USDHC3_DATA0	0x170b9
+				MX6SX_PAD_SD3_DATA1__USDHC3_DATA1	0x170b9
+				MX6SX_PAD_SD3_DATA2__USDHC3_DATA2	0x170b9
+				MX6SX_PAD_SD3_DATA3__USDHC3_DATA3	0x170b9
+				MX6SX_PAD_SD3_DATA4__USDHC3_DATA4	0x170b9
+				MX6SX_PAD_SD3_DATA5__USDHC3_DATA5	0x170b9
+				MX6SX_PAD_SD3_DATA6__USDHC3_DATA6	0x170b9
+				MX6SX_PAD_SD3_DATA7__USDHC3_DATA7	0x170b9
+			>;
+		};
+
+		pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+			fsl,pins = <
+				MX6SX_PAD_SD3_CMD__USDHC3_CMD		0x170f9
+				MX6SX_PAD_SD3_CLK__USDHC3_CLK		0x100f9
+				MX6SX_PAD_SD3_DATA0__USDHC3_DATA0	0x170f9
+				MX6SX_PAD_SD3_DATA1__USDHC3_DATA1	0x170f9
+				MX6SX_PAD_SD3_DATA2__USDHC3_DATA2	0x170f9
+				MX6SX_PAD_SD3_DATA3__USDHC3_DATA3	0x170f9
+				MX6SX_PAD_SD3_DATA4__USDHC3_DATA4	0x170f9
+				MX6SX_PAD_SD3_DATA5__USDHC3_DATA5	0x170f9
+				MX6SX_PAD_SD3_DATA6__USDHC3_DATA6	0x170f9
+				MX6SX_PAD_SD3_DATA7__USDHC3_DATA7	0x170f9
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6SX_PAD_SD4_CMD__USDHC4_CMD		0x17059
+				MX6SX_PAD_SD4_CLK__USDHC4_CLK		0x10059
+				MX6SX_PAD_SD4_DATA0__USDHC4_DATA0	0x17059
+				MX6SX_PAD_SD4_DATA1__USDHC4_DATA1	0x17059
+				MX6SX_PAD_SD4_DATA2__USDHC4_DATA2	0x17059
+				MX6SX_PAD_SD4_DATA3__USDHC4_DATA3	0x17059
+				MX6SX_PAD_SD4_DATA7__GPIO6_IO_21	0x17059 /* CD */
+				MX6SX_PAD_SD4_DATA6__GPIO6_IO_20	0x17059 /* WP */
+			>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/integratorap.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/integratorap.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/integratorap.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/integratorap.dts	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 / {
 	model = "ARM Integrator/AP";
 	compatible = "arm,integrator-ap";
+	dma-ranges = <0x80000000 0x0 0x80000000>;
 
 	aliases {
 		arm,timer-primary = &timer2;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/k2e-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2e-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/k2e-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2e-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@ clocks {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,pll-clock";
 		clocks = <&refclkpass>;
-		clock-output-names = "pa-pll-clk";
+		clock-output-names = "papllclk";
 		reg = <0x02620358 4>;
 		reg-names = "control";
 	};
@@ -40,7 +40,7 @@ clocks {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
 		clocks = <&chipclk16>;
-		clock-output-names = "usb";
+		clock-output-names = "usb1";
 		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
 		reg-names = "control", "domain";
 		domain-id = <0>;
@@ -60,8 +60,8 @@ clocks {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
 		clocks = <&chipclk12>;
-		clock-output-names = "pcie";
-		reg = <0x0235006c 0xb00>, <0x02350000 0x400>;
+		clock-output-names = "pcie1";
+		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
 		reg-names = "control", "domain";
 		domain-id = <18>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@ clocks {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,pll-clock";
 		clocks = <&refclkpass>;
-		clock-output-names = "pa-pll-clk";
+		clock-output-names = "papllclk";
 		reg = <0x02620358 4>;
 		reg-names = "control";
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/k2hk-evm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2hk-evm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/k2hk-evm.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2hk-evm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -167,3 +167,15 @@
 		};
 	};
 };
+
+&mdio {
+	ethphy0: ethernet-phy@0 {
+		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/k2l-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2l-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/k2l-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/k2l-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@ clocks {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,pll-clock";
 		clocks = <&refclksys>;
-		clock-output-names = "pa-pll-clk";
+		clock-output-names = "papllclk";
 		reg = <0x02620358 4>;
 		reg-names = "control";
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/keystone-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/keystone-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/keystone-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/keystone-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -215,7 +215,7 @@ clocks {
 	clkpa: clkpa {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk16>;
+		clocks = <&paclk13>;
 		clock-output-names = "pa";
 		reg = <0x0235001c 0xb00>, <0x02350008 0x400>;
 		reg-names = "control", "domain";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/keystone.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/keystone.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/keystone.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/keystone.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -266,5 +266,16 @@
 			ranges = <0 0 0x30000000 0x10000000
 				  1 0 0x21000A00 0x00000100>;
 		};
+
+		mdio: mdio@02090300 {
+			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg		= <0x02090300 0x100>;
+			status = "disabled";
+			clocks = <&clkpa>;
+			clock-names = "fck";
+			bus_freq	= <2500000>;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-d2net.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-d2net.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-d2net.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-d2net.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Device Tree file for d2 Network v2
+ *
+ * Copyright (C) 2014 Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * 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 "kirkwood-netxbig.dtsi"
+
+/ {
+	model = "LaCie d2 Network v2";
+	compatible = "lacie,d2net_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	ns2-leds {
+		compatible = "lacie,ns2-leds";
+
+		blue-sata {
+			label = "d2net_v2:blue:sata";
+			slow-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+			cmd-gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		red-fail {
+			label = "d2net_v2:red:fail";
+			gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-net2big.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-net2big.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-net2big.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-net2big.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Device Tree file for LaCie 2Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+	model = "LaCie 2Big Network v2";
+	compatible = "lacie,net2big_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+};
+
+&regulators {
+	regulator@2 {
+		compatible = "regulator-fixed";
+		reg = <2>;
+		regulator-name = "hdd1power";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+	};
+
+	clocks {
+	       g762_clk: g762-oscillator {
+			 compatible = "fixed-clock";
+			 #clock-cells = <0>;
+			 clock-frequency = <32768>;
+	       };
+	};
+};
+
+&i2c0 {
+	g762@3e {
+		compatible = "gmt,g762";
+		reg = <0x3e>;
+		clocks = <&g762_clk>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-net5big.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-net5big.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-net5big.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-net5big.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * Device Tree file for LaCie 5Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+	model = "LaCie 5Big Network v2";
+	compatible = "lacie,net5big_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+};
+
+&regulators {
+	regulator@2 {
+		compatible = "regulator-fixed";
+		reg = <2>;
+		regulator-name = "hdd1power";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+	};
+
+	regulator@3 {
+		compatible = "regulator-fixed";
+		reg = <3>;
+		regulator-name = "hdd2power";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+	};
+
+	regulator@4 {
+		compatible = "regulator-fixed";
+		reg = <4>;
+		regulator-name = "hdd3power";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+	};
+
+	regulator@5 {
+		compatible = "regulator-fixed";
+		reg = <5>;
+		regulator-name = "hdd4power";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+	};
+
+	clocks {
+	       g762_clk: g762-oscillator {
+			 compatible = "fixed-clock";
+			 #clock-cells = <0>;
+			 clock-frequency = <32768>;
+	       };
+	};
+};
+
+&mdio {
+	ethphy1: ethernet-phy@1 {
+		reg = <0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
+
+
+&i2c0 {
+	g762@3e {
+		compatible = "gmt,g762";
+		reg = <0x3e>;
+		clocks = <&g762_clk>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * Device Tree common file for LaCie 2Big and 5Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+		stdout-path = &uart0;
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			status = "okay";
+		};
+
+		spi@10600 {
+			status = "okay";
+
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "mxicy,mx25l4005a";
+				reg = <0>;
+				spi-max-frequency = <20000000>;
+				mode = <0>;
+
+				partition@0 {
+					reg = <0x0 0x80000>;
+					label = "u-boot";
+				};
+			};
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/*
+		 * button@1 and button@2 represent a three position rocker
+		 * switch. Thus the conventional KEY_POWER does not fit
+		 */
+		button@1 {
+			label = "Back power switch (on|auto)";
+			linux,code = <KEY_ESC>;
+			linux,input-type = <5>;
+			gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+		};
+		button@2 {
+			label = "Back power switch (auto|off)";
+			linux,code = <KEY_1>;
+			linux,input-type = <5>;
+			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+		};
+		button@3 {
+			label = "Function button";
+			linux,code = <KEY_OPTION>;
+			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+		};
+
+	};
+
+	gpio-poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+	};
+
+	regulators: regulators {
+		status = "okay";
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "hdd0power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		reg = <8>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		reg = <0>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+
+	pmx_button_function: pmx-button-function {
+		marvell,pins = "mpp34";
+		marvell,function = "gpio";
+	};
+	pmx_button_power_off: pmx-button-power-off {
+		marvell,pins = "mpp15";
+		marvell,function = "gpio";
+	};
+	pmx_button_power_on: pmx-button-power-on {
+		marvell,pins = "mpp13";
+		marvell,function = "gpio";
+	};
+};
+
+&i2c0 {
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "atmel,24c04";
+		pagesize = <16>;
+		reg = <0x50>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/kizbox.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kizbox.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/kizbox.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/kizbox.dts	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,10 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/Makefile linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/Makefile
--- linux-libre-3.16-gnu/arch/arm/boot/dts/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,8 @@ dtb-$(CONFIG_ARCH_BERLIN) += \
 	berlin2-sony-nsz-gs7.dtb	\
 	berlin2cd-google-chromecast.dtb	\
 	berlin2q-marvell-dmp.dtb
+dtb-$(CONFIG_ARCH_BRCMSTB) += \
+	bcm7445-bcm97445svmb.dtb
 dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
 	da850-evm.dtb
 dtb-$(CONFIG_ARCH_EFM32) += efm32gg-dk3750.dtb
@@ -66,7 +68,9 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-
 	exynos4210-smdkv310.dtb \
 	exynos4210-trats.dtb \
 	exynos4210-universal_c210.dtb \
+	exynos4412-odroidu3.dtb \
 	exynos4412-odroidx.dtb \
+	exynos4412-odroidx2.dtb \
 	exynos4412-origen.dtb \
 	exynos4412-smdk4412.dtb \
 	exynos4412-tiny4412.dtb \
@@ -83,6 +87,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-
 	exynos5440-ssdk5440.dtb \
 	exynos5800-peach-pi.dtb
 dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb
+dtb-$(CONFIG_ARCH_HIX5HD2) += hisi-x5hd2-dkb.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
@@ -90,9 +95,9 @@ dtb-$(CONFIG_ARCH_INTEGRATOR) += integra
 dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \
 	k2l-evm.dtb \
 	k2e-evm.dtb
-kirkwood := \
-	kirkwood-b3.dtb \
+dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
 	kirkwood-cloudbox.dtb \
+	kirkwood-d2net.dtb \
 	kirkwood-db-88f6281.dtb \
 	kirkwood-db-88f6282.dtb \
 	kirkwood-dns320.dtb \
@@ -123,6 +128,8 @@ kirkwood := \
 	kirkwood-lsxhl.dtb \
 	kirkwood-mplcec4.dtb \
 	kirkwood-mv88f6281gtw-ge.dtb \
+	kirkwood-net2big.dtb \
+	kirkwood-net5big.dtb \
 	kirkwood-netgear_readynas_duo_v2.dtb \
 	kirkwood-netgear_readynas_nv+_v2.dtb \
 	kirkwood-ns2.dtb \
@@ -150,17 +157,19 @@ kirkwood := \
 	kirkwood-ts219-6282.dtb \
 	kirkwood-ts419-6281.dtb \
 	kirkwood-ts419-6282.dtb
-dtb-$(CONFIG_ARCH_KIRKWOOD) += $(kirkwood)
-dtb-$(CONFIG_MACH_KIRKWOOD) += $(kirkwood)
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
 dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
 	imx25-eukrea-mbimxsd25-baseboard.dtb \
+	imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dtb \
+	imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dtb \
+	imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \
 	imx25-karo-tx25.dtb \
 	imx25-pdk.dtb \
 	imx27-apf27.dtb \
 	imx27-apf27dev.dtb \
+	imx27-eukrea-mbimxsd27-baseboard.dtb \
 	imx27-pdk.dtb \
 	imx27-phytec-phycore-rdk.dtb \
 	imx27-phytec-phycard-s-rdk.dtb \
@@ -182,6 +191,8 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx53-tx53-x03x.dtb \
 	imx53-tx53-x13x.dtb \
 	imx53-voipac-bsb.dtb \
+	imx6dl-aristainetos_4.dtb \
+	imx6dl-aristainetos_7.dtb \
 	imx6dl-cubox-i.dtb \
 	imx6dl-dfi-fs700-m60.dtb \
 	imx6dl-gw51xx.dtb \
@@ -191,11 +202,16 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx6dl-hummingboard.dtb \
 	imx6dl-nitrogen6x.dtb \
 	imx6dl-phytec-pbab01.dtb \
+	imx6dl-rex-basic.dtb \
 	imx6dl-riotboard.dtb \
 	imx6dl-sabreauto.dtb \
 	imx6dl-sabrelite.dtb \
 	imx6dl-sabresd.dtb \
+	imx6dl-tx6dl-comtft.dtb \
+	imx6dl-tx6u-801x.dtb \
+	imx6dl-tx6u-811x.dtb \
 	imx6dl-wandboard.dtb \
+	imx6dl-wandboard-revb1.dtb \
 	imx6q-arm2.dtb \
 	imx6q-cm-fx6.dtb \
 	imx6q-cubox-i.dtb \
@@ -209,13 +225,21 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx6q-gw54xx.dtb \
 	imx6q-nitrogen6x.dtb \
 	imx6q-phytec-pbab01.dtb \
+	imx6q-rex-pro.dtb \
 	imx6q-sabreauto.dtb \
 	imx6q-sabrelite.dtb \
 	imx6q-sabresd.dtb \
 	imx6q-sbc6x.dtb \
 	imx6q-udoo.dtb \
 	imx6q-wandboard.dtb \
+	imx6q-wandboard-revb1.dtb \
+	imx6q-tx6q-1010.dtb \
+	imx6q-tx6q-1010-comtft.dtb \
+	imx6q-tx6q-1020.dtb \
+	imx6q-tx6q-1020-comtft.dtb \
+	imx6q-tx6q-1110.dtb \
 	imx6sl-evk.dtb \
+	imx6sx-sdb.dtb \
 	vf610-colibri.dtb \
 	vf610-cosmic.dtb \
 	vf610-twr.dtb
@@ -291,7 +315,8 @@ dtb-$(CONFIG_SOC_AM33XX) += am335x-base0
 	am335x-boneblack.dtb \
 	am335x-evm.dtb \
 	am335x-evmsk.dtb \
-	am335x-nano.dtb
+	am335x-nano.dtb \
+	am335x-pepper.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
 	omap4-panda.dtb \
 	omap4-panda-a4.dtb \
@@ -301,6 +326,7 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duover
 	omap4-var-dvk-om44.dtb \
 	omap4-var-stk-om44.dtb
 dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \
+	am437x-sk-evm.dtb \
 	am437x-gp-evm.dtb
 dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \
 	omap5-sbc-t54.dtb \
@@ -318,16 +344,25 @@ dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8084-mtp.dtb \
 	qcom-msm8660-surf.dtb \
 	qcom-msm8960-cdp.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += \
+	rk3066a-bqcurie2.dtb \
+	rk3188-radxarock.dtb \
+	rk3288-evb-act8846.dtb \
+	rk3288-evb-rk808.dtb
 dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
 dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
 	s3c6410-smdk6410.dtb
+dtb-$(CONFIG_ARCH_S5PV210) += s5pv210-aquila.dtb \
+	s5pv210-goni.dtb \
+	s5pv210-smdkc110.dtb \
+	s5pv210-smdkv210.dtb \
+	s5pv210-torbreck.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += r7s72100-genmai.dtb \
 	r8a7740-armadillo800eva.dtb \
 	r8a7778-bockw.dtb \
 	r8a7778-bockw-reference.dtb \
 	r8a7740-armadillo800eva-reference.dtb \
 	r8a7779-marzen.dtb \
-	r8a7779-marzen-reference.dtb \
 	r8a7791-koelsch.dtb \
 	r8a7790-lager.dtb \
 	sh73a0-kzm9g.dtb \
@@ -339,7 +374,8 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += eme
 	r7s72100-genmai.dtb \
 	r8a7791-henninger.dtb \
 	r8a7791-koelsch.dtb \
-	r8a7790-lager.dtb
+	r8a7790-lager.dtb \
+	r8a7779-marzen.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \
 	socfpga_cyclone5_socdk.dtb \
 	socfpga_cyclone5_sockit.dtb \
@@ -360,6 +396,7 @@ dtb-$(CONFIG_ARCH_STI)+= stih407-b2120.d
 	stih416-b2020e.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
 	sun4i-a10-a1000.dtb \
+	sun4i-a10-ba10-tvbox.dtb \
 	sun4i-a10-cubieboard.dtb \
 	sun4i-a10-mini-xplus.dtb \
 	sun4i-a10-hackberry.dtb \
@@ -374,12 +411,16 @@ dtb-$(CONFIG_MACH_SUN5I) += \
 dtb-$(CONFIG_MACH_SUN6I) += \
 	sun6i-a31-app4-evb1.dtb \
 	sun6i-a31-colombus.dtb \
+	sun6i-a31-hummingbird.dtb \
 	sun6i-a31-m9.dtb
 dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-cubieboard2.dtb \
 	sun7i-a20-cubietruck.dtb \
 	sun7i-a20-i12-tvbox.dtb \
-	sun7i-a20-olinuxino-micro.dtb
+	sun7i-a20-olinuxino-micro.dtb \
+	sun7i-a20-pcduino3.dtb
+dtb-$(CONFIG_MACH_SUN8I) += \
+	sun8i-a23-ippo-q8h-v5.dtb
 dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 	tegra20-iris-512.dtb \
 	tegra20-medcom-wide.dtb \
@@ -390,6 +431,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harm
 	tegra20-trimslice.dtb \
 	tegra20-ventana.dtb \
 	tegra20-whistler.dtb \
+	tegra30-apalis-eval.dtb \
 	tegra30-beaver.dtb \
 	tegra30-cardhu-a02.dtb \
 	tegra30-cardhu-a04.dtb \
@@ -419,7 +461,9 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07
 	wm8650-mid.dtb \
 	wm8750-apc8750.dtb \
 	wm8850-w70v2.dtb
-dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \
+dtb-$(CONFIG_ARCH_ZYNQ) += \
+	zynq-parallella.dtb \
+	zynq-zc702.dtb \
 	zynq-zc706.dtb \
 	zynq-zed.dtb
 dtb-$(CONFIG_MACH_ARMADA_370) += \
@@ -437,11 +481,13 @@ dtb-$(CONFIG_MACH_ARMADA_XP) += \
 	armada-xp-axpwifiap.dtb \
 	armada-xp-db.dtb \
 	armada-xp-gp.dtb \
-	armada-xp-netgear-rn2120.dtb \
+	armada-xp-lenovo-ix4-300d.dtb \
 	armada-xp-matrix.dtb \
+	armada-xp-netgear-rn2120.dtb \
 	armada-xp-openblocks-ax3-4.dtb
 dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-cubox.dtb \
+	dove-cubox-es.dtb \
 	dove-d2plug.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/mpa1600.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mpa1600.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/mpa1600.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mpa1600.dts	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <18432000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/mt6589-aquaris5.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mt6589-aquaris5.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/mt6589-aquaris5.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mt6589-aquaris5.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@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.
+ */
+
+/dts-v1/;
+#include "mt6589.dtsi"
+
+/ {
+	model = "bq Aquaris5";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/mt6589.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mt6589.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/mt6589.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/mt6589.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@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 <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "mediatek,mt6589";
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x1>;
+		};
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x2>;
+		};
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x3>;
+		};
+
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		system_clk: dummy13m {
+			compatible = "fixed-clock";
+			clock-frequency = <13000000>;
+			#clock-cells = <0>;
+		};
+
+		rtc_clk: dummy32k {
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+			#clock-cells = <0>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		timer: timer@10008000 {
+			compatible = "mediatek,mt6577-timer";
+			reg = <0x10008000 0x80>;
+			interrupts = <GIC_SPI 113 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&system_clk>, <&rtc_clk>;
+			clock-names = "system-clk", "rtc-clk";
+		};
+
+		gic: interrupt-controller@10212000 {
+			compatible = "arm,cortex-a15-gic";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0x10211000 0x1000>,
+			      <0x10212000 0x1000>,
+			      <0x10214000 0x2000>,
+			      <0x10216000 0x2000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap2420.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap2420.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap2420.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap2420.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -157,6 +157,8 @@
 			interrupts = <26>, <34>;
 			interrupt-names = "dsp", "iva";
 			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <6>;
 		};
 
 		timer1: timer@48028000 {
@@ -182,3 +184,6 @@
 &i2c2 {
 	compatible = "ti,omap2420-i2c";
 };
+
+/include/ "omap24xx-clocks.dtsi"
+/include/ "omap2420-clocks.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap2430.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap2430.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap2430.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap2430.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -247,6 +247,8 @@
 			reg = <0x48094000 0x200>;
 			interrupts = <26>;
 			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <6>;
 		};
 
 		timer1: timer@49018000 {
@@ -288,3 +290,6 @@
 &i2c2 {
 	compatible = "ti,omap2430-i2c";
 };
+
+/include/ "omap24xx-clocks.dtsi"
+/include/ "omap2430-clocks.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap3430-sdp.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3430-sdp.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap3430-sdp.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3430-sdp.dts	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <1 0 0x08000000>;
-		ti,nand-ecc-opt = "ham1";
+		ti,nand-ecc-opt = "sw";
 		nand-bus-width = <8>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <36>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap3-beagle.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3-beagle.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap3-beagle.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3-beagle.dts	2014-09-28 17:29:07.000000000 -0400
@@ -292,6 +292,7 @@
 &uart3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart3_pins>;
+	interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
 };
 
 &gpio1 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap3.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap3.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -332,6 +332,8 @@
 			ti,hwmods = "mailbox";
 			reg = <0x48094000 0x200>;
 			interrupts = <26>;
+			ti,mbox-num-users = <2>;
+			ti,mbox-num-fifos = <2>;
 		};
 
 		mcspi1: spi@48098000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap3-n900.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3-n900.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap3-n900.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3-n900.dts	2014-09-28 17:29:07.000000000 -0400
@@ -93,7 +93,7 @@
 	};
 
 	tv: connector {
-		compatible = "composite-connector";
+		compatible = "composite-video-connector";
 		label = "tv";
 
 		port {
@@ -353,7 +353,7 @@
 	};
 
 	twl_power: power {
-		compatible = "ti,twl4030-power-n900";
+		compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off";
 		ti,use_poweroff;
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -467,6 +467,7 @@
 		ti,bit-shift = <0x1e>;
 		reg = <0x0d00>;
 		ti,set-bit-to-disable;
+		ti,set-rate-parent;
 	};
 
 	dpll4_m6_ck: dpll4_m6_ck {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap4.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap4.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap4.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap4.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -649,6 +649,15 @@
 			};
 		};
 
+		mailbox: mailbox@4a0f4000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x4a0f4000 0x200>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <3>;
+			ti,mbox-num-fifos = <8>;
+		};
+
 		timer1: timer@4a318000 {
 			compatible = "ti,omap3430-timer";
 			reg = <0x4a318000 0x80>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -367,10 +367,12 @@
 
 	l3_iclk_div: l3_iclk_div {
 		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
+		compatible = "ti,divider-clock";
+		ti,max-div = <2>;
+		ti,bit-shift = <4>;
+		reg = <0x100>;
 		clocks = <&dpll_core_h12x2_ck>;
-		clock-mult = <1>;
-		clock-div = <1>;
+		ti,index-power-of-two;
 	};
 
 	gpu_l3_iclk: gpu_l3_iclk {
@@ -383,10 +385,12 @@
 
 	l4_root_clk_div: l4_root_clk_div {
 		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
+		compatible = "ti,divider-clock";
+		ti,max-div = <2>;
+		ti,bit-shift = <8>;
+		reg = <0x100>;
 		clocks = <&l3_iclk_div>;
-		clock-mult = <1>;
-		clock-div = <1>;
+		ti,index-power-of-two;
 	};
 
 	slimbus1_slimbus_clk: slimbus1_slimbus_clk {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap5-cm-t54.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5-cm-t54.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap5-cm-t54.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5-cm-t54.dts	2014-09-28 17:29:07.000000000 -0400
@@ -353,13 +353,12 @@
 				};
 
 				ldo8_reg: ldo8 {
-					/* VDD_3v0: Does not go anywhere */
+					/* VDD_3V_GP: act led/serial console */
 					regulator-name = "ldo8";
 					regulator-min-microvolt = <3000000>;
 					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
 					regulator-boot-on;
-					/* Unused */
-					status = "disabled";
 				};
 
 				ldo9_reg: ldo9 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap5.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap5.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -640,6 +640,8 @@
 			reg = <0x4a0f4000 0x200>;
 			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <3>;
+			ti,mbox-num-fifos = <8>;
 		};
 
 		timer1: timer@4ae18000 {
@@ -985,6 +987,66 @@
 				dma-names = "audio_tx";
 			};
 		};
+
+		abb_mpu: regulator-abb-mpu {
+			compatible = "ti,abb-v2";
+			regulator-name = "abb_mpu";
+			#address-cells = <0>;
+			#size-cells = <0>;
+			clocks = <&sys_clkin>;
+			ti,settling-time = <50>;
+			ti,clock-cycles = <16>;
+
+			reg = <0x4ae07cdc 0x8>, <0x4ae06014 0x4>,
+			      <0x4a0021c4 0x8>, <0x4ae0c318 0x4>;
+			reg-names = "base-address", "int-address",
+				    "efuse-address", "ldo-address";
+			ti,tranxdone-status-mask = <0x80>;
+			/* LDOVBBMPU_MUX_CTRL */
+			ti,ldovbb-override-mask = <0x400>;
+			/* LDOVBBMPU_VSET_OUT */
+			ti,ldovbb-vset-mask = <0x1F>;
+
+			/*
+			 * NOTE: only FBB mode used but actual vset will
+			 * determine final biasing
+			 */
+			ti,abb_info = <
+			/*uV		ABB	efuse	rbb_m fbb_m	vset_m*/
+			1060000		0	0x0	0 0x02000000 0x01F00000
+			1250000		0	0x4	0 0x02000000 0x01F00000
+			>;
+		};
+
+		abb_mm: regulator-abb-mm {
+			compatible = "ti,abb-v2";
+			regulator-name = "abb_mm";
+			#address-cells = <0>;
+			#size-cells = <0>;
+			clocks = <&sys_clkin>;
+			ti,settling-time = <50>;
+			ti,clock-cycles = <16>;
+
+			reg = <0x4ae07ce4 0x8>, <0x4ae06010 0x4>,
+			      <0x4a0021a4 0x8>, <0x4ae0c314 0x4>;
+			reg-names = "base-address", "int-address",
+				    "efuse-address", "ldo-address";
+			ti,tranxdone-status-mask = <0x80000000>;
+			/* LDOVBBMM_MUX_CTRL */
+			ti,ldovbb-override-mask = <0x400>;
+			/* LDOVBBMM_VSET_OUT */
+			ti,ldovbb-vset-mask = <0x1F>;
+
+			/*
+			 * NOTE: only FBB mode used but actual vset will
+			 * determine final biasing
+			 */
+			ti,abb_info = <
+			/*uV		ABB	efuse	rbb_m fbb_m	vset_m*/
+			1025000		0	0x0	0 0x02000000 0x01F00000
+			1120000		0	0x4	0 0x02000000 0x01F00000
+			>;
+		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/omap5-uevm.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5-uevm.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/omap5-uevm.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/omap5-uevm.dts	2014-09-28 17:29:07.000000000 -0400
@@ -100,15 +100,33 @@
 			};
 		};
 	};
+
+	sound: sound {
+		compatible = "ti,abe-twl6040";
+		ti,model = "omap5-uevm";
+
+		ti,mclk-freq = <19200000>;
+
+		ti,mcpdm = <&mcpdm>;
+
+		ti,twl6040 = <&twl6040>;
+
+		/* Audio routing */
+		ti,audio-routing =
+			"Headset Stereophone", "HSOL",
+			"Headset Stereophone", "HSOR",
+			"Line Out", "AUXL",
+			"Line Out", "AUXR",
+			"HSMIC", "Headset Mic",
+			"Headset Mic", "Headset Mic Bias",
+			"AFML", "Line In",
+			"AFMR", "Line In";
+	};
 };
 
 &omap5_pmx_core {
 	pinctrl-names = "default";
 	pinctrl-0 = <
-			&twl6040_pins
-			&mcpdm_pins
-			&mcbsp1_pins
-			&mcbsp2_pins
 			&usbhost_pins
 			&led_gpio_pins
 	>;
@@ -306,6 +324,11 @@
 			ti,wakeup;
 		};
 
+		clk32kgaudio: palmas_clk32k@1 {
+			compatible = "ti,palmas-clk32kgaudio";
+			#clock-cells = <0>;
+		};
+
 		palmas_pmic {
 			compatible = "ti,palmas-pmic";
 			interrupt-parent = <&palmas>;
@@ -489,6 +512,25 @@
 			};
 		};
 	};
+
+	twl6040: twl@4b {
+		compatible = "ti,twl6040";
+		reg = <0x4b>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&twl6040_pins>;
+
+		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
+		interrupt-parent = <&gic>;
+		ti,audpwron-gpio = <&gpio5 13 0>;  /* gpio line 141 */
+
+		vio-supply = <&smps7_reg>;
+		v2v1-supply = <&smps9_reg>;
+		enable-active-high;
+
+		clocks = <&clk32kgaudio>;
+		clock-names = "clk32k";
+	};
 };
 
 &i2c5 {
@@ -505,8 +547,22 @@
 	};
 };
 
-&mcbsp3 {
-	status = "disabled";
+&mcpdm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcpdm_pins>;
+	status = "okay";
+};
+
+&mcbsp1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp1_pins>;
+	status = "okay";
+};
+
+&mcbsp2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp2_pins>;
+	status = "okay";
 };
 
 &usbhshost {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/pm9g45.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/pm9g45.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/pm9g45.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/pm9g45.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+		      clock-frequency = <32768>;
+		};
+
+		main_xtal {
+		      clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r7s72100.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r7s72100.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r7s72100.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r7s72100.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -144,6 +144,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clock-frequency = <400000000>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r7s72100-genmai.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r7s72100-genmai.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r7s72100-genmai.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r7s72100-genmai.dts	2014-09-28 17:29:07.000000000 -0400
@@ -57,3 +57,13 @@
 &scif2 {
 	status = "okay";
 };
+
+&spi4 {
+	status = "okay";
+
+	codec: codec@0 {
+		compatible = "wlf,wm8978";
+		reg = <0>;
+		spi-max-frequency = <5000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,10 @@
 	model = "APE6EVM";
 	compatible = "renesas,ape6evm-reference", "renesas,r8a73a4";
 
+	aliases {
+		serial0 = &scifa0;
+	};
+
 	chosen {
 		bootargs = "console=ttySC0,115200 ignore_loglevel rw";
 	};
@@ -90,9 +94,6 @@
 };
 
 &pfc {
-	pinctrl-0 = <&scifa0_pins>;
-	pinctrl-names = "default";
-
 	scifa0_pins: serial0 {
 		renesas,groups = "scifa0_data";
 		renesas,function = "scifa0";
@@ -123,6 +124,13 @@
 	status = "okay";
 };
 
+&scifa0 {
+	pinctrl-0 = <&scifa0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
 &sdhi0 {
 	vmmc-supply = <&vcc_sdhi0>;
 	bus-width = <4>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a73a4.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a73a4.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -252,6 +252,48 @@
 		status = "disabled";
 	};
 
+	scifa0: serial@e6c40000 {
+		compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
+		reg = <0 0xe6c40000 0 0x100>;
+		interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa1: serial@e6c50000 {
+		compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
+		reg = <0 0xe6c50000 0 0x100>;
+		interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb2: serial@e6c20000 {
+		compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+		reg = <0 0xe6c20000 0 0x100>;
+		interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb3: serial@e6c30000 {
+		compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+		reg = <0 0xe6c30000 0 0x100>;
+		interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb4: serial@e6ce0000 {
+		compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+		reg = <0 0xe6ce0000 0 0x100>;
+		interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb5: serial@e6cf0000 {
+		compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+		reg = <0 0xe6cf0000 0 0x100>;
+		interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
 	mmcif0: mmc@ee200000 {
 		compatible = "renesas,sh-mmcif";
 		reg = <0 0xee200000 0 0x80>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,12 @@
 	model = "armadillo 800 eva reference";
 	compatible = "renesas,armadillo800eva-reference", "renesas,r8a7740";
 
+	aliases {
+		serial1 = &scifa1;
+	};
+
 	chosen {
-		bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
+		bootargs = "console=tty0 console=ttySC1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
 
 	memory {
@@ -104,17 +108,21 @@
 
 	leds {
 		compatible = "gpio-leds";
-		led1 {
+		led3 {
 			gpios = <&pfc 102 GPIO_ACTIVE_HIGH>;
+			label = "LED3";
 		};
-		led2 {
+		led4 {
 			gpios = <&pfc 111 GPIO_ACTIVE_HIGH>;
+			label = "LED4";
 		};
-		led3 {
+		led5 {
 			gpios = <&pfc 110 GPIO_ACTIVE_HIGH>;
+			label = "LED5";
 		};
-		led4 {
+		led6 {
 			gpios = <&pfc 177 GPIO_ACTIVE_HIGH>;
+			label = "LED6";
 		};
 	};
 
@@ -198,9 +206,6 @@
 };
 
 &pfc {
-	pinctrl-0 = <&scifa1_pins>;
-	pinctrl-names = "default";
-
 	ether_pins: ether {
 		renesas,groups = "gether_mii", "gether_int";
 		renesas,function = "gether";
@@ -252,6 +257,13 @@
 	status = "okay";
 };
 
+&scifa1 {
+	pinctrl-0 = <&scifa1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7740.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7740.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7740.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7740.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -156,6 +156,69 @@
 		status = "disabled";
 	};
 
+	scifa0: serial@e6c40000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6c40000 0x100>;
+		interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa1: serial@e6c50000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6c50000 0x100>;
+		interrupts = <0 101 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa2: serial@e6c60000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6c60000 0x100>;
+		interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa3: serial@e6c70000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6c70000 0x100>;
+		interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa4: serial@e6c80000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6c80000 0x100>;
+		interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa5: serial@e6cb0000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6cb0000 0x100>;
+		interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa6: serial@e6cc0000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6cc0000 0x100>;
+		interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa7: serial@e6cd0000 {
+		compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+		reg = <0xe6cd0000 0x100>;
+		interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb8: serial@e6c30000 {
+		compatible = "renesas,scifb-r8a7740", "renesas,scifb";
+		reg = <0xe6c30000 0x100>;
+		interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
 	pfc: pfc@e6050000 {
 		compatible = "renesas,pfc-r8a7740";
 		reg = <0xe6050000 0x8000>,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7778-bockw-reference.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7778-bockw-reference.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7778-bockw-reference.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7778-bockw-reference.dts	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,10 @@
 	model = "bockw";
 	compatible = "renesas,bockw-reference", "renesas,r8a7778";
 
+	aliases {
+		serial0 = &scif0;
+	};
+
 	chosen {
 		bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
@@ -70,9 +74,6 @@
 };
 
 &pfc {
-	pinctrl-0 = <&scif0_pins>;
-	pinctrl-names = "default";
-
 	scif0_pins: serial0 {
 		renesas,groups = "scif0_data_a", "scif0_ctrl";
 		renesas,function = "scif0";
@@ -124,3 +125,10 @@
 		};
 	};
 };
+
+&scif0 {
+	pinctrl-0 = <&scif0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7778.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7778.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7778.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7778.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -156,6 +156,48 @@
 		status = "disabled";
 	};
 
+	scif0: serial@ffe40000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe40000 0x100>;
+		interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scif1: serial@ffe41000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe41000 0x100>;
+		interrupts = <0 71 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scif2: serial@ffe42000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe42000 0x100>;
+		interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scif3: serial@ffe43000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe43000 0x100>;
+		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scif4: serial@ffe44000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe44000 0x100>;
+		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scif5: serial@ffe45000 {
+		compatible = "renesas,scif-r8a7778", "renesas,scif";
+		reg = <0xffe45000 0x100>;
+		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
 	mmcif: mmc@ffe4e000 {
 		compatible = "renesas,sh-mmcif";
 		reg = <0xffe4e000 0x100>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/clock/r8a7779-clock.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
@@ -25,21 +26,25 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clock-frequency = <1000000000>;
 		};
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clock-frequency = <1000000000>;
 		};
 		cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <2>;
+			clock-frequency = <1000000000>;
 		};
 		cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <3>;
+			clock-frequency = <1000000000>;
 		};
 	};
 
@@ -49,13 +54,13 @@
 		spi2 = &hspi2;
 	};
 
-        gic: interrupt-controller@f0001000 {
-                compatible = "arm,cortex-a9-gic";
-                #interrupt-cells = <3>;
-                interrupt-controller;
-                reg = <0xf0001000 0x1000>,
-                      <0xf0000100 0x100>;
-        };
+	gic: interrupt-controller@f0001000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0xf0001000 0x1000>,
+		      <0xf0000100 0x100>;
+	};
 
 	gpio0: gpio@ffc40000 {
 		compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
@@ -157,6 +162,7 @@
 		compatible = "renesas,i2c-r8a7779";
 		reg = <0xffc70000 0x1000>;
 		interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7779_CLK_I2C0>;
 		status = "disabled";
 	};
 
@@ -166,6 +172,7 @@
 		compatible = "renesas,i2c-r8a7779";
 		reg = <0xffc71000 0x1000>;
 		interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7779_CLK_I2C1>;
 		status = "disabled";
 	};
 
@@ -175,6 +182,7 @@
 		compatible = "renesas,i2c-r8a7779";
 		reg = <0xffc72000 0x1000>;
 		interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7779_CLK_I2C2>;
 		status = "disabled";
 	};
 
@@ -184,6 +192,67 @@
 		compatible = "renesas,i2c-r8a7779";
 		reg = <0xffc73000 0x1000>;
 		interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7779_CLK_I2C3>;
+		status = "disabled";
+	};
+
+	scif0: serial@ffe40000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe40000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif1: serial@ffe41000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe41000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif2: serial@ffe42000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe42000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif3: serial@ffe43000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe43000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif4: serial@ffe44000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe44000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
+		status = "disabled";
+	};
+
+	scif5: serial@ffe45000 {
+		compatible = "renesas,scif-r8a7779", "renesas,scif";
+		reg = <0xffe45000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 93 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg_clocks R8A7779_CLK_P>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -201,12 +270,14 @@
 		compatible = "renesas,rcar-sata";
 		reg = <0xfc600000 0x2000>;
 		interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7779_CLK_SATA>;
 	};
 
 	sdhi0: sd@ffe4c000 {
 		compatible = "renesas,sdhi-r8a7779";
 		reg = <0xffe4c000 0x100>;
 		interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7779_CLK_SDHI0>;
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
@@ -216,6 +287,7 @@
 		compatible = "renesas,sdhi-r8a7779";
 		reg = <0xffe4d000 0x100>;
 		interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7779_CLK_SDHI1>;
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
@@ -225,6 +297,7 @@
 		compatible = "renesas,sdhi-r8a7779";
 		reg = <0xffe4e000 0x100>;
 		interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7779_CLK_SDHI2>;
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
@@ -234,6 +307,7 @@
 		compatible = "renesas,sdhi-r8a7779";
 		reg = <0xffe4f000 0x100>;
 		interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7779_CLK_SDHI3>;
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
@@ -245,6 +319,7 @@
 		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
 		status = "disabled";
 	};
 
@@ -254,6 +329,7 @@
 		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
 		status = "disabled";
 	};
 
@@ -263,6 +339,150 @@
 		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
 		status = "disabled";
 	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* External root clock */
+		extal_clk: extal_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			/* This value must be overriden by the board. */
+			clock-frequency = <0>;
+			clock-output-names = "extal";
+		};
+
+		/* Special CPG clocks */
+		cpg_clocks: clocks@ffc80000 {
+			compatible = "renesas,r8a7779-cpg-clocks";
+			reg = <0xffc80000 0x30>;
+			clocks = <&extal_clk>;
+			#clock-cells = <1>;
+			clock-output-names = "plla", "z", "zs", "s",
+					     "s1", "p", "b", "out";
+		};
+
+		/* Fixed factor clocks */
+		i_clk: i_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "i";
+		};
+		s3_clk: s3_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+			clock-output-names = "s3";
+		};
+		s4_clk: s4_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+			#clock-cells = <0>;
+			clock-div = <16>;
+			clock-mult = <1>;
+			clock-output-names = "s4";
+		};
+		g_clk: g_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+			#clock-cells = <0>;
+			clock-div = <24>;
+			clock-mult = <1>;
+			clock-output-names = "g";
+		};
+
+		/* Gate clocks */
+		mstp0_clks: clocks@ffc80030 {
+			compatible = "renesas,r8a7779-mstp-clocks",
+			             "renesas,cpg-mstp-clocks";
+			reg = <0xffc80030 4>;
+			clocks = <&cpg_clocks R8A7779_CLK_S>,
+			         <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_S1>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>;
+			#clock-cells = <1>;
+			renesas,clock-indices = <
+				R8A7779_CLK_HSPI R8A7779_CLK_TMU2
+				R8A7779_CLK_TMU1 R8A7779_CLK_TMU0
+				R8A7779_CLK_HSCIF1 R8A7779_CLK_HSCIF0
+				R8A7779_CLK_SCIF5 R8A7779_CLK_SCIF4
+				R8A7779_CLK_SCIF3 R8A7779_CLK_SCIF2
+				R8A7779_CLK_SCIF1 R8A7779_CLK_SCIF0
+				R8A7779_CLK_I2C3 R8A7779_CLK_I2C2
+				R8A7779_CLK_I2C1 R8A7779_CLK_I2C0
+			>;
+			clock-output-names =
+				"hspi", "tmu2", "tmu1", "tmu0", "hscif1",
+				"hscif0", "scif5", "scif4", "scif3", "scif2",
+				"scif1", "scif0", "i2c3", "i2c2", "i2c1",
+				"i2c0";
+		};
+		mstp1_clks: clocks@ffc80034 {
+			compatible = "renesas,r8a7779-mstp-clocks",
+			             "renesas,cpg-mstp-clocks";
+			reg = <0xffc80034 4>, <0xffc80044 4>;
+			clocks = <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_S>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_P>,
+				 <&cpg_clocks R8A7779_CLK_S>;
+			#clock-cells = <1>;
+			renesas,clock-indices = <
+				R8A7779_CLK_USB01 R8A7779_CLK_USB2
+				R8A7779_CLK_DU R8A7779_CLK_VIN2
+				R8A7779_CLK_VIN1 R8A7779_CLK_VIN0
+				R8A7779_CLK_ETHER R8A7779_CLK_SATA
+				R8A7779_CLK_PCIE R8A7779_CLK_VIN3
+			>;
+			clock-output-names =
+				"usb01", "usb2",
+				"du", "vin2",
+				"vin1", "vin0",
+				"ether", "sata",
+				"pcie", "vin3";
+		};
+		mstp3_clks: clocks@ffc8003c {
+			compatible = "renesas,r8a7779-mstp-clocks",
+			             "renesas,cpg-mstp-clocks";
+			reg = <0xffc8003c 4>;
+			clocks = <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>,
+				 <&s4_clk>, <&s4_clk>;
+			#clock-cells = <1>;
+			renesas,clock-indices = <
+				R8A7779_CLK_SDHI3 R8A7779_CLK_SDHI2
+				R8A7779_CLK_SDHI1 R8A7779_CLK_SDHI0
+				R8A7779_CLK_MMC1 R8A7779_CLK_MMC0
+			>;
+			clock-output-names =
+				"sdhi3", "sdhi2", "sdhi1", "sdhi0",
+				"mmc1", "mmc0";
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779-marzen.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779-marzen.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2014-09-28 17:29:07.000000000 -0400
@@ -11,17 +11,131 @@
 
 /dts-v1/;
 #include "r8a7779.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	model = "marzen";
 	compatible = "renesas,marzen", "renesas,r8a7779";
 
+	aliases {
+		serial2 = &scif2;
+		serial4 = &scif4;
+	};
+
 	chosen {
-		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on";
+		bootargs = "console=ttySC2,115200 ignore_loglevel root=/dev/nfs ip=on";
 	};
 
 	memory {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
+
+	fixedregulator3v3: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	lan0@18000000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x18000000 0x100>;
+		pinctrl-0 = <&lan0_pins>;
+		pinctrl-names = "default";
+
+		phy-mode = "mii";
+		interrupt-parent = <&irqpin0>;
+		interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+		smsc,irq-push-pull;
+		reg-io-width = <4>;
+		vddvario-supply = <&fixedregulator3v3>;
+		vdd33a-supply = <&fixedregulator3v3>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led2 {
+			gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+		};
+		led3 {
+			gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+		};
+		led4 {
+			gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&irqpin0 {
+	status = "okay";
+};
+
+&extal_clk {
+	clock-frequency = <31250000>;
+};
+
+&pfc {
+	lan0_pins: lan0 {
+		intc {
+			renesas,groups = "intc_irq1_b";
+			renesas,function = "intc";
+		};
+		lbsc {
+			renesas,groups = "lbsc_ex_cs0";
+			renesas,function = "lbsc";
+		};
+	};
+
+	scif2_pins: serial2 {
+		renesas,groups = "scif2_data_c";
+		renesas,function = "scif2";
+	};
+
+	scif4_pins: serial4 {
+		renesas,groups = "scif4_data";
+		renesas,function = "scif4";
+	};
+
+	sdhi0_pins: sd0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+		renesas,function = "sdhi0";
+	};
+
+	hspi0_pins: hspi0 {
+		renesas,groups = "hspi0";
+		renesas,function = "hspi0";
+	};
+};
+
+&scif2 {
+	pinctrl-0 = <&scif2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&scif4 {
+	pinctrl-0 = <&scif4_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&fixedregulator3v3>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&hspi0 {
+	pinctrl-0 = <&hspi0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779-marzen-reference.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779-marzen-reference.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7779-marzen-reference.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7779-marzen-reference.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/*
- * Reference Device Tree Source for the Marzen board
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- * Copyright (C) 2013 Simon Horman
- *
- * 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 "r8a7779.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
-/ {
-	model = "marzen";
-	compatible = "renesas,marzen-reference", "renesas,r8a7779";
-
-	chosen {
-		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on rw";
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x60000000 0x40000000>;
-	};
-
-	fixedregulator3v3: fixedregulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "fixed-3.3V";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
-
-	lan0@18000000 {
-		compatible = "smsc,lan9220", "smsc,lan9115";
-		reg = <0x18000000 0x100>;
-		pinctrl-0 = <&lan0_pins>;
-		pinctrl-names = "default";
-
-		phy-mode = "mii";
-		interrupt-parent = <&irqpin0>;
-		interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
-		smsc,irq-push-pull;
-		reg-io-width = <4>;
-		vddvario-supply = <&fixedregulator3v3>;
-		vdd33a-supply = <&fixedregulator3v3>;
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		led2 {
-			gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
-		};
-		led3 {
-			gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
-		};
-		led4 {
-			gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
-		};
-	};
-};
-
-&irqpin0 {
-	status = "okay";
-};
-
-&pfc {
-	pinctrl-0 = <&scif2_pins &scif4_pins>;
-	pinctrl-names = "default";
-
-	lan0_pins: lan0 {
-		intc {
-			renesas,groups = "intc_irq1_b";
-			renesas,function = "intc";
-		};
-		lbsc {
-			renesas,groups = "lbsc_ex_cs0";
-			renesas,function = "lbsc";
-		};
-	};
-
-	scif2_pins: serial2 {
-		renesas,groups = "scif2_data_c";
-		renesas,function = "scif2";
-	};
-
-	scif4_pins: serial4 {
-		renesas,groups = "scif4_data";
-		renesas,function = "scif4";
-	};
-
-	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
-		renesas,function = "sdhi0";
-	};
-
-	hspi0_pins: hspi0 {
-		renesas,groups = "hspi0";
-		renesas,function = "hspi0";
-	};
-};
-
-&sdhi0 {
-	pinctrl-0 = <&sdhi0_pins>;
-	pinctrl-names = "default";
-
-	vmmc-supply = <&fixedregulator3v3>;
-	bus-width = <4>;
-	status = "okay";
-};
-
-&hspi0 {
-	pinctrl-0 = <&hspi0_pins>;
-	pinctrl-names = "default";
-	status = "okay";
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7790.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7790.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7790.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7790.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,17 @@
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			clock-frequency = <1300000000>;
+			voltage-tolerance = <1>; /* 1% */
+			clocks = <&cpg_clocks R8A7790_CLK_Z>;
+			clock-latency = <300000>; /* 300 us */
+
+			/* kHz - uV - OPPs unknown yet */
+			operating-points = <1400000 1000000>,
+					   <1225000 1000000>,
+					   <1050000 1000000>,
+					   < 875000 1000000>,
+					   < 700000 1000000>,
+					   < 350000 1000000>;
 		};
 
 		cpu1: cpu@1 {
@@ -476,6 +487,15 @@
 			clock-output-names = "extal";
 		};
 
+		/* External PCIe clock - can be overridden by the board */
+		pcie_bus_clk: pcie_bus_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <100000000>;
+			clock-output-names = "pcie_bus";
+			status = "disabled";
+		};
+
 		/*
 		 * The external audio clocks are configured as 0 Hz fixed frequency clocks by
 		 * default. Boards that provide audio clocks should override them.
@@ -754,17 +774,17 @@
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>,
 				 <&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>,
-				 <&hp_clk>, <&hp_clk>, <&rclk_clk>;
+				 <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
 				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0
-				R8A7790_CLK_IIC0 R8A7790_CLK_IIC1 R8A7790_CLK_CMT1
+				R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1
 			>;
 			clock-output-names =
 				"iic2", "tpu0", "mmcif1", "sdhi3",
 				"sdhi2", "sdhi1", "sdhi0", "mmcif0",
-				"iic0", "iic1", "cmt1";
+				"iic0", "pciec", "iic1", "ssusb", "cmt1";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -824,6 +844,39 @@
 				"rcan1", "rcan0", "qspi_mod", "iic3",
 				"i2c3", "i2c2", "i2c1", "i2c0";
 		};
+		mstp10_clks: mstp10_clks@e6150998 {
+			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+			clocks = <&p_clk>,
+				<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				<&p_clk>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>;
+
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7790_CLK_SSI_ALL
+				R8A7790_CLK_SSI9 R8A7790_CLK_SSI8 R8A7790_CLK_SSI7 R8A7790_CLK_SSI6 R8A7790_CLK_SSI5
+				R8A7790_CLK_SSI4 R8A7790_CLK_SSI3 R8A7790_CLK_SSI2 R8A7790_CLK_SSI1 R8A7790_CLK_SSI0
+				R8A7790_CLK_SCU_ALL
+				R8A7790_CLK_SCU_DVC1 R8A7790_CLK_SCU_DVC0
+				R8A7790_CLK_SCU_SRC9 R8A7790_CLK_SCU_SRC8 R8A7790_CLK_SCU_SRC7 R8A7790_CLK_SCU_SRC6 R8A7790_CLK_SCU_SRC5
+				R8A7790_CLK_SCU_SRC4 R8A7790_CLK_SCU_SRC3 R8A7790_CLK_SCU_SRC2 R8A7790_CLK_SCU_SRC1 R8A7790_CLK_SCU_SRC0
+			>;
+			clock-output-names =
+				"ssi-all",
+				"ssi9", "ssi8", "ssi7", "ssi6", "ssi5",
+				"ssi4", "ssi3", "ssi2", "ssi1", "ssi0",
+				"scu-all",
+				"scu-dvc1", "scu-dvc0",
+				"scu-src9", "scu-src8", "scu-src7", "scu-src6", "scu-src5",
+				"scu-src4", "scu-src3", "scu-src2", "scu-src1", "scu-src0";
+		};
 	};
 
 	qspi: spi@e6b10000 {
@@ -876,4 +929,152 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	pci0: pci@ee090000 {
+		compatible = "renesas,pci-r8a7790";
+		device_type = "pci";
+		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+		reg = <0 0xee090000 0 0xc00>,
+		      <0 0xee080000 0 0x1100>;
+		interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		bus-range = <0 0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		ranges = <0x02000000 0 0xee080000 0 0xee080000 0 0x00010000>;
+		interrupt-map-mask = <0xff00 0 0 0x7>;
+		interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+				 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+				 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pci1: pci@ee0b0000 {
+		compatible = "renesas,pci-r8a7790";
+		device_type = "pci";
+		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+		reg = <0 0xee0b0000 0 0xc00>,
+		      <0 0xee0a0000 0 0x1100>;
+		interrupts = <0 112 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		bus-range = <1 1>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		ranges = <0x02000000 0 0xee0a0000 0 0xee0a0000 0 0x00010000>;
+		interrupt-map-mask = <0xff00 0 0 0x7>;
+		interrupt-map = <0x0000 0 0 1 &gic 0 112 IRQ_TYPE_LEVEL_HIGH
+				 0x0800 0 0 1 &gic 0 112 IRQ_TYPE_LEVEL_HIGH
+				 0x1000 0 0 2 &gic 0 112 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pci2: pci@ee0d0000 {
+		compatible = "renesas,pci-r8a7790";
+		device_type = "pci";
+		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+		reg = <0 0xee0d0000 0 0xc00>,
+		      <0 0xee0c0000 0 0x1100>;
+		interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		bus-range = <2 2>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		ranges = <0x02000000 0 0xee0c0000 0 0xee0c0000 0 0x00010000>;
+		interrupt-map-mask = <0xff00 0 0 0x7>;
+		interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+				 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+				 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pciec: pcie@fe000000 {
+		compatible = "renesas,pcie-r8a7790";
+		reg = <0 0xfe000000 0 0x80000>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x00 0xff>;
+		device_type = "pci";
+		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+		/* Map all possible DDR as inbound ranges */
+		dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000
+			      0x43000000 1 0x80000000 1 0x80000000 0 0x80000000>;
+		interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 118 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_PCIEC>, <&pcie_bus_clk>;
+		clock-names = "pcie", "pcie_bus";
+		status = "disabled";
+	};
+
+	rcar_sound: rcar_sound@0xec500000 {
+		#sound-dai-cells = <1>;
+		compatible =  "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
+		interrupt-parent = <&gic>;
+		reg =	<0 0xec500000 0 0x1000>, /* SCU */
+			<0 0xec5a0000 0 0x100>,  /* ADG */
+			<0 0xec540000 0 0x1000>, /* SSIU */
+			<0 0xec541000 0 0x1280>; /* SSI */
+		clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+			<&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>,
+			<&mstp10_clks R8A7790_CLK_SSI7>, <&mstp10_clks R8A7790_CLK_SSI6>,
+			<&mstp10_clks R8A7790_CLK_SSI5>, <&mstp10_clks R8A7790_CLK_SSI4>,
+			<&mstp10_clks R8A7790_CLK_SSI3>, <&mstp10_clks R8A7790_CLK_SSI2>,
+			<&mstp10_clks R8A7790_CLK_SSI1>, <&mstp10_clks R8A7790_CLK_SSI0>,
+			<&mstp10_clks R8A7790_CLK_SCU_SRC9>, <&mstp10_clks R8A7790_CLK_SCU_SRC8>,
+			<&mstp10_clks R8A7790_CLK_SCU_SRC7>, <&mstp10_clks R8A7790_CLK_SCU_SRC6>,
+			<&mstp10_clks R8A7790_CLK_SCU_SRC5>, <&mstp10_clks R8A7790_CLK_SCU_SRC4>,
+			<&mstp10_clks R8A7790_CLK_SCU_SRC3>, <&mstp10_clks R8A7790_CLK_SCU_SRC2>,
+			<&mstp10_clks R8A7790_CLK_SCU_SRC1>, <&mstp10_clks R8A7790_CLK_SCU_SRC0>,
+			<&mstp10_clks R8A7790_CLK_SCU_DVC0>, <&mstp10_clks R8A7790_CLK_SCU_DVC1>,
+			<&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>;
+		clock-names = "ssi-all",
+				"ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
+				"ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+				"src.9", "src.8", "src.7", "src.6", "src.5",
+				"src.4", "src.3", "src.2", "src.1", "src.0",
+				"dvc.0", "dvc.1",
+				"clk_a", "clk_b", "clk_c", "clk_i";
+
+		status = "disabled";
+
+		rcar_sound,dvc {
+			dvc0: dvc@0 { };
+			dvc1: dvc@1 { };
+		};
+
+		rcar_sound,src {
+			src0: src@0 { };
+			src1: src@1 { };
+			src2: src@2 { };
+			src3: src@3 { };
+			src4: src@4 { };
+			src5: src@5 { };
+			src6: src@6 { };
+			src7: src@7 { };
+			src8: src@8 { };
+			src9: src@9 { };
+		};
+
+		rcar_sound,ssi {
+			ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7790-lager.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7790-lager.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,12 +29,12 @@
 
 	memory@40000000 {
 		device_type = "memory";
-		reg = <0 0x40000000 0 0x80000000>;
+		reg = <0 0x40000000 0 0x40000000>;
 	};
 
 	memory@180000000 {
 		device_type = "memory";
-		reg = <1 0x80000000 0 0x80000000>;
+		reg = <1 0x40000000 0 0xc0000000>;
 	};
 
 	lbsc {
@@ -204,6 +204,36 @@
 				 "msiof1_tx";
 		renesas,function = "msiof1";
 	};
+
+	iic1_pins: iic1 {
+		renesas,groups = "iic1";
+		renesas,function = "iic1";
+	};
+
+	iic2_pins: iic2 {
+		renesas,groups = "iic2";
+		renesas,function = "iic2";
+	};
+
+	iic3_pins: iic3 {
+		renesas,groups = "iic3";
+		renesas,function = "iic3";
+	};
+
+	usb0_pins: usb0 {
+		renesas,groups = "usb0";
+		renesas,function = "usb0";
+	};
+
+	usb1_pins: usb1 {
+		renesas,groups = "usb1";
+		renesas,function = "usb1";
+	};
+
+	usb2_pins: usb2 {
+		renesas,groups = "usb2";
+		renesas,function = "usb2";
+	};
 };
 
 &ether {
@@ -317,3 +347,57 @@
 	cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
+
+&cpu0 {
+	cpu0-supply = <&vdd_dvfs>;
+};
+
+&iic0	{
+	status = "ok";
+};
+
+&iic1	{
+	status = "ok";
+	pinctrl-0 = <&iic1_pins>;
+	pinctrl-names = "default";
+};
+
+&iic2	{
+	status = "ok";
+	pinctrl-0 = <&iic2_pins>;
+	pinctrl-names = "default";
+};
+
+&iic3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&iic3_pins>;
+	status = "okay";
+
+	vdd_dvfs: regulator@68 {
+		compatible = "diasemi,da9210";
+		reg = <0x68>;
+
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&pci0 {
+	status = "okay";
+	pinctrl-0 = <&usb0_pins>;
+	pinctrl-names = "default";
+};
+
+&pci1 {
+	status = "okay";
+	pinctrl-0 = <&usb1_pins>;
+	pinctrl-names = "default";
+};
+
+&pci2 {
+	status = "okay";
+	pinctrl-0 = <&usb2_pins>;
+	pinctrl-names = "default";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,17 @@
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			clock-frequency = <1500000000>;
+			voltage-tolerance = <1>; /* 1% */
+			clocks = <&cpg_clocks R8A7791_CLK_Z>;
+			clock-latency = <300000>; /* 300 us */
+
+			/* kHz - uV - OPPs unknown yet */
+			operating-points = <1500000 1000000>,
+					   <1312500 1000000>,
+					   <1125000 1000000>,
+					   < 937500 1000000>,
+					   < 750000 1000000>,
+					   < 375000 1000000>;
 		};
 
 		cpu1: cpu@1 {
@@ -521,6 +532,38 @@
 			clock-output-names = "extal";
 		};
 
+		/*
+		 * The external audio clocks are configured as 0 Hz fixed frequency clocks by
+		 * default. Boards that provide audio clocks should override them.
+		 */
+		audio_clk_a: audio_clk_a {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_a";
+		};
+		audio_clk_b: audio_clk_b {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_b";
+		};
+		audio_clk_c: audio_clk_c {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "audio_clk_c";
+		};
+
+		/* External PCIe clock - can be overridden by the board */
+		pcie_bus_clk: pcie_bus_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <100000000>;
+			clock-output-names = "pcie_bus";
+			status = "disabled";
+		};
+
 		/* Special CPG clocks */
 		cpg_clocks: cpg_clocks@e6150000 {
 			compatible = "renesas,r8a7791-cpg-clocks",
@@ -743,30 +786,34 @@
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>;
 			clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>,
-				 <&mp_clk>, <&mp_clk>, <&mp_clk>;
+				 <&mp_clk>, <&mp_clk>, <&mp_clk>,
+				 <&zs_clk>, <&zs_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7791_CLK_SCIFA2 R8A7791_CLK_SCIFA1 R8A7791_CLK_SCIFA0
 				R8A7791_CLK_MSIOF2 R8A7791_CLK_SCIFB0 R8A7791_CLK_SCIFB1
 				R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2
+				R8A7791_CLK_SYS_DMAC1 R8A7791_CLK_SYS_DMAC0
 			>;
 			clock-output-names =
 				"scifa2", "scifa1", "scifa0", "msiof2", "scifb0",
-				"scifb1", "msiof1", "scifb2";
+				"scifb1", "msiof1", "scifb2",
+				"sys-dmac1", "sys-dmac0";
 		};
 		mstp3_clks: mstp3_clks@e615013c {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7791_CLK_SD0>,
-				 <&mmc0_clk>, <&hp_clk>, <&hp_clk>, <&rclk_clk>;
+				 <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0
-				R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_IIC1 R8A7791_CLK_CMT1
+				R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_PCIEC R8A7791_CLK_IIC1
+				R8A7791_CLK_SSUSB R8A7791_CLK_CMT1
 			>;
 			clock-output-names =
 				"tpu0", "sdhi2", "sdhi1", "sdhi0",
-				"mmcif0", "i2c7", "i2c8", "cmt1";
+				"mmcif0", "i2c7", "pciec", "i2c8", "ssusb", "cmt1";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -828,6 +875,39 @@
 				"rcan1", "rcan0", "qspi_mod", "i2c5", "i2c6", "i2c4", "i2c3", "i2c2",
 				"i2c1", "i2c0";
 		};
+		mstp10_clks: mstp10_clks@e6150998 {
+			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+			clocks = <&p_clk>,
+				<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				<&p_clk>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+				<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>;
+
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7791_CLK_SSI_ALL
+				R8A7791_CLK_SSI9 R8A7791_CLK_SSI8 R8A7791_CLK_SSI7 R8A7791_CLK_SSI6 R8A7791_CLK_SSI5
+				R8A7791_CLK_SSI4 R8A7791_CLK_SSI3 R8A7791_CLK_SSI2 R8A7791_CLK_SSI1 R8A7791_CLK_SSI0
+				R8A7791_CLK_SCU_ALL
+				R8A7791_CLK_SCU_DVC1 R8A7791_CLK_SCU_DVC0
+				R8A7791_CLK_SCU_SRC9 R8A7791_CLK_SCU_SRC8 R8A7791_CLK_SCU_SRC7 R8A7791_CLK_SCU_SRC6 R8A7791_CLK_SCU_SRC5
+				R8A7791_CLK_SCU_SRC4 R8A7791_CLK_SCU_SRC3 R8A7791_CLK_SCU_SRC2 R8A7791_CLK_SCU_SRC1 R8A7791_CLK_SCU_SRC0
+			>;
+			clock-output-names =
+				"ssi-all",
+				"ssi9", "ssi8", "ssi7", "ssi6", "ssi5",
+				"ssi4", "ssi3", "ssi2", "ssi1", "ssi0",
+				"scu-all",
+				"scu-dvc1", "scu-dvc0",
+				"scu-src9", "scu-src8", "scu-src7", "scu-src6", "scu-src5",
+				"scu-src4", "scu-src3", "scu-src2", "scu-src1", "scu-src0";
+		};
 		mstp11_clks: mstp11_clks@e615099c {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>;
@@ -880,4 +960,132 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	pci0: pci@ee090000 {
+		compatible = "renesas,pci-r8a7791";
+		device_type = "pci";
+		clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
+		reg = <0 0xee090000 0 0xc00>,
+		      <0 0xee080000 0 0x1100>;
+		interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		bus-range = <0 0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		ranges = <0x02000000 0 0xee080000 0 0xee080000 0 0x00010000>;
+		interrupt-map-mask = <0xff00 0 0 0x7>;
+		interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+				 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+				 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pci1: pci@ee0d0000 {
+		compatible = "renesas,pci-r8a7791";
+		device_type = "pci";
+		clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
+		reg = <0 0xee0d0000 0 0xc00>,
+		      <0 0xee0c0000 0 0x1100>;
+		interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		bus-range = <1 1>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		ranges = <0x02000000 0 0xee0c0000 0 0xee0c0000 0 0x00010000>;
+		interrupt-map-mask = <0xff00 0 0 0x7>;
+		interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+				 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+				 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pciec: pcie@fe000000 {
+		compatible = "renesas,pcie-r8a7791";
+		reg = <0 0xfe000000 0 0x80000>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x00 0xff>;
+		device_type = "pci";
+		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+		/* Map all possible DDR as inbound ranges */
+		dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000
+			      0x43000000 2 0x00000000 2 0x00000000 1 0x00000000>;
+		interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 118 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_PCIEC>, <&pcie_bus_clk>;
+		clock-names = "pcie", "pcie_bus";
+		status = "disabled";
+	};
+
+	rcar_sound: rcar_sound@0xec500000 {
+		#sound-dai-cells = <1>;
+		compatible =  "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
+		interrupt-parent = <&gic>;
+		reg =	<0 0xec500000 0 0x1000>, /* SCU */
+			<0 0xec5a0000 0 0x100>,  /* ADG */
+			<0 0xec540000 0 0x1000>, /* SSIU */
+			<0 0xec541000 0 0x1280>; /* SSI */
+		clocks = <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+			<&mstp10_clks R8A7791_CLK_SSI9>, <&mstp10_clks R8A7791_CLK_SSI8>,
+			<&mstp10_clks R8A7791_CLK_SSI7>, <&mstp10_clks R8A7791_CLK_SSI6>,
+			<&mstp10_clks R8A7791_CLK_SSI5>, <&mstp10_clks R8A7791_CLK_SSI4>,
+			<&mstp10_clks R8A7791_CLK_SSI3>, <&mstp10_clks R8A7791_CLK_SSI2>,
+			<&mstp10_clks R8A7791_CLK_SSI1>, <&mstp10_clks R8A7791_CLK_SSI0>,
+			<&mstp10_clks R8A7791_CLK_SCU_SRC9>, <&mstp10_clks R8A7791_CLK_SCU_SRC8>,
+			<&mstp10_clks R8A7791_CLK_SCU_SRC7>, <&mstp10_clks R8A7791_CLK_SCU_SRC6>,
+			<&mstp10_clks R8A7791_CLK_SCU_SRC5>, <&mstp10_clks R8A7791_CLK_SCU_SRC4>,
+			<&mstp10_clks R8A7791_CLK_SCU_SRC3>, <&mstp10_clks R8A7791_CLK_SCU_SRC2>,
+			<&mstp10_clks R8A7791_CLK_SCU_SRC1>, <&mstp10_clks R8A7791_CLK_SCU_SRC0>,
+			<&mstp10_clks R8A7791_CLK_SCU_DVC0>, <&mstp10_clks R8A7791_CLK_SCU_DVC1>,
+			<&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>;
+		clock-names = "ssi-all",
+				"ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
+				"ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+				"src.9", "src.8", "src.7", "src.6", "src.5",
+				"src.4", "src.3", "src.2", "src.1", "src.0",
+				"dvc.0", "dvc.1",
+				"clk_a", "clk_b", "clk_c", "clk_i";
+
+		status = "disabled";
+
+		rcar_sound,dvc {
+			dvc0: dvc@0 { };
+			dvc1: dvc@1 { };
+		};
+
+		rcar_sound,src {
+			src0: src@0 { };
+			src1: src@1 { };
+			src2: src@2 { };
+			src3: src@3 { };
+			src4: src@4 { };
+			src5: src@5 { };
+			src6: src@6 { };
+			src7: src@7 { };
+			src8: src@8 { };
+			src9: src@9 { };
+		};
+
+		rcar_sound,ssi {
+			ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791-henninger.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791-henninger.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791-henninger.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791-henninger.dts	2014-09-28 17:29:07.000000000 -0400
@@ -110,6 +110,11 @@
 		renesas,function = "sdhi2";
 	};
 
+	i2c2_pins: i2c2 {
+		renesas,groups = "i2c2";
+		renesas,function = "i2c2";
+	};
+
 	qspi_pins: spi0 {
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
@@ -120,6 +125,16 @@
 				 "msiof0_tx";
 		renesas,function = "msiof0";
 	};
+
+	usb0_pins: usb0 {
+		renesas,groups = "usb0";
+		renesas,function = "usb0";
+	};
+
+	usb1_pins: usb1 {
+		renesas,groups = "usb1";
+		renesas,function = "usb1";
+	};
 };
 
 &scif0 {
@@ -146,7 +161,7 @@
 };
 
 &sata0 {
-       status = "okay";
+	status = "okay";
 };
 
 &sdhi0 {
@@ -170,6 +185,14 @@
 	status = "okay";
 };
 
+&i2c2 {
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+	clock-frequency = <400000>;
+};
+
 &qspi {
 	pinctrl-0 = <&qspi_pins>;
 	pinctrl-names = "default";
@@ -217,3 +240,23 @@
 		spi-cpha;
 	};
 };
+
+&pci0 {
+	status = "okay";
+	pinctrl-0 = <&usb0_pins>;
+	pinctrl-names = "default";
+};
+
+&pci1 {
+	status = "okay";
+	pinctrl-0 = <&usb1_pins>;
+	pinctrl-names = "default";
+};
+
+&pcie_bus_clk {
+	status = "okay";
+};
+
+&pciec {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2014-09-28 17:29:07.000000000 -0400
@@ -215,25 +215,6 @@
 	clock-frequency = <20000000>;
 };
 
-&i2c2 {
-	pinctrl-0 = <&i2c2_pins>;
-	pinctrl-names = "default";
-
-	status = "okay";
-	clock-frequency = <400000>;
-
-	eeprom@50 {
-		compatible = "renesas,24c02";
-		reg = <0x50>;
-		pagesize = <16>;
-	};
-};
-
-&i2c6 {
-	status = "okay";
-	clock-frequency = <100000>;
-};
-
 &pfc {
 	pinctrl-0 = <&du_pins>;
 	pinctrl-names = "default";
@@ -293,6 +274,16 @@
 				 "msiof0_tx";
 		renesas,function = "msiof0";
 	};
+
+	usb0_pins: usb0 {
+		renesas,groups = "usb0";
+		renesas,function = "usb0";
+	};
+
+	usb1_pins: usb1 {
+		renesas,groups = "usb1";
+		renesas,function = "usb1";
+	};
 };
 
 &ether {
@@ -408,3 +399,56 @@
 		spi-cpha;
 	};
 };
+
+&i2c2 {
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	eeprom@50 {
+		compatible = "renesas,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+};
+
+&i2c6 {
+	status = "okay";
+	clock-frequency = <100000>;
+
+	vdd_dvfs: regulator@68 {
+		compatible = "diasemi,da9210";
+		reg = <0x68>;
+
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&pci0 {
+	status = "okay";
+	pinctrl-0 = <&usb0_pins>;
+	pinctrl-names = "default";
+};
+
+&pci1 {
+	status = "okay";
+	pinctrl-0 = <&usb1_pins>;
+	pinctrl-names = "default";
+};
+
+&pcie_bus_clk {
+	status = "okay";
+};
+
+&pciec {
+	status = "okay";
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_dvfs>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -24,87 +24,173 @@
 		reg = <0x60000000 0x40000000>;
 	};
 
-	soc {
-		uart0: serial@10124000 {
-			status = "okay";
-		};
+	vcc_sd0: fixed-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "sdmmc-supply";
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+		gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
 
-		uart1: serial@10126000 {
-			status = "okay";
-		};
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
 
-		uart2: serial@20064000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&uart2_xfer>;
-			status = "okay";
+		button@0 {
+			gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
+			linux,code = <116>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			gpio-key,wakeup = <1>;
+			debounce-interval = <100>;
 		};
-
-		uart3: serial@20068000 {
-			status = "okay";
+		button@1 {
+			gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
+			linux,code = <104>;
+			label = "GPIO Key Vol-";
+			linux,input-type = <1>;
+			gpio-key,wakeup = <0>;
+			debounce-interval = <100>;
 		};
+		/* VOL+ comes somehow thru the ADC */
+	};
+};
 
-		vcc_sd0: fixed-regulator {
-			compatible = "regulator-fixed";
-			regulator-name = "sdmmc-supply";
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
-			startup-delay-us = <100000>;
-		};
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
 
-		dwmmc@10214000 { /* sdmmc */
-			num-slots = <1>;
-			status = "okay";
+	tps: tps@2d {
+		reg = <0x2d>;
 
-			pinctrl-names = "default";
-			pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
-			vmmc-supply = <&vcc_sd0>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
 
-			slot@0 {
-				reg = <0>;
-				bus-width = <4>;
-				disable-wp;
+		vcc5-supply = <&vcc_io>;
+		vcc6-supply = <&vcc_io>;
+
+		regulators {
+			vcc_rtc: regulator@0 {
+				regulator-name = "vcc_rtc";
+				regulator-always-on;
 			};
-		};
 
-		dwmmc@10218000 { /* wifi */
-			num-slots = <1>;
-			status = "okay";
-			non-removable;
+			vcc_io: regulator@1 {
+				regulator-name = "vcc_io";
+				regulator-always-on;
+			};
 
-			pinctrl-names = "default";
-			pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+			vdd_arm: regulator@2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
 
-			slot@0 {
-				reg = <0>;
-				bus-width = <4>;
-				disable-wp;
+			vcc_ddr: regulator@3 {
+				regulator-name = "vcc_ddr";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
 			};
-		};
 
-		gpio-keys {
-			compatible = "gpio-keys";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			autorepeat;
+			vcc18_cif: regulator@5 {
+				regulator-name = "vcc18_cif";
+				regulator-always-on;
+			};
 
-			button@0 {
-				gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
-				linux,code = <116>;
-				label = "GPIO Key Power";
-				linux,input-type = <1>;
-				gpio-key,wakeup = <1>;
-				debounce-interval = <100>;
+			vdd_11: regulator@6 {
+				regulator-name = "vdd_11";
+				regulator-always-on;
 			};
-			button@1 {
-				gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
-				linux,code = <104>;
-				label = "GPIO Key Vol-";
-				linux,input-type = <1>;
-				gpio-key,wakeup = <0>;
-				debounce-interval = <100>;
+
+			vcc_25: regulator@7 {
+				regulator-name = "vcc_25";
+				regulator-always-on;
+			};
+
+			vcc_18: regulator@8 {
+				regulator-name = "vcc_18";
+				regulator-always-on;
+			};
+
+			vcc25_hdmi: regulator@9 {
+				regulator-name = "vcc25_hdmi";
+				regulator-always-on;
+			};
+
+			vcca_33: regulator@10 {
+				regulator-name = "vcca_33";
+				regulator-always-on;
+			};
+
+			vcc_tp: regulator@11 {
+				regulator-name = "vcc_tp";
+				regulator-always-on;
+			};
+
+			vcc28_cif: regulator@12 {
+				regulator-name = "vcc28_cif";
+				regulator-always-on;
 			};
-			/* VOL+ comes somehow thru the ADC */
 		};
 	};
 };
+
+/* must be included after &tps gets defined */
+#include "tps65910.dtsi"
+
+&mmc0 { /* sdmmc */
+	num-slots = <1>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	vmmc-supply = <&vcc_sd0>;
+
+	slot@0 {
+		reg = <0>;
+		bus-width = <4>;
+		disable-wp;
+	};
+};
+
+&mmc1 { /* wifi */
+	num-slots = <1>;
+	status = "okay";
+	non-removable;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+
+	slot@0 {
+		reg = <0>;
+		bus-width = <4>;
+		disable-wp;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2013 MundoReader S.L.
- * Author: Heiko Stuebner <heiko@sntech.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.
- */
-
-/ {
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		/*
-		 * This is a dummy clock, to be used as placeholder on
-		 * other mux clocks when a specific parent clock is not
-		 * yet implemented. It should be dropped when the driver
-		 * is complete.
-		 */
-		dummy: dummy {
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-			#clock-cells = <0>;
-		};
-
-		xin24m: xin24m {
-			compatible = "fixed-clock";
-			clock-frequency = <24000000>;
-			#clock-cells = <0>;
-		};
-
-		dummy48m: dummy48m {
-			compatible = "fixed-clock";
-			clock-frequency = <48000000>;
-			#clock-cells = <0>;
-		};
-
-		dummy150m: dummy150m {
-			compatible = "fixed-clock";
-			clock-frequency = <150000000>;
-			#clock-cells = <0>;
-		};
-
-		clk_gates0: gate-clk@200000d0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d0 0x4>;
-			clocks = <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_core_periph", "gate_cpu_gpll",
-				"gate_ddrphy", "gate_aclk_cpu",
-				"gate_hclk_cpu", "gate_pclk_cpu",
-				"gate_atclk_cpu", "gate_i2s0",
-				"gate_i2s0_frac", "gate_i2s1",
-				"gate_i2s1_frac", "gate_i2s2",
-				"gate_i2s2_frac", "gate_spdif",
-				"gate_spdif_frac", "gate_testclk";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates1: gate-clk@200000d4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d4 0x4>;
-			clocks = <&xin24m>, <&xin24m>,
-				 <&xin24m>, <&dummy>,
-				 <&dummy>, <&xin24m>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>;
-
-			clock-output-names =
-				"gate_timer0", "gate_timer1",
-				"gate_timer2", "gate_jtag",
-				"gate_aclk_lcdc1_src", "gate_otgphy0",
-				"gate_otgphy1", "gate_ddr_gpll",
-				"gate_uart0", "gate_frac_uart0",
-				"gate_uart1", "gate_frac_uart1",
-				"gate_uart2", "gate_frac_uart2",
-				"gate_uart3", "gate_frac_uart3";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates2: gate-clk@200000d8 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d8 0x4>;
-			clocks = <&clk_gates2 1>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&clk_gates2 3>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy48m>,
-				 <&dummy>, <&dummy48m>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_periph_src", "gate_aclk_periph",
-				"gate_hclk_periph", "gate_pclk_periph",
-				"gate_smc", "gate_mac",
-				"gate_hsadc", "gate_hsadc_frac",
-				"gate_saradc", "gate_spi0",
-				"gate_spi1", "gate_mmc0",
-				"gate_mac_lbtest", "gate_mmc1",
-				"gate_emmc", "gate_tsadc";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates3: gate-clk@200000dc {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000dc 0x4>;
-			clocks = <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
-				"gate_dclk_lcdc1", "gate_pclkin_cif0",
-				"gate_pclkin_cif1", "reserved",
-				"reserved", "gate_cif0_out",
-				"gate_cif1_out", "gate_aclk_vepu",
-				"gate_hclk_vepu", "gate_aclk_vdpu",
-				"gate_hclk_vdpu", "gate_gpu_src",
-				"reserved", "gate_xin27m";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates4: gate-clk@200000e0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e0 0x4>;
-			clocks = <&clk_gates2 2>, <&clk_gates2 3>,
-				 <&clk_gates2 1>, <&clk_gates2 1>,
-				 <&clk_gates2 1>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates2 2>,
-				 <&clk_gates0 4>, <&clk_gates0 4>,
-				 <&clk_gates0 3>, <&clk_gates0 3>,
-				 <&clk_gates0 3>, <&clk_gates2 3>,
-				 <&clk_gates0 4>;
-
-			clock-output-names =
-				"gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
-				"gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
-				"gate_aclk_pei_niu", "gate_hclk_usb_peri",
-				"gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
-				"gate_hclk_cpubus", "gate_hclk_ahb2apb",
-				"gate_aclk_strc_sys", "gate_aclk_l2mem_con",
-				"gate_aclk_intmem", "gate_pclk_tsadc",
-				"gate_hclk_hdmi";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates5: gate-clk@200000e4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e4 0x4>;
-			clocks = <&clk_gates0 3>, <&clk_gates2 1>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates0 4>, <&clk_gates0 5>,
-				 <&clk_gates2 1>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates4 5>,
-				 <&clk_gates4 5>, <&dummy>;
-
-			clock-output-names =
-				"gate_aclk_dmac1", "gate_aclk_dmac2",
-				"gate_pclk_efuse", "gate_pclk_tzpc",
-				"gate_pclk_grf", "gate_pclk_pmu",
-				"gate_hclk_rom", "gate_pclk_ddrupctl",
-				"gate_aclk_smc", "gate_hclk_nandc",
-				"gate_hclk_mmc0", "gate_hclk_mmc1",
-				"gate_hclk_emmc", "gate_hclk_otg0",
-				"gate_hclk_otg1", "gate_aclk_gpu";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates6: gate-clk@200000e8 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e8 0x4>;
-			clocks = <&clk_gates3 0>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates1 4>,
-				 <&clk_gates0 4>, <&clk_gates3 0>,
-				 <&clk_gates0 4>, <&clk_gates1 4>,
-				 <&clk_gates3 0>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates1 4>,
-				 <&clk_gates0 4>, <&clk_gates3 0>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_aclk_lcdc0", "gate_hclk_lcdc0",
-				"gate_hclk_lcdc1", "gate_aclk_lcdc1",
-				"gate_hclk_cif0", "gate_aclk_cif0",
-				"gate_hclk_cif1", "gate_aclk_cif1",
-				"gate_aclk_ipp", "gate_hclk_ipp",
-				"gate_hclk_rga", "gate_aclk_rga",
-				"gate_hclk_vio_bus", "gate_aclk_vio0",
-				"gate_aclk_vcodec", "gate_shclk_vio_h2h";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates7: gate-clk@200000ec {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000ec 0x4>;
-			clocks = <&clk_gates2 2>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates2 3>;
-
-			clock-output-names =
-				"gate_hclk_emac", "gate_hclk_spdif",
-				"gate_hclk_i2s0_2ch", "gate_hclk_i2s1_2ch",
-				"gate_hclk_i2s_8ch", "gate_hclk_hsadc",
-				"gate_hclk_pidf", "gate_pclk_timer0",
-				"gate_pclk_timer1", "gate_pclk_timer2",
-				"gate_pclk_pwm01", "gate_pclk_pwm23",
-				"gate_pclk_spi0", "gate_pclk_spi1",
-				"gate_pclk_saradc", "gate_pclk_wdt";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates8: gate-clk@200000f0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000f0 0x4>;
-			clocks = <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&dummy>, <&clk_gates0 5>;
-
-			clock-output-names =
-				"gate_pclk_uart0", "gate_pclk_uart1",
-				"gate_pclk_uart2", "gate_pclk_uart3",
-				"gate_pclk_i2c0", "gate_pclk_i2c1",
-				"gate_pclk_i2c2", "gate_pclk_i2c3",
-				"gate_pclk_i2c4", "gate_pclk_gpio0",
-				"gate_pclk_gpio1", "gate_pclk_gpio2",
-				"gate_pclk_gpio3", "gate_pclk_gpio4",
-				"reserved", "gate_pclk_gpio6";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates9: gate-clk@200000f4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000f4 0x4>;
-			clocks = <&dummy>, <&clk_gates0 5>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&clk_gates1 4>,
-				 <&clk_gates0 5>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>;
-
-			clock-output-names =
-				"gate_clk_core_dbg", "gate_pclk_dbg",
-				"gate_clk_trace", "gate_atclk",
-				"gate_clk_l2c", "gate_aclk_vio1",
-				"gate_pclk_publ", "gate_aclk_intmem0",
-				"gate_aclk_intmem1", "gate_aclk_intmem2",
-				"gate_aclk_intmem3";
-
-			#clock-cells = <1>;
-		};
-	};
-
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3066a.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3066a.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,8 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3066a-cru.h>
 #include "rk3xxx.dtsi"
-#include "rk3066a-clocks.dtsi"
 
 / {
 	compatible = "rockchip,rk3066a";
@@ -40,247 +40,392 @@
 		};
 	};
 
-	soc {
-		timer@20038000 {
-			compatible = "snps,dw-apb-timer-osc";
-			reg = <0x20038000 0x100>;
-			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clk_gates1 0>, <&clk_gates7 7>;
-			clock-names = "timer", "pclk";
-		};
+	sram: sram@10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x10000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x10080000 0x10000>;
 
-		timer@2003a000 {
-			compatible = "snps,dw-apb-timer-osc";
-			reg = <0x2003a000 0x100>;
-			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clk_gates1 1>, <&clk_gates7 8>;
-			clock-names = "timer", "pclk";
+		smp-sram@0 {
+			compatible = "rockchip,rk3066-smp-sram";
+			reg = <0x0 0x50>;
 		};
+	};
 
-		timer@2000e000 {
-			compatible = "snps,dw-apb-timer-osc";
-			reg = <0x2000e000 0x100>;
-			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clk_gates1 2>, <&clk_gates7 9>;
-			clock-names = "timer", "pclk";
+	cru: clock-controller@20000000 {
+		compatible = "rockchip,rk3066a-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	timer@2000e000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x2000e000 0x100>;
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER2>, <&cru PCLK_TIMER2>;
+		clock-names = "timer", "pclk";
+	};
+
+	timer@20038000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x20038000 0x100>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER0>, <&cru PCLK_TIMER0>;
+		clock-names = "timer", "pclk";
+	};
+
+	timer@2003a000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x2003a000 0x100>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER1>, <&cru PCLK_TIMER1>;
+		clock-names = "timer", "pclk";
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3066a-pinctrl";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@20034000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20034000 0x100>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 
-		sram: sram@10080000 {
-			compatible = "mmio-sram";
-			reg = <0x10080000 0x10000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x10080000 0x10000>;
+		gpio1: gpio1@2003c000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003c000 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
 
-			smp-sram@0 {
-				compatible = "rockchip,rk3066-smp-sram";
-				reg = <0x0 0x50>;
-			};
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 
-		pinctrl@20008000 {
-			compatible = "rockchip,rk3066a-pinctrl";
-			rockchip,grf = <&grf>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
+		gpio2: gpio2@2003e000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003e000 0x100>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
 
-			gpio0: gpio0@20034000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x20034000 0x100>;
-				interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 9>;
+			gpio-controller;
+			#gpio-cells = <2>;
 
-				gpio-controller;
-				#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+		gpio3: gpio3@20080000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20080000 0x100>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
 
-			gpio1: gpio1@2003c000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x2003c000 0x100>;
-				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 10>;
+			gpio-controller;
+			#gpio-cells = <2>;
 
-				gpio-controller;
-				#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+		gpio4: gpio4@20084000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20084000 0x100>;
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO4>;
 
-			gpio2: gpio2@2003e000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x2003e000 0x100>;
-				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 11>;
+			gpio-controller;
+			#gpio-cells = <2>;
 
-				gpio-controller;
-				#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+		gpio6: gpio6@2000a000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2000a000 0x100>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO6>;
 
-			gpio3: gpio3@20080000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x20080000 0x100>;
-				interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 12>;
+			gpio-controller;
+			#gpio-cells = <2>;
 
-				gpio-controller;
-				#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+		pcfg_pull_default: pcfg_pull_default {
+			bias-pull-pin-default;
+		};
+
+		pcfg_pull_none: pcfg_pull_none {
+			bias-disable;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <RK_GPIO2 28 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO2 29 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			gpio4: gpio4@20084000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x20084000 0x100>;
-				interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 13>;
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <RK_GPIO2 30 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO2 31 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <RK_GPIO3 0 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <RK_GPIO3 2 RK_FUNC_2 &pcfg_pull_none>,
+						<RK_GPIO3 3 RK_FUNC_2 &pcfg_pull_none>;
 			};
+		};
 
-			gpio6: gpio6@2000a000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x2000a000 0x100>;
-				interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 15>;
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		pwm0 {
+			pwm0_out: pwm0-out {
+				rockchip,pins = <RK_GPIO0 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+		pwm1 {
+			pwm1_out: pwm1-out {
+				rockchip,pins = <RK_GPIO0 4 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			pcfg_pull_default: pcfg_pull_default {
-				bias-pull-pin-default;
+		pwm2 {
+			pwm2_out: pwm2-out {
+				rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			pcfg_pull_none: pcfg_pull_none {
-				bias-disable;
+		pwm3 {
+			pwm3_out: pwm3-out {
+				rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			uart0 {
-				uart0_xfer: uart0-xfer {
-					rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
-				};
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart0_cts: uart0-cts {
-					rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart0_cts: uart0-cts {
+				rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart0_rts: uart0-rts {
-					rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart0_rts: uart0-rts {
+				rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
 			};
+		};
 
-			uart1 {
-				uart1_xfer: uart1-xfer {
-					rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
-				};
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart1_cts: uart1-cts {
-					rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart1_cts: uart1-cts {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart1_rts: uart1-rts {
-					rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart1_rts: uart1-rts {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
 			};
+		};
 
-			uart2 {
-				uart2_xfer: uart2-xfer {
-					rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
-				};
-				/* no rts / cts for uart2 */
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
 			};
+			/* no rts / cts for uart2 */
+		};
 
-			uart3 {
-				uart3_xfer: uart3-xfer {
-					rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
-				};
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart3_cts: uart3-cts {
-					rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart3_cts: uart3-cts {
+				rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				uart3_rts: uart3-rts {
-					rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			uart3_rts: uart3-rts {
+				rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
 			};
+		};
 
-			sd0 {
-				sd0_clk: sd0-clk {
-					rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
-				};
+		sd0 {
+			sd0_clk: sd0-clk {
+				rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd0_cmd: sd0-cmd {
-					rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd0_cmd: sd0-cmd {
+				rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd0_cd: sd0-cd {
-					rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd0_cd: sd0-cd {
+				rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd0_wp: sd0-wp {
-					rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd0_wp: sd0-wp {
+				rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd0_bus1: sd0-bus-width1 {
-					rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd0_bus1: sd0-bus-width1 {
+				rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd0_bus4: sd0-bus-width4 {
-					rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd0_bus4: sd0-bus-width4 {
+				rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
 			};
+		};
 
-			sd1 {
-				sd1_clk: sd1-clk {
-					rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
-				};
+		sd1 {
+			sd1_clk: sd1-clk {
+				rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd1_cmd: sd1-cmd {
-					rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd1_cmd: sd1-cmd {
+				rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd1_cd: sd1-cd {
-					rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd1_cd: sd1-cd {
+				rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd1_wp: sd1-wp {
-					rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd1_wp: sd1-wp {
+				rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd1_bus1: sd1-bus-width1 {
-					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd1_bus1: sd1-bus-width1 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
+			};
 
-				sd1_bus4: sd1-bus-width4 {
-					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
-							<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
-				};
+			sd1_bus4: sd1-bus-width4 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
 			};
 		};
 	};
 };
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_xfer>;
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
+};
+
+&pwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_out>;
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm1_out>;
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm2_out>;
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm3_out>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+	compatible = "rockchip,rk3066-wdt", "snps,dw-wdt";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188-clocks.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188-clocks.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188-clocks.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2013 MundoReader S.L.
- * Author: Heiko Stuebner <heiko@sntech.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.
- */
-
-/ {
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		/*
-		 * This is a dummy clock, to be used as placeholder on
-		 * other mux clocks when a specific parent clock is not
-		 * yet implemented. It should be dropped when the driver
-		 * is complete.
-		 */
-		dummy: dummy {
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-			#clock-cells = <0>;
-		};
-
-		xin24m: xin24m {
-			compatible = "fixed-clock";
-			clock-frequency = <24000000>;
-			#clock-cells = <0>;
-		};
-
-		dummy48m: dummy48m {
-			compatible = "fixed-clock";
-			clock-frequency = <48000000>;
-			#clock-cells = <0>;
-		};
-
-		dummy150m: dummy150m {
-			compatible = "fixed-clock";
-			clock-frequency = <150000000>;
-			#clock-cells = <0>;
-		};
-
-		clk_gates0: gate-clk@200000d0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d0 0x4>;
-			clocks = <&dummy150m>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_core_periph", "gate_cpu_gpll",
-				"gate_ddrphy", "gate_aclk_cpu",
-				"gate_hclk_cpu", "gate_pclk_cpu",
-				"gate_atclk_cpu", "gate_aclk_core",
-				"reserved", "gate_i2s0",
-				"gate_i2s0_frac", "reserved",
-				"reserved", "gate_spdif",
-				"gate_spdif_frac", "gate_testclk";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates1: gate-clk@200000d4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d4 0x4>;
-			clocks = <&xin24m>, <&xin24m>,
-				 <&xin24m>, <&dummy>,
-				 <&dummy>, <&xin24m>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&xin24m>, <&dummy>;
-
-			clock-output-names =
-				"gate_timer0", "gate_timer1",
-				"gate_timer3", "gate_jtag",
-				"gate_aclk_lcdc1_src", "gate_otgphy0",
-				"gate_otgphy1", "gate_ddr_gpll",
-				"gate_uart0", "gate_frac_uart0",
-				"gate_uart1", "gate_frac_uart1",
-				"gate_uart2", "gate_frac_uart2",
-				"gate_uart3", "gate_frac_uart3";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates2: gate-clk@200000d8 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000d8 0x4>;
-			clocks = <&clk_gates2 1>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&clk_gates2 3>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy48m>,
-				 <&dummy>, <&dummy48m>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_periph_src", "gate_aclk_periph",
-				"gate_hclk_periph", "gate_pclk_periph",
-				"gate_smc", "gate_mac",
-				"gate_hsadc", "gate_hsadc_frac",
-				"gate_saradc", "gate_spi0",
-				"gate_spi1", "gate_mmc0",
-				"gate_mac_lbtest", "gate_mmc1",
-				"gate_emmc", "reserved";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates3: gate-clk@200000dc {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000dc 0x4>;
-			clocks = <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&xin24m>, <&xin24m>,
-				 <&dummy>, <&dummy>,
-				 <&xin24m>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&xin24m>, <&dummy>;
-
-			clock-output-names =
-				"gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
-				"gate_dclk_lcdc1", "gate_pclkin_cif0",
-				"gate_timer2", "gate_timer4",
-				"gate_hsicphy", "gate_cif0_out",
-				"gate_timer5", "gate_aclk_vepu",
-				"gate_hclk_vepu", "gate_aclk_vdpu",
-				"gate_hclk_vdpu", "reserved",
-				"gate_timer6", "gate_aclk_gpu_src";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates4: gate-clk@200000e0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e0 0x4>;
-			clocks = <&clk_gates2 2>, <&clk_gates2 3>,
-				 <&clk_gates2 1>, <&clk_gates2 1>,
-				 <&clk_gates2 1>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates2 2>,
-				 <&clk_gates0 4>, <&clk_gates0 4>,
-				 <&clk_gates0 3>, <&dummy>,
-				 <&clk_gates0 3>, <&dummy>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
-				"gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
-				"gate_aclk_pei_niu", "gate_hclk_usb_peri",
-				"gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
-				"gate_hclk_cpubus", "gate_hclk_ahb2apb",
-				"gate_aclk_strc_sys", "reserved",
-				"gate_aclk_intmem", "reserved",
-				"gate_hclk_imem1", "gate_hclk_imem0";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates5: gate-clk@200000e4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e4 0x4>;
-			clocks = <&clk_gates0 3>, <&clk_gates2 1>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates0 4>, <&clk_gates0 5>,
-				 <&clk_gates2 1>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates4 5>;
-
-			clock-output-names =
-				"gate_aclk_dmac1", "gate_aclk_dmac2",
-				"gate_pclk_efuse", "gate_pclk_tzpc",
-				"gate_pclk_grf", "gate_pclk_pmu",
-				"gate_hclk_rom", "gate_pclk_ddrupctl",
-				"gate_aclk_smc", "gate_hclk_nandc",
-				"gate_hclk_mmc0", "gate_hclk_mmc1",
-				"gate_hclk_emmc", "gate_hclk_otg0";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates6: gate-clk@200000e8 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000e8 0x4>;
-			clocks = <&clk_gates3 0>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates1 4>,
-				 <&clk_gates0 4>, <&clk_gates3 0>,
-				 <&dummy>, <&dummy>,
-				 <&clk_gates3 0>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&clk_gates1 4>,
-				 <&clk_gates0 4>, <&clk_gates3 0>;
-
-			clock-output-names =
-				"gate_aclk_lcdc0", "gate_hclk_lcdc0",
-				"gate_hclk_lcdc1", "gate_aclk_lcdc1",
-				"gate_hclk_cif0", "gate_aclk_cif0",
-				"reserved", "reserved",
-				"gate_aclk_ipp", "gate_hclk_ipp",
-				"gate_hclk_rga", "gate_aclk_rga",
-				"gate_hclk_vio_bus", "gate_aclk_vio0";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates7: gate-clk@200000ec {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000ec 0x4>;
-			clocks = <&clk_gates2 2>, <&clk_gates0 4>,
-				 <&clk_gates0 4>, <&dummy>,
-				 <&dummy>, <&clk_gates2 2>,
-				 <&clk_gates2 2>, <&clk_gates0 5>,
-				 <&dummy>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates2 3>;
-
-			clock-output-names =
-				"gate_hclk_emac", "gate_hclk_spdif",
-				"gate_hclk_i2s0_2ch", "gate_hclk_otg1",
-				"gate_hclk_hsic", "gate_hclk_hsadc",
-				"gate_hclk_pidf", "gate_pclk_timer0",
-				"reserved", "gate_pclk_timer2",
-				"gate_pclk_pwm01", "gate_pclk_pwm23",
-				"gate_pclk_spi0", "gate_pclk_spi1",
-				"gate_pclk_saradc", "gate_pclk_wdt";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates8: gate-clk@200000f0 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000f0 0x4>;
-			clocks = <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&clk_gates2 3>,
-				 <&clk_gates2 3>, <&clk_gates0 5>,
-				 <&clk_gates0 5>, <&clk_gates0 5>,
-				 <&clk_gates2 3>, <&dummy>;
-
-			clock-output-names =
-				"gate_pclk_uart0", "gate_pclk_uart1",
-				"gate_pclk_uart2", "gate_pclk_uart3",
-				"gate_pclk_i2c0", "gate_pclk_i2c1",
-				"gate_pclk_i2c2", "gate_pclk_i2c3",
-				"gate_pclk_i2c4", "gate_pclk_gpio0",
-				"gate_pclk_gpio1", "gate_pclk_gpio2",
-				"gate_pclk_gpio3", "gate_aclk_gps";
-
-			#clock-cells = <1>;
-		};
-
-		clk_gates9: gate-clk@200000f4 {
-			compatible = "rockchip,rk2928-gate-clk";
-			reg = <0x200000f4 0x4>;
-			clocks = <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>,
-				 <&dummy>, <&dummy>;
-
-			clock-output-names =
-				"gate_clk_core_dbg", "gate_pclk_dbg",
-				"gate_clk_trace", "gate_atclk",
-				"gate_clk_l2c", "gate_aclk_vio1",
-				"gate_pclk_publ", "gate_aclk_gpu";
-
-			#clock-cells = <1>;
-		};
-	};
-
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,8 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3188-cru.h>
 #include "rk3xxx.dtsi"
-#include "rk3188-clocks.dtsi"
 
 / {
 	compatible = "rockchip,rk3188";
@@ -52,215 +52,355 @@
 		};
 	};
 
-	soc {
-		global-timer@1013c200 {
-			interrupts = <GIC_PPI 11 0xf04>;
+	sram: sram@10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x8000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x10080000 0x8000>;
+
+		smp-sram@0 {
+			compatible = "rockchip,rk3066-smp-sram";
+			reg = <0x0 0x50>;
 		};
+	};
 
-		local-timer@1013c600 {
-			interrupts = <GIC_PPI 13 0xf04>;
+	cru: clock-controller@20000000 {
+		compatible = "rockchip,rk3188-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3188-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmu>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@0x2000a000 {
+			compatible = "rockchip,rk3188-gpio-bank0";
+			reg = <0x2000a000 0x100>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 
-		sram: sram@10080000 {
-			compatible = "mmio-sram";
-			reg = <0x10080000 0x8000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x10080000 0x8000>;
+		gpio1: gpio1@0x2003c000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003c000 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
 
-			smp-sram@0 {
-				compatible = "rockchip,rk3066-smp-sram";
-				reg = <0x0 0x50>;
-			};
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 
-		pinctrl@20008000 {
-			compatible = "rockchip,rk3188-pinctrl";
-			rockchip,grf = <&grf>;
-			rockchip,pmu = <&pmu>;
+		gpio2: gpio2@2003e000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003e000 0x100>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
 
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
+			gpio-controller;
+			#gpio-cells = <2>;
 
-			gpio0: gpio0@0x2000a000 {
-				compatible = "rockchip,rk3188-gpio-bank0";
-				reg = <0x2000a000 0x100>;
-				interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 9>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		gpio3: gpio3@20080000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20080000 0x100>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			gpio-controller;
+			#gpio-cells = <2>;
 
-			gpio1: gpio1@0x2003c000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x2003c000 0x100>;
-				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 10>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		pcfg_pull_up: pcfg_pull_up {
+			bias-pull-up;
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+		pcfg_pull_down: pcfg_pull_down {
+			bias-pull-down;
+		};
 
-			gpio2: gpio2@2003e000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x2003e000 0x100>;
-				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 11>;
+		pcfg_pull_none: pcfg_pull_none {
+			bias-disable;
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <RK_GPIO1 24 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 25 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <RK_GPIO1 26 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 27 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			gpio3: gpio3@20080000 {
-				compatible = "rockchip,gpio-bank";
-				reg = <0x20080000 0x100>;
-				interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk_gates8 12>;
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <RK_GPIO1 28 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 29 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				gpio-controller;
-				#gpio-cells = <2>;
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <RK_GPIO3 14 RK_FUNC_2 &pcfg_pull_none>,
+						<RK_GPIO3 15 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <RK_GPIO1 30 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 31 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			pcfg_pull_up: pcfg_pull_up {
-				bias-pull-up;
+		pwm0 {
+			pwm0_out: pwm0-out {
+				rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			pcfg_pull_down: pcfg_pull_down {
-				bias-pull-down;
+		pwm1 {
+			pwm1_out: pwm1-out {
+				rockchip,pins = <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			pcfg_pull_none: pcfg_pull_none {
-				bias-disable;
+		pwm2 {
+			pwm2_out: pwm2-out {
+				rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			uart0 {
-				uart0_xfer: uart0-xfer {
-					rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
-							<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		pwm3 {
+			pwm3_out: pwm3-out {
+				rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				uart0_cts: uart0-cts {
-					rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				uart0_rts: uart0-rts {
-					rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			uart0_cts: uart0-cts {
+				rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
-			uart1 {
-				uart1_xfer: uart1-xfer {
-					rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
-							<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			uart0_rts: uart0-rts {
+				rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				uart1_cts: uart1-cts {
-					rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				uart1_rts: uart1-rts {
-					rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			uart1_cts: uart1-cts {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
-			uart2 {
-				uart2_xfer: uart2-xfer {
-					rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
-							<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
-				};
-				/* no rts / cts for uart2 */
+			uart1_rts: uart1-rts {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
 			};
+		};
 
-			uart3 {
-				uart3_xfer: uart3-xfer {
-					rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
-							<RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart2 */
+		};
 
-				uart3_cts: uart3-cts {
-					rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				uart3_rts: uart3-rts {
-					rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			uart3_cts: uart3-cts {
+				rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
-			sd0 {
-				sd0_clk: sd0-clk {
-					rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			uart3_rts: uart3-rts {
+				rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				sd0_cmd: sd0-cmd {
-					rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		sd0 {
+			sd0_clk: sd0-clk {
+				rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd0_cd: sd0-cd {
-					rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_cmd: sd0-cmd {
+				rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd0_wp: sd0-wp {
-					rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_cd: sd0-cd {
+				rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd0_pwr: sd0-pwr {
-					rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_wp: sd0-wp {
+				rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd0_bus1: sd0-bus-width1 {
-					rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_pwr: sd0-pwr {
+				rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd0_bus4: sd0-bus-width4 {
-					rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_bus1: sd0-bus-width1 {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
-			sd1 {
-				sd1_clk: sd1-clk {
-					rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd0_bus4: sd0-bus-width4 {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
 
-				sd1_cmd: sd1-cmd {
-					rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
-				};
+		sd1 {
+			sd1_clk: sd1-clk {
+				rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd1_cd: sd1-cd {
-					rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd1_cmd: sd1-cmd {
+				rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd1_wp: sd1-wp {
-					rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd1_cd: sd1-cd {
+				rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd1_bus1: sd1-bus-width1 {
-					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd1_wp: sd1-wp {
+				rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
+			};
 
-				sd1_bus4: sd1-bus-width4 {
-					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
-							<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
-				};
+			sd1_bus1: sd1-bus-width1 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_bus4: sd1-bus-width4 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 	};
 };
+
+&global_timer {
+	interrupts = <GIC_PPI 11 0xf04>;
+};
+
+&local_timer {
+	interrupts = <GIC_PPI 13 0xf04>;
+};
+
+&i2c0 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_xfer>;
+};
+
+&pwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_out>;
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm1_out>;
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm2_out>;
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm3_out>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+	compatible = "rockchip,rk3188-wdt", "snps,dw-wdt";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188-radxarock.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188-radxarock.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2014-09-28 17:29:07.000000000 -0400
@@ -23,59 +23,207 @@
 		reg = <0x60000000 0x80000000>;
 	};
 
-	soc {
-		uart0: serial@10124000 {
-			status = "okay";
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+
+		button@0 {
+			gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+			linux,code = <116>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			gpio-key,wakeup = <1>;
+			debounce-interval = <100>;
 		};
+	};
 
-		uart1: serial@10126000 {
-			status = "okay";
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+			default-state = "off";
 		};
 
-		uart2: serial@20064000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&uart2_xfer>;
-			status = "okay";
+		yellow {
+			gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+			default-state = "off";
 		};
 
-		uart3: serial@20068000 {
-			status = "okay";
+		sleep {
+			gpios = <&gpio0 15 0>;
+			default-state = "off";
 		};
+	};
 
-		gpio-keys {
-			compatible = "gpio-keys";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			autorepeat;
+	ir_recv: gpio-ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio0 10 1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_recv_pin>;
+	};
 
-			button@0 {
-				gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
-				linux,code = <116>;
-				label = "GPIO Key Power";
-				linux,input-type = <1>;
-				gpio-key,wakeup = <1>;
-				debounce-interval = <100>;
+	vcc_sd0: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "sdmmc-supply";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio3 1 GPIO_ACTIVE_LOW>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	act8846: act8846@5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		status = "okay";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&act8846_dvs0_ctl>;
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "VCC_DDR";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
 			};
-		};
 
-		gpio-leds {
-			compatible = "gpio-leds";
+			vdd_log: REG2 {
+				regulator-name = "VDD_LOG";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
 
-			green {
-				gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
-				default-state = "off";
+			vdd_arm: REG3 {
+				regulator-name = "VDD_ARM";
+				regulator-min-microvolt = <875000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
 			};
 
-			yellow {
-				gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
-				default-state = "off";
+			vcc_io: REG4 {
+				regulator-name = "VCC_IO";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
 			};
 
-			sleep {
-				gpios = <&gpio0 15 0>;
-				default-state = "off";
+			vdd_10: REG5 {
+				regulator-name = "VDD_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vdd_hdmi: REG6 {
+				regulator-name = "VDD_HDMI";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+			};
+
+			vcc18: REG7 {
+				regulator-name = "VCC_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
 			};
+
+			vcca_33: REG8 {
+				regulator-name = "VCCA_33";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcc_rmii: REG9 {
+				regulator-name = "VCC_RMII";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vccio_wl: REG10 {
+				regulator-name = "VCCIO_WL";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "VCC18_IO";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc28: REG12 {
+				regulator-name = "VCC_28";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&mmc0 {
+	num-slots = <1>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	vmmc-supply = <&vcc_sd0>;
+
+	slot@0 {
+		reg = <0>;
+		bus-width = <4>;
+		disable-wp;
+	};
+};
+
+&pinctrl {
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	act8846 {
+		act8846_dvs0_ctl: act8846-dvs0-ctl {
+			rockchip,pins = <RK_GPIO3 27 RK_FUNC_GPIO &pcfg_output_low>;
 		};
+	};
 
+	ir-receiver {
+		ir_recv_pin: ir-recv-pin {
+			rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
 	};
 };
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,595 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "rockchip,rk3288";
+
+	interrupt-parent = <&gic>;
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@500 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a12";
+			reg = <0x500>;
+		};
+		cpu@501 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a12";
+			reg = <0x501>;
+		};
+		cpu@502 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a12";
+			reg = <0x502>;
+		};
+		cpu@503 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a12";
+			reg = <0x503>;
+		};
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	timer {
+		compatible = "arm,armv7-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)>;
+		clock-frequency = <24000000>;
+	};
+
+	i2c1: i2c@ff140000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff140000 0x1000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@ff150000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff150000 0x1000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		status = "disabled";
+	};
+
+	i2c4: i2c@ff160000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff160000 0x1000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_xfer>;
+		status = "disabled";
+	};
+
+	i2c5: i2c@ff170000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff170000 0x1000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C5>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_xfer>;
+		status = "disabled";
+	};
+
+	uart0: serial@ff180000 {
+		compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+		reg = <0xff180000 0x100>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer>;
+		status = "disabled";
+	};
+
+	uart1: serial@ff190000 {
+		compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+		reg = <0xff190000 0x100>;
+		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer>;
+		status = "disabled";
+	};
+
+	uart2: serial@ff690000 {
+		compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+		reg = <0xff690000 0x100>;
+		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff1b0000 {
+		compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+		reg = <0xff1b0000 0x100>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3_xfer>;
+		status = "disabled";
+	};
+
+	uart4: serial@ff1c0000 {
+		compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+		reg = <0xff1c0000 0x100>;
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_xfer>;
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb@ff500000 {
+		compatible = "generic-ehci";
+		reg = <0xff500000 0x100>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_USBHOST0>;
+		clock-names = "usbhost";
+		status = "disabled";
+	};
+
+	/* NOTE: ohci@ff520000 doesn't actually work on hardware */
+
+	usb_hsic: usb@ff5c0000 {
+		compatible = "generic-ehci";
+		reg = <0xff5c0000 0x100>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HSIC>;
+		clock-names = "usbhost";
+		status = "disabled";
+	};
+
+	i2c0: i2c@ff650000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff650000 0x1000>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@ff660000 {
+		compatible = "rockchip,rk3288-i2c";
+		reg = <0xff660000 0x1000>;
+		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		status = "disabled";
+	};
+
+	pmu: power-management@ff730000 {
+		compatible = "rockchip,rk3288-pmu", "syscon";
+		reg = <0xff730000 0x100>;
+	};
+
+	sgrf: syscon@ff740000 {
+		compatible = "rockchip,rk3288-sgrf", "syscon";
+		reg = <0xff740000 0x1000>;
+	};
+
+	cru: clock-controller@ff760000 {
+		compatible = "rockchip,rk3288-cru";
+		reg = <0xff760000 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	grf: syscon@ff770000 {
+		compatible = "rockchip,rk3288-grf", "syscon";
+		reg = <0xff770000 0x1000>;
+	};
+
+	wdt: watchdog@ff800000 {
+		compatible = "rockchip,rk3288-wdt", "snps,dw-wdt";
+		reg = <0xff800000 0x100>;
+		interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@ffc01000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0xffc01000 0x1000>,
+		      <0xffc02000 0x1000>,
+		      <0xffc04000 0x2000>,
+		      <0xffc06000 0x2000>;
+		interrupts = <GIC_PPI 9 0xf04>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3288-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmu>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@ff750000 {
+			compatible = "rockchip,gpio-bank";
+			reg =	<0xff750000 0x100>;
+			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@ff780000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff780000 0x100>;
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2@ff790000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff790000 0x100>;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio3@ff7a0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7a0000 0x100>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio4: gpio4@ff7b0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7b0000 0x100>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO4>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio5: gpio5@ff7c0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7c0000 0x100>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO5>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio6: gpio6@ff7d0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7d0000 0x100>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO6>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio7: gpio7@ff7e0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7e0000 0x100>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO7>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio8: gpio8@ff7f0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff7f0000 0x100>;
+			interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO8>;
+
+			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;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>,
+						<0 16 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <8 4 RK_FUNC_1 &pcfg_pull_none>,
+						<8 5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <6 9 RK_FUNC_1 &pcfg_pull_none>,
+						<6 10 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <2 16 RK_FUNC_1 &pcfg_pull_none>,
+						<2 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <7 17 RK_FUNC_1 &pcfg_pull_none>,
+						<7 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c5 {
+			i2c5_xfer: i2c5-xfer {
+				rockchip,pins = <7 19 RK_FUNC_1 &pcfg_pull_none>,
+						<7 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_cd: sdmcc-cd {
+				rockchip,pins = <6 22 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>,
+						<6 17 RK_FUNC_1 &pcfg_pull_up>,
+						<6 18 RK_FUNC_1 &pcfg_pull_up>,
+						<6 19 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_pwr: emmc-pwr {
+				rockchip,pins = <3 9 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus4: emmc-bus4 {
+				rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+						<3 1 RK_FUNC_2 &pcfg_pull_up>,
+						<3 2 RK_FUNC_2 &pcfg_pull_up>,
+						<3 3 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+						<3 1 RK_FUNC_2 &pcfg_pull_up>,
+						<3 2 RK_FUNC_2 &pcfg_pull_up>,
+						<3 3 RK_FUNC_2 &pcfg_pull_up>,
+						<3 4 RK_FUNC_2 &pcfg_pull_up>,
+						<3 5 RK_FUNC_2 &pcfg_pull_up>,
+						<3 6 RK_FUNC_2 &pcfg_pull_up>,
+						<3 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <4 16 RK_FUNC_1 &pcfg_pull_up>,
+						<4 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <4 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <4 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <5 8 RK_FUNC_1 &pcfg_pull_up>,
+						<5 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <5 10 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <5 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <7 22 RK_FUNC_1 &pcfg_pull_up>,
+						<7 23 RK_FUNC_1 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart2 */
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <7 7 RK_FUNC_1 &pcfg_pull_up>,
+						<7 8 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins = <7 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins = <7 10 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins = <5 12 3 &pcfg_pull_up>,
+						<5 13 3 &pcfg_pull_none>;
+			};
+
+			uart4_cts: uart4-cts {
+				rockchip,pins = <5 14 3 &pcfg_pull_none>;
+			};
+
+			uart4_rts: uart4-rts {
+				rockchip,pins = <5 15 3 &pcfg_pull_none>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb-act8846.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb-act8846.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb-act8846.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb-act8846.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "rk3288-evb.dtsi"
+
+/ {
+	compatible = "rockchip,rk3288-evb-act8846", "rockchip,rk3288";
+};
+
+&i2c0 {
+	hym8563@51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+
+		interrupt-parent = <&gpio0>;
+		interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&hym8563_int>;
+
+		#clock-cells = <0>;
+		clock-output-names = "xin32k";
+	};
+
+	act8846: act8846@5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		status = "okay";
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "VCC_DDR";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vcc_io: REG2 {
+				regulator-name = "VCC_IO";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_log: REG3 {
+				regulator-name = "VDD_LOG";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_20: REG4 {
+				regulator-name = "VCC_20";
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+			};
+
+			vccio_sd: REG5 {
+				regulator-name = "VCCIO_SD";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd10_lcd: REG6 {
+				regulator-name = "VDD10_LCD";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcca_codec: REG7 {
+				regulator-name = "VCCA_CODEC";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcca_tp: REG8 {
+				regulator-name = "VCCA_TP";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vccio_pmu: REG9 {
+				regulator-name = "VCCIO_PMU";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_10: REG10 {
+				regulator-name = "VDD_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "VCC_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc18_lcd: REG12 {
+				regulator-name = "VCC18_LCD";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&pinctrl {
+	hym8563 {
+		hym8563_int: hym8563-int {
+			rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "rk3288.dtsi"
+
+/ {
+	memory {
+		reg = <0x0 0x80000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwrbtn>;
+
+		button@0 {
+			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+			linux,code = <116>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			gpio-key,wakeup = <1>;
+			debounce-interval = <100>;
+		};
+	};
+
+	/* This turns on USB vbus for both host0 (ehci) and host1 (dwc2) */
+	vcc_host: vcc-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc_host";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&uart4 {
+	status = "okay";
+};
+
+&pinctrl {
+	buttons {
+		pwrbtn: pwrbtn {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb-rk808.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb-rk808.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3288-evb-rk808.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3288-evb-rk808.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "rk3288-evb.dtsi"
+
+/ {
+	compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/rk3xxx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3xxx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/rk3xxx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/rk3xxx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -20,120 +20,248 @@
 / {
 	interrupt-parent = <&gic>;
 
-	soc {
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		#clock-cells = <0>;
+		clock-output-names = "xin24m";
+	};
+
+	L2: l2-cache-controller@10138000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x10138000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	scu@1013c000 {
+		compatible = "arm,cortex-a9-scu";
+		reg = <0x1013c000 0x100>;
+	};
+
+	global_timer: global-timer@1013c200 {
+		compatible = "arm,cortex-a9-global-timer";
+		reg = <0x1013c200 0x20>;
+		interrupts = <GIC_PPI 11 0x304>;
+		clocks = <&cru CORE_PERI>;
+	};
+
+	local_timer: local-timer@1013c600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x1013c600 0x20>;
+		interrupts = <GIC_PPI 13 0x304>;
+		clocks = <&cru CORE_PERI>;
+	};
+
+	gic: interrupt-controller@1013d000 {
+		compatible = "arm,cortex-a9-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x1013d000 0x1000>,
+		      <0x1013c100 0x0100>;
+	};
+
+	uart0: serial@10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		status = "disabled";
+	};
+
+	uart1: serial@10126000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10126000 0x400>;
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		status = "disabled";
+	};
+
+	mmc0: dwmmc@10214000 {
+		compatible = "rockchip,rk2928-dw-mshc";
+		reg = <0x10214000 0x1000>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		ranges;
+		#size-cells = <0>;
 
-		scu@1013c000 {
-			compatible = "arm,cortex-a9-scu";
-			reg = <0x1013c000 0x100>;
-		};
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
+		clock-names = "biu", "ciu";
 
-		pmu: pmu@20004000 {
-			compatible = "rockchip,rk3066-pmu", "syscon";
-			reg = <0x20004000 0x100>;
-		};
+		status = "disabled";
+	};
 
-		grf: grf@20008000 {
-			compatible = "syscon";
-			reg = <0x20008000 0x200>;
-		};
+	mmc1: dwmmc@10218000 {
+		compatible = "rockchip,rk2928-dw-mshc";
+		reg = <0x10218000 0x1000>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		gic: interrupt-controller@1013d000 {
-			compatible = "arm,cortex-a9-gic";
-			interrupt-controller;
-			#interrupt-cells = <3>;
-			reg = <0x1013d000 0x1000>,
-			      <0x1013c100 0x0100>;
-		};
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>;
+		clock-names = "biu", "ciu";
 
-		L2: l2-cache-controller@10138000 {
-			compatible = "arm,pl310-cache";
-			reg = <0x10138000 0x1000>;
-			cache-unified;
-			cache-level = <2>;
-		};
+		status = "disabled";
+	};
 
-		global-timer@1013c200 {
-			compatible = "arm,cortex-a9-global-timer";
-			reg = <0x1013c200 0x20>;
-			interrupts = <GIC_PPI 11 0x304>;
-			clocks = <&dummy150m>;
-		};
+	pmu: pmu@20004000 {
+		compatible = "rockchip,rk3066-pmu", "syscon";
+		reg = <0x20004000 0x100>;
+	};
 
-		local-timer@1013c600 {
-			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0x1013c600 0x20>;
-			interrupts = <GIC_PPI 13 0x304>;
-			clocks = <&dummy150m>;
-		};
+	grf: grf@20008000 {
+		compatible = "syscon";
+		reg = <0x20008000 0x200>;
+	};
 
-		uart0: serial@10124000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x10124000 0x400>;
-			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 8>;
-			status = "disabled";
-		};
+	i2c0: i2c@2002d000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2002d000 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-		uart1: serial@10126000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x10126000 0x400>;
-			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 10>;
-			status = "disabled";
-		};
+		rockchip,grf = <&grf>;
+		rockchip,bus-index = <0>;
 
-		uart2: serial@20064000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x20064000 0x400>;
-			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 12>;
-			status = "disabled";
-		};
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C0>;
 
-		uart3: serial@20068000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x20068000 0x400>;
-			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 14>;
-			status = "disabled";
-		};
+		status = "disabled";
+	};
 
-		dwmmc@10214000 {
-			compatible = "rockchip,rk2928-dw-mshc";
-			reg = <0x10214000 0x1000>;
-			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-			#address-cells = <1>;
-			#size-cells = <0>;
+	i2c1: i2c@2002f000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2002f000 0x1000>;
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-			clocks = <&clk_gates5 10>, <&clk_gates2 11>;
-			clock-names = "biu", "ciu";
+		rockchip,grf = <&grf>;
 
-			status = "disabled";
-		};
+		clocks = <&cru PCLK_I2C1>;
+		clock-names = "i2c";
 
-		dwmmc@10218000 {
-			compatible = "rockchip,rk2928-dw-mshc";
-			reg = <0x10218000 0x1000>;
-			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-			#address-cells = <1>;
-			#size-cells = <0>;
+		status = "disabled";
+	};
 
-			clocks = <&clk_gates5 11>, <&clk_gates2 13>;
-			clock-names = "biu", "ciu";
+	pwm0: pwm@20030000 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20030000 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM01>;
+		status = "disabled";
+	};
 
-			status = "disabled";
-		};
+	pwm1: pwm@20030010 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20030010 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM01>;
+		status = "disabled";
+	};
+
+	wdt: watchdog@2004c000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x2004c000 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	pwm2: pwm@20050020 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050020 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM23>;
+		status = "disabled";
+	};
+
+	pwm3: pwm@20050030 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050030 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM23>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@20056000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x20056000 0x1000>;
+		interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C2>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	i2c3: i2c@2005a000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2005a000 0x1000>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C3>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	i2c4: i2c@2005e000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2005e000 0x1000>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C4>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	uart2: serial@20064000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20064000 0x400>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		status = "disabled";
+	};
+
+	uart3: serial@20068000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20068000 0x400>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		status = "disabled";
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s3c2416.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c2416.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s3c2416.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c2416.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,10 @@
 	model = "Samsung S3C2416 SoC";
 	compatible = "samsung,s3c2416";
 
+	aliases {
+		serial3 = &uart3;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -68,7 +72,7 @@
 				<&clocks SCLK_UART>;
 	};
 
-	serial@5000C000 {
+	uart3: serial@5000C000 {
 		compatible = "samsung,s3c2440-uart";
 		reg = <0x5000C000 0x4000>;
 		interrupts = <1 18 24 4>, <1 18 25 4>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s3c24xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c24xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s3c24xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c24xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,9 @@
 
 	aliases {
 		pinctrl0 = &pinctrl_0;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
 	};
 
 	intc:interrupt-controller@4a000000 {
@@ -46,21 +49,21 @@
 		#pwm-cells = <4>;
 	};
 
-	serial@50000000 {
+	uart0: serial@50000000 {
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50000000 0x4000>;
 		interrupts = <1 28 0 4>, <1 28 1 4>;
 		status = "disabled";
 	};
 
-	serial@50004000 {
+	uart1: serial@50004000 {
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50004000 0x4000>;
 		interrupts = <1 23 3 4>, <1 23 4 4>;
 		status = "disabled";
 	};
 
-	serial@50008000 {
+	uart2: serial@50008000 {
 		compatible = "samsung,s3c2410-uart";
 		reg = <0x50008000 0x4000>;
 		interrupts = <1 15 6 4>, <1 15 7 4>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s3c64xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c64xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s3c64xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s3c64xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,10 @@
 	aliases {
 		i2c0 = &i2c0;
 		pinctrl0 = &pinctrl0;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
 	};
 
 	cpus {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-aquila.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-aquila.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-aquila.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-aquila.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,392 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Samsung Aquila board.
+ *
+ * This program is free software; you can 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/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+	model = "Samsung Aquila based on S5PC110";
+	compatible = "samsung,aquila", "samsung,s5pv210";
+
+	aliases {
+		i2c3 = &i2c_pmic;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC2,115200n8 root=/dev/mmcblk1p5 rw rootwait ignore_loglevel earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x30000000 0x05000000
+			0x40000000 0x18000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vtf_reg: fixed-regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "V_TF_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpios = <&mp05 4 0>;
+			enable-active-high;
+		};
+
+		pda_reg: fixed-regulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "VCC_1.8V_PDA";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			reg = <1>;
+		};
+
+		bat_reg: fixed-regulator@2 {
+			compatible = "regulator-fixed";
+			regulator-name = "V_BAT";
+			regulator-min-microvolt = <3700000>;
+			regulator-max-microvolt = <3700000>;
+			reg = <2>;
+		};
+	};
+
+	i2c_pmic: i2c-pmic {
+		compatible = "i2c-gpio";
+		gpios = <&gpj4 0 0>, /* sda */
+			<&gpj4 3 0>; /* scl */
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pmic@66 {
+			compatible = "national,lp3974";
+			reg = <0x66>;
+
+			max8998,pmic-buck1-default-dvs-idx = <0>;
+			max8998,pmic-buck1-dvs-gpios = <&gph0 3 0>,
+							<&gph0 4 0>;
+			max8998,pmic-buck1-dvs-voltage = <1200000>, <1200000>,
+							<1200000>, <1200000>;
+
+			max8998,pmic-buck2-default-dvs-idx = <0>;
+			max8998,pmic-buck2-dvs-gpio = <&gph0 5 0>;
+			max8998,pmic-buck2-dvs-voltage = <1200000>, <1200000>;
+
+			regulators {
+				ldo2_reg: LDO2 {
+					regulator-name = "VALIVE_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "VUSB+MIPI_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "VADC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "VTF_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "VCC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "VCC_3.0V";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "VUSB+VDAC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "VCC+VCAM_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "VPLL_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "CAM_IO_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "CAM_ISP_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "CAM_A_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "CAM_CIF_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "CAM_AF_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "VMIPI_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo17_reg: LDO17 {
+					regulator-name = "CAM_8M_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "VARM_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "VINT_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "VCC_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "CAM_CORE_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vichg_reg: ENVICHG {
+					regulator-name = "VICHG";
+				};
+
+				safeout1_reg: ESAFEOUT1 {
+					regulator-name = "SAFEOUT1";
+					regulator-always-on;
+				};
+
+				safeout2_reg: ESAFEOUT2 {
+					regulator-name = "SAFEOUT2";
+					regulator-boot-on;
+				};
+			};
+		};
+
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power-key {
+			gpios = <&gph2 6 1>;
+			linux,code = <KEY_POWER>;
+			label = "power";
+			debounce-interval = <1>;
+			gpio-key,wakeup;
+		};
+	};
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
+
+&keypad {
+	linux,input-no-autorepeat;
+	linux,input-wakeup;
+	samsung,keypad-num-rows = <3>;
+	samsung,keypad-num-columns = <3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+			<&keypad_col0>, <&keypad_col1>, <&keypad_col2>;
+	status = "okay";
+
+	key_1 {
+		keypad,row = <0>;
+		keypad,column = <1>;
+		linux,code = <KEY_CONNECT>;
+	};
+
+	key_2 {
+		keypad,row = <0>;
+		keypad,column = <2>;
+		linux,code = <KEY_BACK>;
+	};
+
+	key_3 {
+		keypad,row = <1>;
+		keypad,column = <1>;
+		linux,code = <KEY_CAMERA_FOCUS>;
+	};
+
+	key_4 {
+		keypad,row = <1>;
+		keypad,column = <2>;
+		linux,code = <KEY_VOLUMEUP>;
+	};
+
+	key_5 {
+		keypad,row = <2>;
+		keypad,column = <1>;
+		linux,code = <KEY_CAMERA>;
+	};
+
+	key_6 {
+		keypad,row = <2>;
+		keypad,column = <2>;
+		linux,code = <KEY_VOLUMEDOWN>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+	vmmc-supply = <&ldo5_reg>;
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+	pinctrl-names = "default";
+};
+
+&sdhci2 {
+	bus-width = <4>;
+	cd-gpios = <&gph3 4 1>;
+	vmmc-supply = <&vtf_reg>;
+	cd-inverted;
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &t_flash_detect>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&onenand {
+	status = "okay";
+};
+
+&hsotg {
+	vusb_a-supply = <&ldo3_reg>;
+	vusb_d-supply = <&ldo8_reg>;
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&fimd {
+	pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: timing {
+			clock-frequency = <0>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <16>;
+			hback-porch = <16>;
+			hsync-len = <2>;
+			vback-porch = <3>;
+			vfront-porch = <28>;
+			vsync-len = <1>;
+		};
+	};
+};
+
+&pinctrl0 {
+	t_flash_detect: t-flash-detect {
+		samsung,pins = "gph3-4";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,633 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S5PV210 SoC. As device tree coverage for S5PV210 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 "skeleton.dtsi"
+#include <dt-bindings/clock/s5pv210.h>
+#include <dt-bindings/clock/s5pv210-audss.h>
+
+/ {
+	aliases {
+		csis0 = &csis0;
+		fimc0 = &fimc0;
+		fimc1 = &fimc1;
+		fimc2 = &fimc2;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2s0 = &i2s0;
+		i2s1 = &i2s1;
+		i2s2 = &i2s2;
+		pinctrl0 = &pinctrl0;
+		spi0 = &spi0;
+		spi1 = &spi1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a8";
+			reg = <0>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		external-clocks {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			xxti: oscillator@0 {
+				compatible = "fixed-clock";
+				reg = <0>;
+				clock-frequency = <0>;
+				clock-output-names = "xxti";
+				#clock-cells = <0>;
+			};
+
+			xusbxti: oscillator@1 {
+				compatible = "fixed-clock";
+				reg = <1>;
+				clock-frequency = <0>;
+				clock-output-names = "xusbxti";
+				#clock-cells = <0>;
+			};
+		};
+
+		onenand: onenand@b0000000 {
+			compatible = "samsung,s5pv210-onenand";
+			reg = <0xb0600000 0x2000>,
+				<0xb0000000 0x20000>,
+				<0xb0040000 0x20000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <31>;
+			clocks = <&clocks CLK_NANDXL>, <&clocks DOUT_FLASH>;
+			clock-names = "bus", "onenand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+		};
+
+		chipid@e0000000 {
+			compatible = "samsung,s5pv210-chipid";
+			reg = <0xe0000000 0x1000>;
+		};
+
+		clocks: clock-controller@e0100000 {
+			compatible = "samsung,s5pv210-clock", "simple-bus";
+			reg = <0xe0100000 0x10000>;
+			clock-names = "xxti", "xusbxti";
+			clocks = <&xxti>, <&xusbxti>;
+			#clock-cells = <1>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pmu_syscon: syscon@e0108000 {
+				compatible = "samsung-s5pv210-pmu", "syscon";
+				reg = <0xe0108000 0x8000>;
+			};
+		};
+
+		pinctrl0: pinctrl@e0200000 {
+			compatible = "samsung,s5pv210-pinctrl";
+			reg = <0xe0200000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <30>;
+
+			wakeup-interrupt-controller {
+				compatible = "samsung,exynos4210-wakeup-eint";
+				interrupts = <16>;
+				interrupt-parent = <&vic0>;
+			};
+		};
+
+		amba {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "arm,amba-bus";
+			ranges;
+
+			pdma0: dma@e0900000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0xe0900000 0x1000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <19>;
+				clocks = <&clocks CLK_PDMA0>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+
+			pdma1: dma@e0a00000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0xe0a00000 0x1000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <20>;
+				clocks = <&clocks CLK_PDMA1>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+		};
+
+		spi0: spi@e1300000 {
+			compatible = "samsung,s5pv210-spi";
+			reg = <0xe1300000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <15>;
+			dmas = <&pdma0 7>, <&pdma0 6>;
+			dma-names = "tx", "rx";
+			clocks = <&clocks SCLK_SPI0>, <&clocks CLK_SPI0>;
+			clock-names = "spi", "spi_busclk0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi0_bus>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi1: spi@e1400000 {
+			compatible = "samsung,s5pv210-spi";
+			reg = <0xe1400000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <16>;
+			dmas = <&pdma1 7>, <&pdma1 6>;
+			dma-names = "tx", "rx";
+			clocks = <&clocks SCLK_SPI1>, <&clocks CLK_SPI1>;
+			clock-names = "spi", "spi_busclk0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi1_bus>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		keypad: keypad@e1600000 {
+			compatible = "samsung,s5pv210-keypad";
+			reg = <0xe1600000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <25>;
+			clocks = <&clocks CLK_KEYIF>;
+			clock-names = "keypad";
+			status = "disabled";
+		};
+
+		i2c0: i2c@e1800000 {
+			compatible = "samsung,s3c2440-i2c";
+			reg = <0xe1800000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <14>;
+			clocks = <&clocks CLK_I2C0>;
+			clock-names = "i2c";
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_bus>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@e1a00000 {
+			compatible = "samsung,s3c2440-i2c";
+			reg = <0xe1a00000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <19>;
+			clocks = <&clocks CLK_I2C2>;
+			clock-names = "i2c";
+			pinctrl-0 = <&i2c2_bus>;
+			pinctrl-names = "default";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		audio-subsystem {
+			compatible = "samsung,s5pv210-audss", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			clk_audss: clock-controller@eee10000 {
+				compatible = "samsung,s5pv210-audss-clock";
+				reg = <0xeee10000 0x1000>;
+				clock-names = "hclk", "xxti",
+						"fout_epll",
+						"sclk_audio0";
+				clocks = <&clocks DOUT_HCLKP>, <&xxti>,
+						<&clocks FOUT_EPLL>,
+						<&clocks SCLK_AUDIO0>;
+				#clock-cells = <1>;
+			};
+
+			i2s0: i2s@eee30000 {
+				compatible = "samsung,s5pv210-i2s";
+				reg = <0xeee30000 0x1000>;
+				interrupt-parent = <&vic2>;
+				interrupts = <16>;
+				dma-names = "rx", "tx", "tx-sec";
+				dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
+				clock-names = "iis",
+						"i2s_opclk0",
+						"i2s_opclk1";
+				clocks = <&clk_audss CLK_I2S>,
+						<&clk_audss CLK_I2S>,
+						<&clk_audss CLK_DOUT_AUD_BUS>;
+				samsung,idma-addr = <0xc0010000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2s0_bus>;
+				#sound-dai-cells = <0>;
+				status = "disabled";
+			};
+		};
+
+		i2s1: i2s@e2100000 {
+			compatible = "samsung,s3c6410-i2s";
+			reg = <0xe2100000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <17>;
+			dma-names = "rx", "tx";
+			dmas = <&pdma1 12>, <&pdma1 13>;
+			clock-names = "iis", "i2s_opclk0";
+			clocks = <&clocks CLK_I2S1>, <&clocks SCLK_AUDIO1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2s1_bus>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
+		i2s2: i2s@e2a00000 {
+			compatible = "samsung,s3c6410-i2s";
+			reg = <0xe2a00000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <18>;
+			dma-names = "rx", "tx";
+			dmas = <&pdma1 14>, <&pdma1 15>;
+			clock-names = "iis", "i2s_opclk0";
+			clocks = <&clocks CLK_I2S2>, <&clocks SCLK_AUDIO2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2s2_bus>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
+		pwm: pwm@e2500000 {
+			compatible = "samsung,s5pc100-pwm";
+			reg = <0xe2500000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <21>, <22>, <23>, <24>, <25>;
+			clock-names = "timers";
+			clocks = <&clocks CLK_PWM>;
+			#pwm-cells = <3>;
+		};
+
+		watchdog: watchdog@e2700000 {
+			compatible = "samsung,s3c2410-wdt";
+			reg = <0xe2700000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <26>;
+			clock-names = "watchdog";
+			clocks = <&clocks CLK_WDT>;
+		};
+
+		rtc: rtc@e2800000 {
+			compatible = "samsung,s3c6410-rtc";
+			reg = <0xe2800000 0x100>;
+			interrupt-parent = <&vic0>;
+			interrupts = <28>, <29>;
+			clocks = <&clocks CLK_RTC>;
+			clock-names = "rtc";
+			status = "disabled";
+		};
+
+		uart0: serial@e2900000 {
+			compatible = "samsung,s5pv210-uart";
+			reg = <0xe2900000 0x400>;
+			interrupt-parent = <&vic1>;
+			interrupts = <10>;
+			clock-names = "uart", "clk_uart_baud0",
+					"clk_uart_baud1";
+			clocks = <&clocks CLK_UART0>, <&clocks CLK_UART0>,
+					<&clocks SCLK_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial@e2900400 {
+			compatible = "samsung,s5pv210-uart";
+			reg = <0xe2900400 0x400>;
+			interrupt-parent = <&vic1>;
+			interrupts = <11>;
+			clock-names = "uart", "clk_uart_baud0",
+					"clk_uart_baud1";
+			clocks = <&clocks CLK_UART1>, <&clocks CLK_UART1>,
+					<&clocks SCLK_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial@e2900800 {
+			compatible = "samsung,s5pv210-uart";
+			reg = <0xe2900800 0x400>;
+			interrupt-parent = <&vic1>;
+			interrupts = <12>;
+			clock-names = "uart", "clk_uart_baud0",
+					"clk_uart_baud1";
+			clocks = <&clocks CLK_UART2>, <&clocks CLK_UART2>,
+					<&clocks SCLK_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial@e2900c00 {
+			compatible = "samsung,s5pv210-uart";
+			reg = <0xe2900c00 0x400>;
+			interrupt-parent = <&vic1>;
+			interrupts = <13>;
+			clock-names = "uart", "clk_uart_baud0",
+					"clk_uart_baud1";
+			clocks = <&clocks CLK_UART3>, <&clocks CLK_UART3>,
+					<&clocks SCLK_UART3>;
+			status = "disabled";
+		};
+
+		sdhci0: sdhci@eb000000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0xeb000000 0x100000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <26>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks CLK_HSMMC0>, <&clocks CLK_HSMMC0>,
+					<&clocks SCLK_MMC0>;
+			status = "disabled";
+		};
+
+		sdhci1: sdhci@eb100000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0xeb100000 0x100000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <27>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks CLK_HSMMC1>, <&clocks CLK_HSMMC1>,
+					<&clocks SCLK_MMC1>;
+			status = "disabled";
+		};
+
+		sdhci2: sdhci@eb200000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0xeb200000 0x100000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <28>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks CLK_HSMMC2>, <&clocks CLK_HSMMC2>,
+					<&clocks SCLK_MMC2>;
+			status = "disabled";
+		};
+
+		sdhci3: sdhci@eb300000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0xeb300000 0x100000>;
+			interrupt-parent = <&vic3>;
+			interrupts = <2>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.3";
+			clocks = <&clocks CLK_HSMMC3>, <&clocks CLK_HSMMC3>,
+					<&clocks SCLK_MMC3>;
+			status = "disabled";
+		};
+
+		hsotg: hsotg@ec000000 {
+			compatible = "samsung,s3c6400-hsotg";
+			reg = <0xec000000 0x20000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <24>;
+			clocks = <&clocks CLK_USB_OTG>;
+			clock-names = "otg";
+			phy-names = "usb2-phy";
+			phys = <&usbphy 0>;
+			status = "disabled";
+		};
+
+		usbphy: usbphy@ec100000 {
+			compatible = "samsung,s5pv210-usb2-phy";
+			reg = <0xec100000 0x100>;
+			samsung,pmureg-phandle = <&pmu_syscon>;
+			clocks = <&clocks CLK_USB_OTG>, <&xusbxti>;
+			clock-names = "phy", "ref";
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		ehci: ehci@ec200000 {
+			compatible = "samsung,exynos4210-ehci";
+			reg = <0xec200000 0x100>;
+			interrupts = <23>;
+			interrupt-parent = <&vic1>;
+			clocks = <&clocks CLK_USB_HOST>;
+			clock-names = "usbhost";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			port@0 {
+				reg = <0>;
+				phys = <&usbphy 1>;
+			};
+		};
+
+		ohci: ohci@ec300000 {
+			compatible = "samsung,exynos4210-ohci";
+			reg = <0xec300000 0x100>;
+			interrupts = <23>;
+			clocks = <&clocks CLK_USB_HOST>;
+			clock-names = "usbhost";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			port@0 {
+				reg = <0>;
+				phys = <&usbphy 1>;
+			};
+		};
+
+		mfc: codec@f1700000 {
+			compatible = "samsung,mfc-v5";
+			reg = <0xf1700000 0x10000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <14>;
+			clocks = <&clocks DOUT_MFC>, <&clocks CLK_MFC>;
+			clock-names = "sclk_mfc", "mfc";
+		};
+
+		vic0: interrupt-controller@f2000000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0xf2000000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@f2100000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0xf2100000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic2: interrupt-controller@f2200000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0xf2200000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic3: interrupt-controller@f2300000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0xf2300000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fimd: fimd@f8000000 {
+			compatible = "samsung,exynos4210-fimd";
+			interrupt-parent = <&vic2>;
+			reg = <0xf8000000 0x20000>;
+			interrupt-names = "fifo", "vsync", "lcd_sys";
+			interrupts = <0>, <1>, <2>;
+			clocks = <&clocks SCLK_FIMD>, <&clocks CLK_FIMD>;
+			clock-names = "sclk_fimd", "fimd";
+			status = "disabled";
+		};
+
+		g2d: g2d@fa000000 {
+			compatible = "samsung,s5pv210-g2d";
+			reg = <0xfa000000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <9>;
+			clocks = <&clocks DOUT_G2D>, <&clocks CLK_G2D>;
+			clock-names = "sclk_fimg2d", "fimg2d";
+		};
+
+		mdma1: mdma@fa200000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xfa200000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <18>;
+			clocks = <&clocks CLK_MDMA>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+			#dma-channels = <8>;
+			#dma-requests = <1>;
+		};
+
+		i2c1: i2c@fab00000 {
+			compatible = "samsung,s3c2440-i2c";
+			reg = <0xfab00000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <13>;
+			clocks = <&clocks CLK_I2C1>;
+			clock-names = "i2c";
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c1_bus>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		camera: camera {
+			compatible = "samsung,fimc", "simple-bus";
+			pinctrl-names = "default";
+			pinctrl-0 = <>;
+			clocks = <&clocks SCLK_CAM0>, <&clocks SCLK_CAM1>;
+			clock-names = "sclk_cam0", "sclk_cam1";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			clock_cam: clock-controller {
+				#clock-cells = <1>;
+			};
+
+			csis0: csis@fa600000 {
+				compatible = "samsung,s5pv210-csis";
+				reg = <0xfa600000 0x4000>;
+				interrupt-parent = <&vic2>;
+				interrupts = <29>;
+				clocks = <&clocks CLK_CSIS>,
+						<&clocks SCLK_CSIS>;
+				clock-names = "clk_csis",
+						"sclk_csis";
+				bus-width = <4>;
+				status = "disabled";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+
+			fimc0: fimc@fb200000 {
+				compatible = "samsung,s5pv210-fimc";
+				reg = <0xfb200000 0x1000>;
+				interrupts = <5>;
+				interrupt-parent = <&vic2>;
+				clocks = <&clocks CLK_FIMC0>,
+						<&clocks SCLK_FIMC0>;
+				clock-names = "fimc",
+						"sclk_fimc";
+				samsung,pix-limits = <4224 8192 1920 4224>;
+				samsung,mainscaler-ext;
+				samsung,cam-if;
+			};
+
+			fimc1: fimc@fb300000 {
+				compatible = "samsung,s5pv210-fimc";
+				reg = <0xfb300000 0x1000>;
+				interrupt-parent = <&vic2>;
+				interrupts = <6>;
+				clocks = <&clocks CLK_FIMC1>,
+						<&clocks SCLK_FIMC1>;
+				clock-names = "fimc",
+						"sclk_fimc";
+				samsung,pix-limits = <4224 8192 1920 4224>;
+				samsung,mainscaler-ext;
+				samsung,cam-if;
+			};
+
+			fimc2: fimc@fb400000 {
+				compatible = "samsung,s5pv210-fimc";
+				reg = <0xfb400000 0x1000>;
+				interrupt-parent = <&vic2>;
+				interrupts = <7>;
+				clocks = <&clocks CLK_FIMC2>,
+						<&clocks SCLK_FIMC2>;
+				clock-names = "fimc",
+						"sclk_fimc";
+				samsung,pix-limits = <4224 8192 1920 4224>;
+				samsung,mainscaler-ext;
+				samsung,lcd-wb;
+			};
+		};
+	};
+};
+
+#include "s5pv210-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-goni.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-goni.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-goni.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-goni.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,449 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Samsung Goni board.
+ *
+ * This program is free software; you can 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/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+	model = "Samsung Goni based on S5PC110";
+	compatible = "samsung,goni", "samsung,s5pv210";
+
+	aliases {
+		i2c3 = &i2c_pmic;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p5 rw rootwait ignore_loglevel earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x30000000 0x05000000
+			0x40000000 0x10000000
+			0x50000000 0x08000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vtf_reg: fixed-regulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "V_TF_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			reg = <0>;
+			gpios = <&mp05 4 0>;
+			enable-active-high;
+		};
+
+		pda_reg: fixed-regulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "VCC_1.8V_PDA";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			reg = <1>;
+		};
+
+		bat_reg: fixed-regulator@2 {
+			compatible = "regulator-fixed";
+			regulator-name = "V_BAT";
+			regulator-min-microvolt = <3700000>;
+			regulator-max-microvolt = <3700000>;
+			reg = <2>;
+		};
+
+		tsp_reg: fixed-regulator@3 {
+			compatible = "regulator-fixed";
+			regulator-name = "TSP_VDD";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			reg = <3>;
+			gpios = <&gpj1 3 0>;
+			enable-active-high;
+		};
+	};
+
+	i2c_pmic: i2c-pmic {
+		compatible = "i2c-gpio";
+		gpios = <&gpj4 0 0>, /* sda */
+			<&gpj4 3 0>; /* scl */
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pmic@66 {
+			compatible = "national,lp3974";
+			reg = <0x66>;
+
+			max8998,pmic-buck1-default-dvs-idx = <0>;
+			max8998,pmic-buck1-dvs-gpios = <&gph0 3 0>,
+							<&gph0 4 0>;
+			max8998,pmic-buck1-dvs-voltage = <1200000>, <1200000>,
+							<1200000>, <1200000>;
+
+			max8998,pmic-buck2-default-dvs-idx = <0>;
+			max8998,pmic-buck2-dvs-gpio = <&gph0 5 0>;
+			max8998,pmic-buck2-dvs-voltage = <1200000>, <1200000>;
+
+			regulators {
+				ldo2_reg: LDO2 {
+					regulator-name = "VALIVE_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "VUSB+MIPI_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "VADC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "VTF_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "VCC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "VLCD_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "VUSB+VDAC_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "VCC+VCAM_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "VPLL_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-boot-on;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "CAM_IO_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "CAM_ISP_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "CAM_A_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "CAM_CIF_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "CAM_AF_3.3V";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "VMIPI_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo17_reg: LDO17 {
+					regulator-name = "CAM_8M_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "VARM_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "VINT_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "VCC_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "CAM_CORE_1.2V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power-key {
+			gpios = <&gph2 6 1>;
+			linux,code = <KEY_POWER>;
+			label = "power";
+			debounce-interval = <1>;
+			gpio-key,wakeup;
+		};
+	};
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
+
+&keypad {
+	linux,input-no-autorepeat;
+	linux,input-wakeup;
+	samsung,keypad-num-rows = <3>;
+	samsung,keypad-num-columns = <3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+			<&keypad_col0>, <&keypad_col1>, <&keypad_col2>;
+	status = "okay";
+
+	key_1 {
+		keypad,row = <0>;
+		keypad,column = <1>;
+		linux,code = <KEY_CONNECT>;
+	};
+
+	key_2 {
+		keypad,row = <0>;
+		keypad,column = <2>;
+		linux,code = <KEY_BACK>;
+	};
+
+	key_3 {
+		keypad,row = <1>;
+		keypad,column = <1>;
+		linux,code = <KEY_CAMERA_FOCUS>;
+	};
+
+	key_4 {
+		keypad,row = <1>;
+		keypad,column = <2>;
+		linux,code = <KEY_VOLUMEUP>;
+	};
+
+	key_5 {
+		keypad,row = <2>;
+		keypad,column = <1>;
+		linux,code = <KEY_CAMERA>;
+	};
+
+	key_6 {
+		keypad,row = <2>;
+		keypad,column = <2>;
+		linux,code = <KEY_VOLUMEDOWN>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	non-removable;
+	vmmc-supply = <&ldo5_reg>;
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci2 {
+	bus-width = <4>;
+	cd-gpios = <&gph3 4 1>;
+	vmmc-supply = <&vtf_reg>;
+	cd-inverted;
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&hsotg {
+	vusb_a-supply = <&ldo3_reg>;
+	vusb_d-supply = <&ldo8_reg>;
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&i2c2 {
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <400000>;
+	samsung,i2c-slave-addr = <0x10>;
+	status = "okay";
+
+	tsp@4a {
+		compatible = "atmel,maxtouch";
+		reg = <0x4a>;
+		interrupt-parent = <&gpj0>;
+		interrupts = <5 2>;
+
+		atmel,x-line = <17>;
+		atmel,y-line = <11>;
+		atmel,x-size = <800>;
+		atmel,y-size = <480>;
+		atmel,burst-length = <0x21>;
+		atmel,threshold = <0x28>;
+		atmel,orientation = <1>;
+
+		vdd-supply = <&tsp_reg>;
+	};
+};
+
+&i2c0 {
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <100000>;
+	samsung,i2c-slave-addr = <0x10>;
+	status = "okay";
+
+	noon010pc30: sensor@30 {
+		compatible = "siliconfile,noon010pc30";
+		reg = <0x30>;
+		vddio-supply = <&ldo11_reg>;
+		vdda-supply = <&ldo13_reg>;
+		vdd_core-supply = <&ldo14_reg>;
+
+		clock-frequency = <16000000>;
+		clocks = <&clock_cam 0>;
+		clock-names = "mclk";
+		nreset-gpios = <&gpb 2 0>;
+		nstby-gpios = <&gpb 0 0>;
+
+		port {
+			noon010pc30_ep: endpoint {
+				remote-endpoint = <&fimc0_ep>;
+				bus-width = <8>;
+				hsync-active = <0>;
+				vsync-active = <1>;
+				pclk-sample = <1>;
+			};
+		};
+	};
+};
+
+&camera {
+	pinctrl-0 = <&cam_port_a_io &cam_port_a_clk_active>;
+	pinctrl-1 = <&cam_port_a_io &cam_port_a_clk_idle>;
+	pinctrl-names = "default", "idle";
+
+	parallel-ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* camera A input */
+		port@1 {
+			reg = <1>;
+			fimc0_ep: endpoint {
+				remote-endpoint = <&noon010pc30_ep>;
+				bus-width = <8>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+				pclk-sample = <0>;
+			};
+		};
+	};
+};
+
+&fimd {
+	pinctrl-0 = <&lcd_clk &lcd_data24>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: timing {
+			/* 480x800@55Hz */
+			clock-frequency = <23439570>;
+			hactive = <480>;
+			hfront-porch = <16>;
+			hback-porch = <16>;
+			hsync-len = <2>;
+			vactive = <800>;
+			vback-porch = <2>;
+			vfront-porch = <28>;
+			vsync-len = <1>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <0>;
+			pixelclk-active = <0>;
+		};
+	};
+};
+
+&onenand {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-pinctrl.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-pinctrl.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-pinctrl.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,839 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S5PV210 SoC. As device tree coverage for S5PV210 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.
+ */
+
+&pinctrl0 {
+	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>;
+	};
+
+	gpe0: gpe0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpe1: gpe1 {
+		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>;
+	};
+
+	gpf3: gpf3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg0: gpg0 {
+		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>;
+	};
+
+	gpj0: gpj0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpj1: gpj1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpj2: gpj2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpj3: gpj3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpj4: gpj4 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpgi: gpgi {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp01: mp01 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp02: mp02 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp03: mp03 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp04: mp04 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp05: mp05 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp06: mp06 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	mp07: mp07 {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gph0: gph0 {
+		gpio-controller;
+		interrupt-controller;
+		interrupt-parent = <&vic0>;
+		interrupts = <0>, <1>, <2>, <3>,
+				<4>, <5>, <6>, <7>;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+	};
+
+	gph1: gph1 {
+		gpio-controller;
+		interrupt-controller;
+		interrupt-parent = <&vic0>;
+		interrupts = <8>, <9>, <10>, <11>,
+				<12>, <13>, <14>, <15>;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+	};
+
+	gph2: gph2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+	};
+
+	gph3: gph3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+	};
+
+	uart0_data: uart0-data {
+		samsung,pins = "gpa0-0", "gpa0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart0_fctl: uart0-fctl {
+		samsung,pins = "gpa0-2", "gpa0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_data: uart1-data {
+		samsung,pins = "gpa0-4", "gpa0-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_fctl: uart1-fctl {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_data: uart2-data {
+		samsung,pins = "gpa1-0", "gpa1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_fctl: uart2-fctl {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart3_data: uart3-data {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart_audio: uart-audio {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi0_bus: spi0-bus {
+		samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi1_bus: spi1-bus {
+		samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2s0_bus: i2s0-bus {
+		samsung,pins = "gpi-0", "gpi-1", "gpi-2", "gpi-3",
+				"gpi-4", "gpi-5", "gpi-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2s1_bus: i2s1-bus {
+		samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+				"gpc0-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2s2_bus: i2s2-bus {
+		samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+				"gpc1-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pcm1_bus: pcm1-bus {
+		samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+				"gpc0-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	ac97_bus: ac97-bus {
+		samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+				"gpc0-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2s2_bus: i2s2-bus {
+		samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+				"gpc1-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pcm2_bus: pcm2-bus {
+		samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+				"gpc1-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	spdif_bus: spdif-bus {
+		samsung,pins = "gpc1-0", "gpc1-1";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi2_bus: spi2-bus {
+		samsung,pins = "gpc1-1", "gpc1-2", "gpc1-3", "gpc1-4";
+		samsung,pin-function = <5>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c0_bus: i2c0-bus {
+		samsung,pins = "gpd1-0", "gpd1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c1_bus: i2c1-bus {
+		samsung,pins = "gpd1-2", "gpd1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c2_bus: i2c2-bus {
+		samsung,pins = "gpd1-4", "gpd1-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpd0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpd0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm2_out: pwm2-out {
+		samsung,pins = "gpd0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm3_out: pwm3-out {
+		samsung,pins = "gpd0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row0: keypad-row-0 {
+		samsung,pins = "gph3-0";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row1: keypad-row-1 {
+		samsung,pins = "gph3-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row2: keypad-row-2 {
+		samsung,pins = "gph3-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row3: keypad-row-3 {
+		samsung,pins = "gph3-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row4: keypad-row-4 {
+		samsung,pins = "gph3-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row5: keypad-row-5 {
+		samsung,pins = "gph3-5";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row6: keypad-row-6 {
+		samsung,pins = "gph3-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_row7: keypad-row-7 {
+		samsung,pins = "gph3-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col0: keypad-col-0 {
+		samsung,pins = "gph2-0";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col1: keypad-col-1 {
+		samsung,pins = "gph2-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col2: keypad-col-2 {
+		samsung,pins = "gph2-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col3: keypad-col-3 {
+		samsung,pins = "gph2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col4: keypad-col-4 {
+		samsung,pins = "gph2-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col5: keypad-col-5 {
+		samsung,pins = "gph2-5";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col6: keypad-col-6 {
+		samsung,pins = "gph2-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	keypad_col7: keypad-col-7 {
+		samsung,pins = "gph2-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpg0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpg0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpg0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpg0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpg0-3", "gpg0-4", "gpg0-5", "gpg0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpg1-3", "gpg1-4", "gpg1-5", "gpg1-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpg1-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_cmd: sd1-cmd {
+		samsung,pins = "gpg1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_cd: sd1-cd {
+		samsung,pins = "gpg1-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_bus1: sd1-bus-width1 {
+		samsung,pins = "gpg1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_bus4: sd1-bus-width4 {
+		samsung,pins = "gpg1-3", "gpg1-4", "gpg1-5", "gpg1-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpg2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpg2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpg2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpg2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpg2-3", "gpg2-4", "gpg2-5", "gpg2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus8: sd2-bus-width8 {
+		samsung,pins = "gpg3-3", "gpg3-4", "gpg3-5", "gpg3-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd3_clk: sd3-clk {
+		samsung,pins = "gpg3-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd3_cmd: sd3-cmd {
+		samsung,pins = "gpg3-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd3_cd: sd3-cd {
+		samsung,pins = "gpg3-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd3_bus1: sd3-bus-width1 {
+		samsung,pins = "gpg3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd3_bus4: sd3-bus-width4 {
+		samsung,pins = "gpg3-3", "gpg3-4", "gpg3-5", "gpg3-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <2>;
+		samsung,pin-drv = <3>;
+	};
+
+	eint0: ext-int0 {
+		samsung,pins = "gph0-0";
+		samsung,pin-function = <0xf>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	eint8: ext-int8 {
+		samsung,pins = "gph1-0";
+		samsung,pin-function = <0xf>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	eint15: ext-int15 {
+		samsung,pins = "gph1-7";
+		samsung,pin-function = <0xf>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	eint16: ext-int16 {
+		samsung,pins = "gph2-0";
+		samsung,pin-function = <0xf>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	eint31: ext-int31 {
+		samsung,pins = "gph3-7";
+		samsung,pin-function = <0xf>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	cam_port_a_io: cam-port-a-io {
+		samsung,pins = "gpe0-0", "gpe0-1", "gpe0-2", "gpe0-3",
+				"gpe0-4", "gpe0-5", "gpe0-6", "gpe0-7",
+				"gpe1-0", "gpe1-1", "gpe1-2", "gpe1-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	cam_port_a_clk_active: cam-port-a-clk-active {
+		samsung,pins = "gpe1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	cam_port_a_clk_idle: cam-port-a-clk-idle {
+		samsung,pins = "gpe1-3";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	cam_port_b_io: cam-port-b-io {
+		samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
+				"gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
+				"gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	cam_port_b_clk_active: cam-port-b-clk-active {
+		samsung,pins = "gpj1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	cam_port_b_clk_idle: cam-port-b-clk-idle {
+		samsung,pins = "gpj1-3";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+		lcd_ctrl: lcd-ctrl {
+		samsung,pins = "gpd0-0", "gpd0-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	lcd_sync: lcd-sync {
+		samsung,pins = "gpf0-0", "gpf0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	lcd_clk: lcd-clk {
+		samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	lcd_data24: lcd-data-width24 {
+		samsung,pins =  "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7",
+				"gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3",
+				"gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7",
+				"gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+				"gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7",
+				"gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-smdkc110.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-smdkc110.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-smdkc110.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-smdkc110.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for YIC System SMDC110 board.
+ *
+ * NOTE: This file is completely based on original board file for mach-smdkc110
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can 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/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+	model = "YIC System SMDKC110 based on S5PC110";
+	compatible = "yic,smdkc110", "samsung,s5pv210";
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x20000000 0x20000000>;
+	};
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	audio-codec@1b {
+		compatible = "wlf,wm8580";
+		reg = <0x1b>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c08";
+		reg = <0x50>;
+	};
+};
+
+&i2s0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,238 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for YIC System SMDV210 board.
+ *
+ * NOTE: This file is completely based on original board file for mach-smdkv210
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can 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/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+	model = "YIC System SMDKV210 based on S5PV210";
+	compatible = "yic,smdkv210", "samsung,s5pv210";
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x20000000 0x40000000>;
+	};
+
+	ethernet@18000000 {
+		compatible = "davicom,dm9000";
+		reg = <0xA8000000 0x2 0xA8000002 0x2>;
+		interrupt-parent = <&gph1>;
+		interrupts = <1 4>;
+		local-mac-address = [00 00 de ad be ef];
+		davicom,no-eeprom;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 3 5000000 0>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_out>;
+	};
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
+
+&keypad {
+	linux,input-no-autorepeat;
+	linux,input-wakeup;
+	samsung,keypad-num-rows = <8>;
+	samsung,keypad-num-columns = <8>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+			<&keypad_row3>, <&keypad_row4>, <&keypad_row5>,
+			<&keypad_row6>, <&keypad_row7>,
+			<&keypad_col0>, <&keypad_col1>, <&keypad_col2>,
+			<&keypad_col3>, <&keypad_col4>, <&keypad_col5>,
+			<&keypad_col6>, <&keypad_col7>;
+	status = "okay";
+
+	key_1 {
+		keypad,row = <0>;
+		keypad,column = <3>;
+		linux,code = <KEY_1>;
+	};
+
+	key_2 {
+		keypad,row = <0>;
+		keypad,column = <4>;
+		linux,code = <KEY_2>;
+	};
+
+	key_3 {
+		keypad,row = <0>;
+		keypad,column = <5>;
+		linux,code = <KEY_3>;
+	};
+
+	key_4 {
+		keypad,row = <0>;
+		keypad,column = <6>;
+		linux,code = <KEY_4>;
+	};
+
+	key_5 {
+		keypad,row = <0
+		>;
+		keypad,column = <7>;
+		linux,code = <KEY_5>;
+	};
+
+	key_6 {
+		keypad,row = <1>;
+		keypad,column = <3>;
+		linux,code = <KEY_A>;
+	};
+	key_7 {
+		keypad,row = <1>;
+		keypad,column = <4>;
+		linux,code = <KEY_B>;
+	};
+
+	key_8 {
+		keypad,row = <1>;
+		keypad,column = <5>;
+		linux,code = <KEY_C>;
+	};
+
+	key_9 {
+		keypad,row = <1>;
+		keypad,column = <6>;
+		linux,code = <KEY_D>;
+	};
+
+	key_10 {
+		keypad,row = <1>;
+		keypad,column = <7>;
+		linux,code = <KEY_E>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci1 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus1 &sd1_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci2 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci3 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_cd &sd3_bus1 &sd3_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&hsotg {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&fimd {
+	pinctrl-0 = <&lcd_clk &lcd_data24>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	display-timings {
+		native-mode = <&timing0>;
+
+		timing0: timing@0 {
+			/* 800x480@60Hz */
+			clock-frequency = <24373920>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <8>;
+			hback-porch = <13>;
+			hsync-len = <3>;
+			vback-porch = <7>;
+			vfront-porch = <5>;
+			vsync-len = <1>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+	};
+};
+
+&pwm {
+	samsung,pwm-outputs = <3>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	audio-codec@1b {
+		compatible = "wlf,wm8580";
+		reg = <0x1b>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c08";
+		reg = <0x50>;
+	};
+};
+
+&i2s0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-torbreck.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-torbreck.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/s5pv210-torbreck.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/s5pv210-torbreck.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Torbreck board.
+ *
+ * NOTE: This file is completely based on original board file for mach-torbreck
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can 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/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+	model = "aESOP Torbreck based on S5PV210";
+	compatible = "aesop,torbreck", "samsung,s5pv210";
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x20000000 0x20000000>;
+	};
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci1 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus1 &sd1_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci2 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhci3 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_cd &sd3_bus1 &sd3_bus4>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -58,19 +58,19 @@
 		reg = <0x20000000 0x8000000>;
 	};
 
-	slow_xtal: slow_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	main_xtal: main_xtal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
 
-	clocks {
 		adc_op_clk: adc_op_clk{
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3_gmac.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3_gmac.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3_gmac.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3_gmac.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@
 			};
 
 			macb0: ethernet@f0028000 {
-				compatible = "cdns,pc302-gem", "cdns,gem";
+				compatible = "atmel,sama5d3-gem";
 				reg = <0xf0028000 0x100>;
 				interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>;
 				pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3xcm.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3xcm.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3xcm.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3xcm.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -18,12 +18,14 @@
 		reg = <0x20000000 0x20000000>;
 	};
 
-	slow_xtal {
-		clock-frequency = <32768>;
-	};
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
 
-	main_xtal {
-		clock-frequency = <12000000>;
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3xmb.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3xmb.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sama5d3xmb.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sama5d3xmb.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,8 @@
 				wm8904: wm8904@1a {
 					compatible = "wm8904";
 					reg = <0x1a>;
+					clocks = <&pck0>;
+					clock-names = "mclk";
 				};
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sh73a0.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sh73a0.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sh73a0.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sh73a0.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -235,6 +235,78 @@
 		status = "disabled";
 	};
 
+	scifa0: serial@e6c40000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c40000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa1: serial@e6c50000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c50000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa2: serial@e6c60000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c60000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa3: serial@e6c70000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c70000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa4: serial@e6c80000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c80000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa5: serial@e6cb0000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6cb0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa6: serial@e6cc0000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6cc0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifa7: serial@e6cd0000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6cd0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	scifb8: serial@e6c30000 {
+		compatible = "renesas,scifb-sh73a0", "renesas,scifb";
+		reg = <0xe6c30000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
 	pfc: pfc@e6050000 {
 		compatible = "renesas,pfc-sh73a0";
 		reg = <0xe6050000 0x8000>,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,10 @@
 	model = "KZM-A9-GT";
 	compatible = "renesas,kzm9g-reference", "renesas,sh73a0";
 
+	aliases {
+		serial4 = &scifa4;
+	};
+
 	cpus {
 		cpu@0 {
 			cpu0-supply = <&vdd_dvfs>;
@@ -35,7 +39,7 @@
 	};
 
 	chosen {
-		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200 rw";
+		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel rw";
 	};
 
 	memory {
@@ -276,9 +280,6 @@
 };
 
 &pfc {
-	pinctrl-0 = <&scifa4_pins>;
-	pinctrl-names = "default";
-
 	i2c3_pins: i2c3 {
 		renesas,groups = "i2c3_1";
 		renesas,function = "i2c3";
@@ -318,6 +319,13 @@
 	};
 };
 
+&scifa4 {
+	pinctrl-0 = <&scifa4_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/socfpga.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/socfpga.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/socfpga.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/socfpga.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -486,6 +486,8 @@
 			clock-names = "stmmaceth";
 			resets = <&rst EMAC0_RESET>;
 			reset-names = "stmmaceth";
+			snps,multicast-filter-bins = <256>;
+			snps,perfect-filter-entries = <128>;
 			status = "disabled";
 		};
 
@@ -500,6 +502,8 @@
 			clock-names = "stmmaceth";
 			resets = <&rst EMAC1_RESET>;
 			reset-names = "stmmaceth";
+			snps,multicast-filter-bins = <256>;
+			snps,perfect-filter-entries = <128>;
 			status = "disabled";
 		};
 
@@ -683,6 +687,7 @@
 		};
 
 		rst: rstmgr@ffd05000 {
+			#reset-cells = <1>;
 			compatible = "altr,rst-mgr";
 			reg = <0xffd05000 0x1000>;
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/spear1310.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1310.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/spear1310.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1310.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -29,24 +29,111 @@
 			#gpio-cells = <2>;
 		};
 
-		ahci@b1000000 {
+		miphy0: miphy@eb800000 {
+			compatible = "st,spear1310-miphy";
+			reg = <0xeb800000 0x4000>;
+			misc = <&misc>;
+			phy-id = <0>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		miphy1: miphy@eb804000 {
+			compatible = "st,spear1310-miphy";
+			reg = <0xeb804000 0x4000>;
+			misc = <&misc>;
+			phy-id = <1>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		miphy2: miphy@eb808000 {
+			compatible = "st,spear1310-miphy";
+			reg = <0xeb808000 0x4000>;
+			misc = <&misc>;
+			phy-id = <2>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		ahci0: ahci@b1000000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb1000000 0x10000>;
 			interrupts = <0 68 0x4>;
+			phys = <&miphy0 0>;
+			phy-names = "sata-phy";
 			status = "disabled";
 		};
 
-		ahci@b1800000 {
+		ahci1: ahci@b1800000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb1800000 0x10000>;
 			interrupts = <0 69 0x4>;
+			phys = <&miphy1 0>;
+			phy-names = "sata-phy";
 			status = "disabled";
 		};
 
-		ahci@b4000000 {
+		ahci2: ahci@b4000000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb4000000 0x10000>;
 			interrupts = <0 70 0x4>;
+			phys = <&miphy2 0>;
+			phy-names = "sata-phy";
+			status = "disabled";
+		};
+
+		pcie0: pcie@b1000000 {
+			compatible = "st,spear1340-pcie", "snps,dw-pcie";
+			reg = <0xb1000000 0x4000>;
+			interrupts = <0 68 0x4>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0x0 0 &gic 0 68 0x4>;
+			num-lanes = <1>;
+			phys = <&miphy0 1>;
+			phy-names = "pcie-phy";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			ranges = <0x00000800 0 0x80000000 0x80000000 0 0x00020000   /* configuration space */
+				0x81000000 0 0	 0x80020000 0 0x00010000   /* downstream I/O */
+				0x82000000 0 0x80030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
+			status = "disabled";
+		};
+
+		pcie1: pcie@b1800000 {
+			compatible = "st,spear1340-pcie", "snps,dw-pcie";
+			reg = <0xb1800000 0x4000>;
+			interrupts = <0 69 0x4>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0x0 0 &gic 0 69 0x4>;
+			num-lanes = <1>;
+			phys = <&miphy1 1>;
+			phy-names = "pcie-phy";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			ranges = <0x00000800 0 0x90000000 0x90000000 0 0x00020000   /* configuration space */
+				0x81000000 0 0  0x90020000 0 0x00010000   /* downstream I/O */
+				0x82000000 0 0x90030000 0x90030000 0 0x0ffd0000>; /* non-prefetchable memory */
+			status = "disabled";
+		};
+
+		pcie2: pcie@b4000000 {
+			compatible = "st,spear1340-pcie", "snps,dw-pcie";
+			reg = <0xb4000000 0x4000>;
+			interrupts = <0 70 0x4>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0x0 0 &gic 0 70 0x4>;
+			num-lanes = <1>;
+			phys = <&miphy2 1>;
+			phy-names = "pcie-phy";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			ranges = <0x00000800 0 0xc0000000 0xc0000000 0 0x00020000   /* configuration space */
+				0x81000000 0 0	 0xc0020000 0 0x00010000   /* downstream I/O */
+				0x82000000 0 0xc0030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/spear1310-evb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1310-evb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/spear1310-evb.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1310-evb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -106,6 +106,10 @@
 			status = "okay";
 		};
 
+		miphy@eb800000 {
+			status = "okay";
+		};
+
 		cf@b2800000 {
 			status = "okay";
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/spear1340.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1340.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/spear1340.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1340.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -31,10 +31,38 @@
 			status = "disabled";
 		};
 
-		ahci@b1000000 {
+		miphy0: miphy@eb800000 {
+			compatible = "st,spear1340-miphy";
+			reg = <0xeb800000 0x4000>;
+			misc = <&misc>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		ahci0: ahci@b1000000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb1000000 0x10000>;
 			interrupts = <0 72 0x4>;
+			phys = <&miphy0 0>;
+			phy-names = "sata-phy";
+			status = "disabled";
+		};
+
+		pcie0: pcie@b1000000 {
+			compatible = "st,spear1340-pcie", "snps,dw-pcie";
+			reg = <0xb1000000 0x4000>;
+			interrupts = <0 68 0x4>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0x0 0 &gic 0 68 0x4>;
+			num-lanes = <1>;
+			phys = <&miphy0 1>;
+			phy-names = "pcie-phy";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			ranges = <0x00000800 0 0x80000000 0x80000000 0 0x00020000   /* configuration space */
+				0x81000000 0 0	 0x80020000 0 0x00010000   /* downstream I/O */
+				0x82000000 0 0x80030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/spear1340-evb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1340-evb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/spear1340-evb.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear1340-evb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -122,6 +122,10 @@
 			status = "okay";
 		};
 
+		miphy@eb800000 {
+			status = "okay";
+		};
+
 		dma@ea800000 {
 			status = "okay";
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/spear13xx.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear13xx.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/spear13xx.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/spear13xx.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -83,8 +83,8 @@
 		#size-cells = <1>;
 		compatible = "simple-bus";
 		ranges = <0x50000000 0x50000000 0x10000000
-			  0xb0000000 0xb0000000 0x10000000
-			  0xd0000000 0xd0000000 0x02000000
+			  0x80000000 0x80000000 0x20000000
+			  0xb0000000 0xb0000000 0x22000000
 			  0xd8000000 0xd8000000 0x01000000
 			  0xe0000000 0xe0000000 0x10000000>;
 
@@ -220,6 +220,11 @@
 				  0xd8000000 0xd8000000 0x01000000
 				  0xe0000000 0xe0000000 0x10000000>;
 
+			misc: syscon@e0700000 {
+				compatible = "st,spear1340-misc", "syscon";
+				reg = <0xe0700000 0x1000>;
+			};
+
 			gpio0: gpio@e0600000 {
 				compatible = "arm,pl061", "arm,primecell";
 				reg = <0xe0600000 0x1000>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -875,6 +875,10 @@
 			reg = <0x80119000 0x1000>;
 			interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
 
+			dmas = <&dma 41 0 0x2>, /* Logical - DevToMem */
+			       <&dma 41 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+
 			clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>;
 			clock-names = "sdi", "apb_pclk";
 
@@ -901,6 +905,10 @@
 			reg = <0x80008000 0x1000>;
 			interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
 
+			dmas = <&dma 43 0 0x2>, /* Logical - DevToMem */
+			       <&dma 43 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+
 			clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
 			clock-names = "sdi", "apb_pclk";
 
@@ -929,6 +937,7 @@
 			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
+			/* This DMA channel only exist on DB8500 v1 */
 			dmas = <&dma 30 0 0x10>; /* Logical - MemToDev - HighPrio */
 			dma-names = "tx";
 
@@ -962,6 +971,7 @@
 			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
+			/* This DMA channel only exist on DB8500 v2 */
 			dmas = <&dma 30 0 0x12>; /* Logical - DevToMem - HighPrio */
 			dma-names = "rx";
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,8 @@
 				interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
 				interrupt-parent = <&gpio6>;
 				interrupt-controller;
+				vcc-supply = <&db8500_vsmps2_reg>;
+				vio-supply = <&db8500_vsmps2_reg>;
 
 				wakeup-source;
 				st,autosleep-timeout = <1024>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -88,6 +88,43 @@
 				};
 			};
 		};
+		/* Sensors mounted on this board variant */
+		i2c@80128000 {
+			lsm303dlh@18 {
+				/* Accelerometer */
+				compatible = "st,lsm303dlh-accel";
+				st,drdy-int-pin = <1>;
+				reg = <0x18>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&accel_tvk_mode>;
+			};
+			lsm303dlm@1e {
+				/* Magnetometer */
+				compatible = "st,lsm303dlm-magn";
+				reg = <0x1e>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&magneto_tvk_mode>;
+			};
+			l3g4200d@68 {
+				/* Gyroscope */
+				compatible = "st,l3g4200d-gyro";
+				st,drdy-int-pin = <2>;
+				reg = <0x68>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+			};
+			lsp001wm@5c {
+				/* Barometer/pressure sensor */
+				compatible = "st,lps001wp-press";
+				reg = <0x5c>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+			};
+		};
 		pinctrl {
 			/* Pull up this GPIO pin */
 			tc35893 {
@@ -114,6 +151,28 @@
 					};
 				};
 			};
+			accelerometer {
+				accel_tvk_mode: accel_tvk {
+					/* Accelerometer interrupt lines 1 & 2 */
+					tvk_cfg {
+						ste,pins = "GPIO82_C1", "GPIO83_D3";
+						ste,config = <&gpio_in_pu>;
+					};
+				};
+			};
+			magnetometer {
+				magneto_tvk_mode: magneto_tvk {
+					/* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
+					tvk_cfg1 {
+						ste,pins = "GPIO31_V3";
+						ste,config = <&gpio_in_pu>;
+					};
+					tvk_cfg2 {
+						ste,pins = "GPIO32_V2";
+						ste,config = <&gpio_in_pd>;
+					};
+				};
+			};
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,6 @@
 			 */
 			pinctrl-names = "default";
 			pinctrl-0 = <&ipgpio_hrefv60_mode>,
-				  <&accel_hrefv60_mode>,
-				  <&magneto_hrefv60_mode>,
 				  <&etm_hrefv60_mode>,
 				  <&nahj_hrefv60_mode>,
 				  <&nfc_hrefv60_mode>,
@@ -83,28 +81,6 @@
 					};
 				};
 			};
-			accelerometer {
-				accel_hrefv60_mode: accel_hrefv60 {
-					/* Accelerometer interrupt lines 1 & 2 */
-					hrefv60_cfg1 {
-						ste,pins = "GPIO82_C1", "GPIO83_D3";
-						ste,config = <&gpio_in_pu>;
-					};
-				};
-			};
-			magnetometer {
-				magneto_hrefv60_mode: magneto_hrefv60 {
-					/* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
-					hrefv60_cfg1 {
-						ste,pins = "GPIO31_V3";
-						ste,config = <&gpio_in_pu>;
-					};
-					hrefv60_cfg2 {
-						ste,pins = "GPIO32_V2";
-						ste,config = <&gpio_in_pd>;
-					};
-				};
-			};
 			etm {
 				/*
 				 * Drive D19-D23 for the ETM PTM trace interface low,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/ste-snowball.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-snowball.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/ste-snowball.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/ste-snowball.dts	2014-09-28 17:29:07.000000000 -0400
@@ -116,7 +116,6 @@
 		msp2: msp@80117000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&msp2_default_mode>;
-			status = "okay";
 		};
 
 		msp3: msp@80125000 {
@@ -241,6 +240,40 @@
 			pinctrl-names = "default","sleep";
 			pinctrl-0 = <&i2c2_default_mode>;
 			pinctrl-1 = <&i2c2_sleep_mode>;
+			lsm303dlh@18 {
+				/* Accelerometer */
+				compatible = "st,lsm303dlh-accel";
+				st,drdy-int-pin = <1>;
+				reg = <0x18>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&accel_snowball_mode>;
+			};
+			lsm303dlm@1e {
+				/* Magnetometer */
+				compatible = "st,lsm303dlm-magn";
+				reg = <0x1e>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&magneto_snowball_mode>;
+			};
+			l3g4200d@68 {
+				/* Gyroscope */
+				compatible = "st,l3g4200d-gyro";
+				st,drdy-int-pin = <2>;
+				reg = <0x68>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+			};
+			lsp001wm@5c {
+				/* Barometer/pressure sensor */
+				compatible = "st,lps001wp-press";
+				reg = <0x5c>;
+				vdd-supply = <&ab8500_ldo_aux1_reg>;
+				vddio-supply = <&db8500_vsmps2_reg>;
+			};
 		};
 
 		i2c@80110000 {
@@ -361,9 +394,7 @@
 			 * can be moved over to being controlled by respective device.
 			 */
 			pinctrl-names = "default";
-			pinctrl-0 = <&accel_snowball_mode>,
-				  <&magneto_snowball_mode>,
-				  <&gbf_snowball_mode>,
+			pinctrl-0 = <&gbf_snowball_mode>,
 				  <&wlan_snowball_mode>;
 
 			ethernet {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts	2014-09-28 17:29:07.000000000 -0400
@@ -88,6 +88,12 @@
 			};
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
@@ -98,6 +104,15 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+	model = "BA10 tvbox";
+	compatible = "allwinner,ba10-tvbox", "allwinner,sun4i-a10";
+
+	soc@01c00000 {
+		emac: ethernet@01c0b000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&emac_pins_a>;
+			phy = <&phy1>;
+			status = "okay";
+		};
+
+		mdio@01c0b080 {
+			status = "okay";
+
+			phy1: ethernet-phy@1 {
+				reg = <1>;
+			};
+		};
+
+		mmc0: mmc@01c0f000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+			vmmc-supply = <&reg_vcc3v3>;
+			bus-width = <4>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			cd-inverted;
+			status = "okay";
+		};
+
+		usbphy: phy@01c13400 {
+			usb1_vbus-supply = <&reg_usb1_vbus>;
+			usb2_vbus-supply = <&reg_usb2_vbus>;
+			status = "okay";
+		};
+
+		ehci0: usb@01c14000 {
+			status = "okay";
+		};
+
+		ohci0: usb@01c14400 {
+			status = "okay";
+		};
+
+		ehci1: usb@01c1c000 {
+			status = "okay";
+		};
+
+		ohci1: usb@01c1c400 {
+			status = "okay";
+		};
+
+		pinctrl@01c20800 {
+			usb2_vbus_pin_a: usb2_vbus_pin@0 {
+				allwinner,pins = "PH12";
+			};
+		};
+
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
+		uart0: serial@01c28000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins_a>;
+			status = "okay";
+		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+	reg_usb1_vbus: usb1-vbus {
+		status = "okay";
+	};
+
+	reg_usb2_vbus: usb2-vbus {
+		gpio = <&pio 7 12 0>;
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-cubieboard.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-cubieboard.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-cubieboard.dts	2014-09-28 17:29:07.000000000 -0400
@@ -80,6 +80,12 @@
 			};
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
@@ -90,6 +96,15 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 
 		i2c1: i2c@01c2b000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -509,7 +509,7 @@
 			clocks = <&apb0_gates 5>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 
@@ -593,6 +593,20 @@
 				allwinner,drive = <0>;
 				allwinner,pull = <1>;
 			};
+
+			ir0_pins_a: ir0@0 {
+				allwinner,pins = "PB3","PB4";
+				allwinner,function = "ir0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			ir1_pins_a: ir1@0 {
+				allwinner,pins = "PB22","PB23";
+				allwinner,function = "ir1";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		timer@01c20c00 {
@@ -621,6 +635,24 @@
 			status = "disabled";
 		};
 
+		ir0: ir@01c21800 {
+			compatible = "allwinner,sun4i-a10-ir";
+			clocks = <&apb0_gates 6>, <&ir0_clk>;
+			clock-names = "apb", "ir";
+			interrupts = <5>;
+			reg = <0x01c21800 0x40>;
+			status = "disabled";
+		};
+
+		ir1: ir@01c21c00 {
+			compatible = "allwinner,sun4i-a10-ir";
+			clocks = <&apb0_gates 7>, <&ir1_clk>;
+			clock-names = "apb", "ir";
+			interrupts = <6>;
+			reg = <0x01c21c00 0x40>;
+			status = "disabled";
+		};
+
 		sid: eeprom@01c23800 {
 			compatible = "allwinner,sun4i-a10-sid";
 			reg = <0x01c23800 0x10>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-hackberry.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-hackberry.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-hackberry.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-hackberry.dts	2014-09-28 17:29:07.000000000 -0400
@@ -87,11 +87,32 @@
 			};
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
 	};
 
 	reg_emac_3v3: emac-3v3 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -40,12 +40,6 @@
 			status = "okay";
 		};
 
-		i2c0: i2c@01c2ac00 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c0_pins_a>;
-			status = "okay";
-		};
-
 		usbphy: phy@01c13400 {
 			usb1_vbus-supply = <&reg_usb1_vbus>;
 			usb2_vbus-supply = <&reg_usb2_vbus>;
@@ -67,6 +61,21 @@
 		ohci1: usb@01c1c400 {
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
 	};
 
 	reg_usb1_vbus: usb1-vbus {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts	2014-09-28 17:29:07.000000000 -0400
@@ -52,11 +52,39 @@
 			status = "okay";
 		};
 
+		pinctrl@01c20800 {
+			ir0_pins_a: ir0@0 {
+				/* The ir receiver is not always populated */
+				allwinner,pull = <1>;
+			};
+		};
+
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
 	};
 
 	reg_usb1_vbus: usb1-vbus {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts	2014-09-28 17:29:07.000000000 -0400
@@ -91,6 +91,21 @@
 			pinctrl-0 = <&uart0_pins_a>;
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
 	};
 
 	leds {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-pcduino.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-pcduino.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun4i-a10-pcduino.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun4i-a10-pcduino.dts	2014-09-28 17:29:07.000000000 -0400
@@ -76,6 +76,15 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupts = <0>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -422,7 +422,7 @@
 			clocks = <&apb0_gates 5>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun5i-a13.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun5i-a13.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun5i-a13.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun5i-a13.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -395,7 +395,7 @@
 			clocks = <&apb0_gates 5>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun6i-a31.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun6i-a31.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun6i-a31.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun6i-a31.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@
 		serial3 = &uart3;
 		serial4 = &uart4;
 		serial5 = &uart5;
+		ethernet0 = &gmac;
 	};
 
 
@@ -281,6 +282,34 @@
 					     "usb_ohci0", "usb_ohci1",
 					     "usb_ohci2";
 		};
+
+		/*
+		 * The following two are dummy clocks, placeholders used in the gmac_tx
+		 * clock. The gmac driver will choose one parent depending on the PHY
+		 * interface mode, using clk_set_rate auto-reparenting.
+		 * The actual TX clock rate is not controlled by the gmac_tx clock.
+		 */
+		mii_phy_tx_clk: clk@1 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <25000000>;
+			clock-output-names = "mii_phy_tx";
+		};
+
+		gmac_int_tx_clk: clk@2 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <125000000>;
+			clock-output-names = "gmac_int_tx";
+		};
+
+		gmac_tx_clk: clk@01c200d0 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun7i-a20-gmac-clk";
+			reg = <0x01c200d0 0x4>;
+			clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
+			clock-output-names = "gmac_tx";
+		};
 	};
 
 	soc@01c00000 {
@@ -429,7 +458,7 @@
 			clocks = <&apb1_gates 5>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 
@@ -467,6 +496,48 @@
 				allwinner,drive = <2>;
 				allwinner,pull = <0>;
 			};
+
+			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 = <0>;
+				allwinner,pull = <0>;
+			};
+
+			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 = <2>;
+				allwinner,pull = <0>;
+			};
+
+			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 = <3>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		ahb1_rst: reset@01c202c0 {
@@ -589,6 +660,8 @@
 			clock-frequency = <100000>;
 			resets = <&apb2_rst 0>;
 			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 
 		i2c1: i2c@01c2b000 {
@@ -599,6 +672,8 @@
 			clock-frequency = <100000>;
 			resets = <&apb2_rst 1>;
 			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 
 		i2c2: i2c@01c2b400 {
@@ -609,6 +684,8 @@
 			clock-frequency = <100000>;
 			resets = <&apb2_rst 2>;
 			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 
 		i2c3: i2c@01c2b800 {
@@ -619,6 +696,25 @@
 			clock-frequency = <100000>;
 			resets = <&apb2_rst 3>;
 			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		gmac: ethernet@01c30000 {
+			compatible = "allwinner,sun7i-a20-gmac";
+			reg = <0x01c30000 0x1054>;
+			interrupts = <0 82 4>;
+			interrupt-names = "macirq";
+			clocks = <&ahb1_gates 17>, <&gmac_tx_clk>;
+			clock-names = "stmmaceth", "allwinner_gmac_tx";
+			resets = <&ahb1_rst 17>;
+			reset-names = "stmmaceth";
+			snps,pbl = <2>;
+			snps,fixed-burst;
+			snps,force_sf_dma_mode;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 
 		timer@01c60000 {
@@ -756,7 +852,7 @@
 			resets = <&apb0_rst 0>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2014 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun6i-a31.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+	model = "Merrii A31 Hummingbird";
+	compatible = "merrii,a31-hummingbird", "allwinner,sun6i-a31";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS0,115200";
+	};
+
+	soc@01c00000 {
+		mmc0: mmc@01c0f000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_hummingbird>;
+			vmmc-supply = <&reg_vcc3v0>;
+			bus-width = <4>;
+			cd-gpios = <&pio 0 8 0>; /* PA8 */
+			cd-inverted;
+			status = "okay";
+		};
+
+		usbphy: phy@01c19400 {
+			usb1_vbus-supply = <&reg_usb1_vbus>;
+			status = "okay";
+		};
+
+		ehci0: usb@01c1a000 {
+			status = "okay";
+		};
+
+		ohci0: usb@01c1a400 {
+			status = "okay";
+		};
+
+		pio: pinctrl@01c20800 {
+			mmc0_pins_a: mmc0@0 {
+				/* external pull-ups missing for some pins */
+				allwinner,pull = <1>;
+			};
+
+			mmc0_cd_pin_hummingbird: mmc0_cd_pin@0 {
+				allwinner,pins = "PA8";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <1>;
+			};
+
+			usb1_vbus_pin_a: usb1_vbus_pin@0 {
+				allwinner,pins = "PH24";
+				allwinner,function = "gpio_out";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+		};
+
+		uart0: serial@01c28000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins_a>;
+			status = "okay";
+		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			/* pull-ups and devices require AXP221 DLDO3 */
+			status = "failed";
+		};
+
+		i2c1: i2c@01c2b000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c1_pins_a>;
+			status = "okay";
+		};
+
+		i2c2: i2c@01c2b400 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c2_pins_a>;
+			status = "okay";
+
+			pcf8563: rtc@51 {
+				compatible = "nxp,pcf8563";
+				reg = <0x51>;
+			};
+		};
+
+		gmac: ethernet@01c30000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&gmac_pins_rgmii_a>;
+			phy = <&phy1>;
+			phy-mode = "rgmii";
+			status = "okay";
+
+			phy1: ethernet-phy@1 {
+				reg = <1>;
+			};
+		};
+	};
+
+	reg_usb1_vbus: usb1-vbus {
+		pinctrl-0 = <&usb1_vbus_pin_a>;
+		gpio = <&pio 7 24 0>; /* PH24 */
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -66,6 +66,12 @@
 			};
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
@@ -76,6 +82,16 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupt-parent = <&nmi_intc>;
+				interrupts = <0 8>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 
 		i2c1: i2c@01c2b000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts	2014-09-28 17:29:07.000000000 -0400
@@ -100,6 +100,12 @@
 			status = "okay";
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
@@ -110,6 +116,16 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupt-parent = <&nmi_intc>;
+				interrupts = <0 8>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 
 		i2c1: i2c@01c2b000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -586,7 +586,7 @@
 			clocks = <&apb0_gates 5>;
 			gpio-controller;
 			interrupt-controller;
-			#address-cells = <1>;
+			#interrupt-cells = <2>;
 			#size-cells = <0>;
 			#gpio-cells = <3>;
 
@@ -738,6 +738,20 @@
 				allwinner,drive = <2>;
 				allwinner,pull = <0>;
 			};
+
+			ir0_pins_a: ir0@0 {
+				    allwinner,pins = "PB3","PB4";
+				    allwinner,function = "ir0";
+				    allwinner,drive = <0>;
+				    allwinner,pull = <0>;
+			};
+
+			ir1_pins_a: ir1@0 {
+				    allwinner,pins = "PB22","PB23";
+				    allwinner,function = "ir1";
+				    allwinner,drive = <0>;
+				    allwinner,pull = <0>;
+			};
 		};
 
 		timer@01c20c00 {
@@ -771,6 +785,24 @@
 			status = "disabled";
 		};
 
+		ir0: ir@01c21800 {
+			compatible = "allwinner,sun4i-a10-ir";
+			clocks = <&apb0_gates 6>, <&ir0_clk>;
+			clock-names = "apb", "ir";
+			interrupts = <0 5 4>;
+			reg = <0x01c21800 0x40>;
+			status = "disabled";
+		};
+
+		ir1: ir@01c21c00 {
+			compatible = "allwinner,sun4i-a10-ir";
+			clocks = <&apb0_gates 7>, <&ir1_clk>;
+			clock-names = "apb", "ir";
+			interrupts = <0 6 4>;
+			reg = <0x01c21c00 0x40>;
+			status = "disabled";
+		};
+
 		sid: eeprom@01c23800 {
 			compatible = "allwinner,sun7i-a20-sid";
 			reg = <0x01c23800 0x200>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts	2014-09-28 17:29:07.000000000 -0400
@@ -94,12 +94,34 @@
 			};
 		};
 
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
 		uart0: serial@01c28000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart0_pins_a>;
 			status = "okay";
 		};
 
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupt-parent = <&nmi_intc>;
+				interrupts = <0 8>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+
 		gmac: ethernet@01c50000 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&gmac_pins_mii_a>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts	2014-09-28 17:29:07.000000000 -0400
@@ -122,6 +122,16 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&i2c0_pins_a>;
 			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupt-parent = <&nmi_intc>;
+				interrupts = <0 8>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
 		};
 
 		i2c1: i2c@01c2b000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-pcduino3.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun7i-a20-pcduino3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun7i-a20-pcduino3.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2014 Zoltan HERPAI
+ * Zoltan HERPAI <wigyori@uid0.hu>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "LinkSprite pcDuino3";
+	compatible = "linksprite,pcduino3", "allwinner,sun7i-a20";
+
+	soc@01c00000 {
+		mmc0: mmc@01c0f000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+			vmmc-supply = <&reg_vcc3v3>;
+			bus-width = <4>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			cd-inverted;
+			status = "okay";
+		};
+
+		usbphy: phy@01c13400 {
+			usb1_vbus-supply = <&reg_usb1_vbus>;
+			usb2_vbus-supply = <&reg_usb2_vbus>;
+			status = "okay";
+		};
+
+		ehci0: usb@01c14000 {
+			status = "okay";
+		};
+
+		ohci0: usb@01c14400 {
+			status = "okay";
+		};
+
+		ahci: sata@01c18000 {
+			target-supply = <&reg_ahci_5v>;
+			status = "okay";
+		};
+
+		ehci1: usb@01c1c000 {
+			status = "okay";
+		};
+
+		ohci1: usb@01c1c400 {
+			status = "okay";
+		};
+
+		pinctrl@01c20800 {
+			ahci_pwr_pin_a: ahci_pwr_pin@0 {
+				allwinner,pins = "PH2";
+			};
+
+			led_pins_pcduino3: led_pins@0 {
+				allwinner,pins = "PH15", "PH16";
+				allwinner,function = "gpio_out";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			key_pins_pcduino3: key_pins@0 {
+				allwinner,pins = "PH17", "PH18", "PH19";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+		};
+
+		ir0: ir@01c21800 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&ir0_pins_a>;
+			status = "okay";
+		};
+
+		uart0: serial@01c28000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins_a>;
+			status = "okay";
+		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+
+			axp209: pmic@34 {
+				compatible = "x-powers,axp209";
+				reg = <0x34>;
+				interrupt-parent = <&nmi_intc>;
+				interrupts = <0 8>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		gmac: ethernet@01c50000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&gmac_pins_mii_a>;
+			phy = <&phy1>;
+			phy-mode = "mii";
+			status = "okay";
+
+			phy1: ethernet-phy@1 {
+				reg = <1>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_pcduino3>;
+
+		tx {
+			label = "pcduino3:green:tx";
+			gpios = <&pio 7 15 GPIO_ACTIVE_LOW>;
+		};
+
+		rx {
+			label = "pcduino3:green:rx";
+			gpios = <&pio 7 16 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&key_pins_pcduino3>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		button@0 {
+			label = "Key Back";
+			linux,code = <KEY_BACK>;
+			gpios = <&pio 7 17 GPIO_ACTIVE_LOW>;
+		};
+		button@1 {
+			label = "Key Home";
+			linux,code = <KEY_HOME>;
+			gpios = <&pio 7 18 GPIO_ACTIVE_LOW>;
+		};
+		button@2 {
+			label = "Key Menu";
+			linux,code = <KEY_MENU>;
+			gpios = <&pio 7 19 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	reg_usb1_vbus: usb1-vbus {
+		status = "okay";
+	};
+
+	reg_usb2_vbus: usb2-vbus {
+		status = "okay";
+	};
+
+	reg_ahci_5v: ahci-5v {
+		gpio = <&pio 7 2 0>;
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun8i-a23.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun8i-a23.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun8i-a23.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun8i-a23.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &r_uart;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a7";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a7";
+			device_type = "cpu";
+			reg = <1>;
+		};
+	};
+
+	memory {
+		reg = <0x40000000 0x40000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		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";
+		};
+
+		pll1: clk@01c20000 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a23-pll1-clk";
+			reg = <0x01c20000 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll1";
+		};
+
+		/* dummy clock until actually implemented */
+		pll6: pll6_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <600000000>;
+			clock-output-names = "pll6";
+		};
+
+		cpu: cpu_clk@01c20050 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-cpu-clk";
+			reg = <0x01c20050 0x4>;
+
+			/*
+			 * PLL1 is listed twice here.
+			 * While it looks suspicious, it's actually documented
+			 * that way both in the datasheet and in the code from
+			 * Allwinner.
+			 */
+			clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
+			clock-output-names = "cpu";
+		};
+
+		axi: axi_clk@01c20050 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a23-axi-clk";
+			reg = <0x01c20050 0x4>;
+			clocks = <&cpu>;
+			clock-output-names = "axi";
+		};
+
+		ahb1_mux: ahb1_mux_clk@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
+			clock-output-names = "ahb1_mux";
+		};
+
+		ahb1: ahb1_clk@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-ahb-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&ahb1_mux>;
+			clock-output-names = "ahb1";
+		};
+
+		apb1: apb1_clk@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-apb0-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&ahb1>;
+			clock-output-names = "apb1";
+		};
+
+		ahb1_gates: clk@01c20060 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
+			reg = <0x01c20060 0x8>;
+			clocks = <&ahb1>;
+			clock-output-names = "ahb1_mipidsi", "ahb1_dma",
+					"ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
+					"ahb1_nand", "ahb1_sdram",
+					"ahb1_hstimer", "ahb1_spi0",
+					"ahb1_spi1", "ahb1_otg", "ahb1_ehci",
+					"ahb1_ohci", "ahb1_ve", "ahb1_lcd",
+					"ahb1_csi", "ahb1_be",	"ahb1_fe",
+					"ahb1_gpu", "ahb1_spinlock",
+					"ahb1_drc";
+		};
+
+		apb1_gates: clk@01c20068 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun8i-a23-apb1-gates-clk";
+			reg = <0x01c20068 0x4>;
+			clocks = <&apb1>;
+			clock-output-names = "apb1_codec", "apb1_pio",
+					"apb1_daudio0",	"apb1_daudio1";
+		};
+
+		apb2_mux: apb2_mux_clk@01c20058 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-apb1-mux-clk";
+			reg = <0x01c20058 0x4>;
+			clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+			clock-output-names = "apb2_mux";
+		};
+
+		apb2: apb2_clk@01c20058 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun6i-a31-apb2-div-clk";
+			reg = <0x01c20058 0x4>;
+			clocks = <&apb2_mux>;
+			clock-output-names = "apb2";
+		};
+
+		apb2_gates: clk@01c2006c {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun8i-a23-apb2-gates-clk";
+			reg = <0x01c2006c 0x4>;
+			clocks = <&apb2>;
+			clock-output-names = "apb2_i2c0", "apb2_i2c1",
+					"apb2_i2c2", "apb2_uart0",
+					"apb2_uart1", "apb2_uart2",
+					"apb2_uart3", "apb2_uart4";
+		};
+	};
+
+	soc@01c00000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ahb1_rst: reset@01c202c0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x01c202c0 0xc>;
+		};
+
+		apb1_rst: reset@01c202d0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x01c202d0 0x4>;
+		};
+
+		apb2_rst: reset@01c202d8 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x01c202d8 0x4>;
+		};
+
+		timer@01c20c00 {
+			compatible = "allwinner,sun4i-a10-timer";
+			reg = <0x01c20c00 0xa0>;
+			interrupts = <0 18 4>,
+				     <0 19 4>;
+			clocks = <&osc24M>;
+		};
+
+		wdt0: watchdog@01c20ca0 {
+			compatible = "allwinner,sun6i-a31-wdt";
+			reg = <0x01c20ca0 0x20>;
+			interrupts = <0 25 4>;
+		};
+
+		uart0: serial@01c28000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28000 0x400>;
+			interrupts = <0 0 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb2_gates 16>;
+			resets = <&apb2_rst 16>;
+			status = "disabled";
+		};
+
+		uart1: serial@01c28400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28400 0x400>;
+			interrupts = <0 1 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb2_gates 17>;
+			resets = <&apb2_rst 17>;
+			status = "disabled";
+		};
+
+		uart2: serial@01c28800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28800 0x400>;
+			interrupts = <0 2 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb2_gates 18>;
+			resets = <&apb2_rst 18>;
+			status = "disabled";
+		};
+
+		uart3: serial@01c28c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28c00 0x400>;
+			interrupts = <0 3 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb2_gates 19>;
+			resets = <&apb2_rst 19>;
+			status = "disabled";
+		};
+
+		uart4: serial@01c29000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c29000 0x400>;
+			interrupts = <0 4 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb2_gates 20>;
+			resets = <&apb2_rst 20>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@01c81000 {
+			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+			reg = <0x01c81000 0x1000>,
+			      <0x01c82000 0x1000>,
+			      <0x01c84000 0x2000>,
+			      <0x01c86000 0x2000>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			interrupts = <1 9 0xf04>;
+		};
+
+		prcm@01f01400 {
+			compatible = "allwinner,sun8i-a23-prcm";
+			reg = <0x01f01400 0x200>;
+
+			ar100: ar100_clk {
+				compatible = "fixed-factor-clock";
+				#clock-cells = <0>;
+				clock-div = <1>;
+				clock-mult = <1>;
+				clocks = <&osc24M>;
+				clock-output-names = "ar100";
+			};
+
+			ahb0: ahb0_clk {
+				compatible = "fixed-factor-clock";
+				#clock-cells = <0>;
+				clock-div = <1>;
+				clock-mult = <1>;
+				clocks = <&ar100>;
+				clock-output-names = "ahb0";
+			};
+
+			apb0: apb0_clk {
+				compatible = "allwinner,sun8i-a23-apb0-clk";
+				#clock-cells = <0>;
+				clocks = <&ahb0>;
+				clock-output-names = "apb0";
+			};
+
+			apb0_gates: apb0_gates_clk {
+				compatible = "allwinner,sun8i-a23-apb0-gates-clk";
+				#clock-cells = <1>;
+				clocks = <&apb0>;
+				clock-output-names = "apb0_pio", "apb0_timer",
+						"apb0_rsb", "apb0_uart",
+						"apb0_i2c";
+			};
+
+			apb0_rst: apb0_rst {
+				compatible = "allwinner,sun6i-a31-clock-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		r_uart: serial@01f02800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01f02800 0x400>;
+			interrupts = <0 38 4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb0_gates 4>;
+			resets = <&apb0_rst 4>;
+			status = "disabled";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun8i-a23.dtsi"
+
+/ {
+	model = "Ippo Q8H Dual Core Tablet (v5)";
+	compatible = "ippo,q8h-v5", "allwinner,sun8i-a23";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS0,115200";
+	};
+
+	soc@01c00000 {
+		r_uart: serial@01f02800 {
+			status = "okay";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra114.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra114.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra114.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra114.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -220,6 +220,12 @@
 		interrupt-controller;
 	};
 
+	apbmisc@70000800 {
+		compatible = "nvidia,tegra114-apbmisc", "nvidia,tegra20-apbmisc";
+		reg = <0x70000800 0x64   /* Chip revision */
+		       0x70000008 0x04>; /* Strapping options */
+	};
+
 	pinmux: pinmux@70000868 {
 		compatible = "nvidia,tegra114-pinmux";
 		reg = <0x70000868 0x148		/* Pad control registers */
@@ -485,6 +491,15 @@
 		clock-names = "pclk", "clk32k_in";
 	};
 
+	fuse@7000f800 {
+		compatible = "nvidia,tegra114-efuse";
+		reg = <0x7000f800 0x400>;
+		clocks = <&tegra_car TEGRA114_CLK_FUSE>;
+		clock-names = "fuse";
+		resets = <&tegra_car 39>;
+		reset-names = "fuse";
+	};
+
 	iommu@70019010 {
 		compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
 		reg = <0x70019010 0x02c
@@ -657,6 +672,8 @@
 			 <&tegra_car TEGRA114_CLK_PLL_U>,
 			 <&tegra_car TEGRA114_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 22>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
@@ -667,6 +684,7 @@
 		nvidia,hssquelch-level = <2>;
 		nvidia,hsdiscon-level = <5>;
 		nvidia,xcvr-hsslew = <12>;
+		nvidia,has-utmi-pad-registers;
 		status = "disabled";
 	};
 
@@ -690,6 +708,8 @@
 			 <&tegra_car TEGRA114_CLK_PLL_U>,
 			 <&tegra_car TEGRA114_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 59>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra114-roth.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra114-roth.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra114-roth.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra114-roth.dts	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,22 @@
 		reg = <0x80000000 0x79600000>;
 	};
 
+	host1x@50000000 {
+		dsi@54300000 {
+			status = "okay";
+
+			vdd-supply = <&vdd_1v2_ap>;
+
+			panel@0 {
+				compatible = "lg,lh500wx1-sd03";
+				reg = <0>;
+
+				power-supply = <&vdd_lcd>;
+				backlight = <&backlight>;
+			};
+		};
+	};
+
 	pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -244,7 +260,7 @@
 				nvidia,function = "sdmmc1";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
-				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 			};
 			sdmmc1_cmd_pz1 {
 				nvidia,pins = "sdmmc1_cmd_pz1",
@@ -262,7 +278,7 @@
 				nvidia,function = "sdmmc3";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
-				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 			};
 			sdmmc3_cmd_pa7 {
 				nvidia,pins = "sdmmc3_cmd_pa7",
@@ -290,7 +306,7 @@
 				nvidia,function = "sdmmc4";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
-				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 			};
 			sdmmc4_cmd_pt7 {
 				nvidia,pins = "sdmmc4_cmd_pt7",
@@ -730,7 +746,6 @@
 				nvidia,pins = "drive_sdio1";
 				nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
 				nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-				nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
 				nvidia,pull-down-strength = <36>;
 				nvidia,pull-up-strength = <20>;
 				nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOW>;
@@ -740,7 +755,6 @@
 				nvidia,pins = "drive_sdio3";
 				nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
 				nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-				nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
 				nvidia,pull-down-strength = <36>;
 				nvidia,pull-up-strength = <20>;
 				nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
@@ -750,12 +764,10 @@
 				nvidia,pins = "drive_gma";
 				nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
 				nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-				nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
 				nvidia,pull-down-strength = <2>;
 				nvidia,pull-up-strength = <2>;
 				nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
 				nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>;
-				nvidia,drive-type = <1>;
 			};
 		};
 	};
@@ -815,7 +827,6 @@
 						regulator-name = "vdd-1v8";
 						regulator-min-microvolt = <1800000>;
 						regulator-max-microvolt = <1800000>;
-						regulator-always-on;
 						regulator-boot-on;
 					};
 
@@ -862,10 +873,11 @@
 						regulator-name = "vdd-2v8-display";
 						regulator-min-microvolt = <2800000>;
 						regulator-max-microvolt = <2800000>;
+						regulator-always-on;
 						regulator-boot-on;
 					};
 
-					ldo3 {
+					vdd_1v2_ap: ldo3 {
 						regulator-name = "avdd-1v2";
 						regulator-min-microvolt = <1200000>;
 						regulator-max-microvolt = <1200000>;
@@ -1052,7 +1064,7 @@
 			regulator-boot-on;
 		};
 
-		regulator@1 {
+		vdd_lcd: regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "vdd_lcd_1v8";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
 #include <dt-bindings/clock/tegra124-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #include "skeleton.dtsi"
@@ -102,6 +103,21 @@
 			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
+	gpu@0,57000000 {
+		compatible = "nvidia,gk20a";
+		reg = <0x0 0x57000000 0x0 0x01000000>,
+		      <0x0 0x58000000 0x0 0x01000000>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "stall", "nonstall";
+		clocks = <&tegra_car TEGRA124_CLK_GPU>,
+			 <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
+		clock-names = "gpu", "pwr";
+		resets = <&tegra_car 184>;
+		reset-names = "gpu";
+		status = "disabled";
+	};
+
 	timer@0,60005000 {
 		compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
@@ -179,6 +195,12 @@
 		#dma-cells = <1>;
 	};
 
+	apbmisc@0,70000800 {
+		compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc";
+		reg = <0x0 0x70000800 0x0 0x64>,   /* Chip revision */
+		      <0x0 0x7000E864 0x0 0x04>;   /* Strapping options */
+	};
+
 	pinmux: pinmux@0,70000868 {
 		compatible = "nvidia,tegra124-pinmux";
 		reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
@@ -449,6 +471,39 @@
 		clock-names = "pclk", "clk32k_in";
 	};
 
+	fuse@0,7000f800 {
+		compatible = "nvidia,tegra124-efuse";
+		reg = <0x0 0x7000f800 0x0 0x400>;
+		clocks = <&tegra_car TEGRA124_CLK_FUSE>;
+		clock-names = "fuse";
+		resets = <&tegra_car 39>;
+		reset-names = "fuse";
+	};
+
+	hda@0,70030000 {
+		compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
+		reg = <0x0 0x70030000 0x0 0x10000>;
+		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_HDA>,
+		         <&tegra_car TEGRA124_CLK_HDA2HDMI>,
+			 <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>;
+		clock-names = "hda", "hda2hdmi", "hdacodec_2x";
+		resets = <&tegra_car 125>, /* hda */
+			 <&tegra_car 128>, /* hda2hdmi */
+			 <&tegra_car 111>; /* hda2codec_2x */
+		reset-names = "hda", "hda2hdmi", "hdacodec_2x";
+		status = "disabled";
+	};
+
+	padctl: padctl@0,7009f000 {
+		compatible = "nvidia,tegra124-xusb-padctl";
+		reg = <0x0 0x7009f000 0x0 0x1000>;
+		resets = <&tegra_car 142>;
+		reset-names = "padctl";
+
+		#phy-cells = <1>;
+	};
+
 	sdhci@0,700b0000 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0000 0x0 0x200>;
@@ -613,6 +668,8 @@
 			 <&tegra_car TEGRA124_CLK_PLL_U>,
 			 <&tegra_car TEGRA124_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 59>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
@@ -647,6 +704,8 @@
 			 <&tegra_car TEGRA124_CLK_PLL_U>,
 			 <&tegra_car TEGRA124_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 22>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
@@ -657,6 +716,7 @@
 		nvidia,hssquelch-level = <2>;
 		nvidia,hsdiscon-level = <5>;
 		nvidia,xcvr-hsslew = <12>;
+		nvidia,has-utmi-pad-registers;
 		status = "disabled";
 	};
 
@@ -681,6 +741,8 @@
 			 <&tegra_car TEGRA124_CLK_PLL_U>,
 			 <&tegra_car TEGRA124_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 58>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts	2014-09-28 17:29:07.000000000 -0400
@@ -1461,7 +1461,7 @@
 					regulator-max-microamp = <3500000>;
 					regulator-always-on;
 					regulator-boot-on;
-					ams,external-control = <2>;
+					ams,ext-control = <2>;
 				};
 
 				sd1 {
@@ -1472,7 +1472,7 @@
 					regulator-max-microamp = <2500000>;
 					regulator-always-on;
 					regulator-boot-on;
-					ams,external-control = <1>;
+					ams,ext-control = <1>;
 				};
 
 				vdd_1v35_lp0: sd2 {
@@ -1521,7 +1521,7 @@
 					regulator-max-microvolt = <1050000>;
 					regulator-boot-on;
 					regulator-always-on;
-					ams,external-control = <1>;
+					ams,ext-control = <1>;
 				};
 
 				ldo1 {
@@ -1619,6 +1619,32 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	padctl@0,7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		padctl_default: pinmux {
+			usb3 {
+				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+			};
+
+			pcie {
+				nvidia,lanes = "pcie-2", "pcie-3",
+					       "pcie-4";
+				nvidia,function = "pcie";
+				nvidia,iddq = <0>;
+			};
+
+			sata {
+				nvidia,lanes = "sata-0";
+				nvidia,function = "sata";
+				nvidia,iddq = <0>;
+			};
+		};
+	};
+
 	/* SD card */
 	sdhci@0,700b0400 {
 		status = "okay";
@@ -1633,6 +1659,7 @@
 	sdhci@0,700b0600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
 	};
 
 	ahub@0,70300000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124-venice2.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124-venice2.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra124-venice2.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra124-venice2.dts	2014-09-28 17:29:07.000000000 -0400
@@ -682,7 +682,7 @@
 					regulator-max-microamp = <3500000>;
 					regulator-always-on;
 					regulator-boot-on;
-					ams,external-control = <2>;
+					ams,ext-control = <2>;
 				};
 
 				sd1 {
@@ -693,7 +693,7 @@
 					regulator-max-microamp = <2500000>;
 					regulator-always-on;
 					regulator-boot-on;
-					ams,external-control = <1>;
+					ams,ext-control = <1>;
 				};
 
 				vdd_1v35_lp0: sd2 {
@@ -742,7 +742,7 @@
 					regulator-max-microvolt = <1050000>;
 					regulator-boot-on;
 					regulator-always-on;
-					ams,external-control = <1>;
+					ams,ext-control = <1>;
 				};
 
 				ldo1 {
@@ -816,7 +816,7 @@
 	spi@0,7000d400 {
 		status = "okay";
 
-		cros-ec@0 {
+		cros_ec: cros-ec@0 {
 			compatible = "google,cros-ec-spi";
 			spi-max-frequency = <4000000>;
 			interrupt-parent = <&gpio>;
@@ -825,96 +825,30 @@
 
 			google,cros-ec-spi-msg-delay = <2000>;
 
-			cros-ec-keyb {
-				compatible = "google,cros-ec-keyb";
-				keypad,num-rows = <8>;
-				keypad,num-columns = <13>;
-				google,needs-ghost-filter;
-
-				linux,keymap = <
-					MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
-					MATRIX_KEY(0x00, 0x02, KEY_F1)
-					MATRIX_KEY(0x00, 0x03, KEY_B)
-					MATRIX_KEY(0x00, 0x04, KEY_F10)
-					MATRIX_KEY(0x00, 0x06, KEY_N)
-					MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
-					MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
-
-					MATRIX_KEY(0x01, 0x01, KEY_ESC)
-					MATRIX_KEY(0x01, 0x02, KEY_F4)
-					MATRIX_KEY(0x01, 0x03, KEY_G)
-					MATRIX_KEY(0x01, 0x04, KEY_F7)
-					MATRIX_KEY(0x01, 0x06, KEY_H)
-					MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
-					MATRIX_KEY(0x01, 0x09, KEY_F9)
-					MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
-
-					MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
-					MATRIX_KEY(0x02, 0x01, KEY_TAB)
-					MATRIX_KEY(0x02, 0x02, KEY_F3)
-					MATRIX_KEY(0x02, 0x03, KEY_T)
-					MATRIX_KEY(0x02, 0x04, KEY_F6)
-					MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
-					MATRIX_KEY(0x02, 0x06, KEY_Y)
-					MATRIX_KEY(0x02, 0x07, KEY_102ND)
-					MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
-					MATRIX_KEY(0x02, 0x09, KEY_F8)
-
-					MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
-					MATRIX_KEY(0x03, 0x02, KEY_F2)
-					MATRIX_KEY(0x03, 0x03, KEY_5)
-					MATRIX_KEY(0x03, 0x04, KEY_F5)
-					MATRIX_KEY(0x03, 0x06, KEY_6)
-					MATRIX_KEY(0x03, 0x08, KEY_MINUS)
-					MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
-
-					MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
-					MATRIX_KEY(0x04, 0x01, KEY_A)
-					MATRIX_KEY(0x04, 0x02, KEY_D)
-					MATRIX_KEY(0x04, 0x03, KEY_F)
-					MATRIX_KEY(0x04, 0x04, KEY_S)
-					MATRIX_KEY(0x04, 0x05, KEY_K)
-					MATRIX_KEY(0x04, 0x06, KEY_J)
-					MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
-					MATRIX_KEY(0x04, 0x09, KEY_L)
-					MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
-					MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
+			i2c-tunnel {
+				compatible = "google,cros-ec-i2c-tunnel";
+				#address-cells = <1>;
+				#size-cells = <0>;
 
-					MATRIX_KEY(0x05, 0x01, KEY_Z)
-					MATRIX_KEY(0x05, 0x02, KEY_C)
-					MATRIX_KEY(0x05, 0x03, KEY_V)
-					MATRIX_KEY(0x05, 0x04, KEY_X)
-					MATRIX_KEY(0x05, 0x05, KEY_COMMA)
-					MATRIX_KEY(0x05, 0x06, KEY_M)
-					MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
-					MATRIX_KEY(0x05, 0x08, KEY_SLASH)
-					MATRIX_KEY(0x05, 0x09, KEY_DOT)
-					MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
+				google,remote-bus = <0>;
 
-					MATRIX_KEY(0x06, 0x01, KEY_1)
-					MATRIX_KEY(0x06, 0x02, KEY_3)
-					MATRIX_KEY(0x06, 0x03, KEY_4)
-					MATRIX_KEY(0x06, 0x04, KEY_2)
-					MATRIX_KEY(0x06, 0x05, KEY_8)
-					MATRIX_KEY(0x06, 0x06, KEY_7)
-					MATRIX_KEY(0x06, 0x08, KEY_0)
-					MATRIX_KEY(0x06, 0x09, KEY_9)
-					MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
-					MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
-					MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
+				charger: bq24735@9 {
+					compatible = "ti,bq24735";
+					reg = <0x9>;
+					interrupt-parent = <&gpio>;
+					interrupts = <TEGRA_GPIO(J, 0)
+							GPIO_ACTIVE_HIGH>;
+					ti,ac-detect-gpios = <&gpio
+							TEGRA_GPIO(J, 0)
+							GPIO_ACTIVE_HIGH>;
+				};
 
-					MATRIX_KEY(0x07, 0x01, KEY_Q)
-					MATRIX_KEY(0x07, 0x02, KEY_E)
-					MATRIX_KEY(0x07, 0x03, KEY_R)
-					MATRIX_KEY(0x07, 0x04, KEY_W)
-					MATRIX_KEY(0x07, 0x05, KEY_I)
-					MATRIX_KEY(0x07, 0x06, KEY_U)
-					MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
-					MATRIX_KEY(0x07, 0x08, KEY_P)
-					MATRIX_KEY(0x07, 0x09, KEY_O)
-					MATRIX_KEY(0x07, 0x0b, KEY_UP)
-					MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
-				>;
+				battery: sbs-battery@b {
+					compatible = "sbs,sbs-battery";
+					reg = <0xb>;
+					sbs,i2c-retry-count = <2>;
+					sbs,poll-retry-count = <1>;
+				};
 			};
 		};
 	};
@@ -940,6 +874,10 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	hda@0,70030000 {
+		status = "okay";
+	};
+
 	sdhci@0,700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -1205,3 +1143,5 @@
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
+
+#include "cros-ec-keyboard.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -236,6 +236,12 @@
 		interrupt-controller;
 	};
 
+	apbmisc@70000800 {
+		compatible = "nvidia,tegra20-apbmisc";
+		reg = <0x70000800 0x64   /* Chip revision */
+		       0x70000008 0x04>; /* Strapping options */
+	};
+
 	pinmux: pinmux@70000014 {
 		compatible = "nvidia,tegra20-pinmux";
 		reg = <0x70000014 0x10   /* Tri-state registers */
@@ -545,6 +551,15 @@
 		#size-cells = <0>;
 	};
 
+	fuse@7000f800 {
+		compatible = "nvidia,tegra20-efuse";
+		reg = <0x7000F800 0x400>;
+		clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+		clock-names = "fuse";
+		resets = <&tegra_car 39>;
+		reset-names = "fuse";
+	};
+
 	pcie-controller@80003000 {
 		compatible = "nvidia,tegra20-pcie";
 		device_type = "pci";
@@ -630,6 +645,8 @@
 			 <&tegra_car TEGRA20_CLK_CLK_M>,
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
+		resets = <&tegra_car 22>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,has-legacy-mode;
 		nvidia,hssync-start-delay = <9>;
 		nvidia,idle-wait-delay = <17>;
@@ -638,6 +655,7 @@
 		nvidia,xcvr-setup = <9>;
 		nvidia,xcvr-lsfslew = <1>;
 		nvidia,xcvr-lsrslew = <1>;
+		nvidia,has-utmi-pad-registers;
 		status = "disabled";
 	};
 
@@ -661,6 +679,8 @@
 			 <&tegra_car TEGRA20_CLK_PLL_U>,
 			 <&tegra_car TEGRA20_CLK_CDEV2>;
 		clock-names = "reg", "pll_u", "ulpi-link";
+		resets = <&tegra_car 58>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		status = "disabled";
 	};
 
@@ -685,6 +705,8 @@
 			 <&tegra_car TEGRA20_CLK_CLK_M>,
 			 <&tegra_car TEGRA20_CLK_USBD>;
 		clock-names = "reg", "pll_u", "timer", "utmi-pads";
+		resets = <&tegra_car 59>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <9>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-harmony.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-harmony.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-harmony.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-harmony.dts	2014-09-28 17:29:07.000000000 -0400
@@ -562,10 +562,14 @@
 	};
 
 	pcie-controller@80003000 {
-		pex-clk-supply = <&pci_clk_reg>;
-		vdd-supply = <&pci_vdd_reg>;
 		status = "okay";
 
+		avdd-pex-supply = <&pci_vdd_reg>;
+		vdd-pex-supply = <&pci_vdd_reg>;
+		avdd-pex-pll-supply = <&pci_vdd_reg>;
+		avdd-plle-supply = <&pci_vdd_reg>;
+		vddio-pex-clk-supply = <&pci_clk_reg>;
+
 		pci@1,0 {
 			status = "okay";
 		};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,15 @@
 		status = "okay";
 	};
 
+	host1x@50000000 {
+		dc@54200000 {
+			rgb {
+				status = "okay";
+				nvidia,panel = <&panel>;
+			};
+		};
+	};
+
 	i2c@7000c000 {
 		wm8903: wm8903@1a {
 			compatible = "wlf,wm8903";
@@ -30,7 +39,7 @@
 		};
 	};
 
-	backlight {
+	backlight: backlight {
 		compatible = "pwm-backlight";
 		pwms = <&pwm 0 5000000>;
 
@@ -38,6 +47,15 @@
 		default-brightness-level = <6>;
 	};
 
+	panel: panel {
+		compatible = "innolux,n156bge-l21", "simple-panel";
+
+		power-supply =  <&vdd_1v8_reg>, <&vdd_3v3_reg>;
+		enable-gpios = <&gpio TEGRA_GPIO(B, 2) GPIO_ACTIVE_HIGH>;
+
+		backlight = <&backlight>;
+	};
+
 	sound {
 		compatible = "ad,tegra-audio-wm8903-medcom-wide",
 			     "nvidia,tegra-audio-wm8903";
@@ -64,4 +82,45 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	regulators {
+		vcc_24v_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			reg = <100>;
+			regulator-name = "vcc_24v";
+			regulator-min-microvolt = <24000000>;
+			regulator-max-microvolt = <24000000>;
+			regulator-always-on;
+		};
+
+		vdd_5v0_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "vdd_5v0";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		vdd_3v3_reg: regulator@102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "vdd_3v3";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		vdd_1v8_reg: regulator@103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "vdd_1v8";
+			vin-supply = <&vdd_3v3_reg>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-paz00.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-paz00.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-paz00.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-paz00.dts	2014-09-28 17:29:07.000000000 -0400
@@ -296,7 +296,7 @@
 		request-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		slave-addr = <138>;
 		clocks = <&tegra_car TEGRA20_CLK_I2C3>,
-		       	 <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
+		         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
 		clock-names = "div-clk", "fast-clk";
 		resets = <&tegra_car 67>;
 		reset-names = "i2c";
@@ -589,8 +589,8 @@
 			GPIO_ACTIVE_HIGH>;
 
 		clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
-		       	 <&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
-			 <&tegra_car TEGRA20_CLK_CDEV1>;
+		         <&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
+		         <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-plutux.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-plutux.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-plutux.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-plutux.dts	2014-09-28 17:29:07.000000000 -0400
@@ -58,4 +58,45 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	regulators {
+		vcc_24v_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			reg = <100>;
+			regulator-name = "vcc_24v";
+			regulator-min-microvolt = <24000000>;
+			regulator-max-microvolt = <24000000>;
+			regulator-always-on;
+		};
+
+		vdd_5v0_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "vdd_5v0";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		vdd_3v3_reg: regulator@102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "vdd_3v3";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		vdd_1v8_reg: regulator@103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "vdd_1v8";
+			vin-supply = <&vdd_3v3_reg>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -334,6 +334,7 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 
+			/* vdd_5v0_reg must be provided by the base board */
 			sys-supply = <&vdd_5v0_reg>;
 			vin-sm0-supply = <&sys_reg>;
 			vin-sm1-supply = <&sys_reg>;
@@ -473,8 +474,11 @@
 	};
 
 	pcie-controller@80003000 {
-		pex-clk-supply = <&pci_clk_reg>;
-		vdd-supply = <&pci_vdd_reg>;
+		avdd-pex-supply = <&pci_vdd_reg>;
+		vdd-pex-supply = <&pci_vdd_reg>;
+		avdd-pex-pll-supply = <&pci_vdd_reg>;
+		avdd-plle-supply = <&pci_vdd_reg>;
+		vddio-pex-clk-supply = <&pci_clk_reg>;
 	};
 
 	usb@c5008000 {
@@ -511,15 +515,6 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		vdd_5v0_reg: regulator@0 {
-			compatible = "regulator-fixed";
-			reg = <0>;
-			regulator-name = "vdd_5v0";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			regulator-always-on;
-		};
-
 		pci_vdd_reg: regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-tec.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-tec.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-tec.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-tec.dts	2014-09-28 17:29:07.000000000 -0400
@@ -67,4 +67,45 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	regulators {
+		vcc_24v_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			reg = <100>;
+			regulator-name = "vcc_24v";
+			regulator-min-microvolt = <24000000>;
+			regulator-max-microvolt = <24000000>;
+			regulator-always-on;
+		};
+
+		vdd_5v0_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "vdd_5v0";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		vdd_3v3_reg: regulator@102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "vdd_3v3";
+			vin-supply = <&vcc_24v_reg>;
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		vdd_1v8_reg: regulator@103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "vdd_1v8";
+			vin-supply = <&vdd_3v3_reg>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-trimslice.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-trimslice.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra20-trimslice.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra20-trimslice.dts	2014-09-28 17:29:07.000000000 -0400
@@ -318,8 +318,12 @@
 
 	pcie-controller@80003000 {
 		status = "okay";
-		pex-clk-supply = <&pci_clk_reg>;
-		vdd-supply = <&pci_vdd_reg>;
+
+		avdd-pex-supply = <&pci_vdd_reg>;
+		vdd-pex-supply = <&pci_vdd_reg>;
+		avdd-pex-pll-supply = <&pci_vdd_reg>;
+		avdd-plle-supply = <&pci_vdd_reg>;
+		vddio-pex-clk-supply = <&pci_clk_reg>;
 
 		pci@1,0 {
 			status = "okay";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,687 @@
+#include "tegra30.dtsi"
+
+/*
+ * Toradex Apalis T30 Device Tree
+ * Compatible for Revisions 1GB: V1.0A; 2GB: V1.0B, V1.0C
+ */
+/ {
+	model = "Toradex Apalis T30";
+	compatible = "toradex,apalis_t30", "nvidia,tegra30";
+
+	pcie-controller@00003000 {
+		avdd-pexa-supply = <&vdd2_reg>;
+		vdd-pexa-supply = <&vdd2_reg>;
+		avdd-pexb-supply = <&vdd2_reg>;
+		vdd-pexb-supply = <&vdd2_reg>;
+		avdd-pex-pll-supply = <&vdd2_reg>;
+		avdd-plle-supply = <&ldo6_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		hvdd-pex-supply = <&sys_3v3_reg>;
+
+		pci@1,0 {
+			nvidia,num-lanes = <4>;
+		};
+
+		pci@2,0 {
+			nvidia,num-lanes = <1>;
+		};
+
+		pci@3,0 {
+			nvidia,num-lanes = <1>;
+		};
+	};
+
+	host1x@50000000 {
+		hdmi@54280000 {
+			vdd-supply = <&sys_3v3_reg>;
+			pll-supply = <&vio_reg>;
+
+			nvidia,hpd-gpio =
+				<&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
+			nvidia,ddc-i2c-bus = <&hdmiddc>;
+		};
+	};
+
+	pinmux@70000868 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			/* Apalis BKL1_ON */
+			pv2 {
+				nvidia,pins = "pv2";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis BKL1_PWM */
+			uart3_rts_n_pc0 {
+				nvidia,pins =	"uart3_rts_n_pc0";
+				nvidia,function = "pwm0";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			/* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */
+			uart3_cts_n_pa1 {
+				nvidia,pins =	"uart3_cts_n_pa1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis CAN1 on SPI6 */
+			spi2_cs0_n_px3 {
+				nvidia,pins =   "spi2_cs0_n_px3",
+						"spi2_miso_px1",
+						"spi2_mosi_px0",
+						"spi2_sck_px2";
+				nvidia,function = "spi6";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			/* CAN_INT1 */
+			spi2_cs1_n_pw2 {
+				nvidia,pins = "spi2_cs1_n_pw2";
+				nvidia,function = "spi3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis CAN2 on SPI4 */
+			gmi_a16_pj7 {
+				nvidia,pins =   "gmi_a16_pj7",
+						"gmi_a17_pb0",
+						"gmi_a18_pb1",
+						"gmi_a19_pk7";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			/* CAN_INT2 */
+			spi2_cs2_n_pw3 {
+				nvidia,pins = "spi2_cs2_n_pw3";
+				nvidia,function = "spi3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis I2C3 */
+			cam_i2c_scl_pbb1 {
+				nvidia,pins = "cam_i2c_scl_pbb1",
+					      "cam_i2c_sda_pbb2";
+				nvidia,function = "i2c3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,lock = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis MMC1 */
+			sdmmc3_clk_pa6 {
+				nvidia,pins =	"sdmmc3_clk_pa6",
+						"sdmmc3_cmd_pa7";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_dat0_pb7 {
+				nvidia,pins =	"sdmmc3_dat0_pb7",
+						"sdmmc3_dat1_pb6",
+						"sdmmc3_dat2_pb5",
+						"sdmmc3_dat3_pb4",
+						"sdmmc3_dat4_pd1",
+						"sdmmc3_dat5_pd0",
+						"sdmmc3_dat6_pd3",
+						"sdmmc3_dat7_pd4";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			/* Apalis MMC1_CD# */
+			pv3 {
+				nvidia,pins = "pv3";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis PWM1 */
+			gpio_pu6 {
+				nvidia,pins =	"gpio_pu6";
+				nvidia,function = "pwm3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis PWM2 */
+			gpio_pu5 {
+				nvidia,pins =	"gpio_pu5";
+				nvidia,function = "pwm2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis PWM3 */
+			gpio_pu4 {
+				nvidia,pins =	"gpio_pu4";
+				nvidia,function = "pwm1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis PWM4 */
+			gpio_pu3 {
+				nvidia,pins =	"gpio_pu3";
+				nvidia,function = "pwm0";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis RESET_MOCI# */
+			gmi_rst_n_pi4 {
+				nvidia,pins = "gmi_rst_n_pi4";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis SD1 */
+			sdmmc1_clk_pz0 {
+				nvidia,pins = "sdmmc1_clk_pz0";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_cmd_pz1 {
+				nvidia,pins =	"sdmmc1_cmd_pz1",
+						"sdmmc1_dat0_py7",
+						"sdmmc1_dat1_py6",
+						"sdmmc1_dat2_py5",
+						"sdmmc1_dat3_py4";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			/* Apalis SD1_CD# */
+			clk2_req_pcc5 {
+				nvidia,pins = "clk2_req_pcc5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis SPI1 */
+			spi1_sck_px5 {
+				nvidia,pins =   "spi1_sck_px5",
+						"spi1_mosi_px4",
+						"spi1_miso_px7",
+						"spi1_cs0_n_px6";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis SPI2 */
+			lcd_sck_pz4 {
+				nvidia,pins =   "lcd_sck_pz4",
+						"lcd_sdout_pn5",
+						"lcd_sdin_pz2",
+						"lcd_cs0_n_pn4";
+				nvidia,function = "spi5";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis UART1 */
+			ulpi_data0 {
+				nvidia,pins =   "ulpi_data0_po1",
+						"ulpi_data1_po2",
+						"ulpi_data2_po3",
+						"ulpi_data3_po4",
+						"ulpi_data4_po5",
+						"ulpi_data5_po6",
+						"ulpi_data6_po7",
+						"ulpi_data7_po0";
+				nvidia,function = "uarta";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis UART2 */
+			ulpi_clk_py0 {
+				nvidia,pins =   "ulpi_clk_py0",
+						"ulpi_dir_py1",
+						"ulpi_nxt_py2",
+						"ulpi_stp_py3";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis UART3 */
+			uart2_rxd_pc3 {
+				nvidia,pins =   "uart2_rxd_pc3",
+						"uart2_txd_pc2";
+				nvidia,function = "uartb";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis UART4 */
+			uart3_rxd_pw7 {
+				nvidia,pins =   "uart3_rxd_pw7",
+						"uart3_txd_pw6";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis USBO1_EN */
+			gen2_i2c_scl_pt5 {
+				nvidia,pins = "gen2_i2c_scl_pt5";
+				nvidia,function = "rsvd4";
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Apalis USBO1_OC# */
+			gen2_i2c_sda_pt6 {
+				nvidia,pins = "gen2_i2c_sda_pt6";
+				nvidia,function = "rsvd4";
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* Apalis WAKE1_MICO */
+			pv1 {
+				nvidia,pins = "pv1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* eMMC (On-module) */
+			sdmmc4_clk_pcc4 {
+				nvidia,pins =	"sdmmc4_clk_pcc4",
+						"sdmmc4_rst_n_pcc3";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc4_dat0_paa0 {
+				nvidia,pins =	"sdmmc4_dat0_paa0",
+						"sdmmc4_dat1_paa1",
+						"sdmmc4_dat2_paa2",
+						"sdmmc4_dat3_paa3",
+						"sdmmc4_dat4_paa4",
+						"sdmmc4_dat5_paa5",
+						"sdmmc4_dat6_paa6",
+						"sdmmc4_dat7_paa7";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* LVDS Transceiver Configuration */
+			pbb0 {
+				nvidia,pins =	"pbb0",
+						"pbb7",
+						"pcc1",
+						"pcc2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,lock = <TEGRA_PIN_DISABLE>;
+			};
+			pbb3 {
+				nvidia,pins =	"pbb3",
+						"pbb4",
+						"pbb5",
+						"pbb6";
+				nvidia,function = "displayb";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,lock = <TEGRA_PIN_DISABLE>;
+			};
+
+			/* Power I2C (On-module) */
+			pwr_i2c_scl_pz6 {
+				nvidia,pins = "pwr_i2c_scl_pz6",
+					      "pwr_i2c_sda_pz7";
+				nvidia,function = "i2cpwr";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,lock = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+
+			/*
+			 * THERMD_ALERT#, unlatched I2C address pin of LM95245
+			 * temperature sensor therefore requires disabling for
+			 * now
+			 */
+			lcd_dc1_pd2 {
+				nvidia,pins = "lcd_dc1_pd2";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+
+			/* TOUCH_PEN_INT# */
+			pv0 {
+				nvidia,pins = "pv0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+		};
+	};
+
+	hdmiddc: i2c@7000c700 {
+		clock-frequency = <100000>;
+	};
+
+	/*
+	 * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+	 * touch screen controller
+	 */
+	i2c@7000d000 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		pmic: tps65911@2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&sys_3v3_reg>;
+			vcc2-supply = <&sys_3v3_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&sys_3v3_reg>;
+			vcc5-supply = <&sys_3v3_reg>;
+			vcc6-supply = <&vio_reg>;
+			vcc7-supply = <&charge_pump_5v0_reg>;
+			vccio-supply = <&sys_3v3_reg>;
+
+			regulators {
+				/* SW1: +V1.35_VDDIO_DDR */
+				vdd1_reg: vdd1 {
+					regulator-name = "vddio_ddr_1v35";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+				};
+
+				/* SW2: +V1.05 */
+				vdd2_reg: vdd2 {
+					regulator-name =
+						"vdd_pexa,vdd_pexb,vdd_sata";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* SW CTRL: +V1.0_VDD_CPU */
+				vddctrl_reg: vddctrl {
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1150000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-always-on;
+				};
+
+				/* SWIO: +V1.8 */
+				vio_reg: vio {
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				/* LDO1: unused */
+
+				/*
+				 * EN_+V3.3 switching via FET:
+				 * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
+				 * see also v3_3 fixed supply
+				 */
+				ldo2_reg: ldo2 {
+					regulator-name = "en_3v3";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				/* +V1.2_CSI */
+				ldo3_reg: ldo3 {
+					regulator-name =
+						"avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				/* +V1.2_VDD_RTC */
+				ldo4_reg: ldo4 {
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				/*
+				 * +V2.8_AVDD_VDAC:
+				 * only required for analog RGB
+				 */
+				ldo5_reg: ldo5 {
+					regulator-name = "avdd_vdac";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				/*
+				 * +V1.05_AVDD_PLLE: avdd_plle should be 1.05V
+				 * but LDO6 can't set voltage in 50mV
+				 * granularity
+				 */
+				ldo6_reg: ldo6 {
+					regulator-name = "avdd_plle";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+				};
+
+				/* +V1.2_AVDD_PLL */
+				ldo7_reg: ldo7 {
+					regulator-name = "avdd_pll";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				/* +V1.0_VDD_DDR_HS */
+				ldo8_reg: ldo8 {
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
+
+		/* STMPE811 touch screen controller */
+		stmpe811@41 {
+			compatible = "st,stmpe811";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x41>;
+			interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
+			interrupt-parent = <&gpio>;
+			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>;
+			};
+		};
+
+		/*
+		 * LM95245 temperature sensor
+		 * Note: OVERT_N directly connected to PMIC PWRDN
+		 */
+		temp-sensor@4c {
+			compatible = "national,lm95245";
+			reg = <0x4c>;
+		};
+
+		/* SW: +V1.2_VDD_CORE */
+		tps62362@60 {
+			compatible = "ti,tps62362";
+			reg = <0x60>;
+
+			regulator-name = "tps62362-vout";
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <1400000>;
+			regulator-boot-on;
+			regulator-always-on;
+			ti,vsel0-state-low;
+			/* VSEL1: EN_CORE_DVFS_N low for DVFS */
+			ti,vsel1-state-low;
+		};
+	};
+
+	/* SPI4: CAN2 */
+	spi@7000da00 {
+		status = "okay";
+		spi-max-frequency = <10000000>;
+
+		can@1 {
+			compatible = "microchip,mcp2515";
+			reg = <1>;
+			clocks = <&clk16m>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>;
+			spi-max-frequency = <10000000>;
+		};
+	};
+
+	/* SPI6: CAN1 */
+	spi@7000de00 {
+		status = "okay";
+		spi-max-frequency = <10000000>;
+
+		can@0 {
+			compatible = "microchip,mcp2515";
+			reg = <0>;
+			clocks = <&clk16m>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>;
+			spi-max-frequency = <10000000>;
+		};
+	};
+
+	pmc@7000e400 {
+		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <1>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <0>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
+	};
+
+	sdhci@78000600 {
+		status = "okay";
+		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clk@0 {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+		clk16m: clk@1 {
+			compatible = "fixed-clock";
+			reg=<1>;
+			#clock-cells = <0>;
+			clock-frequency = <16000000>;
+			clock-output-names = "clk16m";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sys_3v3_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			reg = <100>;
+			regulator-name = "3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		charge_pump_5v0_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,260 @@
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "tegra30-apalis.dtsi"
+
+/ {
+	model = "Toradex Apalis T30 on Apalis Evaluation Board";
+	compatible = "toradex,apalis_t30-eval", "toradex,apalis_t30", "nvidia,tegra30";
+
+	aliases {
+		rtc0 = "/i2c@7000c000/rtc@68";
+		rtc1 = "/i2c@7000d000/tps65911@2d";
+		rtc2 = "/rtc@7000e000";
+	};
+
+	pcie-controller@00003000 {
+		status = "okay";
+
+		pci@1,0 {
+			status = "okay";
+		};
+
+		pci@2,0 {
+			status = "okay";
+		};
+
+		pci@3,0 {
+			status = "okay";
+		};
+	};
+
+	host1x@50000000 {
+		dc@54200000 {
+			rgb {
+				status = "okay";
+				nvidia,panel = <&panel>;
+			};
+		};
+		hdmi@54280000 {
+			status = "okay";
+		};
+	};
+
+	serial@70006000 {
+		status = "okay";
+	};
+
+	serial@70006040 {
+		compatible = "nvidia,tegra30-hsuart";
+		status = "okay";
+	};
+
+	serial@70006200 {
+		compatible = "nvidia,tegra30-hsuart";
+		status = "okay";
+	};
+
+	serial@70006300 {
+		compatible = "nvidia,tegra30-hsuart";
+		status = "okay";
+	};
+
+	pwm@7000a000 {
+		status = "okay";
+	};
+
+	/*
+	 * GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier
+	 * board)
+	 */
+	i2c@7000c000 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		pcie-switch@58 {
+			compatible = "plx,pex8605";
+			reg = <0x58>;
+		};
+
+		/* M41T0M6 real time clock on carrier board */
+		rtc@68 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+
+	/* GEN2_I2C: unused */
+
+	/*
+	 * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on
+	 * carrier board)
+	 */
+	cami2c: i2c@7000c500 {
+		status = "okay";
+		clock-frequency = <400000>;
+	};
+
+	/* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */
+	hdmiddc: i2c@7000c700 {
+		status = "okay";
+	};
+
+	/* SPI1: Apalis SPI1 */
+	spi@7000d400 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+		spidev0: spidev@1 {
+			compatible = "spidev";
+			reg = <1>;
+			spi-max-frequency = <25000000>;
+		};
+	};
+
+	/* SPI5: Apalis SPI2 */
+	spi@7000dc00 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+		spidev1: spidev@2 {
+			compatible = "spidev";
+			reg = <2>;
+			spi-max-frequency = <25000000>;
+		};
+	};
+
+	sd1: sdhci@78000000 {
+		status = "okay";
+		bus-width = <4>;
+		/* SD1_CD# */
+		cd-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_LOW>;
+		no-1-8-v;
+	};
+
+	mmc1: sdhci@78000400 {
+		status = "okay";
+		bus-width = <8>;
+		/* MMC1_CD# */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>;
+		no-1-8-v;
+	};
+
+	/* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */
+	usb@7d000000 {
+		status = "okay";
+	};
+
+	usb-phy@7d000000 {
+		status = "okay";
+		vbus-supply = <&usbo1_vbus_reg>;
+	};
+
+	/* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
+	usb@7d004000 {
+		status = "okay";
+	};
+
+	usb-phy@7d004000 {
+		status = "okay";
+		vbus-supply = <&usbh_vbus_reg>;
+	};
+
+	/* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
+	usb@7d008000 {
+		status = "okay";
+	};
+
+	usb-phy@7d008000 {
+		status = "okay";
+		vbus-supply = <&usbh_vbus_reg>;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+
+		/* PWM0 */
+		pwms = <&pwm 0 5000000>;
+		brightness-levels = <255 231 223 207 191 159 127 0>;
+		default-brightness-level = <6>;
+		/* BKL1_ON */
+		enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+	};
+
+	panel: panel {
+		/*
+		 * edt,et057090dhu: EDT 5.7" LCD TFT
+		 * edt,et070080dh6: EDT 7.0" LCD TFT
+		 */
+		compatible = "edt,et057090dhu", "simple-panel";
+
+		backlight = <&backlight>;
+	};
+
+	pwmleds {
+		compatible = "pwm-leds";
+
+		pwm1 {
+			label = "PWM1";
+			pwms = <&pwm 3 19600>;
+			max-brightness = <255>;
+		};
+
+		pwm2 {
+			label = "PWM2";
+			pwms = <&pwm 2 19600>;
+			max-brightness = <255>;
+		};
+
+		pwm3 {
+			label = "PWM3";
+			pwms = <&pwm 1 19600>;
+			max-brightness = <255>;
+		};
+	};
+
+	regulators {
+		sys_5v0_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		/* USBO1_EN */
+		usbo1_vbus_reg: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usbo1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&sys_5v0_reg>;
+		};
+
+		/* USBH_EN */
+		usbh_vbus_reg: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usbh_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&sys_5v0_reg>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-beaver.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-beaver.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-beaver.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-beaver.dts	2014-09-28 17:29:07.000000000 -0400
@@ -17,9 +17,15 @@
 
 	pcie-controller@00003000 {
 		status = "okay";
-		pex-clk-supply = <&sys_3v3_pexs_reg>;
-		vdd-supply = <&ldo1_reg>;
-		avdd-supply = <&ldo2_reg>;
+
+		avdd-pexa-supply = <&ldo1_reg>;
+		vdd-pexa-supply = <&ldo1_reg>;
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		avdd-plle-supply = <&ldo1_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		hvdd-pex-supply = <&sys_3v3_pexs_reg>;
 
 		pci@1,0 {
 			status = "okay";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -38,9 +38,14 @@
 
 	pcie-controller@00003000 {
 		status = "okay";
-		pex-clk-supply = <&pex_hvdd_3v3_reg>;
-		vdd-supply = <&ldo1_reg>;
-		avdd-supply = <&ldo2_reg>;
+
+		/* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		avdd-plle-supply = <&ldo2_reg>;
 
 		pci@1,0 {
 			nvidia,num-lanes = <4>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -201,7 +201,7 @@
 			vcc4-supply = <&sys_3v3_reg>;
 			vcc5-supply = <&sys_3v3_reg>;
 			vcc6-supply = <&vio_reg>;
-			vcc7-supply = <&sys_5v0_reg>;
+			vcc7-supply = <&charge_pump_5v0_reg>;
 			vccio-supply = <&sys_3v3_reg>;
 
 			regulators {
@@ -373,5 +373,14 @@
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
+
+		charge_pump_5v0_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tegra30.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tegra30.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -335,6 +335,12 @@
 		interrupt-controller;
 	};
 
+	apbmisc@70000800 {
+		compatible = "nvidia,tegra30-apbmisc", "nvidia,tegra20-apbmisc";
+		reg = <0x70000800 0x64   /* Chip revision */
+		       0x70000008 0x04>; /* Strapping options */
+	};
+
 	pinmux: pinmux@70000868 {
 		compatible = "nvidia,tegra30-pinmux";
 		reg = <0x70000868 0xd4    /* Pad control registers */
@@ -631,6 +637,15 @@
 		nvidia,ahb = <&ahb>;
 	};
 
+	fuse@7000f800 {
+		compatible = "nvidia,tegra30-efuse";
+		reg = <0x7000f800 0x400>;
+		clocks = <&tegra_car TEGRA30_CLK_FUSE>;
+		clock-names = "fuse";
+		resets = <&tegra_car 39>;
+		reset-names = "fuse";
+	};
+
 	ahub@70080000 {
 		compatible = "nvidia,tegra30-ahub";
 		reg = <0x70080000 0x200
@@ -775,6 +790,8 @@
 			 <&tegra_car TEGRA30_CLK_PLL_U>,
 			 <&tegra_car TEGRA30_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 22>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <9>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
@@ -786,6 +803,7 @@
 		nvidia,xcvr-hsslew = <32>;
 		nvidia,hssquelch-level = <2>;
 		nvidia,hsdiscon-level = <5>;
+		nvidia,has-utmi-pad-registers;
 		status = "disabled";
 	};
 
@@ -809,6 +827,8 @@
 			 <&tegra_car TEGRA30_CLK_PLL_U>,
 			 <&tegra_car TEGRA30_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 58>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <9>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
@@ -843,6 +863,8 @@
 			 <&tegra_car TEGRA30_CLK_PLL_U>,
 			 <&tegra_car TEGRA30_CLK_USBD>;
 		clock-names = "reg", "pll_u", "utmi-pads";
+		resets = <&tegra_car 59>, <&tegra_car 22>;
+		reset-names = "usb", "utmi-pads";
 		nvidia,hssync-start-delay = <0>;
 		nvidia,idle-wait-delay = <17>;
 		nvidia,elastic-limit = <16>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tny_a9260_common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tny_a9260_common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tny_a9260_common.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tny_a9260_common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/tny_a9263.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tny_a9263.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/tny_a9263.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/tny_a9263.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/twl6030.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/twl6030.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/twl6030.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/twl6030.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -83,10 +83,6 @@
 		regulator-always-on;
 	};
 
-	clk32kg: regulator-clk32kg {
-		compatible = "ti,twl6030-clk32kg";
-	};
-
 	twl_usb_comparator: usb-comparator {
 		compatible = "ti,twl6030-usb";
 		interrupts = <4>, <10>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/usb_a9260_common.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/usb_a9260_common.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/usb_a9260_common.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/usb_a9260_common.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/usb_a9263.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/usb_a9263.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/usb_a9263.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/usb_a9263.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,14 @@
 			compatible = "atmel,osc", "fixed-clock";
 			clock-frequency = <12000000>;
 		};
+
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <12000000>;
+		};
 	};
 
 	ahb {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/versatile-ab.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/versatile-ab.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/versatile-ab.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/versatile-ab.dts	2014-09-28 17:29:07.000000000 -0400
@@ -15,10 +15,49 @@
 		i2c0 = &i2c0;
 	};
 
+	chosen {
+		stdout-path = &uart0;
+	};
+
 	memory {
 		reg = <0x0 0x08000000>;
 	};
 
+	xtal24mhz: xtal24mhz@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	core-module@10000000 {
+		compatible = "arm,core-module-versatile", "syscon";
+		reg = <0x10000000 0x200>;
+
+		/* OSC1 on AB, OSC4 on PB */
+		osc1: cm_aux_osc@24M {
+			#clock-cells = <0>;
+			compatible = "arm,versatile-cm-auxosc";
+			clocks = <&xtal24mhz>;
+		};
+
+		/* The timer clock is the 24 MHz oscillator divided to 1MHz */
+		timclk: timclk@1M {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <24>;
+			clock-mult = <1>;
+			clocks = <&xtal24mhz>;
+		};
+
+		pclk: pclk@24M {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&xtal24mhz>;
+		};
+	};
+
 	flash@34000000 {
 		compatible = "arm,versatile-flash";
 		reg = <0x34000000 0x4000000>;
@@ -59,6 +98,8 @@
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x10140000 0x1000>;
+			clear-mask = <0xffffffff>;
+			valid-mask = <0xffffffff>;
 		};
 
 		sic: intc@10003000 {
@@ -68,69 +109,93 @@
 			reg = <0x10003000 0x1000>;
 			interrupt-parent = <&vic>;
 			interrupts = <31>; /* Cascaded to vic */
+			clear-mask = <0xffffffff>;
+			valid-mask = <0xffc203f8>;
 		};
 
 		dma@10130000 {
 			compatible = "arm,pl081", "arm,primecell";
 			reg = <0x10130000 0x1000>;
 			interrupts = <17>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		uart0: uart@101f1000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x101f1000 0x1000>;
 			interrupts = <12>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		uart1: uart@101f2000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x101f2000 0x1000>;
 			interrupts = <13>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		uart2: uart@101f3000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x101f3000 0x1000>;
 			interrupts = <14>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
 		};
 
 		smc@10100000 {
 			compatible = "arm,primecell";
 			reg = <0x10100000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		mpmc@10110000 {
 			compatible = "arm,primecell";
 			reg = <0x10110000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		display@10120000 {
 			compatible = "arm,pl110", "arm,primecell";
 			reg = <0x10120000 0x1000>;
 			interrupts = <16>;
+			clocks = <&osc1>, <&pclk>;
+			clock-names = "clcd", "apb_pclk";
 		};
 
 		sctl@101e0000 {
 			compatible = "arm,primecell";
 			reg = <0x101e0000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		watchdog@101e1000 {
 			compatible = "arm,primecell";
 			reg = <0x101e1000 0x1000>;
 			interrupts = <0>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		timer@101e2000 {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0x101e2000 0x1000>;
 			interrupts = <4>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timer0", "timer1", "apb_pclk";
 		};
 
 		timer@101e3000 {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0x101e3000 0x1000>;
 			interrupts = <5>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timer0", "timer1", "apb_pclk";
 		};
 
 		gpio0: gpio@101e4000 {
@@ -141,6 +206,8 @@
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpio1: gpio@101e5000 {
@@ -151,24 +218,32 @@
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		rtc@101e8000 {
 			compatible = "arm,pl030", "arm,primecell";
 			reg = <0x101e8000 0x1000>;
 			interrupts = <10>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		sci@101f0000 {
 			compatible = "arm,primecell";
 			reg = <0x101f0000 0x1000>;
 			interrupts = <15>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		ssp@101f4000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x101f4000 0x1000>;
 			interrupts = <11>;
+			clocks = <&xtal24mhz>, <&pclk>;
+			clock-names = "SSPCLK", "apb_pclk";
 		};
 
 		fpga {
@@ -181,23 +256,31 @@
 				compatible = "arm,primecell";
 				reg = <0x4000 0x1000>;
 				interrupts = <24>;
+				clocks = <&pclk>;
+				clock-names = "apb_pclk";
 			};
 			mmc@5000 {
-				compatible = "arm,primecell";
+				compatible = "arm,pl180", "arm,primecell";
 				reg = < 0x5000 0x1000>;
 				interrupts-extended = <&vic 22 &sic 2>;
+				clocks = <&xtal24mhz>, <&pclk>;
+				clock-names = "mclk", "apb_pclk";
 			};
 			kmi@6000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x6000 0x1000>;
 				interrupt-parent = <&sic>;
 				interrupts = <3>;
+				clocks = <&xtal24mhz>, <&pclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 			kmi@7000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x7000 0x1000>;
 				interrupt-parent = <&sic>;
 				interrupts = <4>;
+				clocks = <&xtal24mhz>, <&pclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/versatile-pb.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/versatile-pb.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/versatile-pb.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/versatile-pb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,8 @@
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpio3: gpio@101e7000 {
@@ -23,6 +25,8 @@
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		fpga {
@@ -31,20 +35,24 @@
 				reg = <0x9000 0x1000>;
 				interrupt-parent = <&sic>;
 				interrupts = <6>;
+				clocks = <&xtal24mhz>, <&pclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 			sci@a000 {
 				compatible = "arm,primecell";
 				reg = <0xa000 0x1000>;
 				interrupt-parent = <&sic>;
 				interrupts = <5>;
+				clocks = <&xtal24mhz>;
+				clock-names = "apb_pclk";
 			};
 			mmc@b000 {
-				compatible = "arm,primecell";
+				compatible = "arm,pl180", "arm,primecell";
 				reg = <0xb000 0x1000>;
 				interrupts-extended = <&vic 23 &sic 2>;
+				clocks = <&xtal24mhz>, <&pclk>;
+				clock-names = "mclk", "apb_pclk";
 			};
 		};
 	};
 };
-
-#include <testcases.dtsi>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/vf610.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/vf610.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/vf610.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/vf610.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,8 @@
 
 / {
 	aliases {
+		can0 = &can0;
+		can1 = &can1;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
@@ -103,6 +105,16 @@
 					<&clks VF610_CLK_DMAMUX1>;
 			};
 
+			can0: flexcan@40020000 {
+				compatible = "fsl,vf610-flexcan";
+				reg = <0x40020000 0x4000>;
+				interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks VF610_CLK_FLEXCAN0>,
+					 <&clks VF610_CLK_FLEXCAN0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
 			uart0: serial@40027000 {
 				compatible = "fsl,vf610-lpuart";
 				reg = <0x40027000 0x1000>;
@@ -362,7 +374,7 @@
 
 			esdhc1: esdhc@400b2000 {
 				compatible = "fsl,imx53-esdhc";
-				reg = <0x400b2000 0x4000>;
+				reg = <0x400b2000 0x1000>;
 				interrupts = <0 28 0x04>;
 				clocks = <&clks VF610_CLK_IPG_BUS>,
 					<&clks VF610_CLK_PLATFORM_BUS>,
@@ -405,6 +417,17 @@
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
+
+			can1: flexcan@400d4000 {
+				compatible = "fsl,vf610-flexcan";
+				reg = <0x400d4000 0x4000>;
+				interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks VF610_CLK_FLEXCAN1>,
+					 <&clks VF610_CLK_FLEXCAN1>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/vf610-twr.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/vf610-twr.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/vf610-twr.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/vf610-twr.dts	2014-09-28 17:29:07.000000000 -0400
@@ -168,7 +168,7 @@
 		};
 
 		pinctrl_esdhc1: esdhc1grp {
-			fsl,fsl,pins = <
+			fsl,pins = <
 				VF610_PAD_PTA24__ESDHC1_CLK	0x31ef
 				VF610_PAD_PTA25__ESDHC1_CMD	0x31ef
 				VF610_PAD_PTA26__ESDHC1_DAT0	0x31ef
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-7000.dtsi linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-7000.dtsi
--- linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-7000.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-7000.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -65,6 +65,48 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
+		adc@f8007100 {
+			compatible = "xlnx,zynq-xadc-1.00.a";
+			reg = <0xf8007100 0x20>;
+			interrupts = <0 7 4>;
+			interrupt-parent = <&intc>;
+			clocks = <&clkc 12>;
+		};
+
+		can0: can@e0008000 {
+			compatible = "xlnx,zynq-can-1.0";
+			status = "disabled";
+			clocks = <&clkc 19>, <&clkc 36>;
+			clock-names = "can_clk", "pclk";
+			reg = <0xe0008000 0x1000>;
+			interrupts = <0 28 4>;
+			interrupt-parent = <&intc>;
+			tx-fifo-depth = <0x40>;
+			rx-fifo-depth = <0x40>;
+		};
+
+		can1: can@e0009000 {
+			compatible = "xlnx,zynq-can-1.0";
+			status = "disabled";
+			clocks = <&clkc 20>, <&clkc 37>;
+			clock-names = "can_clk", "pclk";
+			reg = <0xe0009000 0x1000>;
+			interrupts = <0 51 4>;
+			interrupt-parent = <&intc>;
+			tx-fifo-depth = <0x40>;
+			rx-fifo-depth = <0x40>;
+		};
+
+		gpio0: gpio@e000a000 {
+			compatible = "xlnx,zynq-gpio-1.0";
+			#gpio-cells = <2>;
+			clocks = <&clkc 42>;
+			gpio-controller;
+			interrupt-parent = <&intc>;
+			interrupts = <0 20 4>;
+			reg = <0xe000a000 0x1000>;
+		};
+
 		i2c0: i2c@e0004000 {
 			compatible = "cdns,i2c-r1p10";
 			status = "disabled";
@@ -105,23 +147,47 @@
 		};
 
 		uart0: serial@e0000000 {
-			compatible = "xlnx,xuartps";
+			compatible = "xlnx,xuartps", "cdns,uart-r1p8";
 			status = "disabled";
 			clocks = <&clkc 23>, <&clkc 40>;
-			clock-names = "ref_clk", "aper_clk";
+			clock-names = "uart_clk", "pclk";
 			reg = <0xE0000000 0x1000>;
 			interrupts = <0 27 4>;
 		};
 
 		uart1: serial@e0001000 {
-			compatible = "xlnx,xuartps";
+			compatible = "xlnx,xuartps", "cdns,uart-r1p8";
 			status = "disabled";
 			clocks = <&clkc 24>, <&clkc 41>;
-			clock-names = "ref_clk", "aper_clk";
+			clock-names = "uart_clk", "pclk";
 			reg = <0xE0001000 0x1000>;
 			interrupts = <0 50 4>;
 		};
 
+		spi0: spi@e0006000 {
+			compatible = "xlnx,zynq-spi-r1p6";
+			reg = <0xe0006000 0x1000>;
+			status = "disabled";
+			interrupt-parent = <&intc>;
+			interrupts = <0 26 4>;
+			clocks = <&clkc 25>, <&clkc 34>;
+			clock-names = "ref_clk", "pclk";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi1: spi@e0007000 {
+			compatible = "xlnx,zynq-spi-r1p6";
+			reg = <0xe0007000 0x1000>;
+			status = "disabled";
+			interrupt-parent = <&intc>;
+			interrupts = <0 49 4>;
+			clocks = <&clkc 26>, <&clkc 35>;
+			clock-names = "ref_clk", "pclk";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		gem0: ethernet@e000b000 {
 			compatible = "cdns,gem";
 			reg = <0xe000b000 0x4000>;
@@ -186,6 +252,22 @@
 			};
 		};
 
+		dmac_s: dmac@f8003000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xf8003000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 13 4>,
+			             <0 14 4>, <0 15 4>,
+			             <0 16 4>, <0 17 4>,
+			             <0 40 4>, <0 41 4>,
+			             <0 42 4>, <0 43 4>;
+			#dma-cells = <1>;
+			#dma-channels = <8>;
+			#dma-requests = <4>;
+			clocks = <&clkc 27>;
+			clock-names = "apb_pclk";
+		};
+
 		devcfg: devcfg@f8007000 {
 			compatible = "xlnx,zynq-devcfg-1.0";
 			reg = <0xf8007000 0x100>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-parallella.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-parallella.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-parallella.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-parallella.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * Derived from zynq-zed.dts:
+ *
+ *  Copyright (C) 2011 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ *  Copyright (C) 2013 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+	model = "Adapteva Parallella Board";
+	compatible = "adapteva,parallella", "xlnx,zynq-7000";
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait";
+		linux,stdout-path = "/amba/serial@e0001000";
+	};
+};
+
+&gem0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ethernet_phy: ethernet-phy@0 {
+		/* Marvell 88E1318 */
+		compatible = "ethernet-phy-id0141.0e90",
+		             "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+		marvell,reg-init = <0x3 0x10 0xff00 0x1e>,
+		                   <0x3 0x11 0xfff0 0xa>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&sdhci1 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-zc702.dts linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-zc702.dts
--- linux-libre-3.16-gnu/arch/arm/boot/dts/zynq-zc702.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/boot/dts/zynq-zc702.dts	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,10 @@
 
 };
 
+&can0 {
+	status = "okay";
+};
+
 &gem0 {
 	status = "okay";
 	phy-mode = "rgmii";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/common/bL_switcher.c linux-libre-3.17-rc7-gnu/arch/arm/common/bL_switcher.c
--- linux-libre-3.16-gnu/arch/arm/common/bL_switcher.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/common/bL_switcher.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,16 +58,6 @@ static int read_mpidr(void)
 }
 
 /*
- * Get a global nanosecond time stamp for tracing.
- */
-static s64 get_ns(void)
-{
-	struct timespec ts;
-	getnstimeofday(&ts);
-	return timespec_to_ns(&ts);
-}
-
-/*
  * bL switcher core code.
  */
 
@@ -224,7 +214,7 @@ static int bL_switch_to(unsigned int new
 	 */
 	local_irq_disable();
 	local_fiq_disable();
-	trace_cpu_migrate_begin(get_ns(), ob_mpidr);
+	trace_cpu_migrate_begin(ktime_get_real_ns(), ob_mpidr);
 
 	/* redirect GIC's SGIs to our counterpart */
 	gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
@@ -267,7 +257,7 @@ static int bL_switch_to(unsigned int new
 					  tdev->evtdev->next_event, 1);
 	}
 
-	trace_cpu_migrate_finish(get_ns(), ib_mpidr);
+	trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
 	local_fiq_enable();
 	local_irq_enable();
 
@@ -558,7 +548,7 @@ int bL_switcher_get_logical_index(u32 mp
 
 static void bL_switcher_trace_trigger_cpu(void *__always_unused info)
 {
-	trace_cpu_migrate_current(get_ns(), read_mpidr());
+	trace_cpu_migrate_current(ktime_get_real_ns(), read_mpidr());
 }
 
 int bL_switcher_trace_trigger(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/common/edma.c linux-libre-3.17-rc7-gnu/arch/arm/common/edma.c
--- linux-libre-3.16-gnu/arch/arm/common/edma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/common/edma.c	2014-09-28 17:29:07.000000000 -0400
@@ -1414,15 +1414,43 @@ void edma_clear_event(unsigned channel)
 }
 EXPORT_SYMBOL(edma_clear_event);
 
+/*
+ * edma_assign_channel_eventq - move given channel to desired eventq
+ * Arguments:
+ *	channel - channel number
+ *	eventq_no - queue to move the channel
+ *
+ * Can be used to move a channel to a selected event queue.
+ */
+void edma_assign_channel_eventq(unsigned channel, enum dma_event_q eventq_no)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel >= edma_cc[ctlr]->num_channels)
+		return;
+
+	/* default to low priority queue */
+	if (eventq_no == EVENTQ_DEFAULT)
+		eventq_no = edma_cc[ctlr]->default_queue;
+	if (eventq_no >= edma_cc[ctlr]->num_tc)
+		return;
+
+	map_dmach_queue(ctlr, channel, eventq_no);
+}
+EXPORT_SYMBOL(edma_assign_channel_eventq);
+
 static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
-			      struct edma *edma_cc)
+			      struct edma *edma_cc, int cc_id)
 {
 	int i;
 	u32 value, cccfg;
 	s8 (*queue_priority_map)[2];
 
 	/* Decode the eDMA3 configuration from CCCFG register */
-	cccfg = edma_read(0, EDMA_CCCFG);
+	cccfg = edma_read(cc_id, EDMA_CCCFG);
 
 	value = GET_NUM_REGN(cccfg);
 	edma_cc->num_region = BIT(value);
@@ -1436,7 +1464,8 @@ static int edma_setup_from_hw(struct dev
 	value = GET_NUM_EVQUE(cccfg);
 	edma_cc->num_tc = value + 1;
 
-	dev_dbg(dev, "eDMA3 HW configuration (cccfg: 0x%08x):\n", cccfg);
+	dev_dbg(dev, "eDMA3 CC%d HW configuration (cccfg: 0x%08x):\n", cc_id,
+		cccfg);
 	dev_dbg(dev, "num_region: %u\n", edma_cc->num_region);
 	dev_dbg(dev, "num_channel: %u\n", edma_cc->num_channels);
 	dev_dbg(dev, "num_slot: %u\n", edma_cc->num_slots);
@@ -1470,7 +1499,8 @@ static int edma_setup_from_hw(struct dev
 	queue_priority_map[i][1] = -1;
 
 	pdata->queue_priority_mapping = queue_priority_map;
-	pdata->default_queue = 0;
+	/* Default queue has the lowest priority */
+	pdata->default_queue = i - 1;
 
 	return 0;
 }
@@ -1655,7 +1685,7 @@ static int edma_probe(struct platform_de
 			return -ENOMEM;
 
 		/* Get eDMA3 configuration from IP */
-		ret = edma_setup_from_hw(dev, info[j], edma_cc[j]);
+		ret = edma_setup_from_hw(dev, info[j], edma_cc[j], j);
 		if (ret)
 			return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/common/mcpm_entry.c linux-libre-3.17-rc7-gnu/arch/arm/common/mcpm_entry.c
--- linux-libre-3.16-gnu/arch/arm/common/mcpm_entry.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/common/mcpm_entry.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,11 +12,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
+#include <linux/cpu_pm.h>
 
 #include <asm/mcpm.h>
 #include <asm/cacheflush.h>
 #include <asm/idmap.h>
 #include <asm/cputype.h>
+#include <asm/suspend.h>
 
 extern unsigned long mcpm_entry_vectors[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER];
 
@@ -146,6 +148,56 @@ int mcpm_cpu_powered_up(void)
 	return 0;
 }
 
+#ifdef CONFIG_ARM_CPU_SUSPEND
+
+static int __init nocache_trampoline(unsigned long _arg)
+{
+	void (*cache_disable)(void) = (void *)_arg;
+	unsigned int mpidr = read_cpuid_mpidr();
+	unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+	phys_reset_t phys_reset;
+
+	mcpm_set_entry_vector(cpu, cluster, cpu_resume);
+	setup_mm_for_reboot();
+
+	__mcpm_cpu_going_down(cpu, cluster);
+	BUG_ON(!__mcpm_outbound_enter_critical(cpu, cluster));
+	cache_disable();
+	__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+	__mcpm_cpu_down(cpu, cluster);
+
+	phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
+	phys_reset(virt_to_phys(mcpm_entry_point));
+	BUG();
+}
+
+int __init mcpm_loopback(void (*cache_disable)(void))
+{
+	int ret;
+
+	/*
+	 * We're going to soft-restart the current CPU through the
+	 * low-level MCPM code by leveraging the suspend/resume
+	 * infrastructure. Let's play it safe by using cpu_pm_enter()
+	 * in case the CPU init code path resets the VFP or similar.
+	 */
+	local_irq_disable();
+	local_fiq_disable();
+	ret = cpu_pm_enter();
+	if (!ret) {
+		ret = cpu_suspend((unsigned long)cache_disable, nocache_trampoline);
+		cpu_pm_exit();
+	}
+	local_fiq_enable();
+	local_irq_enable();
+	if (ret)
+		pr_err("%s returned %d\n", __func__, ret);
+	return ret;
+}
+
+#endif
+
 struct sync_struct mcpm_sync;
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/common/timer-sp.c linux-libre-3.17-rc7-gnu/arch/arm/common/timer-sp.c
--- linux-libre-3.16-gnu/arch/arm/common/timer-sp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/common/timer-sp.c	2014-09-28 17:29:07.000000000 -0400
@@ -233,13 +233,13 @@ static void __init sp804_of_init(struct
 	if (IS_ERR(clk1))
 		clk1 = NULL;
 
-	/* Get the 2nd clock if the timer has 2 timer clocks */
+	/* Get the 2nd clock if the timer has 3 timer clocks */
 	if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) {
 		clk2 = of_clk_get(np, 1);
 		if (IS_ERR(clk2)) {
 			pr_err("sp804: %s clock not found: %d\n", np->name,
 				(int)PTR_ERR(clk2));
-			goto err;
+			clk2 = NULL;
 		}
 	} else
 		clk2 = clk1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/armadillo800eva_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/armadillo800eva_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/armadillo800eva_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/armadillo800eva_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -96,6 +96,7 @@ CONFIG_I2C_GPIO=y
 CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
@@ -127,6 +128,9 @@ CONFIG_USB_ETH=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
 CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S35390A=y
 CONFIG_DMADEVICES=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/bcm_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/bcm_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/bcm_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/bcm_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM_MOBILE=y
 CONFIG_ARM_THUMBEE=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_COMPACTION is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/exynos_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/exynos_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/exynos_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/exynos_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -8,15 +8,17 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=3
-CONFIG_S3C24XX_PWM=y
-CONFIG_ARCH_EXYNOS5=y
-CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_ARCH_EXYNOS3=y
+CONFIG_EXYNOS5420_MCPM=y
 CONFIG_SMP=y
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_BL_SWITCHER_DUMMY_IF=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_CMA=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -24,6 +26,7 @@ CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -34,6 +37,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -66,11 +71,22 @@ CONFIG_I2C=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_I2C_EXYNOS5=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_SPI=y
+CONFIG_SPI_S3C64XX=y
 CONFIG_I2C_S3C2410=y
 CONFIG_DEBUG_GPIO=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_CHARGER_TPS65090=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_EXYNOS_THERMAL_CORE=y
+CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_MFD_CROS_EC_SPI=y
 CONFIG_MFD_MAX77686=y
 CONFIG_MFD_MAX8997=y
 CONFIG_MFD_SEC_CORE=y
@@ -80,6 +96,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_MAX8997=y
 CONFIG_REGULATOR_MAX77686=y
+CONFIG_REGULATOR_S2MPA01=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_REGULATOR_TPS65090=y
@@ -88,28 +105,50 @@ CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_SIMPLE=y
 CONFIG_EXYNOS_VIDEO=y
 CONFIG_EXYNOS_MIPI_DSI=y
-CONFIG_EXYNOS_DP=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_7x14=y
 CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SNOW=y
 CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_EXYNOS=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
-CONFIG_USB_PHY=y
-CONFIG_SAMSUNG_USB2PHY=y
-CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_USB_HSIC_USB3503=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_S3C=y
+CONFIG_DMADEVICES=y
+CONFIG_PL330_DMA=y
 CONFIG_COMMON_CLK_MAX77686=y
+CONFIG_COMMON_CLK_S2MPS11=y
+CONFIG_EXYNOS_IOMMU=y
+CONFIG_IIO=y
+CONFIG_EXYNOS_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_SAMSUNG=y
+CONFIG_PHY_EXYNOS5250_SATA=y
+CONFIG_PHY_SAMSUNG_USB2=y
+CONFIG_PHY_EXYNOS4210_USB2=y
+CONFIG_PHY_EXYNOS4X12_USB2=y
+CONFIG_PHY_EXYNOS5250_USB2=y
+CONFIG_PHY_EXYNOS5_USBDRD=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
@@ -123,6 +162,7 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/genmai_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/genmai_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/genmai_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/genmai_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,122 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_SLAB=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_R7S72100=y
-CONFIG_MACH_GENMAI=y
-# CONFIG_SH_TIMER_CMT is not set
-# CONFIG_SH_TIMER_MTU2 is not set
-# CONFIG_SH_TIMER_TMU is not set
-# CONFIG_EM_TIMER_STI is not set
-CONFIG_ARM_ERRATA_430973=y
-CONFIG_ARM_ERRATA_458693=y
-CONFIG_ARM_ERRATA_460075=y
-CONFIG_ARM_ERRATA_743622=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_KEXEC=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-# CONFIG_NET_CORE is not set
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY 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_SH_ETH=y
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC 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_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=10
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_RIIC=y
-CONFIG_SPI=y
-CONFIG_SPI_RSPI=y
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
-CONFIG_RCAR_THERMAL=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_DRM=y
-CONFIG_DRM_RCAR_DU=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_SH_MMCIF=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_DMADEVICES=y
-CONFIG_SH_DMAE=y
-# CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_ARM_UNWIND is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/hi3xxx_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/hi3xxx_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/hi3xxx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/hi3xxx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,7 +3,9 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
+CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HIX5HD2=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/imx_v4_v5_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/imx_v4_v5_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/imx_v4_v5_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/imx_v4_v5_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -35,10 +36,8 @@ CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
 CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
 CONFIG_MACH_MX27_3DS=y
 CONFIG_MACH_IMX27_VISSTRIM_M10=y
-CONFIG_MACH_IMX27LITE=y
 CONFIG_MACH_PCA100=y
 CONFIG_MACH_MXT_TD60=y
-CONFIG_MACH_IMX27IPCAM=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -159,6 +158,8 @@ CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/imx_v6_v7_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/imx_v6_v7_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/imx_v6_v7_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/imx_v6_v7_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,6 @@
 CONFIG_KERNEL_LZO=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=18
@@ -31,11 +32,12 @@ CONFIG_MACH_IMX35_DT=y
 CONFIG_MACH_PCM043=y
 CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_VPR200=y
-CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX51=y
 CONFIG_SOC_IMX50=y
 CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SX=y
 CONFIG_SOC_VF610=y
 CONFIG_PCI=y
 CONFIG_PCI_IMX6=y
@@ -67,6 +69,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_NETFILTER=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_RFKILL=y
@@ -160,6 +164,7 @@ CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
+CONFIG_GPIO_STMPE=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
@@ -242,6 +247,7 @@ CONFIG_RTC_DRV_SNVS=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
 CONFIG_MXS_DMA=y
+CONFIG_FSL_EDMA=y
 CONFIG_STAGING=y
 CONFIG_DRM_IMX=y
 CONFIG_DRM_IMX_FB_HELPER=y
@@ -288,6 +294,7 @@ CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/kirkwood_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/kirkwood_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/kirkwood_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/kirkwood_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,181 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=19
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_KIRKWOOD=y
-CONFIG_MACH_D2NET_V2=y
-CONFIG_MACH_NET2BIG_V2=y
-CONFIG_MACH_NET5BIG_V2=y
-CONFIG_MACH_OPENRD_BASE=y
-CONFIG_MACH_OPENRD_CLIENT=y
-CONFIG_MACH_OPENRD_ULTIMATE=y
-CONFIG_MACH_RD88F6192_NAS=y
-CONFIG_MACH_RD88F6281=y
-CONFIG_MACH_T5325=y
-CONFIG_MACH_TS219=y
-CONFIG_MACH_TS41X=y
-CONFIG_ARCH_KIRKWOOD_DT=y
-CONFIG_MACH_MV88F6281GTW_GE_DT=y
-# CONFIG_CPU_FEROCEON_OLD_ID is not set
-CONFIG_PCI_MVEBU=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_HIGHMEM=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-CONFIG_CPU_IDLE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_NET_PKTGEN=m
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ORION=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_EEPROM_AT24=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_SATA_MV=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
-CONFIG_MV643XX_ETH=y
-CONFIG_R8169=y
-CONFIG_MARVELL_PHY=y
-CONFIG_LIBERTAS=y
-CONFIG_LIBERTAS_SDIO=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_SPI=y
-CONFIG_SPI_ORION=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SENSORS_ADT7475=y
-CONFIG_SENSORS_LM63=y
-CONFIG_SENSORS_LM75=y
-CONFIG_SENSORS_LM85=y
-CONFIG_THERMAL=y
-CONFIG_WATCHDOG=y
-CONFIG_ORION_WATCHDOG=y
-CONFIG_HID_DRAGONRISE=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_TWINHAN=y
-CONFIG_HID_NTRIG=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_HID_GREENASIA=y
-CONFIG_HID_SMARTJOYPLUS=y
-CONFIG_HID_TOPSEED=y
-CONFIG_HID_THRUSTMASTER=y
-CONFIG_HID_ZEROPLUS=y
-CONFIG_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_MMC=y
-CONFIG_SDIO_UART=y
-CONFIG_MMC_MVSDIO=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_RS5C372=y
-CONFIG_RTC_DRV_PCF8563=y
-CONFIG_RTC_DRV_S35390A=y
-CONFIG_RTC_DRV_MV=y
-CONFIG_DMADEVICES=y
-CONFIG_MV_XOR=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_MV_CESA=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/msm_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/msm_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/msm_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/msm_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,6 @@ CONFIG_RFKILL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/multi_v5_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/multi_v5_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/multi_v5_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/multi_v5_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_NETXBIG=y
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_IMX25_DT=y
 CONFIG_MACH_IMX27_DT=y
@@ -94,6 +95,7 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
 CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_G762=y
 CONFIG_SENSORS_LM63=y
 CONFIG_SENSORS_LM75=y
 CONFIG_SENSORS_LM85=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/multi_v7_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/multi_v7_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/multi_v7_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/multi_v7_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,15 +19,18 @@ CONFIG_MACH_DOVE=y
 CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM_MOBILE=y
 CONFIG_ARCH_BCM_5301X=y
+CONFIG_ARCH_BRCMSTB=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_MACH_BERLIN_BG2=y
 CONFIG_MACH_BERLIN_BG2CD=y
 CONFIG_MACH_BERLIN_BG2Q=y
 CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HIX5HD2=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARCH_MXC=y
-CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX51=y
 CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_SOC_IMX6SL=y
@@ -66,7 +69,6 @@ CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_VEXPRESS_CA9X4=y
 CONFIG_ARCH_WM8850=y
 CONFIG_ARCH_ZYNQ=y
-CONFIG_NEON=y
 CONFIG_TRUSTED_FOUNDATIONS=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
@@ -83,6 +85,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
+CONFIG_NEON=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -127,6 +130,7 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_ST=y
 CONFIG_AHCI_SUNXI=y
 CONFIG_SATA_HIGHBANK=y
 CONFIG_SATA_MV=y
@@ -134,6 +138,7 @@ CONFIG_NETDEVICES=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_MACB=y
 CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_IGB=y
 CONFIG_MV643XX_ETH=y
 CONFIG_MVNETA=y
 CONFIG_KS8851=y
@@ -155,8 +160,11 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_TEGRA=y
 CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_ST_KEYSCAN=y
 CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
 CONFIG_SERIO_AMBAKMI=y
@@ -195,6 +203,7 @@ CONFIG_I2C_EXYNOS5=y
 CONFIG_I2C_MV64XXX=y
 CONFIG_I2C_SIRF=y
 CONFIG_I2C_TEGRA=y
+CONFIG_I2C_ST=y
 CONFIG_SPI=y
 CONFIG_SPI_OMAP24XX=y
 CONFIG_SPI_ORION=y
@@ -222,8 +231,11 @@ CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_SUN6I=y
 CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM95245=y
 CONFIG_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_ST_THERMAL_SYSCFG=y
+CONFIG_ST_THERMAL_MEMMAP=y
 CONFIG_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
@@ -233,6 +245,7 @@ CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
 CONFIG_MFD_MAX8907=y
 CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_STMPE=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
 CONFIG_MFD_TPS6586X=y
@@ -311,12 +324,16 @@ CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_SDHCI_S3C=y
 CONFIG_MMC_SDHCI_S3C_DMA=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_SDHCI_ST=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_MMC_MVSDIO=y
 CONFIG_MMC_SUNXI=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_EXYNOS=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PWM=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
@@ -368,6 +385,8 @@ CONFIG_PWM=y
 CONFIG_PWM_TEGRA=y
 CONFIG_PWM_VT8500=y
 CONFIG_OMAP_USB2=y
+CONFIG_TI_PIPE3=y
+CONFIG_PHY_MIPHY365X=y
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/mvebu_v5_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/mvebu_v5_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/mvebu_v5_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/mvebu_v5_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_NETXBIG=y
 # CONFIG_CPU_FEROCEON_OLD_ID is not set
 CONFIG_PCI_MVEBU=y
 CONFIG_PREEMPT=y
@@ -19,6 +20,8 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
@@ -36,6 +39,8 @@ CONFIG_NET_PKTGEN=m
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
@@ -89,6 +94,7 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
 CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_G762=y
 CONFIG_SENSORS_LM63=y
 CONFIG_SENSORS_LM75=y
 CONFIG_SENSORS_LM85=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/mvebu_v7_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/mvebu_v7_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/mvebu_v7_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/mvebu_v7_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,10 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_MVEBU_V7_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_GENERIC=y
 CONFIG_VFP=y
 CONFIG_NET=y
 CONFIG_INET=y
@@ -46,6 +50,7 @@ CONFIG_AHCI_MVEBU=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_MVNETA=y
+CONFIG_MVPP2=y
 CONFIG_MARVELL_PHY=y
 CONFIG_MWIFIEX=y
 CONFIG_MWIFIEX_SDIO=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/mxs_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/mxs_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/mxs_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/mxs_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,5 @@
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/omap1_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/omap1_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/omap1_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/omap1_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -26,8 +26,6 @@ CONFIG_ARCH_OMAP=y
 CONFIG_ARCH_OMAP1=y
 CONFIG_OMAP_RESET_CLOCKS=y
 # CONFIG_OMAP_MUX is not set
-CONFIG_MAILBOX=y
-CONFIG_OMAP1_MBOX=y
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_DM_TIMER=y
 CONFIG_ARCH_OMAP730=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/omap2plus_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/omap2plus_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/omap2plus_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/omap2plus_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -180,6 +180,7 @@ CONFIG_TWL4030_WATCHDOG=y
 CONFIG_MFD_SYSCON=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TPS65218=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -188,6 +189,7 @@ CONFIG_REGULATOR_TI_ABB=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_REGULATOR_TPS65217=y
+CONFIG_REGULATOR_TPS65218=y
 CONFIG_REGULATOR_TPS65910=y
 CONFIG_REGULATOR_TWL4030=y
 CONFIG_REGULATOR_PBIAS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/s3c2410_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/s3c2410_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/s3c2410_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/s3c2410_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -225,7 +225,6 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDETAPE=m
 CONFIG_BLK_DEV_PLATFORM=y
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/s5p64x0_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/s5p64x0_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/s5p64x0_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/s5p64x0_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5P64X0=y
-CONFIG_S3C_BOOT_ERROR_RESET=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
-CONFIG_MACH_SMDK6440=y
-CONFIG_MACH_SMDK6450=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_CPU_32v6K=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
-CONFIG_FPE_NWFPE=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-# CONFIG_HWMON is not set
-CONFIG_DISPLAY_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_S3C_UART=1
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/s5pc100_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/s5pc100_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/s5pc100_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/s5pc100_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5PC100=y
-CONFIG_MACH_SMDKC100=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=cramfs init=/linuxrc console=ttySAC2,115200 mem=128M"
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_EEPROM_AT24=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_SDIO_UART=y
-CONFIG_MMC_SDHCI=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/shmobile_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/shmobile_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/shmobile_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/shmobile_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -10,16 +10,20 @@ CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_ARCH_SHMOBILE_MULTI=y
 CONFIG_ARCH_EMEV2=y
+CONFIG_ARCH_R7S72100=y
+CONFIG_ARCH_R8A7779=y
 CONFIG_ARCH_R8A7790=y
 CONFIG_ARCH_R8A7791=y
 CONFIG_MACH_KOELSCH=y
 CONFIG_MACH_LAGER=y
+CONFIG_MACH_MARZEN=y
 # CONFIG_SWP_EMULATE is not set
 CONFIG_CPU_BPREDICT_DISABLE=y
 CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_754322=y
 CONFIG_PCI=y
 CONFIG_PCI_RCAR_GEN2=y
+CONFIG_PCI_RCAR_GEN2_PCIE=y
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
 CONFIG_HAVE_ARM_ARCH_TIMER=y
@@ -33,6 +37,7 @@ CONFIG_KEXEC=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -82,6 +87,7 @@ CONFIG_I2C_RCAR=y
 CONFIG_SPI=y
 CONFIG_SPI_RSPI=y
 CONFIG_SPI_SH_MSIOF=y
+CONFIG_SPI_SH_HSPI=y
 CONFIG_GPIO_EM=y
 CONFIG_GPIO_RCAR=y
 # CONFIG_HWMON is not set
@@ -109,12 +115,14 @@ CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_RCAR=y
 CONFIG_USB=y
-CONFIG_USB_RCAR_GEN2_PHY=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_RCAR_PHY=y
+CONFIG_USB_RCAR_GEN2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_USB_ETH=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
 CONFIG_MMC_SH_MMCIF=y
@@ -141,3 +149,16 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_ARM_UNWIND is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_THERMAL=y
+CONFIG_GENERIC_CPUFREQ_CPU0=y
+CONFIG_REGULATOR_DA9210=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/socfpga_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/socfpga_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/socfpga_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/socfpga_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_HOTPLUG=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
@@ -40,6 +41,15 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
+CONFIG_CAN=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_GW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_C_CAN=y
+CONFIG_CAN_C_CAN_PLATFORM=y
+CONFIG_CAN_DEBUG_DEVICES=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_PROC_DEVICETREE=y
@@ -55,6 +65,14 @@ CONFIG_STMMAC_ETH=y
 CONFIG_MICREL_PHY=y
 # CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set
 CONFIG_INPUT_EVDEV=y
+CONFIG_DWMAC_SOCFPGA=y
+CONFIG_PPS=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_GARP=y
+CONFIG_IPV6=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
@@ -63,7 +81,12 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 CONFIG_SERIAL_8250_DW=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_DWAPB=y
 # CONFIG_RTC_HCTOSYS is not set
+CONFIG_WATCHDOG=y
+CONFIG_DW_WATCHDOG=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -72,6 +95,7 @@ CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
+CONFIG_FHANDLE=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_NTFS_RW=y
@@ -86,5 +110,16 @@ CONFIG_DEBUG_INFO=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DEBUG_USER=y
 CONFIG_XZ_DEC=y
+CONFIG_I2C=y
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_CHARDEV=y
 CONFIG_MMC=y
 CONFIG_MMC_DW=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+CONFIG_USB_DWC2_PLATFORM=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/spear13xx_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/spear13xx_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/spear13xx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/spear13xx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,13 +11,24 @@ CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
 # CONFIG_SWP_EMULATE is not set
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_SPEAR13XX=y
 CONFIG_SMP=y
 # CONFIG_SMP_ON_UP is not set
 # CONFIG_ARM_CPU_TOPOLOGY is not set
+CONFIG_AEABI=y
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_VFP=y
 CONFIG_BINFMT_MISC=y
 CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_OF_PARTS=y
@@ -27,6 +38,7 @@ CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 # CONFIG_SATA_PMP is not set
 CONFIG_SATA_AHCI_PLATFORM=y
@@ -66,6 +78,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SPEAR=y
@@ -79,11 +92,14 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/configs/tegra_defconfig linux-libre-3.17-rc7-gnu/arch/arm/configs/tegra_defconfig
--- linux-libre-3.16-gnu/arch/arm/configs/tegra_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/configs/tegra_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -23,14 +23,11 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_GPIO_PCA953X=y
 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_TEGRA_EMC_SCALING_ENABLE=y
-CONFIG_TRUSTED_FOUNDATIONS=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_TEGRA=y
@@ -74,9 +71,6 @@ CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_TUNNEL=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_CAN=y
-CONFIG_CAN_RAW=y
-CONFIG_CAN_BCM=y
-CONFIG_CAN_DEV=y
 CONFIG_CAN_MCP251X=y
 CONFIG_BT=y
 CONFIG_BT_RFCOMM=y
@@ -96,7 +90,6 @@ CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SPI_NOR=y
-CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_AD525X_DPOT=y
 CONFIG_AD525X_DPOT_I2C=y
@@ -111,6 +104,7 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_IGB=y
 CONFIG_R8169=y
 CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
@@ -125,6 +119,8 @@ CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_TEGRA=y
 CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
 # CONFIG_LEGACY_PTYS is not set
@@ -135,6 +131,7 @@ CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
@@ -144,6 +141,7 @@ CONFIG_SPI_TEGRA20_SFLASH=y
 CONFIG_SPI_TEGRA20_SLINK=y
 CONFIG_PINCTRL_AS3722=y
 CONFIG_PINCTRL_PALMAS=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
@@ -155,10 +153,12 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM95245=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
 CONFIG_MFD_MAX8907=y
+CONFIG_MFD_STMPE=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
 CONFIG_MFD_TPS6586X=y
@@ -221,6 +221,7 @@ CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_ONESHOT=y
@@ -291,5 +292,4 @@ CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_TEGRA_AES=y
 CONFIG_CRC_CCITT=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/aes-armv4.S linux-libre-3.17-rc7-gnu/arch/arm/crypto/aes-armv4.S
--- linux-libre-3.16-gnu/arch/arm/crypto/aes-armv4.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/aes-armv4.S	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 @ that is being targetted.
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 .text
 
@@ -648,7 +649,7 @@ _armv4_AES_set_encrypt_key:
 
 .Ldone:	mov	r0,#0
 	ldmia   sp!,{r4-r12,lr}
-.Labrt:	mov	pc,lr
+.Labrt:	ret	lr
 ENDPROC(private_AES_set_encrypt_key)
 
 .align	5
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/Makefile linux-libre-3.17-rc7-gnu/arch/arm/crypto/Makefile
--- linux-libre-3.16-gnu/arch/arm/crypto/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,10 +5,14 @@
 obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
 obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
 obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
+obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
+obj-$(CONFIG_CRYPTO_SHA512_ARM_NEON) += sha512-arm-neon.o
 
 aes-arm-y	:= aes-armv4.o aes_glue.o
 aes-arm-bs-y	:= aesbs-core.o aesbs-glue.o
 sha1-arm-y	:= sha1-armv4-large.o sha1_glue.o
+sha1-arm-neon-y	:= sha1-armv7-neon.o sha1_neon_glue.o
+sha512-arm-neon-y := sha512-armv7-neon.o sha512_neon_glue.o
 
 quiet_cmd_perl = PERL    $@
       cmd_perl = $(PERL) $(<) > $(@)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/sha1-armv7-neon.S linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1-armv7-neon.S
--- linux-libre-3.16-gnu/arch/arm/crypto/sha1-armv7-neon.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1-armv7-neon.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,634 @@
+/* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
+ *
+ * Copyright Â© 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/linkage.h>
+
+
+.syntax unified
+.code   32
+.fpu neon
+
+.text
+
+
+/* Context structure */
+
+#define state_h0 0
+#define state_h1 4
+#define state_h2 8
+#define state_h3 12
+#define state_h4 16
+
+
+/* Constants */
+
+#define K1  0x5A827999
+#define K2  0x6ED9EBA1
+#define K3  0x8F1BBCDC
+#define K4  0xCA62C1D6
+.align 4
+.LK_VEC:
+.LK1:	.long K1, K1, K1, K1
+.LK2:	.long K2, K2, K2, K2
+.LK3:	.long K3, K3, K3, K3
+.LK4:	.long K4, K4, K4, K4
+
+
+/* Register macros */
+
+#define RSTATE r0
+#define RDATA r1
+#define RNBLKS r2
+#define ROLDSTACK r3
+#define RWK lr
+
+#define _a r4
+#define _b r5
+#define _c r6
+#define _d r7
+#define _e r8
+
+#define RT0 r9
+#define RT1 r10
+#define RT2 r11
+#define RT3 r12
+
+#define W0 q0
+#define W1 q1
+#define W2 q2
+#define W3 q3
+#define W4 q4
+#define W5 q5
+#define W6 q6
+#define W7 q7
+
+#define tmp0 q8
+#define tmp1 q9
+#define tmp2 q10
+#define tmp3 q11
+
+#define qK1 q12
+#define qK2 q13
+#define qK3 q14
+#define qK4 q15
+
+
+/* Round function macros. */
+
+#define WK_offs(i) (((i) & 15) * 4)
+
+#define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	      W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	ldr RT3, [sp, WK_offs(i)]; \
+		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	bic RT0, d, b; \
+	add e, e, a, ror #(32 - 5); \
+	and RT1, c, b; \
+		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add RT0, RT0, RT3; \
+	add e, e, RT1; \
+	ror b, #(32 - 30); \
+		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add e, e, RT0;
+
+#define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	      W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	ldr RT3, [sp, WK_offs(i)]; \
+		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, d, b; \
+	add e, e, a, ror #(32 - 5); \
+	eor RT0, RT0, c; \
+		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add e, e, RT3; \
+	ror b, #(32 - 30); \
+		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add e, e, RT0; \
+
+#define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	      W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	ldr RT3, [sp, WK_offs(i)]; \
+		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, b, c; \
+	and RT1, b, c; \
+	add e, e, a, ror #(32 - 5); \
+		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	and RT0, RT0, d; \
+	add RT1, RT1, RT3; \
+	add e, e, RT0; \
+	ror b, #(32 - 30); \
+		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add e, e, RT1;
+
+#define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	      W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	_R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	      W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define _R(a,b,c,d,e,f,i,pre1,pre2,pre3,i16,\
+           W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	_R_##f(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+	       W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define R(a,b,c,d,e,f,i) \
+	_R_##f(a,b,c,d,e,i,dummy,dummy,dummy,i16,\
+	       W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define dummy(...)
+
+
+/* Input expansion macros. */
+
+/********* Precalc macros for rounds 0-15 *************************************/
+
+#define W_PRECALC_00_15() \
+	add       RWK, sp, #(WK_offs(0));			\
+	\
+	vld1.32   {tmp0, tmp1}, [RDATA]!;			\
+	vrev32.8  W0, tmp0;		/* big => little */	\
+	vld1.32   {tmp2, tmp3}, [RDATA]!;			\
+	vadd.u32  tmp0, W0, curK;				\
+	vrev32.8  W7, tmp1;		/* big => little */	\
+	vrev32.8  W6, tmp2;		/* big => little */	\
+	vadd.u32  tmp1, W7, curK;				\
+	vrev32.8  W5, tmp3;		/* big => little */	\
+	vadd.u32  tmp2, W6, curK;				\
+	vst1.32   {tmp0, tmp1}, [RWK]!;				\
+	vadd.u32  tmp3, W5, curK;				\
+	vst1.32   {tmp2, tmp3}, [RWK];				\
+
+#define WPRECALC_00_15_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vld1.32   {tmp0, tmp1}, [RDATA]!;			\
+
+#define WPRECALC_00_15_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	add       RWK, sp, #(WK_offs(0));			\
+
+#define WPRECALC_00_15_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vrev32.8  W0, tmp0;		/* big => little */	\
+
+#define WPRECALC_00_15_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vld1.32   {tmp2, tmp3}, [RDATA]!;			\
+
+#define WPRECALC_00_15_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32  tmp0, W0, curK;				\
+
+#define WPRECALC_00_15_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vrev32.8  W7, tmp1;		/* big => little */	\
+
+#define WPRECALC_00_15_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vrev32.8  W6, tmp2;		/* big => little */	\
+
+#define WPRECALC_00_15_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32  tmp1, W7, curK;				\
+
+#define WPRECALC_00_15_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vrev32.8  W5, tmp3;		/* big => little */	\
+
+#define WPRECALC_00_15_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32  tmp2, W6, curK;				\
+
+#define WPRECALC_00_15_10(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vst1.32   {tmp0, tmp1}, [RWK]!;				\
+
+#define WPRECALC_00_15_11(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32  tmp3, W5, curK;				\
+
+#define WPRECALC_00_15_12(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vst1.32   {tmp2, tmp3}, [RWK];				\
+
+
+/********* Precalc macros for rounds 16-31 ************************************/
+
+#define WPRECALC_16_31_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor      tmp0, tmp0;			\
+	vext.8    W, W_m16, W_m12, #8;		\
+
+#define WPRECALC_16_31_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	add       RWK, sp, #(WK_offs(i));	\
+	vext.8    tmp0, W_m04, tmp0, #4;	\
+
+#define WPRECALC_16_31_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor      tmp0, tmp0, W_m16;		\
+	veor.32   W, W, W_m08;			\
+
+#define WPRECALC_16_31_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor      tmp1, tmp1;			\
+	veor      W, W, tmp0;			\
+
+#define WPRECALC_16_31_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vshl.u32  tmp0, W, #1;			\
+
+#define WPRECALC_16_31_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vext.8    tmp1, tmp1, W, #(16-12);	\
+	vshr.u32  W, W, #31;			\
+
+#define WPRECALC_16_31_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vorr      tmp0, tmp0, W;		\
+	vshr.u32  W, tmp1, #30;			\
+
+#define WPRECALC_16_31_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vshl.u32  tmp1, tmp1, #2;		\
+
+#define WPRECALC_16_31_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor      tmp0, tmp0, W;		\
+
+#define WPRECALC_16_31_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor      W, tmp0, tmp1;		\
+
+#define WPRECALC_16_31_10(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32  tmp0, W, curK;		\
+
+#define WPRECALC_16_31_11(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vst1.32   {tmp0}, [RWK];
+
+
+/********* Precalc macros for rounds 32-79 ************************************/
+
+#define WPRECALC_32_79_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor W, W_m28; \
+
+#define WPRECALC_32_79_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vext.8 tmp0, W_m08, W_m04, #8; \
+
+#define WPRECALC_32_79_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor W, W_m16; \
+
+#define WPRECALC_32_79_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	veor W, tmp0; \
+
+#define WPRECALC_32_79_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	add RWK, sp, #(WK_offs(i&~3)); \
+
+#define WPRECALC_32_79_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vshl.u32 tmp1, W, #2; \
+
+#define WPRECALC_32_79_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vshr.u32 tmp0, W, #30; \
+
+#define WPRECALC_32_79_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vorr W, tmp0, tmp1; \
+
+#define WPRECALC_32_79_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vadd.u32 tmp0, W, curK; \
+
+#define WPRECALC_32_79_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+	vst1.32 {tmp0}, [RWK];
+
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ *
+ * unsigned int
+ * sha1_transform_neon (void *ctx, const unsigned char *data,
+ *                      unsigned int nblks)
+ */
+.align 3
+ENTRY(sha1_transform_neon)
+  /* input:
+   *	r0: ctx, CTX
+   *	r1: data (64*nblks bytes)
+   *	r2: nblks
+   */
+
+  cmp RNBLKS, #0;
+  beq .Ldo_nothing;
+
+  push {r4-r12, lr};
+  /*vpush {q4-q7};*/
+
+  adr RT3, .LK_VEC;
+
+  mov ROLDSTACK, sp;
+
+  /* Align stack. */
+  sub RT0, sp, #(16*4);
+  and RT0, #(~(16-1));
+  mov sp, RT0;
+
+  vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
+
+  /* Get the values of the chaining variables. */
+  ldm RSTATE, {_a-_e};
+
+  vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
+
+#undef curK
+#define curK qK1
+  /* Precalc 0-15. */
+  W_PRECALC_00_15();
+
+.Loop:
+  /* Transform 0-15 + Precalc 16-31. */
+  _R( _a, _b, _c, _d, _e, F1,  0,
+      WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 16,
+      W4, W5, W6, W7, W0, _, _, _ );
+  _R( _e, _a, _b, _c, _d, F1,  1,
+      WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 16,
+      W4, W5, W6, W7, W0, _, _, _ );
+  _R( _d, _e, _a, _b, _c, F1,  2,
+      WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16,
+      W4, W5, W6, W7, W0, _, _, _ );
+  _R( _c, _d, _e, _a, _b, F1,  3,
+      WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16,
+      W4, W5, W6, W7, W0, _, _, _ );
+
+#undef curK
+#define curK qK2
+  _R( _b, _c, _d, _e, _a, F1,  4,
+      WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20,
+      W3, W4, W5, W6, W7, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F1,  5,
+      WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20,
+      W3, W4, W5, W6, W7, _, _, _ );
+  _R( _e, _a, _b, _c, _d, F1,  6,
+      WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20,
+      W3, W4, W5, W6, W7, _, _, _ );
+  _R( _d, _e, _a, _b, _c, F1,  7,
+      WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,20,
+      W3, W4, W5, W6, W7, _, _, _ );
+
+  _R( _c, _d, _e, _a, _b, F1,  8,
+      WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 24,
+      W2, W3, W4, W5, W6, _, _, _ );
+  _R( _b, _c, _d, _e, _a, F1,  9,
+      WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 24,
+      W2, W3, W4, W5, W6, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F1, 10,
+      WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 24,
+      W2, W3, W4, W5, W6, _, _, _ );
+  _R( _e, _a, _b, _c, _d, F1, 11,
+      WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,24,
+      W2, W3, W4, W5, W6, _, _, _ );
+
+  _R( _d, _e, _a, _b, _c, F1, 12,
+      WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 28,
+      W1, W2, W3, W4, W5, _, _, _ );
+  _R( _c, _d, _e, _a, _b, F1, 13,
+      WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 28,
+      W1, W2, W3, W4, W5, _, _, _ );
+  _R( _b, _c, _d, _e, _a, F1, 14,
+      WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 28,
+      W1, W2, W3, W4, W5, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F1, 15,
+      WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,28,
+      W1, W2, W3, W4, W5, _, _, _ );
+
+  /* Transform 16-63 + Precalc 32-79. */
+  _R( _e, _a, _b, _c, _d, F1, 16,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _d, _e, _a, _b, _c, F1, 17,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _c, _d, _e, _a, _b, F1, 18,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 32,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _b, _c, _d, _e, _a, F1, 19,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 32,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+
+  _R( _a, _b, _c, _d, _e, F2, 20,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _e, _a, _b, _c, _d, F2, 21,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _d, _e, _a, _b, _c, F2, 22,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 36,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _c, _d, _e, _a, _b, F2, 23,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 36,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+
+#undef curK
+#define curK qK3
+  _R( _b, _c, _d, _e, _a, F2, 24,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _a, _b, _c, _d, _e, F2, 25,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _e, _a, _b, _c, _d, F2, 26,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 40,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _d, _e, _a, _b, _c, F2, 27,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 40,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+
+  _R( _c, _d, _e, _a, _b, F2, 28,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _b, _c, _d, _e, _a, F2, 29,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _a, _b, _c, _d, _e, F2, 30,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 44,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _e, _a, _b, _c, _d, F2, 31,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 44,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+
+  _R( _d, _e, _a, _b, _c, F2, 32,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48,
+      W4, W5, W6, W7, W0, W1, W2, W3);
+  _R( _c, _d, _e, _a, _b, F2, 33,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48,
+      W4, W5, W6, W7, W0, W1, W2, W3);
+  _R( _b, _c, _d, _e, _a, F2, 34,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 48,
+      W4, W5, W6, W7, W0, W1, W2, W3);
+  _R( _a, _b, _c, _d, _e, F2, 35,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 48,
+      W4, W5, W6, W7, W0, W1, W2, W3);
+
+  _R( _e, _a, _b, _c, _d, F2, 36,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52,
+      W3, W4, W5, W6, W7, W0, W1, W2);
+  _R( _d, _e, _a, _b, _c, F2, 37,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52,
+      W3, W4, W5, W6, W7, W0, W1, W2);
+  _R( _c, _d, _e, _a, _b, F2, 38,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 52,
+      W3, W4, W5, W6, W7, W0, W1, W2);
+  _R( _b, _c, _d, _e, _a, F2, 39,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 52,
+      W3, W4, W5, W6, W7, W0, W1, W2);
+
+  _R( _a, _b, _c, _d, _e, F3, 40,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56,
+      W2, W3, W4, W5, W6, W7, W0, W1);
+  _R( _e, _a, _b, _c, _d, F3, 41,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56,
+      W2, W3, W4, W5, W6, W7, W0, W1);
+  _R( _d, _e, _a, _b, _c, F3, 42,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 56,
+      W2, W3, W4, W5, W6, W7, W0, W1);
+  _R( _c, _d, _e, _a, _b, F3, 43,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 56,
+      W2, W3, W4, W5, W6, W7, W0, W1);
+
+#undef curK
+#define curK qK4
+  _R( _b, _c, _d, _e, _a, F3, 44,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60,
+      W1, W2, W3, W4, W5, W6, W7, W0);
+  _R( _a, _b, _c, _d, _e, F3, 45,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60,
+      W1, W2, W3, W4, W5, W6, W7, W0);
+  _R( _e, _a, _b, _c, _d, F3, 46,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 60,
+      W1, W2, W3, W4, W5, W6, W7, W0);
+  _R( _d, _e, _a, _b, _c, F3, 47,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 60,
+      W1, W2, W3, W4, W5, W6, W7, W0);
+
+  _R( _c, _d, _e, _a, _b, F3, 48,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _b, _c, _d, _e, _a, F3, 49,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _a, _b, _c, _d, _e, F3, 50,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 64,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _e, _a, _b, _c, _d, F3, 51,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 64,
+      W0, W1, W2, W3, W4, W5, W6, W7);
+
+  _R( _d, _e, _a, _b, _c, F3, 52,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _c, _d, _e, _a, _b, F3, 53,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _b, _c, _d, _e, _a, F3, 54,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 68,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _a, _b, _c, _d, _e, F3, 55,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 68,
+      W7, W0, W1, W2, W3, W4, W5, W6);
+
+  _R( _e, _a, _b, _c, _d, F3, 56,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _d, _e, _a, _b, _c, F3, 57,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _c, _d, _e, _a, _b, F3, 58,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 72,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _b, _c, _d, _e, _a, F3, 59,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 72,
+      W6, W7, W0, W1, W2, W3, W4, W5);
+
+  subs RNBLKS, #1;
+
+  _R( _a, _b, _c, _d, _e, F4, 60,
+      WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _e, _a, _b, _c, _d, F4, 61,
+      WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _d, _e, _a, _b, _c, F4, 62,
+      WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 76,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _c, _d, _e, _a, _b, F4, 63,
+      WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 76,
+      W5, W6, W7, W0, W1, W2, W3, W4);
+
+  beq .Lend;
+
+  /* Transform 64-79 + Precalc 0-15 of next block. */
+#undef curK
+#define curK qK1
+  _R( _b, _c, _d, _e, _a, F4, 64,
+      WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F4, 65,
+      WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _e, _a, _b, _c, _d, F4, 66,
+      WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _d, _e, _a, _b, _c, F4, 67,
+      WPRECALC_00_15_3, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+  _R( _c, _d, _e, _a, _b, F4, 68,
+      dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _b, _c, _d, _e, _a, F4, 69,
+      dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F4, 70,
+      WPRECALC_00_15_4, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _e, _a, _b, _c, _d, F4, 71,
+      WPRECALC_00_15_5, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+  _R( _d, _e, _a, _b, _c, F4, 72,
+      dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _c, _d, _e, _a, _b, F4, 73,
+      dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _b, _c, _d, _e, _a, F4, 74,
+      WPRECALC_00_15_6, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _a, _b, _c, _d, _e, F4, 75,
+      WPRECALC_00_15_7, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+  _R( _e, _a, _b, _c, _d, F4, 76,
+      WPRECALC_00_15_8, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _d, _e, _a, _b, _c, F4, 77,
+      WPRECALC_00_15_9, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _c, _d, _e, _a, _b, F4, 78,
+      WPRECALC_00_15_10, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+  _R( _b, _c, _d, _e, _a, F4, 79,
+      WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );
+
+  /* Update the chaining variables. */
+  ldm RSTATE, {RT0-RT3};
+  add _a, RT0;
+  ldr RT0, [RSTATE, #state_h4];
+  add _b, RT1;
+  add _c, RT2;
+  add _d, RT3;
+  add _e, RT0;
+  stm RSTATE, {_a-_e};
+
+  b .Loop;
+
+.Lend:
+  /* Transform 64-79 */
+  R( _b, _c, _d, _e, _a, F4, 64 );
+  R( _a, _b, _c, _d, _e, F4, 65 );
+  R( _e, _a, _b, _c, _d, F4, 66 );
+  R( _d, _e, _a, _b, _c, F4, 67 );
+  R( _c, _d, _e, _a, _b, F4, 68 );
+  R( _b, _c, _d, _e, _a, F4, 69 );
+  R( _a, _b, _c, _d, _e, F4, 70 );
+  R( _e, _a, _b, _c, _d, F4, 71 );
+  R( _d, _e, _a, _b, _c, F4, 72 );
+  R( _c, _d, _e, _a, _b, F4, 73 );
+  R( _b, _c, _d, _e, _a, F4, 74 );
+  R( _a, _b, _c, _d, _e, F4, 75 );
+  R( _e, _a, _b, _c, _d, F4, 76 );
+  R( _d, _e, _a, _b, _c, F4, 77 );
+  R( _c, _d, _e, _a, _b, F4, 78 );
+  R( _b, _c, _d, _e, _a, F4, 79 );
+
+  mov sp, ROLDSTACK;
+
+  /* Update the chaining variables. */
+  ldm RSTATE, {RT0-RT3};
+  add _a, RT0;
+  ldr RT0, [RSTATE, #state_h4];
+  add _b, RT1;
+  add _c, RT2;
+  add _d, RT3;
+  /*vpop {q4-q7};*/
+  add _e, RT0;
+  stm RSTATE, {_a-_e};
+
+  pop {r4-r12, pc};
+
+.Ldo_nothing:
+  bx lr
+ENDPROC(sha1_transform_neon)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/sha1_glue.c linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1_glue.c
--- linux-libre-3.16-gnu/arch/arm/crypto/sha1_glue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,32 +23,27 @@
 #include <linux/types.h>
 #include <crypto/sha.h>
 #include <asm/byteorder.h>
+#include <asm/crypto/sha1.h>
 
-struct SHA1_CTX {
-	uint32_t h0,h1,h2,h3,h4;
-	u64 count;
-	u8 data[SHA1_BLOCK_SIZE];
-};
 
-asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest,
+asmlinkage void sha1_block_data_order(u32 *digest,
 		const unsigned char *data, unsigned int rounds);
 
 
 static int sha1_init(struct shash_desc *desc)
 {
-	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
-	memset(sctx, 0, sizeof(*sctx));
-	sctx->h0 = SHA1_H0;
-	sctx->h1 = SHA1_H1;
-	sctx->h2 = SHA1_H2;
-	sctx->h3 = SHA1_H3;
-	sctx->h4 = SHA1_H4;
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
 	return 0;
 }
 
 
-static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data,
-			       unsigned int len, unsigned int partial)
+static int __sha1_update(struct sha1_state *sctx, const u8 *data,
+			 unsigned int len, unsigned int partial)
 {
 	unsigned int done = 0;
 
@@ -56,43 +51,44 @@ static int __sha1_update(struct SHA1_CTX
 
 	if (partial) {
 		done = SHA1_BLOCK_SIZE - partial;
-		memcpy(sctx->data + partial, data, done);
-		sha1_block_data_order(sctx, sctx->data, 1);
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_block_data_order(sctx->state, sctx->buffer, 1);
 	}
 
 	if (len - done >= SHA1_BLOCK_SIZE) {
 		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
-		sha1_block_data_order(sctx, data + done, rounds);
+		sha1_block_data_order(sctx->state, data + done, rounds);
 		done += rounds * SHA1_BLOCK_SIZE;
 	}
 
-	memcpy(sctx->data, data + done, len - done);
+	memcpy(sctx->buffer, data + done, len - done);
 	return 0;
 }
 
 
-static int sha1_update(struct shash_desc *desc, const u8 *data,
-			     unsigned int len)
+int sha1_update_arm(struct shash_desc *desc, const u8 *data,
+		    unsigned int len)
 {
-	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	struct sha1_state *sctx = shash_desc_ctx(desc);
 	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
 	int res;
 
 	/* Handle the fast case right here */
 	if (partial + len < SHA1_BLOCK_SIZE) {
 		sctx->count += len;
-		memcpy(sctx->data + partial, data, len);
+		memcpy(sctx->buffer + partial, data, len);
 		return 0;
 	}
 	res = __sha1_update(sctx, data, len, partial);
 	return res;
 }
+EXPORT_SYMBOL_GPL(sha1_update_arm);
 
 
 /* Add padding and return the message digest. */
 static int sha1_final(struct shash_desc *desc, u8 *out)
 {
-	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	struct sha1_state *sctx = shash_desc_ctx(desc);
 	unsigned int i, index, padlen;
 	__be32 *dst = (__be32 *)out;
 	__be64 bits;
@@ -106,7 +102,7 @@ static int sha1_final(struct shash_desc
 	/* We need to fill a whole block for __sha1_update() */
 	if (padlen <= 56) {
 		sctx->count += padlen;
-		memcpy(sctx->data + index, padding, padlen);
+		memcpy(sctx->buffer + index, padding, padlen);
 	} else {
 		__sha1_update(sctx, padding, padlen, index);
 	}
@@ -114,7 +110,7 @@ static int sha1_final(struct shash_desc
 
 	/* Store state in digest */
 	for (i = 0; i < 5; i++)
-		dst[i] = cpu_to_be32(((u32 *)sctx)[i]);
+		dst[i] = cpu_to_be32(sctx->state[i]);
 
 	/* Wipe context */
 	memset(sctx, 0, sizeof(*sctx));
@@ -124,7 +120,7 @@ static int sha1_final(struct shash_desc
 
 static int sha1_export(struct shash_desc *desc, void *out)
 {
-	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	struct sha1_state *sctx = shash_desc_ctx(desc);
 	memcpy(out, sctx, sizeof(*sctx));
 	return 0;
 }
@@ -132,7 +128,7 @@ static int sha1_export(struct shash_desc
 
 static int sha1_import(struct shash_desc *desc, const void *in)
 {
-	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	struct sha1_state *sctx = shash_desc_ctx(desc);
 	memcpy(sctx, in, sizeof(*sctx));
 	return 0;
 }
@@ -141,12 +137,12 @@ static int sha1_import(struct shash_desc
 static struct shash_alg alg = {
 	.digestsize	=	SHA1_DIGEST_SIZE,
 	.init		=	sha1_init,
-	.update		=	sha1_update,
+	.update		=	sha1_update_arm,
 	.final		=	sha1_final,
 	.export		=	sha1_export,
 	.import		=	sha1_import,
-	.descsize	=	sizeof(struct SHA1_CTX),
-	.statesize	=	sizeof(struct SHA1_CTX),
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
 	.base		=	{
 		.cra_name	=	"sha1",
 		.cra_driver_name=	"sha1-asm",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/sha1_neon_glue.c linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1_neon_glue.c
--- linux-libre-3.16-gnu/arch/arm/crypto/sha1_neon_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha1_neon_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * ARM NEON instructions.
+ *
+ * Copyright Â© 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is based on sha1_generic.c and sha1_ssse3_glue.c:
+ *  Copyright (c) Alan Smithee.
+ *  Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ *  Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ *  Copyright (c) Mathias Krause <minipli@googlemail.com>
+ *  Copyright (c) Chandramouli Narayanan <mouli@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; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/crypto/sha1.h>
+
+
+asmlinkage void sha1_transform_neon(void *state_h, const char *data,
+				    unsigned int rounds);
+
+
+static int sha1_neon_init(struct shash_desc *desc)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
+	return 0;
+}
+
+static int __sha1_neon_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_transform_neon(sctx->state, sctx->buffer, 1);
+	}
+
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+		sha1_transform_neon(sctx->state, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buffer, data + done, len - done);
+
+	return 0;
+}
+
+static int sha1_neon_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buffer + partial, data, len);
+
+		return 0;
+	}
+
+	if (!may_use_simd()) {
+		res = sha1_update_arm(desc, data, len);
+	} else {
+		kernel_neon_begin();
+		res = __sha1_neon_update(desc, data, len, partial);
+		kernel_neon_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_neon_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+	if (!may_use_simd()) {
+		sha1_update_arm(desc, padding, padlen);
+		sha1_update_arm(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_neon_begin();
+		/* We need to fill a whole block for __sha1_neon_update() */
+		if (padlen <= 56) {
+			sctx->count += padlen;
+			memcpy(sctx->buffer + index, padding, padlen);
+		} else {
+			__sha1_neon_update(desc, padding, padlen, index);
+		}
+		__sha1_neon_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+		kernel_neon_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_neon_export(struct shash_desc *desc, void *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_neon_import(struct shash_desc *desc, const void *in)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_neon_init,
+	.update		=	sha1_neon_update,
+	.final		=	sha1_neon_final,
+	.export		=	sha1_neon_export,
+	.import		=	sha1_neon_import,
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
+	.base		=	{
+		.cra_name		= "sha1",
+		.cra_driver_name	= "sha1-neon",
+		.cra_priority		= 250,
+		.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize		= SHA1_BLOCK_SIZE,
+		.cra_module		= THIS_MODULE,
+	}
+};
+
+static int __init sha1_neon_mod_init(void)
+{
+	if (!cpu_has_neon())
+		return -ENODEV;
+
+	return crypto_register_shash(&alg);
+}
+
+static void __exit sha1_neon_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_neon_mod_init);
+module_exit(sha1_neon_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, NEON accelerated");
+MODULE_ALIAS("sha1");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/sha512-armv7-neon.S linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha512-armv7-neon.S
--- linux-libre-3.16-gnu/arch/arm/crypto/sha512-armv7-neon.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha512-armv7-neon.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,455 @@
+/* sha512-armv7-neon.S  -  ARM/NEON assembly implementation of SHA-512 transform
+ *
+ * Copyright Â© 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/linkage.h>
+
+
+.syntax unified
+.code   32
+.fpu neon
+
+.text
+
+/* structure of SHA512_CONTEXT */
+#define hd_a 0
+#define hd_b ((hd_a) + 8)
+#define hd_c ((hd_b) + 8)
+#define hd_d ((hd_c) + 8)
+#define hd_e ((hd_d) + 8)
+#define hd_f ((hd_e) + 8)
+#define hd_g ((hd_f) + 8)
+
+/* register macros */
+#define RK %r2
+
+#define RA d0
+#define RB d1
+#define RC d2
+#define RD d3
+#define RE d4
+#define RF d5
+#define RG d6
+#define RH d7
+
+#define RT0 d8
+#define RT1 d9
+#define RT2 d10
+#define RT3 d11
+#define RT4 d12
+#define RT5 d13
+#define RT6 d14
+#define RT7 d15
+
+#define RT01q q4
+#define RT23q q5
+#define RT45q q6
+#define RT67q q7
+
+#define RW0 d16
+#define RW1 d17
+#define RW2 d18
+#define RW3 d19
+#define RW4 d20
+#define RW5 d21
+#define RW6 d22
+#define RW7 d23
+#define RW8 d24
+#define RW9 d25
+#define RW10 d26
+#define RW11 d27
+#define RW12 d28
+#define RW13 d29
+#define RW14 d30
+#define RW15 d31
+
+#define RW01q q8
+#define RW23q q9
+#define RW45q q10
+#define RW67q q11
+#define RW89q q12
+#define RW1011q q13
+#define RW1213q q14
+#define RW1415q q15
+
+/***********************************************************************
+ * ARM assembly implementation of sha512 transform
+ ***********************************************************************/
+#define rounds2_0_63(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, rw01q, rw2, \
+                     rw23q, rw1415q, rw9, rw10, interleave_op, arg1) \
+	/* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
+	vshr.u64 RT2, re, #14; \
+	vshl.u64 RT3, re, #64 - 14; \
+	interleave_op(arg1); \
+	vshr.u64 RT4, re, #18; \
+	vshl.u64 RT5, re, #64 - 18; \
+	vld1.64 {RT0}, [RK]!; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, re, #41; \
+	vshl.u64 RT5, re, #64 - 41; \
+	vadd.u64 RT0, RT0, rw0; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vmov.64 RT7, re; \
+	veor.64 RT1, RT2, RT3; \
+	vbsl.64 RT7, rf, rg; \
+	\
+	vadd.u64 RT1, RT1, rh; \
+	vshr.u64 RT2, ra, #28; \
+	vshl.u64 RT3, ra, #64 - 28; \
+	vadd.u64 RT1, RT1, RT0; \
+	vshr.u64 RT4, ra, #34; \
+	vshl.u64 RT5, ra, #64 - 34; \
+	vadd.u64 RT1, RT1, RT7; \
+	\
+	/* h = Sum0 (a) + Maj (a, b, c); */ \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, ra, #39; \
+	vshl.u64 RT5, ra, #64 - 39; \
+	veor.64 RT0, ra, rb; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vbsl.64 RT0, rc, rb; \
+	vadd.u64 rd, rd, RT1; /* d+=t1; */ \
+	veor.64 rh, RT2, RT3; \
+	\
+	/* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
+	vshr.u64 RT2, rd, #14; \
+	vshl.u64 RT3, rd, #64 - 14; \
+	vadd.u64 rh, rh, RT0; \
+	vshr.u64 RT4, rd, #18; \
+	vshl.u64 RT5, rd, #64 - 18; \
+	vadd.u64 rh, rh, RT1; /* h+=t1; */ \
+	vld1.64 {RT0}, [RK]!; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, rd, #41; \
+	vshl.u64 RT5, rd, #64 - 41; \
+	vadd.u64 RT0, RT0, rw1; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vmov.64 RT7, rd; \
+	veor.64 RT1, RT2, RT3; \
+	vbsl.64 RT7, re, rf; \
+	\
+	vadd.u64 RT1, RT1, rg; \
+	vshr.u64 RT2, rh, #28; \
+	vshl.u64 RT3, rh, #64 - 28; \
+	vadd.u64 RT1, RT1, RT0; \
+	vshr.u64 RT4, rh, #34; \
+	vshl.u64 RT5, rh, #64 - 34; \
+	vadd.u64 RT1, RT1, RT7; \
+	\
+	/* g = Sum0 (h) + Maj (h, a, b); */ \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, rh, #39; \
+	vshl.u64 RT5, rh, #64 - 39; \
+	veor.64 RT0, rh, ra; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vbsl.64 RT0, rb, ra; \
+	vadd.u64 rc, rc, RT1; /* c+=t1; */ \
+	veor.64 rg, RT2, RT3; \
+	\
+	/* w[0] += S1 (w[14]) + w[9] + S0 (w[1]); */ \
+	/* w[1] += S1 (w[15]) + w[10] + S0 (w[2]); */ \
+	\
+	/**** S0(w[1:2]) */ \
+	\
+	/* w[0:1] += w[9:10] */ \
+	/* RT23q = rw1:rw2 */ \
+	vext.u64 RT23q, rw01q, rw23q, #1; \
+	vadd.u64 rw0, rw9; \
+	vadd.u64 rg, rg, RT0; \
+	vadd.u64 rw1, rw10;\
+	vadd.u64 rg, rg, RT1; /* g+=t1; */ \
+	\
+	vshr.u64 RT45q, RT23q, #1; \
+	vshl.u64 RT67q, RT23q, #64 - 1; \
+	vshr.u64 RT01q, RT23q, #8; \
+	veor.u64 RT45q, RT45q, RT67q; \
+	vshl.u64 RT67q, RT23q, #64 - 8; \
+	veor.u64 RT45q, RT45q, RT01q; \
+	vshr.u64 RT01q, RT23q, #7; \
+	veor.u64 RT45q, RT45q, RT67q; \
+	\
+	/**** S1(w[14:15]) */ \
+	vshr.u64 RT23q, rw1415q, #6; \
+	veor.u64 RT01q, RT01q, RT45q; \
+	vshr.u64 RT45q, rw1415q, #19; \
+	vshl.u64 RT67q, rw1415q, #64 - 19; \
+	veor.u64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT45q, rw1415q, #61; \
+	veor.u64 RT23q, RT23q, RT67q; \
+	vshl.u64 RT67q, rw1415q, #64 - 61; \
+	veor.u64 RT23q, RT23q, RT45q; \
+	vadd.u64 rw01q, RT01q; /* w[0:1] += S(w[1:2]) */ \
+	veor.u64 RT01q, RT23q, RT67q;
+#define vadd_RT01q(rw01q) \
+	/* w[0:1] += S(w[14:15]) */ \
+	vadd.u64 rw01q, RT01q;
+
+#define dummy(_) /*_*/
+
+#define rounds2_64_79(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, \
+	              interleave_op1, arg1, interleave_op2, arg2) \
+	/* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
+	vshr.u64 RT2, re, #14; \
+	vshl.u64 RT3, re, #64 - 14; \
+	interleave_op1(arg1); \
+	vshr.u64 RT4, re, #18; \
+	vshl.u64 RT5, re, #64 - 18; \
+	interleave_op2(arg2); \
+	vld1.64 {RT0}, [RK]!; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, re, #41; \
+	vshl.u64 RT5, re, #64 - 41; \
+	vadd.u64 RT0, RT0, rw0; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vmov.64 RT7, re; \
+	veor.64 RT1, RT2, RT3; \
+	vbsl.64 RT7, rf, rg; \
+	\
+	vadd.u64 RT1, RT1, rh; \
+	vshr.u64 RT2, ra, #28; \
+	vshl.u64 RT3, ra, #64 - 28; \
+	vadd.u64 RT1, RT1, RT0; \
+	vshr.u64 RT4, ra, #34; \
+	vshl.u64 RT5, ra, #64 - 34; \
+	vadd.u64 RT1, RT1, RT7; \
+	\
+	/* h = Sum0 (a) + Maj (a, b, c); */ \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, ra, #39; \
+	vshl.u64 RT5, ra, #64 - 39; \
+	veor.64 RT0, ra, rb; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vbsl.64 RT0, rc, rb; \
+	vadd.u64 rd, rd, RT1; /* d+=t1; */ \
+	veor.64 rh, RT2, RT3; \
+	\
+	/* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
+	vshr.u64 RT2, rd, #14; \
+	vshl.u64 RT3, rd, #64 - 14; \
+	vadd.u64 rh, rh, RT0; \
+	vshr.u64 RT4, rd, #18; \
+	vshl.u64 RT5, rd, #64 - 18; \
+	vadd.u64 rh, rh, RT1; /* h+=t1; */ \
+	vld1.64 {RT0}, [RK]!; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, rd, #41; \
+	vshl.u64 RT5, rd, #64 - 41; \
+	vadd.u64 RT0, RT0, rw1; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vmov.64 RT7, rd; \
+	veor.64 RT1, RT2, RT3; \
+	vbsl.64 RT7, re, rf; \
+	\
+	vadd.u64 RT1, RT1, rg; \
+	vshr.u64 RT2, rh, #28; \
+	vshl.u64 RT3, rh, #64 - 28; \
+	vadd.u64 RT1, RT1, RT0; \
+	vshr.u64 RT4, rh, #34; \
+	vshl.u64 RT5, rh, #64 - 34; \
+	vadd.u64 RT1, RT1, RT7; \
+	\
+	/* g = Sum0 (h) + Maj (h, a, b); */ \
+	veor.64 RT23q, RT23q, RT45q; \
+	vshr.u64 RT4, rh, #39; \
+	vshl.u64 RT5, rh, #64 - 39; \
+	veor.64 RT0, rh, ra; \
+	veor.64 RT23q, RT23q, RT45q; \
+	vbsl.64 RT0, rb, ra; \
+	vadd.u64 rc, rc, RT1; /* c+=t1; */ \
+	veor.64 rg, RT2, RT3;
+#define vadd_rg_RT0(rg) \
+	vadd.u64 rg, rg, RT0;
+#define vadd_rg_RT1(rg) \
+	vadd.u64 rg, rg, RT1; /* g+=t1; */
+
+.align 3
+ENTRY(sha512_transform_neon)
+	/* Input:
+	 *	%r0: SHA512_CONTEXT
+	 *	%r1: data
+	 *	%r2: u64 k[] constants
+	 *	%r3: nblks
+	 */
+	push {%lr};
+
+	mov %lr, #0;
+
+	/* Load context to d0-d7 */
+	vld1.64 {RA-RD}, [%r0]!;
+	vld1.64 {RE-RH}, [%r0];
+	sub %r0, #(4*8);
+
+	/* Load input to w[16], d16-d31 */
+	/* NOTE: Assumes that on ARMv7 unaligned accesses are always allowed. */
+	vld1.64 {RW0-RW3}, [%r1]!;
+	vld1.64 {RW4-RW7}, [%r1]!;
+	vld1.64 {RW8-RW11}, [%r1]!;
+	vld1.64 {RW12-RW15}, [%r1]!;
+#ifdef __ARMEL__
+	/* byteswap */
+	vrev64.8 RW01q, RW01q;
+	vrev64.8 RW23q, RW23q;
+	vrev64.8 RW45q, RW45q;
+	vrev64.8 RW67q, RW67q;
+	vrev64.8 RW89q, RW89q;
+	vrev64.8 RW1011q, RW1011q;
+	vrev64.8 RW1213q, RW1213q;
+	vrev64.8 RW1415q, RW1415q;
+#endif
+
+	/* EABI says that d8-d15 must be preserved by callee. */
+	/*vpush {RT0-RT7};*/
+
+.Loop:
+	rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2,
+		     RW23q, RW1415q, RW9, RW10, dummy, _);
+	b .Lenter_rounds;
+
+.Loop_rounds:
+	rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2,
+		     RW23q, RW1415q, RW9, RW10, vadd_RT01q, RW1415q);
+.Lenter_rounds:
+	rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3, RW23q, RW4,
+		     RW45q, RW01q, RW11, RW12, vadd_RT01q, RW01q);
+	rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5, RW45q, RW6,
+		     RW67q, RW23q, RW13, RW14, vadd_RT01q, RW23q);
+	rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7, RW67q, RW8,
+		     RW89q, RW45q, RW15, RW0, vadd_RT01q, RW45q);
+	rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9, RW89q, RW10,
+		     RW1011q, RW67q, RW1, RW2, vadd_RT01q, RW67q);
+	rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11, RW1011q, RW12,
+		     RW1213q, RW89q, RW3, RW4, vadd_RT01q, RW89q);
+	add %lr, #16;
+	rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, RW1213q, RW14,
+		     RW1415q, RW1011q, RW5, RW6, vadd_RT01q, RW1011q);
+	cmp %lr, #64;
+	rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, RW1415q, RW0,
+		     RW01q, RW1213q, RW7, RW8, vadd_RT01q, RW1213q);
+	bne .Loop_rounds;
+
+	subs %r3, #1;
+
+	rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1,
+		      vadd_RT01q, RW1415q, dummy, _);
+	rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3,
+		      vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+	beq .Lhandle_tail;
+	vld1.64 {RW0-RW3}, [%r1]!;
+	rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5,
+		      vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+	rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7,
+		      vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+#ifdef __ARMEL__
+	vrev64.8 RW01q, RW01q;
+	vrev64.8 RW23q, RW23q;
+#endif
+	vld1.64 {RW4-RW7}, [%r1]!;
+	rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9,
+		      vadd_rg_RT0, RA, vadd_rg_RT1, RA);
+	rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11,
+		      vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+#ifdef __ARMEL__
+	vrev64.8 RW45q, RW45q;
+	vrev64.8 RW67q, RW67q;
+#endif
+	vld1.64 {RW8-RW11}, [%r1]!;
+	rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13,
+		      vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+	rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15,
+		      vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+#ifdef __ARMEL__
+	vrev64.8 RW89q, RW89q;
+	vrev64.8 RW1011q, RW1011q;
+#endif
+	vld1.64 {RW12-RW15}, [%r1]!;
+	vadd_rg_RT0(RA);
+	vadd_rg_RT1(RA);
+
+	/* Load context */
+	vld1.64 {RT0-RT3}, [%r0]!;
+	vld1.64 {RT4-RT7}, [%r0];
+	sub %r0, #(4*8);
+
+#ifdef __ARMEL__
+	vrev64.8 RW1213q, RW1213q;
+	vrev64.8 RW1415q, RW1415q;
+#endif
+
+	vadd.u64 RA, RT0;
+	vadd.u64 RB, RT1;
+	vadd.u64 RC, RT2;
+	vadd.u64 RD, RT3;
+	vadd.u64 RE, RT4;
+	vadd.u64 RF, RT5;
+	vadd.u64 RG, RT6;
+	vadd.u64 RH, RT7;
+
+	/* Store the first half of context */
+	vst1.64 {RA-RD}, [%r0]!;
+	sub RK, $(8*80);
+	vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
+	mov %lr, #0;
+	sub %r0, #(4*8);
+
+	b .Loop;
+
+.Lhandle_tail:
+	rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5,
+		      vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+	rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7,
+		      vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+	rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9,
+		      vadd_rg_RT0, RA, vadd_rg_RT1, RA);
+	rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11,
+		      vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+	rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13,
+		      vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+	rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15,
+		      vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+
+	/* Load context to d16-d23 */
+	vld1.64 {RW0-RW3}, [%r0]!;
+	vadd_rg_RT0(RA);
+	vld1.64 {RW4-RW7}, [%r0];
+	vadd_rg_RT1(RA);
+	sub %r0, #(4*8);
+
+	vadd.u64 RA, RW0;
+	vadd.u64 RB, RW1;
+	vadd.u64 RC, RW2;
+	vadd.u64 RD, RW3;
+	vadd.u64 RE, RW4;
+	vadd.u64 RF, RW5;
+	vadd.u64 RG, RW6;
+	vadd.u64 RH, RW7;
+
+	/* Store the first half of context */
+	vst1.64 {RA-RD}, [%r0]!;
+
+	/* Clear used registers */
+	/* d16-d31 */
+	veor.u64 RW01q, RW01q;
+	veor.u64 RW23q, RW23q;
+	veor.u64 RW45q, RW45q;
+	veor.u64 RW67q, RW67q;
+	vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
+	veor.u64 RW89q, RW89q;
+	veor.u64 RW1011q, RW1011q;
+	veor.u64 RW1213q, RW1213q;
+	veor.u64 RW1415q, RW1415q;
+	/* d8-d15 */
+	/*vpop {RT0-RT7};*/
+	/* d0-d7 (q0-q3) */
+	veor.u64 %q0, %q0;
+	veor.u64 %q1, %q1;
+	veor.u64 %q2, %q2;
+	veor.u64 %q3, %q3;
+
+	pop {%pc};
+ENDPROC(sha512_transform_neon)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/crypto/sha512_neon_glue.c linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha512_neon_glue.c
--- linux-libre-3.16-gnu/arch/arm/crypto/sha512_neon_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/crypto/sha512_neon_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,305 @@
+/*
+ * Glue code for the SHA512 Secure Hash Algorithm assembly implementation
+ * using NEON instructions.
+ *
+ * Copyright Â© 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is based on sha512_ssse3_glue.c:
+ *   Copyright (C) 2013 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; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/simd.h>
+#include <asm/neon.h>
+
+
+static const u64 sha512_k[] = {
+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+
+asmlinkage void sha512_transform_neon(u64 *digest, const void *data,
+				      const u64 k[], unsigned int num_blks);
+
+
+static int sha512_neon_init(struct shash_desc *desc)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	sctx->state[0] = SHA512_H0;
+	sctx->state[1] = SHA512_H1;
+	sctx->state[2] = SHA512_H2;
+	sctx->state[3] = SHA512_H3;
+	sctx->state[4] = SHA512_H4;
+	sctx->state[5] = SHA512_H5;
+	sctx->state[6] = SHA512_H6;
+	sctx->state[7] = SHA512_H7;
+	sctx->count[0] = sctx->count[1] = 0;
+
+	return 0;
+}
+
+static int __sha512_neon_update(struct shash_desc *desc, const u8 *data,
+				unsigned int len, unsigned int partial)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count[0] += len;
+	if (sctx->count[0] < len)
+		sctx->count[1]++;
+
+	if (partial) {
+		done = SHA512_BLOCK_SIZE - partial;
+		memcpy(sctx->buf + partial, data, done);
+		sha512_transform_neon(sctx->state, sctx->buf, sha512_k, 1);
+	}
+
+	if (len - done >= SHA512_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA512_BLOCK_SIZE;
+
+		sha512_transform_neon(sctx->state, data + done, sha512_k,
+				      rounds);
+
+		done += rounds * SHA512_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buf, data + done, len - done);
+
+	return 0;
+}
+
+static int sha512_neon_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA512_BLOCK_SIZE) {
+		sctx->count[0] += len;
+		if (sctx->count[0] < len)
+			sctx->count[1]++;
+		memcpy(sctx->buf + partial, data, len);
+
+		return 0;
+	}
+
+	if (!may_use_simd()) {
+		res = crypto_sha512_update(desc, data, len);
+	} else {
+		kernel_neon_begin();
+		res = __sha512_neon_update(desc, data, len, partial);
+		kernel_neon_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha512_neon_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be64 *dst = (__be64 *)out;
+	__be64 bits[2];
+	static const u8 padding[SHA512_BLOCK_SIZE] = { 0x80, };
+
+	/* save number of bits */
+	bits[1] = cpu_to_be64(sctx->count[0] << 3);
+	bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
+
+	/* Pad out to 112 mod 128 and append length */
+	index = sctx->count[0] & 0x7f;
+	padlen = (index < 112) ? (112 - index) : ((128+112) - index);
+
+	if (!may_use_simd()) {
+		crypto_sha512_update(desc, padding, padlen);
+		crypto_sha512_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_neon_begin();
+		/* We need to fill a whole block for __sha512_neon_update() */
+		if (padlen <= 112) {
+			sctx->count[0] += padlen;
+			if (sctx->count[0] < padlen)
+				sctx->count[1]++;
+			memcpy(sctx->buf + index, padding, padlen);
+		} else {
+			__sha512_neon_update(desc, padding, padlen, index);
+		}
+		__sha512_neon_update(desc, (const u8 *)&bits,
+					sizeof(bits), 112);
+		kernel_neon_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be64(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha512_neon_export(struct shash_desc *desc, void *out)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha512_neon_import(struct shash_desc *desc, const void *in)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha384_neon_init(struct shash_desc *desc)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	sctx->state[0] = SHA384_H0;
+	sctx->state[1] = SHA384_H1;
+	sctx->state[2] = SHA384_H2;
+	sctx->state[3] = SHA384_H3;
+	sctx->state[4] = SHA384_H4;
+	sctx->state[5] = SHA384_H5;
+	sctx->state[6] = SHA384_H6;
+	sctx->state[7] = SHA384_H7;
+
+	sctx->count[0] = sctx->count[1] = 0;
+
+	return 0;
+}
+
+static int sha384_neon_final(struct shash_desc *desc, u8 *hash)
+{
+	u8 D[SHA512_DIGEST_SIZE];
+
+	sha512_neon_final(desc, D);
+
+	memcpy(hash, D, SHA384_DIGEST_SIZE);
+	memset(D, 0, SHA512_DIGEST_SIZE);
+
+	return 0;
+}
+
+static struct shash_alg algs[] = { {
+	.digestsize	=	SHA512_DIGEST_SIZE,
+	.init		=	sha512_neon_init,
+	.update		=	sha512_neon_update,
+	.final		=	sha512_neon_final,
+	.export		=	sha512_neon_export,
+	.import		=	sha512_neon_import,
+	.descsize	=	sizeof(struct sha512_state),
+	.statesize	=	sizeof(struct sha512_state),
+	.base		=	{
+		.cra_name	=	"sha512",
+		.cra_driver_name =	"sha512-neon",
+		.cra_priority	=	250,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA512_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+},  {
+	.digestsize	=	SHA384_DIGEST_SIZE,
+	.init		=	sha384_neon_init,
+	.update		=	sha512_neon_update,
+	.final		=	sha384_neon_final,
+	.export		=	sha512_neon_export,
+	.import		=	sha512_neon_import,
+	.descsize	=	sizeof(struct sha512_state),
+	.statesize	=	sizeof(struct sha512_state),
+	.base		=	{
+		.cra_name	=	"sha384",
+		.cra_driver_name =	"sha384-neon",
+		.cra_priority	=	250,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA384_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+} };
+
+static int __init sha512_neon_mod_init(void)
+{
+	if (!cpu_has_neon())
+		return -ENODEV;
+
+	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit sha512_neon_mod_fini(void)
+{
+	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha512_neon_mod_init);
+module_exit(sha512_neon_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, NEON accelerated");
+
+MODULE_ALIAS("sha512");
+MODULE_ALIAS("sha384");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/assembler.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/assembler.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/assembler.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/assembler.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,8 @@
 #include <asm/domain.h>
 #include <asm/opcodes-virt.h>
 #include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
 
 #define IOMEM(x)	(x)
 
@@ -179,10 +181,10 @@
  * Get current thread_info.
  */
 	.macro	get_thread_info, rd
- ARM(	mov	\rd, sp, lsr #13	)
+ ARM(	mov	\rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT	)
  THUMB(	mov	\rd, sp			)
- THUMB(	lsr	\rd, \rd, #13		)
-	mov	\rd, \rd, lsl #13
+ THUMB(	lsr	\rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT	)
+	mov	\rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
 	.endm
 
 /*
@@ -425,4 +427,25 @@ THUMB(	orr	\reg , \reg , #PSR_T_BIT	)
 #endif
 	.endm
 
+	.irp	c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
+	.macro	ret\c, reg
+#if __LINUX_ARM_ARCH__ < 6
+	mov\c	pc, \reg
+#else
+	.ifeqs	"\reg", "lr"
+	bx\c	\reg
+	.else
+	mov\c	pc, \reg
+	.endif
+#endif
+	.endm
+	.endr
+
+	.macro	ret.w, reg
+	ret	\reg
+#ifdef CONFIG_THUMB2_KERNEL
+	nop
+#endif
+	.endm
+
 #endif /* __ASM_ASSEMBLER_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/cacheflush.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/cacheflush.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/cacheflush.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/cacheflush.h	2014-09-28 17:29:07.000000000 -0400
@@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(
 	"mcr	p15, 0, r0, c1, c0, 0	@ set SCTLR \n\t" \
 	"isb	\n\t" \
 	"bl	v7_flush_dcache_"__stringify(level)" \n\t" \
-	"clrex	\n\t" \
 	"mrc	p15, 0, r0, c1, c0, 1	@ get ACTLR \n\t" \
 	"bic	r0, r0, #(1 << 6)	@ disable local coherency \n\t" \
 	"mcr	p15, 0, r0, c1, c0, 1	@ set ACTLR \n\t" \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/cputype.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/cputype.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/cputype.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/cputype.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,17 +62,19 @@
 #define ARM_CPU_IMP_ARM			0x41
 #define ARM_CPU_IMP_INTEL		0x69
 
-#define ARM_CPU_PART_ARM1136		0xB360
-#define ARM_CPU_PART_ARM1156		0xB560
-#define ARM_CPU_PART_ARM1176		0xB760
-#define ARM_CPU_PART_ARM11MPCORE	0xB020
-#define ARM_CPU_PART_CORTEX_A8		0xC080
-#define ARM_CPU_PART_CORTEX_A9		0xC090
-#define ARM_CPU_PART_CORTEX_A5		0xC050
-#define ARM_CPU_PART_CORTEX_A15		0xC0F0
-#define ARM_CPU_PART_CORTEX_A7		0xC070
-#define ARM_CPU_PART_CORTEX_A12		0xC0D0
-#define ARM_CPU_PART_CORTEX_A17		0xC0E0
+/* ARM implemented processors */
+#define ARM_CPU_PART_ARM1136		0x4100b360
+#define ARM_CPU_PART_ARM1156		0x4100b560
+#define ARM_CPU_PART_ARM1176		0x4100b760
+#define ARM_CPU_PART_ARM11MPCORE	0x4100b020
+#define ARM_CPU_PART_CORTEX_A8		0x4100c080
+#define ARM_CPU_PART_CORTEX_A9		0x4100c090
+#define ARM_CPU_PART_CORTEX_A5		0x4100c050
+#define ARM_CPU_PART_CORTEX_A7		0x4100c070
+#define ARM_CPU_PART_CORTEX_A12		0x4100c0d0
+#define ARM_CPU_PART_CORTEX_A17		0x4100c0e0
+#define ARM_CPU_PART_CORTEX_A15		0x4100c0f0
+#define ARM_CPU_PART_MASK		0xff00fff0
 
 #define ARM_CPU_XSCALE_ARCH_MASK	0xe000
 #define ARM_CPU_XSCALE_ARCH_V1		0x2000
@@ -171,14 +173,24 @@ static inline unsigned int __attribute_c
 	return (read_cpuid_id() & 0xFF000000) >> 24;
 }
 
-static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
+/*
+ * The CPU part number is meaningless without referring to the CPU
+ * implementer: implementers are free to define their own part numbers
+ * which are permitted to clash with other implementer part numbers.
+ */
+static inline unsigned int __attribute_const__ read_cpuid_part(void)
+{
+	return read_cpuid_id() & ARM_CPU_PART_MASK;
+}
+
+static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void)
 {
 	return read_cpuid_id() & 0xFFF0;
 }
 
 static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void)
 {
-	return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK;
+	return read_cpuid_id() & ARM_CPU_XSCALE_ARCH_MASK;
 }
 
 static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/crypto/sha1.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/crypto/sha1.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/crypto/sha1.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/crypto/sha1.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,10 @@
+#ifndef ASM_ARM_CRYPTO_SHA1_H
+#define ASM_ARM_CRYPTO_SHA1_H
+
+#include <linux/crypto.h>
+#include <crypto/sha.h>
+
+extern int sha1_update_arm(struct shash_desc *desc, const u8 *data,
+			   unsigned int len);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/elf.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/elf.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/elf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/elf.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
 #define R_ARM_ABS32		2
 #define R_ARM_CALL		28
 #define R_ARM_JUMP24		29
+#define R_ARM_TARGET1		38
 #define R_ARM_V4BX		40
 #define R_ARM_PREL31		42
 #define R_ARM_MOVW_ABS_NC	43
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/entry-macro-multi.S linux-libre-3.17-rc7-gnu/arch/arm/include/asm/entry-macro-multi.S
--- linux-libre-3.16-gnu/arch/arm/include/asm/entry-macro-multi.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/entry-macro-multi.S	2014-09-28 17:29:07.000000000 -0400
@@ -35,5 +35,5 @@
 \symbol_name:
 	mov	r8, lr
 	arch_irq_handler_default
-	mov     pc, r8
+	ret	r8
 	.endm
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/glue-proc.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/glue-proc.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/glue-proc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/glue-proc.h	2014-09-28 17:29:07.000000000 -0400
@@ -221,15 +221,6 @@
 # endif
 #endif
 
-#ifdef CONFIG_CPU_V7
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v7
-# endif
-#endif
-
 #ifdef CONFIG_CPU_V7M
 # ifdef CPU_NAME
 #  undef  MULTI_CPU
@@ -248,6 +239,15 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7
+/*
+ * Cortex-A9 needs a different suspend/resume function, so we need
+ * multiple CPU support for ARMv7 anyway.
+ */
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init			__glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/gpio.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/gpio.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/gpio.h	2014-09-28 17:29:07.000000000 -0400
@@ -5,12 +5,6 @@
 #define ARCH_NR_GPIOS CONFIG_ARCH_NR_GPIO
 #endif
 
-/* not all ARM platforms necessarily support this API ... */
-#ifdef CONFIG_NEED_MACH_GPIO_H
-#include <mach/gpio.h>
-#endif
-
-#ifndef __ARM_GPIOLIB_COMPLEX
 /* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
 #include <asm-generic/gpio.h>
 
@@ -18,7 +12,6 @@
 #define gpio_get_value  __gpio_get_value
 #define gpio_set_value  __gpio_set_value
 #define gpio_cansleep   __gpio_cansleep
-#endif
 
 /*
  * Provide a default gpio_to_irq() which should satisfy every case.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/arm/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/arm/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@ generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
 generic-y += rwsem.h
+generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += sembuf.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/kvm_asm.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_asm.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/kvm_asm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_asm.h	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,24 @@
 #define ARM_EXCEPTION_FIQ	  6
 #define ARM_EXCEPTION_HVC	  7
 
+/*
+ * The rr_lo_hi macro swaps a pair of registers depending on
+ * current endianness. It is used in conjunction with ldrd and strd
+ * instructions that load/store a 64-bit value from/to memory to/from
+ * a pair of registers which are used with the mrrc and mcrr instructions.
+ * If used with the ldrd/strd instructions, the a1 parameter is the first
+ * source/destination register and the a2 parameter is the second
+ * source/destination register. Note that the ldrd/strd instructions
+ * already swap the bytes within the words correctly according to the
+ * endianness setting, but the order of the registers need to be effectively
+ * swapped when used with the mrrc/mcrr instructions.
+ */
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define rr_lo_hi(a1, a2) a2, a1
+#else
+#define rr_lo_hi(a1, a2) a1, a2
+#endif
+
 #ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/kvm_emulate.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_emulate.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/kvm_emulate.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_emulate.h	2014-09-28 17:29:07.000000000 -0400
@@ -185,9 +185,16 @@ static inline unsigned long vcpu_data_gu
 		default:
 			return be32_to_cpu(data);
 		}
+	} else {
+		switch (len) {
+		case 1:
+			return data & 0xff;
+		case 2:
+			return le16_to_cpu(data & 0xffff);
+		default:
+			return le32_to_cpu(data);
+		}
 	}
-
-	return data;		/* Leave LE untouched */
 }
 
 static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
@@ -203,9 +210,16 @@ static inline unsigned long vcpu_data_ho
 		default:
 			return cpu_to_be32(data);
 		}
+	} else {
+		switch (len) {
+		case 1:
+			return data & 0xff;
+		case 2:
+			return cpu_to_le16(data & 0xffff);
+		default:
+			return cpu_to_le32(data);
+		}
 	}
-
-	return data;		/* Leave LE untouched */
 }
 
 #endif /* __ARM_KVM_EMULATE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -225,10 +225,12 @@ static inline int kvm_arch_dev_ioctl_che
 	return 0;
 }
 
+static inline void vgic_arch_setup(const struct vgic_params *vgic)
+{
+	BUG_ON(vgic->type != VGIC_V2);
+}
+
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
-u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
-int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
-
 #endif /* __ARM_KVM_HOST_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/kvm_mmu.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_mmu.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/kvm_mmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/kvm_mmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -127,6 +127,18 @@ static inline void kvm_set_s2pmd_writabl
 	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
 })
 
+static inline bool kvm_page_empty(void *ptr)
+{
+	struct page *ptr_page = virt_to_page(ptr);
+	return page_count(ptr_page) == 1;
+}
+
+
+#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep)
+#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#define kvm_pud_table_empty(pudp) (0)
+
+
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__cpuc_flush_dcache_area((a), (l))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/mcpm.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/mcpm.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/mcpm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/mcpm.h	2014-09-28 17:29:07.000000000 -0400
@@ -217,6 +217,22 @@ int __mcpm_cluster_state(unsigned int cl
 int __init mcpm_sync_init(
 	void (*power_up_setup)(unsigned int affinity_level));
 
+/**
+ * mcpm_loopback - make a run through the MCPM low-level code
+ *
+ * @cache_disable: pointer to function performing cache disabling
+ *
+ * This exercises the MCPM machinery by soft resetting the CPU and branching
+ * to the MCPM low-level entry code before returning to the caller.
+ * The @cache_disable function must do the necessary cache disabling to
+ * let the regular kernel init code turn it back on as if the CPU was
+ * hotplugged in. The MCPM state machine is set as if the cluster was
+ * initialized meaning the power_up_setup callback passed to mcpm_sync_init()
+ * will be invoked for all affinity levels. This may be useful to initialize
+ * some resources such as enabling the CCI that requires the cache to be off, or simply for testing purposes.
+ */
+int __init mcpm_loopback(void (*cache_disable)(void));
+
 void __init mcpm_smp_set_ops(void);
 
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/mcs_spinlock.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/mcs_spinlock.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/mcs_spinlock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/mcs_spinlock.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+#ifndef __ASM_MCS_LOCK_H
+#define __ASM_MCS_LOCK_H
+
+#ifdef CONFIG_SMP
+#include <asm/spinlock.h>
+
+/* MCS spin-locking. */
+#define arch_mcs_spin_lock_contended(lock)				\
+do {									\
+	/* Ensure prior stores are observed before we enter wfe. */	\
+	smp_mb();							\
+	while (!(smp_load_acquire(lock)))				\
+		wfe();							\
+} while (0)								\
+
+#define arch_mcs_spin_unlock_contended(lock)				\
+do {									\
+	smp_store_release(lock, 1);					\
+	dsb_sev();							\
+} while (0)
+
+#endif	/* CONFIG_SMP */
+#endif	/* __ASM_MCS_LOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/memory.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/memory.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -91,9 +91,7 @@
  * of this define that was meant to.
  * Fortunately, there is no reference for this in noMMU mode, for now.
  */
-#ifndef TASK_SIZE
-#define TASK_SIZE		(CONFIG_DRAM_SIZE)
-#endif
+#define TASK_SIZE		UL(0xffffffff)
 
 #ifndef TASK_UNMAPPED_BASE
 #define TASK_UNMAPPED_BASE	UL(0x00000000)
@@ -150,13 +148,11 @@
 
 /*
  * PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
- * memory.  This is used for XIP and NoMMU kernels, or by kernels which
- * have their own mach/memory.h.  Assembly code must always use
+ * memory.  This is used for XIP and NoMMU kernels, and on platforms that don't
+ * have CONFIG_ARM_PATCH_PHYS_VIRT. Assembly code must always use
  * PLAT_PHYS_OFFSET and not PHYS_OFFSET.
  */
-#ifndef PLAT_PHYS_OFFSET
 #define PLAT_PHYS_OFFSET	UL(CONFIG_PHYS_OFFSET)
-#endif
 
 #ifndef __ASSEMBLY__
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/perf_event.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/perf_event.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/perf_event.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/perf_event.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,15 +12,6 @@
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-/*
- * The ARMv7 CPU PMU supports up to 32 event counters.
- */
-#define ARMPMU_MAX_HWEVENTS		32
-
-#define HW_OP_UNSUPPORTED		0xFFFF
-#define C(_x)				PERF_COUNT_HW_CACHE_##_x
-#define CACHE_OP_UNSUPPORTED		0xFFFF
-
 #ifdef CONFIG_HW_PERF_EVENTS
 struct pt_regs;
 extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/pgtable-3level.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable-3level.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/pgtable-3level.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable-3level.h	2014-09-28 17:29:07.000000000 -0400
@@ -79,18 +79,19 @@
 #define L_PTE_PRESENT		(_AT(pteval_t, 3) << 0)		/* Present */
 #define L_PTE_FILE		(_AT(pteval_t, 1) << 2)		/* only when !PRESENT */
 #define L_PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
-#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
 #define L_PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
 #define L_PTE_YOUNG		(_AT(pteval_t, 1) << 10)	/* AF */
 #define L_PTE_XN		(_AT(pteval_t, 1) << 54)	/* XN */
-#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 55)	/* unused */
-#define L_PTE_SPECIAL		(_AT(pteval_t, 1) << 56)	/* unused */
+#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 55)
+#define L_PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
 #define L_PTE_NONE		(_AT(pteval_t, 1) << 57)	/* PROT_NONE */
+#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 58)	/* READ ONLY */
 
-#define PMD_SECT_VALID		(_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_DIRTY		(_AT(pmdval_t, 1) << 55)
-#define PMD_SECT_SPLITTING	(_AT(pmdval_t, 1) << 56)
-#define PMD_SECT_NONE		(_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_VALID	(_AT(pmdval_t, 1) << 0)
+#define L_PMD_SECT_DIRTY	(_AT(pmdval_t, 1) << 55)
+#define L_PMD_SECT_SPLITTING	(_AT(pmdval_t, 1) << 56)
+#define L_PMD_SECT_NONE		(_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_RDONLY	(_AT(pteval_t, 1) << 58)
 
 /*
  * To be used in assembly code with the upper page attributes.
@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *p
 #define pte_huge(pte)		(pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT))
 #define pte_mkhuge(pte)		(__pte(pte_val(pte) & ~PTE_TABLE_BIT))
 
-#define pmd_young(pmd)		(pmd_val(pmd) & PMD_SECT_AF)
+#define pmd_isset(pmd, val)	((u32)(val) == (val) ? pmd_val(pmd) & (val) \
+						: !!(pmd_val(pmd) & (val)))
+#define pmd_isclear(pmd, val)	(!(pmd_val(pmd) & (val)))
+
+#define pmd_young(pmd)		(pmd_isset((pmd), PMD_SECT_AF))
 
 #define __HAVE_ARCH_PMD_WRITE
-#define pmd_write(pmd)		(!(pmd_val(pmd) & PMD_SECT_RDONLY))
+#define pmd_write(pmd)		(pmd_isclear((pmd), L_PMD_SECT_RDONLY))
+#define pmd_dirty(pmd)		(pmd_isset((pmd), L_PMD_SECT_DIRTY))
 
 #define pmd_hugewillfault(pmd)	(!pmd_young(pmd) || !pmd_write(pmd))
 #define pmd_thp_or_huge(pmd)	(pmd_huge(pmd) || pmd_trans_huge(pmd))
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#define pmd_trans_huge(pmd)	(pmd_val(pmd) && !pmd_table(pmd))
+#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING))
 #endif
 
 #define PMD_BIT_FUNC(fn,op) \
 static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
 
-PMD_BIT_FUNC(wrprotect,	|= PMD_SECT_RDONLY);
+PMD_BIT_FUNC(wrprotect,	|= L_PMD_SECT_RDONLY);
 PMD_BIT_FUNC(mkold,	&= ~PMD_SECT_AF);
-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
-PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
-PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING);
+PMD_BIT_FUNC(mkwrite,   &= ~L_PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkdirty,   |= L_PMD_SECT_DIRTY);
 PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 
 #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 {
-	const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY |
-				PMD_SECT_VALID | PMD_SECT_NONE;
+	const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY |
+				L_PMD_SECT_VALID | L_PMD_SECT_NONE;
 	pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
 	return pmd;
 }
@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_
 	BUG_ON(addr >= TASK_SIZE);
 
 	/* create a faulting entry if PROT_NONE protected */
-	if (pmd_val(pmd) & PMD_SECT_NONE)
-		pmd_val(pmd) &= ~PMD_SECT_VALID;
+	if (pmd_val(pmd) & L_PMD_SECT_NONE)
+		pmd_val(pmd) &= ~L_PMD_SECT_VALID;
+
+	if (pmd_write(pmd) && pmd_dirty(pmd))
+		pmd_val(pmd) &= ~PMD_SECT_AP2;
+	else
+		pmd_val(pmd) |= PMD_SECT_AP2;
 
 	*pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG);
 	flush_pmd_entry(pmdp);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/pgtable-3level-hwdef.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable-3level-hwdef.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/pgtable-3level-hwdef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable-3level-hwdef.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@
 #define PMD_SECT_BUFFERABLE	(_AT(pmdval_t, 1) << 2)
 #define PMD_SECT_CACHEABLE	(_AT(pmdval_t, 1) << 3)
 #define PMD_SECT_USER		(_AT(pmdval_t, 1) << 6)		/* AP[1] */
-#define PMD_SECT_RDONLY		(_AT(pmdval_t, 1) << 7)		/* AP[2] */
+#define PMD_SECT_AP2		(_AT(pmdval_t, 1) << 7)		/* read only */
 #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_nG		(_AT(pmdval_t, 1) << 11)
@@ -72,6 +72,7 @@
 #define PTE_TABLE_BIT		(_AT(pteval_t, 1) << 1)
 #define PTE_BUFFERABLE		(_AT(pteval_t, 1) << 2)		/* AttrIndx[0] */
 #define PTE_CACHEABLE		(_AT(pteval_t, 1) << 3)		/* AttrIndx[1] */
+#define PTE_AP2			(_AT(pteval_t, 1) << 7)		/* AP[2] */
 #define PTE_EXT_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
 #define PTE_EXT_AF		(_AT(pteval_t, 1) << 10)	/* Access Flag */
 #define PTE_EXT_NG		(_AT(pteval_t, 1) << 11)	/* nG */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -214,18 +214,22 @@ static inline pte_t *pmd_page_vaddr(pmd_
 
 #define pte_clear(mm,addr,ptep)	set_pte_ext(ptep, __pte(0), 0)
 
+#define pte_isset(pte, val)	((u32)(val) == (val) ? pte_val(pte) & (val) \
+						: !!(pte_val(pte) & (val)))
+#define pte_isclear(pte, val)	(!(pte_val(pte) & (val)))
+
 #define pte_none(pte)		(!pte_val(pte))
-#define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
-#define pte_valid(pte)		(pte_val(pte) & L_PTE_VALID)
+#define pte_present(pte)	(pte_isset((pte), L_PTE_PRESENT))
+#define pte_valid(pte)		(pte_isset((pte), L_PTE_VALID))
 #define pte_accessible(mm, pte)	(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
-#define pte_write(pte)		(!(pte_val(pte) & L_PTE_RDONLY))
-#define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
-#define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN))
+#define pte_write(pte)		(pte_isclear((pte), L_PTE_RDONLY))
+#define pte_dirty(pte)		(pte_isset((pte), L_PTE_DIRTY))
+#define pte_young(pte)		(pte_isset((pte), L_PTE_YOUNG))
+#define pte_exec(pte)		(pte_isclear((pte), L_PTE_XN))
 #define pte_special(pte)	(0)
 
 #define pte_valid_user(pte)	\
-	(pte_valid(pte) && (pte_val(pte) & L_PTE_USER) && pte_young(pte))
+	(pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
 
 #if __LINUX_ARM_ARCH__ < 6
 static inline void __sync_icache_dcache(pte_t pteval)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/pmu.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pmu.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/pmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/pmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,25 @@ struct arm_pmu_platdata {
 
 #ifdef CONFIG_HW_PERF_EVENTS
 
+/*
+ * The ARMv7 CPU PMU supports up to 32 event counters.
+ */
+#define ARMPMU_MAX_HWEVENTS		32
+
+#define HW_OP_UNSUPPORTED		0xFFFF
+#define C(_x)				PERF_COUNT_HW_CACHE_##_x
+#define CACHE_OP_UNSUPPORTED		0xFFFF
+
+#define PERF_MAP_ALL_UNSUPPORTED					\
+	[0 ... PERF_COUNT_HW_MAX - 1] = HW_OP_UNSUPPORTED
+
+#define PERF_CACHE_MAP_ALL_UNSUPPORTED					\
+[0 ... C(MAX) - 1] = {							\
+	[0 ... C(OP_MAX) - 1] = {					\
+		[0 ... C(RESULT_MAX) - 1] = CACHE_OP_UNSUPPORTED,	\
+	},								\
+}
+
 /* The events for a given PMU register set. */
 struct pmu_hw_events {
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -82,6 +82,8 @@ 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-3.16-gnu/arch/arm/include/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -84,6 +84,12 @@ static inline long regs_return_value(str
 
 #define instruction_pointer(regs)	(regs)->ARM_pc
 
+#ifdef CONFIG_THUMB2_KERNEL
+#define frame_pointer(regs) (regs)->ARM_r7
+#else
+#define frame_pointer(regs) (regs)->ARM_fp
+#endif
+
 static inline void instruction_pointer_set(struct pt_regs *regs,
 					   unsigned long val)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-#ifndef _ASMARM_SCATTERLIST_H
-#define _ASMARM_SCATTERLIST_H
-
-#ifdef CONFIG_ARM_HAS_SG_CHAIN
-#define ARCH_HAS_SG_CHAIN
-#endif
-
-#include <asm/memory.h>
-#include <asm/types.h>
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASMARM_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/smp_plat.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/smp_plat.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/smp_plat.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/smp_plat.h	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/cpumask.h>
 #include <linux/err.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 
 /*
@@ -25,6 +26,20 @@ static inline bool is_smp(void)
 #endif
 }
 
+/**
+ * smp_cpuid_part() - return part id for a given cpu
+ * @cpu:	logical cpu id.
+ *
+ * Return: part id of logical cpu passed as argument.
+ */
+static inline unsigned int smp_cpuid_part(int cpu)
+{
+	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpu);
+
+	return is_smp() ? cpu_info->cpuid & ARM_CPU_PART_MASK :
+			  read_cpuid_part();
+}
+
 /* all SMP configurations have the extended CPUID registers */
 #ifndef CONFIG_MMU
 #define tlb_ops_need_broadcast()	0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/smp_scu.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/smp_scu.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/smp_scu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/smp_scu.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,7 @@
 
 static inline bool scu_a9_has_base(void)
 {
-	return read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
+	return read_cpuid_part() == ARM_CPU_PART_CORTEX_A9;
 }
 
 static inline unsigned long scu_a9_get_base(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/stacktrace.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/stacktrace.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/stacktrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/stacktrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,28 @@
 #ifndef __ASM_STACKTRACE_H
 #define __ASM_STACKTRACE_H
 
+#include <asm/ptrace.h>
+
 struct stackframe {
+	/*
+	 * FP member should hold R7 when CONFIG_THUMB2_KERNEL is enabled
+	 * and R11 otherwise.
+	 */
 	unsigned long fp;
 	unsigned long sp;
 	unsigned long lr;
 	unsigned long pc;
 };
 
+static __always_inline
+void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
+{
+		frame->fp = frame_pointer(regs);
+		frame->sp = regs->ARM_sp;
+		frame->lr = regs->ARM_lr;
+		frame->pc = regs->ARM_pc;
+}
+
 extern int unwind_frame(struct stackframe *frame);
 extern void walk_stackframe(struct stackframe *frame,
 			    int (*fn)(struct stackframe *, void *), void *data);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/thread_info.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/thread_info.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/thread_info.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/thread_info.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,9 +14,10 @@
 
 #include <linux/compiler.h>
 #include <asm/fpstate.h>
+#include <asm/page.h>
 
 #define THREAD_SIZE_ORDER	1
-#define THREAD_SIZE		8192
+#define THREAD_SIZE		(PAGE_SIZE << THREAD_SIZE_ORDER)
 #define THREAD_START_SP		(THREAD_SIZE - 8)
 
 #ifndef __ASSEMBLY__
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/tls.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/tls.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/tls.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/tls.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,9 @@
 #ifndef __ASMARM_TLS_H
 #define __ASMARM_TLS_H
 
+#include <linux/compiler.h>
+#include <asm/thread_info.h>
+
 #ifdef __ASSEMBLY__
 #include <asm/asm-offsets.h>
 	.macro switch_tls_none, base, tp, tpuser, tmp1, tmp2
@@ -50,6 +53,47 @@
 #endif
 
 #ifndef __ASSEMBLY__
+
+static inline void set_tls(unsigned long val)
+{
+	struct thread_info *thread;
+
+	thread = current_thread_info();
+
+	thread->tp_value[0] = val;
+
+	/*
+	 * This code runs with preemption enabled and therefore must
+	 * be reentrant with respect to switch_tls.
+	 *
+	 * We need to ensure ordering between the shadow state and the
+	 * hardware state, so that we don't corrupt the hardware state
+	 * with a stale shadow state during context switch.
+	 *
+	 * If we're preempted here, switch_tls will load TPIDRURO from
+	 * thread_info upon resuming execution and the following mcr
+	 * is merely redundant.
+	 */
+	barrier();
+
+	if (!tls_emu) {
+		if (has_tls_reg) {
+			asm("mcr p15, 0, %0, c13, c0, 3"
+			    : : "r" (val));
+		} else {
+			/*
+			 * User space must never try to access this
+			 * directly.  Expect your app to break
+			 * eventually if you do so.  The user helper
+			 * at 0xffff0fe0 must be used instead.  (see
+			 * entry-armv.S for details)
+			 */
+			*((unsigned int *)0xffff0ff0) = val;
+		}
+
+	}
+}
+
 static inline unsigned long get_tpuser(void)
 {
 	unsigned long reg = 0;
@@ -59,5 +103,23 @@ static inline unsigned long get_tpuser(v
 
 	return reg;
 }
+
+static inline void set_tpuser(unsigned long val)
+{
+	/* Since TPIDRURW is fully context-switched (unlike TPIDRURO),
+	 * we need not update thread_info.
+	 */
+	if (has_tls_reg && !tls_emu) {
+		asm("mcr p15, 0, %0, c13, c0, 2"
+		    : : "r" (val));
+	}
+}
+
+static inline void flush_tls(void)
+{
+	set_tls(0);
+	set_tpuser(0);
+}
+
 #endif
 #endif	/* __ASMARM_TLS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/uaccess.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/uaccess.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/uaccess.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/uaccess.h	2014-09-28 17:29:07.000000000 -0400
@@ -107,6 +107,11 @@ static inline void set_fs(mm_segment_t f
 extern int __get_user_1(void *);
 extern int __get_user_2(void *);
 extern int __get_user_4(void *);
+extern int __get_user_32t_8(void *);
+extern int __get_user_8(void *);
+extern int __get_user_64t_1(void *);
+extern int __get_user_64t_2(void *);
+extern int __get_user_64t_4(void *);
 
 #define __GUP_CLOBBER_1	"lr", "cc"
 #ifdef CONFIG_CPU_USE_DOMAINS
@@ -115,6 +120,8 @@ extern int __get_user_4(void *);
 #define __GUP_CLOBBER_2 "lr", "cc"
 #endif
 #define __GUP_CLOBBER_4	"lr", "cc"
+#define __GUP_CLOBBER_32t_8 "lr", "cc"
+#define __GUP_CLOBBER_8	"lr", "cc"
 
 #define __get_user_x(__r2,__p,__e,__l,__s)				\
 	   __asm__ __volatile__ (					\
@@ -125,22 +132,63 @@ extern int __get_user_4(void *);
 		: "0" (__p), "r" (__l)					\
 		: __GUP_CLOBBER_##__s)
 
+/* narrowing a double-word get into a single 32bit word register: */
+#ifdef __ARMEB__
+#define __get_user_x_32t(__r2, __p, __e, __l, __s)				\
+	__get_user_x(__r2, __p, __e, __l, 32t_8)
+#else
+#define __get_user_x_32t __get_user_x
+#endif
+
+/*
+ * storing result into proper least significant word of 64bit target var,
+ * different only for big endian case where 64 bit __r2 lsw is r3:
+ */
+#ifdef __ARMEB__
+#define __get_user_x_64t(__r2, __p, __e, __l, __s)		        \
+	   __asm__ __volatile__ (					\
+		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
+		__asmeq("%3", "r1")					\
+		"bl	__get_user_64t_" #__s				\
+		: "=&r" (__e), "=r" (__r2)				\
+		: "0" (__p), "r" (__l)					\
+		: __GUP_CLOBBER_##__s)
+#else
+#define __get_user_x_64t __get_user_x
+#endif
+
+
 #define __get_user_check(x,p)							\
 	({								\
 		unsigned long __limit = current_thread_info()->addr_limit - 1; \
 		register const typeof(*(p)) __user *__p asm("r0") = (p);\
-		register unsigned long __r2 asm("r2");			\
+		register typeof(x) __r2 asm("r2");			\
 		register unsigned long __l asm("r1") = __limit;		\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
-			__get_user_x(__r2, __p, __e, __l, 1);		\
+			if (sizeof((x)) >= 8)				\
+				__get_user_x_64t(__r2, __p, __e, __l, 1); \
+			else						\
+				__get_user_x(__r2, __p, __e, __l, 1);	\
 			break;						\
 		case 2:							\
-			__get_user_x(__r2, __p, __e, __l, 2);		\
+			if (sizeof((x)) >= 8)				\
+				__get_user_x_64t(__r2, __p, __e, __l, 2); \
+			else						\
+				__get_user_x(__r2, __p, __e, __l, 2);	\
 			break;						\
 		case 4:							\
-			__get_user_x(__r2, __p, __e, __l, 4);		\
+			if (sizeof((x)) >= 8)				\
+				__get_user_x_64t(__r2, __p, __e, __l, 4); \
+			else						\
+				__get_user_x(__r2, __p, __e, __l, 4);	\
+			break;						\
+		case 8:							\
+			if (sizeof((x)) < 8)				\
+				__get_user_x_32t(__r2, __p, __e, __l, 4); \
+			else						\
+				__get_user_x(__r2, __p, __e, __l, 8);	\
 			break;						\
 		default: __e = __get_user_bad(); break;			\
 		}							\
@@ -224,7 +272,7 @@ static inline void set_fs(mm_segment_t f
 #define access_ok(type,addr,size)	(__range_ok(addr,size) == 0)
 
 #define user_addr_max() \
-	(segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL)
+	(segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs())
 
 /*
  * The "__xxx" versions of the user access functions do not verify the
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,17 @@
 
 #include <uapi/asm/unistd.h>
 
-#define __NR_syscalls  (384)
+/*
+ * 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  (388)
+
+/*
+ * *NOTE*: This is a ghost syscall private to the kernel.  Only the
+ * __kuser_cmpxchg code in entry-armv.S should be aware of its
+ * existence.  Don't ever use this from user code.
+ */
 #define __ARM_NR_cmpxchg		(__ARM_NR_BASE+0x00fff0)
 
 #define __ARCH_WANT_STAT64
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/xen/page-coherent.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/xen/page-coherent.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/xen/page-coherent.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/xen/page-coherent.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,25 +26,14 @@ static inline void xen_dma_map_page(stru
 	__generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
-{
-	if (__generic_dma_ops(hwdev)->unmap_page)
-		__generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-}
+		struct dma_attrs *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)
-{
-	if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
-		__generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-}
+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_dma_sync_single_for_device(struct device *hwdev,
-		dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-	if (__generic_dma_ops(hwdev)->sync_single_for_device)
-		__generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-}
 #endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/asm/xen/page.h linux-libre-3.17-rc7-gnu/arch/arm/include/asm/xen/page.h
--- linux-libre-3.16-gnu/arch/arm/include/asm/xen/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/asm/xen/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ typedef struct xpaddr {
 #define INVALID_P2M_ENTRY      (~0UL)
 
 unsigned long __pfn_to_mfn(unsigned long pfn);
-unsigned long __mfn_to_pfn(unsigned long mfn);
 extern struct rb_root phys_to_mach;
 
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
@@ -51,14 +50,6 @@ static inline unsigned long pfn_to_mfn(u
 
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
-	unsigned long pfn;
-
-	if (phys_to_mach.rb_node != NULL) {
-		pfn = __mfn_to_pfn(mfn);
-		if (pfn != INVALID_P2M_ENTRY)
-			return pfn;
-	}
-
 	return mfn;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/debug/clps711x.S linux-libre-3.17-rc7-gnu/arch/arm/include/debug/clps711x.S
--- linux-libre-3.16-gnu/arch/arm/include/debug/clps711x.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/debug/clps711x.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef CONFIG_DEBUG_CLPS711X_UART2
+#define CLPS711X_UART_PADDR	(0x80000000 + 0x0000)
+#define CLPS711X_UART_VADDR	(0xfeff0000 + 0x0000)
+#else
+#define CLPS711X_UART_PADDR	(0x80000000 + 0x1000)
+#define CLPS711X_UART_VADDR	(0xfeff0000 + 0x1000)
+#endif
+
+#define SYSFLG		(0x0140)
+#define SYSFLG_UBUSY	(1 << 11)
+#define UARTDR		(0x0480)
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rv, =CLPS711X_UART_VADDR
+	ldr	\rp, =CLPS711X_UART_PADDR
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
+
+	.macro	senduart,rd,rx
+	str	\rd, [\rx, #UARTDR]
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #SYSFLG]
+	tst	\rd, #SYSFLG_UBUSY
+	bne	1001b
+	.endm
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/debug/s5pv210.S linux-libre-3.17-rc7-gnu/arch/arm/include/debug/s5pv210.S
--- linux-libre-3.16-gnu/arch/arm/include/debug/s5pv210.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/debug/s5pv210.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#define S3C_ADDR_BASE   0xF6000000
+#define S3C_VA_UART	S3C_ADDR_BASE + 0x01000000
+#define S5PV210_PA_UART	0xe2900000
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rp, rv, tmp
+		ldr	\rp, =S5PV210_PA_UART
+		ldr	\rv, =S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+#include <debug/samsung.S>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/arm/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/arm/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -409,11 +409,9 @@
 #define __NR_sched_setattr		(__NR_SYSCALL_BASE+380)
 #define __NR_sched_getattr		(__NR_SYSCALL_BASE+381)
 #define __NR_renameat2			(__NR_SYSCALL_BASE+382)
-
-/*
- * This may need to be greater than __NR_last_syscall+1 in order to
- * account for the padding in the syscall table
- */
+#define __NR_seccomp			(__NR_SYSCALL_BASE+383)
+#define __NR_getrandom			(__NR_SYSCALL_BASE+384)
+#define __NR_memfd_create		(__NR_SYSCALL_BASE+385)
 
 /*
  * The following SWIs are ARM private.
@@ -426,12 +424,6 @@
 #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
 
 /*
- * *NOTE*: This is a ghost syscall private to the kernel.  Only the
- * __kuser_cmpxchg code in entry-armv.S should be aware of its
- * existence.  Don't ever use this from user code.
- */
-
-/*
  * The following syscalls are obsolete and no longer available for EABI.
  */
 #if !defined(__KERNEL__)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/Kconfig
--- linux-libre-3.16-gnu/arch/arm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,6 @@ config ARM
 	select HAVE_UID16
 	select HAVE_VIRT_CPU_ACCOUNTING_GEN
 	select IRQ_FORCED_THREADING
-	select KTIME_SCALAR
 	select MODULES_USE_ELF_REL
 	select NO_BOOTMEM
 	select OLD_SIGACTION
@@ -84,6 +83,7 @@ config ARM
 	  <http://www.arm.linux.org.uk/>.
 
 config ARM_HAS_SG_CHAIN
+	select ARCH_HAS_SG_CHAIN
 	bool
 
 config NEED_SG_DMA_LENGTH
@@ -240,13 +240,6 @@ config ARM_PATCH_PHYS_VIRT
 	  this feature (eg, building a kernel for a single machine) and
 	  you need to shrink the kernel to the minimal size.
 
-config NEED_MACH_GPIO_H
-	bool
-	help
-	  Select this when mach/gpio.h is required to provide special
-	  definitions for this platform. The need for mach/gpio.h should
-	  be avoided when possible.
-
 config NEED_MACH_IO_H
 	bool
 	help
@@ -263,8 +256,22 @@ config NEED_MACH_MEMORY_H
 
 config PHYS_OFFSET
 	hex "Physical address of main memory" if MMU
-	depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
+	depends on !ARM_PATCH_PHYS_VIRT
 	default DRAM_BASE if !MMU
+	default 0x00000000 if ARCH_EBSA110 || \
+			EP93XX_SDCE3_SYNC_PHYS_OFFSET || \
+			ARCH_FOOTBRIDGE || \
+			ARCH_INTEGRATOR || \
+			ARCH_IOP13XX || \
+			ARCH_KS8695 || \
+			(ARCH_REALVIEW && !REALVIEW_HIGH_PHYS_OFFSET)
+	default 0x10000000 if ARCH_OMAP1 || ARCH_RPC
+	default 0x20000000 if ARCH_S5PV210
+	default 0x70000000 if REALVIEW_HIGH_PHYS_OFFSET
+	default 0xc0000000 if EP93XX_SDCE0_PHYS_OFFSET || ARCH_SA1100
+	default 0xd0000000 if EP93XX_SDCE1_PHYS_OFFSET
+	default 0xe0000000 if EP93XX_SDCE2_PHYS_OFFSET
+	default 0xf0000000 if EP93XX_SDCE3_ASYNC_PHYS_OFFSET
 	help
 	  Please provide the physical address corresponding to the
 	  location of main memory in your system.
@@ -321,7 +328,6 @@ config ARCH_INTEGRATOR
 	select HAVE_TCM
 	select ICST
 	select MULTI_IRQ_HANDLER
-	select NEED_MACH_MEMORY_H
 	select PLAT_VERSATILE
 	select SPARSE_IRQ
 	select USE_OF
@@ -341,7 +347,6 @@ config ARCH_REALVIEW
 	select ICST
 	select NEED_MACH_MEMORY_H
 	select PLAT_VERSATILE
-	select PLAT_VERSATILE_CLCD
 	help
 	  This enables support for ARM Ltd RealView boards.
 
@@ -356,7 +361,6 @@ config ARCH_VERSATILE
 	select HAVE_MACH_CLKDEV
 	select ICST
 	select PLAT_VERSATILE
-	select PLAT_VERSATILE_CLCD
 	select PLAT_VERSATILE_CLOCK
 	select VERSATILE_FPGA_IRQ
 	help
@@ -436,7 +440,6 @@ config ARCH_EP93XX
 	select ARM_VIC
 	select CLKDEV_LOOKUP
 	select CPU_ARM920T
-	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
@@ -529,21 +532,6 @@ config ARCH_DOVE
 	help
 	  Support for the Marvell Dove SoC 88AP510
 
-config ARCH_KIRKWOOD
-	bool "Marvell Kirkwood"
-	select ARCH_REQUIRE_GPIOLIB
-	select CPU_FEROCEON
-	select GENERIC_CLOCKEVENTS
-	select MVEBU_MBUS
-	select PCI
-	select PCI_QUIRKS
-	select PINCTRL
-	select PINCTRL_KIRKWOOD
-	select PLAT_ORION_LEGACY
-	help
-	  Support for the following Marvell Kirkwood series SoCs:
-	  88F6180, 88F6192 and 88F6281.
-
 config ARCH_MV78XX0
 	bool "Marvell MV78xx0"
 	select ARCH_REQUIRE_GPIOLIB
@@ -635,6 +623,7 @@ config ARCH_PXA
 	select AUTO_ZRELADDR
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
+	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
 	select GPIO_PXA
 	select HAVE_IDE
@@ -759,61 +748,6 @@ config ARCH_S3C64XX
 	help
 	  Samsung S3C64XX series based systems
 
-config ARCH_S5P64X0
-	bool "Samsung S5P6440 S5P6450"
-	select ATAGS
-	select CLKDEV_LOOKUP
-	select CLKSRC_SAMSUNG_PWM
-	select CPU_V6
-	select GENERIC_CLOCKEVENTS
-	select GPIO_SAMSUNG
-	select HAVE_S3C2410_I2C if I2C
-	select HAVE_S3C2410_WATCHDOG if WATCHDOG
-	select HAVE_S3C_RTC if RTC_CLASS
-	select NEED_MACH_GPIO_H
-	select SAMSUNG_ATAGS
-	select SAMSUNG_WDT_RESET
-	help
-	  Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
-	  SMDK6450.
-
-config ARCH_S5PC100
-	bool "Samsung S5PC100"
-	select ARCH_REQUIRE_GPIOLIB
-	select ATAGS
-	select CLKDEV_LOOKUP
-	select CLKSRC_SAMSUNG_PWM
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
-	select GPIO_SAMSUNG
-	select HAVE_S3C2410_I2C if I2C
-	select HAVE_S3C2410_WATCHDOG if WATCHDOG
-	select HAVE_S3C_RTC if RTC_CLASS
-	select NEED_MACH_GPIO_H
-	select SAMSUNG_ATAGS
-	select SAMSUNG_WDT_RESET
-	help
-	  Samsung S5PC100 series based systems
-
-config ARCH_S5PV210
-	bool "Samsung S5PV210/S5PC110"
-	select ARCH_HAS_HOLES_MEMORYMODEL
-	select ARCH_SPARSEMEM_ENABLE
-	select ATAGS
-	select CLKDEV_LOOKUP
-	select CLKSRC_SAMSUNG_PWM
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
-	select GPIO_SAMSUNG
-	select HAVE_S3C2410_I2C if I2C
-	select HAVE_S3C2410_WATCHDOG if WATCHDOG
-	select HAVE_S3C_RTC if RTC_CLASS
-	select NEED_MACH_GPIO_H
-	select NEED_MACH_MEMORY_H
-	select SAMSUNG_ATAGS
-	help
-	  Samsung S5PV210/S5PC110 series based systems
-
 config ARCH_DAVINCI
 	bool "TI DaVinci"
 	select ARCH_HAS_HOLES_MEMORYMODEL
@@ -952,8 +886,6 @@ source "arch/arm/mach-ixp4xx/Kconfig"
 
 source "arch/arm/mach-keystone/Kconfig"
 
-source "arch/arm/mach-kirkwood/Kconfig"
-
 source "arch/arm/mach-ks8695/Kconfig"
 
 source "arch/arm/mach-msm/Kconfig"
@@ -964,6 +896,8 @@ source "arch/arm/mach-mv78xx0/Kconfig"
 
 source "arch/arm/mach-imx/Kconfig"
 
+source "arch/arm/mach-mediatek/Kconfig"
+
 source "arch/arm/mach-mxs/Kconfig"
 
 source "arch/arm/mach-netx/Kconfig"
@@ -1005,10 +939,6 @@ source "arch/arm/mach-s3c24xx/Kconfig"
 
 source "arch/arm/mach-s3c64xx/Kconfig"
 
-source "arch/arm/mach-s5p64x0/Kconfig"
-
-source "arch/arm/mach-s5pc100/Kconfig"
-
 source "arch/arm/mach-s5pv210/Kconfig"
 
 source "arch/arm/mach-exynos/Kconfig"
@@ -1555,10 +1485,12 @@ config ARM_PSCI
 config ARCH_NR_GPIO
 	int
 	default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
-	default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX
+	default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
+		SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
 	default 416 if ARCH_SUNXI
 	default 392 if ARCH_U8500
 	default 352 if ARCH_VT8500
+	default 288 if ARCH_ROCKCHIP
 	default 264 if MACH_H4700
 	default 0
 	help
@@ -1570,7 +1502,7 @@ source kernel/Kconfig.preempt
 
 config HZ_FIXED
 	int
-	default 200 if ARCH_EBSA110 || ARCH_S3C24XX || ARCH_S5P64X0 || \
+	default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
 		ARCH_S5PV210 || ARCH_EXYNOS4
 	default AT91_TIMER_HZ if ARCH_AT91
 	default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY
@@ -2195,7 +2127,6 @@ menu "Power management options"
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
-	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_FEROCEON || CPU_SA1100 || \
 		CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
 	def_bool y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/Kconfig.debug linux-libre-3.17-rc7-gnu/arch/arm/Kconfig.debug
--- linux-libre-3.16-gnu/arch/arm/Kconfig.debug	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/Kconfig.debug	2014-09-28 17:29:07.000000000 -0400
@@ -223,6 +223,14 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on HI3716 UART.
 
+	config DEBUG_HIX5HD2_UART
+		bool "Hisilicon Hix5hd2 Debug UART"
+		depends on ARCH_HIX5HD2
+		select DEBUG_UART_PL01X
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Hix5hd2 UART.
+
 	config DEBUG_HIGHBANK_UART
 		bool "Kernel low-level debugging messages via Highbank UART"
 		depends on ARCH_HIGHBANK
@@ -582,7 +590,7 @@ choice
 		  on Rockchip based platforms.
 
 	config DEBUG_RK3X_UART0
-		bool "Kernel low-level debugging messages via Rockchip RK3X UART0"
+		bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART0"
 		depends on ARCH_ROCKCHIP
 		select DEBUG_UART_8250
 		help
@@ -590,7 +598,7 @@ choice
 		  on Rockchip based platforms.
 
 	config DEBUG_RK3X_UART1
-		bool "Kernel low-level debugging messages via Rockchip RK3X UART1"
+		bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART1"
 		depends on ARCH_ROCKCHIP
 		select DEBUG_UART_8250
 		help
@@ -598,7 +606,7 @@ choice
 		  on Rockchip based platforms.
 
 	config DEBUG_RK3X_UART2
-		bool "Kernel low-level debugging messages via Rockchip RK3X UART2"
+		bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART2"
 		depends on ARCH_ROCKCHIP
 		select DEBUG_UART_8250
 		help
@@ -606,64 +614,64 @@ choice
 		  on Rockchip based platforms.
 
 	config DEBUG_RK3X_UART3
-		bool "Kernel low-level debugging messages via Rockchip RK3X UART3"
+		bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART3"
 		depends on ARCH_ROCKCHIP
 		select DEBUG_UART_8250
 		help
 		  Say Y here if you want kernel low-level debugging support
 		  on Rockchip based platforms.
 
+	config DEBUG_RK32_UART2
+		bool "Kernel low-level debugging messages via Rockchip RK32 UART2"
+		depends on ARCH_ROCKCHIP
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip RK32xx based platforms.
+
 	config DEBUG_S3C_UART0
 		depends on PLAT_SAMSUNG
 		select DEBUG_EXYNOS_UART if ARCH_EXYNOS
 		select DEBUG_S3C24XX_UART if ARCH_S3C24XX
-		bool "Use S3C UART 0 for low-level debug"
+		select DEBUG_S5PV210_UART if ARCH_S5PV210
+		bool "Use Samsung S3C UART 0 for low-level debug"
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART 0. The port must have been initialised
 		  by the boot-loader before use.
 
-		  The uncompressor code port configuration is now handled
-		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
 	config DEBUG_S3C_UART1
 		depends on PLAT_SAMSUNG
 		select DEBUG_EXYNOS_UART if ARCH_EXYNOS
 		select DEBUG_S3C24XX_UART if ARCH_S3C24XX
-		bool "Use S3C UART 1 for low-level debug"
+		select DEBUG_S5PV210_UART if ARCH_S5PV210
+		bool "Use Samsung S3C UART 1 for low-level debug"
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART 1. The port must have been initialised
 		  by the boot-loader before use.
 
-		  The uncompressor code port configuration is now handled
-		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
 	config DEBUG_S3C_UART2
 		depends on PLAT_SAMSUNG
 		select DEBUG_EXYNOS_UART if ARCH_EXYNOS
 		select DEBUG_S3C24XX_UART if ARCH_S3C24XX
-		bool "Use S3C UART 2 for low-level debug"
+		select DEBUG_S5PV210_UART if ARCH_S5PV210
+		bool "Use Samsung S3C UART 2 for low-level debug"
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART 2. The port must have been initialised
 		  by the boot-loader before use.
 
-		  The uncompressor code port configuration is now handled
-		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
 	config DEBUG_S3C_UART3
-		depends on PLAT_SAMSUNG && ARCH_EXYNOS
-		select DEBUG_EXYNOS_UART
-		bool "Use S3C UART 3 for low-level debug"
+		depends on PLAT_SAMSUNG && (ARCH_EXYNOS || ARCH_S5PV210)
+		select DEBUG_EXYNOS_UART if ARCH_EXYNOS
+		select DEBUG_S5PV210_UART if ARCH_S5PV210
+		bool "Use Samsung S3C UART 3 for low-level debug"
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to UART 3. The port must have been initialised
 		  by the boot-loader before use.
 
-		  The uncompressor code port configuration is now handled
-		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
 	config DEBUG_S3C2410_UART0
 		depends on ARCH_S3C24XX
 		select DEBUG_S3C2410_UART
@@ -715,6 +723,14 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on Allwinner A1X based platforms on the UART1.
 
+	config DEBUG_SUNXI_R_UART
+		bool "Kernel low-level debugging messages via sunXi R_UART"
+		depends on MACH_SUN6I || MACH_SUN8I
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Allwinner A31/A23 based platforms on the R_UART.
+
 	config TEGRA_DEBUG_UART_AUTO_ODMDATA
 		bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
 		depends on ARCH_TEGRA
@@ -949,6 +965,9 @@ config DEBUG_S3C2410_UART
 config DEBUG_S3C24XX_UART
 	bool
 
+config DEBUG_S5PV210_UART
+	bool
+
 config DEBUG_OMAP2PLUS_UART
 	bool
 	depends on ARCH_OMAP2PLUS
@@ -991,6 +1010,7 @@ config DEBUG_STI_UART
 config DEBUG_LL_INCLUDE
 	string
 	default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2
 	default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
 	default "debug/exynos.S" if DEBUG_EXYNOS_UART
 	default "debug/efm32.S" if DEBUG_LL_UART_EFM32
@@ -1009,6 +1029,7 @@ config DEBUG_LL_INCLUDE
 	default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
 	default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
 	default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
+	default "debug/s5pv210.S" if DEBUG_S5PV210_UART
 	default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
 	default "debug/sti.S" if DEBUG_STI_UART
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
@@ -1033,7 +1054,7 @@ config DEBUG_UART_8250
 	def_bool ARCH_DOVE || ARCH_EBSA110 || \
 		(FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
 		ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
-		ARCH_IOP33X || ARCH_IXP4XX || ARCH_KIRKWOOD || \
+		ARCH_IOP33X || ARCH_IXP4XX || \
 		ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC
 
 config DEBUG_UART_PHYS
@@ -1043,6 +1064,7 @@ config DEBUG_UART_PHYS
 	default 0x01c28400 if DEBUG_SUNXI_UART1
 	default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
 	default 0x01d0d000 if DEBUG_DAVINCI_DA8XX_UART2
+	default 0x01f02800 if DEBUG_SUNXI_R_UART
 	default 0x02530c00 if DEBUG_KEYSTONE_UART0
 	default 0x02531000 if DEBUG_KEYSTONE_UART1
 	default 0x03010fe0 if ARCH_RPC
@@ -1089,13 +1111,14 @@ config DEBUG_UART_PHYS
 	default 0xe0000000 if ARCH_SPEAR13XX
 	default 0xf0000be0 if ARCH_EBSA110
 	default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
-	default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
+	default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
 				ARCH_ORION5X
 	default 0xf7fc9000 if DEBUG_BERLIN_UART
-	default 0xf8b00000 if DEBUG_HI3716_UART
+	default 0xf8b00000 if DEBUG_HIX5HD2_UART
 	default 0xf991e000 if DEBUG_QCOM_UARTDM
 	default 0xfcb00000 if DEBUG_HI3620_UART
 	default 0xfe800000 if ARCH_IOP32X
+	default 0xff690000 if DEBUG_RK32_UART2
 	default 0xffc02000 if DEBUG_SOCFPGA_UART
 	default 0xffd82340 if ARCH_IOP13XX
 	default 0xfff36000 if DEBUG_HIGHBANK_UART
@@ -1118,6 +1141,7 @@ config DEBUG_UART_VIRT
 	default 0xf1600000 if ARCH_INTEGRATOR
 	default 0xf1c28000 if DEBUG_SUNXI_UART0
 	default 0xf1c28400 if DEBUG_SUNXI_UART1
+	default 0xf1f02800 if DEBUG_SUNXI_R_UART
 	default 0xf2100000 if DEBUG_PXA_UART1
 	default 0xf4090000 if ARCH_LPC32XX
 	default 0xf4200000 if ARCH_GEMINI
@@ -1144,7 +1168,7 @@ config DEBUG_UART_VIRT
 	default 0xfe230000 if DEBUG_PICOXCELL_UART
 	default 0xfe300000 if DEBUG_BCM_KONA_UART
 	default 0xfe800000 if ARCH_IOP32X
-	default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HI3716_UART
+	default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART
 	default 0xfeb24000 if DEBUG_RK3X_UART0
 	default 0xfeb26000 if DEBUG_RK3X_UART1
 	default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
@@ -1152,9 +1176,9 @@ config DEBUG_UART_VIRT
 	default 0xfec02000 if DEBUG_SOCFPGA_UART
 	default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
 	default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
+	default 0xfec90000 if DEBUG_RK32_UART2
 	default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
 	default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
-	default 0xfed12000 if ARCH_KIRKWOOD
 	default 0xfed60000 if DEBUG_RK29_UART0
 	default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
 	default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
@@ -1186,7 +1210,7 @@ config DEBUG_UART_8250_WORD
 		ARCH_KEYSTONE || \
 		DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
 		DEBUG_DAVINCI_DA8XX_UART2 || \
-		DEBUG_BCM_KONA_UART
+		DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2
 
 config DEBUG_UART_8250_FLOW_CONTROL
 	bool "Enable flow control for 8250 UART"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/armksyms.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/armksyms.c
--- linux-libre-3.16-gnu/arch/arm/kernel/armksyms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/armksyms.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,6 +98,14 @@ EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+
+#ifdef __ARMEB__
+EXPORT_SYMBOL(__get_user_64t_1);
+EXPORT_SYMBOL(__get_user_64t_2);
+EXPORT_SYMBOL(__get_user_64t_4);
+EXPORT_SYMBOL(__get_user_32t_8);
+#endif
 
 EXPORT_SYMBOL(__put_user_1);
 EXPORT_SYMBOL(__put_user_2);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/asm-offsets.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/asm-offsets.c
--- linux-libre-3.16-gnu/arch/arm/kernel/asm-offsets.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/asm-offsets.c	2014-09-28 17:29:07.000000000 -0400
@@ -182,13 +182,13 @@ int main(void)
   DEFINE(VCPU_HYP_PC,		offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
 #ifdef CONFIG_KVM_ARM_VGIC
   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
-  DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
-  DEFINE(VGIC_CPU_VMCR,		offsetof(struct vgic_cpu, vgic_vmcr));
-  DEFINE(VGIC_CPU_MISR,		offsetof(struct vgic_cpu, vgic_misr));
-  DEFINE(VGIC_CPU_EISR,		offsetof(struct vgic_cpu, vgic_eisr));
-  DEFINE(VGIC_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_elrsr));
-  DEFINE(VGIC_CPU_APR,		offsetof(struct vgic_cpu, vgic_apr));
-  DEFINE(VGIC_CPU_LR,		offsetof(struct vgic_cpu, vgic_lr));
+  DEFINE(VGIC_V2_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
+  DEFINE(VGIC_V2_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
+  DEFINE(VGIC_V2_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
+  DEFINE(VGIC_V2_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
+  DEFINE(VGIC_V2_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
+  DEFINE(VGIC_V2_CPU_APR,	offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
+  DEFINE(VGIC_V2_CPU_LR,	offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
   DEFINE(VGIC_CPU_NR_LR,	offsetof(struct vgic_cpu, nr_lr));
 #ifdef CONFIG_KVM_ARM_TIMER
   DEFINE(VCPU_TIMER_CNTV_CTL,	offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/calls.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/calls.S
--- linux-libre-3.16-gnu/arch/arm/kernel/calls.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/calls.S	2014-09-28 17:29:07.000000000 -0400
@@ -392,6 +392,9 @@
 /* 380 */	CALL(sys_sched_setattr)
 		CALL(sys_sched_getattr)
 		CALL(sys_renameat2)
+		CALL(sys_seccomp)
+		CALL(sys_getrandom)
+/* 385 */	CALL(sys_memfd_create)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/debug.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/debug.S
--- linux-libre-3.16-gnu/arch/arm/kernel/debug.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/debug.S	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,7 @@ ENTRY(printascii)
 		ldrneb	r1, [r0], #1
 		teqne	r1, #0
 		bne	1b
-		mov	pc, lr
+		ret	lr
 ENDPROC(printascii)
 
 ENTRY(printch)
@@ -105,7 +105,7 @@ ENTRY(debug_ll_addr)
 		addruart r2, r3, ip
 		str	r2, [r0]
 		str	r3, [r1]
-		mov	pc, lr
+		ret	lr
 ENDPROC(debug_ll_addr)
 #endif
 
@@ -116,7 +116,7 @@ ENTRY(printascii)
 		mov	r0, #0x04		@ SYS_WRITE0
 	ARM(	svc	#0x123456	)
 	THUMB(	svc	#0xab		)
-		mov	pc, lr
+		ret	lr
 ENDPROC(printascii)
 
 ENTRY(printch)
@@ -125,14 +125,14 @@ ENTRY(printch)
 		mov	r0, #0x03		@ SYS_WRITEC
 	ARM(	svc	#0x123456	)
 	THUMB(	svc	#0xab		)
-		mov	pc, lr
+		ret	lr
 ENDPROC(printch)
 
 ENTRY(debug_ll_addr)
 		mov	r2, #0
 		str	r2, [r0]
 		str	r2, [r1]
-		mov	pc, lr
+		ret	lr
 ENDPROC(debug_ll_addr)
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/entry-armv.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-armv.S
--- linux-libre-3.16-gnu/arch/arm/kernel/entry-armv.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-armv.S	2014-09-28 17:29:07.000000000 -0400
@@ -224,7 +224,7 @@ svc_preempt:
 1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
 	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
 	tst	r0, #_TIF_NEED_RESCHED
-	moveq	pc, r8				@ go again
+	reteq	r8				@ go again
 	b	1b
 #endif
 
@@ -490,7 +490,7 @@ ENDPROC(__und_usr)
 	.pushsection .fixup, "ax"
 	.align	2
 4:	str     r4, [sp, #S_PC]			@ retry current instruction
-	mov	pc, r9
+	ret	r9
 	.popsection
 	.pushsection __ex_table,"a"
 	.long	1b, 4b
@@ -552,7 +552,7 @@ call_fpe:
 #endif
 	tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
 	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
-	moveq	pc, lr
+	reteq	lr
 	and	r8, r0, #0x00000f00		@ mask out CP number
  THUMB(	lsr	r8, r8, #8		)
 	mov	r7, #1
@@ -571,33 +571,33 @@ call_fpe:
  THUMB(	add	pc, r8			)
 	nop
 
-	movw_pc	lr				@ CP#0
+	ret.w	lr				@ CP#0
 	W(b)	do_fpe				@ CP#1 (FPE)
 	W(b)	do_fpe				@ CP#2 (FPE)
-	movw_pc	lr				@ CP#3
+	ret.w	lr				@ CP#3
 #ifdef CONFIG_CRUNCH
 	b	crunch_task_enable		@ CP#4 (MaverickCrunch)
 	b	crunch_task_enable		@ CP#5 (MaverickCrunch)
 	b	crunch_task_enable		@ CP#6 (MaverickCrunch)
 #else
-	movw_pc	lr				@ CP#4
-	movw_pc	lr				@ CP#5
-	movw_pc	lr				@ CP#6
+	ret.w	lr				@ CP#4
+	ret.w	lr				@ CP#5
+	ret.w	lr				@ CP#6
 #endif
-	movw_pc	lr				@ CP#7
-	movw_pc	lr				@ CP#8
-	movw_pc	lr				@ CP#9
+	ret.w	lr				@ CP#7
+	ret.w	lr				@ CP#8
+	ret.w	lr				@ CP#9
 #ifdef CONFIG_VFP
 	W(b)	do_vfp				@ CP#10 (VFP)
 	W(b)	do_vfp				@ CP#11 (VFP)
 #else
-	movw_pc	lr				@ CP#10 (VFP)
-	movw_pc	lr				@ CP#11 (VFP)
+	ret.w	lr				@ CP#10 (VFP)
+	ret.w	lr				@ CP#11 (VFP)
 #endif
-	movw_pc	lr				@ CP#12
-	movw_pc	lr				@ CP#13
-	movw_pc	lr				@ CP#14 (Debug)
-	movw_pc	lr				@ CP#15 (Control)
+	ret.w	lr				@ CP#12
+	ret.w	lr				@ CP#13
+	ret.w	lr				@ CP#14 (Debug)
+	ret.w	lr				@ CP#15 (Control)
 
 #ifdef NEED_CPU_ARCHITECTURE
 	.align	2
@@ -649,7 +649,7 @@ ENTRY(fp_enter)
 	.popsection
 
 ENTRY(no_fp)
-	mov	pc, lr
+	ret	lr
 ENDPROC(no_fp)
 
 __und_usr_fault_32:
@@ -745,7 +745,7 @@ ENDPROC(__switch_to)
 #ifdef CONFIG_ARM_THUMB
 	bx	\reg
 #else
-	mov	pc, \reg
+	ret	\reg
 #endif
 	.endm
 
@@ -837,7 +837,7 @@ kuser_cmpxchg64_fixup:
 #if __LINUX_ARM_ARCH__ < 6
 	bcc	kuser_cmpxchg32_fixup
 #endif
-	mov	pc, lr
+	ret	lr
 	.previous
 
 #else
@@ -905,7 +905,7 @@ kuser_cmpxchg32_fixup:
 	subs	r8, r4, r7
 	rsbcss	r8, r8, #(2b - 1b)
 	strcs	r7, [sp, #S_PC]
-	mov	pc, lr
+	ret	lr
 	.previous
 
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/entry-common.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-common.S
--- linux-libre-3.16-gnu/arch/arm/kernel/entry-common.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-common.S	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/assembler.h>
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
 #include <asm/unwind.h>
@@ -88,7 +89,7 @@ ENTRY(ret_from_fork)
 	cmp	r5, #0
 	movne	r0, r4
 	adrne	lr, BSYM(1f)
-	movne	pc, r5
+	retne	r5
 1:	get_thread_info tsk
 	b	ret_slow_syscall
 ENDPROC(ret_from_fork)
@@ -290,7 +291,7 @@ ENDPROC(ftrace_graph_caller_old)
 
 .macro mcount_exit
 	ldmia	sp!, {r0-r3, ip, lr}
-	mov	pc, ip
+	ret	ip
 .endm
 
 ENTRY(__gnu_mcount_nc)
@@ -298,7 +299,7 @@ UNWIND(.fnstart)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	mov	ip, lr
 	ldmia	sp!, {lr}
-	mov	pc, ip
+	ret	ip
 #else
 	__mcount
 #endif
@@ -333,12 +334,12 @@ return_to_handler:
 	bl	ftrace_return_to_handler
 	mov	lr, r0			@ r0 has real ret addr
 	ldmia	sp!, {r0-r3}
-	mov	pc, lr
+	ret	lr
 #endif
 
 ENTRY(ftrace_stub)
 .Lftrace_stub:
-	mov	pc, lr
+	ret	lr
 ENDPROC(ftrace_stub)
 
 #endif /* CONFIG_FUNCTION_TRACER */
@@ -561,7 +562,7 @@ sys_mmap2:
 		streq	r5, [sp, #4]
 		beq	sys_mmap_pgoff
 		mov	r0, #-EINVAL
-		mov	pc, lr
+		ret	lr
 #else
 		str	r5, [sp, #4]
 		b	sys_mmap_pgoff
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/entry-header.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-header.S
--- linux-libre-3.16-gnu/arch/arm/kernel/entry-header.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/entry-header.S	2014-09-28 17:29:07.000000000 -0400
@@ -208,26 +208,21 @@
 #endif
 	.endif
 	msr	spsr_cxsf, \rpsr
-#if defined(CONFIG_CPU_V6)
-	ldr	r0, [sp]
-	strex	r1, r2, [sp]			@ clear the exclusive monitor
-	ldmib	sp, {r1 - pc}^			@ load r1 - pc, cpsr
-#elif defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
-#else
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
+	@ We must avoid clrex due to Cortex-A15 erratum #830321
+	sub	r0, sp, #4			@ uninhabited address
+	strex	r1, r2, [r0]			@ clear the exclusive monitor
 #endif
+	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 	.endm
 
 	.macro	restore_user_regs, fast = 0, offset = 0
 	ldr	r1, [sp, #\offset + S_PSR]	@ get calling cpsr
 	ldr	lr, [sp, #\offset + S_PC]!	@ get pc
 	msr	spsr_cxsf, r1			@ save in spsr_svc
-#if defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
+	@ We must avoid clrex due to Cortex-A15 erratum #830321
 	strex	r1, r2, [sp]			@ clear the exclusive monitor
-#elif defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
 #endif
 	.if	\fast
 	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
@@ -240,12 +235,6 @@
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
 
-	@
-	@ 32-bit wide "mov pc, reg"
-	@
-	.macro	movw_pc, reg
-	mov	pc, \reg
-	.endm
 #else	/* CONFIG_THUMB2_KERNEL */
 	.macro	svc_exit, rpsr, irq = 0
 	.if	\irq != 0
@@ -267,7 +256,10 @@
 	.endif
 	ldr	lr, [sp, #S_SP]			@ top of the stack
 	ldrd	r0, r1, [sp, #S_LR]		@ calling lr and pc
-	clrex					@ clear the exclusive monitor
+
+	@ We must avoid clrex due to Cortex-A15 erratum #830321
+	strex	r2, r1, [sp, #S_LR]		@ clear the exclusive monitor
+
 	stmdb	lr!, {r0, r1, \rpsr}		@ calling lr and rfe context
 	ldmia	sp, {r0 - r12}
 	mov	sp, lr
@@ -288,13 +280,16 @@
 	.endm
 #else	/* ifdef CONFIG_CPU_V7M */
 	.macro	restore_user_regs, fast = 0, offset = 0
-	clrex					@ clear the exclusive monitor
 	mov	r2, sp
 	load_user_sp_lr r2, r3, \offset + S_SP	@ calling sp, lr
 	ldr	r1, [sp, #\offset + S_PSR]	@ get calling cpsr
 	ldr	lr, [sp, #\offset + S_PC]	@ get pc
 	add	sp, sp, #\offset + S_SP
 	msr	spsr_cxsf, r1			@ save in spsr_svc
+
+	@ We must avoid clrex due to Cortex-A15 erratum #830321
+	strex	r1, r2, [sp]			@ clear the exclusive monitor
+
 	.if	\fast
 	ldmdb	sp, {r1 - r12}			@ get calling r1 - r12
 	.else
@@ -304,14 +299,6 @@
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
 #endif	/* ifdef CONFIG_CPU_V7M / else */
-
-	@
-	@ 32-bit wide "mov pc, reg"
-	@
-	.macro	movw_pc, reg
-	mov	pc, \reg
-	nop
-	.endm
 #endif	/* !CONFIG_THUMB2_KERNEL */
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/fiqasm.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/fiqasm.S
--- linux-libre-3.16-gnu/arch/arm/kernel/fiqasm.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/fiqasm.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@ ENTRY(__set_fiq_regs)
 	ldr	lr, [r0]
 	msr	cpsr_c, r1	@ return to SVC mode
 	mov	r0, r0		@ avoid hazard prior to ARMv4
-	mov	pc, lr
+	ret	lr
 ENDPROC(__set_fiq_regs)
 
 ENTRY(__get_fiq_regs)
@@ -45,5 +45,5 @@ ENTRY(__get_fiq_regs)
 	str	lr, [r0]
 	msr	cpsr_c, r1	@ return to SVC mode
 	mov	r0, r0		@ avoid hazard prior to ARMv4
-	mov	pc, lr
+	ret	lr
 ENDPROC(__get_fiq_regs)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/head-common.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/head-common.S
--- linux-libre-3.16-gnu/arch/arm/kernel/head-common.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/head-common.S	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  */
+#include <asm/assembler.h>
 
 #define ATAG_CORE 0x54410001
 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
@@ -61,10 +62,10 @@ __vet_atags:
 	cmp	r5, r6
 	bne	1f
 
-2:	mov	pc, lr				@ atag/dtb pointer is ok
+2:	ret	lr				@ atag/dtb pointer is ok
 
 1:	mov	r2, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__vet_atags)
 
 /*
@@ -162,7 +163,7 @@ __lookup_processor_type:
 	cmp	r5, r6
 	blo	1b
 	mov	r5, #0				@ unknown processor
-2:	mov	pc, lr
+2:	ret	lr
 ENDPROC(__lookup_processor_type)
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/head-nommu.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/head-nommu.S
--- linux-libre-3.16-gnu/arch/arm/kernel/head-nommu.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/head-nommu.S	2014-09-28 17:29:07.000000000 -0400
@@ -82,7 +82,7 @@ ENTRY(stext)
 	adr	lr, BSYM(1f)			@ return (PIC) address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
- THUMB(	mov	pc, r12				)
+ THUMB(	ret	r12				)
  1:	b	__after_proc_init
 ENDPROC(stext)
 
@@ -119,7 +119,7 @@ ENTRY(secondary_startup)
 	mov	r13, r12			@ __secondary_switched address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
- THUMB(	mov	pc, r12				)
+ THUMB(	ret	r12				)
 ENDPROC(secondary_startup)
 
 ENTRY(__secondary_switched)
@@ -164,7 +164,7 @@ __after_proc_init:
 #endif
 	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
 #endif /* CONFIG_CPU_CP15 */
-	mov	pc, r13
+	ret	r13
 ENDPROC(__after_proc_init)
 	.ltorg
 
@@ -254,7 +254,7 @@ ENTRY(__setup_mpu)
 	orr	r0, r0, #CR_M			@ Set SCTRL.M (MPU on)
 	mcr	p15, 0, r0, c1, c0, 0		@ Enable MPU
 	isb
-	mov pc,lr
+	ret	lr
 ENDPROC(__setup_mpu)
 #endif
 #include "head-common.S"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/head.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/head.S
--- linux-libre-3.16-gnu/arch/arm/kernel/head.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/head.S	2014-09-28 17:29:07.000000000 -0400
@@ -140,7 +140,7 @@ ENTRY(stext)
 	mov	r8, r4				@ set TTBR1 to swapper_pg_dir
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
- THUMB(	mov	pc, r12				)
+ THUMB(	ret	r12				)
 1:	b	__enable_mmu
 ENDPROC(stext)
 	.ltorg
@@ -335,7 +335,7 @@ __create_page_tables:
 	sub	r4, r4, #0x1000		@ point to the PGD table
 	mov	r4, r4, lsr #ARCH_PGD_SHIFT
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(__create_page_tables)
 	.ltorg
 	.align
@@ -383,7 +383,7 @@ ENTRY(secondary_startup)
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	) @ initialise processor
 						  @ (return control reg)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
- THUMB(	mov	pc, r12				)
+ THUMB(	ret	r12				)
 ENDPROC(secondary_startup)
 
 	/*
@@ -468,7 +468,7 @@ ENTRY(__turn_mmu_on)
 	instr_sync
 	mov	r3, r3
 	mov	r3, r13
-	mov	pc, r3
+	ret	r3
 __turn_mmu_on_end:
 ENDPROC(__turn_mmu_on)
 	.popsection
@@ -487,7 +487,7 @@ __fixup_smp:
 	orr	r4, r4, #0x0000b000
 	orr	r4, r4, #0x00000020	@ val 0x4100b020
 	teq	r3, r4			@ ARM 11MPCore?
-	moveq	pc, lr			@ yes, assume SMP
+	reteq	lr			@ yes, assume SMP
 
 	mrc	p15, 0, r0, c0, c0, 5	@ read MPIDR
 	and	r0, r0, #0xc0000000	@ multiprocessing extensions and
@@ -500,7 +500,7 @@ __fixup_smp:
 	orr	r4, r4, #0x0000c000
 	orr	r4, r4, #0x00000090
 	teq	r3, r4			@ Check for ARM Cortex-A9
-	movne	pc, lr			@ Not ARM Cortex-A9,
+	retne	lr			@ Not ARM Cortex-A9,
 
 	@ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the
 	@ below address check will need to be #ifdef'd or equivalent
@@ -512,7 +512,7 @@ __fixup_smp:
 ARM_BE8(rev	r0, r0)			@ byteswap if big endian
 	and	r0, r0, #0x3		@ number of CPUs
 	teq	r0, #0x0		@ is 1?
-	movne	pc, lr
+	retne	lr
 
 __fixup_smp_on_up:
 	adr	r0, 1f
@@ -539,7 +539,7 @@ smp_on_up:
 	.text
 __do_fixup_smp_on_up:
 	cmp	r4, r5
-	movhs	pc, lr
+	reths	lr
 	ldmia	r4!, {r0, r6}
  ARM(	str	r6, [r0, r3]	)
  THUMB(	add	r0, r0, r3	)
@@ -672,7 +672,7 @@ ARM_BE8(rev16	ip, ip)
 2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
 	bcc	1b
-	mov	pc, lr
+	ret	lr
 #endif
 ENDPROC(__fixup_a_pv_table)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/hyp-stub.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/hyp-stub.S
--- linux-libre-3.16-gnu/arch/arm/kernel/hyp-stub.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/hyp-stub.S	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary)
 	 * immediately.
 	 */
 	compare_cpu_mode_with_primary	r4, r5, r6, r7
-	movne	pc, lr
+	retne	lr
 
 	/*
 	 * Once we have given up on one CPU, we do not try to install the
@@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary)
 	 */
 
 	cmp	r4, #HYP_MODE
-	movne	pc, lr			@ give up if the CPU is not in HYP mode
+	retne	lr			@ give up if the CPU is not in HYP mode
 
 /*
  * Configure HSCTLR to set correct exception endianness/instruction set
@@ -134,9 +134,7 @@ ENTRY(__hyp_stub_install_secondary)
 	mcr	p15, 4, r7, c1, c1, 3	@ HSTR
 
 THUMB(	orr	r7, #(1 << 30)	)	@ HSCTLR.TE
-#ifdef CONFIG_CPU_BIG_ENDIAN
-	orr	r7, #(1 << 9)		@ HSCTLR.EE
-#endif
+ARM_BE8(orr	r7, r7, #(1 << 25))     @ HSCTLR.EE
 	mcr	p15, 4, r7, c1, c0, 0	@ HSCTLR
 
 	mrc	p15, 4, r7, c1, c1, 1	@ HDCR
@@ -201,7 +199,7 @@ ENDPROC(__hyp_get_vectors)
 	@ fall through
 ENTRY(__hyp_set_vectors)
 	__HVC(0)
-	mov	pc, lr
+	ret	lr
 ENDPROC(__hyp_set_vectors)
 
 #ifndef ZIMAGE
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/irq.c
--- linux-libre-3.16-gnu/arch/arm/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -175,7 +175,7 @@ static bool migrate_one_irq(struct irq_d
 	c = irq_data_get_irq_chip(d);
 	if (!c->irq_set_affinity)
 		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
-	else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+	else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
 		cpumask_copy(d->affinity, affinity);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/iwmmxt.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/iwmmxt.S
--- linux-libre-3.16-gnu/arch/arm/kernel/iwmmxt.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/iwmmxt.S	2014-09-28 17:29:07.000000000 -0400
@@ -100,7 +100,7 @@ ENTRY(iwmmxt_task_enable)
 	get_thread_info r10
 #endif
 4:	dec_preempt_count r10, r3
-	mov	pc, r9				@ normal exit from exception
+	ret	r9				@ normal exit from exception
 
 concan_save:
 
@@ -144,7 +144,7 @@ concan_dump:
 	wstrd	wR15, [r1, #MMX_WR15]
 
 2:	teq	r0, #0				@ anything to load?
-	moveq	pc, lr				@ if not, return
+	reteq	lr				@ if not, return
 
 concan_load:
 
@@ -177,10 +177,10 @@ concan_load:
 	@ clear CUP/MUP (only if r1 != 0)
 	teq	r1, #0
 	mov 	r2, #0
-	moveq	pc, lr
+	reteq	lr
 
 	tmcr	wCon, r2
-	mov	pc, lr
+	ret	lr
 
 /*
  * Back up Concan regs to save area and disable access to them
@@ -266,7 +266,7 @@ ENTRY(iwmmxt_task_copy)
 	mov	r3, lr				@ preserve return address
 	bl	concan_dump
 	msr	cpsr_c, ip			@ restore interrupt mode
-	mov	pc, r3
+	ret	r3
 
 /*
  * Restore Concan state from given memory address
@@ -302,7 +302,7 @@ ENTRY(iwmmxt_task_restore)
 	mov	r3, lr				@ preserve return address
 	bl	concan_load
 	msr	cpsr_c, ip			@ restore interrupt mode
-	mov	pc, r3
+	ret	r3
 
 /*
  * Concan handling on task switch
@@ -324,7 +324,7 @@ ENTRY(iwmmxt_task_switch)
 	add	r3, r0, #TI_IWMMXT_STATE	@ get next task Concan save area
 	ldr	r2, [r2]			@ get current Concan owner
 	teq	r2, r3				@ next task owns it?
-	movne	pc, lr				@ no: leave Concan disabled
+	retne	lr				@ no: leave Concan disabled
 
 1:	@ flip Concan access
 	XSC(eor	r1, r1, #0x3)
@@ -351,7 +351,7 @@ ENTRY(iwmmxt_task_release)
 	eors	r0, r0, r1			@ if equal...
 	streq	r0, [r3]			@ then clear ownership
 	msr	cpsr_c, r2			@ restore interrupts
-	mov	pc, lr
+	ret	lr
 
 	.data
 concan_owner:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/module.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/module.c
--- linux-libre-3.16-gnu/arch/arm/kernel/module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/module.c	2014-09-28 17:29:07.000000000 -0400
@@ -91,6 +91,7 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
 			break;
 
 		case R_ARM_ABS32:
+		case R_ARM_TARGET1:
 			*(u32 *)loc += sym->st_value;
 			break;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/perf_event.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event.c
--- linux-libre-3.16-gnu/arch/arm/kernel/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -560,11 +560,16 @@ user_backtrace(struct frame_tail __user
 	       struct perf_callchain_entry *entry)
 {
 	struct frame_tail buftail;
+	unsigned long err;
 
-	/* Also check accessibility of one struct frame_tail beyond */
 	if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
 		return NULL;
-	if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
+
+	pagefault_disable();
+	err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+	pagefault_enable();
+
+	if (err)
 		return NULL;
 
 	perf_callchain_store(entry, buftail.lr);
@@ -590,6 +595,10 @@ perf_callchain_user(struct perf_callchai
 	}
 
 	perf_callchain_store(entry, regs->ARM_pc);
+
+	if (!current->mm)
+		return;
+
 	tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
 	while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
@@ -621,10 +630,7 @@ perf_callchain_kernel(struct perf_callch
 		return;
 	}
 
-	fr.fp = regs->ARM_fp;
-	fr.sp = regs->ARM_sp;
-	fr.lr = regs->ARM_lr;
-	fr.pc = regs->ARM_pc;
+	arm_get_current_stackframe(regs, &fr);
 	walk_stackframe(&fr, callchain_trace, entry);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/perf_event_cpu.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_cpu.c
--- linux-libre-3.16-gnu/arch/arm/kernel/perf_event_cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,21 +76,15 @@ static struct pmu_hw_events *cpu_pmu_get
 
 static void cpu_pmu_enable_percpu_irq(void *data)
 {
-	struct arm_pmu *cpu_pmu = data;
-	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	int irq = platform_get_irq(pmu_device, 0);
+	int irq = *(int *)data;
 
 	enable_percpu_irq(irq, IRQ_TYPE_NONE);
-	cpumask_set_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
 }
 
 static void cpu_pmu_disable_percpu_irq(void *data)
 {
-	struct arm_pmu *cpu_pmu = data;
-	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	int irq = platform_get_irq(pmu_device, 0);
+	int irq = *(int *)data;
 
-	cpumask_clear_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
 	disable_percpu_irq(irq);
 }
 
@@ -103,7 +97,7 @@ static void cpu_pmu_free_irq(struct arm_
 
 	irq = platform_get_irq(pmu_device, 0);
 	if (irq >= 0 && irq_is_percpu(irq)) {
-		on_each_cpu(cpu_pmu_disable_percpu_irq, cpu_pmu, 1);
+		on_each_cpu(cpu_pmu_disable_percpu_irq, &irq, 1);
 		free_percpu_irq(irq, &percpu_pmu);
 	} else {
 		for (i = 0; i < irqs; ++i) {
@@ -138,7 +132,7 @@ static int cpu_pmu_request_irq(struct ar
 				irq);
 			return err;
 		}
-		on_each_cpu(cpu_pmu_enable_percpu_irq, cpu_pmu, 1);
+		on_each_cpu(cpu_pmu_enable_percpu_irq, &irq, 1);
 	} else {
 		for (i = 0; i < irqs; ++i) {
 			err = 0;
@@ -233,14 +227,17 @@ static struct of_device_id cpu_pmu_of_de
 	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
 	{.compatible = "arm,cortex-a5-pmu",	.data = armv7_a5_pmu_init},
 	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
-	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
-	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
+	{.compatible = "arm,arm1176-pmu",	.data = armv6_1176_pmu_init},
+	{.compatible = "arm,arm1136-pmu",	.data = armv6_1136_pmu_init},
 	{.compatible = "qcom,krait-pmu",	.data = krait_pmu_init},
 	{},
 };
 
 static struct platform_device_id cpu_pmu_plat_device_ids[] = {
 	{.name = "arm-pmu"},
+	{.name = "armv6-pmu"},
+	{.name = "armv7-pmu"},
+	{.name = "xscale-pmu"},
 	{},
 };
 
@@ -250,40 +247,43 @@ static struct platform_device_id cpu_pmu
 static int probe_current_pmu(struct arm_pmu *pmu)
 {
 	int cpu = get_cpu();
-	unsigned long implementor = read_cpuid_implementor();
-	unsigned long part_number = read_cpuid_part_number();
 	int ret = -ENODEV;
 
 	pr_info("probing PMU on CPU %d\n", cpu);
 
+	switch (read_cpuid_part()) {
 	/* ARM Ltd CPUs. */
-	if (implementor == ARM_CPU_IMP_ARM) {
-		switch (part_number) {
-		case ARM_CPU_PART_ARM1136:
-		case ARM_CPU_PART_ARM1156:
-		case ARM_CPU_PART_ARM1176:
-			ret = armv6pmu_init(pmu);
-			break;
-		case ARM_CPU_PART_ARM11MPCORE:
-			ret = armv6mpcore_pmu_init(pmu);
-			break;
-		case ARM_CPU_PART_CORTEX_A8:
-			ret = armv7_a8_pmu_init(pmu);
-			break;
-		case ARM_CPU_PART_CORTEX_A9:
-			ret = armv7_a9_pmu_init(pmu);
-			break;
-		}
-	/* Intel CPUs [xscale]. */
-	} else if (implementor == ARM_CPU_IMP_INTEL) {
-		switch (xscale_cpu_arch_version()) {
-		case ARM_CPU_XSCALE_ARCH_V1:
-			ret = xscale1pmu_init(pmu);
-			break;
-		case ARM_CPU_XSCALE_ARCH_V2:
-			ret = xscale2pmu_init(pmu);
-			break;
+	case ARM_CPU_PART_ARM1136:
+		ret = armv6_1136_pmu_init(pmu);
+		break;
+	case ARM_CPU_PART_ARM1156:
+		ret = armv6_1156_pmu_init(pmu);
+		break;
+	case ARM_CPU_PART_ARM1176:
+		ret = armv6_1176_pmu_init(pmu);
+		break;
+	case ARM_CPU_PART_ARM11MPCORE:
+		ret = armv6mpcore_pmu_init(pmu);
+		break;
+	case ARM_CPU_PART_CORTEX_A8:
+		ret = armv7_a8_pmu_init(pmu);
+		break;
+	case ARM_CPU_PART_CORTEX_A9:
+		ret = armv7_a9_pmu_init(pmu);
+		break;
+
+	default:
+		if (read_cpuid_implementor() == ARM_CPU_IMP_INTEL) {
+			switch (xscale_cpu_arch_version()) {
+			case ARM_CPU_XSCALE_ARCH_V1:
+				ret = xscale1pmu_init(pmu);
+				break;
+			case ARM_CPU_XSCALE_ARCH_V2:
+				ret = xscale2pmu_init(pmu);
+				break;
+			}
 		}
+		break;
 	}
 
 	put_cpu();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/perf_event_v6.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_v6.c
--- linux-libre-3.16-gnu/arch/arm/kernel/perf_event_v6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_v6.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,13 +65,11 @@ enum armv6_counters {
  * accesses/misses in hardware.
  */
 static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV6_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV6_PERFCTR_INSTR_EXEC,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV6_PERFCTR_BR_EXEC,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV6_PERFCTR_BR_MISPREDICT,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV6_PERFCTR_IBUF_STALL,
 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV6_PERFCTR_LSU_FULL_STALL,
 };
@@ -79,116 +77,31 @@ static const unsigned armv6_perf_map[PER
 static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * The ARM performance counters can count micro DTLB misses,
-		 * micro ITLB misses and main TLB misses. There isn't an event
-		 * for TLB misses, so use the micro misses here and if users
-		 * want the main TLB misses they can use a raw counter.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	/*
+	 * The performance counters don't differentiate between read and write
+	 * accesses/misses so this isn't strictly correct, but it's the best we
+	 * can do. Writes and reads get combined.
+	 */
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
+
+	/*
+	 * The ARM performance counters can count micro DTLB misses, micro ITLB
+	 * misses and main TLB misses. There isn't an event for TLB misses, so
+	 * use the micro misses here and if users want the main TLB misses they
+	 * can use a raw counter.
+	 */
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
 };
 
 enum armv6mpcore_perf_types {
@@ -220,13 +133,11 @@ enum armv6mpcore_perf_types {
  * accesses/misses in hardware.
  */
 static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV6MPCORE_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV6MPCORE_PERFCTR_INSTR_EXEC,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV6MPCORE_PERFCTR_BR_EXEC,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV6MPCORE_PERFCTR_IBUF_STALL,
 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV6MPCORE_PERFCTR_LSU_FULL_STALL,
 };
@@ -234,114 +145,26 @@ static const unsigned armv6mpcore_perf_m
 static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  =
-				ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
-			[C(RESULT_MISS)]    =
-				ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  =
-				ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
-			[C(RESULT_MISS)]    =
-				ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * The ARM performance counters can count micro DTLB misses,
-		 * micro ITLB misses and main TLB misses. There isn't an event
-		 * for TLB misses, so use the micro misses here and if users
-		 * want the main TLB misses they can use a raw counter.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+
+	/*
+	 * The ARM performance counters can count micro DTLB misses, micro ITLB
+	 * misses and main TLB misses. There isn't an event for TLB misses, so
+	 * use the micro misses here and if users want the main TLB misses they
+	 * can use a raw counter.
+	 */
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_DTLB_MISS,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_DTLB_MISS,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_ITLB_MISS,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV6MPCORE_PERFCTR_ITLB_MISS,
 };
 
 static inline unsigned long
@@ -653,9 +476,8 @@ static int armv6_map_event(struct perf_e
 				&armv6_perf_cache_map, 0xFF);
 }
 
-static int armv6pmu_init(struct arm_pmu *cpu_pmu)
+static void armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
-	cpu_pmu->name		= "v6";
 	cpu_pmu->handle_irq	= armv6pmu_handle_irq;
 	cpu_pmu->enable		= armv6pmu_enable_event;
 	cpu_pmu->disable	= armv6pmu_disable_event;
@@ -667,7 +489,26 @@ static int armv6pmu_init(struct arm_pmu
 	cpu_pmu->map_event	= armv6_map_event;
 	cpu_pmu->num_events	= 3;
 	cpu_pmu->max_period	= (1LLU << 32) - 1;
+}
+
+static int armv6_1136_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv6pmu_init(cpu_pmu);
+	cpu_pmu->name		= "armv6_1136";
+	return 0;
+}
+
+static int armv6_1156_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv6pmu_init(cpu_pmu);
+	cpu_pmu->name		= "armv6_1156";
+	return 0;
+}
 
+static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv6pmu_init(cpu_pmu);
+	cpu_pmu->name		= "armv6_1176";
 	return 0;
 }
 
@@ -687,7 +528,7 @@ static int armv6mpcore_map_event(struct
 
 static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	cpu_pmu->name		= "v6mpcore";
+	cpu_pmu->name		= "armv6_11mpcore";
 	cpu_pmu->handle_irq	= armv6pmu_handle_irq;
 	cpu_pmu->enable		= armv6pmu_enable_event;
 	cpu_pmu->disable	= armv6mpcore_pmu_disable_event;
@@ -703,7 +544,17 @@ static int armv6mpcore_pmu_init(struct a
 	return 0;
 }
 #else
-static int armv6pmu_init(struct arm_pmu *cpu_pmu)
+static int armv6_1136_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	return -ENODEV;
+}
+
+static int armv6_1156_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	return -ENODEV;
+}
+
+static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	return -ENODEV;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/perf_event_v7.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_v7.c
--- linux-libre-3.16-gnu/arch/arm/kernel/perf_event_v7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_v7.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,137 +148,62 @@ enum krait_perf_types {
  * accesses/misses in hardware.
  */
 static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
 	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV7_PERFCTR_L1_DCACHE_REFILL,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_PERFCTR_PC_WRITE,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV7_A8_PERFCTR_STALL_ISIDE,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	/*
+	 * The performance counters don't differentiate between read and write
+	 * accesses/misses so this isn't strictly correct, but it's the best we
+	 * can do. Writes and reads get combined.
+	 */
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+	[C(LL)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
+	[C(LL)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
+	[C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
+	[C(LL)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Cortex-A9 HW events mapping
  */
 static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_A9_PERFCTR_INSTR_CORE_RENAME,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
 	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV7_PERFCTR_L1_DCACHE_REFILL,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_PERFCTR_PC_WRITE,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV7_A9_PERFCTR_STALL_ICACHE,
 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV7_A9_PERFCTR_STALL_DISPATCH,
 };
@@ -286,238 +211,83 @@ static const unsigned armv7_a9_perf_map[
 static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	/*
+	 * The performance counters don't differentiate between read and write
+	 * accesses/misses so this isn't strictly correct, but it's the best we
+	 * can do. Writes and reads get combined.
+	 */
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Cortex-A5 HW events mapping
  */
 static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
 	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV7_PERFCTR_L1_DCACHE_REFILL,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_PERFCTR_PC_WRITE,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
-			[C(RESULT_MISS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		/*
-		 * The prefetch counters don't differentiate between the I
-		 * side and the D side.
-		 */
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
-			[C(RESULT_MISS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
+	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+	/*
+	 * The prefetch counters don't differentiate between the I side and the
+	 * D side.
+	 */
+	[C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
+	[C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)]	= ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Cortex-A15 HW events mapping
  */
 static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -525,123 +295,48 @@ static const unsigned armv7_a15_perf_map
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_A15_PERFCTR_PC_WRITE_SPEC,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV7_PERFCTR_BUS_CYCLES,
-	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		/*
-		 * Not all performance counters differentiate between read
-		 * and write accesses/misses so we're not always strictly
-		 * correct, but it's the best we can do. Writes and reads get
-		 * combined in these cases.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE,
+
+	/*
+	 * Not all performance counters differentiate between read and write
+	 * accesses/misses so we're not always strictly correct, but it's the
+	 * best we can do. Writes and reads get combined in these cases.
+	 */
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+	[C(LL)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ,
+	[C(LL)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ,
+	[C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE,
+	[C(LL)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Cortex-A7 HW events mapping
  */
 static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -649,123 +344,48 @@ static const unsigned armv7_a7_perf_map[
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_PERFCTR_PC_WRITE,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV7_PERFCTR_BUS_CYCLES,
-	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_CACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_CACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	/*
+	 * The performance counters don't differentiate between read and write
+	 * accesses/misses so this isn't strictly correct, but it's the best we
+	 * can do. Writes and reads get combined.
+	 */
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+	[C(LL)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_CACHE_ACCESS,
+	[C(LL)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+	[C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_CACHE_ACCESS,
+	[C(LL)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Cortex-A12 HW events mapping
  */
 static const unsigned armv7_a12_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV7_PERFCTR_INSTR_EXECUTED,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -773,138 +393,60 @@ static const unsigned armv7_a12_perf_map
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV7_A12_PERFCTR_PC_WRITE_SPEC,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV7_PERFCTR_BUS_CYCLES,
-	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned armv7_a12_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		/*
-		 * Not all performance counters differentiate between read
-		 * and write accesses/misses so we're not always strictly
-		 * correct, but it's the best we can do. Writes and reads get
-		 * combined in these cases.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_A12_PERFCTR_PF_TLB_REFILL,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+	/*
+	 * Not all performance counters differentiate between read and write
+	 * accesses/misses so we're not always strictly correct, but it's the
+	 * best we can do. Writes and reads get combined in these cases.
+	 */
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+	[C(LL)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ,
+	[C(LL)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+	[C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE,
+	[C(LL)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACHE_REFILL,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+	[C(DTLB)][C(OP_PREFETCH)][C(RESULT_MISS)]	= ARMV7_A12_PERFCTR_PF_TLB_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_REFILL,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
  * Krait HW events mapping
  */
 static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
 	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
 
 static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
 	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
@@ -912,110 +454,31 @@ static const unsigned krait_perf_map_no_
 static const unsigned krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= KRAIT_PERFCTR_L1_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	/*
+	 * The performance counters don't differentiate between read and write
+	 * accesses/misses so this isn't strictly correct, but it's the best we
+	 * can do. Writes and reads get combined.
+	 */
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ICACHE_ACCESS,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= KRAIT_PERFCTR_L1_ICACHE_MISS,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_DTLB_ACCESS,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_ACCESS)]	= KRAIT_PERFCTR_L1_ITLB_ACCESS,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
 /*
@@ -1545,7 +1008,7 @@ static u32 armv7_read_num_pmnc_events(vo
 static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A8";
+	cpu_pmu->name		= "armv7_cortex_a8";
 	cpu_pmu->map_event	= armv7_a8_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	return 0;
@@ -1554,7 +1017,7 @@ static int armv7_a8_pmu_init(struct arm_
 static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A9";
+	cpu_pmu->name		= "armv7_cortex_a9";
 	cpu_pmu->map_event	= armv7_a9_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	return 0;
@@ -1563,7 +1026,7 @@ static int armv7_a9_pmu_init(struct arm_
 static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A5";
+	cpu_pmu->name		= "armv7_cortex_a5";
 	cpu_pmu->map_event	= armv7_a5_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	return 0;
@@ -1572,7 +1035,7 @@ static int armv7_a5_pmu_init(struct arm_
 static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A15";
+	cpu_pmu->name		= "armv7_cortex_a15";
 	cpu_pmu->map_event	= armv7_a15_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1582,7 +1045,7 @@ static int armv7_a15_pmu_init(struct arm
 static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A7";
+	cpu_pmu->name		= "armv7_cortex_a7";
 	cpu_pmu->map_event	= armv7_a7_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1592,7 +1055,7 @@ static int armv7_a7_pmu_init(struct arm_
 static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Cortex-A12";
+	cpu_pmu->name		= "armv7_cortex_a12";
 	cpu_pmu->map_event	= armv7_a12_map_event;
 	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
 	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1602,7 +1065,7 @@ static int armv7_a12_pmu_init(struct arm
 static int armv7_a17_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7_a12_pmu_init(cpu_pmu);
-	cpu_pmu->name = "ARMv7 Cortex-A17";
+	cpu_pmu->name = "armv7_cortex_a17";
 	return 0;
 }
 
@@ -1823,6 +1286,7 @@ static void krait_pmu_disable_event(stru
 	unsigned long flags;
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/* Disable counter and interrupt */
@@ -1848,6 +1312,7 @@ static void krait_pmu_enable_event(struc
 	unsigned long flags;
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
@@ -1981,7 +1446,7 @@ static void krait_pmu_clear_event_idx(st
 static int krait_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	armv7pmu_init(cpu_pmu);
-	cpu_pmu->name		= "ARMv7 Krait";
+	cpu_pmu->name		= "armv7_krait";
 	/* Some early versions of Krait don't support PC write events */
 	if (of_property_read_bool(cpu_pmu->plat_device->dev.of_node,
 				  "qcom,no-pc-write"))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/perf_event_xscale.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_xscale.c
--- linux-libre-3.16-gnu/arch/arm/kernel/perf_event_xscale.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/perf_event_xscale.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,118 +48,31 @@ enum xscale_counters {
 };
 
 static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
 	[PERF_COUNT_HW_CPU_CYCLES]		= XSCALE_PERFCTR_CCNT,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= XSCALE_PERFCTR_INSTRUCTION,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= XSCALE_PERFCTR_BRANCH,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= XSCALE_PERFCTR_BRANCH_MISS,
-	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= XSCALE_PERFCTR_ICACHE_NO_DELIVER,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
 };
 
 static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					   [PERF_COUNT_HW_CACHE_OP_MAX]
 					   [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(NODE)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
+	[C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
 };
 
 #define	XSCALE_PMU_ENABLE	0x001
@@ -442,7 +355,7 @@ static int xscale_map_event(struct perf_
 
 static int xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
-	cpu_pmu->name		= "xscale1";
+	cpu_pmu->name		= "armv5_xscale1";
 	cpu_pmu->handle_irq	= xscale1pmu_handle_irq;
 	cpu_pmu->enable		= xscale1pmu_enable_event;
 	cpu_pmu->disable	= xscale1pmu_disable_event;
@@ -812,7 +725,7 @@ static inline void xscale2pmu_write_coun
 
 static int xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
-	cpu_pmu->name		= "xscale2";
+	cpu_pmu->name		= "armv5_xscale2";
 	cpu_pmu->handle_irq	= xscale2pmu_handle_irq;
 	cpu_pmu->enable		= xscale2pmu_enable_event;
 	cpu_pmu->disable	= xscale2pmu_disable_event;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/process.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/process.c
--- linux-libre-3.16-gnu/arch/arm/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -334,6 +334,8 @@ void flush_thread(void)
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
 	memset(&thread->fpstate, 0, sizeof(union fp_state));
 
+	flush_tls();
+
 	thread_notify(THREAD_NOTIFY_FLUSH, thread);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/relocate_kernel.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/relocate_kernel.S
--- linux-libre-3.16-gnu/arch/arm/kernel/relocate_kernel.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/relocate_kernel.S	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/kexec.h>
 
 	.align	3	/* not needed for this code, but keeps fncpy() happy */
@@ -59,7 +60,7 @@ ENTRY(relocate_new_kernel)
 	mov r0,#0
 	ldr r1,kexec_mach_type
 	ldr r2,kexec_boot_atags
- ARM(	mov pc, lr	)
+ ARM(	ret lr	)
  THUMB(	bx lr		)
 
 	.align
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/setup.c
--- linux-libre-3.16-gnu/arch/arm/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -393,19 +393,34 @@ static void __init cpuid_init_hwcaps(voi
 		elf_hwcap |= HWCAP_LPAE;
 }
 
-static void __init feat_v6_fixup(void)
+static void __init elf_hwcap_fixup(void)
 {
-	int id = read_cpuid_id();
-
-	if ((id & 0xff0f0000) != 0x41070000)
-		return;
+	unsigned id = read_cpuid_id();
+	unsigned sync_prim;
 
 	/*
 	 * HWCAP_TLS is available only on 1136 r1p0 and later,
 	 * see also kuser_get_tls_init.
 	 */
-	if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0))
+	if (read_cpuid_part() == ARM_CPU_PART_ARM1136 &&
+	    ((id >> 20) & 3) == 0) {
 		elf_hwcap &= ~HWCAP_TLS;
+		return;
+	}
+
+	/* Verify if CPUID scheme is implemented */
+	if ((id & 0x000f0000) != 0x000f0000)
+		return;
+
+	/*
+	 * If the CPU supports LDREX/STREX and LDREXB/STREXB,
+	 * avoid advertising SWP; it may not be atomic with
+	 * multiprocessing cores.
+	 */
+	sync_prim = ((read_cpuid_ext(CPUID_EXT_ISAR3) >> 8) & 0xf0) |
+		    ((read_cpuid_ext(CPUID_EXT_ISAR4) >> 20) & 0x0f);
+	if (sync_prim >= 0x13)
+		elf_hwcap &= ~HWCAP_SWP;
 }
 
 /*
@@ -609,7 +624,7 @@ static void __init setup_processor(void)
 #endif
 	erratum_a15_798181_init();
 
-	feat_v6_fixup();
+	elf_hwcap_fixup();
 
 	cacheid_init();
 	cpu_init();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/sleep.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/sleep.S
--- linux-libre-3.16-gnu/arch/arm/kernel/sleep.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/sleep.S	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@ ENTRY(cpu_resume_mmu)
 	instr_sync
 	mov	r0, r0
 	mov	r0, r0
-	mov	pc, r3			@ jump to virtual address
+	ret	r3			@ jump to virtual address
 ENDPROC(cpu_resume_mmu)
 	.popsection
 cpu_resume_after_mmu:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp.c
--- linux-libre-3.16-gnu/arch/arm/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,9 @@
 #include <asm/mach/arch.h>
 #include <asm/mpu.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ipi.h>
+
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  * so we need some other way of telling a new secondary core
@@ -430,38 +433,15 @@ void __init smp_prepare_cpus(unsigned in
 	}
 }
 
-static void (*smp_cross_call)(const struct cpumask *, unsigned int);
+static void (*__smp_cross_call)(const struct cpumask *, unsigned int);
 
 void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
 {
-	if (!smp_cross_call)
-		smp_cross_call = fn;
-}
-
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
-	smp_cross_call(mask, IPI_CALL_FUNC);
-}
-
-void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
-{
-	smp_cross_call(mask, IPI_WAKEUP);
-}
-
-void arch_send_call_function_single_ipi(int cpu)
-{
-	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
-}
-
-#ifdef CONFIG_IRQ_WORK
-void arch_irq_work_raise(void)
-{
-	if (is_smp())
-		smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+	if (!__smp_cross_call)
+		__smp_cross_call = fn;
 }
-#endif
 
-static const char *ipi_types[NR_IPI] = {
+static const char *ipi_types[NR_IPI] __tracepoint_string = {
 #define S(x,s)	[x] = s
 	S(IPI_WAKEUP, "CPU wakeup interrupts"),
 	S(IPI_TIMER, "Timer broadcast interrupts"),
@@ -473,6 +453,12 @@ static const char *ipi_types[NR_IPI] = {
 	S(IPI_COMPLETION, "completion interrupts"),
 };
 
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
+{
+	trace_ipi_raise(target, ipi_types[ipinr]);
+	__smp_cross_call(target, ipinr);
+}
+
 void show_ipi_list(struct seq_file *p, int prec)
 {
 	unsigned int cpu, i;
@@ -499,6 +485,29 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	return sum;
 }
 
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_WAKEUP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+#ifdef CONFIG_IRQ_WORK
+void arch_irq_work_raise(void)
+{
+	if (is_smp())
+		smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+}
+#endif
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 void tick_broadcast(const struct cpumask *mask)
 {
@@ -556,8 +565,10 @@ void handle_IPI(int ipinr, struct pt_reg
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
-	if (ipinr < NR_IPI)
+	if ((unsigned)ipinr < NR_IPI) {
+		trace_ipi_entry(ipi_types[ipinr]);
 		__inc_irq_stat(cpu, ipi_irqs[ipinr]);
+	}
 
 	switch (ipinr) {
 	case IPI_WAKEUP:
@@ -612,6 +623,9 @@ void handle_IPI(int ipinr, struct pt_reg
 		       cpu, ipinr);
 		break;
 	}
+
+	if ((unsigned)ipinr < NR_IPI)
+		trace_ipi_exit(ipi_types[ipinr]);
 	set_irq_regs(old_regs);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/smp_scu.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp_scu.c
--- linux-libre-3.16-gnu/arch/arm/kernel/smp_scu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp_scu.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
 #include <asm/cputype.h>
 
 #define SCU_CTRL		0x00
+#define SCU_ENABLE		(1 << 0)
+#define SCU_STANDBY_ENABLE	(1 << 5)
 #define SCU_CONFIG		0x04
 #define SCU_CPU_STATUS		0x08
 #define SCU_INVALIDATE		0x0c
@@ -50,10 +52,16 @@ void scu_enable(void __iomem *scu_base)
 
 	scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
 	/* already enabled? */
-	if (scu_ctrl & 1)
+	if (scu_ctrl & SCU_ENABLE)
 		return;
 
-	scu_ctrl |= 1;
+	scu_ctrl |= SCU_ENABLE;
+
+	/* Cortex-A9 earlier than r2p0 has no standby bit in SCU */
+	if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090 &&
+	    (read_cpuid_id() & 0x00f0000f) >= 0x00200000)
+		scu_ctrl |= SCU_STANDBY_ENABLE;
+
 	writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/smp_tlb.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp_tlb.c
--- linux-libre-3.16-gnu/arch/arm/kernel/smp_tlb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/smp_tlb.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,15 +92,19 @@ void erratum_a15_798181_init(void)
 	unsigned int midr = read_cpuid_id();
 	unsigned int revidr = read_cpuid(CPUID_REVIDR);
 
-	/* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
-	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
-	    (revidr & 0x210) == 0x210) {
-		return;
-	}
-	if (revidr & 0x10)
-		erratum_a15_798181_handler = erratum_a15_798181_partial;
-	else
+	/* Brahma-B15 r0p0..r0p2 affected
+	 * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
+	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
 		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+	else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
+		 (revidr & 0x210) != 0x210) {
+		if (revidr & 0x10)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
+		else
+			erratum_a15_798181_handler =
+				erratum_a15_798181_broadcast;
+	}
 }
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/swp_emulate.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/swp_emulate.c
--- linux-libre-3.16-gnu/arch/arm/kernel/swp_emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/swp_emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/perf_event.h>
 
 #include <asm/opcodes.h>
+#include <asm/system_info.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 
@@ -141,14 +142,6 @@ static int emulate_swpX(unsigned int add
 	while (1) {
 		unsigned long temp;
 
-		/*
-		 * Barrier required between accessing protected resource and
-		 * releasing a lock for it. Legacy code might not have done
-		 * this, and we cannot determine that this is not the case
-		 * being emulated, so insert always.
-		 */
-		smp_mb();
-
 		if (type == TYPE_SWPB)
 			__user_swpb_asm(*data, address, res, temp);
 		else
@@ -161,13 +154,6 @@ static int emulate_swpX(unsigned int add
 	}
 
 	if (res == 0) {
-		/*
-		 * Barrier also required between acquiring a lock for a
-		 * protected resource and accessing the resource. Inserted for
-		 * same reason as above.
-		 */
-		smp_mb();
-
 		if (type == TYPE_SWPB)
 			swpbcounter++;
 		else
@@ -266,6 +252,9 @@ static struct undef_hook swp_hook = {
  */
 static int __init swp_emulation_init(void)
 {
+	if (cpu_architecture() < CPU_ARCH_ARMv7)
+		return 0;
+
 #ifdef CONFIG_PROC_FS
 	if (!proc_create("cpu/swp_emulation", S_IRUGO, NULL, &proc_status_fops))
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/thumbee.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/thumbee.c
--- linux-libre-3.16-gnu/arch/arm/kernel/thumbee.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/thumbee.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@ static int thumbee_notifier(struct notif
 
 	switch (cmd) {
 	case THREAD_NOTIFY_FLUSH:
-		thread->thumbee_state = 0;
+		teehbr_write(0);
 		break;
 	case THREAD_NOTIFY_SWITCH:
 		current_thread_info()->thumbee_state = teehbr_read();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/time.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/time.c
--- linux-libre-3.16-gnu/arch/arm/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,10 +50,7 @@ unsigned long profile_pc(struct pt_regs
 	if (!in_lock_functions(regs->ARM_pc))
 		return regs->ARM_pc;
 
-	frame.fp = regs->ARM_fp;
-	frame.sp = regs->ARM_sp;
-	frame.lr = regs->ARM_lr;
-	frame.pc = regs->ARM_pc;
+	arm_get_current_stackframe(regs, &frame);
 	do {
 		int ret = unwind_frame(&frame);
 		if (ret < 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/traps.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/traps.c
--- linux-libre-3.16-gnu/arch/arm/kernel/traps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/traps.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,11 +31,13 @@
 #include <asm/exception.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
+#include <asm/ptrace.h>
 #include <asm/unwind.h>
 #include <asm/tls.h>
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
 
+
 static const char *handler[]= {
 	"prefetch abort",
 	"data abort",
@@ -184,7 +186,7 @@ static void dump_backtrace(struct pt_reg
 		tsk = current;
 
 	if (regs) {
-		fp = regs->ARM_fp;
+		fp = frame_pointer(regs);
 		mode = processor_mode(regs);
 	} else if (tsk != current) {
 		fp = thread_saved_fp(tsk);
@@ -579,7 +581,6 @@ do_cache_op(unsigned long start, unsigne
 #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE)
 asmlinkage int arm_syscall(int no, struct pt_regs *regs)
 {
-	struct thread_info *thread = current_thread_info();
 	siginfo_t info;
 
 	if ((no >> 16) != (__ARM_NR_BASE>> 16))
@@ -630,21 +631,7 @@ asmlinkage int arm_syscall(int no, struc
 		return regs->ARM_r0;
 
 	case NR(set_tls):
-		thread->tp_value[0] = regs->ARM_r0;
-		if (tls_emu)
-			return 0;
-		if (has_tls_reg) {
-			asm ("mcr p15, 0, %0, c13, c0, 3"
-				: : "r" (regs->ARM_r0));
-		} else {
-			/*
-			 * User space must never try to access this directly.
-			 * Expect your app to break eventually if you do so.
-			 * The user helper at 0xffff0fe0 must be used instead.
-			 * (see entry-armv.S for details)
-			 */
-			*((unsigned int *)0xffff0ff0) = regs->ARM_r0;
-		}
+		set_tls(regs->ARM_r0);
 		return 0;
 
 #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
@@ -719,7 +706,7 @@ asmlinkage int arm_syscall(int no, struc
 		dump_instr("", regs);
 		if (user_mode(regs)) {
 			__show_regs(regs);
-			c_backtrace(regs->ARM_fp, processor_mode(regs));
+			c_backtrace(frame_pointer(regs), processor_mode(regs));
 		}
 	}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/unwind.c linux-libre-3.17-rc7-gnu/arch/arm/kernel/unwind.c
--- linux-libre-3.16-gnu/arch/arm/kernel/unwind.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/unwind.c	2014-09-28 17:29:07.000000000 -0400
@@ -479,12 +479,10 @@ void unwind_backtrace(struct pt_regs *re
 		tsk = current;
 
 	if (regs) {
-		frame.fp = regs->ARM_fp;
-		frame.sp = regs->ARM_sp;
-		frame.lr = regs->ARM_lr;
+		arm_get_current_stackframe(regs, &frame);
 		/* PC might be corrupted, use LR in that case. */
-		frame.pc = kernel_text_address(regs->ARM_pc)
-			 ? regs->ARM_pc : regs->ARM_lr;
+		if (!kernel_text_address(regs->ARM_pc))
+			frame.pc = regs->ARM_lr;
 	} else if (tsk == current) {
 		frame.fp = (unsigned long)__builtin_frame_address(0);
 		frame.sp = current_sp;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kernel/vmlinux.lds.S linux-libre-3.17-rc7-gnu/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-3.16-gnu/arch/arm/kernel/vmlinux.lds.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kernel/vmlinux.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -318,7 +318,6 @@ SECTIONS
 	_end = .;
 
 	STABS_DEBUG
-	.comment 0 : { *(.comment) }
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/arm.c linux-libre-3.17-rc7-gnu/arch/arm/kvm/arm.c
--- linux-libre-3.16-gnu/arch/arm/kvm/arm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/arm.c	2014-09-28 17:29:07.000000000 -0400
@@ -155,16 +155,6 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu
 	return VM_FAULT_SIGBUS;
 }
 
-void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
-			   struct kvm_memory_slot *dont)
-{
-}
-
-int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
-			    unsigned long npages)
-{
-	return 0;
-}
 
 /**
  * kvm_arch_destroy_vm - destroy the VM data structure
@@ -184,7 +174,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm
 	}
 }
 
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 	int r;
 	switch (ext) {
@@ -225,33 +215,6 @@ long kvm_arch_dev_ioctl(struct file *fil
 	return -EINVAL;
 }
 
-void kvm_arch_memslots_updated(struct kvm *kvm)
-{
-}
-
-int kvm_arch_prepare_memory_region(struct kvm *kvm,
-				   struct kvm_memory_slot *memslot,
-				   struct kvm_userspace_memory_region *mem,
-				   enum kvm_mr_change change)
-{
-	return 0;
-}
-
-void kvm_arch_commit_memory_region(struct kvm *kvm,
-				   struct kvm_userspace_memory_region *mem,
-				   const struct kvm_memory_slot *old,
-				   enum kvm_mr_change change)
-{
-}
-
-void kvm_arch_flush_shadow_all(struct kvm *kvm)
-{
-}
-
-void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
-				   struct kvm_memory_slot *slot)
-{
-}
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/coproc.c linux-libre-3.17-rc7-gnu/arch/arm/kvm/coproc.c
--- linux-libre-3.16-gnu/arch/arm/kvm/coproc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/coproc.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,31 @@ static u32 cache_levels;
 /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
 #define CSSELR_MAX 12
 
+/*
+ * kvm_vcpu_arch.cp15 holds cp15 registers as an array of u32, but some
+ * of cp15 registers can be viewed either as couple of two u32 registers
+ * or one u64 register. Current u64 register encoding is that least
+ * significant u32 word is followed by most significant u32 word.
+ */
+static inline void vcpu_cp15_reg64_set(struct kvm_vcpu *vcpu,
+				       const struct coproc_reg *r,
+				       u64 val)
+{
+	vcpu->arch.cp15[r->reg] = val & 0xffffffff;
+	vcpu->arch.cp15[r->reg + 1] = val >> 32;
+}
+
+static inline u64 vcpu_cp15_reg64_get(struct kvm_vcpu *vcpu,
+				      const struct coproc_reg *r)
+{
+	u64 val;
+
+	val = vcpu->arch.cp15[r->reg + 1];
+	val = val << 32;
+	val = val | vcpu->arch.cp15[r->reg];
+	return val;
+}
+
 int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	kvm_inject_undefined(vcpu);
@@ -682,17 +707,23 @@ static struct coproc_reg invariant_cp15[
 	{ CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
 };
 
+/*
+ * Reads a register value from a userspace address to a kernel
+ * variable. Make sure that register size matches sizeof(*__val).
+ */
 static int reg_from_user(void *val, const void __user *uaddr, u64 id)
 {
-	/* This Just Works because we are little endian. */
 	if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
 		return -EFAULT;
 	return 0;
 }
 
+/*
+ * Writes a register value to a userspace address from a kernel variable.
+ * Make sure that register size matches sizeof(*__val).
+ */
 static int reg_to_user(void __user *uaddr, const void *val, u64 id)
 {
-	/* This Just Works because we are little endian. */
 	if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
 		return -EFAULT;
 	return 0;
@@ -702,6 +733,7 @@ static int get_invariant_cp15(u64 id, vo
 {
 	struct coproc_params params;
 	const struct coproc_reg *r;
+	int ret;
 
 	if (!index_to_params(id, &params))
 		return -ENOENT;
@@ -710,7 +742,15 @@ static int get_invariant_cp15(u64 id, vo
 	if (!r)
 		return -ENOENT;
 
-	return reg_to_user(uaddr, &r->val, id);
+	ret = -ENOENT;
+	if (KVM_REG_SIZE(id) == 4) {
+		u32 val = r->val;
+
+		ret = reg_to_user(uaddr, &val, id);
+	} else if (KVM_REG_SIZE(id) == 8) {
+		ret = reg_to_user(uaddr, &r->val, id);
+	}
+	return ret;
 }
 
 static int set_invariant_cp15(u64 id, void __user *uaddr)
@@ -718,7 +758,7 @@ static int set_invariant_cp15(u64 id, vo
 	struct coproc_params params;
 	const struct coproc_reg *r;
 	int err;
-	u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
+	u64 val;
 
 	if (!index_to_params(id, &params))
 		return -ENOENT;
@@ -726,7 +766,16 @@ static int set_invariant_cp15(u64 id, vo
 	if (!r)
 		return -ENOENT;
 
-	err = reg_from_user(&val, uaddr, id);
+	err = -ENOENT;
+	if (KVM_REG_SIZE(id) == 4) {
+		u32 val32;
+
+		err = reg_from_user(&val32, uaddr, id);
+		if (!err)
+			val = val32;
+	} else if (KVM_REG_SIZE(id) == 8) {
+		err = reg_from_user(&val, uaddr, id);
+	}
 	if (err)
 		return err;
 
@@ -1004,6 +1053,7 @@ int kvm_arm_coproc_get_reg(struct kvm_vc
 {
 	const struct coproc_reg *r;
 	void __user *uaddr = (void __user *)(long)reg->addr;
+	int ret;
 
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
 		return demux_c15_get(reg->id, uaddr);
@@ -1015,14 +1065,24 @@ int kvm_arm_coproc_get_reg(struct kvm_vc
 	if (!r)
 		return get_invariant_cp15(reg->id, uaddr);
 
-	/* Note: copies two regs if size is 64 bit. */
-	return reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+	ret = -ENOENT;
+	if (KVM_REG_SIZE(reg->id) == 8) {
+		u64 val;
+
+		val = vcpu_cp15_reg64_get(vcpu, r);
+		ret = reg_to_user(uaddr, &val, reg->id);
+	} else if (KVM_REG_SIZE(reg->id) == 4) {
+		ret = reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+	}
+
+	return ret;
 }
 
 int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
 	const struct coproc_reg *r;
 	void __user *uaddr = (void __user *)(long)reg->addr;
+	int ret;
 
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
 		return demux_c15_set(reg->id, uaddr);
@@ -1034,8 +1094,18 @@ int kvm_arm_coproc_set_reg(struct kvm_vc
 	if (!r)
 		return set_invariant_cp15(reg->id, uaddr);
 
-	/* Note: copies two regs if size is 64 bit */
-	return reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+	ret = -ENOENT;
+	if (KVM_REG_SIZE(reg->id) == 8) {
+		u64 val;
+
+		ret = reg_from_user(&val, uaddr, reg->id);
+		if (!ret)
+			vcpu_cp15_reg64_set(vcpu, r, val);
+	} else if (KVM_REG_SIZE(reg->id) == 4) {
+		ret = reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+	}
+
+	return ret;
 }
 
 static unsigned int num_demux_regs(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/guest.c linux-libre-3.17-rc7-gnu/arch/arm/kvm/guest.c
--- linux-libre-3.16-gnu/arch/arm/kvm/guest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/guest.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,16 +124,6 @@ static bool is_timer_reg(u64 index)
 	return false;
 }
 
-int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
-{
-	return 0;
-}
-
-u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
-{
-	return 0;
-}
-
 #else
 
 #define NUM_TIMER_REGS 3
@@ -274,13 +264,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 
 int __attribute_const__ kvm_target_cpu(void)
 {
-	unsigned long implementor = read_cpuid_implementor();
-	unsigned long part_number = read_cpuid_part_number();
-
-	if (implementor != ARM_CPU_IMP_ARM)
-		return -EINVAL;
-
-	switch (part_number) {
+	switch (read_cpuid_part()) {
 	case ARM_CPU_PART_CORTEX_A7:
 		return KVM_ARM_TARGET_CORTEX_A7;
 	case ARM_CPU_PART_CORTEX_A15:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/handle_exit.c linux-libre-3.17-rc7-gnu/arch/arm/kvm/handle_exit.c
--- linux-libre-3.16-gnu/arch/arm/kvm/handle_exit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/handle_exit.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,6 +93,8 @@ static int kvm_handle_wfx(struct kvm_vcp
 	else
 		kvm_vcpu_block(vcpu);
 
+	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+
 	return 1;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/init.S linux-libre-3.17-rc7-gnu/arch/arm/kvm/init.S
--- linux-libre-3.16-gnu/arch/arm/kvm/init.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/init.S	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/unified.h>
 #include <asm/asm-offsets.h>
 #include <asm/kvm_asm.h>
@@ -71,7 +72,7 @@ __do_hyp_init:
 	bne	phase2			@ Yes, second stage init
 
 	@ Set the HTTBR to point to the hypervisor PGD pointer passed
-	mcrr	p15, 4, r2, r3, c2
+	mcrr	p15, 4, rr_lo_hi(r2, r3), c2
 
 	@ Set the HTCR and VTCR to the same shareability and cacheability
 	@ settings as the non-secure TTBCR and with T0SZ == 0.
@@ -98,6 +99,10 @@ __do_hyp_init:
 	mrc	p15, 0, r0, c10, c2, 1
 	mcr	p15, 4, r0, c10, c2, 1
 
+	@ Invalidate the stale TLBs from Bootloader
+	mcr	p15, 4, r0, c8, c7, 0	@ TLBIALLH
+	dsb	ish
+
 	@ Set the HSCTLR to:
 	@  - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
 	@  - Endianness: Kernel config
@@ -134,10 +139,10 @@ phase2:
 	ldr	r0, =TRAMPOLINE_VA
 	adr	r1, target
 	bfi	r0, r1, #0, #PAGE_SHIFT
-	mov	pc, r0
+	ret	r0
 
 target:	@ We're now in the trampoline code, switch page tables
-	mcrr	p15, 4, r2, r3, c2
+	mcrr	p15, 4, rr_lo_hi(r2, r3), c2
 	isb
 
 	@ Invalidate the old TLBs
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/interrupts_head.S linux-libre-3.17-rc7-gnu/arch/arm/kvm/interrupts_head.S
--- linux-libre-3.16-gnu/arch/arm/kvm/interrupts_head.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/interrupts_head.S	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,5 @@
 #include <linux/irqchip/arm-gic.h>
+#include <asm/assembler.h>
 
 #define VCPU_USR_REG(_reg_nr)	(VCPU_USR_REGS + (_reg_nr * 4))
 #define VCPU_USR_SP		(VCPU_USR_REG(13))
@@ -420,15 +421,23 @@ vcpu	.req	r0		@ vcpu pointer always in r
 	ldr	r8, [r2, #GICH_ELRSR0]
 	ldr	r9, [r2, #GICH_ELRSR1]
 	ldr	r10, [r2, #GICH_APR]
+ARM_BE8(rev	r3, r3	)
+ARM_BE8(rev	r4, r4	)
+ARM_BE8(rev	r5, r5	)
+ARM_BE8(rev	r6, r6	)
+ARM_BE8(rev	r7, r7	)
+ARM_BE8(rev	r8, r8	)
+ARM_BE8(rev	r9, r9	)
+ARM_BE8(rev	r10, r10	)
 
-	str	r3, [r11, #VGIC_CPU_HCR]
-	str	r4, [r11, #VGIC_CPU_VMCR]
-	str	r5, [r11, #VGIC_CPU_MISR]
-	str	r6, [r11, #VGIC_CPU_EISR]
-	str	r7, [r11, #(VGIC_CPU_EISR + 4)]
-	str	r8, [r11, #VGIC_CPU_ELRSR]
-	str	r9, [r11, #(VGIC_CPU_ELRSR + 4)]
-	str	r10, [r11, #VGIC_CPU_APR]
+	str	r3, [r11, #VGIC_V2_CPU_HCR]
+	str	r4, [r11, #VGIC_V2_CPU_VMCR]
+	str	r5, [r11, #VGIC_V2_CPU_MISR]
+	str	r6, [r11, #VGIC_V2_CPU_EISR]
+	str	r7, [r11, #(VGIC_V2_CPU_EISR + 4)]
+	str	r8, [r11, #VGIC_V2_CPU_ELRSR]
+	str	r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
+	str	r10, [r11, #VGIC_V2_CPU_APR]
 
 	/* Clear GICH_HCR */
 	mov	r5, #0
@@ -436,9 +445,10 @@ vcpu	.req	r0		@ vcpu pointer always in r
 
 	/* Save list registers */
 	add	r2, r2, #GICH_LR0
-	add	r3, r11, #VGIC_CPU_LR
+	add	r3, r11, #VGIC_V2_CPU_LR
 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
 1:	ldr	r6, [r2], #4
+ARM_BE8(rev	r6, r6	)
 	str	r6, [r3], #4
 	subs	r4, r4, #1
 	bne	1b
@@ -463,9 +473,12 @@ vcpu	.req	r0		@ vcpu pointer always in r
 	add	r11, vcpu, #VCPU_VGIC_CPU
 
 	/* We only restore a minimal set of registers */
-	ldr	r3, [r11, #VGIC_CPU_HCR]
-	ldr	r4, [r11, #VGIC_CPU_VMCR]
-	ldr	r8, [r11, #VGIC_CPU_APR]
+	ldr	r3, [r11, #VGIC_V2_CPU_HCR]
+	ldr	r4, [r11, #VGIC_V2_CPU_VMCR]
+	ldr	r8, [r11, #VGIC_V2_CPU_APR]
+ARM_BE8(rev	r3, r3	)
+ARM_BE8(rev	r4, r4	)
+ARM_BE8(rev	r8, r8	)
 
 	str	r3, [r2, #GICH_HCR]
 	str	r4, [r2, #GICH_VMCR]
@@ -473,9 +486,10 @@ vcpu	.req	r0		@ vcpu pointer always in r
 
 	/* Restore list registers */
 	add	r2, r2, #GICH_LR0
-	add	r3, r11, #VGIC_CPU_LR
+	add	r3, r11, #VGIC_V2_CPU_LR
 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
 1:	ldr	r6, [r3], #4
+ARM_BE8(rev	r6, r6  )
 	str	r6, [r2], #4
 	subs	r4, r4, #1
 	bne	1b
@@ -506,7 +520,7 @@ vcpu	.req	r0		@ vcpu pointer always in r
 	mcr	p15, 0, r2, c14, c3, 1	@ CNTV_CTL
 	isb
 
-	mrrc	p15, 3, r2, r3, c14	@ CNTV_CVAL
+	mrrc	p15, 3, rr_lo_hi(r2, r3), c14	@ CNTV_CVAL
 	ldr	r4, =VCPU_TIMER_CNTV_CVAL
 	add	r5, vcpu, r4
 	strd	r2, r3, [r5]
@@ -546,12 +560,12 @@ vcpu	.req	r0		@ vcpu pointer always in r
 
 	ldr	r2, [r4, #KVM_TIMER_CNTVOFF]
 	ldr	r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
-	mcrr	p15, 4, r2, r3, c14	@ CNTVOFF
+	mcrr	p15, 4, rr_lo_hi(r2, r3), c14	@ CNTVOFF
 
 	ldr	r4, =VCPU_TIMER_CNTV_CVAL
 	add	r5, vcpu, r4
 	ldrd	r2, r3, [r5]
-	mcrr	p15, 3, r2, r3, c14	@ CNTV_CVAL
+	mcrr	p15, 3, rr_lo_hi(r2, r3), c14	@ CNTV_CVAL
 	isb
 
 	ldr	r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/interrupts.S linux-libre-3.17-rc7-gnu/arch/arm/kvm/interrupts.S
--- linux-libre-3.16-gnu/arch/arm/kvm/interrupts.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/interrupts.S	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
 	dsb	ishst
 	add	r0, r0, #KVM_VTTBR
 	ldrd	r2, r3, [r0]
-	mcrr	p15, 6, r2, r3, c2	@ Write VTTBR
+	mcrr	p15, 6, rr_lo_hi(r2, r3), c2	@ Write VTTBR
 	isb
 	mcr     p15, 0, r0, c8, c3, 0	@ TLBIALLIS (rt ignored)
 	dsb	ish
@@ -135,7 +135,7 @@ ENTRY(__kvm_vcpu_run)
 	ldr	r1, [vcpu, #VCPU_KVM]
 	add	r1, r1, #KVM_VTTBR
 	ldrd	r2, r3, [r1]
-	mcrr	p15, 6, r2, r3, c2	@ Write VTTBR
+	mcrr	p15, 6, rr_lo_hi(r2, r3), c2	@ Write VTTBR
 
 	@ We're all done, just restore the GPRs and go to the guest
 	restore_guest_regs
@@ -199,8 +199,13 @@ after_vfp_restore:
 
 	restore_host_regs
 	clrex				@ Clear exclusive monitor
+#ifndef CONFIG_CPU_ENDIAN_BE8
 	mov	r0, r1			@ Return the return code
 	mov	r1, #0			@ Clear upper bits in return value
+#else
+	@ r1 already has return code
+	mov	r0, #0			@ Clear upper bits in return value
+#endif /* CONFIG_CPU_ENDIAN_BE8 */
 	bx	lr			@ return to IOCTL
 
 /********************************************************************
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/kvm/Kconfig
--- linux-libre-3.16-gnu/arch/arm/kvm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@ config KVM
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select KVM_MMIO
 	select KVM_ARM_HOST
-	depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
+	depends on ARM_VIRT_EXT && ARM_LPAE
 	---help---
 	  Support hosting virtualized guest machines. You will also
 	  need to select one or more of the processor modules below.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/Makefile linux-libre-3.17-rc7-gnu/arch/arm/kvm/Makefile
--- linux-libre-3.16-gnu/arch/arm/kvm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -21,4 +21,5 @@ obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
 obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
+obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
 obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/kvm/mmu.c linux-libre-3.17-rc7-gnu/arch/arm/kvm/mmu.c
--- linux-libre-3.16-gnu/arch/arm/kvm/mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/kvm/mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,104 +90,115 @@ static void *mmu_memory_cache_alloc(stru
 	return p;
 }
 
-static bool page_empty(void *ptr)
+static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
 {
-	struct page *ptr_page = virt_to_page(ptr);
-	return page_count(ptr_page) == 1;
+	pud_t *pud_table __maybe_unused = pud_offset(pgd, 0);
+	pgd_clear(pgd);
+	kvm_tlb_flush_vmid_ipa(kvm, addr);
+	pud_free(NULL, pud_table);
+	put_page(virt_to_page(pgd));
 }
 
 static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
-	if (pud_huge(*pud)) {
-		pud_clear(pud);
-		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	} else {
-		pmd_t *pmd_table = pmd_offset(pud, 0);
-		pud_clear(pud);
-		kvm_tlb_flush_vmid_ipa(kvm, addr);
-		pmd_free(NULL, pmd_table);
-	}
+	pmd_t *pmd_table = pmd_offset(pud, 0);
+	VM_BUG_ON(pud_huge(*pud));
+	pud_clear(pud);
+	kvm_tlb_flush_vmid_ipa(kvm, addr);
+	pmd_free(NULL, pmd_table);
 	put_page(virt_to_page(pud));
 }
 
 static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 {
-	if (kvm_pmd_huge(*pmd)) {
-		pmd_clear(pmd);
-		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	} else {
-		pte_t *pte_table = pte_offset_kernel(pmd, 0);
-		pmd_clear(pmd);
-		kvm_tlb_flush_vmid_ipa(kvm, addr);
-		pte_free_kernel(NULL, pte_table);
-	}
+	pte_t *pte_table = pte_offset_kernel(pmd, 0);
+	VM_BUG_ON(kvm_pmd_huge(*pmd));
+	pmd_clear(pmd);
+	kvm_tlb_flush_vmid_ipa(kvm, addr);
+	pte_free_kernel(NULL, pte_table);
 	put_page(virt_to_page(pmd));
 }
 
-static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
+static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
+		       phys_addr_t addr, phys_addr_t end)
 {
-	if (pte_present(*pte)) {
-		kvm_set_pte(pte, __pte(0));
-		put_page(virt_to_page(pte));
-		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	}
+	phys_addr_t start_addr = addr;
+	pte_t *pte, *start_pte;
+
+	start_pte = pte = pte_offset_kernel(pmd, addr);
+	do {
+		if (!pte_none(*pte)) {
+			kvm_set_pte(pte, __pte(0));
+			put_page(virt_to_page(pte));
+			kvm_tlb_flush_vmid_ipa(kvm, addr);
+		}
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+
+	if (kvm_pte_table_empty(start_pte))
+		clear_pmd_entry(kvm, pmd, start_addr);
 }
 
-static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
-			unsigned long long start, u64 size)
+static void unmap_pmds(struct kvm *kvm, pud_t *pud,
+		       phys_addr_t addr, phys_addr_t end)
 {
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long long addr = start, end = start + size;
-	u64 next;
-
-	while (addr < end) {
-		pgd = pgdp + pgd_index(addr);
-		pud = pud_offset(pgd, addr);
-		pte = NULL;
-		if (pud_none(*pud)) {
-			addr = kvm_pud_addr_end(addr, end);
-			continue;
-		}
+	phys_addr_t next, start_addr = addr;
+	pmd_t *pmd, *start_pmd;
 
-		if (pud_huge(*pud)) {
-			/*
-			 * If we are dealing with a huge pud, just clear it and
-			 * move on.
-			 */
-			clear_pud_entry(kvm, pud, addr);
-			addr = kvm_pud_addr_end(addr, end);
-			continue;
+	start_pmd = pmd = pmd_offset(pud, addr);
+	do {
+		next = kvm_pmd_addr_end(addr, end);
+		if (!pmd_none(*pmd)) {
+			if (kvm_pmd_huge(*pmd)) {
+				pmd_clear(pmd);
+				kvm_tlb_flush_vmid_ipa(kvm, addr);
+				put_page(virt_to_page(pmd));
+			} else {
+				unmap_ptes(kvm, pmd, addr, next);
+			}
 		}
+	} while (pmd++, addr = next, addr != end);
 
-		pmd = pmd_offset(pud, addr);
-		if (pmd_none(*pmd)) {
-			addr = kvm_pmd_addr_end(addr, end);
-			continue;
-		}
+	if (kvm_pmd_table_empty(start_pmd))
+		clear_pud_entry(kvm, pud, start_addr);
+}
 
-		if (!kvm_pmd_huge(*pmd)) {
-			pte = pte_offset_kernel(pmd, addr);
-			clear_pte_entry(kvm, pte, addr);
-			next = addr + PAGE_SIZE;
-		}
+static void unmap_puds(struct kvm *kvm, pgd_t *pgd,
+		       phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t next, start_addr = addr;
+	pud_t *pud, *start_pud;
 
-		/*
-		 * If the pmd entry is to be cleared, walk back up the ladder
-		 */
-		if (kvm_pmd_huge(*pmd) || (pte && page_empty(pte))) {
-			clear_pmd_entry(kvm, pmd, addr);
-			next = kvm_pmd_addr_end(addr, end);
-			if (page_empty(pmd) && !page_empty(pud)) {
-				clear_pud_entry(kvm, pud, addr);
-				next = kvm_pud_addr_end(addr, end);
+	start_pud = pud = pud_offset(pgd, addr);
+	do {
+		next = kvm_pud_addr_end(addr, end);
+		if (!pud_none(*pud)) {
+			if (pud_huge(*pud)) {
+				pud_clear(pud);
+				kvm_tlb_flush_vmid_ipa(kvm, addr);
+				put_page(virt_to_page(pud));
+			} else {
+				unmap_pmds(kvm, pud, addr, next);
 			}
 		}
+	} while (pud++, addr = next, addr != end);
 
-		addr = next;
-	}
+	if (kvm_pud_table_empty(start_pud))
+		clear_pgd_entry(kvm, pgd, start_addr);
+}
+
+
+static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
+			phys_addr_t start, u64 size)
+{
+	pgd_t *pgd;
+	phys_addr_t addr = start, end = start + size;
+	phys_addr_t next;
+
+	pgd = pgdp + pgd_index(addr);
+	do {
+		next = kvm_pgd_addr_end(addr, end);
+		unmap_puds(kvm, pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
 }
 
 static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
@@ -748,6 +759,7 @@ static int user_mem_abort(struct kvm_vcp
 	struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
 	struct vm_area_struct *vma;
 	pfn_t pfn;
+	pgprot_t mem_type = PAGE_S2;
 
 	write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu));
 	if (fault_status == FSC_PERM && !write_fault) {
@@ -798,6 +810,9 @@ static int user_mem_abort(struct kvm_vcp
 	if (is_error_pfn(pfn))
 		return -EFAULT;
 
+	if (kvm_is_mmio_pfn(pfn))
+		mem_type = PAGE_S2_DEVICE;
+
 	spin_lock(&kvm->mmu_lock);
 	if (mmu_notifier_retry(kvm, mmu_seq))
 		goto out_unlock;
@@ -805,7 +820,7 @@ static int user_mem_abort(struct kvm_vcp
 		hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
 
 	if (hugetlb) {
-		pmd_t new_pmd = pfn_pmd(pfn, PAGE_S2);
+		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
 		new_pmd = pmd_mkhuge(new_pmd);
 		if (writable) {
 			kvm_set_s2pmd_writable(&new_pmd);
@@ -814,13 +829,14 @@ static int user_mem_abort(struct kvm_vcp
 		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE);
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
 	} else {
-		pte_t new_pte = pfn_pte(pfn, PAGE_S2);
+		pte_t new_pte = pfn_pte(pfn, mem_type);
 		if (writable) {
 			kvm_set_s2pte_writable(&new_pte);
 			kvm_set_pfn_dirty(pfn);
 		}
 		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE);
-		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false);
+		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte,
+				     mem_type == PAGE_S2_DEVICE);
 	}
 
 
@@ -1100,3 +1116,49 @@ out:
 	free_hyp_pgds();
 	return err;
 }
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				   struct kvm_userspace_memory_region *mem,
+				   const struct kvm_memory_slot *old,
+				   enum kvm_mr_change change)
+{
+	gpa_t gpa = old->base_gfn << PAGE_SHIFT;
+	phys_addr_t size = old->npages << PAGE_SHIFT;
+	if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) {
+		spin_lock(&kvm->mmu_lock);
+		unmap_stage2_range(kvm, gpa, size);
+		spin_unlock(&kvm->mmu_lock);
+	}
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				   struct kvm_memory_slot *memslot,
+				   struct kvm_userspace_memory_region *mem,
+				   enum kvm_mr_change change)
+{
+	return 0;
+}
+
+void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
+			   struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
+			    unsigned long npages)
+{
+	return 0;
+}
+
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
+{
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/ashldi3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/ashldi3.S
--- linux-libre-3.16-gnu/arch/arm/lib/ashldi3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/ashldi3.S	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.  */
 
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #ifdef __ARMEB__
 #define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_llsl)
  THUMB(	lsrmi	r3, al, ip		)
  THUMB(	orrmi	ah, ah, r3		)
 	mov	al, al, lsl r2
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__ashldi3)
 ENDPROC(__aeabi_llsl)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/ashrdi3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/ashrdi3.S
--- linux-libre-3.16-gnu/arch/arm/lib/ashrdi3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/ashrdi3.S	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.  */
 
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #ifdef __ARMEB__
 #define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_lasr)
  THUMB(	lslmi	r3, ah, ip		)
  THUMB(	orrmi	al, al, r3		)
 	mov	ah, ah, asr r2
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__ashrdi3)
 ENDPROC(__aeabi_lasr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/backtrace.S linux-libre-3.17-rc7-gnu/arch/arm/lib/backtrace.S
--- linux-libre-3.16-gnu/arch/arm/lib/backtrace.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/backtrace.S	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 ENTRY(c_backtrace)
 
 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
-		mov	pc, lr
+		ret	lr
 ENDPROC(c_backtrace)
 #else
 		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/bitops.h linux-libre-3.17-rc7-gnu/arch/arm/lib/bitops.h
--- linux-libre-3.16-gnu/arch/arm/lib/bitops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/bitops.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,4 @@
+#include <asm/assembler.h>
 #include <asm/unwind.h>
 
 #if __LINUX_ARM_ARCH__ >= 6
@@ -70,7 +71,7 @@ UNWIND(	.fnstart	)
 	\instr	r2, r2, r3
 	str	r2, [r1, r0, lsl #2]
 	restore_irqs ip
-	mov	pc, lr
+	ret	lr
 UNWIND(	.fnend		)
 ENDPROC(\name		)
 	.endm
@@ -98,7 +99,7 @@ UNWIND(	.fnstart	)
 	\store	r2, [r1]
 	moveq	r0, #0
 	restore_irqs ip
-	mov	pc, lr
+	ret	lr
 UNWIND(	.fnend		)
 ENDPROC(\name		)
 	.endm
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/bswapsdi2.S linux-libre-3.17-rc7-gnu/arch/arm/lib/bswapsdi2.S
--- linux-libre-3.16-gnu/arch/arm/lib/bswapsdi2.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/bswapsdi2.S	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,5 @@
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #if __LINUX_ARM_ARCH__ >= 6
 ENTRY(__bswapsi2)
@@ -18,7 +19,7 @@ ENTRY(__bswapsi2)
 	mov r3, r3, lsr #8
 	bic r3, r3, #0xff00
 	eor r0, r3, r0, ror #8
-	mov pc, lr
+	ret lr
 ENDPROC(__bswapsi2)
 
 ENTRY(__bswapdi2)
@@ -31,6 +32,6 @@ ENTRY(__bswapdi2)
 	bic r1, r1, #0xff00
 	eor r1, r1, r0, ror #8
 	eor r0, r3, ip, ror #8
-	mov pc, lr
+	ret lr
 ENDPROC(__bswapdi2)
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/call_with_stack.S linux-libre-3.17-rc7-gnu/arch/arm/lib/call_with_stack.S
--- linux-libre-3.16-gnu/arch/arm/lib/call_with_stack.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/call_with_stack.S	2014-09-28 17:29:07.000000000 -0400
@@ -36,9 +36,9 @@ ENTRY(call_with_stack)
 	mov	r0, r1
 
 	adr	lr, BSYM(1f)
-	mov	pc, r2
+	ret	r2
 
 1:	ldr	lr, [sp]
 	ldr	sp, [sp, #4]
-	mov	pc, lr
+	ret	lr
 ENDPROC(call_with_stack)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/csumpartialcopygeneric.S linux-libre-3.17-rc7-gnu/arch/arm/lib/csumpartialcopygeneric.S
--- linux-libre-3.16-gnu/arch/arm/lib/csumpartialcopygeneric.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/csumpartialcopygeneric.S	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/assembler.h>
 
 /*
  * unsigned int
@@ -40,7 +41,7 @@ sum	.req	r3
 		adcs	sum, sum, ip, put_byte_1	@ update checksum
 		strb	ip, [dst], #1
 		tst	dst, #2
-		moveq	pc, lr			@ dst is now 32bit aligned
+		reteq	lr			@ dst is now 32bit aligned
 
 .Ldst_16bit:	load2b	r8, ip
 		sub	len, len, #2
@@ -48,7 +49,7 @@ sum	.req	r3
 		strb	r8, [dst], #1
 		adcs	sum, sum, ip, put_byte_1
 		strb	ip, [dst], #1
-		mov	pc, lr			@ dst is now 32bit aligned
+		ret	lr			@ dst is now 32bit aligned
 
 		/*
 		 * Handle 0 to 7 bytes, with any alignment of source and
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/csumpartial.S linux-libre-3.17-rc7-gnu/arch/arm/lib/csumpartial.S
--- linux-libre-3.16-gnu/arch/arm/lib/csumpartial.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/csumpartial.S	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ td3	.req	lr
 #endif
 #endif
 		adcnes	sum, sum, td0		@ update checksum
-		mov	pc, lr
+		ret	lr
 
 ENTRY(csum_partial)
 		stmfd	sp!, {buf, lr}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/delay.c linux-libre-3.17-rc7-gnu/arch/arm/lib/delay.c
--- linux-libre-3.16-gnu/arch/arm/lib/delay.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/delay.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  * Author: Will Deacon <will.deacon@arm.com>
  */
 
+#include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -36,6 +37,7 @@ struct arm_delay_ops arm_delay_ops = {
 
 static const struct delay_timer *delay_timer;
 static bool delay_calibrated;
+static u64 delay_res;
 
 int read_current_timer(unsigned long *timer_val)
 {
@@ -47,6 +49,11 @@ int read_current_timer(unsigned long *ti
 }
 EXPORT_SYMBOL_GPL(read_current_timer);
 
+static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+{
+	return (cyc * mult) >> shift;
+}
+
 static void __timer_delay(unsigned long cycles)
 {
 	cycles_t start = get_cycles();
@@ -69,18 +76,24 @@ static void __timer_udelay(unsigned long
 
 void __init register_current_timer_delay(const struct delay_timer *timer)
 {
-	if (!delay_calibrated) {
-		pr_info("Switching to timer-based delay loop\n");
+	u32 new_mult, new_shift;
+	u64 res;
+
+	clocks_calc_mult_shift(&new_mult, &new_shift, timer->freq,
+			       NSEC_PER_SEC, 3600);
+	res = cyc_to_ns(1ULL, new_mult, new_shift);
+
+	if (!delay_calibrated && (!delay_res || (res < delay_res))) {
+		pr_info("Switching to timer-based delay loop, resolution %lluns\n", res);
 		delay_timer			= timer;
 		lpj_fine			= timer->freq / HZ;
+		delay_res			= res;
 
 		/* cpufreq may scale loops_per_jiffy, so keep a private copy */
 		arm_delay_ops.ticks_per_jiffy	= lpj_fine;
 		arm_delay_ops.delay		= __timer_delay;
 		arm_delay_ops.const_udelay	= __timer_const_udelay;
 		arm_delay_ops.udelay		= __timer_udelay;
-
-		delay_calibrated		= true;
 	} else {
 		pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
 	}
@@ -91,3 +104,8 @@ unsigned long calibrate_delay_is_known(v
 	delay_calibrated = true;
 	return lpj_fine;
 }
+
+void calibration_delay_done(void)
+{
+	delay_calibrated = true;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/delay-loop.S linux-libre-3.17-rc7-gnu/arch/arm/lib/delay-loop.S
--- linux-libre-3.16-gnu/arch/arm/lib/delay-loop.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/delay-loop.S	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@ ENTRY(__loop_const_udelay)			@ 0 <= r0 <
 		mul	r0, r2, r0		@ max = 2^32-1
 		add	r0, r0, r1, lsr #32-6
 		movs	r0, r0, lsr #6
-		moveq	pc, lr
+		reteq	lr
 
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
@@ -46,23 +46,23 @@ ENTRY(__loop_const_udelay)			@ 0 <= r0 <
 ENTRY(__loop_delay)
 		subs	r0, r0, #1
 #if 0
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
-		movls	pc, lr
+		retls	lr
 		subs	r0, r0, #1
 #endif
 		bhi	__loop_delay
-		mov	pc, lr
+		ret	lr
 ENDPROC(__loop_udelay)
 ENDPROC(__loop_const_udelay)
 ENDPROC(__loop_delay)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/div64.S linux-libre-3.17-rc7-gnu/arch/arm/lib/div64.S
--- linux-libre-3.16-gnu/arch/arm/lib/div64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/div64.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/unwind.h>
 
 #ifdef __ARMEB__
@@ -97,7 +98,7 @@ UNWIND(.fnstart)
 	mov	yl, #0
 	cmpeq	xl, r4
 	movlo	xh, xl
-	movlo	pc, lr
+	retlo	lr
 
 	@ The division loop for lower bit positions.
 	@ Here we shift remainer bits leftwards rather than moving the
@@ -111,14 +112,14 @@ UNWIND(.fnstart)
 	subcs	xh, xh, r4
 	movs	ip, ip, lsr #1
 	bne	4b
-	mov	pc, lr
+	ret	lr
 
 	@ The top part of remainder became zero.  If carry is set
 	@ (the 33th bit) this is a false positive so resume the loop.
 	@ Otherwise, if lower part is also null then we are done.
 6:	bcs	5b
 	cmp	xl, #0
-	moveq	pc, lr
+	reteq	lr
 
 	@ We still have remainer bits in the low part.  Bring them up.
 
@@ -144,7 +145,7 @@ UNWIND(.fnstart)
 	movs	ip, ip, lsr #1
 	mov	xh, #1
 	bne	4b
-	mov	pc, lr
+	ret	lr
 
 8:	@ Division by a power of 2: determine what that divisor order is
 	@ then simply shift values around
@@ -184,13 +185,13 @@ UNWIND(.fnstart)
  THUMB(	orr	yl, yl, xh		)
 	mov	xh, xl, lsl ip
 	mov	xh, xh, lsr ip
-	mov	pc, lr
+	ret	lr
 
 	@ eq -> division by 1: obvious enough...
 9:	moveq	yl, xl
 	moveq	yh, xh
 	moveq	xh, #0
-	moveq	pc, lr
+	reteq	lr
 UNWIND(.fnend)
 
 UNWIND(.fnstart)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/findbit.S linux-libre-3.17-rc7-gnu/arch/arm/lib/findbit.S
--- linux-libre-3.16-gnu/arch/arm/lib/findbit.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/findbit.S	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@ ENTRY(_find_first_zero_bit_le)
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		mov	pc, lr
+		ret	lr
 ENDPROC(_find_first_zero_bit_le)
 
 /*
@@ -76,7 +76,7 @@ ENTRY(_find_first_bit_le)
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		mov	pc, lr
+		ret	lr
 ENDPROC(_find_first_bit_le)
 
 /*
@@ -114,7 +114,7 @@ ENTRY(_find_first_zero_bit_be)
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		mov	pc, lr
+		ret	lr
 ENDPROC(_find_first_zero_bit_be)
 
 ENTRY(_find_next_zero_bit_be)
@@ -148,7 +148,7 @@ ENTRY(_find_first_bit_be)
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		mov	pc, lr
+		ret	lr
 ENDPROC(_find_first_bit_be)
 
 ENTRY(_find_next_bit_be)
@@ -192,5 +192,5 @@ ENDPROC(_find_next_bit_be)
 #endif
 		cmp	r1, r0			@ Clamp to maxbit
 		movlo	r0, r1
-		mov	pc, lr
+		ret	lr
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/getuser.S linux-libre-3.17-rc7-gnu/arch/arm/lib/getuser.S
--- linux-libre-3.16-gnu/arch/arm/lib/getuser.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/getuser.S	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,7 @@
  * Inputs:	r0 contains the address
  *		r1 contains the address limit, which must be preserved
  * Outputs:	r0 is the error code
- *		r2 contains the zero-extended value
+ *		r2, r3 contains the zero-extended value
  *		lr corrupted
  *
  * No other registers must be altered.  (see <asm/uaccess.h>
@@ -36,7 +36,7 @@ ENTRY(__get_user_1)
 	check_uaccess r0, 1, r1, r2, __get_user_bad
 1: TUSER(ldrb)	r2, [r0]
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
@@ -56,25 +56,94 @@ rb	.req	r0
 	orr	r2, rb, r2, lsl #8
 #endif
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
 	check_uaccess r0, 4, r1, r2, __get_user_bad
 4: TUSER(ldr)	r2, [r0]
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__get_user_4)
 
+ENTRY(__get_user_8)
+	check_uaccess r0, 8, r1, r2, __get_user_bad
+#ifdef CONFIG_THUMB2_KERNEL
+5: TUSER(ldr)	r2, [r0]
+6: TUSER(ldr)	r3, [r0, #4]
+#else
+5: TUSER(ldr)	r2, [r0], #4
+6: TUSER(ldr)	r3, [r0]
+#endif
+	mov	r0, #0
+	ret	lr
+ENDPROC(__get_user_8)
+
+#ifdef __ARMEB__
+ENTRY(__get_user_32t_8)
+	check_uaccess r0, 8, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+	add	r0, r0, #4
+7:	ldrt	r2, [r0]
+#else
+7:	ldr	r2, [r0, #4]
+#endif
+	mov	r0, #0
+	ret	lr
+ENDPROC(__get_user_32t_8)
+
+ENTRY(__get_user_64t_1)
+	check_uaccess r0, 1, r1, r2, __get_user_bad8
+8: TUSER(ldrb)	r3, [r0]
+	mov	r0, #0
+	ret	lr
+ENDPROC(__get_user_64t_1)
+
+ENTRY(__get_user_64t_2)
+	check_uaccess r0, 2, r1, r2, __get_user_bad8
+#ifdef CONFIG_CPU_USE_DOMAINS
+rb	.req	ip
+9:	ldrbt	r3, [r0], #1
+10:	ldrbt	rb, [r0], #0
+#else
+rb	.req	r0
+9:	ldrb	r3, [r0]
+10:	ldrb	rb, [r0, #1]
+#endif
+	orr	r3, rb, r3, lsl #8
+	mov	r0, #0
+	ret	lr
+ENDPROC(__get_user_64t_2)
+
+ENTRY(__get_user_64t_4)
+	check_uaccess r0, 4, r1, r2, __get_user_bad8
+11: TUSER(ldr)	r3, [r0]
+	mov	r0, #0
+	ret	lr
+ENDPROC(__get_user_64t_4)
+#endif
+
+__get_user_bad8:
+	mov	r3, #0
 __get_user_bad:
 	mov	r2, #0
 	mov	r0, #-EFAULT
-	mov	pc, lr
+	ret	lr
 ENDPROC(__get_user_bad)
+ENDPROC(__get_user_bad8)
 
 .pushsection __ex_table, "a"
 	.long	1b, __get_user_bad
 	.long	2b, __get_user_bad
 	.long	3b, __get_user_bad
 	.long	4b, __get_user_bad
+	.long	5b, __get_user_bad8
+	.long	6b, __get_user_bad8
+#ifdef __ARMEB__
+	.long   7b, __get_user_bad
+	.long	8b, __get_user_bad8
+	.long	9b, __get_user_bad8
+	.long	10b, __get_user_bad8
+	.long	11b, __get_user_bad8
+#endif
 .popsection
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-readsb.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsb.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-readsb.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsb.S	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 
 ENTRY(__raw_readsb)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		ands	ip, r1, #3
 		bne	.Linsb_align
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-readsl.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsl.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-readsl.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsl.S	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,7 @@
 
 ENTRY(__raw_readsl)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		ands	ip, r1, #3
 		bne	3f
 
@@ -33,7 +33,7 @@ ENTRY(__raw_readsl)
 		stmcsia	r1!, {r3, ip}
 		ldrne	r3, [r0, #0]
 		strne	r3, [r1, #0]
-		mov	pc, lr
+		ret	lr
 
 3:		ldr	r3, [r0]
 		cmp	ip, #2
@@ -75,5 +75,5 @@ ENTRY(__raw_readsl)
 		strb	r3, [r1, #1]
 8:		mov	r3, ip, get_byte_0
 		strb	r3, [r1, #0]
-		mov	pc, lr
+		ret	lr
 ENDPROC(__raw_readsl)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-readsw-armv3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsw-armv3.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-readsw-armv3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsw-armv3.S	2014-09-28 17:29:07.000000000 -0400
@@ -27,11 +27,11 @@
 		strb	r3, [r1], #1
 
 		subs	r2, r2, #1
-		moveq	pc, lr
+		reteq	lr
 
 ENTRY(__raw_readsw)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		tst	r1, #3
 		bne	.Linsw_align
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-readsw-armv4.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsw-armv4.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-readsw-armv4.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-readsw-armv4.S	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 
 ENTRY(__raw_readsw)
 		teq	r2, #0
-		moveq	pc, lr
+		reteq	lr
 		tst	r1, #3
 		bne	.Linsw_align
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-writesb.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesb.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-writesb.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesb.S	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@
 
 ENTRY(__raw_writesb)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		ands	ip, r1, #3
 		bne	.Loutsb_align
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-writesl.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesl.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-writesl.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesl.S	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,7 @@
 
 ENTRY(__raw_writesl)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		ands	ip, r1, #3
 		bne	3f
 
@@ -33,7 +33,7 @@ ENTRY(__raw_writesl)
 		ldrne	r3, [r1, #0]
 		strcs	ip, [r0, #0]
 		strne	r3, [r0, #0]
-		mov	pc, lr
+		ret	lr
 
 3:		bic	r1, r1, #3
 		ldr	r3, [r1], #4
@@ -47,7 +47,7 @@ ENTRY(__raw_writesl)
 		orr	ip, ip, r3, lspush #16
 		str	ip, [r0]
 		bne	4b
-		mov	pc, lr
+		ret	lr
 
 5:		mov	ip, r3, lspull #8
 		ldr	r3, [r1], #4
@@ -55,7 +55,7 @@ ENTRY(__raw_writesl)
 		orr	ip, ip, r3, lspush #24
 		str	ip, [r0]
 		bne	5b
-		mov	pc, lr
+		ret	lr
 
 6:		mov	ip, r3, lspull #24
 		ldr	r3, [r1], #4
@@ -63,5 +63,5 @@ ENTRY(__raw_writesl)
 		orr	ip, ip, r3, lspush #8
 		str	ip, [r0]
 		bne	6b
-		mov	pc, lr
+		ret	lr
 ENDPROC(__raw_writesl)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-writesw-armv3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesw-armv3.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-writesw-armv3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesw-armv3.S	2014-09-28 17:29:07.000000000 -0400
@@ -28,11 +28,11 @@
 		orr	r3, r3, r3, lsl #16
 		str	r3, [r0]
 		subs	r2, r2, #1
-		moveq	pc, lr
+		reteq	lr
 
 ENTRY(__raw_writesw)
 		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
+		reteq	lr
 		tst	r1, #3
 		bne	.Loutsw_align
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/io-writesw-armv4.S linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesw-armv4.S
--- linux-libre-3.16-gnu/arch/arm/lib/io-writesw-armv4.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/io-writesw-armv4.S	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@
 
 ENTRY(__raw_writesw)
 		teq	r2, #0
-		moveq	pc, lr
+		reteq	lr
 		ands	r3, r1, #3
 		bne	.Loutsw_align
 
@@ -96,5 +96,5 @@ ENTRY(__raw_writesw)
 		tst	r2, #1
 3:		movne	ip, r3, lsr #8
 		strneh	ip, [r0]
-		mov	pc, lr
+		ret	lr
 ENDPROC(__raw_writesw)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/lib1funcs.S linux-libre-3.17-rc7-gnu/arch/arm/lib/lib1funcs.S
--- linux-libre-3.16-gnu/arch/arm/lib/lib1funcs.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/lib1funcs.S	2014-09-28 17:29:07.000000000 -0400
@@ -210,7 +210,7 @@ ENTRY(__aeabi_uidiv)
 UNWIND(.fnstart)
 
 	subs	r2, r1, #1
-	moveq	pc, lr
+	reteq	lr
 	bcc	Ldiv0
 	cmp	r0, r1
 	bls	11f
@@ -220,16 +220,16 @@ UNWIND(.fnstart)
 	ARM_DIV_BODY r0, r1, r2, r3
 
 	mov	r0, r2
-	mov	pc, lr
+	ret	lr
 
 11:	moveq	r0, #1
 	movne	r0, #0
-	mov	pc, lr
+	ret	lr
 
 12:	ARM_DIV2_ORDER r1, r2
 
 	mov	r0, r0, lsr r2
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__udivsi3)
@@ -244,11 +244,11 @@ UNWIND(.fnstart)
 	moveq   r0, #0
 	tsthi	r1, r2				@ see if divisor is power of 2
 	andeq	r0, r0, r2
-	movls	pc, lr
+	retls	lr
 
 	ARM_MOD_BODY r0, r1, r2, r3
 
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__umodsi3)
@@ -274,23 +274,23 @@ UNWIND(.fnstart)
 
 	cmp	ip, #0
 	rsbmi	r0, r0, #0
-	mov	pc, lr
+	ret	lr
 
 10:	teq	ip, r0				@ same sign ?
 	rsbmi	r0, r0, #0
-	mov	pc, lr
+	ret	lr
 
 11:	movlo	r0, #0
 	moveq	r0, ip, asr #31
 	orreq	r0, r0, #1
-	mov	pc, lr
+	ret	lr
 
 12:	ARM_DIV2_ORDER r1, r2
 
 	cmp	ip, #0
 	mov	r0, r3, lsr r2
 	rsbmi	r0, r0, #0
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__divsi3)
@@ -315,7 +315,7 @@ UNWIND(.fnstart)
 
 10:	cmp	ip, #0
 	rsbmi	r0, r0, #0
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__modsi3)
@@ -331,7 +331,7 @@ UNWIND(.save {r0, r1, ip, lr}	)
 	ldmfd	sp!, {r1, r2, ip, lr}
 	mul	r3, r0, r2
 	sub	r1, r1, r3
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__aeabi_uidivmod)
@@ -344,7 +344,7 @@ UNWIND(.save {r0, r1, ip, lr}	)
 	ldmfd	sp!, {r1, r2, ip, lr}
 	mul	r3, r0, r2
 	sub	r1, r1, r3
-	mov	pc, lr
+	ret	lr
 
 UNWIND(.fnend)
 ENDPROC(__aeabi_idivmod)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/lshrdi3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/lshrdi3.S
--- linux-libre-3.16-gnu/arch/arm/lib/lshrdi3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/lshrdi3.S	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA.  */
 
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #ifdef __ARMEB__
 #define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_llsr)
  THUMB(	lslmi	r3, ah, ip		)
  THUMB(	orrmi	al, al, r3		)
 	mov	ah, ah, lsr r2
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__lshrdi3)
 ENDPROC(__aeabi_llsr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/memchr.S linux-libre-3.17-rc7-gnu/arch/arm/lib/memchr.S
--- linux-libre-3.16-gnu/arch/arm/lib/memchr.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/memchr.S	2014-09-28 17:29:07.000000000 -0400
@@ -22,5 +22,5 @@ ENTRY(memchr)
 	bne	1b
 	sub	r0, r0, #1
 2:	movne	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(memchr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/memset.S linux-libre-3.17-rc7-gnu/arch/arm/lib/memset.S
--- linux-libre-3.16-gnu/arch/arm/lib/memset.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/memset.S	2014-09-28 17:29:07.000000000 -0400
@@ -110,7 +110,7 @@ ENTRY(memset)
 	strneb	r1, [ip], #1
 	tst	r2, #1
 	strneb	r1, [ip], #1
-	mov	pc, lr
+	ret	lr
 
 6:	subs	r2, r2, #4		@ 1 do we have enough
 	blt	5b			@ 1 bytes to align with?
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/memzero.S linux-libre-3.17-rc7-gnu/arch/arm/lib/memzero.S
--- linux-libre-3.16-gnu/arch/arm/lib/memzero.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/memzero.S	2014-09-28 17:29:07.000000000 -0400
@@ -121,5 +121,5 @@ ENTRY(__memzero)
 	strneb	r2, [r0], #1		@ 1
 	tst	r1, #1			@ 1 a byte left over
 	strneb	r2, [r0], #1		@ 1
-	mov	pc, lr			@ 1
+	ret	lr			@ 1
 ENDPROC(__memzero)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/muldi3.S linux-libre-3.17-rc7-gnu/arch/arm/lib/muldi3.S
--- linux-libre-3.16-gnu/arch/arm/lib/muldi3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/muldi3.S	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #ifdef __ARMEB__
 #define xh r0
@@ -41,7 +42,7 @@ ENTRY(__aeabi_lmul)
 	adc	xh, xh, yh, lsr #16
 	adds	xl, xl, ip, lsl #16
 	adc	xh, xh, ip, lsr #16
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__muldi3)
 ENDPROC(__aeabi_lmul)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/putuser.S linux-libre-3.17-rc7-gnu/arch/arm/lib/putuser.S
--- linux-libre-3.16-gnu/arch/arm/lib/putuser.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/putuser.S	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@ ENTRY(__put_user_1)
 	check_uaccess r0, 1, r1, ip, __put_user_bad
 1: TUSER(strb)	r2, [r0]
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__put_user_1)
 
 ENTRY(__put_user_2)
@@ -60,14 +60,14 @@ ENTRY(__put_user_2)
 #endif
 #endif	/* CONFIG_THUMB2_KERNEL */
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
 	check_uaccess r0, 4, r1, ip, __put_user_bad
 4: TUSER(str)	r2, [r0]
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
@@ -80,12 +80,12 @@ ENTRY(__put_user_8)
 6: TUSER(str)	r3, [r0]
 #endif
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(__put_user_8)
 
 __put_user_bad:
 	mov	r0, #-EFAULT
-	mov	pc, lr
+	ret	lr
 ENDPROC(__put_user_bad)
 
 .pushsection __ex_table, "a"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/strchr.S linux-libre-3.17-rc7-gnu/arch/arm/lib/strchr.S
--- linux-libre-3.16-gnu/arch/arm/lib/strchr.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/strchr.S	2014-09-28 17:29:07.000000000 -0400
@@ -23,5 +23,5 @@ ENTRY(strchr)
 		teq	r2, r1
 		movne	r0, #0
 		subeq	r0, r0, #1
-		mov	pc, lr
+		ret	lr
 ENDPROC(strchr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/strrchr.S linux-libre-3.17-rc7-gnu/arch/arm/lib/strrchr.S
--- linux-libre-3.16-gnu/arch/arm/lib/strrchr.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/strrchr.S	2014-09-28 17:29:07.000000000 -0400
@@ -22,5 +22,5 @@ ENTRY(strrchr)
 		teq	r2, #0
 		bne	1b
 		mov	r0, r3
-		mov	pc, lr
+		ret	lr
 ENDPROC(strrchr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/lib/ucmpdi2.S linux-libre-3.17-rc7-gnu/arch/arm/lib/ucmpdi2.S
--- linux-libre-3.16-gnu/arch/arm/lib/ucmpdi2.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/lib/ucmpdi2.S	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #ifdef __ARMEB__
 #define xh r0
@@ -31,7 +32,7 @@ ENTRY(__ucmpdi2)
 	movlo	r0, #0
 	moveq	r0, #1
 	movhi	r0, #2
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__ucmpdi2)
 
@@ -44,7 +45,7 @@ ENTRY(__aeabi_ulcmp)
 	movlo	r0, #-1
 	moveq	r0, #0
 	movhi	r0, #1
-	mov	pc, lr
+	ret	lr
 
 ENDPROC(__aeabi_ulcmp)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91rm9200.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91rm9200.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91rm9200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91rm9200.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,10 +26,11 @@
 #include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "clock.h"
 #include "sam9_smc.h"
 #include "pm.h"
 
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -277,6 +278,9 @@ static void __init at91rm9200_register_c
 	clk_register(&pck2);
 	clk_register(&pck3);
 }
+#else
+#define at91rm9200_register_clocks NULL
+#endif
 
 /* --------------------------------------------------------------------
  *  GPIO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91rm9200_devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91rm9200_devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91rm9200_devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91rm9200_devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
-#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9260.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9260.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9260.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9260.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,10 +27,11 @@
 #include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
-#include "clock.h"
 #include "sam9_smc.h"
 #include "pm.h"
 
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -288,6 +289,9 @@ static void __init at91sam9260_register_
 	clk_register(&pck0);
 	clk_register(&pck1);
 }
+#else
+#define at91sam9260_register_clocks NULL
+#endif
 
 /* --------------------------------------------------------------------
  *  GPIO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9263.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9263.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9263.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9263.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,10 +25,11 @@
 #include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
-#include "clock.h"
 #include "sam9_smc.h"
 #include "pm.h"
 
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -199,6 +200,7 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -280,6 +282,9 @@ static void __init at91sam9263_register_
 	clk_register(&pck2);
 	clk_register(&pck3);
 }
+#else
+#define at91sam9263_register_clocks NULL
+#endif
 
 /* --------------------------------------------------------------------
  *  GPIO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9263_devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9263_devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -1131,9 +1131,7 @@ static void __init at91_add_device_watch
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
 static struct resource pwm_resources[] = {
 	[0] = {
 		.start	= AT91SAM9263_BASE_PWMC,
@@ -1148,11 +1146,8 @@ static struct resource pwm_resources[] =
 };
 
 static struct platform_device at91sam9263_pwm0_device = {
-	.name	= "atmel_pwm",
+	.name	= "at91sam9rl-pwm",
 	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
 	.resource	= pwm_resources,
 	.num_resources	= ARRAY_SIZE(pwm_resources),
 };
@@ -1171,8 +1166,6 @@ void __init at91_add_device_pwm(u32 mask
 	if (mask & (1 << AT91_PWM3))
 		at91_set_B_periph(AT91_PIN_PB29, 1);	/* enable PWM3 */
 
-	pwm_mask = mask;
-
 	platform_device_register(&at91sam9263_pwm0_device);
 }
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9g45.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9g45.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9g45.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9g45.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,10 +25,11 @@
 #include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "clock.h"
 #include "sam9_smc.h"
 #include "pm.h"
 
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -251,6 +252,7 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
 	/* more usart lookup table for DT entries */
 	CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
 	CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
@@ -331,6 +333,9 @@ static void __init at91sam9g45_register_
 	clk_register(&pck0);
 	clk_register(&pck1);
 }
+#else
+#define at91sam9g45_register_clocks NULL
+#endif
 
 /* --------------------------------------------------------------------
  *  GPIO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9g45_devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9g45_devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -1334,9 +1334,7 @@ static void __init at91_add_device_watch
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
 static struct resource pwm_resources[] = {
 	[0] = {
 		.start	= AT91SAM9G45_BASE_PWMC,
@@ -1351,11 +1349,8 @@ static struct resource pwm_resources[] =
 };
 
 static struct platform_device at91sam9g45_pwm0_device = {
-	.name	= "atmel_pwm",
+	.name	= "at91sam9rl-pwm",
 	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
 	.resource	= pwm_resources,
 	.num_resources	= ARRAY_SIZE(pwm_resources),
 };
@@ -1374,8 +1369,6 @@ void __init at91_add_device_pwm(u32 mask
 	if (mask & (1 << AT91_PWM3))
 		at91_set_B_periph(AT91_PIN_PD0, 1);	/* enable PWM3 */
 
-	pwm_mask = mask;
-
 	platform_device_register(&at91sam9g45_pwm0_device);
 }
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9rl.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9rl.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9rl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9rl.c	2014-09-28 17:29:07.000000000 -0400
@@ -200,6 +200,7 @@ static struct clk_lookup periph_clocks_l
 	CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9rl_devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9rl_devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/at91sam9rl_devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/at91sam9rl_devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -799,9 +799,7 @@ static void __init at91_add_device_watch
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
 static struct resource pwm_resources[] = {
 	[0] = {
 		.start	= AT91SAM9RL_BASE_PWMC,
@@ -816,11 +814,8 @@ static struct resource pwm_resources[] =
 };
 
 static struct platform_device at91sam9rl_pwm0_device = {
-	.name	= "atmel_pwm",
+	.name	= "at91sam9rl-pwm",
 	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
 	.resource	= pwm_resources,
 	.num_resources	= ARRAY_SIZE(pwm_resources),
 };
@@ -839,8 +834,6 @@ void __init at91_add_device_pwm(u32 mask
 	if (mask & (1 << AT91_PWM3))
 		at91_set_B_periph(AT91_PIN_PD8, 1);	/* enable PWM3 */
 
-	pwm_mask = mask;
-
 	platform_device_register(&at91sam9rl_pwm0_device);
 }
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/board-dt-rm9200.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-dt-rm9200.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/board-dt-rm9200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-dt-rm9200.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/clk-provider.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -35,13 +36,21 @@ static void __init at91rm9200_dt_init_ir
 	of_irq_init(irq_of_match);
 }
 
+static void __init at91rm9200_dt_timer_init(void)
+{
+#if defined(CONFIG_COMMON_CLK)
+	of_clk_init(NULL);
+#endif
+	at91rm9200_timer_init();
+}
+
 static const char *at91rm9200_dt_board_compat[] __initdata = {
 	"atmel,at91rm9200",
 	NULL
 };
 
 DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
-	.init_time      = at91rm9200_timer_init,
+	.init_time      = at91rm9200_dt_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91rm9200_dt_initialize,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/board.h linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board.h
--- linux-libre-3.16-gnu/arch/arm/mach-at91/board.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board.h	2014-09-28 17:29:07.000000000 -0400
@@ -123,6 +123,5 @@ extern void __init at91_add_device_can(s
 
  /* LEDs */
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/board-sam9263ek.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-sam9263ek.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/board-sam9263ek.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-sam9263ek.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,8 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
 
 #include <video/atmel_lcdc.h>
 
@@ -369,22 +371,48 @@ static struct gpio_led ek_leds[] = {
 		.name			= "ds3",
 		.gpio			= AT91_PIN_PB7,
 		.default_trigger	= "heartbeat",
+	},
+#if !IS_ENABLED(CONFIG_LEDS_PWM)
+	{
+		.name			= "ds1",
+		.gpio			= AT91_PIN_PB8,
+		.active_low		= 1,
+		.default_trigger	= "none",
 	}
+#endif
 };
 
 /*
  * PWM Leds
  */
-static struct gpio_led ek_pwm_led[] = {
-	/* For now only DS1 is PWM-driven (by pwm1) */
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "ds1",
+		   5000, PWM_POLARITY_INVERSED),
+};
+
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct led_pwm pwm_leds[] = {
 	{
-		.name			= "ds1",
-		.gpio			= 1,	/* is PWM channel number */
-		.active_low		= 1,
-		.default_trigger	= "none",
-	}
+		.name = "ds1",
+		.max_brightness = 255,
+	},
 };
 
+static struct led_pwm_platform_data pwm_data = {
+	.num_leds       = ARRAY_SIZE(pwm_leds),
+	.leds           = pwm_leds,
+};
+
+static struct platform_device leds_pwm = {
+	.name   = "leds_pwm",
+	.id     = -1,
+	.dev    = {
+		.platform_data = &pwm_data,
+	},
+};
+#endif
+
+
 /*
  * CAN
  */
@@ -403,6 +431,12 @@ static struct at91_can_data ek_can_data
 	.transceiver_switch = sam9263ek_transceiver_switch,
 };
 
+static struct platform_device *devices[] __initdata = {
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+	&leds_pwm,
+#endif
+};
+
 static void __init ek_board_init(void)
 {
 	/* Serial */
@@ -437,9 +471,14 @@ static void __init ek_board_init(void)
 	at91_add_device_ac97(&ek_ac97_data);
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+	at91_add_device_pwm(1 << AT91_PWM1);
+#endif
 	/* CAN */
 	at91_add_device_can(&ek_can_data);
+	/* Other platform devices */
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,8 @@
 #include <linux/leds.h>
 #include <linux/atmel-mci.h>
 #include <linux/delay.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
 
 #include <linux/platform_data/at91_adc.h>
 
@@ -416,7 +418,7 @@ static struct gpio_led ek_leds[] = {
 		.active_low		= 1,
 		.default_trigger	= "nand-disk",
 	},
-#if !(defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE))
+#if !IS_ENABLED(CONFIG_LEDS_PWM)
 	{	/* "right" led, green, userled1, pwm1 */
 		.name			= "d7",
 		.gpio			= AT91_PIN_PD31,
@@ -430,22 +432,41 @@ static struct gpio_led ek_leds[] = {
 /*
  * PWM Leds
  */
-static struct gpio_led ek_pwm_led[] = {
-#if defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE)
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "d7",
+		   5000, PWM_POLARITY_INVERSED),
+};
+
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct led_pwm pwm_leds[] = {
 	{	/* "right" led, green, userled1, pwm1 */
-		.name			= "d7",
-		.gpio			= 1,	/* is PWM channel number */
-		.active_low		= 1,
-		.default_trigger	= "none",
+		.name = "d7",
+		.max_brightness	= 255,
 	},
-#endif
 };
 
+static struct led_pwm_platform_data pwm_data = {
+	.num_leds	= ARRAY_SIZE(pwm_leds),
+	.leds		= pwm_leds,
+};
+
+static struct platform_device leds_pwm = {
+	.name	= "leds_pwm",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &pwm_data,
+	},
+};
+#endif
+
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SOC_CAMERA_OV2640) || \
 	defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
 	&isi_ov2640,
 #endif
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+	&leds_pwm,
+#endif
 };
 
 static void __init ek_board_init(void)
@@ -486,7 +507,10 @@ static void __init ek_board_init(void)
 	at91_add_device_ac97(&ek_ac97_data);
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+	at91_add_device_pwm(1 << AT91_PWM1);
+#endif
 	/* Other platform devices */
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-at91/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -113,14 +113,12 @@ config SOC_AT91RM9200
 	select HAVE_AT91_DBGU0
 	select MULTI_IRQ_HANDLER
 	select SPARSE_IRQ
-	select AT91_USE_OLD_CLK
 	select HAVE_AT91_USB_CLK
 
 config SOC_AT91SAM9260
 	bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
 	select HAVE_AT91_DBGU0
 	select SOC_AT91SAM9
-	select AT91_USE_OLD_CLK
 	select HAVE_AT91_USB_CLK
 	help
 	  Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -140,7 +138,6 @@ config SOC_AT91SAM9263
 	select HAVE_AT91_DBGU1
 	select HAVE_FB_ATMEL
 	select SOC_AT91SAM9
-	select AT91_USE_OLD_CLK
 	select HAVE_AT91_USB_CLK
 
 config SOC_AT91SAM9RL
@@ -155,7 +152,6 @@ config SOC_AT91SAM9G45
 	select HAVE_AT91_DBGU1
 	select HAVE_FB_ATMEL
 	select SOC_AT91SAM9
-	select AT91_USE_OLD_CLK
 	select HAVE_AT91_UTMI
 	select HAVE_AT91_USB_CLK
 	help
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-at91/leds.c linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/leds.c
--- linux-libre-3.16-gnu/arch/arm/mach-at91/leds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-at91/leds.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,40 +54,3 @@ void __init at91_gpio_leds(struct gpio_l
 void __init at91_gpio_leds(struct gpio_led *leds, int nr) {}
 #endif
 
-
-/* ------------------------------------------------------------------------- */
-
-#if defined (CONFIG_LEDS_ATMEL_PWM)
-
-/*
- * PWM Leds
- */
-
-static struct gpio_led_platform_data pwm_led_data;
-
-static struct platform_device at91_pwm_leds_device = {
-	.name			= "leds-atmel-pwm",
-	.id			= -1,
-	.dev.platform_data	= &pwm_led_data,
-};
-
-void __init at91_pwm_leds(struct gpio_led *leds, int nr)
-{
-	int i;
-	u32 pwm_mask = 0;
-
-	if (!nr)
-		return;
-
-	for (i = 0; i < nr; i++)
-		pwm_mask |= (1 << leds[i].gpio);
-
-	pwm_led_data.leds = leds;
-	pwm_led_data.num_leds = nr;
-
-	at91_add_device_pwm(pwm_mask);
-	platform_device_register(&at91_pwm_leds_device);
-}
-#else
-void __init at91_pwm_leds(struct gpio_led *leds, int nr){}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/board_bcm21664.c linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/board_bcm21664.c
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/board_bcm21664.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/board_bcm21664.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,8 +60,7 @@ static void bcm21664_restart(enum reboot
 
 static void __init bcm21664_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL,
-		&platform_bus);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/board_bcm281xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/board_bcm281xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/board_bcm281xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/board_bcm281xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,8 +58,7 @@ static void bcm281xx_restart(enum reboot
 
 static void __init bcm281xx_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL,
-		&platform_bus);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/brcmstb.c linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/brcmstb.c
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/brcmstb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/brcmstb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013-2014 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 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/init.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static const char *brcmstb_match[] __initconst = {
+	"brcm,bcm7445",
+	"brcm,brcmstb",
+	NULL
+};
+
+DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
+	.dt_compat	= brcmstb_match,
+MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -9,7 +9,6 @@ config ARCH_BCM_MOBILE
 	bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_ERRATA_754322
-	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
 	select ARM_GIC
 	select GPIO_BCM_KONA
@@ -26,16 +25,18 @@ menu "Broadcom Mobile SoC Selection"
 config ARCH_BCM_281XX
 	bool "Broadcom BCM281XX SoC family"
 	default y
+	select HAVE_SMP
 	help
-	  Enable support for the the BCM281XX family, which includes
+	  Enable support for the BCM281XX family, which includes
 	  BCM11130, BCM11140, BCM11351, BCM28145 and BCM28155
 	  variants.
 
 config ARCH_BCM_21664
 	bool "Broadcom BCM21664 SoC family"
 	default y
+	select HAVE_SMP
 	help
-	  Enable support for the the BCM21664 family, which includes
+	  Enable support for the BCM21664 family, which includes
 	  BCM21663 and BCM21664 variants.
 
 config ARCH_BCM_MOBILE_L2_CACHE
@@ -49,6 +50,17 @@ config ARCH_BCM_MOBILE_SMC
 	bool
 	depends on ARCH_BCM_281XX || ARCH_BCM_21664
 
+config ARCH_BCM_MOBILE_SMP
+	bool "Broadcom mobile SoC SMP support"
+	depends on (ARCH_BCM_281XX || ARCH_BCM_21664) && SMP
+	default y
+	select HAVE_ARM_SCU
+	select ARM_ERRATA_764369
+	help
+	  SMP support for the BCM281XX and BCM21664 SoC families.
+	  Provided as an option so SMP support for SoCs of this type
+	  can be disabled for an SMP-enabled kernel.
+
 endmenu
 
 endif
@@ -87,4 +99,20 @@ config ARCH_BCM_5301X
 	  different SoC or with the older BCM47XX and BCM53XX based
 	  network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
 
+config ARCH_BRCMSTB
+	bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
+	depends on MMU
+	select ARM_GIC
+	select MIGHT_HAVE_PCI
+	select HAVE_SMP
+	select HAVE_ARM_ARCH_TIMER
+	select BRCMSTB_GISB_ARB
+	select BRCMSTB_L2_IRQ
+	help
+	  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
+	  chipset.
+
+	  This enables support for Broadcom ARM-based set-top box chipsets,
+	  including the 7445 family of chips.
+
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/kona_smp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/kona_smp.c
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/kona_smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/kona_smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2014 Linaro 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 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/init.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+
+#include <asm/smp.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+/* Size of mapped Cortex A9 SCU address space */
+#define CORTEX_A9_SCU_SIZE	0x58
+
+#define SECONDARY_TIMEOUT_NS	NSEC_PER_MSEC	/* 1 msec (in nanoseconds) */
+#define BOOT_ADDR_CPUID_MASK	0x3
+
+/* Name of device node property defining secondary boot register location */
+#define OF_SECONDARY_BOOT	"secondary-boot-reg"
+
+/* I/O address of register used to coordinate secondary core startup */
+static u32	secondary_boot;
+
+/*
+ * Enable the Cortex A9 Snoop Control Unit
+ *
+ * By the time this is called we already know there are multiple
+ * cores present.  We assume we're running on a Cortex A9 processor,
+ * so any trouble getting the base address register or getting the
+ * SCU base is a problem.
+ *
+ * Return 0 if successful or an error code otherwise.
+ */
+static int __init scu_a9_enable(void)
+{
+	unsigned long config_base;
+	void __iomem *scu_base;
+
+	if (!scu_a9_has_base()) {
+		pr_err("no configuration base address register!\n");
+		return -ENXIO;
+	}
+
+	/* Config base address register value is zero for uniprocessor */
+	config_base = scu_a9_get_base();
+	if (!config_base) {
+		pr_err("hardware reports only one core\n");
+		return -ENOENT;
+	}
+
+	scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
+	if (!scu_base) {
+		pr_err("failed to remap config base (%lu/%u) for SCU\n",
+			config_base, CORTEX_A9_SCU_SIZE);
+		return -ENOMEM;
+	}
+
+	scu_enable(scu_base);
+
+	iounmap(scu_base);	/* That's the last we'll need of this */
+
+	return 0;
+}
+
+static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
+{
+	static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
+	struct device_node *node;
+	int ret;
+
+	BUG_ON(secondary_boot);		/* We're called only once */
+
+	/*
+	 * This function is only called via smp_ops->smp_prepare_cpu().
+	 * That only happens if a "/cpus" device tree node exists
+	 * and has an "enable-method" property that selects the SMP
+	 * operations defined herein.
+	 */
+	node = of_find_node_by_path("/cpus");
+	BUG_ON(!node);
+
+	/*
+	 * Our secondary enable method requires a "secondary-boot-reg"
+	 * property to specify a register address used to request the
+	 * ROM code boot a secondary code.  If we have any trouble
+	 * getting this we fall back to uniprocessor mode.
+	 */
+	if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) {
+		pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n",
+			node->name);
+		ret = -ENOENT;		/* Arrange to disable SMP */
+		goto out;
+	}
+
+	/*
+	 * Enable the SCU on Cortex A9 based SoCs.  If -ENOENT is
+	 * returned, the SoC reported a uniprocessor configuration.
+	 * We bail on any other error.
+	 */
+	ret = scu_a9_enable();
+out:
+	of_node_put(node);
+	if (ret) {
+		/* Update the CPU present map to reflect uniprocessor mode */
+		BUG_ON(ret != -ENOENT);
+		pr_warn("disabling SMP\n");
+		init_cpu_present(&only_cpu_0);
+	}
+}
+
+/*
+ * The ROM code has the secondary cores looping, waiting for an event.
+ * When an event occurs each core examines the bottom two bits of the
+ * secondary boot register.  When a core finds those bits contain its
+ * own core id, it performs initialization, including computing its boot
+ * address by clearing the boot register value's bottom two bits.  The
+ * core signals that it is beginning its execution by writing its boot
+ * address back to the secondary boot register, and finally jumps to
+ * that address.
+ *
+ * So to start a core executing we need to:
+ * - Encode the (hardware) CPU id with the bottom bits of the secondary
+ *   start address.
+ * - Write that value into the secondary boot register.
+ * - Generate an event to wake up the secondary CPU(s).
+ * - Wait for the secondary boot register to be re-written, which
+ *   indicates the secondary core has started.
+ */
+static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	void __iomem *boot_reg;
+	phys_addr_t boot_func;
+	u64 start_clock;
+	u32 cpu_id;
+	u32 boot_val;
+	bool timeout = false;
+
+	cpu_id = cpu_logical_map(cpu);
+	if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
+		pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
+		return -EINVAL;
+	}
+
+	if (!secondary_boot) {
+		pr_err("required secondary boot register not specified\n");
+		return -EINVAL;
+	}
+
+	boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32));
+	if (!boot_reg) {
+		pr_err("unable to map boot register for cpu %u\n", cpu_id);
+		return -ENOSYS;
+	}
+
+	/*
+	 * Secondary cores will start in secondary_startup(),
+	 * defined in "arch/arm/kernel/head.S"
+	 */
+	boot_func = virt_to_phys(secondary_startup);
+	BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
+	BUG_ON(boot_func > (phys_addr_t)U32_MAX);
+
+	/* The core to start is encoded in the low bits */
+	boot_val = (u32)boot_func | cpu_id;
+	writel_relaxed(boot_val, boot_reg);
+
+	sev();
+
+	/* The low bits will be cleared once the core has started */
+	start_clock = local_clock();
+	while (!timeout && readl_relaxed(boot_reg) == boot_val)
+		timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
+
+	iounmap(boot_reg);
+
+	if (!timeout)
+		return 0;
+
+	pr_err("timeout waiting for cpu %u to start\n", cpu_id);
+
+	return -ENOSYS;
+}
+
+static struct smp_operations bcm_smp_ops __initdata = {
+	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
+	.smp_boot_secondary	= bcm_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
+			&bcm_smp_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-bcm/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-bcm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-bcm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,9 @@ obj-$(CONFIG_ARCH_BCM_281XX)	+= board_bc
 # BCM21664
 obj-$(CONFIG_ARCH_BCM_21664)	+= board_bcm21664.o
 
+# BCM281XX and BCM21664 SMP support
+obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += kona_smp.o
+
 # BCM281XX and BCM21664 L2 cache control
 obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o
 
@@ -30,3 +33,7 @@ obj-$(CONFIG_ARCH_BCM2835)	+= board_bcm2
 
 # BCM5301X
 obj-$(CONFIG_ARCH_BCM_5301X)	+= bcm_5301x.o
+
+ifeq ($(CONFIG_ARCH_BRCMSTB),y)
+obj-y				+= brcmstb.o
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-berlin/headsmp.S linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/headsmp.S
--- linux-libre-3.16-gnu/arch/arm/mach-berlin/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/headsmp.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine TÃ©nart <antoine.tenart@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/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+ENTRY(berlin_secondary_startup)
+ ARM_BE8(setend be)
+	bl	v7_invalidate_l1
+	b       secondary_startup
+ENDPROC(berlin_secondary_startup)
+
+/*
+ * If the following instruction is set in the reset exception vector, CPUs
+ * will fetch the value of the software reset address vector when being
+ * reset.
+ */
+.global boot_inst
+boot_inst:
+	ldr	pc, [pc, #140]
+
+	.align
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-berlin/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-berlin/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,9 @@ config MACH_BERLIN_BG2
 	bool "Marvell Armada 1500 (BG2)"
 	select CACHE_L2X0
 	select CPU_PJ4B
+	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
+	select HAVE_SMP
 	select PINCTRL_BERLIN_BG2
 
 config MACH_BERLIN_BG2CD
@@ -25,6 +27,7 @@ config MACH_BERLIN_BG2CD
 config MACH_BERLIN_BG2Q
 	bool "Marvell Armada 1500 Pro (BG2-Q)"
 	select CACHE_L2X0
+	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select PINCTRL_BERLIN_BG2Q
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-berlin/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-berlin/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1 +1,2 @@
-obj-y += berlin.o
+obj-y			+= berlin.o
+obj-$(CONFIG_SMP)	+= headsmp.o platsmp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-berlin/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-berlin/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-berlin/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine TÃ©nart <antoine.tenart@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/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+#define CPU_RESET		0x00
+
+#define RESET_VECT		0x00
+#define SW_RESET_ADDR		0x94
+
+extern void berlin_secondary_startup(void);
+extern u32 boot_inst;
+
+static void __iomem *cpu_ctrl;
+
+static inline void berlin_perform_reset_cpu(unsigned int cpu)
+{
+	u32 val;
+
+	val = readl(cpu_ctrl + CPU_RESET);
+	val |= BIT(cpu_logical_map(cpu));
+	writel(val, cpu_ctrl + CPU_RESET);
+}
+
+static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	if (!cpu_ctrl)
+		return -EFAULT;
+
+	/*
+	 * Reset the CPU, making it to execute the instruction in the reset
+	 * exception vector.
+	 */
+	berlin_perform_reset_cpu(cpu);
+
+	return 0;
+}
+
+static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *np;
+	void __iomem *scu_base;
+	void __iomem *vectors_base;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+	scu_base = of_iomap(np, 0);
+	of_node_put(np);
+	if (!scu_base)
+		return;
+
+	np = of_find_compatible_node(NULL, NULL, "marvell,berlin-cpu-ctrl");
+	cpu_ctrl = of_iomap(np, 0);
+	of_node_put(np);
+	if (!cpu_ctrl)
+		goto unmap_scu;
+
+	vectors_base = ioremap(CONFIG_VECTORS_BASE, SZ_32K);
+	if (!vectors_base)
+		goto unmap_scu;
+
+	scu_enable(scu_base);
+	flush_cache_all();
+
+	/*
+	 * Write the first instruction the CPU will execute after being reset
+	 * in the reset exception vector.
+	 */
+	writel(boot_inst, vectors_base + RESET_VECT);
+
+	/*
+	 * Write the secondary startup address into the SW reset address
+	 * vector. This is used by boot_inst.
+	 */
+	writel(virt_to_phys(berlin_secondary_startup), vectors_base + SW_RESET_ADDR);
+
+	iounmap(vectors_base);
+unmap_scu:
+	iounmap(scu_base);
+}
+
+static struct smp_operations berlin_smp_ops __initdata = {
+	.smp_prepare_cpus	= berlin_smp_prepare_cpus,
+	.smp_boot_secondary	= berlin_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-autcpu12.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-autcpu12.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-autcpu12.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-autcpu12.c	2014-09-28 17:29:07.000000000 -0400
@@ -266,7 +266,6 @@ MACHINE_START(AUTCPU12, "autronix autcpu
 	/* Maintainer: Thomas Gleixner */
 	.atag_offset	= 0x20000,
 	.map_io		= clps711x_map_io,
-	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
 	.init_machine	= autcpu12_init,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-cdb89712.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-cdb89712.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-cdb89712.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-cdb89712.c	2014-09-28 17:29:07.000000000 -0400
@@ -140,7 +140,6 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712
 	/* Maintainer: Ray Lehtiniemi */
 	.atag_offset	= 0x100,
 	.map_io		= clps711x_map_io,
-	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
 	.init_machine	= cdb89712_init,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-clep7312.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-clep7312.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-clep7312.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-clep7312.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <asm/mach/arch.h>
 
 #include "common.h"
+#include "devices.h"
 
 static void __init
 fixup_clep7312(struct tag *tags, char **cmdline)
@@ -37,8 +38,8 @@ MACHINE_START(CLEP7212, "Cirrus Logic 72
 	.atag_offset	= 0x0100,
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
-	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
+	.init_machine	= clps711x_devices_init,
 	.restart	= clps711x_restart,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-edb7211.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-edb7211.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-edb7211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-edb7211.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,26 +148,21 @@ fixup_edb7211(struct tag *tags, char **c
 	memblock_add(0xc1000000, SZ_8M);
 }
 
-static void __init edb7211_init(void)
-{
-	clps711x_devices_init();
-}
-
 static void __init edb7211_init_late(void)
 {
 	gpio_request_array(edb7211_gpios, ARRAY_SIZE(edb7211_gpios));
 
 	platform_device_register(&edb7211_flash_pdev);
-	platform_device_register_data(&platform_bus, "platform-lcd", 0,
+	platform_device_register_data(NULL, "platform-lcd", 0,
 				      &edb7211_lcd_power_pdata,
 				      sizeof(edb7211_lcd_power_pdata));
-	platform_device_register_data(&platform_bus, "generic-bl", 0,
+	platform_device_register_data(NULL, "generic-bl", 0,
 				      &edb7211_lcd_backlight_pdata,
 				      sizeof(edb7211_lcd_backlight_pdata));
 	platform_device_register_simple("video-clps711x", 0, NULL, 0);
 	platform_device_register_simple("cs89x0", 0, edb7211_cs8900_resource,
 					ARRAY_SIZE(edb7211_cs8900_resource));
-	platform_device_register_data(&platform_bus, "i2c-gpio", 0,
+	platform_device_register_data(NULL, "i2c-gpio", 0,
 				      &edb7211_i2c_pdata,
 				      sizeof(edb7211_i2c_pdata));
 }
@@ -178,10 +173,9 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP72
 	.fixup		= fixup_edb7211,
 	.reserve	= edb7211_reserve,
 	.map_io		= clps711x_map_io,
-	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
-	.init_machine	= edb7211_init,
+	.init_machine	= clps711x_devices_init,
 	.init_late	= edb7211_init_late,
 	.restart	= clps711x_restart,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-p720t.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-p720t.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/board-p720t.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/board-p720t.c	2014-09-28 17:29:07.000000000 -0400
@@ -348,14 +348,14 @@ static void __init p720t_init_late(void)
 {
 	WARN_ON(gpio_request_array(p720t_gpios, ARRAY_SIZE(p720t_gpios)));
 
-	platform_device_register_data(&platform_bus, "platform-lcd", 0,
+	platform_device_register_data(NULL, "platform-lcd", 0,
 				      &p720t_lcd_power_pdata,
 				      sizeof(p720t_lcd_power_pdata));
-	platform_device_register_data(&platform_bus, "generic-bl", 0,
+	platform_device_register_data(NULL, "generic-bl", 0,
 				      &p720t_lcd_backlight_pdata,
 				      sizeof(p720t_lcd_backlight_pdata));
 	platform_device_register_simple("video-clps711x", 0, NULL, 0);
-	platform_device_register_data(&platform_bus, "leds-gpio", 0,
+	platform_device_register_data(NULL, "leds-gpio", 0,
 				      &p720t_gpio_led_pdata,
 				      sizeof(p720t_gpio_led_pdata));
 }
@@ -365,7 +365,6 @@ MACHINE_START(P720T, "ARM-Prospector720T
 	.atag_offset	= 0x100,
 	.fixup		= fixup_p720t,
 	.map_io		= clps711x_map_io,
-	.init_early	= clps711x_init_early,
 	.init_irq	= clps711x_init_irq,
 	.init_time	= clps711x_timer_init,
 	.init_machine	= p720t_init,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,15 +193,3 @@ void clps711x_restart(enum reboot_mode m
 {
 	soft_restart(0);
 }
-
-static void clps711x_idle(void)
-{
-	clps_writel(1, HALT);
-	asm("mov r0, r0");
-	asm("mov r0, r0");
-}
-
-void __init clps711x_init_early(void)
-{
-	arm_pm_idle = clps711x_idle;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@ extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
 extern void clps711x_timer_init(void);
 extern void clps711x_restart(enum reboot_mode mode, const char *cmd);
-extern void clps711x_init_early(void);
 
 /* drivers/irqchip/irq-clps711x.c */
 void clps711x_intc_init(phys_addr_t, resource_size_t);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,15 @@
 
 #include <mach/hardware.h>
 
+static const struct resource clps711x_cpuidle_res __initconst =
+	DEFINE_RES_MEM(CLPS711X_PHYS_BASE + HALT, SZ_128);
+
+static void __init clps711x_add_cpuidle(void)
+{
+	platform_device_register_simple("clps711x-cpuidle", PLATFORM_DEVID_NONE,
+					&clps711x_cpuidle_res, 1);
+}
+
 static const phys_addr_t clps711x_gpios[][2] __initconst = {
 	{ PADR, PADDR },
 	{ PBDR, PBDDR },
@@ -83,6 +92,7 @@ static void __init clps711x_add_uart(voi
 
 void __init clps711x_devices_init(void)
 {
+	clps711x_add_cpuidle();
 	clps711x_add_gpio();
 	clps711x_add_syscon();
 	clps711x_add_uart();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* arch/arm/mach-clps711x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <mach/hardware.h>
-
-		.macro	addruart, rp, rv, tmp
-#ifndef CONFIG_DEBUG_CLPS711X_UART2
-		mov	\rp, #0x0000	@ UART1
-#else
-		mov	\rp, #0x1000	@ UART2
-#endif
-		orr	\rv, \rp, #CLPS711X_VIRT_BASE
-		orr	\rp, \rp, #CLPS711X_PHYS_BASE
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x0480]	@ UARTDR
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-1001:		ldr	\rd, [\rx, #0x0140]	@ SYSFLGx
-		tst	\rd, #1 << 11		@ UBUSYx
-		bne	1001b
-		.endm
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-clps711x/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-clps711x/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-clps711x/include/mach/hardware.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,10 +24,7 @@
 
 #include <mach/clps711x.h>
 
-#define IO_ADDRESS(x)		(0xdc000000 + (((x) & 0x03ffffff) | \
-				(((x) >> 2) & 0x3c000000)))
-
-#define CLPS711X_VIRT_BASE	IOMEM(IO_ADDRESS(CLPS711X_PHYS_BASE))
+#define CLPS711X_VIRT_BASE	IOMEM(0xfeff0000)
 
 #ifndef __ASSEMBLY__
 #define clps_readb(off)		readb(CLPS711X_VIRT_BASE + (off))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-davinci/sleep.S linux-libre-3.17-rc7-gnu/arch/arm/mach-davinci/sleep.S
--- linux-libre-3.16-gnu/arch/arm/mach-davinci/sleep.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-davinci/sleep.S	2014-09-28 17:29:07.000000000 -0400
@@ -213,7 +213,7 @@ ddr2clk_stop_done:
 	cmp	ip, r0
 	bne	ddr2clk_stop_done
 
-	mov	pc, lr
+	ret	lr
 ENDPROC(davinci_ddr_psc_config)
 
 CACHE_FLUSH:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ebsa110/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-ebsa110/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-ebsa110/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ebsa110/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,11 +17,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 /*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-/*
  * Cache flushing area - SRAM
  */
 #define FLUSH_BASE_PHYS		0x40000000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ep93xx/crunch-bits.S linux-libre-3.17-rc7-gnu/arch/arm/mach-ep93xx/crunch-bits.S
--- linux-libre-3.16-gnu/arch/arm/mach-ep93xx/crunch-bits.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ep93xx/crunch-bits.S	2014-09-28 17:29:07.000000000 -0400
@@ -198,7 +198,7 @@ crunch_load:
 	get_thread_info r10
 #endif
 2:	dec_preempt_count r10, r3
-	mov	pc, lr
+	ret	lr
 
 /*
  * Back up crunch regs to save area and disable access to them
@@ -277,7 +277,7 @@ ENTRY(crunch_task_copy)
 	mov	r3, lr				@ preserve return address
 	bl	crunch_save
 	msr	cpsr_c, ip			@ restore interrupt mode
-	mov	pc, r3
+	ret	r3
 
 /*
  * Restore crunch state from given memory address
@@ -310,4 +310,4 @@ ENTRY(crunch_task_restore)
 	mov	r3, lr				@ preserve return address
 	bl	crunch_load
 	msr	cpsr_c, ip			@ restore interrupt mode
-	mov	pc, r3
+	ret	r3
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ep93xx/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-ep93xx/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-#elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET		UL(0xc0000000)
-#elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET		UL(0xd0000000)
-#elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET		UL(0xe0000000)
-#elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET		UL(0xf0000000)
-#else
-#error "Kconfig bug: No EP93xx PHYS_OFFSET set"
-#endif
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -111,25 +111,14 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SO
 #define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
 			  soc_is_exynos5420() || soc_is_exynos5800())
 
-void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
-
-struct map_desc;
 extern void __iomem *sysram_ns_base_addr;
 extern void __iomem *sysram_base_addr;
-void exynos_init_io(void);
-void exynos_restart(enum reboot_mode mode, const char *cmd);
+extern void __iomem *pmu_base_addr;
 void exynos_sysram_init(void);
-void exynos_cpuidle_init(void);
-void exynos_cpufreq_init(void);
-void exynos_init_late(void);
 
 void exynos_firmware_init(void);
 
-#ifdef CONFIG_PINCTRL_EXYNOS
 extern u32 exynos_get_eint_wake_mask(void);
-#else
-static inline u32 exynos_get_eint_wake_mask(void) { return 0xffffffff; }
-#endif
 
 #ifdef CONFIG_PM_SLEEP
 extern void __init exynos_pm_init(void);
@@ -145,7 +134,7 @@ extern void exynos_cpu_die(unsigned int
 
 /* PMU(Power Management Unit) support */
 
-#define PMU_TABLE_END	NULL
+#define PMU_TABLE_END	(-1U)
 
 enum sys_powerdown {
 	SYS_AFTR,
@@ -155,7 +144,7 @@ enum sys_powerdown {
 };
 
 struct exynos_pmu_conf {
-	void __iomem *reg;
+	unsigned int offset;
 	unsigned int val[NUM_SYS_POWERDOWN];
 };
 
@@ -171,4 +160,14 @@ extern void exynos_enter_aftr(void);
 extern void s5p_init_cpu(void __iomem *cpuid_addr);
 extern unsigned int samsung_rev(void);
 
+static inline void pmu_raw_writel(u32 val, u32 offset)
+{
+	__raw_writel(val, pmu_base_addr + offset);
+}
+
+static inline u32 pmu_raw_readl(u32 offset)
+{
+	return __raw_readl(pmu_base_addr + offset);
+}
+
 #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/exynos.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/exynos.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/exynos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/exynos.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/irqchip.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -29,6 +30,9 @@
 #include "common.h"
 #include "mfc.h"
 #include "regs-pmu.h"
+#include "regs-sys.h"
+
+void __iomem *pmu_base_addr;
 
 static struct map_desc exynos4_iodesc[] __initdata = {
 	{
@@ -57,11 +61,6 @@ static struct map_desc exynos4_iodesc[]
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_PMU,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_PMU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_COMBINER),
 		.length		= SZ_4K,
@@ -135,19 +134,14 @@ static struct map_desc exynos5_iodesc[]
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_CMU),
 		.length		= 144 * SZ_1K,
 		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_PMU,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_PMU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
 	},
 };
 
-void exynos_restart(enum reboot_mode mode, const char *cmd)
+static void exynos_restart(enum reboot_mode mode, const char *cmd)
 {
 	struct device_node *np;
 	u32 val = 0x1;
-	void __iomem *addr = EXYNOS_SWRESET;
+	void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
 
 	if (of_machine_is_compatible("samsung,exynos5440")) {
 		u32 status;
@@ -171,17 +165,6 @@ static struct platform_device exynos_cpu
 	.id                = -1,
 };
 
-void __init exynos_cpuidle_init(void)
-{
-	if (soc_is_exynos4210() || soc_is_exynos5250())
-		platform_device_register(&exynos_cpuidle);
-}
-
-void __init exynos_cpufreq_init(void)
-{
-	platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-}
-
 void __iomem *sysram_base_addr;
 void __iomem *sysram_ns_base_addr;
 
@@ -204,7 +187,7 @@ void __init exynos_sysram_init(void)
 	}
 }
 
-void __init exynos_init_late(void)
+static void __init exynos_init_late(void)
 {
 	if (of_machine_is_compatible("samsung,exynos5440"))
 		/* to be supported later */
@@ -251,7 +234,7 @@ static void __init exynos_map_io(void)
 		iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
 }
 
-void __init exynos_init_io(void)
+static void __init exynos_init_io(void)
 {
 	debug_ll_io_init();
 
@@ -263,6 +246,41 @@ void __init exynos_init_io(void)
 	exynos_map_io();
 }
 
+static const struct of_device_id exynos_dt_pmu_match[] = {
+	{ .compatible = "samsung,exynos3250-pmu" },
+	{ .compatible = "samsung,exynos4210-pmu" },
+	{ .compatible = "samsung,exynos4212-pmu" },
+	{ .compatible = "samsung,exynos4412-pmu" },
+	{ .compatible = "samsung,exynos5250-pmu" },
+	{ .compatible = "samsung,exynos5260-pmu" },
+	{ .compatible = "samsung,exynos5410-pmu" },
+	{ .compatible = "samsung,exynos5420-pmu" },
+	{ /*sentinel*/ },
+};
+
+static void exynos_map_pmu(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, exynos_dt_pmu_match);
+	if (np)
+		pmu_base_addr = of_iomap(np, 0);
+
+	if (!pmu_base_addr)
+		panic("failed to find exynos pmu register\n");
+}
+
+static void __init exynos_init_irq(void)
+{
+	irqchip_init();
+	/*
+	 * Since platsmp.c needs pmu base address by the time
+	 * DT is not unflatten so we can't use DT APIs before
+	 * init_irq
+	 */
+	exynos_map_pmu();
+}
+
 static void __init exynos_dt_machine_init(void)
 {
 	struct device_node *i2c_np;
@@ -298,8 +316,11 @@ static void __init exynos_dt_machine_ini
 	if (!IS_ENABLED(CONFIG_SMP))
 		exynos_sysram_init();
 
-	exynos_cpuidle_init();
-	exynos_cpufreq_init();
+	if (of_machine_is_compatible("samsung,exynos4210") ||
+			of_machine_is_compatible("samsung,exynos5250"))
+		platform_device_register(&exynos_cpuidle);
+
+	platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
@@ -352,6 +373,7 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXY
 	.smp		= smp_ops(exynos_smp_ops),
 	.map_io		= exynos_init_io,
 	.init_early	= exynos_firmware_init,
+	.init_irq	= exynos_init_irq,
 	.init_machine	= exynos_dt_machine_init,
 	.init_late	= exynos_init_late,
 	.dt_compat	= exynos_dt_compat,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/headsmp.S linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/headsmp.S
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/headsmp.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/headsmp.S	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 /*
- *  linux/arch/arm/mach-exynos4/headsmp.S
  *
  *  Cloned from linux/arch/arm/mach-realview/headsmp.S
  *
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/hotplug.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/hotplug.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/hotplug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/hotplug.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
-/* linux arch/arm/mach-exynos4/hotplug.c
- *
+/*
  *  Cloned from linux/arch/arm/mach-realview/hotplug.c
  *
  *  Copyright (C) 2002 ARM Ltd.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/include/mach/map.h linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/include/mach/map.h
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/include/mach/map.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/include/mach/map.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos/include/mach/map.h
- *
+/*
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
@@ -28,9 +27,6 @@
 #define EXYNOS4_PA_SYSCON		0x10010000
 #define EXYNOS5_PA_SYSCON		0x10050100
 
-#define EXYNOS4_PA_PMU			0x10020000
-#define EXYNOS5_PA_PMU			0x10040000
-
 #define EXYNOS4_PA_CMU			0x10030000
 #define EXYNOS5_PA_CMU			0x10010000
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/include/mach/memory.h
- *
+/*
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -100,7 +100,6 @@ config SOC_EXYNOS5440
 	default y
 	depends on ARCH_EXYNOS5
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
-	select ARCH_HAS_OPP
 	select HAVE_ARM_ARCH_TIMER
 	select AUTO_ZRELADDR
 	select MIGHT_HAVE_PCI
@@ -119,6 +118,7 @@ config EXYNOS5420_MCPM
 	bool "Exynos5420 Multi-Cluster PM support"
 	depends on MCPM && SOC_EXYNOS5420
 	select ARM_CCI
+	select ARM_CPU_SUSPEND
 	help
 	  This is needed to provide CPU and cluster power management
 	  on Exynos5420 implementing big.LITTLE.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/mcpm-exynos.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/mcpm-exynos.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/mcpm-exynos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/mcpm-exynos.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,10 @@
 #define EXYNOS5420_CPUS_PER_CLUSTER	4
 #define EXYNOS5420_NR_CLUSTERS		2
 
+#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN	BIT(9)
+#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE	BIT(29)
+#define EXYNOS5420_USE_L2_COMMON_UP_STATE	BIT(30)
+
 /*
  * The common v7_exit_coherency_flush API could not be used because of the
  * Erratum 799270 workaround. This macro is the same as the common one (in
@@ -39,7 +43,6 @@
 	"mcr	p15, 0, r0, c1, c0, 0	@ set SCTLR\n\t" \
 	"isb\n\t"\
 	"bl	v7_flush_dcache_"__stringify(level)"\n\t" \
-	"clrex\n\t"\
 	"mrc	p15, 0, r0, c1, c0, 1	@ get ACTLR\n\t" \
 	"bic	r0, r0, #(1 << 6)	@ disable local coherency\n\t" \
 	/* Dummy Load of a device register to avoid Erratum 799270 */ \
@@ -51,7 +54,7 @@
 	"dsb\n\t" \
 	"ldmfd	sp!, {fp, ip}" \
 	: \
-	: "Ir" (S5P_INFORM0) \
+	: "Ir" (pmu_base_addr + S5P_INFORM0) \
 	: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
 	  "r9", "r10", "lr", "memory")
 
@@ -73,36 +76,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTE
 
 #define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster)
 
-static int exynos_cluster_power_control(unsigned int cluster, int enable)
-{
-	unsigned int tries = 100;
-	unsigned int val;
-
-	if (enable) {
-		exynos_cluster_power_up(cluster);
-		val = S5P_CORE_LOCAL_PWR_EN;
-	} else {
-		exynos_cluster_power_down(cluster);
-		val = 0;
-	}
-
-	/* Wait until cluster power control is applied */
-	while (tries--) {
-		if (exynos_cluster_power_state(cluster) == val)
-			return 0;
-
-		cpu_relax();
-	}
-	pr_debug("timed out waiting for cluster %u to power %s\n", cluster,
-		enable ? "on" : "off");
-
-	return -ETIMEDOUT;
-}
-
 static int exynos_power_up(unsigned int cpu, unsigned int cluster)
 {
 	unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
-	int err = 0;
 
 	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
 	if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
@@ -126,12 +102,9 @@ static int exynos_power_up(unsigned int
 		 * cores.
 		 */
 		if (was_cluster_down)
-			err = exynos_cluster_power_control(cluster, 1);
+			exynos_cluster_power_up(cluster);
 
-		if (!err)
-			exynos_cpu_power_up(cpunr);
-		else
-			exynos_cluster_power_control(cluster, 0);
+		exynos_cpu_power_up(cpunr);
 	} else if (cpu_use_count[cpu][cluster] != 2) {
 		/*
 		 * The only possible values are:
@@ -147,7 +120,7 @@ static int exynos_power_up(unsigned int
 	arch_spin_unlock(&exynos_mcpm_lock);
 	local_irq_enable();
 
-	return err;
+	return 0;
 }
 
 /*
@@ -178,9 +151,10 @@ static void exynos_power_down(void)
 	if (cpu_use_count[cpu][cluster] == 0) {
 		exynos_cpu_power_down(cpunr);
 
-		if (exynos_cluster_unused(cluster))
-			/* TODO: Turn off the cluster here to save power. */
+		if (exynos_cluster_unused(cluster)) {
+			exynos_cluster_power_down(cluster);
 			last_man = true;
+		}
 	} else if (cpu_use_count[cpu][cluster] == 1) {
 		/*
 		 * A power_up request went ahead of us.
@@ -196,7 +170,7 @@ static void exynos_power_down(void)
 	if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
 		arch_spin_unlock(&exynos_mcpm_lock);
 
-		if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
+		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
 			/*
 			 * On the Cortex-A15 we need to disable
 			 * L2 prefetching before flushing the cache.
@@ -257,10 +231,46 @@ static int exynos_wait_for_powerdown(uns
 	return -ETIMEDOUT; /* timeout */
 }
 
+static void exynos_powered_up(void)
+{
+	unsigned int mpidr, cpu, cluster;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	arch_spin_lock(&exynos_mcpm_lock);
+	if (cpu_use_count[cpu][cluster] == 0)
+		cpu_use_count[cpu][cluster] = 1;
+	arch_spin_unlock(&exynos_mcpm_lock);
+}
+
+static void exynos_suspend(u64 residency)
+{
+	unsigned int mpidr, cpunr;
+
+	exynos_power_down();
+
+	/*
+	 * Execution reaches here only if cpu did not power down.
+	 * Hence roll back the changes done in exynos_power_down function.
+	 *
+	 * CAUTION: "This function requires the stack data to be visible through
+	 * power down and can only be executed on processors like A15 and A7
+	 * that hit the cache with the C bit clear in the SCTLR register."
+	*/
+	mpidr = read_cpuid_mpidr();
+	cpunr = exynos_pmu_cpunr(mpidr);
+
+	exynos_cpu_power_up(cpunr);
+}
+
 static const struct mcpm_platform_ops exynos_power_ops = {
 	.power_up		= exynos_power_up,
 	.power_down		= exynos_power_down,
 	.wait_for_powerdown	= exynos_wait_for_powerdown,
+	.suspend		= exynos_suspend,
+	.powered_up		= exynos_powered_up,
 };
 
 static void __init exynos_mcpm_usage_count_init(void)
@@ -289,6 +299,19 @@ static void __naked exynos_pm_power_up_s
 	"b	cci_enable_port_for_self");
 }
 
+static void __init exynos_cache_off(void)
+{
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+		/* disable L2 prefetching on the Cortex-A15 */
+		asm volatile(
+		"mcr	p15, 1, %0, c15, c0, 3\n\t"
+		"isb\n\t"
+		"dsb"
+		: : "r" (0x400));
+	}
+	exynos_v7_exit_coherency_flush(all);
+}
+
 static const struct of_device_id exynos_dt_mcpm_match[] = {
 	{ .compatible = "samsung,exynos5420" },
 	{ .compatible = "samsung,exynos5800" },
@@ -299,6 +322,7 @@ static int __init exynos_mcpm_init(void)
 {
 	struct device_node *node;
 	void __iomem *ns_sram_base_addr;
+	unsigned int value, i;
 	int ret;
 
 	node = of_find_matching_node(NULL, exynos_dt_mcpm_match);
@@ -325,13 +349,15 @@ static int __init exynos_mcpm_init(void)
 	 * To increase the stability of KFC reset we need to program
 	 * the PMU SPARE3 register
 	 */
-	__raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
+	pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
 
 	exynos_mcpm_usage_count_init();
 
 	ret = mcpm_platform_register(&exynos_power_ops);
 	if (!ret)
 		ret = mcpm_sync_init(exynos_pm_power_up_setup);
+	if (!ret)
+		ret = mcpm_loopback(exynos_cache_off); /* turn on the CCI */
 	if (ret) {
 		iounmap(ns_sram_base_addr);
 		return ret;
@@ -342,6 +368,26 @@ static int __init exynos_mcpm_init(void)
 	pr_info("Exynos MCPM support installed\n");
 
 	/*
+	 * On Exynos5420/5800 for the A15 and A7 clusters:
+	 *
+	 * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores
+	 * in a cluster are turned off before turning off the cluster L2.
+	 *
+	 * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered
+	 * off before waking it up.
+	 *
+	 * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be
+	 * turned on before the first man is powered up.
+	 */
+	for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) {
+		value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i));
+		value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN |
+			 EXYNOS5420_USE_ARM_CORE_DOWN_STATE    |
+			 EXYNOS5420_USE_L2_COMMON_UP_STATE;
+		pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
+	}
+
+	/*
 	 * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
 	 * as part of secondary_cpu_start().  Let's redirect it to the
 	 * mcpm_entry_point().
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/platsmp.c
- *
+ /*
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
@@ -27,15 +26,83 @@
 #include <asm/smp_scu.h>
 #include <asm/firmware.h>
 
+#include <mach/map.h>
+
 #include "common.h"
 #include "regs-pmu.h"
 
 extern void exynos4_secondary_startup(void);
 
+/**
+ * exynos_core_power_down : power down the specified cpu
+ * @cpu : the cpu to power down
+ *
+ * Power down the specified cpu. The sequence must be finished by a
+ * call to cpu_do_idle()
+ *
+ */
+void exynos_cpu_power_down(int cpu)
+{
+	pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+}
+
+/**
+ * exynos_cpu_power_up : power up the specified cpu
+ * @cpu : the cpu to power up
+ *
+ * Power up the specified cpu
+ */
+void exynos_cpu_power_up(int cpu)
+{
+	pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+			EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+}
+
+/**
+ * exynos_cpu_power_state : returns the power state of the cpu
+ * @cpu : the cpu to retrieve the power state from
+ *
+ */
+int exynos_cpu_power_state(int cpu)
+{
+	return (pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
+			S5P_CORE_LOCAL_PWR_EN);
+}
+
+/**
+ * exynos_cluster_power_down : power down the specified cluster
+ * @cluster : the cluster to power down
+ */
+void exynos_cluster_power_down(int cluster)
+{
+	pmu_raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
+}
+
+/**
+ * exynos_cluster_power_up : power up the specified cluster
+ * @cluster : the cluster to power up
+ */
+void exynos_cluster_power_up(int cluster)
+{
+	pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+			EXYNOS_COMMON_CONFIGURATION(cluster));
+}
+
+/**
+ * exynos_cluster_power_state : returns the power state of the cluster
+ * @cluster : the cluster to retrieve the power state from
+ *
+ */
+int exynos_cluster_power_state(int cluster)
+{
+	return (pmu_raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
+		S5P_CORE_LOCAL_PWR_EN);
+}
+
 static inline void __iomem *cpu_boot_reg_base(void)
 {
 	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
-		return S5P_INFORM5;
+		return pmu_base_addr + S5P_INFORM5;
 	return sysram_base_addr;
 }
 
@@ -190,7 +257,7 @@ static void __init exynos_smp_init_cpus(
 	void __iomem *scu_base = scu_base_addr();
 	unsigned int i, ncores;
 
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 	else
 		/*
@@ -216,7 +283,7 @@ static void __init exynos_smp_prepare_cp
 
 	exynos_sysram_init();
 
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		scu_enable(scu_base_addr());
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,13 +28,13 @@
 #include <asm/suspend.h>
 
 #include <plat/pm-common.h>
-#include <plat/pll.h>
 #include <plat/regs-srom.h>
 
 #include <mach/map.h>
 
 #include "common.h"
 #include "regs-pmu.h"
+#include "regs-sys.h"
 
 /**
  * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
@@ -100,102 +100,20 @@ static int exynos_irq_set_wake(struct ir
 	return -ENOENT;
 }
 
-/**
- * exynos_core_power_down : power down the specified cpu
- * @cpu : the cpu to power down
- *
- * Power down the specified cpu. The sequence must be finished by a
- * call to cpu_do_idle()
- *
- */
-void exynos_cpu_power_down(int cpu)
-{
-	__raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
-}
-
-/**
- * exynos_cpu_power_up : power up the specified cpu
- * @cpu : the cpu to power up
- *
- * Power up the specified cpu
- */
-void exynos_cpu_power_up(int cpu)
-{
-	__raw_writel(S5P_CORE_LOCAL_PWR_EN,
-		     EXYNOS_ARM_CORE_CONFIGURATION(cpu));
-}
-
-/**
- * exynos_cpu_power_state : returns the power state of the cpu
- * @cpu : the cpu to retrieve the power state from
- *
- */
-int exynos_cpu_power_state(int cpu)
-{
-	return (__raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
-			S5P_CORE_LOCAL_PWR_EN);
-}
-
-/**
- * exynos_cluster_power_down : power down the specified cluster
- * @cluster : the cluster to power down
- */
-void exynos_cluster_power_down(int cluster)
-{
-	__raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
-}
-
-/**
- * exynos_cluster_power_up : power up the specified cluster
- * @cluster : the cluster to power up
- */
-void exynos_cluster_power_up(int cluster)
-{
-	__raw_writel(S5P_CORE_LOCAL_PWR_EN,
-		     EXYNOS_COMMON_CONFIGURATION(cluster));
-}
-
-/**
- * exynos_cluster_power_state : returns the power state of the cluster
- * @cluster : the cluster to retrieve the power state from
- *
- */
-int exynos_cluster_power_state(int cluster)
-{
-	return (__raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
-			S5P_CORE_LOCAL_PWR_EN);
-}
-
 #define EXYNOS_BOOT_VECTOR_ADDR	(samsung_rev() == EXYNOS4210_REV_1_1 ? \
-			S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
-			(sysram_base_addr + 0x24) : S5P_INFORM0))
+			pmu_base_addr + S5P_INFORM7 : \
+			(samsung_rev() == EXYNOS4210_REV_1_0 ? \
+			(sysram_base_addr + 0x24) : \
+			pmu_base_addr + S5P_INFORM0))
 #define EXYNOS_BOOT_VECTOR_FLAG	(samsung_rev() == EXYNOS4210_REV_1_1 ? \
-			S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
-			(sysram_base_addr + 0x20) : S5P_INFORM1))
+			pmu_base_addr + S5P_INFORM6 : \
+			(samsung_rev() == EXYNOS4210_REV_1_0 ? \
+			(sysram_base_addr + 0x20) : \
+			pmu_base_addr + S5P_INFORM1))
 
 #define S5P_CHECK_AFTR  0xFCBA0D10
 #define S5P_CHECK_SLEEP 0x00000BAD
 
-/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
-static void exynos_set_wakeupmask(long mask)
-{
-	__raw_writel(mask, S5P_WAKEUP_MASK);
-}
-
-static void exynos_cpu_set_boot_vector(long flags)
-{
-	__raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
-	__raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
-}
-
-void exynos_enter_aftr(void)
-{
-	exynos_set_wakeupmask(0x0000ff3e);
-	exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
-	/* Set value of power down register for aftr mode */
-	exynos_sys_powerdown_conf(SYS_AFTR);
-}
-
 /* For Cortex-A9 Diagnostic and Power control register */
 static unsigned int save_arm_register[2];
 
@@ -235,6 +153,82 @@ static void exynos_cpu_restore_register(
 		      : "cc");
 }
 
+static void exynos_pm_central_suspend(void)
+{
+	unsigned long tmp;
+
+	/* Setting Central Sequence Register for power down mode */
+	tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+	pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+}
+
+static int exynos_pm_central_resume(void)
+{
+	unsigned long tmp;
+
+	/*
+	 * If PMU failed while entering sleep mode, WFI will be
+	 * ignored by PMU and then exiting cpu_do_idle().
+	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+	 * in this situation.
+	 */
+	tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+		tmp |= S5P_CENTRAL_LOWPWR_CFG;
+		pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+		/* clear the wakeup state register */
+		pmu_raw_writel(0x0, S5P_WAKEUP_STAT);
+		/* No need to perform below restore code */
+		return -1;
+	}
+
+	return 0;
+}
+
+/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
+static void exynos_set_wakeupmask(long mask)
+{
+	pmu_raw_writel(mask, S5P_WAKEUP_MASK);
+}
+
+static void exynos_cpu_set_boot_vector(long flags)
+{
+	__raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
+	__raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
+}
+
+static int exynos_aftr_finisher(unsigned long flags)
+{
+	exynos_set_wakeupmask(0x0000ff3e);
+	exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
+	/* Set value of power down register for aftr mode */
+	exynos_sys_powerdown_conf(SYS_AFTR);
+	cpu_do_idle();
+
+	return 1;
+}
+
+void exynos_enter_aftr(void)
+{
+	cpu_pm_enter();
+
+	exynos_pm_central_suspend();
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+		exynos_cpu_save_register();
+
+	cpu_suspend(0, exynos_aftr_finisher);
+
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
+		scu_enable(S5P_VA_SCU);
+		exynos_cpu_restore_register();
+	}
+
+	exynos_pm_central_resume();
+
+	cpu_pm_exit();
+}
+
 static int exynos_cpu_suspend(unsigned long arg)
 {
 #ifdef CONFIG_CACHE_L2X0
@@ -256,37 +250,27 @@ static void exynos_pm_prepare(void)
 	unsigned int tmp;
 
 	/* Set wake-up mask registers */
-	__raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
-	__raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
+	pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+	pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
 
 	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
 	if (soc_is_exynos5250()) {
 		s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
 		/* Disable USE_RETENTION of JPEG_MEM_OPTION */
-		tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
+		tmp = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
 		tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
-		__raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
+		pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
 	}
 
 	/* Set value of power down register for sleep mode */
 
 	exynos_sys_powerdown_conf(SYS_SLEEP);
-	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+	pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
 
 	/* ensure at least INFORM0 has the resume address */
 
-	__raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
-}
-
-static void exynos_pm_central_suspend(void)
-{
-	unsigned long tmp;
-
-	/* Setting Central Sequence Register for power down mode */
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
-	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+	pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
 }
 
 static int exynos_pm_suspend(void)
@@ -298,54 +282,31 @@ static int exynos_pm_suspend(void)
 	/* Setting SEQ_OPTION register */
 
 	tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
-	__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+	pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
 
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		exynos_cpu_save_register();
 
 	return 0;
 }
 
-static int exynos_pm_central_resume(void)
-{
-	unsigned long tmp;
-
-	/*
-	 * If PMU failed while entering sleep mode, WFI will be
-	 * ignored by PMU and then exiting cpu_do_idle().
-	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
-	 * in this situation.
-	 */
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
-		tmp |= S5P_CENTRAL_LOWPWR_CFG;
-		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-		/* clear the wakeup state register */
-		__raw_writel(0x0, S5P_WAKEUP_STAT);
-		/* No need to perform below restore code */
-		return -1;
-	}
-
-	return 0;
-}
-
 static void exynos_pm_resume(void)
 {
 	if (exynos_pm_central_resume())
 		goto early_wakeup;
 
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		exynos_cpu_restore_register();
 
 	/* For release retention */
 
-	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
-	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+	pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
 
 	if (soc_is_exynos5250())
 		s3c_pm_do_restore(exynos5_sys_save,
@@ -353,13 +314,13 @@ static void exynos_pm_resume(void)
 
 	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		scu_enable(S5P_VA_SCU);
 
 early_wakeup:
 
 	/* Clear SLEEP mode set in INFORM1 */
-	__raw_writel(0x0, S5P_INFORM1);
+	pmu_raw_writel(0x0, S5P_INFORM1);
 
 	return;
 }
@@ -403,7 +364,7 @@ static int exynos_suspend_enter(suspend_
 	s3c_pm_restore_uarts();
 
 	S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
-			__raw_readl(S5P_WAKEUP_STAT));
+			pmu_raw_readl(S5P_WAKEUP_STAT));
 
 	s3c_pm_check_restore();
 
@@ -431,52 +392,17 @@ static const struct platform_suspend_ops
 	.valid		= suspend_valid_only_mem,
 };
 
-static int exynos_cpu_pm_notifier(struct notifier_block *self,
-				  unsigned long cmd, void *v)
-{
-	int cpu = smp_processor_id();
-
-	switch (cmd) {
-	case CPU_PM_ENTER:
-		if (cpu == 0) {
-			exynos_pm_central_suspend();
-			if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
-				exynos_cpu_save_register();
-		}
-		break;
-
-	case CPU_PM_EXIT:
-		if (cpu == 0) {
-			if (read_cpuid_part_number() ==
-					ARM_CPU_PART_CORTEX_A9) {
-				scu_enable(S5P_VA_SCU);
-				exynos_cpu_restore_register();
-			}
-			exynos_pm_central_resume();
-		}
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block exynos_cpu_pm_notifier_block = {
-	.notifier_call = exynos_cpu_pm_notifier,
-};
-
 void __init exynos_pm_init(void)
 {
 	u32 tmp;
 
-	cpu_pm_register_notifier(&exynos_cpu_pm_notifier_block);
-
 	/* Platform-specific GIC callback */
 	gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
 
 	/* All wakeup disable */
-	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
 	tmp |= ((0xFF << 8) | (0x1F << 1));
-	__raw_writel(tmp, S5P_WAKEUP_MASK);
+	pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
 
 	register_syscore_ops(&exynos_pm_syscore_ops);
 	suspend_set_ops(&exynos_suspend_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/pm_domains.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pm_domains.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/pm_domains.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pm_domains.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,7 @@
 #include <linux/of_platform.h>
 #include <linux/sched.h>
 
-#include "regs-pmu.h"
-
+#define INT_LOCAL_PWR_EN	0x7
 #define MAX_CLK_PER_DOMAIN	4
 
 /*
@@ -63,13 +62,13 @@ static int exynos_pd_power(struct generi
 		}
 	}
 
-	pwr = power_on ? S5P_INT_LOCAL_PWR_EN : 0;
+	pwr = power_on ? INT_LOCAL_PWR_EN : 0;
 	__raw_writel(pwr, base);
 
 	/* Wait max 1ms */
 	timeout = 10;
 
-	while ((__raw_readl(base + 0x4) & S5P_INT_LOCAL_PWR_EN)	!= pwr) {
+	while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
 		if (!timeout) {
 			op = (power_on) ? "enable" : "disable";
 			pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -231,7 +230,7 @@ static __init int exynos4_pm_init_power_
 no_clk:
 		platform_set_drvdata(pdev, pd);
 
-		on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+		on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
 
 		pm_genpd_init(&pd->pd, NULL, !on);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/pmu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pmu.c
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,6 @@
 
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/bug.h>
 
 #include "common.h"
 #include "regs-pmu.h"
@@ -19,7 +18,7 @@
 static const struct exynos_pmu_conf *exynos_pmu_config;
 
 static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
-	/* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+	/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
 	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } },
 	{ S5P_DIS_IRQ_CORE0,			{ 0x0, 0x0, 0x0 } },
 	{ S5P_DIS_IRQ_CENTRAL0,			{ 0x0, 0x0, 0x0 } },
@@ -213,7 +212,7 @@ static const struct exynos_pmu_conf exyn
 };
 
 static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
-	/* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+	/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
 	{ EXYNOS5_ARM_CORE0_SYS_PWR_REG,		{ 0x0, 0x0, 0x2} },
 	{ EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} },
 	{ EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} },
@@ -316,7 +315,7 @@ static const struct exynos_pmu_conf exyn
 	{ PMU_TABLE_END,},
 };
 
-static void __iomem * const exynos5_list_both_cnt_feed[] = {
+static unsigned int const exynos5_list_both_cnt_feed[] = {
 	EXYNOS5_ARM_CORE0_OPTION,
 	EXYNOS5_ARM_CORE1_OPTION,
 	EXYNOS5_ARM_COMMON_OPTION,
@@ -330,7 +329,7 @@ static void __iomem * const exynos5_list
 	EXYNOS5_TOP_PWR_SYSMEM_OPTION,
 };
 
-static void __iomem * const exynos5_list_diable_wfi_wfe[] = {
+static unsigned int const exynos5_list_diable_wfi_wfe[] = {
 	EXYNOS5_ARM_CORE1_OPTION,
 	EXYNOS5_FSYS_ARM_OPTION,
 	EXYNOS5_ISP_ARM_OPTION,
@@ -345,27 +344,27 @@ static void exynos5_init_pmu(void)
 	 * Enable both SC_FEEDBACK and SC_COUNTER
 	 */
 	for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
-		tmp = __raw_readl(exynos5_list_both_cnt_feed[i]);
+		tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
 		tmp |= (EXYNOS5_USE_SC_FEEDBACK |
 			EXYNOS5_USE_SC_COUNTER);
-		__raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
+		pmu_raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
 	}
 
 	/*
 	 * SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
 	 */
-	tmp = __raw_readl(EXYNOS5_ARM_COMMON_OPTION);
+	tmp = pmu_raw_readl(EXYNOS5_ARM_COMMON_OPTION);
 	tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
-	__raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
+	pmu_raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
 
 	/*
 	 * Disable WFI/WFE on XXX_OPTION
 	 */
 	for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
-		tmp = __raw_readl(exynos5_list_diable_wfi_wfe[i]);
+		tmp = pmu_raw_readl(exynos5_list_diable_wfi_wfe[i]);
 		tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
 			 EXYNOS5_OPTION_USE_STANDBYWFI);
-		__raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
+		pmu_raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
 	}
 }
 
@@ -376,14 +375,14 @@ void exynos_sys_powerdown_conf(enum sys_
 	if (soc_is_exynos5250())
 		exynos5_init_pmu();
 
-	for (i = 0; (exynos_pmu_config[i].reg != PMU_TABLE_END) ; i++)
-		__raw_writel(exynos_pmu_config[i].val[mode],
-				exynos_pmu_config[i].reg);
+	for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
+		pmu_raw_writel(exynos_pmu_config[i].val[mode],
+				exynos_pmu_config[i].offset);
 
 	if (soc_is_exynos4412()) {
-		for (i = 0; exynos4412_pmu_config[i].reg != PMU_TABLE_END ; i++)
-			__raw_writel(exynos4412_pmu_config[i].val[mode],
-				exynos4412_pmu_config[i].reg);
+		for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++)
+			pmu_raw_writel(exynos4412_pmu_config[i].val[mode],
+					exynos4412_pmu_config[i].offset);
 	}
 }
 
@@ -404,13 +403,13 @@ static int __init exynos_pmu_init(void)
 		 * When SYS_WDTRESET is set, watchdog timer reset request
 		 * is ignored by power management unit.
 		 */
-		value = __raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+		value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
 		value &= ~EXYNOS5_SYS_WDTRESET;
-		__raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+		pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
 
-		value = __raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+		value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
 		value &= ~EXYNOS5_SYS_WDTRESET;
-		__raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+		pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
 
 		exynos_pmu_config = exynos5250_pmu_config;
 		pr_info("EXYNOS5250 PMU Initialize\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/regs-pmu.h linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/regs-pmu.h
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/regs-pmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/regs-pmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,304 +12,298 @@
 #ifndef __ASM_ARCH_REGS_PMU_H
 #define __ASM_ARCH_REGS_PMU_H __FILE__
 
-#include <mach/map.h>
-
-#define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
-#define S5P_SYSREG(x)				(S3C_VA_SYS + (x))
-
-#define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
+#define S5P_CENTRAL_SEQ_CONFIGURATION		0x0200
 
 #define S5P_CENTRAL_LOWPWR_CFG			(1 << 16)
 
-#define S5P_CENTRAL_SEQ_OPTION			S5P_PMUREG(0x0208)
+#define S5P_CENTRAL_SEQ_OPTION			0x0208
 
 #define S5P_USE_STANDBY_WFI0			(1 << 16)
 #define S5P_USE_STANDBY_WFE0			(1 << 24)
 
-#define EXYNOS_SWRESET				S5P_PMUREG(0x0400)
-#define EXYNOS5440_SWRESET			S5P_PMUREG(0x00C4)
+#define EXYNOS_SWRESET				0x0400
+#define EXYNOS5440_SWRESET			0x00C4
 
-#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
-#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
-#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
+#define S5P_WAKEUP_STAT				0x0600
+#define S5P_EINT_WAKEUP_MASK			0x0604
+#define S5P_WAKEUP_MASK				0x0608
 
-#define S5P_INFORM0				S5P_PMUREG(0x0800)
-#define S5P_INFORM1				S5P_PMUREG(0x0804)
-#define S5P_INFORM5				S5P_PMUREG(0x0814)
-#define S5P_INFORM6				S5P_PMUREG(0x0818)
-#define S5P_INFORM7				S5P_PMUREG(0x081C)
-#define S5P_PMU_SPARE3				S5P_PMUREG(0x090C)
+#define S5P_INFORM0				0x0800
+#define S5P_INFORM1				0x0804
+#define S5P_INFORM5				0x0814
+#define S5P_INFORM6				0x0818
+#define S5P_INFORM7				0x081C
+#define S5P_PMU_SPARE3				0x090C
 
-#define S5P_ARM_CORE0_LOWPWR			S5P_PMUREG(0x1000)
-#define S5P_DIS_IRQ_CORE0			S5P_PMUREG(0x1004)
-#define S5P_DIS_IRQ_CENTRAL0			S5P_PMUREG(0x1008)
-#define S5P_ARM_CORE1_LOWPWR			S5P_PMUREG(0x1010)
-#define S5P_DIS_IRQ_CORE1			S5P_PMUREG(0x1014)
-#define S5P_DIS_IRQ_CENTRAL1			S5P_PMUREG(0x1018)
-#define S5P_ARM_COMMON_LOWPWR			S5P_PMUREG(0x1080)
-#define S5P_L2_0_LOWPWR				S5P_PMUREG(0x10C0)
-#define S5P_L2_1_LOWPWR				S5P_PMUREG(0x10C4)
-#define S5P_CMU_ACLKSTOP_LOWPWR			S5P_PMUREG(0x1100)
-#define S5P_CMU_SCLKSTOP_LOWPWR			S5P_PMUREG(0x1104)
-#define S5P_CMU_RESET_LOWPWR			S5P_PMUREG(0x110C)
-#define S5P_APLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1120)
-#define S5P_MPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1124)
-#define S5P_VPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1128)
-#define S5P_EPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x112C)
-#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	S5P_PMUREG(0x1138)
-#define S5P_CMU_RESET_GPSALIVE_LOWPWR		S5P_PMUREG(0x113C)
-#define S5P_CMU_CLKSTOP_CAM_LOWPWR		S5P_PMUREG(0x1140)
-#define S5P_CMU_CLKSTOP_TV_LOWPWR		S5P_PMUREG(0x1144)
-#define S5P_CMU_CLKSTOP_MFC_LOWPWR		S5P_PMUREG(0x1148)
-#define S5P_CMU_CLKSTOP_G3D_LOWPWR		S5P_PMUREG(0x114C)
-#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		S5P_PMUREG(0x1158)
-#define S5P_CMU_CLKSTOP_GPS_LOWPWR		S5P_PMUREG(0x115C)
-#define S5P_CMU_RESET_CAM_LOWPWR		S5P_PMUREG(0x1160)
-#define S5P_CMU_RESET_TV_LOWPWR			S5P_PMUREG(0x1164)
-#define S5P_CMU_RESET_MFC_LOWPWR		S5P_PMUREG(0x1168)
-#define S5P_CMU_RESET_G3D_LOWPWR		S5P_PMUREG(0x116C)
-#define S5P_CMU_RESET_LCD0_LOWPWR		S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_MAUDIO_LOWPWR		S5P_PMUREG(0x1178)
-#define S5P_CMU_RESET_GPS_LOWPWR		S5P_PMUREG(0x117C)
-#define S5P_TOP_BUS_LOWPWR			S5P_PMUREG(0x1180)
-#define S5P_TOP_RETENTION_LOWPWR		S5P_PMUREG(0x1184)
-#define S5P_TOP_PWR_LOWPWR			S5P_PMUREG(0x1188)
-#define S5P_LOGIC_RESET_LOWPWR			S5P_PMUREG(0x11A0)
-#define S5P_ONENAND_MEM_LOWPWR			S5P_PMUREG(0x11C0)
-#define S5P_G2D_ACP_MEM_LOWPWR			S5P_PMUREG(0x11C8)
-#define S5P_USBOTG_MEM_LOWPWR			S5P_PMUREG(0x11CC)
-#define S5P_HSMMC_MEM_LOWPWR			S5P_PMUREG(0x11D0)
-#define S5P_CSSYS_MEM_LOWPWR			S5P_PMUREG(0x11D4)
-#define S5P_SECSS_MEM_LOWPWR			S5P_PMUREG(0x11D8)
-#define S5P_PAD_RETENTION_DRAM_LOWPWR		S5P_PMUREG(0x1200)
-#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		S5P_PMUREG(0x1204)
-#define S5P_PAD_RETENTION_GPIO_LOWPWR		S5P_PMUREG(0x1220)
-#define S5P_PAD_RETENTION_UART_LOWPWR		S5P_PMUREG(0x1224)
-#define S5P_PAD_RETENTION_MMCA_LOWPWR		S5P_PMUREG(0x1228)
-#define S5P_PAD_RETENTION_MMCB_LOWPWR		S5P_PMUREG(0x122C)
-#define S5P_PAD_RETENTION_EBIA_LOWPWR		S5P_PMUREG(0x1230)
-#define S5P_PAD_RETENTION_EBIB_LOWPWR		S5P_PMUREG(0x1234)
-#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	S5P_PMUREG(0x1240)
-#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	S5P_PMUREG(0x1260)
-#define S5P_XUSBXTI_LOWPWR			S5P_PMUREG(0x1280)
-#define S5P_XXTI_LOWPWR				S5P_PMUREG(0x1284)
-#define S5P_EXT_REGULATOR_LOWPWR		S5P_PMUREG(0x12C0)
-#define S5P_GPIO_MODE_LOWPWR			S5P_PMUREG(0x1300)
-#define S5P_GPIO_MODE_MAUDIO_LOWPWR		S5P_PMUREG(0x1340)
-#define S5P_CAM_LOWPWR				S5P_PMUREG(0x1380)
-#define S5P_TV_LOWPWR				S5P_PMUREG(0x1384)
-#define S5P_MFC_LOWPWR				S5P_PMUREG(0x1388)
-#define S5P_G3D_LOWPWR				S5P_PMUREG(0x138C)
-#define S5P_LCD0_LOWPWR				S5P_PMUREG(0x1390)
-#define S5P_MAUDIO_LOWPWR			S5P_PMUREG(0x1398)
-#define S5P_GPS_LOWPWR				S5P_PMUREG(0x139C)
-#define S5P_GPS_ALIVE_LOWPWR			S5P_PMUREG(0x13A0)
+#define S5P_ARM_CORE0_LOWPWR			0x1000
+#define S5P_DIS_IRQ_CORE0			0x1004
+#define S5P_DIS_IRQ_CENTRAL0			0x1008
+#define S5P_ARM_CORE1_LOWPWR			0x1010
+#define S5P_DIS_IRQ_CORE1			0x1014
+#define S5P_DIS_IRQ_CENTRAL1			0x1018
+#define S5P_ARM_COMMON_LOWPWR			0x1080
+#define S5P_L2_0_LOWPWR				0x10C0
+#define S5P_L2_1_LOWPWR				0x10C4
+#define S5P_CMU_ACLKSTOP_LOWPWR			0x1100
+#define S5P_CMU_SCLKSTOP_LOWPWR			0x1104
+#define S5P_CMU_RESET_LOWPWR			0x110C
+#define S5P_APLL_SYSCLK_LOWPWR			0x1120
+#define S5P_MPLL_SYSCLK_LOWPWR			0x1124
+#define S5P_VPLL_SYSCLK_LOWPWR			0x1128
+#define S5P_EPLL_SYSCLK_LOWPWR			0x112C
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	0x1138
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR		0x113C
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR		0x1140
+#define S5P_CMU_CLKSTOP_TV_LOWPWR		0x1144
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR		0x1148
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR		0x114C
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		0x1150
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		0x1158
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR		0x115C
+#define S5P_CMU_RESET_CAM_LOWPWR		0x1160
+#define S5P_CMU_RESET_TV_LOWPWR			0x1164
+#define S5P_CMU_RESET_MFC_LOWPWR		0x1168
+#define S5P_CMU_RESET_G3D_LOWPWR		0x116C
+#define S5P_CMU_RESET_LCD0_LOWPWR		0x1170
+#define S5P_CMU_RESET_MAUDIO_LOWPWR		0x1178
+#define S5P_CMU_RESET_GPS_LOWPWR		0x117C
+#define S5P_TOP_BUS_LOWPWR			0x1180
+#define S5P_TOP_RETENTION_LOWPWR		0x1184
+#define S5P_TOP_PWR_LOWPWR			0x1188
+#define S5P_LOGIC_RESET_LOWPWR			0x11A0
+#define S5P_ONENAND_MEM_LOWPWR			0x11C0
+#define S5P_G2D_ACP_MEM_LOWPWR			0x11C8
+#define S5P_USBOTG_MEM_LOWPWR			0x11CC
+#define S5P_HSMMC_MEM_LOWPWR			0x11D0
+#define S5P_CSSYS_MEM_LOWPWR			0x11D4
+#define S5P_SECSS_MEM_LOWPWR			0x11D8
+#define S5P_PAD_RETENTION_DRAM_LOWPWR		0x1200
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		0x1204
+#define S5P_PAD_RETENTION_GPIO_LOWPWR		0x1220
+#define S5P_PAD_RETENTION_UART_LOWPWR		0x1224
+#define S5P_PAD_RETENTION_MMCA_LOWPWR		0x1228
+#define S5P_PAD_RETENTION_MMCB_LOWPWR		0x122C
+#define S5P_PAD_RETENTION_EBIA_LOWPWR		0x1230
+#define S5P_PAD_RETENTION_EBIB_LOWPWR		0x1234
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	0x1240
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	0x1260
+#define S5P_XUSBXTI_LOWPWR			0x1280
+#define S5P_XXTI_LOWPWR				0x1284
+#define S5P_EXT_REGULATOR_LOWPWR		0x12C0
+#define S5P_GPIO_MODE_LOWPWR			0x1300
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR		0x1340
+#define S5P_CAM_LOWPWR				0x1380
+#define S5P_TV_LOWPWR				0x1384
+#define S5P_MFC_LOWPWR				0x1388
+#define S5P_G3D_LOWPWR				0x138C
+#define S5P_LCD0_LOWPWR				0x1390
+#define S5P_MAUDIO_LOWPWR			0x1398
+#define S5P_GPS_LOWPWR				0x139C
+#define S5P_GPS_ALIVE_LOWPWR			0x13A0
 
-#define EXYNOS_ARM_CORE0_CONFIGURATION		S5P_PMUREG(0x2000)
+#define EXYNOS_ARM_CORE0_CONFIGURATION		0x2000
 #define EXYNOS_ARM_CORE_CONFIGURATION(_nr)	\
 			(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
 #define EXYNOS_ARM_CORE_STATUS(_nr)		\
 			(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
 
-#define EXYNOS_ARM_COMMON_CONFIGURATION		S5P_PMUREG(0x2500)
+#define EXYNOS_ARM_COMMON_CONFIGURATION		0x2500
 #define EXYNOS_COMMON_CONFIGURATION(_nr)	\
 			(EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr)))
 #define EXYNOS_COMMON_STATUS(_nr)		\
 			(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4)
+#define EXYNOS_COMMON_OPTION(_nr)		\
+			(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
 
-#define S5P_PAD_RET_MAUDIO_OPTION		S5P_PMUREG(0x3028)
-#define S5P_PAD_RET_GPIO_OPTION			S5P_PMUREG(0x3108)
-#define S5P_PAD_RET_UART_OPTION			S5P_PMUREG(0x3128)
-#define S5P_PAD_RET_MMCA_OPTION			S5P_PMUREG(0x3148)
-#define S5P_PAD_RET_MMCB_OPTION			S5P_PMUREG(0x3168)
-#define S5P_PAD_RET_EBIA_OPTION			S5P_PMUREG(0x3188)
-#define S5P_PAD_RET_EBIB_OPTION			S5P_PMUREG(0x31A8)
+#define S5P_PAD_RET_MAUDIO_OPTION		0x3028
+#define S5P_PAD_RET_GPIO_OPTION			0x3108
+#define S5P_PAD_RET_UART_OPTION			0x3128
+#define S5P_PAD_RET_MMCA_OPTION			0x3148
+#define S5P_PAD_RET_MMCB_OPTION			0x3168
+#define S5P_PAD_RET_EBIA_OPTION			0x3188
+#define S5P_PAD_RET_EBIB_OPTION			0x31A8
 
 #define S5P_CORE_LOCAL_PWR_EN			0x3
-#define S5P_INT_LOCAL_PWR_EN			0x7
 
 /* Only for EXYNOS4210 */
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR	S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_LCD1_LOWPWR	S5P_PMUREG(0x1174)
-#define S5P_MODIMIF_MEM_LOWPWR		S5P_PMUREG(0x11C4)
-#define S5P_PCIE_MEM_LOWPWR		S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR		S5P_PMUREG(0x11E4)
-#define S5P_LCD1_LOWPWR			S5P_PMUREG(0x1394)
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR	0x1154
+#define S5P_CMU_RESET_LCD1_LOWPWR	0x1174
+#define S5P_MODIMIF_MEM_LOWPWR		0x11C4
+#define S5P_PCIE_MEM_LOWPWR		0x11E0
+#define S5P_SATA_MEM_LOWPWR		0x11E4
+#define S5P_LCD1_LOWPWR			0x1394
 
 /* Only for EXYNOS4x12 */
-#define S5P_ISP_ARM_LOWPWR			S5P_PMUREG(0x1050)
-#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR	S5P_PMUREG(0x1054)
-#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR	S5P_PMUREG(0x1058)
-#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1110)
-#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1114)
-#define S5P_CMU_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x111C)
-#define S5P_MPLLUSER_SYSCLK_LOWPWR		S5P_PMUREG(0x1130)
-#define S5P_CMU_CLKSTOP_ISP_LOWPWR		S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_ISP_LOWPWR		S5P_PMUREG(0x1174)
-#define S5P_TOP_BUS_COREBLK_LOWPWR		S5P_PMUREG(0x1190)
-#define S5P_TOP_RETENTION_COREBLK_LOWPWR	S5P_PMUREG(0x1194)
-#define S5P_TOP_PWR_COREBLK_LOWPWR		S5P_PMUREG(0x1198)
-#define S5P_OSCCLK_GATE_LOWPWR			S5P_PMUREG(0x11A4)
-#define S5P_LOGIC_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x11B0)
-#define S5P_OSCCLK_GATE_COREBLK_LOWPWR		S5P_PMUREG(0x11B4)
-#define S5P_HSI_MEM_LOWPWR			S5P_PMUREG(0x11C4)
-#define S5P_ROTATOR_MEM_LOWPWR			S5P_PMUREG(0x11DC)
-#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR	S5P_PMUREG(0x123C)
-#define S5P_PAD_ISOLATION_COREBLK_LOWPWR	S5P_PMUREG(0x1250)
-#define S5P_GPIO_MODE_COREBLK_LOWPWR		S5P_PMUREG(0x1320)
-#define S5P_TOP_ASB_RESET_LOWPWR		S5P_PMUREG(0x1344)
-#define S5P_TOP_ASB_ISOLATION_LOWPWR		S5P_PMUREG(0x1348)
-#define S5P_ISP_LOWPWR				S5P_PMUREG(0x1394)
-#define S5P_DRAM_FREQ_DOWN_LOWPWR		S5P_PMUREG(0x13B0)
-#define S5P_DDRPHY_DLLOFF_LOWPWR		S5P_PMUREG(0x13B4)
-#define S5P_CMU_SYSCLK_ISP_LOWPWR		S5P_PMUREG(0x13B8)
-#define S5P_CMU_SYSCLK_GPS_LOWPWR		S5P_PMUREG(0x13BC)
-#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR		S5P_PMUREG(0x13C0)
+#define S5P_ISP_ARM_LOWPWR			0x1050
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR	0x1054
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR	0x1058
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR		0x1110
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR		0x1114
+#define S5P_CMU_RESET_COREBLK_LOWPWR		0x111C
+#define S5P_MPLLUSER_SYSCLK_LOWPWR		0x1130
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR		0x1154
+#define S5P_CMU_RESET_ISP_LOWPWR		0x1174
+#define S5P_TOP_BUS_COREBLK_LOWPWR		0x1190
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR	0x1194
+#define S5P_TOP_PWR_COREBLK_LOWPWR		0x1198
+#define S5P_OSCCLK_GATE_LOWPWR			0x11A4
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR		0x11B0
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR		0x11B4
+#define S5P_HSI_MEM_LOWPWR			0x11C4
+#define S5P_ROTATOR_MEM_LOWPWR			0x11DC
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR	0x123C
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR	0x1250
+#define S5P_GPIO_MODE_COREBLK_LOWPWR		0x1320
+#define S5P_TOP_ASB_RESET_LOWPWR		0x1344
+#define S5P_TOP_ASB_ISOLATION_LOWPWR		0x1348
+#define S5P_ISP_LOWPWR				0x1394
+#define S5P_DRAM_FREQ_DOWN_LOWPWR		0x13B0
+#define S5P_DDRPHY_DLLOFF_LOWPWR		0x13B4
+#define S5P_CMU_SYSCLK_ISP_LOWPWR		0x13B8
+#define S5P_CMU_SYSCLK_GPS_LOWPWR		0x13BC
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR		0x13C0
 
-#define S5P_ARM_L2_0_OPTION			S5P_PMUREG(0x2608)
-#define S5P_ARM_L2_1_OPTION			S5P_PMUREG(0x2628)
-#define S5P_ONENAND_MEM_OPTION			S5P_PMUREG(0x2E08)
-#define S5P_HSI_MEM_OPTION			S5P_PMUREG(0x2E28)
-#define S5P_G2D_ACP_MEM_OPTION			S5P_PMUREG(0x2E48)
-#define S5P_USBOTG_MEM_OPTION			S5P_PMUREG(0x2E68)
-#define S5P_HSMMC_MEM_OPTION			S5P_PMUREG(0x2E88)
-#define S5P_CSSYS_MEM_OPTION			S5P_PMUREG(0x2EA8)
-#define S5P_SECSS_MEM_OPTION			S5P_PMUREG(0x2EC8)
-#define S5P_ROTATOR_MEM_OPTION			S5P_PMUREG(0x2F48)
+#define S5P_ARM_L2_0_OPTION			0x2608
+#define S5P_ARM_L2_1_OPTION			0x2628
+#define S5P_ONENAND_MEM_OPTION			0x2E08
+#define S5P_HSI_MEM_OPTION			0x2E28
+#define S5P_G2D_ACP_MEM_OPTION			0x2E48
+#define S5P_USBOTG_MEM_OPTION			0x2E68
+#define S5P_HSMMC_MEM_OPTION			0x2E88
+#define S5P_CSSYS_MEM_OPTION			0x2EA8
+#define S5P_SECSS_MEM_OPTION			0x2EC8
+#define S5P_ROTATOR_MEM_OPTION			0x2F48
 
 /* Only for EXYNOS4412 */
-#define S5P_ARM_CORE2_LOWPWR			S5P_PMUREG(0x1020)
-#define S5P_DIS_IRQ_CORE2			S5P_PMUREG(0x1024)
-#define S5P_DIS_IRQ_CENTRAL2			S5P_PMUREG(0x1028)
-#define S5P_ARM_CORE3_LOWPWR			S5P_PMUREG(0x1030)
-#define S5P_DIS_IRQ_CORE3			S5P_PMUREG(0x1034)
-#define S5P_DIS_IRQ_CENTRAL3			S5P_PMUREG(0x1038)
+#define S5P_ARM_CORE2_LOWPWR			0x1020
+#define S5P_DIS_IRQ_CORE2			0x1024
+#define S5P_DIS_IRQ_CENTRAL2			0x1028
+#define S5P_ARM_CORE3_LOWPWR			0x1030
+#define S5P_DIS_IRQ_CORE3			0x1034
+#define S5P_DIS_IRQ_CENTRAL3			0x1038
 
 /* For EXYNOS5 */
 
-#define EXYNOS5_SYS_I2C_CFG					S5P_SYSREG(0x0234)
-
-#define EXYNOS5_AUTO_WDTRESET_DISABLE				S5P_PMUREG(0x0408)
-#define EXYNOS5_MASK_WDTRESET_REQUEST				S5P_PMUREG(0x040C)
+#define EXYNOS5_AUTO_WDTRESET_DISABLE				0x0408
+#define EXYNOS5_MASK_WDTRESET_REQUEST				0x040C
 
 #define EXYNOS5_SYS_WDTRESET					(1 << 20)
 
-#define EXYNOS5_ARM_CORE0_SYS_PWR_REG				S5P_PMUREG(0x1000)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG		S5P_PMUREG(0x1004)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG		S5P_PMUREG(0x1008)
-#define EXYNOS5_ARM_CORE1_SYS_PWR_REG				S5P_PMUREG(0x1010)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG		S5P_PMUREG(0x1014)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG		S5P_PMUREG(0x1018)
-#define EXYNOS5_FSYS_ARM_SYS_PWR_REG				S5P_PMUREG(0x1040)
-#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG		S5P_PMUREG(0x1048)
-#define EXYNOS5_ISP_ARM_SYS_PWR_REG				S5P_PMUREG(0x1050)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG		S5P_PMUREG(0x1054)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG		S5P_PMUREG(0x1058)
-#define EXYNOS5_ARM_COMMON_SYS_PWR_REG				S5P_PMUREG(0x1080)
-#define EXYNOS5_ARM_L2_SYS_PWR_REG				S5P_PMUREG(0x10C0)
-#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG			S5P_PMUREG(0x1100)
-#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG			S5P_PMUREG(0x1104)
-#define EXYNOS5_CMU_RESET_SYS_PWR_REG				S5P_PMUREG(0x110C)
-#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x1120)
-#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x1124)
-#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x112C)
-#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG			S5P_PMUREG(0x1130)
-#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG			S5P_PMUREG(0x1134)
-#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG			S5P_PMUREG(0x1138)
-#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x1140)
-#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x1144)
-#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x1148)
-#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x114C)
-#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x1150)
-#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG				S5P_PMUREG(0x1154)
-#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG			S5P_PMUREG(0x1164)
-#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG			S5P_PMUREG(0x1170)
-#define EXYNOS5_TOP_BUS_SYS_PWR_REG				S5P_PMUREG(0x1180)
-#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG			S5P_PMUREG(0x1184)
-#define EXYNOS5_TOP_PWR_SYS_PWR_REG				S5P_PMUREG(0x1188)
-#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x1190)
-#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG		S5P_PMUREG(0x1194)
-#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x1198)
-#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG				S5P_PMUREG(0x11A0)
-#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG				S5P_PMUREG(0x11A4)
-#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x11B0)
-#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x11B4)
-#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG				S5P_PMUREG(0x11C0)
-#define EXYNOS5_G2D_MEM_SYS_PWR_REG				S5P_PMUREG(0x11C8)
-#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG				S5P_PMUREG(0x11CC)
-#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG				S5P_PMUREG(0x11D0)
-#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG				S5P_PMUREG(0x11D4)
-#define EXYNOS5_SECSS_MEM_SYS_PWR_REG				S5P_PMUREG(0x11D8)
-#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG				S5P_PMUREG(0x11DC)
-#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG				S5P_PMUREG(0x11E0)
-#define EXYNOS5_INTROM_MEM_SYS_PWR_REG				S5P_PMUREG(0x11E4)
-#define EXYNOS5_JPEG_MEM_SYS_PWR_REG				S5P_PMUREG(0x11E8)
-#define EXYNOS5_HSI_MEM_SYS_PWR_REG				S5P_PMUREG(0x11EC)
-#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG				S5P_PMUREG(0x11F4)
-#define EXYNOS5_SATA_MEM_SYS_PWR_REG				S5P_PMUREG(0x11FC)
-#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG			S5P_PMUREG(0x1200)
-#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG			S5P_PMUREG(0x1204)
-#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG		S5P_PMUREG(0x1208)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG			S5P_PMUREG(0x1220)
-#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG			S5P_PMUREG(0x1224)
-#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG			S5P_PMUREG(0x1228)
-#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG			S5P_PMUREG(0x122C)
-#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG			S5P_PMUREG(0x1230)
-#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG			S5P_PMUREG(0x1234)
-#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG			S5P_PMUREG(0x1238)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG		S5P_PMUREG(0x123C)
-#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG			S5P_PMUREG(0x1240)
-#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG		S5P_PMUREG(0x1250)
-#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG				S5P_PMUREG(0x1260)
-#define EXYNOS5_XUSBXTI_SYS_PWR_REG				S5P_PMUREG(0x1280)
-#define EXYNOS5_XXTI_SYS_PWR_REG				S5P_PMUREG(0x1284)
-#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG			S5P_PMUREG(0x12C0)
-#define EXYNOS5_GPIO_MODE_SYS_PWR_REG				S5P_PMUREG(0x1300)
-#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG			S5P_PMUREG(0x1320)
-#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG			S5P_PMUREG(0x1340)
-#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG			S5P_PMUREG(0x1344)
-#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG			S5P_PMUREG(0x1348)
-#define EXYNOS5_GSCL_SYS_PWR_REG				S5P_PMUREG(0x1400)
-#define EXYNOS5_ISP_SYS_PWR_REG					S5P_PMUREG(0x1404)
-#define EXYNOS5_MFC_SYS_PWR_REG					S5P_PMUREG(0x1408)
-#define EXYNOS5_G3D_SYS_PWR_REG					S5P_PMUREG(0x140C)
-#define EXYNOS5_DISP1_SYS_PWR_REG				S5P_PMUREG(0x1414)
-#define EXYNOS5_MAU_SYS_PWR_REG					S5P_PMUREG(0x1418)
-#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG			S5P_PMUREG(0x1480)
-#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG			S5P_PMUREG(0x1484)
-#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG			S5P_PMUREG(0x1488)
-#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG			S5P_PMUREG(0x148C)
-#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG			S5P_PMUREG(0x1494)
-#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG			S5P_PMUREG(0x1498)
-#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG			S5P_PMUREG(0x14C0)
-#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG			S5P_PMUREG(0x14C4)
-#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG			S5P_PMUREG(0x14C8)
-#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG			S5P_PMUREG(0x14CC)
-#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG			S5P_PMUREG(0x14D4)
-#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG			S5P_PMUREG(0x14D8)
-#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG			S5P_PMUREG(0x1580)
-#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG			S5P_PMUREG(0x1584)
-#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG			S5P_PMUREG(0x1588)
-#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG			S5P_PMUREG(0x158C)
-#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG			S5P_PMUREG(0x1594)
-#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG			S5P_PMUREG(0x1598)
+#define EXYNOS5_ARM_CORE0_SYS_PWR_REG				0x1000
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG		0x1004
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG		0x1008
+#define EXYNOS5_ARM_CORE1_SYS_PWR_REG				0x1010
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG		0x1014
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG		0x1018
+#define EXYNOS5_FSYS_ARM_SYS_PWR_REG				0x1040
+#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG		0x1048
+#define EXYNOS5_ISP_ARM_SYS_PWR_REG				0x1050
+#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG		0x1054
+#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG		0x1058
+#define EXYNOS5_ARM_COMMON_SYS_PWR_REG				0x1080
+#define EXYNOS5_ARM_L2_SYS_PWR_REG				0x10C0
+#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG			0x1100
+#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG			0x1104
+#define EXYNOS5_CMU_RESET_SYS_PWR_REG				0x110C
+#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG			0x1120
+#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG			0x1124
+#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG			0x112C
+#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG			0x1130
+#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG			0x1134
+#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG			0x1138
+#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG				0x1140
+#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG				0x1144
+#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG				0x1148
+#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG				0x114C
+#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG				0x1150
+#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG				0x1154
+#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG			0x1164
+#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG			0x1170
+#define EXYNOS5_TOP_BUS_SYS_PWR_REG				0x1180
+#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG			0x1184
+#define EXYNOS5_TOP_PWR_SYS_PWR_REG				0x1188
+#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG			0x1190
+#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG		0x1194
+#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG			0x1198
+#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG				0x11A0
+#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG				0x11A4
+#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG			0x11B0
+#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG			0x11B4
+#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG				0x11C0
+#define EXYNOS5_G2D_MEM_SYS_PWR_REG				0x11C8
+#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG				0x11CC
+#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG				0x11D0
+#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG				0x11D4
+#define EXYNOS5_SECSS_MEM_SYS_PWR_REG				0x11D8
+#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG				0x11DC
+#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG				0x11E0
+#define EXYNOS5_INTROM_MEM_SYS_PWR_REG				0x11E4
+#define EXYNOS5_JPEG_MEM_SYS_PWR_REG				0x11E8
+#define EXYNOS5_HSI_MEM_SYS_PWR_REG				0x11EC
+#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG				0x11F4
+#define EXYNOS5_SATA_MEM_SYS_PWR_REG				0x11FC
+#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG			0x1200
+#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG			0x1204
+#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG		0x1208
+#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG			0x1220
+#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG			0x1224
+#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG			0x1228
+#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG			0x122C
+#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG			0x1230
+#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG			0x1234
+#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG			0x1238
+#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG		0x123C
+#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG			0x1240
+#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG		0x1250
+#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG				0x1260
+#define EXYNOS5_XUSBXTI_SYS_PWR_REG				0x1280
+#define EXYNOS5_XXTI_SYS_PWR_REG				0x1284
+#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG			0x12C0
+#define EXYNOS5_GPIO_MODE_SYS_PWR_REG				0x1300
+#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG			0x1320
+#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG			0x1340
+#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG			0x1344
+#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG			0x1348
+#define EXYNOS5_GSCL_SYS_PWR_REG				0x1400
+#define EXYNOS5_ISP_SYS_PWR_REG					0x1404
+#define EXYNOS5_MFC_SYS_PWR_REG					0x1408
+#define EXYNOS5_G3D_SYS_PWR_REG					0x140C
+#define EXYNOS5_DISP1_SYS_PWR_REG				0x1414
+#define EXYNOS5_MAU_SYS_PWR_REG					0x1418
+#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG			0x1480
+#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG			0x1484
+#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG			0x1488
+#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG			0x148C
+#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG			0x1494
+#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG			0x1498
+#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG			0x14C0
+#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG			0x14C4
+#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG			0x14C8
+#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG			0x14CC
+#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG			0x14D4
+#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG			0x14D8
+#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG			0x1580
+#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG			0x1584
+#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG			0x1588
+#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG			0x158C
+#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG			0x1594
+#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG			0x1598
 
-#define EXYNOS5_ARM_CORE0_OPTION				S5P_PMUREG(0x2008)
-#define EXYNOS5_ARM_CORE1_OPTION				S5P_PMUREG(0x2088)
-#define EXYNOS5_FSYS_ARM_OPTION					S5P_PMUREG(0x2208)
-#define EXYNOS5_ISP_ARM_OPTION					S5P_PMUREG(0x2288)
-#define EXYNOS5_ARM_COMMON_OPTION				S5P_PMUREG(0x2408)
-#define EXYNOS5_ARM_L2_OPTION					S5P_PMUREG(0x2608)
-#define EXYNOS5_TOP_PWR_OPTION					S5P_PMUREG(0x2C48)
-#define EXYNOS5_TOP_PWR_SYSMEM_OPTION				S5P_PMUREG(0x2CC8)
-#define EXYNOS5_JPEG_MEM_OPTION					S5P_PMUREG(0x2F48)
-#define EXYNOS5_GSCL_OPTION					S5P_PMUREG(0x4008)
-#define EXYNOS5_ISP_OPTION					S5P_PMUREG(0x4028)
-#define EXYNOS5_MFC_OPTION					S5P_PMUREG(0x4048)
-#define EXYNOS5_G3D_OPTION					S5P_PMUREG(0x4068)
-#define EXYNOS5_DISP1_OPTION					S5P_PMUREG(0x40A8)
-#define EXYNOS5_MAU_OPTION					S5P_PMUREG(0x40C8)
+#define EXYNOS5_ARM_CORE0_OPTION				0x2008
+#define EXYNOS5_ARM_CORE1_OPTION				0x2088
+#define EXYNOS5_FSYS_ARM_OPTION					0x2208
+#define EXYNOS5_ISP_ARM_OPTION					0x2288
+#define EXYNOS5_ARM_COMMON_OPTION				0x2408
+#define EXYNOS5_ARM_L2_OPTION					0x2608
+#define EXYNOS5_TOP_PWR_OPTION					0x2C48
+#define EXYNOS5_TOP_PWR_SYSMEM_OPTION				0x2CC8
+#define EXYNOS5_JPEG_MEM_OPTION					0x2F48
+#define EXYNOS5_GSCL_OPTION					0x4008
+#define EXYNOS5_ISP_OPTION					0x4028
+#define EXYNOS5_MFC_OPTION					0x4048
+#define EXYNOS5_G3D_OPTION					0x4068
+#define EXYNOS5_DISP1_OPTION					0x40A8
+#define EXYNOS5_MAU_OPTION					0x40C8
 
 #define EXYNOS5_USE_SC_FEEDBACK					(1 << 1)
 #define EXYNOS5_USE_SC_COUNTER					(1 << 0)
@@ -323,4 +317,13 @@
 
 #define EXYNOS5420_SWRESET_KFC_SEL				0x3
 
+#include <asm/cputype.h>
+#define MAX_CPUS_IN_CLUSTER	4
+
+static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
+{
+	return ((MPIDR_AFFINITY_LEVEL(mpidr, 1) * MAX_CPUS_IN_CLUSTER)
+		 + MPIDR_AFFINITY_LEVEL(mpidr, 0));
+}
+
 #endif /* __ASM_ARCH_REGS_PMU_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-exynos/regs-sys.h linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/regs-sys.h
--- linux-libre-3.16-gnu/arch/arm/mach-exynos/regs-sys.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-exynos/regs-sys.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * EXYNOS - system register definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SYS_H
+#define __ASM_ARCH_REGS_SYS_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SYSREG(x)                          (S3C_VA_SYS + (x))
+
+/* For EXYNOS5 */
+#define EXYNOS5_SYS_I2C_CFG                    S5P_SYSREG(0x0234)
+
+#endif /* __ASM_ARCH_REGS_SYS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-footbridge/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-footbridge/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-footbridge/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-footbridge/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -59,11 +59,6 @@ extern unsigned long __bus_to_pfn(unsign
  */
 #define FLUSH_BASE		0xf9000000
 
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
 #define FLUSH_BASE_PHYS		0x50000000
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-highbank/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-highbank/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-highbank/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-highbank/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,6 @@ config ARCH_HIGHBANK
 	bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	select ARCH_HAS_HOLES_MEMORYMODEL
-	select ARCH_HAS_OPP
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_ERRATA_764369 if SMP
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/core.h linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/core.h
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/core.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,4 +12,9 @@ extern void hi3xxx_cpu_die(unsigned int
 extern int hi3xxx_cpu_kill(unsigned int cpu);
 extern void hi3xxx_set_cpu(int cpu, bool enable);
 
+extern void hix5hd2_secondary_startup(void);
+extern struct smp_operations hix5hd2_smp_ops;
+extern void hix5hd2_set_cpu(int cpu, bool enable);
+extern void hix5hd2_cpu_die(unsigned int cpu);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/headsmp.S linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/headsmp.S
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/headsmp.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2014 Hisilicon Limited.
+ *  Copyright (c) 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__CPUINIT
+
+ENTRY(hix5hd2_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/hisilicon.c linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/hisilicon.c
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/hisilicon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/hisilicon.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,16 +14,10 @@
 #include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-
-#include <asm/proc-fns.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include "core.h"
-
 #define HI3620_SYSCTRL_PHYS_BASE		0xfc802000
 #define HI3620_SYSCTRL_VIRT_BASE		0xfe802000
 
@@ -51,32 +45,6 @@ static void __init hi3620_map_io(void)
 	iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc));
 }
 
-static void hi3xxx_restart(enum reboot_mode mode, const char *cmd)
-{
-	struct device_node *np;
-	void __iomem *base;
-	int offset;
-
-	np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
-	if (!np) {
-		pr_err("failed to find hisilicon,sysctrl node\n");
-		return;
-	}
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("failed to map address in hisilicon,sysctrl node\n");
-		return;
-	}
-	if (of_property_read_u32(np, "reboot-offset", &offset) < 0) {
-		pr_err("failed to find reboot-offset property\n");
-		return;
-	}
-	writel_relaxed(0xdeadbeef, base + offset);
-
-	while (1)
-		cpu_do_idle();
-}
-
 static const char *hi3xxx_compat[] __initconst = {
 	"hisilicon,hi3620-hi4511",
 	NULL,
@@ -85,6 +53,13 @@ static const char *hi3xxx_compat[] __ini
 DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
 	.map_io		= hi3620_map_io,
 	.dt_compat	= hi3xxx_compat,
-	.smp		= smp_ops(hi3xxx_smp_ops),
-	.restart	= hi3xxx_restart,
+MACHINE_END
+
+static const char *hix5hd2_compat[] __initconst = {
+	"hisilicon,hix5hd2",
+	NULL,
+};
+
+DT_MACHINE_START(HIX5HD2_DT, "Hisilicon HIX5HD2 (Flattened Device Tree)")
+	.dt_compat	= hix5hd2_compat,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/hotplug.c linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/hotplug.c
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/hotplug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/hotplug.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,6 +57,14 @@
 #define CPU0_NEON_SRST_REQ_EN		(1 << 4)
 #define CPU0_SRST_REQ_EN		(1 << 0)
 
+#define HIX5HD2_PERI_CRG20		0x50
+#define CRG20_CPU1_RESET		(1 << 17)
+
+#define HIX5HD2_PERI_PMC0		0x1000
+#define PMC0_CPU1_WAIT_MTCOMS_ACK	(1 << 8)
+#define PMC0_CPU1_PMC_ENABLE		(1 << 7)
+#define PMC0_CPU1_POWERDOWN		(1 << 3)
+
 enum {
 	HI3620_CTRL,
 	ERROR_CTRL,
@@ -157,6 +165,50 @@ void hi3xxx_set_cpu(int cpu, bool enable
 		set_cpu_hi3620(cpu, enable);
 }
 
+static bool hix5hd2_hotplug_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
+	if (np) {
+		ctrl_base = of_iomap(np, 0);
+		return true;
+	}
+	return false;
+}
+
+void hix5hd2_set_cpu(int cpu, bool enable)
+{
+	u32 val = 0;
+
+	if (!ctrl_base)
+		if (!hix5hd2_hotplug_init())
+			BUG();
+
+	if (enable) {
+		/* power on cpu1 */
+		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+		val &= ~(PMC0_CPU1_WAIT_MTCOMS_ACK | PMC0_CPU1_POWERDOWN);
+		val |= PMC0_CPU1_PMC_ENABLE;
+		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+		/* unreset */
+		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+		val &= ~CRG20_CPU1_RESET;
+		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+	} else {
+		/* power down cpu1 */
+		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+		val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
+		val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
+		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+
+		/* reset */
+		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+		val |= CRG20_CPU1_RESET;
+		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+	}
+}
+
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -199,4 +251,10 @@ int hi3xxx_cpu_kill(unsigned int cpu)
 	hi3xxx_set_cpu(cpu, false);
 	return 1;
 }
+
+void hix5hd2_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+	hix5hd2_set_cpu(cpu, false);
+}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,36 @@
-config ARCH_HI3xxx
-	bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
+config ARCH_HISI
+	bool "Hisilicon SoC Support"
+	depends on ARCH_MULTIPLATFORM
 	select ARM_AMBA
 	select ARM_GIC
 	select ARM_TIMER_SP804
+	select POWER_RESET
+	select POWER_RESET_HISI
+	select POWER_SUPPLY
+
+if ARCH_HISI
+
+menu "Hisilicon platform type"
+
+config ARCH_HI3xxx
+	bool "Hisilicon Hi36xx family" if ARCH_MULTI_V7
 	select CACHE_L2X0
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select PINCTRL
 	select PINCTRL_SINGLE
 	help
-	  Support for Hisilicon Hi36xx/Hi37xx processor family
+	  Support for Hisilicon Hi36xx SoC family
+
+config ARCH_HIX5HD2
+	bool "Hisilicon X5HD2 family" if ARCH_MULTI_V7
+	select CACHE_L2X0
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	select PINCTRL
+	select PINCTRL_SINGLE
+	help
+	  Support for Hisilicon HIX5HD2 SoC family
+endmenu
+
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,4 +3,4 @@
 #
 
 obj-y	+= hisilicon.o
-obj-$(CONFIG_SMP)		+= platsmp.o hotplug.o
+obj-$(CONFIG_SMP)		+= platsmp.o hotplug.o headsmp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-hisi/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-hisi/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-hisi/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
 
 #include "core.h"
 
+#define HIX5HD2_BOOT_ADDRESS		0xffff0000
+
 static void __iomem *ctrl_base;
 
 void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
@@ -35,11 +37,9 @@ int hi3xxx_get_cpu_jump(int cpu)
 	return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
 }
 
-static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hisi_enable_scu_a9(void)
 {
-	struct device_node *np = NULL;
 	unsigned long base = 0;
-	u32 offset = 0;
 	void __iomem *scu_base = NULL;
 
 	if (scu_a9_has_base()) {
@@ -52,6 +52,14 @@ static void __init hi3xxx_smp_prepare_cp
 		scu_enable(scu_base);
 		iounmap(scu_base);
 	}
+}
+
+static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *np = NULL;
+	u32 offset = 0;
+
+	hisi_enable_scu_a9();
 	if (!ctrl_base) {
 		np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
 		if (!np) {
@@ -87,3 +95,42 @@ struct smp_operations hi3xxx_smp_ops __i
 	.cpu_kill		= hi3xxx_cpu_kill,
 #endif
 };
+
+static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
+{
+	hisi_enable_scu_a9();
+}
+
+void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
+{
+	void __iomem *virt;
+
+	virt = ioremap(start_addr, PAGE_SIZE);
+
+	writel_relaxed(0xe51ff004, virt);	/* ldr pc, [rc, #-4] */
+	writel_relaxed(jump_addr, virt + 4);	/* pc jump phy address */
+	iounmap(virt);
+}
+
+static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	phys_addr_t jumpaddr;
+
+	jumpaddr = virt_to_phys(hix5hd2_secondary_startup);
+	hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
+	hix5hd2_set_cpu(cpu, true);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+	return 0;
+}
+
+
+struct smp_operations hix5hd2_smp_ops __initdata = {
+	.smp_prepare_cpus	= hix5hd2_smp_prepare_cpus,
+	.smp_boot_secondary	= hix5hd2_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= hix5hd2_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
+CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,16 @@
 
 DEFINE_SPINLOCK(imx_ccm_lock);
 
+void __init imx_check_clocks(struct clk *clks[], unsigned int count)
+{
+	unsigned i;
+
+	for (i = 0; i < count; i++)
+		if (IS_ERR(clks[i]))
+			pr_err("i.MX clk %u: register failed with %ld\n",
+			       i, PTR_ERR(clks[i]));
+}
+
 static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
 {
 	struct of_phandle_args phandle;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-gate2.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-gate2.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-gate2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-gate2.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ static int clk_gate2_is_enabled(struct c
 	struct clk_gate2 *gate = to_clk_gate2(hw);
 
 	if (gate->share_count)
-		return !!(*gate->share_count);
+		return !!__clk_get_enable_count(hw->clk);
 	else
 		return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
 }
@@ -127,10 +127,6 @@ struct clk *clk_register_gate2(struct de
 	gate->bit_idx = bit_idx;
 	gate->flags = clk_gate2_flags;
 	gate->lock = lock;
-
-	/* Initialize share_count per hardware state */
-	if (share_count)
-		*share_count = clk_gate2_reg_is_enabled(reg, bit_idx) ? 1 : 0;
 	gate->share_count = share_count;
 
 	init.name = name;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk.h	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,8 @@
 
 extern spinlock_t imx_ccm_lock;
 
+void imx_check_clocks(struct clk *clks[], unsigned int count);
+
 extern void imx_cscmr1_fixup(u32 *val);
 
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
@@ -95,6 +97,13 @@ static inline struct clk *imx_clk_gate(c
 			shift, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 		u8 shift, u8 width, const char **parents, int num_parents)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx1.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx1.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx1.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,100 +15,103 @@
  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/clk.h>
-#include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx1-clock.h>
 
 #include "clk.h"
 #include "common.h"
 #include "hardware.h"
 
-/* CCM register addresses */
-#define IO_ADDR_CCM(off)	(MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
-
-#define CCM_CSCR	IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0	IO_ADDR_CCM(0x4)
-#define CCM_SPCTL0	IO_ADDR_CCM(0xc)
-#define CCM_PCDR	IO_ADDR_CCM(0x20)
-
-/* SCM register addresses */
-#define IO_ADDR_SCM(off)	(MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
-
-#define SCM_GCCR	IO_ADDR_SCM(0xc)
-
 static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", };
 static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m",
 				       "prem", "fclk", };
 
-enum imx1_clks {
-	dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, mpll_gate,
-	spll, spll_gate, mcu, fclk, hclk, clk48m, per1, per2, per3, clko,
-	uart3_gate, ssi2_gate, brom_gate, dma_gate, csi_gate, mma_gate,
-	usbd_gate, clk_max
-};
+static struct clk *clk[IMX1_CLK_MAX];
+static struct clk_onecell_data clk_data;
 
-static struct clk *clk[clk_max];
+static void __iomem *ccm __initdata;
+#define CCM_CSCR	(ccm + 0x0000)
+#define CCM_MPCTL0	(ccm + 0x0004)
+#define CCM_SPCTL0	(ccm + 0x000c)
+#define CCM_PCDR	(ccm + 0x0020)
+#define SCM_GCCR	(ccm + 0x0810)
 
-int __init mx1_clocks_init(unsigned long fref)
+static void __init _mx1_clocks_init(unsigned long fref)
 {
-	int i;
+	clk[IMX1_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+	clk[IMX1_CLK_CLK32] = imx_obtain_fixed_clock("clk32", fref);
+	clk[IMX1_CLK_CLK16M_EXT] = imx_clk_fixed("clk16m_ext", 16000000);
+	clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
+	clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
+	clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks));
+	clk[IMX1_CLK_MPLL] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
+	clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
+	clk[IMX1_CLK_SPLL] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
+	clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+	clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
+	clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1);
+	clk[IMX1_CLK_HCLK] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4);
+	clk[IMX1_CLK_CLK48M] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3);
+	clk[IMX1_CLK_PER1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4);
+	clk[IMX1_CLK_PER2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4);
+	clk[IMX1_CLK_PER3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7);
+	clk[IMX1_CLK_CLKO] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+	clk[IMX1_CLK_UART3_GATE] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6);
+	clk[IMX1_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5);
+	clk[IMX1_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4);
+	clk[IMX1_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3);
+	clk[IMX1_CLK_CSI_GATE] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
+	clk[IMX1_CLK_MMA_GATE] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
+	clk[IMX1_CLK_USBD_GATE] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
 
-	clk[dummy] = imx_clk_fixed("dummy", 0);
-	clk[clk32] = imx_clk_fixed("clk32", fref);
-	clk[clk16m_ext] = imx_clk_fixed("clk16m_ext", 16000000);
-	clk[clk16m] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
-	clk[clk32_premult] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
-	clk[prem] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks,
-			ARRAY_SIZE(prem_sel_clks));
-	clk[mpll] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
-	clk[mpll_gate] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
-	clk[spll] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
-	clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
-	clk[mcu] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
-	clk[fclk] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1);
-	clk[hclk] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4);
-	clk[clk48m] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3);
-	clk[per1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4);
-	clk[per2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4);
-	clk[per3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7);
-	clk[clko] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks,
-			ARRAY_SIZE(clko_sel_clks));
-	clk[uart3_gate] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6);
-	clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5);
-	clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4);
-	clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3);
-	clk[csi_gate] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
-	clk[mma_gate] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
-	clk[usbd_gate] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+}
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("imx1 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+int __init mx1_clocks_init(unsigned long fref)
+{
+	ccm = MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR);
 
-	clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma");
-	clk_register_clkdev(clk[hclk], "ipg", "imx1-dma");
-	clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[hclk], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[per1], "per", "imx1-uart.0");
-	clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.0");
-	clk_register_clkdev(clk[per1], "per", "imx1-uart.1");
-	clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1");
-	clk_register_clkdev(clk[per1], "per", "imx1-uart.2");
-	clk_register_clkdev(clk[uart3_gate], "ipg", "imx1-uart.2");
-	clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0");
-	clk_register_clkdev(clk[per2], "per", "imx1-cspi.0");
-	clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0");
-	clk_register_clkdev(clk[per2], "per", "imx1-cspi.1");
-	clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1");
-	clk_register_clkdev(clk[per2], "per", "imx1-fb.0");
-	clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0");
-	clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0");
+	_mx1_clocks_init(fref);
+
+	clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX1_CLK_DMA_GATE], "ahb", "imx1-dma");
+	clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-dma");
+	clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.0");
+	clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.0");
+	clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.1");
+	clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.1");
+	clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.2");
+	clk_register_clkdev(clk[IMX1_CLK_UART3_GATE], "ipg", "imx1-uart.2");
+	clk_register_clkdev(clk[IMX1_CLK_HCLK], NULL, "imx1-i2c.0");
+	clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.0");
+	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.0");
+	clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.1");
+	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.1");
+	clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-fb.0");
+	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0");
+	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0");
 
 	mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
 
 	return 0;
 }
+
+static void __init mx1_clocks_init_dt(struct device_node *np)
+{
+	ccm = of_iomap(np, 0);
+	BUG_ON(!ccm);
+
+	_mx1_clocks_init(32768);
+
+	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(imx1_ccm, "fsl,imx1-ccm", mx1_clocks_init_dt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx21.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx21.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx21.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx21.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,178 +7,165 @@
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
  */
 
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/err.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx21-clock.h>
 
 #include "clk.h"
 #include "common.h"
 #include "hardware.h"
 
-#define IO_ADDR_CCM(off)	(MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
+static void __iomem *ccm __initdata;
 
 /* Register offsets */
-#define CCM_CSCR		IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
-#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
-#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
-#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
-#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
-#define CCM_PCDR0		IO_ADDR_CCM(0x18)
-#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
-#define CCM_PCCR0		IO_ADDR_CCM(0x20)
-#define CCM_PCCR1		IO_ADDR_CCM(0x24)
-#define CCM_CCSR		IO_ADDR_CCM(0x28)
-#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
-#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
-#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
+#define CCM_CSCR	(ccm + 0x00)
+#define CCM_MPCTL0	(ccm + 0x04)
+#define CCM_SPCTL0	(ccm + 0x0c)
+#define CCM_PCDR0	(ccm + 0x18)
+#define CCM_PCDR1	(ccm + 0x1c)
+#define CCM_PCCR0	(ccm + 0x20)
+#define CCM_PCCR1	(ccm + 0x24)
 
-static const char *mpll_sel_clks[] = { "fpm", "ckih", };
-static const char *spll_sel_clks[] = { "fpm", "ckih", };
+static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", };
+static const char *mpll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
+static const char *spll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
+static const char *ssi_sel_clks[] = { "spll_gate", "mpll_gate", };
 
-enum imx21_clks {
-	ckil, ckih, fpm, mpll_sel, spll_sel, mpll, spll, fclk, hclk, ipg, per1,
-	per2, per3, per4, uart1_ipg_gate, uart2_ipg_gate, uart3_ipg_gate,
-	uart4_ipg_gate, gpt1_ipg_gate, gpt2_ipg_gate, gpt3_ipg_gate,
-	pwm_ipg_gate, sdhc1_ipg_gate, sdhc2_ipg_gate, lcdc_ipg_gate,
-	lcdc_hclk_gate, cspi3_ipg_gate, cspi2_ipg_gate, cspi1_ipg_gate,
-	per4_gate, csi_hclk_gate, usb_div, usb_gate, usb_hclk_gate, ssi1_gate,
-	ssi2_gate, nfc_div, nfc_gate, dma_gate, dma_hclk_gate, brom_gate,
-	emma_gate, emma_hclk_gate, slcdc_gate, slcdc_hclk_gate, wdog_gate,
-	gpio_gate, i2c_gate, kpp_gate, owire_gate, rtc_gate, clk_max
-};
+static struct clk *clk[IMX21_CLK_MAX];
+static struct clk_onecell_data clk_data;
 
-static struct clk *clk[clk_max];
+static void __init _mx21_clocks_init(unsigned long lref, unsigned long href)
+{
+	BUG_ON(!ccm);
+
+	clk[IMX21_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+	clk[IMX21_CLK_CKIL] = imx_obtain_fixed_clock("ckil", lref);
+	clk[IMX21_CLK_CKIH] = imx_obtain_fixed_clock("ckih", href);
+	clk[IMX21_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
+	clk[IMX21_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3);
+
+	clk[IMX21_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
+	clk[IMX21_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+	clk[IMX21_CLK_FPM_GATE] = imx_clk_gate("fpm_gate", "fpm", CCM_CSCR, 2);
+	clk[IMX21_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
+	clk[IMX21_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
+	clk[IMX21_CLK_IPG] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
+	clk[IMX21_CLK_HCLK] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
+	clk[IMX21_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
+	clk[IMX21_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks, ARRAY_SIZE(spll_sel_clks));
+	clk[IMX21_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 19, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	clk[IMX21_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 20, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3);
+	clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3);
+
+	clk[IMX21_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
+
+	clk[IMX21_CLK_SPLL] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
+
+	clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4);
+	clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
+	clk[IMX21_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
+
+	clk[IMX21_CLK_PER1] = imx_clk_divider("per1", "mpll_gate", CCM_PCDR1, 0, 6);
+	clk[IMX21_CLK_PER2] = imx_clk_divider("per2", "mpll_gate", CCM_PCDR1, 8, 6);
+	clk[IMX21_CLK_PER3] = imx_clk_divider("per3", "mpll_gate", CCM_PCDR1, 16, 6);
+	clk[IMX21_CLK_PER4] = imx_clk_divider("per4", "mpll_gate", CCM_PCDR1, 24, 6);
+
+	clk[IMX21_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
+	clk[IMX21_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
+	clk[IMX21_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
+	clk[IMX21_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
+	clk[IMX21_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
+	clk[IMX21_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
+	clk[IMX21_CLK_SSI1_GATE] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
+	clk[IMX21_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
+	clk[IMX21_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
+	clk[IMX21_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
+	clk[IMX21_CLK_GPIO_GATE] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
+	clk[IMX21_CLK_I2C_GATE] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
+	clk[IMX21_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
+	clk[IMX21_CLK_USB_GATE] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
+	clk[IMX21_CLK_EMMA_GATE] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
+	clk[IMX21_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ipg", CCM_PCCR0, 16);
+	clk[IMX21_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ipg", CCM_PCCR0, 17);
+	clk[IMX21_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
+	clk[IMX21_CLK_NFC_GATE] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
+	clk[IMX21_CLK_SLCDC_HCLK_GATE] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
+	clk[IMX21_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
+	clk[IMX21_CLK_BMI_GATE] = imx_clk_gate("bmi_gate", "hclk", CCM_PCCR0, 23);
+	clk[IMX21_CLK_USB_HCLK_GATE] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
+	clk[IMX21_CLK_SLCDC_GATE] = imx_clk_gate("slcdc_gate", "hclk", CCM_PCCR0, 25);
+	clk[IMX21_CLK_LCDC_HCLK_GATE] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
+	clk[IMX21_CLK_EMMA_HCLK_GATE] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
+	clk[IMX21_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
+	clk[IMX21_CLK_DMA_HCLK_GATE] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
+	clk[IMX21_CLK_CSI_HCLK_GATE] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
+
+	clk[IMX21_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
+	clk[IMX21_CLK_WDOG_GATE] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
+	clk[IMX21_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
+	clk[IMX21_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
+	clk[IMX21_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
+	clk[IMX21_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
+	clk[IMX21_CLK_RTC_GATE] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
+	clk[IMX21_CLK_KPP_GATE] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
+	clk[IMX21_CLK_OWIRE_GATE] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
+
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+}
 
-/*
- * must be called very early to get information about the
- * available clock rate when the timer framework starts
- */
 int __init mx21_clocks_init(unsigned long lref, unsigned long href)
 {
-	int i;
-
-	clk[ckil] = imx_clk_fixed("ckil", lref);
-	clk[ckih] = imx_clk_fixed("ckih", href);
-	clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
-	clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
-			ARRAY_SIZE(mpll_sel_clks));
-	clk[spll_sel] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks,
-			ARRAY_SIZE(spll_sel_clks));
-	clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
-	clk[spll] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
-	clk[fclk] = imx_clk_divider("fclk", "mpll", CCM_CSCR, 29, 3);
-	clk[hclk] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
-	clk[ipg] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
-	clk[per1] = imx_clk_divider("per1", "mpll", CCM_PCDR1, 0, 6);
-	clk[per2] = imx_clk_divider("per2", "mpll", CCM_PCDR1, 8, 6);
-	clk[per3] = imx_clk_divider("per3", "mpll", CCM_PCDR1, 16, 6);
-	clk[per4] = imx_clk_divider("per4", "mpll", CCM_PCDR1, 24, 6);
-	clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
-	clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
-	clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
-	clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
-	clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
-	clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
-	clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
-	clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
-	clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
-	clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
-	clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
-	clk[lcdc_hclk_gate] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
-	clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
-	clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
-	clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
-	clk[per4_gate] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
-	clk[csi_hclk_gate] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
-	clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 26, 3);
-	clk[usb_gate] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
-	clk[usb_hclk_gate] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
-	clk[ssi1_gate] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
-	clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
-	clk[nfc_div] = imx_clk_divider("nfc_div", "ipg", CCM_PCDR0, 12, 4);
-	clk[nfc_gate] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
-	clk[dma_gate] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
-	clk[dma_hclk_gate] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
-	clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
-	clk[emma_gate] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
-	clk[emma_hclk_gate] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
-	clk[slcdc_gate] = imx_clk_gate("slcdc_gate", "ipg", CCM_PCCR0, 25);
-	clk[slcdc_hclk_gate] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
-	clk[wdog_gate] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
-	clk[gpio_gate] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
-	clk[i2c_gate] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
-	clk[kpp_gate] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
-	clk[owire_gate] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
-	clk[rtc_gate] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
+	ccm = ioremap(MX21_CCM_BASE_ADDR, SZ_2K);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX21 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	_mx21_clocks_init(lref, href);
 
-	clk_register_clkdev(clk[per1], "per1", NULL);
-	clk_register_clkdev(clk[per2], "per2", NULL);
-	clk_register_clkdev(clk[per3], "per3", NULL);
-	clk_register_clkdev(clk[per4], "per4", NULL);
-	clk_register_clkdev(clk[per1], "per", "imx21-uart.0");
-	clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
-	clk_register_clkdev(clk[per1], "per", "imx21-uart.1");
-	clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
-	clk_register_clkdev(clk[per1], "per", "imx21-uart.2");
-	clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
-	clk_register_clkdev(clk[per1], "per", "imx21-uart.3");
-	clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
-	clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[gpt2_ipg_gate], "ipg", "imx-gpt.1");
-	clk_register_clkdev(clk[per1], "per", "imx-gpt.1");
-	clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2");
-	clk_register_clkdev(clk[per1], "per", "imx-gpt.2");
-	clk_register_clkdev(clk[per2], "per", "imx21-cspi.0");
-	clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx21-cspi.0");
-	clk_register_clkdev(clk[per2], "per", "imx21-cspi.1");
-	clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx21-cspi.1");
-	clk_register_clkdev(clk[per2], "per", "imx21-cspi.2");
-	clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx21-cspi.2");
-	clk_register_clkdev(clk[per3], "per", "imx21-fb.0");
-	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
-	clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx21-fb.0");
-	clk_register_clkdev(clk[usb_gate], "per", "imx21-hcd.0");
-	clk_register_clkdev(clk[usb_hclk_gate], "ahb", "imx21-hcd.0");
-	clk_register_clkdev(clk[nfc_gate], NULL, "imx21-nand.0");
-	clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx21-dma");
-	clk_register_clkdev(clk[dma_gate], "ipg", "imx21-dma");
-	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[i2c_gate], NULL, "imx21-i2c.0");
-	clk_register_clkdev(clk[kpp_gate], NULL, "mxc-keypad");
-	clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
-	clk_register_clkdev(clk[brom_gate], "brom", NULL);
-	clk_register_clkdev(clk[emma_gate], "emma", NULL);
-	clk_register_clkdev(clk[slcdc_gate], "slcdc", NULL);
-	clk_register_clkdev(clk[gpio_gate], "gpio", NULL);
-	clk_register_clkdev(clk[rtc_gate], "rtc", NULL);
-	clk_register_clkdev(clk[csi_hclk_gate], "csi", NULL);
-	clk_register_clkdev(clk[ssi1_gate], "ssi1", NULL);
-	clk_register_clkdev(clk[ssi2_gate], "ssi2", NULL);
-	clk_register_clkdev(clk[sdhc1_ipg_gate], "sdhc1", NULL);
-	clk_register_clkdev(clk[sdhc2_ipg_gate], "sdhc2", NULL);
+	clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.0");
+	clk_register_clkdev(clk[IMX21_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
+	clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.1");
+	clk_register_clkdev(clk[IMX21_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
+	clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.2");
+	clk_register_clkdev(clk[IMX21_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
+	clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.3");
+	clk_register_clkdev(clk[IMX21_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
+	clk_register_clkdev(clk[IMX21_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.0");
+	clk_register_clkdev(clk[IMX21_CLK_CSPI1_IPG_GATE], "ipg", "imx21-cspi.0");
+	clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.1");
+	clk_register_clkdev(clk[IMX21_CLK_CSPI2_IPG_GATE], "ipg", "imx21-cspi.1");
+	clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.2");
+	clk_register_clkdev(clk[IMX21_CLK_CSPI3_IPG_GATE], "ipg", "imx21-cspi.2");
+	clk_register_clkdev(clk[IMX21_CLK_PER3], "per", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX21_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX21_CLK_LCDC_HCLK_GATE], "ahb", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX21_CLK_USB_GATE], "per", "imx21-hcd.0");
+	clk_register_clkdev(clk[IMX21_CLK_USB_HCLK_GATE], "ahb", "imx21-hcd.0");
+	clk_register_clkdev(clk[IMX21_CLK_NFC_GATE], NULL, "imx21-nand.0");
+	clk_register_clkdev(clk[IMX21_CLK_DMA_HCLK_GATE], "ahb", "imx21-dma");
+	clk_register_clkdev(clk[IMX21_CLK_DMA_GATE], "ipg", "imx21-dma");
+	clk_register_clkdev(clk[IMX21_CLK_WDOG_GATE], NULL, "imx2-wdt.0");
+	clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0");
 
 	mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1);
 
 	return 0;
 }
+
+static void __init mx21_clocks_init_dt(struct device_node *np)
+{
+	ccm = of_iomap(np, 0);
+
+	_mx21_clocks_init(32768, 26000000);
+
+	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(imx27_ccm, "fsl,imx21-ccm", mx21_clocks_init_dt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx25.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx25.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx25.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx25.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,8 +32,6 @@
 #include "hardware.h"
 #include "mx25.h"
 
-#define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
-
 #define CCM_MPCTL	0x00
 #define CCM_UPCTL	0x04
 #define CCM_CCTL	0x08
@@ -56,7 +54,7 @@
 #define CCM_LTR3	0x4c
 #define CCM_MCR		0x64
 
-#define ccm(x)	(CRM_BASE + (x))
+#define ccm(x)	(ccm_base + (x))
 
 static struct clk_onecell_data clk_data;
 
@@ -91,9 +89,10 @@ enum mx25_clks {
 
 static struct clk *clk[clk_max];
 
-static int __init __mx25_clocks_init(unsigned long osc_rate)
+static int __init __mx25_clocks_init(unsigned long osc_rate,
+				     void __iomem *ccm_base)
 {
-	int i;
+	BUG_ON(!ccm_base);
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[osc] = imx_clk_fixed("osc", osc_rate);
@@ -224,19 +223,13 @@ static int __init __mx25_clocks_init(uns
 	/* CCM_CGCR2(19): reserved in datasheet, but used as wdt in FSL kernel */
 	clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX25 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	clk_prepare_enable(clk[emi_ahb]);
 
 	/* Clock source for gpt must be derived from AHB */
 	clk_set_parent(clk[per5_sel], clk[ahb]);
 
-	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-
 	/*
 	 * Let's initially set up CLKO parent as ipg, since this configuration
 	 * is used on some imx25 board designs to clock the audio codec.
@@ -248,8 +241,14 @@ static int __init __mx25_clocks_init(uns
 
 int __init mx25_clocks_init(void)
 {
-	__mx25_clocks_init(24000000);
+	void __iomem *ccm;
+
+	ccm = ioremap(MX25_CRM_BASE_ADDR, SZ_16K);
 
+	__mx25_clocks_init(24000000, ccm);
+
+	clk_register_clkdev(clk[gpt1_ipg], "ipg", "imx-gpt.0");
+	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
 	/* i.mx25 has the i.mx21 type uart */
 	clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
 	clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
@@ -314,29 +313,27 @@ int __init mx25_clocks_init(void)
 	return 0;
 }
 
-int __init mx25_clocks_init_dt(void)
+static void __init mx25_clocks_init_dt(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *refnp;
 	unsigned long osc_rate = 24000000;
+	void __iomem *ccm;
 
 	/* retrieve the freqency of fixed clocks from device tree */
-	for_each_compatible_node(np, NULL, "fixed-clock") {
+	for_each_compatible_node(refnp, NULL, "fixed-clock") {
 		u32 rate;
-		if (of_property_read_u32(np, "clock-frequency", &rate))
+		if (of_property_read_u32(refnp, "clock-frequency", &rate))
 			continue;
 
-		if (of_device_is_compatible(np, "fsl,imx-osc"))
+		if (of_device_is_compatible(refnp, "fsl,imx-osc"))
 			osc_rate = rate;
 	}
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
+	ccm = of_iomap(np, 0);
+	__mx25_clocks_init(osc_rate, ccm);
+
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-
-	__mx25_clocks_init(osc_rate);
-
-	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt"));
-
-	return 0;
 }
+CLK_OF_DECLARE(imx25_ccm, "fsl,imx25-ccm", mx25_clocks_init_dt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx27.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx27.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx27.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx27.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,61 +1,36 @@
 #include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
-#include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx27-clock.h>
 
 #include "clk.h"
 #include "common.h"
 #include "hardware.h"
 
-#define IO_ADDR_CCM(off)	(MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
+static void __iomem *ccm __initdata;
 
 /* Register offsets */
-#define CCM_CSCR		IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
-#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
-#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
-#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
-#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
-#define CCM_PCDR0		IO_ADDR_CCM(0x18)
-#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
-#define CCM_PCCR0		IO_ADDR_CCM(0x20)
-#define CCM_PCCR1		IO_ADDR_CCM(0x24)
-#define CCM_CCSR		IO_ADDR_CCM(0x28)
-#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
-#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
-#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
-
-#define CCM_CSCR_UPDATE_DIS	(1 << 31)
-#define CCM_CSCR_SSI2		(1 << 23)
-#define CCM_CSCR_SSI1		(1 << 22)
-#define CCM_CSCR_VPU		(1 << 21)
-#define CCM_CSCR_MSHC           (1 << 20)
-#define CCM_CSCR_SPLLRES        (1 << 19)
-#define CCM_CSCR_MPLLRES        (1 << 18)
-#define CCM_CSCR_SP             (1 << 17)
-#define CCM_CSCR_MCU            (1 << 16)
-#define CCM_CSCR_OSC26MDIV      (1 << 4)
-#define CCM_CSCR_OSC26M         (1 << 3)
-#define CCM_CSCR_FPM            (1 << 2)
-#define CCM_CSCR_SPEN           (1 << 1)
-#define CCM_CSCR_MPEN           (1 << 0)
-
-/* i.MX27 TO 2+ */
-#define CCM_CSCR_ARM_SRC        (1 << 15)
-
-#define CCM_SPCTL1_LF           (1 << 15)
-#define CCM_SPCTL1_BRMO         (1 << 6)
+#define CCM_CSCR		(ccm + 0x00)
+#define CCM_MPCTL0		(ccm + 0x04)
+#define CCM_MPCTL1		(ccm + 0x08)
+#define CCM_SPCTL0		(ccm + 0x0c)
+#define CCM_SPCTL1		(ccm + 0x10)
+#define CCM_PCDR0		(ccm + 0x18)
+#define CCM_PCDR1		(ccm + 0x1c)
+#define CCM_PCCR0		(ccm + 0x20)
+#define CCM_PCCR1		(ccm + 0x24)
+#define CCM_CCSR		(ccm + 0x28)
 
 static const char *vpu_sel_clks[] = { "spll", "mpll_main2", };
 static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
 static const char *mpll_sel_clks[] = { "fpm", "mpll_osc_sel", };
-static const char *mpll_osc_sel_clks[] = { "ckih", "ckih_div1p5", };
+static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", };
 static const char *clko_sel_clks[] = {
-	"ckil", "fpm", "ckih", "ckih",
-	"ckih", "mpll", "spll", "cpu_div",
+	"ckil", "fpm", "ckih_gate", "ckih_gate",
+	"ckih_gate", "mpll", "spll", "cpu_div",
 	"ahb", "ipg", "per1_div", "per2_div",
 	"per3_div", "per4_div", "ssi1_div", "ssi2_div",
 	"nfc_div", "mshc_div", "vpu_div", "60m",
@@ -64,239 +39,220 @@ static const char *clko_sel_clks[] = {
 
 static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
 
-enum mx27_clks {
-	dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
-	per2_div, per3_div, per4_div, vpu_sel, vpu_div, usb_div, cpu_sel,
-	clko_sel, cpu_div, clko_div, ssi1_sel, ssi2_sel, ssi1_div, ssi2_div,
-	clko_en, ssi2_ipg_gate, ssi1_ipg_gate, slcdc_ipg_gate, sdhc3_ipg_gate,
-	sdhc2_ipg_gate, sdhc1_ipg_gate, scc_ipg_gate, sahara_ipg_gate,
-	rtc_ipg_gate, pwm_ipg_gate, owire_ipg_gate, lcdc_ipg_gate,
-	kpp_ipg_gate, iim_ipg_gate, i2c2_ipg_gate, i2c1_ipg_gate,
-	gpt6_ipg_gate, gpt5_ipg_gate, gpt4_ipg_gate, gpt3_ipg_gate,
-	gpt2_ipg_gate, gpt1_ipg_gate, gpio_ipg_gate, fec_ipg_gate,
-	emma_ipg_gate, dma_ipg_gate, cspi3_ipg_gate, cspi2_ipg_gate,
-	cspi1_ipg_gate, nfc_baud_gate, ssi2_baud_gate, ssi1_baud_gate,
-	vpu_baud_gate, per4_gate, per3_gate, per2_gate, per1_gate,
-	usb_ahb_gate, slcdc_ahb_gate, sahara_ahb_gate, lcdc_ahb_gate,
-	vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
-	csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
-	uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
-	uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
-	mpll_sel, spll_gate, mshc_div, rtic_ipg_gate, mshc_ipg_gate,
-	rtic_ahb_gate, mshc_baud_gate, clk_max
-};
-
-static struct clk *clk[clk_max];
+static struct clk *clk[IMX27_CLK_MAX];
 static struct clk_onecell_data clk_data;
 
-int __init mx27_clocks_init(unsigned long fref)
+static void __init _mx27_clocks_init(unsigned long fref)
 {
-	int i;
-	struct device_node *np;
-
-	clk[dummy] = imx_clk_fixed("dummy", 0);
-	clk[ckih] = imx_clk_fixed("ckih", fref);
-	clk[ckil] = imx_clk_fixed("ckil", 32768);
-	clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
-	clk[ckih_div1p5] = imx_clk_fixed_factor("ckih_div1p5", "ckih", 2, 3);
+	BUG_ON(!ccm);
 
-	clk[mpll_osc_sel] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1,
-			mpll_osc_sel_clks,
-			ARRAY_SIZE(mpll_osc_sel_clks));
-	clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
-			ARRAY_SIZE(mpll_sel_clks));
-	clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
-	clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
-	clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
-	clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
+	clk[IMX27_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+	clk[IMX27_CLK_CKIH] = imx_clk_fixed("ckih", fref);
+	clk[IMX27_CLK_CKIL] = imx_clk_fixed("ckil", 32768);
+	clk[IMX27_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
+	clk[IMX27_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3);
+	clk[IMX27_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
+	clk[IMX27_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
+	clk[IMX27_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
+	clk[IMX27_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
+	clk[IMX27_CLK_SPLL] = imx_clk_pllv1("spll", "ckih_gate", CCM_SPCTL0);
+	clk[IMX27_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+	clk[IMX27_CLK_MPLL_MAIN2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
-		clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
-		clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
+		clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
+		clk[IMX27_CLK_IPG] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
 	} else {
-		clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
-		clk[ipg] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
+		clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
+		clk[IMX27_CLK_IPG] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
 	}
 
-	clk[mshc_div] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6);
-	clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
-	clk[per1_div] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
-	clk[per2_div] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
-	clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
-	clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
-	clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
-	clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
-	clk[usb_div] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
-	clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
-	clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+	clk[IMX27_CLK_MSHC_DIV] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6);
+	clk[IMX27_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
+	clk[IMX27_CLK_PER1_DIV] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
+	clk[IMX27_CLK_PER2_DIV] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
+	clk[IMX27_CLK_PER3_DIV] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
+	clk[IMX27_CLK_PER4_DIV] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
+	clk[IMX27_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
+	clk[IMX27_CLK_VPU_DIV] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
+	clk[IMX27_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
+	clk[IMX27_CLK_CPU_SEL] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
+	clk[IMX27_CLK_CLKO_SEL] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
-		clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
+		clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
 	else
-		clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
-	clk[clko_div] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
-	clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
-	clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
-	clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
-	clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
-	clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
-	clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
-	clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
-	clk[slcdc_ipg_gate] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
-	clk[sdhc3_ipg_gate] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
-	clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
-	clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
-	clk[scc_ipg_gate] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
-	clk[sahara_ipg_gate] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
-	clk[rtic_ipg_gate] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8);
-	clk[rtc_ipg_gate] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
-	clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
-	clk[owire_ipg_gate] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
-	clk[mshc_ipg_gate] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13);
-	clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
-	clk[kpp_ipg_gate] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
-	clk[iim_ipg_gate] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
-	clk[i2c2_ipg_gate] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
-	clk[i2c1_ipg_gate] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
-	clk[gpt6_ipg_gate] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
-	clk[gpt5_ipg_gate] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
-	clk[gpt4_ipg_gate] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
-	clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
-	clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
-	clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
-	clk[gpio_ipg_gate] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
-	clk[fec_ipg_gate] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
-	clk[emma_ipg_gate] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
-	clk[dma_ipg_gate] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
-	clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
-	clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
-	clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
-	clk[mshc_baud_gate] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2);
-	clk[nfc_baud_gate] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1,  3);
-	clk[ssi2_baud_gate] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1,  4);
-	clk[ssi1_baud_gate] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1,  5);
-	clk[vpu_baud_gate] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1,  6);
-	clk[per4_gate] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1,  7);
-	clk[per3_gate] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1,  8);
-	clk[per2_gate] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1,  9);
-	clk[per1_gate] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
-	clk[usb_ahb_gate] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
-	clk[slcdc_ahb_gate] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
-	clk[sahara_ahb_gate] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
-	clk[rtic_ahb_gate] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14);
-	clk[lcdc_ahb_gate] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
-	clk[vpu_ahb_gate] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
-	clk[fec_ahb_gate] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
-	clk[emma_ahb_gate] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
-	clk[emi_ahb_gate] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
-	clk[dma_ahb_gate] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
-	clk[csi_ahb_gate] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
-	clk[brom_ahb_gate] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
-	clk[ata_ahb_gate] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
-	clk[wdog_ipg_gate] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
-	clk[usb_ipg_gate] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
-	clk[uart6_ipg_gate] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
-	clk[uart5_ipg_gate] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
-	clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
-	clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
-	clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
-	clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
-
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX27 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+		clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx27-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);
-	}
+	clk[IMX27_CLK_CLKO_DIV] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
+	clk[IMX27_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	clk[IMX27_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+	clk[IMX27_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
+	clk[IMX27_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
+	clk[IMX27_CLK_CLKO_EN] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
+	clk[IMX27_CLK_SSI2_IPG_GATE] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
+	clk[IMX27_CLK_SSI1_IPG_GATE] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
+	clk[IMX27_CLK_SLCDC_IPG_GATE] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
+	clk[IMX27_CLK_SDHC3_IPG_GATE] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
+	clk[IMX27_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
+	clk[IMX27_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
+	clk[IMX27_CLK_SCC_IPG_GATE] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
+	clk[IMX27_CLK_SAHARA_IPG_GATE] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
+	clk[IMX27_CLK_RTIC_IPG_GATE] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8);
+	clk[IMX27_CLK_RTC_IPG_GATE] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
+	clk[IMX27_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
+	clk[IMX27_CLK_OWIRE_IPG_GATE] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
+	clk[IMX27_CLK_MSHC_IPG_GATE] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13);
+	clk[IMX27_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
+	clk[IMX27_CLK_KPP_IPG_GATE] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
+	clk[IMX27_CLK_IIM_IPG_GATE] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
+	clk[IMX27_CLK_I2C2_IPG_GATE] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
+	clk[IMX27_CLK_I2C1_IPG_GATE] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
+	clk[IMX27_CLK_GPT6_IPG_GATE] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
+	clk[IMX27_CLK_GPT5_IPG_GATE] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
+	clk[IMX27_CLK_GPT4_IPG_GATE] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
+	clk[IMX27_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
+	clk[IMX27_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
+	clk[IMX27_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
+	clk[IMX27_CLK_GPIO_IPG_GATE] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
+	clk[IMX27_CLK_FEC_IPG_GATE] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
+	clk[IMX27_CLK_EMMA_IPG_GATE] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
+	clk[IMX27_CLK_DMA_IPG_GATE] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
+	clk[IMX27_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
+	clk[IMX27_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
+	clk[IMX27_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
+	clk[IMX27_CLK_MSHC_BAUD_GATE] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2);
+	clk[IMX27_CLK_NFC_BAUD_GATE] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1,  3);
+	clk[IMX27_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1,  4);
+	clk[IMX27_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1,  5);
+	clk[IMX27_CLK_VPU_BAUD_GATE] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1,  6);
+	clk[IMX27_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1,  7);
+	clk[IMX27_CLK_PER3_GATE] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1,  8);
+	clk[IMX27_CLK_PER2_GATE] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1,  9);
+	clk[IMX27_CLK_PER1_GATE] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
+	clk[IMX27_CLK_USB_AHB_GATE] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
+	clk[IMX27_CLK_SLCDC_AHB_GATE] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
+	clk[IMX27_CLK_SAHARA_AHB_GATE] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
+	clk[IMX27_CLK_RTIC_AHB_GATE] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14);
+	clk[IMX27_CLK_LCDC_AHB_GATE] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
+	clk[IMX27_CLK_VPU_AHB_GATE] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
+	clk[IMX27_CLK_FEC_AHB_GATE] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
+	clk[IMX27_CLK_EMMA_AHB_GATE] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
+	clk[IMX27_CLK_EMI_AHB_GATE] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
+	clk[IMX27_CLK_DMA_AHB_GATE] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
+	clk[IMX27_CLK_CSI_AHB_GATE] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
+	clk[IMX27_CLK_BROM_AHB_GATE] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
+	clk[IMX27_CLK_ATA_AHB_GATE] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
+	clk[IMX27_CLK_WDOG_IPG_GATE] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
+	clk[IMX27_CLK_USB_IPG_GATE] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
+	clk[IMX27_CLK_UART6_IPG_GATE] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
+	clk[IMX27_CLK_UART5_IPG_GATE] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
+	clk[IMX27_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
+	clk[IMX27_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
+	clk[IMX27_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
+	clk[IMX27_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
 
-	clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.0");
-	clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.1");
-	clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.2");
-	clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.3");
-	clk_register_clkdev(clk[uart5_ipg_gate], "ipg", "imx21-uart.4");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.4");
-	clk_register_clkdev(clk[uart6_ipg_gate], "ipg", "imx21-uart.5");
-	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.5");
-	clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0");
-	clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0");
-	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1");
-	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.1");
-	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.2");
-	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.2");
-	clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.0");
-	clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx27-cspi.0");
-	clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.1");
-	clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx27-cspi.1");
-	clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.2");
-	clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx27-cspi.2");
-	clk_register_clkdev(clk[per3_gate], "per", "imx21-fb.0");
-	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
-	clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
-	clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
-	clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
-	clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
-	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27");
-	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27");
-	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
-	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
-	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
-	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
-	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.1");
-	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.1");
-	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
-	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.2");
-	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.2");
-	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
-	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
-	clk_register_clkdev(clk[nfc_baud_gate], NULL, "imx27-nand.0");
-	clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
-	clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
-	clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx27-dma");
-	clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx27-dma");
-	clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
-	clk_register_clkdev(clk[fec_ahb_gate], "ahb", "imx27-fec.0");
-	clk_register_clkdev(clk[wdog_ipg_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx21-i2c.0");
-	clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx21-i2c.1");
-	clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");
-	clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad");
-	clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "imx27-camera.0");
-	clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "imx27-camera.0");
-	clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0");
-	clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0");
-	clk_register_clkdev(clk[cpu_div], NULL, "cpu0");
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
-	mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
+	clk_register_clkdev(clk[IMX27_CLK_CPU_DIV], NULL, "cpu0");
 
-	clk_prepare_enable(clk[emi_ahb_gate]);
+	clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
 
 	imx_print_silicon_rev("i.MX27", mx27_revision());
+}
+
+int __init mx27_clocks_init(unsigned long fref)
+{
+	ccm = ioremap(MX27_CCM_BASE_ADDR, SZ_4K);
+
+	_mx27_clocks_init(fref);
+
+	clk_register_clkdev(clk[IMX27_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.0");
+	clk_register_clkdev(clk[IMX27_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.1");
+	clk_register_clkdev(clk[IMX27_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.2");
+	clk_register_clkdev(clk[IMX27_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.3");
+	clk_register_clkdev(clk[IMX27_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.4");
+	clk_register_clkdev(clk[IMX27_CLK_UART6_IPG_GATE], "ipg", "imx21-uart.5");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.5");
+	clk_register_clkdev(clk[IMX27_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx-gpt.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.0");
+	clk_register_clkdev(clk[IMX27_CLK_SDHC1_IPG_GATE], "ipg", "imx21-mmc.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.1");
+	clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.1");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.2");
+	clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.2");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.0");
+	clk_register_clkdev(clk[IMX27_CLK_CSPI1_IPG_GATE], "ipg", "imx27-cspi.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.1");
+	clk_register_clkdev(clk[IMX27_CLK_CSPI2_IPG_GATE], "ipg", "imx27-cspi.1");
+	clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.2");
+	clk_register_clkdev(clk[IMX27_CLK_CSPI3_IPG_GATE], "ipg", "imx27-cspi.2");
+	clk_register_clkdev(clk[IMX27_CLK_PER3_GATE], "per", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX27_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX27_CLK_LCDC_AHB_GATE], "ahb", "imx21-fb.0");
+	clk_register_clkdev(clk[IMX27_CLK_CSI_AHB_GATE], "ahb", "imx27-camera.0");
+	clk_register_clkdev(clk[IMX27_CLK_PER4_GATE], "per", "imx27-camera.0");
+	clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "imx-udc-mx27");
+	clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "imx-udc-mx27");
+	clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "imx-udc-mx27");
+	clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.0");
+	clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.0");
+	clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.0");
+	clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.1");
+	clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.1");
+	clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.1");
+	clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.2");
+	clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.2");
+	clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.2");
+	clk_register_clkdev(clk[IMX27_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0");
+	clk_register_clkdev(clk[IMX27_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1");
+	clk_register_clkdev(clk[IMX27_CLK_NFC_BAUD_GATE], NULL, "imx27-nand.0");
+	clk_register_clkdev(clk[IMX27_CLK_VPU_BAUD_GATE], "per", "coda-imx27.0");
+	clk_register_clkdev(clk[IMX27_CLK_VPU_AHB_GATE], "ahb", "coda-imx27.0");
+	clk_register_clkdev(clk[IMX27_CLK_DMA_AHB_GATE], "ahb", "imx27-dma");
+	clk_register_clkdev(clk[IMX27_CLK_DMA_IPG_GATE], "ipg", "imx27-dma");
+	clk_register_clkdev(clk[IMX27_CLK_FEC_IPG_GATE], "ipg", "imx27-fec.0");
+	clk_register_clkdev(clk[IMX27_CLK_FEC_AHB_GATE], "ahb", "imx27-fec.0");
+	clk_register_clkdev(clk[IMX27_CLK_WDOG_IPG_GATE], NULL, "imx2-wdt.0");
+	clk_register_clkdev(clk[IMX27_CLK_I2C1_IPG_GATE], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[IMX27_CLK_I2C2_IPG_GATE], NULL, "imx21-i2c.1");
+	clk_register_clkdev(clk[IMX27_CLK_OWIRE_IPG_GATE], NULL, "mxc_w1.0");
+	clk_register_clkdev(clk[IMX27_CLK_KPP_IPG_GATE], NULL, "imx-keypad");
+	clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "emma-ahb", "imx27-camera.0");
+	clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "emma-ipg", "imx27-camera.0");
+	clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0");
+	clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0");
+
+	mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
 
 	return 0;
 }
 
-int __init mx27_clocks_init_dt(void)
+static void __init mx27_clocks_init_dt(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *refnp;
 	u32 fref = 26000000; /* default */
 
-	for_each_compatible_node(np, NULL, "fixed-clock") {
-		if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
+	for_each_compatible_node(refnp, NULL, "fixed-clock") {
+		if (!of_device_is_compatible(refnp, "fsl,imx-osc26m"))
 			continue;
 
-		if (!of_property_read_u32(np, "clock-frequency", &fref))
+		if (!of_property_read_u32(refnp, "clock-frequency", &fref))
 			break;
 	}
 
-	return mx27_clocks_init(fref);
+	ccm = of_iomap(np, 0);
+
+	_mx27_clocks_init(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(imx27_ccm, "fsl,imx27-ccm", mx27_clocks_init_dt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx31.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx31.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx31.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx31.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,6 @@ static struct clk_onecell_data clk_data;
 int __init mx31_clocks_init(unsigned long fref)
 {
 	void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
-	int i;
 	struct device_node *np;
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
@@ -114,10 +113,7 @@ int __init mx31_clocks_init(unsigned lon
 	clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MXC_CCM_CGR2, 10);
 	clk[firi_gate] = imx_clk_gate2("firi_gate", "upll", base+MXC_CCM_CGR2, 12);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("imx31 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx35.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx35.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx35.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx35.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,6 @@ int __init mx35_clocks_init(void)
 	u32 pdr0, consumer_sel, hsp_sel;
 	struct arm_ahb_div *aad;
 	unsigned char *hsp_div;
-	u32 i;
 
 	pdr0 = __raw_readl(base + MXC_CCM_PDR0);
 	consumer_sel = (pdr0 >> 16) & 0xf;
@@ -200,10 +199,7 @@ int __init mx35_clocks_init(void)
 	clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MX35_CCM_CGR3,  2);
 	clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "ahb", base + MX35_CCM_CGR3,  4);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX35 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
 	clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx51-imx53.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx51-imx53.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx51-imx53.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx51-imx53.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,11 +18,54 @@
 #include <linux/of_irq.h>
 #include <dt-bindings/clock/imx5-clock.h>
 
-#include "crm-regs-imx5.h"
 #include "clk.h"
 #include "common.h"
 #include "hardware.h"
 
+#define MX51_DPLL1_BASE		0x83f80000
+#define MX51_DPLL2_BASE		0x83f84000
+#define MX51_DPLL3_BASE		0x83f88000
+
+#define MX53_DPLL1_BASE		0x63f80000
+#define MX53_DPLL2_BASE		0x63f84000
+#define MX53_DPLL3_BASE		0x63f88000
+#define MX53_DPLL4_BASE		0x63f8c000
+
+#define MXC_CCM_CCR		(ccm_base + 0x00)
+#define MXC_CCM_CCDR		(ccm_base + 0x04)
+#define MXC_CCM_CSR		(ccm_base + 0x08)
+#define MXC_CCM_CCSR		(ccm_base + 0x0c)
+#define MXC_CCM_CACRR		(ccm_base + 0x10)
+#define MXC_CCM_CBCDR		(ccm_base + 0x14)
+#define MXC_CCM_CBCMR		(ccm_base + 0x18)
+#define MXC_CCM_CSCMR1		(ccm_base + 0x1c)
+#define MXC_CCM_CSCMR2		(ccm_base + 0x20)
+#define MXC_CCM_CSCDR1		(ccm_base + 0x24)
+#define MXC_CCM_CS1CDR		(ccm_base + 0x28)
+#define MXC_CCM_CS2CDR		(ccm_base + 0x2c)
+#define MXC_CCM_CDCDR		(ccm_base + 0x30)
+#define MXC_CCM_CHSCDR		(ccm_base + 0x34)
+#define MXC_CCM_CSCDR2		(ccm_base + 0x38)
+#define MXC_CCM_CSCDR3		(ccm_base + 0x3c)
+#define MXC_CCM_CSCDR4		(ccm_base + 0x40)
+#define MXC_CCM_CWDR		(ccm_base + 0x44)
+#define MXC_CCM_CDHIPR		(ccm_base + 0x48)
+#define MXC_CCM_CDCR		(ccm_base + 0x4c)
+#define MXC_CCM_CTOR		(ccm_base + 0x50)
+#define MXC_CCM_CLPCR		(ccm_base + 0x54)
+#define MXC_CCM_CISR		(ccm_base + 0x58)
+#define MXC_CCM_CIMR		(ccm_base + 0x5c)
+#define MXC_CCM_CCOSR		(ccm_base + 0x60)
+#define MXC_CCM_CGPR		(ccm_base + 0x64)
+#define MXC_CCM_CCGR0		(ccm_base + 0x68)
+#define MXC_CCM_CCGR1		(ccm_base + 0x6c)
+#define MXC_CCM_CCGR2		(ccm_base + 0x70)
+#define MXC_CCM_CCGR3		(ccm_base + 0x74)
+#define MXC_CCM_CCGR4		(ccm_base + 0x78)
+#define MXC_CCM_CCGR5		(ccm_base + 0x7c)
+#define MXC_CCM_CCGR6		(ccm_base + 0x80)
+#define MXC_CCM_CCGR7		(ccm_base + 0x84)
+
 /* Low-power Audio Playback Mode clock */
 static const char *lp_apm_sel[] = { "osc", };
 
@@ -86,17 +129,15 @@ static const char *mx51_spdif1_com_sel[]
 static struct clk *clk[IMX5_CLK_END];
 static struct clk_onecell_data clk_data;
 
-static void __init mx5_clocks_common_init(unsigned long rate_ckil,
-		unsigned long rate_osc, unsigned long rate_ckih1,
-		unsigned long rate_ckih2)
+static void __init mx5_clocks_common_init(void __iomem *ccm_base)
 {
-	int i;
+	imx5_pm_set_ccm_base(ccm_base);
 
 	clk[IMX5_CLK_DUMMY]		= imx_clk_fixed("dummy", 0);
-	clk[IMX5_CLK_CKIL]		= imx_obtain_fixed_clock("ckil", rate_ckil);
-	clk[IMX5_CLK_OSC]		= imx_obtain_fixed_clock("osc", rate_osc);
-	clk[IMX5_CLK_CKIH1]		= imx_obtain_fixed_clock("ckih1", rate_ckih1);
-	clk[IMX5_CLK_CKIH2]		= imx_obtain_fixed_clock("ckih2", rate_ckih2);
+	clk[IMX5_CLK_CKIL]		= imx_obtain_fixed_clock("ckil", 0);
+	clk[IMX5_CLK_OSC]		= imx_obtain_fixed_clock("osc", 0);
+	clk[IMX5_CLK_CKIH1]		= imx_obtain_fixed_clock("ckih1", 0);
+	clk[IMX5_CLK_CKIH2]		= imx_obtain_fixed_clock("ckih2", 0);
 
 	clk[IMX5_CLK_PERIPH_APM]	= imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
 						periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
@@ -244,58 +285,8 @@ static void __init mx5_clocks_common_ini
 	clk[IMX5_CLK_SAHARA_IPG_GATE]	= imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14);
 	clk[IMX5_CLK_SATA_REF]		= imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX5 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
-
-	clk_register_clkdev(clk[IMX5_CLK_GPT_HF_GATE], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[IMX5_CLK_GPT_IPG_GATE], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[IMX5_CLK_UART1_PER_GATE], "per", "imx21-uart.0");
-	clk_register_clkdev(clk[IMX5_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
-	clk_register_clkdev(clk[IMX5_CLK_UART2_PER_GATE], "per", "imx21-uart.1");
-	clk_register_clkdev(clk[IMX5_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
-	clk_register_clkdev(clk[IMX5_CLK_UART3_PER_GATE], "per", "imx21-uart.2");
-	clk_register_clkdev(clk[IMX5_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
-	clk_register_clkdev(clk[IMX5_CLK_UART4_PER_GATE], "per", "imx21-uart.3");
-	clk_register_clkdev(clk[IMX5_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
-	clk_register_clkdev(clk[IMX5_CLK_UART5_PER_GATE], "per", "imx21-uart.4");
-	clk_register_clkdev(clk[IMX5_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4");
-	clk_register_clkdev(clk[IMX5_CLK_ECSPI1_PER_GATE], "per", "imx51-ecspi.0");
-	clk_register_clkdev(clk[IMX5_CLK_ECSPI1_IPG_GATE], "ipg", "imx51-ecspi.0");
-	clk_register_clkdev(clk[IMX5_CLK_ECSPI2_PER_GATE], "per", "imx51-ecspi.1");
-	clk_register_clkdev(clk[IMX5_CLK_ECSPI2_IPG_GATE], "ipg", "imx51-ecspi.1");
-	clk_register_clkdev(clk[IMX5_CLK_CSPI_IPG_GATE], NULL, "imx35-cspi.2");
-	clk_register_clkdev(clk[IMX5_CLK_I2C1_GATE], NULL, "imx21-i2c.0");
-	clk_register_clkdev(clk[IMX5_CLK_I2C2_GATE], NULL, "imx21-i2c.1");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.0");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.0");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.0");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.1");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.1");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.1");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.2");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.2");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.2");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "imx-udc-mx51");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "imx-udc-mx51");
-	clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "imx-udc-mx51");
-	clk_register_clkdev(clk[IMX5_CLK_NFC_GATE], NULL, "imx51-nand");
-	clk_register_clkdev(clk[IMX5_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0");
-	clk_register_clkdev(clk[IMX5_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1");
-	clk_register_clkdev(clk[IMX5_CLK_SSI3_IPG_GATE], NULL, "imx-ssi.2");
-	clk_register_clkdev(clk[IMX5_CLK_SDMA_GATE], NULL, "imx35-sdma");
 	clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
-	clk_register_clkdev(clk[IMX5_CLK_IIM_GATE], "iim", NULL);
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.1");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx-keypad");
-	clk_register_clkdev(clk[IMX5_CLK_IPU_DI1_GATE], "di1", "imx-tve.0");
 	clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
-	clk_register_clkdev(clk[IMX5_CLK_EPIT1_IPG_GATE], "ipg", "imx-epit.0");
-	clk_register_clkdev(clk[IMX5_CLK_EPIT1_HF_GATE], "per", "imx-epit.0");
-	clk_register_clkdev(clk[IMX5_CLK_EPIT2_IPG_GATE], "ipg", "imx-epit.1");
-	clk_register_clkdev(clk[IMX5_CLK_EPIT2_HF_GATE], "per", "imx-epit.1");
 
 	/* Set SDHC parents to be PLL2 */
 	clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
@@ -322,12 +313,26 @@ static void __init mx5_clocks_common_ini
 
 static void __init mx50_clocks_init(struct device_node *np)
 {
+	void __iomem *ccm_base;
+	void __iomem *pll_base;
 	unsigned long r;
-	int i;
 
-	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
-	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
-	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
+	pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
 
 	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
 						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
@@ -349,17 +354,12 @@ static void __init mx50_clocks_init(stru
 	clk[IMX5_CLK_CKO2_PODF]		= imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
 	clk[IMX5_CLK_CKO2]		= imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX50 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	mx5_clocks_common_init(0, 0, 0, 0);
-
 	/* set SDHC root clock to 200MHZ*/
 	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
 	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
@@ -370,21 +370,32 @@ static void __init mx50_clocks_init(stru
 
 	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
 	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
-
-	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt"));
 }
 CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
 
-int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
-			unsigned long rate_ckih1, unsigned long rate_ckih2)
+static void __init mx51_clocks_init(struct device_node *np)
 {
-	int i;
+	void __iomem *ccm_base;
+	void __iomem *pll_base;
 	u32 val;
-	struct device_node *np;
 
-	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
-	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
-	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
+	pll_base = ioremap(MX51_DPLL1_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX51_DPLL2_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX51_DPLL3_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
+
 	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
 						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
 	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
@@ -417,35 +428,12 @@ int __init mx51_clocks_init(unsigned lon
 						mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel));
 	clk[IMX5_CLK_SPDIF1_GATE]	= imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX51 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-ccm");
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
-
-	clk_register_clkdev(clk[IMX5_CLK_HSI2C_GATE], NULL, "imx21-i2c.2");
-	clk_register_clkdev(clk[IMX5_CLK_MX51_MIPI], "mipi_hsp", NULL);
-	clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx27-fec.0");
-	clk_register_clkdev(clk[IMX5_CLK_USB_PHY_GATE], "phy", "mxc-ehci.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx51.0");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx51.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx51.1");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.1");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx51.1");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx51.2");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.2");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx51.2");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx51.3");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.3");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx51.3");
-
 	/* set the usboh3 parent to pll2_sw */
 	clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
 
@@ -453,9 +441,6 @@ int __init mx51_clocks_init(unsigned lon
 	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
 	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
 
-	/* System timer */
-	mxc_timer_init(MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_INT_GPT);
-
 	clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
 	imx_print_silicon_rev("i.MX51", mx51_revision());
 	clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
@@ -474,25 +459,35 @@ int __init mx51_clocks_init(unsigned lon
 	val = readl(MXC_CCM_CLPCR);
 	val |= 1 << 23;
 	writel(val, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void __init mx51_clocks_init_dt(struct device_node *np)
-{
-	mx51_clocks_init(0, 0, 0, 0);
 }
-CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
+CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
 
 static void __init mx53_clocks_init(struct device_node *np)
 {
-	int i;
+	void __iomem *ccm_base;
+	void __iomem *pll_base;
 	unsigned long r;
 
-	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
-	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
-	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
-	clk[IMX5_CLK_PLL4_SW]		= imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
+	pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+	pll_base = ioremap(MX53_DPLL4_BASE, SZ_16K);
+	WARN_ON(!pll_base);
+	clk[IMX5_CLK_PLL4_SW]		= imx_clk_pllv2("pll4_sw", "osc", pll_base);
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
 
 	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
 						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
@@ -543,33 +538,12 @@ static void __init mx53_clocks_init(stru
 	clk[IMX5_CLK_SPDIF_XTAL_SEL]	= imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
 						mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX53 clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	mx5_clocks_common_init(0, 0, 0, 0);
-
-	clk_register_clkdev(clk[IMX5_CLK_I2C3_GATE], NULL, "imx21-i2c.2");
-	clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx25-fec.0");
-	clk_register_clkdev(clk[IMX5_CLK_USB_PHY1_GATE], "usb_phy1", "mxc-ehci.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx53.0");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx53.0");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx53.1");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.1");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx53.1");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx53.2");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.2");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx53.2");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx53.3");
-	clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.3");
-	clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx53.3");
-
 	/* set SDHC root clock to 200MHZ*/
 	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
 	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
@@ -583,7 +557,5 @@ static void __init mx53_clocks_init(stru
 
 	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
 	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
-
-	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt"));
 }
 CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6q.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6q.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6q.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6q.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <dt-bindings/clock/imx6qdl-clock.h>
 
 #include "clk.h"
 #include "common.h"
@@ -73,48 +74,13 @@ static const char *lvds_sels[] = {
 	"pcie_ref_125m", "sata_ref_100m",
 };
 
-enum mx6q_clks {
-	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
-	pll3_pfd0_720m, pll3_pfd1_540m, pll3_pfd2_508m, pll3_pfd3_454m,
-	pll2_198m, pll3_120m, pll3_80m, pll3_60m, twd, step, pll1_sw,
-	periph_pre, periph2_pre, periph_clk2_sel, periph2_clk2_sel, axi_sel,
-	esai_sel, asrc_sel, spdif_sel, gpu2d_axi, gpu3d_axi, gpu2d_core_sel,
-	gpu3d_core_sel, gpu3d_shader_sel, ipu1_sel, ipu2_sel, ldb_di0_sel,
-	ldb_di1_sel, ipu1_di0_pre_sel, ipu1_di1_pre_sel, ipu2_di0_pre_sel,
-	ipu2_di1_pre_sel, ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel,
-	ipu2_di1_sel, hsi_tx_sel, pcie_axi_sel, ssi1_sel, ssi2_sel, ssi3_sel,
-	usdhc1_sel, usdhc2_sel, usdhc3_sel, usdhc4_sel, enfc_sel, emi_sel,
-	emi_slow_sel, vdo_axi_sel, vpu_axi_sel, cko1_sel, periph, periph2,
-	periph_clk2, periph2_clk2, ipg, ipg_per, esai_pred, esai_podf,
-	asrc_pred, asrc_podf, spdif_pred, spdif_podf, can_root, ecspi_root,
-	gpu2d_core_podf, gpu3d_core_podf, gpu3d_shader, ipu1_podf, ipu2_podf,
-	ldb_di0_podf, ldb_di1_podf, ipu1_di0_pre, ipu1_di1_pre, ipu2_di0_pre,
-	ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, ssi2_pred, ssi2_podf,
-	ssi3_pred, ssi3_podf, uart_serial_podf, usdhc1_podf, usdhc2_podf,
-	usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, emi_podf,
-	emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf,
-	mmdc_ch1_axi_podf, arm, ahb, apbh_dma, asrc, can1_ipg, can1_serial,
-	can2_ipg, can2_serial, ecspi1, ecspi2, ecspi3, ecspi4, ecspi5, enet,
-	esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
-	hdmi_isfr, i2c1, i2c2, i2c3, iim, enfc, ipu1, ipu1_di0, ipu1_di1, ipu2,
-	ipu2_di0, ldb_di0, ldb_di1, ipu2_di1, hsi_tx, mlb, mmdc_ch0_axi,
-	mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4, per1_bch,
-	gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
-	ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
-	usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
-	pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
-	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
-	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
-	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
-	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
-	lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, esai_ahb, clk_max
-};
-
-static struct clk *clk[clk_max];
+static struct clk *clk[IMX6QDL_CLK_END];
 static struct clk_onecell_data clk_data;
 
-static enum mx6q_clks const clks_init_on[] __initconst = {
-	mmdc_ch0_axi, rom, arm,
+static unsigned int const clks_init_on[] __initconst = {
+	IMX6QDL_CLK_MMDC_CH0_AXI,
+	IMX6QDL_CLK_ROM,
+	IMX6QDL_CLK_ARM,
 };
 
 static struct clk_div_table clk_enet_ref_table[] = {
@@ -149,10 +115,10 @@ static void __init imx6q_clocks_init(str
 	int i;
 	int ret;
 
-	clk[dummy] = imx_clk_fixed("dummy", 0);
-	clk[ckil] = imx_obtain_fixed_clock("ckil", 0);
-	clk[ckih] = imx_obtain_fixed_clock("ckih1", 0);
-	clk[osc] = imx_obtain_fixed_clock("osc", 0);
+	clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+	clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
+	clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0);
+	clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
 	base = of_iomap(np, 0);
@@ -166,14 +132,14 @@ static void __init imx6q_clocks_init(str
 		video_div_table[2].div = 1;
 	};
 
-	/*                   type                               name         parent_name  base     div_mask */
-	clk[pll1_sys]      = imx_clk_pllv3(IMX_PLLV3_SYS,	"pll1_sys",	"osc", base,        0x7f);
-	clk[pll2_bus]      = imx_clk_pllv3(IMX_PLLV3_GENERIC,	"pll2_bus",	"osc", base + 0x30, 0x1);
-	clk[pll3_usb_otg]  = imx_clk_pllv3(IMX_PLLV3_USB,	"pll3_usb_otg",	"osc", base + 0x10, 0x3);
-	clk[pll4_audio]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll4_audio",	"osc", base + 0x70, 0x7f);
-	clk[pll5_video]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll5_video",	"osc", base + 0xa0, 0x7f);
-	clk[pll6_enet]     = imx_clk_pllv3(IMX_PLLV3_ENET,	"pll6_enet",	"osc", base + 0xe0, 0x3);
-	clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB,	"pll7_usb_host","osc", base + 0x20, 0x3);
+	/*                                             type             name         parent_name  base     div_mask */
+	clk[IMX6QDL_CLK_PLL1_SYS]      = imx_clk_pllv3(IMX_PLLV3_SYS,	"pll1_sys",	"osc", base,        0x7f);
+	clk[IMX6QDL_CLK_PLL2_BUS]      = imx_clk_pllv3(IMX_PLLV3_GENERIC,	"pll2_bus",	"osc", base + 0x30, 0x1);
+	clk[IMX6QDL_CLK_PLL3_USB_OTG]  = imx_clk_pllv3(IMX_PLLV3_USB,	"pll3_usb_otg",	"osc", base + 0x10, 0x3);
+	clk[IMX6QDL_CLK_PLL4_AUDIO]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll4_audio",	"osc", base + 0x70, 0x7f);
+	clk[IMX6QDL_CLK_PLL5_VIDEO]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll5_video",	"osc", base + 0xa0, 0x7f);
+	clk[IMX6QDL_CLK_PLL6_ENET]     = imx_clk_pllv3(IMX_PLLV3_ENET,	"pll6_enet",	"osc", base + 0xe0, 0x3);
+	clk[IMX6QDL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB,	"pll7_usb_host","osc", base + 0x20, 0x3);
 
 	/*
 	 * Bit 20 is the reserved and read-only bit, we do this only for:
@@ -181,28 +147,28 @@ static void __init imx6q_clocks_init(str
 	 * - Keep refcount when do usbphy clk_enable/disable, in that case,
 	 * the clk framework may need to enable/disable usbphy's parent
 	 */
-	clk[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
-	clk[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+	clk[IMX6QDL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+	clk[IMX6QDL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
 
 	/*
 	 * usbphy*_gate needs to be on after system boots up, and software
 	 * never needs to control it anymore.
 	 */
-	clk[usbphy1_gate] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
-	clk[usbphy2_gate] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+	clk[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+	clk[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
 
-	clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
-	clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+	clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
+	clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
 
-	clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
-	clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
+	clk[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
+	clk[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
 
-	clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+	clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
 			base + 0xe0, 0, 2, 0, clk_enet_ref_table,
 			&imx_ccm_lock);
 
-	clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
-	clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+	clk[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+	clk[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
 
 	/*
 	 * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
@@ -210,29 +176,33 @@ static void __init imx6q_clocks_init(str
 	 * the "output_enable" bit as a gate, even though it's really just
 	 * enabling clock output.
 	 */
-	clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
-	clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
+	clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
+	clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
 
-	/*                                name              parent_name        reg       idx */
-	clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
-	clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
-	clk[pll2_pfd2_396m] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
-	clk[pll3_pfd0_720m] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
-	clk[pll3_pfd1_540m] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
-	clk[pll3_pfd2_508m] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
-	clk[pll3_pfd3_454m] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
+	/*                                            name              parent_name        reg       idx */
+	clk[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
+	clk[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
+	clk[IMX6QDL_CLK_PLL2_PFD2_396M] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
+	clk[IMX6QDL_CLK_PLL3_PFD0_720M] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+	clk[IMX6QDL_CLK_PLL3_PFD1_540M] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+	clk[IMX6QDL_CLK_PLL3_PFD2_508M] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
+	clk[IMX6QDL_CLK_PLL3_PFD3_454M] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
 
-	/*                                    name         parent_name     mult div */
-	clk[pll2_198m] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
-	clk[pll3_120m] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
-	clk[pll3_80m]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
-	clk[pll3_60m]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
-	clk[twd]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
+	/*                                                name         parent_name     mult div */
+	clk[IMX6QDL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+	clk[IMX6QDL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
+	clk[IMX6QDL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
+	clk[IMX6QDL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
+	clk[IMX6QDL_CLK_TWD]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
+	if (cpu_is_imx6dl()) {
+		clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1);
+		clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
+	}
 
-	clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
-	clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
-	clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
-	clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+	clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+	clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+	clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+	clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
 
 	np = ccm_node;
 	base = of_iomap(np, 0);
@@ -240,262 +210,256 @@ static void __init imx6q_clocks_init(str
 
 	imx6q_pm_set_ccm_base(base);
 
-	/*                                  name                reg       shift width parent_names     num_parents */
-	clk[step]             = imx_clk_mux("step",	        base + 0xc,  8,  1, step_sels,	       ARRAY_SIZE(step_sels));
-	clk[pll1_sw]          = imx_clk_mux("pll1_sw",	        base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
-	clk[periph_pre]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-	clk[periph2_pre]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-	clk[periph_clk2_sel]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
-	clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
-	clk[axi_sel]          = imx_clk_mux("axi_sel",          base + 0x14, 6,  2, axi_sels,          ARRAY_SIZE(axi_sels));
-	clk[esai_sel]         = imx_clk_mux("esai_sel",         base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
-	clk[asrc_sel]         = imx_clk_mux("asrc_sel",         base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
-	clk[spdif_sel]        = imx_clk_mux("spdif_sel",        base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
-	clk[gpu2d_axi]        = imx_clk_mux("gpu2d_axi",        base + 0x18, 0,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
-	clk[gpu3d_axi]        = imx_clk_mux("gpu3d_axi",        base + 0x18, 1,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
-	clk[gpu2d_core_sel]   = imx_clk_mux("gpu2d_core_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
-	clk[gpu3d_core_sel]   = imx_clk_mux("gpu3d_core_sel",   base + 0x18, 4,  2, gpu3d_core_sels,   ARRAY_SIZE(gpu3d_core_sels));
-	clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
-	clk[ipu1_sel]         = imx_clk_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-	clk[ipu2_sel]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-	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[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);
-	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[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[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);
-	clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
-	clk[ipu1_di0_sel]     = imx_clk_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
-	clk[ipu1_di1_sel]     = imx_clk_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
-	clk[ipu2_di0_sel]     = imx_clk_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
-	clk[ipu2_di1_sel]     = imx_clk_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
-	clk[hsi_tx_sel]       = imx_clk_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
-	clk[pcie_axi_sel]     = imx_clk_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
-	clk[ssi1_sel]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
-	clk[ssi2_sel]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
-	clk[ssi3_sel]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
-	clk[usdhc1_sel]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
-	clk[usdhc2_sel]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
-	clk[usdhc3_sel]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
-	clk[usdhc4_sel]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),        imx_cscmr1_fixup);
-	clk[enfc_sel]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
-	clk[emi_sel]          = imx_clk_fixup_mux("emi_sel",      base + 0x1c, 27, 2, emi_sels,        ARRAY_SIZE(emi_sels),          imx_cscmr1_fixup);
-	clk[emi_slow_sel]     = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels,   ARRAY_SIZE(emi_slow_sels),     imx_cscmr1_fixup);
-	clk[vdo_axi_sel]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
-	clk[vpu_axi_sel]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
-	clk[cko1_sel]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
-	clk[cko2_sel]         = imx_clk_mux("cko2_sel",         base + 0x60, 16, 5, cko2_sels,         ARRAY_SIZE(cko2_sels));
-	clk[cko]              = imx_clk_mux("cko",              base + 0x60, 8, 1,  cko_sels,          ARRAY_SIZE(cko_sels));
+	/*                                              name                reg       shift width parent_names     num_parents */
+	clk[IMX6QDL_CLK_STEP]             = imx_clk_mux("step",	            base + 0xc,  8,  1, step_sels,	   ARRAY_SIZE(step_sels));
+	clk[IMX6QDL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",	    base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
+	clk[IMX6QDL_CLK_PERIPH_PRE]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
+	clk[IMX6QDL_CLK_PERIPH2_PRE]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
+	clk[IMX6QDL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+	clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+	clk[IMX6QDL_CLK_AXI_SEL]          = imx_clk_mux("axi_sel",          base + 0x14, 6,  2, axi_sels,          ARRAY_SIZE(axi_sels));
+	clk[IMX6QDL_CLK_ESAI_SEL]         = imx_clk_mux("esai_sel",         base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+	clk[IMX6QDL_CLK_ASRC_SEL]         = imx_clk_mux("asrc_sel",         base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
+	clk[IMX6QDL_CLK_SPDIF_SEL]        = imx_clk_mux("spdif_sel",        base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+	if (cpu_is_imx6q()) {
+		clk[IMX6QDL_CLK_GPU2D_AXI]        = imx_clk_mux("gpu2d_axi",        base + 0x18, 0,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
+		clk[IMX6QDL_CLK_GPU3D_AXI]        = imx_clk_mux("gpu3d_axi",        base + 0x18, 1,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
+	}
+	clk[IMX6QDL_CLK_GPU2D_CORE_SEL]   = imx_clk_mux("gpu2d_core_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
+	clk[IMX6QDL_CLK_GPU3D_CORE_SEL]   = imx_clk_mux("gpu3d_core_sel",   base + 0x18, 4,  2, gpu3d_core_sels,   ARRAY_SIZE(gpu3d_core_sels));
+	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);
+	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);
+	clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+	clk[IMX6QDL_CLK_IPU1_DI0_SEL]     = imx_clk_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
+	clk[IMX6QDL_CLK_IPU1_DI1_SEL]     = imx_clk_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
+	clk[IMX6QDL_CLK_IPU2_DI0_SEL]     = imx_clk_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
+	clk[IMX6QDL_CLK_IPU2_DI1_SEL]     = imx_clk_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
+	clk[IMX6QDL_CLK_HSI_TX_SEL]       = imx_clk_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
+	clk[IMX6QDL_CLK_PCIE_AXI_SEL]     = imx_clk_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
+	clk[IMX6QDL_CLK_SSI1_SEL]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_SSI2_SEL]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_SSI3_SEL]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_USDHC1_SEL]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
+	clk[IMX6QDL_CLK_EMI_SEL]          = imx_clk_fixup_mux("emi_sel",      base + 0x1c, 27, 2, emi_sels,        ARRAY_SIZE(emi_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_EMI_SLOW_SEL]     = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels,   ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_VDO_AXI_SEL]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
+	clk[IMX6QDL_CLK_VPU_AXI_SEL]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
+	clk[IMX6QDL_CLK_CKO1_SEL]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
+	clk[IMX6QDL_CLK_CKO2_SEL]         = imx_clk_mux("cko2_sel",         base + 0x60, 16, 5, cko2_sels,         ARRAY_SIZE(cko2_sels));
+	clk[IMX6QDL_CLK_CKO]              = imx_clk_mux("cko",              base + 0x60, 8, 1,  cko_sels,          ARRAY_SIZE(cko_sels));
 
-	/*                              name         reg      shift width busy: reg, shift parent_names  num_parents */
-	clk[periph]  = imx_clk_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
-	clk[periph2] = imx_clk_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
+	/*                                          name         reg      shift width busy: reg, shift parent_names  num_parents */
+	clk[IMX6QDL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
+	clk[IMX6QDL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
 
-	/*                                      name                parent_name          reg       shift width */
-	clk[periph_clk2]      = imx_clk_divider("periph_clk2",      "periph_clk2_sel",   base + 0x14, 27, 3);
-	clk[periph2_clk2]     = imx_clk_divider("periph2_clk2",     "periph2_clk2_sel",  base + 0x14, 0,  3);
-	clk[ipg]              = imx_clk_divider("ipg",              "ahb",               base + 0x14, 8,  2);
-	clk[ipg_per]          = imx_clk_fixup_divider("ipg_per",    "ipg",               base + 0x1c, 0,  6, imx_cscmr1_fixup);
-	clk[esai_pred]        = imx_clk_divider("esai_pred",        "esai_sel",          base + 0x28, 9,  3);
-	clk[esai_podf]        = imx_clk_divider("esai_podf",        "esai_pred",         base + 0x28, 25, 3);
-	clk[asrc_pred]        = imx_clk_divider("asrc_pred",        "asrc_sel",          base + 0x30, 12, 3);
-	clk[asrc_podf]        = imx_clk_divider("asrc_podf",        "asrc_pred",         base + 0x30, 9,  3);
-	clk[spdif_pred]       = imx_clk_divider("spdif_pred",       "spdif_sel",         base + 0x30, 25, 3);
-	clk[spdif_podf]       = imx_clk_divider("spdif_podf",       "spdif_pred",        base + 0x30, 22, 3);
-	clk[can_root]         = imx_clk_divider("can_root",         "pll3_60m",          base + 0x20, 2,  6);
-	clk[ecspi_root]       = imx_clk_divider("ecspi_root",       "pll3_60m",          base + 0x38, 19, 6);
-	clk[gpu2d_core_podf]  = imx_clk_divider("gpu2d_core_podf",  "gpu2d_core_sel",    base + 0x18, 23, 3);
-	clk[gpu3d_core_podf]  = imx_clk_divider("gpu3d_core_podf",  "gpu3d_core_sel",    base + 0x18, 26, 3);
-	clk[gpu3d_shader]     = imx_clk_divider("gpu3d_shader",     "gpu3d_shader_sel",  base + 0x18, 29, 3);
-	clk[ipu1_podf]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
-	clk[ipu2_podf]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
-	clk[ldb_di0_div_3_5]  = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-	clk[ldb_di0_podf]     = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
-	clk[ldb_di1_div_3_5]  = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
-	clk[ldb_di1_podf]     = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
-	clk[ipu1_di0_pre]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
-	clk[ipu1_di1_pre]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
-	clk[ipu2_di0_pre]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
-	clk[ipu2_di1_pre]     = imx_clk_divider("ipu2_di1_pre",     "ipu2_di1_pre_sel",  base + 0x38, 12, 3);
-	clk[hsi_tx_podf]      = imx_clk_divider("hsi_tx_podf",      "hsi_tx_sel",        base + 0x30, 29, 3);
-	clk[ssi1_pred]        = imx_clk_divider("ssi1_pred",        "ssi1_sel",          base + 0x28, 6,  3);
-	clk[ssi1_podf]        = imx_clk_divider("ssi1_podf",        "ssi1_pred",         base + 0x28, 0,  6);
-	clk[ssi2_pred]        = imx_clk_divider("ssi2_pred",        "ssi2_sel",          base + 0x2c, 6,  3);
-	clk[ssi2_podf]        = imx_clk_divider("ssi2_podf",        "ssi2_pred",         base + 0x2c, 0,  6);
-	clk[ssi3_pred]        = imx_clk_divider("ssi3_pred",        "ssi3_sel",          base + 0x28, 22, 3);
-	clk[ssi3_podf]        = imx_clk_divider("ssi3_podf",        "ssi3_pred",         base + 0x28, 16, 6);
-	clk[uart_serial_podf] = imx_clk_divider("uart_serial_podf", "pll3_80m",          base + 0x24, 0,  6);
-	clk[usdhc1_podf]      = imx_clk_divider("usdhc1_podf",      "usdhc1_sel",        base + 0x24, 11, 3);
-	clk[usdhc2_podf]      = imx_clk_divider("usdhc2_podf",      "usdhc2_sel",        base + 0x24, 16, 3);
-	clk[usdhc3_podf]      = imx_clk_divider("usdhc3_podf",      "usdhc3_sel",        base + 0x24, 19, 3);
-	clk[usdhc4_podf]      = imx_clk_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
-	clk[enfc_pred]        = imx_clk_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
-	clk[enfc_podf]        = imx_clk_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
-	clk[emi_podf]         = imx_clk_fixup_divider("emi_podf",   "emi_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
-	clk[emi_slow_podf]    = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
-	clk[vpu_axi_podf]     = imx_clk_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
-	clk[cko1_podf]        = imx_clk_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
-	clk[cko2_podf]        = imx_clk_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
+	/*                                                  name                parent_name          reg       shift width */
+	clk[IMX6QDL_CLK_PERIPH_CLK2]      = imx_clk_divider("periph_clk2",      "periph_clk2_sel",   base + 0x14, 27, 3);
+	clk[IMX6QDL_CLK_PERIPH2_CLK2]     = imx_clk_divider("periph2_clk2",     "periph2_clk2_sel",  base + 0x14, 0,  3);
+	clk[IMX6QDL_CLK_IPG]              = imx_clk_divider("ipg",              "ahb",               base + 0x14, 8,  2);
+	clk[IMX6QDL_CLK_IPG_PER]          = imx_clk_fixup_divider("ipg_per",    "ipg",               base + 0x1c, 0,  6, imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_ESAI_PRED]        = imx_clk_divider("esai_pred",        "esai_sel",          base + 0x28, 9,  3);
+	clk[IMX6QDL_CLK_ESAI_PODF]        = imx_clk_divider("esai_podf",        "esai_pred",         base + 0x28, 25, 3);
+	clk[IMX6QDL_CLK_ASRC_PRED]        = imx_clk_divider("asrc_pred",        "asrc_sel",          base + 0x30, 12, 3);
+	clk[IMX6QDL_CLK_ASRC_PODF]        = imx_clk_divider("asrc_podf",        "asrc_pred",         base + 0x30, 9,  3);
+	clk[IMX6QDL_CLK_SPDIF_PRED]       = imx_clk_divider("spdif_pred",       "spdif_sel",         base + 0x30, 25, 3);
+	clk[IMX6QDL_CLK_SPDIF_PODF]       = imx_clk_divider("spdif_podf",       "spdif_pred",        base + 0x30, 22, 3);
+	clk[IMX6QDL_CLK_CAN_ROOT]         = imx_clk_divider("can_root",         "pll3_60m",          base + 0x20, 2,  6);
+	clk[IMX6QDL_CLK_ECSPI_ROOT]       = imx_clk_divider("ecspi_root",       "pll3_60m",          base + 0x38, 19, 6);
+	clk[IMX6QDL_CLK_GPU2D_CORE_PODF]  = imx_clk_divider("gpu2d_core_podf",  "gpu2d_core_sel",    base + 0x18, 23, 3);
+	clk[IMX6QDL_CLK_GPU3D_CORE_PODF]  = imx_clk_divider("gpu3d_core_podf",  "gpu3d_core_sel",    base + 0x18, 26, 3);
+	clk[IMX6QDL_CLK_GPU3D_SHADER]     = imx_clk_divider("gpu3d_shader",     "gpu3d_shader_sel",  base + 0x18, 29, 3);
+	clk[IMX6QDL_CLK_IPU1_PODF]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
+	clk[IMX6QDL_CLK_IPU2_PODF]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
+	clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5]  = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+	clk[IMX6QDL_CLK_LDB_DI0_PODF]     = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
+	clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5]  = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+	clk[IMX6QDL_CLK_LDB_DI1_PODF]     = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
+	clk[IMX6QDL_CLK_IPU1_DI0_PRE]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
+	clk[IMX6QDL_CLK_IPU1_DI1_PRE]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
+	clk[IMX6QDL_CLK_IPU2_DI0_PRE]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
+	clk[IMX6QDL_CLK_IPU2_DI1_PRE]     = imx_clk_divider("ipu2_di1_pre",     "ipu2_di1_pre_sel",  base + 0x38, 12, 3);
+	clk[IMX6QDL_CLK_HSI_TX_PODF]      = imx_clk_divider("hsi_tx_podf",      "hsi_tx_sel",        base + 0x30, 29, 3);
+	clk[IMX6QDL_CLK_SSI1_PRED]        = imx_clk_divider("ssi1_pred",        "ssi1_sel",          base + 0x28, 6,  3);
+	clk[IMX6QDL_CLK_SSI1_PODF]        = imx_clk_divider("ssi1_podf",        "ssi1_pred",         base + 0x28, 0,  6);
+	clk[IMX6QDL_CLK_SSI2_PRED]        = imx_clk_divider("ssi2_pred",        "ssi2_sel",          base + 0x2c, 6,  3);
+	clk[IMX6QDL_CLK_SSI2_PODF]        = imx_clk_divider("ssi2_podf",        "ssi2_pred",         base + 0x2c, 0,  6);
+	clk[IMX6QDL_CLK_SSI3_PRED]        = imx_clk_divider("ssi3_pred",        "ssi3_sel",          base + 0x28, 22, 3);
+	clk[IMX6QDL_CLK_SSI3_PODF]        = imx_clk_divider("ssi3_podf",        "ssi3_pred",         base + 0x28, 16, 6);
+	clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "pll3_80m",          base + 0x24, 0,  6);
+	clk[IMX6QDL_CLK_USDHC1_PODF]      = imx_clk_divider("usdhc1_podf",      "usdhc1_sel",        base + 0x24, 11, 3);
+	clk[IMX6QDL_CLK_USDHC2_PODF]      = imx_clk_divider("usdhc2_podf",      "usdhc2_sel",        base + 0x24, 16, 3);
+	clk[IMX6QDL_CLK_USDHC3_PODF]      = imx_clk_divider("usdhc3_podf",      "usdhc3_sel",        base + 0x24, 19, 3);
+	clk[IMX6QDL_CLK_USDHC4_PODF]      = imx_clk_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
+	clk[IMX6QDL_CLK_ENFC_PRED]        = imx_clk_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
+	clk[IMX6QDL_CLK_ENFC_PODF]        = imx_clk_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
+	clk[IMX6QDL_CLK_EMI_PODF]         = imx_clk_fixup_divider("emi_podf",   "emi_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_EMI_SLOW_PODF]    = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
+	clk[IMX6QDL_CLK_VPU_AXI_PODF]     = imx_clk_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
+	clk[IMX6QDL_CLK_CKO1_PODF]        = imx_clk_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
+	clk[IMX6QDL_CLK_CKO2_PODF]        = imx_clk_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
 
-	/*                                            name                 parent_name    reg        shift width busy: reg, shift */
-	clk[axi]               = imx_clk_busy_divider("axi",               "axi_sel",     base + 0x14, 16,  3,   base + 0x48, 0);
-	clk[mmdc_ch0_axi_podf] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph",      base + 0x14, 19,  3,   base + 0x48, 4);
-	clk[mmdc_ch1_axi_podf] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2",     base + 0x14, 3,   3,   base + 0x48, 2);
-	clk[arm]               = imx_clk_busy_divider("arm",               "pll1_sw",     base + 0x10, 0,   3,   base + 0x48, 16);
-	clk[ahb]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
+	/*                                                        name                 parent_name    reg        shift width busy: reg, shift */
+	clk[IMX6QDL_CLK_AXI]               = imx_clk_busy_divider("axi",               "axi_sel",     base + 0x14, 16,  3,   base + 0x48, 0);
+	clk[IMX6QDL_CLK_MMDC_CH0_AXI_PODF] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph",      base + 0x14, 19,  3,   base + 0x48, 4);
+	clk[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2",     base + 0x14, 3,   3,   base + 0x48, 2);
+	clk[IMX6QDL_CLK_ARM]               = imx_clk_busy_divider("arm",               "pll1_sw",     base + 0x10, 0,   3,   base + 0x48, 16);
+	clk[IMX6QDL_CLK_AHB]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
 
-	/*                                name             parent_name          reg         shift */
-	clk[apbh_dma]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
-	clk[asrc]         = imx_clk_gate2("asrc",          "asrc_podf",         base + 0x68, 6);
-	clk[can1_ipg]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
-	clk[can1_serial]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
-	clk[can2_ipg]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
-	clk[can2_serial]  = imx_clk_gate2("can2_serial",   "can_root",          base + 0x68, 20);
-	clk[ecspi1]       = imx_clk_gate2("ecspi1",        "ecspi_root",        base + 0x6c, 0);
-	clk[ecspi2]       = imx_clk_gate2("ecspi2",        "ecspi_root",        base + 0x6c, 2);
-	clk[ecspi3]       = imx_clk_gate2("ecspi3",        "ecspi_root",        base + 0x6c, 4);
-	clk[ecspi4]       = imx_clk_gate2("ecspi4",        "ecspi_root",        base + 0x6c, 6);
+	/*                                            name             parent_name          reg         shift */
+	clk[IMX6QDL_CLK_APBH_DMA]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
+	clk[IMX6QDL_CLK_ASRC]         = imx_clk_gate2("asrc",          "asrc_podf",         base + 0x68, 6);
+	clk[IMX6QDL_CLK_CAN1_IPG]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
+	clk[IMX6QDL_CLK_CAN1_SERIAL]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
+	clk[IMX6QDL_CLK_CAN2_IPG]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
+	clk[IMX6QDL_CLK_CAN2_SERIAL]  = imx_clk_gate2("can2_serial",   "can_root",          base + 0x68, 20);
+	clk[IMX6QDL_CLK_ECSPI1]       = imx_clk_gate2("ecspi1",        "ecspi_root",        base + 0x6c, 0);
+	clk[IMX6QDL_CLK_ECSPI2]       = imx_clk_gate2("ecspi2",        "ecspi_root",        base + 0x6c, 2);
+	clk[IMX6QDL_CLK_ECSPI3]       = imx_clk_gate2("ecspi3",        "ecspi_root",        base + 0x6c, 4);
+	clk[IMX6QDL_CLK_ECSPI4]       = imx_clk_gate2("ecspi4",        "ecspi_root",        base + 0x6c, 6);
 	if (cpu_is_imx6dl())
-		/* ecspi5 is replaced with i2c4 on imx6dl & imx6s */
-		clk[ecspi5] = imx_clk_gate2("i2c4",        "ipg_per",           base + 0x6c, 8);
+		clk[IMX6DL_CLK_I2C4]  = imx_clk_gate2("i2c4",          "ipg_per",           base + 0x6c, 8);
 	else
-		clk[ecspi5] = imx_clk_gate2("ecspi5",      "ecspi_root",        base + 0x6c, 8);
-	clk[enet]         = imx_clk_gate2("enet",          "ipg",               base + 0x6c, 10);
-	clk[esai]         = imx_clk_gate2_shared("esai",   "esai_podf",         base + 0x6c, 16, &share_count_esai);
-	clk[esai_ahb]     = imx_clk_gate2_shared("esai_ahb", "ahb",             base + 0x6c, 16, &share_count_esai);
-	clk[gpt_ipg]      = imx_clk_gate2("gpt_ipg",       "ipg",               base + 0x6c, 20);
-	clk[gpt_ipg_per]  = imx_clk_gate2("gpt_ipg_per",   "ipg_per",           base + 0x6c, 22);
+		clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5",        "ecspi_root",        base + 0x6c, 8);
+	clk[IMX6QDL_CLK_ENET]         = imx_clk_gate2("enet",          "ipg",               base + 0x6c, 10);
+	clk[IMX6QDL_CLK_ESAI]         = imx_clk_gate2_shared("esai",   "esai_podf",         base + 0x6c, 16, &share_count_esai);
+	clk[IMX6QDL_CLK_ESAI_AHB]     = imx_clk_gate2_shared("esai_ahb", "ahb",             base + 0x6c, 16, &share_count_esai);
+	clk[IMX6QDL_CLK_GPT_IPG]      = imx_clk_gate2("gpt_ipg",       "ipg",               base + 0x6c, 20);
+	clk[IMX6QDL_CLK_GPT_IPG_PER]  = imx_clk_gate2("gpt_ipg_per",   "ipg_per",           base + 0x6c, 22);
 	if (cpu_is_imx6dl())
 		/*
 		 * The multiplexer and divider of imx6q clock gpu3d_shader get
 		 * redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl.
 		 */
-		clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24);
+		clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24);
 	else
-		clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
-	clk[gpu3d_core]   = imx_clk_gate2("gpu3d_core",    "gpu3d_core_podf",   base + 0x6c, 26);
-	clk[hdmi_iahb]    = imx_clk_gate2("hdmi_iahb",     "ahb",               base + 0x70, 0);
-	clk[hdmi_isfr]    = imx_clk_gate2("hdmi_isfr",     "pll3_pfd1_540m",    base + 0x70, 4);
-	clk[i2c1]         = imx_clk_gate2("i2c1",          "ipg_per",           base + 0x70, 6);
-	clk[i2c2]         = imx_clk_gate2("i2c2",          "ipg_per",           base + 0x70, 8);
-	clk[i2c3]         = imx_clk_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
-	clk[iim]          = imx_clk_gate2("iim",           "ipg",               base + 0x70, 12);
-	clk[enfc]         = imx_clk_gate2("enfc",          "enfc_podf",         base + 0x70, 14);
-	clk[vdoa]         = imx_clk_gate2("vdoa",          "vdo_axi",           base + 0x70, 26);
-	clk[ipu1]         = imx_clk_gate2("ipu1",          "ipu1_podf",         base + 0x74, 0);
-	clk[ipu1_di0]     = imx_clk_gate2("ipu1_di0",      "ipu1_di0_sel",      base + 0x74, 2);
-	clk[ipu1_di1]     = imx_clk_gate2("ipu1_di1",      "ipu1_di1_sel",      base + 0x74, 4);
-	clk[ipu2]         = imx_clk_gate2("ipu2",          "ipu2_podf",         base + 0x74, 6);
-	clk[ipu2_di0]     = imx_clk_gate2("ipu2_di0",      "ipu2_di0_sel",      base + 0x74, 8);
-	clk[ldb_di0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_podf",      base + 0x74, 12);
-	clk[ldb_di1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
-	clk[ipu2_di1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
-	clk[hsi_tx]       = imx_clk_gate2("hsi_tx",        "hsi_tx_podf",       base + 0x74, 16);
+		clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
+	clk[IMX6QDL_CLK_GPU3D_CORE]   = imx_clk_gate2("gpu3d_core",    "gpu3d_core_podf",   base + 0x6c, 26);
+	clk[IMX6QDL_CLK_HDMI_IAHB]    = imx_clk_gate2("hdmi_iahb",     "ahb",               base + 0x70, 0);
+	clk[IMX6QDL_CLK_HDMI_ISFR]    = imx_clk_gate2("hdmi_isfr",     "pll3_pfd1_540m",    base + 0x70, 4);
+	clk[IMX6QDL_CLK_I2C1]         = imx_clk_gate2("i2c1",          "ipg_per",           base + 0x70, 6);
+	clk[IMX6QDL_CLK_I2C2]         = imx_clk_gate2("i2c2",          "ipg_per",           base + 0x70, 8);
+	clk[IMX6QDL_CLK_I2C3]         = imx_clk_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
+	clk[IMX6QDL_CLK_IIM]          = imx_clk_gate2("iim",           "ipg",               base + 0x70, 12);
+	clk[IMX6QDL_CLK_ENFC]         = imx_clk_gate2("enfc",          "enfc_podf",         base + 0x70, 14);
+	clk[IMX6QDL_CLK_VDOA]         = imx_clk_gate2("vdoa",          "vdo_axi",           base + 0x70, 26);
+	clk[IMX6QDL_CLK_IPU1]         = imx_clk_gate2("ipu1",          "ipu1_podf",         base + 0x74, 0);
+	clk[IMX6QDL_CLK_IPU1_DI0]     = imx_clk_gate2("ipu1_di0",      "ipu1_di0_sel",      base + 0x74, 2);
+	clk[IMX6QDL_CLK_IPU1_DI1]     = imx_clk_gate2("ipu1_di1",      "ipu1_di1_sel",      base + 0x74, 4);
+	clk[IMX6QDL_CLK_IPU2]         = imx_clk_gate2("ipu2",          "ipu2_podf",         base + 0x74, 6);
+	clk[IMX6QDL_CLK_IPU2_DI0]     = imx_clk_gate2("ipu2_di0",      "ipu2_di0_sel",      base + 0x74, 8);
+	clk[IMX6QDL_CLK_LDB_DI0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_podf",      base + 0x74, 12);
+	clk[IMX6QDL_CLK_LDB_DI1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
+	clk[IMX6QDL_CLK_IPU2_DI1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
+	clk[IMX6QDL_CLK_HSI_TX]       = imx_clk_gate2("hsi_tx",        "hsi_tx_podf",       base + 0x74, 16);
 	if (cpu_is_imx6dl())
 		/*
 		 * The multiplexer and divider of the imx6q clock gpu2d get
 		 * redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl.
 		 */
-		clk[mlb] = imx_clk_gate2("mlb",            "gpu2d_core_podf",   base + 0x74, 18);
+		clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb",            "gpu2d_core_podf",   base + 0x74, 18);
 	else
-		clk[mlb] = imx_clk_gate2("mlb",            "axi",               base + 0x74, 18);
-	clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20);
-	clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
-	clk[ocram]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
-	clk[openvg_axi]   = imx_clk_gate2("openvg_axi",    "axi",               base + 0x74, 30);
-	clk[pcie_axi]     = imx_clk_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
-	clk[per1_bch]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
-	clk[pwm1]         = imx_clk_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
-	clk[pwm2]         = imx_clk_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
-	clk[pwm3]         = imx_clk_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
-	clk[pwm4]         = imx_clk_gate2("pwm4",          "ipg_per",           base + 0x78, 22);
-	clk[gpmi_bch_apb] = imx_clk_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
-	clk[gpmi_bch]     = imx_clk_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
-	clk[gpmi_io]      = imx_clk_gate2("gpmi_io",       "enfc",              base + 0x78, 28);
-	clk[gpmi_apb]     = imx_clk_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
-	clk[rom]          = imx_clk_gate2("rom",           "ahb",               base + 0x7c, 0);
-	clk[sata]         = imx_clk_gate2("sata",          "ipg",               base + 0x7c, 4);
-	clk[sdma]         = imx_clk_gate2("sdma",          "ahb",               base + 0x7c, 6);
-	clk[spba]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
-	clk[spdif]        = imx_clk_gate2("spdif",         "spdif_podf",    	base + 0x7c, 14);
-	clk[ssi1_ipg]     = imx_clk_gate2("ssi1_ipg",      "ipg",               base + 0x7c, 18);
-	clk[ssi2_ipg]     = imx_clk_gate2("ssi2_ipg",      "ipg",               base + 0x7c, 20);
-	clk[ssi3_ipg]     = imx_clk_gate2("ssi3_ipg",      "ipg",               base + 0x7c, 22);
-	clk[uart_ipg]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
-	clk[uart_serial]  = imx_clk_gate2("uart_serial",   "uart_serial_podf",  base + 0x7c, 26);
-	clk[usboh3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
-	clk[usdhc1]       = imx_clk_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
-	clk[usdhc2]       = imx_clk_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
-	clk[usdhc3]       = imx_clk_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
-	clk[usdhc4]       = imx_clk_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
-	clk[eim_slow]     = imx_clk_gate2("eim_slow",      "emi_slow_podf",     base + 0x80, 10);
-	clk[vdo_axi]      = imx_clk_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
-	clk[vpu_axi]      = imx_clk_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
-	clk[cko1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
-	clk[cko2]         = imx_clk_gate("cko2",           "cko2_podf",         base + 0x60, 24);
+		clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb",            "axi",               base + 0x74, 18);
+	clk[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_gate2("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20);
+	clk[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
+	clk[IMX6QDL_CLK_OCRAM]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
+	clk[IMX6QDL_CLK_OPENVG_AXI]   = imx_clk_gate2("openvg_axi",    "axi",               base + 0x74, 30);
+	clk[IMX6QDL_CLK_PCIE_AXI]     = imx_clk_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
+	clk[IMX6QDL_CLK_PER1_BCH]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
+	clk[IMX6QDL_CLK_PWM1]         = imx_clk_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
+	clk[IMX6QDL_CLK_PWM2]         = imx_clk_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
+	clk[IMX6QDL_CLK_PWM3]         = imx_clk_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
+	clk[IMX6QDL_CLK_PWM4]         = imx_clk_gate2("pwm4",          "ipg_per",           base + 0x78, 22);
+	clk[IMX6QDL_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
+	clk[IMX6QDL_CLK_GPMI_BCH]     = imx_clk_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
+	clk[IMX6QDL_CLK_GPMI_IO]      = imx_clk_gate2("gpmi_io",       "enfc",              base + 0x78, 28);
+	clk[IMX6QDL_CLK_GPMI_APB]     = imx_clk_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
+	clk[IMX6QDL_CLK_ROM]          = imx_clk_gate2("rom",           "ahb",               base + 0x7c, 0);
+	clk[IMX6QDL_CLK_SATA]         = imx_clk_gate2("sata",          "ipg",               base + 0x7c, 4);
+	clk[IMX6QDL_CLK_SDMA]         = imx_clk_gate2("sdma",          "ahb",               base + 0x7c, 6);
+	clk[IMX6QDL_CLK_SPBA]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
+	clk[IMX6QDL_CLK_SPDIF]        = imx_clk_gate2("spdif",         "spdif_podf",        base + 0x7c, 14);
+	clk[IMX6QDL_CLK_SSI1_IPG]     = imx_clk_gate2("ssi1_ipg",      "ipg",               base + 0x7c, 18);
+	clk[IMX6QDL_CLK_SSI2_IPG]     = imx_clk_gate2("ssi2_ipg",      "ipg",               base + 0x7c, 20);
+	clk[IMX6QDL_CLK_SSI3_IPG]     = imx_clk_gate2("ssi3_ipg",      "ipg",               base + 0x7c, 22);
+	clk[IMX6QDL_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
+	clk[IMX6QDL_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_serial_podf",  base + 0x7c, 26);
+	clk[IMX6QDL_CLK_USBOH3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
+	clk[IMX6QDL_CLK_USDHC1]       = imx_clk_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
+	clk[IMX6QDL_CLK_USDHC2]       = imx_clk_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
+	clk[IMX6QDL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
+	clk[IMX6QDL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
+	clk[IMX6QDL_CLK_EIM_SLOW]     = imx_clk_gate2("eim_slow",      "emi_slow_podf",     base + 0x80, 10);
+	clk[IMX6QDL_CLK_VDO_AXI]      = imx_clk_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
+	clk[IMX6QDL_CLK_VPU_AXI]      = imx_clk_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
+	clk[IMX6QDL_CLK_CKO1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
+	clk[IMX6QDL_CLK_CKO2]         = imx_clk_gate("cko2",           "cko2_podf",         base + 0x60, 24);
 
-	for (i = 0; i < ARRAY_SIZE(clk); i++)
-		if (IS_ERR(clk[i]))
-			pr_err("i.MX6q clk %d: register failed with %ld\n",
-				i, PTR_ERR(clk[i]));
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
 
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-	clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
+	clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
 
 	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
 	    cpu_is_imx6dl()) {
-		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
-		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
+		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_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
-	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
-	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
-	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
-	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
-	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
-	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
-	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_SEL], clk[IMX6QDL_CLK_IPU1_DI0_PRE]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_SEL], clk[IMX6QDL_CLK_IPU1_DI1_PRE]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]);
+	clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]);
 
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
 	 * We can not get the 100MHz from the pll2_pfd0_352m.
 	 * So choose pll2_pfd2_396m as enfc_sel's parent.
 	 */
-	clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]);
+	clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clk[clks_init_on[i]]);
 
 	if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
-		clk_prepare_enable(clk[usbphy1_gate]);
-		clk_prepare_enable(clk[usbphy2_gate]);
+		clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]);
+		clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]);
 	}
 
 	/*
 	 * Let's initially set up CLKO with OSC24M, since this configuration
 	 * is widely used by imx6q board designs to clock audio codec.
 	 */
-	ret = clk_set_parent(clk[cko2_sel], clk[osc]);
+	ret = clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]);
 	if (!ret)
-		ret = clk_set_parent(clk[cko], clk[cko2]);
+		ret = clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]);
 	if (ret)
 		pr_warn("failed to set up CLKO: %d\n", ret);
 
 	/* Audio-related clocks configuration */
-	clk_set_parent(clk[spdif_sel], clk[pll3_pfd3_454m]);
+	clk_set_parent(clk[IMX6QDL_CLK_SPDIF_SEL], clk[IMX6QDL_CLK_PLL3_PFD3_454M]);
 
 	/* All existing boards with PCIe use LVDS1 */
 	if (IS_ENABLED(CONFIG_PCI_IMX6))
-		clk_set_parent(clk[lvds1_sel], clk[sata_ref_100m]);
+		clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
 
 	/* Set initial power mode */
 	imx6q_set_lpm(WAIT_CLOCKED);
-
-	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"));
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6sl.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6sl.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6sl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6sl.c	2014-09-28 17:29:07.000000000 -0400
@@ -348,18 +348,12 @@ static void __init imx6sl_clocks_init(st
 	clks[IMX6SL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",       "usdhc3_podf",       base + 0x80, 6);
 	clks[IMX6SL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",       "usdhc4_podf",       base + 0x80, 8);
 
-	for (i = 0; i < ARRAY_SIZE(clks); i++)
-		if (IS_ERR(clks[i]))
-			pr_err("i.MX6SL clk %d: register failed with %ld\n",
-				i, PTR_ERR(clks[i]));
+	imx_check_clocks(clks, ARRAY_SIZE(clks));
 
 	clk_data.clks = clks;
 	clk_data.clk_num = ARRAY_SIZE(clks);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
-
 	/* Ensure the AHB clk is at 132MHz. */
 	ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
 	if (ret)
@@ -383,8 +377,5 @@ static void __init imx6sl_clocks_init(st
 
 	/* Set initial power mode */
 	imx6q_set_lpm(WAIT_CLOCKED);
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
-	mxc_timer_init_dt(np);
 }
 CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6sx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6sx.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-imx6sx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-imx6sx.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,6 +124,9 @@ static struct clk_div_table video_div_ta
 static u32 share_count_asrc;
 static u32 share_count_audio;
 static u32 share_count_esai;
+static u32 share_count_ssi1;
+static u32 share_count_ssi2;
+static u32 share_count_ssi3;
 
 static void __init imx6sx_clocks_init(struct device_node *ccm_node)
 {
@@ -409,12 +412,12 @@ static void __init imx6sx_clocks_init(st
 	clks[IMX6SX_CLK_SPBA]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
 	clks[IMX6SX_CLK_AUDIO]        = imx_clk_gate2_shared("audio",  "audio_podf",        base + 0x7c, 14, &share_count_audio);
 	clks[IMX6SX_CLK_SPDIF]        = imx_clk_gate2_shared("spdif",  "spdif_podf",        base + 0x7c, 14, &share_count_audio);
-	clks[IMX6SX_CLK_SSI1_IPG]     = imx_clk_gate2("ssi1_ipg",      "ipg",               base + 0x7c, 18);
-	clks[IMX6SX_CLK_SSI2_IPG]     = imx_clk_gate2("ssi2_ipg",      "ipg",               base + 0x7c, 20);
-	clks[IMX6SX_CLK_SSI3_IPG]     = imx_clk_gate2("ssi3_ipg",      "ipg",               base + 0x7c, 22);
-	clks[IMX6SX_CLK_SSI1]         = imx_clk_gate2("ssi1",          "ssi1_podf",         base + 0x7c, 18);
-	clks[IMX6SX_CLK_SSI2]         = imx_clk_gate2("ssi2",          "ssi2_podf",         base + 0x7c, 20);
-	clks[IMX6SX_CLK_SSI3]         = imx_clk_gate2("ssi3",          "ssi3_podf",         base + 0x7c, 22);
+	clks[IMX6SX_CLK_SSI1_IPG]     = imx_clk_gate2_shared("ssi1_ipg",      "ipg",        base + 0x7c, 18, &share_count_ssi1);
+	clks[IMX6SX_CLK_SSI2_IPG]     = imx_clk_gate2_shared("ssi2_ipg",      "ipg",        base + 0x7c, 20, &share_count_ssi2);
+	clks[IMX6SX_CLK_SSI3_IPG]     = imx_clk_gate2_shared("ssi3_ipg",      "ipg",        base + 0x7c, 22, &share_count_ssi3);
+	clks[IMX6SX_CLK_SSI1]         = imx_clk_gate2_shared("ssi1",          "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
+	clks[IMX6SX_CLK_SSI2]         = imx_clk_gate2_shared("ssi2",          "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
+	clks[IMX6SX_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
 	clks[IMX6SX_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
 	clks[IMX6SX_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_podf",         base + 0x7c, 26);
 	clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2("sai1_ipg",      "ipg",               base + 0x7c, 28);
@@ -443,17 +446,12 @@ static void __init imx6sx_clocks_init(st
 	/* mask handshake of mmdc */
 	writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
 
-	for (i = 0; i < ARRAY_SIZE(clks); i++)
-		if (IS_ERR(clks[i]))
-			pr_err("i.MX6sx clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+	imx_check_clocks(clks, ARRAY_SIZE(clks));
 
 	clk_data.clks = clks;
 	clk_data.clk_num = ARRAY_SIZE(clks);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	clk_register_clkdev(clks[IMX6SX_CLK_GPT_BUS], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clks[IMX6SX_CLK_GPT_SERIAL], "per", "imx-gpt.0");
-
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
@@ -517,8 +515,5 @@ static void __init imx6sx_clocks_init(st
 
 	/* Set initial power mode */
 	imx6q_set_lpm(WAIT_CLOCKED);
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-gpt");
-	mxc_timer_init_dt(np);
 }
 CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/clk-vf610.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-vf610.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/clk-vf610.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/clk-vf610.c	2014-09-28 17:29:07.000000000 -0400
@@ -295,14 +295,18 @@ static void __init vf610_clocks_init(str
 
 	clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(1));
 
-	clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(0));
-	clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(4));
+	clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus", CCM_CSCDR2, 11);
+	clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en", CCM_CCGR0, CCM_CCGRx_CGn(0));
+	clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus", CCM_CSCDR2, 12);
+	clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en", CCM_CCGR9, CCM_CCGRx_CGn(4));
 
 	clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(4));
 	clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5));
 	clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
 	clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
 
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+
 	clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
 	clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2);
 	clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ struct pt_regs;
 struct clk;
 struct device_node;
 enum mxc_cpu_pwr_mode;
+struct of_device_id;
 
 void mx1_map_io(void);
 void mx21_map_io(void);
@@ -26,48 +27,34 @@ void mx25_map_io(void);
 void mx27_map_io(void);
 void mx31_map_io(void);
 void mx35_map_io(void);
-void mx51_map_io(void);
-void mx53_map_io(void);
 void imx1_init_early(void);
 void imx21_init_early(void);
 void imx25_init_early(void);
 void imx27_init_early(void);
 void imx31_init_early(void);
 void imx35_init_early(void);
-void imx51_init_early(void);
-void imx53_init_early(void);
 void mxc_init_irq(void __iomem *);
-void tzic_init_irq(void __iomem *);
+void tzic_init_irq(void);
 void mx1_init_irq(void);
 void mx21_init_irq(void);
 void mx25_init_irq(void);
 void mx27_init_irq(void);
 void mx31_init_irq(void);
 void mx35_init_irq(void);
-void mx51_init_irq(void);
-void mx53_init_irq(void);
 void imx1_soc_init(void);
 void imx21_soc_init(void);
 void imx25_soc_init(void);
 void imx27_soc_init(void);
 void imx31_soc_init(void);
 void imx35_soc_init(void);
-void imx51_soc_init(void);
-void imx51_init_late(void);
-void imx53_init_late(void);
 void epit_timer_init(void __iomem *base, int irq);
 void mxc_timer_init(void __iomem *, int);
-void mxc_timer_init_dt(struct device_node *);
 int mx1_clocks_init(unsigned long fref);
 int mx21_clocks_init(unsigned long lref, unsigned long fref);
 int mx25_clocks_init(void);
 int mx27_clocks_init(unsigned long fref);
 int mx31_clocks_init(unsigned long fref);
 int mx35_clocks_init(void);
-int mx51_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2);
-int mx25_clocks_init_dt(void);
-int mx27_clocks_init_dt(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);
@@ -75,8 +62,10 @@ void mxc_set_cpu_type(unsigned int type)
 void mxc_restart(enum reboot_mode, const char *);
 void mxc_arch_reset_init(void __iomem *);
 void mxc_arch_reset_init_dt(void);
+int mx51_revision(void);
 int mx53_revision(void);
 void imx_set_aips(void __iomem *);
+void imx_aips_allow_unprivileged_access(const char *compat);
 int mxc_device_init(void);
 void imx_set_soc_revision(unsigned int rev);
 unsigned int imx_get_soc_revision(void);
@@ -117,7 +106,7 @@ static inline void imx_scu_standby_enabl
 #endif
 void imx_src_init(void);
 void imx_gpc_init(void);
-void imx_gpc_pre_suspend(void);
+void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
 void imx_gpc_restore_all(void);
@@ -127,7 +116,7 @@ void imx_anatop_init(void);
 void imx_anatop_pre_suspend(void);
 void imx_anatop_post_resume(void);
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-void imx6q_set_int_mem_clk_lpm(void);
+void imx6q_set_int_mem_clk_lpm(bool enable);
 void imx6sl_set_wait_clk(bool enter);
 
 void imx_cpu_die(unsigned int cpu);
@@ -144,12 +133,17 @@ static inline void imx6_suspend(void __i
 void imx6q_pm_init(void);
 void imx6dl_pm_init(void);
 void imx6sl_pm_init(void);
+void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
 
 #ifdef CONFIG_PM
-void imx5_pm_init(void);
+void imx51_pm_init(void);
+void imx53_pm_init(void);
+void imx5_pm_set_ccm_base(void __iomem *base);
 #else
-static inline void imx5_pm_init(void) {}
+static inline void imx51_pm_init(void) {}
+static inline void imx53_pm_init(void) {}
+static inline void imx5_pm_set_ccm_base(void __iomem *base) {}
 #endif
 
 #ifdef CONFIG_NEON
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/cpu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpu.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
 
@@ -60,6 +61,18 @@ void __init imx_set_aips(void __iomem *b
 	__raw_writel(reg, base + 0x50);
 }
 
+void __init imx_aips_allow_unprivileged_access(
+		const char *compat)
+{
+	void __iomem *aips_base_addr;
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, compat) {
+		aips_base_addr = of_iomap(np, 0);
+		imx_set_aips(aips_base_addr);
+	}
+}
+
 struct device * __init imx_soc_device_init(void)
 {
 	struct soc_device_attribute *soc_dev_attr;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/cpuidle-imx6q.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpuidle-imx6q.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/cpuidle-imx6q.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpuidle-imx6q.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include "common.h"
 #include "cpuidle.h"
+#include "hardware.h"
 
 static atomic_t master = ATOMIC_INIT(0);
 static DEFINE_SPINLOCK(master_lock);
@@ -66,10 +67,11 @@ static struct cpuidle_driver imx6q_cpuid
 int __init imx6q_cpuidle_init(void)
 {
 	/* Need to enable SCU standby for entering WAIT modes */
-	imx_scu_standby_enable();
+	if (!cpu_is_imx6sx())
+		imx_scu_standby_enable();
 
 	/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
-	imx6q_set_int_mem_clk_lpm();
+	imx6q_set_int_mem_clk_lpm(true);
 
 	return cpuidle_register(&imx6q_cpuidle_driver, NULL);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/cpu-imx5.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpu-imx5.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/cpu-imx5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/cpu-imx5.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "hardware.h"
 #include "common.h"
@@ -24,10 +26,26 @@ static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
 
+static u32 imx5_read_srev_reg(const char *compat)
+{
+	void __iomem *iim_base;
+	struct device_node *np;
+	u32 srev;
+
+	np = of_find_compatible_node(NULL, NULL, compat);
+	iim_base = of_iomap(np, 0);
+	WARN_ON(!iim_base);
+
+	srev = readl(iim_base + IIM_SREV) & 0xff;
+
+	iounmap(iim_base);
+
+	return srev;
+}
+
 static int get_mx51_srev(void)
 {
-	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
-	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+	u32 rev = imx5_read_srev_reg("fsl,imx51-iim");
 
 	switch (rev) {
 	case 0x0:
@@ -77,8 +95,7 @@ int __init mx51_neon_fixup(void)
 
 static int get_mx53_srev(void)
 {
-	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
-	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+	u32 rev = imx5_read_srev_reg("fsl,imx53-iim");
 
 	switch (rev) {
 	case 0x0:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/crm-regs-imx5.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/crm-regs-imx5.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/crm-regs-imx5.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/crm-regs-imx5.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,600 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-
-#define MX51_CCM_BASE		MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE		MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE		MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE		MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE	MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE		MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
-
-/*MX53*/
-#define MX53_CCM_BASE		MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
-#define MX53_DPLL1_BASE		MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
-#define MX53_DPLL2_BASE		MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
-#define MX53_DPLL3_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR)
-
-/* PLL Register Offsets */
-#define MXC_PLL_DP_CTL			0x00
-#define MXC_PLL_DP_CONFIG		0x04
-#define MXC_PLL_DP_OP			0x08
-#define MXC_PLL_DP_MFD			0x0C
-#define MXC_PLL_DP_MFN			0x10
-#define MXC_PLL_DP_MFNMINUS		0x14
-#define MXC_PLL_DP_MFNPLUS		0x18
-#define MXC_PLL_DP_HFS_OP		0x1C
-#define MXC_PLL_DP_HFS_MFD		0x20
-#define MXC_PLL_DP_HFS_MFN		0x24
-#define MXC_PLL_DP_MFN_TOGC		0x28
-#define MXC_PLL_DP_DESTAT		0x2c
-
-/* PLL Register Bit definitions */
-#define MXC_PLL_DP_CTL_MUL_CTRL		0x2000
-#define MXC_PLL_DP_CTL_DPDCK0_2_EN	0x1000
-#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET	12
-#define MXC_PLL_DP_CTL_ADE		0x800
-#define MXC_PLL_DP_CTL_REF_CLK_DIV	0x400
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK	(3 << 8)
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET	8
-#define MXC_PLL_DP_CTL_HFSM		0x80
-#define MXC_PLL_DP_CTL_PRE		0x40
-#define MXC_PLL_DP_CTL_UPEN		0x20
-#define MXC_PLL_DP_CTL_RST		0x10
-#define MXC_PLL_DP_CTL_RCP		0x8
-#define MXC_PLL_DP_CTL_PLM		0x4
-#define MXC_PLL_DP_CTL_BRM0		0x2
-#define MXC_PLL_DP_CTL_LRF		0x1
-
-#define MXC_PLL_DP_CONFIG_BIST		0x8
-#define MXC_PLL_DP_CONFIG_SJC_CE	0x4
-#define MXC_PLL_DP_CONFIG_AREN		0x2
-#define MXC_PLL_DP_CONFIG_LDREQ		0x1
-
-#define MXC_PLL_DP_OP_MFI_OFFSET	4
-#define MXC_PLL_DP_OP_MFI_MASK		(0xF << 4)
-#define MXC_PLL_DP_OP_PDF_OFFSET	0
-#define MXC_PLL_DP_OP_PDF_MASK		0xF
-
-#define MXC_PLL_DP_MFD_OFFSET		0
-#define MXC_PLL_DP_MFD_MASK		0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_OFFSET		0x0
-#define MXC_PLL_DP_MFN_MASK		0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_TOGC_TOG_DIS	(1 << 17)
-#define MXC_PLL_DP_MFN_TOGC_TOG_EN	(1 << 16)
-#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET	0x0
-#define MXC_PLL_DP_MFN_TOGC_CNT_MASK	0xFFFF
-
-#define MXC_PLL_DP_DESTAT_TOG_SEL	(1 << 31)
-#define MXC_PLL_DP_DESTAT_MFN		0x07FFFFFF
-
-/* Register addresses of CCM*/
-#define MXC_CCM_CCR		(MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR		(MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR		(MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR		(MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR		(MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR		(MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR		(MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1		(MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2		(MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1		(MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR		(MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR		(MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR		(MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR		(MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2		(MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3		(MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4		(MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR		(MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR		(MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR		(MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR		(MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR		(MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR		(MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR		(MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR		(MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR		(MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0		(MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1		(MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2		(MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3		(MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4		(MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5		(MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6		(MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CCGR7		(MX51_CCM_BASE + 0x84)
-
-#define MXC_CCM_CMEOR		(MX51_CCM_BASE + 0x84)
-
-/* Define the bits in register CCR */
-#define MXC_CCM_CCR_COSC_EN		(1 << 12)
-#define MXC_CCM_CCR_FPM_MULT_MASK	(1 << 11)
-#define MXC_CCM_CCR_CAMP2_EN		(1 << 10)
-#define MXC_CCM_CCR_CAMP1_EN		(1 << 9)
-#define MXC_CCM_CCR_FPM_EN		(1 << 8)
-#define MXC_CCM_CCR_OSCNT_OFFSET	(0)
-#define MXC_CCM_CCR_OSCNT_MASK	(0xFF)
-
-/* Define the bits in register CCDR */
-#define MXC_CCM_CCDR_HSC_HS_MASK	(0x1 << 18)
-#define MXC_CCM_CCDR_IPU_HS_MASK	(0x1 << 17)
-#define MXC_CCM_CCDR_EMI_HS_MASK	(0x1 << 16)
-
-/* Define the bits in register CSR */
-#define MXC_CCM_CSR_COSR_READY	(1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE	(1 << 4)
-#define MXC_CCM_CSR_CAMP2_READY	(1 << 3)
-#define MXC_CCM_CSR_CAMP1_READY	(1 << 2)
-#define MXC_CCM_CSR_FPM_READY	(1 << 1)
-#define MXC_CCM_CSR_REF_EN_B	(1 << 0)
-
-/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL		(0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET	(7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK	(0x3 << 7)
-#define MXC_CCM_CCSR_STEP_SEL_LP_APM	   0
-#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
-#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
-#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
-#define MXC_CCM_CCSR_PLL2_PODF_OFFSET	(5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK	(0x3 << 5)
-#define MXC_CCM_CCSR_PLL3_PODF_OFFSET	(3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK	(0x3 << 3)
-#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL	(1 << 2) /* 0: pll1_main_clk,
-						    1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL	(1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL	(1 << 0)
-
-/* Define the bits in register CACRR */
-#define MXC_CCM_CACRR_ARM_PODF_OFFSET	(0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK	(0x7)
-
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL		(0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET		(30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL		(0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET		(27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK		(0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET		(22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK		(0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET		(19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK		(0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET		(16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK		(0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET		(13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK		(0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET		(10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK		(0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET		(8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK		(0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET	(6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK		(0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET	(3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK		(0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET	(0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET	(12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK	(0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET	(10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK		(0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET	(8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK	(0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET	(6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK	(0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET	(4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL	(0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL	(0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET		(30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK		(0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET		(28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK		(0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET		(26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL			(0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL			(0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL			(0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET		(8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK		(0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL			(0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL			(0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET		(4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL		(0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL		(0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)		(26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)		(0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET		(20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK			(0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET		(18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK		(0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET		(16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET		(10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK			(0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM			(0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET		(6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK		(0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM			(1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM			(1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET		(0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK		(0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK		(0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET	(11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK	(0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET		(8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK		(0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK		(0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET		(3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK		(0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK		(0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET		(28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK			(0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK			(0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET		(3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK			(0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET		(0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK			(0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET		(12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK		(0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK		(0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET		(3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK		(0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET	(9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET	(6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET	(0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CDHIPR */
-#define MXC_CCM_CDHIPR_ARM_PODF_BUSY			(1 << 16)
-#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY		(1 << 8)
-#define MXC_CCM_CDHIPR_DDR_PODF_BUSY			(1 << 7)
-#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY			(1 << 6)
-#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY		(1 << 5)
-#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY	(1 << 4)
-#define MXC_CCM_CDHIPR_AHB_PODF_BUSY			(1 << 3)
-#define MXC_CCM_CDHIPR_EMI_PODF_BUSY			(1 << 2)
-#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY			(1 << 1)
-#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY			(1 << 0)
-
-/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER		(0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET	(0)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK		(0x3)
-
-/* Define the bits in register CLPCR */
-#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS		(0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS		(0x1 << 22)
-#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 21)
-#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 25)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS	(0x1 << 20)
-#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS		(0x1 << 19)
-#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS		(0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS	(0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS	(0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
-#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET		(9)
-#define MXC_CCM_CLPCR_STBY_COUNT_MASK		(0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY			(0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC		(0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS			(0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET	(3)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK		(0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET		(0)
-#define MXC_CCM_CLPCR_LPM_MASK			(0x3)
-
-/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED			(0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
-#define MXC_CCM_CISR_AHB_PODF_LOADED			(0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED			(0x1 << 19)
-#define MXC_CCM_CISR_AXI_B_PODF_LOADED			(0x1 << 18)
-#define MXC_CCM_CISR_AXI_A_PODF_LOADED			(0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED			(0x1 << 16)
-#define MXC_CCM_CISR_COSC_READY				(0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY			(0x1 << 5)
-#define MXC_CCM_CISR_CKIH_READY				(0x1 << 4)
-#define MXC_CCM_CISR_FPM_READY				(0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3				(0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2				(0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1				(0x1)
-
-/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED		(0x1 << 25)
-#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED		(0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED		(0x1 << 19)
-#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED		(0x1 << 18)
-#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED		(0x1 << 17)
-#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED		(0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY			(0x1 << 5)
-#define MXC_CCM_CIMR_MASK_CKIH_READY			(0x1 << 4)
-#define MXC_CCM_CIMR_MASK_FPM_READY			(0x1 << 3)
-#define MXC_CCM_CIMR_MASK_LRF_PLL3			(0x1 << 2)
-#define MXC_CCM_CIMR_MASK_LRF_PLL2			(0x1 << 1)
-#define MXC_CCM_CIMR_MASK_LRF_PLL1			(0x1)
-
-/* Define the bits in register CCOSR */
-#define MXC_CCM_CCOSR_CKO2_EN_OFFSET			(0x1 << 24)
-#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET			(21)
-#define MXC_CCM_CCOSR_CKO2_DIV_MASK			(0x7 << 21)
-#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET			(16)
-#define MXC_CCM_CCOSR_CKO2_SEL_MASK			(0x1F << 16)
-#define MXC_CCM_CCOSR_CKOL_EN				(0x1 << 7)
-#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET			(4)
-#define MXC_CCM_CCOSR_CKOL_DIV_MASK			(0x7 << 4)
-#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET			(0)
-#define MXC_CCM_CCOSR_CKOL_SEL_MASK			(0xF)
-
-/* Define the bits in registers CGPR */
-#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE		(0x1 << 4)
-#define MXC_CCM_CGPR_FPM_SEL				(0x1 << 3)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET		(0)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK		(0x7)
-
-/* Define the bits in registers CCGRx */
-#define MXC_CCM_CCGRx_CG_MASK				0x3
-#define MXC_CCM_CCGRx_MOD_OFF				0x0
-#define MXC_CCM_CCGRx_MOD_ON				0x3
-#define MXC_CCM_CCGRx_MOD_IDLE				0x1
-
-#define MXC_CCM_CCGRx_CG15_MASK				(0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK				(0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK				(0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK				(0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK				(0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK				(0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK				(0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK				(0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK				(0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK				(0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK				(0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK				(0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK				(0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK				(0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET			30
-#define MXC_CCM_CCGRx_CG14_OFFSET			28
-#define MXC_CCM_CCGRx_CG13_OFFSET			26
-#define MXC_CCM_CCGRx_CG12_OFFSET			24
-#define MXC_CCM_CCGRx_CG11_OFFSET			22
-#define MXC_CCM_CCGRx_CG10_OFFSET			20
-#define MXC_CCM_CCGRx_CG9_OFFSET			18
-#define MXC_CCM_CCGRx_CG8_OFFSET			16
-#define MXC_CCM_CCGRx_CG7_OFFSET			14
-#define MXC_CCM_CCGRx_CG6_OFFSET			12
-#define MXC_CCM_CCGRx_CG5_OFFSET			10
-#define MXC_CCM_CCGRx_CG4_OFFSET			8
-#define MXC_CCM_CCGRx_CG3_OFFSET			6
-#define MXC_CCM_CCGRx_CG2_OFFSET			4
-#define MXC_CCM_CCGRx_CG1_OFFSET			2
-#define MXC_CCM_CCGRx_CG0_OFFSET			0
-
-#define MXC_DPTC_LP_BASE	(MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE	(MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE	(MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE	(MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE	(MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE	(MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE	(MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE	(MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE	(MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE	(MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE	(MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE	(MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE	(MX51_GPC_BASE + 0x300)
-
-/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID		(MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC		(MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC		(MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC		(MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC	(MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC		(MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC		(MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC		(MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS		(MX51_CORTEXA8_BASE + 0x24)
-
-/* DVFS CORE */
-#define MXC_DVFSTHRS		(MXC_DVFS_CORE_BASE + 0x00)
-#define MXC_DVFSCOUN		(MXC_DVFS_CORE_BASE + 0x04)
-#define MXC_DVFSSIG1		(MXC_DVFS_CORE_BASE + 0x08)
-#define MXC_DVFSSIG0		(MXC_DVFS_CORE_BASE + 0x0C)
-#define MXC_DVFSGPC0		(MXC_DVFS_CORE_BASE + 0x10)
-#define MXC_DVFSGPC1		(MXC_DVFS_CORE_BASE + 0x14)
-#define MXC_DVFSGPBT		(MXC_DVFS_CORE_BASE + 0x18)
-#define MXC_DVFSEMAC		(MXC_DVFS_CORE_BASE + 0x1C)
-#define MXC_DVFSCNTR		(MXC_DVFS_CORE_BASE + 0x20)
-#define MXC_DVFSLTR0_0		(MXC_DVFS_CORE_BASE + 0x24)
-#define MXC_DVFSLTR0_1		(MXC_DVFS_CORE_BASE + 0x28)
-#define MXC_DVFSLTR1_0		(MXC_DVFS_CORE_BASE + 0x2C)
-#define MXC_DVFSLTR1_1		(MXC_DVFS_CORE_BASE + 0x30)
-#define MXC_DVFSPT0 		(MXC_DVFS_CORE_BASE + 0x34)
-#define MXC_DVFSPT1 		(MXC_DVFS_CORE_BASE + 0x38)
-#define MXC_DVFSPT2 		(MXC_DVFS_CORE_BASE + 0x3C)
-#define MXC_DVFSPT3 		(MXC_DVFS_CORE_BASE + 0x40)
-
-/* GPC */
-#define MXC_GPC_CNTR		(MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR		(MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR		(MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU		(MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON		(MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET	8
-#define MXC_GPC_PGR_ARMPG_MASK		(3 << 8)
-
-/* PGC */
-#define MXC_PGC_IPU_PGCR	(MXC_PGC_IPU_BASE + 0x0)
-#define MXC_PGC_IPU_PGSR	(MXC_PGC_IPU_BASE + 0xC)
-#define MXC_PGC_VPU_PGCR	(MXC_PGC_VPU_BASE + 0x0)
-#define MXC_PGC_VPU_PGSR	(MXC_PGC_VPU_BASE + 0xC)
-#define MXC_PGC_GPU_PGCR	(MXC_PGC_GPU_BASE + 0x0)
-#define MXC_PGC_GPU_PGSR	(MXC_PGC_GPU_BASE + 0xC)
-
-#define MXC_PGCR_PCR		1
-#define MXC_SRPGCR_PCR		1
-#define MXC_EMPGCR_PCR		1
-#define MXC_PGSR_PSR		1
-
-
-#define MXC_CORTEXA8_PLAT_LPC_DSM	(1 << 0)
-#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM	(1 << 1)
-
-/* SRPG */
-#define MXC_SRPG_NEON_SRPGCR	(MXC_SRPG_NEON_BASE + 0x0)
-#define MXC_SRPG_NEON_PUPSCR	(MXC_SRPG_NEON_BASE + 0x4)
-#define MXC_SRPG_NEON_PDNSCR	(MXC_SRPG_NEON_BASE + 0x8)
-
-#define MXC_SRPG_ARM_SRPGCR	(MXC_SRPG_ARM_BASE + 0x0)
-#define MXC_SRPG_ARM_PUPSCR	(MXC_SRPG_ARM_BASE + 0x4)
-#define MXC_SRPG_ARM_PDNSCR	(MXC_SRPG_ARM_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC0_SRPGCR	(MXC_SRPG_EMPGC0_BASE + 0x0)
-#define MXC_SRPG_EMPGC0_PUPSCR	(MXC_SRPG_EMPGC0_BASE + 0x4)
-#define MXC_SRPG_EMPGC0_PDNSCR	(MXC_SRPG_EMPGC0_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC1_SRPGCR	(MXC_SRPG_EMPGC1_BASE + 0x0)
-#define MXC_SRPG_EMPGC1_PUPSCR	(MXC_SRPG_EMPGC1_BASE + 0x4)
-#define MXC_SRPG_EMPGC1_PDNSCR	(MXC_SRPG_EMPGC1_BASE + 0x8)
-
-#define MXC_SRPG_MEGAMIX_SRPGCR		(MXC_SRPG_MEGAMIX_BASE + 0x0)
-#define MXC_SRPG_MEGAMIX_PUPSCR		(MXC_SRPG_MEGAMIX_BASE + 0x4)
-#define MXC_SRPG_MEGAMIX_PDNSCR		(MXC_SRPG_MEGAMIX_BASE + 0x8)
-
-#define MXC_SRPGC_EMI_SRPGCR	(MXC_SRPGC_EMI_BASE + 0x0)
-#define MXC_SRPGC_EMI_PUPSCR	(MXC_SRPGC_EMI_BASE + 0x4)
-#define MXC_SRPGC_EMI_PDNSCR	(MXC_SRPGC_EMI_BASE + 0x8)
-
-#endif				/* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,10 @@
 
 struct device mxc_aips_bus = {
 	.init_name	= "mxc_aips",
-	.parent		= &platform_bus,
 };
 
 struct device mxc_ahb_bus = {
 	.init_name	= "mxc_ahb",
-	.parent		= &platform_bus,
 };
 
 int __init mxc_device_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/devices-common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/devices-common.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/devices-common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/devices-common.h	2014-09-28 17:29:07.000000000 -0400
@@ -176,22 +176,6 @@ struct platform_device *__init imx_add_i
 		const struct imx_imx_uart_1irq_data *data,
 		const struct imxuart_platform_data *pdata);
 
-#include <linux/platform_data/usb-imx_udc.h>
-struct imx_imx_udc_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq0;
-	resource_size_t irq1;
-	resource_size_t irq2;
-	resource_size_t irq3;
-	resource_size_t irq4;
-	resource_size_t irq5;
-	resource_size_t irq6;
-};
-struct platform_device *__init imx_add_imx_udc(
-		const struct imx_imx_udc_data *data,
-		const struct imxusb_platform_data *pdata);
-
 #include <linux/platform_data/video-mx3fb.h>
 #include <linux/platform_data/camera-mx3.h>
 struct imx_ipu_core_data {
@@ -208,16 +192,6 @@ struct platform_device *__init imx_add_m
 		const struct imx_ipu_core_data *data,
 		struct mx3fb_platform_data *pdata);
 
-#include <linux/platform_data/camera-mx1.h>
-struct imx_mx1_camera_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mx1_camera(
-		const struct imx_mx1_camera_data *data,
-		const struct mx1_camera_pdata *pdata);
-
 #include <linux/platform_data/camera-mx2.h>
 struct imx_mx2_camera_data {
 	const char *devid;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+	default y if SOC_IMX25 || SOC_IMX27 || SOC_IMX35
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	bool
@@ -10,7 +10,6 @@ config IMX_HAVE_PLATFORM_FSL_USB2_UDC
 
 config IMX_HAVE_PLATFORM_GPIO_KEYS
 	bool
-	default y if SOC_IMX51
 
 config IMX_HAVE_PLATFORM_IMX21_HCD
 	bool
@@ -43,15 +42,9 @@ config IMX_HAVE_PLATFORM_IMX_SSI
 config IMX_HAVE_PLATFORM_IMX_UART
 	bool
 
-config IMX_HAVE_PLATFORM_IMX_UDC
-	bool
-
 config IMX_HAVE_PLATFORM_IPU_CORE
 	bool
 
-config IMX_HAVE_PLATFORM_MX1_CAMERA
-	bool
-
 config IMX_HAVE_PLATFORM_MX2_CAMERA
 	bool
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -16,9 +16,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPA
 obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IPU_CORE) += platform-ipu-core.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MX1_CAMERA) += platform-mx1-camera.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-fec.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-fec.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-fec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-fec.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,18 +35,6 @@ const struct imx_fec_data imx35_fec_data
 	imx_fec_data_entry_single(MX35, "imx27-fec");
 #endif
 
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx27 type fec */
-const struct imx_fec_data imx51_fec_data __initconst =
-	imx_fec_data_entry_single(MX51, "imx27-fec");
-#endif
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx25 type fec */
-const struct imx_fec_data imx53_fec_data __initconst =
-	imx_fec_data_entry_single(MX53, "imx25-fec");
-#endif
-
 struct platform_device *__init imx_add_fec(
 		const struct imx_fec_data *data,
 		const struct fec_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,11 +38,6 @@ const struct imx_fsl_usb2_udc_data imx35
 	imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51");
-#endif
-
 struct platform_device *__init imx_add_fsl_usb2_udc(
 		const struct imx_fsl_usb2_udc_data *data,
 		const struct fsl_usb2_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx2-wdt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx2-wdt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx2-wdt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx2-wdt.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,24 +45,6 @@ const struct imx_imx2_wdt_data imx35_imx
 	imx_imx2_wdt_data_entry_single(MX35, 0, , SZ_16K);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
-#define imx51_imx2_wdt_data_entry(_id, _hwid)				\
-	imx_imx2_wdt_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_imx2_wdt_data_entry(0, 1),
-	imx51_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
-#define imx53_imx2_wdt_data_entry(_id, _hwid)				\
-	imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
-	imx53_imx2_wdt_data_entry(0, 1),
-	imx53_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_imx2_wdt(
 		const struct imx_imx2_wdt_data *data)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-i2c.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-i2c.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,32 +70,6 @@ const struct imx_imx_i2c_data imx35_imx_
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
-#define imx51_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX51, "imx21-i2c", _id, _hwid, SZ_4K)
-	imx51_imx_i2c_data_entry(0, 1),
-	imx51_imx_i2c_data_entry(1, 2),
-	{
-		.devid = "imx21-i2c",
-		.id = 2,
-		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
-		.iosize = SZ_16K,
-		.irq = MX51_INT_HS_I2C,
-	},
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
-#define imx53_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX53, "imx21-i2c", _id, _hwid, SZ_4K)
-	imx53_imx_i2c_data_entry(0, 1),
-	imx53_imx_i2c_data_entry(1, 2),
-	imx53_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_imx_i2c(
 		const struct imx_imx_i2c_data *data,
 		const struct imxi2c_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-keypad.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-keypad.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-keypad.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,16 +41,6 @@ const struct imx_imx_keypad_data imx35_i
 	imx_imx_keypad_data_entry_single(MX35, SZ_16);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX51, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX53, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_imx_keypad(
 		const struct imx_imx_keypad_data *data,
 		const struct matrix_keymap_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-ssi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-ssi.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-ssi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-ssi.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,26 +66,6 @@ const struct imx_imx_ssi_data imx35_imx_
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
-#define imx51_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_imx_ssi_data_entry(0, 1),
-	imx51_imx_ssi_data_entry(1, 2),
-	imx51_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
-#define imx53_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
-	imx53_imx_ssi_data_entry(0, 1),
-	imx53_imx_ssi_data_entry(1, 2),
-	imx53_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_imx_ssi(
 		const struct imx_imx_ssi_data *data,
 		const struct imx_ssi_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-uart.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-uart.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx-uart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx-uart.c	2014-09-28 17:29:07.000000000 -0400
@@ -94,28 +94,6 @@ const struct imx_imx_uart_1irq_data imx3
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
-#define imx51_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
-	imx51_imx_uart_data_entry(0, 1),
-	imx51_imx_uart_data_entry(1, 2),
-	imx51_imx_uart_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
-#define imx53_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX53, _id, _hwid, SZ_4K)
-	imx53_imx_uart_data_entry(0, 1),
-	imx53_imx_uart_data_entry(1, 2),
-	imx53_imx_uart_data_entry(2, 3),
-	imx53_imx_uart_data_entry(3, 4),
-	imx53_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_imx_uart_3irq(
 		const struct imx_imx_uart_3irq_data *data,
 		const struct imxuart_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx_udc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx_udc.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-imx_udc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-imx_udc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "../hardware.h"
-#include "devices-common.h"
-
-#define imx_imx_udc_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _USBD_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq0 = soc ## _INT_USBD0,				\
-		.irq1 = soc ## _INT_USBD1,				\
-		.irq2 = soc ## _INT_USBD2,				\
-		.irq3 = soc ## _INT_USBD3,				\
-		.irq4 = soc ## _INT_USBD4,				\
-		.irq5 = soc ## _INT_USBD5,				\
-		.irq6 = soc ## _INT_USBD6,				\
-	}
-
-#define imx_imx_udc_data_entry(soc, _size)				\
-	[_id] = imx_imx_udc_data_entry_single(soc, _size)
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_udc_data imx1_imx_udc_data __initconst =
-	imx_imx_udc_data_entry_single(MX1, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_imx_udc(
-		const struct imx_imx_udc_data *data,
-		const struct imxusb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq0,
-			.end = data->irq0,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq1,
-			.end = data->irq1,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq2,
-			.end = data->irq2,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq3,
-			.end = data->irq3,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq4,
-			.end = data->irq4,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq5,
-			.end = data->irq5,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq6,
-			.end = data->irq6,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imx_udc", 0,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mx1-camera.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mx1-camera.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mx1-camera.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mx1-camera.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "../hardware.h"
-#include "devices-common.h"
-
-#define imx_mx1_camera_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _CSI ## _BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_CSI,					\
-	}
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_mx1_camera_data imx1_mx1_camera_data __initconst =
-	imx_mx1_camera_data_entry_single(MX1, 10);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_mx1_camera(
-		const struct imx_mx1_camera_data *data,
-		const struct mx1_camera_pdata *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("mx1-camera", 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc-ehci.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc-ehci.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc-ehci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc-ehci.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,15 +50,6 @@ const struct imx_mxc_ehci_data imx35_mxc
 	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
-const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
-	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
-	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
 struct platform_device *__init imx_add_mxc_ehci(
 		const struct imx_mxc_ehci_data *data,
 		const struct mxc_usbh_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc_nand.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc_nand.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc_nand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc_nand.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,11 +54,6 @@ const struct imx_mxc_nand_data imx35_mxc
 	imx_mxc_nand_data_entry_single(MX35, "imx25-nand", SZ_8K);
 #endif
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
-	imx_mxc_nandv3_data_entry_single(MX51, "imx51-nand", SZ_16K);
-#endif
-
 struct platform_device *__init imx_add_mxc_nand(
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc_rnga.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc_rnga.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-mxc_rnga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-mxc_rnga.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,9 +48,6 @@ static int __init imxXX_add_mxc_rnga(voi
 #endif /* if defined(CONFIG_SOC_IMX31) */
 		ret = ERR_PTR(-ENODEV);
 
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(ret);
 }
 arch_initcall(imxXX_add_mxc_rnga);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-pata_imx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-pata_imx.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-pata_imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-pata_imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,16 +28,6 @@ const struct imx_pata_imx_data imx35_pat
 	imx_pata_imx_data_entry_single(MX35, SZ_16K);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX51, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX53, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_pata_imx(
 		const struct imx_pata_imx_data *data)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,30 +43,6 @@ imx35_sdhci_esdhc_imx_data[] __initconst
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_sdhci_esdhc_imx_data
-imx51_sdhci_esdhc_imx_data[] __initconst = {
-#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
-	imx51_sdhci_esdhc_imx_data_entry(0, 1),
-	imx51_sdhci_esdhc_imx_data_entry(1, 2),
-	imx51_sdhci_esdhc_imx_data_entry(2, 3),
-	imx51_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_sdhci_esdhc_imx_data
-imx53_sdhci_esdhc_imx_data[] __initconst = {
-#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
-	imx53_sdhci_esdhc_imx_data_entry(0, 1),
-	imx53_sdhci_esdhc_imx_data_entry(1, 2),
-	imx53_sdhci_esdhc_imx_data_entry(2, 3),
-	imx53_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
 	.wp_type = ESDHC_WP_NONE,
 	.cd_type = ESDHC_CD_NONE,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-spi_imx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-spi_imx.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices/platform-spi_imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices/platform-spi_imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -79,33 +79,6 @@ const struct imx_spi_imx_data imx35_cspi
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx51_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
-#define imx51_ecspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
-	imx51_ecspi_data_entry(0, 1),
-	imx51_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx53_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-/* i.mx53 has the i.mx51 type ecspi */
-const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
-#define imx53_ecspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
-	imx53_ecspi_data_entry(0, 1),
-	imx53_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
 struct platform_device *__init imx_add_spi_imx(
 		const struct imx_spi_imx_data *data,
 		const struct spi_imx_master *pdata)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/devices-imx51.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices-imx51.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/devices-imx51.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/devices-imx51.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "devices/devices-common.h"
-
-extern const struct imx_fec_data imx51_fec_data;
-#define imx51_add_fec(pdata)	\
-	imx_add_fec(&imx51_fec_data, pdata)
-
-extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
-#define imx51_add_fsl_usb2_udc(pdata)	\
-	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
-
-extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
-#define imx51_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
-#define imx51_add_hsi2c(pdata)	\
-	imx51_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
-#define imx51_add_imx_ssi(id, pdata)	\
-	imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
-#define imx51_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
-
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
-#define imx51_add_mxc_ehci_otg(pdata)	\
-	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
-#define imx51_add_mxc_ehci_hs(id, pdata)	\
-	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
-
-extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
-#define imx51_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
-#define imx51_add_sdhci_esdhc_imx(id, pdata)	\
-	imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx51_cspi_data;
-#define imx51_add_cspi(pdata)	\
-	imx_add_spi_imx(&imx51_cspi_data, pdata)
-
-extern const struct imx_spi_imx_data imx51_ecspi_data[];
-#define imx51_add_ecspi(id, pdata)	\
-	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id)	\
-	imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
-
-extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
-#define imx51_add_imx_keypad(pdata)	\
-	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx51_pata_imx_data;
-#define imx51_add_pata_imx() \
-	imx_add_pata_imx(&imx51_pata_imx_data)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+#ifndef __MACH_IMX_EHCI_H
+#define __MACH_IMX_EHCI_H
+
+/* values for portsc field */
+#define MXC_EHCI_PHY_LOW_POWER_SUSPEND	(1 << 23)
+#define MXC_EHCI_FORCE_FS		(1 << 24)
+#define MXC_EHCI_UTMI_8BIT		(0 << 28)
+#define MXC_EHCI_UTMI_16BIT		(1 << 28)
+#define MXC_EHCI_SERIAL			(1 << 29)
+#define MXC_EHCI_MODE_UTMI		(0 << 30)
+#define MXC_EHCI_MODE_PHILIPS		(1 << 30)
+#define MXC_EHCI_MODE_ULPI		(2 << 30)
+#define MXC_EHCI_MODE_SERIAL		(3 << 30)
+
+/* values for flags field */
+#define MXC_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
+#define MXC_EHCI_INTERFACE_DIFF_BI	(1 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_BI	(3 << 0)
+#define MXC_EHCI_INTERFACE_MASK		(0xf)
+
+#define MXC_EHCI_POWER_PINS_ENABLED	(1 << 5)
+#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH	(1 << 6)
+#define MXC_EHCI_OC_PIN_ACTIVE_LOW	(1 << 7)
+#define MXC_EHCI_TTL_ENABLED		(1 << 8)
+
+#define MXC_EHCI_INTERNAL_PHY		(1 << 9)
+#define MXC_EHCI_IPPUE_DOWN		(1 << 10)
+#define MXC_EHCI_IPPUE_UP		(1 << 11)
+#define MXC_EHCI_WAKEUP_ENABLED		(1 << 12)
+#define MXC_EHCI_ITC_NO_THRESHOLD	(1 << 13)
+
+#define MXC_USBCTRL_OFFSET		0
+#define MXC_USB_PHY_CTR_FUNC_OFFSET	0x8
+#define MXC_USB_PHY_CTR_FUNC2_OFFSET	0xc
+#define MXC_USBH2CTRL_OFFSET		0x14
+
+int mx25_initialize_usb_hw(int port, unsigned int flags);
+int mx31_initialize_usb_hw(int port, unsigned int flags);
+int mx35_initialize_usb_hw(int port, unsigned int flags);
+int mx27_initialize_usb_hw(int port, unsigned int flags);
+
+#endif /* __MACH_IMX_EHCI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx25.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx25.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx25.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx25.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "ehci.h"
 #include "hardware.h"
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx27.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx27.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx27.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx27.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "ehci.h"
 #include "hardware.h"
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx31.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx31.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx31.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx31.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "ehci.h"
 #include "hardware.h"
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx35.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx35.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx35.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx35.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "ehci.h"
 #include "hardware.h"
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx5.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx5.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/ehci-imx5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/ehci-imx5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/platform_data/usb-ehci-mxc.h>
-
-#include "hardware.h"
-
-#define MXC_OTG_OFFSET			0
-#define MXC_H1_OFFSET			0x200
-#define MXC_H2_OFFSET			0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)	/* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_POL_BIT	(1 << 9)	/* OTG Polarity of Overcurrent */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_POL_BIT		(1 << 6)	/* UH1 Polarity of Overcurrent */
-#define MXC_H1_OC_DIS_BIT		(1 << 5)	/* UH1 Disable Overcurrent Event */
-#define MXC_OTG_PHYCTRL_PWR_POL_BIT	(1 << 3)	/* OTG Power Pin Polarity */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
-
-#define MXC_USBCMD_OFFSET		0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
-
-int mx51_initialize_usb_hw(int port, unsigned int flags)
-{
-	unsigned int v;
-	void __iomem *usb_base;
-	void __iomem *usbotg_base;
-	void __iomem *usbother_base;
-	int ret = 0;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base) {
-		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	switch (port) {
-	case 0:	/* OTG port */
-		usbotg_base = usb_base + MXC_OTG_OFFSET;
-		break;
-	case 1:	/* Host 1 port */
-		usbotg_base = usb_base + MXC_H1_OFFSET;
-		break;
-	case 2: /* Host 2 port */
-		usbotg_base = usb_base + MXC_H2_OFFSET;
-		break;
-	default:
-		printk(KERN_ERR"%s no such port %d\n", __func__, port);
-		ret = -ENOENT;
-		goto error;
-	}
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	switch (port) {
-	case 0:	/*OTG port */
-		if (flags & MXC_EHCI_INTERNAL_PHY) {
-			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
-				v |= MXC_OTG_PHYCTRL_OC_POL_BIT;
-			else
-				v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT;
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-				/* OC/USBPWR is used */
-				v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-			} else {
-				/* OC/USBPWR is not used */
-				v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-			}
-			if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
-				v |= MXC_OTG_PHYCTRL_PWR_POL_BIT;
-			else
-				v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT;
-			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED)
-				v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-			else
-				v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_OTG_UCTRL_OPM_BIT;
-			else
-				v |= MXC_OTG_UCTRL_OPM_BIT;
-			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-		}
-		break;
-	case 1:	/* Host 1 */
-		/*Host ULPI */
-		v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-			/* HOST1 wakeup/ULPI intr enable */
-			v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-		} else {
-			/* HOST1 wakeup/ULPI intr disable */
-			v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-		}
-
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask unused*/
-		else
-			v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-		__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-		v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-		if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
-			v |= MXC_H1_OC_POL_BIT;
-		else
-			v &= ~MXC_H1_OC_POL_BIT;
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-		else
-			v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-		__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-		v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-		if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-			/* Interrupt Threshold Control:Immediate (no threshold) */
-			v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-		__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-		break;
-	case 2: /* Host 2 ULPI */
-		v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-			/* HOST1 wakeup/ULPI intr enable */
-			v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-		} else {
-			/* HOST1 wakeup/ULPI intr disable */
-			v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-		}
-
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask unused*/
-		else
-			v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-		__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-		break;
-	}
-
-error:
-	iounmap(usb_base);
-	return ret;
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/gpc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/gpc.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/gpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/gpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,13 +27,14 @@ static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
 
-void imx_gpc_pre_suspend(void)
+void imx_gpc_pre_suspend(bool arm_power_off)
 {
 	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
 	int i;
 
 	/* Tell GPC to power off ARM core when suspend */
-	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+	if (arm_power_off)
+		writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
 
 	for (i = 0; i < IMR_NUM; i++) {
 		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/hardware.h	2014-09-28 17:29:07.000000000 -0400
@@ -105,8 +105,6 @@
 
 #include "mxc.h"
 
-#include "mx51.h"
-#include "mx53.h"
 #include "mx3x.h"
 #include "mx31.h"
 #include "mx35.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/imx25-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx25-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/imx25-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx25-dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,16 +29,10 @@ static const char * const imx25_dt_board
 	NULL
 };
 
-static void __init imx25_timer_init(void)
-{
-	mx25_clocks_init_dt();
-}
-
 DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
 	.map_io		= mx25_map_io,
 	.init_early	= imx25_init_early,
 	.init_irq	= mx25_init_irq,
-	.init_time	= imx25_timer_init,
 	.init_machine	= imx25_dt_init,
 	.dt_compat	= imx25_dt_board_compat,
 	.restart	= mxc_restart,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/imx27-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx27-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/imx27-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx27-dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,16 +34,10 @@ static const char * const imx27_dt_board
 	NULL
 };
 
-static void __init imx27_timer_init(void)
-{
-	mx27_clocks_init_dt();
-}
-
 DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
 	.map_io		= mx27_map_io,
 	.init_early	= imx27_init_early,
 	.init_irq	= mx27_init_irq,
-	.init_time	= imx27_timer_init,
 	.init_machine	= imx27_dt_init,
 	.dt_compat	= imx27_dt_board_compat,
 	.restart	= mxc_restart,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/imx31-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx31-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/imx31-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx31-dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@ static void __init imx31_dt_init(void)
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *imx31_dt_board_compat[] __initconst = {
+static const char * const imx31_dt_board_compat[] __initconst = {
 	"fsl,imx31",
 	NULL
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/imx35-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx35-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/imx35-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx35-dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@ static void __init imx35_irq_init(void)
 	mx35_init_irq();
 }
 
-static const char *imx35_dt_board_compat[] __initconst = {
+static const char * const imx35_dt_board_compat[] __initconst = {
 	"fsl,imx35",
 	NULL
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/imx51-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx51-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/imx51-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/imx51-dt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-#include "mx51.h"
-
-static void __init imx51_dt_init(void)
-{
-	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
-
-	mxc_arch_reset_init_dt();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	platform_device_register_full(&devinfo);
-}
-
-static const char *imx51_dt_board_compat[] __initconst = {
-	"fsl,imx51",
-	NULL
-};
-
-DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
-	.map_io		= mx51_map_io,
-	.init_early	= imx51_init_early,
-	.init_irq	= mx51_init_irq,
-	.init_machine	= imx51_dt_init,
-	.init_late	= imx51_init_late,
-	.dt_compat	= imx51_dt_board_compat,
-	.restart	= mxc_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/iomux-mx51.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/iomux-mx51.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/iomux-mx51.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/iomux-mx51.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,827 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_IOMUX_MX51_H__
-#define __MACH_IOMUX_MX51_H__
-
-#include "iomux-v3.h"
-#define __NA_	0x000
-
-
-/* Pad control groupings */
-#define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_HYS | PAD_CTL_SRE_FAST)
-#define MX51_I2C_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS)
-#define MX51_ESDHC_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS)
-#define MX51_USBH1_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS | PAD_CTL_PUE)
-#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_HYS | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
-#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \
-				PAD_CTL_SRE_FAST | PAD_CTL_DVS)
-#define MX51_GPIO_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE_FAST)
-
-#define MX51_PAD_CTRL_2		(PAD_CTL_PKE | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_3		(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_CTRL_4		(PAD_CTL_PKE | PAD_CTL_DVS | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_5		(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
-
-/*
- * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO<unit>_<num>
- * See also iomux-v3.h
- */
-
-/* Raw pin modes without pad control */
-/*							  PAD    MUX ALT INPSE PATH PADCTRL */
-
-/* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__GPT_CMPOUT1		IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__GPT_CMPOUT2		IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
-		MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
-		PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__CCM_CLKO		IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2		IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3		IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK	IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN15__DI1_PIN15		IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__CCM_CLKO2		IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPT_CLKIN		IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPT_CAPIN1		IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CCM_CLKO		IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPT_CAPIN2		IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CCM_CLKO2		IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_CLKO		IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX51_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-imx/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,5 @@
 menuconfig ARCH_MXC
 	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
-	select ARCH_HAS_OPP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_CPU_SUSPEND if PM
 	select CLKSRC_MMIO
@@ -65,18 +64,8 @@ config IMX_HAVE_IOMUX_V1
 config ARCH_MXC_IOMUX_V3
 	bool
 
-config ARCH_MX1
-	bool
-
-config ARCH_MX25
-	bool
-
-config MACH_MX27
-	bool
-
 config SOC_IMX1
 	bool
-	select ARCH_MX1
 	select CPU_ARM920T
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
@@ -89,7 +78,6 @@ config SOC_IMX21
 
 config SOC_IMX25
 	bool
-	select ARCH_MX25
 	select ARCH_MXC_IOMUX_V3
 	select CPU_ARM926T
 	select MXC_AVIC
@@ -97,10 +85,8 @@ config SOC_IMX25
 
 config SOC_IMX27
 	bool
-	select ARCH_HAS_OPP
 	select CPU_ARM926T
 	select IMX_HAVE_IOMUX_V1
-	select MACH_MX27
 	select MXC_AVIC
 	select PINCTRL_IMX27
 
@@ -119,18 +105,6 @@ config SOC_IMX35
 	select PINCTRL_IMX35
 	select SMP_ON_UP if SMP
 
-config SOC_IMX5
-	bool
-	select ARCH_HAS_OPP
-	select ARCH_MXC_IOMUX_V3
-	select MXC_TZIC
-
-config	SOC_IMX51
-	bool
-	select HAVE_IMX_SRC
-	select PINCTRL_IMX51
-	select SOC_IMX5
-
 if ARCH_MULTI_V4T
 
 comment "MX1 platforms:"
@@ -366,15 +340,6 @@ config MACH_IMX27_VISSTRIM_M10
 	  This includes specific configurations for the board and its
 	  peripherals.
 
-config MACH_IMX27LITE
-	bool "LogicPD MX27 LITEKIT platform"
-	select IMX_HAVE_PLATFORM_IMX_SSI
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select SOC_IMX27
-	help
-	  Include support for MX27 LITEKIT platform. This includes specific
-	  configurations for the board and its peripherals.
-
 config MACH_PCA100
 	bool "Phytec phyCARD-s (pca100)"
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
@@ -406,15 +371,6 @@ config MACH_MXT_TD60
 	  Include support for i-MXT (aka td60) platform. This
 	  includes specific configurations for the module and its peripherals.
 
-config MACH_IMX27IPCAM
-	bool "IMX27 IPCAM platform"
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select SOC_IMX27
-	help
-	  Include support for IMX27 IPCAM platform. This includes specific
-	  configurations for the board and its peripherals.
-
 config MACH_IMX27_DT
 	bool "Support i.MX27 platforms from device tree"
 	select SOC_IMX27
@@ -700,24 +656,28 @@ if ARCH_MULTI_V7
 
 comment "Device tree only"
 
+config SOC_IMX5
+	bool
+	select HAVE_IMX_SRC
+	select MXC_TZIC
+
 config	SOC_IMX50
 	bool "i.MX50 support"
-	select HAVE_IMX_SRC
 	select PINCTRL_IMX50
 	select SOC_IMX5
 
 	help
 	  This enables support for Freescale i.MX50 processor.
 
-config MACH_IMX51_DT
+config SOC_IMX51
 	bool "i.MX51 support"
-	select SOC_IMX51
+	select PINCTRL_IMX51
+	select SOC_IMX5
 	help
 	  This enables support for Freescale i.MX51 processor
 
 config	SOC_IMX53
 	bool "i.MX53 support"
-	select HAVE_IMX_SRC
 	select PINCTRL_IMX53
 	select SOC_IMX5
 
@@ -734,8 +694,6 @@ config SOC_IMX6
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_SRC
 	select MFD_SYSCON
-	select PL310_ERRATA_588369 if CACHE_L2X0
-	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 
 config SOC_IMX6Q
@@ -771,8 +729,6 @@ config SOC_VF610
 	select ARM_GIC
 	select PINCTRL_VF610
 	select VF_PIT_TIMER
-	select PL310_ERRATA_588369 if CACHE_L2X0
-	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 
 	help
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-armadillo5x0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-armadillo5x0.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-armadillo5x0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-armadillo5x0.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@
 #include "common.h"
 #include "devices-imx31.h"
 #include "crmregs-imx3.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-cpuimx27.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-cpuimx27.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 
 #include "common.h"
 #include "devices-imx27.h"
+#include "ehci.h"
 #include "eukrea-baseboards.h"
 #include "hardware.h"
 #include "iomux-mx27.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-cpuimx35.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-cpuimx35.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-cpuimx35.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-cpuimx35.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,7 @@
 
 #include "common.h"
 #include "devices-imx35.h"
+#include "ehci.h"
 #include "eukrea-baseboards.h"
 #include "hardware.h"
 #include "iomux-mx35.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include "common.h"
 #include "devices-imx25.h"
+#include "ehci.h"
 #include "eukrea-baseboards.h"
 #include "hardware.h"
 #include "iomux-mx25.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27ipcam.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27ipcam.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Author: Fabio Estevam <fabio.estevam@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "hardware.h"
-#include "common.h"
-#include "devices-imx27.h"
-#include "iomux-mx27.h"
-
-static const int mx27ipcam_pins[] __initconst = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-};
-
-static void __init mx27ipcam_init(void)
-{
-	imx27_soc_init();
-
-	mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
-		"mx27ipcam");
-
-	imx27_add_imx_uart0(NULL);
-	imx27_add_fec(NULL);
-	imx27_add_imx2_wdt();
-}
-
-static void __init mx27ipcam_timer_init(void)
-{
-	mx27_clocks_init(25000000);
-}
-
-MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
-	/* maintainer: Freescale Semiconductor, Inc. */
-	.atag_offset = 0x100,
-	.map_io = mx27_map_io,
-	.init_early = imx27_init_early,
-	.init_irq = mx27_init_irq,
-	.init_time	= mx27ipcam_timer_init,
-	.init_machine = mx27ipcam_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27lite.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27lite.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27lite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27lite.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/*
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- * Copyright 2009 Daniel Schaeffer (daniel.schaeffer@timesys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices-imx27.h"
-#include "hardware.h"
-#include "iomux-mx27.h"
-
-static const int mx27lite_pins[] __initconst = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static void __init mx27lite_init(void)
-{
-	imx27_soc_init();
-
-	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
-		"imx27lite");
-	imx27_add_imx_uart0(&uart_pdata);
-	imx27_add_fec(NULL);
-}
-
-static void __init mx27lite_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.atag_offset = 0x100,
-	.map_io = mx27_map_io,
-	.init_early = imx27_init_early,
-	.init_irq = mx27_init_irq,
-	.init_time	= mx27lite_timer_init,
-	.init_machine = mx27lite_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,6 +43,7 @@
 
 #include "common.h"
 #include "devices-imx27.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx27.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx50.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx50.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx50.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,14 +23,13 @@ static void __init imx50_dt_init(void)
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *imx50_dt_board_compat[] __initconst = {
+static const char * const imx50_dt_board_compat[] __initconst = {
 	"fsl,imx50",
 	NULL
 };
 
 DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
-	.map_io		= mx53_map_io,
-	.init_irq	= mx53_init_irq,
+	.init_irq	= tzic_init_irq,
 	.init_machine	= imx50_dt_init,
 	.dt_compat	= imx50_dt_board_compat,
 	.restart	= mxc_restart,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx51.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx51.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx51.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx51.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+#include "hardware.h"
+
+static void __init imx51_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX51);
+}
+
+/*
+ * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
+ * the Freescale marketing division. However this did not remove the
+ * hardware from the chip which still needs to be configured for proper
+ * IPU support.
+ */
+#define MX51_MIPI_HSC_BASE 0x83fdc000
+static void __init imx51_ipu_mipi_setup(void)
+{
+	void __iomem *hsc_addr;
+
+	hsc_addr = ioremap(MX51_MIPI_HSC_BASE, SZ_16K);
+	WARN_ON(!hsc_addr);
+
+	/* setup MIPI module to legacy mode */
+	__raw_writel(0xf00, hsc_addr);
+
+	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
+	__raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
+		hsc_addr + 0x800);
+
+	iounmap(hsc_addr);
+}
+
+static void __init imx51_dt_init(void)
+{
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
+	mxc_arch_reset_init_dt();
+	imx51_ipu_mipi_setup();
+	imx_src_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	platform_device_register_full(&devinfo);
+}
+
+static void __init imx51_init_late(void)
+{
+	mx51_neon_fixup();
+	imx51_pm_init();
+}
+
+static const char * const imx51_dt_board_compat[] __initconst = {
+	"fsl,imx51",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.init_early	= imx51_init_early,
+	.init_irq	= tzic_init_irq,
+	.init_machine	= imx51_dt_init,
+	.init_late	= imx51_init_late,
+	.dt_compat	= imx51_dt_board_compat,
+	.restart	= mxc_restart,
+MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx53.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx53.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx53.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx53.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,24 +22,35 @@
 
 #include "common.h"
 #include "hardware.h"
-#include "mx53.h"
+
+static void __init imx53_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX53);
+}
 
 static void __init imx53_dt_init(void)
 {
 	mxc_arch_reset_init_dt();
+	imx_src_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
 }
 
-static const char *imx53_dt_board_compat[] __initconst = {
+static void __init imx53_init_late(void)
+{
+	imx53_pm_init();
+}
+
+static const char * const imx53_dt_board_compat[] __initconst = {
 	"fsl,imx53",
 	NULL
 };
 
 DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
-	.map_io		= mx53_map_io,
 	.init_early	= imx53_init_early,
-	.init_irq	= mx53_init_irq,
+	.init_irq	= tzic_init_irq,
 	.init_machine	= imx53_dt_init,
 	.init_late	= imx53_init_late,
 	.dt_compat	= imx53_dt_board_compat,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6q.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6q.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6q.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6q.c	2014-09-28 17:29:07.000000000 -0400
@@ -320,7 +320,7 @@ static void __init imx6q_opp_check_speed
 	val >>= OCOTP_CFG3_SPEED_SHIFT;
 	val &= 0x3;
 
-	if (val != OCOTP_CFG3_SPEED_1P2GHZ)
+	if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q())
 		if (dev_pm_opp_disable(cpu_dev, 1200000000))
 			pr_warn("failed to disable 1.2 GHz OPP\n");
 	if (val < OCOTP_CFG3_SPEED_996MHZ)
@@ -396,7 +396,7 @@ static void __init imx6q_init_irq(void)
 	irqchip_init();
 }
 
-static const char *imx6q_dt_compat[] __initconst = {
+static const char * const imx6q_dt_compat[] __initconst = {
 	"fsl,imx6dl",
 	"fsl,imx6q",
 	NULL,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6sl.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6sl.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6sl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6sl.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ static void __init imx6sl_init_irq(void)
 	irqchip_init();
 }
 
-static const char *imx6sl_dt_compat[] __initconst = {
+static const char * const imx6sl_dt_compat[] __initconst = {
 	"fsl,imx6sl",
 	NULL,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6sx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6sx.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-imx6sx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-imx6sx.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
+#include "cpuidle.h"
 
 static void __init imx6sx_init_machine(void)
 {
@@ -26,6 +27,7 @@ static void __init imx6sx_init_machine(v
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
 	imx_anatop_init();
+	imx6sx_pm_init();
 }
 
 static void __init imx6sx_init_irq(void)
@@ -37,7 +39,12 @@ static void __init imx6sx_init_irq(void)
 	irqchip_init();
 }
 
-static const char *imx6sx_dt_compat[] __initconst = {
+static void __init imx6sx_init_late(void)
+{
+	imx6q_cpuidle_init();
+}
+
+static const char * const imx6sx_dt_compat[] __initconst = {
 	"fsl,imx6sx",
 	NULL,
 };
@@ -47,5 +54,6 @@ DT_MACHINE_START(IMX6SX, "Freescale i.MX
 	.init_irq	= imx6sx_init_irq,
 	.init_machine	= imx6sx_init_machine,
 	.dt_compat	= imx6sx_dt_compat,
+	.init_late	= imx6sx_init_late,
 	.restart	= mxc_restart,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx25_3ds.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx25_3ds.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,7 @@
 
 #include "common.h"
 #include "devices-imx25.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx25.h"
 #include "mx25.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx27_3ds.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx27_3ds.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,7 @@
 #include "3ds_debugboard.h"
 #include "common.h"
 #include "devices-imx27.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx27.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx27ads.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx27ads.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx27ads.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx27ads.c	2014-09-28 17:29:07.000000000 -0400
@@ -245,7 +245,7 @@ static void __init mx27ads_regulator_ini
 	vchip->set		= vgpio_set;
 	gpiochip_add(vchip);
 
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage",
+	platform_device_register_data(NULL, "reg-fixed-voltage",
 				      PLATFORM_DEVID_AUTO,
 				      &mx27ads_lcd_regulator_pdata,
 				      sizeof(mx27ads_lcd_regulator_pdata));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31_3ds.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31_3ds.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31_3ds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31_3ds.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,7 @@
 #include "3ds_debugboard.h"
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31lilly.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31lilly.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31lilly.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31lilly.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,7 @@
 #include "board-mx31lilly.h"
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31lite.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31lite.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31lite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31lite.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,7 @@
 #include "board-mx31lite.h"
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31moboard.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31moboard.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx31moboard.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx31moboard.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,7 @@
 #include "board-mx31moboard.h"
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
@@ -434,10 +435,8 @@ static int __init moboard_usbh2_init(voi
 		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 static const struct gpio_led mx31moboard_leds[] __initconst = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx35_3ds.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx35_3ds.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-mx35_3ds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-mx35_3ds.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@
 #include "3ds_debugboard.h"
 #include "common.h"
 #include "devices-imx35.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx35.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pca100.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pca100.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pca100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pca100.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 
 #include "common.h"
 #include "devices-imx27.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx27.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm037.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm037.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm037.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm037.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,7 @@
 
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "pcm037.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm038.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm038.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm038.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm038.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include "board-pcm038.h"
 #include "common.h"
 #include "devices-imx27.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx27.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm043.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm043.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-pcm043.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-pcm043.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include "common.h"
 #include "devices-imx35.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx35.h"
 #include "ulpi.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-vf610.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-vf610.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-vf610.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-vf610.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,7 @@ static void __init vf610_init_machine(vo
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *vf610_dt_compat[] __initconst = {
+static const char * const vf610_dt_compat[] __initconst = {
 	"fsl,vf610",
 	NULL,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mach-vpr200.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-vpr200.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mach-vpr200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mach-vpr200.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 
 #include "common.h"
 #include "devices-imx35.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx35.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-imx/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
 imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y)
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o clk.o \
@@ -31,6 +31,8 @@ ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
 obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
+# i.MX6SX reuses i.MX6Q cpuidle driver
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
 endif
 
 ifdef CONFIG_SND_IMX_SOC
@@ -38,9 +40,6 @@ obj-y += ssi-fiq.o
 obj-y += ssi-fiq-ksym.o
 endif
 
-# Support for CMOS sensor interface
-obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
-
 # i.MX1 based machines
 obj-$(CONFIG_ARCH_MX1ADS) += mach-mx1ads.o
 obj-$(CONFIG_MACH_SCB9328) += mach-scb9328.o
@@ -60,13 +59,11 @@ obj-$(CONFIG_MACH_MX27ADS) += mach-mx27a
 obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
 obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
-obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
 obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o
 obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
 obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
 obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
-obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o
 obj-$(CONFIG_MACH_IMX27_DT) += imx27-dt.o
 
 # i.MX31 based machines
@@ -96,9 +93,11 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
 obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+ifdef CONFIG_SOC_IMX6
 AFLAGS_headsmp.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+endif
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o
@@ -109,8 +108,8 @@ obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
 endif
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
-obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
+obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
 
 obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mm-imx5.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mm-imx5.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mm-imx5.c	2014-08-07 04:46:50.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mm-imx5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/of_address.h>
-
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices/devices-common.h"
-#include "hardware.h"
-#include "iomux-v3.h"
-
-/*
- * Define the MX51 memory map.
- */
-static struct map_desc mx51_io_desc[] __initdata = {
-	imx_map_entry(MX51, TZIC, MT_DEVICE),
-	imx_map_entry(MX51, IRAM, MT_DEVICE),
-	imx_map_entry(MX51, AIPS1, MT_DEVICE),
-	imx_map_entry(MX51, SPBA0, MT_DEVICE),
-	imx_map_entry(MX51, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX53 memory map.
- */
-static struct map_desc mx53_io_desc[] __initdata = {
-	imx_map_entry(MX53, TZIC, MT_DEVICE),
-	imx_map_entry(MX53, AIPS1, MT_DEVICE),
-	imx_map_entry(MX53, SPBA0, MT_DEVICE),
-	imx_map_entry(MX53, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx51_map_io(void)
-{
-	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
-}
-
-void __init mx53_map_io(void)
-{
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
-}
-
-/*
- * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
- * the Freescale marketing division. However this did not remove the
- * hardware from the chip which still needs to be configured for proper
- * IPU support.
- */
-static void __init imx51_ipu_mipi_setup(void)
-{
-	void __iomem *hsc_addr;
-	hsc_addr = MX51_IO_ADDRESS(MX51_MIPI_HSC_BASE_ADDR);
-
-	/* setup MIPI module to legacy mode */
-	__raw_writel(0xf00, hsc_addr);
-
-	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
-	__raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
-		hsc_addr + 0x800);
-}
-
-void __init imx51_init_early(void)
-{
-	imx51_ipu_mipi_setup();
-	mxc_set_cpu_type(MXC_CPU_MX51);
-	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
-	imx_src_init();
-}
-
-void __init imx53_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX53);
-	imx_src_init();
-}
-
-void __init mx51_init_irq(void)
-{
-	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
-}
-
-void __init mx53_init_irq(void)
-{
-	struct device_node *np;
-	void __iomem *base;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-tzic");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-
-	tzic_init_irq(base);
-}
-
-static struct sdma_platform_data imx51_sdma_pdata __initdata = {
-	.fw_name = "/*(DEBLOBBED)*/",
-};
-
-static const struct resource imx51_audmux_res[] __initconst = {
-	DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
-};
-
-void __init imx51_soc_init(void)
-{
-	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-	mxc_device_init();
-
-	/* i.mx51 has the i.mx35 type gpio */
-	mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx35-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx35-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
-
-	pinctrl_provide_dummies();
-
-	/* i.mx51 has the i.mx35 type sdma */
-	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
-
-	/* Setup AIPS registers */
-	imx_set_aips(MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR));
-	imx_set_aips(MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR));
-
-	/* i.mx51 has the i.mx31 type audmux */
-	platform_device_register_simple("imx31-audmux", 0, imx51_audmux_res,
-					ARRAY_SIZE(imx51_audmux_res));
-}
-
-void __init imx51_init_late(void)
-{
-	mx51_neon_fixup();
-	imx5_pm_init();
-}
-
-void __init imx53_init_late(void)
-{
-	imx5_pm_init();
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx1-camera-fiq-ksym.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx1-camera-fiq-ksym.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx1-camera-fiq-ksym.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Exported ksyms of ARCH_MX1
- *
- * Copyright (C) 2008, Darius Augulis <augulis.darius@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/platform_device.h>
-#include <linux/module.h>
-
-#include <linux/platform_data/camera-mx1.h>
-
-/* IMX camera FIQ handler */
-EXPORT_SYMBOL(mx1_camera_sof_fiq_start);
-EXPORT_SYMBOL(mx1_camera_sof_fiq_end);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx1-camera-fiq.S linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx1-camera-fiq.S
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx1-camera-fiq.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx1-camera-fiq.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- *  Copyright (C) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- *  Based on linux/arch/arm/lib/floppydma.S
- *      Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-		.text
-		.global	mx1_camera_sof_fiq_end
-		.global	mx1_camera_sof_fiq_start
-mx1_camera_sof_fiq_start:
-		@ enable dma
-		ldr	r12, [r9]
-		orr	r12, r12, #0x00000001
-		str	r12, [r9]
-		@ unmask DMA interrupt
-		ldr	r12, [r8]
-		bic	r12, r12, r13
-		str	r12, [r8]
-		@ disable SOF interrupt
-		ldr	r12, [r10]
-		bic	r12, r12, #0x00010000
-		str	r12, [r10]
-		@ clear SOF flag
-		mov	r12, #0x00010000
-		str	r12, [r11]
-		@ return from FIQ
-		subs	pc, lr, #4
-mx1_camera_sof_fiq_end:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-devboard.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-devboard.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-devboard.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-devboard.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
@@ -213,10 +214,8 @@ static int __init devboard_usbh1_init(vo
 	usbh1_pdata.otg = phy;
 
 	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-marxbot.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-marxbot.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-marxbot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-marxbot.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
@@ -327,10 +328,8 @@ static int __init marxbot_usbh1_init(voi
 	usbh1_pdata.otg = phy;
 
 	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 static const struct fsl_usb2_platform_data usb_pdata __initconst = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-smartbot.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-smartbot.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx31moboard-smartbot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx31moboard-smartbot.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include "board-mx31moboard.h"
 #include "common.h"
 #include "devices-imx31.h"
+#include "ehci.h"
 #include "hardware.h"
 #include "iomux-mx3.h"
 #include "ulpi.h"
@@ -141,10 +142,8 @@ static int __init smartbot_otg_host_init
 		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_otg(&otg_host_pdata);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 #else
 static inline int smartbot_otg_host_init(void) { return 0; }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx51.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx51.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx51.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx51.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,346 +0,0 @@
-#ifndef __MACH_MX51_H__
-#define __MACH_MX51_H__
-
-/*
- * IROM
- */
-#define MX51_IROM_BASE_ADDR		0x0
-#define MX51_IROM_SIZE			SZ_64K
-
-/*
- * IRAM
- */
-#define MX51_IRAM_BASE_ADDR		0x1ffe0000	/* internal ram */
-#define MX51_IRAM_PARTITIONS		16
-#define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-#define MX51_GPU_BASE_ADDR		0x20000000
-#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
-
-/*
- * SPBA global module enabled #0
- */
-#define MX51_SPBA0_BASE_ADDR		0x70000000
-#define MX51_SPBA0_SIZE			SZ_1M
-
-#define MX51_ESDHC1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x04000)
-#define MX51_ESDHC2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x08000)
-#define MX51_UART3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x0c000)
-#define MX51_ECSPI1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x10000)
-#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x14000)
-#define MX51_ESDHC3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x20000)
-#define MX51_ESDHC4_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x24000)
-#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x28000)
-#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x30000)
-#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x34000)
-#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x38000)
-#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x3c000)
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR		0x73f00000
-#define MX51_AIPS1_SIZE			SZ_1M
-
-#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
-#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
-#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
-#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
-#define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
-#define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
-#define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
-#define MX51_GPIO4_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x90000)
-#define MX51_KPP_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x94000)
-#define MX51_WDOG1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
-#define MX51_WDOG2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x9c000)
-#define MX51_GPT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa0000)
-#define MX51_SRTC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa4000)
-#define MX51_IOMUXC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa8000)
-#define MX51_EPIT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xac000)
-#define MX51_EPIT2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb0000)
-#define MX51_PWM1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb4000)
-#define MX51_PWM2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb8000)
-#define MX51_UART1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xbc000)
-#define MX51_UART2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xc0000)
-#define MX51_SRC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd0000)
-#define MX51_CCM_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd4000)
-#define MX51_GPC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd8000)
-
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR		0x83f00000
-#define MX51_AIPS2_SIZE			SZ_1M
-
-#define MX51_PLL1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x80000)
-#define MX51_PLL2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x84000)
-#define MX51_PLL3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x88000)
-#define MX51_AHBMAX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x94000)
-#define MX51_IIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x98000)
-#define MX51_CSU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x9c000)
-#define MX51_ARM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa0000)
-#define MX51_OWIRE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa4000)
-#define MX51_FIRI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa8000)
-#define MX51_ECSPI2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xac000)
-#define MX51_SDMA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb0000)
-#define MX51_SCC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb4000)
-#define MX51_ROMCP_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb8000)
-#define MX51_RTIC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xbc000)
-#define MX51_CSPI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc0000)
-#define MX51_I2C2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc4000)
-#define MX51_I2C1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc8000)
-#define MX51_SSI1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xcc000)
-#define MX51_AUDMUX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd0000)
-#define MX51_M4IF_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd8000)
-#define MX51_ESDCTL_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd9000)
-#define MX51_WEIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xda000)
-#define MX51_NFC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdb000)
-#define MX51_EMI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdbf00)
-#define MX51_MIPI_HSC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdc000)
-#define MX51_ATA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe0000)
-#define MX51_SIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe4000)
-#define MX51_SSI3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
-#define MX51_FEC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xec000)
-#define MX51_TVE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf0000)
-#define MX51_VPU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf4000)
-#define MX51_SAHARA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf8000)
-
-#define MX51_CSD0_BASE_ADDR		0x90000000
-#define MX51_CSD1_BASE_ADDR		0xa0000000
-#define MX51_CS0_BASE_ADDR		0xb0000000
-#define MX51_CS1_BASE_ADDR		0xb8000000
-#define MX51_CS2_BASE_ADDR		0xc0000000
-#define MX51_CS3_BASE_ADDR		0xc8000000
-#define MX51_CS4_BASE_ADDR		0xcc000000
-#define MX51_CS5_BASE_ADDR		0xce000000
-
-/*
- * NFC
- */
-#define MX51_NFC_AXI_BASE_ADDR		0xcfff0000	/* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE		SZ_64K
-
-#define MX51_GPU2D_BASE_ADDR		0xd0000000
-#define MX51_TZIC_BASE_ADDR		0xe0000000
-#define MX51_TZIC_SIZE			SZ_16K
-
-#define MX51_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX51_SPBA_SDHC1	0x04
-#define MX51_SPBA_SDHC2	0x08
-#define MX51_SPBA_UART3	0x0c
-#define MX51_SPBA_CSPI1	0x10
-#define MX51_SPBA_SSI2	0x14
-#define MX51_SPBA_SDHC3	0x20
-#define MX51_SPBA_SDHC4	0x24
-#define MX51_SPBA_SPDIF	0x28
-#define MX51_SPBA_ATA	0x30
-#define MX51_SPBA_SLIM	0x34
-#define MX51_SPBA_HSI2C	0x38
-#define MX51_SPBA_CTRL	0x3c
-
-/*
- * Defines for modules using static and dynamic DMA channels
- */
-#define MX51_MXC_DMA_CHANNEL_IRAM	30
-#define MX51_MXC_DMA_CHANNEL_SPDIF_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC1	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC2	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#ifdef CONFIG_SDMA_IRAM
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX	(MX51_MXC_DMA_CHANNEL_IRAM + 1)
-#else				/*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#endif				/*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_CSPI1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MEMORY	MXC_DMA_DYNAMIC_CHANNEL
-
-#define MX51_IS_MEM_DEVICE_NONSHARED(x)		0
-
-/*
- * DMA request assignments
- */
-#define MX51_DMA_REQ_VPU		0
-#define MX51_DMA_REQ_GPC		1
-#define MX51_DMA_REQ_ATA_RX		2
-#define MX51_DMA_REQ_ATA_TX		3
-#define MX51_DMA_REQ_ATA_TX_END		4
-#define MX51_DMA_REQ_SLIM_B		5
-#define MX51_DMA_REQ_CSPI1_RX		6
-#define MX51_DMA_REQ_CSPI1_TX		7
-#define MX51_DMA_REQ_CSPI2_RX		8
-#define MX51_DMA_REQ_CSPI2_TX		9
-#define MX51_DMA_REQ_HS_I2C_TX		10
-#define MX51_DMA_REQ_HS_I2C_RX		11
-#define MX51_DMA_REQ_FIRI_RX		12
-#define MX51_DMA_REQ_FIRI_TX		13
-#define MX51_DMA_REQ_EXTREQ1		14
-#define MX51_DMA_REQ_GPU		15
-#define MX51_DMA_REQ_UART2_RX		16
-#define MX51_DMA_REQ_UART2_TX		17
-#define MX51_DMA_REQ_UART1_RX		18
-#define MX51_DMA_REQ_UART1_TX		19
-#define MX51_DMA_REQ_SDHC1		20
-#define MX51_DMA_REQ_SDHC2		21
-#define MX51_DMA_REQ_SSI2_RX1		22
-#define MX51_DMA_REQ_SSI2_TX1		23
-#define MX51_DMA_REQ_SSI2_RX0		24
-#define MX51_DMA_REQ_SSI2_TX0		25
-#define MX51_DMA_REQ_SSI1_RX1		26
-#define MX51_DMA_REQ_SSI1_TX1		27
-#define MX51_DMA_REQ_SSI1_RX0		28
-#define MX51_DMA_REQ_SSI1_TX0		29
-#define MX51_DMA_REQ_EMI_RD		30
-#define MX51_DMA_REQ_CTI2_0		31
-#define MX51_DMA_REQ_EMI_WR		32
-#define MX51_DMA_REQ_CTI2_1		33
-#define MX51_DMA_REQ_EPIT2		34
-#define MX51_DMA_REQ_SSI3_RX1		35
-#define MX51_DMA_REQ_IPU		36
-#define MX51_DMA_REQ_SSI3_TX1		37
-#define MX51_DMA_REQ_CSPI_RX		38
-#define MX51_DMA_REQ_CSPI_TX		39
-#define MX51_DMA_REQ_SDHC3		40
-#define MX51_DMA_REQ_SDHC4		41
-#define MX51_DMA_REQ_SLIM_B_TX		42
-#define MX51_DMA_REQ_UART3_RX		43
-#define MX51_DMA_REQ_UART3_TX		44
-#define MX51_DMA_REQ_SPDIF		45
-#define MX51_DMA_REQ_SSI3_RX0		46
-#define MX51_DMA_REQ_SSI3_TX0		47
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX51_INT_BASE			(NR_IRQS_LEGACY + 0)
-#define MX51_INT_RESV0			(NR_IRQS_LEGACY + 0)
-#define MX51_INT_ESDHC1			(NR_IRQS_LEGACY + 1)
-#define MX51_INT_ESDHC2			(NR_IRQS_LEGACY + 2)
-#define MX51_INT_ESDHC3			(NR_IRQS_LEGACY + 3)
-#define MX51_INT_ESDHC4			(NR_IRQS_LEGACY + 4)
-#define MX51_INT_RESV5			(NR_IRQS_LEGACY + 5)
-#define MX51_INT_SDMA			(NR_IRQS_LEGACY + 6)
-#define MX51_INT_IOMUX			(NR_IRQS_LEGACY + 7)
-#define MX51_INT_NFC			(NR_IRQS_LEGACY + 8)
-#define MX51_INT_VPU			(NR_IRQS_LEGACY + 9)
-#define MX51_INT_IPU_ERR		(NR_IRQS_LEGACY + 10)
-#define MX51_INT_IPU_SYN		(NR_IRQS_LEGACY + 11)
-#define MX51_INT_GPU			(NR_IRQS_LEGACY + 12)
-#define MX51_INT_RESV13			(NR_IRQS_LEGACY + 13)
-#define MX51_INT_USB_HS1		(NR_IRQS_LEGACY + 14)
-#define MX51_INT_EMI			(NR_IRQS_LEGACY + 15)
-#define MX51_INT_USB_HS2		(NR_IRQS_LEGACY + 16)
-#define MX51_INT_USB_HS3		(NR_IRQS_LEGACY + 17)
-#define MX51_INT_USB_OTG		(NR_IRQS_LEGACY + 18)
-#define MX51_INT_SAHARA_H0		(NR_IRQS_LEGACY + 19)
-#define MX51_INT_SAHARA_H1		(NR_IRQS_LEGACY + 20)
-#define MX51_INT_SCC_SMN		(NR_IRQS_LEGACY + 21)
-#define MX51_INT_SCC_STZ		(NR_IRQS_LEGACY + 22)
-#define MX51_INT_SCC_SCM		(NR_IRQS_LEGACY + 23)
-#define MX51_INT_SRTC_NTZ		(NR_IRQS_LEGACY + 24)
-#define MX51_INT_SRTC_TZ		(NR_IRQS_LEGACY + 25)
-#define MX51_INT_RTIC			(NR_IRQS_LEGACY + 26)
-#define MX51_INT_CSU			(NR_IRQS_LEGACY + 27)
-#define MX51_INT_SLIM_B			(NR_IRQS_LEGACY + 28)
-#define MX51_INT_SSI1			(NR_IRQS_LEGACY + 29)
-#define MX51_INT_SSI2			(NR_IRQS_LEGACY + 30)
-#define MX51_INT_UART1			(NR_IRQS_LEGACY + 31)
-#define MX51_INT_UART2			(NR_IRQS_LEGACY + 32)
-#define MX51_INT_UART3			(NR_IRQS_LEGACY + 33)
-#define MX51_INT_RESV34			(NR_IRQS_LEGACY + 34)
-#define MX51_INT_RESV35			(NR_IRQS_LEGACY + 35)
-#define MX51_INT_ECSPI1			(NR_IRQS_LEGACY + 36)
-#define MX51_INT_ECSPI2			(NR_IRQS_LEGACY + 37)
-#define MX51_INT_CSPI			(NR_IRQS_LEGACY + 38)
-#define MX51_INT_GPT			(NR_IRQS_LEGACY + 39)
-#define MX51_INT_EPIT1			(NR_IRQS_LEGACY + 40)
-#define MX51_INT_EPIT2			(NR_IRQS_LEGACY + 41)
-#define MX51_INT_GPIO1_INT7		(NR_IRQS_LEGACY + 42)
-#define MX51_INT_GPIO1_INT6		(NR_IRQS_LEGACY + 43)
-#define MX51_INT_GPIO1_INT5		(NR_IRQS_LEGACY + 44)
-#define MX51_INT_GPIO1_INT4		(NR_IRQS_LEGACY + 45)
-#define MX51_INT_GPIO1_INT3		(NR_IRQS_LEGACY + 46)
-#define MX51_INT_GPIO1_INT2		(NR_IRQS_LEGACY + 47)
-#define MX51_INT_GPIO1_INT1		(NR_IRQS_LEGACY + 48)
-#define MX51_INT_GPIO1_INT0		(NR_IRQS_LEGACY + 49)
-#define MX51_INT_GPIO1_LOW		(NR_IRQS_LEGACY + 50)
-#define MX51_INT_GPIO1_HIGH		(NR_IRQS_LEGACY + 51)
-#define MX51_INT_GPIO2_LOW		(NR_IRQS_LEGACY + 52)
-#define MX51_INT_GPIO2_HIGH		(NR_IRQS_LEGACY + 53)
-#define MX51_INT_GPIO3_LOW		(NR_IRQS_LEGACY + 54)
-#define MX51_INT_GPIO3_HIGH		(NR_IRQS_LEGACY + 55)
-#define MX51_INT_GPIO4_LOW		(NR_IRQS_LEGACY + 56)
-#define MX51_INT_GPIO4_HIGH		(NR_IRQS_LEGACY + 57)
-#define MX51_INT_WDOG1			(NR_IRQS_LEGACY + 58)
-#define MX51_INT_WDOG2			(NR_IRQS_LEGACY + 59)
-#define MX51_INT_KPP			(NR_IRQS_LEGACY + 60)
-#define MX51_INT_PWM1			(NR_IRQS_LEGACY + 61)
-#define MX51_INT_I2C1			(NR_IRQS_LEGACY + 62)
-#define MX51_INT_I2C2			(NR_IRQS_LEGACY + 63)
-#define MX51_INT_HS_I2C			(NR_IRQS_LEGACY + 64)
-#define MX51_INT_RESV65			(NR_IRQS_LEGACY + 65)
-#define MX51_INT_RESV66			(NR_IRQS_LEGACY + 66)
-#define MX51_INT_SIM_IPB		(NR_IRQS_LEGACY + 67)
-#define MX51_INT_SIM_DAT		(NR_IRQS_LEGACY + 68)
-#define MX51_INT_IIM			(NR_IRQS_LEGACY + 69)
-#define MX51_INT_ATA			(NR_IRQS_LEGACY + 70)
-#define MX51_INT_CCM1			(NR_IRQS_LEGACY + 71)
-#define MX51_INT_CCM2			(NR_IRQS_LEGACY + 72)
-#define MX51_INT_GPC1			(NR_IRQS_LEGACY + 73)
-#define MX51_INT_GPC2			(NR_IRQS_LEGACY + 74)
-#define MX51_INT_SRC			(NR_IRQS_LEGACY + 75)
-#define MX51_INT_NM			(NR_IRQS_LEGACY + 76)
-#define MX51_INT_PMU			(NR_IRQS_LEGACY + 77)
-#define MX51_INT_CTI_IRQ		(NR_IRQS_LEGACY + 78)
-#define MX51_INT_CTI1_TG0		(NR_IRQS_LEGACY + 79)
-#define MX51_INT_CTI1_TG1		(NR_IRQS_LEGACY + 80)
-#define MX51_INT_MCG_ERR		(NR_IRQS_LEGACY + 81)
-#define MX51_INT_MCG_TMR		(NR_IRQS_LEGACY + 82)
-#define MX51_INT_MCG_FUNC		(NR_IRQS_LEGACY + 83)
-#define MX51_INT_GPU2_IRQ		(NR_IRQS_LEGACY + 84)
-#define MX51_INT_GPU2_BUSY		(NR_IRQS_LEGACY + 85)
-#define MX51_INT_RESV86			(NR_IRQS_LEGACY + 86)
-#define MX51_INT_FEC			(NR_IRQS_LEGACY + 87)
-#define MX51_INT_OWIRE			(NR_IRQS_LEGACY + 88)
-#define MX51_INT_CTI1_TG2		(NR_IRQS_LEGACY + 89)
-#define MX51_INT_SJC			(NR_IRQS_LEGACY + 90)
-#define MX51_INT_SPDIF			(NR_IRQS_LEGACY + 91)
-#define MX51_INT_TVE			(NR_IRQS_LEGACY + 92)
-#define MX51_INT_FIRI			(NR_IRQS_LEGACY + 93)
-#define MX51_INT_PWM2			(NR_IRQS_LEGACY + 94)
-#define MX51_INT_SLIM_EXP		(NR_IRQS_LEGACY + 95)
-#define MX51_INT_SSI3			(NR_IRQS_LEGACY + 96)
-#define MX51_INT_EMI_BOOT		(NR_IRQS_LEGACY + 97)
-#define MX51_INT_CTI1_TG3		(NR_IRQS_LEGACY + 98)
-#define MX51_INT_SMC_RX			(NR_IRQS_LEGACY + 99)
-#define MX51_INT_VPU_IDLE		(NR_IRQS_LEGACY + 100)
-#define MX51_INT_EMI_NFC		(NR_IRQS_LEGACY + 101)
-#define MX51_INT_GPU_IDLE		(NR_IRQS_LEGACY + 102)
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx51_revision(void);
-extern void mx51_display_revision(void);
-#endif
-
-#endif	/* ifndef __MACH_MX51_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mx53.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx53.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mx53.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mx53.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,342 +0,0 @@
-#ifndef __MACH_MX53_H__
-#define __MACH_MX53_H__
-
-/*
- * IROM
- */
-#define MX53_IROM_BASE_ADDR		0x0
-#define MX53_IROM_SIZE			SZ_64K
-
-/* TZIC */
-#define MX53_TZIC_BASE_ADDR		0x0FFFC000
-#define MX53_TZIC_SIZE			SZ_16K
-
-/*
- * AHCI SATA
- */
-#define MX53_SATA_BASE_ADDR		0x10000000
-
-/*
- * NFC
- */
-#define MX53_NFC_AXI_BASE_ADDR	0xF7FF0000	/* NAND flash AXI */
-#define MX53_NFC_AXI_SIZE		SZ_64K
-
-/*
- * IRAM
- */
-#define MX53_IRAM_BASE_ADDR	0xF8000000	/* internal ram */
-#define MX53_IRAM_PARTITIONS	16
-#define MX53_IRAM_SIZE		(MX53_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-/*
- * Graphics Memory of GPU
- */
-#define MX53_IPU_CTRL_BASE_ADDR	0x18000000
-#define MX53_GPU2D_BASE_ADDR		0x20000000
-#define MX53_GPU_BASE_ADDR		0x30000000
-#define MX53_GPU_GMEM_BASE_ADDR	0xF8020000
-
-#define MX53_DEBUG_BASE_ADDR		0x40000000
-#define MX53_DEBUG_SIZE		SZ_1M
-#define MX53_ETB_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00001000)
-#define MX53_ETM_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00002000)
-#define MX53_TPIU_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00003000)
-#define MX53_CTI0_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00004000)
-#define MX53_CTI1_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00005000)
-#define MX53_CTI2_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00006000)
-#define MX53_CTI3_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00007000)
-#define MX53_CORTEX_DBG_BASE_ADDR	(MX53_DEBUG_BASE_ADDR + 0x00008000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX53_SPBA0_BASE_ADDR		0x50000000
-#define MX53_SPBA0_SIZE		SZ_1M
-
-#define MX53_ESDHC1_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00004000)
-#define MX53_ESDHC2_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00008000)
-#define MX53_UART3_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX53_ECSPI1_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00010000)
-#define MX53_SSI2_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00014000)
-#define MX53_ESDHC3_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00020000)
-#define MX53_ESDHC4_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00024000)
-#define MX53_SPDIF_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00028000)
-#define MX53_ASRC_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0002C000)
-#define MX53_ATA_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00030000)
-#define MX53_SLIM_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00034000)
-#define MX53_HSI2C_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00038000)
-#define MX53_SPBA_CTRL_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x0003C000)
-
-/*
- * AIPS 1
- */
-#define MX53_AIPS1_BASE_ADDR	0x53F00000
-#define MX53_AIPS1_SIZE		SZ_1M
-
-#define MX53_OTG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00080000)
-#define MX53_GPIO1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00084000)
-#define MX53_GPIO2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00088000)
-#define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
-#define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
-#define MX53_WDOG1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
-#define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX53_IOMUXC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX53_EPIT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX53_EPIT2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX53_PWM1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX53_PWM2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX53_UART1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX53_UART2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX53_SRC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX53_CCM_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX53_GPC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D8000)
-#define MX53_GPIO5_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000DC000)
-#define MX53_GPIO6_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E0000)
-#define MX53_GPIO7_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E4000)
-#define MX53_ATA_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E8000)
-#define MX53_I2C3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000EC000)
-#define MX53_UART4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000F0000)
-
-/*
- * AIPS 2
- */
-#define MX53_AIPS2_BASE_ADDR		0x63F00000
-#define MX53_AIPS2_SIZE			SZ_1M
-
-#define MX53_PLL1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00080000)
-#define MX53_PLL2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00084000)
-#define MX53_PLL3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00088000)
-#define MX53_PLL4_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0008C000)
-#define MX53_UART5_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00090000)
-#define MX53_AHBMAX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00094000)
-#define MX53_IIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00098000)
-#define MX53_CSU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX53_ARM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX53_OWIRE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX53_FIRI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX53_ECSPI2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX53_SDMA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX53_SCC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX53_ROMCP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX53_RTIC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX53_CSPI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX53_I2C2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX53_I2C1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX53_SSI1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX53_AUDMUX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX53_RTC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D4000)
-#define MX53_M4IF_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX53_ESDCTL_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX53_WEIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX53_NFC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX53_EMI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX53_MIPI_HSC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX53_MLB_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX53_SSI3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX53_FEC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX53_TVE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX53_VPU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX53_SAHARA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F8000)
-#define MX53_PTP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000FC000)
-
-/*
- * Memory regions and CS
- */
-#define MX53_CSD0_BASE_ADDR		0x70000000
-#define MX53_CSD1_BASE_ADDR		0xB0000000
-#define MX53_CS0_BASE_ADDR		0xF0000000
-#define MX53_CS1_32MB_BASE_ADDR	0xF2000000
-#define MX53_CS1_64MB_BASE_ADDR		0xF4000000
-#define MX53_CS2_64MB_BASE_ADDR		0xF4000000
-#define MX53_CS2_96MB_BASE_ADDR		0xF6000000
-#define MX53_CS3_BASE_ADDR		0xF6000000
-
-#define MX53_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX53_IO_ADDRESS(x)		IOMEM(MX53_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX53_SPBA_SDHC1	0x04
-#define MX53_SPBA_SDHC2	0x08
-#define MX53_SPBA_UART3	0x0C
-#define MX53_SPBA_CSPI1	0x10
-#define MX53_SPBA_SSI2		0x14
-#define MX53_SPBA_SDHC3	0x20
-#define MX53_SPBA_SDHC4	0x24
-#define MX53_SPBA_SPDIF	0x28
-#define MX53_SPBA_ATA		0x30
-#define MX53_SPBA_SLIM		0x34
-#define MX53_SPBA_HSI2C	0x38
-#define MX53_SPBA_CTRL		0x3C
-
-/*
- * DMA request assignments
- */
-#define MX53_DMA_REQ_SSI3_TX0		47
-#define MX53_DMA_REQ_SSI3_RX0		46
-#define MX53_DMA_REQ_SSI3_TX1		45
-#define MX53_DMA_REQ_SSI3_RX1		44
-#define MX53_DMA_REQ_UART3_TX	43
-#define MX53_DMA_REQ_UART3_RX	42
-#define MX53_DMA_REQ_ESAI_TX		41
-#define MX53_DMA_REQ_ESAI_RX		40
-#define MX53_DMA_REQ_CSPI_TX		39
-#define MX53_DMA_REQ_CSPI_RX		38
-#define MX53_DMA_REQ_ASRC_DMA6	37
-#define MX53_DMA_REQ_ASRC_DMA5	36
-#define MX53_DMA_REQ_ASRC_DMA4	35
-#define MX53_DMA_REQ_ASRC_DMA3	34
-#define MX53_DMA_REQ_ASRC_DMA2	33
-#define MX53_DMA_REQ_ASRC_DMA1	32
-#define MX53_DMA_REQ_EMI_WR		31
-#define MX53_DMA_REQ_EMI_RD		30
-#define MX53_DMA_REQ_SSI1_TX0		29
-#define MX53_DMA_REQ_SSI1_RX0		28
-#define MX53_DMA_REQ_SSI1_TX1		27
-#define MX53_DMA_REQ_SSI1_RX1		26
-#define MX53_DMA_REQ_SSI2_TX0		25
-#define MX53_DMA_REQ_SSI2_RX0		24
-#define MX53_DMA_REQ_SSI2_TX1		23
-#define MX53_DMA_REQ_SSI2_RX1		22
-#define MX53_DMA_REQ_I2C2_SDHC2	21
-#define MX53_DMA_REQ_I2C1_SDHC1	20
-#define MX53_DMA_REQ_UART1_TX	19
-#define MX53_DMA_REQ_UART1_RX	18
-#define MX53_DMA_REQ_UART5_TX	17
-#define MX53_DMA_REQ_UART5_RX	16
-#define MX53_DMA_REQ_SPDIF_TX		15
-#define MX53_DMA_REQ_SPDIF_RX		14
-#define MX53_DMA_REQ_UART2_FIRI_TX	13
-#define MX53_DMA_REQ_UART2_FIRI_RX	12
-#define MX53_DMA_REQ_SDHC4		11
-#define MX53_DMA_REQ_I2C3_SDHC3	10
-#define MX53_DMA_REQ_CSPI2_TX		9
-#define MX53_DMA_REQ_CSPI2_RX		8
-#define MX53_DMA_REQ_CSPI1_TX		7
-#define MX53_DMA_REQ_CSPI1_RX		6
-#define MX53_DMA_REQ_IPU		5
-#define MX53_DMA_REQ_ATA_TX_END	4
-#define MX53_DMA_REQ_ATA_UART4_TX	3
-#define MX53_DMA_REQ_ATA_UART4_RX	2
-#define MX53_DMA_REQ_GPC		1
-#define MX53_DMA_REQ_VPU		0
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX53_INT_RESV0		(NR_IRQS_LEGACY + 0)
-#define MX53_INT_ESDHC1		(NR_IRQS_LEGACY + 1)
-#define MX53_INT_ESDHC2		(NR_IRQS_LEGACY + 2)
-#define MX53_INT_ESDHC3		(NR_IRQS_LEGACY + 3)
-#define MX53_INT_ESDHC4		(NR_IRQS_LEGACY + 4)
-#define MX53_INT_DAP		(NR_IRQS_LEGACY + 5)
-#define MX53_INT_SDMA		(NR_IRQS_LEGACY + 6)
-#define MX53_INT_IOMUX		(NR_IRQS_LEGACY + 7)
-#define MX53_INT_NFC		(NR_IRQS_LEGACY + 8)
-#define MX53_INT_VPU		(NR_IRQS_LEGACY + 9)
-#define MX53_INT_IPU_ERR	(NR_IRQS_LEGACY + 10)
-#define MX53_INT_IPU_SYN	(NR_IRQS_LEGACY + 11)
-#define MX53_INT_GPU		(NR_IRQS_LEGACY + 12)
-#define MX53_INT_UART4		(NR_IRQS_LEGACY + 13)
-#define MX53_INT_USB_H1		(NR_IRQS_LEGACY + 14)
-#define MX53_INT_EMI		(NR_IRQS_LEGACY + 15)
-#define MX53_INT_USB_H2		(NR_IRQS_LEGACY + 16)
-#define MX53_INT_USB_H3		(NR_IRQS_LEGACY + 17)
-#define MX53_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
-#define MX53_INT_SAHARA_H0	(NR_IRQS_LEGACY + 19)
-#define MX53_INT_SAHARA_H1	(NR_IRQS_LEGACY + 20)
-#define MX53_INT_SCC_SMN	(NR_IRQS_LEGACY + 21)
-#define MX53_INT_SCC_STZ	(NR_IRQS_LEGACY + 22)
-#define MX53_INT_SCC_SCM	(NR_IRQS_LEGACY + 23)
-#define MX53_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
-#define MX53_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
-#define MX53_INT_RTIC		(NR_IRQS_LEGACY + 26)
-#define MX53_INT_CSU		(NR_IRQS_LEGACY + 27)
-#define MX53_INT_SATA		(NR_IRQS_LEGACY + 28)
-#define MX53_INT_SSI1		(NR_IRQS_LEGACY + 29)
-#define MX53_INT_SSI2		(NR_IRQS_LEGACY + 30)
-#define MX53_INT_UART1		(NR_IRQS_LEGACY + 31)
-#define MX53_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX53_INT_UART3		(NR_IRQS_LEGACY + 33)
-#define MX53_INT_RTC		(NR_IRQS_LEGACY + 34)
-#define MX53_INT_PTP		(NR_IRQS_LEGACY + 35)
-#define MX53_INT_ECSPI1		(NR_IRQS_LEGACY + 36)
-#define MX53_INT_ECSPI2		(NR_IRQS_LEGACY + 37)
-#define MX53_INT_CSPI		(NR_IRQS_LEGACY + 38)
-#define MX53_INT_GPT		(NR_IRQS_LEGACY + 39)
-#define MX53_INT_EPIT1		(NR_IRQS_LEGACY + 40)
-#define MX53_INT_EPIT2		(NR_IRQS_LEGACY + 41)
-#define MX53_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
-#define MX53_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
-#define MX53_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
-#define MX53_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
-#define MX53_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
-#define MX53_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
-#define MX53_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
-#define MX53_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
-#define MX53_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
-#define MX53_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
-#define MX53_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
-#define MX53_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
-#define MX53_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
-#define MX53_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
-#define MX53_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
-#define MX53_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
-#define MX53_INT_WDOG1		(NR_IRQS_LEGACY + 58)
-#define MX53_INT_WDOG2		(NR_IRQS_LEGACY + 59)
-#define MX53_INT_KPP		(NR_IRQS_LEGACY + 60)
-#define MX53_INT_PWM1		(NR_IRQS_LEGACY + 61)
-#define MX53_INT_I2C1		(NR_IRQS_LEGACY + 62)
-#define MX53_INT_I2C2		(NR_IRQS_LEGACY + 63)
-#define MX53_INT_I2C3		(NR_IRQS_LEGACY + 64)
-#define MX53_INT_MLB		(NR_IRQS_LEGACY + 65)
-#define MX53_INT_ASRC		(NR_IRQS_LEGACY + 66)
-#define MX53_INT_SPDIF		(NR_IRQS_LEGACY + 67)
-#define MX53_INT_SIM_DAT	(NR_IRQS_LEGACY + 68)
-#define MX53_INT_IIM		(NR_IRQS_LEGACY + 69)
-#define MX53_INT_ATA		(NR_IRQS_LEGACY + 70)
-#define MX53_INT_CCM1		(NR_IRQS_LEGACY + 71)
-#define MX53_INT_CCM2		(NR_IRQS_LEGACY + 72)
-#define MX53_INT_GPC1		(NR_IRQS_LEGACY + 73)
-#define MX53_INT_GPC2		(NR_IRQS_LEGACY + 74)
-#define MX53_INT_SRC		(NR_IRQS_LEGACY + 75)
-#define MX53_INT_NM		(NR_IRQS_LEGACY + 76)
-#define MX53_INT_PMU		(NR_IRQS_LEGACY + 77)
-#define MX53_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
-#define MX53_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
-#define MX53_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
-#define MX53_INT_ESAI		(NR_IRQS_LEGACY + 81)
-#define MX53_INT_CAN1		(NR_IRQS_LEGACY + 82)
-#define MX53_INT_CAN2		(NR_IRQS_LEGACY + 83)
-#define MX53_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
-#define MX53_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
-#define MX53_INT_UART5		(NR_IRQS_LEGACY + 86)
-#define MX53_INT_FEC		(NR_IRQS_LEGACY + 87)
-#define MX53_INT_OWIRE		(NR_IRQS_LEGACY + 88)
-#define MX53_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
-#define MX53_INT_SJC		(NR_IRQS_LEGACY + 90)
-#define MX53_INT_TVE		(NR_IRQS_LEGACY + 92)
-#define MX53_INT_FIRI		(NR_IRQS_LEGACY + 93)
-#define MX53_INT_PWM2		(NR_IRQS_LEGACY + 94)
-#define MX53_INT_SLIM_EXP	(NR_IRQS_LEGACY + 95)
-#define MX53_INT_SSI3		(NR_IRQS_LEGACY + 96)
-#define MX53_INT_EMI_BOOT	(NR_IRQS_LEGACY + 97)
-#define MX53_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
-#define MX53_INT_SMC_RX		(NR_IRQS_LEGACY + 99)
-#define MX53_INT_VPU_IDLE	(NR_IRQS_LEGACY + 100)
-#define MX53_INT_EMI_NFC	(NR_IRQS_LEGACY + 101)
-#define MX53_INT_GPU_IDLE	(NR_IRQS_LEGACY + 102)
-#define MX53_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
-#define MX53_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
-#define MX53_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
-#define MX53_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
-#define MX53_INT_GPIO7_LOW	(NR_IRQS_LEGACY + 107)
-#define MX53_INT_GPIO7_HIGH	(NR_IRQS_LEGACY + 108)
-
-#endif /* ifndef __MACH_MX53_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/mxc.h linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mxc.h
--- linux-libre-3.16-gnu/arch/arm/mach-imx/mxc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/mxc.h	2014-09-28 17:29:07.000000000 -0400
@@ -154,10 +154,17 @@ extern unsigned int __mxc_cpu_type;
 #endif
 
 #ifndef __ASSEMBLY__
+#ifdef CONFIG_SOC_IMX6SL
 static inline bool cpu_is_imx6sl(void)
 {
 	return __mxc_cpu_type == MXC_CPU_IMX6SL;
 }
+#else
+static inline bool cpu_is_imx6sl(void)
+{
+	return false;
+}
+#endif
 
 static inline bool cpu_is_imx6dl(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/pm-imx5.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/pm-imx5.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/pm-imx5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/pm-imx5.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,9 +19,26 @@
 
 #include "common.h"
 #include "cpuidle.h"
-#include "crm-regs-imx5.h"
 #include "hardware.h"
 
+#define MXC_CCM_CLPCR			0x54
+#define MXC_CCM_CLPCR_LPM_OFFSET	0
+#define MXC_CCM_CLPCR_LPM_MASK		0x3
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET	9
+#define MXC_CCM_CLPCR_VSTBY		(0x1 << 8)
+#define MXC_CCM_CLPCR_SBYOS		(0x1 << 6)
+
+#define MXC_CORTEXA8_PLAT_LPC		0xc
+#define MXC_CORTEXA8_PLAT_LPC_DSM	(1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM	(1 << 1)
+
+#define MXC_SRPG_NEON_SRPGCR		0x280
+#define MXC_SRPG_ARM_SRPGCR		0x2a0
+#define MXC_SRPG_EMPGC0_SRPGCR		0x2c0
+#define MXC_SRPG_EMPGC1_SRPGCR		0x2d0
+
+#define MXC_SRPGCR_PCR			1
+
 /*
  * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
  * This is also the lowest power state possible without affecting
@@ -32,6 +49,30 @@
  */
 #define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
 
+struct imx5_pm_data {
+	phys_addr_t cortex_addr;
+	phys_addr_t gpc_addr;
+};
+
+static const struct imx5_pm_data imx51_pm_data __initconst = {
+	.cortex_addr = 0x83fa0000,
+	.gpc_addr = 0x73fd8000,
+};
+
+static const struct imx5_pm_data imx53_pm_data __initconst = {
+	.cortex_addr = 0x63fa0000,
+	.gpc_addr = 0x53fd8000,
+};
+
+static void __iomem *ccm_base;
+static void __iomem *cortex_base;
+static void __iomem *gpc_base;
+
+void __init imx5_pm_set_ccm_base(void __iomem *base)
+{
+	ccm_base = base;
+}
+
 /*
  * set cpu low power mode before WFI instruction. This function is called
  * mx5 because it can be used for mx51, and mx53.
@@ -43,12 +84,16 @@ static void mx5_cpu_lp_set(enum mxc_cpu_
 	int stop_mode = 0;
 
 	/* always allow platform to issue a deep sleep mode request */
-	plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+	plat_lpc = __raw_readl(cortex_base + MXC_CORTEXA8_PLAT_LPC) &
 	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
-	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
-	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
-	empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
-	empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+	ccm_clpcr = __raw_readl(ccm_base + MXC_CCM_CLPCR) &
+		    ~(MXC_CCM_CLPCR_LPM_MASK);
+	arm_srpgcr = __raw_readl(gpc_base + MXC_SRPG_ARM_SRPGCR) &
+		     ~(MXC_SRPGCR_PCR);
+	empgc0 = __raw_readl(gpc_base + MXC_SRPG_EMPGC0_SRPGCR) &
+		 ~(MXC_SRPGCR_PCR);
+	empgc1 = __raw_readl(gpc_base + MXC_SRPG_EMPGC1_SRPGCR) &
+		 ~(MXC_SRPGCR_PCR);
 
 	switch (mode) {
 	case WAIT_CLOCKED:
@@ -82,17 +127,17 @@ static void mx5_cpu_lp_set(enum mxc_cpu_
 		return;
 	}
 
-	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
-	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
-	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
-	__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+	__raw_writel(plat_lpc, cortex_base + MXC_CORTEXA8_PLAT_LPC);
+	__raw_writel(ccm_clpcr, ccm_base + MXC_CCM_CLPCR);
+	__raw_writel(arm_srpgcr, gpc_base + MXC_SRPG_ARM_SRPGCR);
+	__raw_writel(arm_srpgcr, gpc_base + MXC_SRPG_NEON_SRPGCR);
 
 	if (stop_mode) {
 		empgc0 |= MXC_SRPGCR_PCR;
 		empgc1 |= MXC_SRPGCR_PCR;
 
-		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
-		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+		__raw_writel(empgc0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(empgc1, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
 	}
 }
 
@@ -114,8 +159,8 @@ static int mx5_suspend_enter(suspend_sta
 		flush_cache_all();
 
 		/*clear the EMPGC0/1 bits */
-		__raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
-		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+		__raw_writel(0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(0, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
 	}
 	cpu_do_idle();
 
@@ -149,7 +194,7 @@ static void imx5_pm_idle(void)
 	imx5_cpu_do_idle();
 }
 
-static int __init imx5_pm_common_init(void)
+static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
 {
 	int ret;
 	struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
@@ -163,15 +208,28 @@ static int __init imx5_pm_common_init(vo
 
 	arm_pm_idle = imx5_pm_idle;
 
+	cortex_base = ioremap(data->cortex_addr, SZ_16K);
+	gpc_base = ioremap(data->gpc_addr, SZ_16K);
+	WARN_ON(!ccm_base || !cortex_base || !gpc_base);
+
 	/* Set the registers to the default cpu idle state. */
 	mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
 
-	return imx5_cpuidle_init();
+	ret = imx5_cpuidle_init();
+	if (ret)
+		pr_warn("%s: cpuidle init failed %d\n", __func__, ret);
+
+	suspend_set_ops(&mx5_suspend_ops);
+
+	return 0;
 }
 
-void __init imx5_pm_init(void)
+void __init imx51_pm_init(void)
 {
-	int ret = imx5_pm_common_init();
-	if (!ret)
-		suspend_set_ops(&mx5_suspend_ops);
+	imx5_pm_common_init(&imx51_pm_data);
+}
+
+void __init imx53_pm_init(void)
+{
+	imx5_pm_common_init(&imx53_pm_data);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/pm-imx6.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/pm-imx6.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/pm-imx6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/pm-imx6.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,6 +129,14 @@ static const u32 imx6sl_mmdc_io_offset[]
 	0x330, 0x334, 0x320,        /* SDCKE0, SDCKE1, RESET */
 };
 
+static const u32 imx6sx_mmdc_io_offset[] __initconst = {
+	0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
+	0x60c, 0x610, 0x61c, 0x620, /* GPR_B0DS ~ GPR_B3DS */
+	0x300, 0x2fc, 0x32c, 0x5f4, /* CAS, RAS, SDCLK_0, GPR_ADDS */
+	0x310, 0x314, 0x5f8, 0x608, /* SODT0, SODT1, MODE_CTL, MODE */
+	0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
+};
+
 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
 	.cpu_type = MXC_CPU_IMX6Q,
 	.mmdc_compat = "fsl,imx6q-mmdc",
@@ -159,6 +167,16 @@ static const struct imx6_pm_socdata imx6
 	.mmdc_io_offset = imx6sl_mmdc_io_offset,
 };
 
+static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
+	.cpu_type = MXC_CPU_IMX6SX,
+	.mmdc_compat = "fsl,imx6sx-mmdc",
+	.src_compat = "fsl,imx6sx-src",
+	.iomuxc_compat = "fsl,imx6sx-iomuxc",
+	.gpc_compat = "fsl,imx6sx-gpc",
+	.mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
+	.mmdc_io_offset = imx6sx_mmdc_io_offset,
+};
+
 /*
  * This structure is for passing necessary data for low level ocram
  * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
@@ -181,11 +199,13 @@ struct imx6_cpu_pm_info {
 	u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
 } __aligned(8);
 
-void imx6q_set_int_mem_clk_lpm(void)
+void imx6q_set_int_mem_clk_lpm(bool enable)
 {
 	u32 val = readl_relaxed(ccm_base + CGPR);
 
-	val |= BM_CGPR_INT_MEM_CLK_LPM;
+	val &= ~BM_CGPR_INT_MEM_CLK_LPM;
+	if (enable)
+		val |= BM_CGPR_INT_MEM_CLK_LPM;
 	writel_relaxed(val, ccm_base + CGPR);
 }
 
@@ -254,6 +274,14 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode
 		break;
 	case STOP_POWER_ON:
 		val |= 0x2 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		if (cpu_is_imx6sl())
+			val |= BM_CLPCR_BYPASS_PMIC_READY;
+		if (cpu_is_imx6sl() || cpu_is_imx6sx())
+			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+		else
+			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
 		break;
 	case WAIT_UNCLOCKED_POWER_OFF:
 		val |= 0x1 << BP_CLPCR_LPM;
@@ -265,12 +293,12 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode
 		val |= 0x3 << BP_CLPCR_STBY_COUNT;
 		val |= BM_CLPCR_VSTBY;
 		val |= BM_CLPCR_SBYOS;
-		if (cpu_is_imx6sl()) {
+		if (cpu_is_imx6sl())
 			val |= BM_CLPCR_BYPASS_PMIC_READY;
+		if (cpu_is_imx6sl() || cpu_is_imx6sx())
 			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
-		} else {
+		else
 			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
-		}
 		break;
 	default:
 		return -EINVAL;
@@ -314,8 +342,22 @@ static int imx6q_suspend_finish(unsigned
 static int imx6q_pm_enter(suspend_state_t state)
 {
 	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		imx6q_set_lpm(STOP_POWER_ON);
+		imx6q_set_int_mem_clk_lpm(true);
+		imx_gpc_pre_suspend(false);
+		if (cpu_is_imx6sl())
+			imx6sl_set_wait_clk(true);
+		/* Zzz ... */
+		cpu_do_idle();
+		if (cpu_is_imx6sl())
+			imx6sl_set_wait_clk(false);
+		imx_gpc_post_resume();
+		imx6q_set_lpm(WAIT_CLOCKED);
+		break;
 	case PM_SUSPEND_MEM:
 		imx6q_set_lpm(STOP_POWER_OFF);
+		imx6q_set_int_mem_clk_lpm(false);
 		imx6q_enable_wb(true);
 		/*
 		 * For suspend into ocram, asm code already take care of
@@ -323,7 +365,7 @@ static int imx6q_pm_enter(suspend_state_
 		 */
 		if (!imx6_suspend_in_ocram_fn)
 			imx6q_enable_rbc(true);
-		imx_gpc_pre_suspend();
+		imx_gpc_pre_suspend(true);
 		imx_anatop_pre_suspend();
 		imx_set_cpu_jump(0, v7_cpu_resume);
 		/* Zzz ... */
@@ -334,6 +376,7 @@ static int imx6q_pm_enter(suspend_state_
 		imx_gpc_post_resume();
 		imx6q_enable_rbc(false);
 		imx6q_enable_wb(false);
+		imx6q_set_int_mem_clk_lpm(true);
 		imx6q_set_lpm(WAIT_CLOCKED);
 		break;
 	default:
@@ -343,9 +386,14 @@ static int imx6q_pm_enter(suspend_state_
 	return 0;
 }
 
+static int imx6q_pm_valid(suspend_state_t state)
+{
+	return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
+}
+
 static const struct platform_suspend_ops imx6q_pm_ops = {
 	.enter = imx6q_pm_enter,
-	.valid = suspend_valid_only_mem,
+	.valid = imx6q_pm_valid,
 };
 
 void __init imx6q_pm_set_ccm_base(void __iomem *base)
@@ -549,3 +597,8 @@ void __init imx6sl_pm_init(void)
 {
 	imx6_pm_common_init(&imx6sl_pm_data);
 }
+
+void __init imx6sx_pm_init(void)
+{
+	imx6_pm_common_init(&imx6sx_pm_data);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/suspend-imx6.S linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/suspend-imx6.S
--- linux-libre-3.16-gnu/arch/arm/mach-imx/suspend-imx6.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/suspend-imx6.S	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "hardware.h"
@@ -172,6 +173,8 @@ ENTRY(imx6_suspend)
 	ldr	r6, [r11, #0x0]
 	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
 	ldr	r6, [r11, #0x0]
+	ldr	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
+	ldr	r6, [r11, #0x0]
 
 	/* use r11 to store the IO address */
 	ldr	r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
@@ -301,7 +304,7 @@ rbc_loop:
 	resume_mmdc
 
 	/* return to suspend finish */
-	mov	pc, lr
+	ret	lr
 
 resume:
 	/* invalidate L1 I-cache first */
@@ -325,7 +328,7 @@ resume:
 	mov	r5, #0x1
 	resume_mmdc
 
-	mov	pc, lr
+	ret	lr
 ENDPROC(imx6_suspend)
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/system.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/system.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/system.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/system.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,10 @@ void mxc_restart(enum reboot_mode mode,
 {
 	unsigned int wcr_enable;
 
-	if (wdog_clk)
+	if (!wdog_base)
+		goto reset_fallback;
+
+	if (!IS_ERR(wdog_clk))
 		clk_enable(wdog_clk);
 
 	if (cpu_is_mx1())
@@ -70,6 +73,7 @@ void mxc_restart(enum reboot_mode mode,
 	/* delay to allow the serial port to show the message */
 	mdelay(50);
 
+reset_fallback:
 	/* we'll take a jump through zero as a poor second */
 	soft_restart(0);
 }
@@ -79,13 +83,10 @@ void __init mxc_arch_reset_init(void __i
 	wdog_base = base;
 
 	wdog_clk = clk_get_sys("imx2-wdt.0", NULL);
-	if (IS_ERR(wdog_clk)) {
+	if (IS_ERR(wdog_clk))
 		pr_warn("%s: failed to get wdog clock\n", __func__);
-		wdog_clk = NULL;
-		return;
-	}
-
-	clk_prepare(wdog_clk);
+	else
+		clk_prepare(wdog_clk);
 }
 
 void __init mxc_arch_reset_init_dt(void)
@@ -97,13 +98,10 @@ void __init mxc_arch_reset_init_dt(void)
 	WARN_ON(!wdog_base);
 
 	wdog_clk = of_clk_get(np, 0);
-	if (IS_ERR(wdog_clk)) {
+	if (IS_ERR(wdog_clk))
 		pr_warn("%s: failed to get wdog clock\n", __func__);
-		wdog_clk = NULL;
-		return;
-	}
-
-	clk_prepare(wdog_clk);
+	else
+		clk_prepare(wdog_clk);
 }
 
 #ifdef CONFIG_CACHE_L2X0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/time.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/time.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -290,25 +290,20 @@ static int __init mxc_clockevent_init(st
 	return 0;
 }
 
-void __init mxc_timer_init(void __iomem *base, int irq)
+static void __init _mxc_timer_init(int irq,
+				   struct clk *clk_per, struct clk *clk_ipg)
 {
 	uint32_t tctl_val;
-	struct clk *timer_clk;
-	struct clk *timer_ipg_clk;
 
-	timer_clk = clk_get_sys("imx-gpt.0", "per");
-	if (IS_ERR(timer_clk)) {
+	if (IS_ERR(clk_per)) {
 		pr_err("i.MX timer: unable to get clk\n");
 		return;
 	}
 
-	timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
-	if (!IS_ERR(timer_ipg_clk))
-		clk_prepare_enable(timer_ipg_clk);
-
-	clk_prepare_enable(timer_clk);
+	if (!IS_ERR(clk_ipg))
+		clk_prepare_enable(clk_ipg);
 
-	timer_base = base;
+	clk_prepare_enable(clk_per);
 
 	/*
 	 * Initialise to a known state (all timers off, and timing reset)
@@ -325,21 +320,45 @@ void __init mxc_timer_init(void __iomem
 	__raw_writel(tctl_val, timer_base + MXC_TCTL);
 
 	/* init and register the timer to the framework */
-	mxc_clocksource_init(timer_clk);
-	mxc_clockevent_init(timer_clk);
+	mxc_clocksource_init(clk_per);
+	mxc_clockevent_init(clk_per);
 
 	/* Make irqs happen */
 	setup_irq(irq, &mxc_timer_irq);
 }
 
-void __init mxc_timer_init_dt(struct device_node *np)
+void __init mxc_timer_init(void __iomem *base, int irq)
 {
-	void __iomem *base;
+	struct clk *clk_per = clk_get_sys("imx-gpt.0", "per");
+	struct clk *clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
+
+	timer_base = base;
+
+	_mxc_timer_init(irq, clk_per, clk_ipg);
+}
+
+static void __init mxc_timer_init_dt(struct device_node *np)
+{
+	struct clk *clk_per, *clk_ipg;
 	int irq;
 
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
+	if (timer_base)
+		return;
+
+	timer_base = of_iomap(np, 0);
+	WARN_ON(!timer_base);
 	irq = irq_of_parse_and_map(np, 0);
 
-	mxc_timer_init(base, irq);
+	clk_per = of_clk_get_by_name(np, "per");
+	clk_ipg = of_clk_get_by_name(np, "ipg");
+
+	_mxc_timer_init(irq, clk_per, clk_ipg);
 }
+CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx50_timer, "fsl,imx50-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx51_timer, "fsl,imx51-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx53_timer, "fsl,imx53-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6q_timer, "fsl,imx6q-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6sl_timer, "fsl,imx6sl-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6sx_timer, "fsl,imx6sx-gpt", mxc_timer_init_dt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-imx/tzic.c linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/tzic.c
--- linux-libre-3.16-gnu/arch/arm/mach-imx/tzic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-imx/tzic.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
@@ -153,13 +154,16 @@ static void __exception_irq_entry tzic_h
  * interrupts. It registers the interrupt enable and disable functions
  * to the kernel for each interrupt source.
  */
-void __init tzic_init_irq(void __iomem *irqbase)
+void __init tzic_init_irq(void)
 {
 	struct device_node *np;
 	int irq_base;
 	int i;
 
-	tzic_base = irqbase;
+	np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
+	tzic_base = of_iomap(np, 0);
+	WARN_ON(!tzic_base);
+
 	/* put the TZIC into the reset value with
 	 * all interrupts disabled
 	 */
@@ -181,7 +185,6 @@ void __init tzic_init_irq(void __iomem *
 	irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
 	WARN_ON(irq_base < 0);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
 	domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
 				       &irq_domain_simple_ops, NULL);
 	WARN_ON(!domain);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-integrator/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-integrator/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- *  arch/arm/mach-integrator/include/mach/memory.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#define BUS_OFFSET	UL(0x80000000)
-#define __virt_to_bus(x)	((x) - PAGE_OFFSET + BUS_OFFSET)
-#define __bus_to_virt(x)	((x) - BUS_OFFSET + PAGE_OFFSET)
-#define __pfn_to_bus(x)		(__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
-#define __bus_to_pfn(x)		__phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-integrator/integrator_ap.c linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-3.16-gnu/arch/arm/mach-integrator/integrator_ap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/integrator_ap.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/irqchip/versatile-fpga.h>
+#include <linux/irqchip.h>
 #include <linux/mtd/physmap.h>
 #include <linux/clk.h>
 #include <linux/platform_data/clk-integrator.h>
@@ -439,15 +439,10 @@ static void __init ap_of_timer_init(void
 	integrator_clockevent_init(rate, base, irq);
 }
 
-static const struct of_device_id fpga_irq_of_match[] __initconst = {
-	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
-	{ /* Sentinel */ }
-};
-
 static void __init ap_init_irq_of(void)
 {
 	cm_init();
-	of_irq_init(fpga_irq_of_match);
+	irqchip_init();
 }
 
 /* For the Device Tree, add in the UART callbacks as AUXDATA */
@@ -558,7 +553,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM
 	.map_io		= ap_map_io,
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq_of,
-	.handle_irq	= fpga_handle_irq,
 	.init_time	= ap_of_timer_init,
 	.init_machine	= ap_init_of,
 	.restart	= integrator_restart,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-integrator/integrator_cp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-3.16-gnu/arch/arm/mach-integrator/integrator_cp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/integrator_cp.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,9 +18,10 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/kmi.h>
 #include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
-#include <linux/irqchip/versatile-fpga.h>
+#include <linux/irqchip.h>
 #include <linux/gfp.h>
 #include <linux/mtd/physmap.h>
 #include <linux/of_irq.h>
@@ -36,8 +37,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <plat/clcd.h>
-
 #include "hardware.h"
 #include "cm.h"
 #include "common.h"
@@ -235,15 +234,10 @@ static void __init intcp_init_early(void
 	sched_clock_register(intcp_read_sched_clock, 32, 24000000);
 }
 
-static const struct of_device_id fpga_irq_of_match[] __initconst = {
-	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
-	{ /* Sentinel */ }
-};
-
 static void __init intcp_init_irq_of(void)
 {
 	cm_init();
-	of_irq_init(fpga_irq_of_match);
+	irqchip_init();
 }
 
 /*
@@ -329,7 +323,6 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM
 	.map_io		= intcp_map_io,
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq_of,
-	.handle_irq	= fpga_handle_irq,
 	.init_machine	= intcp_init_of,
 	.restart	= integrator_restart,
 	.dt_compat      = intcp_dt_board_compat,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-integrator/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-integrator/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-integrator/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,6 @@ config ARCH_INTEGRATOR_CP
 	bool "Support Integrator/CP platform"
 	select ARCH_CINTEGRATOR
 	select ARM_TIMER_SP804
-	select PLAT_VERSATILE_CLCD
 	select SERIAL_AMBA_PL011 if TTY
 	select SERIAL_AMBA_PL011_CONSOLE if TTY
 	select SOC_BUS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-iop13xx/include/mach/iop13xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/include/mach/iop13xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-iop13xx/include/mach/iop13xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/include/mach/iop13xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,7 +3,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/reboot.h>
+enum reboot_mode;
 
 /* The ATU offsets can change based on the strapping */
 extern u32 iop13xx_atux_pmmr_offset;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-iop13xx/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-iop13xx/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,11 +3,6 @@
 
 #include <mach/hardware.h>
 
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
 #ifndef __ASSEMBLY__
 
 #if defined(CONFIG_ARCH_IOP13XX)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-iop13xx/setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-iop13xx/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-iop13xx/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
+#include <linux/reboot.h>
 #ifdef CONFIG_MTD_PHYSMAP
 #include <linux/mtd/physmap.h>
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/board-dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/board-dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/board-dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/board-dt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,223 +0,0 @@
-/*
- * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
- *
- * arch/arm/mach-kirkwood/board-dt.c
- *
- * Flattened Device Tree board initialization
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_net.h>
-#include <linux/of_platform.h>
-#include <linux/dma-mapping.h>
-#include <linux/irqchip.h>
-#include <asm/hardware/cache-feroceon-l2.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/bridge-regs.h>
-#include <plat/common.h>
-#include <plat/pcie.h>
-#include "pm.h"
-
-static struct map_desc kirkwood_io_desc[] __initdata = {
-	{
-		.virtual	= (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
-		.pfn		= __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
-		.length		= KIRKWOOD_REGS_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void __init kirkwood_map_io(void)
-{
-	iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
-}
-
-static struct resource kirkwood_cpufreq_resources[] = {
-	[0] = {
-		.start  = CPU_CONTROL_PHYS,
-		.end    = CPU_CONTROL_PHYS + 3,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device kirkwood_cpufreq_device = {
-	.name		= "kirkwood-cpufreq",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(kirkwood_cpufreq_resources),
-	.resource	= kirkwood_cpufreq_resources,
-};
-
-static void __init kirkwood_cpufreq_init(void)
-{
-	platform_device_register(&kirkwood_cpufreq_device);
-}
-
-static struct resource kirkwood_cpuidle_resource[] = {
-	{
-		.flags	= IORESOURCE_MEM,
-		.start	= DDR_OPERATION_BASE,
-		.end	= DDR_OPERATION_BASE + 3,
-	},
-};
-
-static struct platform_device kirkwood_cpuidle = {
-	.name		= "kirkwood_cpuidle",
-	.id		= -1,
-	.resource	= kirkwood_cpuidle_resource,
-	.num_resources	= 1,
-};
-
-static void __init kirkwood_cpuidle_init(void)
-{
-	platform_device_register(&kirkwood_cpuidle);
-}
-
-/* Temporary here since mach-mvebu has a function we can use */
-static void kirkwood_restart(enum reboot_mode mode, const char *cmd)
-{
-	/*
-	 * Enable soft reset to assert RSTOUTn.
-	 */
-	writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
-	/*
-	 * Assert soft reset.
-	 */
-	writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
-	while (1)
-		;
-}
-
-#define MV643XX_ETH_MAC_ADDR_LOW	0x0414
-#define MV643XX_ETH_MAC_ADDR_HIGH	0x0418
-
-static void __init kirkwood_dt_eth_fixup(void)
-{
-	struct device_node *np;
-
-	/*
-	 * The ethernet interfaces forget the MAC address assigned by u-boot
-	 * if the clocks are turned off. Usually, u-boot on kirkwood boards
-	 * has no DT support to properly set local-mac-address property.
-	 * As a workaround, we get the MAC address from mv643xx_eth registers
-	 * and update the port device node if no valid MAC address is set.
-	 */
-	for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
-		struct device_node *pnp = of_get_parent(np);
-		struct clk *clk;
-		struct property *pmac;
-		void __iomem *io;
-		u8 *macaddr;
-		u32 reg;
-
-		if (!pnp)
-			continue;
-
-		/* skip disabled nodes or nodes with valid MAC address*/
-		if (!of_device_is_available(pnp) || of_get_mac_address(np))
-			goto eth_fixup_skip;
-
-		clk = of_clk_get(pnp, 0);
-		if (IS_ERR(clk))
-			goto eth_fixup_skip;
-
-		io = of_iomap(pnp, 0);
-		if (!io)
-			goto eth_fixup_no_map;
-
-		/* ensure port clock is not gated to not hang CPU */
-		clk_prepare_enable(clk);
-
-		/* store MAC address register contents in local-mac-address */
-		pr_err(FW_INFO "%s: local-mac-address is not set\n",
-		       np->full_name);
-
-		pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
-		if (!pmac)
-			goto eth_fixup_no_mem;
-
-		pmac->value = pmac + 1;
-		pmac->length = 6;
-		pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
-		if (!pmac->name) {
-			kfree(pmac);
-			goto eth_fixup_no_mem;
-		}
-
-		macaddr = pmac->value;
-		reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
-		macaddr[0] = (reg >> 24) & 0xff;
-		macaddr[1] = (reg >> 16) & 0xff;
-		macaddr[2] = (reg >> 8) & 0xff;
-		macaddr[3] = reg & 0xff;
-
-		reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
-		macaddr[4] = (reg >> 8) & 0xff;
-		macaddr[5] = reg & 0xff;
-
-		of_update_property(np, pmac);
-
-eth_fixup_no_mem:
-		iounmap(io);
-		clk_disable_unprepare(clk);
-eth_fixup_no_map:
-		clk_put(clk);
-eth_fixup_skip:
-		of_node_put(pnp);
-	}
-}
-
-/*
- * Disable propagation of mbus errors to the CPU local bus, as this
- * causes mbus errors (which can occur for example for PCI aborts) to
- * throw CPU aborts, which we're not set up to deal with.
- */
-static void __init kirkwood_disable_mbus_error_propagation(void)
-{
-	void __iomem *cpu_config;
-
-	cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
-	writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
-	iounmap(cpu_config);
-}
-
-static void __init kirkwood_dt_init(void)
-{
-	kirkwood_disable_mbus_error_propagation();
-
-	BUG_ON(mvebu_mbus_dt_init(false));
-
-#ifdef CONFIG_CACHE_FEROCEON_L2
-	feroceon_of_init();
-#endif
-	kirkwood_cpufreq_init();
-	kirkwood_cpuidle_init();
-
-	kirkwood_pm_init();
-	kirkwood_dt_eth_fixup();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const kirkwood_dt_board_compat[] = {
-	"marvell,kirkwood",
-	NULL
-};
-
-DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
-	/* Maintainer: Jason Cooper <jason@lakedaemon.net> */
-	.map_io		= kirkwood_map_io,
-	.init_machine	= kirkwood_dt_init,
-	.restart	= kirkwood_restart,
-	.dt_compat	= kirkwood_dt_board_compat,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,746 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/common.c
- *
- * Core functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/ata_platform.h>
-#include <linux/mtd/nand.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk-provider.h>
-#include <linux/spinlock.h>
-#include <linux/mv643xx_i2c.h>
-#include <linux/timex.h>
-#include <linux/kexec.h>
-#include <linux/reboot.h>
-#include <net/dsa.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <asm/hardware/cache-feroceon-l2.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
-#include <linux/platform_data/asoc-kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include <linux/platform_data/mtd-orion_nand.h>
-#include <linux/platform_data/usb-ehci-orion.h>
-#include <plat/common.h>
-#include <plat/time.h>
-#include <linux/platform_data/dma-mv_xor.h>
-#include "common.h"
-#include "pm.h"
-
-/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
-#define KIRKWOOD_MBUS_NAND_TARGET 0x01
-#define KIRKWOOD_MBUS_NAND_ATTR   0x2f
-#define KIRKWOOD_MBUS_SRAM_TARGET 0x03
-#define KIRKWOOD_MBUS_SRAM_ATTR   0x01
-
-/*****************************************************************************
- * I/O Address Mapping
- ****************************************************************************/
-static struct map_desc kirkwood_io_desc[] __initdata = {
-	{
-		.virtual	= (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
-		.pfn		= __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
-		.length		= KIRKWOOD_REGS_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-void __init kirkwood_map_io(void)
-{
-	iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
-}
-
-/*****************************************************************************
- * CLK tree
- ****************************************************************************/
-
-static void enable_sata0(void)
-{
-	/* Enable PLL and IVREF */
-	writel(readl(SATA0_PHY_MODE_2) | 0xf, SATA0_PHY_MODE_2);
-	/* Enable PHY */
-	writel(readl(SATA0_IF_CTRL) & ~0x200, SATA0_IF_CTRL);
-}
-
-static void disable_sata0(void)
-{
-	/* Disable PLL and IVREF */
-	writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
-	/* Disable PHY */
-	writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
-}
-
-static void enable_sata1(void)
-{
-	/* Enable PLL and IVREF */
-	writel(readl(SATA1_PHY_MODE_2) | 0xf, SATA1_PHY_MODE_2);
-	/* Enable PHY */
-	writel(readl(SATA1_IF_CTRL) & ~0x200, SATA1_IF_CTRL);
-}
-
-static void disable_sata1(void)
-{
-	/* Disable PLL and IVREF */
-	writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
-	/* Disable PHY */
-	writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
-}
-
-static void disable_pcie0(void)
-{
-	writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
-	while (1)
-		if (readl(PCIE_STATUS) & 0x1)
-			break;
-	writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
-}
-
-static void disable_pcie1(void)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-
-	if (dev == MV88F6282_DEV_ID) {
-		writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
-		while (1)
-			if (readl(PCIE1_STATUS) & 0x1)
-				break;
-		writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
-	}
-}
-
-/* An extended version of the gated clk. This calls fn_en()/fn_dis
- * before enabling/disabling the clock.  We use this to turn on/off
- * PHYs etc.  */
-struct clk_gate_fn {
-	struct clk_gate gate;
-	void (*fn_en)(void);
-	void (*fn_dis)(void);
-};
-
-#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
-#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
-
-static int clk_gate_fn_enable(struct clk_hw *hw)
-{
-	struct clk_gate *gate = to_clk_gate(hw);
-	struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
-	int ret;
-
-	ret = clk_gate_ops.enable(hw);
-	if (!ret && gate_fn->fn_en)
-		gate_fn->fn_en();
-
-	return ret;
-}
-
-static void clk_gate_fn_disable(struct clk_hw *hw)
-{
-	struct clk_gate *gate = to_clk_gate(hw);
-	struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
-
-	if (gate_fn->fn_dis)
-		gate_fn->fn_dis();
-
-	clk_gate_ops.disable(hw);
-}
-
-static struct clk_ops clk_gate_fn_ops;
-
-static struct clk __init *clk_register_gate_fn(struct device *dev,
-		const char *name,
-		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 bit_idx,
-		u8 clk_gate_flags, spinlock_t *lock,
-		void (*fn_en)(void), void (*fn_dis)(void))
-{
-	struct clk_gate_fn *gate_fn;
-	struct clk *clk;
-	struct clk_init_data init;
-
-	gate_fn = kzalloc(sizeof(struct clk_gate_fn), GFP_KERNEL);
-	if (!gate_fn) {
-		pr_err("%s: could not allocate gated clk\n", __func__);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	init.name = name;
-	init.ops = &clk_gate_fn_ops;
-	init.flags = flags;
-	init.parent_names = (parent_name ? &parent_name : NULL);
-	init.num_parents = (parent_name ? 1 : 0);
-
-	/* struct clk_gate assignments */
-	gate_fn->gate.reg = reg;
-	gate_fn->gate.bit_idx = bit_idx;
-	gate_fn->gate.flags = clk_gate_flags;
-	gate_fn->gate.lock = lock;
-	gate_fn->gate.hw.init = &init;
-	gate_fn->fn_en = fn_en;
-	gate_fn->fn_dis = fn_dis;
-
-	/* ops is the gate ops, but with our enable/disable functions */
-	if (clk_gate_fn_ops.enable != clk_gate_fn_enable ||
-	    clk_gate_fn_ops.disable != clk_gate_fn_disable) {
-		clk_gate_fn_ops = clk_gate_ops;
-		clk_gate_fn_ops.enable = clk_gate_fn_enable;
-		clk_gate_fn_ops.disable = clk_gate_fn_disable;
-	}
-
-	clk = clk_register(dev, &gate_fn->gate.hw);
-
-	if (IS_ERR(clk))
-		kfree(gate_fn);
-
-	return clk;
-}
-
-static DEFINE_SPINLOCK(gating_lock);
-static struct clk *tclk;
-
-static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
-{
-	return clk_register_gate(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
-				 bit_idx, 0, &gating_lock);
-}
-
-static struct clk __init *kirkwood_register_gate_fn(const char *name,
-						    u8 bit_idx,
-						    void (*fn_en)(void),
-						    void (*fn_dis)(void))
-{
-	return clk_register_gate_fn(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
-				    bit_idx, 0, &gating_lock, fn_en, fn_dis);
-}
-
-static struct clk *ge0, *ge1;
-
-void __init kirkwood_clk_init(void)
-{
-	struct clk *runit, *sata0, *sata1, *usb0, *sdio;
-	struct clk *crypto, *xor0, *xor1, *pex0, *pex1, *audio;
-
-	tclk = clk_register_fixed_rate(NULL, "tclk", NULL,
-				       CLK_IS_ROOT, kirkwood_tclk);
-
-	runit = kirkwood_register_gate("runit",  CGC_BIT_RUNIT);
-	ge0 = kirkwood_register_gate("ge0",    CGC_BIT_GE0);
-	ge1 = kirkwood_register_gate("ge1",    CGC_BIT_GE1);
-	sata0 = kirkwood_register_gate_fn("sata0",  CGC_BIT_SATA0,
-					  enable_sata0, disable_sata0);
-	sata1 = kirkwood_register_gate_fn("sata1",  CGC_BIT_SATA1,
-					  enable_sata1, disable_sata1);
-	usb0 = kirkwood_register_gate("usb0",   CGC_BIT_USB0);
-	sdio = kirkwood_register_gate("sdio",   CGC_BIT_SDIO);
-	crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
-	xor0 = kirkwood_register_gate("xor0",   CGC_BIT_XOR0);
-	xor1 = kirkwood_register_gate("xor1",   CGC_BIT_XOR1);
-	pex0 = kirkwood_register_gate_fn("pex0",   CGC_BIT_PEX0,
-					 NULL, disable_pcie0);
-	pex1 = kirkwood_register_gate_fn("pex1",   CGC_BIT_PEX1,
-					 NULL, disable_pcie1);
-	audio = kirkwood_register_gate("audio",  CGC_BIT_AUDIO);
-	kirkwood_register_gate("tdm",    CGC_BIT_TDM);
-	kirkwood_register_gate("tsu",    CGC_BIT_TSU);
-
-	/* clkdev entries, mapping clks to devices */
-	orion_clkdev_add(NULL, "orion_spi.0", runit);
-	orion_clkdev_add(NULL, "orion_spi.1", runit);
-	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", ge0);
-	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", ge1);
-	orion_clkdev_add(NULL, "orion_wdt", tclk);
-	orion_clkdev_add("0", "sata_mv.0", sata0);
-	orion_clkdev_add("1", "sata_mv.0", sata1);
-	orion_clkdev_add(NULL, "orion-ehci.0", usb0);
-	orion_clkdev_add(NULL, "orion_nand", runit);
-	orion_clkdev_add(NULL, "mvsdio", sdio);
-	orion_clkdev_add(NULL, "mv_crypto", crypto);
-	orion_clkdev_add(NULL, MV_XOR_NAME ".0", xor0);
-	orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
-	orion_clkdev_add("0", "pcie", pex0);
-	orion_clkdev_add("1", "pcie", pex1);
-	orion_clkdev_add(NULL, "mvebu-audio", audio);
-	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
-	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
-
-	/* Marvell says runit is used by SPI, UART, NAND, TWSI, ...,
-	 * so should never be gated.
-	 */
-	clk_prepare_enable(runit);
-}
-
-/*****************************************************************************
- * EHCI0
- ****************************************************************************/
-void __init kirkwood_ehci_init(void)
-{
-	orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
-}
-
-
-/*****************************************************************************
- * GE00
- ****************************************************************************/
-void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
-{
-	orion_ge00_init(eth_data,
-			GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
-			IRQ_KIRKWOOD_GE00_ERR, 1600);
-	/* The interface forgets the MAC address assigned by u-boot if
-	the clock is turned off, so claim the clk now. */
-	clk_prepare_enable(ge0);
-}
-
-
-/*****************************************************************************
- * GE01
- ****************************************************************************/
-void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
-{
-	orion_ge01_init(eth_data,
-			GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
-			IRQ_KIRKWOOD_GE01_ERR, 1600);
-	clk_prepare_enable(ge1);
-}
-
-
-/*****************************************************************************
- * Ethernet switch
- ****************************************************************************/
-void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq)
-{
-	orion_ge00_switch_init(d, irq);
-}
-
-
-/*****************************************************************************
- * NAND flash
- ****************************************************************************/
-static struct resource kirkwood_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
-	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
-				KIRKWOOD_NAND_MEM_SIZE - 1,
-};
-
-static struct orion_nand_data kirkwood_nand_data = {
-	.cle		= 0,
-	.ale		= 1,
-	.width		= 8,
-};
-
-static struct platform_device kirkwood_nand_flash = {
-	.name		= "orion_nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &kirkwood_nand_data,
-	},
-	.resource	= &kirkwood_nand_resource,
-	.num_resources	= 1,
-};
-
-void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
-			       int chip_delay)
-{
-	kirkwood_nand_data.parts = parts;
-	kirkwood_nand_data.nr_parts = nr_parts;
-	kirkwood_nand_data.chip_delay = chip_delay;
-	platform_device_register(&kirkwood_nand_flash);
-}
-
-void __init kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
-				   int (*dev_ready)(struct mtd_info *))
-{
-	kirkwood_nand_data.parts = parts;
-	kirkwood_nand_data.nr_parts = nr_parts;
-	kirkwood_nand_data.dev_ready = dev_ready;
-	platform_device_register(&kirkwood_nand_flash);
-}
-
-/*****************************************************************************
- * SoC RTC
- ****************************************************************************/
-static void __init kirkwood_rtc_init(void)
-{
-	orion_rtc_init(RTC_PHYS_BASE, IRQ_KIRKWOOD_RTC);
-}
-
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
-{
-	orion_sata_init(sata_data, SATA_PHYS_BASE, IRQ_KIRKWOOD_SATA);
-}
-
-
-/*****************************************************************************
- * SD/SDIO/MMC
- ****************************************************************************/
-static struct resource mvsdio_resources[] = {
-	[0] = {
-		.start	= SDIO_PHYS_BASE,
-		.end	= SDIO_PHYS_BASE + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_KIRKWOOD_SDIO,
-		.end	= IRQ_KIRKWOOD_SDIO,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 mvsdio_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device kirkwood_sdio = {
-	.name		= "mvsdio",
-	.id		= -1,
-	.dev		= {
-		.dma_mask = &mvsdio_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(mvsdio_resources),
-	.resource	= mvsdio_resources,
-};
-
-void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-	if (rev == 0 && dev != MV88F6282_DEV_ID) /* catch all Kirkwood Z0's */
-		mvsdio_data->clock = 100000000;
-	else
-		mvsdio_data->clock = 200000000;
-	kirkwood_sdio.dev.platform_data = mvsdio_data;
-	platform_device_register(&kirkwood_sdio);
-}
-
-
-/*****************************************************************************
- * SPI
- ****************************************************************************/
-void __init kirkwood_spi_init(void)
-{
-	orion_spi_init(SPI_PHYS_BASE);
-}
-
-
-/*****************************************************************************
- * I2C
- ****************************************************************************/
-void __init kirkwood_i2c_init(void)
-{
-	orion_i2c_init(I2C_PHYS_BASE, IRQ_KIRKWOOD_TWSI, 8);
-}
-
-
-/*****************************************************************************
- * UART0
- ****************************************************************************/
-
-void __init kirkwood_uart0_init(void)
-{
-	orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
-			 IRQ_KIRKWOOD_UART_0, tclk);
-}
-
-
-/*****************************************************************************
- * UART1
- ****************************************************************************/
-void __init kirkwood_uart1_init(void)
-{
-	orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
-			 IRQ_KIRKWOOD_UART_1, tclk);
-}
-
-/*****************************************************************************
- * Cryptographic Engines and Security Accelerator (CESA)
- ****************************************************************************/
-void __init kirkwood_crypto_init(void)
-{
-	orion_crypto_init(CRYPTO_PHYS_BASE, KIRKWOOD_SRAM_PHYS_BASE,
-			  KIRKWOOD_SRAM_SIZE, IRQ_KIRKWOOD_CRYPTO);
-}
-
-
-/*****************************************************************************
- * XOR0
- ****************************************************************************/
-void __init kirkwood_xor0_init(void)
-{
-	orion_xor0_init(XOR0_PHYS_BASE, XOR0_HIGH_PHYS_BASE,
-			IRQ_KIRKWOOD_XOR_00, IRQ_KIRKWOOD_XOR_01);
-}
-
-
-/*****************************************************************************
- * XOR1
- ****************************************************************************/
-void __init kirkwood_xor1_init(void)
-{
-	orion_xor1_init(XOR1_PHYS_BASE, XOR1_HIGH_PHYS_BASE,
-			IRQ_KIRKWOOD_XOR_10, IRQ_KIRKWOOD_XOR_11);
-}
-
-
-/*****************************************************************************
- * Watchdog
- ****************************************************************************/
-void __init kirkwood_wdt_init(void)
-{
-	orion_wdt_init();
-}
-
-/*****************************************************************************
- * CPU idle
- ****************************************************************************/
-static struct resource kirkwood_cpuidle_resource[] = {
-	{
-		.flags	= IORESOURCE_MEM,
-		.start	= DDR_OPERATION_BASE,
-		.end	= DDR_OPERATION_BASE + 3,
-	},
-};
-
-static struct platform_device kirkwood_cpuidle = {
-	.name		= "kirkwood_cpuidle",
-	.id		= -1,
-	.resource	= kirkwood_cpuidle_resource,
-	.num_resources	= 1,
-};
-
-void __init kirkwood_cpuidle_init(void)
-{
-	platform_device_register(&kirkwood_cpuidle);
-}
-
-/*****************************************************************************
- * Time handling
- ****************************************************************************/
-void __init kirkwood_init_early(void)
-{
-	orion_time_set_base(TIMER_VIRT_BASE);
-}
-
-int kirkwood_tclk;
-
-static int __init kirkwood_find_tclk(void)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-
-	if (dev == MV88F6281_DEV_ID || dev == MV88F6282_DEV_ID)
-		if (((readl(SAMPLE_AT_RESET) >> 21) & 1) == 0)
-			return 200000000;
-
-	return 166666667;
-}
-
-void __init kirkwood_timer_init(void)
-{
-	kirkwood_tclk = kirkwood_find_tclk();
-
-	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
-			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
-
-/*****************************************************************************
- * Audio
- ****************************************************************************/
-static struct resource kirkwood_audio_resources[] = {
-	[0] = {
-		.start  = AUDIO_PHYS_BASE,
-		.end    = AUDIO_PHYS_BASE + SZ_16K - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = IRQ_KIRKWOOD_I2S,
-		.end    = IRQ_KIRKWOOD_I2S,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct kirkwood_asoc_platform_data kirkwood_audio_data = {
-	.burst       = 128,
-};
-
-static struct platform_device kirkwood_audio_device = {
-	.name		= "mvebu-audio",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(kirkwood_audio_resources),
-	.resource	= kirkwood_audio_resources,
-	.dev		= {
-		.platform_data	= &kirkwood_audio_data,
-	},
-};
-
-void __init kirkwood_audio_init(void)
-{
-	platform_device_register(&kirkwood_audio_device);
-}
-
-/*****************************************************************************
- * CPU Frequency
- ****************************************************************************/
-static struct resource kirkwood_cpufreq_resources[] = {
-	[0] = {
-		.start  = CPU_CONTROL_PHYS,
-		.end    = CPU_CONTROL_PHYS + 3,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device kirkwood_cpufreq_device = {
-	.name		= "kirkwood-cpufreq",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(kirkwood_cpufreq_resources),
-	.resource	= kirkwood_cpufreq_resources,
-};
-
-void __init kirkwood_cpufreq_init(void)
-{
-	platform_device_register(&kirkwood_cpufreq_device);
-}
-
-/*****************************************************************************
- * General
- ****************************************************************************/
-/*
- * Identify device ID and revision.
- */
-char * __init kirkwood_id(void)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-
-	if (dev == MV88F6281_DEV_ID) {
-		if (rev == MV88F6281_REV_Z0)
-			return "MV88F6281-Z0";
-		else if (rev == MV88F6281_REV_A0)
-			return "MV88F6281-A0";
-		else if (rev == MV88F6281_REV_A1)
-			return "MV88F6281-A1";
-		else
-			return "MV88F6281-Rev-Unsupported";
-	} else if (dev == MV88F6192_DEV_ID) {
-		if (rev == MV88F6192_REV_Z0)
-			return "MV88F6192-Z0";
-		else if (rev == MV88F6192_REV_A0)
-			return "MV88F6192-A0";
-		else if (rev == MV88F6192_REV_A1)
-			return "MV88F6192-A1";
-		else
-			return "MV88F6192-Rev-Unsupported";
-	} else if (dev == MV88F6180_DEV_ID) {
-		if (rev == MV88F6180_REV_A0)
-			return "MV88F6180-Rev-A0";
-		else if (rev == MV88F6180_REV_A1)
-			return "MV88F6180-Rev-A1";
-		else
-			return "MV88F6180-Rev-Unsupported";
-	} else if (dev == MV88F6282_DEV_ID) {
-		if (rev == MV88F6282_REV_A0)
-			return "MV88F6282-Rev-A0";
-		else if (rev == MV88F6282_REV_A1)
-			return "MV88F6282-Rev-A1";
-		else
-			return "MV88F6282-Rev-Unsupported";
-	} else {
-		return "Device-Unknown";
-	}
-}
-
-void __init kirkwood_setup_wins(void)
-{
-	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_NAND_TARGET,
-				    KIRKWOOD_MBUS_NAND_ATTR,
-				    KIRKWOOD_NAND_MEM_PHYS_BASE,
-				    KIRKWOOD_NAND_MEM_SIZE);
-	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_SRAM_TARGET,
-				    KIRKWOOD_MBUS_SRAM_ATTR,
-				    KIRKWOOD_SRAM_PHYS_BASE,
-				    KIRKWOOD_SRAM_SIZE);
-}
-
-void __init kirkwood_l2_init(void)
-{
-#ifdef CONFIG_CACHE_FEROCEON_L2
-#ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
-	writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG);
-	feroceon_l2_init(1);
-#else
-	writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG);
-	feroceon_l2_init(0);
-#endif
-#endif
-}
-
-void __init kirkwood_init(void)
-{
-	pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
-
-	/*
-	 * Disable propagation of mbus errors to the CPU local bus,
-	 * as this causes mbus errors (which can occur for example
-	 * for PCI aborts) to throw CPU aborts, which we're not set
-	 * up to deal with.
-	 */
-	writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
-
-	BUG_ON(mvebu_mbus_init("marvell,kirkwood-mbus",
-			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-			DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ));
-
-	kirkwood_setup_wins();
-
-	kirkwood_l2_init();
-
-	/* Setup root of clk tree */
-	kirkwood_clk_init();
-
-	/* internal devices that every board has */
-	kirkwood_rtc_init();
-	kirkwood_wdt_init();
-	kirkwood_xor0_init();
-	kirkwood_xor1_init();
-	kirkwood_crypto_init();
-
-	kirkwood_pm_init();
-	kirkwood_cpuidle_init();
-#ifdef CONFIG_KEXEC
-	kexec_reinit = kirkwood_enable_pcie;
-#endif
-}
-
-void kirkwood_restart(enum reboot_mode mode, const char *cmd)
-{
-	/*
-	 * Enable soft reset to assert RSTOUTn.
-	 */
-	writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
-	/*
-	 * Assert soft reset.
-	 */
-	writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
-	while (1)
-		;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/common.h
- *
- * Core functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ARCH_KIRKWOOD_COMMON_H
-#define __ARCH_KIRKWOOD_COMMON_H
-
-#include <linux/reboot.h>
-
-struct dsa_platform_data;
-struct mv643xx_eth_platform_data;
-struct mv_sata_platform_data;
-struct mvsdio_platform_data;
-struct mtd_partition;
-struct mtd_info;
-struct kirkwood_asoc_platform_data;
-
-#define KW_PCIE0	(1 << 0)
-#define KW_PCIE1	(1 << 1)
-
-/*
- * Basic Kirkwood init functions used early by machine-setup.
- */
-void kirkwood_map_io(void);
-void kirkwood_init(void);
-void kirkwood_init_early(void);
-void kirkwood_init_irq(void);
-
-void kirkwood_setup_wins(void);
-
-void kirkwood_enable_pcie(void);
-void kirkwood_pcie_id(u32 *dev, u32 *rev);
-
-void kirkwood_ehci_init(void);
-void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data);
-void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data);
-void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
-void kirkwood_pcie_init(unsigned int portmask);
-void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
-void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
-void kirkwood_spi_init(void);
-void kirkwood_i2c_init(void);
-void kirkwood_uart0_init(void);
-void kirkwood_uart1_init(void);
-void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
-void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
-			    int (*dev_ready)(struct mtd_info *));
-void kirkwood_audio_init(void);
-void kirkwood_cpuidle_init(void);
-void kirkwood_cpufreq_init(void);
-
-void kirkwood_restart(enum reboot_mode, const char *);
-void kirkwood_clk_init(void);
-
-/* early init functions not converted to fdt yet */
-char *kirkwood_id(void);
-void kirkwood_l2_init(void);
-void kirkwood_wdt_init(void);
-void kirkwood_xor0_init(void);
-void kirkwood_xor1_init(void);
-void kirkwood_crypto_init(void);
-
-extern int kirkwood_tclk;
-extern void kirkwood_timer_init(void);
-
-#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,231 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/d2net_v2-setup.c
- *
- * LaCie d2 Network Space v2 Board Setup
- *
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/leds-kirkwood-ns2.h>
-#include "common.h"
-#include "mpp.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data d2net_v2_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-
-static struct mv_sata_platform_data d2net_v2_sata_data = {
-	.n_ports	= 2,
-};
-
-/*****************************************************************************
- * GPIO keys
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_PUSH_BUTTON          34
-#define D2NET_V2_GPIO_POWER_SWITCH_ON      13
-#define D2NET_V2_GPIO_POWER_SWITCH_OFF     15
-
-#define D2NET_V2_SWITCH_POWER_ON           0x1
-#define D2NET_V2_SWITCH_POWER_OFF          0x2
-
-static struct gpio_keys_button d2net_v2_buttons[] = {
-	[0] = {
-		.type           = EV_SW,
-		.code           = D2NET_V2_SWITCH_POWER_ON,
-		.gpio           = D2NET_V2_GPIO_POWER_SWITCH_ON,
-		.desc           = "Back power switch (on|auto)",
-		.active_low     = 0,
-	},
-	[1] = {
-		.type           = EV_SW,
-		.code           = D2NET_V2_SWITCH_POWER_OFF,
-		.gpio           = D2NET_V2_GPIO_POWER_SWITCH_OFF,
-		.desc           = "Back power switch (auto|off)",
-		.active_low     = 0,
-	},
-	[2] = {
-		.code           = KEY_POWER,
-		.gpio           = D2NET_V2_GPIO_PUSH_BUTTON,
-		.desc           = "Front Push Button",
-		.active_low     = 1,
-	},
-};
-
-static struct gpio_keys_platform_data d2net_v2_button_data = {
-	.buttons	= d2net_v2_buttons,
-	.nbuttons	= ARRAY_SIZE(d2net_v2_buttons),
-};
-
-static struct platform_device d2net_v2_gpio_buttons = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &d2net_v2_button_data,
-	},
-};
-
-/*****************************************************************************
- * GPIO LEDs
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_RED_LED		12
-
-static struct gpio_led d2net_v2_gpio_led_pins[] = {
-	{
-		.name	= "d2net_v2:red:fail",
-		.gpio	= D2NET_V2_GPIO_RED_LED,
-	},
-};
-
-static struct gpio_led_platform_data d2net_v2_gpio_leds_data = {
-	.num_leds	= ARRAY_SIZE(d2net_v2_gpio_led_pins),
-	.leds		= d2net_v2_gpio_led_pins,
-};
-
-static struct platform_device d2net_v2_gpio_leds = {
-	.name		= "leds-gpio",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &d2net_v2_gpio_leds_data,
-	},
-};
-
-/*****************************************************************************
- * Dual-GPIO CPLD LEDs
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_BLUE_LED_SLOW	29
-#define D2NET_V2_GPIO_BLUE_LED_CMD	30
-
-static struct ns2_led d2net_v2_led_pins[] = {
-	{
-		.name	= "d2net_v2:blue:sata",
-		.cmd	= D2NET_V2_GPIO_BLUE_LED_CMD,
-		.slow	= D2NET_V2_GPIO_BLUE_LED_SLOW,
-	},
-};
-
-static struct ns2_led_platform_data d2net_v2_leds_data = {
-	.num_leds	= ARRAY_SIZE(d2net_v2_led_pins),
-	.leds		= d2net_v2_led_pins,
-};
-
-static struct platform_device d2net_v2_leds = {
-	.name		= "leds-ns2",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &d2net_v2_leds_data,
-	},
-};
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-
-static unsigned int d2net_v2_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP6_SYSRST_OUTn,
-	MPP7_GPO,		/* Request power-off */
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP12_GPO,		/* Red led */
-	MPP13_GPIO,		/* Rear power switch (on|auto) */
-	MPP14_GPIO,		/* USB fuse */
-	MPP15_GPIO,		/* Rear power switch (auto|off) */
-	MPP16_GPIO,		/* SATA 0 power */
-	MPP21_SATA0_ACTn,
-	MPP24_GPIO,		/* USB mode select */
-	MPP26_GPIO,		/* USB device vbus */
-	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* Blue led (slow register) */
-	MPP30_GPIO,		/* Blue led (command register) */
-	MPP34_GPIO,		/* Power button (1 = Released, 0 = Pushed) */
-	MPP35_GPIO,		/* Inhibit power-off */
-	0
-};
-
-#define D2NET_V2_GPIO_POWER_OFF		7
-
-static void d2net_v2_power_off(void)
-{
-	gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1);
-}
-
-static void __init d2net_v2_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(d2net_v2_mpp_config);
-
-	lacie_v2_hdd_power_init(1);
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&d2net_v2_ge00_data);
-	kirkwood_sata_init(&d2net_v2_sata_data);
-	kirkwood_uart0_init();
-	lacie_v2_register_flash();
-	lacie_v2_register_i2c_devices();
-
-	platform_device_register(&d2net_v2_leds);
-	platform_device_register(&d2net_v2_gpio_leds);
-	platform_device_register(&d2net_v2_gpio_buttons);
-
-	if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 &&
-	    gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = d2net_v2_power_off;
-	else
-		pr_err("d2net_v2: failed to configure power-off GPIO\n");
-}
-
-MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
-	.atag_offset	= 0x100,
-	.init_machine	= d2net_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/bridge-regs.h
- *
- * Mbus-L to Mbus Bridge Registers
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_BRIDGE_REGS_H
-#define __ASM_ARCH_BRIDGE_REGS_H
-
-#include <mach/kirkwood.h>
-
-#define CPU_CONFIG		(BRIDGE_VIRT_BASE + 0x0100)
-#define CPU_CONFIG_PHYS		(BRIDGE_PHYS_BASE + 0x0100)
-#define CPU_CONFIG_ERROR_PROP	0x00000004
-
-#define CPU_CONTROL		(BRIDGE_VIRT_BASE + 0x0104)
-#define CPU_CONTROL_PHYS	(BRIDGE_PHYS_BASE + 0x0104)
-#define CPU_RESET		0x00000002
-
-#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
-#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
-#define SOFT_RESET_OUT_EN	0x00000004
-
-#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
-#define SOFT_RESET		0x00000001
-
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE + 0x0110)
-
-#define BRIDGE_INT_TIMER1_CLR	(~0x0004)
-
-#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0200)
-#define IRQ_CAUSE_LOW_OFF	0x0000
-#define IRQ_MASK_LOW_OFF	0x0004
-#define IRQ_CAUSE_HIGH_OFF	0x0010
-#define IRQ_MASK_HIGH_OFF	0x0014
-
-#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0300)
-#define TIMER_PHYS_BASE		(BRIDGE_PHYS_BASE + 0x0300)
-
-#define L2_CONFIG_REG		(BRIDGE_VIRT_BASE + 0x0128)
-#define L2_WRITETHROUGH		0x00000010
-
-#define CLOCK_GATING_CTRL	(BRIDGE_VIRT_BASE + 0x11c)
-#define CGC_BIT_GE0		(0)
-#define CGC_BIT_PEX0		(2)
-#define CGC_BIT_USB0		(3)
-#define CGC_BIT_SDIO		(4)
-#define CGC_BIT_TSU		(5)
-#define CGC_BIT_DUNIT		(6)
-#define CGC_BIT_RUNIT		(7)
-#define CGC_BIT_XOR0		(8)
-#define CGC_BIT_AUDIO		(9)
-#define CGC_BIT_SATA0		(14)
-#define CGC_BIT_SATA1		(15)
-#define CGC_BIT_XOR1		(16)
-#define CGC_BIT_CRYPTO		(17)
-#define CGC_BIT_PEX1		(18)
-#define CGC_BIT_GE1		(19)
-#define CGC_BIT_TDM		(20)
-#define CGC_GE0			(1 << 0)
-#define CGC_PEX0		(1 << 2)
-#define CGC_USB0		(1 << 3)
-#define CGC_SDIO		(1 << 4)
-#define CGC_TSU			(1 << 5)
-#define CGC_DUNIT		(1 << 6)
-#define CGC_RUNIT		(1 << 7)
-#define CGC_XOR0		(1 << 8)
-#define CGC_AUDIO		(1 << 9)
-#define CGC_POWERSAVE           (1 << 11)
-#define CGC_SATA0		(1 << 14)
-#define CGC_SATA1		(1 << 15)
-#define CGC_XOR1		(1 << 16)
-#define CGC_CRYPTO		(1 << 17)
-#define CGC_PEX1		(1 << 18)
-#define CGC_GE1			(1 << 19)
-#define CGC_TDM			(1 << 20)
-#define CGC_RESERVED		(0x6 << 21)
-
-#define MEMORY_PM_CTRL		(BRIDGE_VIRT_BASE + 0x118)
-#define MEMORY_PM_CTRL_PHYS	(BRIDGE_PHYS_BASE + 0x118)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/entry-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/entry-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/entry-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Marvell Kirkwood platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/bridge-regs.h>
-
-	.macro  get_irqnr_preamble, base, tmp
-	ldr	\base, =IRQ_VIRT_BASE
-	.endm
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-	@ check low interrupts
-	ldr	\irqstat, [\base, #IRQ_CAUSE_LOW_OFF]
-	ldr	\tmp, [\base, #IRQ_MASK_LOW_OFF]
-	mov	\irqnr, #31
-	ands	\irqstat, \irqstat, \tmp
-	bne	1001f
-
-	@ if no low interrupts set, check high interrupts
-	ldr	\irqstat, [\base, #IRQ_CAUSE_HIGH_OFF]
-	ldr	\tmp, [\base, #IRQ_MASK_HIGH_OFF]
-	mov	\irqnr, #63
-	ands	\irqstat, \irqstat, \tmp
-
-	@ find first active interrupt source
-1001:	clzne	\irqstat, \irqstat
-	subne	\irqnr, \irqnr, \irqstat
-	.endm
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/hardware.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include "kirkwood.h"
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/irqs.h
- *
- * IRQ definitions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-/*
- * Low Interrupt Controller
- */
-#define IRQ_KIRKWOOD_HIGH_SUM	0
-#define IRQ_KIRKWOOD_BRIDGE	1
-#define IRQ_KIRKWOOD_HOST2CPU	2
-#define IRQ_KIRKWOOD_CPU2HOST	3
-#define IRQ_KIRKWOOD_XOR_00	5
-#define IRQ_KIRKWOOD_XOR_01	6
-#define IRQ_KIRKWOOD_XOR_10	7
-#define IRQ_KIRKWOOD_XOR_11	8
-#define IRQ_KIRKWOOD_PCIE	9
-#define IRQ_KIRKWOOD_PCIE1	10
-#define IRQ_KIRKWOOD_GE00_SUM	11
-#define IRQ_KIRKWOOD_GE01_SUM	15
-#define IRQ_KIRKWOOD_USB	19
-#define IRQ_KIRKWOOD_SATA	21
-#define IRQ_KIRKWOOD_CRYPTO	22
-#define IRQ_KIRKWOOD_SPI	23
-#define IRQ_KIRKWOOD_I2S	24
-#define IRQ_KIRKWOOD_TS_0	26
-#define IRQ_KIRKWOOD_SDIO	28
-#define IRQ_KIRKWOOD_TWSI	29
-#define IRQ_KIRKWOOD_AVB	30
-#define IRQ_KIRKWOOD_TDMI	31
-
-/*
- * High Interrupt Controller
- */
-#define IRQ_KIRKWOOD_UART_0	33
-#define IRQ_KIRKWOOD_UART_1	34
-#define IRQ_KIRKWOOD_GPIO_LOW_0_7	35
-#define IRQ_KIRKWOOD_GPIO_LOW_8_15	36
-#define IRQ_KIRKWOOD_GPIO_LOW_16_23	37
-#define IRQ_KIRKWOOD_GPIO_LOW_24_31	38
-#define IRQ_KIRKWOOD_GPIO_HIGH_0_7	39
-#define IRQ_KIRKWOOD_GPIO_HIGH_8_15	40
-#define IRQ_KIRKWOOD_GPIO_HIGH_16_23	41
-#define IRQ_KIRKWOOD_GE00_ERR	46
-#define IRQ_KIRKWOOD_GE01_ERR	47
-#define IRQ_KIRKWOOD_RTC        53
-
-/*
- * KIRKWOOD General Purpose Pins
- */
-#define IRQ_KIRKWOOD_GPIO_START	64
-#define NR_GPIO_IRQS		50
-
-#define NR_IRQS			(IRQ_KIRKWOOD_GPIO_START + NR_GPIO_IRQS)
-
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/kirkwood.h
- *
- * Generic definitions for Marvell Kirkwood SoC flavors:
- *  88F6180, 88F6192 and 88F6281.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_KIRKWOOD_H
-#define __ASM_ARCH_KIRKWOOD_H
-
-/*
- * Marvell Kirkwood address maps.
- *
- * phys
- * e0000000	PCIe #0 Memory space
- * e8000000	PCIe #1 Memory space
- * f1000000	on-chip peripheral registers
- * f2000000	PCIe #0 I/O space
- * f3000000	PCIe #1 I/O space
- * f4000000	NAND controller address window
- * f5000000	Security Accelerator SRAM
- *
- * virt		phys		size
- * fed00000	f1000000	1M	on-chip peripheral registers
- * fee00000	f2000000	1M	PCIe #0 I/O space
- * fef00000	f3000000	1M	PCIe #1 I/O space
- */
-
-#define KIRKWOOD_SRAM_PHYS_BASE		0xf5000000
-#define KIRKWOOD_SRAM_SIZE		SZ_2K
-
-#define KIRKWOOD_NAND_MEM_PHYS_BASE	0xf4000000
-#define KIRKWOOD_NAND_MEM_SIZE		SZ_1K
-
-#define KIRKWOOD_PCIE1_IO_PHYS_BASE	0xf3000000
-#define KIRKWOOD_PCIE1_IO_BUS_BASE	0x00010000
-#define KIRKWOOD_PCIE1_IO_SIZE		SZ_64K
-
-#define KIRKWOOD_PCIE_IO_PHYS_BASE	0xf2000000
-#define KIRKWOOD_PCIE_IO_BUS_BASE	0x00000000
-#define KIRKWOOD_PCIE_IO_SIZE		SZ_64K
-
-#define KIRKWOOD_REGS_PHYS_BASE		0xf1000000
-#define KIRKWOOD_REGS_VIRT_BASE		IOMEM(0xfed00000)
-#define KIRKWOOD_REGS_SIZE		SZ_1M
-
-#define KIRKWOOD_PCIE_MEM_PHYS_BASE	0xe0000000
-#define KIRKWOOD_PCIE_MEM_BUS_BASE	0xe0000000
-#define KIRKWOOD_PCIE_MEM_SIZE		SZ_128M
-
-#define KIRKWOOD_PCIE1_MEM_PHYS_BASE	0xe8000000
-#define KIRKWOOD_PCIE1_MEM_BUS_BASE	0xe8000000
-#define KIRKWOOD_PCIE1_MEM_SIZE		SZ_128M
-
-/*
- * Register Map
- */
-#define DDR_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x00000)
-#define DDR_PHYS_BASE           (KIRKWOOD_REGS_PHYS_BASE + 0x00000)
-#define  DDR_WINDOW_CPU_BASE    (DDR_PHYS_BASE + 0x1500)
-#define  DDR_WINDOW_CPU_SZ      (0x20)
-#define DDR_OPERATION_BASE	(DDR_PHYS_BASE + 0x1418)
-
-#define DEV_BUS_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x10000)
-#define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x10000)
-#define  SAMPLE_AT_RESET	(DEV_BUS_VIRT_BASE + 0x0030)
-#define  DEVICE_ID		(DEV_BUS_VIRT_BASE + 0x0034)
-#define  GPIO_LOW_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x0100)
-#define  GPIO_HIGH_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x0140)
-#define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE + 0x0300)
-#define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE + 0x0600)
-#define  I2C_PHYS_BASE		(DEV_BUS_PHYS_BASE + 0x1000)
-#define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE + 0x2000)
-#define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2000)
-#define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE + 0x2100)
-#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2100)
-
-#define BRIDGE_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x20000)
-#define BRIDGE_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x20000)
-#define  BRIDGE_WINS_BASE       (BRIDGE_PHYS_BASE)
-#define  BRIDGE_WINS_SZ         (0x80)
-
-#define CRYPTO_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x30000)
-
-#define PCIE_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x40000)
-#define PCIE_LINK_CTRL		(PCIE_VIRT_BASE + 0x70)
-#define PCIE_STATUS		(PCIE_VIRT_BASE + 0x1a04)
-#define PCIE1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x44000)
-#define PCIE1_LINK_CTRL		(PCIE1_VIRT_BASE + 0x70)
-#define PCIE1_STATUS		(PCIE1_VIRT_BASE + 0x1a04)
-
-#define USB_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x50000)
-
-#define XOR0_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x60800)
-#define XOR0_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x60800)
-#define XOR1_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x60900)
-#define XOR1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x60900)
-#define XOR0_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x60A00)
-#define XOR0_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x60A00)
-#define XOR1_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x60B00)
-#define XOR1_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x60B00)
-
-#define GE00_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x70000)
-#define GE01_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x74000)
-
-#define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x80000)
-#define SATA_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x80000)
-#define SATA0_IF_CTRL		(SATA_VIRT_BASE + 0x2050)
-#define SATA0_PHY_MODE_2	(SATA_VIRT_BASE + 0x2330)
-#define SATA1_IF_CTRL		(SATA_VIRT_BASE + 0x4050)
-#define SATA1_PHY_MODE_2	(SATA_VIRT_BASE + 0x4330)
-
-#define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x90000)
-
-#define AUDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0xA0000)
-#define AUDIO_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0xA0000)
-
-/*
- * Supported devices and revisions.
- */
-#define MV88F6281_DEV_ID	0x6281
-#define MV88F6281_REV_Z0	0
-#define MV88F6281_REV_A0	2
-#define MV88F6281_REV_A1	3
-
-#define MV88F6192_DEV_ID	0x6192
-#define MV88F6192_REV_Z0	0
-#define MV88F6192_REV_A0	2
-#define MV88F6192_REV_A1	3
-
-#define MV88F6180_DEV_ID	0x6180
-#define MV88F6180_REV_A0	2
-#define MV88F6180_REV_A1	3
-
-#define MV88F6282_DEV_ID	0x6282
-#define MV88F6282_REV_A0	0
-#define MV88F6282_REV_A1	1
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/uncompress.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/uncompress.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/include/mach/uncompress.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/uncompress.h
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/serial_reg.h>
-#include <mach/kirkwood.h>
-
-#define SERIAL_BASE	((unsigned char *)UART0_PHYS_BASE)
-
-static void putc(const char c)
-{
-	unsigned char *base = SERIAL_BASE;
-	int i;
-
-	for (i = 0; i < 0x1000; i++) {
-		if (base[UART_LSR << 2] & UART_LSR_THRE)
-			break;
-		barrier();
-	}
-
-	base[UART_TX << 2] = c;
-}
-
-static void flush(void)
-{
-	unsigned char *base = SERIAL_BASE;
-	unsigned char mask;
-	int i;
-
-	mask = UART_LSR_TEMT | UART_LSR_THRE;
-
-	for (i = 0; i < 0x1000; i++) {
-		if ((base[UART_LSR << 2] & mask) == mask)
-			break;
-		barrier();
-	}
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/irq.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/irq.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/irq.c
- *
- * Kirkwood IRQ handling.
- *
- * 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 <asm/exception.h>
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include <plat/orion-gpio.h>
-#include <plat/irq.h>
-#include "common.h"
-
-static int __initdata gpio0_irqs[4] = {
-	IRQ_KIRKWOOD_GPIO_LOW_0_7,
-	IRQ_KIRKWOOD_GPIO_LOW_8_15,
-	IRQ_KIRKWOOD_GPIO_LOW_16_23,
-	IRQ_KIRKWOOD_GPIO_LOW_24_31,
-};
-
-static int __initdata gpio1_irqs[4] = {
-	IRQ_KIRKWOOD_GPIO_HIGH_0_7,
-	IRQ_KIRKWOOD_GPIO_HIGH_8_15,
-	IRQ_KIRKWOOD_GPIO_HIGH_16_23,
-	0,
-};
-
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-/*
- * Compiling with both non-DT and DT support enabled, will
- * break asm irq handler used by non-DT boards. Therefore,
- * we provide a C-style irq handler even for non-DT boards,
- * if MULTI_IRQ_HANDLER is set.
- */
-
-static void __iomem *kirkwood_irq_base = IRQ_VIRT_BASE;
-
-asmlinkage void
-__exception_irq_entry kirkwood_legacy_handle_irq(struct pt_regs *regs)
-{
-	u32 stat;
-
-	stat = readl_relaxed(kirkwood_irq_base + IRQ_CAUSE_LOW_OFF);
-	stat &= readl_relaxed(kirkwood_irq_base + IRQ_MASK_LOW_OFF);
-	if (stat) {
-		unsigned int hwirq = __fls(stat);
-		handle_IRQ(hwirq, regs);
-		return;
-	}
-	stat = readl_relaxed(kirkwood_irq_base + IRQ_CAUSE_HIGH_OFF);
-	stat &= readl_relaxed(kirkwood_irq_base + IRQ_MASK_HIGH_OFF);
-	if (stat) {
-		unsigned int hwirq = 32 + __fls(stat);
-		handle_IRQ(hwirq, regs);
-		return;
-	}
-}
-#endif
-
-void __init kirkwood_init_irq(void)
-{
-	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
-	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
-
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-	set_handle_irq(kirkwood_legacy_handle_irq);
-#endif
-
-	/*
-	 * Initialize gpiolib for GPIOs 0-49.
-	 */
-	orion_gpio_init(NULL, 0, 32, GPIO_LOW_VIRT_BASE, 0,
-			IRQ_KIRKWOOD_GPIO_START, gpio0_irqs);
-	orion_gpio_init(NULL, 32, 18, GPIO_HIGH_VIRT_BASE, 0,
-			IRQ_KIRKWOOD_GPIO_START + 32, gpio1_irqs);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-if ARCH_KIRKWOOD
-
-menu "Marvell Kirkwood Implementations"
-
-config KIRKWOOD_LEGACY
-	bool
-
-config MACH_D2NET_V2
-	bool "LaCie d2 Network v2 NAS Board"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie d2 Network v2 NAS.
-
-config MACH_NET2BIG_V2
-	bool "LaCie 2Big Network v2 NAS Board"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie 2Big Network v2 NAS.
-
-config MACH_NET5BIG_V2
-	bool "LaCie 5Big Network v2 NAS Board"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  LaCie 5Big Network v2 NAS.
-
-config MACH_OPENRD
-	select KIRKWOOD_LEGACY
-        bool
-
-config MACH_OPENRD_BASE
-	bool "Marvell OpenRD Base Board"
-	select MACH_OPENRD
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell OpenRD Base Board.
-
-config MACH_OPENRD_CLIENT
-	bool "Marvell OpenRD Client Board"
-	select MACH_OPENRD
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell OpenRD Client Board.
-
-config MACH_OPENRD_ULTIMATE
-	bool "Marvell OpenRD Ultimate Board"
-	select MACH_OPENRD
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell OpenRD Ultimate Board.
-
-config MACH_RD88F6192_NAS
-	bool "Marvell RD-88F6192-NAS Reference Board"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell RD-88F6192-NAS Reference Board.
-
-config MACH_RD88F6281
-	bool "Marvell RD-88F6281 Reference Board"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell RD-88F6281 Reference Board.
-
-config MACH_T5325
-	bool "HP t5325 Thin Client"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  HP t5325 Thin Client.
-
-config MACH_TS219
-	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
-	  TS-219P+ Turbo NAS devices.
-
-config MACH_TS41X
-	bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
-	select KIRKWOOD_LEGACY
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
-	  NAS devices.
-
-comment "Device tree entries"
-
-config ARCH_KIRKWOOD_DT
-	bool "Marvell Kirkwood Flattened Device Tree"
-	select KIRKWOOD_CLK
-	select OF_IRQ
-	select ORION_IRQCHIP
-	select ORION_TIMER
-	select POWER_SUPPLY
-	select POWER_RESET
-	select POWER_RESET_GPIO
-	select REGULATOR
-	select REGULATOR_FIXED_VOLTAGE
-	select USE_OF
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell Kirkwood using flattened device tree.
-
-endmenu
-
-endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/lacie_v2-common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/lacie_v2-common.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/lacie_v2-common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/lacie_v2-common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/lacie_v2-common.c
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
-#include <linux/gpio.h>
-#include <asm/mach/time.h>
-#include <mach/kirkwood.h>
-#include <mach/irqs.h>
-#include <plat/time.h>
-#include "common.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition lacie_v2_flash_parts[] = {
-	{
-		.name = "u-boot",
-		.size = MTDPART_SIZ_FULL,
-		.offset = 0,
-		.mask_flags = MTD_WRITEABLE, /* force read-only */
-	},
-};
-
-static const struct flash_platform_data lacie_v2_flash = {
-	.type		= "mx25l4005a",
-	.name		= "spi_flash",
-	.parts		= lacie_v2_flash_parts,
-	.nr_parts	= ARRAY_SIZE(lacie_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &lacie_v2_flash,
-		.irq		= -1,
-		.max_speed_hz	= 20000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
-
-void __init lacie_v2_register_flash(void)
-{
-	spi_register_board_info(lacie_v2_spi_slave_info,
-				ARRAY_SIZE(lacie_v2_spi_slave_info));
-	kirkwood_spi_init();
-}
-
-/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
-	.byte_len	= SZ_4K / 8,
-	.page_size	= 16,
-};
-
-/*
- * i2c addr | chip         | description
- * 0x50     | HT24LC04     | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata lacie_v2_i2c_info[] = {
-	{
-		I2C_BOARD_INFO("24c04", 0x50),
-		.platform_data  = &at24c04,
-	}
-};
-
-void __init lacie_v2_register_i2c_devices(void)
-{
-	kirkwood_i2c_init();
-	i2c_register_board_info(0, lacie_v2_i2c_info,
-				ARRAY_SIZE(lacie_v2_i2c_info));
-}
-
-/*****************************************************************************
- * Hard Disk power
- ****************************************************************************/
-
-static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
-
-void __init lacie_v2_hdd_power_init(int hdd_num)
-{
-	int i;
-	int err;
-
-	/* Power up all hard disks. */
-	for (i = 0; i < hdd_num; i++) {
-		err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL);
-		if (err == 0) {
-			err = gpio_direction_output(
-					lacie_v2_gpio_hdd_power[i], 1);
-			/* Free the HDD power GPIOs. This allow user-space to
-			 * configure them via the gpiolib sysfs interface. */
-			gpio_free(lacie_v2_gpio_hdd_power[i]);
-		}
-		if (err)
-			pr_err("Failed to power up HDD%d\n", i + 1);
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/lacie_v2-common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/lacie_v2-common.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/lacie_v2-common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/lacie_v2-common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/lacie_v2-common.h
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
-#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
-
-void lacie_v2_register_flash(void);
-void lacie_v2_register_i2c_devices(void);
-void lacie_v2_hdd_power_init(int hdd_num);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-obj-$(CONFIG_KIRKWOOD_LEGACY)	+= irq.o mpp.o common.o pcie.o
-obj-$(CONFIG_PM)		+= pm.o
-
-obj-$(CONFIG_MACH_D2NET_V2)		+= d2net_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NET2BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_OPENRD)		+= openrd-setup.o
-obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
-obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
-obj-$(CONFIG_MACH_T5325)		+= t5325-setup.o
-obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
-obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
-
-obj-$(CONFIG_ARCH_KIRKWOOD_DT)		+= board-dt.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Makefile.boot linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Makefile.boot
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/Makefile.boot	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-   zreladdr-y	+= 0x00008000
-params_phys-y	:= 0x00000100
-initrd_phys-y	:= 0x00800000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/mpp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/mpp.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/mpp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/mpp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/mpp.c
- *
- * MPP functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <plat/mpp.h>
-#include "common.h"
-#include "mpp.h"
-
-static unsigned int __init kirkwood_variant(void)
-{
-	u32 dev, rev;
-
-	kirkwood_pcie_id(&dev, &rev);
-
-	if (dev == MV88F6281_DEV_ID && rev >= MV88F6281_REV_A0)
-		return MPP_F6281_MASK;
-	if (dev == MV88F6282_DEV_ID)
-		return MPP_F6282_MASK;
-	if (dev == MV88F6192_DEV_ID && rev >= MV88F6192_REV_A0)
-		return MPP_F6192_MASK;
-	if (dev == MV88F6180_DEV_ID)
-		return MPP_F6180_MASK;
-
-	pr_err("MPP setup: unknown kirkwood variant (dev %#x rev %#x)\n",
-	       dev, rev);
-	return 0;
-}
-
-void __init kirkwood_mpp_conf(unsigned int *mpp_list)
-{
-	orion_mpp_conf(mpp_list, kirkwood_variant(),
-		       MPP_MAX, DEV_BUS_VIRT_BASE);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/mpp.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/mpp.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/mpp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/mpp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,348 +0,0 @@
-/*
- * linux/arch/arm/mach-kirkwood/mpp.h -- Multi Purpose Pins
- *
- * Copyright 2009: Marvell Technology Group Ltd.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __KIRKWOOD_MPP_H
-#define __KIRKWOOD_MPP_H
-
-#define MPP(_num, _sel, _in, _out, _F6180, _F6190, _F6192, _F6281, _F6282) ( \
-	/* MPP number */		((_num) & 0xff) | \
-	/* MPP select value */		(((_sel) & 0xf) << 8) | \
-	/* may be input signal */	((!!(_in)) << 12) | \
-	/* may be output signal */	((!!(_out)) << 13) | \
-	/* available on F6180 */	((!!(_F6180)) << 14) | \
-	/* available on F6190 */	((!!(_F6190)) << 15) | \
-	/* available on F6192 */	((!!(_F6192)) << 16) | \
-	/* available on F6281 */	((!!(_F6281)) << 17) | \
-	/* available on F6282 */	((!!(_F6282)) << 18))
-
-				/*   num sel  i  o  6180 6190 6192 6281 6282 */
-
-#define MPP_F6180_MASK		MPP(  0, 0x0, 0, 0, 1,   0,   0,   0,   0 )
-#define MPP_F6190_MASK		MPP(  0, 0x0, 0, 0, 0,   1,   0,   0,   0 )
-#define MPP_F6192_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   1,   0,   0 )
-#define MPP_F6281_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   0,   1,   0 )
-#define MPP_F6282_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP0_GPIO		MPP(  0, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP0_NF_IO2		MPP(  0, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP0_SPI_SCn		MPP(  0, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP1_GPO		MPP(  1, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP1_NF_IO3		MPP(  1, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP1_SPI_MOSI		MPP(  1, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP2_GPO		MPP(  2, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP2_NF_IO4		MPP(  2, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP2_SPI_SCK		MPP(  2, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP3_GPO		MPP(  3, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP3_NF_IO5		MPP(  3, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP3_SPI_MISO		MPP(  3, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP4_GPIO		MPP(  4, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP4_NF_IO6		MPP(  4, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP4_UART0_RXD		MPP(  4, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP4_SATA1_ACTn		MPP(  4, 0x5, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP4_LCD_VGA_HSYNC	MPP(  4, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP4_PTP_CLK		MPP(  4, 0xd, 0, 0, 1,   1,   1,   1,   0 )
-
-#define MPP5_GPO		MPP(  5, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP5_NF_IO7		MPP(  5, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP5_UART0_TXD		MPP(  5, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP5_PTP_TRIG_GEN	MPP(  5, 0x4, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP5_SATA0_ACTn		MPP(  5, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP5_LCD_VGA_VSYNC	MPP(  5, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP6_SYSRST_OUTn	MPP(  6, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP6_SPI_MOSI		MPP(  6, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP6_PTP_TRIG_GEN	MPP(  6, 0x3, 0, 0, 1,   1,   1,   1,   0 )
-
-#define MPP7_GPO		MPP(  7, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP7_PEX_RST_OUTn	MPP(  7, 0x1, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP7_SPI_SCn		MPP(  7, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP7_PTP_TRIG_GEN	MPP(  7, 0x3, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP7_LCD_PWM		MPP(  7, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP8_GPIO		MPP(  8, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP8_TW0_SDA		MPP(  8, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP8_UART0_RTS		MPP(  8, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP8_UART1_RTS		MPP(  8, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP8_MII0_RXERR		MPP(  8, 0x4, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP8_SATA1_PRESENTn	MPP(  8, 0x5, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP8_PTP_CLK		MPP(  8, 0xc, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP8_MII0_COL		MPP(  8, 0xd, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP9_GPIO		MPP(  9, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP9_TW0_SCK		MPP(  9, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP9_UART0_CTS		MPP(  9, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP9_UART1_CTS		MPP(  9, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP9_SATA0_PRESENTn	MPP(  9, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP9_PTP_EVENT_REQ	MPP(  9, 0xc, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP9_MII0_CRS		MPP(  9, 0xd, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP10_GPO		MPP( 10, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP10_SPI_SCK		MPP( 10, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP10_UART0_TXD		MPP( 10, 0X3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP10_SATA1_ACTn	MPP( 10, 0x5, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP10_PTP_TRIG_GEN	MPP( 10, 0xc, 0, 0, 1,   1,   1,   1,   0 )
-
-#define MPP11_GPIO		MPP( 11, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP11_SPI_MISO		MPP( 11, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP11_UART0_RXD		MPP( 11, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP11_PTP_EVENT_REQ	MPP( 11, 0x4, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP11_PTP_TRIG_GEN	MPP( 11, 0xc, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP11_PTP_CLK		MPP( 11, 0xd, 0, 0, 1,   1,   1,   1,   0 )
-#define MPP11_SATA0_ACTn	MPP( 11, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-
-#define MPP12_GPO		MPP( 12, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP12_GPIO		MPP( 12, 0x0, 1, 1, 0,   0,   0,   1,   0 )
-#define MPP12_SD_CLK		MPP( 12, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP12_AU_SPDIF0		MPP( 12, 0xa, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP12_SPI_MOSI		MPP( 12, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP12_TW1_SDA		MPP( 12, 0xd, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP13_GPIO		MPP( 13, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP13_SD_CMD		MPP( 13, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP13_UART1_TXD		MPP( 13, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP13_AU_SPDIFRMCLK	MPP( 13, 0xa, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP13_LCDPWM		MPP( 13, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP14_GPIO		MPP( 14, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP14_SD_D0		MPP( 14, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP14_UART1_RXD		MPP( 14, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP14_SATA1_PRESENTn	MPP( 14, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP14_AU_SPDIFI		MPP( 14, 0xa, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP14_AU_I2SDI		MPP( 14, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP14_MII0_COL		MPP( 14, 0xd, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP15_GPIO		MPP( 15, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP15_SD_D1		MPP( 15, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP15_UART0_RTS		MPP( 15, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP15_UART1_TXD		MPP( 15, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP15_SATA0_ACTn	MPP( 15, 0x4, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP15_SPI_CSn		MPP( 15, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP16_GPIO		MPP( 16, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP16_SD_D2		MPP( 16, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP16_UART0_CTS		MPP( 16, 0x2, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP16_UART1_RXD		MPP( 16, 0x3, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP16_SATA1_ACTn	MPP( 16, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP16_LCD_EXT_REF_CLK	MPP( 16, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP16_MII0_CRS		MPP( 16, 0xd, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP17_GPIO		MPP( 17, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP17_SD_D3		MPP( 17, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP17_SATA0_PRESENTn	MPP( 17, 0x4, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP17_SATA1_ACTn	MPP( 17, 0xa, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP17_TW1_SCK		MPP( 17, 0xd, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP18_GPO		MPP( 18, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP18_NF_IO0		MPP( 18, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-#define MPP18_PEX0_CLKREQ	MPP( 18, 0x2, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP19_GPO		MPP( 19, 0x0, 0, 1, 1,   1,   1,   1,   1 )
-#define MPP19_NF_IO1		MPP( 19, 0x1, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP20_GPIO		MPP( 20, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP20_TSMP0		MPP( 20, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP20_TDM_CH0_TX_QL	MPP( 20, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP20_GE1_TXD0		MPP( 20, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP20_AU_SPDIFI		MPP( 20, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP20_SATA1_ACTn	MPP( 20, 0x5, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP20_LCD_D0		MPP( 20, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP21_GPIO		MPP( 21, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP21_TSMP1		MPP( 21, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP21_TDM_CH0_RX_QL	MPP( 21, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP21_GE1_TXD1		MPP( 21, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP21_AU_SPDIFO		MPP( 21, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP21_SATA0_ACTn	MPP( 21, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP21_LCD_D1		MPP( 21, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP22_GPIO		MPP( 22, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP22_TSMP2		MPP( 22, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP22_TDM_CH2_TX_QL	MPP( 22, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP22_GE1_TXD2		MPP( 22, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP22_AU_SPDIFRMKCLK	MPP( 22, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP22_SATA1_PRESENTn	MPP( 22, 0x5, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP22_LCD_D2		MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP23_GPIO		MPP( 23, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP23_TSMP3		MPP( 23, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP23_TDM_CH2_RX_QL	MPP( 23, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP23_GE1_TXD3		MPP( 23, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP23_AU_I2SBCLK	MPP( 23, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP23_SATA0_PRESENTn	MPP( 23, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP23_LCD_D3		MPP( 23, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP24_GPIO		MPP( 24, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP24_TSMP4		MPP( 24, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP24_TDM_SPI_CS0	MPP( 24, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP24_GE1_RXD0		MPP( 24, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP24_AU_I2SDO		MPP( 24, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP24_LCD_D4		MPP( 24, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP25_GPIO		MPP( 25, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP25_TSMP5		MPP( 25, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP25_TDM_SPI_SCK	MPP( 25, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP25_GE1_RXD1		MPP( 25, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP25_AU_I2SLRCLK	MPP( 25, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP25_LCD_D5		MPP( 25, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP26_GPIO		MPP( 26, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP26_TSMP6		MPP( 26, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP26_TDM_SPI_MISO	MPP( 26, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP26_GE1_RXD2		MPP( 26, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP26_AU_I2SMCLK	MPP( 26, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP26_LCD_D6		MPP( 26, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP27_GPIO		MPP( 27, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP27_TSMP7		MPP( 27, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP27_TDM_SPI_MOSI	MPP( 27, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP27_GE1_RXD3		MPP( 27, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP27_AU_I2SDI		MPP( 27, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP27_LCD_D7		MPP( 27, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP28_GPIO		MPP( 28, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP28_TSMP8		MPP( 28, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP28_TDM_CODEC_INTn	MPP( 28, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP28_GE1_COL		MPP( 28, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP28_AU_EXTCLK		MPP( 28, 0x4, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP28_LCD_D8		MPP( 28, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP29_GPIO		MPP( 29, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP29_TSMP9		MPP( 29, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP29_TDM_CODEC_RSTn	MPP( 29, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP29_GE1_TCLK		MPP( 29, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP29_LCD_D9		MPP( 29, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP30_GPIO		MPP( 30, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP30_TSMP10		MPP( 30, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP30_TDM_PCLK		MPP( 30, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP30_GE1_RXCTL		MPP( 30, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP30_LCD_D10		MPP( 30, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP31_GPIO		MPP( 31, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP31_TSMP11		MPP( 31, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP31_TDM_FS		MPP( 31, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP31_GE1_RXCLK		MPP( 31, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP31_LCD_D11		MPP( 31, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP32_GPIO		MPP( 32, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP32_TSMP12		MPP( 32, 0x1, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP32_TDM_DRX		MPP( 32, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP32_GE1_TCLKOUT	MPP( 32, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP32_LCD_D12		MPP( 32, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP33_GPO		MPP( 33, 0x0, 0, 1, 0,   1,   1,   1,   1 )
-#define MPP33_TDM_DTX		MPP( 33, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP33_GE1_TXCTL		MPP( 33, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP33_LCD_D13		MPP( 33, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP34_GPIO		MPP( 34, 0x0, 1, 1, 0,   1,   1,   1,   1 )
-#define MPP34_TDM_SPI_CS1	MPP( 34, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP34_GE1_TXEN		MPP( 34, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP34_SATA1_ACTn	MPP( 34, 0x5, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP34_LCD_D14		MPP( 34, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP35_GPIO		MPP( 35, 0x0, 1, 1, 1,   1,   1,   1,   1 )
-#define MPP35_TDM_CH0_TX_QL	MPP( 35, 0x2, 0, 0, 0,   0,   1,   1,   1 )
-#define MPP35_GE1_RXERR		MPP( 35, 0x3, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP35_SATA0_ACTn	MPP( 35, 0x5, 0, 0, 0,   1,   1,   1,   1 )
-#define MPP35_LCD_D15		MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP35_MII0_RXERR	MPP( 35, 0xc, 0, 0, 1,   1,   1,   1,   1 )
-
-#define MPP36_GPIO		MPP( 36, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP36_TSMP0		MPP( 36, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP36_TDM_SPI_CS1	MPP( 36, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP36_AU_SPDIFI		MPP( 36, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP36_TW1_SDA		MPP( 36, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP37_GPIO		MPP( 37, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP37_TSMP1		MPP( 37, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP37_TDM_CH2_TX_QL	MPP( 37, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP37_AU_SPDIFO		MPP( 37, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP37_TW1_SCK		MPP( 37, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP38_GPIO		MPP( 38, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP38_TSMP2		MPP( 38, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP38_TDM_CH2_RX_QL	MPP( 38, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP38_AU_SPDIFRMLCLK	MPP( 38, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP38_LCD_D18		MPP( 38, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP39_GPIO		MPP( 39, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP39_TSMP3		MPP( 39, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP39_TDM_SPI_CS0	MPP( 39, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP39_AU_I2SBCLK	MPP( 39, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP39_LCD_D19		MPP( 39, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP40_GPIO		MPP( 40, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP40_TSMP4		MPP( 40, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP40_TDM_SPI_SCK	MPP( 40, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP40_AU_I2SDO		MPP( 40, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP40_LCD_D20		MPP( 40, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP41_GPIO		MPP( 41, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP41_TSMP5		MPP( 41, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP41_TDM_SPI_MISO	MPP( 41, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP41_AU_I2SLRCLK	MPP( 41, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP41_LCD_D21		MPP( 41, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP42_GPIO		MPP( 42, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP42_TSMP6		MPP( 42, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP42_TDM_SPI_MOSI	MPP( 42, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP42_AU_I2SMCLK	MPP( 42, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP42_LCD_D22		MPP( 42, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP43_GPIO		MPP( 43, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP43_TSMP7		MPP( 43, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP43_TDM_CODEC_INTn	MPP( 43, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP43_AU_I2SDI		MPP( 43, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP43_LCD_D23		MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP44_GPIO		MPP( 44, 0x0, 1, 1, 1,   0,   0,   1,   1 )
-#define MPP44_TSMP8		MPP( 44, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP44_TDM_CODEC_RSTn	MPP( 44, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP44_AU_EXTCLK		MPP( 44, 0x4, 0, 0, 1,   0,   0,   1,   1 )
-#define MPP44_LCD_CLK		MPP( 44, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP45_GPIO		MPP( 45, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP45_TSMP9		MPP( 45, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP45_TDM_PCLK		MPP( 45, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP245_LCD_E		MPP( 45, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP46_GPIO		MPP( 46, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP46_TSMP10		MPP( 46, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP46_TDM_FS		MPP( 46, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP46_LCD_HSYNC		MPP( 46, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP47_GPIO		MPP( 47, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP47_TSMP11		MPP( 47, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP47_TDM_DRX		MPP( 47, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP47_LCD_VSYNC		MPP( 47, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP48_GPIO		MPP( 48, 0x0, 1, 1, 0,   0,   0,   1,   1 )
-#define MPP48_TSMP12		MPP( 48, 0x1, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP48_TDM_DTX		MPP( 48, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP48_LCD_D16		MPP( 22, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP49_GPIO		MPP( 49, 0x0, 1, 1, 0,   0,   0,   1,   0 )
-#define MPP49_GPO		MPP( 49, 0x0, 0, 1, 0,   0,   0,   0,   1 )
-#define MPP49_TSMP9		MPP( 49, 0x1, 0, 0, 0,   0,   0,   1,   0 )
-#define MPP49_TDM_CH0_RX_QL	MPP( 49, 0x2, 0, 0, 0,   0,   0,   1,   1 )
-#define MPP49_PTP_CLK		MPP( 49, 0x5, 0, 0, 0,   0,   0,   1,   0 )
-#define MPP49_PEX0_CLKREQ	MPP( 49, 0xa, 0, 0, 0,   0,   0,   0,   1 )
-#define MPP49_LCD_D17		MPP( 49, 0xb, 0, 0, 0,   0,   0,   0,   1 )
-
-#define MPP_MAX			49
-
-void kirkwood_mpp_conf(unsigned int *mpp_list);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,422 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/netxbig_v2-setup.c
- *
- * LaCie 2Big and 5Big Network v2 board setup
- *
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/leds-kirkwood-netxbig.h>
-#include "common.h"
-#include "mpp.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data netxbig_v2_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-
-static struct mv_sata_platform_data netxbig_v2_sata_data = {
-	.n_ports	= 2,
-};
-
-/*****************************************************************************
- * GPIO keys
- ****************************************************************************/
-
-#define NETXBIG_V2_GPIO_SWITCH_POWER_ON		13
-#define NETXBIG_V2_GPIO_SWITCH_POWER_OFF	15
-#define NETXBIG_V2_GPIO_FUNC_BUTTON		34
-
-#define NETXBIG_V2_SWITCH_POWER_ON		0x1
-#define NETXBIG_V2_SWITCH_POWER_OFF		0x2
-
-static struct gpio_keys_button netxbig_v2_buttons[] = {
-	[0] = {
-		.type           = EV_SW,
-		.code           = NETXBIG_V2_SWITCH_POWER_ON,
-		.gpio           = NETXBIG_V2_GPIO_SWITCH_POWER_ON,
-		.desc           = "Back power switch (on|auto)",
-		.active_low     = 1,
-	},
-	[1] = {
-		.type           = EV_SW,
-		.code           = NETXBIG_V2_SWITCH_POWER_OFF,
-		.gpio           = NETXBIG_V2_GPIO_SWITCH_POWER_OFF,
-		.desc           = "Back power switch (auto|off)",
-		.active_low     = 1,
-	},
-	[2] = {
-		.code		= KEY_OPTION,
-		.gpio		= NETXBIG_V2_GPIO_FUNC_BUTTON,
-		.desc		= "Function button",
-		.active_low	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data netxbig_v2_button_data = {
-	.buttons	= netxbig_v2_buttons,
-	.nbuttons	= ARRAY_SIZE(netxbig_v2_buttons),
-};
-
-static struct platform_device netxbig_v2_gpio_buttons = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &netxbig_v2_button_data,
-	},
-};
-
-/*****************************************************************************
- * GPIO extension LEDs
- ****************************************************************************/
-
-/*
- * The LEDs are controlled by a CPLD and can be configured through a GPIO
- * extension bus:
- *
- * - address register : bit [0-2] -> GPIO [47-49]
- * - data register    : bit [0-2] -> GPIO [44-46]
- * - enable register  : GPIO 29
- */
-
-static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
-static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
-
-static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
-	.addr		= netxbig_v2_gpio_ext_addr,
-	.num_addr	= ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
-	.data		= netxbig_v2_gpio_ext_data,
-	.num_data	= ARRAY_SIZE(netxbig_v2_gpio_ext_data),
-	.enable		= 29,
-};
-
-/*
- * Address register selection:
- *
- * addr | register
- * ----------------------------
- *   0  | front LED
- *   1  | front LED brightness
- *   2  | SATA LED brightness
- *   3  | SATA0 LED
- *   4  | SATA1 LED
- *   5  | SATA2 LED
- *   6  | SATA3 LED
- *   7  | SATA4 LED
- *
- * Data register configuration:
- *
- * data | LED brightness
- * -------------------------------------------------
- *   0  | min (off)
- *   -  | -
- *   7  | max
- *
- * data | front LED mode
- * -------------------------------------------------
- *   0  | fix off
- *   1  | fix blue on
- *   2  | fix red on
- *   3  | blink blue on=1 sec and blue off=1 sec
- *   4  | blink red on=1 sec and red off=1 sec
- *   5  | blink blue on=2.5 sec and red on=0.5 sec
- *   6  | blink blue on=1 sec and red on=1 sec
- *   7  | blink blue on=0.5 sec and blue off=2.5 sec
- *
- * data | SATA LED mode
- * -------------------------------------------------
- *   0  | fix off
- *   1  | SATA activity blink
- *   2  | fix red on
- *   3  | blink blue on=1 sec and blue off=1 sec
- *   4  | blink red on=1 sec and red off=1 sec
- *   5  | blink blue on=2.5 sec and red on=0.5 sec
- *   6  | blink blue on=1 sec and red on=1 sec
- *   7  | fix blue on
- */
-
-static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
-	[NETXBIG_LED_OFF]	= 0,
-	[NETXBIG_LED_ON]	= 2,
-	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
-	[NETXBIG_LED_TIMER1]	= 4,
-	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
-};
-
-static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
-	[NETXBIG_LED_OFF]	= 0,
-	[NETXBIG_LED_ON]	= 1,
-	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
-	[NETXBIG_LED_TIMER1]	= 3,
-	[NETXBIG_LED_TIMER2]	= 7,
-};
-
-static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
-	[NETXBIG_LED_OFF]	= 0,
-	[NETXBIG_LED_ON]	= 7,
-	[NETXBIG_LED_SATA]	= 1,
-	[NETXBIG_LED_TIMER1]	= 3,
-	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
-};
-
-static struct netxbig_led_timer netxbig_v2_led_timer[] = {
-	[0] = {
-		.delay_on	= 500,
-		.delay_off	= 500,
-		.mode		= NETXBIG_LED_TIMER1,
-	},
-	[1] = {
-		.delay_on	= 500,
-		.delay_off	= 1000,
-		.mode		= NETXBIG_LED_TIMER2,
-	},
-};
-
-#define NETXBIG_LED(_name, maddr, mval, baddr)			\
-	{ .name		= _name,				\
-	  .mode_addr	= maddr,				\
-	  .mode_val	= mval,					\
-	  .bright_addr	= baddr }
-
-static struct netxbig_led net2big_v2_leds_ctrl[] = {
-	NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
-	NETXBIG_LED("net2big-v2:red:power",  0, netxbig_v2_red_mled,       1),
-	NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net2big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
-	NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net2big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
-};
-
-static struct netxbig_led_platform_data net2big_v2_leds_data = {
-	.gpio_ext	= &netxbig_v2_gpio_ext,
-	.timer		= netxbig_v2_led_timer,
-	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
-	.leds		= net2big_v2_leds_ctrl,
-	.num_leds	= ARRAY_SIZE(net2big_v2_leds_ctrl),
-};
-
-static struct netxbig_led net5big_v2_leds_ctrl[] = {
-	NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
-	NETXBIG_LED("net5big-v2:red:power",  0, netxbig_v2_red_mled,       1),
-	NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net5big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
-	NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net5big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
-	NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net5big-v2:red:sata2",  5, netxbig_v2_red_mled,       2),
-	NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net5big-v2:red:sata3",  6, netxbig_v2_red_mled,       2),
-	NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
-	NETXBIG_LED("net5big-v2:red:sata5",  7, netxbig_v2_red_mled,       2),
-};
-
-static struct netxbig_led_platform_data net5big_v2_leds_data = {
-	.gpio_ext	= &netxbig_v2_gpio_ext,
-	.timer		= netxbig_v2_led_timer,
-	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
-	.leds		= net5big_v2_leds_ctrl,
-	.num_leds	= ARRAY_SIZE(net5big_v2_leds_ctrl),
-};
-
-static struct platform_device netxbig_v2_leds = {
-	.name		= "leds-netxbig",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &net2big_v2_leds_data,
-	},
-};
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-
-static unsigned int net2big_v2_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP6_SYSRST_OUTn,
-	MPP7_GPO,		/* Request power-off */
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP13_GPIO,		/* Rear power switch (on|auto) */
-	MPP14_GPIO,		/* USB fuse alarm */
-	MPP15_GPIO,		/* Rear power switch (auto|off) */
-	MPP16_GPIO,		/* SATA HDD1 power */
-	MPP17_GPIO,		/* SATA HDD2 power */
-	MPP20_SATA1_ACTn,
-	MPP21_SATA0_ACTn,
-	MPP24_GPIO,		/* USB mode select */
-	MPP26_GPIO,		/* USB device vbus */
-	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* GPIO extension ALE */
-	MPP34_GPIO,		/* Rear Push button */
-	MPP35_GPIO,		/* Inhibit switch power-off */
-	MPP36_GPIO,		/* SATA HDD1 presence */
-	MPP37_GPIO,		/* SATA HDD2 presence */
-	MPP40_GPIO,		/* eSATA presence */
-	MPP44_GPIO,		/* GPIO extension (data 0) */
-	MPP45_GPIO,		/* GPIO extension (data 1) */
-	MPP46_GPIO,		/* GPIO extension (data 2) */
-	MPP47_GPIO,		/* GPIO extension (addr 0) */
-	MPP48_GPIO,		/* GPIO extension (addr 1) */
-	MPP49_GPIO,		/* GPIO extension (addr 2) */
-	0
-};
-
-static unsigned int net5big_v2_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP6_SYSRST_OUTn,
-	MPP7_GPO,		/* Request power-off */
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP13_GPIO,		/* Rear power switch (on|auto) */
-	MPP14_GPIO,		/* USB fuse alarm */
-	MPP15_GPIO,		/* Rear power switch (auto|off) */
-	MPP16_GPIO,		/* SATA HDD1 power */
-	MPP17_GPIO,		/* SATA HDD2 power */
-	MPP20_GE1_TXD0,
-	MPP21_GE1_TXD1,
-	MPP22_GE1_TXD2,
-	MPP23_GE1_TXD3,
-	MPP24_GE1_RXD0,
-	MPP25_GE1_RXD1,
-	MPP26_GE1_RXD2,
-	MPP27_GE1_RXD3,
-	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* GPIO extension ALE */
-	MPP30_GE1_RXCTL,
-	MPP31_GE1_RXCLK,
-	MPP32_GE1_TCLKOUT,
-	MPP33_GE1_TXCTL,
-	MPP34_GPIO,		/* Rear Push button */
-	MPP35_GPIO,		/* Inhibit switch power-off */
-	MPP36_GPIO,		/* SATA HDD1 presence */
-	MPP37_GPIO,		/* SATA HDD2 presence */
-	MPP38_GPIO,		/* SATA HDD3 presence */
-	MPP39_GPIO,		/* SATA HDD4 presence */
-	MPP40_GPIO,		/* SATA HDD5 presence */
-	MPP41_GPIO,		/* SATA HDD3 power */
-	MPP42_GPIO,		/* SATA HDD4 power */
-	MPP43_GPIO,		/* SATA HDD5 power */
-	MPP44_GPIO,		/* GPIO extension (data 0) */
-	MPP45_GPIO,		/* GPIO extension (data 1) */
-	MPP46_GPIO,		/* GPIO extension (data 2) */
-	MPP47_GPIO,		/* GPIO extension (addr 0) */
-	MPP48_GPIO,		/* GPIO extension (addr 1) */
-	MPP49_GPIO,		/* GPIO extension (addr 2) */
-	0
-};
-
-#define NETXBIG_V2_GPIO_POWER_OFF		7
-
-static void netxbig_v2_power_off(void)
-{
-	gpio_set_value(NETXBIG_V2_GPIO_POWER_OFF, 1);
-}
-
-static void __init netxbig_v2_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	if (machine_is_net2big_v2())
-		kirkwood_mpp_conf(net2big_v2_mpp_config);
-	else
-		kirkwood_mpp_conf(net5big_v2_mpp_config);
-
-	if (machine_is_net2big_v2())
-		lacie_v2_hdd_power_init(2);
-	else
-		lacie_v2_hdd_power_init(5);
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&netxbig_v2_ge00_data);
-	if (machine_is_net5big_v2())
-		kirkwood_ge01_init(&netxbig_v2_ge01_data);
-	kirkwood_sata_init(&netxbig_v2_sata_data);
-	kirkwood_uart0_init();
-	lacie_v2_register_flash();
-	lacie_v2_register_i2c_devices();
-
-	if (machine_is_net5big_v2())
-		netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
-	platform_device_register(&netxbig_v2_leds);
-	platform_device_register(&netxbig_v2_gpio_buttons);
-
-	if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 &&
-	    gpio_direction_output(NETXBIG_V2_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = netxbig_v2_power_off;
-	else
-		pr_err("netxbig_v2: failed to configure power-off GPIO\n");
-}
-
-#ifdef CONFIG_MACH_NET2BIG_V2
-MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-	.atag_offset	= 0x100,
-	.init_machine	= netxbig_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_NET5BIG_V2
-MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-	.atag_offset	= 0x100,
-	.init_machine	= netxbig_v2_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/openrd-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/openrd-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/openrd-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/openrd-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,255 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/openrd-setup.c
- *
- * Marvell OpenRD (Base|Client|Ultimate) Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition openrd_nand_parts[] = {
-	{
-		.name		= "u-boot",
-		.offset		= 0,
-		.size		= SZ_1M,
-		.mask_flags	= MTD_WRITEABLE
-	}, {
-		.name		= "uImage",
-		.offset		= MTDPART_OFS_NXTBLK,
-		.size		= SZ_4M
-	}, {
-		.name		= "root",
-		.offset		= MTDPART_OFS_NXTBLK,
-		.size		= MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data openrd_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data openrd_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(24),
-};
-
-static struct mv_sata_platform_data openrd_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct mvsdio_platform_data openrd_mvsdio_data = {
-	.gpio_card_detect = 29,	/* MPP29 used as SD card detect */
-	.gpio_write_protect = -1,
-};
-
-static unsigned int openrd_mpp_config[] __initdata = {
-	MPP12_SD_CLK,
-	MPP13_SD_CMD,
-	MPP14_SD_D0,
-	MPP15_SD_D1,
-	MPP16_SD_D2,
-	MPP17_SD_D3,
-	MPP28_GPIO,
-	MPP29_GPIO,
-	MPP34_GPIO,
-	0
-};
-
-/* Configure MPP for UART1 */
-static unsigned int openrd_uart1_mpp_config[] __initdata = {
-	MPP13_UART1_TXD,
-	MPP14_UART1_RXD,
-	0
-};
-
-static struct i2c_board_info i2c_board_info[] __initdata = {
-	{
-		I2C_BOARD_INFO("cs42l51", 0x4a),
-	},
-};
-
-static struct platform_device openrd_client_audio_device = {
-	.name		= "openrd-client-audio",
-	.id		= -1,
-};
-
-static int __initdata uart1;
-
-static int __init sd_uart_selection(char *str)
-{
-	uart1 = -EINVAL;
-
-	/* Default is SD. Change if required, for UART */
-	if (!str)
-		return 0;
-
-	if (!strncmp(str, "232", 3)) {
-		uart1 = 232;
-	} else if (!strncmp(str, "485", 3)) {
-		/* OpenRD-Base doesn't have RS485. Treat is as an
-		 * unknown argument & just have default setting -
-		 * which is SD */
-		if (machine_is_openrd_base()) {
-			uart1 = -ENODEV;
-			return 1;
-		}
-
-		uart1 = 485;
-	}
-	return 1;
-}
-/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */
-__setup("kw_openrd_init_uart1=", sd_uart_selection);
-
-static int __init uart1_mpp_config(void)
-{
-	kirkwood_mpp_conf(openrd_uart1_mpp_config);
-
-	if (gpio_request(34, "SD_UART1_SEL")) {
-		pr_err("GPIO request 34 failed for SD/UART1 selection\n");
-		return -EIO;
-	}
-
-	if (gpio_request(28, "RS232_RS485_SEL")) {
-		pr_err("GPIO request 28 failed for RS232/RS485 selection\n");
-		gpio_free(34);
-		return -EIO;
-	}
-
-	/* Select UART1
-	 * Pin # 34: 0 => UART1, 1 => SD */
-	gpio_direction_output(34, 0);
-
-	/* Select RS232 OR RS485
-	 * Pin # 28: 0 => RS232, 1 => RS485 */
-	if (uart1 == 232)
-		gpio_direction_output(28, 0);
-	else
-		gpio_direction_output(28, 1);
-
-	gpio_free(34);
-	gpio_free(28);
-
-	return 0;
-}
-
-static void __init openrd_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(openrd_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_nand_init(openrd_nand_parts, ARRAY_SIZE(openrd_nand_parts),
-			   25);
-
-	kirkwood_ehci_init();
-
-	if (machine_is_openrd_ultimate()) {
-		openrd_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
-		openrd_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
-	}
-
-	kirkwood_ge00_init(&openrd_ge00_data);
-	if (!machine_is_openrd_base())
-		kirkwood_ge01_init(&openrd_ge01_data);
-
-	kirkwood_sata_init(&openrd_sata_data);
-
-	kirkwood_i2c_init();
-
-	if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
-		platform_device_register(&openrd_client_audio_device);
-		i2c_register_board_info(0, i2c_board_info,
-			ARRAY_SIZE(i2c_board_info));
-		kirkwood_audio_init();
-	}
-
-	if (uart1 <= 0) {
-		if (uart1 < 0)
-			pr_err("Invalid kernel parameter to select UART1. Defaulting to SD. ERROR CODE: %d\n",
-			       uart1);
-
-		/* Select SD
-		 * Pin # 34: 0 => UART1, 1 => SD */
-		if (gpio_request(34, "SD_UART1_SEL")) {
-			pr_err("GPIO request 34 failed for SD/UART1 selection\n");
-		} else {
-
-			gpio_direction_output(34, 1);
-			gpio_free(34);
-			kirkwood_sdio_init(&openrd_mvsdio_data);
-		}
-	} else {
-		if (!uart1_mpp_config())
-			kirkwood_uart1_init();
-	}
-}
-
-static int __init openrd_pci_init(void)
-{
-	if (machine_is_openrd_base() ||
-	    machine_is_openrd_client() ||
-	    machine_is_openrd_ultimate())
-		kirkwood_pcie_init(KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(openrd_pci_init);
-
-#ifdef CONFIG_MACH_OPENRD_BASE
-MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
-	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= openrd_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_OPENRD_CLIENT
-MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
-	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= openrd_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_OPENRD_ULTIMATE
-MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
-	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= openrd_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pcie.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pcie.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pcie.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pcie.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,296 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/pcie.c
- *
- * PCIe functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/mbus.h>
-#include <video/vga.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <plat/pcie.h>
-#include <mach/bridge-regs.h>
-#include "common.h"
-
-/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
-#define KIRKWOOD_MBUS_PCIE0_MEM_TARGET    0x4
-#define KIRKWOOD_MBUS_PCIE0_MEM_ATTR      0xe8
-#define KIRKWOOD_MBUS_PCIE0_IO_TARGET     0x4
-#define KIRKWOOD_MBUS_PCIE0_IO_ATTR       0xe0
-#define KIRKWOOD_MBUS_PCIE1_MEM_TARGET    0x4
-#define KIRKWOOD_MBUS_PCIE1_MEM_ATTR      0xd8
-#define KIRKWOOD_MBUS_PCIE1_IO_TARGET     0x4
-#define KIRKWOOD_MBUS_PCIE1_IO_ATTR       0xd0
-
-static void kirkwood_enable_pcie_clk(const char *port)
-{
-	struct clk *clk;
-
-	clk = clk_get_sys("pcie", port);
-	if (IS_ERR(clk)) {
-		pr_err("PCIE clock %s missing\n", port);
-		return;
-	}
-	clk_prepare_enable(clk);
-	clk_put(clk);
-}
-
-/* This function is called very early in the boot when probing the
-   hardware to determine what we actually are, and what rate tclk is
-   ticking at. Hence calling kirkwood_enable_pcie_clk() is not
-   possible since the clk tree has not been created yet. */
-void kirkwood_enable_pcie(void)
-{
-	u32 curr = readl(CLOCK_GATING_CTRL);
-	if (!(curr & CGC_PEX0))
-		writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
-}
-
-void kirkwood_pcie_id(u32 *dev, u32 *rev)
-{
-	kirkwood_enable_pcie();
-	*dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
-	*rev = orion_pcie_rev(PCIE_VIRT_BASE);
-}
-
-struct pcie_port {
-	u8			root_bus_nr;
-	void __iomem		*base;
-	spinlock_t		conf_lock;
-	int			irq;
-	struct resource		res;
-};
-
-static int pcie_port_map[2];
-static int num_pcie_ports;
-
-static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
-{
-	/*
-	 * Don't go out when trying to access --
-	 * 1. nonexisting device on local bus
-	 * 2. where there's no device connected (no link)
-	 */
-	if (bus == pp->root_bus_nr && dev == 0)
-		return 1;
-
-	if (!orion_pcie_link_up(pp->base))
-		return 0;
-
-	if (bus == pp->root_bus_nr && dev != 1)
-		return 0;
-
-	return 1;
-}
-
-
-/*
- * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
- * and then reading the PCIE_CONF_DATA register. Need to make sure these
- * transactions are atomic.
- */
-
-static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
-			int size, u32 *val)
-{
-	struct pci_sys_data *sys = bus->sysdata;
-	struct pcie_port *pp = sys->private_data;
-	unsigned long flags;
-	int ret;
-
-	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	spin_lock_irqsave(&pp->conf_lock, flags);
-	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
-	spin_unlock_irqrestore(&pp->conf_lock, flags);
-
-	return ret;
-}
-
-static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
-			int where, int size, u32 val)
-{
-	struct pci_sys_data *sys = bus->sysdata;
-	struct pcie_port *pp = sys->private_data;
-	unsigned long flags;
-	int ret;
-
-	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	spin_lock_irqsave(&pp->conf_lock, flags);
-	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
-	spin_unlock_irqrestore(&pp->conf_lock, flags);
-
-	return ret;
-}
-
-static struct pci_ops pcie_ops = {
-	.read = pcie_rd_conf,
-	.write = pcie_wr_conf,
-};
-
-static void __init pcie0_ioresources_init(struct pcie_port *pp)
-{
-	pp->base = PCIE_VIRT_BASE;
-	pp->irq	= IRQ_KIRKWOOD_PCIE;
-
-	/*
-	 * IORESOURCE_MEM
-	 */
-	pp->res.name = "PCIe 0 MEM";
-	pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
-	pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
-	pp->res.flags = IORESOURCE_MEM;
-}
-
-static void __init pcie1_ioresources_init(struct pcie_port *pp)
-{
-	pp->base = PCIE1_VIRT_BASE;
-	pp->irq	= IRQ_KIRKWOOD_PCIE1;
-
-	/*
-	 * IORESOURCE_MEM
-	 */
-	pp->res.name = "PCIe 1 MEM";
-	pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
-	pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
-	pp->res.flags = IORESOURCE_MEM;
-}
-
-static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-	int index;
-
-	if (nr >= num_pcie_ports)
-		return 0;
-
-	index = pcie_port_map[nr];
-	pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
-
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp)
-		panic("PCIe: failed to allocate pcie_port data");
-	sys->private_data = pp;
-	pp->root_bus_nr = sys->busnr;
-	spin_lock_init(&pp->conf_lock);
-
-	switch (index) {
-	case 0:
-		kirkwood_enable_pcie_clk("0");
-		pcie0_ioresources_init(pp);
-		pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
-		break;
-	case 1:
-		kirkwood_enable_pcie_clk("1");
-		pcie1_ioresources_init(pp);
-		pci_ioremap_io(SZ_64K * sys->busnr,
-			       KIRKWOOD_PCIE1_IO_PHYS_BASE);
-		break;
-	default:
-		panic("PCIe setup: invalid controller %d", index);
-	}
-
-	if (request_resource(&iomem_resource, &pp->res))
-		panic("Request PCIe%d Memory resource failed\n", index);
-
-	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
-
-	/*
-	 * Generic PCIe unit setup.
-	 */
-	orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
-
-	orion_pcie_setup(pp->base);
-
-	return 1;
-}
-
-/*
- * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
- * is operating as a root complex this needs to be switched to
- * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
- * the device. Decoding setup is handled by the orion code.
- */
-static void rc_pci_fixup(struct pci_dev *dev)
-{
-	if (dev->bus->parent == NULL && dev->devfn == 0) {
-		int i;
-
-		dev->class &= 0xff;
-		dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
-		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-			dev->resource[i].start = 0;
-			dev->resource[i].end   = 0;
-			dev->resource[i].flags = 0;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
-
-static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
-	u8 pin)
-{
-	struct pci_sys_data *sys = dev->sysdata;
-	struct pcie_port *pp = sys->private_data;
-
-	return pp->irq;
-}
-
-static struct hw_pci kirkwood_pci __initdata = {
-	.setup		= kirkwood_pcie_setup,
-	.map_irq	= kirkwood_pcie_map_irq,
-	.ops            = &pcie_ops,
-};
-
-static void __init add_pcie_port(int index, void __iomem *base)
-{
-	pcie_port_map[num_pcie_ports++] = index;
-	pr_info("Kirkwood PCIe port %d: link %s\n", index,
-		orion_pcie_link_up(base) ? "up" : "down");
-}
-
-void __init kirkwood_pcie_init(unsigned int portmask)
-{
-	mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE0_IO_TARGET,
-					  KIRKWOOD_MBUS_PCIE0_IO_ATTR,
-					  KIRKWOOD_PCIE_IO_PHYS_BASE,
-					  KIRKWOOD_PCIE_IO_SIZE,
-					  KIRKWOOD_PCIE_IO_BUS_BASE);
-	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE0_MEM_TARGET,
-				    KIRKWOOD_MBUS_PCIE0_MEM_ATTR,
-				    KIRKWOOD_PCIE_MEM_PHYS_BASE,
-				    KIRKWOOD_PCIE_MEM_SIZE);
-	mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE1_IO_TARGET,
-					  KIRKWOOD_MBUS_PCIE1_IO_ATTR,
-					  KIRKWOOD_PCIE1_IO_PHYS_BASE,
-					  KIRKWOOD_PCIE1_IO_SIZE,
-					  KIRKWOOD_PCIE1_IO_BUS_BASE);
-	mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE1_MEM_TARGET,
-				    KIRKWOOD_MBUS_PCIE1_MEM_ATTR,
-				    KIRKWOOD_PCIE1_MEM_PHYS_BASE,
-				    KIRKWOOD_PCIE1_MEM_SIZE);
-
-	vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
-
-	if (portmask & KW_PCIE0)
-		add_pcie_port(0, PCIE_VIRT_BASE);
-
-	if (portmask & KW_PCIE1)
-		add_pcie_port(1, PCIE1_VIRT_BASE);
-
-	kirkwood_pci.nr_controllers = num_pcie_ports;
-	pci_common_init(&kirkwood_pci);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * Power Management driver for Marvell Kirkwood SoCs
- *
- * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/suspend.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include "common.h"
-
-static void __iomem *ddr_operation_base;
-static void __iomem *memory_pm_ctrl;
-
-static void kirkwood_low_power(void)
-{
-	u32 mem_pm_ctrl;
-
-	mem_pm_ctrl = readl(memory_pm_ctrl);
-
-	/* Set peripherals to low-power mode */
-	writel_relaxed(~0, memory_pm_ctrl);
-
-	/* Set DDR in self-refresh */
-	writel_relaxed(0x7, ddr_operation_base);
-
-	/*
-	 * Set CPU in wait-for-interrupt state.
-	 * This disables the CPU core clocks,
-	 * the array clocks, and also the L2 controller.
-	 */
-	cpu_do_idle();
-
-	writel_relaxed(mem_pm_ctrl, memory_pm_ctrl);
-}
-
-static int kirkwood_suspend_enter(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_STANDBY:
-		kirkwood_low_power();
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int kirkwood_pm_valid_standby(suspend_state_t state)
-{
-	return state == PM_SUSPEND_STANDBY;
-}
-
-static const struct platform_suspend_ops kirkwood_suspend_ops = {
-	.enter = kirkwood_suspend_enter,
-	.valid = kirkwood_pm_valid_standby,
-};
-
-void __init kirkwood_pm_init(void)
-{
-	ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
-	memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4);
-
-	suspend_set_ops(&kirkwood_suspend_ops);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pm.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pm.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/pm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/pm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Power Management driver for Marvell Kirkwood SoCs
- *
- * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ARCH_KIRKWOOD_PM_H
-#define __ARCH_KIRKWOOD_PM_H
-
-#ifdef CONFIG_PM
-void kirkwood_pm_init(void);
-#else
-static inline void kirkwood_pm_init(void) {};
-#endif
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,89 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
- *
- * Marvell RD-88F6192-NAS Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <plat/orion-gpio.h>
-#include "common.h"
-
-#define RD88F6192_GPIO_USB_VBUS		10
-
-static struct mv643xx_eth_platform_data rd88f6192_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data rd88f6192_sata_data = {
-	.n_ports	= 2,
-};
-
-static const struct flash_platform_data rd88F6192_spi_slave_data = {
-	.type		= "m25p128",
-};
-
-static struct spi_board_info __initdata rd88F6192_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &rd88F6192_spi_slave_data,
-		.irq		= -1,
-		.max_speed_hz	= 20000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
-
-static void __init rd88f6192_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-
-	orion_gpio_set_valid(RD88F6192_GPIO_USB_VBUS, 1);
-	if (gpio_request(RD88F6192_GPIO_USB_VBUS, "USB VBUS") != 0 ||
-	    gpio_direction_output(RD88F6192_GPIO_USB_VBUS, 1) != 0)
-		pr_err("RD-88F6192-NAS: failed to setup USB VBUS GPIO\n");
-
-	kirkwood_ehci_init();
-	kirkwood_ge00_init(&rd88f6192_ge00_data);
-	kirkwood_sata_init(&rd88f6192_sata_data);
-	spi_register_board_info(rd88F6192_spi_slave_info,
-				ARRAY_SIZE(rd88F6192_spi_slave_info));
-	kirkwood_spi_init();
-	kirkwood_uart0_init();
-}
-
-static int __init rd88f6192_pci_init(void)
-{
-	if (machine_is_rd88f6192_nas())
-		kirkwood_pcie_init(KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(rd88f6192_pci_init);
-
-MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
-	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= rd88f6192_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/rd88f6281-setup.c
- *
- * Marvell RD-88F6281 Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ethtool.h>
-#include <net/dsa.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition rd88f6281_nand_parts[] = {
-	{
-		.name = "u-boot",
-		.offset = 0,
-		.size = SZ_1M
-	}, {
-		.name = "uImage",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = SZ_2M
-	}, {
-		.name = "root",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data rd88f6281_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_NONE,
-	.speed		= SPEED_1000,
-	.duplex		= DUPLEX_FULL,
-};
-
-static struct dsa_chip_data rd88f6281_switch_chip_data = {
-	.port_names[0]	= "lan1",
-	.port_names[1]	= "lan2",
-	.port_names[2]	= "lan3",
-	.port_names[3]	= "lan4",
-	.port_names[5]	= "cpu",
-};
-
-static struct dsa_platform_data rd88f6281_switch_plat_data = {
-	.nr_chips	= 1,
-	.chip		= &rd88f6281_switch_chip_data,
-};
-
-static struct mv643xx_eth_platform_data rd88f6281_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(11),
-};
-
-static struct mv_sata_platform_data rd88f6281_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
-	.gpio_card_detect = 28,
-	.gpio_write_protect = -1,
-};
-
-static unsigned int rd88f6281_mpp_config[] __initdata = {
-	MPP28_GPIO,
-	0
-};
-
-static void __init rd88f6281_init(void)
-{
-	u32 dev, rev;
-
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(rd88f6281_mpp_config);
-
-	kirkwood_nand_init(rd88f6281_nand_parts,
-			   ARRAY_SIZE(rd88f6281_nand_parts),
-			   25);
-	kirkwood_ehci_init();
-
-	kirkwood_ge00_init(&rd88f6281_ge00_data);
-	kirkwood_pcie_id(&dev, &rev);
-	if (rev == MV88F6281_REV_A0) {
-		rd88f6281_switch_chip_data.sw_addr = 10;
-		kirkwood_ge01_init(&rd88f6281_ge01_data);
-	} else {
-		rd88f6281_switch_chip_data.port_names[4] = "wan";
-	}
-	kirkwood_ge00_switch_init(&rd88f6281_switch_plat_data, NO_IRQ);
-
-	kirkwood_sata_init(&rd88f6281_sata_data);
-	kirkwood_sdio_init(&rd88f6281_mvsdio_data);
-	kirkwood_uart0_init();
-}
-
-static int __init rd88f6281_pci_init(void)
-{
-	if (machine_is_rd88f6281())
-		kirkwood_pcie_init(KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(rd88f6281_pci_init);
-
-MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
-	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= rd88f6281_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/t5325-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/t5325-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/t5325-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/t5325-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,216 +0,0 @@
-/*
- *
- * HP t5325 Thin Client setup
- *
- * Copyright (C) 2010  Martin Michlmayr <tbm@cyrius.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <sound/alc5623.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition hp_t5325_partitions[] = {
-	{
-		.name		= "u-boot env",
-		.size		= SZ_64K,
-		.offset		= SZ_512K + SZ_256K,
-	},
-	{
-		.name		= "permanent u-boot env",
-		.size		= SZ_64K,
-		.offset		= MTDPART_OFS_APPEND,
-		.mask_flags	= MTD_WRITEABLE,
-	},
-	{
-		.name		= "HP env",
-		.size		= SZ_64K,
-		.offset		= MTDPART_OFS_APPEND,
-	},
-	{
-		.name		= "u-boot",
-		.size		= SZ_512K,
-		.offset		= 0,
-		.mask_flags	= MTD_WRITEABLE,
-	},
-	{
-		.name		= "SSD firmware",
-		.size		= SZ_256K,
-		.offset		= SZ_512K,
-	},
-};
-
-static const struct flash_platform_data hp_t5325_flash = {
-	.type		= "mx25l8005",
-	.name		= "spi_flash",
-	.parts		= hp_t5325_partitions,
-	.nr_parts	= ARRAY_SIZE(hp_t5325_partitions),
-};
-
-static struct spi_board_info __initdata hp_t5325_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &hp_t5325_flash,
-		.irq		= -1,
-	},
-};
-
-static struct mv643xx_eth_platform_data hp_t5325_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data hp_t5325_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct gpio_keys_button hp_t5325_buttons[] = {
-	{
-		.code		= KEY_POWER,
-		.gpio		= 45,
-		.desc		= "Power",
-		.active_low	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data hp_t5325_button_data = {
-	.buttons	= hp_t5325_buttons,
-	.nbuttons	= ARRAY_SIZE(hp_t5325_buttons),
-};
-
-static struct platform_device hp_t5325_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &hp_t5325_button_data,
-	}
-};
-
-static struct platform_device hp_t5325_audio_device = {
-	.name		= "t5325-audio",
-	.id		= -1,
-};
-
-static unsigned int hp_t5325_mpp_config[] __initdata = {
-	MPP0_NF_IO2,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP4_NF_IO6,
-	MPP5_NF_IO7,
-	MPP6_SYSRST_OUTn,
-	MPP7_SPI_SCn,
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP12_SD_CLK,
-	MPP13_GPIO,
-	MPP14_GPIO,
-	MPP15_GPIO,
-	MPP16_GPIO,
-	MPP17_GPIO,
-	MPP18_NF_IO0,
-	MPP19_NF_IO1,
-	MPP20_GPIO,
-	MPP21_GPIO,
-	MPP22_GPIO,
-	MPP23_GPIO,
-	MPP32_GPIO,
-	MPP33_GE1_TXCTL,
-	MPP39_AU_I2SBCLK,
-	MPP40_AU_I2SDO,
-	MPP43_AU_I2SDI,
-	MPP41_AU_I2SLRCLK,
-	MPP42_AU_I2SMCLK,
-	MPP45_GPIO,		/* Power button */
-	MPP48_GPIO,		/* Board power off */
-	0
-};
-
-static struct alc5623_platform_data alc5621_data = {
-	.add_ctrl = 0x3700,
-	.jack_det_ctrl = 0x4810,
-};
-
-static struct i2c_board_info i2c_board_info[] __initdata = {
-	{
-		I2C_BOARD_INFO("alc5621", 0x1a),
-		.platform_data = &alc5621_data,
-	},
-};
-
-#define HP_T5325_GPIO_POWER_OFF		48
-
-static void hp_t5325_power_off(void)
-{
-	gpio_set_value(HP_T5325_GPIO_POWER_OFF, 1);
-}
-
-static void __init hp_t5325_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(hp_t5325_mpp_config);
-
-	kirkwood_uart0_init();
-	spi_register_board_info(hp_t5325_spi_slave_info,
-				ARRAY_SIZE(hp_t5325_spi_slave_info));
-	kirkwood_spi_init();
-	kirkwood_i2c_init();
-	kirkwood_ge00_init(&hp_t5325_ge00_data);
-	kirkwood_sata_init(&hp_t5325_sata_data);
-	kirkwood_ehci_init();
-	platform_device_register(&hp_t5325_button_device);
-	platform_device_register(&hp_t5325_audio_device);
-
-	i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
-	kirkwood_audio_init();
-
-	if (gpio_request(HP_T5325_GPIO_POWER_OFF, "power-off") == 0 &&
-	    gpio_direction_output(HP_T5325_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = hp_t5325_power_off;
-	else
-		pr_err("t5325: failed to configure power-off GPIO\n");
-}
-
-static int __init hp_t5325_pci_init(void)
-{
-	if (machine_is_t5325())
-		kirkwood_pcie_init(KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(hp_t5325_pci_init);
-
-MACHINE_START(T5325, "HP t5325 Thin Client")
-	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= hp_t5325_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/ts219-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/*
- *
- * QNAP TS-11x/TS-21x Turbo NAS Board Setup
- *
- * Copyright (C) 2009  Martin Michlmayr <tbm@cyrius.com>
- * Copyright (C) 2008  Byron Bradley <byron.bbradley@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-#include "tsx1x-common.h"
-
-static struct i2c_board_info __initdata qnap_ts219_i2c_rtc = {
-	I2C_BOARD_INFO("s35390a", 0x30),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data qnap_ts219_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct gpio_keys_button qnap_ts219_buttons[] = {
-	{
-		.code		= KEY_COPY,
-		.gpio		= 15,
-		.desc		= "USB Copy",
-		.active_low	= 1,
-	},
-	{
-		.code		= KEY_RESTART,
-		.gpio		= 16,
-		.desc		= "Reset",
-		.active_low	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data qnap_ts219_button_data = {
-	.buttons	= qnap_ts219_buttons,
-	.nbuttons	= ARRAY_SIZE(qnap_ts219_buttons),
-};
-
-static struct platform_device qnap_ts219_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &qnap_ts219_button_data,
-	}
-};
-
-static unsigned int qnap_ts219_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP4_SATA1_ACTn,
-	MPP5_SATA0_ACTn,
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP13_UART1_TXD,	/* PIC controller */
-	MPP14_UART1_RXD,	/* PIC controller */
-	MPP15_GPIO,		/* USB Copy button (on devices with 88F6281) */
-	MPP16_GPIO,		/* Reset button (on devices with 88F6281) */
-	MPP36_GPIO,		/* RAM: 0: 256 MB, 1: 512 MB */
-	MPP37_GPIO,		/* Reset button (on devices with 88F6282) */
-	MPP43_GPIO,		/* USB Copy button (on devices with 88F6282) */
-	MPP44_GPIO,		/* Board ID: 0: TS-11x, 1: TS-21x */
-	0
-};
-
-static void __init qnap_ts219_init(void)
-{
-	u32 dev, rev;
-
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(qnap_ts219_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_uart1_init(); /* A PIC controller is connected here. */
-	qnap_tsx1x_register_flash();
-	kirkwood_i2c_init();
-	i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
-
-	kirkwood_pcie_id(&dev, &rev);
-	if (dev == MV88F6282_DEV_ID) {
-		qnap_ts219_buttons[0].gpio = 43; /* USB Copy button */
-		qnap_ts219_buttons[1].gpio = 37; /* Reset button */
-		qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
-	}
-
-	kirkwood_ge00_init(&qnap_ts219_ge00_data);
-	kirkwood_sata_init(&qnap_ts219_sata_data);
-	kirkwood_ehci_init();
-	platform_device_register(&qnap_ts219_button_device);
-
-	pm_power_off = qnap_tsx1x_power_off;
-
-}
-
-static int __init ts219_pci_init(void)
-{
-	if (machine_is_ts219())
-		kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
-
-	return 0;
-}
-subsys_initcall(ts219_pci_init);
-
-MACHINE_START(TS219, "QNAP TS-119/TS-219")
-	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= qnap_ts219_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/ts41x-setup.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/ts41x-setup.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/*
- *
- * QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS Board Setup
- *
- * Copyright (C) 2009-2010  Martin Michlmayr <tbm@cyrius.com>
- * Copyright (C) 2008  Byron Bradley <byron.bbradley@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-#include "tsx1x-common.h"
-
-/* for the PCIe reset workaround */
-#include <plat/pcie.h>
-
-
-#define QNAP_TS41X_JUMPER_JP1	45
-
-static struct i2c_board_info __initdata qnap_ts41x_i2c_rtc = {
-	I2C_BOARD_INFO("s35390a", 0x30),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts41x_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts41x_ge01_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv_sata_platform_data qnap_ts41x_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct gpio_keys_button qnap_ts41x_buttons[] = {
-	{
-		.code		= KEY_COPY,
-		.gpio		= 43,
-		.desc		= "USB Copy",
-		.active_low	= 1,
-	},
-	{
-		.code		= KEY_RESTART,
-		.gpio		= 37,
-		.desc		= "Reset",
-		.active_low	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data qnap_ts41x_button_data = {
-	.buttons	= qnap_ts41x_buttons,
-	.nbuttons	= ARRAY_SIZE(qnap_ts41x_buttons),
-};
-
-static struct platform_device qnap_ts41x_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &qnap_ts41x_button_data,
-	}
-};
-
-static unsigned int qnap_ts41x_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP6_SYSRST_OUTn,
-	MPP7_PEX_RST_OUTn,
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP13_UART1_TXD,	/* PIC controller */
-	MPP14_UART1_RXD,	/* PIC controller */
-	MPP15_SATA0_ACTn,
-	MPP16_SATA1_ACTn,
-	MPP20_GE1_TXD0,
-	MPP21_GE1_TXD1,
-	MPP22_GE1_TXD2,
-	MPP23_GE1_TXD3,
-	MPP24_GE1_RXD0,
-	MPP25_GE1_RXD1,
-	MPP26_GE1_RXD2,
-	MPP27_GE1_RXD3,
-	MPP30_GE1_RXCTL,
-	MPP31_GE1_RXCLK,
-	MPP32_GE1_TCLKOUT,
-	MPP33_GE1_TXCTL,
-	MPP36_GPIO,		/* RAM: 0: 256 MB, 1: 512 MB */
-	MPP37_GPIO,		/* Reset button */
-	MPP43_GPIO,		/* USB Copy button */
-	MPP44_GPIO,		/* Board ID: 0: TS-419U, 1: TS-419 */
-	MPP45_GPIO,		/* JP1: 0: LCD, 1: serial console */
-	MPP46_GPIO,		/* External SATA HDD1 error indicator */
-	MPP47_GPIO,		/* External SATA HDD2 error indicator */
-	MPP48_GPIO,		/* External SATA HDD3 error indicator */
-	MPP49_GPIO,		/* External SATA HDD4 error indicator */
-	0
-};
-
-static void __init qnap_ts41x_init(void)
-{
-	u32 dev, rev;
-
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(qnap_ts41x_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_uart1_init(); /* A PIC controller is connected here. */
-	qnap_tsx1x_register_flash();
-	kirkwood_i2c_init();
-	i2c_register_board_info(0, &qnap_ts41x_i2c_rtc, 1);
-
-	kirkwood_pcie_id(&dev, &rev);
-	if (dev == MV88F6282_DEV_ID) {
-		qnap_ts41x_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
-		qnap_ts41x_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
-	}
-	kirkwood_ge00_init(&qnap_ts41x_ge00_data);
-	kirkwood_ge01_init(&qnap_ts41x_ge01_data);
-
-	kirkwood_sata_init(&qnap_ts41x_sata_data);
-	kirkwood_ehci_init();
-	platform_device_register(&qnap_ts41x_button_device);
-
-	pm_power_off = qnap_tsx1x_power_off;
-
-	if (gpio_request(QNAP_TS41X_JUMPER_JP1, "JP1") == 0)
-		gpio_export(QNAP_TS41X_JUMPER_JP1, 0);
-}
-
-static int __init ts41x_pci_init(void)
-{
-	if (machine_is_ts41x()) {
-		u32 dev, rev;
-
-		/*
-		 * Without this explicit reset, the PCIe SATA controller
-		 * (Marvell 88sx7042/sata_mv) is known to stop working
-		 * after a few minutes.
-		 */
-		orion_pcie_reset(PCIE_VIRT_BASE);
-
-		kirkwood_pcie_id(&dev, &rev);
-		if (dev == MV88F6282_DEV_ID)
-			kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
-		else
-			kirkwood_pcie_init(KW_PCIE0);
-	}
-	return 0;
-}
-subsys_initcall(ts41x_pci_init);
-
-MACHINE_START(TS41X, "QNAP TS-41x")
-	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.atag_offset	= 0x100,
-	.init_machine	= qnap_ts41x_init,
-	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_init_early,
-	.init_irq	= kirkwood_init_irq,
-	.init_time	= kirkwood_timer_init,
-	.restart	= kirkwood_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/tsx1x-common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/tsx1x-common.c
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/tsx1x-common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/tsx1x-common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/serial_reg.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "tsx1x-common.h"
-
-/*
- * QNAP TS-x1x Boards flash
- */
-
-/****************************************************************************
- * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the
- *     partitions on the device because we want to keep compatibility with
- *     the QNAP firmware.
- * Layout as used by QNAP:
- *  0x00000000-0x00080000 : "U-Boot"
- *  0x00200000-0x00400000 : "Kernel"
- *  0x00400000-0x00d00000 : "RootFS"
- *  0x00d00000-0x01000000 : "RootFS2"
- *  0x00080000-0x000c0000 : "U-Boot Config"
- *  0x000c0000-0x00200000 : "NAS Config"
- *
- * We'll use "RootFS1" instead of "RootFS" to stay compatible with the layout
- * used by the QNAP TS-109/TS-209.
- *
- ***************************************************************************/
-
-static struct mtd_partition qnap_tsx1x_partitions[] = {
-	{
-		.name		= "U-Boot",
-		.size		= 0x00080000,
-		.offset		= 0,
-		.mask_flags	= MTD_WRITEABLE,
-	}, {
-		.name		= "Kernel",
-		.size		= 0x00200000,
-		.offset		= 0x00200000,
-	}, {
-		.name		= "RootFS1",
-		.size		= 0x00900000,
-		.offset		= 0x00400000,
-	}, {
-		.name		= "RootFS2",
-		.size		= 0x00300000,
-		.offset		= 0x00d00000,
-	}, {
-		.name		= "U-Boot Config",
-		.size		= 0x00040000,
-		.offset		= 0x00080000,
-	}, {
-		.name		= "NAS Config",
-		.size		= 0x00140000,
-		.offset		= 0x000c0000,
-	},
-};
-
-static const struct flash_platform_data qnap_tsx1x_flash = {
-	.type		= "m25p128",
-	.name		= "spi_flash",
-	.parts		= qnap_tsx1x_partitions,
-	.nr_parts	= ARRAY_SIZE(qnap_tsx1x_partitions),
-};
-
-static struct spi_board_info __initdata qnap_tsx1x_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &qnap_tsx1x_flash,
-		.irq		= -1,
-		.max_speed_hz	= 20000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
-
-void __init qnap_tsx1x_register_flash(void)
-{
-	spi_register_board_info(qnap_tsx1x_spi_slave_info,
-				ARRAY_SIZE(qnap_tsx1x_spi_slave_info));
-	kirkwood_spi_init();
-}
-
-
-/*****************************************************************************
- * QNAP TS-x1x specific power off method via UART1-attached PIC
- ****************************************************************************/
-
-#define UART1_REG(x)	(UART1_VIRT_BASE + ((UART_##x) << 2))
-
-void qnap_tsx1x_power_off(void)
-{
-	/* 19200 baud divisor */
-	const unsigned divisor = ((kirkwood_tclk + (8 * 19200)) / (16 * 19200));
-
-	pr_info("%s: triggering power-off...\n", __func__);
-
-	/* hijack UART1 and reset into sane state (19200,8n1) */
-	writel(0x83, UART1_REG(LCR));
-	writel(divisor & 0xff, UART1_REG(DLL));
-	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
-	writel(0x03, UART1_REG(LCR));
-	writel(0x00, UART1_REG(IER));
-	writel(0x00, UART1_REG(FCR));
-	writel(0x00, UART1_REG(MCR));
-
-	/* send the power-off command 'A' to PIC */
-	writel('A', UART1_REG(TX));
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-kirkwood/tsx1x-common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/tsx1x-common.h
--- linux-libre-3.16-gnu/arch/arm/mach-kirkwood/tsx1x-common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-kirkwood/tsx1x-common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __ARCH_KIRKWOOD_TSX1X_COMMON_H
-#define __ARCH_KIRKWOOD_TSX1X_COMMON_H
-
-extern void __init qnap_tsx1x_register_flash(void);
-extern void qnap_tsx1x_power_off(void);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ks8695/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-ks8695/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-ks8695/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ks8695/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,11 +15,6 @@
 
 #include <mach/hardware.h>
 
-/*
- * Physical SRAM offset.
- */
-#define PLAT_PHYS_OFFSET		KS8695_SDRAM_PA
-
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_PCI
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mediatek/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-mediatek/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+config ARCH_MEDIATEK
+	bool "Mediatek MT6589 SoC" if ARCH_MULTI_V7
+	select ARM_GIC
+	select MTK_TIMER
+	help
+	  Support for Mediatek Cortex-A7 Quad-Core-SoC MT6589.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mediatek/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-mediatek/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mediatek/mediatek.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/mediatek.c
--- linux-libre-3.16-gnu/arch/arm/mach-mediatek/mediatek.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mediatek/mediatek.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * Device Tree support for Mediatek SoCs
+ *
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@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/init.h>
+#include <asm/mach/arch.h>
+
+static const char * const mediatek_board_dt_compat[] = {
+	"mediatek,mt6589",
+	NULL,
+};
+
+DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+	.dt_compat	= mediatek_board_dt_compat,
+MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h linux-libre-3.17-rc7-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
--- linux-libre-3.16-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
 #define SM_nCS0_nCS0		MFP_CFG(SM_nCS0, AF0)
 #define SM_ADV_SM_ADV		MFP_CFG(SM_ADV, AF0)
 #define SM_SCLK_SM_SCLK		MFP_CFG(SM_SCLK, AF0)
-#define SM_SCLK_SM_SCLK		MFP_CFG(SM_SCLK, AF0)
 #define SM_BE0_SM_BE0		MFP_CFG(SM_BE0, AF1)
 #define SM_BE1_SM_BE1		MFP_CFG(SM_BE1, AF1)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-msm/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-msm/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-msm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-msm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -106,7 +106,4 @@ config MSM_GPIOMUX
 	help
 	  Support for MSM V1 TLMM GPIOMUX architecture.
 
-config MSM_SCM
-	bool
-
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/armada-370-xp.h linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/armada-370-xp.h
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/armada-370-xp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/armada-370-xp.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,4 +24,6 @@ void armada_xp_secondary_startup(void);
 extern struct smp_operations armada_xp_smp_ops;
 #endif
 
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
+
 #endif /* __MACH_ARMADA_370_XP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/board.h linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/board.h
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/board.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/board.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,4 +13,9 @@
 #ifndef __ARCH_MVEBU_BOARD_H
 #define __ARCH_MVEBU_BOARD_H
 
+#ifdef CONFIG_MACH_NETXBIG
+void netxbig_init(void);
+#else
+static inline void netxbig_init(void) {};
+#endif
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/board-v7.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/board-v7.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/board-v7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/board-v7.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,14 +34,14 @@
 #include "coherency.h"
 #include "mvebu-soc-id.h"
 
+static void __iomem *scu_base;
+
 /*
  * Enables the SCU when available. Obviously, this is only useful on
  * Cortex-A based SOCs, not on PJ4B based ones.
  */
 static void __init mvebu_scu_enable(void)
 {
-	void __iomem *scu_base;
-
 	struct device_node *np =
 		of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
 	if (np) {
@@ -51,6 +51,11 @@ static void __init mvebu_scu_enable(void
 	}
 }
 
+void __iomem *mvebu_get_scu_base(void)
+{
+	return scu_base;
+}
+
 /*
  * Early versions of Armada 375 SoC have a bug where the BootROM
  * leaves an external data abort pending. The kernel is hit by this
@@ -125,8 +130,16 @@ static void __init thermal_quirk(void)
 {
 	struct device_node *np;
 	u32 dev, rev;
+	int res;
 
-	if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > ARMADA_375_Z1_REV)
+	/*
+	 * The early SoC Z1 revision needs a quirk to be applied in order
+	 * for the thermal controller to work properly. This quirk breaks
+	 * the thermal support if applied on a SoC that doesn't need it,
+	 * so we enforce the SoC revision to be known.
+	 */
+	res = mvebu_get_soc_id(&dev, &rev);
+	if (res < 0 || (res == 0 && rev > ARMADA_375_Z1_REV))
 		return;
 
 	for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
@@ -160,7 +173,8 @@ static void __init thermal_quirk(void)
 
 		/*
 		 * The thermal controller needs some quirk too, so let's change
-		 * the compatible string to reflect this.
+		 * the compatible string to reflect this and allow the driver
+		 * the take the necessary action.
 		 */
 		prop = kzalloc(sizeof(*prop), GFP_KERNEL);
 		prop->name = kstrdup("compatible", GFP_KERNEL);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/coherency_ll.S linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/coherency_ll.S
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/coherency_ll.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/coherency_ll.S	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ ENTRY(ll_get_coherency_base)
 	ldr	r1, =coherency_base
 	ldr	r1, [r1]
 2:
-	mov	pc, lr
+	ret	lr
 ENDPROC(ll_get_coherency_base)
 
 /*
@@ -63,7 +63,7 @@ ENTRY(ll_get_coherency_cpumask)
 	mov	r2, #(1 << 24)
 	lsl	r3, r2, r3
 ARM_BE8(rev	r3, r3)
-	mov	pc, lr
+	ret	lr
 ENDPROC(ll_get_coherency_cpumask)
 
 /*
@@ -94,7 +94,7 @@ ENTRY(ll_add_cpu_to_smp_group)
 	strex	r1, r2, [r0]
 	cmp	r1, #0
 	bne	1b
-	mov	pc, lr
+	ret	lr
 ENDPROC(ll_add_cpu_to_smp_group)
 
 ENTRY(ll_enable_coherency)
@@ -118,7 +118,7 @@ ENTRY(ll_enable_coherency)
 	bne	1b
 	dsb
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(ll_enable_coherency)
 
 ENTRY(ll_disable_coherency)
@@ -141,7 +141,7 @@ ENTRY(ll_disable_coherency)
 	cmp	r1, #0
 	bne	1b
 	dsb
-	mov	pc, lr
+	ret	lr
 ENDPROC(ll_disable_coherency)
 
 	.align 2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,8 @@ void mvebu_restart(enum reboot_mode mode
 int mvebu_cpu_reset_deassert(int cpu);
 void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr);
 void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr);
+int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
 
-void armada_xp_cpu_die(unsigned int cpu);
+void __iomem *mvebu_get_scu_base(void);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/cpu-reset.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/cpu-reset.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/cpu-reset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/cpu-reset.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,7 @@ static int mvebu_cpu_reset_map(struct de
 	return 0;
 }
 
-int __init mvebu_cpu_reset_init(void)
+static int __init mvebu_cpu_reset_init(void)
 {
 	struct device_node *np;
 	int res_idx;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/headsmp-a9.S linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/headsmp-a9.S
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/headsmp-a9.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/headsmp-a9.S	2014-09-28 17:29:07.000000000 -0400
@@ -18,21 +18,6 @@
 #include <asm/assembler.h>
 
 	__CPUINIT
-#define CPU_RESUME_ADDR_REG 0xf10182d4
-
-.global armada_375_smp_cpu1_enable_code_start
-.global armada_375_smp_cpu1_enable_code_end
-
-armada_375_smp_cpu1_enable_code_start:
-ARM_BE8(setend	be)
-	adr     r0, 1f
-	ldr	r0, [r0]
-	ldr     r1, [r0]
-ARM_BE8(rev	r1, r1)
-	mov     pc, r1
-1:
-	.word   CPU_RESUME_ADDR_REG
-armada_375_smp_cpu1_enable_code_end:
 
 ENTRY(mvebu_cortex_a9_secondary_startup)
 ARM_BE8(setend	be)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/hotplug.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/hotplug.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/hotplug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/hotplug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/*
- * Symmetric Multi Processing (SMP) support for Armada XP
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <asm/proc-fns.h>
-#include "common.h"
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void __ref armada_xp_cpu_die(unsigned int cpu)
-{
-	cpu_do_idle();
-
-	/* We should never return from idle */
-	panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -14,11 +14,15 @@ menuconfig ARCH_MVEBU
 
 if ARCH_MVEBU
 
+config MACH_MVEBU_ANY
+	bool
+
 config MACH_MVEBU_V7
 	bool
 	select ARMADA_370_XP_TIMER
 	select CACHE_L2X0
 	select ARM_CPU_SUSPEND
+	select MACH_MVEBU_ANY
 
 config MACH_ARMADA_370
 	bool "Marvell Armada 370 boards" if ARCH_MULTI_V7
@@ -75,6 +79,7 @@ config MACH_DOVE
 	select CACHE_L2X0
 	select CPU_PJ4
 	select DOVE_CLK
+	select MACH_MVEBU_ANY
 	select ORION_IRQCHIP
 	select ORION_TIMER
 	select PINCTRL_DOVE
@@ -87,6 +92,7 @@ config MACH_KIRKWOOD
 	select ARCH_REQUIRE_GPIOLIB
 	select CPU_FEROCEON
 	select KIRKWOOD_CLK
+	select MACH_MVEBU_ANY
 	select ORION_IRQCHIP
 	select ORION_TIMER
 	select PCI
@@ -96,4 +102,11 @@ config MACH_KIRKWOOD
 	  Say 'Y' here if you want your kernel to support boards based
 	  on the Marvell Kirkwood device tree.
 
+config MACH_NETXBIG
+	bool "LaCie 2Big and 5Big Network v2"
+	depends on MACH_KIRKWOOD
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  LaCie 2Big and 5Big Network v2
+
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/kirkwood.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/kirkwood.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/kirkwood.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/kirkwood.c	2014-09-28 17:29:07.000000000 -0400
@@ -180,6 +180,9 @@ static void __init kirkwood_dt_init(void
 	kirkwood_pm_init();
 	kirkwood_dt_eth_fixup();
 
+	if (of_machine_is_compatible("lacie,netxbig"))
+		netxbig_init();
+
 	of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,13 +4,13 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) :=
 AFLAGS_coherency_ll.o		:= -Wa,-march=armv7-a
 CFLAGS_pmsu.o			:= -march=armv7-a
 
-obj-y				 += system-controller.o mvebu-soc-id.o
+obj-$(CONFIG_MACH_MVEBU_ANY)	 += system-controller.o mvebu-soc-id.o
 
 ifeq ($(CONFIG_MACH_MVEBU_V7),y)
 obj-y				 += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
 obj-$(CONFIG_SMP)		 += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
-obj-$(CONFIG_HOTPLUG_CPU)	 += hotplug.o
 endif
 
 obj-$(CONFIG_MACH_DOVE)		 += dove.o
 obj-$(CONFIG_MACH_KIRKWOOD)	 += kirkwood.o kirkwood-pm.o
+obj-$(CONFIG_MACH_NETXBIG)	 += netxbig.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/mvebu-soc-id.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/mvebu-soc-id.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/mvebu-soc-id.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/mvebu-soc-id.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
+#include "common.h"
 #include "mvebu-soc-id.h"
 
 #define PCIE_DEV_ID_OFF		0x0
@@ -51,10 +52,10 @@ int mvebu_get_soc_id(u32 *dev, u32 *rev)
 		*rev = soc_rev;
 		return 0;
 	} else
-		return -1;
+		return -ENODEV;
 }
 
-static int __init mvebu_soc_id_init(void)
+static int __init get_soc_id_by_pci(void)
 {
 	struct device_node *np;
 	int ret = 0;
@@ -129,6 +130,22 @@ clk_err:
 
 	return ret;
 }
+
+static int __init mvebu_soc_id_init(void)
+{
+
+	/*
+	 * First try to get the ID and the revision by the system
+	 * register and use PCI registers only if it is not possible
+	 */
+	if (!mvebu_system_controller_get_soc_id(&soc_dev_id, &soc_rev)) {
+		is_id_valid = true;
+		pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
+		return 0;
+	}
+
+	return get_soc_id_by_pci();
+}
 early_initcall(mvebu_soc_id_init);
 
 static int __init mvebu_soc_device(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/netxbig.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/netxbig.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/netxbig.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/netxbig.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,191 @@
+/*
+ * arch/arm/mach-mvbu/board-netxbig.c
+ *
+ * LaCie 2Big and 5Big Network v2 board setup
+ *
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/of.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/leds-kirkwood-netxbig.h>
+#include "common.h"
+
+/*****************************************************************************
+ * GPIO extension LEDs
+ ****************************************************************************/
+
+/*
+ * The LEDs are controlled by a CPLD and can be configured through a GPIO
+ * extension bus:
+ *
+ * - address register : bit [0-2] -> GPIO [47-49]
+ * - data register    : bit [0-2] -> GPIO [44-46]
+ * - enable register  : GPIO 29
+ */
+
+static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
+static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
+
+static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
+	.addr		= netxbig_v2_gpio_ext_addr,
+	.num_addr	= ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
+	.data		= netxbig_v2_gpio_ext_data,
+	.num_data	= ARRAY_SIZE(netxbig_v2_gpio_ext_data),
+	.enable		= 29,
+};
+
+/*
+ * Address register selection:
+ *
+ * addr | register
+ * ----------------------------
+ *   0  | front LED
+ *   1  | front LED brightness
+ *   2  | SATA LED brightness
+ *   3  | SATA0 LED
+ *   4  | SATA1 LED
+ *   5  | SATA2 LED
+ *   6  | SATA3 LED
+ *   7  | SATA4 LED
+ *
+ * Data register configuration:
+ *
+ * data | LED brightness
+ * -------------------------------------------------
+ *   0  | min (off)
+ *   -  | -
+ *   7  | max
+ *
+ * data | front LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | fix blue on
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | blink blue on=0.5 sec and blue off=2.5 sec
+ *
+ * data | SATA LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | SATA activity blink
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | fix blue on
+ */
+
+static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 2,
+	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
+	[NETXBIG_LED_TIMER1]	= 4,
+	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
+};
+
+static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 1,
+	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
+	[NETXBIG_LED_TIMER1]	= 3,
+	[NETXBIG_LED_TIMER2]	= 7,
+};
+
+static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 7,
+	[NETXBIG_LED_SATA]	= 1,
+	[NETXBIG_LED_TIMER1]	= 3,
+	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
+};
+
+static struct netxbig_led_timer netxbig_v2_led_timer[] = {
+	[0] = {
+		.delay_on	= 500,
+		.delay_off	= 500,
+		.mode		= NETXBIG_LED_TIMER1,
+	},
+	[1] = {
+		.delay_on	= 500,
+		.delay_off	= 1000,
+		.mode		= NETXBIG_LED_TIMER2,
+	},
+};
+
+#define NETXBIG_LED(_name, maddr, mval, baddr)			\
+	{ .name		= _name,				\
+	  .mode_addr	= maddr,				\
+	  .mode_val	= mval,					\
+	  .bright_addr	= baddr }
+
+static struct netxbig_led net2big_v2_leds_ctrl[] = {
+	NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+	NETXBIG_LED("net2big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+	NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net2big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net2big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+};
+
+static struct netxbig_led_platform_data net2big_v2_leds_data = {
+	.gpio_ext	= &netxbig_v2_gpio_ext,
+	.timer		= netxbig_v2_led_timer,
+	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
+	.leds		= net2big_v2_leds_ctrl,
+	.num_leds	= ARRAY_SIZE(net2big_v2_leds_ctrl),
+};
+
+static struct netxbig_led net5big_v2_leds_ctrl[] = {
+	NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+	NETXBIG_LED("net5big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+	NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata2",  5, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata3",  6, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata4",  7, netxbig_v2_red_mled,       2),
+};
+
+static struct netxbig_led_platform_data net5big_v2_leds_data = {
+	.gpio_ext	= &netxbig_v2_gpio_ext,
+	.timer		= netxbig_v2_led_timer,
+	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
+	.leds		= net5big_v2_leds_ctrl,
+	.num_leds	= ARRAY_SIZE(net5big_v2_leds_ctrl),
+};
+
+static struct platform_device netxbig_v2_leds = {
+	.name		= "leds-netxbig",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &net2big_v2_leds_data,
+	},
+};
+
+void __init netxbig_init(void)
+{
+
+	if (of_machine_is_compatible("lacie,net5big_v2"))
+		netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
+	platform_device_register(&netxbig_v2_leds);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/platsmp-a9.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/platsmp-a9.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/platsmp-a9.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/platsmp-a9.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,33 +20,8 @@
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 #include "common.h"
-#include "mvebu-soc-id.h"
 #include "pmsu.h"
 
-#define CRYPT0_ENG_ID   41
-#define CRYPT0_ENG_ATTR 0x1
-#define SRAM_PHYS_BASE  0xFFFF0000
-
-#define BOOTROM_BASE    0xFFF00000
-#define BOOTROM_SIZE    0x100000
-
-extern unsigned char armada_375_smp_cpu1_enable_code_end;
-extern unsigned char armada_375_smp_cpu1_enable_code_start;
-
-void armada_375_smp_cpu1_enable_wa(void)
-{
-	void __iomem *sram_virt_base;
-
-	mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
-	mvebu_mbus_add_window_by_id(CRYPT0_ENG_ID, CRYPT0_ENG_ATTR,
-				SRAM_PHYS_BASE, SZ_64K);
-	sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K);
-
-	memcpy(sram_virt_base, &armada_375_smp_cpu1_enable_code_start,
-	       &armada_375_smp_cpu1_enable_code_end
-	       - &armada_375_smp_cpu1_enable_code_start);
-}
-
 extern void mvebu_cortex_a9_secondary_startup(void);
 
 static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
@@ -63,21 +38,10 @@ static int __cpuinit mvebu_cortex_a9_boo
 	 * address.
 	 */
 	hw_cpu = cpu_logical_map(cpu);
-
-	if (of_machine_is_compatible("marvell,armada375")) {
-		u32 dev, rev;
-
-		if (mvebu_get_soc_id(&dev, &rev) == 0 &&
-		    rev == ARMADA_375_Z1_REV)
-			armada_375_smp_cpu1_enable_wa();
-
+	if (of_machine_is_compatible("marvell,armada375"))
 		mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup);
-	}
-	else {
-		mvebu_pmsu_set_cpu_boot_addr(hw_cpu,
-					     mvebu_cortex_a9_secondary_startup);
-	}
-
+	else
+		mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup);
 	smp_wmb();
 	ret = mvebu_cpu_reset_deassert(hw_cpu);
 	if (ret) {
@@ -91,9 +55,6 @@ static int __cpuinit mvebu_cortex_a9_boo
 
 static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
 	.smp_boot_secondary	= mvebu_cortex_a9_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-	.cpu_die		= armada_xp_cpu_die,
-#endif
 };
 
 CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,7 @@ static void __init set_secondary_cpus_cl
 		if (!cpu_clk)
 			return;
 		clk_set_rate(cpu_clk, rate);
+		clk_prepare_enable(cpu_clk);
 	}
 }
 
@@ -78,6 +79,17 @@ static int armada_xp_boot_secondary(unsi
 
 	hw_cpu = cpu_logical_map(cpu);
 	mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
+
+	/*
+	 * This is needed to wake up CPUs in the offline state after
+	 * using CPU hotplug.
+	 */
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	/*
+	 * This is needed to take secondary CPUs out of reset on the
+	 * initial boot.
+	 */
 	ret = mvebu_cpu_reset_deassert(hw_cpu);
 	if (ret) {
 		pr_warn("unable to boot CPU: %d\n", ret);
@@ -87,6 +99,19 @@ static int armada_xp_boot_secondary(unsi
 	return 0;
 }
 
+/*
+ * When a CPU is brought back online, either through CPU hotplug, or
+ * because of the boot of a kexec'ed kernel, the PMSU configuration
+ * for this CPU might be in the deep idle state, preventing this CPU
+ * from receiving interrupts. Here, we therefore take out the current
+ * CPU from this state, which was entered by armada_xp_cpu_die()
+ * below.
+ */
+static void armada_xp_secondary_init(unsigned int cpu)
+{
+	mvebu_v7_pmsu_idle_exit();
+}
+
 static void __init armada_xp_smp_init_cpus(void)
 {
 	unsigned int ncores = num_possible_cpus();
@@ -122,12 +147,36 @@ static void __init armada_xp_smp_prepare
 		panic("The address for the BootROM is incorrect");
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void armada_xp_cpu_die(unsigned int cpu)
+{
+	/*
+	 * CPU hotplug is implemented by putting offline CPUs into the
+	 * deep idle sleep state.
+	 */
+	armada_370_xp_pmsu_idle_enter(true);
+}
+
+/*
+ * We need a dummy function, so that platform_can_cpu_hotplug() knows
+ * we support CPU hotplug. However, the function does not need to do
+ * anything, because CPUs going offline can enter the deep idle state
+ * by themselves, without any help from a still alive CPU.
+ */
+static int armada_xp_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+#endif
+
 struct smp_operations armada_xp_smp_ops __initdata = {
 	.smp_init_cpus		= armada_xp_smp_init_cpus,
 	.smp_prepare_cpus	= armada_xp_smp_prepare_cpus,
 	.smp_boot_secondary	= armada_xp_boot_secondary,
+	.smp_secondary_init     = armada_xp_secondary_init,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= armada_xp_cpu_die,
+	.cpu_kill               = armada_xp_cpu_kill,
 #endif
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,22 +18,29 @@
 
 #define pr_fmt(fmt) "mvebu-pmsu: " fmt
 
+#include <linux/clk.h>
 #include <linux/cpu_pm.h>
-#include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/of_address.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mbus.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/smp.h>
+#include <linux/pm_opp.h>
 #include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
+#include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 #include "common.h"
+#include "armada-370-xp.h"
 
-static void __iomem *pmsu_mp_base;
 
 #define PMSU_BASE_OFFSET    0x100
 #define PMSU_REG_SIZE	    0x1000
@@ -57,20 +64,45 @@ static void __iomem *pmsu_mp_base;
 #define PMSU_STATUS_AND_MASK_IRQ_MASK		BIT(24)
 #define PMSU_STATUS_AND_MASK_FIQ_MASK		BIT(25)
 
+#define PMSU_EVENT_STATUS_AND_MASK(cpu)     ((cpu * 0x100) + 0x120)
+#define PMSU_EVENT_STATUS_AND_MASK_DFS_DONE        BIT(1)
+#define PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK   BIT(17)
+
 #define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124)
 
 /* PMSU fabric registers */
 #define L2C_NFABRIC_PM_CTL		    0x4
 #define L2C_NFABRIC_PM_CTL_PWR_DOWN		BIT(20)
 
+/* PMSU delay registers */
+#define PMSU_POWERDOWN_DELAY		    0xF04
+#define PMSU_POWERDOWN_DELAY_PMU		BIT(1)
+#define PMSU_POWERDOWN_DELAY_MASK		0xFFFE
+#define PMSU_DFLT_ARMADA38X_DELAY	        0x64
+
+/* CA9 MPcore SoC Control registers */
+
+#define MPCORE_RESET_CTL		    0x64
+#define MPCORE_RESET_CTL_L2			BIT(0)
+#define MPCORE_RESET_CTL_DEBUG			BIT(16)
+
+#define SRAM_PHYS_BASE  0xFFFF0000
+#define BOOTROM_BASE    0xFFF00000
+#define BOOTROM_SIZE    0x100000
+
+#define ARMADA_370_CRYPT0_ENG_TARGET   0x9
+#define ARMADA_370_CRYPT0_ENG_ATTR     0x1
+
 extern void ll_disable_coherency(void);
 extern void ll_enable_coherency(void);
 
 extern void armada_370_xp_cpu_resume(void);
+extern void armada_38x_cpu_resume(void);
 
-static struct platform_device armada_xp_cpuidle_device = {
-	.name = "cpuidle-armada-370-xp",
-};
+static phys_addr_t pmsu_mp_phys_base;
+static void __iomem *pmsu_mp_base;
+
+static void *mvebu_cpu_resume;
 
 static struct of_device_id of_pmsu_table[] = {
 	{ .compatible = "marvell,armada-370-pmsu", },
@@ -85,7 +117,49 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw
 		PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
 }
 
-static int __init armada_370_xp_pmsu_init(void)
+extern unsigned char mvebu_boot_wa_start;
+extern unsigned char mvebu_boot_wa_end;
+
+/*
+ * This function sets up the boot address workaround needed for SMP
+ * boot on Armada 375 Z1 and cpuidle on Armada 370. It unmaps the
+ * BootROM Mbus window, and instead remaps a crypto SRAM into which a
+ * custom piece of code is copied to replace the problematic BootROM.
+ */
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+			     unsigned int crypto_eng_attribute,
+			     phys_addr_t resume_addr_reg)
+{
+	void __iomem *sram_virt_base;
+	u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start;
+
+	mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
+	mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute,
+				    SRAM_PHYS_BASE, SZ_64K);
+
+	sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K);
+	if (!sram_virt_base) {
+		pr_err("Unable to map SRAM to setup the boot address WA\n");
+		return -ENOMEM;
+	}
+
+	memcpy(sram_virt_base, &mvebu_boot_wa_start, code_len);
+
+	/*
+	 * The last word of the code copied in SRAM must contain the
+	 * physical base address of the PMSU register. We
+	 * intentionally store this address in the native endianness
+	 * of the system.
+	 */
+	__raw_writel((unsigned long)resume_addr_reg,
+		     sram_virt_base + code_len - 4);
+
+	iounmap(sram_virt_base);
+
+	return 0;
+}
+
+static int __init mvebu_v7_pmsu_init(void)
 {
 	struct device_node *np;
 	struct resource res;
@@ -116,6 +190,8 @@ static int __init armada_370_xp_pmsu_ini
 		goto out;
 	}
 
+	pmsu_mp_phys_base = res.start;
+
 	pmsu_mp_base = ioremap(res.start, resource_size(&res));
 	if (!pmsu_mp_base) {
 		pr_err("unable to map registers\n");
@@ -129,7 +205,7 @@ static int __init armada_370_xp_pmsu_ini
 	return ret;
 }
 
-static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
+static void mvebu_v7_pmsu_enable_l2_powerdown_onidle(void)
 {
 	u32 reg;
 
@@ -142,14 +218,20 @@ static void armada_370_xp_pmsu_enable_l2
 	writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL);
 }
 
+enum pmsu_idle_prepare_flags {
+	PMSU_PREPARE_NORMAL = 0,
+	PMSU_PREPARE_DEEP_IDLE = BIT(0),
+	PMSU_PREPARE_SNOOP_DISABLE = BIT(1),
+};
+
 /* No locking is needed because we only access per-CPU registers */
-void armada_370_xp_pmsu_idle_prepare(bool deepidle)
+static int mvebu_v7_pmsu_idle_prepare(unsigned long flags)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
 
 	if (pmsu_mp_base == NULL)
-		return;
+		return -EINVAL;
 
 	/*
 	 * Adjust the PMSU configuration to wait for WFI signal, enable
@@ -167,22 +249,34 @@ void armada_370_xp_pmsu_idle_prepare(boo
 
 	reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
 	/* ask HW to power down the L2 Cache if needed */
-	if (deepidle)
+	if (flags & PMSU_PREPARE_DEEP_IDLE)
 		reg |= PMSU_CONTROL_AND_CONFIG_L2_PWDDN;
 
 	/* request power down */
 	reg |= PMSU_CONTROL_AND_CONFIG_PWDDN_REQ;
 	writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
 
-	/* Disable snoop disable by HW - SW is taking care of it */
-	reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
-	reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
-	writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+	if (flags & PMSU_PREPARE_SNOOP_DISABLE) {
+		/* Disable snoop disable by HW - SW is taking care of it */
+		reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+		reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
+		writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+	}
+
+	return 0;
 }
 
-static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle)
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
 {
-	armada_370_xp_pmsu_idle_prepare(deepidle);
+	unsigned long flags = PMSU_PREPARE_SNOOP_DISABLE;
+	int ret;
+
+	if (deepidle)
+		flags |= PMSU_PREPARE_DEEP_IDLE;
+
+	ret = mvebu_v7_pmsu_idle_prepare(flags);
+	if (ret)
+		return ret;
 
 	v7_exit_coherency_flush(all);
 
@@ -208,25 +302,50 @@ static noinline int do_armada_370_xp_cpu
 	"isb	"
 	: : : "r0");
 
-	pr_warn("Failed to suspend the system\n");
+	pr_debug("Failed to suspend the system\n");
 
 	return 0;
 }
 
 static int armada_370_xp_cpu_suspend(unsigned long deepidle)
 {
-	return cpu_suspend(deepidle, do_armada_370_xp_cpu_suspend);
+	return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
+}
+
+static int armada_38x_do_cpu_suspend(unsigned long deepidle)
+{
+	unsigned long flags = 0;
+
+	if (deepidle)
+		flags |= PMSU_PREPARE_DEEP_IDLE;
+
+	mvebu_v7_pmsu_idle_prepare(flags);
+	/*
+	 * Already flushed cache, but do it again as the outer cache
+	 * functions dirty the cache with spinlocks
+	 */
+	v7_exit_coherency_flush(louis);
+
+	scu_power_mode(mvebu_get_scu_base(), SCU_PM_POWEROFF);
+
+	cpu_do_idle();
+
+	return 1;
+}
+
+static int armada_38x_cpu_suspend(unsigned long deepidle)
+{
+	return cpu_suspend(false, armada_38x_do_cpu_suspend);
 }
 
 /* No locking is needed because we only access per-CPU registers */
-static noinline void armada_370_xp_pmsu_idle_restore(void)
+void mvebu_v7_pmsu_idle_exit(void)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
 
 	if (pmsu_mp_base == NULL)
 		return;
-
 	/* cancel ask HW to power down the L2 Cache if possible */
 	reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
 	reg &= ~PMSU_CONTROL_AND_CONFIG_L2_PWDDN;
@@ -241,53 +360,292 @@ static noinline void armada_370_xp_pmsu_
 	writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu));
 }
 
-static int armada_370_xp_cpu_pm_notify(struct notifier_block *self,
+static int mvebu_v7_cpu_pm_notify(struct notifier_block *self,
 				    unsigned long action, void *hcpu)
 {
 	if (action == CPU_PM_ENTER) {
 		unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
-		mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume);
+		mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cpu_resume);
 	} else if (action == CPU_PM_EXIT) {
-		armada_370_xp_pmsu_idle_restore();
+		mvebu_v7_pmsu_idle_exit();
 	}
 
 	return NOTIFY_OK;
 }
 
-static struct notifier_block armada_370_xp_cpu_pm_notifier = {
-	.notifier_call = armada_370_xp_cpu_pm_notify,
+static struct notifier_block mvebu_v7_cpu_pm_notifier = {
+	.notifier_call = mvebu_v7_cpu_pm_notify,
 };
 
-int __init armada_370_xp_cpu_pm_init(void)
+static struct platform_device mvebu_v7_cpuidle_device;
+
+static __init int armada_370_cpuidle_init(void)
 {
 	struct device_node *np;
+	phys_addr_t redirect_reg;
+
+	np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
+	if (!np)
+		return -ENODEV;
+	of_node_put(np);
 
 	/*
-	 * Check that all the requirements are available to enable
-	 * cpuidle. So far, it is only supported on Armada XP, cpuidle
-	 * needs the coherency fabric and the PMSU enabled
+	 * On Armada 370, there is "a slow exit process from the deep
+	 * idle state due to heavy L1/L2 cache cleanup operations
+	 * performed by the BootROM software". To avoid this, we
+	 * replace the restart code of the bootrom by a a simple jump
+	 * to the boot address. Then the code located at this boot
+	 * address will take care of the initialization.
 	 */
+	redirect_reg = pmsu_mp_phys_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(0);
+	mvebu_setup_boot_addr_wa(ARMADA_370_CRYPT0_ENG_TARGET,
+				 ARMADA_370_CRYPT0_ENG_ATTR,
+				 redirect_reg);
 
-	if (!of_machine_is_compatible("marvell,armadaxp"))
-		return 0;
+	mvebu_cpu_resume = armada_370_xp_cpu_resume;
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
+
+	return 0;
+}
+
+static __init int armada_38x_cpuidle_init(void)
+{
+	struct device_node *np;
+	void __iomem *mpsoc_base;
+	u32 reg;
+
+	np = of_find_compatible_node(NULL, NULL,
+				     "marvell,armada-380-coherency-fabric");
+	if (!np)
+		return -ENODEV;
+	of_node_put(np);
+
+	np = of_find_compatible_node(NULL, NULL,
+				     "marvell,armada-380-mpcore-soc-ctrl");
+	if (!np)
+		return -ENODEV;
+	mpsoc_base = of_iomap(np, 0);
+	BUG_ON(!mpsoc_base);
+	of_node_put(np);
+
+	/* Set up reset mask when powering down the cpus */
+	reg = readl(mpsoc_base + MPCORE_RESET_CTL);
+	reg |= MPCORE_RESET_CTL_L2;
+	reg |= MPCORE_RESET_CTL_DEBUG;
+	writel(reg, mpsoc_base + MPCORE_RESET_CTL);
+	iounmap(mpsoc_base);
+
+	/* Set up delay */
+	reg = readl(pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+	reg &= ~PMSU_POWERDOWN_DELAY_MASK;
+	reg |= PMSU_DFLT_ARMADA38X_DELAY;
+	reg |= PMSU_POWERDOWN_DELAY_PMU;
+	writel(reg, pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+
+	mvebu_cpu_resume = armada_38x_cpu_resume;
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x";
+
+	return 0;
+}
+
+static __init int armada_xp_cpuidle_init(void)
+{
+	struct device_node *np;
 
 	np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
 	if (!np)
-		return 0;
+		return -ENODEV;
 	of_node_put(np);
 
+	mvebu_cpu_resume = armada_370_xp_cpu_resume;
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
+
+	return 0;
+}
+
+static int __init mvebu_v7_cpu_pm_init(void)
+{
+	struct device_node *np;
+	int ret;
+
 	np = of_find_matching_node(NULL, of_pmsu_table);
 	if (!np)
 		return 0;
 	of_node_put(np);
 
-	armada_370_xp_pmsu_enable_l2_powerdown_onidle();
-	armada_xp_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
-	platform_device_register(&armada_xp_cpuidle_device);
-	cpu_pm_register_notifier(&armada_370_xp_cpu_pm_notifier);
+	if (of_machine_is_compatible("marvell,armadaxp"))
+		ret = armada_xp_cpuidle_init();
+	else if (of_machine_is_compatible("marvell,armada370"))
+		ret = armada_370_cpuidle_init();
+	else if (of_machine_is_compatible("marvell,armada380"))
+		ret = armada_38x_cpuidle_init();
+	else
+		return 0;
+
+	if (ret)
+		return ret;
+
+	mvebu_v7_pmsu_enable_l2_powerdown_onidle();
+	platform_device_register(&mvebu_v7_cpuidle_device);
+	cpu_pm_register_notifier(&mvebu_v7_cpu_pm_notifier);
 
 	return 0;
 }
 
-arch_initcall(armada_370_xp_cpu_pm_init);
-early_initcall(armada_370_xp_pmsu_init);
+arch_initcall(mvebu_v7_cpu_pm_init);
+early_initcall(mvebu_v7_pmsu_init);
+
+static void mvebu_pmsu_dfs_request_local(void *data)
+{
+	u32 reg;
+	u32 cpu = smp_processor_id();
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* Prepare to enter idle */
+	reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+	reg |= PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT |
+	       PMSU_STATUS_AND_MASK_IRQ_MASK     |
+	       PMSU_STATUS_AND_MASK_FIQ_MASK;
+	writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+
+	/* Request the DFS transition */
+	reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(cpu));
+	reg |= PMSU_CONTROL_AND_CONFIG_DFS_REQ;
+	writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(cpu));
+
+	/* The fact of entering idle will trigger the DFS transition */
+	wfi();
+
+	/*
+	 * We're back from idle, the DFS transition has completed,
+	 * clear the idle wait indication.
+	 */
+	reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+	reg &= ~PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT;
+	writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+
+	local_irq_restore(flags);
+}
+
+int mvebu_pmsu_dfs_request(int cpu)
+{
+	unsigned long timeout;
+	int hwcpu = cpu_logical_map(cpu);
+	u32 reg;
+
+	/* Clear any previous DFS DONE event */
+	reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+	reg &= ~PMSU_EVENT_STATUS_AND_MASK_DFS_DONE;
+	writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+	/* Mask the DFS done interrupt, since we are going to poll */
+	reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+	reg |= PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK;
+	writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+	/* Trigger the DFS on the appropriate CPU */
+	smp_call_function_single(cpu, mvebu_pmsu_dfs_request_local,
+				 NULL, false);
+
+	/* Poll until the DFS done event is generated */
+	timeout = jiffies + HZ;
+	while (time_before(jiffies, timeout)) {
+		reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+		if (reg & PMSU_EVENT_STATUS_AND_MASK_DFS_DONE)
+			break;
+		udelay(10);
+	}
+
+	if (time_after(jiffies, timeout))
+		return -ETIME;
+
+	/* Restore the DFS mask to its original state */
+	reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+	reg &= ~PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK;
+	writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+	return 0;
+}
+
+static int __init armada_xp_pmsu_cpufreq_init(void)
+{
+	struct device_node *np;
+	struct resource res;
+	int ret, cpu;
+
+	if (!of_machine_is_compatible("marvell,armadaxp"))
+		return 0;
+
+	/*
+	 * In order to have proper cpufreq handling, we need to ensure
+	 * that the Device Tree description of the CPU clock includes
+	 * the definition of the PMU DFS registers. If not, we do not
+	 * register the clock notifier and the cpufreq driver. This
+	 * piece of code is only for compatibility with old Device
+	 * Trees.
+	 */
+	np = of_find_compatible_node(NULL, NULL, "marvell,armada-xp-cpu-clock");
+	if (!np)
+		return 0;
+
+	ret = of_address_to_resource(np, 1, &res);
+	if (ret) {
+		pr_warn(FW_WARN "not enabling cpufreq, deprecated armada-xp-cpu-clock binding\n");
+		of_node_put(np);
+		return 0;
+	}
+
+	of_node_put(np);
+
+	/*
+	 * For each CPU, this loop registers the operating points
+	 * supported (which are the nominal CPU frequency and half of
+	 * it), and registers the clock notifier that will take care
+	 * of doing the PMSU part of a frequency transition.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct device *cpu_dev;
+		struct clk *clk;
+		int ret;
+
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("Cannot get CPU %d\n", cpu);
+			continue;
+		}
+
+		clk = clk_get(cpu_dev, 0);
+		if (IS_ERR(clk)) {
+			pr_err("Cannot get clock for CPU %d\n", cpu);
+			return PTR_ERR(clk);
+		}
+
+		/*
+		 * In case of a failure of dev_pm_opp_add(), we don't
+		 * bother with cleaning up the registered OPP (there's
+		 * no function to do so), and simply cancel the
+		 * registration of the cpufreq device.
+		 */
+		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
+		if (ret) {
+			clk_put(clk);
+			return ret;
+		}
+
+		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
+		if (ret) {
+			clk_put(clk);
+			return ret;
+		}
+	}
+
+	platform_device_register_simple("cpufreq-generic", -1, NULL, 0);
+	return 0;
+}
+
+device_initcall(armada_xp_pmsu_cpufreq_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu.h linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu.h
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,5 +12,10 @@
 #define __MACH_MVEBU_PMSU_H
 
 int armada_xp_boot_cpu(unsigned int cpu_id, void *phys_addr);
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+                             unsigned int crypto_eng_attribute,
+                             phys_addr_t resume_addr_reg);
+
+void mvebu_v7_pmsu_idle_exit(void);
 
 #endif	/* __MACH_370_XP_PMSU_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu_ll.S linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu_ll.S
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/pmsu_ll.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/pmsu_ll.S	2014-09-28 17:29:07.000000000 -0400
@@ -23,3 +23,39 @@ ARM_BE8(setend	be )			@ go BE8 if entere
 	b	cpu_resume
 ENDPROC(armada_370_xp_cpu_resume)
 
+ENTRY(armada_38x_cpu_resume)
+	/* do we need it for Armada 38x*/
+ARM_BE8(setend	be )			@ go BE8 if entered LE
+	bl	v7_invalidate_l1
+	mrc     p15, 4, r1, c15, c0	@ get SCU base address
+	orr	r1, r1, #0x8		@ SCU CPU Power Status Register
+	mrc	15, 0, r0, cr0, cr0, 5	@ get the CPU ID
+	and	r0, r0, #15
+	add	r1, r1, r0
+	mov	r0, #0x0
+	strb	r0, [r1]		@ switch SCU power state to Normal mode
+	b	cpu_resume
+ENDPROC(armada_38x_cpu_resume)
+
+.global mvebu_boot_wa_start
+.global mvebu_boot_wa_end
+
+/* The following code will be executed from SRAM */
+ENTRY(mvebu_boot_wa_start)
+mvebu_boot_wa_start:
+ARM_BE8(setend	be)
+	adr	r0, 1f
+	ldr	r0, [r0]		@ load the address of the
+					@ resume register
+	ldr	r0, [r0]		@ load the value in the
+					@ resume register
+ARM_BE8(rev	r0, r0)			@ the value is stored LE
+	mov	pc, r0			@ jump to this value
+/*
+ * the last word of this piece of code will be filled by the physical
+ * address of the boot address register just after being copied in SRAM
+ */
+1:
+	.long   .
+mvebu_boot_wa_end:
+ENDPROC(mvebu_boot_wa_end)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-mvebu/system-controller.c linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/system-controller.c
--- linux-libre-3.16-gnu/arch/arm/mach-mvebu/system-controller.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-mvebu/system-controller.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,8 +28,14 @@
 #include <linux/io.h>
 #include <linux/reboot.h>
 #include "common.h"
+#include "mvebu-soc-id.h"
+#include "pmsu.h"
+
+#define ARMADA_375_CRYPT0_ENG_TARGET 41
+#define ARMADA_375_CRYPT0_ENG_ATTR    1
 
 static void __iomem *system_controller_base;
+static phys_addr_t system_controller_phys_base;
 
 struct mvebu_system_controller {
 	u32 rstoutn_mask_offset;
@@ -39,6 +45,9 @@ struct mvebu_system_controller {
 	u32 system_soft_reset;
 
 	u32 resume_boot_addr;
+
+	u32 dev_id;
+	u32 rev_id;
 };
 static struct mvebu_system_controller *mvebu_sc;
 
@@ -47,6 +56,8 @@ static const struct mvebu_system_control
 	.system_soft_reset_offset = 0x64,
 	.rstoutn_mask_reset_out_en = 0x1,
 	.system_soft_reset = 0x1,
+	.dev_id = 0x38,
+	.rev_id = 0x3c,
 };
 
 static const struct mvebu_system_controller armada_375_system_controller = {
@@ -55,6 +66,8 @@ static const struct mvebu_system_control
 	.rstoutn_mask_reset_out_en = 0x1,
 	.system_soft_reset = 0x1,
 	.resume_boot_addr = 0xd4,
+	.dev_id = 0x38,
+	.rev_id = 0x3c,
 };
 
 static const struct mvebu_system_controller orion_system_controller = {
@@ -101,11 +114,45 @@ void mvebu_restart(enum reboot_mode mode
 		;
 }
 
+int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
+{
+	if (of_machine_is_compatible("marvell,armada380") &&
+		system_controller_base) {
+		*dev = readl(system_controller_base + mvebu_sc->dev_id) >> 16;
+		*rev = (readl(system_controller_base + mvebu_sc->rev_id) >> 8)
+			& 0xF;
+		return 0;
+	} else
+		return -ENODEV;
+}
+
 #ifdef CONFIG_SMP
+void mvebu_armada375_smp_wa_init(void)
+{
+	u32 dev, rev;
+	phys_addr_t resume_addr_reg;
+
+	if (mvebu_get_soc_id(&dev, &rev) != 0)
+		return;
+
+	if (rev != ARMADA_375_Z1_REV)
+		return;
+
+	resume_addr_reg = system_controller_phys_base +
+		mvebu_sc->resume_boot_addr;
+	mvebu_setup_boot_addr_wa(ARMADA_375_CRYPT0_ENG_TARGET,
+				 ARMADA_375_CRYPT0_ENG_ATTR,
+				 resume_addr_reg);
+}
+
 void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
 {
 	BUG_ON(system_controller_base == NULL);
 	BUG_ON(mvebu_sc->resume_boot_addr == 0);
+
+	if (of_machine_is_compatible("marvell,armada375"))
+		mvebu_armada375_smp_wa_init();
+
 	writel(virt_to_phys(boot_addr), system_controller_base +
 	       mvebu_sc->resume_boot_addr);
 }
@@ -119,7 +166,10 @@ static int __init mvebu_system_controlle
 	np = of_find_matching_node_and_match(NULL, of_system_controller_table,
 					     &match);
 	if (np) {
+		struct resource res;
 		system_controller_base = of_iomap(np, 0);
+		of_address_to_resource(np, 0, &res);
+		system_controller_phys_base = res.start;
 		mvebu_sc = (struct mvebu_system_controller *)match->data;
 		of_node_put(np);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap1/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap1/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap1/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap1/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -6,11 +6,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 /*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x10000000)
-
-/*
  * Bus address is physical address, except for OMAP-1510 Local Bus.
  * OMAP-1510 bus address is translated into a Local Bus address if the
  * OMAP bus type is lbus. We do the address translation based on the
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap1/ocpi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap1/ocpi.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap1/ocpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap1/ocpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,6 @@ static struct clk *ocpi_ck;
 
 /*
  * Enables device access to OMAP buses via the OCPI bridge
- * FIXME: Add locking
  */
 int ocpi_enable(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/board-flash.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/board-flash.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/board-flash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/board-flash.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partit
 	board_nand_data.nr_parts	= nr_parts;
 	board_nand_data.devsize		= nand_type;
 
-	board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_HW;
+	board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_SW;
 	gpmc_nand_init(&board_nand_data, gpmc_t);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/board-omap3touchbook.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/board-omap3touchbook.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2014-09-28 17:29:07.000000000 -0400
@@ -336,7 +336,7 @@ static int __init early_touchbook_revisi
 	if (!p)
 		return 0;
 
-	return strict_strtoul(p, 10, &touchbook_revision);
+	return kstrtoul(p, 10, &touchbook_revision);
 }
 early_param("tbr", early_touchbook_revision);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/cclock2420_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cclock2420_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/cclock2420_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cclock2420_data.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1931 +0,0 @@
-/*
- * OMAP2420 clock data
- *
- * Copyright (C) 2005-2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- * Updated to COMMON clk format by Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
-
-/*
- * 2420 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- *	many cases the parent is selectable. The set parent calls will
- *	also switch sources.
- *
- *	Several sources are given initial rates which may be wrong, this will
- *	be fixed up in the init func.
- *
- *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most peripherals have dependencies on multiple clock
- *	domains. Many get their interface clocks from the L4 domain, but get
- *	functional clocks from fixed sources or other core domain derived
- *	clocks.
- */
-
-DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
-
-static struct clk osc_ck;
-
-static const struct clk_ops osc_ck_ops = {
-	.recalc_rate	= &omap2_osc_clk_recalc,
-};
-
-static struct clk_hw_omap osc_ck_hw = {
-	.hw = {
-		.clk = &osc_ck,
-	},
-};
-
-static struct clk osc_ck = {
-	.name	= "osc_ck",
-	.ops	= &osc_ck_ops,
-	.hw	= &osc_ck_hw.hw,
-	.flags	= CLK_IS_ROOT,
-};
-
-DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-static struct clk sys_ck;
-
-static const char *sys_ck_parent_names[] = {
-	"osc_ck",
-};
-
-static const struct clk_ops sys_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.recalc_rate	= &omap2xxx_sys_clk_recalc,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
-
-static struct dpll_data dpll_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.mult_mask	= OMAP24XX_DPLL_MULT_MASK,
-	.div1_mask	= OMAP24XX_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask	= OMAP24XX_EN_DPLL_MASK,
-	.max_multiplier	= 1023,
-	.min_divider	= 1,
-	.max_divider	= 16,
-};
-
-static struct clk dpll_ck;
-
-static const char *dpll_ck_parent_names[] = {
-	"sys_ck",
-};
-
-static const struct clk_ops dpll_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.get_parent	= &omap2_init_dpll_parent,
-	.recalc_rate	= &omap2_dpllcore_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap2_reprogram_dpllcore,
-};
-
-static struct clk_hw_omap dpll_ck_hw = {
-	.hw = {
-		.clk = &dpll_ck,
-	},
-	.ops		= &clkhwops_omap2xxx_dpll,
-	.dpll_data	= &dpll_dd,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
-
-static struct clk core_ck;
-
-static const char *core_ck_parent_names[] = {
-	"dpll_ck",
-};
-
-static const struct clk_ops core_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-
-DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
-		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-		   OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
-		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-		   OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk aes_ick;
-
-static const char *aes_ick_parent_names[] = {
-	"l4_ck",
-};
-
-static const struct clk_ops aes_ick_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes_ick_hw = {
-	.hw = {
-		.clk = &aes_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk apll54_ck;
-
-static const struct clk_ops apll54_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_clk_apll54_enable,
-	.disable	= &omap2_clk_apll54_disable,
-	.recalc_rate	= &omap2_clk_apll54_recalc,
-};
-
-static struct clk_hw_omap apll54_ck_hw = {
-	.hw = {
-		.clk = &apll54_ck,
-	},
-	.ops		= &clkhwops_apll54,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
-
-static struct clk apll96_ck;
-
-static const struct clk_ops apll96_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_clk_apll96_enable,
-	.disable	= &omap2_clk_apll96_disable,
-	.recalc_rate	= &omap2_clk_apll96_recalc,
-};
-
-static struct clk_hw_omap apll96_ck_hw = {
-	.hw = {
-		.clk = &apll96_ck,
-	},
-	.ops		= &clkhwops_apll96,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
-
-static struct clk func_96m_ck;
-
-static const char *func_96m_ck_parent_names[] = {
-	"apll96_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(func_96m_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(func_96m_ck, func_96m_ck_parent_names, core_ck_ops);
-
-static struct clk cam_fck;
-
-static const char *cam_fck_parent_names[] = {
-	"func_96m_ck",
-};
-
-static struct clk_hw_omap cam_fck_hw = {
-	.hw = {
-		.clk = &cam_fck,
-	},
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk cam_ick;
-
-static struct clk_hw_omap cam_ick_hw = {
-	.hw = {
-		.clk = &cam_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk des_ick;
-
-static struct clk_hw_omap des_ick_hw = {
-	.hw = {
-		.clk = &des_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate dsp_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel dsp_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *dsp_fck_parent_names[] = {
-	"core_ck",
-};
-
-static const struct clk_ops dsp_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-			 OMAP24XX_CLKSEL_DSP_MASK,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
-			 dsp_fck_parent_names, dsp_fck_ops);
-
-static const struct clksel dsp_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
-	{ .parent = NULL },
-};
-
-static const char *dsp_ick_parent_names[] = {
-	"dsp_fck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_ick, "dsp_clkdm", dsp_ick_clksel,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-			 OMAP24XX_CLKSEL_DSP_IF_MASK,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
-			 OMAP2420_EN_DSP_IPI_SHIFT, &clkhwops_iclk_wait,
-			 dsp_ick_parent_names, dsp_fck_ops);
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
-	{ .parent = &sys_ck, .rates = dss1_fck_sys_rates },
-	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *dss1_fck_parent_names[] = {
-	"sys_ck", "core_ck",
-};
-
-static struct clk dss1_fck;
-
-static const struct clk_ops dss1_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_DSS1_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_DSS1_SHIFT, NULL,
-			 dss1_fck_parent_names, dss1_fck_ops);
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel func_48m_clksel[] = {
-	{ .parent = &apll96_ck, .rates = func_48m_apll96_rates },
-	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
-	{ .parent = NULL },
-};
-
-static const char *func_48m_ck_parent_names[] = {
-	"apll96_ck", "alt_ck",
-};
-
-static struct clk func_48m_ck;
-
-static const struct clk_ops func_48m_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-static struct clk_hw_omap func_48m_ck_hw = {
-	.hw = {
-		.clk = &func_48m_ck,
-	},
-	.clksel		= func_48m_clksel,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
-
-static const struct clksel dss2_fck_clksel[] = {
-	{ .parent = &sys_ck, .rates = dss2_fck_sys_rates },
-	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
-	{ .parent = NULL },
-};
-
-static const char *dss2_fck_parent_names[] = {
-	"sys_ck", "func_48m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_DSS2_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_DSS2_SHIFT, NULL,
-			 dss2_fck_parent_names, dss1_fck_ops);
-
-static const char *func_54m_ck_parent_names[] = {
-	"apll54_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
-	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	       OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH,
-	       0x0, NULL);
-
-static struct clk dss_54m_fck;
-
-static const char *dss_54m_fck_parent_names[] = {
-	"func_54m_ck",
-};
-
-static struct clk_hw_omap dss_54m_fck_hw = {
-	.hw = {
-		.clk = &dss_54m_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
-
-static struct clk dss_ick;
-
-static struct clk_hw_omap dss_ick_hw = {
-	.hw = {
-		.clk = &dss_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk eac_fck;
-
-static struct clk_hw_omap eac_fck_hw = {
-	.hw = {
-		.clk = &eac_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(eac_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk eac_ick;
-
-static struct clk_hw_omap eac_ick_hw = {
-	.hw = {
-		.clk = &eac_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(eac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk emul_ck;
-
-static struct clk_hw_omap emul_ck_hw = {
-	.hw = {
-		.clk = &emul_ck,
-	},
-	.enable_reg	= OMAP2420_PRCM_CLKEMUL_CTRL,
-	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
-
-static struct clk fac_fck;
-
-static const char *fac_fck_parent_names[] = {
-	"func_12m_ck",
-};
-
-static struct clk_hw_omap fac_fck_hw = {
-	.hw = {
-		.clk = &fac_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk fac_ick;
-
-static struct clk_hw_omap fac_ick_hw = {
-	.hw = {
-		.clk = &fac_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel gfx_fck_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
-	{ .parent = NULL },
-};
-
-static const char *gfx_2d_fck_parent_names[] = {
-	"core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-			 OMAP_CLKSEL_GFX_MASK,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
-			 gfx_2d_fck_parent_names, dsp_fck_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-			 OMAP_CLKSEL_GFX_MASK,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
-			 gfx_2d_fck_parent_names, dsp_fck_ops);
-
-static struct clk gfx_ick;
-
-static const char *gfx_ick_parent_names[] = {
-	"core_l3_ck",
-};
-
-static struct clk_hw_omap gfx_ick_hw = {
-	.hw = {
-		.clk = &gfx_ick,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.clkdm_name	= "gfx_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk gpios_fck;
-
-static const char *gpios_fck_parent_names[] = {
-	"func_32k_ck",
-};
-
-static struct clk_hw_omap gpios_fck_hw = {
-	.hw = {
-		.clk = &gpios_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk gpios_ick;
-
-static const char *gpios_ick_parent_names[] = {
-	"sys_ck",
-};
-
-static struct clk_hw_omap gpios_ick_hw = {
-	.hw = {
-		.clk = &gpios_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk gpmc_fck;
-
-static struct clk_hw_omap gpmc_fck_hw = {
-	.hw = {
-		.clk = &gpmc_fck,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
-
-static const struct clksel_rate gpt_alt_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
-	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
-	{ .parent = &sys_ck, .rates = gpt_sys_rates },
-	{ .parent = &alt_ck, .rates = gpt_alt_rates },
-	{ .parent = NULL },
-};
-
-static const char *gpt10_fck_parent_names[] = {
-	"func_32k_ck", "sys_ck", "alt_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT10_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt10_ick;
-
-static struct clk_hw_omap gpt10_ick_hw = {
-	.hw = {
-		.clk = &gpt10_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT11_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt11_ick;
-
-static struct clk_hw_omap gpt11_ick_hw = {
-	.hw = {
-		.clk = &gpt11_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT12_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt12_ick;
-
-static struct clk_hw_omap gpt12_ick_hw = {
-	.hw = {
-		.clk = &gpt12_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clk_ops gpt1_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_GPT1_MASK,
-			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, gpt1_fck_ops);
-
-static struct clk gpt1_ick;
-
-static struct clk_hw_omap gpt1_ick_hw = {
-	.hw = {
-		.clk = &gpt1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT2_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt2_ick;
-
-static struct clk_hw_omap gpt2_ick_hw = {
-	.hw = {
-		.clk = &gpt2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT3_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt3_ick;
-
-static struct clk_hw_omap gpt3_ick_hw = {
-	.hw = {
-		.clk = &gpt3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT4_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt4_ick;
-
-static struct clk_hw_omap gpt4_ick_hw = {
-	.hw = {
-		.clk = &gpt4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT5_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt5_ick;
-
-static struct clk_hw_omap gpt5_ick_hw = {
-	.hw = {
-		.clk = &gpt5_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT6_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt6_ick;
-
-static struct clk_hw_omap gpt6_ick_hw = {
-	.hw = {
-		.clk = &gpt6_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT7_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt7_ick;
-
-static struct clk_hw_omap gpt7_ick_hw = {
-	.hw = {
-		.clk = &gpt7_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT8_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt8_ick;
-
-static struct clk_hw_omap gpt8_ick_hw = {
-	.hw = {
-		.clk = &gpt8_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT9_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt9_ick;
-
-static struct clk_hw_omap gpt9_ick_hw = {
-	.hw = {
-		.clk = &gpt9_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk hdq_fck;
-
-static struct clk_hw_omap hdq_fck_hw = {
-	.hw = {
-		.clk = &hdq_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk hdq_ick;
-
-static struct clk_hw_omap hdq_ick_hw = {
-	.hw = {
-		.clk = &hdq_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c1_fck;
-
-static struct clk_hw_omap i2c1_fck_hw = {
-	.hw = {
-		.clk = &i2c1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk i2c1_ick;
-
-static struct clk_hw_omap i2c1_ick_hw = {
-	.hw = {
-		.clk = &i2c1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c2_fck;
-
-static struct clk_hw_omap i2c2_fck_hw = {
-	.hw = {
-		.clk = &i2c2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk i2c2_ick;
-
-static struct clk_hw_omap i2c2_ick_hw = {
-	.hw = {
-		.clk = &i2c2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(iva1_ifck, "iva1_clkdm", dsp_fck_clksel,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-			 OMAP2420_CLKSEL_IVA_MASK,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-			 OMAP2420_EN_IVA_COP_SHIFT, &clkhwops_wait,
-			 dsp_fck_parent_names, dsp_fck_ops);
-
-static struct clk iva1_mpu_int_ifck;
-
-static const char *iva1_mpu_int_ifck_parent_names[] = {
-	"iva1_ifck",
-};
-
-static const struct clk_ops iva1_mpu_int_ifck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap_fixed_divisor_recalc,
-};
-
-static struct clk_hw_omap iva1_mpu_int_ifck_hw = {
-	.hw = {
-		.clk = &iva1_mpu_int_ifck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP2420_EN_IVA_MPU_SHIFT,
-	.clkdm_name	= "iva1_clkdm",
-	.fixed_div	= 2,
-};
-
-DEFINE_STRUCT_CLK(iva1_mpu_int_ifck, iva1_mpu_int_ifck_parent_names,
-		  iva1_mpu_int_ifck_ops);
-
-static struct clk mailboxes_ick;
-
-static struct clk_hw_omap mailboxes_ick_hw = {
-	.hw = {
-		.clk = &mailboxes_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
-	{ .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL },
-};
-
-static const char *mcbsp1_fck_parent_names[] = {
-	"func_96m_ck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-			 OMAP2_MCBSP1_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp1_ick;
-
-static struct clk_hw_omap mcbsp1_ick_hw = {
-	.hw = {
-		.clk = &mcbsp1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-			 OMAP2_MCBSP2_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp2_ick;
-
-static struct clk_hw_omap mcbsp2_ick_hw = {
-	.hw = {
-		.clk = &mcbsp2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_fck;
-
-static const char *mcspi1_fck_parent_names[] = {
-	"func_48m_ck",
-};
-
-static struct clk_hw_omap mcspi1_fck_hw = {
-	.hw = {
-		.clk = &mcspi1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_ick;
-
-static struct clk_hw_omap mcspi1_ick_hw = {
-	.hw = {
-		.clk = &mcspi1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_fck;
-
-static struct clk_hw_omap mcspi2_fck_hw = {
-	.hw = {
-		.clk = &mcspi2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_ick;
-
-static struct clk_hw_omap mcspi2_ick_hw = {
-	.hw = {
-		.clk = &mcspi2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmc_fck;
-
-static struct clk_hw_omap mmc_fck_hw = {
-	.hw = {
-		.clk = &mmc_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmc_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmc_ick;
-
-static struct clk_hw_omap mmc_ick_hw = {
-	.hw = {
-		.clk = &mmc_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmc_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
-		   OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
-		   OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk mpu_wdt_fck;
-
-static struct clk_hw_omap mpu_wdt_fck_hw = {
-	.hw = {
-		.clk = &mpu_wdt_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk mpu_wdt_ick;
-
-static struct clk_hw_omap mpu_wdt_ick_hw = {
-	.hw = {
-		.clk = &mpu_wdt_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk mspro_fck;
-
-static struct clk_hw_omap mspro_fck_hw = {
-	.hw = {
-		.clk = &mspro_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mspro_ick;
-
-static struct clk_hw_omap mspro_ick_hw = {
-	.hw = {
-		.clk = &mspro_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk omapctrl_ick;
-
-static struct clk_hw_omap omapctrl_ick_hw = {
-	.hw = {
-		.clk = &omapctrl_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk pka_ick;
-
-static struct clk_hw_omap pka_ick_hw = {
-	.hw = {
-		.clk = &pka_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk rng_ick;
-
-static struct clk_hw_omap rng_ick_hw = {
-	.hw = {
-		.clk = &rng_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk sdma_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
-DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdma_ick;
-
-static struct clk_hw_omap sdma_ick_hw = {
-	.hw = {
-		.clk = &sdma_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdrc_ick;
-
-static struct clk_hw_omap sdrc_ick_hw = {
-	.hw = {
-		.clk = &sdrc_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sha_ick;
-
-static struct clk_hw_omap sha_ick_hw = {
-	.hw = {
-		.clk = &sha_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk ssi_l4_ick;
-
-static struct clk_hw_omap ssi_l4_ick_hw = {
-	.hw = {
-		.clk = &ssi_l4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *ssi_ssr_sst_fck_parent_names[] = {
-	"core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
-			 ssi_ssr_sst_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_SSI_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-			 OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
-			 ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
-
-static struct clk sync_32k_ick;
-
-static struct clk_hw_omap sync_32k_ick_hw = {
-	.hw = {
-		.clk = &sync_32k_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_clkout_src_core_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
-	{ .parent = &core_ck, .rates = common_clkout_src_core_rates },
-	{ .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
-	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
-	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
-	{ .parent = NULL },
-};
-
-static const char *sys_clkout_src_parent_names[] = {
-	"core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
-			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
-			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
-			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
-		   OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
-		   OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout2_src, "wkup_clkdm",
-			 common_clkout_src_clksel, OMAP2420_PRCM_CLKOUT_CTRL,
-			 OMAP2420_CLKOUT2_SOURCE_MASK,
-			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_EN_SHIFT,
-			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout2, "sys_clkout2_src", &sys_clkout2_src, 0x0,
-		   OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_DIV_SHIFT,
-		   OMAP2420_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-static struct clk uart1_fck;
-
-static struct clk_hw_omap uart1_fck_hw = {
-	.hw = {
-		.clk = &uart1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart1_ick;
-
-static struct clk_hw_omap uart1_ick_hw = {
-	.hw = {
-		.clk = &uart1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart2_fck;
-
-static struct clk_hw_omap uart2_fck_hw = {
-	.hw = {
-		.clk = &uart2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart2_ick;
-
-static struct clk_hw_omap uart2_ick_hw = {
-	.hw = {
-		.clk = &uart2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart3_fck;
-
-static struct clk_hw_omap uart3_fck_hw = {
-	.hw = {
-		.clk = &uart3_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart3_ick;
-
-static struct clk_hw_omap uart3_ick_hw = {
-	.hw = {
-		.clk = &uart3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk usb_fck;
-
-static struct clk_hw_omap usb_fck_hw = {
-	.hw = {
-		.clk = &usb_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
-	{ .parent = NULL },
-};
-
-static const char *usb_l4_ick_parent_names[] = {
-	"core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_USB_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-			 OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
-			 usb_l4_ick_parent_names, dsp_fck_ops);
-
-static struct clk virt_prcm_set;
-
-static const char *virt_prcm_set_parent_names[] = {
-	"mpu_ck",
-};
-
-static const struct clk_ops virt_prcm_set_ops = {
-	.recalc_rate	= &omap2_table_mpu_recalc,
-	.set_rate	= &omap2_select_table_rate,
-	.round_rate	= &omap2_round_to_table_rate,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
-DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
-
-static const struct clksel_rate vlynq_fck_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate vlynq_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_242X },
-	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
-	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
-	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 9, .val = 9, .flags = RATE_IN_242X },
-	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
-	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
-	{ .div = 18, .val = 18, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel vlynq_fck_clksel[] = {
-	{ .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
-	{ .parent = &core_ck, .rates = vlynq_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *vlynq_fck_parent_names[] = {
-	"func_96m_ck", "core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(vlynq_fck, "core_l3_clkdm", vlynq_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP2420_CLKSEL_VLYNQ_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP2420_EN_VLYNQ_SHIFT, &clkhwops_wait,
-			 vlynq_fck_parent_names, dss1_fck_ops);
-
-static struct clk vlynq_ick;
-
-static struct clk_hw_omap vlynq_ick_hw = {
-	.hw = {
-		.clk = &vlynq_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(vlynq_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt1_ick;
-
-static struct clk_hw_omap wdt1_ick_hw = {
-	.hw = {
-		.clk = &wdt1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt3_fck;
-
-static struct clk_hw_omap wdt3_fck_hw = {
-	.hw = {
-		.clk = &wdt3_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt3_ick;
-
-static struct clk_hw_omap wdt3_ick_hw = {
-	.hw = {
-		.clk = &wdt3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt4_fck;
-
-static struct clk_hw_omap wdt4_fck_hw = {
-	.hw = {
-		.clk = &wdt4_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt4_ick;
-
-static struct clk_hw_omap wdt4_ick_hw = {
-	.hw = {
-		.clk = &wdt4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2420_clks[] = {
-	/* external root sources */
-	CLK(NULL,	"func_32k_ck",	&func_32k_ck),
-	CLK(NULL,	"secure_32k_ck", &secure_32k_ck),
-	CLK(NULL,	"osc_ck",	&osc_ck),
-	CLK(NULL,	"sys_ck",	&sys_ck),
-	CLK(NULL,	"alt_ck",	&alt_ck),
-	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks),
-	/* internal analog sources */
-	CLK(NULL,	"dpll_ck",	&dpll_ck),
-	CLK(NULL,	"apll96_ck",	&apll96_ck),
-	CLK(NULL,	"apll54_ck",	&apll54_ck),
-	/* internal prcm root sources */
-	CLK(NULL,	"func_54m_ck",	&func_54m_ck),
-	CLK(NULL,	"core_ck",	&core_ck),
-	CLK(NULL,	"func_96m_ck",	&func_96m_ck),
-	CLK(NULL,	"func_48m_ck",	&func_48m_ck),
-	CLK(NULL,	"func_12m_ck",	&func_12m_ck),
-	CLK(NULL,	"sys_clkout_src", &sys_clkout_src),
-	CLK(NULL,	"sys_clkout",	&sys_clkout),
-	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src),
-	CLK(NULL,	"sys_clkout2",	&sys_clkout2),
-	CLK(NULL,	"emul_ck",	&emul_ck),
-	/* mpu domain clocks */
-	CLK(NULL,	"mpu_ck",	&mpu_ck),
-	/* dsp domain clocks */
-	CLK(NULL,	"dsp_fck",	&dsp_fck),
-	CLK(NULL,	"dsp_ick",	&dsp_ick),
-	CLK(NULL,	"iva1_ifck",	&iva1_ifck),
-	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck),
-	/* GFX domain clocks */
-	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck),
-	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck),
-	CLK(NULL,	"gfx_ick",	&gfx_ick),
-	/* DSS domain clocks */
-	CLK("omapdss_dss",	"ick",		&dss_ick),
-	CLK(NULL,	"dss_ick",		&dss_ick),
-	CLK(NULL,	"dss1_fck",		&dss1_fck),
-	CLK(NULL,	"dss2_fck",	&dss2_fck),
-	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck),
-	/* L3 domain clocks */
-	CLK(NULL,	"core_l3_ck",	&core_l3_ck),
-	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck),
-	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick),
-	/* L4 domain clocks */
-	CLK(NULL,	"l4_ck",	&l4_ck),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick),
-	/* virtual meta-group clock */
-	CLK(NULL,	"virt_prcm_set", &virt_prcm_set),
-	/* general l4 interface ck, multi-parent functional clk */
-	CLK(NULL,	"gpt1_ick",	&gpt1_ick),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck),
-	CLK(NULL,	"gpt2_ick",	&gpt2_ick),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck),
-	CLK(NULL,	"gpt3_ick",	&gpt3_ick),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck),
-	CLK(NULL,	"gpt4_ick",	&gpt4_ick),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck),
-	CLK(NULL,	"gpt5_ick",	&gpt5_ick),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck),
-	CLK(NULL,	"gpt6_ick",	&gpt6_ick),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck),
-	CLK(NULL,	"gpt7_ick",	&gpt7_ick),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck),
-	CLK(NULL,	"gpt8_ick",	&gpt8_ick),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck),
-	CLK(NULL,	"gpt9_ick",	&gpt9_ick),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck),
-	CLK(NULL,	"gpt10_ick",	&gpt10_ick),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck),
-	CLK(NULL,	"gpt11_ick",	&gpt11_ick),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck),
-	CLK(NULL,	"gpt12_ick",	&gpt12_ick),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck),
-	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick),
-	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick),
-	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck),
-	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick),
-	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick),
-	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck),
-	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick),
-	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick),
-	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck),
-	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick),
-	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick),
-	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck),
-	CLK(NULL,	"uart1_ick",	&uart1_ick),
-	CLK(NULL,	"uart1_fck",	&uart1_fck),
-	CLK(NULL,	"uart2_ick",	&uart2_ick),
-	CLK(NULL,	"uart2_fck",	&uart2_fck),
-	CLK(NULL,	"uart3_ick",	&uart3_ick),
-	CLK(NULL,	"uart3_fck",	&uart3_fck),
-	CLK(NULL,	"gpios_ick",	&gpios_ick),
-	CLK(NULL,	"gpios_fck",	&gpios_fck),
-	CLK("omap_wdt",	"ick",		&mpu_wdt_ick),
-	CLK(NULL,	"mpu_wdt_ick",		&mpu_wdt_ick),
-	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck),
-	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick),
-	CLK(NULL,	"wdt1_ick",	&wdt1_ick),
-	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick),
-	CLK("omap24xxcam", "fck",	&cam_fck),
-	CLK(NULL,	"cam_fck",	&cam_fck),
-	CLK("omap24xxcam", "ick",	&cam_ick),
-	CLK(NULL,	"cam_ick",	&cam_ick),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick),
-	CLK(NULL,	"wdt4_ick",	&wdt4_ick),
-	CLK(NULL,	"wdt4_fck",	&wdt4_fck),
-	CLK(NULL,	"wdt3_ick",	&wdt3_ick),
-	CLK(NULL,	"wdt3_fck",	&wdt3_fck),
-	CLK(NULL,	"mspro_ick",	&mspro_ick),
-	CLK(NULL,	"mspro_fck",	&mspro_fck),
-	CLK("mmci-omap.0", "ick",	&mmc_ick),
-	CLK(NULL,	"mmc_ick",	&mmc_ick),
-	CLK("mmci-omap.0", "fck",	&mmc_fck),
-	CLK(NULL,	"mmc_fck",	&mmc_fck),
-	CLK(NULL,	"fac_ick",	&fac_ick),
-	CLK(NULL,	"fac_fck",	&fac_fck),
-	CLK(NULL,	"eac_ick",	&eac_ick),
-	CLK(NULL,	"eac_fck",	&eac_fck),
-	CLK("omap_hdq.0", "ick",	&hdq_ick),
-	CLK(NULL,	"hdq_ick",	&hdq_ick),
-	CLK("omap_hdq.0", "fck",	&hdq_fck),
-	CLK(NULL,	"hdq_fck",	&hdq_fck),
-	CLK("omap_i2c.1", "ick",	&i2c1_ick),
-	CLK(NULL,	"i2c1_ick",	&i2c1_ick),
-	CLK(NULL,	"i2c1_fck",	&i2c1_fck),
-	CLK("omap_i2c.2", "ick",	&i2c2_ick),
-	CLK(NULL,	"i2c2_ick",	&i2c2_ick),
-	CLK(NULL,	"i2c2_fck",	&i2c2_fck),
-	CLK(NULL,	"gpmc_fck",	&gpmc_fck),
-	CLK(NULL,	"sdma_fck",	&sdma_fck),
-	CLK(NULL,	"sdma_ick",	&sdma_ick),
-	CLK(NULL,	"sdrc_ick",	&sdrc_ick),
-	CLK(NULL,	"vlynq_ick",	&vlynq_ick),
-	CLK(NULL,	"vlynq_fck",	&vlynq_fck),
-	CLK(NULL,	"des_ick",	&des_ick),
-	CLK("omap-sham",	"ick",	&sha_ick),
-	CLK(NULL,	"sha_ick",	&sha_ick),
-	CLK("omap_rng",	"ick",		&rng_ick),
-	CLK(NULL,	"rng_ick",		&rng_ick),
-	CLK("omap-aes",	"ick",	&aes_ick),
-	CLK(NULL,	"aes_ick",	&aes_ick),
-	CLK(NULL,	"pka_ick",	&pka_ick),
-	CLK(NULL,	"usb_fck",	&usb_fck),
-	CLK("musb-hdrc",	"fck",	&osc_ck),
-	CLK(NULL,	"timer_32k_ck",	&func_32k_ck),
-	CLK(NULL,	"timer_sys_ck",	&sys_ck),
-	CLK(NULL,	"timer_ext_ck",	&alt_ck),
-	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set),
-};
-
-
-static const char *enable_init_clks[] = {
-	"apll96_ck",
-	"apll54_ck",
-	"sync_32k_ick",
-	"omapctrl_ick",
-	"gpmc_fck",
-	"sdrc_ick",
-};
-
-/*
- * init code
- */
-
-int __init omap2420_clk_init(void)
-{
-	prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
-	cpu_mask = RATE_IN_242X;
-	rate_table = omap2420_rate_table;
-
-	omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
-
-	omap2xxx_clkt_vps_check_bootloader_rates();
-
-	omap_clocks_register(omap2420_clks, ARRAY_SIZE(omap2420_clks));
-
-	omap2xxx_clkt_vps_late_init();
-
-	omap2_clk_disable_autoidle_all();
-
-	omap2_clk_enable_init_clocks(enable_init_clks,
-				     ARRAY_SIZE(enable_init_clks));
-
-	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
-		(clk_get_rate(&sys_ck) / 1000000),
-		(clk_get_rate(&sys_ck) / 100000) % 10,
-		(clk_get_rate(&dpll_ck) / 1000000),
-		(clk_get_rate(&mpu_ck) / 1000000));
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/cclock2430_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cclock2430_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/cclock2430_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cclock2430_data.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2048 +0,0 @@
-/*
- * OMAP2430 clock data
- *
- * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
-
-/*
- * 2430 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- *	many cases the parent is selectable. The set parent calls will
- *	also switch sources.
- *
- *	Several sources are given initial rates which may be wrong, this will
- *	be fixed up in the init func.
- *
- *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most peripherals have dependencies on multiple clock
- *	domains. Many get their interface clocks from the L4 domain, but get
- *	functional clocks from fixed sources or other core domain derived
- *	clocks.
- */
-
-DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
-
-static struct clk osc_ck;
-
-static const struct clk_ops osc_ck_ops = {
-	.enable		= &omap2_enable_osc_ck,
-	.disable	= omap2_disable_osc_ck,
-	.recalc_rate	= &omap2_osc_clk_recalc,
-};
-
-static struct clk_hw_omap osc_ck_hw = {
-	.hw = {
-		.clk = &osc_ck,
-	},
-};
-
-static struct clk osc_ck = {
-	.name	= "osc_ck",
-	.ops	= &osc_ck_ops,
-	.hw	= &osc_ck_hw.hw,
-	.flags	= CLK_IS_ROOT,
-};
-
-DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-static struct clk sys_ck;
-
-static const char *sys_ck_parent_names[] = {
-	"osc_ck",
-};
-
-static const struct clk_ops sys_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.recalc_rate	= &omap2xxx_sys_clk_recalc,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
-
-static struct dpll_data dpll_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.mult_mask	= OMAP24XX_DPLL_MULT_MASK,
-	.div1_mask	= OMAP24XX_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask	= OMAP24XX_EN_DPLL_MASK,
-	.max_multiplier	= 1023,
-	.min_divider	= 1,
-	.max_divider	= 16,
-};
-
-static struct clk dpll_ck;
-
-static const char *dpll_ck_parent_names[] = {
-	"sys_ck",
-};
-
-static const struct clk_ops dpll_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.get_parent	= &omap2_init_dpll_parent,
-	.recalc_rate	= &omap2_dpllcore_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap2_reprogram_dpllcore,
-};
-
-static struct clk_hw_omap dpll_ck_hw = {
-	.hw = {
-		.clk = &dpll_ck,
-	},
-	.ops		= &clkhwops_omap2xxx_dpll,
-	.dpll_data	= &dpll_dd,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
-
-static struct clk core_ck;
-
-static const char *core_ck_parent_names[] = {
-	"dpll_ck",
-};
-
-static const struct clk_ops core_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-
-DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
-		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-		   OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
-		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-		   OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk aes_ick;
-
-static const char *aes_ick_parent_names[] = {
-	"l4_ck",
-};
-
-static const struct clk_ops aes_ick_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes_ick_hw = {
-	.hw = {
-		.clk = &aes_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk apll54_ck;
-
-static const struct clk_ops apll54_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_clk_apll54_enable,
-	.disable	= &omap2_clk_apll54_disable,
-	.recalc_rate	= &omap2_clk_apll54_recalc,
-};
-
-static struct clk_hw_omap apll54_ck_hw = {
-	.hw = {
-		.clk = &apll54_ck,
-	},
-	.ops		= &clkhwops_apll54,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
-
-static struct clk apll96_ck;
-
-static const struct clk_ops apll96_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_clk_apll96_enable,
-	.disable	= &omap2_clk_apll96_disable,
-	.recalc_rate	= &omap2_clk_apll96_recalc,
-};
-
-static struct clk_hw_omap apll96_ck_hw = {
-	.hw = {
-		.clk = &apll96_ck,
-	},
-	.ops		= &clkhwops_apll96,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
-
-static const char *func_96m_ck_parent_names[] = {
-	"apll96_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_96m_ck, func_96m_ck_parent_names, NULL, 0x0,
-	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP2430_96M_SOURCE_SHIFT,
-	       OMAP2430_96M_SOURCE_WIDTH, 0x0, NULL);
-
-static struct clk cam_fck;
-
-static const char *cam_fck_parent_names[] = {
-	"func_96m_ck",
-};
-
-static struct clk_hw_omap cam_fck_hw = {
-	.hw = {
-		.clk = &cam_fck,
-	},
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk cam_ick;
-
-static struct clk_hw_omap cam_ick_hw = {
-	.hw = {
-		.clk = &cam_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk des_ick;
-
-static struct clk_hw_omap des_ick_hw = {
-	.hw = {
-		.clk = &des_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate dsp_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dsp_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *dsp_fck_parent_names[] = {
-	"core_ck",
-};
-
-static struct clk dsp_fck;
-
-static const struct clk_ops dsp_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-			 OMAP24XX_CLKSEL_DSP_MASK,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
-			 dsp_fck_parent_names, dsp_fck_ops);
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
-	{ .parent = &sys_ck, .rates = dss1_fck_sys_rates },
-	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *dss1_fck_parent_names[] = {
-	"sys_ck", "core_ck",
-};
-
-static const struct clk_ops dss1_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_DSS1_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_DSS1_SHIFT, NULL,
-			 dss1_fck_parent_names, dss1_fck_ops);
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel func_48m_clksel[] = {
-	{ .parent = &apll96_ck, .rates = func_48m_apll96_rates },
-	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
-	{ .parent = NULL },
-};
-
-static const char *func_48m_ck_parent_names[] = {
-	"apll96_ck", "alt_ck",
-};
-
-static struct clk func_48m_ck;
-
-static const struct clk_ops func_48m_ck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-static struct clk_hw_omap func_48m_ck_hw = {
-	.hw = {
-		.clk = &func_48m_ck,
-	},
-	.clksel		= func_48m_clksel,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
-
-static const struct clksel dss2_fck_clksel[] = {
-	{ .parent = &sys_ck, .rates = dss2_fck_sys_rates },
-	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
-	{ .parent = NULL },
-};
-
-static const char *dss2_fck_parent_names[] = {
-	"sys_ck", "func_48m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_DSS2_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_DSS2_SHIFT, NULL,
-			 dss2_fck_parent_names, dss1_fck_ops);
-
-static const char *func_54m_ck_parent_names[] = {
-	"apll54_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
-	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	       OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH, 0x0, NULL);
-
-static struct clk dss_54m_fck;
-
-static const char *dss_54m_fck_parent_names[] = {
-	"func_54m_ck",
-};
-
-static struct clk_hw_omap dss_54m_fck_hw = {
-	.hw = {
-		.clk = &dss_54m_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
-
-static struct clk dss_ick;
-
-static struct clk_hw_omap dss_ick_hw = {
-	.hw = {
-		.clk = &dss_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk emul_ck;
-
-static struct clk_hw_omap emul_ck_hw = {
-	.hw = {
-		.clk = &emul_ck,
-	},
-	.enable_reg	= OMAP2430_PRCM_CLKEMUL_CTRL,
-	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
-
-static struct clk fac_fck;
-
-static const char *fac_fck_parent_names[] = {
-	"func_12m_ck",
-};
-
-static struct clk_hw_omap fac_fck_hw = {
-	.hw = {
-		.clk = &fac_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk fac_ick;
-
-static struct clk_hw_omap fac_ick_hw = {
-	.hw = {
-		.clk = &fac_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel gfx_fck_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
-	{ .parent = NULL },
-};
-
-static const char *gfx_2d_fck_parent_names[] = {
-	"core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-			 OMAP_CLKSEL_GFX_MASK,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
-			 gfx_2d_fck_parent_names, dsp_fck_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-			 OMAP_CLKSEL_GFX_MASK,
-			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
-			 gfx_2d_fck_parent_names, dsp_fck_ops);
-
-static struct clk gfx_ick;
-
-static const char *gfx_ick_parent_names[] = {
-	"core_l3_ck",
-};
-
-static struct clk_hw_omap gfx_ick_hw = {
-	.hw = {
-		.clk = &gfx_ick,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.clkdm_name	= "gfx_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk gpio5_fck;
-
-static const char *gpio5_fck_parent_names[] = {
-	"func_32k_ck",
-};
-
-static struct clk_hw_omap gpio5_fck_hw = {
-	.hw = {
-		.clk = &gpio5_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk gpio5_ick;
-
-static struct clk_hw_omap gpio5_ick_hw = {
-	.hw = {
-		.clk = &gpio5_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk gpios_fck;
-
-static struct clk_hw_omap gpios_fck_hw = {
-	.hw = {
-		.clk = &gpios_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk gpios_ick;
-
-static const char *gpios_ick_parent_names[] = {
-	"sys_ck",
-};
-
-static struct clk_hw_omap gpios_ick_hw = {
-	.hw = {
-		.clk = &gpios_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk gpmc_fck;
-
-static struct clk_hw_omap gpmc_fck_hw = {
-	.hw = {
-		.clk = &gpmc_fck,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
-
-static const struct clksel_rate gpt_alt_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
-	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
-	{ .parent = &sys_ck, .rates = gpt_sys_rates },
-	{ .parent = &alt_ck, .rates = gpt_alt_rates },
-	{ .parent = NULL },
-};
-
-static const char *gpt10_fck_parent_names[] = {
-	"func_32k_ck", "sys_ck", "alt_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT10_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt10_ick;
-
-static struct clk_hw_omap gpt10_ick_hw = {
-	.hw = {
-		.clk = &gpt10_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT11_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt11_ick;
-
-static struct clk_hw_omap gpt11_ick_hw = {
-	.hw = {
-		.clk = &gpt11_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT12_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt12_ick;
-
-static struct clk_hw_omap gpt12_ick_hw = {
-	.hw = {
-		.clk = &gpt12_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clk_ops gpt1_fck_ops = {
-	.init		= &omap2_init_clk_clkdm,
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.recalc_rate	= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-	.get_parent	= &omap2_clksel_find_parent_index,
-	.set_parent	= &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_GPT1_MASK,
-			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-			 OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, gpt1_fck_ops);
-
-static struct clk gpt1_ick;
-
-static struct clk_hw_omap gpt1_ick_hw = {
-	.hw = {
-		.clk = &gpt1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT2_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt2_ick;
-
-static struct clk_hw_omap gpt2_ick_hw = {
-	.hw = {
-		.clk = &gpt2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT3_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt3_ick;
-
-static struct clk_hw_omap gpt3_ick_hw = {
-	.hw = {
-		.clk = &gpt3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT4_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt4_ick;
-
-static struct clk_hw_omap gpt4_ick_hw = {
-	.hw = {
-		.clk = &gpt4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT5_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt5_ick;
-
-static struct clk_hw_omap gpt5_ick_hw = {
-	.hw = {
-		.clk = &gpt5_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT6_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt6_ick;
-
-static struct clk_hw_omap gpt6_ick_hw = {
-	.hw = {
-		.clk = &gpt6_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT7_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt7_ick;
-
-static struct clk_hw_omap gpt7_ick_hw = {
-	.hw = {
-		.clk = &gpt7_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk gpt8_fck;
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT8_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt8_ick;
-
-static struct clk_hw_omap gpt8_ick_hw = {
-	.hw = {
-		.clk = &gpt8_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-			 OMAP24XX_CLKSEL_GPT9_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
-			 gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt9_ick;
-
-static struct clk_hw_omap gpt9_ick_hw = {
-	.hw = {
-		.clk = &gpt9_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk hdq_fck;
-
-static struct clk_hw_omap hdq_fck_hw = {
-	.hw = {
-		.clk = &hdq_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk hdq_ick;
-
-static struct clk_hw_omap hdq_ick_hw = {
-	.hw = {
-		.clk = &hdq_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c1_ick;
-
-static struct clk_hw_omap i2c1_ick_hw = {
-	.hw = {
-		.clk = &i2c1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c2_ick;
-
-static struct clk_hw_omap i2c2_ick_hw = {
-	.hw = {
-		.clk = &i2c2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2chs1_fck;
-
-static struct clk_hw_omap i2chs1_fck_hw = {
-	.hw = {
-		.clk = &i2chs1_fck,
-	},
-	.ops		= &clkhwops_omap2430_i2chs_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_I2CHS1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2chs1_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk i2chs2_fck;
-
-static struct clk_hw_omap i2chs2_fck_hw = {
-	.hw = {
-		.clk = &i2chs2_fck,
-	},
-	.ops		= &clkhwops_omap2430_i2chs_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_I2CHS2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2chs2_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk icr_ick;
-
-static struct clk_hw_omap icr_ick_hw = {
-	.hw = {
-		.clk = &icr_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(icr_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel dsp_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
-	{ .parent = NULL },
-};
-
-static const char *iva2_1_ick_parent_names[] = {
-	"dsp_fck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(iva2_1_ick, "dsp_clkdm", dsp_ick_clksel,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-			 OMAP24XX_CLKSEL_DSP_IF_MASK,
-			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
-			 iva2_1_ick_parent_names, dsp_fck_ops);
-
-static struct clk mailboxes_ick;
-
-static struct clk_hw_omap mailboxes_ick_hw = {
-	.hw = {
-		.clk = &mailboxes_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
-	{ .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL },
-};
-
-static const char *mcbsp1_fck_parent_names[] = {
-	"func_96m_ck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-			 OMAP2_MCBSP1_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp1_ick;
-
-static struct clk_hw_omap mcbsp1_ick_hw = {
-	.hw = {
-		.clk = &mcbsp1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-			 OMAP2_MCBSP2_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-			 OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp2_ick;
-
-static struct clk_hw_omap mcbsp2_ick_hw = {
-	.hw = {
-		.clk = &mcbsp2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-			 OMAP2_MCBSP3_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-			 OMAP2430_EN_MCBSP3_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp3_ick;
-
-static struct clk_hw_omap mcbsp3_ick_hw = {
-	.hw = {
-		.clk = &mcbsp3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-			 OMAP2_MCBSP4_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-			 OMAP2430_EN_MCBSP4_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp4_ick;
-
-static struct clk_hw_omap mcbsp4_ick_hw = {
-	.hw = {
-		.clk = &mcbsp4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_fck_clksel,
-			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-			 OMAP2_MCBSP5_CLKS_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-			 OMAP2430_EN_MCBSP5_SHIFT, &clkhwops_wait,
-			 mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp5_ick;
-
-static struct clk_hw_omap mcbsp5_ick_hw = {
-	.hw = {
-		.clk = &mcbsp5_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp5_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_fck;
-
-static const char *mcspi1_fck_parent_names[] = {
-	"func_48m_ck",
-};
-
-static struct clk_hw_omap mcspi1_fck_hw = {
-	.hw = {
-		.clk = &mcspi1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_ick;
-
-static struct clk_hw_omap mcspi1_ick_hw = {
-	.hw = {
-		.clk = &mcspi1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_fck;
-
-static struct clk_hw_omap mcspi2_fck_hw = {
-	.hw = {
-		.clk = &mcspi2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_ick;
-
-static struct clk_hw_omap mcspi2_ick_hw = {
-	.hw = {
-		.clk = &mcspi2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi3_fck;
-
-static struct clk_hw_omap mcspi3_fck_hw = {
-	.hw = {
-		.clk = &mcspi3_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi3_ick;
-
-static struct clk_hw_omap mcspi3_ick_hw = {
-	.hw = {
-		.clk = &mcspi3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate mdm_ick_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
-	{ .div = 4, .val = 4, .flags = RATE_IN_243X },
-	{ .div = 6, .val = 6, .flags = RATE_IN_243X },
-	{ .div = 9, .val = 9, .flags = RATE_IN_243X },
-	{ .div = 0 }
-};
-
-static const struct clksel mdm_ick_clksel[] = {
-	{ .parent = &core_ck, .rates = mdm_ick_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *mdm_ick_parent_names[] = {
-	"core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mdm_ick, "mdm_clkdm", mdm_ick_clksel,
-			 OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
-			 OMAP2430_CLKSEL_MDM_MASK,
-			 OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
-			 OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
-			 &clkhwops_iclk_wait, mdm_ick_parent_names,
-			 dsp_fck_ops);
-
-static struct clk mdm_intc_ick;
-
-static struct clk_hw_omap mdm_intc_ick_hw = {
-	.hw = {
-		.clk = &mdm_intc_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mdm_intc_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mdm_osc_ck;
-
-static struct clk_hw_omap mdm_osc_ck_hw = {
-	.hw = {
-		.clk = &mdm_osc_ck,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP2430_EN_OSC_SHIFT,
-	.clkdm_name	= "mdm_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mdm_osc_ck, sys_ck_parent_names, aes_ick_ops);
-
-static struct clk mmchs1_fck;
-
-static struct clk_hw_omap mmchs1_fck_hw = {
-	.hw = {
-		.clk = &mmchs1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchs1_ick;
-
-static struct clk_hw_omap mmchs1_ick_hw = {
-	.hw = {
-		.clk = &mmchs1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmchs2_fck;
-
-static struct clk_hw_omap mmchs2_fck_hw = {
-	.hw = {
-		.clk = &mmchs2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchs2_ick;
-
-static struct clk_hw_omap mmchs2_ick_hw = {
-	.hw = {
-		.clk = &mmchs2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmchsdb1_fck;
-
-static struct clk_hw_omap mmchsdb1_fck_hw = {
-	.hw = {
-		.clk = &mmchsdb1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHSDB1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchsdb1_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchsdb2_fck;
-
-static struct clk_hw_omap mmchsdb2_fck_hw = {
-	.hw = {
-		.clk = &mmchsdb2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHSDB2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchsdb2_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
-		   OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
-		   OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
-		   CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk mpu_wdt_fck;
-
-static struct clk_hw_omap mpu_wdt_fck_hw = {
-	.hw = {
-		.clk = &mpu_wdt_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk mpu_wdt_ick;
-
-static struct clk_hw_omap mpu_wdt_ick_hw = {
-	.hw = {
-		.clk = &mpu_wdt_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk mspro_fck;
-
-static struct clk_hw_omap mspro_fck_hw = {
-	.hw = {
-		.clk = &mspro_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mspro_ick;
-
-static struct clk_hw_omap mspro_ick_hw = {
-	.hw = {
-		.clk = &mspro_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk omapctrl_ick;
-
-static struct clk_hw_omap omapctrl_ick_hw = {
-	.hw = {
-		.clk = &omapctrl_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk pka_ick;
-
-static struct clk_hw_omap pka_ick_hw = {
-	.hw = {
-		.clk = &pka_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk rng_ick;
-
-static struct clk_hw_omap rng_ick_hw = {
-	.hw = {
-		.clk = &rng_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk sdma_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
-DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdma_ick;
-
-static struct clk_hw_omap sdma_ick_hw = {
-	.hw = {
-		.clk = &sdma_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdrc_ick;
-
-static struct clk_hw_omap sdrc_ick_hw = {
-	.hw = {
-		.clk = &sdrc_ick,
-	},
-	.ops		= &clkhwops_iclk,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sha_ick;
-
-static struct clk_hw_omap sha_ick_hw = {
-	.hw = {
-		.clk = &sha_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk ssi_l4_ick;
-
-static struct clk_hw_omap ssi_l4_ick_hw = {
-	.hw = {
-		.clk = &ssi_l4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_243X },
-	{ .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static const char *ssi_ssr_sst_fck_parent_names[] = {
-	"core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
-			 ssi_ssr_sst_fck_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_SSI_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-			 OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
-			 ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
-
-static struct clk sync_32k_ick;
-
-static struct clk_hw_omap sync_32k_ick_hw = {
-	.hw = {
-		.clk = &sync_32k_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_clkout_src_core_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
-	{ .parent = &core_ck, .rates = common_clkout_src_core_rates },
-	{ .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
-	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
-	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
-	{ .parent = NULL },
-};
-
-static const char *sys_clkout_src_parent_names[] = {
-	"core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
-			 OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
-			 OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
-			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
-		   OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
-		   OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-static struct clk uart1_fck;
-
-static struct clk_hw_omap uart1_fck_hw = {
-	.hw = {
-		.clk = &uart1_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart1_ick;
-
-static struct clk_hw_omap uart1_ick_hw = {
-	.hw = {
-		.clk = &uart1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart2_fck;
-
-static struct clk_hw_omap uart2_fck_hw = {
-	.hw = {
-		.clk = &uart2_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart2_ick;
-
-static struct clk_hw_omap uart2_ick_hw = {
-	.hw = {
-		.clk = &uart2_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart3_fck;
-
-static struct clk_hw_omap uart3_fck_hw = {
-	.hw = {
-		.clk = &uart3_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart3_ick;
-
-static struct clk_hw_omap uart3_ick_hw = {
-	.hw = {
-		.clk = &uart3_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk usb_fck;
-
-static struct clk_hw_omap usb_fck_hw = {
-	.hw = {
-		.clk = &usb_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
-	{ .parent = NULL },
-};
-
-static const char *usb_l4_ick_parent_names[] = {
-	"core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-			 OMAP24XX_CLKSEL_USB_MASK,
-			 OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-			 OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
-			 usb_l4_ick_parent_names, dsp_fck_ops);
-
-static struct clk usbhs_ick;
-
-static struct clk_hw_omap usbhs_ick_hw = {
-	.hw = {
-		.clk = &usbhs_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbhs_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk virt_prcm_set;
-
-static const char *virt_prcm_set_parent_names[] = {
-	"mpu_ck",
-};
-
-static const struct clk_ops virt_prcm_set_ops = {
-	.recalc_rate	= &omap2_table_mpu_recalc,
-	.set_rate	= &omap2_select_table_rate,
-	.round_rate	= &omap2_round_to_table_rate,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
-DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
-
-static struct clk wdt1_ick;
-
-static struct clk_hw_omap wdt1_ick_hw = {
-	.hw = {
-		.clk = &wdt1_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt4_fck;
-
-static struct clk_hw_omap wdt4_fck_hw = {
-	.hw = {
-		.clk = &wdt4_fck,
-	},
-	.ops		= &clkhwops_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt4_ick;
-
-static struct clk_hw_omap wdt4_ick_hw = {
-	.hw = {
-		.clk = &wdt4_ick,
-	},
-	.ops		= &clkhwops_iclk_wait,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2430_clks[] = {
-	/* external root sources */
-	CLK(NULL,	"func_32k_ck",	&func_32k_ck),
-	CLK(NULL,	"secure_32k_ck", &secure_32k_ck),
-	CLK(NULL,	"osc_ck",	&osc_ck),
-	CLK("twl",	"fck",		&osc_ck),
-	CLK(NULL,	"sys_ck",	&sys_ck),
-	CLK(NULL,	"alt_ck",	&alt_ck),
-	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks),
-	/* internal analog sources */
-	CLK(NULL,	"dpll_ck",	&dpll_ck),
-	CLK(NULL,	"apll96_ck",	&apll96_ck),
-	CLK(NULL,	"apll54_ck",	&apll54_ck),
-	/* internal prcm root sources */
-	CLK(NULL,	"func_54m_ck",	&func_54m_ck),
-	CLK(NULL,	"core_ck",	&core_ck),
-	CLK(NULL,	"func_96m_ck",	&func_96m_ck),
-	CLK(NULL,	"func_48m_ck",	&func_48m_ck),
-	CLK(NULL,	"func_12m_ck",	&func_12m_ck),
-	CLK(NULL,	"sys_clkout_src", &sys_clkout_src),
-	CLK(NULL,	"sys_clkout",	&sys_clkout),
-	CLK(NULL,	"emul_ck",	&emul_ck),
-	/* mpu domain clocks */
-	CLK(NULL,	"mpu_ck",	&mpu_ck),
-	/* dsp domain clocks */
-	CLK(NULL,	"dsp_fck",	&dsp_fck),
-	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick),
-	/* GFX domain clocks */
-	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck),
-	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck),
-	CLK(NULL,	"gfx_ick",	&gfx_ick),
-	/* Modem domain clocks */
-	CLK(NULL,	"mdm_ick",	&mdm_ick),
-	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck),
-	/* DSS domain clocks */
-	CLK("omapdss_dss",	"ick",		&dss_ick),
-	CLK(NULL,	"dss_ick",		&dss_ick),
-	CLK(NULL,	"dss1_fck",		&dss1_fck),
-	CLK(NULL,	"dss2_fck",	&dss2_fck),
-	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck),
-	/* L3 domain clocks */
-	CLK(NULL,	"core_l3_ck",	&core_l3_ck),
-	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck),
-	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick),
-	/* L4 domain clocks */
-	CLK(NULL,	"l4_ck",	&l4_ck),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick),
-	/* virtual meta-group clock */
-	CLK(NULL,	"virt_prcm_set", &virt_prcm_set),
-	/* general l4 interface ck, multi-parent functional clk */
-	CLK(NULL,	"gpt1_ick",	&gpt1_ick),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck),
-	CLK(NULL,	"gpt2_ick",	&gpt2_ick),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck),
-	CLK(NULL,	"gpt3_ick",	&gpt3_ick),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck),
-	CLK(NULL,	"gpt4_ick",	&gpt4_ick),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck),
-	CLK(NULL,	"gpt5_ick",	&gpt5_ick),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck),
-	CLK(NULL,	"gpt6_ick",	&gpt6_ick),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck),
-	CLK(NULL,	"gpt7_ick",	&gpt7_ick),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck),
-	CLK(NULL,	"gpt8_ick",	&gpt8_ick),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck),
-	CLK(NULL,	"gpt9_ick",	&gpt9_ick),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck),
-	CLK(NULL,	"gpt10_ick",	&gpt10_ick),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck),
-	CLK(NULL,	"gpt11_ick",	&gpt11_ick),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck),
-	CLK(NULL,	"gpt12_ick",	&gpt12_ick),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck),
-	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick),
-	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick),
-	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck),
-	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick),
-	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick),
-	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck),
-	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick),
-	CLK(NULL,	"mcbsp3_ick",	&mcbsp3_ick),
-	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck),
-	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick),
-	CLK(NULL,	"mcbsp4_ick",	&mcbsp4_ick),
-	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck),
-	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick),
-	CLK(NULL,	"mcbsp5_ick",	&mcbsp5_ick),
-	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck),
-	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick),
-	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick),
-	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck),
-	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick),
-	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick),
-	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck),
-	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick),
-	CLK(NULL,	"mcspi3_ick",	&mcspi3_ick),
-	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck),
-	CLK(NULL,	"uart1_ick",	&uart1_ick),
-	CLK(NULL,	"uart1_fck",	&uart1_fck),
-	CLK(NULL,	"uart2_ick",	&uart2_ick),
-	CLK(NULL,	"uart2_fck",	&uart2_fck),
-	CLK(NULL,	"uart3_ick",	&uart3_ick),
-	CLK(NULL,	"uart3_fck",	&uart3_fck),
-	CLK(NULL,	"gpios_ick",	&gpios_ick),
-	CLK(NULL,	"gpios_fck",	&gpios_fck),
-	CLK("omap_wdt",	"ick",		&mpu_wdt_ick),
-	CLK(NULL,	"mpu_wdt_ick",	&mpu_wdt_ick),
-	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck),
-	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick),
-	CLK(NULL,	"wdt1_ick",	&wdt1_ick),
-	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick),
-	CLK(NULL,	"icr_ick",	&icr_ick),
-	CLK("omap24xxcam", "fck",	&cam_fck),
-	CLK(NULL,	"cam_fck",	&cam_fck),
-	CLK("omap24xxcam", "ick",	&cam_ick),
-	CLK(NULL,	"cam_ick",	&cam_ick),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick),
-	CLK(NULL,	"wdt4_ick",	&wdt4_ick),
-	CLK(NULL,	"wdt4_fck",	&wdt4_fck),
-	CLK(NULL,	"mspro_ick",	&mspro_ick),
-	CLK(NULL,	"mspro_fck",	&mspro_fck),
-	CLK(NULL,	"fac_ick",	&fac_ick),
-	CLK(NULL,	"fac_fck",	&fac_fck),
-	CLK("omap_hdq.0", "ick",	&hdq_ick),
-	CLK(NULL,	"hdq_ick",	&hdq_ick),
-	CLK("omap_hdq.1", "fck",	&hdq_fck),
-	CLK(NULL,	"hdq_fck",	&hdq_fck),
-	CLK("omap_i2c.1", "ick",	&i2c1_ick),
-	CLK(NULL,	"i2c1_ick",	&i2c1_ick),
-	CLK(NULL,	"i2chs1_fck",	&i2chs1_fck),
-	CLK("omap_i2c.2", "ick",	&i2c2_ick),
-	CLK(NULL,	"i2c2_ick",	&i2c2_ick),
-	CLK(NULL,	"i2chs2_fck",	&i2chs2_fck),
-	CLK(NULL,	"gpmc_fck",	&gpmc_fck),
-	CLK(NULL,	"sdma_fck",	&sdma_fck),
-	CLK(NULL,	"sdma_ick",	&sdma_ick),
-	CLK(NULL,	"sdrc_ick",	&sdrc_ick),
-	CLK(NULL,	"des_ick",	&des_ick),
-	CLK("omap-sham",	"ick",	&sha_ick),
-	CLK(NULL,	"sha_ick",	&sha_ick),
-	CLK("omap_rng", "ick",		&rng_ick),
-	CLK(NULL,	"rng_ick",	&rng_ick),
-	CLK("omap-aes",	"ick",	&aes_ick),
-	CLK(NULL,	"aes_ick",	&aes_ick),
-	CLK(NULL,	"pka_ick",	&pka_ick),
-	CLK(NULL,	"usb_fck",	&usb_fck),
-	CLK("musb-omap2430",	"ick",	&usbhs_ick),
-	CLK(NULL,	"usbhs_ick",	&usbhs_ick),
-	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick),
-	CLK(NULL,	"mmchs1_ick",	&mmchs1_ick),
-	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck),
-	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick),
-	CLK(NULL,	"mmchs2_ick",	&mmchs2_ick),
-	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck),
-	CLK(NULL,	"gpio5_ick",	&gpio5_ick),
-	CLK(NULL,	"gpio5_fck",	&gpio5_fck),
-	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick),
-	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck),
-	CLK(NULL,	 "mmchsdb1_fck",	&mmchsdb1_fck),
-	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck),
-	CLK(NULL,	 "mmchsdb2_fck",	&mmchsdb2_fck),
-	CLK(NULL,	"timer_32k_ck",  &func_32k_ck),
-	CLK(NULL,	"timer_sys_ck",	&sys_ck),
-	CLK(NULL,	"timer_ext_ck",	&alt_ck),
-	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set),
-};
-
-static const char *enable_init_clks[] = {
-	"apll96_ck",
-	"apll54_ck",
-	"sync_32k_ick",
-	"omapctrl_ick",
-	"gpmc_fck",
-	"sdrc_ick",
-};
-
-/*
- * init code
- */
-
-int __init omap2430_clk_init(void)
-{
-	prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
-	cpu_mask = RATE_IN_243X;
-	rate_table = omap2430_rate_table;
-
-	omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
-
-	omap2xxx_clkt_vps_check_bootloader_rates();
-
-	omap_clocks_register(omap2430_clks, ARRAY_SIZE(omap2430_clks));
-
-	omap2xxx_clkt_vps_late_init();
-
-	omap2_clk_disable_autoidle_all();
-
-	omap2_clk_enable_init_clocks(enable_init_clks,
-				     ARRAY_SIZE(enable_init_clks));
-
-	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
-		(clk_get_rate(&sys_ck) / 1000000),
-		(clk_get_rate(&sys_ck) / 100000) % 10,
-		(clk_get_rate(&dpll_ck) / 1000000),
-		(clk_get_rate(&mpu_ck) / 1000000));
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- * OMAP2xxx osc_clk-specific clock code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-
-/*
- * XXX This does not actually enable the osc_ck, since the osc_ck must
- * be running for this function to be called.  Instead, this function
- * is used to disable an autoidle mode on the osc_ck.  The existing
- * clk_enable/clk_disable()-based usecounting for osc_ck should be
- * replaced with autoidle-based usecounting.
- */
-int omap2_enable_osc_ck(struct clk_hw *clk)
-{
-	u32 pcc;
-
-	pcc = readl_relaxed(prcm_clksrc_ctrl);
-
-	writel_relaxed(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
-
-	return 0;
-}
-
-/*
- * XXX This does not actually disable the osc_ck, since doing so would
- * immediately halt the system.  Instead, this function is used to
- * enable an autoidle mode on the osc_ck.  The existing
- * clk_enable/clk_disable()-based usecounting for osc_ck should be
- * replaced with autoidle-based usecounting.
- */
-void omap2_disable_osc_ck(struct clk_hw *clk)
-{
-	u32 pcc;
-
-	pcc = readl_relaxed(prcm_clksrc_ctrl);
-
-	writel_relaxed(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
-}
-
-unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
-				   unsigned long parent_rate)
-{
-	return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt2xxx_sys.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt2xxx_sys.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt2xxx_sys.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt2xxx_sys.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-/*
- * OMAP2xxx sys_clk-specific clock code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-
-void __iomem *prcm_clksrc_ctrl;
-
-u32 omap2xxx_get_sysclkdiv(void)
-{
-	u32 div;
-
-	div = readl_relaxed(prcm_clksrc_ctrl);
-	div &= OMAP_SYSCLKDIV_MASK;
-	div >>= OMAP_SYSCLKDIV_SHIFT;
-
-	return div;
-}
-
-unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
-				      unsigned long parent_rate)
-{
-	return parent_rate / omap2xxx_get_sysclkdiv();
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt_dpll.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt_dpll.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt_dpll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt_dpll.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,10 +21,7 @@
 
 #include <asm/div64.h>
 
-#include "soc.h"
 #include "clock.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
 
 /* DPLL rate rounding: minimum DPLL multiplier, divider values */
 #define DPLL_MIN_MULTIPLIER		2
@@ -44,20 +41,12 @@
 #define DPLL_ROUNDING_VAL		((DPLL_SCALE_BASE / 2) * \
 					 (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
-/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
-#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
-#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
-#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
-
 /*
  * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
  * From device data manual section 4.3 "DPLL and DLL Specifications".
  */
 #define OMAP3PLUS_DPLL_FINT_JTYPE_MIN	500000
 #define OMAP3PLUS_DPLL_FINT_JTYPE_MAX	2500000
-#define OMAP3PLUS_DPLL_FINT_MIN		32000
-#define OMAP3PLUS_DPLL_FINT_MAX		52000000
 
 /* _dpll_test_fint() return codes */
 #define DPLL_FINT_UNDERFLOW		-1
@@ -87,33 +76,31 @@ static int _dpll_test_fint(struct clk_hw
 	/* DPLL divider must result in a valid jitter correction val */
 	fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
 
-	if (cpu_is_omap24xx()) {
-		/* Should not be called for OMAP2, so warn if it is called */
-		WARN(1, "No fint limits available for OMAP2!\n");
-		return DPLL_FINT_INVALID;
-	} else if (cpu_is_omap3430()) {
-		fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
-		fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
-	} else if (dd->flags & DPLL_J_TYPE) {
+	if (dd->flags & DPLL_J_TYPE) {
 		fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
 		fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
 	} else {
-		fint_min = OMAP3PLUS_DPLL_FINT_MIN;
-		fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+		fint_min = ti_clk_features.fint_min;
+		fint_max = ti_clk_features.fint_max;
 	}
 
-	if (fint < fint_min) {
+	if (!fint_min || !fint_max) {
+		WARN(1, "No fint limits available!\n");
+		return DPLL_FINT_INVALID;
+	}
+
+	if (fint < ti_clk_features.fint_min) {
 		pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
 			 n);
 		dd->max_divider = n;
 		ret = DPLL_FINT_UNDERFLOW;
-	} else if (fint > fint_max) {
+	} else if (fint > ti_clk_features.fint_max) {
 		pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
 			 n);
 		dd->min_divider = n;
 		ret = DPLL_FINT_INVALID;
-	} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
-		   fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+	} else if (fint > ti_clk_features.fint_band1_max &&
+		   fint < ti_clk_features.fint_band2_min) {
 		pr_debug("rejecting n=%d due to Fint failure\n", n);
 		ret = DPLL_FINT_INVALID;
 	}
@@ -185,6 +172,34 @@ static int _dpll_test_mult(int *m, int n
 	return r;
 }
 
+/**
+ * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
+ * @v: bitfield value of the DPLL enable
+ *
+ * Checks given DPLL enable bitfield to see whether the DPLL is in bypass
+ * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise.
+ */
+static int _omap2_dpll_is_in_bypass(u32 v)
+{
+	u8 mask, val;
+
+	mask = ti_clk_features.dpll_bypass_vals;
+
+	/*
+	 * Each set bit in the mask corresponds to a bypass value equal
+	 * to the bitshift. Go through each set-bit in the mask and
+	 * compare against the given register value.
+	 */
+	while (mask) {
+		val = __ffs(mask);
+		mask ^= (1 << val);
+		if (v == val)
+			return 1;
+	}
+
+	return 0;
+}
+
 /* Public functions */
 u8 omap2_init_dpll_parent(struct clk_hw *hw)
 {
@@ -201,20 +216,9 @@ u8 omap2_init_dpll_parent(struct clk_hw
 	v >>= __ffs(dd->enable_mask);
 
 	/* Reparent the struct clk in case the dpll is in bypass */
-	if (cpu_is_omap24xx()) {
-		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-			return 1;
-	} else if (cpu_is_omap34xx()) {
-		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-			return 1;
-	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
-		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-			return 1;
-	}
+	if (_omap2_dpll_is_in_bypass(v))
+		return 1;
+
 	return 0;
 }
 
@@ -247,20 +251,8 @@ unsigned long omap2_get_dpll_rate(struct
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
-	if (cpu_is_omap24xx()) {
-		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	} else if (cpu_is_omap34xx()) {
-		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
-		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	}
+	if (_omap2_dpll_is_in_bypass(v))
+		return __clk_get_rate(dd->clk_bypass);
 
 	v = omap2_clk_readl(clk, dd->mult_div1_reg);
 	dpll_mult = v & dd->mult_mask;
@@ -293,10 +285,13 @@ long omap2_dpll_round_rate(struct clk_hw
 {
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	int m, n, r, scaled_max_m;
+	int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
 	unsigned long scaled_rt_rp;
 	unsigned long new_rate = 0;
 	struct dpll_data *dd;
 	unsigned long ref_rate;
+	long delta;
+	long prev_min_delta = LONG_MAX;
 	const char *clk_name;
 
 	if (!clk || !clk->dpll_data)
@@ -342,23 +337,34 @@ long omap2_dpll_round_rate(struct clk_hw
 		if (r == DPLL_MULT_UNDERFLOW)
 			continue;
 
+		/* skip rates above our target rate */
+		delta = target_rate - new_rate;
+		if (delta < 0)
+			continue;
+
+		if (delta < prev_min_delta) {
+			prev_min_delta = delta;
+			min_delta_m = m;
+			min_delta_n = n;
+		}
+
 		pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
 			 clk_name, m, n, new_rate);
 
-		if (target_rate == new_rate) {
-			dd->last_rounded_m = m;
-			dd->last_rounded_n = n;
-			dd->last_rounded_rate = target_rate;
+		if (delta == 0)
 			break;
-		}
 	}
 
-	if (target_rate != new_rate) {
+	if (prev_min_delta == LONG_MAX) {
 		pr_debug("clock: %s: cannot round to rate %lu\n",
 			 clk_name, target_rate);
 		return ~0;
 	}
 
-	return target_rate;
+	dd->last_rounded_m = min_delta_m;
+	dd->last_rounded_n = min_delta_n;
+	dd->last_rounded_rate = target_rate - prev_min_delta;
+
+	return dd->last_rounded_rate;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt_iclk.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt_iclk.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clkt_iclk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clkt_iclk.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,11 +14,11 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 
-
 #include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
+
+/* Register offsets */
+#define CM_AUTOIDLE			0x30
+#define CM_ICLKEN			0x10
 
 /* Private functions */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clock2xxx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock2xxx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clock2xxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock2xxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,8 +45,6 @@ int omap2430_clk_init(void);
 #define omap2430_clk_init()	do { } while(0)
 #endif
 
-extern void __iomem *prcm_clksrc_ctrl;
-
 extern struct clk_hw *dclk_hw;
 int omap2_enable_osc_ck(struct clk_hw *hw);
 void omap2_disable_osc_ck(struct clk_hw *hw);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clock.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,24 @@
 u16 cpu_mask;
 
 /*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features ti_clk_features;
+
+/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
+#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_MIN		32000
+#define OMAP3PLUS_DPLL_FINT_MAX		52000000
+
+/*
  * clkdm_control: if true, then when a clock is enabled in the
  * hardware, its clockdomain will first be enabled; and when a clock
  * is disabled in the hardware, its clockdomain will be disabled
@@ -82,27 +100,6 @@ u32 omap2_clk_readl(struct clk_hw_omap *
 }
 
 /*
- * Used for clocks that have the same value as the parent clock,
- * divided by some factor
- */
-unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_hw_omap *oclk;
-
-	if (!hw) {
-		pr_warn("%s: hw is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	oclk = to_clk_hw_omap(hw);
-
-	WARN_ON(!oclk->fixed_div);
-
-	return parent_rate / oclk->fixed_div;
-}
-
-/*
  * OMAP2+ specific clock functions
  */
 
@@ -287,13 +284,7 @@ void omap2_clk_dflt_find_idlest(struct c
 	 * 34xx reverses this, just to keep us on our toes
 	 * AM35xx uses both, depending on the module.
 	 */
-	if (cpu_is_omap24xx())
-		*idlest_val = OMAP24XX_CM_IDLEST_VAL;
-	else if (cpu_is_omap34xx())
-		*idlest_val = OMAP34XX_CM_IDLEST_VAL;
-	else
-		BUG();
-
+	*idlest_val = ti_clk_features.cm_idlest_val;
 }
 
 /**
@@ -731,3 +722,53 @@ void __init omap2_clk_print_new_rates(co
 		(clk_get_rate(core_ck) / 1000000),
 		(clk_get_rate(mpu_ck) / 1000000));
 }
+
+/**
+ * ti_clk_init_features - init clock features struct for the SoC
+ *
+ * Initializes the clock features struct based on the SoC type.
+ */
+void __init ti_clk_init_features(void)
+{
+	/* Fint setup for DPLLs */
+	if (cpu_is_omap3430()) {
+		ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+		ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+		ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
+		ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
+	} else {
+		ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+		ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+	}
+
+	/* Bypass value setup for DPLLs */
+	if (cpu_is_omap24xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP2XXX_EN_DPLL_FRBYPASS);
+	} else if (cpu_is_omap34xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP3XXX_EN_DPLL_FRBYPASS);
+	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
+		   soc_is_omap54xx() || soc_is_dra7xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
+			(1 << OMAP4XXX_EN_DPLL_MNBYPASS);
+	}
+
+	/* Jitter correction only available on OMAP343X */
+	if (cpu_is_omap343x())
+		ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
+
+	/* Idlest value for interface clocks.
+	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+	 * 34xx reverses this, just to keep us on our toes
+	 * AM35xx uses both, depending on the module.
+	 */
+	if (cpu_is_omap24xx())
+		ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
+	else if (cpu_is_omap34xx())
+		ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/clock.h	2014-09-28 17:29:07.000000000 -0400
@@ -101,31 +101,6 @@ struct clockdomain;
 	};							\
 	DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
 
-#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name,		\
-				_parent_ptr, _flags,		\
-				_clksel_reg, _clksel_mask)	\
-	static const struct clksel _name##_div[] = {		\
-		{						\
-			.parent = _parent_ptr,			\
-			.rates = div31_1to31_rates		\
-		},						\
-		{ .parent = NULL },				\
-	};							\
-	static struct clk _name;				\
-	static const char *_name##_parent_names[] = {		\
-		_parent_name,					\
-	};							\
-	static struct clk_hw_omap _name##_hw = {		\
-		.hw = {						\
-			.clk = &_name,				\
-		},						\
-		.clksel		= _name##_div,			\
-		.clksel_reg	= _clksel_reg,			\
-		.clksel_mask	= _clksel_mask,			\
-		.ops		= &clkhwops_omap4_dpllmx,	\
-	};							\
-	DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
-
 /* struct clksel_rate.flags possibilities */
 #define RATE_IN_242X		(1 << 0)
 #define RATE_IN_243X		(1 << 1)
@@ -178,9 +153,6 @@ struct clksel {
 	const struct clksel_rate *rates;
 };
 
-unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
-					unsigned long parent_rate);
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K		0x0
 #define CORE_CLK_SRC_DPLL		0x1
@@ -248,6 +220,23 @@ void omap2_clk_writel(u32 val, struct cl
 
 extern u16 cpu_mask;
 
+/*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features {
+	u32 flags;
+	long fint_min;
+	long fint_max;
+	long fint_band1_max;
+	long fint_band2_min;
+	u8 dpll_bypass_vals;
+	u8 cm_idlest_val;
+};
+
+#define TI_CLK_DPLL_HAS_FREQSEL		(1 << 0)
+
+extern struct ti_clk_features ti_clk_features;
+
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_dummy;
 extern const struct clkops clkops_omap2_dflt;
@@ -286,4 +275,6 @@ extern int omap2_clkops_enable_clkdm(str
 extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
 extern void omap_clocks_register(struct omap_clk *oclks, int cnt);
+
+void __init ti_clk_init_features(void);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/cm2_7xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cm2_7xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/cm2_7xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cm2_7xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -357,6 +357,10 @@
 #define DRA7XX_CM_L3INIT_SATA_CLKCTRL				DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x0088)
 #define DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET				0x00a0
 #define DRA7XX_CM_PCIE_STATICDEP_OFFSET				0x00a4
+#define DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL_OFFSET			0x00b0
+#define DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL			DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x00b0)
+#define DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL_OFFSET			0x00b8
+#define DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL			DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x00b8)
 #define DRA7XX_CM_GMAC_CLKSTCTRL_OFFSET				0x00c0
 #define DRA7XX_CM_GMAC_STATICDEP_OFFSET				0x00c4
 #define DRA7XX_CM_GMAC_DYNAMICDEP_OFFSET			0x00c8
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -107,6 +107,7 @@
 #define OMAP24XX_AUTO_DPLL_SHIFT			0
 #define OMAP24XX_AUTO_DPLL_MASK				(0x3 << 0)
 #define OMAP24XX_APLLS_CLKIN_SHIFT			23
+#define OMAP24XX_APLLS_CLKIN_WIDTH			3
 #define OMAP24XX_APLLS_CLKIN_MASK			(0x7 << 23)
 #define OMAP24XX_DPLL_MULT_MASK				(0x3ff << 12)
 #define OMAP24XX_DPLL_DIV_MASK				(0xf << 8)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_data/dsp-omap.h>
 
 #include "common.h"
 #include "omap-secure.h"
@@ -30,7 +29,6 @@ int __weak omap_secure_ram_reserve_membl
 
 void __init omap_reserve(void)
 {
-	omap_dsp_reserve_sdram_memblock();
 	omap_secure_ram_reserve_memblock();
 	omap_barrier_reserve_memblock();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/control.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/control.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/control.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/control.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,8 +44,7 @@ struct omap3_scratchpad {
 };
 
 struct omap3_scratchpad_prcm_block {
-	u32 prm_clksrc_ctrl;
-	u32 prm_clksel;
+	u32 prm_contents[2];
 	u32 cm_contents[11];
 	u32 prcm_block_size;
 };
@@ -281,14 +280,11 @@ void omap3_clear_scratchpad_contents(voi
 	u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
 	void __iomem *v_addr;
 	u32 offset = 0;
+
 	v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
-	if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
-	    OMAP3430_GLOBAL_COLD_RST_MASK) {
+	if (omap3xxx_prm_clear_global_cold_reset()) {
 		for ( ; offset <= max_offset; offset += 0x4)
 			writel_relaxed(0x0, (v_addr + offset));
-		omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
-					   OMAP3430_GR_MOD,
-					   OMAP3_PRM_RSTST_OFFSET);
 	}
 }
 
@@ -314,7 +310,8 @@ void omap3_save_scratchpad_contents(void
 		scratchpad_contents.public_restore_ptr =
 			virt_to_phys(omap3_restore_3630);
 	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
-					omap_rev() != OMAP3430_REV_ES3_1)
+					omap_rev() != OMAP3430_REV_ES3_1 &&
+					omap_rev() != OMAP3430_REV_ES3_1_2)
 		scratchpad_contents.public_restore_ptr =
 			virt_to_phys(omap3_restore);
 	else
@@ -331,13 +328,7 @@ void omap3_save_scratchpad_contents(void
 	scratchpad_contents.sdrc_block_offset = 0x64;
 
 	/* Populate the PRCM block contents */
-	prcm_block_contents.prm_clksrc_ctrl =
-		omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
-				       OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-	prcm_block_contents.prm_clksel =
-		omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
-				       OMAP3_PRM_CLKSEL_OFFSET);
-
+	omap3_prm_save_scratchpad_contents(prcm_block_contents.prm_contents);
 	omap3_cm_save_scratchpad_contents(prcm_block_contents.cm_contents);
 
 	prcm_block_contents.prcm_block_size = 0x0;
@@ -474,7 +465,6 @@ void omap3_control_save_context(void)
 	control_context.csi = omap_ctrl_readl(OMAP343X_CONTROL_CSI);
 	control_context.padconf_sys_nirq =
 		omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
-	return;
 }
 
 void omap3_control_restore_context(void)
@@ -532,7 +522,6 @@ void omap3_control_restore_context(void)
 	omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);
 	omap_ctrl_writel(control_context.padconf_sys_nirq,
 			 OMAP343X_CONTROL_PADCONF_SYSNIRQ);
-	return;
 }
 
 void omap3630_ctrl_disable_rta(void)
@@ -575,9 +564,50 @@ int omap3_ctrl_save_padconf(void)
  * Sets the bootmode for IVA2 to idle. This is needed by the PM code to
  * force disable IVA2 so that it does not prevent any low-power states.
  */
-void omap3_ctrl_set_iva_bootmode_idle(void)
+static void __init omap3_ctrl_set_iva_bootmode_idle(void)
 {
 	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
 			 OMAP343X_CONTROL_IVA2_BOOTMOD);
 }
+
+/**
+ * omap3_ctrl_setup_d2d_padconf - setup stacked modem pads for idle
+ *
+ * Sets up the pads controlling the stacked modem in such way that the
+ * device can enter idle.
+ */
+static void __init omap3_ctrl_setup_d2d_padconf(void)
+{
+	u16 mask, padconf;
+
+	/*
+	 * In a stand alone OMAP3430 where there is not a stacked
+	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
+	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
+	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up.
+	 */
+	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
+
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+}
+
+/**
+ * omap3_ctrl_init - does static initializations for control module
+ *
+ * Initializes system control module. This sets up the sysconfig autoidle,
+ * and sets up modem and iva2 so that they can be idled properly.
+ */
+void __init omap3_ctrl_init(void)
+{
+	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
+
+	omap3_ctrl_set_iva_bootmode_idle();
+
+	omap3_ctrl_setup_d2d_padconf();
+}
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/control.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/control.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/control.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/control.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,11 +16,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
 #define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
-#include "ctrl_module_core_44xx.h"
-#include "ctrl_module_wkup_44xx.h"
-#include "ctrl_module_pad_core_44xx.h"
-#include "ctrl_module_pad_wkup_44xx.h"
-
 #include "am33xx.h"
 
 #ifndef __ASSEMBLY__
@@ -254,6 +249,39 @@
 /* TI81XX CONTROL_DEVCONF register offsets */
 #define TI81XX_CONTROL_DEVICE_ID	(TI81XX_CONTROL_DEVCONF + 0x000)
 
+/* OMAP4 CONTROL MODULE */
+#define OMAP4_CTRL_MODULE_PAD_WKUP			0x4a31e000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2	0x0604
+#define OMAP4_CTRL_MODULE_CORE_STATUS			0x02c4
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1	0x0218
+#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR		0x0304
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY	0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX	0x0608
+
+/* OMAP4 CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT			29
+#define OMAP4_DSI2_LANEENABLE_MASK			(0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT			24
+#define OMAP4_DSI1_LANEENABLE_MASK			(0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT				19
+#define OMAP4_DSI1_PIPD_MASK				(0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT				14
+#define OMAP4_DSI2_PIPD_MASK				(0x1f << 14)
+
+/* OMAP4 CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT		24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK		(0x1f << 24)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT		29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK		(0x3 << 29)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT		21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK		(1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT		19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK		(0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT		18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK		(1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT		16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK		(0x3 << 16)
+
 /* OMAP54XX CONTROL STATUS register */
 #define OMAP5XXX_CONTROL_STATUS                0x134
 #define OMAP5_DEVICETYPE_MASK          (0x7 << 6)
@@ -427,7 +455,7 @@ extern void omap_ctrl_write_dsp_boot_add
 extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
-extern void omap3_ctrl_set_iva_bootmode_idle(void);
+void omap3_ctrl_init(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_core_44xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_core_44xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_core_44xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_core_44xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,392 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_CORE					0x4a002000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_CORE_IP_REVISION			0x0000
-#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO			0x0004
-#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG			0x0010
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0		0x0200
-#define OMAP4_CTRL_MODULE_CORE_ID_CODE				0x0204
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1		0x0208
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2		0x020c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3		0x0210
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0		0x0214
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF		0x021c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP		0x0228
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP		0x0260
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0		0x0264
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1		0x0268
-#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
-#define OMAP4_CTRL_MODULE_CORE_DEV_CONF				0x0300
-#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR			0x0304
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL		0x0314
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL		0x0318
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL		0x0320
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL		0x0324
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL	0x0328
-#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR			0x032c
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0		0x0330
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1		0x0334
-#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL			0x033c
-#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL			0x0340
-#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL			0x0350
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL		0x0400
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU			0x0408
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0		0x042c
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1		0x0430
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2		0x0434
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3		0x0438
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0			0x0440
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1			0x0444
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2			0x0448
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL		0x044c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL		0x0450
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL		0x0454
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0		0x0480
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1		0x0484
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2		0x0488
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3		0x048c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4		0x0490
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5		0x0494
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6		0x0498
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7		0x049c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8		0x04a0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9		0x04a4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10		0x04a8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11		0x04ac
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12		0x04b0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13		0x04b4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14		0x04b8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15		0x04bc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16		0x04c0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17		0x04c4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18		0x04c8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19		0x04cc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20		0x04d0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21		0x04d4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22		0x04d8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23		0x04dc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24		0x04e0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25		0x04e4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26		0x04e8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27		0x04ec
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28		0x04f0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29		0x04f4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30		0x04f8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31		0x04fc
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT			30
-#define OMAP4_IP_REV_SCHEME_MASK			(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT				16
-#define OMAP4_IP_REV_FUNC_MASK				(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT				11
-#define OMAP4_IP_REV_RTL_MASK				(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT			8
-#define OMAP4_IP_REV_MAJOR_MASK				(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT			6
-#define OMAP4_IP_REV_CUSTOM_MASK			(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT			0
-#define OMAP4_IP_REV_MINOR_MASK				(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT				0
-#define OMAP4_IP_HWINFO_MASK				(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT		2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK		(0x3 << 2)
-
-/* STD_FUSE_DIE_ID_0 */
-#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_0_MASK			(0xffffffff << 0)
-
-/* ID_CODE */
-#define OMAP4_STD_FUSE_IDCODE_SHIFT			0
-#define OMAP4_STD_FUSE_IDCODE_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_1 */
-#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_1_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_2 */
-#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_2_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_3 */
-#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_3_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_0 */
-#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT			0
-#define OMAP4_STD_FUSE_PROD_ID_0_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_1 */
-#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT			0
-#define OMAP4_STD_FUSE_PROD_ID_1_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_USB_CONF */
-#define OMAP4_USB_PROD_ID_SHIFT				16
-#define OMAP4_USB_PROD_ID_MASK				(0xffff << 16)
-#define OMAP4_USB_VENDOR_ID_SHIFT			0
-#define OMAP4_USB_VENDOR_ID_MASK			(0xffff << 0)
-
-/* STD_FUSE_OPP_VDD_WKUP */
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT		0
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK		(0xffffffff << 0)
-
-/* STD_FUSE_OPP_BGAP */
-#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_BGAP_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_0 */
-#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_1 */
-#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK			(0xffffffff << 0)
-
-/* STATUS */
-#define OMAP4_ATTILA_CONF_SHIFT				11
-#define OMAP4_ATTILA_CONF_MASK				(0x3 << 11)
-#define OMAP4_DEVICE_TYPE_SHIFT				8
-#define OMAP4_DEVICE_TYPE_MASK				(0x7 << 8)
-#define OMAP4_SYS_BOOT_SHIFT				0
-#define OMAP4_SYS_BOOT_MASK				(0xff << 0)
-
-/* DEV_CONF */
-#define OMAP4_DEV_CONF_SHIFT				1
-#define OMAP4_DEV_CONF_MASK				(0x7fffffff << 1)
-#define OMAP4_USBPHY_PD_SHIFT				0
-#define OMAP4_USBPHY_PD_MASK				(1 << 0)
-
-/* LDOVBB_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT		21
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT		16
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT		5
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT		0
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOVBB_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT		21
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT		16
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT		5
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT		0
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT		16
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT		0
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT		16
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT		0
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_CORE_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT	26
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT	16
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT	10
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
-#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT				11
-#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
-
-/* DPLL_NWELL_TRIM_0 */
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK		(1 << 29)
-#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT			24
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK			(0x1f << 24)
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT	23
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
-#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT			18
-#define OMAP4_DPLL_PER_NWELL_TRIM_MASK			(0x1f << 18)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT	17
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT		12
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK			(0x1f << 12)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT	11
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK		(1 << 11)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT			6
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK			(0x1f << 6)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT	5
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK		(1 << 5)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT			0
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK			(0x1f << 0)
-
-/* DPLL_NWELL_TRIM_1 */
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT	29
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK	(1 << 29)
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT		24
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK		(0x1f << 24)
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT	23
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
-#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT			18
-#define OMAP4_DPLL_USB_NWELL_TRIM_MASK			(0x1f << 18)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT	17
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT		12
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK			(0x1f << 12)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT	11
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK	(1 << 11)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT		6
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK			(0x1f << 6)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT	5
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK	(1 << 5)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT		0
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK			(0x1f << 0)
-
-/* USBOTGHS_CONTROL */
-#define OMAP4_DISCHRGVBUS_SHIFT				8
-#define OMAP4_DISCHRGVBUS_MASK				(1 << 8)
-#define OMAP4_CHRGVBUS_SHIFT				7
-#define OMAP4_CHRGVBUS_MASK				(1 << 7)
-#define OMAP4_DRVVBUS_SHIFT				6
-#define OMAP4_DRVVBUS_MASK				(1 << 6)
-#define OMAP4_IDPULLUP_SHIFT				5
-#define OMAP4_IDPULLUP_MASK				(1 << 5)
-#define OMAP4_IDDIG_SHIFT				4
-#define OMAP4_IDDIG_MASK				(1 << 4)
-#define OMAP4_SESSEND_SHIFT				3
-#define OMAP4_SESSEND_MASK				(1 << 3)
-#define OMAP4_VBUSVALID_SHIFT				2
-#define OMAP4_VBUSVALID_MASK				(1 << 2)
-#define OMAP4_BVALID_SHIFT				1
-#define OMAP4_BVALID_MASK				(1 << 1)
-#define OMAP4_AVALID_SHIFT				0
-#define OMAP4_AVALID_MASK				(1 << 0)
-
-/* DSS_CONTROL */
-#define OMAP4_DSS_MUX6_SELECT_SHIFT			0
-#define OMAP4_DSS_MUX6_SELECT_MASK			(1 << 0)
-
-/* HWOBS_CONTROL */
-#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT			3
-#define OMAP4_HWOBS_CLKDIV_SEL_MASK			(0x1f << 3)
-#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT			2
-#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK			(1 << 2)
-#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT			1
-#define OMAP4_HWOBS_ALL_ONE_MODE_MASK			(1 << 1)
-#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT			0
-#define OMAP4_HWOBS_MACRO_ENABLE_MASK			(1 << 0)
-
-/* DEBOBS_FINAL_MUX_SEL */
-#define OMAP4_SELECT_SHIFT				0
-#define OMAP4_SELECT_MASK				(0xffffffff << 0)
-
-/* DEBOBS_MMR_MPU */
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT		0
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK		(0xf << 0)
-
-/* CONF_SDMA_REQ_SEL0 */
-#define OMAP4_MULT_SHIFT				0
-#define OMAP4_MULT_MASK					(0x7f << 0)
-
-/* CONF_CLK_SEL0 */
-#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL0_MASK			(0x7 << 0)
-
-/* CONF_CLK_SEL1 */
-#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL1_MASK			(0x7 << 0)
-
-/* CONF_CLK_SEL2 */
-#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL2_MASK			(0x7 << 0)
-
-/* CONF_DPLL_FREQLOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT		0
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK		(0x7 << 0)
-
-/* CONF_DPLL_TINITZ_SEL */
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT		0
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK		(0x7 << 0)
-
-/* CONF_DPLL_PHASELOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT	0
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK		(0x7 << 0)
-
-/* CONF_DEBUG_SEL_TST_0 */
-#define OMAP4_MODE_SHIFT				0
-#define OMAP4_MODE_MASK					(0xf << 0)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1409 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_PAD_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_CORE				0x4a100000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION			0x0000
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO			0x0004
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG			0x0010
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0	0x01d8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1	0x01dc
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2	0x01e0
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3	0x01e4
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4	0x01e8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5	0x01ec
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6	0x01f0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL	0x05a0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE		0x05a4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0	0x05a8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1	0x05ac
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0	0x05b0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1	0x05b4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0	0x05b8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1	0x05bc
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2	0x05c0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC		0x05c4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS		0x05c8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0		0x0604
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX		0x0608
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC		0x060c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY		0x0610
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2			0x0614
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP		0x061c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE		0x0620
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI			0x062c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB			0x0630
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ			0x0634
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0		0x0638
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1		0x063c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2		0x0640
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3		0x0644
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0		0x0648
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1		0x064c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2		0x0650
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3		0x0654
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD		0x0658
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C			0x065c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW	0x0660
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R		0x0664
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0	0x0668
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1		0x0700
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2		0x0704
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3		0x0708
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4		0x070c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT				30
-#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT					16
-#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT					11
-#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT				8
-#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT				6
-#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT				0
-#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT					0
-#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_1 */
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_2 */
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	31
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	27
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	14
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 14)
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	13
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	12
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 12)
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	11
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 11)
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	10
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 10)
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	9
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 9)
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	8
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 8)
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	7
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 7)
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	6
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 6)
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	5
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 5)
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	4
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 4)
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	3
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 3)
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	2
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 2)
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	1
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 1)
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT	0
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_3 */
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK			(1 << 16)
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	4
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	3
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_4 */
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	29
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 29)
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	28
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	27
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 27)
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	26
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 26)
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	25
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 25)
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	24
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 24)
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	23
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 23)
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	22
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 22)
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	21
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 21)
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	20
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 20)
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	19
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 19)
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	18
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 18)
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	17
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 17)
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	16
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_5 */
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_6 */
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* CONTROL_PADCONF_GLOBAL */
-#define OMAP4_FORCE_OFFMODE_EN_SHIFT				31
-#define OMAP4_FORCE_OFFMODE_EN_MASK				(1 << 31)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_BANK0_SHIFT				31
-#define OMAP4_VDDS_DV_BANK0_MASK				(1 << 31)
-#define OMAP4_VDDS_DV_BANK1_SHIFT				30
-#define OMAP4_VDDS_DV_BANK1_MASK				(1 << 30)
-#define OMAP4_VDDS_DV_BANK3_SHIFT				29
-#define OMAP4_VDDS_DV_BANK3_MASK				(1 << 29)
-#define OMAP4_VDDS_DV_BANK4_SHIFT				28
-#define OMAP4_VDDS_DV_BANK4_MASK				(1 << 28)
-#define OMAP4_VDDS_DV_BANK5_SHIFT				27
-#define OMAP4_VDDS_DV_BANK5_MASK				(1 << 27)
-#define OMAP4_VDDS_DV_BANK6_SHIFT				26
-#define OMAP4_VDDS_DV_BANK6_MASK				(1 << 26)
-#define OMAP4_VDDS_DV_C2C_SHIFT					25
-#define OMAP4_VDDS_DV_C2C_MASK					(1 << 25)
-#define OMAP4_VDDS_DV_CAM_SHIFT					24
-#define OMAP4_VDDS_DV_CAM_MASK					(1 << 24)
-#define OMAP4_VDDS_DV_GPMC_SHIFT				23
-#define OMAP4_VDDS_DV_GPMC_MASK					(1 << 23)
-#define OMAP4_VDDS_DV_SDMMC2_SHIFT				22
-#define OMAP4_VDDS_DV_SDMMC2_MASK				(1 << 22)
-
-/* CONTROL_SMART1IO_PADCONF_0 */
-#define OMAP4_ABE_DR0_SC_SHIFT					30
-#define OMAP4_ABE_DR0_SC_MASK					(0x3 << 30)
-#define OMAP4_CAM_DR0_SC_SHIFT					28
-#define OMAP4_CAM_DR0_SC_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR2_SC_SHIFT					26
-#define OMAP4_FREF_DR2_SC_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR3_SC_SHIFT					24
-#define OMAP4_FREF_DR3_SC_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR8_SC_SHIFT					22
-#define OMAP4_GPIO_DR8_SC_MASK					(0x3 << 22)
-#define OMAP4_GPIO_DR9_SC_SHIFT					20
-#define OMAP4_GPIO_DR9_SC_MASK					(0x3 << 20)
-#define OMAP4_GPMC_DR2_SC_SHIFT					18
-#define OMAP4_GPMC_DR2_SC_MASK					(0x3 << 18)
-#define OMAP4_GPMC_DR3_SC_SHIFT					16
-#define OMAP4_GPMC_DR3_SC_MASK					(0x3 << 16)
-#define OMAP4_GPMC_DR6_SC_SHIFT					14
-#define OMAP4_GPMC_DR6_SC_MASK					(0x3 << 14)
-#define OMAP4_HDMI_DR0_SC_SHIFT					12
-#define OMAP4_HDMI_DR0_SC_MASK					(0x3 << 12)
-#define OMAP4_MCSPI1_DR0_SC_SHIFT				10
-#define OMAP4_MCSPI1_DR0_SC_MASK				(0x3 << 10)
-#define OMAP4_UART1_DR0_SC_SHIFT				8
-#define OMAP4_UART1_DR0_SC_MASK					(0x3 << 8)
-#define OMAP4_UART3_DR0_SC_SHIFT				6
-#define OMAP4_UART3_DR0_SC_MASK					(0x3 << 6)
-#define OMAP4_UART3_DR1_SC_SHIFT				4
-#define OMAP4_UART3_DR1_SC_MASK					(0x3 << 4)
-#define OMAP4_UNIPRO_DR0_SC_SHIFT				2
-#define OMAP4_UNIPRO_DR0_SC_MASK				(0x3 << 2)
-#define OMAP4_UNIPRO_DR1_SC_SHIFT				0
-#define OMAP4_UNIPRO_DR1_SC_MASK				(0x3 << 0)
-
-/* CONTROL_SMART1IO_PADCONF_1 */
-#define OMAP4_ABE_DR0_LB_SHIFT					30
-#define OMAP4_ABE_DR0_LB_MASK					(0x3 << 30)
-#define OMAP4_CAM_DR0_LB_SHIFT					28
-#define OMAP4_CAM_DR0_LB_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR2_LB_SHIFT					26
-#define OMAP4_FREF_DR2_LB_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR3_LB_SHIFT					24
-#define OMAP4_FREF_DR3_LB_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR8_LB_SHIFT					22
-#define OMAP4_GPIO_DR8_LB_MASK					(0x3 << 22)
-#define OMAP4_GPIO_DR9_LB_SHIFT					20
-#define OMAP4_GPIO_DR9_LB_MASK					(0x3 << 20)
-#define OMAP4_GPMC_DR2_LB_SHIFT					18
-#define OMAP4_GPMC_DR2_LB_MASK					(0x3 << 18)
-#define OMAP4_GPMC_DR3_LB_SHIFT					16
-#define OMAP4_GPMC_DR3_LB_MASK					(0x3 << 16)
-#define OMAP4_GPMC_DR6_LB_SHIFT					14
-#define OMAP4_GPMC_DR6_LB_MASK					(0x3 << 14)
-#define OMAP4_HDMI_DR0_LB_SHIFT					12
-#define OMAP4_HDMI_DR0_LB_MASK					(0x3 << 12)
-#define OMAP4_MCSPI1_DR0_LB_SHIFT				10
-#define OMAP4_MCSPI1_DR0_LB_MASK				(0x3 << 10)
-#define OMAP4_UART1_DR0_LB_SHIFT				8
-#define OMAP4_UART1_DR0_LB_MASK					(0x3 << 8)
-#define OMAP4_UART3_DR0_LB_SHIFT				6
-#define OMAP4_UART3_DR0_LB_MASK					(0x3 << 6)
-#define OMAP4_UART3_DR1_LB_SHIFT				4
-#define OMAP4_UART3_DR1_LB_MASK					(0x3 << 4)
-#define OMAP4_UNIPRO_DR0_LB_SHIFT				2
-#define OMAP4_UNIPRO_DR0_LB_MASK				(0x3 << 2)
-#define OMAP4_UNIPRO_DR1_LB_SHIFT				0
-#define OMAP4_UNIPRO_DR1_LB_MASK				(0x3 << 0)
-
-/* CONTROL_SMART2IO_PADCONF_0 */
-#define OMAP4_C2C_DR0_LB_SHIFT					31
-#define OMAP4_C2C_DR0_LB_MASK					(1 << 31)
-#define OMAP4_DPM_DR1_LB_SHIFT					30
-#define OMAP4_DPM_DR1_LB_MASK					(1 << 30)
-#define OMAP4_DPM_DR2_LB_SHIFT					29
-#define OMAP4_DPM_DR2_LB_MASK					(1 << 29)
-#define OMAP4_DPM_DR3_LB_SHIFT					28
-#define OMAP4_DPM_DR3_LB_MASK					(1 << 28)
-#define OMAP4_GPIO_DR0_LB_SHIFT					27
-#define OMAP4_GPIO_DR0_LB_MASK					(1 << 27)
-#define OMAP4_GPIO_DR1_LB_SHIFT					26
-#define OMAP4_GPIO_DR1_LB_MASK					(1 << 26)
-#define OMAP4_GPIO_DR10_LB_SHIFT				25
-#define OMAP4_GPIO_DR10_LB_MASK					(1 << 25)
-#define OMAP4_GPIO_DR2_LB_SHIFT					24
-#define OMAP4_GPIO_DR2_LB_MASK					(1 << 24)
-#define OMAP4_GPMC_DR0_LB_SHIFT					23
-#define OMAP4_GPMC_DR0_LB_MASK					(1 << 23)
-#define OMAP4_GPMC_DR1_LB_SHIFT					22
-#define OMAP4_GPMC_DR1_LB_MASK					(1 << 22)
-#define OMAP4_GPMC_DR4_LB_SHIFT					21
-#define OMAP4_GPMC_DR4_LB_MASK					(1 << 21)
-#define OMAP4_GPMC_DR5_LB_SHIFT					20
-#define OMAP4_GPMC_DR5_LB_MASK					(1 << 20)
-#define OMAP4_GPMC_DR7_LB_SHIFT					19
-#define OMAP4_GPMC_DR7_LB_MASK					(1 << 19)
-#define OMAP4_HSI2_DR0_LB_SHIFT					18
-#define OMAP4_HSI2_DR0_LB_MASK					(1 << 18)
-#define OMAP4_HSI2_DR1_LB_SHIFT					17
-#define OMAP4_HSI2_DR1_LB_MASK					(1 << 17)
-#define OMAP4_HSI2_DR2_LB_SHIFT					16
-#define OMAP4_HSI2_DR2_LB_MASK					(1 << 16)
-#define OMAP4_KPD_DR0_LB_SHIFT					15
-#define OMAP4_KPD_DR0_LB_MASK					(1 << 15)
-#define OMAP4_KPD_DR1_LB_SHIFT					14
-#define OMAP4_KPD_DR1_LB_MASK					(1 << 14)
-#define OMAP4_PDM_DR0_LB_SHIFT					13
-#define OMAP4_PDM_DR0_LB_MASK					(1 << 13)
-#define OMAP4_SDMMC2_DR0_LB_SHIFT				12
-#define OMAP4_SDMMC2_DR0_LB_MASK				(1 << 12)
-#define OMAP4_SDMMC3_DR0_LB_SHIFT				11
-#define OMAP4_SDMMC3_DR0_LB_MASK				(1 << 11)
-#define OMAP4_SDMMC4_DR0_LB_SHIFT				10
-#define OMAP4_SDMMC4_DR0_LB_MASK				(1 << 10)
-#define OMAP4_SDMMC4_DR1_LB_SHIFT				9
-#define OMAP4_SDMMC4_DR1_LB_MASK				(1 << 9)
-#define OMAP4_SPI3_DR0_LB_SHIFT					8
-#define OMAP4_SPI3_DR0_LB_MASK					(1 << 8)
-#define OMAP4_SPI3_DR1_LB_SHIFT					7
-#define OMAP4_SPI3_DR1_LB_MASK					(1 << 7)
-#define OMAP4_UART3_DR2_LB_SHIFT				6
-#define OMAP4_UART3_DR2_LB_MASK					(1 << 6)
-#define OMAP4_UART3_DR3_LB_SHIFT				5
-#define OMAP4_UART3_DR3_LB_MASK					(1 << 5)
-#define OMAP4_UART3_DR4_LB_SHIFT				4
-#define OMAP4_UART3_DR4_LB_MASK					(1 << 4)
-#define OMAP4_UART3_DR5_LB_SHIFT				3
-#define OMAP4_UART3_DR5_LB_MASK					(1 << 3)
-#define OMAP4_USBA0_DR1_LB_SHIFT				2
-#define OMAP4_USBA0_DR1_LB_MASK					(1 << 2)
-#define OMAP4_USBA_DR2_LB_SHIFT					1
-#define OMAP4_USBA_DR2_LB_MASK					(1 << 1)
-
-/* CONTROL_SMART2IO_PADCONF_1 */
-#define OMAP4_USBB1_DR0_LB_SHIFT				31
-#define OMAP4_USBB1_DR0_LB_MASK					(1 << 31)
-#define OMAP4_USBB2_DR0_LB_SHIFT				30
-#define OMAP4_USBB2_DR0_LB_MASK					(1 << 30)
-#define OMAP4_USBA0_DR0_LB_SHIFT				29
-#define OMAP4_USBA0_DR0_LB_MASK					(1 << 29)
-
-/* CONTROL_SMART3IO_PADCONF_0 */
-#define OMAP4_DMIC_DR0_MB_SHIFT					30
-#define OMAP4_DMIC_DR0_MB_MASK					(0x3 << 30)
-#define OMAP4_GPIO_DR3_MB_SHIFT					28
-#define OMAP4_GPIO_DR3_MB_MASK					(0x3 << 28)
-#define OMAP4_GPIO_DR4_MB_SHIFT					26
-#define OMAP4_GPIO_DR4_MB_MASK					(0x3 << 26)
-#define OMAP4_GPIO_DR5_MB_SHIFT					24
-#define OMAP4_GPIO_DR5_MB_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR6_MB_SHIFT					22
-#define OMAP4_GPIO_DR6_MB_MASK					(0x3 << 22)
-#define OMAP4_HSI_DR1_MB_SHIFT					20
-#define OMAP4_HSI_DR1_MB_MASK					(0x3 << 20)
-#define OMAP4_HSI_DR2_MB_SHIFT					18
-#define OMAP4_HSI_DR2_MB_MASK					(0x3 << 18)
-#define OMAP4_HSI_DR3_MB_SHIFT					16
-#define OMAP4_HSI_DR3_MB_MASK					(0x3 << 16)
-#define OMAP4_MCBSP2_DR0_MB_SHIFT				14
-#define OMAP4_MCBSP2_DR0_MB_MASK				(0x3 << 14)
-#define OMAP4_MCSPI4_DR0_MB_SHIFT				12
-#define OMAP4_MCSPI4_DR0_MB_MASK				(0x3 << 12)
-#define OMAP4_MCSPI4_DR1_MB_SHIFT				10
-#define OMAP4_MCSPI4_DR1_MB_MASK				(0x3 << 10)
-#define OMAP4_SDMMC3_DR0_MB_SHIFT				8
-#define OMAP4_SDMMC3_DR0_MB_MASK				(0x3 << 8)
-#define OMAP4_SPI2_DR0_MB_SHIFT					0
-#define OMAP4_SPI2_DR0_MB_MASK					(0x3 << 0)
-
-/* CONTROL_SMART3IO_PADCONF_1 */
-#define OMAP4_SPI2_DR1_MB_SHIFT					30
-#define OMAP4_SPI2_DR1_MB_MASK					(0x3 << 30)
-#define OMAP4_SPI2_DR2_MB_SHIFT					28
-#define OMAP4_SPI2_DR2_MB_MASK					(0x3 << 28)
-#define OMAP4_UART2_DR0_MB_SHIFT				26
-#define OMAP4_UART2_DR0_MB_MASK					(0x3 << 26)
-#define OMAP4_UART2_DR1_MB_SHIFT				24
-#define OMAP4_UART2_DR1_MB_MASK					(0x3 << 24)
-#define OMAP4_UART4_DR0_MB_SHIFT				22
-#define OMAP4_UART4_DR0_MB_MASK					(0x3 << 22)
-#define OMAP4_HSI_DR0_MB_SHIFT					20
-#define OMAP4_HSI_DR0_MB_MASK					(0x3 << 20)
-
-/* CONTROL_SMART3IO_PADCONF_2 */
-#define OMAP4_DMIC_DR0_LB_SHIFT					31
-#define OMAP4_DMIC_DR0_LB_MASK					(1 << 31)
-#define OMAP4_GPIO_DR3_LB_SHIFT					30
-#define OMAP4_GPIO_DR3_LB_MASK					(1 << 30)
-#define OMAP4_GPIO_DR4_LB_SHIFT					29
-#define OMAP4_GPIO_DR4_LB_MASK					(1 << 29)
-#define OMAP4_GPIO_DR5_LB_SHIFT					28
-#define OMAP4_GPIO_DR5_LB_MASK					(1 << 28)
-#define OMAP4_GPIO_DR6_LB_SHIFT					27
-#define OMAP4_GPIO_DR6_LB_MASK					(1 << 27)
-#define OMAP4_HSI_DR1_LB_SHIFT					26
-#define OMAP4_HSI_DR1_LB_MASK					(1 << 26)
-#define OMAP4_HSI_DR2_LB_SHIFT					25
-#define OMAP4_HSI_DR2_LB_MASK					(1 << 25)
-#define OMAP4_HSI_DR3_LB_SHIFT					24
-#define OMAP4_HSI_DR3_LB_MASK					(1 << 24)
-#define OMAP4_MCBSP2_DR0_LB_SHIFT				23
-#define OMAP4_MCBSP2_DR0_LB_MASK				(1 << 23)
-#define OMAP4_MCSPI4_DR0_LB_SHIFT				22
-#define OMAP4_MCSPI4_DR0_LB_MASK				(1 << 22)
-#define OMAP4_MCSPI4_DR1_LB_SHIFT				21
-#define OMAP4_MCSPI4_DR1_LB_MASK				(1 << 21)
-#define OMAP4_SLIMBUS2_DR0_LB_SHIFT				18
-#define OMAP4_SLIMBUS2_DR0_LB_MASK				(1 << 18)
-#define OMAP4_SPI2_DR0_LB_SHIFT					16
-#define OMAP4_SPI2_DR0_LB_MASK					(1 << 16)
-#define OMAP4_SPI2_DR1_LB_SHIFT					15
-#define OMAP4_SPI2_DR1_LB_MASK					(1 << 15)
-#define OMAP4_SPI2_DR2_LB_SHIFT					14
-#define OMAP4_SPI2_DR2_LB_MASK					(1 << 14)
-#define OMAP4_UART2_DR0_LB_SHIFT				13
-#define OMAP4_UART2_DR0_LB_MASK					(1 << 13)
-#define OMAP4_UART2_DR1_LB_SHIFT				12
-#define OMAP4_UART2_DR1_LB_MASK					(1 << 12)
-#define OMAP4_UART4_DR0_LB_SHIFT				11
-#define OMAP4_UART4_DR0_LB_MASK					(1 << 11)
-#define OMAP4_HSI_DR0_LB_SHIFT					10
-#define OMAP4_HSI_DR0_LB_MASK					(1 << 10)
-
-/* CONTROL_USBB_HSIC */
-#define OMAP4_USBB2_DR1_SR_SHIFT				30
-#define OMAP4_USBB2_DR1_SR_MASK					(0x3 << 30)
-#define OMAP4_USBB2_DR1_I_SHIFT					27
-#define OMAP4_USBB2_DR1_I_MASK					(0x7 << 27)
-#define OMAP4_USBB1_DR1_SR_SHIFT				25
-#define OMAP4_USBB1_DR1_SR_MASK					(0x3 << 25)
-#define OMAP4_USBB1_DR1_I_SHIFT					22
-#define OMAP4_USBB1_DR1_I_MASK					(0x7 << 22)
-#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT				20
-#define OMAP4_USBB1_HSIC_DATA_WD_MASK				(0x3 << 20)
-#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT			18
-#define OMAP4_USBB1_HSIC_STROBE_WD_MASK				(0x3 << 18)
-#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT				16
-#define OMAP4_USBB2_HSIC_DATA_WD_MASK				(0x3 << 16)
-#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT			14
-#define OMAP4_USBB2_HSIC_STROBE_WD_MASK				(0x3 << 14)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		13
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 13)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT			11
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 11)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		10
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 10)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT		8
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 8)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		7
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 7)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT			5
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 5)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		4
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 4)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT		2
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 2)
-
-/* CONTROL_SLIMBUS */
-#define OMAP4_SLIMBUS1_DR0_MB_SHIFT				30
-#define OMAP4_SLIMBUS1_DR0_MB_MASK				(0x3 << 30)
-#define OMAP4_SLIMBUS1_DR1_MB_SHIFT				28
-#define OMAP4_SLIMBUS1_DR1_MB_MASK				(0x3 << 28)
-#define OMAP4_SLIMBUS2_DR0_MB_SHIFT				26
-#define OMAP4_SLIMBUS2_DR0_MB_MASK				(0x3 << 26)
-#define OMAP4_SLIMBUS2_DR1_MB_SHIFT				24
-#define OMAP4_SLIMBUS2_DR1_MB_MASK				(0x3 << 24)
-#define OMAP4_SLIMBUS2_DR2_MB_SHIFT				22
-#define OMAP4_SLIMBUS2_DR2_MB_MASK				(0x3 << 22)
-#define OMAP4_SLIMBUS2_DR3_MB_SHIFT				20
-#define OMAP4_SLIMBUS2_DR3_MB_MASK				(0x3 << 20)
-#define OMAP4_SLIMBUS1_DR0_LB_SHIFT				19
-#define OMAP4_SLIMBUS1_DR0_LB_MASK				(1 << 19)
-#define OMAP4_SLIMBUS2_DR1_LB_SHIFT				18
-#define OMAP4_SLIMBUS2_DR1_LB_MASK				(1 << 18)
-
-/* CONTROL_PBIASLITE */
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT			31
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK			(1 << 31)
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT		30
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 30)
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT			29
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK			(1 << 29)
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT			28
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK			(1 << 28)
-#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT			27
-#define OMAP4_USIM_PBIASLITE_VMODE_MASK				(1 << 27)
-#define OMAP4_MMC1_PWRDNZ_SHIFT					26
-#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT			25
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK			(1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT		24
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT			23
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT			22
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT			21
-#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT				20
-#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK				(1 << 20)
-
-/* CONTROL_I2C_0 */
-#define OMAP4_I2C4_SDA_GLFENB_SHIFT				31
-#define OMAP4_I2C4_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT				29
-#define OMAP4_I2C4_SDA_LOAD_BITS_MASK				(0x3 << 29)
-#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT				28
-#define OMAP4_I2C4_SDA_PULLUPRESX_MASK				(1 << 28)
-#define OMAP4_I2C3_SDA_GLFENB_SHIFT				27
-#define OMAP4_I2C3_SDA_GLFENB_MASK				(1 << 27)
-#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT				25
-#define OMAP4_I2C3_SDA_LOAD_BITS_MASK				(0x3 << 25)
-#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT				24
-#define OMAP4_I2C3_SDA_PULLUPRESX_MASK				(1 << 24)
-#define OMAP4_I2C2_SDA_GLFENB_SHIFT				23
-#define OMAP4_I2C2_SDA_GLFENB_MASK				(1 << 23)
-#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT				21
-#define OMAP4_I2C2_SDA_LOAD_BITS_MASK				(0x3 << 21)
-#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT				20
-#define OMAP4_I2C2_SDA_PULLUPRESX_MASK				(1 << 20)
-#define OMAP4_I2C1_SDA_GLFENB_SHIFT				19
-#define OMAP4_I2C1_SDA_GLFENB_MASK				(1 << 19)
-#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT				17
-#define OMAP4_I2C1_SDA_LOAD_BITS_MASK				(0x3 << 17)
-#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT				16
-#define OMAP4_I2C1_SDA_PULLUPRESX_MASK				(1 << 16)
-#define OMAP4_I2C4_SCL_GLFENB_SHIFT				15
-#define OMAP4_I2C4_SCL_GLFENB_MASK				(1 << 15)
-#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT				13
-#define OMAP4_I2C4_SCL_LOAD_BITS_MASK				(0x3 << 13)
-#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT				12
-#define OMAP4_I2C4_SCL_PULLUPRESX_MASK				(1 << 12)
-#define OMAP4_I2C3_SCL_GLFENB_SHIFT				11
-#define OMAP4_I2C3_SCL_GLFENB_MASK				(1 << 11)
-#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT				9
-#define OMAP4_I2C3_SCL_LOAD_BITS_MASK				(0x3 << 9)
-#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT				8
-#define OMAP4_I2C3_SCL_PULLUPRESX_MASK				(1 << 8)
-#define OMAP4_I2C2_SCL_GLFENB_SHIFT				7
-#define OMAP4_I2C2_SCL_GLFENB_MASK				(1 << 7)
-#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT				5
-#define OMAP4_I2C2_SCL_LOAD_BITS_MASK				(0x3 << 5)
-#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT				4
-#define OMAP4_I2C2_SCL_PULLUPRESX_MASK				(1 << 4)
-#define OMAP4_I2C1_SCL_GLFENB_SHIFT				3
-#define OMAP4_I2C1_SCL_GLFENB_MASK				(1 << 3)
-#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT				1
-#define OMAP4_I2C1_SCL_LOAD_BITS_MASK				(0x3 << 1)
-#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT				0
-#define OMAP4_I2C1_SCL_PULLUPRESX_MASK				(1 << 0)
-
-/* CONTROL_CAMERA_RX */
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT			31
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK			(1 << 31)
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT			29
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK			(0x3 << 29)
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT			24
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK			(0x1f << 24)
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT			22
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK			(0x3 << 22)
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT			21
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK			(1 << 21)
-#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT			19
-#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK			(0x3 << 19)
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT			18
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK			(1 << 18)
-#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT			16
-#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK			(0x3 << 16)
-
-/* CONTROL_AVDAC */
-#define OMAP4_AVDAC_ACEN_SHIFT					31
-#define OMAP4_AVDAC_ACEN_MASK					(1 << 31)
-#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT				30
-#define OMAP4_AVDAC_TVOUTBYPASS_MASK				(1 << 30)
-#define OMAP4_AVDAC_INPUTINV_SHIFT				29
-#define OMAP4_AVDAC_INPUTINV_MASK				(1 << 29)
-#define OMAP4_AVDAC_CTL_SHIFT					13
-#define OMAP4_AVDAC_CTL_MASK					(0xffff << 13)
-#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT				12
-#define OMAP4_AVDAC_CTL_WR_ACK_MASK				(1 << 12)
-
-/* CONTROL_HDMI_TX_PHY */
-#define OMAP4_HDMITXPHY_PADORDER_SHIFT				31
-#define OMAP4_HDMITXPHY_PADORDER_MASK				(1 << 31)
-#define OMAP4_HDMITXPHY_TXVALID_SHIFT				30
-#define OMAP4_HDMITXPHY_TXVALID_MASK				(1 << 30)
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT			29
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK			(1 << 29)
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT			28
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK			(1 << 28)
-
-/* CONTROL_MMC2 */
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT			31
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK			(1 << 31)
-
-/* CONTROL_DSIPHY */
-#define OMAP4_DSI2_LANEENABLE_SHIFT				29
-#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
-#define OMAP4_DSI1_LANEENABLE_SHIFT				24
-#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT					19
-#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT					14
-#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
-
-/* CONTROL_MCBSPLP */
-#define OMAP4_ALBCTRLRX_FSX_SHIFT				31
-#define OMAP4_ALBCTRLRX_FSX_MASK				(1 << 31)
-#define OMAP4_ALBCTRLRX_CLKX_SHIFT				30
-#define OMAP4_ALBCTRLRX_CLKX_MASK				(1 << 30)
-#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT				29
-#define OMAP4_ABE_MCBSP1_DR_EN_MASK				(1 << 29)
-
-/* CONTROL_USB2PHYCORE */
-#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT			31
-#define OMAP4_USB2PHY_AUTORESUME_EN_MASK			(1 << 31)
-#define OMAP4_USB2PHY_DISCHGDET_SHIFT				30
-#define OMAP4_USB2PHY_DISCHGDET_MASK				(1 << 30)
-#define OMAP4_USB2PHY_GPIOMODE_SHIFT				29
-#define OMAP4_USB2PHY_GPIOMODE_MASK				(1 << 29)
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT			28
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK			(1 << 28)
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT			27
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK			(1 << 27)
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT			26
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK			(1 << 26)
-#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT				25
-#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK				(1 << 25)
-#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT			24
-#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK				(1 << 24)
-#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT			21
-#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK			(0x7 << 21)
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT			20
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK			(1 << 20)
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT			19
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK			(1 << 19)
-#define OMAP4_USB2PHY_DATADET_SHIFT				18
-#define OMAP4_USB2PHY_DATADET_MASK				(1 << 18)
-#define OMAP4_USB2PHY_SINKONDP_SHIFT				17
-#define OMAP4_USB2PHY_SINKONDP_MASK				(1 << 17)
-#define OMAP4_USB2PHY_SRCONDM_SHIFT				16
-#define OMAP4_USB2PHY_SRCONDM_MASK				(1 << 16)
-#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT			15
-#define OMAP4_USB2PHY_RESTARTCHGDET_MASK			(1 << 15)
-#define OMAP4_USB2PHY_CHGDETDONE_SHIFT				14
-#define OMAP4_USB2PHY_CHGDETDONE_MASK				(1 << 14)
-#define OMAP4_USB2PHY_CHGDETECTED_SHIFT				13
-#define OMAP4_USB2PHY_CHGDETECTED_MASK				(1 << 13)
-#define OMAP4_USB2PHY_MCPCPUEN_SHIFT				12
-#define OMAP4_USB2PHY_MCPCPUEN_MASK				(1 << 12)
-#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT				11
-#define OMAP4_USB2PHY_MCPCMODEEN_MASK				(1 << 11)
-#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT			10
-#define OMAP4_USB2PHY_RESETDONEMCLK_MASK			(1 << 10)
-#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT			9
-#define OMAP4_USB2PHY_UTMIRESETDONE_MASK			(1 << 9)
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT			8
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK			(1 << 8)
-#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT			7
-#define OMAP4_USB2PHY_DATAPOLARITYN_MASK			(1 << 7)
-#define OMAP4_USBDPLL_FREQLOCK_SHIFT				6
-#define OMAP4_USBDPLL_FREQLOCK_MASK				(1 << 6)
-#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT			5
-#define OMAP4_USB2PHY_RESETDONETCLK_MASK			(1 << 5)
-
-/* CONTROL_I2C_1 */
-#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT				31
-#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT			29
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK			(0x3 << 29)
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT			28
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
-#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT				27
-#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK				(1 << 27)
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT			25
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK			(0x3 << 25)
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT			24
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
-#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT				23
-#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK				(1 << 23)
-#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT				22
-#define OMAP4_HDMI_DDC_SDA_NMODE_MASK				(1 << 22)
-#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT				21
-#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK				(1 << 21)
-#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT				20
-#define OMAP4_HDMI_DDC_SCL_NMODE_MASK				(1 << 20)
-
-/* CONTROL_MMC1 */
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT			31
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT			30
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT			29
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT			28
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT			27
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT			26
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT			25
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
-#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT				24
-#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK				(1 << 24)
-#define OMAP4_USB_FD_CDEN_SHIFT					23
-#define OMAP4_USB_FD_CDEN_MASK					(1 << 23)
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT			22
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK				(1 << 22)
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT			21
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK				(1 << 21)
-
-/* CONTROL_HSI */
-#define OMAP4_HSI1_CALLOOP_SEL_SHIFT				31
-#define OMAP4_HSI1_CALLOOP_SEL_MASK				(1 << 31)
-#define OMAP4_HSI1_CALMUX_SEL_SHIFT				30
-#define OMAP4_HSI1_CALMUX_SEL_MASK				(1 << 30)
-#define OMAP4_HSI2_CALLOOP_SEL_SHIFT				29
-#define OMAP4_HSI2_CALLOOP_SEL_MASK				(1 << 29)
-#define OMAP4_HSI2_CALMUX_SEL_SHIFT				28
-#define OMAP4_HSI2_CALMUX_SEL_MASK				(1 << 28)
-
-/* CONTROL_USB */
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT		31
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK		(1 << 31)
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT		30
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK		(1 << 30)
-
-/* CONTROL_HDQ */
-#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT				31
-#define OMAP4_HDQ_SIO_PWRDNZ_MASK				(1 << 31)
-
-/* CONTROL_LPDDR2IO1_0 */
-#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR4_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR4_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR4_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR4_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR3_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR3_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR3_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR3_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR2_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR2_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR2_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR2_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT				6
-#define OMAP4_LPDDR2IO1_GR1_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR1_I_SHIFT				3
-#define OMAP4_LPDDR2IO1_GR1_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT				1
-#define OMAP4_LPDDR2IO1_GR1_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_1 */
-#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR8_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR8_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR8_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR8_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR7_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR7_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR7_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR7_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR6_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR6_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR6_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR6_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT				6
-#define OMAP4_LPDDR2IO1_GR5_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR5_I_SHIFT				3
-#define OMAP4_LPDDR2IO1_GR5_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT				1
-#define OMAP4_LPDDR2IO1_GR5_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_2 */
-#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR11_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR11_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR11_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR11_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR10_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR10_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR10_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR10_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR9_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR9_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR9_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR9_WD_MASK				(0x3 << 9)
-
-/* CONTROL_LPDDR2IO1_3 */
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT			31
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK			(1 << 31)
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT			30
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK			(1 << 30)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT			29
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK			(1 << 29)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT			28
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK			(1 << 28)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT			27
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK			(1 << 27)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT			26
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK			(1 << 26)
-#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT			25
-#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK				(1 << 25)
-#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT			24
-#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK				(1 << 24)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT			23
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT			22
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT			21
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT			20
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT			19
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT			18
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT			17
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT			16
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT			15
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK			(1 << 15)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT			14
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK			(1 << 14)
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT			13
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK				(1 << 13)
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT			12
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK				(1 << 12)
-
-/* CONTROL_LPDDR2IO2_0 */
-#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR4_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR4_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR4_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR4_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR3_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR3_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR3_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR3_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR2_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR2_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR2_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR2_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT				6
-#define OMAP4_LPDDR2IO2_GR1_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR1_I_SHIFT				3
-#define OMAP4_LPDDR2IO2_GR1_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT				1
-#define OMAP4_LPDDR2IO2_GR1_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_1 */
-#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR8_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR8_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR8_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR8_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR7_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR7_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR7_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR7_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR6_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR6_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR6_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR6_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT				6
-#define OMAP4_LPDDR2IO2_GR5_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR5_I_SHIFT				3
-#define OMAP4_LPDDR2IO2_GR5_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT				1
-#define OMAP4_LPDDR2IO2_GR5_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_2 */
-#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR11_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR11_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR11_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR11_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR10_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR10_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR10_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR10_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR9_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR9_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR9_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR9_WD_MASK				(0x3 << 9)
-
-/* CONTROL_LPDDR2IO2_3 */
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT			31
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK			(1 << 31)
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT			30
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK			(1 << 30)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT			29
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK			(1 << 29)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT			28
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK			(1 << 28)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT			27
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK			(1 << 27)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT			26
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK			(1 << 26)
-#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT			25
-#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK				(1 << 25)
-#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT			24
-#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK				(1 << 24)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT			23
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT			22
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT			21
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT			20
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT			19
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT			18
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT			17
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT			16
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT			15
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK			(1 << 15)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT			14
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK			(1 << 14)
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT			13
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK				(1 << 13)
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT			12
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK				(1 << 12)
-
-/* CONTROL_BUS_HOLD */
-#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT				31
-#define OMAP4_ABE_DMIC_DIN3_EN_MASK				(1 << 31)
-#define OMAP4_MCSPI1_CS3_EN_SHIFT				30
-#define OMAP4_MCSPI1_CS3_EN_MASK				(1 << 30)
-
-/* CONTROL_C2C */
-#define OMAP4_MIRROR_MODE_EN_SHIFT				31
-#define OMAP4_MIRROR_MODE_EN_MASK				(1 << 31)
-#define OMAP4_C2C_SPARE_SHIFT					24
-#define OMAP4_C2C_SPARE_MASK					(0x7f << 24)
-
-/* CORE_CONTROL_SPARE_RW */
-#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT			0
-#define OMAP4_CORE_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R */
-#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT			0
-#define OMAP4_CORE_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R_C0 */
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT			31
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK			(1 << 31)
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT			30
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK			(1 << 30)
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT			29
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK			(1 << 29)
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT			28
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK			(1 << 28)
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT			27
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK			(1 << 27)
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT			26
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK			(1 << 26)
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT			25
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK			(1 << 25)
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT			24
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK			(1 << 24)
-
-/* CONTROL_EFUSE_1 */
-#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT				24
-#define OMAP4_AVDAC_TRIM_BYTE3_MASK				(0x7f << 24)
-#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT				16
-#define OMAP4_AVDAC_TRIM_BYTE2_MASK				(0xff << 16)
-#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT				8
-#define OMAP4_AVDAC_TRIM_BYTE1_MASK				(0xff << 8)
-#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT				0
-#define OMAP4_AVDAC_TRIM_BYTE0_MASK				(0xff << 0)
-
-/* CONTROL_EFUSE_2 */
-#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT				31
-#define OMAP4_EFUSE_SMART2TEST_P0_MASK				(1 << 31)
-#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT				30
-#define OMAP4_EFUSE_SMART2TEST_P1_MASK				(1 << 30)
-#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT				29
-#define OMAP4_EFUSE_SMART2TEST_P2_MASK				(1 << 29)
-#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT				28
-#define OMAP4_EFUSE_SMART2TEST_P3_MASK				(1 << 28)
-#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT				27
-#define OMAP4_EFUSE_SMART2TEST_N0_MASK				(1 << 27)
-#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT				26
-#define OMAP4_EFUSE_SMART2TEST_N1_MASK				(1 << 26)
-#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT				25
-#define OMAP4_EFUSE_SMART2TEST_N2_MASK				(1 << 25)
-#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT				24
-#define OMAP4_EFUSE_SMART2TEST_N3_MASK				(1 << 24)
-#define OMAP4_LPDDR2_PTV_N1_SHIFT				23
-#define OMAP4_LPDDR2_PTV_N1_MASK				(1 << 23)
-#define OMAP4_LPDDR2_PTV_N2_SHIFT				22
-#define OMAP4_LPDDR2_PTV_N2_MASK				(1 << 22)
-#define OMAP4_LPDDR2_PTV_N3_SHIFT				21
-#define OMAP4_LPDDR2_PTV_N3_MASK				(1 << 21)
-#define OMAP4_LPDDR2_PTV_N4_SHIFT				20
-#define OMAP4_LPDDR2_PTV_N4_MASK				(1 << 20)
-#define OMAP4_LPDDR2_PTV_N5_SHIFT				19
-#define OMAP4_LPDDR2_PTV_N5_MASK				(1 << 19)
-#define OMAP4_LPDDR2_PTV_P1_SHIFT				18
-#define OMAP4_LPDDR2_PTV_P1_MASK				(1 << 18)
-#define OMAP4_LPDDR2_PTV_P2_SHIFT				17
-#define OMAP4_LPDDR2_PTV_P2_MASK				(1 << 17)
-#define OMAP4_LPDDR2_PTV_P3_SHIFT				16
-#define OMAP4_LPDDR2_PTV_P3_MASK				(1 << 16)
-#define OMAP4_LPDDR2_PTV_P4_SHIFT				15
-#define OMAP4_LPDDR2_PTV_P4_MASK				(1 << 15)
-#define OMAP4_LPDDR2_PTV_P5_SHIFT				14
-#define OMAP4_LPDDR2_PTV_P5_MASK				(1 << 14)
-
-/* CONTROL_EFUSE_3 */
-#define OMAP4_STD_FUSE_SPARE_1_SHIFT				24
-#define OMAP4_STD_FUSE_SPARE_1_MASK				(0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_2_SHIFT				16
-#define OMAP4_STD_FUSE_SPARE_2_MASK				(0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_3_SHIFT				8
-#define OMAP4_STD_FUSE_SPARE_3_MASK				(0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_4_SHIFT				0
-#define OMAP4_STD_FUSE_SPARE_4_MASK				(0xff << 0)
-
-/* CONTROL_EFUSE_4 */
-#define OMAP4_STD_FUSE_SPARE_5_SHIFT				24
-#define OMAP4_STD_FUSE_SPARE_5_MASK				(0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_6_SHIFT				16
-#define OMAP4_STD_FUSE_SPARE_6_MASK				(0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_7_SHIFT				8
-#define OMAP4_STD_FUSE_SPARE_7_MASK				(0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_8_SHIFT				0
-#define OMAP4_STD_FUSE_SPARE_8_MASK				(0xff << 0)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,236 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_PAD_WKUP_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_WKUP					0x4a31e000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION				0x0000
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO				0x0004
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG				0x0010
-#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0		0x007c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0	0x05a0
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1	0x05a4
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE			0x05a8
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR		0x05ac
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO			0x0600
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2			0x0604
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG				0x0608
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS				0x060c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW		0x0614
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R			0x0618
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0		0x061c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT				30
-#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT					16
-#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT					11
-#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT				8
-#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT				6
-#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT				0
-#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT					0
-#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT	16
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK			(1 << 13)
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT			6
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK			(1 << 6)
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT			5
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK			(1 << 5)
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT			3
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK			(1 << 3)
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK			(1 << 1)
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT			0
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK			(1 << 0)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_0 */
-#define OMAP4_FREF_DR0_SC_SHIFT					30
-#define OMAP4_FREF_DR0_SC_MASK					(0x3 << 30)
-#define OMAP4_FREF_DR1_SC_SHIFT					28
-#define OMAP4_FREF_DR1_SC_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR4_SC_SHIFT					26
-#define OMAP4_FREF_DR4_SC_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR5_SC_SHIFT					24
-#define OMAP4_FREF_DR5_SC_MASK					(0x3 << 24)
-#define OMAP4_FREF_DR6_SC_SHIFT					22
-#define OMAP4_FREF_DR6_SC_MASK					(0x3 << 22)
-#define OMAP4_FREF_DR7_SC_SHIFT					20
-#define OMAP4_FREF_DR7_SC_MASK					(0x3 << 20)
-#define OMAP4_GPIO_DR7_SC_SHIFT					18
-#define OMAP4_GPIO_DR7_SC_MASK					(0x3 << 18)
-#define OMAP4_DPM_DR0_SC_SHIFT					14
-#define OMAP4_DPM_DR0_SC_MASK					(0x3 << 14)
-#define OMAP4_SIM_DR0_SC_SHIFT					12
-#define OMAP4_SIM_DR0_SC_MASK					(0x3 << 12)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_1 */
-#define OMAP4_FREF_DR0_LB_SHIFT					30
-#define OMAP4_FREF_DR0_LB_MASK					(0x3 << 30)
-#define OMAP4_FREF_DR1_LB_SHIFT					28
-#define OMAP4_FREF_DR1_LB_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR4_LB_SHIFT					26
-#define OMAP4_FREF_DR4_LB_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR5_LB_SHIFT					24
-#define OMAP4_FREF_DR5_LB_MASK					(0x3 << 24)
-#define OMAP4_FREF_DR6_LB_SHIFT					22
-#define OMAP4_FREF_DR6_LB_MASK					(0x3 << 22)
-#define OMAP4_FREF_DR7_LB_SHIFT					20
-#define OMAP4_FREF_DR7_LB_MASK					(0x3 << 20)
-#define OMAP4_GPIO_DR7_LB_SHIFT					18
-#define OMAP4_GPIO_DR7_LB_MASK					(0x3 << 18)
-#define OMAP4_DPM_DR0_LB_SHIFT					14
-#define OMAP4_DPM_DR0_LB_MASK					(0x3 << 14)
-#define OMAP4_SIM_DR0_LB_SHIFT					12
-#define OMAP4_SIM_DR0_LB_MASK					(0x3 << 12)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_FREF_SHIFT				31
-#define OMAP4_VDDS_DV_FREF_MASK					(1 << 31)
-#define OMAP4_VDDS_DV_BANK2_SHIFT				30
-#define OMAP4_VDDS_DV_BANK2_MASK				(1 << 30)
-
-/* CONTROL_XTAL_OSCILLATOR */
-#define OMAP4_OSCILLATOR_BOOST_SHIFT				31
-#define OMAP4_OSCILLATOR_BOOST_MASK				(1 << 31)
-#define OMAP4_OSCILLATOR_OS_OUT_SHIFT				30
-#define OMAP4_OSCILLATOR_OS_OUT_MASK				(1 << 30)
-
-/* CONTROL_USIMIO */
-#define OMAP4_PAD_USIM_CLK_LOW_SHIFT				31
-#define OMAP4_PAD_USIM_CLK_LOW_MASK				(1 << 31)
-#define OMAP4_PAD_USIM_RST_LOW_SHIFT				29
-#define OMAP4_PAD_USIM_RST_LOW_MASK				(1 << 29)
-#define OMAP4_USIM_PWRDNZ_SHIFT					28
-#define OMAP4_USIM_PWRDNZ_MASK					(1 << 28)
-
-/* CONTROL_I2C_2 */
-#define OMAP4_SR_SDA_GLFENB_SHIFT				31
-#define OMAP4_SR_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_SR_SDA_LOAD_BITS_SHIFT				29
-#define OMAP4_SR_SDA_LOAD_BITS_MASK				(0x3 << 29)
-#define OMAP4_SR_SDA_PULLUPRESX_SHIFT				28
-#define OMAP4_SR_SDA_PULLUPRESX_MASK				(1 << 28)
-#define OMAP4_SR_SCL_GLFENB_SHIFT				27
-#define OMAP4_SR_SCL_GLFENB_MASK				(1 << 27)
-#define OMAP4_SR_SCL_LOAD_BITS_SHIFT				25
-#define OMAP4_SR_SCL_LOAD_BITS_MASK				(0x3 << 25)
-#define OMAP4_SR_SCL_PULLUPRESX_SHIFT				24
-#define OMAP4_SR_SCL_PULLUPRESX_MASK				(1 << 24)
-
-/* CONTROL_JTAG */
-#define OMAP4_JTAG_NTRST_EN_SHIFT				31
-#define OMAP4_JTAG_NTRST_EN_MASK				(1 << 31)
-#define OMAP4_JTAG_TCK_EN_SHIFT					30
-#define OMAP4_JTAG_TCK_EN_MASK					(1 << 30)
-#define OMAP4_JTAG_RTCK_EN_SHIFT				29
-#define OMAP4_JTAG_RTCK_EN_MASK					(1 << 29)
-#define OMAP4_JTAG_TDI_EN_SHIFT					28
-#define OMAP4_JTAG_TDI_EN_MASK					(1 << 28)
-#define OMAP4_JTAG_TDO_EN_SHIFT					27
-#define OMAP4_JTAG_TDO_EN_MASK					(1 << 27)
-
-/* CONTROL_SYS */
-#define OMAP4_SYS_NRESWARM_PIPU_SHIFT				31
-#define OMAP4_SYS_NRESWARM_PIPU_MASK				(1 << 31)
-
-/* WKUP_CONTROL_SPARE_RW */
-#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT			0
-#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R */
-#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT			0
-#define OMAP4_WKUP_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R_C0 */
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT			31
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK			(1 << 31)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT			30
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK			(1 << 30)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT			29
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK			(1 << 29)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT			28
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK			(1 << 28)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT			27
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK			(1 << 27)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT			26
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK			(1 << 26)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT			25
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK			(1 << 25)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT			24
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK			(1 << 24)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/devices.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/devices.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -432,9 +432,9 @@ static int __init omap2_init_devices(voi
 	 */
 	omap_init_audio();
 	omap_init_camera();
-	omap_init_mbox();
 	/* If dtb is there, the devices will be created dynamically */
 	if (!of_have_populated_dt()) {
+		omap_init_mbox();
 		omap_init_mcspi();
 		omap_init_sham();
 		omap_init_aes();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/dma.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dma.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -259,6 +259,9 @@ static int __init omap2_system_dma_init_
 	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
 		d->dev_caps |= HS_CHANNELS_RESERVED;
 
+	if (platform_get_irq_byname(pdev, "0") < 0)
+		d->dev_caps |= DMA_ENGINE_HANDLE_IRQ;
+
 	/* Check the capabilities register for descriptor loading feature */
 	if (dma_read(CAPS_0, 0) & DMA_HAS_DESCRIPTOR_CAPS)
 		dma_common_ch_end = CCDN;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/dpll3xxx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dpll3xxx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/dpll3xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dpll3xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,11 +28,8 @@
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
 
-#include "soc.h"
 #include "clockdomain.h"
 #include "clock.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 #define DPLL_AUTOIDLE_DISABLE			0x0
@@ -310,7 +307,7 @@ static int omap3_noncore_dpll_program(st
 	 * Set jitter correction. Jitter correction applicable for OMAP343X
 	 * only since freqsel field is no longer present on other devices.
 	 */
-	if (cpu_is_omap343x()) {
+	if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
 		v = omap2_clk_readl(clk, dd->control_reg);
 		v &= ~dd->freqsel_mask;
 		v |= freqsel << __ffs(dd->freqsel_mask);
@@ -478,6 +475,7 @@ int omap3_noncore_dpll_set_rate(struct c
 {
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	struct clk *new_parent = NULL;
+	unsigned long rrate;
 	u16 freqsel = 0;
 	struct dpll_data *dd;
 	int ret;
@@ -505,14 +503,22 @@ int omap3_noncore_dpll_set_rate(struct c
 		__clk_prepare(dd->clk_ref);
 		clk_enable(dd->clk_ref);
 
-		if (dd->last_rounded_rate != rate)
-			rate = __clk_round_rate(hw->clk, rate);
+		/* XXX this check is probably pointless in the CCF context */
+		if (dd->last_rounded_rate != rate) {
+			rrate = __clk_round_rate(hw->clk, rate);
+			if (rrate != rate) {
+				pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
+					__func__, __clk_get_name(hw->clk),
+					rrate, rate);
+				rate = rrate;
+			}
+		}
 
 		if (dd->last_rounded_rate == 0)
 			return -EINVAL;
 
 		/* Freqsel is available only on OMAP343X devices */
-		if (cpu_is_omap343x()) {
+		if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			WARN_ON(!freqsel);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/dpll44xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dpll44xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/dpll44xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dpll44xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,10 +15,7 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 
-#include "soc.h"
 #include "clock.h"
-#include "clock44xx.h"
-#include "cm-regbits-44xx.h"
 
 /*
  * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
@@ -29,13 +26,23 @@
 #define OMAP4_DPLL_LP_FINT_MAX	1000000
 #define OMAP4_DPLL_LP_FOUT_MAX	100000000
 
+/*
+ * Bitfield declarations
+ */
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK		(1 << 8)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK		(1 << 10)
+#define OMAP4430_DPLL_REGM4XEN_MASK			(1 << 11)
+
+/* Static rate multiplier for OMAP4 REGM4XEN clocks */
+#define OMAP4430_REGM4XEN_MULT				4
+
 /* Supported only on OMAP4 */
 int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
 {
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return -EINVAL;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -54,7 +61,7 @@ void omap4_dpllmx_allow_gatectrl(struct
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -72,7 +79,7 @@ void omap4_dpllmx_deny_gatectrl(struct c
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/dsp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dsp.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/dsp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/dsp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- * TI's OMAP DSP platform device registration
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * XXX The function pointers to the PRM/CM functions are incorrect and
- * should be removed.  No device driver should be changing PRM/CM bits
- * directly; that's a layering violation -- those bits are the responsibility
- * of the OMAP PM core code.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/memblock.h>
-
-#include "control.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-#include "omap-pm.h"
-#endif
-#include "soc.h"
-
-#include <linux/platform_data/dsp-omap.h>
-
-static struct platform_device *omap_dsp_pdev;
-
-static struct omap_dsp_platform_data omap_dsp_pdata __initdata = {
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-	.dsp_set_min_opp = omap_pm_dsp_set_min_opp,
-	.dsp_get_opp = omap_pm_dsp_get_opp,
-	.cpu_set_freq = omap_pm_cpu_set_freq,
-	.cpu_get_freq = omap_pm_cpu_get_freq,
-#endif
-	.dsp_prm_read = omap2_prm_read_mod_reg,
-	.dsp_prm_write = omap2_prm_write_mod_reg,
-	.dsp_prm_rmw_bits = omap2_prm_rmw_mod_reg_bits,
-	.dsp_cm_read = omap2_cm_read_mod_reg,
-	.dsp_cm_write = omap2_cm_write_mod_reg,
-	.dsp_cm_rmw_bits = omap2_cm_rmw_mod_reg_bits,
-
-	.set_bootaddr = omap_ctrl_write_dsp_boot_addr,
-	.set_bootmode = omap_ctrl_write_dsp_boot_mode,
-};
-
-static phys_addr_t omap_dsp_phys_mempool_base;
-
-void __init omap_dsp_reserve_sdram_memblock(void)
-{
-	phys_addr_t size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE;
-	phys_addr_t paddr;
-
-	if (!cpu_is_omap34xx())
-		return;
-
-	if (!size)
-		return;
-
-	paddr = arm_memblock_steal(size, SZ_1M);
-	if (!paddr) {
-		pr_err("%s: failed to reserve %llx bytes\n",
-				__func__, (unsigned long long)size);
-		return;
-	}
-
-	omap_dsp_phys_mempool_base = paddr;
-}
-
-static phys_addr_t omap_dsp_get_mempool_base(void)
-{
-	return omap_dsp_phys_mempool_base;
-}
-
-static int __init omap_dsp_init(void)
-{
-	struct platform_device *pdev;
-	int err = -ENOMEM;
-	struct omap_dsp_platform_data *pdata = &omap_dsp_pdata;
-
-	if (!cpu_is_omap34xx())
-		return 0;
-
-	pdata->phys_mempool_base = omap_dsp_get_mempool_base();
-
-	if (pdata->phys_mempool_base) {
-		pdata->phys_mempool_size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE;
-		pr_info("%s: %llx bytes @ %llx\n", __func__,
-			(unsigned long long)pdata->phys_mempool_size,
-			(unsigned long long)pdata->phys_mempool_base);
-	}
-
-	pdev = platform_device_alloc("omap-dsp", -1);
-	if (!pdev)
-		goto err_out;
-
-	err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
-	if (err)
-		goto err_out;
-
-	err = platform_device_add(pdev);
-	if (err)
-		goto err_out;
-
-	omap_dsp_pdev = pdev;
-	return 0;
-
-err_out:
-	platform_device_put(pdev);
-	return err;
-}
-module_init(omap_dsp_init);
-
-static void __exit omap_dsp_exit(void)
-{
-	if (!cpu_is_omap34xx())
-		return;
-
-	platform_device_unregister(omap_dsp_pdev);
-}
-module_exit(omap_dsp_exit);
-
-MODULE_AUTHOR("Hiroshi DOYU");
-MODULE_DESCRIPTION("TI's OMAP DSP platform device registration");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/gpmc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/gpmc.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/gpmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/gpmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1207,8 +1207,7 @@ int gpmc_cs_program_settings(int cs, str
 		}
 	}
 
-	if ((p->wait_on_read || p->wait_on_write) &&
-	    (p->wait_pin > gpmc_nr_waitpins)) {
+	if (p->wait_pin > gpmc_nr_waitpins) {
 		pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
 		return -EINVAL;
 	}
@@ -1288,8 +1287,8 @@ void gpmc_read_settings_dt(struct device
 		p->wait_on_write = of_property_read_bool(np,
 							 "gpmc,wait-on-write");
 		if (!p->wait_on_read && !p->wait_on_write)
-			pr_warn("%s: read/write wait monitoring not enabled!\n",
-				__func__);
+			pr_debug("%s: rd/wr wait monitoring not enabled!\n",
+				 __func__);
 	}
 }
 
@@ -1403,8 +1402,11 @@ static int gpmc_probe_nand_child(struct
 		pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
-		!strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+
+	if (!strcmp(s, "sw"))
+		gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
+	else if (!strcmp(s, "ham1") ||
+		 !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
 		gpmc_nand_data->ecc_opt =
 				OMAP_ECC_HAM1_CODE_HW;
 	else if (!strcmp(s, "bch4"))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/gpmc-nand.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/gpmc-nand.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/gpmc-nand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/gpmc-nand.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,25 +24,6 @@
 /* minimum size for IO mapping */
 #define	NAND_IO_SIZE	4
 
-static struct resource gpmc_nand_resource[] = {
-	{
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device gpmc_nand_device = {
-	.name		= "omap2-nand",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(gpmc_nand_resource),
-	.resource	= gpmc_nand_resource,
-};
-
 static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
 {
 	/* platforms which support all ECC schemes */
@@ -68,7 +49,8 @@ static bool gpmc_hwecc_bch_capable(enum
 		return 0;
 
 	/* legacy platforms support only HAM1 (1-bit Hamming) ECC scheme */
-	if (ecc_opt == OMAP_ECC_HAM1_CODE_HW)
+	if (ecc_opt == OMAP_ECC_HAM1_CODE_HW ||
+	    ecc_opt == OMAP_ECC_HAM1_CODE_SW)
 		return 1;
 	else
 		return 0;
@@ -95,43 +77,41 @@ int gpmc_nand_init(struct omap_nand_plat
 {
 	int err	= 0;
 	struct gpmc_settings s;
-	struct device *dev = &gpmc_nand_device.dev;
-
-	memset(&s, 0, sizeof(struct gpmc_settings));
+	struct platform_device *pdev;
+	struct resource gpmc_nand_res[] = {
+		{ .flags = IORESOURCE_MEM, },
+		{ .flags = IORESOURCE_IRQ, },
+		{ .flags = IORESOURCE_IRQ, },
+	};
 
-	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+	BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
 
 	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				(unsigned long *)&gpmc_nand_resource[0].start);
+			      (unsigned long *)&gpmc_nand_res[0].start);
 	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
-			gpmc_nand_data->cs, err);
+		pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n",
+		       gpmc_nand_data->cs, err);
 		return err;
 	}
-
-	gpmc_nand_resource[0].end = gpmc_nand_resource[0].start +
-							NAND_IO_SIZE - 1;
-
-	gpmc_nand_resource[1].start =
-				gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
-	gpmc_nand_resource[2].start =
-				gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
+	gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
+	gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
+	gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
 
 	if (gpmc_t) {
 		err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
 		if (err < 0) {
-			dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+			pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
 			return err;
 		}
 	}
 
+	memset(&s, 0, sizeof(struct gpmc_settings));
 	if (gpmc_nand_data->of_node)
 		gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
 	else
 		gpmc_set_legacy(gpmc_nand_data, &s);
 
 	s.device_nand = true;
-
 	err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
 	if (err < 0)
 		goto out_free_cs;
@@ -143,18 +123,34 @@ int gpmc_nand_init(struct omap_nand_plat
 	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
 
 	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
-		dev_err(dev, "Unsupported NAND ECC scheme selected\n");
-		return -EINVAL;
+		pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
+		err = -EINVAL;
+		goto out_free_cs;
 	}
 
-	err = platform_device_register(&gpmc_nand_device);
-	if (err < 0) {
-		dev_err(dev, "Unable to register NAND device\n");
-		goto out_free_cs;
+
+	pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
+	if (pdev) {
+		err = platform_device_add_resources(pdev, gpmc_nand_res,
+						    ARRAY_SIZE(gpmc_nand_res));
+		if (!err)
+			pdev->dev.platform_data = gpmc_nand_data;
+	} else {
+		err = -ENOMEM;
+	}
+	if (err)
+		goto out_free_pdev;
+
+	err = platform_device_add(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to register NAND device\n");
+		goto out_free_pdev;
 	}
 
 	return 0;
 
+out_free_pdev:
+	platform_device_put(pdev);
 out_free_cs:
 	gpmc_cs_free(gpmc_nand_data->cs);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/id.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/id.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/id.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/id.c	2014-09-28 17:29:07.000000000 -0400
@@ -663,7 +663,7 @@ void __init dra7xxx_check_revision(void)
 
 	default:
 		/* Unknown default to latest silicon rev as default*/
-		pr_warn("%s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%d)\n",
+		pr_warn("%s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%x)\n",
 			__func__, idcode, hawkeye, rev);
 		omap_revision = DRA752_REV_ES1_1;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/io.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/io.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,6 +53,7 @@
 #include "prm2xxx.h"
 #include "prm3xxx.h"
 #include "prm44xx.h"
+#include "opp2xxx.h"
 
 /*
  * omap_clk_soc_init: points to a function that does the SoC-specific
@@ -410,7 +411,8 @@ void __init omap2420_init_early(void)
 	omap242x_clockdomains_init();
 	omap2420_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_soc_init = omap2420_clk_init;
+	omap_clk_soc_init = omap2420_dt_clk_init;
+	rate_table = omap2420_rate_table;
 }
 
 void __init omap2420_init_late(void)
@@ -439,7 +441,8 @@ void __init omap2430_init_early(void)
 	omap243x_clockdomains_init();
 	omap2430_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap_clk_soc_init = omap2430_clk_init;
+	omap_clk_soc_init = omap2430_dt_clk_init;
+	rate_table = omap2430_rate_table;
 }
 
 void __init omap2430_init_late(void)
@@ -728,6 +731,8 @@ int __init omap_clk_init(void)
 	if (!omap_clk_soc_init)
 		return 0;
 
+	ti_clk_init_features();
+
 	ret = of_prcm_init();
 	if (!ret)
 		ret = omap_clk_soc_init();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,6 @@
 menu "TI OMAP/AM/DM/DRA Family"
 	depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
 
-config ARCH_OMAP
-	bool
-
 config ARCH_OMAP2
 	bool "TI OMAP2"
 	depends on ARCH_MULTI_V6
@@ -15,7 +12,6 @@ config ARCH_OMAP3
 	bool "TI OMAP3"
 	depends on ARCH_MULTI_V7
 	select ARCH_OMAP2PLUS
-	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select OMAP_INTERCONNECT
 	select PM_OPP if PM
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -176,13 +176,11 @@ obj-$(CONFIG_SOC_DRA7XX)		+= clockdomain
 
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_sys.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_virt_prcm_set.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_apll.o clkt2xxx_osc.o
+obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_apll.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2420)		+= cclock2420_data.o
-obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o cclock2430_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o clkt34xx_dpll3m2.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o
@@ -202,6 +200,7 @@ obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_d
 obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
+obj-y					+= omap_hwmod_common_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_3xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_interconnect_data.o
@@ -232,10 +231,6 @@ obj-$(CONFIG_HW_PERF_EVENTS)		+= pmu.o
 iommu-$(CONFIG_OMAP_IOMMU)		:= omap-iommu.o
 obj-y					+= $(iommu-m) $(iommu-y)
 
-ifneq ($(CONFIG_TIDSPBRIDGE),)
-obj-y					+= dsp.o
-endif
-
 # OMAP2420 MSDI controller integration support ("MMC")
 obj-$(CONFIG_SOC_OMAP2420)		+= msdi.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/mux.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/mux.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/mux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/mux.c	2014-09-28 17:29:07.000000000 -0400
@@ -681,29 +681,19 @@ static ssize_t omap_mux_dbg_signal_write
 					 const char __user *user_buf,
 					 size_t count, loff_t *ppos)
 {
-	char buf[OMAP_MUX_MAX_ARG_CHAR];
 	struct seq_file *seqf;
 	struct omap_mux *m;
-	unsigned long val;
-	int buf_size, ret;
+	u16 val;
+	int ret;
 	struct omap_mux_partition *partition;
 
 	if (count > OMAP_MUX_MAX_ARG_CHAR)
 		return -EINVAL;
 
-	memset(buf, 0, sizeof(buf));
-	buf_size = min(count, sizeof(buf) - 1);
-
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-
-	ret = strict_strtoul(buf, 0x10, &val);
+	ret = kstrtou16_from_user(user_buf, count, 0x10, &val);
 	if (ret < 0)
 		return ret;
 
-	if (val > 0xffff)
-		return -EINVAL;
-
 	seqf = file->private_data;
 	m = seqf->private;
 
@@ -711,7 +701,7 @@ static ssize_t omap_mux_dbg_signal_write
 	if (!partition)
 		return -ENODEV;
 
-	omap_mux_write(partition, (u16)val, m->reg_offset);
+	omap_mux_write(partition, val, m->reg_offset);
 	*ppos += count;
 
 	return count;
@@ -917,14 +907,14 @@ static void __init omap_mux_set_cmdline_
 
 	while ((token = strsep(&next_opt, ",")) != NULL) {
 		char *keyval, *name;
-		unsigned long val;
+		u16 val;
 
 		keyval = token;
 		name = strsep(&keyval, "=");
 		if (name) {
 			int res;
 
-			res = strict_strtoul(keyval, 0x10, &val);
+			res = kstrtou16(keyval, 0x10, &val);
 			if (res < 0)
 				continue;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_device.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_device.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_device.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@ static void _add_clkdev(struct omap_devi
 
 	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
 	if (!IS_ERR(r)) {
-		dev_warn(&od->pdev->dev,
+		dev_dbg(&od->pdev->dev,
 			 "alias %s already exists\n", clk_alias);
 		clk_put(r);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,6 @@
 #include <linux/i2c-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
@@ -163,18 +162,6 @@ static struct omap_hwmod omap2420_dma_sy
 };
 
 /* mailbox */
-static struct omap_mbox_dev_info omap2420_mailbox_info[] = {
-	{ .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 },
-	{ .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 },
-};
-
-static struct omap_mbox_pdata omap2420_mailbox_attrs = {
-	.num_users	= 4,
-	.num_fifos	= 6,
-	.info_cnt	= ARRAY_SIZE(omap2420_mailbox_info),
-	.info		= omap2420_mailbox_info,
-};
-
 static struct omap_hwmod omap2420_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap2xxx_mailbox_hwmod_class,
@@ -188,7 +175,6 @@ static struct omap_hwmod omap2420_mailbo
 			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
 		},
 	},
-	.dev_attr	= &omap2420_mailbox_attrs,
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
@@ -161,17 +160,6 @@ static struct omap_hwmod omap2430_dma_sy
 };
 
 /* mailbox */
-static struct omap_mbox_dev_info omap2430_mailbox_info[] = {
-	{ .name = "dsp", .tx_id = 0, .rx_id = 1 },
-};
-
-static struct omap_mbox_pdata omap2430_mailbox_attrs = {
-	.num_users	= 4,
-	.num_fifos	= 6,
-	.info_cnt	= ARRAY_SIZE(omap2430_mailbox_info),
-	.info		= omap2430_mailbox_info,
-};
-
 static struct omap_hwmod omap2430_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap2xxx_mailbox_hwmod_class,
@@ -185,7 +173,6 @@ static struct omap_hwmod omap2430_mailbo
 			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
 		},
 	},
-	.dev_attr	= &omap2430_mailbox_attrs,
 };
 
 /* mcspi3 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -152,15 +152,6 @@ struct omap_hwmod_addr_space omap2_dma_s
 	{ }
 };
 
-struct omap_hwmod_addr_space omap2_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x48094000,
-		.pa_end		= 0x48094000 + SZ_512 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
 struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
 	{
 		.name		= "mpu",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,46 +37,6 @@ struct omap_hwmod_class omap2_uart_class
 };
 
 /*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			   SYSS_HAS_RESET_STATUS),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dss_hwmod_class = {
-	.name	= "dss",
-	.sysc	= &omap2_dss_sysc,
-	.reset	= omap_dss_reset,
-};
-
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_rfbi_hwmod_class = {
-	.name	= "rfbi",
-	.sysc	= &omap2_rfbi_sysc,
-};
-
-/*
  * 'venc' class
  * video encoder
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -317,21 +317,11 @@ struct omap_hwmod_ocp_if am33xx_l4_per__
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space am33xx_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x480C8000,
-		.pa_end		= 0x480C8000 + (SZ_4K - 1),
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
 /* l4 ls -> mailbox */
 struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
 	.master		= &am33xx_l4_ls_hwmod,
 	.slave		= &am33xx_mailbox_hwmod,
 	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mailbox_addrs,
 	.user		= OCP_USER_MPU,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -2986,8 +2986,6 @@ static struct omap_hwmod_class omap3xxx_
 /* mmu isp */
 
 static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
-	.da_start	= 0x0,
-	.da_end		= 0xfffff000,
 	.nr_tlb_entries = 8,
 };
 
@@ -3026,8 +3024,6 @@ static struct omap_hwmod omap3xxx_mmu_is
 /* mmu iva */
 
 static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
-	.da_start	= 0x11000000,
-	.da_end		= 0xfffff000,
 	.nr_tlb_entries = 32,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@
 #include "omap_hwmod.h"
 #include "omap_hwmod_33xx_43xx_common_data.h"
 #include "prcm43xx.h"
+#include "omap_hwmod_common_data.h"
+
 
 /* IP blocks */
 static struct omap_hwmod am43xx_l4_hs_hwmod = {
@@ -415,6 +417,72 @@ static struct omap_hwmod am43xx_qspi_hwm
 	},
 };
 
+/* dss */
+
+static struct omap_hwmod am43xx_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap2_dss_hwmod_class,
+	.clkdm_name	= "dss_clkdm",
+	.main_clk	= "disp_clk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* dispc */
+
+struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = {
+	.manager_count		= 1,
+	.has_framedonetv_irq	= 0
+};
+
+static struct omap_hwmod_class_sysconfig am43xx_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am43xx_dispc_hwmod_class = {
+	.name	= "dispc",
+	.sysc	= &am43xx_dispc_sysc,
+};
+
+static struct omap_hwmod am43xx_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &am43xx_dispc_hwmod_class,
+	.clkdm_name	= "dss_clkdm",
+	.main_clk	= "disp_clk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+		},
+	},
+	.dev_attr	= &am43xx_dss_dispc_dev_attr,
+};
+
+/* rfbi */
+
+static struct omap_hwmod am43xx_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap2_rfbi_hwmod_class,
+	.clkdm_name	= "dss_clkdm",
+	.main_clk	= "disp_clk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+		},
+	},
+};
+
 /* Interfaces */
 static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
 	.master		= &am33xx_l3_main_hwmod,
@@ -654,6 +722,34 @@ static struct omap_hwmod_ocp_if am43xx_l
 	.user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if am43xx_dss__l3_main = {
+	.master		= &am43xx_dss_core_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "l3_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_dss_core_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_dispc = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_dss_dispc_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_dss_rfbi_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_wkup__synctimer,
 	&am43xx_l4_ls__timer8,
@@ -748,6 +844,10 @@ static struct omap_hwmod_ocp_if *am43xx_
 	&am43xx_l4_ls__ocp2scp1,
 	&am43xx_l3_s__usbotgss0,
 	&am43xx_l3_s__usbotgss1,
+	&am43xx_dss__l3_main,
+	&am43xx_l4_ls__dss,
+	&am43xx_l4_ls__dss_dispc,
+	&am43xx_l4_ls__dss_rfbi,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -2084,8 +2084,6 @@ static struct omap_hwmod_class omap44xx_
 /* mmu ipu */
 
 static struct omap_mmu_dev_attr mmu_ipu_dev_attr = {
-	.da_start	= 0x0,
-	.da_end		= 0xfffff000,
 	.nr_tlb_entries = 32,
 };
 
@@ -2133,8 +2131,6 @@ static struct omap_hwmod omap44xx_mmu_ip
 /* mmu dsp */
 
 static struct omap_mmu_dev_attr mmu_dsp_dev_attr = {
-	.da_start	= 0x0,
-	.da_end		= 0xfffff000,
 	.nr_tlb_entries = 32,
 };
 
@@ -4142,21 +4138,11 @@ static struct omap_hwmod_ocp_if omap44xx
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x4a0f4000,
-		.pa_end		= 0x4a0f41ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
 /* l4_cfg -> mailbox */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
 	.master		= &omap44xx_l4_cfg_hwmod,
 	.slave		= &omap44xx_mailbox_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_mailbox_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 #include "i2c.h"
 #include "mmc.h"
 #include "wd_timer.h"
+#include "soc.h"
 
 /* Base offset for all DRA7XX interrupts external to MPUSS */
 #define DRA7XX_IRQ_GIC_START	32
@@ -273,6 +274,56 @@ static struct omap_hwmod dra7xx_ctrl_mod
 };
 
 /*
+ * 'gmac' class
+ * cpsw/gmac sub system
+ */
+static struct omap_hwmod_class_sysconfig dra7xx_gmac_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x8,
+	.syss_offs	= 0x4,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+			   MSTANDBY_NO),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dra7xx_gmac_hwmod_class = {
+	.name		= "gmac",
+	.sysc		= &dra7xx_gmac_sysc,
+};
+
+static struct omap_hwmod dra7xx_gmac_hwmod = {
+	.name		= "gmac",
+	.class		= &dra7xx_gmac_hwmod_class,
+	.clkdm_name	= "gmac_clkdm",
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "dpll_gmac_ck",
+	.mpu_rt_idx	= 1,
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= DRA7XX_CM_GMAC_GMAC_CLKCTRL_OFFSET,
+			.context_offs	= DRA7XX_RM_GMAC_GMAC_CONTEXT_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mdio' class
+ */
+static struct omap_hwmod_class dra7xx_mdio_hwmod_class = {
+	.name		= "davinci_mdio",
+};
+
+static struct omap_hwmod dra7xx_mdio_hwmod = {
+	.name		= "davinci_mdio",
+	.class		= &dra7xx_mdio_hwmod_class,
+	.clkdm_name	= "gmac_clkdm",
+	.main_clk	= "dpll_gmac_ck",
+};
+
+/*
  * 'dcan' class
  *
  */
@@ -343,19 +394,10 @@ static struct omap_dma_dev_attr dma_dev_
 };
 
 /* dma_system */
-static struct omap_hwmod_irq_info dra7xx_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 + DRA7XX_IRQ_GIC_START },
-	{ .name = "1", .irq = 13 + DRA7XX_IRQ_GIC_START },
-	{ .name = "2", .irq = 14 + DRA7XX_IRQ_GIC_START },
-	{ .name = "3", .irq = 15 + DRA7XX_IRQ_GIC_START },
-	{ .irq = -1 }
-};
-
 static struct omap_hwmod dra7xx_dma_system_hwmod = {
 	.name		= "dma_system",
 	.class		= &dra7xx_dma_hwmod_class,
 	.clkdm_name	= "dma_clkdm",
-	.mpu_irqs	= dra7xx_dma_system_irqs,
 	.main_clk	= "l3_iclk_div",
 	.prcm = {
 		.omap4 = {
@@ -939,6 +981,194 @@ static struct omap_hwmod dra7xx_i2c5_hwm
 };
 
 /*
+ * 'mailbox' class
+ *
+ */
+
+static struct omap_hwmod_class_sysconfig dra7xx_mailbox_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class dra7xx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &dra7xx_mailbox_sysc,
+};
+
+/* mailbox1 */
+static struct omap_hwmod dra7xx_mailbox1_hwmod = {
+	.name		= "mailbox1",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX1_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX1_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox2 */
+static struct omap_hwmod dra7xx_mailbox2_hwmod = {
+	.name		= "mailbox2",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX2_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX2_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox3 */
+static struct omap_hwmod dra7xx_mailbox3_hwmod = {
+	.name		= "mailbox3",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX3_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX3_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox4 */
+static struct omap_hwmod dra7xx_mailbox4_hwmod = {
+	.name		= "mailbox4",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX4_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX4_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox5 */
+static struct omap_hwmod dra7xx_mailbox5_hwmod = {
+	.name		= "mailbox5",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX5_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX5_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox6 */
+static struct omap_hwmod dra7xx_mailbox6_hwmod = {
+	.name		= "mailbox6",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX6_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX6_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox7 */
+static struct omap_hwmod dra7xx_mailbox7_hwmod = {
+	.name		= "mailbox7",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX7_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX7_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox8 */
+static struct omap_hwmod dra7xx_mailbox8_hwmod = {
+	.name		= "mailbox8",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX8_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX8_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox9 */
+static struct omap_hwmod dra7xx_mailbox9_hwmod = {
+	.name		= "mailbox9",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX9_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX9_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox10 */
+static struct omap_hwmod dra7xx_mailbox10_hwmod = {
+	.name		= "mailbox10",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX10_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX10_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox11 */
+static struct omap_hwmod dra7xx_mailbox11_hwmod = {
+	.name		= "mailbox11",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX11_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX11_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox12 */
+static struct omap_hwmod dra7xx_mailbox12_hwmod = {
+	.name		= "mailbox12",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX12_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX12_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* mailbox13 */
+static struct omap_hwmod dra7xx_mailbox13_hwmod = {
+	.name		= "mailbox13",
+	.class		= &dra7xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX13_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4CFG_MAILBOX13_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/*
  * 'mcspi' class
  *
  */
@@ -1215,6 +1445,97 @@ static struct omap_hwmod dra7xx_ocp2scp1
 	},
 };
 
+/* ocp2scp3 */
+static struct omap_hwmod dra7xx_ocp2scp3_hwmod = {
+	.name		= "ocp2scp3",
+	.class		= &dra7xx_ocp2scp_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L3INIT_OCP2SCP3_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/*
+ * 'PCIE' class
+ *
+ */
+
+static struct omap_hwmod_class dra7xx_pcie_hwmod_class = {
+	.name	= "pcie",
+};
+
+/* pcie1 */
+static struct omap_hwmod dra7xx_pcie1_hwmod = {
+	.name		= "pcie1",
+	.class		= &dra7xx_pcie_hwmod_class,
+	.clkdm_name	= "pcie_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs	= DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* pcie2 */
+static struct omap_hwmod dra7xx_pcie2_hwmod = {
+	.name		= "pcie2",
+	.class		= &dra7xx_pcie_hwmod_class,
+	.clkdm_name	= "pcie_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'PCIE PHY' class
+ *
+ */
+
+static struct omap_hwmod_class dra7xx_pcie_phy_hwmod_class = {
+	.name	= "pcie-phy",
+};
+
+/* pcie1 phy */
+static struct omap_hwmod dra7xx_pcie1_phy_hwmod = {
+	.name		= "pcie1-phy",
+	.class		= &dra7xx_pcie_phy_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L3INIT_PCIESS1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* pcie2 phy */
+static struct omap_hwmod dra7xx_pcie2_phy_hwmod = {
+	.name		= "pcie2-phy",
+	.class		= &dra7xx_pcie_phy_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L3INIT_PCIESS2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
 /*
  * 'qspi' class
  *
@@ -1249,6 +1570,38 @@ static struct omap_hwmod dra7xx_qspi_hwm
 };
 
 /*
+ * 'rtcss' class
+ *
+ */
+static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = {
+	.sysc_offs	= 0x0078,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dra7xx_rtcss_hwmod_class = {
+	.name	= "rtcss",
+	.sysc	= &dra7xx_rtcss_sysc,
+};
+
+/* rtcss */
+static struct omap_hwmod dra7xx_rtcss_hwmod = {
+	.name		= "rtcss",
+	.class		= &dra7xx_rtcss_hwmod_class,
+	.clkdm_name	= "rtc_clkdm",
+	.main_clk	= "sys_32k_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_RTC_RTCSS_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_RTC_RTCSS_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
  * 'sata' class
  *
  */
@@ -2007,6 +2360,19 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__cpgmac0 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_gmac_hwmod,
+	.clk		= "dpll_gmac_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if dra7xx_gmac__mdio = {
+	.master		= &dra7xx_gmac_hwmod,
+	.slave		= &dra7xx_mdio_hwmod,
+	.user		= OCP_USER_MPU,
+};
+
 /* l4_wkup -> dcan1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_wkup__dcan1 = {
 	.master		= &dra7xx_l4_wkup_hwmod,
@@ -2254,6 +2620,110 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_cfg -> mailbox1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_mailbox1_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox2 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox2_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox3 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox3 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox3_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox4 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox4 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox4_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox5 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox5 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox5_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox6 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox6 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox6_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox7 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox7 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox7_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox8 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox8 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox8_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox9 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox9 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox9_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox10 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox10 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox10_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox11 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox11 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox11_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox12 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox12 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox12_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox13 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox13 = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_mailbox13_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per1 -> mcspi1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__mcspi1 = {
 	.master		= &dra7xx_l4_per1_hwmod,
@@ -2334,6 +2804,62 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_cfg -> ocp2scp3 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__ocp2scp3 = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_ocp2scp3_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> pcie1 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__pcie1 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_pcie1_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie1 = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_pcie1_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> pcie2 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__pcie2 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_pcie2_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie2 = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_pcie2_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie1 phy */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie1_phy = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_pcie1_phy_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie2 phy */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie2_phy = {
+	.master		= &dra7xx_l4_cfg_hwmod,
+	.slave		= &dra7xx_pcie2_phy_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_addr_space dra7xx_qspi_addrs[] = {
 	{
 		.pa_start	= 0x4b300000,
@@ -2352,6 +2878,14 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per3 -> rtcss */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__rtcss = {
+	.master		= &dra7xx_l4_per3_hwmod,
+	.slave		= &dra7xx_rtcss_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_addr_space dra7xx_sata_addrs[] = {
 	{
 		.name		= "sysc",
@@ -2650,6 +3184,8 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_wkup__ctrl_module_wkup,
 	&dra7xx_l4_wkup__dcan1,
 	&dra7xx_l4_per2__dcan2,
+	&dra7xx_l4_per2__cpgmac0,
+	&dra7xx_gmac__mdio,
 	&dra7xx_l4_cfg__dma_system,
 	&dra7xx_l3_main_1__dss,
 	&dra7xx_l3_main_1__dispc,
@@ -2670,6 +3206,19 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_per1__i2c3,
 	&dra7xx_l4_per1__i2c4,
 	&dra7xx_l4_per1__i2c5,
+	&dra7xx_l4_cfg__mailbox1,
+	&dra7xx_l4_per3__mailbox2,
+	&dra7xx_l4_per3__mailbox3,
+	&dra7xx_l4_per3__mailbox4,
+	&dra7xx_l4_per3__mailbox5,
+	&dra7xx_l4_per3__mailbox6,
+	&dra7xx_l4_per3__mailbox7,
+	&dra7xx_l4_per3__mailbox8,
+	&dra7xx_l4_per3__mailbox9,
+	&dra7xx_l4_per3__mailbox10,
+	&dra7xx_l4_per3__mailbox11,
+	&dra7xx_l4_per3__mailbox12,
+	&dra7xx_l4_per3__mailbox13,
 	&dra7xx_l4_per1__mcspi1,
 	&dra7xx_l4_per1__mcspi2,
 	&dra7xx_l4_per1__mcspi3,
@@ -2680,7 +3229,15 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_per1__mmc4,
 	&dra7xx_l4_cfg__mpu,
 	&dra7xx_l4_cfg__ocp2scp1,
+	&dra7xx_l4_cfg__ocp2scp3,
+	&dra7xx_l3_main_1__pcie1,
+	&dra7xx_l4_cfg__pcie1,
+	&dra7xx_l3_main_1__pcie2,
+	&dra7xx_l4_cfg__pcie2,
+	&dra7xx_l4_cfg__pcie1_phy,
+	&dra7xx_l4_cfg__pcie2_phy,
 	&dra7xx_l3_main_1__qspi,
+	&dra7xx_l4_per3__rtcss,
 	&dra7xx_l4_cfg__sata,
 	&dra7xx_l4_cfg__smartreflex_core,
 	&dra7xx_l4_cfg__smartreflex_mpu,
@@ -2705,7 +3262,6 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_per3__usb_otg_ss1,
 	&dra7xx_l4_per3__usb_otg_ss2,
 	&dra7xx_l4_per3__usb_otg_ss3,
-	&dra7xx_l4_per3__usb_otg_ss4,
 	&dra7xx_l3_main_1__vcp1,
 	&dra7xx_l4_per2__vcp1,
 	&dra7xx_l3_main_1__vcp2,
@@ -2714,8 +3270,26 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	NULL,
 };
 
+static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = {
+	&dra7xx_l4_per3__usb_otg_ss4,
+	NULL,
+};
+
+static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = {
+	NULL,
+};
+
 int __init dra7xx_hwmod_init(void)
 {
+	int ret;
+
 	omap_hwmod_init();
-	return omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
+	ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
+
+	if (!ret && soc_is_dra74x())
+		return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
+	else if (!ret && soc_is_dra72x())
+		return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
+
+	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod.c	2014-09-28 17:29:07.000000000 -0400
@@ -2065,7 +2065,7 @@ static void _reconfigure_io_chain(void)
 
 	spin_lock_irqsave(&io_chain_lock, flags);
 
-	if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl())
+	if (cpu_is_omap34xx())
 		omap3xxx_prm_reconfigure_io_chain();
 	else if (cpu_is_omap44xx())
 		omap44xx_prm_reconfigure_io_chain();
@@ -2185,6 +2185,8 @@ static int _enable(struct omap_hwmod *oh
 			 oh->mux->pads_dynamic))) {
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 		_reconfigure_io_chain();
+	} else if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+		_reconfigure_io_chain();
 	}
 
 	_add_initiator_dep(oh, mpu_oh);
@@ -2291,6 +2293,8 @@ static int _idle(struct omap_hwmod *oh)
 	if (oh->mux && oh->mux->pads_dynamic) {
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
 		_reconfigure_io_chain();
+	} else if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+		_reconfigure_io_chain();
 	}
 
 	oh->_state = _HWMOD_STATE_IDLE;
@@ -3345,6 +3349,9 @@ int __init omap_hwmod_register_links(str
 	if (!ois)
 		return 0;
 
+	if (ois[0] == NULL) /* Empty list */
+		return 0;
+
 	if (!linkspace) {
 		if (_alloc_linkspace(ois)) {
 			pr_err("omap_hwmod: could not allocate link space\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ extern struct omap_hwmod_addr_space omap
 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_mailbox_addrs[];
 extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
 extern struct omap_hwmod_addr_space omap2_hdq1w_addr_space[];
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * omap_hwmod_common_ipblock_data.c - common IP block data for OMAP2+
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap_hwmod.h"
+#include "omap_hwmod_common_data.h"
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dss_hwmod_class = {
+	.name	= "dss",
+	.sysc	= &omap2_dss_sysc,
+	.reset	= omap_dss_reset,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_rfbi_hwmod_class = {
+	.name	= "rfbi",
+	.sysc	= &omap2_rfbi_sysc,
+};
+
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/omap-iommu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap-iommu.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/omap-iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/omap-iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,8 +34,6 @@ static int __init omap_iommu_dev_init(st
 
 	pdata->name = oh->name;
 	pdata->nr_tlb_entries = a->nr_tlb_entries;
-	pdata->da_start = a->da_start;
-	pdata->da_end = a->da_end;
 
 	if (oh->rst_lines_cnt == 1) {
 		pdata->reset_name = oh->rst_lines->name;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/pm24xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/pm24xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/pm24xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,9 +75,9 @@ static int omap2_enter_full_retention(vo
 
 	/* Clear old wake-up events */
 	/* REVISIT: These write to reserved bits? */
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+	omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
 	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -104,23 +104,18 @@ no_sleep:
 	clk_enable(osc_ck);
 
 	/* clear CORE wake-up events */
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
 
 	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
-	omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+	omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);
 
 	/* MPU domain wake events */
-	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-	if (l & 0x01)
-		omap2_prm_write_mod_reg(0x01, OCP_MOD,
-				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-	if (l & 0x20)
-		omap2_prm_write_mod_reg(0x20, OCP_MOD,
-				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+				    0x1);
 
-	/* Mask future PRCM-to-MPU interrupts */
-	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+				    0x20);
 
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
@@ -148,9 +143,9 @@ static void omap2_enter_mpu_retention(vo
 	 * it is in retention mode. */
 	if (omap2_allow_mpu_retention()) {
 		/* REVISIT: These write to reserved bits? */
-		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+		omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+		omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+		omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
 		/* Try to enter MPU retention */
 		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -249,6 +244,10 @@ static void __init prcm_setup_regs(void)
 	/* Enable wake-up events */
 	omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
 				WKUP_MOD, PM_WKEN);
+
+	/* Enable SYS_CLKEN control when all domains idle */
+	omap2_prm_set_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, OMAP24XX_GR_MOD,
+				   OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
 }
 
 int __init omap2_pm_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/pm34xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/pm34xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/pm34xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -133,60 +133,13 @@ static void omap3_save_secure_ram_contex
 	}
 }
 
-/*
- * PRCM Interrupt Handler Helper Function
- *
- * The purpose of this function is to clear any wake-up events latched
- * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
- * may occur whilst attempting to clear a PM_WKST_x register and thus
- * set another bit in this register. A while loop is used to ensure
- * that any peripheral wake-up events occurring while attempting to
- * clear the PM_WKST_x are detected and cleared.
- */
-static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
-{
-	u32 wkst, fclk, iclk, clken;
-	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
-	u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
-	u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
-	u16 grpsel_off = (regs == 3) ?
-		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
-	int c = 0;
-
-	wkst = omap2_prm_read_mod_reg(module, wkst_off);
-	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
-	wkst &= ~ignore_bits;
-	if (wkst) {
-		iclk = omap2_cm_read_mod_reg(module, iclk_off);
-		fclk = omap2_cm_read_mod_reg(module, fclk_off);
-		while (wkst) {
-			clken = wkst;
-			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
-			/*
-			 * For USBHOST, we don't know whether HOST1 or
-			 * HOST2 woke us up, so enable both f-clocks
-			 */
-			if (module == OMAP3430ES2_USBHOST_MOD)
-				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
-			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
-			omap2_prm_write_mod_reg(wkst, module, wkst_off);
-			wkst = omap2_prm_read_mod_reg(module, wkst_off);
-			wkst &= ~ignore_bits;
-			c++;
-		}
-		omap2_cm_write_mod_reg(iclk, module, iclk_off);
-		omap2_cm_write_mod_reg(fclk, module, fclk_off);
-	}
-
-	return c;
-}
-
 static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
 {
 	int c;
 
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
-		~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
+	c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+					~(OMAP3430_ST_IO_MASK |
+					  OMAP3430_ST_IO_CHAIN_MASK));
 
 	return c ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -200,13 +153,14 @@ static irqreturn_t _prcm_int_handle_wake
 	 * these are handled in a separate handler to avoid acking
 	 * IO events before parsing in mux code
 	 */
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
-		OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK);
-	c += prcm_clear_mod_irqs(CORE_MOD, 1, 0);
-	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
+	c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+					OMAP3430_ST_IO_MASK |
+					OMAP3430_ST_IO_CHAIN_MASK);
+	c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 1, 0);
+	c += omap3xxx_prm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		c += prcm_clear_mod_irqs(CORE_MOD, 3, 0);
-		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
+		c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 3, 0);
+		c += omap3xxx_prm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
 	}
 
 	return c ? IRQ_HANDLED : IRQ_NONE;
@@ -399,159 +353,11 @@ restore:
 #define omap3_pm_suspend NULL
 #endif /* CONFIG_SUSPEND */
 
-
-/**
- * omap3_iva_idle(): ensure IVA is in idle so it can be put into
- *                   retention
- *
- * In cases where IVA2 is activated by bootcode, it may prevent
- * full-chip retention or off-mode because it is not idle.  This
- * function forces the IVA2 into idle state so it can go
- * into retention/off and thus allow full-chip retention/off.
- *
- **/
-static void __init omap3_iva_idle(void)
-{
-	/* ensure IVA2 clock is disabled */
-	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* if no clock activity, nothing else to do */
-	if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
-	      OMAP3430_CLKACTIVITY_IVA2_MASK))
-		return;
-
-	/* Reset IVA2 */
-	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
-			  OMAP3430_RST2_IVA2_MASK |
-			  OMAP3430_RST3_IVA2_MASK,
-			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
-	/* Enable IVA2 clock */
-	omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
-			 OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* Set IVA2 boot mode to 'idle' */
-	omap3_ctrl_set_iva_bootmode_idle();
-
-	/* Un-reset IVA2 */
-	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
-	/* Disable IVA2 clock */
-	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* Reset IVA2 */
-	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
-			  OMAP3430_RST2_IVA2_MASK |
-			  OMAP3430_RST3_IVA2_MASK,
-			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-}
-
-static void __init omap3_d2d_idle(void)
-{
-	u16 mask, padconf;
-
-	/* In a stand alone OMAP3430 where there is not a stacked
-	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
-	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
-	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
-	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
-	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
-	padconf |= mask;
-	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
-
-	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
-	padconf |= mask;
-	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
-
-	/* reset modem */
-	omap2_prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
-			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
-			  CORE_MOD, OMAP2_RM_RSTCTRL);
-	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
-}
-
 static void __init prcm_setup_regs(void)
 {
-	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_EN_UART4_MASK : 0;
-	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_GRPSEL_UART4_MASK : 0;
-
-	/* XXX This should be handled by hwmod code or SCM init code */
-	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
-
-	/*
-	 * Enable control of expternal oscillator through
-	 * sys_clkreq. In the long run clock framework should
-	 * take care of this.
-	 */
-	omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
-			     1 << OMAP_AUTOEXTCLKMODE_SHIFT,
-			     OMAP3430_GR_MOD,
-			     OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-
-	/* setup wakup source */
-	omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
-			  OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
-			  WKUP_MOD, PM_WKEN);
-	/* No need to write EN_IO, that is always enabled */
-	omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
-			  OMAP3430_GRPSEL_GPT1_MASK |
-			  OMAP3430_GRPSEL_GPT12_MASK,
-			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-
-	/* Enable PM_WKEN to support DSS LPR */
-	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
-				OMAP3430_DSS_MOD, PM_WKEN);
-
-	/* Enable wakeups in PER */
-	omap2_prm_write_mod_reg(omap3630_en_uart4_mask |
-			  OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
-			  OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
-			  OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
-			  OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
-			  OMAP3430_EN_MCBSP4_MASK,
-			  OMAP3430_PER_MOD, PM_WKEN);
-	/* and allow them to wake up MPU */
-	omap2_prm_write_mod_reg(omap3630_grpsel_uart4_mask |
-			  OMAP3430_GRPSEL_GPIO2_MASK |
-			  OMAP3430_GRPSEL_GPIO3_MASK |
-			  OMAP3430_GRPSEL_GPIO4_MASK |
-			  OMAP3430_GRPSEL_GPIO5_MASK |
-			  OMAP3430_GRPSEL_GPIO6_MASK |
-			  OMAP3430_GRPSEL_UART3_MASK |
-			  OMAP3430_GRPSEL_MCBSP2_MASK |
-			  OMAP3430_GRPSEL_MCBSP3_MASK |
-			  OMAP3430_GRPSEL_MCBSP4_MASK,
-			  OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
-
-	/* Don't attach IVA interrupts */
-	if (omap3_has_iva()) {
-		omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-		omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
-					OMAP3430_PM_IVAGRPSEL);
-	}
-
-	/* Clear any pending 'reset' flags */
-	omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
-
-	/* Clear any pending PRCM interrupts */
-	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
-	/*
-	 * We need to idle iva2_pwrdm even on am3703 with no iva2.
-	 */
-	omap3_iva_idle();
+	omap3_ctrl_init();
 
-	omap3_d2d_idle();
+	omap3_prm_init_pm(cpu_is_omap3630(), omap3_has_iva());
 }
 
 void omap3_pm_off_mode_enable(int enable)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prcm43xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prcm43xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prcm43xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prcm43xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -142,5 +142,6 @@
 #define AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET	0x05B8
 #define AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET        0x0268
 #define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET	0x05C0
+#define AM43XX_CM_PER_DSS_CLKCTRL_OFFSET		0x0a20
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm2xxx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm2xxx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm2xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm2xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,6 +114,24 @@ void omap2xxx_prm_dpll_reset(void)
 	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
 }
 
+/**
+ * omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
+ * @module: PRM module to clear wakeups from
+ * @regs: register offset to clear
+ * @wkst_mask: wakeup status mask to clear
+ *
+ * Clears wakeup status bits for a given module, so that the device can
+ * re-enter idle.
+ */
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
+{
+	u32 wkst;
+
+	wkst = omap2_prm_read_mod_reg(module, regs);
+	wkst &= wkst_mask;
+	omap2_prm_write_mod_reg(wkst, module, regs);
+}
+
 int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
 {
 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm2xxx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm2xxx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm2xxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm2xxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -125,6 +125,7 @@ extern int omap2xxx_clkdm_sleep(struct c
 extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
 
 extern void omap2xxx_prm_dpll_reset(void);
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
 
 extern int __init omap2xxx_prm_init(void);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm3xxx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm3xxx.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm3xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm3xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,8 @@
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
+#include "cm3xxx.h"
+#include "cm-regbits-34xx.h"
 
 static const struct omap_prcm_irq omap3_prcm_irqs[] = {
 	OMAP_PRCM_IRQ("wkup",	0,	0),
@@ -43,7 +45,7 @@ static struct omap_prcm_irq_setup omap3_
 	.ocp_barrier		= &omap3xxx_prm_ocp_barrier,
 	.save_and_clear_irqen	= &omap3xxx_prm_save_and_clear_irqen,
 	.restore_irqen		= &omap3xxx_prm_restore_irqen,
-	.reconfigure_io_chain	= &omap3xxx_prm_reconfigure_io_chain,
+	.reconfigure_io_chain	= NULL,
 };
 
 /*
@@ -206,15 +208,191 @@ void omap3xxx_prm_restore_irqen(u32 *sav
 }
 
 /**
- * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
+ * omap3xxx_prm_clear_mod_irqs - clear wake-up events from PRCM interrupt
+ * @module: PRM module to clear wakeups from
+ * @regs: register set to clear, 1 or 3
+ * @ignore_bits: wakeup status bits to ignore
+ *
+ * The purpose of this function is to clear any wake-up events latched
+ * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
+ * may occur whilst attempting to clear a PM_WKST_x register and thus
+ * set another bit in this register. A while loop is used to ensure
+ * that any peripheral wake-up events occurring while attempting to
+ * clear the PM_WKST_x are detected and cleared.
+ */
+int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
+{
+	u32 wkst, fclk, iclk, clken;
+	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
+	u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
+	u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
+	u16 grpsel_off = (regs == 3) ?
+		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
+	int c = 0;
+
+	wkst = omap2_prm_read_mod_reg(module, wkst_off);
+	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
+	wkst &= ~ignore_bits;
+	if (wkst) {
+		iclk = omap2_cm_read_mod_reg(module, iclk_off);
+		fclk = omap2_cm_read_mod_reg(module, fclk_off);
+		while (wkst) {
+			clken = wkst;
+			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
+			/*
+			 * For USBHOST, we don't know whether HOST1 or
+			 * HOST2 woke us up, so enable both f-clocks
+			 */
+			if (module == OMAP3430ES2_USBHOST_MOD)
+				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
+			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
+			omap2_prm_write_mod_reg(wkst, module, wkst_off);
+			wkst = omap2_prm_read_mod_reg(module, wkst_off);
+			wkst &= ~ignore_bits;
+			c++;
+		}
+		omap2_cm_write_mod_reg(iclk, module, iclk_off);
+		omap2_cm_write_mod_reg(fclk, module, fclk_off);
+	}
+
+	return c;
+}
+
+/**
+ * omap3_prm_reset_modem - toggle reset signal for modem
+ *
+ * Toggles the reset signal to modem IP block. Required to allow
+ * OMAP3430 without stacked modem to idle properly.
+ */
+void __init omap3_prm_reset_modem(void)
+{
+	omap2_prm_write_mod_reg(
+		OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
+		OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
+				CORE_MOD, OMAP2_RM_RSTCTRL);
+	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
+ * omap3_prm_init_pm - initialize PM related registers for PRM
+ * @has_uart4: SoC has UART4
+ * @has_iva: SoC has IVA
+ *
+ * Initializes PRM registers for PM use. Called from PM init.
+ */
+void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
+{
+	u32 en_uart4_mask;
+	u32 grpsel_uart4_mask;
+
+	/*
+	 * Enable control of expternal oscillator through
+	 * sys_clkreq. In the long run clock framework should
+	 * take care of this.
+	 */
+	omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
+				   1 << OMAP_AUTOEXTCLKMODE_SHIFT,
+				   OMAP3430_GR_MOD,
+				   OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+	/* setup wakup source */
+	omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
+				OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
+				WKUP_MOD, PM_WKEN);
+	/* No need to write EN_IO, that is always enabled */
+	omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
+				OMAP3430_GRPSEL_GPT1_MASK |
+				OMAP3430_GRPSEL_GPT12_MASK,
+				WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
+
+	/* Enable PM_WKEN to support DSS LPR */
+	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
+				OMAP3430_DSS_MOD, PM_WKEN);
+
+	if (has_uart4) {
+		en_uart4_mask = OMAP3630_EN_UART4_MASK;
+		grpsel_uart4_mask = OMAP3630_GRPSEL_UART4_MASK;
+	}
+
+	/* Enable wakeups in PER */
+	omap2_prm_write_mod_reg(en_uart4_mask |
+				OMAP3430_EN_GPIO2_MASK |
+				OMAP3430_EN_GPIO3_MASK |
+				OMAP3430_EN_GPIO4_MASK |
+				OMAP3430_EN_GPIO5_MASK |
+				OMAP3430_EN_GPIO6_MASK |
+				OMAP3430_EN_UART3_MASK |
+				OMAP3430_EN_MCBSP2_MASK |
+				OMAP3430_EN_MCBSP3_MASK |
+				OMAP3430_EN_MCBSP4_MASK,
+				OMAP3430_PER_MOD, PM_WKEN);
+
+	/* and allow them to wake up MPU */
+	omap2_prm_write_mod_reg(grpsel_uart4_mask |
+				OMAP3430_GRPSEL_GPIO2_MASK |
+				OMAP3430_GRPSEL_GPIO3_MASK |
+				OMAP3430_GRPSEL_GPIO4_MASK |
+				OMAP3430_GRPSEL_GPIO5_MASK |
+				OMAP3430_GRPSEL_GPIO6_MASK |
+				OMAP3430_GRPSEL_UART3_MASK |
+				OMAP3430_GRPSEL_MCBSP2_MASK |
+				OMAP3430_GRPSEL_MCBSP3_MASK |
+				OMAP3430_GRPSEL_MCBSP4_MASK,
+				OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
+
+	/* Don't attach IVA interrupts */
+	if (has_iva) {
+		omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+		omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
+					OMAP3430_PM_IVAGRPSEL);
+	}
+
+	/* Clear any pending 'reset' flags */
+	omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD,
+				OMAP2_RM_RSTST);
+
+	/* Clear any pending PRCM interrupts */
+	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	/* We need to idle iva2_pwrdm even on am3703 with no iva2. */
+	omap3xxx_prm_iva_idle();
+
+	omap3_prm_reset_modem();
+}
+
+/**
+ * omap3430_pre_es3_1_reconfigure_io_chain - restart wake-up daisy chain
+ *
+ * The ST_IO_CHAIN bit does not exist in 3430 before es3.1. The only
+ * thing we can do is toggle EN_IO bit for earlier omaps.
+ */
+void omap3430_pre_es3_1_reconfigure_io_chain(void)
+{
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+				     PM_WKEN);
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+				   PM_WKEN);
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+}
+
+/**
+ * omap3_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
  *
  * Clear any previously-latched I/O wakeup events and ensure that the
  * I/O wakeup gates are aligned with the current mux settings.  Works
  * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
  * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
- * return value.
+ * return value. These registers are only available in 3430 es3.1 and later.
  */
-void omap3xxx_prm_reconfigure_io_chain(void)
+void omap3_prm_reconfigure_io_chain(void)
 {
 	int i = 0;
 
@@ -237,6 +415,15 @@ void omap3xxx_prm_reconfigure_io_chain(v
 }
 
 /**
+ * omap3xxx_prm_reconfigure_io_chain - reconfigure I/O chain
+ */
+void omap3xxx_prm_reconfigure_io_chain(void)
+{
+	if (omap3_prcm_irq_setup.reconfigure_io_chain)
+		omap3_prcm_irq_setup.reconfigure_io_chain();
+}
+
+/**
  * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
  *
  * Activates the I/O wakeup event latches and allows events logged by
@@ -276,6 +463,76 @@ static u32 omap3xxx_prm_read_reset_sourc
 	return r;
 }
 
+/**
+ * omap3xxx_prm_iva_idle - ensure IVA is in idle so it can be put into retention
+ *
+ * In cases where IVA2 is activated by bootcode, it may prevent
+ * full-chip retention or off-mode because it is not idle.  This
+ * function forces the IVA2 into idle state so it can go
+ * into retention/off and thus allow full-chip retention/off.
+ */
+void omap3xxx_prm_iva_idle(void)
+{
+	/* ensure IVA2 clock is disabled */
+	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* if no clock activity, nothing else to do */
+	if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
+	      OMAP3430_CLKACTIVITY_IVA2_MASK))
+		return;
+
+	/* Reset IVA2 */
+	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+				OMAP3430_RST2_IVA2_MASK |
+				OMAP3430_RST3_IVA2_MASK,
+				OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+
+	/* Enable IVA2 clock */
+	omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
+			       OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Un-reset IVA2 */
+	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+
+	/* Disable IVA2 clock */
+	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Reset IVA2 */
+	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+				OMAP3430_RST2_IVA2_MASK |
+				OMAP3430_RST3_IVA2_MASK,
+				OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
+ * omap3xxx_prm_clear_global_cold_reset - checks the global cold reset status
+ *					  and clears it if asserted
+ *
+ * Checks if cold-reset has occurred and clears the status bit if yes. Returns
+ * 1 if cold-reset has occurred, 0 otherwise.
+ */
+int omap3xxx_prm_clear_global_cold_reset(void)
+{
+	if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
+	    OMAP3430_GLOBAL_COLD_RST_MASK) {
+		omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
+					   OMAP3430_GR_MOD,
+					   OMAP3_PRM_RSTST_OFFSET);
+		return 1;
+	}
+
+	return 0;
+}
+
+void omap3_prm_save_scratchpad_contents(u32 *ptr)
+{
+	*ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+					OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+	*ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+					OMAP3_PRM_CLKSEL_OFFSET);
+}
+
 /* Powerdomain low-level functions */
 
 static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
@@ -423,6 +680,13 @@ static int omap3xxx_prm_late_init(void)
 	if (!(prm_features & PRM_HAS_IO_WAKEUP))
 		return 0;
 
+	if (omap3_has_io_chain_ctrl())
+		omap3_prcm_irq_setup.reconfigure_io_chain =
+			omap3_prm_reconfigure_io_chain;
+	else
+		omap3_prcm_irq_setup.reconfigure_io_chain =
+			omap3430_pre_es3_1_reconfigure_io_chain;
+
 	omap3xxx_prm_enable_io_wakeup();
 	ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
 	if (!ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm3xxx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm3xxx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm3xxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm3xxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -162,6 +162,12 @@ extern void omap3xxx_prm_dpll3_reset(voi
 
 extern int __init omap3xxx_prm_init(void);
 extern u32 omap3xxx_prm_get_reset_sources(void);
+int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
+void omap3xxx_prm_iva_idle(void);
+void omap3_prm_reset_modem(void);
+int omap3xxx_prm_clear_global_cold_reset(void);
+void omap3_prm_save_scratchpad_contents(u32 *ptr);
+void omap3_prm_init_pm(bool has_uart4, bool has_iva);
 
 #endif /* __ASSEMBLER */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm7xx.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm7xx.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm7xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm7xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -374,6 +374,10 @@
 #define DRA7XX_RM_L3INIT_IEEE1500_2_OCP_CONTEXT_OFFSET		0x007c
 #define DRA7XX_PM_L3INIT_SATA_WKDEP_OFFSET			0x0088
 #define DRA7XX_RM_L3INIT_SATA_CONTEXT_OFFSET			0x008c
+#define DRA7XX_PM_L3INIT_PCIESS1_WKDEP_OFFSET			0x00b0
+#define DRA7XX_RM_L3INIT_PCIESS1_CONTEXT_OFFSET		0x00b4
+#define DRA7XX_PM_L3INIT_PCIESS2_WKDEP_OFFSET			0x00b8
+#define DRA7XX_RM_L3INIT_PCIESS2_CONTEXT_OFFSET		0x00bc
 #define DRA7XX_RM_GMAC_GMAC_CONTEXT_OFFSET			0x00d4
 #define DRA7XX_RM_L3INIT_OCP2SCP1_CONTEXT_OFFSET		0x00e4
 #define DRA7XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET		0x00ec
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/prm_common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm_common.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/prm_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/prm_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -472,6 +472,8 @@ static struct of_device_id omap_prcm_dt_
 	{ .compatible = "ti,am3-scrm" },
 	{ .compatible = "ti,am4-prcm" },
 	{ .compatible = "ti,am4-scrm" },
+	{ .compatible = "ti,omap2-prcm" },
+	{ .compatible = "ti,omap2-scrm" },
 	{ .compatible = "ti,omap3-prm" },
 	{ .compatible = "ti,omap3-cm" },
 	{ .compatible = "ti,omap3-scrm" },
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/sleep44xx.S linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sleep44xx.S
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/sleep44xx.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sleep44xx.S	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/smp_scu.h>
 #include <asm/memory.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -334,7 +335,7 @@ ENDPROC(omap4_cpu_resume)
 
 #ifndef CONFIG_OMAP4_ERRATA_I688
 ENTRY(omap_bus_sync)
-	mov	pc, lr
+	ret	lr
 ENDPROC(omap_bus_sync)
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/soc.h linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/soc.h
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/soc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/soc.h	2014-09-28 17:29:07.000000000 -0400
@@ -245,6 +245,8 @@ IS_AM_SUBCLASS(437x, 0x437)
 #define soc_is_omap54xx()		0
 #define soc_is_omap543x()		0
 #define soc_is_dra7xx()			0
+#define soc_is_dra74x()			0
+#define soc_is_dra72x()			0
 
 #if defined(MULTI_OMAP2)
 # if defined(CONFIG_ARCH_OMAP2)
@@ -393,7 +395,11 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 #if defined(CONFIG_SOC_DRA7XX)
 #undef soc_is_dra7xx
+#undef soc_is_dra74x
+#undef soc_is_dra72x
 #define soc_is_dra7xx()	(of_machine_is_compatible("ti,dra7"))
+#define soc_is_dra74x()	(of_machine_is_compatible("ti,dra74"))
+#define soc_is_dra72x()	(of_machine_is_compatible("ti,dra72"))
 #endif
 
 /* Various silicon revisions for omap2 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/sram242x.S linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sram242x.S
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/sram242x.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sram242x.S	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ i_dll_wait:
 i_dll_delay:
 	subs	r4, r4, #0x1
 	bne	i_dll_delay
-	mov	pc, lr
+	ret	lr
 
 	/*
 	 * shift up or down voltage, use R9 as input to tell level.
@@ -125,7 +125,7 @@ volt_delay:
 	ldr	r7, [r3]		@ get timer value
 	cmp	r5, r7			@ time up?
 	bhi	volt_delay		@ not yet->branch
-	mov	pc, lr			@ back to caller.
+	ret	lr			@ back to caller.
 
 omap242x_sdi_cm_clksel2_pll:
 	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
@@ -220,7 +220,7 @@ volt_delay_c:
 	ldr	r7, [r10]		@ get timer value
 	cmp	r8, r7			@ time up?
 	bhi	volt_delay_c		@ not yet->branch
-	mov	pc, lr			@ back to caller
+	ret	lr			@ back to caller
 
 omap242x_srs_cm_clksel2_pll:
 	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/sram243x.S linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sram243x.S
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/sram243x.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/sram243x.S	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ i_dll_wait:
 i_dll_delay:
 	subs	r4, r4, #0x1
 	bne	i_dll_delay
-	mov	pc, lr
+	ret	lr
 
 	/*
 	 * shift up or down voltage, use R9 as input to tell level.
@@ -125,7 +125,7 @@ volt_delay:
 	ldr	r7, [r3]		@ get timer value
 	cmp	r5, r7			@ time up?
 	bhi	volt_delay		@ not yet->branch
-	mov	pc, lr			@ back to caller.
+	ret	lr			@ back to caller.
 
 omap243x_sdi_cm_clksel2_pll:
 	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
@@ -220,7 +220,7 @@ volt_delay_c:
 	ldr	r7, [r10]		@ get timer value
 	cmp	r8, r7			@ time up?
 	bhi	volt_delay_c		@ not yet->branch
-	mov	pc, lr			@ back to caller
+	ret	lr			@ back to caller
 
 omap243x_srs_cm_clksel2_pll:
 	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-omap2/usb-tusb6010.c linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/usb-tusb6010.c
--- linux-libre-3.16-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,6 @@ static int tusb_set_sync_mode(unsigned s
 	dev_t.t_avdp_w = t_scsnh_advnh;
 	dev_t.cyc_aavdh_we = 3;
 	dev_t.cyc_wpl = 6;
-	dev_t.t_ce_rdyz = 7000;
 
 	gpmc_calc_timings(&t, &tusb_sync, &dev_t);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/balloon3.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/balloon3.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/balloon3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/balloon3.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,7 @@ int __init parse_balloon3_features(char
 	if (!arg)
 		return 0;
 
-	return strict_strtoul(arg, 0, &balloon3_features_present);
+	return kstrtoul(arg, 0, &balloon3_features_present);
 }
 early_param("balloon3_features", parse_balloon3_features);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/corgi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/corgi.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/corgi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/corgi.c	2014-09-28 17:29:07.000000000 -0400
@@ -514,7 +514,7 @@ static struct pxa2xx_udc_mach_info udc_i
 	.gpio_pullup		= CORGI_GPIO_USB_PULLUP,
 };
 
-#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MASTER)
+#if IS_ENABLED(CONFIG_SPI_PXA2XX)
 static struct pxa2xx_spi_master corgi_spi_info = {
 	.num_chipselect	= 3,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/generic.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/generic.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,11 +25,13 @@
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 
+#include <mach/irqs.h>
 #include <mach/reset.h>
 #include <mach/smemc.h>
 #include <mach/pxa3xx-regs.h>
 
 #include "generic.h"
+#include <clocksource/pxa.h>
 
 void clear_reset_status(unsigned int mask)
 {
@@ -57,6 +59,15 @@ unsigned long get_clock_tick_rate(void)
 EXPORT_SYMBOL(get_clock_tick_rate);
 
 /*
+ * For non device-tree builds, keep legacy timer init
+ */
+void __init pxa_timer_init(void)
+{
+	pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
+			    get_clock_tick_rate());
+}
+
+/*
  * Get the clock frequency as reflected by CCCR and the turbo flag.
  * We assume these values have been applied via a fcs.
  * If info is not 0 we also display the current settings.
@@ -79,19 +90,15 @@ EXPORT_SYMBOL(get_clk_frequency_khz);
  */
 static struct map_desc common_io_desc[] __initdata = {
   	{	/* Devs */
-		.virtual	=  0xf2000000,
-		.pfn		= __phys_to_pfn(0x40000000),
-		.length		= 0x02000000,
-		.type		= MT_DEVICE
-	}, {	/* UNCACHED_PHYS_0 */
-		.virtual	= 0xff000000,
-		.pfn		= __phys_to_pfn(0x00000000),
-		.length		= 0x00100000,
+		.virtual	= (unsigned long)PERIPH_VIRT,
+		.pfn		= __phys_to_pfn(PERIPH_PHYS),
+		.length		= PERIPH_SIZE,
 		.type		= MT_DEVICE
 	}
 };
 
 void __init pxa_map_io(void)
 {
+	debug_ll_io_init();
 	iotable_init(ARRAY_AND_SIZE(common_io_desc));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,8 @@
  * Workarounds for at least 2 errata so far require this.
  * The mapping is set in mach-pxa/generic.c.
  */
-#define UNCACHED_PHYS_0		0xff000000
-#define UNCACHED_ADDR		UNCACHED_PHYS_0
+#define UNCACHED_PHYS_0		0xfe000000
+#define UNCACHED_PHYS_0_SIZE	0x00100000
 
 /*
  * Intel PXA2xx internal register mapping:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,7 @@
 
 # Common support (must be linked before board specific support)
 obj-y				+= clock.o devices.o generic.o irq.o \
-				   time.o reset.o
+				   reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 
 # Generic drivers that other drivers may depend upon
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/mioa701_bootresume.S linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/mioa701_bootresume.S
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/mioa701_bootresume.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/mioa701_bootresume.S	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,7 @@ ENTRY(mioa701_jumpaddr)
 	str	r1, [r0]		@ Early disable resume for next boot
 	ldr	r0, mioa701_jumpaddr	@ (Murphy's Law)
 	ldr	r0, [r0]
-	mov	pc, r0
+	ret	r0
 2:
 
 ENTRY(mioa701_bootstrap_lg)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa25x.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa25x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa25x.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,7 +331,12 @@ static struct map_desc pxa25x_io_desc[]
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
-		.length		= 0x00200000,
+		.length		= SMEMC_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* UNCACHED_PHYS_0 */
+		.virtual	= UNCACHED_PHYS_0,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= UNCACHED_PHYS_0_SIZE,
 		.type		= MT_DEVICE
 	},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa27x.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa27x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa27x.c	2014-09-28 17:29:07.000000000 -0400
@@ -402,12 +402,12 @@ static struct map_desc pxa27x_io_desc[]
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
-		.length		= 0x00200000,
+		.length		= SMEMC_SIZE,
 		.type		= MT_DEVICE
-	}, {	/* IMem ctl */
-		.virtual	=  0xfe000000,
-		.pfn		= __phys_to_pfn(0x58000000),
-		.length		= 0x00100000,
+	}, {	/* UNCACHED_PHYS_0 */
+		.virtual	= UNCACHED_PHYS_0,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= UNCACHED_PHYS_0_SIZE,
 		.type		= MT_DEVICE
 	},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa3xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/pxa3xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/pxa3xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -416,7 +416,7 @@ static struct map_desc pxa3xx_io_desc[]
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA3XX_SMEMC_BASE),
-		.length		= 0x00200000,
+		.length		= SMEMC_SIZE,
 		.type		= MT_DEVICE
 	}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/sleep.S linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/sleep.S
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/sleep.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/sleep.S	2014-09-28 17:29:07.000000000 -0400
@@ -157,7 +157,7 @@ pxa_cpu_do_suspend:
 	@ Do not reorder...
 	@ Intel PXA270 Specification Update notes problems performing
 	@ external accesses after SDRAM is put in self-refresh mode
-	@ (see Errata 39 ...hangs when entering self-refresh mode)
+	@ (see Errata 38 ...hangs when entering self-refresh mode)
 
 	@ force address lines low by reading at physical address 0
 	ldr	r3, [r2]
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/standby.S linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/standby.S
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/standby.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/standby.S	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,7 @@ ENTRY(pxa_cpu_standby)
 	.align	5
 1:	mcr	p14, 0, r2, c7, c0, 0	@ put the system into Standby
 	str	r1, [r0]		@ make sure PSSR_PH/STS are clear
-	mov	pc, lr
+	ret	lr
 
 #endif
 
@@ -108,7 +108,7 @@ ENTRY(pm_enter_standby_start)
 	bic	r0, r0, #0x20000000
 	str	r0, [r1, #PXA3_DMCIER]
 
-	mov	pc, lr
+	ret	lr
 ENTRY(pm_enter_standby_end)
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/time.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/time.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,162 +0,0 @@
-/*
- * arch/arm/mach-pxa/time.c
- *
- * PXA clocksource, clockevents, and OST interrupt handlers.
- * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
- *
- * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
- * by MontaVista Software, Inc.  (Nico, your code rocks!)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/clockchips.h>
-#include <linux/sched_clock.h>
-
-#include <asm/div64.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <mach/regs-ost.h>
-#include <mach/irqs.h>
-
-/*
- * This is PXA's sched_clock implementation. This has a resolution
- * of at least 308 ns and a maximum value of 208 days.
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 582 seconds between successive
- * calls to sched_clock() which should always be the case in practice.
- */
-
-static u64 notrace pxa_read_sched_clock(void)
-{
-	return readl_relaxed(OSCR);
-}
-
-
-#define MIN_OSCR_DELTA 16
-
-static irqreturn_t
-pxa_ost0_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *c = dev_id;
-
-	/* Disarm the compare/match, signal the event. */
-	writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
-	writel_relaxed(OSSR_M0, OSSR);
-	c->event_handler(c);
-
-	return IRQ_HANDLED;
-}
-
-static int
-pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
-{
-	unsigned long next, oscr;
-
-	writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER);
-	next = readl_relaxed(OSCR) + delta;
-	writel_relaxed(next, OSMR0);
-	oscr = readl_relaxed(OSCR);
-
-	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
-}
-
-static void
-pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
-{
-	switch (mode) {
-	case CLOCK_EVT_MODE_ONESHOT:
-		writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
-		writel_relaxed(OSSR_M0, OSSR);
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		/* initializing, released, or preparing for suspend */
-		writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
-		writel_relaxed(OSSR_M0, OSSR);
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-	case CLOCK_EVT_MODE_PERIODIC:
-		break;
-	}
-}
-
-#ifdef CONFIG_PM
-static unsigned long osmr[4], oier, oscr;
-
-static void pxa_timer_suspend(struct clock_event_device *cedev)
-{
-	osmr[0] = readl_relaxed(OSMR0);
-	osmr[1] = readl_relaxed(OSMR1);
-	osmr[2] = readl_relaxed(OSMR2);
-	osmr[3] = readl_relaxed(OSMR3);
-	oier = readl_relaxed(OIER);
-	oscr = readl_relaxed(OSCR);
-}
-
-static void pxa_timer_resume(struct clock_event_device *cedev)
-{
-	/*
-	 * Ensure that we have at least MIN_OSCR_DELTA between match
-	 * register 0 and the OSCR, to guarantee that we will receive
-	 * the one-shot timer interrupt.  We adjust OSMR0 in preference
-	 * to OSCR to guarantee that OSCR is monotonically incrementing.
-	 */
-	if (osmr[0] - oscr < MIN_OSCR_DELTA)
-		osmr[0] += MIN_OSCR_DELTA;
-
-	writel_relaxed(osmr[0], OSMR0);
-	writel_relaxed(osmr[1], OSMR1);
-	writel_relaxed(osmr[2], OSMR2);
-	writel_relaxed(osmr[3], OSMR3);
-	writel_relaxed(oier, OIER);
-	writel_relaxed(oscr, OSCR);
-}
-#else
-#define pxa_timer_suspend NULL
-#define pxa_timer_resume NULL
-#endif
-
-static struct clock_event_device ckevt_pxa_osmr0 = {
-	.name		= "osmr0",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= pxa_osmr0_set_next_event,
-	.set_mode	= pxa_osmr0_set_mode,
-	.suspend	= pxa_timer_suspend,
-	.resume		= pxa_timer_resume,
-};
-
-static struct irqaction pxa_ost0_irq = {
-	.name		= "ost0",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= pxa_ost0_interrupt,
-	.dev_id		= &ckevt_pxa_osmr0,
-};
-
-void __init pxa_timer_init(void)
-{
-	unsigned long clock_tick_rate = get_clock_tick_rate();
-
-	writel_relaxed(0, OIER);
-	writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
-	sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
-
-	ckevt_pxa_osmr0.cpumask = cpumask_of(0);
-
-	setup_irq(IRQ_OST0, &pxa_ost0_irq);
-
-	clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
-		clocksource_mmio_readl_up);
-	clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
-		MIN_OSCR_DELTA * 2, 0x7fffffff);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-pxa/viper.c linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/viper.c
--- linux-libre-3.16-gnu/arch/arm/mach-pxa/viper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-pxa/viper.c	2014-09-28 17:29:07.000000000 -0400
@@ -769,7 +769,7 @@ static unsigned long viper_tpm;
 
 static int __init viper_tpm_setup(char *str)
 {
-	return strict_strtoul(str, 10, &viper_tpm) >= 0;
+	return kstrtoul(str, 10, &viper_tpm) >= 0;
 }
 
 __setup("tpm=", viper_tpm_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-realview/core.c linux-libre-3.17-rc7-gnu/arch/arm/mach-realview/core.c
--- linux-libre-3.16-gnu/arch/arm/mach-realview/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-realview/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/ata_platform.h>
@@ -48,7 +49,6 @@
 #include <mach/irqs.h>
 #include <asm/hardware/timer-sp.h>
 
-#include <plat/clcd.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-realview/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-realview/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-realview/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-realview/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,15 +20,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-/*
- * Physical DRAM offset.
- */
-#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
-#define PLAT_PHYS_OFFSET		UL(0x70000000)
-#else
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-#endif
-
 #ifdef CONFIG_SPARSEMEM
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-rockchip/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-rockchip/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -2,9 +2,11 @@ config ARCH_ROCKCHIP
 	bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7
 	select PINCTRL
 	select PINCTRL_ROCKCHIP
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select CACHE_L2X0
+	select HAVE_ARM_ARCH_TIMER
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select DW_APB_TIMER_OF
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-rockchip/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-rockchip/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,2 +1,4 @@
+CFLAGS_platsmp.o := -march=armv7-a
+
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-rockchip/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-rockchip/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 #include <asm/mach/map.h>
@@ -178,8 +179,27 @@ static void __init rockchip_smp_prepare_
 		pmu_set_power_domain(0 + i, false);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int rockchip_cpu_kill(unsigned int cpu)
+{
+	pmu_set_power_domain(0 + cpu, false);
+	return 1;
+}
+
+static void rockchip_cpu_die(unsigned int cpu)
+{
+	v7_exit_coherency_flush(louis);
+	while(1)
+		cpu_do_idle();
+}
+#endif
+
 static struct smp_operations rockchip_smp_ops __initdata = {
 	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
 	.smp_boot_secondary	= rockchip_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= rockchip_cpu_kill,
+	.cpu_die		= rockchip_cpu_die,
+#endif
 };
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-rockchip/rockchip.c linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/rockchip.c
--- linux-libre-3.16-gnu/arch/arm/mach-rockchip/rockchip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-rockchip/rockchip.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@ static const char * const rockchip_board
 	"rockchip,rk3066a",
 	"rockchip,rk3066b",
 	"rockchip,rk3188",
+	"rockchip,rk3288",
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-rpc/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-rpc/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-rpc/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-rpc/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,11 +19,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 /*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x10000000)
-
-/*
  * Cache flushing area - ROM
  */
 #define FLUSH_BASE_PHYS		0x00000000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,9 +49,7 @@
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/clock.h>
 #include <plat/cpu-freq.h>
-#include <plat/pll.h>
 #include <plat/pwm-core.h>
 #include <plat/watchdog-reset.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/iotiming-s3c2412.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/iotiming-s3c2412.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/iotiming-s3c2412.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/iotiming-s3c2412.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,6 @@
 
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
-#include <plat/clock.h>
 
 #include <mach/s3c2412.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-h1940.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-h1940.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-h1940.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-h1940.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,6 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
-#include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/samsung-time.h>
 
@@ -73,6 +72,10 @@
 
 #define H1940_LATCH_BIT(x)	(1 << ((x) + 16 - S3C_GPIO_END))
 
+#define S3C24XX_PLL_MDIV_SHIFT         (12)
+#define S3C24XX_PLL_PDIV_SHIFT         (4)
+#define S3C24XX_PLL_SDIV_SHIFT         (0)
+
 static struct map_desc h1940_iodesc[] __initdata = {
 	[0] = {
 		.virtual	= (unsigned long)H1940_LATCH,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-jive.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-jive.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-jive.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-jive.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
@@ -243,7 +242,7 @@ static int __init jive_mtdset(char *opti
 	if (options == NULL || options[0] == '\0')
 		return 0;
 
-	if (strict_strtoul(options, 10, &set)) {
+	if (kstrtoul(options, 10, &set)) {
 		printk(KERN_ERR "failed to parse mtdset=%s\n", options);
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2413.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2413.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2413.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2413.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,6 @@
 #include <mach/gpio-samsung.h>
 #include <mach/fb.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/samsung-time.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2416.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2416.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2416.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2416.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2443.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2443.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-smdk2443.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-smdk2443.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,6 @@
 #include <mach/fb.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/samsung-time.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-vstms.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-vstms.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/mach-vstms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/mach-vstms.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/samsung-time.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2410.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2410.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2410.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,6 @@
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/watchdog-reset.h>
 
@@ -83,10 +81,6 @@ void __init s3c2410_map_io(void)
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
 
-void __init_or_cpufreq s3c2410_setup_clocks(void)
-{
-}
-
 struct bus_type s3c2410_subsys = {
 	.name = "s3c2410-core",
 	.dev_name = "s3c2410-core",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2412.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2412.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2412.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2412.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,12 +37,10 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/cpu-freq.h>
 #include <plat/devs.h>
 #include <plat/nand-core.h>
-#include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/regs-spi.h>
 
@@ -171,10 +169,6 @@ void __init s3c2412_map_io(void)
 	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
 }
 
-void __init_or_cpufreq s3c2412_setup_clocks(void)
-{
-}
-
 /* need to register the subsystem before we actually register the device, and
  * we also need to ensure that it has been initialised before any of the
  * drivers even try to use it (even if not on an s3c2412 based system)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2442.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2442.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c2442.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c2442.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,6 @@
 
 #include <mach/regs-clock.h>
 
-#include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c244x.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c244x.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/s3c244x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/s3c244x.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,11 +38,9 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/pll.h>
 #include <plat/nand-core.h>
 #include <plat/watchdog-reset.h>
 
@@ -78,10 +76,6 @@ void __init s3c244x_map_io(void)
 	s3c2410_device_dclk.name = "s3c2440-dclk";
 }
 
-void __init_or_cpufreq s3c244x_setup_clocks(void)
-{
-}
-
 /* Since the S3C2442 and S3C2440 share items, put both subsystems here */
 
 struct bus_type s3c2440_subsys = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/sleep-s3c2410.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/sleep-s3c2410.S
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/sleep-s3c2410.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/sleep-s3c2410.S	2014-09-28 17:29:07.000000000 -0400
@@ -66,4 +66,4 @@ s3c2410_do_sleep:
 	streq	r8, [r5]			@ SDRAM power-down config
 	streq	r9, [r6]			@ CPU sleep
 1:	beq	1b
-	mov	pc, r14
+	ret	lr
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/sleep-s3c2412.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/sleep-s3c2412.S
--- linux-libre-3.16-gnu/arch/arm/mach-s3c24xx/sleep-s3c2412.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c24xx/sleep-s3c2412.S	2014-09-28 17:29:07.000000000 -0400
@@ -65,4 +65,4 @@ s3c2412_sleep_enter1:
 	strne	r9, [r3]
 	bne	s3c2412_sleep_enter1
 
-	mov	pc, r14
+	ret	lr
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <mach/regs-gpio.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,6 @@
 #include <linux/platform_data/spi-s3c64xx.h>
 
 #include <plat/keypad.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/adc.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-hmt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-hmt.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,6 @@
 #include <plat/fb.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/samsung-time.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-ncp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-ncp.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-ncp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-ncp.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,6 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/samsung-time.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smartq.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smartq.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smartq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smartq.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,6 @@
 #include <mach/regs-gpio.h>
 #include <mach/gpio-samsung.h>
 
-#include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <linux/platform_data/i2c-s3c2410.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,6 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,7 +63,6 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/adc.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/s3c6400.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/s3c6400.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/s3c6400.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/s3c6400.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,6 @@
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/clock.h>
 #include <plat/sdhci.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/s3c6410.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/s3c6410.c
--- linux-libre-3.16-gnu/arch/arm/mach-s3c64xx/s3c6410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s3c64xx/s3c6410.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,6 @@
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/clock.h>
 #include <plat/sdhci.h>
 #include <plat/ata-core.h>
 #include <plat/adc-core.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,236 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_apll,
-	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-struct clksrc_clk clk_mout_mpll = {
-	.clk	= {
-		.name		= "mout_mpll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 },
-};
-
-struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_epll,
-	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 },
-};
-
-enum perf_level {
-	L0 = 532*1000,
-	L1 = 266*1000,
-	L2 = 133*1000,
-};
-
-static const u32 clock_table[][3] = {
-	/*{ARM_CLK, DIVarm, DIVhclk}*/
-	{L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
-	{L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
-	{L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
-};
-
-static unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv;
-
-	/* divisor mask starts at bit0, so no need to shift */
-	clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
-
-	return rate / (clkdiv + 1);
-}
-
-static unsigned long s5p64x0_armclk_round_rate(struct clk *clk,
-					       unsigned long rate)
-{
-	u32 iter;
-
-	for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-		if (rate > clock_table[iter][0])
-			return clock_table[iter-1][0];
-	}
-
-	return clock_table[ARRAY_SIZE(clock_table) - 1][0];
-}
-
-static int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 round_tmp;
-	u32 iter;
-	u32 clk_div0_tmp;
-	u32 cur_rate = clk->ops->get_rate(clk);
-	unsigned long flags;
-
-	round_tmp = clk->ops->round_rate(clk, rate);
-	if (round_tmp == cur_rate)
-		return 0;
-
-
-	for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-		if (round_tmp == clock_table[iter][0])
-			break;
-	}
-
-	if (iter >= ARRAY_SIZE(clock_table))
-		iter = ARRAY_SIZE(clock_table) - 1;
-
-	local_irq_save(flags);
-	if (cur_rate > round_tmp) {
-		/* Frequency Down */
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-		clk_div0_tmp |= clock_table[iter][1];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-				~(S5P64X0_CLKDIV0_HCLK_MASK);
-		clk_div0_tmp |= clock_table[iter][2];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-
-	} else {
-		/* Frequency Up */
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-				~(S5P64X0_CLKDIV0_HCLK_MASK);
-		clk_div0_tmp |= clock_table[iter][2];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-		clk_div0_tmp |= clock_table[iter][1];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-	}
-	local_irq_restore(flags);
-
-	clk->rate = clock_table[iter][0];
-
-	return 0;
-}
-
-static struct clk_ops s5p64x0_clkarm_ops = {
-	.get_rate	= s5p64x0_armclk_get_rate,
-	.set_rate	= s5p64x0_armclk_set_rate,
-	.round_rate	= s5p64x0_armclk_round_rate,
-};
-
-struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.id		= 1,
-		.parent		= &clk_mout_apll.clk,
-		.ops		= &s5p64x0_clkarm_ops,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 },
-};
-
-struct clksrc_clk clk_dout_mpll = {
-	.clk	= {
-		.name		= "dout_mpll",
-		.id		= -1,
-		.parent		= &clk_mout_mpll.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_hclk_low_list[] = {
-	&clk_mout_apll.clk,
-	&clk_mout_mpll.clk,
-};
-
-struct clksrc_sources clkset_hclk_low = {
-	.sources	= clkset_hclk_low_list,
-	.nr_sources	= ARRAY_SIZE(clkset_hclk_low_list),
-};
-
-int s5p64x0_pclk_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable);
-}
-
-int s5p64x0_hclk0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable);
-}
-
-int s5p64x0_hclk1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable);
-}
-
-int s5p64x0_sclk_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable);
-}
-
-int s5p64x0_sclk1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable);
-}
-
-int s5p64x0_mem_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable);
-}
-
-int s5p64x0_clk48m_ctrl(struct clk *clk, int enable)
-{
-	unsigned long flags;
-	u32 val;
-
-	/* can't rely on clock lock, this register has other usages */
-	local_irq_save(flags);
-
-	val = __raw_readl(S5P64X0_OTHERS);
-	if (enable)
-		val |= S5P64X0_OTHERS_USB_SIG_MASK;
-	else
-		val &= ~S5P64X0_OTHERS_USB_SIG_MASK;
-
-	__raw_writel(val, S5P64X0_OTHERS);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p64x0 clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __MACH_S5P64X0_CLOCK_H
-#define __MACH_S5P64X0_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk clk_mout_apll;
-extern struct clksrc_clk clk_mout_mpll;
-extern struct clksrc_clk clk_mout_epll;
-
-extern int s5p64x0_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p64x0_epll_get_rate(struct clk *clk);
-
-extern struct clksrc_clk clk_armclk;
-extern struct clksrc_clk clk_dout_mpll;
-
-extern struct clksrc_sources clkset_hclk_low;
-
-extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_mem_ctrl(struct clk *clk, int enable);
-
-extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable);
-
-#endif /* __MACH_S5P64X0_CLOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,632 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P6440 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "clock.h"
-#include "common.h"
-
-static u32 epll_div[][5] = {
-	{ 36000000,	0,	48, 1, 4 },
-	{ 48000000,	0,	32, 1, 3 },
-	{ 60000000,	0,	40, 1, 3 },
-	{ 72000000,	0,	48, 1, 3 },
-	{ 84000000,	0,	28, 1, 2 },
-	{ 96000000,	0,	32, 1, 2 },
-	{ 32768000,	45264,	43, 1, 4 },
-	{ 45158000,	6903,	30, 1, 3 },
-	{ 49152000,	50332,	32, 1, 3 },
-	{ 67738000,	10398,	45, 1, 3 },
-	{ 73728000,	9961,	49, 1, 3 }
-};
-
-static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con, epll_con_k;
-	unsigned int i;
-
-	if (clk->rate == rate)	/* Return if nothing changed */
-		return 0;
-
-	epll_con = __raw_readl(S5P64X0_EPLL_CON);
-	epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
-
-	epll_con_k &= ~(PLL90XX_KDIV_MASK);
-	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		 if (epll_div[i][0] == rate) {
-			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
-			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
-				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
-				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(epll_con, S5P64X0_EPLL_CON);
-	__raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
-
-	printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
-			clk->rate, rate);
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops s5p6440_epll_ops = {
-	.get_rate = s5p_epll_get_rate,
-	.set_rate = s5p6440_epll_set_rate,
-};
-
-static struct clksrc_clk clk_hclk = {
-	.clk	= {
-		.name		= "clk_hclk",
-		.parent		= &clk_armclk.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
-	.clk	= {
-		.name		= "clk_pclk",
-		.parent		= &clk_hclk.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
-};
-static struct clksrc_clk clk_hclk_low = {
-	.clk	= {
-		.name		= "clk_hclk_low",
-	},
-	.sources	= &clkset_hclk_low,
-	.reg_src	= { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
-	.clk	= {
-		.name		= "clk_pclk_low",
-		.parent		= &clk_hclk_low.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "nand",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_mem_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "post",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 5)
-	}, {
-		.name		= "2d",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dma",
-		.devname	= "dma-pl330",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "otg",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 20)
-	}, {
-		.name		= "irom",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk1_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "hclk_fimgvg",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk1_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "tsi",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "timers",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "pcm",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "adc",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "s5p64x0-spi.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "spi",
-		.devname	= "s5p64x0-spi.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "gps",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "dsim",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 28),
-	}, {
-		.name		= "etm",
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 29),
-	}, {
-		.name		= "dmc0",
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 30),
-	}, {
-		.name		= "pclk_fimgvg",
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 31),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_48m,
-		.enable		= s5p64x0_sclk_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_48m,
-		.enable		= s5p64x0_sclk_ctrl,
-		.ctrlbit	= (1 << 28),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_48m,
-		.enable		= s5p64x0_sclk_ctrl,
-		.ctrlbit	= (1 << 29),
-	},
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
-	{
-		.name		= "intc",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "mem",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.2",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.3",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 18),
-	},
-};
-
-static struct clk clk_iis_cd_v40 = {
-	.name		= "iis_cdclk_v40",
-};
-
-static struct clk clk_pcm_cd = {
-	.name		= "pcm_cdclk",
-};
-
-static struct clk *clkset_group1_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_group1 = {
-	.sources	= clkset_group1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_audio_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_fin_epll,
-	&clk_iis_cd_v40,
-	&clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio = {
-	.sources	= clkset_audio_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_post",
-			.ctrlbit	= (1 << 10),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dispcon",
-			.ctrlbit	= (1 << 1),
-			.enable		= s5p64x0_sclk1_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimgvg",
-			.ctrlbit	= (1 << 2),
-			.enable		= s5p64x0_sclk1_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
-	},
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.0",
-		.ctrlbit	= (1 << 24),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group1,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.1",
-		.ctrlbit	= (1 << 25),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group1,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.2",
-		.ctrlbit	= (1 << 26),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group1,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uclk = {
-	.clk	= {
-		.name		= "uclk1",
-		.ctrlbit	= (1 << 5),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
-};
-
-static struct clk clk_i2s0 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.0",
-	.parent		= &clk_pclk_low.clk,
-	.enable		= s5p64x0_pclk_ctrl,
-	.ctrlbit	= (1 << 26),
-};
-
-static struct clksrc_clk clk_audio_bus2 = {
-	.clk	= {
-		.name		= "sclk_audio2",
-		.devname	= "samsung-i2s.0",
-		.ctrlbit	= (1 << 11),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_audio,
-	.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5p64x0-spi.0",
-		.ctrlbit	= (1 << 20),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group1,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5p64x0-spi.1",
-		.ctrlbit	= (1 << 21),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group1,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_dout_mpll,
-	&clk_armclk,
-	&clk_hclk,
-	&clk_pclk,
-	&clk_hclk_low,
-	&clk_pclk_low,
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static struct clk *clk_cdev[] = {
-	&clk_i2s0,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
-	&clk_sclk_uclk,
-	&clk_sclk_spi0,
-	&clk_sclk_spi1,
-	&clk_sclk_mmc0,
-	&clk_sclk_mmc1,
-	&clk_sclk_mmc2,
-	&clk_audio_bus2,
-};
-
-static struct clk_lookup s5p6440_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
-	CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-	CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-	CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus2.clk),
-};
-
-void __init_or_cpufreq s5p6440_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long hclk_low;
-	unsigned long pclk;
-	unsigned long pclk_low;
-
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned int ptr;
-
-	/* Set S5P6440 functions for clk_fout_epll */
-
-	clk_fout_epll.enable = s5p_epll_enable;
-	clk_fout_epll.ops = &s5p6440_epll_ops;
-
-	clk_48m.enable = s5p64x0_clk48m_ctrl;
-
-	xtal_clk = clk_get(NULL, "ext_xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
-	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
-				__raw_readl(S5P64X0_EPLL_CON_K));
-
-	clk_fout_apll.rate = apll;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-
-	printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
-			" E=%ld.%ldMHz\n",
-			print_mhz(apll), print_mhz(mpll), print_mhz(epll));
-
-	fclk = clk_get_rate(&clk_armclk.clk);
-	hclk = clk_get_rate(&clk_hclk.clk);
-	pclk = clk_get_rate(&clk_pclk.clk);
-	hclk_low = clk_get_rate(&clk_hclk_low.clk);
-	pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
-	printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
-			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
-			print_mhz(hclk), print_mhz(hclk_low),
-			print_mhz(pclk), print_mhz(pclk_low));
-
-	clk_f.rate = fclk;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_iis_cd_v40,
-	&clk_pcm_cd,
-};
-
-void __init s5p6440_register_clocks(void)
-{
-	int ptr;
-	unsigned int cnt;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
-	for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
-		s3c_disable_clocks(clk_cdev[cnt], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
-		s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s5p6440_clk_lookup, ARRAY_SIZE(s5p6440_clk_lookup));
-
-	s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,701 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P6450 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "clock.h"
-#include "common.h"
-
-static struct clksrc_clk clk_mout_dpll = {
-	.clk	= {
-		.name		= "mout_dpll",
-	},
-	.sources	= &clk_src_dpll,
-	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
-};
-
-static u32 epll_div[][5] = {
-	{ 133000000,	27307,	55, 2, 2 },
-	{ 100000000,	43691,	41, 2, 2 },
-	{ 480000000,	0,	80, 2, 0 },
-};
-
-static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con, epll_con_k;
-	unsigned int i;
-
-	if (clk->rate == rate)	/* Return if nothing changed */
-		return 0;
-
-	epll_con = __raw_readl(S5P64X0_EPLL_CON);
-	epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
-
-	epll_con_k &= ~(PLL90XX_KDIV_MASK);
-	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		 if (epll_div[i][0] == rate) {
-			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
-			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
-				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
-				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(epll_con, S5P64X0_EPLL_CON);
-	__raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
-
-	printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
-			clk->rate, rate);
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops s5p6450_epll_ops = {
-	.get_rate = s5p_epll_get_rate,
-	.set_rate = s5p6450_epll_set_rate,
-};
-
-static struct clksrc_clk clk_dout_epll = {
-	.clk	= {
-		.name		= "dout_epll",
-		.parent		= &clk_mout_epll.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_mout_hclk_sel = {
-	.clk	= {
-		.name		= "mout_hclk_sel",
-	},
-	.sources	= &clkset_hclk_low,
-	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
-};
-
-static struct clk *clkset_hclk_list[] = {
-	&clk_mout_hclk_sel.clk,
-	&clk_armclk.clk,
-};
-
-static struct clksrc_sources clkset_hclk = {
-	.sources	= clkset_hclk_list,
-	.nr_sources	= ARRAY_SIZE(clkset_hclk_list),
-};
-
-static struct clksrc_clk clk_hclk = {
-	.clk	= {
-		.name		= "clk_hclk",
-	},
-	.sources	= &clkset_hclk,
-	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
-	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
-	.clk	= {
-		.name		= "clk_pclk",
-		.parent		= &clk_hclk.clk,
-	},
-	.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
-};
-static struct clksrc_clk clk_dout_pwm_ratio0 = {
-	.clk	= {
-		.name		= "clk_dout_pwm_ratio0",
-		.parent		= &clk_mout_hclk_sel.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_to_wdt_pwm = {
-	.clk	= {
-		.name		= "clk_pclk_to_wdt_pwm",
-		.parent		= &clk_dout_pwm_ratio0.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
-};
-
-static struct clksrc_clk clk_hclk_low = {
-	.clk	= {
-		.name		= "clk_hclk_low",
-	},
-	.sources	= &clkset_hclk_low,
-	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
-	.clk	= {
-		.name		= "clk_pclk_low",
-		.parent		= &clk_hclk_low.clk,
-	},
-	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "usbhost",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "dma",
-		.devname	= "dma-pl330",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "usbotg",
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_h,
-		.enable		= s5p64x0_hclk1_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "adc",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "s5p64x0-spi.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "spi",
-		.devname	= "s5p64x0-spi.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "dmc0",
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 30),
-	}
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
-	{
-		.name		= "intc",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "mem",
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p64x0_hclk0_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.2",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.3",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "timers",
-		.parent		= &clk_pclk_to_wdt_pwm.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 18),
-	},
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_dout_epll.clk,
-	&clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_mali_list[] = {
-	&clk_mout_epll.clk,
-	&clk_mout_apll.clk,
-	&clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_mali = {
-	.sources	= clkset_mali_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mali_list),
-};
-
-static struct clk *clkset_group2_list[] = {
-	&clk_dout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_ext_xtal_mux,
-};
-
-static struct clksrc_sources clkset_group2 = {
-	.sources	= clkset_group2_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group2_list),
-};
-
-static struct clk *clkset_dispcon_list[] = {
-	&clk_dout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_ext_xtal_mux,
-	&clk_mout_dpll.clk,
-};
-
-static struct clksrc_sources clkset_dispcon = {
-	.sources	= clkset_dispcon_list,
-	.nr_sources	= ARRAY_SIZE(clkset_dispcon_list),
-};
-
-static struct clk *clkset_hsmmc44_list[] = {
-	&clk_dout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_ext_xtal_mux,
-	&s5p_clk_27m,
-	&clk_48m,
-};
-
-static struct clksrc_sources clkset_hsmmc44 = {
-	.sources	= clkset_hsmmc44_list,
-	.nr_sources	= ARRAY_SIZE(clkset_hsmmc44_list),
-};
-
-static struct clk *clkset_sclk_audio0_list[] = {
-	[0] = &clk_dout_epll.clk,
-	[1] = &clk_dout_mpll.clk,
-	[2] = &clk_ext_xtal_mux,
-	[3] = NULL,
-	[4] = NULL,
-};
-
-static struct clksrc_sources clkset_sclk_audio0 = {
-	.sources	= clkset_sclk_audio0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
-	.clk		= {
-		.name		= "audio-bus",
-		.devname	= "samsung-i2s.0",
-		.enable		= s5p64x0_sclk_ctrl,
-		.ctrlbit	= (1 << 8),
-		.parent		= &clk_dout_epll.clk,
-	},
-	.sources	= &clkset_sclk_audio0,
-	.reg_src	= { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
-	.reg_div	= { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_fimc",
-			.ctrlbit	= (1 << 10),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "aclk_mali",
-			.ctrlbit	= (1 << 2),
-			.enable		= s5p64x0_sclk1_ctrl,
-		},
-		.sources = &clkset_mali,
-		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_2d",
-			.ctrlbit	= (1 << 12),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_mali,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_usi",
-			.ctrlbit	= (1 << 7),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_camif",
-			.ctrlbit	= (1 << 6),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dispcon",
-			.ctrlbit	= (1 << 1),
-			.enable		= s5p64x0_sclk1_ctrl,
-		},
-		.sources = &clkset_dispcon,
-		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_hsmmc44",
-			.ctrlbit	= (1 << 30),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_hsmmc44,
-		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
-	},
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.0",
-		.ctrlbit	= (1 << 24),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.1",
-		.ctrlbit	= (1 << 25),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.2",
-		.ctrlbit	= (1 << 26),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uclk = {
-	.clk	= {
-		.name		= "uclk1",
-		.ctrlbit	= (1 << 5),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5p64x0-spi.0",
-		.ctrlbit	= (1 << 20),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5p64x0-spi.1",
-		.ctrlbit	= (1 << 21),
-		.enable		= s5p64x0_sclk_ctrl,
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
-	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-static struct clk clk_i2s0 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.0",
-	.parent		= &clk_pclk_low.clk,
-	.enable		= s5p64x0_pclk_ctrl,
-	.ctrlbit	= (1 << 26),
-};
-
-static struct clk clk_i2s1 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.1",
-	.parent		= &clk_pclk_low.clk,
-	.enable		= s5p64x0_pclk_ctrl,
-	.ctrlbit	= (1 << 15),
-};
-
-static struct clk clk_i2s2 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.2",
-	.parent		= &clk_pclk_low.clk,
-	.enable		= s5p64x0_pclk_ctrl,
-	.ctrlbit	= (1 << 16),
-};
-
-static struct clk *clk_cdev[] = {
-	&clk_i2s0,
-	&clk_i2s1,
-	&clk_i2s2,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
-	&clk_sclk_uclk,
-	&clk_sclk_spi0,
-	&clk_sclk_spi1,
-	&clk_sclk_mmc0,
-	&clk_sclk_mmc1,
-	&clk_sclk_mmc2,
-	&clk_sclk_audio0,
-};
-
-static struct clk_lookup s5p6450_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
-	CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-	CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-	CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_sclk_audio0.clk),
-	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
-	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_dout_epll,
-	&clk_mout_mpll,
-	&clk_dout_mpll,
-	&clk_armclk,
-	&clk_mout_hclk_sel,
-	&clk_dout_pwm_ratio0,
-	&clk_pclk_to_wdt_pwm,
-	&clk_hclk,
-	&clk_pclk,
-	&clk_hclk_low,
-	&clk_pclk_low,
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-void __init_or_cpufreq s5p6450_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long hclk_low;
-	unsigned long pclk;
-	unsigned long pclk_low;
-
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long dpll;
-	unsigned int ptr;
-
-	/* Set S5P6450 functions for clk_fout_epll */
-
-	clk_fout_epll.enable = s5p_epll_enable;
-	clk_fout_epll.ops = &s5p6450_epll_ops;
-
-	clk_48m.enable = s5p64x0_clk48m_ctrl;
-
-	xtal_clk = clk_get(NULL, "ext_xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
-	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
-				__raw_readl(S5P64X0_EPLL_CON_K));
-	dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
-				__raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
-
-	clk_fout_apll.rate = apll;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_dpll.rate = dpll;
-
-	printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
-			" E=%ld.%ldMHz, D=%ld.%ldMHz\n",
-			print_mhz(apll), print_mhz(mpll), print_mhz(epll),
-			print_mhz(dpll));
-
-	fclk = clk_get_rate(&clk_armclk.clk);
-	hclk = clk_get_rate(&clk_hclk.clk);
-	pclk = clk_get_rate(&clk_pclk.clk);
-	hclk_low = clk_get_rate(&clk_hclk_low.clk);
-	pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
-	printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
-			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
-			print_mhz(hclk), print_mhz(hclk_low),
-			print_mhz(pclk), print_mhz(pclk_low));
-
-	clk_f.rate = fclk;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-void __init s5p6450_register_clocks(void)
-{
-	int ptr;
-	unsigned int cnt;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-
-	s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
-	for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
-		s3c_disable_clocks(clk_cdev[cnt], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
-		s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup));
-
-	s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,490 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Common Codes for S5P64X0 machines
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/reboot.h>
-
-#include <asm/irq.h>
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/pm.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/fb-core.h>
-#include <plat/spi-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/pwm-core.h>
-#include <plat/regs-irqtype.h>
-#include <plat/watchdog-reset.h>
-
-#include "common.h"
-
-static const char name_s5p6440[] = "S5P6440";
-static const char name_s5p6450[] = "S5P6450";
-
-static struct cpu_table cpu_ids[] __initdata = {
-	{
-		.idcode		= S5P6440_CPU_ID,
-		.idmask		= S5P64XX_CPU_MASK,
-		.map_io		= s5p6440_map_io,
-		.init_clocks	= s5p6440_init_clocks,
-		.init_uarts	= s5p6440_init_uarts,
-		.init		= s5p64x0_init,
-		.name		= name_s5p6440,
-	}, {
-		.idcode		= S5P6450_CPU_ID,
-		.idmask		= S5P64XX_CPU_MASK,
-		.map_io		= s5p6450_map_io,
-		.init_clocks	= s5p6450_init_clocks,
-		.init_uarts	= s5p6450_init_uarts,
-		.init		= s5p64x0_init,
-		.name		= name_s5p6450,
-	},
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5p64x0_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_CHIPID,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_CHIPID),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_SYS,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_SYSCON),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_TIMER,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_TIMER),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_WDT),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_GPIO),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC0,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_VIC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC1,
-		.pfn		= __phys_to_pfn(S5P64X0_PA_VIC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static struct map_desc s5p6440_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S5P6440_PA_UART(0)),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static struct map_desc s5p6450_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S5P6450_PA_UART(0)),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART + SZ_512K,
-		.pfn		= __phys_to_pfn(S5P6450_PA_UART(5)),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void s5p64x0_idle(void)
-{
-	unsigned long val;
-
-	val = __raw_readl(S5P64X0_PWR_CFG);
-	val &= ~(0x3 << 5);
-	val |= (0x1 << 5);
-	__raw_writel(val, S5P64X0_PWR_CFG);
-
-	cpu_do_idle();
-}
-
-static struct samsung_pwm_variant s5p64x0_pwm_variant = {
-	.bits		= 32,
-	.div_base	= 0,
-	.has_tint_cstat	= true,
-	.tclk_mask	= 0,
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
-	s5p64x0_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
-	s5p64x0_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
-	unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
-		IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
-		IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
-	};
-
-	samsung_pwm_clocksource_init(S3C_VA_TIMER,
-					timer_irqs, &s5p64x0_pwm_variant);
-}
-
-/*
- * s5p64x0_map_io
- *
- * register the standard CPU IO areas
- */
-
-void __init s5p64x0_init_io(struct map_desc *mach_desc, int size)
-{
-	/* initialize the io descriptors we need for initialization */
-	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
-	if (mach_desc)
-		iotable_init(mach_desc, size);
-
-	/* detect cpu id and rev. */
-	s5p_init_cpu(S5P64X0_SYS_ID);
-
-	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
-	samsung_wdt_reset_init(S3C_VA_WATCHDOG);
-
-	samsung_pwm_set_platdata(&s5p64x0_pwm_variant);
-}
-
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_map_io(void)
-{
-	/* initialize any device information early */
-	s3c_adc_setname("s3c64xx-adc");
-	s3c_fb_setname("s5p64x0-fb");
-	s3c64xx_spi_setname("s5p64x0-spi");
-
-	s5p64x0_default_sdhci0();
-	s5p64x0_default_sdhci1();
-	s5p6440_default_sdhci2();
-
-	iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_map_io(void)
-{
-	/* initialize any device information early */
-	s3c_adc_setname("s3c64xx-adc");
-	s3c_fb_setname("s5p64x0-fb");
-	s3c64xx_spi_setname("s5p64x0-spi");
-
-	s5p64x0_default_sdhci0();
-	s5p64x0_default_sdhci1();
-	s5p6450_default_sdhci2();
-
-	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
-}
-#endif
-
-/*
- * s5p64x0_init_clocks
- *
- * register and setup the CPU clocks
- */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5p6440_register_clocks();
-	s5p6440_setup_clocks();
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5p6450_register_clocks();
-	s5p6450_setup_clocks();
-}
-#endif
-
-/*
- * s5p64x0_init_irq
- *
- * register the CPU interrupts
- */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_irq(void)
-{
-	/* S5P6440 supports 2 VIC */
-	u32 vic[2];
-
-	/*
-	 * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
-	 * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
-	 */
-	vic[0] = 0xff800ae7;
-	vic[1] = 0xffbf23e5;
-
-	s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_irq(void)
-{
-	/* S5P6450 supports only 2 VIC */
-	u32 vic[2];
-
-	/*
-	 * VIC0 is missing IRQ_VIC0[(13-15), (21-22)]
-	 * VIC1 is missing IRQ VIC1[12, 14, 23]
-	 */
-	vic[0] = 0xff9f1fff;
-	vic[1] = 0xff7fafff;
-
-	s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-#endif
-
-struct bus_type s5p64x0_subsys = {
-	.name		= "s5p64x0-core",
-	.dev_name	= "s5p64x0-core",
-};
-
-static struct device s5p64x0_dev = {
-	.bus	= &s5p64x0_subsys,
-};
-
-static int __init s5p64x0_core_init(void)
-{
-	return subsys_system_register(&s5p64x0_subsys, NULL);
-}
-core_initcall(s5p64x0_core_init);
-
-int __init s5p64x0_init(void)
-{
-	printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n");
-
-	/* set idle function */
-	arm_pm_idle = s5p64x0_idle;
-
-	return device_register(&s5p64x0_dev);
-}
-
-/* uart registration process */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	int uart;
-
-	for (uart = 0; uart < no; uart++) {
-		s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart);
-		s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
-	}
-
-	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-#endif
-
-#define eint_offset(irq)	((irq) - IRQ_EINT(0))
-
-static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
-	int offs = eint_offset(data->irq);
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-
-	if (offs > 15)
-		return -EINVAL;
-
-	switch (type) {
-	case IRQ_TYPE_NONE:
-		printk(KERN_WARNING "No edge setting!\n");
-		break;
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S3C2410_EXTINT_RISEEDGE;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S3C2410_EXTINT_FALLEDGE;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S3C2410_EXTINT_BOTHEDGE;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S3C2410_EXTINT_LOWLEV;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S3C2410_EXTINT_HILEV;
-		break;
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -EINVAL;
-	}
-
-	shift = (offs / 2) * 4;
-	mask = 0x7 << shift;
-
-	ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, S5P64X0_EINT0CON0);
-
-	/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
-	if (soc_is_s5p6450())
-		s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
-	else
-		s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
-
-	return 0;
-}
-
-/*
- * s5p64x0_irq_demux_eint
- *
- * This function demuxes the IRQ from the group0 external interrupts,
- * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
- * the specific handlers s5p64x0_irq_demux_eintX_Y.
- */
-static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
-{
-	u32 status = __raw_readl(S5P64X0_EINT0PEND);
-	u32 mask = __raw_readl(S5P64X0_EINT0MASK);
-	unsigned int irq;
-
-	status &= ~mask;
-	status >>= start;
-	status &= (1 << (end - start + 1)) - 1;
-
-	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
-		if (status & 1)
-			generic_handle_irq(irq);
-		status >>= 1;
-	}
-}
-
-static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
-	s5p64x0_irq_demux_eint(0, 3);
-}
-
-static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
-{
-	s5p64x0_irq_demux_eint(4, 11);
-}
-
-static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
-					struct irq_desc *desc)
-{
-	s5p64x0_irq_demux_eint(12, 15);
-}
-
-static int s5p64x0_alloc_gc(void)
-{
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
-				    S5P_VA_GPIO, handle_level_irq);
-	if (!gc) {
-		printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
-			"external interrupts failed\n", __func__);
-		return -EINVAL;
-	}
-
-	ct = gc->chip_types;
-	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_mask = irq_gc_mask_set_bit;
-	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-	ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
-	ct->chip.irq_set_wake = s3c_irqext_wake;
-	ct->regs.ack = EINT0PEND_OFFSET;
-	ct->regs.mask = EINT0MASK_OFFSET;
-	irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-	return 0;
-}
-
-static int __init s5p64x0_init_irq_eint(void)
-{
-	int ret = s5p64x0_alloc_gc();
-	irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
-	irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
-	irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
-
-	return ret;
-}
-arch_initcall(s5p64x0_init_irq_eint);
-
-void s5p64x0_restart(enum reboot_mode mode, const char *cmd)
-{
-	if (mode != REBOOT_SOFT)
-		samsung_wdt_reset();
-
-	soft_restart(0);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Common Header for S5P64X0 machines
- *
- * This program is free software; you can 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_S5P64X0_COMMON_H
-#define __ARCH_ARM_MACH_S5P64X0_COMMON_H
-
-#include <linux/reboot.h>
-
-void s5p6440_init_irq(void);
-void s5p6450_init_irq(void);
-void s5p64x0_init_io(struct map_desc *mach_desc, int size);
-
-void s5p6440_register_clocks(void);
-void s5p6440_setup_clocks(void);
-
-void s5p6450_register_clocks(void);
-void s5p6450_setup_clocks(void);
-
-void s5p64x0_restart(enum reboot_mode mode, const char *cmd);
-extern  int s5p64x0_init(void);
-
-#ifdef CONFIG_CPU_S5P6440
-
-extern void s5p6440_map_io(void);
-extern void s5p6440_init_clocks(int xtal);
-
-extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6440_init_clocks NULL
-#define s5p6440_init_uarts NULL
-#define s5p6440_map_io NULL
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-
-extern void s5p6450_map_io(void);
-extern void s5p6450_init_clocks(int xtal);
-
-extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6450_init_clocks NULL
-#define s5p6450_init_uarts NULL
-#define s5p6450_map_io NULL
-#endif
-
-#endif /* __ARCH_ARM_MACH_S5P64X0_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/dev-audio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/dev-audio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/dev-audio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,176 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5p6440_cfg_i2s(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5P6440_GPC(4), 2, S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPC(7), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin_range(S5P6440_GPH(6), 4, S3C_GPIO_SFN(5));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s5p6440_i2s_pdata = {
-	.cfg_gpio = s5p6440_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN,
-		},
-	},
-};
-
-static struct resource s5p64x0_i2s0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P64X0_PA_I2S, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
-};
-
-struct platform_device s5p6440_device_iis = {
-	.name		= "samsung-i2s",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p64x0_i2s0_resource),
-	.resource	= s5p64x0_i2s0_resource,
-	.dev = {
-		.platform_data = &s5p6440_i2s_pdata,
-	},
-};
-
-static int s5p6450_cfg_i2s(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5));
-		break;
-	case 1:
-		s3c_gpio_cfgpin(S5P6440_GPB(4), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin_range(S5P6450_GPC(0), 4, S3C_GPIO_SFN(5));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5P6450_GPK(0), 5, S3C_GPIO_SFN(5));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s5p6450_i2s0_pdata = {
-	.cfg_gpio = s5p6450_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN,
-		},
-	},
-};
-
-struct platform_device s5p6450_device_iis0 = {
-	.name		= "samsung-i2s",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p64x0_i2s0_resource),
-	.resource	= s5p64x0_i2s0_resource,
-	.dev = {
-		.platform_data = &s5p6450_i2s0_pdata,
-	},
-};
-
-static struct s3c_audio_pdata s5p6450_i2s_pdata = {
-	.cfg_gpio = s5p6450_cfg_i2s,
-};
-
-static struct resource s5p6450_i2s1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P6450_PA_I2S1, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5p6450_device_iis1 = {
-	.name		= "samsung-i2s",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p6450_i2s1_resource),
-	.resource	= s5p6450_i2s1_resource,
-	.dev = {
-		.platform_data = &s5p6450_i2s_pdata,
-	},
-};
-
-static struct resource s5p6450_i2s2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P6450_PA_I2S2, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5p6450_device_iis2 = {
-	.name		= "samsung-i2s",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s5p6450_i2s2_resource),
-	.resource	= s5p6450_i2s2_resource,
-	.dev = {
-		.platform_data = &s5p6450_i2s_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5P6440_GPR(6), 3, S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(2));
-		break;
-
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s5p6440_pcm_pdata = {
-	.cfg_gpio = s5p6440_pcm_cfg_gpio,
-};
-
-static struct resource s5p6440_pcm0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P64X0_PA_PCM, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5p6440_device_pcm = {
-	.name		= "samsung-pcm",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p6440_pcm0_resource),
-	.resource	= s5p6440_pcm0_resource,
-	.dev = {
-		.platform_data = &s5p6440_pcm_pdata,
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/dma.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/dma.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/dma.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/regs-clock.h>
-#include <mach/dma.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-static u8 s5p6440_pdma_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_PCM0_TX,
-	DMACH_PCM0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI0_RX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_SPI1_TX,
-	DMACH_SPI1_RX,
-};
-
-static struct dma_pl330_platdata s5p6440_pdma_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
-	.peri_id = s5p6440_pdma_peri,
-};
-
-static u8 s5p6450_pdma_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_UART4_RX,
-	DMACH_UART4_TX,
-	DMACH_PCM0_TX,
-	DMACH_PCM0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI0_RX,
-	DMACH_PCM1_TX,
-	DMACH_PCM1_RX,
-	DMACH_PCM2_TX,
-	DMACH_PCM2_RX,
-	DMACH_SPI1_TX,
-	DMACH_SPI1_RX,
-	DMACH_USI_TX,
-	DMACH_USI_RX,
-	DMACH_MAX,
-	DMACH_I2S1_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S2_TX,
-	DMACH_I2S2_RX,
-	DMACH_PWM,
-	DMACH_UART5_RX,
-	DMACH_UART5_TX,
-};
-
-static struct dma_pl330_platdata s5p6450_pdma_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
-	.peri_id = s5p6450_pdma_peri,
-};
-
-static AMBA_AHB_DEVICE(s5p64x0_pdma, "dma-pl330", 0x00041330,
-	S5P64X0_PA_PDMA, {IRQ_DMA0}, NULL);
-
-static int __init s5p64x0_dma_init(void)
-{
-	if (soc_is_s5p6450()) {
-		dma_cap_set(DMA_SLAVE, s5p6450_pdma_pdata.cap_mask);
-		dma_cap_set(DMA_CYCLIC, s5p6450_pdma_pdata.cap_mask);
-		s5p64x0_pdma_device.dev.platform_data = &s5p6450_pdma_pdata;
-	} else {
-		dma_cap_set(DMA_SLAVE, s5p6440_pdma_pdata.cap_mask);
-		dma_cap_set(DMA_CYCLIC, s5p6440_pdma_pdata.cap_mask);
-		s5p64x0_pdma_device.dev.platform_data = &s5p6440_pdma_pdata;
-	}
-
-	amba_device_register(&s5p64x0_pdma_device, &iomem_resource);
-
-	return 0;
-}
-arch_initcall(s5p64x0_dma_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/i2c.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/i2c.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/i2c.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/i2c.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 I2C configuration
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev);
-extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev);
-
-extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev);
-extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <linux/serial_s3c.h>
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-	.macro addruart, rp, rv, tmp
-		mov	\rp, #0xE0000000
-		orr	\rp, \rp, #0x00100000
-		ldr	\rp, [\rp, #0x118 ]
-		and	\rp, \rp, #0xff000
-		teq	\rp, #0x50000		@@ S5P6450
-		ldreq	\rp, =0xEC800000
-		movne	\rp, #0xEC000000	@@ S5P6440
-		ldrne	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-#include <debug/samsung.S>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common common DMA API driver for PL330 */
-#include <plat/dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* GPIO bank sizes */
-
-#define S5P6440_GPIO_A_NR	(6)
-#define S5P6440_GPIO_B_NR	(7)
-#define S5P6440_GPIO_C_NR	(8)
-#define S5P6440_GPIO_F_NR	(16)
-#define S5P6440_GPIO_G_NR	(7)
-#define S5P6440_GPIO_H_NR	(10)
-#define S5P6440_GPIO_I_NR	(16)
-#define S5P6440_GPIO_J_NR	(12)
-#define S5P6440_GPIO_N_NR	(16)
-#define S5P6440_GPIO_P_NR	(8)
-#define S5P6440_GPIO_R_NR	(15)
-
-#define S5P6450_GPIO_A_NR	(6)
-#define S5P6450_GPIO_B_NR	(7)
-#define S5P6450_GPIO_C_NR	(8)
-#define S5P6450_GPIO_D_NR	(8)
-#define S5P6450_GPIO_F_NR	(16)
-#define S5P6450_GPIO_G_NR	(14)
-#define S5P6450_GPIO_H_NR	(10)
-#define S5P6450_GPIO_I_NR	(16)
-#define S5P6450_GPIO_J_NR	(12)
-#define S5P6450_GPIO_K_NR	(5)
-#define S5P6450_GPIO_N_NR	(16)
-#define S5P6450_GPIO_P_NR	(11)
-#define S5P6450_GPIO_Q_NR	(14)
-#define S5P6450_GPIO_R_NR	(15)
-#define S5P6450_GPIO_S_NR	(8)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5P64X0_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p6440_gpio_number {
-	S5P6440_GPIO_A_START	= 0,
-	S5P6440_GPIO_B_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_A),
-	S5P6440_GPIO_C_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_B),
-	S5P6440_GPIO_F_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_C),
-	S5P6440_GPIO_G_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_F),
-	S5P6440_GPIO_H_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_G),
-	S5P6440_GPIO_I_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_H),
-	S5P6440_GPIO_J_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_I),
-	S5P6440_GPIO_N_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_J),
-	S5P6440_GPIO_P_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_N),
-	S5P6440_GPIO_R_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_P),
-};
-
-enum s5p6450_gpio_number {
-	S5P6450_GPIO_A_START	= 0,
-	S5P6450_GPIO_B_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_A),
-	S5P6450_GPIO_C_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_B),
-	S5P6450_GPIO_D_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_C),
-	S5P6450_GPIO_F_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_D),
-	S5P6450_GPIO_G_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_F),
-	S5P6450_GPIO_H_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_G),
-	S5P6450_GPIO_I_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_H),
-	S5P6450_GPIO_J_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_I),
-	S5P6450_GPIO_K_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_J),
-	S5P6450_GPIO_N_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_K),
-	S5P6450_GPIO_P_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_N),
-	S5P6450_GPIO_Q_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_P),
-	S5P6450_GPIO_R_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q),
-	S5P6450_GPIO_S_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_R),
-};
-
-/* GPIO number definitions */
-
-#define S5P6440_GPA(_nr)	(S5P6440_GPIO_A_START + (_nr))
-#define S5P6440_GPB(_nr)	(S5P6440_GPIO_B_START + (_nr))
-#define S5P6440_GPC(_nr)	(S5P6440_GPIO_C_START + (_nr))
-#define S5P6440_GPF(_nr)	(S5P6440_GPIO_F_START + (_nr))
-#define S5P6440_GPG(_nr)	(S5P6440_GPIO_G_START + (_nr))
-#define S5P6440_GPH(_nr)	(S5P6440_GPIO_H_START + (_nr))
-#define S5P6440_GPI(_nr)	(S5P6440_GPIO_I_START + (_nr))
-#define S5P6440_GPJ(_nr)	(S5P6440_GPIO_J_START + (_nr))
-#define S5P6440_GPN(_nr)	(S5P6440_GPIO_N_START + (_nr))
-#define S5P6440_GPP(_nr)	(S5P6440_GPIO_P_START + (_nr))
-#define S5P6440_GPR(_nr)	(S5P6440_GPIO_R_START + (_nr))
-
-#define S5P6450_GPA(_nr)	(S5P6450_GPIO_A_START + (_nr))
-#define S5P6450_GPB(_nr)	(S5P6450_GPIO_B_START + (_nr))
-#define S5P6450_GPC(_nr)	(S5P6450_GPIO_C_START + (_nr))
-#define S5P6450_GPD(_nr)	(S5P6450_GPIO_D_START + (_nr))
-#define S5P6450_GPF(_nr)	(S5P6450_GPIO_F_START + (_nr))
-#define S5P6450_GPG(_nr)	(S5P6450_GPIO_G_START + (_nr))
-#define S5P6450_GPH(_nr)	(S5P6450_GPIO_H_START + (_nr))
-#define S5P6450_GPI(_nr)	(S5P6450_GPIO_I_START + (_nr))
-#define S5P6450_GPJ(_nr)	(S5P6450_GPIO_J_START + (_nr))
-#define S5P6450_GPK(_nr)	(S5P6450_GPIO_K_START + (_nr))
-#define S5P6450_GPN(_nr)	(S5P6450_GPIO_N_START + (_nr))
-#define S5P6450_GPP(_nr)	(S5P6450_GPIO_P_START + (_nr))
-#define S5P6450_GPQ(_nr)	(S5P6450_GPIO_Q_START + (_nr))
-#define S5P6450_GPR(_nr)	(S5P6450_GPIO_R_START + (_nr))
-#define S5P6450_GPS(_nr)	(S5P6450_GPIO_S_START + (_nr))
-
-/* the end of the S5P64X0 specific gpios */
-
-#define S5P6440_GPIO_END	(S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
-#define S5P6450_GPIO_END	(S5P6450_GPS(S5P6450_GPIO_S_NR) + 1)
-
-#define S5P64X0_GPIO_END	(S5P6440_GPIO_END > S5P6450_GPIO_END ?	\
-				 S5P6440_GPIO_END : S5P6450_GPIO_END)
-
-#define S3C_GPIO_END		S5P64X0_GPIO_END
-
-/* define the number of gpios we need to the one after the last GPIO range */
-
-#define ARCH_NR_GPIOS		(S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Hardware support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,148 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h
- *
- * Copyright 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0 */
-
-#define IRQ_EINT0_3		S5P_IRQ_VIC0(0)
-#define IRQ_EINT4_11		S5P_IRQ_VIC0(1)
-#define IRQ_RTC_TIC		S5P_IRQ_VIC0(2)
-#define IRQ_IIS1		S5P_IRQ_VIC0(3)	/* for only S5P6450 */
-#define IRQ_IIS2		S5P_IRQ_VIC0(4)	/* for only S5P6450 */
-#define IRQ_IIC1		S5P_IRQ_VIC0(5)
-#define IRQ_I2SV40		S5P_IRQ_VIC0(6)
-#define IRQ_GPS			S5P_IRQ_VIC0(7)	/* for only S5P6450 */
-
-#define IRQ_2D			S5P_IRQ_VIC0(11)
-#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(23)
-#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(24)
-#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(25)
-#define IRQ_WDT			S5P_IRQ_VIC0(26)
-#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(27)
-#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(28)
-#define IRQ_DISPCON0		S5P_IRQ_VIC0(29)
-#define IRQ_DISPCON1		S5P_IRQ_VIC0(30)
-#define IRQ_DISPCON2		S5P_IRQ_VIC0(31)
-
-/* VIC1 */
-
-#define IRQ_EINT12_15		S5P_IRQ_VIC1(0)
-#define IRQ_PCM0		S5P_IRQ_VIC1(2)
-#define IRQ_PCM1		S5P_IRQ_VIC1(3)	/* for only S5P6450 */
-#define IRQ_PCM2		S5P_IRQ_VIC1(4)	/* for only S5P6450 */
-#define IRQ_UART0		S5P_IRQ_VIC1(5)
-#define IRQ_UART1		S5P_IRQ_VIC1(6)
-#define IRQ_UART2		S5P_IRQ_VIC1(7)
-#define IRQ_UART3		S5P_IRQ_VIC1(8)
-#define IRQ_DMA0		S5P_IRQ_VIC1(9)
-#define IRQ_UART4		S5P_IRQ_VIC1(10)	/* S5P6450 */
-#define IRQ_UART5		S5P_IRQ_VIC1(11)	/* S5P6450 */
-#define IRQ_NFC			S5P_IRQ_VIC1(13)
-#define IRQ_USI			S5P_IRQ_VIC1(15)	/* S5P6450 */
-#define IRQ_SPI0		S5P_IRQ_VIC1(16)
-#define IRQ_SPI1		S5P_IRQ_VIC1(17)
-#define IRQ_HSMMC2		S5P_IRQ_VIC1(17)	/* Shared */
-#define IRQ_IIC			S5P_IRQ_VIC1(18)
-#define IRQ_DISPCON3		S5P_IRQ_VIC1(19)
-#define IRQ_EINT_GROUPS		S5P_IRQ_VIC1(21)
-#define IRQ_PMU			S5P_IRQ_VIC1(23)	/* S5P6440 */
-#define IRQ_HSMMC0		S5P_IRQ_VIC1(24)
-#define IRQ_HSMMC1		S5P_IRQ_VIC1(25)
-#define IRQ_OTG			S5P_IRQ_VIC1(26)
-#define IRQ_DSI			S5P_IRQ_VIC1(27)
-#define IRQ_RTC_ALARM		S5P_IRQ_VIC1(28)
-#define IRQ_TSI			S5P_IRQ_VIC1(29)
-#define IRQ_PENDN		S5P_IRQ_VIC1(30)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_ADC			S5P_IRQ_VIC1(31)
-
-/* UART interrupts, S5P6450 has 5 UARTs */
-#define IRQ_S5P_UART_BASE4	(96)
-#define IRQ_S5P_UART_BASE5	(100)
-
-#define IRQ_S5P_UART_RX4	(IRQ_S5P_UART_BASE4 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX4	(IRQ_S5P_UART_BASE4 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR4	(IRQ_S5P_UART_BASE4 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX5	(IRQ_S5P_UART_BASE5 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX5	(IRQ_S5P_UART_BASE5 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR5	(IRQ_S5P_UART_BASE5 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX4		IRQ_S5P_UART_RX4
-#define IRQ_S3CUART_RX5		IRQ_S5P_UART_RX5
-
-#define IRQ_I2S0		IRQ_I2SV40
-
-#define IRQ_LCD_FIFO		IRQ_DISPCON0
-#define IRQ_LCD_VSYNC		IRQ_DISPCON1
-#define IRQ_LCD_SYSTEM		IRQ_DISPCON2
-
-/* S5P6450 EINT feature will be added */
-
-/*
- * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
- * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
- * after the pair of VICs.
- */
-
-#define S5P_IRQ_EINT_BASE	(S5P_IRQ_VIC1(31) + 6)
-
-#define S5P_EINT(x)		((x) + S5P_IRQ_EINT_BASE)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE)
-/*
- * S5P6440 has 0-15 external interrupts in group 0. Only these can be used
- * to wake up from sleep. If request is beyond this range, by mistake, a large
- * return value for an irq number should be indication of something amiss.
- */
-#define S5P_EINT_BASE2		(0xf0000000)
-
-/*
- * Next the external interrupt groups. These are similar to the IRQ_EINT(x)
- * that they are sourced from the GPIO pins but with a different scheme for
- * priority and source indication.
- *
- * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
- * interrupts, but for historical reasons they are kept apart from these
- * next interrupts.
- *
- * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
- * machine specific support files.
- */
-
-/* Actually, #6 and #7 are missing in the EINT_GROUP1 */
-#define IRQ_EINT_GROUP1_NR	(15)
-#define IRQ_EINT_GROUP2_NR	(8)
-#define IRQ_EINT_GROUP5_NR	(7)
-#define IRQ_EINT_GROUP6_NR	(10)
-/* Actually, #0, #1 and #2 are missing in the EINT_GROUP8 */
-#define IRQ_EINT_GROUP8_NR	(11)
-
-#define IRQ_EINT_GROUP_BASE	S5P_EINT(16)
-#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0)
-#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
-#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
-#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
-#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
-
-#define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/map.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/map.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/map.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/map.h
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5P64X0_PA_SDRAM	0x20000000
-
-#define S5P64X0_PA_CHIPID	0xE0000000
-
-#define S5P64X0_PA_SYSCON	0xE0100000
-
-#define S5P64X0_PA_GPIO		0xE0308000
-
-#define S5P64X0_PA_VIC0		0xE4000000
-#define S5P64X0_PA_VIC1		0xE4100000
-
-#define S5P64X0_PA_SROMC	0xE7000000
-
-#define S5P64X0_PA_PDMA		0xE9000000
-
-#define S5P64X0_PA_TIMER	0xEA000000
-#define S5P64X0_PA_RTC		0xEA100000
-#define S5P64X0_PA_WDT		0xEA200000
-
-#define S5P6440_PA_IIC0		0xEC104000
-#define S5P6440_PA_IIC1		0xEC20F000
-#define S5P6450_PA_IIC0		0xEC100000
-#define S5P6450_PA_IIC1		0xEC200000
-
-#define S5P64X0_PA_SPI0		0xEC400000
-#define S5P64X0_PA_SPI1		0xEC500000
-
-#define S5P64X0_PA_HSOTG	0xED100000
-
-#define S5P64X0_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
-
-#define S5P64X0_PA_FB		0xEE000000
-
-#define S5P64X0_PA_I2S		0xF2000000
-#define S5P6450_PA_I2S1		0xF2800000
-#define S5P6450_PA_I2S2		0xF2900000
-
-#define S5P64X0_PA_PCM		0xF2100000
-
-#define S5P64X0_PA_ADC		0xF3000000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_HSMMC0		S5P64X0_PA_HSMMC(0)
-#define S3C_PA_HSMMC1		S5P64X0_PA_HSMMC(1)
-#define S3C_PA_HSMMC2		S5P64X0_PA_HSMMC(2)
-#define S3C_PA_IIC		S5P6440_PA_IIC0
-#define S3C_PA_IIC1		S5P6440_PA_IIC1
-#define S3C_PA_RTC		S5P64X0_PA_RTC
-#define S3C_PA_WDT		S5P64X0_PA_WDT
-#define S3C_PA_FB		S5P64X0_PA_FB
-#define S3C_PA_SPI0		S5P64X0_PA_SPI0
-#define S3C_PA_SPI1		S5P64X0_PA_SPI1
-
-#define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
-#define S5P_PA_SROMC		S5P64X0_PA_SROMC
-#define S5P_PA_SYSCON		S5P64X0_PA_SYSCON
-#define S5P_PA_TIMER		S5P64X0_PA_TIMER
-
-#define SAMSUNG_PA_ADC		S5P64X0_PA_ADC
-#define SAMSUNG_PA_TIMER	S5P64X0_PA_TIMER
-
-/* UART */
-
-#define S5P6440_PA_UART(x)	(0xEC000000 + ((x) * S3C_UART_OFFSET))
-#define S5P6450_PA_UART(x)	((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
-
-#define S5P_PA_UART0		S5P6450_PA_UART(0)
-#define S5P_PA_UART1		S5P6450_PA_UART(1)
-#define S5P_PA_UART2		S5P6450_PA_UART(2)
-#define S5P_PA_UART3		S5P6450_PA_UART(3)
-#define S5P_PA_UART4		S5P6450_PA_UART(4)
-#define S5P_PA_UART5		S5P6450_PA_UART(5)
-
-#define S5P_SZ_UART		SZ_256
-#define S3C_VA_UARTx(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
- *
- * Based on PM core support for S3C64XX by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/serial_s3c.h>
-
-#include <mach/regs-gpio.h>
-
-static inline void s3c_pm_debug_init_uart(void)
-{
-	u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
-
-	/*
-	 * As a note, since the S5P64X0 UARTs generally have multiple
-	 * clock sources, we simply enable PCLK at the moment and hope
-	 * that the resume settings for the UART are suitable for the
-	 * use with PCLK.
-	 */
-	tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
-	tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
-	tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
-	tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
-
-	__raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
-	udelay(10);
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
-	/* VIC should have already been taken care of */
-
-	/* clear any pending EINT0 interrupts */
-	__raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void) { }
-static inline void s3c_pm_arch_show_resume_irqs(void) { }
-
-/*
- * make these defines, we currently do not have any need to change
- * the IRQ wake controls depending on the CPU we are running on
- */
-#define s3c_irqwake_eintallow	((1 << 16) - 1)
-#define s3c_irqwake_intallow	(~0)
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-					struct pm_uart_save *save)
-{
-	u32 ucon = __raw_readl(regs + S3C2410_UCON);
-	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
-	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
-	u32 new_ucon;
-	u32 delta;
-
-	/*
-	 * S5P64X0 UART blocks only support level interrupts, so ensure that
-	 * when we restore unused UART blocks we force the level interrupt
-	 * settings.
-	 */
-	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
-
-	/*
-	 * We have a constraint on changing the clock type of the UART
-	 * between UCLKx and PCLK, so ensure that when we restore UCON
-	 * that the CLK field is correctly modified if the bootloader
-	 * has changed anything.
-	 */
-	if (ucon_clk != save_clk) {
-		new_ucon = save->ucon;
-		delta = ucon_clk ^ save_clk;
-
-		/*
-		 * change from UCLKx => wrong PCLK,
-		 * either UCLK can be tested for by a bit-test
-		 * with UCLK0
-		 */
-		if (ucon_clk & S3C6400_UCON_UCLK0 &&
-		!(save_clk & S3C6400_UCON_UCLK0) &&
-		delta & S3C6400_UCON_PCLK2) {
-			new_ucon &= ~S3C6400_UCON_UCLK0;
-		} else if (delta == S3C6400_UCON_PCLK2) {
-			/*
-			 * as a precaution, don't change from
-			 * PCLK2 => PCLK or vice-versa
-			 */
-			new_ucon ^= S3C6400_UCON_PCLK2;
-		}
-
-		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
-			ucon, new_ucon, save->ucon);
-		save->ucon = new_ucon;
-	}
-}
-
-static inline void s3c_pm_restored_gpios(void)
-{
-	/* ensure sleep mode has been cleared from the system */
-	__raw_writel(0, S5P64X0_SLPEN);
-}
-
-static inline void samsung_pm_saved_gpios(void)
-{
-	/*
-	 * turn on the sleep mode and keep it there, as it seems that during
-	 * suspend the xCON registers get re-set and thus you can end up with
-	 * problems between going to sleep and resuming.
-	 */
-	__raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)			(S3C_VA_SYS + (x))
-
-#define S5P64X0_APLL_CON		S5P_CLKREG(0x0C)
-#define S5P64X0_MPLL_CON		S5P_CLKREG(0x10)
-#define S5P64X0_EPLL_CON		S5P_CLKREG(0x14)
-#define S5P64X0_EPLL_CON_K		S5P_CLKREG(0x18)
-
-#define S5P64X0_CLK_SRC0		S5P_CLKREG(0x1C)
-
-#define S5P64X0_CLK_DIV0		S5P_CLKREG(0x20)
-#define S5P64X0_CLK_DIV1		S5P_CLKREG(0x24)
-#define S5P64X0_CLK_DIV2		S5P_CLKREG(0x28)
-
-#define S5P64X0_CLK_GATE_HCLK0		S5P_CLKREG(0x30)
-#define S5P64X0_CLK_GATE_PCLK		S5P_CLKREG(0x34)
-#define S5P64X0_CLK_GATE_SCLK0		S5P_CLKREG(0x38)
-#define S5P64X0_CLK_GATE_MEM0		S5P_CLKREG(0x3C)
-
-#define S5P64X0_CLK_DIV3		S5P_CLKREG(0x40)
-
-#define S5P64X0_CLK_GATE_HCLK1		S5P_CLKREG(0x44)
-#define S5P64X0_CLK_GATE_SCLK1		S5P_CLKREG(0x48)
-
-#define S5P6450_DPLL_CON		S5P_CLKREG(0x50)
-#define S5P6450_DPLL_CON_K		S5P_CLKREG(0x54)
-
-#define S5P64X0_AHB_CON0		S5P_CLKREG(0x100)
-#define S5P64X0_CLK_SRC1		S5P_CLKREG(0x10C)
-
-#define S5P64X0_SYS_ID			S5P_CLKREG(0x118)
-#define S5P64X0_SYS_OTHERS		S5P_CLKREG(0x11C)
-
-#define S5P64X0_PWR_CFG			S5P_CLKREG(0x804)
-#define S5P64X0_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
-#define S5P64X0_SLEEP_CFG		S5P_CLKREG(0x818)
-#define S5P64X0_PWR_STABLE		S5P_CLKREG(0x828)
-
-#define S5P64X0_OTHERS			S5P_CLKREG(0x900)
-#define S5P64X0_WAKEUP_STAT		S5P_CLKREG(0x908)
-
-#define S5P64X0_INFORM0			S5P_CLKREG(0xA00)
-
-#define S5P64X0_CLKDIV0_HCLK_SHIFT	(8)
-#define S5P64X0_CLKDIV0_HCLK_MASK	(0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
-
-/* HCLK GATE Registers */
-#define S5P64X0_CLK_GATE_HCLK1_FIMGVG	(1 << 2)
-#define S5P64X0_CLK_GATE_SCLK1_FIMGVG	(1 << 2)
-
-/* PCLK GATE Registers */
-#define S5P64X0_CLK_GATE_PCLK_UART3	(1 << 4)
-#define S5P64X0_CLK_GATE_PCLK_UART2	(1 << 3)
-#define S5P64X0_CLK_GATE_PCLK_UART1	(1 << 2)
-#define S5P64X0_CLK_GATE_PCLK_UART0	(1 << 1)
-
-#define S5P64X0_PWR_CFG_MMC1_DISABLE		(1 << 15)
-#define S5P64X0_PWR_CFG_MMC0_DISABLE		(1 << 14)
-#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE	(1 << 11)
-#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE	(1 << 10)
-#define S5P64X0_PWR_CFG_WFI_MASK		(3 << 5)
-#define S5P64X0_PWR_CFG_WFI_SLEEP		(3 << 5)
-
-#define S5P64X0_SLEEP_CFG_OSC_EN	(1 << 0)
-
-#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4	(4 << 0)
-
-#define S5P6450_OTHERS_DISABLE_INT	(1 << 31)
-#define S5P64X0_OTHERS_RET_UART		(1 << 26)
-#define S5P64X0_OTHERS_RET_MMC1		(1 << 25)
-#define S5P64X0_OTHERS_RET_MMC0		(1 << 24)
-#define S5P64X0_OTHERS_USB_SIG_MASK	(1 << 16)
-
-/* Compatibility defines */
-
-#define ARM_CLK_DIV			S5P64X0_CLK_DIV0
-#define ARM_DIV_RATIO_SHIFT		0
-#define ARM_DIV_MASK			(0xF << ARM_DIV_RATIO_SHIFT)
-
-#define S5P_EPLL_CON			S5P64X0_EPLL_CON
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - GPIO register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-/* Base addresses for each of the banks */
-
-#define S5P64X0_GPA_BASE		(S5P_VA_GPIO + 0x0000)
-#define S5P64X0_GPB_BASE		(S5P_VA_GPIO + 0x0020)
-#define S5P64X0_GPC_BASE		(S5P_VA_GPIO + 0x0040)
-#define S5P64X0_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
-#define S5P64X0_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
-#define S5P64X0_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
-#define S5P64X0_GPI_BASE		(S5P_VA_GPIO + 0x0100)
-#define S5P64X0_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
-#define S5P64X0_GPN_BASE		(S5P_VA_GPIO + 0x0830)
-#define S5P64X0_GPP_BASE		(S5P_VA_GPIO + 0x0160)
-#define S5P64X0_GPR_BASE		(S5P_VA_GPIO + 0x0290)
-
-#define S5P6450_GPD_BASE		(S5P_VA_GPIO + 0x0060)
-#define S5P6450_GPK_BASE		(S5P_VA_GPIO + 0x0140)
-#define S5P6450_GPQ_BASE		(S5P_VA_GPIO + 0x0180)
-#define S5P6450_GPS_BASE		(S5P_VA_GPIO + 0x0300)
-
-#define S5P64X0_SPCON0			(S5P_VA_GPIO + 0x1A0)
-#define S5P64X0_SPCON0_LCD_SEL_MASK	(0x3 << 0)
-#define S5P64X0_SPCON0_LCD_SEL_RGB	(0x1 << 0)
-#define S5P64X0_SPCON1			(S5P_VA_GPIO + 0x2B0)
-
-#define S5P64X0_MEM0CONSLP0		(S5P_VA_GPIO + 0x1C0)
-#define S5P64X0_MEM0CONSLP1		(S5P_VA_GPIO + 0x1C4)
-#define S5P64X0_MEM0DRVCON		(S5P_VA_GPIO + 0x1D0)
-#define S5P64X0_MEM1DRVCON		(S5P_VA_GPIO + 0x1D4)
-
-#define S5P64X0_EINT12CON		(S5P_VA_GPIO + 0x200)
-#define S5P64X0_EINT12FLTCON		(S5P_VA_GPIO + 0x220)
-#define S5P64X0_EINT12MASK		(S5P_VA_GPIO + 0x240)
-
-/* External interrupt control registers for group0 */
-
-#define EINT0CON0_OFFSET		(0x900)
-#define EINT0FLTCON0_OFFSET		(0x910)
-#define EINT0FLTCON1_OFFSET		(0x914)
-#define EINT0MASK_OFFSET		(0x920)
-#define EINT0PEND_OFFSET		(0x924)
-
-#define S5P64X0_EINT0CON0		(S5P_VA_GPIO + EINT0CON0_OFFSET)
-#define S5P64X0_EINT0FLTCON0		(S5P_VA_GPIO + EINT0FLTCON0_OFFSET)
-#define S5P64X0_EINT0FLTCON1		(S5P_VA_GPIO + EINT0FLTCON1_OFFSET)
-#define S5P64X0_EINT0MASK		(S5P_VA_GPIO + EINT0MASK_OFFSET)
-#define S5P64X0_EINT0PEND		(S5P_VA_GPIO + EINT0PEND_OFFSET)
-
-#define S5P64X0_SLPEN			(S5P_VA_GPIO + 0x930)
-#define S5P64X0_SLPEN_USE_xSLP		(1 << 0)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-irq.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/include/mach/regs-irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/irq-pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/irq-pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/irq-pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/irq-pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/irq-pm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - Interrupt handling Power Management
- *
- * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/syscore_ops.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/io.h>
-
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S5P64X0_EINT0CON0),
-	SAVE_ITEM(S5P64X0_EINT0FLTCON0),
-	SAVE_ITEM(S5P64X0_EINT0FLTCON1),
-	SAVE_ITEM(S5P64X0_EINT0MASK),
-};
-
-static struct irq_grp_save {
-	u32	con;
-	u32	fltcon;
-	u32	mask;
-} eint_grp_save[4];
-
-#ifdef CONFIG_SERIAL_SAMSUNG
-static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
-#endif
-
-static int s5p64x0_irq_pm_suspend(void)
-{
-	struct irq_grp_save *grp = eint_grp_save;
-	int i;
-
-	S3C_PMDBG("%s: suspending IRQs\n", __func__);
-
-	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-
-#ifdef CONFIG_SERIAL_SAMSUNG
-	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
-		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
-#endif
-
-	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
-		grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
-		grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
-		grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
-	}
-
-	return 0;
-}
-
-static void s5p64x0_irq_pm_resume(void)
-{
-	struct irq_grp_save *grp = eint_grp_save;
-	int i;
-
-	S3C_PMDBG("%s: resuming IRQs\n", __func__);
-
-	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-
-#ifdef CONFIG_SERIAL_SAMSUNG
-	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
-		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
-#endif
-
-	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
-		__raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
-		__raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
-		__raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
-	}
-
-	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
-}
-
-static struct syscore_ops s5p64x0_irq_syscore_ops = {
-	.suspend = s5p64x0_irq_pm_suspend,
-	.resume  = s5p64x0_irq_pm_resume,
-};
-
-static int __init s5p64x0_syscore_init(void)
-{
-	register_syscore_ops(&s5p64x0_irq_syscore_ops);
-
-	return 0;
-}
-core_initcall(s5p64x0_syscore_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-# arch/arm/mach-s5p64x0/Kconfig
-#
-# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-if ARCH_S5P64X0
-
-config CPU_S5P6440
-	bool
-	select ARM_AMBA
-	select PL330_DMA if DMADEVICES
-	select S5P_SLEEP if PM
-	select SAMSUNG_WAKEMASK if PM
-	help
-	  Enable S5P6440 CPU support
-
-config CPU_S5P6450
-	bool
-	select ARM_AMBA
-	select PL330_DMA if DMADEVICES
-	select S5P_SLEEP if PM
-	select SAMSUNG_WAKEMASK if PM
-	help
-	  Enable S5P6450 CPU support
-
-config S5P64X0_SETUP_FB_24BPP
-	bool
-	help
-	  Common setup code for S5P64X0 based boards with a LCD display
-	  through RGB interface.
-
-config S5P64X0_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S5P64X0_SETUP_SPI
-	bool
-	help
-	  Common setup code for SPI GPIO configurations
-
-config S5P64X0_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-# machine support
-
-config MACH_SMDK6440
-	bool "SMDK6440"
-	select CPU_S5P6440
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_I2C1
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S5P64X0_SETUP_FB_24BPP
-	select S5P64X0_SETUP_I2C1
-	select S5P64X0_SETUP_SDHCI_GPIO
-	select SAMSUNG_DEV_ADC
-	select SAMSUNG_DEV_BACKLIGHT
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_TS
-	help
-	  Machine support for the Samsung SMDK6440
-
-config MACH_SMDK6450
-	bool "SMDK6450"
-	select CPU_S5P6450
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_I2C1
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S5P64X0_SETUP_FB_24BPP
-	select S5P64X0_SETUP_I2C1
-	select S5P64X0_SETUP_SDHCI_GPIO
-	select SAMSUNG_DEV_ADC
-	select SAMSUNG_DEV_BACKLIGHT
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_TS
-	help
-	  Machine support for the Samsung SMDK6450
-
-menu "Use 8-bit SDHCI bus width"
-
-config S5P64X0_SD_CH1_8BIT
-	bool "SDHCI Channel 1 (Slot 1)"
-	depends on MACH_SMDK6450 || MACH_SMDK6440
-	help
-	  Support SDHCI Channel 1 8-bit bus.
-	  If selected, Channel 2 is disabled.
-
-endmenu
-
-endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,280 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/pwm_backlight.h>
-#include <linux/fb.h>
-#include <linux/mmc/host.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pll.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-
-#include "common.h"
-#include "i2c.h"
-
-#define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				S3C2410_UCON_RXILEVEL |		\
-				S3C2410_UCON_TXIRQMODE |	\
-				S3C2410_UCON_RXIRQMODE |	\
-				S3C2410_UCON_RXFIFO_TOI |	\
-				S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDK6440_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDK6440_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				S3C2440_UFCON_TXTRIG16 |	\
-				S3C2410_UFCON_RXTRIG8)
-
-static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDK6440_UCON_DEFAULT,
-		.ulcon		= SMDK6440_ULCON_DEFAULT,
-		.ufcon		= SMDK6440_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDK6440_UCON_DEFAULT,
-		.ulcon		= SMDK6440_ULCON_DEFAULT,
-		.ufcon		= SMDK6440_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDK6440_UCON_DEFAULT,
-		.ulcon		= SMDK6440_ULCON_DEFAULT,
-		.ufcon		= SMDK6440_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDK6440_UCON_DEFAULT,
-		.ulcon		= SMDK6440_ULCON_DEFAULT,
-		.ufcon		= SMDK6440_UFCON_DEFAULT,
-	},
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdk6440_fb_win0 = {
-	.max_bpp	= 32,
-	.default_bpp	= 24,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct fb_videomode smdk6440_lcd_timing = {
-	.left_margin	= 8,
-	.right_margin	= 13,
-	.upper_margin	= 7,
-	.lower_margin	= 5,
-	.hsync_len	= 3,
-	.vsync_len	= 1,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
-	.win[0]		= &smdk6440_fb_win0,
-	.vtiming	= &smdk6440_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
-};
-
-/* LCD power controller */
-static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
-					 unsigned int power)
-{
-	int err;
-
-	if (power) {
-		err = gpio_request(S5P6440_GPN(5), "GPN");
-		if (err) {
-			printk(KERN_ERR "failed to request GPN for lcd reset\n");
-			return;
-		}
-
-		gpio_direction_output(S5P6440_GPN(5), 1);
-		gpio_set_value(S5P6440_GPN(5), 0);
-		gpio_set_value(S5P6440_GPN(5), 1);
-		gpio_free(S5P6440_GPN(5));
-	}
-}
-
-static struct plat_lcd_data smdk6440_lcd_power_data = {
-	.set_power	= smdk6440_lte480_reset_power,
-};
-
-static struct platform_device smdk6440_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &smdk6440_lcd_power_data,
-};
-
-static struct platform_device *smdk6440_devices[] __initdata = {
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&samsung_device_pwm,
-	&s3c_device_ts,
-	&s3c_device_wdt,
-	&s5p6440_device_iis,
-	&s3c_device_fb,
-	&smdk6440_lcd_lte480wv,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc0_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc1_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_INTERNAL,
-#if defined(CONFIG_S5P64X0_SD_CH1_8BIT)
-	.max_width	= 8,
-	.host_caps	= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc2_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
-	.flags		= 0,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-	.cfg_gpio	= s5p6440_i2c0_cfg_gpio,
-};
-
-static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = {
-	.flags		= 0,
-	.bus_num	= 1,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-	.cfg_gpio	= s5p6440_i2c1_cfg_gpio,
-};
-
-static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("24c08", 0x50), },
-	{ I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
-	/* To be populated */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
-	.no = S5P6440_GPF(15),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdk6440_bl_data = {
-	.pwm_id = 1,
-	.enable_gpio = -1,
-};
-
-static void __init smdk6440_map_io(void)
-{
-	s5p64x0_init_io(NULL, 0);
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void s5p6440_set_lcd_interface(void)
-{
-	unsigned int cfg;
-
-	/* select TFT LCD type (RGB I/F) */
-	cfg = __raw_readl(S5P64X0_SPCON0);
-	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
-	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
-	__raw_writel(cfg, S5P64X0_SPCON0);
-}
-
-static void __init smdk6440_machine_init(void)
-{
-	s3c24xx_ts_set_platdata(NULL);
-
-	s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
-	s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
-	i2c_register_board_info(0, smdk6440_i2c_devs0,
-			ARRAY_SIZE(smdk6440_i2c_devs0));
-	i2c_register_board_info(1, smdk6440_i2c_devs1,
-			ARRAY_SIZE(smdk6440_i2c_devs1));
-
-	s5p6440_set_lcd_interface();
-	s3c_fb_set_platdata(&smdk6440_lcd_pdata);
-
-	s3c_sdhci0_set_platdata(&smdk6440_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdk6440_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdk6440_hsmmc2_pdata);
-
-	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
-
-	samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
-}
-
-MACHINE_START(SMDK6440, "SMDK6440")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.atag_offset	= 0x100,
-
-	.init_irq	= s5p6440_init_irq,
-	.map_io		= smdk6440_map_io,
-	.init_machine	= smdk6440_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5p64x0_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,299 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/pwm_backlight.h>
-#include <linux/fb.h>
-#include <linux/mmc/host.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pll.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-
-#include "common.h"
-#include "i2c.h"
-
-#define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				S3C2410_UCON_RXILEVEL |		\
-				S3C2410_UCON_TXIRQMODE |	\
-				S3C2410_UCON_RXIRQMODE |	\
-				S3C2410_UCON_RXFIFO_TOI |	\
-				S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDK6450_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDK6450_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				S3C2440_UFCON_TXTRIG16 |	\
-				S3C2410_UFCON_RXTRIG8)
-
-static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
-	[4] = {
-		.hwport		= 4,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-#endif
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
-	[5] = {
-		.hwport		= 5,
-		.flags		= 0,
-		.ucon		= SMDK6450_UCON_DEFAULT,
-		.ulcon		= SMDK6450_ULCON_DEFAULT,
-		.ufcon		= SMDK6450_UFCON_DEFAULT,
-	},
-#endif
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdk6450_fb_win0 = {
-	.max_bpp	= 32,
-	.default_bpp	= 24,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct fb_videomode smdk6450_lcd_timing = {
-	.left_margin	= 8,
-	.right_margin	= 13,
-	.upper_margin	= 7,
-	.lower_margin	= 5,
-	.hsync_len	= 3,
-	.vsync_len	= 1,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
-	.win[0]		= &smdk6450_fb_win0,
-	.vtiming	= &smdk6450_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
-};
-
-/* LCD power controller */
-static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
-					 unsigned int power)
-{
-	int err;
-
-	if (power) {
-		err = gpio_request(S5P6450_GPN(5), "GPN");
-		if (err) {
-			printk(KERN_ERR "failed to request GPN for lcd reset\n");
-			return;
-		}
-
-		gpio_direction_output(S5P6450_GPN(5), 1);
-		gpio_set_value(S5P6450_GPN(5), 0);
-		gpio_set_value(S5P6450_GPN(5), 1);
-		gpio_free(S5P6450_GPN(5));
-	}
-}
-
-static struct plat_lcd_data smdk6450_lcd_power_data = {
-	.set_power	= smdk6450_lte480_reset_power,
-};
-
-static struct platform_device smdk6450_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &smdk6450_lcd_power_data,
-};
-
-static struct platform_device *smdk6450_devices[] __initdata = {
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&samsung_device_pwm,
-	&s3c_device_ts,
-	&s3c_device_wdt,
-	&s5p6450_device_iis0,
-	&s3c_device_fb,
-	&smdk6450_lcd_lte480wv,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	/* s5p6450_device_spi0 will be added */
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc0_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc1_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_NONE,
-#if defined(CONFIG_S5P64X0_SD_CH1_8BIT)
-	.max_width	= 8,
-	.host_caps	= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc2_pdata __initdata = {
-	.cd_type	= S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = {
-	.flags		= 0,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-	.cfg_gpio	= s5p6450_i2c0_cfg_gpio,
-};
-
-static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = {
-	.flags		= 0,
-	.bus_num	= 1,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-	.cfg_gpio	= s5p6450_i2c1_cfg_gpio,
-};
-
-static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("wm8580", 0x1b), },
-	{ I2C_BOARD_INFO("24c08", 0x50), },	/* Samsung KS24C080C EEPROM */
-};
-
-static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
-	{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
-	.no = S5P6450_GPF(15),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdk6450_bl_data = {
-	.pwm_id = 1,
-	.enable_gpio = -1,
-};
-
-static void __init smdk6450_map_io(void)
-{
-	s5p64x0_init_io(NULL, 0);
-	s3c24xx_init_clocks(19200000);
-	s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void s5p6450_set_lcd_interface(void)
-{
-	unsigned int cfg;
-
-	/* select TFT LCD type (RGB I/F) */
-	cfg = __raw_readl(S5P64X0_SPCON0);
-	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
-	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
-	__raw_writel(cfg, S5P64X0_SPCON0);
-}
-
-static void __init smdk6450_machine_init(void)
-{
-	s3c24xx_ts_set_platdata(NULL);
-
-	s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
-	s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
-	i2c_register_board_info(0, smdk6450_i2c_devs0,
-			ARRAY_SIZE(smdk6450_i2c_devs0));
-	i2c_register_board_info(1, smdk6450_i2c_devs1,
-			ARRAY_SIZE(smdk6450_i2c_devs1));
-
-	s5p6450_set_lcd_interface();
-	s3c_fb_set_platdata(&smdk6450_lcd_pdata);
-
-	s3c_sdhci0_set_platdata(&smdk6450_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdk6450_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdk6450_hsmmc2_pdata);
-
-	platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
-
-	samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
-}
-
-MACHINE_START(SMDK6450, "SMDK6450")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.atag_offset	= 0x100,
-
-	.init_irq	= s5p6450_init_irq,
-	.map_io		= smdk6450_map_io,
-	.init_machine	= smdk6450_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5p64x0_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-# arch/arm/mach-s5p64x0/Makefile
-#
-# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-# 		http://www.samsung.com
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core
-
-obj-y				+= common.o clock.o
-obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o
-obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
-
-obj-$(CONFIG_PM)		+= pm.o irq-pm.o
-
-obj-y				+= dma.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDK6440)	+= mach-smdk6440.o
-obj-$(CONFIG_MACH_SMDK6450)	+= mach-smdk6450.o
-
-# device support
-
-obj-y				+= dev-audio.o
-
-obj-y					+= setup-i2c0.o
-obj-$(CONFIG_S5P64X0_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
-obj-$(CONFIG_S5P64X0_SETUP_SPI)		+= setup-spi.o
-obj-$(CONFIG_S5P64X0_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Makefile.boot linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Makefile.boot
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/Makefile.boot	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-   zreladdr-y	+= 0x20008000
-params_phys-y	:= 0x20000100
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/pm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 Power Management Support
- *
- * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/suspend.h>
-#include <linux/syscore_ops.h>
-#include <linux/io.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/wakeup-mask.h>
-
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-static struct sleep_save s5p64x0_core_save[] = {
-	SAVE_ITEM(S5P64X0_APLL_CON),
-	SAVE_ITEM(S5P64X0_MPLL_CON),
-	SAVE_ITEM(S5P64X0_EPLL_CON),
-	SAVE_ITEM(S5P64X0_EPLL_CON_K),
-	SAVE_ITEM(S5P64X0_CLK_SRC0),
-	SAVE_ITEM(S5P64X0_CLK_SRC1),
-	SAVE_ITEM(S5P64X0_CLK_DIV0),
-	SAVE_ITEM(S5P64X0_CLK_DIV1),
-	SAVE_ITEM(S5P64X0_CLK_DIV2),
-	SAVE_ITEM(S5P64X0_CLK_DIV3),
-	SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
-	SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
-	SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
-};
-
-static struct sleep_save s5p64x0_misc_save[] = {
-	SAVE_ITEM(S5P64X0_AHB_CON0),
-	SAVE_ITEM(S5P64X0_SPCON0),
-	SAVE_ITEM(S5P64X0_SPCON1),
-	SAVE_ITEM(S5P64X0_MEM0CONSLP0),
-	SAVE_ITEM(S5P64X0_MEM0CONSLP1),
-	SAVE_ITEM(S5P64X0_MEM0DRVCON),
-	SAVE_ITEM(S5P64X0_MEM1DRVCON),
-};
-
-/* DPLL is present only in S5P6450 */
-static struct sleep_save s5p6450_core_save[] = {
-	SAVE_ITEM(S5P6450_DPLL_CON),
-	SAVE_ITEM(S5P6450_DPLL_CON_K),
-};
-
-void s3c_pm_configure_extint(void)
-{
-	__raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
-}
-
-void s3c_pm_restore_core(void)
-{
-	__raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
-
-	s3c_pm_do_restore_core(s5p64x0_core_save,
-				ARRAY_SIZE(s5p64x0_core_save));
-
-	if (soc_is_s5p6450())
-		s3c_pm_do_restore_core(s5p6450_core_save,
-				ARRAY_SIZE(s5p6450_core_save));
-
-	s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
-}
-
-void s3c_pm_save_core(void)
-{
-	s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
-
-	if (soc_is_s5p6450())
-		s3c_pm_do_save(s5p6450_core_save,
-				ARRAY_SIZE(s5p6450_core_save));
-
-	s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
-}
-
-static int s5p64x0_cpu_suspend(unsigned long arg)
-{
-	unsigned long tmp = 0;
-
-	/*
-	 * Issue the standby signal into the pm unit. Note, we
-	 * issue a write-buffer drain just in case.
-	 */
-	asm("b 1f\n\t"
-	    ".align 5\n\t"
-	    "1:\n\t"
-	    "mcr p15, 0, %0, c7, c10, 5\n\t"
-	    "mcr p15, 0, %0, c7, c10, 4\n\t"
-	    "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
-
-	pr_info("Failed to suspend the system\n");
-	return 1; /* Aborting suspend */
-}
-
-/* mapping of interrupts to parts of the wakeup mask */
-static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
-	{ .irq = IRQ_RTC_ALARM,	.bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
-	{ .irq = IRQ_RTC_TIC,	.bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
-	{ .irq = IRQ_HSMMC0,	.bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
-	{ .irq = IRQ_HSMMC1,	.bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
-};
-
-static void s5p64x0_pm_prepare(void)
-{
-	u32 tmp;
-
-	samsung_sync_wakemask(S5P64X0_PWR_CFG,
-			s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
-
-	/* store the resume address in INFORM0 register */
-	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
-
-	/* setup clock gating for FIMGVG block */
-	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
-		(S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
-	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
-		(S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
-
-	/* Configure the stabilization counter with wait time required */
-	__raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
-
-	/* set WFI to SLEEP mode configuration */
-	tmp = __raw_readl(S5P64X0_SLEEP_CFG);
-	tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
-	__raw_writel(tmp, S5P64X0_SLEEP_CFG);
-
-	tmp = __raw_readl(S5P64X0_PWR_CFG);
-	tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
-	tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
-	__raw_writel(tmp, S5P64X0_PWR_CFG);
-
-	/*
-	 * set OTHERS register to disable interrupt before going to
-	 * sleep. This bit is present only in S5P6450, it is reserved
-	 * in S5P6440.
-	 */
-	if (soc_is_s5p6450()) {
-		tmp = __raw_readl(S5P64X0_OTHERS);
-		tmp |= S5P6450_OTHERS_DISABLE_INT;
-		__raw_writel(tmp, S5P64X0_OTHERS);
-	}
-
-	/* ensure previous wakeup state is cleared before sleeping */
-	__raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
-
-}
-
-static int s5p64x0_pm_add(struct device *dev, struct subsys_interface *sif)
-{
-	pm_cpu_prep = s5p64x0_pm_prepare;
-	pm_cpu_sleep = s5p64x0_cpu_suspend;
-
-	return 0;
-}
-
-static struct subsys_interface s5p64x0_pm_interface = {
-	.name		= "s5p64x0_pm",
-	.subsys		= &s5p64x0_subsys,
-	.add_dev	= s5p64x0_pm_add,
-};
-
-static __init int s5p64x0_pm_drvinit(void)
-{
-	s3c_pm_init();
-
-	return subsys_interface_register(&s5p64x0_pm_interface);
-}
-arch_initcall(s5p64x0_pm_drvinit);
-
-static void s5p64x0_pm_resume(void)
-{
-	u32 tmp;
-
-	tmp = __raw_readl(S5P64X0_OTHERS);
-	tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
-			S5P64X0_OTHERS_RET_UART);
-	__raw_writel(tmp , S5P64X0_OTHERS);
-}
-
-static struct syscore_ops s5p64x0_pm_syscore_ops = {
-	.resume		= s5p64x0_pm_resume,
-};
-
-static __init int s5p64x0_pm_syscore_init(void)
-{
-	register_syscore_ops(&s5p64x0_pm_syscore_ops);
-
-	return 0;
-}
-arch_initcall(s5p64x0_pm_syscore_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Base S5P64X0 GPIO setup information for LCD framebuffer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <plat/gpio-cfg.h>
-
-void s5p64x0_fb_gpio_setup_24bpp(void)
-{
-	if (soc_is_s5p6440()) {
-		s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
-		s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
-	} else if (soc_is_s5p6450()) {
-		s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
-		s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-i2c0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-i2c0.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-i2c0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64x0/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-
-#include "i2c.h"
-
-void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5P6440_GPB(5), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
-
-void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5P6450_GPB(5), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-i2c1.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-i2c1.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-i2c1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * I2C1 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-
-#include "i2c.h"
-
-void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5P6440_GPR(9), 2,
-			      S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
-}
-
-void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5P6450_GPR(9), 2,
-			      S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
-}
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P64X0 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-#include <plat/cpu.h>
-
-void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG pins to special-function 2 */
-	if (soc_is_s5p6450())
-		s3c_gpio_cfgrange_nopull(S5P6450_GPG(0), 2 + width,
-					 S3C_GPIO_SFN(2));
-	else
-		s3c_gpio_cfgrange_nopull(S5P6440_GPG(0), 2 + width,
-					 S3C_GPIO_SFN(2));
-
-	/* Set GPG[6] pin to special-function 2 - MMC0 CDn */
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		if (soc_is_s5p6450()) {
-			s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP);
-			s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(2));
-		} else {
-			s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP);
-			s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(2));
-		}
-	}
-}
-
-void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set GPH[0:1] pins to special-function 2 - CLK and CMD */
-	if (soc_is_s5p6450())
-		s3c_gpio_cfgrange_nopull(S5P6450_GPH(0), 2, S3C_GPIO_SFN(2));
-	else
-		s3c_gpio_cfgrange_nopull(S5P6440_GPH(0), 2 , S3C_GPIO_SFN(2));
-
-	switch (width) {
-	case 8:
-		/* Set data pins GPH[6:9] special-function 2 */
-		if (soc_is_s5p6450())
-			s3c_gpio_cfgrange_nopull(S5P6450_GPH(6), 4,
-						 S3C_GPIO_SFN(2));
-		else
-			s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4,
-						 S3C_GPIO_SFN(2));
-	case 4:
-		/* set data pins GPH[2:5] special-function 2 */
-		if (soc_is_s5p6450())
-			s3c_gpio_cfgrange_nopull(S5P6450_GPH(2), 4,
-						 S3C_GPIO_SFN(2));
-		else
-			s3c_gpio_cfgrange_nopull(S5P6440_GPH(2), 4,
-						 S3C_GPIO_SFN(2));
-	default:
-		break;
-	}
-
-	/* Set GPG[6] pin to special-funtion 3 : MMC1 CDn */
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		if (soc_is_s5p6450()) {
-			s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP);
-			s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(3));
-		} else {
-			s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP);
-			s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(3));
-		}
-	}
-}
-
-void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	/* Set GPC[4:5] pins to special-function 3 - CLK and CMD */
-	s3c_gpio_cfgrange_nopull(S5P6440_GPC(4), 2, S3C_GPIO_SFN(3));
-
-	/* Set data pins GPH[6:9] pins to special-function 3 */
-	s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, S3C_GPIO_SFN(3));
-}
-
-void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	/* Set all the necessary GPG pins to special-function 3 */
-	s3c_gpio_cfgrange_nopull(S5P6450_GPG(7), 2 + width, S3C_GPIO_SFN(3));
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-spi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-spi.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5p64x0/setup-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5p64x0/setup-spi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
-	if (soc_is_s5p6450())
-		s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
-					S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	else
-		s3c_gpio_cfgall_range(S5P6440_GPC(0), 3,
-					S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
-	if (soc_is_s5p6450())
-		s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
-					S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	else
-		s3c_gpio_cfgall_range(S5P6440_GPC(4), 3,
-					S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/clock.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/clock.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1361 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PC100 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-static struct clk s5p_clk_otgphy = {
-	.name		= "otg_phy",
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static struct clk *clk_src_mout_href_list[] = {
-	[0] = &s5p_clk_27m,
-	[1] = &clk_fin_hpll,
-};
-
-static struct clksrc_sources clk_src_mout_href = {
-	.sources	= clk_src_mout_href_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mout_href_list),
-};
-
-static struct clksrc_clk clk_mout_href = {
-	.clk = {
-		.name           = "mout_href",
-	},
-	.sources        = &clk_src_mout_href,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
-};
-
-static struct clk *clk_src_mout_48m_list[] = {
-	[0] = &clk_xusbxti,
-	[1] = &s5p_clk_otgphy,
-};
-
-static struct clksrc_sources clk_src_mout_48m = {
-	.sources	= clk_src_mout_48m_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mout_48m_list),
-};
-
-static struct clksrc_clk clk_mout_48m = {
-	.clk = {
-		.name           = "mout_48m",
-	},
-	.sources        = &clk_src_mout_48m,
-	.reg_src        = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name           = "mout_mpll",
-	},
-	.sources        = &clk_src_mpll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
-};
-
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk    = {
-		.name           = "mout_apll",
-	},
-	.sources        = &clk_src_apll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk    = {
-		.name           = "mout_epll",
-	},
-	.sources        = &clk_src_epll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
-};
-
-static struct clk *clk_src_mout_hpll_list[] = {
-	[0] = &s5p_clk_27m,
-};
-
-static struct clksrc_sources clk_src_mout_hpll = {
-	.sources	= clk_src_mout_hpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mout_hpll_list),
-};
-
-static struct clksrc_clk clk_mout_hpll = {
-	.clk    = {
-		.name           = "mout_hpll",
-	},
-	.sources        = &clk_src_mout_hpll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_apll = {
-	.clk	= {
-		.name	= "div_apll",
-		.parent	= &clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_arm = {
-	.clk	= {
-		.name	= "div_arm",
-		.parent	= &clk_div_apll.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_d0_bus = {
-	.clk	= {
-		.name	= "div_d0_bus",
-		.parent	= &clk_div_arm.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_pclkd0 = {
-	.clk	= {
-		.name	= "div_pclkd0",
-		.parent	= &clk_div_d0_bus.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_secss = {
-	.clk	= {
-		.name	= "div_secss",
-		.parent	= &clk_div_d0_bus.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_apll2 = {
-	.clk	= {
-		.name	= "div_apll2",
-		.parent	= &clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 },
-};
-
-static struct clk *clk_src_mout_am_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_div_apll2.clk,
-};
-
-static struct clksrc_sources clk_src_mout_am = {
-	.sources	= clk_src_mout_am_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mout_am_list),
-};
-
-static struct clksrc_clk clk_mout_am = {
-	.clk	= {
-		.name	= "mout_am",
-	},
-	.sources = &clk_src_mout_am,
-	.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_d1_bus = {
-	.clk	= {
-		.name	= "div_d1_bus",
-		.parent	= &clk_mout_am.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_mpll2 = {
-	.clk	= {
-		.name	= "div_mpll2",
-		.parent	= &clk_mout_am.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_mpll = {
-	.clk	= {
-		.name	= "div_mpll",
-		.parent	= &clk_mout_am.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 },
-};
-
-static struct clk *clk_src_mout_onenand_list[] = {
-	[0] = &clk_div_d0_bus.clk,
-	[1] = &clk_div_d1_bus.clk,
-};
-
-static struct clksrc_sources clk_src_mout_onenand = {
-	.sources	= clk_src_mout_onenand_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mout_onenand_list),
-};
-
-static struct clksrc_clk clk_mout_onenand = {
-	.clk	= {
-		.name	= "mout_onenand",
-	},
-	.sources = &clk_src_mout_onenand,
-	.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_onenand = {
-	.clk	= {
-		.name	= "div_onenand",
-		.parent	= &clk_mout_onenand.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 },
-};
-
-static struct clksrc_clk clk_div_pclkd1 = {
-	.clk	= {
-		.name	= "div_pclkd1",
-		.parent	= &clk_div_d1_bus.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_cam = {
-	.clk	= {
-		.name	= "div_cam",
-		.parent	= &clk_div_mpll2.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 },
-};
-
-static struct clksrc_clk clk_div_hdmi = {
-	.clk	= {
-		.name	= "div_hdmi",
-		.parent	= &clk_mout_hpll.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
-};
-
-static u32 epll_div[][4] = {
-	{ 32750000,	131, 3, 4 },
-	{ 32768000,	131, 3, 4 },
-	{ 36000000,	72,  3, 3 },
-	{ 45000000,	90,  3, 3 },
-	{ 45158000,	90,  3, 3 },
-	{ 45158400,	90,  3, 3 },
-	{ 48000000,	96,  3, 3 },
-	{ 49125000,	131, 4, 3 },
-	{ 49152000,	131, 4, 3 },
-	{ 60000000,	120, 3, 3 },
-	{ 67737600,	226, 5, 3 },
-	{ 67738000,	226, 5, 3 },
-	{ 73800000,	246, 5, 3 },
-	{ 73728000,	246, 5, 3 },
-	{ 72000000,	144, 3, 3 },
-	{ 84000000,	168, 3, 3 },
-	{ 96000000,	96,  3, 2 },
-	{ 144000000,	144, 3, 2 },
-	{ 192000000,	96,  3, 1 }
-};
-
-static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con;
-	unsigned int i;
-
-	if (clk->rate == rate)	/* Return if nothing changed */
-		return 0;
-
-	epll_con = __raw_readl(S5P_EPLL_CON);
-
-	epll_con &= ~(PLL65XX_MDIV_MASK | PLL65XX_PDIV_MASK | PLL65XX_SDIV_MASK);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		if (epll_div[i][0] == rate) {
-			epll_con |= (epll_div[i][1] << PLL65XX_MDIV_SHIFT) |
-				    (epll_div[i][2] << PLL65XX_PDIV_SHIFT) |
-				    (epll_div[i][3] << PLL65XX_SDIV_SHIFT);
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(epll_con, S5P_EPLL_CON);
-
-	printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
-			clk->rate, rate);
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops s5pc100_epll_ops = {
-	.get_rate = s5p_epll_get_rate,
-	.set_rate = s5pc100_epll_set_rate,
-};
-
-static int s5pc100_d0_0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D00, clk, enable);
-}
-
-static int s5pc100_d0_1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D01, clk, enable);
-}
-
-static int s5pc100_d0_2_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D02, clk, enable);
-}
-
-static int s5pc100_d1_0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D10, clk, enable);
-}
-
-static int s5pc100_d1_1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D11, clk, enable);
-}
-
-static int s5pc100_d1_2_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D12, clk, enable);
-}
-
-static int s5pc100_d1_3_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D13, clk, enable);
-}
-
-static int s5pc100_d1_4_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D14, clk, enable);
-}
-
-static int s5pc100_d1_5_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_D15, clk, enable);
-}
-
-static int s5pc100_sclk0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_SCLK0, clk, enable);
-}
-
-static int s5pc100_sclk1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_SCLK1, clk, enable);
-}
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "cssys",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "secss",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "g2d",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "mdma",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "cfcon",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "nfcon",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "onenandc",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "sdm",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_2_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "seckey",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_2_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "modemif",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "otg",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "usbhost",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "dma",
-		.devname	= "dma-pl330.1",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "dma",
-		.devname	= "dma-pl330.0",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "rotator",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5p-fimc.0",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5p-fimc.1",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5p-fimc.2",
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "jpeg",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "mipi-dsim",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "mipi-csis",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_1_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "g3d",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "tv",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_2_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "vp",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_2_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "mixer",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_2_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "hdmi",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_2_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "mfc",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_2_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "apc",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "iec",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "systimer",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pc100-spi.0",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pc100-spi.1",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pc100-spi.2",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "irda",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "ccan",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "ccan",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "hsitx",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "hsirx",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "ac97",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.0",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.1",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "spdif",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "adc",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "keypad",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_mout_48m.clk,
-		.enable		= s5pc100_sclk0_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_mout_48m.clk,
-		.enable		= s5pc100_sclk0_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "mmc_48m",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_mout_48m.clk,
-		.enable		= s5pc100_sclk0_ctrl,
-		.ctrlbit	= (1 << 17),
-	},
-};
-
-static struct clk clk_hsmmc2 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.2",
-	.parent		= &clk_div_d1_bus.clk,
-	.enable		= s5pc100_d1_0_ctrl,
-	.ctrlbit	= (1 << 7),
-};
-
-static struct clk clk_hsmmc1 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.1",
-	.parent		= &clk_div_d1_bus.clk,
-	.enable		= s5pc100_d1_0_ctrl,
-	.ctrlbit	= (1 << 6),
-};
-
-static struct clk clk_hsmmc0 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.0",
-	.parent		= &clk_div_d1_bus.clk,
-	.enable		= s5pc100_d1_0_ctrl,
-	.ctrlbit	= (1 << 5),
-};
-
-static struct clk clk_48m_spi0 = {
-	.name		= "spi_48m",
-	.devname	= "s5pc100-spi.0",
-	.parent		= &clk_mout_48m.clk,
-	.enable		= s5pc100_sclk0_ctrl,
-	.ctrlbit	= (1 << 7),
-};
-
-static struct clk clk_48m_spi1 = {
-	.name		= "spi_48m",
-	.devname	= "s5pc100-spi.1",
-	.parent		= &clk_mout_48m.clk,
-	.enable		= s5pc100_sclk0_ctrl,
-	.ctrlbit	= (1 << 8),
-};
-
-static struct clk clk_48m_spi2 = {
-	.name		= "spi_48m",
-	.devname	= "s5pc100-spi.2",
-	.parent		= &clk_mout_48m.clk,
-	.enable		= s5pc100_sclk0_ctrl,
-	.ctrlbit	= (1 << 9),
-};
-
-static struct clk clk_i2s0 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.0",
-	.parent		= &clk_div_pclkd1.clk,
-	.enable		= s5pc100_d1_5_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk clk_i2s1 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.1",
-	.parent		= &clk_div_pclkd1.clk,
-	.enable		= s5pc100_d1_5_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk clk_i2s2 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.2",
-	.parent		= &clk_div_pclkd1.clk,
-	.enable		= s5pc100_d1_5_ctrl,
-	.ctrlbit	= (1 << 2),
-};
-
-static struct clk clk_vclk54m = {
-	.name		= "vclk_54m",
-	.rate		= 54000000,
-};
-
-static struct clk clk_i2scdclk0 = {
-	.name		= "i2s_cdclk0",
-};
-
-static struct clk clk_i2scdclk1 = {
-	.name		= "i2s_cdclk1",
-};
-
-static struct clk clk_i2scdclk2 = {
-	.name		= "i2s_cdclk2",
-};
-
-static struct clk clk_pcmcdclk0 = {
-	.name		= "pcm_cdclk0",
-};
-
-static struct clk clk_pcmcdclk1 = {
-	.name		= "pcm_cdclk1",
-};
-
-static struct clk *clk_src_group1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll2.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group1 = {
-	.sources	= clk_src_group1_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group1_list),
-};
-
-static struct clk *clk_src_group2_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_group2 = {
-	.sources	= clk_src_group2_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group2_list),
-};
-
-static struct clk *clk_src_group3_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_i2scdclk0,
-	[4] = &clk_pcmcdclk0,
-	[5] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group3 = {
-	.sources	= clk_src_group3_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group3_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
-	.clk	= {
-		.name		= "sclk_audio",
-		.devname	= "samsung-pcm.0",
-		.ctrlbit	= (1 << 8),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_group3,
-	.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
-};
-
-static struct clk *clk_src_group4_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_i2scdclk1,
-	[4] = &clk_pcmcdclk1,
-	[5] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group4 = {
-	.sources	= clk_src_group4_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group4_list),
-};
-
-static struct clksrc_clk clk_sclk_audio1 = {
-	.clk	= {
-		.name		= "sclk_audio",
-		.devname	= "samsung-pcm.1",
-		.ctrlbit	= (1 << 9),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_group4,
-	.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
-};
-
-static struct clk *clk_src_group5_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_i2scdclk2,
-	[4] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group5 = {
-	.sources	= clk_src_group5_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group5_list),
-};
-
-static struct clksrc_clk clk_sclk_audio2 = {
-	.clk	= {
-		.name		= "sclk_audio",
-		.devname	= "samsung-pcm.2",
-		.ctrlbit	= (1 << 10),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_group5,
-	.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
-};
-
-static struct clk *clk_src_group6_list[] = {
-	[0] = &s5p_clk_27m,
-	[1] = &clk_vclk54m,
-	[2] = &clk_div_hdmi.clk,
-};
-
-static struct clksrc_sources clk_src_group6 = {
-	.sources	= clk_src_group6_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group6_list),
-};
-
-static struct clk *clk_src_group7_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_mout_hpll.clk,
-	[3] = &clk_vclk54m,
-};
-
-static struct clksrc_sources clk_src_group7 = {
-	.sources	= clk_src_group7_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_group7_list),
-};
-
-static struct clk *clk_src_mmc0_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-};
-
-static struct clksrc_sources clk_src_mmc0 = {
-	.sources	= clk_src_mmc0_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mmc0_list),
-};
-
-static struct clk *clk_src_mmc12_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_mmc12 = {
-	.sources	= clk_src_mmc12_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mmc12_list),
-};
-
-static struct clk *clk_src_irda_usb_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_div_mpll.clk,
-	[2] = &clk_fin_epll,
-	[3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_irda_usb = {
-	.sources	= clk_src_irda_usb_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_irda_usb_list),
-};
-
-static struct clk *clk_src_pwi_list[] = {
-	[0] = &clk_fin_epll,
-	[1] = &clk_mout_epll.clk,
-	[2] = &clk_div_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_pwi = {
-	.sources	= clk_src_pwi_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_pwi_list),
-};
-
-static struct clk *clk_sclk_spdif_list[] = {
-	[0] = &clk_sclk_audio0.clk,
-	[1] = &clk_sclk_audio1.clk,
-	[2] = &clk_sclk_audio2.clk,
-};
-
-static struct clksrc_sources clk_src_sclk_spdif = {
-	.sources	= clk_sclk_spdif_list,
-	.nr_sources	= ARRAY_SIZE(clk_sclk_spdif_list),
-};
-
-static struct clksrc_clk clk_sclk_spdif = {
-	.clk	= {
-		.name		= "sclk_spdif",
-		.ctrlbit	= (1 << 11),
-		.enable		= s5pc100_sclk1_ctrl,
-		.ops		= &s5p_sclk_spdif_ops,
-	},
-	.sources = &clk_src_sclk_spdif,
-	.reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_mixer",
-			.ctrlbit	= (1 << 6),
-			.enable		= s5pc100_sclk0_ctrl,
-
-		},
-		.sources = &clk_src_group6,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 },
-	}, {
-		.clk	= {
-			.name		= "sclk_lcd",
-			.ctrlbit	= (1 << 0),
-			.enable		= s5pc100_sclk1_ctrl,
-
-		},
-		.sources = &clk_src_group7,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 12, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5p-fimc.0",
-			.ctrlbit	= (1 << 1),
-			.enable		= s5pc100_sclk1_ctrl,
-
-		},
-		.sources = &clk_src_group7,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 16, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5p-fimc.1",
-			.ctrlbit	= (1 << 2),
-			.enable		= s5pc100_sclk1_ctrl,
-
-		},
-		.sources = &clk_src_group7,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 20, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5p-fimc.2",
-			.ctrlbit	= (1 << 3),
-			.enable		= s5pc100_sclk1_ctrl,
-
-		},
-		.sources = &clk_src_group7,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 24, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_irda",
-			.ctrlbit	= (1 << 10),
-			.enable		= s5pc100_sclk0_ctrl,
-
-		},
-		.sources = &clk_src_irda_usb,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_irda",
-			.ctrlbit	= (1 << 10),
-			.enable		= s5pc100_sclk0_ctrl,
-
-		},
-		.sources = &clk_src_mmc12,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_pwi",
-			.ctrlbit	= (1 << 1),
-			.enable		= s5pc100_sclk0_ctrl,
-
-		},
-		.sources = &clk_src_pwi,
-		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 0, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 3 },
-	}, {
-		.clk	= {
-			.name		= "sclk_uhost",
-			.ctrlbit	= (1 << 11),
-			.enable		= s5pc100_sclk0_ctrl,
-
-		},
-		.sources = &clk_src_irda_usb,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 20, .size = 4 },
-	},
-};
-
-static struct clksrc_clk clk_sclk_uart = {
-	.clk	= {
-		.name		= "uclk1",
-		.ctrlbit	= (1 << 3),
-		.enable		= s5pc100_sclk0_ctrl,
-	},
-	.sources = &clk_src_group2,
-	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
-	.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.0",
-		.ctrlbit	= (1 << 12),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_mmc0,
-	.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.1",
-		.ctrlbit	= (1 << 13),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_mmc12,
-	.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.2",
-		.ctrlbit	= (1 << 14),
-		.enable		= s5pc100_sclk1_ctrl,
-	},
-	.sources = &clk_src_mmc12,
-	.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5pc100-spi.0",
-		.ctrlbit	= (1 << 4),
-		.enable		= s5pc100_sclk0_ctrl,
-	},
-	.sources = &clk_src_group1,
-	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5pc100-spi.1",
-		.ctrlbit	= (1 << 5),
-		.enable		= s5pc100_sclk0_ctrl,
-	},
-	.sources = &clk_src_group1,
-	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "s5pc100-spi.2",
-		.ctrlbit	= (1 << 6),
-		.enable		= s5pc100_sclk0_ctrl,
-	},
-	.sources = &clk_src_group1,
-	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
-	.reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_mout_hpll,
-	&clk_mout_href,
-	&clk_mout_48m,
-	&clk_div_apll,
-	&clk_div_arm,
-	&clk_div_d0_bus,
-	&clk_div_pclkd0,
-	&clk_div_secss,
-	&clk_div_apll2,
-	&clk_mout_am,
-	&clk_div_d1_bus,
-	&clk_div_mpll2,
-	&clk_div_mpll,
-	&clk_mout_onenand,
-	&clk_div_onenand,
-	&clk_div_pclkd1,
-	&clk_div_cam,
-	&clk_div_hdmi,
-	&clk_sclk_audio0,
-	&clk_sclk_audio1,
-	&clk_sclk_audio2,
-	&clk_sclk_spdif,
-};
-
-static struct clk *clk_cdev[] = {
-	&clk_hsmmc0,
-	&clk_hsmmc1,
-	&clk_hsmmc2,
-	&clk_48m_spi0,
-	&clk_48m_spi1,
-	&clk_48m_spi2,
-	&clk_i2s0,
-	&clk_i2s1,
-	&clk_i2s2,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
-	&clk_sclk_uart,
-	&clk_sclk_mmc0,
-	&clk_sclk_mmc1,
-	&clk_sclk_mmc2,
-	&clk_sclk_spi0,
-	&clk_sclk_spi1,
-	&clk_sclk_spi2,
-};
-
-void __init_or_cpufreq s5pc100_setup_clocks(void)
-{
-	unsigned long xtal;
-	unsigned long arm;
-	unsigned long hclkd0;
-	unsigned long hclkd1;
-	unsigned long pclkd0;
-	unsigned long pclkd1;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long hpll;
-	unsigned int ptr;
-
-	/* Set S5PC100 functions for clk_fout_epll */
-	clk_fout_epll.enable = s5p_epll_enable;
-	clk_fout_epll.ops = &s5pc100_epll_ops;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal = clk_get_rate(&clk_xtal);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	apll = s5p_get_pll65xx(xtal, __raw_readl(S5P_APLL_CON));
-	mpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_MPLL_CON));
-	epll = s5p_get_pll65xx(xtal, __raw_readl(S5P_EPLL_CON));
-	hpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_HPLL_CON));
-
-	printk(KERN_INFO "S5PC100: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz, E=%ld.%ldMHz, H=%ld.%ldMHz\n",
-			print_mhz(apll), print_mhz(mpll), print_mhz(epll), print_mhz(hpll));
-
-	clk_fout_apll.rate = apll;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_mout_hpll.clk.rate = hpll;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-
-	arm = clk_get_rate(&clk_div_arm.clk);
-	hclkd0 = clk_get_rate(&clk_div_d0_bus.clk);
-	pclkd0 = clk_get_rate(&clk_div_pclkd0.clk);
-	hclkd1 = clk_get_rate(&clk_div_d1_bus.clk);
-	pclkd1 = clk_get_rate(&clk_div_pclkd1.clk);
-
-	printk(KERN_INFO "S5PC100: HCLKD0=%ld.%ldMHz, HCLKD1=%ld.%ldMHz, PCLKD0=%ld.%ldMHz, PCLKD1=%ld.%ldMHz\n",
-			print_mhz(hclkd0), print_mhz(hclkd1), print_mhz(pclkd0), print_mhz(pclkd1));
-
-	clk_f.rate = arm;
-	clk_h.rate = hclkd1;
-	clk_p.rate = pclkd1;
-}
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
-	{
-		.name		= "tzic",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "intc",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "ebi",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "intmem",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "sromc",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "dmc",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "chipid",
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.0",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.1",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.2",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.3",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_4_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "timers",
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_3_ctrl,
-		.ctrlbit	= (1 << 6),
-	},
-};
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_i2scdclk0,
-	&clk_i2scdclk1,
-	&clk_i2scdclk2,
-	&clk_pcmcdclk0,
-	&clk_pcmcdclk1,
-};
-
-static struct clk_lookup s5pc100_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uart.clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
-	CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-	CLKDEV_INIT("s5pc100-spi.0", "spi_busclk1", &clk_48m_spi0),
-	CLKDEV_INIT("s5pc100-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
-	CLKDEV_INIT("s5pc100-spi.1", "spi_busclk1", &clk_48m_spi1),
-	CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
-	CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
-	CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
-	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
-	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
-};
-
-void __init s5pc100_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
-		s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s5pc100_clk_lookup, ARRAY_SIZE(s5pc100_clk_lookup));
-
-	s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
-		s3c_disable_clocks(clk_cdev[ptr], 1);
-
-	s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * Common Codes for S5PC100
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/reboot.h>
-
-#include <asm/irq.h>
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/ata-core.h>
-#include <plat/fb-core.h>
-#include <plat/iic-core.h>
-#include <plat/onenand-core.h>
-#include <plat/pwm-core.h>
-#include <plat/spi-core.h>
-#include <plat/watchdog-reset.h>
-
-#include "common.h"
-
-static const char name_s5pc100[] = "S5PC100";
-
-static struct cpu_table cpu_ids[] __initdata = {
-	{
-		.idcode		= S5PC100_CPU_ID,
-		.idmask		= S5PC100_CPU_MASK,
-		.map_io		= s5pc100_map_io,
-		.init_clocks	= s5pc100_init_clocks,
-		.init_uarts	= s5pc100_init_uarts,
-		.init		= s5pc100_init,
-		.name		= name_s5pc100,
-	},
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5pc100_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_CHIPID,
-		.pfn		= __phys_to_pfn(S5PC100_PA_CHIPID),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_SYS,
-		.pfn		= __phys_to_pfn(S5PC100_PA_SYSCON),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_TIMER,
-		.pfn		= __phys_to_pfn(S5PC100_PA_TIMER),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
-		.pfn		= __phys_to_pfn(S5PC100_PA_WATCHDOG),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5PC100_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(S5PC100_PA_SYSTIMER),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO,
-		.pfn		= __phys_to_pfn(S5PC100_PA_GPIO),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC0,
-		.pfn		= __phys_to_pfn(S5PC100_PA_VIC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC1,
-		.pfn		= __phys_to_pfn(S5PC100_PA_VIC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC2,
-		.pfn		= __phys_to_pfn(S5PC100_PA_VIC2),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5PC100_VA_OTHERS,
-		.pfn		= __phys_to_pfn(S5PC100_PA_OTHERS),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}
-};
-
-static struct samsung_pwm_variant s5pc100_pwm_variant = {
-	.bits		= 32,
-	.div_base	= 0,
-	.has_tint_cstat	= true,
-	.tclk_mask	= (1 << 5),
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
-	s5pc100_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
-	s5pc100_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
-	unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
-		IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
-		IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
-	};
-
-	samsung_pwm_clocksource_init(S3C_VA_TIMER,
-					timer_irqs, &s5pc100_pwm_variant);
-}
-
-/*
- * s5pc100_map_io
- *
- * register the standard CPU IO areas
- */
-
-void __init s5pc100_init_io(struct map_desc *mach_desc, int size)
-{
-	/* initialize the io descriptors we need for initialization */
-	iotable_init(s5pc100_iodesc, ARRAY_SIZE(s5pc100_iodesc));
-	if (mach_desc)
-		iotable_init(mach_desc, size);
-
-	/* detect cpu id and rev. */
-	s5p_init_cpu(S5P_VA_CHIPID);
-
-	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
-
-	samsung_pwm_set_platdata(&s5pc100_pwm_variant);
-}
-
-void __init s5pc100_map_io(void)
-{
-	/* initialise device information early */
-	s5pc100_default_sdhci0();
-	s5pc100_default_sdhci1();
-	s5pc100_default_sdhci2();
-
-	s3c_adc_setname("s3c64xx-adc");
-
-	/* the i2c devices are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-
-	s3c_onenand_setname("s5pc100-onenand");
-	s3c_fb_setname("s5pc100-fb");
-	s3c_cfcon_setname("s5pc100-pata");
-
-	s3c64xx_spi_setname("s5pc100-spi");
-}
-
-void __init s5pc100_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5pc100_register_clocks();
-	s5pc100_setup_clocks();
-	samsung_wdt_reset_init(S3C_VA_WATCHDOG);
-}
-
-void __init s5pc100_init_irq(void)
-{
-	u32 vic[] = {~0, ~0, ~0};
-
-	/* VIC0, VIC1, and VIC2 are fully populated. */
-	s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-static struct bus_type s5pc100_subsys = {
-	.name		= "s5pc100-core",
-	.dev_name	= "s5pc100-core",
-};
-
-static struct device s5pc100_dev = {
-	.bus	= &s5pc100_subsys,
-};
-
-static int __init s5pc100_core_init(void)
-{
-	return subsys_system_register(&s5pc100_subsys, NULL);
-}
-core_initcall(s5pc100_core_init);
-
-int __init s5pc100_init(void)
-{
-	printk(KERN_INFO "S5PC100: Initializing architecture\n");
-	return device_register(&s5pc100_dev);
-}
-
-/* uart registration process */
-
-void __init s5pc100_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-
-void s5pc100_restart(enum reboot_mode mode, const char *cmd)
-{
-	if (mode != REBOOT_SOFT)
-		samsung_wdt_reset();
-
-	soft_restart(0);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Common Header for S5PC100 machines
- *
- * This program is free software; you can 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_S5PC100_COMMON_H
-#define __ARCH_ARM_MACH_S5PC100_COMMON_H
-
-#include <linux/reboot.h>
-
-void s5pc100_init_io(struct map_desc *mach_desc, int size);
-void s5pc100_init_irq(void);
-
-void s5pc100_register_clocks(void);
-void s5pc100_setup_clocks(void);
-
-void s5pc100_restart(enum reboot_mode mode, const char *cmd);
-
-extern  int s5pc100_init(void);
-extern void s5pc100_map_io(void);
-extern void s5pc100_init_clocks(int xtal);
-extern void s5pc100_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#endif /* __ARCH_ARM_MACH_S5PC100_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/dev-audio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/dev-audio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/dev-audio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,239 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5pc100_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case 0: /* Dedicated pins */
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
-	.cfg_gpio = s5pc100_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
-					 | QUIRK_NEED_RSTCLR,
-		},
-	},
-};
-
-static struct resource s5pc100_iis0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_I2S0, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
-	[3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
-};
-
-struct platform_device s5pc100_device_iis0 = {
-	.name = "samsung-i2s",
-	.id = 0,
-	.num_resources	  = ARRAY_SIZE(s5pc100_iis0_resource),
-	.resource	  = s5pc100_iis0_resource,
-	.dev = {
-		.platform_data = &i2sv5_pdata,
-	},
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
-	.cfg_gpio = s5pc100_cfg_i2s,
-};
-
-static struct resource s5pc100_iis1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_I2S1, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5pc100_device_iis1 = {
-	.name		  = "samsung-i2s",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5pc100_iis1_resource),
-	.resource	  = s5pc100_iis1_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-static struct resource s5pc100_iis2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_I2S2, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5pc100_device_iis2 = {
-	.name		  = "samsung-i2s",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s5pc100_iis2_resource),
-	.resource	  = s5pc100_iis2_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pc100_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(5));
-		break;
-
-	case 1:
-		s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(3));
-		break;
-
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = s5pc100_pcm_cfg_gpio,
-};
-
-static struct resource s5pc100_pcm0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_PCM0, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5pc100_device_pcm0 = {
-	.name		  = "samsung-pcm",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5pc100_pcm0_resource),
-	.resource	  = s5pc100_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pc100_pcm1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_PCM1, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
-};
-
-struct platform_device s5pc100_device_pcm1 = {
-	.name		  = "samsung-pcm",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5pc100_pcm1_resource),
-	.resource	  = s5pc100_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev)
-{
-	return s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pc100_ac97_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_AC97, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
-	[2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
-	[3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
-	[4] = DEFINE_RES_IRQ(IRQ_AC97),
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
-	.cfg_gpio = s5pc100_ac97_cfg_gpio,
-};
-
-static u64 s5pc100_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pc100_device_ac97 = {
-	.name		  = "samsung-ac97",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s5pc100_ac97_resource),
-	.resource	  = s5pc100_ac97_resource,
-	.dev = {
-		.platform_data = &s3c_ac97_pdata,
-		.dma_mask = &s5pc100_ac97_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-/* S/PDIF Controller platform_device */
-static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3));
-
-	return 0;
-}
-
-static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3));
-
-	return 0;
-}
-
-static struct resource s5pc100_spdif_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PC100_PA_SPDIF, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_SPDIF),
-};
-
-static struct s3c_audio_pdata s5p_spdif_pdata = {
-	.cfg_gpio = s5pc100_spdif_cfg_gpd,
-};
-
-static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pc100_device_spdif = {
-	.name		= "samsung-spdif",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5pc100_spdif_resource),
-	.resource	= s5pc100_spdif_resource,
-	.dev = {
-		.platform_data = &s5p_spdif_pdata,
-		.dma_mask = &s5pc100_spdif_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-void __init s5pc100_spdif_setup_gpio(int gpio)
-{
-	if (gpio == S5PC100_SPDIF_GPD)
-		s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd;
-	else
-		s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/dma.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/dma.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/dma.h>
-
-static u8 pdma0_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_IRDA,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_I2S2_RX,
-	DMACH_I2S2_TX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_SPI2_RX,
-	DMACH_SPI2_TX,
-	DMACH_AC97_MICIN,
-	DMACH_AC97_PCMIN,
-	DMACH_AC97_PCMOUT,
-	DMACH_EXTERNAL,
-	DMACH_PWM,
-	DMACH_SPDIF,
-	DMACH_HSI_RX,
-	DMACH_HSI_TX,
-};
-
-static struct dma_pl330_platdata s5pc100_pdma0_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
-	.peri_id = pdma0_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pc100_pdma0,  "dma-pl330.0", 0x00041330,
-	S5PC100_PA_PDMA0, {IRQ_PDMA0}, &s5pc100_pdma0_pdata);
-
-static u8 pdma1_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_IRDA,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_I2S2_RX,
-	DMACH_I2S2_TX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_SPI2_RX,
-	DMACH_SPI2_TX,
-	DMACH_PCM0_RX,
-	DMACH_PCM0_TX,
-	DMACH_PCM1_RX,
-	DMACH_PCM1_TX,
-	DMACH_MSM_REQ0,
-	DMACH_MSM_REQ1,
-	DMACH_MSM_REQ2,
-	DMACH_MSM_REQ3,
-};
-
-static struct dma_pl330_platdata s5pc100_pdma1_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
-	.peri_id = pdma1_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pc100_pdma1, "dma-pl330.1", 0x00041330,
-	S5PC100_PA_PDMA1, {IRQ_PDMA1}, &s5pc100_pdma1_pdata);
-
-static int __init s5pc100_dma_init(void)
-{
-	dma_cap_set(DMA_SLAVE, s5pc100_pdma0_pdata.cap_mask);
-	dma_cap_set(DMA_CYCLIC, s5pc100_pdma0_pdata.cap_mask);
-	amba_device_register(&s5pc100_pdma0_device, &iomem_resource);
-
-	dma_cap_set(DMA_SLAVE, s5pc100_pdma1_pdata.cap_mask);
-	dma_cap_set(DMA_CYCLIC, s5pc100_pdma1_pdata.cap_mask);
-	amba_device_register(&s5pc100_pdma1_device, &iomem_resource);
-
-	return 0;
-}
-arch_initcall(s5pc100_dma_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/debug-macro.S
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- *
- * Based on mach-s3c6400/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <linux/serial_s3c.h>
-#include <mach/map.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rp, rv, tmp
-		ldr	\rp, = S3C_PA_UART
-		ldr	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <debug/samsung.S>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/dma.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/dma.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common DMA API driver for PL330 */
-#include <plat/dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/entry-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/entry-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/entry-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/entry-macro.S
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * Based on mach-s3c6400/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for the Samsung S5PC1XX series
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-*/
-
-	.macro	get_irqnr_preamble, base, tmp
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	.endm
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/gpio.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - GPIO lib support
- *
- * Base on mach-s3c6400/include/mach/gpio.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_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* GPIO bank sizes */
-#define S5PC100_GPIO_A0_NR	(8)
-#define S5PC100_GPIO_A1_NR	(5)
-#define S5PC100_GPIO_B_NR	(8)
-#define S5PC100_GPIO_C_NR	(5)
-#define S5PC100_GPIO_D_NR	(7)
-#define S5PC100_GPIO_E0_NR	(8)
-#define S5PC100_GPIO_E1_NR	(6)
-#define S5PC100_GPIO_F0_NR	(8)
-#define S5PC100_GPIO_F1_NR	(8)
-#define S5PC100_GPIO_F2_NR	(8)
-#define S5PC100_GPIO_F3_NR	(4)
-#define S5PC100_GPIO_G0_NR	(8)
-#define S5PC100_GPIO_G1_NR	(3)
-#define S5PC100_GPIO_G2_NR	(7)
-#define S5PC100_GPIO_G3_NR	(7)
-#define S5PC100_GPIO_H0_NR	(8)
-#define S5PC100_GPIO_H1_NR	(8)
-#define S5PC100_GPIO_H2_NR	(8)
-#define S5PC100_GPIO_H3_NR	(8)
-#define S5PC100_GPIO_I_NR	(8)
-#define S5PC100_GPIO_J0_NR	(8)
-#define S5PC100_GPIO_J1_NR	(5)
-#define S5PC100_GPIO_J2_NR	(8)
-#define S5PC100_GPIO_J3_NR	(8)
-#define S5PC100_GPIO_J4_NR	(4)
-#define S5PC100_GPIO_K0_NR	(8)
-#define S5PC100_GPIO_K1_NR	(6)
-#define S5PC100_GPIO_K2_NR	(8)
-#define S5PC100_GPIO_K3_NR	(8)
-#define S5PC100_GPIO_L0_NR	(8)
-#define S5PC100_GPIO_L1_NR	(8)
-#define S5PC100_GPIO_L2_NR	(8)
-#define S5PC100_GPIO_L3_NR	(8)
-#define S5PC100_GPIO_L4_NR	(8)
-
-/* GPIO bank numbes */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5PC100_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	S5PC100_GPIO_A0_START	= 0,
-	S5PC100_GPIO_A1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_A0),
-	S5PC100_GPIO_B_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_A1),
-	S5PC100_GPIO_C_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_B),
-	S5PC100_GPIO_D_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_C),
-	S5PC100_GPIO_E0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_D),
-	S5PC100_GPIO_E1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_E0),
-	S5PC100_GPIO_F0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_E1),
-	S5PC100_GPIO_F1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_F0),
-	S5PC100_GPIO_F2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_F1),
-	S5PC100_GPIO_F3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_F2),
-	S5PC100_GPIO_G0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_F3),
-	S5PC100_GPIO_G1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_G0),
-	S5PC100_GPIO_G2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_G1),
-	S5PC100_GPIO_G3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_G2),
-	S5PC100_GPIO_H0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_G3),
-	S5PC100_GPIO_H1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_H0),
-	S5PC100_GPIO_H2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_H1),
-	S5PC100_GPIO_H3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_H2),
-	S5PC100_GPIO_I_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_H3),
-	S5PC100_GPIO_J0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_I),
-	S5PC100_GPIO_J1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_J0),
-	S5PC100_GPIO_J2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_J1),
-	S5PC100_GPIO_J3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_J2),
-	S5PC100_GPIO_J4_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_J3),
-	S5PC100_GPIO_K0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_J4),
-	S5PC100_GPIO_K1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_K0),
-	S5PC100_GPIO_K2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_K1),
-	S5PC100_GPIO_K3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_K2),
-	S5PC100_GPIO_L0_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_K3),
-	S5PC100_GPIO_L1_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_L0),
-	S5PC100_GPIO_L2_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_L1),
-	S5PC100_GPIO_L3_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_L2),
-	S5PC100_GPIO_L4_START	= S5PC100_GPIO_NEXT(S5PC100_GPIO_L3),
-	S5PC100_GPIO_END	= S5PC100_GPIO_NEXT(S5PC100_GPIO_L4),
-};
-
-/* S5PC100 GPIO number definitions. */
-#define S5PC100_GPA0(_nr)	(S5PC100_GPIO_A0_START + (_nr))
-#define S5PC100_GPA1(_nr)	(S5PC100_GPIO_A1_START + (_nr))
-#define S5PC100_GPB(_nr)	(S5PC100_GPIO_B_START + (_nr))
-#define S5PC100_GPC(_nr)	(S5PC100_GPIO_C_START + (_nr))
-#define S5PC100_GPD(_nr)	(S5PC100_GPIO_D_START + (_nr))
-#define S5PC100_GPE0(_nr)	(S5PC100_GPIO_E0_START + (_nr))
-#define S5PC100_GPE1(_nr)	(S5PC100_GPIO_E1_START + (_nr))
-#define S5PC100_GPF0(_nr)	(S5PC100_GPIO_F0_START + (_nr))
-#define S5PC100_GPF1(_nr)	(S5PC100_GPIO_F1_START + (_nr))
-#define S5PC100_GPF2(_nr)	(S5PC100_GPIO_F2_START + (_nr))
-#define S5PC100_GPF3(_nr)	(S5PC100_GPIO_F3_START + (_nr))
-#define S5PC100_GPG0(_nr)	(S5PC100_GPIO_G0_START + (_nr))
-#define S5PC100_GPG1(_nr)	(S5PC100_GPIO_G1_START + (_nr))
-#define S5PC100_GPG2(_nr)	(S5PC100_GPIO_G2_START + (_nr))
-#define S5PC100_GPG3(_nr)	(S5PC100_GPIO_G3_START + (_nr))
-#define S5PC100_GPH0(_nr)	(S5PC100_GPIO_H0_START + (_nr))
-#define S5PC100_GPH1(_nr)	(S5PC100_GPIO_H1_START + (_nr))
-#define S5PC100_GPH2(_nr)	(S5PC100_GPIO_H2_START + (_nr))
-#define S5PC100_GPH3(_nr)	(S5PC100_GPIO_H3_START + (_nr))
-#define S5PC100_GPI(_nr)	(S5PC100_GPIO_I_START + (_nr))
-#define S5PC100_GPJ0(_nr)	(S5PC100_GPIO_J0_START + (_nr))
-#define S5PC100_GPJ1(_nr)	(S5PC100_GPIO_J1_START + (_nr))
-#define S5PC100_GPJ2(_nr)	(S5PC100_GPIO_J2_START + (_nr))
-#define S5PC100_GPJ3(_nr)	(S5PC100_GPIO_J3_START + (_nr))
-#define S5PC100_GPJ4(_nr)	(S5PC100_GPIO_J4_START + (_nr))
-#define S5PC100_GPK0(_nr)	(S5PC100_GPIO_K0_START + (_nr))
-#define S5PC100_GPK1(_nr)	(S5PC100_GPIO_K1_START + (_nr))
-#define S5PC100_GPK2(_nr)	(S5PC100_GPIO_K2_START + (_nr))
-#define S5PC100_GPK3(_nr)	(S5PC100_GPIO_K3_START + (_nr))
-#define S5PC100_GPL0(_nr)	(S5PC100_GPIO_L0_START + (_nr))
-#define S5PC100_GPL1(_nr)	(S5PC100_GPIO_L1_START + (_nr))
-#define S5PC100_GPL2(_nr)	(S5PC100_GPIO_L2_START + (_nr))
-#define S5PC100_GPL3(_nr)	(S5PC100_GPIO_L3_START + (_nr))
-#define S5PC100_GPL4(_nr)	(S5PC100_GPIO_L4_START + (_nr))
-
-/* It used the end of the S5PC100 gpios */
-#define S3C_GPIO_END		S5PC100_GPIO_END
-
-/* define the number of gpios we need to the one after the MP04() range */
-#define ARCH_NR_GPIOS		(S5PC100_GPIO_END + 1)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/hardware.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - Hardware support
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/irqs.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - IRQ definitions
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0: system, DMA, timer */
-#define IRQ_EINT16_31		S5P_IRQ_VIC0(16)
-#define IRQ_BATF		S5P_IRQ_VIC0(17)
-#define IRQ_MDMA		S5P_IRQ_VIC0(18)
-#define IRQ_PDMA0		S5P_IRQ_VIC0(19)
-#define IRQ_PDMA1		S5P_IRQ_VIC0(20)
-#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(21)
-#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(22)
-#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(23)
-#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(24)
-#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(25)
-#define IRQ_SYSTIMER		S5P_IRQ_VIC0(26)
-#define IRQ_WDT			S5P_IRQ_VIC0(27)
-#define IRQ_RTC_ALARM		S5P_IRQ_VIC0(28)
-#define IRQ_RTC_TIC		S5P_IRQ_VIC0(29)
-#define IRQ_GPIOINT		S5P_IRQ_VIC0(30)
-
-/* VIC1: ARM, power, memory, connectivity */
-#define IRQ_PMU			S5P_IRQ_VIC1(0)
-#define IRQ_CORTEX1		S5P_IRQ_VIC1(1)
-#define IRQ_CORTEX2		S5P_IRQ_VIC1(2)
-#define IRQ_CORTEX3		S5P_IRQ_VIC1(3)
-#define IRQ_CORTEX4		S5P_IRQ_VIC1(4)
-#define IRQ_IEMAPC		S5P_IRQ_VIC1(5)
-#define IRQ_IEMIEC		S5P_IRQ_VIC1(6)
-#define IRQ_ONENAND		S5P_IRQ_VIC1(7)
-#define IRQ_NFC			S5P_IRQ_VIC1(8)
-#define IRQ_CFCON		S5P_IRQ_VIC1(9)
-#define IRQ_UART0		S5P_IRQ_VIC1(10)
-#define IRQ_UART1		S5P_IRQ_VIC1(11)
-#define IRQ_UART2		S5P_IRQ_VIC1(12)
-#define IRQ_UART3		S5P_IRQ_VIC1(13)
-#define IRQ_IIC			S5P_IRQ_VIC1(14)
-#define IRQ_SPI0		S5P_IRQ_VIC1(15)
-#define IRQ_SPI1		S5P_IRQ_VIC1(16)
-#define IRQ_SPI2		S5P_IRQ_VIC1(17)
-#define IRQ_IRDA		S5P_IRQ_VIC1(18)
-#define IRQ_IIC2		S5P_IRQ_VIC1(19)
-#define IRQ_IIC3		S5P_IRQ_VIC1(20)
-#define IRQ_HSIRX		S5P_IRQ_VIC1(21)
-#define IRQ_HSITX		S5P_IRQ_VIC1(22)
-#define IRQ_UHOST		S5P_IRQ_VIC1(23)
-#define IRQ_OTG			S5P_IRQ_VIC1(24)
-#define IRQ_MSM			S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC0		S5P_IRQ_VIC1(26)
-#define IRQ_HSMMC1		S5P_IRQ_VIC1(27)
-#define IRQ_HSMMC2		S5P_IRQ_VIC1(28)
-#define IRQ_MIPICSI		S5P_IRQ_VIC1(29)
-#define IRQ_MIPIDSI		S5P_IRQ_VIC1(30)
-
-/* VIC2: multimedia, audio, security */
-#define IRQ_LCD0		S5P_IRQ_VIC2(0)
-#define IRQ_LCD1		S5P_IRQ_VIC2(1)
-#define IRQ_LCD2		S5P_IRQ_VIC2(2)
-#define IRQ_LCD3		S5P_IRQ_VIC2(3)
-#define IRQ_ROTATOR		S5P_IRQ_VIC2(4)
-#define IRQ_FIMC0		S5P_IRQ_VIC2(5)
-#define IRQ_FIMC1		S5P_IRQ_VIC2(6)
-#define IRQ_FIMC2		S5P_IRQ_VIC2(7)
-#define IRQ_JPEG		S5P_IRQ_VIC2(8)
-#define IRQ_2D			S5P_IRQ_VIC2(9)
-#define IRQ_3D			S5P_IRQ_VIC2(10)
-#define IRQ_MIXER		S5P_IRQ_VIC2(11)
-#define IRQ_HDMI		S5P_IRQ_VIC2(12)
-#define IRQ_IIC1		S5P_IRQ_VIC2(13)
-#define IRQ_MFC			S5P_IRQ_VIC2(14)
-#define IRQ_TVENC		S5P_IRQ_VIC2(15)
-#define IRQ_I2S0		S5P_IRQ_VIC2(16)
-#define IRQ_I2S1		S5P_IRQ_VIC2(17)
-#define IRQ_I2S2		S5P_IRQ_VIC2(18)
-#define IRQ_AC97		S5P_IRQ_VIC2(19)
-#define IRQ_PCM0		S5P_IRQ_VIC2(20)
-#define IRQ_PCM1		S5P_IRQ_VIC2(21)
-#define IRQ_SPDIF		S5P_IRQ_VIC2(22)
-#define IRQ_ADC			S5P_IRQ_VIC2(23)
-#define IRQ_PENDN		S5P_IRQ_VIC2(24)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_KEYPAD		S5P_IRQ_VIC2(25)
-#define IRQ_CG			S5P_IRQ_VIC2(26)
-#define IRQ_SEC			S5P_IRQ_VIC2(27)
-#define IRQ_SECRX		S5P_IRQ_VIC2(28)
-#define IRQ_SECTX		S5P_IRQ_VIC2(29)
-#define IRQ_SDMIRQ		S5P_IRQ_VIC2(30)
-#define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
-#define IRQ_VIC_END		S5P_IRQ_VIC2(31)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
-#define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
-
-/* GPIO interrupt */
-#define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
-#define S5P_GPIOINT_GROUP_MAXNR	21
-
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
-
-/* Compatibility */
-#define IRQ_LCD_FIFO		IRQ_LCD0
-#define IRQ_LCD_VSYNC		IRQ_LCD1
-#define IRQ_LCD_SYSTEM		IRQ_LCD2
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/map.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/map.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/map.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,137 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/map.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5PC100_PA_SDRAM		0x20000000
-
-#define S5PC100_PA_ONENAND		0xE7100000
-#define S5PC100_PA_ONENAND_BUF		0xB0000000
-
-#define S5PC100_PA_CHIPID		0xE0000000
-
-#define S5PC100_PA_SYSCON		0xE0100000
-
-#define S5PC100_PA_OTHERS		0xE0200000
-
-#define S5PC100_PA_GPIO			0xE0300000
-
-#define S5PC100_PA_VIC0			0xE4000000
-#define S5PC100_PA_VIC1			0xE4100000
-#define S5PC100_PA_VIC2			0xE4200000
-
-#define S5PC100_PA_SROMC		0xE7000000
-
-#define S5PC100_PA_CFCON		0xE7800000
-
-#define S5PC100_PA_MDMA			0xE8100000
-#define S5PC100_PA_PDMA0		0xE9000000
-#define S5PC100_PA_PDMA1		0xE9200000
-
-#define S5PC100_PA_TIMER		0xEA000000
-#define S5PC100_PA_SYSTIMER		0xEA100000
-#define S5PC100_PA_WATCHDOG		0xEA200000
-#define S5PC100_PA_RTC			0xEA300000
-
-#define S5PC100_PA_UART			0xEC000000
-
-#define S5PC100_PA_IIC0			0xEC100000
-#define S5PC100_PA_IIC1			0xEC200000
-
-#define S5PC100_PA_SPI0			0xEC300000
-#define S5PC100_PA_SPI1			0xEC400000
-#define S5PC100_PA_SPI2			0xEC500000
-
-#define S5PC100_PA_USB_HSOTG		0xED200000
-#define S5PC100_PA_USB_HSPHY		0xED300000
-
-#define S5PC100_PA_HSMMC(x)		(0xED800000 + ((x) * 0x100000))
-
-#define S5PC100_PA_FB			0xEE000000
-
-#define S5PC100_PA_FIMC0		0xEE200000
-#define S5PC100_PA_FIMC1		0xEE300000
-#define S5PC100_PA_FIMC2		0xEE400000
-
-#define S5PC100_PA_I2S0			0xF2000000
-#define S5PC100_PA_I2S1			0xF2100000
-#define S5PC100_PA_I2S2			0xF2200000
-
-#define S5PC100_PA_AC97			0xF2300000
-
-#define S5PC100_PA_PCM0			0xF2400000
-#define S5PC100_PA_PCM1			0xF2500000
-
-#define S5PC100_PA_SPDIF		0xF2600000
-
-#define S5PC100_PA_TSADC		0xF3000000
-
-#define S5PC100_PA_KEYPAD		0xF3100000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_FB			S5PC100_PA_FB
-#define S3C_PA_HSMMC0			S5PC100_PA_HSMMC(0)
-#define S3C_PA_HSMMC1			S5PC100_PA_HSMMC(1)
-#define S3C_PA_HSMMC2			S5PC100_PA_HSMMC(2)
-#define S3C_PA_IIC			S5PC100_PA_IIC0
-#define S3C_PA_IIC1			S5PC100_PA_IIC1
-#define S3C_PA_KEYPAD			S5PC100_PA_KEYPAD
-#define S3C_PA_ONENAND			S5PC100_PA_ONENAND
-#define S3C_PA_ONENAND_BUF		S5PC100_PA_ONENAND_BUF
-#define S3C_PA_RTC			S5PC100_PA_RTC
-#define S3C_PA_TSADC			S5PC100_PA_TSADC
-#define S3C_PA_USB_HSOTG		S5PC100_PA_USB_HSOTG
-#define S3C_PA_USB_HSPHY		S5PC100_PA_USB_HSPHY
-#define S3C_PA_WDT			S5PC100_PA_WATCHDOG
-#define S3C_PA_SPI0			S5PC100_PA_SPI0
-#define S3C_PA_SPI1			S5PC100_PA_SPI1
-#define S3C_PA_SPI2			S5PC100_PA_SPI2
-
-#define S5P_PA_CHIPID			S5PC100_PA_CHIPID
-#define S5P_PA_FIMC0			S5PC100_PA_FIMC0
-#define S5P_PA_FIMC1			S5PC100_PA_FIMC1
-#define S5P_PA_FIMC2			S5PC100_PA_FIMC2
-#define S5P_PA_SDRAM			S5PC100_PA_SDRAM
-#define S5P_PA_SROMC			S5PC100_PA_SROMC
-#define S5P_PA_SYSCON			S5PC100_PA_SYSCON
-#define S5P_PA_TIMER			S5PC100_PA_TIMER
-
-#define SAMSUNG_PA_ADC			S5PC100_PA_TSADC
-#define SAMSUNG_PA_CFCON		S5PC100_PA_CFCON
-#define SAMSUNG_PA_KEYPAD		S5PC100_PA_KEYPAD
-#define SAMSUNG_PA_TIMER		S5PC100_PA_TIMER
-
-#define S5PC100_VA_OTHERS		(S3C_VA_SYS + 0x10000)
-
-#define S3C_SZ_ONENAND_BUF		(SZ_256M - SZ_32M)
-
-/* UART */
-
-#define S3C_PA_UART			S5PC100_PA_UART
-
-#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0			S5P_PA_UART(0)
-#define S5P_PA_UART1			S5P_PA_UART(1)
-#define S5P_PA_UART2			S5P_PA_UART(2)
-#define S5P_PA_UART3			S5P_PA_UART(3)
-
-#define S5P_SZ_UART			SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/regs-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PC100 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)		(S3C_VA_SYS + (x))
-
-#define S5PC100_REG_OTHERS(x)	(S5PC100_VA_OTHERS + (x))
-
-#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
-#define S5P_MPLL_LOCK		S5P_CLKREG(0x04)
-#define S5P_EPLL_LOCK		S5P_CLKREG(0x08)
-#define S5P_HPLL_LOCK		S5P_CLKREG(0x0C)
-
-#define S5P_APLL_CON		S5P_CLKREG(0x100)
-#define S5P_MPLL_CON		S5P_CLKREG(0x104)
-#define S5P_EPLL_CON		S5P_CLKREG(0x108)
-#define S5P_HPLL_CON		S5P_CLKREG(0x10C)
-
-#define S5P_CLK_SRC0		S5P_CLKREG(0x200)
-#define S5P_CLK_SRC1		S5P_CLKREG(0x204)
-#define S5P_CLK_SRC2		S5P_CLKREG(0x208)
-#define S5P_CLK_SRC3		S5P_CLKREG(0x20C)
-
-#define S5P_CLK_DIV0		S5P_CLKREG(0x300)
-#define S5P_CLK_DIV1		S5P_CLKREG(0x304)
-#define S5P_CLK_DIV2		S5P_CLKREG(0x308)
-#define S5P_CLK_DIV3		S5P_CLKREG(0x30C)
-#define S5P_CLK_DIV4		S5P_CLKREG(0x310)
-
-#define S5P_CLK_OUT		S5P_CLKREG(0x400)
-
-#define S5P_CLKGATE_D00		S5P_CLKREG(0x500)
-#define S5P_CLKGATE_D01		S5P_CLKREG(0x504)
-#define S5P_CLKGATE_D02		S5P_CLKREG(0x508)
-
-#define S5P_CLKGATE_D10		S5P_CLKREG(0x520)
-#define S5P_CLKGATE_D11		S5P_CLKREG(0x524)
-#define S5P_CLKGATE_D12		S5P_CLKREG(0x528)
-#define S5P_CLKGATE_D13		S5P_CLKREG(0x52C)
-#define S5P_CLKGATE_D14		S5P_CLKREG(0x530)
-#define S5P_CLKGATE_D15		S5P_CLKREG(0x534)
-
-#define S5P_CLKGATE_D20		S5P_CLKREG(0x540)
-
-#define S5P_CLKGATE_SCLK0	S5P_CLKREG(0x560)
-#define S5P_CLKGATE_SCLK1	S5P_CLKREG(0x564)
-
-/* CLKDIV0 */
-#define S5P_CLKDIV0_D0_MASK		(0x7<<8)
-#define S5P_CLKDIV0_D0_SHIFT		(8)
-#define S5P_CLKDIV0_PCLKD0_MASK		(0x7<<12)
-#define S5P_CLKDIV0_PCLKD0_SHIFT	(12)
-
-/* CLKDIV1 */
-#define S5P_CLKDIV1_D1_MASK		(0x7<<12)
-#define S5P_CLKDIV1_D1_SHIFT		(12)
-#define S5P_CLKDIV1_PCLKD1_MASK		(0x7<<16)
-#define S5P_CLKDIV1_PCLKD1_SHIFT	(16)
-
-#define S5PC100_SWRESET		S5PC100_REG_OTHERS(0x000)
-#define S5PC100_MEM_SYS_CFG	S5PC100_REG_OTHERS(0x200)
-
-#define S5PC100_SWRESET_RESETVAL	0xc100
-
-#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON	0x30
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* linux/arch/arm/plat-s5pc100/include/plat/regs-gpio.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - GPIO register definitions
- */
-
-#ifndef __ASM_MACH_S5PC100_REGS_GPIO_H
-#define __ASM_MACH_S5PC100_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-#define S5PC100EINT30CON		(S5P_VA_GPIO + 0xE00)
-#define S5P_EINT_CON(x)			(S5PC100EINT30CON + ((x) * 0x4))
-
-#define S5PC100EINT30FLTCON0		(S5P_VA_GPIO + 0xE80)
-#define S5P_EINT_FLTCON(x)		(S5PC100EINT30FLTCON0 + ((x) * 0x4))
-
-#define S5PC100EINT30MASK		(S5P_VA_GPIO + 0xF00)
-#define S5P_EINT_MASK(x)		(S5PC100EINT30MASK + ((x) * 0x4))
-
-#define S5PC100EINT30PEND		(S5P_VA_GPIO + 0xF40)
-#define S5P_EINT_PEND(x)		(S5PC100EINT30PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE		S3C_GPIO_SFN(0x2)
-
-#define EINT_GPIO_0(x)		S5PC100_GPH0(x)
-#define EINT_GPIO_1(x)		S5PC100_GPH1(x)
-#define EINT_GPIO_2(x)		S5PC100_GPH2(x)
-#define EINT_GPIO_3(x)		S5PC100_GPH3(x)
-
-#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-irq.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-irq.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/include/mach/regs-irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/regs-irq.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-# Copyright 2009 Samsung Electronics Co.
-#	Byungho Min <bhmin@samsung.com>
-#
-# Licensed under GPLv2
-
-# Configuration options for the S5PC100 CPU
-
-if ARCH_S5PC100
-
-config CPU_S5PC100
-	bool
-	select ARM_AMBA
-	select PL330_DMA if DMADEVICES
-	select S5P_EXT_INT
-	help
-	  Enable S5PC100 CPU support
-
-config S5PC100_SETUP_FB_24BPP
-	bool
-	help
-	  Common setup code for S5PC1XX with an 24bpp RGB display helper.
-
-config S5PC100_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S5PC100_SETUP_IDE
-	bool
-	help
-	  Common setup code for S5PC100 IDE GPIO configurations
-
-config S5PC100_SETUP_KEYPAD
-	bool
-	help
-	  Common setup code for KEYPAD GPIO configurations.
-
-config S5PC100_SETUP_SDHCI
-	bool
-	select S5PC100_SETUP_SDHCI_GPIO
-	help
-	  Internal helper functions for S5PC100 based SDHCI systems
-
-config S5PC100_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-config S5PC100_SETUP_SPI
-	bool
-	help
-	  Common setup code for SPI GPIO configurations.
-
-config MACH_SMDKC100
-	bool "SMDKC100"
-	select CPU_S5PC100
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_I2C1
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S5PC100_SETUP_FB_24BPP
-	select S5PC100_SETUP_I2C1
-	select S5PC100_SETUP_IDE
-	select S5PC100_SETUP_KEYPAD
-	select S5PC100_SETUP_SDHCI
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select SAMSUNG_DEV_ADC
-	select SAMSUNG_DEV_BACKLIGHT
-	select SAMSUNG_DEV_IDE
-	select SAMSUNG_DEV_KEYPAD
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_TS
-	help
-	  Machine support for the Samsung SMDKC100
-
-endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,264 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/mach-smdkc100.c
- *
- * Copyright 2009 Samsung Electronics Co.
- * Author: Byungho Min <bhmin@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/gpio-cfg.h>
-
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <plat/adc.h>
-#include <plat/keypad.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <linux/platform_data/asoc-s3c.h>
-#include <plat/backlight.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC100_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC100_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC100_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S3C2440_UFCON_RXTRIG8 |	\
-				 S3C2440_UFCON_TXTRIG16)
-
-static struct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = SMDKC100_UCON_DEFAULT,
-		.ulcon	     = SMDKC100_ULCON_DEFAULT,
-		.ufcon	     = SMDKC100_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = SMDKC100_UCON_DEFAULT,
-		.ulcon	     = SMDKC100_ULCON_DEFAULT,
-		.ufcon	     = SMDKC100_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = SMDKC100_UCON_DEFAULT,
-		.ulcon	     = SMDKC100_ULCON_DEFAULT,
-		.ufcon	     = SMDKC100_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport	     = 3,
-		.flags	     = 0,
-		.ucon	     = SMDKC100_UCON_DEFAULT,
-		.ulcon	     = SMDKC100_ULCON_DEFAULT,
-		.ufcon	     = SMDKC100_UFCON_DEFAULT,
-	},
-};
-
-/* I2C0 */
-static struct i2c_board_info i2c_devs0[] __initdata = {
-	{I2C_BOARD_INFO("wm8580", 0x1b),},
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c_devs1[] __initdata = {
-};
-
-/* LCD power controller */
-static void smdkc100_lcd_power_set(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-		/* module reset */
-		gpio_direction_output(S5PC100_GPH0(6), 1);
-		mdelay(100);
-		gpio_direction_output(S5PC100_GPH0(6), 0);
-		mdelay(10);
-		gpio_direction_output(S5PC100_GPH0(6), 1);
-		mdelay(10);
-	}
-}
-
-static struct plat_lcd_data smdkc100_lcd_power_data = {
-	.set_power	= smdkc100_lcd_power_set,
-};
-
-static struct platform_device smdkc100_lcd_powerdev = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &smdkc100_lcd_power_data,
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdkc100_fb_win0 = {
-	.max_bpp	= 32,
-	.default_bpp	= 16,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct fb_videomode smdkc100_lcd_timing = {
-	.left_margin	= 8,
-	.right_margin	= 13,
-	.upper_margin	= 7,
-	.lower_margin	= 5,
-	.hsync_len	= 3,
-	.vsync_len	= 1,
-	.xres		= 800,
-	.yres		= 480,
-	.refresh	= 80,
-};
-
-static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = {
-	.win[0]		= &smdkc100_fb_win0,
-	.vtiming	= &smdkc100_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= s5pc100_fb_gpio_setup_24bpp,
-};
-
-static struct s3c_ide_platdata smdkc100_ide_pdata __initdata = {
-	.setup_gpio	= s5pc100_ide_setup_gpio,
-};
-
-static uint32_t smdkc100_keymap[] __initdata = {
-	/* KEY(row, col, keycode) */
-	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
-	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
-	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
-	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
-};
-
-static struct matrix_keymap_data smdkc100_keymap_data __initdata = {
-	.keymap		= smdkc100_keymap,
-	.keymap_size	= ARRAY_SIZE(smdkc100_keymap),
-};
-
-static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = {
-	.keymap_data	= &smdkc100_keymap_data,
-	.rows		= 2,
-	.cols		= 8,
-};
-
-static struct platform_device *smdkc100_devices[] __initdata = {
-	&s3c_device_adc,
-	&s3c_device_cfcon,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_fb,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&samsung_device_pwm,
-	&s3c_device_ts,
-	&s3c_device_wdt,
-	&smdkc100_lcd_powerdev,
-	&s5pc100_device_iis0,
-	&samsung_device_keypad,
-	&s5pc100_device_ac97,
-	&s3c_device_rtc,
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5pc100_device_spdif,
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
-	.no = S5PC100_GPD(0),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc100_bl_data = {
-	.pwm_id = 0,
-	.enable_gpio = -1,
-};
-
-static void __init smdkc100_map_io(void)
-{
-	s5pc100_init_io(NULL, 0);
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdkc100_uartcfgs, ARRAY_SIZE(smdkc100_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init smdkc100_machine_init(void)
-{
-	s3c24xx_ts_set_platdata(NULL);
-
-	/* I2C */
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	s3c_fb_set_platdata(&smdkc100_lcd_pdata);
-	s3c_ide_set_platdata(&smdkc100_ide_pdata);
-
-	samsung_keypad_set_platdata(&smdkc100_keypad_data);
-
-	s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
-
-	/* LCD init */
-	gpio_request(S5PC100_GPH0(6), "GPH0");
-	smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
-
-	platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
-
-	samsung_bl_set(&smdkc100_bl_gpio_info, &smdkc100_bl_data);
-}
-
-MACHINE_START(SMDKC100, "SMDKC100")
-	/* Maintainer: Byungho Min <bhmin@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pc100_init_irq,
-	.map_io		= smdkc100_map_io,
-	.init_machine	= smdkc100_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5pc100_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-# arch/arm/mach-s5pc100/Makefile
-#
-# Copyright 2009 Samsung Electronics Co.
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core
-
-obj-y				+= common.o clock.o
-
-obj-y				+= dma.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDKC100)	+= mach-smdkc100.o
-
-# device support
-
-obj-y				+= dev-audio.o
-
-obj-y					+= setup-i2c0.o
-obj-$(CONFIG_S5PC100_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
-obj-$(CONFIG_S5PC100_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_S5PC100_SETUP_IDE)		+= setup-ide.o
-obj-$(CONFIG_S5PC100_SETUP_KEYPAD)	+= setup-keypad.o
-obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
-obj-$(CONFIG_S5PC100_SETUP_SPI)		+= setup-spi.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Makefile.boot linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Makefile.boot
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/Makefile.boot	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-   zreladdr-y	+= 0x20008000
-params_phys-y	:= 0x20000100
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-fb-24bpp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-fb-24bpp.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-fb-24bpp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-fb-24bpp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pc100/setup-fb-24bpp.c
- *
- * Copyright 2009 Samsung Electronics
- *
- * Base S5PC100 setup information for 24bpp LCD framebuffer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <plat/fb.h>
-#include <plat/gpio-cfg.h>
-
-#define DISR_OFFSET	0x7008
-
-static void s5pc100_fb_setgpios(unsigned int base, unsigned int nr)
-{
-	s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
-}
-
-void s5pc100_fb_gpio_setup_24bpp(void)
-{
-	s5pc100_fb_setgpios(S5PC100_GPF0(0), 8);
-	s5pc100_fb_setgpios(S5PC100_GPF1(0), 8);
-	s5pc100_fb_setgpios(S5PC100_GPF2(0), 8);
-	s5pc100_fb_setgpios(S5PC100_GPF3(0), 4);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-i2c0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-i2c0.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-i2c0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-i2c0.c
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * Base S5PC100 I2C bus 0 gpio configuration
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PC100_GPD(3), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-i2c1.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-i2c1.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-i2c1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-i2c1.c
- *
- * Copyright 2009 Samsung Electronics Co.
- *	Byungho Min <bhmin@samsung.com>
- *
- * Base S5PC100 I2C bus 1 gpio configuration
- *
- * Based on plat-s3c64xx/setup-i2c1.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PC100_GPD(5), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-ide.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-ide.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-ide.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-ide.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PC100 setup information for IDE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/regs-clock.h>
-#include <plat/gpio-cfg.h>
-
-static void s5pc100_ide_cfg_gpios(unsigned int base, unsigned int nr)
-{
-	s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
-
-	for (; nr > 0; nr--, base++)
-		s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-void s5pc100_ide_setup_gpio(void)
-{
-	u32 reg;
-
-	/* Independent CF interface, CF chip select configuration */
-	reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f);
-	writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG);
-
-	/* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
-	s5pc100_ide_cfg_gpios(S5PC100_GPJ0(0), 8);
-
-	/*CF_Data[0 - 7] */
-	s5pc100_ide_cfg_gpios(S5PC100_GPJ2(0), 8);
-
-	/* CF_Data[8 - 15] */
-	s5pc100_ide_cfg_gpios(S5PC100_GPJ3(0), 8);
-
-	/* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
-	s5pc100_ide_cfg_gpios(S5PC100_GPJ4(0), 4);
-
-	/* EBI_OE, EBI_WE */
-	s3c_gpio_cfgpin_range(S5PC100_GPK0(6), 2, S3C_GPIO_SFN(0));
-
-	/* CF_OE, CF_WE */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPK1(6), 8, S3C_GPIO_SFN(2));
-
-	/* CF_CD */
-	s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2));
-	s3c_gpio_setpull(S5PC100_GPK3(5), S3C_GPIO_PULL_NONE);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-keypad.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-keypad.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-keypad.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * GPIO configuration for S5PC100 KeyPad device
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
-{
-	/* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPH3(0), rows, S3C_GPIO_SFN(3));
-
-	/* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPH2(0), cols, S3C_GPIO_SFN(3));
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-sdhci-gpio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-sdhci-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s5pc100/setup-sdhci-gpio.c
- *
- * Copyright 2009 Samsung Eletronics
- *
- * S5PC100 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-
-void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int num;
-
-	num = width;
-	/* In case of 8 width, we should decrease the 2 */
-	if (width == 8)
-		num = width - 2;
-
-	/* Set all the necessary GPG0/GPG1 pins to special-function 0 */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPG0(0), 2 + num, S3C_GPIO_SFN(2));
-
-	if (width == 8)
-		s3c_gpio_cfgrange_nopull(S5PC100_GPG1(0), 2, S3C_GPIO_SFN(2));
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
-	}
-}
-
-void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG2 pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPG2(0), 2 + width, S3C_GPIO_SFN(2));
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
-	}
-}
-
-void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG3 pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PC100_GPG3(0), 2 + width, S3C_GPIO_SFN(2));
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-spi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-spi.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pc100/setup-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pc100/setup-spi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
-	s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
-				S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
-	s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
-				S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI2
-int s3c64xx_spi2_cfg_gpio(void)
-{
-	s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
-	s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgall_range(S5PC100_GPB(2), 2,
-				S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/clock.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/clock.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1365 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-static unsigned long xtal;
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources	= &clk_src_apll,
-	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources	= &clk_src_epll,
-	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-	},
-	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_armclk_list[] = {
-	[0] = &clk_mout_apll.clk,
-	[1] = &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_armclk = {
-	.sources	= clkset_armclk_list,
-	.nr_sources	= ARRAY_SIZE(clkset_armclk_list),
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-	},
-	.sources	= &clkset_armclk,
-	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_hclk_msys = {
-	.clk	= {
-		.name		= "hclk_msys",
-		.parent		= &clk_armclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_pclk_msys = {
-	.clk	= {
-		.name		= "pclk_msys",
-		.parent		= &clk_hclk_msys.clk,
-	},
-	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_sclk_a2m = {
-	.clk	= {
-		.name		= "sclk_a2m",
-		.parent		= &clk_mout_apll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
-};
-
-static struct clk *clkset_hclk_sys_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_a2m.clk,
-};
-
-static struct clksrc_sources clkset_hclk_sys = {
-	.sources	= clkset_hclk_sys_list,
-	.nr_sources	= ARRAY_SIZE(clkset_hclk_sys_list),
-};
-
-static struct clksrc_clk clk_hclk_dsys = {
-	.clk	= {
-		.name	= "hclk_dsys",
-	},
-	.sources	= &clkset_hclk_sys,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
-	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_dsys = {
-	.clk	= {
-		.name	= "pclk_dsys",
-		.parent	= &clk_hclk_dsys.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk clk_hclk_psys = {
-	.clk	= {
-		.name	= "hclk_psys",
-	},
-	.sources	= &clkset_hclk_sys,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
-	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_psys = {
-	.clk	= {
-		.name	= "pclk_psys",
-		.parent	= &clk_hclk_psys.clk,
-	},
-	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
-};
-
-static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
-}
-
-static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
-}
-
-static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
-}
-
-static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
-}
-
-static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
-}
-
-static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
-}
-
-static int s5pv210_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-static struct clk clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-};
-
-static struct clk clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static struct clk clk_pcmcdclk0 = {
-	.name		= "pcmcdclk",
-};
-
-static struct clk clk_pcmcdclk1 = {
-	.name		= "pcmcdclk",
-};
-
-static struct clk clk_pcmcdclk2 = {
-	.name		= "pcmcdclk",
-};
-
-static struct clk *clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources clkset_vpllsrc = {
-	.sources	= clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 7),
-	},
-	.sources	= &clkset_vpllsrc,
-	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
-};
-
-static struct clk *clkset_sclk_vpll_list[] = {
-	[0] = &clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources clkset_sclk_vpll = {
-	.sources	= clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources	= &clkset_sclk_vpll,
-	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
-};
-
-static struct clk *clkset_moutdmc0src_list[] = {
-	[0] = &clk_sclk_a2m.clk,
-	[1] = &clk_mout_mpll.clk,
-	[2] = NULL,
-	[3] = NULL,
-};
-
-static struct clksrc_sources clkset_moutdmc0src = {
-	.sources	= clkset_moutdmc0src_list,
-	.nr_sources	= ARRAY_SIZE(clkset_moutdmc0src_list),
-};
-
-static struct clksrc_clk clk_mout_dmc0 = {
-	.clk	= {
-		.name		= "mout_dmc0",
-	},
-	.sources	= &clkset_moutdmc0src,
-	.reg_src	= { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
-};
-
-static struct clksrc_clk clk_sclk_dmc0 = {
-	.clk	= {
-		.name		= "sclk_dmc0",
-		.parent		= &clk_mout_dmc0.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
-};
-
-static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
-{
-	return clk_get_rate(clk->parent) / 2;
-}
-
-static struct clk_ops clk_hclk_imem_ops = {
-	.get_rate	= s5pv210_clk_imem_get_rate,
-};
-
-static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk)
-{
-	return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
-}
-
-static struct clk_ops clk_fout_apll_ops = {
-	.get_rate	= s5pv210_clk_fout_apll_get_rate,
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "rot",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1<<29),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5pv210-fimc.0",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5pv210-fimc.1",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "fimc",
-		.devname	= "s5pv210-fimc.2",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "jpeg",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 28),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "dac",
-		.devname	= "s5p-sdo",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "mixer",
-		.devname	= "s5p-mixer",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "vp",
-		.devname	= "s5p-mixer",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "hdmi",
-		.devname	= "s5pv210-hdmi",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "s5pv210-hdmi",
-		.enable		= s5pv210_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "dacphy",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_dac_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "otg",
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<16),
-	}, {
-		.name		= "usb-host",
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<17),
-	}, {
-		.name		= "lcd",
-		.parent		= &clk_hclk_dsys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<0),
-	}, {
-		.name		= "cfcon",
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<25),
-	}, {
-		.name		= "systimer",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<16),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<22),
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<15),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pv210-spi.0",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<12),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pv210-spi.1",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<13),
-	}, {
-		.name		= "spi",
-		.devname	= "s5pv210-spi.2",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<14),
-	}, {
-		.name		= "timers",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<23),
-	}, {
-		.name		= "adc",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "keypad",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<21),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<4),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "spdif",
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "hclk_imem",
-		.parent		= &clk_hclk_msys.clk,
-		.ctrlbit	= (1 << 5),
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ops		= &clk_hclk_imem_ops,
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.parent		= &clk_pclk_psys.clk,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "sromc",
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1 << 26),
-	},
-};
-
-static struct clk clk_hsmmc0 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.0",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip2_ctrl,
-	.ctrlbit	= (1<<16),
-};
-
-static struct clk clk_hsmmc1 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.1",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip2_ctrl,
-	.ctrlbit	= (1<<17),
-};
-
-static struct clk clk_hsmmc2 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.2",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip2_ctrl,
-	.ctrlbit	= (1<<18),
-};
-
-static struct clk clk_hsmmc3 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.3",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip2_ctrl,
-	.ctrlbit	= (1<<19),
-};
-
-static struct clk clk_pdma0 = {
-	.name		= "pdma0",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip0_ctrl,
-	.ctrlbit	= (1 << 3),
-};
-
-static struct clk clk_pdma1 = {
-	.name		= "pdma1",
-	.parent		= &clk_hclk_psys.clk,
-	.enable		= s5pv210_clk_ip0_ctrl,
-	.ctrlbit	= (1 << 4),
-};
-
-static struct clk *clkset_uart_list[] = {
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_group1_list[] = {
-	[0] = &clk_sclk_a2m.clk,
-	[1] = &clk_mout_mpll.clk,
-	[2] = &clk_mout_epll.clk,
-	[3] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group1 = {
-	.sources	= clkset_group1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_sclk_onenand_list[] = {
-	[0] = &clk_hclk_psys.clk,
-	[1] = &clk_hclk_dsys.clk,
-};
-
-static struct clksrc_sources clkset_sclk_onenand = {
-	.sources	= clkset_sclk_onenand_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_onenand_list),
-};
-
-static struct clk *clkset_sclk_dac_list[] = {
-	[0] = &clk_sclk_vpll.clk,
-	[1] = &clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources clkset_sclk_dac = {
-	.sources	= clkset_sclk_dac_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk clk_sclk_dac = {
-	.clk		= {
-		.name		= "sclk_dac",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 2),
-	},
-	.sources	= &clkset_sclk_dac,
-	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_pixel = {
-	.clk		= {
-		.name		= "sclk_pixel",
-		.parent		= &clk_sclk_vpll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
-};
-
-static struct clk *clkset_sclk_hdmi_list[] = {
-	[0] = &clk_sclk_pixel.clk,
-	[1] = &clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources clkset_sclk_hdmi = {
-	.sources	= clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk clk_sclk_hdmi = {
-	.clk		= {
-		.name		= "sclk_hdmi",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources	= &clkset_sclk_hdmi,
-	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_sclk_mixer_list[] = {
-	[0] = &clk_sclk_dac.clk,
-	[1] = &clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources clkset_sclk_mixer = {
-	.sources	= clkset_sclk_mixer_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk clk_sclk_mixer = {
-	.clk		= {
-		.name		= "sclk_mixer",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 1),
-	},
-	.sources = &clkset_sclk_mixer,
-	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *sclk_tv[] = {
-	&clk_sclk_dac,
-	&clk_sclk_pixel,
-	&clk_sclk_hdmi,
-	&clk_sclk_mixer,
-};
-
-static struct clk *clkset_sclk_audio0_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_pcmcdclk0,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio0 = {
-	.sources	= clkset_sclk_audio0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
-	.clk		= {
-		.name		= "sclk_audio",
-		.devname	= "soc-audio.0",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.sources = &clkset_sclk_audio0,
-	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
-};
-
-static struct clk *clkset_sclk_audio1_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_pcmcdclk1,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio1 = {
-	.sources	= clkset_sclk_audio1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio1_list),
-};
-
-static struct clksrc_clk clk_sclk_audio1 = {
-	.clk		= {
-		.name		= "sclk_audio",
-		.devname	= "soc-audio.1",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 25),
-	},
-	.sources = &clkset_sclk_audio1,
-	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
-};
-
-static struct clk *clkset_sclk_audio2_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_pcmcdclk0,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio2 = {
-	.sources	= clkset_sclk_audio2_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio2_list),
-};
-
-static struct clksrc_clk clk_sclk_audio2 = {
-	.clk		= {
-		.name		= "sclk_audio",
-		.devname	= "soc-audio.2",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 26),
-	},
-	.sources = &clkset_sclk_audio2,
-	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
-};
-
-static struct clk *clkset_sclk_spdif_list[] = {
-	[0] = &clk_sclk_audio0.clk,
-	[1] = &clk_sclk_audio1.clk,
-	[2] = &clk_sclk_audio2.clk,
-};
-
-static struct clksrc_sources clkset_sclk_spdif = {
-	.sources	= clkset_sclk_spdif_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_spdif_list),
-};
-
-static struct clksrc_clk clk_sclk_spdif = {
-	.clk		= {
-		.name		= "sclk_spdif",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 27),
-		.ops		= &s5p_sclk_spdif_ops,
-	},
-	.sources = &clkset_sclk_spdif,
-	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
-};
-
-static struct clk *clkset_group2_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group2 = {
-	.sources	= clkset_group2_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group2_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_dmc",
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_onenand",
-		},
-		.sources = &clkset_sclk_onenand,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
-		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5pv210-fimc.0",
-			.enable		= s5pv210_clk_mask1_ctrl,
-			.ctrlbit	= (1 << 2),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5pv210-fimc.1",
-			.enable		= s5pv210_clk_mask1_ctrl,
-			.ctrlbit	= (1 << 3),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "s5pv210-fimc.2",
-			.enable		= s5pv210_clk_mask1_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam0",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 3),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam1",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 5),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-			.enable		= s5pv210_clk_ip0_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_g2d",
-			.enable		= s5pv210_clk_ip0_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_g3d",
-			.enable		= s5pv210_clk_ip0_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 6),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_pwi",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 29),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_pwm",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 19),
-		},
-		.sources = &clkset_group2,
-		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
-	},
-};
-
-static struct clksrc_clk clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "s5pv210-uart.0",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart1 = {
-	.clk		= {
-		.name		= "uclk1",
-		.devname	= "s5pv210-uart.1",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 13),
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart2 = {
-	.clk		= {
-		.name		= "uclk1",
-		.devname	= "s5pv210-uart.2",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 14),
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart3	= {
-	.clk		= {
-		.name		= "uclk1",
-		.devname	= "s5pv210-uart.3",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 15),
-	},
-	.sources = &clkset_uart,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
-	.clk		= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.0",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
-	.clk		= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.1",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 9),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
-	.clk		= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.2",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 10),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc3 = {
-	.clk		= {
-		.name		= "sclk_mmc",
-		.devname	= "s3c-sdhci.3",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 11),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
-	.clk		= {
-		.name		= "sclk_spi",
-		.devname	= "s5pv210-spi.0",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
-	};
-
-static struct clksrc_clk clk_sclk_spi1 = {
-	.clk		= {
-		.name		= "sclk_spi",
-		.devname	= "s5pv210-spi.1",
-		.enable		= s5pv210_clk_mask0_ctrl,
-		.ctrlbit	= (1 << 17),
-	},
-	.sources = &clkset_group2,
-	.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
-	};
-
-
-static struct clksrc_clk *clksrc_cdev[] = {
-	&clk_sclk_uart0,
-	&clk_sclk_uart1,
-	&clk_sclk_uart2,
-	&clk_sclk_uart3,
-	&clk_sclk_mmc0,
-	&clk_sclk_mmc1,
-	&clk_sclk_mmc2,
-	&clk_sclk_mmc3,
-	&clk_sclk_spi0,
-	&clk_sclk_spi1,
-};
-
-static struct clk *clk_cdev[] = {
-	&clk_hsmmc0,
-	&clk_hsmmc1,
-	&clk_hsmmc2,
-	&clk_hsmmc3,
-	&clk_pdma0,
-	&clk_pdma1,
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_armclk,
-	&clk_hclk_msys,
-	&clk_sclk_a2m,
-	&clk_hclk_dsys,
-	&clk_hclk_psys,
-	&clk_pclk_msys,
-	&clk_pclk_dsys,
-	&clk_pclk_psys,
-	&clk_vpllsrc,
-	&clk_sclk_vpll,
-	&clk_mout_dmc0,
-	&clk_sclk_dmc0,
-	&clk_sclk_audio0,
-	&clk_sclk_audio1,
-	&clk_sclk_audio2,
-	&clk_sclk_spdif,
-};
-
-static u32 epll_div[][6] = {
-	{  48000000, 0, 48, 3, 3, 0 },
-	{  96000000, 0, 48, 3, 2, 0 },
-	{ 144000000, 1, 72, 3, 2, 0 },
-	{ 192000000, 0, 48, 3, 1, 0 },
-	{ 288000000, 1, 72, 3, 1, 0 },
-	{  32750000, 1, 65, 3, 4, 35127 },
-	{  32768000, 1, 65, 3, 4, 35127 },
-	{  45158400, 0, 45, 3, 3, 10355 },
-	{  45000000, 0, 45, 3, 3, 10355 },
-	{  45158000, 0, 45, 3, 3, 10355 },
-	{  49125000, 0, 49, 3, 3, 9961 },
-	{  49152000, 0, 49, 3, 3, 9961 },
-	{  67737600, 1, 67, 3, 3, 48366 },
-	{  67738000, 1, 67, 3, 3, 48366 },
-	{  73800000, 1, 73, 3, 3, 47710 },
-	{  73728000, 1, 73, 3, 3, 47710 },
-	{  36000000, 1, 32, 3, 4, 0 },
-	{  60000000, 1, 60, 3, 3, 0 },
-	{  72000000, 1, 72, 3, 3, 0 },
-	{  80000000, 1, 80, 3, 3, 0 },
-	{  84000000, 0, 42, 3, 2, 0 },
-	{  50000000, 0, 50, 3, 3, 0 },
-};
-
-static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con, epll_con_k;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	epll_con = __raw_readl(S5P_EPLL_CON);
-	epll_con_k = __raw_readl(S5P_EPLL_CON1);
-
-	epll_con_k &= ~PLL46XX_KDIV_MASK;
-	epll_con &= ~(1 << 27 |
-			PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
-			PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
-			PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		if (epll_div[i][0] == rate) {
-			epll_con_k |= epll_div[i][5] << 0;
-			epll_con |= (epll_div[i][1] << 27 |
-					epll_div[i][2] << PLL46XX_MDIV_SHIFT |
-					epll_div[i][3] << PLL46XX_PDIV_SHIFT |
-					epll_div[i][4] << PLL46XX_SDIV_SHIFT);
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(epll_con, S5P_EPLL_CON);
-	__raw_writel(epll_con_k, S5P_EPLL_CON1);
-
-	printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
-			clk->rate, rate);
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops s5pv210_epll_ops = {
-	.set_rate = s5pv210_epll_set_rate,
-	.get_rate = s5p_epll_get_rate,
-};
-
-static u32 vpll_div[][5] = {
-	{  54000000, 3, 53, 3, 0 },
-	{ 108000000, 3, 53, 2, 0 },
-};
-
-static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int vpll_con;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	vpll_con = __raw_readl(S5P_VPLL_CON);
-	vpll_con &= ~(0x1 << 27 |					\
-			PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |	\
-			PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |	\
-			PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
-		if (vpll_div[i][0] == rate) {
-			vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
-			vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
-			vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
-			vpll_con |= vpll_div[i][4] << 27;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(vpll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(vpll_con, S5P_VPLL_CON);
-
-	/* Wait for VPLL lock */
-	while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
-		continue;
-
-	clk->rate = rate;
-	return 0;
-}
-static struct clk_ops s5pv210_vpll_ops = {
-	.get_rate = s5pv210_vpll_get_rate,
-	.set_rate = s5pv210_vpll_set_rate,
-};
-
-void __init_or_cpufreq s5pv210_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long vpllsrc;
-	unsigned long armclk;
-	unsigned long hclk_msys;
-	unsigned long hclk_dsys;
-	unsigned long hclk_psys;
-	unsigned long pclk_msys;
-	unsigned long pclk_dsys;
-	unsigned long pclk_psys;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
-	unsigned int ptr;
-	u32 clkdiv0, clkdiv1;
-
-	/* Set functions for clk_fout_epll */
-	clk_fout_epll.enable = s5p_epll_enable;
-	clk_fout_epll.ops = &s5pv210_epll_ops;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	clkdiv0 = __raw_readl(S5P_CLK_DIV0);
-	clkdiv1 = __raw_readl(S5P_CLK_DIV1);
-
-	printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
-				__func__, clkdiv0, clkdiv1);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
-	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON),
-				__raw_readl(S5P_EPLL_CON1), pll_4600);
-	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
-	vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
-
-	clk_fout_apll.ops = &clk_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.ops = &s5pv210_vpll_ops;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&clk_armclk.clk);
-	hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
-	hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
-	hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
-	pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
-	pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
-	pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
-
-	printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
-			 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
-			armclk, hclk_msys, hclk_dsys, hclk_psys,
-			pclk_msys, pclk_dsys, pclk_psys);
-
-	clk_f.rate = armclk;
-	clk_h.rate = hclk_psys;
-	clk_p.rate = pclk_psys;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	&clk_sclk_hdmi27m,
-	&clk_sclk_hdmiphy,
-	&clk_sclk_usbphy0,
-	&clk_sclk_usbphy1,
-	&clk_pcmcdclk0,
-	&clk_pcmcdclk1,
-	&clk_pcmcdclk2,
-};
-
-static struct clk_lookup s5pv210_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
-	CLKDEV_INIT("s5pv210-uart.0", "clk_uart_baud1", &clk_sclk_uart0.clk),
-	CLKDEV_INIT("s5pv210-uart.1", "clk_uart_baud1", &clk_sclk_uart1.clk),
-	CLKDEV_INIT("s5pv210-uart.2", "clk_uart_baud1", &clk_sclk_uart2.clk),
-	CLKDEV_INIT("s5pv210-uart.3", "clk_uart_baud1", &clk_sclk_uart3.clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
-	CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.0", &clk_hsmmc3),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
-	CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
-	CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-	CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-	CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1),
-};
-
-void __init s5pv210_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
-		s3c_register_clksrc(sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
-		s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	clkdev_add_table(s5pv210_clk_lookup, ARRAY_SIZE(s5pv210_clk_lookup));
-
-	s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
-		s3c_disable_clocks(clk_cdev[ptr], 1);
-
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/common.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/common.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Common Codes for S5PV210
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-
-#include <asm/proc-fns.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/ata-core.h>
-#include <plat/fb-core.h>
-#include <plat/fimc-core.h>
-#include <plat/iic-core.h>
-#include <plat/keypad-core.h>
-#include <plat/pwm-core.h>
-#include <plat/tv-core.h>
-#include <plat/spi-core.h>
-
-#include "common.h"
-
-static const char name_s5pv210[] = "S5PV210/S5PC110";
-
-static struct cpu_table cpu_ids[] __initdata = {
-	{
-		.idcode		= S5PV210_CPU_ID,
-		.idmask		= S5PV210_CPU_MASK,
-		.map_io		= s5pv210_map_io,
-		.init_clocks	= s5pv210_init_clocks,
-		.init_uarts	= s5pv210_init_uarts,
-		.init		= s5pv210_init,
-		.name		= name_s5pv210,
-	},
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5pv210_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_CHIPID,
-		.pfn		= __phys_to_pfn(S5PV210_PA_CHIPID),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_SYS,
-		.pfn		= __phys_to_pfn(S5PV210_PA_SYSCON),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_TIMER,
-		.pfn		= __phys_to_pfn(S5PV210_PA_TIMER),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
-		.pfn		= __phys_to_pfn(S5PV210_PA_WATCHDOG),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5PV210_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(S5PV210_PA_SYSTIMER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO,
-		.pfn		= __phys_to_pfn(S5PV210_PA_GPIO),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC0,
-		.pfn		= __phys_to_pfn(S5PV210_PA_VIC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC1,
-		.pfn		= __phys_to_pfn(S5PV210_PA_VIC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC2,
-		.pfn		= __phys_to_pfn(S5PV210_PA_VIC2),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC3,
-		.pfn		= __phys_to_pfn(S5PV210_PA_VIC3),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_DMC0,
-		.pfn		= __phys_to_pfn(S5PV210_PA_DMC0),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_DMC1,
-		.pfn		= __phys_to_pfn(S5PV210_PA_DMC1),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
-		.pfn		=__phys_to_pfn(S5PV210_PA_HSPHY),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}
-};
-
-void s5pv210_restart(enum reboot_mode mode, const char *cmd)
-{
-	__raw_writel(0x1, S5P_SWRESET);
-}
-
-static struct samsung_pwm_variant s5pv210_pwm_variant = {
-	.bits		= 32,
-	.div_base	= 0,
-	.has_tint_cstat	= true,
-	.tclk_mask	= (1 << 5),
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
-	s5pv210_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
-	s5pv210_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
-	unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
-		IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
-		IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
-	};
-
-	samsung_pwm_clocksource_init(S3C_VA_TIMER,
-					timer_irqs, &s5pv210_pwm_variant);
-}
-
-/*
- * s5pv210_map_io
- *
- * register the standard cpu IO areas
- */
-
-void __init s5pv210_init_io(struct map_desc *mach_desc, int size)
-{
-	/* initialize the io descriptors we need for initialization */
-	iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
-	if (mach_desc)
-		iotable_init(mach_desc, size);
-
-	/* detect cpu id and rev. */
-	s5p_init_cpu(S5P_VA_CHIPID);
-
-	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
-
-	samsung_pwm_set_platdata(&s5pv210_pwm_variant);
-}
-
-void __init s5pv210_map_io(void)
-{
-	/* initialise device information early */
-	s5pv210_default_sdhci0();
-	s5pv210_default_sdhci1();
-	s5pv210_default_sdhci2();
-	s5pv210_default_sdhci3();
-
-	s3c_adc_setname("samsung-adc-v3");
-
-	s3c_cfcon_setname("s5pv210-pata");
-
-	s3c_fimc_setname(0, "s5pv210-fimc");
-	s3c_fimc_setname(1, "s5pv210-fimc");
-	s3c_fimc_setname(2, "s5pv210-fimc");
-
-	/* the i2c devices are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-	s3c_i2c2_setname("s3c2440-i2c");
-
-	s3c_fb_setname("s5pv210-fb");
-
-	/* Use s5pv210-keypad instead of samsung-keypad */
-	samsung_keypad_setname("s5pv210-keypad");
-
-	/* setup TV devices */
-	s5p_hdmi_setname("s5pv210-hdmi");
-
-	s3c64xx_spi_setname("s5pv210-spi");
-}
-
-void __init s5pv210_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5pv210_register_clocks();
-	s5pv210_setup_clocks();
-}
-
-void __init s5pv210_init_irq(void)
-{
-	u32 vic[4];	/* S5PV210 supports 4 VIC */
-
-	/* All the VICs are fully populated. */
-	vic[0] = ~0;
-	vic[1] = ~0;
-	vic[2] = ~0;
-	vic[3] = ~0;
-
-	s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-struct bus_type s5pv210_subsys = {
-	.name		= "s5pv210-core",
-	.dev_name	= "s5pv210-core",
-};
-
-static struct device s5pv210_dev = {
-	.bus	= &s5pv210_subsys,
-};
-
-static int __init s5pv210_core_init(void)
-{
-	return subsys_system_register(&s5pv210_subsys, NULL);
-}
-core_initcall(s5pv210_core_init);
-
-int __init s5pv210_init(void)
-{
-	printk(KERN_INFO "S5PV210: Initializing architecture\n");
-	return device_register(&s5pv210_dev);
-}
-
-/* uart registration process */
-
-void __init s5pv210_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,19 +12,12 @@
 #ifndef __ARCH_ARM_MACH_S5PV210_COMMON_H
 #define __ARCH_ARM_MACH_S5PV210_COMMON_H
 
-#include <linux/reboot.h>
-
-void s5pv210_init_io(struct map_desc *mach_desc, int size);
-void s5pv210_init_irq(void);
-
-void s5pv210_register_clocks(void);
-void s5pv210_setup_clocks(void);
-
-void s5pv210_restart(enum reboot_mode mode, const char *cmd);
-
-extern  int s5pv210_init(void);
-extern void s5pv210_map_io(void);
-extern void s5pv210_init_clocks(int xtal);
-extern void s5pv210_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+#ifdef CONFIG_PM_SLEEP
+u32 exynos_get_eint_wake_mask(void);
+void s5pv210_cpu_resume(void);
+void s5pv210_pm_init(void);
+#else
+static inline void s5pv210_pm_init(void) {}
+#endif
 
 #endif /* __ARCH_ARM_MACH_S5PV210_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/dev-audio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/dev-audio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/dev-audio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-#define S5PV210_AUDSS_INT_MEM	(0xC0000000)
-
-static int s5pv210_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
-	.cfg_gpio = s5pv210_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
-					 | QUIRK_NEED_RSTCLR,
-			.idma_addr = S5PV210_AUDSS_INT_MEM,
-		},
-	},
-};
-
-static struct resource s5pv210_iis0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_IIS0, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
-	[3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
-};
-
-struct platform_device s5pv210_device_iis0 = {
-	.name = "samsung-i2s",
-	.id = 0,
-	.num_resources	  = ARRAY_SIZE(s5pv210_iis0_resource),
-	.resource	  = s5pv210_iis0_resource,
-	.dev = {
-		.platform_data = &i2sv5_pdata,
-	},
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
-	.cfg_gpio = s5pv210_cfg_i2s,
-};
-
-static struct resource s5pv210_iis1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_IIS1, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5pv210_device_iis1 = {
-	.name		  = "samsung-i2s",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5pv210_iis1_resource),
-	.resource	  = s5pv210_iis1_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-static struct resource s5pv210_iis2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_IIS2, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
-	[2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5pv210_device_iis2 = {
-	.name		  = "samsung-i2s",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s5pv210_iis2_resource),
-	.resource	  = s5pv210_iis2_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2));
-		break;
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = s5pv210_pcm_cfg_gpio,
-};
-
-static struct resource s5pv210_pcm0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_PCM0, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5pv210_device_pcm0 = {
-	.name		  = "samsung-pcm",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5pv210_pcm0_resource),
-	.resource	  = s5pv210_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv210_pcm1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_PCM1, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
-};
-
-struct platform_device s5pv210_device_pcm1 = {
-	.name		  = "samsung-pcm",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5pv210_pcm1_resource),
-	.resource	  = s5pv210_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv210_pcm2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_PCM2, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_PCM2_TX),
-	[2] = DEFINE_RES_DMA(DMACH_PCM2_RX),
-};
-
-struct platform_device s5pv210_device_pcm2 = {
-	.name		  = "samsung-pcm",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s5pv210_pcm2_resource),
-	.resource	  = s5pv210_pcm2_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
-{
-	return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pv210_ac97_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_AC97, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
-	[2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
-	[3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
-	[4] = DEFINE_RES_IRQ(IRQ_AC97),
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
-	.cfg_gpio = s5pv210_ac97_cfg_gpio,
-};
-
-static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv210_device_ac97 = {
-	.name		  = "samsung-ac97",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s5pv210_ac97_resource),
-	.resource	  = s5pv210_ac97_resource,
-	.dev = {
-		.platform_data = &s3c_ac97_pdata,
-		.dma_mask = &s5pv210_ac97_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-/* S/PDIF Controller platform_device */
-
-static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3));
-
-	return 0;
-}
-
-static struct resource s5pv210_spdif_resource[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_SPDIF, SZ_256),
-	[1] = DEFINE_RES_DMA(DMACH_SPDIF),
-};
-
-static struct s3c_audio_pdata samsung_spdif_pdata = {
-	.cfg_gpio = s5pv210_spdif_cfg_gpio,
-};
-
-static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv210_device_spdif = {
-	.name		= "samsung-spdif",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5pv210_spdif_resource),
-	.resource	= s5pv210_spdif_resource,
-	.dev = {
-		.platform_data = &samsung_spdif_pdata,
-		.dma_mask = &s5pv210_spdif_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/dma.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/dma.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/dma.h>
-
-static u8 pdma0_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_MAX,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_AC97_MICIN,
-	DMACH_AC97_PCMIN,
-	DMACH_AC97_PCMOUT,
-	DMACH_MAX,
-	DMACH_PWM,
-	DMACH_SPDIF,
-};
-
-static struct dma_pl330_platdata s5pv210_pdma0_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
-	.peri_id = pdma0_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pv210_pdma0, "dma-pl330.0", 0x00041330,
-	S5PV210_PA_PDMA0, {IRQ_PDMA0}, &s5pv210_pdma0_pdata);
-
-static u8 pdma1_peri[] = {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_MAX,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_I2S2_RX,
-	DMACH_I2S2_TX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_MAX,
-	DMACH_MAX,
-	DMACH_PCM0_RX,
-	DMACH_PCM0_TX,
-	DMACH_PCM1_RX,
-	DMACH_PCM1_TX,
-	DMACH_MSM_REQ0,
-	DMACH_MSM_REQ1,
-	DMACH_MSM_REQ2,
-	DMACH_MSM_REQ3,
-	DMACH_PCM2_RX,
-	DMACH_PCM2_TX,
-};
-
-static struct dma_pl330_platdata s5pv210_pdma1_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
-	.peri_id = pdma1_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pv210_pdma1, "dma-pl330.1", 0x00041330,
-	S5PV210_PA_PDMA1, {IRQ_PDMA1}, &s5pv210_pdma1_pdata);
-
-static int __init s5pv210_dma_init(void)
-{
-	dma_cap_set(DMA_SLAVE, s5pv210_pdma0_pdata.cap_mask);
-	dma_cap_set(DMA_CYCLIC, s5pv210_pdma0_pdata.cap_mask);
-	amba_device_register(&s5pv210_pdma0_device, &iomem_resource);
-
-	dma_cap_set(DMA_SLAVE, s5pv210_pdma1_pdata.cap_mask);
-	dma_cap_set(DMA_CYCLIC, s5pv210_pdma1_pdata.cap_mask);
-	amba_device_register(&s5pv210_pdma1_device, &iomem_resource);
-
-	return 0;
-}
-arch_initcall(s5pv210_dma_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/debug-macro.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <linux/serial_s3c.h>
-#include <mach/map.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rp, rv, tmp
-		ldr	\rp, = S3C_PA_UART
-		ldr	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-#define fifo_full fifo_full_s5pv210
-#define fifo_level fifo_level_s5pv210
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <debug/samsung.S>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/dma.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/dma.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common DMA API driver for PL330 */
-#include <plat/dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* Practically, GPIO banks up to MP03 are the configurable gpio banks */
-
-/* GPIO bank sizes */
-#define S5PV210_GPIO_A0_NR	(8)
-#define S5PV210_GPIO_A1_NR	(4)
-#define S5PV210_GPIO_B_NR	(8)
-#define S5PV210_GPIO_C0_NR	(5)
-#define S5PV210_GPIO_C1_NR	(5)
-#define S5PV210_GPIO_D0_NR	(4)
-#define S5PV210_GPIO_D1_NR	(6)
-#define S5PV210_GPIO_E0_NR	(8)
-#define S5PV210_GPIO_E1_NR	(5)
-#define S5PV210_GPIO_F0_NR	(8)
-#define S5PV210_GPIO_F1_NR	(8)
-#define S5PV210_GPIO_F2_NR	(8)
-#define S5PV210_GPIO_F3_NR	(6)
-#define S5PV210_GPIO_G0_NR	(7)
-#define S5PV210_GPIO_G1_NR	(7)
-#define S5PV210_GPIO_G2_NR	(7)
-#define S5PV210_GPIO_G3_NR	(7)
-#define S5PV210_GPIO_H0_NR	(8)
-#define S5PV210_GPIO_H1_NR	(8)
-#define S5PV210_GPIO_H2_NR	(8)
-#define S5PV210_GPIO_H3_NR	(8)
-#define S5PV210_GPIO_I_NR	(7)
-#define S5PV210_GPIO_J0_NR	(8)
-#define S5PV210_GPIO_J1_NR	(6)
-#define S5PV210_GPIO_J2_NR	(8)
-#define S5PV210_GPIO_J3_NR	(8)
-#define S5PV210_GPIO_J4_NR	(5)
-
-#define S5PV210_GPIO_MP01_NR	(8)
-#define S5PV210_GPIO_MP02_NR	(4)
-#define S5PV210_GPIO_MP03_NR	(8)
-#define S5PV210_GPIO_MP04_NR	(8)
-#define S5PV210_GPIO_MP05_NR	(8)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5PV210_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	S5PV210_GPIO_A0_START	= 0,
-	S5PV210_GPIO_A1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_A0),
-	S5PV210_GPIO_B_START 	= S5PV210_GPIO_NEXT(S5PV210_GPIO_A1),
-	S5PV210_GPIO_C0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_B),
-	S5PV210_GPIO_C1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_C0),
-	S5PV210_GPIO_D0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_C1),
-	S5PV210_GPIO_D1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_D0),
-	S5PV210_GPIO_E0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_D1),
-	S5PV210_GPIO_E1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_E0),
-	S5PV210_GPIO_F0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_E1),
-	S5PV210_GPIO_F1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F0),
-	S5PV210_GPIO_F2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F1),
-	S5PV210_GPIO_F3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F2),
-	S5PV210_GPIO_G0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F3),
-	S5PV210_GPIO_G1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G0),
-	S5PV210_GPIO_G2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G1),
-	S5PV210_GPIO_G3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G2),
-	S5PV210_GPIO_H0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G3),
-	S5PV210_GPIO_H1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H0),
-	S5PV210_GPIO_H2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H1),
-	S5PV210_GPIO_H3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H2),
-	S5PV210_GPIO_I_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H3),
-	S5PV210_GPIO_J0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_I),
-	S5PV210_GPIO_J1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J0),
-	S5PV210_GPIO_J2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),
-	S5PV210_GPIO_J3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J2),
-	S5PV210_GPIO_J4_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J3),
-	S5PV210_GPIO_MP01_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J4),
-	S5PV210_GPIO_MP02_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01),
-	S5PV210_GPIO_MP03_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02),
-	S5PV210_GPIO_MP04_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03),
-	S5PV210_GPIO_MP05_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP04),
-};
-
-/* S5PV210 GPIO number definitions */
-#define S5PV210_GPA0(_nr)	(S5PV210_GPIO_A0_START + (_nr))
-#define S5PV210_GPA1(_nr)	(S5PV210_GPIO_A1_START + (_nr))
-#define S5PV210_GPB(_nr)	(S5PV210_GPIO_B_START + (_nr))
-#define S5PV210_GPC0(_nr)	(S5PV210_GPIO_C0_START + (_nr))
-#define S5PV210_GPC1(_nr)	(S5PV210_GPIO_C1_START + (_nr))
-#define S5PV210_GPD0(_nr)	(S5PV210_GPIO_D0_START + (_nr))
-#define S5PV210_GPD1(_nr)	(S5PV210_GPIO_D1_START + (_nr))
-#define S5PV210_GPE0(_nr)	(S5PV210_GPIO_E0_START + (_nr))
-#define S5PV210_GPE1(_nr)	(S5PV210_GPIO_E1_START + (_nr))
-#define S5PV210_GPF0(_nr)	(S5PV210_GPIO_F0_START + (_nr))
-#define S5PV210_GPF1(_nr)	(S5PV210_GPIO_F1_START + (_nr))
-#define S5PV210_GPF2(_nr)	(S5PV210_GPIO_F2_START + (_nr))
-#define S5PV210_GPF3(_nr)	(S5PV210_GPIO_F3_START + (_nr))
-#define S5PV210_GPG0(_nr)	(S5PV210_GPIO_G0_START + (_nr))
-#define S5PV210_GPG1(_nr)	(S5PV210_GPIO_G1_START + (_nr))
-#define S5PV210_GPG2(_nr)	(S5PV210_GPIO_G2_START + (_nr))
-#define S5PV210_GPG3(_nr)	(S5PV210_GPIO_G3_START + (_nr))
-#define S5PV210_GPH0(_nr)	(S5PV210_GPIO_H0_START + (_nr))
-#define S5PV210_GPH1(_nr)	(S5PV210_GPIO_H1_START + (_nr))
-#define S5PV210_GPH2(_nr)	(S5PV210_GPIO_H2_START + (_nr))
-#define S5PV210_GPH3(_nr)	(S5PV210_GPIO_H3_START + (_nr))
-#define S5PV210_GPI(_nr)	(S5PV210_GPIO_I_START + (_nr))
-#define S5PV210_GPJ0(_nr)	(S5PV210_GPIO_J0_START + (_nr))
-#define S5PV210_GPJ1(_nr)	(S5PV210_GPIO_J1_START + (_nr))
-#define S5PV210_GPJ2(_nr)	(S5PV210_GPIO_J2_START + (_nr))
-#define S5PV210_GPJ3(_nr)	(S5PV210_GPIO_J3_START + (_nr))
-#define S5PV210_GPJ4(_nr)	(S5PV210_GPIO_J4_START + (_nr))
-#define S5PV210_MP01(_nr)	(S5PV210_GPIO_MP01_START + (_nr))
-#define S5PV210_MP02(_nr)	(S5PV210_GPIO_MP02_START + (_nr))
-#define S5PV210_MP03(_nr)	(S5PV210_GPIO_MP03_START + (_nr))
-#define S5PV210_MP04(_nr)	(S5PV210_GPIO_MP04_START + (_nr))
-#define S5PV210_MP05(_nr)	(S5PV210_GPIO_MP05_START + (_nr))
-
-/* the end of the S5PV210 specific gpios */
-#define S5PV210_GPIO_END	(S5PV210_MP05(S5PV210_GPIO_MP05_NR) + 1)
-#define S3C_GPIO_END		S5PV210_GPIO_END
-
-/* define the number of gpios we need to the one after the MP05() range */
-#define ARCH_NR_GPIOS		(S5PV210_MP05(S5PV210_GPIO_MP05_NR) +	\
-				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/hardware.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/hardware.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/hardware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/hardware.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - Hardware support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,137 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/irqs.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0: System, DMA, Timer */
-
-#define IRQ_EINT16_31		S5P_IRQ_VIC0(16)
-#define IRQ_BATF		S5P_IRQ_VIC0(17)
-#define IRQ_MDMA		S5P_IRQ_VIC0(18)
-#define IRQ_PDMA0		S5P_IRQ_VIC0(19)
-#define IRQ_PDMA1		S5P_IRQ_VIC0(20)
-#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(21)
-#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(22)
-#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(23)
-#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(24)
-#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(25)
-#define IRQ_SYSTIMER		S5P_IRQ_VIC0(26)
-#define IRQ_WDT			S5P_IRQ_VIC0(27)
-#define IRQ_RTC_ALARM		S5P_IRQ_VIC0(28)
-#define IRQ_RTC_TIC		S5P_IRQ_VIC0(29)
-#define IRQ_GPIOINT		S5P_IRQ_VIC0(30)
-#define IRQ_FIMC3		S5P_IRQ_VIC0(31)
-
-/* VIC1: ARM, Power, Memory, Connectivity, Storage */
-
-#define IRQ_PMU			S5P_IRQ_VIC1(0)
-#define IRQ_CORTEX1		S5P_IRQ_VIC1(1)
-#define IRQ_CORTEX2		S5P_IRQ_VIC1(2)
-#define IRQ_CORTEX3		S5P_IRQ_VIC1(3)
-#define IRQ_CORTEX4		S5P_IRQ_VIC1(4)
-#define IRQ_IEMAPC		S5P_IRQ_VIC1(5)
-#define IRQ_IEMIEC		S5P_IRQ_VIC1(6)
-#define IRQ_ONENAND		S5P_IRQ_VIC1(7)
-#define IRQ_NFC			S5P_IRQ_VIC1(8)
-#define IRQ_CFCON		S5P_IRQ_VIC1(9)
-#define IRQ_UART0		S5P_IRQ_VIC1(10)
-#define IRQ_UART1		S5P_IRQ_VIC1(11)
-#define IRQ_UART2		S5P_IRQ_VIC1(12)
-#define IRQ_UART3		S5P_IRQ_VIC1(13)
-#define IRQ_IIC			S5P_IRQ_VIC1(14)
-#define IRQ_SPI0		S5P_IRQ_VIC1(15)
-#define IRQ_SPI1		S5P_IRQ_VIC1(16)
-#define IRQ_SPI2		S5P_IRQ_VIC1(17)
-#define IRQ_IRDA		S5P_IRQ_VIC1(18)
-#define IRQ_IIC2		S5P_IRQ_VIC1(19)
-#define IRQ_IIC_HDMIPHY		S5P_IRQ_VIC1(20)
-#define IRQ_HSIRX		S5P_IRQ_VIC1(21)
-#define IRQ_HSITX		S5P_IRQ_VIC1(22)
-#define IRQ_UHOST		S5P_IRQ_VIC1(23)
-#define IRQ_OTG			S5P_IRQ_VIC1(24)
-#define IRQ_MSM			S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC0		S5P_IRQ_VIC1(26)
-#define IRQ_HSMMC1		S5P_IRQ_VIC1(27)
-#define IRQ_HSMMC2		S5P_IRQ_VIC1(28)
-#define IRQ_MIPI_CSIS		S5P_IRQ_VIC1(29)
-#define IRQ_MIPIDSI		S5P_IRQ_VIC1(30)
-#define IRQ_ONENAND_AUDI	S5P_IRQ_VIC1(31)
-
-/* VIC2: Multimedia, Audio, Security */
-
-#define IRQ_LCD0		S5P_IRQ_VIC2(0)
-#define IRQ_LCD1		S5P_IRQ_VIC2(1)
-#define IRQ_LCD2		S5P_IRQ_VIC2(2)
-#define IRQ_LCD3		S5P_IRQ_VIC2(3)
-#define IRQ_ROTATOR		S5P_IRQ_VIC2(4)
-#define IRQ_FIMC0		S5P_IRQ_VIC2(5)
-#define IRQ_FIMC1		S5P_IRQ_VIC2(6)
-#define IRQ_FIMC2		S5P_IRQ_VIC2(7)
-#define IRQ_JPEG		S5P_IRQ_VIC2(8)
-#define IRQ_2D			S5P_IRQ_VIC2(9)
-#define IRQ_3D			S5P_IRQ_VIC2(10)
-#define IRQ_MIXER		S5P_IRQ_VIC2(11)
-#define IRQ_HDMI		S5P_IRQ_VIC2(12)
-#define IRQ_IIC1		S5P_IRQ_VIC2(13)
-#define IRQ_MFC			S5P_IRQ_VIC2(14)
-#define IRQ_SDO			S5P_IRQ_VIC2(15)
-#define IRQ_I2S0		S5P_IRQ_VIC2(16)
-#define IRQ_I2S1		S5P_IRQ_VIC2(17)
-#define IRQ_I2S2		S5P_IRQ_VIC2(18)
-#define IRQ_AC97		S5P_IRQ_VIC2(19)
-#define IRQ_PCM0		S5P_IRQ_VIC2(20)
-#define IRQ_PCM1		S5P_IRQ_VIC2(21)
-#define IRQ_SPDIF		S5P_IRQ_VIC2(22)
-#define IRQ_ADC			S5P_IRQ_VIC2(23)
-#define IRQ_PENDN		S5P_IRQ_VIC2(24)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_KEYPAD		S5P_IRQ_VIC2(25)
-#define IRQ_CG			S5P_IRQ_VIC2(26)
-#define IRQ_SSS_INT		S5P_IRQ_VIC2(27)
-#define IRQ_SSS_HASH		S5P_IRQ_VIC2(28)
-#define IRQ_PCM2		S5P_IRQ_VIC2(29)
-#define IRQ_SDMIRQ		S5P_IRQ_VIC2(30)
-#define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
-
-/* VIC3: Etc */
-
-#define IRQ_IPC			S5P_IRQ_VIC3(0)
-#define IRQ_HOSTIF		S5P_IRQ_VIC3(1)
-#define IRQ_HSMMC3		S5P_IRQ_VIC3(2)
-#define IRQ_CEC			S5P_IRQ_VIC3(3)
-#define IRQ_TSI			S5P_IRQ_VIC3(4)
-#define IRQ_MDNIE0		S5P_IRQ_VIC3(5)
-#define IRQ_MDNIE1		S5P_IRQ_VIC3(6)
-#define IRQ_MDNIE2		S5P_IRQ_VIC3(7)
-#define IRQ_MDNIE3		S5P_IRQ_VIC3(8)
-#define IRQ_VIC_END		S5P_IRQ_VIC3(31)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
-#define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
-
-/* GPIO interrupt */
-#define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
-#define S5P_GPIOINT_GROUP_MAXNR	22
-
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
-
-/* Compatibility */
-#define IRQ_LCD_FIFO		IRQ_LCD0
-#define IRQ_LCD_VSYNC		IRQ_LCD1
-#define IRQ_LCD_SYSTEM		IRQ_LCD2
-#define IRQ_MIPI_CSIS0		IRQ_MIPI_CSIS
-
-#endif /* ASM_ARCH_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/map.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/map.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/map.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,158 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/map.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5PV210_PA_SDRAM		0x20000000
-
-#define S5PV210_PA_SROM_BANK5		0xA8000000
-
-#define S5PC110_PA_ONENAND		0xB0000000
-#define S5PC110_PA_ONENAND_DMA		0xB0600000
-
-#define S5PV210_PA_CHIPID		0xE0000000
-
-#define S5PV210_PA_SYSCON		0xE0100000
-
-#define S5PV210_PA_GPIO			0xE0200000
-
-#define S5PV210_PA_SPDIF		0xE1100000
-
-#define S5PV210_PA_SPI0			0xE1300000
-#define S5PV210_PA_SPI1			0xE1400000
-
-#define S5PV210_PA_KEYPAD		0xE1600000
-
-#define S5PV210_PA_ADC			0xE1700000
-
-#define S5PV210_PA_IIC0			0xE1800000
-#define S5PV210_PA_IIC1			0xFAB00000
-#define S5PV210_PA_IIC2			0xE1A00000
-
-#define S5PV210_PA_AC97			0xE2200000
-
-#define S5PV210_PA_PCM0			0xE2300000
-#define S5PV210_PA_PCM1			0xE1200000
-#define S5PV210_PA_PCM2			0xE2B00000
-
-#define S5PV210_PA_TIMER		0xE2500000
-#define S5PV210_PA_SYSTIMER		0xE2600000
-#define S5PV210_PA_WATCHDOG		0xE2700000
-#define S5PV210_PA_RTC			0xE2800000
-
-#define S5PV210_PA_UART			0xE2900000
-
-#define S5PV210_PA_SROMC		0xE8000000
-
-#define S5PV210_PA_CFCON		0xE8200000
-
-#define S5PV210_PA_MFC			0xF1700000
-
-#define S5PV210_PA_HSMMC(x)		(0xEB000000 + ((x) * 0x100000))
-
-#define S5PV210_PA_HSOTG		0xEC000000
-#define S5PV210_PA_HSPHY		0xEC100000
-
-#define S5PV210_PA_IIS0			0xEEE30000
-#define S5PV210_PA_IIS1			0xE2100000
-#define S5PV210_PA_IIS2			0xE2A00000
-
-#define S5PV210_PA_DMC0			0xF0000000
-#define S5PV210_PA_DMC1			0xF1400000
-
-#define S5PV210_PA_VIC0			0xF2000000
-#define S5PV210_PA_VIC1			0xF2100000
-#define S5PV210_PA_VIC2			0xF2200000
-#define S5PV210_PA_VIC3			0xF2300000
-
-#define S5PV210_PA_FB			0xF8000000
-
-#define S5PV210_PA_MDMA			0xFA200000
-#define S5PV210_PA_PDMA0		0xE0900000
-#define S5PV210_PA_PDMA1		0xE0A00000
-
-#define S5PV210_PA_MIPI_CSIS		0xFA600000
-
-#define S5PV210_PA_FIMC0		0xFB200000
-#define S5PV210_PA_FIMC1		0xFB300000
-#define S5PV210_PA_FIMC2		0xFB400000
-
-#define S5PV210_PA_JPEG			0xFB600000
-
-#define S5PV210_PA_SDO			0xF9000000
-#define S5PV210_PA_VP			0xF9100000
-#define S5PV210_PA_MIXER		0xF9200000
-#define S5PV210_PA_HDMI			0xFA100000
-#define S5PV210_PA_IIC_HDMIPHY		0xFA900000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_FB			S5PV210_PA_FB
-#define S3C_PA_HSMMC0			S5PV210_PA_HSMMC(0)
-#define S3C_PA_HSMMC1			S5PV210_PA_HSMMC(1)
-#define S3C_PA_HSMMC2			S5PV210_PA_HSMMC(2)
-#define S3C_PA_HSMMC3			S5PV210_PA_HSMMC(3)
-#define S3C_PA_IIC			S5PV210_PA_IIC0
-#define S3C_PA_IIC1			S5PV210_PA_IIC1
-#define S3C_PA_IIC2			S5PV210_PA_IIC2
-#define S3C_PA_RTC			S5PV210_PA_RTC
-#define S3C_PA_USB_HSOTG		S5PV210_PA_HSOTG
-#define S3C_PA_WDT			S5PV210_PA_WATCHDOG
-#define S3C_PA_SPI0			S5PV210_PA_SPI0
-#define S3C_PA_SPI1			S5PV210_PA_SPI1
-
-#define S5P_PA_CHIPID			S5PV210_PA_CHIPID
-#define S5P_PA_FIMC0			S5PV210_PA_FIMC0
-#define S5P_PA_FIMC1			S5PV210_PA_FIMC1
-#define S5P_PA_FIMC2			S5PV210_PA_FIMC2
-#define S5P_PA_MIPI_CSIS0		S5PV210_PA_MIPI_CSIS
-#define S5P_PA_MFC			S5PV210_PA_MFC
-#define S5P_PA_IIC_HDMIPHY		S5PV210_PA_IIC_HDMIPHY
-
-#define S5P_PA_SDO			S5PV210_PA_SDO
-#define S5P_PA_VP			S5PV210_PA_VP
-#define S5P_PA_MIXER			S5PV210_PA_MIXER
-#define S5P_PA_HDMI			S5PV210_PA_HDMI
-
-#define S5P_PA_ONENAND			S5PC110_PA_ONENAND
-#define S5P_PA_ONENAND_DMA		S5PC110_PA_ONENAND_DMA
-#define S5P_PA_SDRAM			S5PV210_PA_SDRAM
-#define S5P_PA_SROMC			S5PV210_PA_SROMC
-#define S5P_PA_SYSCON			S5PV210_PA_SYSCON
-#define S5P_PA_TIMER			S5PV210_PA_TIMER
-
-#define S5P_PA_JPEG			S5PV210_PA_JPEG
-
-#define SAMSUNG_PA_ADC			S5PV210_PA_ADC
-#define SAMSUNG_PA_CFCON		S5PV210_PA_CFCON
-#define SAMSUNG_PA_KEYPAD		S5PV210_PA_KEYPAD
-#define SAMSUNG_PA_TIMER		S5PV210_PA_TIMER
-
-/* UART */
-
-#define S3C_VA_UARTx(x)			(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-
-#define S3C_PA_UART			S5PV210_PA_UART
-
-#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0			S5P_PA_UART(0)
-#define S5P_PA_UART1			S5P_PA_UART(1)
-#define S5P_PA_UART2			S5P_PA_UART(2)
-#define S5P_PA_UART3			S5P_PA_UART(3)
-
-#define S5P_SZ_UART			SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/memory.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-
-/*
- * Sparsemem support
- * Physical memory can be located from 0x20000000 to 0x7fffffff,
- * so MAX_PHYSMEM_BITS is 31.
- */
-
-#define MAX_PHYSMEM_BITS	31
-#define SECTION_SIZE_BITS	28
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-static inline void s3c_pm_debug_init_uart(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
-	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
-	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_show_resume_irqs(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-					   struct pm_uart_save *save)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_restored_gpios(void) { }
-static inline void samsung_pm_saved_gpios(void) { }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_REGS_CLOCK_H
 #define __ASM_ARCH_REGS_CLOCK_H __FILE__
 
-#include <mach/map.h>
+#include <plat/map-base.h>
 
 #define S5P_CLKREG(x)		(S3C_VA_SYS + (x))
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-gpio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV210 - GPIO (including EINT) register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-#define S5PV210_EINT30CON		(S5P_VA_GPIO + 0xE00)
-#define S5P_EINT_CON(x)			(S5PV210_EINT30CON + ((x) * 0x4))
-
-#define S5PV210_EINT30FLTCON0		(S5P_VA_GPIO + 0xE80)
-#define S5P_EINT_FLTCON(x)		(S5PV210_EINT30FLTCON0 + ((x) * 0x4))
-
-#define S5PV210_EINT30MASK		(S5P_VA_GPIO + 0xF00)
-#define S5P_EINT_MASK(x)		(S5PV210_EINT30MASK + ((x) * 0x4))
-
-#define S5PV210_EINT30PEND		(S5P_VA_GPIO + 0xF40)
-#define S5P_EINT_PEND(x)		(S5PV210_EINT30PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE		S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x)		S5PV210_GPH0(x)
-#define EINT_GPIO_1(x)		S5PV210_GPH1(x)
-#define EINT_GPIO_2(x)		S5PV210_GPH2(x)
-#define EINT_GPIO_3(x)		S5PV210_GPH3(x)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-irq.h linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-irq.h
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/include/mach/regs-irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/regs-irq.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -7,193 +7,28 @@
 
 # Configuration options for the S5PV210/S5PC110
 
+config ARCH_S5PV210
+	bool "Samsung S5PV210/S5PC110" if ARCH_MULTI_V7
+	select ARCH_HAS_HOLES_MEMORYMODEL
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_VIC
+	select CLKSRC_SAMSUNG_PWM
+	select COMMON_CLK_SAMSUNG
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select HAVE_S3C_RTC if RTC_CLASS
+	select PINCTRL
+	select PINCTRL_EXYNOS
+	help
+	  Samsung S5PV210/S5PC110 series based systems
+
 if ARCH_S5PV210
 
 config CPU_S5PV210
-	bool
+	def_bool y
 	select ARM_AMBA
 	select PL330_DMA if DMADEVICES
-	select S5P_EXT_INT
-	select S5P_PM if PM
-	select S5P_SLEEP if PM
 	help
 	  Enable S5PV210 CPU support
 
-config S5PV210_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S5PV210_SETUP_I2C2
-	bool
-	help
-	  Common setup code for i2c bus 2.
-
-config S5PV210_SETUP_IDE
-	bool
-	help
-	  Common setup code for S5PV210 IDE GPIO configurations
-
-config S5PV210_SETUP_FB_24BPP
-	bool
-	help
-          Common setup code for S5PV210 with an 24bpp RGB display helper.
-
-config S5PV210_SETUP_KEYPAD
-	bool
-	help
-	  Common setup code for keypad.
-
-config S5PV210_SETUP_SDHCI
-        bool
-        select S5PV210_SETUP_SDHCI_GPIO
-        help
-          Internal helper functions for S5PV210 based SDHCI systems
-
-config S5PV210_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-config S5PV210_SETUP_FIMC
-	bool
-	help
-	  Common setup code for the camera interfaces.
-
-config S5PV210_SETUP_SPI
-	bool
-	help
-	  Common setup code for SPI GPIO configurations.
-
-config S5PV210_SETUP_USB_PHY
-	bool
-	help
-	  Common setup code for USB PHY controller
-
-menu "S5PC110 Machines"
-
-config MACH_AQUILA
-	bool "Aquila"
-	select CPU_S5PV210
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S5PV210_SETUP_FB_24BPP
-	select S5PV210_SETUP_SDHCI
-	select S5PV210_SETUP_USB_PHY
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_ONENAND
-	help
-	  Machine support for the Samsung Aquila target based on S5PC110 SoC
-
-config MACH_GONI
-	bool "GONI"
-	select CPU_S5PV210
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C2
-	select S3C_DEV_USB_HSOTG
-	select S5PV210_SETUP_FB_24BPP
-	select S5PV210_SETUP_FIMC
-	select S5PV210_SETUP_I2C1
-	select S5PV210_SETUP_I2C2
-	select S5PV210_SETUP_KEYPAD
-	select S5PV210_SETUP_SDHCI
-	select S5PV210_SETUP_USB_PHY
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_MFC
-	select S5P_DEV_ONENAND
-	select S5P_DEV_TV
-	select S5P_GPIO_INT
-	select SAMSUNG_DEV_KEYPAD
-	help
-	  Machine support for Samsung GONI board
-	  S5PC110(MCP) is one of package option of S5PV210
-
-config MACH_SMDKC110
-	bool "SMDKC110"
-	select CPU_S5PV210
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C2
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S5PV210_SETUP_I2C1
-	select S5PV210_SETUP_I2C2
-	select S5PV210_SETUP_IDE
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_MFC
-	select SAMSUNG_DEV_IDE
-	help
-	  Machine support for Samsung SMDKC110
-	  S5PC110(MCP) is one of package option of S5PV210
-
-endmenu
-
-menu "S5PV210 Machines"
-
-config MACH_SMDKV210
-	bool "SMDKV210"
-	select CPU_S5PV210
-	select S3C_DEV_FB
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C2
-	select S3C_DEV_RTC
-	select S3C_DEV_USB_HSOTG
-	select S3C_DEV_WDT
-	select S5PV210_SETUP_FB_24BPP
-	select S5PV210_SETUP_I2C1
-	select S5PV210_SETUP_I2C2
-	select S5PV210_SETUP_IDE
-	select S5PV210_SETUP_KEYPAD
-	select S5PV210_SETUP_SDHCI
-	select S5PV210_SETUP_USB_PHY
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_JPEG
-	select S5P_DEV_MFC
-	select SAMSUNG_DEV_ADC
-	select SAMSUNG_DEV_BACKLIGHT
-	select SAMSUNG_DEV_IDE
-	select SAMSUNG_DEV_KEYPAD
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_TS
-	help
-	  Machine support for Samsung SMDKV210
-
-config MACH_TORBRECK
-	bool "Torbreck"
-	select ARCH_SPARSEMEM_ENABLE
-	select CPU_S5PV210
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C2
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S5PV210_SETUP_I2C1
-	select S5PV210_SETUP_I2C2
-	select S5PV210_SETUP_SDHCI
-	select SAMSUNG_DEV_IDE
-	help
-	  Machine support for aESOP Torbreck
-
-endmenu
-
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-aquila.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-aquila.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-aquila.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-aquila.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,687 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-aquila.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
-#include <linux/mfd/max8998.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/regulator/fixed.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <plat/fimc-core.h>
-#include <plat/sdhci.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define AQUILA_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define AQUILA_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define AQUILA_UFCON_DEFAULT	S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= AQUILA_UCON_DEFAULT,
-		.ulcon		= AQUILA_ULCON_DEFAULT,
-		/*
-		 * Actually UART0 can support 256 bytes fifo, but aquila board
-		 * supports 128 bytes fifo because of initial chip bug
-		 */
-		.ufcon		= AQUILA_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG128 | S5PV210_UFCON_RXTRIG128,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= AQUILA_UCON_DEFAULT,
-		.ulcon		= AQUILA_ULCON_DEFAULT,
-		.ufcon		= AQUILA_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= AQUILA_UCON_DEFAULT,
-		.ulcon		= AQUILA_ULCON_DEFAULT,
-		.ufcon		= AQUILA_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= AQUILA_UCON_DEFAULT,
-		.ulcon		= AQUILA_ULCON_DEFAULT,
-		.ufcon		= AQUILA_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
-	},
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win aquila_fb_win0 = {
-	.max_bpp = 32,
-	.default_bpp = 16,
-	.xres = 480,
-	.yres = 800,
-};
-
-static struct s3c_fb_pd_win aquila_fb_win1 = {
-	.max_bpp = 32,
-	.default_bpp = 16,
-	.xres = 480,
-	.yres = 800,
-};
-
-static struct fb_videomode aquila_lcd_timing = {
-	.left_margin = 16,
-	.right_margin = 16,
-	.upper_margin = 3,
-	.lower_margin = 28,
-	.hsync_len = 2,
-	.vsync_len = 2,
-	.xres = 480,
-	.yres = 800,
-};
-
-static struct s3c_fb_platdata aquila_lcd_pdata __initdata = {
-	.win[0]		= &aquila_fb_win0,
-	.win[1]		= &aquila_fb_win1,
-	.vtiming	= &aquila_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
-			  VIDCON1_INV_VCLK | VIDCON1_INV_VDEN,
-	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
-};
-
-/* MAX8998 regulators */
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-
-static struct regulator_init_data aquila_ldo2_data = {
-	.constraints	= {
-		.name		= "VALIVE_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled = 1,
-		},
-	},
-};
-
-static struct regulator_init_data aquila_ldo3_data = {
-	.constraints	= {
-		.name		= "VUSB+MIPI_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo4_data = {
-	.constraints	= {
-		.name		= "VDAC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo5_data = {
-	.constraints	= {
-		.name		= "VTF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo6_data = {
-	.constraints	= {
-		.name		= "VCC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo7_data = {
-	.constraints	= {
-		.name		= "VCC_3.0V",
-		.min_uV		= 3000000,
-		.max_uV		= 3000000,
-		.apply_uV	= 1,
-		.boot_on	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo8_data = {
-	.constraints	= {
-		.name		= "VUSB+VADC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo9_data = {
-	.constraints	= {
-		.name		= "VCC+VCAM_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo10_data = {
-	.constraints	= {
-		.name		= "VPLL_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.boot_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo11_data = {
-	.constraints	= {
-		.name		= "CAM_IO_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo12_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo13_data = {
-	.constraints	= {
-		.name		= "CAM_A_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo14_data = {
-	.constraints	= {
-		.name		= "CAM_CIF_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo15_data = {
-	.constraints	= {
-		.name		= "CAM_AF_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo16_data = {
-	.constraints	= {
-		.name		= "VMIPI_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data aquila_ldo17_data = {
-	.constraints	= {
-		.name		= "CAM_8M_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-/* BUCK */
-static struct regulator_consumer_supply buck1_consumer =
-	REGULATOR_SUPPLY("vddarm", NULL);
-
-static struct regulator_consumer_supply buck2_consumer =
-	REGULATOR_SUPPLY("vddint", NULL);
-
-static struct regulator_init_data aquila_buck1_data = {
-	.constraints	= {
-		.name		= "VARM_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &buck1_consumer,
-};
-
-static struct regulator_init_data aquila_buck2_data = {
-	.constraints	= {
-		.name		= "VINT_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &buck2_consumer,
-};
-
-static struct regulator_init_data aquila_buck3_data = {
-	.constraints	= {
-		.name		= "VCC_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.enabled = 1,
-		},
-	},
-};
-
-static struct regulator_init_data aquila_buck4_data = {
-	.constraints	= {
-		.name		= "CAM_CORE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct max8998_regulator_data aquila_regulators[] = {
-	{ MAX8998_LDO2,  &aquila_ldo2_data },
-	{ MAX8998_LDO3,  &aquila_ldo3_data },
-	{ MAX8998_LDO4,  &aquila_ldo4_data },
-	{ MAX8998_LDO5,  &aquila_ldo5_data },
-	{ MAX8998_LDO6,  &aquila_ldo6_data },
-	{ MAX8998_LDO7,  &aquila_ldo7_data },
-	{ MAX8998_LDO8,  &aquila_ldo8_data },
-	{ MAX8998_LDO9,  &aquila_ldo9_data },
-	{ MAX8998_LDO10, &aquila_ldo10_data },
-	{ MAX8998_LDO11, &aquila_ldo11_data },
-	{ MAX8998_LDO12, &aquila_ldo12_data },
-	{ MAX8998_LDO13, &aquila_ldo13_data },
-	{ MAX8998_LDO14, &aquila_ldo14_data },
-	{ MAX8998_LDO15, &aquila_ldo15_data },
-	{ MAX8998_LDO16, &aquila_ldo16_data },
-	{ MAX8998_LDO17, &aquila_ldo17_data },
-	{ MAX8998_BUCK1, &aquila_buck1_data },
-	{ MAX8998_BUCK2, &aquila_buck2_data },
-	{ MAX8998_BUCK3, &aquila_buck3_data },
-	{ MAX8998_BUCK4, &aquila_buck4_data },
-};
-
-static struct max8998_platform_data aquila_max8998_pdata = {
-	.num_regulators	= ARRAY_SIZE(aquila_regulators),
-	.regulators	= aquila_regulators,
-	.buck1_set1	= S5PV210_GPH0(3),
-	.buck1_set2	= S5PV210_GPH0(4),
-	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_voltage	= { 1200000, 1200000, 1200000, 1200000 },
-	.buck2_voltage	= { 1200000, 1200000 },
-};
-#endif
-
-static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	REGULATOR_SUPPLY("DBVDD", "5-001a"),
-	REGULATOR_SUPPLY("AVDD2", "5-001a"),
-	REGULATOR_SUPPLY("CPVDD", "5-001a"),
-};
-
-static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
-	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
-};
-
-static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
-	.constraints = {
-		.always_on = 1,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
-	.consumer_supplies	= wm8994_fixed_voltage0_supplies,
-};
-
-static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
-	.constraints = {
-		.always_on = 1,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
-	.consumer_supplies	= wm8994_fixed_voltage1_supplies,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
-	.supply_name	= "VCC_1.8V_PDA",
-	.microvolts	= 1800000,
-	.gpio		= -EINVAL,
-	.init_data	= &wm8994_fixed_voltage0_init_data,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
-	.supply_name	= "V_BAT",
-	.microvolts	= 3700000,
-	.gpio		= -EINVAL,
-	.init_data	= &wm8994_fixed_voltage1_init_data,
-};
-
-static struct platform_device wm8994_fixed_voltage0 = {
-	.name		= "reg-fixed-voltage",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &wm8994_fixed_voltage0_config,
-	},
-};
-
-static struct platform_device wm8994_fixed_voltage1 = {
-	.name		= "reg-fixed-voltage",
-	.id		= 1,
-	.dev		= {
-		.platform_data	= &wm8994_fixed_voltage1_config,
-	},
-};
-
-static struct regulator_consumer_supply wm8994_avdd1_supply =
-	REGULATOR_SUPPLY("AVDD1", "5-001a");
-
-static struct regulator_consumer_supply wm8994_dcvdd_supply =
-	REGULATOR_SUPPLY("DCVDD", "5-001a");
-
-static struct regulator_init_data wm8994_ldo1_data = {
-	.constraints	= {
-		.name		= "AVDD1_3.0V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &wm8994_avdd1_supply,
-};
-
-static struct regulator_init_data wm8994_ldo2_data = {
-	.constraints	= {
-		.name		= "DCVDD_1.0V",
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &wm8994_dcvdd_supply,
-};
-
-static struct wm8994_pdata wm8994_platform_data = {
-	/* configure gpio1 function: 0x0001(Logic level input/output) */
-	.gpio_defaults[0] = 0x0001,
-	/* configure gpio3/4/5/7 function for AIF2 voice */
-	.gpio_defaults[2] = 0x8100,
-	.gpio_defaults[3] = 0x8100,
-	.gpio_defaults[4] = 0x8100,
-	.gpio_defaults[6] = 0x0100,
-	/* configure gpio8/9/10/11 function for AIF3 BT */
-	.gpio_defaults[7] = 0x8100,
-	.gpio_defaults[8] = 0x0100,
-	.gpio_defaults[9] = 0x0100,
-	.gpio_defaults[10] = 0x0100,
-	.ldo[0]	= { S5PV210_MP03(6), &wm8994_ldo1_data },	/* XM0FRNB_2 */
-	.ldo[1]	= { 0, &wm8994_ldo2_data },
-};
-
-/* GPIO I2C PMIC */
-#define AP_I2C_GPIO_PMIC_BUS_4	4
-static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = {
-	.sda_pin	= S5PV210_GPJ4(0),	/* XMSMCSN */
-	.scl_pin	= S5PV210_GPJ4(3),	/* XMSMIRQN */
-};
-
-static struct platform_device aquila_i2c_gpio_pmic = {
-	.name		= "i2c-gpio",
-	.id		= AP_I2C_GPIO_PMIC_BUS_4,
-	.dev		= {
-		.platform_data = &aquila_i2c_gpio_pmic_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-	{
-		/* 0xCC when SRAD = 0 */
-		I2C_BOARD_INFO("max8998", 0xCC >> 1),
-		.platform_data = &aquila_max8998_pdata,
-	},
-#endif
-};
-
-/* GPIO I2C AP 1.8V */
-#define AP_I2C_GPIO_BUS_5	5
-static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = {
-	.sda_pin	= S5PV210_MP05(3),	/* XM0ADDR_11 */
-	.scl_pin	= S5PV210_MP05(2),	/* XM0ADDR_10 */
-};
-
-static struct platform_device aquila_i2c_gpio5 = {
-	.name		= "i2c-gpio",
-	.id		= AP_I2C_GPIO_BUS_5,
-	.dev		= {
-		.platform_data	= &aquila_i2c_gpio5_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
-	{
-		/* CS/ADDR = low 0x34 (FYI: high = 0x36) */
-		I2C_BOARD_INFO("wm8994", 0x1a),
-		.platform_data	= &wm8994_platform_data,
-	},
-};
-
-/* PMIC Power button */
-static struct gpio_keys_button aquila_gpio_keys_table[] = {
-	{
-		.code 		= KEY_POWER,
-		.gpio		= S5PV210_GPH2(6),
-		.desc		= "gpio-keys: KEY_POWER",
-		.type		= EV_KEY,
-		.active_low	= 1,
-		.wakeup		= 1,
-		.debounce_interval = 1,
-	},
-};
-
-static struct gpio_keys_platform_data aquila_gpio_keys_data = {
-	.buttons	= aquila_gpio_keys_table,
-	.nbuttons	= ARRAY_SIZE(aquila_gpio_keys_table),
-};
-
-static struct platform_device aquila_device_gpiokeys = {
-	.name = "gpio-keys",
-	.dev = {
-		.platform_data = &aquila_gpio_keys_data,
-	},
-};
-
-static void __init aquila_pmic_init(void)
-{
-	/* AP_PMIC_IRQ: EINT7 */
-	s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP);
-
-	/* nPower: EINT22 */
-	s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP);
-}
-
-/* MoviNAND */
-static struct s3c_sdhci_platdata aquila_hsmmc0_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-};
-
-/* Wireless LAN */
-static struct s3c_sdhci_platdata aquila_hsmmc1_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-	/* ext_cd_{init,cleanup} callbacks will be added later */
-};
-
-/* External Flash */
-#define AQUILA_EXT_FLASH_EN	S5PV210_MP05(4)
-#define AQUILA_EXT_FLASH_CD	S5PV210_GPH3(4)
-static struct s3c_sdhci_platdata aquila_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= AQUILA_EXT_FLASH_CD,
-	.ext_cd_gpio_invert	= 1,
-};
-
-static void aquila_setup_sdhci(void)
-{
-	gpio_request_one(AQUILA_EXT_FLASH_EN, GPIOF_OUT_INIT_HIGH, "FLASH_EN");
-
-	s3c_sdhci0_set_platdata(&aquila_hsmmc0_data);
-	s3c_sdhci1_set_platdata(&aquila_hsmmc1_data);
-	s3c_sdhci2_set_platdata(&aquila_hsmmc2_data);
-};
-
-/* Audio device */
-static struct platform_device aquila_device_audio = {
-	.name = "smdk-audio",
-	.id = -1,
-};
-
-static struct platform_device *aquila_devices[] __initdata = {
-	&aquila_i2c_gpio_pmic,
-	&aquila_i2c_gpio5,
-	&aquila_device_gpiokeys,
-	&aquila_device_audio,
-	&s3c_device_fb,
-	&s5p_device_onenand,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5p_device_fimc_md,
-	&s5pv210_device_iis0,
-	&wm8994_fixed_voltage0,
-	&wm8994_fixed_voltage1,
-};
-
-static void __init aquila_sound_init(void)
-{
-	unsigned int gpio;
-
-	/* CODEC_XTAL_EN
-	 *
-	 * The Aquila board have a oscillator which provide main clock
-	 * to WM8994 codec. The oscillator provide 24MHz clock to WM8994
-	 * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator.
-	 * */
-	gpio = S5PV210_GPH3(2);		/* XEINT_26 */
-	gpio_request(gpio, "CODEC_XTAL_EN");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
-	/* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
-	 * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
-	 * because it needs 24MHz clock to operate WM8994 codec.
-	 */
-	__raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
-}
-
-static void __init aquila_map_io(void)
-{
-	s5pv210_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init aquila_machine_init(void)
-{
-	/* PMIC */
-	aquila_pmic_init();
-	i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
-			ARRAY_SIZE(i2c_gpio_pmic_devs));
-	/* SDHCI */
-	aquila_setup_sdhci();
-
-	s3c_fimc_setname(0, "s5p-fimc");
-	s3c_fimc_setname(1, "s5p-fimc");
-	s3c_fimc_setname(2, "s5p-fimc");
-
-	/* SOUND */
-	aquila_sound_init();
-	i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
-			ARRAY_SIZE(i2c_gpio5_devs));
-
-	/* FB */
-	s3c_fb_set_platdata(&aquila_lcd_pdata);
-
-	platform_add_devices(aquila_devices, ARRAY_SIZE(aquila_devices));
-}
-
-MACHINE_START(AQUILA, "Aquila")
-	/* Maintainers:
-	   Marek Szyprowski <m.szyprowski@samsung.com>
-	   Kyungmin Park <kyungmin.park@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pv210_init_irq,
-	.map_io		= aquila_map_io,
-	.init_machine	= aquila_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5pv210_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-goni.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-goni.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-goni.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-goni.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,916 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-goni.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/mfd/max8998.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/regulator/fixed.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_gpio.h>
-#include <linux/lcd.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/interrupt.h>
-#include <linux/platform_data/s3c-hsotg.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/keypad.h>
-#include <plat/sdhci.h>
-#include <plat/clock.h>
-#include <plat/samsung-time.h>
-#include <plat/mfc.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define GONI_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define GONI_UFCON_DEFAULT	S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= GONI_UCON_DEFAULT,
-		.ulcon		= GONI_ULCON_DEFAULT,
-		.ufcon		= GONI_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG256 | S5PV210_UFCON_RXTRIG256,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= GONI_UCON_DEFAULT,
-		.ulcon		= GONI_ULCON_DEFAULT,
-		.ufcon		= GONI_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= GONI_UCON_DEFAULT,
-		.ulcon		= GONI_ULCON_DEFAULT,
-		.ufcon		= GONI_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= GONI_UCON_DEFAULT,
-		.ulcon		= GONI_ULCON_DEFAULT,
-		.ufcon		= GONI_UFCON_DEFAULT |
-			S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
-	},
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win goni_fb_win0 = {
-	.max_bpp	= 32,
-	.default_bpp	= 16,
-	.xres		= 480,
-	.yres		= 800,
-	.virtual_x	= 480,
-	.virtual_y	= 2 * 800,
-};
-
-static struct fb_videomode goni_lcd_timing = {
-	.left_margin	= 16,
-	.right_margin	= 16,
-	.upper_margin	= 2,
-	.lower_margin	= 28,
-	.hsync_len	= 2,
-	.vsync_len	= 1,
-	.xres		= 480,
-	.yres		= 800,
-	.refresh	= 55,
-};
-
-static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
-	.win[0]		= &goni_fb_win0,
-	.vtiming	= &goni_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
-			  VIDCON0_CLKSEL_LCD,
-	.vidcon1	= VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
-			  | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
-};
-
-static int lcd_power_on(struct lcd_device *ld, int enable)
-{
-	return 1;
-}
-
-static int reset_lcd(struct lcd_device *ld)
-{
-	static unsigned int first = 1;
-	int reset_gpio = -1;
-
-	reset_gpio = S5PV210_MP05(5);
-
-	if (first) {
-		gpio_request(reset_gpio, "MLCD_RST");
-		first = 0;
-	}
-
-	gpio_direction_output(reset_gpio, 1);
-	return 1;
-}
-
-static struct lcd_platform_data goni_lcd_platform_data = {
-	.reset			= reset_lcd,
-	.power_on		= lcd_power_on,
-	.lcd_enabled		= 0,
-	.reset_delay		= 120,	/* 120ms */
-	.power_on_delay		= 25,	/* 25ms */
-	.power_off_delay	= 200,	/* 200ms */
-};
-
-#define LCD_BUS_NUM	3
-static struct spi_board_info spi_board_info[] __initdata = {
-	{
-		.modalias	= "s6e63m0",
-		.platform_data	= &goni_lcd_platform_data,
-		.max_speed_hz	= 1200000,
-		.bus_num	= LCD_BUS_NUM,
-		.chip_select	= 0,
-		.mode		= SPI_MODE_3,
-		.controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */
-	},
-};
-
-static struct spi_gpio_platform_data lcd_spi_gpio_data = {
-	.sck	= S5PV210_MP04(1), /* DISPLAY_CLK */
-	.mosi	= S5PV210_MP04(3), /* DISPLAY_SI */
-	.miso	= SPI_GPIO_NO_MISO,
-	.num_chipselect	= 1,
-};
-
-static struct platform_device goni_spi_gpio = {
-	.name	= "spi_gpio",
-	.id	= LCD_BUS_NUM,
-	.dev	= {
-		.parent		= &s3c_device_fb.dev,
-		.platform_data	= &lcd_spi_gpio_data,
-	},
-};
-
-/* KEYPAD */
-static uint32_t keymap[] __initdata = {
-	/* KEY(row, col, keycode) */
-	KEY(0, 1, KEY_MENU),		/* Send */
-	KEY(0, 2, KEY_BACK),		/* End */
-	KEY(1, 1, KEY_CONFIG),		/* Half shot */
-	KEY(1, 2, KEY_VOLUMEUP),
-	KEY(2, 1, KEY_CAMERA),		/* Full shot */
-	KEY(2, 2, KEY_VOLUMEDOWN),
-};
-
-static struct matrix_keymap_data keymap_data __initdata = {
-	.keymap		= keymap,
-	.keymap_size	= ARRAY_SIZE(keymap),
-};
-
-static struct samsung_keypad_platdata keypad_data __initdata = {
-	.keymap_data	= &keymap_data,
-	.rows		= 3,
-	.cols		= 3,
-};
-
-/* Radio */
-static struct i2c_board_info i2c1_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("si470x", 0x10),
-	},
-};
-
-static void __init goni_radio_init(void)
-{
-	int gpio;
-
-	gpio = S5PV210_GPJ2(4);			/* XMSMDATA_4 */
-	gpio_request(gpio, "FM_INT");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	i2c1_devs[0].irq = gpio_to_irq(gpio);
-
-	gpio = S5PV210_GPJ2(5);			/* XMSMDATA_5 */
-	gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "FM_RST");
-}
-
-/* TSP */
-static struct mxt_platform_data qt602240_platform_data = {
-	.irqflags	= IRQF_TRIGGER_FALLING,
-};
-
-static struct s3c2410_platform_i2c i2c2_data __initdata = {
-	.flags		= 0,
-	.bus_num	= 2,
-	.slave_addr	= 0x10,
-	.frequency	= 400 * 1000,
-	.sda_delay	= 100,
-};
-
-static struct i2c_board_info i2c2_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("qt602240_ts", 0x4a),
-		.platform_data = &qt602240_platform_data,
-	},
-};
-
-static void __init goni_tsp_init(void)
-{
-	int gpio;
-
-	gpio = S5PV210_GPJ1(3);		/* XMSMADDR_11 */
-	gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "TSP_LDO_ON");
-	gpio_export(gpio, 0);
-
-	gpio = S5PV210_GPJ0(5);		/* XMSMADDR_5 */
-	gpio_request(gpio, "TSP_INT");
-
-	s5p_register_gpio_interrupt(gpio);
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-	i2c2_devs[0].irq = gpio_to_irq(gpio);
-}
-
-/* USB OTG */
-static struct s3c_hsotg_plat goni_hsotg_pdata;
-
-/* MAX8998 regulators */
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-
-static struct regulator_consumer_supply goni_ldo3_consumers[] = {
-	REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
-};
-
-static struct regulator_consumer_supply goni_ldo5_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-};
-
-static struct regulator_consumer_supply goni_ldo8_consumers[] = {
-	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
-	REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
-};
-
-static struct regulator_consumer_supply goni_ldo11_consumers[] = {
-	REGULATOR_SUPPLY("vddio", "0-0030"), /* "CAM_IO_2.8V" */
-};
-
-static struct regulator_consumer_supply goni_ldo13_consumers[] = {
-	REGULATOR_SUPPLY("vdda", "0-0030"), /* "CAM_A_2.8V" */
-};
-
-static struct regulator_consumer_supply goni_ldo14_consumers[] = {
-	REGULATOR_SUPPLY("vdd_core", "0-0030"), /* "CAM_CIF_1.8V" */
-};
-
-static struct regulator_init_data goni_ldo2_data = {
-	.constraints	= {
-		.name		= "VALIVE_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled = 1,
-		},
-	},
-};
-
-static struct regulator_init_data goni_ldo3_data = {
-	.constraints	= {
-		.name		= "VUSB+MIPI_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(goni_ldo3_consumers),
-	.consumer_supplies = goni_ldo3_consumers,
-};
-
-static struct regulator_init_data goni_ldo4_data = {
-	.constraints	= {
-		.name		= "VDAC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo5_data = {
-	.constraints	= {
-		.name		= "VTF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
-	.consumer_supplies = goni_ldo5_consumers,
-};
-
-static struct regulator_init_data goni_ldo6_data = {
-	.constraints	= {
-		.name		= "VCC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo7_data = {
-	.constraints	= {
-		.name		= "VLCD_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo8_data = {
-	.constraints	= {
-		.name		= "VUSB+VADC_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(goni_ldo8_consumers),
-	.consumer_supplies = goni_ldo8_consumers,
-};
-
-static struct regulator_init_data goni_ldo9_data = {
-	.constraints	= {
-		.name		= "VCC+VCAM_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo10_data = {
-	.constraints	= {
-		.name		= "VPLL_1.1V",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.boot_on	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo11_data = {
-	.constraints	= {
-		.name		= "CAM_IO_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo11_consumers),
-	.consumer_supplies	= goni_ldo11_consumers,
-};
-
-static struct regulator_init_data goni_ldo12_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo13_data = {
-	.constraints	= {
-		.name		= "CAM_A_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo13_consumers),
-	.consumer_supplies	= goni_ldo13_consumers,
-};
-
-static struct regulator_init_data goni_ldo14_data = {
-	.constraints	= {
-		.name		= "CAM_CIF_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo14_consumers),
-	.consumer_supplies	= goni_ldo14_consumers,
-};
-
-static struct regulator_init_data goni_ldo15_data = {
-	.constraints	= {
-		.name		= "CAM_AF_3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo16_data = {
-	.constraints	= {
-		.name		= "VMIPI_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data goni_ldo17_data = {
-	.constraints	= {
-		.name		= "VCC_3.0V_LCD",
-		.min_uV		= 3000000,
-		.max_uV		= 3000000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-/* BUCK */
-static struct regulator_consumer_supply buck1_consumer =
-	REGULATOR_SUPPLY("vddarm", NULL);
-
-static struct regulator_consumer_supply buck2_consumer =
-	REGULATOR_SUPPLY("vddint", NULL);
-
-static struct regulator_consumer_supply buck3_consumer =
-	REGULATOR_SUPPLY("vdet", "s5p-sdo");
-
-
-static struct regulator_init_data goni_buck1_data = {
-	.constraints	= {
-		.name		= "VARM_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &buck1_consumer,
-};
-
-static struct regulator_init_data goni_buck2_data = {
-	.constraints	= {
-		.name		= "VINT_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &buck2_consumer,
-};
-
-static struct regulator_init_data goni_buck3_data = {
-	.constraints	= {
-		.name		= "VCC_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.enabled = 1,
-		},
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &buck3_consumer,
-};
-
-static struct regulator_init_data goni_buck4_data = {
-	.constraints	= {
-		.name		= "CAM_CORE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-	},
-};
-
-static struct max8998_regulator_data goni_regulators[] = {
-	{ MAX8998_LDO2,  &goni_ldo2_data },
-	{ MAX8998_LDO3,  &goni_ldo3_data },
-	{ MAX8998_LDO4,  &goni_ldo4_data },
-	{ MAX8998_LDO5,  &goni_ldo5_data },
-	{ MAX8998_LDO6,  &goni_ldo6_data },
-	{ MAX8998_LDO7,  &goni_ldo7_data },
-	{ MAX8998_LDO8,  &goni_ldo8_data },
-	{ MAX8998_LDO9,  &goni_ldo9_data },
-	{ MAX8998_LDO10, &goni_ldo10_data },
-	{ MAX8998_LDO11, &goni_ldo11_data },
-	{ MAX8998_LDO12, &goni_ldo12_data },
-	{ MAX8998_LDO13, &goni_ldo13_data },
-	{ MAX8998_LDO14, &goni_ldo14_data },
-	{ MAX8998_LDO15, &goni_ldo15_data },
-	{ MAX8998_LDO16, &goni_ldo16_data },
-	{ MAX8998_LDO17, &goni_ldo17_data },
-	{ MAX8998_BUCK1, &goni_buck1_data },
-	{ MAX8998_BUCK2, &goni_buck2_data },
-	{ MAX8998_BUCK3, &goni_buck3_data },
-	{ MAX8998_BUCK4, &goni_buck4_data },
-};
-
-static struct max8998_platform_data goni_max8998_pdata = {
-	.num_regulators	= ARRAY_SIZE(goni_regulators),
-	.regulators	= goni_regulators,
-	.buck1_set1	= S5PV210_GPH0(3),
-	.buck1_set2	= S5PV210_GPH0(4),
-	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_voltage	= { 1200000, 1200000, 1200000, 1200000 },
-	.buck2_voltage	= { 1200000, 1200000 },
-};
-#endif
-
-static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	REGULATOR_SUPPLY("DBVDD", "5-001a"),
-	REGULATOR_SUPPLY("AVDD2", "5-001a"),
-	REGULATOR_SUPPLY("CPVDD", "5-001a"),
-};
-
-static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
-	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
-};
-
-static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
-	.constraints = {
-		.always_on = 1,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
-	.consumer_supplies	= wm8994_fixed_voltage0_supplies,
-};
-
-static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
-	.constraints = {
-		.always_on = 1,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
-	.consumer_supplies	= wm8994_fixed_voltage1_supplies,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
-	.supply_name	= "VCC_1.8V_PDA",
-	.microvolts	= 1800000,
-	.gpio		= -EINVAL,
-	.init_data	= &wm8994_fixed_voltage0_init_data,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
-	.supply_name	= "V_BAT",
-	.microvolts	= 3700000,
-	.gpio		= -EINVAL,
-	.init_data	= &wm8994_fixed_voltage1_init_data,
-};
-
-static struct platform_device wm8994_fixed_voltage0 = {
-	.name		= "reg-fixed-voltage",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &wm8994_fixed_voltage0_config,
-	},
-};
-
-static struct platform_device wm8994_fixed_voltage1 = {
-	.name		= "reg-fixed-voltage",
-	.id		= 1,
-	.dev		= {
-		.platform_data	= &wm8994_fixed_voltage1_config,
-	},
-};
-
-static struct regulator_consumer_supply wm8994_avdd1_supply =
-	REGULATOR_SUPPLY("AVDD1", "5-001a");
-
-static struct regulator_consumer_supply wm8994_dcvdd_supply =
-	REGULATOR_SUPPLY("DCVDD", "5-001a");
-
-static struct regulator_init_data wm8994_ldo1_data = {
-	.constraints	= {
-		.name		= "AVDD1_3.0V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &wm8994_avdd1_supply,
-};
-
-static struct regulator_init_data wm8994_ldo2_data = {
-	.constraints	= {
-		.name		= "DCVDD_1.0V",
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &wm8994_dcvdd_supply,
-};
-
-static struct wm8994_pdata wm8994_platform_data = {
-	/* configure gpio1 function: 0x0001(Logic level input/output) */
-	.gpio_defaults[0] = 0x0001,
-	/* configure gpio3/4/5/7 function for AIF2 voice */
-	.gpio_defaults[2] = 0x8100,
-	.gpio_defaults[3] = 0x8100,
-	.gpio_defaults[4] = 0x8100,
-	.gpio_defaults[6] = 0x0100,
-	/* configure gpio8/9/10/11 function for AIF3 BT */
-	.gpio_defaults[7] = 0x8100,
-	.gpio_defaults[8] = 0x0100,
-	.gpio_defaults[9] = 0x0100,
-	.gpio_defaults[10] = 0x0100,
-	.ldo[0]	= { S5PV210_MP03(6), &wm8994_ldo1_data },	/* XM0FRNB_2 */
-	.ldo[1]	= { 0, &wm8994_ldo2_data },
-};
-
-/* GPIO I2C PMIC */
-#define AP_I2C_GPIO_PMIC_BUS_4	4
-static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = {
-	.sda_pin	= S5PV210_GPJ4(0),	/* XMSMCSN */
-	.scl_pin	= S5PV210_GPJ4(3),	/* XMSMIRQN */
-};
-
-static struct platform_device goni_i2c_gpio_pmic = {
-	.name		= "i2c-gpio",
-	.id		= AP_I2C_GPIO_PMIC_BUS_4,
-	.dev		= {
-		.platform_data	= &goni_i2c_gpio_pmic_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-	{
-		/* 0xCC when SRAD = 0 */
-		I2C_BOARD_INFO("max8998", 0xCC >> 1),
-		.platform_data = &goni_max8998_pdata,
-	},
-#endif
-};
-
-/* GPIO I2C AP 1.8V */
-#define AP_I2C_GPIO_BUS_5	5
-static struct i2c_gpio_platform_data goni_i2c_gpio5_data = {
-	.sda_pin	= S5PV210_MP05(3),	/* XM0ADDR_11 */
-	.scl_pin	= S5PV210_MP05(2),	/* XM0ADDR_10 */
-};
-
-static struct platform_device goni_i2c_gpio5 = {
-	.name		= "i2c-gpio",
-	.id		= AP_I2C_GPIO_BUS_5,
-	.dev		= {
-		.platform_data	= &goni_i2c_gpio5_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
-	{
-		/* CS/ADDR = low 0x34 (FYI: high = 0x36) */
-		I2C_BOARD_INFO("wm8994", 0x1a),
-		.platform_data	= &wm8994_platform_data,
-	},
-};
-
-/* PMIC Power button */
-static struct gpio_keys_button goni_gpio_keys_table[] = {
-	{
-		.code 		= KEY_POWER,
-		.gpio		= S5PV210_GPH2(6),
-		.desc		= "gpio-keys: KEY_POWER",
-		.type		= EV_KEY,
-		.active_low	= 1,
-		.wakeup		= 1,
-		.debounce_interval = 1,
-	},
-};
-
-static struct gpio_keys_platform_data goni_gpio_keys_data = {
-	.buttons	= goni_gpio_keys_table,
-	.nbuttons	= ARRAY_SIZE(goni_gpio_keys_table),
-};
-
-static struct platform_device goni_device_gpiokeys = {
-	.name = "gpio-keys",
-	.dev = {
-		.platform_data = &goni_gpio_keys_data,
-	},
-};
-
-static void __init goni_pmic_init(void)
-{
-	/* AP_PMIC_IRQ: EINT7 */
-	s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP);
-
-	/* nPower: EINT22 */
-	s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP);
-}
-
-/* MoviNAND */
-static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-};
-
-/* Wireless LAN */
-static struct s3c_sdhci_platdata goni_hsmmc1_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-	/* ext_cd_{init,cleanup} callbacks will be added later */
-};
-
-/* External Flash */
-#define GONI_EXT_FLASH_EN	S5PV210_MP05(4)
-#define GONI_EXT_FLASH_CD	S5PV210_GPH3(4)
-static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= GONI_EXT_FLASH_CD,
-	.ext_cd_gpio_invert	= 1,
-};
-
-static struct regulator_consumer_supply mmc2_supplies[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
-};
-
-static struct regulator_init_data mmc2_fixed_voltage_init_data = {
-	.constraints		= {
-		.name		= "V_TF_2.8V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(mmc2_supplies),
-	.consumer_supplies	= mmc2_supplies,
-};
-
-static struct fixed_voltage_config mmc2_fixed_voltage_config = {
-	.supply_name		= "EXT_FLASH_EN",
-	.microvolts		= 2800000,
-	.gpio			= GONI_EXT_FLASH_EN,
-	.enable_high		= true,
-	.init_data		= &mmc2_fixed_voltage_init_data,
-};
-
-static struct platform_device mmc2_fixed_voltage = {
-	.name		= "reg-fixed-voltage",
-	.id		= 2,
-	.dev		= {
-		.platform_data	= &mmc2_fixed_voltage_config,
-	},
-};
-
-static void goni_setup_sdhci(void)
-{
-	s3c_sdhci0_set_platdata(&goni_hsmmc0_data);
-	s3c_sdhci1_set_platdata(&goni_hsmmc1_data);
-	s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
-};
-
-/* Audio device */
-static struct platform_device goni_device_audio = {
-	.name = "smdk-audio",
-	.id = -1,
-};
-
-static struct platform_device *goni_devices[] __initdata = {
-	&s3c_device_fb,
-	&s5p_device_onenand,
-	&goni_spi_gpio,
-	&goni_i2c_gpio_pmic,
-	&goni_i2c_gpio5,
-	&goni_device_audio,
-	&mmc2_fixed_voltage,
-	&goni_device_gpiokeys,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&s5p_device_mixer,
-	&s5p_device_sdo,
-	&s3c_device_i2c0,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s5pv210_device_iis0,
-	&s3c_device_usb_hsotg,
-	&samsung_device_keypad,
-	&s3c_device_i2c1,
-	&s3c_device_i2c2,
-	&wm8994_fixed_voltage0,
-	&wm8994_fixed_voltage1,
-};
-
-static void __init goni_sound_init(void)
-{
-	/* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
-	 * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
-	 * because it needs 24MHz clock to operate WM8994 codec.
-	 */
-	__raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
-}
-
-static void __init goni_map_io(void)
-{
-	s5pv210_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
-	s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init goni_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init goni_machine_init(void)
-{
-	/* Radio: call before I2C 1 registeration */
-	goni_radio_init();
-
-	/* I2C0 */
-	s3c_i2c0_set_platdata(NULL);
-
-	/* I2C1 */
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-
-	/* TSP: call before I2C 2 registeration */
-	goni_tsp_init();
-
-	/* I2C2 */
-	s3c_i2c2_set_platdata(&i2c2_data);
-	i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs));
-
-	/* PMIC */
-	goni_pmic_init();
-	i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
-			ARRAY_SIZE(i2c_gpio_pmic_devs));
-	/* SDHCI */
-	goni_setup_sdhci();
-
-	/* SOUND */
-	goni_sound_init();
-	i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
-			ARRAY_SIZE(i2c_gpio5_devs));
-
-	/* FB */
-	s3c_fb_set_platdata(&goni_lcd_pdata);
-
-	s3c_hsotg_set_platdata(&goni_hsotg_pdata);
-
-	/* SPI */
-	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-
-	/* KEYPAD */
-	samsung_keypad_set_platdata(&keypad_data);
-
-	platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
-}
-
-MACHINE_START(GONI, "GONI")
-	/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pv210_init_irq,
-	.map_io		= goni_map_io,
-	.init_machine	= goni_machine_init,
-	.init_time	= samsung_timer_init,
-	.reserve	= &goni_reserve,
-	.restart	= s5pv210_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,159 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-smdkc110.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/i2c.h>
-#include <linux/device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pm.h>
-#include <plat/samsung-time.h>
-#include <plat/mfc.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC110_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC110_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC110_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKC110_UCON_DEFAULT,
-		.ulcon		= SMDKC110_ULCON_DEFAULT,
-		.ufcon		= SMDKC110_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKC110_UCON_DEFAULT,
-		.ulcon		= SMDKC110_ULCON_DEFAULT,
-		.ufcon		= SMDKC110_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKC110_UCON_DEFAULT,
-		.ulcon		= SMDKC110_ULCON_DEFAULT,
-		.ufcon		= SMDKC110_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKC110_UCON_DEFAULT,
-		.ulcon		= SMDKC110_ULCON_DEFAULT,
-		.ufcon		= SMDKC110_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
-	.setup_gpio	= s5pv210_ide_setup_gpio,
-};
-
-static struct platform_device *smdkc110_devices[] __initdata = {
-	&s5pv210_device_iis0,
-	&s5pv210_device_ac97,
-	&s5pv210_device_spdif,
-	&s3c_device_cfcon,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_i2c2,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5p_device_fimc_md,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-};
-
-static struct i2c_board_info smdkc110_i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("24c08", 0x50), },     /* Samsung S524AD0XD1 */
-	{ I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdkc110_i2c_devs1[] __initdata = {
-	/* To Be Updated */
-};
-
-static struct i2c_board_info smdkc110_i2c_devs2[] __initdata = {
-	/* To Be Updated */
-};
-
-static void __init smdkc110_map_io(void)
-{
-	s5pv210_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init smdkc110_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init smdkc110_machine_init(void)
-{
-	s3c_pm_init();
-
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	s3c_i2c2_set_platdata(NULL);
-	i2c_register_board_info(0, smdkc110_i2c_devs0,
-			ARRAY_SIZE(smdkc110_i2c_devs0));
-	i2c_register_board_info(1, smdkc110_i2c_devs1,
-			ARRAY_SIZE(smdkc110_i2c_devs1));
-	i2c_register_board_info(2, smdkc110_i2c_devs2,
-			ARRAY_SIZE(smdkc110_i2c_devs2));
-
-	s3c_ide_set_platdata(&smdkc110_ide_pdata);
-
-	platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
-}
-
-MACHINE_START(SMDKC110, "SMDKC110")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pv210_init_irq,
-	.map_io		= smdkc110_map_io,
-	.init_machine	= smdkc110_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5pv210_restart,
-	.reserve	= &smdkc110_reserve,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,337 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-smdkv210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/device.h>
-#include <linux/dm9000.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/pwm_backlight.h>
-#include <linux/platform_data/s3c-hsotg.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/regs-srom.h>
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/keypad.h>
-#include <plat/pm.h>
-#include <plat/fb.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/mfc.h>
-#include <plat/clock.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKV210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKV210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKV210_UCON_DEFAULT,
-		.ulcon		= SMDKV210_ULCON_DEFAULT,
-		.ufcon		= SMDKV210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKV210_UCON_DEFAULT,
-		.ulcon		= SMDKV210_ULCON_DEFAULT,
-		.ufcon		= SMDKV210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKV210_UCON_DEFAULT,
-		.ulcon		= SMDKV210_ULCON_DEFAULT,
-		.ufcon		= SMDKV210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKV210_UCON_DEFAULT,
-		.ulcon		= SMDKV210_ULCON_DEFAULT,
-		.ufcon		= SMDKV210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_ide_platdata smdkv210_ide_pdata __initdata = {
-	.setup_gpio	= s5pv210_ide_setup_gpio,
-};
-
-static uint32_t smdkv210_keymap[] __initdata = {
-	/* KEY(row, col, keycode) */
-	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
-	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
-	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
-	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
-};
-
-static struct matrix_keymap_data smdkv210_keymap_data __initdata = {
-	.keymap		= smdkv210_keymap,
-	.keymap_size	= ARRAY_SIZE(smdkv210_keymap),
-};
-
-static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = {
-	.keymap_data	= &smdkv210_keymap_data,
-	.rows		= 8,
-	.cols		= 8,
-};
-
-static struct resource smdkv210_dm9000_resources[] = {
-	[0] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5, 1),
-	[1] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5 + 2, 1),
-	[2] = DEFINE_RES_NAMED(IRQ_EINT(9), 1, NULL, IORESOURCE_IRQ \
-				| IORESOURCE_IRQ_HIGHLEVEL),
-};
-
-static struct dm9000_plat_data smdkv210_dm9000_platdata = {
-	.flags		= DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
-	.dev_addr	= { 0x00, 0x09, 0xc0, 0xff, 0xec, 0x48 },
-};
-
-static struct platform_device smdkv210_dm9000 = {
-	.name		= "dm9000",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkv210_dm9000_resources),
-	.resource	= smdkv210_dm9000_resources,
-	.dev		= {
-		.platform_data	= &smdkv210_dm9000_platdata,
-	},
-};
-
-static void smdkv210_lte480wv_set_power(struct plat_lcd_data *pd,
-					unsigned int power)
-{
-	if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(S5PV210_GPD0(3), GPIOF_OUT_INIT_HIGH, "GPD0");
-		gpio_free(S5PV210_GPD0(3));
-#endif
-
-		/* fire nRESET on power up */
-		gpio_request_one(S5PV210_GPH0(6), GPIOF_OUT_INIT_HIGH, "GPH0");
-
-		gpio_set_value(S5PV210_GPH0(6), 0);
-		mdelay(10);
-
-		gpio_set_value(S5PV210_GPH0(6), 1);
-		mdelay(10);
-
-		gpio_free(S5PV210_GPH0(6));
-	} else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(S5PV210_GPD0(3), GPIOF_OUT_INIT_LOW, "GPD0");
-		gpio_free(S5PV210_GPD0(3));
-#endif
-	}
-}
-
-static struct plat_lcd_data smdkv210_lcd_lte480wv_data = {
-	.set_power	= smdkv210_lte480wv_set_power,
-};
-
-static struct platform_device smdkv210_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &smdkv210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkv210_fb_win0 = {
-	.max_bpp	= 32,
-	.default_bpp	= 24,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct fb_videomode smdkv210_lcd_timing = {
-	.left_margin	= 13,
-	.right_margin	= 8,
-	.upper_margin	= 7,
-	.lower_margin	= 5,
-	.hsync_len	= 3,
-	.vsync_len	= 1,
-	.xres		= 800,
-	.yres		= 480,
-};
-
-static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
-	.win[0]		= &smdkv210_fb_win0,
-	.vtiming	= &smdkv210_lcd_timing,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
-};
-
-/* USB OTG */
-static struct s3c_hsotg_plat smdkv210_hsotg_pdata;
-
-static struct platform_device *smdkv210_devices[] __initdata = {
-	&s3c_device_adc,
-	&s3c_device_cfcon,
-	&s3c_device_fb,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_i2c2,
-	&samsung_device_pwm,
-	&s3c_device_rtc,
-	&s3c_device_ts,
-	&s3c_device_usb_hsotg,
-	&s3c_device_wdt,
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5p_device_fimc_md,
-	&s5p_device_jpeg,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&s5pv210_device_ac97,
-	&s5pv210_device_iis0,
-	&s5pv210_device_spdif,
-	&samsung_asoc_idma,
-	&samsung_device_keypad,
-	&smdkv210_dm9000,
-	&smdkv210_lcd_lte480wv,
-};
-
-static void __init smdkv210_dm9000_init(void)
-{
-	unsigned int tmp;
-
-	gpio_request(S5PV210_MP01(5), "nCS5");
-	s3c_gpio_cfgpin(S5PV210_MP01(5), S3C_GPIO_SFN(2));
-	gpio_free(S5PV210_MP01(5));
-
-	tmp = (5 << S5P_SROM_BCX__TACC__SHIFT);
-	__raw_writel(tmp, S5P_SROM_BC5);
-
-	tmp = __raw_readl(S5P_SROM_BW);
-	tmp &= (S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS5__SHIFT);
-	tmp |= (1 << S5P_SROM_BW__NCS5__SHIFT);
-	__raw_writel(tmp, S5P_SROM_BW);
-}
-
-static struct i2c_board_info smdkv210_i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("24c08", 0x50), },     /* Samsung S524AD0XD1 */
-	{ I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdkv210_i2c_devs1[] __initdata = {
-	/* To Be Updated */
-};
-
-static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
-	/* To Be Updated */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
-	.no = S5PV210_GPD0(3),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkv210_bl_data = {
-	.pwm_id = 3,
-	.pwm_period_ns = 1000,
-	.enable_gpio = -1,
-};
-
-static void __init smdkv210_map_io(void)
-{
-	s5pv210_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
-	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
-}
-
-static void __init smdkv210_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init smdkv210_machine_init(void)
-{
-	s3c_pm_init();
-
-	smdkv210_dm9000_init();
-
-	samsung_keypad_set_platdata(&smdkv210_keypad_data);
-	s3c24xx_ts_set_platdata(NULL);
-
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	s3c_i2c2_set_platdata(NULL);
-	i2c_register_board_info(0, smdkv210_i2c_devs0,
-			ARRAY_SIZE(smdkv210_i2c_devs0));
-	i2c_register_board_info(1, smdkv210_i2c_devs1,
-			ARRAY_SIZE(smdkv210_i2c_devs1));
-	i2c_register_board_info(2, smdkv210_i2c_devs2,
-			ARRAY_SIZE(smdkv210_i2c_devs2));
-
-	s3c_ide_set_platdata(&smdkv210_ide_pdata);
-
-	s3c_fb_set_platdata(&smdkv210_lcd0_pdata);
-
-	s3c_hsotg_set_platdata(&smdkv210_hsotg_pdata);
-
-	platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
-
-	samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
-}
-
-MACHINE_START(SMDKV210, "SMDKV210")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pv210_init_irq,
-	.map_io		= smdkv210_map_io,
-	.init_machine	= smdkv210_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5pv210_restart,
-	.reserve	= &smdkv210_reserve,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-torbreck.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-torbreck.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-torbreck.c
- *
- * Copyright (c) 2010 aESOP Community
- *		http://www.aesop.or.kr/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define TORBRECK_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define TORBRECK_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define TORBRECK_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= TORBRECK_UCON_DEFAULT,
-		.ulcon		= TORBRECK_ULCON_DEFAULT,
-		.ufcon		= TORBRECK_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= TORBRECK_UCON_DEFAULT,
-		.ulcon		= TORBRECK_ULCON_DEFAULT,
-		.ufcon		= TORBRECK_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= TORBRECK_UCON_DEFAULT,
-		.ulcon		= TORBRECK_ULCON_DEFAULT,
-		.ufcon		= TORBRECK_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= TORBRECK_UCON_DEFAULT,
-		.ulcon		= TORBRECK_ULCON_DEFAULT,
-		.ufcon		= TORBRECK_UFCON_DEFAULT,
-	},
-};
-
-static struct platform_device *torbreck_devices[] __initdata = {
-	&s5pv210_device_iis0,
-	&s3c_device_cfcon,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_i2c2,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-};
-
-static struct i2c_board_info torbreck_i2c_devs0[] __initdata = {
-	/* To Be Updated */
-};
-
-static struct i2c_board_info torbreck_i2c_devs1[] __initdata = {
-	/* To Be Updated */
-};
-
-static struct i2c_board_info torbreck_i2c_devs2[] __initdata = {
-	/* To Be Updated */
-};
-
-static void __init torbreck_map_io(void)
-{
-	s5pv210_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
-	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init torbreck_machine_init(void)
-{
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	s3c_i2c2_set_platdata(NULL);
-	i2c_register_board_info(0, torbreck_i2c_devs0,
-			ARRAY_SIZE(torbreck_i2c_devs0));
-	i2c_register_board_info(1, torbreck_i2c_devs1,
-			ARRAY_SIZE(torbreck_i2c_devs1));
-	i2c_register_board_info(2, torbreck_i2c_devs2,
-			ARRAY_SIZE(torbreck_i2c_devs2));
-
-	platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
-}
-
-MACHINE_START(TORBRECK, "TORBRECK")
-	/* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= s5pv210_init_irq,
-	.map_io		= torbreck_map_io,
-	.init_machine	= torbreck_machine_init,
-	.init_time	= samsung_timer_init,
-	.restart	= s5pv210_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,8 @@
 #
 # Licensed under GPLv2
 
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)/arch/arm/plat-samsung/include
+
 obj-y				:=
 obj-m				:=
 obj-n				:=
@@ -12,31 +14,8 @@ obj-				:=
 
 # Core
 
-obj-y				+= common.o clock.o
-
-obj-$(CONFIG_PM)		+= pm.o
-
-obj-y				+= dma.o
+obj-$(CONFIG_PM_SLEEP)		+= pm.o sleep.o
 
 # machine support
 
-obj-$(CONFIG_MACH_AQUILA)	+= mach-aquila.o
-obj-$(CONFIG_MACH_GONI)		+= mach-goni.o
-obj-$(CONFIG_MACH_SMDKC110)	+= mach-smdkc110.o
-obj-$(CONFIG_MACH_SMDKV210)	+= mach-smdkv210.o
-obj-$(CONFIG_MACH_TORBRECK)	+= mach-torbreck.o
-
-# device support
-
-obj-y				+= dev-audio.o
-
-obj-y					+= setup-i2c0.o
-obj-$(CONFIG_S5PV210_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
-obj-$(CONFIG_S5PV210_SETUP_FIMC)	+= setup-fimc.o
-obj-$(CONFIG_S5PV210_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_S5PV210_SETUP_I2C2)	+= setup-i2c2.o
-obj-$(CONFIG_S5PV210_SETUP_IDE)		+= setup-ide.o
-obj-$(CONFIG_S5PV210_SETUP_KEYPAD)	+= setup-keypad.o
-obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
-obj-$(CONFIG_S5PV210_SETUP_SPI)		+= setup-spi.o
-obj-$(CONFIG_S5PV210_SETUP_USB_PHY) += setup-usb-phy.o
+obj-y				+= s5pv210.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Makefile.boot linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Makefile.boot
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/Makefile.boot	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-   zreladdr-y	+= 0x20008000
-params_phys-y	:= 0x20000100
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s5pv210/pm.c
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * S5PV210 - Power Management support
@@ -19,65 +19,28 @@
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
 
-#include <plat/cpu.h>
-#include <plat/pm.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-clock.h>
-
-static struct sleep_save s5pv210_core_save[] = {
-	/* Clock source */
-	SAVE_ITEM(S5P_CLK_SRC0),
-	SAVE_ITEM(S5P_CLK_SRC1),
-	SAVE_ITEM(S5P_CLK_SRC2),
-	SAVE_ITEM(S5P_CLK_SRC3),
-	SAVE_ITEM(S5P_CLK_SRC4),
-	SAVE_ITEM(S5P_CLK_SRC5),
-	SAVE_ITEM(S5P_CLK_SRC6),
-
-	/* Clock source Mask */
-	SAVE_ITEM(S5P_CLK_SRC_MASK0),
-	SAVE_ITEM(S5P_CLK_SRC_MASK1),
-
-	/* Clock Divider */
-	SAVE_ITEM(S5P_CLK_DIV0),
-	SAVE_ITEM(S5P_CLK_DIV1),
-	SAVE_ITEM(S5P_CLK_DIV2),
-	SAVE_ITEM(S5P_CLK_DIV3),
-	SAVE_ITEM(S5P_CLK_DIV4),
-	SAVE_ITEM(S5P_CLK_DIV5),
-	SAVE_ITEM(S5P_CLK_DIV6),
-	SAVE_ITEM(S5P_CLK_DIV7),
-
-	/* Clock Main Gate */
-	SAVE_ITEM(S5P_CLKGATE_MAIN0),
-	SAVE_ITEM(S5P_CLKGATE_MAIN1),
-	SAVE_ITEM(S5P_CLKGATE_MAIN2),
-
-	/* Clock source Peri Gate */
-	SAVE_ITEM(S5P_CLKGATE_PERI0),
-	SAVE_ITEM(S5P_CLKGATE_PERI1),
+#include <asm/cacheflush.h>
+#include <asm/suspend.h>
 
-	/* Clock source SCLK Gate */
-	SAVE_ITEM(S5P_CLKGATE_SCLK0),
-	SAVE_ITEM(S5P_CLKGATE_SCLK1),
+#include <plat/pm-common.h>
 
-	/* Clock IP Clock gate */
-	SAVE_ITEM(S5P_CLKGATE_IP0),
-	SAVE_ITEM(S5P_CLKGATE_IP1),
-	SAVE_ITEM(S5P_CLKGATE_IP2),
-	SAVE_ITEM(S5P_CLKGATE_IP3),
-	SAVE_ITEM(S5P_CLKGATE_IP4),
+#include <mach/regs-clock.h>
 
-	/* Clock Blcok and Bus gate */
-	SAVE_ITEM(S5P_CLKGATE_BLOCK),
-	SAVE_ITEM(S5P_CLKGATE_BUS0),
+#include "common.h"
 
+static struct sleep_save s5pv210_core_save[] = {
 	/* Clock ETC */
-	SAVE_ITEM(S5P_CLK_OUT),
 	SAVE_ITEM(S5P_MDNIE_SEL),
 };
 
+/*
+ * VIC wake-up support (TODO)
+ */
+static u32 s5pv210_irqwake_intmask = 0xffffffff;
+
+/*
+ * Suspend helpers.
+ */
 static int s5pv210_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
@@ -102,8 +65,12 @@ static void s5pv210_pm_prepare(void)
 {
 	unsigned int tmp;
 
+	/* Set wake-up mask registers */
+	__raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+	__raw_writel(s5pv210_irqwake_intmask, S5P_WAKEUP_MASK);
+
 	/* ensure at least INFORM0 has the resume address */
-	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+	__raw_writel(virt_to_phys(s5pv210_cpu_resume), S5P_INFORM0);
 
 	tmp = __raw_readl(S5P_SLEEP_CFG);
 	tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
@@ -123,26 +90,70 @@ static void s5pv210_pm_prepare(void)
 	s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
 }
 
-static int s5pv210_pm_add(struct device *dev, struct subsys_interface *sif)
+/*
+ * Suspend operations.
+ */
+static int s5pv210_suspend_enter(suspend_state_t state)
 {
-	pm_cpu_prep = s5pv210_pm_prepare;
-	pm_cpu_sleep = s5pv210_cpu_suspend;
+	int ret;
+
+	s3c_pm_debug_init();
+
+	S3C_PMDBG("%s: suspending the system...\n", __func__);
+
+	S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
+			s5pv210_irqwake_intmask, exynos_get_eint_wake_mask());
+
+	if (s5pv210_irqwake_intmask == -1U
+	    && exynos_get_eint_wake_mask() == -1U) {
+		pr_err("%s: No wake-up sources!\n", __func__);
+		pr_err("%s: Aborting sleep\n", __func__);
+		return -EINVAL;
+	}
+
+	s3c_pm_save_uarts();
+	s5pv210_pm_prepare();
+	flush_cache_all();
+	s3c_pm_check_store();
+
+	ret = cpu_suspend(0, s5pv210_cpu_suspend);
+	if (ret)
+		return ret;
+
+	s3c_pm_restore_uarts();
+
+	S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
+			__raw_readl(S5P_WAKEUP_STAT));
+
+	s3c_pm_check_restore();
+
+	S3C_PMDBG("%s: resuming the system...\n", __func__);
 
 	return 0;
 }
 
-static struct subsys_interface s5pv210_pm_interface = {
-	.name		= "s5pv210_pm",
-	.subsys		= &s5pv210_subsys,
-	.add_dev	= s5pv210_pm_add,
-};
+static int s5pv210_suspend_prepare(void)
+{
+	s3c_pm_check_prepare();
 
-static __init int s5pv210_pm_drvinit(void)
+	return 0;
+}
+
+static void s5pv210_suspend_finish(void)
 {
-	return subsys_interface_register(&s5pv210_pm_interface);
+	s3c_pm_check_cleanup();
 }
-arch_initcall(s5pv210_pm_drvinit);
 
+static const struct platform_suspend_ops s5pv210_suspend_ops = {
+	.enter		= s5pv210_suspend_enter,
+	.prepare	= s5pv210_suspend_prepare,
+	.finish		= s5pv210_suspend_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+/*
+ * Syscore operations used to delay restore of certain registers.
+ */
 static void s5pv210_pm_resume(void)
 {
 	u32 tmp;
@@ -159,9 +170,11 @@ static struct syscore_ops s5pv210_pm_sys
 	.resume		= s5pv210_pm_resume,
 };
 
-static __init int s5pv210_pm_syscore_init(void)
+/*
+ * Initialization entry point.
+ */
+void __init s5pv210_pm_init(void)
 {
 	register_syscore_ops(&s5pv210_pm_syscore_ops);
-	return 0;
+	suspend_set_ops(&s5pv210_suspend_ops);
 }
-arch_initcall(s5pv210_pm_syscore_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/s5pv210.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/s5pv210.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/s5pv210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/s5pv210.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * Samsung's S5PC110/S5PV210 flattened device tree enabled machine.
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+
+#include <plat/map-base.h>
+#include <mach/regs-clock.h>
+
+#include "common.h"
+
+static int __init s5pv210_fdt_map_sys(unsigned long node, const char *uname,
+					int depth, void *data)
+{
+	struct map_desc iodesc;
+	const __be32 *reg;
+	int len;
+
+	if (!of_flat_dt_is_compatible(node, "samsung,s5pv210-clock"))
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "reg", &len);
+	if (reg == NULL || len != (sizeof(unsigned long) * 2))
+		return 0;
+
+	iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
+	iodesc.length = be32_to_cpu(reg[1]) - 1;
+	iodesc.virtual = (unsigned long)S3C_VA_SYS;
+	iodesc.type = MT_DEVICE;
+	iotable_init(&iodesc, 1);
+
+	return 1;
+}
+
+static void __init s5pv210_dt_map_io(void)
+{
+	debug_ll_io_init();
+
+	of_scan_flat_dt(s5pv210_fdt_map_sys, NULL);
+}
+
+static void s5pv210_dt_restart(enum reboot_mode mode, const char *cmd)
+{
+	__raw_writel(0x1, S5P_SWRESET);
+}
+
+static void __init s5pv210_dt_init_late(void)
+{
+	platform_device_register_simple("s5pv210-cpufreq", -1, NULL, 0);
+	s5pv210_pm_init();
+}
+
+static char const *s5pv210_dt_compat[] __initconst = {
+	"samsung,s5pc110",
+	"samsung,s5pv210",
+	NULL
+};
+
+DT_MACHINE_START(S5PV210_DT, "Samsung S5PC110/S5PV210-based board")
+	.dt_compat = s5pv210_dt_compat,
+	.map_io = s5pv210_dt_map_io,
+	.restart = s5pv210_dt_restart,
+	.init_late = s5pv210_dt_init_late,
+MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-fb-24bpp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-fb-24bpp.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-fb-24bpp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-fb-24bpp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/* linux/arch/arm/plat-s5pv210/setup-fb-24bpp.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Base s5pv210 setup information for 24bpp LCD framebuffer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <plat/fb.h>
-#include <mach/regs-clock.h>
-#include <plat/gpio-cfg.h>
-
-static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr)
-{
-	s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
-
-	for (; nr > 0; nr--, base++)
-		s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-
-void s5pv210_fb_gpio_setup_24bpp(void)
-{
-	s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8);
-	s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8);
-	s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8);
-	s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4);
-
-	/* Set DISPLAY_CONTROL register for Display path selection.
-	 *
-	 * ouput   |   RGB   |   I80   |   ITU
-	 * -----------------------------------
-	 *  00     |   MIE   |  FIMD   |  FIMD
-	 *  01     | MDNIE   | MDNIE   |  FIMD
-	 *  10     |  FIMD   |  FIMD   |  FIMD
-	 *  11     |  FIMD   |  FIMD   |  FIMD
-	 */
-	writel(0x2, S5P_MDNIE_SEL);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-fimc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-fimc.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-fimc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5PV210 camera interface GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-#include <plat/camport.h>
-
-int s5pv210_fimc_setup_gpio(enum s5p_camport_id id)
-{
-	u32 gpio8, gpio5;
-	int ret;
-
-	switch (id) {
-	case S5P_CAMPORT_A:
-		gpio8 = S5PV210_GPE0(0);
-		gpio5 = S5PV210_GPE1(0);
-		break;
-
-	case S5P_CAMPORT_B:
-		gpio8 = S5PV210_GPJ0(0);
-		gpio5 = S5PV210_GPJ1(0);
-		break;
-
-	default:
-		WARN(1, "Wrong camport id: %d\n", id);
-		return -EINVAL;
-	}
-
-	ret = s3c_gpio_cfgall_range(gpio8, 8, S3C_GPIO_SFN(2),
-				    S3C_GPIO_PULL_UP);
-	if (ret)
-		return ret;
-
-	return s3c_gpio_cfgall_range(gpio5, 5, S3C_GPIO_SFN(2),
-				     S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c0.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c1.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c1.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c1.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C1 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c1.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c2.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c2.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-i2c2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c2.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C2 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c2_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-ide.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-ide.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-ide.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-ide.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV210 setup information for IDE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-
-static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr)
-{
-	s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
-
-	for (; nr > 0; nr--, base++)
-		s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-void s5pv210_ide_setup_gpio(void)
-{
-	/* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
-	s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8);
-
-	/* CF_Data[0 - 7] */
-	s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8);
-
-	/* CF_Data[8 - 15] */
-	s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8);
-
-	/* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
-	s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-keypad.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-keypad.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv210/setup-keypad.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
-{
-	/* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3));
-
-	/* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3));
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,103 +0,0 @@
-/* linux/arch/arm/plat-s5pc1xx/setup-sdhci-gpio.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV210 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-
-void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG0/GPG1 pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2));
-
-	switch (width) {
-	case 8:
-		/* GPG1[3:6] special-function 3 */
-		s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
-	case 4:
-		/* GPG0[3:6] special-function 2 */
-		s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
-	}
-}
-
-void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG1[0:1] pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2));
-
-	/* Data pin GPG1[3:6] to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2));
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
-	}
-}
-
-void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG2[0:1] pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2));
-
-	switch (width) {
-	case 8:
-		/* Data pin GPG3[3:6] to special-function 3 */
-		s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3));
-	case 4:
-		/* Data pin GPG2[3:6] to special-function 2 */
-		s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2));
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
-	}
-}
-
-void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
-	/* Set all the necessary GPG3[0:1] pins to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2));
-
-	/* Data pin GPG3[3:6] to special-function 2 */
-	s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2));
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP);
-		s3c_gpio_cfgpin(S5PV210_GPG3(2), S3C_GPIO_SFN(2));
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-spi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-spi.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-spi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
-	s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
-	s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgall_range(S5PV210_GPB(2), 2,
-				S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
-	s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
-	s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgall_range(S5PV210_GPB(6), 2,
-				S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-	return 0;
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-usb-phy.c linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-usb-phy.c
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/setup-usb-phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/setup-usb-phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-usb-hsotg-phy.h>
-#include <plat/usb-phy.h>
-
-#define S5PV210_USB_PHY_CON	(S3C_VA_SYS + 0xE80C)
-#define S5PV210_USB_PHY0_EN	(1 << 0)
-#define S5PV210_USB_PHY1_EN	(1 << 1)
-
-static int s5pv210_usb_otgphy_init(struct platform_device *pdev)
-{
-	struct clk *xusbxti;
-	u32 phyclk;
-
-	writel(readl(S5PV210_USB_PHY_CON) | S5PV210_USB_PHY0_EN,
-			S5PV210_USB_PHY_CON);
-
-	/* set clock frequency for PLL */
-	phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
-
-	xusbxti = clk_get(&pdev->dev, "xusbxti");
-	if (xusbxti && !IS_ERR(xusbxti)) {
-		switch (clk_get_rate(xusbxti)) {
-		case 12 * MHZ:
-			phyclk |= S3C_PHYCLK_CLKSEL_12M;
-			break;
-		case 24 * MHZ:
-			phyclk |= S3C_PHYCLK_CLKSEL_24M;
-			break;
-		default:
-		case 48 * MHZ:
-			/* default reference clock */
-			break;
-		}
-		clk_put(xusbxti);
-	}
-
-	/* TODO: select external clock/oscillator */
-	writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
-
-	/* set to normal OTG PHY */
-	writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
-	mdelay(1);
-
-	/* reset OTG PHY and Link */
-	writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
-			S3C_RSTCON);
-	udelay(20);	/* at-least 10uS */
-	writel(0, S3C_RSTCON);
-
-	return 0;
-}
-
-static int s5pv210_usb_otgphy_exit(struct platform_device *pdev)
-{
-	writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
-				S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
-
-	writel(readl(S5PV210_USB_PHY_CON) & ~S5PV210_USB_PHY0_EN,
-			S5PV210_USB_PHY_CON);
-
-	return 0;
-}
-
-int s5p_usb_phy_init(struct platform_device *pdev, int type)
-{
-	if (type == USB_PHY_TYPE_DEVICE)
-		return s5pv210_usb_otgphy_init(pdev);
-
-	return -EINVAL;
-}
-
-int s5p_usb_phy_exit(struct platform_device *pdev, int type)
-{
-	if (type == USB_PHY_TYPE_DEVICE)
-		return s5pv210_usb_otgphy_exit(pdev);
-
-	return -EINVAL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-s5pv210/sleep.S linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/sleep.S
--- linux-libre-3.16-gnu/arch/arm/mach-s5pv210/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-s5pv210/sleep.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV210 Sleep Code
+ * Based on S3C64XX sleep code by:
+ *	Ben Dooks, (c) 2008 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+	.data
+	.align
+
+	/*
+	 * sleep magic, to allow the bootloader to check for an valid
+	 * image to resume to. Must be the first word before the
+	 * s3c_cpu_resume entry.
+	 */
+
+	.word	0x2bedf00d
+
+	/*
+	 * s3c_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 */
+
+ENTRY(s5pv210_cpu_resume)
+	b	cpu_resume
+ENDPROC(s5pv210_cpu_resume)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-sa1100/include/mach/memory.h linux-libre-3.17-rc7-gnu/arch/arm/mach-sa1100/include/mach/memory.h
--- linux-libre-3.16-gnu/arch/arm/mach-sa1100/include/mach/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-sa1100/include/mach/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,11 +10,6 @@
 #include <asm/sizes.h>
 
 /*
- * Physical DRAM offset is 0xc0000000 on the SA1100
- */
-#define PLAT_PHYS_OFFSET	UL(0xc0000000)
-
-/*
  * Because of the wide memory address space between physical RAM banks on the
  * SA1100, it's much convenient to use Linux's SparseMEM support to implement
  * our memory map representation.  Assuming all memory nodes have equal access
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-ape6evm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-ape6evm.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-ape6evm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-ape6evm.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,12 +33,14 @@
 #include <linux/regulator/machine.h>
 #include <linux/sh_clk.h>
 #include <linux/smsc911x.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a73a4.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a73a4.h"
+
 /* LEDS */
 static struct gpio_led ape6evm_leds[] = {
 	{
@@ -248,29 +250,29 @@ static void __init ape6evm_add_standard_
 
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
-	platform_device_register_resndata(&platform_bus, "smsc911x", -1,
+	platform_device_register_resndata(NULL, "smsc911x", -1,
 					  lan9220_res, ARRAY_SIZE(lan9220_res),
 					  &lan9220_data, sizeof(lan9220_data));
 
 	regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
 				     ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
-	platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
+	platform_device_register_resndata(NULL, "sh_mmcif", 0,
 					  mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
 					  &mmcif0_pdata, sizeof(mmcif0_pdata));
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+	platform_device_register_data(NULL, "reg-fixed-voltage", 2,
 				      &vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
 					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 					  &sdhi0_pdata, sizeof(sdhi0_pdata));
 	regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
 				     ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
 					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
 					  &sdhi1_pdata, sizeof(sdhi1_pdata));
-	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+	platform_device_register_data(NULL, "gpio-keys", -1,
 				      &ape6evm_keys_pdata,
 				      sizeof(ape6evm_keys_pdata));
-	platform_device_register_data(&platform_bus, "leds-gpio", -1,
+	platform_device_register_data(NULL, "leds-gpio", -1,
 				      &ape6evm_leds_pdata,
 				      sizeof(ape6evm_leds_pdata));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-ape6evm-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-ape6evm-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-ape6evm-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-ape6evm-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,11 +24,13 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_device.h>
 #include <linux/sh_clk.h>
-#include <mach/common.h>
-#include <mach/r8a73a4.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "r8a73a4.h"
+
 static void __init ape6evm_add_standard_devices(void)
 {
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-armadillo800eva.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-armadillo800eva.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-armadillo800eva.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-armadillo800eva.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,9 +45,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/i2c-gpio.h>
 #include <linux/reboot.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7740.h>
+
 #include <media/mt9t112.h>
 #include <media/sh_mobile_ceu.h>
 #include <media/soc_camera.h>
@@ -62,6 +60,10 @@
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
 #include "sh-gpio.h"
 
 /*
@@ -578,6 +580,40 @@ static struct platform_device hdmi_lcdc_
 	},
 };
 
+/* LEDS */
+static struct gpio_led gpio_leds[] = {
+	{
+		.name		= "LED3",
+		.gpio		= 102,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}, {
+		.name		= "LED4",
+		.gpio		= 111,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}, {
+		.name		= "LED5",
+		.gpio		= 110,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}, {
+		.name		= "LED6",
+		.gpio		= 177,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+};
+
+static struct gpio_led_platform_data leds_gpio_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio_device = {
+	.name   = "leds-gpio",
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &leds_gpio_info,
+	},
+};
+
 /* GPIO KEY */
 #define GPIO_KEY(c, g, d, ...) \
 	{ .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
@@ -998,6 +1034,8 @@ static struct platform_device fsi_wm8978
 	.id	= 0,
 	.dev	= {
 		.platform_data	= &fsi_wm8978_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
 	},
 };
 
@@ -1021,6 +1059,8 @@ static struct platform_device fsi_hdmi_d
 	.id	= 1,
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 };
 
@@ -1069,6 +1109,7 @@ static struct platform_device *eva_devic
 	&lcdc0_device,
 	&pwm_device,
 	&pwm_backlight_device,
+	&leds_gpio_device,
 	&gpio_keys_device,
 	&sh_eth_device,
 	&vcc_sdhi0,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-armadillo800eva-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-armadillo800eva-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-armadillo800eva-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,11 +24,13 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
-#include <mach/common.h>
-#include <mach/r8a7740.h>
+
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include "common.h"
+#include "r8a7740.h"
+
 /*
  * CON1		Camera Module
  * CON2		Extension Bus
@@ -53,11 +55,11 @@
  * CON22	Serial
  * CON23	LAN
  * CON24	USB3
- * LED1		Camera LED(Yellow)
+ * LED1		Camera LED (Yellow)
  * LED2		Power LED (Green)
- * ED3-LED6	User LED(Yellow)
- * LED7		LAN link LED(Green)
- * LED8		LAN activity LED(Yellow)
+ * LED3-LED6	User LED (Yellow)
+ * LED7		LAN link LED (Green)
+ * LED8		LAN activity LED (Yellow)
  */
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-bockw.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-bockw.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-bockw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-bockw.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,14 +34,16 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb/renesas_usbhs.h>
+
 #include <media/soc_camera.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7778.h>
 #include <asm/mach/arch.h>
 #include <sound/rcar_snd.h>
 #include <sound/simple_card.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
 #define FPGA	0x18200000
 #define IRQ0MR	0x30
 #define COMCTLR	0x101c
@@ -177,7 +179,7 @@ static struct renesas_usbhs_platform_inf
 #define USB1_DEVICE	"renesas_usbhs"
 #define ADD_USB_FUNC_DEVICE_IF_POSSIBLE()			\
 	platform_device_register_resndata(			\
-		&platform_bus, "renesas_usbhs", -1,		\
+		NULL, "renesas_usbhs", -1,			\
 		usbhsf_resources,				\
 		ARRAY_SIZE(usbhsf_resources),			\
 		&usbhs_info, sizeof(struct renesas_usbhs_platform_info))
@@ -236,7 +238,6 @@ static struct sh_eth_plat_data ether_pla
 };
 
 static struct platform_device_info ether_info __initdata = {
-	.parent		= &platform_bus,
 	.name		= "r8a777x-ether",
 	.id		= -1,
 	.res		= ether_resources,
@@ -322,7 +323,6 @@ static struct resource vin##idx##_resour
 };									\
 									\
 static struct platform_device_info vin##idx##_info __initdata = {	\
-	.parent		= &platform_bus,				\
 	.name		= "r8a7778-vin",				\
 	.id		= idx,						\
 	.res		= vin##idx##_resources,				\
@@ -621,10 +621,10 @@ static void __init bockw_init(void)
 	/* VIN1 has a pin conflict with Ether */
 	if (!IS_ENABLED(CONFIG_SH_ETH))
 		platform_device_register_full(&vin1_info);
-	platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
+	platform_device_register_data(NULL, "soc-camera-pdrv", 0,
 				      &iclink0_ml86v7667,
 				      sizeof(iclink0_ml86v7667));
-	platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+	platform_device_register_data(NULL, "soc-camera-pdrv", 1,
 				      &iclink1_ml86v7667,
 				      sizeof(iclink1_ml86v7667));
 
@@ -637,12 +637,12 @@ static void __init bockw_init(void)
 	r8a7778_pinmux_init();
 
 	platform_device_register_resndata(
-		&platform_bus, "sh_mmcif", -1,
+		NULL, "sh_mmcif", -1,
 		mmc_resources, ARRAY_SIZE(mmc_resources),
 		&sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data));
 
 	platform_device_register_resndata(
-		&platform_bus, "rcar_usb_phy", -1,
+		NULL, "rcar_usb_phy", -1,
 		usb_phy_resources,
 		ARRAY_SIZE(usb_phy_resources),
 		&usb_phy_platform_data,
@@ -668,7 +668,7 @@ static void __init bockw_init(void)
 		iowrite16(val, fpga + IRQ0MR);
 
 		platform_device_register_resndata(
-			&platform_bus, "smsc911x", -1,
+			NULL, "smsc911x", -1,
 			smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
 			&smsc911x_data, sizeof(smsc911x_data));
 	}
@@ -685,7 +685,7 @@ static void __init bockw_init(void)
 		iounmap(base);
 
 		platform_device_register_resndata(
-			&platform_bus, "sh_mobile_sdhi", 0,
+			NULL, "sh_mobile_sdhi", 0,
 			sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 			&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
 	}
@@ -700,7 +700,7 @@ static void __init bockw_init(void)
 		"ak4554-adc-dac", 1, NULL, 0);
 
 	pdev = platform_device_register_resndata(
-		&platform_bus, "rcar_sound", -1,
+		NULL, "rcar_sound", -1,
 		rsnd_resources, ARRAY_SIZE(rsnd_resources),
 		&rsnd_info, sizeof(rsnd_info));
 
@@ -710,7 +710,6 @@ static void __init bockw_init(void)
 
 	for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
 		struct platform_device_info cardinfo = {
-			.parent         = &platform_bus,
 			.name           = "asoc-simple-card",
 			.id             = i,
 			.data           = &rsnd_card_info[i],
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-bockw-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-bockw-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-bockw-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-bockw-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,10 +19,12 @@
  */
 
 #include <linux/of_platform.h>
-#include <mach/common.h>
-#include <mach/r8a7778.h>
+
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "r8a7778.h"
+
 /*
  *	see board-bock.c for checking detail of dip-switch
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-genmai.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-genmai.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-genmai.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-genmai.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,12 +25,14 @@
 #include <linux/sh_eth.h>
 #include <linux/spi/rspi.h>
 #include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r7s72100.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r7s72100.h"
+
 /* Ether */
 static const struct sh_eth_plat_data ether_pdata __initconst = {
 	.phy			= 0x00, /* PD60610 */
@@ -46,7 +48,6 @@ static const struct resource ether_resou
 };
 
 static const struct platform_device_info ether_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "r7s72100-ether",
 	.id		= -1,
 	.res		= ether_resources,
@@ -76,7 +77,7 @@ static const struct rspi_plat_data rspi_
 };
 
 #define r7s72100_register_rspi(idx)					   \
-	platform_device_register_resndata(&platform_bus, "rspi-rz", idx,   \
+	platform_device_register_resndata(NULL, "rspi-rz", idx,            \
 					rspi##idx##_resources,		   \
 					ARRAY_SIZE(rspi##idx##_resources), \
 					&rspi_pdata, sizeof(rspi_pdata))
@@ -118,7 +119,7 @@ R7S72100_SCIF(6, 0xe800a000, gic_iid(245
 R7S72100_SCIF(7, 0xe800a800, gic_iid(249));
 
 #define r7s72100_register_scif(index)					       \
-	platform_device_register_resndata(&platform_bus, "sh-sci", index,      \
+	platform_device_register_resndata(NULL, "sh-sci", index,               \
 					  scif##index##_resources,	       \
 					  ARRAY_SIZE(scif##index##_resources), \
 					  &scif##index##_platform_data,	       \
@@ -154,7 +155,7 @@ static const char * const genmai_boards_
 };
 
 DT_MACHINE_START(GENMAI_DT, "genmai")
-	.init_early	= r7s72100_init_early,
+	.init_early	= shmobile_init_delay,
 	.init_machine	= genmai_add_standard_devices,
 	.dt_compat	= genmai_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-genmai-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-genmai-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-genmai-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-genmai-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,12 +20,14 @@
 
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r7s72100.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "clock.h"
+#include "common.h"
+#include "r7s72100.h"
+
 /*
  * This is a really crude hack to provide clkdev support to platform
  * devices until they get moved to DT.
@@ -47,7 +49,7 @@ static const char * const genmai_boards_
 };
 
 DT_MACHINE_START(GENMAI_DT, "genmai")
-	.init_early	= r7s72100_init_early,
+	.init_early	= shmobile_init_delay,
 	.init_machine	= genmai_add_standard_devices,
 	.dt_compat	= genmai_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-koelsch.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-koelsch.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-koelsch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-koelsch.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,13 +45,15 @@
 #include <linux/spi/flash.h>
 #include <linux/spi/rspi.h>
 #include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
 /* DU */
 static struct rcar_du_encoder_data koelsch_du_encoders[] = {
 	{
@@ -118,7 +120,6 @@ static const struct resource ether_resou
 };
 
 static const struct platform_device_info ether_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "r8a7791-ether",
 	.id		= -1,
 	.res		= ether_resources,
@@ -230,7 +231,6 @@ static const struct resource sata0_resou
 };
 
 static const struct platform_device_info sata0_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "sata-r8a7791",
 	.id		= 0,
 	.res		= sata0_resources,
@@ -439,13 +439,13 @@ static void __init koelsch_add_standard_
 	r8a7791_pinmux_init();
 	r8a7791_add_standard_devices();
 	platform_device_register_full(&ether_info);
-	platform_device_register_data(&platform_bus, "leds-gpio", -1,
+	platform_device_register_data(NULL, "leds-gpio", -1,
 				      &koelsch_leds_pdata,
 				      sizeof(koelsch_leds_pdata));
-	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+	platform_device_register_data(NULL, "gpio-keys", -1,
 				      &koelsch_keys_pdata,
 				      sizeof(koelsch_keys_pdata));
-	platform_device_register_resndata(&platform_bus, "qspi", 0,
+	platform_device_register_resndata(NULL, "qspi", 0,
 					  qspi_resources,
 					  ARRAY_SIZE(qspi_resources),
 					  &qspi_pdata, sizeof(qspi_pdata));
@@ -460,28 +460,28 @@ static void __init koelsch_add_standard_
 	koelsch_add_i2c(4);
 	koelsch_add_i2c(5);
 
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 0,
+	platform_device_register_data(NULL, "reg-fixed-voltage", 0,
 				      &vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 1,
+	platform_device_register_data(NULL, "reg-fixed-voltage", 1,
 				      &vcc_sdhi1_info, sizeof(struct fixed_voltage_config));
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+	platform_device_register_data(NULL, "reg-fixed-voltage", 2,
 				      &vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
-	platform_device_register_data(&platform_bus, "gpio-regulator", 0,
+	platform_device_register_data(NULL, "gpio-regulator", 0,
 				      &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
-	platform_device_register_data(&platform_bus, "gpio-regulator", 1,
+	platform_device_register_data(NULL, "gpio-regulator", 1,
 				      &vccq_sdhi1_info, sizeof(struct gpio_regulator_config));
-	platform_device_register_data(&platform_bus, "gpio-regulator", 2,
+	platform_device_register_data(NULL, "gpio-regulator", 2,
 				      &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
 
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
 					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 					  &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
 
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
 					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
 					  &sdhi1_info, sizeof(struct sh_mobile_sdhi_info));
 
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
 					  sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
 					  &sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
 
@@ -526,5 +526,6 @@ DT_MACHINE_START(KOELSCH_DT, "koelsch")
 	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= koelsch_init,
 	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= koelsch_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-koelsch-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-koelsch-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-koelsch-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-koelsch-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,13 +23,15 @@
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/rcar-gen2.h>
-#include <mach/r8a7791.h>
+
 #include <asm/mach/arch.h>
 
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
 /* DU */
 static struct rcar_du_encoder_data koelsch_du_encoders[] = {
 	{
@@ -92,24 +94,9 @@ static const struct clk_name clk_names[]
 	{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
 };
 
-/*
- * This is a really crude hack to work around core platform clock issues
- */
-static const struct clk_name clk_enables[] __initconst = {
-	{ "ether", NULL, "ee700000.ethernet" },
-	{ "i2c2", NULL, "e6530000.i2c" },
-	{ "msiof0", NULL, "e6e20000.spi" },
-	{ "qspi_mod", NULL, "e6b10000.spi" },
-	{ "sdhi0", NULL, "ee100000.sd" },
-	{ "sdhi1", NULL, "ee140000.sd" },
-	{ "sdhi2", NULL, "ee160000.sd" },
-	{ "thermal", NULL, "e61f0000.thermal" },
-};
-
 static void __init koelsch_add_standard_devices(void)
 {
 	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
-	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
@@ -128,5 +115,6 @@ DT_MACHINE_START(KOELSCH_DT, "koelsch")
 	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= koelsch_add_standard_devices,
 	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= koelsch_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-kzm9g.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-kzm9g.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-kzm9g.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-kzm9g.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,16 +41,18 @@
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/renesas_usbhs.h>
 #include <linux/videodev2.h>
+
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <video/sh_mobile_lcdc.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
 /*
  * external GPIO
  */
@@ -603,6 +605,8 @@ static struct platform_device fsi_ak4648
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi2_ak4648_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-kzm9g-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-kzm9g-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-kzm9g-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-kzm9g-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,12 +25,14 @@
 #include <linux/irq.h>
 #include <linux/input.h>
 #include <linux/of_platform.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
+
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "sh73a0.h"
+
 static void __init kzm_init(void)
 {
 	sh73a0_add_standard_devices_dt();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-lager.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-lager.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-lager.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-lager.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/camera-rcar.h>
 #include <linux/platform_data/gpio-rcar.h>
@@ -43,22 +45,23 @@
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/rspi.h>
+#include <linux/spi/spi.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/renesas_usbhs.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7790.h>
+
 #include <media/soc_camera.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/mtd.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/rspi.h>
-#include <linux/spi/spi.h>
 #include <sound/rcar_snd.h>
 #include <sound/simple_card.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
 /*
  * SSI-AK4643
  *
@@ -277,7 +280,6 @@ static const struct resource ether_resou
 };
 
 static const struct platform_device_info ether_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "r8a7790-ether",
 	.id		= -1,
 	.res		= ether_resources,
@@ -354,7 +356,6 @@ static void __init lager_add_vin_device(
 					struct rcar_vin_platform_data *pdata)
 {
 	struct platform_device_info vin_info = {
-		.parent		= &platform_bus,
 		.name		= "r8a7790-vin",
 		.id		= idx,
 		.res		= &vin_resources[idx * 2],
@@ -391,7 +392,7 @@ LAGER_CAMERA(1, "adv7180", 0x20, NULL, R
 
 static void __init lager_add_camera1_device(void)
 {
-	platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+	platform_device_register_data(NULL, "soc-camera-pdrv", 1,
 				      &cam1_link, sizeof(cam1_link));
 	lager_add_vin_device(1, &vin1_pdata);
 }
@@ -403,7 +404,6 @@ static const struct resource sata1_resou
 };
 
 static const struct platform_device_info sata1_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "sata-r8a7790",
 	.id		= 1,
 	.res		= sata1_resources,
@@ -533,7 +533,7 @@ static struct usbhs_private usbhs_priv _
 static void __init lager_register_usbhs(void)
 {
 	usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
-	platform_device_register_resndata(&platform_bus,
+	platform_device_register_resndata(NULL,
 					  "renesas_usbhs", -1,
 					  usbhs_resources,
 					  ARRAY_SIZE(usbhs_resources),
@@ -608,7 +608,6 @@ static struct asoc_simple_card_info rsnd
 static void __init lager_add_rsnd_device(void)
 {
 	struct platform_device_info cardinfo = {
-		.parent         = &platform_bus,
 		.name           = "asoc-simple-card",
 		.id             = -1,
 		.data           = &rsnd_card_info,
@@ -620,7 +619,7 @@ static void __init lager_add_rsnd_device
 				ARRAY_SIZE(i2c2_devices));
 
 	platform_device_register_resndata(
-		&platform_bus, "rcar_sound", -1,
+		NULL, "rcar_sound", -1,
 		rsnd_resources, ARRAY_SIZE(rsnd_resources),
 		&rsnd_info, sizeof(rsnd_info));
 
@@ -663,7 +662,6 @@ static const struct resource pci1_resour
 };
 
 static const struct platform_device_info pci1_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "pci-rcar-gen2",
 	.id		= 1,
 	.res		= pci1_resources,
@@ -684,7 +682,6 @@ static const struct resource pci2_resour
 };
 
 static const struct platform_device_info pci2_info __initconst = {
-	.parent		= &platform_bus,
 	.name		= "pci-rcar-gen2",
 	.id		= 2,
 	.res		= pci2_resources,
@@ -795,16 +792,16 @@ static void __init lager_add_standard_de
 	r8a7790_pinmux_init();
 
 	r8a7790_add_standard_devices();
-	platform_device_register_data(&platform_bus, "leds-gpio", -1,
+	platform_device_register_data(NULL, "leds-gpio", -1,
 				      &lager_leds_pdata,
 				      sizeof(lager_leds_pdata));
-	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+	platform_device_register_data(NULL, "gpio-keys", -1,
 				      &lager_keys_pdata,
 				      sizeof(lager_keys_pdata));
 	regulator_register_always_on(fixed_regulator_idx++,
 				     "fixed-3.3V", fixed3v3_power_consumers,
 				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-	platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
+	platform_device_register_resndata(NULL, "sh_mmcif", 1,
 					  mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
 					  &mmcif1_pdata, sizeof(mmcif1_pdata));
 
@@ -812,27 +809,27 @@ static void __init lager_add_standard_de
 
 	lager_add_du_device();
 
-	platform_device_register_resndata(&platform_bus, "qspi", 0,
+	platform_device_register_resndata(NULL, "qspi", 0,
 					  qspi_resources,
 					  ARRAY_SIZE(qspi_resources),
 					  &qspi_pdata, sizeof(qspi_pdata));
 	spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
 
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+	platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
 				      &vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
-	platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+	platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
 				      &vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
 
-	platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+	platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
 				      &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
-	platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+	platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
 				      &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
 
 	lager_add_camera1_device();
 
 	platform_device_register_full(&sata1_info);
 
-	platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
+	platform_device_register_resndata(NULL, "usb_phy_rcar_gen2",
 					  -1, usbhs_phy_resources,
 					  ARRAY_SIZE(usbhs_phy_resources),
 					  &usbhs_phy_pdata,
@@ -843,10 +840,10 @@ static void __init lager_add_standard_de
 
 	lager_add_rsnd_device();
 
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
 					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 					  &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
-	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+	platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
 					  sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
 					  &sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
 }
@@ -886,9 +883,10 @@ static const char * const lager_boards_c
 
 DT_MACHINE_START(LAGER_DT, "lager")
 	.smp		= smp_ops(r8a7790_smp_ops),
-	.init_early	= r8a7790_init_early,
+	.init_early	= shmobile_init_delay,
 	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= lager_init,
 	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= lager_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-lager-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-lager-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-lager-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-lager-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,13 +22,15 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/rcar-gen2.h>
-#include <mach/r8a7790.h>
+
 #include <asm/mach/arch.h>
 
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
 /* DU */
 static struct rcar_du_encoder_data lager_du_encoders[] = {
 	{
@@ -98,23 +100,9 @@ static const struct clk_name clk_names[]
 	{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
 };
 
-/*
- * This is a really crude hack to work around core platform clock issues
- */
-static const struct clk_name clk_enables[] __initconst = {
-	{ "ether", NULL, "ee700000.ethernet" },
-	{ "msiof1", NULL, "e6e10000.spi" },
-	{ "mmcif1", NULL, "ee220000.mmc" },
-	{ "qspi_mod", NULL, "e6b10000.spi" },
-	{ "sdhi0", NULL, "ee100000.sd" },
-	{ "sdhi2", NULL, "ee140000.sd" },
-	{ "thermal", NULL, "e61f0000.thermal" },
-};
-
 static void __init lager_add_standard_devices(void)
 {
 	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
-	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
@@ -129,9 +117,10 @@ static const char *lager_boards_compat_d
 
 DT_MACHINE_START(LAGER_DT, "lager")
 	.smp		= smp_ops(r8a7790_smp_ops),
-	.init_early	= r8a7790_init_early,
+	.init_early	= shmobile_init_delay,
 	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= lager_add_standard_devices,
 	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= lager_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-mackerel.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-mackerel.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-mackerel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-mackerel.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,10 +47,11 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
-#include <linux/sh_intc.h>
+#include <linux/sh_clk.h>
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/renesas_usbhs.h>
 #include <linux/dma-mapping.h>
+
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
@@ -58,15 +59,14 @@
 #include <media/soc_camera_platform.h>
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
-
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/sh7372.h>
-
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
 #include "sh-gpio.h"
+#include "sh7372.h"
 
 /*
  * Address	Interface		BusWidth	note
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_d
 	.id	= 1,
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 };
 
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi2_ak4643_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-marzen.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-marzen.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-marzen.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-marzen.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,14 +41,16 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
+
 #include <media/soc_camera.h>
-#include <mach/r8a7779.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/traps.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
 /* Fixed 3.3V regulator to be used by SDHI0 */
 static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -272,7 +274,6 @@ static struct resource vin##idx##_resour
 };								\
 								\
 static struct platform_device_info vin##idx##_info __initdata = { \
-	.parent		= &platform_bus,			\
 	.name		= "r8a7779-vin",			\
 	.id		= idx,					\
 	.res		= vin##idx##_resources,			\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-marzen-reference.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-marzen-reference.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/board-marzen-reference.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/board-marzen-reference.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,19 +19,42 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <mach/r8a7779.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
+#include <linux/clk/shmobile.h>
+#include <linux/clocksource.h>
+#include <linux/of_platform.h>
+
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
+static void __init marzen_init_timer(void)
+{
+	r8a7779_clocks_init(r8a7779_read_mode_pins());
+	clocksource_of_init();
+}
+
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] __initconst = {
+	{ "tmu0", "fck", "sh-tmu.0" },
+};
+
 static void __init marzen_init(void)
 {
+	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
 	r8a7779_add_standard_devices_dt();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	r8a7779_init_irq_extpin_dt(1); /* IRQ1 as individual interrupt */
 }
 
 static const char *marzen_boards_compat_dt[] __initdata = {
+	"renesas,marzen",
 	"renesas,marzen-reference",
 	NULL,
 };
@@ -39,7 +62,8 @@ static const char *marzen_boards_compat_
 DT_MACHINE_START(MARZEN, "marzen")
 	.smp		= smp_ops(r8a7779_smp_ops),
 	.map_io		= r8a7779_map_io,
-	.init_early	= r8a7779_init_delay,
+	.init_early	= shmobile_init_delay,
+	.init_time	= marzen_init_timer,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= r8a7779_init_irq_dt,
 	.init_machine	= marzen_init,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #ifdef CONFIG_COMMON_CLK
 #include <linux/clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
+#include "clock.h"
 
 void __init shmobile_clk_workaround(const struct clk_name *clks,
 				    int nr_clks, bool enable)
@@ -49,8 +49,8 @@ void __init shmobile_clk_workaround(cons
 #else /* CONFIG_COMMON_CLK */
 #include <linux/sh_clk.h>
 #include <linux/export.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
 
 unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,56 @@
+#ifndef CLOCK_H
+#define CLOCK_H
+
+#ifdef CONFIG_COMMON_CLK
+/* temporary clock configuration helper for platform devices */
+
+struct clk_name {
+	const char *clk;
+	const char *con_id;
+	const char *dev_id;
+};
+
+void shmobile_clk_workaround(const struct clk_name *clks, int nr_clks,
+			     bool enable);
+
+#else /* CONFIG_COMMON_CLK */
+/* legacy clock implementation */
+
+struct clk;
+unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
+extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
+
+/* clock ratio */
+struct clk_ratio {
+	int mul;
+	int div;
+};
+
+#define SH_CLK_RATIO(name, m, d)		\
+static struct clk_ratio name ##_ratio = {	\
+	.mul = m,				\
+	.div = d,				\
+}
+
+#define SH_FIXED_RATIO_CLKg(name, p, r)	\
+struct clk name = {			\
+	.parent	= &p,				\
+	.ops	= &shmobile_fixed_ratio_clk_ops,\
+	.priv	= &r ## _ratio,			\
+}
+
+#define SH_FIXED_RATIO_CLK(name, p, r)		\
+static SH_FIXED_RATIO_CLKg(name, p, r)
+
+#define SH_FIXED_RATIO_CLK_SET(name, p, m, d)	\
+	SH_CLK_RATIO(name, m, d);		\
+	SH_FIXED_RATIO_CLK(name, p, name)
+
+#define SH_CLK_SET_RATIO(p, m, d)	\
+do {			\
+	(p)->mul = m;	\
+	(p)->div = d;	\
+} while (0)
+
+#endif /* CONFIG_COMMON_CLK */
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r7s72100.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r7s72100.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r7s72100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r7s72100.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,9 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/common.h>
-#include <mach/r7s72100.h>
+
+#include "common.h"
+#include "r7s72100.h"
 
 /* Frequency Control Registers */
 #define FRQCR		0xfcfe0010
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a73a4.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a73a4.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a73a4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a73a4.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "common.h"
+#include "clock.h"
 
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x270
@@ -574,11 +574,17 @@ static struct clk_lookup lookups[] = {
 
 	/* MSTP */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+	CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+	CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
+	CLKDEV_DEV_ID("e6c20000.serial", &mstp_clks[MSTP206]),
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
+	CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP207]),
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
+	CLKDEV_DEV_ID("e6ce0000.serial", &mstp_clks[MSTP216]),
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
+	CLKDEV_DEV_ID("e6cf0000.serial", &mstp_clks[MSTP217]),
 	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
 	CLKDEV_DEV_ID("e6700020.dma-controller", &mstp_clks[MSTP218]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
@@ -598,6 +604,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
 	CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
 	CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.1", &mstp_clks[MSTP329]),
+	CLKDEV_ICK_ID("fck", "e6130000.timer", &mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
 	CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
 	CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7740.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7740.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7740.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7740.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,10 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r8a7740.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7740.h"
 
 /*
  *        |  MDx  |  XTAL1/EXTAL1   |  System   | EXTALR |
@@ -555,27 +556,27 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_ceu.1",	&mstp_clks[MSTP128]),
 
 	CLKDEV_DEV_ID("sh-sci.4",		&mstp_clks[MSTP200]),
-	CLKDEV_DEV_ID("e6c80000.sci",		&mstp_clks[MSTP200]),
+	CLKDEV_DEV_ID("e6c80000.serial",	&mstp_clks[MSTP200]),
 	CLKDEV_DEV_ID("sh-sci.3",		&mstp_clks[MSTP201]),
-	CLKDEV_DEV_ID("e6c70000.sci",		&mstp_clks[MSTP201]),
+	CLKDEV_DEV_ID("e6c70000.serial",	&mstp_clks[MSTP201]),
 	CLKDEV_DEV_ID("sh-sci.2",		&mstp_clks[MSTP202]),
-	CLKDEV_DEV_ID("e6c60000.sci",		&mstp_clks[MSTP202]),
+	CLKDEV_DEV_ID("e6c60000.serial",	&mstp_clks[MSTP202]),
 	CLKDEV_DEV_ID("sh-sci.1",		&mstp_clks[MSTP203]),
-	CLKDEV_DEV_ID("e6c50000.sci",		&mstp_clks[MSTP203]),
+	CLKDEV_DEV_ID("e6c50000.serial",	&mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.0",		&mstp_clks[MSTP204]),
-	CLKDEV_DEV_ID("e6c40000.sci",		&mstp_clks[MSTP204]),
+	CLKDEV_DEV_ID("e6c40000.serial",	&mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.8",		&mstp_clks[MSTP206]),
-	CLKDEV_DEV_ID("e6c30000.sci",		&mstp_clks[MSTP206]),
+	CLKDEV_DEV_ID("e6c30000.serial",	&mstp_clks[MSTP206]),
 	CLKDEV_DEV_ID("sh-sci.5",		&mstp_clks[MSTP207]),
-	CLKDEV_DEV_ID("e6cb0000.sci",		&mstp_clks[MSTP207]),
+	CLKDEV_DEV_ID("e6cb0000.serial",	&mstp_clks[MSTP207]),
 	CLKDEV_DEV_ID("sh-dma-engine.3",	&mstp_clks[MSTP214]),
 	CLKDEV_DEV_ID("sh-dma-engine.2",	&mstp_clks[MSTP216]),
 	CLKDEV_DEV_ID("sh-dma-engine.1",	&mstp_clks[MSTP217]),
 	CLKDEV_DEV_ID("sh-dma-engine.0",	&mstp_clks[MSTP218]),
 	CLKDEV_DEV_ID("sh-sci.7",		&mstp_clks[MSTP222]),
-	CLKDEV_DEV_ID("e6cd0000.sci",		&mstp_clks[MSTP222]),
+	CLKDEV_DEV_ID("e6cd0000.serial",	&mstp_clks[MSTP222]),
 	CLKDEV_DEV_ID("sh-sci.6",		&mstp_clks[MSTP230]),
-	CLKDEV_DEV_ID("e6cc0000.sci",		&mstp_clks[MSTP230]),
+	CLKDEV_DEV_ID("e6cc0000.serial",	&mstp_clks[MSTP230]),
 
 	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("fe1f0000.sound",		&mstp_clks[MSTP328]),
@@ -598,8 +599,11 @@ static struct clk_lookup lookups[] = {
 
 	/* ICK */
 	CLKDEV_ICK_ID("fck",	"sh-tmu.1",		&mstp_clks[MSTP111]),
+	CLKDEV_ICK_ID("fck",	"fff90000.timer",	&mstp_clks[MSTP111]),
 	CLKDEV_ICK_ID("fck",	"sh-tmu.0",		&mstp_clks[MSTP125]),
+	CLKDEV_ICK_ID("fck",	"fff80000.timer",	&mstp_clks[MSTP125]),
 	CLKDEV_ICK_ID("fck",	"sh-cmt-48.1",		&mstp_clks[MSTP329]),
+	CLKDEV_ICK_ID("fck",	"e6138000.timer",	&mstp_clks[MSTP329]),
 	CLKDEV_ICK_ID("host",	"renesas_usbhs",	&mstp_clks[MSTP416]),
 	CLKDEV_ICK_ID("func",	"renesas_usbhs",	&mstp_clks[MSTP407]),
 	CLKDEV_ICK_ID("phy",	"renesas_usbhs",	&mstp_clks[MSTP406]),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7778.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7778.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7778.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7778.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,8 +39,8 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
 
 #define MSTPCR0		IOMEM(0xffc80030)
 #define MSTPCR1		IOMEM(0xffc80034)
@@ -202,11 +202,17 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
 	CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+	CLKDEV_DEV_ID("ffe40000.serial", &mstp_clks[MSTP026]), /* SCIF0 */
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+	CLKDEV_DEV_ID("ffe41000.serial", &mstp_clks[MSTP025]), /* SCIF1 */
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+	CLKDEV_DEV_ID("ffe42000.serial", &mstp_clks[MSTP024]), /* SCIF2 */
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+	CLKDEV_DEV_ID("ffe43000.serial", &mstp_clks[MSTP023]), /* SCIF3 */
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+	CLKDEV_DEV_ID("ffe44000.serial", &mstp_clks[MSTP022]), /* SCIF4 */
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+	CLKDEV_DEV_ID("ffe45000.serial", &mstp_clks[MSTP021]), /* SCIF5 */
 	CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
 	CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
 	CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
@@ -238,7 +244,9 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
 	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
 	CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
+	CLKDEV_ICK_ID("fck", "ffd80000.timer", &mstp_clks[MSTP016]),
 	CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
+	CLKDEV_ICK_ID("fck", "ffd81000.timer", &mstp_clks[MSTP015]),
 };
 
 void __init r8a7778_clock_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7779.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7779.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7779.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7779.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,11 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include <linux/sh_timer.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7779.h"
 
 /*
  *		MD1 = 1			MD1 = 0
@@ -52,9 +55,6 @@
 #define MSTPCR3		IOMEM(0xffc8003c)
 #define MSTPSR1		IOMEM(0xffc80044)
 
-#define MODEMR		0xffcc0020
-
-
 /* ioremap() through clock mapping mandatory to avoid
  * collision with ARM coherent DMA virtual memory range.
  */
@@ -207,14 +207,9 @@ static struct clk_lookup lookups[] = {
 
 void __init r8a7779_clock_init(void)
 {
-	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-	u32 mode;
+	u32 mode = r8a7779_read_mode_pins();
 	int k, ret = 0;
 
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
 	if (mode & MD(1)) {
 		plla_clk.rate = 1500000000;
 
@@ -268,3 +263,13 @@ void __init r8a7779_clock_init(void)
 	else
 		panic("failed to setup r8a7779 clocks\n");
 }
+
+/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
+void __init __weak r8a7779_register_twd(void) { }
+
+void __init r8a7779_earlytimer_init(void)
+{
+	r8a7779_clock_init();
+	r8a7779_register_twd();
+	shmobile_earlytimer_init();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7790.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7790.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7790.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7790.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,11 @@
 #include <linux/kernel.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r8a7790.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
 
 /*
  *   MD		EXTAL		PLL0	PLL1	PLL3
@@ -181,8 +183,8 @@ enum {
 
 static struct clk div4_clks[DIV4_NR] = {
 	[DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
-	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
-	[DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1de0, CLK_ENABLE_ON_INIT),
+	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT),
+	[DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1df0, CLK_ENABLE_ON_INIT),
 };
 
 /* DIV6 clocks */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7791.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7791.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-r8a7791.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-r8a7791.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,9 +23,9 @@
 #include <linux/kernel.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/rcar-gen2.h>
+#include "clock.h"
+#include "common.h"
+#include "rcar-gen2.h"
 
 /*
  *   MD		EXTAL		PLL0	PLL1	PLL3
@@ -152,7 +152,7 @@ enum {
 
 static struct clk div4_clks[DIV4_NR] = {
 	[DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
-	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
+	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT),
 };
 
 /* DIV6 clocks */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-sh7372.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-sh7372.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-sh7372.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-sh7372.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,8 +21,8 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
 
 /* SH7372 registers */
 #define FRQCRA		IOMEM(0xe6150000)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-sh73a0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-sh73a0.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/clock-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/clock-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,8 @@
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
 #include <asm/processor.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
 
 #define FRQCRA		IOMEM(0xe6150000)
 #define FRQCRB		IOMEM(0xe6150004)
@@ -638,16 +638,25 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
+	CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP219]), /* SCIFA7 */
 	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
 	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
+	CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), /* SCIFA5 */
 	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
+	CLKDEV_DEV_ID("e6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+	CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), /* SCIFA0 */
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+	CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]), /* SCIFA1 */
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
+	CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]), /* SCIFA2 */
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
+	CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]), /* SCIFA3 */
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
+	CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
+	CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP331]), /* SCIFA6 */
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
@@ -681,6 +690,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk),
 	CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk),
 	CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]), /* CMT1 */
+	CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]), /* CMT1 */
 	CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), /* TMU0 */
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,65 @@
+#ifndef __ARCH_MACH_COMMON_H
+#define __ARCH_MACH_COMMON_H
+
+extern void shmobile_earlytimer_init(void);
+extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+			 unsigned int mult, unsigned int div);
+extern void shmobile_init_delay(void);
+struct twd_local_timer;
+extern void shmobile_setup_console(void);
+extern void shmobile_boot_vector(void);
+extern unsigned long shmobile_boot_fn;
+extern unsigned long shmobile_boot_arg;
+extern unsigned long shmobile_boot_size;
+extern void shmobile_smp_boot(void);
+extern void shmobile_smp_sleep(void);
+extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
+			      unsigned long arg);
+extern int shmobile_smp_cpu_disable(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
+extern void shmobile_boot_scu(void);
+extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
+extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
+extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
+extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+					    struct task_struct *idle);
+extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
+struct clk;
+extern int shmobile_clk_init(void);
+extern void shmobile_handle_irq_intc(struct pt_regs *);
+extern struct platform_suspend_ops shmobile_suspend_ops;
+struct cpuidle_driver;
+extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
+
+#ifdef CONFIG_SUSPEND
+int shmobile_suspend_init(void);
+void shmobile_smp_apmu_suspend_init(void);
+#else
+static inline int shmobile_suspend_init(void) { return 0; }
+static inline void shmobile_smp_apmu_suspend_init(void) { }
+#endif
+
+#ifdef CONFIG_CPU_IDLE
+int shmobile_cpuidle_init(void);
+#else
+static inline int shmobile_cpuidle_init(void) { return 0; }
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+int shmobile_cpufreq_init(void);
+#else
+static inline int shmobile_cpufreq_init(void) { return 0; }
+#endif
+
+extern void __iomem *shmobile_scu_base;
+
+static inline void __init shmobile_init_late(void)
+{
+	shmobile_suspend_init();
+	shmobile_cpuidle_init();
+	shmobile_cpufreq_init();
+}
+
+#endif /* __ARCH_MACH_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/console.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/console.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/console.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/console.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <mach/common.h>
 #include <asm/mach/map.h>
+#include "common.h"
 
 void __init shmobile_setup_console(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/cpufreq.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/cpufreq.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ * CPUFreq support code for SH-Mobile ARM
+ *
+ *  Copyright (C) 2014 Gaku Inami
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+
+int __init shmobile_cpufreq_init(void)
+{
+	platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/dma-register.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/dma-register.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/dma-register.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/dma-register.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * SH-ARM CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef DMA_REGISTER_H
+#define DMA_REGISTER_H
+
+/*
+ *		Direct Memory Access Controller
+ */
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+	XMIT_SZ_8BIT		= 0,
+	XMIT_SZ_16BIT		= 1,
+	XMIT_SZ_32BIT		= 2,
+	XMIT_SZ_64BIT		= 7,
+	XMIT_SZ_128BIT		= 3,
+	XMIT_SZ_256BIT		= 4,
+	XMIT_SZ_512BIT		= 5,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+static const unsigned int dma_ts_shift[] = {
+	[XMIT_SZ_8BIT]		= 0,
+	[XMIT_SZ_16BIT]		= 1,
+	[XMIT_SZ_32BIT]		= 2,
+	[XMIT_SZ_64BIT]		= 3,
+	[XMIT_SZ_128BIT]	= 4,
+	[XMIT_SZ_256BIT]	= 5,
+	[XMIT_SZ_512BIT]	= 6,
+};
+
+#define TS_LOW_BIT	0x3 /* --xx */
+#define TS_HI_BIT	0xc /* xx-- */
+
+#define TS_LOW_SHIFT	(3)
+#define TS_HI_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
+
+#define TS_INDEX2VAL(i) \
+	((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
+	 (((i) & TS_HI_BIT)  << TS_HI_SHIFT))
+
+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
+
+
+/*
+ *		USB High-Speed DMAC
+ */
+/* Transmit sizes and respective CHCR register values */
+enum {
+	USBTS_XMIT_SZ_8BYTE		= 0,
+	USBTS_XMIT_SZ_16BYTE		= 1,
+	USBTS_XMIT_SZ_32BYTE		= 2,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+static const unsigned int dma_usbts_shift[] = {
+	[USBTS_XMIT_SZ_8BYTE]	= 3,
+	[USBTS_XMIT_SZ_16BYTE]	= 4,
+	[USBTS_XMIT_SZ_32BYTE]	= 5,
+};
+
+#define USBTS_LOW_BIT	0x3 /* --xx */
+#define USBTS_HI_BIT	0x0 /* ---- */
+
+#define USBTS_LOW_SHIFT	6
+#define USBTS_HI_SHIFT	0
+
+#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
+
+#endif /* DMA_REGISTER_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/headsmp.S linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/headsmp.S
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/headsmp.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/headsmp.S	2014-09-28 17:29:07.000000000 -0400
@@ -10,14 +10,18 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/assembler.h>
 #include <asm/memory.h>
 
+#ifdef CONFIG_SMP
 ENTRY(shmobile_invalidate_start)
 	bl	v7_invalidate_l1
 	b	secondary_startup
 ENDPROC(shmobile_invalidate_start)
+#endif
 
 /*
  * Reset vector for secondary CPUs.
@@ -68,14 +72,14 @@ shmobile_smp_boot_find_mpidr:
 
 shmobile_smp_boot_next:
 	add	r1, r1, #1
-	cmp	r1, #CONFIG_NR_CPUS
+	cmp	r1, #NR_CPUS
 	blo	shmobile_smp_boot_find_mpidr
 
 	b	shmobile_smp_sleep
 
 shmobile_smp_boot_found:
 	ldr	r0, [r7, r1, lsl #2]
-	mov	pc, r9
+	ret	r9
 ENDPROC(shmobile_smp_boot)
 
 ENTRY(shmobile_smp_sleep)
@@ -85,10 +89,10 @@ ENDPROC(shmobile_smp_sleep)
 
 	.globl	shmobile_smp_mpidr
 shmobile_smp_mpidr:
-1:	.space	CONFIG_NR_CPUS * 4
+1:	.space	NR_CPUS * 4
 	.globl	shmobile_smp_fn
 shmobile_smp_fn:
-2:	.space	CONFIG_NR_CPUS * 4
+2:	.space	NR_CPUS * 4
 	.globl	shmobile_smp_arg
 shmobile_smp_arg:
-3:	.space	CONFIG_NR_CPUS * 4
+3:	.space	NR_CPUS * 4
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/clock.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/clock.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-#ifndef CLOCK_H
-#define CLOCK_H
-
-#ifdef CONFIG_COMMON_CLK
-/* temporary clock configuration helper for platform devices */
-
-struct clk_name {
-	const char *clk;
-	const char *con_id;
-	const char *dev_id;
-};
-
-void shmobile_clk_workaround(const struct clk_name *clks, int nr_clks,
-			     bool enable);
-
-#else /* CONFIG_COMMON_CLK */
-/* legacy clock implementation */
-
-struct clk;
-unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
-extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
-
-/* clock ratio */
-struct clk_ratio {
-	int mul;
-	int div;
-};
-
-#define SH_CLK_RATIO(name, m, d)		\
-static struct clk_ratio name ##_ratio = {	\
-	.mul = m,				\
-	.div = d,				\
-}
-
-#define SH_FIXED_RATIO_CLKg(name, p, r)	\
-struct clk name = {			\
-	.parent	= &p,				\
-	.ops	= &shmobile_fixed_ratio_clk_ops,\
-	.priv	= &r ## _ratio,			\
-}
-
-#define SH_FIXED_RATIO_CLK(name, p, r)		\
-static SH_FIXED_RATIO_CLKg(name, p, r)
-
-#define SH_FIXED_RATIO_CLK_SET(name, p, m, d)	\
-	SH_CLK_RATIO(name, m, d);		\
-	SH_FIXED_RATIO_CLK(name, p, name)
-
-#define SH_CLK_SET_RATIO(p, m, d)	\
-do {			\
-	(p)->mul = m;	\
-	(p)->div = d;	\
-} while (0)
-
-#endif /* CONFIG_COMMON_CLK */
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/common.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/common.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-#ifndef __ARCH_MACH_COMMON_H
-#define __ARCH_MACH_COMMON_H
-
-extern void shmobile_earlytimer_init(void);
-extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-			 unsigned int mult, unsigned int div);
-extern void shmobile_init_delay(void);
-struct twd_local_timer;
-extern void shmobile_setup_console(void);
-extern void shmobile_boot_vector(void);
-extern unsigned long shmobile_boot_fn;
-extern unsigned long shmobile_boot_arg;
-extern unsigned long shmobile_boot_size;
-extern void shmobile_smp_boot(void);
-extern void shmobile_smp_sleep(void);
-extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
-			      unsigned long arg);
-extern int shmobile_smp_cpu_disable(unsigned int cpu);
-extern void shmobile_invalidate_start(void);
-extern void shmobile_boot_scu(void);
-extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
-extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
-extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
-extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
-extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
-					    struct task_struct *idle);
-extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
-extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
-struct clk;
-extern int shmobile_clk_init(void);
-extern void shmobile_handle_irq_intc(struct pt_regs *);
-extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_driver;
-extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
-
-#ifdef CONFIG_SUSPEND
-int shmobile_suspend_init(void);
-#else
-static inline int shmobile_suspend_init(void) { return 0; }
-#endif
-
-#ifdef CONFIG_CPU_IDLE
-int shmobile_cpuidle_init(void);
-#else
-static inline int shmobile_cpuidle_init(void) { return 0; }
-#endif
-
-extern void __iomem *shmobile_scu_base;
-
-static inline void __init shmobile_init_late(void)
-{
-	shmobile_suspend_init();
-	shmobile_cpuidle_init();
-}
-
-#endif /* __ARCH_MACH_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/dma-register.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/dma-register.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/dma-register.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/dma-register.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/*
- * SH-ARM CPU-specific DMA definitions, used by both DMA drivers
- *
- * Copyright (C) 2012 Renesas Solutions Corp
- *
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h
- * 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef DMA_REGISTER_H
-#define DMA_REGISTER_H
-
-/*
- *		Direct Memory Access Controller
- */
-
-/* Transmit sizes and respective CHCR register values */
-enum {
-	XMIT_SZ_8BIT		= 0,
-	XMIT_SZ_16BIT		= 1,
-	XMIT_SZ_32BIT		= 2,
-	XMIT_SZ_64BIT		= 7,
-	XMIT_SZ_128BIT		= 3,
-	XMIT_SZ_256BIT		= 4,
-	XMIT_SZ_512BIT		= 5,
-};
-
-/* log2(size / 8) - used to calculate number of transfers */
-static const unsigned int dma_ts_shift[] = {
-	[XMIT_SZ_8BIT]		= 0,
-	[XMIT_SZ_16BIT]		= 1,
-	[XMIT_SZ_32BIT]		= 2,
-	[XMIT_SZ_64BIT]		= 3,
-	[XMIT_SZ_128BIT]	= 4,
-	[XMIT_SZ_256BIT]	= 5,
-	[XMIT_SZ_512BIT]	= 6,
-};
-
-#define TS_LOW_BIT	0x3 /* --xx */
-#define TS_HI_BIT	0xc /* xx-- */
-
-#define TS_LOW_SHIFT	(3)
-#define TS_HI_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
-
-#define TS_INDEX2VAL(i) \
-	((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
-	 (((i) & TS_HI_BIT)  << TS_HI_SHIFT))
-
-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
-
-
-/*
- *		USB High-Speed DMAC
- */
-/* Transmit sizes and respective CHCR register values */
-enum {
-	USBTS_XMIT_SZ_8BYTE		= 0,
-	USBTS_XMIT_SZ_16BYTE		= 1,
-	USBTS_XMIT_SZ_32BYTE		= 2,
-};
-
-/* log2(size / 8) - used to calculate number of transfers */
-static const unsigned int dma_usbts_shift[] = {
-	[USBTS_XMIT_SZ_8BYTE]	= 3,
-	[USBTS_XMIT_SZ_16BYTE]	= 4,
-	[USBTS_XMIT_SZ_32BYTE]	= 5,
-};
-
-#define USBTS_LOW_BIT	0x3 /* --xx */
-#define USBTS_HI_BIT	0x0 /* ---- */
-
-#define USBTS_LOW_SHIFT	6
-#define USBTS_HI_SHIFT	0
-
-#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
-
-#endif /* DMA_REGISTER_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/intc.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/intc.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/intc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/intc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,290 +0,0 @@
-#ifndef __ASM_MACH_INTC_H
-#define __ASM_MACH_INTC_H
-#include <linux/sh_intc.h>
-
-#define INTC_IRQ_PINS_ENUM_16L(p)				\
-	p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
-	p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7,		\
-	p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,	\
-	p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
-
-#define INTC_IRQ_PINS_ENUM_16H(p)				\
-	p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,	\
-	p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23,	\
-	p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,	\
-	p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
-
-#define INTC_IRQ_PINS_VECT_16L(p, vect)				\
-	vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220),	\
-	vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260),	\
-	vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0),	\
-	vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0),	\
-	vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320),	\
-	vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360),	\
-	vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0),	\
-	vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
-
-#define INTC_IRQ_PINS_VECT_16H(p, vect)				\
-	vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220),	\
-	vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260),	\
-	vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0),	\
-	vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0),	\
-	vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320),	\
-	vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360),	\
-	vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0),	\
-	vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
-
-#define INTC_IRQ_PINS_MASK_16L(p, base)					\
-	{ base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */	\
-	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
-	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
-	{ base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */	\
-	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
-	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
-
-#define INTC_IRQ_PINS_MASK_16H(p, base)					\
-	{ base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */	\
-	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
-	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
-	{ base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */	\
-	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
-	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
-
-#define INTC_IRQ_PINS_PRIO_16L(p, base)					\
-	{ base + 0x10, 0, 32, 4, /* INTPRI00A */			\
-	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
-	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
-	{ base + 0x14, 0, 32, 4, /* INTPRI10A */			\
-	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
-	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
-
-#define INTC_IRQ_PINS_PRIO_16H(p, base)					\
-	{ base + 0x18, 0, 32, 4, /* INTPRI20A */			\
-	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
-	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
-	{ base + 0x1c, 0, 32, 4, /* INTPRI30A */			\
-	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
-	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
-
-#define INTC_IRQ_PINS_SENSE_16L(p, base)				\
-	{ base + 0x00, 32, 4, /* ICR1A */				\
-	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
-	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
-	{ base + 0x04, 32, 4, /* ICR2A */				\
-	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
-	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
-
-#define INTC_IRQ_PINS_SENSE_16H(p, base)				\
-	{ base + 0x08, 32, 4, /* ICR3A */				\
-	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
-	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
-	{ base + 0x0c, 32, 4, /* ICR4A */				\
-	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
-	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
-
-#define INTC_IRQ_PINS_ACK_16L(p, base)					\
-	{ base + 0x20, 0, 8, /* INTREQ00A */				\
-	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
-	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
-	{ base + 0x24, 0, 8, /* INTREQ10A */				\
-	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
-	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
-
-#define INTC_IRQ_PINS_ACK_16H(p, base)					\
-	{ base + 0x28, 0, 8, /* INTREQ20A */				\
-	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
-	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
-	{ base + 0x2c, 0, 8, /* INTREQ30A */				\
-	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
-	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
-
-#define INTC_IRQ_PINS_16(p, base, vect, str)				\
-									\
-static struct resource p ## _resources[] __initdata = {			\
-	[0] = {								\
-		.start	= base,						\
-		.end	= base + 0x64,					\
-		.flags	= IORESOURCE_MEM,				\
-	},								\
-};									\
-									\
-enum {									\
-	p ## _UNUSED = 0,						\
-	INTC_IRQ_PINS_ENUM_16L(p),					\
-};									\
-									\
-static struct intc_vect p ## _vectors[] __initdata = {			\
-	INTC_IRQ_PINS_VECT_16L(p, vect),				\
-};									\
-									\
-static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
-	INTC_IRQ_PINS_MASK_16L(p, base),				\
-};									\
-									\
-static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
-	INTC_IRQ_PINS_PRIO_16L(p, base),				\
-};									\
-									\
-static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
-	INTC_IRQ_PINS_SENSE_16L(p, base),				\
-};									\
-									\
-static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
-	INTC_IRQ_PINS_ACK_16L(p, base),					\
-};									\
-									\
-static struct intc_desc p ## _desc __initdata = {			\
-	.name = str,							\
-	.resource = p ## _resources,					\
-	.num_resources = ARRAY_SIZE(p ## _resources),			\
-	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
-			     p ## _mask_registers, p ## _prio_registers, \
-			     p ## _sense_registers, p ## _ack_registers) \
-}
-
-#define INTC_IRQ_PINS_16H(p, base, vect, str)				\
-									\
-static struct resource p ## _resources[] __initdata = {			\
-	[0] = {								\
-		.start	= base,						\
-		.end	= base + 0x64,					\
-		.flags	= IORESOURCE_MEM,				\
-	},								\
-};									\
-									\
-enum {									\
-	p ## _UNUSED = 0,						\
-	INTC_IRQ_PINS_ENUM_16H(p),					\
-};									\
-									\
-static struct intc_vect p ## _vectors[] __initdata = {			\
-	INTC_IRQ_PINS_VECT_16H(p, vect),				\
-};									\
-									\
-static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
-	INTC_IRQ_PINS_MASK_16H(p, base),				\
-};									\
-									\
-static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
-	INTC_IRQ_PINS_PRIO_16H(p, base),				\
-};									\
-									\
-static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
-	INTC_IRQ_PINS_SENSE_16H(p, base),				\
-};									\
-									\
-static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
-	INTC_IRQ_PINS_ACK_16H(p, base),					\
-};									\
-									\
-static struct intc_desc p ## _desc __initdata = {			\
-	.name = str,							\
-	.resource = p ## _resources,					\
-	.num_resources = ARRAY_SIZE(p ## _resources),			\
-	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
-			     p ## _mask_registers, p ## _prio_registers, \
-			     p ## _sense_registers, p ## _ack_registers) \
-}
-
-#define INTC_IRQ_PINS_32(p, base, vect, str)				\
-									\
-static struct resource p ## _resources[] __initdata = {			\
-	[0] = {								\
-		.start	= base,						\
-		.end	= base + 0x6c,					\
-		.flags	= IORESOURCE_MEM,				\
-	},								\
-};									\
-									\
-enum {									\
-	p ## _UNUSED = 0,						\
-	INTC_IRQ_PINS_ENUM_16L(p),					\
-	INTC_IRQ_PINS_ENUM_16H(p),					\
-};									\
-									\
-static struct intc_vect p ## _vectors[] __initdata = {			\
-	INTC_IRQ_PINS_VECT_16L(p, vect),				\
-	INTC_IRQ_PINS_VECT_16H(p, vect),				\
-};									\
-									\
-static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
-	INTC_IRQ_PINS_MASK_16L(p, base),				\
-	INTC_IRQ_PINS_MASK_16H(p, base),				\
-};									\
-									\
-static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
-	INTC_IRQ_PINS_PRIO_16L(p, base),				\
-	INTC_IRQ_PINS_PRIO_16H(p, base),				\
-};									\
-									\
-static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
-	INTC_IRQ_PINS_SENSE_16L(p, base),				\
-	INTC_IRQ_PINS_SENSE_16H(p, base),				\
-};									\
-									\
-static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
-	INTC_IRQ_PINS_ACK_16L(p, base),					\
-	INTC_IRQ_PINS_ACK_16H(p, base),					\
-};									\
-									\
-static struct intc_desc p ## _desc __initdata = {			\
-	.name = str,							\
-	.resource = p ## _resources,					\
-	.num_resources = ARRAY_SIZE(p ## _resources),			\
-	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
-			     p ## _mask_registers, p ## _prio_registers, \
-			     p ## _sense_registers, p ## _ack_registers) \
-}
-
-#define INTC_PINT_E_EMPTY
-#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
-#define INTC_PINT_E(p)							\
-	PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3,	\
-	PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
-
-#define INTC_PINT_V_NONE
-#define INTC_PINT_V(p, vect)					\
-	vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1),	\
-	vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3),	\
-	vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5),	\
-	vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
-
-#define INTC_PINT(p, mask_reg, sense_base, str,				\
-	enums_1, enums_2, enums_3, enums_4,				\
-	vect_1, vect_2, vect_3, vect_4,					\
-	mask_a, mask_b, mask_c, mask_d,					\
-	sense_a, sense_b, sense_c, sense_d)				\
-									\
-enum {									\
-	PINT ## p ## _UNUSED = 0,					\
-	enums_1 enums_2 enums_3 enums_4 				\
-};									\
-									\
-static struct intc_vect p ## _vectors[] __initdata = {			\
-	vect_1 vect_2 vect_3 vect_4					\
-};									\
-									\
-static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
-	{ mask_reg, 0, 32, /* PINTER */					\
-	  { mask_a mask_b mask_c mask_d } }				\
-};									\
-									\
-static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
-	{ sense_base + 0x00, 16, 2, /* PINTCR */			\
-	  { sense_a } },						\
-	{ sense_base + 0x04, 16, 2, /* PINTCR */			\
-	  { sense_b } },						\
-	{ sense_base + 0x08, 16, 2, /* PINTCR */			\
-	  { sense_c } },						\
-	{ sense_base + 0x0c, 16, 2, /* PINTCR */			\
-	  { sense_d } },						\
-};									\
-									\
-static struct intc_desc p ## _desc __initdata = {			\
-	.name = str,							\
-	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
-			     p ## _mask_registers, NULL,		\
-			     p ## _sense_registers, NULL),		\
-}
-
-#endif  /* __ASM_MACH_INTC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/irqs.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,24 +1,10 @@
 #ifndef __ASM_MACH_IRQS_H
 #define __ASM_MACH_IRQS_H
 
-#include <linux/sh_intc.h>
-
-/* GIC */
-#define gic_spi(nr)		((nr) + 32)
-#define gic_iid(nr)		(nr) /* ICCIAR / interrupt ID */
-
-/* INTCS */
-#define INTCS_VECT_BASE		0x3400
-#define INTCS_VECT(n, vect)	INTC_VECT((n), INTCS_VECT_BASE + (vect))
-#define intcs_evt2irq(evt)	evt2irq(INTCS_VECT_BASE + (evt))
+/* Stuck here until drivers/pinctl/sh-pfc gets rid of legacy code */
 
 /* External IRQ pins */
 #define IRQPIN_BASE		2000
 #define irq_pin(nr)		((nr) + IRQPIN_BASE)
 
-/* GPIO IRQ */
-#define _GPIO_IRQ_BASE		2500
-#define GPIO_IRQ_BASE(x)	(_GPIO_IRQ_BASE + (32 * x))
-#define GPIO_IRQ(x, y)		(_GPIO_IRQ_BASE + (32 * x) + y)
-
 #endif /* __ASM_MACH_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/pm-rcar.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/pm-rcar.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/pm-rcar.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/pm-rcar.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-#ifndef PM_RCAR_H
-#define PM_RCAR_H
-
-struct rcar_sysc_ch {
-	unsigned long chan_offs;
-	unsigned int chan_bit;
-	unsigned int isr_bit;
-};
-
-int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch);
-int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch);
-bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch);
-void __iomem *rcar_sysc_init(phys_addr_t base);
-
-#endif /* PM_RCAR_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/pm-rmobile.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/pm-rmobile.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/pm-rmobile.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef PM_RMOBILE_H
-#define PM_RMOBILE_H
-
-#include <linux/pm_domain.h>
-
-#define DEFAULT_DEV_LATENCY_NS	250000
-
-struct platform_device;
-
-struct rmobile_pm_domain {
-	struct generic_pm_domain genpd;
-	struct dev_power_governor *gov;
-	int (*suspend)(void);
-	void (*resume)(void);
-	unsigned int bit_shift;
-	bool no_debug;
-};
-
-static inline
-struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
-{
-	return container_of(d, struct rmobile_pm_domain, genpd);
-}
-
-struct pm_domain_device {
-	const char *domain_name;
-	struct platform_device *pdev;
-};
-
-#ifdef CONFIG_PM
-extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
-extern void rmobile_add_device_to_domain_td(const char *domain_name,
-					    struct platform_device *pdev,
-					    struct gpd_timing_data *td);
-
-static inline void rmobile_add_device_to_domain(const char *domain_name,
-						struct platform_device *pdev)
-{
-	rmobile_add_device_to_domain_td(domain_name, pdev, NULL);
-}
-
-extern void rmobile_add_devices_to_domains(struct pm_domain_device data[],
-					   int size);
-#else
-
-#define rmobile_init_domains(domains, num) do { } while (0)
-#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0)
-#define rmobile_add_device_to_domain(name, pdev) do { } while (0)
-
-static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[],
-						  int size) {}
-#endif /* CONFIG_PM */
-
-#endif /* PM_RMOBILE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r7s72100.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r7s72100.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r7s72100.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r7s72100.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#ifndef __ASM_R7S72100_H__
-#define __ASM_R7S72100_H__
-
-void r7s72100_add_dt_devices(void);
-void r7s72100_clock_init(void);
-void r7s72100_init_early(void);
-
-#endif /* __ASM_R7S72100_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a73a4.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a73a4.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a73a4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a73a4.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-#ifndef __ASM_R8A73A4_H__
-#define __ASM_R8A73A4_H__
-
-/* DMA slave IDs */
-enum {
-	SHDMA_SLAVE_INVALID,
-	SHDMA_SLAVE_MMCIF0_TX,
-	SHDMA_SLAVE_MMCIF0_RX,
-	SHDMA_SLAVE_MMCIF1_TX,
-	SHDMA_SLAVE_MMCIF1_RX,
-};
-
-void r8a73a4_add_standard_devices(void);
-void r8a73a4_add_dt_devices(void);
-void r8a73a4_clock_init(void);
-void r8a73a4_pinmux_init(void);
-void r8a73a4_init_early(void);
-
-#endif /* __ASM_R8A73A4_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7740.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7740.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7740.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7740.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011  Renesas Solutions Corp.
- * Copyright (C) 2011  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 as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __ASM_R8A7740_H__
-#define __ASM_R8A7740_H__
-
-#include <mach/pm-rmobile.h>
-
-/*
- * MD_CKx pin
- */
-#define MD_CK2	(1 << 2)
-#define MD_CK1	(1 << 1)
-#define MD_CK0	(1 << 0)
-
-/* DMA slave IDs */
-enum {
-	SHDMA_SLAVE_INVALID,
-	SHDMA_SLAVE_SDHI0_RX,
-	SHDMA_SLAVE_SDHI0_TX,
-	SHDMA_SLAVE_SDHI1_RX,
-	SHDMA_SLAVE_SDHI1_TX,
-	SHDMA_SLAVE_SDHI2_RX,
-	SHDMA_SLAVE_SDHI2_TX,
-	SHDMA_SLAVE_FSIA_RX,
-	SHDMA_SLAVE_FSIA_TX,
-	SHDMA_SLAVE_FSIB_TX,
-	SHDMA_SLAVE_USBHS_TX,
-	SHDMA_SLAVE_USBHS_RX,
-	SHDMA_SLAVE_MMCIF_TX,
-	SHDMA_SLAVE_MMCIF_RX,
-};
-
-extern void r8a7740_meram_workaround(void);
-extern void r8a7740_init_irq_of(void);
-extern void r8a7740_map_io(void);
-extern void r8a7740_add_early_devices(void);
-extern void r8a7740_add_standard_devices(void);
-extern void r8a7740_add_standard_devices_dt(void);
-extern void r8a7740_clock_init(u8 md_ck);
-extern void r8a7740_pinmux_init(void);
-extern void r8a7740_pm_init(void);
-
-#ifdef CONFIG_PM
-extern void __init r8a7740_init_pm_domains(void);
-#else
-static inline void r8a7740_init_pm_domains(void) {}
-#endif /* CONFIG_PM */
-
-#endif /* __ASM_R8A7740_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7778.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7778.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7778.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7778.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- * Copyright (C) 2013  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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __ASM_R8A7778_H__
-#define __ASM_R8A7778_H__
-
-#include <linux/sh_eth.h>
-
-/* HPB-DMA slave IDs */
-enum {
-	HPBDMA_SLAVE_DUMMY,
-	HPBDMA_SLAVE_SDHI0_TX,
-	HPBDMA_SLAVE_SDHI0_RX,
-	HPBDMA_SLAVE_SSI0_TX,
-	HPBDMA_SLAVE_SSI0_RX,
-	HPBDMA_SLAVE_SSI1_TX,
-	HPBDMA_SLAVE_SSI1_RX,
-	HPBDMA_SLAVE_SSI2_TX,
-	HPBDMA_SLAVE_SSI2_RX,
-	HPBDMA_SLAVE_SSI3_TX,
-	HPBDMA_SLAVE_SSI3_RX,
-	HPBDMA_SLAVE_SSI4_TX,
-	HPBDMA_SLAVE_SSI4_RX,
-	HPBDMA_SLAVE_SSI5_TX,
-	HPBDMA_SLAVE_SSI5_RX,
-	HPBDMA_SLAVE_SSI6_TX,
-	HPBDMA_SLAVE_SSI6_RX,
-	HPBDMA_SLAVE_SSI7_TX,
-	HPBDMA_SLAVE_SSI7_RX,
-	HPBDMA_SLAVE_SSI8_TX,
-	HPBDMA_SLAVE_SSI8_RX,
-	HPBDMA_SLAVE_HPBIF0_TX,
-	HPBDMA_SLAVE_HPBIF0_RX,
-	HPBDMA_SLAVE_HPBIF1_TX,
-	HPBDMA_SLAVE_HPBIF1_RX,
-	HPBDMA_SLAVE_HPBIF2_TX,
-	HPBDMA_SLAVE_HPBIF2_RX,
-	HPBDMA_SLAVE_HPBIF3_TX,
-	HPBDMA_SLAVE_HPBIF3_RX,
-	HPBDMA_SLAVE_HPBIF4_TX,
-	HPBDMA_SLAVE_HPBIF4_RX,
-	HPBDMA_SLAVE_HPBIF5_TX,
-	HPBDMA_SLAVE_HPBIF5_RX,
-	HPBDMA_SLAVE_HPBIF6_TX,
-	HPBDMA_SLAVE_HPBIF6_RX,
-	HPBDMA_SLAVE_HPBIF7_TX,
-	HPBDMA_SLAVE_HPBIF7_RX,
-	HPBDMA_SLAVE_HPBIF8_TX,
-	HPBDMA_SLAVE_HPBIF8_RX,
-	HPBDMA_SLAVE_USBFUNC_TX,
-	HPBDMA_SLAVE_USBFUNC_RX,
-};
-
-extern void r8a7778_add_standard_devices(void);
-extern void r8a7778_add_standard_devices_dt(void);
-extern void r8a7778_add_dt_devices(void);
-
-extern void r8a7778_init_late(void);
-extern void r8a7778_init_delay(void);
-extern void r8a7778_init_irq_dt(void);
-extern void r8a7778_clock_init(void);
-extern void r8a7778_init_irq_extpin(int irlm);
-extern void r8a7778_init_irq_extpin_dt(int irlm);
-extern void r8a7778_pinmux_init(void);
-
-extern int r8a7778_usb_phy_power(bool enable);
-
-#endif /* __ASM_R8A7778_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7779.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7779.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7779.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7779.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-#ifndef __ASM_R8A7779_H__
-#define __ASM_R8A7779_H__
-
-#include <linux/sh_clk.h>
-#include <linux/pm_domain.h>
-#include <mach/pm-rcar.h>
-
-/* HPB-DMA slave IDs */
-enum {
-	HPBDMA_SLAVE_DUMMY,
-	HPBDMA_SLAVE_SDHI0_TX,
-	HPBDMA_SLAVE_SDHI0_RX,
-};
-
-struct r8a7779_pm_domain {
-	struct generic_pm_domain genpd;
-	struct rcar_sysc_ch ch;
-};
-
-static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
-{
-	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
-}
-
-extern void r8a7779_init_delay(void);
-extern void r8a7779_init_irq_extpin(int irlm);
-extern void r8a7779_init_irq_extpin_dt(int irlm);
-extern void r8a7779_init_irq_dt(void);
-extern void r8a7779_map_io(void);
-extern void r8a7779_earlytimer_init(void);
-extern void r8a7779_add_early_devices(void);
-extern void r8a7779_add_standard_devices(void);
-extern void r8a7779_add_standard_devices_dt(void);
-extern void r8a7779_init_late(void);
-extern void r8a7779_clock_init(void);
-extern void r8a7779_pinmux_init(void);
-extern void r8a7779_pm_init(void);
-extern void r8a7779_register_twd(void);
-
-#ifdef CONFIG_PM
-extern void __init r8a7779_init_pm_domains(void);
-#else
-static inline void r8a7779_init_pm_domains(void) {}
-#endif /* CONFIG_PM */
-
-extern struct smp_operations r8a7779_smp_ops;
-
-#endif /* __ASM_R8A7779_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7790.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7790.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7790.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7790.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-#ifndef __ASM_R8A7790_H__
-#define __ASM_R8A7790_H__
-
-#include <mach/rcar-gen2.h>
-
-/* DMA slave IDs */
-enum {
-	RCAR_DMA_SLAVE_INVALID,
-	AUDIO_DMAC_SLAVE_SSI0_TX,
-	AUDIO_DMAC_SLAVE_SSI0_RX,
-	AUDIO_DMAC_SLAVE_SSI1_TX,
-	AUDIO_DMAC_SLAVE_SSI1_RX,
-	AUDIO_DMAC_SLAVE_SSI2_TX,
-	AUDIO_DMAC_SLAVE_SSI2_RX,
-	AUDIO_DMAC_SLAVE_SSI3_TX,
-	AUDIO_DMAC_SLAVE_SSI3_RX,
-	AUDIO_DMAC_SLAVE_SSI4_TX,
-	AUDIO_DMAC_SLAVE_SSI4_RX,
-	AUDIO_DMAC_SLAVE_SSI5_TX,
-	AUDIO_DMAC_SLAVE_SSI5_RX,
-	AUDIO_DMAC_SLAVE_SSI6_TX,
-	AUDIO_DMAC_SLAVE_SSI6_RX,
-	AUDIO_DMAC_SLAVE_SSI7_TX,
-	AUDIO_DMAC_SLAVE_SSI7_RX,
-	AUDIO_DMAC_SLAVE_SSI8_TX,
-	AUDIO_DMAC_SLAVE_SSI8_RX,
-	AUDIO_DMAC_SLAVE_SSI9_TX,
-	AUDIO_DMAC_SLAVE_SSI9_RX,
-};
-
-void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
-void r8a7790_clock_init(void);
-void r8a7790_pinmux_init(void);
-void r8a7790_pm_init(void);
-void r8a7790_init_early(void);
-extern struct smp_operations r8a7790_smp_ops;
-
-#endif /* __ASM_R8A7790_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7791.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7791.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/r8a7791.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/r8a7791.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#ifndef __ASM_R8A7791_H__
-#define __ASM_R8A7791_H__
-
-void r8a7791_add_standard_devices(void);
-void r8a7791_add_dt_devices(void);
-void r8a7791_clock_init(void);
-void r8a7791_pinmux_init(void);
-extern struct smp_operations r8a7791_smp_ops;
-
-#endif /* __ASM_R8A7791_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/rcar-gen2.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/rcar-gen2.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/rcar-gen2.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/rcar-gen2.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#ifndef __ASM_RCAR_GEN2_H__
-#define __ASM_RCAR_GEN2_H__
-
-void rcar_gen2_timer_init(void);
-#define MD(nr) BIT(nr)
-u32 rcar_gen2_read_mode_pins(void);
-
-#endif /* __ASM_RCAR_GEN2_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 Renesas Solutions Corp.
- *
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef __ASM_SH7372_H__
-#define __ASM_SH7372_H__
-
-#include <linux/sh_clk.h>
-#include <linux/pm_domain.h>
-#include <mach/pm-rmobile.h>
-
-/* DMA slave IDs */
-enum {
-	SHDMA_SLAVE_INVALID,
-	SHDMA_SLAVE_SCIF0_TX,
-	SHDMA_SLAVE_SCIF0_RX,
-	SHDMA_SLAVE_SCIF1_TX,
-	SHDMA_SLAVE_SCIF1_RX,
-	SHDMA_SLAVE_SCIF2_TX,
-	SHDMA_SLAVE_SCIF2_RX,
-	SHDMA_SLAVE_SCIF3_TX,
-	SHDMA_SLAVE_SCIF3_RX,
-	SHDMA_SLAVE_SCIF4_TX,
-	SHDMA_SLAVE_SCIF4_RX,
-	SHDMA_SLAVE_SCIF5_TX,
-	SHDMA_SLAVE_SCIF5_RX,
-	SHDMA_SLAVE_SCIF6_TX,
-	SHDMA_SLAVE_SCIF6_RX,
-	SHDMA_SLAVE_FLCTL0_TX,
-	SHDMA_SLAVE_FLCTL0_RX,
-	SHDMA_SLAVE_FLCTL1_TX,
-	SHDMA_SLAVE_FLCTL1_RX,
-	SHDMA_SLAVE_SDHI0_RX,
-	SHDMA_SLAVE_SDHI0_TX,
-	SHDMA_SLAVE_SDHI1_RX,
-	SHDMA_SLAVE_SDHI1_TX,
-	SHDMA_SLAVE_SDHI2_RX,
-	SHDMA_SLAVE_SDHI2_TX,
-	SHDMA_SLAVE_FSIA_RX,
-	SHDMA_SLAVE_FSIA_TX,
-	SHDMA_SLAVE_MMCIF_RX,
-	SHDMA_SLAVE_MMCIF_TX,
-	SHDMA_SLAVE_USB0_TX,
-	SHDMA_SLAVE_USB0_RX,
-	SHDMA_SLAVE_USB1_TX,
-	SHDMA_SLAVE_USB1_RX,
-};
-
-extern struct clk sh7372_extal1_clk;
-extern struct clk sh7372_extal2_clk;
-extern struct clk sh7372_dv_clki_clk;
-extern struct clk sh7372_dv_clki_div2_clk;
-extern struct clk sh7372_pllc2_clk;
-
-extern void sh7372_init_irq(void);
-extern void sh7372_map_io(void);
-extern void sh7372_earlytimer_init(void);
-extern void sh7372_add_early_devices(void);
-extern void sh7372_add_standard_devices(void);
-extern void sh7372_add_early_devices_dt(void);
-extern void sh7372_add_standard_devices_dt(void);
-extern void sh7372_clock_init(void);
-extern void sh7372_pinmux_init(void);
-extern void sh7372_pm_init(void);
-extern void sh7372_resume_core_standby_sysc(void);
-extern int  sh7372_do_idle_sysc(unsigned long sleep_mode);
-extern void sh7372_intcs_suspend(void);
-extern void sh7372_intcs_resume(void);
-extern void sh7372_intca_suspend(void);
-extern void sh7372_intca_resume(void);
-
-extern unsigned long sh7372_cpu_resume;
-
-#ifdef CONFIG_PM
-extern void __init sh7372_init_pm_domains(void);
-#else
-static inline void sh7372_init_pm_domains(void) {}
-#endif
-
-extern void __init sh7372_pm_init_late(void);
-
-#endif /* __ASM_SH7372_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-#ifndef __ASM_SH73A0_H__
-#define __ASM_SH73A0_H__
-
-/* DMA slave IDs */
-enum {
-	SHDMA_SLAVE_INVALID,
-	SHDMA_SLAVE_SCIF0_TX,
-	SHDMA_SLAVE_SCIF0_RX,
-	SHDMA_SLAVE_SCIF1_TX,
-	SHDMA_SLAVE_SCIF1_RX,
-	SHDMA_SLAVE_SCIF2_TX,
-	SHDMA_SLAVE_SCIF2_RX,
-	SHDMA_SLAVE_SCIF3_TX,
-	SHDMA_SLAVE_SCIF3_RX,
-	SHDMA_SLAVE_SCIF4_TX,
-	SHDMA_SLAVE_SCIF4_RX,
-	SHDMA_SLAVE_SCIF5_TX,
-	SHDMA_SLAVE_SCIF5_RX,
-	SHDMA_SLAVE_SCIF6_TX,
-	SHDMA_SLAVE_SCIF6_RX,
-	SHDMA_SLAVE_SCIF7_TX,
-	SHDMA_SLAVE_SCIF7_RX,
-	SHDMA_SLAVE_SCIF8_TX,
-	SHDMA_SLAVE_SCIF8_RX,
-	SHDMA_SLAVE_SDHI0_TX,
-	SHDMA_SLAVE_SDHI0_RX,
-	SHDMA_SLAVE_SDHI1_TX,
-	SHDMA_SLAVE_SDHI1_RX,
-	SHDMA_SLAVE_SDHI2_TX,
-	SHDMA_SLAVE_SDHI2_RX,
-	SHDMA_SLAVE_MMCIF_TX,
-	SHDMA_SLAVE_MMCIF_RX,
-	SHDMA_SLAVE_FSI2A_TX,
-	SHDMA_SLAVE_FSI2A_RX,
-	SHDMA_SLAVE_FSI2B_TX,
-	SHDMA_SLAVE_FSI2B_RX,
-	SHDMA_SLAVE_FSI2C_TX,
-	SHDMA_SLAVE_FSI2C_RX,
-	SHDMA_SLAVE_FSI2D_RX,
-};
-
-/*
- *		SH73A0 IRQ LOCATION TABLE
- *
- * 416	-----------------------------------------
- *		IRQ0-IRQ15
- * 431	-----------------------------------------
- * ...
- * 448	-----------------------------------------
- *		sh73a0-intcs
- *		sh73a0-intca-irq-pins
- * 680	-----------------------------------------
- * ...
- * 700	-----------------------------------------
- *		sh73a0-pint0
- * 731	-----------------------------------------
- * 732	-----------------------------------------
- *		sh73a0-pint1
- * 739	-----------------------------------------
- * ...
- * 800	-----------------------------------------
- *		IRQ16-IRQ31
- * 815	-----------------------------------------
- * ...
- * 928	-----------------------------------------
- *		sh73a0-intca-irq-pins
- * 943	-----------------------------------------
- */
-
-/* PINT interrupts are located at Linux IRQ 700 and up */
-#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
-#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
-
-extern void sh73a0_init_delay(void);
-extern void sh73a0_init_irq(void);
-extern void sh73a0_init_irq_dt(void);
-extern void sh73a0_map_io(void);
-extern void sh73a0_earlytimer_init(void);
-extern void sh73a0_add_early_devices(void);
-extern void sh73a0_add_standard_devices(void);
-extern void sh73a0_add_standard_devices_dt(void);
-extern void sh73a0_clock_init(void);
-extern void sh73a0_pinmux_init(void);
-extern void sh73a0_pm_init(void);
-extern struct clk sh73a0_extal1_clk;
-extern struct clk sh73a0_extal2_clk;
-extern struct clk sh73a0_extcki_clk;
-extern struct clk sh73a0_extalr_clk;
-extern struct smp_operations sh73a0_smp_ops;
-
-#endif /* __ASM_SH73A0_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,290 @@
+#ifndef __ASM_MACH_INTC_H
+#define __ASM_MACH_INTC_H
+#include <linux/sh_intc.h>
+
+#define INTC_IRQ_PINS_ENUM_16L(p)				\
+	p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7,		\
+	p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,	\
+	p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
+
+#define INTC_IRQ_PINS_ENUM_16H(p)				\
+	p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,	\
+	p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23,	\
+	p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,	\
+	p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
+
+#define INTC_IRQ_PINS_VECT_16L(p, vect)				\
+	vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220),	\
+	vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260),	\
+	vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0),	\
+	vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0),	\
+	vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320),	\
+	vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360),	\
+	vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0),	\
+	vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
+
+#define INTC_IRQ_PINS_VECT_16H(p, vect)				\
+	vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220),	\
+	vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260),	\
+	vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0),	\
+	vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0),	\
+	vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320),	\
+	vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360),	\
+	vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0),	\
+	vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
+
+#define INTC_IRQ_PINS_MASK_16L(p, base)					\
+	{ base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */	\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */	\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_MASK_16H(p, base)					\
+	{ base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */	\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */	\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_PRIO_16L(p, base)					\
+	{ base + 0x10, 0, 32, 4, /* INTPRI00A */			\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x14, 0, 32, 4, /* INTPRI10A */			\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_PRIO_16H(p, base)					\
+	{ base + 0x18, 0, 32, 4, /* INTPRI20A */			\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x1c, 0, 32, 4, /* INTPRI30A */			\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_SENSE_16L(p, base)				\
+	{ base + 0x00, 32, 4, /* ICR1A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x04, 32, 4, /* ICR2A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_SENSE_16H(p, base)				\
+	{ base + 0x08, 32, 4, /* ICR3A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x0c, 32, 4, /* ICR4A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_ACK_16L(p, base)					\
+	{ base + 0x20, 0, 8, /* INTREQ00A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x24, 0, 8, /* INTREQ10A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_ACK_16H(p, base)					\
+	{ base + 0x28, 0, 8, /* INTREQ20A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x2c, 0, 8, /* INTREQ30A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_16(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x64,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_16H(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x64,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16H(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16H(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16H(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16H(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16H(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16H(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_32(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x6c,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+	INTC_IRQ_PINS_ENUM_16H(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+	INTC_IRQ_PINS_VECT_16H(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+	INTC_IRQ_PINS_MASK_16H(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+	INTC_IRQ_PINS_PRIO_16H(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+	INTC_IRQ_PINS_SENSE_16H(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+	INTC_IRQ_PINS_ACK_16H(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_PINT_E_EMPTY
+#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
+#define INTC_PINT_E(p)							\
+	PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3,	\
+	PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
+
+#define INTC_PINT_V_NONE
+#define INTC_PINT_V(p, vect)					\
+	vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1),	\
+	vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3),	\
+	vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5),	\
+	vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
+
+#define INTC_PINT(p, mask_reg, sense_base, str,				\
+	enums_1, enums_2, enums_3, enums_4,				\
+	vect_1, vect_2, vect_3, vect_4,					\
+	mask_a, mask_b, mask_c, mask_d,					\
+	sense_a, sense_b, sense_c, sense_d)				\
+									\
+enum {									\
+	PINT ## p ## _UNUSED = 0,					\
+	enums_1 enums_2 enums_3 enums_4 				\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	vect_1 vect_2 vect_3 vect_4					\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	{ mask_reg, 0, 32, /* PINTER */					\
+	  { mask_a mask_b mask_c mask_d } }				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	{ sense_base + 0x00, 16, 2, /* PINTCR */			\
+	  { sense_a } },						\
+	{ sense_base + 0x04, 16, 2, /* PINTCR */			\
+	  { sense_b } },						\
+	{ sense_base + 0x08, 16, 2, /* PINTCR */			\
+	  { sense_c } },						\
+	{ sense_base + 0x0c, 16, 2, /* PINTCR */			\
+	  { sense_d } },						\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, NULL,		\
+			     p ## _sense_registers, NULL),		\
+}
+
+#endif  /* __ASM_MACH_INTC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc-sh7372.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc-sh7372.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,11 +22,10 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sh_intc.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include "intc.h"
+#include "irqs.h"
 
 enum {
 	UNUSED_INTCA = 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc-sh73a0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc-sh73a0.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/intc-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/intc-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,15 +22,16 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sh_intc.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "intc.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
 enum {
 	UNUSED = 0,
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/irqs.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/irqs.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,21 @@
+#ifndef __SHMOBILE_IRQS_H
+#define __SHMOBILE_IRQS_H
+
+#include <linux/sh_intc.h>
+#include <mach/irqs.h>
+
+/* GIC */
+#define gic_spi(nr)		((nr) + 32)
+#define gic_iid(nr)		(nr) /* ICCIAR / interrupt ID */
+
+/* INTCS */
+#define INTCS_VECT_BASE		0x3400
+#define INTCS_VECT(n, vect)	INTC_VECT((n), INTCS_VECT_BASE + (vect))
+#define intcs_evt2irq(evt)	evt2irq(INTCS_VECT_BASE + (evt))
+
+/* GPIO IRQ */
+#define _GPIO_IRQ_BASE		2500
+#define GPIO_IRQ_BASE(x)	(_GPIO_IRQ_BASE + (32 * x))
+#define GPIO_IRQ(x, y)		(_GPIO_IRQ_BASE + (32 * x) + y)
+
+#endif /* __SHMOBILE_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@ menuconfig ARCH_SHMOBILE_MULTI
 	select NO_IOPORT_MAP
 	select PINCTRL
 	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_OPP
 
 if ARCH_SHMOBILE_MULTI
 
@@ -25,6 +26,11 @@ config ARCH_R7S72100
 	bool "RZ/A1H (R7S72100)"
 	select SYS_SUPPORTS_SH_MTU2
 
+config ARCH_R8A7779
+	bool "R-Car H1 (R8A77790)"
+	select RENESAS_INTC_IRQPIN
+	select SYS_SUPPORTS_SH_TMU
+
 config ARCH_R8A7790
 	bool "R-Car H2 (R8A77900)"
 	select RENESAS_IRQC
@@ -51,6 +57,11 @@ config MACH_LAGER
 	depends on ARCH_R8A7790
 	select MICREL_PHY if SH_ETH
 
+config MACH_MARZEN
+	bool "MARZEN board"
+	depends on ARCH_R8A7779
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+
 comment "Renesas ARM SoCs System Configuration"
 endif
 
@@ -64,6 +75,7 @@ config ARCH_SH7372
 	select ARM_CPU_SUSPEND if PM || CPU_IDLE
 	select CPU_V7
 	select SH_CLK_CPG
+	select SH_INTC
 	select SYS_SUPPORTS_SH_CMT
 	select SYS_SUPPORTS_SH_TMU
 
@@ -74,6 +86,7 @@ config ARCH_SH73A0
 	select CPU_V7
 	select I2C
 	select SH_CLK_CPG
+	select SH_INTC
 	select RENESAS_INTC_IRQPIN
 	select SYS_SUPPORTS_SH_CMT
 	select SYS_SUPPORTS_SH_TMU
@@ -85,7 +98,6 @@ config ARCH_R8A73A4
 	select CPU_V7
 	select SH_CLK_CPG
 	select RENESAS_IRQC
-	select ARCH_HAS_OPP
 	select SYS_SUPPORTS_SH_CMT
 	select SYS_SUPPORTS_SH_TMU
 
@@ -234,19 +246,6 @@ config MACH_MARZEN
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
 
-config MACH_MARZEN_REFERENCE
-	bool "MARZEN board - Reference Device Tree Implementation"
-	depends on ARCH_R8A7779
-	select ARCH_REQUIRE_GPIOLIB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	select USE_OF
-	---help---
-	   Use reference implementation of Marzen board support
-	   which makes use of device tree at the expense
-	   of not supporting a number of devices.
-
-	   This is intended to aid developers
-
 config MACH_LAGER
 	bool "Lager board"
 	depends on ARCH_R8A7790
@@ -263,7 +262,6 @@ config MACH_KOELSCH
 config MACH_KZM9G
 	bool "KZM-A9-GT board"
 	depends on ARCH_SH73A0
-	select ARCH_HAS_OPP
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -34,31 +34,39 @@ obj-$(CONFIG_ARCH_R8A7791)	+= clock-r8a7
 obj-$(CONFIG_ARCH_R7S72100)	+= clock-r7s72100.o
 endif
 
+# CPU reset vector handling objects
+cpu-y				:= platsmp.o headsmp.o
+cpu-$(CONFIG_ARCH_R8A7790)	+= platsmp-apmu.o
+cpu-$(CONFIG_ARCH_R8A7791)	+= platsmp-apmu.o
+
 # SMP objects
-smp-y				:= platsmp.o headsmp.o
+smp-y				:= $(cpu-y)
 smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o platsmp-scu.o
 smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o platsmp-scu.o
-smp-$(CONFIG_ARCH_R8A7790)	+= smp-r8a7790.o platsmp-apmu.o
-smp-$(CONFIG_ARCH_R8A7791)	+= smp-r8a7791.o platsmp-apmu.o
+smp-$(CONFIG_ARCH_R8A7790)	+= smp-r8a7790.o
+smp-$(CONFIG_ARCH_R8A7791)	+= smp-r8a7791.o
 smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o platsmp-scu.o
 
-# IRQ objects
-obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
-
 # PM objects
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o pm-rmobile.o
 obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
 obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o pm-rmobile.o
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o pm-rcar.o
-obj-$(CONFIG_ARCH_R8A7790)	+= pm-r8a7790.o pm-rcar.o
+obj-$(CONFIG_ARCH_R8A7790)	+= pm-r8a7790.o pm-rcar.o $(cpu-y)
+obj-$(CONFIG_ARCH_R8A7791)	+= pm-r8a7791.o pm-rcar.o $(cpu-y)
+
+# IRQ objects
+obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
 
 # Board objects
 ifdef CONFIG_ARCH_SHMOBILE_MULTI
 obj-$(CONFIG_MACH_GENMAI)	+= board-genmai-reference.o
 obj-$(CONFIG_MACH_KOELSCH)	+= board-koelsch-reference.o
 obj-$(CONFIG_MACH_LAGER)	+= board-lager-reference.o
+obj-$(CONFIG_MACH_MARZEN)	+= board-marzen-reference.o
 else
 obj-$(CONFIG_MACH_APE6EVM)	+= board-ape6evm.o
 obj-$(CONFIG_MACH_APE6EVM_REFERENCE)	+= board-ape6evm-reference.o
@@ -67,7 +75,6 @@ obj-$(CONFIG_MACH_BOCKW)	+= board-bockw.
 obj-$(CONFIG_MACH_BOCKW_REFERENCE)	+= board-bockw-reference.o
 obj-$(CONFIG_MACH_GENMAI)	+= board-genmai.o
 obj-$(CONFIG_MACH_MARZEN)	+= board-marzen.o
-obj-$(CONFIG_MACH_MARZEN_REFERENCE)	+= board-marzen-reference.o
 obj-$(CONFIG_MACH_LAGER)	+= board-lager.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)	+= board-armadillo800eva.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE)	+= board-armadillo800eva-reference.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/Makefile.boot linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Makefile.boot
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/Makefile.boot	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/Makefile.boot	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@ loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE)
 loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
 loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000
 loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
-loadaddr-$(CONFIG_MACH_MARZEN_REFERENCE) += 0x60008000
 
 __ZRELADDR	:= $(sort $(loadaddr-y))
    zreladdr-y   += $(__ZRELADDR)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp-apmu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp-apmu.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp-apmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp-apmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,27 +7,32 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/cpu_pm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
 #include <linux/smp.h>
+#include <linux/suspend.h>
+#include <linux/threads.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
+#include <asm/proc-fns.h>
 #include <asm/smp_plat.h>
-#include <mach/common.h>
+#include <asm/suspend.h>
+#include "common.h"
 
 static struct {
 	void __iomem *iomem;
 	int bit;
-} apmu_cpus[CONFIG_NR_CPUS];
+} apmu_cpus[NR_CPUS];
 
 #define WUPCR_OFFS 0x10
 #define PSTR_OFFS 0x40
 #define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
 
-static int apmu_power_on(void __iomem *p, int bit)
+static int __maybe_unused apmu_power_on(void __iomem *p, int bit)
 {
 	/* request power on */
 	writel_relaxed(BIT(bit), p + WUPCR_OFFS);
@@ -46,7 +51,7 @@ static int apmu_power_off(void __iomem *
 	return 0;
 }
 
-static int apmu_power_off_poll(void __iomem *p, int bit)
+static int __maybe_unused apmu_power_off_poll(void __iomem *p, int bit)
 {
 	int k;
 
@@ -69,7 +74,7 @@ static int apmu_wrap(int cpu, int (*fn)(
 
 static void apmu_init_cpu(struct resource *res, int cpu, int bit)
 {
-	if (apmu_cpus[cpu].iomem)
+	if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem)
 		return;
 
 	apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
@@ -133,6 +138,7 @@ void __init shmobile_smp_apmu_prepare_cp
 	apmu_parse_cfg(apmu_init_cpu);
 }
 
+#ifdef CONFIG_SMP
 int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	/* For this particular CPU register boot vector */
@@ -140,8 +146,9 @@ int shmobile_smp_apmu_boot_secondary(uns
 
 	return apmu_wrap(cpu, apmu_power_on);
 }
+#endif
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
 /* nicked from arch/arm/mach-exynos/hotplug.c */
 static inline void cpu_enter_lowpower_a15(void)
 {
@@ -172,16 +179,40 @@ static inline void cpu_enter_lowpower_a1
 	dsb();
 }
 
-void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
 {
-	/* For this particular CPU deregister boot vector */
-	shmobile_smp_hook(cpu, 0, 0);
 
 	/* Select next sleep mode using the APMU */
 	apmu_wrap(cpu, apmu_power_off);
 
 	/* Do ARM specific CPU shutdown */
 	cpu_enter_lowpower_a15();
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile("mrc    p15, 0, %0, c1, c0, 0\n"
+		     "       orr     %0, %0, %1\n"
+		     "       mcr     p15, 0, %0, c1, c0, 0\n"
+		     "       mrc     p15, 0, %0, c1, c0, 1\n"
+		     "       orr     %0, %0, %2\n"
+		     "       mcr     p15, 0, %0, c1, c0, 1\n"
+		     : "=&r" (v)
+		     : "Ir" (CR_C), "Ir" (0x40)
+		     : "cc");
+}
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU)
+void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+	/* For this particular CPU deregister boot vector */
+	shmobile_smp_hook(cpu, 0, 0);
+
+	/* Shutdown CPU core */
+	shmobile_smp_apmu_cpu_shutdown(cpu);
 
 	/* jump to shared mach-shmobile sleep / reset code */
 	shmobile_smp_sleep();
@@ -192,3 +223,25 @@ int shmobile_smp_apmu_cpu_kill(unsigned
 	return apmu_wrap(cpu, apmu_power_off_poll);
 }
 #endif
+
+#if defined(CONFIG_SUSPEND)
+static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
+{
+	shmobile_smp_hook(cpu, virt_to_phys(cpu_resume), 0);
+	shmobile_smp_apmu_cpu_shutdown(cpu);
+	cpu_do_idle(); /* WFI selects Core Standby */
+	return 1;
+}
+
+static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
+{
+	cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
+	cpu_leave_lowpower();
+	return 0;
+}
+
+void __init shmobile_smp_apmu_suspend_init(void)
+{
+	shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
+}
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
-#include <mach/common.h>
+#include "common.h"
 
 extern unsigned long shmobile_smp_fn[];
 extern unsigned long shmobile_smp_arg[];
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp-scu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp-scu.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/platsmp-scu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/platsmp-scu.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,7 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <mach/common.h>
+#include "common.h"
 
 static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
 					  unsigned long action, void *hcpu)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7740.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7740.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7740.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7740.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,8 +10,8 @@
  */
 #include <linux/console.h>
 #include <linux/suspend.h>
-#include <mach/pm-rmobile.h>
-#include <mach/common.h>
+#include "common.h"
+#include "pm-rmobile.h"
 
 #ifdef CONFIG_PM
 static int r8a7740_pd_a4s_suspend(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7779.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7779.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7779.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7779.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,20 +13,33 @@
 #include <linux/suspend.h>
 #include <linux/err.h>
 #include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
+
 #include <asm/io.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7779.h>
+
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
 
 /* SYSC */
 #define SYSCIER 0x0c
 #define SYSCIMR 0x10
 
+struct r8a7779_pm_domain {
+	struct generic_pm_domain genpd;
+	struct rcar_sysc_ch ch;
+};
+
+static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+{
+	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
+}
+
 #if defined(CONFIG_PM) || defined(CONFIG_SMP)
 
 static void __init r8a7779_sysc_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7790.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7790.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7790.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7790.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,9 +11,21 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <asm/io.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7790.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7790.h"
+
+/* RST */
+#define RST		0xe6160000
+#define CA15BAR		0x0020
+#define CA7BAR		0x0030
+#define CA15RESCNT	0x0040
+#define CA7RESCNT	0x0044
+
+/* On-chip RAM */
+#define MERAM          0xe8080000
 
 /* SYSC */
 #define SYSCIER 0x0c
@@ -38,8 +50,33 @@ static inline void r8a7790_sysc_init(voi
 
 void __init r8a7790_pm_init(void)
 {
+	void __iomem *p;
+	u32 bar;
 	static int once;
 
-	if (!once++)
-		r8a7790_sysc_init();
+	if (once++)
+		return;
+
+	/* MERAM for jump stub, because BAR requires 256KB aligned address */
+	p = ioremap_nocache(MERAM, shmobile_boot_size);
+	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+	iounmap(p);
+
+	/* setup reset vectors */
+	p = ioremap_nocache(RST, 0x63);
+	bar = (MERAM >> 8) & 0xfffffc00;
+	writel_relaxed(bar, p + CA15BAR);
+	writel_relaxed(bar, p + CA7BAR);
+	writel_relaxed(bar | 0x10, p + CA15BAR);
+	writel_relaxed(bar | 0x10, p + CA7BAR);
+
+	/* de-assert reset for all CPUs */
+	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+		       p + CA15RESCNT);
+	writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
+		       p + CA7RESCNT);
+	iounmap(p);
+
+	r8a7790_sysc_init();
+	shmobile_smp_apmu_suspend_init();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7791.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7791.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-r8a7791.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-r8a7791.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * r8a7791 Power management support
+ *
+ * Copyright (C) 2014  Renesas Electronics Corporation
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7791.h"
+
+#define RST		0xe6160000
+#define CA15BAR		0x0020
+#define CA15RESCNT	0x0040
+#define RAM		0xe6300000
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init r8a7791_sysc_init(void)
+{
+	void __iomem *base = rcar_sysc_init(0xe6180000);
+
+	/* enable all interrupt sources, but do not use interrupt handler */
+	iowrite32(0x0131000e, base + SYSCIER);
+	iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_SMP */
+
+static inline void r8a7791_sysc_init(void) {}
+
+#endif /* CONFIG_SMP */
+
+void __init r8a7791_pm_init(void)
+{
+	void __iomem *p;
+	u32 bar;
+	static int once;
+
+	if (once++)
+		return;
+
+	/* RAM for jump stub, because BAR requires 256KB aligned address */
+	p = ioremap_nocache(RAM, shmobile_boot_size);
+	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+	iounmap(p);
+
+	/* setup reset vectors */
+	p = ioremap_nocache(RST, 0x63);
+	bar = (RAM >> 8) & 0xfffffc00;
+	writel_relaxed(bar, p + CA15BAR);
+	writel_relaxed(bar | 0x10, p + CA15BAR);
+
+	/* enable clocks to all CPUs */
+	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+		       p + CA15RESCNT);
+	iounmap(p);
+
+	r8a7791_sysc_init();
+	shmobile_smp_apmu_suspend_init();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rcar.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rcar.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rcar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rcar.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
-#include <mach/pm-rcar.h>
+#include "pm-rcar.h"
 
 /* SYSC */
 #define SYSCSR 0x00
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rcar.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rcar.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rcar.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rcar.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,15 @@
+#ifndef PM_RCAR_H
+#define PM_RCAR_H
+
+struct rcar_sysc_ch {
+	unsigned long chan_offs;
+	unsigned int chan_bit;
+	unsigned int isr_bit;
+};
+
+int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch);
+int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch);
+bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch);
+void __iomem *rcar_sysc_init(phys_addr_t base);
+
+#endif /* PM_RCAR_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rmobile.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rmobile.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rmobile.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rmobile.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,7 @@
 #include <linux/pm.h>
 #include <linux/pm_clock.h>
 #include <asm/io.h>
-#include <mach/pm-rmobile.h>
+#include "pm-rmobile.h"
 
 /* SYSC */
 #define SPDCR		IOMEM(0xe6180008)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rmobile.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rmobile.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-rmobile.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-rmobile.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef PM_RMOBILE_H
+#define PM_RMOBILE_H
+
+#include <linux/pm_domain.h>
+
+#define DEFAULT_DEV_LATENCY_NS	250000
+
+struct platform_device;
+
+struct rmobile_pm_domain {
+	struct generic_pm_domain genpd;
+	struct dev_power_governor *gov;
+	int (*suspend)(void);
+	void (*resume)(void);
+	unsigned int bit_shift;
+	bool no_debug;
+};
+
+static inline
+struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
+{
+	return container_of(d, struct rmobile_pm_domain, genpd);
+}
+
+struct pm_domain_device {
+	const char *domain_name;
+	struct platform_device *pdev;
+};
+
+#ifdef CONFIG_PM
+extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
+extern void rmobile_add_device_to_domain_td(const char *domain_name,
+					    struct platform_device *pdev,
+					    struct gpd_timing_data *td);
+
+static inline void rmobile_add_device_to_domain(const char *domain_name,
+						struct platform_device *pdev)
+{
+	rmobile_add_device_to_domain_td(domain_name, pdev, NULL);
+}
+
+extern void rmobile_add_devices_to_domains(struct pm_domain_device data[],
+					   int size);
+#else
+
+#define rmobile_init_domains(domains, num) do { } while (0)
+#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0)
+#define rmobile_add_device_to_domain(name, pdev) do { } while (0)
+
+static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[],
+						  int size) {}
+#endif /* CONFIG_PM */
+
+#endif /* PM_RMOBILE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-sh7372.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-sh7372.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-sh7372.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-sh7372.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,13 +21,15 @@
 #include <linux/irq.h>
 #include <linux/bitrev.h>
 #include <linux/console.h>
+
 #include <asm/cpuidle.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/suspend.h>
-#include <mach/common.h>
-#include <mach/sh7372.h>
-#include <mach/pm-rmobile.h>
+
+#include "common.h"
+#include "pm-rmobile.h"
+#include "sh7372.h"
 
 /* DBG */
 #define DBGREG1 IOMEM(0xe6100020)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-sh73a0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-sh73a0.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/pm-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/pm-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,7 +9,7 @@
  */
 
 #include <linux/suspend.h>
-#include <mach/common.h>
+#include "common.h"
 
 #ifdef CONFIG_SUSPEND
 static int sh73a0_enter_suspend(suspend_state_t suspend_state)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r7s72100.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r7s72100.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r7s72100.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r7s72100.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __ASM_R7S72100_H__
+#define __ASM_R7S72100_H__
+
+void r7s72100_add_dt_devices(void);
+void r7s72100_clock_init(void);
+
+#endif /* __ASM_R7S72100_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a73a4.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a73a4.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a73a4.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a73a4.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+#ifndef __ASM_R8A73A4_H__
+#define __ASM_R8A73A4_H__
+
+/* DMA slave IDs */
+enum {
+	SHDMA_SLAVE_INVALID,
+	SHDMA_SLAVE_MMCIF0_TX,
+	SHDMA_SLAVE_MMCIF0_RX,
+	SHDMA_SLAVE_MMCIF1_TX,
+	SHDMA_SLAVE_MMCIF1_RX,
+};
+
+void r8a73a4_add_standard_devices(void);
+void r8a73a4_add_dt_devices(void);
+void r8a73a4_clock_init(void);
+void r8a73a4_pinmux_init(void);
+void r8a73a4_init_early(void);
+
+#endif /* __ASM_R8A73A4_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7740.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7740.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7740.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7740.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  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 as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __ASM_R8A7740_H__
+#define __ASM_R8A7740_H__
+
+/*
+ * MD_CKx pin
+ */
+#define MD_CK2	(1 << 2)
+#define MD_CK1	(1 << 1)
+#define MD_CK0	(1 << 0)
+
+/* DMA slave IDs */
+enum {
+	SHDMA_SLAVE_INVALID,
+	SHDMA_SLAVE_SDHI0_RX,
+	SHDMA_SLAVE_SDHI0_TX,
+	SHDMA_SLAVE_SDHI1_RX,
+	SHDMA_SLAVE_SDHI1_TX,
+	SHDMA_SLAVE_SDHI2_RX,
+	SHDMA_SLAVE_SDHI2_TX,
+	SHDMA_SLAVE_FSIA_RX,
+	SHDMA_SLAVE_FSIA_TX,
+	SHDMA_SLAVE_FSIB_TX,
+	SHDMA_SLAVE_USBHS_TX,
+	SHDMA_SLAVE_USBHS_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+};
+
+extern void r8a7740_meram_workaround(void);
+extern void r8a7740_init_irq_of(void);
+extern void r8a7740_map_io(void);
+extern void r8a7740_add_early_devices(void);
+extern void r8a7740_add_standard_devices(void);
+extern void r8a7740_add_standard_devices_dt(void);
+extern void r8a7740_clock_init(u8 md_ck);
+extern void r8a7740_pinmux_init(void);
+extern void r8a7740_pm_init(void);
+
+#ifdef CONFIG_PM
+extern void __init r8a7740_init_pm_domains(void);
+#else
+static inline void r8a7740_init_pm_domains(void) {}
+#endif /* CONFIG_PM */
+
+#endif /* __ASM_R8A7740_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7778.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7778.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7778.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7778.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2013  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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __ASM_R8A7778_H__
+#define __ASM_R8A7778_H__
+
+#include <linux/sh_eth.h>
+
+/* HPB-DMA slave IDs */
+enum {
+	HPBDMA_SLAVE_DUMMY,
+	HPBDMA_SLAVE_SDHI0_TX,
+	HPBDMA_SLAVE_SDHI0_RX,
+	HPBDMA_SLAVE_SSI0_TX,
+	HPBDMA_SLAVE_SSI0_RX,
+	HPBDMA_SLAVE_SSI1_TX,
+	HPBDMA_SLAVE_SSI1_RX,
+	HPBDMA_SLAVE_SSI2_TX,
+	HPBDMA_SLAVE_SSI2_RX,
+	HPBDMA_SLAVE_SSI3_TX,
+	HPBDMA_SLAVE_SSI3_RX,
+	HPBDMA_SLAVE_SSI4_TX,
+	HPBDMA_SLAVE_SSI4_RX,
+	HPBDMA_SLAVE_SSI5_TX,
+	HPBDMA_SLAVE_SSI5_RX,
+	HPBDMA_SLAVE_SSI6_TX,
+	HPBDMA_SLAVE_SSI6_RX,
+	HPBDMA_SLAVE_SSI7_TX,
+	HPBDMA_SLAVE_SSI7_RX,
+	HPBDMA_SLAVE_SSI8_TX,
+	HPBDMA_SLAVE_SSI8_RX,
+	HPBDMA_SLAVE_HPBIF0_TX,
+	HPBDMA_SLAVE_HPBIF0_RX,
+	HPBDMA_SLAVE_HPBIF1_TX,
+	HPBDMA_SLAVE_HPBIF1_RX,
+	HPBDMA_SLAVE_HPBIF2_TX,
+	HPBDMA_SLAVE_HPBIF2_RX,
+	HPBDMA_SLAVE_HPBIF3_TX,
+	HPBDMA_SLAVE_HPBIF3_RX,
+	HPBDMA_SLAVE_HPBIF4_TX,
+	HPBDMA_SLAVE_HPBIF4_RX,
+	HPBDMA_SLAVE_HPBIF5_TX,
+	HPBDMA_SLAVE_HPBIF5_RX,
+	HPBDMA_SLAVE_HPBIF6_TX,
+	HPBDMA_SLAVE_HPBIF6_RX,
+	HPBDMA_SLAVE_HPBIF7_TX,
+	HPBDMA_SLAVE_HPBIF7_RX,
+	HPBDMA_SLAVE_HPBIF8_TX,
+	HPBDMA_SLAVE_HPBIF8_RX,
+	HPBDMA_SLAVE_USBFUNC_TX,
+	HPBDMA_SLAVE_USBFUNC_RX,
+};
+
+extern void r8a7778_add_standard_devices(void);
+extern void r8a7778_add_standard_devices_dt(void);
+extern void r8a7778_add_dt_devices(void);
+
+extern void r8a7778_init_late(void);
+extern void r8a7778_init_delay(void);
+extern void r8a7778_init_irq_dt(void);
+extern void r8a7778_clock_init(void);
+extern void r8a7778_init_irq_extpin(int irlm);
+extern void r8a7778_init_irq_extpin_dt(int irlm);
+extern void r8a7778_pinmux_init(void);
+
+extern int r8a7778_usb_phy_power(bool enable);
+
+#endif /* __ASM_R8A7778_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7779.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7779.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7779.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7779.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+#ifndef __ASM_R8A7779_H__
+#define __ASM_R8A7779_H__
+
+#include <linux/sh_clk.h>
+
+/* HPB-DMA slave IDs */
+enum {
+	HPBDMA_SLAVE_DUMMY,
+	HPBDMA_SLAVE_SDHI0_TX,
+	HPBDMA_SLAVE_SDHI0_RX,
+};
+
+extern void r8a7779_init_irq_extpin(int irlm);
+extern void r8a7779_init_irq_extpin_dt(int irlm);
+extern void r8a7779_init_irq_dt(void);
+extern void r8a7779_map_io(void);
+extern void r8a7779_earlytimer_init(void);
+extern void r8a7779_add_early_devices(void);
+extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_add_standard_devices_dt(void);
+extern void r8a7779_init_late(void);
+extern u32 r8a7779_read_mode_pins(void);
+extern void r8a7779_clock_init(void);
+extern void r8a7779_pinmux_init(void);
+extern void r8a7779_pm_init(void);
+extern void r8a7779_register_twd(void);
+
+#ifdef CONFIG_PM
+extern void __init r8a7779_init_pm_domains(void);
+#else
+static inline void r8a7779_init_pm_domains(void) {}
+#endif /* CONFIG_PM */
+
+extern struct smp_operations r8a7779_smp_ops;
+
+#endif /* __ASM_R8A7779_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7790.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7790.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7790.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7790.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+#ifndef __ASM_R8A7790_H__
+#define __ASM_R8A7790_H__
+
+/* DMA slave IDs */
+enum {
+	RCAR_DMA_SLAVE_INVALID,
+	AUDIO_DMAC_SLAVE_SSI0_TX,
+	AUDIO_DMAC_SLAVE_SSI0_RX,
+	AUDIO_DMAC_SLAVE_SSI1_TX,
+	AUDIO_DMAC_SLAVE_SSI1_RX,
+	AUDIO_DMAC_SLAVE_SSI2_TX,
+	AUDIO_DMAC_SLAVE_SSI2_RX,
+	AUDIO_DMAC_SLAVE_SSI3_TX,
+	AUDIO_DMAC_SLAVE_SSI3_RX,
+	AUDIO_DMAC_SLAVE_SSI4_TX,
+	AUDIO_DMAC_SLAVE_SSI4_RX,
+	AUDIO_DMAC_SLAVE_SSI5_TX,
+	AUDIO_DMAC_SLAVE_SSI5_RX,
+	AUDIO_DMAC_SLAVE_SSI6_TX,
+	AUDIO_DMAC_SLAVE_SSI6_RX,
+	AUDIO_DMAC_SLAVE_SSI7_TX,
+	AUDIO_DMAC_SLAVE_SSI7_RX,
+	AUDIO_DMAC_SLAVE_SSI8_TX,
+	AUDIO_DMAC_SLAVE_SSI8_RX,
+	AUDIO_DMAC_SLAVE_SSI9_TX,
+	AUDIO_DMAC_SLAVE_SSI9_RX,
+};
+
+void r8a7790_add_standard_devices(void);
+void r8a7790_add_dt_devices(void);
+void r8a7790_clock_init(void);
+void r8a7790_pinmux_init(void);
+void r8a7790_pm_init(void);
+extern struct smp_operations r8a7790_smp_ops;
+
+#endif /* __ASM_R8A7790_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7791.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7791.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/r8a7791.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/r8a7791.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,11 @@
+#ifndef __ASM_R8A7791_H__
+#define __ASM_R8A7791_H__
+
+void r8a7791_add_standard_devices(void);
+void r8a7791_add_dt_devices(void);
+void r8a7791_clock_init(void);
+void r8a7791_pinmux_init(void);
+void r8a7791_pm_init(void);
+extern struct smp_operations r8a7791_smp_ops;
+
+#endif /* __ASM_R8A7791_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/rcar-gen2.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/rcar-gen2.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/rcar-gen2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/rcar-gen2.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef __ASM_RCAR_GEN2_H__
+#define __ASM_RCAR_GEN2_H__
+
+void rcar_gen2_timer_init(void);
+#define MD(nr) BIT(nr)
+u32 rcar_gen2_read_mode_pins(void);
+void rcar_gen2_reserve(void);
+
+#endif /* __ASM_RCAR_GEN2_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-emev2.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-emev2.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-emev2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-emev2.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,14 +16,13 @@
  * 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/clk-provider.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/of_platform.h>
-#include <mach/common.h>
+#include <linux/mm.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include "common.h"
 
 static struct map_desc emev2_io_desc[] __initdata = {
 #ifdef CONFIG_SMP
@@ -42,17 +41,6 @@ static void __init emev2_map_io(void)
 	iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
 }
 
-static void __init emev2_init_delay(void)
-{
-	shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
-}
-
-static void __init emev2_add_standard_devices_dt(void)
-{
-	of_clk_init(NULL);
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char *emev2_boards_compat_dt[] __initconst = {
 	"renesas,emev2",
 	NULL,
@@ -63,8 +51,7 @@ extern struct smp_operations emev2_smp_o
 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
 	.smp		= smp_ops(emev2_smp_ops),
 	.map_io		= emev2_map_io,
-	.init_early	= emev2_init_delay,
-	.init_machine	= emev2_add_standard_devices_dt,
+	.init_early	= shmobile_init_delay,
 	.init_late	= shmobile_init_late,
 	.dt_compat	= emev2_boards_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r7s72100.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r7s72100.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r7s72100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r7s72100.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,18 +22,20 @@
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r7s72100.h>
+
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r7s72100.h"
+
 static struct resource mtu2_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfcff0000, 0x400),
 	DEFINE_RES_IRQ_NAMED(gic_iid(139), "tgi0a"),
 };
 
 #define r7s72100_register_mtu2()					\
-	platform_device_register_resndata(&platform_bus, "sh-mtu2",	\
+	platform_device_register_resndata(NULL, "sh-mtu2",		\
 					  -1, mtu2_resources,		\
 					  ARRAY_SIZE(mtu2_resources),	\
 					  NULL, 0)
@@ -43,11 +45,6 @@ void __init r7s72100_add_dt_devices(void
 	r7s72100_register_mtu2();
 }
 
-void __init r7s72100_init_early(void)
-{
-	shmobile_setup_delay(400, 1, 3); /* Cortex-A9 @ 400MHz */
-}
-
 #ifdef CONFIG_USE_OF
 static const char *r7s72100_boards_compat_dt[] __initdata = {
 	"renesas,r7s72100",
@@ -55,7 +52,7 @@ static const char *r7s72100_boards_compa
 };
 
 DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
-	.init_early	= r7s72100_init_early,
+	.init_early	= shmobile_init_delay,
 	.dt_compat	= r7s72100_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a73a4.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a73a4.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a73a4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a73a4.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,14 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/r8a73a4.h>
+
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "r8a73a4.h"
+
 static const struct resource pfc_resources[] = {
 	DEFINE_RES_MEM(0xe6050000, 0x9000),
 };
@@ -68,7 +70,7 @@ R8A73A4_SCIFB(4, 0xe6ce0000, gic_spi(150
 R8A73A4_SCIFB(5, 0xe6cf0000, gic_spi(151)); /* SCIFB3 */
 
 #define r8a73a4_register_scif(index)					       \
-	platform_device_register_resndata(&platform_bus, "sh-sci", index,      \
+	platform_device_register_resndata(NULL, "sh-sci", index,	       \
 					  scif##index##_resources,	       \
 					  ARRAY_SIZE(scif##index##_resources), \
 					  &scif##index##_platform_data,	       \
@@ -149,7 +151,7 @@ static const struct resource irqc1_resou
 };
 
 #define r8a73a4_register_irqc(idx)					\
-	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+	platform_device_register_resndata(NULL, "renesas_irqc", 	\
 					  idx, irqc##idx##_resources,	\
 					  ARRAY_SIZE(irqc##idx##_resources), \
 					  &irqc##idx##_data,		\
@@ -179,7 +181,7 @@ static struct resource cmt1_resources[]
 };
 
 #define r8a7790_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+	platform_device_register_resndata(NULL, "sh-cmt-48-gen2",	\
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -187,12 +189,6 @@ static struct resource cmt1_resources[]
 
 void __init r8a73a4_add_dt_devices(void)
 {
-	r8a73a4_register_scif(0);
-	r8a73a4_register_scif(1);
-	r8a73a4_register_scif(2);
-	r8a73a4_register_scif(3);
-	r8a73a4_register_scif(4);
-	r8a73a4_register_scif(5);
 	r8a7790_register_cmt(1);
 }
 
@@ -280,13 +276,19 @@ static struct resource dma_resources[] =
 };
 
 #define r8a73a4_register_dmac()							\
-	platform_device_register_resndata(&platform_bus, "sh-dma-engine", 0,	\
+	platform_device_register_resndata(NULL, "sh-dma-engine", 0,		\
 				dma_resources, ARRAY_SIZE(dma_resources),	\
 				&dma_pdata, sizeof(dma_pdata))
 
 void __init r8a73a4_add_standard_devices(void)
 {
 	r8a73a4_add_dt_devices();
+	r8a73a4_register_scif(0);
+	r8a73a4_register_scif(1);
+	r8a73a4_register_scif(2);
+	r8a73a4_register_scif(3);
+	r8a73a4_register_scif(4);
+	r8a73a4_register_scif(5);
 	r8a73a4_register_irqc(0);
 	r8a73a4_register_irqc(1);
 	r8a73a4_register_thermal();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7740.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7740.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7740.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7740.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,16 +31,18 @@
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
 #include <linux/platform_data/sh_ipmmu.h>
-#include <mach/dma-register.h>
-#include <mach/r8a7740.h>
-#include <mach/pm-rmobile.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
+
 static struct map_desc r8a7740_io_desc[] __initdata = {
 	 /*
 	  * for CPGA/INTC/PFC
@@ -310,6 +312,10 @@ static struct platform_device ipmmu_devi
 };
 
 static struct platform_device *r8a7740_devices_dt[] __initdata = {
+	&cmt1_device,
+};
+
+static struct platform_device *r8a7740_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -319,10 +325,6 @@ static struct platform_device *r8a7740_d
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt1_device,
-};
-
-static struct platform_device *r8a7740_early_devices[] __initdata = {
 	&irqpin0_device,
 	&irqpin1_device,
 	&irqpin2_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7778.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7778.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7778.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7778.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,12 +37,14 @@
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/dma-mapping.h>
-#include <mach/irqs.h>
-#include <mach/r8a7778.h>
-#include <mach/common.h>
+
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
 /* SCIF */
 #define R8A7778_SCIF(index, baseaddr, irq)			\
 static struct plat_sci_port scif##index##_platform_data = {	\
@@ -64,7 +66,7 @@ R8A7778_SCIF(4, 0xffe44000, gic_iid(0x6a
 R8A7778_SCIF(5, 0xffe45000, gic_iid(0x6b));
 
 #define r8a7778_register_scif(index)					       \
-	platform_device_register_resndata(&platform_bus, "sh-sci", index,      \
+	platform_device_register_resndata(NULL, "sh-sci", index,	       \
 					  scif##index##_resources,	       \
 					  ARRAY_SIZE(scif##index##_resources), \
 					  &scif##index##_platform_data,	       \
@@ -84,7 +86,7 @@ static struct resource sh_tmu0_resources
 
 #define r8a7778_register_tmu(idx)			\
 	platform_device_register_resndata(		\
-		&platform_bus, "sh-tmu", idx,		\
+		NULL, "sh-tmu", idx,			\
 		sh_tmu##idx##_resources,		\
 		ARRAY_SIZE(sh_tmu##idx##_resources),	\
 		&sh_tmu##idx##_platform_data,		\
@@ -173,7 +175,6 @@ static struct resource ohci_resources[]
 
 #define USB_PLATFORM_INFO(hci)					\
 static struct platform_device_info hci##_info __initdata = {	\
-	.parent		= &platform_bus,			\
 	.name		= #hci "-platform",			\
 	.id		= -1,					\
 	.res		= hci##_resources,			\
@@ -212,7 +213,7 @@ R8A7778_GPIO(4);
 
 #define r8a7778_register_gpio(idx)				\
 	platform_device_register_resndata(			\
-		&platform_bus, "gpio_rcar", idx,		\
+		NULL, "gpio_rcar", idx,				\
 		r8a7778_gpio##idx##_resources,			\
 		ARRAY_SIZE(r8a7778_gpio##idx##_resources),	\
 		&r8a7778_gpio##idx##_platform_data,		\
@@ -292,12 +293,6 @@ void __init r8a7778_add_dt_devices(void)
 	}
 #endif
 
-	r8a7778_register_scif(0);
-	r8a7778_register_scif(1);
-	r8a7778_register_scif(2);
-	r8a7778_register_scif(3);
-	r8a7778_register_scif(4);
-	r8a7778_register_scif(5);
 	r8a7778_register_tmu(0);
 }
 
@@ -496,8 +491,8 @@ static struct resource hpb_dmae_resource
 
 static void __init r8a7778_register_hpb_dmae(void)
 {
-	platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
-					  hpb_dmae_resources,
+	platform_device_register_resndata(NULL, "hpb-dma-engine",
+					  -1, hpb_dmae_resources,
 					  ARRAY_SIZE(hpb_dmae_resources),
 					  &dma_platform_data,
 					  sizeof(dma_platform_data));
@@ -506,6 +501,12 @@ static void __init r8a7778_register_hpb_
 void __init r8a7778_add_standard_devices(void)
 {
 	r8a7778_add_dt_devices();
+	r8a7778_register_scif(0);
+	r8a7778_register_scif(1);
+	r8a7778_register_scif(2);
+	r8a7778_register_scif(3);
+	r8a7778_register_scif(4);
+	r8a7778_register_scif(5);
 	r8a7778_register_i2c(0);
 	r8a7778_register_i2c(1);
 	r8a7778_register_i2c(2);
@@ -565,7 +566,7 @@ void __init r8a7778_init_irq_extpin(int
 	r8a7778_init_irq_extpin_dt(irlm);
 	if (irlm)
 		platform_device_register_resndata(
-			&platform_bus, "renesas_intc_irqpin", -1,
+			NULL, "renesas_intc_irqpin", -1,
 			irqpin_resources, ARRAY_SIZE(irqpin_resources),
 			&irqpin_platform_data, sizeof(irqpin_platform_data));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7779.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7779.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7779.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7779.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,15 +40,17 @@
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/pm_runtime.h>
-#include <mach/irqs.h>
-#include <mach/r8a7779.h>
-#include <mach/common.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
 static struct map_desc r8a7779_io_desc[] __initdata = {
 	/* 2M entity map for 0xf0000000 (MPCORE) */
 	{
@@ -123,7 +125,7 @@ void __init r8a7779_init_irq_extpin(int
 	r8a7779_init_irq_extpin_dt(irlm);
 	if (irlm)
 		platform_device_register_resndata(
-			&platform_bus, "renesas_intc_irqpin", -1,
+			NULL, "renesas_intc_irqpin", -1,
 			irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
 			&irqpin0_platform_data, sizeof(irqpin0_platform_data));
 }
@@ -632,24 +634,24 @@ static struct resource hpb_dmae_resource
 
 static void __init r8a7779_register_hpb_dmae(void)
 {
-	platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
-					  hpb_dmae_resources,
+	platform_device_register_resndata(NULL, "hpb-dma-engine",
+					  -1, hpb_dmae_resources,
 					  ARRAY_SIZE(hpb_dmae_resources),
 					  &dma_platform_data,
 					  sizeof(dma_platform_data));
 }
 
 static struct platform_device *r8a7779_devices_dt[] __initdata = {
+	&tmu0_device,
+};
+
+static struct platform_device *r8a7779_standard_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
 	&scif3_device,
 	&scif4_device,
 	&scif5_device,
-	&tmu0_device,
-};
-
-static struct platform_device *r8a7779_standard_devices[] __initdata = {
 	&i2c0_device,
 	&i2c1_device,
 	&i2c2_device,
@@ -674,16 +676,6 @@ void __init r8a7779_add_standard_devices
 	r8a7779_register_hpb_dmae();
 }
 
-/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
-void __init __weak r8a7779_register_twd(void) { }
-
-void __init r8a7779_earlytimer_init(void)
-{
-	r8a7779_clock_init();
-	r8a7779_register_twd();
-	shmobile_earlytimer_init();
-}
-
 void __init r8a7779_add_early_devices(void)
 {
 	early_platform_add_devices(r8a7779_devices_dt,
@@ -747,19 +739,28 @@ void __init r8a7779_init_irq_dt(void)
 	__raw_writel(0x003fee3f, INT2SMSKCR4);
 }
 
-void __init r8a7779_init_delay(void)
+void __init r8a7779_add_standard_devices_dt(void)
 {
-	shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
+	platform_add_devices(r8a7779_devices_dt,
+			     ARRAY_SIZE(r8a7779_devices_dt));
 }
 
-void __init r8a7779_add_standard_devices_dt(void)
+#define MODEMR		0xffcc0020
+
+u32 __init r8a7779_read_mode_pins(void)
 {
-	/* clocks are setup late during boot in the case of DT */
-	r8a7779_clock_init();
+	static u32 mode;
+	static bool mode_valid;
 
-	platform_add_devices(r8a7779_devices_dt,
-			     ARRAY_SIZE(r8a7779_devices_dt));
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	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 const char *r8a7779_compat_dt[] __initdata = {
@@ -769,7 +770,7 @@ static const char *r8a7779_compat_dt[] _
 
 DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
 	.map_io		= r8a7779_map_io,
-	.init_early	= r8a7779_init_delay,
+	.init_early	= shmobile_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= r8a7779_init_irq_dt,
 	.init_machine	= r8a7779_add_standard_devices_dt,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7790.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7790.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7790.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7790.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,12 +26,15 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/r8a7790.h>
+
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
 /* Audio-DMAC */
 #define AUDIO_DMAC_SLAVE(_id, _addr, t, r)			\
 {								\
@@ -113,7 +116,7 @@ static struct resource r8a7790_audio_dma
 
 #define r8a7790_register_audio_dmac(id)				\
 	platform_device_register_resndata(			\
-		&platform_bus, "sh-dma-engine", id,		\
+		NULL, "sh-dma-engine", id,			\
 		&r8a7790_audio_dmac_resources[id * 3],	3,	\
 		&r8a7790_audio_dmac_platform_data,		\
 		sizeof(r8a7790_audio_dmac_platform_data))
@@ -149,7 +152,7 @@ R8A7790_GPIO(4);
 R8A7790_GPIO(5);
 
 #define r8a7790_register_gpio(idx)					\
-	platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+	platform_device_register_resndata(NULL, "gpio_rcar", idx,	\
 		r8a7790_gpio##idx##_resources,				\
 		ARRAY_SIZE(r8a7790_gpio##idx##_resources),		\
 		&r8a7790_gpio##idx##_platform_data,			\
@@ -227,7 +230,7 @@ R8A7790_HSCIF(8, 0xe62c0000, gic_spi(154
 R8A7790_HSCIF(9, 0xe62c8000, gic_spi(155)); /* HSCIF1 */
 
 #define r8a7790_register_scif(index)					       \
-	platform_device_register_resndata(&platform_bus, "sh-sci", index,      \
+	platform_device_register_resndata(NULL, "sh-sci", index,  	       \
 					  scif##index##_resources,	       \
 					  ARRAY_SIZE(scif##index##_resources), \
 					  &scif##index##_platform_data,	       \
@@ -246,7 +249,7 @@ static const struct resource irqc0_resou
 };
 
 #define r8a7790_register_irqc(idx)					\
-	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+	platform_device_register_resndata(NULL, "renesas_irqc",		\
 					  idx, irqc##idx##_resources,	\
 					  ARRAY_SIZE(irqc##idx##_resources), \
 					  &irqc##idx##_data,		\
@@ -273,7 +276,7 @@ static struct resource cmt0_resources[]
 };
 
 #define r8a7790_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+	platform_device_register_resndata(NULL, "sh-cmt-48-gen2",	\
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -307,13 +310,6 @@ void __init r8a7790_add_standard_devices
 	r8a7790_register_audio_dmac(1);
 }
 
-void __init r8a7790_init_early(void)
-{
-#ifndef CONFIG_ARM_ARCH_TIMER
-	shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
-#endif
-}
-
 #ifdef CONFIG_USE_OF
 
 static const char * const r8a7790_boards_compat_dt[] __initconst = {
@@ -323,8 +319,10 @@ static const char * const r8a7790_boards
 
 DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
 	.smp		= smp_ops(r8a7790_smp_ops),
-	.init_early	= r8a7790_init_early,
+	.init_early	= shmobile_init_delay,
 	.init_time	= rcar_gen2_timer_init,
+	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= r8a7790_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7791.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7791.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-r8a7791.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-r8a7791.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,12 +26,14 @@
 #include <linux/platform_data/irq-renesas-irqc.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
+
 #include <asm/mach/arch.h>
 
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
 static const struct resource pfc_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe6060000, 0x250),
 };
@@ -65,7 +67,7 @@ R8A7791_GPIO(6, 0xe6055400, 32);
 R8A7791_GPIO(7, 0xe6055800, 26);
 
 #define r8a7791_register_gpio(idx)					\
-	platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+	platform_device_register_resndata(NULL, "gpio_rcar", idx,	\
 		r8a7791_gpio##idx##_resources,				\
 		ARRAY_SIZE(r8a7791_gpio##idx##_resources),		\
 		&r8a7791_gpio##idx##_platform_data,			\
@@ -122,7 +124,7 @@ R8A7791_SCIFA(13, 0xe6c78000, gic_spi(30
 R8A7791_SCIFA(14, 0xe6c80000, gic_spi(31)); /* SCIFA5 */
 
 #define r8a7791_register_scif(index)					       \
-	platform_device_register_resndata(&platform_bus, "sh-sci", index,      \
+	platform_device_register_resndata(NULL, "sh-sci", index,  	       \
 					  scif##index##_resources,	       \
 					  ARRAY_SIZE(scif##index##_resources), \
 					  &scif##index##_platform_data,	       \
@@ -138,7 +140,7 @@ static struct resource cmt0_resources[]
 };
 
 #define r8a7791_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+	platform_device_register_resndata(NULL, "sh-cmt-48-gen2",	\
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -163,7 +165,7 @@ static struct resource irqc0_resources[]
 };
 
 #define r8a7791_register_irqc(idx)					\
-	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+	platform_device_register_resndata(NULL, "renesas_irqc",		\
 					  idx, irqc##idx##_resources,	\
 					  ARRAY_SIZE(irqc##idx##_resources), \
 					  &irqc##idx##_data,		\
@@ -217,6 +219,8 @@ DT_MACHINE_START(R8A7791_DT, "Generic R8
 	.smp		= smp_ops(r8a7791_smp_ops),
 	.init_early	= shmobile_init_delay,
 	.init_time	= rcar_gen2_timer_init,
+	.init_late	= shmobile_init_late,
+	.reserve	= rcar_gen2_reserve,
 	.dt_compat	= r8a7791_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,11 +20,14 @@
 
 #include <linux/clk/shmobile.h>
 #include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/dma-contiguous.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <mach/common.h>
-#include <mach/rcar-gen2.h>
+#include <linux/of_fdt.h>
 #include <asm/mach/arch.h>
+#include "common.h"
+#include "rcar-gen2.h"
 
 #define MODEMR 0xe6160060
 
@@ -110,3 +113,72 @@ void __init rcar_gen2_timer_init(void)
 #endif
 	clocksource_of_init();
 }
+
+struct memory_reserve_config {
+	u64 reserved;
+	u64 base, size;
+};
+
+static int __init rcar_gen2_scan_mem(unsigned long node, const char *uname,
+				     int depth, void *data)
+{
+	const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+	const __be32 *reg, *endp;
+	int l;
+	struct memory_reserve_config *mrc = data;
+	u64 lpae_start = 1ULL << 32;
+
+	/* We are scanning "memory" nodes only */
+	if (type == NULL || strcmp(type, "memory"))
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+	if (reg == NULL)
+		reg = of_get_flat_dt_prop(node, "reg", &l);
+	if (reg == NULL)
+		return 0;
+
+	endp = reg + (l / sizeof(__be32));
+	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+		u64 base, size;
+
+		base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+		size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+		if (base >= lpae_start)
+			continue;
+
+		if ((base + size) >= lpae_start)
+			size = lpae_start - base;
+
+		if (size < mrc->reserved)
+			continue;
+
+		if (base < mrc->base)
+			continue;
+
+		/* keep the area at top near the 32-bit legacy limit */
+		mrc->base = base + size - mrc->reserved;
+		mrc->size = mrc->reserved;
+	}
+
+	return 0;
+}
+
+struct cma *rcar_gen2_dma_contiguous;
+
+void __init rcar_gen2_reserve(void)
+{
+	struct memory_reserve_config mrc;
+
+	/* reserve 256 MiB at the top of the physical legacy 32-bit space */
+	memset(&mrc, 0, sizeof(mrc));
+	mrc.reserved = SZ_256M;
+
+	of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
+#ifdef CONFIG_DMA_CMA
+	if (mrc.size)
+		dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
+					    &rcar_gen2_dma_contiguous, true);
+#endif
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-sh7372.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-sh7372.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,20 +29,22 @@
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
-#include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/pm_domain.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/sh_ipmmu.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/sh7372.h>
-#include <mach/common.h>
+
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "sh7372.h"
+
 static struct map_desc sh7372_io_desc[] __initdata = {
 	/* create a 1:1 entity map for 0xe6xxxxxx
 	 * used by CPGA, INTC and PFC.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-sh73a0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-sh73a0.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/setup-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/setup-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,19 +29,20 @@
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
-#include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/platform_data/sh_ipmmu.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
 static struct map_desc sh73a0_io_desc[] __initdata = {
 	/* create a 1:1 entity map for 0xe6xxxxxx
 	 * used by CPGA, INTC and PFC.
@@ -696,6 +697,10 @@ static struct platform_device irqpin3_de
 };
 
 static struct platform_device *sh73a0_devices_dt[] __initdata = {
+	&cmt1_device,
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -705,10 +710,6 @@ static struct platform_device *sh73a0_de
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt1_device,
-};
-
-static struct platform_device *sh73a0_early_devices[] __initdata = {
 	&tmu0_device,
 	&ipmmu_device,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/sh7372.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/sh7372.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/sh7372.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/sh7372.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ASM_SH7372_H__
+#define __ASM_SH7372_H__
+
+/* DMA slave IDs */
+enum {
+	SHDMA_SLAVE_INVALID,
+	SHDMA_SLAVE_SCIF0_TX,
+	SHDMA_SLAVE_SCIF0_RX,
+	SHDMA_SLAVE_SCIF1_TX,
+	SHDMA_SLAVE_SCIF1_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_SCIF5_TX,
+	SHDMA_SLAVE_SCIF5_RX,
+	SHDMA_SLAVE_SCIF6_TX,
+	SHDMA_SLAVE_SCIF6_RX,
+	SHDMA_SLAVE_FLCTL0_TX,
+	SHDMA_SLAVE_FLCTL0_RX,
+	SHDMA_SLAVE_FLCTL1_TX,
+	SHDMA_SLAVE_FLCTL1_RX,
+	SHDMA_SLAVE_SDHI0_RX,
+	SHDMA_SLAVE_SDHI0_TX,
+	SHDMA_SLAVE_SDHI1_RX,
+	SHDMA_SLAVE_SDHI1_TX,
+	SHDMA_SLAVE_SDHI2_RX,
+	SHDMA_SLAVE_SDHI2_TX,
+	SHDMA_SLAVE_FSIA_RX,
+	SHDMA_SLAVE_FSIA_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_USB0_TX,
+	SHDMA_SLAVE_USB0_RX,
+	SHDMA_SLAVE_USB1_TX,
+	SHDMA_SLAVE_USB1_RX,
+};
+
+extern struct clk sh7372_extal1_clk;
+extern struct clk sh7372_extal2_clk;
+extern struct clk sh7372_dv_clki_clk;
+extern struct clk sh7372_dv_clki_div2_clk;
+extern struct clk sh7372_pllc2_clk;
+
+extern void sh7372_init_irq(void);
+extern void sh7372_map_io(void);
+extern void sh7372_earlytimer_init(void);
+extern void sh7372_add_early_devices(void);
+extern void sh7372_add_standard_devices(void);
+extern void sh7372_add_early_devices_dt(void);
+extern void sh7372_add_standard_devices_dt(void);
+extern void sh7372_clock_init(void);
+extern void sh7372_pinmux_init(void);
+extern void sh7372_pm_init(void);
+extern void sh7372_resume_core_standby_sysc(void);
+extern int  sh7372_do_idle_sysc(unsigned long sleep_mode);
+extern void sh7372_intcs_suspend(void);
+extern void sh7372_intcs_resume(void);
+extern void sh7372_intca_suspend(void);
+extern void sh7372_intca_resume(void);
+
+extern unsigned long sh7372_cpu_resume;
+
+#ifdef CONFIG_PM
+extern void __init sh7372_init_pm_domains(void);
+#else
+static inline void sh7372_init_pm_domains(void) {}
+#endif
+
+extern void __init sh7372_pm_init_late(void);
+
+#endif /* __ASM_SH7372_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/sh73a0.h linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/sh73a0.h
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/sh73a0.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/sh73a0.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,91 @@
+#ifndef __ASM_SH73A0_H__
+#define __ASM_SH73A0_H__
+
+/* DMA slave IDs */
+enum {
+	SHDMA_SLAVE_INVALID,
+	SHDMA_SLAVE_SCIF0_TX,
+	SHDMA_SLAVE_SCIF0_RX,
+	SHDMA_SLAVE_SCIF1_TX,
+	SHDMA_SLAVE_SCIF1_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_SCIF5_TX,
+	SHDMA_SLAVE_SCIF5_RX,
+	SHDMA_SLAVE_SCIF6_TX,
+	SHDMA_SLAVE_SCIF6_RX,
+	SHDMA_SLAVE_SCIF7_TX,
+	SHDMA_SLAVE_SCIF7_RX,
+	SHDMA_SLAVE_SCIF8_TX,
+	SHDMA_SLAVE_SCIF8_RX,
+	SHDMA_SLAVE_SDHI0_TX,
+	SHDMA_SLAVE_SDHI0_RX,
+	SHDMA_SLAVE_SDHI1_TX,
+	SHDMA_SLAVE_SDHI1_RX,
+	SHDMA_SLAVE_SDHI2_TX,
+	SHDMA_SLAVE_SDHI2_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+	SHDMA_SLAVE_FSI2A_TX,
+	SHDMA_SLAVE_FSI2A_RX,
+	SHDMA_SLAVE_FSI2B_TX,
+	SHDMA_SLAVE_FSI2B_RX,
+	SHDMA_SLAVE_FSI2C_TX,
+	SHDMA_SLAVE_FSI2C_RX,
+	SHDMA_SLAVE_FSI2D_RX,
+};
+
+/*
+ *		SH73A0 IRQ LOCATION TABLE
+ *
+ * 416	-----------------------------------------
+ *		IRQ0-IRQ15
+ * 431	-----------------------------------------
+ * ...
+ * 448	-----------------------------------------
+ *		sh73a0-intcs
+ *		sh73a0-intca-irq-pins
+ * 680	-----------------------------------------
+ * ...
+ * 700	-----------------------------------------
+ *		sh73a0-pint0
+ * 731	-----------------------------------------
+ * 732	-----------------------------------------
+ *		sh73a0-pint1
+ * 739	-----------------------------------------
+ * ...
+ * 800	-----------------------------------------
+ *		IRQ16-IRQ31
+ * 815	-----------------------------------------
+ * ...
+ * 928	-----------------------------------------
+ *		sh73a0-intca-irq-pins
+ * 943	-----------------------------------------
+ */
+
+/* PINT interrupts are located at Linux IRQ 700 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
+
+extern void sh73a0_init_delay(void);
+extern void sh73a0_init_irq(void);
+extern void sh73a0_init_irq_dt(void);
+extern void sh73a0_map_io(void);
+extern void sh73a0_earlytimer_init(void);
+extern void sh73a0_add_early_devices(void);
+extern void sh73a0_add_standard_devices(void);
+extern void sh73a0_add_standard_devices_dt(void);
+extern void sh73a0_clock_init(void);
+extern void sh73a0_pinmux_init(void);
+extern void sh73a0_pm_init(void);
+extern struct clk sh73a0_extal1_clk;
+extern struct clk sh73a0_extal2_clk;
+extern struct clk sh73a0_extcki_clk;
+extern struct clk sh73a0_extalr_clk;
+extern struct smp_operations sh73a0_smp_ops;
+
+#endif /* __ASM_SH73A0_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-emev2.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-emev2.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-emev2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-emev2.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,9 +23,9 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <mach/common.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
+#include "common.h"
 
 #define EMEV2_SCU_BASE 0x1e000000
 #define EMEV2_SMU_BASE 0xe0110000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7779.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7779.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7779.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7779.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,14 +23,16 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7779.h>
+
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
+
 #define AVECR IOMEM(0xfe700040)
 #define R8A7779_SCU_BASE 0xf0000000
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7790.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7790.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7790.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7790.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,17 +17,12 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+
 #include <asm/smp_plat.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7790.h>
 
-#define RST		0xe6160000
-#define CA15BAR		0x0020
-#define CA7BAR		0x0030
-#define CA15RESCNT	0x0040
-#define CA7RESCNT	0x0044
-#define MERAM		0xe8080000
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7790.h"
 
 static struct rcar_sysc_ch r8a7790_ca15_scu = {
 	.chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
@@ -41,32 +36,9 @@ static struct rcar_sysc_ch r8a7790_ca7_s
 
 static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
 {
-	void __iomem *p;
-	u32 bar;
-
 	/* let APMU code install data related to shmobile_boot_vector */
 	shmobile_smp_apmu_prepare_cpus(max_cpus);
 
-	/* MERAM for jump stub, because BAR requires 256KB aligned address */
-	p = ioremap_nocache(MERAM, shmobile_boot_size);
-	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
-	iounmap(p);
-
-	/* setup reset vectors */
-	p = ioremap_nocache(RST, 0x63);
-	bar = (MERAM >> 8) & 0xfffffc00;
-	writel_relaxed(bar, p + CA15BAR);
-	writel_relaxed(bar, p + CA7BAR);
-	writel_relaxed(bar | 0x10, p + CA15BAR);
-	writel_relaxed(bar | 0x10, p + CA7BAR);
-
-	/* enable clocks to all CPUs */
-	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
-		       p + CA15RESCNT);
-	writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
-		       p + CA7RESCNT);
-	iounmap(p);
-
 	/* turn on power to SCU */
 	r8a7790_pm_init();
 	rcar_sysc_power_up(&r8a7790_ca15_scu);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7791.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7791.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-r8a7791.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-r8a7791.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,39 +17,19 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+
 #include <asm/smp_plat.h>
-#include <mach/common.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
 
-#define RST		0xe6160000
-#define CA15BAR		0x0020
-#define CA15RESCNT	0x0040
-#define RAM		0xe6300000
+#include "common.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
 
 static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
 {
-	void __iomem *p;
-	u32 bar;
-
 	/* let APMU code install data related to shmobile_boot_vector */
 	shmobile_smp_apmu_prepare_cpus(max_cpus);
 
-	/* RAM for jump stub, because BAR requires 256KB aligned address */
-	p = ioremap_nocache(RAM, shmobile_boot_size);
-	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
-	iounmap(p);
-
-	/* setup reset vectors */
-	p = ioremap_nocache(RST, 0x63);
-	bar = (RAM >> 8) & 0xfffffc00;
-	writel_relaxed(bar, p + CA15BAR);
-	writel_relaxed(bar | 0x10, p + CA15BAR);
-
-	/* enable clocks to all CPUs */
-	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
-		       p + CA15RESCNT);
-	iounmap(p);
+	r8a7791_pm_init();
 }
 
 static int r8a7791_smp_boot_secondary(unsigned int cpu,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-sh73a0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-sh73a0.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/smp-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/smp-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,11 +22,13 @@
 #include <linux/smp.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <mach/common.h>
-#include <mach/sh73a0.h>
+
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
 
+#include "common.h"
+#include "sh73a0.h"
+
 #define WUPCR		IOMEM(0xe6151010)
 #define SRESCR		IOMEM(0xe6151018)
 #define PSTR		IOMEM(0xe6151040)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-shmobile/timer.c linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/timer.c
--- linux-libre-3.16-gnu/arch/arm/mach-shmobile/timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-shmobile/timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,29 +59,37 @@ void __init shmobile_setup_delay(unsigne
 
 void __init shmobile_init_delay(void)
 {
-	struct device_node *np, *parent;
-	u32 max_freq, freq;
+	struct device_node *np, *cpus;
+	bool is_a8_a9 = false;
+	bool is_a15 = false;
+	u32 max_freq = 0;
 
-	max_freq = 0;
+	cpus = of_find_node_by_path("/cpus");
+	if (!cpus)
+		return;
 
-	parent = of_find_node_by_path("/cpus");
-	if (parent) {
-		for_each_child_of_node(parent, np) {
-			if (!of_property_read_u32(np, "clock-frequency", &freq))
-				max_freq = max(max_freq, freq);
-		}
-		of_node_put(parent);
-	}
+	for_each_child_of_node(cpus, np) {
+		u32 freq;
 
-	if (max_freq) {
-		if (of_find_compatible_node(NULL, NULL, "arm,cortex-a8"))
-			shmobile_setup_delay_hz(max_freq, 1, 3);
-		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
-			shmobile_setup_delay_hz(max_freq, 1, 3);
-		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a15"))
-			if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
-				shmobile_setup_delay_hz(max_freq, 2, 4);
+		if (!of_property_read_u32(np, "clock-frequency", &freq))
+			max_freq = max(max_freq, freq);
+
+		if (of_device_is_compatible(np, "arm,cortex-a8") ||
+		    of_device_is_compatible(np, "arm,cortex-a9"))
+			is_a8_a9 = true;
+		else if (of_device_is_compatible(np, "arm,cortex-a15"))
+			is_a15 = true;
 	}
+
+	of_node_put(cpus);
+
+	if (!max_freq)
+		return;
+
+	if (is_a8_a9)
+		shmobile_setup_delay_hz(max_freq, 1, 3);
+	else if (is_a15 && !IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
+		shmobile_setup_delay_hz(max_freq, 2, 4);
 }
 
 static void __init shmobile_late_time_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-spear/include/mach/spear.h linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/include/mach/spear.h
--- linux-libre-3.16-gnu/arch/arm/mach-spear/include/mach/spear.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/include/mach/spear.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,10 +52,10 @@
 #ifdef CONFIG_ARCH_SPEAR13XX
 
 #define PERIP_GRP2_BASE				UL(0xB3000000)
-#define VA_PERIP_GRP2_BASE			IOMEM(0xFE000000)
+#define VA_PERIP_GRP2_BASE			IOMEM(0xF9000000)
 #define MCIF_SDHCI_BASE				UL(0xB3000000)
 #define SYSRAM0_BASE				UL(0xB3800000)
-#define VA_SYSRAM0_BASE				IOMEM(0xFE800000)
+#define VA_SYSRAM0_BASE				IOMEM(0xF9800000)
 #define SYS_LOCATION				(VA_SYSRAM0_BASE + 0x600)
 
 #define PERIP_GRP1_BASE				UL(0xE0000000)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-spear/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-spear/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@ config ARCH_SPEAR13XX
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select PINCTRL
+	select MFD_SYSCON
+	select MIGHT_HAVE_PCI
 	help
 	  Supports for ARM's SPEAR13XX family
 
@@ -27,12 +29,14 @@ if ARCH_SPEAR13XX
 config MACH_SPEAR1310
 	bool "SPEAr1310 Machine support with Device Tree"
 	select PINCTRL_SPEAR1310
+	select PHY_ST_SPEAR1310_MIPHY
 	help
 	  Supports ST SPEAr1310 machine configured via the device-tree
 
 config MACH_SPEAR1340
 	bool "SPEAr1340 Machine support with Device Tree"
 	select PINCTRL_SPEAR1340
+	select PHY_ST_SPEAR1340_MIPHY
 	help
 	  Supports ST SPEAr1340 machine configured via the device-tree
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-spear/spear1310.c linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear1310.c
--- linux-libre-3.16-gnu/arch/arm/mach-spear/spear1310.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear1310.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,7 @@ static const char * const spear1310_dt_b
  * PHYSICAL		VIRTUAL
  * 0xD8000000		0xFA000000
  */
-struct map_desc spear1310_io_desc[] __initdata = {
+static struct map_desc spear1310_io_desc[] __initdata = {
 	{
 		.virtual	= VA_SPEAR1310_RAS_GRP1_BASE,
 		.pfn		= __phys_to_pfn(SPEAR1310_RAS_GRP1_BASE),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-spear/spear1340.c linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear1340.c
--- linux-libre-3.16-gnu/arch/arm/mach-spear/spear1340.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear1340.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,136 +13,13 @@
 
 #define pr_fmt(fmt) "SPEAr1340: " fmt
 
-#include <linux/ahci_platform.h>
-#include <linux/amba/serial.h>
-#include <linux/delay.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include "generic.h"
-#include <mach/spear.h>
-
-/* FIXME: Move SATA PHY code into a standalone driver */
-
-/* Base addresses */
-#define SPEAR1340_SATA_BASE			UL(0xB1000000)
-
-/* Power Management Registers */
-#define SPEAR1340_PCM_CFG			(VA_MISC_BASE + 0x100)
-#define SPEAR1340_PCM_WKUP_CFG			(VA_MISC_BASE + 0x104)
-#define SPEAR1340_SWITCH_CTR			(VA_MISC_BASE + 0x108)
-
-#define SPEAR1340_PERIP1_SW_RST			(VA_MISC_BASE + 0x318)
-#define SPEAR1340_PERIP2_SW_RST			(VA_MISC_BASE + 0x31C)
-#define SPEAR1340_PERIP3_SW_RST			(VA_MISC_BASE + 0x320)
-
-/* PCIE - SATA configuration registers */
-#define SPEAR1340_PCIE_SATA_CFG			(VA_MISC_BASE + 0x424)
-	/* PCIE CFG MASks */
-	#define SPEAR1340_PCIE_CFG_DEVICE_PRESENT	(1 << 11)
-	#define SPEAR1340_PCIE_CFG_POWERUP_RESET	(1 << 10)
-	#define SPEAR1340_PCIE_CFG_CORE_CLK_EN		(1 << 9)
-	#define SPEAR1340_PCIE_CFG_AUX_CLK_EN		(1 << 8)
-	#define SPEAR1340_SATA_CFG_TX_CLK_EN		(1 << 4)
-	#define SPEAR1340_SATA_CFG_RX_CLK_EN		(1 << 3)
-	#define SPEAR1340_SATA_CFG_POWERUP_RESET	(1 << 2)
-	#define SPEAR1340_SATA_CFG_PM_CLK_EN		(1 << 1)
-	#define SPEAR1340_PCIE_SATA_SEL_PCIE		(0)
-	#define SPEAR1340_PCIE_SATA_SEL_SATA		(1)
-	#define SPEAR1340_SATA_PCIE_CFG_MASK		0xF1F
-	#define SPEAR1340_PCIE_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_PCIE | \
-			SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
-			SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
-			SPEAR1340_PCIE_CFG_POWERUP_RESET | \
-			SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
-	#define SPEAR1340_SATA_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_SATA | \
-			SPEAR1340_SATA_CFG_PM_CLK_EN | \
-			SPEAR1340_SATA_CFG_POWERUP_RESET | \
-			SPEAR1340_SATA_CFG_RX_CLK_EN | \
-			SPEAR1340_SATA_CFG_TX_CLK_EN)
-
-#define SPEAR1340_PCIE_MIPHY_CFG		(VA_MISC_BASE + 0x428)
-	#define SPEAR1340_MIPHY_OSC_BYPASS_EXT		(1 << 31)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV2		(1 << 27)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV4		(2 << 27)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV8		(3 << 27)
-	#define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)	(x << 0)
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
-			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-			SPEAR1340_MIPHY_CLK_REF_DIV2 | \
-			SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
-			(SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
-			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-
-/* SATA device registration */
-static int sata_miphy_init(struct device *dev, void __iomem *addr)
-{
-	writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
-	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
-			SPEAR1340_PCIE_MIPHY_CFG);
-	/* Switch on sata power domain */
-	writel((readl(SPEAR1340_PCM_CFG) | (0x800)), SPEAR1340_PCM_CFG);
-	msleep(20);
-	/* Disable PCIE SATA Controller reset */
-	writel((readl(SPEAR1340_PERIP1_SW_RST) & (~0x1000)),
-			SPEAR1340_PERIP1_SW_RST);
-	msleep(20);
-
-	return 0;
-}
-
-void sata_miphy_exit(struct device *dev)
-{
-	writel(0, SPEAR1340_PCIE_SATA_CFG);
-	writel(0, SPEAR1340_PCIE_MIPHY_CFG);
-
-	/* Enable PCIE SATA Controller reset */
-	writel((readl(SPEAR1340_PERIP1_SW_RST) | (0x1000)),
-			SPEAR1340_PERIP1_SW_RST);
-	msleep(20);
-	/* Switch off sata power domain */
-	writel((readl(SPEAR1340_PCM_CFG) & (~0x800)), SPEAR1340_PCM_CFG);
-	msleep(20);
-}
-
-int sata_suspend(struct device *dev)
-{
-	if (dev->power.power_state.event == PM_EVENT_FREEZE)
-		return 0;
-
-	sata_miphy_exit(dev);
-
-	return 0;
-}
-
-int sata_resume(struct device *dev)
-{
-	if (dev->power.power_state.event == PM_EVENT_THAW)
-		return 0;
-
-	return sata_miphy_init(dev, NULL);
-}
-
-static struct ahci_platform_data sata_pdata = {
-	.init = sata_miphy_init,
-	.exit = sata_miphy_exit,
-	.suspend = sata_suspend,
-	.resume = sata_resume,
-};
-
-/* Add SPEAr1340 auxdata to pass platform data */
-static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
-			&sata_pdata),
-	{}
-};
 
 static void __init spear1340_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear1340_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-spear/spear13xx.c linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear13xx.c
--- linux-libre-3.16-gnu/arch/arm/mach-spear/spear13xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-spear/spear13xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,12 +52,12 @@ void __init spear13xx_l2x0_init(void)
 /*
  * Following will create 16MB static virtual/physical mappings
  * PHYSICAL		VIRTUAL
- * 0xB3000000		0xFE000000
+ * 0xB3000000		0xF9000000
  * 0xE0000000		0xFD000000
  * 0xEC000000		0xFC000000
  * 0xED000000		0xFB000000
  */
-struct map_desc spear13xx_io_desc[] __initdata = {
+static struct map_desc spear13xx_io_desc[] __initdata = {
 	{
 		.virtual	= (unsigned long)VA_PERIP_GRP2_BASE,
 		.pfn		= __phys_to_pfn(PERIP_GRP2_BASE),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-sti/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-sti/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-sti/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-sti/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@ static void write_pen_release(int val)
 
 static DEFINE_SPINLOCK(boot_lock);
 
-void sti_secondary_init(unsigned int cpu)
+static void sti_secondary_init(unsigned int cpu)
 {
 	trace_hardirqs_off();
 
@@ -53,7 +53,7 @@ void sti_secondary_init(unsigned int cpu
 	spin_unlock(&boot_lock);
 }
 
-int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 
@@ -97,7 +97,7 @@ int sti_boot_secondary(unsigned int cpu,
 	return pen_release != -1 ? -ENOSYS : 0;
 }
 
-void __init sti_smp_prepare_cpus(unsigned int max_cpus)
+static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
 {
 	void __iomem *scu_base = NULL;
 	struct device_node *np = of_find_compatible_node(
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-sunxi/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-sunxi/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-sunxi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-sunxi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
 	select PINCTRL
-	select PINCTRL_SUNXI
 	select SUN4I_TIMER
 
 if ARCH_SUNXI
@@ -35,4 +34,12 @@ config MACH_SUN7I
 	select HAVE_ARM_ARCH_TIMER
 	select SUN5I_HSTIMER
 
+config MACH_SUN8I
+	bool "Allwinner A23 (sun8i) SoCs support"
+	default ARCH_SUNXI
+	select ARCH_HAS_RESET_CONTROLLER
+	select ARM_GIC
+	select MFD_SUN6I_PRCM
+	select RESET_CONTROLLER
+
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-sunxi/sunxi.c linux-libre-3.17-rc7-gnu/arch/arm/mach-sunxi/sunxi.c
--- linux-libre-3.16-gnu/arch/arm/mach-sunxi/sunxi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-sunxi/sunxi.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,3 +130,12 @@ DT_MACHINE_START(SUN7I_DT, "Allwinner su
 	.dt_compat	= sun7i_board_dt_compat,
 	.restart	= sun4i_restart,
 MACHINE_END
+
+static const char * const sun8i_board_dt_compat[] = {
+	"allwinner,sun8i-a23",
+	NULL,
+};
+
+DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family")
+	.dt_compat	= sun8i_board_dt_compat,
+MACHINE_END
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/apbio.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/apbio.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/apbio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/apbio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2010 NVIDIA Corporation.
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-
-#include "apbio.h"
-#include "iomap.h"
-
-#if defined(CONFIG_TEGRA20_APB_DMA)
-static DEFINE_MUTEX(tegra_apb_dma_lock);
-static u32 *tegra_apb_bb;
-static dma_addr_t tegra_apb_bb_phys;
-static DECLARE_COMPLETION(tegra_apb_wait);
-
-static u32 tegra_apb_readl_direct(unsigned long offset);
-static void tegra_apb_writel_direct(u32 value, unsigned long offset);
-
-static struct dma_chan *tegra_apb_dma_chan;
-static struct dma_slave_config dma_sconfig;
-
-static bool tegra_apb_dma_init(void)
-{
-	dma_cap_mask_t mask;
-
-	mutex_lock(&tegra_apb_dma_lock);
-
-	/* Check to see if we raced to setup */
-	if (tegra_apb_dma_chan)
-		goto skip_init;
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL);
-	if (!tegra_apb_dma_chan) {
-		/*
-		 * This is common until the device is probed, so don't
-		 * shout about it.
-		 */
-		pr_debug("%s: can not allocate dma channel\n", __func__);
-		goto err_dma_alloc;
-	}
-
-	tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
-		&tegra_apb_bb_phys, GFP_KERNEL);
-	if (!tegra_apb_bb) {
-		pr_err("%s: can not allocate bounce buffer\n", __func__);
-		goto err_buff_alloc;
-	}
-
-	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	dma_sconfig.src_maxburst = 1;
-	dma_sconfig.dst_maxburst = 1;
-
-skip_init:
-	mutex_unlock(&tegra_apb_dma_lock);
-	return true;
-
-err_buff_alloc:
-	dma_release_channel(tegra_apb_dma_chan);
-	tegra_apb_dma_chan = NULL;
-
-err_dma_alloc:
-	mutex_unlock(&tegra_apb_dma_lock);
-	return false;
-}
-
-static void apb_dma_complete(void *args)
-{
-	complete(&tegra_apb_wait);
-}
-
-static int do_dma_transfer(unsigned long apb_add,
-		enum dma_transfer_direction dir)
-{
-	struct dma_async_tx_descriptor *dma_desc;
-	int ret;
-
-	if (dir == DMA_DEV_TO_MEM)
-		dma_sconfig.src_addr = apb_add;
-	else
-		dma_sconfig.dst_addr = apb_add;
-
-	ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig);
-	if (ret)
-		return ret;
-
-	dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan,
-			tegra_apb_bb_phys, sizeof(u32), dir,
-			DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
-	if (!dma_desc)
-		return -EINVAL;
-
-	dma_desc->callback = apb_dma_complete;
-	dma_desc->callback_param = NULL;
-
-	reinit_completion(&tegra_apb_wait);
-
-	dmaengine_submit(dma_desc);
-	dma_async_issue_pending(tegra_apb_dma_chan);
-	ret = wait_for_completion_timeout(&tegra_apb_wait,
-		msecs_to_jiffies(50));
-
-	if (WARN(ret == 0, "apb read dma timed out")) {
-		dmaengine_terminate_all(tegra_apb_dma_chan);
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static u32 tegra_apb_readl_using_dma(unsigned long offset)
-{
-	int ret;
-
-	if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
-		return tegra_apb_readl_direct(offset);
-
-	mutex_lock(&tegra_apb_dma_lock);
-	ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
-	if (ret < 0) {
-		pr_err("error in reading offset 0x%08lx using dma\n", offset);
-		*(u32 *)tegra_apb_bb = 0;
-	}
-	mutex_unlock(&tegra_apb_dma_lock);
-	return *((u32 *)tegra_apb_bb);
-}
-
-static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
-{
-	int ret;
-
-	if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) {
-		tegra_apb_writel_direct(value, offset);
-		return;
-	}
-
-	mutex_lock(&tegra_apb_dma_lock);
-	*((u32 *)tegra_apb_bb) = value;
-	ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
-	if (ret < 0)
-		pr_err("error in writing offset 0x%08lx using dma\n", offset);
-	mutex_unlock(&tegra_apb_dma_lock);
-}
-#else
-#define tegra_apb_readl_using_dma tegra_apb_readl_direct
-#define tegra_apb_writel_using_dma tegra_apb_writel_direct
-#endif
-
-typedef u32 (*apbio_read_fptr)(unsigned long offset);
-typedef void (*apbio_write_fptr)(u32 value, unsigned long offset);
-
-static apbio_read_fptr apbio_read;
-static apbio_write_fptr apbio_write;
-
-static u32 tegra_apb_readl_direct(unsigned long offset)
-{
-	return readl(IO_ADDRESS(offset));
-}
-
-static void tegra_apb_writel_direct(u32 value, unsigned long offset)
-{
-	writel(value, IO_ADDRESS(offset));
-}
-
-void tegra_apb_io_init(void)
-{
-	/* Need to use dma only when it is Tegra20 based platform */
-	if (of_machine_is_compatible("nvidia,tegra20") ||
-			!of_have_populated_dt()) {
-		apbio_read = tegra_apb_readl_using_dma;
-		apbio_write = tegra_apb_writel_using_dma;
-	} else {
-		apbio_read = tegra_apb_readl_direct;
-		apbio_write = tegra_apb_writel_direct;
-	}
-}
-
-u32 tegra_apb_readl(unsigned long offset)
-{
-	return apbio_read(offset);
-}
-
-void tegra_apb_writel(u32 value, unsigned long offset)
-{
-	apbio_write(value, offset);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/apbio.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/apbio.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/apbio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/apbio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 NVIDIA Corporation.
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_APBIO_H
-#define __MACH_TEGRA_APBIO_H
-
-void tegra_apb_io_init(void);
-u32 tegra_apb_readl(unsigned long offset);
-void tegra_apb_writel(u32 value, unsigned long offset);
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/board.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/board.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/board.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/board.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,13 +28,6 @@
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 
-int __init tegra_powergate_init(void);
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
-int __init tegra_powergate_debugfs_init(void);
-#else
-static inline int tegra_powergate_debugfs_init(void) { return 0; }
-#endif
-
 void __init tegra_paz00_wifikill_init(void);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/board-paz00.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/board-paz00.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/board-paz00.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/board-paz00.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,9 +17,10 @@
  *
  */
 
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
-#include <linux/gpio/driver.h>
 #include <linux/rfkill-gpio.h>
+
 #include "board.h"
 
 static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,13 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#include "fuse.h"
+#include <soc/tegra/fuse.h>
+
 #include "cpuidle.h"
 
 void __init tegra_cpuidle_init(void)
 {
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
 			tegra20_cpuidle_init();
@@ -49,7 +50,7 @@ void __init tegra_cpuidle_init(void)
 
 void tegra_cpuidle_pcie_irqs_in_use(void)
 {
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
 			tegra20_cpuidle_pcie_irqs_in_use();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra114.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra114.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra114.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra114.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,16 +14,16 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <asm/firmware.h>
+#include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <asm/firmware.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/cpuidle.h>
-#include <asm/suspend.h>
 #include <asm/smp_plat.h>
+#include <asm/suspend.h>
 
 #include "pm.h"
 #include "sleep.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra20.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra20.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra20.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,23 +19,23 @@
  * more details.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/clk/tegra.h>
+#include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <linux/clk/tegra.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
-#include <asm/suspend.h>
 #include <asm/smp_plat.h>
+#include <asm/suspend.h>
 
-#include "pm.h"
-#include "sleep.h"
+#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
-#include "flowctrl.h"
+#include "pm.h"
+#include "sleep.h"
 
 #ifdef CONFIG_PM_SLEEP
 static bool abort_flag;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra30.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra30.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/cpuidle-tegra30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/cpuidle-tegra30.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,17 +19,17 @@
  * more details.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/clk/tegra.h>
+#include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <linux/clk/tegra.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
-#include <asm/suspend.h>
 #include <asm/smp_plat.h>
+#include <asm/suspend.h>
 
 #include "pm.h"
 #include "sleep.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/flowctrl.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/flowctrl.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/flowctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/flowctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,14 +18,15 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/cpumask.h>
 #include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/io.h>
-#include <linux/cpumask.h>
+#include <linux/kernel.h>
+
+#include <soc/tegra/fuse.h>
 
 #include "flowctrl.h"
 #include "iomap.h"
-#include "fuse.h"
 
 static u8 flowctrl_offset_halt_cpu[] = {
 	FLOW_CTRL_HALT_CPU0_EVENTS,
@@ -76,7 +77,7 @@ void flowctrl_cpu_suspend_enter(unsigned
 	int i;
 
 	reg = flowctrl_read_cpu_csr(cpuid);
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
@@ -117,7 +118,7 @@ void flowctrl_cpu_suspend_exit(unsigned
 
 	/* Disable powergating via flow controller for CPU0 */
 	reg = flowctrl_read_cpu_csr(cpuid);
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/fuse.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/fuse.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/fuse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/fuse.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,252 +0,0 @@
-/*
- * arch/arm/mach-tegra/fuse.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/random.h>
-#include <linux/clk.h>
-#include <linux/tegra-soc.h>
-
-#include "fuse.h"
-#include "iomap.h"
-#include "apbio.h"
-
-/* Tegra20 only */
-#define FUSE_UID_LOW		0x108
-#define FUSE_UID_HIGH		0x10c
-
-/* Tegra30 and later */
-#define FUSE_VENDOR_CODE	0x200
-#define FUSE_FAB_CODE		0x204
-#define FUSE_LOT_CODE_0		0x208
-#define FUSE_LOT_CODE_1		0x20c
-#define FUSE_WAFER_ID		0x210
-#define FUSE_X_COORDINATE	0x214
-#define FUSE_Y_COORDINATE	0x218
-
-#define FUSE_SKU_INFO		0x110
-
-#define TEGRA20_FUSE_SPARE_BIT		0x200
-#define TEGRA30_FUSE_SPARE_BIT		0x244
-
-int tegra_sku_id;
-int tegra_cpu_process_id;
-int tegra_core_process_id;
-int tegra_chip_id;
-int tegra_cpu_speedo_id;		/* only exist in Tegra30 and later */
-int tegra_soc_speedo_id;
-enum tegra_revision tegra_revision;
-
-static struct clk *fuse_clk;
-static int tegra_fuse_spare_bit;
-static void (*tegra_init_speedo_data)(void);
-
-/* The BCT to use at boot is specified by board straps that can be read
- * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
- */
-int tegra_bct_strapping;
-
-#define STRAP_OPT 0x008
-#define GMI_AD0 (1 << 4)
-#define GMI_AD1 (1 << 5)
-#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
-#define RAM_CODE_SHIFT 4
-
-static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
-	[TEGRA_REVISION_UNKNOWN] = "unknown",
-	[TEGRA_REVISION_A01]     = "A01",
-	[TEGRA_REVISION_A02]     = "A02",
-	[TEGRA_REVISION_A03]     = "A03",
-	[TEGRA_REVISION_A03p]    = "A03 prime",
-	[TEGRA_REVISION_A04]     = "A04",
-};
-
-static void tegra_fuse_enable_clk(void)
-{
-	if (IS_ERR(fuse_clk))
-		fuse_clk = clk_get_sys(NULL, "fuse");
-	if (IS_ERR(fuse_clk))
-		return;
-	clk_prepare_enable(fuse_clk);
-}
-
-static void tegra_fuse_disable_clk(void)
-{
-	if (IS_ERR(fuse_clk))
-		return;
-	clk_disable_unprepare(fuse_clk);
-}
-
-u32 tegra_fuse_readl(unsigned long offset)
-{
-	return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
-}
-
-bool tegra_spare_fuse(int bit)
-{
-	bool ret;
-
-	tegra_fuse_enable_clk();
-
-	ret = tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
-
-	tegra_fuse_disable_clk();
-
-	return ret;
-}
-
-static enum tegra_revision tegra_get_revision(u32 id)
-{
-	u32 minor_rev = (id >> 16) & 0xf;
-
-	switch (minor_rev) {
-	case 1:
-		return TEGRA_REVISION_A01;
-	case 2:
-		return TEGRA_REVISION_A02;
-	case 3:
-		if (tegra_chip_id == TEGRA20 &&
-			(tegra_spare_fuse(18) || tegra_spare_fuse(19)))
-			return TEGRA_REVISION_A03p;
-		else
-			return TEGRA_REVISION_A03;
-	case 4:
-		return TEGRA_REVISION_A04;
-	default:
-		return TEGRA_REVISION_UNKNOWN;
-	}
-}
-
-static void tegra_get_process_id(void)
-{
-	u32 reg;
-
-	tegra_fuse_enable_clk();
-
-	reg = tegra_fuse_readl(tegra_fuse_spare_bit);
-	tegra_cpu_process_id = (reg >> 6) & 3;
-	reg = tegra_fuse_readl(tegra_fuse_spare_bit);
-	tegra_core_process_id = (reg >> 12) & 3;
-
-	tegra_fuse_disable_clk();
-}
-
-u32 tegra_read_chipid(void)
-{
-	return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
-}
-
-static void __init tegra20_fuse_init_randomness(void)
-{
-	u32 randomness[2];
-
-	randomness[0] = tegra_fuse_readl(FUSE_UID_LOW);
-	randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH);
-
-	add_device_randomness(randomness, sizeof(randomness));
-}
-
-/* Applies to Tegra30 or later */
-static void __init tegra30_fuse_init_randomness(void)
-{
-	u32 randomness[7];
-
-	randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE);
-	randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE);
-	randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0);
-	randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1);
-	randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID);
-	randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE);
-	randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE);
-
-	add_device_randomness(randomness, sizeof(randomness));
-}
-
-void __init tegra_init_fuse(void)
-{
-	u32 id;
-	u32 randomness[5];
-
-	u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
-	reg |= 1 << 28;
-	writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
-
-	/*
-	 * Enable FUSE clock. This needs to be hardcoded because the clock
-	 * subsystem is not active during early boot.
-	 */
-	reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
-	reg |= 1 << 7;
-	writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
-	fuse_clk = ERR_PTR(-EINVAL);
-
-	reg = tegra_fuse_readl(FUSE_SKU_INFO);
-	randomness[0] = reg;
-	tegra_sku_id = reg & 0xFF;
-
-	reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
-	randomness[1] = reg;
-	tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
-
-	id = tegra_read_chipid();
-	randomness[2] = id;
-	tegra_chip_id = (id >> 8) & 0xff;
-
-	switch (tegra_chip_id) {
-	case TEGRA20:
-		tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
-		tegra_init_speedo_data = &tegra20_init_speedo_data;
-		break;
-	case TEGRA30:
-		tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
-		tegra_init_speedo_data = &tegra30_init_speedo_data;
-		break;
-	case TEGRA114:
-		tegra_init_speedo_data = &tegra114_init_speedo_data;
-		break;
-	default:
-		pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
-		tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
-		tegra_init_speedo_data = &tegra_get_process_id;
-	}
-
-	tegra_revision = tegra_get_revision(id);
-	tegra_init_speedo_data();
-	randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id;
-	randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id;
-
-	add_device_randomness(randomness, sizeof(randomness));
-	switch (tegra_chip_id) {
-	case TEGRA20:
-		tegra20_fuse_init_randomness();
-		break;
-	case TEGRA30:
-	case TEGRA114:
-	default:
-		tegra30_fuse_init_randomness();
-		break;
-	}
-
-	pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
-		tegra_revision_name[tegra_revision],
-		tegra_sku_id, tegra_cpu_process_id,
-		tegra_core_process_id);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/fuse.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/fuse.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/fuse.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/fuse.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_FUSE_H
-#define __MACH_TEGRA_FUSE_H
-
-#define SKU_ID_T20	8
-#define SKU_ID_T25SE	20
-#define SKU_ID_AP25	23
-#define SKU_ID_T25	24
-#define SKU_ID_AP25E	27
-#define SKU_ID_T25E	28
-
-#define TEGRA20		0x20
-#define TEGRA30		0x30
-#define TEGRA114	0x35
-#define TEGRA124	0x40
-
-#ifndef __ASSEMBLY__
-enum tegra_revision {
-	TEGRA_REVISION_UNKNOWN = 0,
-	TEGRA_REVISION_A01,
-	TEGRA_REVISION_A02,
-	TEGRA_REVISION_A03,
-	TEGRA_REVISION_A03p,
-	TEGRA_REVISION_A04,
-	TEGRA_REVISION_MAX,
-};
-
-extern int tegra_sku_id;
-extern int tegra_cpu_process_id;
-extern int tegra_core_process_id;
-extern int tegra_chip_id;
-extern int tegra_cpu_speedo_id;		/* only exist in Tegra30 and later */
-extern int tegra_soc_speedo_id;
-extern enum tegra_revision tegra_revision;
-
-extern int tegra_bct_strapping;
-
-unsigned long long tegra_chip_uid(void);
-void tegra_init_fuse(void);
-bool tegra_spare_fuse(int bit);
-u32 tegra_fuse_readl(unsigned long offset);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void tegra20_init_speedo_data(void);
-#else
-static inline void tegra20_init_speedo_data(void) {}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-void tegra30_init_speedo_data(void);
-#else
-static inline void tegra30_init_speedo_data(void) {}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
-void tegra114_init_speedo_data(void);
-#else
-static inline void tegra114_init_speedo_data(void) {}
-#endif
-#endif /* __ASSEMBLY__ */
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/hotplug.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/hotplug.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/hotplug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/hotplug.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,13 +7,16 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include <linux/clk/tegra.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/clk/tegra.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
 
 #include <asm/smp_plat.h>
 
-#include "fuse.h"
 #include "sleep.h"
 
 static void (*tegra_hotplug_shutdown)(void);
@@ -36,6 +39,11 @@ int tegra_cpu_kill(unsigned cpu)
  */
 void __ref tegra_cpu_die(unsigned int cpu)
 {
+	if (!tegra_hotplug_shutdown) {
+		WARN(1, "hotplug is not yet initialized\n");
+		return;
+	}
+
 	/* Clean L1 data cache */
 	tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
 
@@ -46,17 +54,23 @@ void __ref tegra_cpu_die(unsigned int cp
 	BUG();
 }
 
-void __init tegra_hotplug_init(void)
+static int __init tegra_hotplug_init(void)
 {
 	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
-		return;
+		return 0;
 
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+	if (!soc_is_tegra())
+		return 0;
+
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
 		tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
 		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
 		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
 		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+
+	return 0;
 }
+pure_initcall(tegra_hotplug_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/io.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/io.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/io.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,14 +18,14 @@
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
-#include <linux/mm.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 
-#include <asm/page.h>
 #include <asm/mach/map.h>
+#include <asm/page.h>
 
 #include "board.h"
 #include "iomap.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/irq.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/irq.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,14 +17,14 @@
  *
  */
 
-#include <linux/kernel.h>
 #include <linux/cpu_pm.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
 #include <linux/syscore_ops.h>
 
 #include "board.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/Makefile linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/Makefile
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,24 +2,18 @@ asflags-y				+= -march=armv7-a
 
 obj-y                                   += io.o
 obj-y                                   += irq.o
-obj-y					+= fuse.o
-obj-y					+= pmc.o
 obj-y					+= flowctrl.o
-obj-y					+= powergate.o
-obj-y					+= apbio.o
 obj-y					+= pm.o
 obj-y					+= reset.o
 obj-y					+= reset-handler.o
 obj-y					+= sleep.o
 obj-y					+= tegra.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
 endif
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= pm-tegra30.o
 ifeq ($(CONFIG_CPU_IDLE),y)
@@ -28,7 +22,6 @@ endif
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 
-obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= tegra114_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= sleep-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= pm-tegra30.o
 ifeq ($(CONFIG_CPU_IDLE),y)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/platsmp.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/platsmp.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/platsmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/platsmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,27 +11,28 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/init.h>
-#include <linux/errno.h>
+
+#include <linux/clk/tegra.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/clk/tegra.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
 
 #include <asm/cacheflush.h>
 #include <asm/mach-types.h>
-#include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
-
-#include "fuse.h"
-#include "flowctrl.h"
-#include "reset.h"
-#include "pmc.h"
+#include <asm/smp_scu.h>
 
 #include "common.h"
+#include "flowctrl.h"
 #include "iomap.h"
+#include "reset.h"
 
 static cpumask_t tegra_cpu_init_mask;
 
@@ -170,13 +171,13 @@ static int tegra114_boot_secondary(unsig
 static int tegra_boot_secondary(unsigned int cpu,
 					  struct task_struct *idle)
 {
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
 		return tegra20_boot_secondary(cpu, idle);
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
 		return tegra30_boot_secondary(cpu, idle);
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
 		return tegra114_boot_secondary(cpu, idle);
-	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
 		return tegra114_boot_secondary(cpu, idle);
 
 	return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,30 +16,32 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
+#include <linux/clk/tegra.h>
 #include <linux/cpumask.h>
-#include <linux/delay.h>
 #include <linux/cpu_pm.h>
-#include <linux/suspend.h>
+#include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/clk/tegra.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pm.h>
+#include <soc/tegra/pmc.h>
 
-#include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
-#include <asm/suspend.h>
 #include <asm/idmap.h>
 #include <asm/proc-fns.h>
+#include <asm/smp_plat.h>
+#include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-#include "iomap.h"
-#include "reset.h"
 #include "flowctrl.h"
-#include "fuse.h"
+#include "iomap.h"
 #include "pm.h"
-#include "pmc.h"
+#include "reset.h"
 #include "sleep.h"
 
 #ifdef CONFIG_PM_SLEEP
@@ -53,7 +55,7 @@ static int (*tegra_sleep_func)(unsigned
 
 static void tegra_tear_down_cpu_init(void)
 {
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
 			tegra_tear_down_cpu = tegra20_tear_down_cpu;
@@ -143,7 +145,7 @@ bool tegra_set_cpu_in_lp2(void)
 
 	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
 		last_cpu = true;
-	else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1)
+	else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
 		tegra20_cpu_set_resettable_soon();
 
 	spin_unlock(&tegra_lp2_lock);
@@ -166,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long
 	return 0;
 }
 
+static void tegra_pm_set(enum tegra_suspend_mode mode)
+{
+	u32 value;
+
+	switch (tegra_get_chip_id()) {
+	case TEGRA20:
+	case TEGRA30:
+		break;
+	default:
+		/* Turn off CRAIL */
+		value = flowctrl_read_cpu_csr(0);
+		value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
+		value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+		flowctrl_write_cpu_csr(0, value);
+		break;
+	}
+
+	tegra_pmc_enter_suspend_mode(mode);
+}
+
 void tegra_idle_lp2_last(void)
 {
-	tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
+	tegra_pm_set(TEGRA_SUSPEND_LP2);
 
 	cpu_cluster_pm_enter();
 	suspend_cpu_complex();
@@ -212,7 +234,7 @@ static int tegra_sleep_core(unsigned lon
  */
 static bool tegra_lp1_iram_hook(void)
 {
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
 			tegra20_lp1_iram_hook();
@@ -242,7 +264,7 @@ static bool tegra_lp1_iram_hook(void)
 
 static bool tegra_sleep_core_init(void)
 {
-	switch (tegra_chip_id) {
+	switch (tegra_get_chip_id()) {
 	case TEGRA20:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
 			tegra20_sleep_core_init();
@@ -267,8 +289,6 @@ static bool tegra_sleep_core_init(void)
 
 static void tegra_suspend_enter_lp1(void)
 {
-	tegra_pmc_suspend();
-
 	/* copy the reset vector & SDRAM shutdown code into IRAM */
 	memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
 		iram_save_size);
@@ -280,8 +300,6 @@ static void tegra_suspend_enter_lp1(void
 
 static void tegra_suspend_exit_lp1(void)
 {
-	tegra_pmc_resume();
-
 	/* restore IRAM */
 	memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
 		iram_save_size);
@@ -306,7 +324,7 @@ static int tegra_suspend_enter(suspend_s
 
 	pr_info("Entering suspend state %s\n", lp_state[mode]);
 
-	tegra_pmc_pm_set(mode);
+	tegra_pm_set(mode);
 
 	local_fiq_disable();
 
@@ -354,7 +372,6 @@ void __init tegra_init_suspend(void)
 		return;
 
 	tegra_tear_down_cpu_init();
-	tegra_pmc_suspend_init();
 
 	if (mode >= TEGRA_SUSPEND_LP1) {
 		if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pmc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pmc.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pmc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,413 +0,0 @@
-/*
- * Copyright (C) 2012,2013 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.
- *
- * 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/clk.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/tegra-powergate.h>
-
-#include "flowctrl.h"
-#include "fuse.h"
-#include "pm.h"
-#include "pmc.h"
-#include "sleep.h"
-
-#define TEGRA_POWER_SYSCLK_POLARITY	(1 << 10)  /* sys clk polarity */
-#define TEGRA_POWER_SYSCLK_OE		(1 << 11)  /* system clock enable */
-#define TEGRA_POWER_EFFECT_LP0		(1 << 14)  /* LP0 when CPU pwr gated */
-#define TEGRA_POWER_CPU_PWRREQ_POLARITY	(1 << 15)  /* CPU pwr req polarity */
-#define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
-
-#define PMC_CTRL			0x0
-#define PMC_CTRL_INTR_LOW		(1 << 17)
-#define PMC_PWRGATE_TOGGLE		0x30
-#define PMC_PWRGATE_TOGGLE_START	(1 << 8)
-#define PMC_REMOVE_CLAMPING		0x34
-#define PMC_PWRGATE_STATUS		0x38
-
-#define PMC_SCRATCH0			0x50
-#define PMC_SCRATCH0_MODE_RECOVERY	(1 << 31)
-#define PMC_SCRATCH0_MODE_BOOTLOADER	(1 << 30)
-#define PMC_SCRATCH0_MODE_RCM		(1 << 1)
-#define PMC_SCRATCH0_MODE_MASK		(PMC_SCRATCH0_MODE_RECOVERY | \
-					 PMC_SCRATCH0_MODE_BOOTLOADER | \
-					 PMC_SCRATCH0_MODE_RCM)
-
-#define PMC_CPUPWRGOOD_TIMER	0xc8
-#define PMC_CPUPWROFF_TIMER	0xcc
-
-static u8 tegra_cpu_domains[] = {
-	0xFF,			/* not available for CPU0 */
-	TEGRA_POWERGATE_CPU1,
-	TEGRA_POWERGATE_CPU2,
-	TEGRA_POWERGATE_CPU3,
-};
-static DEFINE_SPINLOCK(tegra_powergate_lock);
-
-static void __iomem *tegra_pmc_base;
-static bool tegra_pmc_invert_interrupt;
-static struct clk *tegra_pclk;
-
-struct pmc_pm_data {
-	u32 cpu_good_time;	/* CPU power good time in uS */
-	u32 cpu_off_time;	/* CPU power off time in uS */
-	u32 core_osc_time;	/* Core power good osc time in uS */
-	u32 core_pmu_time;	/* Core power good pmu time in uS */
-	u32 core_off_time;	/* Core power off time in uS */
-	bool corereq_high;	/* Core power request active-high */
-	bool sysclkreq_high;	/* System clock request active-high */
-	bool combined_req;	/* Combined pwr req for CPU & Core */
-	bool cpu_pwr_good_en;	/* CPU power good signal is enabled */
-	u32 lp0_vec_phy_addr;	/* The phy addr of LP0 warm boot code */
-	u32 lp0_vec_size;	/* The size of LP0 warm boot code */
-	enum tegra_suspend_mode suspend_mode;
-};
-static struct pmc_pm_data pmc_pm_data;
-
-static inline u32 tegra_pmc_readl(u32 reg)
-{
-	return readl(tegra_pmc_base + reg);
-}
-
-static inline void tegra_pmc_writel(u32 val, u32 reg)
-{
-	writel(val, tegra_pmc_base + reg);
-}
-
-static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
-{
-	if (cpuid <= 0 || cpuid >= num_possible_cpus())
-		return -EINVAL;
-	return tegra_cpu_domains[cpuid];
-}
-
-static bool tegra_pmc_powergate_is_powered(int id)
-{
-	return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
-}
-
-static int tegra_pmc_powergate_set(int id, bool new_state)
-{
-	bool old_state;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tegra_powergate_lock, flags);
-
-	old_state = tegra_pmc_powergate_is_powered(id);
-	WARN_ON(old_state == new_state);
-
-	tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
-
-	spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-
-	return 0;
-}
-
-static int tegra_pmc_powergate_remove_clamping(int id)
-{
-	u32 mask;
-
-	/*
-	 * Tegra has a bug where PCIE and VDE clamping masks are
-	 * swapped relatively to the partition ids.
-	 */
-	if (id ==  TEGRA_POWERGATE_VDEC)
-		mask = (1 << TEGRA_POWERGATE_PCIE);
-	else if	(id == TEGRA_POWERGATE_PCIE)
-		mask = (1 << TEGRA_POWERGATE_VDEC);
-	else
-		mask = (1 << id);
-
-	tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
-
-	return 0;
-}
-
-bool tegra_pmc_cpu_is_powered(int cpuid)
-{
-	int id;
-
-	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
-	if (id < 0)
-		return false;
-	return tegra_pmc_powergate_is_powered(id);
-}
-
-int tegra_pmc_cpu_power_on(int cpuid)
-{
-	int id;
-
-	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
-	if (id < 0)
-		return id;
-	return tegra_pmc_powergate_set(id, true);
-}
-
-int tegra_pmc_cpu_remove_clamping(int cpuid)
-{
-	int id;
-
-	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
-	if (id < 0)
-		return id;
-	return tegra_pmc_powergate_remove_clamping(id);
-}
-
-void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
-{
-	u32 val;
-
-	val = tegra_pmc_readl(PMC_SCRATCH0);
-	val &= ~PMC_SCRATCH0_MODE_MASK;
-
-	if (cmd) {
-		if (strcmp(cmd, "recovery") == 0)
-			val |= PMC_SCRATCH0_MODE_RECOVERY;
-
-		if (strcmp(cmd, "bootloader") == 0)
-			val |= PMC_SCRATCH0_MODE_BOOTLOADER;
-
-		if (strcmp(cmd, "forced-recovery") == 0)
-			val |= PMC_SCRATCH0_MODE_RCM;
-	}
-
-	tegra_pmc_writel(val, PMC_SCRATCH0);
-
-	val = tegra_pmc_readl(0);
-	val |= 0x10;
-	tegra_pmc_writel(val, 0);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
-{
-	unsigned long long ticks;
-	unsigned long long pclk;
-	static unsigned long tegra_last_pclk;
-
-	if (WARN_ON_ONCE(rate <= 0))
-		pclk = 100000000;
-	else
-		pclk = rate;
-
-	if ((rate != tegra_last_pclk)) {
-		ticks = (us_on * pclk) + 999999ull;
-		do_div(ticks, 1000000);
-		tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
-
-		ticks = (us_off * pclk) + 999999ull;
-		do_div(ticks, 1000000);
-		tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
-		wmb();
-	}
-	tegra_last_pclk = pclk;
-}
-
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
-{
-	return pmc_pm_data.suspend_mode;
-}
-
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
-{
-	if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
-		return;
-
-	pmc_pm_data.suspend_mode = mode;
-}
-
-void tegra_pmc_suspend(void)
-{
-	tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
-}
-
-void tegra_pmc_resume(void)
-{
-	tegra_pmc_writel(0x0, PMC_SCRATCH41);
-}
-
-void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
-{
-	u32 reg, csr_reg;
-	unsigned long rate = 0;
-
-	reg = tegra_pmc_readl(PMC_CTRL);
-	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
-	reg &= ~TEGRA_POWER_EFFECT_LP0;
-
-	switch (tegra_chip_id) {
-	case TEGRA20:
-	case TEGRA30:
-		break;
-	default:
-		/* Turn off CRAIL */
-		csr_reg = flowctrl_read_cpu_csr(0);
-		csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
-		csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
-		flowctrl_write_cpu_csr(0, csr_reg);
-		break;
-	}
-
-	switch (mode) {
-	case TEGRA_SUSPEND_LP1:
-		rate = 32768;
-		break;
-	case TEGRA_SUSPEND_LP2:
-		rate = clk_get_rate(tegra_pclk);
-		break;
-	default:
-		break;
-	}
-
-	set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
-			 rate);
-
-	tegra_pmc_writel(reg, PMC_CTRL);
-}
-
-void tegra_pmc_suspend_init(void)
-{
-	u32 reg;
-
-	/* Always enable CPU power request */
-	reg = tegra_pmc_readl(PMC_CTRL);
-	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
-	tegra_pmc_writel(reg, PMC_CTRL);
-
-	reg = tegra_pmc_readl(PMC_CTRL);
-
-	if (!pmc_pm_data.sysclkreq_high)
-		reg |= TEGRA_POWER_SYSCLK_POLARITY;
-	else
-		reg &= ~TEGRA_POWER_SYSCLK_POLARITY;
-
-	/* configure the output polarity while the request is tristated */
-	tegra_pmc_writel(reg, PMC_CTRL);
-
-	/* now enable the request */
-	reg |= TEGRA_POWER_SYSCLK_OE;
-	tegra_pmc_writel(reg, PMC_CTRL);
-}
-#endif
-
-static const struct of_device_id matches[] __initconst = {
-	{ .compatible = "nvidia,tegra124-pmc" },
-	{ .compatible = "nvidia,tegra114-pmc" },
-	{ .compatible = "nvidia,tegra30-pmc" },
-	{ .compatible = "nvidia,tegra20-pmc" },
-	{ }
-};
-
-void __init tegra_pmc_init_irq(void)
-{
-	struct device_node *np;
-	u32 val;
-
-	np = of_find_matching_node(NULL, matches);
-	BUG_ON(!np);
-
-	tegra_pmc_base = of_iomap(np, 0);
-
-	tegra_pmc_invert_interrupt = of_property_read_bool(np,
-				     "nvidia,invert-interrupt");
-
-	val = tegra_pmc_readl(PMC_CTRL);
-	if (tegra_pmc_invert_interrupt)
-		val |= PMC_CTRL_INTR_LOW;
-	else
-		val &= ~PMC_CTRL_INTR_LOW;
-	tegra_pmc_writel(val, PMC_CTRL);
-}
-
-void __init tegra_pmc_init(void)
-{
-	struct device_node *np;
-	u32 prop;
-	enum tegra_suspend_mode suspend_mode;
-	u32 core_good_time[2] = {0, 0};
-	u32 lp0_vec[2] = {0, 0};
-
-	np = of_find_matching_node(NULL, matches);
-	BUG_ON(!np);
-
-	tegra_pclk = of_clk_get_by_name(np, "pclk");
-	WARN_ON(IS_ERR(tegra_pclk));
-
-	/* Grabbing the power management configurations */
-	if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
-		suspend_mode = TEGRA_SUSPEND_NONE;
-	} else {
-		switch (prop) {
-		case 0:
-			suspend_mode = TEGRA_SUSPEND_LP0;
-			break;
-		case 1:
-			suspend_mode = TEGRA_SUSPEND_LP1;
-			break;
-		case 2:
-			suspend_mode = TEGRA_SUSPEND_LP2;
-			break;
-		default:
-			suspend_mode = TEGRA_SUSPEND_NONE;
-			break;
-		}
-	}
-	suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
-
-	if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
-		suspend_mode = TEGRA_SUSPEND_NONE;
-	pmc_pm_data.cpu_good_time = prop;
-
-	if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
-		suspend_mode = TEGRA_SUSPEND_NONE;
-	pmc_pm_data.cpu_off_time = prop;
-
-	if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
-			core_good_time, ARRAY_SIZE(core_good_time)))
-		suspend_mode = TEGRA_SUSPEND_NONE;
-	pmc_pm_data.core_osc_time = core_good_time[0];
-	pmc_pm_data.core_pmu_time = core_good_time[1];
-
-	if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
-				 &prop))
-		suspend_mode = TEGRA_SUSPEND_NONE;
-	pmc_pm_data.core_off_time = prop;
-
-	pmc_pm_data.corereq_high = of_property_read_bool(np,
-				"nvidia,core-power-req-active-high");
-
-	pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
-				"nvidia,sys-clock-req-active-high");
-
-	pmc_pm_data.combined_req = of_property_read_bool(np,
-				"nvidia,combined-power-req");
-
-	pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
-				"nvidia,cpu-pwr-good-en");
-
-	if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
-				       ARRAY_SIZE(lp0_vec)))
-		if (suspend_mode == TEGRA_SUSPEND_LP0)
-			suspend_mode = TEGRA_SUSPEND_LP1;
-
-	pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
-	pmc_pm_data.lp0_vec_size = lp0_vec[1];
-
-	pmc_pm_data.suspend_mode = suspend_mode;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pmc.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pmc.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pmc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __MACH_TEGRA_PMC_H
-#define __MACH_TEGRA_PMC_H
-
-#include <linux/reboot.h>
-
-enum tegra_suspend_mode {
-	TEGRA_SUSPEND_NONE = 0,
-	TEGRA_SUSPEND_LP2,	/* CPU voltage off */
-	TEGRA_SUSPEND_LP1,	/* CPU voltage off, DRAM self-refresh */
-	TEGRA_SUSPEND_LP0,      /* CPU + core voltage off, DRAM self-refresh */
-	TEGRA_MAX_SUSPEND_MODE,
-};
-
-#ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
-void tegra_pmc_suspend(void);
-void tegra_pmc_resume(void);
-void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
-void tegra_pmc_suspend_init(void);
-#endif
-
-bool tegra_pmc_cpu_is_powered(int cpuid);
-int tegra_pmc_cpu_power_on(int cpuid);
-int tegra_pmc_cpu_remove_clamping(int cpuid);
-
-void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
-
-void tegra_pmc_init_irq(void);
-void tegra_pmc_init(void);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pm.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,12 +21,11 @@
 #ifndef _MACH_TEGRA_PM_H_
 #define _MACH_TEGRA_PM_H_
 
-#include "pmc.h"
-
 struct tegra_lp1_iram {
 	void	*start_addr;
 	void	*end_addr;
 };
+
 extern struct tegra_lp1_iram tegra_lp1_iram;
 extern void (*tegra_sleep_core_finish)(unsigned long v2p);
 
@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
 #ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
-				enum tegra_suspend_mode mode);
 void tegra_init_suspend(void);
 #else
-static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
-				enum tegra_suspend_mode mode)
-{
-	return TEGRA_SUSPEND_NONE;
-}
 static inline void tegra_init_suspend(void) {}
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pm-tegra20.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm-tegra20.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pm-tegra20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm-tegra20.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
  * 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 "pm.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/pm-tegra30.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm-tegra30.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/pm-tegra30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/pm-tegra30.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
  * 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 "pm.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/powergate.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/powergate.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/powergate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/powergate.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,515 +0,0 @@
-/*
- * drivers/powergate/tegra-powergate.c
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/reset.h>
-#include <linux/seq_file.h>
-#include <linux/spinlock.h>
-#include <linux/clk/tegra.h>
-#include <linux/tegra-powergate.h>
-
-#include "fuse.h"
-#include "iomap.h"
-
-#define DPD_SAMPLE		0x020
-#define  DPD_SAMPLE_ENABLE	(1 << 0)
-#define  DPD_SAMPLE_DISABLE	(0 << 0)
-
-#define PWRGATE_TOGGLE		0x30
-#define  PWRGATE_TOGGLE_START	(1 << 8)
-
-#define REMOVE_CLAMPING		0x34
-
-#define PWRGATE_STATUS		0x38
-
-#define IO_DPD_REQ		0x1b8
-#define  IO_DPD_REQ_CODE_IDLE	(0 << 30)
-#define  IO_DPD_REQ_CODE_OFF	(1 << 30)
-#define  IO_DPD_REQ_CODE_ON	(2 << 30)
-#define  IO_DPD_REQ_CODE_MASK	(3 << 30)
-
-#define IO_DPD_STATUS		0x1bc
-#define IO_DPD2_REQ		0x1c0
-#define IO_DPD2_STATUS		0x1c4
-#define SEL_DPD_TIM		0x1c8
-
-#define GPU_RG_CNTRL		0x2d4
-
-static int tegra_num_powerdomains;
-static int tegra_num_cpu_domains;
-static const u8 *tegra_cpu_domains;
-
-static const u8 tegra30_cpu_domains[] = {
-	TEGRA_POWERGATE_CPU,
-	TEGRA_POWERGATE_CPU1,
-	TEGRA_POWERGATE_CPU2,
-	TEGRA_POWERGATE_CPU3,
-};
-
-static const u8 tegra114_cpu_domains[] = {
-	TEGRA_POWERGATE_CPU0,
-	TEGRA_POWERGATE_CPU1,
-	TEGRA_POWERGATE_CPU2,
-	TEGRA_POWERGATE_CPU3,
-};
-
-static const u8 tegra124_cpu_domains[] = {
-	TEGRA_POWERGATE_CPU0,
-	TEGRA_POWERGATE_CPU1,
-	TEGRA_POWERGATE_CPU2,
-	TEGRA_POWERGATE_CPU3,
-};
-
-static DEFINE_SPINLOCK(tegra_powergate_lock);
-
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-
-static u32 pmc_read(unsigned long reg)
-{
-	return readl(pmc + reg);
-}
-
-static void pmc_write(u32 val, unsigned long reg)
-{
-	writel(val, pmc + reg);
-}
-
-static int tegra_powergate_set(int id, bool new_state)
-{
-	bool status;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tegra_powergate_lock, flags);
-
-	status = pmc_read(PWRGATE_STATUS) & (1 << id);
-
-	if (status == new_state) {
-		spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-		return 0;
-	}
-
-	pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
-
-	spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-
-	return 0;
-}
-
-int tegra_powergate_power_on(int id)
-{
-	if (id < 0 || id >= tegra_num_powerdomains)
-		return -EINVAL;
-
-	return tegra_powergate_set(id, true);
-}
-
-int tegra_powergate_power_off(int id)
-{
-	if (id < 0 || id >= tegra_num_powerdomains)
-		return -EINVAL;
-
-	return tegra_powergate_set(id, false);
-}
-EXPORT_SYMBOL(tegra_powergate_power_off);
-
-int tegra_powergate_is_powered(int id)
-{
-	u32 status;
-
-	if (id < 0 || id >= tegra_num_powerdomains)
-		return -EINVAL;
-
-	status = pmc_read(PWRGATE_STATUS) & (1 << id);
-	return !!status;
-}
-
-int tegra_powergate_remove_clamping(int id)
-{
-	u32 mask;
-
-	if (id < 0 || id >= tegra_num_powerdomains)
-		return -EINVAL;
-
-	/*
-	 * The Tegra124 GPU has a separate register (with different semantics)
-	 * to remove clamps.
-	 */
-	if (tegra_chip_id == TEGRA124) {
-		if (id == TEGRA_POWERGATE_3D) {
-			pmc_write(0, GPU_RG_CNTRL);
-			return 0;
-		}
-	}
-
-	/*
-	 * Tegra 2 has a bug where PCIE and VDE clamping masks are
-	 * swapped relatively to the partition ids
-	 */
-	if (id == TEGRA_POWERGATE_VDEC)
-		mask = (1 << TEGRA_POWERGATE_PCIE);
-	else if (id == TEGRA_POWERGATE_PCIE)
-		mask = (1 << TEGRA_POWERGATE_VDEC);
-	else
-		mask = (1 << id);
-
-	pmc_write(mask, REMOVE_CLAMPING);
-
-	return 0;
-}
-EXPORT_SYMBOL(tegra_powergate_remove_clamping);
-
-/* Must be called with clk disabled, and returns with clk enabled */
-int tegra_powergate_sequence_power_up(int id, struct clk *clk,
-					struct reset_control *rst)
-{
-	int ret;
-
-	reset_control_assert(rst);
-
-	ret = tegra_powergate_power_on(id);
-	if (ret)
-		goto err_power;
-
-	ret = clk_prepare_enable(clk);
-	if (ret)
-		goto err_clk;
-
-	udelay(10);
-
-	ret = tegra_powergate_remove_clamping(id);
-	if (ret)
-		goto err_clamp;
-
-	udelay(10);
-	reset_control_deassert(rst);
-
-	return 0;
-
-err_clamp:
-	clk_disable_unprepare(clk);
-err_clk:
-	tegra_powergate_power_off(id);
-err_power:
-	return ret;
-}
-EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
-
-int tegra_cpu_powergate_id(int cpuid)
-{
-	if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
-		return tegra_cpu_domains[cpuid];
-
-	return -EINVAL;
-}
-
-int __init tegra_powergate_init(void)
-{
-	switch (tegra_chip_id) {
-	case TEGRA20:
-		tegra_num_powerdomains = 7;
-		break;
-	case TEGRA30:
-		tegra_num_powerdomains = 14;
-		tegra_num_cpu_domains = 4;
-		tegra_cpu_domains = tegra30_cpu_domains;
-		break;
-	case TEGRA114:
-		tegra_num_powerdomains = 23;
-		tegra_num_cpu_domains = 4;
-		tegra_cpu_domains = tegra114_cpu_domains;
-		break;
-	case TEGRA124:
-		tegra_num_powerdomains = 25;
-		tegra_num_cpu_domains = 4;
-		tegra_cpu_domains = tegra124_cpu_domains;
-		break;
-	default:
-		/* Unknown Tegra variant. Disable powergating */
-		tegra_num_powerdomains = 0;
-		break;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static const char * const *powergate_name;
-
-static const char * const powergate_name_t20[] = {
-	[TEGRA_POWERGATE_CPU]	= "cpu",
-	[TEGRA_POWERGATE_3D]	= "3d",
-	[TEGRA_POWERGATE_VENC]	= "venc",
-	[TEGRA_POWERGATE_VDEC]	= "vdec",
-	[TEGRA_POWERGATE_PCIE]	= "pcie",
-	[TEGRA_POWERGATE_L2]	= "l2",
-	[TEGRA_POWERGATE_MPE]	= "mpe",
-};
-
-static const char * const powergate_name_t30[] = {
-	[TEGRA_POWERGATE_CPU]	= "cpu0",
-	[TEGRA_POWERGATE_3D]	= "3d0",
-	[TEGRA_POWERGATE_VENC]	= "venc",
-	[TEGRA_POWERGATE_VDEC]	= "vdec",
-	[TEGRA_POWERGATE_PCIE]	= "pcie",
-	[TEGRA_POWERGATE_L2]	= "l2",
-	[TEGRA_POWERGATE_MPE]	= "mpe",
-	[TEGRA_POWERGATE_HEG]	= "heg",
-	[TEGRA_POWERGATE_SATA]	= "sata",
-	[TEGRA_POWERGATE_CPU1]	= "cpu1",
-	[TEGRA_POWERGATE_CPU2]	= "cpu2",
-	[TEGRA_POWERGATE_CPU3]	= "cpu3",
-	[TEGRA_POWERGATE_CELP]	= "celp",
-	[TEGRA_POWERGATE_3D1]	= "3d1",
-};
-
-static const char * const powergate_name_t114[] = {
-	[TEGRA_POWERGATE_CPU]	= "crail",
-	[TEGRA_POWERGATE_3D]	= "3d",
-	[TEGRA_POWERGATE_VENC]	= "venc",
-	[TEGRA_POWERGATE_VDEC]	= "vdec",
-	[TEGRA_POWERGATE_MPE]	= "mpe",
-	[TEGRA_POWERGATE_HEG]	= "heg",
-	[TEGRA_POWERGATE_CPU1]	= "cpu1",
-	[TEGRA_POWERGATE_CPU2]	= "cpu2",
-	[TEGRA_POWERGATE_CPU3]	= "cpu3",
-	[TEGRA_POWERGATE_CELP]	= "celp",
-	[TEGRA_POWERGATE_CPU0]	= "cpu0",
-	[TEGRA_POWERGATE_C0NC]	= "c0nc",
-	[TEGRA_POWERGATE_C1NC]	= "c1nc",
-	[TEGRA_POWERGATE_DIS]	= "dis",
-	[TEGRA_POWERGATE_DISB]	= "disb",
-	[TEGRA_POWERGATE_XUSBA]	= "xusba",
-	[TEGRA_POWERGATE_XUSBB]	= "xusbb",
-	[TEGRA_POWERGATE_XUSBC]	= "xusbc",
-};
-
-static const char * const powergate_name_t124[] = {
-	[TEGRA_POWERGATE_CPU]	= "crail",
-	[TEGRA_POWERGATE_3D]	= "3d",
-	[TEGRA_POWERGATE_VENC]	= "venc",
-	[TEGRA_POWERGATE_PCIE]	= "pcie",
-	[TEGRA_POWERGATE_VDEC]	= "vdec",
-	[TEGRA_POWERGATE_L2]	= "l2",
-	[TEGRA_POWERGATE_MPE]	= "mpe",
-	[TEGRA_POWERGATE_HEG]	= "heg",
-	[TEGRA_POWERGATE_SATA]	= "sata",
-	[TEGRA_POWERGATE_CPU1]	= "cpu1",
-	[TEGRA_POWERGATE_CPU2]	= "cpu2",
-	[TEGRA_POWERGATE_CPU3]	= "cpu3",
-	[TEGRA_POWERGATE_CELP]	= "celp",
-	[TEGRA_POWERGATE_CPU0]	= "cpu0",
-	[TEGRA_POWERGATE_C0NC]	= "c0nc",
-	[TEGRA_POWERGATE_C1NC]	= "c1nc",
-	[TEGRA_POWERGATE_SOR]	= "sor",
-	[TEGRA_POWERGATE_DIS]	= "dis",
-	[TEGRA_POWERGATE_DISB]	= "disb",
-	[TEGRA_POWERGATE_XUSBA]	= "xusba",
-	[TEGRA_POWERGATE_XUSBB]	= "xusbb",
-	[TEGRA_POWERGATE_XUSBC]	= "xusbc",
-	[TEGRA_POWERGATE_VIC]	= "vic",
-	[TEGRA_POWERGATE_IRAM]	= "iram",
-};
-
-static int powergate_show(struct seq_file *s, void *data)
-{
-	int i;
-
-	seq_printf(s, " powergate powered\n");
-	seq_printf(s, "------------------\n");
-
-	for (i = 0; i < tegra_num_powerdomains; i++) {
-		if (!powergate_name[i])
-			continue;
-
-		seq_printf(s, " %9s %7s\n", powergate_name[i],
-			tegra_powergate_is_powered(i) ? "yes" : "no");
-	}
-
-	return 0;
-}
-
-static int powergate_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, powergate_show, inode->i_private);
-}
-
-static const struct file_operations powergate_fops = {
-	.open		= powergate_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-int __init tegra_powergate_debugfs_init(void)
-{
-	struct dentry *d;
-
-	switch (tegra_chip_id) {
-	case TEGRA20:
-		powergate_name = powergate_name_t20;
-		break;
-	case TEGRA30:
-		powergate_name = powergate_name_t30;
-		break;
-	case TEGRA114:
-		powergate_name = powergate_name_t114;
-		break;
-	case TEGRA124:
-		powergate_name = powergate_name_t124;
-		break;
-	}
-
-	if (powergate_name) {
-		d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
-			&powergate_fops);
-		if (!d)
-			return -ENOMEM;
-	}
-
-	return 0;
-}
-
-#endif
-
-static int tegra_io_rail_prepare(int id, unsigned long *request,
-				 unsigned long *status, unsigned int *bit)
-{
-	unsigned long rate, value;
-	struct clk *clk;
-
-	*bit = id % 32;
-
-	/*
-	 * There are two sets of 30 bits to select IO rails, but bits 30 and
-	 * 31 are control bits rather than IO rail selection bits.
-	 */
-	if (id > 63 || *bit == 30 || *bit == 31)
-		return -EINVAL;
-
-	if (id < 32) {
-		*status = IO_DPD_STATUS;
-		*request = IO_DPD_REQ;
-	} else {
-		*status = IO_DPD2_STATUS;
-		*request = IO_DPD2_REQ;
-	}
-
-	clk = clk_get_sys(NULL, "pclk");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	rate = clk_get_rate(clk);
-	clk_put(clk);
-
-	pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-
-	/* must be at least 200 ns, in APB (PCLK) clock cycles */
-	value = DIV_ROUND_UP(1000000000, rate);
-	value = DIV_ROUND_UP(200, value);
-	pmc_write(value, SEL_DPD_TIM);
-
-	return 0;
-}
-
-static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
-			      unsigned long val, unsigned long timeout)
-{
-	unsigned long value;
-
-	timeout = jiffies + msecs_to_jiffies(timeout);
-
-	while (time_after(timeout, jiffies)) {
-		value = pmc_read(offset);
-		if ((value & mask) == val)
-			return 0;
-
-		usleep_range(250, 1000);
-	}
-
-	return -ETIMEDOUT;
-}
-
-static void tegra_io_rail_unprepare(void)
-{
-	pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
-}
-
-int tegra_io_rail_power_on(int id)
-{
-	unsigned long request, status, value;
-	unsigned int bit, mask;
-	int err;
-
-	err = tegra_io_rail_prepare(id, &request, &status, &bit);
-	if (err < 0)
-		return err;
-
-	mask = 1 << bit;
-
-	value = pmc_read(request);
-	value |= mask;
-	value &= ~IO_DPD_REQ_CODE_MASK;
-	value |= IO_DPD_REQ_CODE_OFF;
-	pmc_write(value, request);
-
-	err = tegra_io_rail_poll(status, mask, 0, 250);
-	if (err < 0)
-		return err;
-
-	tegra_io_rail_unprepare();
-
-	return 0;
-}
-EXPORT_SYMBOL(tegra_io_rail_power_on);
-
-int tegra_io_rail_power_off(int id)
-{
-	unsigned long request, status, value;
-	unsigned int bit, mask;
-	int err;
-
-	err = tegra_io_rail_prepare(id, &request, &status, &bit);
-	if (err < 0)
-		return err;
-
-	mask = 1 << bit;
-
-	value = pmc_read(request);
-	value |= mask;
-	value &= ~IO_DPD_REQ_CODE_MASK;
-	value |= IO_DPD_REQ_CODE_ON;
-	pmc_write(value, request);
-
-	err = tegra_io_rail_poll(status, mask, mask, 250);
-	if (err < 0)
-		return err;
-
-	tegra_io_rail_unprepare();
-
-	return 0;
-}
-EXPORT_SYMBOL(tegra_io_rail_power_off);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/reset.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/reset.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/reset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/reset.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,20 +14,21 @@
  *
  */
 
+#include <linux/bitops.h>
+#include <linux/cpumask.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/cpumask.h>
-#include <linux/bitops.h>
+
+#include <soc/tegra/fuse.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
 #include <asm/firmware.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include "iomap.h"
 #include "irammap.h"
 #include "reset.h"
 #include "sleep.h"
-#include "fuse.h"
 
 #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
 				TEGRA_IRAM_RESET_HANDLER_OFFSET)
@@ -53,12 +54,10 @@ static void __init tegra_cpu_reset_handl
 	 * Prevent further modifications to the physical reset vector.
 	 *  NOTE: Has no effect on chips prior to Tegra30.
 	 */
-	if (tegra_chip_id != TEGRA20) {
-		reg = readl(sb_ctrl);
-		reg |= 2;
-		writel(reg, sb_ctrl);
-		wmb();
-	}
+	reg = readl(sb_ctrl);
+	reg |= 2;
+	writel(reg, sb_ctrl);
+	wmb();
 }
 
 static void __init tegra_cpu_reset_handler_enable(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/reset-handler.S linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/reset-handler.S
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/reset-handler.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/reset-handler.S	2014-09-28 17:29:07.000000000 -0400
@@ -14,14 +14,15 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
+
+#include <soc/tegra/fuse.h>
 
-#include <asm/cache.h>
 #include <asm/asm-offsets.h>
+#include <asm/cache.h>
 
 #include "flowctrl.h"
-#include "fuse.h"
 #include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep.h linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep.h
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep.h	2014-09-28 17:29:07.000000000 -0400
@@ -130,9 +130,6 @@ void tegra_disable_clean_inv_dcache(u32
 #ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_shutdown(void);
 void tegra30_hotplug_shutdown(void);
-void tegra_hotplug_init(void);
-#else
-static inline void tegra_hotplug_init(void) {}
 #endif
 
 void tegra20_cpu_shutdown(int cpu);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep.S linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep.S
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep.S	2014-09-28 17:29:07.000000000 -0400
@@ -87,7 +87,7 @@ ENTRY(tegra_init_l2_for_a15)
 	mcrne	p15, 0x1, r0, c9, c0, 2
 _exit_init_l2_a15:
 
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra_init_l2_for_a15)
 
 /*
@@ -111,7 +111,7 @@ ENTRY(tegra_sleep_cpu_finish)
 	add	r3, r3, r0
 	mov	r0, r1
 
-	mov	pc, r3
+	ret	r3
 ENDPROC(tegra_sleep_cpu_finish)
 
 /*
@@ -139,7 +139,7 @@ ENTRY(tegra_shut_off_mmu)
 	moveq	r3, #0
 	streq	r3, [r2, #L2X0_CTRL]
 #endif
-	mov	pc, r0
+	ret	r0
 ENDPROC(tegra_shut_off_mmu)
 	.popsection
 
@@ -156,6 +156,6 @@ ENTRY(tegra_switch_cpu_to_pllp)
 	str	r0, [r5, #CLK_RESET_CCLK_BURST]
 	mov	r0, #0
 	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra_switch_cpu_to_pllp)
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep-tegra20.S linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep-tegra20.S
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep-tegra20.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep-tegra20.S	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,7 @@ ENTRY(tegra20_hotplug_shutdown)
 	/* Put this CPU down */
 	cpu_id	r0
 	bl	tegra20_cpu_shutdown
-	mov	pc, lr			@ should never get here
+	ret	lr			@ should never get here
 ENDPROC(tegra20_hotplug_shutdown)
 
 /*
@@ -96,7 +96,7 @@ ENDPROC(tegra20_hotplug_shutdown)
  */
 ENTRY(tegra20_cpu_shutdown)
 	cmp	r0, #0
-	moveq	pc, lr			@ must not be called for CPU 0
+	reteq	lr			@ must not be called for CPU 0
 	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
 	mov	r12, #CPU_RESETTABLE
 	str	r12, [r1]
@@ -117,7 +117,7 @@ ENTRY(tegra20_cpu_shutdown)
 	cpu_id	r3
 	cmp	r3, r0
 	beq	.
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra20_cpu_shutdown)
 #endif
 
@@ -164,7 +164,7 @@ ENTRY(tegra_pen_lock)
 	cmpeq	r12, r0			@ !turn == cpu?
 	beq	1b			@ while !turn == cpu && flag[!cpu] == 1
 
-	mov	pc, lr			@ locked
+	ret	lr			@ locked
 ENDPROC(tegra_pen_lock)
 
 ENTRY(tegra_pen_unlock)
@@ -176,7 +176,7 @@ ENTRY(tegra_pen_unlock)
 	addne	r2, r3, #PMC_SCRATCH39
 	mov	r12, #0
 	str	r12, [r2]
-	mov     pc, lr
+	ret     lr
 ENDPROC(tegra_pen_unlock)
 
 /*
@@ -189,7 +189,7 @@ ENTRY(tegra20_cpu_clear_resettable)
 	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
 	mov	r12, #CPU_NOT_RESETTABLE
 	str	r12, [r1]
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra20_cpu_clear_resettable)
 
 /*
@@ -202,7 +202,7 @@ ENTRY(tegra20_cpu_set_resettable_soon)
 	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
 	mov	r12, #CPU_RESETTABLE_SOON
 	str	r12, [r1]
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra20_cpu_set_resettable_soon)
 
 /*
@@ -217,7 +217,7 @@ ENTRY(tegra20_cpu_is_resettable_soon)
 	cmp	r12, #CPU_RESETTABLE_SOON
 	moveq	r0, #1
 	movne	r0, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(tegra20_cpu_is_resettable_soon)
 
 /*
@@ -239,7 +239,7 @@ ENTRY(tegra20_sleep_core_finish)
 	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
 	add	r0, r0, r1
 
-	mov	pc, r3
+	ret	r3
 ENDPROC(tegra20_sleep_core_finish)
 
 /*
@@ -402,7 +402,7 @@ exit_selfrefresh_loop:
 
 	mov32	r0, TEGRA_PMC_BASE
 	ldr	r0, [r0, #PMC_SCRATCH41]
-	mov	pc, r0			@ jump to tegra_resume
+	ret	r0			@ jump to tegra_resume
 ENDPROC(tegra20_lp1_reset)
 
 /*
@@ -455,7 +455,7 @@ tegra20_switch_cpu_to_clk32k:
 	mov	r0, #0	/* brust policy = 32KHz */
 	str	r0, [r5, #CLK_RESET_SCLK_BURST]
 
-	mov	pc, lr
+	ret	lr
 
 /*
  * tegra20_enter_sleep
@@ -535,7 +535,7 @@ padsave_done:
 	adr	r2, tegra20_sclk_save
 	str	r0, [r2]
 	dsb
-	mov	pc, lr
+	ret	lr
 
 tegra20_sdram_pad_address:
 	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep-tegra30.S linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep-tegra30.S
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/sleep-tegra30.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/sleep-tegra30.S	2014-09-28 17:29:07.000000000 -0400
@@ -16,14 +16,15 @@
 
 #include <linux/linkage.h>
 
-#include <asm/assembler.h>
+#include <soc/tegra/fuse.h>
+
 #include <asm/asm-offsets.h>
+#include <asm/assembler.h>
 #include <asm/cache.h>
 
+#include "flowctrl.h"
 #include "irammap.h"
-#include "fuse.h"
 #include "sleep.h"
-#include "flowctrl.h"
 
 #define EMC_CFG				0xc
 #define EMC_ADR_CFG			0x10
@@ -142,7 +143,7 @@ ENTRY(tegra30_hotplug_shutdown)
 	/* Powergate this CPU */
 	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
 	bl	tegra30_cpu_shutdown
-	mov	pc, lr			@ should never get here
+	ret	lr			@ should never get here
 ENDPROC(tegra30_hotplug_shutdown)
 
 /*
@@ -161,7 +162,7 @@ ENTRY(tegra30_cpu_shutdown)
 	bne	_no_cpu0_chk	@ It's not Tegra30
 
 	cmp	r3, #0
-	moveq	pc, lr		@ Must never be called for CPU 0
+	reteq	lr		@ Must never be called for CPU 0
 _no_cpu0_chk:
 
 	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
@@ -266,7 +267,7 @@ ENTRY(tegra30_sleep_core_finish)
 	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
 	add	r0, r0, r1
 
-	mov	pc, r3
+	ret	r3
 ENDPROC(tegra30_sleep_core_finish)
 
 /*
@@ -285,7 +286,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish
 	mov	r0, #0                          @ power mode flags (!hotplug)
 	bl	tegra30_cpu_shutdown
 	mov	r0, #1                          @ never return here
-	mov	pc, r7
+	ret	r7
 ENDPROC(tegra30_sleep_cpu_secondary_finish)
 
 /*
@@ -529,7 +530,7 @@ __no_dual_emc_chanl:
 
 	mov32	r0, TEGRA_PMC_BASE
 	ldr	r0, [r0, #PMC_SCRATCH41]
-	mov	pc, r0			@ jump to tegra_resume
+	ret	r0			@ jump to tegra_resume
 ENDPROC(tegra30_lp1_reset)
 
 	.align	L1_CACHE_SHIFT
@@ -659,7 +660,7 @@ _no_pll_in_iddq:
 	mov	r0, #0	/* brust policy = 32KHz */
 	str	r0, [r5, #CLK_RESET_SCLK_BURST]
 
-	mov	pc, lr
+	ret	lr
 
 /*
  * tegra30_enter_sleep
@@ -819,7 +820,7 @@ pmc_io_dpd_skip:
 
 	dsb
 
-	mov	pc, lr
+	ret	lr
 
 	.ltorg
 /* dummy symbol for end of IRAM */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra114_speedo.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra114_speedo.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra114_speedo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra114_speedo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- *
- * 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/bug.h>
-
-#include "fuse.h"
-
-#define CORE_PROCESS_CORNERS_NUM	2
-#define CPU_PROCESS_CORNERS_NUM		2
-
-enum {
-	THRESHOLD_INDEX_0,
-	THRESHOLD_INDEX_1,
-	THRESHOLD_INDEX_COUNT,
-};
-
-static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
-	{1123,     UINT_MAX},
-	{0,        UINT_MAX},
-};
-
-static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
-	{1695,     UINT_MAX},
-	{0,        UINT_MAX},
-};
-
-static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
-{
-	u32 tmp;
-
-	switch (sku) {
-	case 0x00:
-	case 0x10:
-	case 0x05:
-	case 0x06:
-		tegra_cpu_speedo_id = 1;
-		tegra_soc_speedo_id = 0;
-		*threshold = THRESHOLD_INDEX_0;
-		break;
-
-	case 0x03:
-	case 0x04:
-		tegra_cpu_speedo_id = 2;
-		tegra_soc_speedo_id = 1;
-		*threshold = THRESHOLD_INDEX_1;
-		break;
-
-	default:
-		pr_err("Tegra114 Unknown SKU %d\n", sku);
-		tegra_cpu_speedo_id = 0;
-		tegra_soc_speedo_id = 0;
-		*threshold = THRESHOLD_INDEX_0;
-		break;
-	}
-
-	if (rev == TEGRA_REVISION_A01) {
-		tmp = tegra_fuse_readl(0x270) << 1;
-		tmp |= tegra_fuse_readl(0x26c);
-		if (!tmp)
-			tegra_cpu_speedo_id = 0;
-	}
-}
-
-void tegra114_init_speedo_data(void)
-{
-	u32 cpu_speedo_val;
-	u32 core_speedo_val;
-	int threshold;
-	int i;
-
-	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
-			THRESHOLD_INDEX_COUNT);
-	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
-			THRESHOLD_INDEX_COUNT);
-
-	rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
-
-	cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
-	core_speedo_val = tegra_fuse_readl(0x134);
-
-	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
-		if (cpu_speedo_val < cpu_process_speedos[threshold][i])
-			break;
-	tegra_cpu_process_id = i;
-
-	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
-		if (core_speedo_val < core_process_speedos[threshold][i])
-			break;
-	tegra_core_process_id = i;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra20_speedo.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra20_speedo.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra20_speedo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra20_speedo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- * 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/bug.h>
-
-#include "fuse.h"
-
-#define CPU_SPEEDO_LSBIT		20
-#define CPU_SPEEDO_MSBIT		29
-#define CPU_SPEEDO_REDUND_LSBIT		30
-#define CPU_SPEEDO_REDUND_MSBIT		39
-#define CPU_SPEEDO_REDUND_OFFS	(CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
-
-#define CORE_SPEEDO_LSBIT		40
-#define CORE_SPEEDO_MSBIT		47
-#define CORE_SPEEDO_REDUND_LSBIT	48
-#define CORE_SPEEDO_REDUND_MSBIT	55
-#define CORE_SPEEDO_REDUND_OFFS	(CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
-
-#define SPEEDO_MULT			4
-
-#define PROCESS_CORNERS_NUM		4
-
-#define SPEEDO_ID_SELECT_0(rev)		((rev) <= 2)
-#define SPEEDO_ID_SELECT_1(sku)		\
-	(((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
-	 ((sku) != 27) && ((sku) != 28))
-
-enum {
-	SPEEDO_ID_0,
-	SPEEDO_ID_1,
-	SPEEDO_ID_2,
-	SPEEDO_ID_COUNT,
-};
-
-static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
-	{315, 366, 420, UINT_MAX},
-	{303, 368, 419, UINT_MAX},
-	{316, 331, 383, UINT_MAX},
-};
-
-static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
-	{165, 195, 224, UINT_MAX},
-	{165, 195, 224, UINT_MAX},
-	{165, 195, 224, UINT_MAX},
-};
-
-void tegra20_init_speedo_data(void)
-{
-	u32 reg;
-	u32 val;
-	int i;
-
-	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
-	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
-
-	if (SPEEDO_ID_SELECT_0(tegra_revision))
-		tegra_soc_speedo_id = SPEEDO_ID_0;
-	else if (SPEEDO_ID_SELECT_1(tegra_sku_id))
-		tegra_soc_speedo_id = SPEEDO_ID_1;
-	else
-		tegra_soc_speedo_id = SPEEDO_ID_2;
-
-	val = 0;
-	for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
-		reg = tegra_spare_fuse(i) |
-			tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
-		val = (val << 1) | (reg & 0x1);
-	}
-	val = val * SPEEDO_MULT;
-	pr_debug("%s CPU speedo value %u\n", __func__, val);
-
-	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
-		if (val <= cpu_process_speedos[tegra_soc_speedo_id][i])
-			break;
-	}
-	tegra_cpu_process_id = i;
-
-	val = 0;
-	for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
-		reg = tegra_spare_fuse(i) |
-			tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
-		val = (val << 1) | (reg & 0x1);
-	}
-	val = val * SPEEDO_MULT;
-	pr_debug("%s Core speedo value %u\n", __func__, val);
-
-	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
-		if (val <= core_process_speedos[tegra_soc_speedo_id][i])
-			break;
-	}
-	tegra_core_process_id = i;
-
-	pr_info("Tegra20 Soc Speedo ID %d", tegra_soc_speedo_id);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra30_speedo.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra30_speedo.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra30_speedo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra30_speedo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- * 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/bug.h>
-
-#include "fuse.h"
-
-#define CORE_PROCESS_CORNERS_NUM	1
-#define CPU_PROCESS_CORNERS_NUM		6
-
-#define FUSE_SPEEDO_CALIB_0	0x114
-#define FUSE_PACKAGE_INFO	0X1FC
-#define FUSE_TEST_PROG_VER	0X128
-
-#define G_SPEEDO_BIT_MINUS1	58
-#define G_SPEEDO_BIT_MINUS1_R	59
-#define G_SPEEDO_BIT_MINUS2	60
-#define G_SPEEDO_BIT_MINUS2_R	61
-#define LP_SPEEDO_BIT_MINUS1	62
-#define LP_SPEEDO_BIT_MINUS1_R	63
-#define LP_SPEEDO_BIT_MINUS2	64
-#define LP_SPEEDO_BIT_MINUS2_R	65
-
-enum {
-	THRESHOLD_INDEX_0,
-	THRESHOLD_INDEX_1,
-	THRESHOLD_INDEX_2,
-	THRESHOLD_INDEX_3,
-	THRESHOLD_INDEX_4,
-	THRESHOLD_INDEX_5,
-	THRESHOLD_INDEX_6,
-	THRESHOLD_INDEX_7,
-	THRESHOLD_INDEX_8,
-	THRESHOLD_INDEX_9,
-	THRESHOLD_INDEX_10,
-	THRESHOLD_INDEX_11,
-	THRESHOLD_INDEX_COUNT,
-};
-
-static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
-	{180},
-	{170},
-	{195},
-	{180},
-	{168},
-	{192},
-	{180},
-	{170},
-	{195},
-	{180},
-	{180},
-	{180},
-};
-
-static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
-	{306, 338, 360, 376, UINT_MAX},
-	{295, 336, 358, 375, UINT_MAX},
-	{325, 325, 358, 375, UINT_MAX},
-	{325, 325, 358, 375, UINT_MAX},
-	{292, 324, 348, 364, UINT_MAX},
-	{324, 324, 348, 364, UINT_MAX},
-	{324, 324, 348, 364, UINT_MAX},
-	{295, 336, 358, 375, UINT_MAX},
-	{358, 358, 358, 358, 397, UINT_MAX},
-	{364, 364, 364, 364, 397, UINT_MAX},
-	{295, 336, 358, 375, 391, UINT_MAX},
-	{295, 336, 358, 375, 391, UINT_MAX},
-};
-
-static int threshold_index;
-static int package_id;
-
-static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
-{
-	u32 reg;
-	int ate_ver;
-	int bit_minus1;
-	int bit_minus2;
-
-	reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
-
-	*speedo_lp = (reg & 0xFFFF) * 4;
-	*speedo_g = ((reg >> 16) & 0xFFFF) * 4;
-
-	ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
-	pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
-
-	if (ate_ver >= 26) {
-		bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
-		bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
-		bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
-		bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
-		*speedo_lp |= (bit_minus1 << 1) | bit_minus2;
-
-		bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
-		bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
-		bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
-		bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
-		*speedo_g |= (bit_minus1 << 1) | bit_minus2;
-	} else {
-		*speedo_lp |= 0x3;
-		*speedo_g |= 0x3;
-	}
-}
-
-static void rev_sku_to_speedo_ids(int rev, int sku)
-{
-	switch (rev) {
-	case TEGRA_REVISION_A01:
-		tegra_cpu_speedo_id = 0;
-		tegra_soc_speedo_id = 0;
-		threshold_index = THRESHOLD_INDEX_0;
-		break;
-	case TEGRA_REVISION_A02:
-	case TEGRA_REVISION_A03:
-		switch (sku) {
-		case 0x87:
-		case 0x82:
-			tegra_cpu_speedo_id = 1;
-			tegra_soc_speedo_id = 1;
-			threshold_index = THRESHOLD_INDEX_1;
-			break;
-		case 0x81:
-			switch (package_id) {
-			case 1:
-				tegra_cpu_speedo_id = 2;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_2;
-				break;
-			case 2:
-				tegra_cpu_speedo_id = 4;
-				tegra_soc_speedo_id = 1;
-				threshold_index = THRESHOLD_INDEX_7;
-				break;
-			default:
-				pr_err("Tegra30: Unknown pkg %d\n", package_id);
-				BUG();
-				break;
-			}
-			break;
-		case 0x80:
-			switch (package_id) {
-			case 1:
-				tegra_cpu_speedo_id = 5;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_8;
-				break;
-			case 2:
-				tegra_cpu_speedo_id = 6;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_9;
-				break;
-			default:
-				pr_err("Tegra30: Unknown pkg %d\n", package_id);
-				BUG();
-				break;
-			}
-			break;
-		case 0x83:
-			switch (package_id) {
-			case 1:
-				tegra_cpu_speedo_id = 7;
-				tegra_soc_speedo_id = 1;
-				threshold_index = THRESHOLD_INDEX_10;
-				break;
-			case 2:
-				tegra_cpu_speedo_id = 3;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_3;
-				break;
-			default:
-				pr_err("Tegra30: Unknown pkg %d\n", package_id);
-				BUG();
-				break;
-			}
-			break;
-		case 0x8F:
-			tegra_cpu_speedo_id = 8;
-			tegra_soc_speedo_id = 1;
-			threshold_index = THRESHOLD_INDEX_11;
-			break;
-		case 0x08:
-			tegra_cpu_speedo_id = 1;
-			tegra_soc_speedo_id = 1;
-			threshold_index = THRESHOLD_INDEX_4;
-			break;
-		case 0x02:
-			tegra_cpu_speedo_id = 2;
-			tegra_soc_speedo_id = 2;
-			threshold_index = THRESHOLD_INDEX_5;
-			break;
-		case 0x04:
-			tegra_cpu_speedo_id = 3;
-			tegra_soc_speedo_id = 2;
-			threshold_index = THRESHOLD_INDEX_6;
-			break;
-		case 0:
-			switch (package_id) {
-			case 1:
-				tegra_cpu_speedo_id = 2;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_2;
-				break;
-			case 2:
-				tegra_cpu_speedo_id = 3;
-				tegra_soc_speedo_id = 2;
-				threshold_index = THRESHOLD_INDEX_3;
-				break;
-			default:
-				pr_err("Tegra30: Unknown pkg %d\n", package_id);
-				BUG();
-				break;
-			}
-			break;
-		default:
-			pr_warn("Tegra30: Unknown SKU %d\n", sku);
-			tegra_cpu_speedo_id = 0;
-			tegra_soc_speedo_id = 0;
-			threshold_index = THRESHOLD_INDEX_0;
-			break;
-		}
-		break;
-	default:
-		pr_warn("Tegra30: Unknown chip rev %d\n", rev);
-		tegra_cpu_speedo_id = 0;
-		tegra_soc_speedo_id = 0;
-		threshold_index = THRESHOLD_INDEX_0;
-		break;
-	}
-}
-
-void tegra30_init_speedo_data(void)
-{
-	u32 cpu_speedo_val;
-	u32 core_speedo_val;
-	int i;
-
-	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
-			THRESHOLD_INDEX_COUNT);
-	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
-			THRESHOLD_INDEX_COUNT);
-
-	package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
-
-	rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
-	fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
-	pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
-	pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
-
-	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
-		if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
-			break;
-	}
-	tegra_cpu_process_id = i - 1;
-
-	if (tegra_cpu_process_id == -1) {
-		pr_warn("Tegra30: CPU speedo value %3d out of range",
-		       cpu_speedo_val);
-		tegra_cpu_process_id = 0;
-		tegra_cpu_speedo_id = 1;
-	}
-
-	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
-		if (core_speedo_val < core_process_speedos[threshold_index][i])
-			break;
-	}
-	tegra_core_process_id = i - 1;
-
-	if (tegra_core_process_id == -1) {
-		pr_warn("Tegra30: CORE speedo value %3d out of range",
-		       core_speedo_val);
-		tegra_core_process_id = 0;
-		tegra_soc_speedo_id = 1;
-	}
-
-	pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
-		tegra_cpu_speedo_id, tegra_soc_speedo_id);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra.c linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra.c
--- linux-libre-3.16-gnu/arch/arm/mach-tegra/tegra.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-tegra/tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,40 +16,40 @@
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
 #include <linux/clk.h>
+#include <linux/clk/tegra.h>
 #include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/pda_power.h>
-#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
 #include <linux/usb/tegra_usb_phy.h>
-#include <linux/clk/tegra.h>
-#include <linux/irqchip.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
 
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/trusted_foundations.h>
 
-#include "apbio.h"
 #include "board.h"
 #include "common.h"
 #include "cpuidle.h"
-#include "fuse.h"
 #include "iomap.h"
 #include "irq.h"
-#include "pmc.h"
 #include "pm.h"
 #include "reset.h"
 #include "sleep.h"
@@ -73,16 +73,11 @@ u32 tegra_uart_config[3] = {
 static void __init tegra_init_early(void)
 {
 	of_register_trusted_foundations();
-	tegra_apb_io_init();
-	tegra_init_fuse();
 	tegra_cpu_reset_handler_init();
-	tegra_powergate_init();
-	tegra_hotplug_init();
 }
 
 static void __init tegra_dt_init_irq(void)
 {
-	tegra_pmc_init_irq();
 	tegra_init_irq();
 	irqchip_init();
 	tegra_legacy_irq_syscore_init();
@@ -94,8 +89,6 @@ static void __init tegra_dt_init(void)
 	struct soc_device *soc_dev;
 	struct device *parent = NULL;
 
-	tegra_pmc_init();
-
 	tegra_clocks_apply_init_table();
 
 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -103,8 +96,9 @@ static void __init tegra_dt_init(void)
 		goto out;
 
 	soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
-	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
-	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d",
+					   tegra_sku_info.revision);
+	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
 
 	soc_dev = soc_device_register(soc_dev_attr);
 	if (IS_ERR(soc_dev)) {
@@ -144,7 +138,6 @@ static void __init tegra_dt_init_late(vo
 
 	tegra_init_suspend();
 	tegra_cpuidle_init();
-	tegra_powergate_debugfs_init();
 
 	for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
 		if (of_machine_is_compatible(board_init_funcs[i].machine)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ux500/board-mop500-regulators.c linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/board-mop500-regulators.c
--- linux-libre-3.16-gnu/arch/arm/mach-ux500/board-mop500-regulators.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/board-mop500-regulators.c	2014-09-28 17:29:07.000000000 -0400
@@ -796,7 +796,7 @@ static struct ab8500_regulator_reg_init
 	INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX6,              0x00, 0x00),
 };
 
-struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
+static struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
 	/* supplies to the display/camera */
 	[AB8505_LDO_AUX1] = {
 		.constraints = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ux500/cache-l2x0.c linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cache-l2x0.c
--- linux-libre-3.16-gnu/arch/arm/mach-ux500/cache-l2x0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cache-l2x0.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,17 +7,15 @@
 #include <linux/io.h>
 #include <linux/of.h>
 
-#include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include "db8500-regs.h"
 #include "id.h"
 
-static void __iomem *l2x0_base;
-
 static int __init ux500_l2x0_unlock(void)
 {
 	int i;
+	void __iomem *l2x0_base = __io_address(U8500_L2CC_BASE);
 
 	/*
 	 * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
@@ -45,23 +43,15 @@ static void ux500_l2c310_write_sec(unsig
 
 static int __init ux500_l2x0_init(void)
 {
-	if (cpu_is_u8500_family() || cpu_is_ux540_family())
-		l2x0_base = __io_address(U8500_L2CC_BASE);
-	else
-		/* Non-Ux500 platform */
+	/* Multiplatform guard */
+	if (!((cpu_is_u8500_family() || cpu_is_ux540_family())))
 		return -ENODEV;
 
 	/* Unlock before init */
 	ux500_l2x0_unlock();
-
 	outer_cache.write_sec = ux500_l2c310_write_sec;
-
-	if (of_have_populated_dt())
-		l2x0_of_init(0, ~0);
-	else
-		l2x0_init(l2x0_base, 0, ~0);
+	l2x0_of_init(0, ~0);
 
 	return 0;
 }
-
 early_initcall(ux500_l2x0_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ux500/cpu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cpu.c
--- linux-libre-3.16-gnu/arch/arm/mach-ux500/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,7 @@ static void __init soc_info_populate(str
 	soc_dev_attr->revision = ux500_get_revision();
 }
 
-struct device_attribute ux500_soc_attr =
+static const struct device_attribute ux500_soc_attr =
 	__ATTR(process,  S_IRUGO, ux500_get_process,  NULL);
 
 struct device * __init ux500_soc_device_init(const char *soc_id)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ux500/cpu-db8500.c linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cpu-db8500.c
--- linux-libre-3.16-gnu/arch/arm/mach-ux500/cpu-db8500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/cpu-db8500.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,11 +33,11 @@
 #include "db8500-regs.h"
 #include "id.h"
 
-struct ab8500_platform_data ab8500_platdata = {
+static struct ab8500_platform_data ab8500_platdata = {
 	.regulator	= &ab8500_regulator_plat_data,
 };
 
-struct prcmu_pdata db8500_prcmu_pdata = {
+static struct prcmu_pdata db8500_prcmu_pdata = {
 	.ab_platdata	= &ab8500_platdata,
 	.version_offset	= DB8500_PRCMU_FW_VERSION_OFFSET,
 	.legacy_offset	= DB8500_PRCMU_LEGACY_OFFSET,
@@ -82,7 +82,7 @@ static struct map_desc u9540_io_desc[] _
 	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K),
 };
 
-void __init u8500_map_io(void)
+static void __init u8500_map_io(void)
 {
 	/*
 	 * Map the UARTs early so that the DEBUG_LL stuff continues to work.
@@ -119,7 +119,7 @@ static irqreturn_t db8500_pmu_handler(in
 	return ret;
 }
 
-struct arm_pmu_platdata db8500_pmu_platdata = {
+static struct arm_pmu_platdata db8500_pmu_platdata = {
 	.handle_irq		= db8500_pmu_handler,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-ux500/timer.c linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/timer.c
--- linux-libre-3.16-gnu/arch/arm/mach-ux500/timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-ux500/timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,7 @@
 #include "db8500-regs.h"
 #include "id.h"
 
-const static struct of_device_id prcmu_timer_of_match[] __initconst = {
+static const struct of_device_id prcmu_timer_of_match[] __initconst = {
 	{ .compatible = "stericsson,db8500-prcmu-timer-4", },
 	{ },
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-versatile/core.c linux-libre-3.17-rc7-gnu/arch/arm/mach-versatile/core.c
--- linux-libre-3.16-gnu/arch/arm/mach-versatile/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-versatile/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/of_platform.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
 #include <linux/amba/pl061.h>
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
@@ -53,7 +54,6 @@
 #include <mach/platform.h>
 #include <asm/hardware/timer-sp.h>
 
-#include <plat/clcd.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-versatile/versatile_dt.c linux-libre-3.17-rc7-gnu/arch/arm/mach-versatile/versatile_dt.c
--- linux-libre-3.16-gnu/arch/arm/mach-versatile/versatile_dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-versatile/versatile_dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,6 @@ static const char *versatile_dt_match[]
 DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
-	.init_irq	= versatile_init_irq,
 	.init_machine	= versatile_dt_init,
 	.dt_compat	= versatile_dt_match,
 	.restart	= versatile_restart,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-vexpress/ct-ca9x4.c linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/ct-ca9x4.c
--- linux-libre-3.16-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
 #include <linux/clkdev.h>
 #include <linux/vexpress.h>
 #include <linux/irqchip/arm-gic.h>
@@ -29,8 +30,6 @@
 #include <mach/motherboard.h>
 #include <mach/irqs.h>
 
-#include <plat/clcd.h>
-
 static struct map_desc ct_ca9x4_io_desc[] __initdata = {
 	{
 		.virtual        = V2T_PERIPH,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-vexpress/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-vexpress/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@ menuconfig ARCH_VEXPRESS
 	select ICST
 	select NO_IOPORT_MAP
 	select PLAT_VERSATILE
-	select PLAT_VERSATILE_CLCD
 	select POWER_RESET
 	select POWER_RESET_VEXPRESS
 	select POWER_SUPPLY
@@ -64,7 +63,6 @@ config ARCH_VEXPRESS_DCSCB
 
 config ARCH_VEXPRESS_SPC
 	bool "Versatile Express Serial Power Controller (SPC)"
-	select ARCH_HAS_OPP
 	select PM_OPP
 	help
 	  The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-vexpress/spc.c linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/spc.c
--- linux-libre-3.16-gnu/arch/arm/mach-vexpress/spc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/spc.c	2014-09-28 17:29:07.000000000 -0400
@@ -426,9 +426,15 @@ static int ve_spc_populate_opps(uint32_t
 
 static int ve_init_opp_table(struct device *cpu_dev)
 {
-	int cluster = topology_physical_package_id(cpu_dev->id);
-	int idx, ret = 0, max_opp = info->num_opps[cluster];
-	struct ve_spc_opp *opps = info->opps[cluster];
+	int cluster;
+	int idx, ret = 0, max_opp;
+	struct ve_spc_opp *opps;
+
+	cluster = topology_physical_package_id(cpu_dev->id);
+	cluster = cluster < 0 ? 0 : cluster;
+
+	max_opp = info->num_opps[cluster];
+	opps = info->opps[cluster];
 
 	for (idx = 0; idx < max_opp; idx++, opps++) {
 		ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
@@ -537,6 +543,8 @@ static struct clk *ve_spc_clk_register(s
 	spc->hw.init = &init;
 	spc->cluster = topology_physical_package_id(cpu_dev->id);
 
+	spc->cluster = spc->cluster < 0 ? 0 : spc->cluster;
+
 	init.name = dev_name(cpu_dev);
 	init.ops = &clk_spc_ops;
 	init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-vexpress/tc2_pm.c linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/tc2_pm.c
--- linux-libre-3.16-gnu/arch/arm/mach-vexpress/tc2_pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-vexpress/tc2_pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -152,7 +152,7 @@ static void tc2_pm_down(u64 residency)
 	if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
 		arch_spin_unlock(&tc2_pm_lock);
 
-		if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
+		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
 			/*
 			 * On the Cortex-A15 we need to disable
 			 * L2 prefetching before flushing the cache.
@@ -323,6 +323,21 @@ static void __naked tc2_pm_power_up_setu
 "	b	cci_enable_port_for_self ");
 }
 
+static void __init tc2_cache_off(void)
+{
+	pr_info("TC2: disabling cache during MCPM loopback test\n");
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+		/* disable L2 prefetching on the Cortex-A15 */
+		asm volatile(
+		"mcr	p15, 1, %0, c15, c0, 3 \n\t"
+		"isb	\n\t"
+		"dsb	"
+		: : "r" (0x400) );
+	}
+	v7_exit_coherency_flush(all);
+	cci_disable_port_by_cpu(read_cpuid_mpidr());
+}
+
 static int __init tc2_pm_init(void)
 {
 	int ret, irq;
@@ -370,6 +385,8 @@ static int __init tc2_pm_init(void)
 	ret = mcpm_platform_register(&tc2_pm_power_ops);
 	if (!ret) {
 		mcpm_sync_init(tc2_pm_power_up_setup);
+		/* test if we can (re)enable the CCI on our own */
+		BUG_ON(mcpm_loopback(tc2_cache_off) != 0);
 		pr_info("TC2 power management initialized\n");
 	}
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-vt8500/vt8500.c linux-libre-3.17-rc7-gnu/arch/arm/mach-vt8500/vt8500.c
--- linux-libre-3.16-gnu/arch/arm/mach-vt8500/vt8500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-vt8500/vt8500.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,7 @@
 
 static void __iomem *pmc_base;
 
-void vt8500_restart(enum reboot_mode mode, const char *cmd)
+static void vt8500_restart(enum reboot_mode mode, const char *cmd)
 {
 	if (pmc_base)
 		writel(1, pmc_base + VT8500_PMSR_REG);
@@ -60,7 +60,7 @@ static struct map_desc vt8500_io_desc[]
 	},
 };
 
-void __init vt8500_map_io(void)
+static void __init vt8500_map_io(void)
 {
 	iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
 }
@@ -72,7 +72,7 @@ static void vt8500_power_off(void)
 	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
 }
 
-void __init vt8500_init(void)
+static void __init vt8500_init(void)
 {
 	struct device_node *np;
 #if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-w90x900/cpu.c linux-libre-3.17-rc7-gnu/arch/arm/mach-w90x900/cpu.c
--- linux-libre-3.16-gnu/arch/arm/mach-w90x900/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-w90x900/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -178,7 +178,8 @@ static int __init nuc900_set_cpufreq(cha
 	if (!*str)
 		return 0;
 
-	strict_strtoul(str, 0, &cpufreq);
+	if (kstrtoul(str, 0, &cpufreq))
+		return 0;
 
 	nuc900_clock_source(NULL, "ext");
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mach-zynq/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mach-zynq/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mach-zynq/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mach-zynq/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,5 @@
 config ARCH_ZYNQ
 	bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
-	select ARCH_HAS_OPP
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/Makefile linux-libre-3.17-rc7-gnu/arch/arm/Makefile
--- linux-libre-3.16-gnu/arch/arm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -127,6 +127,9 @@ CHECKFLAGS	+= -D__arm__
 
 #Default value
 head-y		:= arch/arm/kernel/head$(MMUEXT).o
+
+# Text offset. This list is sorted numerically by address in order to
+# provide a means to avoid/resolve conflicts in multi-arch kernels.
 textofs-y	:= 0x00008000
 textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
 # We don't want the htc bootloader to corrupt kernel during resume
@@ -156,14 +159,13 @@ machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_GEMINI)		+= gemini
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
-machine-$(CONFIG_ARCH_HI3xxx)		+= hisi
+machine-$(CONFIG_ARCH_HISI)		+= hisi
 machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
 machine-$(CONFIG_ARCH_IOP32X)		+= iop32x
 machine-$(CONFIG_ARCH_IOP33X)		+= iop33x
 machine-$(CONFIG_ARCH_IXP4XX)		+= ixp4xx
 machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
-machine-$(CONFIG_ARCH_KIRKWOOD)		+= kirkwood
 machine-$(CONFIG_ARCH_KS8695)		+= ks8695
 machine-$(CONFIG_ARCH_LPC32XX)		+= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		+= mmp
@@ -172,6 +174,7 @@ machine-$(CONFIG_ARCH_MSM)		+= msm
 machine-$(CONFIG_ARCH_MV78XX0)		+= mv78xx0
 machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
 machine-$(CONFIG_ARCH_MXC)		+= imx
+machine-$(CONFIG_ARCH_MEDIATEK)		+= mediatek
 machine-$(CONFIG_ARCH_MXS)		+= mxs
 machine-$(CONFIG_ARCH_NETX)		+= netx
 machine-$(CONFIG_ARCH_NOMADIK)		+= nomadik
@@ -187,8 +190,6 @@ machine-$(CONFIG_ARCH_ROCKCHIP)		+= rock
 machine-$(CONFIG_ARCH_RPC)		+= rpc
 machine-$(CONFIG_ARCH_S3C24XX)		+= s3c24xx
 machine-$(CONFIG_ARCH_S3C64XX)		+= s3c64xx
-machine-$(CONFIG_ARCH_S5P64X0)		+= s5p64x0
-machine-$(CONFIG_ARCH_S5PC100)		+= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		+= s5pv210
 machine-$(CONFIG_ARCH_SA1100)		+= sa1100
 machine-$(CONFIG_ARCH_SHMOBILE) 	+= shmobile
@@ -212,11 +213,11 @@ machine-$(CONFIG_PLAT_SPEAR)		+= spear
 plat-$(CONFIG_ARCH_EXYNOS)	+= samsung
 plat-$(CONFIG_ARCH_OMAP)	+= omap
 plat-$(CONFIG_ARCH_S3C64XX)	+= samsung
+plat-$(CONFIG_ARCH_S5PV210)	+= samsung
 plat-$(CONFIG_PLAT_IOP)		+= iop
 plat-$(CONFIG_PLAT_ORION)	+= orion
 plat-$(CONFIG_PLAT_PXA)		+= pxa
 plat-$(CONFIG_PLAT_S3C24XX)	+= samsung
-plat-$(CONFIG_PLAT_S5P)		+= samsung
 plat-$(CONFIG_PLAT_VERSATILE)	+= versatile
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
@@ -240,7 +241,7 @@ MACHINE  :=
 endif
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
-platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y))
+platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
 
 ifneq ($(CONFIG_ARCH_MULTIPLATFORM),y)
 ifeq ($(KBUILD_SRC),)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/abort-ev6.S linux-libre-3.17-rc7-gnu/arch/arm/mm/abort-ev6.S
--- linux-libre-3.16-gnu/arch/arm/mm/abort-ev6.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/abort-ev6.S	2014-09-28 17:29:07.000000000 -0400
@@ -17,12 +17,6 @@
  */
 	.align	5
 ENTRY(v6_early_abort)
-#ifdef CONFIG_CPU_V6
-	sub	r1, sp, #4			@ Get unused stack location
-	strex	r0, r1, [r1]			@ Clear the exclusive monitor
-#elif defined(CONFIG_CPU_32v6K)
-	clrex
-#endif
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/abort-ev7.S linux-libre-3.17-rc7-gnu/arch/arm/mm/abort-ev7.S
--- linux-libre-3.16-gnu/arch/arm/mm/abort-ev7.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/abort-ev7.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,12 +13,6 @@
  */
 	.align	5
 ENTRY(v7_early_abort)
-	/*
-	 * The effect of data aborts on on the exclusive access monitor are
-	 * UNPREDICTABLE. Do a CLREX to clear the state
-	 */
-	clrex
-
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/alignment.c linux-libre-3.17-rc7-gnu/arch/arm/mm/alignment.c
--- linux-libre-3.16-gnu/arch/arm/mm/alignment.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/alignment.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,6 +76,7 @@
 
 static unsigned long ai_user;
 static unsigned long ai_sys;
+static void *ai_sys_last_pc;
 static unsigned long ai_skipped;
 static unsigned long ai_half;
 static unsigned long ai_word;
@@ -130,7 +131,7 @@ static const char *usermode_action[] = {
 static int alignment_proc_show(struct seq_file *m, void *v)
 {
 	seq_printf(m, "User:\t\t%lu\n", ai_user);
-	seq_printf(m, "System:\t\t%lu\n", ai_sys);
+	seq_printf(m, "System:\t\t%lu (%pF)\n", ai_sys, ai_sys_last_pc);
 	seq_printf(m, "Skipped:\t%lu\n", ai_skipped);
 	seq_printf(m, "Half:\t\t%lu\n", ai_half);
 	seq_printf(m, "Word:\t\t%lu\n", ai_word);
@@ -794,6 +795,7 @@ do_alignment(unsigned long addr, unsigne
 		goto user;
 
 	ai_sys += 1;
+	ai_sys_last_pc = (void *)instruction_pointer(regs);
 
  fixup:
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-fa.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-fa.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-fa.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-fa.S	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/memory.h>
 #include <asm/page.h>
 
@@ -45,7 +46,7 @@
 ENTRY(fa_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(fa_flush_icache_all)
 
 /*
@@ -71,7 +72,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain write buffer
 	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -99,7 +100,7 @@ ENTRY(fa_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
 	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -135,7 +136,7 @@ ENTRY(fa_coherent_user_range)
 	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -155,7 +156,7 @@ ENTRY(fa_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -181,7 +182,7 @@ fa_dma_inv_range:
 	blo	1b
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -199,7 +200,7 @@ fa_dma_clean_range:
 	blo	1b
 	mov	r0, #0	
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start,end)
@@ -214,7 +215,7 @@ ENTRY(fa_dma_flush_range)
 	blo	1b
 	mov	r0, #0	
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -237,7 +238,7 @@ ENDPROC(fa_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(fa_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(fa_dma_unmap_area)
 
 	.globl	fa_flush_kern_cache_louis
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-l2x0.c linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-l2x0.c
--- linux-libre-3.16-gnu/arch/arm/mm/cache-l2x0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-l2x0.c	2014-09-28 17:29:07.000000000 -0400
@@ -665,7 +665,7 @@ static int l2c310_cpu_enable_flz(struct
 static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
 {
 	unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK;
-	bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
+	bool cortex_a9 = read_cpuid_part() == ARM_CPU_PART_CORTEX_A9;
 
 	if (rev >= L310_CACHE_ID_RTL_R2P0) {
 		if (cortex_a9) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-nop.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-nop.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-nop.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-nop.S	2014-09-28 17:29:07.000000000 -0400
@@ -5,11 +5,12 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 
 #include "proc-macros.S"
 
 ENTRY(nop_flush_icache_all)
-	mov	pc, lr
+	ret	lr
 ENDPROC(nop_flush_icache_all)
 
 	.globl nop_flush_kern_cache_all
@@ -29,7 +30,7 @@ ENDPROC(nop_flush_icache_all)
 
 ENTRY(nop_coherent_user_range)
 	mov	r0, 0
-	mov	pc, lr
+	ret	lr
 ENDPROC(nop_coherent_user_range)
 
 	.globl nop_flush_kern_dcache_area
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-v4.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-v4.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4.S	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/page.h>
 #include "proc-macros.S"
 
@@ -18,7 +19,7 @@
  *	Unconditionally clean and invalidate the entire icache.
  */
 ENTRY(v4_flush_icache_all)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4_flush_icache_all)
 
 /*
@@ -40,7 +41,7 @@ ENTRY(v4_flush_kern_cache_all)
 #ifdef CONFIG_CPU_CP15
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
-	mov	pc, lr
+	ret	lr
 #else
 	/* FALLTHROUGH */
 #endif
@@ -59,7 +60,7 @@ ENTRY(v4_flush_user_cache_range)
 #ifdef CONFIG_CPU_CP15
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c7, 0		@ flush ID cache
-	mov	pc, lr
+	ret	lr
 #else
 	/* FALLTHROUGH */
 #endif
@@ -89,7 +90,7 @@ ENTRY(v4_coherent_kern_range)
  */
 ENTRY(v4_coherent_user_range)
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -116,7 +117,7 @@ ENTRY(v4_dma_flush_range)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_unmap_area(start, size, dir)
@@ -136,7 +137,7 @@ ENTRY(v4_dma_unmap_area)
  *	- dir	- DMA direction
  */
 ENTRY(v4_dma_map_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4_dma_unmap_area)
 ENDPROC(v4_dma_map_area)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-v4wb.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4wb.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-v4wb.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4wb.S	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/memory.h>
 #include <asm/page.h>
 #include "proc-macros.S"
@@ -58,7 +59,7 @@ flush_base:
 ENTRY(v4wb_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4wb_flush_icache_all)
 
 /*
@@ -94,7 +95,7 @@ __flush_whole_cache:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -122,7 +123,7 @@ ENTRY(v4wb_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -170,7 +171,7 @@ ENTRY(v4wb_coherent_user_range)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 
 /*
@@ -195,7 +196,7 @@ v4wb_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -212,7 +213,7 @@ v4wb_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -248,7 +249,7 @@ ENDPROC(v4wb_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(v4wb_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4wb_dma_unmap_area)
 
 	.globl	v4wb_flush_kern_cache_louis
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-v4wt.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4wt.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-v4wt.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v4wt.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/page.h>
 #include "proc-macros.S"
 
@@ -48,7 +49,7 @@
 ENTRY(v4wt_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4wt_flush_icache_all)
 
 /*
@@ -71,7 +72,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -94,7 +95,7 @@ ENTRY(v4wt_flush_user_cache_range)
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -126,7 +127,7 @@ ENTRY(v4wt_coherent_user_range)
 	cmp	r0, r1
 	blo	1b
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -160,7 +161,7 @@ v4wt_dma_inv_range:
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -192,7 +193,7 @@ ENTRY(v4wt_dma_unmap_area)
  *	- dir	- DMA direction
  */
 ENTRY(v4wt_dma_map_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v4wt_dma_unmap_area)
 ENDPROC(v4wt_dma_map_area)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-v6.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v6.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-v6.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v6.S	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ ENTRY(v6_flush_icache_all)
 #else
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I-cache
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(v6_flush_icache_all)
 
 /*
@@ -73,7 +73,7 @@ ENTRY(v6_flush_kern_cache_all)
 #else
 	mcr	p15, 0, r0, c7, c15, 0		@ Cache clean+invalidate
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v6_flush_cache_all()
@@ -98,7 +98,7 @@ ENTRY(v6_flush_user_cache_all)
  *	- we have a VIPT cache.
  */
 ENTRY(v6_flush_user_cache_range)
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v6_coherent_kern_range(start,end)
@@ -150,7 +150,7 @@ ENTRY(v6_coherent_user_range)
 #else
 	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * Fault handling for the cache operation above. If the virtual address in r0
@@ -158,7 +158,7 @@ ENTRY(v6_coherent_user_range)
  */
 9001:
 	mov	r0, #-EFAULT
-	mov	pc, lr
+	ret	lr
  UNWIND(.fnend		)
 ENDPROC(v6_coherent_user_range)
 ENDPROC(v6_coherent_kern_range)
@@ -188,7 +188,7 @@ ENTRY(v6_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4
 #endif
-	mov	pc, lr
+	ret	lr
 
 
 /*
@@ -239,7 +239,7 @@ v6_dma_inv_range:
 	blo	1b
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v6_dma_clean_range(start,end)
@@ -262,7 +262,7 @@ v6_dma_clean_range:
 	blo	1b
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v6_dma_flush_range(start,end)
@@ -290,7 +290,7 @@ ENTRY(v6_dma_flush_range)
 	blo	1b
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -323,7 +323,7 @@ ENTRY(v6_dma_unmap_area)
 	teq	r2, #DMA_TO_DEVICE
 	bne	v6_dma_inv_range
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(v6_dma_unmap_area)
 
 	.globl	v6_flush_kern_cache_louis
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/cache-v7.S linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v7.S
--- linux-libre-3.16-gnu/arch/arm/mm/cache-v7.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/cache-v7.S	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ ENTRY(v7_invalidate_l1)
        bgt     1b
        dsb     st
        isb
-       mov     pc, lr
+       ret     lr
 ENDPROC(v7_invalidate_l1)
 
 /*
@@ -76,7 +76,7 @@ ENTRY(v7_flush_icache_all)
 	mov	r0, #0
 	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)		@ invalidate I-cache inner shareable
 	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)		@ I+BTB cache invalidate
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_icache_all)
 
  /*
@@ -94,7 +94,7 @@ ENTRY(v7_flush_dcache_louis)
 	ALT_UP(ands	r3, r0, #(7 << 27))	@ extract LoUU from clidr
 #ifdef CONFIG_ARM_ERRATA_643719
 	ALT_SMP(mrceq	p15, 0, r2, c0, c0, 0)	@ read main ID register
-	ALT_UP(moveq	pc, lr)			@ LoUU is zero, so nothing to do
+	ALT_UP(reteq	lr)			@ LoUU is zero, so nothing to do
 	ldreq	r1, =0x410fc090                 @ ID of ARM Cortex A9 r0p?
 	biceq	r2, r2, #0x0000000f             @ clear minor revision number
 	teqeq	r2, r1                          @ test for errata affected core and if so...
@@ -102,7 +102,7 @@ ENTRY(v7_flush_dcache_louis)
 #endif
 	ALT_SMP(mov	r3, r3, lsr #20)	@ r3 = LoUIS * 2
 	ALT_UP(mov	r3, r3, lsr #26)	@ r3 = LoUU * 2
-	moveq	pc, lr				@ return if level == 0
+	reteq	lr				@ return if level == 0
 	mov	r10, #0				@ r10 (starting level) = 0
 	b	flush_levels			@ start flushing cache levels
 ENDPROC(v7_flush_dcache_louis)
@@ -168,7 +168,7 @@ finished:
 	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
 	dsb	st
 	isb
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_dcache_all)
 
 /*
@@ -191,7 +191,7 @@ ENTRY(v7_flush_kern_cache_all)
 	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
  ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
  THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_kern_cache_all)
 
  /*
@@ -209,7 +209,7 @@ ENTRY(v7_flush_kern_cache_louis)
 	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
  ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
  THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_kern_cache_louis)
 
 /*
@@ -235,7 +235,7 @@ ENTRY(v7_flush_user_cache_all)
  *	- we have a VIPT cache.
  */
 ENTRY(v7_flush_user_cache_range)
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_user_cache_all)
 ENDPROC(v7_flush_user_cache_range)
 
@@ -296,7 +296,7 @@ ENTRY(v7_coherent_user_range)
 	ALT_UP(mcr	p15, 0, r0, c7, c5, 6)	@ invalidate BTB
 	dsb	ishst
 	isb
-	mov	pc, lr
+	ret	lr
 
 /*
  * Fault handling for the cache operation above. If the virtual address in r0
@@ -307,7 +307,7 @@ ENTRY(v7_coherent_user_range)
 	dsb
 #endif
 	mov	r0, #-EFAULT
-	mov	pc, lr
+	ret	lr
  UNWIND(.fnend		)
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
@@ -336,7 +336,7 @@ ENTRY(v7_flush_kern_dcache_area)
 	cmp	r0, r1
 	blo	1b
 	dsb	st
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_flush_kern_dcache_area)
 
 /*
@@ -369,7 +369,7 @@ v7_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	dsb	st
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_dma_inv_range)
 
 /*
@@ -391,7 +391,7 @@ v7_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	dsb	st
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_dma_clean_range)
 
 /*
@@ -413,7 +413,7 @@ ENTRY(v7_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	dsb	st
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_dma_flush_range)
 
 /*
@@ -439,7 +439,7 @@ ENTRY(v7_dma_unmap_area)
 	add	r1, r1, r0
 	teq	r2, #DMA_TO_DEVICE
 	bne	v7_dma_inv_range
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7_dma_unmap_area)
 
 	__INITDATA
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/dma-mapping.c linux-libre-3.17-rc7-gnu/arch/arm/mm/dma-mapping.c
--- linux-libre-3.16-gnu/arch/arm/mm/dma-mapping.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/dma-mapping.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/vmalloc.h>
 #include <linux/sizes.h>
+#include <linux/cma.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/dump.c linux-libre-3.17-rc7-gnu/arch/arm/mm/dump.c
--- linux-libre-3.16-gnu/arch/arm/mm/dump.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/dump.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,8 +126,8 @@ static const struct prot_bits section_bi
 		.val	= PMD_SECT_USER,
 		.set	= "USR",
 	}, {
-		.mask	= PMD_SECT_RDONLY,
-		.val	= PMD_SECT_RDONLY,
+		.mask	= L_PMD_SECT_RDONLY,
+		.val	= L_PMD_SECT_RDONLY,
 		.set	= "ro",
 		.clear	= "RW",
 #elif __LINUX_ARM_ARCH__ >= 6
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/mm/Kconfig
--- linux-libre-3.16-gnu/arch/arm/mm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -669,7 +669,7 @@ config ARM_VIRT_EXT
 	  details.
 
 config SWP_EMULATE
-	bool "Emulate SWP/SWPB instructions"
+	bool "Emulate SWP/SWPB instructions" if !SMP
 	depends on CPU_V7
 	default y if SMP
 	select HAVE_PROC_CPU if PROC_FS
@@ -854,7 +854,7 @@ config OUTER_CACHE_SYNC
 
 config CACHE_FEROCEON_L2
 	bool "Enable the Feroceon L2 cache controller"
-	depends on ARCH_KIRKWOOD || ARCH_MV78XX0 || ARCH_MVEBU
+	depends on ARCH_MV78XX0 || ARCH_MVEBU
 	default y
 	select OUTER_CACHE
 	help
@@ -907,8 +907,8 @@ config PL310_ERRATA_588369
 	   They are architecturally defined to behave as the execution of a
 	   clean operation followed immediately by an invalidate operation,
 	   both performing to the same memory location. This functionality
-	   is not correctly implemented in PL310 as clean lines are not
-	   invalidated as a result of these operations.
+	   is not correctly implemented in PL310 prior to r2p0 (fixed in r2p0)
+	   as clean lines are not invalidated as a result of these operations.
 
 config PL310_ERRATA_727915
 	bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
@@ -918,7 +918,8 @@ config PL310_ERRATA_727915
 	  PL310 can handle normal accesses while it is in progress. Under very
 	  rare circumstances, due to this erratum, write data can be lost when
 	  PL310 treats a cacheable write transaction during a Clean &
-	  Invalidate by Way operation.
+	  Invalidate by Way operation.  Revisions prior to r3p1 are affected by
+	  this errata (fixed in r3p1).
 
 config PL310_ERRATA_753970
 	bool "PL310 errata: cache sync operation may be faulty"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/l2c-l2x0-resume.S linux-libre-3.17-rc7-gnu/arch/arm/mm/l2c-l2x0-resume.S
--- linux-libre-3.16-gnu/arch/arm/mm/l2c-l2x0-resume.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/l2c-l2x0-resume.S	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@
  * This code can only be used to if you are running in the secure world.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/hardware/cache-l2x0.h>
 
 	.text
@@ -27,7 +28,7 @@ ENTRY(l2c310_early_resume)
 
 	@ Check that the address has been initialised
 	teq	r1, #0
-	moveq	pc, lr
+	reteq	lr
 
 	@ The prefetch and power control registers are revision dependent
 	@ and can be written whether or not the L2 cache is enabled
@@ -41,7 +42,7 @@ ENTRY(l2c310_early_resume)
 	@ Don't setup the L2 cache if it is already enabled
 	ldr	r0, [r1, #L2X0_CTRL]
 	tst	r0, #L2X0_CTRL_EN
-	movne	pc, lr
+	retne	lr
 
 	str	r3, [r1, #L310_TAG_LATENCY_CTRL]
 	str	r4, [r1, #L310_DATA_LATENCY_CTRL]
@@ -51,7 +52,7 @@ ENTRY(l2c310_early_resume)
 	str	r2, [r1, #L2X0_AUX_CTRL]
 	mov	r9, #L2X0_CTRL_EN
 	str	r9, [r1, #L2X0_CTRL]
-	mov	pc, lr
+	ret	lr
 ENDPROC(l2c310_early_resume)
 
 	.align
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/mmu.c linux-libre-3.17-rc7-gnu/arch/arm/mm/mmu.c
--- linux-libre-3.16-gnu/arch/arm/mm/mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1434,23 +1434,64 @@ void __init early_paging_init(const stru
 	dsb(ishst);
 	isb();
 
-	/* remap level 1 table */
+	/*
+	 * FIXME: This code is not architecturally compliant: we modify
+	 * the mappings in-place, indeed while they are in use by this
+	 * very same code.  This may lead to unpredictable behaviour of
+	 * the CPU.
+	 *
+	 * Even modifying the mappings in a separate page table does
+	 * not resolve this.
+	 *
+	 * The architecture strongly recommends that when a mapping is
+	 * changed, that it is changed by first going via an invalid
+	 * mapping and back to the new mapping.  This is to ensure that
+	 * no TLB conflicts (caused by the TLB having more than one TLB
+	 * entry match a translation) can occur.  However, doing that
+	 * here will result in unmapping the code we are running.
+	 */
+	pr_warn("WARNING: unsafe modification of in-place page tables - tainting kernel\n");
+	add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+
+	/*
+	 * Remap level 1 table.  This changes the physical addresses
+	 * used to refer to the level 2 page tables to the high
+	 * physical address alias, leaving everything else the same.
+	 */
 	for (i = 0; i < PTRS_PER_PGD; pud0++, i++) {
 		set_pud(pud0,
 			__pud(__pa(pmd0) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
 		pmd0 += PTRS_PER_PMD;
 	}
 
-	/* remap pmds for kernel mapping */
+	/*
+	 * Remap the level 2 table, pointing the mappings at the high
+	 * physical address alias of these pages.
+	 */
 	phys = __pa(map_start);
 	do {
 		*pmdk++ = __pmd(phys | pmdprot);
 		phys += PMD_SIZE;
 	} while (phys < map_end);
 
+	/*
+	 * Ensure that the above updates are flushed out of the cache.
+	 * This is not strictly correct; on a system where the caches
+	 * are coherent with each other, but the MMU page table walks
+	 * may not be coherent, flush_cache_all() may be a no-op, and
+	 * this will fail.
+	 */
 	flush_cache_all();
+
+	/*
+	 * Re-write the TTBR values to point them at the high physical
+	 * alias of the page tables.  We expect __va() will work on
+	 * cpu_get_pgd(), which returns the value of TTBR0.
+	 */
 	cpu_switch_mm(pgd0, &init_mm);
 	cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
+
+	/* Finally flush any stale TLB values. */
 	local_flush_bp_all();
 	local_flush_tlb_all();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm1020e.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1020e.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm1020e.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1020e.S	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@
  * cpu_arm1020e_proc_init()
  */
 ENTRY(cpu_arm1020e_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1020e_proc_fin()
@@ -83,7 +83,7 @@ ENTRY(cpu_arm1020e_proc_fin)
 	bic	r0, r0, #0x1000 		@ ...i............
 	bic	r0, r0, #0x000e 		@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1020e_reset(loc)
@@ -107,7 +107,7 @@ ENTRY(cpu_arm1020e_reset)
 	bic	ip, ip, #0x000f 		@ ............wcam
 	bic	ip, ip, #0x1100 		@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm1020e_reset)
 	.popsection
 
@@ -117,7 +117,7 @@ ENDPROC(cpu_arm1020e_reset)
 	.align	5
 ENTRY(cpu_arm1020e_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -133,7 +133,7 @@ ENTRY(arm1020e_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1020e_flush_icache_all)
 
 /*
@@ -168,7 +168,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -197,7 +197,7 @@ ENTRY(arm1020e_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -236,7 +236,7 @@ ENTRY(arm1020e_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -257,7 +257,7 @@ ENTRY(arm1020e_flush_kern_dcache_area)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -286,7 +286,7 @@ arm1020e_dma_inv_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -308,7 +308,7 @@ arm1020e_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -328,7 +328,7 @@ ENTRY(arm1020e_dma_flush_range)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -351,7 +351,7 @@ ENDPROC(arm1020e_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm1020e_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1020e_dma_unmap_area)
 
 	.globl	arm1020e_flush_kern_cache_louis
@@ -369,7 +369,7 @@ ENTRY(cpu_arm1020e_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -407,7 +407,7 @@ ENTRY(cpu_arm1020e_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
         
 /*
  * cpu_arm1020e_set_pte(ptep, pte)
@@ -423,7 +423,7 @@ ENTRY(cpu_arm1020e_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm1020e_setup, #function
 __arm1020e_setup:
@@ -441,7 +441,7 @@ __arm1020e_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .R.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm1020e_setup, . - __arm1020e_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm1020.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1020.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm1020.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1020.S	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@
  * cpu_arm1020_proc_init()
  */
 ENTRY(cpu_arm1020_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1020_proc_fin()
@@ -83,7 +83,7 @@ ENTRY(cpu_arm1020_proc_fin)
 	bic	r0, r0, #0x1000 		@ ...i............
 	bic	r0, r0, #0x000e 		@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1020_reset(loc)
@@ -107,7 +107,7 @@ ENTRY(cpu_arm1020_reset)
 	bic	ip, ip, #0x000f 		@ ............wcam
 	bic	ip, ip, #0x1100 		@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm1020_reset)
 	.popsection
 
@@ -117,7 +117,7 @@ ENDPROC(cpu_arm1020_reset)
 	.align	5
 ENTRY(cpu_arm1020_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -133,7 +133,7 @@ ENTRY(arm1020_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1020_flush_icache_all)
 
 /*
@@ -169,7 +169,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -200,7 +200,7 @@ ENTRY(arm1020_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -242,7 +242,7 @@ ENTRY(arm1020_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -264,7 +264,7 @@ ENTRY(arm1020_flush_kern_dcache_area)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -297,7 +297,7 @@ arm1020_dma_inv_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -320,7 +320,7 @@ arm1020_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -342,7 +342,7 @@ ENTRY(arm1020_dma_flush_range)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -365,7 +365,7 @@ ENDPROC(arm1020_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm1020_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1020_dma_unmap_area)
 
 	.globl	arm1020_flush_kern_cache_louis
@@ -384,7 +384,7 @@ ENTRY(cpu_arm1020_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -423,7 +423,7 @@ ENTRY(cpu_arm1020_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
         
 /*
  * cpu_arm1020_set_pte(ptep, pte)
@@ -441,7 +441,7 @@ ENTRY(cpu_arm1020_set_pte_ext)
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm1020_setup, #function
 __arm1020_setup:
@@ -460,7 +460,7 @@ __arm1020_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .R.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm1020_setup, . - __arm1020_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm1022.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1022.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm1022.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1022.S	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@
  * cpu_arm1022_proc_init()
  */
 ENTRY(cpu_arm1022_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1022_proc_fin()
@@ -72,7 +72,7 @@ ENTRY(cpu_arm1022_proc_fin)
 	bic	r0, r0, #0x1000 		@ ...i............
 	bic	r0, r0, #0x000e 		@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1022_reset(loc)
@@ -96,7 +96,7 @@ ENTRY(cpu_arm1022_reset)
 	bic	ip, ip, #0x000f 		@ ............wcam
 	bic	ip, ip, #0x1100 		@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm1022_reset)
 	.popsection
 
@@ -106,7 +106,7 @@ ENDPROC(cpu_arm1022_reset)
 	.align	5
 ENTRY(cpu_arm1022_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -122,7 +122,7 @@ ENTRY(arm1022_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1022_flush_icache_all)
 
 /*
@@ -156,7 +156,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -185,7 +185,7 @@ ENTRY(arm1022_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -225,7 +225,7 @@ ENTRY(arm1022_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -246,7 +246,7 @@ ENTRY(arm1022_flush_kern_dcache_area)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -275,7 +275,7 @@ arm1022_dma_inv_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -297,7 +297,7 @@ arm1022_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -317,7 +317,7 @@ ENTRY(arm1022_dma_flush_range)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -340,7 +340,7 @@ ENDPROC(arm1022_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm1022_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1022_dma_unmap_area)
 
 	.globl	arm1022_flush_kern_cache_louis
@@ -358,7 +358,7 @@ ENTRY(cpu_arm1022_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -389,7 +389,7 @@ ENTRY(cpu_arm1022_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
         
 /*
  * cpu_arm1022_set_pte_ext(ptep, pte, ext)
@@ -405,7 +405,7 @@ ENTRY(cpu_arm1022_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm1022_setup, #function
 __arm1022_setup:
@@ -423,7 +423,7 @@ __arm1022_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .R..............
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm1022_setup, . - __arm1022_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm1026.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1026.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm1026.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm1026.S	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@
  * cpu_arm1026_proc_init()
  */
 ENTRY(cpu_arm1026_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1026_proc_fin()
@@ -72,7 +72,7 @@ ENTRY(cpu_arm1026_proc_fin)
 	bic	r0, r0, #0x1000 		@ ...i............
 	bic	r0, r0, #0x000e 		@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm1026_reset(loc)
@@ -96,7 +96,7 @@ ENTRY(cpu_arm1026_reset)
 	bic	ip, ip, #0x000f 		@ ............wcam
 	bic	ip, ip, #0x1100 		@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm1026_reset)
 	.popsection
 
@@ -106,7 +106,7 @@ ENDPROC(cpu_arm1026_reset)
 	.align	5
 ENTRY(cpu_arm1026_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -122,7 +122,7 @@ ENTRY(arm1026_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1026_flush_icache_all)
 
 /*
@@ -151,7 +151,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -180,7 +180,7 @@ ENTRY(arm1026_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -219,7 +219,7 @@ ENTRY(arm1026_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -240,7 +240,7 @@ ENTRY(arm1026_flush_kern_dcache_area)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -269,7 +269,7 @@ arm1026_dma_inv_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -291,7 +291,7 @@ arm1026_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -311,7 +311,7 @@ ENTRY(arm1026_dma_flush_range)
 	blo	1b
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -334,7 +334,7 @@ ENDPROC(arm1026_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm1026_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm1026_dma_unmap_area)
 
 	.globl	arm1026_flush_kern_cache_louis
@@ -352,7 +352,7 @@ ENTRY(cpu_arm1026_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -378,7 +378,7 @@ ENTRY(cpu_arm1026_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
         
 /*
  * cpu_arm1026_set_pte_ext(ptep, pte, ext)
@@ -394,7 +394,7 @@ ENTRY(cpu_arm1026_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm1026_setup, #function
 __arm1026_setup:
@@ -417,7 +417,7 @@ __arm1026_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .R.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm1026_setup, . - __arm1026_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm720.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm720.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm720.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm720.S	2014-09-28 17:29:07.000000000 -0400
@@ -51,14 +51,14 @@
  */
 ENTRY(cpu_arm720_dcache_clean_area)
 ENTRY(cpu_arm720_proc_init)
-		mov	pc, lr
+		ret	lr
 
 ENTRY(cpu_arm720_proc_fin)
 		mrc	p15, 0, r0, c1, c0, 0
 		bic	r0, r0, #0x1000			@ ...i............
 		bic	r0, r0, #0x000e			@ ............wca.
 		mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-		mov	pc, lr
+		ret	lr
 
 /*
  * Function: arm720_proc_do_idle(void)
@@ -66,7 +66,7 @@ ENTRY(cpu_arm720_proc_fin)
  * Purpose : put the processor in proper idle mode
  */
 ENTRY(cpu_arm720_do_idle)
-		mov	pc, lr
+		ret	lr
 
 /*
  * Function: arm720_switch_mm(unsigned long pgd_phys)
@@ -81,7 +81,7 @@ ENTRY(cpu_arm720_switch_mm)
 		mcr	p15, 0, r0, c2, c0, 0		@ update page table ptr
 		mcr	p15, 0, r1, c8, c7, 0		@ flush TLB (v4)
 #endif
-		mov	pc, lr
+		ret	lr
 
 /*
  * Function: arm720_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext)
@@ -94,7 +94,7 @@ ENTRY(cpu_arm720_set_pte_ext)
 #ifdef CONFIG_MMU
 	armv3_set_pte_ext wc_disable=0
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * Function: arm720_reset
@@ -112,7 +112,7 @@ ENTRY(cpu_arm720_reset)
 		bic	ip, ip, #0x000f			@ ............wcam
 		bic	ip, ip, #0x2100			@ ..v....s........
 		mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-		mov	pc, r0
+		ret	r0
 ENDPROC(cpu_arm720_reset)
 		.popsection
 
@@ -128,7 +128,7 @@ __arm710_setup:
 	bic	r0, r0, r5
 	ldr	r5, arm710_cr1_set
 	orr	r0, r0, r5
-	mov	pc, lr				@ __ret (head.S)
+	ret	lr				@ __ret (head.S)
 	.size	__arm710_setup, . - __arm710_setup
 
 	/*
@@ -156,7 +156,7 @@ __arm720_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr				@ __ret (head.S)
+	ret	lr				@ __ret (head.S)
 	.size	__arm720_setup, . - __arm720_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm740.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm740.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm740.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm740.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@ ENTRY(cpu_arm740_proc_init)
 ENTRY(cpu_arm740_do_idle)
 ENTRY(cpu_arm740_dcache_clean_area)
 ENTRY(cpu_arm740_switch_mm)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm740_proc_fin()
@@ -42,7 +42,7 @@ ENTRY(cpu_arm740_proc_fin)
 	bic	r0, r0, #0x3f000000		@ bank/f/lock/s
 	bic	r0, r0, #0x0000000c		@ w-buffer/cache
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm740_reset(loc)
@@ -56,7 +56,7 @@ ENTRY(cpu_arm740_reset)
 	mrc	p15, 0, ip, c1, c0, 0		@ get ctrl register
 	bic	ip, ip, #0x0000000c		@ ............wc..
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm740_reset)
 	.popsection
 
@@ -115,7 +115,7 @@ __arm740_setup:
 						@ need some benchmark
 	orr	r0, r0, #0x0000000d		@ MPU/Cache/WB
 
-	mov	pc, lr
+	ret	lr
 
 	.size	__arm740_setup, . - __arm740_setup
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm7tdmi.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm7tdmi.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm7tdmi.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm7tdmi.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,13 +32,13 @@ ENTRY(cpu_arm7tdmi_proc_init)
 ENTRY(cpu_arm7tdmi_do_idle)
 ENTRY(cpu_arm7tdmi_dcache_clean_area)
 ENTRY(cpu_arm7tdmi_switch_mm)
-		mov	pc, lr
+		ret	lr
 
 /*
  * cpu_arm7tdmi_proc_fin()
  */
 ENTRY(cpu_arm7tdmi_proc_fin)
-		mov	pc, lr
+		ret	lr
 
 /*
  * Function: cpu_arm7tdmi_reset(loc)
@@ -47,13 +47,13 @@ ENTRY(cpu_arm7tdmi_proc_fin)
  */
 		.pushsection	.idmap.text, "ax"
 ENTRY(cpu_arm7tdmi_reset)
-		mov	pc, r0
+		ret	r0
 ENDPROC(cpu_arm7tdmi_reset)
 		.popsection
 
 		.type	__arm7tdmi_setup, #function
 __arm7tdmi_setup:
-		mov	pc, lr
+		ret	lr
 		.size	__arm7tdmi_setup, . - __arm7tdmi_setup
 
 		__INITDATA
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm920.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm920.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm920.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm920.S	2014-09-28 17:29:07.000000000 -0400
@@ -63,7 +63,7 @@
  * cpu_arm920_proc_init()
  */
 ENTRY(cpu_arm920_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm920_proc_fin()
@@ -73,7 +73,7 @@ ENTRY(cpu_arm920_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm920_reset(loc)
@@ -97,7 +97,7 @@ ENTRY(cpu_arm920_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm920_reset)
 	.popsection
 
@@ -107,7 +107,7 @@ ENDPROC(cpu_arm920_reset)
 	.align	5
 ENTRY(cpu_arm920_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -120,7 +120,7 @@ ENTRY(cpu_arm920_do_idle)
 ENTRY(arm920_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm920_flush_icache_all)
 
 /*
@@ -151,7 +151,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -177,7 +177,7 @@ ENTRY(arm920_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -211,7 +211,7 @@ ENTRY(arm920_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -231,7 +231,7 @@ ENTRY(arm920_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -257,7 +257,7 @@ arm920_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -276,7 +276,7 @@ arm920_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -293,7 +293,7 @@ ENTRY(arm920_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -316,7 +316,7 @@ ENDPROC(arm920_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm920_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm920_dma_unmap_area)
 
 	.globl	arm920_flush_kern_cache_louis
@@ -332,7 +332,7 @@ ENTRY(cpu_arm920_dcache_clean_area)
 	add	r0, r0, #CACHE_DLINESIZE
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -367,7 +367,7 @@ ENTRY(cpu_arm920_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm920_set_pte(ptep, pte, ext)
@@ -382,7 +382,7 @@ ENTRY(cpu_arm920_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm920_suspend_size
@@ -423,7 +423,7 @@ __arm920_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__arm920_setup, . - __arm920_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm922.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm922.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm922.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm922.S	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@
  * cpu_arm922_proc_init()
  */
 ENTRY(cpu_arm922_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm922_proc_fin()
@@ -75,7 +75,7 @@ ENTRY(cpu_arm922_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm922_reset(loc)
@@ -99,7 +99,7 @@ ENTRY(cpu_arm922_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm922_reset)
 	.popsection
 
@@ -109,7 +109,7 @@ ENDPROC(cpu_arm922_reset)
 	.align	5
 ENTRY(cpu_arm922_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -122,7 +122,7 @@ ENTRY(cpu_arm922_do_idle)
 ENTRY(arm922_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm922_flush_icache_all)
 
 /*
@@ -153,7 +153,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -179,7 +179,7 @@ ENTRY(arm922_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -213,7 +213,7 @@ ENTRY(arm922_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -233,7 +233,7 @@ ENTRY(arm922_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -259,7 +259,7 @@ arm922_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -278,7 +278,7 @@ arm922_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -295,7 +295,7 @@ ENTRY(arm922_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -318,7 +318,7 @@ ENDPROC(arm922_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm922_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm922_dma_unmap_area)
 
 	.globl	arm922_flush_kern_cache_louis
@@ -336,7 +336,7 @@ ENTRY(cpu_arm922_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -371,7 +371,7 @@ ENTRY(cpu_arm922_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm922_set_pte_ext(ptep, pte, ext)
@@ -386,7 +386,7 @@ ENTRY(cpu_arm922_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm922_setup, #function
 __arm922_setup:
@@ -401,7 +401,7 @@ __arm922_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__arm922_setup, . - __arm922_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm925.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm925.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm925.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm925.S	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@
  * cpu_arm925_proc_init()
  */
 ENTRY(cpu_arm925_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm925_proc_fin()
@@ -96,7 +96,7 @@ ENTRY(cpu_arm925_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm925_reset(loc)
@@ -129,7 +129,7 @@ ENDPROC(cpu_arm925_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 
 /*
  * cpu_arm925_do_idle()
@@ -145,7 +145,7 @@ ENTRY(cpu_arm925_do_idle)
 	mcr	p15, 0, r2, c1, c0, 0		@ Disable I cache
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
 	mcr	p15, 0, r1, c1, c0, 0		@ Restore ICache enable
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -155,7 +155,7 @@ ENTRY(cpu_arm925_do_idle)
 ENTRY(arm925_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm925_flush_icache_all)
 
 /*
@@ -188,7 +188,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -225,7 +225,7 @@ ENTRY(arm925_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -259,7 +259,7 @@ ENTRY(arm925_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -279,7 +279,7 @@ ENTRY(arm925_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -307,7 +307,7 @@ arm925_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -328,7 +328,7 @@ arm925_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -350,7 +350,7 @@ ENTRY(arm925_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -373,7 +373,7 @@ ENDPROC(arm925_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm925_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm925_dma_unmap_area)
 
 	.globl	arm925_flush_kern_cache_louis
@@ -390,7 +390,7 @@ ENTRY(cpu_arm925_dcache_clean_area)
 	bhi	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -419,7 +419,7 @@ ENTRY(cpu_arm925_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm925_set_pte_ext(ptep, pte, ext)
@@ -436,7 +436,7 @@ ENTRY(cpu_arm925_set_pte_ext)
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif /* CONFIG_MMU */
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm925_setup, #function
 __arm925_setup:
@@ -469,7 +469,7 @@ __arm925_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000			@ .1.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm925_setup, . - __arm925_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm926.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm926.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm926.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm926.S	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,7 @@
  * cpu_arm926_proc_init()
  */
 ENTRY(cpu_arm926_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm926_proc_fin()
@@ -65,7 +65,7 @@ ENTRY(cpu_arm926_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm926_reset(loc)
@@ -89,7 +89,7 @@ ENTRY(cpu_arm926_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm926_reset)
 	.popsection
 
@@ -111,7 +111,7 @@ ENTRY(cpu_arm926_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
 	mcr	p15, 0, r1, c1, c0, 0		@ Restore ICache enable
 	msr	cpsr_c, r3			@ Restore FIQ state
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -121,7 +121,7 @@ ENTRY(cpu_arm926_do_idle)
 ENTRY(arm926_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm926_flush_icache_all)
 
 /*
@@ -151,7 +151,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -188,7 +188,7 @@ ENTRY(arm926_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -222,7 +222,7 @@ ENTRY(arm926_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -242,7 +242,7 @@ ENTRY(arm926_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -270,7 +270,7 @@ arm926_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -291,7 +291,7 @@ arm926_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -313,7 +313,7 @@ ENTRY(arm926_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -336,7 +336,7 @@ ENDPROC(arm926_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm926_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm926_dma_unmap_area)
 
 	.globl	arm926_flush_kern_cache_louis
@@ -353,7 +353,7 @@ ENTRY(cpu_arm926_dcache_clean_area)
 	bhi	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -380,7 +380,7 @@ ENTRY(cpu_arm926_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm926_set_pte_ext(ptep, pte, ext)
@@ -397,7 +397,7 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm926_suspend_size
@@ -448,7 +448,7 @@ __arm926_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000			@ .1.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 	.size	__arm926_setup, . - __arm926_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm940.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm940.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm940.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm940.S	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@
  */
 ENTRY(cpu_arm940_proc_init)
 ENTRY(cpu_arm940_switch_mm)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm940_proc_fin()
@@ -41,7 +41,7 @@ ENTRY(cpu_arm940_proc_fin)
 	bic	r0, r0, #0x00001000		@ i-cache
 	bic	r0, r0, #0x00000004		@ d-cache
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm940_reset(loc)
@@ -58,7 +58,7 @@ ENTRY(cpu_arm940_reset)
 	bic	ip, ip, #0x00000005		@ .............c.p
 	bic	ip, ip, #0x00001000		@ i-cache
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm940_reset)
 	.popsection
 
@@ -68,7 +68,7 @@ ENDPROC(cpu_arm940_reset)
 	.align	5
 ENTRY(cpu_arm940_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -78,7 +78,7 @@ ENTRY(cpu_arm940_do_idle)
 ENTRY(arm940_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm940_flush_icache_all)
 
 /*
@@ -122,7 +122,7 @@ ENTRY(arm940_flush_user_cache_range)
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -170,7 +170,7 @@ ENTRY(arm940_flush_kern_dcache_area)
 	bcs	1b				@ segments 7 to 0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -191,7 +191,7 @@ arm940_dma_inv_range:
 	subs	r1, r1, #1 << 4
 	bcs	1b				@ segments 7 to 0
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -215,7 +215,7 @@ ENTRY(cpu_arm940_dcache_clean_area)
 	bcs	1b				@ segments 7 to 0
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -241,7 +241,7 @@ ENTRY(arm940_dma_flush_range)
 	subs	r1, r1, #1 << 4
 	bcs	1b				@ segments 7 to 0
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -264,7 +264,7 @@ ENDPROC(arm940_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm940_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm940_dma_unmap_area)
 
 	.globl	arm940_flush_kern_cache_louis
@@ -337,7 +337,7 @@ __arm940_setup:
 	orr	r0, r0, #0x00001000		@ I-cache
 	orr	r0, r0, #0x00000005		@ MPU/D-cache
 
-	mov	pc, lr
+	ret	lr
 
 	.size	__arm940_setup, . - __arm940_setup
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm946.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm946.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm946.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm946.S	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
  */
 ENTRY(cpu_arm946_proc_init)
 ENTRY(cpu_arm946_switch_mm)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm946_proc_fin()
@@ -48,7 +48,7 @@ ENTRY(cpu_arm946_proc_fin)
 	bic	r0, r0, #0x00001000		@ i-cache
 	bic	r0, r0, #0x00000004		@ d-cache
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_arm946_reset(loc)
@@ -65,7 +65,7 @@ ENTRY(cpu_arm946_reset)
 	bic	ip, ip, #0x00000005		@ .............c.p
 	bic	ip, ip, #0x00001000		@ i-cache
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_arm946_reset)
 	.popsection
 
@@ -75,7 +75,7 @@ ENDPROC(cpu_arm946_reset)
 	.align	5
 ENTRY(cpu_arm946_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -85,7 +85,7 @@ ENTRY(cpu_arm946_do_idle)
 ENTRY(arm946_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm946_flush_icache_all)
 
 /*
@@ -117,7 +117,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ flush I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -156,7 +156,7 @@ ENTRY(arm946_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -191,7 +191,7 @@ ENTRY(arm946_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -212,7 +212,7 @@ ENTRY(arm946_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -239,7 +239,7 @@ arm946_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -260,7 +260,7 @@ arm946_dma_clean_range:
 	blo	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -284,7 +284,7 @@ ENTRY(arm946_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -307,7 +307,7 @@ ENDPROC(arm946_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(arm946_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(arm946_dma_unmap_area)
 
 	.globl	arm946_flush_kern_cache_louis
@@ -324,7 +324,7 @@ ENTRY(cpu_arm946_dcache_clean_area)
 	bhi	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 	.type	__arm946_setup, #function
 __arm946_setup:
@@ -392,7 +392,7 @@ __arm946_setup:
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x00004000		@ .1.. .... .... ....
 #endif
-	mov	pc, lr
+	ret	lr
 
 	.size	__arm946_setup, . - __arm946_setup
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-arm9tdmi.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm9tdmi.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-arm9tdmi.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-arm9tdmi.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,13 +32,13 @@ ENTRY(cpu_arm9tdmi_proc_init)
 ENTRY(cpu_arm9tdmi_do_idle)
 ENTRY(cpu_arm9tdmi_dcache_clean_area)
 ENTRY(cpu_arm9tdmi_switch_mm)
-		mov	pc, lr
+		ret	lr
 
 /*
  * cpu_arm9tdmi_proc_fin()
  */
 ENTRY(cpu_arm9tdmi_proc_fin)
-		mov	pc, lr
+		ret	lr
 
 /*
  * Function: cpu_arm9tdmi_reset(loc)
@@ -47,13 +47,13 @@ ENTRY(cpu_arm9tdmi_proc_fin)
  */
 		.pushsection	.idmap.text, "ax"
 ENTRY(cpu_arm9tdmi_reset)
-		mov	pc, r0
+		ret	r0
 ENDPROC(cpu_arm9tdmi_reset)
 		.popsection
 
 		.type	__arm9tdmi_setup, #function
 __arm9tdmi_setup:
-		mov	pc, lr
+		ret	lr
 		.size	__arm9tdmi_setup, . - __arm9tdmi_setup
 
 		__INITDATA
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-fa526.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-fa526.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-fa526.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-fa526.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@
  * cpu_fa526_proc_init()
  */
 ENTRY(cpu_fa526_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_fa526_proc_fin()
@@ -44,7 +44,7 @@ ENTRY(cpu_fa526_proc_fin)
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
 	nop
 	nop
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_fa526_reset(loc)
@@ -72,7 +72,7 @@ ENTRY(cpu_fa526_reset)
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
 	nop
 	nop
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_fa526_reset)
 	.popsection
 
@@ -81,7 +81,7 @@ ENDPROC(cpu_fa526_reset)
  */
 	.align	4
 ENTRY(cpu_fa526_do_idle)
-	mov	pc, lr
+	ret	lr
 
 
 ENTRY(cpu_fa526_dcache_clean_area)
@@ -90,7 +90,7 @@ ENTRY(cpu_fa526_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -117,7 +117,7 @@ ENTRY(cpu_fa526_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate UTLB
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_fa526_set_pte_ext(ptep, pte, ext)
@@ -133,7 +133,7 @@ ENTRY(cpu_fa526_set_pte_ext)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 	.type	__fa526_setup, #function
 __fa526_setup:
@@ -162,7 +162,7 @@ __fa526_setup:
 	bic	r0, r0, r5
 	ldr	r5, fa526_cr1_set
 	orr	r0, r0, r5
-	mov	pc, lr
+	ret	lr
 	.size	__fa526_setup, . - __fa526_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-feroceon.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-feroceon.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-feroceon.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-feroceon.S	2014-09-28 17:29:07.000000000 -0400
@@ -69,7 +69,7 @@ ENTRY(cpu_feroceon_proc_init)
 	movne	r2, r2, lsr #2			@ turned into # of sets
 	sub	r2, r2, #(1 << 5)
 	stmia	r1, {r2, r3}
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_feroceon_proc_fin()
@@ -86,7 +86,7 @@ ENTRY(cpu_feroceon_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_feroceon_reset(loc)
@@ -110,7 +110,7 @@ ENTRY(cpu_feroceon_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_feroceon_reset)
 	.popsection
 
@@ -124,7 +124,7 @@ ENTRY(cpu_feroceon_do_idle)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -134,7 +134,7 @@ ENTRY(cpu_feroceon_do_idle)
 ENTRY(feroceon_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(feroceon_flush_icache_all)
 
 /*
@@ -169,7 +169,7 @@ __flush_whole_cache:
 	mov	ip, #0
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -198,7 +198,7 @@ ENTRY(feroceon_flush_user_cache_range)
 	tst	r2, #VM_EXEC
 	mov	ip, #0
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -233,7 +233,7 @@ ENTRY(feroceon_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -254,7 +254,7 @@ ENTRY(feroceon_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 	.align	5
 ENTRY(feroceon_range_flush_kern_dcache_area)
@@ -268,7 +268,7 @@ ENTRY(feroceon_range_flush_kern_dcache_a
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -295,7 +295,7 @@ feroceon_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 	.align	5
 feroceon_range_dma_inv_range:
@@ -311,7 +311,7 @@ feroceon_range_dma_inv_range:
 	mcr	p15, 5, r0, c15, c14, 0		@ D inv range start
 	mcr	p15, 5, r1, c15, c14, 1		@ D inv range top
 	msr	cpsr_c, r2			@ restore interrupts
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -331,7 +331,7 @@ feroceon_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 	.align	5
 feroceon_range_dma_clean_range:
@@ -344,7 +344,7 @@ feroceon_range_dma_clean_range:
 	mcr	p15, 5, r1, c15, c13, 1		@ D clean range top
 	msr	cpsr_c, r2			@ restore interrupts
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -362,7 +362,7 @@ ENTRY(feroceon_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 	.align	5
 ENTRY(feroceon_range_dma_flush_range)
@@ -375,7 +375,7 @@ ENTRY(feroceon_range_dma_flush_range)
 	mcr	p15, 5, r1, c15, c15, 1		@ D clean/inv range top
 	msr	cpsr_c, r2			@ restore interrupts
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -412,7 +412,7 @@ ENDPROC(feroceon_range_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(feroceon_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(feroceon_dma_unmap_area)
 
 	.globl	feroceon_flush_kern_cache_louis
@@ -461,7 +461,7 @@ ENTRY(cpu_feroceon_dcache_clean_area)
 	bhi	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -490,9 +490,9 @@ ENTRY(cpu_feroceon_switch_mm)
 
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, r2
+	ret	r2
 #else
-	mov	pc, lr
+	ret	lr
 #endif
 
 /*
@@ -512,7 +512,7 @@ ENTRY(cpu_feroceon_set_pte_ext)
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* Suspend/resume support: taken from arch/arm/mm/proc-arm926.S */
 .globl	cpu_feroceon_suspend_size
@@ -554,7 +554,7 @@ __feroceon_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__feroceon_setup, . - __feroceon_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-mohawk.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-mohawk.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-mohawk.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-mohawk.S	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@
  * cpu_mohawk_proc_init()
  */
 ENTRY(cpu_mohawk_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_mohawk_proc_fin()
@@ -55,7 +55,7 @@ ENTRY(cpu_mohawk_proc_fin)
 	bic	r0, r0, #0x1800			@ ...iz...........
 	bic	r0, r0, #0x0006			@ .............ca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_mohawk_reset(loc)
@@ -79,7 +79,7 @@ ENTRY(cpu_mohawk_reset)
 	bic	ip, ip, #0x0007			@ .............cam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_mohawk_reset)
 	.popsection
 
@@ -93,7 +93,7 @@ ENTRY(cpu_mohawk_do_idle)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r0, c7, c0, 4		@ wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_icache_all()
@@ -103,7 +103,7 @@ ENTRY(cpu_mohawk_do_idle)
 ENTRY(mohawk_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(mohawk_flush_icache_all)
 
 /*
@@ -128,7 +128,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 	mcrne	p15, 0, ip, c7, c10, 0		@ drain write buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -158,7 +158,7 @@ ENTRY(mohawk_flush_user_cache_range)
 	blo	1b
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -194,7 +194,7 @@ ENTRY(mohawk_coherent_user_range)
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	r0, #0
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -214,7 +214,7 @@ ENTRY(mohawk_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -240,7 +240,7 @@ mohawk_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -259,7 +259,7 @@ mohawk_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -277,7 +277,7 @@ ENTRY(mohawk_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -300,7 +300,7 @@ ENDPROC(mohawk_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(mohawk_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(mohawk_dma_unmap_area)
 
 	.globl	mohawk_flush_kern_cache_louis
@@ -315,7 +315,7 @@ ENTRY(cpu_mohawk_dcache_clean_area)
 	subs	r1, r1, #CACHE_DLINESIZE
 	bhi	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_mohawk_switch_mm(pgd)
@@ -333,7 +333,7 @@ ENTRY(cpu_mohawk_switch_mm)
 	orr	r0, r0, #0x18			@ cache the page table in L2
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_mohawk_set_pte_ext(ptep, pte, ext)
@@ -346,7 +346,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
 	mov	r0, r0
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
+	ret	lr
 
 .globl	cpu_mohawk_suspend_size
 .equ	cpu_mohawk_suspend_size, 4 * 6
@@ -400,7 +400,7 @@ __mohawk_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 
 	.size	__mohawk_setup, . - __mohawk_setup
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-sa1100.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-sa1100.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-sa1100.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-sa1100.S	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@ ENTRY(cpu_sa1100_proc_init)
 	mov	r0, #0
 	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
 	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_sa1100_proc_fin()
@@ -58,7 +58,7 @@ ENTRY(cpu_sa1100_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_sa1100_reset(loc)
@@ -82,7 +82,7 @@ ENTRY(cpu_sa1100_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_sa1100_reset)
 	.popsection
 
@@ -113,7 +113,7 @@ ENTRY(cpu_sa1100_do_idle)
 	mcr	p15, 0, r0, c15, c8, 2		@ wait for interrupt
 	mov	r0, r0				@ safety
 	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -131,7 +131,7 @@ ENTRY(cpu_sa1100_dcache_clean_area)
 	add	r0, r0, #DCACHELINESIZE
 	subs	r1, r1, #DCACHELINESIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -152,7 +152,7 @@ ENTRY(cpu_sa1100_switch_mm)
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 	ldr	pc, [sp], #4
 #else
-	mov	pc, lr
+	ret	lr
 #endif
 
 /*
@@ -168,7 +168,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 .globl	cpu_sa1100_suspend_size
 .equ	cpu_sa1100_suspend_size, 4 * 3
@@ -211,7 +211,7 @@ __sa1100_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__sa1100_setup, . - __sa1100_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-sa110.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-sa110.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-sa110.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-sa110.S	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
 ENTRY(cpu_sa110_proc_init)
 	mov	r0, #0
 	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_sa110_proc_fin()
@@ -50,7 +50,7 @@ ENTRY(cpu_sa110_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_sa110_reset(loc)
@@ -74,7 +74,7 @@ ENTRY(cpu_sa110_reset)
 	bic	ip, ip, #0x000f			@ ............wcam
 	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_sa110_reset)
 	.popsection
 
@@ -103,7 +103,7 @@ ENTRY(cpu_sa110_do_idle)
 	mov	r0, r0				@ safety
 	mov	r0, r0				@ safety
 	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -121,7 +121,7 @@ ENTRY(cpu_sa110_dcache_clean_area)
 	add	r0, r0, #DCACHELINESIZE
 	subs	r1, r1, #DCACHELINESIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -141,7 +141,7 @@ ENTRY(cpu_sa110_switch_mm)
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 	ldr	pc, [sp], #4
 #else
-	mov	pc, lr
+	ret	lr
 #endif
 
 /*
@@ -157,7 +157,7 @@ ENTRY(cpu_sa110_set_pte_ext)
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-	mov	pc, lr
+	ret	lr
 
 	.type	__sa110_setup, #function
 __sa110_setup:
@@ -173,7 +173,7 @@ __sa110_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__sa110_setup, . - __sa110_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-v6.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v6.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-v6.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v6.S	2014-09-28 17:29:07.000000000 -0400
@@ -36,14 +36,14 @@
 #define PMD_FLAGS_SMP	PMD_SECT_WBWA|PMD_SECT_S
 
 ENTRY(cpu_v6_proc_init)
-	mov	pc, lr
+	ret	lr
 
 ENTRY(cpu_v6_proc_fin)
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x0006			@ .............ca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  *	cpu_v6_reset(loc)
@@ -62,7 +62,7 @@ ENTRY(cpu_v6_reset)
 	mcr	p15, 0, r1, c1, c0, 0		@ disable MMU
 	mov	r1, #0
 	mcr	p15, 0, r1, c7, c5, 4		@ ISB
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_v6_reset)
 	.popsection
 
@@ -77,14 +77,14 @@ ENTRY(cpu_v6_do_idle)
 	mov	r1, #0
 	mcr	p15, 0, r1, c7, c10, 4		@ DWB - WFI may enter a low-power mode
 	mcr	p15, 0, r1, c7, c0, 4		@ wait for interrupt
-	mov	pc, lr
+	ret	lr
 
 ENTRY(cpu_v6_dcache_clean_area)
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #D_CACHE_LINE_SIZE
 	subs	r1, r1, #D_CACHE_LINE_SIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /*
  *	cpu_v6_switch_mm(pgd_phys, tsk)
@@ -113,7 +113,7 @@ ENTRY(cpu_v6_switch_mm)
 #endif
 	mcr	p15, 0, r1, c13, c0, 1		@ set context ID
 #endif
-	mov	pc, lr
+	ret	lr
 
 /*
  *	cpu_v6_set_pte_ext(ptep, pte, ext)
@@ -131,7 +131,7 @@ ENTRY(cpu_v6_set_pte_ext)
 #ifdef CONFIG_MMU
 	armv6_set_pte_ext cpu_v6
 #endif
-	mov	pc, lr
+	ret	lr
 
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
@@ -241,7 +241,7 @@ __v6_setup:
 	mcreq	p15, 0, r5, c1, c0, 1		@ write aux control reg
 	orreq	r0, r0, #(1 << 21)		@ low interrupt latency configuration
 #endif
-	mov	pc, lr				@ return to head.S:__ret
+	ret	lr				@ return to head.S:__ret
 
 	/*
 	 *         V X F   I D LR
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-v7-2level.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7-2level.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-v7-2level.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7-2level.S	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ ENTRY(cpu_v7_switch_mm)
 	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
 	isb
 #endif
-	mov	pc, lr
+	bx	lr
 ENDPROC(cpu_v7_switch_mm)
 
 /*
@@ -106,7 +106,7 @@ ENTRY(cpu_v7_set_pte_ext)
 	ALT_SMP(W(nop))
 	ALT_UP (mcr	p15, 0, r0, c7, c10, 1)		@ flush_pte
 #endif
-	mov	pc, lr
+	bx	lr
 ENDPROC(cpu_v7_set_pte_ext)
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-v7-3level.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7-3level.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-v7-3level.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7-3level.S	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
+#include <asm/assembler.h>
 
 #define TTB_IRGN_NC	(0 << 8)
 #define TTB_IRGN_WBWA	(1 << 8)
@@ -61,7 +62,7 @@ ENTRY(cpu_v7_switch_mm)
 	mcrr	p15, 0, rpgdl, rpgdh, c2		@ set TTB 0
 	isb
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_switch_mm)
 
 #ifdef __ARMEB__
@@ -86,13 +87,18 @@ ENTRY(cpu_v7_set_pte_ext)
 	tst	rh, #1 << (57 - 32)		@ L_PTE_NONE
 	bicne	rl, #L_PTE_VALID
 	bne	1f
-	tst	rh, #1 << (55 - 32)		@ L_PTE_DIRTY
-	orreq	rl, #L_PTE_RDONLY
+
+	eor	ip, rh, #1 << (55 - 32)	@ toggle L_PTE_DIRTY in temp reg to
+					@ test for !L_PTE_DIRTY || L_PTE_RDONLY
+	tst	ip, #1 << (55 - 32) | 1 << (58 - 32)
+	orrne	rl, #PTE_AP2
+	biceq	rl, #PTE_AP2
+
 1:	strd	r2, r3, [r0]
 	ALT_SMP(W(nop))
 	ALT_UP (mcr	p15, 0, r0, c7, c10, 1)		@ flush_pte
 #endif
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_set_pte_ext)
 
 	/*
@@ -140,12 +146,10 @@ ENDPROC(cpu_v7_set_pte_ext)
 	mov	\tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT)	@ upper bits
 	mov	\ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT		@ lower bits
 	addls	\ttbr1, \ttbr1, #TTBR1_OFFSET
-	mcrr	p15, 1, \ttbr1, \zero, c2			@ load TTBR1
+	mcrr	p15, 1, \ttbr1, \tmp, c2			@ load TTBR1
 	mov	\tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT)	@ upper bits
 	mov	\ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT		@ lower bits
-	mcrr	p15, 0, \ttbr0, \zero, c2			@ load TTBR0
-	mcrr	p15, 1, \ttbr1, \zero, c2			@ load TTBR1
-	mcrr	p15, 0, \ttbr0, \zero, c2			@ load TTBR0
+	mcrr	p15, 0, \ttbr0, \tmp, c2			@ load TTBR0
 	.endm
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-v7m.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7m.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-v7m.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7m.S	2014-09-28 17:29:07.000000000 -0400
@@ -16,11 +16,11 @@
 #include "proc-macros.S"
 
 ENTRY(cpu_v7m_proc_init)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_proc_init)
 
 ENTRY(cpu_v7m_proc_fin)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_proc_fin)
 
 /*
@@ -34,7 +34,7 @@ ENDPROC(cpu_v7m_proc_fin)
  */
 	.align	5
 ENTRY(cpu_v7m_reset)
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_v7m_reset)
 
 /*
@@ -46,18 +46,18 @@ ENDPROC(cpu_v7m_reset)
  */
 ENTRY(cpu_v7m_do_idle)
 	wfi
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_do_idle)
 
 ENTRY(cpu_v7m_dcache_clean_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_dcache_clean_area)
 
 /*
  * There is no MMU, so here is nothing to do.
  */
 ENTRY(cpu_v7m_switch_mm)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_switch_mm)
 
 .globl	cpu_v7m_suspend_size
@@ -65,11 +65,11 @@ ENDPROC(cpu_v7m_switch_mm)
 
 #ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v7m_do_suspend)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_do_suspend)
 
 ENTRY(cpu_v7m_do_resume)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7m_do_resume)
 #endif
 
@@ -120,7 +120,7 @@ __v7m_setup:
 	ldr	r12, [r0, V7M_SCB_CCR]	@ system control register
 	orr	r12, #V7M_SCB_CCR_STKALIGN
 	str	r12, [r0, V7M_SCB_CCR]
-	mov	pc, lr
+	ret	lr
 ENDPROC(__v7m_setup)
 
 	.align 2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-v7.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-v7.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-v7.S	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 #endif
 
 ENTRY(cpu_v7_proc_init)
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_proc_init)
 
 ENTRY(cpu_v7_proc_fin)
@@ -34,7 +34,7 @@ ENTRY(cpu_v7_proc_fin)
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x0006			@ .............ca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_proc_fin)
 
 /*
@@ -71,20 +71,20 @@ ENDPROC(cpu_v7_reset)
 ENTRY(cpu_v7_do_idle)
 	dsb					@ WFI may enter a low-power mode
 	wfi
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_do_idle)
 
 ENTRY(cpu_v7_dcache_clean_area)
 	ALT_SMP(W(nop))			@ MP extensions imply L1 PTW
 	ALT_UP_B(1f)
-	mov	pc, lr
+	ret	lr
 1:	dcache_line_size r2, r3
 2:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, r2
 	subs	r1, r1, r2
 	bhi	2b
 	dsb	ishst
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_v7_dcache_clean_area)
 
 	string	cpu_v7_name, "ARMv7 Processor"
@@ -152,6 +152,40 @@ ENTRY(cpu_v7_do_resume)
 ENDPROC(cpu_v7_do_resume)
 #endif
 
+/*
+ * Cortex-A9 processor functions
+ */
+	globl_equ	cpu_ca9mp_proc_init,	cpu_v7_proc_init
+	globl_equ	cpu_ca9mp_proc_fin,	cpu_v7_proc_fin
+	globl_equ	cpu_ca9mp_reset,	cpu_v7_reset
+	globl_equ	cpu_ca9mp_do_idle,	cpu_v7_do_idle
+	globl_equ	cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area
+	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_switch_mm
+	globl_equ	cpu_ca9mp_set_pte_ext,	cpu_v7_set_pte_ext
+.globl	cpu_ca9mp_suspend_size
+.equ	cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2
+#ifdef CONFIG_ARM_CPU_SUSPEND
+ENTRY(cpu_ca9mp_do_suspend)
+	stmfd	sp!, {r4 - r5}
+	mrc	p15, 0, r4, c15, c0, 1		@ Diagnostic register
+	mrc	p15, 0, r5, c15, c0, 0		@ Power register
+	stmia	r0!, {r4 - r5}
+	ldmfd	sp!, {r4 - r5}
+	b	cpu_v7_do_suspend
+ENDPROC(cpu_ca9mp_do_suspend)
+
+ENTRY(cpu_ca9mp_do_resume)
+	ldmia	r0!, {r4 - r5}
+	mrc	p15, 0, r10, c15, c0, 1		@ Read Diagnostic register
+	teq	r4, r10				@ Already restored?
+	mcrne	p15, 0, r4, c15, c0, 1		@ No, so restore it
+	mrc	p15, 0, r10, c15, c0, 0		@ Read Power register
+	teq	r5, r10				@ Already restored?
+	mcrne	p15, 0, r5, c15, c0, 0		@ No, so restore it
+	b	cpu_v7_do_resume
+ENDPROC(cpu_ca9mp_do_resume)
+#endif
+
 #ifdef CONFIG_CPU_PJ4B
 	globl_equ	cpu_pj4b_switch_mm,     cpu_v7_switch_mm
 	globl_equ	cpu_pj4b_set_pte_ext,	cpu_v7_set_pte_ext
@@ -163,7 +197,7 @@ ENTRY(cpu_pj4b_do_idle)
 	dsb					@ WFI may enter a low-power mode
 	wfi
 	dsb					@barrier
-	mov	pc, lr
+	ret	lr
 ENDPROC(cpu_pj4b_do_idle)
 #else
 	globl_equ	cpu_pj4b_do_idle,  	cpu_v7_do_idle
@@ -184,16 +218,16 @@ ENDPROC(cpu_pj4b_do_suspend)
 
 ENTRY(cpu_pj4b_do_resume)
 	ldmia	r0!, {r6 - r10}
-	mcr	p15, 1, r6, c15, c1, 0  @ save CP15 - extra features
-	mcr	p15, 1, r7, c15, c2, 0	@ save CP15 - Aux Func Modes Ctrl 0
-	mcr	p15, 1, r8, c15, c1, 2	@ save CP15 - Aux Debug Modes Ctrl 2
-	mcr	p15, 1, r9, c15, c1, 1  @ save CP15 - Aux Debug Modes Ctrl 1
-	mcr	p15, 0, r10, c9, c14, 0  @ save CP15 - PMC
+	mcr	p15, 1, r6, c15, c1, 0  @ restore CP15 - extra features
+	mcr	p15, 1, r7, c15, c2, 0	@ restore CP15 - Aux Func Modes Ctrl 0
+	mcr	p15, 1, r8, c15, c1, 2	@ restore CP15 - Aux Debug Modes Ctrl 2
+	mcr	p15, 1, r9, c15, c1, 1  @ restore CP15 - Aux Debug Modes Ctrl 1
+	mcr	p15, 0, r10, c9, c14, 0  @ restore CP15 - PMC
 	b cpu_v7_do_resume
 ENDPROC(cpu_pj4b_do_resume)
 #endif
 .globl	cpu_pj4b_suspend_size
-.equ	cpu_pj4b_suspend_size, 4 * 14
+.equ	cpu_pj4b_suspend_size, cpu_v7_suspend_size + 4 * 5
 
 #endif
 
@@ -216,6 +250,7 @@ __v7_cr7mp_setup:
 __v7_ca7mp_setup:
 __v7_ca12mp_setup:
 __v7_ca15mp_setup:
+__v7_b15mp_setup:
 __v7_ca17mp_setup:
 	mov	r10, #0
 1:
@@ -407,7 +442,7 @@ __v7_setup:
 	bic	r0, r0, r5			@ clear bits them
 	orr	r0, r0, r6			@ set them
  THUMB(	orr	r0, r0, #1 << 30	)	@ Thumb exceptions
-	mov	pc, lr				@ return to head.S:__ret
+	ret	lr				@ return to head.S:__ret
 ENDPROC(__v7_setup)
 
 	.align	2
@@ -418,6 +453,7 @@ __v7_setup_stack:
 
 	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
 	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #ifdef CONFIG_CPU_PJ4B
 	define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #endif
@@ -470,7 +506,7 @@ __v7_ca5mp_proc_info:
 __v7_ca9mp_proc_info:
 	.long	0x410fc090
 	.long	0xff0ffff0
-	__v7_proc __v7_ca9mp_setup
+	__v7_proc __v7_ca9mp_setup, proc_fns = ca9mp_processor_functions
 	.size	__v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
 
 #endif	/* CONFIG_ARM_LPAE */
@@ -528,6 +564,16 @@ __v7_ca15mp_proc_info:
 	.size	__v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
 
 	/*
+	 * Broadcom Corporation Brahma-B15 processor.
+	 */
+	.type	__v7_b15mp_proc_info, #object
+__v7_b15mp_proc_info:
+	.long	0x420f00f0
+	.long	0xff0ffff0
+	__v7_proc __v7_b15mp_setup, hwcaps = HWCAP_IDIV
+	.size	__v7_b15mp_proc_info, . - __v7_b15mp_proc_info
+
+	/*
 	 * ARM Ltd. Cortex A17 processor.
 	 */
 	.type	__v7_ca17mp_proc_info, #object
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-xsc3.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-xsc3.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-xsc3.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-xsc3.S	2014-09-28 17:29:07.000000000 -0400
@@ -83,7 +83,7 @@
  * Nothing too exciting at the moment
  */
 ENTRY(cpu_xsc3_proc_init)
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_xsc3_proc_fin()
@@ -93,7 +93,7 @@ ENTRY(cpu_xsc3_proc_fin)
 	bic	r0, r0, #0x1800			@ ...IZ...........
 	bic	r0, r0, #0x0006			@ .............CA.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_xsc3_reset(loc)
@@ -119,7 +119,7 @@ ENTRY(cpu_xsc3_reset)
 	@ CAUTION: MMU turned off from this point.  We count on the pipeline
 	@ already containing those two last instructions to survive.
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I and D TLBs
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_xsc3_reset)
 	.popsection
 
@@ -138,7 +138,7 @@ ENDPROC(cpu_xsc3_reset)
 ENTRY(cpu_xsc3_do_idle)
 	mov	r0, #1
 	mcr	p14, 0, r0, c7, c0, 0		@ go to idle
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -150,7 +150,7 @@ ENTRY(cpu_xsc3_do_idle)
 ENTRY(xsc3_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(xsc3_flush_icache_all)
 
 /*
@@ -176,7 +176,7 @@ __flush_whole_cache:
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate L1 I cache and BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
 	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, vm_flags)
@@ -205,7 +205,7 @@ ENTRY(xsc3_flush_user_cache_range)
 	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
 	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -232,7 +232,7 @@ ENTRY(xsc3_coherent_user_range)
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate L1 I cache and BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
 	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -253,7 +253,7 @@ ENTRY(xsc3_flush_kern_dcache_area)
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate L1 I cache and BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
 	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -277,7 +277,7 @@ xsc3_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -294,7 +294,7 @@ xsc3_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -311,7 +311,7 @@ ENTRY(xsc3_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -334,7 +334,7 @@ ENDPROC(xsc3_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(xsc3_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(xsc3_dma_unmap_area)
 
 	.globl	xsc3_flush_kern_cache_louis
@@ -348,7 +348,7 @@ ENTRY(cpu_xsc3_dcache_clean_area)
 	add	r0, r0, #CACHELINESIZE
 	subs	r1, r1, #CACHELINESIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -406,7 +406,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	orr	r2, r2, ip
 
 	xscale_set_pte_ext_epilogue
-	mov	pc, lr
+	ret	lr
 
 	.ltorg
 	.align
@@ -478,7 +478,7 @@ __xsc3_setup:
 	bic	r0, r0, r5			@ ..V. ..R. .... ..A.
 	orr	r0, r0, r6			@ ..VI Z..S .... .C.M (mmu)
 						@ ...I Z..S .... .... (uc)
-	mov	pc, lr
+	ret	lr
 
 	.size	__xsc3_setup, . - __xsc3_setup
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/proc-xscale.S linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-xscale.S
--- linux-libre-3.16-gnu/arch/arm/mm/proc-xscale.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/proc-xscale.S	2014-09-28 17:29:07.000000000 -0400
@@ -118,7 +118,7 @@ ENTRY(cpu_xscale_proc_init)
 	mrc	p15, 0, r1, c1, c0, 1
 	bic	r1, r1, #1
 	mcr	p15, 0, r1, c1, c0, 1
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_xscale_proc_fin()
@@ -128,7 +128,7 @@ ENTRY(cpu_xscale_proc_fin)
 	bic	r0, r0, #0x1800			@ ...IZ...........
 	bic	r0, r0, #0x0006			@ .............CA.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	mov	pc, lr
+	ret	lr
 
 /*
  * cpu_xscale_reset(loc)
@@ -160,7 +160,7 @@ ENTRY(cpu_xscale_reset)
 	@ CAUTION: MMU turned off from this point. We count on the pipeline
 	@ already containing those two last instructions to survive.
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, r0
+	ret	r0
 ENDPROC(cpu_xscale_reset)
 	.popsection
 
@@ -179,7 +179,7 @@ ENDPROC(cpu_xscale_reset)
 ENTRY(cpu_xscale_do_idle)
 	mov	r0, #1
 	mcr	p14, 0, r0, c7, c0, 0		@ Go to IDLE
-	mov	pc, lr
+	ret	lr
 
 /* ================================= CACHE ================================ */
 
@@ -191,7 +191,7 @@ ENTRY(cpu_xscale_do_idle)
 ENTRY(xscale_flush_icache_all)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+	ret	lr
 ENDPROC(xscale_flush_icache_all)
 
 /*
@@ -216,7 +216,7 @@ __flush_whole_cache:
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_user_cache_range(start, end, vm_flags)
@@ -245,7 +245,7 @@ ENTRY(xscale_flush_user_cache_range)
 	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
 	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_kern_range(start, end)
@@ -269,7 +269,7 @@ ENTRY(xscale_coherent_kern_range)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	coherent_user_range(start, end)
@@ -291,7 +291,7 @@ ENTRY(xscale_coherent_user_range)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 6		@ Invalidate BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	flush_kern_dcache_area(void *addr, size_t size)
@@ -312,7 +312,7 @@ ENTRY(xscale_flush_kern_dcache_area)
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_inv_range(start, end)
@@ -336,7 +336,7 @@ xscale_dma_inv_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_clean_range(start, end)
@@ -353,7 +353,7 @@ xscale_dma_clean_range:
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_flush_range(start, end)
@@ -371,7 +371,7 @@ ENTRY(xscale_dma_flush_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
+	ret	lr
 
 /*
  *	dma_map_area(start, size, dir)
@@ -407,7 +407,7 @@ ENDPROC(xscale_80200_A0_A1_dma_map_area)
  *	- dir	- DMA direction
  */
 ENTRY(xscale_dma_unmap_area)
-	mov	pc, lr
+	ret	lr
 ENDPROC(xscale_dma_unmap_area)
 
 	.globl	xscale_flush_kern_cache_louis
@@ -458,7 +458,7 @@ ENTRY(cpu_xscale_dcache_clean_area)
 	add	r0, r0, #CACHELINESIZE
 	subs	r1, r1, #CACHELINESIZE
 	bhi	1b
-	mov	pc, lr
+	ret	lr
 
 /* =============================== PageTable ============================== */
 
@@ -521,7 +521,7 @@ ENTRY(cpu_xscale_set_pte_ext)
 	orr	r2, r2, ip
 
 	xscale_set_pte_ext_epilogue
-	mov	pc, lr
+	ret	lr
 
 	.ltorg
 	.align
@@ -572,7 +572,7 @@ __xscale_setup:
 	mrc	p15, 0, r0, c1, c0, 0		@ get control register
 	bic	r0, r0, r5
 	orr	r0, r0, r6
-	mov	pc, lr
+	ret	lr
 	.size	__xscale_setup, . - __xscale_setup
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-fa.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-fa.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-fa.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-fa.S	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
@@ -37,7 +38,7 @@ ENTRY(fa_flush_user_tlb_range)
 	vma_vm_mm ip, r2
 	act_mm	r3				@ get current->active_mm
 	eors	r3, ip, r3			@ == mm ?
-	movne	pc, lr				@ no, we dont do anything
+	retne	lr				@ no, we dont do anything
 	mov	r3, #0
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 	bic	r0, r0, #0x0ff
@@ -47,7 +48,7 @@ ENTRY(fa_flush_user_tlb_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
-	mov	pc, lr
+	ret	lr
 
 
 ENTRY(fa_flush_kern_tlb_range)
@@ -61,7 +62,7 @@ ENTRY(fa_flush_kern_tlb_range)
 	blo	1b
 	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
 	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush (isb)
-	mov	pc, lr
+	ret	lr
 
 	__INITDATA
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-v4.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-v4.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4.S	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
@@ -33,7 +34,7 @@ ENTRY(v4_flush_user_tlb_range)
 	vma_vm_mm ip, r2
 	act_mm	r3				@ get current->active_mm
 	eors	r3, ip, r3				@ == mm ?
-	movne	pc, lr				@ no, we dont do anything
+	retne	lr				@ no, we dont do anything
 .v4_flush_kern_tlb_range:
 	bic	r0, r0, #0x0ff
 	bic	r0, r0, #0xf00
@@ -41,7 +42,7 @@ ENTRY(v4_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v4_flush_kern_tlb_range(start, end)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-v4wbi.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4wbi.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-v4wbi.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4wbi.S	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
@@ -32,7 +33,7 @@ ENTRY(v4wbi_flush_user_tlb_range)
 	vma_vm_mm ip, r2
 	act_mm	r3				@ get current->active_mm
 	eors	r3, ip, r3			@ == mm ?
-	movne	pc, lr				@ no, we dont do anything
+	retne	lr				@ no, we dont do anything
 	mov	r3, #0
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 	vma_vm_flags r2, r2
@@ -44,7 +45,7 @@ ENTRY(v4wbi_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 ENTRY(v4wbi_flush_kern_tlb_range)
 	mov	r3, #0
@@ -56,7 +57,7 @@ ENTRY(v4wbi_flush_kern_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 	__INITDATA
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-v4wb.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4wb.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-v4wb.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v4wb.S	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
@@ -33,7 +34,7 @@ ENTRY(v4wb_flush_user_tlb_range)
 	vma_vm_mm ip, r2
 	act_mm	r3				@ get current->active_mm
 	eors	r3, ip, r3				@ == mm ?
-	movne	pc, lr				@ no, we dont do anything
+	retne	lr				@ no, we dont do anything
 	vma_vm_flags r2, r2
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 	tst	r2, #VM_EXEC
@@ -44,7 +45,7 @@ ENTRY(v4wb_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v4_flush_kern_tlb_range(start, end)
@@ -65,7 +66,7 @@ ENTRY(v4wb_flush_kern_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	pc, lr
+	ret	lr
 
 	__INITDATA
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-v6.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v6.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-v6.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v6.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/assembler.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
@@ -55,7 +56,7 @@ ENTRY(v6wbi_flush_user_tlb_range)
 	cmp	r0, r1
 	blo	1b
 	mcr	p15, 0, ip, c7, c10, 4		@ data synchronization barrier
-	mov	pc, lr
+	ret	lr
 
 /*
  *	v6wbi_flush_kern_tlb_range(start,end)
@@ -84,7 +85,7 @@ ENTRY(v6wbi_flush_kern_tlb_range)
 	blo	1b
 	mcr	p15, 0, r2, c7, c10, 4		@ data synchronization barrier
 	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush (isb)
-	mov	pc, lr
+	ret	lr
 
 	__INIT
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/mm/tlb-v7.S linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v7.S
--- linux-libre-3.16-gnu/arch/arm/mm/tlb-v7.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/mm/tlb-v7.S	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,7 @@ ENTRY(v7wbi_flush_user_tlb_range)
 	cmp	r0, r1
 	blo	1b
 	dsb	ish
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7wbi_flush_user_tlb_range)
 
 /*
@@ -86,7 +86,7 @@ ENTRY(v7wbi_flush_kern_tlb_range)
 	blo	1b
 	dsb	ish
 	isb
-	mov	pc, lr
+	ret	lr
 ENDPROC(v7wbi_flush_kern_tlb_range)
 
 	__INIT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/net/bpf_jit_32.c linux-libre-3.17-rc7-gnu/arch/arm/net/bpf_jit_32.c
--- linux-libre-3.16-gnu/arch/arm/net/bpf_jit_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/net/bpf_jit_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@
 #define FLAG_NEED_X_RESET	(1 << 0)
 
 struct jit_ctx {
-	const struct sk_filter *skf;
+	const struct bpf_prog *skf;
 	unsigned idx;
 	unsigned prologue_bytes;
 	int ret0_fp_idx;
@@ -465,7 +465,7 @@ static inline void update_on_xread(struc
 static int build_body(struct jit_ctx *ctx)
 {
 	void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
-	const struct sk_filter *prog = ctx->skf;
+	const struct bpf_prog *prog = ctx->skf;
 	const struct sock_filter *inst;
 	unsigned i, load_order, off, condt;
 	int imm12;
@@ -857,7 +857,7 @@ b_epilogue:
 }
 
 
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
 {
 	struct jit_ctx ctx;
 	unsigned tmp_idx;
@@ -926,7 +926,7 @@ out:
 	return;
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
 		module_free(NULL, fp->bpf_func);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/nwfpe/entry.S linux-libre-3.17-rc7-gnu/arch/arm/nwfpe/entry.S
--- linux-libre-3.16-gnu/arch/arm/nwfpe/entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/nwfpe/entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -19,7 +19,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
-
+#include <asm/assembler.h>
 #include <asm/opcodes.h>
 
 /* This is the kernel's entry point into the floating point emulator.
@@ -92,7 +92,7 @@ emulate:
 	mov	r0, r6			@ prepare for EmulateAll()
 	bl	EmulateAll		@ emulate the instruction
 	cmp	r0, #0			@ was emulation successful
-	moveq	pc, r4			@ no, return failure
+	reteq	r4			@ no, return failure
 
 next:
 .Lx1:	ldrt	r6, [r5], #4		@ get the next instruction and
@@ -102,7 +102,7 @@ next:
 	teq	r2, #0x0C000000
 	teqne	r2, #0x0D000000
 	teqne	r2, #0x0E000000
-	movne	pc, r9			@ return ok if not a fp insn
+	retne	r9			@ return ok if not a fp insn
 
 	str	r5, [sp, #S_PC]		@ update PC copy in regs
 
@@ -115,7 +115,7 @@ next:
 	@ plain LDR instruction.  Weird, but it seems harmless.
 	.pushsection .fixup,"ax"
 	.align	2
-.Lfix:	mov	pc, r9			@ let the user eat segfaults
+.Lfix:	ret	r9			@ let the user eat segfaults
 	.popsection
 
 	.pushsection __ex_table,"a"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/oprofile/common.c linux-libre-3.17-rc7-gnu/arch/arm/oprofile/common.c
--- linux-libre-3.16-gnu/arch/arm/oprofile/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/oprofile/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,12 +33,14 @@ static struct op_perf_name {
 	char *perf_name;
 	char *op_name;
 } op_perf_name_map[] = {
-	{ "xscale1",		"arm/xscale1"	},
-	{ "xscale1",		"arm/xscale2"	},
-	{ "v6",			"arm/armv6"	},
-	{ "v6mpcore",		"arm/mpcore"	},
-	{ "ARMv7 Cortex-A8",	"arm/armv7"	},
-	{ "ARMv7 Cortex-A9",	"arm/armv7-ca9"	},
+	{ "armv5_xscale1",	"arm/xscale1"	},
+	{ "armv5_xscale2",	"arm/xscale2"	},
+	{ "armv6_1136",		"arm/armv6"	},
+	{ "armv6_1156",		"arm/armv6"	},
+	{ "armv6_1176",		"arm/armv6"	},
+	{ "armv6_11mpcore",	"arm/mpcore"	},
+	{ "armv7_cortex_a8",	"arm/armv7"	},
+	{ "armv7_cortex_a9",	"arm/armv7-ca9"	},
 };
 
 char *op_name_from_perf_id(void)
@@ -107,10 +109,7 @@ static void arm_backtrace(struct pt_regs
 
 	if (!user_mode(regs)) {
 		struct stackframe frame;
-		frame.fp = regs->ARM_fp;
-		frame.sp = regs->ARM_sp;
-		frame.lr = regs->ARM_lr;
-		frame.pc = regs->ARM_pc;
+		arm_get_current_stackframe(regs, &frame);
 		walk_stackframe(&frame, report_trace, &depth);
 		return;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-omap/dma.c linux-libre-3.17-rc7-gnu/arch/arm/plat-omap/dma.c
--- linux-libre-3.16-gnu/arch/arm/plat-omap/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-omap/dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -698,6 +698,8 @@ int omap_request_dma(int dev_id, const c
 	unsigned long flags;
 	struct omap_dma_lch *chan;
 
+	WARN(strcmp(dev_name, "DMA engine"), "Using deprecated platform DMA API - please update to DMA engine");
+
 	spin_lock_irqsave(&dma_chan_lock, flags);
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
@@ -2100,7 +2102,7 @@ static int omap_system_dma_probe(struct
 		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (dma_omap2plus()) {
+	if (dma_omap2plus() && !(d->dev_caps & DMA_ENGINE_HANDLE_IRQ)) {
 		strcpy(irq_name, "0");
 		dma_irq = platform_get_irq_byname(pdev, irq_name);
 		if (dma_irq < 0) {
@@ -2145,7 +2147,8 @@ static int omap_system_dma_remove(struct
 		char irq_name[4];
 		strcpy(irq_name, "0");
 		dma_irq = platform_get_irq_byname(pdev, irq_name);
-		remove_irq(dma_irq, &omap24xx_dma_irq);
+		if (dma_irq >= 0)
+			remove_irq(dma_irq, &omap24xx_dma_irq);
 	} else {
 		int irq_rel = 0;
 		for ( ; irq_rel < dma_chan_count; irq_rel++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-omap/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/plat-omap/Kconfig
--- linux-libre-3.16-gnu/arch/arm/plat-omap/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-omap/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,6 @@
+config ARCH_OMAP
+	bool
+
 if ARCH_OMAP
 
 menu "TI OMAP Common Features"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/adc.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/adc.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/adc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/adc.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@ enum s3c_cpu_type {
 	TYPE_ADCV1, /* S3C24XX */
 	TYPE_ADCV11, /* S3C2443 */
 	TYPE_ADCV12, /* S3C2416, S3C2450 */
-	TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+	TYPE_ADCV2, /* S3C64XX */
 	TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/clock.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/clock.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,539 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/clock.c
- *
- * Copyright 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- **  Copyright (C) 2004 ARM Limited.
- **  Written by Deep Blue Solutions Limited.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/debugfs.h>
-#endif
-
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h> /* for s3c24xx_uart_devs */
-
-/* clock information */
-
-static LIST_HEAD(clocks);
-
-/* We originally used an mutex here, but some contexts (see resume)
- * are calling functions such as clk_set_parent() with IRQs disabled
- * causing an BUG to be triggered.
- */
-DEFINE_SPINLOCK(clocks_lock);
-
-/* Global watchdog clock used by arch_wtd_reset() callback */
-struct clk *s3c2410_wdtclk;
-static int __init s3c_wdt_reset_init(void)
-{
-	s3c2410_wdtclk = clk_get(NULL, "watchdog");
-	if (IS_ERR(s3c2410_wdtclk))
-		printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
-	return 0;
-}
-arch_initcall(s3c_wdt_reset_init);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
-{
-	return 0;
-}
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (IS_ERR(clk) || clk == NULL)
-		return -EINVAL;
-
-	clk_enable(clk->parent);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-
-	if ((clk->usage++) == 0)
-		(clk->enable)(clk, 1);
-
-	spin_unlock_irqrestore(&clocks_lock, flags);
-	return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (IS_ERR(clk) || clk == NULL)
-		return;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-
-	if ((--clk->usage) == 0)
-		(clk->enable)(clk, 0);
-
-	spin_unlock_irqrestore(&clocks_lock, flags);
-	clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (IS_ERR_OR_NULL(clk))
-		return 0;
-
-	if (clk->rate != 0)
-		return clk->rate;
-
-	if (clk->ops != NULL && clk->ops->get_rate != NULL)
-		return (clk->ops->get_rate)(clk);
-
-	if (clk->parent != NULL)
-		return clk_get_rate(clk->parent);
-
-	return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
-		return (clk->ops->round_rate)(clk, rate);
-
-	return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long flags;
-	int ret;
-
-	if (IS_ERR_OR_NULL(clk))
-		return -EINVAL;
-
-	/* We do not default just do a clk->rate = rate as
-	 * the clock may have been made this way by choice.
-	 */
-
-	WARN_ON(clk->ops == NULL);
-	WARN_ON(clk->ops && clk->ops->set_rate == NULL);
-
-	if (clk->ops == NULL || clk->ops->set_rate == NULL)
-		return -EINVAL;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	ret = (clk->ops->set_rate)(clk, rate);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
-		return -EINVAL;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-
-	if (clk->ops && clk->ops->set_parent)
-		ret = (clk->ops->set_parent)(clk, parent);
-
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-int clk_default_setrate(struct clk *clk, unsigned long rate)
-{
-	clk->rate = rate;
-	return 0;
-}
-
-struct clk_ops clk_ops_def_setrate = {
-	.set_rate	= clk_default_setrate,
-};
-
-struct clk clk_xtal = {
-	.name		= "xtal",
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_ext = {
-	.name		= "ext",
-};
-
-struct clk clk_epll = {
-	.name		= "epll",
-};
-
-struct clk clk_mpll = {
-	.name		= "mpll",
-	.ops		= &clk_ops_def_setrate,
-};
-
-struct clk clk_upll = {
-	.name		= "upll",
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_f = {
-	.name		= "fclk",
-	.rate		= 0,
-	.parent		= &clk_mpll,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_h = {
-	.name		= "hclk",
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.ops		= &clk_ops_def_setrate,
-};
-
-struct clk clk_p = {
-	.name		= "pclk",
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.ops		= &clk_ops_def_setrate,
-};
-
-struct clk clk_usb_bus = {
-	.name		= "usb-bus",
-	.rate		= 0,
-	.parent		= &clk_upll,
-};
-
-
-struct clk s3c24xx_uclk = {
-	.name		= "uclk",
-};
-
-/* initialise the clock system */
-
-/**
- * s3c24xx_register_clock() - register a clock
- * @clk: The clock to register
- *
- * Add the specified clock to the list of clocks known by the system.
- */
-int s3c24xx_register_clock(struct clk *clk)
-{
-	if (clk->enable == NULL)
-		clk->enable = clk_null_enable;
-
-	/* fill up the clk_lookup structure and register it*/
-	clk->lookup.dev_id = clk->devname;
-	clk->lookup.con_id = clk->name;
-	clk->lookup.clk = clk;
-	clkdev_add(&clk->lookup);
-
-	return 0;
-}
-
-/**
- * s3c24xx_register_clocks() - register an array of clock pointers
- * @clks: Pointer to an array of struct clk pointers
- * @nr_clks: The number of clocks in the @clks array.
- *
- * Call s3c24xx_register_clock() for all the clock pointers contained
- * in the @clks list. Returns the number of failures.
- */
-int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
-{
-	int fails = 0;
-
-	for (; nr_clks > 0; nr_clks--, clks++) {
-		if (s3c24xx_register_clock(*clks) < 0) {
-			struct clk *clk = *clks;
-			printk(KERN_ERR "%s: failed to register %p: %s\n",
-			       __func__, clk, clk->name);
-			fails++;
-		}
-	}
-
-	return fails;
-}
-
-/**
- * s3c_register_clocks() - register an array of clocks
- * @clkp: Pointer to the first clock in the array.
- * @nr_clks: Number of clocks to register.
- *
- * Call s3c24xx_register_clock() on the @clkp array given, printing an
- * error if it fails to register the clock (unlikely).
- */
-void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
-{
-	int ret;
-
-	for (; nr_clks > 0; nr_clks--, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-}
-
-/**
- * s3c_disable_clocks() - disable an array of clocks
- * @clkp: Pointer to the first clock in the array.
- * @nr_clks: Number of clocks to register.
- *
- * for internal use only at initialisation time. disable the clocks in the
- * @clkp array.
- */
-
-void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
-{
-	for (; nr_clks > 0; nr_clks--, clkp++)
-		(clkp->enable)(clkp, 0);
-}
-
-/* initialise all the clocks */
-
-int __init s3c24xx_register_baseclocks(unsigned long xtal)
-{
-	printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
-
-	clk_xtal.rate = xtal;
-
-	/* register our clocks */
-
-	if (s3c24xx_register_clock(&clk_xtal) < 0)
-		printk(KERN_ERR "failed to register master xtal\n");
-
-	if (s3c24xx_register_clock(&clk_mpll) < 0)
-		printk(KERN_ERR "failed to register mpll clock\n");
-
-	if (s3c24xx_register_clock(&clk_upll) < 0)
-		printk(KERN_ERR "failed to register upll clock\n");
-
-	if (s3c24xx_register_clock(&clk_f) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
-
-	if (s3c24xx_register_clock(&clk_h) < 0)
-		printk(KERN_ERR "failed to register cpu hclk\n");
-
-	if (s3c24xx_register_clock(&clk_p) < 0)
-		printk(KERN_ERR "failed to register cpu pclk\n");
-
-	return 0;
-}
-
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-/* debugfs support to trace clock tree hierarchy and attributes */
-
-static struct dentry *clk_debugfs_root;
-
-static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
-{
-	struct clk *child;
-	const char *state;
-	char buf[255] = { 0 };
-	int n = 0;
-
-	if (c->name)
-		n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
-
-	if (c->devname)
-		n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
-
-	state = (c->usage > 0) ? "on" : "off";
-
-	seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
-		   level * 3 + 1, "",
-		   50 - level * 3, buf,
-		   state, c->usage, clk_get_rate(c));
-
-	list_for_each_entry(child, &clocks, list) {
-		if (child->parent != c)
-			continue;
-
-		clock_tree_show_one(s, child, level + 1);
-	}
-}
-
-static int clock_tree_show(struct seq_file *s, void *data)
-{
-	struct clk *c;
-	unsigned long flags;
-
-	seq_printf(s, " clock state ref rate\n");
-	seq_printf(s, "----------------------------------------------------\n");
-
-	spin_lock_irqsave(&clocks_lock, flags);
-
-	list_for_each_entry(c, &clocks, list)
-		if (c->parent == NULL)
-			clock_tree_show_one(s, c, 0);
-
-	spin_unlock_irqrestore(&clocks_lock, flags);
-	return 0;
-}
-
-static int clock_tree_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clock_tree_show, inode->i_private);
-}
-
-static const struct file_operations clock_tree_fops = {
-	.open		= clock_tree_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int clock_rate_show(void *data, u64 *val)
-{
-	struct clk *c = data;
-	*val = clk_get_rate(c);
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-	int err;
-	struct dentry *d;
-	struct clk *pa = c->parent;
-	char s[255];
-	char *p = s;
-
-	p += sprintf(p, "%s", c->devname);
-
-	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
-	if (!d)
-		return -ENOMEM;
-
-	c->dent = d;
-
-	d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
-	if (!d) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
-	if (!d) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(c->dent);
-	return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-	int err;
-	struct clk *pa = c->parent;
-
-	if (pa && !pa->dent) {
-		err = clk_debugfs_register(pa);
-		if (err)
-			return err;
-	}
-
-	if (!c->dent) {
-		err = clk_debugfs_register_one(c);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
-	struct clk *c;
-	struct dentry *d;
-	int err = -ENOMEM;
-
-	d = debugfs_create_dir("clock", NULL);
-	if (!d)
-		return -ENOMEM;
-	clk_debugfs_root = d;
-
-	d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
-				 &clock_tree_fops);
-	if (!d)
-		goto err_out;
-
-	list_for_each_entry(c, &clocks, list) {
-		err = clk_debugfs_register(c);
-		if (err)
-			goto err_out;
-	}
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(clk_debugfs_root);
-	return err;
-}
-late_initcall(clk_debugfs_init);
-
-#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/clock-clksrc.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/clock-clksrc.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/clock-clksrc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/clock-clksrc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,212 +0,0 @@
-/* linux/arch/arm/plat-samsung/clock-clksrc.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/cpu-freq.h>
-
-static inline struct clksrc_clk *to_clksrc(struct clk *clk)
-{
-	return container_of(clk, struct clksrc_clk, clk);
-}
-
-static inline u32 bit_mask(u32 shift, u32 nr_bits)
-{
-	u32 mask = 0xffffffff >> (32 - nr_bits);
-
-	return mask << shift;
-}
-
-static unsigned long s3c_getrate_clksrc(struct clk *clk)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv = __raw_readl(sclk->reg_div.reg);
-	u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
-
-	clkdiv &= mask;
-	clkdiv >>= sclk->reg_div.shift;
-	clkdiv++;
-
-	rate /= clkdiv;
-	return rate;
-}
-
-static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	void __iomem *reg = sclk->reg_div.reg;
-	unsigned int div;
-	u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
-	u32 val;
-
-	rate = clk_round_rate(clk, rate);
-	div = clk_get_rate(clk->parent) / rate;
-	if (div > (1 << sclk->reg_div.size))
-		return -EINVAL;
-
-	val = __raw_readl(reg);
-	val &= ~mask;
-	val |= (div - 1) << sclk->reg_div.shift;
-	__raw_writel(val, reg);
-
-	return 0;
-}
-
-static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	struct clksrc_sources *srcs = sclk->sources;
-	u32 clksrc = __raw_readl(sclk->reg_src.reg);
-	u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size);
-	int src_nr = -1;
-	int ptr;
-
-	for (ptr = 0; ptr < srcs->nr_sources; ptr++)
-		if (srcs->sources[ptr] == parent) {
-			src_nr = ptr;
-			break;
-		}
-
-	if (src_nr >= 0) {
-		clk->parent = parent;
-
-		clksrc &= ~mask;
-		clksrc |= src_nr << sclk->reg_src.shift;
-
-		__raw_writel(clksrc, sclk->reg_src.reg);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static unsigned long s3c_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int max_div = 1 << sclk->reg_div.size;
-	int div;
-
-	if (rate >= parent_rate)
-		rate = parent_rate;
-	else {
-		div = parent_rate / rate;
-		if (parent_rate % rate)
-			div++;
-
-		if (div == 0)
-			div = 1;
-		if (div > max_div)
-			div = max_div;
-
-		rate = parent_rate / div;
-	}
-
-	return rate;
-}
-
-/* Clock initialisation code */
-
-void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce)
-{
-	struct clksrc_sources *srcs = clk->sources;
-	u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size);
-	u32 clksrc;
-
-	if (!clk->reg_src.reg) {
-		if (!clk->clk.parent)
-			printk(KERN_ERR "%s: no parent clock specified\n",
-				clk->clk.name);
-		return;
-	}
-
-	clksrc = __raw_readl(clk->reg_src.reg);
-	clksrc &= mask;
-	clksrc >>= clk->reg_src.shift;
-
-	if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
-		printk(KERN_ERR "%s: bad source %d\n",
-		       clk->clk.name, clksrc);
-		return;
-	}
-
-	clk->clk.parent = srcs->sources[clksrc];
-
-	if (announce)
-		printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
-		       clk->clk.name, clk->clk.parent->name, clksrc,
-		       clk_get_rate(&clk->clk));
-}
-
-static struct clk_ops clksrc_ops = {
-	.set_parent	= s3c_setparent_clksrc,
-	.get_rate	= s3c_getrate_clksrc,
-	.set_rate	= s3c_setrate_clksrc,
-	.round_rate	= s3c_roundrate_clksrc,
-};
-
-static struct clk_ops clksrc_ops_nodiv = {
-	.set_parent	= s3c_setparent_clksrc,
-};
-
-static struct clk_ops clksrc_ops_nosrc = {
-	.get_rate	= s3c_getrate_clksrc,
-	.set_rate	= s3c_setrate_clksrc,
-	.round_rate	= s3c_roundrate_clksrc,
-};
-
-void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
-{
-	int ret;
-
-	for (; size > 0; size--, clksrc++) {
-		if (!clksrc->reg_div.reg && !clksrc->reg_src.reg)
-			printk(KERN_ERR "%s: clock %s has no registers set\n",
-			       __func__, clksrc->clk.name);
-
-		/* fill in the default functions */
-
-		if (!clksrc->clk.ops) {
-			if (!clksrc->reg_div.reg)
-				clksrc->clk.ops = &clksrc_ops_nodiv;
-			else if (!clksrc->reg_src.reg)
-				clksrc->clk.ops = &clksrc_ops_nosrc;
-			else
-				clksrc->clk.ops = &clksrc_ops;
-		}
-
-		/* setup the clocksource, but do not announce it
-		 * as it may be re-set by the setup routines
-		 * called after the rest of the clocks have been
-		 * registered
-		 */
-		s3c_set_clksrc(clksrc, false);
-
-		ret = s3c24xx_register_clock(&clksrc->clk);
-
-		if (ret < 0) {
-			printk(KERN_ERR "%s: failed to register %s (%d)\n",
-			       __func__, clksrc->clk.name, ret);
-		}
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/cpu.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/cpu.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
-
-#include <mach/map.h>
+#include <plat/map-base.h>
 #include <plat/cpu.h>
 
 unsigned long samsung_cpu_id;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/devs.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/devs.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/devs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/devs.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,6 @@
 #include <linux/platform_data/ata-samsung_cf.h>
 #include <plat/fb.h>
 #include <plat/fb-s3c2410.h>
-#include <plat/hdmi.h>
 #include <linux/platform_data/hwmon-s3c.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
@@ -145,23 +144,6 @@ struct platform_device s3c_device_camif
 };
 #endif /* CONFIG_CPU_S3C2440 */
 
-/* ASOC DMA */
-
-#ifdef CONFIG_PLAT_S5P 
-static struct resource samsung_asoc_idma_resource = DEFINE_RES_IRQ(IRQ_I2S0);
-
-struct platform_device samsung_asoc_idma = {
-	.name		= "samsung-idma",
-	.id		= -1,
-	.num_resources	= 1,
-	.resource	= &samsung_asoc_idma_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
-#endif
-
 /* FB */
 
 #ifdef CONFIG_S3C_DEV_FB
@@ -190,151 +172,6 @@ void __init s3c_fb_set_platdata(struct s
 }
 #endif /* CONFIG_S3C_DEV_FB */
 
-/* FIMC */
-
-#ifdef CONFIG_S5P_DEV_FIMC0
-static struct resource s5p_fimc0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_FIMC0),
-};
-
-struct platform_device s5p_device_fimc0 = {
-	.name		= "s5p-fimc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimc0_resource),
-	.resource	= s5p_fimc0_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device s5p_device_fimc_md = {
-	.name	= "s5p-fimc-md",
-	.id	= -1,
-};
-#endif /* CONFIG_S5P_DEV_FIMC0 */
-
-#ifdef CONFIG_S5P_DEV_FIMC1
-static struct resource s5p_fimc1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_FIMC1),
-};
-
-struct platform_device s5p_device_fimc1 = {
-	.name		= "s5p-fimc",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p_fimc1_resource),
-	.resource	= s5p_fimc1_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#endif /* CONFIG_S5P_DEV_FIMC1 */
-
-#ifdef CONFIG_S5P_DEV_FIMC2
-static struct resource s5p_fimc2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_FIMC2),
-};
-
-struct platform_device s5p_device_fimc2 = {
-	.name		= "s5p-fimc",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s5p_fimc2_resource),
-	.resource	= s5p_fimc2_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#endif /* CONFIG_S5P_DEV_FIMC2 */
-
-#ifdef CONFIG_S5P_DEV_FIMC3
-static struct resource s5p_fimc3_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_FIMC3),
-};
-
-struct platform_device s5p_device_fimc3 = {
-	.name		= "s5p-fimc",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s5p_fimc3_resource),
-	.resource	= s5p_fimc3_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#endif /* CONFIG_S5P_DEV_FIMC3 */
-
-/* G2D */
-
-#ifdef CONFIG_S5P_DEV_G2D
-static struct resource s5p_g2d_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_G2D, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_2D),
-};
-
-struct platform_device s5p_device_g2d = {
-	.name		= "s5p-g2d",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_g2d_resource),
-	.resource	= s5p_g2d_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#endif /* CONFIG_S5P_DEV_G2D */
-
-#ifdef CONFIG_S5P_DEV_JPEG
-static struct resource s5p_jpeg_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_JPEG, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_JPEG),
-};
-
-struct platform_device s5p_device_jpeg = {
-	.name		= "s5p-jpeg",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_jpeg_resource),
-	.resource	= s5p_jpeg_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#endif /*  CONFIG_S5P_DEV_JPEG */
-
-/* FIMD0 */
-
-#ifdef CONFIG_S5P_DEV_FIMD0
-static struct resource s5p_fimd0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
-	[1] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_VSYNC, "vsync"),
-	[2] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_FIFO, "fifo"),
-	[3] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_SYSTEM, "lcd_sys"),
-};
-
-struct platform_device s5p_device_fimd0 = {
-	.name		= "s5p-fb",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
-	.resource	= s5p_fimd0_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-			 &s5p_device_fimd0);
-}
-#endif /* CONFIG_S5P_DEV_FIMD0 */
-
 /* HWMON */
 
 #ifdef CONFIG_S3C_DEV_HWMON
@@ -722,60 +559,6 @@ void __init s3c_i2c7_set_platdata(struct
 }
 #endif /* CONFIG_S3C_DEV_I2C7 */
 
-/* I2C HDMIPHY */
-
-#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
-static struct resource s5p_i2c_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
-	[1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
-};
-
-struct platform_device s5p_device_i2c_hdmiphy = {
-	.name		= "s3c2440-hdmiphy-i2c",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_i2c_resource),
-	.resource	= s5p_i2c_resource,
-};
-
-void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-
-		if (soc_is_s5pv210())
-			pd->bus_num = 3;
-		else
-			pd->bus_num = 0;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s5p_device_i2c_hdmiphy);
-}
-
-static struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
-
-void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
-				  struct i2c_board_info *mhl_info, int mhl_bus)
-{
-	struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata;
-
-	if (soc_is_s5pv210())
-		pd->hdmiphy_bus = 3;
-	else
-		pd->hdmiphy_bus = 0;
-
-	pd->hdmiphy_info = hdmiphy_info;
-	pd->mhl_info = mhl_info;
-	pd->mhl_bus = mhl_bus;
-
-	s3c_set_platdata(pd, sizeof(struct s5p_hdmi_platform_data),
-			 &s5p_device_hdmi);
-}
-
-#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
-
 /* I2S */
 
 #ifdef CONFIG_PLAT_S3C24XX
@@ -879,36 +662,6 @@ void __init s3c24xx_fb_set_platdata(stru
 }
 #endif /* CONFIG_PLAT_S3C24XX */
 
-/* MIPI CSIS */
-
-#ifdef CONFIG_S5P_DEV_CSIS0
-static struct resource s5p_mipi_csis0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_16K),
-	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
-};
-
-struct platform_device s5p_device_mipi_csis0 = {
-	.name		= "s5p-mipi-csis",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_mipi_csis0_resource),
-	.resource	= s5p_mipi_csis0_resource,
-};
-#endif /* CONFIG_S5P_DEV_CSIS0 */
-
-#ifdef CONFIG_S5P_DEV_CSIS1
-static struct resource s5p_mipi_csis1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_16K),
-	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
-};
-
-struct platform_device s5p_device_mipi_csis1 = {
-	.name		= "s5p-mipi-csis",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p_mipi_csis1_resource),
-	.resource	= s5p_mipi_csis1_resource,
-};
-#endif
-
 /* NAND */
 
 #ifdef CONFIG_S3C_DEV_NAND
@@ -1052,43 +805,6 @@ void __init s3c64xx_onenand1_set_platdat
 }
 #endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
 
-#ifdef CONFIG_S5P_DEV_ONENAND
-static struct resource s5p_onenand_resources[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
-	[1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
-	[2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
-};
-
-struct platform_device s5p_device_onenand = {
-	.name		= "s5pc110-onenand",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
-	.resource	= s5p_onenand_resources,
-};
-#endif /* CONFIG_S5P_DEV_ONENAND */
-
-/* PMU */
-
-#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
-static struct resource s5p_pmu_resource[] = {
-	DEFINE_RES_IRQ(IRQ_PMU)
-};
-
-static struct platform_device s5p_device_pmu = {
-	.name		= "arm-pmu",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_pmu_resource),
-	.resource	= s5p_pmu_resource,
-};
-
-static int __init s5p_pmu_init(void)
-{
-	platform_device_register(&s5p_device_pmu);
-	return 0;
-}
-arch_initcall(s5p_pmu_init);
-#endif /* CONFIG_PLAT_S5P */
-
 /* PWM Timer */
 
 #ifdef CONFIG_SAMSUNG_DEV_PWM
@@ -1251,52 +967,6 @@ void __init s3c24xx_ts_set_platdata(stru
 }
 #endif /* CONFIG_SAMSUNG_DEV_TS */
 
-/* TV */
-
-#ifdef CONFIG_S5P_DEV_TV
-
-static struct resource s5p_hdmi_resources[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
-	[1] = DEFINE_RES_IRQ(IRQ_HDMI),
-};
-
-struct platform_device s5p_device_hdmi = {
-	.name		= "s5p-hdmi",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_hdmi_resources),
-	.resource	= s5p_hdmi_resources,
-};
-
-static struct resource s5p_sdo_resources[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
-	[1] = DEFINE_RES_IRQ(IRQ_SDO),
-};
-
-struct platform_device s5p_device_sdo = {
-	.name		= "s5p-sdo",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_sdo_resources),
-	.resource	= s5p_sdo_resources,
-};
-
-static struct resource s5p_mixer_resources[] = {
-	[0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
-	[1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
-	[2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
-};
-
-struct platform_device s5p_device_mixer = {
-	.name		= "s5p-mixer",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_mixer_resources),
-	.resource	= s5p_mixer_resources,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
-#endif /* CONFIG_S5P_DEV_TV */
-
 /* USB */
 
 #ifdef CONFIG_S3C_DEV_USB_HOST
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/camport.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/camport.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/camport.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5P series camera interface helper functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_SAMSUNG_CAMPORT_H_
-#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
-
-enum s5p_camport_id {
-	S5P_CAMPORT_A,
-	S5P_CAMPORT_B,
-};
-
-/*
- * The helper functions to configure GPIO for the camera parallel bus.
- * The camera port can be multiplexed with any FIMC entity, even multiple
- * FIMC entities are allowed to be attached to a single port simultaneously.
- * These functions are to be used in the board setup code.
- */
-int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
-int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
-
-#endif /* __PLAT_SAMSUNG_CAMPORT_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/clock-clksrc.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/clock-clksrc.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/clock-clksrc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/clock-clksrc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h
- *
- * Parts taken from arch/arm/plat-s3c64xx/clock.c
- *	Copyright 2008 Openmoko, Inc.
- *	Copyright 2008 Simtec Electronics
- *		Ben Dooks <ben@simtec.co.uk>
- *		http://armlinux.simtec.co.uk/
- *
- * Copyright 2009 Ben Dooks <ben-linux@fluff.org>
- * Copyright 2009 Harald Welte
- *
- * This program is free software; you can 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 clksrc_sources - list of sources for a given clock
- * @sources: array of pointers to clocks
- * @nr_sources: The size of @sources
- */
-struct clksrc_sources {
-	unsigned int	nr_sources;
-	struct clk	**sources;
-};
-
-/**
- * struct clksrc_reg - register definition for clock control bits
- * @reg: pointer to the register in virtual memory.
- * @shift: the shift in bits to where the bitfield is.
- * @size: the size in bits of the bitfield.
- *
- * This specifies the size and position of the bits we are interested
- * in within the register specified by @reg.
- */
-struct clksrc_reg {
-	void __iomem		*reg;
-	unsigned short		shift;
-	unsigned short		size;
-};
-
-/**
- * struct clksrc_clk - class of clock for newer style samsung devices.
- * @clk: the standard clock representation
- * @sources: the sources for this clock
- * @reg_src: the register definition for selecting the clock's source
- * @reg_div: the register definition for the clock's output divisor
- *
- * This clock implements the features required by the newer SoCs where
- * the standard clock block provides an input mux and a post-mux divisor
- * to provide the periperhal's clock.
- *
- * The array of @sources provides the mapping of mux position to the
- * clock, and @reg_src shows the code where to modify to change the mux
- * position. The @reg_div defines how to change the divider settings on
- * the output.
- */
-struct clksrc_clk {
-	struct clk		clk;
-	struct clksrc_sources	*sources;
-
-	struct clksrc_reg	reg_src;
-	struct clksrc_reg	reg_div;
-};
-
-/**
- * s3c_set_clksrc() - setup the clock from the register settings
- * @clk: The clock to setup.
- * @announce: true to announce the setting to printk().
- *
- * Setup the clock from the current register settings, for when the
- * kernel boots or if it is resuming from a possibly unknown state.
- */
-extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce);
-
-/**
- * s3c_register_clksrc() register clocks from an array of clksrc clocks
- * @srcs: The array of clocks to register
- * @size: The size of the @srcs array.
- *
- * Initialise and register the array of clocks described by @srcs.
- */
-extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/clock.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/clock.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/clock.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://www.simtec.co.uk/products/SWLINUX/
- *	Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_CLOCK_H
-#define __ASM_PLAT_CLOCK_H __FILE__
-
-#include <linux/spinlock.h>
-#include <linux/clkdev.h>
-
-struct clk;
-
-/**
- * struct clk_ops - standard clock operations
- * @set_rate: set the clock rate, see clk_set_rate().
- * @get_rate: get the clock rate, see clk_get_rate().
- * @round_rate: round a given clock rate, see clk_round_rate().
- * @set_parent: set the clock's parent, see clk_set_parent().
- *
- * Group the common clock implementations together so that we
- * don't have to keep setting the same fields again. We leave
- * enable in struct clk.
- *
- * Adding an extra layer of indirection into the process should
- * not be a problem as it is unlikely these operations are going
- * to need to be called quickly.
- */
-struct clk_ops {
-	int		    (*set_rate)(struct clk *c, unsigned long rate);
-	unsigned long	    (*get_rate)(struct clk *c);
-	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
-	int		    (*set_parent)(struct clk *c, struct clk *parent);
-};
-
-struct clk {
-	struct list_head      list;
-	struct module        *owner;
-	struct clk           *parent;
-	const char           *name;
-	const char		*devname;
-	int		      id;
-	int		      usage;
-	unsigned long         rate;
-	unsigned long         ctrlbit;
-
-	struct clk_ops		*ops;
-	int		    (*enable)(struct clk *, int enable);
-	struct clk_lookup	lookup;
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-	struct dentry		*dent;	/* For visible tree hierarchy */
-#endif
-};
-
-/* other clocks which may be registered by board support */
-
-extern struct clk s3c24xx_dclk0;
-extern struct clk s3c24xx_dclk1;
-extern struct clk s3c24xx_clkout0;
-extern struct clk s3c24xx_clkout1;
-extern struct clk s3c24xx_uclk;
-
-extern struct clk clk_usb_bus;
-
-/* core clock support */
-
-extern struct clk clk_f;
-extern struct clk clk_h;
-extern struct clk clk_p;
-extern struct clk clk_mpll;
-extern struct clk clk_upll;
-extern struct clk clk_epll;
-extern struct clk clk_xtal;
-extern struct clk clk_ext;
-
-/* S3C2443/S3C2416 specific clocks */
-extern struct clksrc_clk clk_epllref;
-extern struct clksrc_clk clk_esysclk;
-
-/* S3C24XX UART clocks */
-extern struct clk s3c24xx_clk_uart0;
-extern struct clk s3c24xx_clk_uart1;
-extern struct clk s3c24xx_clk_uart2;
-
-/* S3C64XX specific clocks */
-extern struct clk clk_h2;
-extern struct clk clk_27m;
-extern struct clk clk_48m;
-extern struct clk clk_xusbxti;
-
-extern int clk_default_setrate(struct clk *clk, unsigned long rate);
-extern struct clk_ops clk_ops_def_setrate;
-
-/* exports for arch/arm/mach-s3c2410
- *
- * Please DO NOT use these outside of arch/arm/mach-s3c2410
-*/
-
-extern spinlock_t clocks_lock;
-
-extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
-
-extern int s3c24xx_register_clock(struct clk *clk);
-extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
-
-extern void s3c_register_clocks(struct clk *clk, int nr_clks);
-extern void s3c_disable_clocks(struct clk *clkp, int nr_clks);
-
-extern int s3c24xx_register_baseclocks(unsigned long xtal);
-
-extern void s5p_register_clocks(unsigned long xtal_freq);
-
-extern void s3c24xx_setup_clocks(unsigned long fclk,
-				 unsigned long hclk,
-				 unsigned long pclk);
-
-extern void s3c2410_setup_clocks(void);
-extern void s3c2412_setup_clocks(void);
-extern void s3c244x_setup_clocks(void);
-
-/* S3C2410 specific clock functions */
-
-extern int s3c2410_baseclk_add(void);
-
-/* S3C2443/S3C2416 specific clock functions */
-
-typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
-
-extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
-extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
-				       unsigned int *divs, int nr_divs,
-				       int divmask);
-
-extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
-
-/* S3C64XX specific functions and clocks */
-
-extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
-
-/* Global watchdog clock used by arch_wtd_reset() callback */
-
-extern struct clk *s3c2410_wdtclk;
-
-#endif /* __ASM_PLAT_CLOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	2014-09-28 17:29:07.000000000 -0400
@@ -140,7 +140,6 @@ struct s3c_cpufreq_config {
  *	any frequency changes. This is really only need by devices like the
  *	S3C2410 where there is no or limited divider between the PLL and the
  *	ARMCLK.
- * @resume_clocks: Update the clocks on resume.
  * @get_iotiming: Get the current IO timing data, mainly for use at start.
  * @set_iotiming: Update the IO timings from the cached copies calculated
  *	from the @calc_iotiming entry when changing the frequency.
@@ -169,8 +168,6 @@ struct s3c_cpufreq_info {
 
 	/* driver routines */
 
-	void		(*resume_clocks)(void);
-
 	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
 					struct s3c_iotimings *timings);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/cpu.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/cpu.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,13 +33,6 @@ extern unsigned long samsung_cpu_id;
 #define S3C6410_CPU_ID		0x36410000
 #define S3C64XX_CPU_MASK	0xFFFFF000
 
-#define S5P6440_CPU_ID		0x56440000
-#define S5P6450_CPU_ID		0x36450000
-#define S5P64XX_CPU_MASK	0xFFFFF000
-
-#define S5PC100_CPU_ID		0x43100000
-#define S5PC100_CPU_MASK	0xFFFFF000
-
 #define S5PV210_CPU_ID		0x43110000
 #define S5PV210_CPU_MASK	0xFFFFF000
 
@@ -54,10 +47,6 @@ IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID,
 IS_SAMSUNG_CPU(s3c2412, S3C2412_CPU_ID, S3C2412_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
-IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
 
 #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
     defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
@@ -86,30 +75,6 @@ IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID,
 # define soc_is_s3c64xx()	0
 #endif
 
-#if defined(CONFIG_CPU_S5P6440)
-# define soc_is_s5p6440()	is_samsung_s5p6440()
-#else
-# define soc_is_s5p6440()	0
-#endif
-
-#if defined(CONFIG_CPU_S5P6450)
-# define soc_is_s5p6450()	is_samsung_s5p6450()
-#else
-# define soc_is_s5p6450()	0
-#endif
-
-#if defined(CONFIG_CPU_S5PC100)
-# define soc_is_s5pc100()	is_samsung_s5pc100()
-#else
-# define soc_is_s5pc100()	0
-#endif
-
-#if defined(CONFIG_CPU_S5PV210)
-# define soc_is_s5pv210()	is_samsung_s5pv210()
-#else
-# define soc_is_s5pv210()	0
-#endif
-
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef KHZ
@@ -145,12 +110,9 @@ extern void s3c_init_cpu(unsigned long i
 
 /* core initialisation functions */
 
-extern void s5p_init_irq(u32 *vic, u32 num_vic);
-
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
 
 extern void s3c64xx_init_cpu(void);
-extern void s5p_init_cpu(void __iomem *cpuid_addr);
 
 extern unsigned int samsung_rev(void);
 
@@ -177,9 +139,5 @@ extern struct bus_type s3c2440_subsys;
 extern struct bus_type s3c2442_subsys;
 extern struct bus_type s3c2443_subsys;
 extern struct bus_type s3c6410_subsys;
-extern struct bus_type s5p64x0_subsys;
-extern struct bus_type s5pv210_subsys;
-
-extern void (*s5pc1xx_idle)(void);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/devs.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/devs.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/devs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/devs.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,9 +25,6 @@ struct s3c24xx_uart_resources {
 
 extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
 extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
-extern struct s3c24xx_uart_resources s5p_uart_resources[];
-extern struct s3c24xx_uart_resources exynos4_uart_resources[];
-extern struct s3c24xx_uart_resources exynos5_uart_resources[];
 
 extern struct platform_device *s3c24xx_uart_devs[];
 extern struct platform_device *s3c24xx_uart_src[];
@@ -75,62 +72,6 @@ extern struct platform_device s3c_device
 extern struct platform_device s3c_device_usb_hsudc;
 extern struct platform_device s3c_device_wdt;
 
-extern struct platform_device s5p_device_fimc0;
-extern struct platform_device s5p_device_fimc1;
-extern struct platform_device s5p_device_fimc2;
-extern struct platform_device s5p_device_fimc3;
-extern struct platform_device s5p_device_fimc_md;
-extern struct platform_device s5p_device_jpeg;
-extern struct platform_device s5p_device_g2d;
-extern struct platform_device s5p_device_fimd0;
-extern struct platform_device s5p_device_hdmi;
-extern struct platform_device s5p_device_i2c_hdmiphy;
-extern struct platform_device s5p_device_mfc;
-extern struct platform_device s5p_device_mfc_l;
-extern struct platform_device s5p_device_mfc_r;
-extern struct platform_device s5p_device_mipi_csis0;
-extern struct platform_device s5p_device_mipi_csis1;
-extern struct platform_device s5p_device_mixer;
-extern struct platform_device s5p_device_onenand;
-extern struct platform_device s5p_device_sdo;
-
-extern struct platform_device s5p6440_device_iis;
-extern struct platform_device s5p6440_device_pcm;
-
-extern struct platform_device s5p6450_device_iis0;
-extern struct platform_device s5p6450_device_iis1;
-extern struct platform_device s5p6450_device_iis2;
-extern struct platform_device s5p6450_device_pcm0;
-
-
-extern struct platform_device s5pc100_device_ac97;
-extern struct platform_device s5pc100_device_iis0;
-extern struct platform_device s5pc100_device_iis1;
-extern struct platform_device s5pc100_device_iis2;
-extern struct platform_device s5pc100_device_pcm0;
-extern struct platform_device s5pc100_device_pcm1;
-extern struct platform_device s5pc100_device_spdif;
-
-extern struct platform_device s5pv210_device_ac97;
-extern struct platform_device s5pv210_device_iis0;
-extern struct platform_device s5pv210_device_iis1;
-extern struct platform_device s5pv210_device_iis2;
-extern struct platform_device s5pv210_device_pcm0;
-extern struct platform_device s5pv210_device_pcm1;
-extern struct platform_device s5pv210_device_pcm2;
-extern struct platform_device s5pv210_device_spdif;
-
-extern struct platform_device exynos4_device_ac97;
-extern struct platform_device exynos4_device_ahci;
-extern struct platform_device exynos4_device_i2s0;
-extern struct platform_device exynos4_device_i2s1;
-extern struct platform_device exynos4_device_i2s2;
-extern struct platform_device exynos4_device_ohci;
-extern struct platform_device exynos4_device_pcm0;
-extern struct platform_device exynos4_device_pcm1;
-extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_spdif;
-
 extern struct platform_device samsung_asoc_idma;
 extern struct platform_device samsung_device_keypad;
 extern struct platform_device samsung_device_pwm;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fb-core.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fb-core.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fb-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fb-core.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,19 +26,4 @@ static inline void s3c_fb_setname(char *
 #endif
 }
 
-/* Re-define device name depending on support. */
-static inline void s5p_fb_setname(int id, char *name)
-{
-	switch (id) {
-#ifdef CONFIG_S5P_DEV_FIMD0
-	case 0:
-		s5p_device_fimd0.name = name;
-	break;
-#endif
-	default:
-		printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
-	break;
-	}
-}
-
 #endif /* __ASM_PLAT_FB_CORE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fb.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fb.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fb.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,46 +26,10 @@
 extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
 
 /**
- * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
- * @pd: The platform data to set. The data is copied from the passed structure
- *      so the machine data can mark the data __initdata so that any unused
- *      machines will end up dumping their data at runtime.
- */
-extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
-
-/**
  * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
  *
  * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
  */
 extern void s3c64xx_fb_gpio_setup_24bpp(void);
 
-/**
- * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5pc100_fb_gpio_setup_24bpp(void);
-
-/**
- * s5pv210_fb_gpio_setup_24bpp() - S5PV210/S5PC110 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5pv210_fb_gpio_setup_24bpp(void);
-
-/**
- * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
- */
-extern void exynos4_fimd0_gpio_setup_24bpp(void);
-
-/**
- * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5p64x0_fb_gpio_setup_24bpp(void);
-
 #endif /* __PLAT_S3C_FB_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/*
- * arch/arm/plat-samsung/include/plat/fimc-core.h
- *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- *	Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * Samsung camera interface driver core functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_PLAT_FIMC_CORE_H
-#define __ASM_PLAT_FIMC_CORE_H __FILE__
-
-/*
- * These functions are only for use with the core support code, such as
- * the CPU-specific initialization code.
- */
-
-/* Re-define device name to differentiate the subsystem in various SoCs. */
-static inline void s3c_fimc_setname(int id, char *name)
-{
-	switch (id) {
-#ifdef CONFIG_S5P_DEV_FIMC0
-	case 0:
-		s5p_device_fimc0.name = name;
-		break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC1
-	case 1:
-		s5p_device_fimc1.name = name;
-		break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC2
-	case 2:
-		s5p_device_fimc2.name = name;
-		break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC3
-	case 3:
-		s5p_device_fimc3.name = name;
-		break;
-#endif
-	default:
-		break;
-	}
-}
-
-#endif /* __ASM_PLAT_FIMC_CORE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 
 typedef unsigned int __bitwise__ samsung_gpio_pull_t;
-typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
 struct samsung_gpio_chip;
@@ -180,67 +179,4 @@ static inline int s3c_gpio_cfgrange_nopu
 	return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE);
 }
 
-/* Define values for the drvstr available for each gpio pin.
- *
- * These values control the value of the output signal driver strength,
- * configurable on most pins on the S5P series.
- */
-#define S5P_GPIO_DRVSTR_LV1	((__force s5p_gpio_drvstr_t)0x0)
-#define S5P_GPIO_DRVSTR_LV2	((__force s5p_gpio_drvstr_t)0x2)
-#define S5P_GPIO_DRVSTR_LV3	((__force s5p_gpio_drvstr_t)0x1)
-#define S5P_GPIO_DRVSTR_LV4	((__force s5p_gpio_drvstr_t)0x3)
-
-/**
- * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin
- * @pin: The pin number to get the settings for
- *
- * Read the driver streght value for the specified pin.
-*/
-extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);
-
-/**
- * s3c_gpio_set_drvstr() - set the driver streght value of a gpio pin
- * @pin: The pin number to configure the driver streght value
- * @drvstr: The new value of the driver strength
- *
- * This function sets the driver strength value for the specified pin.
- * It will return 0 if successful, or a negative error code if the pin
- * cannot support the requested setting.
-*/
-extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
-
-/**
- * s5p_register_gpio_interrupt() - register interrupt support for a gpio group
- * @pin: The pin number from the group to be registered
- *
- * This function registers gpio interrupt support for the group that the
- * specified pin belongs to.
- *
- * The total number of gpio pins is quite large ob s5p series. Registering
- * irq support for all of them would be a resource waste. Because of that the
- * interrupt support for standard gpio pins is registered dynamically.
- *
- * It will return the irq number of the interrupt that has been registered
- * or -ENOMEM if no more gpio interrupts can be registered. It is allowed
- * to call this function more than once for the same gpio group (the group
- * will be registered only once).
- */
-extern int s5p_register_gpio_interrupt(int pin);
-
-/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
- * registration (see s5p_register_gpio_interrupt function)
- * @chain_irq: chained irq number for the gpio int handler for this bank
- * @start: start gpio group number of this bank
- * @nr_groups: number of gpio groups handled by this bank
- *
- * This functions registers initial information about gpio banks that
- * can be later used by the s5p_register_gpio_interrupt() function to
- * enable support for gpio interrupt for particular gpio group.
- */
-#ifdef CONFIG_S5P_GPIO_INT
-extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
-#else
-#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
-#endif
-
 #endif /* __PLAT_GPIO_CFG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,9 @@
 #ifndef __PLAT_SAMSUNG_GPIO_CORE_H
 #define __PLAT_SAMSUNG_GPIO_CORE_H
 
+/* Bring in machine-local definitions, especially S3C_GPIO_END */
+#include <mach/gpio-samsung.h>
+
 #define GPIOCON_OFF	(0x00)
 #define GPIODAT_OFF	(0x04)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/hdmi.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/hdmi.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/hdmi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/hdmi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_HDMI_H
-#define __PLAT_SAMSUNG_HDMI_H __FILE__
-
-extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
-				  struct i2c_board_info *mhl_info, int mhl_bus);
-
-#endif /* __PLAT_SAMSUNG_HDMI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/irqs.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/irqs.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/irqs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/irqs.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P Common IRQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_SAMSUNG_IRQS_H
-#define __PLAT_SAMSUNG_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S5P_IRQ_OFFSET		(32)
-
-#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
-
-#define S5P_VIC0_BASE		S5P_IRQ(0)
-#define S5P_VIC1_BASE		S5P_IRQ(32)
-#define S5P_VIC2_BASE		S5P_IRQ(64)
-#define S5P_VIC3_BASE		S5P_IRQ(96)
-
-#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
-
-#define IRQ_VIC0_BASE		S5P_VIC0_BASE
-#define IRQ_VIC1_BASE		S5P_VIC1_BASE
-#define IRQ_VIC2_BASE		S5P_VIC2_BASE
-
-/* VIC based IRQs */
-
-#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
-#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
-#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
-#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
-
-#define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
-					: ((x) - 16 + S5P_EINT_BASE2))
-
-#define EINT_OFFSET(irq)	((irq) < S5P_EINT_BASE2 ? \
-						((irq) - S5P_EINT_BASE1) : \
-						((irq) + 16 - S5P_EINT_BASE2))
-
-#define IRQ_EINT_BIT(x)		EINT_OFFSET(x)
-
-/* Typically only a few gpio chips require gpio interrupt support.
-   To avoid memory waste irq descriptors are allocated only for
-   S5P_GPIOINT_GROUP_COUNT chips, each with total number of
-   S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
-   to any gpio chip with the s5p_register_gpio_interrupt() function */
-#define S5P_GPIOINT_GROUP_COUNT 4
-#define S5P_GPIOINT_GROUP_SIZE	8
-#define S5P_GPIOINT_COUNT	(S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
-
-/* IRQ types common for all s5p platforms */
-#define S5P_IRQ_TYPE_LEVEL_LOW		(0x00)
-#define S5P_IRQ_TYPE_LEVEL_HIGH		(0x01)
-#define S5P_IRQ_TYPE_EDGE_FALLING	(0x02)
-#define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
-#define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
-
-#endif /* __PLAT_SAMSUNG_IRQS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,6 @@
 
 #define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
 #define S5P_VA_CMU		S3C_ADDR(0x02100000)
-#define S5P_VA_PMU		S3C_ADDR(0x02180000)
 #define S5P_VA_GPIO		S3C_ADDR(0x02200000)
 #define S5P_VA_GPIO1		S5P_VA_GPIO
 #define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/mfc.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/mfc.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/mfc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/mfc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_MFC_H
-#define __PLAT_SAMSUNG_MFC_H __FILE__
-
-struct s5p_mfc_dt_meminfo {
-	unsigned long	loff;
-	unsigned long	lsize;
-	unsigned long	roff;
-	unsigned long	rsize;
-	char		*compatible;
-};
-
-/**
- * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
- * @rbase:	base address for MFC 'right' memory interface
- * @rsize:	size of the memory reserved for MFC 'right' interface
- * @lbase:	base address for MFC 'left' memory interface
- * @lsize:	size of the memory reserved for MFC 'left' interface
- *
- * This function reserves system memory for both MFC device memory
- * interfaces and registers it to respective struct device entries as
- * coherent memory.
- */
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
-				phys_addr_t lbase, unsigned int lsize);
-
-#endif /* __PLAT_SAMSUNG_MFC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/pll.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/pll.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/pll.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,323 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/pll.h
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Samsung PLL codes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <asm/div64.h>
-
-#define S3C24XX_PLL_MDIV_MASK		(0xFF)
-#define S3C24XX_PLL_PDIV_MASK		(0x1F)
-#define S3C24XX_PLL_SDIV_MASK		(0x3)
-#define S3C24XX_PLL_MDIV_SHIFT		(12)
-#define S3C24XX_PLL_PDIV_SHIFT		(4)
-#define S3C24XX_PLL_SDIV_SHIFT		(0)
-
-static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
-					   unsigned int baseclk)
-{
-	unsigned int mdiv, pdiv, sdiv;
-	uint64_t fvco;
-
-	mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
-	pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
-	sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
-
-	fvco = (uint64_t)baseclk * (mdiv + 8);
-	do_div(fvco, (pdiv + 2) << sdiv);
-
-	return (unsigned int)fvco;
-}
-
-#define S3C2416_PLL_MDIV_MASK		(0x3FF)
-#define S3C2416_PLL_PDIV_MASK		(0x3F)
-#define S3C2416_PLL_SDIV_MASK		(0x7)
-#define S3C2416_PLL_MDIV_SHIFT		(14)
-#define S3C2416_PLL_PDIV_SHIFT		(5)
-#define S3C2416_PLL_SDIV_SHIFT		(0)
-
-static inline unsigned int s3c2416_get_pll(unsigned int pllval,
-					   unsigned int baseclk)
-{
-	unsigned int mdiv, pdiv, sdiv;
-	uint64_t fvco;
-
-	mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
-	pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
-	sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
-
-	fvco = (uint64_t)baseclk * mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned int)fvco;
-}
-
-#define S3C6400_PLL_MDIV_MASK		(0x3FF)
-#define S3C6400_PLL_PDIV_MASK		(0x3F)
-#define S3C6400_PLL_SDIV_MASK		(0x7)
-#define S3C6400_PLL_MDIV_SHIFT		(16)
-#define S3C6400_PLL_PDIV_SHIFT		(8)
-#define S3C6400_PLL_SDIV_SHIFT		(0)
-
-static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
-					    u32 pllcon)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
-	pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
-	sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-#define PLL6553X_MDIV_MASK	(0x7F)
-#define PLL6553X_PDIV_MASK	(0x1F)
-#define PLL6553X_SDIV_MASK	(0x3)
-#define PLL6553X_KDIV_MASK	(0xFFFF)
-#define PLL6553X_MDIV_SHIFT	(16)
-#define PLL6553X_PDIV_SHIFT	(8)
-#define PLL6553X_SDIV_SHIFT	(0)
-
-static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
-					     u32 pll_con0, u32 pll_con1)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
-	pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
-	sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
-	kdiv = pll_con1 & PLL6553X_KDIV_MASK;
-
-	/*
-	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
-
-#define PLL35XX_MDIV_MASK	(0x3FF)
-#define PLL35XX_PDIV_MASK	(0x3F)
-#define PLL35XX_SDIV_MASK	(0x7)
-#define PLL35XX_MDIV_SHIFT	(16)
-#define PLL35XX_PDIV_SHIFT	(8)
-#define PLL35XX_SDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-#define PLL36XX_KDIV_MASK	(0xFFFF)
-#define PLL36XX_MDIV_MASK	(0x1FF)
-#define PLL36XX_PDIV_MASK	(0x3F)
-#define PLL36XX_SDIV_MASK	(0x7)
-#define PLL36XX_MDIV_SHIFT	(16)
-#define PLL36XX_PDIV_SHIFT	(8)
-#define PLL36XX_SDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
-					    u32 pll_con0, u32 pll_con1)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
-	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
-	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
-	kdiv = pll_con1 & PLL36XX_KDIV_MASK;
-
-	tmp = baseclk;
-
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
-
-#define PLL45XX_MDIV_MASK	(0x3FF)
-#define PLL45XX_PDIV_MASK	(0x3F)
-#define PLL45XX_SDIV_MASK	(0x7)
-#define PLL45XX_MDIV_SHIFT	(16)
-#define PLL45XX_PDIV_SHIFT	(8)
-#define PLL45XX_SDIV_SHIFT	(0)
-
-enum pll45xx_type_t {
-	pll_4500,
-	pll_4502,
-	pll_4508
-};
-
-static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
-					    enum pll45xx_type_t pll_type)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
-
-	if (pll_type == pll_4508)
-		sdiv = sdiv - 1;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-/* CON0 bit-fields */
-#define PLL46XX_MDIV_MASK	(0x1FF)
-#define PLL46XX_PDIV_MASK	(0x3F)
-#define PLL46XX_SDIV_MASK	(0x7)
-#define PLL46XX_LOCKED_SHIFT	(29)
-#define PLL46XX_MDIV_SHIFT	(16)
-#define PLL46XX_PDIV_SHIFT	(8)
-#define PLL46XX_SDIV_SHIFT	(0)
-
-/* CON1 bit-fields */
-#define PLL46XX_MRR_MASK	(0x1F)
-#define PLL46XX_MFR_MASK	(0x3F)
-#define PLL46XX_KDIV_MASK	(0xFFFF)
-#define PLL4650C_KDIV_MASK	(0xFFF)
-#define PLL46XX_MRR_SHIFT	(24)
-#define PLL46XX_MFR_SHIFT	(16)
-#define PLL46XX_KDIV_SHIFT	(0)
-
-enum pll46xx_type_t {
-	pll_4600,
-	pll_4650,
-	pll_4650c,
-};
-
-static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
-					    u32 pll_con0, u32 pll_con1,
-					    enum pll46xx_type_t pll_type)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
-	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
-	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
-	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	if (pll_type == pll_4650c)
-		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
-	else
-		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	tmp = baseclk;
-
-	if (pll_type == pll_4600) {
-		tmp *= (mdiv << 16) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 16;
-	} else {
-		tmp *= (mdiv << 10) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 10;
-	}
-
-	return result;
-}
-
-#define PLL90XX_MDIV_MASK	(0xFF)
-#define PLL90XX_PDIV_MASK	(0x3F)
-#define PLL90XX_SDIV_MASK	(0x7)
-#define PLL90XX_KDIV_MASK	(0xffff)
-#define PLL90XX_LOCKED_SHIFT	(29)
-#define PLL90XX_MDIV_SHIFT	(16)
-#define PLL90XX_PDIV_SHIFT	(8)
-#define PLL90XX_SDIV_SHIFT	(0)
-#define PLL90XX_KDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
-					    u32 pll_con, u32 pll_conk)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
-	kdiv = pll_conk & PLL90XX_KDIV_MASK;
-
-	/*
-	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
-
-#define PLL65XX_MDIV_MASK	(0x3FF)
-#define PLL65XX_PDIV_MASK	(0x3F)
-#define PLL65XX_SDIV_MASK	(0x7)
-#define PLL65XX_MDIV_SHIFT	(16)
-#define PLL65XX_PDIV_SHIFT	(8)
-#define PLL65XX_SDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_CLOCK_H
-#define __ASM_PLAT_S5P_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_bpll clk_ext_xtal_mux
-#define clk_fin_cpll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-#define clk_fin_dpll clk_ext_xtal_mux
-#define clk_fin_vpll clk_ext_xtal_mux
-#define clk_fin_hpll clk_ext_xtal_mux
-
-extern struct clk clk_ext_xtal_mux;
-extern struct clk clk_xusbxti;
-extern struct clk clk_48m;
-extern struct clk s5p_clk_27m;
-extern struct clk clk_fout_apll;
-extern struct clk clk_fout_bpll;
-extern struct clk clk_fout_bpll_div2;
-extern struct clk clk_fout_cpll;
-extern struct clk clk_fout_mpll;
-extern struct clk clk_fout_mpll_div2;
-extern struct clk clk_fout_epll;
-extern struct clk clk_fout_dpll;
-extern struct clk clk_fout_vpll;
-extern struct clk clk_arm;
-extern struct clk clk_vpll;
-
-extern struct clksrc_sources clk_src_apll;
-extern struct clksrc_sources clk_src_bpll;
-extern struct clksrc_sources clk_src_bpll_fout;
-extern struct clksrc_sources clk_src_cpll;
-extern struct clksrc_sources clk_src_mpll;
-extern struct clksrc_sources clk_src_mpll_fout;
-extern struct clksrc_sources clk_src_epll;
-extern struct clksrc_sources clk_src_dpll;
-
-extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
-
-/* Common EPLL operations for S5P platform */
-extern int s5p_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p_epll_get_rate(struct clk *clk);
-
-/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
-extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
-extern unsigned long s5p_spdif_get_rate(struct clk *clk);
-
-extern struct clk_ops s5p_sclk_spdif_ops;
-#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/sdhci.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/sdhci.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,22 +56,7 @@ extern void s3c2416_setup_sdhci0_cfg_gpi
 extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
 extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
 extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
 extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
 
 /* S3C2416 SDHCI setup */
 
@@ -151,115 +136,6 @@ static inline void s3c6400_default_sdhci
 
 #endif /* CONFIG_S3C64XX_SETUP_SDHCI */
 
-/* S5P64X0 SDHCI setup */
-
-#ifdef CONFIG_S5P64X0_SETUP_SDHCI_GPIO
-static inline void s5p64x0_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5p64x0_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5p64x0_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5p64x0_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5p6440_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5p6440_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-static inline void s5p6450_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5p6450_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5p64x0_default_sdhci0(void) { }
-static inline void s5p64x0_default_sdhci1(void) { }
-static inline void s5p6440_default_sdhci2(void) { }
-static inline void s5p6450_default_sdhci2(void) { }
-
-#endif /* CONFIG_S5P64X0_SETUP_SDHCI_GPIO */
-
-/* S5PC100 SDHCI setup */
-
-#ifdef CONFIG_S5PC100_SETUP_SDHCI
-static inline void s5pc100_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5pc100_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5pc100_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5pc100_default_sdhci0(void) { }
-static inline void s5pc100_default_sdhci1(void) { }
-static inline void s5pc100_default_sdhci2(void) { }
-
-#endif /* CONFIG_S5PC100_SETUP_SDHCI */
-
-/* S5PV210 SDHCI setup */
-
-#ifdef CONFIG_S5PV210_SETUP_SDHCI
-static inline void s5pv210_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci3(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC3
-	s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5pv210_default_sdhci0(void) { }
-static inline void s5pv210_default_sdhci1(void) { }
-static inline void s5pv210_default_sdhci2(void) { }
-static inline void s5pv210_default_sdhci3(void) { }
-
-#endif /* CONFIG_S5PV210_SETUP_SDHCI */
-
 static inline void s3c_sdhci_setname(int id, char *name)
 {
 	switch (id) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/tv-core.h linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/tv-core.h
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/include/plat/tv-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/include/plat/tv-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * arch/arm/plat-samsung/include/plat/tv.h
- *
- * Copyright 2011 Samsung Electronics Co., Ltd.
- *	Tomasz Stanislawski <t.stanislaws@samsung.com>
- *
- * Samsung TV driver core functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __SAMSUNG_PLAT_TV_H
-#define __SAMSUNG_PLAT_TV_H __FILE__
-
-/*
- * These functions are only for use with the core support code, such as
- * the CPU-specific initialization code.
- */
-
-/* Re-define device name to differentiate the subsystem in various SoCs. */
-static inline void s5p_hdmi_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
-	s5p_device_hdmi.name = name;
-#endif
-}
-
-static inline void s5p_mixer_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
-	s5p_device_mixer.name = name;
-#endif
-}
-
-static inline void s5p_sdo_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
-	s5p_device_sdo.name = name;
-#endif
-}
-
-#endif /* __SAMSUNG_PLAT_TV_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/init.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/init.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,6 @@
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/clock.h>
 
 static struct cpu_table *cpu;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/Kconfig
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -6,30 +6,16 @@
 
 config PLAT_SAMSUNG
 	bool
-	depends on PLAT_S3C24XX || ARCH_S3C64XX || PLAT_S5P || ARCH_EXYNOS
+	depends on PLAT_S3C24XX || ARCH_S3C64XX || ARCH_EXYNOS || ARCH_S5PV210
 	default y
 	select GENERIC_IRQ_CHIP
 	select NO_IOPORT_MAP
 	help
 	  Base platform code for all Samsung SoC based systems
 
-config PLAT_S5P
-	bool
-	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
-	default y
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_VIC
-	select NO_IOPORT_MAP
-	select PLAT_SAMSUNG
-	select S3C_GPIO_TRACK
-	select S5P_GPIO_DRVSTR
-	select SAMSUNG_CLKSRC if !COMMON_CLK
-	help
-	  Base platform code for Samsung's S5P series SoC.
-
 config SAMSUNG_PM
 	bool
-	depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || S5P_PM)
+	depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX)
 	default y
 	help
 	  Base platform power management code for samsung code
@@ -65,65 +51,6 @@ config SAMSUNG_ATAGS
 
 if SAMSUNG_ATAGS
 
-# clock options
-
-config SAMSUNG_CLOCK
-	bool
-	default y if !COMMON_CLK
-
-config SAMSUNG_CLKSRC
-	bool
-	help
-	  Select the clock code for the clksrc implementation
-	  used by newer systems such as the S3C64XX.
-
-config S5P_CLOCK
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
-	help
-	  Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
-
-# options for IRQ support
-
-config S5P_IRQ
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
-	help
-	  Support common interrupt part for ARCH_S5P SoCs
-
-config S5P_EXT_INT
-	bool
-	help
-	  Use the external interrupts (other than GPIO interrupts.)
-	  Note: Do not choose this for S5P6440 and S5P6450.
-
-config S5P_GPIO_INT
-	bool
-	help
-	  Common code for the GPIO interrupts (other than external interrupts.)
-
-# options for gpio configuration support
-
-config S5P_GPIO_DRVSTR
-	bool
-	help
-	  Internal configuration to get and set correct GPIO driver strength
-	  helper
-
-config SAMSUNG_GPIO_EXTRA
-	int "Number of additional GPIO pins"
-	default 128 if SAMSUNG_GPIO_EXTRA128
-	default 64 if SAMSUNG_GPIO_EXTRA64
-	default 0
-	help
-	  Use additional GPIO space in addition to the GPIO's the SOC
-	  provides. This allows expanding the GPIO space for use with
-	  GPIO expanders.
-
-config SAMSUNG_GPIO_EXTRA64
-	bool
-
-config SAMSUNG_GPIO_EXTRA128
-	bool
-
 config S3C_GPIO_SPACE
 	int "Space between gpio banks"
 	default 0
@@ -139,12 +66,6 @@ config S3C_GPIO_TRACK
 	  Internal configuration option to enable the s3c specific gpio
 	  chip tracking if the platform requires it.
 
-# uart options
-
-config S5P_DEV_UART
-	def_bool y
-	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
-
 # ADC driver
 
 config S3C_ADC
@@ -302,66 +223,6 @@ config SAMSUNG_DEV_BACKLIGHT
 	help
 	  Compile in platform device definition LCD backlight with PWM Timer
 
-config S5P_DEV_CSIS0
-	bool
-	help
-	  Compile in platform device definitions for MIPI-CSIS channel 0
-
-config S5P_DEV_CSIS1
-	bool
-	help
-	  Compile in platform device definitions for MIPI-CSIS channel 1
-
-config S5P_DEV_FIMC0
-	bool
-	help
-	  Compile in platform device definitions for FIMC controller 0
-
-config S5P_DEV_FIMC1
-	bool
-	help
-	  Compile in platform device definitions for FIMC controller 1
-
-config S5P_DEV_FIMC2
-	bool
-	help
-	  Compile in platform device definitions for FIMC controller 2
-
-config S5P_DEV_FIMC3
-	bool
-	help
-	  Compile in platform device definitions for FIMC controller 3
-
-config S5P_DEV_FIMD0
-	bool
-	help
-	  Compile in platform device definitions for FIMD controller 0
-
-config S5P_DEV_G2D
-	bool
-	help
-	  Compile in platform device definitions for G2D device
-
-config S5P_DEV_I2C_HDMIPHY
-	bool
-	help
-	  Compile in platform device definitions for I2C HDMIPHY controller
-
-config S5P_DEV_JPEG
-	bool
-	help
-	  Compile in platform device definitions for JPEG codec
-
-config S5P_DEV_ONENAND
-	bool
-	help
-	  Compile in platform device definition for OneNAND controller
-
-config S5P_DEV_TV
-	bool
-	help
-	  Compile in platform device definition for TV interface
-
 config S3C24XX_PWM
 	bool "PWM device support"
 	select PWM
@@ -382,12 +243,6 @@ config S3C_DMA
 	help
 	  Internal configuration for S3C DMA core
 
-config S5P_IRQ_PM
-	bool
-	default y if S5P_PM
-	help
-	  Legacy IRQ power management for S5P platforms
-
 config SAMSUNG_PM_GPIO
 	bool
 	default y if GPIO_SAMSUNG && PM
@@ -397,7 +252,7 @@ config SAMSUNG_PM_GPIO
 
 config SAMSUNG_DMADEV
 	bool "Use legacy Samsung DMA abstraction"
-	depends on CPU_S5PV210 || CPU_S5PC100 || ARCH_S5P64X0 || ARCH_S3C64XX
+	depends on CPU_S5PV210 || ARCH_S3C64XX
 	select DMADEVICES
 	default y
 	help
@@ -470,18 +325,6 @@ config SAMSUNG_WDT_RESET
 	  Compile support for system restart by triggering watchdog reset.
 	  Used on SoCs that do not provide dedicated reset control.
 
-config S5P_PM
-	bool
-	help
-	  Common code for power management support on S5P and newer SoCs
-	  Note: Do not select this for S5P6440 and S5P6450.
-
-config S5P_SLEEP
-	bool
-	help
-	  Internal config node to apply common S5P sleep management code.
-	  Can be selected by S5P and newer SoCs with similar sleep procedure.
-
 config DEBUG_S3C_UART
 	depends on PLAT_SAMSUNG
 	int
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/Makefile linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/Makefile
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,7 +5,6 @@
 # Licensed under GPLv2
 
 ccflags-$(CONFIG_ARCH_MULTI_V7) += -I$(srctree)/$(src)/include
-ccflags-$(CONFIG_ARCH_EXYNOS)	+= -I$(srctree)/arch/arm/mach-exynos/include
 
 obj-y				:=
 obj-m				:=
@@ -16,15 +15,6 @@ obj-				:=
 
 obj-y				+= init.o cpu.o
 
-obj-$(CONFIG_SAMSUNG_CLOCK)	+= clock.o
-
-obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
-obj-$(CONFIG_S5P_CLOCK)		+= s5p-clock.o
-
-obj-$(CONFIG_S5P_IRQ)		+= s5p-irq.o
-obj-$(CONFIG_S5P_EXT_INT)	+= s5p-irq-eint.o
-obj-$(CONFIG_S5P_GPIO_INT)	+= s5p-irq-gpioint.o
-
 # ADC
 
 obj-$(CONFIG_S3C_ADC)	+= adc.o
@@ -36,7 +26,6 @@ obj-$(CONFIG_SAMSUNG_ATAGS)	+= platformd
 obj-$(CONFIG_SAMSUNG_ATAGS)	+= devs.o
 obj-$(CONFIG_SAMSUNG_ATAGS)	+= dev-uart.o
 obj-$(CONFIG_S5P_DEV_MFC)	+= s5p-dev-mfc.o
-obj-$(CONFIG_S5P_DEV_UART)	+= s5p-dev-uart.o
 
 obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)	+= dev-backlight.o
 
@@ -58,7 +47,3 @@ obj-$(CONFIG_SAMSUNG_PM_DEBUG)	+= pm-deb
 
 obj-$(CONFIG_SAMSUNG_WAKEMASK)	+= wakeup-mask.o
 obj-$(CONFIG_SAMSUNG_WDT_RESET)	+= watchdog-reset.o
-
-obj-$(CONFIG_S5P_PM)		+= s5p-pm.o
-obj-$(CONFIG_S5P_IRQ_PM)	+= s5p-irq-pm.o
-obj-$(CONFIG_S5P_SLEEP)		+= s5p-sleep.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/pm-gpio.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/pm-gpio.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/pm-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/pm-gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,9 +19,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
 #include <mach/gpio-samsung.h>
-#endif
 
 #include <plat/gpio-core.h>
 #include <plat/pm.h>
@@ -196,7 +194,7 @@ struct samsung_gpio_pm samsung_gpio_pm_2
 	.resume = samsung_gpio_pm_2bit_resume,
 };
 
-#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
+#if defined(CONFIG_ARCH_S3C64XX)
 static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
@@ -306,7 +304,7 @@ struct samsung_gpio_pm samsung_gpio_pm_4
 	.save	= samsung_gpio_pm_4bit_save,
 	.resume = samsung_gpio_pm_4bit_resume,
 };
-#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
+#endif /* CONFIG_ARCH_S3C64XX */
 
 /**
  * samsung_pm_save_gpio() - save gpio chip data for suspend
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-clock.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-clock.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,294 +0,0 @@
-/*
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - Common clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/s5p-clock.h>
-
-/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
- * clk_ext_xtal_mux.
-*/
-struct clk clk_ext_xtal_mux = {
-	.name		= "ext_xtal",
-	.id		= -1,
-};
-
-struct clk clk_xusbxti = {
-	.name		= "xusbxti",
-	.id		= -1,
-	.rate		= 24000000,
-};
-
-struct clk s5p_clk_27m = {
-	.name		= "clk_27m",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-/* 48MHz USB Phy clock output */
-struct clk clk_48m = {
-	.name		= "clk_48m",
-	.id		= -1,
-	.rate		= 48000000,
-};
-
-/* APLL clock output
- * No need .ctrlbit, this is always on
-*/
-struct clk clk_fout_apll = {
-	.name		= "fout_apll",
-	.id		= -1,
-};
-
-/* BPLL clock output */
-
-struct clk clk_fout_bpll = {
-	.name		= "fout_bpll",
-	.id		= -1,
-};
-
-struct clk clk_fout_bpll_div2 = {
-	.name		= "fout_bpll_div2",
-	.id		= -1,
-};
-
-/* CPLL clock output */
-
-struct clk clk_fout_cpll = {
-	.name		= "fout_cpll",
-	.id		= -1,
-};
-
-/* MPLL clock output
- * No need .ctrlbit, this is always on
-*/
-struct clk clk_fout_mpll = {
-	.name		= "fout_mpll",
-	.id		= -1,
-};
-
-struct clk clk_fout_mpll_div2 = {
-	.name		= "fout_mpll_div2",
-	.id		= -1,
-};
-
-/* EPLL clock output */
-struct clk clk_fout_epll = {
-	.name		= "fout_epll",
-	.id		= -1,
-	.ctrlbit	= (1 << 31),
-};
-
-/* DPLL clock output */
-struct clk clk_fout_dpll = {
-	.name		= "fout_dpll",
-	.id		= -1,
-	.ctrlbit	= (1 << 31),
-};
-
-/* VPLL clock output */
-struct clk clk_fout_vpll = {
-	.name		= "fout_vpll",
-	.id		= -1,
-	.ctrlbit	= (1 << 31),
-};
-
-/* Possible clock sources for APLL Mux */
-static struct clk *clk_src_apll_list[] = {
-	[0] = &clk_fin_apll,
-	[1] = &clk_fout_apll,
-};
-
-struct clksrc_sources clk_src_apll = {
-	.sources	= clk_src_apll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
-};
-
-/* Possible clock sources for BPLL Mux */
-static struct clk *clk_src_bpll_list[] = {
-	[0] = &clk_fin_bpll,
-	[1] = &clk_fout_bpll,
-};
-
-struct clksrc_sources clk_src_bpll = {
-	.sources	= clk_src_bpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_bpll_list),
-};
-
-static struct clk *clk_src_bpll_fout_list[] = {
-	[0] = &clk_fout_bpll_div2,
-	[1] = &clk_fout_bpll,
-};
-
-struct clksrc_sources clk_src_bpll_fout = {
-	.sources	= clk_src_bpll_fout_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_bpll_fout_list),
-};
-
-/* Possible clock sources for CPLL Mux */
-static struct clk *clk_src_cpll_list[] = {
-	[0] = &clk_fin_cpll,
-	[1] = &clk_fout_cpll,
-};
-
-struct clksrc_sources clk_src_cpll = {
-	.sources	= clk_src_cpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_cpll_list),
-};
-
-/* Possible clock sources for MPLL Mux */
-static struct clk *clk_src_mpll_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &clk_fout_mpll,
-};
-
-struct clksrc_sources clk_src_mpll = {
-	.sources	= clk_src_mpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
-};
-
-static struct clk *clk_src_mpll_fout_list[] = {
-	[0] = &clk_fout_mpll_div2,
-	[1] = &clk_fout_mpll,
-};
-
-struct clksrc_sources clk_src_mpll_fout = {
-	.sources	= clk_src_mpll_fout_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_fout_list),
-};
-
-/* Possible clock sources for EPLL Mux */
-static struct clk *clk_src_epll_list[] = {
-	[0] = &clk_fin_epll,
-	[1] = &clk_fout_epll,
-};
-
-struct clksrc_sources clk_src_epll = {
-	.sources	= clk_src_epll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
-};
-
-/* Possible clock sources for DPLL Mux */
-static struct clk *clk_src_dpll_list[] = {
-	[0] = &clk_fin_dpll,
-	[1] = &clk_fout_dpll,
-};
-
-struct clksrc_sources clk_src_dpll = {
-	.sources	= clk_src_dpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_dpll_list),
-};
-
-struct clk clk_vpll = {
-	.name		= "vpll",
-	.id		= -1,
-};
-
-int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
-{
-	unsigned int ctrlbit = clk->ctrlbit;
-	u32 con;
-
-	con = __raw_readl(reg);
-	con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
-	__raw_writel(con, reg);
-	return 0;
-}
-
-int s5p_epll_enable(struct clk *clk, int enable)
-{
-	unsigned int ctrlbit = clk->ctrlbit;
-	unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
-
-	if (enable)
-		__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
-	else
-		__raw_writel(epll_con, S5P_EPLL_CON);
-
-	return 0;
-}
-
-unsigned long s5p_epll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct clk *pclk;
-	int ret;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	ret = pclk->ops->set_rate(pclk, rate);
-	clk_put(pclk);
-
-	return ret;
-}
-
-unsigned long s5p_spdif_get_rate(struct clk *clk)
-{
-	struct clk *pclk;
-	int rate;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	rate = pclk->ops->get_rate(pclk);
-	clk_put(pclk);
-
-	return rate;
-}
-
-struct clk_ops s5p_sclk_spdif_ops = {
-	.set_rate	= s5p_spdif_set_rate,
-	.get_rate	= s5p_spdif_get_rate,
-};
-
-static struct clk *s5p_clks[] __initdata = {
-	&clk_ext_xtal_mux,
-	&clk_48m,
-	&s5p_clk_27m,
-	&clk_fout_apll,
-	&clk_fout_mpll,
-	&clk_fout_epll,
-	&clk_fout_dpll,
-	&clk_fout_vpll,
-	&clk_vpll,
-	&clk_xusbxti,
-};
-
-void __init s5p_register_clocks(unsigned long xtal_freq)
-{
-	int ret;
-
-	clk_ext_xtal_mux.rate = xtal_freq;
-
-	ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
-	if (ret > 0)
-		printk(KERN_ERR "Failed to register s5p clocks\n");
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-dev-mfc.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-dev-mfc.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-dev-mfc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-dev-mfc.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,56 +17,16 @@
 #include <linux/of_fdt.h>
 #include <linux/of.h>
 
-#include <plat/mfc.h>
-
-#ifdef CONFIG_SAMSUNG_ATAGS
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <plat/devs.h>
-
-static struct resource s5p_mfc_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
-	[1] = DEFINE_RES_IRQ(IRQ_MFC),
-};
-
-struct platform_device s5p_device_mfc = {
-	.name		= "s5p-mfc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
-	.resource	= s5p_mfc_resource,
-};
-
-/*
- * MFC hardware has 2 memory interfaces which are modelled as two separate
- * platform devices to let dma-mapping distinguish between them.
- *
- * MFC parent device (s5p_device_mfc) must be registered before memory
- * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
- */
-
-struct platform_device s5p_device_mfc_l = {
-	.name		= "s5p-mfc-l",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_device_mfc_l.dev.coherent_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device s5p_device_mfc_r = {
-	.name		= "s5p-mfc-r",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_device_mfc_r.dev.coherent_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-#else
 static struct platform_device s5p_device_mfc_l;
 static struct platform_device s5p_device_mfc_r;
-#endif
+
+struct s5p_mfc_dt_meminfo {
+	unsigned long	loff;
+	unsigned long	lsize;
+	unsigned long	roff;
+	unsigned long	rsize;
+	char		*compatible;
+};
 
 struct s5p_mfc_reserved_mem {
 	phys_addr_t	base;
@@ -77,7 +37,7 @@ struct s5p_mfc_reserved_mem {
 static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
 
 
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+static void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
 				phys_addr_t lbase, unsigned int lsize)
 {
 	int i;
@@ -100,28 +60,6 @@ void __init s5p_mfc_reserve_mem(phys_add
 	}
 }
 
-#ifdef CONFIG_SAMSUNG_ATAGS
-static int __init s5p_mfc_memory_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
-		struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
-		if (!area->base)
-			continue;
-
-		if (dma_declare_coherent_memory(area->dev, area->base,
-				area->base, area->size,
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
-			printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
-			       area->size, (unsigned long) area->base);
-	}
-	return 0;
-}
-device_initcall(s5p_mfc_memory_init);
-#endif
-
-#ifdef CONFIG_OF
 int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
 				int depth, void *data)
 {
@@ -154,4 +92,3 @@ int __init s5p_fdt_alloc_mfc_mem(unsigne
 
 	return 1;
 }
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-dev-uart.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-dev-uart.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-dev-uart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-dev-uart.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2009,2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Base S5P UART resource and device definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
- /* Serial port registrations */
-
-static struct resource s5p_uart0_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_UART0, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART0),
-};
-
-static struct resource s5p_uart1_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_UART1, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART1),
-};
-
-static struct resource s5p_uart2_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_UART2, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART2),
-};
-
-static struct resource s5p_uart3_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
-	[0] = DEFINE_RES_MEM(S5P_PA_UART3, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART3),
-#endif
-};
-
-static struct resource s5p_uart4_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
-	[0] = DEFINE_RES_MEM(S5P_PA_UART4, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART4),
-#endif
-};
-
-static struct resource s5p_uart5_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
-	[0] = DEFINE_RES_MEM(S5P_PA_UART5, S5P_SZ_UART),
-	[1] = DEFINE_RES_IRQ(IRQ_UART5),
-#endif
-};
-
-struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= s5p_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart0_resource),
-	},
-	[1] = {
-		.resources	= s5p_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart1_resource),
-	},
-	[2] = {
-		.resources	= s5p_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart2_resource),
-	},
-	[3] = {
-		.resources	= s5p_uart3_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart3_resource),
-	},
-	[4] = {
-		.resources	= s5p_uart4_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart4_resource),
-	},
-	[5] = {
-		.resources	= s5p_uart5_resource,
-		.nr_resources	= ARRAY_SIZE(s5p_uart5_resource),
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - Interrupt handling
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-vic.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/cpu.h>
-
-void __init s5p_init_irq(u32 *vic, u32 num_vic)
-{
-#ifdef CONFIG_ARM_VIC
-	int irq;
-
-	/* initialize the VICs */
-	for (irq = 0; irq < num_vic; irq++)
-		vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
-#endif
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-eint.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-eint.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-eint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-eint.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P - IRQ EINT support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/irqchip/arm-vic.h>
-#include <linux/of.h>
-
-#include <plat/regs-irqtype.h>
-
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-
-#include <plat/gpio-cfg.h>
-#include <mach/regs-gpio.h>
-
-static inline void s5p_irq_eint_mask(struct irq_data *data)
-{
-	u32 mask;
-
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask |= eint_irq_to_bit(data->irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_eint_unmask(struct irq_data *data)
-{
-	u32 mask;
-
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask &= ~(eint_irq_to_bit(data->irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-}
-
-static inline void s5p_irq_eint_ack(struct irq_data *data)
-{
-	__raw_writel(eint_irq_to_bit(data->irq),
-		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_eint_maskack(struct irq_data *data)
-{
-	/* compiler should in-line these */
-	s5p_irq_eint_mask(data);
-	s5p_irq_eint_ack(data);
-}
-
-static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
-	int offs = EINT_OFFSET(data->irq);
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
-		break;
-
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -EINVAL;
-	}
-
-	shift = (offs & 0x7) * 4;
-	mask = 0x7 << shift;
-
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	ctrl &= ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
-
-	if ((0 <= offs) && (offs < 8))
-		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-
-	else if ((8 <= offs) && (offs < 16))
-		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-
-	else if ((16 <= offs) && (offs < 24))
-		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-
-	else if ((24 <= offs) && (offs < 32))
-		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-
-	else
-		printk(KERN_ERR "No such irq number %d", offs);
-
-	return 0;
-}
-
-static struct irq_chip s5p_irq_eint = {
-	.name		= "s5p-eint",
-	.irq_mask	= s5p_irq_eint_mask,
-	.irq_unmask	= s5p_irq_eint_unmask,
-	.irq_mask_ack	= s5p_irq_eint_maskack,
-	.irq_ack	= s5p_irq_eint_ack,
-	.irq_set_type	= s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= s3c_irqext_wake,
-#endif
-};
-
-/* s5p_irq_demux_eint
- *
- * This function demuxes the IRQ from the group0 external interrupts,
- * from EINTs 16 to 31. It is designed to be inlined into the specific
- * handler s5p_irq_demux_eintX_Y.
- *
- * Each EINT pend/mask registers handle eight of them.
- */
-static inline void s5p_irq_demux_eint(unsigned int start)
-{
-	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
-	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
-	unsigned int irq;
-
-	status &= ~mask;
-	status &= 0xff;
-
-	while (status) {
-		irq = fls(status) - 1;
-		generic_handle_irq(irq + start);
-		status &= ~(1 << irq);
-	}
-}
-
-static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
-	s5p_irq_demux_eint(IRQ_EINT(16));
-	s5p_irq_demux_eint(IRQ_EINT(24));
-}
-
-static inline void s5p_irq_vic_eint_mask(struct irq_data *data)
-{
-	void __iomem *base = irq_data_get_irq_chip_data(data);
-
-	s5p_irq_eint_mask(data);
-	writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR);
-}
-
-static void s5p_irq_vic_eint_unmask(struct irq_data *data)
-{
-	void __iomem *base = irq_data_get_irq_chip_data(data);
-
-	s5p_irq_eint_unmask(data);
-	writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE);
-}
-
-static inline void s5p_irq_vic_eint_ack(struct irq_data *data)
-{
-	__raw_writel(eint_irq_to_bit(data->irq),
-		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_vic_eint_maskack(struct irq_data *data)
-{
-	s5p_irq_vic_eint_mask(data);
-	s5p_irq_vic_eint_ack(data);
-}
-
-static struct irq_chip s5p_irq_vic_eint = {
-	.name		= "s5p_vic_eint",
-	.irq_mask	= s5p_irq_vic_eint_mask,
-	.irq_unmask	= s5p_irq_vic_eint_unmask,
-	.irq_mask_ack	= s5p_irq_vic_eint_maskack,
-	.irq_ack	= s5p_irq_vic_eint_ack,
-	.irq_set_type	= s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= s3c_irqext_wake,
-#endif
-};
-
-static int __init s5p_init_irq_eint(void)
-{
-	int irq;
-
-	if (of_have_populated_dt())
-		return -ENODEV;
-
-	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
-		irq_set_chip(irq, &s5p_irq_vic_eint);
-
-	for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
-		irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
-	return 0;
-}
-
-arch_initcall(s5p_init_irq_eint);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-gpioint.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-gpioint.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-gpioint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-gpioint.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * Author: Kyungmin Park <kyungmin.park@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- * Author: Marek Szyprowski <m.szyprowski@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <mach/map.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-
-#define GPIO_BASE(chip)		((void __iomem *)((unsigned long)((chip)->base) & 0xFFFFF000u))
-
-#define CON_OFFSET		0x700
-#define MASK_OFFSET		0x900
-#define PEND_OFFSET		0xA00
-#define REG_OFFSET(x)		((x) << 2)
-
-struct s5p_gpioint_bank {
-	struct list_head	list;
-	int			start;
-	int			nr_groups;
-	int			irq;
-	struct samsung_gpio_chip	**chips;
-	void			(*handler)(unsigned int, struct irq_desc *);
-};
-
-static LIST_HEAD(banks);
-
-static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	struct irq_chip_type *ct = gc->chip_types;
-	unsigned int shift = (d->irq - gc->irq_base) << 2;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		type = S5P_IRQ_TYPE_EDGE_RISING;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		type = S5P_IRQ_TYPE_EDGE_FALLING;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		type = S5P_IRQ_TYPE_EDGE_BOTH;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		type = S5P_IRQ_TYPE_LEVEL_HIGH;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		type = S5P_IRQ_TYPE_LEVEL_LOW;
-		break;
-	case IRQ_TYPE_NONE:
-	default:
-		printk(KERN_WARNING "No irq type\n");
-		return -EINVAL;
-	}
-
-	gc->type_cache &= ~(0x7 << shift);
-	gc->type_cache |= type << shift;
-	writel(gc->type_cache, gc->reg_base + ct->regs.type);
-	return 0;
-}
-
-static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
-	int group, pend_offset, mask_offset;
-	unsigned int pend, mask;
-
-	struct irq_chip *chip = irq_get_chip(irq);
-	chained_irq_enter(chip, desc);
-
-	for (group = 0; group < bank->nr_groups; group++) {
-		struct samsung_gpio_chip *chip = bank->chips[group];
-		if (!chip)
-			continue;
-
-		pend_offset = REG_OFFSET(group);
-		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
-		if (!pend)
-			continue;
-
-		mask_offset = REG_OFFSET(group);
-		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
-		pend &= ~mask;
-
-		while (pend) {
-			int offset = fls(pend) - 1;
-			int real_irq = chip->irq_base + offset;
-			generic_handle_irq(real_irq);
-			pend &= ~BIT(offset);
-		}
-	}
-	chained_irq_exit(chip, desc);
-}
-
-static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
-{
-	static int used_gpioint_groups = 0;
-	int group = chip->group;
-	struct s5p_gpioint_bank *b, *bank = NULL;
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
-		return -ENOMEM;
-
-	list_for_each_entry(b, &banks, list) {
-		if (group >= b->start && group < b->start + b->nr_groups) {
-			bank = b;
-			break;
-		}
-	}
-	if (!bank)
-		return -EINVAL;
-
-	if (!bank->handler) {
-		bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
-				      bank->nr_groups, GFP_KERNEL);
-		if (!bank->chips)
-			return -ENOMEM;
-
-		irq_set_chained_handler(bank->irq, s5p_gpioint_handler);
-		irq_set_handler_data(bank->irq, bank);
-		bank->handler = s5p_gpioint_handler;
-		printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
-		       bank->irq);
-	}
-
-	/*
-	 * chained GPIO irq has been successfully registered, allocate new gpio
-	 * int group and assign irq nubmers
-	 */
-	chip->irq_base = S5P_GPIOINT_BASE +
-			 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
-	used_gpioint_groups++;
-
-	bank->chips[group - bank->start] = chip;
-
-	gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
-				    GPIO_BASE(chip),
-				    handle_level_irq);
-	if (!gc)
-		return -ENOMEM;
-	ct = gc->chip_types;
-	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_mask = irq_gc_mask_set_bit;
-	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-	ct->chip.irq_set_type = s5p_gpioint_set_type,
-	ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start);
-	ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start);
-	ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start);
-	irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
-			       IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-	return 0;
-}
-
-int __init s5p_register_gpio_interrupt(int pin)
-{
-	struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
-	int offset, group;
-	int ret;
-
-	if (!my_chip)
-		return -EINVAL;
-
-	offset = pin - my_chip->chip.base;
-	group = my_chip->group;
-
-	/* check if the group has been already registered */
-	if (my_chip->irq_base)
-		goto success;
-
-	/* register gpio group */
-	ret = s5p_gpioint_add(my_chip);
-	if (ret == 0) {
-		my_chip->chip.to_irq = samsung_gpiolib_to_irq;
-		printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
-		       group);
-		goto success;
-	}
-	return ret;
-success:
-	my_chip->bitmap_gpio_int |= BIT(offset);
-
-	return my_chip->irq_base + offset;
-}
-
-int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
-{
-	struct s5p_gpioint_bank *bank;
-
-	bank = kzalloc(sizeof(*bank), GFP_KERNEL);
-	if (!bank)
-		return -ENOMEM;
-
-	bank->start = start;
-	bank->nr_groups = nr_groups;
-	bank->irq = chain_irq;
-
-	list_add_tail(&bank->list, &banks);
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-pm.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-pm.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-irq-pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-irq-pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/plat-s3c24xx/irq-pm.c,
- * Copyright (c) 2003,2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-
-#include <plat/cpu.h>
-#include <plat/irqs.h>
-#include <plat/pm.h>
-#include <mach/map.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/regs-irq.h>
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM,
- * as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow	= 0x00000006L;
-unsigned long s3c_irqwake_eintallow	= 0xffffffffL;
-
-int s3c_irq_wake(struct irq_data *data, unsigned int state)
-{
-	unsigned long irqbit;
-	unsigned int irq_rtc_tic, irq_rtc_alarm;
-
-	irq_rtc_tic = IRQ_RTC_TIC;
-	irq_rtc_alarm = IRQ_RTC_ALARM;
-
-	if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) {
-		irqbit = 1 << (data->irq + 1 - irq_rtc_alarm);
-
-		if (!state)
-			s3c_irqwake_intmask |= irqbit;
-		else
-			s3c_irqwake_intmask &= ~irqbit;
-	} else {
-		return -ENOENT;
-	}
-
-	return 0;
-}
-
-static struct sleep_save eint_save[] = {
-	SAVE_ITEM(S5P_EINT_CON(0)),
-	SAVE_ITEM(S5P_EINT_CON(1)),
-	SAVE_ITEM(S5P_EINT_CON(2)),
-	SAVE_ITEM(S5P_EINT_CON(3)),
-
-	SAVE_ITEM(S5P_EINT_FLTCON(0)),
-	SAVE_ITEM(S5P_EINT_FLTCON(1)),
-	SAVE_ITEM(S5P_EINT_FLTCON(2)),
-	SAVE_ITEM(S5P_EINT_FLTCON(3)),
-	SAVE_ITEM(S5P_EINT_FLTCON(4)),
-	SAVE_ITEM(S5P_EINT_FLTCON(5)),
-	SAVE_ITEM(S5P_EINT_FLTCON(6)),
-	SAVE_ITEM(S5P_EINT_FLTCON(7)),
-
-	SAVE_ITEM(S5P_EINT_MASK(0)),
-	SAVE_ITEM(S5P_EINT_MASK(1)),
-	SAVE_ITEM(S5P_EINT_MASK(2)),
-	SAVE_ITEM(S5P_EINT_MASK(3)),
-};
-
-int s3c24xx_irq_suspend(void)
-{
-	s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
-
-	return 0;
-}
-
-void s3c24xx_irq_resume(void)
-{
-	s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-pm.c linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-pm.c
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P Power Manager (Suspend-To-RAM) support
- *
- * Based on arch/arm/plat-s3c24xx/pm.c
- * Copyright (c) 2004,2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/suspend.h>
-#include <plat/pm.h>
-
-#define PFX "s5p pm: "
-
-/* s3c_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
-
-void s3c_pm_configure_extint(void)
-{
-	/* nothing here yet */
-}
-
-void s3c_pm_restore_core(void)
-{
-	/* nothing here yet */
-}
-
-void s3c_pm_save_core(void)
-{
-	/* nothing here yet */
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-sleep.S linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-sleep.S
--- linux-libre-3.16-gnu/arch/arm/plat-samsung/s5p-sleep.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-samsung/s5p-sleep.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Common S5P Sleep Code
- * Based on S3C64XX sleep code by:
- *	Ben Dooks, (c) 2008 Simtec Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-
-	.data
-	.align
-
-	/*
-	 * sleep magic, to allow the bootloader to check for an valid
-	 * image to resume to. Must be the first word before the
-	 * s3c_cpu_resume entry.
-	 */
-
-	.word	0x2bedf00d
-
-	/*
-	 * s3c_cpu_resume
-	 *
-	 * resume code entry for bootloader to call
-	 */
-
-ENTRY(s3c_cpu_resume)
-	b	cpu_resume
-ENDPROC(s3c_cpu_resume)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-versatile/clcd.c linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/clcd.c
--- linux-libre-3.16-gnu/arch/arm/plat-versatile/clcd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/clcd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,182 +0,0 @@
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <plat/clcd.h>
-
-static struct clcd_panel vga = {
-	.mode		= {
-		.name		= "VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 39721,
-		.left_margin	= 40,
-		.right_margin	= 24,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 96,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
-	.bpp		= 16,
-};
-
-static struct clcd_panel xvga = {
-	.mode		= {
-		.name		= "XVGA",
-		.refresh	= 60,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 15748,
-		.left_margin	= 152,
-		.right_margin	= 48,
-		.upper_margin	= 23,
-		.lower_margin	= 3,
-		.hsync_len	= 104,
-		.vsync_len	= 4,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
-	.bpp		= 16,
-};
-
-/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */
-static struct clcd_panel sanyo_tm38qv67a02a = {
-	.mode		= {
-		.name		= "Sanyo TM38QV67A02A",
-		.refresh	= 116,
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= 100000,
-		.left_margin	= 6,
-		.right_margin	= 6,
-		.upper_margin	= 5,
-		.lower_margin	= 5,
-		.hsync_len	= 6,
-		.vsync_len	= 6,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.caps		= CLCD_CAP_5551,
-	.bpp		= 16,
-};
-
-static struct clcd_panel sanyo_2_5_in = {
-	.mode		= {
-		.name		= "Sanyo QVGA Portrait",
-		.refresh	= 116,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 100000,
-		.left_margin	= 20,
-		.right_margin	= 10,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 10,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.caps		= CLCD_CAP_5551,
-	.bpp		= 16,
-};
-
-/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */
-static struct clcd_panel epson_l2f50113t00 = {
-	.mode		= {
-		.name		= "Epson L2F50113T00",
-		.refresh	= 390,
-		.xres		= 176,
-		.yres		= 220,
-		.pixclock	= 62500,
-		.left_margin	= 3,
-		.right_margin	= 2,
-		.upper_margin	= 1,
-		.lower_margin	= 0,
-		.hsync_len	= 3,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.caps		= CLCD_CAP_5551,
-	.bpp		= 16,
-};
-
-static struct clcd_panel *panels[] = {
-	&vga,
-	&xvga,
-	&sanyo_tm38qv67a02a,
-	&sanyo_2_5_in,
-	&epson_l2f50113t00,
-};
-
-struct clcd_panel *versatile_clcd_get_panel(const char *name)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(panels); i++)
-		if (strcmp(panels[i]->mode.name, name) == 0)
-			break;
-
-	if (i < ARRAY_SIZE(panels))
-		return panels[i];
-
-	pr_err("CLCD: couldn't get parameters for panel %s\n", name);
-
-	return NULL;
-}
-
-int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
-{
-	dma_addr_t dma;
-
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-						    &dma, GFP_KERNEL);
-	if (!fb->fb.screen_base) {
-		pr_err("CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-	fb->fb.fix.smem_start	= dma;
-	fb->fb.fix.smem_len	= framesize;
-
-	return 0;
-}
-
-int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
-
-void versatile_clcd_remove_dma(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			      fb->fb.screen_base, fb->fb.fix.smem_start);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-versatile/include/plat/clcd.h linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/include/plat/clcd.h
--- linux-libre-3.16-gnu/arch/arm/plat-versatile/include/plat/clcd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/include/plat/clcd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef PLAT_CLCD_H
-#define PLAT_CLCD_H
-
-struct clcd_panel *versatile_clcd_get_panel(const char *);
-int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long);
-int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *);
-void versatile_clcd_remove_dma(struct clcd_fb *);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-versatile/Kconfig linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/Kconfig
--- linux-libre-3.16-gnu/arch/arm/plat-versatile/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,9 +3,6 @@ if PLAT_VERSATILE
 config PLAT_VERSATILE_CLOCK
 	bool
 
-config PLAT_VERSATILE_CLCD
-	bool
-
 config PLAT_VERSATILE_SCHED_CLOCK
 	def_bool y
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/plat-versatile/Makefile linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/Makefile
--- linux-libre-3.16-gnu/arch/arm/plat-versatile/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/plat-versatile/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,5 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
 
 obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
-obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/vfp/entry.S linux-libre-3.17-rc7-gnu/arch/arm/vfp/entry.S
--- linux-libre-3.16-gnu/arch/arm/vfp/entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/vfp/entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@ ENDPROC(do_vfp)
 
 ENTRY(vfp_null_entry)
 	dec_preempt_count_ti r10, r4
-	mov	pc, lr
+	ret	lr
 ENDPROC(vfp_null_entry)
 
 	.align	2
@@ -49,7 +49,7 @@ ENTRY(vfp_testing_entry)
 	dec_preempt_count_ti r10, r4
 	ldr	r0, VFP_arch_address
 	str	r0, [r0]		@ set to non-zero value
-	mov	pc, r9			@ we have handled the fault
+	ret	r9			@ we have handled the fault
 ENDPROC(vfp_testing_entry)
 
 	.align	2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/vfp/vfphw.S linux-libre-3.17-rc7-gnu/arch/arm/vfp/vfphw.S
--- linux-libre-3.16-gnu/arch/arm/vfp/vfphw.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/vfp/vfphw.S	2014-09-28 17:29:07.000000000 -0400
@@ -183,7 +183,7 @@ vfp_hw_state_valid:
 					@ always subtract 4 from the following
 					@ instruction address.
 	dec_preempt_count_ti r10, r4
-	mov	pc, r9			@ we think we have handled things
+	ret	r9			@ we think we have handled things
 
 
 look_for_VFP_exceptions:
@@ -202,7 +202,7 @@ look_for_VFP_exceptions:
 
 	DBGSTR	"not VFP"
 	dec_preempt_count_ti r10, r4
-	mov	pc, lr
+	ret	lr
 
 process_exception:
 	DBGSTR	"bounce"
@@ -234,7 +234,7 @@ ENTRY(vfp_save_state)
 	VFPFMRX	r12, FPINST2		@ FPINST2 if needed (and present)
 1:
 	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
-	mov	pc, lr
+	ret	lr
 ENDPROC(vfp_save_state)
 
 	.align
@@ -245,7 +245,7 @@ vfp_current_hw_state_address:
 #ifdef CONFIG_THUMB2_KERNEL
 	adr	\tmp, 1f
 	add	\tmp, \tmp, \base, lsl \shift
-	mov	pc, \tmp
+	ret	\tmp
 #else
 	add	pc, pc, \base, lsl \shift
 	mov	r0, r0
@@ -257,10 +257,10 @@ ENTRY(vfp_get_float)
 	tbl_branch r0, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	mrc	p10, 0, r0, c\dr, c0, 0	@ fmrs	r0, s0
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 1:	mrc	p10, 0, r0, c\dr, c0, 4	@ fmrs	r0, s1
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 ENDPROC(vfp_get_float)
@@ -269,10 +269,10 @@ ENTRY(vfp_put_float)
 	tbl_branch r1, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	mcr	p10, 0, r0, c\dr, c0, 0	@ fmsr	r0, s0
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 1:	mcr	p10, 0, r0, c\dr, c0, 4	@ fmsr	r0, s1
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 ENDPROC(vfp_put_float)
@@ -281,14 +281,14 @@ ENTRY(vfp_get_double)
 	tbl_branch r0, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	fmrrd	r0, r1, d\dr
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 #ifdef CONFIG_VFPv3
 	@ d16 - d31 registers
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	mrrc	p11, 3, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 #endif
@@ -296,21 +296,21 @@ ENTRY(vfp_get_double)
 	@ virtual register 16 (or 32 if VFPv3) for compare with zero
 	mov	r0, #0
 	mov	r1, #0
-	mov	pc, lr
+	ret	lr
 ENDPROC(vfp_get_double)
 
 ENTRY(vfp_put_double)
 	tbl_branch r2, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	fmdrr	d\dr, r0, r1
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 #ifdef CONFIG_VFPv3
 	@ d16 - d31 registers
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 1:	mcrr	p11, 3, r0, r1, c\dr	@ fmdrr	r0, r1, d\dr
-	mov	pc, lr
+	ret	lr
 	.org	1b + 8
 	.endr
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/enlighten.c linux-libre-3.17-rc7-gnu/arch/arm/xen/enlighten.c
--- linux-libre-3.16-gnu/arch/arm/xen/enlighten.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/enlighten.c	2014-09-28 17:29:07.000000000 -0400
@@ -181,8 +181,7 @@ static void xen_restart(enum reboot_mode
 	struct sched_shutdown r = { .reason = SHUTDOWN_reboot };
 	int rc;
 	rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
-	if (rc)
-		BUG();
+	BUG_ON(rc);
 }
 
 static void xen_power_off(void)
@@ -190,8 +189,7 @@ static void xen_power_off(void)
 	struct sched_shutdown r = { .reason = SHUTDOWN_poweroff };
 	int rc;
 	rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
-	if (rc)
-		BUG();
+	BUG_ON(rc);
 }
 
 static int xen_cpu_notification(struct notifier_block *self,
@@ -262,6 +260,12 @@ static int __init xen_guest_init(void)
 	xen_domain_type = XEN_HVM_DOMAIN;
 
 	xen_setup_features();
+
+	if (!xen_feature(XENFEAT_grant_map_identity)) {
+		pr_warn("Please upgrade your Xen.\n"
+				"If your platform has any non-coherent DMA devices, they won't work properly.\n");
+	}
+
 	if (xen_feature(XENFEAT_dom0))
 		xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
 	else
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/grant-table.c linux-libre-3.17-rc7-gnu/arch/arm/xen/grant-table.c
--- linux-libre-3.16-gnu/arch/arm/xen/grant-table.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/grant-table.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,14 +45,7 @@ void arch_gnttab_unmap(void *shared, uns
 	return;
 }
 
-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
-			   unsigned long max_nr_gframes,
-			   grant_status_t **__shared)
-{
-	return -ENOSYS;
-}
-
-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
+int arch_gnttab_init(unsigned long nr_shared)
 {
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/hypercall.S linux-libre-3.17-rc7-gnu/arch/arm/xen/hypercall.S
--- linux-libre-3.16-gnu/arch/arm/xen/hypercall.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/hypercall.S	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@
 ENTRY(HYPERVISOR_##hypercall)			\
 	mov r12, #__HYPERVISOR_##hypercall;	\
 	__HVC(XEN_IMM);						\
-	mov pc, lr;							\
+	ret lr;					\
 ENDPROC(HYPERVISOR_##hypercall)
 
 #define HYPERCALL0 HYPERCALL_SIMPLE
@@ -74,7 +74,7 @@ ENTRY(HYPERVISOR_##hypercall)			\
 	mov r12, #__HYPERVISOR_##hypercall;	\
 	__HVC(XEN_IMM);						\
 	ldm sp!, {r4}						\
-	mov pc, lr							\
+	ret lr					\
 ENDPROC(HYPERVISOR_##hypercall)
 
                 .text
@@ -101,5 +101,5 @@ ENTRY(privcmd_call)
 	ldr r4, [sp, #4]
 	__HVC(XEN_IMM)
 	ldm sp!, {r4}
-	mov pc, lr
+	ret lr
 ENDPROC(privcmd_call);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/Makefile linux-libre-3.17-rc7-gnu/arch/arm/xen/Makefile
--- linux-libre-3.16-gnu/arch/arm/xen/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1 +1 @@
-obj-y		:= enlighten.o hypercall.o grant-table.o p2m.o mm.o
+obj-y		:= enlighten.o hypercall.o grant-table.o p2m.o mm.o mm32.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/mm32.c linux-libre-3.17-rc7-gnu/arch/arm/xen/mm32.c
--- linux-libre-3.16-gnu/arch/arm/xen/mm32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/mm32.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,202 @@
+#include <linux/cpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+
+#include <xen/features.h>
+
+static DEFINE_PER_CPU(unsigned long, xen_mm32_scratch_virt);
+static DEFINE_PER_CPU(pte_t *, xen_mm32_scratch_ptep);
+
+static int alloc_xen_mm32_scratch_page(int cpu)
+{
+	struct page *page;
+	unsigned long virt;
+	pmd_t *pmdp;
+	pte_t *ptep;
+
+	if (per_cpu(xen_mm32_scratch_ptep, cpu) != NULL)
+		return 0;
+
+	page = alloc_page(GFP_KERNEL);
+	if (page == NULL) {
+		pr_warn("Failed to allocate xen_mm32_scratch_page for cpu %d\n", cpu);
+		return -ENOMEM;
+	}
+
+	virt = (unsigned long)__va(page_to_phys(page));
+	pmdp = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt);
+	ptep = pte_offset_kernel(pmdp, virt);
+
+	per_cpu(xen_mm32_scratch_virt, cpu) = virt;
+	per_cpu(xen_mm32_scratch_ptep, cpu) = ptep;
+
+	return 0;
+}
+
+static int xen_mm32_cpu_notify(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	int cpu = (long)hcpu;
+	switch (action) {
+	case CPU_UP_PREPARE:
+		if (alloc_xen_mm32_scratch_page(cpu))
+			return NOTIFY_BAD;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block xen_mm32_cpu_notifier = {
+	.notifier_call	= xen_mm32_cpu_notify,
+};
+
+static void* xen_mm32_remap_page(dma_addr_t handle)
+{
+	unsigned long virt = get_cpu_var(xen_mm32_scratch_virt);
+	pte_t *ptep = __get_cpu_var(xen_mm32_scratch_ptep);
+
+	*ptep = pfn_pte(handle >> PAGE_SHIFT, PAGE_KERNEL);
+	local_flush_tlb_kernel_page(virt);
+
+	return (void*)virt;
+}
+
+static void xen_mm32_unmap(void *vaddr)
+{
+	put_cpu_var(xen_mm32_scratch_virt);
+}
+
+
+/* functions called by SWIOTLB */
+
+static void dma_cache_maint(dma_addr_t handle, unsigned long offset,
+	size_t size, enum dma_data_direction dir,
+	void (*op)(const void *, size_t, int))
+{
+	unsigned long pfn;
+	size_t left = size;
+
+	pfn = (handle >> PAGE_SHIFT) + offset / PAGE_SIZE;
+	offset %= PAGE_SIZE;
+
+	do {
+		size_t len = left;
+		void *vaddr;
+	
+		if (!pfn_valid(pfn))
+		{
+			/* Cannot map the page, we don't know its physical address.
+			 * Return and hope for the best */
+			if (!xen_feature(XENFEAT_grant_map_identity))
+				return;
+			vaddr = xen_mm32_remap_page(handle) + offset;
+			op(vaddr, len, dir);
+			xen_mm32_unmap(vaddr - offset);
+		} else {
+			struct page *page = pfn_to_page(pfn);
+
+			if (PageHighMem(page)) {
+				if (len + offset > PAGE_SIZE)
+					len = PAGE_SIZE - offset;
+
+				if (cache_is_vipt_nonaliasing()) {
+					vaddr = kmap_atomic(page);
+					op(vaddr + offset, len, dir);
+					kunmap_atomic(vaddr);
+				} else {
+					vaddr = kmap_high_get(page);
+					if (vaddr) {
+						op(vaddr + offset, len, dir);
+						kunmap_high(page);
+					}
+				}
+			} else {
+				vaddr = page_address(page) + offset;
+				op(vaddr, len, dir);
+			}
+		}
+
+		offset = 0;
+		pfn++;
+		left -= len;
+	} while (left);
+}
+
+static void __xen_dma_page_dev_to_cpu(struct device *hwdev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir)
+{
+	/* Cannot use __dma_page_dev_to_cpu because we don't have a
+	 * struct page for handle */
+
+	if (dir != DMA_TO_DEVICE)
+		outer_inv_range(handle, handle + size);
+
+	dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_unmap_area);
+}
+
+static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir)
+{
+
+	dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_map_area);
+
+	if (dir == DMA_FROM_DEVICE) {
+		outer_inv_range(handle, handle + size);
+	} else {
+		outer_clean_range(handle, handle + size);
+	}
+}
+
+void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir,
+		struct dma_attrs *attrs)
+
+{
+	if (!__generic_dma_ops(hwdev)->unmap_page)
+		return;
+	if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+		return;
+
+	__xen_dma_page_dev_to_cpu(hwdev, handle, size, dir);
+}
+
+void xen_dma_sync_single_for_cpu(struct device *hwdev,
+		dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+	if (!__generic_dma_ops(hwdev)->sync_single_for_cpu)
+		return;
+	__xen_dma_page_dev_to_cpu(hwdev, handle, size, dir);
+}
+
+void xen_dma_sync_single_for_device(struct device *hwdev,
+		dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+	if (!__generic_dma_ops(hwdev)->sync_single_for_device)
+		return;
+	__xen_dma_page_cpu_to_dev(hwdev, handle, size, dir);
+}
+
+int __init xen_mm32_init(void)
+{
+	int cpu;
+
+	if (!xen_initial_domain())
+		return 0;
+
+	register_cpu_notifier(&xen_mm32_cpu_notifier);
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		if (alloc_xen_mm32_scratch_page(cpu)) {
+			put_online_cpus();
+			unregister_cpu_notifier(&xen_mm32_cpu_notifier);
+			return -ENOMEM;
+		}
+	}
+	put_online_cpus();
+
+	return 0;
+}
+arch_initcall(xen_mm32_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm/xen/p2m.c linux-libre-3.17-rc7-gnu/arch/arm/xen/p2m.c
--- linux-libre-3.16-gnu/arch/arm/xen/p2m.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm/xen/p2m.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,14 +21,12 @@ struct xen_p2m_entry {
 	unsigned long pfn;
 	unsigned long mfn;
 	unsigned long nr_pages;
-	struct rb_node rbnode_mach;
 	struct rb_node rbnode_phys;
 };
 
 static rwlock_t p2m_lock;
 struct rb_root phys_to_mach = RB_ROOT;
 EXPORT_SYMBOL_GPL(phys_to_mach);
-static struct rb_root mach_to_phys = RB_ROOT;
 
 static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
 {
@@ -41,8 +39,6 @@ static int xen_add_phys_to_mach_entry(st
 		parent = *link;
 		entry = rb_entry(parent, struct xen_p2m_entry, rbnode_phys);
 
-		if (new->mfn == entry->mfn)
-			goto err_out;
 		if (new->pfn == entry->pfn)
 			goto err_out;
 
@@ -88,64 +84,6 @@ unsigned long __pfn_to_mfn(unsigned long
 }
 EXPORT_SYMBOL_GPL(__pfn_to_mfn);
 
-static int xen_add_mach_to_phys_entry(struct xen_p2m_entry *new)
-{
-	struct rb_node **link = &mach_to_phys.rb_node;
-	struct rb_node *parent = NULL;
-	struct xen_p2m_entry *entry;
-	int rc = 0;
-
-	while (*link) {
-		parent = *link;
-		entry = rb_entry(parent, struct xen_p2m_entry, rbnode_mach);
-
-		if (new->mfn == entry->mfn)
-			goto err_out;
-		if (new->pfn == entry->pfn)
-			goto err_out;
-
-		if (new->mfn < entry->mfn)
-			link = &(*link)->rb_left;
-		else
-			link = &(*link)->rb_right;
-	}
-	rb_link_node(&new->rbnode_mach, parent, link);
-	rb_insert_color(&new->rbnode_mach, &mach_to_phys);
-	goto out;
-
-err_out:
-	rc = -EINVAL;
-	pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
-			__func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
-out:
-	return rc;
-}
-
-unsigned long __mfn_to_pfn(unsigned long mfn)
-{
-	struct rb_node *n = mach_to_phys.rb_node;
-	struct xen_p2m_entry *entry;
-	unsigned long irqflags;
-
-	read_lock_irqsave(&p2m_lock, irqflags);
-	while (n) {
-		entry = rb_entry(n, struct xen_p2m_entry, rbnode_mach);
-		if (entry->mfn <= mfn &&
-				entry->mfn + entry->nr_pages > mfn) {
-			read_unlock_irqrestore(&p2m_lock, irqflags);
-			return entry->pfn + (mfn - entry->mfn);
-		}
-		if (mfn < entry->mfn)
-			n = n->rb_left;
-		else
-			n = n->rb_right;
-	}
-	read_unlock_irqrestore(&p2m_lock, irqflags);
-
-	return INVALID_P2M_ENTRY;
-}
-EXPORT_SYMBOL_GPL(__mfn_to_pfn);
-
 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)
@@ -192,7 +130,6 @@ bool __set_phys_to_machine_multi(unsigne
 			p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
 			if (p2m_entry->pfn <= pfn &&
 					p2m_entry->pfn + p2m_entry->nr_pages > pfn) {
-				rb_erase(&p2m_entry->rbnode_mach, &mach_to_phys);
 				rb_erase(&p2m_entry->rbnode_phys, &phys_to_mach);
 				write_unlock_irqrestore(&p2m_lock, irqflags);
 				kfree(p2m_entry);
@@ -217,8 +154,7 @@ bool __set_phys_to_machine_multi(unsigne
 	p2m_entry->mfn = mfn;
 
 	write_lock_irqsave(&p2m_lock, irqflags);
-	if ((rc = xen_add_phys_to_mach_entry(p2m_entry) < 0) ||
-		(rc = xen_add_mach_to_phys_entry(p2m_entry) < 0)) {
+	if ((rc = xen_add_phys_to_mach_entry(p2m_entry)) < 0) {
 		write_unlock_irqrestore(&p2m_lock, irqflags);
 		return false;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/boot/dts/apm-mustang.dts linux-libre-3.17-rc7-gnu/arch/arm64/boot/dts/apm-mustang.dts
--- linux-libre-3.16-gnu/arch/arm64/boot/dts/apm-mustang.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/boot/dts/apm-mustang.dts	2014-09-28 17:29:07.000000000 -0400
@@ -28,3 +28,7 @@
 &serial0 {
 	status = "ok";
 };
+
+&menet {
+	status = "ok";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/boot/dts/apm-storm.dtsi linux-libre-3.17-rc7-gnu/arch/arm64/boot/dts/apm-storm.dtsi
--- linux-libre-3.16-gnu/arch/arm64/boot/dts/apm-storm.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/boot/dts/apm-storm.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -167,14 +167,13 @@
 				clock-output-names = "ethclk";
 			};
 
-			eth8clk: eth8clk {
+			menetclk: menetclk {
 				compatible = "apm,xgene-device-clock";
 				#clock-cells = <1>;
 				clocks = <&ethclk 0>;
-				clock-names = "eth8clk";
 				reg = <0x0 0x1702C000 0x0 0x1000>;
 				reg-names = "csr-reg";
-				clock-output-names = "eth8clk";
+				clock-output-names = "menetclk";
 			};
 
 			sataphy1clk: sataphy1clk@1f21c000 {
@@ -397,5 +396,30 @@
 			#clock-cells = <1>;
 			clocks = <&rtcclk 0>;
 		};
+
+		menet: ethernet@17020000 {
+			compatible = "apm,xgene-enet";
+			status = "disabled";
+			reg = <0x0 0x17020000 0x0 0xd100>,
+			      <0x0 0X17030000 0x0 0X400>,
+			      <0x0 0X10000000 0x0 0X200>;
+			reg-names = "enet_csr", "ring_csr", "ring_cmd";
+			interrupts = <0x0 0x3c 0x4>;
+			dma-coherent;
+			clocks = <&menetclk 0>;
+			local-mac-address = [00 01 73 00 00 01];
+			phy-connection-type = "rgmii";
+			phy-handle = <&menetphy>;
+			mdio {
+				compatible = "apm,xgene-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				menetphy: menetphy@3 {
+					compatible = "ethernet-phy-id001c.c915";
+					reg = <0x3>;
+				};
+
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/configs/defconfig linux-libre-3.17-rc7-gnu/arch/arm64/configs/defconfig
--- linux-libre-3.16-gnu/arch/arm64/configs/defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/configs/defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -52,8 +52,11 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DMA_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
@@ -61,12 +64,16 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
+CONFIG_AHCI_XGENE=y
+CONFIG_PHY_XGENE=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
+CONFIG_NET_XGENE=y
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
@@ -76,6 +83,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_VIRTIO_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
@@ -90,6 +98,7 @@ CONFIG_USB_ISP1760_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
+CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_MMIO=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
@@ -107,6 +116,7 @@ CONFIG_HUGETLBFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
+CONFIG_9P_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_VIRTUALIZATION=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/crypto/Makefile linux-libre-3.17-rc7-gnu/arch/arm64/crypto/Makefile
--- linux-libre-3.16-gnu/arch/arm64/crypto/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/crypto/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -35,4 +35,4 @@ AFLAGS_aes-neon.o	:= -DINTERLEAVE=4
 CFLAGS_aes-glue-ce.o	:= -DUSE_V8_CRYPTO_EXTENSIONS
 
 $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
-	$(call if_changed_dep,cc_o_c)
+	$(call if_changed_rule,cc_o_c)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/crypto/sha2-ce-glue.c linux-libre-3.17-rc7-gnu/arch/arm64/crypto/sha2-ce-glue.c
--- linux-libre-3.16-gnu/arch/arm64/crypto/sha2-ce-glue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/crypto/sha2-ce-glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -150,7 +150,6 @@ static void sha2_finup(struct shash_desc
 	kernel_neon_begin_partial(28);
 	sha2_ce_transform(blocks, data, sctx->state, NULL, len);
 	kernel_neon_end();
-	data += blocks * SHA256_BLOCK_SIZE;
 }
 
 static int sha224_finup(struct shash_desc *desc, const u8 *data,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/cacheflush.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cacheflush.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/cacheflush.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cacheflush.h	2014-09-28 17:29:07.000000000 -0400
@@ -138,19 +138,10 @@ static inline void __flush_icache_all(vo
 #define flush_icache_page(vma,page)	do { } while (0)
 
 /*
- * flush_cache_vmap() is used when creating mappings (eg, via vmap,
- * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
- * caches, since the direct-mappings of these pages may contain cached
- * data, we need to do a full cache flush to ensure that writebacks
- * don't corrupt data placed into these pages via the new mappings.
+ * Not required on AArch64 (PIPT or VIPT non-aliasing D-cache).
  */
 static inline void flush_cache_vmap(unsigned long start, unsigned long end)
 {
-	/*
-	 * set_pte_at() called from vmap_pte_range() does not
-	 * have a DSB after cleaning the cache line.
-	 */
-	dsb(ish);
 }
 
 static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/cachetype.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cachetype.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/cachetype.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cachetype.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,10 +30,14 @@
 
 #ifndef __ASSEMBLY__
 
-static inline u32 icache_policy(void)
-{
-	return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK;
-}
+#include <linux/bitops.h>
+
+#define CTR_L1IP(ctr)	(((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
+
+#define ICACHEF_ALIASING	BIT(0)
+#define ICACHEF_AIVIVT		BIT(1)
+
+extern unsigned long __icache_flags;
 
 /*
  * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
@@ -41,12 +45,12 @@ static inline u32 icache_policy(void)
  */
 static inline int icache_is_aliasing(void)
 {
-	return icache_policy() != ICACHE_POLICY_PIPT;
+	return test_bit(ICACHEF_ALIASING, &__icache_flags);
 }
 
 static inline int icache_is_aivivt(void)
 {
-	return icache_policy() == ICACHE_POLICY_AIVIVT;
+	return test_bit(ICACHEF_AIVIVT, &__icache_flags);
 }
 
 static inline u32 cache_type_cwg(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/cpu.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cpu.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/cpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+  * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CPU_H
+#define __ASM_CPU_H
+
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+
+/*
+ * Records attributes of an individual CPU.
+ */
+struct cpuinfo_arm64 {
+	struct cpu	cpu;
+	u32		reg_ctr;
+	u32		reg_cntfrq;
+	u32		reg_dczid;
+	u32		reg_midr;
+
+	u64		reg_id_aa64isar0;
+	u64		reg_id_aa64isar1;
+	u64		reg_id_aa64mmfr0;
+	u64		reg_id_aa64mmfr1;
+	u64		reg_id_aa64pfr0;
+	u64		reg_id_aa64pfr1;
+
+	u32		reg_id_isar0;
+	u32		reg_id_isar1;
+	u32		reg_id_isar2;
+	u32		reg_id_isar3;
+	u32		reg_id_isar4;
+	u32		reg_id_isar5;
+	u32		reg_id_mmfr0;
+	u32		reg_id_mmfr1;
+	u32		reg_id_mmfr2;
+	u32		reg_id_mmfr3;
+	u32		reg_id_pfr0;
+	u32		reg_id_pfr1;
+};
+
+DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
+
+void cpuinfo_store_cpu(void);
+void __init cpuinfo_store_boot_cpu(void);
+
+#endif /* __ASM_CPU_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/cputype.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cputype.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/cputype.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/cputype.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,8 @@
 
 #define INVALID_HWID		ULONG_MAX
 
+#define MPIDR_UP_BITMASK	(0x1 << 30)
+#define MPIDR_MT_BITMASK	(0x1 << 24)
 #define MPIDR_HWID_BITMASK	0xff00ffffff
 
 #define MPIDR_LEVEL_BITS_SHIFT	3
@@ -36,15 +38,34 @@
 	__val;								\
 })
 
+#define MIDR_REVISION_MASK	0xf
+#define MIDR_REVISION(midr)	((midr) & MIDR_REVISION_MASK)
+#define MIDR_PARTNUM_SHIFT	4
+#define MIDR_PARTNUM_MASK	(0xfff << MIDR_PARTNUM_SHIFT)
+#define MIDR_PARTNUM(midr)	\
+	(((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
+#define MIDR_ARCHITECTURE_SHIFT	16
+#define MIDR_ARCHITECTURE_MASK	(0xf << MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_ARCHITECTURE(midr)	\
+	(((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_VARIANT_SHIFT	20
+#define MIDR_VARIANT_MASK	(0xf << MIDR_VARIANT_SHIFT)
+#define MIDR_VARIANT(midr)	\
+	(((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
+#define MIDR_IMPLEMENTOR_SHIFT	24
+#define MIDR_IMPLEMENTOR_MASK	(0xff << MIDR_IMPLEMENTOR_SHIFT)
+#define MIDR_IMPLEMENTOR(midr)	\
+	(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
+
 #define ARM_CPU_IMP_ARM		0x41
 #define ARM_CPU_IMP_APM		0x50
 
-#define ARM_CPU_PART_AEM_V8	0xD0F0
-#define ARM_CPU_PART_FOUNDATION	0xD000
-#define ARM_CPU_PART_CORTEX_A53	0xD030
-#define ARM_CPU_PART_CORTEX_A57	0xD070
+#define ARM_CPU_PART_AEM_V8	0xD0F
+#define ARM_CPU_PART_FOUNDATION	0xD00
+#define ARM_CPU_PART_CORTEX_A57	0xD07
+#define ARM_CPU_PART_CORTEX_A53	0xD03
 
-#define APM_CPU_PART_POTENZA	0x0000
+#define APM_CPU_PART_POTENZA	0x000
 
 #ifndef __ASSEMBLY__
 
@@ -65,12 +86,12 @@ static inline u64 __attribute_const__ re
 
 static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
 {
-	return (read_cpuid_id() & 0xFF000000) >> 24;
+	return MIDR_IMPLEMENTOR(read_cpuid_id());
 }
 
 static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
 {
-	return (read_cpuid_id() & 0xFFF0);
+	return MIDR_PARTNUM(read_cpuid_id());
 }
 
 static inline u32 __attribute_const__ read_cpuid_cachetype(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/debug-monitors.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/debug-monitors.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/debug-monitors.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/debug-monitors.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,15 @@
 
 #ifdef __KERNEL__
 
+/* Low-level stepping controls. */
+#define DBG_MDSCR_SS		(1 << 0)
+#define DBG_SPSR_SS		(1 << 21)
+
+/* MDSCR_EL1 enabling bits */
+#define DBG_MDSCR_KDE		(1 << 13)
+#define DBG_MDSCR_MDE		(1 << 15)
+#define DBG_MDSCR_MASK		~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
+
 #define	DBG_ESR_EVT(x)		(((x) >> 27) & 0x7)
 
 /* AArch64 */
@@ -73,11 +82,6 @@
 
 #define CACHE_FLUSH_IS_SAFE		1
 
-enum debug_el {
-	DBG_ACTIVE_EL0 = 0,
-	DBG_ACTIVE_EL1,
-};
-
 /* AArch32 */
 #define DBG_ESR_EVT_BKPT	0x4
 #define DBG_ESR_EVT_VECC	0x5
@@ -115,6 +119,11 @@ void unregister_break_hook(struct break_
 
 u8 debug_monitors_arch(void);
 
+enum debug_el {
+	DBG_ACTIVE_EL0 = 0,
+	DBG_ACTIVE_EL1,
+};
+
 void enable_debug_monitors(enum debug_el el);
 void disable_debug_monitors(enum debug_el el);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/efi.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/efi.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/efi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/efi.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,7 @@
 #define _ASM_EFI_H
 
 #include <asm/io.h>
+#include <asm/neon.h>
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
@@ -11,4 +12,36 @@ extern void efi_idmap_init(void);
 #define efi_idmap_init()
 #endif
 
+#define efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f = efi.systab->runtime->f;			\
+	efi_status_t __s;						\
+									\
+	kernel_neon_begin();						\
+	__s = __f(__VA_ARGS__);						\
+	kernel_neon_end();						\
+	__s;								\
+})
+
+#define __efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f = efi.systab->runtime->f;			\
+									\
+	kernel_neon_begin();						\
+	__f(__VA_ARGS__);						\
+	kernel_neon_end();						\
+})
+
+/* arch specific definitions used by the stub code */
+
+/*
+ * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
+ * start of kernel and may not cross a 2MiB boundary. We set alignment to
+ * 2MiB so we know it won't cross a 2MiB boundary.
+ */
+#define EFI_FDT_ALIGN	SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
+#define MAX_FDT_OFFSET	SZ_512M
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
 #endif /* _ASM_EFI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/fpsimdmacros.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/fpsimdmacros.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/fpsimdmacros.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/fpsimdmacros.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,19 @@
 	str	w\tmpnr, [\state, #16 * 2 + 4]
 .endm
 
+.macro fpsimd_restore_fpcr state, tmp
+	/*
+	 * Writes to fpcr may be self-synchronising, so avoid restoring
+	 * the register if it hasn't changed.
+	 */
+	mrs	\tmp, fpcr
+	cmp	\tmp, \state
+	b.eq	9999f
+	msr	fpcr, \state
+9999:
+.endm
+
+/* Clobbers \state */
 .macro fpsimd_restore state, tmpnr
 	ldp	q0, q1, [\state, #16 * 0]
 	ldp	q2, q3, [\state, #16 * 2]
@@ -60,7 +73,7 @@
 	ldr	w\tmpnr, [\state, #16 * 2]
 	msr	fpsr, x\tmpnr
 	ldr	w\tmpnr, [\state, #16 * 2 + 4]
-	msr	fpcr, x\tmpnr
+	fpsimd_restore_fpcr x\tmpnr, \state
 .endm
 
 .altmacro
@@ -84,7 +97,7 @@
 .macro fpsimd_restore_partial state, tmpnr1, tmpnr2
 	ldp	w\tmpnr1, w\tmpnr2, [\state]
 	msr	fpsr, x\tmpnr1
-	msr	fpcr, x\tmpnr2
+	fpsimd_restore_fpcr x\tmpnr2, x\tmpnr1
 	adr	x\tmpnr1, 0f
 	ldr	w\tmpnr2, [\state, #8]
 	add	\state, \state, x\tmpnr2, lsl #4
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/hw_breakpoint.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/hw_breakpoint.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/hw_breakpoint.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/hw_breakpoint.h	2014-09-28 17:29:07.000000000 -0400
@@ -79,7 +79,6 @@ static inline void decode_ctrl_reg(u32 r
  */
 #define ARM_MAX_BRP		16
 #define ARM_MAX_WRP		16
-#define ARM_MAX_HBP_SLOTS	(ARM_MAX_BRP + ARM_MAX_WRP)
 
 /* Virtual debug register bases. */
 #define AARCH64_DBG_REG_BVR	0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_arm.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_arm.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_arm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_arm.h	2014-09-28 17:29:07.000000000 -0400
@@ -76,9 +76,10 @@
  */
 #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
 			 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
-			 HCR_AMO | HCR_IMO | HCR_FMO | \
-			 HCR_SWIO | HCR_TIDCP | HCR_RW)
+			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
 #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+#define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
+
 
 /* Hyp System Control Register (SCTLR_EL2) bits */
 #define SCTLR_EL2_EE	(1 << 25)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_asm.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_asm.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_asm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_asm.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,8 @@
 #ifndef __ARM_KVM_ASM_H__
 #define __ARM_KVM_ASM_H__
 
+#include <asm/virt.h>
+
 /*
  * 0 is reserved as an invalid value.
  * Order *must* be kept in sync with the hyp switch code.
@@ -43,14 +45,25 @@
 #define	AMAIR_EL1	19	/* Aux Memory Attribute Indirection Register */
 #define	CNTKCTL_EL1	20	/* Timer Control Register (EL1) */
 #define	PAR_EL1		21	/* Physical Address Register */
+#define MDSCR_EL1	22	/* Monitor Debug System Control Register */
+#define DBGBCR0_EL1	23	/* Debug Breakpoint Control Registers (0-15) */
+#define DBGBCR15_EL1	38
+#define DBGBVR0_EL1	39	/* Debug Breakpoint Value Registers (0-15) */
+#define DBGBVR15_EL1	54
+#define DBGWCR0_EL1	55	/* Debug Watchpoint Control Registers (0-15) */
+#define DBGWCR15_EL1	70
+#define DBGWVR0_EL1	71	/* Debug Watchpoint Value Registers (0-15) */
+#define DBGWVR15_EL1	86
+#define MDCCINT_EL1	87	/* Monitor Debug Comms Channel Interrupt Enable Reg */
+
 /* 32bit specific registers. Keep them at the end of the range */
-#define	DACR32_EL2	22	/* Domain Access Control Register */
-#define	IFSR32_EL2	23	/* Instruction Fault Status Register */
-#define	FPEXC32_EL2	24	/* Floating-Point Exception Control Register */
-#define	DBGVCR32_EL2	25	/* Debug Vector Catch Register */
-#define	TEECR32_EL1	26	/* ThumbEE Configuration Register */
-#define	TEEHBR32_EL1	27	/* ThumbEE Handler Base Register */
-#define	NR_SYS_REGS	28
+#define	DACR32_EL2	88	/* Domain Access Control Register */
+#define	IFSR32_EL2	89	/* Instruction Fault Status Register */
+#define	FPEXC32_EL2	90	/* Floating-Point Exception Control Register */
+#define	DBGVCR32_EL2	91	/* Debug Vector Catch Register */
+#define	TEECR32_EL1	92	/* ThumbEE Configuration Register */
+#define	TEEHBR32_EL1	93	/* ThumbEE Handler Base Register */
+#define	NR_SYS_REGS	94
 
 /* 32bit mapping */
 #define c0_MPIDR	(MPIDR_EL1 * 2)	/* MultiProcessor ID Register */
@@ -82,11 +95,23 @@
 #define c10_AMAIR0	(AMAIR_EL1 * 2)	/* Aux Memory Attr Indirection Reg */
 #define c10_AMAIR1	(c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */
 #define c14_CNTKCTL	(CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */
-#define NR_CP15_REGS	(NR_SYS_REGS * 2)
+
+#define cp14_DBGDSCRext	(MDSCR_EL1 * 2)
+#define cp14_DBGBCR0	(DBGBCR0_EL1 * 2)
+#define cp14_DBGBVR0	(DBGBVR0_EL1 * 2)
+#define cp14_DBGBXVR0	(cp14_DBGBVR0 + 1)
+#define cp14_DBGWCR0	(DBGWCR0_EL1 * 2)
+#define cp14_DBGWVR0	(DBGWVR0_EL1 * 2)
+#define cp14_DBGDCCINT	(MDCCINT_EL1 * 2)
+
+#define NR_COPRO_REGS	(NR_SYS_REGS * 2)
 
 #define ARM_EXCEPTION_IRQ	  0
 #define ARM_EXCEPTION_TRAP	  1
 
+#define KVM_ARM64_DEBUG_DIRTY_SHIFT	0
+#define KVM_ARM64_DEBUG_DIRTY		(1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
+
 #ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
@@ -96,13 +121,21 @@ extern char __kvm_hyp_init_end[];
 
 extern char __kvm_hyp_vector[];
 
-extern char __kvm_hyp_code_start[];
-extern char __kvm_hyp_code_end[];
+#define	__kvm_hyp_code_start	__hyp_text_start
+#define	__kvm_hyp_code_end	__hyp_text_end
 
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+
+extern u64 __vgic_v3_get_ich_vtr_el2(void);
+
+extern char __save_vgic_v2_state[];
+extern char __restore_vgic_v2_state[];
+extern char __save_vgic_v3_state[];
+extern char __restore_vgic_v3_state[];
+
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_coproc.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_coproc.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_coproc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_coproc.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,8 @@ void kvm_register_target_sys_reg_table(u
 				       struct kvm_sys_reg_target_table *table);
 
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_emulate.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_emulate.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_emulate.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_emulate.h	2014-09-28 17:29:07.000000000 -0400
@@ -213,6 +213,17 @@ static inline unsigned long vcpu_data_gu
 		default:
 			return be64_to_cpu(data);
 		}
+	} else {
+		switch (len) {
+		case 1:
+			return data & 0xff;
+		case 2:
+			return le16_to_cpu(data & 0xffff);
+		case 4:
+			return le32_to_cpu(data & 0xffffffff);
+		default:
+			return le64_to_cpu(data);
+		}
 	}
 
 	return data;		/* Leave LE untouched */
@@ -233,6 +244,17 @@ static inline unsigned long vcpu_data_ho
 		default:
 			return cpu_to_be64(data);
 		}
+	} else {
+		switch (len) {
+		case 1:
+			return data & 0xff;
+		case 2:
+			return cpu_to_le16(data & 0xffff);
+		case 4:
+			return cpu_to_le32(data & 0xffffffff);
+		default:
+			return cpu_to_le64(data);
+		}
 	}
 
 	return data;		/* Leave LE untouched */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@ struct kvm_cpu_context {
 	struct kvm_regs	gp_regs;
 	union {
 		u64 sys_regs[NR_SYS_REGS];
-		u32 cp15[NR_CP15_REGS];
+		u32 copro[NR_COPRO_REGS];
 	};
 };
 
@@ -101,6 +101,9 @@ struct kvm_vcpu_arch {
 	/* Exception Information */
 	struct kvm_vcpu_fault_info fault;
 
+	/* Debug state */
+	u64 debug_flags;
+
 	/* Pointer to host CPU context */
 	kvm_cpu_context_t *host_cpu_context;
 
@@ -138,7 +141,20 @@ struct kvm_vcpu_arch {
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
 #define vcpu_sys_reg(v,r)	((v)->arch.ctxt.sys_regs[(r)])
-#define vcpu_cp15(v,r)		((v)->arch.ctxt.cp15[(r)])
+/*
+ * CP14 and CP15 live in the same array, as they are backed by the
+ * same system registers.
+ */
+#define vcpu_cp14(v,r)		((v)->arch.ctxt.copro[(r)])
+#define vcpu_cp15(v,r)		((v)->arch.ctxt.copro[(r)])
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define vcpu_cp15_64_high(v,r)	vcpu_cp15((v),(r))
+#define vcpu_cp15_64_low(v,r)	vcpu_cp15((v),(r) + 1)
+#else
+#define vcpu_cp15_64_high(v,r)	vcpu_cp15((v),(r) + 1)
+#define vcpu_cp15_64_low(v,r)	vcpu_cp15((v),(r))
+#endif
 
 struct kvm_vm_stat {
 	u32 remote_tlb_flush;
@@ -200,4 +216,32 @@ static inline void __cpu_init_hyp_mode(p
 		     hyp_stack_ptr, vector_ptr);
 }
 
+struct vgic_sr_vectors {
+	void	*save_vgic;
+	void	*restore_vgic;
+};
+
+static inline void vgic_arch_setup(const struct vgic_params *vgic)
+{
+	extern struct vgic_sr_vectors __vgic_sr_vectors;
+
+	switch(vgic->type)
+	{
+	case VGIC_V2:
+		__vgic_sr_vectors.save_vgic	= __save_vgic_v2_state;
+		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v2_state;
+		break;
+
+#ifdef CONFIG_ARM_GIC_V3
+	case VGIC_V3:
+		__vgic_sr_vectors.save_vgic	= __save_vgic_v3_state;
+		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v3_state;
+		break;
+#endif
+
+	default:
+		BUG();
+	}
+}
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_mmu.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_mmu.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/kvm_mmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/kvm_mmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -125,6 +125,21 @@ static inline void kvm_set_s2pmd_writabl
 #define kvm_pud_addr_end(addr, end)	pud_addr_end(addr, end)
 #define kvm_pmd_addr_end(addr, end)	pmd_addr_end(addr, end)
 
+static inline bool kvm_page_empty(void *ptr)
+{
+	struct page *ptr_page = virt_to_page(ptr);
+	return page_count(ptr_page) == 1;
+}
+
+#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep)
+#ifndef CONFIG_ARM64_64K_PAGES
+#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#else
+#define kvm_pmd_table_empty(pmdp) (0)
+#endif
+#define kvm_pud_table_empty(pudp) (0)
+
+
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__flush_dcache_area((a), (l))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/memory.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/memory.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/memory.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/memory.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,7 @@
  * The module space lives between the addresses given by TASK_SIZE
  * and PAGE_OFFSET - it must be within 128MB of the kernel text.
  */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define VA_BITS			(42)
-#else
-#define VA_BITS			(39)
-#endif
+#define VA_BITS			(CONFIG_ARM64_VA_BITS)
 #define PAGE_OFFSET		(UL(0xffffffffffffffff) << (VA_BITS - 1))
 #define MODULES_END		(PAGE_OFFSET)
 #define MODULES_VADDR		(MODULES_END - SZ_64M)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/page.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,17 +28,26 @@
 #define PAGE_SIZE		(_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
-/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
-#define __HAVE_ARCH_GATE_AREA		1
-
-#ifndef __ASSEMBLY__
-
+/*
+ * The idmap and swapper page tables need some space reserved in the kernel
+ * image. Both require pgd, pud (4 levels only) and pmd tables to (section)
+ * map the kernel. With the 64K page configuration, swapper and idmap need to
+ * map to pte level. The swapper also maps the FDT (see __create_page_tables
+ * for more information).
+ */
 #ifdef CONFIG_ARM64_64K_PAGES
-#include <asm/pgtable-2level-types.h>
+#define SWAPPER_PGTABLE_LEVELS	(CONFIG_ARM64_PGTABLE_LEVELS)
 #else
-#include <asm/pgtable-3level-types.h>
+#define SWAPPER_PGTABLE_LEVELS	(CONFIG_ARM64_PGTABLE_LEVELS - 1)
 #endif
 
+#define SWAPPER_DIR_SIZE	(SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
+#define IDMAP_DIR_SIZE		(SWAPPER_DIR_SIZE)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/pgtable-types.h>
+
 extern void __cpu_clear_user_page(void *p, unsigned long user);
 extern void __cpu_copy_user_page(void *to, const void *from,
 				 unsigned long user);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgalloc.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgalloc.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgalloc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgalloc.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 
 #define check_pgt_cache()		do { } while (0)
 
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
@@ -44,7 +44,27 @@ static inline void pud_populate(struct m
 	set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
 }
 
-#endif	/* CONFIG_ARM64_64K_PAGES */
+#endif	/* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+	free_page((unsigned long)pud);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+	set_pgd(pgd, __pgd(__pa(pud) | PUD_TYPE_TABLE));
+}
+
+#endif	/* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
 
 extern pgd_t *pgd_alloc(struct mm_struct *mm);
 extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-2level-hwdef.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-2level-hwdef.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-2level-hwdef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-2level-hwdef.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H
-#define __ASM_PGTABLE_2LEVEL_HWDEF_H
-
-/*
- * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has
- * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not
- * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each
- * entry representing 512MB. The user and kernel address spaces are limited to
- * 4TB in the 64KB page configuration.
- */
-#define PTRS_PER_PTE		8192
-#define PTRS_PER_PGD		8192
-
-/*
- * PGDIR_SHIFT determines the size a top-level page table entry can map.
- */
-#define PGDIR_SHIFT		29
-#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
-#define PGDIR_MASK		(~(PGDIR_SIZE-1))
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT		29
-#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)
-#define SECTION_MASK		(~(SECTION_SIZE-1))
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-2level-types.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-2level-types.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-2level-types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-2level-types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_2LEVEL_TYPES_H
-#define __ASM_PGTABLE_2LEVEL_TYPES_H
-
-#include <asm/types.h>
-
-typedef u64 pteval_t;
-typedef u64 pgdval_t;
-typedef pgdval_t pmdval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { pgdval_t pgd; } pgd_t;
-typedef struct { pteval_t pgprot; } pgprot_t;
-
-#define pte_val(x)      ((x).pte)
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)   ((x).pgprot)
-
-#define __pte(x)        ((pte_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)     ((pgprot_t) { (x) } )
-
-#else	/* !STRICT_MM_TYPECHECKS */
-
-typedef pteval_t pte_t;
-typedef pgdval_t pgd_t;
-typedef pteval_t pgprot_t;
-
-#define pte_val(x)	(x)
-#define pgd_val(x)	(x)
-#define pgprot_val(x)	(x)
-
-#define __pte(x)	(x)
-#define __pgd(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif	/* STRICT_MM_TYPECHECKS */
-
-#include <asm-generic/pgtable-nopmd.h>
-
-#endif	/* __ASM_PGTABLE_2LEVEL_TYPES_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-3level-hwdef.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-3level-hwdef.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-3level-hwdef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-3level-hwdef.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_3LEVEL_HWDEF_H
-#define __ASM_PGTABLE_3LEVEL_HWDEF_H
-
-/*
- * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has
- * 512 entries of 8 bytes each, occupying a 4K page. The first level table
- * covers a range of 512GB, each entry representing 1GB. The user and kernel
- * address spaces are limited to 512GB each.
- */
-#define PTRS_PER_PTE		512
-#define PTRS_PER_PMD		512
-#define PTRS_PER_PGD		512
-
-/*
- * PGDIR_SHIFT determines the size a top-level page table entry can map.
- */
-#define PGDIR_SHIFT		30
-#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
-#define PGDIR_MASK		(~(PGDIR_SIZE-1))
-
-/*
- * PMD_SHIFT determines the size a middle-level page table entry can map.
- */
-#define PMD_SHIFT		21
-#define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
-#define PMD_MASK		(~(PMD_SIZE-1))
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT		21
-#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)
-#define SECTION_MASK		(~(SECTION_SIZE-1))
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-3level-types.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-3level-types.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-3level-types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-3level-types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_3LEVEL_TYPES_H
-#define __ASM_PGTABLE_3LEVEL_TYPES_H
-
-#include <asm/types.h>
-
-typedef u64 pteval_t;
-typedef u64 pmdval_t;
-typedef u64 pgdval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { pmdval_t pmd; } pmd_t;
-typedef struct { pgdval_t pgd; } pgd_t;
-typedef struct { pteval_t pgprot; } pgprot_t;
-
-#define pte_val(x)      ((x).pte)
-#define pmd_val(x)      ((x).pmd)
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)   ((x).pgprot)
-
-#define __pte(x)        ((pte_t) { (x) } )
-#define __pmd(x)        ((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)     ((pgprot_t) { (x) } )
-
-#else	/* !STRICT_MM_TYPECHECKS */
-
-typedef pteval_t pte_t;
-typedef pmdval_t pmd_t;
-typedef pgdval_t pgd_t;
-typedef pteval_t pgprot_t;
-
-#define pte_val(x)	(x)
-#define pmd_val(x)	(x)
-#define pgd_val(x)	(x)
-#define pgprot_val(x)	(x)
-
-#define __pte(x)	(x)
-#define __pmd(x)	(x)
-#define __pgd(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif	/* STRICT_MM_TYPECHECKS */
-
-#include <asm-generic/pgtable-nopud.h>
-
-#endif	/* __ASM_PGTABLE_3LEVEL_TYPES_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,9 +33,16 @@
 
 /*
  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
+ *
+ * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
+ *	(rounded up to PUD_SIZE).
+ * VMALLOC_START: beginning of the kernel VA space
+ * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
+ *	fixed mappings and modules
  */
+#define VMEMMAP_SIZE		ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
 #define VMALLOC_START		(UL(0xffffffffffffffff) << VA_BITS)
-#define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K)
+#define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
 #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
 
@@ -44,14 +51,9 @@
 #ifndef __ASSEMBLY__
 extern void __pte_error(const char *file, int line, unsigned long val);
 extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pud_error(const char *file, int line, unsigned long val);
 extern void __pgd_error(const char *file, int line, unsigned long val);
 
-#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
-#ifndef CONFIG_ARM64_64K_PAGES
-#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
-#endif
-#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
-
 #ifdef CONFIG_SMP
 #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
 #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
@@ -112,6 +114,8 @@ extern void __pgd_error(const char *file
 extern struct page *empty_zero_page;
 #define ZERO_PAGE(vaddr)	(empty_zero_page)
 
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+
 #define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
 
 #define pfn_pte(pfn,prot)	(__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
@@ -119,6 +123,10 @@ extern struct page *empty_zero_page;
 #define pte_none(pte)		(!pte_val(pte))
 #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
+
+/* Find an entry in the third-level page table. */
+#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
 #define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + pte_index(addr))
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
@@ -138,6 +146,8 @@ extern struct page *empty_zero_page;
 
 #define pte_valid_user(pte) \
 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
+#define pte_valid_not_user(pte) \
+	((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
 
 static inline pte_t pte_wrprotect(pte_t pte)
 {
@@ -184,6 +194,15 @@ static inline pte_t pte_mkspecial(pte_t
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
 	*ptep = pte;
+
+	/*
+	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
+	 * or update_mmu_cache() have the necessary barriers.
+	 */
+	if (pte_valid_not_user(pte)) {
+		dsb(ishst);
+		isb();
+	}
 }
 
 extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
@@ -303,6 +322,7 @@ static inline void set_pmd(pmd_t *pmdp,
 {
 	*pmdp = pmd;
 	dsb(ishst);
+	isb();
 }
 
 static inline void pmd_clear(pmd_t *pmdp)
@@ -323,7 +343,9 @@ static inline pte_t *pmd_page_vaddr(pmd_
  */
 #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
 
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+
+#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
 
 #define pud_none(pud)		(!pud_val(pud))
 #define pud_bad(pud)		(!(pud_val(pud) & 2))
@@ -333,6 +355,7 @@ static inline void set_pud(pud_t *pudp,
 {
 	*pudp = pud;
 	dsb(ishst);
+	isb();
 }
 
 static inline void pud_clear(pud_t *pudp)
@@ -345,7 +368,51 @@ static inline pmd_t *pud_page_vaddr(pud_
 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
 }
 
-#endif	/* CONFIG_ARM64_64K_PAGES */
+/* Find an entry in the second-level page table. */
+#define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
+{
+	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
+}
+
+#endif	/* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+
+#define pud_ERROR(pud)		__pud_error(__FILE__, __LINE__, pud_val(pud))
+
+#define pgd_none(pgd)		(!pgd_val(pgd))
+#define pgd_bad(pgd)		(!(pgd_val(pgd) & 2))
+#define pgd_present(pgd)	(pgd_val(pgd))
+
+static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
+{
+	*pgdp = pgd;
+	dsb(ishst);
+}
+
+static inline void pgd_clear(pgd_t *pgdp)
+{
+	set_pgd(pgdp, __pgd(0));
+}
+
+static inline pud_t *pgd_page_vaddr(pgd_t pgd)
+{
+	return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
+}
+
+/* Find an entry in the frst-level page table. */
+#define pud_index(addr)		(((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+
+static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
+{
+	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
+}
+
+#endif  /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
+
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
 
 /* to find an entry in a page-table-directory */
 #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
@@ -355,18 +422,6 @@ static inline pmd_t *pud_page_vaddr(pud_
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
-/* Find an entry in the second-level page table.. */
-#ifndef CONFIG_ARM64_64K_PAGES
-#define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
-static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
-{
-	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
-}
-#endif
-
-/* Find an entry in the third-level page table.. */
-#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
@@ -383,9 +438,6 @@ static inline pmd_t pmd_modify(pmd_t pmd
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
 
-#define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
-#define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
-
 /*
  * Encode and decode a swap entry:
  *	bits 0-1:	present (must be zero)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-hwdef.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-hwdef.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-hwdef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-hwdef.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,18 +16,50 @@
 #ifndef __ASM_PGTABLE_HWDEF_H
 #define __ASM_PGTABLE_HWDEF_H
 
-#ifdef CONFIG_ARM64_64K_PAGES
-#include <asm/pgtable-2level-hwdef.h>
-#else
-#include <asm/pgtable-3level-hwdef.h>
+#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
+
+/*
+ * PMD_SHIFT determines the size a level 2 page table entry can map.
+ */
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#define PMD_SHIFT		((PAGE_SHIFT - 3) * 2 + 3)
+#define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+#define PTRS_PER_PMD		PTRS_PER_PTE
+#endif
+
+/*
+ * PUD_SHIFT determines the size a level 1 page table entry can map.
+ */
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#define PUD_SHIFT		((PAGE_SHIFT - 3) * 3 + 3)
+#define PUD_SIZE		(_AC(1, UL) << PUD_SHIFT)
+#define PUD_MASK		(~(PUD_SIZE-1))
+#define PTRS_PER_PUD		PTRS_PER_PTE
 #endif
 
 /*
+ * PGDIR_SHIFT determines the size a top-level page table entry can map
+ * (depending on the configuration, this level can be 0, 1 or 2).
+ */
+#define PGDIR_SHIFT		((PAGE_SHIFT - 3) * CONFIG_ARM64_PGTABLE_LEVELS + 3)
+#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))
+
+/*
+ * Section address mask and size definitions.
+ */
+#define SECTION_SHIFT		PMD_SHIFT
+#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+/*
  * Hardware page table definitions.
  *
  * Level 1 descriptor (PUD).
  */
-
+#define PUD_TYPE_TABLE		(_AT(pudval_t, 3) << 0)
 #define PUD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
 #define PUD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
 #define PUD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-types.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-types.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/pgtable-types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/pgtable-types.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Page table types definitions.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.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 __ASM_PGTABLE_TYPES_H
+#define __ASM_PGTABLE_TYPES_H
+
+#include <asm/types.h>
+
+typedef u64 pteval_t;
+typedef u64 pmdval_t;
+typedef u64 pudval_t;
+typedef u64 pgdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+#define pte_val(x)	((x).pte)
+#define __pte(x)	((pte_t) { (x) } )
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+typedef struct { pmdval_t pmd; } pmd_t;
+#define pmd_val(x)	((x).pmd)
+#define __pmd(x)	((pmd_t) { (x) } )
+#endif
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+typedef struct { pudval_t pud; } pud_t;
+#define pud_val(x)	((x).pud)
+#define __pud(x)	((pud_t) { (x) } )
+#endif
+
+typedef struct { pgdval_t pgd; } pgd_t;
+#define pgd_val(x)	((x).pgd)
+#define __pgd(x)	((pgd_t) { (x) } )
+
+typedef struct { pteval_t pgprot; } pgprot_t;
+#define pgprot_val(x)	((x).pgprot)
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#else	/* !STRICT_MM_TYPECHECKS */
+
+typedef pteval_t pte_t;
+#define pte_val(x)	(x)
+#define __pte(x)	(x)
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+typedef pmdval_t pmd_t;
+#define pmd_val(x)	(x)
+#define __pmd(x)	(x)
+#endif
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+typedef pudval_t pud_t;
+#define pud_val(x)	(x)
+#define __pud(x)	(x)
+#endif
+
+typedef pgdval_t pgd_t;
+#define pgd_val(x)	(x)
+#define __pgd(x)	(x)
+
+typedef pteval_t pgprot_t;
+#define pgprot_val(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+#if CONFIG_ARM64_PGTABLE_LEVELS == 2
+#include <asm-generic/pgtable-nopmd.h>
+#elif CONFIG_ARM64_PGTABLE_LEVELS == 3
+#include <asm-generic/pgtable-nopud.h>
+#endif
+
+#endif	/* __ASM_PGTABLE_TYPES_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -129,6 +129,7 @@ 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()
 
 /* Thread switching */
 extern struct task_struct *cpu_switch_to(struct task_struct *prev,
@@ -137,8 +138,8 @@ extern struct task_struct *cpu_switch_to
 #define task_pt_regs(p) \
 	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
-#define KSTK_EIP(tsk)	task_pt_regs(tsk)->pc
-#define KSTK_ESP(tsk)	task_pt_regs(tsk)->sp
+#define KSTK_EIP(tsk)	((unsigned long)task_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk)	user_stack_pointer(task_pt_regs(tsk))
 
 /*
  * Prefetching support
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -137,7 +137,7 @@ struct pt_regs {
 	(!((regs)->pstate & PSR_F_BIT))
 
 #define user_stack_pointer(regs) \
-	(!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
+	(!compat_user_mode(regs) ? (regs)->sp : (regs)->compat_sp)
 
 static inline unsigned long regs_return_value(struct pt_regs *regs)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/signal32.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/signal32.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/signal32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/signal32.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,22 +24,21 @@
 
 extern const compat_ulong_t aarch32_sigret_code[6];
 
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
 		       struct pt_regs *regs);
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set, struct pt_regs *regs);
+int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs);
 
 void compat_setup_restart_syscall(struct pt_regs *regs);
 #else
 
-static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
+static inline int compat_setup_frame(int usid, struct ksignal *ksig,
 				     sigset_t *set, struct pt_regs *regs)
 {
 	return -ENOSYS;
 }
 
-static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
-					siginfo_t *info, sigset_t *set,
+static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 					struct pt_regs *regs)
 {
 	return -ENOSYS;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/sparsemem.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/sparsemem.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/sparsemem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/sparsemem.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,7 @@
 #define __ASM_SPARSEMEM_H
 
 #ifdef CONFIG_SPARSEMEM
-#define MAX_PHYSMEM_BITS	40
+#define MAX_PHYSMEM_BITS	48
 #define SECTION_SIZE_BITS	30
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/stackprotector.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/stackprotector.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/stackprotector.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/stackprotector.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * GCC stack protector support.
+ *
+ * Stack protector works by putting predefined pattern at the start of
+ * the stack frame and verifying that it hasn't been overwritten when
+ * returning from the function.  The pattern is called stack canary
+ * and gcc expects it to be defined by a global variable called
+ * "__stack_chk_guard" on ARM.  This unfortunately means that on SMP
+ * we cannot have a different canary value per task.
+ */
+
+#ifndef __ASM_STACKPROTECTOR_H
+#define __ASM_STACKPROTECTOR_H
+
+#include <linux/random.h>
+#include <linux/version.h>
+
+extern unsigned long __stack_chk_guard;
+
+/*
+ * Initialize the stackprotector canary value.
+ *
+ * NOTE: this must only be called from functions that never return,
+ * and it must always be inlined.
+ */
+static __always_inline void boot_init_stack_canary(void)
+{
+	unsigned long canary;
+
+	/* Try to get a semi random initial value. */
+	get_random_bytes(&canary, sizeof(canary));
+	canary ^= LINUX_VERSION_CODE;
+
+	current->stack_canary = canary;
+	__stack_chk_guard = current->stack_canary;
+}
+
+#endif	/* _ASM_STACKPROTECTOR_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/syscall.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/syscall.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/syscall.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/syscall.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,8 @@
 #ifndef __ASM_SYSCALL_H
 #define __ASM_SYSCALL_H
 
+#include <uapi/linux/audit.h>
+#include <linux/compat.h>
 #include <linux/err.h>
 
 extern const void *sys_call_table[];
@@ -105,4 +107,16 @@ static inline void syscall_set_arguments
 	memcpy(&regs->regs[i], args, n * sizeof(args[0]));
 }
 
+/*
+ * We don't care about endianness (__AUDIT_ARCH_LE bit) here because
+ * AArch64 has the same system calls both on little- and big- endian.
+ */
+static inline int syscall_get_arch(void)
+{
+	if (is_compat_task())
+		return AUDIT_ARCH_ARM;
+
+	return AUDIT_ARCH_AARCH64;
+}
+
 #endif	/* __ASM_SYSCALL_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/sysreg.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/sysreg.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/sysreg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/sysreg.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Macros for accessing system registers with older binutils.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.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 __ASM_SYSREG_H
+#define __ASM_SYSREG_H
+
+#define sys_reg(op0, op1, crn, crm, op2) \
+	((((op0)-2)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
+
+#ifdef __ASSEMBLY__
+
+	.irp	num,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
+	.equ	__reg_num_x\num, \num
+	.endr
+	.equ	__reg_num_xzr, 31
+
+	.macro	mrs_s, rt, sreg
+	.inst	0xd5300000|(\sreg)|(__reg_num_\rt)
+	.endm
+
+	.macro	msr_s, sreg, rt
+	.inst	0xd5100000|(\sreg)|(__reg_num_\rt)
+	.endm
+
+#else
+
+asm(
+"	.irp	num,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\n"
+"	.equ	__reg_num_x\\num, \\num\n"
+"	.endr\n"
+"	.equ	__reg_num_xzr, 31\n"
+"\n"
+"	.macro	mrs_s, rt, sreg\n"
+"	.inst	0xd5300000|(\\sreg)|(__reg_num_\\rt)\n"
+"	.endm\n"
+"\n"
+"	.macro	msr_s, sreg, rt\n"
+"	.inst	0xd5100000|(\\sreg)|(__reg_num_\\rt)\n"
+"	.endm\n"
+);
+
+#endif
+
+#endif	/* __ASM_SYSREG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/thread_info.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/thread_info.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/thread_info.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/thread_info.h	2014-09-28 17:29:07.000000000 -0400
@@ -103,6 +103,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_NOHZ		7
 #define TIF_SYSCALL_TRACE	8
 #define TIF_SYSCALL_AUDIT	9
 #define TIF_SYSCALL_TRACEPOINT	10
@@ -118,6 +119,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_FOREIGN_FPSTATE	(1 << TIF_FOREIGN_FPSTATE)
+#define _TIF_NOHZ		(1 << TIF_NOHZ)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
@@ -128,7 +130,8 @@ static inline struct thread_info *curren
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
-				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
+				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
+				 _TIF_NOHZ)
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_THREAD_INFO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/tlbflush.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/tlbflush.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/tlbflush.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/tlbflush.h	2014-09-28 17:29:07.000000000 -0400
@@ -98,8 +98,8 @@ static inline void flush_tlb_page(struct
 	dsb(ish);
 }
 
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-					unsigned long start, unsigned long end)
+static inline void __flush_tlb_range(struct vm_area_struct *vma,
+				     unsigned long start, unsigned long end)
 {
 	unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48;
 	unsigned long addr;
@@ -112,7 +112,7 @@ static inline void flush_tlb_range(struc
 	dsb(ish);
 }
 
-static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
 	unsigned long addr;
 	start >>= 12;
@@ -122,6 +122,30 @@ static inline void flush_tlb_kernel_rang
 	for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
 		asm("tlbi vaae1is, %0" : : "r"(addr));
 	dsb(ish);
+	isb();
+}
+
+/*
+ * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
+ * necessarily a performance improvement.
+ */
+#define MAX_TLB_RANGE	(1024UL << PAGE_SHIFT)
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	if ((end - start) <= MAX_TLB_RANGE)
+		__flush_tlb_range(vma, start, end);
+	else
+		flush_tlb_mm(vma->vm_mm);
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	if ((end - start) <= MAX_TLB_RANGE)
+		__flush_tlb_kernel_range(start, end);
+	else
+		flush_tlb_all();
 }
 
 /*
@@ -131,8 +155,8 @@ static inline void update_mmu_cache(stru
 				    unsigned long addr, pte_t *ptep)
 {
 	/*
-	 * set_pte() does not have a DSB, so make sure that the page table
-	 * write is visible.
+	 * set_pte() does not have a DSB for user mappings, so make sure that
+	 * the page table write is visible.
 	 */
 	dsb(ishst);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/tlb.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/tlb.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/tlb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/tlb.h	2014-09-28 17:29:07.000000000 -0400
@@ -91,7 +91,7 @@ static inline void __pte_free_tlb(struct
 	tlb_remove_page(tlb, pte);
 }
 
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
 				  unsigned long addr)
 {
@@ -100,6 +100,15 @@ static inline void __pmd_free_tlb(struct
 }
 #endif
 
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
+				  unsigned long addr)
+{
+	tlb_add_flush(tlb, addr);
+	tlb_remove_page(tlb, virt_to_page(pudp));
+}
+#endif
+
 static inline void __tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp,
 						unsigned long address)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/unistd32.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/unistd32.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/unistd32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/unistd32.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,403 +21,774 @@
 #define __SYSCALL(x, y)
 #endif
 
-__SYSCALL(0,   sys_restart_syscall)
-__SYSCALL(1,   sys_exit)
-__SYSCALL(2,   sys_fork)
-__SYSCALL(3,   sys_read)
-__SYSCALL(4,   sys_write)
-__SYSCALL(5,   compat_sys_open)
-__SYSCALL(6,   sys_close)
-__SYSCALL(7,   sys_ni_syscall)			/* 7 was sys_waitpid */
-__SYSCALL(8,   sys_creat)
-__SYSCALL(9,   sys_link)
-__SYSCALL(10,  sys_unlink)
-__SYSCALL(11,  compat_sys_execve)
-__SYSCALL(12,  sys_chdir)
-__SYSCALL(13,  sys_ni_syscall)			/* 13 was sys_time */
-__SYSCALL(14,  sys_mknod)
-__SYSCALL(15,  sys_chmod)
-__SYSCALL(16,  sys_lchown16)
-__SYSCALL(17,  sys_ni_syscall)			/* 17 was sys_break */
-__SYSCALL(18,  sys_ni_syscall)			/* 18 was sys_stat */
-__SYSCALL(19,  compat_sys_lseek)
-__SYSCALL(20,  sys_getpid)
-__SYSCALL(21,  compat_sys_mount)
-__SYSCALL(22,  sys_ni_syscall)			/* 22 was sys_umount */
-__SYSCALL(23,  sys_setuid16)
-__SYSCALL(24,  sys_getuid16)
-__SYSCALL(25,  sys_ni_syscall)			/* 25 was sys_stime */
-__SYSCALL(26,  compat_sys_ptrace)
-__SYSCALL(27,  sys_ni_syscall)			/* 27 was sys_alarm */
-__SYSCALL(28,  sys_ni_syscall)			/* 28 was sys_fstat */
-__SYSCALL(29,  sys_pause)
-__SYSCALL(30,  sys_ni_syscall)			/* 30 was sys_utime */
-__SYSCALL(31,  sys_ni_syscall)			/* 31 was sys_stty */
-__SYSCALL(32,  sys_ni_syscall)			/* 32 was sys_gtty */
-__SYSCALL(33,  sys_access)
-__SYSCALL(34,  sys_nice)
-__SYSCALL(35,  sys_ni_syscall)			/* 35 was sys_ftime */
-__SYSCALL(36,  sys_sync)
-__SYSCALL(37,  sys_kill)
-__SYSCALL(38,  sys_rename)
-__SYSCALL(39,  sys_mkdir)
-__SYSCALL(40,  sys_rmdir)
-__SYSCALL(41,  sys_dup)
-__SYSCALL(42,  sys_pipe)
-__SYSCALL(43,  compat_sys_times)
-__SYSCALL(44,  sys_ni_syscall)			/* 44 was sys_prof */
-__SYSCALL(45,  sys_brk)
-__SYSCALL(46,  sys_setgid16)
-__SYSCALL(47,  sys_getgid16)
-__SYSCALL(48,  sys_ni_syscall)			/* 48 was sys_signal */
-__SYSCALL(49,  sys_geteuid16)
-__SYSCALL(50,  sys_getegid16)
-__SYSCALL(51,  sys_acct)
-__SYSCALL(52,  sys_umount)
-__SYSCALL(53,  sys_ni_syscall)			/* 53 was sys_lock */
-__SYSCALL(54,  compat_sys_ioctl)
-__SYSCALL(55,  compat_sys_fcntl)
-__SYSCALL(56,  sys_ni_syscall)			/* 56 was sys_mpx */
-__SYSCALL(57,  sys_setpgid)
-__SYSCALL(58,  sys_ni_syscall)			/* 58 was sys_ulimit */
-__SYSCALL(59,  sys_ni_syscall)			/* 59 was sys_olduname */
-__SYSCALL(60,  sys_umask)
-__SYSCALL(61,  sys_chroot)
-__SYSCALL(62,  compat_sys_ustat)
-__SYSCALL(63,  sys_dup2)
-__SYSCALL(64,  sys_getppid)
-__SYSCALL(65,  sys_getpgrp)
-__SYSCALL(66,  sys_setsid)
-__SYSCALL(67,  compat_sys_sigaction)
-__SYSCALL(68,  sys_ni_syscall)			/* 68 was sys_sgetmask */
-__SYSCALL(69,  sys_ni_syscall)			/* 69 was sys_ssetmask */
-__SYSCALL(70,  sys_setreuid16)
-__SYSCALL(71,  sys_setregid16)
-__SYSCALL(72,  sys_sigsuspend)
-__SYSCALL(73,  compat_sys_sigpending)
-__SYSCALL(74,  sys_sethostname)
-__SYSCALL(75,  compat_sys_setrlimit)
-__SYSCALL(76,  sys_ni_syscall)			/* 76 was compat_sys_getrlimit */
-__SYSCALL(77,  compat_sys_getrusage)
-__SYSCALL(78,  compat_sys_gettimeofday)
-__SYSCALL(79,  compat_sys_settimeofday)
-__SYSCALL(80,  sys_getgroups16)
-__SYSCALL(81,  sys_setgroups16)
-__SYSCALL(82,  sys_ni_syscall)			/* 82 was compat_sys_select */
-__SYSCALL(83,  sys_symlink)
-__SYSCALL(84,  sys_ni_syscall)			/* 84 was sys_lstat */
-__SYSCALL(85,  sys_readlink)
-__SYSCALL(86,  sys_uselib)
-__SYSCALL(87,  sys_swapon)
-__SYSCALL(88,  sys_reboot)
-__SYSCALL(89,  sys_ni_syscall)			/* 89 was sys_readdir */
-__SYSCALL(90,  sys_ni_syscall)			/* 90 was sys_mmap */
-__SYSCALL(91,  sys_munmap)
-__SYSCALL(92,  compat_sys_truncate)
-__SYSCALL(93,  compat_sys_ftruncate)
-__SYSCALL(94,  sys_fchmod)
-__SYSCALL(95,  sys_fchown16)
-__SYSCALL(96,  sys_getpriority)
-__SYSCALL(97,  sys_setpriority)
-__SYSCALL(98,  sys_ni_syscall)			/* 98 was sys_profil */
-__SYSCALL(99,  compat_sys_statfs)
-__SYSCALL(100, compat_sys_fstatfs)
-__SYSCALL(101, sys_ni_syscall)			/* 101 was sys_ioperm */
-__SYSCALL(102, sys_ni_syscall)			/* 102 was sys_socketcall */
-__SYSCALL(103, sys_syslog)
-__SYSCALL(104, compat_sys_setitimer)
-__SYSCALL(105, compat_sys_getitimer)
-__SYSCALL(106, compat_sys_newstat)
-__SYSCALL(107, compat_sys_newlstat)
-__SYSCALL(108, compat_sys_newfstat)
-__SYSCALL(109, sys_ni_syscall)			/* 109 was sys_uname */
-__SYSCALL(110, sys_ni_syscall)			/* 110 was sys_iopl */
-__SYSCALL(111, sys_vhangup)
-__SYSCALL(112, sys_ni_syscall)			/* 112 was sys_idle */
-__SYSCALL(113, sys_ni_syscall)			/* 113 was sys_syscall */
-__SYSCALL(114, compat_sys_wait4)
-__SYSCALL(115, sys_swapoff)
-__SYSCALL(116, compat_sys_sysinfo)
-__SYSCALL(117, sys_ni_syscall)			/* 117 was sys_ipc */
-__SYSCALL(118, sys_fsync)
-__SYSCALL(119, compat_sys_sigreturn_wrapper)
-__SYSCALL(120, sys_clone)
-__SYSCALL(121, sys_setdomainname)
-__SYSCALL(122, sys_newuname)
-__SYSCALL(123, sys_ni_syscall)			/* 123 was sys_modify_ldt */
-__SYSCALL(124, compat_sys_adjtimex)
-__SYSCALL(125, sys_mprotect)
-__SYSCALL(126, compat_sys_sigprocmask)
-__SYSCALL(127, sys_ni_syscall)			/* 127 was sys_create_module */
-__SYSCALL(128, sys_init_module)
-__SYSCALL(129, sys_delete_module)
-__SYSCALL(130, sys_ni_syscall)			/* 130 was sys_get_kernel_syms */
-__SYSCALL(131, sys_quotactl)
-__SYSCALL(132, sys_getpgid)
-__SYSCALL(133, sys_fchdir)
-__SYSCALL(134, sys_bdflush)
-__SYSCALL(135, sys_sysfs)
-__SYSCALL(136, sys_personality)
-__SYSCALL(137, sys_ni_syscall)			/* 137 was sys_afs_syscall */
-__SYSCALL(138, sys_setfsuid16)
-__SYSCALL(139, sys_setfsgid16)
-__SYSCALL(140, sys_llseek)
-__SYSCALL(141, compat_sys_getdents)
-__SYSCALL(142, compat_sys_select)
-__SYSCALL(143, sys_flock)
-__SYSCALL(144, sys_msync)
-__SYSCALL(145, compat_sys_readv)
-__SYSCALL(146, compat_sys_writev)
-__SYSCALL(147, sys_getsid)
-__SYSCALL(148, sys_fdatasync)
-__SYSCALL(149, compat_sys_sysctl)
-__SYSCALL(150, sys_mlock)
-__SYSCALL(151, sys_munlock)
-__SYSCALL(152, sys_mlockall)
-__SYSCALL(153, sys_munlockall)
-__SYSCALL(154, sys_sched_setparam)
-__SYSCALL(155, sys_sched_getparam)
-__SYSCALL(156, sys_sched_setscheduler)
-__SYSCALL(157, sys_sched_getscheduler)
-__SYSCALL(158, sys_sched_yield)
-__SYSCALL(159, sys_sched_get_priority_max)
-__SYSCALL(160, sys_sched_get_priority_min)
-__SYSCALL(161, compat_sys_sched_rr_get_interval)
-__SYSCALL(162, compat_sys_nanosleep)
-__SYSCALL(163, sys_mremap)
-__SYSCALL(164, sys_setresuid16)
-__SYSCALL(165, sys_getresuid16)
-__SYSCALL(166, sys_ni_syscall)			/* 166 was sys_vm86 */
-__SYSCALL(167, sys_ni_syscall)			/* 167 was sys_query_module */
-__SYSCALL(168, sys_poll)
-__SYSCALL(169, sys_ni_syscall)
-__SYSCALL(170, sys_setresgid16)
-__SYSCALL(171, sys_getresgid16)
-__SYSCALL(172, sys_prctl)
-__SYSCALL(173, compat_sys_rt_sigreturn_wrapper)
-__SYSCALL(174, compat_sys_rt_sigaction)
-__SYSCALL(175, compat_sys_rt_sigprocmask)
-__SYSCALL(176, compat_sys_rt_sigpending)
-__SYSCALL(177, compat_sys_rt_sigtimedwait)
-__SYSCALL(178, compat_sys_rt_sigqueueinfo)
-__SYSCALL(179, compat_sys_rt_sigsuspend)
-__SYSCALL(180, compat_sys_pread64_wrapper)
-__SYSCALL(181, compat_sys_pwrite64_wrapper)
-__SYSCALL(182, sys_chown16)
-__SYSCALL(183, sys_getcwd)
-__SYSCALL(184, sys_capget)
-__SYSCALL(185, sys_capset)
-__SYSCALL(186, compat_sys_sigaltstack)
-__SYSCALL(187, compat_sys_sendfile)
-__SYSCALL(188, sys_ni_syscall)			/* 188 reserved */
-__SYSCALL(189, sys_ni_syscall)			/* 189 reserved */
-__SYSCALL(190, sys_vfork)
-__SYSCALL(191, compat_sys_getrlimit)		/* SuS compliant getrlimit */
-__SYSCALL(192, sys_mmap_pgoff)
-__SYSCALL(193, compat_sys_truncate64_wrapper)
-__SYSCALL(194, compat_sys_ftruncate64_wrapper)
-__SYSCALL(195, sys_stat64)
-__SYSCALL(196, sys_lstat64)
-__SYSCALL(197, sys_fstat64)
-__SYSCALL(198, sys_lchown)
-__SYSCALL(199, sys_getuid)
-__SYSCALL(200, sys_getgid)
-__SYSCALL(201, sys_geteuid)
-__SYSCALL(202, sys_getegid)
-__SYSCALL(203, sys_setreuid)
-__SYSCALL(204, sys_setregid)
-__SYSCALL(205, sys_getgroups)
-__SYSCALL(206, sys_setgroups)
-__SYSCALL(207, sys_fchown)
-__SYSCALL(208, sys_setresuid)
-__SYSCALL(209, sys_getresuid)
-__SYSCALL(210, sys_setresgid)
-__SYSCALL(211, sys_getresgid)
-__SYSCALL(212, sys_chown)
-__SYSCALL(213, sys_setuid)
-__SYSCALL(214, sys_setgid)
-__SYSCALL(215, sys_setfsuid)
-__SYSCALL(216, sys_setfsgid)
-__SYSCALL(217, compat_sys_getdents64)
-__SYSCALL(218, sys_pivot_root)
-__SYSCALL(219, sys_mincore)
-__SYSCALL(220, sys_madvise)
-__SYSCALL(221, compat_sys_fcntl64)
-__SYSCALL(222, sys_ni_syscall)			/* 222 for tux */
-__SYSCALL(223, sys_ni_syscall)			/* 223 is unused */
-__SYSCALL(224, sys_gettid)
-__SYSCALL(225, compat_sys_readahead_wrapper)
-__SYSCALL(226, sys_setxattr)
-__SYSCALL(227, sys_lsetxattr)
-__SYSCALL(228, sys_fsetxattr)
-__SYSCALL(229, sys_getxattr)
-__SYSCALL(230, sys_lgetxattr)
-__SYSCALL(231, sys_fgetxattr)
-__SYSCALL(232, sys_listxattr)
-__SYSCALL(233, sys_llistxattr)
-__SYSCALL(234, sys_flistxattr)
-__SYSCALL(235, sys_removexattr)
-__SYSCALL(236, sys_lremovexattr)
-__SYSCALL(237, sys_fremovexattr)
-__SYSCALL(238, sys_tkill)
-__SYSCALL(239, sys_sendfile64)
-__SYSCALL(240, compat_sys_futex)
-__SYSCALL(241, compat_sys_sched_setaffinity)
-__SYSCALL(242, compat_sys_sched_getaffinity)
-__SYSCALL(243, compat_sys_io_setup)
-__SYSCALL(244, sys_io_destroy)
-__SYSCALL(245, compat_sys_io_getevents)
-__SYSCALL(246, compat_sys_io_submit)
-__SYSCALL(247, sys_io_cancel)
-__SYSCALL(248, sys_exit_group)
-__SYSCALL(249, compat_sys_lookup_dcookie)
-__SYSCALL(250, sys_epoll_create)
-__SYSCALL(251, sys_epoll_ctl)
-__SYSCALL(252, sys_epoll_wait)
-__SYSCALL(253, sys_remap_file_pages)
-__SYSCALL(254, sys_ni_syscall)			/* 254 for set_thread_area */
-__SYSCALL(255, sys_ni_syscall)			/* 255 for get_thread_area */
-__SYSCALL(256, sys_set_tid_address)
-__SYSCALL(257, compat_sys_timer_create)
-__SYSCALL(258, compat_sys_timer_settime)
-__SYSCALL(259, compat_sys_timer_gettime)
-__SYSCALL(260, sys_timer_getoverrun)
-__SYSCALL(261, sys_timer_delete)
-__SYSCALL(262, compat_sys_clock_settime)
-__SYSCALL(263, compat_sys_clock_gettime)
-__SYSCALL(264, compat_sys_clock_getres)
-__SYSCALL(265, compat_sys_clock_nanosleep)
-__SYSCALL(266, compat_sys_statfs64_wrapper)
-__SYSCALL(267, compat_sys_fstatfs64_wrapper)
-__SYSCALL(268, sys_tgkill)
-__SYSCALL(269, compat_sys_utimes)
-__SYSCALL(270, compat_sys_fadvise64_64_wrapper)
-__SYSCALL(271, sys_pciconfig_iobase)
-__SYSCALL(272, sys_pciconfig_read)
-__SYSCALL(273, sys_pciconfig_write)
-__SYSCALL(274, compat_sys_mq_open)
-__SYSCALL(275, sys_mq_unlink)
-__SYSCALL(276, compat_sys_mq_timedsend)
-__SYSCALL(277, compat_sys_mq_timedreceive)
-__SYSCALL(278, compat_sys_mq_notify)
-__SYSCALL(279, compat_sys_mq_getsetattr)
-__SYSCALL(280, compat_sys_waitid)
-__SYSCALL(281, sys_socket)
-__SYSCALL(282, sys_bind)
-__SYSCALL(283, sys_connect)
-__SYSCALL(284, sys_listen)
-__SYSCALL(285, sys_accept)
-__SYSCALL(286, sys_getsockname)
-__SYSCALL(287, sys_getpeername)
-__SYSCALL(288, sys_socketpair)
-__SYSCALL(289, sys_send)
-__SYSCALL(290, sys_sendto)
-__SYSCALL(291, compat_sys_recv)
-__SYSCALL(292, compat_sys_recvfrom)
-__SYSCALL(293, sys_shutdown)
-__SYSCALL(294, compat_sys_setsockopt)
-__SYSCALL(295, compat_sys_getsockopt)
-__SYSCALL(296, compat_sys_sendmsg)
-__SYSCALL(297, compat_sys_recvmsg)
-__SYSCALL(298, sys_semop)
-__SYSCALL(299, sys_semget)
-__SYSCALL(300, compat_sys_semctl)
-__SYSCALL(301, compat_sys_msgsnd)
-__SYSCALL(302, compat_sys_msgrcv)
-__SYSCALL(303, sys_msgget)
-__SYSCALL(304, compat_sys_msgctl)
-__SYSCALL(305, compat_sys_shmat)
-__SYSCALL(306, sys_shmdt)
-__SYSCALL(307, sys_shmget)
-__SYSCALL(308, compat_sys_shmctl)
-__SYSCALL(309, sys_add_key)
-__SYSCALL(310, sys_request_key)
-__SYSCALL(311, compat_sys_keyctl)
-__SYSCALL(312, compat_sys_semtimedop)
-__SYSCALL(313, sys_ni_syscall)
-__SYSCALL(314, sys_ioprio_set)
-__SYSCALL(315, sys_ioprio_get)
-__SYSCALL(316, sys_inotify_init)
-__SYSCALL(317, sys_inotify_add_watch)
-__SYSCALL(318, sys_inotify_rm_watch)
-__SYSCALL(319, compat_sys_mbind)
-__SYSCALL(320, compat_sys_get_mempolicy)
-__SYSCALL(321, compat_sys_set_mempolicy)
-__SYSCALL(322, compat_sys_openat)
-__SYSCALL(323, sys_mkdirat)
-__SYSCALL(324, sys_mknodat)
-__SYSCALL(325, sys_fchownat)
-__SYSCALL(326, compat_sys_futimesat)
-__SYSCALL(327, sys_fstatat64)
-__SYSCALL(328, sys_unlinkat)
-__SYSCALL(329, sys_renameat)
-__SYSCALL(330, sys_linkat)
-__SYSCALL(331, sys_symlinkat)
-__SYSCALL(332, sys_readlinkat)
-__SYSCALL(333, sys_fchmodat)
-__SYSCALL(334, sys_faccessat)
-__SYSCALL(335, compat_sys_pselect6)
-__SYSCALL(336, compat_sys_ppoll)
-__SYSCALL(337, sys_unshare)
-__SYSCALL(338, compat_sys_set_robust_list)
-__SYSCALL(339, compat_sys_get_robust_list)
-__SYSCALL(340, sys_splice)
-__SYSCALL(341, compat_sys_sync_file_range2_wrapper)
-__SYSCALL(342, sys_tee)
-__SYSCALL(343, compat_sys_vmsplice)
-__SYSCALL(344, compat_sys_move_pages)
-__SYSCALL(345, sys_getcpu)
-__SYSCALL(346, compat_sys_epoll_pwait)
-__SYSCALL(347, compat_sys_kexec_load)
-__SYSCALL(348, compat_sys_utimensat)
-__SYSCALL(349, compat_sys_signalfd)
-__SYSCALL(350, sys_timerfd_create)
-__SYSCALL(351, sys_eventfd)
-__SYSCALL(352, compat_sys_fallocate_wrapper)
-__SYSCALL(353, compat_sys_timerfd_settime)
-__SYSCALL(354, compat_sys_timerfd_gettime)
-__SYSCALL(355, compat_sys_signalfd4)
-__SYSCALL(356, sys_eventfd2)
-__SYSCALL(357, sys_epoll_create1)
-__SYSCALL(358, sys_dup3)
-__SYSCALL(359, sys_pipe2)
-__SYSCALL(360, sys_inotify_init1)
-__SYSCALL(361, compat_sys_preadv)
-__SYSCALL(362, compat_sys_pwritev)
-__SYSCALL(363, compat_sys_rt_tgsigqueueinfo)
-__SYSCALL(364, sys_perf_event_open)
-__SYSCALL(365, compat_sys_recvmmsg)
-__SYSCALL(366, sys_accept4)
-__SYSCALL(367, sys_fanotify_init)
-__SYSCALL(368, compat_sys_fanotify_mark)
-__SYSCALL(369, sys_prlimit64)
-__SYSCALL(370, sys_name_to_handle_at)
-__SYSCALL(371, compat_sys_open_by_handle_at)
-__SYSCALL(372, compat_sys_clock_adjtime)
-__SYSCALL(373, sys_syncfs)
-__SYSCALL(374, compat_sys_sendmmsg)
-__SYSCALL(375, sys_setns)
-__SYSCALL(376, compat_sys_process_vm_readv)
-__SYSCALL(377, compat_sys_process_vm_writev)
-__SYSCALL(378, sys_kcmp)
-__SYSCALL(379, sys_finit_module)
-__SYSCALL(380, sys_sched_setattr)
-__SYSCALL(381, sys_sched_getattr)
-__SYSCALL(382, sys_renameat2)
-
-#define __NR_compat_syscalls		383
-
-/*
- * Compat syscall numbers used by the AArch64 kernel.
- */
-#define __NR_compat_restart_syscall	0
-#define __NR_compat_sigreturn		119
-#define __NR_compat_rt_sigreturn	173
-
-
-/*
- * The following SVCs are ARM private.
- */
-#define __ARM_NR_COMPAT_BASE		0x0f0000
-#define __ARM_NR_compat_cacheflush	(__ARM_NR_COMPAT_BASE+2)
-#define __ARM_NR_compat_set_tls		(__ARM_NR_COMPAT_BASE+5)
+#define __NR_restart_syscall 0
+__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
+#define __NR_exit 1
+__SYSCALL(__NR_exit, sys_exit)
+#define __NR_fork 2
+__SYSCALL(__NR_fork, sys_fork)
+#define __NR_read 3
+__SYSCALL(__NR_read, sys_read)
+#define __NR_write 4
+__SYSCALL(__NR_write, sys_write)
+#define __NR_open 5
+__SYSCALL(__NR_open, compat_sys_open)
+#define __NR_close 6
+__SYSCALL(__NR_close, sys_close)
+			/* 7 was sys_waitpid */
+__SYSCALL(7, sys_ni_syscall)
+#define __NR_creat 8
+__SYSCALL(__NR_creat, sys_creat)
+#define __NR_link 9
+__SYSCALL(__NR_link, sys_link)
+#define __NR_unlink 10
+__SYSCALL(__NR_unlink, sys_unlink)
+#define __NR_execve 11
+__SYSCALL(__NR_execve, compat_sys_execve)
+#define __NR_chdir 12
+__SYSCALL(__NR_chdir, sys_chdir)
+			/* 13 was sys_time */
+__SYSCALL(13, sys_ni_syscall)
+#define __NR_mknod 14
+__SYSCALL(__NR_mknod, sys_mknod)
+#define __NR_chmod 15
+__SYSCALL(__NR_chmod, sys_chmod)
+#define __NR_lchown 16
+__SYSCALL(__NR_lchown, sys_lchown16)
+			/* 17 was sys_break */
+__SYSCALL(17, sys_ni_syscall)
+			/* 18 was sys_stat */
+__SYSCALL(18, sys_ni_syscall)
+#define __NR_lseek 19
+__SYSCALL(__NR_lseek, compat_sys_lseek)
+#define __NR_getpid 20
+__SYSCALL(__NR_getpid, sys_getpid)
+#define __NR_mount 21
+__SYSCALL(__NR_mount, compat_sys_mount)
+			/* 22 was sys_umount */
+__SYSCALL(22, sys_ni_syscall)
+#define __NR_setuid 23
+__SYSCALL(__NR_setuid, sys_setuid16)
+#define __NR_getuid 24
+__SYSCALL(__NR_getuid, sys_getuid16)
+			/* 25 was sys_stime */
+__SYSCALL(25, sys_ni_syscall)
+#define __NR_ptrace 26
+__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+			/* 27 was sys_alarm */
+__SYSCALL(27, sys_ni_syscall)
+			/* 28 was sys_fstat */
+__SYSCALL(28, sys_ni_syscall)
+#define __NR_pause 29
+__SYSCALL(__NR_pause, sys_pause)
+			/* 30 was sys_utime */
+__SYSCALL(30, sys_ni_syscall)
+			/* 31 was sys_stty */
+__SYSCALL(31, sys_ni_syscall)
+			/* 32 was sys_gtty */
+__SYSCALL(32, sys_ni_syscall)
+#define __NR_access 33
+__SYSCALL(__NR_access, sys_access)
+#define __NR_nice 34
+__SYSCALL(__NR_nice, sys_nice)
+			/* 35 was sys_ftime */
+__SYSCALL(35, sys_ni_syscall)
+#define __NR_sync 36
+__SYSCALL(__NR_sync, sys_sync)
+#define __NR_kill 37
+__SYSCALL(__NR_kill, sys_kill)
+#define __NR_rename 38
+__SYSCALL(__NR_rename, sys_rename)
+#define __NR_mkdir 39
+__SYSCALL(__NR_mkdir, sys_mkdir)
+#define __NR_rmdir 40
+__SYSCALL(__NR_rmdir, sys_rmdir)
+#define __NR_dup 41
+__SYSCALL(__NR_dup, sys_dup)
+#define __NR_pipe 42
+__SYSCALL(__NR_pipe, sys_pipe)
+#define __NR_times 43
+__SYSCALL(__NR_times, compat_sys_times)
+			/* 44 was sys_prof */
+__SYSCALL(44, sys_ni_syscall)
+#define __NR_brk 45
+__SYSCALL(__NR_brk, sys_brk)
+#define __NR_setgid 46
+__SYSCALL(__NR_setgid, sys_setgid16)
+#define __NR_getgid 47
+__SYSCALL(__NR_getgid, sys_getgid16)
+			/* 48 was sys_signal */
+__SYSCALL(48, sys_ni_syscall)
+#define __NR_geteuid 49
+__SYSCALL(__NR_geteuid, sys_geteuid16)
+#define __NR_getegid 50
+__SYSCALL(__NR_getegid, sys_getegid16)
+#define __NR_acct 51
+__SYSCALL(__NR_acct, sys_acct)
+#define __NR_umount2 52
+__SYSCALL(__NR_umount2, sys_umount)
+			/* 53 was sys_lock */
+__SYSCALL(53, sys_ni_syscall)
+#define __NR_ioctl 54
+__SYSCALL(__NR_ioctl, compat_sys_ioctl)
+#define __NR_fcntl 55
+__SYSCALL(__NR_fcntl, compat_sys_fcntl)
+			/* 56 was sys_mpx */
+__SYSCALL(56, sys_ni_syscall)
+#define __NR_setpgid 57
+__SYSCALL(__NR_setpgid, sys_setpgid)
+			/* 58 was sys_ulimit */
+__SYSCALL(58, sys_ni_syscall)
+			/* 59 was sys_olduname */
+__SYSCALL(59, sys_ni_syscall)
+#define __NR_umask 60
+__SYSCALL(__NR_umask, sys_umask)
+#define __NR_chroot 61
+__SYSCALL(__NR_chroot, sys_chroot)
+#define __NR_ustat 62
+__SYSCALL(__NR_ustat, compat_sys_ustat)
+#define __NR_dup2 63
+__SYSCALL(__NR_dup2, sys_dup2)
+#define __NR_getppid 64
+__SYSCALL(__NR_getppid, sys_getppid)
+#define __NR_getpgrp 65
+__SYSCALL(__NR_getpgrp, sys_getpgrp)
+#define __NR_setsid 66
+__SYSCALL(__NR_setsid, sys_setsid)
+#define __NR_sigaction 67
+__SYSCALL(__NR_sigaction, compat_sys_sigaction)
+			/* 68 was sys_sgetmask */
+__SYSCALL(68, sys_ni_syscall)
+			/* 69 was sys_ssetmask */
+__SYSCALL(69, sys_ni_syscall)
+#define __NR_setreuid 70
+__SYSCALL(__NR_setreuid, sys_setreuid16)
+#define __NR_setregid 71
+__SYSCALL(__NR_setregid, sys_setregid16)
+#define __NR_sigsuspend 72
+__SYSCALL(__NR_sigsuspend, sys_sigsuspend)
+#define __NR_sigpending 73
+__SYSCALL(__NR_sigpending, compat_sys_sigpending)
+#define __NR_sethostname 74
+__SYSCALL(__NR_sethostname, sys_sethostname)
+#define __NR_setrlimit 75
+__SYSCALL(__NR_setrlimit, compat_sys_setrlimit)
+			/* 76 was compat_sys_getrlimit */
+__SYSCALL(76, sys_ni_syscall)
+#define __NR_getrusage 77
+__SYSCALL(__NR_getrusage, compat_sys_getrusage)
+#define __NR_gettimeofday 78
+__SYSCALL(__NR_gettimeofday, compat_sys_gettimeofday)
+#define __NR_settimeofday 79
+__SYSCALL(__NR_settimeofday, compat_sys_settimeofday)
+#define __NR_getgroups 80
+__SYSCALL(__NR_getgroups, sys_getgroups16)
+#define __NR_setgroups 81
+__SYSCALL(__NR_setgroups, sys_setgroups16)
+			/* 82 was compat_sys_select */
+__SYSCALL(82, sys_ni_syscall)
+#define __NR_symlink 83
+__SYSCALL(__NR_symlink, sys_symlink)
+			/* 84 was sys_lstat */
+__SYSCALL(84, sys_ni_syscall)
+#define __NR_readlink 85
+__SYSCALL(__NR_readlink, sys_readlink)
+#define __NR_uselib 86
+__SYSCALL(__NR_uselib, sys_uselib)
+#define __NR_swapon 87
+__SYSCALL(__NR_swapon, sys_swapon)
+#define __NR_reboot 88
+__SYSCALL(__NR_reboot, sys_reboot)
+			/* 89 was sys_readdir */
+__SYSCALL(89, sys_ni_syscall)
+			/* 90 was sys_mmap */
+__SYSCALL(90, sys_ni_syscall)
+#define __NR_munmap 91
+__SYSCALL(__NR_munmap, sys_munmap)
+#define __NR_truncate 92
+__SYSCALL(__NR_truncate, compat_sys_truncate)
+#define __NR_ftruncate 93
+__SYSCALL(__NR_ftruncate, compat_sys_ftruncate)
+#define __NR_fchmod 94
+__SYSCALL(__NR_fchmod, sys_fchmod)
+#define __NR_fchown 95
+__SYSCALL(__NR_fchown, sys_fchown16)
+#define __NR_getpriority 96
+__SYSCALL(__NR_getpriority, sys_getpriority)
+#define __NR_setpriority 97
+__SYSCALL(__NR_setpriority, sys_setpriority)
+			/* 98 was sys_profil */
+__SYSCALL(98, sys_ni_syscall)
+#define __NR_statfs 99
+__SYSCALL(__NR_statfs, compat_sys_statfs)
+#define __NR_fstatfs 100
+__SYSCALL(__NR_fstatfs, compat_sys_fstatfs)
+			/* 101 was sys_ioperm */
+__SYSCALL(101, sys_ni_syscall)
+			/* 102 was sys_socketcall */
+__SYSCALL(102, sys_ni_syscall)
+#define __NR_syslog 103
+__SYSCALL(__NR_syslog, sys_syslog)
+#define __NR_setitimer 104
+__SYSCALL(__NR_setitimer, compat_sys_setitimer)
+#define __NR_getitimer 105
+__SYSCALL(__NR_getitimer, compat_sys_getitimer)
+#define __NR_stat 106
+__SYSCALL(__NR_stat, compat_sys_newstat)
+#define __NR_lstat 107
+__SYSCALL(__NR_lstat, compat_sys_newlstat)
+#define __NR_fstat 108
+__SYSCALL(__NR_fstat, compat_sys_newfstat)
+			/* 109 was sys_uname */
+__SYSCALL(109, sys_ni_syscall)
+			/* 110 was sys_iopl */
+__SYSCALL(110, sys_ni_syscall)
+#define __NR_vhangup 111
+__SYSCALL(__NR_vhangup, sys_vhangup)
+			/* 112 was sys_idle */
+__SYSCALL(112, sys_ni_syscall)
+			/* 113 was sys_syscall */
+__SYSCALL(113, sys_ni_syscall)
+#define __NR_wait4 114
+__SYSCALL(__NR_wait4, compat_sys_wait4)
+#define __NR_swapoff 115
+__SYSCALL(__NR_swapoff, sys_swapoff)
+#define __NR_sysinfo 116
+__SYSCALL(__NR_sysinfo, compat_sys_sysinfo)
+			/* 117 was sys_ipc */
+__SYSCALL(117, sys_ni_syscall)
+#define __NR_fsync 118
+__SYSCALL(__NR_fsync, sys_fsync)
+#define __NR_sigreturn 119
+__SYSCALL(__NR_sigreturn, compat_sys_sigreturn_wrapper)
+#define __NR_clone 120
+__SYSCALL(__NR_clone, sys_clone)
+#define __NR_setdomainname 121
+__SYSCALL(__NR_setdomainname, sys_setdomainname)
+#define __NR_uname 122
+__SYSCALL(__NR_uname, sys_newuname)
+			/* 123 was sys_modify_ldt */
+__SYSCALL(123, sys_ni_syscall)
+#define __NR_adjtimex 124
+__SYSCALL(__NR_adjtimex, compat_sys_adjtimex)
+#define __NR_mprotect 125
+__SYSCALL(__NR_mprotect, sys_mprotect)
+#define __NR_sigprocmask 126
+__SYSCALL(__NR_sigprocmask, compat_sys_sigprocmask)
+			/* 127 was sys_create_module */
+__SYSCALL(127, sys_ni_syscall)
+#define __NR_init_module 128
+__SYSCALL(__NR_init_module, sys_init_module)
+#define __NR_delete_module 129
+__SYSCALL(__NR_delete_module, sys_delete_module)
+			/* 130 was sys_get_kernel_syms */
+__SYSCALL(130, sys_ni_syscall)
+#define __NR_quotactl 131
+__SYSCALL(__NR_quotactl, sys_quotactl)
+#define __NR_getpgid 132
+__SYSCALL(__NR_getpgid, sys_getpgid)
+#define __NR_fchdir 133
+__SYSCALL(__NR_fchdir, sys_fchdir)
+#define __NR_bdflush 134
+__SYSCALL(__NR_bdflush, sys_bdflush)
+#define __NR_sysfs 135
+__SYSCALL(__NR_sysfs, sys_sysfs)
+#define __NR_personality 136
+__SYSCALL(__NR_personality, sys_personality)
+			/* 137 was sys_afs_syscall */
+__SYSCALL(137, sys_ni_syscall)
+#define __NR_setfsuid 138
+__SYSCALL(__NR_setfsuid, sys_setfsuid16)
+#define __NR_setfsgid 139
+__SYSCALL(__NR_setfsgid, sys_setfsgid16)
+#define __NR__llseek 140
+__SYSCALL(__NR__llseek, sys_llseek)
+#define __NR_getdents 141
+__SYSCALL(__NR_getdents, compat_sys_getdents)
+#define __NR__newselect 142
+__SYSCALL(__NR__newselect, compat_sys_select)
+#define __NR_flock 143
+__SYSCALL(__NR_flock, sys_flock)
+#define __NR_msync 144
+__SYSCALL(__NR_msync, sys_msync)
+#define __NR_readv 145
+__SYSCALL(__NR_readv, compat_sys_readv)
+#define __NR_writev 146
+__SYSCALL(__NR_writev, compat_sys_writev)
+#define __NR_getsid 147
+__SYSCALL(__NR_getsid, sys_getsid)
+#define __NR_fdatasync 148
+__SYSCALL(__NR_fdatasync, sys_fdatasync)
+#define __NR__sysctl 149
+__SYSCALL(__NR__sysctl, compat_sys_sysctl)
+#define __NR_mlock 150
+__SYSCALL(__NR_mlock, sys_mlock)
+#define __NR_munlock 151
+__SYSCALL(__NR_munlock, sys_munlock)
+#define __NR_mlockall 152
+__SYSCALL(__NR_mlockall, sys_mlockall)
+#define __NR_munlockall 153
+__SYSCALL(__NR_munlockall, sys_munlockall)
+#define __NR_sched_setparam 154
+__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
+#define __NR_sched_getparam 155
+__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
+#define __NR_sched_setscheduler 156
+__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
+#define __NR_sched_getscheduler 157
+__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
+#define __NR_sched_yield 158
+__SYSCALL(__NR_sched_yield, sys_sched_yield)
+#define __NR_sched_get_priority_max 159
+__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
+#define __NR_sched_get_priority_min 160
+__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
+#define __NR_sched_rr_get_interval 161
+__SYSCALL(__NR_sched_rr_get_interval, compat_sys_sched_rr_get_interval)
+#define __NR_nanosleep 162
+__SYSCALL(__NR_nanosleep, compat_sys_nanosleep)
+#define __NR_mremap 163
+__SYSCALL(__NR_mremap, sys_mremap)
+#define __NR_setresuid 164
+__SYSCALL(__NR_setresuid, sys_setresuid16)
+#define __NR_getresuid 165
+__SYSCALL(__NR_getresuid, sys_getresuid16)
+			/* 166 was sys_vm86 */
+__SYSCALL(166, sys_ni_syscall)
+			/* 167 was sys_query_module */
+__SYSCALL(167, sys_ni_syscall)
+#define __NR_poll 168
+__SYSCALL(__NR_poll, sys_poll)
+#define __NR_nfsservctl 169
+__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
+#define __NR_setresgid 170
+__SYSCALL(__NR_setresgid, sys_setresgid16)
+#define __NR_getresgid 171
+__SYSCALL(__NR_getresgid, sys_getresgid16)
+#define __NR_prctl 172
+__SYSCALL(__NR_prctl, sys_prctl)
+#define __NR_rt_sigreturn 173
+__SYSCALL(__NR_rt_sigreturn, compat_sys_rt_sigreturn_wrapper)
+#define __NR_rt_sigaction 174
+__SYSCALL(__NR_rt_sigaction, compat_sys_rt_sigaction)
+#define __NR_rt_sigprocmask 175
+__SYSCALL(__NR_rt_sigprocmask, compat_sys_rt_sigprocmask)
+#define __NR_rt_sigpending 176
+__SYSCALL(__NR_rt_sigpending, compat_sys_rt_sigpending)
+#define __NR_rt_sigtimedwait 177
+__SYSCALL(__NR_rt_sigtimedwait, compat_sys_rt_sigtimedwait)
+#define __NR_rt_sigqueueinfo 178
+__SYSCALL(__NR_rt_sigqueueinfo, compat_sys_rt_sigqueueinfo)
+#define __NR_rt_sigsuspend 179
+__SYSCALL(__NR_rt_sigsuspend, compat_sys_rt_sigsuspend)
+#define __NR_pread64 180
+__SYSCALL(__NR_pread64, compat_sys_pread64_wrapper)
+#define __NR_pwrite64 181
+__SYSCALL(__NR_pwrite64, compat_sys_pwrite64_wrapper)
+#define __NR_chown 182
+__SYSCALL(__NR_chown, sys_chown16)
+#define __NR_getcwd 183
+__SYSCALL(__NR_getcwd, sys_getcwd)
+#define __NR_capget 184
+__SYSCALL(__NR_capget, sys_capget)
+#define __NR_capset 185
+__SYSCALL(__NR_capset, sys_capset)
+#define __NR_sigaltstack 186
+__SYSCALL(__NR_sigaltstack, compat_sys_sigaltstack)
+#define __NR_sendfile 187
+__SYSCALL(__NR_sendfile, compat_sys_sendfile)
+			/* 188 reserved */
+__SYSCALL(188, sys_ni_syscall)
+			/* 189 reserved */
+__SYSCALL(189, sys_ni_syscall)
+#define __NR_vfork 190
+__SYSCALL(__NR_vfork, sys_vfork)
+#define __NR_ugetrlimit 191	/* SuS compliant getrlimit */
+__SYSCALL(__NR_ugetrlimit, compat_sys_getrlimit)		/* SuS compliant getrlimit */
+#define __NR_mmap2 192
+__SYSCALL(__NR_mmap2, sys_mmap_pgoff)
+#define __NR_truncate64 193
+__SYSCALL(__NR_truncate64, compat_sys_truncate64_wrapper)
+#define __NR_ftruncate64 194
+__SYSCALL(__NR_ftruncate64, compat_sys_ftruncate64_wrapper)
+#define __NR_stat64 195
+__SYSCALL(__NR_stat64, sys_stat64)
+#define __NR_lstat64 196
+__SYSCALL(__NR_lstat64, sys_lstat64)
+#define __NR_fstat64 197
+__SYSCALL(__NR_fstat64, sys_fstat64)
+#define __NR_lchown32 198
+__SYSCALL(__NR_lchown32, sys_lchown)
+#define __NR_getuid32 199
+__SYSCALL(__NR_getuid32, sys_getuid)
+#define __NR_getgid32 200
+__SYSCALL(__NR_getgid32, sys_getgid)
+#define __NR_geteuid32 201
+__SYSCALL(__NR_geteuid32, sys_geteuid)
+#define __NR_getegid32 202
+__SYSCALL(__NR_getegid32, sys_getegid)
+#define __NR_setreuid32 203
+__SYSCALL(__NR_setreuid32, sys_setreuid)
+#define __NR_setregid32 204
+__SYSCALL(__NR_setregid32, sys_setregid)
+#define __NR_getgroups32 205
+__SYSCALL(__NR_getgroups32, sys_getgroups)
+#define __NR_setgroups32 206
+__SYSCALL(__NR_setgroups32, sys_setgroups)
+#define __NR_fchown32 207
+__SYSCALL(__NR_fchown32, sys_fchown)
+#define __NR_setresuid32 208
+__SYSCALL(__NR_setresuid32, sys_setresuid)
+#define __NR_getresuid32 209
+__SYSCALL(__NR_getresuid32, sys_getresuid)
+#define __NR_setresgid32 210
+__SYSCALL(__NR_setresgid32, sys_setresgid)
+#define __NR_getresgid32 211
+__SYSCALL(__NR_getresgid32, sys_getresgid)
+#define __NR_chown32 212
+__SYSCALL(__NR_chown32, sys_chown)
+#define __NR_setuid32 213
+__SYSCALL(__NR_setuid32, sys_setuid)
+#define __NR_setgid32 214
+__SYSCALL(__NR_setgid32, sys_setgid)
+#define __NR_setfsuid32 215
+__SYSCALL(__NR_setfsuid32, sys_setfsuid)
+#define __NR_setfsgid32 216
+__SYSCALL(__NR_setfsgid32, sys_setfsgid)
+#define __NR_getdents64 217
+__SYSCALL(__NR_getdents64, compat_sys_getdents64)
+#define __NR_pivot_root 218
+__SYSCALL(__NR_pivot_root, sys_pivot_root)
+#define __NR_mincore 219
+__SYSCALL(__NR_mincore, sys_mincore)
+#define __NR_madvise 220
+__SYSCALL(__NR_madvise, sys_madvise)
+#define __NR_fcntl64 221
+__SYSCALL(__NR_fcntl64, compat_sys_fcntl64)
+			/* 222 for tux */
+__SYSCALL(222, sys_ni_syscall)
+			/* 223 is unused */
+__SYSCALL(223, sys_ni_syscall)
+#define __NR_gettid 224
+__SYSCALL(__NR_gettid, sys_gettid)
+#define __NR_readahead 225
+__SYSCALL(__NR_readahead, compat_sys_readahead_wrapper)
+#define __NR_setxattr 226
+__SYSCALL(__NR_setxattr, sys_setxattr)
+#define __NR_lsetxattr 227
+__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
+#define __NR_fsetxattr 228
+__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
+#define __NR_getxattr 229
+__SYSCALL(__NR_getxattr, sys_getxattr)
+#define __NR_lgetxattr 230
+__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
+#define __NR_fgetxattr 231
+__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+#define __NR_listxattr 232
+__SYSCALL(__NR_listxattr, sys_listxattr)
+#define __NR_llistxattr 233
+__SYSCALL(__NR_llistxattr, sys_llistxattr)
+#define __NR_flistxattr 234
+__SYSCALL(__NR_flistxattr, sys_flistxattr)
+#define __NR_removexattr 235
+__SYSCALL(__NR_removexattr, sys_removexattr)
+#define __NR_lremovexattr 236
+__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+#define __NR_fremovexattr 237
+__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+#define __NR_tkill 238
+__SYSCALL(__NR_tkill, sys_tkill)
+#define __NR_sendfile64 239
+__SYSCALL(__NR_sendfile64, sys_sendfile64)
+#define __NR_futex 240
+__SYSCALL(__NR_futex, compat_sys_futex)
+#define __NR_sched_setaffinity 241
+__SYSCALL(__NR_sched_setaffinity, compat_sys_sched_setaffinity)
+#define __NR_sched_getaffinity 242
+__SYSCALL(__NR_sched_getaffinity, compat_sys_sched_getaffinity)
+#define __NR_io_setup 243
+__SYSCALL(__NR_io_setup, compat_sys_io_setup)
+#define __NR_io_destroy 244
+__SYSCALL(__NR_io_destroy, sys_io_destroy)
+#define __NR_io_getevents 245
+__SYSCALL(__NR_io_getevents, compat_sys_io_getevents)
+#define __NR_io_submit 246
+__SYSCALL(__NR_io_submit, compat_sys_io_submit)
+#define __NR_io_cancel 247
+__SYSCALL(__NR_io_cancel, sys_io_cancel)
+#define __NR_exit_group 248
+__SYSCALL(__NR_exit_group, sys_exit_group)
+#define __NR_lookup_dcookie 249
+__SYSCALL(__NR_lookup_dcookie, compat_sys_lookup_dcookie)
+#define __NR_epoll_create 250
+__SYSCALL(__NR_epoll_create, sys_epoll_create)
+#define __NR_epoll_ctl 251
+__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
+#define __NR_epoll_wait 252
+__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
+#define __NR_remap_file_pages 253
+__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
+			/* 254 for set_thread_area */
+__SYSCALL(254, sys_ni_syscall)
+			/* 255 for get_thread_area */
+__SYSCALL(255, sys_ni_syscall)
+#define __NR_set_tid_address 256
+__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
+#define __NR_timer_create 257
+__SYSCALL(__NR_timer_create, compat_sys_timer_create)
+#define __NR_timer_settime 258
+__SYSCALL(__NR_timer_settime, compat_sys_timer_settime)
+#define __NR_timer_gettime 259
+__SYSCALL(__NR_timer_gettime, compat_sys_timer_gettime)
+#define __NR_timer_getoverrun 260
+__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
+#define __NR_timer_delete 261
+__SYSCALL(__NR_timer_delete, sys_timer_delete)
+#define __NR_clock_settime 262
+__SYSCALL(__NR_clock_settime, compat_sys_clock_settime)
+#define __NR_clock_gettime 263
+__SYSCALL(__NR_clock_gettime, compat_sys_clock_gettime)
+#define __NR_clock_getres 264
+__SYSCALL(__NR_clock_getres, compat_sys_clock_getres)
+#define __NR_clock_nanosleep 265
+__SYSCALL(__NR_clock_nanosleep, compat_sys_clock_nanosleep)
+#define __NR_statfs64 266
+__SYSCALL(__NR_statfs64, compat_sys_statfs64_wrapper)
+#define __NR_fstatfs64 267
+__SYSCALL(__NR_fstatfs64, compat_sys_fstatfs64_wrapper)
+#define __NR_tgkill 268
+__SYSCALL(__NR_tgkill, sys_tgkill)
+#define __NR_utimes 269
+__SYSCALL(__NR_utimes, compat_sys_utimes)
+#define __NR_arm_fadvise64_64 270
+__SYSCALL(__NR_arm_fadvise64_64, compat_sys_fadvise64_64_wrapper)
+#define __NR_pciconfig_iobase 271
+__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase)
+#define __NR_pciconfig_read 272
+__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read)
+#define __NR_pciconfig_write 273
+__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write)
+#define __NR_mq_open 274
+__SYSCALL(__NR_mq_open, compat_sys_mq_open)
+#define __NR_mq_unlink 275
+__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+#define __NR_mq_timedsend 276
+__SYSCALL(__NR_mq_timedsend, compat_sys_mq_timedsend)
+#define __NR_mq_timedreceive 277
+__SYSCALL(__NR_mq_timedreceive, compat_sys_mq_timedreceive)
+#define __NR_mq_notify 278
+__SYSCALL(__NR_mq_notify, compat_sys_mq_notify)
+#define __NR_mq_getsetattr 279
+__SYSCALL(__NR_mq_getsetattr, compat_sys_mq_getsetattr)
+#define __NR_waitid 280
+__SYSCALL(__NR_waitid, compat_sys_waitid)
+#define __NR_socket 281
+__SYSCALL(__NR_socket, sys_socket)
+#define __NR_bind 282
+__SYSCALL(__NR_bind, sys_bind)
+#define __NR_connect 283
+__SYSCALL(__NR_connect, sys_connect)
+#define __NR_listen 284
+__SYSCALL(__NR_listen, sys_listen)
+#define __NR_accept 285
+__SYSCALL(__NR_accept, sys_accept)
+#define __NR_getsockname 286
+__SYSCALL(__NR_getsockname, sys_getsockname)
+#define __NR_getpeername 287
+__SYSCALL(__NR_getpeername, sys_getpeername)
+#define __NR_socketpair 288
+__SYSCALL(__NR_socketpair, sys_socketpair)
+#define __NR_send 289
+__SYSCALL(__NR_send, sys_send)
+#define __NR_sendto 290
+__SYSCALL(__NR_sendto, sys_sendto)
+#define __NR_recv 291
+__SYSCALL(__NR_recv, compat_sys_recv)
+#define __NR_recvfrom 292
+__SYSCALL(__NR_recvfrom, compat_sys_recvfrom)
+#define __NR_shutdown 293
+__SYSCALL(__NR_shutdown, sys_shutdown)
+#define __NR_setsockopt 294
+__SYSCALL(__NR_setsockopt, compat_sys_setsockopt)
+#define __NR_getsockopt 295
+__SYSCALL(__NR_getsockopt, compat_sys_getsockopt)
+#define __NR_sendmsg 296
+__SYSCALL(__NR_sendmsg, compat_sys_sendmsg)
+#define __NR_recvmsg 297
+__SYSCALL(__NR_recvmsg, compat_sys_recvmsg)
+#define __NR_semop 298
+__SYSCALL(__NR_semop, sys_semop)
+#define __NR_semget 299
+__SYSCALL(__NR_semget, sys_semget)
+#define __NR_semctl 300
+__SYSCALL(__NR_semctl, compat_sys_semctl)
+#define __NR_msgsnd 301
+__SYSCALL(__NR_msgsnd, compat_sys_msgsnd)
+#define __NR_msgrcv 302
+__SYSCALL(__NR_msgrcv, compat_sys_msgrcv)
+#define __NR_msgget 303
+__SYSCALL(__NR_msgget, sys_msgget)
+#define __NR_msgctl 304
+__SYSCALL(__NR_msgctl, compat_sys_msgctl)
+#define __NR_shmat 305
+__SYSCALL(__NR_shmat, compat_sys_shmat)
+#define __NR_shmdt 306
+__SYSCALL(__NR_shmdt, sys_shmdt)
+#define __NR_shmget 307
+__SYSCALL(__NR_shmget, sys_shmget)
+#define __NR_shmctl 308
+__SYSCALL(__NR_shmctl, compat_sys_shmctl)
+#define __NR_add_key 309
+__SYSCALL(__NR_add_key, sys_add_key)
+#define __NR_request_key 310
+__SYSCALL(__NR_request_key, sys_request_key)
+#define __NR_keyctl 311
+__SYSCALL(__NR_keyctl, compat_sys_keyctl)
+#define __NR_semtimedop 312
+__SYSCALL(__NR_semtimedop, compat_sys_semtimedop)
+#define __NR_vserver 313
+__SYSCALL(__NR_vserver, sys_ni_syscall)
+#define __NR_ioprio_set 314
+__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
+#define __NR_ioprio_get 315
+__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
+#define __NR_inotify_init 316
+__SYSCALL(__NR_inotify_init, sys_inotify_init)
+#define __NR_inotify_add_watch 317
+__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
+#define __NR_inotify_rm_watch 318
+__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
+#define __NR_mbind 319
+__SYSCALL(__NR_mbind, compat_sys_mbind)
+#define __NR_get_mempolicy 320
+__SYSCALL(__NR_get_mempolicy, compat_sys_get_mempolicy)
+#define __NR_set_mempolicy 321
+__SYSCALL(__NR_set_mempolicy, compat_sys_set_mempolicy)
+#define __NR_openat 322
+__SYSCALL(__NR_openat, compat_sys_openat)
+#define __NR_mkdirat 323
+__SYSCALL(__NR_mkdirat, sys_mkdirat)
+#define __NR_mknodat 324
+__SYSCALL(__NR_mknodat, sys_mknodat)
+#define __NR_fchownat 325
+__SYSCALL(__NR_fchownat, sys_fchownat)
+#define __NR_futimesat 326
+__SYSCALL(__NR_futimesat, compat_sys_futimesat)
+#define __NR_fstatat64 327
+__SYSCALL(__NR_fstatat64, sys_fstatat64)
+#define __NR_unlinkat 328
+__SYSCALL(__NR_unlinkat, sys_unlinkat)
+#define __NR_renameat 329
+__SYSCALL(__NR_renameat, sys_renameat)
+#define __NR_linkat 330
+__SYSCALL(__NR_linkat, sys_linkat)
+#define __NR_symlinkat 331
+__SYSCALL(__NR_symlinkat, sys_symlinkat)
+#define __NR_readlinkat 332
+__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#define __NR_fchmodat 333
+__SYSCALL(__NR_fchmodat, sys_fchmodat)
+#define __NR_faccessat 334
+__SYSCALL(__NR_faccessat, sys_faccessat)
+#define __NR_pselect6 335
+__SYSCALL(__NR_pselect6, compat_sys_pselect6)
+#define __NR_ppoll 336
+__SYSCALL(__NR_ppoll, compat_sys_ppoll)
+#define __NR_unshare 337
+__SYSCALL(__NR_unshare, sys_unshare)
+#define __NR_set_robust_list 338
+__SYSCALL(__NR_set_robust_list, compat_sys_set_robust_list)
+#define __NR_get_robust_list 339
+__SYSCALL(__NR_get_robust_list, compat_sys_get_robust_list)
+#define __NR_splice 340
+__SYSCALL(__NR_splice, sys_splice)
+#define __NR_sync_file_range2 341
+__SYSCALL(__NR_sync_file_range2, compat_sys_sync_file_range2_wrapper)
+#define __NR_tee 342
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_vmsplice 343
+__SYSCALL(__NR_vmsplice, compat_sys_vmsplice)
+#define __NR_move_pages 344
+__SYSCALL(__NR_move_pages, compat_sys_move_pages)
+#define __NR_getcpu 345
+__SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_epoll_pwait 346
+__SYSCALL(__NR_epoll_pwait, compat_sys_epoll_pwait)
+#define __NR_kexec_load 347
+__SYSCALL(__NR_kexec_load, compat_sys_kexec_load)
+#define __NR_utimensat 348
+__SYSCALL(__NR_utimensat, compat_sys_utimensat)
+#define __NR_signalfd 349
+__SYSCALL(__NR_signalfd, compat_sys_signalfd)
+#define __NR_timerfd_create 350
+__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
+#define __NR_eventfd 351
+__SYSCALL(__NR_eventfd, sys_eventfd)
+#define __NR_fallocate 352
+__SYSCALL(__NR_fallocate, compat_sys_fallocate_wrapper)
+#define __NR_timerfd_settime 353
+__SYSCALL(__NR_timerfd_settime, compat_sys_timerfd_settime)
+#define __NR_timerfd_gettime 354
+__SYSCALL(__NR_timerfd_gettime, compat_sys_timerfd_gettime)
+#define __NR_signalfd4 355
+__SYSCALL(__NR_signalfd4, compat_sys_signalfd4)
+#define __NR_eventfd2 356
+__SYSCALL(__NR_eventfd2, sys_eventfd2)
+#define __NR_epoll_create1 357
+__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
+#define __NR_dup3 358
+__SYSCALL(__NR_dup3, sys_dup3)
+#define __NR_pipe2 359
+__SYSCALL(__NR_pipe2, sys_pipe2)
+#define __NR_inotify_init1 360
+__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
+#define __NR_preadv 361
+__SYSCALL(__NR_preadv, compat_sys_preadv)
+#define __NR_pwritev 362
+__SYSCALL(__NR_pwritev, compat_sys_pwritev)
+#define __NR_rt_tgsigqueueinfo 363
+__SYSCALL(__NR_rt_tgsigqueueinfo, compat_sys_rt_tgsigqueueinfo)
+#define __NR_perf_event_open 364
+__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+#define __NR_recvmmsg 365
+__SYSCALL(__NR_recvmmsg, compat_sys_recvmmsg)
+#define __NR_accept4 366
+__SYSCALL(__NR_accept4, sys_accept4)
+#define __NR_fanotify_init 367
+__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
+#define __NR_fanotify_mark 368
+__SYSCALL(__NR_fanotify_mark, compat_sys_fanotify_mark)
+#define __NR_prlimit64 369
+__SYSCALL(__NR_prlimit64, sys_prlimit64)
+#define __NR_name_to_handle_at 370
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at 371
+__SYSCALL(__NR_open_by_handle_at, compat_sys_open_by_handle_at)
+#define __NR_clock_adjtime 372
+__SYSCALL(__NR_clock_adjtime, compat_sys_clock_adjtime)
+#define __NR_syncfs 373
+__SYSCALL(__NR_syncfs, sys_syncfs)
+#define __NR_sendmmsg 374
+__SYSCALL(__NR_sendmmsg, compat_sys_sendmmsg)
+#define __NR_setns 375
+__SYSCALL(__NR_setns, sys_setns)
+#define __NR_process_vm_readv 376
+__SYSCALL(__NR_process_vm_readv, compat_sys_process_vm_readv)
+#define __NR_process_vm_writev 377
+__SYSCALL(__NR_process_vm_writev, compat_sys_process_vm_writev)
+#define __NR_kcmp 378
+__SYSCALL(__NR_kcmp, sys_kcmp)
+#define __NR_finit_module 379
+__SYSCALL(__NR_finit_module, sys_finit_module)
+#define __NR_sched_setattr 380
+__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+#define __NR_sched_getattr 381
+__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+#define __NR_renameat2 382
+__SYSCALL(__NR_renameat2, sys_renameat2)
+			/* 383 for seccomp */
+#define __NR_getrandom 384
+__SYSCALL(__NR_getrandom, sys_getrandom)
+#define __NR_memfd_create 385
+__SYSCALL(__NR_memfd_create, sys_memfd_create)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,24 @@
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
+
+/*
+ * Compat syscall numbers used by the AArch64 kernel.
+ */
+#define __NR_compat_restart_syscall	0
+#define __NR_compat_sigreturn		119
+#define __NR_compat_rt_sigreturn	173
+
+/*
+ * The following SVCs are ARM private.
+ */
+#define __ARM_NR_COMPAT_BASE		0x0f0000
+#define __ARM_NR_compat_cacheflush	(__ARM_NR_COMPAT_BASE+2)
+#define __ARM_NR_compat_set_tls		(__ARM_NR_COMPAT_BASE+5)
+
+#define __NR_compat_syscalls		386
 #endif
+
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/include/asm/virt.h linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/virt.h
--- linux-libre-3.16-gnu/arch/arm64/include/asm/virt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/include/asm/virt.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,10 @@ static inline bool is_hyp_mode_mismatche
 	return __boot_cpu_mode[0] != __boot_cpu_mode[1];
 }
 
+/* The section containing the hypervisor text */
+extern char __hyp_text_start[];
+extern char __hyp_text_end[];
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* ! __ASM__VIRT_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/Kconfig linux-libre-3.17-rc7-gnu/arch/arm64/Kconfig
--- linux-libre-3.16-gnu/arch/arm64/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 config ARM64
 	def_bool y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
-	select ARCH_HAS_OPP
+	select ARCH_HAS_SG_CHAIN
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_SUPPORTS_ATOMIC_RMW
@@ -11,6 +11,8 @@ config ARM64
 	select ARM_AMBA
 	select ARM_ARCH_TIMER
 	select ARM_GIC
+	select AUDIT_ARCH_COMPAT_GENERIC
+	select ARM_GIC_V3
 	select BUILDTIME_EXTABLE_SORT
 	select CLONE_BACKWARDS
 	select COMMON_CLK
@@ -29,10 +31,12 @@ config ARM64
 	select GENERIC_STRNLEN_USER
 	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
+	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_C_RECORDMCOUNT
+	select HAVE_CC_STACKPROTECTOR
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -63,6 +67,7 @@ config ARM64
 	select RTC_LIB
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select HAVE_CONTEXT_TRACKING
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -155,14 +160,63 @@ endmenu
 
 menu "Kernel Features"
 
+choice
+	prompt "Page size"
+	default ARM64_4K_PAGES
+	help
+	  Page size (translation granule) configuration.
+
+config ARM64_4K_PAGES
+	bool "4KB"
+	help
+	  This feature enables 4KB pages support.
+
 config ARM64_64K_PAGES
-	bool "Enable 64KB pages support"
+	bool "64KB"
 	help
 	  This feature enables 64KB pages support (4KB by default)
 	  allowing only two levels of page tables and faster TLB
 	  look-up. AArch32 emulation is not available when this feature
 	  is enabled.
 
+endchoice
+
+choice
+	prompt "Virtual address space size"
+	default ARM64_VA_BITS_39 if ARM64_4K_PAGES
+	default ARM64_VA_BITS_42 if ARM64_64K_PAGES
+	help
+	  Allows choosing one of multiple possible virtual address
+	  space sizes. The level of translation table is determined by
+	  a combination of page size and virtual address space size.
+
+config ARM64_VA_BITS_39
+	bool "39-bit"
+	depends on ARM64_4K_PAGES
+
+config ARM64_VA_BITS_42
+	bool "42-bit"
+	depends on ARM64_64K_PAGES
+
+config ARM64_VA_BITS_48
+	bool "48-bit"
+	depends on BROKEN
+
+endchoice
+
+config ARM64_VA_BITS
+	int
+	default 39 if ARM64_VA_BITS_39
+	default 42 if ARM64_VA_BITS_42
+	default 48 if ARM64_VA_BITS_48
+
+config ARM64_PGTABLE_LEVELS
+	int
+	default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
+	default 3 if ARM64_64K_PAGES && ARM64_VA_BITS_48
+	default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
+	default 4 if ARM64_4K_PAGES && ARM64_VA_BITS_48
+
 config CPU_BIG_ENDIAN
        bool "Build big-endian kernel"
        help
@@ -294,12 +348,18 @@ config CMDLINE_FORCE
 	  This is useful if you cannot or don't want to change the
 	  command-line options your boot loader passes to the kernel.
 
+config EFI_STUB
+	bool
+
 config EFI
 	bool "UEFI runtime support"
 	depends on OF && !CPU_BIG_ENDIAN
 	select LIBFDT
 	select UCS2_STRING
 	select EFI_PARAMS_FROM_FDT
+	select EFI_RUNTIME_WRAPPERS
+	select EFI_STUB
+	select EFI_ARMSTUB
 	default y
 	help
 	  This option provides support for runtime services provided
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/Kconfig.debug linux-libre-3.17-rc7-gnu/arch/arm64/Kconfig.debug
--- linux-libre-3.16-gnu/arch/arm64/Kconfig.debug	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/Kconfig.debug	2014-09-28 17:29:07.000000000 -0400
@@ -28,4 +28,19 @@ config PID_IN_CONTEXTIDR
 	  instructions during context switch. Say Y here only if you are
 	  planning to use hardware trace tools with this kernel.
 
+config ARM64_RANDOMIZE_TEXT_OFFSET
+	bool "Randomize TEXT_OFFSET at build time"
+	help
+	  Say Y here if you want the image load offset (AKA TEXT_OFFSET)
+	  of the kernel to be randomized at build-time. When selected,
+	  this option will cause TEXT_OFFSET to be randomized upon any
+	  build of the kernel, and the offset will be reflected in the
+	  text_offset field of the resulting Image. This can be used to
+	  fuzz-test bootloaders which respect text_offset.
+
+	  This option is intended for bootloader and/or kernel testing
+	  only. Bootloaders must make no assumptions regarding the value
+	  of TEXT_OFFSET and platforms must not require a specific
+	  value.
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/asm-offsets.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/asm-offsets.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/asm-offsets.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/asm-offsets.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,6 +120,7 @@ int main(void)
   DEFINE(VCPU_ESR_EL2,		offsetof(struct kvm_vcpu, arch.fault.esr_el2));
   DEFINE(VCPU_FAR_EL2,		offsetof(struct kvm_vcpu, arch.fault.far_el2));
   DEFINE(VCPU_HPFAR_EL2,	offsetof(struct kvm_vcpu, arch.fault.hpfar_el2));
+  DEFINE(VCPU_DEBUG_FLAGS,	offsetof(struct kvm_vcpu, arch.debug_flags));
   DEFINE(VCPU_HCR_EL2,		offsetof(struct kvm_vcpu, arch.hcr_el2));
   DEFINE(VCPU_IRQ_LINES,	offsetof(struct kvm_vcpu, arch.irq_lines));
   DEFINE(VCPU_HOST_CONTEXT,	offsetof(struct kvm_vcpu, arch.host_cpu_context));
@@ -129,13 +130,24 @@ int main(void)
   DEFINE(KVM_TIMER_ENABLED,	offsetof(struct kvm, arch.timer.enabled));
   DEFINE(VCPU_KVM,		offsetof(struct kvm_vcpu, kvm));
   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
-  DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
-  DEFINE(VGIC_CPU_VMCR,		offsetof(struct vgic_cpu, vgic_vmcr));
-  DEFINE(VGIC_CPU_MISR,		offsetof(struct vgic_cpu, vgic_misr));
-  DEFINE(VGIC_CPU_EISR,		offsetof(struct vgic_cpu, vgic_eisr));
-  DEFINE(VGIC_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_elrsr));
-  DEFINE(VGIC_CPU_APR,		offsetof(struct vgic_cpu, vgic_apr));
-  DEFINE(VGIC_CPU_LR,		offsetof(struct vgic_cpu, vgic_lr));
+  DEFINE(VGIC_SAVE_FN,		offsetof(struct vgic_sr_vectors, save_vgic));
+  DEFINE(VGIC_RESTORE_FN,	offsetof(struct vgic_sr_vectors, restore_vgic));
+  DEFINE(VGIC_SR_VECTOR_SZ,	sizeof(struct vgic_sr_vectors));
+  DEFINE(VGIC_V2_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
+  DEFINE(VGIC_V2_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
+  DEFINE(VGIC_V2_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
+  DEFINE(VGIC_V2_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
+  DEFINE(VGIC_V2_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
+  DEFINE(VGIC_V2_CPU_APR,	offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
+  DEFINE(VGIC_V2_CPU_LR,	offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
+  DEFINE(VGIC_V3_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v3.vgic_hcr));
+  DEFINE(VGIC_V3_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr));
+  DEFINE(VGIC_V3_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v3.vgic_misr));
+  DEFINE(VGIC_V3_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v3.vgic_eisr));
+  DEFINE(VGIC_V3_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v3.vgic_elrsr));
+  DEFINE(VGIC_V3_CPU_AP0R,	offsetof(struct vgic_cpu, vgic_v3.vgic_ap0r));
+  DEFINE(VGIC_V3_CPU_AP1R,	offsetof(struct vgic_cpu, vgic_v3.vgic_ap1r));
+  DEFINE(VGIC_V3_CPU_LR,	offsetof(struct vgic_cpu, vgic_v3.vgic_lr));
   DEFINE(VGIC_CPU_NR_LR,	offsetof(struct vgic_cpu, nr_lr));
   DEFINE(KVM_VTTBR,		offsetof(struct kvm, arch.vttbr));
   DEFINE(KVM_VGIC_VCTRL,	offsetof(struct kvm, arch.vgic.vctrl_base));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/cpuinfo.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/cpuinfo.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/cpuinfo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/cpuinfo.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,192 @@
+/*
+ * Record and handle CPU attributes.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <asm/arch_timer.h>
+#include <asm/cachetype.h>
+#include <asm/cpu.h>
+#include <asm/cputype.h>
+
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/smp.h>
+
+/*
+ * In case the boot CPU is hotpluggable, we record its initial state and
+ * current state separately. Certain system registers may contain different
+ * values depending on configuration at or after reset.
+ */
+DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
+static struct cpuinfo_arm64 boot_cpu_data;
+
+static char *icache_policy_str[] = {
+	[ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
+	[ICACHE_POLICY_AIVIVT] = "AIVIVT",
+	[ICACHE_POLICY_VIPT] = "VIPT",
+	[ICACHE_POLICY_PIPT] = "PIPT",
+};
+
+unsigned long __icache_flags;
+
+static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
+{
+	unsigned int cpu = smp_processor_id();
+	u32 l1ip = CTR_L1IP(info->reg_ctr);
+
+	if (l1ip != ICACHE_POLICY_PIPT)
+		set_bit(ICACHEF_ALIASING, &__icache_flags);
+	if (l1ip == ICACHE_POLICY_AIVIVT)
+		set_bit(ICACHEF_AIVIVT, &__icache_flags);
+
+	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
+}
+
+static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu)
+{
+	if ((boot & mask) == (cur & mask))
+		return 0;
+
+	pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016lx, CPU%d: %#016lx\n",
+		name, (unsigned long)boot, cpu, (unsigned long)cur);
+
+	return 1;
+}
+
+#define CHECK_MASK(field, mask, boot, cur, cpu) \
+	check_reg_mask(#field, mask, (boot)->reg_ ## field, (cur)->reg_ ## field, cpu)
+
+#define CHECK(field, boot, cur, cpu) \
+	CHECK_MASK(field, ~0ULL, boot, cur, cpu)
+
+/*
+ * Verify that CPUs don't have unexpected differences that will cause problems.
+ */
+static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
+{
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo_arm64 *boot = &boot_cpu_data;
+	unsigned int diff = 0;
+
+	/*
+	 * The kernel can handle differing I-cache policies, but otherwise
+	 * caches should look identical. Userspace JITs will make use of
+	 * *minLine.
+	 */
+	diff |= CHECK_MASK(ctr, 0xffff3fff, boot, cur, cpu);
+
+	/*
+	 * Userspace may perform DC ZVA instructions. Mismatched block sizes
+	 * could result in too much or too little memory being zeroed if a
+	 * process is preempted and migrated between CPUs.
+	 */
+	diff |= CHECK(dczid, boot, cur, cpu);
+
+	/* If different, timekeeping will be broken (especially with KVM) */
+	diff |= CHECK(cntfrq, boot, cur, cpu);
+
+	/*
+	 * Even in big.LITTLE, processors should be identical instruction-set
+	 * wise.
+	 */
+	diff |= CHECK(id_aa64isar0, boot, cur, cpu);
+	diff |= CHECK(id_aa64isar1, boot, cur, cpu);
+
+	/*
+	 * Differing PARange support is fine as long as all peripherals and
+	 * memory are mapped within the minimum PARange of all CPUs.
+	 * Linux should not care about secure memory.
+	 * ID_AA64MMFR1 is currently RES0.
+	 */
+	diff |= CHECK_MASK(id_aa64mmfr0, 0xffffffffffff0ff0, boot, cur, cpu);
+	diff |= CHECK(id_aa64mmfr1, boot, cur, cpu);
+
+	/*
+	 * EL3 is not our concern.
+	 * ID_AA64PFR1 is currently RES0.
+	 */
+	diff |= CHECK_MASK(id_aa64pfr0, 0xffffffffffff0fff, boot, cur, cpu);
+	diff |= CHECK(id_aa64pfr1, boot, cur, cpu);
+
+	/*
+	 * If we have AArch32, we care about 32-bit features for compat. These
+	 * registers should be RES0 otherwise.
+	 */
+	diff |= CHECK(id_isar0, boot, cur, cpu);
+	diff |= CHECK(id_isar1, boot, cur, cpu);
+	diff |= CHECK(id_isar2, boot, cur, cpu);
+	diff |= CHECK(id_isar3, boot, cur, cpu);
+	diff |= CHECK(id_isar4, boot, cur, cpu);
+	diff |= CHECK(id_isar5, boot, cur, cpu);
+	diff |= CHECK(id_mmfr0, boot, cur, cpu);
+	diff |= CHECK(id_mmfr1, boot, cur, cpu);
+	diff |= CHECK(id_mmfr2, boot, cur, cpu);
+	diff |= CHECK(id_mmfr3, boot, cur, cpu);
+	diff |= CHECK(id_pfr0, boot, cur, cpu);
+	diff |= CHECK(id_pfr1, boot, cur, cpu);
+
+	/*
+	 * Mismatched CPU features are a recipe for disaster. Don't even
+	 * pretend to support them.
+	 */
+	WARN_TAINT_ONCE(diff, TAINT_CPU_OUT_OF_SPEC,
+			"Unsupported CPU feature variation.");
+}
+
+static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
+{
+	info->reg_cntfrq = arch_timer_get_cntfrq();
+	info->reg_ctr = read_cpuid_cachetype();
+	info->reg_dczid = read_cpuid(DCZID_EL0);
+	info->reg_midr = read_cpuid_id();
+
+	info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
+	info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
+	info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
+	info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
+	info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
+	info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
+
+	info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
+	info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
+	info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
+	info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
+	info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
+	info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
+	info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
+	info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
+	info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
+	info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
+	info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
+	info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
+
+	cpuinfo_detect_icache_policy(info);
+}
+
+void cpuinfo_store_cpu(void)
+{
+	struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
+	__cpuinfo_store_cpu(info);
+	cpuinfo_sanity_check(info);
+}
+
+void __init cpuinfo_store_boot_cpu(void)
+{
+	struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
+	__cpuinfo_store_cpu(info);
+
+	boot_cpu_data = *info;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/cpu_ops.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/cpu_ops.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/cpu_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/cpu_ops.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,8 +30,8 @@ const struct cpu_operations *cpu_ops[NR_
 static const struct cpu_operations *supported_cpu_ops[] __initconst = {
 #ifdef CONFIG_SMP
 	&smp_spin_table_ops,
-	&cpu_psci_ops,
 #endif
+	&cpu_psci_ops,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/debug-monitors.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/debug-monitors.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/debug-monitors.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/debug-monitors.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,15 +30,6 @@
 #include <asm/cputype.h>
 #include <asm/system_misc.h>
 
-/* Low-level stepping controls. */
-#define DBG_MDSCR_SS		(1 << 0)
-#define DBG_SPSR_SS		(1 << 21)
-
-/* MDSCR_EL1 enabling bits */
-#define DBG_MDSCR_KDE		(1 << 13)
-#define DBG_MDSCR_MDE		(1 << 15)
-#define DBG_MDSCR_MASK		~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
-
 /* Determine debug architecture. */
 u8 debug_monitors_arch(void)
 {
@@ -315,20 +306,20 @@ static int brk_handler(unsigned long add
 {
 	siginfo_t info;
 
-	if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
-		return 0;
+	if (user_mode(regs)) {
+		info = (siginfo_t) {
+			.si_signo = SIGTRAP,
+			.si_errno = 0,
+			.si_code  = TRAP_BRKPT,
+			.si_addr  = (void __user *)instruction_pointer(regs),
+		};
 
-	if (!user_mode(regs))
+		force_sig_info(SIGTRAP, &info, current);
+	} else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
+		pr_warning("Unexpected kernel BRK exception at EL1\n");
 		return -EFAULT;
+	}
 
-	info = (siginfo_t) {
-		.si_signo = SIGTRAP,
-		.si_errno = 0,
-		.si_code  = TRAP_BRKPT,
-		.si_addr  = (void __user *)instruction_pointer(regs),
-	};
-
-	force_sig_info(SIGTRAP, &info, current);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/efi.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/efi.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/efi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -188,6 +188,8 @@ static __init void reserve_regions(void)
 		if (uefi_debug)
 			pr_cont("\n");
 	}
+
+	set_bit(EFI_MEMMAP, &efi.flags);
 }
 
 
@@ -414,13 +416,24 @@ static int __init arm64_enter_virtual_mo
 	for_each_efi_memory_desc(&memmap, md) {
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
-		if (remap_region(md, &virt_md))
-			++count;
+		if (!remap_region(md, &virt_md))
+			goto err_unmap;
+		++count;
 	}
 
 	efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
-	if (efi.systab)
-		set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+	if (!efi.systab) {
+		/*
+		 * If we have no virtual mapping for the System Table at this
+		 * point, the memory map doesn't cover the physical offset where
+		 * it resides. This means the System Table will be inaccessible
+		 * to Runtime Services themselves once the virtual mapping is
+		 * installed.
+		 */
+		pr_err("Failed to remap EFI System Table -- buggy firmware?\n");
+		goto err_unmap;
+	}
+	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
 
 	local_irq_save(flags);
 	cpu_switch_mm(idmap_pg_dir, &init_mm);
@@ -449,21 +462,20 @@ static int __init arm64_enter_virtual_mo
 
 	/* Set up runtime services function pointers */
 	runtime = efi.systab->runtime;
-	efi.get_time = runtime->get_time;
-	efi.set_time = runtime->set_time;
-	efi.get_wakeup_time = runtime->get_wakeup_time;
-	efi.set_wakeup_time = runtime->set_wakeup_time;
-	efi.get_variable = runtime->get_variable;
-	efi.get_next_variable = runtime->get_next_variable;
-	efi.set_variable = runtime->set_variable;
-	efi.query_variable_info = runtime->query_variable_info;
-	efi.update_capsule = runtime->update_capsule;
-	efi.query_capsule_caps = runtime->query_capsule_caps;
-	efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
-	efi.reset_system = runtime->reset_system;
-
+	efi_native_runtime_setup();
 	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 
+	efi.runtime_version = efi.systab->hdr.revision;
+
 	return 0;
+
+err_unmap:
+	/* unmap all mappings that succeeded: there are 'count' of those */
+	for (virt_md = virtmap; count--; virt_md += memmap.desc_size) {
+		md = virt_md;
+		iounmap((__force void __iomem *)md->virt_addr);
+	}
+	kfree(virtmap);
+	return -1;
 }
 early_initcall(arm64_enter_virtual_mode);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/efi-stub.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/efi-stub.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/efi-stub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/efi-stub.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,46 +10,16 @@
  *
  */
 #include <linux/efi.h>
-#include <linux/libfdt.h>
+#include <asm/efi.h>
 #include <asm/sections.h>
 
-/*
- * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
- * start of kernel and may not cross a 2MiB boundary. We set alignment to
- * 2MiB so we know it won't cross a 2MiB boundary.
- */
-#define EFI_FDT_ALIGN	SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET	SZ_512M
-
-#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
-
-static void efi_char16_printk(efi_system_table_t *sys_table_arg,
-			      efi_char16_t *str);
-
-static efi_status_t efi_open_volume(efi_system_table_t *sys_table,
-				    void *__image, void **__fh);
-static efi_status_t efi_file_close(void *handle);
-
-static efi_status_t
-efi_file_read(void *handle, unsigned long *size, void *addr);
-
-static efi_status_t
-efi_file_size(efi_system_table_t *sys_table, void *__fh,
-	      efi_char16_t *filename_16, void **handle, u64 *file_sz);
-
-/* Include shared EFI stub code */
-#include "../../../drivers/firmware/efi/efi-stub-helper.c"
-#include "../../../drivers/firmware/efi/fdt.c"
-#include "../../../drivers/firmware/efi/arm-stub.c"
-
-
-static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
-					unsigned long *image_addr,
-					unsigned long *image_size,
-					unsigned long *reserve_addr,
-					unsigned long *reserve_size,
-					unsigned long dram_base,
-					efi_loaded_image_t *image)
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+				 unsigned long *image_addr,
+				 unsigned long *image_size,
+				 unsigned long *reserve_addr,
+				 unsigned long *reserve_size,
+				 unsigned long dram_base,
+				 efi_loaded_image_t *image)
 {
 	efi_status_t status;
 	unsigned long kernel_size, kernel_memsize = 0;
@@ -69,7 +39,7 @@ static efi_status_t handle_kernel_image(
 		if (*image_addr != (dram_base + TEXT_OFFSET)) {
 			pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
 			efi_free(sys_table, kernel_memsize, *image_addr);
-			return EFI_ERROR;
+			return EFI_LOAD_ERROR;
 		}
 		*image_size = kernel_memsize;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/entry-fpsimd.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry-fpsimd.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/entry-fpsimd.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry-fpsimd.S	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ ENDPROC(fpsimd_load_state)
 ENTRY(fpsimd_save_partial_state)
 	fpsimd_save_partial x0, 1, 8, 9
 	ret
-ENDPROC(fpsimd_load_partial_state)
+ENDPROC(fpsimd_save_partial_state)
 
 /*
  * Load the bottom n FP registers.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/entry-ftrace.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry-ftrace.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/entry-ftrace.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry-ftrace.S	2014-09-28 17:29:07.000000000 -0400
@@ -96,11 +96,6 @@
  *     - ftrace_graph_caller to set up an exit hook
  */
 ENTRY(_mcount)
-#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-	ldr	x0, =ftrace_trace_stop
-	ldr	x0, [x0]		// if ftrace_trace_stop
-	ret				//   return;
-#endif
 	mcount_enter
 
 	ldr	x0, =ftrace_trace_function
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/entry.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,32 @@
 #include <asm/esr.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
-#include <asm/unistd32.h>
+
+/*
+ * Context tracking subsystem.  Used to instrument transitions
+ * between user and kernel mode.
+ */
+	.macro ct_user_exit, syscall = 0
+#ifdef CONFIG_CONTEXT_TRACKING
+	bl	context_tracking_user_exit
+	.if \syscall == 1
+	/*
+	 * Save/restore needed during syscalls.  Restore syscall arguments from
+	 * the values already saved on stack during kernel_entry.
+	 */
+	ldp	x0, x1, [sp]
+	ldp	x2, x3, [sp, #S_X2]
+	ldp	x4, x5, [sp, #S_X4]
+	ldp	x6, x7, [sp, #S_X6]
+	.endif
+#endif
+	.endm
+
+	.macro ct_user_enter
+#ifdef CONFIG_CONTEXT_TRACKING
+	bl	context_tracking_user_enter
+#endif
+	.endm
 
 /*
  * Bad Abort numbers
@@ -91,6 +116,7 @@
 	.macro	kernel_exit, el, ret = 0
 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
 	.if	\el == 0
+	ct_user_enter
 	ldr	x23, [sp, #S_SP]		// load return stack pointer
 	.endif
 	.if	\ret
@@ -353,7 +379,6 @@ el0_sync:
 	lsr	x24, x25, #ESR_EL1_EC_SHIFT	// exception class
 	cmp	x24, #ESR_EL1_EC_SVC64		// SVC in 64-bit state
 	b.eq	el0_svc
-	adr	lr, ret_to_user
 	cmp	x24, #ESR_EL1_EC_DABT_EL0	// data abort in EL0
 	b.eq	el0_da
 	cmp	x24, #ESR_EL1_EC_IABT_EL0	// instruction abort in EL0
@@ -382,7 +407,6 @@ el0_sync_compat:
 	lsr	x24, x25, #ESR_EL1_EC_SHIFT	// exception class
 	cmp	x24, #ESR_EL1_EC_SVC32		// SVC in 32-bit state
 	b.eq	el0_svc_compat
-	adr	lr, ret_to_user
 	cmp	x24, #ESR_EL1_EC_DABT_EL0	// data abort in EL0
 	b.eq	el0_da
 	cmp	x24, #ESR_EL1_EC_IABT_EL0	// instruction abort in EL0
@@ -425,48 +449,59 @@ el0_da:
 	/*
 	 * Data abort handling
 	 */
-	mrs	x0, far_el1
-	bic	x0, x0, #(0xff << 56)
+	mrs	x26, far_el1
 	// enable interrupts before calling the main handler
 	enable_dbg_and_irq
+	ct_user_exit
+	bic	x0, x26, #(0xff << 56)
 	mov	x1, x25
 	mov	x2, sp
+	adr	lr, ret_to_user
 	b	do_mem_abort
 el0_ia:
 	/*
 	 * Instruction abort handling
 	 */
-	mrs	x0, far_el1
+	mrs	x26, far_el1
 	// enable interrupts before calling the main handler
 	enable_dbg_and_irq
+	ct_user_exit
+	mov	x0, x26
 	orr	x1, x25, #1 << 24		// use reserved ISS bit for instruction aborts
 	mov	x2, sp
+	adr	lr, ret_to_user
 	b	do_mem_abort
 el0_fpsimd_acc:
 	/*
 	 * Floating Point or Advanced SIMD access
 	 */
 	enable_dbg
+	ct_user_exit
 	mov	x0, x25
 	mov	x1, sp
+	adr	lr, ret_to_user
 	b	do_fpsimd_acc
 el0_fpsimd_exc:
 	/*
 	 * Floating Point or Advanced SIMD exception
 	 */
 	enable_dbg
+	ct_user_exit
 	mov	x0, x25
 	mov	x1, sp
+	adr	lr, ret_to_user
 	b	do_fpsimd_exc
 el0_sp_pc:
 	/*
 	 * Stack or PC alignment exception handling
 	 */
-	mrs	x0, far_el1
+	mrs	x26, far_el1
 	// enable interrupts before calling the main handler
 	enable_dbg_and_irq
+	mov	x0, x26
 	mov	x1, x25
 	mov	x2, sp
+	adr	lr, ret_to_user
 	b	do_sp_pc_abort
 el0_undef:
 	/*
@@ -474,7 +509,9 @@ el0_undef:
 	 */
 	// enable interrupts before calling the main handler
 	enable_dbg_and_irq
+	ct_user_exit
 	mov	x0, sp
+	adr	lr, ret_to_user
 	b	do_undefinstr
 el0_dbg:
 	/*
@@ -486,12 +523,15 @@ el0_dbg:
 	mov	x2, sp
 	bl	do_debug_exception
 	enable_dbg
+	ct_user_exit
 	b	ret_to_user
 el0_inv:
 	enable_dbg
+	ct_user_exit
 	mov	x0, sp
 	mov	x1, #BAD_SYNC
 	mrs	x2, esr_el1
+	adr	lr, ret_to_user
 	b	bad_mode
 ENDPROC(el0_sync)
 
@@ -504,6 +544,7 @@ el0_irq_naked:
 	bl	trace_hardirqs_off
 #endif
 
+	ct_user_exit
 	irq_handler
 
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -608,6 +649,7 @@ el0_svc:
 el0_svc_naked:					// compat entry point
 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
+	ct_user_exit 1
 
 	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
 	tst	x16, #_TIF_SYSCALL_WORK
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/fpsimd.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/fpsimd.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/fpsimd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/fpsimd.c	2014-09-28 17:29:07.000000000 -0400
@@ -270,6 +270,7 @@ static int fpsimd_cpu_pm_notifier(struct
 	case CPU_PM_ENTER:
 		if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE))
 			fpsimd_save_state(&current->thread.fpsimd_state);
+		this_cpu_write(fpsimd_last_state, NULL);
 		break;
 	case CPU_PM_EXIT:
 		if (current->mm)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/head.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/head.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/head.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/head.S	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
 #include <asm/ptrace.h>
@@ -35,37 +36,31 @@
 #include <asm/page.h>
 #include <asm/virt.h>
 
-/*
- * swapper_pg_dir is the virtual address of the initial page table. We place
- * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has
- * 2 pages and is placed below swapper_pg_dir.
- */
 #define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 
-#if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000
-#error KERNEL_RAM_VADDR must start at 0xXXX80000
+#if (TEXT_OFFSET & 0xfff) != 0
+#error TEXT_OFFSET must be at least 4KB aligned
+#elif (PAGE_OFFSET & 0x1fffff) != 0
+#error PAGE_OFFSET must be at least 2MB aligned
+#elif TEXT_OFFSET > 0x1fffff
+#error TEXT_OFFSET must be less than 2MB
 #endif
 
-#define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
-#define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
-
-	.globl	swapper_pg_dir
-	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE
-
-	.globl	idmap_pg_dir
-	.equ	idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE
-
-	.macro	pgtbl, ttb0, ttb1, phys
-	add	\ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE
-	sub	\ttb0, \ttb1, #IDMAP_DIR_SIZE
+	.macro	pgtbl, ttb0, ttb1, virt_to_phys
+	ldr	\ttb1, =swapper_pg_dir
+	ldr	\ttb0, =idmap_pg_dir
+	add	\ttb1, \ttb1, \virt_to_phys
+	add	\ttb0, \ttb0, \virt_to_phys
 	.endm
 
 #ifdef CONFIG_ARM64_64K_PAGES
 #define BLOCK_SHIFT	PAGE_SHIFT
 #define BLOCK_SIZE	PAGE_SIZE
+#define TABLE_SHIFT	PMD_SHIFT
 #else
 #define BLOCK_SHIFT	SECTION_SHIFT
 #define BLOCK_SIZE	SECTION_SIZE
+#define TABLE_SHIFT	PUD_SHIFT
 #endif
 
 #define KERNEL_START	KERNEL_RAM_VADDR
@@ -120,9 +115,9 @@ efi_head:
 	b	stext				// branch to kernel start, magic
 	.long	0				// reserved
 #endif
-	.quad	TEXT_OFFSET			// Image load offset from start of RAM
-	.quad	0				// reserved
-	.quad	0				// reserved
+	.quad	_kernel_offset_le		// Image load offset from start of RAM, little-endian
+	.quad	_kernel_size_le			// Effective size of kernel image, little-endian
+	.quad	_kernel_flags_le		// Informative flags, little-endian
 	.quad	0				// reserved
 	.quad	0				// reserved
 	.quad	0				// reserved
@@ -295,6 +290,23 @@ CPU_LE(	bic	x0, x0, #(3 << 24)	)	// Clea
 	msr	cnthctl_el2, x0
 	msr	cntvoff_el2, xzr		// Clear virtual offset
 
+#ifdef CONFIG_ARM_GIC_V3
+	/* GICv3 system register access */
+	mrs	x0, id_aa64pfr0_el1
+	ubfx	x0, x0, #24, #4
+	cmp	x0, #1
+	b.ne	3f
+
+	mrs_s	x0, ICC_SRE_EL2
+	orr	x0, x0, #ICC_SRE_EL2_SRE	// Set ICC_SRE_EL2.SRE==1
+	orr	x0, x0, #ICC_SRE_EL2_ENABLE	// Set ICC_SRE_EL2.Enable==1
+	msr_s	ICC_SRE_EL2, x0
+	isb					// Make sure SRE is now set
+	msr_s	ICH_HCR_EL2, xzr		// Reset ICC_HCR_EL2 to defaults
+
+3:
+#endif
+
 	/* Populate ID registers. */
 	mrs	x0, midr_el1
 	mrs	x1, mpidr_el1
@@ -361,10 +373,6 @@ ENTRY(__boot_cpu_mode)
 	.long	0
 	.popsection
 
-	.align	3
-2:	.quad	.
-	.quad	PAGE_OFFSET
-
 #ifdef CONFIG_SMP
 	.align	3
 1:	.quad	.
@@ -413,7 +421,7 @@ ENTRY(secondary_startup)
 	mov	x23, x0				// x23=current cpu_table
 	cbz	x23, __error_p			// invalid processor (x23=0)?
 
-	pgtbl	x25, x26, x24			// x25=TTBR0, x26=TTBR1
+	pgtbl	x25, x26, x28			// x25=TTBR0, x26=TTBR1
 	ldr	x12, [x23, #CPU_INFO_SETUP]
 	add	x12, x12, x28			// __virt_to_phys
 	blr	x12				// initialise processor
@@ -455,8 +463,13 @@ ENDPROC(__enable_mmu)
  *  x27 = *virtual* address to jump to upon completion
  *
  * other registers depend on the function called upon completion
+ *
+ * We align the entire function to the smallest power of two larger than it to
+ * ensure it fits within a single block map entry. Otherwise were PHYS_OFFSET
+ * close to the end of a 512MB or 1GB block we might require an additional
+ * table to map the entire function.
  */
-	.align	6
+	.align	4
 __turn_mmu_on:
 	msr	sctlr_el1, x0
 	isb
@@ -479,17 +492,38 @@ ENDPROC(__calc_phys_offset)
 	.quad	PAGE_OFFSET
 
 /*
- * Macro to populate the PGD for the corresponding block entry in the next
- * level (tbl) for the given virtual address.
+ * Macro to create a table entry to the next page.
  *
- * Preserves:	pgd, tbl, virt
+ *	tbl:	page table address
+ *	virt:	virtual address
+ *	shift:	#imm page table shift
+ *	ptrs:	#imm pointers per table page
+ *
+ * Preserves:	virt
  * Corrupts:	tmp1, tmp2
+ * Returns:	tbl -> next level table page address
  */
-	.macro	create_pgd_entry, pgd, tbl, virt, tmp1, tmp2
-	lsr	\tmp1, \virt, #PGDIR_SHIFT
-	and	\tmp1, \tmp1, #PTRS_PER_PGD - 1	// PGD index
-	orr	\tmp2, \tbl, #3			// PGD entry table type
-	str	\tmp2, [\pgd, \tmp1, lsl #3]
+	.macro	create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
+	lsr	\tmp1, \virt, #\shift
+	and	\tmp1, \tmp1, #\ptrs - 1	// table index
+	add	\tmp2, \tbl, #PAGE_SIZE
+	orr	\tmp2, \tmp2, #PMD_TYPE_TABLE	// address of next table and entry type
+	str	\tmp2, [\tbl, \tmp1, lsl #3]
+	add	\tbl, \tbl, #PAGE_SIZE		// next level table page
+	.endm
+
+/*
+ * Macro to populate the PGD (and possibily PUD) for the corresponding
+ * block entry in the next level (tbl) for the given virtual address.
+ *
+ * Preserves:	tbl, next, virt
+ * Corrupts:	tmp1, tmp2
+ */
+	.macro	create_pgd_entry, tbl, virt, tmp1, tmp2
+	create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
+#if SWAPPER_PGTABLE_LEVELS == 3
+	create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2
+#endif
 	.endm
 
 /*
@@ -522,7 +556,7 @@ ENDPROC(__calc_phys_offset)
  *   - pgd entry for fixed mappings (TTBR1)
  */
 __create_page_tables:
-	pgtbl	x25, x26, x24			// idmap_pg_dir and swapper_pg_dir addresses
+	pgtbl	x25, x26, x28			// idmap_pg_dir and swapper_pg_dir addresses
 	mov	x27, lr
 
 	/*
@@ -550,10 +584,10 @@ __create_page_tables:
 	/*
 	 * Create the identity mapping.
 	 */
-	add	x0, x25, #PAGE_SIZE		// section table address
+	mov	x0, x25				// idmap_pg_dir
 	ldr	x3, =KERNEL_START
 	add	x3, x3, x28			// __pa(KERNEL_START)
-	create_pgd_entry x25, x0, x3, x5, x6
+	create_pgd_entry x0, x3, x5, x6
 	ldr	x6, =KERNEL_END
 	mov	x5, x3				// __pa(KERNEL_START)
 	add	x6, x6, x28			// __pa(KERNEL_END)
@@ -562,9 +596,9 @@ __create_page_tables:
 	/*
 	 * Map the kernel image (starting with PHYS_OFFSET).
 	 */
-	add	x0, x26, #PAGE_SIZE		// section table address
+	mov	x0, x26				// swapper_pg_dir
 	mov	x5, #PAGE_OFFSET
-	create_pgd_entry x26, x0, x5, x3, x6
+	create_pgd_entry x0, x5, x3, x6
 	ldr	x6, =KERNEL_END
 	mov	x3, x24				// phys offset
 	create_block_map x0, x7, x3, x5, x6
@@ -586,13 +620,6 @@ __create_page_tables:
 	create_block_map x0, x7, x3, x5, x6
 1:
 	/*
-	 * Create the pgd entry for the fixed mappings.
-	 */
-	ldr	x5, =FIXADDR_TOP		// Fixed mapping virtual address
-	add	x0, x26, #2 * PAGE_SIZE		// section table address
-	create_pgd_entry x26, x0, x5, x6, x7
-
-	/*
 	 * Since the page tables have been populated with non-cacheable
 	 * accesses (MMU disabled), invalidate the idmap and swapper page
 	 * tables again to remove any speculatively loaded cache lines.
@@ -611,7 +638,7 @@ ENDPROC(__create_page_tables)
 __switch_data:
 	.quad	__mmap_switched
 	.quad	__bss_start			// x6
-	.quad	_end				// x7
+	.quad	__bss_stop			// x7
 	.quad	processor_id			// x4
 	.quad	__fdt_pointer			// x5
 	.quad	memstart_addr			// x6
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/hyp-stub.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/hyp-stub.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/hyp-stub.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/hyp-stub.S	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
 #include <asm/ptrace.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/image.h linux-libre-3.17-rc7-gnu/arch/arm64/kernel/image.h
--- linux-libre-3.16-gnu/arch/arm64/kernel/image.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/image.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Linker script macros to generate Image header fields.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IMAGE_H
+#define __ASM_IMAGE_H
+
+#ifndef LINKER_SCRIPT
+#error This file should only be included in vmlinux.lds.S
+#endif
+
+/*
+ * There aren't any ELF relocations we can use to endian-swap values known only
+ * at link time (e.g. the subtraction of two symbol addresses), so we must get
+ * the linker to endian-swap certain values before emitting them.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define DATA_LE64(data)					\
+	((((data) & 0x00000000000000ff) << 56) |	\
+	 (((data) & 0x000000000000ff00) << 40) |	\
+	 (((data) & 0x0000000000ff0000) << 24) |	\
+	 (((data) & 0x00000000ff000000) << 8)  |	\
+	 (((data) & 0x000000ff00000000) >> 8)  |	\
+	 (((data) & 0x0000ff0000000000) >> 24) |	\
+	 (((data) & 0x00ff000000000000) >> 40) |	\
+	 (((data) & 0xff00000000000000) >> 56))
+#else
+#define DATA_LE64(data) ((data) & 0xffffffffffffffff)
+#endif
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define __HEAD_FLAG_BE	1
+#else
+#define __HEAD_FLAG_BE	0
+#endif
+
+#define __HEAD_FLAGS	(__HEAD_FLAG_BE << 0)
+
+/*
+ * These will output as part of the Image header, which should be little-endian
+ * regardless of the endianness of the kernel. While constant values could be
+ * endian swapped in head.S, all are done here for consistency.
+ */
+#define HEAD_SYMBOLS						\
+	_kernel_size_le		= DATA_LE64(_end - _text);	\
+	_kernel_offset_le	= DATA_LE64(TEXT_OFFSET);	\
+	_kernel_flags_le	= DATA_LE64(__HEAD_FLAGS);
+
+#endif /* __ASM_IMAGE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/irq.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,19 +97,15 @@ static bool migrate_one_irq(struct irq_d
 	if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
 		return false;
 
-	if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids)
+	if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+		affinity = cpu_online_mask;
 		ret = true;
+	}
 
-	/*
-	 * when using forced irq_set_affinity we must ensure that the cpu
-	 * being offlined is not present in the affinity mask, it may be
-	 * selected as the target CPU otherwise
-	 */
-	affinity = cpu_online_mask;
 	c = irq_data_get_irq_chip(d);
 	if (!c->irq_set_affinity)
 		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
-	else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+	else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
 		cpumask_copy(d->affinity, affinity);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/kuser32.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/kuser32.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/kuser32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/kuser32.S	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
  * See Documentation/arm/kernel_user_helpers.txt for formal definitions.
  */
 
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
 
 	.align	5
 	.globl	__kuser_helper_start
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/Makefile linux-libre-3.17-rc7-gnu/arch/arm64/kernel/Makefile
--- linux-libre-3.16-gnu/arch/arm64/kernel/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,8 +4,7 @@
 
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
-CFLAGS_efi-stub.o 	:= -DTEXT_OFFSET=$(TEXT_OFFSET) \
-			   -I$(src)/../../../scripts/dtc/libfdt
+CFLAGS_efi-stub.o 	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
@@ -15,7 +14,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o	\
+			   cpuinfo.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/perf_regs.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/perf_regs.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/perf_regs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/perf_regs.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,12 @@ u64 perf_reg_value(struct pt_regs *regs,
 			return regs->compat_lr;
 	}
 
+	if ((u32)idx == PERF_REG_ARM64_SP)
+		return regs->sp;
+
+	if ((u32)idx == PERF_REG_ARM64_PC)
+		return regs->pc;
+
 	return regs->regs[idx];
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/process.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/process.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,12 @@
 #include <asm/processor.h>
 #include <asm/stacktrace.h>
 
+#ifdef CONFIG_CC_STACKPROTECTOR
+#include <linux/stackprotector.h>
+unsigned long __stack_chk_guard __read_mostly;
+EXPORT_SYMBOL(__stack_chk_guard);
+#endif
+
 static void setup_restart(void)
 {
 	/*
@@ -224,9 +230,27 @@ void exit_thread(void)
 {
 }
 
+static void tls_thread_flush(void)
+{
+	asm ("msr tpidr_el0, xzr");
+
+	if (is_compat_task()) {
+		current->thread.tp_value = 0;
+
+		/*
+		 * We need to ensure ordering between the shadow state and the
+		 * hardware state, so that we don't corrupt the hardware state
+		 * with a stale shadow state during context switch.
+		 */
+		barrier();
+		asm ("msr tpidrro_el0, xzr");
+	}
+}
+
 void flush_thread(void)
 {
 	fpsimd_flush_thread();
+	tls_thread_flush();
 	flush_ptrace_hw_breakpoint(current);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/psci.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/psci.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/psci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/psci.c	2014-09-28 17:29:07.000000000 -0400
@@ -235,7 +235,7 @@ static void psci_sys_poweroff(void)
  * PSCI Function IDs for v0.2+ are well defined so use
  * standard values.
  */
-static int psci_0_2_init(struct device_node *np)
+static int __init psci_0_2_init(struct device_node *np)
 {
 	int err, ver;
 
@@ -296,7 +296,7 @@ out_put_node:
 /*
  * PSCI < v0.2 get PSCI Function IDs via DT.
  */
-static int psci_0_1_init(struct device_node *np)
+static int __init psci_0_1_init(struct device_node *np)
 {
 	u32 id;
 	int err;
@@ -434,9 +434,11 @@ static int cpu_psci_cpu_kill(unsigned in
 	return 0;
 }
 #endif
+#endif
 
 const struct cpu_operations cpu_psci_ops = {
 	.name		= "psci",
+#ifdef CONFIG_SMP
 	.cpu_init	= cpu_psci_cpu_init,
 	.cpu_prepare	= cpu_psci_cpu_prepare,
 	.cpu_boot	= cpu_psci_cpu_boot,
@@ -445,6 +447,6 @@ const struct cpu_operations cpu_psci_ops
 	.cpu_die	= cpu_psci_cpu_die,
 	.cpu_kill	= cpu_psci_cpu_kill,
 #endif
+#endif
 };
 
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/ptrace.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/ptrace.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/ptrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/ptrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/audit.h>
 #include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -39,6 +40,7 @@
 #include <asm/compat.h>
 #include <asm/debug-monitors.h>
 #include <asm/pgtable.h>
+#include <asm/syscall.h>
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
@@ -85,7 +87,8 @@ static void ptrace_hbptriggered(struct p
 			break;
 		}
 	}
-	for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
+
+	for (i = 0; i < ARM_MAX_WRP; ++i) {
 		if (current->thread.debug.hbp_watch[i] == bp) {
 			info.si_errno = -((i << 1) + 1);
 			break;
@@ -660,8 +663,10 @@ static int compat_gpr_get(struct task_st
 			kbuf += sizeof(reg);
 		} else {
 			ret = copy_to_user(ubuf, &reg, sizeof(reg));
-			if (ret)
+			if (ret) {
+				ret = -EFAULT;
 				break;
+			}
 
 			ubuf += sizeof(reg);
 		}
@@ -699,8 +704,10 @@ static int compat_gpr_set(struct task_st
 			kbuf += sizeof(reg);
 		} else {
 			ret = copy_from_user(&reg, ubuf, sizeof(reg));
-			if (ret)
-				return ret;
+			if (ret) {
+				ret = -EFAULT;
+				break;
+			}
 
 			ubuf += sizeof(reg);
 		}
@@ -1113,11 +1120,16 @@ asmlinkage int syscall_trace_enter(struc
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_enter(regs, regs->syscallno);
 
+	audit_syscall_entry(syscall_get_arch(), regs->syscallno,
+		regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]);
+
 	return regs->syscallno;
 }
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	audit_syscall_exit(regs);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_exit(regs, regs_return_value(regs));
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/setup.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,7 @@
 #include <linux/efi.h>
 
 #include <asm/fixmap.h>
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cputable.h>
@@ -219,6 +220,8 @@ static void __init setup_processor(void)
 	sprintf(init_utsname()->machine, ELF_PLATFORM);
 	elf_hwcap = 0;
 
+	cpuinfo_store_boot_cpu();
+
 	/*
 	 * Check for sane CTR_EL0.CWG value.
 	 */
@@ -417,14 +420,12 @@ static int __init arm64_device_init(void
 }
 arch_initcall_sync(arm64_device_init);
 
-static DEFINE_PER_CPU(struct cpu, cpu_data);
-
 static int __init topology_init(void)
 {
 	int i;
 
 	for_each_possible_cpu(i) {
-		struct cpu *cpu = &per_cpu(cpu_data, i);
+		struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
 		cpu->hotpluggable = 1;
 		register_cpu(cpu, i);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/signal32.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/signal32.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/signal32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/signal32.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,7 @@
 #include <asm/fpsimd.h>
 #include <asm/signal32.h>
 #include <asm/uaccess.h>
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
 
 struct compat_sigcontext {
 	/* We always set these two fields to 0 */
@@ -407,20 +407,14 @@ badframe:
 	return 0;
 }
 
-static void __user *compat_get_sigframe(struct k_sigaction *ka,
+static void __user *compat_get_sigframe(struct ksignal *ksig,
 					struct pt_regs *regs,
 					int framesize)
 {
-	compat_ulong_t sp = regs->compat_sp;
+	compat_ulong_t sp = sigsp(regs->compat_sp, ksig);
 	void __user *frame;
 
 	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
-	/*
 	 * ATPCS B01 mandates 8-byte alignment
 	 */
 	frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7));
@@ -520,18 +514,18 @@ static int compat_setup_sigframe(struct
 /*
  * 32-bit signal handling routines called from signal.c
  */
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+int compat_setup_rt_frame(int usig, struct ksignal *ksig,
 			  sigset_t *set, struct pt_regs *regs)
 {
 	struct compat_rt_sigframe __user *frame;
 	int err = 0;
 
-	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+	frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!frame)
 		return 1;
 
-	err |= copy_siginfo_to_user32(&frame->info, info);
+	err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
 
 	__put_user_error(0, &frame->sig.uc.uc_flags, err);
 	__put_user_error(0, &frame->sig.uc.uc_link, err);
@@ -541,7 +535,7 @@ int compat_setup_rt_frame(int usig, stru
 	err |= compat_setup_sigframe(&frame->sig, regs, set);
 
 	if (err == 0) {
-		compat_setup_return(regs, ka, frame->sig.retcode, frame, usig);
+		compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
 		regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
 		regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
 	}
@@ -549,13 +543,13 @@ int compat_setup_rt_frame(int usig, stru
 	return err;
 }
 
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
 		       struct pt_regs *regs)
 {
 	struct compat_sigframe __user *frame;
 	int err = 0;
 
-	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+	frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!frame)
 		return 1;
@@ -564,7 +558,7 @@ int compat_setup_frame(int usig, struct
 
 	err |= compat_setup_sigframe(frame, regs, set);
 	if (err == 0)
-		compat_setup_return(regs, ka, frame->retcode, frame, usig);
+		compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/signal.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigf
 	return err;
 }
 
-static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka,
+static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
 					       struct pt_regs *regs)
 {
 	unsigned long sp, sp_top;
 	struct rt_sigframe __user *frame;
 
-	sp = sp_top = regs->sp;
-
-	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
-		sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
+	sp = sp_top = sigsp(regs->sp, ksig);
 
 	sp = (sp - sizeof(struct rt_sigframe)) & ~15;
 	frame = (struct rt_sigframe __user *)sp;
@@ -253,13 +247,13 @@ static void setup_return(struct pt_regs
 	regs->regs[30] = (unsigned long)sigtramp;
 }
 
-static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs);
+	frame = get_sigframe(ksig, regs);
 	if (!frame)
 		return 1;
 
@@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, stru
 	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
 	err |= setup_sigframe(frame, regs, set);
 	if (err == 0) {
-		setup_return(regs, ka, frame, usig);
-		if (ka->sa.sa_flags & SA_SIGINFO) {
-			err |= copy_siginfo_to_user(&frame->info, info);
+		setup_return(regs, &ksig->ka, frame, usig);
+		if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+			err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 			regs->regs[1] = (unsigned long)&frame->info;
 			regs->regs[2] = (unsigned long)&frame->uc;
 		}
@@ -291,13 +285,12 @@ static void setup_restart_syscall(struct
 /*
  * OK, we're invoking a handler
  */
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
-			  siginfo_t *info, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
 	sigset_t *oldset = sigmask_to_save();
-	int usig = sig;
+	int usig = ksig->sig;
 	int ret;
 
 	/*
@@ -310,13 +303,12 @@ static void handle_signal(unsigned long
 	 * Set up the stack frame
 	 */
 	if (is_compat_task()) {
-		if (ka->sa.sa_flags & SA_SIGINFO)
-			ret = compat_setup_rt_frame(usig, ka, info, oldset,
-						    regs);
+		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
 		else
-			ret = compat_setup_frame(usig, ka, oldset, regs);
+			ret = compat_setup_frame(usig, ksig, oldset, regs);
 	} else {
-		ret = setup_rt_frame(usig, ka, info, oldset, regs);
+		ret = setup_rt_frame(usig, ksig, oldset, regs);
 	}
 
 	/*
@@ -324,18 +316,14 @@ static void handle_signal(unsigned long
 	 */
 	ret |= !valid_user_regs(&regs->user_regs);
 
-	if (ret != 0) {
-		force_sigsegv(sig, tsk);
-		return;
-	}
-
 	/*
 	 * Fast forward the stepping logic so we step into the signal
 	 * handler.
 	 */
-	user_fastforward_single_step(tsk);
+	if (!ret)
+		user_fastforward_single_step(tsk);
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -350,10 +338,9 @@ static void handle_signal(unsigned long
 static void do_signal(struct pt_regs *regs)
 {
 	unsigned long continue_addr = 0, restart_addr = 0;
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr, retval = 0;
+	int retval = 0;
 	int syscall = (int)regs->syscallno;
+	struct ksignal ksig;
 
 	/*
 	 * If we were from a system call, check for system call restarting...
@@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *re
 	 * Get the signal to deliver. When running under ptrace, at this point
 	 * the debugger may change all of our registers.
 	 */
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/*
 		 * Depending on the signal settings, we may need to revert the
 		 * decision to restart the system call, but skip this if a
@@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *re
 		    (retval == -ERESTARTNOHAND ||
 		     retval == -ERESTART_RESTARTBLOCK ||
 		     (retval == -ERESTARTSYS &&
-		      !(ka.sa.sa_flags & SA_RESTART)))) {
+		      !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
 			regs->regs[0] = -EINTR;
 			regs->pc = continue_addr;
 		}
 
-		handle_signal(signr, &ka, &info, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/smp.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,7 @@
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/cpu_ops.h>
 #include <asm/mmu_context.h>
@@ -50,6 +51,9 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ipi.h>
+
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  * so we need some other way of telling a new secondary core
@@ -155,6 +159,11 @@ asmlinkage void secondary_start_kernel(v
 		cpu_ops[cpu]->cpu_postboot();
 
 	/*
+	 * Log the CPU info before it is marked online and might get read.
+	 */
+	cpuinfo_store_cpu();
+
+	/*
 	 * Enable GIC and timers.
 	 */
 	notify_cpu_starting(cpu);
@@ -307,8 +316,6 @@ void __init smp_prepare_boot_cpu(void)
 	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 }
 
-static void (*smp_cross_call)(const struct cpumask *, unsigned int);
-
 /*
  * Enumerate the possible CPU set from the device tree and build the
  * cpu logical map array containing MPIDR values related to logical
@@ -463,32 +470,15 @@ void __init smp_prepare_cpus(unsigned in
 	}
 }
 
+static void (*__smp_cross_call)(const struct cpumask *, unsigned int);
 
 void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
 {
-	smp_cross_call = fn;
-}
-
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
-	smp_cross_call(mask, IPI_CALL_FUNC);
-}
-
-void arch_send_call_function_single_ipi(int cpu)
-{
-	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
-}
-
-#ifdef CONFIG_IRQ_WORK
-void arch_irq_work_raise(void)
-{
-	if (smp_cross_call)
-		smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+	__smp_cross_call = fn;
 }
-#endif
 
-static const char *ipi_types[NR_IPI] = {
-#define S(x,s)	[x - IPI_RESCHEDULE] = s
+static const char *ipi_types[NR_IPI] __tracepoint_string = {
+#define S(x,s)	[x] = s
 	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
 	S(IPI_CALL_FUNC, "Function call interrupts"),
 	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
@@ -497,12 +487,18 @@ static const char *ipi_types[NR_IPI] = {
 	S(IPI_IRQ_WORK, "IRQ work interrupts"),
 };
 
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
+{
+	trace_ipi_raise(target, ipi_types[ipinr]);
+	__smp_cross_call(target, ipinr);
+}
+
 void show_ipi_list(struct seq_file *p, int prec)
 {
 	unsigned int cpu, i;
 
 	for (i = 0; i < NR_IPI; i++) {
-		seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE,
+		seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
 			   prec >= 4 ? " " : "");
 		for_each_online_cpu(cpu)
 			seq_printf(p, "%10u ",
@@ -522,6 +518,24 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	return sum;
 }
 
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+#ifdef CONFIG_IRQ_WORK
+void arch_irq_work_raise(void)
+{
+	if (__smp_cross_call)
+		smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+}
+#endif
+
 static DEFINE_RAW_SPINLOCK(stop_lock);
 
 /*
@@ -553,8 +567,10 @@ void handle_IPI(int ipinr, struct pt_reg
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
-	if (ipinr >= IPI_RESCHEDULE && ipinr < IPI_RESCHEDULE + NR_IPI)
-		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_RESCHEDULE]);
+	if ((unsigned)ipinr < NR_IPI) {
+		trace_ipi_entry(ipi_types[ipinr]);
+		__inc_irq_stat(cpu, ipi_irqs[ipinr]);
+	}
 
 	switch (ipinr) {
 	case IPI_RESCHEDULE:
@@ -599,6 +615,9 @@ void handle_IPI(int ipinr, struct pt_reg
 		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
 		break;
 	}
+
+	if ((unsigned)ipinr < NR_IPI)
+		trace_ipi_exit(ipi_types[ipinr]);
 	set_irq_regs(old_regs);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/suspend.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/suspend.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/suspend.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/suspend.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,7 +119,7 @@ int cpu_suspend(unsigned long arg)
 extern struct sleep_save_sp sleep_save_sp;
 extern phys_addr_t sleep_idmap_phys;
 
-static int cpu_suspend_init(void)
+static int __init cpu_suspend_init(void)
 {
 	void *ctx_ptr;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/sys_compat.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/sys_compat.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/sys_compat.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/sys_compat.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 #include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
 
 static inline void
 do_compat_cache_op(unsigned long start, unsigned long end, int flags)
@@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *
 
 	case __ARM_NR_compat_set_tls:
 		current->thread.tp_value = regs->regs[0];
+
+		/*
+		 * Protect against register corruption from context switch.
+		 * See comment in tls_thread_flush.
+		 */
+		barrier();
 		asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0]));
 		return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/topology.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/topology.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/topology.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/topology.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/sched.h>
 
+#include <asm/cputype.h>
 #include <asm/topology.h>
 
 static int __init get_cpu_for_node(struct device_node *node)
@@ -188,13 +189,9 @@ static int __init parse_dt_topology(void
 	 * Check that all cores are in the topology; the SMP code will
 	 * only mark cores described in the DT as possible.
 	 */
-	for_each_possible_cpu(cpu) {
-		if (cpu_topology[cpu].cluster_id == -1) {
-			pr_err("CPU%d: No topology information specified\n",
-			       cpu);
+	for_each_possible_cpu(cpu)
+		if (cpu_topology[cpu].cluster_id == -1)
 			ret = -EINVAL;
-		}
-	}
 
 out_map:
 	of_node_put(map);
@@ -219,14 +216,6 @@ static void update_siblings_masks(unsign
 	struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
 	int cpu;
 
-	if (cpuid_topo->cluster_id == -1) {
-		/*
-		 * DT does not contain topology information for this cpu.
-		 */
-		pr_debug("CPU%u: No topology information configured\n", cpuid);
-		return;
-	}
-
 	/* update core and thread sibling masks */
 	for_each_possible_cpu(cpu) {
 		cpu_topo = &cpu_topology[cpu];
@@ -249,6 +238,36 @@ static void update_siblings_masks(unsign
 
 void store_cpu_topology(unsigned int cpuid)
 {
+	struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
+	u64 mpidr;
+
+	if (cpuid_topo->cluster_id != -1)
+		goto topology_populated;
+
+	mpidr = read_cpuid_mpidr();
+
+	/* Uniprocessor systems can rely on default topology values */
+	if (mpidr & MPIDR_UP_BITMASK)
+		return;
+
+	/* Create cpu topology mapping based on MPIDR. */
+	if (mpidr & MPIDR_MT_BITMASK) {
+		/* Multiprocessor system : Multi-threads per core */
+		cpuid_topo->thread_id  = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+		cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+		cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
+	} else {
+		/* Multiprocessor system : Single-thread per core */
+		cpuid_topo->thread_id  = -1;
+		cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+		cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+	}
+
+	pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
+		 cpuid, cpuid_topo->cluster_id, cpuid_topo->core_id,
+		 cpuid_topo->thread_id, mpidr);
+
+topology_populated:
 	update_siblings_masks(cpuid);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/traps.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/traps.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/traps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/traps.c	2014-09-28 17:29:07.000000000 -0400
@@ -156,7 +156,7 @@ static void dump_backtrace(struct pt_reg
 		frame.pc = thread_saved_pc(tsk);
 	}
 
-	printk("Call trace:\n");
+	pr_emerg("Call trace:\n");
 	while (1) {
 		unsigned long where = frame.pc;
 		int ret;
@@ -331,17 +331,22 @@ asmlinkage void bad_mode(struct pt_regs
 
 void __pte_error(const char *file, int line, unsigned long val)
 {
-	printk("%s:%d: bad pte %016lx.\n", file, line, val);
+	pr_crit("%s:%d: bad pte %016lx.\n", file, line, val);
 }
 
 void __pmd_error(const char *file, int line, unsigned long val)
 {
-	printk("%s:%d: bad pmd %016lx.\n", file, line, val);
+	pr_crit("%s:%d: bad pmd %016lx.\n", file, line, val);
+}
+
+void __pud_error(const char *file, int line, unsigned long val)
+{
+	pr_crit("%s:%d: bad pud %016lx.\n", file, line, val);
 }
 
 void __pgd_error(const char *file, int line, unsigned long val)
 {
-	printk("%s:%d: bad pgd %016lx.\n", file, line, val);
+	pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);
 }
 
 void __init trap_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/vdso/Makefile linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso/Makefile
--- linux-libre-3.16-gnu/arch/arm64/kernel/vdso/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -43,13 +43,13 @@ $(obj)/vdso-offsets.h: $(obj)/vdso.so.db
 	$(call if_changed,vdsosym)
 
 # Assembly rules for the .S files
-$(obj-vdso): %.o: %.S
+$(obj-vdso): %.o: %.S FORCE
 	$(call if_changed_dep,vdsoas)
 
 # Actual build commands
-quiet_cmd_vdsold = VDSOL $@
+quiet_cmd_vdsold = VDSOL   $@
       cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
-quiet_cmd_vdsoas = VDSOA $@
+quiet_cmd_vdsoas = VDSOA   $@
       cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
 
 # Install commands for the unstripped file
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/vdso/vdso.lds.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso/vdso.lds.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/vdso/vdso.lds.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso/vdso.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@ OUTPUT_ARCH(aarch64)
 
 SECTIONS
 {
+	PROVIDE(_vdso_data = . - PAGE_SIZE);
 	. = VDSO_LBASE + SIZEOF_HEADERS;
 
 	.hash		: { *(.hash) }			:text
@@ -57,9 +58,6 @@ SECTIONS
 	_end = .;
 	PROVIDE(end = .);
 
-	. = ALIGN(PAGE_SIZE);
-	PROVIDE(_vdso_data = .);
-
 	/DISCARD/	: {
 		*(.note.GNU-stack)
 		*(.data .data.* .gnu.linkonce.d.* .sdata*)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/vdso.c linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso.c
--- linux-libre-3.16-gnu/arch/arm64/kernel/vdso.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vdso.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,22 +88,29 @@ int aarch32_setup_vectors_page(struct li
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = AARCH32_VECTORS_BASE;
-	int ret;
+	static struct vm_special_mapping spec = {
+		.name	= "[vectors]",
+		.pages	= vectors_page,
+
+	};
+	void *ret;
 
 	down_write(&mm->mmap_sem);
 	current->mm->context.vdso = (void *)addr;
 
 	/* Map vectors page at the high address. */
-	ret = install_special_mapping(mm, addr, PAGE_SIZE,
-				      VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC,
-				      vectors_page);
+	ret = _install_special_mapping(mm, addr, PAGE_SIZE,
+				       VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC,
+				       &spec);
 
 	up_write(&mm->mmap_sem);
 
-	return ret;
+	return PTR_ERR_OR_ZERO(ret);
 }
 #endif /* CONFIG_COMPAT */
 
+static struct vm_special_mapping vdso_spec[2];
+
 static int __init vdso_init(void)
 {
 	int i;
@@ -114,8 +121,8 @@ static int __init vdso_init(void)
 	}
 
 	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
-	pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
-		vdso_pages + 1, vdso_pages, 1L, &vdso_start);
+	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
 
 	/* Allocate the vDSO pagelist, plus a page for the data. */
 	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
@@ -123,12 +130,23 @@ static int __init vdso_init(void)
 	if (vdso_pagelist == NULL)
 		return -ENOMEM;
 
+	/* Grab the vDSO data page. */
+	vdso_pagelist[0] = virt_to_page(vdso_data);
+
 	/* Grab the vDSO code pages. */
 	for (i = 0; i < vdso_pages; i++)
-		vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
 
-	/* Grab the vDSO data page. */
-	vdso_pagelist[i] = virt_to_page(vdso_data);
+	/* Populate the special mapping structures */
+	vdso_spec[0] = (struct vm_special_mapping) {
+		.name	= "[vvar]",
+		.pages	= vdso_pagelist,
+	};
+
+	vdso_spec[1] = (struct vm_special_mapping) {
+		.name	= "[vdso]",
+		.pages	= &vdso_pagelist[1],
+	};
 
 	return 0;
 }
@@ -138,71 +156,42 @@ int arch_setup_additional_pages(struct l
 				int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long vdso_base, vdso_mapping_len;
-	int ret;
+	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
+	void *ret;
 
+	vdso_text_len = vdso_pages << PAGE_SHIFT;
 	/* Be sure to map the data page */
-	vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
 
 	down_write(&mm->mmap_sem);
 	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
-		ret = vdso_base;
+		ret = ERR_PTR(vdso_base);
 		goto up_fail;
 	}
-	mm->context.vdso = (void *)vdso_base;
-
-	ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
-				      VM_READ|VM_EXEC|
-				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-				      vdso_pagelist);
-	if (ret) {
-		mm->context.vdso = NULL;
+	ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
+				       VM_READ|VM_MAYREAD,
+				       &vdso_spec[0]);
+	if (IS_ERR(ret))
 		goto up_fail;
-	}
 
-up_fail:
-	up_write(&mm->mmap_sem);
-
-	return ret;
-}
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-	/*
-	 * We can re-use the vdso pointer in mm_context_t for identifying
-	 * the vectors page for compat applications. The vDSO will always
-	 * sit above TASK_UNMAPPED_BASE and so we don't need to worry about
-	 * it conflicting with the vectors base.
-	 */
-	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) {
-#ifdef CONFIG_COMPAT
-		if (vma->vm_start == AARCH32_VECTORS_BASE)
-			return "[vectors]";
-#endif
-		return "[vdso]";
-	}
-
-	return NULL;
-}
+	vdso_base += PAGE_SIZE;
+	mm->context.vdso = (void *)vdso_base;
+	ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
+				       VM_READ|VM_EXEC|
+				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				       &vdso_spec[1]);
+	if (IS_ERR(ret))
+		goto up_fail;
 
-/*
- * We define AT_SYSINFO_EHDR, so we need these function stubs to keep
- * Linux happy.
- */
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
 
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
+	up_write(&mm->mmap_sem);
 	return 0;
-}
 
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
+up_fail:
+	mm->context.vdso = NULL;
+	up_write(&mm->mmap_sem);
+	return PTR_ERR(ret);
 }
 
 /*
@@ -211,7 +200,7 @@ struct vm_area_struct *get_gate_vma(stru
 void update_vsyscall(struct timekeeper *tk)
 {
 	struct timespec xtime_coarse;
-	u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
+	u32 use_syscall = strcmp(tk->tkr.clock->name, "arch_sys_counter");
 
 	++vdso_data->tb_seq_count;
 	smp_wmb();
@@ -224,11 +213,11 @@ void update_vsyscall(struct timekeeper *
 	vdso_data->wtm_clock_nsec		= tk->wall_to_monotonic.tv_nsec;
 
 	if (!use_syscall) {
-		vdso_data->cs_cycle_last	= tk->clock->cycle_last;
+		vdso_data->cs_cycle_last	= tk->tkr.cycle_last;
 		vdso_data->xtime_clock_sec	= tk->xtime_sec;
-		vdso_data->xtime_clock_nsec	= tk->xtime_nsec;
-		vdso_data->cs_mult		= tk->mult;
-		vdso_data->cs_shift		= tk->shift;
+		vdso_data->xtime_clock_nsec	= tk->tkr.xtime_nsec;
+		vdso_data->cs_mult		= tk->tkr.mult;
+		vdso_data->cs_shift		= tk->tkr.shift;
 	}
 
 	smp_wmb();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kernel/vmlinux.lds.S linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vmlinux.lds.S
--- linux-libre-3.16-gnu/arch/arm64/kernel/vmlinux.lds.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kernel/vmlinux.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,8 @@
 #include <asm/memory.h>
 #include <asm/page.h>
 
+#include "image.h"
+
 #define ARM_EXIT_KEEP(x)
 #define ARM_EXIT_DISCARD(x)	x
 
@@ -104,9 +106,18 @@ SECTIONS
 	_edata = .;
 
 	BSS_SECTION(0, 0, 0)
+
+	. = ALIGN(PAGE_SIZE);
+	idmap_pg_dir = .;
+	. += IDMAP_DIR_SIZE;
+	swapper_pg_dir = .;
+	. += SWAPPER_DIR_SIZE;
+
 	_end = .;
 
 	STABS_DEBUG
+
+	HEAD_SYMBOLS
 }
 
 /*
@@ -114,3 +125,8 @@ SECTIONS
  */
 ASSERT(((__hyp_idmap_text_start + PAGE_SIZE) > __hyp_idmap_text_end),
        "HYP init code too big")
+
+/*
+ * If padding is applied before .head.text, virt<->phys conversions will fail.
+ */
+ASSERT(_text == (PAGE_OFFSET + TEXT_OFFSET), "HEAD is misaligned")
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/guest.c linux-libre-3.17-rc7-gnu/arch/arm64/kvm/guest.c
--- linux-libre-3.16-gnu/arch/arm64/kvm/guest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/guest.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,13 +136,67 @@ static unsigned long num_core_regs(void)
 }
 
 /**
+ * ARM64 versions of the TIMER registers, always available on arm64
+ */
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+	switch (index) {
+	case KVM_REG_ARM_TIMER_CTL:
+	case KVM_REG_ARM_TIMER_CNT:
+	case KVM_REG_ARM_TIMER_CVAL:
+		return true;
+	}
+	return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+	if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+		return -EFAULT;
+	uindices++;
+	if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+		return -EFAULT;
+	uindices++;
+	if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	void __user *uaddr = (void __user *)(long)reg->addr;
+	u64 val;
+	int ret;
+
+	ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id));
+	if (ret != 0)
+		return ret;
+
+	return kvm_arm_timer_set_reg(vcpu, reg->id, val);
+}
+
+static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	void __user *uaddr = (void __user *)(long)reg->addr;
+	u64 val;
+
+	val = kvm_arm_timer_get_reg(vcpu, reg->id);
+	return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+}
+
+/**
  * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
  *
  * This is for all registers.
  */
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
-	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu);
+	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
+                + NUM_TIMER_REGS;
 }
 
 /**
@@ -154,6 +208,7 @@ int kvm_arm_copy_reg_indices(struct kvm_
 {
 	unsigned int i;
 	const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;
+	int ret;
 
 	for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
 		if (put_user(core_reg | i, uindices))
@@ -161,6 +216,11 @@ int kvm_arm_copy_reg_indices(struct kvm_
 		uindices++;
 	}
 
+	ret = copy_timer_indices(vcpu, uindices);
+	if (ret)
+		return ret;
+	uindices += NUM_TIMER_REGS;
+
 	return kvm_arm_copy_sys_reg_indices(vcpu, uindices);
 }
 
@@ -174,6 +234,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcp
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return get_core_reg(vcpu, reg);
 
+	if (is_timer_reg(reg->id))
+		return get_timer_reg(vcpu, reg);
+
 	return kvm_arm_sys_reg_get_reg(vcpu, reg);
 }
 
@@ -187,6 +250,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcp
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return set_core_reg(vcpu, reg);
 
+	if (is_timer_reg(reg->id))
+		return set_timer_reg(vcpu, reg);
+
 	return kvm_arm_sys_reg_set_reg(vcpu, reg);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/handle_exit.c linux-libre-3.17-rc7-gnu/arch/arm64/kvm/handle_exit.c
--- linux-libre-3.16-gnu/arch/arm64/kvm/handle_exit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/handle_exit.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,6 +66,8 @@ static int kvm_handle_wfx(struct kvm_vcp
 	else
 		kvm_vcpu_block(vcpu);
 
+	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+
 	return 1;
 }
 
@@ -73,9 +75,9 @@ static exit_handle_fn arm_exit_handlers[
 	[ESR_EL2_EC_WFI]	= kvm_handle_wfx,
 	[ESR_EL2_EC_CP15_32]	= kvm_handle_cp15_32,
 	[ESR_EL2_EC_CP15_64]	= kvm_handle_cp15_64,
-	[ESR_EL2_EC_CP14_MR]	= kvm_handle_cp14_access,
+	[ESR_EL2_EC_CP14_MR]	= kvm_handle_cp14_32,
 	[ESR_EL2_EC_CP14_LS]	= kvm_handle_cp14_load_store,
-	[ESR_EL2_EC_CP14_64]	= kvm_handle_cp14_access,
+	[ESR_EL2_EC_CP14_64]	= kvm_handle_cp14_64,
 	[ESR_EL2_EC_HVC32]	= handle_hvc,
 	[ESR_EL2_EC_SMC32]	= handle_smc,
 	[ESR_EL2_EC_HVC64]	= handle_hvc,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/hyp-init.S linux-libre-3.17-rc7-gnu/arch/arm64/kvm/hyp-init.S
--- linux-libre-3.16-gnu/arch/arm64/kvm/hyp-init.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/hyp-init.S	2014-09-28 17:29:07.000000000 -0400
@@ -80,6 +80,10 @@ __do_hyp_init:
 	msr	mair_el2, x4
 	isb
 
+	/* Invalidate the stale TLBs from Bootloader */
+	tlbi	alle2
+	dsb	sy
+
 	mrs	x4, sctlr_el2
 	and	x4, x4, #SCTLR_EL2_EE	// preserve endianness of EL2
 	ldr	x5, =SCTLR_EL2_FLAGS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/hyp.S linux-libre-3.17-rc7-gnu/arch/arm64/kvm/hyp.S
--- linux-libre-3.16-gnu/arch/arm64/kvm/hyp.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/hyp.S	2014-09-28 17:29:07.000000000 -0400
@@ -16,11 +16,11 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/assembler.h>
 #include <asm/memory.h>
 #include <asm/asm-offsets.h>
+#include <asm/debug-monitors.h>
 #include <asm/fpsimdmacros.h>
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
@@ -36,9 +36,6 @@
 	.pushsection	.hyp.text, "ax"
 	.align	PAGE_SHIFT
 
-__kvm_hyp_code_start:
-	.globl __kvm_hyp_code_start
-
 .macro save_common_regs
 	// x2: base address for cpu context
 	// x3: tmp register
@@ -215,6 +212,7 @@ __kvm_hyp_code_start:
 	mrs	x22, 	amair_el1
 	mrs	x23, 	cntkctl_el1
 	mrs	x24,	par_el1
+	mrs	x25,	mdscr_el1
 
 	stp	x4, x5, [x3]
 	stp	x6, x7, [x3, #16]
@@ -226,7 +224,202 @@ __kvm_hyp_code_start:
 	stp	x18, x19, [x3, #112]
 	stp	x20, x21, [x3, #128]
 	stp	x22, x23, [x3, #144]
-	str	x24, [x3, #160]
+	stp	x24, x25, [x3, #160]
+.endm
+
+.macro save_debug
+	// x2: base address for cpu context
+	// x3: tmp register
+
+	mrs	x26, id_aa64dfr0_el1
+	ubfx	x24, x26, #12, #4	// Extract BRPs
+	ubfx	x25, x26, #20, #4	// Extract WRPs
+	mov	w26, #15
+	sub	w24, w26, w24		// How many BPs to skip
+	sub	w25, w26, w25		// How many WPs to skip
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	mrs	x20, dbgbcr15_el1
+	mrs	x19, dbgbcr14_el1
+	mrs	x18, dbgbcr13_el1
+	mrs	x17, dbgbcr12_el1
+	mrs	x16, dbgbcr11_el1
+	mrs	x15, dbgbcr10_el1
+	mrs	x14, dbgbcr9_el1
+	mrs	x13, dbgbcr8_el1
+	mrs	x12, dbgbcr7_el1
+	mrs	x11, dbgbcr6_el1
+	mrs	x10, dbgbcr5_el1
+	mrs	x9, dbgbcr4_el1
+	mrs	x8, dbgbcr3_el1
+	mrs	x7, dbgbcr2_el1
+	mrs	x6, dbgbcr1_el1
+	mrs	x5, dbgbcr0_el1
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+
+1:
+	str	x20, [x3, #(15 * 8)]
+	str	x19, [x3, #(14 * 8)]
+	str	x18, [x3, #(13 * 8)]
+	str	x17, [x3, #(12 * 8)]
+	str	x16, [x3, #(11 * 8)]
+	str	x15, [x3, #(10 * 8)]
+	str	x14, [x3, #(9 * 8)]
+	str	x13, [x3, #(8 * 8)]
+	str	x12, [x3, #(7 * 8)]
+	str	x11, [x3, #(6 * 8)]
+	str	x10, [x3, #(5 * 8)]
+	str	x9, [x3, #(4 * 8)]
+	str	x8, [x3, #(3 * 8)]
+	str	x7, [x3, #(2 * 8)]
+	str	x6, [x3, #(1 * 8)]
+	str	x5, [x3, #(0 * 8)]
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	mrs	x20, dbgbvr15_el1
+	mrs	x19, dbgbvr14_el1
+	mrs	x18, dbgbvr13_el1
+	mrs	x17, dbgbvr12_el1
+	mrs	x16, dbgbvr11_el1
+	mrs	x15, dbgbvr10_el1
+	mrs	x14, dbgbvr9_el1
+	mrs	x13, dbgbvr8_el1
+	mrs	x12, dbgbvr7_el1
+	mrs	x11, dbgbvr6_el1
+	mrs	x10, dbgbvr5_el1
+	mrs	x9, dbgbvr4_el1
+	mrs	x8, dbgbvr3_el1
+	mrs	x7, dbgbvr2_el1
+	mrs	x6, dbgbvr1_el1
+	mrs	x5, dbgbvr0_el1
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+
+1:
+	str	x20, [x3, #(15 * 8)]
+	str	x19, [x3, #(14 * 8)]
+	str	x18, [x3, #(13 * 8)]
+	str	x17, [x3, #(12 * 8)]
+	str	x16, [x3, #(11 * 8)]
+	str	x15, [x3, #(10 * 8)]
+	str	x14, [x3, #(9 * 8)]
+	str	x13, [x3, #(8 * 8)]
+	str	x12, [x3, #(7 * 8)]
+	str	x11, [x3, #(6 * 8)]
+	str	x10, [x3, #(5 * 8)]
+	str	x9, [x3, #(4 * 8)]
+	str	x8, [x3, #(3 * 8)]
+	str	x7, [x3, #(2 * 8)]
+	str	x6, [x3, #(1 * 8)]
+	str	x5, [x3, #(0 * 8)]
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	mrs	x20, dbgwcr15_el1
+	mrs	x19, dbgwcr14_el1
+	mrs	x18, dbgwcr13_el1
+	mrs	x17, dbgwcr12_el1
+	mrs	x16, dbgwcr11_el1
+	mrs	x15, dbgwcr10_el1
+	mrs	x14, dbgwcr9_el1
+	mrs	x13, dbgwcr8_el1
+	mrs	x12, dbgwcr7_el1
+	mrs	x11, dbgwcr6_el1
+	mrs	x10, dbgwcr5_el1
+	mrs	x9, dbgwcr4_el1
+	mrs	x8, dbgwcr3_el1
+	mrs	x7, dbgwcr2_el1
+	mrs	x6, dbgwcr1_el1
+	mrs	x5, dbgwcr0_el1
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+
+1:
+	str	x20, [x3, #(15 * 8)]
+	str	x19, [x3, #(14 * 8)]
+	str	x18, [x3, #(13 * 8)]
+	str	x17, [x3, #(12 * 8)]
+	str	x16, [x3, #(11 * 8)]
+	str	x15, [x3, #(10 * 8)]
+	str	x14, [x3, #(9 * 8)]
+	str	x13, [x3, #(8 * 8)]
+	str	x12, [x3, #(7 * 8)]
+	str	x11, [x3, #(6 * 8)]
+	str	x10, [x3, #(5 * 8)]
+	str	x9, [x3, #(4 * 8)]
+	str	x8, [x3, #(3 * 8)]
+	str	x7, [x3, #(2 * 8)]
+	str	x6, [x3, #(1 * 8)]
+	str	x5, [x3, #(0 * 8)]
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	mrs	x20, dbgwvr15_el1
+	mrs	x19, dbgwvr14_el1
+	mrs	x18, dbgwvr13_el1
+	mrs	x17, dbgwvr12_el1
+	mrs	x16, dbgwvr11_el1
+	mrs	x15, dbgwvr10_el1
+	mrs	x14, dbgwvr9_el1
+	mrs	x13, dbgwvr8_el1
+	mrs	x12, dbgwvr7_el1
+	mrs	x11, dbgwvr6_el1
+	mrs	x10, dbgwvr5_el1
+	mrs	x9, dbgwvr4_el1
+	mrs	x8, dbgwvr3_el1
+	mrs	x7, dbgwvr2_el1
+	mrs	x6, dbgwvr1_el1
+	mrs	x5, dbgwvr0_el1
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+
+1:
+	str	x20, [x3, #(15 * 8)]
+	str	x19, [x3, #(14 * 8)]
+	str	x18, [x3, #(13 * 8)]
+	str	x17, [x3, #(12 * 8)]
+	str	x16, [x3, #(11 * 8)]
+	str	x15, [x3, #(10 * 8)]
+	str	x14, [x3, #(9 * 8)]
+	str	x13, [x3, #(8 * 8)]
+	str	x12, [x3, #(7 * 8)]
+	str	x11, [x3, #(6 * 8)]
+	str	x10, [x3, #(5 * 8)]
+	str	x9, [x3, #(4 * 8)]
+	str	x8, [x3, #(3 * 8)]
+	str	x7, [x3, #(2 * 8)]
+	str	x6, [x3, #(1 * 8)]
+	str	x5, [x3, #(0 * 8)]
+
+	mrs	x21, mdccint_el1
+	str	x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
 .endm
 
 .macro restore_sysregs
@@ -245,7 +438,7 @@ __kvm_hyp_code_start:
 	ldp	x18, x19, [x3, #112]
 	ldp	x20, x21, [x3, #128]
 	ldp	x22, x23, [x3, #144]
-	ldr	x24, [x3, #160]
+	ldp	x24, x25, [x3, #160]
 
 	msr	vmpidr_el2,	x4
 	msr	csselr_el1,	x5
@@ -268,6 +461,198 @@ __kvm_hyp_code_start:
 	msr	amair_el1,	x22
 	msr	cntkctl_el1,	x23
 	msr	par_el1,	x24
+	msr	mdscr_el1,	x25
+.endm
+
+.macro restore_debug
+	// x2: base address for cpu context
+	// x3: tmp register
+
+	mrs	x26, id_aa64dfr0_el1
+	ubfx	x24, x26, #12, #4	// Extract BRPs
+	ubfx	x25, x26, #20, #4	// Extract WRPs
+	mov	w26, #15
+	sub	w24, w26, w24		// How many BPs to skip
+	sub	w25, w26, w25		// How many WPs to skip
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	ldr	x20, [x3, #(15 * 8)]
+	ldr	x19, [x3, #(14 * 8)]
+	ldr	x18, [x3, #(13 * 8)]
+	ldr	x17, [x3, #(12 * 8)]
+	ldr	x16, [x3, #(11 * 8)]
+	ldr	x15, [x3, #(10 * 8)]
+	ldr	x14, [x3, #(9 * 8)]
+	ldr	x13, [x3, #(8 * 8)]
+	ldr	x12, [x3, #(7 * 8)]
+	ldr	x11, [x3, #(6 * 8)]
+	ldr	x10, [x3, #(5 * 8)]
+	ldr	x9, [x3, #(4 * 8)]
+	ldr	x8, [x3, #(3 * 8)]
+	ldr	x7, [x3, #(2 * 8)]
+	ldr	x6, [x3, #(1 * 8)]
+	ldr	x5, [x3, #(0 * 8)]
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	msr	dbgbcr15_el1, x20
+	msr	dbgbcr14_el1, x19
+	msr	dbgbcr13_el1, x18
+	msr	dbgbcr12_el1, x17
+	msr	dbgbcr11_el1, x16
+	msr	dbgbcr10_el1, x15
+	msr	dbgbcr9_el1, x14
+	msr	dbgbcr8_el1, x13
+	msr	dbgbcr7_el1, x12
+	msr	dbgbcr6_el1, x11
+	msr	dbgbcr5_el1, x10
+	msr	dbgbcr4_el1, x9
+	msr	dbgbcr3_el1, x8
+	msr	dbgbcr2_el1, x7
+	msr	dbgbcr1_el1, x6
+	msr	dbgbcr0_el1, x5
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	ldr	x20, [x3, #(15 * 8)]
+	ldr	x19, [x3, #(14 * 8)]
+	ldr	x18, [x3, #(13 * 8)]
+	ldr	x17, [x3, #(12 * 8)]
+	ldr	x16, [x3, #(11 * 8)]
+	ldr	x15, [x3, #(10 * 8)]
+	ldr	x14, [x3, #(9 * 8)]
+	ldr	x13, [x3, #(8 * 8)]
+	ldr	x12, [x3, #(7 * 8)]
+	ldr	x11, [x3, #(6 * 8)]
+	ldr	x10, [x3, #(5 * 8)]
+	ldr	x9, [x3, #(4 * 8)]
+	ldr	x8, [x3, #(3 * 8)]
+	ldr	x7, [x3, #(2 * 8)]
+	ldr	x6, [x3, #(1 * 8)]
+	ldr	x5, [x3, #(0 * 8)]
+
+	adr	x26, 1f
+	add	x26, x26, x24, lsl #2
+	br	x26
+1:
+	msr	dbgbvr15_el1, x20
+	msr	dbgbvr14_el1, x19
+	msr	dbgbvr13_el1, x18
+	msr	dbgbvr12_el1, x17
+	msr	dbgbvr11_el1, x16
+	msr	dbgbvr10_el1, x15
+	msr	dbgbvr9_el1, x14
+	msr	dbgbvr8_el1, x13
+	msr	dbgbvr7_el1, x12
+	msr	dbgbvr6_el1, x11
+	msr	dbgbvr5_el1, x10
+	msr	dbgbvr4_el1, x9
+	msr	dbgbvr3_el1, x8
+	msr	dbgbvr2_el1, x7
+	msr	dbgbvr1_el1, x6
+	msr	dbgbvr0_el1, x5
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	ldr	x20, [x3, #(15 * 8)]
+	ldr	x19, [x3, #(14 * 8)]
+	ldr	x18, [x3, #(13 * 8)]
+	ldr	x17, [x3, #(12 * 8)]
+	ldr	x16, [x3, #(11 * 8)]
+	ldr	x15, [x3, #(10 * 8)]
+	ldr	x14, [x3, #(9 * 8)]
+	ldr	x13, [x3, #(8 * 8)]
+	ldr	x12, [x3, #(7 * 8)]
+	ldr	x11, [x3, #(6 * 8)]
+	ldr	x10, [x3, #(5 * 8)]
+	ldr	x9, [x3, #(4 * 8)]
+	ldr	x8, [x3, #(3 * 8)]
+	ldr	x7, [x3, #(2 * 8)]
+	ldr	x6, [x3, #(1 * 8)]
+	ldr	x5, [x3, #(0 * 8)]
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	msr	dbgwcr15_el1, x20
+	msr	dbgwcr14_el1, x19
+	msr	dbgwcr13_el1, x18
+	msr	dbgwcr12_el1, x17
+	msr	dbgwcr11_el1, x16
+	msr	dbgwcr10_el1, x15
+	msr	dbgwcr9_el1, x14
+	msr	dbgwcr8_el1, x13
+	msr	dbgwcr7_el1, x12
+	msr	dbgwcr6_el1, x11
+	msr	dbgwcr5_el1, x10
+	msr	dbgwcr4_el1, x9
+	msr	dbgwcr3_el1, x8
+	msr	dbgwcr2_el1, x7
+	msr	dbgwcr1_el1, x6
+	msr	dbgwcr0_el1, x5
+
+	add	x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	ldr	x20, [x3, #(15 * 8)]
+	ldr	x19, [x3, #(14 * 8)]
+	ldr	x18, [x3, #(13 * 8)]
+	ldr	x17, [x3, #(12 * 8)]
+	ldr	x16, [x3, #(11 * 8)]
+	ldr	x15, [x3, #(10 * 8)]
+	ldr	x14, [x3, #(9 * 8)]
+	ldr	x13, [x3, #(8 * 8)]
+	ldr	x12, [x3, #(7 * 8)]
+	ldr	x11, [x3, #(6 * 8)]
+	ldr	x10, [x3, #(5 * 8)]
+	ldr	x9, [x3, #(4 * 8)]
+	ldr	x8, [x3, #(3 * 8)]
+	ldr	x7, [x3, #(2 * 8)]
+	ldr	x6, [x3, #(1 * 8)]
+	ldr	x5, [x3, #(0 * 8)]
+
+	adr	x26, 1f
+	add	x26, x26, x25, lsl #2
+	br	x26
+1:
+	msr	dbgwvr15_el1, x20
+	msr	dbgwvr14_el1, x19
+	msr	dbgwvr13_el1, x18
+	msr	dbgwvr12_el1, x17
+	msr	dbgwvr11_el1, x16
+	msr	dbgwvr10_el1, x15
+	msr	dbgwvr9_el1, x14
+	msr	dbgwvr8_el1, x13
+	msr	dbgwvr7_el1, x12
+	msr	dbgwvr6_el1, x11
+	msr	dbgwvr5_el1, x10
+	msr	dbgwvr4_el1, x9
+	msr	dbgwvr3_el1, x8
+	msr	dbgwvr2_el1, x7
+	msr	dbgwvr1_el1, x6
+	msr	dbgwvr0_el1, x5
+
+	ldr	x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
+	msr	mdccint_el1, x21
 .endm
 
 .macro skip_32bit_state tmp, target
@@ -282,6 +667,35 @@ __kvm_hyp_code_start:
 	tbz	\tmp, #12, \target
 .endm
 
+.macro skip_debug_state tmp, target
+	ldr	\tmp, [x0, #VCPU_DEBUG_FLAGS]
+	tbz	\tmp, #KVM_ARM64_DEBUG_DIRTY_SHIFT, \target
+.endm
+
+.macro compute_debug_state target
+	// Compute debug state: If any of KDE, MDE or KVM_ARM64_DEBUG_DIRTY
+	// is set, we do a full save/restore cycle and disable trapping.
+	add	x25, x0, #VCPU_CONTEXT
+
+	// Check the state of MDSCR_EL1
+	ldr	x25, [x25, #CPU_SYSREG_OFFSET(MDSCR_EL1)]
+	and	x26, x25, #DBG_MDSCR_KDE
+	and	x25, x25, #DBG_MDSCR_MDE
+	adds	xzr, x25, x26
+	b.eq	9998f		// Nothing to see there
+
+	// If any interesting bits was set, we must set the flag
+	mov	x26, #KVM_ARM64_DEBUG_DIRTY
+	str	x26, [x0, #VCPU_DEBUG_FLAGS]
+	b	9999f		// Don't skip restore
+
+9998:
+	// Otherwise load the flags from memory in case we recently
+	// trapped
+	skip_debug_state x25, \target
+9999:
+.endm
+
 .macro save_guest_32bit_state
 	skip_32bit_state x3, 1f
 
@@ -297,10 +711,13 @@ __kvm_hyp_code_start:
 	mrs	x4, dacr32_el2
 	mrs	x5, ifsr32_el2
 	mrs	x6, fpexc32_el2
-	mrs	x7, dbgvcr32_el2
 	stp	x4, x5, [x3]
-	stp	x6, x7, [x3, #16]
+	str	x6, [x3, #16]
 
+	skip_debug_state x8, 2f
+	mrs	x7, dbgvcr32_el2
+	str	x7, [x3, #24]
+2:
 	skip_tee_state x8, 1f
 
 	add	x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
@@ -323,12 +740,15 @@ __kvm_hyp_code_start:
 
 	add	x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
 	ldp	x4, x5, [x3]
-	ldp	x6, x7, [x3, #16]
+	ldr	x6, [x3, #16]
 	msr	dacr32_el2, x4
 	msr	ifsr32_el2, x5
 	msr	fpexc32_el2, x6
-	msr	dbgvcr32_el2, x7
 
+	skip_debug_state x8, 2f
+	ldr	x7, [x3, #24]
+	msr	dbgvcr32_el2, x7
+2:
 	skip_tee_state x8, 1f
 
 	add	x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
@@ -339,11 +759,8 @@ __kvm_hyp_code_start:
 .endm
 
 .macro activate_traps
-	ldr	x2, [x0, #VCPU_IRQ_LINES]
-	ldr	x1, [x0, #VCPU_HCR_EL2]
-	orr	x2, x2, x1
-	msr	hcr_el2, x2
-
+	ldr     x2, [x0, #VCPU_HCR_EL2]
+	msr     hcr_el2, x2
 	ldr	x2, =(CPTR_EL2_TTA)
 	msr	cptr_el2, x2
 
@@ -353,6 +770,14 @@ __kvm_hyp_code_start:
 	mrs	x2, mdcr_el2
 	and	x2, x2, #MDCR_EL2_HPMN_MASK
 	orr	x2, x2, #(MDCR_EL2_TPM | MDCR_EL2_TPMCR)
+	orr	x2, x2, #(MDCR_EL2_TDRA | MDCR_EL2_TDOSA)
+
+	// Check for KVM_ARM64_DEBUG_DIRTY, and set debug to trap
+	// if not dirty.
+	ldr	x3, [x0, #VCPU_DEBUG_FLAGS]
+	tbnz	x3, #KVM_ARM64_DEBUG_DIRTY_SHIFT, 1f
+	orr	x2, x2,  #MDCR_EL2_TDA
+1:
 	msr	mdcr_el2, x2
 .endm
 
@@ -379,100 +804,33 @@ __kvm_hyp_code_start:
 .endm
 
 /*
- * Save the VGIC CPU state into memory
- * x0: Register pointing to VCPU struct
- * Do not corrupt x1!!!
+ * Call into the vgic backend for state saving
  */
 .macro save_vgic_state
-	/* Get VGIC VCTRL base into x2 */
-	ldr	x2, [x0, #VCPU_KVM]
-	kern_hyp_va	x2
-	ldr	x2, [x2, #KVM_VGIC_VCTRL]
-	kern_hyp_va	x2
-	cbz	x2, 2f		// disabled
-
-	/* Compute the address of struct vgic_cpu */
-	add	x3, x0, #VCPU_VGIC_CPU
-
-	/* Save all interesting registers */
-	ldr	w4, [x2, #GICH_HCR]
-	ldr	w5, [x2, #GICH_VMCR]
-	ldr	w6, [x2, #GICH_MISR]
-	ldr	w7, [x2, #GICH_EISR0]
-	ldr	w8, [x2, #GICH_EISR1]
-	ldr	w9, [x2, #GICH_ELRSR0]
-	ldr	w10, [x2, #GICH_ELRSR1]
-	ldr	w11, [x2, #GICH_APR]
-CPU_BE(	rev	w4,  w4  )
-CPU_BE(	rev	w5,  w5  )
-CPU_BE(	rev	w6,  w6  )
-CPU_BE(	rev	w7,  w7  )
-CPU_BE(	rev	w8,  w8  )
-CPU_BE(	rev	w9,  w9  )
-CPU_BE(	rev	w10, w10 )
-CPU_BE(	rev	w11, w11 )
-
-	str	w4, [x3, #VGIC_CPU_HCR]
-	str	w5, [x3, #VGIC_CPU_VMCR]
-	str	w6, [x3, #VGIC_CPU_MISR]
-	str	w7, [x3, #VGIC_CPU_EISR]
-	str	w8, [x3, #(VGIC_CPU_EISR + 4)]
-	str	w9, [x3, #VGIC_CPU_ELRSR]
-	str	w10, [x3, #(VGIC_CPU_ELRSR + 4)]
-	str	w11, [x3, #VGIC_CPU_APR]
-
-	/* Clear GICH_HCR */
-	str	wzr, [x2, #GICH_HCR]
-
-	/* Save list registers */
-	add	x2, x2, #GICH_LR0
-	ldr	w4, [x3, #VGIC_CPU_NR_LR]
-	add	x3, x3, #VGIC_CPU_LR
-1:	ldr	w5, [x2], #4
-CPU_BE(	rev	w5, w5 )
-	str	w5, [x3], #4
-	sub	w4, w4, #1
-	cbnz	w4, 1b
-2:
+	adr	x24, __vgic_sr_vectors
+	ldr	x24, [x24, VGIC_SAVE_FN]
+	kern_hyp_va	x24
+	blr	x24
+	mrs	x24, hcr_el2
+	mov	x25, #HCR_INT_OVERRIDE
+	neg	x25, x25
+	and	x24, x24, x25
+	msr	hcr_el2, x24
 .endm
 
 /*
- * Restore the VGIC CPU state from memory
- * x0: Register pointing to VCPU struct
+ * Call into the vgic backend for state restoring
  */
 .macro restore_vgic_state
-	/* Get VGIC VCTRL base into x2 */
-	ldr	x2, [x0, #VCPU_KVM]
-	kern_hyp_va	x2
-	ldr	x2, [x2, #KVM_VGIC_VCTRL]
-	kern_hyp_va	x2
-	cbz	x2, 2f		// disabled
-
-	/* Compute the address of struct vgic_cpu */
-	add	x3, x0, #VCPU_VGIC_CPU
-
-	/* We only restore a minimal set of registers */
-	ldr	w4, [x3, #VGIC_CPU_HCR]
-	ldr	w5, [x3, #VGIC_CPU_VMCR]
-	ldr	w6, [x3, #VGIC_CPU_APR]
-CPU_BE(	rev	w4, w4 )
-CPU_BE(	rev	w5, w5 )
-CPU_BE(	rev	w6, w6 )
-
-	str	w4, [x2, #GICH_HCR]
-	str	w5, [x2, #GICH_VMCR]
-	str	w6, [x2, #GICH_APR]
-
-	/* Restore list registers */
-	add	x2, x2, #GICH_LR0
-	ldr	w4, [x3, #VGIC_CPU_NR_LR]
-	add	x3, x3, #VGIC_CPU_LR
-1:	ldr	w5, [x3], #4
-CPU_BE(	rev	w5, w5 )
-	str	w5, [x2], #4
-	sub	w4, w4, #1
-	cbnz	w4, 1b
-2:
+	mrs	x24, hcr_el2
+	ldr	x25, [x0, #VCPU_IRQ_LINES]
+	orr	x24, x24, #HCR_INT_OVERRIDE
+	orr	x24, x24, x25
+	msr	hcr_el2, x24
+	adr	x24, __vgic_sr_vectors
+	ldr	x24, [x24, #VGIC_RESTORE_FN]
+	kern_hyp_va	x24
+	blr	x24
 .endm
 
 .macro save_timer_state
@@ -537,6 +895,14 @@ __restore_sysregs:
 	restore_sysregs
 	ret
 
+__save_debug:
+	save_debug
+	ret
+
+__restore_debug:
+	restore_debug
+	ret
+
 __save_fpsimd:
 	save_fpsimd
 	ret
@@ -568,6 +934,9 @@ ENTRY(__kvm_vcpu_run)
 	bl __save_fpsimd
 	bl __save_sysregs
 
+	compute_debug_state 1f
+	bl	__save_debug
+1:
 	activate_traps
 	activate_vm
 
@@ -579,6 +948,10 @@ ENTRY(__kvm_vcpu_run)
 
 	bl __restore_sysregs
 	bl __restore_fpsimd
+
+	skip_debug_state x3, 1f
+	bl	__restore_debug
+1:
 	restore_guest_32bit_state
 	restore_guest_regs
 
@@ -595,6 +968,10 @@ __kvm_vcpu_return:
 	save_guest_regs
 	bl __save_fpsimd
 	bl __save_sysregs
+
+	skip_debug_state x3, 1f
+	bl	__save_debug
+1:
 	save_guest_32bit_state
 
 	save_timer_state
@@ -609,6 +986,14 @@ __kvm_vcpu_return:
 
 	bl __restore_sysregs
 	bl __restore_fpsimd
+
+	skip_debug_state x3, 1f
+	// Clear the dirty flag for the next run, as all the state has
+	// already been saved. Note that we nuke the whole 64bit word.
+	// If we ever add more flags, we'll have to be more careful...
+	str	xzr, [x0, #VCPU_DEBUG_FLAGS]
+	bl	__restore_debug
+1:
 	restore_host_regs
 
 	mov	x0, x1
@@ -653,6 +1038,12 @@ ENTRY(__kvm_flush_vm_context)
 	ret
 ENDPROC(__kvm_flush_vm_context)
 
+	// struct vgic_sr_vectors __vgi_sr_vectors;
+	.align 3
+ENTRY(__vgic_sr_vectors)
+	.skip	VGIC_SR_VECTOR_SZ
+ENDPROC(__vgic_sr_vectors)
+
 __kvm_hyp_panic:
 	// Guess the context by looking at VTTBR:
 	// If zero, then we're already a host.
@@ -830,7 +1221,7 @@ el1_trap:
 	mrs	x2, far_el2
 
 2:	mrs	x0, tpidr_el2
-	str	x1, [x0, #VCPU_ESR_EL2]
+	str	w1, [x0, #VCPU_ESR_EL2]
 	str	x2, [x0, #VCPU_FAR_EL2]
 	str	x3, [x0, #VCPU_HPFAR_EL2]
 
@@ -880,7 +1271,4 @@ ENTRY(__kvm_hyp_vector)
 	ventry	el1_error_invalid		// Error 32-bit EL1
 ENDPROC(__kvm_hyp_vector)
 
-__kvm_hyp_code_end:
-	.globl	__kvm_hyp_code_end
-
 	.popsection
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/Makefile linux-libre-3.17-rc7-gnu/arch/arm64/kvm/Makefile
--- linux-libre-3.16-gnu/arch/arm64/kvm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -20,4 +20,8 @@ kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
 
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
 kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/sys_regs.c linux-libre-3.17-rc7-gnu/arch/arm64/kvm/sys_regs.c
--- linux-libre-3.16-gnu/arch/arm64/kvm/sys_regs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/sys_regs.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,7 @@
 #include <asm/kvm_mmu.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
+#include <asm/debug-monitors.h>
 #include <trace/events/kvm.h>
 
 #include "sys_regs.h"
@@ -137,10 +138,11 @@ static bool access_vm_reg(struct kvm_vcp
 	if (!p->is_aarch32) {
 		vcpu_sys_reg(vcpu, r->reg) = val;
 	} else {
-		vcpu_cp15(vcpu, r->reg) = val & 0xffffffffUL;
 		if (!p->is_32bit)
-			vcpu_cp15(vcpu, r->reg + 1) = val >> 32;
+			vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
+		vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
 	}
+
 	return true;
 }
 
@@ -163,18 +165,9 @@ static bool access_sctlr(struct kvm_vcpu
 	return true;
 }
 
-/*
- * We could trap ID_DFR0 and tell the guest we don't support performance
- * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
- * NAKed, so it will read the PMCR anyway.
- *
- * Therefore we tell the guest we have 0 counters.  Unfortunately, we
- * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
- * all PM registers, which doesn't crash the guest kernel at least.
- */
-static bool pm_fake(struct kvm_vcpu *vcpu,
-		    const struct sys_reg_params *p,
-		    const struct sys_reg_desc *r)
+static bool trap_raz_wi(struct kvm_vcpu *vcpu,
+			const struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
 {
 	if (p->is_write)
 		return ignore_write(vcpu, p);
@@ -182,6 +175,73 @@ static bool pm_fake(struct kvm_vcpu *vcp
 		return read_zero(vcpu, p);
 }
 
+static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
+			   const struct sys_reg_params *p,
+			   const struct sys_reg_desc *r)
+{
+	if (p->is_write) {
+		return ignore_write(vcpu, p);
+	} else {
+		*vcpu_reg(vcpu, p->Rt) = (1 << 3);
+		return true;
+	}
+}
+
+static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
+				   const struct sys_reg_params *p,
+				   const struct sys_reg_desc *r)
+{
+	if (p->is_write) {
+		return ignore_write(vcpu, p);
+	} else {
+		u32 val;
+		asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val));
+		*vcpu_reg(vcpu, p->Rt) = val;
+		return true;
+	}
+}
+
+/*
+ * We want to avoid world-switching all the DBG registers all the
+ * time:
+ * 
+ * - If we've touched any debug register, it is likely that we're
+ *   going to touch more of them. It then makes sense to disable the
+ *   traps and start doing the save/restore dance
+ * - If debug is active (DBG_MDSCR_KDE or DBG_MDSCR_MDE set), it is
+ *   then mandatory to save/restore the registers, as the guest
+ *   depends on them.
+ * 
+ * For this, we use a DIRTY bit, indicating the guest has modified the
+ * debug registers, used as follow:
+ *
+ * On guest entry:
+ * - If the dirty bit is set (because we're coming back from trapping),
+ *   disable the traps, save host registers, restore guest registers.
+ * - If debug is actively in use (DBG_MDSCR_KDE or DBG_MDSCR_MDE set),
+ *   set the dirty bit, disable the traps, save host registers,
+ *   restore guest registers.
+ * - Otherwise, enable the traps
+ *
+ * On guest exit:
+ * - If the dirty bit is set, save guest registers, restore host
+ *   registers and clear the dirty bit. This ensure that the host can
+ *   now use the debug registers.
+ */
+static bool trap_debug_regs(struct kvm_vcpu *vcpu,
+			    const struct sys_reg_params *p,
+			    const struct sys_reg_desc *r)
+{
+	if (p->is_write) {
+		vcpu_sys_reg(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+	} else {
+		*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, r->reg);
+	}
+
+	return true;
+}
+
 static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
 	u64 amair;
@@ -198,9 +258,39 @@ static void reset_mpidr(struct kvm_vcpu
 	vcpu_sys_reg(vcpu, MPIDR_EL1) = (1UL << 31) | (vcpu->vcpu_id & 0xff);
 }
 
+/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
+#define DBG_BCR_BVR_WCR_WVR_EL1(n)					\
+	/* DBGBVRn_EL1 */						\
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b100),	\
+	  trap_debug_regs, reset_val, (DBGBVR0_EL1 + (n)), 0 },		\
+	/* DBGBCRn_EL1 */						\
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b101),	\
+	  trap_debug_regs, reset_val, (DBGBCR0_EL1 + (n)), 0 },		\
+	/* DBGWVRn_EL1 */						\
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b110),	\
+	  trap_debug_regs, reset_val, (DBGWVR0_EL1 + (n)), 0 },		\
+	/* DBGWCRn_EL1 */						\
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b111),	\
+	  trap_debug_regs, reset_val, (DBGWCR0_EL1 + (n)), 0 }
+
 /*
  * Architected system registers.
  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
+ *
+ * We could trap ID_DFR0 and tell the guest we don't support performance
+ * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
+ * NAKed, so it will read the PMCR anyway.
+ *
+ * Therefore we tell the guest we have 0 counters.  Unfortunately, we
+ * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
+ * all PM registers, which doesn't crash the guest kernel at least.
+ *
+ * Debug handling: We do trap most, if not all debug related system
+ * registers. The implementation is good enough to ensure that a guest
+ * can use these with minimal performance degradation. The drawback is
+ * that we don't implement any of the external debug, none of the
+ * OSlock protocol. This should be revisited if we ever encounter a
+ * more demanding guest...
  */
 static const struct sys_reg_desc sys_reg_descs[] = {
 	/* DC ISW */
@@ -213,12 +303,71 @@ static const struct sys_reg_desc sys_reg
 	{ Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010),
 	  access_dcsw },
 
+	DBG_BCR_BVR_WCR_WVR_EL1(0),
+	DBG_BCR_BVR_WCR_WVR_EL1(1),
+	/* MDCCINT_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm(0b0010), Op2(0b000),
+	  trap_debug_regs, reset_val, MDCCINT_EL1, 0 },
+	/* MDSCR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0000), CRm(0b0010), Op2(0b010),
+	  trap_debug_regs, reset_val, MDSCR_EL1, 0 },
+	DBG_BCR_BVR_WCR_WVR_EL1(2),
+	DBG_BCR_BVR_WCR_WVR_EL1(3),
+	DBG_BCR_BVR_WCR_WVR_EL1(4),
+	DBG_BCR_BVR_WCR_WVR_EL1(5),
+	DBG_BCR_BVR_WCR_WVR_EL1(6),
+	DBG_BCR_BVR_WCR_WVR_EL1(7),
+	DBG_BCR_BVR_WCR_WVR_EL1(8),
+	DBG_BCR_BVR_WCR_WVR_EL1(9),
+	DBG_BCR_BVR_WCR_WVR_EL1(10),
+	DBG_BCR_BVR_WCR_WVR_EL1(11),
+	DBG_BCR_BVR_WCR_WVR_EL1(12),
+	DBG_BCR_BVR_WCR_WVR_EL1(13),
+	DBG_BCR_BVR_WCR_WVR_EL1(14),
+	DBG_BCR_BVR_WCR_WVR_EL1(15),
+
+	/* MDRAR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b000),
+	  trap_raz_wi },
+	/* OSLAR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b100),
+	  trap_raz_wi },
+	/* OSLSR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0001), Op2(0b100),
+	  trap_oslsr_el1 },
+	/* OSDLR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0011), Op2(0b100),
+	  trap_raz_wi },
+	/* DBGPRCR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0100), Op2(0b100),
+	  trap_raz_wi },
+	/* DBGCLAIMSET_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1000), Op2(0b110),
+	  trap_raz_wi },
+	/* DBGCLAIMCLR_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1001), Op2(0b110),
+	  trap_raz_wi },
+	/* DBGAUTHSTATUS_EL1 */
+	{ Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b110),
+	  trap_dbgauthstatus_el1 },
+
 	/* TEECR32_EL1 */
 	{ Op0(0b10), Op1(0b010), CRn(0b0000), CRm(0b0000), Op2(0b000),
 	  NULL, reset_val, TEECR32_EL1, 0 },
 	/* TEEHBR32_EL1 */
 	{ Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b0000), Op2(0b000),
 	  NULL, reset_val, TEEHBR32_EL1, 0 },
+
+	/* MDCCSR_EL1 */
+	{ Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0001), Op2(0b000),
+	  trap_raz_wi },
+	/* DBGDTR_EL0 */
+	{ Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0100), Op2(0b000),
+	  trap_raz_wi },
+	/* DBGDTR[TR]X_EL0 */
+	{ Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0101), Op2(0b000),
+	  trap_raz_wi },
+
 	/* DBGVCR32_EL2 */
 	{ Op0(0b10), Op1(0b100), CRn(0b0000), CRm(0b0111), Op2(0b000),
 	  NULL, reset_val, DBGVCR32_EL2, 0 },
@@ -260,10 +409,10 @@ static const struct sys_reg_desc sys_reg
 
 	/* PMINTENSET_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMINTENCLR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b010),
-	  pm_fake },
+	  trap_raz_wi },
 
 	/* MAIR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000),
@@ -292,43 +441,43 @@ static const struct sys_reg_desc sys_reg
 
 	/* PMCR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b000),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMCNTENSET_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b001),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMCNTENCLR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b010),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMOVSCLR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b011),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMSWINC_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b100),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMSELR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b101),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMCEID0_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b110),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMCEID1_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b111),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMCCNTR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b000),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMXEVTYPER_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b001),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMXEVCNTR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b010),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMUSERENR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b000),
-	  pm_fake },
+	  trap_raz_wi },
 	/* PMOVSSET_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b011),
-	  pm_fake },
+	  trap_raz_wi },
 
 	/* TPIDR_EL0 */
 	{ Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b010),
@@ -348,13 +497,161 @@ static const struct sys_reg_desc sys_reg
 	  NULL, reset_val, FPEXC32_EL2, 0x70 },
 };
 
+static bool trap_dbgidr(struct kvm_vcpu *vcpu,
+			const struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (p->is_write) {
+		return ignore_write(vcpu, p);
+	} else {
+		u64 dfr = read_cpuid(ID_AA64DFR0_EL1);
+		u64 pfr = read_cpuid(ID_AA64PFR0_EL1);
+		u32 el3 = !!((pfr >> 12) & 0xf);
+
+		*vcpu_reg(vcpu, p->Rt) = ((((dfr >> 20) & 0xf) << 28) |
+					  (((dfr >> 12) & 0xf) << 24) |
+					  (((dfr >> 28) & 0xf) << 20) |
+					  (6 << 16) | (el3 << 14) | (el3 << 12));
+		return true;
+	}
+}
+
+static bool trap_debug32(struct kvm_vcpu *vcpu,
+			 const struct sys_reg_params *p,
+			 const struct sys_reg_desc *r)
+{
+	if (p->is_write) {
+		vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+	} else {
+		*vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
+	}
+
+	return true;
+}
+
+#define DBG_BCR_BVR_WCR_WVR(n)					\
+	/* DBGBVRn */						\
+	{ Op1( 0), CRn( 0), CRm((n)), Op2( 4), trap_debug32,	\
+	  NULL, (cp14_DBGBVR0 + (n) * 2) },			\
+	/* DBGBCRn */						\
+	{ Op1( 0), CRn( 0), CRm((n)), Op2( 5), trap_debug32,	\
+	  NULL, (cp14_DBGBCR0 + (n) * 2) },			\
+	/* DBGWVRn */						\
+	{ Op1( 0), CRn( 0), CRm((n)), Op2( 6), trap_debug32,	\
+	  NULL, (cp14_DBGWVR0 + (n) * 2) },			\
+	/* DBGWCRn */						\
+	{ Op1( 0), CRn( 0), CRm((n)), Op2( 7), trap_debug32,	\
+	  NULL, (cp14_DBGWCR0 + (n) * 2) }
+
+#define DBGBXVR(n)						\
+	{ Op1( 0), CRn( 1), CRm((n)), Op2( 1), trap_debug32,	\
+	  NULL, cp14_DBGBXVR0 + n * 2 }
+
+/*
+ * Trapped cp14 registers. We generally ignore most of the external
+ * debug, on the principle that they don't really make sense to a
+ * guest. Revisit this one day, whould this principle change.
+ */
+static const struct sys_reg_desc cp14_regs[] = {
+	/* DBGIDR */
+	{ Op1( 0), CRn( 0), CRm( 0), Op2( 0), trap_dbgidr },
+	/* DBGDTRRXext */
+	{ Op1( 0), CRn( 0), CRm( 0), Op2( 2), trap_raz_wi },
+
+	DBG_BCR_BVR_WCR_WVR(0),
+	/* DBGDSCRint */
+	{ Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
+	DBG_BCR_BVR_WCR_WVR(1),
+	/* DBGDCCINT */
+	{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
+	/* DBGDSCRext */
+	{ Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
+	DBG_BCR_BVR_WCR_WVR(2),
+	/* DBGDTR[RT]Xint */
+	{ Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
+	/* DBGDTR[RT]Xext */
+	{ Op1( 0), CRn( 0), CRm( 3), Op2( 2), trap_raz_wi },
+	DBG_BCR_BVR_WCR_WVR(3),
+	DBG_BCR_BVR_WCR_WVR(4),
+	DBG_BCR_BVR_WCR_WVR(5),
+	/* DBGWFAR */
+	{ Op1( 0), CRn( 0), CRm( 6), Op2( 0), trap_raz_wi },
+	/* DBGOSECCR */
+	{ Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
+	DBG_BCR_BVR_WCR_WVR(6),
+	/* DBGVCR */
+	{ Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
+	DBG_BCR_BVR_WCR_WVR(7),
+	DBG_BCR_BVR_WCR_WVR(8),
+	DBG_BCR_BVR_WCR_WVR(9),
+	DBG_BCR_BVR_WCR_WVR(10),
+	DBG_BCR_BVR_WCR_WVR(11),
+	DBG_BCR_BVR_WCR_WVR(12),
+	DBG_BCR_BVR_WCR_WVR(13),
+	DBG_BCR_BVR_WCR_WVR(14),
+	DBG_BCR_BVR_WCR_WVR(15),
+
+	/* DBGDRAR (32bit) */
+	{ Op1( 0), CRn( 1), CRm( 0), Op2( 0), trap_raz_wi },
+
+	DBGBXVR(0),
+	/* DBGOSLAR */
+	{ Op1( 0), CRn( 1), CRm( 0), Op2( 4), trap_raz_wi },
+	DBGBXVR(1),
+	/* DBGOSLSR */
+	{ Op1( 0), CRn( 1), CRm( 1), Op2( 4), trap_oslsr_el1 },
+	DBGBXVR(2),
+	DBGBXVR(3),
+	/* DBGOSDLR */
+	{ Op1( 0), CRn( 1), CRm( 3), Op2( 4), trap_raz_wi },
+	DBGBXVR(4),
+	/* DBGPRCR */
+	{ Op1( 0), CRn( 1), CRm( 4), Op2( 4), trap_raz_wi },
+	DBGBXVR(5),
+	DBGBXVR(6),
+	DBGBXVR(7),
+	DBGBXVR(8),
+	DBGBXVR(9),
+	DBGBXVR(10),
+	DBGBXVR(11),
+	DBGBXVR(12),
+	DBGBXVR(13),
+	DBGBXVR(14),
+	DBGBXVR(15),
+
+	/* DBGDSAR (32bit) */
+	{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), trap_raz_wi },
+
+	/* DBGDEVID2 */
+	{ Op1( 0), CRn( 7), CRm( 0), Op2( 7), trap_raz_wi },
+	/* DBGDEVID1 */
+	{ Op1( 0), CRn( 7), CRm( 1), Op2( 7), trap_raz_wi },
+	/* DBGDEVID */
+	{ Op1( 0), CRn( 7), CRm( 2), Op2( 7), trap_raz_wi },
+	/* DBGCLAIMSET */
+	{ Op1( 0), CRn( 7), CRm( 8), Op2( 6), trap_raz_wi },
+	/* DBGCLAIMCLR */
+	{ Op1( 0), CRn( 7), CRm( 9), Op2( 6), trap_raz_wi },
+	/* DBGAUTHSTATUS */
+	{ Op1( 0), CRn( 7), CRm(14), Op2( 6), trap_dbgauthstatus_el1 },
+};
+
+/* Trapped cp14 64bit registers */
+static const struct sys_reg_desc cp14_64_regs[] = {
+	/* DBGDRAR (64bit) */
+	{ Op1( 0), CRm( 1), .access = trap_raz_wi },
+
+	/* DBGDSAR (64bit) */
+	{ Op1( 0), CRm( 2), .access = trap_raz_wi },
+};
+
 /*
  * Trapped cp15 registers. TTBR0/TTBR1 get a double encoding,
  * depending on the way they are accessed (as a 32bit or a 64bit
  * register).
  */
 static const struct sys_reg_desc cp15_regs[] = {
-	{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
 	{ Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR },
 	{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
 	{ Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
@@ -374,26 +671,30 @@ static const struct sys_reg_desc cp15_re
 	{ Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw },
 	{ Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
 
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 3), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 5), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 6), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(12), Op2( 7), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(13), Op2( 0), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(13), Op2( 1), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(13), Op2( 2), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake },
-	{ Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake },
+	/* PMU */
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 0), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 1), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 2), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 3), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 5), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 6), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(12), Op2( 7), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(13), Op2( 0), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(13), Op2( 1), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(13), Op2( 2), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(14), Op2( 0), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(14), Op2( 1), trap_raz_wi },
+	{ Op1( 0), CRn( 9), CRm(14), Op2( 2), trap_raz_wi },
 
 	{ Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR },
 	{ Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
 	{ Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
 	{ Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
 	{ Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
+};
 
+static const struct sys_reg_desc cp15_64_regs[] = {
+	{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
 	{ Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
 };
 
@@ -454,26 +755,29 @@ int kvm_handle_cp14_load_store(struct kv
 	return 1;
 }
 
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	kvm_inject_undefined(vcpu);
-	return 1;
-}
-
-static void emulate_cp15(struct kvm_vcpu *vcpu,
-			 const struct sys_reg_params *params)
+/*
+ * emulate_cp --  tries to match a sys_reg access in a handling table, and
+ *                call the corresponding trap handler.
+ *
+ * @params: pointer to the descriptor of the access
+ * @table: array of trap descriptors
+ * @num: size of the trap descriptor array
+ *
+ * Return 0 if the access has been handled, and -1 if not.
+ */
+static int emulate_cp(struct kvm_vcpu *vcpu,
+		      const struct sys_reg_params *params,
+		      const struct sys_reg_desc *table,
+		      size_t num)
 {
-	size_t num;
-	const struct sys_reg_desc *table, *r;
+	const struct sys_reg_desc *r;
 
-	table = get_target_table(vcpu->arch.target, false, &num);
+	if (!table)
+		return -1;	/* Not handled */
 
-	/* Search target-specific then generic table. */
 	r = find_reg(params, table, num);
-	if (!r)
-		r = find_reg(params, cp15_regs, ARRAY_SIZE(cp15_regs));
 
-	if (likely(r)) {
+	if (r) {
 		/*
 		 * Not having an accessor means that we have
 		 * configured a trap that we don't know how to
@@ -485,22 +789,51 @@ static void emulate_cp15(struct kvm_vcpu
 		if (likely(r->access(vcpu, params, r))) {
 			/* Skip instruction, since it was emulated */
 			kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-			return;
 		}
-		/* If access function fails, it should complain. */
+
+		/* Handled */
+		return 0;
 	}
 
-	kvm_err("Unsupported guest CP15 access at: %08lx\n", *vcpu_pc(vcpu));
+	/* Not handled */
+	return -1;
+}
+
+static void unhandled_cp_access(struct kvm_vcpu *vcpu,
+				struct sys_reg_params *params)
+{
+	u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+	int cp;
+
+	switch(hsr_ec) {
+	case ESR_EL2_EC_CP15_32:
+	case ESR_EL2_EC_CP15_64:
+		cp = 15;
+		break;
+	case ESR_EL2_EC_CP14_MR:
+	case ESR_EL2_EC_CP14_64:
+		cp = 14;
+		break;
+	default:
+		WARN_ON((cp = -1));
+	}
+
+	kvm_err("Unsupported guest CP%d access at: %08lx\n",
+		cp, *vcpu_pc(vcpu));
 	print_sys_reg_instr(params);
 	kvm_inject_undefined(vcpu);
 }
 
 /**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP15 access
  * @vcpu: The VCPU pointer
  * @run:  The kvm_run struct
  */
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
+			    const struct sys_reg_desc *global,
+			    size_t nr_global,
+			    const struct sys_reg_desc *target_specific,
+			    size_t nr_specific)
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -529,8 +862,14 @@ int kvm_handle_cp15_64(struct kvm_vcpu *
 		*vcpu_reg(vcpu, params.Rt) = val;
 	}
 
-	emulate_cp15(vcpu, &params);
+	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
+		goto out;
+	if (!emulate_cp(vcpu, &params, global, nr_global))
+		goto out;
+
+	unhandled_cp_access(vcpu, &params);
 
+out:
 	/* Do the opposite hack for the read side */
 	if (!params.is_write) {
 		u64 val = *vcpu_reg(vcpu, params.Rt);
@@ -546,7 +885,11 @@ int kvm_handle_cp15_64(struct kvm_vcpu *
  * @vcpu: The VCPU pointer
  * @run:  The kvm_run struct
  */
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
+			    const struct sys_reg_desc *global,
+			    size_t nr_global,
+			    const struct sys_reg_desc *target_specific,
+			    size_t nr_specific)
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -561,10 +904,51 @@ int kvm_handle_cp15_32(struct kvm_vcpu *
 	params.Op1 = (hsr >> 14) & 0x7;
 	params.Op2 = (hsr >> 17) & 0x7;
 
-	emulate_cp15(vcpu, &params);
+	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
+		return 1;
+	if (!emulate_cp(vcpu, &params, global, nr_global))
+		return 1;
+
+	unhandled_cp_access(vcpu, &params);
 	return 1;
 }
 
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	const struct sys_reg_desc *target_specific;
+	size_t num;
+
+	target_specific = get_target_table(vcpu->arch.target, false, &num);
+	return kvm_handle_cp_64(vcpu,
+				cp15_64_regs, ARRAY_SIZE(cp15_64_regs),
+				target_specific, num);
+}
+
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	const struct sys_reg_desc *target_specific;
+	size_t num;
+
+	target_specific = get_target_table(vcpu->arch.target, false, &num);
+	return kvm_handle_cp_32(vcpu,
+				cp15_regs, ARRAY_SIZE(cp15_regs),
+				target_specific, num);
+}
+
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	return kvm_handle_cp_64(vcpu,
+				cp14_64_regs, ARRAY_SIZE(cp14_64_regs),
+				NULL, 0);
+}
+
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	return kvm_handle_cp_32(vcpu,
+				cp14_regs, ARRAY_SIZE(cp14_regs),
+				NULL, 0);
+}
+
 static int emulate_sys_reg(struct kvm_vcpu *vcpu,
 			   const struct sys_reg_params *params)
 {
@@ -776,17 +1160,15 @@ static struct sys_reg_desc invariant_sys
 	  NULL, get_ctr_el0 },
 };
 
-static int reg_from_user(void *val, const void __user *uaddr, u64 id)
+static int reg_from_user(u64 *val, const void __user *uaddr, u64 id)
 {
-	/* This Just Works because we are little endian. */
 	if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
 		return -EFAULT;
 	return 0;
 }
 
-static int reg_to_user(void __user *uaddr, const void *val, u64 id)
+static int reg_to_user(void __user *uaddr, const u64 *val, u64 id)
 {
-	/* This Just Works because we are little endian. */
 	if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
 		return -EFAULT;
 	return 0;
@@ -962,7 +1344,7 @@ static unsigned int num_demux_regs(void)
 
 static int write_demux_regids(u64 __user *uindices)
 {
-	u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
+	u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
 	unsigned int i;
 
 	val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
@@ -1069,14 +1451,32 @@ int kvm_arm_copy_sys_reg_indices(struct
 	return write_demux_regids(uindices);
 }
 
+static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 1; i < n; i++) {
+		if (cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
+			kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 void kvm_sys_reg_table_init(void)
 {
 	unsigned int i;
 	struct sys_reg_desc clidr;
 
 	/* Make sure tables are unique and in order. */
-	for (i = 1; i < ARRAY_SIZE(sys_reg_descs); i++)
-		BUG_ON(cmp_sys_reg(&sys_reg_descs[i-1], &sys_reg_descs[i]) >= 0);
+	BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs)));
+	BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs)));
+	BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs)));
+	BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
+	BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs)));
+	BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs)));
 
 	/* We abuse the reset function to overwrite the table itself. */
 	for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/vgic-v2-switch.S linux-libre-3.17-rc7-gnu/arch/arm64/kvm/vgic-v2-switch.S
--- linux-libre-3.16-gnu/arch/arm64/kvm/vgic-v2-switch.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/vgic-v2-switch.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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 <linux/linkage.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
+
+	.text
+	.pushsection	.hyp.text, "ax"
+
+/*
+ * Save the VGIC CPU state into memory
+ * x0: Register pointing to VCPU struct
+ * Do not corrupt x1!!!
+ */
+ENTRY(__save_vgic_v2_state)
+__save_vgic_v2_state:
+	/* Get VGIC VCTRL base into x2 */
+	ldr	x2, [x0, #VCPU_KVM]
+	kern_hyp_va	x2
+	ldr	x2, [x2, #KVM_VGIC_VCTRL]
+	kern_hyp_va	x2
+	cbz	x2, 2f		// disabled
+
+	/* Compute the address of struct vgic_cpu */
+	add	x3, x0, #VCPU_VGIC_CPU
+
+	/* Save all interesting registers */
+	ldr	w4, [x2, #GICH_HCR]
+	ldr	w5, [x2, #GICH_VMCR]
+	ldr	w6, [x2, #GICH_MISR]
+	ldr	w7, [x2, #GICH_EISR0]
+	ldr	w8, [x2, #GICH_EISR1]
+	ldr	w9, [x2, #GICH_ELRSR0]
+	ldr	w10, [x2, #GICH_ELRSR1]
+	ldr	w11, [x2, #GICH_APR]
+CPU_BE(	rev	w4,  w4  )
+CPU_BE(	rev	w5,  w5  )
+CPU_BE(	rev	w6,  w6  )
+CPU_BE(	rev	w7,  w7  )
+CPU_BE(	rev	w8,  w8  )
+CPU_BE(	rev	w9,  w9  )
+CPU_BE(	rev	w10, w10 )
+CPU_BE(	rev	w11, w11 )
+
+	str	w4, [x3, #VGIC_V2_CPU_HCR]
+	str	w5, [x3, #VGIC_V2_CPU_VMCR]
+	str	w6, [x3, #VGIC_V2_CPU_MISR]
+	str	w7, [x3, #VGIC_V2_CPU_EISR]
+	str	w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
+	str	w9, [x3, #VGIC_V2_CPU_ELRSR]
+	str	w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
+	str	w11, [x3, #VGIC_V2_CPU_APR]
+
+	/* Clear GICH_HCR */
+	str	wzr, [x2, #GICH_HCR]
+
+	/* Save list registers */
+	add	x2, x2, #GICH_LR0
+	ldr	w4, [x3, #VGIC_CPU_NR_LR]
+	add	x3, x3, #VGIC_V2_CPU_LR
+1:	ldr	w5, [x2], #4
+CPU_BE(	rev	w5, w5 )
+	str	w5, [x3], #4
+	sub	w4, w4, #1
+	cbnz	w4, 1b
+2:
+	ret
+ENDPROC(__save_vgic_v2_state)
+
+/*
+ * Restore the VGIC CPU state from memory
+ * x0: Register pointing to VCPU struct
+ */
+ENTRY(__restore_vgic_v2_state)
+__restore_vgic_v2_state:
+	/* Get VGIC VCTRL base into x2 */
+	ldr	x2, [x0, #VCPU_KVM]
+	kern_hyp_va	x2
+	ldr	x2, [x2, #KVM_VGIC_VCTRL]
+	kern_hyp_va	x2
+	cbz	x2, 2f		// disabled
+
+	/* Compute the address of struct vgic_cpu */
+	add	x3, x0, #VCPU_VGIC_CPU
+
+	/* We only restore a minimal set of registers */
+	ldr	w4, [x3, #VGIC_V2_CPU_HCR]
+	ldr	w5, [x3, #VGIC_V2_CPU_VMCR]
+	ldr	w6, [x3, #VGIC_V2_CPU_APR]
+CPU_BE(	rev	w4, w4 )
+CPU_BE(	rev	w5, w5 )
+CPU_BE(	rev	w6, w6 )
+
+	str	w4, [x2, #GICH_HCR]
+	str	w5, [x2, #GICH_VMCR]
+	str	w6, [x2, #GICH_APR]
+
+	/* Restore list registers */
+	add	x2, x2, #GICH_LR0
+	ldr	w4, [x3, #VGIC_CPU_NR_LR]
+	add	x3, x3, #VGIC_V2_CPU_LR
+1:	ldr	w5, [x3], #4
+CPU_BE(	rev	w5, w5 )
+	str	w5, [x2], #4
+	sub	w4, w4, #1
+	cbnz	w4, 1b
+2:
+	ret
+ENDPROC(__restore_vgic_v2_state)
+
+	.popsection
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/kvm/vgic-v3-switch.S linux-libre-3.17-rc7-gnu/arch/arm64/kvm/vgic-v3-switch.S
--- linux-libre-3.16-gnu/arch/arm64/kvm/vgic-v3-switch.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/arm64/kvm/vgic-v3-switch.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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 <linux/linkage.h>
+#include <linux/irqchip/arm-gic-v3.h>
+
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+
+	.text
+	.pushsection	.hyp.text, "ax"
+
+/*
+ * We store LRs in reverse order to let the CPU deal with streaming
+ * access. Use this macro to make it look saner...
+ */
+#define LR_OFFSET(n)	(VGIC_V3_CPU_LR + (15 - n) * 8)
+
+/*
+ * Save the VGIC CPU state into memory
+ * x0: Register pointing to VCPU struct
+ * Do not corrupt x1!!!
+ */
+.macro	save_vgic_v3_state
+	// Compute the address of struct vgic_cpu
+	add	x3, x0, #VCPU_VGIC_CPU
+
+	// Make sure stores to the GIC via the memory mapped interface
+	// are now visible to the system register interface
+	dsb	st
+
+	// Save all interesting registers
+	mrs_s	x4, ICH_HCR_EL2
+	mrs_s	x5, ICH_VMCR_EL2
+	mrs_s	x6, ICH_MISR_EL2
+	mrs_s	x7, ICH_EISR_EL2
+	mrs_s	x8, ICH_ELSR_EL2
+
+	str	w4, [x3, #VGIC_V3_CPU_HCR]
+	str	w5, [x3, #VGIC_V3_CPU_VMCR]
+	str	w6, [x3, #VGIC_V3_CPU_MISR]
+	str	w7, [x3, #VGIC_V3_CPU_EISR]
+	str	w8, [x3, #VGIC_V3_CPU_ELRSR]
+
+	msr_s	ICH_HCR_EL2, xzr
+
+	mrs_s	x21, ICH_VTR_EL2
+	mvn	w22, w21
+	ubfiz	w23, w22, 2, 4	// w23 = (15 - ListRegs) * 4
+
+	adr	x24, 1f
+	add	x24, x24, x23
+	br	x24
+
+1:
+	mrs_s	x20, ICH_LR15_EL2
+	mrs_s	x19, ICH_LR14_EL2
+	mrs_s	x18, ICH_LR13_EL2
+	mrs_s	x17, ICH_LR12_EL2
+	mrs_s	x16, ICH_LR11_EL2
+	mrs_s	x15, ICH_LR10_EL2
+	mrs_s	x14, ICH_LR9_EL2
+	mrs_s	x13, ICH_LR8_EL2
+	mrs_s	x12, ICH_LR7_EL2
+	mrs_s	x11, ICH_LR6_EL2
+	mrs_s	x10, ICH_LR5_EL2
+	mrs_s	x9, ICH_LR4_EL2
+	mrs_s	x8, ICH_LR3_EL2
+	mrs_s	x7, ICH_LR2_EL2
+	mrs_s	x6, ICH_LR1_EL2
+	mrs_s	x5, ICH_LR0_EL2
+
+	adr	x24, 1f
+	add	x24, x24, x23
+	br	x24
+
+1:
+	str	x20, [x3, #LR_OFFSET(15)]
+	str	x19, [x3, #LR_OFFSET(14)]
+	str	x18, [x3, #LR_OFFSET(13)]
+	str	x17, [x3, #LR_OFFSET(12)]
+	str	x16, [x3, #LR_OFFSET(11)]
+	str	x15, [x3, #LR_OFFSET(10)]
+	str	x14, [x3, #LR_OFFSET(9)]
+	str	x13, [x3, #LR_OFFSET(8)]
+	str	x12, [x3, #LR_OFFSET(7)]
+	str	x11, [x3, #LR_OFFSET(6)]
+	str	x10, [x3, #LR_OFFSET(5)]
+	str	x9, [x3, #LR_OFFSET(4)]
+	str	x8, [x3, #LR_OFFSET(3)]
+	str	x7, [x3, #LR_OFFSET(2)]
+	str	x6, [x3, #LR_OFFSET(1)]
+	str	x5, [x3, #LR_OFFSET(0)]
+
+	tbnz	w21, #29, 6f	// 6 bits
+	tbz	w21, #30, 5f	// 5 bits
+				// 7 bits
+	mrs_s	x20, ICH_AP0R3_EL2
+	str	w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
+	mrs_s	x19, ICH_AP0R2_EL2
+	str	w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
+6:	mrs_s	x18, ICH_AP0R1_EL2
+	str	w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
+5:	mrs_s	x17, ICH_AP0R0_EL2
+	str	w17, [x3, #VGIC_V3_CPU_AP0R]
+
+	tbnz	w21, #29, 6f	// 6 bits
+	tbz	w21, #30, 5f	// 5 bits
+				// 7 bits
+	mrs_s	x20, ICH_AP1R3_EL2
+	str	w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
+	mrs_s	x19, ICH_AP1R2_EL2
+	str	w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
+6:	mrs_s	x18, ICH_AP1R1_EL2
+	str	w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
+5:	mrs_s	x17, ICH_AP1R0_EL2
+	str	w17, [x3, #VGIC_V3_CPU_AP1R]
+
+	// Restore SRE_EL1 access and re-enable SRE at EL1.
+	mrs_s	x5, ICC_SRE_EL2
+	orr	x5, x5, #ICC_SRE_EL2_ENABLE
+	msr_s	ICC_SRE_EL2, x5
+	isb
+	mov	x5, #1
+	msr_s	ICC_SRE_EL1, x5
+.endm
+
+/*
+ * Restore the VGIC CPU state from memory
+ * x0: Register pointing to VCPU struct
+ */
+.macro	restore_vgic_v3_state
+	// Disable SRE_EL1 access. Necessary, otherwise
+	// ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens...
+	msr_s	ICC_SRE_EL1, xzr
+	isb
+
+	// Compute the address of struct vgic_cpu
+	add	x3, x0, #VCPU_VGIC_CPU
+
+	// Restore all interesting registers
+	ldr	w4, [x3, #VGIC_V3_CPU_HCR]
+	ldr	w5, [x3, #VGIC_V3_CPU_VMCR]
+
+	msr_s	ICH_HCR_EL2, x4
+	msr_s	ICH_VMCR_EL2, x5
+
+	mrs_s	x21, ICH_VTR_EL2
+
+	tbnz	w21, #29, 6f	// 6 bits
+	tbz	w21, #30, 5f	// 5 bits
+				// 7 bits
+	ldr	w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
+	msr_s	ICH_AP1R3_EL2, x20
+	ldr	w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
+	msr_s	ICH_AP1R2_EL2, x19
+6:	ldr	w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
+	msr_s	ICH_AP1R1_EL2, x18
+5:	ldr	w17, [x3, #VGIC_V3_CPU_AP1R]
+	msr_s	ICH_AP1R0_EL2, x17
+
+	tbnz	w21, #29, 6f	// 6 bits
+	tbz	w21, #30, 5f	// 5 bits
+				// 7 bits
+	ldr	w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
+	msr_s	ICH_AP0R3_EL2, x20
+	ldr	w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
+	msr_s	ICH_AP0R2_EL2, x19
+6:	ldr	w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
+	msr_s	ICH_AP0R1_EL2, x18
+5:	ldr	w17, [x3, #VGIC_V3_CPU_AP0R]
+	msr_s	ICH_AP0R0_EL2, x17
+
+	and	w22, w21, #0xf
+	mvn	w22, w21
+	ubfiz	w23, w22, 2, 4	// w23 = (15 - ListRegs) * 4
+
+	adr	x24, 1f
+	add	x24, x24, x23
+	br	x24
+
+1:
+	ldr	x20, [x3, #LR_OFFSET(15)]
+	ldr	x19, [x3, #LR_OFFSET(14)]
+	ldr	x18, [x3, #LR_OFFSET(13)]
+	ldr	x17, [x3, #LR_OFFSET(12)]
+	ldr	x16, [x3, #LR_OFFSET(11)]
+	ldr	x15, [x3, #LR_OFFSET(10)]
+	ldr	x14, [x3, #LR_OFFSET(9)]
+	ldr	x13, [x3, #LR_OFFSET(8)]
+	ldr	x12, [x3, #LR_OFFSET(7)]
+	ldr	x11, [x3, #LR_OFFSET(6)]
+	ldr	x10, [x3, #LR_OFFSET(5)]
+	ldr	x9, [x3, #LR_OFFSET(4)]
+	ldr	x8, [x3, #LR_OFFSET(3)]
+	ldr	x7, [x3, #LR_OFFSET(2)]
+	ldr	x6, [x3, #LR_OFFSET(1)]
+	ldr	x5, [x3, #LR_OFFSET(0)]
+
+	adr	x24, 1f
+	add	x24, x24, x23
+	br	x24
+
+1:
+	msr_s	ICH_LR15_EL2, x20
+	msr_s	ICH_LR14_EL2, x19
+	msr_s	ICH_LR13_EL2, x18
+	msr_s	ICH_LR12_EL2, x17
+	msr_s	ICH_LR11_EL2, x16
+	msr_s	ICH_LR10_EL2, x15
+	msr_s	ICH_LR9_EL2,  x14
+	msr_s	ICH_LR8_EL2,  x13
+	msr_s	ICH_LR7_EL2,  x12
+	msr_s	ICH_LR6_EL2,  x11
+	msr_s	ICH_LR5_EL2,  x10
+	msr_s	ICH_LR4_EL2,   x9
+	msr_s	ICH_LR3_EL2,   x8
+	msr_s	ICH_LR2_EL2,   x7
+	msr_s	ICH_LR1_EL2,   x6
+	msr_s	ICH_LR0_EL2,   x5
+
+	// Ensure that the above will have reached the
+	// (re)distributors. This ensure the guest will read
+	// the correct values from the memory-mapped interface.
+	isb
+	dsb	sy
+
+	// Prevent the guest from touching the GIC system registers
+	mrs_s	x5, ICC_SRE_EL2
+	and	x5, x5, #~ICC_SRE_EL2_ENABLE
+	msr_s	ICC_SRE_EL2, x5
+.endm
+
+ENTRY(__save_vgic_v3_state)
+	save_vgic_v3_state
+	ret
+ENDPROC(__save_vgic_v3_state)
+
+ENTRY(__restore_vgic_v3_state)
+	restore_vgic_v3_state
+	ret
+ENDPROC(__restore_vgic_v3_state)
+
+ENTRY(__vgic_v3_get_ich_vtr_el2)
+	mrs_s	x0, ICH_VTR_EL2
+	ret
+ENDPROC(__vgic_v3_get_ich_vtr_el2)
+
+	.popsection
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/Makefile linux-libre-3.17-rc7-gnu/arch/arm64/Makefile
--- linux-libre-3.16-gnu/arch/arm64/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,11 @@ CHECKFLAGS	+= -D__aarch64__
 head-y		:= arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
+ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
+TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')
+else
 TEXT_OFFSET := 0x00080000
+endif
 
 export	TEXT_OFFSET GZFLAGS
 
@@ -48,6 +52,7 @@ core-$(CONFIG_XEN) += arch/arm64/xen/
 core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
 libs-y		:= arch/arm64/lib/ $(libs-y)
 libs-y		+= $(LIBGCC)
+libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/
 
 # Default target when executing plain make
 KBUILD_IMAGE	:= Image.gz
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/mm/fault.c linux-libre-3.17-rc7-gnu/arch/arm64/mm/fault.c
--- linux-libre-3.16-gnu/arch/arm64/mm/fault.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/mm/fault.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,6 +62,7 @@ void show_pte(struct mm_struct *mm, unsi
 			break;
 
 		pud = pud_offset(pgd, addr);
+		printk(", *pud=%016llx", pud_val(*pud));
 		if (pud_none(*pud) || pud_bad(*pud))
 			break;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/mm/init.c linux-libre-3.17-rc7-gnu/arch/arm64/mm/init.c
--- linux-libre-3.16-gnu/arch/arm64/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,9 @@
 #include <linux/of_fdt.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
+#include <linux/efi.h>
 
+#include <asm/fixmap.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/sizes.h>
@@ -137,20 +139,16 @@ void __init arm64_memblock_init(void)
 {
 	phys_addr_t dma_phys_limit = 0;
 
-	/* Register the kernel text, kernel data and initrd with memblock */
+	/*
+	 * Register the kernel text, kernel data, initrd, and initial
+	 * pagetables with memblock.
+	 */
 	memblock_reserve(__pa(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
 		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
 #endif
 
-	/*
-	 * Reserve the page tables.  These are already in use,
-	 * and can only be in node 0.
-	 */
-	memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
-	memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
-
 	early_init_fdt_scan_reserved_mem();
 
 	/* 4GB maximum for 32-bit only capable devices */
@@ -269,26 +267,33 @@ void __init mem_init(void)
 
 #define MLK(b, t) b, t, ((t) - (b)) >> 10
 #define MLM(b, t) b, t, ((t) - (b)) >> 20
+#define MLG(b, t) b, t, ((t) - (b)) >> 30
 #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
 
 	pr_notice("Virtual kernel memory layout:\n"
-		  "    vmalloc : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+		  "    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n"
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-		  "    vmemmap : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+		  "    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
+		  "              0x%16lx - 0x%16lx   (%6ld MB actual)\n"
 #endif
+		  "    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+		  "    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n"
 		  "    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n"
 		  "    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-		  "      .init : 0x%p" " - 0x%p" "   (%6ld kB)\n"
-		  "      .text : 0x%p" " - 0x%p" "   (%6ld kB)\n"
-		  "      .data : 0x%p" " - 0x%p" "   (%6ld kB)\n",
-		  MLM(VMALLOC_START, VMALLOC_END),
+		  "      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+		  "      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+		  "      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		  MLG(VMALLOC_START, VMALLOC_END),
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
+		  MLG((unsigned long)vmemmap,
+		      (unsigned long)vmemmap + VMEMMAP_SIZE),
 		  MLM((unsigned long)virt_to_page(PAGE_OFFSET),
 		      (unsigned long)virt_to_page(high_memory)),
 #endif
+		  MLM((unsigned long)PCI_IOBASE, (unsigned long)PCI_IOBASE + SZ_16M),
+		  MLK(FIXADDR_START, FIXADDR_TOP),
 		  MLM(MODULES_VADDR, MODULES_END),
 		  MLM(PAGE_OFFSET, (unsigned long)high_memory),
-
 		  MLK_ROUNDUP(__init_begin, __init_end),
 		  MLK_ROUNDUP(_text, _etext),
 		  MLK_ROUNDUP(_sdata, _edata));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/mm/ioremap.c linux-libre-3.17-rc7-gnu/arch/arm64/mm/ioremap.c
--- linux-libre-3.16-gnu/arch/arm64/mm/ioremap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/mm/ioremap.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,19 +103,28 @@ void __iomem *ioremap_cache(phys_addr_t
 }
 EXPORT_SYMBOL(ioremap_cache);
 
-#ifndef CONFIG_ARM64_64K_PAGES
 static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
+#endif
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
 #endif
 
-static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+static inline pud_t * __init early_ioremap_pud(unsigned long addr)
 {
 	pgd_t *pgd;
-	pud_t *pud;
 
 	pgd = pgd_offset_k(addr);
 	BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
 
-	pud = pud_offset(pgd, addr);
+	return pud_offset(pgd, addr);
+}
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	pud_t *pud = early_ioremap_pud(addr);
+
 	BUG_ON(pud_none(*pud) || pud_bad(*pud));
 
 	return pmd_offset(pud, addr);
@@ -132,13 +141,18 @@ static inline pte_t * __init early_iorem
 
 void __init early_ioremap_init(void)
 {
+	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
+	unsigned long addr = fix_to_virt(FIX_BTMAP_BEGIN);
 
-	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
-#ifndef CONFIG_ARM64_64K_PAGES
-	/* need to populate pmd for 4k pagesize only */
+	pgd = pgd_offset_k(addr);
+	pgd_populate(&init_mm, pgd, bm_pud);
+	pud = pud_offset(pgd, addr);
+	pud_populate(&init_mm, pud, bm_pmd);
+	pmd = pmd_offset(pud, addr);
 	pmd_populate_kernel(&init_mm, pmd, bm_pte);
-#endif
+
 	/*
 	 * The boot-ioremap range spans multiple pmds, for which
 	 * we are not prepared:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/arm64/mm/mmu.c linux-libre-3.17-rc7-gnu/arch/arm64/mm/mmu.c
--- linux-libre-3.16-gnu/arch/arm64/mm/mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/arm64/mm/mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,7 @@
 #include <asm/setup.h>
 #include <asm/sizes.h>
 #include <asm/tlb.h>
+#include <asm/memblock.h>
 #include <asm/mmu_context.h>
 
 #include "mm.h"
@@ -204,9 +205,16 @@ static void __init alloc_init_pud(pgd_t
 				  unsigned long end, unsigned long phys,
 				  int map_io)
 {
-	pud_t *pud = pud_offset(pgd, addr);
+	pud_t *pud;
 	unsigned long next;
 
+	if (pgd_none(*pgd)) {
+		pud = early_alloc(PTRS_PER_PUD * sizeof(pud_t));
+		pgd_populate(&init_mm, pgd, pud);
+	}
+	BUG_ON(pgd_bad(*pgd));
+
+	pud = pud_offset(pgd, addr);
 	do {
 		next = pud_addr_end(addr, end);
 
@@ -290,10 +298,10 @@ static void __init map_mem(void)
 	 * memory addressable from the initial direct kernel mapping.
 	 *
 	 * The initial direct kernel mapping, located at swapper_pg_dir,
-	 * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (which must be
+	 * gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
 	 * aligned to 2MB as per Documentation/arm64/booting.txt).
 	 */
-	limit = PHYS_OFFSET + PGDIR_SIZE;
+	limit = PHYS_OFFSET + PUD_SIZE;
 	memblock_set_current_limit(limit);
 
 	/* map all the memory banks */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/boards/atngw100/mrmt.c linux-libre-3.17-rc7-gnu/arch/avr32/boards/atngw100/mrmt.c
--- linux-libre-3.16-gnu/arch/avr32/boards/atngw100/mrmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/boards/atngw100/mrmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
 #include <linux/types.h>
 #include <linux/fb.h>
 #include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/atmel_serial.h>
@@ -155,21 +157,28 @@ static struct platform_device rmt_ts_dev
 
 #ifdef CONFIG_BOARD_MRMT_BL_PWM
 /* PWM LEDs: LCD Backlight, etc */
-static struct gpio_led rmt_pwm_led[] = {
-	/* here the "gpio" is actually a PWM channel */
-	{ .name = "backlight",	.gpio = PWM_CH_BL, },
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1",
+		   5000, PWM_POLARITY_INVERSED),
 };
 
-static struct gpio_led_platform_data rmt_pwm_led_data = {
-	.num_leds	= ARRAY_SIZE(rmt_pwm_led),
-	.leds		= rmt_pwm_led,
+static struct led_pwm pwm_leds[] = {
+	{
+		.name = "backlight",
+		.max_brightness = 255,
+	},
 };
 
-static struct platform_device rmt_pwm_led_dev = {
-	.name		= "leds-atmel-pwm",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &rmt_pwm_led_data,
+static struct led_pwm_platform_data pwm_data = {
+	.num_leds       = ARRAY_SIZE(pwm_leds),
+	.leds           = pwm_leds,
+};
+
+static struct platform_device leds_pwm = {
+	.name   = "leds_pwm",
+	.id     = -1,
+	.dev    = {
+		.platform_data = &pwm_data,
 	},
 };
 #endif
@@ -325,7 +334,8 @@ static int __init mrmt1_init(void)
 #ifdef CONFIG_BOARD_MRMT_BL_PWM
 	/* Use PWM for Backlight controls */
 	at32_add_device_pwm(1 << PWM_CH_BL);
-	platform_device_register(&rmt_pwm_led_dev);
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+	platform_device_register(&leds_pwm);
 #else
 	/* Backlight always on */
 	udelay( 1 );
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/boards/favr-32/setup.c linux-libre-3.17-rc7-gnu/arch/avr32/boards/favr-32/setup.c
--- linux-libre-3.16-gnu/arch/avr32/boards/favr-32/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/boards/favr-32/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,10 @@
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/atmel-mci.h>
-#include <linux/atmel-pwm-bl.h>
+#include <linux/pwm.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
@@ -33,6 +36,8 @@
 #include <mach/board.h>
 #include <mach/portmux.h>
 
+#define PWM_BL_CH 2
+
 /* Oscillator frequencies. These are board-specific */
 unsigned long at32_board_osc_rates[3] = {
 	[0] = 32768,	/* 32.768 kHz on RTC osc */
@@ -227,29 +232,36 @@ void __init favr32_setup_leds(void)
 	platform_device_register(&favr32_led_dev);
 }
 
-static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = {
-	.pwm_channel		= 2,
-	.pwm_frequency		= 200000,
-	.pwm_compare_max	= 345,
-	.pwm_duty_max		= 345,
-	.pwm_duty_min		= 90,
-	.pwm_active_low		= 1,
-	.gpio_on		= GPIO_PIN_PA(28),
-	.on_active_low		= 0,
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("at91sam9rl-pwm", PWM_BL_CH, "pwm-backlight.0", NULL,
+		   5000, PWM_POLARITY_INVERSED),
 };
 
-static struct platform_device atmel_pwm_bl_dev = {
-	.name		= "atmel-pwm-bl",
-	.id		= 0,
-	.dev		= {
-		.platform_data = &atmel_pwm_bl_pdata,
+static struct regulator_consumer_supply fixed_power_consumers[] = {
+	REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
+static struct platform_pwm_backlight_data pwm_bl_data = {
+	.enable_gpio		= GPIO_PIN_PA(28),
+	.max_brightness		= 255,
+	.dft_brightness		= 255,
+	.lth_brightness		= 50,
+};
+
+static struct platform_device pwm_bl_device = {
+	.name = "pwm-backlight",
+	.dev = {
+		.platform_data = &pwm_bl_data,
 	},
 };
 
 static void __init favr32_setup_atmel_pwm_bl(void)
 {
-	platform_device_register(&atmel_pwm_bl_dev);
-	at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0);
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+	regulator_register_always_on(0, "fixed", fixed_power_consumers,
+				    ARRAY_SIZE(fixed_power_consumers), 3300000);
+	platform_device_register(&pwm_bl_device);
+	at32_select_gpio(pwm_bl_data.enable_gpio, 0);
 }
 
 void __init setup_board(void)
@@ -339,7 +351,7 @@ static int __init favr32_init(void)
 
 	set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
 
-	at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
+	at32_add_device_pwm(1 << PWM_BL_CH);
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 	at32_add_device_mci(0, &mci0_data);
 	at32_add_device_usba(0, NULL);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/boards/hammerhead/flash.c linux-libre-3.17-rc7-gnu/arch/avr32/boards/hammerhead/flash.c
--- linux-libre-3.16-gnu/arch/avr32/boards/hammerhead/flash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/boards/hammerhead/flash.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,14 +190,19 @@ static int __init hammerhead_usbh_init(v
 
 	/* setup gclk0 to run from osc1 */
 	gclk = clk_get(NULL, "gclk0");
-	if (IS_ERR(gclk))
+	if (IS_ERR(gclk)) {
+		ret = PTR_ERR(gclk);
 		goto err_gclk;
+	}
 
 	osc = clk_get(NULL, "osc1");
-	if (IS_ERR(osc))
+	if (IS_ERR(osc)) {
+		ret = PTR_ERR(osc);
 		goto err_osc;
+	}
 
-	if (clk_set_parent(gclk, osc)) {
+	ret = clk_set_parent(gclk, osc);
+	if (ret < 0) {
 		pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
 		goto err_set_clk;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/boards/merisc/setup.c linux-libre-3.17-rc7-gnu/arch/avr32/boards/merisc/setup.c
--- linux-libre-3.16-gnu/arch/avr32/boards/merisc/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/boards/merisc/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,8 @@
 #include <linux/irq.h>
 #include <linux/fb.h>
 #include <linux/atmel-mci.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
 
 #include <asm/io.h>
 #include <asm/setup.h>
@@ -167,24 +169,29 @@ static struct i2c_board_info __initdata
 	},
 };
 
-#ifdef CONFIG_LEDS_ATMEL_PWM
-static struct gpio_led stk_pwm_led[] = {
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct pwm_lookup pwm_lookup[] = {
+	PWM_LOOKUP("at91sam9rl-pwm", 0, "leds_pwm", "backlight",
+		   5000, PWM_POLARITY_NORMAL),
+};
+
+static struct led_pwm pwm_leds[] = {
 	{
 		.name	= "backlight",
-		.gpio	= 0,		/* PWM channel 0 (LCD backlight) */
+		.max_brightness = 255,
 	},
 };
 
-static struct gpio_led_platform_data stk_pwm_led_data = {
-	.num_leds	= ARRAY_SIZE(stk_pwm_led),
-	.leds		= stk_pwm_led,
+static struct led_pwm_platform_data pwm_data = {
+	.num_leds       = ARRAY_SIZE(pwm_leds),
+	.leds           = pwm_leds,
 };
 
-static struct platform_device stk_pwm_led_dev = {
-	.name	= "leds-atmel-pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &stk_pwm_led_data,
+static struct platform_device leds_pwm = {
+	.name   = "leds_pwm",
+	.id     = -1,
+	.dev    = {
+		.platform_data = &pwm_data,
 	},
 };
 #endif
@@ -278,9 +285,10 @@ static int __init merisc_init(void)
 
 	at32_add_device_mci(0, &mci0_data);
 
-#ifdef CONFIG_LEDS_ATMEL_PWM
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+	pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
 	at32_add_device_pwm((1 << 0) | (1 << 2));
-	platform_device_register(&stk_pwm_led_dev);
+	platform_device_register(&leds_pwm);
 #else
 	at32_add_device_pwm((1 << 2));
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/atngw100_mrmt_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/atngw100_mrmt_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/atngw100_mrmt_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/atngw100_mrmt_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,6 @@ CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_ATMEL_PWM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
@@ -104,8 +103,8 @@ CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -114,6 +113,8 @@ CONFIG_RTC_DRV_S35390A=m
 CONFIG_RTC_DRV_AT32AP700X=m
 CONFIG_DMADEVICES=y
 CONFIG_UIO=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/atstk1002_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1002_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/atstk1002_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1002_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -64,7 +64,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -133,14 +132,16 @@ CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/atstk1003_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1003_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/atstk1003_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1003_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -112,14 +111,16 @@ CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/atstk1004_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1004_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/atstk1004_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1004_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -111,14 +110,16 @@ CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/atstk1006_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1006_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/atstk1006_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/atstk1006_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -136,14 +135,16 @@ CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/favr-32_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/favr-32_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/favr-32_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/favr-32_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,6 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
-CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
 CONFIG_NETDEVICES=y
@@ -108,7 +107,7 @@ CONFIG_FB=y
 CONFIG_FB_ATMEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_BACKLIGHT_ATMEL_PWM=m
+CONFIG_BACKLIGHT_PWM=m
 CONFIG_SOUND=m
 CONFIG_SOUND_PRIME=m
 # CONFIG_HID_SUPPORT is not set
@@ -123,7 +122,6 @@ CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
@@ -132,6 +130,8 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/configs/merisc_defconfig linux-libre-3.17-rc7-gnu/arch/avr32/configs/merisc_defconfig
--- linux-libre-3.16-gnu/arch/avr32/configs/merisc_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/configs/merisc_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,6 @@ CONFIG_MTD_ABSENT=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_ATMEL_PWM=y
 CONFIG_ATMEL_SSC=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -103,12 +102,14 @@ CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_PWM=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_DMADEVICES=y
 CONFIG_UIO=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
 CONFIG_EXT2_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/avr32/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/avr32/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -92,6 +92,7 @@ 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-3.16-gnu/arch/avr32/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/avr32/kernel/signal.c
--- linux-libre-3.16-gnu/arch/avr32/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __use
 }
 
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
 {
-	unsigned long sp = regs->sp;
-
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	unsigned long sp = sigsp(regs->sp, ksig);
 
 	return (void __user *)((sp - framesize) & ~3);
 }
 
 static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	err = -EFAULT;
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto out;
@@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
 			 &frame->retcode);
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Set up the ucontext */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigacti
 	if (err)
 		goto out;
 
-	regs->r12 = sig;
+	regs->r12 = ksig->sig;
 	regs->r11 = (unsigned long) &frame->info;
 	regs->r10 = (unsigned long) &frame->uc;
 	regs->sp = (unsigned long) frame;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		regs->lr = (unsigned long)ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
 	else {
 		printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
 		       current->comm, current->pid);
@@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigacti
 	}
 
 	pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
-		 current->comm, current->pid, sig, regs->sp,
-		 regs->pc, ka->sa.sa_handler, regs->lr);
+		 current->comm, current->pid, ksig->sig, regs->sp,
+		 regs->pc, ksig->ka.sa.sa_handler, regs->lr);
 
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 
 out:
 	return err;
@@ -208,15 +204,14 @@ static inline void setup_syscall_restart
 }
 
 static inline void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs *regs, int syscall)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall)
 {
 	int ret;
 
 	/*
 	 * Set up the stack frame
 	 */
-	ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
+	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
 
 	/*
 	 * Check that the resulting registers are sane
@@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct
 	/*
 	 * Block the signal if we were successful.
 	 */
-	if (ret != 0)
-		force_sigsegv(sig, current);
-	else
-		signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct
  */
 static void do_signal(struct pt_regs *regs, int syscall)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which is why we may in
@@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	get_signal(&ksig);
 	if (syscall) {
 		switch (regs->r12) {
 		case -ERESTART_RESTARTBLOCK:
 		case -ERESTARTNOHAND:
-			if (signr > 0) {
+			if (ksig.sig > 0) {
 				regs->r12 = -EINTR;
 				break;
 			}
 			/* fall through */
 		case -ERESTARTSYS:
-			if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
+			if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) {
 				regs->r12 = -EINTR;
 				break;
 			}
@@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *re
 		}
 	}
 
-	if (signr == 0) {
+	if (!ksig.sig) {
 		/* No signal to deliver -- put the saved sigmask back */
 		restore_saved_sigmask();
 		return;
 	}
 
-	handle_signal(signr, &ka, &info, regs, syscall);
+	handle_signal(&ksig, regs, syscall);
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/avr32/mach-at32ap/at32ap700x.c linux-libre-3.17-rc7-gnu/arch/avr32/mach-at32ap/at32ap700x.c
--- linux-libre-3.16-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1553,7 +1553,7 @@ static struct resource atmel_pwm0_resour
 	IRQ(24),
 };
 static struct clk atmel_pwm0_mck = {
-	.name		= "pwm_clk",
+	.name		= "at91sam9rl-pwm",
 	.parent		= &pbb_clk,
 	.mode		= pbb_clk_mode,
 	.get_rate	= pbb_clk_get_rate,
@@ -1568,7 +1568,7 @@ struct platform_device *__init at32_add_
 	if (!mask)
 		return NULL;
 
-	pdev = platform_device_alloc("atmel_pwm", 0);
+	pdev = platform_device_alloc("at91sam9rl-pwm", 0);
 	if (!pdev)
 		return NULL;
 
@@ -1576,9 +1576,6 @@ struct platform_device *__init at32_add_
 				ARRAY_SIZE(atmel_pwm0_resource)))
 		goto out_free_pdev;
 
-	if (platform_device_add_data(pdev, &mask, sizeof(mask)))
-		goto out_free_pdev;
-
 	pin_mask = 0;
 	if (mask & (1 << 0))
 		pin_mask |= (1 << 28);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/blackfin/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/blackfin/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/blackfin/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/blackfin/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@ 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-3.16-gnu/arch/blackfin/Kconfig linux-libre-3.17-rc7-gnu/arch/blackfin/Kconfig
--- linux-libre-3.16-gnu/arch/blackfin/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/blackfin/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@ config BLACKFIN
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_IDE
 	select HAVE_KERNEL_GZIP if RAMKERNEL
 	select HAVE_KERNEL_BZIP2 if RAMKERNEL
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/blackfin/kernel/ftrace-entry.S linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/ftrace-entry.S
--- linux-libre-3.16-gnu/arch/blackfin/kernel/ftrace-entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/ftrace-entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -33,15 +33,6 @@ ENDPROC(__mcount)
  * function will be waiting there.  mmmm pie.
  */
 ENTRY(_ftrace_caller)
-# ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-	/* optional micro optimization: return if stopped */
-	p1.l = _function_trace_stop;
-	p1.h = _function_trace_stop;
-	r3 = [p1];
-	cc = r3 == 0;
-	if ! cc jump _ftrace_stub (bp);
-# endif
-
 	/* save first/second/third function arg and the return register */
 	[--sp] = r2;
 	[--sp] = r0;
@@ -83,15 +74,6 @@ ENDPROC(_ftrace_caller)
 
 /* See documentation for _ftrace_caller */
 ENTRY(__mcount)
-# ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
-	/* optional micro optimization: return if stopped */
-	p1.l = _function_trace_stop;
-	p1.h = _function_trace_stop;
-	r3 = [p1];
-	cc = r3 == 0;
-	if ! cc jump _ftrace_stub (bp);
-# endif
-
 	/* save third function arg early so we can do testing below */
 	[--sp] = r2;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/blackfin/kernel/perf_event.c linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/perf_event.c
--- linux-libre-3.16-gnu/arch/blackfin/kernel/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -389,14 +389,6 @@ static int bfin_pmu_event_init(struct pe
 	if (attr->exclude_hv || attr->exclude_idle)
 		return -EPERM;
 
-	/*
-	 * All of the on-chip counters are "limited", in that they have
-	 * no interrupts, and are therefore unable to do sampling without
-	 * further work and timer assistance.
-	 */
-	if (hwc->sample_period)
-		return -EINVAL;
-
 	ret = 0;
 	switch (attr->type) {
 	case PERF_TYPE_RAW:
@@ -490,6 +482,13 @@ static int __init bfin_pmu_init(void)
 {
 	int ret;
 
+	/*
+	 * All of the on-chip counters are "limited", in that they have
+	 * no interrupts, and are therefore unable to do sampling without
+	 * further work and timer assistance.
+	 */
+	pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	ret = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	if (!ret)
 		perf_cpu_notifier(bfin_pmu_notifier);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/blackfin/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/signal.c
--- linux-libre-3.16-gnu/arch/blackfin/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/blackfin/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,40 +135,31 @@ static inline int rt_setup_sigcontext(st
 	return err;
 }
 
-static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+static inline void *get_sigframe(struct ksignal *ksig,
 				 size_t frame_size)
 {
-	unsigned long usp;
-
-	/* Default to using normal stack.  */
-	usp = rdusp();
+	unsigned long usp = sigsp(rdusp(), ksig);
 
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
-			usp = current->sas_ss_sp + current->sas_ss_size;
-	}
 	return (void *)((usp - frame_size) & -8UL);
 }
 
 static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
-	       sigset_t * set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	err |= __put_user((current_thread_info()->exec_domain
 			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
+			   && ksig->sig < 32
 			   ? current_thread_info()->exec_domain->
-			   signal_invmap[sig] : sig), &frame->sig);
+			   signal_invmap[ksig->sig] : ksig->sig), &frame->sig);
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -183,7 +174,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	/* Set up registers for signal handler */
 	if (current->personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor *) ka->sa.sa_handler;
+			(struct fdpic_func_descriptor *) ksig->ka.sa.sa_handler;
 		u32 pc, p3;
 		err |= __get_user(pc, &funcptr->text);
 		err |= __get_user(p3, &funcptr->GOT);
@@ -192,7 +183,7 @@ setup_rt_frame(int sig, struct k_sigacti
 		regs->pc = pc;
 		regs->p3 = p3;
 	} else
-		regs->pc = (unsigned long)ka->sa.sa_handler;
+		regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 	wrusp((unsigned long)frame);
 	regs->rets = SIGRETURN_STUB;
 
@@ -237,20 +228,19 @@ handle_restart(struct pt_regs *regs, str
  * OK, we're invoking a handler
  */
 static void
-handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
-	      struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
+	int ret;
+
 	/* are we from a system call? to see pt_regs->orig_p0 */
 	if (regs->orig_p0 >= 0)
 		/* If so, check system call restarting.. */
-		handle_restart(regs, ka, 1);
+		handle_restart(regs, &ksig->ka, 1);
 
 	/* set up the stack frame */
-	if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
-		force_sigsegv(sig, current);
-	else 
-		signal_delivered(sig, info, ka, regs,
-				test_thread_flag(TIF_SINGLESTEP));
+	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
+
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -264,16 +254,13 @@ handle_signal(int sig, siginfo_t *info,
  */
 asmlinkage void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	current->thread.esp0 = (unsigned long)regs;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/c6x/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/c6x/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/c6x/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/c6x/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -121,6 +121,7 @@ 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-3.16-gnu/arch/c6x/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/c6x/kernel/signal.c
--- linux-libre-3.16-gnu/arch/c6x/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/c6x/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -127,17 +127,11 @@ static int setup_sigcontext(struct sigco
 	return err;
 }
 
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
 					struct pt_regs *regs,
 					unsigned long framesize)
 {
-	unsigned long sp = regs->sp;
-
-	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	unsigned long sp = sigsp(regs->sp, ksig);
 
 	/*
 	 * No matter what happens, 'sp' must be dword
@@ -146,21 +140,21 @@ static inline void __user *get_sigframe(
 	return (void __user *)((sp - framesize) & ~7);
 }
 
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	unsigned long __user *retcode;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto segv_and_exit;
+		return -EFAULT;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Clear all the bits of the ucontext we don't use.  */
 	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -188,7 +182,7 @@ static int setup_rt_frame(int signr, str
 #undef COPY
 
 	if (err)
-		goto segv_and_exit;
+		return -EFAULT;
 
 	flush_icache_range((unsigned long) &frame->retcode,
 			   (unsigned long) &frame->retcode + RETCODE_SIZE);
@@ -198,10 +192,10 @@ static int setup_rt_frame(int signr, str
 	/* Change user context to branch to signal handler */
 	regs->sp = (unsigned long) frame - 8;
 	regs->b3 = (unsigned long) retcode;
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 
 	/* Give the signal number to the handler */
-	regs->a4 = signr;
+	regs->a4 = ksig->sig;
 
 	/*
 	 * For realtime signals we must also set the second and third
@@ -212,10 +206,6 @@ static int setup_rt_frame(int signr, str
 	regs->a6 = (unsigned long)&frame->uc;
 
 	return 0;
-
-segv_and_exit:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
 static inline void
@@ -245,10 +235,11 @@ do_restart:
 /*
  * handle the actual delivery of a signal to userspace
  */
-static void handle_signal(int sig,
-			 siginfo_t *info, struct k_sigaction *ka,
-			 struct pt_regs *regs, int syscall)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
+			  int syscall)
 {
+	int ret;
+
 	/* Are we from a system call? */
 	if (syscall) {
 		/* If so, check system call restarting.. */
@@ -259,7 +250,7 @@ static void handle_signal(int sig,
 			break;
 
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->a4 = -EINTR;
 				break;
 			}
@@ -272,9 +263,8 @@ static void handle_signal(int sig,
 	}
 
 	/* Set up the stack frame */
-	if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
-		return;
-	signal_delivered(sig, info, ka, regs, 0);
+	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -282,18 +272,15 @@ static void handle_signal(int sig,
  */
 static void do_signal(struct pt_regs *regs, int syscall)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 
 	/* we want the common case to go fast, which is why we may in certain
 	 * cases get here from kernel mode */
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &info, &ka, regs, syscall);
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig, regs, syscall);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/cris/arch-v10/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/cris/arch-v10/kernel/signal.c
--- linux-libre-3.16-gnu/arch/cris/arch-v10/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/cris/arch-v10/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,15 +203,9 @@ static int setup_sigcontext(struct sigco
  * - usually on the stack. */
 
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
 {
-	unsigned long sp = rdusp();
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! on_sig_stack(sp))
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
+	unsigned long sp = sigsp(rdusp(), ksig);
 
 	/* make sure the frame is dword-aligned */
 
@@ -228,33 +222,33 @@ get_sigframe(struct k_sigaction *ka, str
  * user-mode trampoline.
  */
 
-static int setup_frame(int sig, struct k_sigaction *ka,
-		       sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+		       struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
 	unsigned long return_ip;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (_NSIG_WORDS > 1) {
 		err |= __copy_to_user(frame->extramask, &set->sig[1],
 				      sizeof(frame->extramask));
 	}
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		return_ip = (unsigned long)ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
 	} else {
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
@@ -265,42 +259,38 @@ static int setup_frame(int sig, struct k
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 
-	regs->irp = (unsigned long) ka->sa.sa_handler;  /* what we enter NOW   */
+	regs->irp = (unsigned long) ksig->ka.sa.sa_handler;  /* what we enter NOW   */
 	regs->srp = return_ip;                          /* what we enter LATER */
-	regs->r10 = sig;                                /* first argument is signo */
+	regs->r10 = ksig->sig;                                /* first argument is signo */
 
 	/* actually move the usp to reflect the stacked frame */
 
 	wrusp((unsigned long)frame);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	unsigned long return_ip;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Clear all the bits of the ucontext we don't use.  */
         err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -312,12 +302,12 @@ static int setup_rt_frame(int sig, struc
 	err |= __save_altstack(&frame->uc.uc_stack, rdusp());
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		return_ip = (unsigned long)ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
 	} else {
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
@@ -329,18 +319,18 @@ static int setup_rt_frame(int sig, struc
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* TODO what is the current->exec_domain stuff and invmap ? */
 
 	/* Set up registers for signal handler */
 
 	/* What we enter NOW   */
-	regs->irp = (unsigned long) ka->sa.sa_handler;
+	regs->irp = (unsigned long) ksig->ka.sa.sa_handler;
 	/* What we enter LATER */
 	regs->srp = return_ip;
 	/* First argument is signo */
-	regs->r10 = sig;
+	regs->r10 = ksig->sig;
 	/* Second argument is (siginfo_t *) */
 	regs->r11 = (unsigned long)&frame->info;
 	/* Third argument is unused */
@@ -350,19 +340,14 @@ static int setup_rt_frame(int sig, struc
 	wrusp((unsigned long)frame);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static inline void handle_signal(int canrestart, unsigned long sig,
-	siginfo_t *info, struct k_sigaction *ka,
-	struct pt_regs *regs)
+static inline void handle_signal(int canrestart, struct ksignal *ksig,
+				 struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -383,7 +368,7 @@ static inline void handle_signal(int can
 			/* ERESTARTSYS means to restart the syscall if
 			 * there is no handler or the handler was
 			 * registered with SA_RESTART */
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->r10 = -EINTR;
 				break;
 			}
@@ -396,13 +381,12 @@ static inline void handle_signal(int can
 	}
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(ksig, oldset, regs);
 
-	if (ret == 0)
-		signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -419,9 +403,7 @@ static inline void handle_signal(int can
 
 void do_signal(int canrestart, struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-        struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which
@@ -432,10 +414,9 @@ void do_signal(int canrestart, struct pt
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(canrestart, signr, &info, &ka, regs);
+		handle_signal(canrestart, &ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/cris/arch-v32/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/cris/arch-v32/kernel/signal.c
--- linux-libre-3.16-gnu/arch/cris/arch-v32/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/cris/arch-v32/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -189,17 +189,9 @@ setup_sigcontext(struct sigcontext __use
 
 /* Figure out where to put the new signal frame - usually on the stack. */
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
 {
-	unsigned long sp;
-
-	sp = rdusp();
-
-	/* This is the X/Open sanctioned signal stack switching. */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(sp))
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
+	unsigned long sp = sigsp(rdusp(), ksig);
 
 	/* Make sure the frame is dword-aligned. */
 	sp &= ~3;
@@ -215,23 +207,22 @@ get_sigframe(struct k_sigaction *ka, str
  * trampoline.
   */
 static int
-setup_frame(int sig, struct k_sigaction *ka,  sigset_t *set,
-	    struct pt_regs * regs)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	int err;
 	unsigned long return_ip;
 	struct signal_frame __user *frame;
 
 	err = 0;
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (_NSIG_WORDS > 1) {
 		err |= __copy_to_user(frame->extramask, &set->sig[1],
@@ -239,14 +230,14 @@ setup_frame(int sig, struct k_sigaction
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Set up to return from user-space. If provided, use a stub
 	 * already located in user-space.
 	 */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		return_ip = (unsigned long)ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
 	} else {
 		/* Trampoline - the desired return ip is in the signal return page. */
 		return_ip = cris_signal_return_page;
@@ -264,7 +255,7 @@ setup_frame(int sig, struct k_sigaction
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Set up registers for signal handler.
@@ -273,42 +264,37 @@ setup_frame(int sig, struct k_sigaction
 	 * Where the code enter later.
 	 * First argument, signo.
 	 */
-	regs->erp = (unsigned long) ka->sa.sa_handler;
+	regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
 	regs->srp = return_ip;
-	regs->r10 = sig;
+	regs->r10 = ksig->sig;
 
 	/* Actually move the USP to reflect the stacked frame. */
 	wrusp((unsigned long)frame);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs * regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	int err;
 	unsigned long return_ip;
 	struct rt_signal_frame __user *frame;
 
 	err = 0;
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* TODO: what is the current->exec_domain stuff and invmap ? */
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Clear all the bits of the ucontext we don't use.  */
 	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -317,14 +303,14 @@ setup_rt_frame(int sig, struct k_sigacti
 	err |= __save_altstack(&frame->uc.uc_stack, rdusp());
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Set up to return from user-space. If provided, use a stub
 	 * already located in user-space.
 	 */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		return_ip = (unsigned long) ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long) ksig->ka.sa.sa_restorer;
 	} else {
 		/* Trampoline - the desired return ip is in the signal return page. */
 		return_ip = cris_signal_return_page + 6;
@@ -345,7 +331,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Set up registers for signal handler.
@@ -356,9 +342,9 @@ setup_rt_frame(int sig, struct k_sigacti
 	 * Second argument is (siginfo_t *).
 	 * Third argument is unused.
 	 */
-	regs->erp = (unsigned long) ka->sa.sa_handler;
+	regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
 	regs->srp = return_ip;
-	regs->r10 = sig;
+	regs->r10 = ksig->sig;
 	regs->r11 = (unsigned long) &frame->info;
 	regs->r12 = 0;
 
@@ -366,17 +352,11 @@ setup_rt_frame(int sig, struct k_sigacti
 	wrusp((unsigned long)frame);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /* Invoke a signal handler to, well, handle the signal. */
 static inline void
-handle_signal(int canrestart, unsigned long sig,
-	      siginfo_t *info, struct k_sigaction *ka,
-              struct pt_regs * regs)
+handle_signal(int canrestart, struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -404,7 +384,7 @@ handle_signal(int canrestart, unsigned l
                                  * there is no handler, or the handler
                                  * was registered with SA_RESTART.
 				 */
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
+				if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 					regs->r10 = -EINTR;
 					break;
 				}
@@ -423,13 +403,12 @@ handle_signal(int canrestart, unsigned l
         }
 
 	/* Set up the stack frame. */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(ksig, oldset, regs);
 
-	if (ret == 0)
-		signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -446,9 +425,7 @@ handle_signal(int canrestart, unsigned l
 void
 do_signal(int canrestart, struct pt_regs *regs)
 {
-	int signr;
-	siginfo_t info;
-        struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * The common case should go fast, which is why this point is
@@ -458,11 +435,9 @@ do_signal(int canrestart, struct pt_regs
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(canrestart, signr, &info, &ka, regs);
+		handle_signal(canrestart, &ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/cris/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/cris/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/cris/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/cris/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@ generic-y += linkage.h
 generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/cris/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/cris/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/cris/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/cris/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,7 @@ 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-3.16-gnu/arch/cris/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/cris/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/cris/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/cris/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ASM_CRIS_SCATTERLIST_H
-#define __ASM_CRIS_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(__ASM_CRIS_SCATTERLIST_H) */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/frv/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/frv/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/frv/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/frv/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -5,4 +5,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/frv/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/frv/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/frv/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/frv/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -129,7 +129,8 @@ unsigned long get_wchan(struct task_stru
 #define	KSTK_EIP(tsk)	((tsk)->thread.frame0->pc)
 #define	KSTK_ESP(tsk)	((tsk)->thread.frame0->sp)
 
-#define cpu_relax()    barrier()
+#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
 
 /* data cache prefetch */
 #define ARCH_HAS_PREFETCH
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/frv/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/frv/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/frv/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/frv/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !_ASM_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/frv/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/frv/kernel/signal.c
--- linux-libre-3.16-gnu/arch/frv/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/frv/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigco
 /*
  * Determine which stack to use..
  */
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
 					size_t frame_size)
 {
-	unsigned long sp;
-
-	/* Default to using normal stack */
-	sp = __frame->sp;
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! sas_ss_flags(sp))
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
+	unsigned long sp = sigsp(__frame->sp, ksig);
 
 	return (void __user *) ((sp - frame_size) & ~7UL);
 
@@ -180,17 +171,17 @@ static inline void __user *get_sigframe(
 /*
  *
  */
-static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
+static int setup_frame(struct ksignal *ksig, sigset_t *set)
 {
 	struct sigframe __user *frame;
-	int rsig;
+	int rsig, sig = ksig->sig;
 
 	set_fs(USER_DS);
 
-	frame = get_sigframe(ka, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	rsig = sig;
 	if (sig < 32 &&
@@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k
 		rsig = __current_thread_info->exec_domain->signal_invmap[sig];
 
 	if (__put_user(rsig, &frame->sig) < 0)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (setup_sigcontext(&frame->sc, set->sig[0]))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (_NSIG_WORDS > 1) {
 		if (__copy_to_user(frame->extramask, &set->sig[1],
 				   sizeof(frame->extramask)))
-			goto give_sigsegv;
+			return -EFAULT;
 	}
 
 	/* Set up to return from userspace.  If provided, use a stub
 	 * already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
-			goto give_sigsegv;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode) < 0)
+			return -EFAULT;
 	}
 	else {
 		/* Set up the following code on the stack:
@@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k
 		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
-			goto give_sigsegv;
+			return -EFAULT;
 
 		flush_icache_range((unsigned long) frame->retcode,
 				   (unsigned long) (frame->retcode + 2));
@@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k
 	/* Set up registers for the signal handler */
 	if (current->personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
 		struct fdpic_func_descriptor desc;
 		if (copy_from_user(&desc, funcptr, sizeof(desc)))
-			goto give_sigsegv;
+			return -EFAULT;
 		__frame->pc = desc.text;
 		__frame->gr15 = desc.GOT;
 	} else {
-		__frame->pc   = (unsigned long) ka->sa.sa_handler;
+		__frame->pc   = (unsigned long) ksig->ka.sa.sa_handler;
 		__frame->gr15 = 0;
 	}
 
@@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
-
 } /* end setup_frame() */
 
 /*****************************************************************************/
 /*
  *
  */
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set)
 {
 	struct rt_sigframe __user *frame;
-	int rsig;
+	int rsig, sig = ksig->sig;
 
 	set_fs(USER_DS);
 
-	frame = get_sigframe(ka, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	rsig = sig;
 	if (sig < 32 &&
@@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struc
 	if (__put_user(rsig,		&frame->sig) ||
 	    __put_user(&frame->info,	&frame->pinfo) ||
 	    __put_user(&frame->uc,	&frame->puc))
-		goto give_sigsegv;
+		return -EFAULT;
 
-	if (copy_siginfo_to_user(&frame->info, info))
-		goto give_sigsegv;
+	if (copy_siginfo_to_user(&frame->info, &ksig->info))
+		return -EFAULT;
 
 	/* Create the ucontext.  */
 	if (__put_user(0, &frame->uc.uc_flags) ||
 	    __put_user(NULL, &frame->uc.uc_link) ||
 	    __save_altstack(&frame->uc.uc_stack, __frame->sp))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	 * already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
-			goto give_sigsegv;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+			return -EFAULT;
 	}
 	else {
 		/* Set up the following code on the stack:
@@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struc
 		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
-			goto give_sigsegv;
+			return -EFAULT;
 
 		flush_icache_range((unsigned long) frame->retcode,
 				   (unsigned long) (frame->retcode + 2));
@@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struc
 	/* Set up registers for signal handler */
 	if (current->personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
 		struct fdpic_func_descriptor desc;
 		if (copy_from_user(&desc, funcptr, sizeof(desc)))
-			goto give_sigsegv;
+			return -EFAULT;
 		__frame->pc = desc.text;
 		__frame->gr15 = desc.GOT;
 	} else {
-		__frame->pc   = (unsigned long) ka->sa.sa_handler;
+		__frame->pc   = (unsigned long) ksig->ka.sa.sa_handler;
 		__frame->gr15 = 0;
 	}
 
@@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struc
 	       sig, current->comm, current->pid, frame, __frame->pc,
 	       frame->pretcode);
 #endif
-
 	return 0;
 
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
-
 } /* end setup_rt_frame() */
 
 /*****************************************************************************/
 /*
  * OK, we're invoking a handler
  */
-static void handle_signal(unsigned long sig, siginfo_t *info,
-			 struct k_sigaction *ka)
+static void handle_signal(struct ksignal *ksig)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -378,7 +357,7 @@ static void handle_signal(unsigned long
 			break;
 
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				__frame->gr8 = -EINTR;
 				break;
 			}
@@ -392,16 +371,12 @@ static void handle_signal(unsigned long
 	}
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset);
 	else
-		ret = setup_frame(sig, ka, oldset);
-
-	if (ret)
-		return;
+		ret = setup_frame(ksig, oldset);
 
-	signal_delivered(sig, info, ka, __frame,
-				 test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 } /* end handle_signal() */
 
 /*****************************************************************************/
@@ -412,13 +387,10 @@ static void handle_signal(unsigned long
  */
 static void do_signal(void)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 
-	signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &info, &ka);
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/hexagon/include/asm/cache.h linux-libre-3.17-rc7-gnu/arch/hexagon/include/asm/cache.h
--- linux-libre-3.16-gnu/arch/hexagon/include/asm/cache.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/hexagon/include/asm/cache.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 #define __cacheline_aligned	__aligned(L1_CACHE_BYTES)
 #define ____cacheline_aligned	__aligned(L1_CACHE_BYTES)
 
-/* See http://kerneltrap.org/node/15100  */
+/* See http://lwn.net/Articles/262554/ */
 #define __read_mostly
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/hexagon/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/hexagon/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/hexagon/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/hexagon/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,7 @@ 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-3.16-gnu/arch/hexagon/Kconfig linux-libre-3.17-rc7-gnu/arch/hexagon/Kconfig
--- linux-libre-3.16-gnu/arch/hexagon/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/hexagon/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@ config HEXAGON
 	select GENERIC_IOMAP
 	select GENERIC_SMP_IDLE_THREAD
 	select STACKTRACE_SUPPORT
-	select KTIME_SCALAR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select MODULES_USE_ELF_RELA
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/hexagon/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/hexagon/kernel/signal.c
--- linux-libre-3.16-gnu/arch/hexagon/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/hexagon/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,18 +36,10 @@ struct rt_sigframe {
 	struct ucontext uc;
 };
 
-static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
 			  size_t frame_size)
 {
-	unsigned long sp = regs->r29;
-
-	/* check if we would overflow the alt stack */
-	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
-		return (void __user __force *)-1UL;
-
-	/* Switch to signal stack if appropriate */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	unsigned long sp = sigsp(regs->r29, ksig);
 
 	return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
 }
@@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_
 /*
  * Setup signal stack frame with siginfo structure
  */
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set,  struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	int err = 0;
 	struct rt_sigframe __user *frame;
 	struct hexagon_vdso *vdso = current->mm->context.vdso;
 
-	frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+	frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
-		goto	sigsegv;
+		return -EFAULT;
 
-	if (copy_siginfo_to_user(&frame->info, info))
-		goto	sigsegv;
+	if (copy_siginfo_to_user(&frame->info, &ksig->info))
+		return -EFAULT;
 
 	/* The on-stack signal trampoline is no longer executed;
 	 * however, the libgcc signal frame unwinding code checks for
@@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, str
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
 	if (err)
-		goto sigsegv;
+		return -EFAULT;
 
 	/* Load r0/r1 pair with signumber/siginfo pointer... */
 	regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
-		| (unsigned long long)signr;
+		| (unsigned long long)ksig->sig;
 	regs->r02 = (unsigned long) &frame->uc;
 	regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
 	pt_psp(regs) = (unsigned long) frame;
-	pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+	pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
 
 	return 0;
-
-sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
 /*
  * Setup invocation of signal handler
  */
-static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
-			 struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
+	int ret;
+
 	/*
 	 * If we're handling a signal that aborted a system call,
 	 * set up the error return value before adding the signal
@@ -173,7 +162,7 @@ static void handle_signal(int sig, sigin
 			regs->r00 = -EINTR;
 			break;
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->r00 = -EINTR;
 				break;
 			}
@@ -193,11 +182,9 @@ static void handle_signal(int sig, sigin
 	 * only set up the rt_frame flavor.
 	 */
 	/* If there was an error on setup, no signal was delivered. */
-	if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
-		return;
+	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
 
-	signal_delivered(sig, info, ka, regs,
-			test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -205,17 +192,13 @@ static void handle_signal(int sig, sigin
  */
 void do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction sigact;
-	siginfo_t info;
-	int signo;
+	struct ksignal ksig;
 
 	if (!user_mode(regs))
 		return;
 
-	signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
-
-	if (signo > 0) {
-		handle_signal(signo, &info, &sigact, regs);
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/hexagon/mm/cache.c linux-libre-3.17-rc7-gnu/arch/hexagon/mm/cache.c
--- linux-libre-3.16-gnu/arch/hexagon/mm/cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/hexagon/mm/cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,7 @@ void flush_icache_range(unsigned long st
 	);
 	local_irq_restore(flags);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/bigsur_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/bigsur_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/bigsur_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/bigsur_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=16
@@ -6,6 +5,8 @@ CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_SGI_PARTITION=y
 CONFIG_IA64_DIG=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
@@ -51,9 +52,6 @@ CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_NET_PCI=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -85,7 +83,6 @@ CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
@@ -95,17 +92,13 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFSD=m
 CONFIG_NFSD_V4=y
 CONFIG_CIFS=m
 CONFIG_CIFS_STATS=y
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/generic_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/generic_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/generic_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/generic_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
@@ -6,13 +5,13 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=20
 CONFIG_CGROUPS=y
 CONFIG_CPUSETS=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_SGI_PARTITION=y
 CONFIG_MCKINLEY=y
 CONFIG_IA64_PAGE_SIZE_64KB=y
 CONFIG_IA64_CYCLONE=y
@@ -29,14 +28,13 @@ CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_DOCK=y
 CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-CONFIG_ARPD=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -82,16 +80,13 @@ CONFIG_FUSION_FC=m
 CONFIG_FUSION_SAS=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_NET_ETHERNET=y
+CONFIG_NETCONSOLE=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
-CONFIG_NET_PCI=y
-CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_IGB=y
-CONFIG_TIGON3=y
-CONFIG_NETCONSOLE=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_GAMEPORT=m
 CONFIG_SERIAL_NONSTANDARD=y
@@ -151,6 +146,7 @@ CONFIG_USB_STORAGE=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INTEL_IOMMU=y
 CONFIG_MSPEC=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
@@ -164,7 +160,6 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
@@ -175,16 +170,10 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFSD=m
 CONFIG_NFSD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
@@ -225,11 +214,7 @@ CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
-CONFIG_INTEL_IOMMU=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/gensparse_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/gensparse_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/gensparse_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/gensparse_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
@@ -9,6 +8,8 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_SGI_PARTITION=y
 CONFIG_MCKINLEY=y
 CONFIG_IA64_CYCLONE=y
 CONFIG_SMP=y
@@ -24,14 +25,12 @@ CONFIG_BINFMT_MISC=m
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-CONFIG_ARPD=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
 CONFIG_BLK_DEV_LOOP=m
@@ -71,15 +70,12 @@ CONFIG_FUSION_SPI=y
 CONFIG_FUSION_FC=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_NET_ETHERNET=y
+CONFIG_NETCONSOLE=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
-CONFIG_NET_PCI=y
-CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
-CONFIG_TIGON3=y
-CONFIG_NETCONSOLE=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_GAMEPORT=m
 CONFIG_SERIAL_NONSTANDARD=y
@@ -146,7 +142,6 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
@@ -157,16 +152,10 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFSD=m
 CONFIG_NFSD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/sim_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/sim_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/sim_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/sim_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,12 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_IA64_HP_SIM=y
 CONFIG_MCKINLEY=y
 CONFIG_IA64_PAGE_SIZE_64KB=y
@@ -27,7 +26,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=y
@@ -49,8 +47,6 @@ CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
+CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_INFO=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/tiger_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/tiger_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/tiger_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/tiger_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
@@ -11,6 +10,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_SGI_PARTITION=y
 CONFIG_IA64_DIG=y
 CONFIG_MCKINLEY=y
 CONFIG_IA64_PAGE_SIZE_64KB=y
@@ -29,14 +30,12 @@ CONFIG_BINFMT_MISC=m
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=m
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-CONFIG_ARPD=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
 CONFIG_BLK_DEV_LOOP=m
@@ -53,6 +52,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_QLOGIC_1280=y
 CONFIG_MD=y
@@ -72,15 +72,12 @@ CONFIG_FUSION_FC=y
 CONFIG_FUSION_CTL=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_NET_ETHERNET=y
+CONFIG_NETCONSOLE=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
-CONFIG_NET_PCI=y
-CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
-CONFIG_TIGON3=y
-CONFIG_NETCONSOLE=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_GAMEPORT=m
 CONFIG_SERIAL_NONSTANDARD=y
@@ -118,7 +115,6 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
@@ -129,16 +125,10 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFSD=m
 CONFIG_NFSD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
@@ -180,6 +170,5 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_IA64_GRANULE_16MB=y
-CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD5=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/configs/zx1_defconfig linux-libre-3.17-rc7-gnu/arch/ia64/configs/zx1_defconfig
--- linux-libre-3.16-gnu/arch/ia64/configs/zx1_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/configs/zx1_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,9 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_IA64_HP_ZX1=y
 CONFIG_MCKINLEY=y
 CONFIG_SMP=y
@@ -18,6 +18,7 @@ CONFIG_EFI_VARS=y
 CONFIG_BINFMT_MISC=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -37,9 +38,9 @@ CONFIG_CHR_DEV_OSST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_QLOGIC_1280=y
 CONFIG_FUSION=y
@@ -48,18 +49,15 @@ CONFIG_FUSION_FC=y
 CONFIG_FUSION_CTL=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=y
 CONFIG_TULIP_MWI=y
 CONFIG_TULIP_MMIO=y
 CONFIG_TULIP_NAPI=y
 CONFIG_TULIP_NAPI_HW_MITIGATION=y
-CONFIG_NET_PCI=y
-CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=y
 CONFIG_E1000=y
-CONFIG_TIGON3=y
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
@@ -100,7 +98,6 @@ CONFIG_USB_STORAGE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
-CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=y
@@ -110,12 +107,9 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=y
 CONFIG_NLS_CODEPAGE_775=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/acenv.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/acenv.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/acenv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/acenv.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,6 @@
 
 /* Asm macros */
 
-#ifdef CONFIG_ACPI
-
 static inline int
 ia64_acpi_acquire_global_lock(unsigned int *lock)
 {
@@ -51,6 +49,4 @@ ia64_acpi_release_global_lock(unsigned i
 #define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq)				\
 	((Acq) = ia64_acpi_release_global_lock(&facs->global_lock))
 
-#endif
-
 #endif /* _ASM_IA64_ACENV_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/acpi.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/acpi.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/acpi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/acpi.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,11 @@ extern int acpi_lapic;
 #define acpi_noirq 0	/* ACPI always enabled on IA64 */
 #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
 #define acpi_strict 1	/* no ACPI spec workarounds on IA64 */
+
+static inline bool acpi_has_cpu_in_madt(void)
+{
+	return !!acpi_lapic;
+}
 #endif
 #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
 static inline void disable_acpi(void) { }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/io.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/io.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/io.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/io.h	2014-09-28 17:29:07.000000000 -0400
@@ -426,6 +426,7 @@ extern void iounmap (volatile void __iom
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
 #define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
+#define early_memunmap(addr, size)             early_iounmap(addr, size)
 static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
 {
 	return ioremap(phys_addr, size);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/ia64/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -5,5 +5,6 @@ generic-y += hash.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vtime.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/page.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -231,4 +231,6 @@ get_order (unsigned long size)
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 #define LOAD_OFFSET		(KERNEL_START - KERNEL_TR_PAGE_SIZE)
 
+#define __HAVE_ARCH_GATE_AREA	1
+
 #endif /* _ASM_IA64_PAGE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -548,6 +548,7 @@ 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-3.16-gnu/arch/ia64/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _ASM_IA64_SCATTERLIST_H
-#define _ASM_IA64_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_IA64_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/ia64/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls			315 /* length of syscall table */
+#define NR_syscalls			317 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/ia64/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/ia64/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -328,5 +328,7 @@
 #define __NR_sched_setattr		1336
 #define __NR_sched_getattr		1337
 #define __NR_renameat2			1338
+#define __NR_getrandom			1339
+#define __NR_memfd_create		1340
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/Kconfig linux-libre-3.17-rc7-gnu/arch/ia64/Kconfig
--- linux-libre-3.16-gnu/arch/ia64/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@ config IA64
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select PCI if (!IA64_HP_SIM)
 	select ACPI if (!IA64_HP_SIM)
+	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
 	select PM if (!IA64_HP_SIM)
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
@@ -27,6 +28,7 @@ config IA64
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_VIRT_CPU_ACCOUNTING
+	select ARCH_HAS_SG_CHAIN
 	select VIRT_TO_BUS
 	select ARCH_DISCARD_MEMBLOCK
 	select GENERIC_IRQ_PROBE
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kernel/entry.S linux-libre-3.17-rc7-gnu/arch/ia64/kernel/entry.S
--- linux-libre-3.16-gnu/arch/ia64/kernel/entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kernel/entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -1776,6 +1776,8 @@ sys_call_table:
 	data8 sys_sched_setattr
 	data8 sys_sched_getattr
 	data8 sys_renameat2
+	data8 sys_getrandom
+	data8 sys_memfd_create			// 1340
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kernel/process.c linux-libre-3.17-rc7-gnu/arch/ia64/kernel/process.c
--- linux-libre-3.16-gnu/arch/ia64/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -662,7 +662,7 @@ void
 machine_restart (char *restart_cmd)
 {
 	(void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
-	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
+	efi_reboot(REBOOT_WARM, NULL);
 }
 
 void
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/ia64/kernel/signal.c
--- linux-libre-3.16-gnu/arch/ia64/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -309,12 +309,11 @@ force_sigsegv_info (int sig, void __user
 	si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
 	si.si_addr = addr;
 	force_sig_info(SIGSEGV, &si, current);
-	return 0;
+	return 1;
 }
 
 static long
-setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
-	     struct sigscratch *scr)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
 {
 	extern char __kernel_sigtramp[];
 	unsigned long tramp_addr, new_rbs = 0, new_sp;
@@ -323,7 +322,7 @@ setup_frame (int sig, struct k_sigaction
 
 	new_sp = scr->pt.r12;
 	tramp_addr = (unsigned long) __kernel_sigtramp;
-	if (ka->sa.sa_flags & SA_ONSTACK) {
+	if (ksig->ka.sa.sa_flags & SA_ONSTACK) {
 		int onstack = sas_ss_flags(new_sp);
 
 		if (onstack == 0) {
@@ -347,29 +346,29 @@ setup_frame (int sig, struct k_sigaction
 			 */
 			check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
 			if (!likely(on_sig_stack(check_sp)))
-				return force_sigsegv_info(sig, (void __user *)
+				return force_sigsegv_info(ksig->sig, (void __user *)
 							  check_sp);
 		}
 	}
 	frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return force_sigsegv_info(sig, frame);
+		return force_sigsegv_info(ksig->sig, frame);
 
-	err  = __put_user(sig, &frame->arg0);
+	err  = __put_user(ksig->sig, &frame->arg0);
 	err |= __put_user(&frame->info, &frame->arg1);
 	err |= __put_user(&frame->sc, &frame->arg2);
 	err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
 	err |= __put_user(0, &frame->sc.sc_loadrs);	/* initialize to zero */
-	err |= __put_user(ka->sa.sa_handler, &frame->handler);
+	err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler);
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
 	err |= setup_sigcontext(&frame->sc, set, scr);
 
 	if (unlikely(err))
-		return force_sigsegv_info(sig, frame);
+		return force_sigsegv_info(ksig->sig, frame);
 
 	scr->pt.r12 = (unsigned long) frame - 16;	/* new stack pointer */
 	scr->pt.ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
@@ -394,22 +393,20 @@ setup_frame (int sig, struct k_sigaction
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n",
-	       current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
+	       current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
 #endif
-	return 1;
+	return 0;
 }
 
 static long
-handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	       struct sigscratch *scr)
+handle_signal (struct ksignal *ksig, struct sigscratch *scr)
 {
-	if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
-		return 0;
+	int ret = setup_frame(ksig, sigmask_to_save(), scr);
 
-	signal_delivered(sig, info, ka, &scr->pt,
-				 test_thread_flag(TIF_SINGLESTEP));
+	if (!ret)
+		signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 
-	return 1;
+	return ret;
 }
 
 /*
@@ -419,17 +416,16 @@ handle_signal (unsigned long sig, struct
 void
 ia64_do_signal (struct sigscratch *scr, long in_syscall)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
 	long restart = in_syscall;
 	long errno = scr->pt.r8;
+	struct ksignal ksig;
 
 	/*
 	 * This only loops in the rare cases of handle_signal() failing, in which case we
 	 * need to push through a forced SIGSEGV.
 	 */
 	while (1) {
-		int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL);
+		get_signal(&ksig);
 
 		/*
 		 * get_signal_to_deliver() may have run a debugger (via notify_parent())
@@ -446,7 +442,7 @@ ia64_do_signal (struct sigscratch *scr,
 			 */
 			restart = 0;
 
-		if (signr <= 0)
+		if (ksig.sig <= 0)
 			break;
 
 		if (unlikely(restart)) {
@@ -458,7 +454,7 @@ ia64_do_signal (struct sigscratch *scr,
 				break;
 
 			      case ERESTARTSYS:
-				if ((ka.sa.sa_flags & SA_RESTART) == 0) {
+				if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
 					scr->pt.r8 = EINTR;
 					/* note: scr->pt.r10 is already -1 */
 					break;
@@ -473,7 +469,7 @@ ia64_do_signal (struct sigscratch *scr,
 		 * Whee!  Actually deliver the signal.  If the delivery failed, we need to
 		 * continue to iterate in this loop so we can deliver the SIGSEGV...
 		 */
-		if (handle_signal(signr, &ka, &info, scr))
+		if (handle_signal(&ksig, scr))
 			return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kernel/time.c linux-libre-3.17-rc7-gnu/arch/ia64/kernel/time.c
--- linux-libre-3.16-gnu/arch/ia64/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -384,21 +384,6 @@ static struct irqaction timer_irqaction
 	.name =		"timer"
 };
 
-static struct platform_device rtc_efi_dev = {
-	.name = "rtc-efi",
-	.id = -1,
-};
-
-static int __init rtc_init(void)
-{
-	if (platform_device_register(&rtc_efi_dev) < 0)
-		printk(KERN_ERR "unable to register rtc device...\n");
-
-	/* not necessarily an error */
-	return 0;
-}
-module_init(rtc_init);
-
 void read_persistent_clock(struct timespec *ts)
 {
 	efi_gettimeofday(ts);
@@ -441,7 +426,7 @@ void update_vsyscall_tz(void)
 }
 
 void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
-			struct clocksource *c, u32 mult)
+			 struct clocksource *c, u32 mult, cycle_t cycle_last)
 {
 	write_seqcount_begin(&fsyscall_gtod_data.seq);
 
@@ -450,7 +435,7 @@ void update_vsyscall_old(struct timespec
         fsyscall_gtod_data.clk_mult = mult;
         fsyscall_gtod_data.clk_shift = c->shift;
         fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
-        fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
+        fsyscall_gtod_data.clk_cycle_last = cycle_last;
 
 	/* copy kernel time structures */
         fsyscall_gtod_data.wall_time.tv_sec = wall->tv_sec;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kvm/Kconfig linux-libre-3.17-rc7-gnu/arch/ia64/kvm/Kconfig
--- linux-libre-3.16-gnu/arch/ia64/kvm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kvm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@ config KVM
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	select HAVE_KVM_IRQCHIP
+	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQ_ROUTING
 	select KVM_APIC_ARCHITECTURE
 	select KVM_MMIO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/kvm/kvm-ia64.c linux-libre-3.17-rc7-gnu/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-3.16-gnu/arch/ia64/kvm/kvm-ia64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/kvm/kvm-ia64.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,7 +190,7 @@ void kvm_arch_check_processor_compat(voi
 	*(int *)rtn = 0;
 }
 
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 
 	int r;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/Makefile linux-libre-3.17-rc7-gnu/arch/ia64/Makefile
--- linux-libre-3.16-gnu/arch/ia64/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ vmlinux.gz: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
 
 unwcheck: vmlinux
-	-$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $<
+	-$(Q)READELF=$(READELF) $(PYTHON) $(srctree)/arch/ia64/scripts/unwcheck.py $<
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/mm/init.c linux-libre-3.17-rc7-gnu/arch/ia64/mm/init.c
--- linux-libre-3.16-gnu/arch/ia64/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -278,6 +278,37 @@ setup_gate (void)
 	ia64_patch_gate();
 }
 
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+
+	return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return &gate_vma;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+		return 1;
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return in_gate_area_no_mm(addr);
+}
+
 void ia64_mmu_init(void *my_cpu_data)
 {
 	unsigned long pta, impl_va_bits;
@@ -631,7 +662,8 @@ int arch_add_memory(int nid, u64 start,
 
 	pgdat = NODE_DATA(nid);
 
-	zone = pgdat->node_zones + ZONE_NORMAL;
+	zone = pgdat->node_zones +
+		zone_for_memory(nid, start, size, ZONE_NORMAL);
 	ret = __add_pages(nid, zone, start_pfn, nr_pages);
 
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/pci/fixup.c linux-libre-3.17-rc7-gnu/arch/ia64/pci/fixup.c
--- linux-libre-3.16-gnu/arch/ia64/pci/fixup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/pci/fixup.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/vgaarb.h>
+#include <linux/screen_info.h>
 
 #include <asm/machvec.h>
 
@@ -61,8 +62,7 @@ static void pci_fixup_video(struct pci_d
 		pci_read_config_word(pdev, PCI_COMMAND, &config);
 		if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 			pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-			dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
-			vga_set_default_device(pdev);
+			dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
 		}
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/sn/kernel/bte.c linux-libre-3.17-rc7-gnu/arch/ia64/sn/kernel/bte.c
--- linux-libre-3.16-gnu/arch/ia64/sn/kernel/bte.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/sn/kernel/bte.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,7 @@ bte_result_t bte_copy(u64 src, u64 dest,
 		if (mode & BTE_USE_ANY) {
 			nasid_to_try[1] = my_nasid;
 		} else {
-			nasid_to_try[1] = (int)NULL;
+			nasid_to_try[1] = 0;
 		}
 	} else {
 		/* try local then remote */
@@ -122,7 +122,7 @@ bte_result_t bte_copy(u64 src, u64 dest,
 		if (mode & BTE_USE_ANY) {
 			nasid_to_try[1] = NASID_GET(dest);
 		} else {
-			nasid_to_try[1] = (int)NULL;
+			nasid_to_try[1] = 0;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/ia64/sn/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/ia64/sn/kernel/setup.c
--- linux-libre-3.16-gnu/arch/ia64/sn/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/ia64/sn/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -579,7 +579,7 @@ void sn_cpu_init(void)
 		       (sn_prom_type == 1) ? "real" : "fake");
 	}
 
-	memset(pda, 0, sizeof(pda));
+	memset(pda, 0, sizeof(*pda));
 	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
 				&sn_hub_info->nasid_bitmask,
 				&sn_hub_info->nasid_shift,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/Kconfig linux-libre-3.17-rc7-gnu/arch/Kconfig
--- linux-libre-3.16-gnu/arch/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -321,6 +321,7 @@ config HAVE_ARCH_SECCOMP_FILTER
 	  - secure_computing is called from a ptrace_event()-safe context
 	  - secure_computing return value is checked and a return value of -1
 	    results in the system call being skipped immediately.
+	  - seccomp syscall wired up
 
 config SECCOMP_FILTER
 	def_bool y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m32r/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/m32r/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -6,4 +6,5 @@ generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m32r/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/m32r/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -133,5 +133,6 @@ 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-3.16-gnu/arch/m32r/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/m32r/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m32r/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_SCATTERLIST_H
-#define _ASM_M32R_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_M32R_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m32r/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/m32r/kernel/signal.c
--- linux-libre-3.16-gnu/arch/m32r/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m32r/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,28 +162,22 @@ setup_sigcontext(struct sigcontext __use
  * Determine which stack to use..
  */
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
 {
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (sas_ss_flags(sp) == 0)
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
-
-	return (void __user *)((sp - frame_size) & -8ul);
+	return (void __user *)((sigsp(sp, ksig) - frame_size) & -8ul);
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
-	int signal;
+	int signal, sig = ksig->sig;
 
-	frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+	frame = get_sigframe(ksig, regs->spu, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -193,13 +187,13 @@ static int setup_rt_frame(int sig, struc
 
 	err |= __put_user(signal, &frame->sig);
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -208,17 +202,17 @@ static int setup_rt_frame(int sig, struc
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  */
-	regs->lr = (unsigned long)ka->sa.sa_restorer;
+	regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
 
 	/* Set up registers for signal handler */
 	regs->spu = (unsigned long)frame;
 	regs->r0 = signal;	/* Arg for signal handler */
 	regs->r1 = (unsigned long)&frame->info;
 	regs->r2 = (unsigned long)&frame->uc;
-	regs->bpc = (unsigned long)ka->sa.sa_handler;
+	regs->bpc = (unsigned long)ksig->ka.sa.sa_handler;
 
 	set_fs(USER_DS);
 
@@ -228,10 +222,6 @@ static int setup_rt_frame(int sig, struc
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 static int prev_insn(struct pt_regs *regs)
@@ -252,9 +242,10 @@ static int prev_insn(struct pt_regs *reg
  */
 
 static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
+	int ret;
+
 	/* Are we from a system call? */
 	if (regs->syscall_nr >= 0) {
 		/* If so, check system call restarting.. */
@@ -265,7 +256,7 @@ handle_signal(unsigned long sig, struct
 				break;
 
 			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
+				if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 					regs->r0 = -EINTR;
 					break;
 				}
@@ -278,10 +269,9 @@ handle_signal(unsigned long sig, struct
 	}
 
 	/* Set up the stack frame */
-	if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
-		return;
+	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -291,9 +281,7 @@ handle_signal(unsigned long sig, struct
  */
 static void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which
@@ -304,8 +292,7 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Re-enable any watchpoints before delivering the
 		 * signal to user space. The processor register will
 		 * have been cleared if the watchpoint triggered
@@ -313,7 +300,7 @@ static void do_signal(struct pt_regs *re
 		 */
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, regs);
+		handle_signal(&ksig, regs);
 
 		return;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/amiga_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/amiga_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/amiga_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/amiga_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -257,7 +257,6 @@ CONFIG_BLK_DEV_GAYLE=y
 CONFIG_BLK_DEV_BUDDHA=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/apollo_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/apollo_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/apollo_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/apollo_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/atari_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/atari_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/atari_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/atari_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_FALCON_IDE=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/bvme6000_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/bvme6000_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/bvme6000_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/bvme6000_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/hp300_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/hp300_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/hp300_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/hp300_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/mac_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/mac_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/mac_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/mac_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_MAC_IDE=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/multi_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/multi_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/multi_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/multi_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -273,7 +273,6 @@ CONFIG_BLK_DEV_MAC_IDE=y
 CONFIG_BLK_DEV_Q40IDE=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/mvme147_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/mvme147_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/mvme147_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/mvme147_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -241,7 +241,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/mvme16x_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/mvme16x_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/mvme16x_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/mvme16x_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/q40_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/q40_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/q40_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/q40_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -249,7 +249,6 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_Q40IDE=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/sun3_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/sun3_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/sun3_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/sun3_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/configs/sun3x_defconfig linux-libre-3.17-rc7-gnu/arch/m68k/configs/sun3x_defconfig
--- linux-libre-3.16-gnu/arch/m68k/configs/sun3x_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/configs/sun3x_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/include/asm/pgtable_no.h linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/pgtable_no.h
--- linux-libre-3.16-gnu/arch/m68k/include/asm/pgtable_no.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/pgtable_no.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,11 +46,6 @@ static inline int pte_file(pte_t pte) {
 #define ZERO_PAGE(vaddr)	(virt_to_page(0))
 
 /*
- * These would be in other places but having them here reduces the diffs.
- */
-extern unsigned int kobjsize(const void *objp);
-
-/*
  * No page table caches to initialise.
  */
 #define pgtable_cache_init()	do { } while (0)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/m68k/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -176,5 +176,6 @@ 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-3.16-gnu/arch/m68k/include/asm/sun3_pgalloc.h linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/sun3_pgalloc.h
--- linux-libre-3.16-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,10 +12,6 @@
 
 #include <asm/tlb.h>
 
-/* FIXME - when we get this compiling */
-/* erm, now that it's compiling, what do we do with it? */
-#define _KERNPG_TABLE 0
-
 extern const char bad_pmd_string[];
 
 #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/m68k/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls		352
+#define NR_syscalls		354
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/include/asm/virtconvert.h linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/virtconvert.h
--- linux-libre-3.16-gnu/arch/m68k/include/asm/virtconvert.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/asm/virtconvert.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,16 +26,12 @@ static inline void *phys_to_virt(unsigne
 }
 
 /* Permanent address of a page. */
-#ifdef CONFIG_MMU
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#if defined(CONFIG_MMU) && defined(CONFIG_SINGLE_MEMORY_CHUNK)
 #define page_to_phys(page) \
 	__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
 #else
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 #endif
-#else
-#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
-#endif
 
 /*
  * IO bus memory addresses are 1:1 with the physical address,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/m68k/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/m68k/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -357,5 +357,7 @@
 #define __NR_sched_setattr	349
 #define __NR_sched_getattr	350
 #define __NR_renameat2		351
+#define __NR_getrandom		352
+#define __NR_memfd_create	353
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/m68k/kernel/signal.c
--- linux-libre-3.16-gnu/arch/m68k/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -835,38 +835,30 @@ static inline int rt_setup_ucontext(stru
 }
 
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
 {
-	unsigned long usp;
-
-	/* Default to using normal stack.  */
-	usp = rdusp();
+	unsigned long usp = sigsp(rdusp(), ksig);
 
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!sas_ss_flags(usp))
-			usp = current->sas_ss_sp + current->sas_ss_size;
-	}
 	return (void __user *)((usp - frame_size) & -8UL);
 }
 
-static int setup_frame (int sig, struct k_sigaction *ka,
-			 sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+			struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
 	int fsize = frame_extra_sizes(regs->format);
 	struct sigcontext context;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
 #ifdef DEBUG
 		printk ("setup_frame: Unknown frame format %#x\n",
 			regs->format);
 #endif
-		goto give_sigsegv;
+		return -EFAULT;
 	}
 
-	frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
+	frame = get_sigframe(ksig, sizeof(*frame) + fsize);
 
 	if (fsize)
 		err |= copy_to_user (frame + 1, regs + 1, fsize);
@@ -899,7 +891,7 @@ static int setup_frame (int sig, struct
 #endif
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	push_cache ((unsigned long) &frame->retcode);
 
@@ -908,7 +900,7 @@ static int setup_frame (int sig, struct
 	 * to destroy is successfully copied to sigframe.
 	 */
 	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 	adjustformat(regs);
 
 	/*
@@ -934,28 +926,24 @@ static int setup_frame (int sig, struct
 		tregs->sr = regs->sr;
 	}
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return err;
 }
 
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
-			    sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			   struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	int fsize = frame_extra_sizes(regs->format);
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
 #ifdef DEBUG
 		printk ("setup_frame: Unknown frame format %#x\n",
 			regs->format);
 #endif
-		goto give_sigsegv;
+		return -EFAULT;
 	}
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, sizeof(*frame));
 
 	if (fsize)
 		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
@@ -968,7 +956,7 @@ static int setup_rt_frame (int sig, stru
 			  &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -996,7 +984,7 @@ static int setup_rt_frame (int sig, stru
 #endif /* CONFIG_MMU */
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	push_cache ((unsigned long) &frame->retcode);
 
@@ -1005,7 +993,7 @@ static int setup_rt_frame (int sig, stru
 	 * to destroy is successfully copied to sigframe.
 	 */
 	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 	adjustformat(regs);
 
 	/*
@@ -1031,10 +1019,6 @@ static int setup_rt_frame (int sig, stru
 		tregs->sr = regs->sr;
 	}
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return err;
 }
 
 static inline void
@@ -1074,26 +1058,22 @@ handle_restart(struct pt_regs *regs, str
  * OK, we're invoking a handler
  */
 static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int err;
 	/* are we from a system call? */
 	if (regs->orig_d0 >= 0)
 		/* If so, check system call restarting.. */
-		handle_restart(regs, ka, 1);
+		handle_restart(regs, &ksig->ka, 1);
 
 	/* set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		err = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		err = setup_rt_frame(ksig, oldset, regs);
 	else
-		err = setup_frame(sig, ka, oldset, regs);
-
-	if (err)
-		return;
+		err = setup_frame(ksig, oldset, regs);
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(err, ksig, 0);
 
 	if (test_thread_flag(TIF_DELAYED_TRACE)) {
 		regs->sr &= ~0x8000;
@@ -1108,16 +1088,13 @@ handle_signal(int sig, struct k_sigactio
  */
 static void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	struct k_sigaction ka;
-	int signr;
+	struct ksignal ksig;
 
 	current->thread.esp0 = (unsigned long) regs;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/m68k/kernel/syscalltable.S linux-libre-3.17-rc7-gnu/arch/m68k/kernel/syscalltable.S
--- linux-libre-3.16-gnu/arch/m68k/kernel/syscalltable.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/m68k/kernel/syscalltable.S	2014-09-28 17:29:07.000000000 -0400
@@ -372,4 +372,6 @@ ENTRY(sys_call_table)
 	.long sys_sched_setattr
 	.long sys_sched_getattr		/* 350 */
 	.long sys_renameat2
+	.long sys_getrandom
+	.long sys_memfd_create
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/metag/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/metag/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -155,6 +155,7 @@ 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-3.16-gnu/arch/metag/Kconfig linux-libre-3.17-rc7-gnu/arch/metag/Kconfig
--- linux-libre-3.16-gnu/arch/metag/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@ config METAG
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/kernel/cachepart.c linux-libre-3.17-rc7-gnu/arch/metag/kernel/cachepart.c
--- linux-libre-3.16-gnu/arch/metag/kernel/cachepart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/kernel/cachepart.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,7 @@ unsigned int get_global_icache_size(void
 	return (get_icache_size() * ((temp >> SYSC_xCPARTG_AND_S) + 1)) >> 4;
 }
 
-static unsigned int get_thread_cache_size(unsigned int cache, int thread_id)
+static int get_thread_cache_size(unsigned int cache, int thread_id)
 {
 	unsigned int cache_size;
 	unsigned int t_cache_part;
@@ -94,7 +94,7 @@ static unsigned int get_thread_cache_siz
 
 void check_for_cache_aliasing(int thread_id)
 {
-	unsigned int thread_cache_size;
+	int thread_cache_size;
 	unsigned int cache_type;
 	for (cache_type = ICACHE; cache_type <= DCACHE; cache_type++) {
 		thread_cache_size =
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/kernel/ftrace_stub.S linux-libre-3.17-rc7-gnu/arch/metag/kernel/ftrace_stub.S
--- linux-libre-3.16-gnu/arch/metag/kernel/ftrace_stub.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/kernel/ftrace_stub.S	2014-09-28 17:29:07.000000000 -0400
@@ -16,13 +16,6 @@ _mcount_wrapper:
 	.global _ftrace_caller
 	.type	_ftrace_caller,function
 _ftrace_caller:
-	MOVT    D0Re0,#HI(_function_trace_stop)
-	ADD	D0Re0,D0Re0,#LO(_function_trace_stop)
-	GETD	D0Re0,[D0Re0]
-	CMP	D0Re0,#0
-	BEQ	$Lcall_stub
-	MOV	PC,D0.4
-$Lcall_stub:
 	MSETL   [A0StP], D0Ar6, D0Ar4, D0Ar2, D0.4
 	MOV     D1Ar1, D0.4
 	MOV     D0Ar2, D1RtP
@@ -42,13 +35,6 @@ _ftrace_call:
 	.global	_mcount_wrapper
 	.type	_mcount_wrapper,function
 _mcount_wrapper:
-	MOVT    D0Re0,#HI(_function_trace_stop)
-	ADD	D0Re0,D0Re0,#LO(_function_trace_stop)
-	GETD	D0Re0,[D0Re0]
-	CMP	D0Re0,#0
-	BEQ	$Lcall_mcount
-	MOV	PC,D0.4
-$Lcall_mcount:
 	MSETL   [A0StP], D0Ar6, D0Ar4, D0Ar2, D0.4
 	MOV     D1Ar1, D0.4
 	MOV     D0Ar2, D1RtP
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/kernel/perf/perf_event.c linux-libre-3.17-rc7-gnu/arch/metag/kernel/perf/perf_event.c
--- linux-libre-3.16-gnu/arch/metag/kernel/perf/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/kernel/perf/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -568,16 +568,6 @@ static int _hw_perf_event_init(struct pe
 		return -EINVAL;
 
 	/*
-	 * Early cores have "limited" counters - they have no overflow
-	 * interrupts - and so are unable to do sampling without extra work
-	 * and timer assistance.
-	 */
-	if (metag_pmu->max_period == 0) {
-		if (hwc->sample_period)
-			return -EINVAL;
-	}
-
-	/*
 	 * Don't assign an index until the event is placed into the hardware.
 	 * -1 signifies that we're still deciding where to put it. On SMP
 	 * systems each core has its own set of counters, so we can't do any
@@ -866,6 +856,15 @@ static int __init init_hw_perf_events(vo
 	pr_info("enabled with %s PMU driver, %d counters available\n",
 			metag_pmu->name, metag_pmu->max_events);
 
+	/*
+	 * Early cores have "limited" counters - they have no overflow
+	 * interrupts - and so are unable to do sampling without extra work
+	 * and timer assistance.
+	 */
+	if (metag_pmu->max_period == 0) {
+		metag_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+	}
+
 	/* Initialise the active events and reservation mutex */
 	atomic_set(&metag_pmu->active_events, 0);
 	mutex_init(&metag_pmu->reserve_mutex);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/metag/kernel/signal.c
--- linux-libre-3.16-gnu/arch/metag/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -140,13 +140,9 @@ static int setup_sigcontext(struct sigco
 /*
  * Determine which stack to use..
  */
-static void __user *get_sigframe(struct k_sigaction *ka, unsigned long sp,
-				 size_t frame_size)
+static void __user *get_sigframe(struct ksignal *ksig, unsigned long sp)
 {
-	/* Meta stacks grows upwards */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
-		sp = current->sas_ss_sp;
-
+	sp = sigsp(sp, ksig);
 	sp = (sp + 7) & ~7;			/* 8byte align stack */
 
 	return (void __user *)sp;
@@ -159,7 +155,7 @@ static int setup_rt_frame(struct ksignal
 	int err;
 	unsigned long code;
 
-	frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame));
+	frame = get_sigframe(ksig, regs->REG_SP);
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/metag/mm/hugetlbpage.c linux-libre-3.17-rc7-gnu/arch/metag/mm/hugetlbpage.c
--- linux-libre-3.16-gnu/arch/metag/mm/hugetlbpage.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/metag/mm/hugetlbpage.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,7 +173,7 @@ new_search:
 				mm->context.part_huge = 0;
 			return addr;
 		}
-		if (vma && (vma->vm_flags & MAP_HUGETLB)) {
+		if (vma->vm_flags & MAP_HUGETLB) {
 			/* space after a huge vma in 2nd level page table? */
 			if (vma->vm_end & HUGEPT_MASK) {
 				after_huge = 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/delay.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/delay.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/delay.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/delay.h	2014-09-28 17:29:07.000000000 -0400
@@ -61,13 +61,29 @@ extern inline void __udelay(unsigned int
 extern void __bad_udelay(void);		/* deliberately undefined */
 extern void __bad_ndelay(void);		/* deliberately undefined */
 
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > __MAX_UDELAY ? __bad_udelay() : __udelay((n) * (19 * HZ))) : \
-	__udelay((n) * (19 * HZ)))
+#define udelay(n)						\
+	({							\
+		if (__builtin_constant_p(n)) {			\
+			if ((n) / __MAX_UDELAY >= 1)		\
+				__bad_udelay();			\
+			else					\
+				__udelay((n) * (19 * HZ));	\
+		} else {					\
+			__udelay((n) * (19 * HZ));		\
+		}						\
+	})
 
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > __MAX_NDELAY ? __bad_ndelay() : __udelay((n) * HZ)) : \
-	__udelay((n) * HZ))
+#define ndelay(n)						\
+	({							\
+		if (__builtin_constant_p(n)) {			\
+			if ((n) / __MAX_NDELAY >= 1)		\
+				__bad_ndelay();			\
+			else					\
+				__udelay((n) * HZ);		\
+		} else {					\
+			__udelay((n) * HZ);			\
+		}						\
+	})
 
 #define muldiv(a, b, c)		(((a)*(b))/(c))
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/entry.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/entry.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/entry.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/entry.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <asm/percpu.h>
 #include <asm/ptrace.h>
+#include <linux/linkage.h>
 
 /*
  * These are per-cpu variables required in entry.S, among other
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -7,5 +7,6 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 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-3.16-gnu/arch/microblaze/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/scatterlist.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/uaccess.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/uaccess.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/uaccess.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/uaccess.h	2014-09-28 17:29:07.000000000 -0400
@@ -98,13 +98,13 @@ static inline int access_ok(int type, co
 
 	if ((get_fs().seg < ((unsigned long)addr)) ||
 			(get_fs().seg < ((unsigned long)addr + size - 1))) {
-		pr_debug("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
+		pr_devel("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
 			type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
 			(u32)get_fs().seg);
 		return 0;
 	}
 ok:
-	pr_debug("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
+	pr_devel("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
 			type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
 			(u32)get_fs().seg);
 	return 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/microblaze/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define __NR_syscalls         381
+#define __NR_syscalls         387
 
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/microblaze/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/microblaze/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -398,5 +398,9 @@
 #define __NR_finit_module	380
 #define __NR_sched_setattr	381
 #define __NR_sched_getattr	382
+#define __NR_renameat2		383
+#define __NR_seccomp		384
+#define __NR_getrandom		385
+#define __NR_memfd_create	386
 
 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/Kconfig linux-libre-3.17-rc7-gnu/arch/microblaze/Kconfig
--- linux-libre-3.16-gnu/arch/microblaze/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,6 @@ config MICROBLAZE
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FUNCTION_TRACER
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
@@ -128,7 +127,7 @@ config SECCOMP
 
 endmenu
 
-menu "Advanced setup"
+menu "Kernel features"
 
 config ADVANCED_OPTIONS
 	bool "Prompt for advanced kernel configuration options"
@@ -249,10 +248,10 @@ config MICROBLAZE_64K_PAGES
 
 endchoice
 
-endmenu
-
 source "mm/Kconfig"
 
+endmenu
+
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/microblaze/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,9 @@ void prepare_ftrace_return(unsigned long
 	unsigned long return_hooker = (unsigned long)
 				&return_to_handler;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/kernel/mcount.S linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/mcount.S
--- linux-libre-3.16-gnu/arch/microblaze/kernel/mcount.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/mcount.S	2014-09-28 17:29:07.000000000 -0400
@@ -91,11 +91,6 @@ ENTRY(ftrace_caller)
 #endif /* CONFIG_DYNAMIC_FTRACE */
 	SAVE_REGS
 	swi	r15, r1, 0;
-	/* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */
-	lwi	r5, r0, function_trace_stop;
-	bneid	r5, end;
-	nop;
-	/* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 #ifndef CONFIG_DYNAMIC_FTRACE
 	lwi	r5, r0, ftrace_graph_return;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/signal.c
--- linux-libre-3.16-gnu/arch/microblaze/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,22 +145,19 @@ setup_sigcontext(struct sigcontext __use
  * Determine which stack to use..
  */
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
 {
 	/* Default to using normal stack */
-	unsigned long sp = regs->r1;
-
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	unsigned long sp = sigsp(regs->r1, ksig);
 
 	return (void __user *)((sp - frame_size) & -8UL);
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 	unsigned long address = 0;
 #ifdef CONFIG_MMU
@@ -168,10 +165,10 @@ static int setup_rt_frame(int sig, struc
 	pte_t *ptep;
 #endif
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -179,8 +176,8 @@ static int setup_rt_frame(int sig, struc
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	if (info)
-		err |= copy_siginfo_to_user(&frame->info, info);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Create the ucontext. */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -227,7 +224,7 @@ static int setup_rt_frame(int sig, struc
 	flush_dcache_range(address, address + 8);
 #endif
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->r1 = (unsigned long) frame;
@@ -237,7 +234,7 @@ static int setup_rt_frame(int sig, struc
 	regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
 	regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
 	/* Offset to handle microblaze rtid r14, 0 */
-	regs->pc = (unsigned long)ka->sa.sa_handler;
+	regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 
 	set_fs(USER_DS);
 
@@ -247,10 +244,6 @@ static int setup_rt_frame(int sig, struc
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /* Handle restarting system calls */
@@ -283,23 +276,15 @@ do_restart:
  */
 
 static void
-handle_signal(unsigned long sig, struct k_sigaction *ka,
-		siginfo_t *info, struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
-	else
-		ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
-
-	if (ret)
-		return;
+	ret = setup_rt_frame(ksig, oldset, regs);
 
-	signal_delivered(sig, info, ka, regs,
-			test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -313,21 +298,19 @@ handle_signal(unsigned long sig, struct
  */
 static void do_signal(struct pt_regs *regs, int in_syscall)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
+
 #ifdef DEBUG_SIG
 	pr_info("do signal: %p %d\n", regs, in_syscall);
 	pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
 			regs->r12, current_thread_info()->flags);
 #endif
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee! Actually deliver the signal. */
 		if (in_syscall)
-			handle_restart(regs, &ka, 1);
-		handle_signal(signr, &ka, &info, regs);
+			handle_restart(regs, &ksig.ka, 1);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/kernel/syscall_table.S linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/syscall_table.S
--- linux-libre-3.16-gnu/arch/microblaze/kernel/syscall_table.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/kernel/syscall_table.S	2014-09-28 17:29:07.000000000 -0400
@@ -380,6 +380,10 @@ ENTRY(sys_call_table)
 	.long sys_process_vm_readv
 	.long sys_process_vm_writev
 	.long sys_kcmp
-	.long sys_finit_module
+	.long sys_finit_module		/* 380 */
 	.long sys_sched_setattr
 	.long sys_sched_getattr
+	.long sys_renameat2
+	.long sys_seccomp
+	.long sys_getrandom		/* 385 */
+	.long sys_memfd_create
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/microblaze/lib/Makefile linux-libre-3.17-rc7-gnu/arch/microblaze/lib/Makefile
--- linux-libre-3.16-gnu/arch/microblaze/lib/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/microblaze/lib/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -18,14 +18,6 @@ endif
 
 lib-y += uaccess_old.o
 
-lib-y += ashldi3.o
-lib-y += ashrdi3.o
-lib-y += cmpdi2.o
-lib-y += divsi3.o
-lib-y += lshrdi3.o
-lib-y += modsi3.o
-lib-y += muldi3.o
-lib-y += mulsi3.o
-lib-y += ucmpdi2.o
-lib-y += udivsi3.o
-lib-y += umodsi3.o
+# libgcc-style stuff needed in the kernel
+obj-y += ashldi3.o ashrdi3.o cmpdi2.o divsi3.o lshrdi3.o modsi3.o
+obj-y += muldi3.o mulsi3.o ucmpdi2.o udivsi3.o umodsi3.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/board-mtx1.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/board-mtx1.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/board-mtx1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/board-mtx1.c	2014-09-28 17:29:07.000000000 -0400
@@ -85,10 +85,10 @@ void __init board_setup(void)
 #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
 
 	/* Initialize sys_pinfunc */
-	au_writel(SYS_PF_NI2, SYS_PINFUNC);
+	alchemy_wrsys(SYS_PF_NI2, AU1000_SYS_PINFUNC);
 
 	/* Initialize GPIO */
-	au_writel(~0, KSEG1ADDR(AU1000_SYS_PHYS_ADDR) + SYS_TRIOUTCLR);
+	alchemy_wrsys(~0, AU1000_SYS_TRIOUTCLR);
 	alchemy_gpio_direction_output(0, 0);	/* Disable M66EN (PCI 66MHz) */
 	alchemy_gpio_direction_output(3, 1);	/* Disable PCI CLKRUN# */
 	alchemy_gpio_direction_output(1, 1);	/* Enable EXT_IO3 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/board-xxs1500.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/board-xxs1500.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/board-xxs1500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/board-xxs1500.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,9 +87,9 @@ void __init board_setup(void)
 	alchemy_gpio2_enable();
 
 	/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
-	pin_func  = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
+	pin_func  = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PF_UR3;
 	pin_func |= SYS_PF_UR3;
-	au_writel(pin_func, SYS_PINFUNC);
+	alchemy_wrsys(pin_func, AU1000_SYS_PINFUNC);
 
 	/* Enable UART */
 	alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/clock.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/clock.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1094 @@
+/*
+ * Alchemy clocks.
+ *
+ * Exposes all configurable internal clock sources to the clk framework.
+ *
+ * We have:
+ *  - Root source, usually 12MHz supplied by an external crystal
+ *  - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
+ *
+ * Dividers:
+ *  - 6 clock dividers with:
+ *   * selectable source [one of the PLLs],
+ *   * output divided between [2 .. 512 in steps of 2] (!Au1300)
+ *     or [1 .. 256 in steps of 1] (Au1300),
+ *   * can be enabled individually.
+ *
+ * - up to 6 "internal" (fixed) consumers which:
+ *   * take either AUXPLL or one of the above 6 dividers as input,
+ *   * divide this input by 1, 2, or 4 (and 3 on Au1300).
+ *   * can be disabled separately.
+ *
+ * Misc clocks:
+ * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
+ *    depends on board design and should be set by bootloader, read-only.
+ * - peripheral clock: half the rate of sysbus clock, source for a lot
+ *    of peripheral blocks, read-only.
+ * - memory clock: clk rate to main memory chips, depends on board
+ *    design and is read-only,
+ * - lrclk: the static bus clock signal for synchronous operation.
+ *    depends on board design, must be set by bootloader,
+ *    but may be required to correctly configure devices attached to
+ *    the static bus. The Au1000/1500/1100 manuals call it LCLK, on
+ *    later models it's called RCLK.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* Base clock: 12MHz is the default in all databooks, and I haven't
+ * found any board yet which uses a different rate.
+ */
+#define ALCHEMY_ROOTCLK_RATE	12000000
+
+/*
+ * the internal sources which can be driven by the PLLs and dividers.
+ * Names taken from the databooks, refer to them for more information,
+ * especially which ones are share a clock line.
+ */
+static const char * const alchemy_au1300_intclknames[] = {
+	"lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
+	"EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1200_intclknames[] = {
+	"lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1550_intclknames[] = {
+	"usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
+	"EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1100_intclknames[] = {
+	"usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1500_intclknames[] = {
+	NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1000_intclknames[] = {
+	"irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
+	"EXTCLK1"
+};
+
+/* aliases for a few on-chip sources which are either shared
+ * or have gone through name changes.
+ */
+static struct clk_aliastable {
+	char *alias;
+	char *base;
+	int cputype;
+} alchemy_clk_aliases[] __initdata = {
+	{ "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "irda_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+	{ "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+	{ "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
+	{ "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
+	{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
+	{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
+	{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+	{ "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+	{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+	{ "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+
+	{ NULL, NULL, 0 },
+};
+
+#define IOMEM(x)	((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
+
+/* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
+static spinlock_t alchemy_clk_fg0_lock;
+static spinlock_t alchemy_clk_fg1_lock;
+static spinlock_t alchemy_clk_csrc_lock;
+
+/* CPU Core clock *****************************************************/
+
+static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	unsigned long t;
+
+	/*
+	 * On early Au1000, sys_cpupll was write-only. Since these
+	 * silicon versions of Au1000 are not sold, we don't bend
+	 * over backwards trying to determine the frequency.
+	 */
+	if (unlikely(au1xxx_cpu_has_pll_wo()))
+		t = 396000000;
+	else {
+		t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
+		t *= parent_rate;
+	}
+
+	return t;
+}
+
+static struct clk_ops alchemy_clkops_cpu = {
+	.recalc_rate	= alchemy_clk_cpu_recalc,
+};
+
+static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
+						int ctype)
+{
+	struct clk_init_data id;
+	struct clk_hw *h;
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return ERR_PTR(-ENOMEM);
+
+	id.name = ALCHEMY_CPU_CLK;
+	id.parent_names = &parent_name;
+	id.num_parents = 1;
+	id.flags = CLK_IS_BASIC;
+	id.ops = &alchemy_clkops_cpu;
+	h->init = &id;
+
+	return clk_register(NULL, h);
+}
+
+/* AUXPLLs ************************************************************/
+
+struct alchemy_auxpll_clk {
+	struct clk_hw hw;
+	unsigned long reg;	/* au1300 has also AUXPLL2 */
+	int maxmult;		/* max multiplier */
+};
+#define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
+
+static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+
+	return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
+}
+
+static int alchemy_clk_aux_setr(struct clk_hw *hw,
+				unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+	unsigned long d = rate;
+
+	if (rate)
+		d /= parent_rate;
+	else
+		d = 0;
+
+	/* minimum is 84MHz, max is 756-1032 depending on variant */
+	if (((d < 7) && (d != 0)) || (d > a->maxmult))
+		return -EINVAL;
+
+	alchemy_wrsys(d, a->reg);
+	return 0;
+}
+
+static long alchemy_clk_aux_roundr(struct clk_hw *hw,
+					    unsigned long rate,
+					    unsigned long *parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+	unsigned long mult;
+
+	if (!rate || !*parent_rate)
+		return 0;
+
+	mult = rate / (*parent_rate);
+
+	if (mult && (mult < 7))
+		mult = 7;
+	if (mult > a->maxmult)
+		mult = a->maxmult;
+
+	return (*parent_rate) * mult;
+}
+
+static struct clk_ops alchemy_clkops_aux = {
+	.recalc_rate	= alchemy_clk_aux_recalc,
+	.set_rate	= alchemy_clk_aux_setr,
+	.round_rate	= alchemy_clk_aux_roundr,
+};
+
+static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
+						char *name, int maxmult,
+						unsigned long reg)
+{
+	struct clk_init_data id;
+	struct clk *c;
+	struct alchemy_auxpll_clk *a;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return ERR_PTR(-ENOMEM);
+
+	id.name = name;
+	id.parent_names = &parent_name;
+	id.num_parents = 1;
+	id.flags = CLK_GET_RATE_NOCACHE;
+	id.ops = &alchemy_clkops_aux;
+
+	a->reg = reg;
+	a->maxmult = maxmult;
+	a->hw.init = &id;
+
+	c = clk_register(NULL, &a->hw);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, name, NULL);
+	else
+		kfree(a);
+
+	return c;
+}
+
+/* sysbus_clk *********************************************************/
+
+static struct clk __init  *alchemy_clk_setup_sysbus(const char *pn)
+{
+	unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
+	struct clk *c;
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
+				      pn, 0, 1, v);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
+	return c;
+}
+
+/* Peripheral Clock ***************************************************/
+
+static struct clk __init *alchemy_clk_setup_periph(const char *pn)
+{
+	/* Peripheral clock runs at half the rate of sysbus clk */
+	struct clk *c;
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
+				      pn, 0, 1, 2);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
+	return c;
+}
+
+/* mem clock **********************************************************/
+
+static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
+{
+	void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
+	unsigned long v;
+	struct clk *c;
+	int div;
+
+	switch (ct) {
+	case ALCHEMY_CPU_AU1550:
+	case ALCHEMY_CPU_AU1200:
+		v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+		div = (v & (1 << 15)) ? 1 : 2;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+		div = (v & (1 << 31)) ? 1 : 2;
+		break;
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+	default:
+		div = 2;
+		break;
+	}
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
+				      0, 1, div);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
+	return c;
+}
+
+/* lrclk: external synchronous static bus clock ***********************/
+
+static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
+{
+	/* MEM_STCFG0[15:13] = divisor.
+	 * L/RCLK = periph_clk / (divisor + 1)
+	 * On Au1000, Au1500, Au1100 it's called LCLK,
+	 * on later models it's called RCLK, but it's the same thing.
+	 */
+	struct clk *c;
+	unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
+
+	v = (v & 7) + 1;
+	c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
+				      pn, 0, 1, v);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
+	return c;
+}
+
+/* Clock dividers and muxes *******************************************/
+
+/* data for fgen and csrc mux-dividers */
+struct alchemy_fgcs_clk {
+	struct clk_hw hw;
+	spinlock_t *reglock;	/* register lock		  */
+	unsigned long reg;	/* SYS_FREQCTRL0/1		  */
+	int shift;		/* offset in register		  */
+	int parent;		/* parent before disable [Au1300] */
+	int isen;		/* is it enabled?		  */
+	int *dt;		/* dividertable for csrc	  */
+};
+#define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
+
+static long alchemy_calc_div(unsigned long rate, unsigned long prate,
+			       int scale, int maxdiv, unsigned long *rv)
+{
+	long div1, div2;
+
+	div1 = prate / rate;
+	if ((prate / div1) > rate)
+		div1++;
+
+	if (scale == 2) {	/* only div-by-multiple-of-2 possible */
+		if (div1 & 1)
+			div1++;	/* stay <=prate */
+	}
+
+	div2 = (div1 / scale) - 1;	/* value to write to register */
+
+	if (div2 > maxdiv)
+		div2 = maxdiv;
+	if (rv)
+		*rv = div2;
+
+	div1 = ((div2 + 1) * scale);
+	return div1;
+}
+
+static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk,
+					int scale, int maxdiv)
+{
+	struct clk *pc, *bpc, *free;
+	long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
+	int j;
+
+	lastdiff = INT_MAX;
+	bpr = 0;
+	bpc = NULL;
+	br = -EINVAL;
+	free = NULL;
+
+	/* look at the rates each enabled parent supplies and select
+	 * the one that gets closest to but not over the requested rate.
+	 */
+	for (j = 0; j < 7; j++) {
+		pc = clk_get_parent_by_index(hw->clk, j);
+		if (!pc)
+			break;
+
+		/* if this parent is currently unused, remember it.
+		 * XXX: I know it's a layering violation, but it works
+		 * so well.. (if (!clk_has_active_children(pc)) )
+		 */
+		if (pc->prepare_count == 0) {
+			if (!free)
+				free = pc;
+		}
+
+		pr = clk_get_rate(pc);
+		if (pr < rate)
+			continue;
+
+		/* what can hardware actually provide */
+		tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+		nr = pr / tdv;
+		diff = rate - nr;
+		if (nr > rate)
+			continue;
+
+		if (diff < lastdiff) {
+			lastdiff = diff;
+			bpr = pr;
+			bpc = pc;
+			br = nr;
+		}
+		if (diff == 0)
+			break;
+	}
+
+	/* if we couldn't get the exact rate we wanted from the enabled
+	 * parents, maybe we can tell an available disabled/inactive one
+	 * to give us a rate we can divide down to the requested rate.
+	 */
+	if (lastdiff && free) {
+		for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
+			tpr = rate * j;
+			if (tpr < 0)
+				break;
+			pr = clk_round_rate(free, tpr);
+
+			tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+			nr = pr / tdv;
+			diff = rate - nr;
+			if (nr > rate)
+				continue;
+			if (diff < lastdiff) {
+				lastdiff = diff;
+				bpr = pr;
+				bpc = free;
+				br = nr;
+			}
+			if (diff == 0)
+				break;
+		}
+	}
+
+	*best_parent_rate = bpr;
+	*best_parent_clk = bpc;
+	return br;
+}
+
+static int alchemy_clk_fgv1_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v |= (1 << 1) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
+
+	return v & 1;
+}
+
+static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~((1 << 1) << c->shift);
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	if (index)
+		v |= (1 << c->shift);
+	else
+		v &= ~(1 << c->shift);
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return (alchemy_rdsys(c->reg) >> c->shift) & 1;
+}
+
+static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long div, v, flags, ret;
+	int sh = c->shift + 2;
+
+	if (!rate || !parent_rate || rate > (parent_rate / 2))
+		return -EINVAL;
+	ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(0xff << sh);
+	v |= div << sh;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
+
+	v = ((v & 0xff) + 1) * 2;
+	return parent_rate / v;
+}
+
+static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, 2, 512);
+}
+
+/* Au1000, Au1100, Au15x0, Au12x0 */
+static struct clk_ops alchemy_clkops_fgenv1 = {
+	.recalc_rate	= alchemy_clk_fgv1_recalc,
+	.determine_rate	= alchemy_clk_fgv1_detr,
+	.set_rate	= alchemy_clk_fgv1_setr,
+	.set_parent	= alchemy_clk_fgv1_setp,
+	.get_parent	= alchemy_clk_fgv1_getp,
+	.enable		= alchemy_clk_fgv1_en,
+	.disable	= alchemy_clk_fgv1_dis,
+	.is_enabled	= alchemy_clk_fgv1_isen,
+};
+
+static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
+{
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	v &= ~(3 << c->shift);
+	v |= (c->parent & 3) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	c->isen = 1;
+}
+
+static int alchemy_clk_fgv2_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	/* enable by setting the previous parent clock */
+	spin_lock_irqsave(c->reglock, flags);
+	__alchemy_clk_fgv2_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
+}
+
+static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(3 << c->shift);	/* set input mux to "disabled" state */
+	alchemy_wrsys(v, c->reg);
+	c->isen = 0;
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	c->parent = index + 1;	/* value to write to register */
+	if (c->isen)
+		__alchemy_clk_fgv2_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags, v;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = c->parent - 1;
+	spin_unlock_irqrestore(c->reglock, flags);
+	return v;
+}
+
+/* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
+ * dividers behave exactly as on previous models (dividers are multiples
+ * of 2); with the bit set, dividers are multiples of 1, halving their
+ * range, but making them also much more flexible.
+ */
+static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int sh = c->shift + 2;
+	unsigned long div, v, flags, ret;
+
+	if (!rate || !parent_rate || rate > parent_rate)
+		return -EINVAL;
+
+	v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */
+	ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
+			       v ? 256 : 512, &div);
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(0xff << sh);
+	v |= (div & 0xff) << sh;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int sh = c->shift + 2;
+	unsigned long v, t;
+
+	v = alchemy_rdsys(c->reg);
+	t = parent_rate / (((v >> sh) & 0xff) + 1);
+	if ((v & (1 << 30)) == 0)		/* test scale bit */
+		t /= 2;
+
+	return t;
+}
+
+static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int scale, maxdiv;
+
+	if (alchemy_rdsys(c->reg) & (1 << 30)) {
+		scale = 1;
+		maxdiv = 256;
+	} else {
+		scale = 2;
+		maxdiv = 512;
+	}
+
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, scale, maxdiv);
+}
+
+/* Au1300 larger input mux, no separate disable bit, flexible divider */
+static struct clk_ops alchemy_clkops_fgenv2 = {
+	.recalc_rate	= alchemy_clk_fgv2_recalc,
+	.determine_rate	= alchemy_clk_fgv2_detr,
+	.set_rate	= alchemy_clk_fgv2_setr,
+	.set_parent	= alchemy_clk_fgv2_setp,
+	.get_parent	= alchemy_clk_fgv2_getp,
+	.enable		= alchemy_clk_fgv2_en,
+	.disable	= alchemy_clk_fgv2_dis,
+	.is_enabled	= alchemy_clk_fgv2_isen,
+};
+
+static const char * const alchemy_clk_fgv1_parents[] = {
+	ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgv2_parents[] = {
+	ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgen_names[] = {
+	ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+	ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
+
+static int __init alchemy_clk_init_fgens(int ctype)
+{
+	struct clk *c;
+	struct clk_init_data id;
+	struct alchemy_fgcs_clk *a;
+	unsigned long v;
+	int i, ret;
+
+	switch (ctype) {
+	case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+		id.ops = &alchemy_clkops_fgenv1;
+		id.parent_names = (const char **)alchemy_clk_fgv1_parents;
+		id.num_parents = 2;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		id.ops = &alchemy_clkops_fgenv2;
+		id.parent_names = (const char **)alchemy_clk_fgv2_parents;
+		id.num_parents = 3;
+		break;
+	default:
+		return -ENODEV;
+	}
+	id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+	a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	spin_lock_init(&alchemy_clk_fg0_lock);
+	spin_lock_init(&alchemy_clk_fg1_lock);
+	ret = 0;
+	for (i = 0; i < 6; i++) {
+		id.name = alchemy_clk_fgen_names[i];
+		a->shift = 10 * (i < 3 ? i : i - 3);
+		if (i > 2) {
+			a->reg = AU1000_SYS_FREQCTRL1;
+			a->reglock = &alchemy_clk_fg1_lock;
+		} else {
+			a->reg = AU1000_SYS_FREQCTRL0;
+			a->reglock = &alchemy_clk_fg0_lock;
+		}
+
+		/* default to first parent if bootloader has set
+		 * the mux to disabled state.
+		 */
+		if (ctype == ALCHEMY_CPU_AU1300) {
+			v = alchemy_rdsys(a->reg);
+			a->parent = (v >> a->shift) & 3;
+			if (!a->parent) {
+				a->parent = 1;
+				a->isen = 0;
+			} else
+				a->isen = 1;
+		}
+
+		a->hw.init = &id;
+		c = clk_register(NULL, &a->hw);
+		if (IS_ERR(c))
+			ret++;
+		else
+			clk_register_clkdev(c, id.name, NULL);
+		a++;
+	}
+
+	return ret;
+}
+
+/* internal sources muxes *********************************************/
+
+static int alchemy_clk_csrc_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	return (((v >> c->shift) >> 2) & 7) != 0;
+}
+
+static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
+{
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	v &= ~((7 << 2) << c->shift);
+	v |= ((c->parent & 7) << 2) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	c->isen = 1;
+}
+
+static int alchemy_clk_csrc_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	/* enable by setting the previous parent clock */
+	spin_lock_irqsave(c->reglock, flags);
+	__alchemy_clk_csrc_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static void alchemy_clk_csrc_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~((3 << 2) << c->shift);	/* mux to "disabled" state */
+	alchemy_wrsys(v, c->reg);
+	c->isen = 0;
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	c->parent = index + 1;	/* value to write to register */
+	if (c->isen)
+		__alchemy_clk_csrc_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return c->parent - 1;
+}
+
+static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
+
+	return parent_rate / c->dt[v];
+}
+
+static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long d, v, flags;
+	int i;
+
+	if (!rate || !parent_rate || rate > parent_rate)
+		return -EINVAL;
+
+	d = (parent_rate + (rate / 2)) / rate;
+	if (d > 4)
+		return -EINVAL;
+	if ((d == 3) && (c->dt[2] != 3))
+		d = 4;
+
+	for (i = 0; i < 4; i++)
+		if (c->dt[i] == d)
+			break;
+
+	if (i >= 4)
+		return -EINVAL;	/* oops */
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(3 << c->shift);
+	v |= (i & 3) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
+
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, scale, 4);
+}
+
+static struct clk_ops alchemy_clkops_csrc = {
+	.recalc_rate	= alchemy_clk_csrc_recalc,
+	.determine_rate	= alchemy_clk_csrc_detr,
+	.set_rate	= alchemy_clk_csrc_setr,
+	.set_parent	= alchemy_clk_csrc_setp,
+	.get_parent	= alchemy_clk_csrc_getp,
+	.enable		= alchemy_clk_csrc_en,
+	.disable	= alchemy_clk_csrc_dis,
+	.is_enabled	= alchemy_clk_csrc_isen,
+};
+
+static const char * const alchemy_clk_csrc_parents[] = {
+	/* disabled at index 0 */ ALCHEMY_AUXPLL_CLK,
+	ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+	ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
+};
+
+/* divider tables */
+static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 };	/* rest */
+static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 };	/* Au1300 */
+
+static int __init alchemy_clk_setup_imux(int ctype)
+{
+	struct alchemy_fgcs_clk *a;
+	const char * const *names;
+	struct clk_init_data id;
+	unsigned long v;
+	int i, ret, *dt;
+	struct clk *c;
+
+	id.ops = &alchemy_clkops_csrc;
+	id.parent_names = (const char **)alchemy_clk_csrc_parents;
+	id.num_parents = 7;
+	id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+	dt = alchemy_csrc_dt1;
+	switch (ctype) {
+	case ALCHEMY_CPU_AU1000:
+		names = alchemy_au1000_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1500:
+		names = alchemy_au1500_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1100:
+		names = alchemy_au1100_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1550:
+		names = alchemy_au1550_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1200:
+		names = alchemy_au1200_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		dt = alchemy_csrc_dt2;
+		names = alchemy_au1300_intclknames;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	spin_lock_init(&alchemy_clk_csrc_lock);
+	ret = 0;
+
+	for (i = 0; i < 6; i++) {
+		id.name = names[i];
+		if (!id.name)
+			goto next;
+
+		a->shift = i * 5;
+		a->reg = AU1000_SYS_CLKSRC;
+		a->reglock = &alchemy_clk_csrc_lock;
+		a->dt = dt;
+
+		/* default to first parent clock if mux is initially
+		 * set to disabled state.
+		 */
+		v = alchemy_rdsys(a->reg);
+		a->parent = ((v >> a->shift) >> 2) & 7;
+		if (!a->parent) {
+			a->parent = 1;
+			a->isen = 0;
+		} else
+			a->isen = 1;
+
+		a->hw.init = &id;
+		c = clk_register(NULL, &a->hw);
+		if (IS_ERR(c))
+			ret++;
+		else
+			clk_register_clkdev(c, id.name, NULL);
+next:
+		a++;
+	}
+
+	return ret;
+}
+
+
+/**********************************************************************/
+
+
+#define ERRCK(x)						\
+	if (IS_ERR(x)) {					\
+		ret = PTR_ERR(x);				\
+		goto out;					\
+	}
+
+static int __init alchemy_clk_init(void)
+{
+	int ctype = alchemy_get_cputype(), ret, i;
+	struct clk_aliastable *t = alchemy_clk_aliases;
+	struct clk *c;
+
+	/* Root of the Alchemy clock tree: external 12MHz crystal osc */
+	c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
+					   CLK_IS_ROOT,
+					   ALCHEMY_ROOTCLK_RATE);
+	ERRCK(c)
+
+	/* CPU core clock */
+	c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
+	ERRCK(c)
+
+	/* AUXPLLs: max 1GHz on Au1300, 748MHz on older models */
+	i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
+	c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
+				  i, AU1000_SYS_AUXPLL);
+	ERRCK(c)
+
+	if (ctype == ALCHEMY_CPU_AU1300) {
+		c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
+					  ALCHEMY_AUXPLL2_CLK, i,
+					  AU1300_SYS_AUXPLL2);
+		ERRCK(c)
+	}
+
+	/* sysbus clock: cpu core clock divided by 2, 3 or 4 */
+	c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
+	ERRCK(c)
+
+	/* peripheral clock: runs at half rate of sysbus clk */
+	c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
+	ERRCK(c)
+
+	/* SDR/DDR memory clock */
+	c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
+	ERRCK(c)
+
+	/* L/RCLK: external static bus clock for synchronous mode */
+	c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
+	ERRCK(c)
+
+	/* Frequency dividers 0-5 */
+	ret = alchemy_clk_init_fgens(ctype);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* diving muxes for internal sources */
+	ret = alchemy_clk_setup_imux(ctype);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* set up aliases drivers might look for */
+	while (t->base) {
+		if (t->cputype == ctype)
+			clk_add_alias(t->alias, NULL, t->base, NULL);
+		t++;
+	}
+
+	pr_info("Alchemy clocktree installed\n");
+	return 0;
+
+out:
+	return ret;
+}
+postcore_initcall(alchemy_clk_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/clocks.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/clocks.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/clocks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/clocks.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Simple Au1xx0 clocks routines.
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/time.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK	12000000
-
-static unsigned int au1x00_clock; /*  Hz */
-static unsigned long uart_baud_base;
-
-/*
- * Set the au1000_clock
- */
-void set_au1x00_speed(unsigned int new_freq)
-{
-	au1x00_clock = new_freq;
-}
-
-unsigned int get_au1x00_speed(void)
-{
-	return au1x00_clock;
-}
-EXPORT_SYMBOL(get_au1x00_speed);
-
-/*
- * The UART baud base is not known at compile time ... if
- * we want to be able to use the same code on different
- * speed CPUs.
- */
-unsigned long get_au1x00_uart_baud_base(void)
-{
-	return uart_baud_base;
-}
-
-void set_au1x00_uart_baud_base(unsigned long new_baud_base)
-{
-	uart_baud_base = new_baud_base;
-}
-
-/*
- * We read the real processor speed from the PLL.  This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists.  If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly.  This function is further convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register.			-- Dan
- */
-unsigned long au1xxx_calc_clock(void)
-{
-	unsigned long cpu_speed;
-
-	/*
-	 * On early Au1000, sys_cpupll was write-only. Since these
-	 * silicon versions of Au1000 are not sold by AMD, we don't bend
-	 * over backwards trying to determine the frequency.
-	 */
-	if (au1xxx_cpu_has_pll_wo())
-		cpu_speed = 396000000;
-	else
-		cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
-
-	/* On Alchemy CPU:counter ratio is 1:1 */
-	mips_hpt_frequency = cpu_speed;
-	/* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
-	set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
-							  & 0x03) + 2) * 16));
-
-	set_au1x00_speed(cpu_speed);
-
-	return cpu_speed;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/dbdma.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/dbdma.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/dbdma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/dbdma.c	2014-09-28 17:29:07.000000000 -0400
@@ -341,7 +341,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u
 			(dtp->dev_flags & DEV_FLAGS_SYNC))
 				i |= DDMA_CFG_SYNC;
 		cp->ddma_cfg = i;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/*
 		 * Return a non-zero value that can be used to find the channel
@@ -631,7 +631,7 @@ u32 au1xxx_dbdma_put_source(u32 chanid,
 	 */
 	dma_cache_wback_inv((unsigned long)buf, nbytes);
 	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
 	ctp->chan_ptr->ddma_dbell = 0;
 
@@ -693,7 +693,7 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dm
 	 */
 	dma_cache_inv((unsigned long)buf, nbytes);
 	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
 	ctp->chan_ptr->ddma_dbell = 0;
 
@@ -760,7 +760,7 @@ void au1xxx_dbdma_stop(u32 chanid)
 
 	cp = ctp->chan_ptr;
 	cp->ddma_cfg &= ~DDMA_CFG_EN;	/* Disable channel */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	while (!(cp->ddma_stat & DDMA_STAT_H)) {
 		udelay(1);
 		halt_timeout++;
@@ -771,7 +771,7 @@ void au1xxx_dbdma_stop(u32 chanid)
 	}
 	/* clear current desc valid and doorbell */
 	cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_stop);
 
@@ -789,9 +789,9 @@ void au1xxx_dbdma_start(u32 chanid)
 	cp = ctp->chan_ptr;
 	cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
 	cp->ddma_cfg |= DDMA_CFG_EN;	/* Enable channel */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	cp->ddma_dbell = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_start);
 
@@ -832,7 +832,7 @@ u32 au1xxx_get_dma_residue(u32 chanid)
 
 	/* This is only valid if the channel is stopped. */
 	rv = cp->ddma_bytecnt;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	return rv;
 }
@@ -868,7 +868,7 @@ static irqreturn_t dbdma_interrupt(int i
 	au1x_dma_chan_t *cp;
 
 	intstat = dbdma_gptr->ddma_intstat;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	chan_index = __ffs(intstat);
 
 	ctp = chan_tab_ptr[chan_index];
@@ -877,7 +877,7 @@ static irqreturn_t dbdma_interrupt(int i
 
 	/* Reset interrupt. */
 	cp->ddma_irq = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (ctp->chan_callback)
 		ctp->chan_callback(irq, ctp->chan_callparam);
@@ -1061,7 +1061,7 @@ static int __init dbdma_setup(unsigned i
 	dbdma_gptr->ddma_config = 0;
 	dbdma_gptr->ddma_throttle = 0;
 	dbdma_gptr->ddma_inten = 0xffff;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/dma.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/dma.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,17 +141,17 @@ void dump_au1000_dma_channel(unsigned in
 
 	printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
 	printk(KERN_INFO "  mode = 0x%08x\n",
-	       au_readl(chan->io + DMA_MODE_SET));
+	       __raw_readl(chan->io + DMA_MODE_SET));
 	printk(KERN_INFO "  addr = 0x%08x\n",
-	       au_readl(chan->io + DMA_PERIPHERAL_ADDR));
+	       __raw_readl(chan->io + DMA_PERIPHERAL_ADDR));
 	printk(KERN_INFO "  start0 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER0_START));
+	       __raw_readl(chan->io + DMA_BUFFER0_START));
 	printk(KERN_INFO "  start1 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER1_START));
+	       __raw_readl(chan->io + DMA_BUFFER1_START));
 	printk(KERN_INFO "  count0 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER0_COUNT));
+	       __raw_readl(chan->io + DMA_BUFFER0_COUNT));
 	printk(KERN_INFO "  count1 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER1_COUNT));
+	       __raw_readl(chan->io + DMA_BUFFER1_COUNT));
 }
 
 /*
@@ -204,7 +204,8 @@ int request_au1000_dma(int dev_id, const
 	}
 
 	/* fill it in */
-	chan->io = KSEG1ADDR(AU1000_DMA_PHYS_ADDR) + i * DMA_CHANNEL_LEN;
+	chan->io = (void __iomem *)(KSEG1ADDR(AU1000_DMA_PHYS_ADDR) +
+			i * DMA_CHANNEL_LEN);
 	chan->dev_id = dev_id;
 	chan->dev_str = dev_str;
 	chan->fifo_addr = dev->fifo_addr;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/irq.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/irq.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -389,13 +389,12 @@ static int au1x_ic1_setwake(struct irq_d
 		return -EINVAL;
 
 	local_irq_save(flags);
-	wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
+	wakemsk = alchemy_rdsys(AU1000_SYS_WAKEMSK);
 	if (on)
 		wakemsk |= 1 << bit;
 	else
 		wakemsk &= ~(1 << bit);
-	__raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
-	wmb();
+	alchemy_wrsys(wakemsk, AU1000_SYS_WAKEMSK);
 	local_irq_restore(flags);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/Makefile linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/Makefile
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,8 +5,8 @@
 # Makefile for the Alchemy Au1xx0 CPUs, generic files.
 #
 
-obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-	sleeper.o dma.o dbdma.o vss.o irq.o usb.o
+obj-y += prom.o time.o clock.o platform.o power.o \
+	 setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/platform.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/platform.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -99,10 +100,20 @@ static struct platform_device au1xx0_uar
 
 static void __init alchemy_setup_uarts(int ctype)
 {
-	unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
+	long uartclk;
 	int s = sizeof(struct plat_serial8250_port);
 	int c = alchemy_get_uarts(ctype);
 	struct plat_serial8250_port *ports;
+	struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
+
+	if (IS_ERR(clk))
+		return;
+	if (clk_prepare_enable(clk)) {
+		clk_put(clk);
+		return;
+	}
+	uartclk = clk_get_rate(clk);
+	clk_put(clk);
 
 	ports = kzalloc(s * (c + 1), GFP_KERNEL);
 	if (!ports) {
@@ -420,7 +431,7 @@ static void __init alchemy_setup_macs(in
 		memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
 
 	/* Register second MAC if enabled in pinfunc */
-	if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) {
+	if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
 		ret = platform_device_register(&au1xxx_eth1_device);
 		if (ret)
 			printk(KERN_INFO "Alchemy: failed to register MAC1\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/power.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/power.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/power.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,28 +54,28 @@ static unsigned int sleep_static_memctlr
 static void save_core_regs(void)
 {
 	/* Clocks and PLLs. */
-	sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
-	sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
-	sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
-	sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
-	sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
+	sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
+	sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
+	sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
+	sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
+	sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
 
 	/* pin mux config */
-	sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
+	sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
 
 	/* Save the static memory controller configuration. */
-	sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
-	sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
-	sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
-	sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
-	sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
-	sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
-	sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
-	sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
-	sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
-	sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
-	sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
-	sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+	sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
+	sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
+	sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
+	sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
+	sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
+	sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
+	sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
+	sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
+	sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
+	sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
+	sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
+	sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
 }
 
 static void restore_core_regs(void)
@@ -85,30 +85,28 @@ static void restore_core_regs(void)
 	 * one of those Au1000 with a write-only PLL, where we dont
 	 * have a valid value)
 	 */
-	au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
-	au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
-	au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
-	au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+	alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
+	alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
+	alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
+	alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
 	if (!au1xxx_cpu_has_pll_wo())
-		au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
-	au_sync();
+		alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
 
-	au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
-	au_sync();
+	alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
 
 	/* Restore the static memory controller configuration. */
-	au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
-	au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
-	au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
-	au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
-	au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
-	au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
-	au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
-	au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
-	au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
-	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
-	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
-	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+	alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
+	alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
+	alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
+	alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
+	alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
+	alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
+	alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
+	alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
+	alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
+	alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
+	alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
+	alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
 }
 
 void au_sleep(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/setup.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/setup.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,12 +27,9 @@
 
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
 
 #include <asm/dma-coherence.h>
 #include <asm/mipsregs.h>
-#include <asm/time.h>
 
 #include <au1000.h>
 
@@ -41,18 +38,6 @@ extern void set_cpuspec(void);
 
 void __init plat_mem_setup(void)
 {
-	unsigned long est_freq;
-
-	/* determine core clock */
-	est_freq = au1xxx_calc_clock();
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq % 10000;
-	printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
-	       est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
-
-	/* this is faster than wasting cycles trying to approximate it */
-	preset_lpj = (est_freq >> 1) / HZ;
-
 	if (au1xxx_cpu_needs_config_od())
 		/* Various early Au1xx0 errata corrected by this */
 		set_c0_config(1 << 19); /* Set Config[OD] */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/time.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/time.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@
 
 static cycle_t au1x_counter1_read(struct clocksource *cs)
 {
-	return au_readl(SYS_RTCREAD);
+	return alchemy_rdsys(AU1000_SYS_RTCREAD);
 }
 
 static struct clocksource au1x_counter1_clocksource = {
@@ -60,12 +60,11 @@ static struct clocksource au1x_counter1_
 static int au1x_rtcmatch2_set_next_event(unsigned long delta,
 					 struct clock_event_device *cd)
 {
-	delta += au_readl(SYS_RTCREAD);
+	delta += alchemy_rdsys(AU1000_SYS_RTCREAD);
 	/* wait for register access */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21)
 		;
-	au_writel(delta, SYS_RTCMATCH2);
-	au_sync();
+	alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2);
 
 	return 0;
 }
@@ -112,31 +111,29 @@ static int __init alchemy_time_init(unsi
 	 * (the 32S bit seems to be stuck set to 1 once a single clock-
 	 * edge is detected, hence the timeouts).
 	 */
-	if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+	if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK))
 		goto cntr_err;
 
 	/*
 	 * setup counter 1 (RTC) to tick at full speed
 	 */
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
 
-	au_writel(0, SYS_RTCTRIM);	/* 32.768 kHz */
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_RTCTRIM);	/* 32.768 kHz */
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
-	au_writel(0, SYS_RTCWRITE);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_RTCWRITE);
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/common/usb.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/usb.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/common/usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/common/usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -387,10 +388,25 @@ static inline void au1200_usb_init(void)
 	udelay(1000);
 }
 
-static inline void au1000_usb_init(unsigned long rb, int reg)
+static inline int au1000_usb_init(unsigned long rb, int reg)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
 	unsigned long r = __raw_readl(base);
+	struct clk *c;
+
+	/* 48MHz check. Don't init if no one can provide it */
+	c = clk_get(NULL, "usbh_clk");
+	if (IS_ERR(c))
+		return -ENODEV;
+	if (clk_round_rate(c, 48000000) != 48000000) {
+		clk_put(c);
+		return -ENODEV;
+	}
+	if (clk_set_rate(c, 48000000)) {
+		clk_put(c);
+		return -ENODEV;
+	}
+	clk_put(c);
 
 #if defined(__BIG_ENDIAN)
 	r |= USBHEN_BE;
@@ -400,6 +416,8 @@ static inline void au1000_usb_init(unsig
 	__raw_writel(r, base);
 	wmb();
 	udelay(1000);
+
+	return 0;
 }
 
 
@@ -407,8 +425,15 @@ static inline void __au1xx0_ohci_control
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
 	unsigned long r = __raw_readl(base + creg);
+	struct clk *c = clk_get(NULL, "usbh_clk");
+
+	if (IS_ERR(c))
+		return;
 
 	if (enable) {
+		if (clk_prepare_enable(c))
+			goto out;
+
 		__raw_writel(r | USBHEN_CE, base + creg);
 		wmb();
 		udelay(1000);
@@ -423,7 +448,10 @@ static inline void __au1xx0_ohci_control
 	} else {
 		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
 		wmb();
+		clk_disable_unprepare(c);
 	}
+out:
+	clk_put(c);
 }
 
 static inline int au1000_usb_control(int block, int enable, unsigned long rb,
@@ -457,11 +485,11 @@ int alchemy_usb_control(int block, int e
 	case ALCHEMY_CPU_AU1500:
 	case ALCHEMY_CPU_AU1100:
 		ret = au1000_usb_control(block, enable,
-				AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+			AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1550:
 		ret = au1000_usb_control(block, enable,
-				AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+			AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1200:
 		ret = au1200_usb_control(block, enable);
@@ -569,14 +597,18 @@ static struct syscore_ops alchemy_usb_pm
 
 static int __init alchemy_usb_init(void)
 {
+	int ret = 0;
+
 	switch (alchemy_get_cputype()) {
 	case ALCHEMY_CPU_AU1000:
 	case ALCHEMY_CPU_AU1500:
 	case ALCHEMY_CPU_AU1100:
-		au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+		ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
+				      AU1000_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1550:
-		au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+		ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
+				      AU1550_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1200:
 		au1200_usb_init();
@@ -586,8 +618,9 @@ static int __init alchemy_usb_init(void)
 		break;
 	}
 
-	register_syscore_ops(&alchemy_usb_pm_ops);
+	if (!ret)
+		register_syscore_ops(&alchemy_usb_pm_ops);
 
-	return 0;
+	return ret;
 }
 arch_initcall(alchemy_usb_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1000.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1000.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1000.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
@@ -496,6 +497,7 @@ int __init db1000_dev_setup(void)
 	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
 	unsigned long pfc;
+	struct clk *c, *p;
 
 	if (board == BCSR_WHOAMI_DB1500) {
 		c0 = AU1500_GPIO2_INT;
@@ -518,14 +520,25 @@ int __init db1000_dev_setup(void)
 		gpio_direction_input(20);	/* sd1 cd# */
 
 		/* spi_gpio on SSI0 pins */
-		pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
+		pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
 		pfc |= (1 << 0);	/* SSI0 pins as GPIOs */
-		__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-		wmb();
+		alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
 		spi_register_board_info(db1100_spi_info,
 					ARRAY_SIZE(db1100_spi_info));
 
+		/* link LCD clock to AUXPLL */
+		p = clk_get(NULL, "auxpll_clk");
+		c = clk_get(NULL, "lcd_intclk");
+		if (!IS_ERR(c) && !IS_ERR(p)) {
+			clk_set_parent(c, p);
+			clk_set_rate(c, clk_get_rate(p));
+		}
+		if (!IS_ERR(c))
+			clk_put(c);
+		if (!IS_ERR(p))
+			clk_put(p);
+
 		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
 		platform_device_register(&db1100_spi_dev);
 	} else if (board == BCSR_WHOAMI_DB1000) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1200.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1200.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1200.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -129,7 +130,6 @@ static int __init db1200_detect_board(vo
 
 int __init db1200_board_setup(void)
 {
-	unsigned long freq0, clksrc, div, pfc;
 	unsigned short whoami;
 
 	if (db1200_detect_board())
@@ -149,34 +149,6 @@ int __init db1200_board_setup(void)
 		"  Board-ID %d	Daughtercard ID %d\n", get_system_type(),
 		(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
 
-	/* SMBus/SPI on PSC0, Audio on PSC1 */
-	pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
-	pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
-	pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
-	pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
-	__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-	wmb();
-
-	/* Clock configurations: PSC0: ~50MHz via Clkgen0, derived from
-	 * CPU clock; all other clock generators off/unused.
-	 */
-	div = (get_au1x00_speed() + 25000000) / 50000000;
-	if (div & 1)
-		div++;
-	div = ((div >> 1) - 1) & 0xff;
-
-	freq0 = div << SYS_FC_FRDIV0_BIT;
-	__raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-	wmb();
-	freq0 |= SYS_FC_FE0;	/* enable F0 */
-	__raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-	wmb();
-
-	/* psc0_intclk comes 1:1 from F0 */
-	clksrc = SYS_CS_MUX_FQ0 << SYS_CS_ME0_BIT;
-	__raw_writel(clksrc, (void __iomem *)SYS_CLKSRC);
-	wmb();
-
 	return 0;
 }
 
@@ -250,7 +222,7 @@ static void au1200_nand_cmd_ctrl(struct
 
 static int au1200_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1200_nand_parts[] = {
@@ -847,6 +819,7 @@ int __init db1200_dev_setup(void)
 	unsigned long pfc;
 	unsigned short sw;
 	int swapped, bid;
+	struct clk *c;
 
 	bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 	if ((bid == BCSR_WHOAMI_PB1200_DDR1) ||
@@ -859,6 +832,25 @@ int __init db1200_dev_setup(void)
 	irq_set_irq_type(AU1200_GPIO7_INT, IRQ_TYPE_LEVEL_LOW);
 	bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
 
+	/* SMBus/SPI on PSC0, Audio on PSC1 */
+	pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
+	pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
+	pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
+	pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
+	alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
+
+	/* get 50MHz for I2C driver on PSC0 */
+	c = clk_get(NULL, "psc0_intclk");
+	if (!IS_ERR(c)) {
+		pfc = clk_round_rate(c, 50000000);
+		if ((pfc < 1) || (abs(50000000 - pfc) > 2500000))
+			pr_warn("DB1200: cant get I2C close to 50MHz\n");
+		else
+			clk_set_rate(c, pfc);
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
+
 	/* insert/eject pairs: one of both is always screaming.	 To avoid
 	 * issues they must not be automatically enabled when initially
 	 * requested.
@@ -886,7 +878,7 @@ int __init db1200_dev_setup(void)
 	 * As a result, in SPI mode, OTG simply won't work (PSC0 uses
 	 * it as an input pin which is pulled high on the boards).
 	 */
-	pfc = __raw_readl((void __iomem *)SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
+	pfc = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
 
 	/* switch off OTG VBUS supply */
 	gpio_request(215, "otg-vbus");
@@ -912,8 +904,7 @@ int __init db1200_dev_setup(void)
 		printk(KERN_INFO " S6.8 ON : PSC0 mode SPI\n");
 		printk(KERN_INFO "   OTG port VBUS supply disabled\n");
 	}
-	__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-	wmb();
+	alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
 	/* Audio: DIP7 selects I2S(0)/AC97(1), but need I2C for I2S!
 	 * so: DIP7=1 || DIP8=0 => AC97, DIP7=0 && DIP8=1 => I2S
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1300.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1300.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1300.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1300.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
  * (c) 2009 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
@@ -169,7 +170,7 @@ static void au1300_nand_cmd_ctrl(struct
 
 static int au1300_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1300_nand_parts[] = {
@@ -731,6 +732,7 @@ static struct platform_device *db1300_de
 int __init db1300_dev_setup(void)
 {
 	int swapped, cpldirq;
+	struct clk *c;
 
 	/* setup CPLD IRQ muxer */
 	cpldirq = au1300_gpio_to_irq(AU1300_PIN_EXTCLK1);
@@ -761,6 +763,11 @@ int __init db1300_dev_setup(void)
 	    (void __iomem *)KSEG1ADDR(AU1300_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
 	/* I2C uses internal 48MHz EXTCLK1 */
+	c = clk_get(NULL, "psc3_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
 	__raw_writel(PSC_SEL_CLK_INTCLK,
 	    (void __iomem *)KSEG1ADDR(AU1300_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1550.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1550.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/devboards/db1550.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/db1550.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
  * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -31,16 +32,16 @@
 static void __init db1550_hw_setup(void)
 {
 	void __iomem *base;
+	unsigned long v;
 
 	/* complete SPI setup: link psc0_intclk to a 48MHz source,
 	 * and assign GPIO16 to PSC0_SYNC1 (SPI cs# line) as well as PSC1_SYNC
 	 * for AC97 on PB1550.
 	 */
-	base = (void __iomem *)SYS_CLKSRC;
-	__raw_writel(__raw_readl(base) | 0x000001e0, base);
-	base = (void __iomem *)SYS_PINFUNC;
-	__raw_writel(__raw_readl(base) | 1 | SYS_PF_PSC1_S1, base);
-	wmb();
+	v = alchemy_rdsys(AU1000_SYS_CLKSRC);
+	alchemy_wrsys(v | 0x000001e0, AU1000_SYS_CLKSRC);
+	v = alchemy_rdsys(AU1000_SYS_PINFUNC);
+	alchemy_wrsys(v | 1 | SYS_PF_PSC1_S1, AU1000_SYS_PINFUNC);
 
 	/* reset the AC97 codec now, the reset time in the psc-ac97 driver
 	 * is apparently too short although it's ridiculous as it is.
@@ -151,7 +152,7 @@ static void au1550_nand_cmd_ctrl(struct
 
 static int au1550_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1550_nand_parts[] = {
@@ -217,7 +218,7 @@ static struct platform_device pb1550_nan
 
 static void __init pb1550_nand_setup(void)
 {
-	int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) |
+	int boot_swapboot = (alchemy_rdsmem(AU1000_MEM_STSTAT) & (0x7 << 1)) |
 			    ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
 
 	gpio_direction_input(206);	/* de-assert NAND CS# */
@@ -574,6 +575,7 @@ static void __init pb1550_devices(void)
 int __init db1550_dev_setup(void)
 {
 	int swapped, id;
+	struct clk *c;
 
 	id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550);
 
@@ -582,6 +584,17 @@ int __init db1550_dev_setup(void)
 	spi_register_board_info(db1550_spi_devs,
 				ARRAY_SIZE(db1550_i2c_devs));
 
+	c = clk_get(NULL, "psc0_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
+	c = clk_get(NULL, "psc2_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
+
 	/* Audio PSC clock is supplied by codecs (PSC1, 3) FIXME: platdata!! */
 	__raw_writel(PSC_SEL_CLK_SERCLK,
 	    (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/alchemy/devboards/pm.c linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/pm.c
--- linux-libre-3.16-gnu/arch/mips/alchemy/devboards/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/alchemy/devboards/pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,23 +45,20 @@ static int db1x_pm_enter(suspend_state_t
 	alchemy_gpio1_input_enable();
 
 	/* clear and setup wake cause and source */
-	au_writel(0, SYS_WAKEMSK);
-	au_sync();
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 
-	au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
-	au_sync();
+	alchemy_wrsys(db1x_pm_wakemsk, AU1000_SYS_WAKEMSK);
 
 	/* setup 1Hz-timer-based wakeup: wait for reg access */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
 		asm volatile ("nop");
 
-	au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
-	au_sync();
+	alchemy_wrsys(alchemy_rdsys(AU1000_SYS_TOYREAD) + db1x_pm_sleep_secs,
+		      AU1000_SYS_TOYMATCH2);
 
 	/* wait for value to really hit the register */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
 		asm volatile ("nop");
 
 	/* ...and now the sandman can come! */
@@ -102,12 +99,10 @@ static void db1x_pm_end(void)
 	/* read and store wakeup source, the clear the register. To
 	 * be able to clear it, WAKEMSK must be cleared first.
 	 */
-	db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
-
-	au_writel(0, SYS_WAKEMSK);
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
+	db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 }
 
 static const struct platform_suspend_ops db1x_pm_ops = {
@@ -242,17 +237,13 @@ static int __init pm_init(void)
 	 * for confirmation since there's plenty of time from here to
 	 * the next suspend cycle.
 	 */
-	if (au_readl(SYS_TOYTRIM) != 32767) {
-		au_writel(32767, SYS_TOYTRIM);
-		au_sync();
-	}
+	if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767)
+		alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
 
-	db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+	db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
-	au_writel(0, SYS_WAKEMSK);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
 
 	suspend_set_ops(&db1x_pm_ops);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/bcm47xx_private.h linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/bcm47xx_private.h
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/bcm47xx_private.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/bcm47xx_private.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,9 @@
 
 #include <linux/kernel.h>
 
+/* prom.c */
+void __init bcm47xx_prom_highmem_init(void);
+
 /* buttons.c */
 int __init bcm47xx_buttons_register(void);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/board.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/board.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/board.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/board.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,6 +58,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
 	{{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
+	{{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
 	{{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
 	{{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
 	{{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
@@ -80,6 +81,14 @@ struct bcm47xx_board_type_list1 bcm47xx_
 	{ {0}, NULL},
 };
 
+/* hardware_version, boardnum */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
+	{{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
+	{{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
+	{ {0}, NULL},
+};
+
 /* productid */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
@@ -98,7 +107,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
 /* ModelId */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
-	{{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+	{{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
 	{{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
 	{{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
 	{{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
@@ -180,9 +189,9 @@ struct bcm47xx_board_type_list3 bcm47xx_
 	{{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
 	{{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
 	{{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
 	{ {0}, NULL},
 };
 
@@ -237,6 +246,15 @@ static __init const struct bcm47xx_board
 		}
 	}
 
+	if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
+		for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+			if (!strstarts(buf1, e2->value1) &&
+			    !strcmp(buf2, e2->value2))
+				return &e2->board;
+		}
+	}
+
 	if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/buttons.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/buttons.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/buttons.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/buttons.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,11 @@ bcm47xx_buttons_asus_wl330ge[] __initcon
 };
 
 static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500g[] __initconst = {
+	BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
 bcm47xx_buttons_asus_wl500gd[] __initconst = {
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -265,7 +270,7 @@ bcm47xx_buttons_linksys_wrt54g3gv2[] __i
 };
 
 static const struct gpio_keys_button
-bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -288,6 +293,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __in
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
 
+/* Microsoft */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_microsoft_nm700[] __initconst = {
+	BCM47XX_GPIO_KEY(7, KEY_RESTART),
+};
+
 /* Motorola */
 
 static const struct gpio_keys_button
@@ -329,6 +341,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __i
 };
 
 static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
+	BCM47XX_GPIO_KEY(4, KEY_RESTART),
+	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
 bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -395,6 +413,9 @@ int __init bcm47xx_buttons_register(void
 	case BCM47XX_BOARD_ASUS_WL330GE:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
 		break;
+	case BCM47XX_BOARD_ASUS_WL500G:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
+		break;
 	case BCM47XX_BOARD_ASUS_WL500GD:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
 		break;
@@ -501,12 +522,14 @@ int __init bcm47xx_buttons_register(void
 	case BCM47XX_BOARD_LINKSYS_WRT310NV1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
 		break;
-	case BCM47XX_BOARD_LINKSYS_WRT54G:
-		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
-		break;
 	case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
 		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
+		break;
 	case BCM47XX_BOARD_LINKSYS_WRT610NV1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
 		break;
@@ -517,6 +540,10 @@ int __init bcm47xx_buttons_register(void
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
 		break;
 
+	case BCM47XX_BOARD_MICROSOFT_MN700:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
+		break;
+
 	case BCM47XX_BOARD_MOTOROLA_WE800G:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
 		break;
@@ -536,6 +563,9 @@ int __init bcm47xx_buttons_register(void
 	case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
 		break;
+	case BCM47XX_BOARD_NETGEAR_WNR3500L:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
+		break;
 	case BCM47XX_BOARD_NETGEAR_WNR834BV2:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/Kconfig linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/Kconfig
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,6 @@ config BCM47XX_SSB
 	select SSB_DRIVER_PCICORE if PCI
 	select SSB_PCICORE_HOSTMODE if PCI
 	select SSB_DRIVER_GPIO
-	select GPIOLIB
-	select LEDS_GPIO_REGISTER
 	default y
 	help
 	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -22,6 +20,7 @@ config BCM47XX_SSB
 config BCM47XX_BCMA
 	bool "BCMA Support for Broadcom BCM47XX"
 	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_HIGHMEM
 	select CPU_MIPSR2_IRQ_VI
 	select BCMA
 	select BCMA_HOST_SOC
@@ -29,8 +28,6 @@ config BCM47XX_BCMA
 	select BCMA_HOST_PCI if PCI
 	select BCMA_DRIVER_PCI_HOSTMODE if PCI
 	select BCMA_DRIVER_GPIO
-	select GPIOLIB
-	select LEDS_GPIO_REGISTER
 	default y
 	help
 	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/leds.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/leds.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/leds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/leds.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,15 @@ bcm47xx_leds_asus_rtn12[] __initconst =
 };
 
 static const struct gpio_led
+bcm47xx_leds_asus_rtn15u[] __initconst = {
+	/* TODO: Add "wlan" LED */
+	BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
 bcm47xx_leds_asus_rtn16[] __initconst = {
 	BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -42,8 +51,8 @@ bcm47xx_leds_asus_rtn16[] __initconst =
 
 static const struct gpio_led
 bcm47xx_leds_asus_rtn66u[] __initconst = {
-	BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-	BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
 };
 
 static const struct gpio_led
@@ -64,6 +73,11 @@ bcm47xx_leds_asus_wl330ge[] __initconst
 };
 
 static const struct gpio_led
+bcm47xx_leds_asus_wl500g[] __initconst = {
+	BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
 bcm47xx_leds_asus_wl500gd[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 };
@@ -216,8 +230,8 @@ bcm47xx_leds_linksys_e1000v1[] __initcon
 
 static const struct gpio_led
 bcm47xx_leds_linksys_e1000v21[] __initconst = {
-	BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
 	BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
@@ -292,7 +306,7 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc
 };
 
 static const struct gpio_led
-bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
 	BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -306,6 +320,24 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __init
 	BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
 
+/* Verified on: WRT54GS V1.0 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
+	BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Verified on: WRT54GL V1.1 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
+	BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
 static const struct gpio_led
 bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "usb",  1, LEDS_GPIO_DEFSTATE_OFF),
@@ -325,11 +357,17 @@ bcm47xx_leds_linksys_wrt610nv2[] __initc
 
 static const struct gpio_led
 bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
-	BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-	BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Microsoft */
+
+static const struct gpio_led
+bcm47xx_leds_microsoft_nm700[] __initconst = {
+	BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 };
 
 /* Motorola */
@@ -377,6 +415,15 @@ bcm47xx_leds_netgear_wndr4500v1[] __init
 };
 
 static const struct gpio_led
+bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
+	BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
 bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
 	BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -417,6 +464,9 @@ void __init bcm47xx_leds_register(void)
 	case BCM47XX_BOARD_ASUS_RTN12:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
 		break;
+	case BCM47XX_BOARD_ASUS_RTN15U:
+		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
+		break;
 	case BCM47XX_BOARD_ASUS_RTN16:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
 		break;
@@ -432,6 +482,9 @@ void __init bcm47xx_leds_register(void)
 	case BCM47XX_BOARD_ASUS_WL330GE:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
 		break;
+	case BCM47XX_BOARD_ASUS_WL500G:
+		bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
+		break;
 	case BCM47XX_BOARD_ASUS_WL500GD:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
 		break;
@@ -538,12 +591,18 @@ void __init bcm47xx_leds_register(void)
 	case BCM47XX_BOARD_LINKSYS_WRT310NV1:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
 		break;
-	case BCM47XX_BOARD_LINKSYS_WRT54G:
-		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
-		break;
 	case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
 		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
+		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
+		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+		break;
 	case BCM47XX_BOARD_LINKSYS_WRT610NV1:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
 		break;
@@ -554,6 +613,10 @@ void __init bcm47xx_leds_register(void)
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
 		break;
 
+	case BCM47XX_BOARD_MICROSOFT_MN700:
+		bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
+		break;
+
 	case BCM47XX_BOARD_MOTOROLA_WE800G:
 		bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
 		break;
@@ -570,6 +633,9 @@ void __init bcm47xx_leds_register(void)
 	case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
 		bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
 		break;
+	case BCM47XX_BOARD_NETGEAR_WNR3500L:
+		bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
+		break;
 	case BCM47XX_BOARD_NETGEAR_WNR834BV2:
 		bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/prom.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/prom.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/prom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/prom.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,8 @@ __init void bcm47xx_set_system_type(u16
 		 chip_id);
 }
 
+static unsigned long lowmem __initdata;
+
 static __init void prom_init_mem(void)
 {
 	unsigned long mem;
@@ -87,6 +89,7 @@ static __init void prom_init_mem(void)
 		if (!memcmp(prom_init, prom_init + mem, 32))
 			break;
 	}
+	lowmem = mem;
 
 	/* Ignoring the last page when ddr size is 128M. Cached
 	 * accesses to last page is causing the processor to prefetch
@@ -95,7 +98,6 @@ static __init void prom_init_mem(void)
 	 */
 	if (c->cputype == CPU_74K && (mem == (128  << 20)))
 		mem -= 0x1000;
-
 	add_memory_region(0, mem, BOOT_MEM_RAM);
 }
 
@@ -114,3 +116,67 @@ void __init prom_init(void)
 void __init prom_free_prom_memory(void)
 {
 }
+
+#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
+
+#define EXTVBASE	0xc0000000
+#define ENTRYLO(x)	((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
+
+#include <asm/tlbflush.h>
+
+/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
+ * dropped. Calling it at this stage causes a hang.
+ */
+void __cpuinit early_tlb_init(void)
+{
+	write_c0_pagemask(PM_DEFAULT_MASK);
+	write_c0_wired(0);
+	temp_tlb_entry = current_cpu_data.tlbsize - 1;
+	local_flush_tlb_all();
+}
+
+void __init bcm47xx_prom_highmem_init(void)
+{
+	unsigned long off = (unsigned long)prom_init;
+	unsigned long extmem = 0;
+	bool highmem_region = false;
+
+	if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
+		return;
+
+	if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
+		highmem_region = true;
+
+	if (lowmem != 128 << 20 || !highmem_region)
+		return;
+
+	early_tlb_init();
+
+	/* Add one temporary TLB entry to map SDRAM Region 2.
+	 *      Physical        Virtual
+	 *      0x80000000      0xc0000000      (1st: 256MB)
+	 *      0x90000000      0xd0000000      (2nd: 256MB)
+	 */
+	add_temporary_entry(ENTRYLO(0x80000000),
+			    ENTRYLO(0x80000000 + (256 << 20)),
+			    EXTVBASE, PM_256M);
+
+	off = EXTVBASE + __pa(off);
+	for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
+		if (!memcmp(prom_init, (void *)(off + extmem), 16))
+			break;
+	}
+	extmem -= lowmem;
+
+	early_tlb_init();
+
+	if (!extmem)
+		return;
+
+	pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
+		extmem >> 20);
+
+	/* TODO: Register extra memory */
+}
+
+#endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/setup.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/setup.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,16 @@ static void bcm47xx_machine_restart(char
 	switch (bcm47xx_bus_type) {
 #ifdef CONFIG_BCM47XX_SSB
 	case BCM47XX_BUS_TYPE_SSB:
+		if (bcm47xx_bus.ssb.chip_id == 0x4785)
+			write_c0_diag4(1 << 22);
 		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+		if (bcm47xx_bus.ssb.chip_id == 0x4785) {
+			__asm__ __volatile__(
+				".set\tmips3\n\t"
+				"sync\n\t"
+				"wait\n\t"
+				".set\tmips0");
+		}
 		break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
@@ -218,6 +227,9 @@ void __init plat_mem_setup(void)
 		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
 		bcm47xx_register_bcma();
 		bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
+#ifdef CONFIG_HIGHMEM
+		bcm47xx_prom_highmem_init();
+#endif
 #endif
 	} else {
 		printk(KERN_INFO "bcm47xx: using ssb bus\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm47xx/sprom.c linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/sprom.c
--- linux-libre-3.16-gnu/arch/mips/bcm47xx/sprom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm47xx/sprom.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,8 @@
 
 #include <bcm47xx.h>
 #include <bcm47xx_nvram.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 static void create_key(const char *prefix, const char *postfix,
 		       const char *name, char *buf, int len)
@@ -631,6 +633,33 @@ static void bcm47xx_fill_sprom_path_r45(
 	}
 }
 
+static bool bcm47xx_is_valid_mac(u8 *mac)
+{
+	return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
+}
+
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
+{
+	u8 *oui = mac + ETH_ALEN/2 - 1;
+	u8 *p = mac + ETH_ALEN - 1;
+
+	do {
+		(*p) += num;
+		if (*p > num)
+			break;
+		p--;
+		num = 1;
+	} while (p != oui);
+
+	if (p == oui) {
+		pr_err("unable to fetch mac address\n");
+		return -ENOENT;
+	}
+	return 0;
+}
+
+static int mac_addr_used = 2;
+
 static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
 					const char *prefix, bool fallback)
 {
@@ -648,6 +677,25 @@ static void bcm47xx_fill_sprom_ethernet(
 
 	nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
 	nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+
+	/* The address prefix 00:90:4C is used by Broadcom in their initial
+	   configuration. When a mac address with the prefix 00:90:4C is used
+	   all devices from the same series are sharing the same mac address.
+	   To prevent mac address collisions we replace them with a mac address
+	   based on the base address. */
+	if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
+		u8 mac[6];
+
+		nvram_read_macaddr(NULL, "et0macaddr", mac, false);
+		if (bcm47xx_is_valid_mac(mac)) {
+			int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
+
+			if (!err) {
+				ether_addr_copy(sprom->il0mac, mac);
+				mac_addr_used++;
+			}
+		}
+	}
 }
 
 static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/cpu.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/cpu.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,9 @@ EXPORT_SYMBOL(bcm63xx_regs_base);
 const int *bcm63xx_irqs;
 EXPORT_SYMBOL(bcm63xx_irqs);
 
-static u16 bcm63xx_cpu_id;
+u16 bcm63xx_cpu_id __read_mostly;
+EXPORT_SYMBOL(bcm63xx_cpu_id);
+
 static u8 bcm63xx_cpu_rev;
 static unsigned int bcm63xx_cpu_freq;
 static unsigned int bcm63xx_memory_size;
@@ -97,13 +99,6 @@ static const int bcm6368_irqs[] = {
 
 };
 
-u16 __bcm63xx_get_cpu_id(void)
-{
-	return bcm63xx_cpu_id;
-}
-
-EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
-
 u8 bcm63xx_get_cpu_rev(void)
 {
 	return bcm63xx_cpu_rev;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/dev-enet.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/dev-enet.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/dev-enet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/dev-enet.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,6 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 static const unsigned long bcm6348_regs_enetdmac[] = {
 	[ENETDMAC_CHANCFG]	= ENETDMAC_CHANCFG_REG,
 	[ENETDMAC_IR]		= ENETDMAC_IR_REG,
@@ -43,9 +42,6 @@ static __init void bcm63xx_enetdmac_regs
 	else
 		bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
 }
-#else
-static __init void bcm63xx_enetdmac_regs_init(void) { }
-#endif
 
 static struct resource shared_res[] = {
 	{
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/dev-spi.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/dev-spi.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/dev-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/dev-spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@
 #include <bcm63xx_dev_spi.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 /*
  * register offsets
  */
@@ -41,9 +40,6 @@ static __init void bcm63xx_spi_regs_init
 		BCMCPU_IS_6362() || BCMCPU_IS_6368())
 		bcm63xx_regs_spi = bcm6358_regs_spi;
 }
-#else
-static __init void bcm63xx_spi_regs_init(void) { }
-#endif
 
 static struct resource spi_resources[] = {
 	{
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/gpio.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/gpio.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,19 +18,6 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifndef BCMCPU_RUNTIME_DETECT
-#define gpio_out_low_reg	GPIO_DATA_LO_REG
-#ifdef CONFIG_BCM63XX_CPU_6345
-#ifdef gpio_out_low_reg
-#undef gpio_out_low_reg
-#define gpio_out_low_reg	GPIO_DATA_LO_REG_6345
-#endif /* gpio_out_low_reg */
-#endif /* CONFIG_BCM63XX_CPU_6345 */
-
-static inline void bcm63xx_gpio_out_low_reg_init(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
 static u32 gpio_out_low_reg;
 
 static void bcm63xx_gpio_out_low_reg_init(void)
@@ -44,7 +31,6 @@ static void bcm63xx_gpio_out_low_reg_ini
 		break;
 	}
 }
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
 static u32 gpio_out_low, gpio_out_high;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/irq.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/irq.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/spinlock.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <bcm63xx_cpu.h>
@@ -19,222 +20,20 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_irq.h>
 
-static void __dispatch_internal(void) __maybe_unused;
-static void __dispatch_internal_64(void) __maybe_unused;
-static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
-
-#ifndef BCMCPU_RUNTIME_DETECT
-#ifdef CONFIG_BCM63XX_CPU_3368
-#define irq_stat_reg		PERF_IRQSTAT_3368_REG
-#define irq_mask_reg		PERF_IRQMASK_3368_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_3368
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-#define irq_stat_reg		PERF_IRQSTAT_6328_REG
-#define irq_mask_reg		PERF_IRQMASK_6328_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6328
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-#define irq_stat_reg		PERF_IRQSTAT_6338_REG
-#define irq_mask_reg		PERF_IRQMASK_6338_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6338
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-#define irq_stat_reg		PERF_IRQSTAT_6345_REG
-#define irq_mask_reg		PERF_IRQMASK_6345_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6345
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-#define irq_stat_reg		PERF_IRQSTAT_6348_REG
-#define irq_mask_reg		PERF_IRQMASK_6348_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6348
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-#define irq_stat_reg		PERF_IRQSTAT_6358_REG
-#define irq_mask_reg		PERF_IRQMASK_6358_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6358
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-#define irq_stat_reg		PERF_IRQSTAT_6362_REG
-#define irq_mask_reg		PERF_IRQMASK_6362_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6362
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-#define irq_stat_reg		PERF_IRQSTAT_6368_REG
-#define irq_mask_reg		PERF_IRQMASK_6368_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		6
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6368
-#define ext_irq_cfg_reg2	PERF_EXTIRQ_CFG_REG2_6368
-#endif
-
-#if irq_bits == 32
-#define dispatch_internal			__dispatch_internal
-#define internal_irq_mask			__internal_irq_mask_32
-#define internal_irq_unmask			__internal_irq_unmask_32
-#else
-#define dispatch_internal			__dispatch_internal_64
-#define internal_irq_mask			__internal_irq_mask_64
-#define internal_irq_unmask			__internal_irq_unmask_64
-#endif
-
-#define irq_stat_addr	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
-#define irq_mask_addr	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
 
-static inline void bcm63xx_init_irq(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
+static DEFINE_SPINLOCK(ipic_lock);
+static DEFINE_SPINLOCK(epic_lock);
 
-static u32 irq_stat_addr, irq_mask_addr;
-static void (*dispatch_internal)(void);
+static u32 irq_stat_addr[2];
+static u32 irq_mask_addr[2];
+static void (*dispatch_internal)(int cpu);
 static int is_ext_irq_cascaded;
 static unsigned int ext_irq_count;
 static unsigned int ext_irq_start, ext_irq_end;
 static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(unsigned int irq);
-static void (*internal_irq_unmask)(unsigned int irq);
-
-static void bcm63xx_init_irq(void)
-{
-	int irq_bits;
-
-	irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
-	irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
-
-	switch (bcm63xx_get_cpu_id()) {
-	case BCM3368_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_3368_REG;
-		irq_mask_addr += PERF_IRQMASK_3368_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
-		break;
-	case BCM6328_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6328_REG;
-		irq_mask_addr += PERF_IRQMASK_6328_REG;
-		irq_bits = 64;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
-		break;
-	case BCM6338_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6338_REG;
-		irq_mask_addr += PERF_IRQMASK_6338_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
-		break;
-	case BCM6345_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6345_REG;
-		irq_mask_addr += PERF_IRQMASK_6345_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
-		break;
-	case BCM6348_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6348_REG;
-		irq_mask_addr += PERF_IRQMASK_6348_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
-		break;
-	case BCM6358_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6358_REG;
-		irq_mask_addr += PERF_IRQMASK_6358_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
-		break;
-	case BCM6362_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6362_REG;
-		irq_mask_addr += PERF_IRQMASK_6362_REG;
-		irq_bits = 64;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
-		break;
-	case BCM6368_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6368_REG;
-		irq_mask_addr += PERF_IRQMASK_6368_REG;
-		irq_bits = 64;
-		ext_irq_count = 6;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
-		ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
-		break;
-	default:
-		BUG();
-	}
+static void (*internal_irq_mask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
 
-	if (irq_bits == 32) {
-		dispatch_internal = __dispatch_internal;
-		internal_irq_mask = __internal_irq_mask_32;
-		internal_irq_unmask = __internal_irq_unmask_32;
-	} else {
-		dispatch_internal = __dispatch_internal_64;
-		internal_irq_mask = __internal_irq_mask_64;
-		internal_irq_unmask = __internal_irq_unmask_64;
-	}
-}
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static inline u32 get_ext_irq_perf_reg(int irq)
 {
@@ -252,53 +51,113 @@ static inline void handle_internal(int i
 		do_IRQ(intbit + IRQ_INTERNAL_BASE);
 }
 
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+				     const struct cpumask *m)
+{
+	bool enable = cpu_online(cpu);
+
+#ifdef CONFIG_SMP
+	if (m)
+		enable &= cpu_isset(cpu, *m);
+	else if (irqd_affinity_was_set(d))
+		enable &= cpu_isset(cpu, *d->affinity);
+#endif
+	return enable;
+}
+
 /*
  * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
  * prioritize any interrupt relatively to another. the static counter
  * will resume the loop where it ended the last time we left this
  * function.
  */
-static void __dispatch_internal(void)
-{
-	u32 pending;
-	static int i;
-
-	pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
 
-	if (!pending)
-		return ;
-
-	while (1) {
-		int to_call = i;
-
-		i = (i + 1) & 0x1f;
-		if (pending & (1 << to_call)) {
-			handle_internal(to_call);
-			break;
-		}
-	}
+#define BUILD_IPIC_INTERNAL(width)					\
+void __dispatch_internal_##width(int cpu)				\
+{									\
+	u32 pending[width / 32];					\
+	unsigned int src, tgt;						\
+	bool irqs_pending = false;					\
+	static unsigned int i[2];					\
+	unsigned int *next = &i[cpu];					\
+	unsigned long flags;						\
+									\
+	/* read registers in reverse order */				\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+		u32 val;						\
+									\
+		val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
+		val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
+		pending[--tgt] = val;					\
+									\
+		if (val)						\
+			irqs_pending = true;				\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
+									\
+	if (!irqs_pending)						\
+		return;							\
+									\
+	while (1) {							\
+		unsigned int to_call = *next;				\
+									\
+		*next = (*next + 1) & (width - 1);			\
+		if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {	\
+			handle_internal(to_call);			\
+			break;						\
+		}							\
+	}								\
+}									\
+									\
+static void __internal_irq_mask_##width(struct irq_data *d)		\
+{									\
+	u32 val;							\
+	unsigned irq = d->irq - IRQ_INTERNAL_BASE;			\
+	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+	unsigned bit = irq & 0x1f;					\
+	unsigned long flags;						\
+	int cpu;							\
+									\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for_each_present_cpu(cpu) {					\
+		if (!irq_mask_addr[cpu])				\
+			break;						\
+									\
+		val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+		val &= ~(1 << bit);					\
+		bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
+}									\
+									\
+static void __internal_irq_unmask_##width(struct irq_data *d,		\
+					  const struct cpumask *m)	\
+{									\
+	u32 val;							\
+	unsigned irq = d->irq - IRQ_INTERNAL_BASE;			\
+	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+	unsigned bit = irq & 0x1f;					\
+	unsigned long flags;						\
+	int cpu;							\
+									\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for_each_present_cpu(cpu) {					\
+		if (!irq_mask_addr[cpu])				\
+			break;						\
+									\
+		val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+		if (enable_irq_for_cpu(cpu, d, m))			\
+			val |= (1 << bit);				\
+		else							\
+			val &= ~(1 << bit);				\
+		bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
 }
 
-static void __dispatch_internal_64(void)
-{
-	u64 pending;
-	static int i;
-
-	pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
-
-	if (!pending)
-		return ;
-
-	while (1) {
-		int to_call = i;
-
-		i = (i + 1) & 0x3f;
-		if (pending & (1ull << to_call)) {
-			handle_internal(to_call);
-			break;
-		}
-	}
-}
+BUILD_IPIC_INTERNAL(32);
+BUILD_IPIC_INTERNAL(64);
 
 asmlinkage void plat_irq_dispatch(void)
 {
@@ -317,8 +176,11 @@ asmlinkage void plat_irq_dispatch(void)
 		if (cause & CAUSEF_IP1)
 			do_IRQ(1);
 		if (cause & CAUSEF_IP2)
-			dispatch_internal();
-		if (!is_ext_irq_cascaded) {
+			dispatch_internal(0);
+		if (is_ext_irq_cascaded) {
+			if (cause & CAUSEF_IP3)
+				dispatch_internal(1);
+		} else {
 			if (cause & CAUSEF_IP3)
 				do_IRQ(IRQ_EXT_0);
 			if (cause & CAUSEF_IP4)
@@ -335,50 +197,14 @@ asmlinkage void plat_irq_dispatch(void)
  * internal IRQs operations: only mask/unmask on PERF irq mask
  * register.
  */
-static void __internal_irq_mask_32(unsigned int irq)
-{
-	u32 mask;
-
-	mask = bcm_readl(irq_mask_addr);
-	mask &= ~(1 << irq);
-	bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_mask_64(unsigned int irq)
-{
-	u64 mask;
-
-	mask = bcm_readq(irq_mask_addr);
-	mask &= ~(1ull << irq);
-	bcm_writeq(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_32(unsigned int irq)
-{
-	u32 mask;
-
-	mask = bcm_readl(irq_mask_addr);
-	mask |= (1 << irq);
-	bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_64(unsigned int irq)
-{
-	u64 mask;
-
-	mask = bcm_readq(irq_mask_addr);
-	mask |= (1ull << irq);
-	bcm_writeq(mask, irq_mask_addr);
-}
-
 static void bcm63xx_internal_irq_mask(struct irq_data *d)
 {
-	internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
+	internal_irq_mask(d);
 }
 
 static void bcm63xx_internal_irq_unmask(struct irq_data *d)
 {
-	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
+	internal_irq_unmask(d, NULL);
 }
 
 /*
@@ -389,8 +215,10 @@ static void bcm63xx_external_irq_mask(st
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -399,16 +227,20 @@ static void bcm63xx_external_irq_mask(st
 		reg &= ~EXTIRQ_CFG_MASK(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
+
 	if (is_ext_irq_cascaded)
-		internal_irq_mask(irq + ext_irq_start);
+		internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
 }
 
 static void bcm63xx_external_irq_unmask(struct irq_data *d)
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -417,17 +249,21 @@ static void bcm63xx_external_irq_unmask(
 		reg |= EXTIRQ_CFG_MASK(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 
 	if (is_ext_irq_cascaded)
-		internal_irq_unmask(irq + ext_irq_start);
+		internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+				    NULL);
 }
 
 static void bcm63xx_external_irq_clear(struct irq_data *d)
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -436,6 +272,7 @@ static void bcm63xx_external_irq_clear(s
 		reg |= EXTIRQ_CFG_CLEAR(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 }
 
 static int bcm63xx_external_irq_set_type(struct irq_data *d,
@@ -444,6 +281,7 @@ static int bcm63xx_external_irq_set_type
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
 	int levelsense, sense, bothedge;
+	unsigned long flags;
 
 	flow_type &= IRQ_TYPE_SENSE_MASK;
 
@@ -478,6 +316,7 @@ static int bcm63xx_external_irq_set_type
 	}
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 	irq %= 4;
 
@@ -522,6 +361,7 @@ static int bcm63xx_external_irq_set_type
 	}
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 
 	irqd_set_trigger_type(d, flow_type);
 	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -532,6 +372,18 @@ static int bcm63xx_external_irq_set_type
 	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+					 const struct cpumask *dest,
+					 bool force)
+{
+	if (!irqd_irq_disabled(data))
+		internal_irq_unmask(data, dest);
+
+	return 0;
+}
+#endif
+
 static struct irq_chip bcm63xx_internal_irq_chip = {
 	.name		= "bcm63xx_ipic",
 	.irq_mask	= bcm63xx_internal_irq_mask,
@@ -554,12 +406,130 @@ static struct irqaction cpu_ip2_cascade_
 	.flags		= IRQF_NO_THREAD,
 };
 
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+	.handler	= no_action,
+	.name		= "cascade_ip3",
+	.flags		= IRQF_NO_THREAD,
+};
+#endif
+
 static struct irqaction cpu_ext_cascade_action = {
 	.handler	= no_action,
 	.name		= "cascade_extirq",
 	.flags		= IRQF_NO_THREAD,
 };
 
+static void bcm63xx_init_irq(void)
+{
+	int irq_bits;
+
+	irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
+	irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
+	irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
+	irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+
+	switch (bcm63xx_get_cpu_id()) {
+	case BCM3368_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+		break;
+	case BCM6328_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6328_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+		break;
+	case BCM6338_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+		break;
+	case BCM6345_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+		break;
+	case BCM6348_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+		break;
+	case BCM6358_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
+		irq_bits = 32;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+		break;
+	case BCM6362_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+		break;
+	case BCM6368_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 6;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
+		ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+		break;
+	default:
+		BUG();
+	}
+
+	if (irq_bits == 32) {
+		dispatch_internal = __dispatch_internal_32;
+		internal_irq_mask = __internal_irq_mask_32;
+		internal_irq_unmask = __internal_irq_unmask_32;
+	} else {
+		dispatch_internal = __dispatch_internal_64;
+		internal_irq_mask = __internal_irq_mask_64;
+		internal_irq_unmask = __internal_irq_unmask_64;
+	}
+}
+
 void __init arch_init_irq(void)
 {
 	int i;
@@ -580,4 +550,14 @@ void __init arch_init_irq(void)
 	}
 
 	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+	if (is_ext_irq_cascaded) {
+		setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+		bcm63xx_internal_irq_chip.irq_set_affinity =
+			bcm63xx_internal_set_affinity;
+
+		cpumask_clear(irq_default_affinity);
+		cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+	}
+#endif
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/bcm63xx/reset.c linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/reset.c
--- linux-libre-3.16-gnu/arch/mips/bcm63xx/reset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/bcm63xx/reset.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,8 +125,6 @@
 #define BCM6368_RESET_PCIE	0
 #define BCM6368_RESET_PCIE_EXT	0
 
-#ifdef BCMCPU_RUNTIME_DETECT
-
 /*
  * core reset bits
  */
@@ -188,64 +186,6 @@ static int __init bcm63xx_reset_bits_ini
 
 	return 0;
 }
-#else
-
-#ifdef CONFIG_BCM63XX_CPU_3368
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(3368)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6328
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6328)
-};
-#define reset_reg PERF_SOFTRESET_6328_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6338
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6338)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6345
-static const u32 bcm63xx_reset_bits[] = { };
-#define reset_reg 0
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6348
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6348)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6358
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6358)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6362
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6362)
-};
-#define reset_reg PERF_SOFTRESET_6362_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6368
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6368)
-};
-#define reset_reg PERF_SOFTRESET_6368_REG
-#endif
-
-static int __init bcm63xx_reset_bits_init(void) { return 0; }
-#endif
 
 static DEFINE_SPINLOCK(reset_mutex);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/boot/compressed/decompress.c linux-libre-3.17-rc7-gnu/arch/mips/boot/compressed/decompress.c
--- linux-libre-3.16-gnu/arch/mips/boot/compressed/decompress.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/boot/compressed/decompress.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #include <asm/addrspace.h>
 
@@ -67,10 +68,24 @@ void error(char *x)
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
+unsigned long __stack_chk_guard;
+
+void __stack_chk_guard_setup(void)
+{
+	__stack_chk_guard = 0x000a0dff;
+}
+
+void __stack_chk_fail(void)
+{
+	error("stack-protector: Kernel stack is corrupted\n");
+}
+
 void decompress_kernel(unsigned long boot_heap_start)
 {
 	unsigned long zimage_start, zimage_size;
 
+	__stack_chk_guard_setup();
+
 	zimage_start = (unsigned long)(&__image_begin);
 	zimage_size = (unsigned long)(&__image_end) -
 	    (unsigned long)(&__image_begin);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-board.c linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
--- linux-libre-3.16-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-board.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-board.c	2014-09-28 17:29:07.000000000 -0400
@@ -186,6 +186,15 @@ int cvmx_helper_board_get_mii_address(in
 			return 7 - ipd_port;
 		else
 			return -1;
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
+		/*
+		 * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1)
+		 * connect to a switch (BCM53115).
+		 */
+		if (ipd_port == 2)
+			return 8;
+		else
+			return -1;
 	}
 
 	/* Some unknown board. Somebody forgot to update this function... */
@@ -274,6 +283,18 @@ cvmx_helper_link_info_t __cvmx_helper_bo
 			return result;
 		}
 		break;
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
+		if (ipd_port == 0 || ipd_port == 1) {
+			/* Ports 0 and 1 connect to a switch (BCM53115). */
+			result.s.link_up = 1;
+			result.s.full_duplex = 1;
+			result.s.speed = 1000;
+			return result;
+		} else {
+			/* Port 2 uses a Broadcom PHY (B5081). */
+			is_broadcom_phy = 1;
+		}
+		break;
 	}
 
 	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
@@ -738,6 +759,7 @@ enum cvmx_helper_board_usb_clock_types _
 	case CVMX_BOARD_TYPE_LANAI2_G:
 	case CVMX_BOARD_TYPE_NIC10E_66:
 	case CVMX_BOARD_TYPE_UBNT_E100:
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
 		return USB_CLOCK_TYPE_CRYSTAL_12;
 	case CVMX_BOARD_TYPE_NIC10E:
 		return USB_CLOCK_TYPE_REF_12;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
--- linux-libre-3.16-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c	2014-09-28 17:29:07.000000000 -0400
@@ -317,10 +317,14 @@ static int __cvmx_helper_sgmii_hardware_
 	for (index = 0; index < num_ports; index++) {
 		int ipd_port = cvmx_helper_get_ipd_port(interface, index);
 		__cvmx_helper_sgmii_hardware_init_one_time(interface, index);
-		__cvmx_helper_sgmii_link_set(ipd_port,
-					     __cvmx_helper_sgmii_link_get
-					     (ipd_port));
-
+		/* Linux kernel driver will call ....link_set with the
+		 * proper link state. In the simulator there is no
+		 * link state polling and hence it is set from
+		 * here.
+		 */
+		if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
+			__cvmx_helper_sgmii_link_set(ipd_port,
+				       __cvmx_helper_sgmii_link_get(ipd_port));
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/cavium-octeon/oct_ilm.c linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/oct_ilm.c
--- linux-libre-3.16-gnu/arch/mips/cavium-octeon/oct_ilm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/oct_ilm.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,8 +194,7 @@ err_irq:
 static __exit void oct_ilm_module_exit(void)
 {
 	disable_timer(TIMER_NUM);
-	if (dir)
-		debugfs_remove_recursive(dir);
+	debugfs_remove_recursive(dir);
 	free_irq(OCTEON_IRQ_TIMER0 + TIMER_NUM, 0);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/cavium-octeon/setup.c linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/setup.c
--- linux-libre-3.16-gnu/arch/mips/cavium-octeon/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -263,7 +263,6 @@ static uint64_t crashk_size, crashk_base
 static int octeon_uart;
 
 extern asmlinkage void handle_int(void);
-extern asmlinkage void plat_irq_dispatch(void);
 
 /**
  * Return non zero if we are currently running in the Octeon simulator
@@ -458,6 +457,18 @@ static void octeon_halt(void)
 	octeon_kill_core(NULL);
 }
 
+static char __read_mostly octeon_system_type[80];
+
+static int __init init_octeon_system_type(void)
+{
+	snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
+		cvmx_board_type_to_string(octeon_bootinfo->board_type),
+		octeon_model_get_string(read_c0_prid()));
+
+	return 0;
+}
+early_initcall(init_octeon_system_type);
+
 /**
  * Return a string representing the system type
  *
@@ -465,11 +476,7 @@ static void octeon_halt(void)
  */
 const char *octeon_board_type_string(void)
 {
-	static char name[80];
-	sprintf(name, "%s (%s)",
-		cvmx_board_type_to_string(octeon_bootinfo->board_type),
-		octeon_model_get_string(read_c0_prid()));
-	return name;
+	return octeon_system_type;
 }
 
 const char *get_system_type(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/cavium-octeon/smp.c linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/smp.c
--- linux-libre-3.16-gnu/arch/mips/cavium-octeon/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/cavium-octeon/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -84,9 +84,14 @@ static void octeon_smp_hotplug_setup(voi
 #ifdef CONFIG_HOTPLUG_CPU
 	struct linux_app_boot_info *labi;
 
+	if (!setup_max_cpus)
+		return;
+
 	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-	if (labi->labi_signature != LABI_SIGNATURE)
-		panic("The bootloader version on this board is incorrect.");
+	if (labi->labi_signature != LABI_SIGNATURE) {
+		pr_info("The bootloader on this board does not support HOTPLUG_CPU.");
+		return;
+	}
 
 	octeon_bootloader_entry_addr = labi->InitTLBStart_addr;
 #endif
@@ -129,7 +134,8 @@ static void octeon_smp_setup(void)
 	 * will assign CPU numbers for possible cores as well.	Cores
 	 * are always consecutively numberd from 0.
 	 */
-	for (id = 0; id < num_cores && id < NR_CPUS; id++) {
+	for (id = 0; setup_max_cpus && octeon_bootloader_entry_addr &&
+		     id < num_cores && id < NR_CPUS; id++) {
 		if (!(core_mask & (1 << id))) {
 			set_cpu_possible(cpus, true);
 			__cpu_number_map[id] = cpus;
@@ -192,14 +198,6 @@ static void octeon_init_secondary(void)
  */
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
-#ifdef CONFIG_HOTPLUG_CPU
-	struct linux_app_boot_info *labi;
-
-	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
-	if (labi->labi_signature != LABI_SIGNATURE)
-		panic("The bootloader version on this board is incorrect.");
-#endif
 	/*
 	 * Only the low order mailbox bits are used for IPIs, leave
 	 * the other bits alone.
@@ -237,6 +235,9 @@ static int octeon_cpu_disable(void)
 	if (cpu == 0)
 		return -EBUSY;
 
+	if (!octeon_bootloader_entry_addr)
+		return -ENOTSUPP;
+
 	set_cpu_online(cpu, false);
 	cpu_clear(cpu, cpu_callin_map);
 	local_irq_disable();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/cavium_octeon_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/cavium_octeon_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/cavium_octeon_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/cavium_octeon_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -124,7 +124,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_STAGING=y
 CONFIG_OCTEON_ETHERNET=y
-# CONFIG_NET_VENDOR_SILICOM is not set
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/db1xxx_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/db1xxx_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/db1xxx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/db1xxx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -116,7 +116,6 @@ CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_SPI_NOR=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_MULTI_LUN=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/decstation_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/decstation_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/decstation_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/decstation_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,6 @@ CONFIG_VLAN_8021Q=m
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/gpr_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/gpr_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/gpr_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/gpr_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PCI=y
 CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/ip22_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/ip22_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/ip22_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/ip22_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,6 @@ CONFIG_ATA_OVER_ETH=m
 # CONFIG_MISC_DEVICES is not set
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/ip27_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/ip27_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/ip27_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/ip27_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@ CONFIG_MIPS32_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
 CONFIG_PM=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -106,7 +107,6 @@ CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 # CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/ip32_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/ip32_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/ip32_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/ip32_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,6 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_SGI_IOC4=y
 CONFIG_RAID_ATTRS=y
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/jazz_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/jazz_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/jazz_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/jazz_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PM=y
+CONFIG_NET=y
 CONFIG_PACKET=m
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
@@ -208,7 +209,6 @@ CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/loongson3_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/loongson3_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/loongson3_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/loongson3_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 CONFIG_MACH_LOONGSON=y
 CONFIG_SWIOTLB=y
-CONFIG_LEMOTE_MACH3A=y
+CONFIG_LOONGSON_MACH3X=y
 CONFIG_CPU_LOONGSON3=y
 CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_16KB=y
@@ -59,6 +59,7 @@ CONFIG_MIPS32_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
 CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
@@ -120,7 +121,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/malta_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/malta_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_PCI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -253,7 +254,6 @@ CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/malta_kvm_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_kvm_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/malta_kvm_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_kvm_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_PCI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -254,7 +255,6 @@ CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/malta_kvm_guest_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_kvm_guest_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/malta_kvm_guest_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/malta_kvm_guest_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_PCI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -254,7 +255,6 @@ CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/markeins_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/markeins_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/markeins_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/markeins_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -134,7 +134,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_SGI_IOC4=m
 CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_SG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/mtx1_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/mtx1_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/mtx1_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/mtx1_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ CONFIG_PD6729=m
 CONFIG_I82092=m
 CONFIG_BINFMT_MISC=m
 CONFIG_PM=y
+CONFIG_NET=y
 CONFIG_PACKET=m
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/nlm_xlp_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/nlm_xlp_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/nlm_xlp_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/nlm_xlp_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,7 @@ CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
 CONFIG_PM_RUNTIME=y
 CONFIG_PM_DEBUG=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -334,7 +335,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
@@ -346,10 +346,8 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_TGT_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_ISCSI_TCP=m
 CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/nlm_xlr_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/nlm_xlr_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/nlm_xlr_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/nlm_xlr_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -43,6 +43,7 @@ CONFIG_PCI_DEBUG=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PM_RUNTIME=y
 CONFIG_PM_DEBUG=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
@@ -311,7 +312,6 @@ CONFIG_CDROM_PKTCDVD=y
 CONFIG_MISC_DEVICES=y
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
@@ -323,10 +323,8 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_TGT_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_ISCSI_TCP=m
 CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/rm200_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/rm200_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/rm200_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/rm200_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@ CONFIG_MODVERSIONS=y
 CONFIG_PCI=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PM=y
+CONFIG_NET=y
 CONFIG_PACKET=m
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
@@ -221,7 +222,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_SGI_IOC4=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/tb0226_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/tb0226_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/tb0226_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/tb0226_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_XIP=y
 # CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_SCAN_ASYNC=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/configs/tb0287_defconfig linux-libre-3.17-rc7-gnu/arch/mips/configs/tb0287_defconfig
--- linux-libre-3.16-gnu/arch/mips/configs/tb0287_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/configs/tb0287_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,6 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_XIP=y
 # CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SCAN_ASYNC=y
 # CONFIG_SCSI_LOWLEVEL is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/abi.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/abi.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/abi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/abi.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,13 +13,11 @@
 #include <asm/siginfo.h>
 
 struct mips_abi {
-	int (* const setup_frame)(void *sig_return, struct k_sigaction *ka,
-				  struct pt_regs *regs, int signr,
-				  sigset_t *set);
+	int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
+				  struct pt_regs *regs, sigset_t *set);
 	const unsigned long	signal_return_offset;
-	int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka,
-			       struct pt_regs *regs, int signr,
-			       sigset_t *set, siginfo_t *info);
+	int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
+				     struct pt_regs *regs, sigset_t *set);
 	const unsigned long	rt_signal_return_offset;
 	const unsigned long	restart;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/addrspace.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/addrspace.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/addrspace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/addrspace.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@
  */
 #define CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)
 #define XPHYSADDR(a)		((_ACAST64_(a)) &			\
-				 _CONST64_(0x000000ffffffffff))
+				 _CONST64_(0x0000ffffffffffff))
 
 #ifdef CONFIG_64BIT
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/asmmacro.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/asmmacro.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/asmmacro.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/asmmacro.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
 
 #include <asm/hazards.h>
 #include <asm/asm-offsets.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
@@ -378,9 +379,19 @@
 	st_d	29, THREAD_FPR29, \thread
 	st_d	30, THREAD_FPR30, \thread
 	st_d	31, THREAD_FPR31, \thread
+	.set	push
+	.set	noat
+	cfcmsa	$1, MSA_CSR
+	sw	$1, THREAD_MSA_CSR(\thread)
+	.set	pop
 	.endm
 
 	.macro	msa_restore_all	thread
+	.set	push
+	.set	noat
+	lw	$1, THREAD_MSA_CSR(\thread)
+	ctcmsa	MSA_CSR, $1
+	.set	pop
 	ld_d	0, THREAD_FPR0, \thread
 	ld_d	1, THREAD_FPR1, \thread
 	ld_d	2, THREAD_FPR2, \thread
@@ -415,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_init_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_init_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_init_all_upper
+	.set	push
+	.set	noat
+	not	$1, zero
+	msa_init_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/bitops.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/bitops.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/bitops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/bitops.h	2014-09-28 17:29:07.000000000 -0400
@@ -559,7 +559,13 @@ static inline int fls(int x)
 	int r;
 
 	if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
-		__asm__("clz %0, %1" : "=r" (x) : "r" (x));
+		__asm__(
+		"	.set	push					\n"
+		"	.set	mips32					\n"
+		"	clz	%0, %1					\n"
+		"	.set	pop					\n"
+		: "=r" (x)
+		: "r" (x));
 
 		return 32 - x;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/cop2.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cop2.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/cop2.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cop2.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,8 +16,8 @@
 extern void octeon_cop2_save(struct octeon_cop2_state *);
 extern void octeon_cop2_restore(struct octeon_cop2_state *);
 
-#define cop2_save(r)		octeon_cop2_save(r)
-#define cop2_restore(r)		octeon_cop2_restore(r)
+#define cop2_save(r)		octeon_cop2_save(&(r)->thread.cp2)
+#define cop2_restore(r)		octeon_cop2_restore(&(r)->thread.cp2)
 
 #define cop2_present		1
 #define cop2_lazy_restore	1
@@ -26,18 +26,26 @@ extern void octeon_cop2_restore(struct o
 
 extern void nlm_cop2_save(struct nlm_cop2_state *);
 extern void nlm_cop2_restore(struct nlm_cop2_state *);
-#define cop2_save(r)		nlm_cop2_save(r)
-#define cop2_restore(r)		nlm_cop2_restore(r)
+
+#define cop2_save(r)		nlm_cop2_save(&(r)->thread.cp2)
+#define cop2_restore(r)		nlm_cop2_restore(&(r)->thread.cp2)
 
 #define cop2_present		1
 #define cop2_lazy_restore	0
 
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+#define cop2_present		1
+#define cop2_lazy_restore	1
+#define cop2_save(r)		do { (r); } while (0)
+#define cop2_restore(r)		do { (r); } while (0)
+
 #else
 
 #define cop2_present		0
 #define cop2_lazy_restore	0
-#define cop2_save(r)
-#define cop2_restore(r)
+#define cop2_save(r)		do { (r); } while (0)
+#define cop2_restore(r)		do { (r); } while (0)
 #endif
 
 enum cu2_ops {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/cpu-features.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu-features.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/cpu-features.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu-features.h	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,15 @@
 #ifndef cpu_has_eva
 #define cpu_has_eva		(cpu_data[0].options & MIPS_CPU_EVA)
 #endif
+#ifndef cpu_has_htw
+#define cpu_has_htw		(cpu_data[0].options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_has_rixiex
+#define cpu_has_rixiex		(cpu_data[0].options & MIPS_CPU_RIXIEX)
+#endif
+#ifndef cpu_has_maar
+#define cpu_has_maar		(cpu_data[0].options & MIPS_CPU_MAAR)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/cpu.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/cpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -233,6 +233,8 @@
 #define PRID_REV_LOONGSON2E	0x0002
 #define PRID_REV_LOONGSON2F	0x0003
 #define PRID_REV_LOONGSON3A	0x0005
+#define PRID_REV_LOONGSON3B_R1	0x0006
+#define PRID_REV_LOONGSON3B_R2	0x0007
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -335,34 +337,37 @@ enum cpu_type_enum {
 /*
  * CPU Option encodings
  */
-#define MIPS_CPU_TLB		0x00000001 /* CPU has TLB */
-#define MIPS_CPU_4KEX		0x00000002 /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE	0x00000004 /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE	0x00000008 /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE	0x00000010 /* TX3900-style caches */
-#define MIPS_CPU_FPU		0x00000020 /* CPU has FPU */
-#define MIPS_CPU_32FPR		0x00000040 /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER	0x00000080 /* Cycle count/compare */
-#define MIPS_CPU_WATCH		0x00000100 /* watchpoint registers */
-#define MIPS_CPU_DIVEC		0x00000200 /* dedicated interrupt vector */
-#define MIPS_CPU_VCE		0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P	0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S	0x00001000 /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK		0x00002000 /* Machine check exception */
-#define MIPS_CPU_EJTAG		0x00004000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX	0x00008000 /* no FPU exception */
-#define MIPS_CPU_LLSC		0x00010000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES	0x00020000 /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH	0x00040000 /* CPU has usable prefetch */
-#define MIPS_CPU_VINT		0x00080000 /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC		0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI		0x00200000 /* CPU has ULRI feature */
-#define MIPS_CPU_PCI		0x00400000 /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI		0x00800000 /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS	0x01000000 /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV		0x02000000 /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS	0x04000000 /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA		0x80000000 /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_TLB		0x00000001ull /* CPU has TLB */
+#define MIPS_CPU_4KEX		0x00000002ull /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE	0x00000004ull /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE	0x00000008ull /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE	0x00000010ull /* TX3900-style caches */
+#define MIPS_CPU_FPU		0x00000020ull /* CPU has FPU */
+#define MIPS_CPU_32FPR		0x00000040ull /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER	0x00000080ull /* Cycle count/compare */
+#define MIPS_CPU_WATCH		0x00000100ull /* watchpoint registers */
+#define MIPS_CPU_DIVEC		0x00000200ull /* dedicated interrupt vector */
+#define MIPS_CPU_VCE		0x00000400ull /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P	0x00000800ull /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S	0x00001000ull /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK		0x00002000ull /* Machine check exception */
+#define MIPS_CPU_EJTAG		0x00004000ull /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX	0x00008000ull /* no FPU exception */
+#define MIPS_CPU_LLSC		0x00010000ull /* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES	0x00020000ull /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH	0x00040000ull /* CPU has usable prefetch */
+#define MIPS_CPU_VINT		0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC		0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI		0x00200000ull /* CPU has ULRI feature */
+#define MIPS_CPU_PCI		0x00400000ull /* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI		0x00800000ull /* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS	0x01000000ull /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV		0x02000000ull /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS	0x04000000ull /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA		0x80000000ull /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW		0x100000000ull /* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX		0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR		0x400000000ull /* MAAR(I) registers are present */
 
 /*
  * CPU ASE encodings
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/cpu-info.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu-info.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/cpu-info.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/cpu-info.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,8 +44,8 @@ struct cpuinfo_mips {
 	/*
 	 * Capability and feature descriptor structure for MIPS CPU
 	 */
-	unsigned long		options;
 	unsigned long		ases;
+	unsigned long long	options;
 	unsigned int		udelay_val;
 	unsigned int		processor_id;
 	unsigned int		fpu_id;
@@ -61,6 +61,7 @@ struct cpuinfo_mips {
 	struct cache_desc	scache; /* Secondary cache */
 	struct cache_desc	tcache; /* Tertiary/split secondary cache */
 	int			srsets; /* Shadow register sets */
+	int			package;/* physical package number */
 	int			core;	/* physical core number */
 #ifdef CONFIG_64BIT
 	int			vmbits; /* Virtual memory size in bits */
@@ -115,7 +116,7 @@ struct proc_cpuinfo_notifier_args {
 #ifdef CONFIG_MIPS_MT_SMP
 # define cpu_vpe_id(cpuinfo)	((cpuinfo)->vpe_id)
 #else
-# define cpu_vpe_id(cpuinfo)	0
+# define cpu_vpe_id(cpuinfo)	({ (void)cpuinfo; 0; })
 #endif
 
 #endif /* __ASM_CPU_INFO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/elf.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/elf.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/elf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/elf.h	2014-09-28 17:29:07.000000000 -0400
@@ -339,23 +339,6 @@ do {									\
 
 #endif /* CONFIG_64BIT */
 
-struct pt_regs;
-struct task_struct;
-
-extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
-
-#ifndef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(elf_regs, regs)			\
-	elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
-#endif
-#ifndef ELF_CORE_COPY_TASK_REGS
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#endif
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
-	dump_task_fpu(tsk, elf_fpregs)
-
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/eva.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/eva.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/eva.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/eva.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * 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) 2014, Imagination Technologies Ltd.
+ *
+ * EVA functions for generic code
+ */
+
+#ifndef _ASM_EVA_H
+#define _ASM_EVA_H
+
+#include <kernel-entry-init.h>
+
+#ifdef __ASSEMBLY__
+
+#ifdef CONFIG_EVA
+
+/*
+ * EVA early init code
+ *
+ * Platforms must define their own 'platform_eva_init' macro in
+ * their kernel-entry-init.h header. This macro usually does the
+ * platform specific configuration of the segmentation registers,
+ * and it is normally called from assembly code.
+ *
+ */
+
+.macro eva_init
+platform_eva_init
+.endm
+
+#else
+
+.macro eva_init
+.endm
+
+#endif /* CONFIG_EVA */
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/fpu.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/fpu.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/fpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/fpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include <asm/hazards.h>
 #include <asm/processor.h>
 #include <asm/current.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #include <asm/mips_mt.h>
@@ -141,13 +142,21 @@ static inline int own_fpu(int restore)
 static inline void lose_fpu(int save)
 {
 	preempt_disable();
-	if (is_fpu_owner()) {
+	if (is_msa_enabled()) {
+		if (save) {
+			save_msa(current);
+			asm volatile("cfc1 %0, $31"
+				: "=r"(current->thread.fpu.fcr31));
+		}
+		disable_msa();
+		clear_thread_flag(TIF_USEDMSA);
+	} else if (is_fpu_owner()) {
 		if (save)
 			_save_fp(current);
-		KSTK_STATUS(current) &= ~ST0_CU1;
-		clear_thread_flag(TIF_USEDFPU);
 		__disable_fpu();
 	}
+	KSTK_STATUS(current) &= ~ST0_CU1;
+	clear_thread_flag(TIF_USEDFPU);
 	preempt_enable();
 }
 
@@ -155,8 +164,6 @@ static inline int init_fpu(void)
 {
 	int ret = 0;
 
-	preempt_disable();
-
 	if (cpu_has_fpu) {
 		ret = __own_fpu();
 		if (!ret)
@@ -164,8 +171,6 @@ static inline int init_fpu(void)
 	} else
 		fpu_emulator_init_fpu();
 
-	preempt_enable();
-
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/gic.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/gic.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/gic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/gic.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,8 @@
 #include <linux/bitmap.h>
 #include <linux/threads.h>
 
+#include <irq.h>
+
 #undef	GICISBYTELITTLEENDIAN
 
 /* Constants */
@@ -22,8 +24,6 @@
 #define GIC_TRIG_EDGE			1
 #define GIC_TRIG_LEVEL			0
 
-#define GIC_NUM_INTRS			(24 + NR_CPUS * 2)
-
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)		(*(volatile unsigned int *) (addr))
 #define REG(base, offs)		REG32((unsigned long)(base) + offs##_##OFS)
@@ -43,18 +43,17 @@
 #ifdef GICISBYTELITTLEENDIAN
 #define GICREAD(reg, data)	((data) = (reg), (data) = le32_to_cpu(data))
 #define GICWRITE(reg, data)	((reg) = cpu_to_le32(data))
-#define GICBIS(reg, bits)			\
-	({unsigned int data;			\
-		GICREAD(reg, data);		\
-		data |= bits;			\
-		GICWRITE(reg, data);		\
-	})
-
 #else
 #define GICREAD(reg, data)	((data) = (reg))
 #define GICWRITE(reg, data)	((reg) = (data))
-#define GICBIS(reg, bits)	((reg) |= (bits))
 #endif
+#define GICBIS(reg, mask, bits)			\
+	do { u32 data;				\
+		GICREAD(reg, data);		\
+		data &= ~(mask);		\
+		data |= ((bits) & (mask));	\
+		GICWRITE((reg), data);		\
+	} while (0)
 
 
 /* GIC Address Space */
@@ -170,13 +169,15 @@
 #define GIC_SH_SET_POLARITY_OFS		0x0100
 #define GIC_SET_POLARITY(intr, pol) \
 	GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
-		GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
+		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+		(pol) << GIC_INTR_BIT(intr))
 
 /* Triggering : Reset Value is always 0 */
 #define GIC_SH_SET_TRIGGER_OFS		0x0180
 #define GIC_SET_TRIGGER(intr, trig) \
 	GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
-		GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
+		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+		(trig) << GIC_INTR_BIT(intr))
 
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS		0x0380
@@ -306,18 +307,6 @@
 	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
 		 GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
 
-struct gic_pcpu_mask {
-	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
-};
-
-struct gic_pending_regs {
-	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
-};
-
-struct gic_intrmask_regs {
-	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
-};
-
 /*
  * Interrupt Meta-data specification. The ipiflag helps
  * in building ipi_map.
@@ -329,8 +318,7 @@ struct gic_intr_map {
 	unsigned int polarity;	/* Polarity : +/-	*/
 	unsigned int trigtype;	/* Trigger  : Edge/Levl */
 	unsigned int flags;	/* Misc flags	*/
-#define GIC_FLAG_IPI	       0x01
-#define GIC_FLAG_TRANSPARENT   0x02
+#define GIC_FLAG_TRANSPARENT   0x01
 };
 
 /*
@@ -386,6 +374,7 @@ extern unsigned int plat_ipi_call_int_xl
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
+extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
 extern void gic_enable_interrupt(int irq_vec);
 extern void gic_disable_interrupt(int irq_vec);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/irq.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/irq.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,8 @@ static inline int irq_canonicalize(int i
 #define irq_canonicalize(irq) (irq)	/* Sane hardware, sane code ... */
 #endif
 
+asmlinkage void plat_irq_dispatch(void);
+
 extern void do_IRQ(unsigned int irq);
 
 extern void arch_init_irq(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/mips/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/mips/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -15,4 +15,5 @@ generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
+generic-y += user.h
 generic-y += xor.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -359,13 +359,17 @@ enum emulation_result {
 #define MIPS3_PG_FRAME		0x3fffffc0
 
 #define VPN2_MASK		0xffffe000
-#define TLB_IS_GLOBAL(x)	(((x).tlb_lo0 & MIPS3_PG_G) &&	\
+#define TLB_IS_GLOBAL(x)	(((x).tlb_lo0 & MIPS3_PG_G) &&		\
 				 ((x).tlb_lo1 & MIPS3_PG_G))
 #define TLB_VPN2(x)		((x).tlb_hi & VPN2_MASK)
 #define TLB_ASID(x)		((x).tlb_hi & ASID_MASK)
-#define TLB_IS_VALID(x, va)	(((va) & (1 << PAGE_SHIFT))	\
-				 ? ((x).tlb_lo1 & MIPS3_PG_V)	\
+#define TLB_IS_VALID(x, va)	(((va) & (1 << PAGE_SHIFT))		\
+				 ? ((x).tlb_lo1 & MIPS3_PG_V)		\
 				 : ((x).tlb_lo0 & MIPS3_PG_V))
+#define TLB_HI_VPN2_HIT(x, y)	((TLB_VPN2(x) & ~(x).tlb_mask) ==	\
+				 ((y) & VPN2_MASK & ~(x).tlb_mask))
+#define TLB_HI_ASID_HIT(x, y)	(TLB_IS_GLOBAL(x) ||			\
+				 TLB_ASID(x) == ((y) & ASID_MASK))
 
 struct kvm_mips_tlb {
 	long tlb_mask;
@@ -760,7 +764,7 @@ extern int kvm_mips_trans_mtc0(uint32_t
 			       struct kvm_vcpu *vcpu);
 
 /* Misc */
-extern int kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
+extern void kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
 extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm);
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/maar.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/maar.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/maar.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/maar.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 __MIPS_ASM_MIPS_MAAR_H__
+#define __MIPS_ASM_MIPS_MAAR_H__
+
+#include <asm/hazards.h>
+#include <asm/mipsregs.h>
+
+/**
+ * platform_maar_init() - perform platform-level MAAR configuration
+ * @num_pairs:	The number of MAAR pairs present in the system.
+ *
+ * Platforms should implement this function such that it configures as many
+ * MAAR pairs as required, from 0 up to the maximum of num_pairs-1, and returns
+ * the number that were used. Any further MAARs will be configured to be
+ * invalid. The default implementation of this function will simply indicate
+ * that it has configured 0 MAAR pairs.
+ *
+ * Return:	The number of MAAR pairs configured.
+ */
+unsigned __weak platform_maar_init(unsigned num_pairs);
+
+/**
+ * write_maar_pair() - write to a pair of MAARs
+ * @idx:	The index of the pair (ie. use MAARs idx*2 & (idx*2)+1).
+ * @lower:	The lowest address that the MAAR pair will affect. Must be
+ *		aligned to a 2^16 byte boundary.
+ * @upper:	The highest address that the MAAR pair will affect. Must be
+ *		aligned to one byte before a 2^16 byte boundary.
+ * @attrs:	The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *		MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Program the pair of MAAR registers specified by idx to apply the attributes
+ * specified by attrs to the range of addresses from lower to higher.
+ */
+static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
+				   phys_addr_t upper, unsigned attrs)
+{
+	/* Addresses begin at bit 16, but are shifted right 4 bits */
+	BUG_ON(lower & (0xffff | ~(MIPS_MAAR_ADDR << 4)));
+	BUG_ON(((upper & 0xffff) != 0xffff)
+		|| ((upper & ~0xffffull) & ~(MIPS_MAAR_ADDR << 4)));
+
+	/* Automatically set MIPS_MAAR_V */
+	attrs |= MIPS_MAAR_V;
+
+	/* Write the upper address & attributes (only MIPS_MAAR_V matters) */
+	write_c0_maari(idx << 1);
+	back_to_back_c0_hazard();
+	write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
+	back_to_back_c0_hazard();
+
+	/* Write the lower address & attributes */
+	write_c0_maari((idx << 1) | 0x1);
+	back_to_back_c0_hazard();
+	write_c0_maar((lower >> 4) | attrs);
+	back_to_back_c0_hazard();
+}
+
+/**
+ * struct maar_config - MAAR configuration data
+ * @lower:	The lowest address that the MAAR pair will affect. Must be
+ *		aligned to a 2^16 byte boundary.
+ * @upper:	The highest address that the MAAR pair will affect. Must be
+ *		aligned to one byte before a 2^16 byte boundary.
+ * @attrs:	The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *		MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Describes the configuration of a pair of Memory Accessibility Attribute
+ * Registers - applying attributes from attrs to the range of physical
+ * addresses from lower to upper inclusive.
+ */
+struct maar_config {
+	phys_addr_t lower;
+	phys_addr_t upper;
+	unsigned attrs;
+};
+
+/**
+ * maar_config() - configure MAARs according to provided data
+ * @cfg:	Pointer to an array of struct maar_config.
+ * @num_cfg:	The number of structs in the cfg array.
+ * @num_pairs:	The number of MAAR pairs present in the system.
+ *
+ * Configures as many MAARs as are present and specified in the cfg
+ * array with the values taken from the cfg array.
+ *
+ * Return:	The number of MAAR pairs configured.
+ */
+static inline unsigned maar_config(const struct maar_config *cfg,
+				   unsigned num_cfg, unsigned num_pairs)
+{
+	unsigned i;
+
+	for (i = 0; i < min(num_cfg, num_pairs); i++)
+		write_maar_pair(i, cfg[i].lower, cfg[i].upper, cfg[i].attrs);
+
+	return i;
+}
+
+#endif /* __MIPS_ASM_MIPS_MAAR_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/au1000_dma.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/au1000_dma.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/au1000_dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/au1000_dma.h	2014-09-28 17:29:07.000000000 -0400
@@ -106,7 +106,7 @@ enum {
 struct dma_chan {
 	int dev_id;		/* this channel is allocated if >= 0, */
 				/* free otherwise */
-	unsigned int io;
+	void __iomem *io;
 	const char *dev_str;
 	int irq;
 	void *irq_dev;
@@ -157,7 +157,7 @@ static inline void enable_dma_buffer0(un
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE0, chan->io + DMA_MODE_SET);
 }
 
 static inline void enable_dma_buffer1(unsigned int dmanr)
@@ -166,7 +166,7 @@ static inline void enable_dma_buffer1(un
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE1, chan->io + DMA_MODE_SET);
 }
 static inline void enable_dma_buffers(unsigned int dmanr)
 {
@@ -174,7 +174,7 @@ static inline void enable_dma_buffers(un
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
 }
 
 static inline void start_dma(unsigned int dmanr)
@@ -183,7 +183,7 @@ static inline void start_dma(unsigned in
 
 	if (!chan)
 		return;
-	au_writel(DMA_GO, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_GO, chan->io + DMA_MODE_SET);
 }
 
 #define DMA_HALT_POLL 0x5000
@@ -195,11 +195,11 @@ static inline void halt_dma(unsigned int
 
 	if (!chan)
 		return;
-	au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
 
 	/* Poll the halt bit */
 	for (i = 0; i < DMA_HALT_POLL; i++)
-		if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
+		if (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
 			break;
 	if (i == DMA_HALT_POLL)
 		printk(KERN_INFO "halt_dma: HALT poll expired!\n");
@@ -215,7 +215,7 @@ static inline void disable_dma(unsigned
 	halt_dma(dmanr);
 
 	/* Now we can disable the buffers */
-	au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline int dma_halted(unsigned int dmanr)
@@ -224,7 +224,7 @@ static inline int dma_halted(unsigned in
 
 	if (!chan)
 		return 1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
+	return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
 }
 
 /* Initialize a DMA channel. */
@@ -239,14 +239,14 @@ static inline void init_dma(unsigned int
 	disable_dma(dmanr);
 
 	/* Set device FIFO address */
-	au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
+	__raw_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
 
 	mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
 	if (chan->irq)
 		mode |= DMA_IE;
 
-	au_writel(~mode, chan->io + DMA_MODE_CLEAR);
-	au_writel(mode,	 chan->io + DMA_MODE_SET);
+	__raw_writel(~mode, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(mode,	 chan->io + DMA_MODE_SET);
 }
 
 /*
@@ -283,7 +283,7 @@ static inline int get_dma_active_buffer(
 
 	if (!chan)
 		return -1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
+	return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
 }
 
 /*
@@ -304,7 +304,7 @@ static inline void set_dma_fifo_addr(uns
 	if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
 		return;
 
-	au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
+	__raw_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
 }
 
 /*
@@ -316,7 +316,7 @@ static inline void clear_dma_done0(unsig
 
 	if (!chan)
 		return;
-	au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline void clear_dma_done1(unsigned int dmanr)
@@ -325,7 +325,7 @@ static inline void clear_dma_done1(unsig
 
 	if (!chan)
 		return;
-	au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
 }
 
 /*
@@ -344,7 +344,7 @@ static inline void set_dma_addr0(unsigne
 
 	if (!chan)
 		return;
-	au_writel(a, chan->io + DMA_BUFFER0_START);
+	__raw_writel(a, chan->io + DMA_BUFFER0_START);
 }
 
 /*
@@ -356,7 +356,7 @@ static inline void set_dma_addr1(unsigne
 
 	if (!chan)
 		return;
-	au_writel(a, chan->io + DMA_BUFFER1_START);
+	__raw_writel(a, chan->io + DMA_BUFFER1_START);
 }
 
 
@@ -370,7 +370,7 @@ static inline void set_dma_count0(unsign
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
 }
 
 /*
@@ -383,7 +383,7 @@ static inline void set_dma_count1(unsign
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -396,8 +396,8 @@ static inline void set_dma_count(unsigne
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -410,7 +410,7 @@ static inline unsigned int get_dma_buffe
 
 	if (!chan)
 		return 0;
-	return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
+	return __raw_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
 }
 
 
@@ -437,10 +437,10 @@ static inline int get_dma_residue(unsign
 	if (!chan)
 		return 0;
 
-	curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
+	curBufCntReg = (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
 	    DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
 
-	count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
+	count = __raw_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
 
 	if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
 		count <<= 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/au1000.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/au1000.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/au1000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/au1000.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,558 @@
 #ifndef _AU1000_H_
 #define _AU1000_H_
 
+/* SOC Interrupt numbers */
+/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
+#define AU1000_INTC0_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
+#define AU1000_INTC0_INT_LAST	(AU1000_INTC0_INT_BASE + 31)
+#define AU1000_INTC1_INT_BASE	(AU1000_INTC0_INT_LAST + 1)
+#define AU1000_INTC1_INT_LAST	(AU1000_INTC1_INT_BASE + 31)
+#define AU1000_MAX_INTR		AU1000_INTC1_INT_LAST
+
+/* Au1300-style (GPIC): 1 controller with up to 128 sources */
+#define ALCHEMY_GPIC_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
+#define ALCHEMY_GPIC_INT_NUM	128
+#define ALCHEMY_GPIC_INT_LAST	(ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
+
+/* common clock names, shared among all variants. AUXPLL2 is Au1300 */
+#define ALCHEMY_ROOT_CLK		"root_clk"
+#define ALCHEMY_CPU_CLK			"cpu_clk"
+#define ALCHEMY_AUXPLL_CLK		"auxpll_clk"
+#define ALCHEMY_AUXPLL2_CLK		"auxpll2_clk"
+#define ALCHEMY_SYSBUS_CLK		"sysbus_clk"
+#define ALCHEMY_PERIPH_CLK		"periph_clk"
+#define ALCHEMY_MEM_CLK			"mem_clk"
+#define ALCHEMY_LR_CLK			"lr_clk"
+#define ALCHEMY_FG0_CLK			"fg0_clk"
+#define ALCHEMY_FG1_CLK			"fg1_clk"
+#define ALCHEMY_FG2_CLK			"fg2_clk"
+#define ALCHEMY_FG3_CLK			"fg3_clk"
+#define ALCHEMY_FG4_CLK			"fg4_clk"
+#define ALCHEMY_FG5_CLK			"fg5_clk"
+
+/* Au1300 peripheral interrupt numbers */
+#define AU1300_FIRST_INT	(ALCHEMY_GPIC_INT_BASE)
+#define AU1300_UART1_INT	(AU1300_FIRST_INT + 17)
+#define AU1300_UART2_INT	(AU1300_FIRST_INT + 25)
+#define AU1300_UART3_INT	(AU1300_FIRST_INT + 27)
+#define AU1300_SD1_INT		(AU1300_FIRST_INT + 32)
+#define AU1300_SD2_INT		(AU1300_FIRST_INT + 38)
+#define AU1300_PSC0_INT		(AU1300_FIRST_INT + 48)
+#define AU1300_PSC1_INT		(AU1300_FIRST_INT + 52)
+#define AU1300_PSC2_INT		(AU1300_FIRST_INT + 56)
+#define AU1300_PSC3_INT		(AU1300_FIRST_INT + 60)
+#define AU1300_NAND_INT		(AU1300_FIRST_INT + 62)
+#define AU1300_DDMA_INT		(AU1300_FIRST_INT + 75)
+#define AU1300_MMU_INT		(AU1300_FIRST_INT + 76)
+#define AU1300_MPU_INT		(AU1300_FIRST_INT + 77)
+#define AU1300_GPU_INT		(AU1300_FIRST_INT + 78)
+#define AU1300_UDMA_INT		(AU1300_FIRST_INT + 79)
+#define AU1300_TOY_INT		(AU1300_FIRST_INT + 80)
+#define AU1300_TOY_MATCH0_INT	(AU1300_FIRST_INT + 81)
+#define AU1300_TOY_MATCH1_INT	(AU1300_FIRST_INT + 82)
+#define AU1300_TOY_MATCH2_INT	(AU1300_FIRST_INT + 83)
+#define AU1300_RTC_INT		(AU1300_FIRST_INT + 84)
+#define AU1300_RTC_MATCH0_INT	(AU1300_FIRST_INT + 85)
+#define AU1300_RTC_MATCH1_INT	(AU1300_FIRST_INT + 86)
+#define AU1300_RTC_MATCH2_INT	(AU1300_FIRST_INT + 87)
+#define AU1300_UART0_INT	(AU1300_FIRST_INT + 88)
+#define AU1300_SD0_INT		(AU1300_FIRST_INT + 89)
+#define AU1300_USB_INT		(AU1300_FIRST_INT + 90)
+#define AU1300_LCD_INT		(AU1300_FIRST_INT + 91)
+#define AU1300_BSA_INT		(AU1300_FIRST_INT + 92)
+#define AU1300_MPE_INT		(AU1300_FIRST_INT + 93)
+#define AU1300_ITE_INT		(AU1300_FIRST_INT + 94)
+#define AU1300_AES_INT		(AU1300_FIRST_INT + 95)
+#define AU1300_CIM_INT		(AU1300_FIRST_INT + 96)
+
+/**********************************************************************/
+
+/*
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
+ */
+
+#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
+#define AU1300_ROM_PHYS_ADDR		0x10000000 /* 5 */
+#define AU1300_OTP_PHYS_ADDR		0x10002000 /* 5 */
+#define AU1300_VSS_PHYS_ADDR		0x10003000 /* 5 */
+#define AU1300_UART0_PHYS_ADDR		0x10100000 /* 5 */
+#define AU1300_UART1_PHYS_ADDR		0x10101000 /* 5 */
+#define AU1300_UART2_PHYS_ADDR		0x10102000 /* 5 */
+#define AU1300_UART3_PHYS_ADDR		0x10103000 /* 5 */
+#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
+#define AU1300_GPIC_PHYS_ADDR		0x10200000 /* 5 */
+#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR		0x10300000 /* 45 */
+#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
+#define AU1300_GPU_PHYS_ADDR		0x10500000 /* 5 */
+#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 245 */
+#define AU1300_SD1_PHYS_ADDR		0x10601000 /* 5 */
+#define AU1300_SD2_PHYS_ADDR		0x10602000 /* 5 */
+#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
+#define AU1300_SYS_PHYS_ADDR		0x10900000 /* 5 */
+#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
+#define AU1300_PSC0_PHYS_ADDR		0x10A00000 /* 5 */
+#define AU1300_PSC1_PHYS_ADDR		0x10A01000 /* 5 */
+#define AU1300_PSC2_PHYS_ADDR		0x10A02000 /* 5 */
+#define AU1300_PSC3_PHYS_ADDR		0x10A03000 /* 5 */
+#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 012345 */
+#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
+#define AU1300_UDMA_PHYS_ADDR		0x14001800 /* 5 */
+#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 345 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 345 */
+#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 45 */
+#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
+#define AU1300_MAEITE_PHYS_ADDR		0x14010000 /* 5 */
+#define AU1300_MAEMPE_PHYS_ADDR		0x14014000 /* 5 */
+#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
+#define AU1300_USB_EHCI_PHYS_ADDR	0x14020000 /* 5 */
+#define AU1300_USB_OHCI0_PHYS_ADDR	0x14020400 /* 5 */
+#define AU1300_USB_OHCI1_PHYS_ADDR	0x14020800 /* 5 */
+#define AU1300_USB_CTL_PHYS_ADDR	0x14021000 /* 5 */
+#define AU1300_USB_OTG_PHYS_ADDR	0x14022000 /* 5 */
+#define AU1300_MAEBSA_PHYS_ADDR		0x14030000 /* 5 */
+#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 45 */
+#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 012345 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 012345 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 012345 */
+
+/**********************************************************************/
+
+
+/*
+ * Au1300 GPIO+INT controller (GPIC) register offsets and bits
+ * Registers are 128bits (0x10 bytes), divided into 4 "banks".
+ */
+#define AU1300_GPIC_PINVAL	0x0000
+#define AU1300_GPIC_PINVALCLR	0x0010
+#define AU1300_GPIC_IPEND	0x0020
+#define AU1300_GPIC_PRIENC	0x0030
+#define AU1300_GPIC_IEN		0x0040	/* int_mask in manual */
+#define AU1300_GPIC_IDIS	0x0050	/* int_maskclr in manual */
+#define AU1300_GPIC_DMASEL	0x0060
+#define AU1300_GPIC_DEVSEL	0x0080
+#define AU1300_GPIC_DEVCLR	0x0090
+#define AU1300_GPIC_RSTVAL	0x00a0
+/* pin configuration space. one 32bit register for up to 128 IRQs */
+#define AU1300_GPIC_PINCFG	0x1000
+
+#define GPIC_GPIO_TO_BIT(gpio)	\
+	(1 << ((gpio) & 0x1f))
+
+#define GPIC_GPIO_BANKOFF(gpio) \
+	(((gpio) >> 5) * 4)
+
+/* Pin Control bits: who owns the pin, what does it do */
+#define GPIC_CFG_PC_GPIN		0
+#define GPIC_CFG_PC_DEV			1
+#define GPIC_CFG_PC_GPOLOW		2
+#define GPIC_CFG_PC_GPOHIGH		3
+#define GPIC_CFG_PC_MASK		3
+
+/* assign pin to MIPS IRQ line */
+#define GPIC_CFG_IL_SET(x)	(((x) & 3) << 2)
+#define GPIC_CFG_IL_MASK	(3 << 2)
+
+/* pin interrupt type setup */
+#define GPIC_CFG_IC_OFF		(0 << 4)
+#define GPIC_CFG_IC_LEVEL_LOW	(1 << 4)
+#define GPIC_CFG_IC_LEVEL_HIGH	(2 << 4)
+#define GPIC_CFG_IC_EDGE_FALL	(5 << 4)
+#define GPIC_CFG_IC_EDGE_RISE	(6 << 4)
+#define GPIC_CFG_IC_EDGE_BOTH	(7 << 4)
+#define GPIC_CFG_IC_MASK	(7 << 4)
+
+/* allow interrupt to wake cpu from 'wait' */
+#define GPIC_CFG_IDLEWAKE	(1 << 7)
+
+/***********************************************************************/
+
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0		0x0000
+#define AU1000_MEM_SDMODE1		0x0004
+#define AU1000_MEM_SDMODE2		0x0008
+#define AU1000_MEM_SDADDR0		0x000C
+#define AU1000_MEM_SDADDR1		0x0010
+#define AU1000_MEM_SDADDR2		0x0014
+#define AU1000_MEM_SDREFCFG		0x0018
+#define AU1000_MEM_SDPRECMD		0x001C
+#define AU1000_MEM_SDAUTOREF		0x0020
+#define AU1000_MEM_SDWRMD0		0x0024
+#define AU1000_MEM_SDWRMD1		0x0028
+#define AU1000_MEM_SDWRMD2		0x002C
+#define AU1000_MEM_SDSLEEP		0x0030
+#define AU1000_MEM_SDSMCKE		0x0034
+
+/* MEM_SDMODE register content definitions */
+#define MEM_SDMODE_F		(1 << 22)
+#define MEM_SDMODE_SR		(1 << 21)
+#define MEM_SDMODE_BS		(1 << 20)
+#define MEM_SDMODE_RS		(3 << 18)
+#define MEM_SDMODE_CS		(7 << 15)
+#define MEM_SDMODE_TRAS		(15 << 11)
+#define MEM_SDMODE_TMRD		(3 << 9)
+#define MEM_SDMODE_TWR		(3 << 7)
+#define MEM_SDMODE_TRP		(3 << 5)
+#define MEM_SDMODE_TRCD		(3 << 3)
+#define MEM_SDMODE_TCL		(7 << 0)
+
+#define MEM_SDMODE_BS_2Bank	(0 << 20)
+#define MEM_SDMODE_BS_4Bank	(1 << 20)
+#define MEM_SDMODE_RS_11Row	(0 << 18)
+#define MEM_SDMODE_RS_12Row	(1 << 18)
+#define MEM_SDMODE_RS_13Row	(2 << 18)
+#define MEM_SDMODE_RS_N(N)	((N) << 18)
+#define MEM_SDMODE_CS_7Col	(0 << 15)
+#define MEM_SDMODE_CS_8Col	(1 << 15)
+#define MEM_SDMODE_CS_9Col	(2 << 15)
+#define MEM_SDMODE_CS_10Col	(3 << 15)
+#define MEM_SDMODE_CS_11Col	(4 << 15)
+#define MEM_SDMODE_CS_N(N)	((N) << 15)
+#define MEM_SDMODE_TRAS_N(N)	((N) << 11)
+#define MEM_SDMODE_TMRD_N(N)	((N) << 9)
+#define MEM_SDMODE_TWR_N(N)	((N) << 7)
+#define MEM_SDMODE_TRP_N(N)	((N) << 5)
+#define MEM_SDMODE_TRCD_N(N)	((N) << 3)
+#define MEM_SDMODE_TCL_N(N)	((N) << 0)
+
+/* MEM_SDADDR register contents definitions */
+#define MEM_SDADDR_E		(1 << 20)
+#define MEM_SDADDR_CSBA		(0x03FF << 10)
+#define MEM_SDADDR_CSMASK	(0x03FF << 0)
+#define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
+#define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
+
+/* MEM_SDREFCFG register content definitions */
+#define MEM_SDREFCFG_TRC	(15 << 28)
+#define MEM_SDREFCFG_TRPM	(3 << 26)
+#define MEM_SDREFCFG_E		(1 << 25)
+#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
+#define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
+#define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
+#define MEM_SDREFCFG_REF_N(N)	(N)
+
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0		0x0800
+#define AU1550_MEM_SDMODE1		0x0808
+#define AU1550_MEM_SDMODE2		0x0810
+#define AU1550_MEM_SDADDR0		0x0820
+#define AU1550_MEM_SDADDR1		0x0828
+#define AU1550_MEM_SDADDR2		0x0830
+#define AU1550_MEM_SDCONFIGA		0x0840
+#define AU1550_MEM_SDCONFIGB		0x0848
+#define AU1550_MEM_SDSTAT		0x0850
+#define AU1550_MEM_SDERRADDR		0x0858
+#define AU1550_MEM_SDSTRIDE0		0x0860
+#define AU1550_MEM_SDSTRIDE1		0x0868
+#define AU1550_MEM_SDSTRIDE2		0x0870
+#define AU1550_MEM_SDWRMD0		0x0880
+#define AU1550_MEM_SDWRMD1		0x0888
+#define AU1550_MEM_SDWRMD2		0x0890
+#define AU1550_MEM_SDPRECMD		0x08C0
+#define AU1550_MEM_SDAUTOREF		0x08C8
+#define AU1550_MEM_SDSREF		0x08D0
+#define AU1550_MEM_SDSLEEP		MEM_SDSREF
+
+/* Static Bus Controller register offsets */
+#define AU1000_MEM_STCFG0	0x000
+#define AU1000_MEM_STTIME0	0x004
+#define AU1000_MEM_STADDR0	0x008
+#define AU1000_MEM_STCFG1	0x010
+#define AU1000_MEM_STTIME1	0x014
+#define AU1000_MEM_STADDR1	0x018
+#define AU1000_MEM_STCFG2	0x020
+#define AU1000_MEM_STTIME2	0x024
+#define AU1000_MEM_STADDR2	0x028
+#define AU1000_MEM_STCFG3	0x030
+#define AU1000_MEM_STTIME3	0x034
+#define AU1000_MEM_STADDR3	0x038
+#define AU1000_MEM_STNDCTL	0x100
+#define AU1000_MEM_STSTAT	0x104
+
+#define MEM_STNAND_CMD		0x0
+#define MEM_STNAND_ADDR		0x4
+#define MEM_STNAND_DATA		0x20
+
+
+/* Programmable Counters 0 and 1 */
+#define AU1000_SYS_CNTRCTRL	0x14
+#  define SYS_CNTRL_E1S		(1 << 23)
+#  define SYS_CNTRL_T1S		(1 << 20)
+#  define SYS_CNTRL_M21		(1 << 19)
+#  define SYS_CNTRL_M11		(1 << 18)
+#  define SYS_CNTRL_M01		(1 << 17)
+#  define SYS_CNTRL_C1S		(1 << 16)
+#  define SYS_CNTRL_BP		(1 << 14)
+#  define SYS_CNTRL_EN1		(1 << 13)
+#  define SYS_CNTRL_BT1		(1 << 12)
+#  define SYS_CNTRL_EN0		(1 << 11)
+#  define SYS_CNTRL_BT0		(1 << 10)
+#  define SYS_CNTRL_E0		(1 << 8)
+#  define SYS_CNTRL_E0S		(1 << 7)
+#  define SYS_CNTRL_32S		(1 << 5)
+#  define SYS_CNTRL_T0S		(1 << 4)
+#  define SYS_CNTRL_M20		(1 << 3)
+#  define SYS_CNTRL_M10		(1 << 2)
+#  define SYS_CNTRL_M00		(1 << 1)
+#  define SYS_CNTRL_C0S		(1 << 0)
+
+/* Programmable Counter 0 Registers */
+#define AU1000_SYS_TOYTRIM	0x00
+#define AU1000_SYS_TOYWRITE	0x04
+#define AU1000_SYS_TOYMATCH0	0x08
+#define AU1000_SYS_TOYMATCH1	0x0c
+#define AU1000_SYS_TOYMATCH2	0x10
+#define AU1000_SYS_TOYREAD	0x40
+
+/* Programmable Counter 1 Registers */
+#define AU1000_SYS_RTCTRIM	0x44
+#define AU1000_SYS_RTCWRITE	0x48
+#define AU1000_SYS_RTCMATCH0	0x4c
+#define AU1000_SYS_RTCMATCH1	0x50
+#define AU1000_SYS_RTCMATCH2	0x54
+#define AU1000_SYS_RTCREAD	0x58
+
+
+/* GPIO */
+#define AU1000_SYS_PINFUNC	0x2C
+#  define SYS_PF_USB		(1 << 15)	/* 2nd USB device/host */
+#  define SYS_PF_U3		(1 << 14)	/* GPIO23/U3TXD */
+#  define SYS_PF_U2		(1 << 13)	/* GPIO22/U2TXD */
+#  define SYS_PF_U1		(1 << 12)	/* GPIO21/U1TXD */
+#  define SYS_PF_SRC		(1 << 11)	/* GPIO6/SROMCKE */
+#  define SYS_PF_CK5		(1 << 10)	/* GPIO3/CLK5 */
+#  define SYS_PF_CK4		(1 << 9)	/* GPIO2/CLK4 */
+#  define SYS_PF_IRF		(1 << 8)	/* GPIO15/IRFIRSEL */
+#  define SYS_PF_UR3		(1 << 7)	/* GPIO[14:9]/UART3 */
+#  define SYS_PF_I2D		(1 << 6)	/* GPIO8/I2SDI */
+#  define SYS_PF_I2S		(1 << 5)	/* I2S/GPIO[29:31] */
+#  define SYS_PF_NI2		(1 << 4)	/* NI2/GPIO[24:28] */
+#  define SYS_PF_U0		(1 << 3)	/* U0TXD/GPIO20 */
+#  define SYS_PF_RD		(1 << 2)	/* IRTXD/GPIO19 */
+#  define SYS_PF_A97		(1 << 1)	/* AC97/SSL1 */
+#  define SYS_PF_S0		(1 << 0)	/* SSI_0/GPIO[16:18] */
+
+/* Au1100 only */
+#  define SYS_PF_PC		(1 << 18)	/* PCMCIA/GPIO[207:204] */
+#  define SYS_PF_LCD		(1 << 17)	/* extern lcd/GPIO[203:200] */
+#  define SYS_PF_CS		(1 << 16)	/* EXTCLK0/32KHz to gpio2 */
+#  define SYS_PF_EX0		(1 << 9)	/* GPIO2/clock */
+
+/* Au1550 only.	 Redefines lots of pins */
+#  define SYS_PF_PSC2_MASK	(7 << 17)
+#  define SYS_PF_PSC2_AC97	0
+#  define SYS_PF_PSC2_SPI	0
+#  define SYS_PF_PSC2_I2S	(1 << 17)
+#  define SYS_PF_PSC2_SMBUS	(3 << 17)
+#  define SYS_PF_PSC2_GPIO	(7 << 17)
+#  define SYS_PF_PSC3_MASK	(7 << 20)
+#  define SYS_PF_PSC3_AC97	0
+#  define SYS_PF_PSC3_SPI	0
+#  define SYS_PF_PSC3_I2S	(1 << 20)
+#  define SYS_PF_PSC3_SMBUS	(3 << 20)
+#  define SYS_PF_PSC3_GPIO	(7 << 20)
+#  define SYS_PF_PSC1_S1	(1 << 1)
+#  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
+
+/* Au1200 only */
+#define SYS_PINFUNC_DMA		(1 << 31)
+#define SYS_PINFUNC_S0A		(1 << 30)
+#define SYS_PINFUNC_S1A		(1 << 29)
+#define SYS_PINFUNC_LP0		(1 << 28)
+#define SYS_PINFUNC_LP1		(1 << 27)
+#define SYS_PINFUNC_LD16	(1 << 26)
+#define SYS_PINFUNC_LD8		(1 << 25)
+#define SYS_PINFUNC_LD1		(1 << 24)
+#define SYS_PINFUNC_LD0		(1 << 23)
+#define SYS_PINFUNC_P1A		(3 << 21)
+#define SYS_PINFUNC_P1B		(1 << 20)
+#define SYS_PINFUNC_FS3		(1 << 19)
+#define SYS_PINFUNC_P0A		(3 << 17)
+#define SYS_PINFUNC_CS		(1 << 16)
+#define SYS_PINFUNC_CIM		(1 << 15)
+#define SYS_PINFUNC_P1C		(1 << 14)
+#define SYS_PINFUNC_U1T		(1 << 12)
+#define SYS_PINFUNC_U1R		(1 << 11)
+#define SYS_PINFUNC_EX1		(1 << 10)
+#define SYS_PINFUNC_EX0		(1 << 9)
+#define SYS_PINFUNC_U0R		(1 << 8)
+#define SYS_PINFUNC_MC		(1 << 7)
+#define SYS_PINFUNC_S0B		(1 << 6)
+#define SYS_PINFUNC_S0C		(1 << 5)
+#define SYS_PINFUNC_P0B		(1 << 4)
+#define SYS_PINFUNC_U0T		(1 << 3)
+#define SYS_PINFUNC_S1B		(1 << 2)
+
+/* Power Management */
+#define AU1000_SYS_SCRATCH0	0x18
+#define AU1000_SYS_SCRATCH1	0x1c
+#define AU1000_SYS_WAKEMSK	0x34
+#define AU1000_SYS_ENDIAN	0x38
+#define AU1000_SYS_POWERCTRL	0x3c
+#define AU1000_SYS_WAKESRC	0x5c
+#define AU1000_SYS_SLPPWR	0x78
+#define AU1000_SYS_SLEEP	0x7c
+
+#define SYS_WAKEMSK_D2		(1 << 9)
+#define SYS_WAKEMSK_M2		(1 << 8)
+#define SYS_WAKEMSK_GPIO(x)	(1 << (x))
+
+/* Clock Controller */
+#define AU1000_SYS_FREQCTRL0	0x20
+#define AU1000_SYS_FREQCTRL1	0x24
+#define AU1000_SYS_CLKSRC	0x28
+#define AU1000_SYS_CPUPLL	0x60
+#define AU1000_SYS_AUXPLL	0x64
+#define AU1300_SYS_AUXPLL2	0x68
+
+
+/**********************************************************************/
+
+
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI.  When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
+ */
+#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
+
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START		0x00001000
+#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
+
+#ifdef CONFIG_PCI
+
+#define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
+#define IOPORT_RESOURCE_END	0xffffffff
+#define IOMEM_RESOURCE_START	0x10000000
+#define IOMEM_RESOURCE_END	0xfffffffffULL
+
+#else
+
+/* Don't allow any legacy ports probing */
+#define IOPORT_RESOURCE_START	0x10000000
+#define IOPORT_RESOURCE_END	0xffffffff
+#define IOMEM_RESOURCE_START	0x10000000
+#define IOMEM_RESOURCE_END	0xfffffffffULL
+
+#endif
+
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM		0x0000
+#define PCI_REG_CONFIG		0x0004
+#define PCI_REG_B2BMASK_CCH	0x0008
+#define PCI_REG_B2BBASE0_VID	0x000C
+#define PCI_REG_B2BBASE1_SID	0x0010
+#define PCI_REG_MWMASK_DEV	0x0014
+#define PCI_REG_MWBASE_REV_CCL	0x0018
+#define PCI_REG_ERR_ADDR	0x001C
+#define PCI_REG_SPEC_INTACK	0x0020
+#define PCI_REG_ID		0x0100
+#define PCI_REG_STATCMD		0x0104
+#define PCI_REG_CLASSREV	0x0108
+#define PCI_REG_PARAM		0x010C
+#define PCI_REG_MBAR		0x0110
+#define PCI_REG_TIMEOUT		0x0140
+
+/* PCI controller block register bits */
+#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
+#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
+#define PCI_CONFIG_EP		(1 << 24) /* parity error */
+#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
+#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
+#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
+#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
+#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x)	 (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x)	 ((x) & 0xff)
+#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
+#define PCI_ID_VID(x)		((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x)	((x) & 0xff)
+#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x)	((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
+#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
+
+
+/**********************************************************************/
+
 
 #ifndef _LANGUAGE_ASSEMBLY
 
@@ -45,52 +597,36 @@
 
 #include <asm/cpu.h>
 
-/* cpu pipeline flush */
-void static inline au_sync(void)
-{
-	__asm__ volatile ("sync");
-}
-
-void static inline au_sync_udelay(int us)
+/* helpers to access the SYS_* registers */
+static inline unsigned long alchemy_rdsys(int regofs)
 {
-	__asm__ volatile ("sync");
-	udelay(us);
-}
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 
-void static inline au_sync_delay(int ms)
-{
-	__asm__ volatile ("sync");
-	mdelay(ms);
+	return __raw_readl(b + regofs);
 }
 
-void static inline au_writeb(u8 val, unsigned long reg)
+static inline void alchemy_wrsys(unsigned long v, int regofs)
 {
-	*(volatile u8 *)reg = val;
-}
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 
-void static inline au_writew(u16 val, unsigned long reg)
-{
-	*(volatile u16 *)reg = val;
+	__raw_writel(v, b + regofs);
+	wmb(); /* drain writebuffer */
 }
 
-void static inline au_writel(u32 val, unsigned long reg)
+/* helpers to access static memctrl registers */
+static inline unsigned long alchemy_rdsmem(int regofs)
 {
-	*(volatile u32 *)reg = val;
-}
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 
-static inline u8 au_readb(unsigned long reg)
-{
-	return *(volatile u8 *)reg;
+	return __raw_readl(b + regofs);
 }
 
-static inline u16 au_readw(unsigned long reg)
+static inline void alchemy_wrsmem(unsigned long v, int regofs)
 {
-	return *(volatile u16 *)reg;
-}
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 
-static inline u32 au_readl(unsigned long reg)
-{
-	return *(volatile u32 *)reg;
+	__raw_writel(v, b + regofs);
+	wmb(); /* drain writebuffer */
 }
 
 /* Early Au1000 have a write-only SYS_CPUPLL register. */
@@ -192,19 +728,20 @@ static inline void alchemy_uart_enable(u
 	/* reset, enable clock, deassert reset */
 	if ((__raw_readl(addr + 0x100) & 3) != 3) {
 		__raw_writel(0, addr + 0x100);
-		wmb();
+		wmb(); /* drain writebuffer */
 		__raw_writel(1, addr + 0x100);
-		wmb();
+		wmb(); /* drain writebuffer */
 	}
 	__raw_writel(3, addr + 0x100);
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 static inline void alchemy_uart_disable(u32 uart_phys)
 {
 	void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+
 	__raw_writel(0, addr + 0x100);	/* UART_MOD_CNTRL */
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
@@ -223,7 +760,7 @@ static inline void alchemy_uart_putchar(
 	} while (--timeout);
 
 	__raw_writel(c, base + 0x04);	/* tx */
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 /* return number of ethernet MACs on a given cputype */
@@ -240,20 +777,13 @@ static inline int alchemy_get_macs(int t
 	return 0;
 }
 
-/* arch/mips/au1000/common/clocks.c */
-extern void set_au1x00_speed(unsigned int new_freq);
-extern unsigned int get_au1x00_speed(void);
-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
-extern unsigned long get_au1x00_uart_baud_base(void);
-extern unsigned long au1xxx_calc_clock(void);
-
 /* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
 void alchemy_sleep_au1000(void);
 void alchemy_sleep_au1550(void);
 void alchemy_sleep_au1300(void);
 void au_sleep(void);
 
-/* USB: drivers/usb/host/alchemy-common.c */
+/* USB: arch/mips/alchemy/common/usb.c */
 enum alchemy_usb_block {
 	ALCHEMY_USB_OHCI0,
 	ALCHEMY_USB_UDC0,
@@ -272,6 +802,20 @@ struct alchemy_pci_platdata {
 	unsigned long pci_cfg_clr;
 };
 
+/* The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's
+ * not used to select FIR/SIR mode on the transceiver but as a GPIO.
+ * Instead a CPLD has to be told about the mode.  The driver calls the
+ * set_phy_mode() function in addition to driving the IRFIRSEL pin.
+ */
+#define AU1000_IRDA_PHY_MODE_OFF	0
+#define AU1000_IRDA_PHY_MODE_SIR	1
+#define AU1000_IRDA_PHY_MODE_FIR	2
+
+struct au1k_irda_platform_data {
+	void (*set_phy_mode)(int mode);
+};
+
+
 /* Multifunction pins: Each of these pins can either be assigned to the
  * GPIO controller or a on-chip peripheral.
  * Call "au1300_pinfunc_to_dev()" or "au1300_pinfunc_to_gpio()" to
@@ -344,20 +888,6 @@ enum au1300_vss_block {
 
 extern void au1300_vss_block_control(int block, int enable);
 
-
-/* SOC Interrupt numbers */
-/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
-#define AU1000_INTC0_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
-#define AU1000_INTC0_INT_LAST	(AU1000_INTC0_INT_BASE + 31)
-#define AU1000_INTC1_INT_BASE	(AU1000_INTC0_INT_LAST + 1)
-#define AU1000_INTC1_INT_LAST	(AU1000_INTC1_INT_BASE + 31)
-#define AU1000_MAX_INTR		AU1000_INTC1_INT_LAST
-
-/* Au1300-style (GPIC): 1 controller with up to 128 sources */
-#define ALCHEMY_GPIC_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
-#define ALCHEMY_GPIC_INT_NUM	128
-#define ALCHEMY_GPIC_INT_LAST	(ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
-
 enum soc_au1000_ints {
 	AU1000_FIRST_INT	= AU1000_INTC0_INT_BASE,
 	AU1000_UART0_INT	= AU1000_FIRST_INT,
@@ -678,885 +1208,4 @@ enum soc_au1200_ints {
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
-/* Au1300 peripheral interrupt numbers */
-#define AU1300_FIRST_INT	(ALCHEMY_GPIC_INT_BASE)
-#define AU1300_UART1_INT	(AU1300_FIRST_INT + 17)
-#define AU1300_UART2_INT	(AU1300_FIRST_INT + 25)
-#define AU1300_UART3_INT	(AU1300_FIRST_INT + 27)
-#define AU1300_SD1_INT		(AU1300_FIRST_INT + 32)
-#define AU1300_SD2_INT		(AU1300_FIRST_INT + 38)
-#define AU1300_PSC0_INT		(AU1300_FIRST_INT + 48)
-#define AU1300_PSC1_INT		(AU1300_FIRST_INT + 52)
-#define AU1300_PSC2_INT		(AU1300_FIRST_INT + 56)
-#define AU1300_PSC3_INT		(AU1300_FIRST_INT + 60)
-#define AU1300_NAND_INT		(AU1300_FIRST_INT + 62)
-#define AU1300_DDMA_INT		(AU1300_FIRST_INT + 75)
-#define AU1300_MMU_INT		(AU1300_FIRST_INT + 76)
-#define AU1300_MPU_INT		(AU1300_FIRST_INT + 77)
-#define AU1300_GPU_INT		(AU1300_FIRST_INT + 78)
-#define AU1300_UDMA_INT		(AU1300_FIRST_INT + 79)
-#define AU1300_TOY_INT		(AU1300_FIRST_INT + 80)
-#define AU1300_TOY_MATCH0_INT	(AU1300_FIRST_INT + 81)
-#define AU1300_TOY_MATCH1_INT	(AU1300_FIRST_INT + 82)
-#define AU1300_TOY_MATCH2_INT	(AU1300_FIRST_INT + 83)
-#define AU1300_RTC_INT		(AU1300_FIRST_INT + 84)
-#define AU1300_RTC_MATCH0_INT	(AU1300_FIRST_INT + 85)
-#define AU1300_RTC_MATCH1_INT	(AU1300_FIRST_INT + 86)
-#define AU1300_RTC_MATCH2_INT	(AU1300_FIRST_INT + 87)
-#define AU1300_UART0_INT	(AU1300_FIRST_INT + 88)
-#define AU1300_SD0_INT		(AU1300_FIRST_INT + 89)
-#define AU1300_USB_INT		(AU1300_FIRST_INT + 90)
-#define AU1300_LCD_INT		(AU1300_FIRST_INT + 91)
-#define AU1300_BSA_INT		(AU1300_FIRST_INT + 92)
-#define AU1300_MPE_INT		(AU1300_FIRST_INT + 93)
-#define AU1300_ITE_INT		(AU1300_FIRST_INT + 94)
-#define AU1300_AES_INT		(AU1300_FIRST_INT + 95)
-#define AU1300_CIM_INT		(AU1300_FIRST_INT + 96)
-
-/**********************************************************************/
-
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
- */
-
-#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
-#define AU1300_ROM_PHYS_ADDR		0x10000000 /* 5 */
-#define AU1300_OTP_PHYS_ADDR		0x10002000 /* 5 */
-#define AU1300_VSS_PHYS_ADDR		0x10003000 /* 5 */
-#define AU1300_UART0_PHYS_ADDR		0x10100000 /* 5 */
-#define AU1300_UART1_PHYS_ADDR		0x10101000 /* 5 */
-#define AU1300_UART2_PHYS_ADDR		0x10102000 /* 5 */
-#define AU1300_UART3_PHYS_ADDR		0x10103000 /* 5 */
-#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
-#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
-#define AU1300_GPIC_PHYS_ADDR		0x10200000 /* 5 */
-#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
-#define AU1200_AES_PHYS_ADDR		0x10300000 /* 45 */
-#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
-#define AU1300_GPU_PHYS_ADDR		0x10500000 /* 5 */
-#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 245 */
-#define AU1300_SD1_PHYS_ADDR		0x10601000 /* 5 */
-#define AU1300_SD2_PHYS_ADDR		0x10602000 /* 5 */
-#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
-#define AU1300_SYS_PHYS_ADDR		0x10900000 /* 5 */
-#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
-#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
-#define AU1300_PSC0_PHYS_ADDR		0x10A00000 /* 5 */
-#define AU1300_PSC1_PHYS_ADDR		0x10A01000 /* 5 */
-#define AU1300_PSC2_PHYS_ADDR		0x10A02000 /* 5 */
-#define AU1300_PSC3_PHYS_ADDR		0x10A03000 /* 5 */
-#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
-#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
-#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
-#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
-#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
-#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 012345 */
-#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
-#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
-#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
-#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
-#define AU1300_UDMA_PHYS_ADDR		0x14001800 /* 5 */
-#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 345 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 345 */
-#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
-#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 45 */
-#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
-#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
-#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
-#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
-#define AU1300_MAEITE_PHYS_ADDR		0x14010000 /* 5 */
-#define AU1300_MAEMPE_PHYS_ADDR		0x14014000 /* 5 */
-#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
-#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
-#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
-#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
-#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
-#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
-#define AU1300_USB_EHCI_PHYS_ADDR	0x14020000 /* 5 */
-#define AU1300_USB_OHCI0_PHYS_ADDR	0x14020400 /* 5 */
-#define AU1300_USB_OHCI1_PHYS_ADDR	0x14020800 /* 5 */
-#define AU1300_USB_CTL_PHYS_ADDR	0x14021000 /* 5 */
-#define AU1300_USB_OTG_PHYS_ADDR	0x14022000 /* 5 */
-#define AU1300_MAEBSA_PHYS_ADDR		0x14030000 /* 5 */
-#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
-#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 45 */
-#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
-#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
-#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
-#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
-#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 012345 */
-#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 012345 */
-#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 012345 */
-
-/**********************************************************************/
-
-
-/*
- * Au1300 GPIO+INT controller (GPIC) register offsets and bits
- * Registers are 128bits (0x10 bytes), divided into 4 "banks".
- */
-#define AU1300_GPIC_PINVAL	0x0000
-#define AU1300_GPIC_PINVALCLR	0x0010
-#define AU1300_GPIC_IPEND	0x0020
-#define AU1300_GPIC_PRIENC	0x0030
-#define AU1300_GPIC_IEN		0x0040	/* int_mask in manual */
-#define AU1300_GPIC_IDIS	0x0050	/* int_maskclr in manual */
-#define AU1300_GPIC_DMASEL	0x0060
-#define AU1300_GPIC_DEVSEL	0x0080
-#define AU1300_GPIC_DEVCLR	0x0090
-#define AU1300_GPIC_RSTVAL	0x00a0
-/* pin configuration space. one 32bit register for up to 128 IRQs */
-#define AU1300_GPIC_PINCFG	0x1000
-
-#define GPIC_GPIO_TO_BIT(gpio)	\
-	(1 << ((gpio) & 0x1f))
-
-#define GPIC_GPIO_BANKOFF(gpio) \
-	(((gpio) >> 5) * 4)
-
-/* Pin Control bits: who owns the pin, what does it do */
-#define GPIC_CFG_PC_GPIN		0
-#define GPIC_CFG_PC_DEV			1
-#define GPIC_CFG_PC_GPOLOW		2
-#define GPIC_CFG_PC_GPOHIGH		3
-#define GPIC_CFG_PC_MASK		3
-
-/* assign pin to MIPS IRQ line */
-#define GPIC_CFG_IL_SET(x)	(((x) & 3) << 2)
-#define GPIC_CFG_IL_MASK	(3 << 2)
-
-/* pin interrupt type setup */
-#define GPIC_CFG_IC_OFF		(0 << 4)
-#define GPIC_CFG_IC_LEVEL_LOW	(1 << 4)
-#define GPIC_CFG_IC_LEVEL_HIGH	(2 << 4)
-#define GPIC_CFG_IC_EDGE_FALL	(5 << 4)
-#define GPIC_CFG_IC_EDGE_RISE	(6 << 4)
-#define GPIC_CFG_IC_EDGE_BOTH	(7 << 4)
-#define GPIC_CFG_IC_MASK	(7 << 4)
-
-/* allow interrupt to wake cpu from 'wait' */
-#define GPIC_CFG_IDLEWAKE	(1 << 7)
-
-/***********************************************************************/
-
-/* Au1000 SDRAM memory controller register offsets */
-#define AU1000_MEM_SDMODE0		0x0000
-#define AU1000_MEM_SDMODE1		0x0004
-#define AU1000_MEM_SDMODE2		0x0008
-#define AU1000_MEM_SDADDR0		0x000C
-#define AU1000_MEM_SDADDR1		0x0010
-#define AU1000_MEM_SDADDR2		0x0014
-#define AU1000_MEM_SDREFCFG		0x0018
-#define AU1000_MEM_SDPRECMD		0x001C
-#define AU1000_MEM_SDAUTOREF		0x0020
-#define AU1000_MEM_SDWRMD0		0x0024
-#define AU1000_MEM_SDWRMD1		0x0028
-#define AU1000_MEM_SDWRMD2		0x002C
-#define AU1000_MEM_SDSLEEP		0x0030
-#define AU1000_MEM_SDSMCKE		0x0034
-
-/* MEM_SDMODE register content definitions */
-#define MEM_SDMODE_F		(1 << 22)
-#define MEM_SDMODE_SR		(1 << 21)
-#define MEM_SDMODE_BS		(1 << 20)
-#define MEM_SDMODE_RS		(3 << 18)
-#define MEM_SDMODE_CS		(7 << 15)
-#define MEM_SDMODE_TRAS		(15 << 11)
-#define MEM_SDMODE_TMRD		(3 << 9)
-#define MEM_SDMODE_TWR		(3 << 7)
-#define MEM_SDMODE_TRP		(3 << 5)
-#define MEM_SDMODE_TRCD		(3 << 3)
-#define MEM_SDMODE_TCL		(7 << 0)
-
-#define MEM_SDMODE_BS_2Bank	(0 << 20)
-#define MEM_SDMODE_BS_4Bank	(1 << 20)
-#define MEM_SDMODE_RS_11Row	(0 << 18)
-#define MEM_SDMODE_RS_12Row	(1 << 18)
-#define MEM_SDMODE_RS_13Row	(2 << 18)
-#define MEM_SDMODE_RS_N(N)	((N) << 18)
-#define MEM_SDMODE_CS_7Col	(0 << 15)
-#define MEM_SDMODE_CS_8Col	(1 << 15)
-#define MEM_SDMODE_CS_9Col	(2 << 15)
-#define MEM_SDMODE_CS_10Col	(3 << 15)
-#define MEM_SDMODE_CS_11Col	(4 << 15)
-#define MEM_SDMODE_CS_N(N)	((N) << 15)
-#define MEM_SDMODE_TRAS_N(N)	((N) << 11)
-#define MEM_SDMODE_TMRD_N(N)	((N) << 9)
-#define MEM_SDMODE_TWR_N(N)	((N) << 7)
-#define MEM_SDMODE_TRP_N(N)	((N) << 5)
-#define MEM_SDMODE_TRCD_N(N)	((N) << 3)
-#define MEM_SDMODE_TCL_N(N)	((N) << 0)
-
-/* MEM_SDADDR register contents definitions */
-#define MEM_SDADDR_E		(1 << 20)
-#define MEM_SDADDR_CSBA		(0x03FF << 10)
-#define MEM_SDADDR_CSMASK	(0x03FF << 0)
-#define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
-#define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
-
-/* MEM_SDREFCFG register content definitions */
-#define MEM_SDREFCFG_TRC	(15 << 28)
-#define MEM_SDREFCFG_TRPM	(3 << 26)
-#define MEM_SDREFCFG_E		(1 << 25)
-#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
-#define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
-#define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
-#define MEM_SDREFCFG_REF_N(N)	(N)
-
-/* Au1550 SDRAM Register Offsets */
-#define AU1550_MEM_SDMODE0		0x0800
-#define AU1550_MEM_SDMODE1		0x0808
-#define AU1550_MEM_SDMODE2		0x0810
-#define AU1550_MEM_SDADDR0		0x0820
-#define AU1550_MEM_SDADDR1		0x0828
-#define AU1550_MEM_SDADDR2		0x0830
-#define AU1550_MEM_SDCONFIGA		0x0840
-#define AU1550_MEM_SDCONFIGB		0x0848
-#define AU1550_MEM_SDSTAT		0x0850
-#define AU1550_MEM_SDERRADDR		0x0858
-#define AU1550_MEM_SDSTRIDE0		0x0860
-#define AU1550_MEM_SDSTRIDE1		0x0868
-#define AU1550_MEM_SDSTRIDE2		0x0870
-#define AU1550_MEM_SDWRMD0		0x0880
-#define AU1550_MEM_SDWRMD1		0x0888
-#define AU1550_MEM_SDWRMD2		0x0890
-#define AU1550_MEM_SDPRECMD		0x08C0
-#define AU1550_MEM_SDAUTOREF		0x08C8
-#define AU1550_MEM_SDSREF		0x08D0
-#define AU1550_MEM_SDSLEEP		MEM_SDSREF
-
-/* Static Bus Controller */
-#define MEM_STCFG0		0xB4001000
-#define MEM_STTIME0		0xB4001004
-#define MEM_STADDR0		0xB4001008
-
-#define MEM_STCFG1		0xB4001010
-#define MEM_STTIME1		0xB4001014
-#define MEM_STADDR1		0xB4001018
-
-#define MEM_STCFG2		0xB4001020
-#define MEM_STTIME2		0xB4001024
-#define MEM_STADDR2		0xB4001028
-
-#define MEM_STCFG3		0xB4001030
-#define MEM_STTIME3		0xB4001034
-#define MEM_STADDR3		0xB4001038
-
-#define MEM_STNDCTL		0xB4001100
-#define MEM_STSTAT		0xB4001104
-
-#define MEM_STNAND_CMD		0x0
-#define MEM_STNAND_ADDR		0x4
-#define MEM_STNAND_DATA		0x20
-
-
-/* Programmable Counters 0 and 1 */
-#define SYS_BASE		0xB1900000
-#define SYS_COUNTER_CNTRL	(SYS_BASE + 0x14)
-#  define SYS_CNTRL_E1S		(1 << 23)
-#  define SYS_CNTRL_T1S		(1 << 20)
-#  define SYS_CNTRL_M21		(1 << 19)
-#  define SYS_CNTRL_M11		(1 << 18)
-#  define SYS_CNTRL_M01		(1 << 17)
-#  define SYS_CNTRL_C1S		(1 << 16)
-#  define SYS_CNTRL_BP		(1 << 14)
-#  define SYS_CNTRL_EN1		(1 << 13)
-#  define SYS_CNTRL_BT1		(1 << 12)
-#  define SYS_CNTRL_EN0		(1 << 11)
-#  define SYS_CNTRL_BT0		(1 << 10)
-#  define SYS_CNTRL_E0		(1 << 8)
-#  define SYS_CNTRL_E0S		(1 << 7)
-#  define SYS_CNTRL_32S		(1 << 5)
-#  define SYS_CNTRL_T0S		(1 << 4)
-#  define SYS_CNTRL_M20		(1 << 3)
-#  define SYS_CNTRL_M10		(1 << 2)
-#  define SYS_CNTRL_M00		(1 << 1)
-#  define SYS_CNTRL_C0S		(1 << 0)
-
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM		(SYS_BASE + 0)
-#define SYS_TOYWRITE		(SYS_BASE + 4)
-#define SYS_TOYMATCH0		(SYS_BASE + 8)
-#define SYS_TOYMATCH1		(SYS_BASE + 0xC)
-#define SYS_TOYMATCH2		(SYS_BASE + 0x10)
-#define SYS_TOYREAD		(SYS_BASE + 0x40)
-
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM		(SYS_BASE + 0x44)
-#define SYS_RTCWRITE		(SYS_BASE + 0x48)
-#define SYS_RTCMATCH0		(SYS_BASE + 0x4C)
-#define SYS_RTCMATCH1		(SYS_BASE + 0x50)
-#define SYS_RTCMATCH2		(SYS_BASE + 0x54)
-#define SYS_RTCREAD		(SYS_BASE + 0x58)
-
-/* I2S Controller */
-#define I2S_DATA		0xB1000000
-#  define I2S_DATA_MASK		0xffffff
-#define I2S_CONFIG		0xB1000004
-#  define I2S_CONFIG_XU		(1 << 25)
-#  define I2S_CONFIG_XO		(1 << 24)
-#  define I2S_CONFIG_RU		(1 << 23)
-#  define I2S_CONFIG_RO		(1 << 22)
-#  define I2S_CONFIG_TR		(1 << 21)
-#  define I2S_CONFIG_TE		(1 << 20)
-#  define I2S_CONFIG_TF		(1 << 19)
-#  define I2S_CONFIG_RR		(1 << 18)
-#  define I2S_CONFIG_RE		(1 << 17)
-#  define I2S_CONFIG_RF		(1 << 16)
-#  define I2S_CONFIG_PD		(1 << 11)
-#  define I2S_CONFIG_LB		(1 << 10)
-#  define I2S_CONFIG_IC		(1 << 9)
-#  define I2S_CONFIG_FM_BIT	7
-#  define I2S_CONFIG_FM_MASK	(0x3 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_I2S	(0x0 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_LJ	(0x1 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_RJ	(0x2 << I2S_CONFIG_FM_BIT)
-#  define I2S_CONFIG_TN		(1 << 6)
-#  define I2S_CONFIG_RN		(1 << 5)
-#  define I2S_CONFIG_SZ_BIT	0
-#  define I2S_CONFIG_SZ_MASK	(0x1F << I2S_CONFIG_SZ_BIT)
-
-#define I2S_CONTROL		0xB1000008
-#  define I2S_CONTROL_D		(1 << 1)
-#  define I2S_CONTROL_CE	(1 << 0)
-
-
-/* Ethernet Controllers  */
-
-/* 4 byte offsets from AU1000_ETH_BASE */
-#define MAC_CONTROL		0x0
-#  define MAC_RX_ENABLE		(1 << 2)
-#  define MAC_TX_ENABLE		(1 << 3)
-#  define MAC_DEF_CHECK		(1 << 5)
-#  define MAC_SET_BL(X)		(((X) & 0x3) << 6)
-#  define MAC_AUTO_PAD		(1 << 8)
-#  define MAC_DISABLE_RETRY	(1 << 10)
-#  define MAC_DISABLE_BCAST	(1 << 11)
-#  define MAC_LATE_COL		(1 << 12)
-#  define MAC_HASH_MODE		(1 << 13)
-#  define MAC_HASH_ONLY		(1 << 15)
-#  define MAC_PASS_ALL		(1 << 16)
-#  define MAC_INVERSE_FILTER	(1 << 17)
-#  define MAC_PROMISCUOUS	(1 << 18)
-#  define MAC_PASS_ALL_MULTI	(1 << 19)
-#  define MAC_FULL_DUPLEX	(1 << 20)
-#  define MAC_NORMAL_MODE	0
-#  define MAC_INT_LOOPBACK	(1 << 21)
-#  define MAC_EXT_LOOPBACK	(1 << 22)
-#  define MAC_DISABLE_RX_OWN	(1 << 23)
-#  define MAC_BIG_ENDIAN	(1 << 30)
-#  define MAC_RX_ALL		(1 << 31)
-#define MAC_ADDRESS_HIGH	0x4
-#define MAC_ADDRESS_LOW		0x8
-#define MAC_MCAST_HIGH		0xC
-#define MAC_MCAST_LOW		0x10
-#define MAC_MII_CNTRL		0x14
-#  define MAC_MII_BUSY		(1 << 0)
-#  define MAC_MII_READ		0
-#  define MAC_MII_WRITE		(1 << 1)
-#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
-#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
-#define MAC_MII_DATA		0x18
-#define MAC_FLOW_CNTRL		0x1C
-#  define MAC_FLOW_CNTRL_BUSY	(1 << 0)
-#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
-#  define MAC_PASS_CONTROL	(1 << 2)
-#  define MAC_SET_PAUSE(X)	(((X) & 0xffff) << 16)
-#define MAC_VLAN1_TAG		0x20
-#define MAC_VLAN2_TAG		0x24
-
-/* Ethernet Controller Enable */
-
-#  define MAC_EN_CLOCK_ENABLE	(1 << 0)
-#  define MAC_EN_RESET0		(1 << 1)
-#  define MAC_EN_TOSS		(0 << 2)
-#  define MAC_EN_CACHEABLE	(1 << 3)
-#  define MAC_EN_RESET1		(1 << 4)
-#  define MAC_EN_RESET2		(1 << 5)
-#  define MAC_DMA_RESET		(1 << 6)
-
-/* Ethernet Controller DMA Channels */
-
-#define MAC0_TX_DMA_ADDR	0xB4004000
-#define MAC1_TX_DMA_ADDR	0xB4004200
-/* offsets from MAC_TX_RING_ADDR address */
-#define MAC_TX_BUFF0_STATUS	0x0
-#  define TX_FRAME_ABORTED	(1 << 0)
-#  define TX_JAB_TIMEOUT	(1 << 1)
-#  define TX_NO_CARRIER		(1 << 2)
-#  define TX_LOSS_CARRIER	(1 << 3)
-#  define TX_EXC_DEF		(1 << 4)
-#  define TX_LATE_COLL_ABORT	(1 << 5)
-#  define TX_EXC_COLL		(1 << 6)
-#  define TX_UNDERRUN		(1 << 7)
-#  define TX_DEFERRED		(1 << 8)
-#  define TX_LATE_COLL		(1 << 9)
-#  define TX_COLL_CNT_MASK	(0xF << 10)
-#  define TX_PKT_RETRY		(1 << 31)
-#define MAC_TX_BUFF0_ADDR	0x4
-#  define TX_DMA_ENABLE		(1 << 0)
-#  define TX_T_DONE		(1 << 1)
-#  define TX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
-#define MAC_TX_BUFF0_LEN	0x8
-#define MAC_TX_BUFF1_STATUS	0x10
-#define MAC_TX_BUFF1_ADDR	0x14
-#define MAC_TX_BUFF1_LEN	0x18
-#define MAC_TX_BUFF2_STATUS	0x20
-#define MAC_TX_BUFF2_ADDR	0x24
-#define MAC_TX_BUFF2_LEN	0x28
-#define MAC_TX_BUFF3_STATUS	0x30
-#define MAC_TX_BUFF3_ADDR	0x34
-#define MAC_TX_BUFF3_LEN	0x38
-
-#define MAC0_RX_DMA_ADDR	0xB4004100
-#define MAC1_RX_DMA_ADDR	0xB4004300
-/* offsets from MAC_RX_RING_ADDR */
-#define MAC_RX_BUFF0_STATUS	0x0
-#  define RX_FRAME_LEN_MASK	0x3fff
-#  define RX_WDOG_TIMER		(1 << 14)
-#  define RX_RUNT		(1 << 15)
-#  define RX_OVERLEN		(1 << 16)
-#  define RX_COLL		(1 << 17)
-#  define RX_ETHER		(1 << 18)
-#  define RX_MII_ERROR		(1 << 19)
-#  define RX_DRIBBLING		(1 << 20)
-#  define RX_CRC_ERROR		(1 << 21)
-#  define RX_VLAN1		(1 << 22)
-#  define RX_VLAN2		(1 << 23)
-#  define RX_LEN_ERROR		(1 << 24)
-#  define RX_CNTRL_FRAME	(1 << 25)
-#  define RX_U_CNTRL_FRAME	(1 << 26)
-#  define RX_MCAST_FRAME	(1 << 27)
-#  define RX_BCAST_FRAME	(1 << 28)
-#  define RX_FILTER_FAIL	(1 << 29)
-#  define RX_PACKET_FILTER	(1 << 30)
-#  define RX_MISSED_FRAME	(1 << 31)
-
-#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
-		    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
-		    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
-#define MAC_RX_BUFF0_ADDR	0x4
-#  define RX_DMA_ENABLE		(1 << 0)
-#  define RX_T_DONE		(1 << 1)
-#  define RX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
-#  define RX_SET_BUFF_ADDR(X)	((X) & 0xffffffc0)
-#define MAC_RX_BUFF1_STATUS	0x10
-#define MAC_RX_BUFF1_ADDR	0x14
-#define MAC_RX_BUFF2_STATUS	0x20
-#define MAC_RX_BUFF2_ADDR	0x24
-#define MAC_RX_BUFF3_STATUS	0x30
-#define MAC_RX_BUFF3_ADDR	0x34
-
-/* SSIO */
-#define SSI0_STATUS		0xB1600000
-#  define SSI_STATUS_BF		(1 << 4)
-#  define SSI_STATUS_OF		(1 << 3)
-#  define SSI_STATUS_UF		(1 << 2)
-#  define SSI_STATUS_D		(1 << 1)
-#  define SSI_STATUS_B		(1 << 0)
-#define SSI0_INT		0xB1600004
-#  define SSI_INT_OI		(1 << 3)
-#  define SSI_INT_UI		(1 << 2)
-#  define SSI_INT_DI		(1 << 1)
-#define SSI0_INT_ENABLE		0xB1600008
-#  define SSI_INTE_OIE		(1 << 3)
-#  define SSI_INTE_UIE		(1 << 2)
-#  define SSI_INTE_DIE		(1 << 1)
-#define SSI0_CONFIG		0xB1600020
-#  define SSI_CONFIG_AO		(1 << 24)
-#  define SSI_CONFIG_DO		(1 << 23)
-#  define SSI_CONFIG_ALEN_BIT	20
-#  define SSI_CONFIG_ALEN_MASK	(0x7 << 20)
-#  define SSI_CONFIG_DLEN_BIT	16
-#  define SSI_CONFIG_DLEN_MASK	(0x7 << 16)
-#  define SSI_CONFIG_DD		(1 << 11)
-#  define SSI_CONFIG_AD		(1 << 10)
-#  define SSI_CONFIG_BM_BIT	8
-#  define SSI_CONFIG_BM_MASK	(0x3 << 8)
-#  define SSI_CONFIG_CE		(1 << 7)
-#  define SSI_CONFIG_DP		(1 << 6)
-#  define SSI_CONFIG_DL		(1 << 5)
-#  define SSI_CONFIG_EP		(1 << 4)
-#define SSI0_ADATA		0xB1600024
-#  define SSI_AD_D		(1 << 24)
-#  define SSI_AD_ADDR_BIT	16
-#  define SSI_AD_ADDR_MASK	(0xff << 16)
-#  define SSI_AD_DATA_BIT	0
-#  define SSI_AD_DATA_MASK	(0xfff << 0)
-#define SSI0_CLKDIV		0xB1600028
-#define SSI0_CONTROL		0xB1600100
-#  define SSI_CONTROL_CD	(1 << 1)
-#  define SSI_CONTROL_E		(1 << 0)
-
-/* SSI1 */
-#define SSI1_STATUS		0xB1680000
-#define SSI1_INT		0xB1680004
-#define SSI1_INT_ENABLE		0xB1680008
-#define SSI1_CONFIG		0xB1680020
-#define SSI1_ADATA		0xB1680024
-#define SSI1_CLKDIV		0xB1680028
-#define SSI1_ENABLE		0xB1680100
-
-/*
- * Register content definitions
- */
-#define SSI_STATUS_BF		(1 << 4)
-#define SSI_STATUS_OF		(1 << 3)
-#define SSI_STATUS_UF		(1 << 2)
-#define SSI_STATUS_D		(1 << 1)
-#define SSI_STATUS_B		(1 << 0)
-
-/* SSI_INT */
-#define SSI_INT_OI		(1 << 3)
-#define SSI_INT_UI		(1 << 2)
-#define SSI_INT_DI		(1 << 1)
-
-/* SSI_INTEN */
-#define SSI_INTEN_OIE		(1 << 3)
-#define SSI_INTEN_UIE		(1 << 2)
-#define SSI_INTEN_DIE		(1 << 1)
-
-#define SSI_CONFIG_AO		(1 << 24)
-#define SSI_CONFIG_DO		(1 << 23)
-#define SSI_CONFIG_ALEN		(7 << 20)
-#define SSI_CONFIG_DLEN		(15 << 16)
-#define SSI_CONFIG_DD		(1 << 11)
-#define SSI_CONFIG_AD		(1 << 10)
-#define SSI_CONFIG_BM		(3 << 8)
-#define SSI_CONFIG_CE		(1 << 7)
-#define SSI_CONFIG_DP		(1 << 6)
-#define SSI_CONFIG_DL		(1 << 5)
-#define SSI_CONFIG_EP		(1 << 4)
-#define SSI_CONFIG_ALEN_N(N)	((N-1) << 20)
-#define SSI_CONFIG_DLEN_N(N)	((N-1) << 16)
-#define SSI_CONFIG_BM_HI	(0 << 8)
-#define SSI_CONFIG_BM_LO	(1 << 8)
-#define SSI_CONFIG_BM_CY	(2 << 8)
-
-#define SSI_ADATA_D		(1 << 24)
-#define SSI_ADATA_ADDR		(0xFF << 16)
-#define SSI_ADATA_DATA		0x0FFF
-#define SSI_ADATA_ADDR_N(N)	(N << 16)
-
-#define SSI_ENABLE_CD		(1 << 1)
-#define SSI_ENABLE_E		(1 << 0)
-
-
-/*
- * The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's not
- * used to select FIR/SIR mode on the transceiver but as a GPIO.  Instead a
- * CPLD has to be told about the mode.
- */
-#define AU1000_IRDA_PHY_MODE_OFF	0
-#define AU1000_IRDA_PHY_MODE_SIR	1
-#define AU1000_IRDA_PHY_MODE_FIR	2
-
-struct au1k_irda_platform_data {
-	void(*set_phy_mode)(int mode);
-};
-
-
-/* GPIO */
-#define SYS_PINFUNC		0xB190002C
-#  define SYS_PF_USB		(1 << 15)	/* 2nd USB device/host */
-#  define SYS_PF_U3		(1 << 14)	/* GPIO23/U3TXD */
-#  define SYS_PF_U2		(1 << 13)	/* GPIO22/U2TXD */
-#  define SYS_PF_U1		(1 << 12)	/* GPIO21/U1TXD */
-#  define SYS_PF_SRC		(1 << 11)	/* GPIO6/SROMCKE */
-#  define SYS_PF_CK5		(1 << 10)	/* GPIO3/CLK5 */
-#  define SYS_PF_CK4		(1 << 9)	/* GPIO2/CLK4 */
-#  define SYS_PF_IRF		(1 << 8)	/* GPIO15/IRFIRSEL */
-#  define SYS_PF_UR3		(1 << 7)	/* GPIO[14:9]/UART3 */
-#  define SYS_PF_I2D		(1 << 6)	/* GPIO8/I2SDI */
-#  define SYS_PF_I2S		(1 << 5)	/* I2S/GPIO[29:31] */
-#  define SYS_PF_NI2		(1 << 4)	/* NI2/GPIO[24:28] */
-#  define SYS_PF_U0		(1 << 3)	/* U0TXD/GPIO20 */
-#  define SYS_PF_RD		(1 << 2)	/* IRTXD/GPIO19 */
-#  define SYS_PF_A97		(1 << 1)	/* AC97/SSL1 */
-#  define SYS_PF_S0		(1 << 0)	/* SSI_0/GPIO[16:18] */
-
-/* Au1100 only */
-#  define SYS_PF_PC		(1 << 18)	/* PCMCIA/GPIO[207:204] */
-#  define SYS_PF_LCD		(1 << 17)	/* extern lcd/GPIO[203:200] */
-#  define SYS_PF_CS		(1 << 16)	/* EXTCLK0/32KHz to gpio2 */
-#  define SYS_PF_EX0		(1 << 9)	/* GPIO2/clock */
-
-/* Au1550 only.	 Redefines lots of pins */
-#  define SYS_PF_PSC2_MASK	(7 << 17)
-#  define SYS_PF_PSC2_AC97	0
-#  define SYS_PF_PSC2_SPI	0
-#  define SYS_PF_PSC2_I2S	(1 << 17)
-#  define SYS_PF_PSC2_SMBUS	(3 << 17)
-#  define SYS_PF_PSC2_GPIO	(7 << 17)
-#  define SYS_PF_PSC3_MASK	(7 << 20)
-#  define SYS_PF_PSC3_AC97	0
-#  define SYS_PF_PSC3_SPI	0
-#  define SYS_PF_PSC3_I2S	(1 << 20)
-#  define SYS_PF_PSC3_SMBUS	(3 << 20)
-#  define SYS_PF_PSC3_GPIO	(7 << 20)
-#  define SYS_PF_PSC1_S1	(1 << 1)
-#  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
-
-/* Au1200 only */
-#define SYS_PINFUNC_DMA		(1 << 31)
-#define SYS_PINFUNC_S0A		(1 << 30)
-#define SYS_PINFUNC_S1A		(1 << 29)
-#define SYS_PINFUNC_LP0		(1 << 28)
-#define SYS_PINFUNC_LP1		(1 << 27)
-#define SYS_PINFUNC_LD16	(1 << 26)
-#define SYS_PINFUNC_LD8		(1 << 25)
-#define SYS_PINFUNC_LD1		(1 << 24)
-#define SYS_PINFUNC_LD0		(1 << 23)
-#define SYS_PINFUNC_P1A		(3 << 21)
-#define SYS_PINFUNC_P1B		(1 << 20)
-#define SYS_PINFUNC_FS3		(1 << 19)
-#define SYS_PINFUNC_P0A		(3 << 17)
-#define SYS_PINFUNC_CS		(1 << 16)
-#define SYS_PINFUNC_CIM		(1 << 15)
-#define SYS_PINFUNC_P1C		(1 << 14)
-#define SYS_PINFUNC_U1T		(1 << 12)
-#define SYS_PINFUNC_U1R		(1 << 11)
-#define SYS_PINFUNC_EX1		(1 << 10)
-#define SYS_PINFUNC_EX0		(1 << 9)
-#define SYS_PINFUNC_U0R		(1 << 8)
-#define SYS_PINFUNC_MC		(1 << 7)
-#define SYS_PINFUNC_S0B		(1 << 6)
-#define SYS_PINFUNC_S0C		(1 << 5)
-#define SYS_PINFUNC_P0B		(1 << 4)
-#define SYS_PINFUNC_U0T		(1 << 3)
-#define SYS_PINFUNC_S1B		(1 << 2)
-
-/* Power Management */
-#define SYS_SCRATCH0		0xB1900018
-#define SYS_SCRATCH1		0xB190001C
-#define SYS_WAKEMSK		0xB1900034
-#define SYS_ENDIAN		0xB1900038
-#define SYS_POWERCTRL		0xB190003C
-#define SYS_WAKESRC		0xB190005C
-#define SYS_SLPPWR		0xB1900078
-#define SYS_SLEEP		0xB190007C
-
-#define SYS_WAKEMSK_D2		(1 << 9)
-#define SYS_WAKEMSK_M2		(1 << 8)
-#define SYS_WAKEMSK_GPIO(x)	(1 << (x))
-
-/* Clock Controller */
-#define SYS_FREQCTRL0		0xB1900020
-#  define SYS_FC_FRDIV2_BIT	22
-#  define SYS_FC_FRDIV2_MASK	(0xff << SYS_FC_FRDIV2_BIT)
-#  define SYS_FC_FE2		(1 << 21)
-#  define SYS_FC_FS2		(1 << 20)
-#  define SYS_FC_FRDIV1_BIT	12
-#  define SYS_FC_FRDIV1_MASK	(0xff << SYS_FC_FRDIV1_BIT)
-#  define SYS_FC_FE1		(1 << 11)
-#  define SYS_FC_FS1		(1 << 10)
-#  define SYS_FC_FRDIV0_BIT	2
-#  define SYS_FC_FRDIV0_MASK	(0xff << SYS_FC_FRDIV0_BIT)
-#  define SYS_FC_FE0		(1 << 1)
-#  define SYS_FC_FS0		(1 << 0)
-#define SYS_FREQCTRL1		0xB1900024
-#  define SYS_FC_FRDIV5_BIT	22
-#  define SYS_FC_FRDIV5_MASK	(0xff << SYS_FC_FRDIV5_BIT)
-#  define SYS_FC_FE5		(1 << 21)
-#  define SYS_FC_FS5		(1 << 20)
-#  define SYS_FC_FRDIV4_BIT	12
-#  define SYS_FC_FRDIV4_MASK	(0xff << SYS_FC_FRDIV4_BIT)
-#  define SYS_FC_FE4		(1 << 11)
-#  define SYS_FC_FS4		(1 << 10)
-#  define SYS_FC_FRDIV3_BIT	2
-#  define SYS_FC_FRDIV3_MASK	(0xff << SYS_FC_FRDIV3_BIT)
-#  define SYS_FC_FE3		(1 << 1)
-#  define SYS_FC_FS3		(1 << 0)
-#define SYS_CLKSRC		0xB1900028
-#  define SYS_CS_ME1_BIT	27
-#  define SYS_CS_ME1_MASK	(0x7 << SYS_CS_ME1_BIT)
-#  define SYS_CS_DE1		(1 << 26)
-#  define SYS_CS_CE1		(1 << 25)
-#  define SYS_CS_ME0_BIT	22
-#  define SYS_CS_ME0_MASK	(0x7 << SYS_CS_ME0_BIT)
-#  define SYS_CS_DE0		(1 << 21)
-#  define SYS_CS_CE0		(1 << 20)
-#  define SYS_CS_MI2_BIT	17
-#  define SYS_CS_MI2_MASK	(0x7 << SYS_CS_MI2_BIT)
-#  define SYS_CS_DI2		(1 << 16)
-#  define SYS_CS_CI2		(1 << 15)
-
-#  define SYS_CS_ML_BIT		7
-#  define SYS_CS_ML_MASK	(0x7 << SYS_CS_ML_BIT)
-#  define SYS_CS_DL		(1 << 6)
-#  define SYS_CS_CL		(1 << 5)
-
-#  define SYS_CS_MUH_BIT	12
-#  define SYS_CS_MUH_MASK	(0x7 << SYS_CS_MUH_BIT)
-#  define SYS_CS_DUH		(1 << 11)
-#  define SYS_CS_CUH		(1 << 10)
-#  define SYS_CS_MUD_BIT	7
-#  define SYS_CS_MUD_MASK	(0x7 << SYS_CS_MUD_BIT)
-#  define SYS_CS_DUD		(1 << 6)
-#  define SYS_CS_CUD		(1 << 5)
-
-#  define SYS_CS_MIR_BIT	2
-#  define SYS_CS_MIR_MASK	(0x7 << SYS_CS_MIR_BIT)
-#  define SYS_CS_DIR		(1 << 1)
-#  define SYS_CS_CIR		(1 << 0)
-
-#  define SYS_CS_MUX_AUX	0x1
-#  define SYS_CS_MUX_FQ0	0x2
-#  define SYS_CS_MUX_FQ1	0x3
-#  define SYS_CS_MUX_FQ2	0x4
-#  define SYS_CS_MUX_FQ3	0x5
-#  define SYS_CS_MUX_FQ4	0x6
-#  define SYS_CS_MUX_FQ5	0x7
-#define SYS_CPUPLL		0xB1900060
-#define SYS_AUXPLL		0xB1900064
-
-/* AC97 Controller */
-#define AC97C_CONFIG		0xB0000000
-#  define AC97C_RECV_SLOTS_BIT	13
-#  define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
-#  define AC97C_XMIT_SLOTS_BIT	3
-#  define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
-#  define AC97C_SG		(1 << 2)
-#  define AC97C_SYNC		(1 << 1)
-#  define AC97C_RESET		(1 << 0)
-#define AC97C_STATUS		0xB0000004
-#  define AC97C_XU		(1 << 11)
-#  define AC97C_XO		(1 << 10)
-#  define AC97C_RU		(1 << 9)
-#  define AC97C_RO		(1 << 8)
-#  define AC97C_READY		(1 << 7)
-#  define AC97C_CP		(1 << 6)
-#  define AC97C_TR		(1 << 5)
-#  define AC97C_TE		(1 << 4)
-#  define AC97C_TF		(1 << 3)
-#  define AC97C_RR		(1 << 2)
-#  define AC97C_RE		(1 << 1)
-#  define AC97C_RF		(1 << 0)
-#define AC97C_DATA		0xB0000008
-#define AC97C_CMD		0xB000000C
-#  define AC97C_WD_BIT		16
-#  define AC97C_READ		(1 << 7)
-#  define AC97C_INDEX_MASK	0x7f
-#define AC97C_CNTRL		0xB0000010
-#  define AC97C_RS		(1 << 1)
-#  define AC97C_CE		(1 << 0)
-
-
-/* The PCI chip selects are outside the 32bit space, and since we can't
- * just program the 36bit addresses into BARs, we have to take a chunk
- * out of the 32bit space and reserve it for PCI.  When these addresses
- * are ioremap()ed, they'll be fixed up to the real 36bit address before
- * being passed to the real ioremap function.
- */
-#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
-#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
-
-/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
- * adjust the device's resources.
- */
-#define ALCHEMY_PCI_IOWIN_START		0x00001000
-#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
-
-#ifdef CONFIG_PCI
-
-#define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
-#define IOPORT_RESOURCE_END	0xffffffff
-#define IOMEM_RESOURCE_START	0x10000000
-#define IOMEM_RESOURCE_END	0xfffffffffULL
-
-#else
-
-/* Don't allow any legacy ports probing */
-#define IOPORT_RESOURCE_START	0x10000000
-#define IOPORT_RESOURCE_END	0xffffffff
-#define IOMEM_RESOURCE_START	0x10000000
-#define IOMEM_RESOURCE_END	0xfffffffffULL
-
-#endif
-
-/* PCI controller block register offsets */
-#define PCI_REG_CMEM		0x0000
-#define PCI_REG_CONFIG		0x0004
-#define PCI_REG_B2BMASK_CCH	0x0008
-#define PCI_REG_B2BBASE0_VID	0x000C
-#define PCI_REG_B2BBASE1_SID	0x0010
-#define PCI_REG_MWMASK_DEV	0x0014
-#define PCI_REG_MWBASE_REV_CCL	0x0018
-#define PCI_REG_ERR_ADDR	0x001C
-#define PCI_REG_SPEC_INTACK	0x0020
-#define PCI_REG_ID		0x0100
-#define PCI_REG_STATCMD		0x0104
-#define PCI_REG_CLASSREV	0x0108
-#define PCI_REG_PARAM		0x010C
-#define PCI_REG_MBAR		0x0110
-#define PCI_REG_TIMEOUT		0x0140
-
-/* PCI controller block register bits */
-#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
-#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
-#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
-#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
-#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
-#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
-#define PCI_CONFIG_EP		(1 << 24) /* parity error */
-#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
-#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
-#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
-#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
-#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
-#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
-#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
-#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
-#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
-#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
-#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
-#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
-#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
-#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
-#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
-#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
-#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
-#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
-#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
-#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
-#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
-#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
-#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
-#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
-#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
-#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
-#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
-#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
-#define PCI_MWBASEREVCCL_REV(x)	 (((x) & 0xff) << 8)
-#define PCI_MWBASEREVCCL_CCL(x)	 ((x) & 0xff)
-#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
-#define PCI_ID_VID(x)		((x) & 0xffff)
-#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
-#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
-#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
-#define PCI_CLASSREV_REV(x)	((x) & 0xff)
-#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
-#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
-#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
-#define PCI_PARAM_CLS(x)	((x) & 0xff)
-#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
-#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,20 +25,20 @@
 #define MAKE_IRQ(intc, off)	(AU1000_INTC##intc##_INT_BASE + (off))
 
 /* GPIO1 registers within SYS_ area */
-#define SYS_TRIOUTRD		0x100
-#define SYS_TRIOUTCLR		0x100
-#define SYS_OUTPUTRD		0x108
-#define SYS_OUTPUTSET		0x108
-#define SYS_OUTPUTCLR		0x10C
-#define SYS_PINSTATERD		0x110
-#define SYS_PININPUTEN		0x110
+#define AU1000_SYS_TRIOUTRD	0x100
+#define AU1000_SYS_TRIOUTCLR	0x100
+#define AU1000_SYS_OUTPUTRD	0x108
+#define AU1000_SYS_OUTPUTSET	0x108
+#define AU1000_SYS_OUTPUTCLR	0x10C
+#define AU1000_SYS_PINSTATERD	0x110
+#define AU1000_SYS_PININPUTEN	0x110
 
 /* register offsets within GPIO2 block */
-#define GPIO2_DIR		0x00
-#define GPIO2_OUTPUT		0x08
-#define GPIO2_PINSTATE		0x0C
-#define GPIO2_INTENABLE		0x10
-#define GPIO2_ENABLE		0x14
+#define AU1000_GPIO2_DIR	0x00
+#define AU1000_GPIO2_OUTPUT	0x08
+#define AU1000_GPIO2_PINSTATE	0x0C
+#define AU1000_GPIO2_INTENABLE	0x10
+#define AU1000_GPIO2_ENABLE	0x14
 
 struct gpio;
 
@@ -217,26 +217,21 @@ static inline int au1200_irq_to_gpio(int
  */
 static inline void alchemy_gpio1_set_value(int gpio, int v)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
-	__raw_writel(mask, base + r);
-	wmb();
+	unsigned long r = v ? AU1000_SYS_OUTPUTSET : AU1000_SYS_OUTPUTCLR;
+	alchemy_wrsys(mask, r);
 }
 
 static inline int alchemy_gpio1_get_value(int gpio)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	return __raw_readl(base + SYS_PINSTATERD) & mask;
+	return alchemy_rdsys(AU1000_SYS_PINSTATERD) & mask;
 }
 
 static inline int alchemy_gpio1_direction_input(int gpio)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	__raw_writel(mask, base + SYS_TRIOUTCLR);
-	wmb();
+	alchemy_wrsys(mask, AU1000_SYS_TRIOUTCLR);
 	return 0;
 }
 
@@ -279,13 +274,13 @@ static inline void __alchemy_gpio2_mod_d
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
-	unsigned long d = __raw_readl(base + GPIO2_DIR);
+	unsigned long d = __raw_readl(base + AU1000_GPIO2_DIR);
 
 	if (to_out)
 		d |= mask;
 	else
 		d &= ~mask;
-	__raw_writel(d, base + GPIO2_DIR);
+	__raw_writel(d, base + AU1000_GPIO2_DIR);
 	wmb();
 }
 
@@ -294,14 +289,15 @@ static inline void alchemy_gpio2_set_val
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
 	unsigned long mask;
 	mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
-	__raw_writel(mask, base + GPIO2_OUTPUT);
+	__raw_writel(mask, base + AU1000_GPIO2_OUTPUT);
 	wmb();
 }
 
 static inline int alchemy_gpio2_get_value(int gpio)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	return __raw_readl(base + GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+	return __raw_readl(base + AU1000_GPIO2_PINSTATE) &
+				(1 << (gpio - ALCHEMY_GPIO2_BASE));
 }
 
 static inline int alchemy_gpio2_direction_input(int gpio)
@@ -352,12 +348,12 @@ static inline int alchemy_gpio2_to_irq(i
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	unsigned long r = __raw_readl(base + GPIO2_INTENABLE);
+	unsigned long r = __raw_readl(base + AU1000_GPIO2_INTENABLE);
 	if (en)
 		r |= 1 << gpio2;
 	else
 		r &= ~(1 << gpio2);
-	__raw_writel(r, base + GPIO2_INTENABLE);
+	__raw_writel(r, base + AU1000_GPIO2_INTENABLE);
 	wmb();
 }
 
@@ -434,9 +430,9 @@ static inline void alchemy_gpio2_disable
 static inline void alchemy_gpio2_enable(void)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	__raw_writel(3, base + GPIO2_ENABLE);	/* reset, clock enabled */
+	__raw_writel(3, base + AU1000_GPIO2_ENABLE);	/* reset, clock enabled */
 	wmb();
-	__raw_writel(1, base + GPIO2_ENABLE);	/* clock enabled */
+	__raw_writel(1, base + AU1000_GPIO2_ENABLE);	/* clock enabled */
 	wmb();
 }
 
@@ -448,7 +444,7 @@ static inline void alchemy_gpio2_enable(
 static inline void alchemy_gpio2_disable(void)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	__raw_writel(2, base + GPIO2_ENABLE);	/* reset, clock disabled */
+	__raw_writel(2, base + AU1000_GPIO2_ENABLE);	/* reset, clock disabled */
 	wmb();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@ enum bcm47xx_board {
 	BCM47XX_BOARD_ASUS_WL300G,
 	BCM47XX_BOARD_ASUS_WL320GE,
 	BCM47XX_BOARD_ASUS_WL330GE,
+	BCM47XX_BOARD_ASUS_WL500G,
 	BCM47XX_BOARD_ASUS_WL500GD,
 	BCM47XX_BOARD_ASUS_WL500GPV1,
 	BCM47XX_BOARD_ASUS_WL500GPV2,
@@ -70,11 +71,15 @@ enum bcm47xx_board {
 	BCM47XX_BOARD_LINKSYS_WRT310NV1,
 	BCM47XX_BOARD_LINKSYS_WRT310NV2,
 	BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
-	BCM47XX_BOARD_LINKSYS_WRT54G,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
 	BCM47XX_BOARD_LINKSYS_WRT610NV1,
 	BCM47XX_BOARD_LINKSYS_WRT610NV2,
 	BCM47XX_BOARD_LINKSYS_WRTSL54GS,
 
+	BCM47XX_BOARD_MICROSOFT_MN700,
+
 	BCM47XX_BOARD_MOTOROLA_WE800G,
 	BCM47XX_BOARD_MOTOROLA_WR850GP,
 	BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,118 +19,68 @@
 #define BCM6368_CPU_ID		0x6368
 
 void __init bcm63xx_cpu_init(void);
-u16 __bcm63xx_get_cpu_id(void);
 u8 bcm63xx_get_cpu_rev(void);
 unsigned int bcm63xx_get_cpu_freq(void);
 
+static inline u16 __pure __bcm63xx_get_cpu_id(const u16 cpu_id)
+{
+	switch (cpu_id) {
 #ifdef CONFIG_BCM63XX_CPU_3368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM3368_CPU_ID
-# endif
-# define BCMCPU_IS_3368()	(bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
-#else
-# define BCMCPU_IS_3368()	(0)
+		case BCM3368_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6328
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6328_CPU_ID
-# endif
-# define BCMCPU_IS_6328()	(bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
-#else
-# define BCMCPU_IS_6328()	(0)
+		case BCM6328_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6338
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6338_CPU_ID
-# endif
-# define BCMCPU_IS_6338()	(bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
-#else
-# define BCMCPU_IS_6338()	(0)
+		case BCM6338_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6345
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6345_CPU_ID
-# endif
-# define BCMCPU_IS_6345()	(bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
-#else
-# define BCMCPU_IS_6345()	(0)
+		case BCM6345_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6348
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6348_CPU_ID
-# endif
-# define BCMCPU_IS_6348()	(bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
-#else
-# define BCMCPU_IS_6348()	(0)
+		case BCM6348_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6358
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6358_CPU_ID
-# endif
-# define BCMCPU_IS_6358()	(bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
-#else
-# define BCMCPU_IS_6358()	(0)
+		case BCM6358_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6362
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6362_CPU_ID
-# endif
-# define BCMCPU_IS_6362()	(bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
-#else
-# define BCMCPU_IS_6362()	(0)
+		case BCM6362_CPU_ID:
 #endif
 
-
 #ifdef CONFIG_BCM63XX_CPU_6368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6368_CPU_ID
-# endif
-# define BCMCPU_IS_6368()	(bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
-#else
-# define BCMCPU_IS_6368()	(0)
+		case BCM6368_CPU_ID:
 #endif
+		break;
+	default:
+		unreachable();
+	}
 
-#ifndef bcm63xx_get_cpu_id
-#error "No CPU support configured"
-#endif
+	return cpu_id;
+}
+
+extern u16 bcm63xx_cpu_id;
+
+static inline u16 __pure bcm63xx_get_cpu_id(void)
+{
+	const u16 cpu_id = bcm63xx_cpu_id;
+
+	return __bcm63xx_get_cpu_id(cpu_id);
+}
+
+#define BCMCPU_IS_3368()	(bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#define BCMCPU_IS_6328()	(bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
+#define BCMCPU_IS_6338()	(bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
+#define BCMCPU_IS_6345()	(bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
+#define BCMCPU_IS_6348()	(bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
+#define BCMCPU_IS_6358()	(bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
+#define BCMCPU_IS_6362()	(bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
+#define BCMCPU_IS_6368()	(bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
 
 /*
  * While registers sets are (mostly) the same across 63xx CPU, base
@@ -598,55 +548,6 @@ enum bcm63xx_regs_set {
 
 extern const unsigned long *bcm63xx_regs_base;
 
-#define __GEN_RSET_BASE(__cpu, __rset)					\
-	case RSET_## __rset :						\
-		return BCM_## __cpu ##_## __rset ##_BASE;
-
-#define __GEN_RSET(__cpu)						\
-	switch (set) {							\
-	__GEN_RSET_BASE(__cpu, DSL_LMEM)				\
-	__GEN_RSET_BASE(__cpu, PERF)					\
-	__GEN_RSET_BASE(__cpu, TIMER)					\
-	__GEN_RSET_BASE(__cpu, WDT)					\
-	__GEN_RSET_BASE(__cpu, UART0)					\
-	__GEN_RSET_BASE(__cpu, UART1)					\
-	__GEN_RSET_BASE(__cpu, GPIO)					\
-	__GEN_RSET_BASE(__cpu, SPI)					\
-	__GEN_RSET_BASE(__cpu, HSSPI)					\
-	__GEN_RSET_BASE(__cpu, UDC0)					\
-	__GEN_RSET_BASE(__cpu, OHCI0)					\
-	__GEN_RSET_BASE(__cpu, OHCI_PRIV)				\
-	__GEN_RSET_BASE(__cpu, USBH_PRIV)				\
-	__GEN_RSET_BASE(__cpu, USBD)					\
-	__GEN_RSET_BASE(__cpu, USBDMA)					\
-	__GEN_RSET_BASE(__cpu, MPI)					\
-	__GEN_RSET_BASE(__cpu, PCMCIA)					\
-	__GEN_RSET_BASE(__cpu, PCIE)					\
-	__GEN_RSET_BASE(__cpu, DSL)					\
-	__GEN_RSET_BASE(__cpu, ENET0)					\
-	__GEN_RSET_BASE(__cpu, ENET1)					\
-	__GEN_RSET_BASE(__cpu, ENETDMA)					\
-	__GEN_RSET_BASE(__cpu, ENETDMAC)				\
-	__GEN_RSET_BASE(__cpu, ENETDMAS)				\
-	__GEN_RSET_BASE(__cpu, ENETSW)					\
-	__GEN_RSET_BASE(__cpu, EHCI0)					\
-	__GEN_RSET_BASE(__cpu, SDRAM)					\
-	__GEN_RSET_BASE(__cpu, MEMC)					\
-	__GEN_RSET_BASE(__cpu, DDR)					\
-	__GEN_RSET_BASE(__cpu, M2M)					\
-	__GEN_RSET_BASE(__cpu, ATM)					\
-	__GEN_RSET_BASE(__cpu, XTM)					\
-	__GEN_RSET_BASE(__cpu, XTMDMA)					\
-	__GEN_RSET_BASE(__cpu, XTMDMAC)					\
-	__GEN_RSET_BASE(__cpu, XTMDMAS)					\
-	__GEN_RSET_BASE(__cpu, PCM)					\
-	__GEN_RSET_BASE(__cpu, PCMDMA)					\
-	__GEN_RSET_BASE(__cpu, PCMDMAC)					\
-	__GEN_RSET_BASE(__cpu, PCMDMAS)					\
-	__GEN_RSET_BASE(__cpu, RNG)					\
-	__GEN_RSET_BASE(__cpu, MISC)					\
-	}
-
 #define __GEN_CPU_REGS_TABLE(__cpu)					\
 	[RSET_DSL_LMEM]		= BCM_## __cpu ##_DSL_LMEM_BASE,	\
 	[RSET_PERF]		= BCM_## __cpu ##_PERF_BASE,		\
@@ -693,36 +594,7 @@ extern const unsigned long *bcm63xx_regs
 
 static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	return bcm63xx_regs_base[set];
-#else
-#ifdef CONFIG_BCM63XX_CPU_3368
-	__GEN_RSET(3368)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-	__GEN_RSET(6328)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-	__GEN_RSET(6338)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-	__GEN_RSET(6345)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-	__GEN_RSET(6348)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-	__GEN_RSET(6358)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-	__GEN_RSET(6362)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-	__GEN_RSET(6368)
-#endif
-#endif
-	/* unreached */
-	return 0;
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h	2014-09-28 17:29:07.000000000 -0400
@@ -112,55 +112,9 @@ enum bcm63xx_regs_enetdmac {
 
 static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	extern const unsigned long *bcm63xx_regs_enetdmac;
 
 	return bcm63xx_regs_enetdmac[reg];
-#else
-#ifdef CONFIG_BCM63XX_CPU_6345
-	switch (reg) {
-	case ENETDMAC_CHANCFG:
-		return ENETDMA_6345_CHANCFG_REG;
-	case ENETDMAC_IR:
-		return ENETDMA_6345_IR_REG;
-	case ENETDMAC_IRMASK:
-		return ENETDMA_6345_IRMASK_REG;
-	case ENETDMAC_MAXBURST:
-		return ENETDMA_6345_MAXBURST_REG;
-	case ENETDMAC_BUFALLOC:
-		return ENETDMA_6345_BUFALLOC_REG;
-	case ENETDMAC_RSTART:
-		return ENETDMA_6345_RSTART_REG;
-	case ENETDMAC_FC:
-		return ENETDMA_6345_FC_REG;
-	case ENETDMAC_LEN:
-		return ENETDMA_6345_LEN_REG;
-	}
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6328) || \
-	defined(CONFIG_BCM63XX_CPU_6338) || \
-	defined(CONFIG_BCM63XX_CPU_6348) || \
-	defined(CONFIG_BCM63XX_CPU_6358) || \
-	defined(CONFIG_BCM63XX_CPU_6362) || \
-	defined(CONFIG_BCM63XX_CPU_6368)
-	switch (reg) {
-	case ENETDMAC_CHANCFG:
-		return ENETDMAC_CHANCFG_REG;
-	case ENETDMAC_IR:
-		return ENETDMAC_IR_REG;
-	case ENETDMAC_IRMASK:
-		return ENETDMAC_IRMASK_REG;
-	case ENETDMAC_MAXBURST:
-		return ENETDMAC_MAXBURST_REG;
-	case ENETDMAC_BUFALLOC:
-	case ENETDMAC_RSTART:
-	case ENETDMAC_FC:
-	case ENETDMAC_LEN:
-		return 0;
-	}
-#endif
-#endif
-	return 0;
 }
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,26 +30,6 @@ enum bcm63xx_regs_spi {
 	SPI_RX_DATA,
 };
 
-#define __GEN_SPI_RSET_BASE(__cpu, __rset)				\
-	case SPI_## __rset:						\
-		return SPI_## __cpu ##_## __rset;
-
-#define __GEN_SPI_RSET(__cpu)						\
-	switch (reg) {							\
-	__GEN_SPI_RSET_BASE(__cpu, CMD)					\
-	__GEN_SPI_RSET_BASE(__cpu, INT_STATUS)				\
-	__GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST)				\
-	__GEN_SPI_RSET_BASE(__cpu, INT_MASK)				\
-	__GEN_SPI_RSET_BASE(__cpu, ST)					\
-	__GEN_SPI_RSET_BASE(__cpu, CLK_CFG)				\
-	__GEN_SPI_RSET_BASE(__cpu, FILL_BYTE)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_TAIL)				\
-	__GEN_SPI_RSET_BASE(__cpu, RX_TAIL)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_CTL)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_DATA)				\
-	__GEN_SPI_RSET_BASE(__cpu, RX_DATA)				\
-	}
-
 #define __GEN_SPI_REGS_TABLE(__cpu)					\
 	[SPI_CMD]		= SPI_## __cpu ##_CMD,			\
 	[SPI_INT_STATUS]	= SPI_## __cpu ##_INT_STATUS,		\
@@ -66,20 +46,9 @@ enum bcm63xx_regs_spi {
 
 static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	extern const unsigned long *bcm63xx_regs_spi;
 
 	return bcm63xx_regs_spi[reg];
-#else
-#if defined(CONFIG_BCM63XX_CPU_6338) || defined(CONFIG_BCM63XX_CPU_6348)
-	__GEN_SPI_RSET(6348)
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6358) || defined(CONFIG_BCM63XX_CPU_6362) || \
-	defined(CONFIG_BCM63XX_CPU_6368)
-	__GEN_SPI_RSET(6358)
-#endif
-#endif
-	return 0;
 }
 
 #endif /* BCM63XX_DEV_SPI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -215,23 +215,23 @@
 
 /* Interrupt Mask register */
 #define PERF_IRQMASK_3368_REG		0xc
-#define PERF_IRQMASK_6328_REG		0x20
+#define PERF_IRQMASK_6328_REG(x)	(0x20 + (x) * 0x10)
 #define PERF_IRQMASK_6338_REG		0xc
 #define PERF_IRQMASK_6345_REG		0xc
 #define PERF_IRQMASK_6348_REG		0xc
-#define PERF_IRQMASK_6358_REG		0xc
-#define PERF_IRQMASK_6362_REG		0x20
-#define PERF_IRQMASK_6368_REG		0x20
+#define PERF_IRQMASK_6358_REG(x)	(0xc + (x) * 0x2c)
+#define PERF_IRQMASK_6362_REG(x)	(0x20 + (x) * 0x10)
+#define PERF_IRQMASK_6368_REG(x)	(0x20 + (x) * 0x10)
 
 /* Interrupt Status register */
 #define PERF_IRQSTAT_3368_REG		0x10
-#define PERF_IRQSTAT_6328_REG		0x28
+#define PERF_IRQSTAT_6328_REG(x)	(0x28 + (x) * 0x10)
 #define PERF_IRQSTAT_6338_REG		0x10
 #define PERF_IRQSTAT_6345_REG		0x10
 #define PERF_IRQSTAT_6348_REG		0x10
-#define PERF_IRQSTAT_6358_REG		0x10
-#define PERF_IRQSTAT_6362_REG		0x28
-#define PERF_IRQSTAT_6368_REG		0x28
+#define PERF_IRQSTAT_6358_REG(x)	(0x10 + (x) * 0x2c)
+#define PERF_IRQSTAT_6362_REG(x)	(0x28 + (x) * 0x10)
+#define PERF_IRQSTAT_6368_REG(x)	(0x28 + (x) * 0x10)
 
 /* External Interrupt Configuration register */
 #define PERF_EXTIRQ_CFG_REG_3368	0x14
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,7 @@
 #define cpu_has_smartmips		0
 #define cpu_has_vtag_icache		0
 
-#if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCM63XX_CPU_6348) || defined(CONFIG_BCM63XX_CPU_6345) || defined(CONFIG_BCM63XX_CPU_6338))
+#if !defined(CONFIG_SYS_HAS_CPU_BMIPS4350)
 #define cpu_has_dc_aliases		0
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-ip28/spaces.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-ip28/spaces.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-ip28/spaces.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-ip28/spaces.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,15 +11,8 @@
 #ifndef _ASM_MACH_IP28_SPACES_H
 #define _ASM_MACH_IP28_SPACES_H
 
-#define CAC_BASE	_AC(0xa800000000000000, UL)
-
-#define HIGHMEM_START	(~0UL)
-
 #define PHYS_OFFSET	_AC(0x20000000, UL)
 
-#define UNCAC_BASE	_AC(0xc0000000, UL)     /* 0xa0000000 + PHYS_OFFSET */
-#define IO_BASE		UNCAC_BASE
-
 #include <asm/mach-generic/spaces.h>
 
 #endif /* _ASM_MACH_IP28_SPACES_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/boot_param.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/boot_param.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/boot_param.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/boot_param.h	2014-09-28 17:29:07.000000000 -0400
@@ -146,6 +146,9 @@ struct boot_params {
 
 struct loongson_system_configuration {
 	u32 nr_cpus;
+	u32 nr_nodes;
+	int cores_per_node;
+	int cores_per_package;
 	enum loongson_cpu_type cputype;
 	u64 ht_control_base;
 	u64 pci_mem_start_addr;
@@ -160,4 +163,5 @@ struct loongson_system_configuration {
 
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
+extern int cpuhotplug_workaround;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/kernel-entry-init.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/kernel-entry-init.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/kernel-entry-init.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
+ */
+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+
+/*
+ * Override macros used in arch/mips/kernel/head.S.
+ */
+	.macro	kernel_entry_setup
+#ifdef CONFIG_CPU_LOONGSON3
+	.set	push
+	.set	mips64
+	/* Set LPA on LOONGSON3 config3 */
+	mfc0	t0, $16, 3
+	or	t0, (0x1 << 7)
+	mtc0	t0, $16, 3
+	/* Set ELPA on LOONGSON3 pagegrain */
+	li	t0, (0x1 << 29)
+	mtc0	t0, $5, 1
+	_ehb
+	.set	pop
+#endif
+	.endm
+
+/*
+ * Do SMP slave processor setup.
+ */
+	.macro	smp_slave_setup
+#ifdef CONFIG_CPU_LOONGSON3
+	.set	push
+	.set	mips64
+	/* Set LPA on LOONGSON3 config3 */
+	mfc0	t0, $16, 3
+	or	t0, (0x1 << 7)
+	mtc0	t0, $16, 3
+	/* Set ELPA on LOONGSON3 pagegrain */
+	li	t0, (0x1 << 29)
+	mtc0	t0, $5, 1
+	_ehb
+	.set	pop
+#endif
+	.endm
+
+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/loongson.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/loongson.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/loongson.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/loongson.h	2014-09-28 17:29:07.000000000 -0400
@@ -249,8 +249,15 @@ static inline void do_perfcnt_IRQ(void)
 #define LOONGSON_PXARB_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x68)
 #define LOONGSON_PXARB_STATUS		LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
 
-/* Chip Config */
-#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#define MAX_PACKAGES 4
+
+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
+extern u64 loongson_chipcfg[MAX_PACKAGES];
+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
+
+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
+extern u64 loongson_freqctrl[MAX_PACKAGES];
+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
 
 /* pcimap */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/machine.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/machine.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/machine.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/machine.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,10 +24,10 @@
 
 #endif
 
-#ifdef CONFIG_LEMOTE_MACH3A
+#ifdef CONFIG_LOONGSON_MACH3X
 
 #define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
 
-#endif /* CONFIG_LEMOTE_MACH3A */
+#endif /* CONFIG_LOONGSON_MACH3X */
 
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/mmzone.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/mmzone.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/mmzone.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/mmzone.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_MACH_MMZONE_H
+#define _ASM_MACH_MMZONE_H
+
+#include <boot_param.h>
+#define NODE_ADDRSPACE_SHIFT 44
+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
+
+#define pa_to_nid(addr)  (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
+
+#define LEVELS_PER_SLICE 128
+
+struct slice_data {
+	unsigned long irq_enable_mask[2];
+	int level_to_irq[LEVELS_PER_SLICE];
+};
+
+struct hub_data {
+	cpumask_t	h_cpus;
+	unsigned long slice_map;
+	unsigned long irq_alloc_mask[2];
+	struct slice_data slice[2];
+};
+
+struct node_data {
+	struct pglist_data pglist;
+	struct hub_data hub;
+	cpumask_t cpumask;
+};
+
+extern struct node_data *__node_data[];
+
+#define NODE_DATA(n)		(&__node_data[(n)]->pglist)
+#define hub_data(n)		(&__node_data[(n)]->hub)
+
+extern void setup_zero_pages(void);
+extern void __init prom_init_numa_memory(void);
+
+#endif /* _ASM_MACH_MMZONE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/topology.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/topology.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-loongson/topology.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-loongson/topology.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+#ifndef _ASM_MACH_TOPOLOGY_H
+#define _ASM_MACH_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#define cpu_to_node(cpu)	((cpu) >> 2)
+#define parent_node(node)	(node)
+#define cpumask_of_node(node)	(&__node_data[(node)]->cpumask)
+
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *);
+
+#define cpumask_of_pcibus(bus)	(cpu_online_mask)
+
+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+
+#define node_distance(from, to)	(__node_distances[(from)][(to)])
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_MACH_TOPOLOGY_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-malta/irq.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-malta/irq.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-malta/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-malta/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,7 @@
 #define __ASM_MACH_MIPS_IRQ_H
 
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 #include_next <irq.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,14 +10,15 @@
 #ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
 #define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
 
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
 	/*
 	 * Prepare segments for EVA boot:
 	 *
 	 * This is in case the processor boots in legacy configuration
 	 * (SI_EVAReset is de-asserted and CONFIG5.K == 0)
 	 *
-	 * On entry, t1 is loaded with CP0_CONFIG
-	 *
 	 * ========================= Mappings =============================
 	 * Virtual memory           Physical memory           Mapping
 	 * 0x00000000 - 0x7fffffff  0x80000000 - 0xfffffffff   MUSUK (kuseg)
@@ -30,12 +31,20 @@
 	 *
 	 *
 	 * Lowmem is expanded to 2GB
+	 *
+	 * The following code uses the t0, t1, t2 and ra registers without
+	 * previously preserving them.
+	 *
 	 */
-	.macro	eva_entry
+	.macro	platform_eva_init
+
+	.set	push
+	.set	reorder
 	/*
 	 * Get Config.K0 value and use it to program
 	 * the segmentation registers
 	 */
+	mfc0    t1, CP0_CONFIG
 	andi	t1, 0x7 /* CCA */
 	move	t2, t1
 	ins	t2, t1, 16, 3
@@ -77,6 +86,8 @@
 	mtc0    t0, $16, 5
 	sync
 	jal	mips_ihb
+
+	.set	pop
 	.endm
 
 	.macro	kernel_entry_setup
@@ -95,7 +106,7 @@
 	sll     t0, t0, 6   /* SC bit */
 	bgez    t0, 9f
 
-	eva_entry
+	platform_eva_init
 	b       0f
 9:
 	/* Assume we came from YAMON... */
@@ -127,8 +138,7 @@ nonsc_processor:
 #ifdef CONFIG_EVA
 	sync
 	ehb
-	mfc0    t1, CP0_CONFIG
-	eva_entry
+	platform_eva_init
 #endif
 	.endm
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-netlogic/topology.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-netlogic/topology.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-netlogic/topology.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-netlogic/topology.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,13 +10,6 @@
 
 #include <asm/mach-netlogic/multi-node.h>
 
-#ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu)	cpu_to_node(cpu)
-#define topology_core_id(cpu)	(cpu_logical_map(cpu) / NLM_THREADS_PER_CORE)
-#define topology_thread_cpumask(cpu)		(&cpu_sibling_map[cpu])
-#define topology_core_cpumask(cpu)	cpumask_of_node(cpu_to_node(cpu))
-#endif
-
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_MACH_NETLOGIC_TOPOLOGY_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mach-sead3/irq.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-sead3/irq.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mach-sead3/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mach-sead3/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mips-boards/bonito64.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mips-boards/bonito64.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mips-boards/bonito64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mips-boards/bonito64.h	2014-09-28 17:29:07.000000000 -0400
@@ -414,7 +414,6 @@ extern unsigned long _pcictrl_bonito_pci
 
 
 #define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)	 ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
-#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)	 ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 #define BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 
 #define BONITO_PCITOPHYS(WIN, ADDR, CFG)	  ( \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mipsregs.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mipsregs.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mipsregs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mipsregs.h	2014-09-28 17:29:07.000000000 -0400
@@ -265,6 +265,7 @@
 #define PG_XIE		(_ULCAST_(1) <<	 30)
 #define PG_ELPA		(_ULCAST_(1) <<	 29)
 #define PG_ESP		(_ULCAST_(1) <<	 28)
+#define PG_IEC		(_ULCAST_(1) <<  27)
 
 /*
  * R4x00 interrupt enable / cause bits
@@ -630,7 +631,6 @@
 #define MIPS_CONF4_MMUSIZEEXT_SHIFT	(0)
 #define MIPS_CONF4_MMUSIZEEXT	(_ULCAST_(255) << 0)
 #define MIPS_CONF4_FTLBSETS_SHIFT	(0)
-#define MIPS_CONF4_FTLBSETS_SHIFT	(0)
 #define MIPS_CONF4_FTLBSETS	(_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT)
 #define MIPS_CONF4_FTLBWAYS_SHIFT	(4)
 #define MIPS_CONF4_FTLBWAYS	(_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT)
@@ -652,6 +652,7 @@
 
 #define MIPS_CONF5_NF		(_ULCAST_(1) << 0)
 #define MIPS_CONF5_UFR		(_ULCAST_(1) << 2)
+#define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA		(_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV		(_ULCAST_(1) << 29)
@@ -668,6 +669,12 @@
 #define MIPS_CONF7_IAR		(_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR		(_ULCAST_(1) << 16)
 
+/* MAAR bit definitions */
+#define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
+#define MIPS_MAAR_ADDR_SHIFT	12
+#define MIPS_MAAR_S		(_ULCAST_(1) << 1)
+#define MIPS_MAAR_V		(_ULCAST_(1) << 0)
+
 /*  EntryHI bit definition */
 #define MIPS_ENTRYHI_EHINV	(_ULCAST_(1) << 10)
 
@@ -706,6 +713,37 @@
 #define MIPS_SEGCFG_MK		_ULCAST_(1)
 #define MIPS_SEGCFG_UK		_ULCAST_(0)
 
+#define MIPS_PWFIELD_GDI_SHIFT	24
+#define MIPS_PWFIELD_GDI_MASK	0x3f000000
+#define MIPS_PWFIELD_UDI_SHIFT	18
+#define MIPS_PWFIELD_UDI_MASK	0x00fc0000
+#define MIPS_PWFIELD_MDI_SHIFT	12
+#define MIPS_PWFIELD_MDI_MASK	0x0003f000
+#define MIPS_PWFIELD_PTI_SHIFT	6
+#define MIPS_PWFIELD_PTI_MASK	0x00000fc0
+#define MIPS_PWFIELD_PTEI_SHIFT	0
+#define MIPS_PWFIELD_PTEI_MASK	0x0000003f
+
+#define MIPS_PWSIZE_GDW_SHIFT	24
+#define MIPS_PWSIZE_GDW_MASK	0x3f000000
+#define MIPS_PWSIZE_UDW_SHIFT	18
+#define MIPS_PWSIZE_UDW_MASK	0x00fc0000
+#define MIPS_PWSIZE_MDW_SHIFT	12
+#define MIPS_PWSIZE_MDW_MASK	0x0003f000
+#define MIPS_PWSIZE_PTW_SHIFT	6
+#define MIPS_PWSIZE_PTW_MASK	0x00000fc0
+#define MIPS_PWSIZE_PTEW_SHIFT	0
+#define MIPS_PWSIZE_PTEW_MASK	0x0000003f
+
+#define MIPS_PWCTL_PWEN_SHIFT	31
+#define MIPS_PWCTL_PWEN_MASK	0x80000000
+#define MIPS_PWCTL_DPH_SHIFT	7
+#define MIPS_PWCTL_DPH_MASK	0x00000080
+#define MIPS_PWCTL_HUGEPG_SHIFT	6
+#define MIPS_PWCTL_HUGEPG_MASK	0x00000060
+#define MIPS_PWCTL_PSN_SHIFT	0
+#define MIPS_PWCTL_PSN_MASK	0x0000003f
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -1044,6 +1082,11 @@ do {									\
 #define write_c0_config6(val)	__write_32bit_c0_register($16, 6, val)
 #define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
+#define read_c0_maar()		__read_ulong_c0_register($17, 1)
+#define write_c0_maar(val)	__write_ulong_c0_register($17, 1, val)
+#define read_c0_maari()		__read_32bit_c0_register($17, 2)
+#define write_c0_maari(val)	__write_32bit_c0_register($17, 2, val)
+
 /*
  * The WatchLo register.  There may be up to 8 of them.
  */
@@ -1201,6 +1244,19 @@ do {									\
 #define read_c0_segctl2()	__read_32bit_c0_register($5, 4)
 #define write_c0_segctl2(val)	__write_32bit_c0_register($5, 4, val)
 
+/* Hardware Page Table Walker */
+#define read_c0_pwbase()	__read_ulong_c0_register($5, 5)
+#define write_c0_pwbase(val)	__write_ulong_c0_register($5, 5, val)
+
+#define read_c0_pwfield()	__read_ulong_c0_register($5, 6)
+#define write_c0_pwfield(val)	__write_ulong_c0_register($5, 6, val)
+
+#define read_c0_pwsize()	__read_ulong_c0_register($5, 7)
+#define write_c0_pwsize(val)	__write_ulong_c0_register($5, 7, val)
+
+#define read_c0_pwctl()		__read_32bit_c0_register($6, 6)
+#define write_c0_pwctl(val)	__write_32bit_c0_register($6, 6, val)
+
 /* Cavium OCTEON (cnMIPS) */
 #define read_c0_cvmcount()	__read_ulong_c0_register($9, 6)
 #define write_c0_cvmcount(val)	__write_ulong_c0_register($9, 6, val)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/mmu_context.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mmu_context.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/mmu_context.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/mmu_context.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,10 +20,20 @@
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
 
+#define htw_set_pwbase(pgd)						\
+do {									\
+	if (cpu_has_htw) {						\
+		write_c0_pwbase(pgd);					\
+		back_to_back_c0_hazard();				\
+		htw_reset();						\
+	}								\
+} while (0)
+
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
 do {									\
 	extern void tlbmiss_handler_setup_pgd(unsigned long);		\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd));		\
+	htw_set_pwbase((unsigned long)pgd);				\
 } while (0)
 
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/msa.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/msa.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/msa.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/msa.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,8 +12,11 @@
 
 #include <asm/mipsregs.h>
 
+#ifndef __ASSEMBLY__
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
 
 static inline void enable_msa(void)
 {
@@ -112,10 +115,10 @@ static inline unsigned int read_msa_##na
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
 	"	.insn\n"					\
-	"	.word	#CFC_MSA_INSN | (" #cs " << 11)\n"	\
+	"	.word	%1 | (" #cs " << 11)\n"			\
 	"	move	%0, $1\n"				\
 	"	.set	pop\n"					\
-	: "=r"(reg));						\
+	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
 	return reg;						\
 }								\
 								\
@@ -126,22 +129,13 @@ static inline void write_msa_##name(unsi
 	"	.set	noat\n"					\
 	"	move	$1, %0\n"				\
 	"	.insn\n"					\
-	"	.word	#CTC_MSA_INSN | (" #cs " << 6)\n"	\
+	"	.word	%1 | (" #cs " << 6)\n"			\
 	"	.set	pop\n"					\
-	: : "r"(val));						\
+	: : "r"(val), "i"(CTC_MSA_INSN));			\
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
 
-#define MSA_IR		0
-#define MSA_CSR		1
-#define MSA_ACCESS	2
-#define MSA_SAVE	3
-#define MSA_MODIFY	4
-#define MSA_REQUEST	5
-#define MSA_MAP		6
-#define MSA_UNMAP	7
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +145,17 @@ __BUILD_MSA_CTL_REG(request, 5)
 __BUILD_MSA_CTL_REG(map, 6)
 __BUILD_MSA_CTL_REG(unmap, 7)
 
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR		0
+#define MSA_CSR		1
+#define MSA_ACCESS	2
+#define MSA_SAVE	3
+#define MSA_MODIFY	4
+#define MSA_REQUEST	5
+#define MSA_MAP		6
+#define MSA_UNMAP	7
+
 /* MSA Implementation Register (MSAIR) */
 #define MSA_IR_REVB		0
 #define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2014-09-28 17:29:07.000000000 -0400
@@ -228,6 +228,7 @@ enum cvmx_board_types_enum {
 	 */
 	CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
 	CVMX_BOARD_TYPE_UBNT_E100 = 20002,
+	CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
 	CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
 
 	/* The remaining range is reserved for future use. */
@@ -327,6 +328,7 @@ static inline const char *cvmx_board_typ
 		    /* Customer private range */
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
 	}
 	return "Unsupported Board";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/page.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 
 /*
  * This is used for calculating the real page sizes
- * for FTLB or VTLB + FTLB confugrations.
+ * for FTLB or VTLB + FTLB configurations.
  */
 static inline unsigned int page_size_ftlb(unsigned int mmuextdef)
 {
@@ -223,7 +223,8 @@ static inline int pfn_valid(unsigned lon
 
 #endif
 
-#define virt_to_page(kaddr)	pfn_to_page(PFN_DOWN(virt_to_phys(kaddr)))
+#define virt_to_page(kaddr)	pfn_to_page(PFN_DOWN(virt_to_phys((void *)     \
+								  (kaddr))))
 
 extern int __virt_addr_valid(const volatile void *kaddr);
 #define virt_addr_valid(kaddr)						\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/pgtable-32.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/pgtable-32.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/pgtable-32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/pgtable-32.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,18 @@
 
 #include <asm-generic/pgtable-nopmd.h>
 
+extern int temp_tlb_entry __cpuinitdata;
+
+/*
+ * - add_temporary_entry() add a temporary TLB entry. We use TLB entries
+ *	starting at the top and working down. This is for populating the
+ *	TLB before trap_init() puts the TLB miss handler in place. It
+ *	should be used only for entries matching the actual page tables,
+ *	to prevent inconsistencies.
+ */
+extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+			       unsigned long entryhi, unsigned long pagemask);
+
 /*
  * Basically we have the same two-level (which is the logical three level
  * Linux page table layout folded) page tables as the i386.  Some day
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,6 +97,34 @@ extern void paging_init(void);
 
 #define pmd_page_vaddr(pmd)	pmd_val(pmd)
 
+#define htw_stop()							\
+do {									\
+	if (cpu_has_htw)						\
+		write_c0_pwctl(read_c0_pwctl() &			\
+			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));		\
+} while(0)
+
+#define htw_start()							\
+do {									\
+	if (cpu_has_htw)						\
+		write_c0_pwctl(read_c0_pwctl() |			\
+			       (1 << MIPS_PWCTL_PWEN_SHIFT));		\
+} while(0)
+
+
+#define htw_reset()							\
+do {									\
+	if (cpu_has_htw) {						\
+		htw_stop();						\
+		back_to_back_c0_hazard();				\
+		htw_start();						\
+		back_to_back_c0_hazard();				\
+	}								\
+} while(0)
+
+extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
+	pte_t pteval);
+
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 
 #define pte_none(pte)		(!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
@@ -120,7 +148,6 @@ static inline void set_pte(pte_t *ptep,
 		}
 	}
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -131,6 +158,7 @@ static inline void pte_clear(struct mm_s
 		null.pte_low = null.pte_high = _PAGE_GLOBAL;
 
 	set_pte_at(mm, addr, ptep, null);
+	htw_reset();
 }
 #else
 
@@ -157,7 +185,6 @@ static inline void set_pte(pte_t *ptep,
 	}
 #endif
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -168,6 +195,7 @@ static inline void pte_clear(struct mm_s
 	else
 #endif
 		set_pte_at(mm, addr, ptep, __pte(0));
+	htw_reset();
 }
 #endif
 
@@ -363,15 +391,12 @@ static inline pte_t pte_modify(pte_t pte
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
 	pte_t pte);
-extern void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte);
 
 static inline void update_mmu_cache(struct vm_area_struct *vma,
 	unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
 	__update_tlb(vma, address, pte);
-	__update_cache(vma, address, pte);
 }
 
 static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -238,7 +238,13 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#define ARCH_MIN_TASKALIGN	8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN	16
+# define FPU_ALIGN		__aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN	8
+# define FPU_ALIGN
+#endif
 
 struct mips_abi;
 
@@ -255,7 +261,7 @@ struct thread_struct {
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	struct mips_fpu_struct fpu;
+	struct mips_fpu_struct fpu FPU_ALIGN;
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* Emulated instruction count */
 	unsigned long emulated_fp;
@@ -367,6 +373,7 @@ 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-3.16-gnu/arch/mips/include/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 struct pt_regs {
 #ifdef CONFIG_32BIT
 	/* Pad bytes for argument save space on the stack. */
-	unsigned long pad0[6];
+	unsigned long pad0[8];
 #endif
 
 	/* Saved main processor registers. */
@@ -47,8 +47,10 @@ struct pt_regs {
 
 struct task_struct;
 
-extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
-extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
+extern int ptrace_getregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
+extern int ptrace_setregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
 
 extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
 extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/r4kcache.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/r4kcache.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/r4kcache.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/r4kcache.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,9 @@
 #include <asm/mipsmtregs.h>
 #include <asm/uaccess.h> /* for segment_eq() */
 
+extern void (*r4k_blast_dcache)(void);
+extern void (*r4k_blast_icache)(void);
+
 /*
  * This macro return a properly sign-extended address suitable as base address
  * for indexed cache operations.  Two issues here:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/reg.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/reg.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,128 +1 @@
-/*
- * Various register offset definitions for debuggers, core file
- * examiners and whatnot.
- *
- * 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) 1995, 1999 Ralf Baechle
- * Copyright (C) 1995, 1999 Silicon Graphics
- */
-#ifndef __ASM_MIPS_REG_H
-#define __ASM_MIPS_REG_H
-
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			6
-#define EF_R1			7
-#define EF_R2			8
-#define EF_R3			9
-#define EF_R4			10
-#define EF_R5			11
-#define EF_R6			12
-#define EF_R7			13
-#define EF_R8			14
-#define EF_R9			15
-#define EF_R10			16
-#define EF_R11			17
-#define EF_R12			18
-#define EF_R13			19
-#define EF_R14			20
-#define EF_R15			21
-#define EF_R16			22
-#define EF_R17			23
-#define EF_R18			24
-#define EF_R19			25
-#define EF_R20			26
-#define EF_R21			27
-#define EF_R22			28
-#define EF_R23			29
-#define EF_R24			30
-#define EF_R25			31
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26			32
-#define EF_R27			33
-
-#define EF_R28			34
-#define EF_R29			35
-#define EF_R30			36
-#define EF_R31			37
-
-/*
- * Saved special registers
- */
-#define EF_LO			38
-#define EF_HI			39
-
-#define EF_CP0_EPC		40
-#define EF_CP0_BADVADDR		41
-#define EF_CP0_STATUS		42
-#define EF_CP0_CAUSE		43
-#define EF_UNUSED0		44
-
-#define EF_SIZE			180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			 0
-#define EF_R1			 1
-#define EF_R2			 2
-#define EF_R3			 3
-#define EF_R4			 4
-#define EF_R5			 5
-#define EF_R6			 6
-#define EF_R7			 7
-#define EF_R8			 8
-#define EF_R9			 9
-#define EF_R10			10
-#define EF_R11			11
-#define EF_R12			12
-#define EF_R13			13
-#define EF_R14			14
-#define EF_R15			15
-#define EF_R16			16
-#define EF_R17			17
-#define EF_R18			18
-#define EF_R19			19
-#define EF_R20			20
-#define EF_R21			21
-#define EF_R22			22
-#define EF_R23			23
-#define EF_R24			24
-#define EF_R25			25
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26			26
-#define EF_R27			27
-
-
-#define EF_R28			28
-#define EF_R29			29
-#define EF_R30			30
-#define EF_R31			31
-
-/*
- * Saved special registers
- */
-#define EF_LO			32
-#define EF_HI			33
-
-#define EF_CP0_EPC		34
-#define EF_CP0_BADVADDR		35
-#define EF_CP0_STATUS		36
-#define EF_CP0_CAUSE		37
-
-#define EF_SIZE			304	/* size in bytes */
-
-#endif /* CONFIG_64BIT */
-
-#endif /* __ASM_MIPS_REG_H */
+#include <uapi/asm/reg.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/smp-cps.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/smp-cps.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/smp-cps.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/smp-cps.h	2014-09-28 17:29:07.000000000 -0400
@@ -31,11 +31,19 @@ extern void mips_cps_core_init(void);
 
 extern struct vpe_boot_config *mips_cps_boot_vpes(void);
 
-extern bool mips_cps_smp_in_use(void);
-
 extern void mips_cps_pm_save(void);
 extern void mips_cps_pm_restore(void);
 
+#ifdef CONFIG_MIPS_CPS
+
+extern bool mips_cps_smp_in_use(void);
+
+#else /* !CONFIG_MIPS_CPS */
+
+static inline bool mips_cps_smp_in_use(void) { return false; }
+
+#endif /* !CONFIG_MIPS_CPS */
+
 #else /* __ASSEMBLY__ */
 
 .extern mips_cps_bootcfg;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/smp.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/smp.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/smp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/smp.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 
 extern int smp_num_siblings;
 extern cpumask_t cpu_sibling_map[];
+extern cpumask_t cpu_core_map[];
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/sparsemem.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/sparsemem.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/sparsemem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/sparsemem.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,7 @@
 #else
 # define SECTION_SIZE_BITS	28
 #endif
-#define MAX_PHYSMEM_BITS	35
+#define MAX_PHYSMEM_BITS	48
 
 #endif /* CONFIG_SPARSEMEM */
 #endif /* _MIPS_SPARSEMEM_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/switch_to.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/switch_to.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/switch_to.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/switch_to.h	2014-09-28 17:29:07.000000000 -0400
@@ -92,7 +92,7 @@ do {									\
 			KSTK_STATUS(prev) &= ~ST0_CU2;			\
 		__c0_stat = read_c0_status();				\
 		write_c0_status(__c0_stat | ST0_CU2);			\
-		cop2_save(&prev->thread.cp2);				\
+		cop2_save(prev);					\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	__clear_software_ll_bit();					\
@@ -111,7 +111,7 @@ do {									\
 			(KSTK_STATUS(current) & ST0_CU2)) {		\
 		__c0_stat = read_c0_status();				\
 		write_c0_status(__c0_stat | ST0_CU2);			\
-		cop2_restore(&current->thread.cp2);			\
+		cop2_restore(current);					\
 		write_c0_status(__c0_stat & ~ST0_CU2);			\
 	}								\
 	if (cpu_has_dsp)						\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/syscall.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/syscall.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/syscall.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/syscall.h	2014-09-28 17:29:07.000000000 -0400
@@ -131,10 +131,12 @@ static inline int syscall_get_arch(void)
 {
 	int arch = EM_MIPS;
 #ifdef CONFIG_64BIT
-	if (!test_thread_flag(TIF_32BIT_REGS))
+	if (!test_thread_flag(TIF_32BIT_REGS)) {
 		arch |= __AUDIT_ARCH_64BIT;
-	if (test_thread_flag(TIF_32BIT_ADDR))
-		arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
+		/* N32 sets only TIF_32BIT_ADDR */
+		if (test_thread_flag(TIF_32BIT_ADDR))
+			arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
+	}
 #endif
 #if defined(__LITTLE_ENDIAN)
 	arch |=  __AUDIT_ARCH_LE;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/topology.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/topology.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/topology.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/topology.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,5 +9,13 @@
 #define __ASM_TOPOLOGY_H
 
 #include <topology.h>
+#include <linux/smp.h>
+
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)	(cpu_data[cpu].package)
+#define topology_core_id(cpu)			(cpu_data[cpu].core)
+#define topology_core_cpumask(cpu)		(&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu)		(&cpu_sibling_map[cpu])
+#endif
 
 #endif /* __ASM_TOPOLOGY_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/asm/user.h linux-libre-3.17-rc7-gnu/arch/mips/include/asm/user.h
--- linux-libre-3.16-gnu/arch/mips/include/asm/user.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/asm/user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
- */
-#ifndef _ASM_USER_H
-#define _ASM_USER_H
-
-#include <asm/page.h>
-#include <asm/reg.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the irix-core).  The file
- * contents are as follows:
- *
- *  upage: 1 page consisting of a user struct that tells gdb
- *	what is present in the file.  Directly after this is a
- *	copy of the task_struct, which is currently not used by gdb,
- *	but it may come in handy at some point.	 All of the registers
- *	are stored as part of the upage.  The upage should always be
- *	only one page long.
- *  data: The data segment follows next.  We use current->end_text to
- *	current->brk to pick up all of the user variables, plus any memory
- *	that may have been sbrk'ed.  No attempt is made to determine if a
- *	page is demand-zero or if a page is totally unused, we just cover
- *	the entire range.  All of the addresses are rounded in such a way
- *	that an integral number of pages is written.
- *  stack: We need the stack information in order to get a meaningful
- *	backtrace.  We need to write the data from usp to
- *	current->start_stack, so we round each of these in order to be able
- *	to write an integer number of pages.
- */
-struct user {
-	unsigned long	regs[EF_SIZE /		/* integer and fp regs */
-			sizeof(unsigned long) + 64];
-	size_t		u_tsize;		/* text size (pages) */
-	size_t		u_dsize;		/* data size (pages) */
-	size_t		u_ssize;		/* stack size (pages) */
-	unsigned long	start_code;		/* text starting address */
-	unsigned long	start_data;		/* data starting address */
-	unsigned long	start_stack;		/* stack starting address */
-	long int	signal;			/* signal causing core dump */
-	unsigned long	u_ar0;			/* help gdb find registers */
-	unsigned long	magic;			/* identifies a core file */
-	char		u_comm[32];		/* user command name */
-};
-
-#define NBPG			PAGE_SIZE
-#define UPAGES			1
-#define HOST_TEXT_START_ADDR	(u.start_code)
-#define HOST_DATA_START_ADDR	(u.start_data)
-#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _ASM_USER_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/uapi/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/mips/include/uapi/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,24 +22,27 @@
 #define DSP_CONTROL	77
 #define ACX		78
 
-#ifndef __KERNEL__
 /*
- * This struct defines the way the registers are stored on the stack during a
- * system call/exception. As usual the registers k0/k1 aren't being saved.
+ * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
+ * format is the same for both 32- and 64-bit processes. Registers for 32-bit
+ * processes are sign extended.
  */
+#ifdef __KERNEL__
+struct user_pt_regs {
+#else
 struct pt_regs {
+#endif
 	/* Saved main processor registers. */
-	unsigned long regs[32];
+	__u64 regs[32];
 
 	/* Saved special registers. */
-	unsigned long cp0_status;
-	unsigned long hi;
-	unsigned long lo;
-	unsigned long cp0_badvaddr;
-	unsigned long cp0_cause;
-	unsigned long cp0_epc;
+	__u64 lo;
+	__u64 hi;
+	__u64 cp0_epc;
+	__u64 cp0_badvaddr;
+	__u64 cp0_status;
+	__u64 cp0_cause;
 } __attribute__ ((aligned (8)));
-#endif /* __KERNEL__ */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS		12
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/uapi/asm/reg.h linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/reg.h
--- linux-libre-3.16-gnu/arch/mips/include/uapi/asm/reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
+ *
+ * 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) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999 Silicon Graphics
+ */
+#ifndef __UAPI_ASM_MIPS_REG_H
+#define __UAPI_ASM_MIPS_REG_H
+
+#define MIPS32_EF_R0		6
+#define MIPS32_EF_R1		7
+#define MIPS32_EF_R2		8
+#define MIPS32_EF_R3		9
+#define MIPS32_EF_R4		10
+#define MIPS32_EF_R5		11
+#define MIPS32_EF_R6		12
+#define MIPS32_EF_R7		13
+#define MIPS32_EF_R8		14
+#define MIPS32_EF_R9		15
+#define MIPS32_EF_R10		16
+#define MIPS32_EF_R11		17
+#define MIPS32_EF_R12		18
+#define MIPS32_EF_R13		19
+#define MIPS32_EF_R14		20
+#define MIPS32_EF_R15		21
+#define MIPS32_EF_R16		22
+#define MIPS32_EF_R17		23
+#define MIPS32_EF_R18		24
+#define MIPS32_EF_R19		25
+#define MIPS32_EF_R20		26
+#define MIPS32_EF_R21		27
+#define MIPS32_EF_R22		28
+#define MIPS32_EF_R23		29
+#define MIPS32_EF_R24		30
+#define MIPS32_EF_R25		31
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS32_EF_R26		32
+#define MIPS32_EF_R27		33
+
+#define MIPS32_EF_R28		34
+#define MIPS32_EF_R29		35
+#define MIPS32_EF_R30		36
+#define MIPS32_EF_R31		37
+
+/*
+ * Saved special registers
+ */
+#define MIPS32_EF_LO		38
+#define MIPS32_EF_HI		39
+
+#define MIPS32_EF_CP0_EPC	40
+#define MIPS32_EF_CP0_BADVADDR	41
+#define MIPS32_EF_CP0_STATUS	42
+#define MIPS32_EF_CP0_CAUSE	43
+#define MIPS32_EF_UNUSED0	44
+
+#define MIPS32_EF_SIZE		180
+
+#define MIPS64_EF_R0		0
+#define MIPS64_EF_R1		1
+#define MIPS64_EF_R2		2
+#define MIPS64_EF_R3		3
+#define MIPS64_EF_R4		4
+#define MIPS64_EF_R5		5
+#define MIPS64_EF_R6		6
+#define MIPS64_EF_R7		7
+#define MIPS64_EF_R8		8
+#define MIPS64_EF_R9		9
+#define MIPS64_EF_R10		10
+#define MIPS64_EF_R11		11
+#define MIPS64_EF_R12		12
+#define MIPS64_EF_R13		13
+#define MIPS64_EF_R14		14
+#define MIPS64_EF_R15		15
+#define MIPS64_EF_R16		16
+#define MIPS64_EF_R17		17
+#define MIPS64_EF_R18		18
+#define MIPS64_EF_R19		19
+#define MIPS64_EF_R20		20
+#define MIPS64_EF_R21		21
+#define MIPS64_EF_R22		22
+#define MIPS64_EF_R23		23
+#define MIPS64_EF_R24		24
+#define MIPS64_EF_R25		25
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS64_EF_R26		26
+#define MIPS64_EF_R27		27
+
+
+#define MIPS64_EF_R28		28
+#define MIPS64_EF_R29		29
+#define MIPS64_EF_R30		30
+#define MIPS64_EF_R31		31
+
+/*
+ * Saved special registers
+ */
+#define MIPS64_EF_LO		32
+#define MIPS64_EF_HI		33
+
+#define MIPS64_EF_CP0_EPC	34
+#define MIPS64_EF_CP0_BADVADDR	35
+#define MIPS64_EF_CP0_STATUS	36
+#define MIPS64_EF_CP0_CAUSE	37
+
+#define MIPS64_EF_SIZE		304	/* size in bytes */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+#define EF_R0			MIPS32_EF_R0
+#define EF_R1			MIPS32_EF_R1
+#define EF_R2			MIPS32_EF_R2
+#define EF_R3			MIPS32_EF_R3
+#define EF_R4			MIPS32_EF_R4
+#define EF_R5			MIPS32_EF_R5
+#define EF_R6			MIPS32_EF_R6
+#define EF_R7			MIPS32_EF_R7
+#define EF_R8			MIPS32_EF_R8
+#define EF_R9			MIPS32_EF_R9
+#define EF_R10			MIPS32_EF_R10
+#define EF_R11			MIPS32_EF_R11
+#define EF_R12			MIPS32_EF_R12
+#define EF_R13			MIPS32_EF_R13
+#define EF_R14			MIPS32_EF_R14
+#define EF_R15			MIPS32_EF_R15
+#define EF_R16			MIPS32_EF_R16
+#define EF_R17			MIPS32_EF_R17
+#define EF_R18			MIPS32_EF_R18
+#define EF_R19			MIPS32_EF_R19
+#define EF_R20			MIPS32_EF_R20
+#define EF_R21			MIPS32_EF_R21
+#define EF_R22			MIPS32_EF_R22
+#define EF_R23			MIPS32_EF_R23
+#define EF_R24			MIPS32_EF_R24
+#define EF_R25			MIPS32_EF_R25
+#define EF_R26			MIPS32_EF_R26
+#define EF_R27			MIPS32_EF_R27
+#define EF_R28			MIPS32_EF_R28
+#define EF_R29			MIPS32_EF_R29
+#define EF_R30			MIPS32_EF_R30
+#define EF_R31			MIPS32_EF_R31
+#define EF_LO			MIPS32_EF_LO
+#define EF_HI			MIPS32_EF_HI
+#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0		MIPS32_EF_UNUSED0
+#define EF_SIZE			MIPS32_EF_SIZE
+
+#elif _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+
+#define EF_R0			MIPS64_EF_R0
+#define EF_R1			MIPS64_EF_R1
+#define EF_R2			MIPS64_EF_R2
+#define EF_R3			MIPS64_EF_R3
+#define EF_R4			MIPS64_EF_R4
+#define EF_R5			MIPS64_EF_R5
+#define EF_R6			MIPS64_EF_R6
+#define EF_R7			MIPS64_EF_R7
+#define EF_R8			MIPS64_EF_R8
+#define EF_R9			MIPS64_EF_R9
+#define EF_R10			MIPS64_EF_R10
+#define EF_R11			MIPS64_EF_R11
+#define EF_R12			MIPS64_EF_R12
+#define EF_R13			MIPS64_EF_R13
+#define EF_R14			MIPS64_EF_R14
+#define EF_R15			MIPS64_EF_R15
+#define EF_R16			MIPS64_EF_R16
+#define EF_R17			MIPS64_EF_R17
+#define EF_R18			MIPS64_EF_R18
+#define EF_R19			MIPS64_EF_R19
+#define EF_R20			MIPS64_EF_R20
+#define EF_R21			MIPS64_EF_R21
+#define EF_R22			MIPS64_EF_R22
+#define EF_R23			MIPS64_EF_R23
+#define EF_R24			MIPS64_EF_R24
+#define EF_R25			MIPS64_EF_R25
+#define EF_R26			MIPS64_EF_R26
+#define EF_R27			MIPS64_EF_R27
+#define EF_R28			MIPS64_EF_R28
+#define EF_R29			MIPS64_EF_R29
+#define EF_R30			MIPS64_EF_R30
+#define EF_R31			MIPS64_EF_R31
+#define EF_LO			MIPS64_EF_LO
+#define EF_HI			MIPS64_EF_HI
+#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
+#define EF_SIZE			MIPS64_EF_SIZE
+
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#endif /* __UAPI_ASM_MIPS_REG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/mips/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -372,16 +372,19 @@
 #define __NR_sched_setattr		(__NR_Linux + 349)
 #define __NR_sched_getattr		(__NR_Linux + 350)
 #define __NR_renameat2			(__NR_Linux + 351)
+#define __NR_seccomp			(__NR_Linux + 352)
+#define __NR_getrandom			(__NR_Linux + 353)
+#define __NR_memfd_create		(__NR_Linux + 354)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		351
+#define __NR_Linux_syscalls		354
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		351
+#define __NR_O32_Linux_syscalls		354
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -701,16 +704,19 @@
 #define __NR_sched_setattr		(__NR_Linux + 309)
 #define __NR_sched_getattr		(__NR_Linux + 310)
 #define __NR_renameat2			(__NR_Linux + 311)
+#define __NR_seccomp			(__NR_Linux + 312)
+#define __NR_getrandom			(__NR_Linux + 313)
+#define __NR_memfd_create		(__NR_Linux + 314)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		311
+#define __NR_Linux_syscalls		314
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		311
+#define __NR_64_Linux_syscalls		314
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -1034,15 +1040,18 @@
 #define __NR_sched_setattr		(__NR_Linux + 313)
 #define __NR_sched_getattr		(__NR_Linux + 314)
 #define __NR_renameat2			(__NR_Linux + 315)
+#define __NR_seccomp			(__NR_Linux + 316)
+#define __NR_getrandom			(__NR_Linux + 317)
+#define __NR_memfd_create		(__NR_Linux + 318)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		315
+#define __NR_Linux_syscalls		318
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		315
+#define __NR_N32_Linux_syscalls		318
 
 #endif /* _UAPI_ASM_UNISTD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/jz4740/board-qi_lb60.c linux-libre-3.17-rc7-gnu/arch/mips/jz4740/board-qi_lb60.c
--- linux-libre-3.16-gnu/arch/mips/jz4740/board-qi_lb60.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/jz4740/board-qi_lb60.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/jz4740/clock-debugfs.c linux-libre-3.17-rc7-gnu/arch/mips/jz4740/clock-debugfs.c
--- linux-libre-3.16-gnu/arch/mips/jz4740/clock-debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/jz4740/clock-debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,8 +87,7 @@ void jz4740_clock_debugfs_add_clk(struct
 /* TODO: Locking */
 void jz4740_clock_debugfs_update_parent(struct clk *clk)
 {
-	if (clk->debugfs_parent_entry)
-		debugfs_remove(clk->debugfs_parent_entry);
+	debugfs_remove(clk->debugfs_parent_entry);
 
 	if (clk->parent) {
 		char parent_path[100];
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/jz4740/platform.c linux-libre-3.17-rc7-gnu/arch/mips/jz4740/platform.c
--- linux-libre-3.16-gnu/arch/mips/jz4740/platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/jz4740/platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ struct platform_device jz4740_usb_ohci_d
 
 /* USB Device Controller */
 struct platform_device jz4740_udc_xceiv_device = {
-	.name = "usb_phy_gen_xceiv",
+	.name = "usb_phy_generic",
 	.id   = 0,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/Kconfig linux-libre-3.17-rc7-gnu/arch/mips/Kconfig
--- linux-libre-3.16-gnu/arch/mips/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,6 @@ config MIPS
 	select HAVE_BPF_JIT if !CPU_MICROMIPS
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_C_RECORDMCOUNT
@@ -72,6 +71,7 @@ config MIPS_ALCHEMY
 	select SYS_SUPPORTS_APM_EMULATION
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
+	select COMMON_CLK
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -130,6 +130,8 @@ config BCM47XX
 	select SYS_SUPPORTS_MIPS16
 	select SYS_HAS_EARLY_PRINTK
 	select USE_GENERIC_EARLY_PRINTK_8250
+	select GPIOLIB
+	select LEDS_GPIO_REGISTER
 	help
 	 Support for BCM47XX based boards
 
@@ -138,6 +140,7 @@ config BCM63XX
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
+	select SYNC_R4K
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select SYS_SUPPORTS_32BIT_KERNEL
@@ -543,6 +546,7 @@ config SGI_IP28
 	# select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select MIPS_L1_CACHE_SHIFT_7
       help
         This is the SGI Indigo2 with R10000 processor.  To compile a Linux
         kernel that runs on these, say Y here.
@@ -2026,7 +2030,9 @@ config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
 	depends on SYS_SUPPORTS_MIPS_CMP
 	select MIPS_GIC_IPI
+	select SMP
 	select SYNC_R4K
+	select SYS_SUPPORTS_SMP
 	select WEAK_ORDERING
 	default n
 	help
@@ -2057,6 +2063,7 @@ config MIPS_CPS
 	  support is unavailable.
 
 config MIPS_CPS_PM
+	select MIPS_CPC
 	bool
 
 config MIPS_GIC_IPI
@@ -2110,9 +2117,9 @@ config CPU_MICROMIPS
 	  microMIPS ISA
 
 config CPU_HAS_MSA
-	bool "Support for the MIPS SIMD Architecture"
+	bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
 	depends on CPU_SUPPORTS_MSA
-	default y
+	depends on 64BIT || MIPS_O32_FP64_SUPPORT
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
 	  and a set of SIMD instructions to operate on them. When this option
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/asm-offsets.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/asm-offsets.c
--- linux-libre-3.16-gnu/arch/mips/kernel/asm-offsets.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/asm-offsets.c	2014-09-28 17:29:07.000000000 -0400
@@ -234,6 +234,7 @@ void output_thread_fpu_defines(void)
 	       thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
 
 	OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+	OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
 	BLANK();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/binfmt_elfo32.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/binfmt_elfo32.c
--- linux-libre-3.16-gnu/arch/mips/kernel/binfmt_elfo32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/binfmt_elfo32.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,22 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 
 #include <asm/processor.h>
 
-/*
- * When this file is selected, we are definitely running a 64bit kernel.
- * So using the right regs define in asm/reg.h
- */
-#define WANT_COMPAT_REG_H
-
-/* These MUST be defined before elf.h gets included */
-extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)				\
-({									\
-	int __res = 1;							\
-	elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));		\
-	__res;								\
-})
-
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -145,28 +129,6 @@ jiffies_to_compat_timeval(unsigned long
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < EF_R0; i++)
-		grp[i] = 0;
-	grp[EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
-	grp[EF_R26] = 0;
-	grp[EF_R27] = 0;
-	grp[EF_LO] = (elf_greg_t) regs->lo;
-	grp[EF_HI] = (elf_greg_t) regs->hi;
-	grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-	grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-	grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-	grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
-	grp[EF_UNUSED0] = 0;
-#endif
-}
-
 MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
 MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/cps-vec.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/cps-vec.S
--- linux-libre-3.16-gnu/arch/mips/kernel/cps-vec.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/cps-vec.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/asmmacro.h>
 #include <asm/cacheops.h>
+#include <asm/eva.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/pm.h>
@@ -166,6 +167,9 @@ dcache_done:
 1:	jal	mips_cps_core_init
 	 nop
 
+	/* Do any EVA initialization if necessary */
+	eva_init
+
 	/*
 	 * Boot any other VPEs within this core that should be online, and
 	 * deactivate this VPE if it should be offline.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/cpu-probe.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/cpu-probe.c
--- linux-libre-3.16-gnu/arch/mips/kernel/cpu-probe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/cpu-probe.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,6 +54,20 @@ static int __init dsp_disable(char *s)
 
 __setup("nodsp", dsp_disable);
 
+static int mips_htw_disabled;
+
+static int __init htw_disable(char *s)
+{
+	mips_htw_disabled = 1;
+	cpu_data[0].options &= ~MIPS_CPU_HTW;
+	write_c0_pwctl(read_c0_pwctl() &
+		       ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+
+	return 1;
+}
+
+__setup("nohtw", htw_disable);
+
 static inline void check_errata(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -130,14 +144,13 @@ static inline int __cpu_has_fpu(void)
 
 static inline unsigned long cpu_get_msa_id(void)
 {
-	unsigned long status, conf5, msa_id;
+	unsigned long status, msa_id;
 
 	status = read_c0_status();
 	__enable_fpu(FPU_64BIT);
-	conf5 = read_c0_config5();
 	enable_msa();
 	msa_id = read_msa_ir();
-	write_c0_config5(conf5);
+	disable_msa();
 	write_c0_status(status);
 	return msa_id;
 }
@@ -321,6 +334,9 @@ static inline unsigned int decode_config
 		c->options |= MIPS_CPU_SEGMENTS;
 	if (config3 & MIPS_CONF3_MSA)
 		c->ases |= MIPS_ASE_MSA;
+	/* Only tested on 32-bit cores */
+	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
+		c->options |= MIPS_CPU_HTW;
 
 	return config3 & MIPS_CONF_M;
 }
@@ -389,6 +405,8 @@ static inline unsigned int decode_config
 
 	if (config5 & MIPS_CONF5_EVA)
 		c->options |= MIPS_CPU_EVA;
+	if (config5 & MIPS_CONF5_MRP)
+		c->options |= MIPS_CPU_MAAR;
 
 	return config5 & MIPS_CONF_M;
 }
@@ -421,6 +439,15 @@ static void decode_configs(struct cpuinf
 
 	mips_probe_watch_registers(c);
 
+	if (cpu_has_rixi) {
+		/* Enable the RIXI exceptions */
+		write_c0_pagegrain(read_c0_pagegrain() | PG_IEC);
+		back_to_back_c0_hazard();
+		/* Verify the IEC bit is set */
+		if (read_c0_pagegrain() & PG_IEC)
+			c->options |= MIPS_CPU_RIXIEX;
+	}
+
 #ifndef CONFIG_MIPS_CPS
 	if (cpu_has_mips_r2) {
 		c->core = get_ebase_cpunum();
@@ -740,6 +767,12 @@ static inline void cpu_probe_legacy(stru
 			__cpu_name[cpu] = "ICT Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
 			break;
+		case PRID_REV_LOONGSON3B_R1:
+		case PRID_REV_LOONGSON3B_R2:
+			c->cputype = CPU_LOONGSON3;
+			__cpu_name[cpu] = "ICT Loongson-3";
+			set_elf_platform(cpu, "loongson3b");
+			break;
 		}
 
 		set_isa(c, MIPS_CPU_ISA_III);
@@ -1187,6 +1220,12 @@ void cpu_probe(void)
 	if (mips_dsp_disabled)
 		c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
 
+	if (mips_htw_disabled) {
+		c->options &= ~MIPS_CPU_HTW;
+		write_c0_pwctl(read_c0_pwctl() &
+			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+	}
+
 	if (c->options & MIPS_CPU_FPU) {
 		c->fpu_id = cpu_get_fpu_id();
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/mips/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,7 +63,7 @@ static inline int in_kernel_space(unsign
 	((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
 
 static unsigned int insn_jal_ftrace_caller __read_mostly;
-static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
+static unsigned int insn_la_mcount[2] __read_mostly;
 static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
 
 static inline void ftrace_dyn_arch_init_insns(void)
@@ -71,10 +71,10 @@ static inline void ftrace_dyn_arch_init_
 	u32 *buf;
 	unsigned int v1;
 
-	/* lui v1, hi16_mcount */
+	/* la v1, _mcount */
 	v1 = 3;
-	buf = (u32 *)&insn_lui_v1_hi16_mcount;
-	UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
+	buf = (u32 *)&insn_la_mcount[0];
+	UASM_i_LA(&buf, v1, MCOUNT_ADDR);
 
 	/* jal (ftrace_caller + 8), jump over the first two instruction */
 	buf = (u32 *)&insn_jal_ftrace_caller;
@@ -111,14 +111,47 @@ static int ftrace_modify_code_2(unsigned
 				unsigned int new_code2)
 {
 	int faulted;
+	mm_segment_t old_fs;
 
 	safe_store_code(new_code1, ip, faulted);
 	if (unlikely(faulted))
 		return -EFAULT;
-	safe_store_code(new_code2, ip + 4, faulted);
+
+	ip += 4;
+	safe_store_code(new_code2, ip, faulted);
 	if (unlikely(faulted))
 		return -EFAULT;
+
+	ip -= 4;
+	old_fs = get_fs();
+	set_fs(get_ds());
 	flush_icache_range(ip, ip + 8);
+	set_fs(old_fs);
+
+	return 0;
+}
+
+static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
+				 unsigned int new_code2)
+{
+	int faulted;
+	mm_segment_t old_fs;
+
+	ip += 4;
+	safe_store_code(new_code2, ip, faulted);
+	if (unlikely(faulted))
+		return -EFAULT;
+
+	ip -= 4;
+	safe_store_code(new_code1, ip, faulted);
+	if (unlikely(faulted))
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+	flush_icache_range(ip, ip + 8);
+	set_fs(old_fs);
+
 	return 0;
 }
 #endif
@@ -130,13 +163,14 @@ static int ftrace_modify_code_2(unsigned
  *
  * move at, ra
  * jal _mcount		--> nop
+ *  sub sp, sp, 8	--> nop  (CONFIG_32BIT)
  *
  * 2. For modules:
  *
  * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
  *
  * lui v1, hi_16bit_of_mcount	     --> b 1f (0x10000005)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop  (CONFIG_32BIT)
  * move at, ra
  * move $12, ra_address
  * jalr v1
@@ -145,7 +179,7 @@ static int ftrace_modify_code_2(unsigned
  * 2.2 For the Other situations
  *
  * lui v1, hi_16bit_of_mcount	     --> b 1f (0x10000004)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop  (CONFIG_32BIT)
  * move at, ra
  * jalr v1
  *  nop | move $12, ra_address | sub sp, sp, 8
@@ -184,10 +218,14 @@ int ftrace_make_call(struct dyn_ftrace *
 	unsigned int new;
 	unsigned long ip = rec->ip;
 
-	new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
-		insn_lui_v1_hi16_mcount;
+	new = in_kernel_space(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
 
+#ifdef CONFIG_64BIT
 	return ftrace_modify_code(ip, new);
+#else
+	return ftrace_modify_code_2r(ip, new, in_kernel_space(ip) ?
+						INSN_NOP : insn_la_mcount[1]);
+#endif
 }
 
 #define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
@@ -302,6 +340,9 @@ void prepare_ftrace_return(unsigned long
 	    &return_to_handler;
 	int faulted, insns;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/irq-gic.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/irq-gic.c
--- linux-libre-3.16-gnu/arch/mips/kernel/irq-gic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/irq-gic.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,18 @@ unsigned int gic_irq_flags[GIC_NUM_INTRS
 /* The index into this array is the vector # of the interrupt. */
 struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
 
+struct gic_pcpu_mask {
+	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+};
+
+struct gic_pending_regs {
+	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+};
+
+struct gic_intrmask_regs {
+	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+};
+
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
@@ -177,7 +189,7 @@ unsigned int gic_compare_int(void)
 		return 0;
 }
 
-unsigned int gic_get_int(void)
+void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 {
 	unsigned int i;
 	unsigned long *pending, *intrmask, *pcpu_mask;
@@ -202,8 +214,17 @@ unsigned int gic_get_int(void)
 
 	bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
 	bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+	bitmap_and(dst, src, pending, GIC_NUM_INTRS);
+}
 
-	return find_first_bit(pending, GIC_NUM_INTRS);
+unsigned int gic_get_int(void)
+{
+	DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
+
+	bitmap_fill(interrupts, GIC_NUM_INTRS);
+	gic_get_int_mask(interrupts, interrupts);
+
+	return find_first_bit(interrupts, GIC_NUM_INTRS);
 }
 
 static void gic_mask_irq(struct irq_data *d)
@@ -269,11 +290,13 @@ static void __init gic_setup_intr(unsign
 
 	/* Setup Intr to Pin mapping */
 	if (pin & GIC_MAP_TO_NMI_MSK) {
+		int i;
+
 		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
 		/* FIXME: hack to route NMI to all cpu's */
-		for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
+		for (i = 0; i < NR_CPUS; i += 32) {
 			GICWRITE(GIC_REG_ADDR(SHARED,
-					  GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
+					  GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
 				 0xffffffff);
 		}
 	} else {
@@ -299,9 +322,10 @@ static void __init gic_setup_intr(unsign
 
 	/* Init Intr Masks */
 	GIC_CLR_INTR_MASK(intr);
+
 	/* Initialise per-cpu Interrupt software masks */
-	if (flags & GIC_FLAG_IPI)
-		set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+	set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+
 	if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
 		GIC_SET_INTR_MASK(intr);
 	if (trigtype == GIC_TRIG_EDGE)
@@ -340,8 +364,6 @@ static void __init gic_basic_init(int nu
 		cpu = intrmap[i].cpunum;
 		if (cpu == GIC_UNUSED)
 			continue;
-		if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
-			continue;
 		gic_setup_intr(i,
 			intrmap[i].cpunum,
 			intrmap[i].pin + pin_offset,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/machine_kexec.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/machine_kexec.c
--- linux-libre-3.16-gnu/arch/mips/kernel/machine_kexec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/machine_kexec.c	2014-09-28 17:29:07.000000000 -0400
@@ -71,8 +71,12 @@ machine_kexec(struct kimage *image)
 	kexec_start_address =
 		(unsigned long) phys_to_virt(image->start);
 
-	kexec_indirection_page =
-		(unsigned long) phys_to_virt(image->head & PAGE_MASK);
+	if (image->type == KEXEC_TYPE_DEFAULT) {
+		kexec_indirection_page =
+			(unsigned long) phys_to_virt(image->head & PAGE_MASK);
+	} else {
+		kexec_indirection_page = (unsigned long)&image->head;
+	}
 
 	memcpy((void*)reboot_code_buffer, relocate_new_kernel,
 	       relocate_new_kernel_size);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/mcount.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/mcount.S
--- linux-libre-3.16-gnu/arch/mips/kernel/mcount.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/mcount.S	2014-09-28 17:29:07.000000000 -0400
@@ -74,16 +74,25 @@ _mcount:
 #endif
 
 	/* When tracing is activated, it calls ftrace_caller+8 (aka here) */
-	lw	t1, function_trace_stop
-	bnez	t1, ftrace_stub
-	 nop
-
 	MCOUNT_SAVE_REGS
 #ifdef KBUILD_MCOUNT_RA_ADDRESS
 	PTR_S	MCOUNT_RA_ADDRESS_REG, PT_R12(sp)
 #endif
 
 	PTR_SUBU a0, ra, 8	/* arg1: self address */
+	PTR_LA   t1, _stext
+	sltu     t2, a0, t1	/* t2 = (a0 < _stext) */
+	PTR_LA   t1, _etext
+	sltu     t3, t1, a0	/* t3 = (a0 > _etext) */
+	or       t1, t2, t3
+	beqz     t1, ftrace_call
+	 nop
+#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
+	PTR_SUBU a0, a0, 16	/* arg1: adjust to module's recorded callsite */
+#else
+	PTR_SUBU a0, a0, 12
+#endif
+
 	.globl ftrace_call
 ftrace_call:
 	nop	/* a placeholder for the call to a real tracing function */
@@ -105,9 +114,6 @@ ftrace_stub:
 #else	/* ! CONFIG_DYNAMIC_FTRACE */
 
 NESTED(_mcount, PT_SIZE, ra)
-	lw	t1, function_trace_stop
-	bnez	t1, ftrace_stub
-	 nop
 	PTR_LA	t1, ftrace_stub
 	PTR_L	t2, ftrace_trace_function /* Prepare t2 for (1) */
 	bne	t1, t2, static_trace
@@ -123,7 +129,11 @@ NESTED(_mcount, PT_SIZE, ra)
 	 nop
 #endif
 	b	ftrace_stub
+#ifdef CONFIG_32BIT
+	 addiu sp, sp, 8
+#else
 	 nop
+#endif
 
 static_trace:
 	MCOUNT_SAVE_REGS
@@ -133,6 +143,9 @@ static_trace:
 	 move	a1, AT		/* arg2: parent's return address */
 
 	MCOUNT_RESTORE_REGS
+#ifdef CONFIG_32BIT
+	addiu sp, sp, 8
+#endif
 	.globl ftrace_stub
 ftrace_stub:
 	RETURN_BACK
@@ -177,6 +190,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
 	jal	prepare_ftrace_return
 	 nop
 	MCOUNT_RESTORE_REGS
+#ifndef CONFIG_DYNAMIC_FTRACE
+#ifdef CONFIG_32BIT
+	addiu sp, sp, 8
+#endif
+#endif
 	RETURN_BACK
 	END(ftrace_graph_caller)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/perf_event_mipsxx.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-3.16-gnu/arch/mips/kernel/perf_event_mipsxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/perf_event_mipsxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -558,7 +558,7 @@ static int mipspmu_get_irq(void)
 	if (mipspmu.irq >= 0) {
 		/* Request my own irq handler. */
 		err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq,
-			IRQF_PERCPU | IRQF_NOBALANCING,
+			IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD,
 			"mips_perf_pmu", NULL);
 		if (err) {
 			pr_warning("Unable to request IRQ%d for MIPS "
@@ -1386,6 +1386,9 @@ static irqreturn_t mipsxx_pmu_handle_irq
 /* proAptiv */
 #define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b)				\
 	((b) == 0 || (b) == 1)
+/* P5600 */
+#define IS_BOTH_COUNTERS_P5600_EVENT(b)					\
+	((b) == 0 || (b) == 1)
 
 /* 1004K */
 #define IS_BOTH_COUNTERS_1004K_EVENT(b)					\
@@ -1420,20 +1423,23 @@ static irqreturn_t mipsxx_pmu_handle_irq
 
 
 /*
- * User can use 0-255 raw events, where 0-127 for the events of even
- * counters, and 128-255 for odd counters. Note that bit 7 is used to
- * indicate the parity. So, for example, when user wants to take the
- * Event Num of 15 for odd counters (by referring to the user manual),
- * then 128 needs to be added to 15 as the input for the event config,
- * i.e., 143 (0x8F) to be used.
+ * For most cores the user can use 0-255 raw events, where 0-127 for the events
+ * of even counters, and 128-255 for odd counters. Note that bit 7 is used to
+ * indicate the even/odd bank selector. So, for example, when user wants to take
+ * the Event Num of 15 for odd counters (by referring to the user manual), then
+ * 128 needs to be added to 15 as the input for the event config, i.e., 143 (0x8F)
+ * to be used.
+ *
+ * Some newer cores have even more events, in which case the user can use raw
+ * events 0-511, where 0-255 are for the events of even counters, and 256-511
+ * are for odd counters, so bit 8 is used to indicate the even/odd bank selector.
  */
 static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 {
+	/* currently most cores have 7-bit event numbers */
 	unsigned int raw_id = config & 0xff;
 	unsigned int base_id = raw_id & 0x7f;
 
-	raw_event.event_id = base_id;
-
 	switch (current_cpu_type()) {
 	case CPU_24K:
 		if (IS_BOTH_COUNTERS_24K_EVENT(base_id))
@@ -1485,6 +1491,19 @@ static const struct mips_perf_event *mip
 		raw_event.range = P;
 #endif
 		break;
+	case CPU_P5600:
+		/* 8-bit event numbers */
+		raw_id = config & 0x1ff;
+		base_id = raw_id & 0xff;
+		if (IS_BOTH_COUNTERS_P5600_EVENT(base_id))
+			raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+		else
+			raw_event.cntr_mask =
+				raw_id > 255 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+		raw_event.range = P;
+#endif
+		break;
 	case CPU_1004K:
 		if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
 			raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1523,6 +1542,8 @@ static const struct mips_perf_event *mip
 				raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
 	}
 
+	raw_event.event_id = base_id;
+
 	return &raw_event;
 }
 
@@ -1633,6 +1654,11 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
+	case CPU_P5600:
+		mipspmu.name = "mips/P5600";
+		mipspmu.general_event_map = &mipsxxcore_event_map2;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+		break;
 	case CPU_1004K:
 		mipspmu.name = "mips/1004K";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/pm-cps.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/pm-cps.c
--- linux-libre-3.16-gnu/arch/mips/kernel/pm-cps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/pm-cps.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,8 +149,12 @@ int cps_pm_enter_state(enum cps_pm_state
 
 	/* Setup the VPE to run mips_cps_pm_restore when started again */
 	if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+		/* Power gating relies upon CPS SMP */
+		if (!mips_cps_smp_in_use())
+			return -EINVAL;
+
 		core_cfg = &mips_cps_core_bootcfg[core];
-		vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id];
+		vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(&current_cpu_data)];
 		vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
 		vpe_cfg->gp = (unsigned long)current_thread_info();
 		vpe_cfg->sp = 0;
@@ -376,6 +380,10 @@ static void * __init cps_gen_entry_code(
 	memset(relocs, 0, sizeof(relocs));
 
 	if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+		/* Power gating relies upon CPS SMP */
+		if (!mips_cps_smp_in_use())
+			goto out_err;
+
 		/*
 		 * Save CPU state. Note the non-standard calling convention
 		 * with the return address placed in v0 to avoid clobbering
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/proc.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/proc.c
--- linux-libre-3.16-gnu/arch/mips/kernel/proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,6 +113,7 @@ static int show_cpuinfo(struct seq_file
 	if (cpu_has_vz)		seq_printf(m, "%s", " vz");
 	if (cpu_has_msa)	seq_printf(m, "%s", " msa");
 	if (cpu_has_eva)	seq_printf(m, "%s", " eva");
+	if (cpu_has_htw)	seq_printf(m, "%s", " htw");
 	seq_printf(m, "\n");
 
 	if (cpu_has_mmips) {
@@ -123,6 +124,7 @@ static int show_cpuinfo(struct seq_file
 		      cpu_data[n].srsets);
 	seq_printf(m, "kscratch registers\t: %d\n",
 		      hweight8(cpu_data[n].kscratch_mask));
+	seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
 	seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/process.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/process.c
--- linux-libre-3.16-gnu/arch/mips/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/mman.h>
 #include <linux/personality.h>
 #include <linux/sys.h>
-#include <linux/user.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
@@ -36,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
@@ -66,6 +66,7 @@ void start_thread(struct pt_regs * regs,
 	clear_used_math();
 	clear_fpu_owner();
 	init_dsp();
+	clear_thread_flag(TIF_USEDMSA);
 	clear_thread_flag(TIF_MSA_CTX_LIVE);
 	disable_msa();
 	regs->cp0_epc = pc;
@@ -141,6 +142,8 @@ int copy_thread(unsigned long clone_flag
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
+	clear_tsk_thread_flag(p, TIF_USEDMSA);
+	clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 	clear_tsk_thread_flag(p, TIF_FPUBOUND);
@@ -152,61 +155,6 @@ int copy_thread(unsigned long clone_flag
 	return 0;
 }
 
-/* Fill in the fpu structure for a core dump.. */
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
-
-	memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
-	       sizeof(current->thread.fpu.fcr31));
-
-	return 1;
-}
-
-void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < EF_R0; i++)
-		gp[i] = 0;
-	gp[EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		gp[EF_R0 + i] = regs->regs[i];
-	gp[EF_R26] = 0;
-	gp[EF_R27] = 0;
-	gp[EF_LO] = regs->lo;
-	gp[EF_HI] = regs->hi;
-	gp[EF_CP0_EPC] = regs->cp0_epc;
-	gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
-	gp[EF_CP0_STATUS] = regs->cp0_status;
-	gp[EF_CP0_CAUSE] = regs->cp0_cause;
-#ifdef EF_UNUSED0
-	gp[EF_UNUSED0] = 0;
-#endif
-}
-
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-	elf_dump_regs(*regs, task_pt_regs(tsk));
-	return 1;
-}
-
-int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
-
-	memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
-	       sizeof(t->thread.fpu.fcr31));
-
-	return 1;
-}
-
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
 unsigned long __stack_chk_guard __read_mostly;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/ptrace32.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/ptrace32.c
--- linux-libre-3.16-gnu/arch/mips/kernel/ptrace32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/ptrace32.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 
 #include <asm/cpu.h>
@@ -32,6 +31,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
@@ -129,7 +129,7 @@ long compat_arch_ptrace(struct task_stru
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
@@ -256,11 +256,13 @@ long compat_arch_ptrace(struct task_stru
 		}
 
 	case PTRACE_GETREGS:
-		ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_getregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_SETREGS:
-		ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_setregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_GETFPREGS:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/ptrace.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/ptrace.c
--- linux-libre-3.16-gnu/arch/mips/kernel/ptrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/ptrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 #include <linux/tracehook.h>
 #include <linux/audit.h>
@@ -63,7 +62,7 @@ void ptrace_disable(struct task_struct *
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
  */
-int ptrace_getregs(struct task_struct *child, __s64 __user *data)
+int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -74,13 +73,13 @@ int ptrace_getregs(struct task_struct *c
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__put_user((long)regs->regs[i], data + i);
-	__put_user((long)regs->lo, data + EF_LO - EF_R0);
-	__put_user((long)regs->hi, data + EF_HI - EF_R0);
-	__put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
-	__put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
-	__put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
-	__put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+		__put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__put_user((long)regs->lo, (__s64 __user *)&data->lo);
+	__put_user((long)regs->hi, (__s64 __user *)&data->hi);
+	__put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
+	__put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
+	__put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
+	__put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
 
 	return 0;
 }
@@ -90,7 +89,7 @@ int ptrace_getregs(struct task_struct *c
  * the 64-bit format.  On a 32-bit kernel only the lower order half
  * (according to endianness) will be used.
  */
-int ptrace_setregs(struct task_struct *child, __s64 __user *data)
+int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -101,10 +100,10 @@ int ptrace_setregs(struct task_struct *c
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__get_user(regs->regs[i], data + i);
-	__get_user(regs->lo, data + EF_LO - EF_R0);
-	__get_user(regs->hi, data + EF_HI - EF_R0);
-	__get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+		__get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__get_user(regs->lo, (__s64 __user *)&data->lo);
+	__get_user(regs->hi, (__s64 __user *)&data->hi);
+	__get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
 
 	/* badvaddr, status, and cause may not be written.  */
 
@@ -129,7 +128,7 @@ int ptrace_getfpregs(struct task_struct
 	}
 
 	__put_user(child->thread.fpu.fcr31, data + 64);
-	__put_user(current_cpu_data.fpu_id, data + 65);
+	__put_user(boot_cpu_data.fpu_id, data + 65);
 
 	return 0;
 }
@@ -151,6 +150,7 @@ int ptrace_setfpregs(struct task_struct
 	}
 
 	__get_user(child->thread.fpu.fcr31, data + 64);
+	child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
 	/* FIR may not be written.  */
 
@@ -246,36 +246,160 @@ int ptrace_set_watch_regs(struct task_st
 
 /* regset get/set implementations */
 
-static int gpr_get(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
 {
 	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG] = {};
+	unsigned i;
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   regs, 0, sizeof(*regs));
+	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS32_EF_R0];
+	}
+
+	uregs[MIPS32_EF_LO] = regs->lo;
+	uregs[MIPS32_EF_HI] = regs->hi;
+	uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
 }
 
-static int gpr_set(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
 {
-	struct pt_regs newregs;
-	int ret;
+	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
 
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &newregs,
-				 0, sizeof(newregs));
-	if (ret)
-		return ret;
+	start = pos / sizeof(u32);
+	num_regs = count / sizeof(u32);
 
-	*task_pt_regs(target) = newregs;
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		/*
+		 * Cast all values to signed here so that if this is a 64-bit
+		 * kernel, the supplied 32-bit values will be sign extended.
+		 */
+		switch (i) {
+		case MIPS32_EF_R1 ... MIPS32_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS32_EF_R28 ... MIPS32_EF_R31:
+			regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+			break;
+		case MIPS32_EF_LO:
+			regs->lo = (s32)uregs[i];
+			break;
+		case MIPS32_EF_HI:
+			regs->hi = (s32)uregs[i];
+			break;
+		case MIPS32_EF_CP0_EPC:
+			regs->cp0_epc = (s32)uregs[i];
+			break;
+		}
+	}
 
 	return 0;
 }
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS64_EF_R0];
+	}
+
+	uregs[MIPS64_EF_LO] = regs->lo;
+	uregs[MIPS64_EF_HI] = regs->hi;
+	uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
+}
+
+static int gpr64_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u64);
+	num_regs = count / sizeof(u64);
+
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		switch (i) {
+		case MIPS64_EF_R1 ... MIPS64_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS64_EF_R28 ... MIPS64_EF_R31:
+			regs->regs[i - MIPS64_EF_R0] = uregs[i];
+			break;
+		case MIPS64_EF_LO:
+			regs->lo = uregs[i];
+			break;
+		case MIPS64_EF_HI:
+			regs->hi = uregs[i];
+			break;
+		case MIPS64_EF_CP0_EPC:
+			regs->cp0_epc = uregs[i];
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_64BIT */
+
 static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -337,14 +461,16 @@ enum mips_regset {
 	REGSET_FPR,
 };
 
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
 static const struct user_regset mips_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned int),
 		.align		= sizeof(unsigned int),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr32_get,
+		.set		= gpr32_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -364,14 +490,18 @@ static const struct user_regset_view use
 	.n		= ARRAY_SIZE(mips_regsets),
 };
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
 static const struct user_regset mips64_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned long),
 		.align		= sizeof(unsigned long),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr64_get,
+		.set		= gpr64_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -384,25 +514,26 @@ static const struct user_regset mips64_r
 };
 
 static const struct user_regset_view user_mips64_view = {
-	.name		= "mips",
+	.name		= "mips64",
 	.e_machine	= ELF_ARCH,
 	.ei_osabi	= ELF_OSABI,
 	.regsets	= mips64_regsets,
-	.n		= ARRAY_SIZE(mips_regsets),
+	.n		= ARRAY_SIZE(mips64_regsets),
 };
 
+#endif /* CONFIG_64BIT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_32BIT
 	return &user_mips_view;
-#endif
-
+#else
 #ifdef CONFIG_MIPS32_O32
-		if (test_thread_flag(TIF_32BIT_REGS))
-			return &user_mips_view;
+	if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+		return &user_mips_view;
 #endif
-
 	return &user_mips64_view;
+#endif
 }
 
 long arch_ptrace(struct task_struct *child, long request,
@@ -480,7 +611,7 @@ long arch_ptrace(struct task_struct *chi
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
@@ -565,7 +696,7 @@ long arch_ptrace(struct task_struct *chi
 			break;
 #endif
 		case FPC_CSR:
-			child->thread.fpu.fcr31 = data;
+			child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/r4k_switch.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/r4k_switch.S
--- linux-libre-3.16-gnu/arch/mips/kernel/r4k_switch.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/r4k_switch.S	2014-09-28 17:29:07.000000000 -0400
@@ -64,8 +64,10 @@
 	/* Check whether we're saving scalar or vector context. */
 	bgtz	a3, 1f
 
-	/* Save 128b MSA vector context. */
+	/* Save 128b MSA vector context + scalar FP control & status. */
+	cfc1	t1, fcr31
 	msa_save_all	a0
+	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
 1:	/* Save 32b/64b scalar FP context. */
@@ -142,6 +144,11 @@ LEAF(_restore_msa)
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_init_msa_upper)
+	msa_init_all_upper
+	jr	ra
+	END(_init_msa_upper)
+
 #endif
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/rtlx-cmp.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/rtlx-cmp.c
--- linux-libre-3.16-gnu/arch/mips/kernel/rtlx-cmp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/rtlx-cmp.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,6 +77,9 @@ int __init rtlx_module_init(void)
 		dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
 				    "%s%d", RTLX_MODULE_NAME, i);
 		if (IS_ERR(dev)) {
+			while (i--)
+				device_destroy(mt_class, MKDEV(major, i));
+
 			err = PTR_ERR(dev);
 			goto out_chrdev;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/rtlx-mt.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/rtlx-mt.c
--- linux-libre-3.16-gnu/arch/mips/kernel/rtlx-mt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/rtlx-mt.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,6 +103,9 @@ int __init rtlx_module_init(void)
 		dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
 				    "%s%d", RTLX_MODULE_NAME, i);
 		if (IS_ERR(dev)) {
+			while (i--)
+				device_destroy(mt_class, MKDEV(major, i));
+
 			err = PTR_ERR(dev);
 			goto out_chrdev;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/scall32-o32.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall32-o32.S
--- linux-libre-3.16-gnu/arch/mips/kernel/scall32-o32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall32-o32.S	2014-09-28 17:29:07.000000000 -0400
@@ -67,8 +67,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 
 	/*
 	 * Ok, copy the args from the luser stack to the kernel stack.
-	 * t3 is the precomputed number of instruction bytes needed to
-	 * load or store arguments 6-8.
 	 */
 
 	.set    push
@@ -495,8 +493,8 @@ EXPORT(sys_call_table)
 	PTR	sys_tgkill
 	PTR	sys_utimes
 	PTR	sys_mbind
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	sys_get_mempolicy
+	PTR	sys_set_mempolicy		/* 4270 */
 	PTR	sys_mq_open
 	PTR	sys_mq_unlink
 	PTR	sys_mq_timedsend
@@ -578,3 +576,6 @@ EXPORT(sys_call_table)
 	PTR	sys_sched_setattr
 	PTR	sys_sched_getattr		/* 4350 */
 	PTR	sys_renameat2
+	PTR	sys_seccomp
+	PTR	sys_getrandom
+	PTR	sys_memfd_create
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/scall64-64.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-64.S
--- linux-libre-3.16-gnu/arch/mips/kernel/scall64-64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-64.S	2014-09-28 17:29:07.000000000 -0400
@@ -347,8 +347,8 @@ EXPORT(sys_call_table)
 	PTR	sys_tgkill			/* 5225 */
 	PTR	sys_utimes
 	PTR	sys_mbind
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* sys_set_mempolicy */
+	PTR	sys_get_mempolicy
+	PTR	sys_set_mempolicy
 	PTR	sys_mq_open			/* 5230 */
 	PTR	sys_mq_unlink
 	PTR	sys_mq_timedsend
@@ -431,4 +431,7 @@ EXPORT(sys_call_table)
 	PTR	sys_sched_setattr
 	PTR	sys_sched_getattr		/* 5310 */
 	PTR	sys_renameat2
+	PTR	sys_seccomp
+	PTR	sys_getrandom
+	PTR	sys_memfd_create
 	.size	sys_call_table,.-sys_call_table
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/scall64-n32.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-n32.S
--- linux-libre-3.16-gnu/arch/mips/kernel/scall64-n32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-n32.S	2014-09-28 17:29:07.000000000 -0400
@@ -162,7 +162,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_getpeername
 	PTR	sys_socketpair
 	PTR	compat_sys_setsockopt
-	PTR	sys_getsockopt
+	PTR	compat_sys_getsockopt
 	PTR	__sys_clone			/* 6055 */
 	PTR	__sys_fork
 	PTR	compat_sys_execve
@@ -339,9 +339,9 @@ EXPORT(sysn32_call_table)
 	PTR	compat_sys_clock_nanosleep
 	PTR	sys_tgkill
 	PTR	compat_sys_utimes		/* 6230 */
-	PTR	sys_ni_syscall			/* sys_mbind */
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* sys_set_mempolicy */
+	PTR	compat_sys_mbind
+	PTR	compat_sys_get_mempolicy
+	PTR	compat_sys_set_mempolicy
 	PTR	compat_sys_mq_open
 	PTR	sys_mq_unlink			/* 6235 */
 	PTR	compat_sys_mq_timedsend
@@ -358,7 +358,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch
 	PTR	sys_inotify_rm_watch
-	PTR	sys_migrate_pages		/* 6250 */
+	PTR	compat_sys_migrate_pages	/* 6250 */
 	PTR	sys_openat
 	PTR	sys_mkdirat
 	PTR	sys_mknodat
@@ -379,7 +379,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_sync_file_range
 	PTR	sys_tee
 	PTR	compat_sys_vmsplice		/* 6270 */
-	PTR	sys_move_pages
+	PTR	compat_sys_move_pages
 	PTR	compat_sys_set_robust_list
 	PTR	compat_sys_get_robust_list
 	PTR	compat_sys_kexec_load
@@ -424,4 +424,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_sched_setattr
 	PTR	sys_sched_getattr
 	PTR	sys_renameat2			/* 6315 */
+	PTR	sys_seccomp
+	PTR	sys_getrandom
+	PTR	sys_memfd_create
 	.size	sysn32_call_table,.-sysn32_call_table
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/scall64-o32.S linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-o32.S
--- linux-libre-3.16-gnu/arch/mips/kernel/scall64-o32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/scall64-o32.S	2014-09-28 17:29:07.000000000 -0400
@@ -113,15 +113,19 @@ trace_a_syscall:
 	move	s0, t2			# Save syscall pointer
 	move	a0, sp
 	/*
-	 * syscall number is in v0 unless we called syscall(__NR_###)
+	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
 	 * where the real syscall number is in a0
 	 * note: NR_syscall is the first O32 syscall but the macro is
 	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
 	 * therefore __NR_O32_Linux is used (4000)
 	 */
-	addiu	a1, v0,  __NR_O32_Linux
-	bnez	v0, 1f /* __NR_syscall at offset 0 */
-	lw	a1, PT_R4(sp)
+	.set	push
+	.set	reorder
+	subu	t1, v0,  __NR_O32_Linux
+	move	a1, v0
+	bnez	t1, 1f /* __NR_syscall at offset 0 */
+	lw	a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
+	.set	pop
 
 1:	jal	syscall_trace_enter
 
@@ -473,9 +477,9 @@ EXPORT(sys32_call_table)
 	PTR	compat_sys_clock_nanosleep	/* 4265 */
 	PTR	sys_tgkill
 	PTR	compat_sys_utimes
-	PTR	sys_ni_syscall			/* sys_mbind */
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	compat_sys_mbind
+	PTR	compat_sys_get_mempolicy
+	PTR	compat_sys_set_mempolicy	/* 4270 */
 	PTR	compat_sys_mq_open
 	PTR	sys_mq_unlink
 	PTR	compat_sys_mq_timedsend
@@ -492,7 +496,7 @@ EXPORT(sys32_call_table)
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch		/* 4285 */
 	PTR	sys_inotify_rm_watch
-	PTR	sys_migrate_pages
+	PTR	compat_sys_migrate_pages
 	PTR	compat_sys_openat
 	PTR	sys_mkdirat
 	PTR	sys_mknodat			/* 4290 */
@@ -557,4 +561,7 @@ EXPORT(sys32_call_table)
 	PTR	sys_sched_setattr
 	PTR	sys_sched_getattr		/* 4350 */
 	PTR	sys_renameat2
+	PTR	sys_seccomp
+	PTR	sys_getrandom
+	PTR	sys_memfd_create
 	.size	sys32_call_table,.-sys32_call_table
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/setup.c
--- linux-libre-3.16-gnu/arch/mips/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(
  * Initialize the bootmem allocator. It also setup initrd related data
  * if needed.
  */
-#ifdef CONFIG_SGI_IP27
+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
 
 static void __init bootmem_init(void)
 {
@@ -729,6 +729,25 @@ static void __init resource_init(void)
 	}
 }
 
+#ifdef CONFIG_SMP
+static void __init prefill_possible_map(void)
+{
+	int i, possible = num_possible_cpus();
+
+	if (possible > nr_cpu_ids)
+		possible = nr_cpu_ids;
+
+	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;
+}
+#else
+static inline void prefill_possible_map(void) {}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
 	cpu_probe();
@@ -752,6 +771,7 @@ void __init setup_arch(char **cmdline_p)
 
 	resource_init();
 	plat_smp_setup();
+	prefill_possible_map();
 
 	cpu_cache_init();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/signal32.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal32.c
--- linux-libre-3.16-gnu/arch/mips/kernel/signal32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal32.c	2014-09-28 17:29:07.000000000 -0400
@@ -490,21 +490,21 @@ badframe:
 	force_sig(SIGSEGV, current);
 }
 
-static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
-			  struct pt_regs *regs, int signr, sigset_t *set)
+static int setup_frame_32(void *sig_return, struct ksignal *ksig,
+			  struct pt_regs *regs, sigset_t *set)
 {
 	struct sigframe32 __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= setup_sigcontext32(regs, &frame->sf_sc);
 	err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Arguments to signal handler:
@@ -516,37 +516,32 @@ static int setup_frame_32(void *sig_retu
 	 * $25 and c0_epc point to the signal handler, $29 points to the
 	 * struct sigframe.
 	 */
-	regs->regs[ 4] = signr;
+	regs->regs[ 4] = ksig->sig;
 	regs->regs[ 5] = 0;
 	regs->regs[ 6] = (unsigned long) &frame->sf_sc;
 	regs->regs[29] = (unsigned long) frame;
 	regs->regs[31] = (unsigned long) sig_return;
-	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 
 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
-			     struct pt_regs *regs, int signr, sigset_t *set,
-			     siginfo_t *info)
+static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
+			     struct pt_regs *regs, sigset_t *set)
 {
 	struct rt_sigframe32 __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
-	err |= copy_siginfo_to_user32(&frame->rs_info, info);
+	err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
 
 	/* Create the ucontext.	 */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -556,7 +551,7 @@ static int setup_rt_frame_32(void *sig_r
 	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Arguments to signal handler:
@@ -568,22 +563,18 @@ static int setup_rt_frame_32(void *sig_r
 	 * $25 and c0_epc point to the signal handler, $29 points to
 	 * the struct rt_sigframe32.
 	 */
-	regs->regs[ 4] = signr;
+	regs->regs[ 4] = ksig->sig;
 	regs->regs[ 5] = (unsigned long) &frame->rs_info;
 	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 	regs->regs[29] = (unsigned long) frame;
 	regs->regs[31] = (unsigned long) sig_return;
-	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 
 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal.c
--- linux-libre-3.16-gnu/arch/mips/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *r
 	return err;
 }
 
-void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
 			  size_t frame_size)
 {
 	unsigned long sp;
@@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigac
 	 */
 	sp -= 32;
 
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	sp = sigsp(sp, ksig);
 
 	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
 }
@@ -428,20 +426,20 @@ badframe:
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
-static int setup_frame(void *sig_return, struct k_sigaction *ka,
-		       struct pt_regs *regs, int signr, sigset_t *set)
+static int setup_frame(void *sig_return, struct ksignal *ksig,
+		       struct pt_regs *regs, sigset_t *set)
 {
 	struct sigframe __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	err |= setup_sigcontext(regs, &frame->sf_sc);
 	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Arguments to signal handler:
@@ -453,37 +451,32 @@ static int setup_frame(void *sig_return,
 	 * $25 and c0_epc point to the signal handler, $29 points to the
 	 * struct sigframe.
 	 */
-	regs->regs[ 4] = signr;
+	regs->regs[ 4] = ksig->sig;
 	regs->regs[ 5] = 0;
 	regs->regs[ 6] = (unsigned long) &frame->sf_sc;
 	regs->regs[29] = (unsigned long) frame;
 	regs->regs[31] = (unsigned long) sig_return;
-	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 
 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 #endif
 
-static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
-			  struct pt_regs *regs, int signr, sigset_t *set,
-			  siginfo_t *info)
+static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
+			  struct pt_regs *regs, sigset_t *set)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Create siginfo.  */
-	err |= copy_siginfo_to_user(&frame->rs_info, info);
+	err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
 
 	/* Create the ucontext.	 */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_retu
 	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Arguments to signal handler:
@@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_retu
 	 * $25 and c0_epc point to the signal handler, $29 points to
 	 * the struct rt_sigframe.
 	 */
-	regs->regs[ 4] = signr;
+	regs->regs[ 4] = ksig->sig;
 	regs->regs[ 5] = (unsigned long) &frame->rs_info;
 	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 	regs->regs[29] = (unsigned long) frame;
 	regs->regs[31] = (unsigned long) sig_return;
-	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 
 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
 struct mips_abi mips_abi = {
@@ -534,8 +523,7 @@ struct mips_abi mips_abi = {
 	.restart	= __NR_restart_syscall
 };
 
-static void handle_signal(unsigned long sig, siginfo_t *info,
-	struct k_sigaction *ka, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -557,7 +545,7 @@ static void handle_signal(unsigned long
 			regs->regs[2] = EINTR;
 			break;
 		case ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->regs[2] = EINTR;
 				break;
 			}
@@ -571,29 +559,23 @@ static void handle_signal(unsigned long
 		regs->regs[0] = 0;		/* Don't deal with this again.	*/
 	}
 
-	if (sig_uses_siginfo(ka))
+	if (sig_uses_siginfo(&ksig->ka))
 		ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
-					  ka, regs, sig, oldset, info);
+					  ksig, regs, oldset);
 	else
-		ret = abi->setup_frame(vdso + abi->signal_return_offset,
-				       ka, regs, sig, oldset);
-
-	if (ret)
-		return;
+		ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
+				       regs, oldset);
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 static void do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.	*/
-		handle_signal(signr, &info, &ka, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/signal-common.h linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal-common.h
--- linux-libre-3.16-gnu/arch/mips/kernel/signal-common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal-common.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@
 /*
  * Determine which stack to use..
  */
-extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
 				 size_t frame_size);
 /* Check and clear pending FPU exceptions in saved CSR */
 extern int fpcsr_pending(unsigned int __user *fpcsr);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/signal_n32.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal_n32.c
--- linux-libre-3.16-gnu/arch/mips/kernel/signal_n32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/signal_n32.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,18 +102,18 @@ badframe:
 	force_sig(SIGSEGV, current);
 }
 
-static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
-	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
+static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
+			      struct pt_regs *regs, sigset_t *set)
 {
 	struct rt_sigframe_n32 __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Create siginfo.  */
-	err |= copy_siginfo_to_user32(&frame->rs_info, info);
+	err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
 
 	/* Create the ucontext.	 */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -123,7 +123,7 @@ static int setup_rt_frame_n32(void *sig_
 	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Arguments to signal handler:
@@ -135,22 +135,18 @@ static int setup_rt_frame_n32(void *sig_
 	 * $25 and c0_epc point to the signal handler, $29 points to
 	 * the struct rt_sigframe.
 	 */
-	regs->regs[ 4] = signr;
+	regs->regs[ 4] = ksig->sig;
 	regs->regs[ 5] = (unsigned long) &frame->rs_info;
 	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 	regs->regs[29] = (unsigned long) frame;
 	regs->regs[31] = (unsigned long) sig_return;
-	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 
 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
 struct mips_abi mips_abi_n32 = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp.c
--- linux-libre-3.16-gnu/arch/mips/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,9 +59,16 @@ EXPORT_SYMBOL(smp_num_siblings);
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_sibling_map);
 
+/* representing the core map of multi-core chips of each logical CPU */
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(cpu_core_map);
+
 /* representing cpus for which sibling maps can be computed */
 static cpumask_t cpu_sibling_setup_map;
 
+/* representing cpus for which core maps can be computed */
+static cpumask_t cpu_core_setup_map;
+
 cpumask_t cpu_coherent_mask;
 
 static inline void set_cpu_sibling_map(int cpu)
@@ -72,7 +79,8 @@ static inline void set_cpu_sibling_map(i
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (cpu_data[cpu].core == cpu_data[i].core) {
+			if (cpu_data[cpu].package == cpu_data[i].package &&
+				    cpu_data[cpu].core == cpu_data[i].core) {
 				cpu_set(i, cpu_sibling_map[cpu]);
 				cpu_set(cpu, cpu_sibling_map[i]);
 			}
@@ -81,6 +89,20 @@ static inline void set_cpu_sibling_map(i
 		cpu_set(cpu, cpu_sibling_map[cpu]);
 }
 
+static inline void set_cpu_core_map(int cpu)
+{
+	int i;
+
+	cpu_set(cpu, cpu_core_setup_map);
+
+	for_each_cpu_mask(i, cpu_core_setup_map) {
+		if (cpu_data[cpu].package == cpu_data[i].package) {
+			cpu_set(i, cpu_core_map[cpu]);
+			cpu_set(cpu, cpu_core_map[i]);
+		}
+	}
+}
+
 struct plat_smp_ops *mp_ops;
 EXPORT_SYMBOL(mp_ops);
 
@@ -122,6 +144,7 @@ asmlinkage void start_secondary(void)
 	set_cpu_online(cpu, true);
 
 	set_cpu_sibling_map(cpu);
+	set_cpu_core_map(cpu);
 
 	cpu_set(cpu, cpu_callin_map);
 
@@ -175,6 +198,7 @@ void __init smp_prepare_cpus(unsigned in
 	current_thread_info()->cpu = 0;
 	mp_ops->prepare_cpus(max_cpus);
 	set_cpu_sibling_map(0);
+	set_cpu_core_map(0);
 #ifndef CONFIG_HOTPLUG_CPU
 	init_cpu_present(cpu_possible_mask);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/smp-cps.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp-cps.c
--- linux-libre-3.16-gnu/arch/mips/kernel/smp-cps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp-cps.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,13 +14,14 @@
 #include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/cacheflush.h>
+#include <asm/bcache.h>
 #include <asm/gic.h>
 #include <asm/mips-cm.h>
 #include <asm/mips-cpc.h>
 #include <asm/mips_mt.h>
 #include <asm/mipsregs.h>
 #include <asm/pm-cps.h>
+#include <asm/r4kcache.h>
 #include <asm/smp-cps.h>
 #include <asm/time.h>
 #include <asm/uasm.h>
@@ -132,8 +133,11 @@ static void __init cps_prepare_cpus(unsi
 	entry_code = (u32 *)&mips_cps_core_entry;
 	UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
 	uasm_i_addiu(&entry_code, 16, 0, cca);
-	dma_cache_wback_inv((unsigned long)&mips_cps_core_entry,
-			    (void *)entry_code - (void *)&mips_cps_core_entry);
+	blast_dcache_range((unsigned long)&mips_cps_core_entry,
+			   (unsigned long)entry_code);
+	bc_wback_inv((unsigned long)&mips_cps_core_entry,
+		     (void *)entry_code - (void *)&mips_cps_core_entry);
+	__sync();
 
 	/* Allocate core boot configuration structs */
 	mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
@@ -360,7 +364,7 @@ void play_dead(void)
 static void wait_for_sibling_halt(void *ptr_cpu)
 {
 	unsigned cpu = (unsigned)ptr_cpu;
-	unsigned vpe_id = cpu_data[cpu].vpe_id;
+	unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
 	unsigned halted;
 	unsigned long flags;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/smp-mt.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp-mt.c
--- linux-libre-3.16-gnu/arch/mips/kernel/smp-mt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/smp-mt.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,6 +288,7 @@ struct plat_smp_ops vsmp_smp_ops = {
 	.prepare_cpus		= vsmp_prepare_cpus,
 };
 
+#ifdef CONFIG_PROC_FS
 static int proc_cpuinfo_chain_call(struct notifier_block *nfb,
 	unsigned long action_unused, void *data)
 {
@@ -309,3 +310,4 @@ static int __init proc_cpuinfo_notifier_
 }
 
 subsys_initcall(proc_cpuinfo_notifier_init);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/traps.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/traps.c
--- linux-libre-3.16-gnu/arch/mips/kernel/traps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/traps.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,6 +90,7 @@ extern asmlinkage void handle_mt(void);
 extern asmlinkage void handle_dsp(void);
 extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
+extern void tlb_do_page_fault_0(void);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -1088,13 +1089,19 @@ static int default_cu2_call(struct notif
 
 static int enable_restore_fp_context(int msa)
 {
-	int err, was_fpu_owner;
+	int err, was_fpu_owner, prior_msa;
 
 	if (!used_math()) {
 		/* First time FP context user. */
+		preempt_disable();
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_init_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
+		}
+		preempt_enable();
 		if (!err)
 			set_used_math();
 		return err;
@@ -1134,10 +1141,11 @@ static int enable_restore_fp_context(int
 	 * This task is using or has previously used MSA. Thus we require
 	 * that Status.FR == 1.
 	 */
+	preempt_disable();
 	was_fpu_owner = is_fpu_owner();
-	err = own_fpu(0);
+	err = own_fpu_inatomic(0);
 	if (err)
-		return err;
+		goto out;
 
 	enable_msa();
 	write_msa_csr(current->thread.fpu.msacsr);
@@ -1146,13 +1154,42 @@ static int enable_restore_fp_context(int
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
-		return 0;
+	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+	if (!prior_msa && was_fpu_owner) {
+		_init_msa_upper();
+
+		goto out;
+	}
+
+	if (!prior_msa) {
+		/*
+		 * Restore the least significant 64b of each vector register
+		 * from the existing scalar FP context.
+		 */
+		_restore_fp(current);
+
+		/*
+		 * The task has not formerly used MSA, so clear the upper 64b
+		 * of each vector register such that it cannot see data left
+		 * behind by another task.
+		 */
+		_init_msa_upper();
+	} else {
+		/* We need to restore the vector context. */
+		restore_msa(current);
+
+		/* Restore the scalar FP control & status register */
+		if (!was_fpu_owner)
+			asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+	}
+
+out:
+	preempt_enable();
 
-	/* We need to restore the vector context. */
-	restore_msa(current);
 	return 0;
 }
 
@@ -2114,6 +2151,12 @@ void __init trap_init(void)
 		set_except_vector(15, handle_fpe);
 
 	set_except_vector(16, handle_ftlb);
+
+	if (cpu_has_rixiex) {
+		set_except_vector(19, tlb_do_page_fault_0);
+		set_except_vector(20, tlb_do_page_fault_0);
+	}
+
 	set_except_vector(21, handle_msa);
 	set_except_vector(22, handle_mdmx);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kernel/unaligned.c linux-libre-3.17-rc7-gnu/arch/mips/kernel/unaligned.c
--- linux-libre-3.16-gnu/arch/mips/kernel/unaligned.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kernel/unaligned.c	2014-09-28 17:29:07.000000000 -0400
@@ -690,7 +690,6 @@ static void emulate_load_store_insn(stru
 	case sdc1_op:
 		die_if_kernel("Unaligned FP access in kernel code", regs);
 		BUG_ON(!used_math());
-		BUG_ON(!is_fpu_owner());
 
 		lose_fpu(1);	/* Save FPU state for the emulator. */
 		res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/callback.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/callback.c
--- linux-libre-3.16-gnu/arch/mips/kvm/callback.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/callback.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Yann Le Du <ledu@kymasys.com>
+ */
+
+#include <linux/export.h>
+#include <linux/kvm_host.h>
+
+struct kvm_mips_callbacks *kvm_mips_callbacks;
+EXPORT_SYMBOL(kvm_mips_callbacks);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/commpage.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/commpage.c
--- linux-libre-3.16-gnu/arch/mips/kvm/commpage.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/commpage.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * commpage, currently used for Virtual COP0 registers.
+ * Mapped into the guest kernel @ 0x0.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+#include <linux/kvm_host.h>
+
+#include "commpage.h"
+
+void kvm_mips_commpage_init(struct kvm_vcpu *vcpu)
+{
+	struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage;
+
+	/* Specific init values for fields */
+	vcpu->arch.cop0 = &page->cop0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/commpage.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/commpage.h
--- linux-libre-3.16-gnu/arch/mips/kvm/commpage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/commpage.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: commpage: mapped into get kernel space
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#ifndef __KVM_MIPS_COMMPAGE_H__
+#define __KVM_MIPS_COMMPAGE_H__
+
+struct kvm_mips_commpage {
+	/* COP0 state is mapped into Guest kernel via commpage */
+	struct mips_coproc cop0;
+};
+
+#define KVM_MIPS_COMM_EIDI_OFFSET       0x0
+
+extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu);
+
+#endif /* __KVM_MIPS_COMMPAGE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/dyntrans.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/dyntrans.c
--- linux-libre-3.16-gnu/arch/mips/kvm/dyntrans.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/dyntrans.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: Binary Patching for privileged instructions, reduces traps.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/cacheflush.h>
+
+#include "commpage.h"
+
+#define SYNCI_TEMPLATE  0x041f0000
+#define SYNCI_BASE(x)   (((x) >> 21) & 0x1f)
+#define SYNCI_OFFSET    ((x) & 0xffff)
+
+#define LW_TEMPLATE     0x8c000000
+#define CLEAR_TEMPLATE  0x00000020
+#define SW_TEMPLATE     0xac000000
+
+int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
+			       struct kvm_vcpu *vcpu)
+{
+	int result = 0;
+	unsigned long kseg0_opc;
+	uint32_t synci_inst = 0x0;
+
+	/* Replace the CACHE instruction, with a NOP */
+	kseg0_opc =
+	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+		       (vcpu, (unsigned long) opc));
+	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
+	local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
+
+	return result;
+}
+
+/*
+ * Address based CACHE instructions are transformed into synci(s). A little
+ * heavy for just D-cache invalidates, but avoids an expensive trap
+ */
+int kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
+			    struct kvm_vcpu *vcpu)
+{
+	int result = 0;
+	unsigned long kseg0_opc;
+	uint32_t synci_inst = SYNCI_TEMPLATE, base, offset;
+
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	synci_inst |= (base << 21);
+	synci_inst |= offset;
+
+	kseg0_opc =
+	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+		       (vcpu, (unsigned long) opc));
+	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
+	local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
+
+	return result;
+}
+
+int kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	int32_t rt, rd, sel;
+	uint32_t mfc0_inst;
+	unsigned long kseg0_opc, flags;
+
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+
+	if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
+		mfc0_inst = CLEAR_TEMPLATE;
+		mfc0_inst |= ((rt & 0x1f) << 16);
+	} else {
+		mfc0_inst = LW_TEMPLATE;
+		mfc0_inst |= ((rt & 0x1f) << 16);
+		mfc0_inst |=
+		    offsetof(struct mips_coproc,
+			     reg[rd][sel]) + offsetof(struct kvm_mips_commpage,
+						      cop0);
+	}
+
+	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		kseg0_opc =
+		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+			       (vcpu, (unsigned long) opc));
+		memcpy((void *)kseg0_opc, (void *)&mfc0_inst, sizeof(uint32_t));
+		local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
+	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		memcpy((void *)opc, (void *)&mfc0_inst, sizeof(uint32_t));
+		local_flush_icache_range((unsigned long)opc,
+					 (unsigned long)opc + 32);
+		local_irq_restore(flags);
+	} else {
+		kvm_err("%s: Invalid address: %p\n", __func__, opc);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	int32_t rt, rd, sel;
+	uint32_t mtc0_inst = SW_TEMPLATE;
+	unsigned long kseg0_opc, flags;
+
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+
+	mtc0_inst |= ((rt & 0x1f) << 16);
+	mtc0_inst |=
+	    offsetof(struct mips_coproc,
+		     reg[rd][sel]) + offsetof(struct kvm_mips_commpage, cop0);
+
+	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		kseg0_opc =
+		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+			       (vcpu, (unsigned long) opc));
+		memcpy((void *)kseg0_opc, (void *)&mtc0_inst, sizeof(uint32_t));
+		local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
+	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		memcpy((void *)opc, (void *)&mtc0_inst, sizeof(uint32_t));
+		local_flush_icache_range((unsigned long)opc,
+					 (unsigned long)opc + 32);
+		local_irq_restore(flags);
+	} else {
+		kvm_err("%s: Invalid address: %p\n", __func__, opc);
+		return -EFAULT;
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/emulate.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/emulate.c
--- linux-libre-3.16-gnu/arch/mips/kvm/emulate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2319 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: Instruction/Exception emulation
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/ktime.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <linux/random.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-info.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/inst.h>
+
+#undef CONFIG_MIPS_MT
+#include <asm/r4kcache.h>
+#define CONFIG_MIPS_MT
+
+#include "opcode.h"
+#include "interrupt.h"
+#include "commpage.h"
+
+#include "trace.h"
+
+/*
+ * Compute the return address and do emulate branch simulation, if required.
+ * This function should be called only in branch delay slot active.
+ */
+unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
+	unsigned long instpc)
+{
+	unsigned int dspcontrol;
+	union mips_instruction insn;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	long epc = instpc;
+	long nextpc = KVM_INVALID_INST;
+
+	if (epc & 3)
+		goto unaligned;
+
+	/* Read the instruction */
+	insn.word = kvm_get_inst((uint32_t *) epc, vcpu);
+
+	if (insn.word == KVM_INVALID_INST)
+		return KVM_INVALID_INST;
+
+	switch (insn.i_format.opcode) {
+		/* jr and jalr are in r_format format. */
+	case spec_op:
+		switch (insn.r_format.func) {
+		case jalr_op:
+			arch->gprs[insn.r_format.rd] = epc + 8;
+			/* Fall through */
+		case jr_op:
+			nextpc = arch->gprs[insn.r_format.rs];
+			break;
+		}
+		break;
+
+		/*
+		 * This group contains:
+		 * bltz_op, bgez_op, bltzl_op, bgezl_op,
+		 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+		 */
+	case bcond_op:
+		switch (insn.i_format.rt) {
+		case bltz_op:
+		case bltzl_op:
+			if ((long)arch->gprs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bgez_op:
+		case bgezl_op:
+			if ((long)arch->gprs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bltzal_op:
+		case bltzall_op:
+			arch->gprs[31] = epc + 8;
+			if ((long)arch->gprs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bgezal_op:
+		case bgezall_op:
+			arch->gprs[31] = epc + 8;
+			if ((long)arch->gprs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+		case bposge32_op:
+			if (!cpu_has_dsp)
+				goto sigill;
+
+			dspcontrol = rddsp(0x01);
+
+			if (dspcontrol >= 32)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+		}
+		break;
+
+		/* These are unconditional and in j_format. */
+	case jal_op:
+		arch->gprs[31] = instpc + 8;
+	case j_op:
+		epc += 4;
+		epc >>= 28;
+		epc <<= 28;
+		epc |= (insn.j_format.target << 2);
+		nextpc = epc;
+		break;
+
+		/* These are conditional and in i_format. */
+	case beq_op:
+	case beql_op:
+		if (arch->gprs[insn.i_format.rs] ==
+		    arch->gprs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case bne_op:
+	case bnel_op:
+		if (arch->gprs[insn.i_format.rs] !=
+		    arch->gprs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case blez_op:		/* not really i_format */
+	case blezl_op:
+		/* rt field assumed to be zero */
+		if ((long)arch->gprs[insn.i_format.rs] <= 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case bgtz_op:
+	case bgtzl_op:
+		/* rt field assumed to be zero */
+		if ((long)arch->gprs[insn.i_format.rs] > 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+		/* And now the FPA/cp1 branch instructions. */
+	case cop1_op:
+		kvm_err("%s: unsupported cop1_op\n", __func__);
+		break;
+	}
+
+	return nextpc;
+
+unaligned:
+	kvm_err("%s: unaligned epc\n", __func__);
+	return nextpc;
+
+sigill:
+	kvm_err("%s: DSP branch but not DSP ASE\n", __func__);
+	return nextpc;
+}
+
+enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
+{
+	unsigned long branch_pc;
+	enum emulation_result er = EMULATE_DONE;
+
+	if (cause & CAUSEF_BD) {
+		branch_pc = kvm_compute_return_epc(vcpu, vcpu->arch.pc);
+		if (branch_pc == KVM_INVALID_INST) {
+			er = EMULATE_FAIL;
+		} else {
+			vcpu->arch.pc = branch_pc;
+			kvm_debug("BD update_pc(): New PC: %#lx\n",
+				  vcpu->arch.pc);
+		}
+	} else
+		vcpu->arch.pc += 4;
+
+	kvm_debug("update_pc(): New PC: %#lx\n", vcpu->arch.pc);
+
+	return er;
+}
+
+/**
+ * kvm_mips_count_disabled() - Find whether the CP0_Count timer is disabled.
+ * @vcpu:	Virtual CPU.
+ *
+ * Returns:	1 if the CP0_Count timer is disabled by either the guest
+ *		CP0_Cause.DC bit or the count_ctl.DC bit.
+ *		0 otherwise (in which case CP0_Count timer is running).
+ */
+static inline int kvm_mips_count_disabled(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	return	(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) ||
+		(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC);
+}
+
+/**
+ * kvm_mips_ktime_to_count() - Scale ktime_t to a 32-bit count.
+ *
+ * Caches the dynamic nanosecond bias in vcpu->arch.count_dyn_bias.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static uint32_t kvm_mips_ktime_to_count(struct kvm_vcpu *vcpu, ktime_t now)
+{
+	s64 now_ns, periods;
+	u64 delta;
+
+	now_ns = ktime_to_ns(now);
+	delta = now_ns + vcpu->arch.count_dyn_bias;
+
+	if (delta >= vcpu->arch.count_period) {
+		/* If delta is out of safe range the bias needs adjusting */
+		periods = div64_s64(now_ns, vcpu->arch.count_period);
+		vcpu->arch.count_dyn_bias = -periods * vcpu->arch.count_period;
+		/* Recalculate delta with new bias */
+		delta = now_ns + vcpu->arch.count_dyn_bias;
+	}
+
+	/*
+	 * We've ensured that:
+	 *   delta < count_period
+	 *
+	 * Therefore the intermediate delta*count_hz will never overflow since
+	 * at the boundary condition:
+	 *   delta = count_period
+	 *   delta = NSEC_PER_SEC * 2^32 / count_hz
+	 *   delta * count_hz = NSEC_PER_SEC * 2^32
+	 */
+	return div_u64(delta * vcpu->arch.count_hz, NSEC_PER_SEC);
+}
+
+/**
+ * kvm_mips_count_time() - Get effective current time.
+ * @vcpu:	Virtual CPU.
+ *
+ * Get effective monotonic ktime. This is usually a straightforward ktime_get(),
+ * except when the master disable bit is set in count_ctl, in which case it is
+ * count_resume, i.e. the time that the count was disabled.
+ *
+ * Returns:	Effective monotonic ktime for CP0_Count.
+ */
+static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu)
+{
+	if (unlikely(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
+		return vcpu->arch.count_resume;
+
+	return ktime_get();
+}
+
+/**
+ * kvm_mips_read_count_running() - Read the current count value as if running.
+ * @vcpu:	Virtual CPU.
+ * @now:	Kernel time to read CP0_Count at.
+ *
+ * Returns the current guest CP0_Count register at time @now and handles if the
+ * timer interrupt is pending and hasn't been handled yet.
+ *
+ * Returns:	The current value of the guest CP0_Count register.
+ */
+static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
+{
+	ktime_t expires;
+	int running;
+
+	/* Is the hrtimer pending? */
+	expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
+	if (ktime_compare(now, expires) >= 0) {
+		/*
+		 * Cancel it while we handle it so there's no chance of
+		 * interference with the timeout handler.
+		 */
+		running = hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+		/* Nothing should be waiting on the timeout */
+		kvm_mips_callbacks->queue_timer_int(vcpu);
+
+		/*
+		 * Restart the timer if it was running based on the expiry time
+		 * we read, so that we don't push it back 2 periods.
+		 */
+		if (running) {
+			expires = ktime_add_ns(expires,
+					       vcpu->arch.count_period);
+			hrtimer_start(&vcpu->arch.comparecount_timer, expires,
+				      HRTIMER_MODE_ABS);
+		}
+	}
+
+	/* Return the biased and scaled guest CP0_Count */
+	return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+}
+
+/**
+ * kvm_mips_read_count() - Read the current count value.
+ * @vcpu:	Virtual CPU.
+ *
+ * Read the current guest CP0_Count value, taking into account whether the timer
+ * is stopped.
+ *
+ * Returns:	The current guest CP0_Count value.
+ */
+uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	/* If count disabled just read static copy of count */
+	if (kvm_mips_count_disabled(vcpu))
+		return kvm_read_c0_guest_count(cop0);
+
+	return kvm_mips_read_count_running(vcpu, ktime_get());
+}
+
+/**
+ * kvm_mips_freeze_hrtimer() - Safely stop the hrtimer.
+ * @vcpu:	Virtual CPU.
+ * @count:	Output pointer for CP0_Count value at point of freeze.
+ *
+ * Freeze the hrtimer safely and return both the ktime and the CP0_Count value
+ * at the point it was frozen. It is guaranteed that any pending interrupts at
+ * the point it was frozen are handled, and none after that point.
+ *
+ * This is useful where the time/CP0_Count is needed in the calculation of the
+ * new parameters.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ *
+ * Returns:	The ktime at the point of freeze.
+ */
+static ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu,
+				       uint32_t *count)
+{
+	ktime_t now;
+
+	/* stop hrtimer before finding time */
+	hrtimer_cancel(&vcpu->arch.comparecount_timer);
+	now = ktime_get();
+
+	/* find count at this point and handle pending hrtimer */
+	*count = kvm_mips_read_count_running(vcpu, now);
+
+	return now;
+}
+
+/**
+ * kvm_mips_resume_hrtimer() - Resume hrtimer, updating expiry.
+ * @vcpu:	Virtual CPU.
+ * @now:	ktime at point of resume.
+ * @count:	CP0_Count at point of resume.
+ *
+ * Resumes the timer and updates the timer expiry based on @now and @count.
+ * This can be used in conjunction with kvm_mips_freeze_timer() when timer
+ * parameters need to be changed.
+ *
+ * It is guaranteed that a timer interrupt immediately after resume will be
+ * handled, but not if CP_Compare is exactly at @count. That case is already
+ * handled by kvm_mips_freeze_timer().
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu,
+				    ktime_t now, uint32_t count)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t compare;
+	u64 delta;
+	ktime_t expire;
+
+	/* Calculate timeout (wrap 0 to 2^32) */
+	compare = kvm_read_c0_guest_compare(cop0);
+	delta = (u64)(uint32_t)(compare - count - 1) + 1;
+	delta = div_u64(delta * NSEC_PER_SEC, vcpu->arch.count_hz);
+	expire = ktime_add_ns(now, delta);
+
+	/* Update hrtimer to use new timeout */
+	hrtimer_cancel(&vcpu->arch.comparecount_timer);
+	hrtimer_start(&vcpu->arch.comparecount_timer, expire, HRTIMER_MODE_ABS);
+}
+
+/**
+ * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
+ * @vcpu:	Virtual CPU.
+ *
+ * Recalculates and updates the expiry time of the hrtimer. This can be used
+ * after timer parameters have been altered which do not depend on the time that
+ * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
+ * kvm_mips_resume_hrtimer() are used directly).
+ *
+ * It is guaranteed that no timer interrupts will be lost in the process.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
+{
+	ktime_t now;
+	uint32_t count;
+
+	/*
+	 * freeze_hrtimer takes care of a timer interrupts <= count, and
+	 * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
+	 */
+	now = kvm_mips_freeze_hrtimer(vcpu, &count);
+	kvm_mips_resume_hrtimer(vcpu, now, count);
+}
+
+/**
+ * kvm_mips_write_count() - Modify the count and update timer.
+ * @vcpu:	Virtual CPU.
+ * @count:	Guest CP0_Count value to set.
+ *
+ * Sets the CP0_Count value and updates the timer accordingly.
+ */
+void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	ktime_t now;
+
+	/* Calculate bias */
+	now = kvm_mips_count_time(vcpu);
+	vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
+
+	if (kvm_mips_count_disabled(vcpu))
+		/* The timer's disabled, adjust the static count */
+		kvm_write_c0_guest_count(cop0, count);
+	else
+		/* Update timeout */
+		kvm_mips_resume_hrtimer(vcpu, now, count);
+}
+
+/**
+ * kvm_mips_init_count() - Initialise timer.
+ * @vcpu:	Virtual CPU.
+ *
+ * Initialise the timer to a sensible frequency, namely 100MHz, zero it, and set
+ * it going if it's enabled.
+ */
+void kvm_mips_init_count(struct kvm_vcpu *vcpu)
+{
+	/* 100 MHz */
+	vcpu->arch.count_hz = 100*1000*1000;
+	vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32,
+					  vcpu->arch.count_hz);
+	vcpu->arch.count_dyn_bias = 0;
+
+	/* Starting at 0 */
+	kvm_mips_write_count(vcpu, 0);
+}
+
+/**
+ * kvm_mips_set_count_hz() - Update the frequency of the timer.
+ * @vcpu:	Virtual CPU.
+ * @count_hz:	Frequency of CP0_Count timer in Hz.
+ *
+ * Change the frequency of the CP0_Count timer. This is done atomically so that
+ * CP0_Count is continuous and no timer interrupt is lost.
+ *
+ * Returns:	-EINVAL if @count_hz is out of range.
+ *		0 on success.
+ */
+int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int dc;
+	ktime_t now;
+	u32 count;
+
+	/* ensure the frequency is in a sensible range... */
+	if (count_hz <= 0 || count_hz > NSEC_PER_SEC)
+		return -EINVAL;
+	/* ... and has actually changed */
+	if (vcpu->arch.count_hz == count_hz)
+		return 0;
+
+	/* Safely freeze timer so we can keep it continuous */
+	dc = kvm_mips_count_disabled(vcpu);
+	if (dc) {
+		now = kvm_mips_count_time(vcpu);
+		count = kvm_read_c0_guest_count(cop0);
+	} else {
+		now = kvm_mips_freeze_hrtimer(vcpu, &count);
+	}
+
+	/* Update the frequency */
+	vcpu->arch.count_hz = count_hz;
+	vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32, count_hz);
+	vcpu->arch.count_dyn_bias = 0;
+
+	/* Calculate adjusted bias so dynamic count is unchanged */
+	vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
+
+	/* Update and resume hrtimer */
+	if (!dc)
+		kvm_mips_resume_hrtimer(vcpu, now, count);
+	return 0;
+}
+
+/**
+ * kvm_mips_write_compare() - Modify compare and update timer.
+ * @vcpu:	Virtual CPU.
+ * @compare:	New CP0_Compare value.
+ *
+ * Update CP0_Compare to a new value and update the timeout.
+ */
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	/* if unchanged, must just be an ack */
+	if (kvm_read_c0_guest_compare(cop0) == compare)
+		return;
+
+	/* Update compare */
+	kvm_write_c0_guest_compare(cop0, compare);
+
+	/* Update timeout if count enabled */
+	if (!kvm_mips_count_disabled(vcpu))
+		kvm_mips_update_hrtimer(vcpu);
+}
+
+/**
+ * kvm_mips_count_disable() - Disable count.
+ * @vcpu:	Virtual CPU.
+ *
+ * Disable the CP0_Count timer. A timer interrupt on or before the final stop
+ * time will be handled but not after.
+ *
+ * Assumes CP0_Count was previously enabled but now Guest.CP0_Cause.DC or
+ * count_ctl.DC has been set (count disabled).
+ *
+ * Returns:	The time that the timer was stopped.
+ */
+static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t count;
+	ktime_t now;
+
+	/* Stop hrtimer */
+	hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+	/* Set the static count from the dynamic count, handling pending TI */
+	now = ktime_get();
+	count = kvm_mips_read_count_running(vcpu, now);
+	kvm_write_c0_guest_count(cop0, count);
+
+	return now;
+}
+
+/**
+ * kvm_mips_count_disable_cause() - Disable count using CP0_Cause.DC.
+ * @vcpu:	Virtual CPU.
+ *
+ * Disable the CP0_Count timer and set CP0_Cause.DC. A timer interrupt on or
+ * before the final stop time will be handled if the timer isn't disabled by
+ * count_ctl.DC, but not after.
+ *
+ * Assumes CP0_Cause.DC is clear (count enabled).
+ */
+void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	kvm_set_c0_guest_cause(cop0, CAUSEF_DC);
+	if (!(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
+		kvm_mips_count_disable(vcpu);
+}
+
+/**
+ * kvm_mips_count_enable_cause() - Enable count using CP0_Cause.DC.
+ * @vcpu:	Virtual CPU.
+ *
+ * Enable the CP0_Count timer and clear CP0_Cause.DC. A timer interrupt after
+ * the start time will be handled if the timer isn't disabled by count_ctl.DC,
+ * potentially before even returning, so the caller should be careful with
+ * ordering of CP0_Cause modifications so as not to lose it.
+ *
+ * Assumes CP0_Cause.DC is set (count disabled).
+ */
+void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t count;
+
+	kvm_clear_c0_guest_cause(cop0, CAUSEF_DC);
+
+	/*
+	 * Set the dynamic count to match the static count.
+	 * This starts the hrtimer if count_ctl.DC allows it.
+	 * Otherwise it conveniently updates the biases.
+	 */
+	count = kvm_read_c0_guest_count(cop0);
+	kvm_mips_write_count(vcpu, count);
+}
+
+/**
+ * kvm_mips_set_count_ctl() - Update the count control KVM register.
+ * @vcpu:	Virtual CPU.
+ * @count_ctl:	Count control register new value.
+ *
+ * Set the count control KVM register. The timer is updated accordingly.
+ *
+ * Returns:	-EINVAL if reserved bits are set.
+ *		0 on success.
+ */
+int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	s64 changed = count_ctl ^ vcpu->arch.count_ctl;
+	s64 delta;
+	ktime_t expire, now;
+	uint32_t count, compare;
+
+	/* Only allow defined bits to be changed */
+	if (changed & ~(s64)(KVM_REG_MIPS_COUNT_CTL_DC))
+		return -EINVAL;
+
+	/* Apply new value */
+	vcpu->arch.count_ctl = count_ctl;
+
+	/* Master CP0_Count disable */
+	if (changed & KVM_REG_MIPS_COUNT_CTL_DC) {
+		/* Is CP0_Cause.DC already disabling CP0_Count? */
+		if (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC) {
+			if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)
+				/* Just record the current time */
+				vcpu->arch.count_resume = ktime_get();
+		} else if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) {
+			/* disable timer and record current time */
+			vcpu->arch.count_resume = kvm_mips_count_disable(vcpu);
+		} else {
+			/*
+			 * Calculate timeout relative to static count at resume
+			 * time (wrap 0 to 2^32).
+			 */
+			count = kvm_read_c0_guest_count(cop0);
+			compare = kvm_read_c0_guest_compare(cop0);
+			delta = (u64)(uint32_t)(compare - count - 1) + 1;
+			delta = div_u64(delta * NSEC_PER_SEC,
+					vcpu->arch.count_hz);
+			expire = ktime_add_ns(vcpu->arch.count_resume, delta);
+
+			/* Handle pending interrupt */
+			now = ktime_get();
+			if (ktime_compare(now, expire) >= 0)
+				/* Nothing should be waiting on the timeout */
+				kvm_mips_callbacks->queue_timer_int(vcpu);
+
+			/* Resume hrtimer without changing bias */
+			count = kvm_mips_read_count_running(vcpu, now);
+			kvm_mips_resume_hrtimer(vcpu, now, count);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * kvm_mips_set_count_resume() - Update the count resume KVM register.
+ * @vcpu:		Virtual CPU.
+ * @count_resume:	Count resume register new value.
+ *
+ * Set the count resume KVM register.
+ *
+ * Returns:	-EINVAL if out of valid range (0..now).
+ *		0 on success.
+ */
+int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume)
+{
+	/*
+	 * It doesn't make sense for the resume time to be in the future, as it
+	 * would be possible for the next interrupt to be more than a full
+	 * period in the future.
+	 */
+	if (count_resume < 0 || count_resume > ktime_to_ns(ktime_get()))
+		return -EINVAL;
+
+	vcpu->arch.count_resume = ns_to_ktime(count_resume);
+	return 0;
+}
+
+/**
+ * kvm_mips_count_timeout() - Push timer forward on timeout.
+ * @vcpu:	Virtual CPU.
+ *
+ * Handle an hrtimer event by push the hrtimer forward a period.
+ *
+ * Returns:	The hrtimer_restart value to return to the hrtimer subsystem.
+ */
+enum hrtimer_restart kvm_mips_count_timeout(struct kvm_vcpu *vcpu)
+{
+	/* Add the Count period to the current expiry time */
+	hrtimer_add_expires_ns(&vcpu->arch.comparecount_timer,
+			       vcpu->arch.count_period);
+	return HRTIMER_RESTART;
+}
+
+enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+
+	if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
+		kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
+			  kvm_read_c0_guest_epc(cop0));
+		kvm_clear_c0_guest_status(cop0, ST0_EXL);
+		vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
+
+	} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
+		kvm_clear_c0_guest_status(cop0, ST0_ERL);
+		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
+	} else {
+		kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
+			vcpu->arch.pc);
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
+{
+	kvm_debug("[%#lx] !!!WAIT!!! (%#lx)\n", vcpu->arch.pc,
+		  vcpu->arch.pending_exceptions);
+
+	++vcpu->stat.wait_exits;
+	trace_kvm_exit(vcpu, WAIT_EXITS);
+	if (!vcpu->arch.pending_exceptions) {
+		vcpu->arch.wait = 1;
+		kvm_vcpu_block(vcpu);
+
+		/*
+		 * We we are runnable, then definitely go off to user space to
+		 * check if any I/O interrupts are pending.
+		 */
+		if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
+			clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+			vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
+		}
+	}
+
+	return EMULATE_DONE;
+}
+
+/*
+ * XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that
+ * we can catch this, if things ever change
+ */
+enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t pc = vcpu->arch.pc;
+
+	kvm_err("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0));
+	return EMULATE_FAIL;
+}
+
+/* Write Guest TLB Entry @ Index */
+enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int index = kvm_read_c0_guest_index(cop0);
+	struct kvm_mips_tlb *tlb = NULL;
+	uint32_t pc = vcpu->arch.pc;
+
+	if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
+		kvm_debug("%s: illegal index: %d\n", __func__, index);
+		kvm_debug("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+			  pc, index, kvm_read_c0_guest_entryhi(cop0),
+			  kvm_read_c0_guest_entrylo0(cop0),
+			  kvm_read_c0_guest_entrylo1(cop0),
+			  kvm_read_c0_guest_pagemask(cop0));
+		index = (index & ~0x80000000) % KVM_MIPS_GUEST_TLB_SIZE;
+	}
+
+	tlb = &vcpu->arch.guest_tlb[index];
+	/*
+	 * Probe the shadow host TLB for the entry being overwritten, if one
+	 * matches, invalidate it
+	 */
+	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+
+	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
+	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
+	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
+	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
+
+	kvm_debug("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+		  pc, index, kvm_read_c0_guest_entryhi(cop0),
+		  kvm_read_c0_guest_entrylo0(cop0),
+		  kvm_read_c0_guest_entrylo1(cop0),
+		  kvm_read_c0_guest_pagemask(cop0));
+
+	return EMULATE_DONE;
+}
+
+/* Write Guest TLB Entry @ Random Index */
+enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_mips_tlb *tlb = NULL;
+	uint32_t pc = vcpu->arch.pc;
+	int index;
+
+	get_random_bytes(&index, sizeof(index));
+	index &= (KVM_MIPS_GUEST_TLB_SIZE - 1);
+
+	tlb = &vcpu->arch.guest_tlb[index];
+
+	/*
+	 * Probe the shadow host TLB for the entry being overwritten, if one
+	 * matches, invalidate it
+	 */
+	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+
+	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
+	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
+	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
+	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
+
+	kvm_debug("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n",
+		  pc, index, kvm_read_c0_guest_entryhi(cop0),
+		  kvm_read_c0_guest_entrylo0(cop0),
+		  kvm_read_c0_guest_entrylo1(cop0));
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	long entryhi = kvm_read_c0_guest_entryhi(cop0);
+	uint32_t pc = vcpu->arch.pc;
+	int index = -1;
+
+	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
+
+	kvm_write_c0_guest_index(cop0, index);
+
+	kvm_debug("[%#x] COP0_TLBP (entryhi: %#lx), index: %d\n", pc, entryhi,
+		  index);
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
+					   uint32_t cause, struct kvm_run *run,
+					   struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+	int32_t rt, rd, copz, sel, co_bit, op;
+	uint32_t pc = vcpu->arch.pc;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	copz = (inst >> 21) & 0x1f;
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+	co_bit = (inst >> 25) & 1;
+
+	if (co_bit) {
+		op = (inst) & 0xff;
+
+		switch (op) {
+		case tlbr_op:	/*  Read indexed TLB entry  */
+			er = kvm_mips_emul_tlbr(vcpu);
+			break;
+		case tlbwi_op:	/*  Write indexed  */
+			er = kvm_mips_emul_tlbwi(vcpu);
+			break;
+		case tlbwr_op:	/*  Write random  */
+			er = kvm_mips_emul_tlbwr(vcpu);
+			break;
+		case tlbp_op:	/* TLB Probe */
+			er = kvm_mips_emul_tlbp(vcpu);
+			break;
+		case rfe_op:
+			kvm_err("!!!COP0_RFE!!!\n");
+			break;
+		case eret_op:
+			er = kvm_mips_emul_eret(vcpu);
+			goto dont_update_pc;
+			break;
+		case wait_op:
+			er = kvm_mips_emul_wait(vcpu);
+			break;
+		}
+	} else {
+		switch (copz) {
+		case mfc_op:
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[rd][sel]++;
+#endif
+			/* Get reg */
+			if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
+				vcpu->arch.gprs[rt] = kvm_mips_read_count(vcpu);
+			} else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
+				vcpu->arch.gprs[rt] = 0x0;
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mfc0(inst, opc, vcpu);
+#endif
+			} else {
+				vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mfc0(inst, opc, vcpu);
+#endif
+			}
+
+			kvm_debug
+			    ("[%#x] MFCz[%d][%d], vcpu->arch.gprs[%d]: %#lx\n",
+			     pc, rd, sel, rt, vcpu->arch.gprs[rt]);
+
+			break;
+
+		case dmfc_op:
+			vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
+			break;
+
+		case mtc_op:
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[rd][sel]++;
+#endif
+			if ((rd == MIPS_CP0_TLB_INDEX)
+			    && (vcpu->arch.gprs[rt] >=
+				KVM_MIPS_GUEST_TLB_SIZE)) {
+				kvm_err("Invalid TLB Index: %ld",
+					vcpu->arch.gprs[rt]);
+				er = EMULATE_FAIL;
+				break;
+			}
+#define C0_EBASE_CORE_MASK 0xff
+			if ((rd == MIPS_CP0_PRID) && (sel == 1)) {
+				/* Preserve CORE number */
+				kvm_change_c0_guest_ebase(cop0,
+							  ~(C0_EBASE_CORE_MASK),
+							  vcpu->arch.gprs[rt]);
+				kvm_err("MTCz, cop0->reg[EBASE]: %#lx\n",
+					kvm_read_c0_guest_ebase(cop0));
+			} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
+				uint32_t nasid =
+					vcpu->arch.gprs[rt] & ASID_MASK;
+				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
+				    ((kvm_read_c0_guest_entryhi(cop0) &
+				      ASID_MASK) != nasid)) {
+					kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
+						kvm_read_c0_guest_entryhi(cop0)
+						& ASID_MASK,
+						vcpu->arch.gprs[rt]
+						& ASID_MASK);
+
+					/* Blow away the shadow host TLBs */
+					kvm_mips_flush_host_tlb(1);
+				}
+				kvm_write_c0_guest_entryhi(cop0,
+							   vcpu->arch.gprs[rt]);
+			}
+			/* Are we writing to COUNT */
+			else if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
+				kvm_mips_write_count(vcpu, vcpu->arch.gprs[rt]);
+				goto done;
+			} else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) {
+				kvm_debug("[%#x] MTCz, COMPARE %#lx <- %#lx\n",
+					  pc, kvm_read_c0_guest_compare(cop0),
+					  vcpu->arch.gprs[rt]);
+
+				/* If we are writing to COMPARE */
+				/* Clear pending timer interrupt, if any */
+				kvm_mips_callbacks->dequeue_timer_int(vcpu);
+				kvm_mips_write_compare(vcpu,
+						       vcpu->arch.gprs[rt]);
+			} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
+				kvm_write_c0_guest_status(cop0,
+							  vcpu->arch.gprs[rt]);
+				/*
+				 * Make sure that CU1 and NMI bits are
+				 * never set
+				 */
+				kvm_clear_c0_guest_status(cop0,
+							  (ST0_CU1 | ST0_NMI));
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mtc0(inst, opc, vcpu);
+#endif
+			} else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) {
+				uint32_t old_cause, new_cause;
+
+				old_cause = kvm_read_c0_guest_cause(cop0);
+				new_cause = vcpu->arch.gprs[rt];
+				/* Update R/W bits */
+				kvm_change_c0_guest_cause(cop0, 0x08800300,
+							  new_cause);
+				/* DC bit enabling/disabling timer? */
+				if ((old_cause ^ new_cause) & CAUSEF_DC) {
+					if (new_cause & CAUSEF_DC)
+						kvm_mips_count_disable_cause(vcpu);
+					else
+						kvm_mips_count_enable_cause(vcpu);
+				}
+			} else {
+				cop0->reg[rd][sel] = vcpu->arch.gprs[rt];
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mtc0(inst, opc, vcpu);
+#endif
+			}
+
+			kvm_debug("[%#x] MTCz, cop0->reg[%d][%d]: %#lx\n", pc,
+				  rd, sel, cop0->reg[rd][sel]);
+			break;
+
+		case dmtc_op:
+			kvm_err("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
+				vcpu->arch.pc, rt, rd, sel);
+			er = EMULATE_FAIL;
+			break;
+
+		case mfmcz_op:
+#ifdef KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[MIPS_CP0_STATUS][0]++;
+#endif
+			if (rt != 0) {
+				vcpu->arch.gprs[rt] =
+				    kvm_read_c0_guest_status(cop0);
+			}
+			/* EI */
+			if (inst & 0x20) {
+				kvm_debug("[%#lx] mfmcz_op: EI\n",
+					  vcpu->arch.pc);
+				kvm_set_c0_guest_status(cop0, ST0_IE);
+			} else {
+				kvm_debug("[%#lx] mfmcz_op: DI\n",
+					  vcpu->arch.pc);
+				kvm_clear_c0_guest_status(cop0, ST0_IE);
+			}
+
+			break;
+
+		case wrpgpr_op:
+			{
+				uint32_t css =
+				    cop0->reg[MIPS_CP0_STATUS][2] & 0xf;
+				uint32_t pss =
+				    (cop0->reg[MIPS_CP0_STATUS][2] >> 6) & 0xf;
+				/*
+				 * We don't support any shadow register sets, so
+				 * SRSCtl[PSS] == SRSCtl[CSS] = 0
+				 */
+				if (css || pss) {
+					er = EMULATE_FAIL;
+					break;
+				}
+				kvm_debug("WRPGPR[%d][%d] = %#lx\n", pss, rd,
+					  vcpu->arch.gprs[rt]);
+				vcpu->arch.gprs[rd] = vcpu->arch.gprs[rt];
+			}
+			break;
+		default:
+			kvm_err("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n",
+				vcpu->arch.pc, copz);
+			er = EMULATE_FAIL;
+			break;
+		}
+	}
+
+done:
+	/* Rollback PC only if emulation was unsuccessful */
+	if (er == EMULATE_FAIL)
+		vcpu->arch.pc = curr_pc;
+
+dont_update_pc:
+	/*
+	 * This is for special instructions whose emulation
+	 * updates the PC, so do not overwrite the PC under
+	 * any circumstances
+	 */
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
+					     struct kvm_run *run,
+					     struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DO_MMIO;
+	int32_t op, base, rt, offset;
+	uint32_t bytes;
+	void *data = run->mmio.data;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	rt = (inst >> 16) & 0x1f;
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	op = (inst >> 26) & 0x3f;
+
+	switch (op) {
+	case sb_op:
+		bytes = 1;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(u8 *) data = vcpu->arch.gprs[rt];
+		kvm_debug("OP_SB: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.host_cp0_badvaddr, vcpu->arch.gprs[rt],
+			  *(uint8_t *) data);
+
+		break;
+
+	case sw_op:
+		bytes = 4;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(uint32_t *) data = vcpu->arch.gprs[rt];
+
+		kvm_debug("[%#lx] OP_SW: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
+			  vcpu->arch.gprs[rt], *(uint32_t *) data);
+		break;
+
+	case sh_op:
+		bytes = 2;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(uint16_t *) data = vcpu->arch.gprs[rt];
+
+		kvm_debug("[%#lx] OP_SH: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
+			  vcpu->arch.gprs[rt], *(uint32_t *) data);
+		break;
+
+	default:
+		kvm_err("Store not yet supported");
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	/* Rollback PC if emulation was unsuccessful */
+	if (er == EMULATE_FAIL)
+		vcpu->arch.pc = curr_pc;
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
+					    struct kvm_run *run,
+					    struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DO_MMIO;
+	int32_t op, base, rt, offset;
+	uint32_t bytes;
+
+	rt = (inst >> 16) & 0x1f;
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	op = (inst >> 26) & 0x3f;
+
+	vcpu->arch.pending_load_cause = cause;
+	vcpu->arch.io_gpr = rt;
+
+	switch (op) {
+	case lw_op:
+		bytes = 4;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 0;
+		break;
+
+	case lh_op:
+	case lhu_op:
+		bytes = 2;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 0;
+
+		if (op == lh_op)
+			vcpu->mmio_needed = 2;
+		else
+			vcpu->mmio_needed = 1;
+
+		break;
+
+	case lbu_op:
+	case lb_op:
+		bytes = 1;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_is_write = 0;
+
+		if (op == lb_op)
+			vcpu->mmio_needed = 2;
+		else
+			vcpu->mmio_needed = 1;
+
+		break;
+
+	default:
+		kvm_err("Load not yet supported");
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	return er;
+}
+
+int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
+{
+	unsigned long offset = (va & ~PAGE_MASK);
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long pa;
+	gfn_t gfn;
+	pfn_t pfn;
+
+	gfn = va >> PAGE_SHIFT;
+
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: %#llx\n", __func__, gfn);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		return -1;
+	}
+	pfn = kvm->arch.guest_pmap[gfn];
+	pa = (pfn << PAGE_SHIFT) | offset;
+
+	kvm_debug("%s: va: %#lx, unmapped: %#x\n", __func__, va,
+		  CKSEG0ADDR(pa));
+
+	local_flush_icache_range(CKSEG0ADDR(pa), 32);
+	return 0;
+}
+
+#define MIPS_CACHE_OP_INDEX_INV         0x0
+#define MIPS_CACHE_OP_INDEX_LD_TAG      0x1
+#define MIPS_CACHE_OP_INDEX_ST_TAG      0x2
+#define MIPS_CACHE_OP_IMP               0x3
+#define MIPS_CACHE_OP_HIT_INV           0x4
+#define MIPS_CACHE_OP_FILL_WB_INV       0x5
+#define MIPS_CACHE_OP_HIT_HB            0x6
+#define MIPS_CACHE_OP_FETCH_LOCK        0x7
+
+#define MIPS_CACHE_ICACHE               0x0
+#define MIPS_CACHE_DCACHE               0x1
+#define MIPS_CACHE_SEC                  0x3
+
+enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
+					     uint32_t cause,
+					     struct kvm_run *run,
+					     struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+	int32_t offset, cache, op_inst, op, base;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long va;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	base = (inst >> 21) & 0x1f;
+	op_inst = (inst >> 16) & 0x1f;
+	offset = inst & 0xffff;
+	cache = (inst >> 16) & 0x3;
+	op = (inst >> 18) & 0x7;
+
+	va = arch->gprs[base] + offset;
+
+	kvm_debug("CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+		  cache, op, base, arch->gprs[base], offset);
+
+	/*
+	 * Treat INDEX_INV as a nop, basically issued by Linux on startup to
+	 * invalidate the caches entirely by stepping through all the
+	 * ways/indexes
+	 */
+	if (op == MIPS_CACHE_OP_INDEX_INV) {
+		kvm_debug("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+			  vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
+			  arch->gprs[base], offset);
+
+		if (cache == MIPS_CACHE_DCACHE)
+			r4k_blast_dcache();
+		else if (cache == MIPS_CACHE_ICACHE)
+			r4k_blast_icache();
+		else {
+			kvm_err("%s: unsupported CACHE INDEX operation\n",
+				__func__);
+			return EMULATE_FAIL;
+		}
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		kvm_mips_trans_cache_index(inst, opc, vcpu);
+#endif
+		goto done;
+	}
+
+	preempt_disable();
+	if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
+		if (kvm_mips_host_tlb_lookup(vcpu, va) < 0)
+			kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
+	} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
+		   KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
+		int index;
+
+		/* If an entry already exists then skip */
+		if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0)
+			goto skip_fault;
+
+		/*
+		 * If address not in the guest TLB, then give the guest a fault,
+		 * the resulting handler will do the right thing
+		 */
+		index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
+						  (kvm_read_c0_guest_entryhi
+						   (cop0) & ASID_MASK));
+
+		if (index < 0) {
+			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
+			vcpu->arch.host_cp0_badvaddr = va;
+			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
+							 vcpu);
+			preempt_enable();
+			goto dont_update_pc;
+		} else {
+			struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
+			/*
+			 * Check if the entry is valid, if not then setup a TLB
+			 * invalid exception to the guest
+			 */
+			if (!TLB_IS_VALID(*tlb, va)) {
+				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
+								run, vcpu);
+				preempt_enable();
+				goto dont_update_pc;
+			} else {
+				/*
+				 * We fault an entry from the guest tlb to the
+				 * shadow host TLB
+				 */
+				kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
+								     NULL,
+								     NULL);
+			}
+		}
+	} else {
+		kvm_err("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+			cache, op, base, arch->gprs[base], offset);
+		er = EMULATE_FAIL;
+		preempt_enable();
+		goto dont_update_pc;
+
+	}
+
+skip_fault:
+	/* XXXKYMA: Only a subset of cache ops are supported, used by Linux */
+	if (cache == MIPS_CACHE_DCACHE
+	    && (op == MIPS_CACHE_OP_FILL_WB_INV
+		|| op == MIPS_CACHE_OP_HIT_INV)) {
+		flush_dcache_line(va);
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		/*
+		 * Replace the CACHE instruction, with a SYNCI, not the same,
+		 * but avoids a trap
+		 */
+		kvm_mips_trans_cache_va(inst, opc, vcpu);
+#endif
+	} else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) {
+		flush_dcache_line(va);
+		flush_icache_line(va);
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		/* Replace the CACHE instruction, with a SYNCI */
+		kvm_mips_trans_cache_va(inst, opc, vcpu);
+#endif
+	} else {
+		kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+			cache, op, base, arch->gprs[base], offset);
+		er = EMULATE_FAIL;
+		preempt_enable();
+		goto dont_update_pc;
+	}
+
+	preempt_enable();
+
+dont_update_pc:
+	/* Rollback PC */
+	vcpu->arch.pc = curr_pc;
+done:
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
+					    struct kvm_run *run,
+					    struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t inst;
+
+	/* Fetch the instruction. */
+	if (cause & CAUSEF_BD)
+		opc += 1;
+
+	inst = kvm_get_inst(opc, vcpu);
+
+	switch (((union mips_instruction)inst).r_format.opcode) {
+	case cop0_op:
+		er = kvm_mips_emulate_CP0(inst, opc, cause, run, vcpu);
+		break;
+	case sb_op:
+	case sh_op:
+	case sw_op:
+		er = kvm_mips_emulate_store(inst, cause, run, vcpu);
+		break;
+	case lb_op:
+	case lbu_op:
+	case lhu_op:
+	case lh_op:
+	case lw_op:
+		er = kvm_mips_emulate_load(inst, cause, run, vcpu);
+		break;
+
+	case cache_op:
+		++vcpu->stat.cache_exits;
+		trace_kvm_exit(vcpu, CACHE_EXITS);
+		er = kvm_mips_emulate_cache(inst, opc, cause, run, vcpu);
+		break;
+
+	default:
+		kvm_err("Instruction emulation not supported (%p/%#x)\n", opc,
+			inst);
+		kvm_arch_vcpu_dump_regs(vcpu);
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_syscall(unsigned long cause,
+					       uint32_t *opc,
+					       struct kvm_run *run,
+					       struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering SYSCALL @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_SYSCALL << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_err("Trying to deliver SYSCALL when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
+						  uint32_t *opc,
+						  struct kvm_run *run,
+						  struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* set pc to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x0;
+
+	} else {
+		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
+						 uint32_t *opc,
+						 struct kvm_run *run,
+						 struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long entryhi =
+		(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] delivering TLB INV @ pc %#lx\n",
+			  arch->pc);
+
+		/* set pc to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
+						  uint32_t *opc,
+						  struct kvm_run *run,
+						  struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x0;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
+						 uint32_t *opc,
+						 struct kvm_run *run,
+						 struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return EMULATE_DONE;
+}
+
+/* TLBMOD: store into address matching TLB with Dirty bit off */
+enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
+					     struct kvm_run *run,
+					     struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+#ifdef DEBUG
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+	int index;
+
+	/* If address not in the guest TLB, then we are in trouble */
+	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
+	if (index < 0) {
+		/* XXXKYMA Invalidate and retry */
+		kvm_mips_host_tlb_inv(vcpu, vcpu->arch.host_cp0_badvaddr);
+		kvm_err("%s: host got TLBMOD for %#lx but entry not present in Guest TLB\n",
+		     __func__, entryhi);
+		kvm_mips_dump_guest_tlbs(vcpu);
+		kvm_mips_dump_host_tlbs();
+		return EMULATE_FAIL;
+	}
+#endif
+
+	er = kvm_mips_emulate_tlbmod(cause, opc, run, vcpu);
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
+					      uint32_t *opc,
+					      struct kvm_run *run,
+					      struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MOD @ pc %#lx\n",
+			  arch->pc);
+
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MOD @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff), (T_TLB_MOD << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_fpu_exc(unsigned long cause,
+					       uint32_t *opc,
+					       struct kvm_run *run,
+					       struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+	}
+
+	arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_COP_UNUSABLE << CAUSEB_EXCCODE));
+	kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE));
+
+	return EMULATE_DONE;
+}
+
+enum emulation_result kvm_mips_emulate_ri_exc(unsigned long cause,
+					      uint32_t *opc,
+					      struct kvm_run *run,
+					      struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering RI @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_RES_INST << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_err("Trying to deliver RI when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
+					      uint32_t *opc,
+					      struct kvm_run *run,
+					      struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering BP @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_BREAK << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_err("Trying to deliver BP when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+/* ll/sc, rdhwr, sync emulation */
+
+#define OPCODE 0xfc000000
+#define BASE   0x03e00000
+#define RT     0x001f0000
+#define OFFSET 0x0000ffff
+#define LL     0xc0000000
+#define SC     0xe0000000
+#define SPEC0  0x00000000
+#define SPEC3  0x7c000000
+#define RD     0x0000f800
+#define FUNC   0x0000003f
+#define SYNC   0x0000000f
+#define RDHWR  0x0000003b
+
+enum emulation_result kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
+					 struct kvm_run *run,
+					 struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long curr_pc;
+	uint32_t inst;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	/* Fetch the instruction. */
+	if (cause & CAUSEF_BD)
+		opc += 1;
+
+	inst = kvm_get_inst(opc, vcpu);
+
+	if (inst == KVM_INVALID_INST) {
+		kvm_err("%s: Cannot get inst @ %p\n", __func__, opc);
+		return EMULATE_FAIL;
+	}
+
+	if ((inst & OPCODE) == SPEC3 && (inst & FUNC) == RDHWR) {
+		int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
+		int rd = (inst & RD) >> 11;
+		int rt = (inst & RT) >> 16;
+		/* If usermode, check RDHWR rd is allowed by guest HWREna */
+		if (usermode && !(kvm_read_c0_guest_hwrena(cop0) & BIT(rd))) {
+			kvm_debug("RDHWR %#x disallowed by HWREna @ %p\n",
+				  rd, opc);
+			goto emulate_ri;
+		}
+		switch (rd) {
+		case 0:	/* CPU number */
+			arch->gprs[rt] = 0;
+			break;
+		case 1:	/* SYNCI length */
+			arch->gprs[rt] = min(current_cpu_data.dcache.linesz,
+					     current_cpu_data.icache.linesz);
+			break;
+		case 2:	/* Read count register */
+			arch->gprs[rt] = kvm_mips_read_count(vcpu);
+			break;
+		case 3:	/* Count register resolution */
+			switch (current_cpu_data.cputype) {
+			case CPU_20KC:
+			case CPU_25KF:
+				arch->gprs[rt] = 1;
+				break;
+			default:
+				arch->gprs[rt] = 2;
+			}
+			break;
+		case 29:
+			arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
+			break;
+
+		default:
+			kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
+			goto emulate_ri;
+		}
+	} else {
+		kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
+		goto emulate_ri;
+	}
+
+	return EMULATE_DONE;
+
+emulate_ri:
+	/*
+	 * Rollback PC (if in branch delay slot then the PC already points to
+	 * branch target), and pass the RI exception to the guest OS.
+	 */
+	vcpu->arch.pc = curr_pc;
+	return kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
+}
+
+enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
+						  struct kvm_run *run)
+{
+	unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long curr_pc;
+
+	if (run->mmio.len > sizeof(*gpr)) {
+		kvm_err("Bad MMIO length: %d", run->mmio.len);
+		er = EMULATE_FAIL;
+		goto done;
+	}
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	switch (run->mmio.len) {
+	case 4:
+		*gpr = *(int32_t *) run->mmio.data;
+		break;
+
+	case 2:
+		if (vcpu->mmio_needed == 2)
+			*gpr = *(int16_t *) run->mmio.data;
+		else
+			*gpr = *(int16_t *) run->mmio.data;
+
+		break;
+	case 1:
+		if (vcpu->mmio_needed == 2)
+			*gpr = *(int8_t *) run->mmio.data;
+		else
+			*gpr = *(u8 *) run->mmio.data;
+		break;
+	}
+
+	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
+		kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
+			  vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
+			  vcpu->mmio_needed);
+
+done:
+	return er;
+}
+
+static enum emulation_result kvm_mips_emulate_exc(unsigned long cause,
+						  uint32_t *opc,
+						  struct kvm_run *run,
+						  struct kvm_vcpu *vcpu)
+{
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (exccode << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+		kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+
+		kvm_debug("Delivering EXC %d @ pc %#lx, badVaddr: %#lx\n",
+			  exccode, kvm_read_c0_guest_epc(cop0),
+			  kvm_read_c0_guest_badvaddr(cop0));
+	} else {
+		kvm_err("Trying to deliver EXC when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_check_privilege(unsigned long cause,
+					       uint32_t *opc,
+					       struct kvm_run *run,
+					       struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+
+	int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
+
+	if (usermode) {
+		switch (exccode) {
+		case T_INT:
+		case T_SYSCALL:
+		case T_BREAK:
+		case T_RES_INST:
+			break;
+
+		case T_COP_UNUSABLE:
+			if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 0)
+				er = EMULATE_PRIV_FAIL;
+			break;
+
+		case T_TLB_MOD:
+			break;
+
+		case T_TLB_LD_MISS:
+			/*
+			 * We we are accessing Guest kernel space, then send an
+			 * address error exception to the guest
+			 */
+			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
+				kvm_debug("%s: LD MISS @ %#lx\n", __func__,
+					  badvaddr);
+				cause &= ~0xff;
+				cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE);
+				er = EMULATE_PRIV_FAIL;
+			}
+			break;
+
+		case T_TLB_ST_MISS:
+			/*
+			 * We we are accessing Guest kernel space, then send an
+			 * address error exception to the guest
+			 */
+			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
+				kvm_debug("%s: ST MISS @ %#lx\n", __func__,
+					  badvaddr);
+				cause &= ~0xff;
+				cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE);
+				er = EMULATE_PRIV_FAIL;
+			}
+			break;
+
+		case T_ADDR_ERR_ST:
+			kvm_debug("%s: address error ST @ %#lx\n", __func__,
+				  badvaddr);
+			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
+				cause &= ~0xff;
+				cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE);
+			}
+			er = EMULATE_PRIV_FAIL;
+			break;
+		case T_ADDR_ERR_LD:
+			kvm_debug("%s: address error LD @ %#lx\n", __func__,
+				  badvaddr);
+			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
+				cause &= ~0xff;
+				cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE);
+			}
+			er = EMULATE_PRIV_FAIL;
+			break;
+		default:
+			er = EMULATE_PRIV_FAIL;
+			break;
+		}
+	}
+
+	if (er == EMULATE_PRIV_FAIL)
+		kvm_mips_emulate_exc(cause, opc, run, vcpu);
+
+	return er;
+}
+
+/*
+ * User Address (UA) fault, this could happen if
+ * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
+ *     case we pass on the fault to the guest kernel and let it handle it.
+ * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
+ *     case we inject the TLB from the Guest TLB into the shadow host TLB
+ */
+enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
+					      uint32_t *opc,
+					      struct kvm_run *run,
+					      struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	unsigned long va = vcpu->arch.host_cp0_badvaddr;
+	int index;
+
+	kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx, entryhi: %#lx\n",
+		  vcpu->arch.host_cp0_badvaddr, vcpu->arch.host_cp0_entryhi);
+
+	/*
+	 * KVM would not have got the exception if this entry was valid in the
+	 * shadow host TLB. Check the Guest TLB, if the entry is not there then
+	 * send the guest an exception. The guest exc handler should then inject
+	 * an entry into the guest TLB.
+	 */
+	index = kvm_mips_guest_tlb_lookup(vcpu,
+					  (va & VPN2_MASK) |
+					  (kvm_read_c0_guest_entryhi
+					   (vcpu->arch.cop0) & ASID_MASK));
+	if (index < 0) {
+		if (exccode == T_TLB_LD_MISS) {
+			er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
+		} else if (exccode == T_TLB_ST_MISS) {
+			er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);
+		} else {
+			kvm_err("%s: invalid exc code: %d\n", __func__,
+				exccode);
+			er = EMULATE_FAIL;
+		}
+	} else {
+		struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
+
+		/*
+		 * Check if the entry is valid, if not then setup a TLB invalid
+		 * exception to the guest
+		 */
+		if (!TLB_IS_VALID(*tlb, va)) {
+			if (exccode == T_TLB_LD_MISS) {
+				er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,
+								vcpu);
+			} else if (exccode == T_TLB_ST_MISS) {
+				er = kvm_mips_emulate_tlbinv_st(cause, opc, run,
+								vcpu);
+			} else {
+				kvm_err("%s: invalid exc code: %d\n", __func__,
+					exccode);
+				er = EMULATE_FAIL;
+			}
+		} else {
+			kvm_debug("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
+				  tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
+			/*
+			 * OK we have a Guest TLB entry, now inject it into the
+			 * shadow host TLB
+			 */
+			kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
+							     NULL);
+		}
+	}
+
+	return er;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/interrupt.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/interrupt.c
--- linux-libre-3.16-gnu/arch/mips/kvm/interrupt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/interrupt.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: Interrupt delivery
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+
+#include <linux/kvm_host.h>
+
+#include "interrupt.h"
+
+void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
+{
+	set_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
+{
+	clear_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Cause bits to reflect the pending timer interrupt,
+	 * the EXC code will be set when we are actually
+	 * delivering the interrupt:
+	 */
+	kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
+
+	/* Queue up an INT exception for the core */
+	kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_TIMER);
+
+}
+
+void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu)
+{
+	kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
+	kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER);
+}
+
+void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
+			      struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+
+	/*
+	 * Cause bits to reflect the pending IO interrupt,
+	 * the EXC code will be set when we are actually
+	 * delivering the interrupt:
+	 */
+	switch (intr) {
+	case 2:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
+		/* Queue up an INT exception for the core */
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IO);
+		break;
+
+	case 3:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_1);
+		break;
+
+	case 4:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_2);
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
+				struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+
+	switch (intr) {
+	case -2:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IO);
+		break;
+
+	case -3:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_1);
+		break;
+
+	case -4:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_2);
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+/* Deliver the interrupt of the corresponding priority, if possible. */
+int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			    uint32_t cause)
+{
+	int allowed = 0;
+	uint32_t exccode;
+
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	switch (priority) {
+	case MIPS_EXC_INT_TIMER:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ5)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IO:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ0)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IPI_1:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ1)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IPI_2:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ2)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	/* Are we allowed to deliver the interrupt ??? */
+	if (allowed) {
+		if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+			/* save old pc */
+			kvm_write_c0_guest_epc(cop0, arch->pc);
+			kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+			if (cause & CAUSEF_BD)
+				kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+			else
+				kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+			kvm_debug("Delivering INT @ pc %#lx\n", arch->pc);
+
+		} else
+			kvm_err("Trying to deliver interrupt when EXL is already set\n");
+
+		kvm_change_c0_guest_cause(cop0, CAUSEF_EXCCODE,
+					  (exccode << CAUSEB_EXCCODE));
+
+		/* XXXSL Set PC to the interrupt exception entry point */
+		if (kvm_read_c0_guest_cause(cop0) & CAUSEF_IV)
+			arch->pc = KVM_GUEST_KSEG0 + 0x200;
+		else
+			arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+		clear_bit(priority, &vcpu->arch.pending_exceptions);
+	}
+
+	return allowed;
+}
+
+int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			  uint32_t cause)
+{
+	return 1;
+}
+
+void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause)
+{
+	unsigned long *pending = &vcpu->arch.pending_exceptions;
+	unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr;
+	unsigned int priority;
+
+	if (!(*pending) && !(*pending_clr))
+		return;
+
+	priority = __ffs(*pending_clr);
+	while (priority <= MIPS_EXC_MAX) {
+		if (kvm_mips_callbacks->irq_clear(vcpu, priority, cause)) {
+			if (!KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE)
+				break;
+		}
+
+		priority = find_next_bit(pending_clr,
+					 BITS_PER_BYTE * sizeof(*pending_clr),
+					 priority + 1);
+	}
+
+	priority = __ffs(*pending);
+	while (priority <= MIPS_EXC_MAX) {
+		if (kvm_mips_callbacks->irq_deliver(vcpu, priority, cause)) {
+			if (!KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE)
+				break;
+		}
+
+		priority = find_next_bit(pending,
+					 BITS_PER_BYTE * sizeof(*pending),
+					 priority + 1);
+	}
+
+}
+
+int kvm_mips_pending_timer(struct kvm_vcpu *vcpu)
+{
+	return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/interrupt.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/interrupt.h
--- linux-libre-3.16-gnu/arch/mips/kvm/interrupt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/interrupt.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: Interrupts
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+/*
+ * MIPS Exception Priorities, exceptions (including interrupts) are queued up
+ * for the guest in the order specified by their priorities
+ */
+
+#define MIPS_EXC_RESET              0
+#define MIPS_EXC_SRESET             1
+#define MIPS_EXC_DEBUG_ST           2
+#define MIPS_EXC_DEBUG              3
+#define MIPS_EXC_DDB                4
+#define MIPS_EXC_NMI                5
+#define MIPS_EXC_MCHK               6
+#define MIPS_EXC_INT_TIMER          7
+#define MIPS_EXC_INT_IO             8
+#define MIPS_EXC_EXECUTE            9
+#define MIPS_EXC_INT_IPI_1          10
+#define MIPS_EXC_INT_IPI_2          11
+#define MIPS_EXC_MAX                12
+/* XXXSL More to follow */
+
+extern char mips32_exception[], mips32_exceptionEnd[];
+extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
+
+#define C_TI        (_ULCAST_(1) << 30)
+
+#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0)
+#define KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE   (0)
+
+void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
+void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
+int kvm_mips_pending_timer(struct kvm_vcpu *vcpu);
+
+void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu);
+void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu);
+void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
+			      struct kvm_mips_interrupt *irq);
+void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
+				struct kvm_mips_interrupt *irq);
+int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			    uint32_t cause);
+int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			  uint32_t cause);
+void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_cb.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_cb.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_cb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_cb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
- * Authors: Yann Le Du <ledu@kymasys.com>
- */
-
-#include <linux/export.h>
-#include <linux/kvm_host.h>
-
-struct kvm_mips_callbacks *kvm_mips_callbacks;
-EXPORT_SYMBOL(kvm_mips_callbacks);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_locore.S linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_locore.S
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_locore.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_locore.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,613 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Main entry point for the guest, exception handling.
- *
- * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
- */
-
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/asm-offsets.h>
-
-
-#define _C_LABEL(x)     x
-#define MIPSX(name)     mips32_ ## name
-#define CALLFRAME_SIZ   32
-
-/*
- * VECTOR
- *  exception vector entrypoint
- */
-#define VECTOR(x, regmask)      \
-    .ent    _C_LABEL(x),0;      \
-    EXPORT(x);
-
-#define VECTOR_END(x)      \
-    EXPORT(x);
-
-/* Overload, Danger Will Robinson!! */
-#define PT_HOST_ASID        PT_BVADDR
-#define PT_HOST_USERLOCAL   PT_EPC
-
-#define CP0_DDATA_LO        $28,3
-#define CP0_EBASE           $15,1
-
-#define CP0_INTCTL          $12,1
-#define CP0_SRSCTL          $12,2
-#define CP0_SRSMAP          $12,3
-#define CP0_HWRENA          $7,0
-
-/* Resume Flags */
-#define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
-
-#define RESUME_GUEST            0
-#define RESUME_HOST             RESUME_FLAG_HOST
-
-/*
- * __kvm_mips_vcpu_run: entry point to the guest
- * a0: run
- * a1: vcpu
- */
-	.set	noreorder
-	.set	noat
-
-FEXPORT(__kvm_mips_vcpu_run)
-	/* k0/k1 not being used in host kernel context */
-	INT_ADDIU k1, sp, -PT_SIZE
-	LONG_S	$0, PT_R0(k1)
-	LONG_S	$1, PT_R1(k1)
-	LONG_S	$2, PT_R2(k1)
-	LONG_S	$3, PT_R3(k1)
-
-	LONG_S	$4, PT_R4(k1)
-	LONG_S	$5, PT_R5(k1)
-	LONG_S	$6, PT_R6(k1)
-	LONG_S	$7, PT_R7(k1)
-
-	LONG_S	$8,  PT_R8(k1)
-	LONG_S	$9,  PT_R9(k1)
-	LONG_S	$10, PT_R10(k1)
-	LONG_S	$11, PT_R11(k1)
-	LONG_S	$12, PT_R12(k1)
-	LONG_S	$13, PT_R13(k1)
-	LONG_S	$14, PT_R14(k1)
-	LONG_S	$15, PT_R15(k1)
-	LONG_S	$16, PT_R16(k1)
-	LONG_S	$17, PT_R17(k1)
-
-	LONG_S	$18, PT_R18(k1)
-	LONG_S	$19, PT_R19(k1)
-	LONG_S	$20, PT_R20(k1)
-	LONG_S	$21, PT_R21(k1)
-	LONG_S	$22, PT_R22(k1)
-	LONG_S	$23, PT_R23(k1)
-	LONG_S	$24, PT_R24(k1)
-	LONG_S	$25, PT_R25(k1)
-
-	/* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */
-
-	LONG_S	$28, PT_R28(k1)
-	LONG_S	$29, PT_R29(k1)
-	LONG_S	$30, PT_R30(k1)
-	LONG_S	$31, PT_R31(k1)
-
-	/* Save hi/lo */
-	mflo	v0
-	LONG_S	v0, PT_LO(k1)
-	mfhi	v1
-	LONG_S	v1, PT_HI(k1)
-
-	/* Save host status */
-	mfc0	v0, CP0_STATUS
-	LONG_S	v0, PT_STATUS(k1)
-
-	/* Save host ASID, shove it into the BVADDR location */
-	mfc0	v1, CP0_ENTRYHI
-	andi	v1, 0xff
-	LONG_S	v1, PT_HOST_ASID(k1)
-
-	/* Save DDATA_LO, will be used to store pointer to vcpu */
-	mfc0	v1, CP0_DDATA_LO
-	LONG_S	v1, PT_HOST_USERLOCAL(k1)
-
-	/* DDATA_LO has pointer to vcpu */
-	mtc0	a1, CP0_DDATA_LO
-
-	/* Offset into vcpu->arch */
-	INT_ADDIU k1, a1, VCPU_HOST_ARCH
-
-	/*
-	 * Save the host stack to VCPU, used for exception processing
-	 * when we exit from the Guest
-	 */
-	LONG_S	sp, VCPU_HOST_STACK(k1)
-
-	/* Save the kernel gp as well */
-	LONG_S	gp, VCPU_HOST_GP(k1)
-
-	/* Setup status register for running the guest in UM, interrupts are disabled */
-	li	k0, (ST0_EXL | KSU_USER | ST0_BEV)
-	mtc0	k0, CP0_STATUS
-	ehb
-
-	/* load up the new EBASE */
-	LONG_L	k0, VCPU_GUEST_EBASE(k1)
-	mtc0	k0, CP0_EBASE
-
-	/*
-	 * Now that the new EBASE has been loaded, unset BEV, set
-	 * interrupt mask as it was but make sure that timer interrupts
-	 * are enabled
-	 */
-	li	k0, (ST0_EXL | KSU_USER | ST0_IE)
-	andi	v0, v0, ST0_IM
-	or	k0, k0, v0
-	mtc0	k0, CP0_STATUS
-	ehb
-
-
-	/* Set Guest EPC */
-	LONG_L	t0, VCPU_PC(k1)
-	mtc0	t0, CP0_EPC
-
-FEXPORT(__kvm_mips_load_asid)
-	/* Set the ASID for the Guest Kernel */
-	INT_SLL	t0, t0, 1	/* with kseg0 @ 0x40000000, kernel */
-			        /* addresses shift to 0x80000000 */
-	bltz	t0, 1f		/* If kernel */
-	 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
-	INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
-1:
-	     /* t1: contains the base of the ASID array, need to get the cpu id  */
-	LONG_L	t2, TI_CPU($28)             /* smp_processor_id */
-	INT_SLL	t2, t2, 2                   /* x4 */
-	REG_ADDU t3, t1, t2
-	LONG_L	k0, (t3)
-	andi	k0, k0, 0xff
-	mtc0	k0, CP0_ENTRYHI
-	ehb
-
-	/* Disable RDHWR access */
-	mtc0	zero, CP0_HWRENA
-
-	/* Now load up the Guest Context from VCPU */
-	LONG_L	$1, VCPU_R1(k1)
-	LONG_L	$2, VCPU_R2(k1)
-	LONG_L	$3, VCPU_R3(k1)
-
-	LONG_L	$4, VCPU_R4(k1)
-	LONG_L	$5, VCPU_R5(k1)
-	LONG_L	$6, VCPU_R6(k1)
-	LONG_L	$7, VCPU_R7(k1)
-
-	LONG_L	$8, VCPU_R8(k1)
-	LONG_L	$9, VCPU_R9(k1)
-	LONG_L	$10, VCPU_R10(k1)
-	LONG_L	$11, VCPU_R11(k1)
-	LONG_L	$12, VCPU_R12(k1)
-	LONG_L	$13, VCPU_R13(k1)
-	LONG_L	$14, VCPU_R14(k1)
-	LONG_L	$15, VCPU_R15(k1)
-	LONG_L	$16, VCPU_R16(k1)
-	LONG_L	$17, VCPU_R17(k1)
-	LONG_L	$18, VCPU_R18(k1)
-	LONG_L	$19, VCPU_R19(k1)
-	LONG_L	$20, VCPU_R20(k1)
-	LONG_L	$21, VCPU_R21(k1)
-	LONG_L	$22, VCPU_R22(k1)
-	LONG_L	$23, VCPU_R23(k1)
-	LONG_L	$24, VCPU_R24(k1)
-	LONG_L	$25, VCPU_R25(k1)
-
-	/* k0/k1 loaded up later */
-
-	LONG_L	$28, VCPU_R28(k1)
-	LONG_L	$29, VCPU_R29(k1)
-	LONG_L	$30, VCPU_R30(k1)
-	LONG_L	$31, VCPU_R31(k1)
-
-	/* Restore hi/lo */
-	LONG_L	k0, VCPU_LO(k1)
-	mtlo	k0
-
-	LONG_L	k0, VCPU_HI(k1)
-	mthi	k0
-
-FEXPORT(__kvm_mips_load_k0k1)
-	/* Restore the guest's k0/k1 registers */
-	LONG_L	k0, VCPU_R26(k1)
-	LONG_L	k1, VCPU_R27(k1)
-
-	/* Jump to guest */
-	eret
-
-VECTOR(MIPSX(exception), unknown)
-/*
- * Find out what mode we came from and jump to the proper handler.
- */
-	mtc0	k0, CP0_ERROREPC	#01: Save guest k0
-	ehb				#02:
-
-	mfc0	k0, CP0_EBASE		#02: Get EBASE
-	INT_SRL	k0, k0, 10		#03: Get rid of CPUNum
-	INT_SLL	k0, k0, 10		#04
-	LONG_S	k1, 0x3000(k0)		#05: Save k1 @ offset 0x3000
-	INT_ADDIU k0, k0, 0x2000		#06: Exception handler is installed @ offset 0x2000
-	j	k0			#07: jump to the function
-	 nop				#08: branch delay slot
-VECTOR_END(MIPSX(exceptionEnd))
-.end MIPSX(exception)
-
-/*
- * Generic Guest exception handler. We end up here when the guest
- * does something that causes a trap to kernel mode.
- *
- */
-NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
-	/* Get the VCPU pointer from DDTATA_LO */
-	mfc0	k1, CP0_DDATA_LO
-	INT_ADDIU k1, k1, VCPU_HOST_ARCH
-
-	/* Start saving Guest context to VCPU */
-	LONG_S	$0, VCPU_R0(k1)
-	LONG_S	$1, VCPU_R1(k1)
-	LONG_S	$2, VCPU_R2(k1)
-	LONG_S	$3, VCPU_R3(k1)
-	LONG_S	$4, VCPU_R4(k1)
-	LONG_S	$5, VCPU_R5(k1)
-	LONG_S	$6, VCPU_R6(k1)
-	LONG_S	$7, VCPU_R7(k1)
-	LONG_S	$8, VCPU_R8(k1)
-	LONG_S	$9, VCPU_R9(k1)
-	LONG_S	$10, VCPU_R10(k1)
-	LONG_S	$11, VCPU_R11(k1)
-	LONG_S	$12, VCPU_R12(k1)
-	LONG_S	$13, VCPU_R13(k1)
-	LONG_S	$14, VCPU_R14(k1)
-	LONG_S	$15, VCPU_R15(k1)
-	LONG_S	$16, VCPU_R16(k1)
-	LONG_S	$17, VCPU_R17(k1)
-	LONG_S	$18, VCPU_R18(k1)
-	LONG_S	$19, VCPU_R19(k1)
-	LONG_S	$20, VCPU_R20(k1)
-	LONG_S	$21, VCPU_R21(k1)
-	LONG_S	$22, VCPU_R22(k1)
-	LONG_S	$23, VCPU_R23(k1)
-	LONG_S	$24, VCPU_R24(k1)
-	LONG_S	$25, VCPU_R25(k1)
-
-	/* Guest k0/k1 saved later */
-
-	LONG_S	$28, VCPU_R28(k1)
-	LONG_S	$29, VCPU_R29(k1)
-	LONG_S	$30, VCPU_R30(k1)
-	LONG_S	$31, VCPU_R31(k1)
-
-	/* We need to save hi/lo and restore them on
-	 * the way out
-	 */
-	mfhi	t0
-	LONG_S	t0, VCPU_HI(k1)
-
-	mflo	t0
-	LONG_S	t0, VCPU_LO(k1)
-
-	/* Finally save guest k0/k1 to VCPU */
-	mfc0	t0, CP0_ERROREPC
-	LONG_S	t0, VCPU_R26(k1)
-
-	/* Get GUEST k1 and save it in VCPU */
-	PTR_LI	t1, ~0x2ff
-	mfc0	t0, CP0_EBASE
-	and	t0, t0, t1
-	LONG_L	t0, 0x3000(t0)
-	LONG_S	t0, VCPU_R27(k1)
-
-	/* Now that context has been saved, we can use other registers */
-
-	/* Restore vcpu */
-	mfc0	a1, CP0_DDATA_LO
-	move	s1, a1
-
-	/* Restore run (vcpu->run) */
-	LONG_L	a0, VCPU_RUN(a1)
-	/* Save pointer to run in s0, will be saved by the compiler */
-	move	s0, a0
-
-	/* Save Host level EPC, BadVaddr and Cause to VCPU, useful to
-	 * process the exception */
-	mfc0	k0,CP0_EPC
-	LONG_S	k0, VCPU_PC(k1)
-
-	mfc0	k0, CP0_BADVADDR
-	LONG_S	k0, VCPU_HOST_CP0_BADVADDR(k1)
-
-	mfc0	k0, CP0_CAUSE
-	LONG_S	k0, VCPU_HOST_CP0_CAUSE(k1)
-
-	mfc0	k0, CP0_ENTRYHI
-	LONG_S	k0, VCPU_HOST_ENTRYHI(k1)
-
-	/* Now restore the host state just enough to run the handlers */
-
-	/* Swtich EBASE to the one used by Linux */
-	/* load up the host EBASE */
-	mfc0	v0, CP0_STATUS
-
-	.set	at
-	or	k0, v0, ST0_BEV
-	.set	noat
-
-	mtc0	k0, CP0_STATUS
-	ehb
-
-	LONG_L	k0, VCPU_HOST_EBASE(k1)
-	mtc0	k0,CP0_EBASE
-
-
-	/* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
-	.set	at
-	and	v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
-	or	v0, v0, ST0_CU0
-	.set	noat
-	mtc0	v0, CP0_STATUS
-	ehb
-
-	/* Load up host GP */
-	LONG_L	gp, VCPU_HOST_GP(k1)
-
-	/* Need a stack before we can jump to "C" */
-	LONG_L	sp, VCPU_HOST_STACK(k1)
-
-	/* Saved host state */
-	INT_ADDIU sp, sp, -PT_SIZE
-
-	/* XXXKYMA do we need to load the host ASID, maybe not because the
-	 * kernel entries are marked GLOBAL, need to verify
-	 */
-
-	/* Restore host DDATA_LO */
-	LONG_L	k0, PT_HOST_USERLOCAL(sp)
-	mtc0	k0, CP0_DDATA_LO
-
-	/* Restore RDHWR access */
-	PTR_LI	k0, 0x2000000F
-	mtc0	k0, CP0_HWRENA
-
-	/* Jump to handler */
-FEXPORT(__kvm_mips_jump_to_handler)
-	/* XXXKYMA: not sure if this is safe, how large is the stack??
-	 * Now jump to the kvm_mips_handle_exit() to see if we can deal
-	 * with this in the kernel */
-	PTR_LA	t9, kvm_mips_handle_exit
-	jalr.hb	t9
-	 INT_ADDIU sp, sp, -CALLFRAME_SIZ           /* BD Slot */
-
-	/* Return from handler Make sure interrupts are disabled */
-	di
-	ehb
-
-	/* XXXKYMA: k0/k1 could have been blown away if we processed
-	 * an exception while we were handling the exception from the
-	 * guest, reload k1
-	 */
-
-	move	k1, s1
-	INT_ADDIU k1, k1, VCPU_HOST_ARCH
-
-	/* Check return value, should tell us if we are returning to the
-	 * host (handle I/O etc)or resuming the guest
-	 */
-	andi	t0, v0, RESUME_HOST
-	bnez	t0, __kvm_mips_return_to_host
-	 nop
-
-__kvm_mips_return_to_guest:
-	/* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
-	mtc0	s1, CP0_DDATA_LO
-
-	/* Load up the Guest EBASE to minimize the window where BEV is set */
-	LONG_L	t0, VCPU_GUEST_EBASE(k1)
-
-	/* Switch EBASE back to the one used by KVM */
-	mfc0	v1, CP0_STATUS
-	.set	at
-	or	k0, v1, ST0_BEV
-	.set	noat
-	mtc0	k0, CP0_STATUS
-	ehb
-	mtc0	t0, CP0_EBASE
-
-	/* Setup status register for running guest in UM */
-	.set	at
-	or	v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
-	and	v1, v1, ~ST0_CU0
-	.set	noat
-	mtc0	v1, CP0_STATUS
-	ehb
-
-	/* Set Guest EPC */
-	LONG_L	t0, VCPU_PC(k1)
-	mtc0	t0, CP0_EPC
-
-	/* Set the ASID for the Guest Kernel */
-	INT_SLL	t0, t0, 1	/* with kseg0 @ 0x40000000, kernel */
-				/* addresses shift to 0x80000000 */
-	bltz	t0, 1f		/* If kernel */
-	 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
-	INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
-1:
-	/* t1: contains the base of the ASID array, need to get the cpu id  */
-	LONG_L	t2, TI_CPU($28)		/* smp_processor_id */
-	INT_SLL	t2, t2, 2		/* x4 */
-	REG_ADDU t3, t1, t2
-	LONG_L	k0, (t3)
-	andi	k0, k0, 0xff
-	mtc0	k0,CP0_ENTRYHI
-	ehb
-
-	/* Disable RDHWR access */
-	mtc0    zero,  CP0_HWRENA
-
-	/* load the guest context from VCPU and return */
-	LONG_L	$0, VCPU_R0(k1)
-	LONG_L	$1, VCPU_R1(k1)
-	LONG_L	$2, VCPU_R2(k1)
-	LONG_L	$3, VCPU_R3(k1)
-	LONG_L	$4, VCPU_R4(k1)
-	LONG_L	$5, VCPU_R5(k1)
-	LONG_L	$6, VCPU_R6(k1)
-	LONG_L	$7, VCPU_R7(k1)
-	LONG_L	$8, VCPU_R8(k1)
-	LONG_L	$9, VCPU_R9(k1)
-	LONG_L	$10, VCPU_R10(k1)
-	LONG_L	$11, VCPU_R11(k1)
-	LONG_L	$12, VCPU_R12(k1)
-	LONG_L	$13, VCPU_R13(k1)
-	LONG_L	$14, VCPU_R14(k1)
-	LONG_L	$15, VCPU_R15(k1)
-	LONG_L	$16, VCPU_R16(k1)
-	LONG_L	$17, VCPU_R17(k1)
-	LONG_L	$18, VCPU_R18(k1)
-	LONG_L	$19, VCPU_R19(k1)
-	LONG_L	$20, VCPU_R20(k1)
-	LONG_L	$21, VCPU_R21(k1)
-	LONG_L	$22, VCPU_R22(k1)
-	LONG_L	$23, VCPU_R23(k1)
-	LONG_L	$24, VCPU_R24(k1)
-	LONG_L	$25, VCPU_R25(k1)
-
-	/* $/k1 loaded later */
-	LONG_L	$28, VCPU_R28(k1)
-	LONG_L	$29, VCPU_R29(k1)
-	LONG_L	$30, VCPU_R30(k1)
-	LONG_L	$31, VCPU_R31(k1)
-
-FEXPORT(__kvm_mips_skip_guest_restore)
-	LONG_L	k0, VCPU_HI(k1)
-	mthi	k0
-
-	LONG_L	k0, VCPU_LO(k1)
-	mtlo	k0
-
-	LONG_L	k0, VCPU_R26(k1)
-	LONG_L	k1, VCPU_R27(k1)
-
-	eret
-
-__kvm_mips_return_to_host:
-	/* EBASE is already pointing to Linux */
-	LONG_L	k1, VCPU_HOST_STACK(k1)
-	INT_ADDIU k1,k1, -PT_SIZE
-
-	/* Restore host DDATA_LO */
-	LONG_L	k0, PT_HOST_USERLOCAL(k1)
-	mtc0	k0, CP0_DDATA_LO
-
-	/* Restore host ASID */
-	LONG_L	k0, PT_HOST_ASID(sp)
-	andi	k0, 0xff
-	mtc0	k0,CP0_ENTRYHI
-	ehb
-
-	/* Load context saved on the host stack */
-	LONG_L	$0, PT_R0(k1)
-	LONG_L	$1, PT_R1(k1)
-
-	/* r2/v0 is the return code, shift it down by 2 (arithmetic)
-	 * to recover the err code  */
-	INT_SRA	k0, v0, 2
-	move	$2, k0
-
-	LONG_L	$3, PT_R3(k1)
-	LONG_L	$4, PT_R4(k1)
-	LONG_L	$5, PT_R5(k1)
-	LONG_L	$6, PT_R6(k1)
-	LONG_L	$7, PT_R7(k1)
-	LONG_L	$8, PT_R8(k1)
-	LONG_L	$9, PT_R9(k1)
-	LONG_L	$10, PT_R10(k1)
-	LONG_L	$11, PT_R11(k1)
-	LONG_L	$12, PT_R12(k1)
-	LONG_L	$13, PT_R13(k1)
-	LONG_L	$14, PT_R14(k1)
-	LONG_L	$15, PT_R15(k1)
-	LONG_L	$16, PT_R16(k1)
-	LONG_L	$17, PT_R17(k1)
-	LONG_L	$18, PT_R18(k1)
-	LONG_L	$19, PT_R19(k1)
-	LONG_L	$20, PT_R20(k1)
-	LONG_L	$21, PT_R21(k1)
-	LONG_L	$22, PT_R22(k1)
-	LONG_L	$23, PT_R23(k1)
-	LONG_L	$24, PT_R24(k1)
-	LONG_L	$25, PT_R25(k1)
-
-	/* Host k0/k1 were not saved */
-
-	LONG_L	$28, PT_R28(k1)
-	LONG_L	$29, PT_R29(k1)
-	LONG_L	$30, PT_R30(k1)
-
-	LONG_L	k0, PT_HI(k1)
-	mthi	k0
-
-	LONG_L	k0, PT_LO(k1)
-	mtlo	k0
-
-	/* Restore RDHWR access */
-	PTR_LI	k0, 0x2000000F
-	mtc0	k0,  CP0_HWRENA
-
-
-	/* Restore RA, which is the address we will return to */
-	LONG_L  ra, PT_R31(k1)
-	j       ra
-	 nop
-
-VECTOR_END(MIPSX(GuestExceptionEnd))
-.end MIPSX(GuestException)
-
-MIPSX(exceptions):
-	####
-	##### The exception handlers.
-	#####
-	.word _C_LABEL(MIPSX(GuestException))	#  0
-	.word _C_LABEL(MIPSX(GuestException))	#  1
-	.word _C_LABEL(MIPSX(GuestException))	#  2
-	.word _C_LABEL(MIPSX(GuestException))	#  3
-	.word _C_LABEL(MIPSX(GuestException))	#  4
-	.word _C_LABEL(MIPSX(GuestException))	#  5
-	.word _C_LABEL(MIPSX(GuestException))	#  6
-	.word _C_LABEL(MIPSX(GuestException))	#  7
-	.word _C_LABEL(MIPSX(GuestException))	#  8
-	.word _C_LABEL(MIPSX(GuestException))	#  9
-	.word _C_LABEL(MIPSX(GuestException))	# 10
-	.word _C_LABEL(MIPSX(GuestException))	# 11
-	.word _C_LABEL(MIPSX(GuestException))	# 12
-	.word _C_LABEL(MIPSX(GuestException))	# 13
-	.word _C_LABEL(MIPSX(GuestException))	# 14
-	.word _C_LABEL(MIPSX(GuestException))	# 15
-	.word _C_LABEL(MIPSX(GuestException))	# 16
-	.word _C_LABEL(MIPSX(GuestException))	# 17
-	.word _C_LABEL(MIPSX(GuestException))	# 18
-	.word _C_LABEL(MIPSX(GuestException))	# 19
-	.word _C_LABEL(MIPSX(GuestException))	# 20
-	.word _C_LABEL(MIPSX(GuestException))	# 21
-	.word _C_LABEL(MIPSX(GuestException))	# 22
-	.word _C_LABEL(MIPSX(GuestException))	# 23
-	.word _C_LABEL(MIPSX(GuestException))	# 24
-	.word _C_LABEL(MIPSX(GuestException))	# 25
-	.word _C_LABEL(MIPSX(GuestException))	# 26
-	.word _C_LABEL(MIPSX(GuestException))	# 27
-	.word _C_LABEL(MIPSX(GuestException))	# 28
-	.word _C_LABEL(MIPSX(GuestException))	# 29
-	.word _C_LABEL(MIPSX(GuestException))	# 30
-	.word _C_LABEL(MIPSX(GuestException))	# 31
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1227 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * KVM/MIPS: MIPS specific KVM APIs
- *
- * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/mmu_context.h>
-
-#include <linux/kvm_host.h>
-
-#include "kvm_mips_int.h"
-#include "kvm_mips_comm.h"
-
-#define CREATE_TRACE_POINTS
-#include "trace.h"
-
-#ifndef VECTORSPACING
-#define VECTORSPACING 0x100	/* for EI/VI mode */
-#endif
-
-#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
-struct kvm_stats_debugfs_item debugfs_entries[] = {
-	{ "wait", VCPU_STAT(wait_exits) },
-	{ "cache", VCPU_STAT(cache_exits) },
-	{ "signal", VCPU_STAT(signal_exits) },
-	{ "interrupt", VCPU_STAT(int_exits) },
-	{ "cop_unsuable", VCPU_STAT(cop_unusable_exits) },
-	{ "tlbmod", VCPU_STAT(tlbmod_exits) },
-	{ "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits) },
-	{ "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits) },
-	{ "addrerr_st", VCPU_STAT(addrerr_st_exits) },
-	{ "addrerr_ld", VCPU_STAT(addrerr_ld_exits) },
-	{ "syscall", VCPU_STAT(syscall_exits) },
-	{ "resvd_inst", VCPU_STAT(resvd_inst_exits) },
-	{ "break_inst", VCPU_STAT(break_inst_exits) },
-	{ "flush_dcache", VCPU_STAT(flush_dcache_exits) },
-	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
-	{NULL}
-};
-
-static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu)
-{
-	int i;
-	for_each_possible_cpu(i) {
-		vcpu->arch.guest_kernel_asid[i] = 0;
-		vcpu->arch.guest_user_asid[i] = 0;
-	}
-	return 0;
-}
-
-/* XXXKYMA: We are simulatoring a processor that has the WII bit set in Config7, so we
- * are "runnable" if interrupts are pending
- */
-int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
-{
-	return !!(vcpu->arch.pending_exceptions);
-}
-
-int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
-{
-	return 1;
-}
-
-int kvm_arch_hardware_enable(void *garbage)
-{
-	return 0;
-}
-
-void kvm_arch_hardware_disable(void *garbage)
-{
-}
-
-int kvm_arch_hardware_setup(void)
-{
-	return 0;
-}
-
-void kvm_arch_hardware_unsetup(void)
-{
-}
-
-void kvm_arch_check_processor_compat(void *rtn)
-{
-	int *r = (int *)rtn;
-	*r = 0;
-	return;
-}
-
-static void kvm_mips_init_tlbs(struct kvm *kvm)
-{
-	unsigned long wired;
-
-	/* Add a wired entry to the TLB, it is used to map the commpage to the Guest kernel */
-	wired = read_c0_wired();
-	write_c0_wired(wired + 1);
-	mtc0_tlbw_hazard();
-	kvm->arch.commpage_tlb = wired;
-
-	kvm_debug("[%d] commpage TLB: %d\n", smp_processor_id(),
-		  kvm->arch.commpage_tlb);
-}
-
-static void kvm_mips_init_vm_percpu(void *arg)
-{
-	struct kvm *kvm = (struct kvm *)arg;
-
-	kvm_mips_init_tlbs(kvm);
-	kvm_mips_callbacks->vm_init(kvm);
-
-}
-
-int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
-{
-	if (atomic_inc_return(&kvm_mips_instance) == 1) {
-		kvm_debug("%s: 1st KVM instance, setup host TLB parameters\n",
-			  __func__);
-		on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1);
-	}
-
-
-	return 0;
-}
-
-void kvm_mips_free_vcpus(struct kvm *kvm)
-{
-	unsigned int i;
-	struct kvm_vcpu *vcpu;
-
-	/* Put the pages we reserved for the guest pmap */
-	for (i = 0; i < kvm->arch.guest_pmap_npages; i++) {
-		if (kvm->arch.guest_pmap[i] != KVM_INVALID_PAGE)
-			kvm_mips_release_pfn_clean(kvm->arch.guest_pmap[i]);
-	}
-	kfree(kvm->arch.guest_pmap);
-
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		kvm_arch_vcpu_free(vcpu);
-	}
-
-	mutex_lock(&kvm->lock);
-
-	for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
-		kvm->vcpus[i] = NULL;
-
-	atomic_set(&kvm->online_vcpus, 0);
-
-	mutex_unlock(&kvm->lock);
-}
-
-void kvm_arch_sync_events(struct kvm *kvm)
-{
-}
-
-static void kvm_mips_uninit_tlbs(void *arg)
-{
-	/* Restore wired count */
-	write_c0_wired(0);
-	mtc0_tlbw_hazard();
-	/* Clear out all the TLBs */
-	kvm_local_flush_tlb_all();
-}
-
-void kvm_arch_destroy_vm(struct kvm *kvm)
-{
-	kvm_mips_free_vcpus(kvm);
-
-	/* If this is the last instance, restore wired count */
-	if (atomic_dec_return(&kvm_mips_instance) == 0) {
-		kvm_debug("%s: last KVM instance, restoring TLB parameters\n",
-			  __func__);
-		on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1);
-	}
-}
-
-long
-kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
-			   struct kvm_memory_slot *dont)
-{
-}
-
-int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
-			    unsigned long npages)
-{
-	return 0;
-}
-
-void kvm_arch_memslots_updated(struct kvm *kvm)
-{
-}
-
-int kvm_arch_prepare_memory_region(struct kvm *kvm,
-                                struct kvm_memory_slot *memslot,
-                                struct kvm_userspace_memory_region *mem,
-                                enum kvm_mr_change change)
-{
-	return 0;
-}
-
-void kvm_arch_commit_memory_region(struct kvm *kvm,
-                                struct kvm_userspace_memory_region *mem,
-                                const struct kvm_memory_slot *old,
-                                enum kvm_mr_change change)
-{
-	unsigned long npages = 0;
-	int i, err = 0;
-
-	kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n",
-		  __func__, kvm, mem->slot, mem->guest_phys_addr,
-		  mem->memory_size, mem->userspace_addr);
-
-	/* Setup Guest PMAP table */
-	if (!kvm->arch.guest_pmap) {
-		if (mem->slot == 0)
-			npages = mem->memory_size >> PAGE_SHIFT;
-
-		if (npages) {
-			kvm->arch.guest_pmap_npages = npages;
-			kvm->arch.guest_pmap =
-			    kzalloc(npages * sizeof(unsigned long), GFP_KERNEL);
-
-			if (!kvm->arch.guest_pmap) {
-				kvm_err("Failed to allocate guest PMAP");
-				err = -ENOMEM;
-				goto out;
-			}
-
-			kvm_debug("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
-				  npages, kvm->arch.guest_pmap);
-
-			/* Now setup the page table */
-			for (i = 0; i < npages; i++) {
-				kvm->arch.guest_pmap[i] = KVM_INVALID_PAGE;
-			}
-		}
-	}
-out:
-	return;
-}
-
-void kvm_arch_flush_shadow_all(struct kvm *kvm)
-{
-}
-
-void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
-				   struct kvm_memory_slot *slot)
-{
-}
-
-void kvm_arch_flush_shadow(struct kvm *kvm)
-{
-}
-
-struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
-{
-	extern char mips32_exception[], mips32_exceptionEnd[];
-	extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
-	int err, size, offset;
-	void *gebase;
-	int i;
-
-	struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
-
-	if (!vcpu) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	err = kvm_vcpu_init(vcpu, kvm, id);
-
-	if (err)
-		goto out_free_cpu;
-
-	kvm_debug("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
-
-	/* Allocate space for host mode exception handlers that handle
-	 * guest mode exits
-	 */
-	if (cpu_has_veic || cpu_has_vint) {
-		size = 0x200 + VECTORSPACING * 64;
-	} else {
-		size = 0x4000;
-	}
-
-	/* Save Linux EBASE */
-	vcpu->arch.host_ebase = (void *)read_c0_ebase();
-
-	gebase = kzalloc(ALIGN(size, PAGE_SIZE), GFP_KERNEL);
-
-	if (!gebase) {
-		err = -ENOMEM;
-		goto out_free_cpu;
-	}
-	kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n",
-		  ALIGN(size, PAGE_SIZE), gebase);
-
-	/* Save new ebase */
-	vcpu->arch.guest_ebase = gebase;
-
-	/* Copy L1 Guest Exception handler to correct offset */
-
-	/* TLB Refill, EXL = 0 */
-	memcpy(gebase, mips32_exception,
-	       mips32_exceptionEnd - mips32_exception);
-
-	/* General Exception Entry point */
-	memcpy(gebase + 0x180, mips32_exception,
-	       mips32_exceptionEnd - mips32_exception);
-
-	/* For vectored interrupts poke the exception code @ all offsets 0-7 */
-	for (i = 0; i < 8; i++) {
-		kvm_debug("L1 Vectored handler @ %p\n",
-			  gebase + 0x200 + (i * VECTORSPACING));
-		memcpy(gebase + 0x200 + (i * VECTORSPACING), mips32_exception,
-		       mips32_exceptionEnd - mips32_exception);
-	}
-
-	/* General handler, relocate to unmapped space for sanity's sake */
-	offset = 0x2000;
-	kvm_debug("Installing KVM Exception handlers @ %p, %#x bytes\n",
-		  gebase + offset,
-		  mips32_GuestExceptionEnd - mips32_GuestException);
-
-	memcpy(gebase + offset, mips32_GuestException,
-	       mips32_GuestExceptionEnd - mips32_GuestException);
-
-	/* Invalidate the icache for these ranges */
-	local_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 mapping GVA @ 0xFFFF8000 to this page */
-	vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL);
-
-	if (!vcpu->arch.kseg0_commpage) {
-		err = -ENOMEM;
-		goto out_free_gebase;
-	}
-
-	kvm_debug("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage);
-	kvm_mips_commpage_init(vcpu);
-
-	/* Init */
-	vcpu->arch.last_sched_cpu = -1;
-
-	/* Start off the timer */
-	kvm_mips_init_count(vcpu);
-
-	return vcpu;
-
-out_free_gebase:
-	kfree(gebase);
-
-out_free_cpu:
-	kfree(vcpu);
-
-out:
-	return ERR_PTR(err);
-}
-
-void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
-{
-	hrtimer_cancel(&vcpu->arch.comparecount_timer);
-
-	kvm_vcpu_uninit(vcpu);
-
-	kvm_mips_dump_stats(vcpu);
-
-	kfree(vcpu->arch.guest_ebase);
-	kfree(vcpu->arch.kseg0_commpage);
-	kfree(vcpu);
-}
-
-void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
-{
-	kvm_arch_vcpu_free(vcpu);
-}
-
-int
-kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
-				    struct kvm_guest_debug *dbg)
-{
-	return -ENOIOCTLCMD;
-}
-
-int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	int r = 0;
-	sigset_t sigsaved;
-
-	if (vcpu->sigset_active)
-		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
-
-	if (vcpu->mmio_needed) {
-		if (!vcpu->mmio_is_write)
-			kvm_mips_complete_mmio_load(vcpu, run);
-		vcpu->mmio_needed = 0;
-	}
-
-	local_irq_disable();
-	/* Check if we have any exceptions/interrupts pending */
-	kvm_mips_deliver_interrupts(vcpu,
-				    kvm_read_c0_guest_cause(vcpu->arch.cop0));
-
-	kvm_guest_enter();
-
-	r = __kvm_mips_vcpu_run(run, vcpu);
-
-	kvm_guest_exit();
-	local_irq_enable();
-
-	if (vcpu->sigset_active)
-		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-
-	return r;
-}
-
-int
-kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
-{
-	int intr = (int)irq->irq;
-	struct kvm_vcpu *dvcpu = NULL;
-
-	if (intr == 3 || intr == -3 || intr == 4 || intr == -4)
-		kvm_debug("%s: CPU: %d, INTR: %d\n", __func__, irq->cpu,
-			  (int)intr);
-
-	if (irq->cpu == -1)
-		dvcpu = vcpu;
-	else
-		dvcpu = vcpu->kvm->vcpus[irq->cpu];
-
-	if (intr == 2 || intr == 3 || intr == 4) {
-		kvm_mips_callbacks->queue_io_int(dvcpu, irq);
-
-	} else if (intr == -2 || intr == -3 || intr == -4) {
-		kvm_mips_callbacks->dequeue_io_int(dvcpu, irq);
-	} else {
-		kvm_err("%s: invalid interrupt ioctl (%d:%d)\n", __func__,
-			irq->cpu, irq->irq);
-		return -EINVAL;
-	}
-
-	dvcpu->arch.wait = 0;
-
-	if (waitqueue_active(&dvcpu->wq)) {
-		wake_up_interruptible(&dvcpu->wq);
-	}
-
-	return 0;
-}
-
-int
-kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
-				struct kvm_mp_state *mp_state)
-{
-	return -ENOIOCTLCMD;
-}
-
-int
-kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
-				struct kvm_mp_state *mp_state)
-{
-	return -ENOIOCTLCMD;
-}
-
-static u64 kvm_mips_get_one_regs[] = {
-	KVM_REG_MIPS_R0,
-	KVM_REG_MIPS_R1,
-	KVM_REG_MIPS_R2,
-	KVM_REG_MIPS_R3,
-	KVM_REG_MIPS_R4,
-	KVM_REG_MIPS_R5,
-	KVM_REG_MIPS_R6,
-	KVM_REG_MIPS_R7,
-	KVM_REG_MIPS_R8,
-	KVM_REG_MIPS_R9,
-	KVM_REG_MIPS_R10,
-	KVM_REG_MIPS_R11,
-	KVM_REG_MIPS_R12,
-	KVM_REG_MIPS_R13,
-	KVM_REG_MIPS_R14,
-	KVM_REG_MIPS_R15,
-	KVM_REG_MIPS_R16,
-	KVM_REG_MIPS_R17,
-	KVM_REG_MIPS_R18,
-	KVM_REG_MIPS_R19,
-	KVM_REG_MIPS_R20,
-	KVM_REG_MIPS_R21,
-	KVM_REG_MIPS_R22,
-	KVM_REG_MIPS_R23,
-	KVM_REG_MIPS_R24,
-	KVM_REG_MIPS_R25,
-	KVM_REG_MIPS_R26,
-	KVM_REG_MIPS_R27,
-	KVM_REG_MIPS_R28,
-	KVM_REG_MIPS_R29,
-	KVM_REG_MIPS_R30,
-	KVM_REG_MIPS_R31,
-
-	KVM_REG_MIPS_HI,
-	KVM_REG_MIPS_LO,
-	KVM_REG_MIPS_PC,
-
-	KVM_REG_MIPS_CP0_INDEX,
-	KVM_REG_MIPS_CP0_CONTEXT,
-	KVM_REG_MIPS_CP0_USERLOCAL,
-	KVM_REG_MIPS_CP0_PAGEMASK,
-	KVM_REG_MIPS_CP0_WIRED,
-	KVM_REG_MIPS_CP0_HWRENA,
-	KVM_REG_MIPS_CP0_BADVADDR,
-	KVM_REG_MIPS_CP0_COUNT,
-	KVM_REG_MIPS_CP0_ENTRYHI,
-	KVM_REG_MIPS_CP0_COMPARE,
-	KVM_REG_MIPS_CP0_STATUS,
-	KVM_REG_MIPS_CP0_CAUSE,
-	KVM_REG_MIPS_CP0_EPC,
-	KVM_REG_MIPS_CP0_CONFIG,
-	KVM_REG_MIPS_CP0_CONFIG1,
-	KVM_REG_MIPS_CP0_CONFIG2,
-	KVM_REG_MIPS_CP0_CONFIG3,
-	KVM_REG_MIPS_CP0_CONFIG7,
-	KVM_REG_MIPS_CP0_ERROREPC,
-
-	KVM_REG_MIPS_COUNT_CTL,
-	KVM_REG_MIPS_COUNT_RESUME,
-	KVM_REG_MIPS_COUNT_HZ,
-};
-
-static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
-			    const struct kvm_one_reg *reg)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	int ret;
-	s64 v;
-
-	switch (reg->id) {
-	case KVM_REG_MIPS_R0 ... KVM_REG_MIPS_R31:
-		v = (long)vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0];
-		break;
-	case KVM_REG_MIPS_HI:
-		v = (long)vcpu->arch.hi;
-		break;
-	case KVM_REG_MIPS_LO:
-		v = (long)vcpu->arch.lo;
-		break;
-	case KVM_REG_MIPS_PC:
-		v = (long)vcpu->arch.pc;
-		break;
-
-	case KVM_REG_MIPS_CP0_INDEX:
-		v = (long)kvm_read_c0_guest_index(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONTEXT:
-		v = (long)kvm_read_c0_guest_context(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_USERLOCAL:
-		v = (long)kvm_read_c0_guest_userlocal(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_PAGEMASK:
-		v = (long)kvm_read_c0_guest_pagemask(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_WIRED:
-		v = (long)kvm_read_c0_guest_wired(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_HWRENA:
-		v = (long)kvm_read_c0_guest_hwrena(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_BADVADDR:
-		v = (long)kvm_read_c0_guest_badvaddr(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_ENTRYHI:
-		v = (long)kvm_read_c0_guest_entryhi(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_COMPARE:
-		v = (long)kvm_read_c0_guest_compare(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_STATUS:
-		v = (long)kvm_read_c0_guest_status(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CAUSE:
-		v = (long)kvm_read_c0_guest_cause(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_EPC:
-		v = (long)kvm_read_c0_guest_epc(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_ERROREPC:
-		v = (long)kvm_read_c0_guest_errorepc(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONFIG:
-		v = (long)kvm_read_c0_guest_config(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONFIG1:
-		v = (long)kvm_read_c0_guest_config1(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONFIG2:
-		v = (long)kvm_read_c0_guest_config2(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONFIG3:
-		v = (long)kvm_read_c0_guest_config3(cop0);
-		break;
-	case KVM_REG_MIPS_CP0_CONFIG7:
-		v = (long)kvm_read_c0_guest_config7(cop0);
-		break;
-	/* registers to be handled specially */
-	case KVM_REG_MIPS_CP0_COUNT:
-	case KVM_REG_MIPS_COUNT_CTL:
-	case KVM_REG_MIPS_COUNT_RESUME:
-	case KVM_REG_MIPS_COUNT_HZ:
-		ret = kvm_mips_callbacks->get_one_reg(vcpu, reg, &v);
-		if (ret)
-			return ret;
-		break;
-	default:
-		return -EINVAL;
-	}
-	if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
-		u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
-		return put_user(v, uaddr64);
-	} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
-		u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
-		u32 v32 = (u32)v;
-		return put_user(v32, uaddr32);
-	} else {
-		return -EINVAL;
-	}
-}
-
-static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
-			    const struct kvm_one_reg *reg)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	u64 v;
-
-	if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
-		u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
-
-		if (get_user(v, uaddr64) != 0)
-			return -EFAULT;
-	} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
-		u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
-		s32 v32;
-
-		if (get_user(v32, uaddr32) != 0)
-			return -EFAULT;
-		v = (s64)v32;
-	} else {
-		return -EINVAL;
-	}
-
-	switch (reg->id) {
-	case KVM_REG_MIPS_R0:
-		/* Silently ignore requests to set $0 */
-		break;
-	case KVM_REG_MIPS_R1 ... KVM_REG_MIPS_R31:
-		vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0] = v;
-		break;
-	case KVM_REG_MIPS_HI:
-		vcpu->arch.hi = v;
-		break;
-	case KVM_REG_MIPS_LO:
-		vcpu->arch.lo = v;
-		break;
-	case KVM_REG_MIPS_PC:
-		vcpu->arch.pc = v;
-		break;
-
-	case KVM_REG_MIPS_CP0_INDEX:
-		kvm_write_c0_guest_index(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_CONTEXT:
-		kvm_write_c0_guest_context(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_USERLOCAL:
-		kvm_write_c0_guest_userlocal(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_PAGEMASK:
-		kvm_write_c0_guest_pagemask(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_WIRED:
-		kvm_write_c0_guest_wired(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_HWRENA:
-		kvm_write_c0_guest_hwrena(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_BADVADDR:
-		kvm_write_c0_guest_badvaddr(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_ENTRYHI:
-		kvm_write_c0_guest_entryhi(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_STATUS:
-		kvm_write_c0_guest_status(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_EPC:
-		kvm_write_c0_guest_epc(cop0, v);
-		break;
-	case KVM_REG_MIPS_CP0_ERROREPC:
-		kvm_write_c0_guest_errorepc(cop0, v);
-		break;
-	/* registers to be handled specially */
-	case KVM_REG_MIPS_CP0_COUNT:
-	case KVM_REG_MIPS_CP0_COMPARE:
-	case KVM_REG_MIPS_CP0_CAUSE:
-	case KVM_REG_MIPS_COUNT_CTL:
-	case KVM_REG_MIPS_COUNT_RESUME:
-	case KVM_REG_MIPS_COUNT_HZ:
-		return kvm_mips_callbacks->set_one_reg(vcpu, reg, v);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-long
-kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
-{
-	struct kvm_vcpu *vcpu = filp->private_data;
-	void __user *argp = (void __user *)arg;
-	long r;
-
-	switch (ioctl) {
-	case KVM_SET_ONE_REG:
-	case KVM_GET_ONE_REG: {
-		struct kvm_one_reg reg;
-		if (copy_from_user(&reg, argp, sizeof(reg)))
-			return -EFAULT;
-		if (ioctl == KVM_SET_ONE_REG)
-			return kvm_mips_set_reg(vcpu, &reg);
-		else
-			return kvm_mips_get_reg(vcpu, &reg);
-	}
-	case KVM_GET_REG_LIST: {
-		struct kvm_reg_list __user *user_list = argp;
-		u64 __user *reg_dest;
-		struct kvm_reg_list reg_list;
-		unsigned n;
-
-		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
-			return -EFAULT;
-		n = reg_list.n;
-		reg_list.n = ARRAY_SIZE(kvm_mips_get_one_regs);
-		if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
-			return -EFAULT;
-		if (n < reg_list.n)
-			return -E2BIG;
-		reg_dest = user_list->reg;
-		if (copy_to_user(reg_dest, kvm_mips_get_one_regs,
-				 sizeof(kvm_mips_get_one_regs)))
-			return -EFAULT;
-		return 0;
-	}
-	case KVM_NMI:
-		/* Treat the NMI as a CPU reset */
-		r = kvm_mips_reset_vcpu(vcpu);
-		break;
-	case KVM_INTERRUPT:
-		{
-			struct kvm_mips_interrupt irq;
-			r = -EFAULT;
-			if (copy_from_user(&irq, argp, sizeof(irq)))
-				goto out;
-
-			kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__,
-				  irq.irq);
-
-			r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
-			break;
-		}
-	default:
-		r = -ENOIOCTLCMD;
-	}
-
-out:
-	return r;
-}
-
-/*
- * Get (and clear) the dirty memory log for a memory slot.
- */
-int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
-{
-	struct kvm_memory_slot *memslot;
-	unsigned long ga, ga_end;
-	int is_dirty = 0;
-	int r;
-	unsigned long n;
-
-	mutex_lock(&kvm->slots_lock);
-
-	r = kvm_get_dirty_log(kvm, log, &is_dirty);
-	if (r)
-		goto out;
-
-	/* If nothing is dirty, don't bother messing with page tables. */
-	if (is_dirty) {
-		memslot = &kvm->memslots->memslots[log->slot];
-
-		ga = memslot->base_gfn << PAGE_SHIFT;
-		ga_end = ga + (memslot->npages << PAGE_SHIFT);
-
-		printk("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga,
-		       ga_end);
-
-		n = kvm_dirty_bitmap_bytes(memslot);
-		memset(memslot->dirty_bitmap, 0, n);
-	}
-
-	r = 0;
-out:
-	mutex_unlock(&kvm->slots_lock);
-	return r;
-
-}
-
-long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
-{
-	long r;
-
-	switch (ioctl) {
-	default:
-		r = -ENOIOCTLCMD;
-	}
-
-	return r;
-}
-
-int kvm_arch_init(void *opaque)
-{
-	int ret;
-
-	if (kvm_mips_callbacks) {
-		kvm_err("kvm: module already exists\n");
-		return -EEXIST;
-	}
-
-	ret = kvm_mips_emulation_init(&kvm_mips_callbacks);
-
-	return ret;
-}
-
-void kvm_arch_exit(void)
-{
-	kvm_mips_callbacks = NULL;
-}
-
-int
-kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
-{
-	return -ENOIOCTLCMD;
-}
-
-int
-kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
-{
-	return -ENOIOCTLCMD;
-}
-
-int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
-{
-	return 0;
-}
-
-int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
-{
-	return -ENOIOCTLCMD;
-}
-
-int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
-{
-	return -ENOIOCTLCMD;
-}
-
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
-{
-	return VM_FAULT_SIGBUS;
-}
-
-int kvm_dev_ioctl_check_extension(long ext)
-{
-	int r;
-
-	switch (ext) {
-	case KVM_CAP_ONE_REG:
-		r = 1;
-		break;
-	case KVM_CAP_COALESCED_MMIO:
-		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
-		break;
-	default:
-		r = 0;
-		break;
-	}
-	return r;
-}
-
-int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
-{
-	return kvm_mips_pending_timer(vcpu);
-}
-
-int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
-{
-	int i;
-	struct mips_coproc *cop0;
-
-	if (!vcpu)
-		return -1;
-
-	printk("VCPU Register Dump:\n");
-	printk("\tpc = 0x%08lx\n", vcpu->arch.pc);
-	printk("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
-
-	for (i = 0; i < 32; i += 4) {
-		printk("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i,
-		       vcpu->arch.gprs[i],
-		       vcpu->arch.gprs[i + 1],
-		       vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]);
-	}
-	printk("\thi: 0x%08lx\n", vcpu->arch.hi);
-	printk("\tlo: 0x%08lx\n", vcpu->arch.lo);
-
-	cop0 = vcpu->arch.cop0;
-	printk("\tStatus: 0x%08lx, Cause: 0x%08lx\n",
-	       kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0));
-
-	printk("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0));
-
-	return 0;
-}
-
-int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-	int i;
-
-	for (i = 1; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
-		vcpu->arch.gprs[i] = regs->gpr[i];
-	vcpu->arch.gprs[0] = 0; /* zero is special, and cannot be set. */
-	vcpu->arch.hi = regs->hi;
-	vcpu->arch.lo = regs->lo;
-	vcpu->arch.pc = regs->pc;
-
-	return 0;
-}
-
-int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
-		regs->gpr[i] = vcpu->arch.gprs[i];
-
-	regs->hi = vcpu->arch.hi;
-	regs->lo = vcpu->arch.lo;
-	regs->pc = vcpu->arch.pc;
-
-	return 0;
-}
-
-static void kvm_mips_comparecount_func(unsigned long data)
-{
-	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
-
-	kvm_mips_callbacks->queue_timer_int(vcpu);
-
-	vcpu->arch.wait = 0;
-	if (waitqueue_active(&vcpu->wq)) {
-		wake_up_interruptible(&vcpu->wq);
-	}
-}
-
-/*
- * low level hrtimer wake routine.
- */
-static enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
-{
-	struct kvm_vcpu *vcpu;
-
-	vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer);
-	kvm_mips_comparecount_func((unsigned long) vcpu);
-	return kvm_mips_count_timeout(vcpu);
-}
-
-int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
-{
-	kvm_mips_callbacks->vcpu_init(vcpu);
-	hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC,
-		     HRTIMER_MODE_REL);
-	vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup;
-	return 0;
-}
-
-void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
-{
-	return;
-}
-
-int
-kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, struct kvm_translation *tr)
-{
-	return 0;
-}
-
-/* Initial guest state */
-int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
-{
-	return kvm_mips_callbacks->vcpu_setup(vcpu);
-}
-
-static
-void kvm_mips_set_c0_status(void)
-{
-	uint32_t status = read_c0_status();
-
-	if (cpu_has_fpu)
-		status |= (ST0_CU1);
-
-	if (cpu_has_dsp)
-		status |= (ST0_MX);
-
-	write_c0_status(status);
-	ehb();
-}
-
-/*
- * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
- */
-int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	uint32_t cause = vcpu->arch.host_cp0_cause;
-	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	/* Set a default exit reason */
-	run->exit_reason = KVM_EXIT_UNKNOWN;
-	run->ready_for_interrupt_injection = 1;
-
-	/* Set the appropriate status bits based on host CPU features, before we hit the scheduler */
-	kvm_mips_set_c0_status();
-
-	local_irq_enable();
-
-	kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n",
-			cause, opc, run, vcpu);
-
-	/* Do a privilege check, if in UM most of these exit conditions end up
-	 * causing an exception to be delivered to the Guest Kernel
-	 */
-	er = kvm_mips_check_privilege(cause, opc, run, vcpu);
-	if (er == EMULATE_PRIV_FAIL) {
-		goto skip_emul;
-	} else if (er == EMULATE_FAIL) {
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-		goto skip_emul;
-	}
-
-	switch (exccode) {
-	case T_INT:
-		kvm_debug("[%d]T_INT @ %p\n", vcpu->vcpu_id, opc);
-
-		++vcpu->stat.int_exits;
-		trace_kvm_exit(vcpu, INT_EXITS);
-
-		if (need_resched()) {
-			cond_resched();
-		}
-
-		ret = RESUME_GUEST;
-		break;
-
-	case T_COP_UNUSABLE:
-		kvm_debug("T_COP_UNUSABLE: @ PC: %p\n", opc);
-
-		++vcpu->stat.cop_unusable_exits;
-		trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS);
-		ret = kvm_mips_callbacks->handle_cop_unusable(vcpu);
-		/* XXXKYMA: Might need to return to user space */
-		if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN) {
-			ret = RESUME_HOST;
-		}
-		break;
-
-	case T_TLB_MOD:
-		++vcpu->stat.tlbmod_exits;
-		trace_kvm_exit(vcpu, TLBMOD_EXITS);
-		ret = kvm_mips_callbacks->handle_tlb_mod(vcpu);
-		break;
-
-	case T_TLB_ST_MISS:
-		kvm_debug
-		    ("TLB ST fault:  cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
-		     badvaddr);
-
-		++vcpu->stat.tlbmiss_st_exits;
-		trace_kvm_exit(vcpu, TLBMISS_ST_EXITS);
-		ret = kvm_mips_callbacks->handle_tlb_st_miss(vcpu);
-		break;
-
-	case T_TLB_LD_MISS:
-		kvm_debug("TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n",
-			  cause, opc, badvaddr);
-
-		++vcpu->stat.tlbmiss_ld_exits;
-		trace_kvm_exit(vcpu, TLBMISS_LD_EXITS);
-		ret = kvm_mips_callbacks->handle_tlb_ld_miss(vcpu);
-		break;
-
-	case T_ADDR_ERR_ST:
-		++vcpu->stat.addrerr_st_exits;
-		trace_kvm_exit(vcpu, ADDRERR_ST_EXITS);
-		ret = kvm_mips_callbacks->handle_addr_err_st(vcpu);
-		break;
-
-	case T_ADDR_ERR_LD:
-		++vcpu->stat.addrerr_ld_exits;
-		trace_kvm_exit(vcpu, ADDRERR_LD_EXITS);
-		ret = kvm_mips_callbacks->handle_addr_err_ld(vcpu);
-		break;
-
-	case T_SYSCALL:
-		++vcpu->stat.syscall_exits;
-		trace_kvm_exit(vcpu, SYSCALL_EXITS);
-		ret = kvm_mips_callbacks->handle_syscall(vcpu);
-		break;
-
-	case T_RES_INST:
-		++vcpu->stat.resvd_inst_exits;
-		trace_kvm_exit(vcpu, RESVD_INST_EXITS);
-		ret = kvm_mips_callbacks->handle_res_inst(vcpu);
-		break;
-
-	case T_BREAK:
-		++vcpu->stat.break_inst_exits;
-		trace_kvm_exit(vcpu, BREAK_INST_EXITS);
-		ret = kvm_mips_callbacks->handle_break(vcpu);
-		break;
-
-	default:
-		kvm_err
-		    ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x  BadVaddr: %#lx Status: %#lx\n",
-		     exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
-		     kvm_read_c0_guest_status(vcpu->arch.cop0));
-		kvm_arch_vcpu_dump_regs(vcpu);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-		break;
-
-	}
-
-skip_emul:
-	local_irq_disable();
-
-	if (er == EMULATE_DONE && !(ret & RESUME_HOST))
-		kvm_mips_deliver_interrupts(vcpu, cause);
-
-	if (!(ret & RESUME_HOST)) {
-		/* Only check for signals if not already exiting to userspace  */
-		if (signal_pending(current)) {
-			run->exit_reason = KVM_EXIT_INTR;
-			ret = (-EINTR << 2) | RESUME_HOST;
-			++vcpu->stat.signal_exits;
-			trace_kvm_exit(vcpu, SIGNAL_EXITS);
-		}
-	}
-
-	return ret;
-}
-
-int __init kvm_mips_init(void)
-{
-	int ret;
-
-	ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
-
-	if (ret)
-		return ret;
-
-	/* On MIPS, kernel modules are executed from "mapped space", which requires TLBs.
-	 * The TLB handling code is statically linked with the rest of the kernel (kvm_tlb.c)
-	 * to avoid the possibility of double faulting. The issue is that the TLB code
-	 * references routines that are part of the the KVM module,
-	 * which are only available once the module is loaded.
-	 */
-	kvm_mips_gfn_to_pfn = gfn_to_pfn;
-	kvm_mips_release_pfn_clean = kvm_release_pfn_clean;
-	kvm_mips_is_error_pfn = is_error_pfn;
-
-	pr_info("KVM/MIPS Initialized\n");
-	return 0;
-}
-
-void __exit kvm_mips_exit(void)
-{
-	kvm_exit();
-
-	kvm_mips_gfn_to_pfn = NULL;
-	kvm_mips_release_pfn_clean = NULL;
-	kvm_mips_is_error_pfn = NULL;
-
-	pr_info("KVM/MIPS unloaded\n");
-}
-
-module_init(kvm_mips_init);
-module_exit(kvm_mips_exit);
-
-EXPORT_TRACEPOINT_SYMBOL(kvm_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_comm.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_comm.h
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_comm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_comm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: commpage: mapped into get kernel space
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#ifndef __KVM_MIPS_COMMPAGE_H__
-#define __KVM_MIPS_COMMPAGE_H__
-
-struct kvm_mips_commpage {
-	struct mips_coproc cop0;	/* COP0 state is mapped into Guest kernel via commpage */
-};
-
-#define KVM_MIPS_COMM_EIDI_OFFSET       0x0
-
-extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu);
-
-#endif /* __KVM_MIPS_COMMPAGE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_commpage.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_commpage.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_commpage.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_commpage.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* commpage, currently used for Virtual COP0 registers.
-* Mapped into the guest kernel @ 0x0.
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/mmu_context.h>
-
-#include <linux/kvm_host.h>
-
-#include "kvm_mips_comm.h"
-
-void kvm_mips_commpage_init(struct kvm_vcpu *vcpu)
-{
-	struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage;
-	memset(page, 0, sizeof(struct kvm_mips_commpage));
-
-	/* Specific init values for fields */
-	vcpu->arch.cop0 = &page->cop0;
-	memset(vcpu->arch.cop0, 0, sizeof(struct mips_coproc));
-
-	return;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_dyntrans.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_dyntrans.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_dyntrans.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_dyntrans.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Binary Patching for privileged instructions, reduces traps.
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/kvm_host.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <asm/cacheflush.h>
-
-#include "kvm_mips_comm.h"
-
-#define SYNCI_TEMPLATE  0x041f0000
-#define SYNCI_BASE(x)   (((x) >> 21) & 0x1f)
-#define SYNCI_OFFSET    ((x) & 0xffff)
-
-#define LW_TEMPLATE     0x8c000000
-#define CLEAR_TEMPLATE  0x00000020
-#define SW_TEMPLATE     0xac000000
-
-int
-kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
-			   struct kvm_vcpu *vcpu)
-{
-	int result = 0;
-	unsigned long kseg0_opc;
-	uint32_t synci_inst = 0x0;
-
-	/* Replace the CACHE instruction, with a NOP */
-	kseg0_opc =
-	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
-		       (vcpu, (unsigned long) opc));
-	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
-	local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
-
-	return result;
-}
-
-/*
- *  Address based CACHE instructions are transformed into synci(s). A little heavy
- * for just D-cache invalidates, but avoids an expensive trap
- */
-int
-kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
-			struct kvm_vcpu *vcpu)
-{
-	int result = 0;
-	unsigned long kseg0_opc;
-	uint32_t synci_inst = SYNCI_TEMPLATE, base, offset;
-
-	base = (inst >> 21) & 0x1f;
-	offset = inst & 0xffff;
-	synci_inst |= (base << 21);
-	synci_inst |= offset;
-
-	kseg0_opc =
-	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
-		       (vcpu, (unsigned long) opc));
-	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
-	local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
-
-	return result;
-}
-
-int
-kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
-{
-	int32_t rt, rd, sel;
-	uint32_t mfc0_inst;
-	unsigned long kseg0_opc, flags;
-
-	rt = (inst >> 16) & 0x1f;
-	rd = (inst >> 11) & 0x1f;
-	sel = inst & 0x7;
-
-	if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
-		mfc0_inst = CLEAR_TEMPLATE;
-		mfc0_inst |= ((rt & 0x1f) << 16);
-	} else {
-		mfc0_inst = LW_TEMPLATE;
-		mfc0_inst |= ((rt & 0x1f) << 16);
-		mfc0_inst |=
-		    offsetof(struct mips_coproc,
-			     reg[rd][sel]) + offsetof(struct kvm_mips_commpage,
-						      cop0);
-	}
-
-	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
-		kseg0_opc =
-		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
-			       (vcpu, (unsigned long) opc));
-		memcpy((void *)kseg0_opc, (void *)&mfc0_inst, sizeof(uint32_t));
-		local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
-	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
-		local_irq_save(flags);
-		memcpy((void *)opc, (void *)&mfc0_inst, sizeof(uint32_t));
-		local_flush_icache_range((unsigned long)opc,
-					 (unsigned long)opc + 32);
-		local_irq_restore(flags);
-	} else {
-		kvm_err("%s: Invalid address: %p\n", __func__, opc);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-int
-kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
-{
-	int32_t rt, rd, sel;
-	uint32_t mtc0_inst = SW_TEMPLATE;
-	unsigned long kseg0_opc, flags;
-
-	rt = (inst >> 16) & 0x1f;
-	rd = (inst >> 11) & 0x1f;
-	sel = inst & 0x7;
-
-	mtc0_inst |= ((rt & 0x1f) << 16);
-	mtc0_inst |=
-	    offsetof(struct mips_coproc,
-		     reg[rd][sel]) + offsetof(struct kvm_mips_commpage, cop0);
-
-	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
-		kseg0_opc =
-		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
-			       (vcpu, (unsigned long) opc));
-		memcpy((void *)kseg0_opc, (void *)&mtc0_inst, sizeof(uint32_t));
-		local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
-	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
-		local_irq_save(flags);
-		memcpy((void *)opc, (void *)&mtc0_inst, sizeof(uint32_t));
-		local_flush_icache_range((unsigned long)opc,
-					 (unsigned long)opc + 32);
-		local_irq_restore(flags);
-	} else {
-		kvm_err("%s: Invalid address: %p\n", __func__, opc);
-		return -EFAULT;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_emul.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_emul.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_emul.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_emul.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2332 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Instruction/Exception emulation
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/ktime.h>
-#include <linux/kvm_host.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <linux/random.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/cpu-info.h>
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
-#include <asm/inst.h>
-
-#undef CONFIG_MIPS_MT
-#include <asm/r4kcache.h>
-#define CONFIG_MIPS_MT
-
-#include "kvm_mips_opcode.h"
-#include "kvm_mips_int.h"
-#include "kvm_mips_comm.h"
-
-#include "trace.h"
-
-/*
- * Compute the return address and do emulate branch simulation, if required.
- * This function should be called only in branch delay slot active.
- */
-unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
-	unsigned long instpc)
-{
-	unsigned int dspcontrol;
-	union mips_instruction insn;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	long epc = instpc;
-	long nextpc = KVM_INVALID_INST;
-
-	if (epc & 3)
-		goto unaligned;
-
-	/*
-	 * Read the instruction
-	 */
-	insn.word = kvm_get_inst((uint32_t *) epc, vcpu);
-
-	if (insn.word == KVM_INVALID_INST)
-		return KVM_INVALID_INST;
-
-	switch (insn.i_format.opcode) {
-		/*
-		 * jr and jalr are in r_format format.
-		 */
-	case spec_op:
-		switch (insn.r_format.func) {
-		case jalr_op:
-			arch->gprs[insn.r_format.rd] = epc + 8;
-			/* Fall through */
-		case jr_op:
-			nextpc = arch->gprs[insn.r_format.rs];
-			break;
-		}
-		break;
-
-		/*
-		 * This group contains:
-		 * bltz_op, bgez_op, bltzl_op, bgezl_op,
-		 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
-		 */
-	case bcond_op:
-		switch (insn.i_format.rt) {
-		case bltz_op:
-		case bltzl_op:
-			if ((long)arch->gprs[insn.i_format.rs] < 0)
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-			else
-				epc += 8;
-			nextpc = epc;
-			break;
-
-		case bgez_op:
-		case bgezl_op:
-			if ((long)arch->gprs[insn.i_format.rs] >= 0)
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-			else
-				epc += 8;
-			nextpc = epc;
-			break;
-
-		case bltzal_op:
-		case bltzall_op:
-			arch->gprs[31] = epc + 8;
-			if ((long)arch->gprs[insn.i_format.rs] < 0)
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-			else
-				epc += 8;
-			nextpc = epc;
-			break;
-
-		case bgezal_op:
-		case bgezall_op:
-			arch->gprs[31] = epc + 8;
-			if ((long)arch->gprs[insn.i_format.rs] >= 0)
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-			else
-				epc += 8;
-			nextpc = epc;
-			break;
-		case bposge32_op:
-			if (!cpu_has_dsp)
-				goto sigill;
-
-			dspcontrol = rddsp(0x01);
-
-			if (dspcontrol >= 32) {
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-			} else
-				epc += 8;
-			nextpc = epc;
-			break;
-		}
-		break;
-
-		/*
-		 * These are unconditional and in j_format.
-		 */
-	case jal_op:
-		arch->gprs[31] = instpc + 8;
-	case j_op:
-		epc += 4;
-		epc >>= 28;
-		epc <<= 28;
-		epc |= (insn.j_format.target << 2);
-		nextpc = epc;
-		break;
-
-		/*
-		 * These are conditional and in i_format.
-		 */
-	case beq_op:
-	case beql_op:
-		if (arch->gprs[insn.i_format.rs] ==
-		    arch->gprs[insn.i_format.rt])
-			epc = epc + 4 + (insn.i_format.simmediate << 2);
-		else
-			epc += 8;
-		nextpc = epc;
-		break;
-
-	case bne_op:
-	case bnel_op:
-		if (arch->gprs[insn.i_format.rs] !=
-		    arch->gprs[insn.i_format.rt])
-			epc = epc + 4 + (insn.i_format.simmediate << 2);
-		else
-			epc += 8;
-		nextpc = epc;
-		break;
-
-	case blez_op:		/* not really i_format */
-	case blezl_op:
-		/* rt field assumed to be zero */
-		if ((long)arch->gprs[insn.i_format.rs] <= 0)
-			epc = epc + 4 + (insn.i_format.simmediate << 2);
-		else
-			epc += 8;
-		nextpc = epc;
-		break;
-
-	case bgtz_op:
-	case bgtzl_op:
-		/* rt field assumed to be zero */
-		if ((long)arch->gprs[insn.i_format.rs] > 0)
-			epc = epc + 4 + (insn.i_format.simmediate << 2);
-		else
-			epc += 8;
-		nextpc = epc;
-		break;
-
-		/*
-		 * And now the FPA/cp1 branch instructions.
-		 */
-	case cop1_op:
-		printk("%s: unsupported cop1_op\n", __func__);
-		break;
-	}
-
-	return nextpc;
-
-unaligned:
-	printk("%s: unaligned epc\n", __func__);
-	return nextpc;
-
-sigill:
-	printk("%s: DSP branch but not DSP ASE\n", __func__);
-	return nextpc;
-}
-
-enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
-{
-	unsigned long branch_pc;
-	enum emulation_result er = EMULATE_DONE;
-
-	if (cause & CAUSEF_BD) {
-		branch_pc = kvm_compute_return_epc(vcpu, vcpu->arch.pc);
-		if (branch_pc == KVM_INVALID_INST) {
-			er = EMULATE_FAIL;
-		} else {
-			vcpu->arch.pc = branch_pc;
-			kvm_debug("BD update_pc(): New PC: %#lx\n", vcpu->arch.pc);
-		}
-	} else
-		vcpu->arch.pc += 4;
-
-	kvm_debug("update_pc(): New PC: %#lx\n", vcpu->arch.pc);
-
-	return er;
-}
-
-/**
- * kvm_mips_count_disabled() - Find whether the CP0_Count timer is disabled.
- * @vcpu:	Virtual CPU.
- *
- * Returns:	1 if the CP0_Count timer is disabled by either the guest
- *		CP0_Cause.DC bit or the count_ctl.DC bit.
- *		0 otherwise (in which case CP0_Count timer is running).
- */
-static inline int kvm_mips_count_disabled(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	return	(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) ||
-		(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC);
-}
-
-/**
- * kvm_mips_ktime_to_count() - Scale ktime_t to a 32-bit count.
- *
- * Caches the dynamic nanosecond bias in vcpu->arch.count_dyn_bias.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static uint32_t kvm_mips_ktime_to_count(struct kvm_vcpu *vcpu, ktime_t now)
-{
-	s64 now_ns, periods;
-	u64 delta;
-
-	now_ns = ktime_to_ns(now);
-	delta = now_ns + vcpu->arch.count_dyn_bias;
-
-	if (delta >= vcpu->arch.count_period) {
-		/* If delta is out of safe range the bias needs adjusting */
-		periods = div64_s64(now_ns, vcpu->arch.count_period);
-		vcpu->arch.count_dyn_bias = -periods * vcpu->arch.count_period;
-		/* Recalculate delta with new bias */
-		delta = now_ns + vcpu->arch.count_dyn_bias;
-	}
-
-	/*
-	 * We've ensured that:
-	 *   delta < count_period
-	 *
-	 * Therefore the intermediate delta*count_hz will never overflow since
-	 * at the boundary condition:
-	 *   delta = count_period
-	 *   delta = NSEC_PER_SEC * 2^32 / count_hz
-	 *   delta * count_hz = NSEC_PER_SEC * 2^32
-	 */
-	return div_u64(delta * vcpu->arch.count_hz, NSEC_PER_SEC);
-}
-
-/**
- * kvm_mips_count_time() - Get effective current time.
- * @vcpu:	Virtual CPU.
- *
- * Get effective monotonic ktime. This is usually a straightforward ktime_get(),
- * except when the master disable bit is set in count_ctl, in which case it is
- * count_resume, i.e. the time that the count was disabled.
- *
- * Returns:	Effective monotonic ktime for CP0_Count.
- */
-static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu)
-{
-	if (unlikely(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
-		return vcpu->arch.count_resume;
-
-	return ktime_get();
-}
-
-/**
- * kvm_mips_read_count_running() - Read the current count value as if running.
- * @vcpu:	Virtual CPU.
- * @now:	Kernel time to read CP0_Count at.
- *
- * Returns the current guest CP0_Count register at time @now and handles if the
- * timer interrupt is pending and hasn't been handled yet.
- *
- * Returns:	The current value of the guest CP0_Count register.
- */
-static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
-{
-	ktime_t expires;
-	int running;
-
-	/* Is the hrtimer pending? */
-	expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
-	if (ktime_compare(now, expires) >= 0) {
-		/*
-		 * Cancel it while we handle it so there's no chance of
-		 * interference with the timeout handler.
-		 */
-		running = hrtimer_cancel(&vcpu->arch.comparecount_timer);
-
-		/* Nothing should be waiting on the timeout */
-		kvm_mips_callbacks->queue_timer_int(vcpu);
-
-		/*
-		 * Restart the timer if it was running based on the expiry time
-		 * we read, so that we don't push it back 2 periods.
-		 */
-		if (running) {
-			expires = ktime_add_ns(expires,
-					       vcpu->arch.count_period);
-			hrtimer_start(&vcpu->arch.comparecount_timer, expires,
-				      HRTIMER_MODE_ABS);
-		}
-	}
-
-	/* Return the biased and scaled guest CP0_Count */
-	return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
-}
-
-/**
- * kvm_mips_read_count() - Read the current count value.
- * @vcpu:	Virtual CPU.
- *
- * Read the current guest CP0_Count value, taking into account whether the timer
- * is stopped.
- *
- * Returns:	The current guest CP0_Count value.
- */
-uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-	/* If count disabled just read static copy of count */
-	if (kvm_mips_count_disabled(vcpu))
-		return kvm_read_c0_guest_count(cop0);
-
-	return kvm_mips_read_count_running(vcpu, ktime_get());
-}
-
-/**
- * kvm_mips_freeze_hrtimer() - Safely stop the hrtimer.
- * @vcpu:	Virtual CPU.
- * @count:	Output pointer for CP0_Count value at point of freeze.
- *
- * Freeze the hrtimer safely and return both the ktime and the CP0_Count value
- * at the point it was frozen. It is guaranteed that any pending interrupts at
- * the point it was frozen are handled, and none after that point.
- *
- * This is useful where the time/CP0_Count is needed in the calculation of the
- * new parameters.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- *
- * Returns:	The ktime at the point of freeze.
- */
-static ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu,
-				       uint32_t *count)
-{
-	ktime_t now;
-
-	/* stop hrtimer before finding time */
-	hrtimer_cancel(&vcpu->arch.comparecount_timer);
-	now = ktime_get();
-
-	/* find count at this point and handle pending hrtimer */
-	*count = kvm_mips_read_count_running(vcpu, now);
-
-	return now;
-}
-
-
-/**
- * kvm_mips_resume_hrtimer() - Resume hrtimer, updating expiry.
- * @vcpu:	Virtual CPU.
- * @now:	ktime at point of resume.
- * @count:	CP0_Count at point of resume.
- *
- * Resumes the timer and updates the timer expiry based on @now and @count.
- * This can be used in conjunction with kvm_mips_freeze_timer() when timer
- * parameters need to be changed.
- *
- * It is guaranteed that a timer interrupt immediately after resume will be
- * handled, but not if CP_Compare is exactly at @count. That case is already
- * handled by kvm_mips_freeze_timer().
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu,
-				    ktime_t now, uint32_t count)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	uint32_t compare;
-	u64 delta;
-	ktime_t expire;
-
-	/* Calculate timeout (wrap 0 to 2^32) */
-	compare = kvm_read_c0_guest_compare(cop0);
-	delta = (u64)(uint32_t)(compare - count - 1) + 1;
-	delta = div_u64(delta * NSEC_PER_SEC, vcpu->arch.count_hz);
-	expire = ktime_add_ns(now, delta);
-
-	/* Update hrtimer to use new timeout */
-	hrtimer_cancel(&vcpu->arch.comparecount_timer);
-	hrtimer_start(&vcpu->arch.comparecount_timer, expire, HRTIMER_MODE_ABS);
-}
-
-/**
- * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
- * @vcpu:	Virtual CPU.
- *
- * Recalculates and updates the expiry time of the hrtimer. This can be used
- * after timer parameters have been altered which do not depend on the time that
- * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
- * kvm_mips_resume_hrtimer() are used directly).
- *
- * It is guaranteed that no timer interrupts will be lost in the process.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
-{
-	ktime_t now;
-	uint32_t count;
-
-	/*
-	 * freeze_hrtimer takes care of a timer interrupts <= count, and
-	 * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
-	 */
-	now = kvm_mips_freeze_hrtimer(vcpu, &count);
-	kvm_mips_resume_hrtimer(vcpu, now, count);
-}
-
-/**
- * kvm_mips_write_count() - Modify the count and update timer.
- * @vcpu:	Virtual CPU.
- * @count:	Guest CP0_Count value to set.
- *
- * Sets the CP0_Count value and updates the timer accordingly.
- */
-void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	ktime_t now;
-
-	/* Calculate bias */
-	now = kvm_mips_count_time(vcpu);
-	vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
-
-	if (kvm_mips_count_disabled(vcpu))
-		/* The timer's disabled, adjust the static count */
-		kvm_write_c0_guest_count(cop0, count);
-	else
-		/* Update timeout */
-		kvm_mips_resume_hrtimer(vcpu, now, count);
-}
-
-/**
- * kvm_mips_init_count() - Initialise timer.
- * @vcpu:	Virtual CPU.
- *
- * Initialise the timer to a sensible frequency, namely 100MHz, zero it, and set
- * it going if it's enabled.
- */
-void kvm_mips_init_count(struct kvm_vcpu *vcpu)
-{
-	/* 100 MHz */
-	vcpu->arch.count_hz = 100*1000*1000;
-	vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32,
-					  vcpu->arch.count_hz);
-	vcpu->arch.count_dyn_bias = 0;
-
-	/* Starting at 0 */
-	kvm_mips_write_count(vcpu, 0);
-}
-
-/**
- * kvm_mips_set_count_hz() - Update the frequency of the timer.
- * @vcpu:	Virtual CPU.
- * @count_hz:	Frequency of CP0_Count timer in Hz.
- *
- * Change the frequency of the CP0_Count timer. This is done atomically so that
- * CP0_Count is continuous and no timer interrupt is lost.
- *
- * Returns:	-EINVAL if @count_hz is out of range.
- *		0 on success.
- */
-int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	int dc;
-	ktime_t now;
-	u32 count;
-
-	/* ensure the frequency is in a sensible range... */
-	if (count_hz <= 0 || count_hz > NSEC_PER_SEC)
-		return -EINVAL;
-	/* ... and has actually changed */
-	if (vcpu->arch.count_hz == count_hz)
-		return 0;
-
-	/* Safely freeze timer so we can keep it continuous */
-	dc = kvm_mips_count_disabled(vcpu);
-	if (dc) {
-		now = kvm_mips_count_time(vcpu);
-		count = kvm_read_c0_guest_count(cop0);
-	} else {
-		now = kvm_mips_freeze_hrtimer(vcpu, &count);
-	}
-
-	/* Update the frequency */
-	vcpu->arch.count_hz = count_hz;
-	vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32, count_hz);
-	vcpu->arch.count_dyn_bias = 0;
-
-	/* Calculate adjusted bias so dynamic count is unchanged */
-	vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
-
-	/* Update and resume hrtimer */
-	if (!dc)
-		kvm_mips_resume_hrtimer(vcpu, now, count);
-	return 0;
-}
-
-/**
- * kvm_mips_write_compare() - Modify compare and update timer.
- * @vcpu:	Virtual CPU.
- * @compare:	New CP0_Compare value.
- *
- * Update CP0_Compare to a new value and update the timeout.
- */
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-	/* if unchanged, must just be an ack */
-	if (kvm_read_c0_guest_compare(cop0) == compare)
-		return;
-
-	/* Update compare */
-	kvm_write_c0_guest_compare(cop0, compare);
-
-	/* Update timeout if count enabled */
-	if (!kvm_mips_count_disabled(vcpu))
-		kvm_mips_update_hrtimer(vcpu);
-}
-
-/**
- * kvm_mips_count_disable() - Disable count.
- * @vcpu:	Virtual CPU.
- *
- * Disable the CP0_Count timer. A timer interrupt on or before the final stop
- * time will be handled but not after.
- *
- * Assumes CP0_Count was previously enabled but now Guest.CP0_Cause.DC or
- * count_ctl.DC has been set (count disabled).
- *
- * Returns:	The time that the timer was stopped.
- */
-static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	uint32_t count;
-	ktime_t now;
-
-	/* Stop hrtimer */
-	hrtimer_cancel(&vcpu->arch.comparecount_timer);
-
-	/* Set the static count from the dynamic count, handling pending TI */
-	now = ktime_get();
-	count = kvm_mips_read_count_running(vcpu, now);
-	kvm_write_c0_guest_count(cop0, count);
-
-	return now;
-}
-
-/**
- * kvm_mips_count_disable_cause() - Disable count using CP0_Cause.DC.
- * @vcpu:	Virtual CPU.
- *
- * Disable the CP0_Count timer and set CP0_Cause.DC. A timer interrupt on or
- * before the final stop time will be handled if the timer isn't disabled by
- * count_ctl.DC, but not after.
- *
- * Assumes CP0_Cause.DC is clear (count enabled).
- */
-void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-	kvm_set_c0_guest_cause(cop0, CAUSEF_DC);
-	if (!(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
-		kvm_mips_count_disable(vcpu);
-}
-
-/**
- * kvm_mips_count_enable_cause() - Enable count using CP0_Cause.DC.
- * @vcpu:	Virtual CPU.
- *
- * Enable the CP0_Count timer and clear CP0_Cause.DC. A timer interrupt after
- * the start time will be handled if the timer isn't disabled by count_ctl.DC,
- * potentially before even returning, so the caller should be careful with
- * ordering of CP0_Cause modifications so as not to lose it.
- *
- * Assumes CP0_Cause.DC is set (count disabled).
- */
-void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	uint32_t count;
-
-	kvm_clear_c0_guest_cause(cop0, CAUSEF_DC);
-
-	/*
-	 * Set the dynamic count to match the static count.
-	 * This starts the hrtimer if count_ctl.DC allows it.
-	 * Otherwise it conveniently updates the biases.
-	 */
-	count = kvm_read_c0_guest_count(cop0);
-	kvm_mips_write_count(vcpu, count);
-}
-
-/**
- * kvm_mips_set_count_ctl() - Update the count control KVM register.
- * @vcpu:	Virtual CPU.
- * @count_ctl:	Count control register new value.
- *
- * Set the count control KVM register. The timer is updated accordingly.
- *
- * Returns:	-EINVAL if reserved bits are set.
- *		0 on success.
- */
-int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	s64 changed = count_ctl ^ vcpu->arch.count_ctl;
-	s64 delta;
-	ktime_t expire, now;
-	uint32_t count, compare;
-
-	/* Only allow defined bits to be changed */
-	if (changed & ~(s64)(KVM_REG_MIPS_COUNT_CTL_DC))
-		return -EINVAL;
-
-	/* Apply new value */
-	vcpu->arch.count_ctl = count_ctl;
-
-	/* Master CP0_Count disable */
-	if (changed & KVM_REG_MIPS_COUNT_CTL_DC) {
-		/* Is CP0_Cause.DC already disabling CP0_Count? */
-		if (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC) {
-			if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)
-				/* Just record the current time */
-				vcpu->arch.count_resume = ktime_get();
-		} else if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) {
-			/* disable timer and record current time */
-			vcpu->arch.count_resume = kvm_mips_count_disable(vcpu);
-		} else {
-			/*
-			 * Calculate timeout relative to static count at resume
-			 * time (wrap 0 to 2^32).
-			 */
-			count = kvm_read_c0_guest_count(cop0);
-			compare = kvm_read_c0_guest_compare(cop0);
-			delta = (u64)(uint32_t)(compare - count - 1) + 1;
-			delta = div_u64(delta * NSEC_PER_SEC,
-					vcpu->arch.count_hz);
-			expire = ktime_add_ns(vcpu->arch.count_resume, delta);
-
-			/* Handle pending interrupt */
-			now = ktime_get();
-			if (ktime_compare(now, expire) >= 0)
-				/* Nothing should be waiting on the timeout */
-				kvm_mips_callbacks->queue_timer_int(vcpu);
-
-			/* Resume hrtimer without changing bias */
-			count = kvm_mips_read_count_running(vcpu, now);
-			kvm_mips_resume_hrtimer(vcpu, now, count);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * kvm_mips_set_count_resume() - Update the count resume KVM register.
- * @vcpu:		Virtual CPU.
- * @count_resume:	Count resume register new value.
- *
- * Set the count resume KVM register.
- *
- * Returns:	-EINVAL if out of valid range (0..now).
- *		0 on success.
- */
-int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume)
-{
-	/*
-	 * It doesn't make sense for the resume time to be in the future, as it
-	 * would be possible for the next interrupt to be more than a full
-	 * period in the future.
-	 */
-	if (count_resume < 0 || count_resume > ktime_to_ns(ktime_get()))
-		return -EINVAL;
-
-	vcpu->arch.count_resume = ns_to_ktime(count_resume);
-	return 0;
-}
-
-/**
- * kvm_mips_count_timeout() - Push timer forward on timeout.
- * @vcpu:	Virtual CPU.
- *
- * Handle an hrtimer event by push the hrtimer forward a period.
- *
- * Returns:	The hrtimer_restart value to return to the hrtimer subsystem.
- */
-enum hrtimer_restart kvm_mips_count_timeout(struct kvm_vcpu *vcpu)
-{
-	/* Add the Count period to the current expiry time */
-	hrtimer_add_expires_ns(&vcpu->arch.comparecount_timer,
-			       vcpu->arch.count_period);
-	return HRTIMER_RESTART;
-}
-
-enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	enum emulation_result er = EMULATE_DONE;
-
-	if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
-		kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
-			  kvm_read_c0_guest_epc(cop0));
-		kvm_clear_c0_guest_status(cop0, ST0_EXL);
-		vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
-
-	} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
-		kvm_clear_c0_guest_status(cop0, ST0_ERL);
-		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
-	} else {
-		printk("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
-		       vcpu->arch.pc);
-		er = EMULATE_FAIL;
-	}
-
-	return er;
-}
-
-enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DONE;
-
-	kvm_debug("[%#lx] !!!WAIT!!! (%#lx)\n", vcpu->arch.pc,
-		  vcpu->arch.pending_exceptions);
-
-	++vcpu->stat.wait_exits;
-	trace_kvm_exit(vcpu, WAIT_EXITS);
-	if (!vcpu->arch.pending_exceptions) {
-		vcpu->arch.wait = 1;
-		kvm_vcpu_block(vcpu);
-
-		/* We we are runnable, then definitely go off to user space to check if any
-		 * I/O interrupts are pending.
-		 */
-		if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
-			clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
-			vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
-		}
-	}
-
-	return er;
-}
-
-/* XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that we can catch
- * this, if things ever change
- */
-enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	enum emulation_result er = EMULATE_FAIL;
-	uint32_t pc = vcpu->arch.pc;
-
-	printk("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0));
-	return er;
-}
-
-/* Write Guest TLB Entry @ Index */
-enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	int index = kvm_read_c0_guest_index(cop0);
-	enum emulation_result er = EMULATE_DONE;
-	struct kvm_mips_tlb *tlb = NULL;
-	uint32_t pc = vcpu->arch.pc;
-
-	if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
-		printk("%s: illegal index: %d\n", __func__, index);
-		printk
-		    ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
-		     pc, index, kvm_read_c0_guest_entryhi(cop0),
-		     kvm_read_c0_guest_entrylo0(cop0),
-		     kvm_read_c0_guest_entrylo1(cop0),
-		     kvm_read_c0_guest_pagemask(cop0));
-		index = (index & ~0x80000000) % KVM_MIPS_GUEST_TLB_SIZE;
-	}
-
-	tlb = &vcpu->arch.guest_tlb[index];
-#if 1
-	/* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
-	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
-#endif
-
-	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
-	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
-	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
-	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
-
-	kvm_debug
-	    ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
-	     pc, index, kvm_read_c0_guest_entryhi(cop0),
-	     kvm_read_c0_guest_entrylo0(cop0), kvm_read_c0_guest_entrylo1(cop0),
-	     kvm_read_c0_guest_pagemask(cop0));
-
-	return er;
-}
-
-/* Write Guest TLB Entry @ Random Index */
-enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	enum emulation_result er = EMULATE_DONE;
-	struct kvm_mips_tlb *tlb = NULL;
-	uint32_t pc = vcpu->arch.pc;
-	int index;
-
-#if 1
-	get_random_bytes(&index, sizeof(index));
-	index &= (KVM_MIPS_GUEST_TLB_SIZE - 1);
-#else
-	index = jiffies % KVM_MIPS_GUEST_TLB_SIZE;
-#endif
-
-	if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
-		printk("%s: illegal index: %d\n", __func__, index);
-		return EMULATE_FAIL;
-	}
-
-	tlb = &vcpu->arch.guest_tlb[index];
-
-#if 1
-	/* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
-	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
-#endif
-
-	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
-	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
-	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
-	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
-
-	kvm_debug
-	    ("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n",
-	     pc, index, kvm_read_c0_guest_entryhi(cop0),
-	     kvm_read_c0_guest_entrylo0(cop0),
-	     kvm_read_c0_guest_entrylo1(cop0));
-
-	return er;
-}
-
-enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	long entryhi = kvm_read_c0_guest_entryhi(cop0);
-	enum emulation_result er = EMULATE_DONE;
-	uint32_t pc = vcpu->arch.pc;
-	int index = -1;
-
-	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
-
-	kvm_write_c0_guest_index(cop0, index);
-
-	kvm_debug("[%#x] COP0_TLBP (entryhi: %#lx), index: %d\n", pc, entryhi,
-		  index);
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
-		     struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	enum emulation_result er = EMULATE_DONE;
-	int32_t rt, rd, copz, sel, co_bit, op;
-	uint32_t pc = vcpu->arch.pc;
-	unsigned long curr_pc;
-
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
-	er = update_pc(vcpu, cause);
-	if (er == EMULATE_FAIL) {
-		return er;
-	}
-
-	copz = (inst >> 21) & 0x1f;
-	rt = (inst >> 16) & 0x1f;
-	rd = (inst >> 11) & 0x1f;
-	sel = inst & 0x7;
-	co_bit = (inst >> 25) & 1;
-
-	if (co_bit) {
-		op = (inst) & 0xff;
-
-		switch (op) {
-		case tlbr_op:	/*  Read indexed TLB entry  */
-			er = kvm_mips_emul_tlbr(vcpu);
-			break;
-		case tlbwi_op:	/*  Write indexed  */
-			er = kvm_mips_emul_tlbwi(vcpu);
-			break;
-		case tlbwr_op:	/*  Write random  */
-			er = kvm_mips_emul_tlbwr(vcpu);
-			break;
-		case tlbp_op:	/* TLB Probe */
-			er = kvm_mips_emul_tlbp(vcpu);
-			break;
-		case rfe_op:
-			printk("!!!COP0_RFE!!!\n");
-			break;
-		case eret_op:
-			er = kvm_mips_emul_eret(vcpu);
-			goto dont_update_pc;
-			break;
-		case wait_op:
-			er = kvm_mips_emul_wait(vcpu);
-			break;
-		}
-	} else {
-		switch (copz) {
-		case mfc_op:
-#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
-			cop0->stat[rd][sel]++;
-#endif
-			/* Get reg */
-			if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
-				vcpu->arch.gprs[rt] = kvm_mips_read_count(vcpu);
-			} else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
-				vcpu->arch.gprs[rt] = 0x0;
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-				kvm_mips_trans_mfc0(inst, opc, vcpu);
-#endif
-			}
-			else {
-				vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
-
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-				kvm_mips_trans_mfc0(inst, opc, vcpu);
-#endif
-			}
-
-			kvm_debug
-			    ("[%#x] MFCz[%d][%d], vcpu->arch.gprs[%d]: %#lx\n",
-			     pc, rd, sel, rt, vcpu->arch.gprs[rt]);
-
-			break;
-
-		case dmfc_op:
-			vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
-			break;
-
-		case mtc_op:
-#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
-			cop0->stat[rd][sel]++;
-#endif
-			if ((rd == MIPS_CP0_TLB_INDEX)
-			    && (vcpu->arch.gprs[rt] >=
-				KVM_MIPS_GUEST_TLB_SIZE)) {
-				printk("Invalid TLB Index: %ld",
-				       vcpu->arch.gprs[rt]);
-				er = EMULATE_FAIL;
-				break;
-			}
-#define C0_EBASE_CORE_MASK 0xff
-			if ((rd == MIPS_CP0_PRID) && (sel == 1)) {
-				/* Preserve CORE number */
-				kvm_change_c0_guest_ebase(cop0,
-							  ~(C0_EBASE_CORE_MASK),
-							  vcpu->arch.gprs[rt]);
-				printk("MTCz, cop0->reg[EBASE]: %#lx\n",
-				       kvm_read_c0_guest_ebase(cop0));
-			} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
-				uint32_t nasid =
-				    vcpu->arch.gprs[rt] & ASID_MASK;
-				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
-				    &&
-				    ((kvm_read_c0_guest_entryhi(cop0) &
-				      ASID_MASK) != nasid)) {
-
-					kvm_debug
-					    ("MTCz, change ASID from %#lx to %#lx\n",
-					     kvm_read_c0_guest_entryhi(cop0) &
-					     ASID_MASK,
-					     vcpu->arch.gprs[rt] & ASID_MASK);
-
-					/* Blow away the shadow host TLBs */
-					kvm_mips_flush_host_tlb(1);
-				}
-				kvm_write_c0_guest_entryhi(cop0,
-							   vcpu->arch.gprs[rt]);
-			}
-			/* Are we writing to COUNT */
-			else if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
-				kvm_mips_write_count(vcpu, vcpu->arch.gprs[rt]);
-				goto done;
-			} else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) {
-				kvm_debug("[%#x] MTCz, COMPARE %#lx <- %#lx\n",
-					  pc, kvm_read_c0_guest_compare(cop0),
-					  vcpu->arch.gprs[rt]);
-
-				/* If we are writing to COMPARE */
-				/* Clear pending timer interrupt, if any */
-				kvm_mips_callbacks->dequeue_timer_int(vcpu);
-				kvm_mips_write_compare(vcpu,
-						       vcpu->arch.gprs[rt]);
-			} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
-				kvm_write_c0_guest_status(cop0,
-							  vcpu->arch.gprs[rt]);
-				/* Make sure that CU1 and NMI bits are never set */
-				kvm_clear_c0_guest_status(cop0,
-							  (ST0_CU1 | ST0_NMI));
-
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-				kvm_mips_trans_mtc0(inst, opc, vcpu);
-#endif
-			} else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) {
-				uint32_t old_cause, new_cause;
-				old_cause = kvm_read_c0_guest_cause(cop0);
-				new_cause = vcpu->arch.gprs[rt];
-				/* Update R/W bits */
-				kvm_change_c0_guest_cause(cop0, 0x08800300,
-							  new_cause);
-				/* DC bit enabling/disabling timer? */
-				if ((old_cause ^ new_cause) & CAUSEF_DC) {
-					if (new_cause & CAUSEF_DC)
-						kvm_mips_count_disable_cause(vcpu);
-					else
-						kvm_mips_count_enable_cause(vcpu);
-				}
-			} else {
-				cop0->reg[rd][sel] = vcpu->arch.gprs[rt];
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-				kvm_mips_trans_mtc0(inst, opc, vcpu);
-#endif
-			}
-
-			kvm_debug("[%#x] MTCz, cop0->reg[%d][%d]: %#lx\n", pc,
-				  rd, sel, cop0->reg[rd][sel]);
-			break;
-
-		case dmtc_op:
-			printk
-			    ("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
-			     vcpu->arch.pc, rt, rd, sel);
-			er = EMULATE_FAIL;
-			break;
-
-		case mfmcz_op:
-#ifdef KVM_MIPS_DEBUG_COP0_COUNTERS
-			cop0->stat[MIPS_CP0_STATUS][0]++;
-#endif
-			if (rt != 0) {
-				vcpu->arch.gprs[rt] =
-				    kvm_read_c0_guest_status(cop0);
-			}
-			/* EI */
-			if (inst & 0x20) {
-				kvm_debug("[%#lx] mfmcz_op: EI\n",
-					  vcpu->arch.pc);
-				kvm_set_c0_guest_status(cop0, ST0_IE);
-			} else {
-				kvm_debug("[%#lx] mfmcz_op: DI\n",
-					  vcpu->arch.pc);
-				kvm_clear_c0_guest_status(cop0, ST0_IE);
-			}
-
-			break;
-
-		case wrpgpr_op:
-			{
-				uint32_t css =
-				    cop0->reg[MIPS_CP0_STATUS][2] & 0xf;
-				uint32_t pss =
-				    (cop0->reg[MIPS_CP0_STATUS][2] >> 6) & 0xf;
-				/* We don't support any shadow register sets, so SRSCtl[PSS] == SRSCtl[CSS] = 0 */
-				if (css || pss) {
-					er = EMULATE_FAIL;
-					break;
-				}
-				kvm_debug("WRPGPR[%d][%d] = %#lx\n", pss, rd,
-					  vcpu->arch.gprs[rt]);
-				vcpu->arch.gprs[rd] = vcpu->arch.gprs[rt];
-			}
-			break;
-		default:
-			printk
-			    ("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n",
-			     vcpu->arch.pc, copz);
-			er = EMULATE_FAIL;
-			break;
-		}
-	}
-
-done:
-	/*
-	 * Rollback PC only if emulation was unsuccessful
-	 */
-	if (er == EMULATE_FAIL) {
-		vcpu->arch.pc = curr_pc;
-	}
-
-dont_update_pc:
-	/*
-	 * This is for special instructions whose emulation
-	 * updates the PC, so do not overwrite the PC under
-	 * any circumstances
-	 */
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
-		       struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DO_MMIO;
-	int32_t op, base, rt, offset;
-	uint32_t bytes;
-	void *data = run->mmio.data;
-	unsigned long curr_pc;
-
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
-	er = update_pc(vcpu, cause);
-	if (er == EMULATE_FAIL)
-		return er;
-
-	rt = (inst >> 16) & 0x1f;
-	base = (inst >> 21) & 0x1f;
-	offset = inst & 0xffff;
-	op = (inst >> 26) & 0x3f;
-
-	switch (op) {
-	case sb_op:
-		bytes = 1;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-		run->mmio.len = bytes;
-		run->mmio.is_write = 1;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_is_write = 1;
-		*(u8 *) data = vcpu->arch.gprs[rt];
-		kvm_debug("OP_SB: eaddr: %#lx, gpr: %#lx, data: %#x\n",
-			  vcpu->arch.host_cp0_badvaddr, vcpu->arch.gprs[rt],
-			  *(uint8_t *) data);
-
-		break;
-
-	case sw_op:
-		bytes = 4;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-
-		run->mmio.len = bytes;
-		run->mmio.is_write = 1;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_is_write = 1;
-		*(uint32_t *) data = vcpu->arch.gprs[rt];
-
-		kvm_debug("[%#lx] OP_SW: eaddr: %#lx, gpr: %#lx, data: %#x\n",
-			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
-			  vcpu->arch.gprs[rt], *(uint32_t *) data);
-		break;
-
-	case sh_op:
-		bytes = 2;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-
-		run->mmio.len = bytes;
-		run->mmio.is_write = 1;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_is_write = 1;
-		*(uint16_t *) data = vcpu->arch.gprs[rt];
-
-		kvm_debug("[%#lx] OP_SH: eaddr: %#lx, gpr: %#lx, data: %#x\n",
-			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
-			  vcpu->arch.gprs[rt], *(uint32_t *) data);
-		break;
-
-	default:
-		printk("Store not yet supported");
-		er = EMULATE_FAIL;
-		break;
-	}
-
-	/*
-	 * Rollback PC if emulation was unsuccessful
-	 */
-	if (er == EMULATE_FAIL) {
-		vcpu->arch.pc = curr_pc;
-	}
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
-		      struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DO_MMIO;
-	int32_t op, base, rt, offset;
-	uint32_t bytes;
-
-	rt = (inst >> 16) & 0x1f;
-	base = (inst >> 21) & 0x1f;
-	offset = inst & 0xffff;
-	op = (inst >> 26) & 0x3f;
-
-	vcpu->arch.pending_load_cause = cause;
-	vcpu->arch.io_gpr = rt;
-
-	switch (op) {
-	case lw_op:
-		bytes = 4;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-			er = EMULATE_FAIL;
-			break;
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-
-		run->mmio.len = bytes;
-		run->mmio.is_write = 0;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_is_write = 0;
-		break;
-
-	case lh_op:
-	case lhu_op:
-		bytes = 2;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-			er = EMULATE_FAIL;
-			break;
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-
-		run->mmio.len = bytes;
-		run->mmio.is_write = 0;
-		vcpu->mmio_needed = 1;
-		vcpu->mmio_is_write = 0;
-
-		if (op == lh_op)
-			vcpu->mmio_needed = 2;
-		else
-			vcpu->mmio_needed = 1;
-
-		break;
-
-	case lbu_op:
-	case lb_op:
-		bytes = 1;
-		if (bytes > sizeof(run->mmio.data)) {
-			kvm_err("%s: bad MMIO length: %d\n", __func__,
-			       run->mmio.len);
-			er = EMULATE_FAIL;
-			break;
-		}
-		run->mmio.phys_addr =
-		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
-						   host_cp0_badvaddr);
-		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
-			er = EMULATE_FAIL;
-			break;
-		}
-
-		run->mmio.len = bytes;
-		run->mmio.is_write = 0;
-		vcpu->mmio_is_write = 0;
-
-		if (op == lb_op)
-			vcpu->mmio_needed = 2;
-		else
-			vcpu->mmio_needed = 1;
-
-		break;
-
-	default:
-		printk("Load not yet supported");
-		er = EMULATE_FAIL;
-		break;
-	}
-
-	return er;
-}
-
-int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
-{
-	unsigned long offset = (va & ~PAGE_MASK);
-	struct kvm *kvm = vcpu->kvm;
-	unsigned long pa;
-	gfn_t gfn;
-	pfn_t pfn;
-
-	gfn = va >> PAGE_SHIFT;
-
-	if (gfn >= kvm->arch.guest_pmap_npages) {
-		printk("%s: Invalid gfn: %#llx\n", __func__, gfn);
-		kvm_mips_dump_host_tlbs();
-		kvm_arch_vcpu_dump_regs(vcpu);
-		return -1;
-	}
-	pfn = kvm->arch.guest_pmap[gfn];
-	pa = (pfn << PAGE_SHIFT) | offset;
-
-	printk("%s: va: %#lx, unmapped: %#x\n", __func__, va, CKSEG0ADDR(pa));
-
-	local_flush_icache_range(CKSEG0ADDR(pa), 32);
-	return 0;
-}
-
-#define MIPS_CACHE_OP_INDEX_INV         0x0
-#define MIPS_CACHE_OP_INDEX_LD_TAG      0x1
-#define MIPS_CACHE_OP_INDEX_ST_TAG      0x2
-#define MIPS_CACHE_OP_IMP               0x3
-#define MIPS_CACHE_OP_HIT_INV           0x4
-#define MIPS_CACHE_OP_FILL_WB_INV       0x5
-#define MIPS_CACHE_OP_HIT_HB            0x6
-#define MIPS_CACHE_OP_FETCH_LOCK        0x7
-
-#define MIPS_CACHE_ICACHE               0x0
-#define MIPS_CACHE_DCACHE               0x1
-#define MIPS_CACHE_SEC                  0x3
-
-enum emulation_result
-kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
-		       struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	extern void (*r4k_blast_dcache) (void);
-	extern void (*r4k_blast_icache) (void);
-	enum emulation_result er = EMULATE_DONE;
-	int32_t offset, cache, op_inst, op, base;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	unsigned long va;
-	unsigned long curr_pc;
-
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
-	er = update_pc(vcpu, cause);
-	if (er == EMULATE_FAIL)
-		return er;
-
-	base = (inst >> 21) & 0x1f;
-	op_inst = (inst >> 16) & 0x1f;
-	offset = inst & 0xffff;
-	cache = (inst >> 16) & 0x3;
-	op = (inst >> 18) & 0x7;
-
-	va = arch->gprs[base] + offset;
-
-	kvm_debug("CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
-		  cache, op, base, arch->gprs[base], offset);
-
-	/* Treat INDEX_INV as a nop, basically issued by Linux on startup to invalidate
-	 * the caches entirely by stepping through all the ways/indexes
-	 */
-	if (op == MIPS_CACHE_OP_INDEX_INV) {
-		kvm_debug
-		    ("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
-		     vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
-		     arch->gprs[base], offset);
-
-		if (cache == MIPS_CACHE_DCACHE)
-			r4k_blast_dcache();
-		else if (cache == MIPS_CACHE_ICACHE)
-			r4k_blast_icache();
-		else {
-			printk("%s: unsupported CACHE INDEX operation\n",
-			       __func__);
-			return EMULATE_FAIL;
-		}
-
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-		kvm_mips_trans_cache_index(inst, opc, vcpu);
-#endif
-		goto done;
-	}
-
-	preempt_disable();
-	if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
-
-		if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) {
-			kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
-		}
-	} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
-		   KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
-		int index;
-
-		/* If an entry already exists then skip */
-		if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0) {
-			goto skip_fault;
-		}
-
-		/* If address not in the guest TLB, then give the guest a fault, the
-		 * resulting handler will do the right thing
-		 */
-		index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
-						  (kvm_read_c0_guest_entryhi
-						   (cop0) & ASID_MASK));
-
-		if (index < 0) {
-			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
-			vcpu->arch.host_cp0_badvaddr = va;
-			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
-							 vcpu);
-			preempt_enable();
-			goto dont_update_pc;
-		} else {
-			struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
-			/* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
-			if (!TLB_IS_VALID(*tlb, va)) {
-				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
-								run, vcpu);
-				preempt_enable();
-				goto dont_update_pc;
-			} else {
-				/* We fault an entry from the guest tlb to the shadow host TLB */
-				kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
-								     NULL,
-								     NULL);
-			}
-		}
-	} else {
-		printk
-		    ("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
-		     cache, op, base, arch->gprs[base], offset);
-		er = EMULATE_FAIL;
-		preempt_enable();
-		goto dont_update_pc;
-
-	}
-
-skip_fault:
-	/* XXXKYMA: Only a subset of cache ops are supported, used by Linux */
-	if (cache == MIPS_CACHE_DCACHE
-	    && (op == MIPS_CACHE_OP_FILL_WB_INV
-		|| op == MIPS_CACHE_OP_HIT_INV)) {
-		flush_dcache_line(va);
-
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-		/* Replace the CACHE instruction, with a SYNCI, not the same, but avoids a trap */
-		kvm_mips_trans_cache_va(inst, opc, vcpu);
-#endif
-	} else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) {
-		flush_dcache_line(va);
-		flush_icache_line(va);
-
-#ifdef CONFIG_KVM_MIPS_DYN_TRANS
-		/* Replace the CACHE instruction, with a SYNCI */
-		kvm_mips_trans_cache_va(inst, opc, vcpu);
-#endif
-	} else {
-		printk
-		    ("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
-		     cache, op, base, arch->gprs[base], offset);
-		er = EMULATE_FAIL;
-		preempt_enable();
-		goto dont_update_pc;
-	}
-
-	preempt_enable();
-
-      dont_update_pc:
-	/*
-	 * Rollback PC
-	 */
-	vcpu->arch.pc = curr_pc;
-      done:
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
-		      struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DONE;
-	uint32_t inst;
-
-	/*
-	 *  Fetch the instruction.
-	 */
-	if (cause & CAUSEF_BD) {
-		opc += 1;
-	}
-
-	inst = kvm_get_inst(opc, vcpu);
-
-	switch (((union mips_instruction)inst).r_format.opcode) {
-	case cop0_op:
-		er = kvm_mips_emulate_CP0(inst, opc, cause, run, vcpu);
-		break;
-	case sb_op:
-	case sh_op:
-	case sw_op:
-		er = kvm_mips_emulate_store(inst, cause, run, vcpu);
-		break;
-	case lb_op:
-	case lbu_op:
-	case lhu_op:
-	case lh_op:
-	case lw_op:
-		er = kvm_mips_emulate_load(inst, cause, run, vcpu);
-		break;
-
-	case cache_op:
-		++vcpu->stat.cache_exits;
-		trace_kvm_exit(vcpu, CACHE_EXITS);
-		er = kvm_mips_emulate_cache(inst, opc, cause, run, vcpu);
-		break;
-
-	default:
-		printk("Instruction emulation not supported (%p/%#x)\n", opc,
-		       inst);
-		kvm_arch_vcpu_dump_regs(vcpu);
-		er = EMULATE_FAIL;
-		break;
-	}
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_syscall(unsigned long cause, uint32_t *opc,
-			 struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("Delivering SYSCALL @ pc %#lx\n", arch->pc);
-
-		kvm_change_c0_guest_cause(cop0, (0xff),
-					  (T_SYSCALL << CAUSEB_EXCCODE));
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-	} else {
-		printk("Trying to deliver SYSCALL when EXL is already set\n");
-		er = EMULATE_FAIL;
-	}
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
-			    struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("[EXL == 0] delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-
-		/* set pc to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x0;
-
-	} else {
-		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	}
-
-	kvm_change_c0_guest_cause(cop0, (0xff),
-				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
-
-	/* setup badvaddr, context and entryhi registers for the guest */
-	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-	/* XXXKYMA: is the context register used by linux??? */
-	kvm_write_c0_guest_entryhi(cop0, entryhi);
-	/* Blow away the shadow host TLBs */
-	kvm_mips_flush_host_tlb(1);
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
-			   struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long entryhi =
-		(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("[EXL == 0] delivering TLB INV @ pc %#lx\n",
-			  arch->pc);
-
-		/* set pc to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-	} else {
-		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	}
-
-	kvm_change_c0_guest_cause(cop0, (0xff),
-				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
-
-	/* setup badvaddr, context and entryhi registers for the guest */
-	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-	/* XXXKYMA: is the context register used by linux??? */
-	kvm_write_c0_guest_entryhi(cop0, entryhi);
-	/* Blow away the shadow host TLBs */
-	kvm_mips_flush_host_tlb(1);
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
-			    struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x0;
-	} else {
-		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	}
-
-	kvm_change_c0_guest_cause(cop0, (0xff),
-				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
-
-	/* setup badvaddr, context and entryhi registers for the guest */
-	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-	/* XXXKYMA: is the context register used by linux??? */
-	kvm_write_c0_guest_entryhi(cop0, entryhi);
-	/* Blow away the shadow host TLBs */
-	kvm_mips_flush_host_tlb(1);
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
-			   struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	} else {
-		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
-			  arch->pc);
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	}
-
-	kvm_change_c0_guest_cause(cop0, (0xff),
-				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
-
-	/* setup badvaddr, context and entryhi registers for the guest */
-	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-	/* XXXKYMA: is the context register used by linux??? */
-	kvm_write_c0_guest_entryhi(cop0, entryhi);
-	/* Blow away the shadow host TLBs */
-	kvm_mips_flush_host_tlb(1);
-
-	return er;
-}
-
-/* TLBMOD: store into address matching TLB with Dirty bit off */
-enum emulation_result
-kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
-		       struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DONE;
-#ifdef DEBUG
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-	int index;
-
-	/*
-	 * If address not in the guest TLB, then we are in trouble
-	 */
-	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
-	if (index < 0) {
-		/* XXXKYMA Invalidate and retry */
-		kvm_mips_host_tlb_inv(vcpu, vcpu->arch.host_cp0_badvaddr);
-		kvm_err("%s: host got TLBMOD for %#lx but entry not present in Guest TLB\n",
-		     __func__, entryhi);
-		kvm_mips_dump_guest_tlbs(vcpu);
-		kvm_mips_dump_host_tlbs();
-		return EMULATE_FAIL;
-	}
-#endif
-
-	er = kvm_mips_emulate_tlbmod(cause, opc, run, vcpu);
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
-			struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("[EXL == 0] Delivering TLB MOD @ pc %#lx\n",
-			  arch->pc);
-
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	} else {
-		kvm_debug("[EXL == 1] Delivering TLB MOD @ pc %#lx\n",
-			  arch->pc);
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-	}
-
-	kvm_change_c0_guest_cause(cop0, (0xff), (T_TLB_MOD << CAUSEB_EXCCODE));
-
-	/* setup badvaddr, context and entryhi registers for the guest */
-	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-	/* XXXKYMA: is the context register used by linux??? */
-	kvm_write_c0_guest_entryhi(cop0, entryhi);
-	/* Blow away the shadow host TLBs */
-	kvm_mips_flush_host_tlb(1);
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_fpu_exc(unsigned long cause, uint32_t *opc,
-			 struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-	}
-
-	arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-	kvm_change_c0_guest_cause(cop0, (0xff),
-				  (T_COP_UNUSABLE << CAUSEB_EXCCODE));
-	kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE));
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_ri_exc(unsigned long cause, uint32_t *opc,
-			struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("Delivering RI @ pc %#lx\n", arch->pc);
-
-		kvm_change_c0_guest_cause(cop0, (0xff),
-					  (T_RES_INST << CAUSEB_EXCCODE));
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-	} else {
-		kvm_err("Trying to deliver RI when EXL is already set\n");
-		er = EMULATE_FAIL;
-	}
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc,
-			struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_debug("Delivering BP @ pc %#lx\n", arch->pc);
-
-		kvm_change_c0_guest_cause(cop0, (0xff),
-					  (T_BREAK << CAUSEB_EXCCODE));
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-	} else {
-		printk("Trying to deliver BP when EXL is already set\n");
-		er = EMULATE_FAIL;
-	}
-
-	return er;
-}
-
-/*
- * ll/sc, rdhwr, sync emulation
- */
-
-#define OPCODE 0xfc000000
-#define BASE   0x03e00000
-#define RT     0x001f0000
-#define OFFSET 0x0000ffff
-#define LL     0xc0000000
-#define SC     0xe0000000
-#define SPEC0  0x00000000
-#define SPEC3  0x7c000000
-#define RD     0x0000f800
-#define FUNC   0x0000003f
-#define SYNC   0x0000000f
-#define RDHWR  0x0000003b
-
-enum emulation_result
-kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
-		   struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long curr_pc;
-	uint32_t inst;
-
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
-	er = update_pc(vcpu, cause);
-	if (er == EMULATE_FAIL)
-		return er;
-
-	/*
-	 *  Fetch the instruction.
-	 */
-	if (cause & CAUSEF_BD)
-		opc += 1;
-
-	inst = kvm_get_inst(opc, vcpu);
-
-	if (inst == KVM_INVALID_INST) {
-		printk("%s: Cannot get inst @ %p\n", __func__, opc);
-		return EMULATE_FAIL;
-	}
-
-	if ((inst & OPCODE) == SPEC3 && (inst & FUNC) == RDHWR) {
-		int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
-		int rd = (inst & RD) >> 11;
-		int rt = (inst & RT) >> 16;
-		/* If usermode, check RDHWR rd is allowed by guest HWREna */
-		if (usermode && !(kvm_read_c0_guest_hwrena(cop0) & BIT(rd))) {
-			kvm_debug("RDHWR %#x disallowed by HWREna @ %p\n",
-				  rd, opc);
-			goto emulate_ri;
-		}
-		switch (rd) {
-		case 0:	/* CPU number */
-			arch->gprs[rt] = 0;
-			break;
-		case 1:	/* SYNCI length */
-			arch->gprs[rt] = min(current_cpu_data.dcache.linesz,
-					     current_cpu_data.icache.linesz);
-			break;
-		case 2:	/* Read count register */
-			arch->gprs[rt] = kvm_mips_read_count(vcpu);
-			break;
-		case 3:	/* Count register resolution */
-			switch (current_cpu_data.cputype) {
-			case CPU_20KC:
-			case CPU_25KF:
-				arch->gprs[rt] = 1;
-				break;
-			default:
-				arch->gprs[rt] = 2;
-			}
-			break;
-		case 29:
-			arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
-			break;
-
-		default:
-			kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
-			goto emulate_ri;
-		}
-	} else {
-		kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
-		goto emulate_ri;
-	}
-
-	return EMULATE_DONE;
-
-emulate_ri:
-	/*
-	 * Rollback PC (if in branch delay slot then the PC already points to
-	 * branch target), and pass the RI exception to the guest OS.
-	 */
-	vcpu->arch.pc = curr_pc;
-	return kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
-}
-
-enum emulation_result
-kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
-	enum emulation_result er = EMULATE_DONE;
-	unsigned long curr_pc;
-
-	if (run->mmio.len > sizeof(*gpr)) {
-		printk("Bad MMIO length: %d", run->mmio.len);
-		er = EMULATE_FAIL;
-		goto done;
-	}
-
-	/*
-	 * Update PC and hold onto current PC in case there is
-	 * an error and we want to rollback the PC
-	 */
-	curr_pc = vcpu->arch.pc;
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
-
-	switch (run->mmio.len) {
-	case 4:
-		*gpr = *(int32_t *) run->mmio.data;
-		break;
-
-	case 2:
-		if (vcpu->mmio_needed == 2)
-			*gpr = *(int16_t *) run->mmio.data;
-		else
-			*gpr = *(int16_t *) run->mmio.data;
-
-		break;
-	case 1:
-		if (vcpu->mmio_needed == 2)
-			*gpr = *(int8_t *) run->mmio.data;
-		else
-			*gpr = *(u8 *) run->mmio.data;
-		break;
-	}
-
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug
-		    ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-		     vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-		     vcpu->mmio_needed);
-
-done:
-	return er;
-}
-
-static enum emulation_result
-kvm_mips_emulate_exc(unsigned long cause, uint32_t *opc,
-		     struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	enum emulation_result er = EMULATE_DONE;
-
-	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-		/* save old pc */
-		kvm_write_c0_guest_epc(cop0, arch->pc);
-		kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-		if (cause & CAUSEF_BD)
-			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-		else
-			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-		kvm_change_c0_guest_cause(cop0, (0xff),
-					  (exccode << CAUSEB_EXCCODE));
-
-		/* Set PC to the exception entry point */
-		arch->pc = KVM_GUEST_KSEG0 + 0x180;
-		kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
-
-		kvm_debug("Delivering EXC %d @ pc %#lx, badVaddr: %#lx\n",
-			  exccode, kvm_read_c0_guest_epc(cop0),
-			  kvm_read_c0_guest_badvaddr(cop0));
-	} else {
-		printk("Trying to deliver EXC when EXL is already set\n");
-		er = EMULATE_FAIL;
-	}
-
-	return er;
-}
-
-enum emulation_result
-kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
-			 struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DONE;
-	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-
-	int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
-
-	if (usermode) {
-		switch (exccode) {
-		case T_INT:
-		case T_SYSCALL:
-		case T_BREAK:
-		case T_RES_INST:
-			break;
-
-		case T_COP_UNUSABLE:
-			if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 0)
-				er = EMULATE_PRIV_FAIL;
-			break;
-
-		case T_TLB_MOD:
-			break;
-
-		case T_TLB_LD_MISS:
-			/* We we are accessing Guest kernel space, then send an address error exception to the guest */
-			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
-				printk("%s: LD MISS @ %#lx\n", __func__,
-				       badvaddr);
-				cause &= ~0xff;
-				cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE);
-				er = EMULATE_PRIV_FAIL;
-			}
-			break;
-
-		case T_TLB_ST_MISS:
-			/* We we are accessing Guest kernel space, then send an address error exception to the guest */
-			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
-				printk("%s: ST MISS @ %#lx\n", __func__,
-				       badvaddr);
-				cause &= ~0xff;
-				cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE);
-				er = EMULATE_PRIV_FAIL;
-			}
-			break;
-
-		case T_ADDR_ERR_ST:
-			printk("%s: address error ST @ %#lx\n", __func__,
-			       badvaddr);
-			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
-				cause &= ~0xff;
-				cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE);
-			}
-			er = EMULATE_PRIV_FAIL;
-			break;
-		case T_ADDR_ERR_LD:
-			printk("%s: address error LD @ %#lx\n", __func__,
-			       badvaddr);
-			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
-				cause &= ~0xff;
-				cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE);
-			}
-			er = EMULATE_PRIV_FAIL;
-			break;
-		default:
-			er = EMULATE_PRIV_FAIL;
-			break;
-		}
-	}
-
-	if (er == EMULATE_PRIV_FAIL) {
-		kvm_mips_emulate_exc(cause, opc, run, vcpu);
-	}
-	return er;
-}
-
-/* User Address (UA) fault, this could happen if
- * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
- *     case we pass on the fault to the guest kernel and let it handle it.
- * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
- *     case we inject the TLB from the Guest TLB into the shadow host TLB
- */
-enum emulation_result
-kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
-			struct kvm_run *run, struct kvm_vcpu *vcpu)
-{
-	enum emulation_result er = EMULATE_DONE;
-	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
-	unsigned long va = vcpu->arch.host_cp0_badvaddr;
-	int index;
-
-	kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx, entryhi: %#lx\n",
-		  vcpu->arch.host_cp0_badvaddr, vcpu->arch.host_cp0_entryhi);
-
-	/* KVM would not have got the exception if this entry was valid in the shadow host TLB
-	 * Check the Guest TLB, if the entry is not there then send the guest an
-	 * exception. The guest exc handler should then inject an entry into the
-	 * guest TLB
-	 */
-	index = kvm_mips_guest_tlb_lookup(vcpu,
-					  (va & VPN2_MASK) |
-					  (kvm_read_c0_guest_entryhi
-					   (vcpu->arch.cop0) & ASID_MASK));
-	if (index < 0) {
-		if (exccode == T_TLB_LD_MISS) {
-			er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
-		} else if (exccode == T_TLB_ST_MISS) {
-			er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);
-		} else {
-			printk("%s: invalid exc code: %d\n", __func__, exccode);
-			er = EMULATE_FAIL;
-		}
-	} else {
-		struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
-
-		/* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
-		if (!TLB_IS_VALID(*tlb, va)) {
-			if (exccode == T_TLB_LD_MISS) {
-				er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,
-								vcpu);
-			} else if (exccode == T_TLB_ST_MISS) {
-				er = kvm_mips_emulate_tlbinv_st(cause, opc, run,
-								vcpu);
-			} else {
-				printk("%s: invalid exc code: %d\n", __func__,
-				       exccode);
-				er = EMULATE_FAIL;
-			}
-		} else {
-			kvm_debug
-			    ("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
-			     tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
-			/* OK we have a Guest TLB entry, now inject it into the shadow host TLB */
-			kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
-							     NULL);
-		}
-	}
-
-	return er;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_int.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_int.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_int.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_int.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,243 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Interrupt delivery
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-
-#include <linux/kvm_host.h>
-
-#include "kvm_mips_int.h"
-
-void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
-{
-	set_bit(priority, &vcpu->arch.pending_exceptions);
-}
-
-void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
-{
-	clear_bit(priority, &vcpu->arch.pending_exceptions);
-}
-
-void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu)
-{
-	/* Cause bits to reflect the pending timer interrupt,
-	 * the EXC code will be set when we are actually
-	 * delivering the interrupt:
-	 */
-	kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
-
-	/* Queue up an INT exception for the core */
-	kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_TIMER);
-
-}
-
-void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu)
-{
-	kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
-	kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER);
-}
-
-void
-kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
-{
-	int intr = (int)irq->irq;
-
-	/* Cause bits to reflect the pending IO interrupt,
-	 * the EXC code will be set when we are actually
-	 * delivering the interrupt:
-	 */
-	switch (intr) {
-	case 2:
-		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
-		/* Queue up an INT exception for the core */
-		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IO);
-		break;
-
-	case 3:
-		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
-		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_1);
-		break;
-
-	case 4:
-		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
-		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_2);
-		break;
-
-	default:
-		break;
-	}
-
-}
-
-void
-kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
-			   struct kvm_mips_interrupt *irq)
-{
-	int intr = (int)irq->irq;
-	switch (intr) {
-	case -2:
-		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
-		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IO);
-		break;
-
-	case -3:
-		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
-		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_1);
-		break;
-
-	case -4:
-		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
-		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_2);
-		break;
-
-	default:
-		break;
-	}
-
-}
-
-/* Deliver the interrupt of the corresponding priority, if possible. */
-int
-kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
-			uint32_t cause)
-{
-	int allowed = 0;
-	uint32_t exccode;
-
-	struct kvm_vcpu_arch *arch = &vcpu->arch;
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-	switch (priority) {
-	case MIPS_EXC_INT_TIMER:
-		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
-		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
-		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ5)) {
-			allowed = 1;
-			exccode = T_INT;
-		}
-		break;
-
-	case MIPS_EXC_INT_IO:
-		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
-		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
-		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ0)) {
-			allowed = 1;
-			exccode = T_INT;
-		}
-		break;
-
-	case MIPS_EXC_INT_IPI_1:
-		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
-		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
-		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ1)) {
-			allowed = 1;
-			exccode = T_INT;
-		}
-		break;
-
-	case MIPS_EXC_INT_IPI_2:
-		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
-		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
-		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ2)) {
-			allowed = 1;
-			exccode = T_INT;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	/* Are we allowed to deliver the interrupt ??? */
-	if (allowed) {
-
-		if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
-			/* save old pc */
-			kvm_write_c0_guest_epc(cop0, arch->pc);
-			kvm_set_c0_guest_status(cop0, ST0_EXL);
-
-			if (cause & CAUSEF_BD)
-				kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
-			else
-				kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
-
-			kvm_debug("Delivering INT @ pc %#lx\n", arch->pc);
-
-		} else
-			kvm_err("Trying to deliver interrupt when EXL is already set\n");
-
-		kvm_change_c0_guest_cause(cop0, CAUSEF_EXCCODE,
-					  (exccode << CAUSEB_EXCCODE));
-
-		/* XXXSL Set PC to the interrupt exception entry point */
-		if (kvm_read_c0_guest_cause(cop0) & CAUSEF_IV)
-			arch->pc = KVM_GUEST_KSEG0 + 0x200;
-		else
-			arch->pc = KVM_GUEST_KSEG0 + 0x180;
-
-		clear_bit(priority, &vcpu->arch.pending_exceptions);
-	}
-
-	return allowed;
-}
-
-int
-kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
-		      uint32_t cause)
-{
-	return 1;
-}
-
-void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause)
-{
-	unsigned long *pending = &vcpu->arch.pending_exceptions;
-	unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr;
-	unsigned int priority;
-
-	if (!(*pending) && !(*pending_clr))
-		return;
-
-	priority = __ffs(*pending_clr);
-	while (priority <= MIPS_EXC_MAX) {
-		if (kvm_mips_callbacks->irq_clear(vcpu, priority, cause)) {
-			if (!KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE)
-				break;
-		}
-
-		priority = find_next_bit(pending_clr,
-					 BITS_PER_BYTE * sizeof(*pending_clr),
-					 priority + 1);
-	}
-
-	priority = __ffs(*pending);
-	while (priority <= MIPS_EXC_MAX) {
-		if (kvm_mips_callbacks->irq_deliver(vcpu, priority, cause)) {
-			if (!KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE)
-				break;
-		}
-
-		priority = find_next_bit(pending,
-					 BITS_PER_BYTE * sizeof(*pending),
-					 priority + 1);
-	}
-
-}
-
-int kvm_mips_pending_timer(struct kvm_vcpu *vcpu)
-{
-	return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_int.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_int.h
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_int.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_int.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Interrupts
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-/* MIPS Exception Priorities, exceptions (including interrupts) are queued up
- * for the guest in the order specified by their priorities
- */
-
-#define MIPS_EXC_RESET              0
-#define MIPS_EXC_SRESET             1
-#define MIPS_EXC_DEBUG_ST           2
-#define MIPS_EXC_DEBUG              3
-#define MIPS_EXC_DDB                4
-#define MIPS_EXC_NMI                5
-#define MIPS_EXC_MCHK               6
-#define MIPS_EXC_INT_TIMER          7
-#define MIPS_EXC_INT_IO             8
-#define MIPS_EXC_EXECUTE            9
-#define MIPS_EXC_INT_IPI_1          10
-#define MIPS_EXC_INT_IPI_2          11
-#define MIPS_EXC_MAX                12
-/* XXXSL More to follow */
-
-#define C_TI        (_ULCAST_(1) << 30)
-
-#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0)
-#define KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE   (0)
-
-void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
-void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
-int kvm_mips_pending_timer(struct kvm_vcpu *vcpu);
-
-void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu);
-void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu);
-void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
-			      struct kvm_mips_interrupt *irq);
-void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
-				struct kvm_mips_interrupt *irq);
-int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
-			    uint32_t cause);
-int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
-			  uint32_t cause);
-void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_opcode.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_opcode.h
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_opcode.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_opcode.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-/*
- * Define opcode values not defined in <asm/isnt.h>
- */
-
-#ifndef __KVM_MIPS_OPCODE_H__
-#define __KVM_MIPS_OPCODE_H__
-
-/* COP0 Ops */
-#define     mfmcz_op         0x0b	/*  01011  */
-#define     wrpgpr_op        0x0e	/*  01110  */
-
-/*  COP0 opcodes (only if COP0 and CO=1):  */
-#define     wait_op               0x20	/*  100000  */
-
-#endif /* __KVM_MIPS_OPCODE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_stats.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_stats.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_mips_stats.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_mips_stats.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: COP0 access histogram
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/kvm_host.h>
-
-char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = {
-	"WAIT",
-	"CACHE",
-	"Signal",
-	"Interrupt",
-	"COP0/1 Unusable",
-	"TLB Mod",
-	"TLB Miss (LD)",
-	"TLB Miss (ST)",
-	"Address Err (ST)",
-	"Address Error (LD)",
-	"System Call",
-	"Reserved Inst",
-	"Break Inst",
-	"D-Cache Flushes",
-};
-
-char *kvm_cop0_str[N_MIPS_COPROC_REGS] = {
-	"Index",
-	"Random",
-	"EntryLo0",
-	"EntryLo1",
-	"Context",
-	"PG Mask",
-	"Wired",
-	"HWREna",
-	"BadVAddr",
-	"Count",
-	"EntryHI",
-	"Compare",
-	"Status",
-	"Cause",
-	"EXC PC",
-	"PRID",
-	"Config",
-	"LLAddr",
-	"Watch Lo",
-	"Watch Hi",
-	"X Context",
-	"Reserved",
-	"Impl Dep",
-	"Debug",
-	"DEPC",
-	"PerfCnt",
-	"ErrCtl",
-	"CacheErr",
-	"TagLo",
-	"TagHi",
-	"ErrorEPC",
-	"DESAVE"
-};
-
-int kvm_mips_dump_stats(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
-	int i, j;
-
-	printk("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id);
-	for (i = 0; i < N_MIPS_COPROC_REGS; i++) {
-		for (j = 0; j < N_MIPS_COPROC_SEL; j++) {
-			if (vcpu->arch.cop0->stat[i][j])
-				printk("%s[%d]: %lu\n", kvm_cop0_str[i], j,
-				       vcpu->arch.cop0->stat[i][j]);
-		}
-	}
-#endif
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_tlb.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_tlb.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_tlb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_tlb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,819 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
-* TLB handlers run from KSEG0
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/kvm_host.h>
-#include <linux/srcu.h>
-
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/mmu_context.h>
-#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-#include <asm/tlb.h>
-
-#undef CONFIG_MIPS_MT
-#include <asm/r4kcache.h>
-#define CONFIG_MIPS_MT
-
-#define KVM_GUEST_PC_TLB    0
-#define KVM_GUEST_SP_TLB    1
-
-#define PRIx64 "llx"
-
-atomic_t kvm_mips_instance;
-EXPORT_SYMBOL(kvm_mips_instance);
-
-/* These function pointers are initialized once the KVM module is loaded */
-pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn);
-EXPORT_SYMBOL(kvm_mips_gfn_to_pfn);
-
-void (*kvm_mips_release_pfn_clean) (pfn_t pfn);
-EXPORT_SYMBOL(kvm_mips_release_pfn_clean);
-
-bool(*kvm_mips_is_error_pfn) (pfn_t pfn);
-EXPORT_SYMBOL(kvm_mips_is_error_pfn);
-
-uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
-}
-
-
-uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
-}
-
-inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
-{
-	return vcpu->kvm->arch.commpage_tlb;
-}
-
-
-/*
- * Structure defining an tlb entry data set.
- */
-
-void kvm_mips_dump_host_tlbs(void)
-{
-	unsigned long old_entryhi;
-	unsigned long old_pagemask;
-	struct kvm_mips_tlb tlb;
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-
-	old_entryhi = read_c0_entryhi();
-	old_pagemask = read_c0_pagemask();
-
-	printk("HOST TLBs:\n");
-	printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
-
-	for (i = 0; i < current_cpu_data.tlbsize; i++) {
-		write_c0_index(i);
-		mtc0_tlbw_hazard();
-
-		tlb_read();
-		tlbw_use_hazard();
-
-		tlb.tlb_hi = read_c0_entryhi();
-		tlb.tlb_lo0 = read_c0_entrylo0();
-		tlb.tlb_lo1 = read_c0_entrylo1();
-		tlb.tlb_mask = read_c0_pagemask();
-
-		printk("TLB%c%3d Hi 0x%08lx ",
-		       (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
-		       i, tlb.tlb_hi);
-		printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
-		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
-		       (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
-		       (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
-		       (tlb.tlb_lo0 >> 3) & 7);
-		printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
-		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
-		       (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
-		       (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
-		       (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
-	}
-	write_c0_entryhi(old_entryhi);
-	write_c0_pagemask(old_pagemask);
-	mtc0_tlbw_hazard();
-	local_irq_restore(flags);
-}
-
-void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	struct kvm_mips_tlb tlb;
-	int i;
-
-	printk("Guest TLBs:\n");
-	printk("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
-
-	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
-		tlb = vcpu->arch.guest_tlb[i];
-		printk("TLB%c%3d Hi 0x%08lx ",
-		       (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
-		       i, tlb.tlb_hi);
-		printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
-		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
-		       (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
-		       (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
-		       (tlb.tlb_lo0 >> 3) & 7);
-		printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
-		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
-		       (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
-		       (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
-		       (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
-	}
-}
-
-static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
-{
-	int srcu_idx, err = 0;
-	pfn_t pfn;
-
-	if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)
-		return 0;
-
-        srcu_idx = srcu_read_lock(&kvm->srcu);
-	pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
-
-	if (kvm_mips_is_error_pfn(pfn)) {
-		kvm_err("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
-		err = -EFAULT;
-		goto out;
-	}
-
-	kvm->arch.guest_pmap[gfn] = pfn;
-out:
-	srcu_read_unlock(&kvm->srcu, srcu_idx);
-	return err;
-}
-
-/* Translate guest KSEG0 addresses to Host PA */
-unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
-	unsigned long gva)
-{
-	gfn_t gfn;
-	uint32_t offset = gva & ~PAGE_MASK;
-	struct kvm *kvm = vcpu->kvm;
-
-	if (KVM_GUEST_KSEGX(gva) != KVM_GUEST_KSEG0) {
-		kvm_err("%s/%p: Invalid gva: %#lx\n", __func__,
-			__builtin_return_address(0), gva);
-		return KVM_INVALID_PAGE;
-	}
-
-	gfn = (KVM_GUEST_CPHYSADDR(gva) >> PAGE_SHIFT);
-
-	if (gfn >= kvm->arch.guest_pmap_npages) {
-		kvm_err("%s: Invalid gfn: %#llx, GVA: %#lx\n", __func__, gfn,
-			gva);
-		return KVM_INVALID_PAGE;
-	}
-
-	if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
-		return KVM_INVALID_ADDR;
-
-	return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
-}
-
-/* XXXKYMA: Must be called with interrupts disabled */
-/* set flush_dcache_mask == 0 if no dcache flush required */
-int
-kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
-	unsigned long entrylo0, unsigned long entrylo1, int flush_dcache_mask)
-{
-	unsigned long flags;
-	unsigned long old_entryhi;
-	volatile int idx;
-
-	local_irq_save(flags);
-
-
-	old_entryhi = read_c0_entryhi();
-	write_c0_entryhi(entryhi);
-	mtc0_tlbw_hazard();
-
-	tlb_probe();
-	tlb_probe_hazard();
-	idx = read_c0_index();
-
-	if (idx > current_cpu_data.tlbsize) {
-		kvm_err("%s: Invalid Index: %d\n", __func__, idx);
-		kvm_mips_dump_host_tlbs();
-		return -1;
-	}
-
-	write_c0_entrylo0(entrylo0);
-	write_c0_entrylo1(entrylo1);
-	mtc0_tlbw_hazard();
-
-	if (idx < 0)
-		tlb_write_random();
-	else
-		tlb_write_indexed();
-	tlbw_use_hazard();
-
-	kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n",
-		  vcpu->arch.pc, idx, read_c0_entryhi(),
-		  read_c0_entrylo0(), read_c0_entrylo1());
-
-	/* Flush D-cache */
-	if (flush_dcache_mask) {
-		if (entrylo0 & MIPS3_PG_V) {
-			++vcpu->stat.flush_dcache_exits;
-			flush_data_cache_page((entryhi & VPN2_MASK) & ~flush_dcache_mask);
-		}
-		if (entrylo1 & MIPS3_PG_V) {
-			++vcpu->stat.flush_dcache_exits;
-			flush_data_cache_page(((entryhi & VPN2_MASK) & ~flush_dcache_mask) |
-				(0x1 << PAGE_SHIFT));
-		}
-	}
-
-	/* Restore old ASID */
-	write_c0_entryhi(old_entryhi);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-	local_irq_restore(flags);
-	return 0;
-}
-
-
-/* XXXKYMA: Must be called with interrupts disabled */
-int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
-	struct kvm_vcpu *vcpu)
-{
-	gfn_t gfn;
-	pfn_t pfn0, pfn1;
-	unsigned long vaddr = 0;
-	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
-	int even;
-	struct kvm *kvm = vcpu->kvm;
-	const int flush_dcache_mask = 0;
-
-
-	if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) {
-		kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		return -1;
-	}
-
-	gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
-	if (gfn >= kvm->arch.guest_pmap_npages) {
-		kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
-			gfn, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		return -1;
-	}
-	even = !(gfn & 0x1);
-	vaddr = badvaddr & (PAGE_MASK << 1);
-
-	if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
-		return -1;
-
-	if (kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1) < 0)
-		return -1;
-
-	if (even) {
-		pfn0 = kvm->arch.guest_pmap[gfn];
-		pfn1 = kvm->arch.guest_pmap[gfn ^ 0x1];
-	} else {
-		pfn0 = kvm->arch.guest_pmap[gfn ^ 0x1];
-		pfn1 = kvm->arch.guest_pmap[gfn];
-	}
-
-	entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
-	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
-			(0x1 << 1);
-	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
-			(0x1 << 1);
-
-	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
-				       flush_dcache_mask);
-}
-
-int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
-	struct kvm_vcpu *vcpu)
-{
-	pfn_t pfn0, pfn1;
-	unsigned long flags, old_entryhi = 0, vaddr = 0;
-	unsigned long entrylo0 = 0, entrylo1 = 0;
-
-
-	pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
-	pfn1 = 0;
-	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
-			(0x1 << 1);
-	entrylo1 = 0;
-
-	local_irq_save(flags);
-
-	old_entryhi = read_c0_entryhi();
-	vaddr = badvaddr & (PAGE_MASK << 1);
-	write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu));
-	mtc0_tlbw_hazard();
-	write_c0_entrylo0(entrylo0);
-	mtc0_tlbw_hazard();
-	write_c0_entrylo1(entrylo1);
-	mtc0_tlbw_hazard();
-	write_c0_index(kvm_mips_get_commpage_asid(vcpu));
-	mtc0_tlbw_hazard();
-	tlb_write_indexed();
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	kvm_debug ("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
-	     vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
-	     read_c0_entrylo0(), read_c0_entrylo1());
-
-	/* Restore old ASID */
-	write_c0_entryhi(old_entryhi);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-int
-kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
-	struct kvm_mips_tlb *tlb, unsigned long *hpa0, unsigned long *hpa1)
-{
-	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
-	struct kvm *kvm = vcpu->kvm;
-	pfn_t pfn0, pfn1;
-
-
-	if ((tlb->tlb_hi & VPN2_MASK) == 0) {
-		pfn0 = 0;
-		pfn1 = 0;
-	} else {
-		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT) < 0)
-			return -1;
-
-		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT) < 0)
-			return -1;
-
-		pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT];
-		pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT];
-	}
-
-	if (hpa0)
-		*hpa0 = pfn0 << PAGE_SHIFT;
-
-	if (hpa1)
-		*hpa1 = pfn1 << PAGE_SHIFT;
-
-	/* Get attributes from the Guest TLB */
-	entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
-			kvm_mips_get_kernel_asid(vcpu) : kvm_mips_get_user_asid(vcpu));
-	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
-			(tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
-	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
-			(tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
-
-	kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
-		  tlb->tlb_lo0, tlb->tlb_lo1);
-
-	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
-				       tlb->tlb_mask);
-}
-
-int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
-{
-	int i;
-	int index = -1;
-	struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb;
-
-
-	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
-		if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
-			(TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) {
-			index = i;
-			break;
-		}
-	}
-
-	kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n",
-		  __func__, entryhi, index, tlb[i].tlb_lo0, tlb[i].tlb_lo1);
-
-	return index;
-}
-
-int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
-{
-	unsigned long old_entryhi, flags;
-	volatile int idx;
-
-
-	local_irq_save(flags);
-
-	old_entryhi = read_c0_entryhi();
-
-	if (KVM_GUEST_KERNEL_MODE(vcpu))
-		write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_kernel_asid(vcpu));
-	else {
-		write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
-	}
-
-	mtc0_tlbw_hazard();
-
-	tlb_probe();
-	tlb_probe_hazard();
-	idx = read_c0_index();
-
-	/* Restore old ASID */
-	write_c0_entryhi(old_entryhi);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	local_irq_restore(flags);
-
-	kvm_debug("Host TLB lookup, %#lx, idx: %2d\n", vaddr, idx);
-
-	return idx;
-}
-
-int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
-{
-	int idx;
-	unsigned long flags, old_entryhi;
-
-	local_irq_save(flags);
-
-
-	old_entryhi = read_c0_entryhi();
-
-	write_c0_entryhi((va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
-	mtc0_tlbw_hazard();
-
-	tlb_probe();
-	tlb_probe_hazard();
-	idx = read_c0_index();
-
-	if (idx >= current_cpu_data.tlbsize)
-		BUG();
-
-	if (idx > 0) {
-		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
-		mtc0_tlbw_hazard();
-
-		write_c0_entrylo0(0);
-		mtc0_tlbw_hazard();
-
-		write_c0_entrylo1(0);
-		mtc0_tlbw_hazard();
-
-		tlb_write_indexed();
-		mtc0_tlbw_hazard();
-	}
-
-	write_c0_entryhi(old_entryhi);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	local_irq_restore(flags);
-
-	if (idx > 0)
-		kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
-			  (va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu), idx);
-
-	return 0;
-}
-
-/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID*/
-int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
-{
-	unsigned long flags, old_entryhi;
-
-	if (index >= current_cpu_data.tlbsize)
-		BUG();
-
-	local_irq_save(flags);
-
-
-	old_entryhi = read_c0_entryhi();
-
-	write_c0_entryhi(UNIQUE_ENTRYHI(index));
-	mtc0_tlbw_hazard();
-
-	write_c0_index(index);
-	mtc0_tlbw_hazard();
-
-	write_c0_entrylo0(0);
-	mtc0_tlbw_hazard();
-
-	write_c0_entrylo1(0);
-	mtc0_tlbw_hazard();
-
-	tlb_write_indexed();
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	write_c0_entryhi(old_entryhi);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-void kvm_mips_flush_host_tlb(int skip_kseg0)
-{
-	unsigned long flags;
-	unsigned long old_entryhi, entryhi;
-	unsigned long old_pagemask;
-	int entry = 0;
-	int maxentry = current_cpu_data.tlbsize;
-
-
-	local_irq_save(flags);
-
-	old_entryhi = read_c0_entryhi();
-	old_pagemask = read_c0_pagemask();
-
-	/* Blast 'em all away. */
-	for (entry = 0; entry < maxentry; entry++) {
-
-		write_c0_index(entry);
-		mtc0_tlbw_hazard();
-
-		if (skip_kseg0) {
-			tlb_read();
-			tlbw_use_hazard();
-
-			entryhi = read_c0_entryhi();
-
-			/* Don't blow away guest kernel entries */
-			if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0) {
-				continue;
-			}
-		}
-
-		/* Make sure all entries differ. */
-		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
-		mtc0_tlbw_hazard();
-		write_c0_entrylo0(0);
-		mtc0_tlbw_hazard();
-		write_c0_entrylo1(0);
-		mtc0_tlbw_hazard();
-
-		tlb_write_indexed();
-		mtc0_tlbw_hazard();
-	}
-
-	tlbw_use_hazard();
-
-	write_c0_entryhi(old_entryhi);
-	write_c0_pagemask(old_pagemask);
-	mtc0_tlbw_hazard();
-	tlbw_use_hazard();
-
-	local_irq_restore(flags);
-}
-
-void
-kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
-			struct kvm_vcpu *vcpu)
-{
-	unsigned long asid = asid_cache(cpu);
-
-	if (!((asid += ASID_INC) & ASID_MASK)) {
-		if (cpu_has_vtag_icache) {
-			flush_icache_all();
-		}
-
-		kvm_local_flush_tlb_all();      /* start new asid cycle */
-
-		if (!asid)      /* fix version if needed */
-			asid = ASID_FIRST_VERSION;
-	}
-
-	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
-}
-
-void kvm_local_flush_tlb_all(void)
-{
-	unsigned long flags;
-	unsigned long old_ctx;
-	int entry = 0;
-
-	local_irq_save(flags);
-	/* Save old context and create impossible VPN2 value */
-	old_ctx = read_c0_entryhi();
-	write_c0_entrylo0(0);
-	write_c0_entrylo1(0);
-
-	/* Blast 'em all away. */
-	while (entry < current_cpu_data.tlbsize) {
-		/* Make sure all entries differ. */
-		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
-		write_c0_index(entry);
-		mtc0_tlbw_hazard();
-		tlb_write_indexed();
-		entry++;
-	}
-	tlbw_use_hazard();
-	write_c0_entryhi(old_ctx);
-	mtc0_tlbw_hazard();
-
-	local_irq_restore(flags);
-}
-
-/**
- * kvm_mips_migrate_count() - Migrate timer.
- * @vcpu:	Virtual CPU.
- *
- * Migrate CP0_Count hrtimer to the current CPU by cancelling and restarting it
- * if it was running prior to being cancelled.
- *
- * Must be called when the VCPU is migrated to a different CPU to ensure that
- * timer expiry during guest execution interrupts the guest and causes the
- * interrupt to be delivered in a timely manner.
- */
-static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu)
-{
-	if (hrtimer_cancel(&vcpu->arch.comparecount_timer))
-		hrtimer_restart(&vcpu->arch.comparecount_timer);
-}
-
-/* Restore ASID once we are scheduled back after preemption */
-void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
-	unsigned long flags;
-	int newasid = 0;
-
-	kvm_debug("%s: vcpu %p, cpu: %d\n", __func__, vcpu, cpu);
-
-	/* Alocate new kernel and user ASIDs if needed */
-
-	local_irq_save(flags);
-
-	if (((vcpu->arch.
-	      guest_kernel_asid[cpu] ^ asid_cache(cpu)) & ASID_VERSION_MASK)) {
-		kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
-		vcpu->arch.guest_kernel_asid[cpu] =
-		    vcpu->arch.guest_kernel_mm.context.asid[cpu];
-		kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);
-		vcpu->arch.guest_user_asid[cpu] =
-		    vcpu->arch.guest_user_mm.context.asid[cpu];
-		newasid++;
-
-		kvm_debug("[%d]: cpu_context: %#lx\n", cpu,
-			  cpu_context(cpu, current->mm));
-		kvm_debug("[%d]: Allocated new ASID for Guest Kernel: %#x\n",
-			  cpu, vcpu->arch.guest_kernel_asid[cpu]);
-		kvm_debug("[%d]: Allocated new ASID for Guest User: %#x\n", cpu,
-			  vcpu->arch.guest_user_asid[cpu]);
-	}
-
-	if (vcpu->arch.last_sched_cpu != cpu) {
-		kvm_debug("[%d->%d]KVM VCPU[%d] switch\n",
-			  vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
-		/*
-		 * Migrate the timer interrupt to the current CPU so that it
-		 * always interrupts the guest and synchronously triggers a
-		 * guest timer interrupt.
-		 */
-		kvm_mips_migrate_count(vcpu);
-	}
-
-	if (!newasid) {
-		/* If we preempted while the guest was executing, then reload the pre-empted ASID */
-		if (current->flags & PF_VCPU) {
-			write_c0_entryhi(vcpu->arch.
-					 preempt_entryhi & ASID_MASK);
-			ehb();
-		}
-	} else {
-		/* New ASIDs were allocated for the VM */
-
-		/* Were we in guest context? If so then the pre-empted ASID is no longer
-		 * valid, we need to set it to what it should be based on the mode of
-		 * the Guest (Kernel/User)
-		 */
-		if (current->flags & PF_VCPU) {
-			if (KVM_GUEST_KERNEL_MODE(vcpu))
-				write_c0_entryhi(vcpu->arch.
-						 guest_kernel_asid[cpu] &
-						 ASID_MASK);
-			else
-				write_c0_entryhi(vcpu->arch.
-						 guest_user_asid[cpu] &
-						 ASID_MASK);
-			ehb();
-		}
-	}
-
-	local_irq_restore(flags);
-
-}
-
-/* ASID can change if another task is scheduled during preemption */
-void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
-{
-	unsigned long flags;
-	uint32_t cpu;
-
-	local_irq_save(flags);
-
-	cpu = smp_processor_id();
-
-
-	vcpu->arch.preempt_entryhi = read_c0_entryhi();
-	vcpu->arch.last_sched_cpu = cpu;
-
-	if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
-	     ASID_VERSION_MASK)) {
-		kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
-			  cpu_context(cpu, current->mm));
-		drop_mmu_context(current->mm, cpu);
-	}
-	write_c0_entryhi(cpu_asid(cpu, current->mm));
-	ehb();
-
-	local_irq_restore(flags);
-}
-
-uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	unsigned long paddr, flags;
-	uint32_t inst;
-	int index;
-
-	if (KVM_GUEST_KSEGX((unsigned long) opc) < KVM_GUEST_KSEG0 ||
-	    KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
-		local_irq_save(flags);
-		index = kvm_mips_host_tlb_lookup(vcpu, (unsigned long) opc);
-		if (index >= 0) {
-			inst = *(opc);
-		} else {
-			index =
-			    kvm_mips_guest_tlb_lookup(vcpu,
-						      ((unsigned long) opc & VPN2_MASK)
-						      |
-						      (kvm_read_c0_guest_entryhi
-						       (cop0) & ASID_MASK));
-			if (index < 0) {
-				kvm_err
-				    ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
-				     __func__, opc, vcpu, read_c0_entryhi());
-				kvm_mips_dump_host_tlbs();
-				local_irq_restore(flags);
-				return KVM_INVALID_INST;
-			}
-			kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
-							     &vcpu->arch.
-							     guest_tlb[index],
-							     NULL, NULL);
-			inst = *(opc);
-		}
-		local_irq_restore(flags);
-	} else if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
-		paddr =
-		    kvm_mips_translate_guest_kseg0_to_hpa(vcpu,
-							 (unsigned long) opc);
-		inst = *(uint32_t *) CKSEG0ADDR(paddr);
-	} else {
-		kvm_err("%s: illegal address: %p\n", __func__, opc);
-		return KVM_INVALID_INST;
-	}
-
-	return inst;
-}
-
-EXPORT_SYMBOL(kvm_local_flush_tlb_all);
-EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
-EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
-EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
-EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
-EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
-EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
-EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
-EXPORT_SYMBOL(kvm_get_inst);
-EXPORT_SYMBOL(kvm_arch_vcpu_load);
-EXPORT_SYMBOL(kvm_arch_vcpu_put);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/kvm_trap_emul.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_trap_emul.c
--- linux-libre-3.16-gnu/arch/mips/kvm/kvm_trap_emul.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/kvm_trap_emul.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,494 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Deliver/Emulate exceptions to the guest kernel
-*
-* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#include <linux/kvm_host.h>
-
-#include "kvm_mips_opcode.h"
-#include "kvm_mips_int.h"
-
-static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
-{
-	gpa_t gpa;
-	uint32_t kseg = KSEGX(gva);
-
-	if ((kseg == CKSEG0) || (kseg == CKSEG1))
-		gpa = CPHYSADDR(gva);
-	else {
-		printk("%s: cannot find GPA for GVA: %#lx\n", __func__, gva);
-		kvm_mips_dump_host_tlbs();
-		gpa = KVM_INVALID_ADDR;
-	}
-
-	kvm_debug("%s: gva %#lx, gpa: %#llx\n", __func__, gva, gpa);
-
-	return gpa;
-}
-
-
-static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) {
-		er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
-	} else
-		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
-
-	switch (er) {
-	case EMULATE_DONE:
-		ret = RESUME_GUEST;
-		break;
-
-	case EMULATE_FAIL:
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-		break;
-
-	case EMULATE_WAIT:
-		run->exit_reason = KVM_EXIT_INTR;
-		ret = RESUME_HOST;
-		break;
-
-	default:
-		BUG();
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
-	    || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-		kvm_debug
-		    ("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu);
-
-		if (er == EMULATE_DONE)
-			ret = RESUME_GUEST;
-		else {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
-		/* XXXKYMA: The guest kernel does not expect to get this fault when we are not
-		 * using HIGHMEM. Need to address this in a HIGHMEM kernel
-		 */
-		printk
-		    ("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		kvm_arch_vcpu_dump_regs(vcpu);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	} else {
-		printk
-		    ("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		kvm_arch_vcpu_dump_regs(vcpu);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
-	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
-		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
-		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-		kvm_debug
-		    ("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
-		if (er == EMULATE_DONE)
-			ret = RESUME_GUEST;
-		else {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
-		/* All KSEG0 faults are handled by KVM, as the guest kernel does not
-		 * expect to ever get them
-		 */
-		if (kvm_mips_handle_kseg0_tlb_fault
-		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else {
-		kvm_err
-		    ("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		kvm_arch_vcpu_dump_regs(vcpu);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
-	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
-		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
-		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-		kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n",
-			  vcpu->arch.pc, badvaddr);
-
-		/* User Address (UA) fault, this could happen if
-		 * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
-		 *     case we pass on the fault to the guest kernel and let it handle it.
-		 * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
-		 *     case we inject the TLB from the Guest TLB into the shadow host TLB
-		 */
-
-		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
-		if (er == EMULATE_DONE)
-			ret = RESUME_GUEST;
-		else {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
-		if (kvm_mips_handle_kseg0_tlb_fault
-		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		}
-	} else {
-		printk
-		    ("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		kvm_mips_dump_host_tlbs();
-		kvm_arch_vcpu_dump_regs(vcpu);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (KVM_GUEST_KERNEL_MODE(vcpu)
-	    && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) {
-		kvm_debug("Emulate Store to MMIO space\n");
-		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
-		if (er == EMULATE_FAIL) {
-			printk("Emulate Store to MMIO space failed\n");
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		} else {
-			run->exit_reason = KVM_EXIT_MMIO;
-			ret = RESUME_HOST;
-		}
-	} else {
-		printk
-		    ("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) {
-		kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr);
-		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
-		if (er == EMULATE_FAIL) {
-			printk("Emulate Load from MMIO space failed\n");
-			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-			ret = RESUME_HOST;
-		} else {
-			run->exit_reason = KVM_EXIT_MMIO;
-			ret = RESUME_HOST;
-		}
-	} else {
-		printk
-		    ("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n",
-		     cause, opc, badvaddr);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-		er = EMULATE_FAIL;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	er = kvm_mips_emulate_syscall(cause, opc, run, vcpu);
-	if (er == EMULATE_DONE)
-		ret = RESUME_GUEST;
-	else {
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	er = kvm_mips_handle_ri(cause, opc, run, vcpu);
-	if (er == EMULATE_DONE)
-		ret = RESUME_GUEST;
-	else {
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
-{
-	struct kvm_run *run = vcpu->run;
-	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
-	unsigned long cause = vcpu->arch.host_cp0_cause;
-	enum emulation_result er = EMULATE_DONE;
-	int ret = RESUME_GUEST;
-
-	er = kvm_mips_emulate_bp_exc(cause, opc, run, vcpu);
-	if (er == EMULATE_DONE)
-		ret = RESUME_GUEST;
-	else {
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		ret = RESUME_HOST;
-	}
-	return ret;
-}
-
-static int kvm_trap_emul_vm_init(struct kvm *kvm)
-{
-	return 0;
-}
-
-static int kvm_trap_emul_vcpu_init(struct kvm_vcpu *vcpu)
-{
-	return 0;
-}
-
-static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	uint32_t config1;
-	int vcpu_id = vcpu->vcpu_id;
-
-	/* Arch specific stuff, set up config registers properly so that the
-	 * guest will come up as expected, for now we simulate a
-	 * MIPS 24kc
-	 */
-	kvm_write_c0_guest_prid(cop0, 0x00019300);
-	kvm_write_c0_guest_config(cop0,
-				  MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
-				  (MMU_TYPE_R4000 << CP0C0_MT));
-
-	/* Read the cache characteristics from the host Config1 Register */
-	config1 = (read_c0_config1() & ~0x7f);
-
-	/* Set up MMU size */
-	config1 &= ~(0x3f << 25);
-	config1 |= ((KVM_MIPS_GUEST_TLB_SIZE - 1) << 25);
-
-	/* We unset some bits that we aren't emulating */
-	config1 &=
-	    ~((1 << CP0C1_C2) | (1 << CP0C1_MD) | (1 << CP0C1_PC) |
-	      (1 << CP0C1_WR) | (1 << CP0C1_CA));
-	kvm_write_c0_guest_config1(cop0, config1);
-
-	kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2);
-	/* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */
-	kvm_write_c0_guest_config3(cop0,
-				   MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 <<
-								       CP0C3_ULRI));
-
-	/* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
-	kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
-
-	/* Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5) */
-	kvm_write_c0_guest_intctl(cop0, 0xFC000000);
-
-	/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
-	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
-
-	return 0;
-}
-
-static int kvm_trap_emul_get_one_reg(struct kvm_vcpu *vcpu,
-				     const struct kvm_one_reg *reg,
-				     s64 *v)
-{
-	switch (reg->id) {
-	case KVM_REG_MIPS_CP0_COUNT:
-		*v = kvm_mips_read_count(vcpu);
-		break;
-	case KVM_REG_MIPS_COUNT_CTL:
-		*v = vcpu->arch.count_ctl;
-		break;
-	case KVM_REG_MIPS_COUNT_RESUME:
-		*v = ktime_to_ns(vcpu->arch.count_resume);
-		break;
-	case KVM_REG_MIPS_COUNT_HZ:
-		*v = vcpu->arch.count_hz;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
-				     const struct kvm_one_reg *reg,
-				     s64 v)
-{
-	struct mips_coproc *cop0 = vcpu->arch.cop0;
-	int ret = 0;
-
-	switch (reg->id) {
-	case KVM_REG_MIPS_CP0_COUNT:
-		kvm_mips_write_count(vcpu, v);
-		break;
-	case KVM_REG_MIPS_CP0_COMPARE:
-		kvm_mips_write_compare(vcpu, v);
-		break;
-	case KVM_REG_MIPS_CP0_CAUSE:
-		/*
-		 * If the timer is stopped or started (DC bit) it must look
-		 * atomic with changes to the interrupt pending bits (TI, IRQ5).
-		 * A timer interrupt should not happen in between.
-		 */
-		if ((kvm_read_c0_guest_cause(cop0) ^ v) & CAUSEF_DC) {
-			if (v & CAUSEF_DC) {
-				/* disable timer first */
-				kvm_mips_count_disable_cause(vcpu);
-				kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
-			} else {
-				/* enable timer last */
-				kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
-				kvm_mips_count_enable_cause(vcpu);
-			}
-		} else {
-			kvm_write_c0_guest_cause(cop0, v);
-		}
-		break;
-	case KVM_REG_MIPS_COUNT_CTL:
-		ret = kvm_mips_set_count_ctl(vcpu, v);
-		break;
-	case KVM_REG_MIPS_COUNT_RESUME:
-		ret = kvm_mips_set_count_resume(vcpu, v);
-		break;
-	case KVM_REG_MIPS_COUNT_HZ:
-		ret = kvm_mips_set_count_hz(vcpu, v);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return ret;
-}
-
-static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
-	/* exit handlers */
-	.handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
-	.handle_tlb_mod = kvm_trap_emul_handle_tlb_mod,
-	.handle_tlb_st_miss = kvm_trap_emul_handle_tlb_st_miss,
-	.handle_tlb_ld_miss = kvm_trap_emul_handle_tlb_ld_miss,
-	.handle_addr_err_st = kvm_trap_emul_handle_addr_err_st,
-	.handle_addr_err_ld = kvm_trap_emul_handle_addr_err_ld,
-	.handle_syscall = kvm_trap_emul_handle_syscall,
-	.handle_res_inst = kvm_trap_emul_handle_res_inst,
-	.handle_break = kvm_trap_emul_handle_break,
-
-	.vm_init = kvm_trap_emul_vm_init,
-	.vcpu_init = kvm_trap_emul_vcpu_init,
-	.vcpu_setup = kvm_trap_emul_vcpu_setup,
-	.gva_to_gpa = kvm_trap_emul_gva_to_gpa_cb,
-	.queue_timer_int = kvm_mips_queue_timer_int_cb,
-	.dequeue_timer_int = kvm_mips_dequeue_timer_int_cb,
-	.queue_io_int = kvm_mips_queue_io_int_cb,
-	.dequeue_io_int = kvm_mips_dequeue_io_int_cb,
-	.irq_deliver = kvm_mips_irq_deliver_cb,
-	.irq_clear = kvm_mips_irq_clear_cb,
-	.get_one_reg = kvm_trap_emul_get_one_reg,
-	.set_one_reg = kvm_trap_emul_set_one_reg,
-};
-
-int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
-{
-	*install_callbacks = &kvm_trap_emul_callbacks;
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/locore.S linux-libre-3.17-rc7-gnu/arch/mips/kvm/locore.S
--- linux-libre-3.16-gnu/arch/mips/kvm/locore.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/locore.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,620 @@
+/*
+ * 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.
+ *
+ * Main entry point for the guest, exception handling.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/asm-offsets.h>
+
+#define _C_LABEL(x)     x
+#define MIPSX(name)     mips32_ ## name
+#define CALLFRAME_SIZ   32
+
+/*
+ * VECTOR
+ *  exception vector entrypoint
+ */
+#define VECTOR(x, regmask)      \
+    .ent    _C_LABEL(x),0;      \
+    EXPORT(x);
+
+#define VECTOR_END(x)      \
+    EXPORT(x);
+
+/* Overload, Danger Will Robinson!! */
+#define PT_HOST_ASID        PT_BVADDR
+#define PT_HOST_USERLOCAL   PT_EPC
+
+#define CP0_DDATA_LO        $28,3
+#define CP0_EBASE           $15,1
+
+#define CP0_INTCTL          $12,1
+#define CP0_SRSCTL          $12,2
+#define CP0_SRSMAP          $12,3
+#define CP0_HWRENA          $7,0
+
+/* Resume Flags */
+#define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
+
+#define RESUME_GUEST            0
+#define RESUME_HOST             RESUME_FLAG_HOST
+
+/*
+ * __kvm_mips_vcpu_run: entry point to the guest
+ * a0: run
+ * a1: vcpu
+ */
+	.set	noreorder
+	.set	noat
+
+FEXPORT(__kvm_mips_vcpu_run)
+	/* k0/k1 not being used in host kernel context */
+	INT_ADDIU k1, sp, -PT_SIZE
+	LONG_S	$0, PT_R0(k1)
+	LONG_S	$1, PT_R1(k1)
+	LONG_S	$2, PT_R2(k1)
+	LONG_S	$3, PT_R3(k1)
+
+	LONG_S	$4, PT_R4(k1)
+	LONG_S	$5, PT_R5(k1)
+	LONG_S	$6, PT_R6(k1)
+	LONG_S	$7, PT_R7(k1)
+
+	LONG_S	$8,  PT_R8(k1)
+	LONG_S	$9,  PT_R9(k1)
+	LONG_S	$10, PT_R10(k1)
+	LONG_S	$11, PT_R11(k1)
+	LONG_S	$12, PT_R12(k1)
+	LONG_S	$13, PT_R13(k1)
+	LONG_S	$14, PT_R14(k1)
+	LONG_S	$15, PT_R15(k1)
+	LONG_S	$16, PT_R16(k1)
+	LONG_S	$17, PT_R17(k1)
+
+	LONG_S	$18, PT_R18(k1)
+	LONG_S	$19, PT_R19(k1)
+	LONG_S	$20, PT_R20(k1)
+	LONG_S	$21, PT_R21(k1)
+	LONG_S	$22, PT_R22(k1)
+	LONG_S	$23, PT_R23(k1)
+	LONG_S	$24, PT_R24(k1)
+	LONG_S	$25, PT_R25(k1)
+
+	/*
+	 * XXXKYMA k0/k1 not saved, not being used if we got here through
+	 * an ioctl()
+	 */
+
+	LONG_S	$28, PT_R28(k1)
+	LONG_S	$29, PT_R29(k1)
+	LONG_S	$30, PT_R30(k1)
+	LONG_S	$31, PT_R31(k1)
+
+	/* Save hi/lo */
+	mflo	v0
+	LONG_S	v0, PT_LO(k1)
+	mfhi	v1
+	LONG_S	v1, PT_HI(k1)
+
+	/* Save host status */
+	mfc0	v0, CP0_STATUS
+	LONG_S	v0, PT_STATUS(k1)
+
+	/* Save host ASID, shove it into the BVADDR location */
+	mfc0	v1, CP0_ENTRYHI
+	andi	v1, 0xff
+	LONG_S	v1, PT_HOST_ASID(k1)
+
+	/* Save DDATA_LO, will be used to store pointer to vcpu */
+	mfc0	v1, CP0_DDATA_LO
+	LONG_S	v1, PT_HOST_USERLOCAL(k1)
+
+	/* DDATA_LO has pointer to vcpu */
+	mtc0	a1, CP0_DDATA_LO
+
+	/* Offset into vcpu->arch */
+	INT_ADDIU k1, a1, VCPU_HOST_ARCH
+
+	/*
+	 * Save the host stack to VCPU, used for exception processing
+	 * when we exit from the Guest
+	 */
+	LONG_S	sp, VCPU_HOST_STACK(k1)
+
+	/* Save the kernel gp as well */
+	LONG_S	gp, VCPU_HOST_GP(k1)
+
+	/*
+	 * Setup status register for running the guest in UM, interrupts
+	 * are disabled
+	 */
+	li	k0, (ST0_EXL | KSU_USER | ST0_BEV)
+	mtc0	k0, CP0_STATUS
+	ehb
+
+	/* load up the new EBASE */
+	LONG_L	k0, VCPU_GUEST_EBASE(k1)
+	mtc0	k0, CP0_EBASE
+
+	/*
+	 * Now that the new EBASE has been loaded, unset BEV, set
+	 * interrupt mask as it was but make sure that timer interrupts
+	 * are enabled
+	 */
+	li	k0, (ST0_EXL | KSU_USER | ST0_IE)
+	andi	v0, v0, ST0_IM
+	or	k0, k0, v0
+	mtc0	k0, CP0_STATUS
+	ehb
+
+	/* Set Guest EPC */
+	LONG_L	t0, VCPU_PC(k1)
+	mtc0	t0, CP0_EPC
+
+FEXPORT(__kvm_mips_load_asid)
+	/* Set the ASID for the Guest Kernel */
+	INT_SLL	t0, t0, 1	/* with kseg0 @ 0x40000000, kernel */
+			        /* addresses shift to 0x80000000 */
+	bltz	t0, 1f		/* If kernel */
+	 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
+	INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
+1:
+	/* t1: contains the base of the ASID array, need to get the cpu id */
+	LONG_L	t2, TI_CPU($28)             /* smp_processor_id */
+	INT_SLL	t2, t2, 2                   /* x4 */
+	REG_ADDU t3, t1, t2
+	LONG_L	k0, (t3)
+	andi	k0, k0, 0xff
+	mtc0	k0, CP0_ENTRYHI
+	ehb
+
+	/* Disable RDHWR access */
+	mtc0	zero, CP0_HWRENA
+
+	/* Now load up the Guest Context from VCPU */
+	LONG_L	$1, VCPU_R1(k1)
+	LONG_L	$2, VCPU_R2(k1)
+	LONG_L	$3, VCPU_R3(k1)
+
+	LONG_L	$4, VCPU_R4(k1)
+	LONG_L	$5, VCPU_R5(k1)
+	LONG_L	$6, VCPU_R6(k1)
+	LONG_L	$7, VCPU_R7(k1)
+
+	LONG_L	$8, VCPU_R8(k1)
+	LONG_L	$9, VCPU_R9(k1)
+	LONG_L	$10, VCPU_R10(k1)
+	LONG_L	$11, VCPU_R11(k1)
+	LONG_L	$12, VCPU_R12(k1)
+	LONG_L	$13, VCPU_R13(k1)
+	LONG_L	$14, VCPU_R14(k1)
+	LONG_L	$15, VCPU_R15(k1)
+	LONG_L	$16, VCPU_R16(k1)
+	LONG_L	$17, VCPU_R17(k1)
+	LONG_L	$18, VCPU_R18(k1)
+	LONG_L	$19, VCPU_R19(k1)
+	LONG_L	$20, VCPU_R20(k1)
+	LONG_L	$21, VCPU_R21(k1)
+	LONG_L	$22, VCPU_R22(k1)
+	LONG_L	$23, VCPU_R23(k1)
+	LONG_L	$24, VCPU_R24(k1)
+	LONG_L	$25, VCPU_R25(k1)
+
+	/* k0/k1 loaded up later */
+
+	LONG_L	$28, VCPU_R28(k1)
+	LONG_L	$29, VCPU_R29(k1)
+	LONG_L	$30, VCPU_R30(k1)
+	LONG_L	$31, VCPU_R31(k1)
+
+	/* Restore hi/lo */
+	LONG_L	k0, VCPU_LO(k1)
+	mtlo	k0
+
+	LONG_L	k0, VCPU_HI(k1)
+	mthi	k0
+
+FEXPORT(__kvm_mips_load_k0k1)
+	/* Restore the guest's k0/k1 registers */
+	LONG_L	k0, VCPU_R26(k1)
+	LONG_L	k1, VCPU_R27(k1)
+
+	/* Jump to guest */
+	eret
+
+VECTOR(MIPSX(exception), unknown)
+/* Find out what mode we came from and jump to the proper handler. */
+	mtc0	k0, CP0_ERROREPC	#01: Save guest k0
+	ehb				#02:
+
+	mfc0	k0, CP0_EBASE		#02: Get EBASE
+	INT_SRL	k0, k0, 10		#03: Get rid of CPUNum
+	INT_SLL	k0, k0, 10		#04
+	LONG_S	k1, 0x3000(k0)		#05: Save k1 @ offset 0x3000
+	INT_ADDIU k0, k0, 0x2000	#06: Exception handler is
+					#    installed @ offset 0x2000
+	j	k0			#07: jump to the function
+	 nop				#08: branch delay slot
+VECTOR_END(MIPSX(exceptionEnd))
+.end MIPSX(exception)
+
+/*
+ * Generic Guest exception handler. We end up here when the guest
+ * does something that causes a trap to kernel mode.
+ */
+NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
+	/* Get the VCPU pointer from DDTATA_LO */
+	mfc0	k1, CP0_DDATA_LO
+	INT_ADDIU k1, k1, VCPU_HOST_ARCH
+
+	/* Start saving Guest context to VCPU */
+	LONG_S	$0, VCPU_R0(k1)
+	LONG_S	$1, VCPU_R1(k1)
+	LONG_S	$2, VCPU_R2(k1)
+	LONG_S	$3, VCPU_R3(k1)
+	LONG_S	$4, VCPU_R4(k1)
+	LONG_S	$5, VCPU_R5(k1)
+	LONG_S	$6, VCPU_R6(k1)
+	LONG_S	$7, VCPU_R7(k1)
+	LONG_S	$8, VCPU_R8(k1)
+	LONG_S	$9, VCPU_R9(k1)
+	LONG_S	$10, VCPU_R10(k1)
+	LONG_S	$11, VCPU_R11(k1)
+	LONG_S	$12, VCPU_R12(k1)
+	LONG_S	$13, VCPU_R13(k1)
+	LONG_S	$14, VCPU_R14(k1)
+	LONG_S	$15, VCPU_R15(k1)
+	LONG_S	$16, VCPU_R16(k1)
+	LONG_S	$17, VCPU_R17(k1)
+	LONG_S	$18, VCPU_R18(k1)
+	LONG_S	$19, VCPU_R19(k1)
+	LONG_S	$20, VCPU_R20(k1)
+	LONG_S	$21, VCPU_R21(k1)
+	LONG_S	$22, VCPU_R22(k1)
+	LONG_S	$23, VCPU_R23(k1)
+	LONG_S	$24, VCPU_R24(k1)
+	LONG_S	$25, VCPU_R25(k1)
+
+	/* Guest k0/k1 saved later */
+
+	LONG_S	$28, VCPU_R28(k1)
+	LONG_S	$29, VCPU_R29(k1)
+	LONG_S	$30, VCPU_R30(k1)
+	LONG_S	$31, VCPU_R31(k1)
+
+	/* We need to save hi/lo and restore them on the way out */
+	mfhi	t0
+	LONG_S	t0, VCPU_HI(k1)
+
+	mflo	t0
+	LONG_S	t0, VCPU_LO(k1)
+
+	/* Finally save guest k0/k1 to VCPU */
+	mfc0	t0, CP0_ERROREPC
+	LONG_S	t0, VCPU_R26(k1)
+
+	/* Get GUEST k1 and save it in VCPU */
+	PTR_LI	t1, ~0x2ff
+	mfc0	t0, CP0_EBASE
+	and	t0, t0, t1
+	LONG_L	t0, 0x3000(t0)
+	LONG_S	t0, VCPU_R27(k1)
+
+	/* Now that context has been saved, we can use other registers */
+
+	/* Restore vcpu */
+	mfc0	a1, CP0_DDATA_LO
+	move	s1, a1
+
+	/* Restore run (vcpu->run) */
+	LONG_L	a0, VCPU_RUN(a1)
+	/* Save pointer to run in s0, will be saved by the compiler */
+	move	s0, a0
+
+	/*
+	 * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
+	 * process the exception
+	 */
+	mfc0	k0,CP0_EPC
+	LONG_S	k0, VCPU_PC(k1)
+
+	mfc0	k0, CP0_BADVADDR
+	LONG_S	k0, VCPU_HOST_CP0_BADVADDR(k1)
+
+	mfc0	k0, CP0_CAUSE
+	LONG_S	k0, VCPU_HOST_CP0_CAUSE(k1)
+
+	mfc0	k0, CP0_ENTRYHI
+	LONG_S	k0, VCPU_HOST_ENTRYHI(k1)
+
+	/* Now restore the host state just enough to run the handlers */
+
+	/* Swtich EBASE to the one used by Linux */
+	/* load up the host EBASE */
+	mfc0	v0, CP0_STATUS
+
+	.set	at
+	or	k0, v0, ST0_BEV
+	.set	noat
+
+	mtc0	k0, CP0_STATUS
+	ehb
+
+	LONG_L	k0, VCPU_HOST_EBASE(k1)
+	mtc0	k0,CP0_EBASE
+
+	/* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
+	.set	at
+	and	v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
+	or	v0, v0, ST0_CU0
+	.set	noat
+	mtc0	v0, CP0_STATUS
+	ehb
+
+	/* Load up host GP */
+	LONG_L	gp, VCPU_HOST_GP(k1)
+
+	/* Need a stack before we can jump to "C" */
+	LONG_L	sp, VCPU_HOST_STACK(k1)
+
+	/* Saved host state */
+	INT_ADDIU sp, sp, -PT_SIZE
+
+	/*
+	 * XXXKYMA do we need to load the host ASID, maybe not because the
+	 * kernel entries are marked GLOBAL, need to verify
+	 */
+
+	/* Restore host DDATA_LO */
+	LONG_L	k0, PT_HOST_USERLOCAL(sp)
+	mtc0	k0, CP0_DDATA_LO
+
+	/* Restore RDHWR access */
+	PTR_LI	k0, 0x2000000F
+	mtc0	k0, CP0_HWRENA
+
+	/* Jump to handler */
+FEXPORT(__kvm_mips_jump_to_handler)
+	/*
+	 * XXXKYMA: not sure if this is safe, how large is the stack??
+	 * Now jump to the kvm_mips_handle_exit() to see if we can deal
+	 * with this in the kernel
+	 */
+	PTR_LA	t9, kvm_mips_handle_exit
+	jalr.hb	t9
+	 INT_ADDIU sp, sp, -CALLFRAME_SIZ           /* BD Slot */
+
+	/* Return from handler Make sure interrupts are disabled */
+	di
+	ehb
+
+	/*
+	 * XXXKYMA: k0/k1 could have been blown away if we processed
+	 * an exception while we were handling the exception from the
+	 * guest, reload k1
+	 */
+
+	move	k1, s1
+	INT_ADDIU k1, k1, VCPU_HOST_ARCH
+
+	/*
+	 * Check return value, should tell us if we are returning to the
+	 * host (handle I/O etc)or resuming the guest
+	 */
+	andi	t0, v0, RESUME_HOST
+	bnez	t0, __kvm_mips_return_to_host
+	 nop
+
+__kvm_mips_return_to_guest:
+	/* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
+	mtc0	s1, CP0_DDATA_LO
+
+	/* Load up the Guest EBASE to minimize the window where BEV is set */
+	LONG_L	t0, VCPU_GUEST_EBASE(k1)
+
+	/* Switch EBASE back to the one used by KVM */
+	mfc0	v1, CP0_STATUS
+	.set	at
+	or	k0, v1, ST0_BEV
+	.set	noat
+	mtc0	k0, CP0_STATUS
+	ehb
+	mtc0	t0, CP0_EBASE
+
+	/* Setup status register for running guest in UM */
+	.set	at
+	or	v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
+	and	v1, v1, ~ST0_CU0
+	.set	noat
+	mtc0	v1, CP0_STATUS
+	ehb
+
+	/* Set Guest EPC */
+	LONG_L	t0, VCPU_PC(k1)
+	mtc0	t0, CP0_EPC
+
+	/* Set the ASID for the Guest Kernel */
+	INT_SLL	t0, t0, 1	/* with kseg0 @ 0x40000000, kernel */
+				/* addresses shift to 0x80000000 */
+	bltz	t0, 1f		/* If kernel */
+	 INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
+	INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
+1:
+	/* t1: contains the base of the ASID array, need to get the cpu id  */
+	LONG_L	t2, TI_CPU($28)		/* smp_processor_id */
+	INT_SLL	t2, t2, 2		/* x4 */
+	REG_ADDU t3, t1, t2
+	LONG_L	k0, (t3)
+	andi	k0, k0, 0xff
+	mtc0	k0,CP0_ENTRYHI
+	ehb
+
+	/* Disable RDHWR access */
+	mtc0    zero,  CP0_HWRENA
+
+	/* load the guest context from VCPU and return */
+	LONG_L	$0, VCPU_R0(k1)
+	LONG_L	$1, VCPU_R1(k1)
+	LONG_L	$2, VCPU_R2(k1)
+	LONG_L	$3, VCPU_R3(k1)
+	LONG_L	$4, VCPU_R4(k1)
+	LONG_L	$5, VCPU_R5(k1)
+	LONG_L	$6, VCPU_R6(k1)
+	LONG_L	$7, VCPU_R7(k1)
+	LONG_L	$8, VCPU_R8(k1)
+	LONG_L	$9, VCPU_R9(k1)
+	LONG_L	$10, VCPU_R10(k1)
+	LONG_L	$11, VCPU_R11(k1)
+	LONG_L	$12, VCPU_R12(k1)
+	LONG_L	$13, VCPU_R13(k1)
+	LONG_L	$14, VCPU_R14(k1)
+	LONG_L	$15, VCPU_R15(k1)
+	LONG_L	$16, VCPU_R16(k1)
+	LONG_L	$17, VCPU_R17(k1)
+	LONG_L	$18, VCPU_R18(k1)
+	LONG_L	$19, VCPU_R19(k1)
+	LONG_L	$20, VCPU_R20(k1)
+	LONG_L	$21, VCPU_R21(k1)
+	LONG_L	$22, VCPU_R22(k1)
+	LONG_L	$23, VCPU_R23(k1)
+	LONG_L	$24, VCPU_R24(k1)
+	LONG_L	$25, VCPU_R25(k1)
+
+	/* $/k1 loaded later */
+	LONG_L	$28, VCPU_R28(k1)
+	LONG_L	$29, VCPU_R29(k1)
+	LONG_L	$30, VCPU_R30(k1)
+	LONG_L	$31, VCPU_R31(k1)
+
+FEXPORT(__kvm_mips_skip_guest_restore)
+	LONG_L	k0, VCPU_HI(k1)
+	mthi	k0
+
+	LONG_L	k0, VCPU_LO(k1)
+	mtlo	k0
+
+	LONG_L	k0, VCPU_R26(k1)
+	LONG_L	k1, VCPU_R27(k1)
+
+	eret
+
+__kvm_mips_return_to_host:
+	/* EBASE is already pointing to Linux */
+	LONG_L	k1, VCPU_HOST_STACK(k1)
+	INT_ADDIU k1,k1, -PT_SIZE
+
+	/* Restore host DDATA_LO */
+	LONG_L	k0, PT_HOST_USERLOCAL(k1)
+	mtc0	k0, CP0_DDATA_LO
+
+	/* Restore host ASID */
+	LONG_L	k0, PT_HOST_ASID(sp)
+	andi	k0, 0xff
+	mtc0	k0,CP0_ENTRYHI
+	ehb
+
+	/* Load context saved on the host stack */
+	LONG_L	$0, PT_R0(k1)
+	LONG_L	$1, PT_R1(k1)
+
+	/*
+	 * r2/v0 is the return code, shift it down by 2 (arithmetic)
+	 * to recover the err code
+	 */
+	INT_SRA	k0, v0, 2
+	move	$2, k0
+
+	LONG_L	$3, PT_R3(k1)
+	LONG_L	$4, PT_R4(k1)
+	LONG_L	$5, PT_R5(k1)
+	LONG_L	$6, PT_R6(k1)
+	LONG_L	$7, PT_R7(k1)
+	LONG_L	$8, PT_R8(k1)
+	LONG_L	$9, PT_R9(k1)
+	LONG_L	$10, PT_R10(k1)
+	LONG_L	$11, PT_R11(k1)
+	LONG_L	$12, PT_R12(k1)
+	LONG_L	$13, PT_R13(k1)
+	LONG_L	$14, PT_R14(k1)
+	LONG_L	$15, PT_R15(k1)
+	LONG_L	$16, PT_R16(k1)
+	LONG_L	$17, PT_R17(k1)
+	LONG_L	$18, PT_R18(k1)
+	LONG_L	$19, PT_R19(k1)
+	LONG_L	$20, PT_R20(k1)
+	LONG_L	$21, PT_R21(k1)
+	LONG_L	$22, PT_R22(k1)
+	LONG_L	$23, PT_R23(k1)
+	LONG_L	$24, PT_R24(k1)
+	LONG_L	$25, PT_R25(k1)
+
+	/* Host k0/k1 were not saved */
+
+	LONG_L	$28, PT_R28(k1)
+	LONG_L	$29, PT_R29(k1)
+	LONG_L	$30, PT_R30(k1)
+
+	LONG_L	k0, PT_HI(k1)
+	mthi	k0
+
+	LONG_L	k0, PT_LO(k1)
+	mtlo	k0
+
+	/* Restore RDHWR access */
+	PTR_LI	k0, 0x2000000F
+	mtc0	k0,  CP0_HWRENA
+
+	/* Restore RA, which is the address we will return to */
+	LONG_L  ra, PT_R31(k1)
+	j       ra
+	 nop
+
+VECTOR_END(MIPSX(GuestExceptionEnd))
+.end MIPSX(GuestException)
+
+MIPSX(exceptions):
+	####
+	##### The exception handlers.
+	#####
+	.word _C_LABEL(MIPSX(GuestException))	#  0
+	.word _C_LABEL(MIPSX(GuestException))	#  1
+	.word _C_LABEL(MIPSX(GuestException))	#  2
+	.word _C_LABEL(MIPSX(GuestException))	#  3
+	.word _C_LABEL(MIPSX(GuestException))	#  4
+	.word _C_LABEL(MIPSX(GuestException))	#  5
+	.word _C_LABEL(MIPSX(GuestException))	#  6
+	.word _C_LABEL(MIPSX(GuestException))	#  7
+	.word _C_LABEL(MIPSX(GuestException))	#  8
+	.word _C_LABEL(MIPSX(GuestException))	#  9
+	.word _C_LABEL(MIPSX(GuestException))	# 10
+	.word _C_LABEL(MIPSX(GuestException))	# 11
+	.word _C_LABEL(MIPSX(GuestException))	# 12
+	.word _C_LABEL(MIPSX(GuestException))	# 13
+	.word _C_LABEL(MIPSX(GuestException))	# 14
+	.word _C_LABEL(MIPSX(GuestException))	# 15
+	.word _C_LABEL(MIPSX(GuestException))	# 16
+	.word _C_LABEL(MIPSX(GuestException))	# 17
+	.word _C_LABEL(MIPSX(GuestException))	# 18
+	.word _C_LABEL(MIPSX(GuestException))	# 19
+	.word _C_LABEL(MIPSX(GuestException))	# 20
+	.word _C_LABEL(MIPSX(GuestException))	# 21
+	.word _C_LABEL(MIPSX(GuestException))	# 22
+	.word _C_LABEL(MIPSX(GuestException))	# 23
+	.word _C_LABEL(MIPSX(GuestException))	# 24
+	.word _C_LABEL(MIPSX(GuestException))	# 25
+	.word _C_LABEL(MIPSX(GuestException))	# 26
+	.word _C_LABEL(MIPSX(GuestException))	# 27
+	.word _C_LABEL(MIPSX(GuestException))	# 28
+	.word _C_LABEL(MIPSX(GuestException))	# 29
+	.word _C_LABEL(MIPSX(GuestException))	# 30
+	.word _C_LABEL(MIPSX(GuestException))	# 31
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/Makefile linux-libre-3.17-rc7-gnu/arch/mips/kvm/Makefile
--- linux-libre-3.16-gnu/arch/mips/kvm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,9 +5,9 @@ common-objs = $(addprefix ../../../virt/
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm
 
-kvm-objs := $(common-objs) kvm_mips.o kvm_mips_emul.o kvm_locore.o \
-	    kvm_mips_int.o kvm_mips_stats.o kvm_mips_commpage.o \
-	    kvm_mips_dyntrans.o kvm_trap_emul.o
+kvm-objs := $(common-objs) mips.o emulate.o locore.o \
+	    interrupt.o stats.o commpage.o \
+	    dyntrans.o trap_emul.o
 
 obj-$(CONFIG_KVM)	+= kvm.o
-obj-y			+= kvm_cb.o kvm_tlb.o
+obj-y			+= callback.o tlb.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/mips.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/mips.c
--- linux-libre-3.16-gnu/arch/mips/kvm/mips.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/mips.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1219 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+#include <linux/kvm_host.h>
+
+#include "interrupt.h"
+#include "commpage.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#ifndef VECTORSPACING
+#define VECTORSPACING 0x100	/* for EI/VI mode */
+#endif
+
+#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x)
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+	{ "wait",	  VCPU_STAT(wait_exits),	 KVM_STAT_VCPU },
+	{ "cache",	  VCPU_STAT(cache_exits),	 KVM_STAT_VCPU },
+	{ "signal",	  VCPU_STAT(signal_exits),	 KVM_STAT_VCPU },
+	{ "interrupt",	  VCPU_STAT(int_exits),		 KVM_STAT_VCPU },
+	{ "cop_unsuable", VCPU_STAT(cop_unusable_exits), KVM_STAT_VCPU },
+	{ "tlbmod",	  VCPU_STAT(tlbmod_exits),	 KVM_STAT_VCPU },
+	{ "tlbmiss_ld",	  VCPU_STAT(tlbmiss_ld_exits),	 KVM_STAT_VCPU },
+	{ "tlbmiss_st",	  VCPU_STAT(tlbmiss_st_exits),	 KVM_STAT_VCPU },
+	{ "addrerr_st",	  VCPU_STAT(addrerr_st_exits),	 KVM_STAT_VCPU },
+	{ "addrerr_ld",	  VCPU_STAT(addrerr_ld_exits),	 KVM_STAT_VCPU },
+	{ "syscall",	  VCPU_STAT(syscall_exits),	 KVM_STAT_VCPU },
+	{ "resvd_inst",	  VCPU_STAT(resvd_inst_exits),	 KVM_STAT_VCPU },
+	{ "break_inst",	  VCPU_STAT(break_inst_exits),	 KVM_STAT_VCPU },
+	{ "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
+	{ "halt_wakeup",  VCPU_STAT(halt_wakeup),	 KVM_STAT_VCPU },
+	{NULL}
+};
+
+static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		vcpu->arch.guest_kernel_asid[i] = 0;
+		vcpu->arch.guest_user_asid[i] = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * XXXKYMA: We are simulatoring a processor that has the WII bit set in
+ * Config7, so we are "runnable" if interrupts are pending
+ */
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+	return !!(vcpu->arch.pending_exceptions);
+}
+
+int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
+{
+	return 1;
+}
+
+int kvm_arch_hardware_enable(void *garbage)
+{
+	return 0;
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+}
+
+int kvm_arch_hardware_setup(void)
+{
+	return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+	*(int *)rtn = 0;
+}
+
+static void kvm_mips_init_tlbs(struct kvm *kvm)
+{
+	unsigned long wired;
+
+	/*
+	 * Add a wired entry to the TLB, it is used to map the commpage to
+	 * the Guest kernel
+	 */
+	wired = read_c0_wired();
+	write_c0_wired(wired + 1);
+	mtc0_tlbw_hazard();
+	kvm->arch.commpage_tlb = wired;
+
+	kvm_debug("[%d] commpage TLB: %d\n", smp_processor_id(),
+		  kvm->arch.commpage_tlb);
+}
+
+static void kvm_mips_init_vm_percpu(void *arg)
+{
+	struct kvm *kvm = (struct kvm *)arg;
+
+	kvm_mips_init_tlbs(kvm);
+	kvm_mips_callbacks->vm_init(kvm);
+
+}
+
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+{
+	if (atomic_inc_return(&kvm_mips_instance) == 1) {
+		kvm_debug("%s: 1st KVM instance, setup host TLB parameters\n",
+			  __func__);
+		on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1);
+	}
+
+	return 0;
+}
+
+void kvm_mips_free_vcpus(struct kvm *kvm)
+{
+	unsigned int i;
+	struct kvm_vcpu *vcpu;
+
+	/* Put the pages we reserved for the guest pmap */
+	for (i = 0; i < kvm->arch.guest_pmap_npages; i++) {
+		if (kvm->arch.guest_pmap[i] != KVM_INVALID_PAGE)
+			kvm_mips_release_pfn_clean(kvm->arch.guest_pmap[i]);
+	}
+	kfree(kvm->arch.guest_pmap);
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		kvm_arch_vcpu_free(vcpu);
+	}
+
+	mutex_lock(&kvm->lock);
+
+	for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
+		kvm->vcpus[i] = NULL;
+
+	atomic_set(&kvm->online_vcpus, 0);
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
+static void kvm_mips_uninit_tlbs(void *arg)
+{
+	/* Restore wired count */
+	write_c0_wired(0);
+	mtc0_tlbw_hazard();
+	/* Clear out all the TLBs */
+	kvm_local_flush_tlb_all();
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+	kvm_mips_free_vcpus(kvm);
+
+	/* If this is the last instance, restore wired count */
+	if (atomic_dec_return(&kvm_mips_instance) == 0) {
+		kvm_debug("%s: last KVM instance, restoring TLB parameters\n",
+			  __func__);
+		on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1);
+	}
+}
+
+long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl,
+			unsigned long arg)
+{
+	return -ENOIOCTLCMD;
+}
+
+void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
+			   struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
+			    unsigned long npages)
+{
+	return 0;
+}
+
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				   struct kvm_memory_slot *memslot,
+				   struct kvm_userspace_memory_region *mem,
+				   enum kvm_mr_change change)
+{
+	return 0;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				   struct kvm_userspace_memory_region *mem,
+				   const struct kvm_memory_slot *old,
+				   enum kvm_mr_change change)
+{
+	unsigned long npages = 0;
+	int i;
+
+	kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n",
+		  __func__, kvm, mem->slot, mem->guest_phys_addr,
+		  mem->memory_size, mem->userspace_addr);
+
+	/* Setup Guest PMAP table */
+	if (!kvm->arch.guest_pmap) {
+		if (mem->slot == 0)
+			npages = mem->memory_size >> PAGE_SHIFT;
+
+		if (npages) {
+			kvm->arch.guest_pmap_npages = npages;
+			kvm->arch.guest_pmap =
+			    kzalloc(npages * sizeof(unsigned long), GFP_KERNEL);
+
+			if (!kvm->arch.guest_pmap) {
+				kvm_err("Failed to allocate guest PMAP");
+				return;
+			}
+
+			kvm_debug("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
+				  npages, kvm->arch.guest_pmap);
+
+			/* Now setup the page table */
+			for (i = 0; i < npages; i++)
+				kvm->arch.guest_pmap[i] = KVM_INVALID_PAGE;
+		}
+	}
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
+{
+}
+
+void kvm_arch_flush_shadow(struct kvm *kvm)
+{
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+	int err, size, offset;
+	void *gebase;
+	int i;
+
+	struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+
+	if (!vcpu) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = kvm_vcpu_init(vcpu, kvm, id);
+
+	if (err)
+		goto out_free_cpu;
+
+	kvm_debug("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
+
+	/*
+	 * Allocate space for host mode exception handlers that handle
+	 * guest mode exits
+	 */
+	if (cpu_has_veic || cpu_has_vint)
+		size = 0x200 + VECTORSPACING * 64;
+	else
+		size = 0x4000;
+
+	/* Save Linux EBASE */
+	vcpu->arch.host_ebase = (void *)read_c0_ebase();
+
+	gebase = kzalloc(ALIGN(size, PAGE_SIZE), GFP_KERNEL);
+
+	if (!gebase) {
+		err = -ENOMEM;
+		goto out_free_cpu;
+	}
+	kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n",
+		  ALIGN(size, PAGE_SIZE), gebase);
+
+	/* Save new ebase */
+	vcpu->arch.guest_ebase = gebase;
+
+	/* Copy L1 Guest Exception handler to correct offset */
+
+	/* TLB Refill, EXL = 0 */
+	memcpy(gebase, mips32_exception,
+	       mips32_exceptionEnd - mips32_exception);
+
+	/* General Exception Entry point */
+	memcpy(gebase + 0x180, mips32_exception,
+	       mips32_exceptionEnd - mips32_exception);
+
+	/* For vectored interrupts poke the exception code @ all offsets 0-7 */
+	for (i = 0; i < 8; i++) {
+		kvm_debug("L1 Vectored handler @ %p\n",
+			  gebase + 0x200 + (i * VECTORSPACING));
+		memcpy(gebase + 0x200 + (i * VECTORSPACING), mips32_exception,
+		       mips32_exceptionEnd - mips32_exception);
+	}
+
+	/* General handler, relocate to unmapped space for sanity's sake */
+	offset = 0x2000;
+	kvm_debug("Installing KVM Exception handlers @ %p, %#x bytes\n",
+		  gebase + offset,
+		  mips32_GuestExceptionEnd - mips32_GuestException);
+
+	memcpy(gebase + offset, mips32_GuestException,
+	       mips32_GuestExceptionEnd - mips32_GuestException);
+
+	/* Invalidate the icache for these ranges */
+	local_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
+	 * mapping GVA @ 0xFFFF8000 to this page
+	 */
+	vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL);
+
+	if (!vcpu->arch.kseg0_commpage) {
+		err = -ENOMEM;
+		goto out_free_gebase;
+	}
+
+	kvm_debug("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage);
+	kvm_mips_commpage_init(vcpu);
+
+	/* Init */
+	vcpu->arch.last_sched_cpu = -1;
+
+	/* Start off the timer */
+	kvm_mips_init_count(vcpu);
+
+	return vcpu;
+
+out_free_gebase:
+	kfree(gebase);
+
+out_free_cpu:
+	kfree(vcpu);
+
+out:
+	return ERR_PTR(err);
+}
+
+void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
+{
+	hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+	kvm_vcpu_uninit(vcpu);
+
+	kvm_mips_dump_stats(vcpu);
+
+	kfree(vcpu->arch.guest_ebase);
+	kfree(vcpu->arch.kseg0_commpage);
+	kfree(vcpu);
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	kvm_arch_vcpu_free(vcpu);
+}
+
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+					struct kvm_guest_debug *dbg)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	int r = 0;
+	sigset_t sigsaved;
+
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+	if (vcpu->mmio_needed) {
+		if (!vcpu->mmio_is_write)
+			kvm_mips_complete_mmio_load(vcpu, run);
+		vcpu->mmio_needed = 0;
+	}
+
+	local_irq_disable();
+	/* Check if we have any exceptions/interrupts pending */
+	kvm_mips_deliver_interrupts(vcpu,
+				    kvm_read_c0_guest_cause(vcpu->arch.cop0));
+
+	kvm_guest_enter();
+
+	r = __kvm_mips_vcpu_run(run, vcpu);
+
+	kvm_guest_exit();
+	local_irq_enable();
+
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return r;
+}
+
+int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
+			     struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+	struct kvm_vcpu *dvcpu = NULL;
+
+	if (intr == 3 || intr == -3 || intr == 4 || intr == -4)
+		kvm_debug("%s: CPU: %d, INTR: %d\n", __func__, irq->cpu,
+			  (int)intr);
+
+	if (irq->cpu == -1)
+		dvcpu = vcpu;
+	else
+		dvcpu = vcpu->kvm->vcpus[irq->cpu];
+
+	if (intr == 2 || intr == 3 || intr == 4) {
+		kvm_mips_callbacks->queue_io_int(dvcpu, irq);
+
+	} else if (intr == -2 || intr == -3 || intr == -4) {
+		kvm_mips_callbacks->dequeue_io_int(dvcpu, irq);
+	} else {
+		kvm_err("%s: invalid interrupt ioctl (%d:%d)\n", __func__,
+			irq->cpu, irq->irq);
+		return -EINVAL;
+	}
+
+	dvcpu->arch.wait = 0;
+
+	if (waitqueue_active(&dvcpu->wq))
+		wake_up_interruptible(&dvcpu->wq);
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+				    struct kvm_mp_state *mp_state)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+				    struct kvm_mp_state *mp_state)
+{
+	return -ENOIOCTLCMD;
+}
+
+static u64 kvm_mips_get_one_regs[] = {
+	KVM_REG_MIPS_R0,
+	KVM_REG_MIPS_R1,
+	KVM_REG_MIPS_R2,
+	KVM_REG_MIPS_R3,
+	KVM_REG_MIPS_R4,
+	KVM_REG_MIPS_R5,
+	KVM_REG_MIPS_R6,
+	KVM_REG_MIPS_R7,
+	KVM_REG_MIPS_R8,
+	KVM_REG_MIPS_R9,
+	KVM_REG_MIPS_R10,
+	KVM_REG_MIPS_R11,
+	KVM_REG_MIPS_R12,
+	KVM_REG_MIPS_R13,
+	KVM_REG_MIPS_R14,
+	KVM_REG_MIPS_R15,
+	KVM_REG_MIPS_R16,
+	KVM_REG_MIPS_R17,
+	KVM_REG_MIPS_R18,
+	KVM_REG_MIPS_R19,
+	KVM_REG_MIPS_R20,
+	KVM_REG_MIPS_R21,
+	KVM_REG_MIPS_R22,
+	KVM_REG_MIPS_R23,
+	KVM_REG_MIPS_R24,
+	KVM_REG_MIPS_R25,
+	KVM_REG_MIPS_R26,
+	KVM_REG_MIPS_R27,
+	KVM_REG_MIPS_R28,
+	KVM_REG_MIPS_R29,
+	KVM_REG_MIPS_R30,
+	KVM_REG_MIPS_R31,
+
+	KVM_REG_MIPS_HI,
+	KVM_REG_MIPS_LO,
+	KVM_REG_MIPS_PC,
+
+	KVM_REG_MIPS_CP0_INDEX,
+	KVM_REG_MIPS_CP0_CONTEXT,
+	KVM_REG_MIPS_CP0_USERLOCAL,
+	KVM_REG_MIPS_CP0_PAGEMASK,
+	KVM_REG_MIPS_CP0_WIRED,
+	KVM_REG_MIPS_CP0_HWRENA,
+	KVM_REG_MIPS_CP0_BADVADDR,
+	KVM_REG_MIPS_CP0_COUNT,
+	KVM_REG_MIPS_CP0_ENTRYHI,
+	KVM_REG_MIPS_CP0_COMPARE,
+	KVM_REG_MIPS_CP0_STATUS,
+	KVM_REG_MIPS_CP0_CAUSE,
+	KVM_REG_MIPS_CP0_EPC,
+	KVM_REG_MIPS_CP0_CONFIG,
+	KVM_REG_MIPS_CP0_CONFIG1,
+	KVM_REG_MIPS_CP0_CONFIG2,
+	KVM_REG_MIPS_CP0_CONFIG3,
+	KVM_REG_MIPS_CP0_CONFIG7,
+	KVM_REG_MIPS_CP0_ERROREPC,
+
+	KVM_REG_MIPS_COUNT_CTL,
+	KVM_REG_MIPS_COUNT_RESUME,
+	KVM_REG_MIPS_COUNT_HZ,
+};
+
+static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
+			    const struct kvm_one_reg *reg)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int ret;
+	s64 v;
+
+	switch (reg->id) {
+	case KVM_REG_MIPS_R0 ... KVM_REG_MIPS_R31:
+		v = (long)vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0];
+		break;
+	case KVM_REG_MIPS_HI:
+		v = (long)vcpu->arch.hi;
+		break;
+	case KVM_REG_MIPS_LO:
+		v = (long)vcpu->arch.lo;
+		break;
+	case KVM_REG_MIPS_PC:
+		v = (long)vcpu->arch.pc;
+		break;
+
+	case KVM_REG_MIPS_CP0_INDEX:
+		v = (long)kvm_read_c0_guest_index(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONTEXT:
+		v = (long)kvm_read_c0_guest_context(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_USERLOCAL:
+		v = (long)kvm_read_c0_guest_userlocal(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_PAGEMASK:
+		v = (long)kvm_read_c0_guest_pagemask(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_WIRED:
+		v = (long)kvm_read_c0_guest_wired(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_HWRENA:
+		v = (long)kvm_read_c0_guest_hwrena(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_BADVADDR:
+		v = (long)kvm_read_c0_guest_badvaddr(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_ENTRYHI:
+		v = (long)kvm_read_c0_guest_entryhi(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_COMPARE:
+		v = (long)kvm_read_c0_guest_compare(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_STATUS:
+		v = (long)kvm_read_c0_guest_status(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CAUSE:
+		v = (long)kvm_read_c0_guest_cause(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_EPC:
+		v = (long)kvm_read_c0_guest_epc(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_ERROREPC:
+		v = (long)kvm_read_c0_guest_errorepc(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONFIG:
+		v = (long)kvm_read_c0_guest_config(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONFIG1:
+		v = (long)kvm_read_c0_guest_config1(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONFIG2:
+		v = (long)kvm_read_c0_guest_config2(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONFIG3:
+		v = (long)kvm_read_c0_guest_config3(cop0);
+		break;
+	case KVM_REG_MIPS_CP0_CONFIG7:
+		v = (long)kvm_read_c0_guest_config7(cop0);
+		break;
+	/* registers to be handled specially */
+	case KVM_REG_MIPS_CP0_COUNT:
+	case KVM_REG_MIPS_COUNT_CTL:
+	case KVM_REG_MIPS_COUNT_RESUME:
+	case KVM_REG_MIPS_COUNT_HZ:
+		ret = kvm_mips_callbacks->get_one_reg(vcpu, reg, &v);
+		if (ret)
+			return ret;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
+		u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
+
+		return put_user(v, uaddr64);
+	} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
+		u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
+		u32 v32 = (u32)v;
+
+		return put_user(v32, uaddr32);
+	} else {
+		return -EINVAL;
+	}
+}
+
+static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
+			    const struct kvm_one_reg *reg)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	u64 v;
+
+	if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
+		u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
+
+		if (get_user(v, uaddr64) != 0)
+			return -EFAULT;
+	} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
+		u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
+		s32 v32;
+
+		if (get_user(v32, uaddr32) != 0)
+			return -EFAULT;
+		v = (s64)v32;
+	} else {
+		return -EINVAL;
+	}
+
+	switch (reg->id) {
+	case KVM_REG_MIPS_R0:
+		/* Silently ignore requests to set $0 */
+		break;
+	case KVM_REG_MIPS_R1 ... KVM_REG_MIPS_R31:
+		vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0] = v;
+		break;
+	case KVM_REG_MIPS_HI:
+		vcpu->arch.hi = v;
+		break;
+	case KVM_REG_MIPS_LO:
+		vcpu->arch.lo = v;
+		break;
+	case KVM_REG_MIPS_PC:
+		vcpu->arch.pc = v;
+		break;
+
+	case KVM_REG_MIPS_CP0_INDEX:
+		kvm_write_c0_guest_index(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_CONTEXT:
+		kvm_write_c0_guest_context(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_USERLOCAL:
+		kvm_write_c0_guest_userlocal(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_PAGEMASK:
+		kvm_write_c0_guest_pagemask(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_WIRED:
+		kvm_write_c0_guest_wired(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_HWRENA:
+		kvm_write_c0_guest_hwrena(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_BADVADDR:
+		kvm_write_c0_guest_badvaddr(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_ENTRYHI:
+		kvm_write_c0_guest_entryhi(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_STATUS:
+		kvm_write_c0_guest_status(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_EPC:
+		kvm_write_c0_guest_epc(cop0, v);
+		break;
+	case KVM_REG_MIPS_CP0_ERROREPC:
+		kvm_write_c0_guest_errorepc(cop0, v);
+		break;
+	/* registers to be handled specially */
+	case KVM_REG_MIPS_CP0_COUNT:
+	case KVM_REG_MIPS_CP0_COMPARE:
+	case KVM_REG_MIPS_CP0_CAUSE:
+	case KVM_REG_MIPS_COUNT_CTL:
+	case KVM_REG_MIPS_COUNT_RESUME:
+	case KVM_REG_MIPS_COUNT_HZ:
+		return kvm_mips_callbacks->set_one_reg(vcpu, reg, v);
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
+			 unsigned long arg)
+{
+	struct kvm_vcpu *vcpu = filp->private_data;
+	void __user *argp = (void __user *)arg;
+	long r;
+
+	switch (ioctl) {
+	case KVM_SET_ONE_REG:
+	case KVM_GET_ONE_REG: {
+		struct kvm_one_reg reg;
+
+		if (copy_from_user(&reg, argp, sizeof(reg)))
+			return -EFAULT;
+		if (ioctl == KVM_SET_ONE_REG)
+			return kvm_mips_set_reg(vcpu, &reg);
+		else
+			return kvm_mips_get_reg(vcpu, &reg);
+	}
+	case KVM_GET_REG_LIST: {
+		struct kvm_reg_list __user *user_list = argp;
+		u64 __user *reg_dest;
+		struct kvm_reg_list reg_list;
+		unsigned n;
+
+		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
+			return -EFAULT;
+		n = reg_list.n;
+		reg_list.n = ARRAY_SIZE(kvm_mips_get_one_regs);
+		if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
+			return -EFAULT;
+		if (n < reg_list.n)
+			return -E2BIG;
+		reg_dest = user_list->reg;
+		if (copy_to_user(reg_dest, kvm_mips_get_one_regs,
+				 sizeof(kvm_mips_get_one_regs)))
+			return -EFAULT;
+		return 0;
+	}
+	case KVM_NMI:
+		/* Treat the NMI as a CPU reset */
+		r = kvm_mips_reset_vcpu(vcpu);
+		break;
+	case KVM_INTERRUPT:
+		{
+			struct kvm_mips_interrupt irq;
+
+			r = -EFAULT;
+			if (copy_from_user(&irq, argp, sizeof(irq)))
+				goto out;
+
+			kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__,
+				  irq.irq);
+
+			r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+			break;
+		}
+	default:
+		r = -ENOIOCTLCMD;
+	}
+
+out:
+	return r;
+}
+
+/* Get (and clear) the dirty memory log for a memory slot. */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
+{
+	struct kvm_memory_slot *memslot;
+	unsigned long ga, ga_end;
+	int is_dirty = 0;
+	int r;
+	unsigned long n;
+
+	mutex_lock(&kvm->slots_lock);
+
+	r = kvm_get_dirty_log(kvm, log, &is_dirty);
+	if (r)
+		goto out;
+
+	/* If nothing is dirty, don't bother messing with page tables. */
+	if (is_dirty) {
+		memslot = &kvm->memslots->memslots[log->slot];
+
+		ga = memslot->base_gfn << PAGE_SHIFT;
+		ga_end = ga + (memslot->npages << PAGE_SHIFT);
+
+		kvm_info("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga,
+			 ga_end);
+
+		n = kvm_dirty_bitmap_bytes(memslot);
+		memset(memslot->dirty_bitmap, 0, n);
+	}
+
+	r = 0;
+out:
+	mutex_unlock(&kvm->slots_lock);
+	return r;
+
+}
+
+long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+	long r;
+
+	switch (ioctl) {
+	default:
+		r = -ENOIOCTLCMD;
+	}
+
+	return r;
+}
+
+int kvm_arch_init(void *opaque)
+{
+	if (kvm_mips_callbacks) {
+		kvm_err("kvm: module already exists\n");
+		return -EEXIST;
+	}
+
+	return kvm_mips_emulation_init(&kvm_mips_callbacks);
+}
+
+void kvm_arch_exit(void)
+{
+	kvm_mips_callbacks = NULL;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+				  struct kvm_sregs *sregs)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+				  struct kvm_sregs *sregs)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	return -ENOIOCTLCMD;
+}
+
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
+{
+	int r;
+
+	switch (ext) {
+	case KVM_CAP_ONE_REG:
+		r = 1;
+		break;
+	case KVM_CAP_COALESCED_MMIO:
+		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
+		break;
+	default:
+		r = 0;
+		break;
+	}
+	return r;
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+	return kvm_mips_pending_timer(vcpu);
+}
+
+int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
+{
+	int i;
+	struct mips_coproc *cop0;
+
+	if (!vcpu)
+		return -1;
+
+	kvm_debug("VCPU Register Dump:\n");
+	kvm_debug("\tpc = 0x%08lx\n", vcpu->arch.pc);
+	kvm_debug("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
+
+	for (i = 0; i < 32; i += 4) {
+		kvm_debug("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i,
+		       vcpu->arch.gprs[i],
+		       vcpu->arch.gprs[i + 1],
+		       vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]);
+	}
+	kvm_debug("\thi: 0x%08lx\n", vcpu->arch.hi);
+	kvm_debug("\tlo: 0x%08lx\n", vcpu->arch.lo);
+
+	cop0 = vcpu->arch.cop0;
+	kvm_debug("\tStatus: 0x%08lx, Cause: 0x%08lx\n",
+		  kvm_read_c0_guest_status(cop0),
+		  kvm_read_c0_guest_cause(cop0));
+
+	kvm_debug("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0));
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+		vcpu->arch.gprs[i] = regs->gpr[i];
+	vcpu->arch.gprs[0] = 0; /* zero is special, and cannot be set. */
+	vcpu->arch.hi = regs->hi;
+	vcpu->arch.lo = regs->lo;
+	vcpu->arch.pc = regs->pc;
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+		regs->gpr[i] = vcpu->arch.gprs[i];
+
+	regs->hi = vcpu->arch.hi;
+	regs->lo = vcpu->arch.lo;
+	regs->pc = vcpu->arch.pc;
+
+	return 0;
+}
+
+static void kvm_mips_comparecount_func(unsigned long data)
+{
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+	kvm_mips_callbacks->queue_timer_int(vcpu);
+
+	vcpu->arch.wait = 0;
+	if (waitqueue_active(&vcpu->wq))
+		wake_up_interruptible(&vcpu->wq);
+}
+
+/* low level hrtimer wake routine */
+static enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
+{
+	struct kvm_vcpu *vcpu;
+
+	vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer);
+	kvm_mips_comparecount_func((unsigned long) vcpu);
+	return kvm_mips_count_timeout(vcpu);
+}
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	kvm_mips_callbacks->vcpu_init(vcpu);
+	hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+	vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup;
+	return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+				  struct kvm_translation *tr)
+{
+	return 0;
+}
+
+/* Initial guest state */
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	return kvm_mips_callbacks->vcpu_setup(vcpu);
+}
+
+static void kvm_mips_set_c0_status(void)
+{
+	uint32_t status = read_c0_status();
+
+	if (cpu_has_fpu)
+		status |= (ST0_CU1);
+
+	if (cpu_has_dsp)
+		status |= (ST0_MX);
+
+	write_c0_status(status);
+	ehb();
+}
+
+/*
+ * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
+ */
+int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	uint32_t cause = vcpu->arch.host_cp0_cause;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	/* Set a default exit reason */
+	run->exit_reason = KVM_EXIT_UNKNOWN;
+	run->ready_for_interrupt_injection = 1;
+
+	/*
+	 * Set the appropriate status bits based on host CPU features,
+	 * before we hit the scheduler
+	 */
+	kvm_mips_set_c0_status();
+
+	local_irq_enable();
+
+	kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n",
+			cause, opc, run, vcpu);
+
+	/*
+	 * Do a privilege check, if in UM most of these exit conditions end up
+	 * causing an exception to be delivered to the Guest Kernel
+	 */
+	er = kvm_mips_check_privilege(cause, opc, run, vcpu);
+	if (er == EMULATE_PRIV_FAIL) {
+		goto skip_emul;
+	} else if (er == EMULATE_FAIL) {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		goto skip_emul;
+	}
+
+	switch (exccode) {
+	case T_INT:
+		kvm_debug("[%d]T_INT @ %p\n", vcpu->vcpu_id, opc);
+
+		++vcpu->stat.int_exits;
+		trace_kvm_exit(vcpu, INT_EXITS);
+
+		if (need_resched())
+			cond_resched();
+
+		ret = RESUME_GUEST;
+		break;
+
+	case T_COP_UNUSABLE:
+		kvm_debug("T_COP_UNUSABLE: @ PC: %p\n", opc);
+
+		++vcpu->stat.cop_unusable_exits;
+		trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS);
+		ret = kvm_mips_callbacks->handle_cop_unusable(vcpu);
+		/* XXXKYMA: Might need to return to user space */
+		if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN)
+			ret = RESUME_HOST;
+		break;
+
+	case T_TLB_MOD:
+		++vcpu->stat.tlbmod_exits;
+		trace_kvm_exit(vcpu, TLBMOD_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_mod(vcpu);
+		break;
+
+	case T_TLB_ST_MISS:
+		kvm_debug("TLB ST fault:  cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
+			  cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
+			  badvaddr);
+
+		++vcpu->stat.tlbmiss_st_exits;
+		trace_kvm_exit(vcpu, TLBMISS_ST_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_st_miss(vcpu);
+		break;
+
+	case T_TLB_LD_MISS:
+		kvm_debug("TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n",
+			  cause, opc, badvaddr);
+
+		++vcpu->stat.tlbmiss_ld_exits;
+		trace_kvm_exit(vcpu, TLBMISS_LD_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_ld_miss(vcpu);
+		break;
+
+	case T_ADDR_ERR_ST:
+		++vcpu->stat.addrerr_st_exits;
+		trace_kvm_exit(vcpu, ADDRERR_ST_EXITS);
+		ret = kvm_mips_callbacks->handle_addr_err_st(vcpu);
+		break;
+
+	case T_ADDR_ERR_LD:
+		++vcpu->stat.addrerr_ld_exits;
+		trace_kvm_exit(vcpu, ADDRERR_LD_EXITS);
+		ret = kvm_mips_callbacks->handle_addr_err_ld(vcpu);
+		break;
+
+	case T_SYSCALL:
+		++vcpu->stat.syscall_exits;
+		trace_kvm_exit(vcpu, SYSCALL_EXITS);
+		ret = kvm_mips_callbacks->handle_syscall(vcpu);
+		break;
+
+	case T_RES_INST:
+		++vcpu->stat.resvd_inst_exits;
+		trace_kvm_exit(vcpu, RESVD_INST_EXITS);
+		ret = kvm_mips_callbacks->handle_res_inst(vcpu);
+		break;
+
+	case T_BREAK:
+		++vcpu->stat.break_inst_exits;
+		trace_kvm_exit(vcpu, BREAK_INST_EXITS);
+		ret = kvm_mips_callbacks->handle_break(vcpu);
+		break;
+
+	default:
+		kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x  BadVaddr: %#lx Status: %#lx\n",
+			exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
+			kvm_read_c0_guest_status(vcpu->arch.cop0));
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		break;
+
+	}
+
+skip_emul:
+	local_irq_disable();
+
+	if (er == EMULATE_DONE && !(ret & RESUME_HOST))
+		kvm_mips_deliver_interrupts(vcpu, cause);
+
+	if (!(ret & RESUME_HOST)) {
+		/* Only check for signals if not already exiting to userspace */
+		if (signal_pending(current)) {
+			run->exit_reason = KVM_EXIT_INTR;
+			ret = (-EINTR << 2) | RESUME_HOST;
+			++vcpu->stat.signal_exits;
+			trace_kvm_exit(vcpu, SIGNAL_EXITS);
+		}
+	}
+
+	return ret;
+}
+
+int __init kvm_mips_init(void)
+{
+	int ret;
+
+	ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * On MIPS, kernel modules are executed from "mapped space", which
+	 * requires TLBs. The TLB handling code is statically linked with
+	 * the rest of the kernel (tlb.c) to avoid the possibility of
+	 * double faulting. The issue is that the TLB code references
+	 * routines that are part of the the KVM module, which are only
+	 * available once the module is loaded.
+	 */
+	kvm_mips_gfn_to_pfn = gfn_to_pfn;
+	kvm_mips_release_pfn_clean = kvm_release_pfn_clean;
+	kvm_mips_is_error_pfn = is_error_pfn;
+
+	pr_info("KVM/MIPS Initialized\n");
+	return 0;
+}
+
+void __exit kvm_mips_exit(void)
+{
+	kvm_exit();
+
+	kvm_mips_gfn_to_pfn = NULL;
+	kvm_mips_release_pfn_clean = NULL;
+	kvm_mips_is_error_pfn = NULL;
+
+	pr_info("KVM/MIPS unloaded\n");
+}
+
+module_init(kvm_mips_init);
+module_exit(kvm_mips_exit);
+
+EXPORT_TRACEPOINT_SYMBOL(kvm_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/opcode.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/opcode.h
--- linux-libre-3.16-gnu/arch/mips/kvm/opcode.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/opcode.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+/* Define opcode values not defined in <asm/isnt.h> */
+
+#ifndef __KVM_MIPS_OPCODE_H__
+#define __KVM_MIPS_OPCODE_H__
+
+/* COP0 Ops */
+#define mfmcz_op	0x0b	/* 01011 */
+#define wrpgpr_op	0x0e	/* 01110 */
+
+/* COP0 opcodes (only if COP0 and CO=1): */
+#define wait_op		0x20	/* 100000 */
+
+#endif /* __KVM_MIPS_OPCODE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/stats.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/stats.c
--- linux-libre-3.16-gnu/arch/mips/kvm/stats.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/stats.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: COP0 access histogram
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/kvm_host.h>
+
+char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = {
+	"WAIT",
+	"CACHE",
+	"Signal",
+	"Interrupt",
+	"COP0/1 Unusable",
+	"TLB Mod",
+	"TLB Miss (LD)",
+	"TLB Miss (ST)",
+	"Address Err (ST)",
+	"Address Error (LD)",
+	"System Call",
+	"Reserved Inst",
+	"Break Inst",
+	"D-Cache Flushes",
+};
+
+char *kvm_cop0_str[N_MIPS_COPROC_REGS] = {
+	"Index",
+	"Random",
+	"EntryLo0",
+	"EntryLo1",
+	"Context",
+	"PG Mask",
+	"Wired",
+	"HWREna",
+	"BadVAddr",
+	"Count",
+	"EntryHI",
+	"Compare",
+	"Status",
+	"Cause",
+	"EXC PC",
+	"PRID",
+	"Config",
+	"LLAddr",
+	"Watch Lo",
+	"Watch Hi",
+	"X Context",
+	"Reserved",
+	"Impl Dep",
+	"Debug",
+	"DEPC",
+	"PerfCnt",
+	"ErrCtl",
+	"CacheErr",
+	"TagLo",
+	"TagHi",
+	"ErrorEPC",
+	"DESAVE"
+};
+
+void kvm_mips_dump_stats(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+	int i, j;
+
+	kvm_info("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id);
+	for (i = 0; i < N_MIPS_COPROC_REGS; i++) {
+		for (j = 0; j < N_MIPS_COPROC_SEL; j++) {
+			if (vcpu->arch.cop0->stat[i][j])
+				kvm_info("%s[%d]: %lu\n", kvm_cop0_str[i], j,
+					 vcpu->arch.cop0->stat[i][j]);
+		}
+	}
+#endif
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/tlb.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/tlb.c
--- linux-libre-3.16-gnu/arch/mips/kvm/tlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/tlb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,809 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
+ * TLB handlers run from KSEG0
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kvm_host.h>
+#include <linux/srcu.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+
+#undef CONFIG_MIPS_MT
+#include <asm/r4kcache.h>
+#define CONFIG_MIPS_MT
+
+#define KVM_GUEST_PC_TLB    0
+#define KVM_GUEST_SP_TLB    1
+
+#define PRIx64 "llx"
+
+atomic_t kvm_mips_instance;
+EXPORT_SYMBOL(kvm_mips_instance);
+
+/* These function pointers are initialized once the KVM module is loaded */
+pfn_t (*kvm_mips_gfn_to_pfn)(struct kvm *kvm, gfn_t gfn);
+EXPORT_SYMBOL(kvm_mips_gfn_to_pfn);
+
+void (*kvm_mips_release_pfn_clean)(pfn_t pfn);
+EXPORT_SYMBOL(kvm_mips_release_pfn_clean);
+
+bool (*kvm_mips_is_error_pfn)(pfn_t pfn);
+EXPORT_SYMBOL(kvm_mips_is_error_pfn);
+
+uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
+}
+
+uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
+}
+
+inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu)
+{
+	return vcpu->kvm->arch.commpage_tlb;
+}
+
+/* Structure defining an tlb entry data set. */
+
+void kvm_mips_dump_host_tlbs(void)
+{
+	unsigned long old_entryhi;
+	unsigned long old_pagemask;
+	struct kvm_mips_tlb tlb;
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+
+	kvm_info("HOST TLBs:\n");
+	kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
+
+	for (i = 0; i < current_cpu_data.tlbsize; i++) {
+		write_c0_index(i);
+		mtc0_tlbw_hazard();
+
+		tlb_read();
+		tlbw_use_hazard();
+
+		tlb.tlb_hi = read_c0_entryhi();
+		tlb.tlb_lo0 = read_c0_entrylo0();
+		tlb.tlb_lo1 = read_c0_entrylo1();
+		tlb.tlb_mask = read_c0_pagemask();
+
+		kvm_info("TLB%c%3d Hi 0x%08lx ",
+			 (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+			 i, tlb.tlb_hi);
+		kvm_info("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+			 (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+			 (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+			 (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+			 (tlb.tlb_lo0 >> 3) & 7);
+		kvm_info("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+			 (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+			 (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+			 (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+			 (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+	}
+	write_c0_entryhi(old_entryhi);
+	write_c0_pagemask(old_pagemask);
+	mtc0_tlbw_hazard();
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
+
+void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_mips_tlb tlb;
+	int i;
+
+	kvm_info("Guest TLBs:\n");
+	kvm_info("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
+
+	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
+		tlb = vcpu->arch.guest_tlb[i];
+		kvm_info("TLB%c%3d Hi 0x%08lx ",
+			 (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+			 i, tlb.tlb_hi);
+		kvm_info("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+			 (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+			 (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+			 (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+			 (tlb.tlb_lo0 >> 3) & 7);
+		kvm_info("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+			 (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+			 (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+			 (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+			 (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+	}
+}
+EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
+
+static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
+{
+	int srcu_idx, err = 0;
+	pfn_t pfn;
+
+	if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)
+		return 0;
+
+	srcu_idx = srcu_read_lock(&kvm->srcu);
+	pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
+
+	if (kvm_mips_is_error_pfn(pfn)) {
+		kvm_err("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
+		err = -EFAULT;
+		goto out;
+	}
+
+	kvm->arch.guest_pmap[gfn] = pfn;
+out:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+	return err;
+}
+
+/* Translate guest KSEG0 addresses to Host PA */
+unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
+						    unsigned long gva)
+{
+	gfn_t gfn;
+	uint32_t offset = gva & ~PAGE_MASK;
+	struct kvm *kvm = vcpu->kvm;
+
+	if (KVM_GUEST_KSEGX(gva) != KVM_GUEST_KSEG0) {
+		kvm_err("%s/%p: Invalid gva: %#lx\n", __func__,
+			__builtin_return_address(0), gva);
+		return KVM_INVALID_PAGE;
+	}
+
+	gfn = (KVM_GUEST_CPHYSADDR(gva) >> PAGE_SHIFT);
+
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: %#llx, GVA: %#lx\n", __func__, gfn,
+			gva);
+		return KVM_INVALID_PAGE;
+	}
+
+	if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
+		return KVM_INVALID_ADDR;
+
+	return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
+}
+EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
+
+/* XXXKYMA: Must be called with interrupts disabled */
+/* set flush_dcache_mask == 0 if no dcache flush required */
+int kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
+			    unsigned long entrylo0, unsigned long entrylo1,
+			    int flush_dcache_mask)
+{
+	unsigned long flags;
+	unsigned long old_entryhi;
+	int idx;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	write_c0_entryhi(entryhi);
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	if (idx > current_cpu_data.tlbsize) {
+		kvm_err("%s: Invalid Index: %d\n", __func__, idx);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+
+	if (idx < 0)
+		tlb_write_random();
+	else
+		tlb_write_indexed();
+	tlbw_use_hazard();
+
+	kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+		  vcpu->arch.pc, idx, read_c0_entryhi(),
+		  read_c0_entrylo0(), read_c0_entrylo1());
+
+	/* Flush D-cache */
+	if (flush_dcache_mask) {
+		if (entrylo0 & MIPS3_PG_V) {
+			++vcpu->stat.flush_dcache_exits;
+			flush_data_cache_page((entryhi & VPN2_MASK) &
+					      ~flush_dcache_mask);
+		}
+		if (entrylo1 & MIPS3_PG_V) {
+			++vcpu->stat.flush_dcache_exits;
+			flush_data_cache_page(((entryhi & VPN2_MASK) &
+					       ~flush_dcache_mask) |
+					      (0x1 << PAGE_SHIFT));
+		}
+	}
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* XXXKYMA: Must be called with interrupts disabled */
+int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
+				    struct kvm_vcpu *vcpu)
+{
+	gfn_t gfn;
+	pfn_t pfn0, pfn1;
+	unsigned long vaddr = 0;
+	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
+	int even;
+	struct kvm *kvm = vcpu->kvm;
+	const int flush_dcache_mask = 0;
+
+	if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) {
+		kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+
+	gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
+			gfn, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+	even = !(gfn & 0x1);
+	vaddr = badvaddr & (PAGE_MASK << 1);
+
+	if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
+		return -1;
+
+	if (kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1) < 0)
+		return -1;
+
+	if (even) {
+		pfn0 = kvm->arch.guest_pmap[gfn];
+		pfn1 = kvm->arch.guest_pmap[gfn ^ 0x1];
+	} else {
+		pfn0 = kvm->arch.guest_pmap[gfn ^ 0x1];
+		pfn1 = kvm->arch.guest_pmap[gfn];
+	}
+
+	entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+		   (1 << 2) | (0x1 << 1);
+	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
+		   (1 << 2) | (0x1 << 1);
+
+	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				       flush_dcache_mask);
+}
+EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
+
+int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
+	struct kvm_vcpu *vcpu)
+{
+	pfn_t pfn0, pfn1;
+	unsigned long flags, old_entryhi = 0, vaddr = 0;
+	unsigned long entrylo0 = 0, entrylo1 = 0;
+
+	pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
+	pfn1 = 0;
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+		   (1 << 2) | (0x1 << 1);
+	entrylo1 = 0;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	vaddr = badvaddr & (PAGE_MASK << 1);
+	write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu));
+	mtc0_tlbw_hazard();
+	write_c0_entrylo0(entrylo0);
+	mtc0_tlbw_hazard();
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+	write_c0_index(kvm_mips_get_commpage_asid(vcpu));
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+		  vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
+		  read_c0_entrylo0(), read_c0_entrylo1());
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
+
+int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
+					 struct kvm_mips_tlb *tlb,
+					 unsigned long *hpa0,
+					 unsigned long *hpa1)
+{
+	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
+	struct kvm *kvm = vcpu->kvm;
+	pfn_t pfn0, pfn1;
+
+	if ((tlb->tlb_hi & VPN2_MASK) == 0) {
+		pfn0 = 0;
+		pfn1 = 0;
+	} else {
+		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
+					   >> PAGE_SHIFT) < 0)
+			return -1;
+
+		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
+					   >> PAGE_SHIFT) < 0)
+			return -1;
+
+		pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
+					    >> PAGE_SHIFT];
+		pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
+					    >> PAGE_SHIFT];
+	}
+
+	if (hpa0)
+		*hpa0 = pfn0 << PAGE_SHIFT;
+
+	if (hpa1)
+		*hpa1 = pfn1 << PAGE_SHIFT;
+
+	/* Get attributes from the Guest TLB */
+	entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
+					       kvm_mips_get_kernel_asid(vcpu) :
+					       kvm_mips_get_user_asid(vcpu));
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+		   (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
+	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
+		   (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
+
+	kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
+		  tlb->tlb_lo0, tlb->tlb_lo1);
+
+	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				       tlb->tlb_mask);
+}
+EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
+
+int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
+{
+	int i;
+	int index = -1;
+	struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb;
+
+	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
+		if (TLB_HI_VPN2_HIT(tlb[i], entryhi) &&
+		    TLB_HI_ASID_HIT(tlb[i], entryhi)) {
+			index = i;
+			break;
+		}
+	}
+
+	kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n",
+		  __func__, entryhi, index, tlb[i].tlb_lo0, tlb[i].tlb_lo1);
+
+	return index;
+}
+EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
+
+int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
+{
+	unsigned long old_entryhi, flags;
+	int idx;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+
+	if (KVM_GUEST_KERNEL_MODE(vcpu))
+		write_c0_entryhi((vaddr & VPN2_MASK) |
+				 kvm_mips_get_kernel_asid(vcpu));
+	else {
+		write_c0_entryhi((vaddr & VPN2_MASK) |
+				 kvm_mips_get_user_asid(vcpu));
+	}
+
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+	kvm_debug("Host TLB lookup, %#lx, idx: %2d\n", vaddr, idx);
+
+	return idx;
+}
+EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
+
+int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
+{
+	int idx;
+	unsigned long flags, old_entryhi;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+
+	write_c0_entryhi((va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	if (idx >= current_cpu_data.tlbsize)
+		BUG();
+
+	if (idx > 0) {
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+		mtc0_tlbw_hazard();
+
+		write_c0_entrylo0(0);
+		mtc0_tlbw_hazard();
+
+		write_c0_entrylo1(0);
+		mtc0_tlbw_hazard();
+
+		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+	}
+
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+	if (idx > 0)
+		kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
+			  (va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu), idx);
+
+	return 0;
+}
+EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
+
+/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID */
+int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
+{
+	unsigned long flags, old_entryhi;
+
+	if (index >= current_cpu_data.tlbsize)
+		BUG();
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+
+	write_c0_entryhi(UNIQUE_ENTRYHI(index));
+	mtc0_tlbw_hazard();
+
+	write_c0_index(index);
+	mtc0_tlbw_hazard();
+
+	write_c0_entrylo0(0);
+	mtc0_tlbw_hazard();
+
+	write_c0_entrylo1(0);
+	mtc0_tlbw_hazard();
+
+	tlb_write_indexed();
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void kvm_mips_flush_host_tlb(int skip_kseg0)
+{
+	unsigned long flags;
+	unsigned long old_entryhi, entryhi;
+	unsigned long old_pagemask;
+	int entry = 0;
+	int maxentry = current_cpu_data.tlbsize;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+
+	/* Blast 'em all away. */
+	for (entry = 0; entry < maxentry; entry++) {
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+
+		if (skip_kseg0) {
+			tlb_read();
+			tlbw_use_hazard();
+
+			entryhi = read_c0_entryhi();
+
+			/* Don't blow away guest kernel entries */
+			if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0)
+				continue;
+		}
+
+		/* Make sure all entries differ. */
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+		mtc0_tlbw_hazard();
+		write_c0_entrylo0(0);
+		mtc0_tlbw_hazard();
+		write_c0_entrylo1(0);
+		mtc0_tlbw_hazard();
+
+		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+	}
+
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_entryhi);
+	write_c0_pagemask(old_pagemask);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
+
+void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
+			     struct kvm_vcpu *vcpu)
+{
+	unsigned long asid = asid_cache(cpu);
+
+	asid += ASID_INC;
+	if (!(asid & ASID_MASK)) {
+		if (cpu_has_vtag_icache)
+			flush_icache_all();
+
+		kvm_local_flush_tlb_all();      /* start new asid cycle */
+
+		if (!asid)      /* fix version if needed */
+			asid = ASID_FIRST_VERSION;
+	}
+
+	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
+}
+
+void kvm_local_flush_tlb_all(void)
+{
+	unsigned long flags;
+	unsigned long old_ctx;
+	int entry = 0;
+
+	local_irq_save(flags);
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi();
+	write_c0_entrylo0(0);
+	write_c0_entrylo1(0);
+
+	/* Blast 'em all away. */
+	while (entry < current_cpu_data.tlbsize) {
+		/* Make sure all entries differ. */
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+		tlb_write_indexed();
+		entry++;
+	}
+	tlbw_use_hazard();
+	write_c0_entryhi(old_ctx);
+	mtc0_tlbw_hazard();
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(kvm_local_flush_tlb_all);
+
+/**
+ * kvm_mips_migrate_count() - Migrate timer.
+ * @vcpu:	Virtual CPU.
+ *
+ * Migrate CP0_Count hrtimer to the current CPU by cancelling and restarting it
+ * if it was running prior to being cancelled.
+ *
+ * Must be called when the VCPU is migrated to a different CPU to ensure that
+ * timer expiry during guest execution interrupts the guest and causes the
+ * interrupt to be delivered in a timely manner.
+ */
+static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu)
+{
+	if (hrtimer_cancel(&vcpu->arch.comparecount_timer))
+		hrtimer_restart(&vcpu->arch.comparecount_timer);
+}
+
+/* Restore ASID once we are scheduled back after preemption */
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+	unsigned long flags;
+	int newasid = 0;
+
+	kvm_debug("%s: vcpu %p, cpu: %d\n", __func__, vcpu, cpu);
+
+	/* Alocate new kernel and user ASIDs if needed */
+
+	local_irq_save(flags);
+
+	if (((vcpu->arch.
+	      guest_kernel_asid[cpu] ^ asid_cache(cpu)) & ASID_VERSION_MASK)) {
+		kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
+		vcpu->arch.guest_kernel_asid[cpu] =
+		    vcpu->arch.guest_kernel_mm.context.asid[cpu];
+		kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);
+		vcpu->arch.guest_user_asid[cpu] =
+		    vcpu->arch.guest_user_mm.context.asid[cpu];
+		newasid++;
+
+		kvm_debug("[%d]: cpu_context: %#lx\n", cpu,
+			  cpu_context(cpu, current->mm));
+		kvm_debug("[%d]: Allocated new ASID for Guest Kernel: %#x\n",
+			  cpu, vcpu->arch.guest_kernel_asid[cpu]);
+		kvm_debug("[%d]: Allocated new ASID for Guest User: %#x\n", cpu,
+			  vcpu->arch.guest_user_asid[cpu]);
+	}
+
+	if (vcpu->arch.last_sched_cpu != cpu) {
+		kvm_debug("[%d->%d]KVM VCPU[%d] switch\n",
+			  vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
+		/*
+		 * Migrate the timer interrupt to the current CPU so that it
+		 * always interrupts the guest and synchronously triggers a
+		 * guest timer interrupt.
+		 */
+		kvm_mips_migrate_count(vcpu);
+	}
+
+	if (!newasid) {
+		/*
+		 * If we preempted while the guest was executing, then reload
+		 * the pre-empted ASID
+		 */
+		if (current->flags & PF_VCPU) {
+			write_c0_entryhi(vcpu->arch.
+					 preempt_entryhi & ASID_MASK);
+			ehb();
+		}
+	} else {
+		/* New ASIDs were allocated for the VM */
+
+		/*
+		 * Were we in guest context? If so then the pre-empted ASID is
+		 * no longer valid, we need to set it to what it should be based
+		 * on the mode of the Guest (Kernel/User)
+		 */
+		if (current->flags & PF_VCPU) {
+			if (KVM_GUEST_KERNEL_MODE(vcpu))
+				write_c0_entryhi(vcpu->arch.
+						 guest_kernel_asid[cpu] &
+						 ASID_MASK);
+			else
+				write_c0_entryhi(vcpu->arch.
+						 guest_user_asid[cpu] &
+						 ASID_MASK);
+			ehb();
+		}
+	}
+
+	local_irq_restore(flags);
+
+}
+EXPORT_SYMBOL(kvm_arch_vcpu_load);
+
+/* ASID can change if another task is scheduled during preemption */
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags;
+	uint32_t cpu;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+
+	vcpu->arch.preempt_entryhi = read_c0_entryhi();
+	vcpu->arch.last_sched_cpu = cpu;
+
+	if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
+	     ASID_VERSION_MASK)) {
+		kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
+			  cpu_context(cpu, current->mm));
+		drop_mmu_context(current->mm, cpu);
+	}
+	write_c0_entryhi(cpu_asid(cpu, current->mm));
+	ehb();
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(kvm_arch_vcpu_put);
+
+uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	unsigned long paddr, flags, vpn2, asid;
+	uint32_t inst;
+	int index;
+
+	if (KVM_GUEST_KSEGX((unsigned long) opc) < KVM_GUEST_KSEG0 ||
+	    KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		index = kvm_mips_host_tlb_lookup(vcpu, (unsigned long) opc);
+		if (index >= 0) {
+			inst = *(opc);
+		} else {
+			vpn2 = (unsigned long) opc & VPN2_MASK;
+			asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK;
+			index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
+			if (index < 0) {
+				kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
+					__func__, opc, vcpu, read_c0_entryhi());
+				kvm_mips_dump_host_tlbs();
+				local_irq_restore(flags);
+				return KVM_INVALID_INST;
+			}
+			kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
+							     &vcpu->arch.
+							     guest_tlb[index],
+							     NULL, NULL);
+			inst = *(opc);
+		}
+		local_irq_restore(flags);
+	} else if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		paddr =
+		    kvm_mips_translate_guest_kseg0_to_hpa(vcpu,
+							  (unsigned long) opc);
+		inst = *(uint32_t *) CKSEG0ADDR(paddr);
+	} else {
+		kvm_err("%s: illegal address: %p\n", __func__, opc);
+		return KVM_INVALID_INST;
+	}
+
+	return inst;
+}
+EXPORT_SYMBOL(kvm_get_inst);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/trace.h linux-libre-3.17-rc7-gnu/arch/mips/kvm/trace.h
--- linux-libre-3.16-gnu/arch/mips/kvm/trace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/trace.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,11 +1,11 @@
 /*
-* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.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.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
 
 #if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_KVM_H
@@ -17,9 +17,7 @@
 #define TRACE_INCLUDE_PATH .
 #define TRACE_INCLUDE_FILE trace
 
-/*
- * Tracepoints for VM eists
- */
+/* Tracepoints for VM eists */
 extern char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES];
 
 TRACE_EVENT(kvm_exit,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/kvm/trap_emul.c linux-libre-3.17-rc7-gnu/arch/mips/kvm/trap_emul.c
--- linux-libre-3.16-gnu/arch/mips/kvm/trap_emul.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/kvm/trap_emul.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,492 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: Deliver/Emulate exceptions to the guest kernel
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/kvm_host.h>
+
+#include "opcode.h"
+#include "interrupt.h"
+
+static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
+{
+	gpa_t gpa;
+	uint32_t kseg = KSEGX(gva);
+
+	if ((kseg == CKSEG0) || (kseg == CKSEG1))
+		gpa = CPHYSADDR(gva);
+	else {
+		kvm_err("%s: cannot find GPA for GVA: %#lx\n", __func__, gva);
+		kvm_mips_dump_host_tlbs();
+		gpa = KVM_INVALID_ADDR;
+	}
+
+	kvm_debug("%s: gva %#lx, gpa: %#llx\n", __func__, gva, gpa);
+
+	return gpa;
+}
+
+static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1)
+		er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
+	else
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+
+	switch (er) {
+	case EMULATE_DONE:
+		ret = RESUME_GUEST;
+		break;
+
+	case EMULATE_FAIL:
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		break;
+
+	case EMULATE_WAIT:
+		run->exit_reason = KVM_EXIT_INTR;
+		ret = RESUME_HOST;
+		break;
+
+	default:
+		BUG();
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+	    || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+		kvm_debug("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			  cause, opc, badvaddr);
+		er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu);
+
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		/*
+		 * XXXKYMA: The guest kernel does not expect to get this fault
+		 * when we are not using HIGHMEM. Need to address this in a
+		 * HIGHMEM kernel
+		 */
+		kvm_err("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	} else {
+		kvm_err("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
+	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
+		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+		kvm_debug("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			  cause, opc, badvaddr);
+		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		/*
+		 * All KSEG0 faults are handled by KVM, as the guest kernel does
+		 * not expect to ever get them
+		 */
+		if (kvm_mips_handle_kseg0_tlb_fault
+		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else {
+		kvm_err("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
+	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
+		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+		kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n",
+			  vcpu->arch.pc, badvaddr);
+
+		/*
+		 * User Address (UA) fault, this could happen if
+		 * (1) TLB entry not present/valid in both Guest and shadow host
+		 *     TLBs, in this case we pass on the fault to the guest
+		 *     kernel and let it handle it.
+		 * (2) TLB entry is present in the Guest TLB but not in the
+		 *     shadow, in this case we inject the TLB from the Guest TLB
+		 *     into the shadow host TLB
+		 */
+
+		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		if (kvm_mips_handle_kseg0_tlb_fault
+		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else {
+		kvm_err("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KVM_GUEST_KERNEL_MODE(vcpu)
+	    && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) {
+		kvm_debug("Emulate Store to MMIO space\n");
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+		if (er == EMULATE_FAIL) {
+			kvm_err("Emulate Store to MMIO space failed\n");
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		} else {
+			run->exit_reason = KVM_EXIT_MMIO;
+			ret = RESUME_HOST;
+		}
+	} else {
+		kvm_err("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) {
+		kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr);
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+		if (er == EMULATE_FAIL) {
+			kvm_err("Emulate Load from MMIO space failed\n");
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		} else {
+			run->exit_reason = KVM_EXIT_MMIO;
+			ret = RESUME_HOST;
+		}
+	} else {
+		kvm_err("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+			cause, opc, badvaddr);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		er = EMULATE_FAIL;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_emulate_syscall(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_handle_ri(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_emulate_bp_exc(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_vm_init(struct kvm *kvm)
+{
+	return 0;
+}
+
+static int kvm_trap_emul_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t config1;
+	int vcpu_id = vcpu->vcpu_id;
+
+	/*
+	 * Arch specific stuff, set up config registers properly so that the
+	 * guest will come up as expected, for now we simulate a MIPS 24kc
+	 */
+	kvm_write_c0_guest_prid(cop0, 0x00019300);
+	kvm_write_c0_guest_config(cop0,
+				  MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+				  (MMU_TYPE_R4000 << CP0C0_MT));
+
+	/* Read the cache characteristics from the host Config1 Register */
+	config1 = (read_c0_config1() & ~0x7f);
+
+	/* Set up MMU size */
+	config1 &= ~(0x3f << 25);
+	config1 |= ((KVM_MIPS_GUEST_TLB_SIZE - 1) << 25);
+
+	/* We unset some bits that we aren't emulating */
+	config1 &=
+	    ~((1 << CP0C1_C2) | (1 << CP0C1_MD) | (1 << CP0C1_PC) |
+	      (1 << CP0C1_WR) | (1 << CP0C1_CA));
+	kvm_write_c0_guest_config1(cop0, config1);
+
+	kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2);
+	/* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */
+	kvm_write_c0_guest_config3(cop0, MIPS_CONFIG3 | (0 << CP0C3_VInt) |
+					 (1 << CP0C3_ULRI));
+
+	/* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
+	kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
+
+	/*
+	 * Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5)
+	 */
+	kvm_write_c0_guest_intctl(cop0, 0xFC000000);
+
+	/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
+	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
+
+	return 0;
+}
+
+static int kvm_trap_emul_get_one_reg(struct kvm_vcpu *vcpu,
+				     const struct kvm_one_reg *reg,
+				     s64 *v)
+{
+	switch (reg->id) {
+	case KVM_REG_MIPS_CP0_COUNT:
+		*v = kvm_mips_read_count(vcpu);
+		break;
+	case KVM_REG_MIPS_COUNT_CTL:
+		*v = vcpu->arch.count_ctl;
+		break;
+	case KVM_REG_MIPS_COUNT_RESUME:
+		*v = ktime_to_ns(vcpu->arch.count_resume);
+		break;
+	case KVM_REG_MIPS_COUNT_HZ:
+		*v = vcpu->arch.count_hz;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
+				     const struct kvm_one_reg *reg,
+				     s64 v)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int ret = 0;
+
+	switch (reg->id) {
+	case KVM_REG_MIPS_CP0_COUNT:
+		kvm_mips_write_count(vcpu, v);
+		break;
+	case KVM_REG_MIPS_CP0_COMPARE:
+		kvm_mips_write_compare(vcpu, v);
+		break;
+	case KVM_REG_MIPS_CP0_CAUSE:
+		/*
+		 * If the timer is stopped or started (DC bit) it must look
+		 * atomic with changes to the interrupt pending bits (TI, IRQ5).
+		 * A timer interrupt should not happen in between.
+		 */
+		if ((kvm_read_c0_guest_cause(cop0) ^ v) & CAUSEF_DC) {
+			if (v & CAUSEF_DC) {
+				/* disable timer first */
+				kvm_mips_count_disable_cause(vcpu);
+				kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
+			} else {
+				/* enable timer last */
+				kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
+				kvm_mips_count_enable_cause(vcpu);
+			}
+		} else {
+			kvm_write_c0_guest_cause(cop0, v);
+		}
+		break;
+	case KVM_REG_MIPS_COUNT_CTL:
+		ret = kvm_mips_set_count_ctl(vcpu, v);
+		break;
+	case KVM_REG_MIPS_COUNT_RESUME:
+		ret = kvm_mips_set_count_resume(vcpu, v);
+		break;
+	case KVM_REG_MIPS_COUNT_HZ:
+		ret = kvm_mips_set_count_hz(vcpu, v);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return ret;
+}
+
+static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
+	/* exit handlers */
+	.handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
+	.handle_tlb_mod = kvm_trap_emul_handle_tlb_mod,
+	.handle_tlb_st_miss = kvm_trap_emul_handle_tlb_st_miss,
+	.handle_tlb_ld_miss = kvm_trap_emul_handle_tlb_ld_miss,
+	.handle_addr_err_st = kvm_trap_emul_handle_addr_err_st,
+	.handle_addr_err_ld = kvm_trap_emul_handle_addr_err_ld,
+	.handle_syscall = kvm_trap_emul_handle_syscall,
+	.handle_res_inst = kvm_trap_emul_handle_res_inst,
+	.handle_break = kvm_trap_emul_handle_break,
+
+	.vm_init = kvm_trap_emul_vm_init,
+	.vcpu_init = kvm_trap_emul_vcpu_init,
+	.vcpu_setup = kvm_trap_emul_vcpu_setup,
+	.gva_to_gpa = kvm_trap_emul_gva_to_gpa_cb,
+	.queue_timer_int = kvm_mips_queue_timer_int_cb,
+	.dequeue_timer_int = kvm_mips_dequeue_timer_int_cb,
+	.queue_io_int = kvm_mips_queue_io_int_cb,
+	.dequeue_io_int = kvm_mips_dequeue_io_int_cb,
+	.irq_deliver = kvm_mips_irq_deliver_cb,
+	.irq_clear = kvm_mips_irq_clear_cb,
+	.get_one_reg = kvm_trap_emul_get_one_reg,
+	.set_one_reg = kvm_trap_emul_set_one_reg,
+};
+
+int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
+{
+	*install_callbacks = &kvm_trap_emul_callbacks;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/common/env.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/env.c
--- linux-libre-3.16-gnu/arch/mips/loongson/common/env.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/env.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,12 @@ EXPORT_SYMBOL(cpu_clock_freq);
 struct efi_memory_map_loongson *loongson_memmap;
 struct loongson_system_configuration loongson_sysconf;
 
+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
+u64 loongson_freqctrl[MAX_PACKAGES];
+
+unsigned long long smp_group[4];
+int cpuhotplug_workaround = 0;
+
 #define parse_even_earlier(res, option, p)				\
 do {									\
 	unsigned int tmp __maybe_unused;				\
@@ -77,9 +83,47 @@ void __init prom_init_env(void)
 
 	cpu_clock_freq = ecpu->cpu_clock_freq;
 	loongson_sysconf.cputype = ecpu->cputype;
+	if (ecpu->cputype == Loongson_3A) {
+		loongson_sysconf.cores_per_node = 4;
+		loongson_sysconf.cores_per_package = 4;
+		smp_group[0] = 0x900000003ff01000;
+		smp_group[1] = 0x900010003ff01000;
+		smp_group[2] = 0x900020003ff01000;
+		smp_group[3] = 0x900030003ff01000;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+		loongson_chipcfg[1] = 0x900010001fe00180;
+		loongson_chipcfg[2] = 0x900020001fe00180;
+		loongson_chipcfg[3] = 0x900030001fe00180;
+		loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+	} else if (ecpu->cputype == Loongson_3B) {
+		loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
+		loongson_sysconf.cores_per_package = 8;
+		smp_group[0] = 0x900000003ff01000;
+		smp_group[1] = 0x900010003ff05000;
+		smp_group[2] = 0x900020003ff09000;
+		smp_group[3] = 0x900030003ff0d000;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+		loongson_chipcfg[1] = 0x900020001fe00180;
+		loongson_chipcfg[2] = 0x900040001fe00180;
+		loongson_chipcfg[3] = 0x900060001fe00180;
+		loongson_freqctrl[0] = 0x900000001fe001d0;
+		loongson_freqctrl[1] = 0x900020001fe001d0;
+		loongson_freqctrl[2] = 0x900040001fe001d0;
+		loongson_freqctrl[3] = 0x900060001fe001d0;
+		loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
+		cpuhotplug_workaround = 1;
+	} else {
+		loongson_sysconf.cores_per_node = 1;
+		loongson_sysconf.cores_per_package = 1;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+	}
+
 	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
 	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
 		loongson_sysconf.nr_cpus = NR_CPUS;
+	loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
+		loongson_sysconf.cores_per_node - 1) /
+		loongson_sysconf.cores_per_node;
 
 	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
 	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -93,7 +137,6 @@ void __init prom_init_env(void)
 	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
 	loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
 
-	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
 	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
 	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
 		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
@@ -111,6 +154,10 @@ void __init prom_init_env(void)
 		case PRID_REV_LOONGSON3A:
 			cpu_clock_freq = 900000000;
 			break;
+		case PRID_REV_LOONGSON3B_R1:
+		case PRID_REV_LOONGSON3B_R2:
+			cpu_clock_freq = 1000000000;
+			break;
 		default:
 			cpu_clock_freq = 100000000;
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/common/init.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/init.c
--- linux-libre-3.16-gnu/arch/mips/loongson/common/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,11 @@ void __init prom_init(void)
 	set_io_port_base((unsigned long)
 		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+#ifdef CONFIG_NUMA
+	prom_init_numa_memory();
+#else
 	prom_init_memory();
+#endif
 
 	/*init the uart base address */
 	prom_init_uart_base();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/common/pm.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/pm.c
--- linux-libre-3.16-gnu/arch/mips/loongson/common/pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/common/pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -79,7 +79,7 @@ int __weak wakeup_loongson(void)
 static void wait_for_wakeup_events(void)
 {
 	while (!wakeup_loongson())
-		LOONGSON_CHIPCFG0 &= ~0x7;
+		LOONGSON_CHIPCFG(0) &= ~0x7;
 }
 
 /*
@@ -102,15 +102,15 @@ static void loongson_suspend_enter(void)
 
 	stop_perf_counters();
 
-	cached_cpu_freq = LOONGSON_CHIPCFG0;
+	cached_cpu_freq = LOONGSON_CHIPCFG(0);
 
 	/* Put CPU into wait mode */
-	LOONGSON_CHIPCFG0 &= ~0x7;
+	LOONGSON_CHIPCFG(0) &= ~0x7;
 
 	/* wait for the given events to wakeup cpu from wait mode */
 	wait_for_wakeup_events();
 
-	LOONGSON_CHIPCFG0 = cached_cpu_freq;
+	LOONGSON_CHIPCFG(0) = cached_cpu_freq;
 	mmiowb();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/Kconfig linux-libre-3.17-rc7-gnu/arch/mips/loongson/Kconfig
--- linux-libre-3.16-gnu/arch/mips/loongson/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -60,8 +60,8 @@ config LEMOTE_MACH2F
 	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
 	  LingLoong allinone PC and so forth.
 
-config LEMOTE_MACH3A
-	bool "Lemote Loongson 3A family machines"
+config LOONGSON_MACH3X
+	bool "Generic Loongson 3 family machines"
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
 	select BOOT_ELF32
@@ -79,6 +79,7 @@ config LEMOTE_MACH3A
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_HOTPLUG_CPU
+	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -86,8 +87,8 @@ config LEMOTE_MACH3A
 	select ZONE_DMA32
 	select LEFI_FIRMWARE_INTERFACE
 	help
-		Lemote Loongson 3A family machines utilize the 3A revision of
-		Loongson processor and RS780/SBX00 chipset.
+		Generic Loongson 3 family machines utilize the 3A/3B revision
+		of Loongson processor and RS780/SBX00 chipset.
 endchoice
 
 config CS5536
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/lemote-2f/clock.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/lemote-2f/clock.c
--- linux-libre-3.16-gnu/arch/mips/loongson/lemote-2f/clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/lemote-2f/clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,9 +114,9 @@ int clk_set_rate(struct clk *clk, unsign
 
 	clk->rate = rate;
 
-	regval = LOONGSON_CHIPCFG0;
+	regval = LOONGSON_CHIPCFG(0);
 	regval = (regval & ~0x7) | (pos->driver_data - 1);
-	LOONGSON_CHIPCFG0 = regval;
+	LOONGSON_CHIPCFG(0) = regval;
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/lemote-2f/reset.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/lemote-2f/reset.c
--- linux-libre-3.16-gnu/arch/mips/loongson/lemote-2f/reset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/lemote-2f/reset.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@ static void reset_cpu(void)
 	 * reset cpu to full speed, this is needed when enabling cpu frequency
 	 * scalling
 	 */
-	LOONGSON_CHIPCFG0 |= 0x7;
+	LOONGSON_CHIPCFG(0) |= 0x7;
 }
 
 /* reset support for fuloong2f */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/cop2-ex.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/cop2-ex.c
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/cop2-ex.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/cop2-ex.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * 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) 2014 Lemote Corporation.
+ *   written by Huacai Chen <chenhc@lemote.com>
+ *
+ * based on arch/mips/cavium-octeon/cpu.c
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+
+#include <asm/fpu.h>
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+
+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
+	void *data)
+{
+	int fpu_owned;
+	int fr = !test_thread_flag(TIF_32BIT_FPREGS);
+
+	switch (action) {
+	case CU2_EXCEPTION:
+		preempt_disable();
+		fpu_owned = __is_fpu_owner();
+		if (!fr)
+			set_c0_status(ST0_CU1 | ST0_CU2);
+		else
+			set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR);
+		enable_fpu_hazard();
+		KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2);
+		if (fr)
+			KSTK_STATUS(current) |= ST0_FR;
+		else
+			KSTK_STATUS(current) &= ~ST0_FR;
+		/* If FPU is owned, we needn't init or restore fp */
+		if (!fpu_owned) {
+			set_thread_flag(TIF_USEDFPU);
+			if (!used_math()) {
+				_init_fpu();
+				set_used_math();
+			} else
+				_restore_fp(current);
+		}
+		preempt_enable();
+
+		return NOTIFY_STOP;	/* Don't call default notifier */
+	}
+
+	return NOTIFY_OK;		/* Let default notifier send signals */
+}
+
+static int __init loongson_cu2_setup(void)
+{
+	return cu2_notifier(loongson_cu2_call, 0);
+}
+early_initcall(loongson_cu2_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/irq.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/irq.c
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,8 @@
 #include <asm/i8259.h>
 #include <asm/mipsregs.h>
 
+#include "smp.h"
+
 unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
 
 static void ht_irqdispatch(void)
@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(str
 	/* Workaround: UART IRQ may deliver to any core */
 	if (d->irq == LOONGSON_UART_IRQ) {
 		int cpu = smp_processor_id();
+		int node_id = cpu / loongson_sysconf.cores_per_node;
+		int core_id = cpu % loongson_sysconf.cores_per_node;
+		u64 intenclr_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_INTENCLR);
+		u64 introuter_lpc_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_LPC);
 
-		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
-		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+		*(volatile u32 *)intenclr_addr = 1 << 10;
+		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
 	}
 }
 
@@ -64,9 +72,15 @@ static inline void unmask_loongson_irq(s
 	/* Workaround: UART IRQ may deliver to any core */
 	if (d->irq == LOONGSON_UART_IRQ) {
 		int cpu = smp_processor_id();
+		int node_id = cpu / loongson_sysconf.cores_per_node;
+		int core_id = cpu % loongson_sysconf.cores_per_node;
+		u64 intenset_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_INTENSET);
+		u64 introuter_lpc_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_LPC);
 
-		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
-		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+		*(volatile u32 *)intenset_addr = 1 << 10;
+		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
 	}
 
 	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/Makefile linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/Makefile
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,8 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y			+= irq.o
+obj-y			+= irq.o cop2-ex.o
 
 obj-$(CONFIG_SMP)	+= smp.o
+
+obj-$(CONFIG_NUMA)	+= numa.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/numa.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/numa.c
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/numa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/numa.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/kernel.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <linux/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+#include <boot_param.h>
+
+static struct node_data prealloc__node_data[MAX_NUMNODES];
+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+struct node_data *__node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(__node_data);
+
+static void enable_lpa(void)
+{
+	unsigned long value;
+
+	value = __read_32bit_c0_register($16, 3);
+	value |= 0x00000080;
+	__write_32bit_c0_register($16, 3, value);
+	value = __read_32bit_c0_register($16, 3);
+	pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
+
+	value = __read_32bit_c0_register($5, 1);
+	value |= 0x20000000;
+	__write_32bit_c0_register($5, 1, value);
+	value = __read_32bit_c0_register($5, 1);
+	pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
+}
+
+static void cpu_node_probe(void)
+{
+	int i;
+
+	nodes_clear(node_possible_map);
+	nodes_clear(node_online_map);
+	for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
+		node_set_state(num_online_nodes(), N_POSSIBLE);
+		node_set_online(num_online_nodes());
+	}
+
+	pr_info("NUMA: Discovered %d cpus on %d nodes\n",
+		loongson_sysconf.nr_cpus, num_online_nodes());
+}
+
+static int __init compute_node_distance(int row, int col)
+{
+	int package_row = row * loongson_sysconf.cores_per_node /
+				loongson_sysconf.cores_per_package;
+	int package_col = col * loongson_sysconf.cores_per_node /
+				loongson_sysconf.cores_per_package;
+
+	if (col == row)
+		return 0;
+	else if (package_row == package_col)
+		return 40;
+	else
+		return 100;
+}
+
+static void __init init_topology_matrix(void)
+{
+	int row, col;
+
+	for (row = 0; row < MAX_NUMNODES; row++)
+		for (col = 0; col < MAX_NUMNODES; col++)
+			__node_distances[row][col] = -1;
+
+	for_each_online_node(row) {
+		for_each_online_node(col) {
+			__node_distances[row][col] =
+				compute_node_distance(row, col);
+		}
+	}
+}
+
+static unsigned long nid_to_addroffset(unsigned int nid)
+{
+	unsigned long result;
+	switch (nid) {
+	case 0:
+	default:
+		result = NODE0_ADDRSPACE_OFFSET;
+		break;
+	case 1:
+		result = NODE1_ADDRSPACE_OFFSET;
+		break;
+	case 2:
+		result = NODE2_ADDRSPACE_OFFSET;
+		break;
+	case 3:
+		result = NODE3_ADDRSPACE_OFFSET;
+		break;
+	}
+	return result;
+}
+
+static void __init szmem(unsigned int node)
+{
+	u32 i, mem_type;
+	static unsigned long num_physpages = 0;
+	u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+
+	/* Parse memory information and activate */
+	for (i = 0; i < loongson_memmap->nr_map; i++) {
+		node_id = loongson_memmap->map[i].node_id;
+		if (node_id != node)
+			continue;
+
+		mem_type = loongson_memmap->map[i].mem_type;
+		mem_size = loongson_memmap->map[i].mem_size;
+		mem_start = loongson_memmap->map[i].mem_start;
+
+		switch (mem_type) {
+		case SYSTEM_RAM_LOW:
+			start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+			node_psize = (mem_size << 20) >> PAGE_SHIFT;
+			end_pfn  = start_pfn + node_psize;
+			num_physpages += node_psize;
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+				start_pfn, end_pfn, num_physpages);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RAM);
+			memblock_add_node(PFN_PHYS(start_pfn),
+				PFN_PHYS(end_pfn - start_pfn), node);
+			break;
+		case SYSTEM_RAM_HIGH:
+			start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+			node_psize = (mem_size << 20) >> PAGE_SHIFT;
+			end_pfn  = start_pfn + node_psize;
+			num_physpages += node_psize;
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+				start_pfn, end_pfn, num_physpages);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RAM);
+			memblock_add_node(PFN_PHYS(start_pfn),
+				PFN_PHYS(end_pfn - start_pfn), node);
+			break;
+		case MEM_RESERVED:
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RESERVED);
+			memblock_reserve(((node_id << 44) + mem_start),
+				mem_size << 20);
+			break;
+		}
+	}
+}
+
+static void __init node_mem_init(unsigned int node)
+{
+	unsigned long bootmap_size;
+	unsigned long node_addrspace_offset;
+	unsigned long start_pfn, end_pfn, freepfn;
+
+	node_addrspace_offset = nid_to_addroffset(node);
+	pr_info("Node%d's addrspace_offset is 0x%lx\n",
+			node, node_addrspace_offset);
+
+	get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+	freepfn = start_pfn;
+	if (node == 0)
+		freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
+	pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
+		node, start_pfn, end_pfn, freepfn);
+
+	__node_data[node] = prealloc__node_data + node;
+
+	NODE_DATA(node)->bdata = &bootmem_node_data[node];
+	NODE_DATA(node)->node_start_pfn = start_pfn;
+	NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
+
+	bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
+					start_pfn, end_pfn);
+	free_bootmem_with_active_regions(node, end_pfn);
+	if (node == 0) /* used by finalize_initrd() */
+		max_low_pfn = end_pfn;
+
+	/* This is reserved for the kernel and bdata->node_bootmem_map */
+	reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
+		((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
+		BOOTMEM_DEFAULT);
+
+	if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
+		/* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+		reserve_bootmem_node(NODE_DATA(node),
+				(node_addrspace_offset | 0xff800000),
+				8 << 20, BOOTMEM_DEFAULT);
+	}
+
+	sparse_memory_present_with_active_regions(node);
+}
+
+static __init void prom_meminit(void)
+{
+	unsigned int node, cpu;
+
+	cpu_node_probe();
+	init_topology_matrix();
+
+	for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
+		if (node_online(node)) {
+			szmem(node);
+			node_mem_init(node);
+			cpus_clear(__node_data[(node)]->cpumask);
+		}
+	}
+	for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
+		node = cpu / loongson_sysconf.cores_per_node;
+		if (node >= num_online_nodes())
+			node = 0;
+		pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
+		cpu_set(cpu, __node_data[(node)]->cpumask);
+	}
+}
+
+void __init paging_init(void)
+{
+	unsigned node;
+	unsigned long zones_size[MAX_NR_ZONES] = {0, };
+
+	pagetable_init();
+
+	for_each_online_node(node) {
+		unsigned long  start_pfn, end_pfn;
+
+		get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+
+		if (end_pfn > max_low_pfn)
+			max_low_pfn = end_pfn;
+	}
+#ifdef CONFIG_ZONE_DMA32
+	zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
+#endif
+	zones_size[ZONE_NORMAL] = max_low_pfn;
+	free_area_init_nodes(zones_size);
+}
+
+void __init mem_init(void)
+{
+	high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
+	free_all_bootmem();
+	setup_zero_pages();	/* This comes from node 0 */
+	mem_init_print_info(NULL);
+}
+
+/* All PCI device belongs to logical Node-0 */
+int pcibus_to_node(struct pci_bus *bus)
+{
+	return 0;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+
+void __init prom_init_numa_memory(void)
+{
+	enable_lpa();
+	prom_meminit();
+}
+EXPORT_SYMBOL(prom_init_numa_memory);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/smp.c linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/smp.c
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,12 @@
 DEFINE_PER_CPU(int, cpu_state);
 DEFINE_PER_CPU(uint32_t, core0_c0count);
 
+static void *ipi_set0_regs[16];
+static void *ipi_clear0_regs[16];
+static void *ipi_status0_regs[16];
+static void *ipi_en0_regs[16];
+static void *ipi_mailbox_buf[16];
+
 /* read a 32bit value from ipi register */
 #define loongson3_ipi_read32(addr) readl(addr)
 /* read a 64bit value from ipi register */
@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count);
 		__wbflush();			\
 	} while (0)
 
-static void *ipi_set0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
-};
+static void ipi_set0_regs_init(void)
+{
+	ipi_set0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
+}
 
-static void *ipi_clear0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
-};
+static void ipi_clear0_regs_init(void)
+{
+	ipi_clear0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
+}
 
-static void *ipi_status0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
-};
+static void ipi_status0_regs_init(void)
+{
+	ipi_status0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
+}
 
-static void *ipi_en0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
-};
+static void ipi_en0_regs_init(void)
+{
+	ipi_en0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
+}
 
-static void *ipi_mailbox_buf[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
-};
+static void ipi_mailbox_buf_init(void)
+{
+	ipi_mailbox_buf[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
+}
 
 /*
  * Simple enough, just poke the appropriate ipi register
@@ -203,6 +294,8 @@ static void loongson3_init_secondary(voi
 	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
 		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
 
+	cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
+	cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
 	per_cpu(cpu_state, cpu) = CPU_ONLINE;
 
 	i = 0;
@@ -246,6 +339,11 @@ static void __init loongson3_smp_setup(v
 		__cpu_number_map[i] = ++num;
 		__cpu_logical_map[num] = i;
 	}
+	ipi_set0_regs_init();
+	ipi_clear0_regs_init();
+	ipi_status0_regs_init();
+	ipi_en0_regs_init();
+	ipi_mailbox_buf_init();
 	pr_info("Detected %i available secondary CPU(s)\n", num);
 }
 
@@ -313,7 +411,7 @@ static void loongson3_cpu_die(unsigned i
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
  * called via CKSEG1 (uncached and unmmaped) */
-static void loongson3_play_dead(int *state_addr)
+static void loongson3a_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -375,6 +473,70 @@ static void loongson3_play_dead(int *sta
 		: "a1");
 }
 
+static void loongson3b_play_dead(int *state_addr)
+{
+	register int val;
+	register long cpuid, core, node, count;
+	register void *addr, *base, *initfunc;
+
+	__asm__ __volatile__(
+		"   .set push                     \n"
+		"   .set noreorder                \n"
+		"   li %[addr], 0x80000000        \n" /* KSEG0 */
+		"1: cache 0, 0(%[addr])           \n" /* flush L1 ICache */
+		"   cache 0, 1(%[addr])           \n"
+		"   cache 0, 2(%[addr])           \n"
+		"   cache 0, 3(%[addr])           \n"
+		"   cache 1, 0(%[addr])           \n" /* flush L1 DCache */
+		"   cache 1, 1(%[addr])           \n"
+		"   cache 1, 2(%[addr])           \n"
+		"   cache 1, 3(%[addr])           \n"
+		"   addiu %[sets], %[sets], -1    \n"
+		"   bnez  %[sets], 1b             \n"
+		"   addiu %[addr], %[addr], 0x20  \n"
+		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
+		"   sw    %[val], (%[state_addr]) \n"
+		"   sync                          \n"
+		"   cache 21, (%[state_addr])     \n" /* flush entry of *state_addr */
+		"   .set pop                      \n"
+		: [addr] "=&r" (addr), [val] "=&r" (val)
+		: [state_addr] "r" (state_addr),
+		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+
+	__asm__ __volatile__(
+		"   .set push                         \n"
+		"   .set noreorder                    \n"
+		"   .set mips64                       \n"
+		"   mfc0  %[cpuid], $15, 1            \n"
+		"   andi  %[cpuid], 0x3ff             \n"
+		"   dli   %[base], 0x900000003ff01000 \n"
+		"   andi  %[core], %[cpuid], 0x3      \n"
+		"   sll   %[core], 8                  \n" /* get core id */
+		"   or    %[base], %[base], %[core]   \n"
+		"   andi  %[node], %[cpuid], 0xc      \n"
+		"   dsll  %[node], 42                 \n" /* get node id */
+		"   or    %[base], %[base], %[node]   \n"
+		"   dsrl  %[node], 30                 \n" /* 15:14 */
+		"   or    %[base], %[base], %[node]   \n"
+		"1: li    %[count], 0x100             \n" /* wait for init loop */
+		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
+		"   addiu %[count], -1                \n"
+		"   ld    %[initfunc], 0x20(%[base])  \n" /* get PC via mailbox */
+		"   beqz  %[initfunc], 1b             \n"
+		"   nop                               \n"
+		"   ld    $sp, 0x28(%[base])          \n" /* get SP via mailbox */
+		"   ld    $gp, 0x30(%[base])          \n" /* get GP via mailbox */
+		"   ld    $a1, 0x38(%[base])          \n"
+		"   jr    %[initfunc]                 \n" /* jump to initial PC */
+		"   nop                               \n"
+		"   .set pop                          \n"
+		: [core] "=&r" (core), [node] "=&r" (node),
+		  [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+		  [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+		: /* No Input */
+		: "a1");
+}
+
 void play_dead(void)
 {
 	int *state_addr;
@@ -382,13 +544,48 @@ void play_dead(void)
 	void (*play_dead_at_ckseg1)(int *);
 
 	idle_task_exit();
-	play_dead_at_ckseg1 =
-		(void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+	switch (loongson_sysconf.cputype) {
+	case Loongson_3A:
+	default:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+		break;
+	case Loongson_3B:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
+		break;
+	}
 	state_addr = &per_cpu(cpu_state, cpu);
 	mb();
 	play_dead_at_ckseg1(state_addr);
 }
 
+void loongson3_disable_clock(int cpu)
+{
+	uint64_t core_id = cpu_data[cpu].core;
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if (loongson_sysconf.cputype == Loongson_3A) {
+		LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
+	} else if (loongson_sysconf.cputype == Loongson_3B) {
+		if (!cpuhotplug_workaround)
+			LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
+	}
+}
+
+void loongson3_enable_clock(int cpu)
+{
+	uint64_t core_id = cpu_data[cpu].core;
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if (loongson_sysconf.cputype == Loongson_3A) {
+		LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
+	} else if (loongson_sysconf.cputype == Loongson_3B) {
+		if (!cpuhotplug_workaround)
+			LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
+	}
+}
+
 #define CPU_POST_DEAD_FROZEN	(CPU_POST_DEAD | CPU_TASKS_FROZEN)
 static int loongson3_cpu_callback(struct notifier_block *nfb,
 	unsigned long action, void *hcpu)
@@ -399,12 +596,12 @@ static int loongson3_cpu_callback(struct
 	case CPU_POST_DEAD:
 	case CPU_POST_DEAD_FROZEN:
 		pr_info("Disable clock for CPU#%d\n", cpu);
-		LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+		loongson3_disable_clock(cpu);
 		break;
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
 		pr_info("Enable clock for CPU#%d\n", cpu);
-		LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+		loongson3_enable_clock(cpu);
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/smp.h linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/smp.h
--- linux-libre-3.16-gnu/arch/mips/loongson/loongson-3/smp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/loongson-3/smp.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,29 +1,30 @@
 #ifndef __LOONGSON_SMP_H_
 #define __LOONGSON_SMP_H_
 
-/* for Loongson-3A smp support */
+/* for Loongson-3 smp support */
+extern unsigned long long smp_group[4];
 
 /* 4 groups(nodes) in maximum in numa case */
-#define  SMP_CORE_GROUP0_BASE    0x900000003ff01000
-#define  SMP_CORE_GROUP1_BASE    0x900010003ff01000
-#define  SMP_CORE_GROUP2_BASE    0x900020003ff01000
-#define  SMP_CORE_GROUP3_BASE    0x900030003ff01000
+#define SMP_CORE_GROUP0_BASE	(smp_group[0])
+#define SMP_CORE_GROUP1_BASE	(smp_group[1])
+#define SMP_CORE_GROUP2_BASE	(smp_group[2])
+#define SMP_CORE_GROUP3_BASE	(smp_group[3])
 
 /* 4 cores in each group(node) */
-#define  SMP_CORE0_OFFSET  0x000
-#define  SMP_CORE1_OFFSET  0x100
-#define  SMP_CORE2_OFFSET  0x200
-#define  SMP_CORE3_OFFSET  0x300
+#define SMP_CORE0_OFFSET  0x000
+#define SMP_CORE1_OFFSET  0x100
+#define SMP_CORE2_OFFSET  0x200
+#define SMP_CORE3_OFFSET  0x300
 
 /* ipi registers offsets */
-#define  STATUS0  0x00
-#define  EN0      0x04
-#define  SET0     0x08
-#define  CLEAR0   0x0c
-#define  STATUS1  0x10
-#define  MASK1    0x14
-#define  SET1     0x18
-#define  CLEAR1   0x1c
-#define  BUF      0x20
+#define STATUS0  0x00
+#define EN0      0x04
+#define SET0     0x08
+#define CLEAR0   0x0c
+#define STATUS1  0x10
+#define MASK1    0x14
+#define SET1     0x18
+#define CLEAR1   0x1c
+#define BUF      0x20
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/loongson/Platform linux-libre-3.17-rc7-gnu/arch/mips/loongson/Platform
--- linux-libre-3.16-gnu/arch/mips/loongson/Platform	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/loongson/Platform	2014-09-28 17:29:07.000000000 -0400
@@ -30,4 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loon
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
 load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/Makefile linux-libre-3.17-rc7-gnu/arch/mips/Makefile
--- linux-libre-3.16-gnu/arch/mips/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -113,7 +113,16 @@ predef-le += -DMIPSEL -D_MIPSEL -D__MIPS
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
 
-cflags-$(CONFIG_CPU_HAS_SMARTMIPS)	+= $(call cc-option,-msmartmips)
+# For smartmips configurations, there are hundreds of warnings due to ISA overrides
+# in assembly and header files. smartmips is only supported for MIPS32r1 onwards
+# and there is no support for 64-bit. Various '.set mips2' or '.set mips3' or
+# similar directives in the kernel will spam the build logs with the following warnings:
+# Warning: the `smartmips' extension requires MIPS32 revision 1 or greater
+# or
+# Warning: the 64-bit MIPS architecture does not support the `smartmips' extension
+# Pass -Wa,--no-warn to disable all assembler warnings until the kernel code has
+# been fixed properly.
+cflags-$(CONFIG_CPU_HAS_SMARTMIPS)	+= $(call cc-option,-msmartmips) -Wa,--no-warn
 cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips)
 
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= $(call cc-option,-mno-sched-prolog) \
@@ -151,8 +160,10 @@ cflags-$(CONFIG_CPU_NEVADA)	+= $(call cc
 			-Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)	+= $(call cc-option,-march=rm7000,-march=r5000) \
 			-Wa,--trap
-cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1,-march=r5000) \
 			-Wa,--trap
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-mno-mdmx)
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-mno-mips3d)
 cflags-$(CONFIG_CPU_R8000)	+= -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)	+= $(call cc-option,-march=r10000,-march=r8000) \
 			-Wa,--trap
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/math-emu/cp1emu.c linux-libre-3.17-rc7-gnu/arch/mips/math-emu/cp1emu.c
--- linux-libre-3.16-gnu/arch/mips/math-emu/cp1emu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/math-emu/cp1emu.c	2014-09-28 17:29:07.000000000 -0400
@@ -650,9 +650,9 @@ static inline int cop1_64bit(struct pt_r
 #define SIFROMREG(si, x)						\
 do {									\
 	if (cop1_64bit(xcp))						\
-		(si) = get_fpr32(&ctx->fpr[x], 0);			\
+		(si) = (int)get_fpr32(&ctx->fpr[x], 0);			\
 	else								\
-		(si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1);		\
+		(si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1);	\
 } while (0)
 
 #define SITOREG(si, x)							\
@@ -667,7 +667,7 @@ do {									\
 	}								\
 } while (0)
 
-#define SIFROMHREG(si, x)	((si) = get_fpr32(&ctx->fpr[x], 1))
+#define SIFROMHREG(si, x)	((si) = (int)get_fpr32(&ctx->fpr[x], 1))
 
 #define SITOHREG(si, x)							\
 do {									\
@@ -1827,7 +1827,7 @@ dcopuop:
 	case -1:
 
 		if (cpu_has_mips_4_5_r)
-			cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
+			cbit = fpucondbit[MIPSInst_FD(ir) >> 2];
 		else
 			cbit = FPU_CSR_COND;
 		if (rv.w)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/cache.c linux-libre-3.17-rc7-gnu/arch/mips/mm/cache.c
--- linux-libre-3.16-gnu/arch/mips/mm/cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,25 +119,36 @@ void __flush_anon_page(struct page *page
 
 EXPORT_SYMBOL(__flush_anon_page);
 
-void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte)
+static void mips_flush_dcache_from_pte(pte_t pteval, unsigned long address)
 {
 	struct page *page;
-	unsigned long pfn, addr;
-	int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
+	unsigned long pfn = pte_pfn(pteval);
 
-	pfn = pte_pfn(pte);
 	if (unlikely(!pfn_valid(pfn)))
 		return;
+
 	page = pfn_to_page(pfn);
 	if (page_mapping(page) && Page_dcache_dirty(page)) {
-		addr = (unsigned long) page_address(page);
-		if (exec || pages_do_alias(addr, address & PAGE_MASK))
-			flush_data_cache_page(addr);
+		unsigned long page_addr = (unsigned long) page_address(page);
+
+		if (!cpu_has_ic_fills_f_dc ||
+		    pages_do_alias(page_addr, address & PAGE_MASK))
+			flush_data_cache_page(page_addr);
 		ClearPageDcacheDirty(page);
 	}
 }
 
+void set_pte_at(struct mm_struct *mm, unsigned long addr,
+        pte_t *ptep, pte_t pteval)
+{
+        if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) {
+                if (pte_present(pteval))
+                        mips_flush_dcache_from_pte(pteval, addr);
+        }
+
+        set_pte(ptep, pteval);
+}
+
 unsigned long _page_cachable_default;
 EXPORT_SYMBOL(_page_cachable_default);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/c-r4k.c linux-libre-3.17-rc7-gnu/arch/mips/mm/c-r4k.c
--- linux-libre-3.16-gnu/arch/mips/mm/c-r4k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/c-r4k.c	2014-09-28 17:29:07.000000000 -0400
@@ -1230,19 +1230,19 @@ static void probe_pcache(void)
 	case CPU_R14000:
 		break;
 
+	case CPU_74K:
+	case CPU_1074K:
+		alias_74k_erratum(c);
+		/* Fall through. */
 	case CPU_M14KC:
 	case CPU_M14KEC:
 	case CPU_24K:
 	case CPU_34K:
-	case CPU_74K:
 	case CPU_1004K:
-	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
-		if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
-			alias_74k_erratum(c);
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/init.c linux-libre-3.17-rc7-gnu/arch/mips/mm/init.c
--- linux-libre-3.16-gnu/arch/mips/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,6 +53,7 @@
  */
 unsigned long empty_zero_page, zero_page_mask;
 EXPORT_SYMBOL_GPL(empty_zero_page);
+EXPORT_SYMBOL(zero_page_mask);
 
 /*
  * Not static inline because used by IP27 special magic initialization code
@@ -325,6 +326,38 @@ static inline void mem_init_free_highmem
 #endif
 }
 
+unsigned __weak platform_maar_init(unsigned num_maars)
+{
+	return 0;
+}
+
+static void maar_init(void)
+{
+	unsigned num_maars, used, i;
+
+	if (!cpu_has_maar)
+		return;
+
+	/* Detect the number of MAARs */
+	write_c0_maari(~0);
+	back_to_back_c0_hazard();
+	num_maars = read_c0_maari() + 1;
+
+	/* MAARs should be in pairs */
+	WARN_ON(num_maars % 2);
+
+	/* Configure the required MAARs */
+	used = platform_maar_init(num_maars / 2);
+
+	/* Disable any further MAARs */
+	for (i = (used * 2); i < num_maars; i++) {
+		write_c0_maari(i);
+		back_to_back_c0_hazard();
+		write_c0_maar(0);
+		back_to_back_c0_hazard();
+	}
+}
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -337,6 +370,7 @@ void __init mem_init(void)
 #endif
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
+	maar_init();
 	free_all_bootmem();
 	setup_zero_pages();	/* Setup zeroed pages.  */
 	mem_init_free_highmem();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/tlbex.c linux-libre-3.17-rc7-gnu/arch/mips/mm/tlbex.c
--- linux-libre-3.16-gnu/arch/mips/mm/tlbex.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/tlbex.c	2014-09-28 17:29:07.000000000 -0400
@@ -429,6 +429,7 @@ static void build_r3000_tlb_refill_handl
 		 (unsigned int)(p - tlb_handler));
 
 	memcpy((void *)ebase, tlb_handler, 0x80);
+	local_flush_icache_range(ebase, ebase + 0x80);
 
 	dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
 }
@@ -1299,6 +1300,7 @@ static void build_r4000_tlb_refill_handl
 	}
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	uasm_l_tlb_huge_update(&l, p);
+	UASM_i_LW(&p, K0, 0, K1);
 	build_huge_update_entries(&p, htlb_info.huge_pte, K1);
 	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
 				   htlb_info.restore_scratch);
@@ -1415,6 +1417,7 @@ static void build_r4000_tlb_refill_handl
 		 final_len);
 
 	memcpy((void *)ebase, final_handler, 0x100);
+	local_flush_icache_range(ebase, ebase + 0x100);
 
 	dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
@@ -1919,7 +1922,7 @@ static void build_r4000_tlb_load_handler
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 
-	if (cpu_has_rixi) {
+	if (cpu_has_rixi && !cpu_has_rixiex) {
 		/*
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
@@ -1986,7 +1989,7 @@ static void build_r4000_tlb_load_handler
 	build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
 	build_tlb_probe_entry(&p);
 
-	if (cpu_has_rixi) {
+	if (cpu_has_rixi && !cpu_has_rixiex) {
 		/*
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
@@ -2194,6 +2197,94 @@ static void flush_tlb_handlers(void)
 			   (unsigned long)tlbmiss_handler_setup_pgd_end);
 }
 
+static void print_htw_config(void)
+{
+	unsigned long config;
+	unsigned int pwctl;
+	const int field = 2 * sizeof(unsigned long);
+
+	config = read_c0_pwfield();
+	pr_debug("PWField (0x%0*lx): GDI: 0x%02lx  UDI: 0x%02lx  MDI: 0x%02lx  PTI: 0x%02lx  PTEI: 0x%02lx\n",
+		field, config,
+		(config & MIPS_PWFIELD_GDI_MASK) >> MIPS_PWFIELD_GDI_SHIFT,
+		(config & MIPS_PWFIELD_UDI_MASK) >> MIPS_PWFIELD_UDI_SHIFT,
+		(config & MIPS_PWFIELD_MDI_MASK) >> MIPS_PWFIELD_MDI_SHIFT,
+		(config & MIPS_PWFIELD_PTI_MASK) >> MIPS_PWFIELD_PTI_SHIFT,
+		(config & MIPS_PWFIELD_PTEI_MASK) >> MIPS_PWFIELD_PTEI_SHIFT);
+
+	config = read_c0_pwsize();
+	pr_debug("PWSize  (0x%0*lx): GDW: 0x%02lx  UDW: 0x%02lx  MDW: 0x%02lx  PTW: 0x%02lx  PTEW: 0x%02lx\n",
+		field, config,
+		(config & MIPS_PWSIZE_GDW_MASK) >> MIPS_PWSIZE_GDW_SHIFT,
+		(config & MIPS_PWSIZE_UDW_MASK) >> MIPS_PWSIZE_UDW_SHIFT,
+		(config & MIPS_PWSIZE_MDW_MASK) >> MIPS_PWSIZE_MDW_SHIFT,
+		(config & MIPS_PWSIZE_PTW_MASK) >> MIPS_PWSIZE_PTW_SHIFT,
+		(config & MIPS_PWSIZE_PTEW_MASK) >> MIPS_PWSIZE_PTEW_SHIFT);
+
+	pwctl = read_c0_pwctl();
+	pr_debug("PWCtl   (0x%x): PWEn: 0x%x  DPH: 0x%x  HugePg: 0x%x  Psn: 0x%x\n",
+		pwctl,
+		(pwctl & MIPS_PWCTL_PWEN_MASK) >> MIPS_PWCTL_PWEN_SHIFT,
+		(pwctl & MIPS_PWCTL_DPH_MASK) >> MIPS_PWCTL_DPH_SHIFT,
+		(pwctl & MIPS_PWCTL_HUGEPG_MASK) >> MIPS_PWCTL_HUGEPG_SHIFT,
+		(pwctl & MIPS_PWCTL_PSN_MASK) >> MIPS_PWCTL_PSN_SHIFT);
+}
+
+static void config_htw_params(void)
+{
+	unsigned long pwfield, pwsize, ptei;
+	unsigned int config;
+
+	/*
+	 * We are using 2-level page tables, so we only need to
+	 * setup GDW and PTW appropriately. UDW and MDW will remain 0.
+	 * The default value of GDI/UDI/MDI/PTI is 0xc. It is illegal to
+	 * write values less than 0xc in these fields because the entire
+	 * write will be dropped. As a result of which, we must preserve
+	 * the original reset values and overwrite only what we really want.
+	 */
+
+	pwfield = read_c0_pwfield();
+	/* re-initialize the GDI field */
+	pwfield &= ~MIPS_PWFIELD_GDI_MASK;
+	pwfield |= PGDIR_SHIFT << MIPS_PWFIELD_GDI_SHIFT;
+	/* re-initialize the PTI field including the even/odd bit */
+	pwfield &= ~MIPS_PWFIELD_PTI_MASK;
+	pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+	/* Set the PTEI right shift */
+	ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
+	pwfield |= ptei;
+	write_c0_pwfield(pwfield);
+	/* Check whether the PTEI value is supported */
+	back_to_back_c0_hazard();
+	pwfield = read_c0_pwfield();
+	if (((pwfield & MIPS_PWFIELD_PTEI_MASK) << MIPS_PWFIELD_PTEI_SHIFT)
+		!= ptei) {
+		pr_warn("Unsupported PTEI field value: 0x%lx. HTW will not be enabled",
+			ptei);
+		/*
+		 * Drop option to avoid HTW being enabled via another path
+		 * (eg htw_reset())
+		 */
+		current_cpu_data.options &= ~MIPS_CPU_HTW;
+		return;
+	}
+
+	pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
+	pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+	write_c0_pwsize(pwsize);
+
+	/* Make sure everything is set before we enable the HTW */
+	back_to_back_c0_hazard();
+
+	/* Enable HTW and disable the rest of the pwctl fields */
+	config = 1 << MIPS_PWCTL_PWEN_SHIFT;
+	write_c0_pwctl(config);
+	pr_info("Hardware Page Table Walker enabled\n");
+
+	print_htw_config();
+}
+
 void build_tlb_refill_handler(void)
 {
 	/*
@@ -2258,5 +2349,8 @@ void build_tlb_refill_handler(void)
 		}
 		if (cpu_has_local_ebase)
 			build_r4000_tlb_refill_handler();
+		if (cpu_has_htw)
+			config_htw_params();
+
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/tlb-r3k.c linux-libre-3.17-rc7-gnu/arch/mips/mm/tlb-r3k.c
--- linux-libre-3.16-gnu/arch/mips/mm/tlb-r3k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/tlb-r3k.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,7 +158,7 @@ void local_flush_tlb_page(struct vm_area
 {
 	int cpu = smp_processor_id();
 
-	if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+	if (cpu_context(cpu, vma->vm_mm) != 0) {
 		unsigned long flags;
 		int oldpid, newpid, idx;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mm/tlb-r4k.c linux-libre-3.17-rc7-gnu/arch/mips/mm/tlb-r4k.c
--- linux-libre-3.16-gnu/arch/mips/mm/tlb-r4k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mm/tlb-r4k.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,6 +57,7 @@ void local_flush_tlb_all(void)
 	local_irq_save(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
+	htw_stop();
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
 
@@ -90,6 +91,7 @@ void local_flush_tlb_all(void)
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
+	htw_start();
 	flush_itlb();
 	local_irq_restore(flags);
 }
@@ -131,6 +133,7 @@ void local_flush_tlb_range(struct vm_are
 			int oldpid = read_c0_entryhi();
 			int newpid = cpu_asid(cpu, mm);
 
+			htw_stop();
 			while (start < end) {
 				int idx;
 
@@ -151,6 +154,7 @@ void local_flush_tlb_range(struct vm_are
 			}
 			tlbw_use_hazard();
 			write_c0_entryhi(oldpid);
+			htw_start();
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
@@ -174,6 +178,7 @@ void local_flush_tlb_kernel_range(unsign
 		start &= (PAGE_MASK << 1);
 		end += ((PAGE_SIZE << 1) - 1);
 		end &= (PAGE_MASK << 1);
+		htw_stop();
 
 		while (start < end) {
 			int idx;
@@ -195,6 +200,7 @@ void local_flush_tlb_kernel_range(unsign
 		}
 		tlbw_use_hazard();
 		write_c0_entryhi(pid);
+		htw_start();
 	} else {
 		local_flush_tlb_all();
 	}
@@ -214,6 +220,7 @@ void local_flush_tlb_page(struct vm_area
 		page &= (PAGE_MASK << 1);
 		local_irq_save(flags);
 		oldpid = read_c0_entryhi();
+		htw_stop();
 		write_c0_entryhi(page | newpid);
 		mtc0_tlbw_hazard();
 		tlb_probe();
@@ -231,6 +238,7 @@ void local_flush_tlb_page(struct vm_area
 
 	finish:
 		write_c0_entryhi(oldpid);
+		htw_start();
 		flush_itlb_vm(vma);
 		local_irq_restore(flags);
 	}
@@ -247,6 +255,7 @@ void local_flush_tlb_one(unsigned long p
 
 	local_irq_save(flags);
 	oldpid = read_c0_entryhi();
+	htw_stop();
 	page &= (PAGE_MASK << 1);
 	write_c0_entryhi(page);
 	mtc0_tlbw_hazard();
@@ -263,6 +272,7 @@ void local_flush_tlb_one(unsigned long p
 		tlbw_use_hazard();
 	}
 	write_c0_entryhi(oldpid);
+	htw_start();
 	flush_itlb();
 	local_irq_restore(flags);
 }
@@ -351,6 +361,7 @@ void add_wired_entry(unsigned long entry
 	local_irq_save(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
+	htw_stop();
 	old_pagemask = read_c0_pagemask();
 	wired = read_c0_wired();
 	write_c0_wired(wired + 1);
@@ -366,6 +377,7 @@ void add_wired_entry(unsigned long entry
 
 	write_c0_entryhi(old_ctx);
 	tlbw_use_hazard();	/* What is the hazard here? */
+	htw_start();
 	write_c0_pagemask(old_pagemask);
 	local_flush_tlb_all();
 	local_irq_restore(flags);
@@ -391,6 +403,51 @@ int __init has_transparent_hugepage(void
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
 
+/*
+ * Used for loading TLB entries before trap_init() has started, when we
+ * don't actually want to add a wired entry which remains throughout the
+ * lifetime of the system
+ */
+
+int temp_tlb_entry __cpuinitdata;
+
+__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+			       unsigned long entryhi, unsigned long pagemask)
+{
+	int ret = 0;
+	unsigned long flags;
+	unsigned long wired;
+	unsigned long old_pagemask;
+	unsigned long old_ctx;
+
+	local_irq_save(flags);
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+	wired = read_c0_wired();
+	if (--temp_tlb_entry < wired) {
+		printk(KERN_WARNING
+		       "No TLB space left for add_temporary_entry\n");
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	write_c0_index(temp_tlb_entry);
+	write_c0_pagemask(pagemask);
+	write_c0_entryhi(entryhi);
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_ctx);
+	write_c0_pagemask(old_pagemask);
+out:
+	local_irq_restore(flags);
+	return ret;
+}
+
 static int ntlb;
 static int __init set_ntlb(char *str)
 {
@@ -431,6 +488,8 @@ static void r4k_tlb_configure(void)
 		write_c0_pagegrain(pg);
 	}
 
+	temp_tlb_entry = current_cpu_data.tlbsize - 1;
+
 	/* From this point on the ARC firmware is dead.	 */
 	local_flush_tlb_all();
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mti-malta/malta-int.c linux-libre-3.17-rc7-gnu/arch/mips/mti-malta/malta-int.c
--- linux-libre-3.16-gnu/arch/mips/mti-malta/malta-int.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mti-malta/malta-int.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,10 @@ static unsigned int ipi_map[NR_CPUS];
 
 static DEFINE_RAW_SPINLOCK(mips_irq_lock);
 
+#ifdef CONFIG_MIPS_GIC_IPI
+DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS);
+#endif
+
 static inline int mips_pcibios_iack(void)
 {
 	int irq;
@@ -125,16 +129,22 @@ static void malta_hw0_irqdispatch(void)
 
 static void malta_ipi_irqdispatch(void)
 {
-	int irq;
+#ifdef CONFIG_MIPS_GIC_IPI
+	unsigned long irq;
+	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
 
-	if (gic_compare_int())
-		do_IRQ(MIPS_GIC_IRQ_BASE);
+	gic_get_int_mask(pending, ipi_ints);
 
-	irq = gic_get_int();
-	if (irq < 0)
-		return;	 /* interrupt has already been cleared */
+	irq = find_first_bit(pending, GIC_NUM_INTRS);
 
-	do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+	while (irq < GIC_NUM_INTRS) {
+		do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+
+		irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1);
+	}
+#endif
+	if (gic_compare_int())
+		do_IRQ(MIPS_GIC_IRQ_BASE);
 }
 
 static void corehi_irqdispatch(void)
@@ -427,8 +437,9 @@ static void __init fill_ipi_map1(int bas
 	gic_intr_map[intr].pin = cpupin;
 	gic_intr_map[intr].polarity = GIC_POL_POS;
 	gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
-	gic_intr_map[intr].flags = GIC_FLAG_IPI;
+	gic_intr_map[intr].flags = 0;
 	ipi_map[cpu] |= (1 << (cpupin + 2));
+	bitmap_set(ipi_ints, intr, 1);
 }
 
 static void __init fill_ipi_map(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/mti-malta/malta-memory.c linux-libre-3.17-rc7-gnu/arch/mips/mti-malta/malta-memory.c
--- linux-libre-3.16-gnu/arch/mips/mti-malta/malta-memory.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/mti-malta/malta-memory.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/maar.h>
 #include <asm/sections.h>
 #include <asm/fw/fw.h>
 
@@ -34,13 +35,19 @@ fw_memblock_t * __init fw_getmdesc(int e
 	/* otherwise look in the environment */
 
 	memsize_str = fw_getenv("memsize");
-	if (memsize_str)
-		tmp = kstrtol(memsize_str, 0, &memsize);
+	if (memsize_str) {
+		tmp = kstrtoul(memsize_str, 0, &memsize);
+		if (tmp)
+			pr_warn("Failed to read the 'memsize' env variable.\n");
+	}
 	if (eva) {
 	/* Look for ememsize for EVA */
 		ememsize_str = fw_getenv("ememsize");
-		if (ememsize_str)
-			tmp = kstrtol(ememsize_str, 0, &ememsize);
+		if (ememsize_str) {
+			tmp = kstrtoul(ememsize_str, 0, &ememsize);
+			if (tmp)
+				pr_warn("Failed to read the 'ememsize' env variable.\n");
+		}
 	}
 	if (!memsize && !ememsize) {
 		pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
@@ -164,3 +171,28 @@ void __init prom_free_prom_memory(void)
 				addr, addr + boot_mem_map.map[i].size);
 	}
 }
+
+unsigned platform_maar_init(unsigned num_pairs)
+{
+	phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
+	struct maar_config cfg[] = {
+		/* DRAM preceding I/O */
+		{ 0x00000000, 0x0fffffff, MIPS_MAAR_S },
+
+		/* DRAM following I/O */
+		{ 0x20000000, mem_end, MIPS_MAAR_S },
+
+		/* DRAM alias in upper half of physical */
+		{ 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
+	};
+	unsigned i, num_cfg = ARRAY_SIZE(cfg);
+
+	/* If DRAM fits before I/O, drop the region following it */
+	if (physical_memsize <= 0x10000000) {
+		num_cfg--;
+		for (i = 1; i < num_cfg; i++)
+			cfg[i] = cfg[i + 1];
+	}
+
+	return maar_config(cfg, num_cfg, num_pairs);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/net/bpf_jit.c linux-libre-3.17-rc7-gnu/arch/mips/net/bpf_jit.c
--- linux-libre-3.16-gnu/arch/mips/net/bpf_jit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/net/bpf_jit.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,7 +131,7 @@
  * @target:		Memory location for the compiled filter
  */
 struct jit_ctx {
-	const struct sk_filter *skf;
+	const struct bpf_prog *skf;
 	unsigned int prologue_bytes;
 	u32 idx;
 	u32 flags;
@@ -789,10 +789,11 @@ static int pkt_type_offset(void)
 static int build_body(struct jit_ctx *ctx)
 {
 	void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
-	const struct sk_filter *prog = ctx->skf;
+	const struct bpf_prog *prog = ctx->skf;
 	const struct sock_filter *inst;
 	unsigned int i, off, load_order, condt;
 	u32 k, b_off __maybe_unused;
+	int tmp;
 
 	for (i = 0; i < prog->len; i++) {
 		u16 code;
@@ -1332,9 +1333,9 @@ jmp_cmp:
 		case BPF_ANC | SKF_AD_PKTTYPE:
 			ctx->flags |= SEEN_SKB;
 
-			off = pkt_type_offset();
+			tmp = off = pkt_type_offset();
 
-			if (off < 0)
+			if (tmp < 0)
 				return -1;
 			emit_load_byte(r_tmp, r_skb, off, ctx);
 			/* Keep only the last 3 bits */
@@ -1369,7 +1370,7 @@ jmp_cmp:
 
 int bpf_jit_enable __read_mostly;
 
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
 {
 	struct jit_ctx ctx;
 	unsigned int alloc_size, tmp_idx;
@@ -1423,7 +1424,7 @@ out:
 	kfree(ctx.offsets);
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
 		module_free(NULL, fp->bpf_func);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/pci/Makefile linux-libre-3.17-rc7-gnu/arch/mips/pci/Makefile
--- linux-libre-3.16-gnu/arch/mips/pci/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/pci/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
 obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_LEMOTE_MACH3A)	+= fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_LOONGSON_MACH3X)	+= fixup-loongson3.o ops-loongson3.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o pci-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/pci/ops-tx4927.c linux-libre-3.17-rc7-gnu/arch/mips/pci/ops-tx4927.c
--- linux-libre-3.16-gnu/arch/mips/pci/ops-tx4927.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/pci/ops-tx4927.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,8 +199,6 @@ static struct {
 
 char *tx4927_pcibios_setup(char *str)
 {
-	unsigned long val;
-
 	if (!strncmp(str, "trdyto=", 7)) {
 		u8 val = 0;
 		if (kstrtou8(str + 7, 0, &val) == 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/pci/pci-alchemy.c linux-libre-3.17-rc7-gnu/arch/mips/pci/pci-alchemy.c
--- linux-libre-3.16-gnu/arch/mips/pci/pci-alchemy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/pci/pci-alchemy.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@
  * Support for all devices (greater than 16) added by David Gathright.
  */
 
+#include <linux/clk.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -364,6 +365,7 @@ static int alchemy_pci_probe(struct plat
 	void __iomem *virt_io;
 	unsigned long val;
 	struct resource *r;
+	struct clk *c;
 	int ret;
 
 	/* need at least PCI IRQ mapping table */
@@ -393,11 +395,24 @@ static int alchemy_pci_probe(struct plat
 		goto out1;
 	}
 
+	c = clk_get(&pdev->dev, "pci_clko");
+	if (IS_ERR(c)) {
+		dev_err(&pdev->dev, "unable to find PCI clock\n");
+		ret = PTR_ERR(c);
+		goto out2;
+	}
+
+	ret = clk_prepare_enable(c);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot enable PCI clock\n");
+		goto out6;
+	}
+
 	ctx->regs = ioremap_nocache(r->start, resource_size(r));
 	if (!ctx->regs) {
 		dev_err(&pdev->dev, "cannot map pci regs\n");
 		ret = -ENODEV;
-		goto out2;
+		goto out5;
 	}
 
 	/* map parts of the PCI IO area */
@@ -465,12 +480,19 @@ static int alchemy_pci_probe(struct plat
 	register_syscore_ops(&alchemy_pci_pmops);
 	register_pci_controller(&ctx->alchemy_pci_ctrl);
 
+	dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
+		 clk_get_rate(c) / 1000000);
+
 	return 0;
 
 out4:
 	iounmap(virt_io);
 out3:
 	iounmap(ctx->regs);
+out5:
+	clk_disable_unprepare(c);
+out6:
+	clk_put(c);
 out2:
 	release_mem_region(r->start, resource_size(r));
 out1:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/pmcs-msp71xx/msp_irq.c linux-libre-3.17-rc7-gnu/arch/mips/pmcs-msp71xx/msp_irq.c
--- linux-libre-3.16-gnu/arch/mips/pmcs-msp71xx/msp_irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/pmcs-msp71xx/msp_irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ static inline void sec_int_dispatch(void
  * the range 40-71.
  */
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	u32 pending;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/ralink/of.c linux-libre-3.17-rc7-gnu/arch/mips/ralink/of.c
--- linux-libre-3.16-gnu/arch/mips/ralink/of.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/ralink/of.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,7 +81,7 @@ static int __init plat_of_setup(void)
 		panic("device tree not present");
 
 	strlcpy(of_ids[0].compatible, soc_info.compatible, len);
-	strncpy(of_ids[1].compatible, "palmbus", len);
+	strlcpy(of_ids[1].compatible, "palmbus", len);
 
 	if (of_platform_populate(NULL, of_ids, NULL, NULL))
 		panic("failed to populate DT");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/rb532/devices.c linux-libre-3.17-rc7-gnu/arch/mips/rb532/devices.c
--- linux-libre-3.16-gnu/arch/mips/rb532/devices.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/rb532/devices.c	2014-09-28 17:29:07.000000000 -0400
@@ -223,6 +223,7 @@ static struct platform_device rb532_wdt
 
 static struct plat_serial8250_port rb532_uart_res[] = {
 	{
+		.type           = PORT_16550A,
 		.membase	= (char *)KSEG1ADDR(REGBASE + UART0BASE),
 		.irq		= UART0_IRQ,
 		.regshift	= 2,
@@ -250,28 +251,6 @@ static struct platform_device *rb532_dev
 	&rb532_wdt
 };
 
-static void __init parse_mac_addr(char *macstr)
-{
-	int i, h, l;
-
-	for (i = 0; i < 6; i++) {
-		if (i != 5 && *(macstr + 2) != ':')
-			return;
-
-		h = hex_to_bin(*macstr++);
-		if (h == -1)
-			return;
-
-		l = hex_to_bin(*macstr++);
-		if (l == -1)
-			return;
-
-		macstr++;
-		korina_dev0_data.mac[i] = (h << 4) + l;
-	}
-}
-
-
 /* NAND definitions */
 #define NAND_CHIP_DELAY 25
 
@@ -333,7 +312,10 @@ static int __init plat_setup_devices(voi
 static int __init setup_kmac(char *s)
 {
 	printk(KERN_INFO "korina mac = %s\n", s);
-	parse_mac_addr(s);
+	if (!mac_pton(s, korina_dev0_data.mac)) {
+		printk(KERN_ERR "Invalid mac\n");
+		return -EINVAL;
+	}
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/sgi-ip22/ip22-gio.c linux-libre-3.17-rc7-gnu/arch/mips/sgi-ip22/ip22-gio.c
--- linux-libre-3.16-gnu/arch/mips/sgi-ip22/ip22-gio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/sgi-ip22/ip22-gio.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,8 +27,14 @@ static struct {
 	{ .name = "SGI GR2/GR3", .id = 0x7f },
 };
 
+static void gio_bus_release(struct device *dev)
+{
+	kfree(dev);
+}
+
 static struct device gio_bus = {
 	.init_name = "gio",
+	.release = &gio_bus_release,
 };
 
 /**
@@ -413,8 +419,10 @@ int __init ip22_gio_init(void)
 	int ret;
 
 	ret = device_register(&gio_bus);
-	if (ret)
+	if (ret) {
+		put_device(&gio_bus);
 		return ret;
+	}
 
 	ret = bus_register(&gio_bus_type);
 	if (!ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/txx9/generic/7segled.c linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/7segled.c
--- linux-libre-3.16-gnu/arch/mips/txx9/generic/7segled.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/7segled.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,6 +83,11 @@ static struct bus_type tx_7segled_subsys
 	.dev_name	= "7segled",
 };
 
+static void tx_7segled_release(struct device *dev)
+{
+	kfree(dev);
+}
+
 static int __init tx_7segled_init_sysfs(void)
 {
 	int error, i;
@@ -103,11 +108,14 @@ static int __init tx_7segled_init_sysfs(
 		}
 		dev->id = i;
 		dev->bus = &tx_7segled_subsys;
+		dev->release = &tx_7segled_release;
 		error = device_register(dev);
-		if (!error) {
-			device_create_file(dev, &dev_attr_ascii);
-			device_create_file(dev, &dev_attr_raw);
+		if (error) {
+			put_device(dev);
+			return error;
 		}
+		device_create_file(dev, &dev_attr_ascii);
+		device_create_file(dev, &dev_attr_raw);
 	}
 	return error;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/txx9/generic/pci.c linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/pci.c
--- linux-libre-3.16-gnu/arch/mips/txx9/generic/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -268,7 +268,7 @@ static int txx9_i8259_irq_setup(int irq)
 	return err;
 }
 
-static void quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __init_refok quirk_slc90e66_bridge(struct pci_dev *dev)
 {
 	int irq;	/* PCI/ISA Bridge interrupt */
 	u8 reg_64;
@@ -331,7 +331,7 @@ static void quirk_slc90e66_ide(struct pc
 	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
 	 */
 	dat |= 0x01;
-	pci_write_config_byte(dev, regs[i], dat);
+	pci_write_config_byte(dev, 0x5c, dat);
 	pci_read_config_byte(dev, 0x5c, &dat);
 	printk(KERN_CONT " REG5C %02x", dat);
 	printk(KERN_CONT "\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mips/txx9/generic/setup.c linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/setup.c
--- linux-libre-3.16-gnu/arch/mips/txx9/generic/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mips/txx9/generic/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -937,6 +937,14 @@ static ssize_t txx9_sram_write(struct fi
 	return size;
 }
 
+static void txx9_device_release(struct device *dev)
+{
+	struct txx9_sramc_dev *tdev;
+
+	tdev = container_of(dev, struct txx9_sramc_dev, dev);
+	kfree(tdev);
+}
+
 void __init txx9_sramc_init(struct resource *r)
 {
 	struct txx9_sramc_dev *dev;
@@ -951,8 +959,11 @@ void __init txx9_sramc_init(struct resou
 		return;
 	size = resource_size(r);
 	dev->base = ioremap(r->start, size);
-	if (!dev->base)
-		goto exit;
+	if (!dev->base) {
+		kfree(dev);
+		return;
+	}
+	dev->dev.release = &txx9_device_release;
 	dev->dev.bus = &txx9_sramc_subsys;
 	sysfs_bin_attr_init(&dev->bindata_attr);
 	dev->bindata_attr.attr.name = "bindata";
@@ -963,17 +974,15 @@ void __init txx9_sramc_init(struct resou
 	dev->bindata_attr.private = dev;
 	err = device_register(&dev->dev);
 	if (err)
-		goto exit;
+		goto exit_put;
 	err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
 	if (err) {
 		device_unregister(&dev->dev);
-		goto exit;
-	}
-	return;
-exit:
-	if (dev) {
-		if (dev->base)
-			iounmap(dev->base);
+		iounmap(dev->base);
 		kfree(dev);
 	}
+	return;
+exit_put:
+	put_device(&dev->dev);
+	return;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mn10300/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/mn10300/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -6,4 +6,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mn10300/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/mn10300/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,9 @@ extern struct mn10300_cpuinfo cpu_data[]
 extern void identify_cpu(struct mn10300_cpuinfo *);
 extern void print_cpu_info(struct mn10300_cpuinfo *);
 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-3.16-gnu/arch/mn10300/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/mn10300/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mn10300/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* MN10300 Scatterlist definitions
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, 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 Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/mn10300/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/mn10300/kernel/signal.c
--- linux-libre-3.16-gnu/arch/mn10300/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/mn10300/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigco
 /*
  * determine which stack to use..
  */
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
 					struct pt_regs *regs,
 					size_t frame_size)
 {
-	unsigned long sp;
-
-	/* default to using normal stack */
-	sp = regs->sp;
-
-	/* this is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (sas_ss_flags(sp) == 0)
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
+	unsigned long sp = sigsp(regs->sp, ksig);
 
 	return (void __user *) ((sp - frame_size) & ~7UL);
 }
@@ -207,16 +198,16 @@ static inline void __user *get_sigframe(
 /*
  * set up a normal signal frame
  */
-static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
 		       struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	int rsig;
+	int rsig, sig = ksig->sig;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	rsig = sig;
 	if (sig < 32 &&
@@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k
 
 	if (__put_user(rsig, &frame->sig) < 0 ||
 	    __put_user(&frame->sc, &frame->psc) < 0)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (_NSIG_WORDS > 1) {
 		if (__copy_to_user(frame->extramask, &set->sig[1],
 				   sizeof(frame->extramask)))
-			goto give_sigsegv;
+			return -EFAULT;
 	}
 
 	/* set up to return from userspace.  If provided, use a stub already in
 	 * userspace */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
-			goto give_sigsegv;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+			return -EFAULT;
 	} else {
 		if (__put_user((void (*)(void))frame->retcode,
 			       &frame->pretcode))
-			goto give_sigsegv;
+			return -EFAULT;
 		/* this is mov $,d0; syscall 0 */
 		if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
 		    __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
 		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
 		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
 		    __put_user(0xe0, (char *)(frame->retcode + 4)))
-			goto give_sigsegv;
+			return -EFAULT;
 		flush_icache_range((unsigned long) frame->retcode,
 				   (unsigned long) frame->retcode + 5);
 	}
 
 	/* set up registers for signal handler */
 	regs->sp = (unsigned long) frame;
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 	regs->d0 = sig;
 	regs->d1 = (unsigned long) &frame->sc;
 
@@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /*
  * set up a realtime signal frame
  */
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int rsig;
+	int rsig, sig = ksig->sig;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	rsig = sig;
 	if (sig < 32 &&
@@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struc
 	if (__put_user(rsig, &frame->sig) ||
 	    __put_user(&frame->info, &frame->pinfo) ||
 	    __put_user(&frame->uc, &frame->puc) ||
-	    copy_siginfo_to_user(&frame->info, info))
-		goto give_sigsegv;
+	    copy_siginfo_to_user(&frame->info, &ksig->info))
+		return -EFAULT;
 
 	/* create the ucontext.  */
 	if (__put_user(0, &frame->uc.uc_flags) ||
@@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struc
 	    setup_sigcontext(&frame->uc.uc_mcontext,
 			     &frame->fpuctx, regs, set->sig[0]) ||
 	    __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* set up to return from userspace.  If provided, use a stub already in
 	 * userspace */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
-			goto give_sigsegv;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+			return -EFAULT;
+
 	} else {
 		if (__put_user((void(*)(void))frame->retcode,
 			       &frame->pretcode) ||
@@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struc
 		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
 		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
 		    __put_user(0xe0, (char *)(frame->retcode + 4)))
-			goto give_sigsegv;
+			return -EFAULT;
 
 		flush_icache_range((u_long) frame->retcode,
 				   (u_long) frame->retcode + 5);
@@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struc
 
 	/* Set up registers for signal handler */
 	regs->sp = (unsigned long) frame;
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 	regs->d0 = sig;
 	regs->d1 = (long) &frame->info;
 
@@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struc
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 static inline void stepback(struct pt_regs *regs)
@@ -360,9 +344,7 @@ static inline void stepback(struct pt_re
 /*
  * handle the actual delivery of a signal to userspace
  */
-static int handle_signal(int sig,
-			 siginfo_t *info, struct k_sigaction *ka,
-			 struct pt_regs *regs)
+static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -377,7 +359,7 @@ static int handle_signal(int sig,
 			break;
 
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->d0 = -EINTR;
 				break;
 			}
@@ -390,15 +372,12 @@ static int handle_signal(int sig,
 	}
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
-	if (ret)
-		return ret;
+		ret = setup_frame(ksig, oldset, regs);
 
-	signal_delivered(sig, info, ka, regs,
-			 test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 	return 0;
 }
 
@@ -407,15 +386,10 @@ static int handle_signal(int sig,
  */
 static void do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		if (handle_signal(signr, &info, &ka, regs) == 0) {
-		}
+	struct ksignal ksig;
 
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/openrisc/include/asm/irq.h linux-libre-3.17-rc7-gnu/arch/openrisc/include/asm/irq.h
--- linux-libre-3.16-gnu/arch/openrisc/include/asm/irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/openrisc/include/asm/irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,4 +24,7 @@
 
 #define NO_IRQ		(-1)
 
+void handle_IRQ(unsigned int, struct pt_regs *);
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
+
 #endif /* __ASM_OPENRISC_IRQ_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/openrisc/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/openrisc/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/openrisc/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/openrisc/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -101,6 +101,7 @@ 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-3.16-gnu/arch/openrisc/Kconfig linux-libre-3.17-rc7-gnu/arch/openrisc/Kconfig
--- linux-libre-3.16-gnu/arch/openrisc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/openrisc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@ config OPENRISC
 	select GENERIC_STRNLEN_USER
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
+	select OR1K_PIC
 
 config MMU
 	def_bool y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/openrisc/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/openrisc/kernel/irq.c
--- linux-libre-3.16-gnu/arch/openrisc/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/openrisc/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,11 +16,10 @@
 
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/of.h>
 #include <linux/ftrace.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/export.h>
-#include <linux/irqdomain.h>
 #include <linux/irqflags.h>
 
 /* read interrupt enabled status */
@@ -37,150 +36,31 @@ void arch_local_irq_restore(unsigned lon
 }
 EXPORT_SYMBOL(arch_local_irq_restore);
 
-
-/* OR1K PIC implementation */
-
-/* We're a couple of cycles faster than the generic implementations with
- * these 'fast' versions.
- */
-
-static void or1k_pic_mask(struct irq_data *data)
-{
-	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
-}
-
-static void or1k_pic_unmask(struct irq_data *data)
-{
-	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
-}
-
-static void or1k_pic_ack(struct irq_data *data)
-{
-	/* EDGE-triggered interrupts need to be ack'ed in order to clear
-	 * the latch.
-	 * LEVEL-triggered interrupts do not need to be ack'ed; however,
-	 * ack'ing the interrupt has no ill-effect and is quicker than
-	 * trying to figure out what type it is...
-	 */
-
-	/* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
-	 * interrupt, but the OR1200 does this backwards and requires a 0
-	 * to be written...
-	 */
-
-#ifdef CONFIG_OR1K_1200
-	/* There are two oddities with the OR1200 PIC implementation:
-	 * i)  LEVEL-triggered interrupts are latched and need to be cleared
-	 * ii) the interrupt latch is cleared by writing a 0 to the bit,
-	 *     as opposed to a 1 as mandated by the spec
-	 */
-
-	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
-#else
-	WARN(1, "Interrupt handling possibly broken\n");
-	mtspr(SPR_PICSR, (1UL << data->hwirq));
-#endif
-}
-
-static void or1k_pic_mask_ack(struct irq_data *data)
-{
-	/* Comments for pic_ack apply here, too */
-
-#ifdef CONFIG_OR1K_1200
-	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
-	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
-#else
-	WARN(1, "Interrupt handling possibly broken\n");
-	mtspr(SPR_PICMR, (1UL << data->hwirq));
-	mtspr(SPR_PICSR, (1UL << data->hwirq));
-#endif
-}
-
-#if 0
-static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
-{
-	/* There's nothing to do in the PIC configuration when changing
-	 * flow type.  Level and edge-triggered interrupts are both
-	 * supported, but it's PIC-implementation specific which type
-	 * is handled. */
-
-	return irq_setup_alt_chip(data, flow_type);
-}
-#endif
-
-static struct irq_chip or1k_dev = {
-	.name = "or1k-PIC",
-	.irq_unmask = or1k_pic_unmask,
-	.irq_mask = or1k_pic_mask,
-	.irq_ack = or1k_pic_ack,
-	.irq_mask_ack = or1k_pic_mask_ack,
-};
-
-static struct irq_domain *root_domain;
-
-static inline int pic_get_irq(int first)
-{
-	int hwirq;
-
-	hwirq = ffs(mfspr(SPR_PICSR) >> first);
-	if (!hwirq)
-		return NO_IRQ;
-	else
-		hwirq = hwirq + first -1;
-
-	return irq_find_mapping(root_domain, hwirq);
-}
-
-
-static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+void __init init_IRQ(void)
 {
-	irq_set_chip_and_handler_name(irq, &or1k_dev,
-				      handle_level_irq, "level");
-	irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE);
-
-	return 0;
+	irqchip_init();
 }
 
-static const struct irq_domain_ops or1k_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onecell,
-	.map = or1k_map,
-};
-
-/*
- * This sets up the IRQ domain for the PIC built in to the OpenRISC
- * 1000 CPU.  This is the "root" domain as these are the interrupts
- * that directly trigger an exception in the CPU.
- */
-static void __init or1k_irq_init(void)
-{
-	struct device_node *intc = NULL;
-
-	/* The interrupt controller device node is mandatory */
-	intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic");
-	BUG_ON(!intc);
-
-	/* Disable all interrupts until explicitly requested */
-	mtspr(SPR_PICMR, (0UL));
-
-	root_domain = irq_domain_add_linear(intc, 32,
-					    &or1k_irq_domain_ops, NULL);
-}
+static void (*handle_arch_irq)(struct pt_regs *);
 
-void __init init_IRQ(void)
+void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
 {
-	or1k_irq_init();
+	handle_arch_irq = handle_irq;
 }
 
-void __irq_entry do_IRQ(struct pt_regs *regs)
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
 {
-	int irq = -1;
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
 	irq_enter();
 
-	while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
-		generic_handle_irq(irq);
+	generic_handle_irq(irq);
 
 	irq_exit();
 	set_irq_regs(old_regs);
 }
+
+void __irq_entry do_IRQ(struct pt_regs *regs)
+{
+	handle_arch_irq(regs);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/openrisc/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/openrisc/kernel/signal.c
--- linux-libre-3.16-gnu/arch/openrisc/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/openrisc/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,30 +132,16 @@ static inline unsigned long align_sigfra
  * or the alternate stack.
  */
 
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
 					struct pt_regs *regs, size_t frame_size)
 {
 	unsigned long sp = regs->sp;
-	int onsigstack = on_sig_stack(sp);
 
 	/* redzone */
 	sp -= STACK_FRAME_OVERHEAD;
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
-		if (current->sas_ss_size)
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	}
-
+	sp = sigsp(sp, ksig);
 	sp = align_sigframe(sp - frame_size);
 
-	/*
-	 * If we are on the alternate signal stack and would overflow it, don't.
-	 * Return an always-bogus address instead so we will die with SIGSEGV.
-	 */
-	if (onsigstack && !likely(on_sig_stack(sp)))
-		return (void __user *)-1L;
-
 	return (void __user *)sp;
 }
 
@@ -173,7 +159,7 @@ static int setup_rt_frame(struct ksignal
 	unsigned long return_ip;
 	int err = 0;
 
-	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/configs/a500_defconfig linux-libre-3.17-rc7-gnu/arch/parisc/configs/a500_defconfig
--- linux-libre-3.16-gnu/arch/parisc/configs/a500_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/configs/a500_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@ CONFIG_PD6729=m
 CONFIG_I82092=m
 # CONFIG_SUPERIO is not set
 # CONFIG_CHASSIS_LCD_LED is not set
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/configs/c8000_defconfig linux-libre-3.17-rc7-gnu/arch/parisc/configs/c8000_defconfig
--- linux-libre-3.16-gnu/arch/parisc/configs/c8000_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/configs/c8000_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@ CONFIG_PCI_LBA=y
 # CONFIG_PDC_CHASSIS_WARN is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/configs/generic-64bit_defconfig linux-libre-3.17-rc7-gnu/arch/parisc/configs/generic-64bit_defconfig
--- linux-libre-3.16-gnu/arch/parisc/configs/generic-64bit_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/configs/generic-64bit_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -241,7 +241,6 @@ CONFIG_UIO_AEC=m
 CONFIG_UIO_SERCOS3=m
 CONFIG_UIO_PCI_GENERIC=m
 CONFIG_STAGING=y
-# CONFIG_NET_VENDOR_SILICOM is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/hpux/sys_hpux.c linux-libre-3.17-rc7-gnu/arch/parisc/hpux/sys_hpux.c
--- linux-libre-3.16-gnu/arch/parisc/hpux/sys_hpux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/hpux/sys_hpux.c	2014-09-28 17:29:07.000000000 -0400
@@ -456,7 +456,7 @@ int hpux_sysfs(int opcode, unsigned long
 		}
 
 		/* String could be altered by userspace after strlen_user() */
-		fsname[len] = '\0';
+		fsname[len - 1] = '\0';
 
 		printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname);
 		if ( !strcmp(fsname, "hfs") ) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/parisc/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -338,6 +338,7 @@ 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()
 
 /* Used as a macro to identify the combined VIPT/PIPT cached
  * CPUs which require a guarantee of coherency (no inequivalent
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/include/asm/seccomp.h linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/seccomp.h
--- linux-libre-3.16-gnu/arch/parisc/include/asm/seccomp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/seccomp.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef _ASM_PARISC_SECCOMP_H
+#define _ASM_PARISC_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_rt_sigreturn
+
+#endif	/* _ASM_PARISC_SECCOMP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/include/asm/thread_info.h linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/thread_info.h
--- linux-libre-3.16-gnu/arch/parisc/include/asm/thread_info.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/include/asm/thread_info.h	2014-09-28 17:29:07.000000000 -0400
@@ -60,6 +60,7 @@ struct thread_info {
 #define TIF_NOTIFY_RESUME	8	/* callback before returning to user */
 #define TIF_SINGLESTEP		9	/* single stepping? */
 #define TIF_BLOCKSTEP		10	/* branch stepping? */
+#define TIF_SECCOMP		11	/* secure computing */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -70,11 +71,13 @@ struct thread_info {
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_BLOCKSTEP		(1 << TIF_BLOCKSTEP)
+#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP |	\
-				 _TIF_BLOCKSTEP | _TIF_SYSCALL_AUDIT)
+				 _TIF_BLOCKSTEP | _TIF_SYSCALL_AUDIT | \
+				 _TIF_SECCOMP)
 
 #ifdef CONFIG_64BIT
 # ifdef CONFIG_COMPAT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/parisc/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/parisc/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -830,8 +830,11 @@
 #define __NR_sched_getattr	(__NR_Linux + 335)
 #define __NR_utimes		(__NR_Linux + 336)
 #define __NR_renameat2		(__NR_Linux + 337)
+#define __NR_seccomp		(__NR_Linux + 338)
+#define __NR_getrandom		(__NR_Linux + 339)
+#define __NR_memfd_create	(__NR_Linux + 340)
 
-#define __NR_Linux_syscalls	(__NR_renameat2 + 1)
+#define __NR_Linux_syscalls	(__NR_memfd_create + 1)
 
 
 #define __IGNORE_select		/* newselect */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/Kconfig linux-libre-3.17-rc7-gnu/arch/parisc/Kconfig
--- linux-libre-3.16-gnu/arch/parisc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -6,7 +6,6 @@ config PARISC
 	select HAVE_OPROFILE
 	select HAVE_FUNCTION_TRACER if 64BIT
 	select HAVE_FUNCTION_GRAPH_TRACER if 64BIT
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST if 64BIT
 	select ARCH_WANT_FRAME_POINTERS
 	select RTC_CLASS
 	select RTC_DRV_GENERIC
@@ -322,6 +321,22 @@ source "fs/Kconfig"
 
 source "arch/parisc/Kconfig.debug"
 
+config SECCOMP
+	def_bool y
+	prompt "Enable seccomp to safely compute untrusted bytecode"
+	---help---
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/parisc/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/parisc/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,6 +112,9 @@ void prepare_ftrace_return(unsigned long
 	unsigned long long calltime;
 	struct ftrace_graph_ent trace;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
@@ -152,9 +155,6 @@ void ftrace_function_trampoline(unsigned
 {
 	extern ftrace_func_t ftrace_trace_function;
 
-	if (function_trace_stop)
-		return;
-
 	if (ftrace_trace_function != ftrace_stub) {
 		ftrace_trace_function(parent, self_addr);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/kernel/ptrace.c linux-libre-3.17-rc7-gnu/arch/parisc/kernel/ptrace.c
--- linux-libre-3.16-gnu/arch/parisc/kernel/ptrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/kernel/ptrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/user.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/seccomp.h>
 #include <linux/compat.h>
 #include <linux/signal.h>
 #include <linux/audit.h>
@@ -270,6 +271,9 @@ long do_syscall_trace_enter(struct pt_re
 {
 	long ret = 0;
 
+	/* Do the secure computing check first. */
+	secure_computing_strict(regs->gr[20]);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    tracehook_report_syscall_entry(regs))
 		ret = -1L;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/parisc/kernel/signal.c
--- linux-libre-3.16-gnu/arch/parisc/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -227,8 +227,8 @@ setup_sigcontext(struct sigcontext __use
 }
 
 static long
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs, int in_syscall)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
+	       int in_syscall)
 {
 	struct rt_sigframe __user *frame;
 	unsigned long rp, usp;
@@ -241,10 +241,10 @@ setup_rt_frame(int sig, struct k_sigacti
 	
 	usp = (regs->gr[30] & ~(0x01UL));
 	/*FIXME: frame_size parameter is unused, remove it. */
-	frame = get_sigframe(ka, usp, sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
 
 	DBG(1,"SETUP_RT_FRAME: START\n");
-	DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
+	DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
 
 	
 #ifdef CONFIG_64BIT
@@ -253,7 +253,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	
 	if (is_compat_task()) {
 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
-		err |= copy_siginfo_to_user32(&compat_frame->info, info);
+		err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
 		err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
 		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
 		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
@@ -265,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigacti
 #endif
 	{	
 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
-		err |= copy_siginfo_to_user(&frame->info, info);
+		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 		err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
 		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
 		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
@@ -275,7 +275,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	}
 	
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace. The first words of tramp are used to
@@ -312,9 +312,9 @@ setup_rt_frame(int sig, struct k_sigacti
 	rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
-	haddr = A(ka->sa.sa_handler);
+	haddr = A(ksig->ka.sa.sa_handler);
 	/* The sa_handler may be a pointer to a function descriptor */
 #ifdef CONFIG_64BIT
 	if (is_compat_task()) {
@@ -326,7 +326,7 @@ setup_rt_frame(int sig, struct k_sigacti
 			err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
 
 			if (err)
-				goto give_sigsegv;
+				return -EFAULT;
 
 			haddr = fdesc.addr;
 			regs->gr[19] = fdesc.gp;
@@ -339,7 +339,7 @@ setup_rt_frame(int sig, struct k_sigacti
 		err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
 		
 		if (err)
-			goto give_sigsegv;
+			return -EFAULT;
 		
 		haddr = fdesc.addr;
 		regs->gr[19] = fdesc.gp;
@@ -386,7 +386,7 @@ setup_rt_frame(int sig, struct k_sigacti
 	}
 
 	regs->gr[2]  = rp;                /* userland return pointer */
-	regs->gr[26] = sig;               /* signal number */
+	regs->gr[26] = ksig->sig;               /* signal number */
 	
 #ifdef CONFIG_64BIT
 	if (is_compat_task()) {
@@ -410,11 +410,6 @@ setup_rt_frame(int sig, struct k_sigacti
 	       current->comm, current->pid, frame, regs->gr[30],
 	       regs->iaoq[0], regs->iaoq[1], rp);
 
-	return 1;
-
-give_sigsegv:
-	DBG(1,"setup_rt_frame: sending SIGSEGV\n");
-	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -423,20 +418,19 @@ give_sigsegv:
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-		struct pt_regs *regs, int in_syscall)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
 {
+	int ret;
 	sigset_t *oldset = sigmask_to_save();
+
 	DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
-	       sig, ka, info, oldset, regs);
+	       ksig->sig, ksig->ka, ksig->info, oldset, regs);
 	
 	/* Set up the stack frame */
-	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
-		return;
+	ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
 
-	signal_delivered(sig, info, ka, regs, 
-		test_thread_flag(TIF_SINGLESTEP) ||
-		test_thread_flag(TIF_BLOCKSTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
+			  test_thread_flag(TIF_BLOCKSTEP));
 
 	DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
 		regs->gr[28]);
@@ -544,22 +538,18 @@ insert_restart_trampoline(struct pt_regs
 asmlinkage void
 do_signal(struct pt_regs *regs, long in_syscall)
 {
-	siginfo_t info;
-	struct k_sigaction ka;
-	int signr;
+	struct ksignal ksig;
 
 	DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
 	       regs, regs->sr[7], in_syscall);
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
-	
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
+		DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
 		/* Restart a system call if necessary. */
 		if (in_syscall)
-			syscall_restart(regs, &ka);
+			syscall_restart(regs, &ksig.ka);
 
-		handle_signal(signr, &info, &ka, regs, in_syscall);
+		handle_signal(&ksig, regs, in_syscall);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/kernel/syscall.S linux-libre-3.17-rc7-gnu/arch/parisc/kernel/syscall.S
--- linux-libre-3.16-gnu/arch/parisc/kernel/syscall.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/kernel/syscall.S	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@ ENTRY(linux_gateway_page)
 	/* ADDRESS 0xb0 to 0xb8, lws uses two insns for entry */
 	/* Light-weight-syscall entry must always be located at 0xb0 */
 	/* WARNING: Keep this number updated with table size changes */
-#define __NR_lws_entries (2)
+#define __NR_lws_entries (3)
 
 lws_entry:
 	gate	lws_start, %r0		/* increase privilege */
@@ -502,7 +502,7 @@ lws_exit:
 
 	
 	/***************************************************
-		Implementing CAS as an atomic operation:
+		Implementing 32bit CAS as an atomic operation:
 
 		%r26 - Address to examine
 		%r25 - Old value to check (old)
@@ -659,6 +659,230 @@ cas_action:
 	ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page)
 
 
+	/***************************************************
+		New CAS implementation which uses pointers and variable size
+		information. The value pointed by old and new MUST NOT change
+		while performing CAS. The lock only protect the value at %r26.
+
+		%r26 - Address to examine
+		%r25 - Pointer to the value to check (old)
+		%r24 - Pointer to the value to set (new)
+		%r23 - Size of the variable (0/1/2/3 for 8/16/32/64 bit)
+		%r28 - Return non-zero on failure
+		%r21 - Kernel error code
+
+		%r21 has the following meanings:
+
+		EAGAIN - CAS is busy, ldcw failed, try again.
+		EFAULT - Read or write failed.
+
+		Scratch: r20, r22, r28, r29, r1, fr4 (32bit for 64bit CAS only)
+
+	****************************************************/
+
+	/* ELF32 Process entry path */
+lws_compare_and_swap_2:
+#ifdef CONFIG_64BIT
+	/* Clip the input registers */
+	depdi	0, 31, 32, %r26
+	depdi	0, 31, 32, %r25
+	depdi	0, 31, 32, %r24
+	depdi	0, 31, 32, %r23
+#endif
+
+	/* Check the validity of the size pointer */
+	subi,>>= 4, %r23, %r0
+	b,n	lws_exit_nosys
+
+	/* Jump to the functions which will load the old and new values into
+	   registers depending on the their size */
+	shlw	%r23, 2, %r29
+	blr	%r29, %r0
+	nop
+
+	/* 8bit load */
+4:	ldb	0(%sr3,%r25), %r25
+	b	cas2_lock_start
+5:	ldb	0(%sr3,%r24), %r24
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* 16bit load */
+6:	ldh	0(%sr3,%r25), %r25
+	b	cas2_lock_start
+7:	ldh	0(%sr3,%r24), %r24
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* 32bit load */
+8:	ldw	0(%sr3,%r25), %r25
+	b	cas2_lock_start
+9:	ldw	0(%sr3,%r24), %r24
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* 64bit load */
+#ifdef CONFIG_64BIT
+10:	ldd	0(%sr3,%r25), %r25
+11:	ldd	0(%sr3,%r24), %r24
+#else
+	/* Load new value into r22/r23 - high/low */
+10:	ldw	0(%sr3,%r25), %r22
+11:	ldw	4(%sr3,%r25), %r23
+	/* Load new value into fr4 for atomic store later */
+12:	flddx	0(%sr3,%r24), %fr4
+#endif
+
+cas2_lock_start:
+	/* Load start of lock table */
+	ldil	L%lws_lock_start, %r20
+	ldo	R%lws_lock_start(%r20), %r28
+
+	/* Extract four bits from r26 and hash lock (Bits 4-7) */
+	extru  %r26, 27, 4, %r20
+
+	/* Find lock to use, the hash is either one of 0 to
+	   15, multiplied by 16 (keep it 16-byte aligned)
+	   and add to the lock table offset. */
+	shlw	%r20, 4, %r20
+	add	%r20, %r28, %r20
+
+	rsm	PSW_SM_I, %r0			/* Disable interrupts */
+	/* COW breaks can cause contention on UP systems */
+	LDCW	0(%sr2,%r20), %r28		/* Try to acquire the lock */
+	cmpb,<>,n	%r0, %r28, cas2_action	/* Did we get it? */
+cas2_wouldblock:
+	ldo	2(%r0), %r28			/* 2nd case */
+	ssm	PSW_SM_I, %r0
+	b	lws_exit			/* Contended... */
+	ldo	-EAGAIN(%r0), %r21		/* Spin in userspace */
+
+	/*
+		prev = *addr;
+		if ( prev == old )
+		  *addr = new;
+		return prev;
+	*/
+
+	/* NOTES:
+		This all works becuse intr_do_signal
+		and schedule both check the return iasq
+		and see that we are on the kernel page
+		so this process is never scheduled off
+		or is ever sent any signal of any sort,
+		thus it is wholly atomic from usrspaces
+		perspective
+	*/
+cas2_action:
+	/* Jump to the correct function */
+	blr	%r29, %r0
+	/* Set %r28 as non-zero for now */
+	ldo	1(%r0),%r28
+
+	/* 8bit CAS */
+13:	ldb,ma	0(%sr3,%r26), %r29
+	sub,=	%r29, %r25, %r0
+	b,n	cas2_end
+14:	stb,ma	%r24, 0(%sr3,%r26)
+	b	cas2_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 16bit CAS */
+15:	ldh,ma	0(%sr3,%r26), %r29
+	sub,=	%r29, %r25, %r0
+	b,n	cas2_end
+16:	sth,ma	%r24, 0(%sr3,%r26)
+	b	cas2_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 32bit CAS */
+17:	ldw,ma	0(%sr3,%r26), %r29
+	sub,=	%r29, %r25, %r0
+	b,n	cas2_end
+18:	stw,ma	%r24, 0(%sr3,%r26)
+	b	cas2_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 64bit CAS */
+#ifdef CONFIG_64BIT
+19:	ldd,ma	0(%sr3,%r26), %r29
+	sub,=	%r29, %r25, %r0
+	b,n	cas2_end
+20:	std,ma	%r24, 0(%sr3,%r26)
+	copy	%r0, %r28
+#else
+	/* Compare first word */
+19:	ldw,ma	0(%sr3,%r26), %r29
+	sub,=	%r29, %r22, %r0
+	b,n	cas2_end
+	/* Compare second word */
+20:	ldw,ma	4(%sr3,%r26), %r29
+	sub,=	%r29, %r23, %r0
+	b,n	cas2_end
+	/* Perform the store */
+21:	fstdx	%fr4, 0(%sr3,%r26)
+	copy	%r0, %r28
+#endif
+
+cas2_end:
+	/* Free lock */
+	stw,ma	%r20, 0(%sr2,%r20)
+	/* Enable interrupts */
+	ssm	PSW_SM_I, %r0
+	/* Return to userspace, set no error */
+	b	lws_exit
+	copy	%r0, %r21
+
+22:
+	/* Error occurred on load or store */
+	/* Free lock */
+	stw	%r20, 0(%sr2,%r20)
+	ssm	PSW_SM_I, %r0
+	ldo	1(%r0),%r28
+	b	lws_exit
+	ldo	-EFAULT(%r0),%r21	/* set errno */
+	nop
+	nop
+	nop
+
+	/* Exception table entries, for the load and store, return EFAULT.
+	   Each of the entries must be relocated. */
+	ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(17b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(18b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(19b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(20b-linux_gateway_page, 22b-linux_gateway_page)
+#ifndef CONFIG_64BIT
+	ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gateway_page, 22b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(21b-linux_gateway_page, 22b-linux_gateway_page)
+#endif
+
 	/* Make sure nothing else is placed on this page */
 	.align PAGE_SIZE
 END(linux_gateway_page)
@@ -675,8 +899,9 @@ ENTRY(end_linux_gateway_page)
 	/* Light-weight-syscall table */
 	/* Start of lws table. */
 ENTRY(lws_table)
-	LWS_ENTRY(compare_and_swap32)	/* 0 - ELF32 Atomic compare and swap */
-	LWS_ENTRY(compare_and_swap64)	/* 1 - ELF64 Atomic compare and swap */
+	LWS_ENTRY(compare_and_swap32)		/* 0 - ELF32 Atomic 32bit CAS */
+	LWS_ENTRY(compare_and_swap64)		/* 1 - ELF64 Atomic 32bit CAS */
+	LWS_ENTRY(compare_and_swap_2)		/* 2 - ELF32 Atomic 64bit CAS */
 END(lws_table)
 	/* End of lws table */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/kernel/syscall_table.S linux-libre-3.17-rc7-gnu/arch/parisc/kernel/syscall_table.S
--- linux-libre-3.16-gnu/arch/parisc/kernel/syscall_table.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/kernel/syscall_table.S	2014-09-28 17:29:07.000000000 -0400
@@ -433,6 +433,9 @@
 	ENTRY_SAME(sched_getattr)	/* 335 */
 	ENTRY_COMP(utimes)
 	ENTRY_SAME(renameat2)
+	ENTRY_SAME(seccomp)
+	ENTRY_SAME(getrandom)
+	ENTRY_SAME(memfd_create)	/* 340 */
 
 	/* Nothing yet */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/parisc/Makefile linux-libre-3.17-rc7-gnu/arch/parisc/Makefile
--- linux-libre-3.16-gnu/arch/parisc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/parisc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,12 @@ cflags-y	:= -pipe
 
 # These flags should be implied by an hppa-linux configuration, but they
 # are not in gcc 3.2.
-cflags-y	+= -mno-space-regs -mfast-indirect-calls
+cflags-y	+= -mno-space-regs
+
+# -mfast-indirect-calls is only relevant for 32-bit kernels.
+ifndef CONFIG_64BIT
+cflags-y	+= -mfast-indirect-calls
+endif
 
 # Currently we save and restore fpregs on all kernel entry/interruption paths.
 # If that gets optimized, we might need to disable the use of fpregs in the
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -359,6 +359,7 @@
 			compatible = "fsl,qoriq-core-mux-1.0";
 			clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>;
 			clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2";
+			clock-output-names = "cmux2";
 		};
 
 		mux3: mux3@60 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-	compatible = "fsl,sec-v6.0";
+	compatible = "fsl,sec-v6.0", "fsl,sec-v5.0",
+		     "fsl,sec-v4.0";
 	fsl,sec-era = <6>;
 	#address-cells = <1>;
 	#size-cells = <1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * T2080 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2013 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/ "t2081si-post.dtsi"
+
+&soc {
+/include/ "qoriq-sata2-0.dtsi"
+	sata@220000 {
+		fsl,iommu-parent = <&pamu1>;
+		fsl,liodn-reg = <&guts 0x550>; /* SATA1LIODNR */
+	};
+
+/include/ "qoriq-sata2-1.dtsi"
+	sata@221000 {
+		fsl,iommu-parent = <&pamu1>;
+		fsl,liodn-reg = <&guts 0x554>; /* SATA2LIODNR */
+	};
+};
+
+&rio {
+	compatible = "fsl,srio";
+	interrupts = <16 2 1 11>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+
+	port1 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		cell-index = <1>;
+	};
+
+	port2 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		cell-index = <2>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,435 @@
+/*
+ * T2081 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2013 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.
+ */
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,ifc", "simple-bus";
+	interrupts = <25 2 0 0>;
+};
+
+/* controller at 0x240000 */
+&pci0 {
+	compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <20 2 0 0>;
+	fsl,iommu-parent = <&pamu0>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <20 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 40 1 0 0
+			0000 0 0 2 &mpic 1 1 0 0
+			0000 0 0 3 &mpic 2 1 0 0
+			0000 0 0 4 &mpic 3 1 0 0
+		>;
+	};
+};
+
+/* controller at 0x250000 */
+&pci1 {
+	compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0 0xff>;
+	interrupts = <21 2 0 0>;
+	fsl,iommu-parent = <&pamu0>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <21 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 41 1 0 0
+			0000 0 0 2 &mpic 5 1 0 0
+			0000 0 0 3 &mpic 6 1 0 0
+			0000 0 0 4 &mpic 7 1 0 0
+		>;
+	};
+};
+
+/* controller at 0x260000 */
+&pci2 {
+	compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <22 2 0 0>;
+	fsl,iommu-parent = <&pamu0>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <22 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 42 1 0 0
+			0000 0 0 2 &mpic 9 1 0 0
+			0000 0 0 3 &mpic 10 1 0 0
+			0000 0 0 4 &mpic 11 1 0 0
+		>;
+	};
+};
+
+/* controller at 0x270000 */
+&pci3 {
+	compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <23 2 0 0>;
+	fsl,iommu-parent = <&pamu0>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <23 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 43 1 0 0
+			0000 0 0 2 &mpic 0 1 0 0
+			0000 0 0 3 &mpic 4 1 0 0
+			0000 0 0 4 &mpic 8 1 0 0
+		>;
+	};
+};
+
+&dcsr {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "fsl,dcsr", "simple-bus";
+
+	dcsr-epu@0 {
+		compatible = "fsl,t2080-dcsr-epu", "fsl,dcsr-epu";
+		interrupts = <52 2 0 0
+			      84 2 0 0
+			      85 2 0 0
+			      94 2 0 0
+			      95 2 0 0>;
+		reg = <0x0 0x1000>;
+	};
+	dcsr-npc {
+		compatible = "fsl,t2080-dcsr-cnpc", "fsl,dcsr-cnpc";
+		reg = <0x1000 0x1000 0x1002000 0x10000>;
+	};
+	dcsr-nxc@2000 {
+		compatible = "fsl,dcsr-nxc";
+		reg = <0x2000 0x1000>;
+	};
+	dcsr-corenet {
+		compatible = "fsl,dcsr-corenet";
+		reg = <0x8000 0x1000 0x1A000 0x1000>;
+	};
+	dcsr-ocn@11000 {
+		compatible = "fsl,t2080-dcsr-ocn", "fsl,dcsr-ocn";
+		reg = <0x11000 0x1000>;
+	};
+	dcsr-ddr@12000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr1>;
+		reg = <0x12000 0x1000>;
+	};
+	dcsr-nal@18000 {
+		compatible = "fsl,t2080-dcsr-nal", "fsl,dcsr-nal";
+		reg = <0x18000 0x1000>;
+	};
+	dcsr-rcpm@22000 {
+		compatible = "fsl,t2080-dcsr-rcpm", "fsl,dcsr-rcpm";
+		reg = <0x22000 0x1000>;
+	};
+	dcsr-snpc@30000 {
+		compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x30000 0x1000 0x1022000 0x10000>;
+	};
+	dcsr-snpc@31000 {
+		compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x31000 0x1000 0x1042000 0x10000>;
+	};
+	dcsr-snpc@32000 {
+		compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x32000 0x1000 0x1062000 0x10000>;
+	};
+	dcsr-cpu-sb-proxy@100000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu0>;
+		reg = <0x100000 0x1000 0x101000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@108000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu1>;
+		reg = <0x108000 0x1000 0x109000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@110000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu2>;
+		reg = <0x110000 0x1000 0x111000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@118000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu3>;
+		reg = <0x118000 0x1000 0x119000 0x1000>;
+	};
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "simple-bus";
+
+	soc-sram-error {
+		compatible = "fsl,soc-sram-error";
+		interrupts = <16 2 1 29>;
+	};
+
+	corenet-law@0 {
+		compatible = "fsl,corenet-law";
+		reg = <0x0 0x1000>;
+		fsl,num-laws = <32>;
+	};
+
+	ddr1: memory-controller@8000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
+
+	cpc: l3-cache-controller@10000 {
+		compatible = "fsl,t2080-l3-cache-controller", "cache";
+		reg = <0x10000 0x1000
+		       0x11000 0x1000
+		       0x12000 0x1000>;
+		interrupts = <16 2 1 27
+			      16 2 1 26
+			      16 2 1 25>;
+	};
+
+	corenet-cf@18000 {
+		compatible = "fsl,corenet2-cf", "fsl,corenet-cf";
+		reg = <0x18000 0x1000>;
+		interrupts = <16 2 1 31>;
+		fsl,ccf-num-csdids = <32>;
+		fsl,ccf-num-snoopids = <32>;
+	};
+
+	iommu@20000 {
+		compatible = "fsl,pamu-v1.0", "fsl,pamu";
+		reg = <0x20000 0x3000>;
+		fsl,portid-mapping = <0x8000>;
+		ranges = <0 0x20000 0x3000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupts = <
+			24 2 0 0
+			16 2 1 30>;
+
+		pamu0: pamu@0 {
+			reg = <0 0x1000>;
+			fsl,primary-cache-geometry = <32 1>;
+			fsl,secondary-cache-geometry = <128 2>;
+		};
+
+		pamu1: pamu@1000 {
+			reg = <0x1000 0x1000>;
+			fsl,primary-cache-geometry = <32 1>;
+			fsl,secondary-cache-geometry = <128 2>;
+		};
+
+		pamu2: pamu@2000 {
+			reg = <0x2000 0x1000>;
+			fsl,primary-cache-geometry = <32 1>;
+			fsl,secondary-cache-geometry = <128 2>;
+		};
+	};
+
+/include/ "qoriq-mpic4.3.dtsi"
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,t2080-device-config", "fsl,qoriq-device-config-2.0";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		fsl,liodn-bits = <12>;
+	};
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0";
+		ranges = <0x0 0xe1000 0x1000>;
+		reg = <0xe1000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sysclk: sysclk {
+			#clock-cells = <0>;
+			compatible = "fsl,qoriq-sysclk-2.0";
+			clock-output-names = "sysclk", "fixed-clock";
+		};
+
+		pll0: pll0@800 {
+			#clock-cells = <1>;
+			reg = <0x800 4>;
+			compatible = "fsl,qoriq-core-pll-2.0";
+			clocks = <&sysclk>;
+			clock-output-names = "pll0", "pll0-div2", "pll0-div4";
+		};
+
+		pll1: pll1@820 {
+			#clock-cells = <1>;
+			reg = <0x820 4>;
+			compatible = "fsl,qoriq-core-pll-2.0";
+			clocks = <&sysclk>;
+			clock-output-names = "pll1", "pll1-div2", "pll1-div4";
+		};
+
+		mux0: mux0@0 {
+			#clock-cells = <0>;
+			reg = <0x0 4>;
+			compatible = "fsl,qoriq-core-mux-2.0";
+			clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>,
+				 <&pll1 0>, <&pll1 1>, <&pll1 2>;
+			clock-names = "pll0", "pll0-div2", "pll1-div4",
+				"pll1", "pll1-div2", "pll1-div4";
+			clock-output-names = "cmux0";
+		};
+
+		mux1: mux1@20 {
+			#clock-cells = <0>;
+			reg = <0x20 4>;
+			compatible = "fsl,qoriq-core-mux-2.0";
+			clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>,
+				 <&pll1 0>, <&pll1 1>, <&pll1 2>;
+			clock-names = "pll0", "pll0-div2", "pll1-div4",
+				"pll1", "pll1-div2", "pll1-div4";
+			clock-output-names = "cmux1";
+		};
+	};
+
+	rcpm: global-utilities@e2000 {
+		compatible = "fsl,t2080-rcpm", "fsl,qoriq-rcpm-2.0";
+		reg = <0xe2000 0x1000>;
+	};
+
+	sfp: sfp@e8000 {
+		compatible = "fsl,t2080-sfp";
+		reg = <0xe8000 0x1000>;
+	};
+
+	serdes: serdes@ea000 {
+		compatible = "fsl,t2080-serdes";
+		reg = <0xea000 0x4000>;
+	};
+
+/include/ "elo3-dma-0.dtsi"
+	dma@100300 {
+		fsl,iommu-parent = <&pamu0>;
+		fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */
+	};
+/include/ "elo3-dma-1.dtsi"
+	dma@101300 {
+		fsl,iommu-parent = <&pamu0>;
+		fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */
+	};
+/include/ "elo3-dma-2.dtsi"
+	dma@102300 {
+		fsl,iommu-parent = <&pamu0>;
+		fsl,liodn-reg = <&guts 0x588>; /* DMA3LIODNR */
+	};
+
+/include/ "qoriq-espi-0.dtsi"
+	spi@110000 {
+		fsl,espi-num-chipselects = <4>;
+	};
+
+/include/ "qoriq-esdhc-0.dtsi"
+	sdhc@114000 {
+		compatible = "fsl,t2080-esdhc", "fsl,esdhc";
+		fsl,iommu-parent = <&pamu1>;
+		fsl,liodn-reg = <&guts 0x530>; /* SDMMCLIODNR */
+		sdhci,auto-cmd12;
+	};
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-gpio-1.dtsi"
+/include/ "qoriq-gpio-2.dtsi"
+/include/ "qoriq-gpio-3.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+	usb0: usb@210000 {
+		compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph";
+		fsl,iommu-parent = <&pamu1>;
+		fsl,liodn-reg = <&guts 0x520>; /* USB1LIODNR */
+		phy_type = "utmi";
+		port0;
+	};
+/include/ "qoriq-usb2-dr-0.dtsi"
+	usb1: usb@211000 {
+		compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr";
+		fsl,iommu-parent = <&pamu1>;
+		fsl,liodn-reg = <&guts 0x524>; /* USB1LIODNR */
+		dr_mode = "host";
+		phy_type = "utmi";
+	};
+/include/ "qoriq-sec5.2-0.dtsi"
+
+	L2_1: l2-cache-controller@c20000 {
+		/* Cluster 0 L2 cache */
+		compatible = "fsl,t2080-l2-cache-controller";
+		reg = <0xc20000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * T2080/T2081 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+
+		crypto = &crypto;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		dma2 = &dma2;
+		sdhc = &sdhc;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e6500@0 {
+			device_type = "cpu";
+			reg = <0 1>;
+			clocks = <&mux0>;
+			next-level-cache = <&L2_1>;
+			fsl,portid-mapping = <0x80000000>;
+		};
+		cpu1: PowerPC,e6500@2 {
+			device_type = "cpu";
+			reg = <2 3>;
+			clocks = <&mux0>;
+			next-level-cache = <&L2_1>;
+			fsl,portid-mapping = <0x80000000>;
+		};
+		cpu2: PowerPC,e6500@4 {
+			device_type = "cpu";
+			reg = <4 5>;
+			clocks = <&mux0>;
+			next-level-cache = <&L2_1>;
+			fsl,portid-mapping = <0x80000000>;
+		};
+		cpu3: PowerPC,e6500@6 {
+			device_type = "cpu";
+			reg = <6 7>;
+			clocks = <&mux0>;
+			next-level-cache = <&L2_1>;
+			fsl,portid-mapping = <0x80000000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -476,6 +476,7 @@
 
 /include/ "elo3-dma-0.dtsi"
 /include/ "elo3-dma-1.dtsi"
+/include/ "elo3-dma-2.dtsi"
 
 /include/ "qoriq-espi-0.dtsi"
 	spi@110000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -57,6 +57,7 @@
 		pci3 = &pci3;
 		dma0 = &dma0;
 		dma1 = &dma1;
+		dma2 = &dma2;
 		sdhc = &sdhc;
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/mpc5121.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/mpc5121.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/mpc5121.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/mpc5121.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -498,6 +498,7 @@
 			compatible = "fsl,mpc5121-dma";
 			reg = <0x14000 0x1800>;
 			interrupts = <65 0x8>;
+			#dma-cells = <1>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2080qds.dts linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2080qds.dts
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2080qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2080qds.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * T2080QDS Device Tree Source
+ *
+ * Copyright 2013 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/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xqds.dtsi"
+
+/ {
+	model = "fsl,T2080QDS";
+	compatible = "fsl,T2080QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	rio: rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+};
+
+/include/ "fsl/t2080si-post.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2080rdb.dts linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2080rdb.dts
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2080rdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2080rdb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * T2080PCIe-RDB Board Device Tree Source
+ *
+ * Copyright 2014 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/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xrdb.dtsi"
+
+/ {
+	model = "fsl,T2080RDB";
+	compatible = "fsl,T2080RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	rio: rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+};
+
+/include/ "fsl/t2080si-post.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2081qds.dts linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2081qds.dts
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t2081qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t2081qds.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * T2081QDS Device Tree Source
+ *
+ * Copyright 2013 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/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xqds.dtsi"
+
+/ {
+	model = "fsl,T2081QDS";
+	compatible = "fsl,T2081QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+};
+
+/include/ "fsl/t2081si-post.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t208xqds.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t208xqds.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t208xqds.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t208xqds.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,239 @@
+/*
+ * T2080/T2081 QDS Device Tree Source
+ *
+ * Copyright 2013 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.
+ */
+
+/ {
+	model = "fsl,T2080QDS";
+	compatible = "fsl,T2080QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x2 0x0 0x10000>;
+		};
+
+		boardctrl: board-control@3,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,fpga-qixis";
+			reg = <3 0 0x300>;
+			ranges = <0 3 0 0x300>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "micron,n25q128a11"; /* 16MB */
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+			};
+
+			flash@1 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "sst,sst25wf040";
+				reg = <1>;
+				spi-max-frequency = <35000000>;
+			};
+
+			flash@2 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "eon,en25s64";
+				reg = <2>;
+				spi-max-frequency = <35000000>;
+			};
+		};
+
+		i2c@118000 {
+			pca9547@77 {
+				compatible = "nxp,pca9547";
+				reg = <0x77>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				i2c@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x0>;
+
+					eeprom@50 {
+						compatible = "at24,24c512";
+						reg = <0x50>;
+					};
+
+					eeprom@51 {
+						compatible = "at24,24c02";
+						reg = <0x51>;
+					};
+
+					eeprom@57 {
+						compatible = "at24,24c02";
+						reg = <0x57>;
+					};
+
+					rtc@68 {
+						compatible = "dallas,ds3232";
+						reg = <0x68>;
+						interrupts = <0x1 0x1 0 0>;
+					};
+				};
+
+				i2c@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x1>;
+
+					eeprom@55 {
+						compatible = "at24,24c02";
+						reg = <0x55>;
+					};
+				};
+
+				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>;
+					};
+				};
+			};
+		};
+
+		sdhc@114000 {
+			voltage-ranges = <1800 1800 3300 3300>;
+		};
+	};
+
+	pci0: pcie@ffe240000 {
+		reg = <0xf 0xfe240000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe250000 {
+		reg = <0xf 0xfe250000 0 0x10000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe260000 {
+		reg = <0xf 0xfe260000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe270000 {
+		reg = <0xf 0xfe270000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t208xrdb.dtsi linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t208xrdb.dtsi
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t208xrdb.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t208xrdb.dtsi	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * T2080PCIe-RDB Board Device Tree Source
+ *
+ * Copyright 2014 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.
+ */
+
+/ {
+	model = "fsl,T2080RDB";
+	compatible = "fsl,T2080RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		nand@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x2 0x0 0x10000>;
+		};
+
+		boardctrl: board-control@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,t2080-cpld";
+			reg = <3 0 0x300>;
+			ranges = <0 3 0 0x300>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "micron,n25q512a";
+				reg = <0>;
+				spi-max-frequency = <10000000>; /* input clock */
+			};
+		};
+
+		i2c@118000 {
+			adt7481@4c {
+				compatible = "adi,adt7481";
+				reg = <0x4c>;
+			};
+
+			rtc@68 {
+				compatible = "dallas,ds1339";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+
+			eeprom@50 {
+				compatible = "atmel,24c256";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@118100 {
+			pca9546@77 {
+				compatible = "nxp,pca9546";
+				reg = <0x77>;
+			};
+		};
+
+		sdhc@114000 {
+			voltage-ranges = <1800 1800 3300 3300>;
+		};
+	};
+
+	pci0: pcie@ffe240000 {
+		reg = <0xf 0xfe240000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe250000 {
+		reg = <0xf 0xfe250000 0 0x10000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe260000 {
+		reg = <0xf 0xfe260000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe270000 {
+		reg = <0xf 0xfe270000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/dts/t4240rdb.dts linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t4240rdb.dts
--- linux-libre-3.16-gnu/arch/powerpc/boot/dts/t4240rdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/dts/t4240rdb.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ * T4240RDB Device Tree Source
+ *
+ * Copyright 2014 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/ "fsl/t4240si-pre.dtsi"
+
+/ {
+	model = "fsl,T4240RDB";
+	compatible = "fsl,T4240RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x2 0x0 0x10000>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "sst,sst25wf040";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+			};
+		};
+
+		i2c@118000 {
+			eeprom@52 {
+				compatible = "at24,24c256";
+				reg = <0x52>;
+			};
+			eeprom@54 {
+				compatible = "at24,24c256";
+				reg = <0x54>;
+			};
+			eeprom@56 {
+				compatible = "at24,24c256";
+				reg = <0x56>;
+			};
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+
+		sdhc@114000 {
+			voltage-ranges = <1800 1800 3300 3300>;
+		};
+	};
+
+	pci0: pcie@ffe240000 {
+		reg = <0xf 0xfe240000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe250000 {
+		reg = <0xf 0xfe250000 0 0x10000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe260000 {
+		reg = <0xf 0xfe260000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe270000 {
+		reg = <0xf 0xfe270000 0 0x10000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	rio: rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+};
+
+/include/ "fsl/t4240si-post.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/gunzip_util.c linux-libre-3.17-rc7-gnu/arch/powerpc/boot/gunzip_util.c
--- linux-libre-3.16-gnu/arch/powerpc/boot/gunzip_util.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/gunzip_util.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,10 +112,10 @@ int gunzip_partial(struct gunzip_state *
 		r = zlib_inflate(&state->s, Z_FULL_FLUSH);
 		if (r != Z_OK && r != Z_STREAM_END)
 			fatal("inflate returned %d msg: %s\n\r", r, state->s.msg);
-		len = state->s.next_out - (unsigned char *)dst;
+		len = state->s.next_out - (Byte *)dst;
 	} else {
 		/* uncompressed image */
-		len = min(state->s.avail_in, (unsigned)dstlen);
+		len = min(state->s.avail_in, (uLong)dstlen);
 		memcpy(dst, state->s.next_in, len);
 		state->s.next_in += len;
 		state->s.avail_in -= len;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/boot/io.h linux-libre-3.17-rc7-gnu/arch/powerpc/boot/io.h
--- linux-libre-3.16-gnu/arch/powerpc/boot/io.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/boot/io.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 #ifndef _IO_H
-#define __IO_H
+#define _IO_H
 
 #include "types.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/52xx/motionpro_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/52xx/motionpro_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/52xx/motionpro_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/52xx/motionpro_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/85xx/kmp204x_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/85xx/kmp204x_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/85xx/kmp204x_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/85xx/kmp204x_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -192,7 +192,6 @@ CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
-# CONFIG_NET_VENDOR_SILICOM is not set
 CONFIG_CLK_PPC_CORENET=y
 CONFIG_EXT2_FS=y
 CONFIG_NTFS_FS=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
 CONFIG_IDE=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/c2k_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/c2k_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/c2k_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/c2k_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@ CONFIG_PM=y
 CONFIG_PCI_MSI=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/cell_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/cell_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/cell_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/cell_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/celleb_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/celleb_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/celleb_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/celleb_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/corenet32_smp_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/corenet32_smp_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/corenet32_smp_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/corenet32_smp_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -139,8 +139,9 @@ CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_DS3232=y
-CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
 CONFIG_VIRT_DRIVERS=y
@@ -179,3 +180,4 @@ CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_FSL_CORENET_CF=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/corenet64_smp_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/corenet64_smp_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/corenet64_smp_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/corenet64_smp_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@ CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=24
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -123,6 +124,10 @@ CONFIG_USB_EHCI_FSL=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_DMADEVICES=y
@@ -175,3 +180,4 @@ CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_FSL_CORENET_CF=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/g5_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/g5_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/g5_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/g5_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_BLK_DEV_INITRD=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/maple_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/maple_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/maple_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/maple_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@ CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_COMPAT_BRK is not set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/mpc5200_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc5200_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/mpc5200_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc5200_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_EEPROM_AT24=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/mpc85xx_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/mpc85xx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc85xx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -209,6 +209,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_DMADEVICES=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -210,6 +210,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_DMADEVICES=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/pasemi_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pasemi_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/pasemi_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pasemi_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@ CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/pmac32_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pmac32_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/pmac32_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pmac32_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@ CONFIG_HIBERNATION=y
 CONFIG_APM_EMULATION=y
 CONFIG_PCCARD=m
 CONFIG_YENTA=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/ppc44x_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc44x_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/ppc44x_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc44x_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -127,4 +127,3 @@ CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_VIRTUALIZATION=y
-CONFIG_KVM_440=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/ppc64_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc64_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/ppc64_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc64_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@ CONFIG_VSX=y
 CONFIG_SMP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -57,6 +58,7 @@ CONFIG_ELECTRA_CF=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/ppc64e_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc64e_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/ppc64e_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc64e_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@ CONFIG_PPC_BOOK3E_64=y
 CONFIG_SMP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
@@ -32,6 +33,7 @@ CONFIG_SPARSEMEM_MANUAL=y
 CONFIG_PCI_MSI=y
 CONFIG_PCCARD=y
 CONFIG_HOTPLUG_PCI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/ppc6xx_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/ppc6xx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ppc6xx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -425,10 +425,8 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_SCSI_MESH=m
 CONFIG_SCSI_MAC53C94=m
-CONFIG_SCSI_SRP=m
 CONFIG_SCSI_LOWLEVEL_PCMCIA=y
 CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/ps3_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ps3_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/ps3_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/ps3_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/pseries_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pseries_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/pseries_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pseries_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2048
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
@@ -52,6 +53,7 @@ CONFIG_SCHED_SMT=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/configs/pseries_le_defconfig linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pseries_le_defconfig
--- linux-libre-3.16-gnu/arch/powerpc/configs/pseries_le_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/configs/pseries_le_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@ CONFIG_NR_CPUS=2048
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
@@ -54,6 +55,7 @@ CONFIG_SCHED_SMT=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/asm-compat.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/asm-compat.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/asm-compat.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/asm-compat.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,10 +34,14 @@
 #define PPC_MIN_STKFRM	112
 
 #ifdef __BIG_ENDIAN__
+#define LWZX_BE	stringify_in_c(lwzx)
 #define LDX_BE	stringify_in_c(ldx)
+#define STWX_BE	stringify_in_c(stwx)
 #define STDX_BE	stringify_in_c(stdx)
 #else
+#define LWZX_BE	stringify_in_c(lwbrx)
 #define LDX_BE	stringify_in_c(ldbrx)
+#define STWX_BE	stringify_in_c(stwbrx)
 #define STDX_BE	stringify_in_c(stdbrx)
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/cache.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/cache.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/cache.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/cache.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/reg.h>
 
 /* bytes per L1 cache line */
 #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -39,6 +40,12 @@ struct ppc64_caches {
 };
 
 extern struct ppc64_caches ppc64_caches;
+
+static inline void logmpp(u64 x)
+{
+	asm volatile(PPC_LOGMPP(R1) : : "r" (x));
+}
+
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if defined(__ASSEMBLY__)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/cputable.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/cputable.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/cputable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/cputable.h	2014-09-28 17:29:07.000000000 -0400
@@ -195,8 +195,7 @@ extern const char *powerpc_base_platform
 
 #define CPU_FTR_PPCAS_ARCH_V2	(CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN)
 
-#define MMU_FTR_PPCAS_ARCH_V2 	(MMU_FTR_SLB | MMU_FTR_TLBIEL | \
-				 MMU_FTR_16M_PAGE)
+#define MMU_FTR_PPCAS_ARCH_V2 	(MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE)
 
 /* We only set the altivec features if the kernel was compiled with altivec
  * support
@@ -268,10 +267,6 @@ extern const char *powerpc_base_platform
 #define CPU_FTR_MAYBE_CAN_NAP	0
 #endif
 
-#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
-		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
-		     !defined(CONFIG_BOOKE))
-
 #define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | \
 	CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
 #define CPU_FTRS_603	(CPU_FTR_COMMON | \
@@ -396,15 +391,10 @@ extern const char *powerpc_base_platform
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \
-	    CPU_FTR_CELL_TB_BUG)
+	    CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
-	    CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
-	    CPU_FTR_IABR | \
-	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
 #define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
@@ -467,15 +457,15 @@ extern const char *powerpc_base_platform
 #define CPU_FTRS_POSSIBLE	(CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2)
 #else
 #define CPU_FTRS_POSSIBLE	\
-	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
-	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |	\
-	    CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 |	\
-	    CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX)
+	    (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
+	     CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \
+	     CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \
+	     CPU_FTRS_PA6T | CPU_FTR_VSX)
 #endif
 #else
 enum {
 	CPU_FTRS_POSSIBLE =
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
 	    CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
 	    CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
 	    CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX |
@@ -518,14 +508,15 @@ enum {
 #define CPU_FTRS_ALWAYS		(CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2)
 #else
 #define CPU_FTRS_ALWAYS		\
-	    (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &	\
-	    CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 &	\
-	    CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE)
+	    (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \
+	     CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \
+	     CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \
+	     CPU_FTRS_POWER8_DD1 & CPU_FTRS_POSSIBLE)
 #endif
 #else
 enum {
 	CPU_FTRS_ALWAYS =
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
 	    CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
 	    CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
 	    CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX &
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/eeh.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/eeh.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/eeh.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/eeh.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/string.h>
 #include <linux/time.h>
+#include <linux/atomic.h>
 
 struct pci_dev;
 struct pci_bus;
@@ -33,10 +34,11 @@ struct device_node;
 #ifdef CONFIG_EEH
 
 /* EEH subsystem flags */
-#define EEH_ENABLED		0x1	/* EEH enabled		*/
-#define EEH_FORCE_DISABLED	0x2	/* EEH disabled		*/
-#define EEH_PROBE_MODE_DEV	0x4	/* From PCI device	*/
-#define EEH_PROBE_MODE_DEVTREE	0x8	/* From device tree	*/
+#define EEH_ENABLED		0x01	/* EEH enabled		*/
+#define EEH_FORCE_DISABLED	0x02	/* EEH disabled		*/
+#define EEH_PROBE_MODE_DEV	0x04	/* From PCI device	*/
+#define EEH_PROBE_MODE_DEVTREE	0x08	/* From device tree	*/
+#define EEH_ENABLE_IO_FOR_LOG	0x10	/* Enable IO for log	*/
 
 /*
  * Delay for PE reset, all in ms
@@ -84,7 +86,9 @@ struct eeh_pe {
 	int freeze_count;		/* Times of froze up		*/
 	struct timeval tstamp;		/* Time on first-time freeze	*/
 	int false_positives;		/* Times of reported #ff's	*/
+	atomic_t pass_dev_cnt;		/* Count of passed through devs	*/
 	struct eeh_pe *parent;		/* Parent PE			*/
+	void *data;			/* PE auxillary data		*/
 	struct list_head child_list;	/* Link PE to the child list	*/
 	struct list_head edevs;		/* Link list of EEH devices	*/
 	struct list_head child;		/* Child PEs			*/
@@ -93,6 +97,11 @@ struct eeh_pe {
 #define eeh_pe_for_each_dev(pe, edev, tmp) \
 		list_for_each_entry_safe(edev, tmp, &pe->edevs, list)
 
+static inline bool eeh_pe_passed(struct eeh_pe *pe)
+{
+	return pe ? !!atomic_read(&pe->pass_dev_cnt) : false;
+}
+
 /*
  * The struct is used to trace EEH state for the associated
  * PCI device node or PCI device. In future, it might
@@ -165,6 +174,11 @@ enum {
 #define EEH_STATE_DMA_ACTIVE	(1 << 4)	/* Active DMA		*/
 #define EEH_STATE_MMIO_ENABLED	(1 << 5)	/* MMIO enabled		*/
 #define EEH_STATE_DMA_ENABLED	(1 << 6)	/* DMA enabled		*/
+#define EEH_PE_STATE_NORMAL		0	/* Normal state		*/
+#define EEH_PE_STATE_RESET		1	/* PE reset asserted	*/
+#define EEH_PE_STATE_STOPPED_IO_DMA	2	/* Frozen PE		*/
+#define EEH_PE_STATE_STOPPED_DMA	4	/* Stopped DMA, Enabled IO */
+#define EEH_PE_STATE_UNAVAIL		5	/* Unavailable		*/
 #define EEH_RESET_DEACTIVATE	0	/* Deactivate the PE reset	*/
 #define EEH_RESET_HOT		1	/* Hot reset			*/
 #define EEH_RESET_FUNDAMENTAL	3	/* Fundamental reset		*/
@@ -194,36 +208,28 @@ extern int eeh_subsystem_flags;
 extern struct eeh_ops *eeh_ops;
 extern raw_spinlock_t confirm_error_lock;
 
-static inline bool eeh_enabled(void)
+static inline void eeh_add_flag(int flag)
 {
-	if ((eeh_subsystem_flags & EEH_FORCE_DISABLED) ||
-	    !(eeh_subsystem_flags & EEH_ENABLED))
-		return false;
-
-	return true;
+	eeh_subsystem_flags |= flag;
 }
 
-static inline void eeh_set_enable(bool mode)
+static inline void eeh_clear_flag(int flag)
 {
-	if (mode)
-		eeh_subsystem_flags |= EEH_ENABLED;
-	else
-		eeh_subsystem_flags &= ~EEH_ENABLED;
+	eeh_subsystem_flags &= ~flag;
 }
 
-static inline void eeh_probe_mode_set(int flag)
+static inline bool eeh_has_flag(int flag)
 {
-	eeh_subsystem_flags |= flag;
+        return !!(eeh_subsystem_flags & flag);
 }
 
-static inline int eeh_probe_mode_devtree(void)
+static inline bool eeh_enabled(void)
 {
-	return (eeh_subsystem_flags & EEH_PROBE_MODE_DEVTREE);
-}
+	if (eeh_has_flag(EEH_FORCE_DISABLED) ||
+	    !eeh_has_flag(EEH_ENABLED))
+		return false;
 
-static inline int eeh_probe_mode_dev(void)
-{
-	return (eeh_subsystem_flags & EEH_PROBE_MODE_DEV);
+	return true;
 }
 
 static inline void eeh_serialize_lock(unsigned long *flags)
@@ -243,6 +249,7 @@ static inline void eeh_serialize_unlock(
 #define EEH_MAX_ALLOWED_FREEZES 5
 
 typedef void *(*eeh_traverse_func)(void *data, void *flag);
+void eeh_set_pe_aux_size(int size);
 int eeh_phb_pe_create(struct pci_controller *phb);
 struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
 struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
@@ -272,6 +279,13 @@ void eeh_add_device_late(struct pci_dev
 void eeh_add_device_tree_late(struct pci_bus *);
 void eeh_add_sysfs_files(struct pci_bus *);
 void eeh_remove_device(struct pci_dev *);
+int eeh_dev_open(struct pci_dev *pdev);
+void eeh_dev_release(struct pci_dev *pdev);
+struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
+int eeh_pe_set_option(struct eeh_pe *pe, int option);
+int eeh_pe_get_state(struct eeh_pe *pe);
+int eeh_pe_reset(struct eeh_pe *pe, int option);
+int eeh_pe_configure(struct eeh_pe *pe);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -295,8 +309,6 @@ static inline bool eeh_enabled(void)
         return false;
 }
 
-static inline void eeh_set_enable(bool mode) { }
-
 static inline int eeh_init(void)
 {
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/exception-64s.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/exception-64s.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/exception-64s.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/exception-64s.h	2014-09-28 17:29:07.000000000 -0400
@@ -425,6 +425,8 @@ label##_relon_hv:						\
 #define SOFTEN_VALUE_0xa00	PACA_IRQ_DBELL
 #define SOFTEN_VALUE_0xe80	PACA_IRQ_DBELL
 #define SOFTEN_VALUE_0xe82	PACA_IRQ_DBELL
+#define SOFTEN_VALUE_0xe60	PACA_IRQ_HMI
+#define SOFTEN_VALUE_0xe62	PACA_IRQ_HMI
 
 #define __SOFTEN_TEST(h, vec)						\
 	lbz	r10,PACASOFTIRQEN(r13);					\
@@ -513,8 +515,11 @@ label##_relon_hv:							\
  * runlatch, etc...
  */
 
-/* Exception addition: Hard disable interrupts */
-#define DISABLE_INTS	RECONCILE_IRQ_STATE(r10,r11)
+/*
+ * This addition reconciles our actual IRQ state with the various software
+ * flags that track it. This may call C code.
+ */
+#define ADD_RECONCILE	RECONCILE_IRQ_STATE(r10,r11)
 
 #define ADD_NVGPRS				\
 	bl	save_nvgprs
@@ -532,6 +537,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
 	.globl label##_common;					\
 label##_common:							\
 	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);		\
+	/* Volatile regs are potentially clobbered here */	\
 	additions;						\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
 	bl	hdlr;						\
@@ -539,7 +545,7 @@ label##_common:							\
 
 #define STD_EXCEPTION_COMMON(trap, label, hdlr)			\
 	EXCEPTION_COMMON(trap, label, hdlr, ret_from_except,	\
-			 ADD_NVGPRS;DISABLE_INTS)
+			 ADD_NVGPRS;ADD_RECONCILE)
 
 /*
  * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
@@ -548,7 +554,7 @@ label##_common:							\
  */
 #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)		  \
 	EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
-			 FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)
+			 FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
 
 /*
  * When the idle code in power4_idle puts the CPU into NAP mode,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/fs_pd.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/fs_pd.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/fs_pd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/fs_pd.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,6 @@
 
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
 
 extern immap_t __iomem *mpc8xx_immr;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/hardirq.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hardirq.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/hardirq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hardirq.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ typedef struct {
 	unsigned int pmu_irqs;
 	unsigned int mce_exceptions;
 	unsigned int spurious_irqs;
+	unsigned int hmi_exceptions;
 #ifdef CONFIG_PPC_DOORBELL
 	unsigned int doorbell_irqs;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/hvcall.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hvcall.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/hvcall.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hvcall.h	2014-09-28 17:29:07.000000000 -0400
@@ -279,6 +279,12 @@
 #define H_GET_24X7_DATA		0xF07C
 #define H_GET_PERF_COUNTER_INFO	0xF080
 
+/* Values for 2nd argument to H_SET_MODE */
+#define H_SET_MODE_RESOURCE_SET_CIABR		1
+#define H_SET_MODE_RESOURCE_SET_DAWR		2
+#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE	3
+#define H_SET_MODE_RESOURCE_LE			4
+
 #ifndef __ASSEMBLY__
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/hw_irq.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hw_irq.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/hw_irq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/hw_irq.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #define PACA_IRQ_EE		0x04
 #define PACA_IRQ_DEC		0x08 /* Or FIT */
 #define PACA_IRQ_EE_EDGE	0x10 /* BookE only */
+#define PACA_IRQ_HMI		0x20
 
 #endif /* CONFIG_PPC64 */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/irqflags.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/irqflags.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/irqflags.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/irqflags.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,9 +32,8 @@
 #endif
 
 /*
- * Most of the CPU's IRQ-state tracing is done from assembly code; we
- * have to call a C function so call a wrapper that saves all the
- * C-clobbered registers.
+ * These are calls to C code, so the caller must be prepared for volatiles to
+ * be clobbered.
  */
 #define TRACE_ENABLE_INTS	TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on)
 #define TRACE_DISABLE_INTS	TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off)
@@ -42,6 +41,9 @@
 /*
  * This is used by assembly code to soft-disable interrupts first and
  * reconcile irq state.
+ *
+ * NB: This may call C code, so the caller must be prepared for volatiles to
+ * be clobbered.
  */
 #define RECONCILE_IRQ_STATE(__rA, __rB)		\
 	lbz	__rA,PACASOFTIRQEN(r13);	\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/jump_label.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/jump_label.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/jump_label.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/jump_label.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#ifndef __ASSEMBLY__
 #include <linux/types.h>
 
 #include <asm/feature-fixups.h>
@@ -42,4 +43,12 @@ struct jump_entry {
 	jump_label_t key;
 };
 
+#else
+#define ARCH_STATIC_BRANCH(LABEL, KEY)		\
+1098:	nop;					\
+	.pushsection __jump_table, "aw";	\
+	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
+	.popsection
+#endif
+
 #endif /* _ASM_POWERPC_JUMP_LABEL_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -4,5 +4,6 @@ generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vtime.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_44x.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_44x.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_44x.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_44x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#ifndef __ASM_44X_H__
-#define __ASM_44X_H__
-
-#include <linux/kvm_host.h>
-
-#define PPC44x_TLB_SIZE 64
-
-/* If the guest is expecting it, this can be as large as we like; we'd just
- * need to find some way of advertising it. */
-#define KVM44x_GUEST_TLB_SIZE 64
-
-struct kvmppc_44x_tlbe {
-	u32 tid; /* Only the low 8 bits are used. */
-	u32 word0;
-	u32 word1;
-	u32 word2;
-};
-
-struct kvmppc_44x_shadow_ref {
-	struct page *page;
-	u16 gtlb_index;
-	u8 writeable;
-	u8 tid;
-};
-
-struct kvmppc_vcpu_44x {
-	/* Unmodified copy of the guest's TLB. */
-	struct kvmppc_44x_tlbe guest_tlb[KVM44x_GUEST_TLB_SIZE];
-
-	/* References to guest pages in the hardware TLB. */
-	struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE];
-
-	/* State of the shadow TLB at guest context switch time. */
-	struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE];
-	u8 shadow_tlb_mod[PPC44x_TLB_SIZE];
-
-	struct kvm_vcpu vcpu;
-};
-
-static inline struct kvmppc_vcpu_44x *to_44x(struct kvm_vcpu *vcpu)
-{
-	return container_of(vcpu, struct kvmppc_vcpu_44x, vcpu);
-}
-
-void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu);
-void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu);
-
-#endif /* __ASM_44X_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_asm.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_asm.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_asm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_asm.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@
 /* IVPR must be 64KiB-aligned. */
 #define VCPU_SIZE_ORDER 4
 #define VCPU_SIZE_LOG   (VCPU_SIZE_ORDER + 12)
-#define VCPU_TLB_PGSZ   PPC44x_TLB_64K
 #define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG)
 
 #define BOOKE_INTERRUPT_CRITICAL 0
@@ -98,6 +97,7 @@
 #define BOOK3S_INTERRUPT_H_DATA_STORAGE	0xe00
 #define BOOK3S_INTERRUPT_H_INST_STORAGE	0xe20
 #define BOOK3S_INTERRUPT_H_EMUL_ASSIST	0xe40
+#define BOOK3S_INTERRUPT_HMI		0xe60
 #define BOOK3S_INTERRUPT_H_DOORBELL	0xe80
 #define BOOK3S_INTERRUPT_PERFMON	0xf00
 #define BOOK3S_INTERRUPT_ALTIVEC	0xf20
@@ -131,6 +131,7 @@
 #define BOOK3S_HFLAG_NATIVE_PS			0x8
 #define BOOK3S_HFLAG_MULTI_PGSIZE		0x10
 #define BOOK3S_HFLAG_NEW_TLBIE			0x20
+#define BOOK3S_HFLAG_SPLIT_HACK			0x40
 
 #define RESUME_FLAG_NV          (1<<0)  /* Reload guest nonvolatile state? */
 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_book3s_64.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_book3s_64.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -59,20 +59,29 @@ extern unsigned long kvm_rma_pages;
 /* These bits are reserved in the guest view of the HPTE */
 #define HPTE_GR_RESERVED	HPTE_GR_MODIFIED
 
-static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
+static inline long try_lock_hpte(__be64 *hpte, unsigned long bits)
 {
 	unsigned long tmp, old;
+	__be64 be_lockbit, be_bits;
+
+	/*
+	 * We load/store in native endian, but the HTAB is in big endian. If
+	 * we byte swap all data we apply on the PTE we're implicitly correct
+	 * again.
+	 */
+	be_lockbit = cpu_to_be64(HPTE_V_HVLOCK);
+	be_bits = cpu_to_be64(bits);
 
 	asm volatile("	ldarx	%0,0,%2\n"
 		     "	and.	%1,%0,%3\n"
 		     "	bne	2f\n"
-		     "	ori	%0,%0,%4\n"
+		     "	or	%0,%0,%4\n"
 		     "  stdcx.	%0,0,%2\n"
 		     "	beq+	2f\n"
 		     "	mr	%1,%3\n"
 		     "2:	isync"
 		     : "=&r" (tmp), "=&r" (old)
-		     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+		     : "r" (hpte), "r" (be_bits), "r" (be_lockbit)
 		     : "cc", "memory");
 	return old == 0;
 }
@@ -110,16 +119,12 @@ static inline int __hpte_actual_psize(un
 static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
 					     unsigned long pte_index)
 {
-	int b_psize, a_psize;
+	int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K;
 	unsigned int penc;
 	unsigned long rb = 0, va_low, sllp;
 	unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
 
-	if (!(v & HPTE_V_LARGE)) {
-		/* both base and actual psize is 4k */
-		b_psize = MMU_PAGE_4K;
-		a_psize = MMU_PAGE_4K;
-	} else {
+	if (v & HPTE_V_LARGE) {
 		for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) {
 
 			/* valid entries have a shift value */
@@ -142,6 +147,8 @@ static inline unsigned long compute_tlbi
 	 */
 	/* This covers 14..54 bits of va*/
 	rb = (v & ~0x7fUL) << 16;		/* AVA field */
+
+	rb |= v >> (62 - 8);			/*  B field */
 	/*
 	 * AVA in v had cleared lower 23 bits. We need to derive
 	 * that from pteg index
@@ -172,10 +179,10 @@ static inline unsigned long compute_tlbi
 	{
 		int aval_shift;
 		/*
-		 * remaining 7bits of AVA/LP fields
+		 * remaining bits of AVA/LP fields
 		 * Also contain the rr bits of LP
 		 */
-		rb |= (va_low & 0x7f) << 16;
+		rb |= (va_low << mmu_psize_defs[b_psize].shift) & 0x7ff000;
 		/*
 		 * Now clear not needed LP bits based on actual psize
 		 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_book3s.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_book3s.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_book3s.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_book3s.h	2014-09-28 17:29:07.000000000 -0400
@@ -83,8 +83,6 @@ struct kvmppc_vcpu_book3s {
 	u64 sdr1;
 	u64 hior;
 	u64 msr_mask;
-	u64 purr_offset;
-	u64 spurr_offset;
 #ifdef CONFIG_PPC_BOOK3S_32
 	u32 vsid_pool[VSID_POOL_SIZE];
 	u32 vsid_next;
@@ -148,9 +146,10 @@ extern void kvmppc_mmu_invalidate_pte(st
 extern int kvmppc_mmu_hpte_sysinit(void);
 extern void kvmppc_mmu_hpte_sysexit(void);
 extern int kvmppc_mmu_hv_init(void);
+extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc);
 
+/* XXX remove this export when load_last_inst() is generic */
 extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
-extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
 extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
 extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
 					  unsigned int vec);
@@ -159,13 +158,13 @@ extern void kvmppc_set_bat(struct kvm_vc
 			   bool upper, u32 val);
 extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
-extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
+extern pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
 			bool *writable);
 extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
 			unsigned long *rmap, long pte_index, int realmode);
-extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
 			unsigned long pte_index);
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
 			unsigned long pte_index);
 extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
 			unsigned long *nb_ret);
@@ -183,12 +182,16 @@ extern long kvmppc_hv_get_dirty_log(stru
 			struct kvm_memory_slot *memslot, unsigned long *map);
 extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr,
 			unsigned long mask);
+extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
 extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm);
+extern int kvmppc_hcall_impl_pr(unsigned long cmd);
+extern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd);
 extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
 				 struct kvm_vcpu *vcpu);
 extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
@@ -274,32 +277,6 @@ static inline bool kvmppc_need_byteswap(
 	return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE);
 }
 
-static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
-{
-	/* Load the instruction manually if it failed to do so in the
-	 * exit path */
-	if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
-		kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false);
-
-	return kvmppc_need_byteswap(vcpu) ? swab32(vcpu->arch.last_inst) :
-		vcpu->arch.last_inst;
-}
-
-static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
-{
-	return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu));
-}
-
-/*
- * Like kvmppc_get_last_inst(), but for fetching a sc instruction.
- * Because the sc instruction sets SRR0 to point to the following
- * instruction, we have to fetch from pc - 4.
- */
-static inline u32 kvmppc_get_last_sc(struct kvm_vcpu *vcpu)
-{
-	return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu) - 4);
-}
-
 static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.fault_dar;
@@ -310,6 +287,13 @@ static inline bool is_kvmppc_resume_gues
 	return (r == RESUME_GUEST || r == RESUME_GUEST_NV);
 }
 
+static inline bool is_kvmppc_hv_enabled(struct kvm *kvm);
+static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
+{
+	/* Only PR KVM supports the magic page */
+	return !is_kvmppc_hv_enabled(vcpu->kvm);
+}
+
 /* Magic register values loaded into r3 and r4 before the 'sc' assembly
  * instruction for the OSI hypercalls */
 #define OSI_SC_MAGIC_R3			0x113724FA
@@ -322,4 +306,7 @@ static inline bool is_kvmppc_resume_gues
 /* LPIDs we support with this build -- runtime limit may be lower */
 #define KVMPPC_NR_LPIDS			(LPID_RSVD + 1)
 
+#define SPLIT_HACK_MASK			0xff000000
+#define SPLIT_HACK_OFFS			0xfb000000
+
 #endif /* __ASM_KVM_BOOK3S_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_booke.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_booke.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_booke.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_booke.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,11 +69,6 @@ static inline bool kvmppc_need_byteswap(
 	return false;
 }
 
-static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.last_inst;
-}
-
 static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
 {
 	vcpu->arch.ctr = val;
@@ -108,4 +103,14 @@ static inline ulong kvmppc_get_fault_dar
 {
 	return vcpu->arch.fault_dear;
 }
+
+static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
+{
+	/* Magic page is only supported on e500v2 */
+#ifdef CONFIG_KVM_E500V2
+	return true;
+#else
+	return false;
+#endif
+}
 #endif /* __ASM_KVM_BOOKE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
+#include <asm/hvcall.h>
 
 #define KVM_MAX_VCPUS		NR_CPUS
 #define KVM_MAX_VCORES		NR_CPUS
@@ -48,7 +49,6 @@
 #define KVM_NR_IRQCHIPS          1
 #define KVM_IRQCHIP_NUM_PINS     256
 
-#if !defined(CONFIG_KVM_440)
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -61,8 +61,6 @@ extern int kvm_age_hva(struct kvm *kvm,
 extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 
-#endif
-
 #define HPTEG_CACHE_NUM			(1 << 15)
 #define HPTEG_HASH_BITS_PTE		13
 #define HPTEG_HASH_BITS_PTE_LONG	12
@@ -96,7 +94,6 @@ struct kvm_vm_stat {
 struct kvm_vcpu_stat {
 	u32 sum_exits;
 	u32 mmio_exits;
-	u32 dcr_exits;
 	u32 signal_exits;
 	u32 light_exits;
 	/* Account for special types of light exits: */
@@ -113,22 +110,21 @@ struct kvm_vcpu_stat {
 	u32 halt_wakeup;
 	u32 dbell_exits;
 	u32 gdbell_exits;
+	u32 ld;
+	u32 st;
 #ifdef CONFIG_PPC_BOOK3S
 	u32 pf_storage;
 	u32 pf_instruc;
 	u32 sp_storage;
 	u32 sp_instruc;
 	u32 queue_intr;
-	u32 ld;
 	u32 ld_slow;
-	u32 st;
 	u32 st_slow;
 #endif
 };
 
 enum kvm_exit_types {
 	MMIO_EXITS,
-	DCR_EXITS,
 	SIGNAL_EXITS,
 	ITLB_REAL_MISS_EXITS,
 	ITLB_VIRT_MISS_EXITS,
@@ -254,7 +250,6 @@ struct kvm_arch {
 	atomic_t hpte_mod_interest;
 	spinlock_t slot_phys_lock;
 	cpumask_t need_tlb_flush;
-	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
 	int hpt_cma_alloc;
 #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
@@ -263,6 +258,7 @@ struct kvm_arch {
 #ifdef CONFIG_PPC_BOOK3S_64
 	struct list_head spapr_tce_tables;
 	struct list_head rtas_tokens;
+	DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
 #endif
 #ifdef CONFIG_KVM_MPIC
 	struct openpic *mpic;
@@ -271,6 +267,10 @@ struct kvm_arch {
 	struct kvmppc_xics *xics;
 #endif
 	struct kvmppc_ops *kvm_ops;
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	/* This array can grow quite large, keep it at the end */
+	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+#endif
 };
 
 /*
@@ -305,6 +305,8 @@ struct kvmppc_vcore {
 	u32 arch_compat;
 	ulong pcr;
 	ulong dpdes;		/* doorbell state (POWER8) */
+	void *mpp_buffer; /* Micro Partition Prefetch buffer */
+	bool mpp_buffer_is_valid;
 };
 
 #define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
@@ -503,8 +505,10 @@ struct kvm_vcpu_arch {
 #ifdef CONFIG_BOOKE
 	u32 decar;
 #endif
-	u32 tbl;
-	u32 tbu;
+	/* Time base value when we entered the guest */
+	u64 entry_tb;
+	u64 entry_vtb;
+	u64 entry_ic;
 	u32 tcr;
 	ulong tsr; /* we need to perform set/clr_bits() which requires ulong */
 	u32 ivor[64];
@@ -580,6 +584,8 @@ struct kvm_vcpu_arch {
 	u32 mmucfg;
 	u32 eptcfg;
 	u32 epr;
+	u64 sprg9;
+	u32 pwrmgtcr0;
 	u32 crit_save;
 	/* guest debug registers*/
 	struct debug_reg dbg_reg;
@@ -593,8 +599,6 @@ struct kvm_vcpu_arch {
 	u8 io_gpr; /* GPR used as IO source/target */
 	u8 mmio_is_bigendian;
 	u8 mmio_sign_extend;
-	u8 dcr_needed;
-	u8 dcr_is_write;
 	u8 osi_needed;
 	u8 osi_enabled;
 	u8 papr_enabled;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_ppc.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_ppc.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/kvm_ppc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/kvm_ppc.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,12 +41,26 @@
 enum emulation_result {
 	EMULATE_DONE,         /* no further processing */
 	EMULATE_DO_MMIO,      /* kvm_run filled with MMIO request */
-	EMULATE_DO_DCR,       /* kvm_run filled with DCR request */
 	EMULATE_FAIL,         /* can't emulate this instruction */
 	EMULATE_AGAIN,        /* something went wrong. go again */
 	EMULATE_EXIT_USER,    /* emulation requires exit to user-space */
 };
 
+enum instruction_type {
+	INST_GENERIC,
+	INST_SC,		/* system call */
+};
+
+enum xlate_instdata {
+	XLATE_INST,		/* translate instruction address */
+	XLATE_DATA		/* translate data address */
+};
+
+enum xlate_readwrite {
+	XLATE_READ,		/* check for read permissions */
+	XLATE_WRITE		/* check for write permissions */
+};
+
 extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
 extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
 extern void kvmppc_handler_highmem(void);
@@ -62,8 +76,16 @@ extern int kvmppc_handle_store(struct kv
 			       u64 val, unsigned int bytes,
 			       int is_default_endian);
 
+extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
+				 enum instruction_type type, u32 *inst);
+
+extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+		     bool data);
+extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+		     bool data);
 extern int kvmppc_emulate_instruction(struct kvm_run *run,
                                       struct kvm_vcpu *vcpu);
+extern int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu);
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
@@ -86,6 +108,9 @@ extern gpa_t kvmppc_mmu_xlate(struct kvm
                               gva_t eaddr);
 extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu);
 extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu);
+extern int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr,
+			enum xlate_instdata xlid, enum xlate_readwrite xlrw,
+			struct kvmppc_pte *pte);
 
 extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
                                                 unsigned int id);
@@ -106,6 +131,14 @@ extern void kvmppc_core_dequeue_dec(stru
 extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, ulong dear_flags,
+					ulong esr_flags);
+extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
+					   ulong dear_flags,
+					   ulong esr_flags);
+extern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
+					   ulong esr_flags);
 extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
 
@@ -228,12 +261,35 @@ struct kvmppc_ops {
 	void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu);
 	long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl,
 			      unsigned long arg);
-
+	int (*hcall_implemented)(unsigned long hcall);
 };
 
 extern struct kvmppc_ops *kvmppc_hv_ops;
 extern struct kvmppc_ops *kvmppc_pr_ops;
 
+static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
+					enum instruction_type type, u32 *inst)
+{
+	int ret = EMULATE_DONE;
+	u32 fetched_inst;
+
+	/* Load the instruction manually if it failed to do so in the
+	 * exit path */
+	if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
+		ret = kvmppc_load_last_inst(vcpu, type, &vcpu->arch.last_inst);
+
+	/*  Write fetch_failed unswapped if the fetch failed */
+	if (ret == EMULATE_DONE)
+		fetched_inst = kvmppc_need_byteswap(vcpu) ?
+				swab32(vcpu->arch.last_inst) :
+				vcpu->arch.last_inst;
+	else
+		fetched_inst = vcpu->arch.last_inst;
+
+	*inst = fetched_inst;
+	return ret;
+}
+
 static inline bool is_kvmppc_hv_enabled(struct kvm *kvm)
 {
 	return kvm->arch.kvm_ops == kvmppc_hv_ops;
@@ -392,6 +448,17 @@ static inline int kvmppc_xics_hcall(stru
 	{ return 0; }
 #endif
 
+static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_KVM_BOOKE_HV
+	return mfspr(SPRN_GEPR);
+#elif defined(CONFIG_BOOKE)
+	return vcpu->arch.epr;
+#else
+	return 0;
+#endif
+}
+
 static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
@@ -472,8 +539,20 @@ static inline bool kvmppc_shared_big_end
 #endif
 }
 
+#define SPRNG_WRAPPER_GET(reg, bookehv_spr)				\
+static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
+{									\
+	return mfspr(bookehv_spr);					\
+}									\
+
+#define SPRNG_WRAPPER_SET(reg, bookehv_spr)				\
+static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val)	\
+{									\
+	mtspr(bookehv_spr, val);						\
+}									\
+
 #define SHARED_WRAPPER_GET(reg, size)					\
-static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)	\
+static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
 {									\
 	if (kvmppc_shared_big_endian(vcpu))				\
 	       return be##size##_to_cpu(vcpu->arch.shared->reg);	\
@@ -494,14 +573,31 @@ static inline void kvmppc_set_##reg(stru
 	SHARED_WRAPPER_GET(reg, size)					\
 	SHARED_WRAPPER_SET(reg, size)					\
 
+#define SPRNG_WRAPPER(reg, bookehv_spr)					\
+	SPRNG_WRAPPER_GET(reg, bookehv_spr)				\
+	SPRNG_WRAPPER_SET(reg, bookehv_spr)				\
+
+#ifdef CONFIG_KVM_BOOKE_HV
+
+#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr)			\
+	SPRNG_WRAPPER(reg, bookehv_spr)					\
+
+#else
+
+#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr)			\
+	SHARED_WRAPPER(reg, size)					\
+
+#endif
+
 SHARED_WRAPPER(critical, 64)
-SHARED_WRAPPER(sprg0, 64)
-SHARED_WRAPPER(sprg1, 64)
-SHARED_WRAPPER(sprg2, 64)
-SHARED_WRAPPER(sprg3, 64)
-SHARED_WRAPPER(srr0, 64)
-SHARED_WRAPPER(srr1, 64)
-SHARED_WRAPPER(dar, 64)
+SHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0)
+SHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1)
+SHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2)
+SHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3)
+SHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0)
+SHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1)
+SHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR)
+SHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR)
 SHARED_WRAPPER_GET(msr, 64)
 static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/machdep.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/machdep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/machdep.h	2014-09-28 17:29:07.000000000 -0400
@@ -57,10 +57,10 @@ struct machdep_calls {
 	void            (*hpte_removebolted)(unsigned long ea,
 					     int psize, int ssize);
 	void		(*flush_hash_range)(unsigned long number, int local);
-	void		(*hugepage_invalidate)(struct mm_struct *mm,
+	void		(*hugepage_invalidate)(unsigned long vsid,
+					       unsigned long addr,
 					       unsigned char *hpte_slot_array,
-					       unsigned long addr, int psize);
-
+					       int psize, int ssize);
 	/* special for kexec, to be called in real mode, linear mapping is
 	 * destroyed as well */
 	void		(*hpte_clear_all)(void);
@@ -174,6 +174,10 @@ struct machdep_calls {
 	/* Exception handlers */
 	int		(*system_reset_exception)(struct pt_regs *regs);
 	int 		(*machine_check_exception)(struct pt_regs *regs);
+	int		(*handle_hmi_exception)(struct pt_regs *regs);
+
+	/* Early exception handlers called in realmode */
+	int		(*hmi_exception_early)(struct pt_regs *regs);
 
 	/* Called during machine check exception to retrive fixup address. */
 	bool		(*mce_check_early_recovery)(struct pt_regs *regs);
@@ -366,6 +370,7 @@ static inline void log_error(char *buf,
 	} \
 	__define_initcall(__machine_initcall_##mach##_##fn, id);
 
+#define machine_early_initcall(mach, fn)	__define_machine_initcall(mach, fn, early)
 #define machine_core_initcall(mach, fn)		__define_machine_initcall(mach, fn, 1)
 #define machine_core_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 1s)
 #define machine_postcore_initcall(mach, fn)	__define_machine_initcall(mach, fn, 2)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu-book3e.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu-book3e.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu-book3e.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu-book3e.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,11 @@
 
 /* MAS registers bit definitions */
 
-#define MAS0_TLBSEL(x)		(((x) << 28) & 0x30000000)
+#define MAS0_TLBSEL_MASK	0x30000000
+#define MAS0_TLBSEL_SHIFT	28
+#define MAS0_TLBSEL(x)		(((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK)
+#define MAS0_GET_TLBSEL(mas0)	(((mas0) & MAS0_TLBSEL_MASK) >> \
+			MAS0_TLBSEL_SHIFT)
 #define MAS0_ESEL_MASK		0x0FFF0000
 #define MAS0_ESEL_SHIFT		16
 #define MAS0_ESEL(x)		(((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
@@ -58,6 +62,7 @@
 #define MAS1_TSIZE_MASK		0x00000f80
 #define MAS1_TSIZE_SHIFT	7
 #define MAS1_TSIZE(x)		(((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
+#define MAS1_GET_TSIZE(mas1)	(((mas1) & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT)
 
 #define MAS2_EPN		(~0xFFFUL)
 #define MAS2_X0			0x00000040
@@ -86,6 +91,7 @@
 #define MAS3_SPSIZE		0x0000003e
 #define MAS3_SPSIZE_SHIFT	1
 
+#define MAS4_TLBSEL_MASK	MAS0_TLBSEL_MASK
 #define MAS4_TLBSELD(x) 	MAS0_TLBSEL(x)
 #define MAS4_INDD		0x00008000	/* Default IND */
 #define MAS4_TSIZED(x)		MAS1_TSIZE(x)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu_context.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu_context.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu_context.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu_context.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@ extern int init_new_context(struct task_
 extern void destroy_context(struct mm_struct *mm);
 
 extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
-extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
 extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
 extern void set_context(unsigned long id, pgd_t *pgd);
 
@@ -77,10 +76,7 @@ static inline void switch_mm(struct mm_s
 	 * sub architectures.
 	 */
 #ifdef CONFIG_PPC_STD_MMU_64
-	if (mmu_has_feature(MMU_FTR_SLB))
-		switch_slb(tsk, next);
-	else
-		switch_stab(tsk, next);
+	switch_slb(tsk, next);
 #else
 	/* Out of line for now */
 	switch_mmu_context(prev, next);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -64,9 +64,9 @@
  */
 #define MMU_FTR_USE_PAIRED_MAS		ASM_CONST(0x01000000)
 
-/* MMU is SLB-based
+/* Doesn't support the B bit (1T segment) in SLBIE
  */
-#define MMU_FTR_SLB			ASM_CONST(0x02000000)
+#define MMU_FTR_NO_SLBIE_B		ASM_CONST(0x02000000)
 
 /* Support 16M large pages
  */
@@ -88,10 +88,6 @@
  */
 #define MMU_FTR_1T_SEGMENT		ASM_CONST(0x40000000)
 
-/* Doesn't support the B bit (1T segment) in SLBIE
- */
-#define MMU_FTR_NO_SLBIE_B		ASM_CONST(0x80000000)
-
 /* MMU feature bit sets for various CPUs */
 #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2	\
 	MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu-hash64.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu-hash64.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mmu-hash64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mmu-hash64.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,26 +25,6 @@
 #include <asm/processor.h>
 
 /*
- * Segment table
- */
-
-#define STE_ESID_V	0x80
-#define STE_ESID_KS	0x20
-#define STE_ESID_KP	0x10
-#define STE_ESID_N	0x08
-
-#define STE_VSID_SHIFT	12
-
-/* Location of cpu0's segment table */
-#define STAB0_PAGE	0x8
-#define STAB0_OFFSET	(STAB0_PAGE << 12)
-#define STAB0_PHYS_ADDR	(STAB0_OFFSET + PHYSICAL_START)
-
-#ifndef __ASSEMBLY__
-extern char initial_stab[];
-#endif /* ! __ASSEMBLY */
-
-/*
  * SLB
  */
 
@@ -370,10 +350,8 @@ extern void hpte_init_lpar(void);
 extern void hpte_init_beat(void);
 extern void hpte_init_beat_v3(void);
 
-extern void stabs_alloc(void);
 extern void slb_initialize(void);
 extern void slb_flush_and_rebolt(void);
-extern void stab_initialize(unsigned long stab);
 
 extern void slb_vmalloc_update(void);
 extern void slb_set_size(u16 size);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mpc85xx.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mpc85xx.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mpc85xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mpc85xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -77,6 +77,8 @@
 #define SVR_T1020	0x852100
 #define SVR_T1021	0x852101
 #define SVR_T1022	0x852102
+#define SVR_T2080	0x853000
+#define SVR_T2081	0x853100
 
 #define SVR_8610	0x80A000
 #define SVR_8641	0x809000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/mpc8xx.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mpc8xx.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/mpc8xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/mpc8xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/* This is the single file included by all MPC8xx build options.
- * Since there are many different boards and no standard configuration,
- * we have a unique include file for each.  Rather than change every
- * file that has to include MPC8xx configuration, they all include
- * this one and the configuration switching is done here.
- */
-#ifndef __CONFIG_8xx_DEFS
-#define __CONFIG_8xx_DEFS
-
-extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
-
-#endif /* __CONFIG_8xx_DEFS */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/opal.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/opal.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/opal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/opal.h	2014-09-28 17:29:07.000000000 -0400
@@ -147,6 +147,10 @@ struct opal_sg_list {
 #define OPAL_SET_PARAM				90
 #define OPAL_DUMP_RESEND			91
 #define OPAL_DUMP_INFO2				94
+#define OPAL_PCI_EEH_FREEZE_SET			97
+#define OPAL_HANDLE_HMI				98
+#define OPAL_REGISTER_DUMP_REGION		101
+#define OPAL_UNREGISTER_DUMP_REGION		102
 
 #ifndef __ASSEMBLY__
 
@@ -170,7 +174,11 @@ enum OpalFreezeState {
 enum OpalEehFreezeActionToken {
 	OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
 	OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
-	OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+	OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3,
+
+	OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1,
+	OPAL_EEH_ACTION_SET_FREEZE_DMA  = 2,
+	OPAL_EEH_ACTION_SET_FREEZE_ALL  = 3
 };
 
 enum OpalPciStatusToken {
@@ -240,6 +248,7 @@ enum OpalMessageType {
 	OPAL_MSG_MEM_ERR,
 	OPAL_MSG_EPOW,
 	OPAL_MSG_SHUTDOWN,
+	OPAL_MSG_HMI_EVT,
 	OPAL_MSG_TYPE_MAX,
 };
 
@@ -340,6 +349,12 @@ enum OpalMveEnableAction {
 	OPAL_ENABLE_MVE = 1
 };
 
+enum OpalM64EnableAction {
+	OPAL_DISABLE_M64 = 0,
+	OPAL_ENABLE_M64_SPLIT = 1,
+	OPAL_ENABLE_M64_NON_SPLIT = 2
+};
+
 enum OpalPciResetScope {
 	OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
 	OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
@@ -502,6 +517,50 @@ struct OpalMemoryErrorData {
 	} u;
 };
 
+/* HMI interrupt event */
+enum OpalHMI_Version {
+	OpalHMIEvt_V1 = 1,
+};
+
+enum OpalHMI_Severity {
+	OpalHMI_SEV_NO_ERROR = 0,
+	OpalHMI_SEV_WARNING = 1,
+	OpalHMI_SEV_ERROR_SYNC = 2,
+	OpalHMI_SEV_FATAL = 3,
+};
+
+enum OpalHMI_Disposition {
+	OpalHMI_DISPOSITION_RECOVERED = 0,
+	OpalHMI_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalHMI_ErrType {
+	OpalHMI_ERROR_MALFUNC_ALERT	= 0,
+	OpalHMI_ERROR_PROC_RECOV_DONE,
+	OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN,
+	OpalHMI_ERROR_PROC_RECOV_MASKED,
+	OpalHMI_ERROR_TFAC,
+	OpalHMI_ERROR_TFMR_PARITY,
+	OpalHMI_ERROR_HA_OVERFLOW_WARN,
+	OpalHMI_ERROR_XSCOM_FAIL,
+	OpalHMI_ERROR_XSCOM_DONE,
+	OpalHMI_ERROR_SCOM_FIR,
+	OpalHMI_ERROR_DEBUG_TRIG_FIR,
+	OpalHMI_ERROR_HYP_RESOURCE,
+};
+
+struct OpalHMIEvent {
+	uint8_t		version;	/* 0x00 */
+	uint8_t		severity;	/* 0x01 */
+	uint8_t		type;		/* 0x02 */
+	uint8_t		disposition;	/* 0x03 */
+	uint8_t		reserved_1[4];	/* 0x04 */
+
+	__be64		hmer;
+	/* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */
+	__be64		tfmr;
+};
+
 enum {
 	OPAL_P7IOC_DIAG_TYPE_NONE	= 0,
 	OPAL_P7IOC_DIAG_TYPE_RGC	= 1,
@@ -513,40 +572,40 @@ enum {
 };
 
 struct OpalIoP7IOCErrorData {
-	uint16_t type;
+	__be16 type;
 
 	/* GEM */
-	uint64_t gemXfir;
-	uint64_t gemRfir;
-	uint64_t gemRirqfir;
-	uint64_t gemMask;
-	uint64_t gemRwof;
+	__be64 gemXfir;
+	__be64 gemRfir;
+	__be64 gemRirqfir;
+	__be64 gemMask;
+	__be64 gemRwof;
 
 	/* LEM */
-	uint64_t lemFir;
-	uint64_t lemErrMask;
-	uint64_t lemAction0;
-	uint64_t lemAction1;
-	uint64_t lemWof;
+	__be64 lemFir;
+	__be64 lemErrMask;
+	__be64 lemAction0;
+	__be64 lemAction1;
+	__be64 lemWof;
 
 	union {
 		struct OpalIoP7IOCRgcErrorData {
-			uint64_t rgcStatus;		/* 3E1C10 */
-			uint64_t rgcLdcp;		/* 3E1C18 */
+			__be64 rgcStatus;	/* 3E1C10 */
+			__be64 rgcLdcp;		/* 3E1C18 */
 		}rgc;
 		struct OpalIoP7IOCBiErrorData {
-			uint64_t biLdcp0;		/* 3C0100, 3C0118 */
-			uint64_t biLdcp1;		/* 3C0108, 3C0120 */
-			uint64_t biLdcp2;		/* 3C0110, 3C0128 */
-			uint64_t biFenceStatus;		/* 3C0130, 3C0130 */
+			__be64 biLdcp0;		/* 3C0100, 3C0118 */
+			__be64 biLdcp1;		/* 3C0108, 3C0120 */
+			__be64 biLdcp2;		/* 3C0110, 3C0128 */
+			__be64 biFenceStatus;	/* 3C0130, 3C0130 */
 
-			uint8_t  biDownbound;		/* BI Downbound or Upbound */
+			    u8 biDownbound;	/* BI Downbound or Upbound */
 		}bi;
 		struct OpalIoP7IOCCiErrorData {
-			uint64_t ciPortStatus;		/* 3Dn008 */
-			uint64_t ciPortLdcp;		/* 3Dn010 */
+			__be64 ciPortStatus;	/* 3Dn008 */
+			__be64 ciPortLdcp;	/* 3Dn010 */
 
-			uint8_t	 ciPort;		/* Index of CI port: 0/1 */
+			    u8 ciPort;		/* Index of CI port: 0/1 */
 		}ci;
 	};
 };
@@ -578,60 +637,60 @@ struct OpalIoPhbErrorCommon {
 struct OpalIoP7IOCPhbErrorData {
 	struct OpalIoPhbErrorCommon common;
 
-	uint32_t brdgCtl;
+	__be32 brdgCtl;
 
 	// P7IOC utl regs
-	uint32_t portStatusReg;
-	uint32_t rootCmplxStatus;
-	uint32_t busAgentStatus;
+	__be32 portStatusReg;
+	__be32 rootCmplxStatus;
+	__be32 busAgentStatus;
 
 	// P7IOC cfg regs
-	uint32_t deviceStatus;
-	uint32_t slotStatus;
-	uint32_t linkStatus;
-	uint32_t devCmdStatus;
-	uint32_t devSecStatus;
+	__be32 deviceStatus;
+	__be32 slotStatus;
+	__be32 linkStatus;
+	__be32 devCmdStatus;
+	__be32 devSecStatus;
 
 	// cfg AER regs
-	uint32_t rootErrorStatus;
-	uint32_t uncorrErrorStatus;
-	uint32_t corrErrorStatus;
-	uint32_t tlpHdr1;
-	uint32_t tlpHdr2;
-	uint32_t tlpHdr3;
-	uint32_t tlpHdr4;
-	uint32_t sourceId;
+	__be32 rootErrorStatus;
+	__be32 uncorrErrorStatus;
+	__be32 corrErrorStatus;
+	__be32 tlpHdr1;
+	__be32 tlpHdr2;
+	__be32 tlpHdr3;
+	__be32 tlpHdr4;
+	__be32 sourceId;
 
-	uint32_t rsv3;
+	__be32 rsv3;
 
 	// Record data about the call to allocate a buffer.
-	uint64_t errorClass;
-	uint64_t correlator;
+	__be64 errorClass;
+	__be64 correlator;
 
 	//P7IOC MMIO Error Regs
-	uint64_t p7iocPlssr;                // n120
-	uint64_t p7iocCsr;                  // n110
-	uint64_t lemFir;                    // nC00
-	uint64_t lemErrorMask;              // nC18
-	uint64_t lemWOF;                    // nC40
-	uint64_t phbErrorStatus;            // nC80
-	uint64_t phbFirstErrorStatus;       // nC88
-	uint64_t phbErrorLog0;              // nCC0
-	uint64_t phbErrorLog1;              // nCC8
-	uint64_t mmioErrorStatus;           // nD00
-	uint64_t mmioFirstErrorStatus;      // nD08
-	uint64_t mmioErrorLog0;             // nD40
-	uint64_t mmioErrorLog1;             // nD48
-	uint64_t dma0ErrorStatus;           // nD80
-	uint64_t dma0FirstErrorStatus;      // nD88
-	uint64_t dma0ErrorLog0;             // nDC0
-	uint64_t dma0ErrorLog1;             // nDC8
-	uint64_t dma1ErrorStatus;           // nE00
-	uint64_t dma1FirstErrorStatus;      // nE08
-	uint64_t dma1ErrorLog0;             // nE40
-	uint64_t dma1ErrorLog1;             // nE48
-	uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS];
-	uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
+	__be64 p7iocPlssr;                // n120
+	__be64 p7iocCsr;                  // n110
+	__be64 lemFir;                    // nC00
+	__be64 lemErrorMask;              // nC18
+	__be64 lemWOF;                    // nC40
+	__be64 phbErrorStatus;            // nC80
+	__be64 phbFirstErrorStatus;       // nC88
+	__be64 phbErrorLog0;              // nCC0
+	__be64 phbErrorLog1;              // nCC8
+	__be64 mmioErrorStatus;           // nD00
+	__be64 mmioFirstErrorStatus;      // nD08
+	__be64 mmioErrorLog0;             // nD40
+	__be64 mmioErrorLog1;             // nD48
+	__be64 dma0ErrorStatus;           // nD80
+	__be64 dma0FirstErrorStatus;      // nD88
+	__be64 dma0ErrorLog0;             // nDC0
+	__be64 dma0ErrorLog1;             // nDC8
+	__be64 dma1ErrorStatus;           // nE00
+	__be64 dma1FirstErrorStatus;      // nE08
+	__be64 dma1ErrorLog0;             // nE40
+	__be64 dma1ErrorLog1;             // nE48
+	__be64 pestA[OPAL_P7IOC_NUM_PEST_REGS];
+	__be64 pestB[OPAL_P7IOC_NUM_PEST_REGS];
 };
 
 struct OpalIoPhb3ErrorData {
@@ -758,6 +817,8 @@ int64_t opal_pci_eeh_freeze_status(uint6
 				   __be64 *phb_status);
 int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
 				  uint64_t eeh_action_token);
+int64_t opal_pci_eeh_freeze_set(uint64_t phb_id, uint64_t pe_number,
+				uint64_t eeh_action_token);
 int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
 
 
@@ -768,7 +829,7 @@ int64_t opal_pci_set_phb_mem_window(uint
 				    uint16_t window_num,
 				    uint64_t starting_real_address,
 				    uint64_t starting_pci_address,
-				    uint16_t segment_size);
+				    uint64_t size);
 int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
 				    uint16_t window_type, uint16_t window_num,
 				    uint16_t segment_num);
@@ -860,6 +921,9 @@ int64_t opal_get_param(uint64_t token, u
 int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
 		uint64_t length);
 int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data);
+int64_t opal_handle_hmi(void);
+int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
+int64_t opal_unregister_dump_region(uint32_t id);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
@@ -902,6 +966,8 @@ extern void opal_msglog_init(void);
 
 extern int opal_machine_check(struct pt_regs *regs);
 extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
+extern int opal_hmi_exception_early(struct pt_regs *regs);
+extern int opal_handle_hmi_exception(struct pt_regs *regs);
 
 extern void opal_shutdown(void);
 extern int opal_resync_timebase(void);
@@ -912,6 +978,13 @@ struct opal_sg_list *opal_vmalloc_to_sg_
 					     unsigned long vmalloc_size);
 void opal_free_sg_list(struct opal_sg_list *sg);
 
+/*
+ * Dump region ID range usable by the OS
+ */
+#define OPAL_DUMP_REGION_HOST_START		0x80
+#define OPAL_DUMP_REGION_LOG_BUF		0x80
+#define OPAL_DUMP_REGION_HOST_END		0xFF
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/oprofile_impl.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/oprofile_impl.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/oprofile_impl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/oprofile_impl.h	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,6 @@ struct op_powerpc_model {
 };
 
 extern struct op_powerpc_model op_model_fsl_emb;
-extern struct op_powerpc_model op_model_rs64;
 extern struct op_powerpc_model op_model_power4;
 extern struct op_powerpc_model op_model_7450;
 extern struct op_powerpc_model op_model_cell;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/paca.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/paca.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/paca.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/paca.h	2014-09-28 17:29:07.000000000 -0400
@@ -78,10 +78,6 @@ struct paca_struct {
 	u64 kernel_toc;			/* Kernel TOC address */
 	u64 kernelbase;			/* Base address of kernel */
 	u64 kernel_msr;			/* MSR while running in kernel */
-#ifdef CONFIG_PPC_STD_MMU_64
-	u64 stab_real;			/* Absolute address of segment table */
-	u64 stab_addr;			/* Virtual address of segment table */
-#endif /* CONFIG_PPC_STD_MMU_64 */
 	void *emergency_sp;		/* pointer to emergency stack */
 	u64 data_offset;		/* per cpu data offset */
 	s16 hw_cpu_id;			/* Physical processor number */
@@ -171,6 +167,7 @@ struct paca_struct {
 	 * and already using emergency stack.
 	 */
 	u16 in_mce;
+	u8 hmi_event_available;		 /* HMI event is available */
 #endif
 
 	/* Stuff for accurate time accounting */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,9 +48,6 @@ extern unsigned int HPAGE_SHIFT;
 #define HUGE_MAX_HSTATE		(MMU_PAGE_COUNT-1)
 #endif
 
-/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
-#define __HAVE_ARCH_GATE_AREA		1
-
 /*
  * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we
  * assign PAGE_MASK to a larger type it gets extended the way we want
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/perf_event_server.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/perf_event_server.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/perf_event_server.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/perf_event_server.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@
 #define MAX_EVENT_ALTERNATIVES	8
 #define MAX_LIMITED_HWCOUNTERS	2
 
+struct perf_event;
+
 /*
  * This struct provides the constants and functions needed to
  * describe the PMU on a particular POWER-family CPU.
@@ -30,7 +32,8 @@ struct power_pmu {
 	unsigned long	add_fields;
 	unsigned long	test_adder;
 	int		(*compute_mmcr)(u64 events[], int n_ev,
-				unsigned int hwc[], unsigned long mmcr[]);
+				unsigned int hwc[], unsigned long mmcr[],
+				struct perf_event *pevents[]);
 	int		(*get_constraint)(u64 event_id, unsigned long *mskp,
 				unsigned long *valp);
 	int		(*get_alternatives)(u64 event_id, unsigned int flags,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/pgtable-ppc64.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pgtable-ppc64.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/pgtable-ppc64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pgtable-ppc64.h	2014-09-28 17:29:07.000000000 -0400
@@ -413,7 +413,7 @@ static inline char *get_hpte_slot_array(
 }
 
 extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
-				   pmd_t *pmdp);
+				   pmd_t *pmdp, unsigned long old_pmd);
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot);
 extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/ppc-opcode.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/ppc-opcode.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/ppc-opcode.h	2014-09-28 17:29:07.000000000 -0400
@@ -139,6 +139,7 @@
 #define PPC_INST_ISEL			0x7c00001e
 #define PPC_INST_ISEL_MASK		0xfc00003e
 #define PPC_INST_LDARX			0x7c0000a8
+#define PPC_INST_LOGMPP			0x7c0007e4
 #define PPC_INST_LSWI			0x7c0004aa
 #define PPC_INST_LSWX			0x7c00042a
 #define PPC_INST_LWARX			0x7c000028
@@ -150,8 +151,10 @@
 #define PPC_INST_MCRXR_MASK		0xfc0007fe
 #define PPC_INST_MFSPR_PVR		0x7c1f42a6
 #define PPC_INST_MFSPR_PVR_MASK		0xfc1fffff
+#define PPC_INST_MFTMR			0x7c0002dc
 #define PPC_INST_MSGSND			0x7c00019c
 #define PPC_INST_MSGSNDP		0x7c00011c
+#define PPC_INST_MTTMR			0x7c0003dc
 #define PPC_INST_NOP			0x60000000
 #define PPC_INST_POPCNTB		0x7c0000f4
 #define PPC_INST_POPCNTB_MASK		0xfc0007fe
@@ -275,6 +278,20 @@
 #define __PPC_EH(eh)	0
 #endif
 
+/* POWER8 Micro Partition Prefetch (MPP) parameters */
+/* Address mask is common for LOGMPP instruction and MPPR SPR */
+#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000
+
+/* Bits 60 and 61 of MPP SPR should be set to one of the following */
+/* Aborting the fetch is indeed setting 00 in the table size bits */
+#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
+#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
+
+/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
+#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
+#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
+#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
+
 /* Deal with instructions that older assemblers aren't aware of */
 #define	PPC_DCBAL(a, b)		stringify_in_c(.long PPC_INST_DCBAL | \
 					__PPC_RA(a) | __PPC_RB(b))
@@ -283,6 +300,8 @@
 #define PPC_LDARX(t, a, b, eh)	stringify_in_c(.long PPC_INST_LDARX | \
 					___PPC_RT(t) | ___PPC_RA(a) | \
 					___PPC_RB(b) | __PPC_EH(eh))
+#define PPC_LOGMPP(b)		stringify_in_c(.long PPC_INST_LOGMPP | \
+					__PPC_RB(b))
 #define PPC_LWARX(t, a, b, eh)	stringify_in_c(.long PPC_INST_LWARX | \
 					___PPC_RT(t) | ___PPC_RA(a) | \
 					___PPC_RB(b) | __PPC_EH(eh))
@@ -369,4 +388,11 @@
 #define TABORT(r)		stringify_in_c(.long PPC_INST_TABORT \
 					       | __PPC_RA(r))
 
+/* book3e thread control instructions */
+#define TMRN(x)			((((x) & 0x1f) << 16) | (((x) & 0x3e0) << 6))
+#define MTTMR(tmr, r)		stringify_in_c(.long PPC_INST_MTTMR | \
+					       TMRN(tmr) | ___PPC_RS(r))
+#define MFTMR(tmr, r)		stringify_in_c(.long PPC_INST_MFTMR | \
+					       TMRN(tmr) | ___PPC_RT(r))
+
 #endif /* _ASM_POWERPC_PPC_OPCODE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -400,6 +400,8 @@ 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-3.16-gnu/arch/powerpc/include/asm/pte-fsl-booke.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pte-fsl-booke.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/pte-fsl-booke.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pte-fsl-booke.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,5 +37,7 @@
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD	(~PAGE_MASK)
 
+#define PTE_WIMGE_SHIFT (6)
+
 #endif /* __KERNEL__ */
 #endif /*  _ASM_POWERPC_PTE_FSL_BOOKE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/pte-hash64-64k.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pte-hash64-64k.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/pte-hash64-64k.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/pte-hash64-64k.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,11 +46,31 @@
  * in order to deal with 64K made of 4K HW pages. Thus we override the
  * generic accessors and iterators here
  */
-#define __real_pte(e,p) 	((real_pte_t) { \
-			(e), (pte_val(e) & _PAGE_COMBO) ? \
-				(pte_val(*((p) + PTRS_PER_PTE))) : 0 })
-#define __rpte_to_hidx(r,index)	((pte_val((r).pte) & _PAGE_COMBO) ? \
-        (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
+#define __real_pte __real_pte
+static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep)
+{
+	real_pte_t rpte;
+
+	rpte.pte = pte;
+	rpte.hidx = 0;
+	if (pte_val(pte) & _PAGE_COMBO) {
+		/*
+		 * Make sure we order the hidx load against the _PAGE_COMBO
+		 * check. The store side ordering is done in __hash_page_4K
+		 */
+		smp_rmb();
+		rpte.hidx = pte_val(*((ptep) + PTRS_PER_PTE));
+	}
+	return rpte;
+}
+
+static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
+{
+	if ((pte_val(rpte.pte) & _PAGE_COMBO))
+		return (rpte.hidx >> (index<<2)) & 0xf;
+	return (pte_val(rpte.pte) >> 12) & 0xf;
+}
+
 #define __rpte_to_pte(r)	((r).pte)
 #define __rpte_sub_valid(rpte, index) \
 	(pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index)))
@@ -75,7 +95,8 @@
 	(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
 #define remap_4k_pfn(vma, addr, pfn, prot)				\
-	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,		\
-			__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
+	(WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL :	\
+		remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,	\
+			__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)))
 
 #endif	/* __ASSEMBLY__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,12 @@
 				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
 #define STACK_FRAME_MARKER	12
 
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+#define STACK_FRAME_MIN_SIZE	32
+#else
+#define STACK_FRAME_MIN_SIZE	STACK_FRAME_OVERHEAD
+#endif
+
 /* Size of dummy stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE	128
 #define __SIGNAL_FRAMESIZE32	64
@@ -60,6 +66,7 @@
 #define STACK_FRAME_REGS_MARKER	ASM_CONST(0x72656773)
 #define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
 #define STACK_FRAME_MARKER	2
+#define STACK_FRAME_MIN_SIZE	STACK_FRAME_OVERHEAD
 
 /* Size of stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE	64
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/reg_booke.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/reg_booke.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/reg_booke.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,16 +15,28 @@
 #ifndef __ASM_POWERPC_REG_BOOKE_H__
 #define __ASM_POWERPC_REG_BOOKE_H__
 
+#include <asm/ppc-opcode.h>
+
 /* Machine State Register (MSR) Fields */
-#define MSR_GS		(1<<28) /* Guest state */
-#define MSR_UCLE	(1<<26)	/* User-mode cache lock enable */
-#define MSR_SPE		(1<<25)	/* Enable SPE */
-#define MSR_DWE		(1<<10)	/* Debug Wait Enable */
-#define MSR_UBLE	(1<<10)	/* BTB lock enable (e500) */
-#define MSR_IS		MSR_IR	/* Instruction Space */
-#define MSR_DS		MSR_DR	/* Data Space */
-#define MSR_PMM		(1<<2)	/* Performance monitor mark bit */
-#define MSR_CM		(1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */
+#define MSR_GS_LG	28	/* Guest state */
+#define MSR_UCLE_LG	26	/* User-mode cache lock enable */
+#define MSR_SPE_LG	25	/* Enable SPE */
+#define MSR_DWE_LG	10	/* Debug Wait Enable */
+#define MSR_UBLE_LG	10	/* BTB lock enable (e500) */
+#define MSR_IS_LG	MSR_IR_LG /* Instruction Space */
+#define MSR_DS_LG	MSR_DR_LG /* Data Space */
+#define MSR_PMM_LG	2	/* Performance monitor mark bit */
+#define MSR_CM_LG	31	/* Computation Mode (0=32-bit, 1=64-bit) */
+
+#define MSR_GS		__MASK(MSR_GS_LG)
+#define MSR_UCLE	__MASK(MSR_UCLE_LG)
+#define MSR_SPE		__MASK(MSR_SPE_LG)
+#define MSR_DWE		__MASK(MSR_DWE_LG)
+#define MSR_UBLE	__MASK(MSR_UBLE_LG)
+#define MSR_IS		__MASK(MSR_IS_LG)
+#define MSR_DS		__MASK(MSR_DS_LG)
+#define MSR_PMM		__MASK(MSR_PMM_LG)
+#define MSR_CM		__MASK(MSR_CM_LG)
 
 #if defined(CONFIG_PPC_BOOK3E_64)
 #define MSR_64BIT	MSR_CM
@@ -260,7 +272,7 @@
 
 /* e500mc */
 #define MCSR_DCPERR_MC	0x20000000UL /* D-Cache Parity Error */
-#define MCSR_L2MMU_MHIT	0x04000000UL /* Hit on multiple TLB entries */
+#define MCSR_L2MMU_MHIT	0x08000000UL /* Hit on multiple TLB entries */
 #define MCSR_NMI	0x00100000UL /* Non-Maskable Interrupt */
 #define MCSR_MAV	0x00080000UL /* MCAR address valid */
 #define MCSR_MEA	0x00040000UL /* MCAR is effective address */
@@ -598,6 +610,13 @@
 /* Bit definitions for L1CSR2. */
 #define L1CSR2_DCWS	0x40000000	/* Data Cache write shadow */
 
+/* Bit definitions for BUCSR. */
+#define BUCSR_STAC_EN	0x01000000	/* Segment Target Address Cache */
+#define BUCSR_LS_EN	0x00400000	/* Link Stack */
+#define BUCSR_BBFI	0x00000200	/* Branch Buffer flash invalidate */
+#define BUCSR_BPEN	0x00000001	/* Branch prediction enable */
+#define BUCSR_INIT	(BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN)
+
 /* Bit definitions for L2CSR0. */
 #define L2CSR0_L2E	0x80000000	/* L2 Cache Enable */
 #define L2CSR0_L2PE	0x40000000	/* L2 Cache Parity/ECC Enable */
@@ -721,5 +740,23 @@
 #define MMUBE1_VBE4		0x00000002
 #define MMUBE1_VBE5		0x00000001
 
+#define TMRN_IMSR0	0x120	/* Initial MSR Register 0 (e6500) */
+#define TMRN_IMSR1	0x121	/* Initial MSR Register 1 (e6500) */
+#define TMRN_INIA0	0x140	/* Next Instruction Address Register 0 */
+#define TMRN_INIA1	0x141	/* Next Instruction Address Register 1 */
+#define SPRN_TENSR	0x1b5	/* Thread Enable Status Register */
+#define SPRN_TENS	0x1b6	/* Thread Enable Set Register */
+#define SPRN_TENC	0x1b7	/* Thread Enable Clear Register */
+
+#define TEN_THREAD(x)	(1 << (x))
+
+#ifndef __ASSEMBLY__
+#define mftmr(rn)	({unsigned long rval; \
+			asm volatile(MFTMR(rn, %0) : "=r" (rval)); rval;})
+#define mttmr(rn, v)	asm volatile(MTTMR(rn, %0) : \
+				     : "r" ((unsigned long)(v)) \
+				     : "memory")
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __ASM_POWERPC_REG_BOOKE_H__ */
 #endif /* __KERNEL__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/reg.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -213,9 +213,8 @@
 #define SPRN_ACOP	0x1F	/* Available Coprocessor Register */
 #define SPRN_TFIAR	0x81	/* Transaction Failure Inst Addr   */
 #define SPRN_TEXASR	0x82	/* Transaction EXception & Summary */
-#define   TEXASR_FS	__MASK(63-36)	/* Transaction Failure Summary */
 #define SPRN_TEXASRU	0x83	/* ''	   ''	   ''	 Upper 32  */
-#define   TEXASR_FS     __MASK(63-36) /* TEXASR Failure Summary */
+#define   TEXASR_FS	__MASK(63-36) /* TEXASR Failure Summary */
 #define SPRN_TFHAR	0x80	/* Transaction Failure Handler Addr */
 #define SPRN_CTRLF	0x088
 #define SPRN_CTRLT	0x098
@@ -225,6 +224,7 @@
 #define   CTRL_TE	0x00c00000	/* thread enable */
 #define   CTRL_RUNLATCH	0x1
 #define SPRN_DAWR	0xB4
+#define SPRN_MPPR	0xB8	/* Micro Partition Prefetch Register */
 #define SPRN_RPR	0xBA	/* Relative Priority Register */
 #define SPRN_CIABR	0xBB
 #define   CIABR_PRIV		0x3
@@ -254,7 +254,7 @@
 #define   DSISR_PROTFAULT	0x08000000	/* protection fault */
 #define   DSISR_ISSTORE		0x02000000	/* access was a store */
 #define   DSISR_DABRMATCH	0x00400000	/* hit data breakpoint */
-#define   DSISR_NOSEGMENT	0x00200000	/* STAB/SLB miss */
+#define   DSISR_NOSEGMENT	0x00200000	/* SLB miss */
 #define   DSISR_KEYFAULT	0x00200000	/* Key fault */
 #define SPRN_TBRL	0x10C	/* Time Base Read Lower Register (user, R/O) */
 #define SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
@@ -944,9 +944,6 @@
  *      readable variant for reads, which can avoid a fault
  *      with KVM type virtualization.
  *
- *      (*) Under KVM, the host SPRG1 is used to point to
- *      the current VCPU data structure
- *
  * 32-bit 8xx:
  *	- SPRG0 scratch for exception vectors
  *	- SPRG1 scratch for exception vectors
@@ -1203,6 +1200,15 @@
 				     : "r" ((unsigned long)(v)) \
 				     : "memory")
 
+static inline unsigned long mfvtb (void)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		return mfspr(SPRN_VTB);
+#endif
+	return 0;
+}
+
 #ifdef __powerpc64__
 #if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E)
 #define mftb()		({unsigned long rval;				\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#ifndef _ASM_POWERPC_SCATTERLIST_H
-#define _ASM_POWERPC_SCATTERLIST_H
-/*
- * Copyright (C) 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/dma.h>
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_POWERPC_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/spinlock.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/spinlock.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/spinlock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/spinlock.h	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,7 @@ static __always_inline int arch_spin_val
 
 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
 {
+	smp_mb();
 	return !arch_spin_value_unlocked(*lock);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/systbl.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/systbl.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/systbl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/systbl.h	2014-09-28 17:29:07.000000000 -0400
@@ -77,10 +77,10 @@ SYSCALL_SPU(setreuid)
 SYSCALL_SPU(setregid)
 #define compat_sys_sigsuspend sys_sigsuspend
 SYS32ONLY(sigsuspend)
-COMPAT_SYS(sigpending)
+SYSX(sys_ni_syscall,compat_sys_sigpending,sys_sigpending)
 SYSCALL_SPU(sethostname)
 COMPAT_SYS_SPU(setrlimit)
-COMPAT_SYS(old_getrlimit)
+SYSX(sys_ni_syscall,compat_sys_old_getrlimit,sys_old_getrlimit)
 COMPAT_SYS_SPU(getrusage)
 COMPAT_SYS_SPU(gettimeofday)
 COMPAT_SYS_SPU(settimeofday)
@@ -362,3 +362,6 @@ SYSCALL(ni_syscall) /* sys_kcmp */
 SYSCALL_SPU(sched_setattr)
 SYSCALL_SPU(sched_getattr)
 SYSCALL_SPU(renameat2)
+SYSCALL_SPU(seccomp)
+SYSCALL_SPU(getrandom)
+SYSCALL_SPU(memfd_create)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/time.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/time.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/time.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/time.h	2014-09-28 17:29:07.000000000 -0400
@@ -102,6 +102,15 @@ static inline u64 get_rtc(void)
 	return (u64)hi * 1000000000 + lo;
 }
 
+static inline u64 get_vtb(void)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		return mfvtb();
+#endif
+	return 0;
+}
+
 #ifdef CONFIG_PPC64
 static inline u64 get_tb(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/trace.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/trace.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/trace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/trace.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,51 @@ TRACE_EVENT_FN(hcall_exit,
 );
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+extern void opal_tracepoint_regfunc(void);
+extern void opal_tracepoint_unregfunc(void);
+
+TRACE_EVENT_FN(opal_entry,
+
+	TP_PROTO(unsigned long opcode, unsigned long *args),
+
+	TP_ARGS(opcode, args),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, opcode)
+	),
+
+	TP_fast_assign(
+		__entry->opcode = opcode;
+	),
+
+	TP_printk("opcode=%lu", __entry->opcode),
+
+	opal_tracepoint_regfunc, opal_tracepoint_unregfunc
+);
+
+TRACE_EVENT_FN(opal_exit,
+
+	TP_PROTO(unsigned long opcode, unsigned long retval),
+
+	TP_ARGS(opcode, retval),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, opcode)
+		__field(unsigned long, retval)
+	),
+
+	TP_fast_assign(
+		__entry->opcode = opcode;
+		__entry->retval = retval;
+	),
+
+	TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval),
+
+	opal_tracepoint_regfunc, opal_tracepoint_unregfunc
+);
+#endif
+
 #endif /* _TRACE_POWERPC_H */
 
 #undef TRACE_INCLUDE_PATH
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/unistd.h
--- linux-libre-3.16-gnu/arch/powerpc/include/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls		358
+#define __NR_syscalls		361
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/uapi/asm/kvm.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/uapi/asm/kvm.h
--- linux-libre-3.16-gnu/arch/powerpc/include/uapi/asm/kvm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/uapi/asm/kvm.h	2014-09-28 17:29:07.000000000 -0400
@@ -548,6 +548,7 @@ struct kvm_get_htab_header {
 
 #define KVM_REG_PPC_VRSAVE	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
 #define KVM_REG_PPC_LPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
+#define KVM_REG_PPC_LPCR_64	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
 #define KVM_REG_PPC_PPR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
 
 /* Architecture compatibility level */
@@ -555,6 +556,7 @@ struct kvm_get_htab_header {
 
 #define KVM_REG_PPC_DABRX	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
 #define KVM_REG_PPC_WORT	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
+#define KVM_REG_PPC_SPRG9	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
 
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/powerpc/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/powerpc/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -380,5 +380,8 @@
 #define __NR_sched_setattr	355
 #define __NR_sched_getattr	356
 #define __NR_renameat2		357
+#define __NR_seccomp		358
+#define __NR_getrandom		359
+#define __NR_memfd_create	360
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/Kconfig linux-libre-3.17-rc7-gnu/arch/powerpc/Kconfig
--- linux-libre-3.16-gnu/arch/powerpc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -111,6 +111,7 @@ config PPC
 	select HAVE_DMA_API_DEBUG
 	select HAVE_OPROFILE
 	select HAVE_DEBUG_KMEMLEAK
+	select ARCH_HAS_SG_CHAIN
 	select GENERIC_ATOMIC64 if PPC32
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select HAVE_PERF_EVENTS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/Kconfig.debug linux-libre-3.17-rc7-gnu/arch/powerpc/Kconfig.debug
--- linux-libre-3.16-gnu/arch/powerpc/Kconfig.debug	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/Kconfig.debug	2014-09-28 17:29:07.000000000 -0400
@@ -202,9 +202,7 @@ config PPC_EARLY_DEBUG_BEAT
 
 config PPC_EARLY_DEBUG_44x
 	bool "Early serial debugging for IBM/AMCC 44x CPUs"
-	# PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
-	# mark, which doesn't work with current 440 KVM.
-	depends on 44x && !KVM
+	depends on 44x
 	help
 	  Select this to enable early debugging for IBM 44x chips via the
 	  inbuilt serial port.  If you enable this, ensure you set
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/asm-offsets.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/asm-offsets.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/asm-offsets.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,8 +216,6 @@ int main(void)
 #endif /* CONFIG_PPC_BOOK3E */
 
 #ifdef CONFIG_PPC_STD_MMU_64
-	DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real));
-	DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr));
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
 	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
 	DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
@@ -493,6 +491,7 @@ int main(void)
 	DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
 	DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
 	DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
+	DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
 	DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
 	DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
 	DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
@@ -667,6 +666,7 @@ int main(void)
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
 	DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
+	DEFINE(VCPU_SPRG9, offsetof(struct kvm_vcpu, arch.sprg9));
 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
 	DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
 	DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/cputable.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/cputable.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/cputable.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/cputable.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,96 +123,6 @@ extern void __restore_cpu_e6500(void);
 
 static struct cpu_spec __initdata cpu_specs[] = {
 #ifdef CONFIG_PPC_BOOK3S_64
-	{	/* Power3 */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00400000,
-		.cpu_name		= "POWER3 (630)",
-		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/power3",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "power3",
-	},
-	{	/* Power3+ */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00410000,
-		.cpu_name		= "POWER3 (630+)",
-		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/power3",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "power3",
-	},
-	{	/* Northstar */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00330000,
-		.cpu_name		= "RS64-II (northstar)",
-		.cpu_features		= CPU_FTRS_RS64,
-		.cpu_user_features	= COMMON_USER_PPC64,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/rs64",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "rs64",
-	},
-	{	/* Pulsar */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00340000,
-		.cpu_name		= "RS64-III (pulsar)",
-		.cpu_features		= CPU_FTRS_RS64,
-		.cpu_user_features	= COMMON_USER_PPC64,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/rs64",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "rs64",
-	},
-	{	/* I-star */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00360000,
-		.cpu_name		= "RS64-III (icestar)",
-		.cpu_features		= CPU_FTRS_RS64,
-		.cpu_user_features	= COMMON_USER_PPC64,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/rs64",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "rs64",
-	},
-	{	/* S-star */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x00370000,
-		.cpu_name		= "RS64-IV (sstar)",
-		.cpu_features		= CPU_FTRS_RS64,
-		.cpu_user_features	= COMMON_USER_PPC64,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
-		.icache_bsize		= 128,
-		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
-		.pmc_type		= PPC_PMC_IBM,
-		.oprofile_cpu_type	= "ppc64/rs64",
-		.oprofile_type		= PPC_OPROFILE_RS64,
-		.platform		= "rs64",
-	},
 	{	/* Power4 */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00350000,
@@ -617,7 +527,7 @@ static struct cpu_spec __initdata cpu_sp
 #endif	/* CONFIG_PPC_BOOK3S_64 */
 
 #ifdef CONFIG_PPC32
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
 	{	/* 601 */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00010000,
@@ -1257,7 +1167,7 @@ static struct cpu_spec __initdata cpu_sp
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc603",
 	},
-#endif /* CLASSIC_PPC */
+#endif /* CONFIG_PPC_BOOK3S_32 */
 #ifdef CONFIG_8xx
 	{	/* 8xx */
 		.pvr_mask		= 0xffff0000,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/eeh.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/eeh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/iommu.h>
 #include <linux/proc_fs.h>
 #include <linux/rbtree.h>
 #include <linux/reboot.h>
@@ -40,6 +41,7 @@
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
 #include <asm/io.h>
+#include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
 #include <asm/rtas.h>
@@ -108,6 +110,9 @@ struct eeh_ops *eeh_ops = NULL;
 /* Lock to avoid races due to multiple reports of an error */
 DEFINE_RAW_SPINLOCK(confirm_error_lock);
 
+/* Lock to protect passed flags */
+static DEFINE_MUTEX(eeh_dev_mutex);
+
 /* Buffer for reporting pci register dumps. Its here in BSS, and
  * not dynamically alloced, so that it ends up in RMO where RTAS
  * can access it.
@@ -137,7 +142,7 @@ static struct eeh_stats eeh_stats;
 static int __init eeh_setup(char *str)
 {
 	if (!strcmp(str, "off"))
-		eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+		eeh_add_flag(EEH_FORCE_DISABLED);
 
 	return 1;
 }
@@ -152,12 +157,13 @@ __setup("eeh=", eeh_setup);
  * This routine captures assorted PCI configuration space data,
  * and puts them into a buffer for RTAS error logging.
  */
-static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
+static size_t eeh_gather_pci_data(struct eeh_dev *edev, char *buf, size_t len)
 {
 	struct device_node *dn = eeh_dev_to_of_node(edev);
 	u32 cfg;
 	int cap, i;
-	int n = 0;
+	int n = 0, l = 0;
+	char buffer[128];
 
 	n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
 	pr_warn("EEH: of node=%s\n", dn->full_name);
@@ -202,8 +208,22 @@ static size_t eeh_gather_pci_data(struct
 		for (i=0; i<=8; i++) {
 			eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
 			n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
-			pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg);
+
+			if ((i % 4) == 0) {
+				if (i != 0)
+					pr_warn("%s\n", buffer);
+
+				l = scnprintf(buffer, sizeof(buffer),
+					      "EEH: PCI-E %02x: %08x ",
+					      4*i, cfg);
+			} else {
+				l += scnprintf(buffer+l, sizeof(buffer)-l,
+					       "%08x ", cfg);
+			}
+
 		}
+
+		pr_warn("%s\n", buffer);
 	}
 
 	/* If AER capable, dump it */
@@ -212,11 +232,24 @@ static size_t eeh_gather_pci_data(struct
 		n += scnprintf(buf+n, len-n, "pci-e AER:\n");
 		pr_warn("EEH: PCI-E AER capability register set follows:\n");
 
-		for (i=0; i<14; i++) {
+		for (i=0; i<=13; i++) {
 			eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
 			n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
-			pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg);
+
+			if ((i % 4) == 0) {
+				if (i != 0)
+					pr_warn("%s\n", buffer);
+
+				l = scnprintf(buffer, sizeof(buffer),
+					      "EEH: PCI-E AER %02x: %08x ",
+					      4*i, cfg);
+			} else {
+				l += scnprintf(buffer+l, sizeof(buffer)-l,
+					       "%08x ", cfg);
+			}
 		}
+
+		pr_warn("%s\n", buffer);
 	}
 
 	return n;
@@ -247,7 +280,7 @@ void eeh_slot_error_detail(struct eeh_pe
 	 * 0xFF's is always returned from PCI config space.
 	 */
 	if (!(pe->type & EEH_PE_PHB)) {
-		if (eeh_probe_mode_devtree())
+		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
 			eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 		eeh_ops->configure_bridge(pe);
 		eeh_pe_restore_bars(pe);
@@ -298,14 +331,14 @@ static int eeh_phb_check_failure(struct
 	unsigned long flags;
 	int ret;
 
-	if (!eeh_probe_mode_dev())
+	if (!eeh_has_flag(EEH_PROBE_MODE_DEV))
 		return -EPERM;
 
 	/* Find the PHB PE */
 	phb_pe = eeh_phb_pe_get(pe->phb);
 	if (!phb_pe) {
-		pr_warning("%s Can't find PE for PHB#%d\n",
-			   __func__, pe->phb->global_number);
+		pr_warn("%s Can't find PE for PHB#%d\n",
+			__func__, pe->phb->global_number);
 		return -EEXIST;
 	}
 
@@ -400,6 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev
 	if (ret > 0)
 		return ret;
 
+	/*
+	 * If the PE isn't owned by us, we shouldn't check the
+	 * state. Instead, let the owner handle it if the PE has
+	 * been frozen.
+	 */
+	if (eeh_pe_passed(pe))
+		return 0;
+
 	/* If we already have a pending isolation event for this
 	 * slot, we know it's bad already, we don't need to check.
 	 * Do this checking under a lock; as multiple PCI devices
@@ -746,13 +787,13 @@ void eeh_save_bars(struct eeh_dev *edev)
 int __init eeh_ops_register(struct eeh_ops *ops)
 {
 	if (!ops->name) {
-		pr_warning("%s: Invalid EEH ops name for %p\n",
+		pr_warn("%s: Invalid EEH ops name for %p\n",
 			__func__, ops);
 		return -EINVAL;
 	}
 
 	if (eeh_ops && eeh_ops != ops) {
-		pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
+		pr_warn("%s: EEH ops of platform %s already existing (%s)\n",
 			__func__, eeh_ops->name, ops->name);
 		return -EEXIST;
 	}
@@ -772,7 +813,7 @@ int __init eeh_ops_register(struct eeh_o
 int __exit eeh_ops_unregister(const char *name)
 {
 	if (!name || !strlen(name)) {
-		pr_warning("%s: Invalid EEH ops name\n",
+		pr_warn("%s: Invalid EEH ops name\n",
 			__func__);
 		return -EINVAL;
 	}
@@ -788,7 +829,7 @@ int __exit eeh_ops_unregister(const char
 static int eeh_reboot_notifier(struct notifier_block *nb,
 			       unsigned long action, void *unused)
 {
-	eeh_set_enable(false);
+	eeh_clear_flag(EEH_ENABLED);
 	return NOTIFY_DONE;
 }
 
@@ -837,11 +878,11 @@ int eeh_init(void)
 
 	/* call platform initialization function */
 	if (!eeh_ops) {
-		pr_warning("%s: Platform EEH operation not found\n",
+		pr_warn("%s: Platform EEH operation not found\n",
 			__func__);
 		return -EEXIST;
 	} else if ((ret = eeh_ops->init())) {
-		pr_warning("%s: Failed to call platform init function (%d)\n",
+		pr_warn("%s: Failed to call platform init function (%d)\n",
 			__func__, ret);
 		return ret;
 	}
@@ -852,13 +893,13 @@ int eeh_init(void)
 		return ret;
 
 	/* Enable EEH for all adapters */
-	if (eeh_probe_mode_devtree()) {
+	if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) {
 		list_for_each_entry_safe(hose, tmp,
 			&hose_list, list_node) {
 			phb = hose->dn;
 			traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
 		}
-	} else if (eeh_probe_mode_dev()) {
+	} else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) {
 		list_for_each_entry_safe(hose, tmp,
 			&hose_list, list_node)
 			pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL);
@@ -882,7 +923,7 @@ int eeh_init(void)
 	if (eeh_enabled())
 		pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
 	else
-		pr_warning("EEH: No capable adapters found\n");
+		pr_warn("EEH: No capable adapters found\n");
 
 	return ret;
 }
@@ -910,7 +951,7 @@ void eeh_add_device_early(struct device_
 	 * would delay the probe until late stage because
 	 * the PCI device isn't available this moment.
 	 */
-	if (!eeh_probe_mode_devtree())
+	if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
 		return;
 
 	if (!of_node_to_eeh_dev(dn))
@@ -996,7 +1037,7 @@ void eeh_add_device_late(struct pci_dev
 	 * We have to do the EEH probe here because the PCI device
 	 * hasn't been created yet in the early stage.
 	 */
-	if (eeh_probe_mode_dev())
+	if (eeh_has_flag(EEH_PROBE_MODE_DEV))
 		eeh_ops->dev_probe(dev, NULL);
 
 	eeh_addr_cache_insert_dev(dev);
@@ -1100,6 +1141,285 @@ void eeh_remove_device(struct pci_dev *d
 	edev->mode &= ~EEH_DEV_SYSFS;
 }
 
+/**
+ * eeh_dev_open - Increase count of pass through devices for PE
+ * @pdev: PCI device
+ *
+ * Increase count of passed through devices for the indicated
+ * PE. In the result, the EEH errors detected on the PE won't be
+ * reported. The PE owner will be responsible for detection
+ * and recovery.
+ */
+int eeh_dev_open(struct pci_dev *pdev)
+{
+	struct eeh_dev *edev;
+
+	mutex_lock(&eeh_dev_mutex);
+
+	/* No PCI device ? */
+	if (!pdev)
+		goto out;
+
+	/* No EEH device or PE ? */
+	edev = pci_dev_to_eeh_dev(pdev);
+	if (!edev || !edev->pe)
+		goto out;
+
+	/* Increase PE's pass through count */
+	atomic_inc(&edev->pe->pass_dev_cnt);
+	mutex_unlock(&eeh_dev_mutex);
+
+	return 0;
+out:
+	mutex_unlock(&eeh_dev_mutex);
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(eeh_dev_open);
+
+/**
+ * eeh_dev_release - Decrease count of pass through devices for PE
+ * @pdev: PCI device
+ *
+ * Decrease count of pass through devices for the indicated PE. If
+ * there is no passed through device in PE, the EEH errors detected
+ * on the PE will be reported and handled as usual.
+ */
+void eeh_dev_release(struct pci_dev *pdev)
+{
+	struct eeh_dev *edev;
+
+	mutex_lock(&eeh_dev_mutex);
+
+	/* No PCI device ? */
+	if (!pdev)
+		goto out;
+
+	/* No EEH device ? */
+	edev = pci_dev_to_eeh_dev(pdev);
+	if (!edev || !edev->pe || !eeh_pe_passed(edev->pe))
+		goto out;
+
+	/* Decrease PE's pass through count */
+	atomic_dec(&edev->pe->pass_dev_cnt);
+	WARN_ON(atomic_read(&edev->pe->pass_dev_cnt) < 0);
+out:
+	mutex_unlock(&eeh_dev_mutex);
+}
+EXPORT_SYMBOL(eeh_dev_release);
+
+#ifdef CONFIG_IOMMU_API
+
+static int dev_has_iommu_table(struct device *dev, void *data)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pci_dev **ppdev = data;
+	struct iommu_table *tbl;
+
+	if (!dev)
+		return 0;
+
+	tbl = get_iommu_table_base(dev);
+	if (tbl && tbl->it_group) {
+		*ppdev = pdev;
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * eeh_iommu_group_to_pe - Convert IOMMU group to EEH PE
+ * @group: IOMMU group
+ *
+ * The routine is called to convert IOMMU group to EEH PE.
+ */
+struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group)
+{
+	struct pci_dev *pdev = NULL;
+	struct eeh_dev *edev;
+	int ret;
+
+	/* No IOMMU group ? */
+	if (!group)
+		return NULL;
+
+	ret = iommu_group_for_each_dev(group, &pdev, dev_has_iommu_table);
+	if (!ret || !pdev)
+		return NULL;
+
+	/* No EEH device or PE ? */
+	edev = pci_dev_to_eeh_dev(pdev);
+	if (!edev || !edev->pe)
+		return NULL;
+
+	return edev->pe;
+}
+EXPORT_SYMBOL_GPL(eeh_iommu_group_to_pe);
+
+#endif /* CONFIG_IOMMU_API */
+
+/**
+ * eeh_pe_set_option - Set options for the indicated PE
+ * @pe: EEH PE
+ * @option: requested option
+ *
+ * The routine is called to enable or disable EEH functionality
+ * on the indicated PE, to enable IO or DMA for the frozen PE.
+ */
+int eeh_pe_set_option(struct eeh_pe *pe, int option)
+{
+	int ret = 0;
+
+	/* Invalid PE ? */
+	if (!pe)
+		return -ENODEV;
+
+	/*
+	 * EEH functionality could possibly be disabled, just
+	 * return error for the case. And the EEH functinality
+	 * isn't expected to be disabled on one specific PE.
+	 */
+	switch (option) {
+	case EEH_OPT_ENABLE:
+		if (eeh_enabled())
+			break;
+		ret = -EIO;
+		break;
+	case EEH_OPT_DISABLE:
+		break;
+	case EEH_OPT_THAW_MMIO:
+	case EEH_OPT_THAW_DMA:
+		if (!eeh_ops || !eeh_ops->set_option) {
+			ret = -ENOENT;
+			break;
+		}
+
+		ret = eeh_ops->set_option(pe, option);
+		break;
+	default:
+		pr_debug("%s: Option %d out of range (%d, %d)\n",
+			__func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_set_option);
+
+/**
+ * eeh_pe_get_state - Retrieve PE's state
+ * @pe: EEH PE
+ *
+ * Retrieve the PE's state, which includes 3 aspects: enabled
+ * DMA, enabled IO and asserted reset.
+ */
+int eeh_pe_get_state(struct eeh_pe *pe)
+{
+	int result, ret = 0;
+	bool rst_active, dma_en, mmio_en;
+
+	/* Existing PE ? */
+	if (!pe)
+		return -ENODEV;
+
+	if (!eeh_ops || !eeh_ops->get_state)
+		return -ENOENT;
+
+	result = eeh_ops->get_state(pe, NULL);
+	rst_active = !!(result & EEH_STATE_RESET_ACTIVE);
+	dma_en = !!(result & EEH_STATE_DMA_ENABLED);
+	mmio_en = !!(result & EEH_STATE_MMIO_ENABLED);
+
+	if (rst_active)
+		ret = EEH_PE_STATE_RESET;
+	else if (dma_en && mmio_en)
+		ret = EEH_PE_STATE_NORMAL;
+	else if (!dma_en && !mmio_en)
+		ret = EEH_PE_STATE_STOPPED_IO_DMA;
+	else if (!dma_en && mmio_en)
+		ret = EEH_PE_STATE_STOPPED_DMA;
+	else
+		ret = EEH_PE_STATE_UNAVAIL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_get_state);
+
+/**
+ * eeh_pe_reset - Issue PE reset according to specified type
+ * @pe: EEH PE
+ * @option: reset type
+ *
+ * The routine is called to reset the specified PE with the
+ * indicated type, either fundamental reset or hot reset.
+ * PE reset is the most important part for error recovery.
+ */
+int eeh_pe_reset(struct eeh_pe *pe, int option)
+{
+	int ret = 0;
+
+	/* Invalid PE ? */
+	if (!pe)
+		return -ENODEV;
+
+	if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset)
+		return -ENOENT;
+
+	switch (option) {
+	case EEH_RESET_DEACTIVATE:
+		ret = eeh_ops->reset(pe, option);
+		if (ret)
+			break;
+
+		/*
+		 * The PE is still in frozen state and we need to clear
+		 * that. It's good to clear frozen state after deassert
+		 * to avoid messy IO access during reset, which might
+		 * cause recursive frozen PE.
+		 */
+		ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
+		if (!ret)
+			ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
+		if (!ret)
+			eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
+		break;
+	case EEH_RESET_HOT:
+	case EEH_RESET_FUNDAMENTAL:
+		ret = eeh_ops->reset(pe, option);
+		break;
+	default:
+		pr_debug("%s: Unsupported option %d\n",
+			__func__, option);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_reset);
+
+/**
+ * eeh_pe_configure - Configure PCI bridges after PE reset
+ * @pe: EEH PE
+ *
+ * The routine is called to restore the PCI config space for
+ * those PCI devices, especially PCI bridges affected by PE
+ * reset issued previously.
+ */
+int eeh_pe_configure(struct eeh_pe *pe)
+{
+	int ret = 0;
+
+	/* Invalid PE ? */
+	if (!pe)
+		return -ENODEV;
+
+	/* Restore config space for the affected devices */
+	eeh_pe_restore_bars(pe);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_configure);
+
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
 	if (!eeh_enabled()) {
@@ -1143,9 +1463,9 @@ static const struct file_operations proc
 static int eeh_enable_dbgfs_set(void *data, u64 val)
 {
 	if (val)
-		eeh_subsystem_flags &= ~EEH_FORCE_DISABLED;
+		eeh_clear_flag(EEH_FORCE_DISABLED);
 	else
-		eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+		eeh_add_flag(EEH_FORCE_DISABLED);
 
 	/* Notify the backend */
 	if (eeh_ops->post_init)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_cache.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_cache.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,7 +143,7 @@ eeh_addr_cache_insert(struct pci_dev *de
 		} else {
 			if (dev != piar->pcidev ||
 			    alo != piar->addr_lo || ahi != piar->addr_hi) {
-				pr_warning("PIAR: overlapping address range\n");
+				pr_warn("PIAR: overlapping address range\n");
 			}
 			return piar;
 		}
@@ -177,19 +177,20 @@ static void __eeh_addr_cache_insert_dev(
 
 	dn = pci_device_to_OF_node(dev);
 	if (!dn) {
-		pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev));
+		pr_warn("PCI: no pci dn found for dev=%s\n",
+			pci_name(dev));
 		return;
 	}
 
 	edev = of_node_to_eeh_dev(dn);
 	if (!edev) {
-		pr_warning("PCI: no EEH dev found for dn=%s\n",
+		pr_warn("PCI: no EEH dev found for dn=%s\n",
 			dn->full_name);
 		return;
 	}
 
 	/* Skip any devices for which EEH is not enabled. */
-	if (!eeh_probe_mode_dev() && !edev->pe) {
+	if (!edev->pe) {
 #ifdef DEBUG
 		pr_info("PCI: skip building address cache for=%s - %s\n",
 			pci_name(dev), dn->full_name);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_dev.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_dev.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,8 @@ void *eeh_dev_init(struct device_node *d
 	/* Allocate EEH device */
 	edev = kzalloc(sizeof(*edev), GFP_KERNEL);
 	if (!edev) {
-		pr_warning("%s: out of memory\n", __func__);
+		pr_warn("%s: out of memory\n",
+			__func__);
 		return NULL;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_driver.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_driver.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -599,7 +599,7 @@ static void eeh_handle_normal_event(stru
 	pe->freeze_count++;
 	if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES)
 		goto excess_failures;
-	pr_warning("EEH: This PCI device has failed %d times in the last hour\n",
+	pr_warn("EEH: This PCI device has failed %d times in the last hour\n",
 		pe->freeze_count);
 
 	/* Walk the various device drivers attached to this slot through
@@ -616,7 +616,7 @@ static void eeh_handle_normal_event(stru
 	 */
 	rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000);
 	if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {
-		pr_warning("EEH: Permanent failure\n");
+		pr_warn("EEH: Permanent failure\n");
 		goto hard_fail;
 	}
 
@@ -635,8 +635,8 @@ static void eeh_handle_normal_event(stru
 		pr_info("EEH: Reset with hotplug activity\n");
 		rc = eeh_reset_device(pe, frozen_bus);
 		if (rc) {
-			pr_warning("%s: Unable to reset, err=%d\n",
-				   __func__, rc);
+			pr_warn("%s: Unable to reset, err=%d\n",
+				__func__, rc);
 			goto hard_fail;
 		}
 	}
@@ -678,7 +678,7 @@ static void eeh_handle_normal_event(stru
 
 	/* If any device has a hard failure, then shut off everything. */
 	if (result == PCI_ERS_RESULT_DISCONNECT) {
-		pr_warning("EEH: Device driver gave up\n");
+		pr_warn("EEH: Device driver gave up\n");
 		goto hard_fail;
 	}
 
@@ -687,8 +687,8 @@ static void eeh_handle_normal_event(stru
 		pr_info("EEH: Reset without hotplug activity\n");
 		rc = eeh_reset_device(pe, NULL);
 		if (rc) {
-			pr_warning("%s: Cannot reset, err=%d\n",
-				   __func__, rc);
+			pr_warn("%s: Cannot reset, err=%d\n",
+				__func__, rc);
 			goto hard_fail;
 		}
 
@@ -701,7 +701,7 @@ static void eeh_handle_normal_event(stru
 	/* All devices should claim they have recovered by now. */
 	if ((result != PCI_ERS_RESULT_RECOVERED) &&
 	    (result != PCI_ERS_RESULT_NONE)) {
-		pr_warning("EEH: Not recovered\n");
+		pr_warn("EEH: Not recovered\n");
 		goto hard_fail;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_pe.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_pe.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/eeh_pe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/eeh_pe.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,9 +32,24 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
+static int eeh_pe_aux_size = 0;
 static LIST_HEAD(eeh_phb_pe);
 
 /**
+ * eeh_set_pe_aux_size - Set PE auxillary data size
+ * @size: PE auxillary data size
+ *
+ * Set PE auxillary data size
+ */
+void eeh_set_pe_aux_size(int size)
+{
+	if (size < 0)
+		return;
+
+	eeh_pe_aux_size = size;
+}
+
+/**
  * eeh_pe_alloc - Allocate PE
  * @phb: PCI controller
  * @type: PE type
@@ -44,9 +59,16 @@ static LIST_HEAD(eeh_phb_pe);
 static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
 {
 	struct eeh_pe *pe;
+	size_t alloc_size;
+
+	alloc_size = sizeof(struct eeh_pe);
+	if (eeh_pe_aux_size) {
+		alloc_size = ALIGN(alloc_size, cache_line_size());
+		alloc_size += eeh_pe_aux_size;
+	}
 
 	/* Allocate PHB PE */
-	pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
+	pe = kzalloc(alloc_size, GFP_KERNEL);
 	if (!pe) return NULL;
 
 	/* Initialize PHB PE */
@@ -56,6 +78,8 @@ static struct eeh_pe *eeh_pe_alloc(struc
 	INIT_LIST_HEAD(&pe->child);
 	INIT_LIST_HEAD(&pe->edevs);
 
+	pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe),
+				      cache_line_size());
 	return pe;
 }
 
@@ -179,7 +203,8 @@ void *eeh_pe_dev_traverse(struct eeh_pe
 	void *ret;
 
 	if (!root) {
-		pr_warning("%s: Invalid PE %p\n", __func__, root);
+		pr_warn("%s: Invalid PE %p\n",
+			__func__, root);
 		return NULL;
 	}
 
@@ -351,17 +376,6 @@ int eeh_add_to_parent_pe(struct eeh_dev
 	pe->config_addr	= edev->config_addr;
 
 	/*
-	 * While doing PE reset, we probably hot-reset the
-	 * upstream bridge. However, the PCI devices including
-	 * the associated EEH devices might be removed when EEH
-	 * core is doing recovery. So that won't safe to retrieve
-	 * the bridge through downstream EEH device. We have to
-	 * trace the parent PCI bus, then the upstream bridge.
-	 */
-	if (eeh_probe_mode_dev())
-		pe->bus = eeh_dev_to_pci_dev(edev)->bus;
-
-	/*
 	 * Put the new EEH PE into hierarchy tree. If the parent
 	 * can't be found, the newly created PE will be attached
 	 * to PHB directly. Otherwise, we have to associate the
@@ -802,53 +816,33 @@ void eeh_pe_restore_bars(struct eeh_pe *
  */
 const char *eeh_pe_loc_get(struct eeh_pe *pe)
 {
-	struct pci_controller *hose;
 	struct pci_bus *bus = eeh_pe_bus_get(pe);
-	struct pci_dev *pdev;
-	struct device_node *dn;
-	const char *loc;
+	struct device_node *dn = pci_bus_to_OF_node(bus);
+	const char *loc = NULL;
 
-	if (!bus)
-		return "N/A";
+	if (!dn)
+		goto out;
 
 	/* PHB PE or root PE ? */
 	if (pci_is_root_bus(bus)) {
-		hose = pci_bus_to_host(bus);
-		loc = of_get_property(hose->dn,
-				"ibm,loc-code", NULL);
-		if (loc)
-			return loc;
-		loc = of_get_property(hose->dn,
-				"ibm,io-base-loc-code", NULL);
+		loc = of_get_property(dn, "ibm,loc-code", NULL);
+		if (!loc)
+			loc = of_get_property(dn, "ibm,io-base-loc-code", NULL);
 		if (loc)
-			return loc;
-
-		pdev = pci_get_slot(bus, 0x0);
-	} else {
-		pdev = bus->self;
-	}
-
-	if (!pdev) {
-		loc = "N/A";
-		goto out;
-	}
+			goto out;
 
-	dn = pci_device_to_OF_node(pdev);
-	if (!dn) {
-		loc = "N/A";
-		goto out;
+		/* Check the root port */
+		dn = dn->child;
+		if (!dn)
+			goto out;
 	}
 
 	loc = of_get_property(dn, "ibm,loc-code", NULL);
 	if (!loc)
 		loc = of_get_property(dn, "ibm,slot-location-code", NULL);
-	if (!loc)
-		loc = "N/A";
 
 out:
-	if (pci_is_root_bus(bus) && pdev)
-		pci_dev_put(pdev);
-	return loc;
+	return loc ? loc : "N/A";
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/entry_64.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/entry_64.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/entry_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/entry_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -482,16 +482,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECK
 	ld	r8,KSP(r4)	/* new stack pointer */
 #ifdef CONFIG_PPC_BOOK3S
 BEGIN_FTR_SECTION
-  BEGIN_FTR_SECTION_NESTED(95)
 	clrrdi	r6,r8,28	/* get its ESID */
 	clrrdi	r9,r1,28	/* get current sp ESID */
-  FTR_SECTION_ELSE_NESTED(95)
+FTR_SECTION_ELSE
 	clrrdi	r6,r8,40	/* get its 1T ESID */
 	clrrdi	r9,r1,40	/* get current sp 1T ESID */
-  ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(MMU_FTR_1T_SEGMENT, 95)
-FTR_SECTION_ELSE
-	b	2f
-ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_SLB)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_1T_SEGMENT)
 	clrldi.	r0,r6,2		/* is new ESID c00000000? */
 	cmpd	cr1,r6,r9	/* or is new ESID the same as current ESID? */
 	cror	eq,4*cr1+eq,eq
@@ -919,6 +915,11 @@ restore_check_irq_replay:
 	addi	r3,r1,STACK_FRAME_OVERHEAD;
  	bl	do_IRQ
 	b	ret_from_except
+1:	cmpwi	cr0,r3,0xe60
+	bne	1f
+	addi	r3,r1,STACK_FRAME_OVERHEAD;
+	bl	handle_hmi_exception
+	b	ret_from_except
 1:	cmpwi	cr0,r3,0x900
 	bne	1f
 	addi	r3,r1,STACK_FRAME_OVERHEAD;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/exceptions-64s.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/exceptions-64s.S	2014-09-28 17:29:07.000000000 -0400
@@ -188,10 +188,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE
 data_access_pSeries:
 	HMT_MEDIUM_PPR_DISCARD
 	SET_SCRATCH0(r13)
-BEGIN_FTR_SECTION
-	b	data_access_check_stab
-data_access_not_stab:
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
 				 KVMTEST, 0x300)
 
@@ -339,7 +335,7 @@ emulation_assist_trampoline:
 hv_exception_trampoline:
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	hmi_exception_hv
+	b	hmi_exception_early
 
 	. = 0xe80
 hv_doorbell_trampoline:
@@ -514,34 +510,6 @@ machine_check_pSeries_0:
 	EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200)
 	EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD)
 	KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
-
-	/* moved from 0x300 */
-data_access_check_stab:
-	GET_PACA(r13)
-	std	r9,PACA_EXSLB+EX_R9(r13)
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	mfspr	r10,SPRN_DAR
-	mfspr	r9,SPRN_DSISR
-	srdi	r10,r10,60
-	rlwimi	r10,r9,16,0x20
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
-	lbz	r9,HSTATE_IN_GUEST(r13)
-	rlwimi	r10,r9,8,0x300
-#endif
-	mfcr	r9
-	cmpwi	r10,0x2c
-	beq	do_stab_bolted_pSeries
-	mtcrf	0x80,r9
-	ld	r9,PACA_EXSLB+EX_R9(r13)
-	ld	r10,PACA_EXSLB+EX_R10(r13)
-	b	data_access_not_stab
-do_stab_bolted_pSeries:
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	GET_SCRATCH0(r10)
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	EXCEPTION_PROLOG_PSERIES_1(do_stab_bolted, EXC_STD)
-
 	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
 	KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
@@ -621,8 +589,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22)
 	STD_EXCEPTION_HV_OOL(0xe42, emulation_assist)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42)
-	STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */
+	MASKABLE_EXCEPTION_HV_OOL(0xe62, hmi_exception)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62)
+
 	MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82)
 
@@ -643,6 +612,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
  * - If it was a decrementer interrupt, we bump the dec to max and and return.
  * - If it was a doorbell we return immediately since doorbells are edge
  *   triggered and won't automatically refire.
+ * - If it was a HMI we return immediately since we handled it in realmode
+ *   and it won't refire.
  * - else we hard disable and return.
  * This is called with r10 containing the value to OR to the paca field.
  */
@@ -660,6 +631,8 @@ masked_##_H##interrupt:					\
 	b	2f;					\
 1:	cmpwi	r10,PACA_IRQ_DBELL;			\
 	beq	2f;					\
+	cmpwi	r10,PACA_IRQ_HMI;			\
+	beq	2f;					\
 	mfspr	r10,SPRN_##_H##SRR1;			\
 	rldicl	r10,r10,48,1; /* clear MSR_EE */	\
 	rotldi	r10,r10,16;				\
@@ -799,7 +772,7 @@ kvmppc_skip_Hinterrupt:
 	STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception)
 	STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception)
 	STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt)
-	STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception)
+	STD_EXCEPTION_COMMON_ASYNC(0xe60, hmi_exception, handle_hmi_exception)
 #ifdef CONFIG_PPC_DOORBELL
 	STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception)
 #else
@@ -985,66 +958,6 @@ ppc64_runlatch_on_trampoline:
 	b	__ppc64_runlatch_on
 
 /*
- * Here we have detected that the kernel stack pointer is bad.
- * R9 contains the saved CR, r13 points to the paca,
- * r10 contains the (bad) kernel stack pointer,
- * r11 and r12 contain the saved SRR0 and SRR1.
- * We switch to using an emergency stack, save the registers there,
- * and call kernel_bad_stack(), which panics.
- */
-bad_stack:
-	ld	r1,PACAEMERGSP(r13)
-	subi	r1,r1,64+INT_FRAME_SIZE
-	std	r9,_CCR(r1)
-	std	r10,GPR1(r1)
-	std	r11,_NIP(r1)
-	std	r12,_MSR(r1)
-	mfspr	r11,SPRN_DAR
-	mfspr	r12,SPRN_DSISR
-	std	r11,_DAR(r1)
-	std	r12,_DSISR(r1)
-	mflr	r10
-	mfctr	r11
-	mfxer	r12
-	std	r10,_LINK(r1)
-	std	r11,_CTR(r1)
-	std	r12,_XER(r1)
-	SAVE_GPR(0,r1)
-	SAVE_GPR(2,r1)
-	ld	r10,EX_R3(r3)
-	std	r10,GPR3(r1)
-	SAVE_GPR(4,r1)
-	SAVE_4GPRS(5,r1)
-	ld	r9,EX_R9(r3)
-	ld	r10,EX_R10(r3)
-	SAVE_2GPRS(9,r1)
-	ld	r9,EX_R11(r3)
-	ld	r10,EX_R12(r3)
-	ld	r11,EX_R13(r3)
-	std	r9,GPR11(r1)
-	std	r10,GPR12(r1)
-	std	r11,GPR13(r1)
-BEGIN_FTR_SECTION
-	ld	r10,EX_CFAR(r3)
-	std	r10,ORIG_GPR3(r1)
-END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
-	SAVE_8GPRS(14,r1)
-	SAVE_10GPRS(22,r1)
-	lhz	r12,PACA_TRAP_SAVE(r13)
-	std	r12,_TRAP(r1)
-	addi	r11,r1,INT_FRAME_SIZE
-	std	r11,0(r1)
-	li	r12,0
-	std	r12,0(r11)
-	ld	r2,PACATOC(r13)
-	ld	r11,exception_marker@toc(r2)
-	std	r12,RESULT(r1)
-	std	r11,STACK_FRAME_OVERHEAD-16(r1)
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	kernel_bad_stack
-	b	1b
-
-/*
  * Here r13 points to the paca, r9 contains the saved CR,
  * SRR0 and SRR1 are saved in r11 and r12,
  * r9 - r13 are saved in paca->exgen.
@@ -1057,7 +970,7 @@ data_access_common:
 	mfspr	r10,SPRN_DSISR
 	stw	r10,PACA_EXGEN+EX_DSISR(r13)
 	EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	ld	r12,_MSR(r1)
 	ld	r3,PACA_EXGEN+EX_DAR(r13)
 	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
@@ -1073,7 +986,7 @@ h_data_storage_common:
 	stw     r10,PACA_EXGEN+EX_DSISR(r13)
 	EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
 	bl      save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi    r3,r1,STACK_FRAME_OVERHEAD
 	bl      unknown_exception
 	b       ret_from_except
@@ -1082,7 +995,7 @@ h_data_storage_common:
 	.globl instruction_access_common
 instruction_access_common:
 	EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	ld	r12,_MSR(r1)
 	ld	r3,_NIP(r1)
 	andis.	r4,r12,0x5820
@@ -1146,7 +1059,7 @@ slb_miss_fault:
 
 unrecov_user_slb:
 	EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	bl	save_nvgprs
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	unrecoverable_exception
@@ -1169,7 +1082,7 @@ machine_check_common:
 	stw	r10,PACA_EXGEN+EX_DSISR(r13)
 	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
 	FINISH_NAP
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	ld	r3,PACA_EXGEN+EX_DAR(r13)
 	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
 	std	r3,_DAR(r1)
@@ -1192,7 +1105,7 @@ alignment_common:
 	std	r3,_DAR(r1)
 	std	r4,_DSISR(r1)
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	alignment_exception
 	b	ret_from_except
@@ -1202,7 +1115,7 @@ alignment_common:
 program_check_common:
 	EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	program_check_exception
 	b	ret_from_except
@@ -1213,7 +1126,7 @@ fp_unavailable_common:
 	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
 	bne	1f			/* if from user, just load it up */
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	kernel_fp_unavailable_exception
 	BUG_OPCODE
@@ -1232,7 +1145,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 2:	/* User process was in a transaction */
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	fp_unavailable_tm
 	b	ret_from_except
@@ -1258,7 +1171,7 @@ BEGIN_FTR_SECTION
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 2:	/* User process was in a transaction */
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	altivec_unavailable_tm
 	b	ret_from_except
@@ -1267,7 +1180,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	altivec_unavailable_exception
 	b	ret_from_except
@@ -1292,7 +1205,7 @@ BEGIN_FTR_SECTION
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 2:	/* User process was in a transaction */
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	vsx_unavailable_tm
 	b	ret_from_except
@@ -1301,7 +1214,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
 	bl	save_nvgprs
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	vsx_unavailable_exception
 	b	ret_from_except
@@ -1338,11 +1251,60 @@ fwnmi_data_area:
 	. = 0x8000
 #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
-/* Space for CPU0's segment table */
-	.balign 4096
-	.globl initial_stab
-initial_stab:
-	.space	4096
+	.globl hmi_exception_early
+hmi_exception_early:
+	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60)
+	mr	r10,r1			/* Save r1			*/
+	ld	r1,PACAEMERGSP(r13)	/* Use emergency stack		*/
+	subi	r1,r1,INT_FRAME_SIZE	/* alloc stack frame		*/
+	std	r9,_CCR(r1)		/* save CR in stackframe	*/
+	mfspr	r11,SPRN_HSRR0		/* Save HSRR0 */
+	std	r11,_NIP(r1)		/* save HSRR0 in stackframe	*/
+	mfspr	r12,SPRN_HSRR1		/* Save SRR1 */
+	std	r12,_MSR(r1)		/* save SRR1 in stackframe	*/
+	std	r10,0(r1)		/* make stack chain pointer	*/
+	std	r0,GPR0(r1)		/* save r0 in stackframe	*/
+	std	r10,GPR1(r1)		/* save r1 in stackframe	*/
+	EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN)
+	EXCEPTION_PROLOG_COMMON_3(0xe60)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	hmi_exception_realmode
+	/* Windup the stack. */
+	/* Clear MSR_RI before setting SRR0 and SRR1. */
+	li	r0,MSR_RI
+	mfmsr	r9			/* get MSR value */
+	andc	r9,r9,r0
+	mtmsrd	r9,1			/* Clear MSR_RI */
+	/* Move original HSRR0 and HSRR1 into the respective regs */
+	ld	r9,_MSR(r1)
+	mtspr	SPRN_HSRR1,r9
+	ld	r3,_NIP(r1)
+	mtspr	SPRN_HSRR0,r3
+	ld	r9,_CTR(r1)
+	mtctr	r9
+	ld	r9,_XER(r1)
+	mtxer	r9
+	ld	r9,_LINK(r1)
+	mtlr	r9
+	REST_GPR(0, r1)
+	REST_8GPRS(2, r1)
+	REST_GPR(10, r1)
+	ld	r11,_CCR(r1)
+	mtcr	r11
+	REST_GPR(11, r1)
+	REST_2GPRS(12, r1)
+	/* restore original r1. */
+	ld	r1,GPR1(r1)
+
+	/*
+	 * Go to virtual mode and pull the HMI event information from
+	 * firmware.
+	 */
+	.globl hmi_exception_after_realmode
+hmi_exception_after_realmode:
+	SET_SCRATCH0(r13)
+	EXCEPTION_PROLOG_0(PACA_EXGEN)
+	b	hmi_exception_hv
 
 #ifdef CONFIG_PPC_POWERNV
 _GLOBAL(opal_mc_secondary_handler)
@@ -1566,7 +1528,7 @@ slb_miss_realmode:
 
 unrecov_slb:
 	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
-	DISABLE_INTS
+	RECONCILE_IRQ_STATE(r10, r11)
 	bl	save_nvgprs
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	unrecoverable_exception
@@ -1594,12 +1556,6 @@ do_hash_page:
 	bne-	handle_page_fault	/* if not, try to insert a HPTE */
 	andis.  r0,r4,DSISR_DABRMATCH@h
 	bne-    handle_dabr_fault
-
-BEGIN_FTR_SECTION
-	andis.	r0,r4,0x0020		/* Is it a segment table fault? */
-	bne-	do_ste_alloc		/* If so handle it */
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
-
 	CURRENT_THREAD_INFO(r11, r1)
 	lwz	r0,TI_PREEMPT(r11)	/* If we're in an "NMI" */
 	andis.	r0,r0,NMI_MASK@h	/* (i.e. an irq when soft-disabled) */
@@ -1681,113 +1637,62 @@ handle_dabr_fault:
 	bl	bad_page_fault
 	b	ret_from_except
 
-	/* here we have a segment miss */
-do_ste_alloc:
-	bl	ste_allocate		/* try to insert stab entry */
-	cmpdi	r3,0
-	bne-	handle_page_fault
-	b	fast_exception_return
-
 /*
- * r13 points to the PACA, r9 contains the saved CR,
+ * Here we have detected that the kernel stack pointer is bad.
+ * R9 contains the saved CR, r13 points to the paca,
+ * r10 contains the (bad) kernel stack pointer,
  * r11 and r12 contain the saved SRR0 and SRR1.
- * r9 - r13 are saved in paca->exslb.
- * We assume we aren't going to take any exceptions during this procedure.
- * We assume (DAR >> 60) == 0xc.
+ * We switch to using an emergency stack, save the registers there,
+ * and call kernel_bad_stack(), which panics.
  */
-	.align	7
-do_stab_bolted:
-	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
-	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
-	mfspr	r11,SPRN_DAR			/* ea */
-
-	/*
-	 * check for bad kernel/user address
-	 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
-	 */
-	rldicr. r9,r11,4,(63 - 46 - 4)
-	li	r9,0	/* VSID = 0 for bad address */
-	bne-	0f
-
-	/*
-	 * Calculate VSID:
-	 * This is the kernel vsid, we take the top for context from
-	 * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
-	 * Here we know that (ea >> 60) == 0xc
-	 */
-	lis	r9,(MAX_USER_CONTEXT + 1)@ha
-	addi	r9,r9,(MAX_USER_CONTEXT + 1)@l
-
-	srdi	r10,r11,SID_SHIFT
-	rldimi  r10,r9,ESID_BITS,0 /* proto vsid */
-	ASM_VSID_SCRAMBLE(r10, r9, 256M)
-	rldic	r9,r10,12,16	/* r9 = vsid << 12 */
-
-0:
-	/* Hash to the primary group */
-	ld	r10,PACASTABVIRT(r13)
-	srdi	r11,r11,SID_SHIFT
-	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
-
-	/* Search the primary group for a free entry */
-1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
-	andi.	r11,r11,0x80
-	beq	2f
-	addi	r10,r10,16
-	andi.	r11,r10,0x70
-	bne	1b
-
-	/* Stick for only searching the primary group for now.		*/
-	/* At least for now, we use a very simple random castout scheme */
-	/* Use the TB as a random number ;  OR in 1 to avoid entry 0	*/
-	mftb	r11
-	rldic	r11,r11,4,57	/* r11 = (r11 << 4) & 0x70 */
-	ori	r11,r11,0x10
-
-	/* r10 currently points to an ste one past the group of interest */
-	/* make it point to the randomly selected entry			*/
-	subi	r10,r10,128
-	or 	r10,r10,r11	/* r10 is the entry to invalidate	*/
-
-	isync			/* mark the entry invalid		*/
-	ld	r11,0(r10)
-	rldicl	r11,r11,56,1	/* clear the valid bit */
-	rotldi	r11,r11,8
-	std	r11,0(r10)
-	sync
-
-	clrrdi	r11,r11,28	/* Get the esid part of the ste		*/
-	slbie	r11
-
-2:	std	r9,8(r10)	/* Store the vsid part of the ste	*/
-	eieio
-
-	mfspr	r11,SPRN_DAR		/* Get the new esid			*/
-	clrrdi	r11,r11,28	/* Permits a full 32b of ESID		*/
-	ori	r11,r11,0x90	/* Turn on valid and kp			*/
-	std	r11,0(r10)	/* Put new entry back into the stab	*/
-
-	sync
-
-	/* All done -- return from exception. */
-	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
-	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
-
-	andi.	r10,r12,MSR_RI
-	beq-	unrecov_slb
-
-	mtcrf	0x80,r9			/* restore CR */
-
-	mfmsr	r10
-	clrrdi	r10,r10,2
-	mtmsrd	r10,1
-
-	mtspr	SPRN_SRR0,r11
-	mtspr	SPRN_SRR1,r12
-	ld	r9,PACA_EXSLB+EX_R9(r13)
-	ld	r10,PACA_EXSLB+EX_R10(r13)
-	ld	r11,PACA_EXSLB+EX_R11(r13)
-	ld	r12,PACA_EXSLB+EX_R12(r13)
-	ld	r13,PACA_EXSLB+EX_R13(r13)
-	rfid
-	b	.	/* prevent speculative execution */
+bad_stack:
+	ld	r1,PACAEMERGSP(r13)
+	subi	r1,r1,64+INT_FRAME_SIZE
+	std	r9,_CCR(r1)
+	std	r10,GPR1(r1)
+	std	r11,_NIP(r1)
+	std	r12,_MSR(r1)
+	mfspr	r11,SPRN_DAR
+	mfspr	r12,SPRN_DSISR
+	std	r11,_DAR(r1)
+	std	r12,_DSISR(r1)
+	mflr	r10
+	mfctr	r11
+	mfxer	r12
+	std	r10,_LINK(r1)
+	std	r11,_CTR(r1)
+	std	r12,_XER(r1)
+	SAVE_GPR(0,r1)
+	SAVE_GPR(2,r1)
+	ld	r10,EX_R3(r3)
+	std	r10,GPR3(r1)
+	SAVE_GPR(4,r1)
+	SAVE_4GPRS(5,r1)
+	ld	r9,EX_R9(r3)
+	ld	r10,EX_R10(r3)
+	SAVE_2GPRS(9,r1)
+	ld	r9,EX_R11(r3)
+	ld	r10,EX_R12(r3)
+	ld	r11,EX_R13(r3)
+	std	r9,GPR11(r1)
+	std	r10,GPR12(r1)
+	std	r11,GPR13(r1)
+BEGIN_FTR_SECTION
+	ld	r10,EX_CFAR(r3)
+	std	r10,ORIG_GPR3(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
+	SAVE_8GPRS(14,r1)
+	SAVE_10GPRS(22,r1)
+	lhz	r12,PACA_TRAP_SAVE(r13)
+	std	r12,_TRAP(r1)
+	addi	r11,r1,INT_FRAME_SIZE
+	std	r11,0(r1)
+	li	r12,0
+	std	r12,0(r11)
+	ld	r2,PACATOC(r13)
+	ld	r11,exception_marker@toc(r2)
+	std	r12,RESULT(r1)
+	std	r11,STACK_FRAME_OVERHEAD-16(r1)
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	kernel_bad_stack
+	b	1b
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -525,6 +525,9 @@ void prepare_ftrace_return(unsigned long
 	struct ftrace_graph_ent trace;
 	unsigned long return_hooker = (unsigned long)&return_to_handler;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/head_44x.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/head_44x.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/head_44x.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/head_44x.S	2014-09-28 17:29:07.000000000 -0400
@@ -1210,10 +1210,12 @@ clear_utlb_entry:
 
 	/* We configure icbi to invalidate 128 bytes at a time since the
 	 * current 32-bit kernel code isn't too happy with icache != dcache
-	 * block size
+	 * block size. We also disable the BTAC as this can cause errors
+	 * in some circumstances (see IBM Erratum 47).
 	 */
 	mfspr	r3,SPRN_CCR0
 	oris	r3,r3,0x0020
+	ori	r3,r3,0x0040
 	mtspr	SPRN_CCR0,r3
 	isync
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/head_64.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/head_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/head_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -180,6 +180,28 @@ exception_marker:
 #include "exceptions-64s.S"
 #endif
 
+#ifdef CONFIG_PPC_BOOK3E
+_GLOBAL(fsl_secondary_thread_init)
+	/* Enable branch prediction */
+	lis     r3,BUCSR_INIT@h
+	ori     r3,r3,BUCSR_INIT@l
+	mtspr   SPRN_BUCSR,r3
+	isync
+
+	/*
+	 * Fix PIR to match the linear numbering in the device tree.
+	 *
+	 * On e6500, the reset value of PIR uses the low three bits for
+	 * the thread within a core, and the upper bits for the core
+	 * number.  There are two threads per core, so shift everything
+	 * but the low bit right by two bits so that the cpu numbering is
+	 * continuous.
+	 */
+	mfspr	r3, SPRN_PIR
+	rlwimi	r3, r3, 30, 2, 30
+	mtspr	SPRN_PIR, r3
+#endif
+
 _GLOBAL(generic_secondary_thread_init)
 	mr	r24,r3
 
@@ -618,7 +640,7 @@ __secondary_start:
 	addi	r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD
 	std	r14,PACAKSAVE(r13)
 
-	/* Do early setup for that CPU (stab, slb, hash table pointer) */
+	/* Do early setup for that CPU (SLB and hash table pointer) */
 	bl	early_setup_secondary
 
 	/*
@@ -771,8 +793,10 @@ start_here_multiplatform:
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 
-	/* Do very early kernel initializations, including initial hash table,
-	 * stab and slb setup before we turn on relocation.	*/
+	/*
+	 * Do very early kernel initializations, including initial hash table
+	 * and SLB setup before we turn on relocation.
+	 */
 
 	/* Restore parameters passed from prom_init/kexec */
 	mr	r3,r31
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/idle_power7.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/idle_power7.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/idle_power7.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/idle_power7.S	2014-09-28 17:29:07.000000000 -0400
@@ -135,17 +135,68 @@ _GLOBAL(power7_sleep)
 	b	power7_powersave_common
 	/* No return */
 
+/*
+ * Make opal call in realmode. This is a generic function to be called
+ * from realmode from reset vector. It handles endianess.
+ *
+ * r13 - paca pointer
+ * r1  - stack pointer
+ * r3  - opal token
+ */
+opal_call_realmode:
+	mflr	r12
+	std	r12,_LINK(r1)
+	ld	r2,PACATOC(r13)
+	/* Set opal return address */
+	LOAD_REG_ADDR(r0,return_from_opal_call)
+	mtlr	r0
+	/* Handle endian-ness */
+	li	r0,MSR_LE
+	mfmsr	r12
+	andc	r12,r12,r0
+	mtspr	SPRN_HSRR1,r12
+	mr	r0,r3			/* Move opal token to r0 */
+	LOAD_REG_ADDR(r11,opal)
+	ld	r12,8(r11)
+	ld	r2,0(r11)
+	mtspr	SPRN_HSRR0,r12
+	hrfid
+
+return_from_opal_call:
+	FIXUP_ENDIAN
+	ld	r0,_LINK(r1)
+	mtlr	r0
+	blr
+
+#define CHECK_HMI_INTERRUPT						\
+	mfspr	r0,SPRN_SRR1;						\
+BEGIN_FTR_SECTION_NESTED(66);						\
+	rlwinm	r0,r0,45-31,0xf;  /* extract wake reason field (P8) */	\
+FTR_SECTION_ELSE_NESTED(66);						\
+	rlwinm	r0,r0,45-31,0xe;  /* P7 wake reason field is 3 bits */	\
+ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66);		\
+	cmpwi	r0,0xa;			/* Hypervisor maintenance ? */	\
+	bne	20f;							\
+	/* Invoke opal call to handle hmi */				\
+	ld	r2,PACATOC(r13);					\
+	ld	r1,PACAR1(r13);						\
+	std	r3,ORIG_GPR3(r1);	/* Save original r3 */		\
+	li	r3,OPAL_HANDLE_HMI;	/* Pass opal token argument*/	\
+	bl	opal_call_realmode;					\
+	ld	r3,ORIG_GPR3(r1);	/* Restore original r3 */	\
+20:	nop;
+
+
 _GLOBAL(power7_wakeup_tb_loss)
 	ld	r2,PACATOC(r13);
 	ld	r1,PACAR1(r13)
 
+BEGIN_FTR_SECTION
+	CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
 	/* Time base re-sync */
-	li	r0,OPAL_RESYNC_TIMEBASE
-	LOAD_REG_ADDR(r11,opal);
-	ld	r12,8(r11);
-	ld	r2,0(r11);
-	mtctr	r12
-	bctrl
+	li	r3,OPAL_RESYNC_TIMEBASE
+	bl	opal_call_realmode;
 
 	/* TODO: Check r3 for failure */
 
@@ -163,6 +214,9 @@ _GLOBAL(power7_wakeup_tb_loss)
 
 _GLOBAL(power7_wakeup_loss)
 	ld	r1,PACAR1(r13)
+BEGIN_FTR_SECTION
+	CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
 	REST_NVGPRS(r1)
 	REST_GPR(2, r1)
 	ld	r3,_CCR(r1)
@@ -178,6 +232,9 @@ _GLOBAL(power7_wakeup_noloss)
 	lbz	r0,PACA_NAPSTATELOST(r13)
 	cmpwi	r0,0
 	bne	power7_wakeup_loss
+BEGIN_FTR_SECTION
+	CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
 	ld	r1,PACAR1(r13)
 	ld	r4,_MSR(r1)
 	ld	r5,_NIP(r1)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/iommu.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/iommu.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *
 
 	/* if (unlikely(ret))
 		pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n",
-			__func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl),
+			__func__, hwaddr, entry << tbl->it_page_shift,
 				hwaddr, ret); */
 
 	return ret;
@@ -1056,7 +1056,7 @@ int iommu_put_tce_user_mode(struct iommu
 			direction != DMA_TO_DEVICE, &page);
 	if (unlikely(ret != 1)) {
 		/* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n",
-				tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */
+				tce, entry << tbl->it_page_shift, ret); */
 		return -EFAULT;
 	}
 	hwaddr = (unsigned long) page_address(page) + offset;
@@ -1120,37 +1120,41 @@ EXPORT_SYMBOL_GPL(iommu_release_ownershi
 int iommu_add_device(struct device *dev)
 {
 	struct iommu_table *tbl;
-	int ret = 0;
 
-	if (WARN_ON(dev->iommu_group)) {
-		pr_warn("iommu_tce: device %s is already in iommu group %d, skipping\n",
-				dev_name(dev),
-				iommu_group_id(dev->iommu_group));
+	/*
+	 * The sysfs entries should be populated before
+	 * binding IOMMU group. If sysfs entries isn't
+	 * ready, we simply bail.
+	 */
+	if (!device_is_registered(dev))
+		return -ENOENT;
+
+	if (dev->iommu_group) {
+		pr_debug("%s: Skipping device %s with iommu group %d\n",
+			 __func__, dev_name(dev),
+			 iommu_group_id(dev->iommu_group));
 		return -EBUSY;
 	}
 
 	tbl = get_iommu_table_base(dev);
 	if (!tbl || !tbl->it_group) {
-		pr_debug("iommu_tce: skipping device %s with no tbl\n",
-				dev_name(dev));
+		pr_debug("%s: Skipping device %s with no tbl\n",
+			 __func__, dev_name(dev));
 		return 0;
 	}
 
-	pr_debug("iommu_tce: adding %s to iommu group %d\n",
-			dev_name(dev), iommu_group_id(tbl->it_group));
+	pr_debug("%s: Adding %s to iommu group %d\n",
+		 __func__, dev_name(dev),
+		 iommu_group_id(tbl->it_group));
 
 	if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
-		pr_err("iommu_tce: unsupported iommu page size.");
-		pr_err("%s has not been added\n", dev_name(dev));
+		pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n",
+		       __func__, IOMMU_PAGE_SIZE(tbl),
+		       PAGE_SIZE, dev_name(dev));
 		return -EINVAL;
 	}
 
-	ret = iommu_group_add_device(tbl->it_group, dev);
-	if (ret < 0)
-		pr_err("iommu_tce: %s has not been added, ret=%d\n",
-				dev_name(dev), ret);
-
-	return ret;
+	return iommu_group_add_device(tbl->it_group, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_add_device);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -189,6 +189,11 @@ notrace unsigned int __check_irq_replay(
 	}
 #endif /* CONFIG_PPC_BOOK3E */
 
+	/* Check if an hypervisor Maintenance interrupt happened */
+	local_paca->irq_happened &= ~PACA_IRQ_HMI;
+	if (happened & PACA_IRQ_HMI)
+		return 0xe60;
+
 	/* There should be nothing left ! */
 	BUG_ON(local_paca->irq_happened != 0);
 
@@ -377,6 +382,14 @@ int arch_show_interrupts(struct seq_file
 		seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
 	seq_printf(p, "  Machine check exceptions\n");
 
+	if (cpu_has_feature(CPU_FTR_HVMODE)) {
+		seq_printf(p, "%*s: ", prec, "HMI");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+					per_cpu(irq_stat, j).hmi_exceptions);
+		seq_printf(p, "  Hypervisor Maintenance Interrupts\n");
+	}
+
 #ifdef CONFIG_PPC_DOORBELL
 	if (cpu_has_feature(CPU_FTR_DBELL)) {
 		seq_printf(p, "%*s: ", prec, "DBL");
@@ -400,6 +413,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 	sum += per_cpu(irq_stat, cpu).mce_exceptions;
 	sum += per_cpu(irq_stat, cpu).spurious_irqs;
 	sum += per_cpu(irq_stat, cpu).timer_irqs_others;
+	sum += per_cpu(irq_stat, cpu).hmi_exceptions;
 #ifdef CONFIG_PPC_DOORBELL
 	sum += per_cpu(irq_stat, cpu).doorbell_irqs;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/pci-common.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/pci-common.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/pci-common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/pci-common.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,21 +123,12 @@ resource_size_t pcibios_window_alignment
 
 void pcibios_reset_secondary_bus(struct pci_dev *dev)
 {
-	u16 ctrl;
-
 	if (ppc_md.pcibios_reset_secondary_bus) {
 		ppc_md.pcibios_reset_secondary_bus(dev);
 		return;
 	}
 
-	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
-	ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
-	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
-	msleep(2);
-
-	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
-	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
-	ssleep(1);
+	pci_reset_secondary_bus(dev);
 }
 
 static resource_size_t pcibios_io_size(const struct pci_controller *hose)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/process.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/process.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -1095,6 +1095,23 @@ int arch_dup_task_struct(struct task_str
 	return 0;
 }
 
+static void setup_ksp_vsid(struct task_struct *p, unsigned long sp)
+{
+#ifdef CONFIG_PPC_STD_MMU_64
+	unsigned long sp_vsid;
+	unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
+
+	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
+		sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
+			<< SLB_VSID_SHIFT_1T;
+	else
+		sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M)
+			<< SLB_VSID_SHIFT;
+	sp_vsid |= SLB_VSID_KERNEL | llp;
+	p->thread.ksp_vsid = sp_vsid;
+#endif
+}
+
 /*
  * Copy a thread..
  */
@@ -1174,21 +1191,8 @@ int copy_thread(unsigned long clone_flag
 	p->thread.vr_save_area = NULL;
 #endif
 
-#ifdef CONFIG_PPC_STD_MMU_64
-	if (mmu_has_feature(MMU_FTR_SLB)) {
-		unsigned long sp_vsid;
-		unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
+	setup_ksp_vsid(p, sp);
 
-		if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
-			sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
-				<< SLB_VSID_SHIFT_1T;
-		else
-			sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M)
-				<< SLB_VSID_SHIFT;
-		sp_vsid |= SLB_VSID_KERNEL | llp;
-		p->thread.ksp_vsid = sp_vsid;
-	}
-#endif /* CONFIG_PPC_STD_MMU_64 */
 #ifdef CONFIG_PPC64 
 	if (cpu_has_feature(CPU_FTR_DSCR)) {
 		p->thread.dscr_inherit = current->thread.dscr_inherit;
@@ -1577,7 +1581,7 @@ void show_stack(struct task_struct *tsk,
 			struct pt_regs *regs = (struct pt_regs *)
 				(sp + STACK_FRAME_OVERHEAD);
 			lr = regs->link;
-			printk("--- Exception: %lx at %pS\n    LR = %pS\n",
+			printk("--- interrupt: %lx at %pS\n    LR = %pS\n",
 			       regs->trap, (void *)regs->nip, (void *)lr);
 			firstframe = 1;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/prom.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/prom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/prom.c	2014-09-28 17:29:07.000000000 -0400
@@ -155,7 +155,6 @@ static struct ibm_pa_feature {
 } ibm_pa_features[] __initdata = {
 	{0, 0, PPC_FEATURE_HAS_MMU,	0, 0, 0},
 	{0, 0, PPC_FEATURE_HAS_FPU,	0, 1, 0},
-	{0, MMU_FTR_SLB, 0,		0, 2, 0},
 	{CPU_FTR_CTRL, 0, 0,		0, 3, 0},
 	{CPU_FTR_NOEXECUTE, 0, 0,	0, 6, 0},
 	{CPU_FTR_NODSISRALIGN, 0, 0,	1, 1, 1},
@@ -309,12 +308,10 @@ static int __init early_init_dt_scan_cpu
 
 	/* Get physical cpuid */
 	intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
-	if (intserv) {
-		nthreads = len / sizeof(int);
-	} else {
-		intserv = of_get_flat_dt_prop(node, "reg", NULL);
-		nthreads = 1;
-	}
+	if (!intserv)
+		intserv = of_get_flat_dt_prop(node, "reg", &len);
+
+	nthreads = len / sizeof(int);
 
 	/*
 	 * Now see if any of these threads match our boot cpu.
@@ -821,76 +818,6 @@ int cpu_to_chip_id(int cpu)
 }
 EXPORT_SYMBOL(cpu_to_chip_id);
 
-#ifdef CONFIG_PPC_PSERIES
-/*
- * Fix up the uninitialized fields in a new device node:
- * name, type and pci-specific fields
- */
-
-static int of_finish_dynamic_node(struct device_node *node)
-{
-	struct device_node *parent = of_get_parent(node);
-	int err = 0;
-	const phandle *ibm_phandle;
-
-	node->name = of_get_property(node, "name", NULL);
-	node->type = of_get_property(node, "device_type", NULL);
-
-	if (!node->name)
-		node->name = "<NULL>";
-	if (!node->type)
-		node->type = "<NULL>";
-
-	if (!parent) {
-		err = -ENODEV;
-		goto out;
-	}
-
-	/* We don't support that function on PowerMac, at least
-	 * not yet
-	 */
-	if (machine_is(powermac))
-		return -ENODEV;
-
-	/* fix up new node's phandle field */
-	if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
-		node->phandle = *ibm_phandle;
-
-out:
-	of_node_put(parent);
-	return err;
-}
-
-static int prom_reconfig_notifier(struct notifier_block *nb,
-				  unsigned long action, void *node)
-{
-	int err;
-
-	switch (action) {
-	case OF_RECONFIG_ATTACH_NODE:
-		err = of_finish_dynamic_node(node);
-		if (err < 0)
-			printk(KERN_ERR "finish_node returned %d\n", err);
-		break;
-	default:
-		err = 0;
-		break;
-	}
-	return notifier_from_errno(err);
-}
-
-static struct notifier_block prom_reconfig_nb = {
-	.notifier_call = prom_reconfig_notifier,
-	.priority = 10, /* This one needs to run first */
-};
-
-static int __init prom_reconfig_setup(void)
-{
-	return of_reconfig_notifier_register(&prom_reconfig_nb);
-}
-__initcall(prom_reconfig_setup);
-#endif
-
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
 {
 	return (int)phys_id == get_hard_smp_processor_id(cpu);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/setup_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/setup_64.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/setup_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/setup_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,13 +149,13 @@ static void check_smt_enabled(void)
 		else if (!strcmp(smt_enabled_cmdline, "off"))
 			smt_enabled_at_boot = 0;
 		else {
-			long smt;
+			int smt;
 			int rc;
 
-			rc = strict_strtol(smt_enabled_cmdline, 10, &smt);
+			rc = kstrtoint(smt_enabled_cmdline, 10, &smt);
 			if (!rc)
 				smt_enabled_at_boot =
-					min(threads_per_core, (int)smt);
+					min(threads_per_core, smt);
 		}
 	} else {
 		dn = of_find_node_by_path("/options");
@@ -201,7 +201,11 @@ static void cpu_ready_for_interrupts(voi
 	/* Set IR and DR in PACA MSR */
 	get_paca()->kernel_msr = MSR_KERNEL;
 
-	/* Enable AIL if supported */
+	/*
+	 * Enable AIL if supported, and we are in hypervisor mode. If we are
+	 * not in hypervisor mode, we enable relocation-on interrupts later
+	 * in pSeries_setup_arch() using the H_SET_MODE hcall.
+	 */
 	if (cpu_has_feature(CPU_FTR_HVMODE) &&
 	    cpu_has_feature(CPU_FTR_ARCH_207S)) {
 		unsigned long lpcr = mfspr(SPRN_LPCR);
@@ -507,7 +511,11 @@ void __init setup_system(void)
 	check_smt_enabled();
 	setup_tlb_core_data();
 
-#ifdef CONFIG_SMP
+	/*
+	 * Freescale Book3e parts spin in a loop provided by firmware,
+	 * so smp_release_cpus() does nothing for them
+	 */
+#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_FSL_BOOK3E)
 	/* Release secondary cpus out of their spinloops at 0x60 now that
 	 * we can map physical -> logical CPU ids
 	 */
@@ -673,9 +681,6 @@ void __init setup_arch(char **cmdline_p)
 	exc_lvl_early_init();
 	emergency_stack_init();
 
-#ifdef CONFIG_PPC_STD_MMU_64
-	stabs_alloc();
-#endif
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 	sparse_init();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/setup-common.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/setup-common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/setup-common.c	2014-09-28 17:29:07.000000000 -0400
@@ -456,18 +456,20 @@ void __init smp_setup_cpu_maps(void)
 		intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
 				&len);
 		if (intserv) {
-			nthreads = len / sizeof(int);
 			DBG("    ibm,ppc-interrupt-server#s -> %d threads\n",
 			    nthreads);
 		} else {
 			DBG("    no ibm,ppc-interrupt-server#s -> 1 thread\n");
-			intserv = of_get_property(dn, "reg", NULL);
+			intserv = of_get_property(dn, "reg", &len);
 			if (!intserv) {
 				cpu_be = cpu_to_be32(cpu);
 				intserv = &cpu_be;	/* assume logical == phys */
+				len = 4;
 			}
 		}
 
+		nthreads = len / sizeof(int);
+
 		for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
 			bool avail;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/signal_32.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal_32.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/signal_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *
  * Set up a signal frame for a "real-time" signal handler
  * (one which gets siginfo).
  */
-int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
-		siginfo_t *info, sigset_t *oldset,
-		struct pt_regs *regs)
+int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
+		       struct pt_regs *regs)
 {
 	struct rt_sigframe __user *rt_sf;
 	struct mcontext __user *frame;
@@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig
 
 	/* Set up Signal Frame */
 	/* Put a Real Time Context onto stack */
-	rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
+	rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
 	addr = rt_sf;
 	if (unlikely(rt_sf == NULL))
 		goto badframe;
 
 	/* Put the siginfo & fill in most of the ucontext */
-	if (copy_siginfo_to_user(&rt_sf->info, info)
+	if (copy_siginfo_to_user(&rt_sf->info, &ksig->info)
 	    || __put_user(0, &rt_sf->uc.uc_flags)
 	    || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])
 	    || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
@@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig
 
 	/* Fill registers for signal handler */
 	regs->gpr[1] = newsp;
-	regs->gpr[3] = sig;
+	regs->gpr[3] = ksig->sig;
 	regs->gpr[4] = (unsigned long) &rt_sf->info;
 	regs->gpr[5] = (unsigned long) &rt_sf->uc;
 	regs->gpr[6] = (unsigned long) rt_sf;
-	regs->nip = (unsigned long) ka->sa.sa_handler;
+	regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
 	/* enter the signal handler in native-endian mode */
 	regs->msr &= ~MSR_LE;
 	regs->msr |= (MSR_KERNEL & MSR_LE);
-	return 1;
+	return 0;
 
 badframe:
 	if (show_unhandled_signals)
@@ -1069,8 +1068,7 @@ badframe:
 				   current->comm, current->pid,
 				   addr, regs->nip, regs->link);
 
-	force_sigsegv(sig, current);
-	return 0;
+	return 1;
 }
 
 static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
@@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext
 /*
  * OK, we're invoking a handler
  */
-int handle_signal32(unsigned long sig, struct k_sigaction *ka,
-		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs)
 {
 	struct sigcontext __user *sc;
 	struct sigframe __user *frame;
@@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, s
 	unsigned long tramp;
 
 	/* Set up Signal Frame */
-	frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
+	frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1);
 	if (unlikely(frame == NULL))
 		goto badframe;
 	sc = (struct sigcontext __user *) &frame->sctx;
@@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, s
 #if _NSIG != 64
 #error "Please adjust handle_signal()"
 #endif
-	if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler)
+	if (__put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler)
 	    || __put_user(oldset->sig[0], &sc->oldmask)
 #ifdef CONFIG_PPC64
 	    || __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
@@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, s
 	    || __put_user(oldset->sig[1], &sc->_unused[3])
 #endif
 	    || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
-	    || __put_user(sig, &sc->signal))
+	    || __put_user(ksig->sig, &sc->signal))
 		goto badframe;
 
 	if (vdso32_sigtramp && current->mm->context.vdso_base) {
@@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, s
 		goto badframe;
 
 	regs->gpr[1] = newsp;
-	regs->gpr[3] = sig;
+	regs->gpr[3] = ksig->sig;
 	regs->gpr[4] = (unsigned long) sc;
-	regs->nip = (unsigned long) ka->sa.sa_handler;
+	regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;
 	/* enter the signal handler in big-endian mode */
 	regs->msr &= ~MSR_LE;
-	return 1;
+	return 0;
 
 badframe:
 	if (show_unhandled_signals)
@@ -1486,8 +1483,7 @@ badframe:
 				   current->comm, current->pid,
 				   frame, regs->nip, regs->link);
 
-	force_sigsegv(sig, current);
-	return 0;
+	return 1;
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/signal_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal_64.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/signal_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -708,20 +708,19 @@ badframe:
 	return 0;
 }
 
-int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
-		sigset_t *set, struct pt_regs *regs)
+int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	unsigned long newsp = 0;
 	long err = 0;
 
-	frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
+	frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0);
 	if (unlikely(frame == NULL))
 		goto badframe;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	if (err)
 		goto badframe;
 
@@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct
 		err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
 		err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
 					    &frame->uc_transact.uc_mcontext,
-					    regs, signr,
+					    regs, ksig->sig,
 					    NULL,
-					    (unsigned long)ka->sa.sa_handler);
+					    (unsigned long)ksig->ka.sa.sa_handler);
 	} else
 #endif
 	{
 		err |= __put_user(0, &frame->uc.uc_link);
-		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr,
-					NULL, (unsigned long)ka->sa.sa_handler,
+		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig,
+					NULL, (unsigned long)ksig->ka.sa.sa_handler,
 					1);
 	}
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
@@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct
 
 	/* Set up "regs" so we "return" to the signal handler. */
 	if (is_elf2_task()) {
-		regs->nip = (unsigned long) ka->sa.sa_handler;
+		regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
 		regs->gpr[12] = regs->nip;
 	} else {
 		/* Handler is *really* a pointer to the function descriptor for
@@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct
 		 * entry is the TOC value we need to use.
 		 */
 		func_descr_t __user *funct_desc_ptr =
-			(func_descr_t __user *) ka->sa.sa_handler;
+			(func_descr_t __user *) ksig->ka.sa.sa_handler;
 
 		err |= get_user(regs->nip, &funct_desc_ptr->entry);
 		err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
@@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct
 	regs->msr &= ~MSR_LE;
 	regs->msr |= (MSR_KERNEL & MSR_LE);
 	regs->gpr[1] = newsp;
-	regs->gpr[3] = signr;
+	regs->gpr[3] = ksig->sig;
 	regs->result = 0;
-	if (ka->sa.sa_flags & SA_SIGINFO) {
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
 		err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo);
 		err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc);
 		regs->gpr[6] = (unsigned long) frame;
@@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct
 	if (err)
 		goto badframe;
 
-	return 1;
+	return 0;
 
 badframe:
 	if (show_unhandled_signals)
@@ -809,6 +808,5 @@ badframe:
 				   current->comm, current->pid, "setup_rt_frame",
 				   (long)frame, regs->nip, regs->link);
 
-	force_sigsegv(signr, current);
-	return 0;
+	return 1;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,20 +31,14 @@ int show_unhandled_signals = 1;
 /*
  * Allocate space for the signal frame
  */
-void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
+void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
 			   size_t frame_size, int is_32)
 {
         unsigned long oldsp, newsp;
 
         /* Default to using normal stack */
         oldsp = get_clean_sp(sp, is_32);
-
-	/* Check for alt stack */
-	if ((ka->sa.sa_flags & SA_ONSTACK) &&
-	    current->sas_ss_size && !on_sig_stack(oldsp))
-		oldsp = (current->sas_ss_sp + current->sas_ss_size);
-
-	/* Get aligned frame */
+	oldsp = sigsp(oldsp, ksig);
 	newsp = (oldsp - frame_size) & ~0xFUL;
 
 	/* Check access */
@@ -105,25 +99,23 @@ static void check_syscall_restart(struct
 	}
 }
 
-static int do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 	int ret;
 	int is32 = is_32bit_task();
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	get_signal(&ksig);
 
 	/* Is there any syscall restart business here ? */
-	check_syscall_restart(regs, &ka, signr > 0);
+	check_syscall_restart(regs, &ksig.ka, ksig.sig > 0);
 
-	if (signr <= 0) {
+	if (ksig.sig <= 0) {
 		/* No signal to deliver -- put the saved sigmask back */
 		restore_saved_sigmask();
 		regs->trap = 0;
-		return 0;               /* no signals delivered */
+		return;               /* no signals delivered */
 	}
 
 #ifndef CONFIG_PPC_ADV_DEBUG_REGS
@@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *reg
 	thread_change_pc(current, regs);
 
 	if (is32) {
-        	if (ka.sa.sa_flags & SA_SIGINFO)
-			ret = handle_rt_signal32(signr, &ka, &info, oldset,
-					regs);
+        	if (ksig.ka.sa.sa_flags & SA_SIGINFO)
+			ret = handle_rt_signal32(&ksig, oldset, regs);
 		else
-			ret = handle_signal32(signr, &ka, &info, oldset,
-					regs);
+			ret = handle_signal32(&ksig, oldset, regs);
 	} else {
-		ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+		ret = handle_rt_signal64(&ksig, oldset, regs);
 	}
 
 	regs->trap = 0;
-	if (ret) {
-		signal_delivered(signr, &info, &ka, regs,
-					 test_thread_flag(TIF_SINGLESTEP));
-	}
-
-	return ret;
+	signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/signal.h linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal.h
--- linux-libre-3.16-gnu/arch/powerpc/kernel/signal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/signal.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,15 +12,13 @@
 
 extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
 
-extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
+extern void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
 				  size_t frame_size, int is_32);
 
-extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
-			   siginfo_t *info, sigset_t *oldset,
+extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 			   struct pt_regs *regs);
 
-extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
-			      siginfo_t *info, sigset_t *oldset,
+extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
 			      struct pt_regs *regs);
 
 extern unsigned long copy_fpr_to_user(void __user *to,
@@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_f
 
 #ifdef CONFIG_PPC64
 
-extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
-			      siginfo_t *info, sigset_t *set,
+extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
 			      struct pt_regs *regs);
 
 #else /* CONFIG_PPC64 */
 
-static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
-				     siginfo_t *info, sigset_t *set,
+static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
 				     struct pt_regs *regs)
 {
 	return -EFAULT;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -376,6 +376,11 @@ void __init smp_prepare_cpus(unsigned in
 					GFP_KERNEL, cpu_to_node(cpu));
 		zalloc_cpumask_var_node(&per_cpu(cpu_core_map, cpu),
 					GFP_KERNEL, cpu_to_node(cpu));
+		/*
+		 * numa_node_id() works after this.
+		 */
+		set_cpu_numa_node(cpu, numa_cpu_lookup_table[cpu]);
+		set_cpu_numa_mem(cpu, local_memory_node(numa_cpu_lookup_table[cpu]));
 	}
 
 	cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid));
@@ -723,12 +728,6 @@ void start_secondary(void *unused)
 	}
 	traverse_core_siblings(cpu, true);
 
-	/*
-	 * numa_node_id() works after this.
-	 */
-	set_numa_node(numa_cpu_lookup_table[cpu]);
-	set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
-
 	smp_wmb();
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/systbl.S linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/systbl.S
--- linux-libre-3.16-gnu/arch/powerpc/kernel/systbl.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/systbl.S	2014-09-28 17:29:07.000000000 -0400
@@ -39,9 +39,6 @@
 .section .rodata,"a"
 
 #ifdef CONFIG_PPC64
-#define sys_sigpending	sys_ni_syscall
-#define sys_old_getrlimit sys_ni_syscall
-
 	.p2align	3
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/time.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/time.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -741,7 +741,7 @@ static cycle_t timebase_read(struct cloc
 }
 
 void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
-			struct clocksource *clock, u32 mult)
+			 struct clocksource *clock, u32 mult, cycle_t cycle_last)
 {
 	u64 new_tb_to_xs, new_stamp_xsec;
 	u32 frac_sec;
@@ -774,7 +774,7 @@ void update_vsyscall_old(struct timespec
 	 * We expect the caller to have done the first increment of
 	 * vdso_data->tb_update_count already.
 	 */
-	vdso_data->tb_orig_stamp = clock->cycle_last;
+	vdso_data->tb_orig_stamp = cycle_last;
 	vdso_data->stamp_xsec = new_stamp_xsec;
 	vdso_data->tb_to_xs = new_tb_to_xs;
 	vdso_data->wtom_clock_sec = wtm->tv_sec;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/traps.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/traps.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/traps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/traps.c	2014-09-28 17:29:07.000000000 -0400
@@ -302,6 +302,16 @@ long machine_check_early(struct pt_regs
 	return handled;
 }
 
+long hmi_exception_realmode(struct pt_regs *regs)
+{
+	__get_cpu_var(irq_stat).hmi_exceptions++;
+
+	if (ppc_md.hmi_exception_early)
+		ppc_md.hmi_exception_early(regs);
+
+	return 0;
+}
+
 #endif
 
 /*
@@ -609,7 +619,7 @@ int machine_check_e500(struct pt_regs *r
 	if (reason & MCSR_BUS_RBERR)
 		printk("Bus - Read Data Bus Error\n");
 	if (reason & MCSR_BUS_WBERR)
-		printk("Bus - Read Data Bus Error\n");
+		printk("Bus - Write Data Bus Error\n");
 	if (reason & MCSR_BUS_IPERR)
 		printk("Bus - Instruction Parity Error\n");
 	if (reason & MCSR_BUS_RPERR)
@@ -738,6 +748,20 @@ void SMIException(struct pt_regs *regs)
 	die("System Management Interrupt", regs, SIGABRT);
 }
 
+void handle_hmi_exception(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs;
+
+	old_regs = set_irq_regs(regs);
+	irq_enter();
+
+	if (ppc_md.handle_hmi_exception)
+		ppc_md.handle_hmi_exception(regs);
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
 void unknown_exception(struct pt_regs *regs)
 {
 	enum ctx_state prev_state = exception_enter();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/vdso.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/vdso.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/vdso.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/vdso.c	2014-09-28 17:29:07.000000000 -0400
@@ -840,19 +840,3 @@ static int __init vdso_init(void)
 	return 0;
 }
 arch_initcall(vdso_init);
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kernel/vio.c linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/vio.c
--- linux-libre-3.16-gnu/arch/powerpc/kernel/vio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kernel/vio.c	2014-09-28 17:29:07.000000000 -0400
@@ -977,7 +977,7 @@ static ssize_t viodev_cmo_desired_set(st
 	size_t new_desired;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &new_desired);
+	ret = kstrtoul(buf, 10, &new_desired);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/44x.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/44x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <linux/kvm_host.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-
-#include <asm/reg.h>
-#include <asm/cputable.h>
-#include <asm/tlbflush.h>
-#include <asm/kvm_44x.h>
-#include <asm/kvm_ppc.h>
-
-#include "44x_tlb.h"
-#include "booke.h"
-
-static void kvmppc_core_vcpu_load_44x(struct kvm_vcpu *vcpu, int cpu)
-{
-	kvmppc_booke_vcpu_load(vcpu, cpu);
-	kvmppc_44x_tlb_load(vcpu);
-}
-
-static void kvmppc_core_vcpu_put_44x(struct kvm_vcpu *vcpu)
-{
-	kvmppc_44x_tlb_put(vcpu);
-	kvmppc_booke_vcpu_put(vcpu);
-}
-
-int kvmppc_core_check_processor_compat(void)
-{
-	int r;
-
-	if (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 0)
-		r = 0;
-	else
-		r = -ENOTSUPP;
-
-	return r;
-}
-
-int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0];
-	int i;
-
-	tlbe->tid = 0;
-	tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
-	tlbe->word1 = 0;
-	tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
-
-	tlbe++;
-	tlbe->tid = 0;
-	tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
-	tlbe->word1 = 0xef600000;
-	tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
-	              | PPC44x_TLB_I | PPC44x_TLB_G;
-
-	/* Since the guest can directly access the timebase, it must know the
-	 * real timebase frequency. Accordingly, it must see the state of
-	 * CCR1[TCS]. */
-	/* XXX CCR1 doesn't exist on all 440 SoCs. */
-	vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
-
-	for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
-		vcpu_44x->shadow_refs[i].gtlb_index = -1;
-
-	vcpu->arch.cpu_type = KVM_CPU_440;
-	vcpu->arch.pvr = mfspr(SPRN_PVR);
-
-	return 0;
-}
-
-/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
-int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
-                               struct kvm_translation *tr)
-{
-	int index;
-	gva_t eaddr;
-	u8 pid;
-	u8 as;
-
-	eaddr = tr->linear_address;
-	pid = (tr->linear_address >> 32) & 0xff;
-	as = (tr->linear_address >> 40) & 0x1;
-
-	index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
-	if (index == -1) {
-		tr->valid = 0;
-		return 0;
-	}
-
-	tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr);
-	/* XXX what does "writeable" and "usermode" even mean? */
-	tr->valid = 1;
-
-	return 0;
-}
-
-static int kvmppc_core_get_sregs_44x(struct kvm_vcpu *vcpu,
-				      struct kvm_sregs *sregs)
-{
-	return kvmppc_get_sregs_ivor(vcpu, sregs);
-}
-
-static int kvmppc_core_set_sregs_44x(struct kvm_vcpu *vcpu,
-				     struct kvm_sregs *sregs)
-{
-	return kvmppc_set_sregs_ivor(vcpu, sregs);
-}
-
-static int kvmppc_get_one_reg_44x(struct kvm_vcpu *vcpu, u64 id,
-				  union kvmppc_one_reg *val)
-{
-	return -EINVAL;
-}
-
-static int kvmppc_set_one_reg_44x(struct kvm_vcpu *vcpu, u64 id,
-				  union kvmppc_one_reg *val)
-{
-	return -EINVAL;
-}
-
-static struct kvm_vcpu *kvmppc_core_vcpu_create_44x(struct kvm *kvm,
-						    unsigned int id)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x;
-	struct kvm_vcpu *vcpu;
-	int err;
-
-	vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
-	if (!vcpu_44x) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	vcpu = &vcpu_44x->vcpu;
-	err = kvm_vcpu_init(vcpu, kvm, id);
-	if (err)
-		goto free_vcpu;
-
-	vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
-	if (!vcpu->arch.shared)
-		goto uninit_vcpu;
-
-	return vcpu;
-
-uninit_vcpu:
-	kvm_vcpu_uninit(vcpu);
-free_vcpu:
-	kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
-out:
-	return ERR_PTR(err);
-}
-
-static void kvmppc_core_vcpu_free_44x(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-
-	free_page((unsigned long)vcpu->arch.shared);
-	kvm_vcpu_uninit(vcpu);
-	kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
-}
-
-static int kvmppc_core_init_vm_44x(struct kvm *kvm)
-{
-	return 0;
-}
-
-static void kvmppc_core_destroy_vm_44x(struct kvm *kvm)
-{
-}
-
-static struct kvmppc_ops kvm_ops_44x = {
-	.get_sregs = kvmppc_core_get_sregs_44x,
-	.set_sregs = kvmppc_core_set_sregs_44x,
-	.get_one_reg = kvmppc_get_one_reg_44x,
-	.set_one_reg = kvmppc_set_one_reg_44x,
-	.vcpu_load   = kvmppc_core_vcpu_load_44x,
-	.vcpu_put    = kvmppc_core_vcpu_put_44x,
-	.vcpu_create = kvmppc_core_vcpu_create_44x,
-	.vcpu_free   = kvmppc_core_vcpu_free_44x,
-	.mmu_destroy  = kvmppc_mmu_destroy_44x,
-	.init_vm = kvmppc_core_init_vm_44x,
-	.destroy_vm = kvmppc_core_destroy_vm_44x,
-	.emulate_op = kvmppc_core_emulate_op_44x,
-	.emulate_mtspr = kvmppc_core_emulate_mtspr_44x,
-	.emulate_mfspr = kvmppc_core_emulate_mfspr_44x,
-};
-
-static int __init kvmppc_44x_init(void)
-{
-	int r;
-
-	r = kvmppc_booke_init();
-	if (r)
-		goto err_out;
-
-	r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE);
-	if (r)
-		goto err_out;
-	kvm_ops_44x.owner = THIS_MODULE;
-	kvmppc_pr_ops = &kvm_ops_44x;
-
-err_out:
-	return r;
-}
-
-static void __exit kvmppc_44x_exit(void)
-{
-	kvmppc_pr_ops = NULL;
-	kvmppc_booke_exit();
-}
-
-module_init(kvmppc_44x_init);
-module_exit(kvmppc_44x_exit);
-MODULE_ALIAS_MISCDEV(KVM_MINOR);
-MODULE_ALIAS("devname:kvm");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/44x_emulate.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_emulate.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/44x_emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_emulate.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,194 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <asm/kvm_ppc.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#include <asm/disassemble.h>
-#include <asm/kvm_44x.h>
-#include "timing.h"
-
-#include "booke.h"
-#include "44x_tlb.h"
-
-#define XOP_MFDCRX  259
-#define XOP_MFDCR   323
-#define XOP_MTDCRX  387
-#define XOP_MTDCR   451
-#define XOP_TLBSX   914
-#define XOP_ICCCI   966
-#define XOP_TLBWE   978
-
-static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
-{
-	/* emulate some access in kernel */
-	switch (dcrn) {
-	case DCRN_CPR0_CONFIG_ADDR:
-		vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
-		return EMULATE_DONE;
-	default:
-		vcpu->run->dcr.dcrn = dcrn;
-		vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
-		vcpu->run->dcr.is_write = 1;
-		vcpu->arch.dcr_is_write = 1;
-		vcpu->arch.dcr_needed = 1;
-		kvmppc_account_exit(vcpu, DCR_EXITS);
-		return EMULATE_DO_DCR;
-	}
-}
-
-static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
-{
-	/* The guest may access CPR0 registers to determine the timebase
-	 * frequency, and it must know the real host frequency because it
-	 * can directly access the timebase registers.
-	 *
-	 * It would be possible to emulate those accesses in userspace,
-	 * but userspace can really only figure out the end frequency.
-	 * We could decompose that into the factors that compute it, but
-	 * that's tricky math, and it's easier to just report the real
-	 * CPR0 values.
-	 */
-	switch (dcrn) {
-	case DCRN_CPR0_CONFIG_ADDR:
-		kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
-		break;
-	case DCRN_CPR0_CONFIG_DATA:
-		local_irq_disable();
-		mtdcr(DCRN_CPR0_CONFIG_ADDR,
-			  vcpu->arch.cpr0_cfgaddr);
-		kvmppc_set_gpr(vcpu, rt,
-			       mfdcr(DCRN_CPR0_CONFIG_DATA));
-		local_irq_enable();
-		break;
-	default:
-		vcpu->run->dcr.dcrn = dcrn;
-		vcpu->run->dcr.data =  0;
-		vcpu->run->dcr.is_write = 0;
-		vcpu->arch.dcr_is_write = 0;
-		vcpu->arch.io_gpr = rt;
-		vcpu->arch.dcr_needed = 1;
-		kvmppc_account_exit(vcpu, DCR_EXITS);
-		return EMULATE_DO_DCR;
-	}
-
-	return EMULATE_DONE;
-}
-
-int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu,
-			       unsigned int inst, int *advance)
-{
-	int emulated = EMULATE_DONE;
-	int dcrn = get_dcrn(inst);
-	int ra = get_ra(inst);
-	int rb = get_rb(inst);
-	int rc = get_rc(inst);
-	int rs = get_rs(inst);
-	int rt = get_rt(inst);
-	int ws = get_ws(inst);
-
-	switch (get_op(inst)) {
-	case 31:
-		switch (get_xop(inst)) {
-
-		case XOP_MFDCR:
-			emulated = emulate_mfdcr(vcpu, rt, dcrn);
-			break;
-
-		case XOP_MFDCRX:
-			emulated = emulate_mfdcr(vcpu, rt,
-					kvmppc_get_gpr(vcpu, ra));
-			break;
-
-		case XOP_MTDCR:
-			emulated = emulate_mtdcr(vcpu, rs, dcrn);
-			break;
-
-		case XOP_MTDCRX:
-			emulated = emulate_mtdcr(vcpu, rs,
-					kvmppc_get_gpr(vcpu, ra));
-			break;
-
-		case XOP_TLBWE:
-			emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws);
-			break;
-
-		case XOP_TLBSX:
-			emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc);
-			break;
-
-		case XOP_ICCCI:
-			break;
-
-		default:
-			emulated = EMULATE_FAIL;
-		}
-
-		break;
-
-	default:
-		emulated = EMULATE_FAIL;
-	}
-
-	if (emulated == EMULATE_FAIL)
-		emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
-
-	return emulated;
-}
-
-int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
-{
-	int emulated = EMULATE_DONE;
-
-	switch (sprn) {
-	case SPRN_PID:
-		kvmppc_set_pid(vcpu, spr_val); break;
-	case SPRN_MMUCR:
-		vcpu->arch.mmucr = spr_val; break;
-	case SPRN_CCR0:
-		vcpu->arch.ccr0 = spr_val; break;
-	case SPRN_CCR1:
-		vcpu->arch.ccr1 = spr_val; break;
-	default:
-		emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val);
-	}
-
-	return emulated;
-}
-
-int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
-{
-	int emulated = EMULATE_DONE;
-
-	switch (sprn) {
-	case SPRN_PID:
-		*spr_val = vcpu->arch.pid; break;
-	case SPRN_MMUCR:
-		*spr_val = vcpu->arch.mmucr; break;
-	case SPRN_CCR0:
-		*spr_val = vcpu->arch.ccr0; break;
-	case SPRN_CCR1:
-		*spr_val = vcpu->arch.ccr1; break;
-	default:
-		emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val);
-	}
-
-	return emulated;
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/44x_tlb.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_tlb.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/44x_tlb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_tlb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,528 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright IBM Corp. 2007
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kvm.h>
-#include <linux/kvm_host.h>
-#include <linux/highmem.h>
-
-#include <asm/tlbflush.h>
-#include <asm/mmu-44x.h>
-#include <asm/kvm_ppc.h>
-#include <asm/kvm_44x.h>
-#include "timing.h"
-
-#include "44x_tlb.h"
-#include "trace.h"
-
-#ifndef PPC44x_TLBE_SIZE
-#define PPC44x_TLBE_SIZE	PPC44x_TLB_4K
-#endif
-
-#define PAGE_SIZE_4K (1<<12)
-#define PAGE_MASK_4K (~(PAGE_SIZE_4K - 1))
-
-#define PPC44x_TLB_UATTR_MASK \
-	(PPC44x_TLB_U0|PPC44x_TLB_U1|PPC44x_TLB_U2|PPC44x_TLB_U3)
-#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
-#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
-
-#ifdef DEBUG
-void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	struct kvmppc_44x_tlbe *tlbe;
-	int i;
-
-	printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
-	printk("| %2s | %3s | %8s | %8s | %8s |\n",
-			"nr", "tid", "word0", "word1", "word2");
-
-	for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
-		tlbe = &vcpu_44x->guest_tlb[i];
-		if (tlbe->word0 & PPC44x_TLB_VALID)
-			printk(" G%2d |  %02X | %08X | %08X | %08X |\n",
-			       i, tlbe->tid, tlbe->word0, tlbe->word1,
-			       tlbe->word2);
-	}
-}
-#endif
-
-static inline void kvmppc_44x_tlbie(unsigned int index)
-{
-	/* 0 <= index < 64, so the V bit is clear and we can use the index as
-	 * word0. */
-	asm volatile(
-		"tlbwe %[index], %[index], 0\n"
-	:
-	: [index] "r"(index)
-	);
-}
-
-static inline void kvmppc_44x_tlbre(unsigned int index,
-                                    struct kvmppc_44x_tlbe *tlbe)
-{
-	asm volatile(
-		"tlbre %[word0], %[index], 0\n"
-		"mfspr %[tid], %[sprn_mmucr]\n"
-		"andi. %[tid], %[tid], 0xff\n"
-		"tlbre %[word1], %[index], 1\n"
-		"tlbre %[word2], %[index], 2\n"
-		: [word0] "=r"(tlbe->word0),
-		  [word1] "=r"(tlbe->word1),
-		  [word2] "=r"(tlbe->word2),
-		  [tid]   "=r"(tlbe->tid)
-		: [index] "r"(index),
-		  [sprn_mmucr] "i"(SPRN_MMUCR)
-		: "cc"
-	);
-}
-
-static inline void kvmppc_44x_tlbwe(unsigned int index,
-                                    struct kvmppc_44x_tlbe *stlbe)
-{
-	unsigned long tmp;
-
-	asm volatile(
-		"mfspr %[tmp], %[sprn_mmucr]\n"
-		"rlwimi %[tmp], %[tid], 0, 0xff\n"
-		"mtspr %[sprn_mmucr], %[tmp]\n"
-		"tlbwe %[word0], %[index], 0\n"
-		"tlbwe %[word1], %[index], 1\n"
-		"tlbwe %[word2], %[index], 2\n"
-		: [tmp]   "=&r"(tmp)
-		: [word0] "r"(stlbe->word0),
-		  [word1] "r"(stlbe->word1),
-		  [word2] "r"(stlbe->word2),
-		  [tid]   "r"(stlbe->tid),
-		  [index] "r"(index),
-		  [sprn_mmucr] "i"(SPRN_MMUCR)
-	);
-}
-
-static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
-{
-	/* We only care about the guest's permission and user bits. */
-	attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_UATTR_MASK;
-
-	if (!usermode) {
-		/* Guest is in supervisor mode, so we need to translate guest
-		 * supervisor permissions into user permissions. */
-		attrib &= ~PPC44x_TLB_USER_PERM_MASK;
-		attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3;
-	}
-
-	/* Make sure host can always access this memory. */
-	attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW;
-
-	/* WIMGE = 0b00100 */
-	attrib |= PPC44x_TLB_M;
-
-	return attrib;
-}
-
-/* Load shadow TLB back into hardware. */
-void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	for (i = 0; i <= tlb_44x_hwater; i++) {
-		struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
-
-		if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
-			kvmppc_44x_tlbwe(i, stlbe);
-	}
-}
-
-static void kvmppc_44x_tlbe_set_modified(struct kvmppc_vcpu_44x *vcpu_44x,
-                                         unsigned int i)
-{
-	vcpu_44x->shadow_tlb_mod[i] = 1;
-}
-
-/* Save hardware TLB to the vcpu, and invalidate all guest mappings. */
-void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	for (i = 0; i <= tlb_44x_hwater; i++) {
-		struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
-
-		if (vcpu_44x->shadow_tlb_mod[i])
-			kvmppc_44x_tlbre(i, stlbe);
-
-		if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
-			kvmppc_44x_tlbie(i);
-	}
-}
-
-
-/* Search the guest TLB for a matching entry. */
-int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
-                         unsigned int as)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	/* XXX Replace loop with fancy data structures. */
-	for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
-		struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[i];
-		unsigned int tid;
-
-		if (eaddr < get_tlb_eaddr(tlbe))
-			continue;
-
-		if (eaddr > get_tlb_end(tlbe))
-			continue;
-
-		tid = get_tlb_tid(tlbe);
-		if (tid && (tid != pid))
-			continue;
-
-		if (!get_tlb_v(tlbe))
-			continue;
-
-		if (get_tlb_ts(tlbe) != as)
-			continue;
-
-		return i;
-	}
-
-	return -1;
-}
-
-gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
-                       gva_t eaddr)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
-	unsigned int pgmask = get_tlb_bytes(gtlbe) - 1;
-
-	return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
-}
-
-int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
-{
-	unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
-
-	return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-}
-
-int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
-{
-	unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
-
-	return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-}
-
-void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
-{
-}
-
-void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
-{
-}
-
-static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x,
-                                      unsigned int stlb_index)
-{
-	struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[stlb_index];
-
-	if (!ref->page)
-		return;
-
-	/* Discard from the TLB. */
-	/* Note: we could actually invalidate a host mapping, if the host overwrote
-	 * this TLB entry since we inserted a guest mapping. */
-	kvmppc_44x_tlbie(stlb_index);
-
-	/* Now release the page. */
-	if (ref->writeable)
-		kvm_release_page_dirty(ref->page);
-	else
-		kvm_release_page_clean(ref->page);
-
-	ref->page = NULL;
-
-	/* XXX set tlb_44x_index to stlb_index? */
-
-	trace_kvm_stlb_inval(stlb_index);
-}
-
-void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	for (i = 0; i <= tlb_44x_hwater; i++)
-		kvmppc_44x_shadow_release(vcpu_44x, i);
-}
-
-/**
- * kvmppc_mmu_map -- create a host mapping for guest memory
- *
- * If the guest wanted a larger page than the host supports, only the first
- * host page is mapped here and the rest are demand faulted.
- *
- * If the guest wanted a smaller page than the host page size, we map only the
- * guest-size page (i.e. not a full host page mapping).
- *
- * Caller must ensure that the specified guest TLB entry is safe to insert into
- * the shadow TLB.
- */
-void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
-                    unsigned int gtlb_index)
-{
-	struct kvmppc_44x_tlbe stlbe;
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
-	struct kvmppc_44x_shadow_ref *ref;
-	struct page *new_page;
-	hpa_t hpaddr;
-	gfn_t gfn;
-	u32 asid = gtlbe->tid;
-	u32 flags = gtlbe->word2;
-	u32 max_bytes = get_tlb_bytes(gtlbe);
-	unsigned int victim;
-
-	/* Select TLB entry to clobber. Indirectly guard against races with the TLB
-	 * miss handler by disabling interrupts. */
-	local_irq_disable();
-	victim = ++tlb_44x_index;
-	if (victim > tlb_44x_hwater)
-		victim = 0;
-	tlb_44x_index = victim;
-	local_irq_enable();
-
-	/* Get reference to new page. */
-	gfn = gpaddr >> PAGE_SHIFT;
-	new_page = gfn_to_page(vcpu->kvm, gfn);
-	if (is_error_page(new_page)) {
-		printk(KERN_ERR "Couldn't get guest page for gfn %llx!\n",
-			(unsigned long long)gfn);
-		return;
-	}
-	hpaddr = page_to_phys(new_page);
-
-	/* Invalidate any previous shadow mappings. */
-	kvmppc_44x_shadow_release(vcpu_44x, victim);
-
-	/* XXX Make sure (va, size) doesn't overlap any other
-	 * entries. 440x6 user manual says the result would be
-	 * "undefined." */
-
-	/* XXX what about AS? */
-
-	/* Force TS=1 for all guest mappings. */
-	stlbe.word0 = PPC44x_TLB_VALID | PPC44x_TLB_TS;
-
-	if (max_bytes >= PAGE_SIZE) {
-		/* Guest mapping is larger than or equal to host page size. We can use
-		 * a "native" host mapping. */
-		stlbe.word0 |= (gvaddr & PAGE_MASK) | PPC44x_TLBE_SIZE;
-	} else {
-		/* Guest mapping is smaller than host page size. We must restrict the
-		 * size of the mapping to be at most the smaller of the two, but for
-		 * simplicity we fall back to a 4K mapping (this is probably what the
-		 * guest is using anyways). */
-		stlbe.word0 |= (gvaddr & PAGE_MASK_4K) | PPC44x_TLB_4K;
-
-		/* 'hpaddr' is a host page, which is larger than the mapping we're
-		 * inserting here. To compensate, we must add the in-page offset to the
-		 * sub-page. */
-		hpaddr |= gpaddr & (PAGE_MASK ^ PAGE_MASK_4K);
-	}
-
-	stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
-	stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
-	                                            vcpu->arch.shared->msr & MSR_PR);
-	stlbe.tid = !(asid & 0xff);
-
-	/* Keep track of the reference so we can properly release it later. */
-	ref = &vcpu_44x->shadow_refs[victim];
-	ref->page = new_page;
-	ref->gtlb_index = gtlb_index;
-	ref->writeable = !!(stlbe.word2 & PPC44x_TLB_UW);
-	ref->tid = stlbe.tid;
-
-	/* Insert shadow mapping into hardware TLB. */
-	kvmppc_44x_tlbe_set_modified(vcpu_44x, victim);
-	kvmppc_44x_tlbwe(victim, &stlbe);
-	trace_kvm_stlb_write(victim, stlbe.tid, stlbe.word0, stlbe.word1,
-			     stlbe.word2);
-}
-
-/* For a particular guest TLB entry, invalidate the corresponding host TLB
- * mappings and release the host pages. */
-static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
-                                  unsigned int gtlb_index)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
-		struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
-		if (ref->gtlb_index == gtlb_index)
-			kvmppc_44x_shadow_release(vcpu_44x, i);
-	}
-}
-
-void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
-{
-	int usermode = vcpu->arch.shared->msr & MSR_PR;
-
-	vcpu->arch.shadow_pid = !usermode;
-}
-
-void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	int i;
-
-	if (unlikely(vcpu->arch.pid == new_pid))
-		return;
-
-	vcpu->arch.pid = new_pid;
-
-	/* Guest userspace runs with TID=0 mappings and PID=0, to make sure it
-	 * can't access guest kernel mappings (TID=1). When we switch to a new
-	 * guest PID, which will also use host PID=0, we must discard the old guest
-	 * userspace mappings. */
-	for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
-		struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
-
-		if (ref->tid == 0)
-			kvmppc_44x_shadow_release(vcpu_44x, i);
-	}
-}
-
-static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
-                             const struct kvmppc_44x_tlbe *tlbe)
-{
-	gpa_t gpa;
-
-	if (!get_tlb_v(tlbe))
-		return 0;
-
-	/* Does it match current guest AS? */
-	/* XXX what about IS != DS? */
-	if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
-		return 0;
-
-	gpa = get_tlb_raddr(tlbe);
-	if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
-		/* Mapping is not for RAM. */
-		return 0;
-
-	return 1;
-}
-
-int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
-{
-	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-	struct kvmppc_44x_tlbe *tlbe;
-	unsigned int gtlb_index;
-	int idx;
-
-	gtlb_index = kvmppc_get_gpr(vcpu, ra);
-	if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) {
-		printk("%s: index %d\n", __func__, gtlb_index);
-		kvmppc_dump_vcpu(vcpu);
-		return EMULATE_FAIL;
-	}
-
-	tlbe = &vcpu_44x->guest_tlb[gtlb_index];
-
-	/* Invalidate shadow mappings for the about-to-be-clobbered TLB entry. */
-	if (tlbe->word0 & PPC44x_TLB_VALID)
-		kvmppc_44x_invalidate(vcpu, gtlb_index);
-
-	switch (ws) {
-	case PPC44x_TLB_PAGEID:
-		tlbe->tid = get_mmucr_stid(vcpu);
-		tlbe->word0 = kvmppc_get_gpr(vcpu, rs);
-		break;
-
-	case PPC44x_TLB_XLAT:
-		tlbe->word1 = kvmppc_get_gpr(vcpu, rs);
-		break;
-
-	case PPC44x_TLB_ATTRIB:
-		tlbe->word2 = kvmppc_get_gpr(vcpu, rs);
-		break;
-
-	default:
-		return EMULATE_FAIL;
-	}
-
-	idx = srcu_read_lock(&vcpu->kvm->srcu);
-
-	if (tlbe_is_host_safe(vcpu, tlbe)) {
-		gva_t eaddr;
-		gpa_t gpaddr;
-		u32 bytes;
-
-		eaddr = get_tlb_eaddr(tlbe);
-		gpaddr = get_tlb_raddr(tlbe);
-
-		/* Use the advertised page size to mask effective and real addrs. */
-		bytes = get_tlb_bytes(tlbe);
-		eaddr &= ~(bytes - 1);
-		gpaddr &= ~(bytes - 1);
-
-		kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index);
-	}
-
-	srcu_read_unlock(&vcpu->kvm->srcu, idx);
-
-	trace_kvm_gtlb_write(gtlb_index, tlbe->tid, tlbe->word0, tlbe->word1,
-			     tlbe->word2);
-
-	kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
-	return EMULATE_DONE;
-}
-
-int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8 rc)
-{
-	u32 ea;
-	int gtlb_index;
-	unsigned int as = get_mmucr_sts(vcpu);
-	unsigned int pid = get_mmucr_stid(vcpu);
-
-	ea = kvmppc_get_gpr(vcpu, rb);
-	if (ra)
-		ea += kvmppc_get_gpr(vcpu, ra);
-
-	gtlb_index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
-	if (rc) {
-		u32 cr = kvmppc_get_cr(vcpu);
-
-		if (gtlb_index < 0)
-			kvmppc_set_cr(vcpu, cr & ~0x20000000);
-		else
-			kvmppc_set_cr(vcpu, cr | 0x20000000);
-	}
-	kvmppc_set_gpr(vcpu, rt, gtlb_index);
-
-	kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
-	return EMULATE_DONE;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/44x_tlb.h linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_tlb.h
--- linux-libre-3.16-gnu/arch/powerpc/kvm/44x_tlb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/44x_tlb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright IBM Corp. 2007
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#ifndef __KVM_POWERPC_TLB_H__
-#define __KVM_POWERPC_TLB_H__
-
-#include <linux/kvm_host.h>
-#include <asm/mmu-44x.h>
-
-extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
-                                unsigned int pid, unsigned int as);
-
-extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb,
-                                 u8 rc);
-extern int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws);
-
-/* TLB helper functions */
-static inline unsigned int get_tlb_size(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return (tlbe->word0 >> 4) & 0xf;
-}
-
-static inline gva_t get_tlb_eaddr(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return tlbe->word0 & 0xfffffc00;
-}
-
-static inline gva_t get_tlb_bytes(const struct kvmppc_44x_tlbe *tlbe)
-{
-	unsigned int pgsize = get_tlb_size(tlbe);
-	return 1 << 10 << (pgsize << 1);
-}
-
-static inline gva_t get_tlb_end(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1;
-}
-
-static inline u64 get_tlb_raddr(const struct kvmppc_44x_tlbe *tlbe)
-{
-	u64 word1 = tlbe->word1;
-	return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00);
-}
-
-static inline unsigned int get_tlb_tid(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return tlbe->tid & 0xff;
-}
-
-static inline unsigned int get_tlb_ts(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return (tlbe->word0 >> 8) & 0x1;
-}
-
-static inline unsigned int get_tlb_v(const struct kvmppc_44x_tlbe *tlbe)
-{
-	return (tlbe->word0 >> 9) & 0x1;
-}
-
-static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.mmucr & 0xff;
-}
-
-static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu)
-{
-	return (vcpu->arch.mmucr >> 16) & 0x1;
-}
-
-#endif /* __KVM_POWERPC_TLB_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_32_mmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_32_mmu.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_32_mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_32_mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -335,7 +335,7 @@ static int kvmppc_mmu_book3s_32_xlate(st
 	if (r < 0)
 		r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte,
 						   data, iswrite, true);
-	if (r < 0)
+	if (r == -ENOENT)
 		r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte,
 						   data, iswrite, false);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_32_mmu_host.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_32_mmu_host.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_32_mmu_host.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_32_mmu_host.c	2014-09-28 17:29:07.000000000 -0400
@@ -156,11 +156,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu
 	bool writable;
 
 	/* Get host physical address for gpa */
-	hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT,
-				   iswrite, &writable);
+	hpaddr = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
 	if (is_error_noslot_pfn(hpaddr)) {
-		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
-				 orig_pte->eaddr);
+		printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
+				 orig_pte->raddr);
 		r = -EINVAL;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_64_mmu_host.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_64_mmu_host.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_64_mmu_host.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_64_mmu_host.c	2014-09-28 17:29:07.000000000 -0400
@@ -104,9 +104,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu
 	smp_rmb();
 
 	/* Get host physical address for gpa */
-	pfn = kvmppc_gfn_to_pfn(vcpu, gfn, iswrite, &writable);
+	pfn = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
 	if (is_error_noslot_pfn(pfn)) {
-		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", gfn);
+		printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
+		       orig_pte->raddr);
 		r = -EINVAL;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,8 +37,6 @@
 #include <asm/ppc-opcode.h>
 #include <asm/cputable.h>
 
-#include "book3s_hv_cma.h"
-
 /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
 #define MAX_LPID_970	63
 
@@ -64,10 +62,10 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u
 	}
 
 	kvm->arch.hpt_cma_alloc = 0;
-	VM_BUG_ON(order < KVM_CMA_CHUNK_ORDER);
-	page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
+	page = kvm_alloc_hpt(1ul << (order - PAGE_SHIFT));
 	if (page) {
 		hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+		memset((void *)hpt, 0, (1ul << order));
 		kvm->arch.hpt_cma_alloc = 1;
 	}
 
@@ -450,7 +448,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate
 	unsigned long slb_v;
 	unsigned long pp, key;
 	unsigned long v, gr;
-	unsigned long *hptep;
+	__be64 *hptep;
 	int index;
 	int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
 
@@ -473,13 +471,13 @@ static int kvmppc_mmu_book3s_64_hv_xlate
 		preempt_enable();
 		return -ENOENT;
 	}
-	hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
-	v = hptep[0] & ~HPTE_V_HVLOCK;
+	hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
+	v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
 	gr = kvm->arch.revmap[index].guest_rpte;
 
 	/* Unlock the HPTE */
 	asm volatile("lwsync" : : : "memory");
-	hptep[0] = v;
+	hptep[0] = cpu_to_be64(v);
 	preempt_enable();
 
 	gpte->eaddr = eaddr;
@@ -530,21 +528,14 @@ static int instruction_is_store(unsigned
 static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
 				  unsigned long gpa, gva_t ea, int is_store)
 {
-	int ret;
 	u32 last_inst;
-	unsigned long srr0 = kvmppc_get_pc(vcpu);
 
-	/* We try to load the last instruction.  We don't let
-	 * emulate_instruction do it as it doesn't check what
-	 * kvmppc_ld returns.
+	/*
 	 * If we fail, we just return to the guest and try executing it again.
 	 */
-	if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) {
-		ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
-		if (ret != EMULATE_DONE || last_inst == KVM_INST_FETCH_FAILED)
-			return RESUME_GUEST;
-		vcpu->arch.last_inst = last_inst;
-	}
+	if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) !=
+		EMULATE_DONE)
+		return RESUME_GUEST;
 
 	/*
 	 * WARNING: We do not know for sure whether the instruction we just
@@ -558,7 +549,7 @@ static int kvmppc_hv_emulate_mmio(struct
 	 * we just return and retry the instruction.
 	 */
 
-	if (instruction_is_store(kvmppc_get_last_inst(vcpu)) != !!is_store)
+	if (instruction_is_store(last_inst) != !!is_store)
 		return RESUME_GUEST;
 
 	/*
@@ -583,7 +574,8 @@ int kvmppc_book3s_hv_page_fault(struct k
 				unsigned long ea, unsigned long dsisr)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long *hptep, hpte[3], r;
+	unsigned long hpte[3], r;
+	__be64 *hptep;
 	unsigned long mmu_seq, psize, pte_size;
 	unsigned long gpa_base, gfn_base;
 	unsigned long gpa, gfn, hva, pfn;
@@ -606,16 +598,16 @@ int kvmppc_book3s_hv_page_fault(struct k
 	if (ea != vcpu->arch.pgfault_addr)
 		return RESUME_GUEST;
 	index = vcpu->arch.pgfault_index;
-	hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+	hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
 	rev = &kvm->arch.revmap[index];
 	preempt_disable();
 	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
 		cpu_relax();
-	hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
-	hpte[1] = hptep[1];
+	hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
+	hpte[1] = be64_to_cpu(hptep[1]);
 	hpte[2] = r = rev->guest_rpte;
 	asm volatile("lwsync" : : : "memory");
-	hptep[0] = hpte[0];
+	hptep[0] = cpu_to_be64(hpte[0]);
 	preempt_enable();
 
 	if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
@@ -731,8 +723,9 @@ int kvmppc_book3s_hv_page_fault(struct k
 	preempt_disable();
 	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
-	    rev->guest_rpte != hpte[2])
+	if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] ||
+		be64_to_cpu(hptep[1]) != 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;
@@ -752,20 +745,20 @@ int kvmppc_book3s_hv_page_fault(struct k
 	rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
 	r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
 
-	if (hptep[0] & HPTE_V_VALID) {
+	if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) {
 		/* HPTE was previously valid, so we need to invalidate it */
 		unlock_rmap(rmap);
-		hptep[0] |= HPTE_V_ABSENT;
+		hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 		kvmppc_invalidate_hpte(kvm, hptep, index);
 		/* don't lose previous R and C bits */
-		r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
+		r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
 	} else {
 		kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
 	}
 
-	hptep[1] = r;
+	hptep[1] = cpu_to_be64(r);
 	eieio();
-	hptep[0] = hpte[0];
+	hptep[0] = cpu_to_be64(hpte[0]);
 	asm volatile("ptesync" : : : "memory");
 	preempt_enable();
 	if (page && hpte_is_writable(r))
@@ -784,7 +777,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 	return ret;
 
  out_unlock:
-	hptep[0] &= ~HPTE_V_HVLOCK;
+	hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	preempt_enable();
 	goto out_put;
 }
@@ -860,7 +853,7 @@ static int kvm_unmap_rmapp(struct kvm *k
 {
 	struct revmap_entry *rev = kvm->arch.revmap;
 	unsigned long h, i, j;
-	unsigned long *hptep;
+	__be64 *hptep;
 	unsigned long ptel, psize, rcbits;
 
 	for (;;) {
@@ -876,11 +869,11 @@ static int kvm_unmap_rmapp(struct kvm *k
 		 * rmap chain lock.
 		 */
 		i = *rmapp & KVMPPC_RMAP_INDEX;
-		hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+		hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
 				cpu_relax();
 			continue;
 		}
@@ -899,14 +892,14 @@ static int kvm_unmap_rmapp(struct kvm *k
 
 		/* Now check and modify the HPTE */
 		ptel = rev[i].guest_rpte;
-		psize = hpte_page_size(hptep[0], ptel);
-		if ((hptep[0] & HPTE_V_VALID) &&
+		psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
+		if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
 		    hpte_rpn(ptel, psize) == gfn) {
 			if (kvm->arch.using_mmu_notifiers)
-				hptep[0] |= HPTE_V_ABSENT;
+				hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 			kvmppc_invalidate_hpte(kvm, hptep, i);
 			/* Harvest R and C */
-			rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
+			rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
 			*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
 			if (rcbits & ~rev[i].guest_rpte) {
 				rev[i].guest_rpte = ptel | rcbits;
@@ -914,7 +907,7 @@ static int kvm_unmap_rmapp(struct kvm *k
 			}
 		}
 		unlock_rmap(rmapp);
-		hptep[0] &= ~HPTE_V_HVLOCK;
+		hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	}
 	return 0;
 }
@@ -961,7 +954,7 @@ static int kvm_age_rmapp(struct kvm *kvm
 {
 	struct revmap_entry *rev = kvm->arch.revmap;
 	unsigned long head, i, j;
-	unsigned long *hptep;
+	__be64 *hptep;
 	int ret = 0;
 
  retry:
@@ -977,23 +970,24 @@ static int kvm_age_rmapp(struct kvm *kvm
 
 	i = head = *rmapp & KVMPPC_RMAP_INDEX;
 	do {
-		hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+		hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
 		j = rev[i].forw;
 
 		/* If this HPTE isn't referenced, ignore it */
-		if (!(hptep[1] & HPTE_R_R))
+		if (!(be64_to_cpu(hptep[1]) & HPTE_R_R))
 			continue;
 
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
 				cpu_relax();
 			goto retry;
 		}
 
 		/* Now check and modify the HPTE */
-		if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
+		if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
+		    (be64_to_cpu(hptep[1]) & HPTE_R_R)) {
 			kvmppc_clear_ref_hpte(kvm, hptep, i);
 			if (!(rev[i].guest_rpte & HPTE_R_R)) {
 				rev[i].guest_rpte |= HPTE_R_R;
@@ -1001,7 +995,7 @@ static int kvm_age_rmapp(struct kvm *kvm
 			}
 			ret = 1;
 		}
-		hptep[0] &= ~HPTE_V_HVLOCK;
+		hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 	} while ((i = j) != head);
 
 	unlock_rmap(rmapp);
@@ -1035,7 +1029,7 @@ static int kvm_test_age_rmapp(struct kvm
 		do {
 			hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
 			j = rev[i].forw;
-			if (hp[1] & HPTE_R_R)
+			if (be64_to_cpu(hp[1]) & HPTE_R_R)
 				goto out;
 		} while ((i = j) != head);
 	}
@@ -1075,7 +1069,7 @@ static int kvm_test_clear_dirty_npages(s
 	unsigned long head, i, j;
 	unsigned long n;
 	unsigned long v, r;
-	unsigned long *hptep;
+	__be64 *hptep;
 	int npages_dirty = 0;
 
  retry:
@@ -1091,7 +1085,8 @@ static int kvm_test_clear_dirty_npages(s
 
 	i = head = *rmapp & KVMPPC_RMAP_INDEX;
 	do {
-		hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+		unsigned long hptep1;
+		hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
 		j = rev[i].forw;
 
 		/*
@@ -1108,29 +1103,30 @@ static int kvm_test_clear_dirty_npages(s
 		 * Otherwise we need to do the tlbie even if C==0 in
 		 * order to pick up any delayed writeback of C.
 		 */
-		if (!(hptep[1] & HPTE_R_C) &&
-		    (!hpte_is_writable(hptep[1]) || vcpus_running(kvm)))
+		hptep1 = be64_to_cpu(hptep[1]);
+		if (!(hptep1 & HPTE_R_C) &&
+		    (!hpte_is_writable(hptep1) || vcpus_running(kvm)))
 			continue;
 
 		if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 			/* unlock rmap before spinning on the HPTE lock */
 			unlock_rmap(rmapp);
-			while (hptep[0] & HPTE_V_HVLOCK)
+			while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK))
 				cpu_relax();
 			goto retry;
 		}
 
 		/* Now check and modify the HPTE */
-		if (!(hptep[0] & HPTE_V_VALID))
+		if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID)))
 			continue;
 
 		/* need to make it temporarily absent so C is stable */
-		hptep[0] |= HPTE_V_ABSENT;
+		hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 		kvmppc_invalidate_hpte(kvm, hptep, i);
-		v = hptep[0];
-		r = hptep[1];
+		v = be64_to_cpu(hptep[0]);
+		r = be64_to_cpu(hptep[1]);
 		if (r & HPTE_R_C) {
-			hptep[1] = r & ~HPTE_R_C;
+			hptep[1] = cpu_to_be64(r & ~HPTE_R_C);
 			if (!(rev[i].guest_rpte & HPTE_R_C)) {
 				rev[i].guest_rpte |= HPTE_R_C;
 				note_hpte_modification(kvm, &rev[i]);
@@ -1143,7 +1139,7 @@ static int kvm_test_clear_dirty_npages(s
 		}
 		v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
 		v |= HPTE_V_VALID;
-		hptep[0] = v;
+		hptep[0] = cpu_to_be64(v);
 	} while ((i = j) != head);
 
 	unlock_rmap(rmapp);
@@ -1307,7 +1303,7 @@ struct kvm_htab_ctx {
  * Returns 1 if this HPT entry has been modified or has pending
  * R/C bit changes.
  */
-static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp)
+static int hpte_dirty(struct revmap_entry *revp, __be64 *hptp)
 {
 	unsigned long rcbits_unset;
 
@@ -1316,13 +1312,14 @@ static int hpte_dirty(struct revmap_entr
 
 	/* Also need to consider changes in reference and changed bits */
 	rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
-	if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset))
+	if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) &&
+	    (be64_to_cpu(hptp[1]) & rcbits_unset))
 		return 1;
 
 	return 0;
 }
 
-static long record_hpte(unsigned long flags, unsigned long *hptp,
+static long record_hpte(unsigned long flags, __be64 *hptp,
 			unsigned long *hpte, struct revmap_entry *revp,
 			int want_valid, int first_pass)
 {
@@ -1337,10 +1334,10 @@ static long record_hpte(unsigned long fl
 		return 0;
 
 	valid = 0;
-	if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+	if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) {
 		valid = 1;
 		if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
-		    !(hptp[0] & HPTE_V_BOLTED))
+		    !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED))
 			valid = 0;
 	}
 	if (valid != want_valid)
@@ -1352,7 +1349,7 @@ static long record_hpte(unsigned long fl
 		preempt_disable();
 		while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
 			cpu_relax();
-		v = hptp[0];
+		v = be64_to_cpu(hptp[0]);
 
 		/* re-evaluate valid and dirty from synchronized HPTE value */
 		valid = !!(v & HPTE_V_VALID);
@@ -1360,9 +1357,9 @@ 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 & hptp[1])) {
-			revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) |
-				HPTE_GR_MODIFIED;
+		if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) {
+			revp->guest_rpte |= (be64_to_cpu(hptp[1]) &
+				(HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED;
 			dirty = 1;
 		}
 
@@ -1381,13 +1378,13 @@ static long record_hpte(unsigned long fl
 			revp->guest_rpte = r;
 		}
 		asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-		hptp[0] &= ~HPTE_V_HVLOCK;
+		hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		preempt_enable();
 		if (!(valid == want_valid && (first_pass || dirty)))
 			ok = 0;
 	}
-	hpte[0] = v;
-	hpte[1] = r;
+	hpte[0] = cpu_to_be64(v);
+	hpte[1] = cpu_to_be64(r);
 	return ok;
 }
 
@@ -1397,7 +1394,7 @@ static ssize_t kvm_htab_read(struct file
 	struct kvm_htab_ctx *ctx = file->private_data;
 	struct kvm *kvm = ctx->kvm;
 	struct kvm_get_htab_header hdr;
-	unsigned long *hptp;
+	__be64 *hptp;
 	struct revmap_entry *revp;
 	unsigned long i, nb, nw;
 	unsigned long __user *lbuf;
@@ -1413,7 +1410,7 @@ static ssize_t kvm_htab_read(struct file
 	flags = ctx->flags;
 
 	i = ctx->index;
-	hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+	hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
 	revp = kvm->arch.revmap + i;
 	lbuf = (unsigned long __user *)buf;
 
@@ -1497,7 +1494,7 @@ static ssize_t kvm_htab_write(struct fil
 	unsigned long i, j;
 	unsigned long v, r;
 	unsigned long __user *lbuf;
-	unsigned long *hptp;
+	__be64 *hptp;
 	unsigned long tmp[2];
 	ssize_t nb;
 	long int err, ret;
@@ -1539,7 +1536,7 @@ static ssize_t kvm_htab_write(struct fil
 		    i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte)
 			break;
 
-		hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+		hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
 		lbuf = (unsigned long __user *)buf;
 		for (j = 0; j < hdr.n_valid; ++j) {
 			err = -EFAULT;
@@ -1551,7 +1548,7 @@ static ssize_t kvm_htab_write(struct fil
 			lbuf += 2;
 			nb += HPTE_SIZE;
 
-			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+			if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
 				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
 			err = -EIO;
 			ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
@@ -1577,7 +1574,7 @@ static ssize_t kvm_htab_write(struct fil
 		}
 
 		for (j = 0; j < hdr.n_invalid; ++j) {
-			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+			if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
 				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
 			++i;
 			hptp += 2;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,6 +72,17 @@ void kvmppc_core_load_guest_debugstate(s
 {
 }
 
+void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) {
+		ulong pc = kvmppc_get_pc(vcpu);
+		if ((pc & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)
+			kvmppc_set_pc(vcpu, pc & ~SPLIT_HACK_MASK);
+		vcpu->arch.hflags &= ~BOOK3S_HFLAG_SPLIT_HACK;
+	}
+}
+EXPORT_SYMBOL_GPL(kvmppc_unfixup_split_real);
+
 static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
 {
 	if (!is_kvmppc_hv_enabled(vcpu->kvm))
@@ -118,6 +129,7 @@ static inline bool kvmppc_critical_secti
 
 void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
 {
+	kvmppc_unfixup_split_real(vcpu);
 	kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
 	kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags);
 	kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
@@ -218,6 +230,23 @@ void kvmppc_core_dequeue_external(struct
 	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
 }
 
+void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar,
+				    ulong flags)
+{
+	kvmppc_set_dar(vcpu, dar);
+	kvmppc_set_dsisr(vcpu, flags);
+	kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
+}
+
+void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong flags)
+{
+	u64 msr = kvmppc_get_msr(vcpu);
+	msr &= ~(SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
+	msr |= flags & (SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
+	kvmppc_set_msr_fast(vcpu, msr);
+	kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+}
+
 int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 {
 	int deliver = 1;
@@ -342,18 +371,18 @@ int kvmppc_core_prepare_to_enter(struct
 }
 EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter);
 
-pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
+pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
 			bool *writable)
 {
-	ulong mp_pa = vcpu->arch.magic_page_pa;
+	ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM;
+	gfn_t gfn = gpa >> PAGE_SHIFT;
 
 	if (!(kvmppc_get_msr(vcpu) & MSR_SF))
 		mp_pa = (uint32_t)mp_pa;
 
 	/* Magic page override */
-	if (unlikely(mp_pa) &&
-	    unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) ==
-		     ((mp_pa & PAGE_MASK) & KVM_PAM))) {
+	gpa &= ~0xFFFULL;
+	if (unlikely(mp_pa) && unlikely((gpa & KVM_PAM) == mp_pa)) {
 		ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
 		pfn_t pfn;
 
@@ -366,11 +395,13 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu
 
 	return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable);
 }
-EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn);
+EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn);
 
-static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
-			bool iswrite, struct kvmppc_pte *pte)
+int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
+		 enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
 {
+	bool data = (xlid == XLATE_DATA);
+	bool iswrite = (xlrw == XLATE_WRITE);
 	int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
 	int r;
 
@@ -384,88 +415,34 @@ static int kvmppc_xlate(struct kvm_vcpu
 		pte->may_write = true;
 		pte->may_execute = true;
 		r = 0;
+
+		if ((kvmppc_get_msr(vcpu) & (MSR_IR | MSR_DR)) == MSR_DR &&
+		    !data) {
+			if ((vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) &&
+			    ((eaddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS))
+			pte->raddr &= ~SPLIT_HACK_MASK;
+		}
 	}
 
 	return r;
 }
 
-static hva_t kvmppc_bad_hva(void)
-{
-	return PAGE_OFFSET;
-}
-
-static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte,
-			       bool read)
-{
-	hva_t hpage;
-
-	if (read && !pte->may_read)
-		goto err;
-
-	if (!read && !pte->may_write)
-		goto err;
-
-	hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
-	if (kvm_is_error_hva(hpage))
-		goto err;
-
-	return hpage | (pte->raddr & ~PAGE_MASK);
-err:
-	return kvmppc_bad_hva();
-}
-
-int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
-	      bool data)
-{
-	struct kvmppc_pte pte;
-
-	vcpu->stat.st++;
-
-	if (kvmppc_xlate(vcpu, *eaddr, data, true, &pte))
-		return -ENOENT;
-
-	*eaddr = pte.raddr;
-
-	if (!pte.may_write)
-		return -EPERM;
-
-	if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
-		return EMULATE_DO_MMIO;
-
-	return EMULATE_DONE;
-}
-EXPORT_SYMBOL_GPL(kvmppc_st);
-
-int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
-		      bool data)
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+					 u32 *inst)
 {
-	struct kvmppc_pte pte;
-	hva_t hva = *eaddr;
-
-	vcpu->stat.ld++;
-
-	if (kvmppc_xlate(vcpu, *eaddr, data, false, &pte))
-		goto nopte;
-
-	*eaddr = pte.raddr;
-
-	hva = kvmppc_pte_to_hva(vcpu, &pte, true);
-	if (kvm_is_error_hva(hva))
-		goto mmio;
-
-	if (copy_from_user(ptr, (void __user *)hva, size)) {
-		printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
-		goto mmio;
-	}
+	ulong pc = kvmppc_get_pc(vcpu);
+	int r;
 
-	return EMULATE_DONE;
+	if (type == INST_SC)
+		pc -= 4;
 
-nopte:
-	return -ENOENT;
-mmio:
-	return EMULATE_DO_MMIO;
+	r = kvmppc_ld(vcpu, &pc, sizeof(u32), inst, false);
+	if (r == EMULATE_DONE)
+		return r;
+	else
+		return EMULATE_AGAIN;
 }
-EXPORT_SYMBOL_GPL(kvmppc_ld);
+EXPORT_SYMBOL_GPL(kvmppc_load_last_inst);
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
@@ -646,6 +623,12 @@ int kvm_vcpu_ioctl_get_one_reg(struct kv
 		case KVM_REG_PPC_BESCR:
 			val = get_reg_val(reg->id, vcpu->arch.bescr);
 			break;
+		case KVM_REG_PPC_VTB:
+			val = get_reg_val(reg->id, vcpu->arch.vtb);
+			break;
+		case KVM_REG_PPC_IC:
+			val = get_reg_val(reg->id, vcpu->arch.ic);
+			break;
 		default:
 			r = -EINVAL;
 			break;
@@ -750,6 +733,12 @@ int kvm_vcpu_ioctl_set_one_reg(struct kv
 		case KVM_REG_PPC_BESCR:
 			vcpu->arch.bescr = set_reg_val(reg->id, val);
 			break;
+		case KVM_REG_PPC_VTB:
+			vcpu->arch.vtb = set_reg_val(reg->id, val);
+			break;
+		case KVM_REG_PPC_IC:
+			vcpu->arch.ic = set_reg_val(reg->id, val);
+			break;
 		default:
 			r = -EINVAL;
 			break;
@@ -913,6 +902,11 @@ int kvmppc_core_check_processor_compat(v
 	return 0;
 }
 
+int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall)
+{
+	return kvm->arch.kvm_ops->hcall_implemented(hcall);
+}
+
 static int kvmppc_book3s_init(void)
 {
 	int r;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_emulate.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_emulate.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -439,12 +439,6 @@ int kvmppc_core_emulate_mtspr_pr(struct
 		    (mfmsr() & MSR_HV))
 			vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
 		break;
-	case SPRN_PURR:
-		to_book3s(vcpu)->purr_offset = spr_val - get_tb();
-		break;
-	case SPRN_SPURR:
-		to_book3s(vcpu)->spurr_offset = spr_val - get_tb();
-		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
 	case SPRN_GQR2:
@@ -455,10 +449,10 @@ int kvmppc_core_emulate_mtspr_pr(struct
 	case SPRN_GQR7:
 		to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val;
 		break;
+#ifdef CONFIG_PPC_BOOK3S_64
 	case SPRN_FSCR:
-		vcpu->arch.fscr = spr_val;
+		kvmppc_set_fscr(vcpu, spr_val);
 		break;
-#ifdef CONFIG_PPC_BOOK3S_64
 	case SPRN_BESCR:
 		vcpu->arch.bescr = spr_val;
 		break;
@@ -572,10 +566,22 @@ int kvmppc_core_emulate_mfspr_pr(struct
 		*spr_val = 0;
 		break;
 	case SPRN_PURR:
-		*spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+		/*
+		 * On exit we would have updated purr
+		 */
+		*spr_val = vcpu->arch.purr;
 		break;
 	case SPRN_SPURR:
-		*spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+		/*
+		 * On exit we would have updated spurr
+		 */
+		*spr_val = vcpu->arch.spurr;
+		break;
+	case SPRN_VTB:
+		*spr_val = vcpu->arch.vtb;
+		break;
+	case SPRN_IC:
+		*spr_val = vcpu->arch.ic;
 		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
@@ -587,10 +593,10 @@ int kvmppc_core_emulate_mfspr_pr(struct
 	case SPRN_GQR7:
 		*spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0];
 		break;
+#ifdef CONFIG_PPC_BOOK3S_64
 	case SPRN_FSCR:
 		*spr_val = vcpu->arch.fscr;
 		break;
-#ifdef CONFIG_PPC_BOOK3S_64
 	case SPRN_BESCR:
 		*spr_val = vcpu->arch.bescr;
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_builtin.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_builtin.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,12 +16,14 @@
 #include <linux/init.h>
 #include <linux/memblock.h>
 #include <linux/sizes.h>
+#include <linux/cma.h>
 
 #include <asm/cputable.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 
-#include "book3s_hv_cma.h"
+#define KVM_CMA_CHUNK_ORDER	18
+
 /*
  * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206)
  * should be power of 2.
@@ -43,6 +45,8 @@ static unsigned long kvm_cma_resv_ratio
 unsigned long kvm_rma_pages = (1 << 27) >> PAGE_SHIFT;	/* 128MB */
 EXPORT_SYMBOL_GPL(kvm_rma_pages);
 
+static struct cma *kvm_cma;
+
 /* Work out RMLS (real mode limit selector) field value for a given RMA size.
    Assumes POWER7 or PPC970. */
 static inline int lpcr_rmls(unsigned long rma_size)
@@ -97,7 +101,7 @@ struct kvm_rma_info *kvm_alloc_rma()
 	ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL);
 	if (!ri)
 		return NULL;
-	page = kvm_alloc_cma(kvm_rma_pages, kvm_rma_pages);
+	page = cma_alloc(kvm_cma, kvm_rma_pages, order_base_2(kvm_rma_pages));
 	if (!page)
 		goto err_out;
 	atomic_set(&ri->use_count, 1);
@@ -112,7 +116,7 @@ EXPORT_SYMBOL_GPL(kvm_alloc_rma);
 void kvm_release_rma(struct kvm_rma_info *ri)
 {
 	if (atomic_dec_and_test(&ri->use_count)) {
-		kvm_release_cma(pfn_to_page(ri->base_pfn), kvm_rma_pages);
+		cma_release(kvm_cma, pfn_to_page(ri->base_pfn), kvm_rma_pages);
 		kfree(ri);
 	}
 }
@@ -131,16 +135,18 @@ struct page *kvm_alloc_hpt(unsigned long
 {
 	unsigned long align_pages = HPT_ALIGN_PAGES;
 
+	VM_BUG_ON(order_base_2(nr_pages) < KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
+
 	/* Old CPUs require HPT aligned on a multiple of its size */
 	if (!cpu_has_feature(CPU_FTR_ARCH_206))
 		align_pages = nr_pages;
-	return kvm_alloc_cma(nr_pages, align_pages);
+	return cma_alloc(kvm_cma, nr_pages, order_base_2(align_pages));
 }
 EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
 
 void kvm_release_hpt(struct page *page, unsigned long nr_pages)
 {
-	kvm_release_cma(page, nr_pages);
+	cma_release(kvm_cma, page, nr_pages);
 }
 EXPORT_SYMBOL_GPL(kvm_release_hpt);
 
@@ -179,7 +185,8 @@ void __init kvm_cma_reserve(void)
 			align_size = HPT_ALIGN_PAGES << PAGE_SHIFT;
 
 		align_size = max(kvm_rma_pages << PAGE_SHIFT, align_size);
-		kvm_cma_declare_contiguous(selected_size, align_size);
+		cma_declare_contiguous(0, selected_size, 0, align_size,
+			KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma);
 	}
 }
 
@@ -212,3 +219,16 @@ bool kvm_hv_mode_active(void)
 {
 	return atomic_read(&hv_vm_count) != 0;
 }
+
+extern int hcall_real_table[], hcall_real_table_end[];
+
+int kvmppc_hcall_impl_hv_realmode(unsigned long cmd)
+{
+	cmd /= 4;
+	if (cmd < hcall_real_table_end - hcall_real_table &&
+	    hcall_real_table[cmd])
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
+#include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
@@ -67,6 +68,15 @@
 /* Used as a "null" value for timebase values */
 #define TB_NIL	(~(u64)0)
 
+static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
+
+#if defined(CONFIG_PPC_64K_PAGES)
+#define MPP_BUFFER_ORDER	0
+#elif defined(CONFIG_PPC_4K_PAGES)
+#define MPP_BUFFER_ORDER	3
+#endif
+
+
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
@@ -270,7 +280,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct
 static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
 {
 	vpa->__old_status |= LPPACA_OLD_SHARED_PROC;
-	vpa->yield_count = 1;
+	vpa->yield_count = cpu_to_be32(1);
 }
 
 static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
@@ -293,8 +303,8 @@ static int set_vpa(struct kvm_vcpu *vcpu
 struct reg_vpa {
 	u32 dummy;
 	union {
-		u16 hword;
-		u32 word;
+		__be16 hword;
+		__be32 word;
 	} length;
 };
 
@@ -333,9 +343,9 @@ static unsigned long do_h_register_vpa(s
 		if (va == NULL)
 			return H_PARAMETER;
 		if (subfunc == H_VPA_REG_VPA)
-			len = ((struct reg_vpa *)va)->length.hword;
+			len = be16_to_cpu(((struct reg_vpa *)va)->length.hword);
 		else
-			len = ((struct reg_vpa *)va)->length.word;
+			len = be32_to_cpu(((struct reg_vpa *)va)->length.word);
 		kvmppc_unpin_guest_page(kvm, va, vpa, false);
 
 		/* Check length */
@@ -540,21 +550,63 @@ static void kvmppc_create_dtl_entry(stru
 		return;
 	memset(dt, 0, sizeof(struct dtl_entry));
 	dt->dispatch_reason = 7;
-	dt->processor_id = vc->pcpu + vcpu->arch.ptid;
-	dt->timebase = now + vc->tb_offset;
-	dt->enqueue_to_dispatch_time = stolen;
-	dt->srr0 = kvmppc_get_pc(vcpu);
-	dt->srr1 = vcpu->arch.shregs.msr;
+	dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid);
+	dt->timebase = cpu_to_be64(now + vc->tb_offset);
+	dt->enqueue_to_dispatch_time = cpu_to_be32(stolen);
+	dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu));
+	dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr);
 	++dt;
 	if (dt == vcpu->arch.dtl.pinned_end)
 		dt = vcpu->arch.dtl.pinned_addr;
 	vcpu->arch.dtl_ptr = dt;
 	/* order writing *dt vs. writing vpa->dtl_idx */
 	smp_wmb();
-	vpa->dtl_idx = ++vcpu->arch.dtl_index;
+	vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index);
 	vcpu->arch.dtl.dirty = true;
 }
 
+static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
+		return true;
+	if ((!vcpu->arch.vcore->arch_compat) &&
+	    cpu_has_feature(CPU_FTR_ARCH_207S))
+		return true;
+	return false;
+}
+
+static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
+			     unsigned long resource, unsigned long value1,
+			     unsigned long value2)
+{
+	switch (resource) {
+	case H_SET_MODE_RESOURCE_SET_CIABR:
+		if (!kvmppc_power8_compatible(vcpu))
+			return H_P2;
+		if (value2)
+			return H_P4;
+		if (mflags)
+			return H_UNSUPPORTED_FLAG_START;
+		/* Guests can't breakpoint the hypervisor */
+		if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER)
+			return H_P3;
+		vcpu->arch.ciabr  = value1;
+		return H_SUCCESS;
+	case H_SET_MODE_RESOURCE_SET_DAWR:
+		if (!kvmppc_power8_compatible(vcpu))
+			return H_P2;
+		if (mflags)
+			return H_UNSUPPORTED_FLAG_START;
+		if (value2 & DABRX_HYP)
+			return H_P4;
+		vcpu->arch.dawr  = value1;
+		vcpu->arch.dawrx = value2;
+		return H_SUCCESS;
+	default:
+		return H_TOO_HARD;
+	}
+}
+
 int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 {
 	unsigned long req = kvmppc_get_gpr(vcpu, 3);
@@ -562,6 +614,10 @@ int kvmppc_pseries_do_hcall(struct kvm_v
 	struct kvm_vcpu *tvcpu;
 	int idx, rc;
 
+	if (req <= MAX_HCALL_OPCODE &&
+	    !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls))
+		return RESUME_HOST;
+
 	switch (req) {
 	case H_ENTER:
 		idx = srcu_read_lock(&vcpu->kvm->srcu);
@@ -620,7 +676,14 @@ int kvmppc_pseries_do_hcall(struct kvm_v
 
 		/* Send the error out to userspace via KVM_RUN */
 		return rc;
-
+	case H_SET_MODE:
+		ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4),
+					kvmppc_get_gpr(vcpu, 5),
+					kvmppc_get_gpr(vcpu, 6),
+					kvmppc_get_gpr(vcpu, 7));
+		if (ret == H_TOO_HARD)
+			return RESUME_HOST;
+		break;
 	case H_XIRR:
 	case H_CPPR:
 	case H_EOI:
@@ -639,6 +702,29 @@ int kvmppc_pseries_do_hcall(struct kvm_v
 	return RESUME_GUEST;
 }
 
+static int kvmppc_hcall_impl_hv(unsigned long cmd)
+{
+	switch (cmd) {
+	case H_CEDE:
+	case H_PROD:
+	case H_CONFER:
+	case H_REGISTER_VPA:
+	case H_SET_MODE:
+#ifdef CONFIG_KVM_XICS
+	case H_XIRR:
+	case H_CPPR:
+	case H_EOI:
+	case H_IPI:
+	case H_IPOLL:
+	case H_XIRR_X:
+#endif
+		return 1;
+	}
+
+	/* See if it's in the real-mode table */
+	return kvmppc_hcall_impl_hv_realmode(cmd);
+}
+
 static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
 				 struct task_struct *tsk)
 {
@@ -785,7 +871,8 @@ static int kvm_arch_vcpu_ioctl_set_sregs
 	return 0;
 }
 
-static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
+static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
+		bool preserve_top32)
 {
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 	u64 mask;
@@ -820,6 +907,10 @@ static void kvmppc_set_lpcr(struct kvm_v
 	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
 	if (cpu_has_feature(CPU_FTR_ARCH_207S))
 		mask |= LPCR_AIL;
+
+	/* Broken 32-bit version of LPCR must not clear top bits */
+	if (preserve_top32)
+		mask &= 0xFFFFFFFF;
 	vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask);
 	spin_unlock(&vc->lock);
 }
@@ -894,12 +985,6 @@ static int kvmppc_get_one_reg_hv(struct
 	case KVM_REG_PPC_CIABR:
 		*val = get_reg_val(id, vcpu->arch.ciabr);
 		break;
-	case KVM_REG_PPC_IC:
-		*val = get_reg_val(id, vcpu->arch.ic);
-		break;
-	case KVM_REG_PPC_VTB:
-		*val = get_reg_val(id, vcpu->arch.vtb);
-		break;
 	case KVM_REG_PPC_CSIGR:
 		*val = get_reg_val(id, vcpu->arch.csigr);
 		break;
@@ -939,6 +1024,7 @@ static int kvmppc_get_one_reg_hv(struct
 		*val = get_reg_val(id, vcpu->arch.vcore->tb_offset);
 		break;
 	case KVM_REG_PPC_LPCR:
+	case KVM_REG_PPC_LPCR_64:
 		*val = get_reg_val(id, vcpu->arch.vcore->lpcr);
 		break;
 	case KVM_REG_PPC_PPR:
@@ -1094,12 +1180,6 @@ static int kvmppc_set_one_reg_hv(struct
 		if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
 			vcpu->arch.ciabr &= ~CIABR_PRIV;	/* disable */
 		break;
-	case KVM_REG_PPC_IC:
-		vcpu->arch.ic = set_reg_val(id, *val);
-		break;
-	case KVM_REG_PPC_VTB:
-		vcpu->arch.vtb = set_reg_val(id, *val);
-		break;
 	case KVM_REG_PPC_CSIGR:
 		vcpu->arch.csigr = set_reg_val(id, *val);
 		break;
@@ -1150,7 +1230,10 @@ static int kvmppc_set_one_reg_hv(struct
 			ALIGN(set_reg_val(id, *val), 1UL << 24);
 		break;
 	case KVM_REG_PPC_LPCR:
-		kvmppc_set_lpcr(vcpu, set_reg_val(id, *val));
+		kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true);
+		break;
+	case KVM_REG_PPC_LPCR_64:
+		kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false);
 		break;
 	case KVM_REG_PPC_PPR:
 		vcpu->arch.ppr = set_reg_val(id, *val);
@@ -1228,6 +1311,33 @@ static int kvmppc_set_one_reg_hv(struct
 	return r;
 }
 
+static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
+{
+	struct kvmppc_vcore *vcore;
+
+	vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
+
+	if (vcore == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&vcore->runnable_threads);
+	spin_lock_init(&vcore->lock);
+	init_waitqueue_head(&vcore->wq);
+	vcore->preempt_tb = TB_NIL;
+	vcore->lpcr = kvm->arch.lpcr;
+	vcore->first_vcpuid = core * threads_per_subcore;
+	vcore->kvm = kvm;
+
+	vcore->mpp_buffer_is_valid = false;
+
+	if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		vcore->mpp_buffer = (void *)__get_free_pages(
+			GFP_KERNEL|__GFP_ZERO,
+			MPP_BUFFER_ORDER);
+
+	return vcore;
+}
+
 static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
 						   unsigned int id)
 {
@@ -1279,16 +1389,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 	mutex_lock(&kvm->lock);
 	vcore = kvm->arch.vcores[core];
 	if (!vcore) {
-		vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
-		if (vcore) {
-			INIT_LIST_HEAD(&vcore->runnable_threads);
-			spin_lock_init(&vcore->lock);
-			init_waitqueue_head(&vcore->wq);
-			vcore->preempt_tb = TB_NIL;
-			vcore->lpcr = kvm->arch.lpcr;
-			vcore->first_vcpuid = core * threads_per_subcore;
-			vcore->kvm = kvm;
-		}
+		vcore = kvmppc_vcore_create(kvm, core);
 		kvm->arch.vcores[core] = vcore;
 		kvm->arch.online_vcores++;
 	}
@@ -1500,6 +1601,33 @@ static int on_primary_thread(void)
 	return 1;
 }
 
+static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
+{
+	phys_addr_t phy_addr, mpp_addr;
+
+	phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
+	mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+	mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
+	logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
+
+	vc->mpp_buffer_is_valid = true;
+}
+
+static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
+{
+	phys_addr_t phy_addr, mpp_addr;
+
+	phy_addr = virt_to_phys(vc->mpp_buffer);
+	mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+	/* We must abort any in-progress save operations to ensure
+	 * the table is valid so that prefetch engine knows when to
+	 * stop prefetching. */
+	logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
+	mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
+}
+
 /*
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
@@ -1577,9 +1705,16 @@ static void kvmppc_run_core(struct kvmpp
 
 	srcu_idx = srcu_read_lock(&vc->kvm->srcu);
 
+	if (vc->mpp_buffer_is_valid)
+		kvmppc_start_restoring_l2_cache(vc);
+
 	__kvmppc_vcore_entry();
 
 	spin_lock(&vc->lock);
+
+	if (vc->mpp_buffer)
+		kvmppc_start_saving_l2_cache(vc);
+
 	/* disable sending of IPIs on virtual external irqs */
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
 		vcpu->cpu = -1;
@@ -1929,12 +2064,6 @@ static void kvmppc_add_seg_page_size(str
 	(*sps)->page_shift = def->shift;
 	(*sps)->slb_enc = def->sllp;
 	(*sps)->enc[0].page_shift = def->shift;
-	/*
-	 * Only return base page encoding. We don't want to return
-	 * all the supporting pte_enc, because our H_ENTER doesn't
-	 * support MPSS yet. Once they do, we can start passing all
-	 * support pte_enc here
-	 */
 	(*sps)->enc[0].pte_enc = def->penc[linux_psize];
 	/*
 	 * Add 16MB MPSS support if host supports it
@@ -2281,6 +2410,10 @@ static int kvmppc_core_init_vm_hv(struct
 	 */
 	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.rma = NULL;
 
 	kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
@@ -2323,8 +2456,14 @@ static void kvmppc_free_vcores(struct kv
 {
 	long int i;
 
-	for (i = 0; i < KVM_MAX_VCORES; ++i)
+	for (i = 0; i < KVM_MAX_VCORES; ++i) {
+		if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
+			struct kvmppc_vcore *vc = kvm->arch.vcores[i];
+			free_pages((unsigned long)vc->mpp_buffer,
+				   MPP_BUFFER_ORDER);
+		}
 		kfree(kvm->arch.vcores[i]);
+	}
 	kvm->arch.online_vcores = 0;
 }
 
@@ -2419,6 +2558,49 @@ static long kvm_arch_vm_ioctl_hv(struct
 	return r;
 }
 
+/*
+ * List of hcall numbers to enable by default.
+ * For compatibility with old userspace, we enable by default
+ * all hcalls that were implemented before the hcall-enabling
+ * facility was added.  Note this list should not include H_RTAS.
+ */
+static unsigned int default_hcall_list[] = {
+	H_REMOVE,
+	H_ENTER,
+	H_READ,
+	H_PROTECT,
+	H_BULK_REMOVE,
+	H_GET_TCE,
+	H_PUT_TCE,
+	H_SET_DABR,
+	H_SET_XDABR,
+	H_CEDE,
+	H_PROD,
+	H_CONFER,
+	H_REGISTER_VPA,
+#ifdef CONFIG_KVM_XICS
+	H_EOI,
+	H_CPPR,
+	H_IPI,
+	H_IPOLL,
+	H_XIRR,
+	H_XIRR_X,
+#endif
+	0
+};
+
+static void init_default_hcalls(void)
+{
+	int i;
+	unsigned int hcall;
+
+	for (i = 0; default_hcall_list[i]; ++i) {
+		hcall = default_hcall_list[i];
+		WARN_ON(!kvmppc_hcall_impl_hv(hcall));
+		__set_bit(hcall / 4, default_enabled_hcalls);
+	}
+}
+
 static struct kvmppc_ops kvm_ops_hv = {
 	.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
 	.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
@@ -2451,6 +2633,7 @@ static struct kvmppc_ops kvm_ops_hv = {
 	.emulate_mfspr = kvmppc_core_emulate_mfspr_hv,
 	.fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv,
 	.arch_vm_ioctl  = kvm_arch_vm_ioctl_hv,
+	.hcall_implemented = kvmppc_hcall_impl_hv,
 };
 
 static int kvmppc_book3s_init_hv(void)
@@ -2466,6 +2649,8 @@ static int kvmppc_book3s_init_hv(void)
 	kvm_ops_hv.owner = THIS_MODULE;
 	kvmppc_hv_ops = &kvm_ops_hv;
 
+	init_default_hcalls();
+
 	r = kvmppc_mmu_hv_init();
 	return r;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_cma.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_cma.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_cma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_cma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,240 +0,0 @@
-/*
- * Contiguous Memory Allocator for ppc KVM hash pagetable  based on CMA
- * for DMA mapping framework
- *
- * Copyright IBM Corporation, 2013
- * Author Aneesh Kumar K.V <aneesh.kumar@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 optional) any later version of the license.
- *
- */
-#define pr_fmt(fmt) "kvm_cma: " fmt
-
-#ifdef CONFIG_CMA_DEBUG
-#ifndef DEBUG
-#  define DEBUG
-#endif
-#endif
-
-#include <linux/memblock.h>
-#include <linux/mutex.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-
-#include "book3s_hv_cma.h"
-
-struct kvm_cma {
-	unsigned long	base_pfn;
-	unsigned long	count;
-	unsigned long	*bitmap;
-};
-
-static DEFINE_MUTEX(kvm_cma_mutex);
-static struct kvm_cma kvm_cma_area;
-
-/**
- * kvm_cma_declare_contiguous() - reserve area for contiguous memory handling
- *			          for kvm hash pagetable
- * @size:  Size of the reserved memory.
- * @alignment:  Alignment for the contiguous memory area
- *
- * This function reserves memory for kvm cma area. It should be
- * called by arch code when early allocator (memblock or bootmem)
- * is still activate.
- */
-long __init kvm_cma_declare_contiguous(phys_addr_t size, phys_addr_t alignment)
-{
-	long base_pfn;
-	phys_addr_t addr;
-	struct kvm_cma *cma = &kvm_cma_area;
-
-	pr_debug("%s(size %lx)\n", __func__, (unsigned long)size);
-
-	if (!size)
-		return -EINVAL;
-	/*
-	 * Sanitise input arguments.
-	 * We should be pageblock aligned for CMA.
-	 */
-	alignment = max(alignment, (phys_addr_t)(PAGE_SIZE << pageblock_order));
-	size = ALIGN(size, alignment);
-	/*
-	 * Reserve memory
-	 * Use __memblock_alloc_base() since
-	 * memblock_alloc_base() panic()s.
-	 */
-	addr = __memblock_alloc_base(size, alignment, 0);
-	if (!addr) {
-		base_pfn = -ENOMEM;
-		goto err;
-	} else
-		base_pfn = PFN_DOWN(addr);
-
-	/*
-	 * Each reserved area must be initialised later, when more kernel
-	 * subsystems (like slab allocator) are available.
-	 */
-	cma->base_pfn = base_pfn;
-	cma->count    = size >> PAGE_SHIFT;
-	pr_info("CMA: reserved %ld MiB\n", (unsigned long)size / SZ_1M);
-	return 0;
-err:
-	pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
-	return base_pfn;
-}
-
-/**
- * kvm_alloc_cma() - allocate pages from contiguous area
- * @nr_pages: Requested number of pages.
- * @align_pages: Requested alignment in number of pages
- *
- * This function allocates memory buffer for hash pagetable.
- */
-struct page *kvm_alloc_cma(unsigned long nr_pages, unsigned long align_pages)
-{
-	int ret;
-	struct page *page = NULL;
-	struct kvm_cma *cma = &kvm_cma_area;
-	unsigned long chunk_count, nr_chunk;
-	unsigned long mask, pfn, pageno, start = 0;
-
-
-	if (!cma || !cma->count)
-		return NULL;
-
-	pr_debug("%s(cma %p, count %lu, align pages %lu)\n", __func__,
-		 (void *)cma, nr_pages, align_pages);
-
-	if (!nr_pages)
-		return NULL;
-	/*
-	 * align mask with chunk size. The bit tracks pages in chunk size
-	 */
-	VM_BUG_ON(!is_power_of_2(align_pages));
-	mask = (align_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT)) - 1;
-	BUILD_BUG_ON(PAGE_SHIFT > KVM_CMA_CHUNK_ORDER);
-
-	chunk_count = cma->count >>  (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-	nr_chunk = nr_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-
-	mutex_lock(&kvm_cma_mutex);
-	for (;;) {
-		pageno = bitmap_find_next_zero_area(cma->bitmap, chunk_count,
-						    start, nr_chunk, mask);
-		if (pageno >= chunk_count)
-			break;
-
-		pfn = cma->base_pfn + (pageno << (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT));
-		ret = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_CMA);
-		if (ret == 0) {
-			bitmap_set(cma->bitmap, pageno, nr_chunk);
-			page = pfn_to_page(pfn);
-			memset(pfn_to_kaddr(pfn), 0, nr_pages << PAGE_SHIFT);
-			break;
-		} else if (ret != -EBUSY) {
-			break;
-		}
-		pr_debug("%s(): memory range at %p is busy, retrying\n",
-			 __func__, pfn_to_page(pfn));
-		/* try again with a bit different memory target */
-		start = pageno + mask + 1;
-	}
-	mutex_unlock(&kvm_cma_mutex);
-	pr_debug("%s(): returned %p\n", __func__, page);
-	return page;
-}
-
-/**
- * kvm_release_cma() - release allocated pages for hash pagetable
- * @pages: Allocated pages.
- * @nr_pages: Number of allocated pages.
- *
- * This function releases memory allocated by kvm_alloc_cma().
- * It returns false when provided pages do not belong to contiguous area and
- * true otherwise.
- */
-bool kvm_release_cma(struct page *pages, unsigned long nr_pages)
-{
-	unsigned long pfn;
-	unsigned long nr_chunk;
-	struct kvm_cma *cma = &kvm_cma_area;
-
-	if (!cma || !pages)
-		return false;
-
-	pr_debug("%s(page %p count %lu)\n", __func__, (void *)pages, nr_pages);
-
-	pfn = page_to_pfn(pages);
-
-	if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
-		return false;
-
-	VM_BUG_ON(pfn + nr_pages > cma->base_pfn + cma->count);
-	nr_chunk = nr_pages >>  (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-
-	mutex_lock(&kvm_cma_mutex);
-	bitmap_clear(cma->bitmap,
-		     (pfn - cma->base_pfn) >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT),
-		     nr_chunk);
-	free_contig_range(pfn, nr_pages);
-	mutex_unlock(&kvm_cma_mutex);
-
-	return true;
-}
-
-static int __init kvm_cma_activate_area(unsigned long base_pfn,
-					unsigned long count)
-{
-	unsigned long pfn = base_pfn;
-	unsigned i = count >> pageblock_order;
-	struct zone *zone;
-
-	WARN_ON_ONCE(!pfn_valid(pfn));
-	zone = page_zone(pfn_to_page(pfn));
-	do {
-		unsigned j;
-		base_pfn = pfn;
-		for (j = pageblock_nr_pages; j; --j, pfn++) {
-			WARN_ON_ONCE(!pfn_valid(pfn));
-			/*
-			 * alloc_contig_range requires the pfn range
-			 * specified to be in the same zone. Make this
-			 * simple by forcing the entire CMA resv range
-			 * to be in the same zone.
-			 */
-			if (page_zone(pfn_to_page(pfn)) != zone)
-				return -EINVAL;
-		}
-		init_cma_reserved_pageblock(pfn_to_page(base_pfn));
-	} while (--i);
-	return 0;
-}
-
-static int __init kvm_cma_init_reserved_areas(void)
-{
-	int bitmap_size, ret;
-	unsigned long chunk_count;
-	struct kvm_cma *cma = &kvm_cma_area;
-
-	pr_debug("%s()\n", __func__);
-	if (!cma->count)
-		return 0;
-	chunk_count = cma->count >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-	bitmap_size = BITS_TO_LONGS(chunk_count) * sizeof(long);
-	cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!cma->bitmap)
-		return -ENOMEM;
-
-	ret = kvm_cma_activate_area(cma->base_pfn, cma->count);
-	if (ret)
-		goto error;
-	return 0;
-
-error:
-	kfree(cma->bitmap);
-	return ret;
-}
-core_initcall(kvm_cma_init_reserved_areas);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_cma.h linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_cma.h
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_cma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_cma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * Contiguous Memory Allocator for ppc KVM hash pagetable  based on CMA
- * for DMA mapping framework
- *
- * Copyright IBM Corporation, 2013
- * Author Aneesh Kumar K.V <aneesh.kumar@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 optional) any later version of the license.
- *
- */
-
-#ifndef __POWERPC_KVM_CMA_ALLOC_H__
-#define __POWERPC_KVM_CMA_ALLOC_H__
-/*
- * Both RMA and Hash page allocation will be multiple of 256K.
- */
-#define KVM_CMA_CHUNK_ORDER	18
-
-extern struct page *kvm_alloc_cma(unsigned long nr_pages,
-				  unsigned long align_pages);
-extern bool kvm_release_cma(struct page *pages, unsigned long nr_pages);
-extern long kvm_cma_declare_contiguous(phys_addr_t size,
-				       phys_addr_t alignment) __init;
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_ras.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_ras.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_ras.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_ras.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *
 		return;
 
 	/* Sanity check */
-	n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+	n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
 	if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
 		return;
 
 	/* Load up the SLB from that */
 	for (i = 0; i < n; ++i) {
-		unsigned long rb = slb->save_area[i].esid;
-		unsigned long rs = slb->save_area[i].vsid;
+		unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
+		unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
 
 		rb = (rb & ~0xFFFul) | i;	/* insert entry number */
 		asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,6 @@
 
 #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
 
-#ifdef __LITTLE_ENDIAN__
-#error Need to fix lppaca and SLB shadow accesses in little endian mode
-#endif
-
 /* Values in HSTATE_NAPPING(r13) */
 #define NAPPING_CEDE	1
 #define NAPPING_NOVCPU	2
@@ -159,6 +155,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
 BEGIN_FTR_SECTION
 	beq	11f
+	cmpwi	cr2, r12, BOOK3S_INTERRUPT_HMI
+	beq	cr2, 14f			/* HMI check */
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 	/* RFI into the highmem handler, or branch to interrupt handler */
@@ -179,6 +177,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 13:	b	machine_check_fwnmi
 
+14:	mtspr	SPRN_HSRR0, r8
+	mtspr	SPRN_HSRR1, r7
+	b	hmi_exception_after_realmode
+
 kvmppc_primary_no_guest:
 	/* We handle this much like a ceded vcpu */
 	/* set our bit in napping_threads */
@@ -595,9 +597,10 @@ kvmppc_got_guest:
 	ld	r3, VCPU_VPA(r4)
 	cmpdi	r3, 0
 	beq	25f
-	lwz	r5, LPPACA_YIELDCOUNT(r3)
+	li	r6, LPPACA_YIELDCOUNT
+	LWZX_BE	r5, r3, r6
 	addi	r5, r5, 1
-	stw	r5, LPPACA_YIELDCOUNT(r3)
+	STWX_BE	r5, r3, r6
 	li	r6, 1
 	stb	r6, VCPU_VPA_DIRTY(r4)
 25:
@@ -671,9 +674,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
 
 	mr	r31, r4
 	addi	r3, r31, VCPU_FPRS_TM
-	bl	.load_fp_state
+	bl	load_fp_state
 	addi	r3, r31, VCPU_VRS_TM
-	bl	.load_vr_state
+	bl	load_vr_state
 	mr	r4, r31
 	lwz	r7, VCPU_VRSAVE_TM(r4)
 	mtspr	SPRN_VRSAVE, r7
@@ -1417,9 +1420,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
 
 	/* Save FP/VSX. */
 	addi	r3, r9, VCPU_FPRS_TM
-	bl	.store_fp_state
+	bl	store_fp_state
 	addi	r3, r9, VCPU_VRS_TM
-	bl	.store_vr_state
+	bl	store_vr_state
 	mfspr	r6, SPRN_VRSAVE
 	stw	r6, VCPU_VRSAVE_TM(r9)
 1:
@@ -1442,9 +1445,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
 	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
 	cmpdi	r8, 0
 	beq	25f
-	lwz	r3, LPPACA_YIELDCOUNT(r8)
+	li	r4, LPPACA_YIELDCOUNT
+	LWZX_BE	r3, r8, r4
 	addi	r3, r3, 1
-	stw	r3, LPPACA_YIELDCOUNT(r8)
+	STWX_BE	r3, r8, r4
 	li	r3, 1
 	stb	r3, VCPU_VPA_DIRTY(r9)
 25:
@@ -1757,8 +1761,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 33:	ld	r8,PACA_SLBSHADOWPTR(r13)
 
 	.rept	SLB_NUM_BOLTED
-	ld	r5,SLBSHADOW_SAVEAREA(r8)
-	ld	r6,SLBSHADOW_SAVEAREA+8(r8)
+	li	r3, SLBSHADOW_SAVEAREA
+	LDX_BE	r5, r8, r3
+	addi	r3, r3, 8
+	LDX_BE	r6, r8, r3
 	andis.	r7,r5,SLB_ESID_V@h
 	beq	1f
 	slbmte	r6,r5
@@ -1909,12 +1915,23 @@ hcall_try_real_mode:
 	clrrdi	r3,r3,2
 	cmpldi	r3,hcall_real_table_end - hcall_real_table
 	bge	guest_exit_cont
+	/* See if this hcall is enabled for in-kernel handling */
+	ld	r4, VCPU_KVM(r9)
+	srdi	r0, r3, 8	/* r0 = (r3 / 4) >> 6 */
+	sldi	r0, r0, 3	/* index into kvm->arch.enabled_hcalls[] */
+	add	r4, r4, r0
+	ld	r0, KVM_ENABLED_HCALLS(r4)
+	rlwinm	r4, r3, 32-2, 0x3f	/* r4 = (r3 / 4) & 0x3f */
+	srd	r0, r0, r4
+	andi.	r0, r0, 1
+	beq	guest_exit_cont
+	/* Get pointer to handler, if any, and call it */
 	LOAD_REG_ADDR(r4, hcall_real_table)
 	lwax	r3,r3,r4
 	cmpwi	r3,0
 	beq	guest_exit_cont
-	add	r3,r3,r4
-	mtctr	r3
+	add	r12,r3,r4
+	mtctr	r12
 	mr	r3,r9		/* get vcpu pointer */
 	ld	r4,VCPU_GPR(R4)(r9)
 	bctrl
@@ -2031,6 +2048,7 @@ hcall_real_table:
 	.long	0		/* 0x12c */
 	.long	0		/* 0x130 */
 	.long	DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
+	.globl	hcall_real_table_end
 hcall_real_table_end:
 
 ignore_hdec:
@@ -2338,7 +2356,18 @@ kvmppc_read_intr:
 	cmpdi	r6, 0
 	beq-	1f
 	lwzcix	r0, r6, r7
-	rlwinm.	r3, r0, 0, 0xffffff
+	/*
+	 * Save XIRR for later. Since we get in in reverse endian on LE
+	 * systems, save it byte reversed and fetch it back in host endian.
+	 */
+	li	r3, HSTATE_SAVED_XIRR
+	STWX_BE	r0, r3, r13
+#ifdef __LITTLE_ENDIAN__
+	lwz	r3, HSTATE_SAVED_XIRR(r13)
+#else
+	mr	r3, r0
+#endif
+	rlwinm.	r3, r3, 0, 0xffffff
 	sync
 	beq	1f			/* if nothing pending in the ICP */
 
@@ -2370,10 +2399,9 @@ kvmppc_read_intr:
 	li	r3, -1
 1:	blr
 
-42:	/* It's not an IPI and it's for the host, stash it in the PACA
-	 * before exit, it will be picked up by the host ICP driver
+42:	/* It's not an IPI and it's for the host. We saved a copy of XIRR in
+	 * the PACA earlier, it will be picked up by the host ICP driver
 	 */
-	stw	r0, HSTATE_SAVED_XIRR(r13)
 	li	r3, 1
 	b	1b
 
@@ -2408,11 +2436,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 	mtmsrd	r8
 	isync
 	addi	r3,r3,VCPU_FPRS
-	bl	.store_fp_state
+	bl	store_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
 	addi	r3,r31,VCPU_VRS
-	bl	.store_vr_state
+	bl	store_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	mfspr	r6,SPRN_VRSAVE
@@ -2444,11 +2472,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 	mtmsrd	r8
 	isync
 	addi	r3,r4,VCPU_FPRS
-	bl	.load_fp_state
+	bl	load_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
 	addi	r3,r31,VCPU_VRS
-	bl	.load_vr_state
+	bl	load_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	lwz	r7,VCPU_VRSAVE(r31)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -154,10 +154,10 @@ static pte_t lookup_linux_pte_and_update
 	return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift);
 }
 
-static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
+static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v)
 {
 	asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-	hpte[0] = hpte_v;
+	hpte[0] = cpu_to_be64(hpte_v);
 }
 
 long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
@@ -166,7 +166,7 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 {
 	unsigned long i, pa, gpa, gfn, psize;
 	unsigned long slot_fn, hva;
-	unsigned long *hpte;
+	__be64 *hpte;
 	struct revmap_entry *rev;
 	unsigned long g_ptel;
 	struct kvm_memory_slot *memslot;
@@ -275,9 +275,9 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 		return H_PARAMETER;
 	if (likely((flags & H_EXACT) == 0)) {
 		pte_index &= ~7UL;
-		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 		for (i = 0; i < 8; ++i) {
-			if ((*hpte & HPTE_V_VALID) == 0 &&
+			if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 &&
 			    try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
 					  HPTE_V_ABSENT))
 				break;
@@ -292,11 +292,13 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 			 */
 			hpte -= 16;
 			for (i = 0; i < 8; ++i) {
+				u64 pte;
 				while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 					cpu_relax();
-				if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
+				pte = be64_to_cpu(*hpte);
+				if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT)))
 					break;
-				*hpte &= ~HPTE_V_HVLOCK;
+				*hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				hpte += 2;
 			}
 			if (i == 8)
@@ -304,14 +306,17 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 		}
 		pte_index += i;
 	} else {
-		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 		if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
 				   HPTE_V_ABSENT)) {
 			/* Lock the slot and check again */
+			u64 pte;
+
 			while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 				cpu_relax();
-			if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
-				*hpte &= ~HPTE_V_HVLOCK;
+			pte = be64_to_cpu(*hpte);
+			if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+				*hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				return H_PTEG_FULL;
 			}
 		}
@@ -347,11 +352,11 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 		}
 	}
 
-	hpte[1] = ptel;
+	hpte[1] = cpu_to_be64(ptel);
 
 	/* Write the first HPTE dword, unlocking the HPTE and making it valid */
 	eieio();
-	hpte[0] = pteh;
+	hpte[0] = cpu_to_be64(pteh);
 	asm volatile("ptesync" : : : "memory");
 
 	*pte_idx_ret = pte_index;
@@ -468,30 +473,35 @@ long kvmppc_do_h_remove(struct kvm *kvm,
 			unsigned long pte_index, unsigned long avpn,
 			unsigned long *hpret)
 {
-	unsigned long *hpte;
+	__be64 *hpte;
 	unsigned long v, r, rb;
 	struct revmap_entry *rev;
+	u64 pte;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
-	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+	hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
-	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
-	    ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
-		hpte[0] &= ~HPTE_V_HVLOCK;
+	pte = be64_to_cpu(hpte[0]);
+	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
+	    ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
+		hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		return H_NOT_FOUND;
 	}
 
 	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
-	v = hpte[0] & ~HPTE_V_HVLOCK;
+	v = pte & ~HPTE_V_HVLOCK;
 	if (v & HPTE_V_VALID) {
-		hpte[0] &= ~HPTE_V_VALID;
-		rb = compute_tlbie_rb(v, hpte[1], pte_index);
+		u64 pte1;
+
+		pte1 = be64_to_cpu(hpte[1]);
+		hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
+		rb = compute_tlbie_rb(v, pte1, pte_index);
 		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
 		/* Read PTE low word after tlbie to get final R/C values */
-		remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
+		remove_revmap_chain(kvm, pte_index, rev, v, pte1);
 	}
 	r = rev->guest_rpte & ~HPTE_GR_RESERVED;
 	note_hpte_modification(kvm, rev);
@@ -514,12 +524,14 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 {
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long *args = &vcpu->arch.gpr[4];
-	unsigned long *hp, *hptes[4], tlbrb[4];
+	__be64 *hp, *hptes[4];
+	unsigned long tlbrb[4];
 	long int i, j, k, n, found, indexes[4];
 	unsigned long flags, req, pte_index, rcbits;
 	int global;
 	long int ret = H_SUCCESS;
 	struct revmap_entry *rev, *revs[4];
+	u64 hp0;
 
 	global = global_invalidates(kvm, 0);
 	for (i = 0; i < 4 && ret == H_SUCCESS; ) {
@@ -542,8 +554,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 				ret = H_PARAMETER;
 				break;
 			}
-			hp = (unsigned long *)
-				(kvm->arch.hpt_virt + (pte_index << 4));
+			hp = (__be64 *) (kvm->arch.hpt_virt + (pte_index << 4));
 			/* to avoid deadlock, don't spin except for first */
 			if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) {
 				if (n)
@@ -552,23 +563,24 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 					cpu_relax();
 			}
 			found = 0;
-			if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
+			hp0 = be64_to_cpu(hp[0]);
+			if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) {
 				switch (flags & 3) {
 				case 0:		/* absolute */
 					found = 1;
 					break;
 				case 1:		/* andcond */
-					if (!(hp[0] & args[j + 1]))
+					if (!(hp0 & args[j + 1]))
 						found = 1;
 					break;
 				case 2:		/* AVPN */
-					if ((hp[0] & ~0x7fUL) == args[j + 1])
+					if ((hp0 & ~0x7fUL) == args[j + 1])
 						found = 1;
 					break;
 				}
 			}
 			if (!found) {
-				hp[0] &= ~HPTE_V_HVLOCK;
+				hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 				args[j] = ((0x90 | flags) << 56) + pte_index;
 				continue;
 			}
@@ -577,7 +589,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 			rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
 			note_hpte_modification(kvm, rev);
 
-			if (!(hp[0] & HPTE_V_VALID)) {
+			if (!(hp0 & HPTE_V_VALID)) {
 				/* insert R and C bits from PTE */
 				rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
 				args[j] |= rcbits << (56 - 5);
@@ -585,8 +597,10 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 				continue;
 			}
 
-			hp[0] &= ~HPTE_V_VALID;		/* leave it locked */
-			tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+			/* 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);
 			indexes[n] = j;
 			hptes[n] = hp;
 			revs[n] = rev;
@@ -605,7 +619,8 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 			pte_index = args[j] & ((1ul << 56) - 1);
 			hp = hptes[k];
 			rev = revs[k];
-			remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
+			remove_revmap_chain(kvm, pte_index, rev,
+				be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
 			rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
 			args[j] |= rcbits << (56 - 5);
 			hp[0] = 0;
@@ -620,23 +635,25 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 		      unsigned long va)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long *hpte;
+	__be64 *hpte;
 	struct revmap_entry *rev;
 	unsigned long v, r, rb, mask, bits;
+	u64 pte;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
 
-	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+	hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
-	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
-		hpte[0] &= ~HPTE_V_HVLOCK;
+	pte = be64_to_cpu(hpte[0]);
+	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
+		hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
 		return H_NOT_FOUND;
 	}
 
-	v = hpte[0];
+	v = pte;
 	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);
@@ -650,12 +667,12 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 		rev->guest_rpte = r;
 		note_hpte_modification(kvm, rev);
 	}
-	r = (hpte[1] & ~mask) | bits;
+	r = (be64_to_cpu(hpte[1]) & ~mask) | bits;
 
 	/* Update HPTE */
 	if (v & HPTE_V_VALID) {
 		rb = compute_tlbie_rb(v, r, pte_index);
-		hpte[0] = v & ~HPTE_V_VALID;
+		hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID);
 		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
 		/*
 		 * If the host has this page as readonly but the guest
@@ -681,9 +698,9 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 			}
 		}
 	}
-	hpte[1] = r;
+	hpte[1] = cpu_to_be64(r);
 	eieio();
-	hpte[0] = v & ~HPTE_V_HVLOCK;
+	hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK);
 	asm volatile("ptesync" : : : "memory");
 	return H_SUCCESS;
 }
@@ -692,7 +709,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu
 		   unsigned long pte_index)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long *hpte, v, r;
+	__be64 *hpte;
+	unsigned long v, r;
 	int i, n = 1;
 	struct revmap_entry *rev = NULL;
 
@@ -704,9 +722,9 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu
 	}
 	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
 	for (i = 0; i < n; ++i, ++pte_index) {
-		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-		v = hpte[0] & ~HPTE_V_HVLOCK;
-		r = hpte[1];
+		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 (v & HPTE_V_ABSENT) {
 			v &= ~HPTE_V_ABSENT;
 			v |= HPTE_V_VALID;
@@ -721,25 +739,27 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu
 	return H_SUCCESS;
 }
 
-void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
 			unsigned long pte_index)
 {
 	unsigned long rb;
 
-	hptep[0] &= ~HPTE_V_VALID;
-	rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+	hptep[0] &= ~cpu_to_be64(HPTE_V_VALID);
+	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+			      pte_index);
 	do_tlbies(kvm, &rb, 1, 1, true);
 }
 EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
 
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
 			   unsigned long pte_index)
 {
 	unsigned long rb;
 	unsigned char rbyte;
 
-	rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
-	rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
+	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+			      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;
 	do_tlbies(kvm, &rb, 1, 1, false);
@@ -765,7 +785,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 	unsigned long somask;
 	unsigned long vsid, hash;
 	unsigned long avpn;
-	unsigned long *hpte;
+	__be64 *hpte;
 	unsigned long mask, val;
 	unsigned long v, r;
 
@@ -797,11 +817,11 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 	val |= avpn;
 
 	for (;;) {
-		hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7));
+		hpte = (__be64 *)(kvm->arch.hpt_virt + (hash << 7));
 
 		for (i = 0; i < 16; i += 2) {
 			/* Read the PTE racily */
-			v = hpte[i] & ~HPTE_V_HVLOCK;
+			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
 
 			/* Check valid/absent, hash, segment size and AVPN */
 			if (!(v & valid) || (v & mask) != val)
@@ -810,8 +830,8 @@ 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 = hpte[i] & ~HPTE_V_HVLOCK;
-			r = hpte[i+1];
+			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
+			r = be64_to_cpu(hpte[i+1]);
 
 			/*
 			 * Check the HPTE again, including base page size
@@ -822,7 +842,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 				return (hash << 3) + (i >> 1);
 
 			/* Unlock and move on */
-			hpte[i] = v;
+			hpte[i] = cpu_to_be64(v);
 		}
 
 		if (val & HPTE_V_SECONDARY)
@@ -851,7 +871,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcp
 	struct kvm *kvm = vcpu->kvm;
 	long int index;
 	unsigned long v, r, gr;
-	unsigned long *hpte;
+	__be64 *hpte;
 	unsigned long valid;
 	struct revmap_entry *rev;
 	unsigned long pp, key;
@@ -867,9 +887,9 @@ long kvmppc_hpte_hv_fault(struct kvm_vcp
 			return status;	/* there really was no HPTE */
 		return 0;		/* for prot fault, HPTE disappeared */
 	}
-	hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
-	v = hpte[0] & ~HPTE_V_HVLOCK;
-	r = hpte[1];
+	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;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c	2014-09-28 17:29:07.000000000 -0400
@@ -401,6 +401,11 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcp
 		icp->rm_action |= XICS_RM_REJECT;
 		icp->rm_reject = irq;
 	}
+
+	if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) {
+		icp->rm_action |= XICS_RM_NOTIFY_EOI;
+		icp->rm_eoied_irq = irq;
+	}
  bail:
 	return check_too_hard(xics, icp);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_paired_singles.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_paired_singles.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_paired_singles.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_paired_singles.c	2014-09-28 17:29:07.000000000 -0400
@@ -639,26 +639,36 @@ static int kvmppc_ps_one_in(struct kvm_v
 
 int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
-	u32 inst = kvmppc_get_last_inst(vcpu);
+	u32 inst;
 	enum emulation_result emulated = EMULATE_DONE;
+	int ax_rd, ax_ra, ax_rb, ax_rc;
+	short full_d;
+	u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c;
 
-	int ax_rd = inst_get_field(inst, 6, 10);
-	int ax_ra = inst_get_field(inst, 11, 15);
-	int ax_rb = inst_get_field(inst, 16, 20);
-	int ax_rc = inst_get_field(inst, 21, 25);
-	short full_d = inst_get_field(inst, 16, 31);
-
-	u64 *fpr_d = &VCPU_FPR(vcpu, ax_rd);
-	u64 *fpr_a = &VCPU_FPR(vcpu, ax_ra);
-	u64 *fpr_b = &VCPU_FPR(vcpu, ax_rb);
-	u64 *fpr_c = &VCPU_FPR(vcpu, ax_rc);
-
-	bool rcomp = (inst & 1) ? true : false;
-	u32 cr = kvmppc_get_cr(vcpu);
+	bool rcomp;
+	u32 cr;
 #ifdef DEBUG
 	int i;
 #endif
 
+	emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst);
+	if (emulated != EMULATE_DONE)
+		return emulated;
+
+	ax_rd = inst_get_field(inst, 6, 10);
+	ax_ra = inst_get_field(inst, 11, 15);
+	ax_rb = inst_get_field(inst, 16, 20);
+	ax_rc = inst_get_field(inst, 21, 25);
+	full_d = inst_get_field(inst, 16, 31);
+
+	fpr_d = &VCPU_FPR(vcpu, ax_rd);
+	fpr_a = &VCPU_FPR(vcpu, ax_ra);
+	fpr_b = &VCPU_FPR(vcpu, ax_rb);
+	fpr_c = &VCPU_FPR(vcpu, ax_rc);
+
+	rcomp = (inst & 1) ? true : false;
+	cr = kvmppc_get_cr(vcpu);
+
 	if (!kvmppc_inst_is_paired_single(vcpu, inst))
 		return EMULATE_FAIL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_pr.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_pr.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_pr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_pr.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,6 +62,35 @@ static void kvmppc_giveup_fac(struct kvm
 #define HW_PAGE_SIZE PAGE_SIZE
 #endif
 
+static bool kvmppc_is_split_real(struct kvm_vcpu *vcpu)
+{
+	ulong msr = kvmppc_get_msr(vcpu);
+	return (msr & (MSR_IR|MSR_DR)) == MSR_DR;
+}
+
+static void kvmppc_fixup_split_real(struct kvm_vcpu *vcpu)
+{
+	ulong msr = kvmppc_get_msr(vcpu);
+	ulong pc = kvmppc_get_pc(vcpu);
+
+	/* We are in DR only split real mode */
+	if ((msr & (MSR_IR|MSR_DR)) != MSR_DR)
+		return;
+
+	/* We have not fixed up the guest already */
+	if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK)
+		return;
+
+	/* The code is in fixupable address space */
+	if (pc & SPLIT_HACK_MASK)
+		return;
+
+	vcpu->arch.hflags |= BOOK3S_HFLAG_SPLIT_HACK;
+	kvmppc_set_pc(vcpu, pc | SPLIT_HACK_OFFS);
+}
+
+void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu);
+
 static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
@@ -71,10 +100,19 @@ static void kvmppc_core_vcpu_load_pr(str
 	svcpu->in_use = 0;
 	svcpu_put(svcpu);
 #endif
+
+	/* Disable AIL if supported */
+	if (cpu_has_feature(CPU_FTR_HVMODE) &&
+	    cpu_has_feature(CPU_FTR_ARCH_207S))
+		mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
+
 	vcpu->cpu = smp_processor_id();
 #ifdef CONFIG_PPC_BOOK3S_32
 	current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu;
 #endif
+
+	if (kvmppc_is_split_real(vcpu))
+		kvmppc_fixup_split_real(vcpu);
 }
 
 static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
@@ -89,8 +127,17 @@ static void kvmppc_core_vcpu_put_pr(stru
 	svcpu_put(svcpu);
 #endif
 
+	if (kvmppc_is_split_real(vcpu))
+		kvmppc_unfixup_split_real(vcpu);
+
 	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
 	kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+
+	/* Enable AIL if supported */
+	if (cpu_has_feature(CPU_FTR_HVMODE) &&
+	    cpu_has_feature(CPU_FTR_ARCH_207S))
+		mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
+
 	vcpu->cpu = -1;
 }
 
@@ -120,6 +167,14 @@ void kvmppc_copy_to_svcpu(struct kvmppc_
 #ifdef CONFIG_PPC_BOOK3S_64
 	svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
 #endif
+	/*
+	 * Now also save the current time base value. We use this
+	 * to find the guest purr and spurr value.
+	 */
+	vcpu->arch.entry_tb = get_tb();
+	vcpu->arch.entry_vtb = get_vtb();
+	if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		vcpu->arch.entry_ic = mfspr(SPRN_IC);
 	svcpu->in_use = true;
 }
 
@@ -166,6 +221,14 @@ void kvmppc_copy_from_svcpu(struct kvm_v
 #ifdef CONFIG_PPC_BOOK3S_64
 	vcpu->arch.shadow_fscr = svcpu->shadow_fscr;
 #endif
+	/*
+	 * Update purr and spurr using time base on exit.
+	 */
+	vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb;
+	vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb;
+	vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb;
+	if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic;
 	svcpu->in_use = false;
 
 out:
@@ -294,6 +357,11 @@ static void kvmppc_set_msr_pr(struct kvm
 		}
 	}
 
+	if (kvmppc_is_split_real(vcpu))
+		kvmppc_fixup_split_real(vcpu);
+	else
+		kvmppc_unfixup_split_real(vcpu);
+
 	if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) !=
 		   (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
 		kvmppc_mmu_flush_segments(vcpu);
@@ -443,19 +511,19 @@ static void kvmppc_patch_dcbz(struct kvm
 	put_page(hpage);
 }
 
-static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+static int kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
 {
 	ulong mp_pa = vcpu->arch.magic_page_pa;
 
 	if (!(kvmppc_get_msr(vcpu) & MSR_SF))
 		mp_pa = (uint32_t)mp_pa;
 
-	if (unlikely(mp_pa) &&
-	    unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
+	gpa &= ~0xFFFULL;
+	if (unlikely(mp_pa) && unlikely((mp_pa & KVM_PAM) == (gpa & KVM_PAM))) {
 		return 1;
 	}
 
-	return kvm_is_visible_gfn(vcpu->kvm, gfn);
+	return kvm_is_visible_gfn(vcpu->kvm, gpa >> PAGE_SHIFT);
 }
 
 int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -494,6 +562,11 @@ int kvmppc_handle_pagefault(struct kvm_r
 		pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
 		break;
 	case MSR_DR:
+		if (!data &&
+		    (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) &&
+		    ((pte.raddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS))
+			pte.raddr &= ~SPLIT_HACK_MASK;
+		/* fall through */
 	case MSR_IR:
 		vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
 
@@ -541,7 +614,7 @@ int kvmppc_handle_pagefault(struct kvm_r
 		kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
 		kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
 	} else if (!is_mmio &&
-		   kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
+		   kvmppc_visible_gpa(vcpu, pte.raddr)) {
 		if (data && !(vcpu->arch.fault_dsisr & DSISR_NOHPTE)) {
 			/*
 			 * There is already a host HPTE there, presumably
@@ -637,42 +710,6 @@ static void kvmppc_giveup_fac(struct kvm
 #endif
 }
 
-static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
-{
-	ulong srr0 = kvmppc_get_pc(vcpu);
-	u32 last_inst = kvmppc_get_last_inst(vcpu);
-	int ret;
-
-	ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
-	if (ret == -ENOENT) {
-		ulong msr = kvmppc_get_msr(vcpu);
-
-		msr = kvmppc_set_field(msr, 33, 33, 1);
-		msr = kvmppc_set_field(msr, 34, 36, 0);
-		msr = kvmppc_set_field(msr, 42, 47, 0);
-		kvmppc_set_msr_fast(vcpu, msr);
-		kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
-		return EMULATE_AGAIN;
-	}
-
-	return EMULATE_DONE;
-}
-
-static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
-{
-
-	/* Need to do paired single emulation? */
-	if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
-		return EMULATE_DONE;
-
-	/* Read out the instruction */
-	if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
-		/* Need to emulate */
-		return EMULATE_FAIL;
-
-	return EMULATE_AGAIN;
-}
-
 /* Handle external providers (FPU, Altivec, VSX) */
 static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 			     ulong msr)
@@ -834,6 +871,15 @@ static int kvmppc_handle_fac(struct kvm_
 
 	return RESUME_GUEST;
 }
+
+void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr)
+{
+	if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) {
+		/* TAR got dropped, drop it in shadow too */
+		kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+	}
+	vcpu->arch.fscr = fscr;
+}
 #endif
 
 int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -858,6 +904,9 @@ int kvmppc_handle_exit_pr(struct kvm_run
 		ulong shadow_srr1 = vcpu->arch.shadow_srr1;
 		vcpu->stat.pf_instruc++;
 
+		if (kvmppc_is_split_real(vcpu))
+			kvmppc_fixup_split_real(vcpu);
+
 #ifdef CONFIG_PPC_BOOK3S_32
 		/* We set segments as unused segments when invalidating them. So
 		 * treat the respective fault as segment fault. */
@@ -960,6 +1009,7 @@ int kvmppc_handle_exit_pr(struct kvm_run
 	case BOOK3S_INTERRUPT_DECREMENTER:
 	case BOOK3S_INTERRUPT_HV_DECREMENTER:
 	case BOOK3S_INTERRUPT_DOORBELL:
+	case BOOK3S_INTERRUPT_H_DOORBELL:
 		vcpu->stat.dec_exits++;
 		r = RESUME_GUEST;
 		break;
@@ -977,15 +1027,24 @@ int kvmppc_handle_exit_pr(struct kvm_run
 	{
 		enum emulation_result er;
 		ulong flags;
+		u32 last_inst;
+		int emul;
 
 program_interrupt:
 		flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
 
+		emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
+		if (emul != EMULATE_DONE) {
+			r = RESUME_GUEST;
+			break;
+		}
+
 		if (kvmppc_get_msr(vcpu) & MSR_PR) {
 #ifdef EXIT_DEBUG
-			printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+			pr_info("Userspace triggered 0x700 exception at\n 0x%lx (0x%x)\n",
+				kvmppc_get_pc(vcpu), last_inst);
 #endif
-			if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
+			if ((last_inst & 0xff0007ff) !=
 			    (INS_DCBZ & 0xfffffff7)) {
 				kvmppc_core_queue_program(vcpu, flags);
 				r = RESUME_GUEST;
@@ -1004,7 +1063,7 @@ program_interrupt:
 			break;
 		case EMULATE_FAIL:
 			printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
-			       __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+			       __func__, kvmppc_get_pc(vcpu), last_inst);
 			kvmppc_core_queue_program(vcpu, flags);
 			r = RESUME_GUEST;
 			break;
@@ -1021,8 +1080,23 @@ program_interrupt:
 		break;
 	}
 	case BOOK3S_INTERRUPT_SYSCALL:
+	{
+		u32 last_sc;
+		int emul;
+
+		/* Get last sc for papr */
+		if (vcpu->arch.papr_enabled) {
+			/* The sc instuction points SRR0 to the next inst */
+			emul = kvmppc_get_last_inst(vcpu, INST_SC, &last_sc);
+			if (emul != EMULATE_DONE) {
+				kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) - 4);
+				r = RESUME_GUEST;
+				break;
+			}
+		}
+
 		if (vcpu->arch.papr_enabled &&
-		    (kvmppc_get_last_sc(vcpu) == 0x44000022) &&
+		    (last_sc == 0x44000022) &&
 		    !(kvmppc_get_msr(vcpu) & MSR_PR)) {
 			/* SC 1 papr hypercalls */
 			ulong cmd = kvmppc_get_gpr(vcpu, 3);
@@ -1067,36 +1141,51 @@ program_interrupt:
 			r = RESUME_GUEST;
 		}
 		break;
+	}
 	case BOOK3S_INTERRUPT_FP_UNAVAIL:
 	case BOOK3S_INTERRUPT_ALTIVEC:
 	case BOOK3S_INTERRUPT_VSX:
 	{
 		int ext_msr = 0;
+		int emul;
+		u32 last_inst;
 
-		switch (exit_nr) {
-		case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP;  break;
-		case BOOK3S_INTERRUPT_ALTIVEC:    ext_msr = MSR_VEC; break;
-		case BOOK3S_INTERRUPT_VSX:        ext_msr = MSR_VSX; break;
+		if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) {
+			/* Do paired single instruction emulation */
+			emul = kvmppc_get_last_inst(vcpu, INST_GENERIC,
+						    &last_inst);
+			if (emul == EMULATE_DONE)
+				goto program_interrupt;
+			else
+				r = RESUME_GUEST;
+
+			break;
 		}
 
-		switch (kvmppc_check_ext(vcpu, exit_nr)) {
-		case EMULATE_DONE:
-			/* everything ok - let's enable the ext */
-			r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
+		/* Enable external provider */
+		switch (exit_nr) {
+		case BOOK3S_INTERRUPT_FP_UNAVAIL:
+			ext_msr = MSR_FP;
 			break;
-		case EMULATE_FAIL:
-			/* we need to emulate this instruction */
-			goto program_interrupt;
+
+		case BOOK3S_INTERRUPT_ALTIVEC:
+			ext_msr = MSR_VEC;
 			break;
-		default:
-			/* nothing to worry about - go again */
+
+		case BOOK3S_INTERRUPT_VSX:
+			ext_msr = MSR_VSX;
 			break;
 		}
+
+		r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
 		break;
 	}
 	case BOOK3S_INTERRUPT_ALIGNMENT:
-		if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
-			u32 last_inst = kvmppc_get_last_inst(vcpu);
+	{
+		u32 last_inst;
+		int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
+
+		if (emul == EMULATE_DONE) {
 			u32 dsisr;
 			u64 dar;
 
@@ -1110,6 +1199,7 @@ program_interrupt:
 		}
 		r = RESUME_GUEST;
 		break;
+	}
 #ifdef CONFIG_PPC_BOOK3S_64
 	case BOOK3S_INTERRUPT_FAC_UNAVAIL:
 		kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
@@ -1233,6 +1323,7 @@ static int kvmppc_get_one_reg_pr(struct
 		*val = get_reg_val(id, to_book3s(vcpu)->hior);
 		break;
 	case KVM_REG_PPC_LPCR:
+	case KVM_REG_PPC_LPCR_64:
 		/*
 		 * We are only interested in the LPCR_ILE bit
 		 */
@@ -1268,6 +1359,7 @@ static int kvmppc_set_one_reg_pr(struct
 		to_book3s(vcpu)->hior_explicit = true;
 		break;
 	case KVM_REG_PPC_LPCR:
+	case KVM_REG_PPC_LPCR_64:
 		kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
 		break;
 	default:
@@ -1310,8 +1402,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 	p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
 	if (!p)
 		goto uninit_vcpu;
-	/* the real shared page fills the last 4k of our page */
-	vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096);
+	vcpu->arch.shared = (void *)p;
 #ifdef CONFIG_PPC_BOOK3S_64
 	/* Always start the shared struct in native endian mode */
 #ifdef __BIG_ENDIAN__
@@ -1568,6 +1659,11 @@ static int kvmppc_core_init_vm_pr(struct
 {
 	mutex_init(&kvm->arch.hpt_mutex);
 
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* Start out with the default set of hcalls enabled */
+	kvmppc_pr_init_default_hcalls(kvm);
+#endif
+
 	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
 		spin_lock(&kvm_global_user_count_lock);
 		if (++kvm_global_user_count == 1)
@@ -1636,6 +1732,9 @@ static struct kvmppc_ops kvm_ops_pr = {
 	.emulate_mfspr = kvmppc_core_emulate_mfspr_pr,
 	.fast_vcpu_kick = kvm_vcpu_kick,
 	.arch_vm_ioctl  = kvm_arch_vm_ioctl_pr,
+#ifdef CONFIG_PPC_BOOK3S_64
+	.hcall_implemented = kvmppc_hcall_impl_pr,
+#endif
 };
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_pr_papr.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_pr_papr.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_pr_papr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_pr_papr.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,9 @@ static int kvmppc_h_pr_enter(struct kvm_
 {
 	long flags = kvmppc_get_gpr(vcpu, 4);
 	long pte_index = kvmppc_get_gpr(vcpu, 5);
-	unsigned long pteg[2 * 8];
-	unsigned long pteg_addr, i, *hpte;
+	__be64 pteg[2 * 8];
+	__be64 *hpte;
+	unsigned long pteg_addr, i;
 	long int ret;
 
 	i = pte_index & 7;
@@ -93,8 +94,8 @@ static int kvmppc_h_pr_remove(struct kvm
 	pteg = get_pteg_addr(vcpu, pte_index);
 	mutex_lock(&vcpu->kvm->arch.hpt_mutex);
 	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
-	pte[0] = be64_to_cpu(pte[0]);
-	pte[1] = be64_to_cpu(pte[1]);
+	pte[0] = be64_to_cpu((__force __be64)pte[0]);
+	pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
 	ret = H_NOT_FOUND;
 	if ((pte[0] & HPTE_V_VALID) == 0 ||
@@ -171,8 +172,8 @@ static int kvmppc_h_pr_bulk_remove(struc
 
 		pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
 		copy_from_user(pte, (void __user *)pteg, sizeof(pte));
-		pte[0] = be64_to_cpu(pte[0]);
-		pte[1] = be64_to_cpu(pte[1]);
+		pte[0] = be64_to_cpu((__force __be64)pte[0]);
+		pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
 		/* tsl = AVPN */
 		flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
@@ -211,8 +212,8 @@ static int kvmppc_h_pr_protect(struct kv
 	pteg = get_pteg_addr(vcpu, pte_index);
 	mutex_lock(&vcpu->kvm->arch.hpt_mutex);
 	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
-	pte[0] = be64_to_cpu(pte[0]);
-	pte[1] = be64_to_cpu(pte[1]);
+	pte[0] = be64_to_cpu((__force __be64)pte[0]);
+	pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
 	ret = H_NOT_FOUND;
 	if ((pte[0] & HPTE_V_VALID) == 0 ||
@@ -231,8 +232,8 @@ static int kvmppc_h_pr_protect(struct kv
 
 	rb = compute_tlbie_rb(v, r, pte_index);
 	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
-	pte[0] = cpu_to_be64(pte[0]);
-	pte[1] = cpu_to_be64(pte[1]);
+	pte[0] = (__force u64)cpu_to_be64(pte[0]);
+	pte[1] = (__force u64)cpu_to_be64(pte[1]);
 	copy_to_user((void __user *)pteg, pte, sizeof(pte));
 	ret = H_SUCCESS;
 
@@ -266,6 +267,12 @@ static int kvmppc_h_pr_xics_hcall(struct
 
 int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
 {
+	int rc, idx;
+
+	if (cmd <= MAX_HCALL_OPCODE &&
+	    !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls))
+		return EMULATE_FAIL;
+
 	switch (cmd) {
 	case H_ENTER:
 		return kvmppc_h_pr_enter(vcpu);
@@ -294,8 +301,11 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, u
 		break;
 	case H_RTAS:
 		if (list_empty(&vcpu->kvm->arch.rtas_tokens))
-			return RESUME_HOST;
-		if (kvmppc_rtas_hcall(vcpu))
+			break;
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
+		rc = kvmppc_rtas_hcall(vcpu);
+		srcu_read_unlock(&vcpu->kvm->srcu, idx);
+		if (rc)
 			break;
 		kvmppc_set_gpr(vcpu, 3, 0);
 		return EMULATE_DONE;
@@ -303,3 +313,61 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, u
 
 	return EMULATE_FAIL;
 }
+
+int kvmppc_hcall_impl_pr(unsigned long cmd)
+{
+	switch (cmd) {
+	case H_ENTER:
+	case H_REMOVE:
+	case H_PROTECT:
+	case H_BULK_REMOVE:
+	case H_PUT_TCE:
+	case H_CEDE:
+#ifdef CONFIG_KVM_XICS
+	case H_XIRR:
+	case H_CPPR:
+	case H_EOI:
+	case H_IPI:
+	case H_IPOLL:
+	case H_XIRR_X:
+#endif
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * List of hcall numbers to enable by default.
+ * For compatibility with old userspace, we enable by default
+ * all hcalls that were implemented before the hcall-enabling
+ * facility was added.  Note this list should not include H_RTAS.
+ */
+static unsigned int default_hcall_list[] = {
+	H_ENTER,
+	H_REMOVE,
+	H_PROTECT,
+	H_BULK_REMOVE,
+	H_PUT_TCE,
+	H_CEDE,
+#ifdef CONFIG_KVM_XICS
+	H_XIRR,
+	H_CPPR,
+	H_EOI,
+	H_IPI,
+	H_IPOLL,
+	H_XIRR_X,
+#endif
+	0
+};
+
+void kvmppc_pr_init_default_hcalls(struct kvm *kvm)
+{
+	int i;
+	unsigned int hcall;
+
+	for (i = 0; default_hcall_list[i]; ++i) {
+		hcall = default_hcall_list[i];
+		WARN_ON(!kvmppc_hcall_impl_pr(hcall));
+		__set_bit(hcall / 4, kvm->arch.enabled_hcalls);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_xics.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_xics.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_xics.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_xics.c	2014-09-28 17:29:07.000000000 -0400
@@ -64,8 +64,12 @@
 static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
 			    u32 new_irq);
 
-static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
-			   bool report_status)
+/*
+ * Return value ideally indicates how the interrupt was handled, but no
+ * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
+ * so just return 0.
+ */
+static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
 {
 	struct ics_irq_state *state;
 	struct kvmppc_ics *ics;
@@ -82,17 +86,14 @@ static int ics_deliver_irq(struct kvmppc
 	if (!state->exists)
 		return -EINVAL;
 
-	if (report_status)
-		return state->asserted;
-
 	/*
 	 * We set state->asserted locklessly. This should be fine as
 	 * we are the only setter, thus concurrent access is undefined
 	 * to begin with.
 	 */
-	if (level == KVM_INTERRUPT_SET_LEVEL)
+	if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL)
 		state->asserted = 1;
-	else if (level == KVM_INTERRUPT_UNSET) {
+	else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
 		state->asserted = 0;
 		return 0;
 	}
@@ -100,7 +101,7 @@ static int ics_deliver_irq(struct kvmppc
 	/* Attempt delivery */
 	icp_deliver_irq(xics, NULL, irq);
 
-	return state->asserted;
+	return 0;
 }
 
 static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
@@ -772,6 +773,8 @@ static noinline int kvmppc_h_eoi(struct
 	if (state->asserted)
 		icp_deliver_irq(xics, icp, irq);
 
+	kvm_notify_acked_irq(vcpu->kvm, 0, irq);
+
 	return H_SUCCESS;
 }
 
@@ -789,6 +792,8 @@ static noinline int kvmppc_xics_rm_compl
 		icp_check_resend(xics, icp);
 	if (icp->rm_action & XICS_RM_REJECT)
 		icp_deliver_irq(xics, icp, icp->rm_reject);
+	if (icp->rm_action & XICS_RM_NOTIFY_EOI)
+		kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq);
 
 	icp->rm_action = 0;
 
@@ -1170,7 +1175,16 @@ int kvm_set_irq(struct kvm *kvm, int irq
 {
 	struct kvmppc_xics *xics = kvm->arch.xics;
 
-	return ics_deliver_irq(xics, irq, level, line_status);
+	return ics_deliver_irq(xics, irq, level);
+}
+
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
+		int irq_source_id, int level, bool line_status)
+{
+	if (!level)
+		return -1;
+	return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
+			   level, line_status);
 }
 
 static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
@@ -1301,3 +1315,26 @@ void kvmppc_xics_free_icp(struct kvm_vcp
 	vcpu->arch.icp = NULL;
 	vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
 }
+
+static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e,
+			struct kvm *kvm, int irq_source_id, int level,
+			bool line_status)
+{
+	return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
+}
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries, int gsi)
+{
+	entries->gsi = gsi;
+	entries->type = KVM_IRQ_ROUTING_IRQCHIP;
+	entries->set = xics_set_irq;
+	entries->irqchip.irqchip = 0;
+	entries->irqchip.pin = gsi;
+	return 1;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+	return pin;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_xics.h linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_xics.h
--- linux-libre-3.16-gnu/arch/powerpc/kvm/book3s_xics.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/book3s_xics.h	2014-09-28 17:29:07.000000000 -0400
@@ -71,9 +71,11 @@ struct kvmppc_icp {
 #define XICS_RM_KICK_VCPU	0x1
 #define XICS_RM_CHECK_RESEND	0x2
 #define XICS_RM_REJECT		0x4
+#define XICS_RM_NOTIFY_EOI	0x8
 	u32 rm_action;
 	struct kvm_vcpu *rm_kick_target;
 	u32  rm_reject;
+	u32  rm_eoied_irq;
 
 	/* Debug stuff for real mode */
 	union kvmppc_icp_state rm_dbgstate;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/booke.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/booke.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,6 @@ unsigned long kvmppc_booke_handlers;
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "mmio",       VCPU_STAT(mmio_exits) },
-	{ "dcr",        VCPU_STAT(dcr_exits) },
 	{ "sig",        VCPU_STAT(signal_exits) },
 	{ "itlb_r",     VCPU_STAT(itlb_real_miss_exits) },
 	{ "itlb_v",     VCPU_STAT(itlb_virt_miss_exits) },
@@ -185,24 +184,28 @@ static void kvmppc_booke_queue_irqprio(s
 	set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
-static void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
-                                        ulong dear_flags, ulong esr_flags)
+void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
+				 ulong dear_flags, ulong esr_flags)
 {
 	vcpu->arch.queued_dear = dear_flags;
 	vcpu->arch.queued_esr = esr_flags;
 	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
 }
 
-static void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
-                                           ulong dear_flags, ulong esr_flags)
+void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
+				    ulong dear_flags, ulong esr_flags)
 {
 	vcpu->arch.queued_dear = dear_flags;
 	vcpu->arch.queued_esr = esr_flags;
 	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
 }
 
-static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
-                                           ulong esr_flags)
+void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu)
+{
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
+}
+
+void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong esr_flags)
 {
 	vcpu->arch.queued_esr = esr_flags;
 	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
@@ -266,13 +269,8 @@ static void kvmppc_core_dequeue_watchdog
 
 static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
 {
-#ifdef CONFIG_KVM_BOOKE_HV
-	mtspr(SPRN_GSRR0, srr0);
-	mtspr(SPRN_GSRR1, srr1);
-#else
-	vcpu->arch.shared->srr0 = srr0;
-	vcpu->arch.shared->srr1 = srr1;
-#endif
+	kvmppc_set_srr0(vcpu, srr0);
+	kvmppc_set_srr1(vcpu, srr1);
 }
 
 static void set_guest_csrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
@@ -297,51 +295,6 @@ static void set_guest_mcsrr(struct kvm_v
 	vcpu->arch.mcsrr1 = srr1;
 }
 
-static unsigned long get_guest_dear(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
-	return mfspr(SPRN_GDEAR);
-#else
-	return vcpu->arch.shared->dar;
-#endif
-}
-
-static void set_guest_dear(struct kvm_vcpu *vcpu, unsigned long dear)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
-	mtspr(SPRN_GDEAR, dear);
-#else
-	vcpu->arch.shared->dar = dear;
-#endif
-}
-
-static unsigned long get_guest_esr(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
-	return mfspr(SPRN_GESR);
-#else
-	return vcpu->arch.shared->esr;
-#endif
-}
-
-static void set_guest_esr(struct kvm_vcpu *vcpu, u32 esr)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
-	mtspr(SPRN_GESR, esr);
-#else
-	vcpu->arch.shared->esr = esr;
-#endif
-}
-
-static unsigned long get_guest_epr(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
-	return mfspr(SPRN_GEPR);
-#else
-	return vcpu->arch.epr;
-#endif
-}
-
 /* Deliver the interrupt of the corresponding priority, if possible. */
 static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                                         unsigned int priority)
@@ -450,9 +403,9 @@ static int kvmppc_booke_irqprio_deliver(
 
 		vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
 		if (update_esr == true)
-			set_guest_esr(vcpu, vcpu->arch.queued_esr);
+			kvmppc_set_esr(vcpu, vcpu->arch.queued_esr);
 		if (update_dear == true)
-			set_guest_dear(vcpu, vcpu->arch.queued_dear);
+			kvmppc_set_dar(vcpu, vcpu->arch.queued_dear);
 		if (update_epr == true) {
 			if (vcpu->arch.epr_flags & KVMPPC_EPR_USER)
 				kvm_make_request(KVM_REQ_EPR_EXIT, vcpu);
@@ -752,9 +705,8 @@ static int emulation_exit(struct kvm_run
 		 * they were actually modified by emulation. */
 		return RESUME_GUEST_NV;
 
-	case EMULATE_DO_DCR:
-		run->exit_reason = KVM_EXIT_DCR;
-		return RESUME_HOST;
+	case EMULATE_AGAIN:
+		return RESUME_GUEST;
 
 	case EMULATE_FAIL:
 		printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
@@ -866,6 +818,28 @@ static void kvmppc_restart_interrupt(str
 	}
 }
 
+static int kvmppc_resume_inst_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+				  enum emulation_result emulated, u32 last_inst)
+{
+	switch (emulated) {
+	case EMULATE_AGAIN:
+		return RESUME_GUEST;
+
+	case EMULATE_FAIL:
+		pr_debug("%s: load instruction from guest address %lx failed\n",
+		       __func__, vcpu->arch.pc);
+		/* For debugging, encode the failing instruction and
+		 * report it to userspace. */
+		run->hw.hardware_exit_reason = ~0ULL << 32;
+		run->hw.hardware_exit_reason |= last_inst;
+		kvmppc_core_queue_program(vcpu, ESR_PIL);
+		return RESUME_HOST;
+
+	default:
+		BUG();
+	}
+}
+
 /**
  * kvmppc_handle_exit
  *
@@ -877,6 +851,8 @@ int kvmppc_handle_exit(struct kvm_run *r
 	int r = RESUME_HOST;
 	int s;
 	int idx;
+	u32 last_inst = KVM_INST_FETCH_FAILED;
+	enum emulation_result emulated = EMULATE_DONE;
 
 	/* update before a new last_exit_type is rewritten */
 	kvmppc_update_timing_stats(vcpu);
@@ -884,6 +860,20 @@ int kvmppc_handle_exit(struct kvm_run *r
 	/* restart interrupts if they were meant for the host */
 	kvmppc_restart_interrupt(vcpu, exit_nr);
 
+	/*
+	 * get last instruction before beeing preempted
+	 * TODO: for e6500 check also BOOKE_INTERRUPT_LRAT_ERROR & ESR_DATA
+	 */
+	switch (exit_nr) {
+	case BOOKE_INTERRUPT_DATA_STORAGE:
+	case BOOKE_INTERRUPT_DTLB_MISS:
+	case BOOKE_INTERRUPT_HV_PRIV:
+		emulated = kvmppc_get_last_inst(vcpu, false, &last_inst);
+		break;
+	default:
+		break;
+	}
+
 	local_irq_enable();
 
 	trace_kvm_exit(exit_nr, vcpu);
@@ -892,6 +882,11 @@ int kvmppc_handle_exit(struct kvm_run *r
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	run->ready_for_interrupt_injection = 1;
 
+	if (emulated != EMULATE_DONE) {
+		r = kvmppc_resume_inst_load(run, vcpu, emulated, last_inst);
+		goto out;
+	}
+
 	switch (exit_nr) {
 	case BOOKE_INTERRUPT_MACHINE_CHECK:
 		printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR));
@@ -1181,6 +1176,7 @@ int kvmppc_handle_exit(struct kvm_run *r
 		BUG();
 	}
 
+out:
 	/*
 	 * To avoid clobbering exit_reason, only check for signals if we
 	 * aren't already exiting to userspace for some other reason.
@@ -1265,17 +1261,17 @@ int kvm_arch_vcpu_ioctl_get_regs(struct
 	regs->lr = vcpu->arch.lr;
 	regs->xer = kvmppc_get_xer(vcpu);
 	regs->msr = vcpu->arch.shared->msr;
-	regs->srr0 = vcpu->arch.shared->srr0;
-	regs->srr1 = vcpu->arch.shared->srr1;
+	regs->srr0 = kvmppc_get_srr0(vcpu);
+	regs->srr1 = kvmppc_get_srr1(vcpu);
 	regs->pid = vcpu->arch.pid;
-	regs->sprg0 = vcpu->arch.shared->sprg0;
-	regs->sprg1 = vcpu->arch.shared->sprg1;
-	regs->sprg2 = vcpu->arch.shared->sprg2;
-	regs->sprg3 = vcpu->arch.shared->sprg3;
-	regs->sprg4 = vcpu->arch.shared->sprg4;
-	regs->sprg5 = vcpu->arch.shared->sprg5;
-	regs->sprg6 = vcpu->arch.shared->sprg6;
-	regs->sprg7 = vcpu->arch.shared->sprg7;
+	regs->sprg0 = kvmppc_get_sprg0(vcpu);
+	regs->sprg1 = kvmppc_get_sprg1(vcpu);
+	regs->sprg2 = kvmppc_get_sprg2(vcpu);
+	regs->sprg3 = kvmppc_get_sprg3(vcpu);
+	regs->sprg4 = kvmppc_get_sprg4(vcpu);
+	regs->sprg5 = kvmppc_get_sprg5(vcpu);
+	regs->sprg6 = kvmppc_get_sprg6(vcpu);
+	regs->sprg7 = kvmppc_get_sprg7(vcpu);
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -1293,17 +1289,17 @@ int kvm_arch_vcpu_ioctl_set_regs(struct
 	vcpu->arch.lr = regs->lr;
 	kvmppc_set_xer(vcpu, regs->xer);
 	kvmppc_set_msr(vcpu, regs->msr);
-	vcpu->arch.shared->srr0 = regs->srr0;
-	vcpu->arch.shared->srr1 = regs->srr1;
+	kvmppc_set_srr0(vcpu, regs->srr0);
+	kvmppc_set_srr1(vcpu, regs->srr1);
 	kvmppc_set_pid(vcpu, regs->pid);
-	vcpu->arch.shared->sprg0 = regs->sprg0;
-	vcpu->arch.shared->sprg1 = regs->sprg1;
-	vcpu->arch.shared->sprg2 = regs->sprg2;
-	vcpu->arch.shared->sprg3 = regs->sprg3;
-	vcpu->arch.shared->sprg4 = regs->sprg4;
-	vcpu->arch.shared->sprg5 = regs->sprg5;
-	vcpu->arch.shared->sprg6 = regs->sprg6;
-	vcpu->arch.shared->sprg7 = regs->sprg7;
+	kvmppc_set_sprg0(vcpu, regs->sprg0);
+	kvmppc_set_sprg1(vcpu, regs->sprg1);
+	kvmppc_set_sprg2(vcpu, regs->sprg2);
+	kvmppc_set_sprg3(vcpu, regs->sprg3);
+	kvmppc_set_sprg4(vcpu, regs->sprg4);
+	kvmppc_set_sprg5(vcpu, regs->sprg5);
+	kvmppc_set_sprg6(vcpu, regs->sprg6);
+	kvmppc_set_sprg7(vcpu, regs->sprg7);
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -1321,8 +1317,8 @@ static void get_sregs_base(struct kvm_vc
 	sregs->u.e.csrr0 = vcpu->arch.csrr0;
 	sregs->u.e.csrr1 = vcpu->arch.csrr1;
 	sregs->u.e.mcsr = vcpu->arch.mcsr;
-	sregs->u.e.esr = get_guest_esr(vcpu);
-	sregs->u.e.dear = get_guest_dear(vcpu);
+	sregs->u.e.esr = kvmppc_get_esr(vcpu);
+	sregs->u.e.dear = kvmppc_get_dar(vcpu);
 	sregs->u.e.tsr = vcpu->arch.tsr;
 	sregs->u.e.tcr = vcpu->arch.tcr;
 	sregs->u.e.dec = kvmppc_get_dec(vcpu, tb);
@@ -1339,8 +1335,8 @@ static int set_sregs_base(struct kvm_vcp
 	vcpu->arch.csrr0 = sregs->u.e.csrr0;
 	vcpu->arch.csrr1 = sregs->u.e.csrr1;
 	vcpu->arch.mcsr = sregs->u.e.mcsr;
-	set_guest_esr(vcpu, sregs->u.e.esr);
-	set_guest_dear(vcpu, sregs->u.e.dear);
+	kvmppc_set_esr(vcpu, sregs->u.e.esr);
+	kvmppc_set_dar(vcpu, sregs->u.e.dear);
 	vcpu->arch.vrsave = sregs->u.e.vrsave;
 	kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
 
@@ -1493,7 +1489,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kv
 		val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2);
 		break;
 	case KVM_REG_PPC_EPR: {
-		u32 epr = get_guest_epr(vcpu);
+		u32 epr = kvmppc_get_epr(vcpu);
 		val = get_reg_val(reg->id, epr);
 		break;
 	}
@@ -1788,6 +1784,57 @@ void kvm_guest_protect_msr(struct kvm_vc
 #endif
 }
 
+int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
+		 enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
+{
+	int gtlb_index;
+	gpa_t gpaddr;
+
+#ifdef CONFIG_KVM_E500V2
+	if (!(vcpu->arch.shared->msr & MSR_PR) &&
+	    (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
+		pte->eaddr = eaddr;
+		pte->raddr = (vcpu->arch.magic_page_pa & PAGE_MASK) |
+			     (eaddr & ~PAGE_MASK);
+		pte->vpage = eaddr >> PAGE_SHIFT;
+		pte->may_read = true;
+		pte->may_write = true;
+		pte->may_execute = true;
+
+		return 0;
+	}
+#endif
+
+	/* Check the guest TLB. */
+	switch (xlid) {
+	case XLATE_INST:
+		gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr);
+		break;
+	case XLATE_DATA:
+		gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
+		break;
+	default:
+		BUG();
+	}
+
+	/* Do we have a TLB entry at all? */
+	if (gtlb_index < 0)
+		return -ENOENT;
+
+	gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
+
+	pte->eaddr = eaddr;
+	pte->raddr = (gpaddr & PAGE_MASK) | (eaddr & ~PAGE_MASK);
+	pte->vpage = eaddr >> PAGE_SHIFT;
+
+	/* XXX read permissions from the guest TLB */
+	pte->may_read = true;
+	pte->may_write = true;
+	pte->may_execute = true;
+
+	return 0;
+}
+
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
 					 struct kvm_guest_debug *dbg)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/booke_emulate.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke_emulate.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/booke_emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke_emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -165,16 +165,16 @@ int kvmppc_booke_emulate_mtspr(struct kv
 	 * guest (PR-mode only).
 	 */
 	case SPRN_SPRG4:
-		vcpu->arch.shared->sprg4 = spr_val;
+		kvmppc_set_sprg4(vcpu, spr_val);
 		break;
 	case SPRN_SPRG5:
-		vcpu->arch.shared->sprg5 = spr_val;
+		kvmppc_set_sprg5(vcpu, spr_val);
 		break;
 	case SPRN_SPRG6:
-		vcpu->arch.shared->sprg6 = spr_val;
+		kvmppc_set_sprg6(vcpu, spr_val);
 		break;
 	case SPRN_SPRG7:
-		vcpu->arch.shared->sprg7 = spr_val;
+		kvmppc_set_sprg7(vcpu, spr_val);
 		break;
 
 	case SPRN_IVPR:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/booke.h linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke.h
--- linux-libre-3.16-gnu/arch/powerpc/kvm/booke.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,13 +99,6 @@ enum int_class {
 
 void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type);
 
-extern void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu);
-extern int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu,
-				      unsigned int inst, int *advance);
-extern int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn,
-					 ulong spr_val);
-extern int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn,
-					 ulong *spr_val);
 extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_emulate_op_e500(struct kvm_run *run,
 				       struct kvm_vcpu *vcpu,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/bookehv_interrupts.S linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/bookehv_interrupts.S
--- linux-libre-3.16-gnu/arch/powerpc/kvm/bookehv_interrupts.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/bookehv_interrupts.S	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,10 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
-#include <asm/mmu-44x.h>
 #include <asm/page.h>
 #include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 #include <asm/bitsperlong.h>
-#include <asm/thread_info.h>
 
 #ifdef CONFIG_64BIT
 #include <asm/exception-64e.h>
@@ -122,38 +120,14 @@
 1:
 
 	.if	\flags & NEED_EMU
-	/*
-	 * This assumes you have external PID support.
-	 * To support a bookehv CPU without external PID, you'll
-	 * need to look up the TLB entry and create a temporary mapping.
-	 *
-	 * FIXME: we don't currently handle if the lwepx faults.  PR-mode
-	 * booke doesn't handle it either.  Since Linux doesn't use
-	 * broadcast tlbivax anymore, the only way this should happen is
-	 * if the guest maps its memory execute-but-not-read, or if we
-	 * somehow take a TLB miss in the middle of this entry code and
-	 * evict the relevant entry.  On e500mc, all kernel lowmem is
-	 * bolted into TLB1 large page mappings, and we don't use
-	 * broadcast invalidates, so we should not take a TLB miss here.
-	 *
-	 * Later we'll need to deal with faults here.  Disallowing guest
-	 * mappings that are execute-but-not-read could be an option on
-	 * e500mc, but not on chips with an LRAT if it is used.
-	 */
-
-	mfspr	r3, SPRN_EPLC	/* will already have correct ELPID and EGS */
 	PPC_STL	r15, VCPU_GPR(R15)(r4)
 	PPC_STL	r16, VCPU_GPR(R16)(r4)
 	PPC_STL	r17, VCPU_GPR(R17)(r4)
 	PPC_STL	r18, VCPU_GPR(R18)(r4)
 	PPC_STL	r19, VCPU_GPR(R19)(r4)
-	mr	r8, r3
 	PPC_STL	r20, VCPU_GPR(R20)(r4)
-	rlwimi	r8, r6, EPC_EAS_SHIFT - MSR_IR_LG, EPC_EAS
 	PPC_STL	r21, VCPU_GPR(R21)(r4)
-	rlwimi	r8, r6, EPC_EPR_SHIFT - MSR_PR_LG, EPC_EPR
 	PPC_STL	r22, VCPU_GPR(R22)(r4)
-	rlwimi	r8, r10, EPC_EPID_SHIFT, EPC_EPID
 	PPC_STL	r23, VCPU_GPR(R23)(r4)
 	PPC_STL	r24, VCPU_GPR(R24)(r4)
 	PPC_STL	r25, VCPU_GPR(R25)(r4)
@@ -163,33 +137,15 @@
 	PPC_STL	r29, VCPU_GPR(R29)(r4)
 	PPC_STL	r30, VCPU_GPR(R30)(r4)
 	PPC_STL	r31, VCPU_GPR(R31)(r4)
-	mtspr	SPRN_EPLC, r8
-
-	/* disable preemption, so we are sure we hit the fixup handler */
-	CURRENT_THREAD_INFO(r8, r1)
-	li	r7, 1
-	stw	r7, TI_PREEMPT(r8)
-
-	isync
 
 	/*
-	 * In case the read goes wrong, we catch it and write an invalid value
-	 * in LAST_INST instead.
+	 * We don't use external PID support. lwepx faults would need to be
+	 * handled by KVM and this implies aditional code in DO_KVM (for
+	 * DTB_MISS, DSI and LRAT) to check ESR[EPID] and EPLC[EGS] which
+	 * is too intrusive for the host. Get last instuction in
+	 * kvmppc_get_last_inst().
 	 */
-1:	lwepx	r9, 0, r5
-2:
-.section .fixup, "ax"
-3:	li	r9, KVM_INST_FETCH_FAILED
-	b	2b
-.previous
-.section __ex_table,"a"
-	PPC_LONG_ALIGN
-	PPC_LONG 1b,3b
-.previous
-
-	mtspr	SPRN_EPLC, r3
-	li	r7, 0
-	stw	r7, TI_PREEMPT(r8)
+	li	r9, KVM_INST_FETCH_FAILED
 	stw	r9, VCPU_LAST_INST(r4)
 	.endif
 
@@ -441,6 +397,7 @@ _GLOBAL(kvmppc_resume_host)
 #ifdef CONFIG_64BIT
 	PPC_LL	r3, PACA_SPRG_VDSO(r13)
 #endif
+	mfspr	r5, SPRN_SPRG9
 	PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
 	mfspr	r8, SPRN_SPRG6
 	PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
@@ -448,6 +405,7 @@ _GLOBAL(kvmppc_resume_host)
 #ifdef CONFIG_64BIT
 	mtspr	SPRN_SPRG_VDSO_WRITE, r3
 #endif
+	PPC_STD(r5, VCPU_SPRG9, r4)
 	PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
 	mfxer	r3
 	PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
@@ -682,7 +640,9 @@ lightweight_exit:
 	mtspr	SPRN_SPRG5W, r6
 	PPC_LD(r8, VCPU_SHARED_SPRG7, r11)
 	mtspr	SPRN_SPRG6W, r7
+	PPC_LD(r5, VCPU_SPRG9, r4)
 	mtspr	SPRN_SPRG7W, r8
+	mtspr	SPRN_SPRG9, r5
 
 	/* Load some guest volatiles. */
 	PPC_LL	r3, VCPU_LR(r4)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/booke_interrupts.S linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke_interrupts.S
--- linux-libre-3.16-gnu/arch/powerpc/kvm/booke_interrupts.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/booke_interrupts.S	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,6 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
-#include <asm/mmu-44x.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
@@ -424,10 +423,6 @@ lightweight_exit:
 	mtspr	SPRN_PID1, r3
 #endif
 
-#ifdef CONFIG_44x
-	iccci	0, 0 /* XXX hack */
-#endif
-
 	/* Load some guest volatiles. */
 	lwz	r0, VCPU_GPR(R0)(r4)
 	lwz	r2, VCPU_GPR(R2)(r4)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/e500_emulate.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500_emulate.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/e500_emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500_emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -250,6 +250,14 @@ int kvmppc_core_emulate_mtspr_e500(struc
 				spr_val);
 		break;
 
+	case SPRN_PWRMGTCR0:
+		/*
+		 * Guest relies on host power management configurations
+		 * Treat the request as a general store
+		 */
+		vcpu->arch.pwrmgtcr0 = spr_val;
+		break;
+
 	/* extra exceptions */
 	case SPRN_IVOR32:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
@@ -368,6 +376,10 @@ int kvmppc_core_emulate_mfspr_e500(struc
 		*spr_val = vcpu->arch.eptcfg;
 		break;
 
+	case SPRN_PWRMGTCR0:
+		*spr_val = vcpu->arch.pwrmgtcr0;
+		break;
+
 	/* extra exceptions */
 	case SPRN_IVOR32:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/e500mc.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500mc.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/e500mc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500mc.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,7 +110,7 @@ void kvmppc_mmu_msr_notify(struct kvm_vc
 {
 }
 
-static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
+static DEFINE_PER_CPU(struct kvm_vcpu *[KVMPPC_NR_LPIDS], last_vcpu_of_lpid);
 
 static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
 {
@@ -141,9 +141,9 @@ static void kvmppc_core_vcpu_load_e500mc
 	mtspr(SPRN_GESR, vcpu->arch.shared->esr);
 
 	if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
-	    __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
+	    __get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] != vcpu) {
 		kvmppc_e500_tlbil_all(vcpu_e500);
-		__get_cpu_var(last_vcpu_on_cpu) = vcpu;
+		__get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] = vcpu;
 	}
 
 	kvmppc_load_guest_fp(vcpu);
@@ -267,14 +267,32 @@ static int kvmppc_core_set_sregs_e500mc(
 static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
 			      union kvmppc_one_reg *val)
 {
-	int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+	int r = 0;
+
+	switch (id) {
+	case KVM_REG_PPC_SPRG9:
+		*val = get_reg_val(id, vcpu->arch.sprg9);
+		break;
+	default:
+		r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+	}
+
 	return r;
 }
 
 static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
 			      union kvmppc_one_reg *val)
 {
-	int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val);
+	int r = 0;
+
+	switch (id) {
+	case KVM_REG_PPC_SPRG9:
+		vcpu->arch.sprg9 = set_reg_val(id, *val);
+		break;
+	default:
+		r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val);
+	}
+
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/e500_mmu_host.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500_mmu_host.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/e500_mmu_host.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/e500_mmu_host.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,11 +107,15 @@ static u32 get_host_mas0(unsigned long e
 {
 	unsigned long flags;
 	u32 mas0;
+	u32 mas4;
 
 	local_irq_save(flags);
 	mtspr(SPRN_MAS6, 0);
+	mas4 = mfspr(SPRN_MAS4);
+	mtspr(SPRN_MAS4, mas4 & ~MAS4_TLBSEL_MASK);
 	asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET));
 	mas0 = mfspr(SPRN_MAS0);
+	mtspr(SPRN_MAS4, mas4);
 	local_irq_restore(flags);
 
 	return mas0;
@@ -607,6 +611,104 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcp
 	}
 }
 
+#ifdef CONFIG_KVM_BOOKE_HV
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+			  u32 *instr)
+{
+	gva_t geaddr;
+	hpa_t addr;
+	hfn_t pfn;
+	hva_t eaddr;
+	u32 mas1, mas2, mas3;
+	u64 mas7_mas3;
+	struct page *page;
+	unsigned int addr_space, psize_shift;
+	bool pr;
+	unsigned long flags;
+
+	/* Search TLB for guest pc to get the real address */
+	geaddr = kvmppc_get_pc(vcpu);
+
+	addr_space = (vcpu->arch.shared->msr & MSR_IS) >> MSR_IR_LG;
+
+	local_irq_save(flags);
+	mtspr(SPRN_MAS6, (vcpu->arch.pid << MAS6_SPID_SHIFT) | addr_space);
+	mtspr(SPRN_MAS5, MAS5_SGS | vcpu->kvm->arch.lpid);
+	asm volatile("tlbsx 0, %[geaddr]\n" : :
+		     [geaddr] "r" (geaddr));
+	mtspr(SPRN_MAS5, 0);
+	mtspr(SPRN_MAS8, 0);
+	mas1 = mfspr(SPRN_MAS1);
+	mas2 = mfspr(SPRN_MAS2);
+	mas3 = mfspr(SPRN_MAS3);
+#ifdef CONFIG_64BIT
+	mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
+#else
+	mas7_mas3 = ((u64)mfspr(SPRN_MAS7) << 32) | mas3;
+#endif
+	local_irq_restore(flags);
+
+	/*
+	 * If the TLB entry for guest pc was evicted, return to the guest.
+	 * There are high chances to find a valid TLB entry next time.
+	 */
+	if (!(mas1 & MAS1_VALID))
+		return EMULATE_AGAIN;
+
+	/*
+	 * Another thread may rewrite the TLB entry in parallel, don't
+	 * execute from the address if the execute permission is not set
+	 */
+	pr = vcpu->arch.shared->msr & MSR_PR;
+	if (unlikely((pr && !(mas3 & MAS3_UX)) ||
+		     (!pr && !(mas3 & MAS3_SX)))) {
+		pr_err_ratelimited(
+			"%s: Instuction emulation from guest addres %08lx without execute permission\n",
+			__func__, geaddr);
+		return EMULATE_AGAIN;
+	}
+
+	/*
+	 * The real address will be mapped by a cacheable, memory coherent,
+	 * write-back page. Check for mismatches when LRAT is used.
+	 */
+	if (has_feature(vcpu, VCPU_FTR_MMU_V2) &&
+	    unlikely((mas2 & MAS2_I) || (mas2 & MAS2_W) || !(mas2 & MAS2_M))) {
+		pr_err_ratelimited(
+			"%s: Instuction emulation from guest addres %08lx mismatches storage attributes\n",
+			__func__, geaddr);
+		return EMULATE_AGAIN;
+	}
+
+	/* Get pfn */
+	psize_shift = MAS1_GET_TSIZE(mas1) + 10;
+	addr = (mas7_mas3 & (~0ULL << psize_shift)) |
+	       (geaddr & ((1ULL << psize_shift) - 1ULL));
+	pfn = addr >> PAGE_SHIFT;
+
+	/* Guard against emulation from devices area */
+	if (unlikely(!page_is_ram(pfn))) {
+		pr_err_ratelimited("%s: Instruction emulation from non-RAM host addres %08llx is not supported\n",
+			 __func__, addr);
+		return EMULATE_AGAIN;
+	}
+
+	/* Map a page and get guest's instruction */
+	page = pfn_to_page(pfn);
+	eaddr = (unsigned long)kmap_atomic(page);
+	*instr = *(u32 *)(eaddr | (unsigned long)(addr & ~PAGE_MASK));
+	kunmap_atomic((u32 *)eaddr);
+
+	return EMULATE_DONE;
+}
+#else
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+			  u32 *instr)
+{
+	return EMULATE_AGAIN;
+}
+#endif
+
 /************* MMU Notifiers *************/
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/emulate.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/emulate.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -207,36 +207,28 @@ static int kvmppc_emulate_mfspr(struct k
 	return emulated;
 }
 
-/* XXX to do:
- * lhax
- * lhaux
- * lswx
- * lswi
- * stswx
- * stswi
- * lha
- * lhau
- * lmw
- * stmw
- *
- */
 /* XXX Should probably auto-generate instruction decoding for a particular core
  * from opcode tables in the future. */
 int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
-	u32 inst = kvmppc_get_last_inst(vcpu);
-	int ra = get_ra(inst);
-	int rs = get_rs(inst);
-	int rt = get_rt(inst);
-	int sprn = get_sprn(inst);
-	enum emulation_result emulated = EMULATE_DONE;
+	u32 inst;
+	int rs, rt, sprn;
+	enum emulation_result emulated;
 	int advance = 1;
 
 	/* this default type might be overwritten by subcategories */
 	kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
 
+	emulated = kvmppc_get_last_inst(vcpu, false, &inst);
+	if (emulated != EMULATE_DONE)
+		return emulated;
+
 	pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
 
+	rs = get_rs(inst);
+	rt = get_rt(inst);
+	sprn = get_sprn(inst);
+
 	switch (get_op(inst)) {
 	case OP_TRAP:
 #ifdef CONFIG_PPC_BOOK3S
@@ -264,200 +256,24 @@ int kvmppc_emulate_instruction(struct kv
 #endif
 			advance = 0;
 			break;
-		case OP_31_XOP_LWZX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
-			break;
-
-		case OP_31_XOP_LBZX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-			break;
-
-		case OP_31_XOP_LBZUX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-			break;
-
-		case OP_31_XOP_STWX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               4, 1);
-			break;
-
-		case OP_31_XOP_STBX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               1, 1);
-			break;
-
-		case OP_31_XOP_STBUX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               1, 1);
-			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-			break;
-
-		case OP_31_XOP_LHAX:
-			emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
-			break;
-
-		case OP_31_XOP_LHZX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-			break;
-
-		case OP_31_XOP_LHZUX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-			break;
 
 		case OP_31_XOP_MFSPR:
 			emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
 			break;
 
-		case OP_31_XOP_STHX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               2, 1);
-			break;
-
-		case OP_31_XOP_STHUX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               2, 1);
-			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-			break;
-
 		case OP_31_XOP_MTSPR:
 			emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
 			break;
 
-		case OP_31_XOP_DCBST:
-		case OP_31_XOP_DCBF:
-		case OP_31_XOP_DCBI:
-			/* Do nothing. The guest is performing dcbi because
-			 * hardware DMA is not snooped by the dcache, but
-			 * emulated DMA either goes through the dcache as
-			 * normal writes, or the host kernel has handled dcache
-			 * coherence. */
-			break;
-
-		case OP_31_XOP_LWBRX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
-			break;
-
 		case OP_31_XOP_TLBSYNC:
 			break;
 
-		case OP_31_XOP_STWBRX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               4, 0);
-			break;
-
-		case OP_31_XOP_LHBRX:
-			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
-			break;
-
-		case OP_31_XOP_STHBRX:
-			emulated = kvmppc_handle_store(run, vcpu,
-						       kvmppc_get_gpr(vcpu, rs),
-			                               2, 0);
-			break;
-
 		default:
 			/* Attempt core-specific emulation below. */
 			emulated = EMULATE_FAIL;
 		}
 		break;
 
-	case OP_LWZ:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
-		break;
-
-	/* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */
-	case OP_LD:
-		rt = get_rt(inst);
-		emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
-		break;
-
-	case OP_LWZU:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_LBZ:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-		break;
-
-	case OP_LBZU:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_STW:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               4, 1);
-		break;
-
-	/* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */
-	case OP_STD:
-		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               8, 1);
-		break;
-
-	case OP_STWU:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               4, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_STB:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               1, 1);
-		break;
-
-	case OP_STBU:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               1, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_LHZ:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-		break;
-
-	case OP_LHZU:
-		emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_LHA:
-		emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
-		break;
-
-	case OP_LHAU:
-		emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
-	case OP_STH:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               2, 1);
-		break;
-
-	case OP_STHU:
-		emulated = kvmppc_handle_store(run, vcpu,
-					       kvmppc_get_gpr(vcpu, rs),
-		                               2, 1);
-		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
-		break;
-
 	default:
 		emulated = EMULATE_FAIL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/emulate_loadstore.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/emulate_loadstore.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/emulate_loadstore.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/emulate_loadstore.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,272 @@
+/*
+ * This program is free software; you can 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/jiffies.h>
+#include <linux/hrtimer.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm_host.h>
+#include <linux/clockchips.h>
+
+#include <asm/reg.h>
+#include <asm/time.h>
+#include <asm/byteorder.h>
+#include <asm/kvm_ppc.h>
+#include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
+#include "timing.h"
+#include "trace.h"
+
+/* XXX to do:
+ * lhax
+ * lhaux
+ * lswx
+ * lswi
+ * stswx
+ * stswi
+ * lha
+ * lhau
+ * lmw
+ * stmw
+ *
+ */
+int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	u32 inst;
+	int ra, rs, rt;
+	enum emulation_result emulated;
+	int advance = 1;
+
+	/* this default type might be overwritten by subcategories */
+	kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
+
+	emulated = kvmppc_get_last_inst(vcpu, false, &inst);
+	if (emulated != EMULATE_DONE)
+		return emulated;
+
+	ra = get_ra(inst);
+	rs = get_rs(inst);
+	rt = get_rt(inst);
+
+	switch (get_op(inst)) {
+	case 31:
+		switch (get_xop(inst)) {
+		case OP_31_XOP_LWZX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+			break;
+
+		case OP_31_XOP_LBZX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+			break;
+
+		case OP_31_XOP_LBZUX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+			break;
+
+		case OP_31_XOP_STWX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               4, 1);
+			break;
+
+		case OP_31_XOP_STBX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               1, 1);
+			break;
+
+		case OP_31_XOP_STBUX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               1, 1);
+			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+			break;
+
+		case OP_31_XOP_LHAX:
+			emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+			break;
+
+		case OP_31_XOP_LHZX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+			break;
+
+		case OP_31_XOP_LHZUX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+			break;
+
+		case OP_31_XOP_STHX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               2, 1);
+			break;
+
+		case OP_31_XOP_STHUX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               2, 1);
+			kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+			break;
+
+		case OP_31_XOP_DCBST:
+		case OP_31_XOP_DCBF:
+		case OP_31_XOP_DCBI:
+			/* Do nothing. The guest is performing dcbi because
+			 * hardware DMA is not snooped by the dcache, but
+			 * emulated DMA either goes through the dcache as
+			 * normal writes, or the host kernel has handled dcache
+			 * coherence. */
+			break;
+
+		case OP_31_XOP_LWBRX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
+			break;
+
+		case OP_31_XOP_STWBRX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               4, 0);
+			break;
+
+		case OP_31_XOP_LHBRX:
+			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
+			break;
+
+		case OP_31_XOP_STHBRX:
+			emulated = kvmppc_handle_store(run, vcpu,
+						       kvmppc_get_gpr(vcpu, rs),
+			                               2, 0);
+			break;
+
+		default:
+			emulated = EMULATE_FAIL;
+			break;
+		}
+		break;
+
+	case OP_LWZ:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+		break;
+
+	/* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */
+	case OP_LD:
+		rt = get_rt(inst);
+		emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
+		break;
+
+	case OP_LWZU:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_LBZ:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+		break;
+
+	case OP_LBZU:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_STW:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               4, 1);
+		break;
+
+	/* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */
+	case OP_STD:
+		rs = get_rs(inst);
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               8, 1);
+		break;
+
+	case OP_STWU:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               4, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_STB:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               1, 1);
+		break;
+
+	case OP_STBU:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               1, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_LHZ:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+		break;
+
+	case OP_LHZU:
+		emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_LHA:
+		emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+		break;
+
+	case OP_LHAU:
+		emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	case OP_STH:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               2, 1);
+		break;
+
+	case OP_STHU:
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
+		                               2, 1);
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+		break;
+
+	default:
+		emulated = EMULATE_FAIL;
+		break;
+	}
+
+	if (emulated == EMULATE_FAIL) {
+		advance = 0;
+		kvmppc_core_queue_program(vcpu, 0);
+	}
+
+	trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated);
+
+	/* Advance past emulated instruction. */
+	if (advance)
+		kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
+
+	return emulated;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/Kconfig linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/Kconfig
--- linux-libre-3.16-gnu/arch/powerpc/kvm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,6 @@ config KVM_BOOK3S_64
 config KVM_BOOK3S_64_HV
 	tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
 	depends on KVM_BOOK3S_64
-	depends on !CPU_LITTLE_ENDIAN
 	select KVM_BOOK3S_HV_POSSIBLE
 	select MMU_NOTIFIER
 	select CMA
@@ -113,23 +112,9 @@ config KVM_BOOK3S_64_PR
 config KVM_BOOKE_HV
 	bool
 
-config KVM_440
-	bool "KVM support for PowerPC 440 processors"
-	depends on 44x
-	select KVM
-	select KVM_MMIO
-	---help---
-	  Support running unmodified 440 guest kernels in virtual machines on
-	  440 host processors.
-
-	  This module provides access to the hardware capabilities through
-	  a character device node named /dev/kvm.
-
-	  If unsure, say N.
-
 config KVM_EXIT_TIMING
 	bool "Detailed exit timing"
-	depends on KVM_440 || KVM_E500V2 || KVM_E500MC
+	depends on KVM_E500V2 || KVM_E500MC
 	---help---
 	  Calculate elapsed time for every exit/enter cycle. A per-vcpu
 	  report is available in debugfs kvm/vm#_vcpu#_timing.
@@ -173,6 +158,7 @@ config KVM_MPIC
 	bool "KVM in-kernel MPIC emulation"
 	depends on KVM && E500
 	select HAVE_KVM_IRQCHIP
+	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQ_ROUTING
 	select HAVE_KVM_MSI
 	help
@@ -184,6 +170,8 @@ config KVM_MPIC
 config KVM_XICS
 	bool "KVM in-kernel XICS emulation"
 	depends on KVM_BOOK3S_64 && !KVM_MPIC
+	select HAVE_KVM_IRQCHIP
+	select HAVE_KVM_IRQFD
 	---help---
 	  Include support for the XICS (eXternal Interrupt Controller
 	  Specification) interrupt controller architecture used on
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/Makefile linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/Makefile
--- linux-libre-3.16-gnu/arch/powerpc/kvm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,27 +10,17 @@ KVM := ../../../virt/kvm
 common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
 		$(KVM)/eventfd.o
 
-CFLAGS_44x_tlb.o  := -I.
 CFLAGS_e500_mmu.o := -I.
 CFLAGS_e500_mmu_host.o := -I.
 CFLAGS_emulate.o  := -I.
+CFLAGS_emulate_loadstore.o  := -I.
 
-common-objs-y += powerpc.o emulate.o
+common-objs-y += powerpc.o emulate.o emulate_loadstore.o
 obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
 obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o
 
 AFLAGS_booke_interrupts.o := -I$(obj)
 
-kvm-440-objs := \
-	$(common-objs-y) \
-	booke.o \
-	booke_emulate.o \
-	booke_interrupts.o \
-	44x.o \
-	44x_tlb.o \
-	44x_emulate.o
-kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs)
-
 kvm-e500-objs := \
 	$(common-objs-y) \
 	booke.o \
@@ -58,6 +48,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_
 
 kvm-pr-y := \
 	fpu.o \
+	emulate.o \
 	book3s_paired_singles.o \
 	book3s_pr.o \
 	book3s_pr_papr.o \
@@ -90,7 +81,6 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_
 	book3s_hv_rm_mmu.o \
 	book3s_hv_ras.o \
 	book3s_hv_builtin.o \
-	book3s_hv_cma.o \
 	$(kvm-book3s_64-builtin-xics-objs-y)
 endif
 
@@ -101,7 +91,7 @@ kvm-book3s_64-module-objs += \
 	$(KVM)/kvm_main.o \
 	$(KVM)/eventfd.o \
 	powerpc.o \
-	emulate.o \
+	emulate_loadstore.o \
 	book3s.o \
 	book3s_64_vio.o \
 	book3s_rtas.o \
@@ -127,7 +117,6 @@ kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING)
 
 kvm-objs := $(kvm-objs-m) $(kvm-objs-y)
 
-obj-$(CONFIG_KVM_440) += kvm.o
 obj-$(CONFIG_KVM_E500V2) += kvm.o
 obj-$(CONFIG_KVM_E500MC) += kvm.o
 obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/mpic.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/mpic.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/mpic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/mpic.c	2014-09-28 17:29:07.000000000 -0400
@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_ro
 	return 0;
 }
 
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
-			  struct kvm_kernel_irq_routing_entry *e,
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
 			  const struct kvm_irq_routing_entry *ue)
 {
 	int r = -EINVAL;
@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq
 		e->irqchip.pin = ue->u.irqchip.pin;
 		if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
 			goto out;
-		rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
 		break;
 	case KVM_IRQ_ROUTING_MSI:
 		e->set = kvm_set_msi;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/powerpc.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/powerpc.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/powerpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/powerpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,6 +190,25 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 		vcpu->arch.magic_page_pa = param1 & ~0xfffULL;
 		vcpu->arch.magic_page_ea = param2 & ~0xfffULL;
 
+#ifdef CONFIG_PPC_64K_PAGES
+		/*
+		 * Make sure our 4k magic page is in the same window of a 64k
+		 * page within the guest and within the host's page.
+		 */
+		if ((vcpu->arch.magic_page_pa & 0xf000) !=
+		    ((ulong)vcpu->arch.shared & 0xf000)) {
+			void *old_shared = vcpu->arch.shared;
+			ulong shared = (ulong)vcpu->arch.shared;
+			void *new_shared;
+
+			shared &= PAGE_MASK;
+			shared |= vcpu->arch.magic_page_pa & 0xf000;
+			new_shared = (void*)shared;
+			memcpy(new_shared, old_shared, 0x1000);
+			vcpu->arch.shared = new_shared;
+		}
+#endif
+
 		r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
 		r = EV_SUCCESS;
@@ -198,7 +217,6 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 	case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
 		r = EV_SUCCESS;
 #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
-		/* XXX Missing magic page on 44x */
 		r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
 #endif
 
@@ -254,13 +272,16 @@ int kvmppc_emulate_mmio(struct kvm_run *
 	enum emulation_result er;
 	int r;
 
-	er = kvmppc_emulate_instruction(run, vcpu);
+	er = kvmppc_emulate_loadstore(vcpu);
 	switch (er) {
 	case EMULATE_DONE:
 		/* Future optimization: only reload non-volatiles if they were
 		 * actually modified. */
 		r = RESUME_GUEST_NV;
 		break;
+	case EMULATE_AGAIN:
+		r = RESUME_GUEST;
+		break;
 	case EMULATE_DO_MMIO:
 		run->exit_reason = KVM_EXIT_MMIO;
 		/* We must reload nonvolatiles because "update" load/store
@@ -270,11 +291,15 @@ int kvmppc_emulate_mmio(struct kvm_run *
 		r = RESUME_HOST_NV;
 		break;
 	case EMULATE_FAIL:
+	{
+		u32 last_inst;
+
+		kvmppc_get_last_inst(vcpu, false, &last_inst);
 		/* XXX Deliver Program interrupt to guest. */
-		printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
-		       kvmppc_get_last_inst(vcpu));
+		pr_emerg("%s: emulation failed (%08x)\n", __func__, last_inst);
 		r = RESUME_HOST;
 		break;
+	}
 	default:
 		WARN_ON(1);
 		r = RESUME_GUEST;
@@ -284,6 +309,81 @@ int kvmppc_emulate_mmio(struct kvm_run *
 }
 EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio);
 
+int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+	      bool data)
+{
+	ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
+	struct kvmppc_pte pte;
+	int r;
+
+	vcpu->stat.st++;
+
+	r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
+			 XLATE_WRITE, &pte);
+	if (r < 0)
+		return r;
+
+	*eaddr = pte.raddr;
+
+	if (!pte.may_write)
+		return -EPERM;
+
+	/* Magic page override */
+	if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+	    ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+	    !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+		void *magic = vcpu->arch.shared;
+		magic += pte.eaddr & 0xfff;
+		memcpy(magic, ptr, size);
+		return EMULATE_DONE;
+	}
+
+	if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
+		return EMULATE_DO_MMIO;
+
+	return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvmppc_st);
+
+int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+		      bool data)
+{
+	ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
+	struct kvmppc_pte pte;
+	int rc;
+
+	vcpu->stat.ld++;
+
+	rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
+			  XLATE_READ, &pte);
+	if (rc)
+		return rc;
+
+	*eaddr = pte.raddr;
+
+	if (!pte.may_read)
+		return -EPERM;
+
+	if (!data && !pte.may_execute)
+		return -ENOEXEC;
+
+	/* Magic page override */
+	if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+	    ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+	    !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+		void *magic = vcpu->arch.shared;
+		magic += pte.eaddr & 0xfff;
+		memcpy(ptr, magic, size);
+		return EMULATE_DONE;
+	}
+
+	if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size))
+		return EMULATE_DO_MMIO;
+
+	return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvmppc_ld);
+
 int kvm_arch_hardware_enable(void *garbage)
 {
 	return 0;
@@ -366,14 +466,20 @@ void kvm_arch_sync_events(struct kvm *kv
 {
 }
 
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 	int r;
-	/* FIXME!!
-	 * Should some of this be vm ioctl ? is it possible now ?
-	 */
+	/* Assume we're using HV mode when the HV module is loaded */
 	int hv_enabled = kvmppc_hv_ops ? 1 : 0;
 
+	if (kvm) {
+		/*
+		 * Hooray - we know which VM type we're running on. Depend on
+		 * that rather than the guess above.
+		 */
+		hv_enabled = is_kvmppc_hv_enabled(kvm);
+	}
+
 	switch (ext) {
 #ifdef CONFIG_BOOKE
 	case KVM_CAP_PPC_BOOKE_SREGS:
@@ -387,6 +493,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_PPC_UNSET_IRQ:
 	case KVM_CAP_PPC_IRQ_LEVEL:
 	case KVM_CAP_ENABLE_CAP:
+	case KVM_CAP_ENABLE_CAP_VM:
 	case KVM_CAP_ONE_REG:
 	case KVM_CAP_IOEVENTFD:
 	case KVM_CAP_DEVICE_CTRL:
@@ -417,6 +524,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_PPC_ALLOC_HTAB:
 	case KVM_CAP_PPC_RTAS:
 	case KVM_CAP_PPC_FIXUP_HCALL:
+	case KVM_CAP_PPC_ENABLE_HCALL:
 #ifdef CONFIG_KVM_XICS
 	case KVM_CAP_IRQ_XICS:
 #endif
@@ -635,12 +743,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
 #endif
 }
 
-static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
-                                     struct kvm_run *run)
-{
-	kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, run->dcr.data);
-}
-
 static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
                                       struct kvm_run *run)
 {
@@ -837,10 +939,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 		if (!vcpu->mmio_is_write)
 			kvmppc_complete_mmio_load(vcpu, run);
 		vcpu->mmio_needed = 0;
-	} else if (vcpu->arch.dcr_needed) {
-		if (!vcpu->arch.dcr_is_write)
-			kvmppc_complete_dcr_load(vcpu, run);
-		vcpu->arch.dcr_needed = 0;
 	} else if (vcpu->arch.osi_needed) {
 		u64 *gprs = run->osi.gprs;
 		int i;
@@ -1099,6 +1197,42 @@ int kvm_vm_ioctl_irq_line(struct kvm *kv
 	return 0;
 }
 
+
+static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
+				   struct kvm_enable_cap *cap)
+{
+	int r;
+
+	if (cap->flags)
+		return -EINVAL;
+
+	switch (cap->cap) {
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+	case KVM_CAP_PPC_ENABLE_HCALL: {
+		unsigned long hcall = cap->args[0];
+
+		r = -EINVAL;
+		if (hcall > MAX_HCALL_OPCODE || (hcall & 3) ||
+		    cap->args[1] > 1)
+			break;
+		if (!kvmppc_book3s_hcall_implemented(kvm, hcall))
+			break;
+		if (cap->args[1])
+			set_bit(hcall / 4, kvm->arch.enabled_hcalls);
+		else
+			clear_bit(hcall / 4, kvm->arch.enabled_hcalls);
+		r = 0;
+		break;
+	}
+#endif
+	default:
+		r = -EINVAL;
+		break;
+	}
+
+	return r;
+}
+
 long kvm_arch_vm_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg)
 {
@@ -1118,6 +1252,15 @@ long kvm_arch_vm_ioctl(struct file *filp
 
 		break;
 	}
+	case KVM_ENABLE_CAP:
+	{
+		struct kvm_enable_cap cap;
+		r = -EFAULT;
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			goto out;
+		r = kvm_vm_ioctl_enable_cap(kvm, &cap);
+		break;
+	}
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CREATE_SPAPR_TCE: {
 		struct kvm_create_spapr_tce create_tce;
@@ -1204,3 +1347,5 @@ void kvm_arch_exit(void)
 {
 
 }
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ppc_instr);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/timing.c linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/timing.c
--- linux-libre-3.16-gnu/arch/powerpc/kvm/timing.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/timing.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,7 +110,6 @@ void kvmppc_update_timing_stats(struct k
 
 static const char *kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = {
 	[MMIO_EXITS] =              "MMIO",
-	[DCR_EXITS] =               "DCR",
 	[SIGNAL_EXITS] =            "SIGNAL",
 	[ITLB_REAL_MISS_EXITS] =    "ITLBREAL",
 	[ITLB_VIRT_MISS_EXITS] =    "ITLBVIRT",
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/kvm/timing.h linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/timing.h
--- linux-libre-3.16-gnu/arch/powerpc/kvm/timing.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/kvm/timing.h	2014-09-28 17:29:07.000000000 -0400
@@ -63,9 +63,6 @@ static inline void kvmppc_account_exit_s
 	case EMULATED_INST_EXITS:
 		vcpu->stat.emulated_inst_exits++;
 		break;
-	case DCR_EXITS:
-		vcpu->stat.dcr_exits++;
-		break;
 	case DSI_EXITS:
 		vcpu->stat.dsi_exits++;
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/lib/copyuser_64.S linux-libre-3.17-rc7-gnu/arch/powerpc/lib/copyuser_64.S
--- linux-libre-3.16-gnu/arch/powerpc/lib/copyuser_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/lib/copyuser_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -461,8 +461,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_
 /*
  * Routine to copy a whole page of data, optimized for POWER4.
  * On POWER4 it is more than 50% faster than the simple loop
- * above (following the .Ldst_aligned label) but it runs slightly
- * slower on POWER3.
+ * above (following the .Ldst_aligned label).
  */
 .Lcopy_page_4K:
 	std	r31,-32(1)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/lib/locks.c linux-libre-3.17-rc7-gnu/arch/powerpc/lib/locks.c
--- linux-libre-3.16-gnu/arch/powerpc/lib/locks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/lib/locks.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,12 +70,16 @@ void __rw_yield(arch_rwlock_t *rw)
 
 void arch_spin_unlock_wait(arch_spinlock_t *lock)
 {
+	smp_mb();
+
 	while (lock->slock) {
 		HMT_low();
 		if (SHARED_PROCESSOR)
 			__spin_yield(lock);
 	}
 	HMT_medium();
+
+	smp_mb();
 }
 
 EXPORT_SYMBOL(arch_spin_unlock_wait);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/dma-noncoherent.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/dma-noncoherent.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/dma-noncoherent.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/dma-noncoherent.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/export.h>
 
 #include <asm/tlbflush.h>
+#include <asm/dma.h>
 
 #include "mmu_decl.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/hash_native_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hash_native_64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/hash_native_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hash_native_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -412,18 +412,18 @@ static void native_hpte_invalidate(unsig
 	local_irq_restore(flags);
 }
 
-static void native_hugepage_invalidate(struct mm_struct *mm,
+static void native_hugepage_invalidate(unsigned long vsid,
+				       unsigned long addr,
 				       unsigned char *hpte_slot_array,
-				       unsigned long addr, int psize)
+				       int psize, int ssize)
 {
-	int ssize = 0, i;
-	int lock_tlbie;
+	int i;
 	struct hash_pte *hptep;
 	int actual_psize = MMU_PAGE_16M;
 	unsigned int max_hpte_count, valid;
 	unsigned long flags, s_addr = addr;
 	unsigned long hpte_v, want_v, shift;
-	unsigned long hidx, vpn = 0, vsid, hash, slot;
+	unsigned long hidx, vpn = 0, hash, slot;
 
 	shift = mmu_psize_defs[psize].shift;
 	max_hpte_count = 1U << (PMD_SHIFT - shift);
@@ -437,15 +437,6 @@ static void native_hugepage_invalidate(s
 
 		/* get the vpn */
 		addr = s_addr + (i * (1ul << shift));
-		if (!is_kernel_addr(addr)) {
-			ssize = user_segment_size(addr);
-			vsid = get_vsid(mm->context.id, addr, ssize);
-			WARN_ON(vsid == 0);
-		} else {
-			vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
-			ssize = mmu_kernel_ssize;
-		}
-
 		vpn = hpt_vpn(addr, vsid, ssize);
 		hash = hpt_hash(vpn, shift, ssize);
 		if (hidx & _PTEIDX_SECONDARY)
@@ -465,22 +456,13 @@ static void native_hugepage_invalidate(s
 		else
 			/* Invalidate the hpte. NOTE: this also unlocks it */
 			hptep->v = 0;
+		/*
+		 * We need to do tlb invalidate for all the address, tlbie
+		 * instruction compares entry_VA in tlb with the VA specified
+		 * here
+		 */
+		tlbie(vpn, psize, actual_psize, ssize, 0);
 	}
-	/*
-	 * Since this is a hugepage, we just need a single tlbie.
-	 * use the last vpn.
-	 */
-	lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
-	if (lock_tlbie)
-		raw_spin_lock(&native_tlbie_lock);
-
-	asm volatile("ptesync":::"memory");
-	__tlbie(vpn, psize, actual_psize, ssize);
-	asm volatile("eieio; tlbsync; ptesync":::"memory");
-
-	if (lock_tlbie)
-		raw_spin_unlock(&native_tlbie_lock);
-
 	local_irq_restore(flags);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/hash_utils_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/hash_utils_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hash_utils_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -243,7 +243,7 @@ int htab_bolt_mapping(unsigned long vsta
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-static int htab_remove_mapping(unsigned long vstart, unsigned long vend,
+int htab_remove_mapping(unsigned long vstart, unsigned long vend,
 		      int psize, int ssize)
 {
 	unsigned long vaddr;
@@ -821,21 +821,14 @@ static void __init htab_initialize(void)
 
 void __init early_init_mmu(void)
 {
-	/* Setup initial STAB address in the PACA */
-	get_paca()->stab_real = __pa((u64)&initial_stab);
-	get_paca()->stab_addr = (u64)&initial_stab;
-
 	/* Initialize the MMU Hash table and create the linear mapping
-	 * of memory. Has to be done before stab/slb initialization as
-	 * this is currently where the page size encoding is obtained
+	 * of memory. Has to be done before SLB initialization as this is
+	 * currently where the page size encoding is obtained.
 	 */
 	htab_initialize();
 
-	/* Initialize stab / SLB management */
-	if (mmu_has_feature(MMU_FTR_SLB))
-		slb_initialize();
-	else
-		stab_initialize(get_paca()->stab_real);
+	/* Initialize SLB management */
+	slb_initialize();
 }
 
 #ifdef CONFIG_SMP
@@ -845,13 +838,8 @@ void early_init_mmu_secondary(void)
 	if (!firmware_has_feature(FW_FEATURE_LPAR))
 		mtspr(SPRN_SDR1, _SDR1);
 
-	/* Initialize STAB/SLB. We use a virtual address as it works
-	 * in real mode on pSeries.
-	 */
-	if (mmu_has_feature(MMU_FTR_SLB))
-		slb_initialize();
-	else
-		stab_initialize(get_paca()->stab_addr);
+	/* Initialize SLB */
+	slb_initialize();
 }
 #endif /* CONFIG_SMP */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/hugepage-hash64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hugepage-hash64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/hugepage-hash64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/hugepage-hash64.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,57 @@
 #include <linux/mm.h>
 #include <asm/machdep.h>
 
+static void invalidate_old_hpte(unsigned long vsid, unsigned long addr,
+				pmd_t *pmdp, unsigned int psize, int ssize)
+{
+	int i, max_hpte_count, valid;
+	unsigned long s_addr;
+	unsigned char *hpte_slot_array;
+	unsigned long hidx, shift, vpn, hash, slot;
+
+	s_addr = addr & HPAGE_PMD_MASK;
+	hpte_slot_array = get_hpte_slot_array(pmdp);
+	/*
+	 * IF we try to do a HUGE PTE update after a withdraw is done.
+	 * we will find the below NULL. This happens when we do
+	 * split_huge_page_pmd
+	 */
+	if (!hpte_slot_array)
+		return;
+
+	if (ppc_md.hugepage_invalidate)
+		return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array,
+						  psize, ssize);
+	/*
+	 * No bluk hpte removal support, invalidate each entry
+	 */
+	shift = mmu_psize_defs[psize].shift;
+	max_hpte_count = HPAGE_PMD_SIZE >> shift;
+	for (i = 0; i < max_hpte_count; i++) {
+		/*
+		 * 8 bits per each hpte entries
+		 * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit]
+		 */
+		valid = hpte_valid(hpte_slot_array, i);
+		if (!valid)
+			continue;
+		hidx =  hpte_hash_index(hpte_slot_array, i);
+
+		/* get the vpn */
+		addr = s_addr + (i * (1ul << shift));
+		vpn = hpt_vpn(addr, vsid, ssize);
+		hash = hpt_hash(vpn, shift, ssize);
+		if (hidx & _PTEIDX_SECONDARY)
+			hash = ~hash;
+
+		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+		slot += hidx & _PTEIDX_GROUP_IX;
+		ppc_md.hpte_invalidate(slot, vpn, psize,
+				       MMU_PAGE_16M, ssize, 0);
+	}
+}
+
+
 int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
 		    pmd_t *pmdp, unsigned long trap, int local, int ssize,
 		    unsigned int psize)
@@ -33,7 +84,9 @@ int __hash_page_thp(unsigned long ea, un
 	 * atomically mark the linux large page PMD busy and dirty
 	 */
 	do {
-		old_pmd = pmd_val(*pmdp);
+		pmd_t pmd = ACCESS_ONCE(*pmdp);
+
+		old_pmd = pmd_val(pmd);
 		/* If PMD busy, retry the access */
 		if (unlikely(old_pmd & _PAGE_BUSY))
 			return 0;
@@ -85,6 +138,15 @@ int __hash_page_thp(unsigned long ea, un
 	vpn = hpt_vpn(ea, vsid, ssize);
 	hash = hpt_hash(vpn, shift, ssize);
 	hpte_slot_array = get_hpte_slot_array(pmdp);
+	if (psize == MMU_PAGE_4K) {
+		/*
+		 * invalidate the old hpte entry if we have that mapped via 64K
+		 * base page size. This is because demote_segment won't flush
+		 * hash page table entries.
+		 */
+		if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO))
+			invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize);
+	}
 
 	valid = hpte_valid(hpte_slot_array, index);
 	if (valid) {
@@ -107,11 +169,8 @@ int __hash_page_thp(unsigned long ea, un
 			 * safely update this here.
 			 */
 			valid = 0;
-			new_pmd &= ~_PAGE_HPTEFLAGS;
 			hpte_slot_array[index] = 0;
-		} else
-			/* clear the busy bits and set the hash pte bits */
-			new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
+		}
 	}
 
 	if (!valid) {
@@ -119,11 +178,7 @@ int __hash_page_thp(unsigned long ea, un
 
 		/* insert new entry */
 		pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT;
-repeat:
-		hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
-
-		/* clear the busy bits and set the hash pte bits */
-		new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
+		new_pmd |= _PAGE_HASHPTE;
 
 		/* Add in WIMG bits */
 		rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
@@ -132,6 +187,8 @@ repeat:
 		 * enable the memory coherence always
 		 */
 		rflags |= HPTE_R_M;
+repeat:
+		hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
 
 		/* Insert into the hash table, primary slot */
 		slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
@@ -172,8 +229,17 @@ repeat:
 		mark_hpte_slot_valid(hpte_slot_array, index, slot);
 	}
 	/*
-	 * No need to use ldarx/stdcx here
+	 * Mark the pte with _PAGE_COMBO, if we are trying to hash it with
+	 * base page size 4k.
 	 */
+	if (psize == MMU_PAGE_4K)
+		new_pmd |= _PAGE_COMBO;
+	/*
+	 * The hpte valid is stored in the pgtable whose address is in the
+	 * second half of the PMD. Order this against clearing of the busy bit in
+	 * huge pmd.
+	 */
+	smp_wmb();
 	*pmdp = __pmd(new_pmd & ~_PAGE_BUSY);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/init_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/init_64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/init_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/init_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -175,9 +175,10 @@ static unsigned long __meminit vmemmap_s
 static int __meminit vmemmap_populated(unsigned long start, int page_size)
 {
 	unsigned long end = start + page_size;
+	start = (unsigned long)(pfn_to_page(vmemmap_section_start(start)));
 
 	for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page)))
-		if (pfn_valid(vmemmap_section_start(start)))
+		if (pfn_valid(page_to_pfn((struct page *)start)))
 			return 1;
 
 	return 0;
@@ -212,6 +213,13 @@ static void __meminit vmemmap_create_map
 	for (i = 0; i < page_size; i += PAGE_SIZE)
 		BUG_ON(map_kernel_page(start + i, phys, flags));
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static void vmemmap_remove_mapping(unsigned long start,
+				   unsigned long page_size)
+{
+}
+#endif
 #else /* CONFIG_PPC_BOOK3E */
 static void __meminit vmemmap_create_mapping(unsigned long start,
 					     unsigned long page_size,
@@ -223,17 +231,42 @@ static void __meminit vmemmap_create_map
 					mmu_kernel_ssize);
 	BUG_ON(mapped < 0);
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+extern int htab_remove_mapping(unsigned long vstart, unsigned long vend,
+			int psize, int ssize);
+
+static void vmemmap_remove_mapping(unsigned long start,
+				   unsigned long page_size)
+{
+	int mapped = htab_remove_mapping(start, start + page_size,
+					 mmu_vmemmap_psize,
+					 mmu_kernel_ssize);
+	BUG_ON(mapped < 0);
+}
+#endif
+
 #endif /* CONFIG_PPC_BOOK3E */
 
 struct vmemmap_backing *vmemmap_list;
+static struct vmemmap_backing *next;
+static int num_left;
+static int num_freed;
 
 static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node)
 {
-	static struct vmemmap_backing *next;
-	static int num_left;
+	struct vmemmap_backing *vmem_back;
+	/* get from freed entries first */
+	if (num_freed) {
+		num_freed--;
+		vmem_back = next;
+		next = next->list;
+
+		return vmem_back;
+	}
 
 	/* allocate a page when required and hand out chunks */
-	if (!next || !num_left) {
+	if (!num_left) {
 		next = vmemmap_alloc_block(PAGE_SIZE, node);
 		if (unlikely(!next)) {
 			WARN_ON(1);
@@ -296,10 +329,85 @@ int __meminit vmemmap_populate(unsigned
 	return 0;
 }
 
-void vmemmap_free(unsigned long start, unsigned long end)
+#ifdef CONFIG_MEMORY_HOTPLUG
+static unsigned long vmemmap_list_free(unsigned long start)
 {
+	struct vmemmap_backing *vmem_back, *vmem_back_prev;
+
+	vmem_back_prev = vmem_back = vmemmap_list;
+
+	/* look for it with prev pointer recorded */
+	for (; vmem_back; vmem_back = vmem_back->list) {
+		if (vmem_back->virt_addr == start)
+			break;
+		vmem_back_prev = vmem_back;
+	}
+
+	if (unlikely(!vmem_back)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	/* remove it from vmemmap_list */
+	if (vmem_back == vmemmap_list) /* remove head */
+		vmemmap_list = vmem_back->list;
+	else
+		vmem_back_prev->list = vmem_back->list;
+
+	/* next point to this freed entry */
+	vmem_back->list = next;
+	next = vmem_back;
+	num_freed++;
+
+	return vmem_back->phys;
 }
 
+void __ref vmemmap_free(unsigned long start, unsigned long end)
+{
+	unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
+
+	start = _ALIGN_DOWN(start, page_size);
+
+	pr_debug("vmemmap_free %lx...%lx\n", start, end);
+
+	for (; start < end; start += page_size) {
+		unsigned long addr;
+
+		/*
+		 * the section has already be marked as invalid, so
+		 * vmemmap_populated() true means some other sections still
+		 * in this page, so skip it.
+		 */
+		if (vmemmap_populated(start, page_size))
+			continue;
+
+		addr = vmemmap_list_free(start);
+		if (addr) {
+			struct page *page = pfn_to_page(addr >> PAGE_SHIFT);
+
+			if (PageReserved(page)) {
+				/* allocated from bootmem */
+				if (page_size < PAGE_SIZE) {
+					/*
+					 * this shouldn't happen, but if it is
+					 * the case, leave the memory there
+					 */
+					WARN_ON_ONCE(1);
+				} else {
+					unsigned int nr_pages =
+						1 << get_order(page_size);
+					while (nr_pages--)
+						free_reserved_page(page++);
+				}
+			} else
+				free_pages((unsigned long)(__va(addr)),
+							get_order(page_size));
+
+			vmemmap_remove_mapping(start, page_size);
+		}
+	}
+}
+#endif
 void register_page_bootmem_memmap(unsigned long section_nr,
 				  struct page *start_page, unsigned long size)
 {
@@ -331,16 +439,16 @@ struct page *realmode_pfn_to_page(unsign
 		if (pg_va < vmem_back->virt_addr)
 			continue;
 
-		/* Check that page struct is not split between real pages */
-		if ((pg_va + sizeof(struct page)) >
-				(vmem_back->virt_addr + page_size))
-			return NULL;
-
-		page = (struct page *) (vmem_back->phys + pg_va -
+		/* After vmemmap_list entry free is possible, need check all */
+		if ((pg_va + sizeof(struct page)) <=
+				(vmem_back->virt_addr + page_size)) {
+			page = (struct page *) (vmem_back->phys + pg_va -
 				vmem_back->virt_addr);
-		return page;
+			return page;
+		}
 	}
 
+	/* Probably that page struct is split between real pages */
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/Makefile linux-libre-3.17-rc7-gnu/arch/powerpc/mm/Makefile
--- linux-libre-3.16-gnu/arch/powerpc/mm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -13,9 +13,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH)	+= mmu_cont
 				   tlb_nohash_low.o
 obj-$(CONFIG_PPC_BOOK3E)	+= tlb_low_$(CONFIG_WORD_SIZE)e.o
 hash64-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
-obj-$(CONFIG_PPC_STD_MMU_64)	+= hash_utils_64.o \
-				   slb_low.o slb.o stab.o \
-				   $(hash64-y)
+obj-$(CONFIG_PPC_STD_MMU_64)	+= hash_utils_64.o slb_low.o slb.o $(hash64-y)
 obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o
 obj-$(CONFIG_PPC_STD_MMU)	+= hash_low_$(CONFIG_WORD_SIZE).o \
 				   tlb_hash$(CONFIG_WORD_SIZE).o \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/mem.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/mem.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -128,7 +128,8 @@ int arch_add_memory(int nid, u64 start,
 		return -EINVAL;
 
 	/* this should work for most non-highmem platforms */
-	zone = pgdata->node_zones;
+	zone = pgdata->node_zones +
+		zone_for_memory(nid, start, size, 0);
 
 	return __add_pages(nid, zone, start_pfn, nr_pages);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/mmu_context_hash32.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/mmu_context_hash32.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/mmu_context_hash32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/mmu_context_hash32.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
  * This file contains the routines for handling the MMU on those
  * PowerPC implementations where the MMU substantially follows the
  * architecture specification.  This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * and 8260 implementations but excludes the 8xx and 4xx.
  *  -- paulus
  *
  *  Derived from arch/ppc/mm/init.c:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/numa.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/numa.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/numa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/numa.c	2014-09-28 17:29:07.000000000 -0400
@@ -611,8 +611,8 @@ static int cpu_numa_callback(struct noti
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 		unmap_cpu_from_node(lcpu);
-		break;
 		ret = NOTIFY_OK;
+		break;
 #endif
 	}
 	return ret;
@@ -1049,7 +1049,7 @@ static void __init mark_reserved_regions
 
 void __init do_init_bootmem(void)
 {
-	int nid;
+	int nid, cpu;
 
 	min_low_pfn = 0;
 	max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
@@ -1122,8 +1122,15 @@ void __init do_init_bootmem(void)
 
 	reset_numa_cpu_lookup_table();
 	register_cpu_notifier(&ppc64_numa_nb);
-	cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
-			  (void *)(unsigned long)boot_cpuid);
+	/*
+	 * We need the numa_cpu_lookup_table to be accurate for all CPUs,
+	 * even before we online them, so that we can use cpu_to_{node,mem}
+	 * early in boot, cf. smp_prepare_cpus().
+	 */
+	for_each_possible_cpu(cpu) {
+		cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
+				  (void *)(unsigned long)cpu);
+	}
 }
 
 void __init paging_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/pgtable_32.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/pgtable_32.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/pgtable_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/pgtable_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ unsigned long ioremap_base;
 unsigned long ioremap_bot;
 EXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */
 
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#ifdef CONFIG_6xx
 #define HAVE_BATS	1
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/pgtable_64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/pgtable_64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/pgtable_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/pgtable_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,6 +54,9 @@
 
 #include "mmu_decl.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/thp.h>
+
 /* Some sanity checking */
 #if TASK_SIZE_USER64 > PGTABLE_RANGE
 #error TASK_SIZE_USER64 exceeds pagetable range
@@ -68,7 +71,7 @@
 unsigned long ioremap_bot = IOREMAP_BASE;
 
 #ifdef CONFIG_PPC_MMU_NOHASH
-static void *early_alloc_pgtable(unsigned long size)
+static __ref void *early_alloc_pgtable(unsigned long size)
 {
 	void *pt;
 
@@ -537,8 +540,9 @@ unsigned long pmd_hugepage_update(struct
 	old = pmd_val(*pmdp);
 	*pmdp = __pmd((old & ~clr) | set);
 #endif
+	trace_hugepage_update(addr, old, clr, set);
 	if (old & _PAGE_HASHPTE)
-		hpte_do_hugepage_flush(mm, addr, pmdp);
+		hpte_do_hugepage_flush(mm, addr, pmdp, old);
 	return old;
 }
 
@@ -642,10 +646,11 @@ void pmdp_splitting_flush(struct vm_area
 	 * If we didn't had the splitting flag set, go and flush the
 	 * HPTE entries.
 	 */
+	trace_hugepage_splitting(address, old);
 	if (!(old & _PAGE_SPLITTING)) {
 		/* We need to flush the hpte */
 		if (old & _PAGE_HASHPTE)
-			hpte_do_hugepage_flush(vma->vm_mm, address, pmdp);
+			hpte_do_hugepage_flush(vma->vm_mm, address, pmdp, old);
 	}
 	/*
 	 * This ensures that generic code that rely on IRQ disabling
@@ -709,6 +714,7 @@ void set_pmd_at(struct mm_struct *mm, un
 	assert_spin_locked(&mm->page_table_lock);
 	WARN_ON(!pmd_trans_huge(pmd));
 #endif
+	trace_hugepage_set_pmd(addr, pmd);
 	return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
 }
 
@@ -723,7 +729,7 @@ void pmdp_invalidate(struct vm_area_stru
  * neesd to be flushed.
  */
 void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
-			    pmd_t *pmdp)
+			    pmd_t *pmdp, unsigned long old_pmd)
 {
 	int ssize, i;
 	unsigned long s_addr;
@@ -745,12 +751,29 @@ void hpte_do_hugepage_flush(struct mm_st
 	if (!hpte_slot_array)
 		return;
 
-	/* get the base page size */
+	/* get the base page size,vsid and segment size */
+#ifdef CONFIG_DEBUG_VM
 	psize = get_slice_psize(mm, s_addr);
+	BUG_ON(psize == MMU_PAGE_16M);
+#endif
+	if (old_pmd & _PAGE_COMBO)
+		psize = MMU_PAGE_4K;
+	else
+		psize = MMU_PAGE_64K;
+
+	if (!is_kernel_addr(s_addr)) {
+		ssize = user_segment_size(s_addr);
+		vsid = get_vsid(mm->context.id, s_addr, ssize);
+		WARN_ON(vsid == 0);
+	} else {
+		vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize);
+		ssize = mmu_kernel_ssize;
+	}
 
 	if (ppc_md.hugepage_invalidate)
-		return ppc_md.hugepage_invalidate(mm, hpte_slot_array,
-						  s_addr, psize);
+		return ppc_md.hugepage_invalidate(vsid, s_addr,
+						  hpte_slot_array,
+						  psize, ssize);
 	/*
 	 * No bluk hpte removal support, invalidate each entry
 	 */
@@ -768,15 +791,6 @@ void hpte_do_hugepage_flush(struct mm_st
 
 		/* get the vpn */
 		addr = s_addr + (i * (1ul << shift));
-		if (!is_kernel_addr(addr)) {
-			ssize = user_segment_size(addr);
-			vsid = get_vsid(mm->context.id, addr, ssize);
-			WARN_ON(vsid == 0);
-		} else {
-			vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
-			ssize = mmu_kernel_ssize;
-		}
-
 		vpn = hpt_vpn(addr, vsid, ssize);
 		hash = hpt_hash(vpn, shift, ssize);
 		if (hidx & _PTEIDX_SECONDARY)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/ppc_mmu_32.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/ppc_mmu_32.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/ppc_mmu_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/ppc_mmu_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
  * This file contains the routines for handling the MMU on those
  * PowerPC implementations where the MMU substantially follows the
  * architecture specification.  This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * and 8260 implementations but excludes the 8xx and 4xx.
  *  -- paulus
  *
  *  Derived from arch/ppc/mm/init.c:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/stab.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/stab.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/stab.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/stab.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,286 +0,0 @@
-/*
- * PowerPC64 Segment Translation Support.
- *
- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
- *    Copyright (c) 2001 Dave Engebretsen
- *
- * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the 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/memblock.h>
-
-#include <asm/pgtable.h>
-#include <asm/mmu.h>
-#include <asm/mmu_context.h>
-#include <asm/paca.h>
-#include <asm/cputable.h>
-#include <asm/prom.h>
-
-struct stab_entry {
-	unsigned long esid_data;
-	unsigned long vsid_data;
-};
-
-#define NR_STAB_CACHE_ENTRIES 8
-static DEFINE_PER_CPU(long, stab_cache_ptr);
-static DEFINE_PER_CPU(long [NR_STAB_CACHE_ENTRIES], stab_cache);
-
-/*
- * Create a segment table entry for the given esid/vsid pair.
- */
-static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
-{
-	unsigned long esid_data, vsid_data;
-	unsigned long entry, group, old_esid, castout_entry, i;
-	unsigned int global_entry;
-	struct stab_entry *ste, *castout_ste;
-	unsigned long kernel_segment = (esid << SID_SHIFT) >= PAGE_OFFSET;
-
-	vsid_data = vsid << STE_VSID_SHIFT;
-	esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
-	if (! kernel_segment)
-		esid_data |= STE_ESID_KS;
-
-	/* Search the primary group first. */
-	global_entry = (esid & 0x1f) << 3;
-	ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
-
-	/* Find an empty entry, if one exists. */
-	for (group = 0; group < 2; group++) {
-		for (entry = 0; entry < 8; entry++, ste++) {
-			if (!(ste->esid_data & STE_ESID_V)) {
-				ste->vsid_data = vsid_data;
-				eieio();
-				ste->esid_data = esid_data;
-				return (global_entry | entry);
-			}
-		}
-		/* Now search the secondary group. */
-		global_entry = ((~esid) & 0x1f) << 3;
-		ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
-	}
-
-	/*
-	 * Could not find empty entry, pick one with a round robin selection.
-	 * Search all entries in the two groups.
-	 */
-	castout_entry = get_paca()->stab_rr;
-	for (i = 0; i < 16; i++) {
-		if (castout_entry < 8) {
-			global_entry = (esid & 0x1f) << 3;
-			ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
-			castout_ste = ste + castout_entry;
-		} else {
-			global_entry = ((~esid) & 0x1f) << 3;
-			ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
-			castout_ste = ste + (castout_entry - 8);
-		}
-
-		/* Dont cast out the first kernel segment */
-		if ((castout_ste->esid_data & ESID_MASK) != PAGE_OFFSET)
-			break;
-
-		castout_entry = (castout_entry + 1) & 0xf;
-	}
-
-	get_paca()->stab_rr = (castout_entry + 1) & 0xf;
-
-	/* Modify the old entry to the new value. */
-
-	/* Force previous translations to complete. DRENG */
-	asm volatile("isync" : : : "memory");
-
-	old_esid = castout_ste->esid_data >> SID_SHIFT;
-	castout_ste->esid_data = 0;		/* Invalidate old entry */
-
-	asm volatile("sync" : : : "memory");    /* Order update */
-
-	castout_ste->vsid_data = vsid_data;
-	eieio();				/* Order update */
-	castout_ste->esid_data = esid_data;
-
-	asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
-	/* Ensure completion of slbie */
-	asm volatile("sync" : : : "memory");
-
-	return (global_entry | (castout_entry & 0x7));
-}
-
-/*
- * Allocate a segment table entry for the given ea and mm
- */
-static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
-{
-	unsigned long vsid;
-	unsigned char stab_entry;
-	unsigned long offset;
-
-	/* Kernel or user address? */
-	if (is_kernel_addr(ea)) {
-		vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
-	} else {
-		if ((ea >= TASK_SIZE_USER64) || (! mm))
-			return 1;
-
-		vsid = get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M);
-	}
-
-	stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
-
-	if (!is_kernel_addr(ea)) {
-		offset = __get_cpu_var(stab_cache_ptr);
-		if (offset < NR_STAB_CACHE_ENTRIES)
-			__get_cpu_var(stab_cache[offset++]) = stab_entry;
-		else
-			offset = NR_STAB_CACHE_ENTRIES+1;
-		__get_cpu_var(stab_cache_ptr) = offset;
-
-		/* Order update */
-		asm volatile("sync":::"memory");
-	}
-
-	return 0;
-}
-
-int ste_allocate(unsigned long ea)
-{
-	return __ste_allocate(ea, current->mm);
-}
-
-/*
- * Do the segment table work for a context switch: flush all user
- * entries from the table, then preload some probably useful entries
- * for the new task
- */
-void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
-{
-	struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
-	struct stab_entry *ste;
-	unsigned long offset;
-	unsigned long pc = KSTK_EIP(tsk);
-	unsigned long stack = KSTK_ESP(tsk);
-	unsigned long unmapped_base;
-
-	/* Force previous translations to complete. DRENG */
-	asm volatile("isync" : : : "memory");
-
-	/*
-	 * We need interrupts hard-disabled here, not just soft-disabled,
-	 * so that a PMU interrupt can't occur, which might try to access
-	 * user memory (to get a stack trace) and possible cause an STAB miss
-	 * which would update the stab_cache/stab_cache_ptr per-cpu variables.
-	 */
-	hard_irq_disable();
-
-	offset = __get_cpu_var(stab_cache_ptr);
-	if (offset <= NR_STAB_CACHE_ENTRIES) {
-		int i;
-
-		for (i = 0; i < offset; i++) {
-			ste = stab + __get_cpu_var(stab_cache[i]);
-			ste->esid_data = 0; /* invalidate entry */
-		}
-	} else {
-		unsigned long entry;
-
-		/* Invalidate all entries. */
-		ste = stab;
-
-		/* Never flush the first entry. */
-		ste += 1;
-		for (entry = 1;
-		     entry < (HW_PAGE_SIZE / sizeof(struct stab_entry));
-		     entry++, ste++) {
-			unsigned long ea;
-			ea = ste->esid_data & ESID_MASK;
-			if (!is_kernel_addr(ea)) {
-				ste->esid_data = 0;
-			}
-		}
-	}
-
-	asm volatile("sync; slbia; sync":::"memory");
-
-	__get_cpu_var(stab_cache_ptr) = 0;
-
-	/* Now preload some entries for the new task */
-	if (test_tsk_thread_flag(tsk, TIF_32BIT))
-		unmapped_base = TASK_UNMAPPED_BASE_USER32;
-	else
-		unmapped_base = TASK_UNMAPPED_BASE_USER64;
-
-	__ste_allocate(pc, mm);
-
-	if (GET_ESID(pc) == GET_ESID(stack))
-		return;
-
-	__ste_allocate(stack, mm);
-
-	if ((GET_ESID(pc) == GET_ESID(unmapped_base))
-	    || (GET_ESID(stack) == GET_ESID(unmapped_base)))
-		return;
-
-	__ste_allocate(unmapped_base, mm);
-
-	/* Order update */
-	asm volatile("sync" : : : "memory");
-}
-
-/*
- * Allocate segment tables for secondary CPUs.  These must all go in
- * the first (bolted) segment, so that do_stab_bolted won't get a
- * recursive segment miss on the segment table itself.
- */
-void __init stabs_alloc(void)
-{
-	int cpu;
-
-	if (mmu_has_feature(MMU_FTR_SLB))
-		return;
-
-	for_each_possible_cpu(cpu) {
-		unsigned long newstab;
-
-		if (cpu == 0)
-			continue; /* stab for CPU 0 is statically allocated */
-
-		newstab = memblock_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE,
-					 1<<SID_SHIFT);
-		newstab = (unsigned long)__va(newstab);
-
-		memset((void *)newstab, 0, HW_PAGE_SIZE);
-
-		paca[cpu].stab_addr = newstab;
-		paca[cpu].stab_real = __pa(newstab);
-		printk(KERN_INFO "Segment table for CPU %d at 0x%llx "
-		       "virtual, 0x%llx absolute\n",
-		       cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
-	}
-}
-
-/*
- * Build an entry for the base kernel segment and put it into
- * the segment table or SLB.  All other segment table or SLB
- * entries are faulted in.
- */
-void stab_initialize(unsigned long stab)
-{
-	unsigned long vsid = get_kernel_vsid(PAGE_OFFSET, MMU_SEGSIZE_256M);
-	unsigned long stabreal;
-
-	asm volatile("isync; slbia; isync":::"memory");
-	make_ste(stab, GET_ESID(PAGE_OFFSET), vsid);
-
-	/* Order update */
-	asm volatile("sync":::"memory");
-
-	/* Set ASR */
-	stabreal = get_paca()->stab_real | 0x1ul;
-
-	mtspr(SPRN_ASR, stabreal);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/tlb_hash64.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_hash64.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/tlb_hash64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_hash64.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,8 @@
 #include <asm/tlb.h>
 #include <asm/bug.h>
 
+#include <trace/events/thp.h>
+
 DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 
 /*
@@ -213,10 +215,12 @@ void __flush_hash_table_range(struct mm_
 		if (ptep == NULL)
 			continue;
 		pte = pte_val(*ptep);
+		if (hugepage_shift)
+			trace_hugepage_invalidate(start, pte_val(pte));
 		if (!(pte & _PAGE_HASHPTE))
 			continue;
 		if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte)))
-			hpte_do_hugepage_flush(mm, start, (pmd_t *)pte);
+			hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte);
 		else
 			hpte_need_flush(mm, start, ptep, pte, 0);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/tlb_low_64e.S linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_low_64e.S
--- linux-libre-3.16-gnu/arch/powerpc/mm/tlb_low_64e.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_low_64e.S	2014-09-28 17:29:07.000000000 -0400
@@ -296,9 +296,12 @@ itlb_miss_fault_bolted:
  * r14 = page table base
  * r13 = PACA
  * r11 = tlb_per_core ptr
- * r10 = cpu number
+ * r10 = crap (free to use)
  */
 tlb_miss_common_e6500:
+	crmove	cr2*4+2,cr0*4+2		/* cr2.eq != 0 if kernel address */
+
+BEGIN_FTR_SECTION		/* CPU_FTR_SMT */
 	/*
 	 * Search if we already have an indirect entry for that virtual
 	 * address, and if we do, bail out.
@@ -309,6 +312,7 @@ tlb_miss_common_e6500:
 	lhz	r10,PACAPACAINDEX(r13)
 	cmpdi	r15,0
 	cmpdi	cr1,r15,1	/* set cr1.eq = 0 for non-recursive */
+	addi	r10,r10,1
 	bne	2f
 	stbcx.	r10,0,r11
 	bne	1b
@@ -322,18 +326,62 @@ tlb_miss_common_e6500:
 	b	1b
 	.previous
 
+	/*
+	 * Erratum A-008139 says that we can't use tlbwe to change
+	 * an indirect entry in any way (including replacing or
+	 * invalidating) if the other thread could be in the process
+	 * of a lookup.  The workaround is to invalidate the entry
+	 * with tlbilx before overwriting.
+	 */
+
+	lbz	r15,TCD_ESEL_NEXT(r11)
+	rlwinm	r10,r15,16,0xff0000
+	oris	r10,r10,MAS0_TLBSEL(1)@h
+	mtspr	SPRN_MAS0,r10
+	isync
+	tlbre
+	mfspr	r15,SPRN_MAS1
+	andis.	r15,r15,MAS1_VALID@h
+	beq	5f
+
+BEGIN_FTR_SECTION_NESTED(532)
+	mfspr	r10,SPRN_MAS8
+	rlwinm	r10,r10,0,0x80000fff  /* tgs,tlpid -> sgs,slpid */
+	mtspr	SPRN_MAS5,r10
+END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
+
+	mfspr	r10,SPRN_MAS1
+	rlwinm	r15,r10,0,0x3fff0000  /* tid -> spid */
+	rlwimi	r15,r10,20,0x00000003 /* ind,ts -> sind,sas */
+	mfspr	r10,SPRN_MAS6
+	mtspr	SPRN_MAS6,r15
+
 	mfspr	r15,SPRN_MAS2
+	isync
+	tlbilxva 0,r15
+	isync
+
+	mtspr	SPRN_MAS6,r10
+
+5:
+BEGIN_FTR_SECTION_NESTED(532)
+	li	r10,0
+	mtspr	SPRN_MAS8,r10
+	mtspr	SPRN_MAS5,r10
+END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
 
 	tlbsx	0,r16
 	mfspr	r10,SPRN_MAS1
-	andis.	r10,r10,MAS1_VALID@h
+	andis.	r15,r10,MAS1_VALID@h
 	bne	tlb_miss_done_e6500
-
-	/* Undo MAS-damage from the tlbsx */
+FTR_SECTION_ELSE
 	mfspr	r10,SPRN_MAS1
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT)
+
 	oris	r10,r10,MAS1_VALID@h
-	mtspr	SPRN_MAS1,r10
-	mtspr	SPRN_MAS2,r15
+	beq	cr2,4f
+	rlwinm	r10,r10,0,16,1		/* Clear TID */
+4:	mtspr	SPRN_MAS1,r10
 
 	/* Now, we need to walk the page tables. First check if we are in
 	 * range.
@@ -394,11 +442,13 @@ tlb_miss_common_e6500:
 
 tlb_miss_done_e6500:
 	.macro	tlb_unlock_e6500
+BEGIN_FTR_SECTION
 	beq	cr1,1f		/* no unlock if lock was recursively grabbed */
 	li	r15,0
 	isync
 	stb	r15,0(r11)
 1:
+END_FTR_SECTION_IFSET(CPU_FTR_SMT)
 	.endm
 
 	tlb_unlock_e6500
@@ -407,12 +457,9 @@ tlb_miss_done_e6500:
 	rfi
 
 tlb_miss_kernel_e6500:
-	mfspr	r10,SPRN_MAS1
 	ld	r14,PACA_KERNELPGD(r13)
-	cmpldi	cr0,r15,8		/* Check for vmalloc region */
-	rlwinm	r10,r10,0,16,1		/* Clear TID */
-	mtspr	SPRN_MAS1,r10
-	beq+	tlb_miss_common_e6500
+	cmpldi	cr1,r15,8		/* Check for vmalloc region */
+	beq+	cr1,tlb_miss_common_e6500
 
 tlb_miss_fault_e6500:
 	tlb_unlock_e6500
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/mm/tlb_nohash.c linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_nohash.c
--- linux-libre-3.16-gnu/arch/powerpc/mm/tlb_nohash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/mm/tlb_nohash.c	2014-09-28 17:29:07.000000000 -0400
@@ -581,42 +581,10 @@ static void setup_mmu_htw(void)
 /*
  * Early initialization of the MMU TLB code
  */
-static void __early_init_mmu(int boot_cpu)
+static void early_init_this_mmu(void)
 {
 	unsigned int mas4;
 
-	/* XXX This will have to be decided at runtime, but right
-	 * now our boot and TLB miss code hard wires it. Ideally
-	 * we should find out a suitable page size and patch the
-	 * TLB miss code (either that or use the PACA to store
-	 * the value we want)
-	 */
-	mmu_linear_psize = MMU_PAGE_1G;
-
-	/* XXX This should be decided at runtime based on supported
-	 * page sizes in the TLB, but for now let's assume 16M is
-	 * always there and a good fit (which it probably is)
-	 *
-	 * Freescale booke only supports 4K pages in TLB0, so use that.
-	 */
-	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
-		mmu_vmemmap_psize = MMU_PAGE_4K;
-	else
-		mmu_vmemmap_psize = MMU_PAGE_16M;
-
-	/* XXX This code only checks for TLB 0 capabilities and doesn't
-	 *     check what page size combos are supported by the HW. It
-	 *     also doesn't handle the case where a separate array holds
-	 *     the IND entries from the array loaded by the PT.
-	 */
-	if (boot_cpu) {
-		/* Look for supported page sizes */
-		setup_page_sizes();
-
-		/* Look for HW tablewalk support */
-		setup_mmu_htw();
-	}
-
 	/* Set MAS4 based on page table setting */
 
 	mas4 = 0x4 << MAS4_WIMGED_SHIFT;
@@ -650,11 +618,6 @@ static void __early_init_mmu(int boot_cp
 	}
 	mtspr(SPRN_MAS4, mas4);
 
-	/* Set the global containing the top of the linear mapping
-	 * for use by the TLB miss code
-	 */
-	linear_map_top = memblock_end_of_DRAM();
-
 #ifdef CONFIG_PPC_FSL_BOOK3E
 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
 		unsigned int num_cams;
@@ -662,10 +625,49 @@ static void __early_init_mmu(int boot_cp
 		/* use a quarter of the TLBCAM for bolted linear map */
 		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
 		linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
+	}
+#endif
 
-		/* limit memory so we dont have linear faults */
-		memblock_enforce_memory_limit(linear_map_top);
+	/* A sync won't hurt us after mucking around with
+	 * the MMU configuration
+	 */
+	mb();
+}
 
+static void __init early_init_mmu_global(void)
+{
+	/* XXX This will have to be decided at runtime, but right
+	 * now our boot and TLB miss code hard wires it. Ideally
+	 * we should find out a suitable page size and patch the
+	 * TLB miss code (either that or use the PACA to store
+	 * the value we want)
+	 */
+	mmu_linear_psize = MMU_PAGE_1G;
+
+	/* XXX This should be decided at runtime based on supported
+	 * page sizes in the TLB, but for now let's assume 16M is
+	 * always there and a good fit (which it probably is)
+	 *
+	 * Freescale booke only supports 4K pages in TLB0, so use that.
+	 */
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
+		mmu_vmemmap_psize = MMU_PAGE_4K;
+	else
+		mmu_vmemmap_psize = MMU_PAGE_16M;
+
+	/* XXX This code only checks for TLB 0 capabilities and doesn't
+	 *     check what page size combos are supported by the HW. It
+	 *     also doesn't handle the case where a separate array holds
+	 *     the IND entries from the array loaded by the PT.
+	 */
+	/* Look for supported page sizes */
+	setup_page_sizes();
+
+	/* Look for HW tablewalk support */
+	setup_mmu_htw();
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
 		if (book3e_htw_mode == PPC_HTW_NONE) {
 			extlb_level_exc = EX_TLB_SIZE;
 			patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
@@ -675,22 +677,41 @@ static void __early_init_mmu(int boot_cp
 	}
 #endif
 
-	/* A sync won't hurt us after mucking around with
-	 * the MMU configuration
+	/* Set the global containing the top of the linear mapping
+	 * for use by the TLB miss code
 	 */
-	mb();
+	linear_map_top = memblock_end_of_DRAM();
+}
+
+static void __init early_mmu_set_memory_limit(void)
+{
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+		/*
+		 * Limit memory so we dont have linear faults.
+		 * Unlike memblock_set_current_limit, which limits
+		 * memory available during early boot, this permanently
+		 * reduces the memory available to Linux.  We need to
+		 * do this because highmem is not supported on 64-bit.
+		 */
+		memblock_enforce_memory_limit(linear_map_top);
+	}
+#endif
 
 	memblock_set_current_limit(linear_map_top);
 }
 
+/* boot cpu only */
 void __init early_init_mmu(void)
 {
-	__early_init_mmu(1);
+	early_init_mmu_global();
+	early_init_this_mmu();
+	early_mmu_set_memory_limit();
 }
 
 void early_init_mmu_secondary(void)
 {
-	__early_init_mmu(0);
+	early_init_this_mmu();
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/net/bpf_jit_comp.c linux-libre-3.17-rc7-gnu/arch/powerpc/net/bpf_jit_comp.c
--- linux-libre-3.16-gnu/arch/powerpc/net/bpf_jit_comp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/net/bpf_jit_comp.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@ static inline void bpf_flush_icache(void
 	flush_icache_range((unsigned long)start, (unsigned long)end);
 }
 
-static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image,
 				   struct codegen_context *ctx)
 {
 	int i;
@@ -121,7 +121,7 @@ static void bpf_jit_build_epilogue(u32 *
 	((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
 
 /* Assemble the body code between the prologue & epilogue. */
-static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 			      struct codegen_context *ctx,
 			      unsigned int *addrs)
 {
@@ -569,7 +569,7 @@ static int bpf_jit_build_body(struct sk_
 	return 0;
 }
 
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
 {
 	unsigned int proglen;
 	unsigned int alloclen;
@@ -693,7 +693,7 @@ out:
 	return;
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
 		module_free(NULL, fp->bpf_func);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/oprofile/common.c linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/common.c
--- linux-libre-3.16-gnu/arch/powerpc/oprofile/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -205,9 +205,6 @@ int __init oprofile_arch_init(struct opr
 			ops->sync_stop = model->sync_stop;
 			break;
 #endif
-		case PPC_OPROFILE_RS64:
-			model = &op_model_rs64;
-			break;
 		case PPC_OPROFILE_POWER4:
 			model = &op_model_power4;
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/oprofile/Makefile linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/Makefile
--- linux-libre-3.16-gnu/arch/powerpc/oprofile/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,6 @@ oprofile-y := $(DRIVER_OBJS) common.o ba
 oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \
 		cell/spu_profiler.o cell/vma_map.o \
 		cell/spu_task_sync.o
-oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
+oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_power4.o op_model_pa6t.o
 oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o
 oprofile-$(CONFIG_6xx) += op_model_7450.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/oprofile/op_model_rs64.c linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/op_model_rs64.c
--- linux-libre-3.16-gnu/arch/powerpc/oprofile/op_model_rs64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/oprofile/op_model_rs64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/oprofile.h>
-#include <linux/smp.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/cputable.h>
-#include <asm/oprofile_impl.h>
-
-#define dbg(args...)
-
-static void ctrl_write(unsigned int i, unsigned int val)
-{
-	unsigned int tmp = 0;
-	unsigned long shift = 0, mask = 0;
-
-	dbg("ctrl_write %d %x\n", i, val);
-
-	switch(i) {
-	case 0:
-		tmp = mfspr(SPRN_MMCR0);
-		shift = 6;
-		mask = 0x7F;
-		break;
-	case 1:
-		tmp = mfspr(SPRN_MMCR0);
-		shift = 0;
-		mask = 0x3F;
-		break;
-	case 2:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 4;
-		mask = 0x1F;
-		break;
-	case 3:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 9;
-		mask = 0x1F;
-		break;
-	case 4:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 14;
-		mask = 0x1F;
-		break;
-	case 5:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 19;
-		mask = 0x1F;
-		break;
-	case 6:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 24;
-		mask = 0x1F;
-		break;
-	case 7:
-		tmp = mfspr(SPRN_MMCR1);
-		shift = 31 - 28;
-		mask = 0xF;
-		break;
-	}
-
-	tmp = tmp & ~(mask << shift);
-	tmp |= val << shift;
-
-	switch(i) {
-		case 0:
-		case 1:
-			mtspr(SPRN_MMCR0, tmp);
-			break;
-		default:
-			mtspr(SPRN_MMCR1, tmp);
-	}
-
-	dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0),
-	       mfspr(SPRN_MMCR1));
-}
-
-static unsigned long reset_value[OP_MAX_COUNTER];
-
-static int num_counters;
-
-static int rs64_reg_setup(struct op_counter_config *ctr,
-			   struct op_system_config *sys,
-			   int num_ctrs)
-{
-	int i;
-
-	num_counters = num_ctrs;
-
-	for (i = 0; i < num_counters; ++i)
-		reset_value[i] = 0x80000000UL - ctr[i].count;
-
-	/* XXX setup user and kernel profiling */
-	return 0;
-}
-
-static int rs64_cpu_setup(struct op_counter_config *ctr)
-{
-	unsigned int mmcr0;
-
-	/* reset MMCR0 and set the freeze bit */
-	mmcr0 = MMCR0_FC;
-	mtspr(SPRN_MMCR0, mmcr0);
-
-	/* reset MMCR1, MMCRA */
-	mtspr(SPRN_MMCR1, 0);
-
-	if (cpu_has_feature(CPU_FTR_MMCRA))
-		mtspr(SPRN_MMCRA, 0);
-
-	mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
-	/* Only applies to POWER3, but should be safe on RS64 */
-	mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
-	mtspr(SPRN_MMCR0, mmcr0);
-
-	dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
-	    mfspr(SPRN_MMCR0));
-	dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
-	    mfspr(SPRN_MMCR1));
-
-	return 0;
-}
-
-static int rs64_start(struct op_counter_config *ctr)
-{
-	int i;
-	unsigned int mmcr0;
-
-	/* set the PMM bit (see comment below) */
-	mtmsrd(mfmsr() | MSR_PMM);
-
-	for (i = 0; i < num_counters; ++i) {
-		if (ctr[i].enabled) {
-			classic_ctr_write(i, reset_value[i]);
-			ctrl_write(i, ctr[i].event);
-		} else {
-			classic_ctr_write(i, 0);
-		}
-	}
-
-	mmcr0 = mfspr(SPRN_MMCR0);
-
-	/*
-	 * now clear the freeze bit, counting will not start until we
-	 * rfid from this excetion, because only at that point will
-	 * the PMM bit be cleared
-	 */
-	mmcr0 &= ~MMCR0_FC;
-	mtspr(SPRN_MMCR0, mmcr0);
-
-	dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
-	return 0;
-}
-
-static void rs64_stop(void)
-{
-	unsigned int mmcr0;
-
-	/* freeze counters */
-	mmcr0 = mfspr(SPRN_MMCR0);
-	mmcr0 |= MMCR0_FC;
-	mtspr(SPRN_MMCR0, mmcr0);
-
-	dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
-
-	mb();
-}
-
-static void rs64_handle_interrupt(struct pt_regs *regs,
-				  struct op_counter_config *ctr)
-{
-	unsigned int mmcr0;
-	int is_kernel;
-	int val;
-	int i;
-	unsigned long pc = mfspr(SPRN_SIAR);
-
-	is_kernel = is_kernel_addr(pc);
-
-	/* set the PMM bit (see comment below) */
-	mtmsrd(mfmsr() | MSR_PMM);
-
-	for (i = 0; i < num_counters; ++i) {
-		val = classic_ctr_read(i);
-		if (val < 0) {
-			if (ctr[i].enabled) {
-				oprofile_add_ext_sample(pc, regs, i, is_kernel);
-				classic_ctr_write(i, reset_value[i]);
-			} else {
-				classic_ctr_write(i, 0);
-			}
-		}
-	}
-
-	mmcr0 = mfspr(SPRN_MMCR0);
-
-	/* reset the perfmon trigger */
-	mmcr0 |= MMCR0_PMXE;
-
-	/*
-	 * now clear the freeze bit, counting will not start until we
-	 * rfid from this exception, because only at that point will
-	 * the PMM bit be cleared
-	 */
-	mmcr0 &= ~MMCR0_FC;
-	mtspr(SPRN_MMCR0, mmcr0);
-}
-
-struct op_powerpc_model op_model_rs64 = {
-	.reg_setup		= rs64_reg_setup,
-	.cpu_setup		= rs64_cpu_setup,
-	.start			= rs64_start,
-	.stop			= rs64_stop,
-	.handle_interrupt	= rs64_handle_interrupt,
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/callchain.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/callchain.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/callchain.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/callchain.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@ static int valid_next_sp(unsigned long s
 		return 0;		/* must be 16-byte aligned */
 	if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
 		return 0;
-	if (sp >= prev_sp + STACK_FRAME_OVERHEAD)
+	if (sp >= prev_sp + STACK_FRAME_MIN_SIZE)
 		return 1;
 	/*
 	 * sp could decrease when we jump off an interrupt stack
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/core-book3s.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/core-book3s.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/core-book3s.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/core-book3s.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,12 @@ struct cpu_hw_events {
 	struct perf_event *event[MAX_HWEVENTS];
 	u64 events[MAX_HWEVENTS];
 	unsigned int flags[MAX_HWEVENTS];
-	unsigned long mmcr[3];
+	/*
+	 * The order of the MMCR array is:
+	 *  - 64-bit, MMCR0, MMCR1, MMCRA, MMCR2
+	 *  - 32-bit, MMCR0, MMCR1, MMCR2
+	 */
+	unsigned long mmcr[4];
 	struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS];
 	u8  limited_hwidx[MAX_LIMITED_HWCOUNTERS];
 	u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES];
@@ -112,9 +117,9 @@ static bool is_ebb_event(struct perf_eve
 static int ebb_event_check(struct perf_event *event) { return 0; }
 static void ebb_event_add(struct perf_event *event) { }
 static void ebb_switch_out(unsigned long mmcr0) { }
-static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
+static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
 {
-	return mmcr0;
+	return cpuhw->mmcr[0];
 }
 
 static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
@@ -542,8 +547,10 @@ static void ebb_switch_out(unsigned long
 	current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK;
 }
 
-static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
+static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
 {
+	unsigned long mmcr0 = cpuhw->mmcr[0];
+
 	if (!ebb)
 		goto out;
 
@@ -568,7 +575,15 @@ static unsigned long ebb_switch_in(bool
 	mtspr(SPRN_SIAR, current->thread.siar);
 	mtspr(SPRN_SIER, current->thread.sier);
 	mtspr(SPRN_SDAR, current->thread.sdar);
-	mtspr(SPRN_MMCR2, current->thread.mmcr2);
+
+	/*
+	 * Merge the kernel & user values of MMCR2. The semantics we implement
+	 * are that the user MMCR2 can set bits, ie. cause counters to freeze,
+	 * but not clear bits. If a task wants to be able to clear bits, ie.
+	 * unfreeze counters, it should not set exclude_xxx in its events and
+	 * instead manage the MMCR2 entirely by itself.
+	 */
+	mtspr(SPRN_MMCR2, cpuhw->mmcr[3] | current->thread.mmcr2);
 out:
 	return mmcr0;
 }
@@ -915,6 +930,14 @@ static int check_excludes(struct perf_ev
 	int i, n, first;
 	struct perf_event *event;
 
+	/*
+	 * If the PMU we're on supports per event exclude settings then we
+	 * don't need to do any of this logic. NB. This assumes no PMU has both
+	 * per event exclude and limited PMCs.
+	 */
+	if (ppmu->flags & PPMU_ARCH_207S)
+		return 0;
+
 	n = n_prev + n_new;
 	if (n <= 1)
 		return 0;
@@ -1219,28 +1242,31 @@ static void power_pmu_enable(struct pmu
 	}
 
 	/*
-	 * Compute MMCR* values for the new set of events
+	 * Clear all MMCR settings and recompute them for the new set of events.
 	 */
+	memset(cpuhw->mmcr, 0, sizeof(cpuhw->mmcr));
+
 	if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index,
-			       cpuhw->mmcr)) {
+			       cpuhw->mmcr, cpuhw->event)) {
 		/* shouldn't ever get here */
 		printk(KERN_ERR "oops compute_mmcr failed\n");
 		goto out;
 	}
 
-	/*
-	 * Add in MMCR0 freeze bits corresponding to the
-	 * attr.exclude_* bits for the first event.
-	 * We have already checked that all events have the
-	 * same values for these bits as the first event.
-	 */
-	event = cpuhw->event[0];
-	if (event->attr.exclude_user)
-		cpuhw->mmcr[0] |= MMCR0_FCP;
-	if (event->attr.exclude_kernel)
-		cpuhw->mmcr[0] |= freeze_events_kernel;
-	if (event->attr.exclude_hv)
-		cpuhw->mmcr[0] |= MMCR0_FCHV;
+	if (!(ppmu->flags & PPMU_ARCH_207S)) {
+		/*
+		 * Add in MMCR0 freeze bits corresponding to the attr.exclude_*
+		 * bits for the first event. We have already checked that all
+		 * events have the same value for these bits as the first event.
+		 */
+		event = cpuhw->event[0];
+		if (event->attr.exclude_user)
+			cpuhw->mmcr[0] |= MMCR0_FCP;
+		if (event->attr.exclude_kernel)
+			cpuhw->mmcr[0] |= freeze_events_kernel;
+		if (event->attr.exclude_hv)
+			cpuhw->mmcr[0] |= MMCR0_FCHV;
+	}
 
 	/*
 	 * Write the new configuration to MMCR* with the freeze
@@ -1252,6 +1278,8 @@ static void power_pmu_enable(struct pmu
 	mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
 	mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
 				| MMCR0_FC);
+	if (ppmu->flags & PPMU_ARCH_207S)
+		mtspr(SPRN_MMCR2, cpuhw->mmcr[3]);
 
 	/*
 	 * Read off any pre-existing events that need to move
@@ -1307,10 +1335,7 @@ static void power_pmu_enable(struct pmu
  out_enable:
 	pmao_restore_workaround(ebb);
 
-	if (ppmu->flags & PPMU_ARCH_207S)
-		mtspr(SPRN_MMCR2, 0);
-
-	mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]);
+	mmcr0 = ebb_switch_in(ebb, cpuhw);
 
 	mb();
 	if (cpuhw->bhrb_users)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/hv-24x7.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/hv-24x7.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/hv-24x7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/hv-24x7.c	2014-09-28 17:29:07.000000000 -0400
@@ -223,7 +223,7 @@ e_free:
 		pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
 		       " rc=%ld\n",
 		       catalog_version_num, page_offset, hret);
-	kfree(page);
+	kmem_cache_free(hv_page_cache, page);
 
 	pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n",
 			offset, page_offset, count, page_count, catalog_len,
@@ -387,8 +387,7 @@ static int h_24x7_event_init(struct perf
 	    event->attr.exclude_hv     ||
 	    event->attr.exclude_idle   ||
 	    event->attr.exclude_host   ||
-	    event->attr.exclude_guest  ||
-	    is_sampling_event(event)) /* no sampling */
+	    event->attr.exclude_guest)
 		return -EINVAL;
 
 	/* no branch sampling */
@@ -513,6 +512,9 @@ static int hv_24x7_init(void)
 	if (!hv_page_cache)
 		return -ENOMEM;
 
+	/* sampling not supported */
+	h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
 	if (r)
 		return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/hv-gpci.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/hv-gpci.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/hv-gpci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/hv-gpci.c	2014-09-28 17:29:07.000000000 -0400
@@ -210,8 +210,7 @@ static int h_gpci_event_init(struct perf
 	    event->attr.exclude_hv     ||
 	    event->attr.exclude_idle   ||
 	    event->attr.exclude_host   ||
-	    event->attr.exclude_guest  ||
-	    is_sampling_event(event)) /* no sampling */
+	    event->attr.exclude_guest)
 		return -EINVAL;
 
 	/* no branch sampling */
@@ -284,6 +283,9 @@ static int hv_gpci_init(void)
 		return -ENODEV;
 	}
 
+	/* sampling not supported */
+	h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1);
 	if (r)
 		return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/mpc7450-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/mpc7450-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/mpc7450-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/mpc7450-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -260,8 +260,9 @@ static const u32 pmcsel_mask[N_COUNTER]
 /*
  * Compute MMCR0/1/2 values for a set of events.
  */
-static int mpc7450_compute_mmcr(u64 event[], int n_ev,
-				unsigned int hwc[], unsigned long mmcr[])
+static int mpc7450_compute_mmcr(u64 event[], int n_ev, unsigned int hwc[],
+				unsigned long mmcr[],
+				struct perf_event *pevents[])
 {
 	u8 event_index[N_CLASSES][N_COUNTER];
 	int n_classevent[N_CLASSES];
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power4-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power4-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power4-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power4-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -356,7 +356,7 @@ static int p4_get_alternatives(u64 event
 }
 
 static int p4_compute_mmcr(u64 event[], int n_ev,
-			   unsigned int hwc[], unsigned long mmcr[])
+			   unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
 	unsigned int pmc, unit, byte, psel, lower;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power5-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power5-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power5-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power5-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -383,7 +383,7 @@ static int power5_marked_instr_event(u64
 }
 
 static int power5_compute_mmcr(u64 event[], int n_ev,
-			       unsigned int hwc[], unsigned long mmcr[])
+			       unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr1 = 0;
 	unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power5+-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power5+-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power5+-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power5+-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -452,7 +452,7 @@ static int power5p_marked_instr_event(u6
 }
 
 static int power5p_compute_mmcr(u64 event[], int n_ev,
-				unsigned int hwc[], unsigned long mmcr[])
+				unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr1 = 0;
 	unsigned long mmcra = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power6-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power6-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power6-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power6-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -175,7 +175,7 @@ static int power6_marked_instr_event(u64
  * Assign PMC numbers and compute MMCR1 value for a set of events
  */
 static int p6_compute_mmcr(u64 event[], int n_ev,
-			   unsigned int hwc[], unsigned long mmcr[])
+			   unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr1 = 0;
 	unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power7-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power7-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power7-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power7-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -245,7 +245,7 @@ static int power7_marked_instr_event(u64
 }
 
 static int power7_compute_mmcr(u64 event[], int n_ev,
-			       unsigned int hwc[], unsigned long mmcr[])
+			       unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr1 = 0;
 	unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/power8-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power8-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/power8-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/power8-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
 #include <asm/firmware.h>
+#include <asm/cputable.h>
 
 
 /*
@@ -266,6 +267,11 @@
 #define MMCRA_SDAR_MODE_TLB		(1ull << 42)
 #define MMCRA_IFM_SHIFT			30
 
+/* Bits in MMCR2 for POWER8 */
+#define MMCR2_FCS(pmc)			(1ull << (63 - (((pmc) - 1) * 9)))
+#define MMCR2_FCP(pmc)			(1ull << (62 - (((pmc) - 1) * 9)))
+#define MMCR2_FCH(pmc)			(1ull << (57 - (((pmc) - 1) * 9)))
+
 
 static inline bool event_is_fab_match(u64 event)
 {
@@ -393,9 +399,10 @@ static int power8_get_constraint(u64 eve
 }
 
 static int power8_compute_mmcr(u64 event[], int n_ev,
-			       unsigned int hwc[], unsigned long mmcr[])
+			       unsigned int hwc[], unsigned long mmcr[],
+			       struct perf_event *pevents[])
 {
-	unsigned long mmcra, mmcr1, unit, combine, psel, cache, val;
+	unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val;
 	unsigned int pmc, pmc_inuse;
 	int i;
 
@@ -410,7 +417,7 @@ static int power8_compute_mmcr(u64 event
 
 	/* In continous sampling mode, update SDAR on TLB miss */
 	mmcra = MMCRA_SDAR_MODE_TLB;
-	mmcr1 = 0;
+	mmcr1 = mmcr2 = 0;
 
 	/* Second pass: assign PMCs, set all MMCR1 fields */
 	for (i = 0; i < n_ev; ++i) {
@@ -472,6 +479,19 @@ static int power8_compute_mmcr(u64 event
 			mmcra |= val << MMCRA_IFM_SHIFT;
 		}
 
+		if (pevents[i]->attr.exclude_user)
+			mmcr2 |= MMCR2_FCP(pmc);
+
+		if (pevents[i]->attr.exclude_hv)
+			mmcr2 |= MMCR2_FCH(pmc);
+
+		if (pevents[i]->attr.exclude_kernel) {
+			if (cpu_has_feature(CPU_FTR_HVMODE))
+				mmcr2 |= MMCR2_FCH(pmc);
+			else
+				mmcr2 |= MMCR2_FCS(pmc);
+		}
+
 		hwc[i] = pmc - 1;
 	}
 
@@ -491,6 +511,7 @@ static int power8_compute_mmcr(u64 event
 
 	mmcr[1] = mmcr1;
 	mmcr[2] = mmcra;
+	mmcr[3] = mmcr2;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/perf/ppc970-pmu.c linux-libre-3.17-rc7-gnu/arch/powerpc/perf/ppc970-pmu.c
--- linux-libre-3.16-gnu/arch/powerpc/perf/ppc970-pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/perf/ppc970-pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -257,7 +257,7 @@ static int p970_get_alternatives(u64 eve
 }
 
 static int p970_compute_mmcr(u64 event[], int n_ev,
-			     unsigned int hwc[], unsigned long mmcr[])
+			     unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 {
 	unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
 	unsigned int pmc, unit, byte, psel;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/44x/warp.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/44x/warp.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/44x/warp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/44x/warp.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <asm/time.h>
 #include <asm/uic.h>
 #include <asm/ppc4xx.h>
+#include <asm/dma.h>
 
 
 static __initdata struct of_device_id warp_of_bus[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/52xx/efika.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/52xx/efika.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/52xx/efika.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/52xx/efika.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@
 #include <generated/utsrelease.h>
 #include <linux/pci.h>
 #include <linux/of.h>
+#include <asm/dma.h>
 #include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/corenet_generic.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/corenet_generic.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/corenet_generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/corenet_generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,7 +119,11 @@ static const char * const boards[] __ini
 	"fsl,P4080DS",
 	"fsl,P5020DS",
 	"fsl,P5040DS",
+	"fsl,T2080QDS",
+	"fsl,T2080RDB",
+	"fsl,T2081QDS",
 	"fsl,T4240QDS",
+	"fsl,T4240RDB",
 	"fsl,B4860QDS",
 	"fsl,B4420QDS",
 	"fsl,B4220QDS",
@@ -129,28 +133,14 @@ static const char * const boards[] __ini
 	NULL
 };
 
-static const char * const hv_boards[] __initconst = {
-	"fsl,P2041RDB-hv",
-	"fsl,P3041DS-hv",
-	"fsl,OCA4080-hv",
-	"fsl,P4080DS-hv",
-	"fsl,P5020DS-hv",
-	"fsl,P5040DS-hv",
-	"fsl,T4240QDS-hv",
-	"fsl,B4860QDS-hv",
-	"fsl,B4420QDS-hv",
-	"fsl,B4220QDS-hv",
-	"fsl,T1040QDS-hv",
-	"fsl,T1042QDS-hv",
-	NULL
-};
-
 /*
  * Called very early, device-tree isn't unflattened
  */
 static int __init corenet_generic_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
+	char hv_compat[24];
+	int i;
 #ifdef CONFIG_SMP
 	extern struct smp_ops_t smp_85xx_ops;
 #endif
@@ -159,21 +149,26 @@ static int __init corenet_generic_probe(
 		return 1;
 
 	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_match(root, hv_boards)) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
+	for (i = 0; boards[i]; i++) {
+		snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
+		if (of_flat_dt_is_compatible(root, hv_compat)) {
+			ppc_md.init_IRQ = ehv_pic_init;
+
+			ppc_md.get_irq = ehv_pic_get_irq;
+			ppc_md.restart = fsl_hv_restart;
+			ppc_md.power_off = fsl_hv_halt;
+			ppc_md.halt = fsl_hv_halt;
 #ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
+			/*
+			 * Disable the timebase sync operations because we
+			 * can't write to the timebase registers under the
+			 * hypervisor.
+			 */
+			smp_85xx_ops.give_timebase = NULL;
+			smp_85xx_ops.take_timebase = NULL;
 #endif
-		return 1;
+			return 1;
+		}
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/Kconfig linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/Kconfig
--- linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -274,7 +274,7 @@ config CORENET_GENERIC
 	  For 32bit kernel, the following boards are supported:
 	    P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080
 	  For 64bit kernel, the following boards are supported:
-	    T4240 QDS and B4 QDS
+	    T208x QDS/RDB, T4240 QDS/RDB and B4 QDS
 	  The following boards are supported for both 32bit and 64bit kernel:
 	    P5020 DS, P5040 DS and T104xQDS
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/smp.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/85xx/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/85xx/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/dbell.h>
 #include <asm/fsl_guts.h>
 #include <asm/code-patching.h>
+#include <asm/cputhreads.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
@@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l
 	return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
 }
 
+#ifdef CONFIG_PPC64
+static void wake_hw_thread(void *info)
+{
+	void fsl_secondary_thread_init(void);
+	unsigned long imsr1, inia1;
+	int nr = *(const int *)info;
+
+	imsr1 = MSR_KERNEL;
+	inia1 = *(unsigned long *)fsl_secondary_thread_init;
+
+	mttmr(TMRN_IMSR1, imsr1);
+	mttmr(TMRN_INIA1, inia1);
+	mtspr(SPRN_TENS, TEN_THREAD(1));
+
+	smp_generic_kick_cpu(nr);
+}
+#endif
+
 static int smp_85xx_kick_cpu(int nr)
 {
 	unsigned long flags;
@@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr)
 
 	pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
+#ifdef CONFIG_PPC64
+	/* Threads don't use the spin table */
+	if (cpu_thread_in_core(nr) != 0) {
+		int primary = cpu_first_thread_sibling(nr);
+
+		if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
+			return -ENOENT;
+
+		if (cpu_thread_in_core(nr) != 1) {
+			pr_err("%s: cpu %d: invalid hw thread %d\n",
+			       __func__, nr, cpu_thread_in_core(nr));
+			return -ENOENT;
+		}
+
+		if (!cpu_online(primary)) {
+			pr_err("%s: cpu %d: primary %d not online\n",
+			       __func__, nr, primary);
+			return -ENOENT;
+		}
+
+		smp_call_function_single(primary, wake_hw_thread, &nr, 0);
+		return 0;
+	}
+#endif
+
 	np = of_get_cpu_node(nr, NULL);
 	cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/fsl_devices.h>
 
 #include <asm/io.h>
-#include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/prom.h>
 #include <asm/fs_pd.h>
@@ -28,8 +27,6 @@
 
 #include "mpc8xx.h"
 
-struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
-
 extern int cpm_pic_init(void);
 extern int cpm_get_irq(void);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/mpc885ads_setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/mpc885ads_setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/mpc885ads_setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/mpc885ads_setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,6 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/time.h>
-#include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/cpm1.h>
 #include <asm/fs_pd.h>
@@ -46,61 +45,6 @@
 
 static u32 __iomem *bcsr, *bcsr5;
 
-#ifdef CONFIG_PCMCIA_M8XX
-static void pcmcia_hw_setup(int slot, int enable)
-{
-	if (enable)
-		clrbits32(&bcsr[1], BCSR1_PCCEN);
-	else
-		setbits32(&bcsr[1], BCSR1_PCCEN);
-}
-
-static int pcmcia_set_voltage(int slot, int vcc, int vpp)
-{
-	u32 reg = 0;
-
-	switch (vcc) {
-	case 0:
-		break;
-	case 33:
-		reg |= BCSR1_PCCVCC0;
-		break;
-	case 50:
-		reg |= BCSR1_PCCVCC1;
-		break;
-	default:
-		return 1;
-	}
-
-	switch (vpp) {
-	case 0:
-		break;
-	case 33:
-	case 50:
-		if (vcc == vpp)
-			reg |= BCSR1_PCCVPP1;
-		else
-			return 1;
-		break;
-	case 120:
-		if ((vcc == 33) || (vcc == 50))
-			reg |= BCSR1_PCCVPP0;
-		else
-			return 1;
-	default:
-		return 1;
-	}
-
-	/* first, turn off all power */
-	clrbits32(&bcsr[1], 0x00610000);
-
-	/* enable new powersettings */
-	setbits32(&bcsr[1], reg);
-
-	return 0;
-}
-#endif
-
 struct cpm_pin {
 	int port, pin, flags;
 };
@@ -245,12 +189,6 @@ static void __init mpc885ads_setup_arch(
 		of_detach_node(np);
 		of_node_put(np);
 	}
-
-#ifdef CONFIG_PCMCIA_M8XX
-	/* Set up board specific hook-ups.*/
-	m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
-	m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
-#endif
 }
 
 static int __init mpc885ads_probe(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,6 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/time.h>
-#include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/cpm1.h>
 #include <asm/fs_pd.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/amigaone/setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/amigaone/setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/amigaone/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/amigaone/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <asm/i8259.h>
 #include <asm/time.h>
 #include <asm/udbg.h>
+#include <asm/dma.h>
 
 extern void __flush_disable_L1(void);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spu_base.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spu_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spu_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -611,7 +611,6 @@ static int __init create_spu(void *data)
 	int ret;
 	static int number;
 	unsigned long flags;
-	struct timespec ts;
 
 	ret = -ENOMEM;
 	spu = kzalloc(sizeof (*spu), GFP_KERNEL);
@@ -652,8 +651,7 @@ static int __init create_spu(void *data)
 	mutex_unlock(&spu_full_list_mutex);
 
 	spu->stats.util_state = SPU_UTIL_IDLE_LOADED;
-	ktime_get_ts(&ts);
-	spu->stats.tstamp = timespec_to_ns(&ts);
+	spu->stats.tstamp = ktime_get_ns();
 
 	INIT_LIST_HEAD(&spu->aff_list);
 
@@ -676,7 +674,6 @@ static const char *spu_state_names[] = {
 static unsigned long long spu_acct_time(struct spu *spu,
 		enum spu_utilization_state state)
 {
-	struct timespec ts;
 	unsigned long long time = spu->stats.times[state];
 
 	/*
@@ -684,10 +681,8 @@ static unsigned long long spu_acct_time(
 	 * statistics are not updated.  Apply the time delta from the
 	 * last recorded state of the spu.
 	 */
-	if (spu->stats.util_state == state) {
-		ktime_get_ts(&ts);
-		time += timespec_to_ns(&ts) - spu->stats.tstamp;
-	}
+	if (spu->stats.util_state == state)
+		time += ktime_get_ns() - spu->stats.tstamp;
 
 	return time / NSEC_PER_MSEC;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/context.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/context.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/context.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/context.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,6 @@ atomic_t nr_spu_contexts = ATOMIC_INIT(0
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
-	struct timespec ts;
 
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
@@ -67,8 +66,7 @@ struct spu_context *alloc_spu_context(st
 	__spu_update_sched_info(ctx);
 	spu_set_timeslice(ctx);
 	ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
-	ktime_get_ts(&ts);
-	ctx->stats.tstamp = timespec_to_ns(&ts);
+	ctx->stats.tstamp = ktime_get_ns();
 
 	atomic_inc(&nr_spu_contexts);
 	goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/file.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/file.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/file.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/file.c	2014-09-28 17:29:07.000000000 -0400
@@ -2338,7 +2338,6 @@ static const char *ctx_state_names[] = {
 static unsigned long long spufs_acct_time(struct spu_context *ctx,
 		enum spu_utilization_state state)
 {
-	struct timespec ts;
 	unsigned long long time = ctx->stats.times[state];
 
 	/*
@@ -2351,8 +2350,7 @@ static unsigned long long spufs_acct_tim
 	 * of the spu context.
 	 */
 	if (ctx->spu && ctx->stats.util_state == state) {
-		ktime_get_ts(&ts);
-		time += timespec_to_ns(&ts) - ctx->stats.tstamp;
+		time += ktime_get_ns() - ctx->stats.tstamp;
 	}
 
 	return time / NSEC_PER_MSEC;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/sched.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/sched.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2014-09-28 17:29:07.000000000 -0400
@@ -1039,13 +1039,11 @@ void spuctx_switch_state(struct spu_cont
 {
 	unsigned long long curtime;
 	signed long long delta;
-	struct timespec ts;
 	struct spu *spu;
 	enum spu_utilization_state old_state;
 	int node;
 
-	ktime_get_ts(&ts);
-	curtime = timespec_to_ns(&ts);
+	curtime = ktime_get_ns();
 	delta = curtime - ctx->stats.tstamp;
 
 	WARN_ON(!mutex_is_locked(&ctx->state_mutex));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/Kconfig.cputype linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-3.16-gnu/arch/powerpc/platforms/Kconfig.cputype	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/Kconfig.cputype	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ choice
 	help
 	  There are two families of 64 bit PowerPC chips supported.
 	  The most common ones are the desktop and server CPUs
-	  (POWER3, RS64, POWER4, POWER5, POWER5+, POWER6, ...)
+	  (POWER4, POWER5, 970, POWER5+, POWER6, POWER7, POWER8 ...)
 
 	  The other are the "embedded" processors compliant with the
 	  "Book 3E" variant of the architecture
@@ -140,14 +140,6 @@ config 6xx
 	depends on PPC32 && PPC_BOOK3S
 	select PPC_HAVE_PMU_SUPPORT
 
-config POWER3
-	depends on PPC64 && PPC_BOOK3S
-	def_bool y
-
-config POWER4
-	depends on PPC64 && PPC_BOOK3S
-	def_bool y
-
 config TUNE_CELL
 	bool "Optimize for Cell Broadband Engine"
 	depends on PPC64 && PPC_BOOK3S
@@ -244,7 +236,7 @@ config PHYS_64BIT
 
 config ALTIVEC
 	bool "AltiVec Support"
-	depends on 6xx || POWER4 || (PPC_E500MC && PPC64)
+	depends on 6xx || PPC_BOOK3S_64 || (PPC_E500MC && PPC64)
 	---help---
 	  This option enables kernel support for the Altivec extensions to the
 	  PowerPC processor. The kernel currently supports saving and restoring
@@ -260,7 +252,7 @@ config ALTIVEC
 
 config VSX
 	bool "VSX Support"
-	depends on POWER4 && ALTIVEC && PPC_FPU
+	depends on PPC_BOOK3S_64 && ALTIVEC && PPC_FPU
 	---help---
 
 	  This option enables kernel support for the Vector Scaler extensions
@@ -276,7 +268,7 @@ config VSX
 
 config PPC_ICSWX
 	bool "Support for PowerPC icswx coprocessor instruction"
-	depends on POWER4
+	depends on PPC_BOOK3S_64
 	default n
 	---help---
 
@@ -294,7 +286,7 @@ config PPC_ICSWX
 
 config PPC_ICSWX_PID
 	bool "icswx requires direct PID management"
-	depends on PPC_ICSWX && POWER4
+	depends on PPC_ICSWX
 	default y
 	---help---
 	  The PID register in server is used explicitly for ICSWX.  In
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/feature.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/feature.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/feature.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/feature.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,7 +158,7 @@ static inline int simple_feature_tweak(s
 	return 0;
 }
 
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 
 static long ohare_htw_scc_enable(struct device_node *node, long param,
 				 long value)
@@ -1318,7 +1318,7 @@ intrepid_aack_delay_enable(struct device
 }
 
 
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 
 static long
 core99_read_gpio(struct device_node *node, long param, long value)
@@ -1338,7 +1338,7 @@ core99_write_gpio(struct device_node *no
 	return 0;
 }
 
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
 static long g5_gmac_enable(struct device_node *node, long param, long value)
 {
 	struct macio_chip *macio = &macio_chips[0];
@@ -1550,9 +1550,9 @@ void g5_phy_disable_cpu1(void)
 	if (uninorth_maj == 3)
 		UN_OUT(U3_API_PHY_CONFIG_1, 0);
 }
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 
 
 #ifdef CONFIG_PM
@@ -1864,7 +1864,7 @@ core99_sleep_state(struct device_node *n
 	return 0;
 }
 
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 
 static long
 generic_dev_can_wake(struct device_node *node, long param, long value)
@@ -1906,7 +1906,7 @@ static struct feature_table_entry any_fe
 	{ 0, NULL }
 };
 
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 
 /* OHare based motherboards. Currently, we only use these on the
  * 2400,3400 and 3500 series powerbooks. Some older desktops seem
@@ -2056,7 +2056,7 @@ static struct feature_table_entry intrep
 	{ 0, NULL }
 };
 
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
 
 /* G5 features
  */
@@ -2074,10 +2074,10 @@ static struct feature_table_entry g5_fea
 	{ 0, NULL }
 };
 
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 
 static struct pmac_mb_def pmac_mb_defs[] = {
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 	/*
 	 * Desktops
 	 */
@@ -2342,7 +2342,7 @@ static struct pmac_mb_def pmac_mb_defs[]
 		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
 		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
 	},
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
 	{	"PowerMac7,2",			"PowerMac G5",
 		PMAC_TYPE_POWERMAC_G5,		g5_features,
 		0,
@@ -2373,7 +2373,7 @@ static struct pmac_mb_def pmac_mb_defs[]
 		0,
 	},
 #endif /* CONFIG_PPC64 */
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 };
 
 /*
@@ -2441,7 +2441,7 @@ static int __init probe_motherboard(void
 
 	/* Fallback to selection depending on mac-io chip type */
 	switch(macio->type) {
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 	    case macio_grand_central:
 		pmac_mb.model_id = PMAC_TYPE_PSURGE;
 		pmac_mb.model_name = "Unknown PowerSurge";
@@ -2475,7 +2475,7 @@ static int __init probe_motherboard(void
 		pmac_mb.model_name = "Unknown Intrepid-based";
 		pmac_mb.features = intrepid_features;
 		break;
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
 	case macio_keylargo2:
 		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
 		pmac_mb.model_name = "Unknown K2-based";
@@ -2486,13 +2486,13 @@ static int __init probe_motherboard(void
 		pmac_mb.model_name = "Unknown Shasta-based";
 		pmac_mb.features = g5_features;
 		break;
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 	default:
 		ret = -ENODEV;
 		goto done;
 	}
 found:
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
 	/* Fixup Hooper vs. Comet */
 	if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
 		u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
@@ -2546,9 +2546,9 @@ found:
 	 */
 	powersave_lowspeed = 1;
 
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
 	powersave_nap = 1;
-#endif  /* CONFIG_POWER4 */
+#endif  /* CONFIG_PPC64 */
 
 	/* Check for "mobile" machine */
 	if (model && (strncmp(model, "PowerBook", 9) == 0
@@ -2786,7 +2786,7 @@ set_initial_features(void)
 		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
 	}
 
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
 	if (macio_chips[0].type == macio_keylargo2 ||
 	    macio_chips[0].type == macio_shasta) {
 #ifndef CONFIG_SMP
@@ -2805,28 +2805,23 @@ set_initial_features(void)
 		/* Enable GMAC for now for PCI probing. It will be disabled
 		 * later on after PCI probe
 		 */
-		np = of_find_node_by_name(NULL, "ethernet");
-		while(np) {
+		for_each_node_by_name(np, "ethernet")
 			if (of_device_is_compatible(np, "K2-GMAC"))
 				g5_gmac_enable(np, 0, 1);
-			np = of_find_node_by_name(np, "ethernet");
-		}
 
 		/* Enable FW before PCI probe. Will be disabled later on
 		 * Note: We should have a batter way to check that we are
 		 * dealing with uninorth internal cell and not a PCI cell
 		 * on the external PCI. The code below works though.
 		 */
-		np = of_find_node_by_name(NULL, "firewire");
-		while(np) {
+		for_each_node_by_name(np, "firewire") {
 			if (of_device_is_compatible(np, "pci106b,5811")) {
 				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
 				g5_fw_enable(np, 0, 1);
 			}
-			np = of_find_node_by_name(np, "firewire");
 		}
 	}
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
 
 	if (macio_chips[0].type == macio_keylargo ||
 	    macio_chips[0].type == macio_pangea ||
@@ -2834,13 +2829,11 @@ set_initial_features(void)
 		/* Enable GMAC for now for PCI probing. It will be disabled
 		 * later on after PCI probe
 		 */
-		np = of_find_node_by_name(NULL, "ethernet");
-		while(np) {
+		for_each_node_by_name(np, "ethernet") {
 			if (np->parent
 			    && of_device_is_compatible(np->parent, "uni-north")
 			    && of_device_is_compatible(np, "gmac"))
 				core99_gmac_enable(np, 0, 1);
-			np = of_find_node_by_name(np, "ethernet");
 		}
 
 		/* Enable FW before PCI probe. Will be disabled later on
@@ -2848,8 +2841,7 @@ set_initial_features(void)
 		 * dealing with uninorth internal cell and not a PCI cell
 		 * on the external PCI. The code below works though.
 		 */
-		np = of_find_node_by_name(NULL, "firewire");
-		while(np) {
+		for_each_node_by_name(np, "firewire") {
 			if (np->parent
 			    && of_device_is_compatible(np->parent, "uni-north")
 			    && (of_device_is_compatible(np, "pci106b,18") ||
@@ -2858,18 +2850,16 @@ set_initial_features(void)
 				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
 				core99_firewire_enable(np, 0, 1);
 			}
-			np = of_find_node_by_name(np, "firewire");
 		}
 
 		/* Enable ATA-100 before PCI probe. */
 		np = of_find_node_by_name(NULL, "ata-6");
-		while(np) {
+		for_each_node_by_name(np, "ata-6") {
 			if (np->parent
 			    && of_device_is_compatible(np->parent, "uni-north")
 			    && of_device_is_compatible(np, "kauai-ata")) {
 				core99_ata100_enable(np, 1);
 			}
-			np = of_find_node_by_name(np, "ata-6");
 		}
 
 		/* Switch airport off */
@@ -2895,7 +2885,7 @@ set_initial_features(void)
 		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
 	}
 
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
 
 	/* On all machines, switch modem & serial ports off */
 	for_each_node_by_name(np, "ch-a")
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/Kconfig linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/Kconfig
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@ config PPC_PMAC
 
 config PPC_PMAC64
 	bool
-	depends on PPC_PMAC && POWER4
+	depends on PPC_PMAC && PPC64
 	select MPIC
 	select U3_DART
 	select MPIC_U3_HT_IRQS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/pci.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/pci.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -698,7 +698,7 @@ static void __init fixup_nec_usb2(void)
 {
 	struct device_node *nec;
 
-	for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
+	for_each_node_by_name(nec, "usb") {
 		struct pci_controller *hose;
 		u32 data;
 		const u32 *prop;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/smp.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/smp.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -577,7 +577,7 @@ static void __init smp_core99_setup_i2c_
 	int ok;
 
 	/* Look for the clock chip */
-	while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
+	for_each_node_by_name(cc, "i2c-hwclock") {
 		p = of_get_parent(cc);
 		ok = p && of_device_is_compatible(p, "uni-n-i2c");
 		of_node_put(p);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/udbg_adb.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/udbg_adb.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powermac/udbg_adb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powermac/udbg_adb.c	2014-09-28 17:29:07.000000000 -0400
@@ -191,7 +191,7 @@ int __init udbg_adb_init(int force_btext
 	 * of type "adb". If not, we return a failure, but we keep the
 	 * bext output set for now
 	 */
-	for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) {
+	for_each_node_by_name(np, "keyboard") {
 		struct device_node *parent = of_get_parent(np);
 		int found = (parent && strcmp(parent->type, "adb") == 0);
 		of_node_put(parent);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/eeh-ioda.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/eeh-ioda.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/eeh-ioda.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/eeh-ioda.c	2014-09-28 17:29:07.000000000 -0400
@@ -187,10 +187,10 @@ static int ioda_eeh_post_init(struct pci
  */
 static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
 {
-	s64 ret;
-	u32 pe_no;
 	struct pci_controller *hose = pe->phb;
 	struct pnv_phb *phb = hose->private_data;
+	int enable, ret = 0;
+	s64 rc;
 
 	/* Check on PE number */
 	if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
@@ -201,184 +201,214 @@ static int ioda_eeh_set_option(struct ee
 		return -EINVAL;
 	}
 
-	pe_no = pe->addr;
 	switch (option) {
 	case EEH_OPT_DISABLE:
-		ret = -EEXIST;
-		break;
+		return -EPERM;
 	case EEH_OPT_ENABLE:
-		ret = 0;
-		break;
+		return 0;
 	case EEH_OPT_THAW_MMIO:
-		ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
-				OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO);
-		if (ret) {
-			pr_warning("%s: Failed to enable MMIO for "
-				   "PHB#%x-PE#%x, err=%lld\n",
-				__func__, hose->global_number, pe_no, ret);
-			return -EIO;
-		}
-
+		enable = OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO;
 		break;
 	case EEH_OPT_THAW_DMA:
-		ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
-				OPAL_EEH_ACTION_CLEAR_FREEZE_DMA);
-		if (ret) {
-			pr_warning("%s: Failed to enable DMA for "
-				   "PHB#%x-PE#%x, err=%lld\n",
-				__func__, hose->global_number, pe_no, ret);
-			return -EIO;
-		}
-
+		enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA;
 		break;
 	default:
-		pr_warning("%s: Invalid option %d\n", __func__, option);
+		pr_warn("%s: Invalid option %d\n",
+			__func__, option);
 		return -EINVAL;
 	}
 
+	/* If PHB supports compound PE, to handle it */
+	if (phb->unfreeze_pe) {
+		ret = phb->unfreeze_pe(phb, pe->addr, enable);
+	} else {
+		rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+					       pe->addr,
+					       enable);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n",
+				__func__, rc, option, phb->hose->global_number,
+				pe->addr);
+			ret = -EIO;
+		}
+	}
+
 	return ret;
 }
 
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
+static void ioda_eeh_phb_diag(struct eeh_pe *pe)
 {
-	struct pnv_phb *phb = hose->private_data;
+	struct pnv_phb *phb = pe->phb->private_data;
 	long rc;
 
-	rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+	rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data,
 					 PNV_PCI_DIAG_BUF_SIZE);
-	if (rc != OPAL_SUCCESS) {
-		pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
-			    __func__, hose->global_number, rc);
-		return;
-	}
-
-	pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+	if (rc != OPAL_SUCCESS)
+		pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+			__func__, pe->phb->global_number, rc);
 }
 
-/**
- * ioda_eeh_get_state - Retrieve the state of PE
- * @pe: EEH PE
- *
- * The PE's state should be retrieved from the PEEV, PEST
- * IODA tables. Since the OPAL has exported the function
- * to do it, it'd better to use that.
- */
-static int ioda_eeh_get_state(struct eeh_pe *pe)
+static int ioda_eeh_get_phb_state(struct eeh_pe *pe)
 {
-	s64 ret = 0;
+	struct pnv_phb *phb = pe->phb->private_data;
 	u8 fstate;
 	__be16 pcierr;
-	u32 pe_no;
-	int result;
-	struct pci_controller *hose = pe->phb;
-	struct pnv_phb *phb = hose->private_data;
+	s64 rc;
+	int result = 0;
 
-	/*
-	 * Sanity check on PE address. The PHB PE address should
-	 * be zero.
-	 */
-	if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
-		pr_err("%s: PE address %x out of range [0, %x] "
-		       "on PHB#%x\n",
-		       __func__, pe->addr, phb->ioda.total_pe,
-		       hose->global_number);
+	rc = opal_pci_eeh_freeze_status(phb->opal_id,
+					pe->addr,
+					&fstate,
+					&pcierr,
+					NULL);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: Failure %lld getting PHB#%x state\n",
+			__func__, rc, phb->hose->global_number);
 		return EEH_STATE_NOT_SUPPORT;
 	}
 
 	/*
-	 * If we're in middle of PE reset, return normal
-	 * state to keep EEH core going. For PHB reset, we
-	 * still expect to have fenced PHB cleared with
-	 * PHB reset.
+	 * Check PHB state. If the PHB is frozen for the
+	 * first time, to dump the PHB diag-data.
 	 */
-	if (!(pe->type & EEH_PE_PHB) &&
-	    (pe->state & EEH_PE_RESET)) {
-		result = (EEH_STATE_MMIO_ACTIVE |
-			  EEH_STATE_DMA_ACTIVE |
+	if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
+		result = (EEH_STATE_MMIO_ACTIVE  |
+			  EEH_STATE_DMA_ACTIVE   |
 			  EEH_STATE_MMIO_ENABLED |
 			  EEH_STATE_DMA_ENABLED);
-		return result;
-	}
-
-	/* Retrieve PE status through OPAL */
-	pe_no = pe->addr;
-	ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no,
-			&fstate, &pcierr, NULL);
-	if (ret) {
-		pr_err("%s: Failed to get EEH status on "
-		       "PHB#%x-PE#%x\n, err=%lld\n",
-		       __func__, hose->global_number, pe_no, ret);
-		return EEH_STATE_NOT_SUPPORT;
+	} else if (!(pe->state & EEH_PE_ISOLATED)) {
+		eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+		ioda_eeh_phb_diag(pe);
 	}
 
-	/* Check PHB status */
-	if (pe->type & EEH_PE_PHB) {
-		result = 0;
-		result &= ~EEH_STATE_RESET_ACTIVE;
+	return result;
+}
 
-		if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
-			result |= EEH_STATE_MMIO_ACTIVE;
-			result |= EEH_STATE_DMA_ACTIVE;
-			result |= EEH_STATE_MMIO_ENABLED;
-			result |= EEH_STATE_DMA_ENABLED;
-		} else if (!(pe->state & EEH_PE_ISOLATED)) {
-			eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
-			ioda_eeh_phb_diag(hose);
-		}
+static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
+{
+	struct pnv_phb *phb = pe->phb->private_data;
+	u8 fstate;
+	__be16 pcierr;
+	s64 rc;
+	int result;
 
+	/*
+	 * We don't clobber hardware frozen state until PE
+	 * reset is completed. In order to keep EEH core
+	 * moving forward, we have to return operational
+	 * state during PE reset.
+	 */
+	if (pe->state & EEH_PE_RESET) {
+		result = (EEH_STATE_MMIO_ACTIVE  |
+			  EEH_STATE_DMA_ACTIVE   |
+			  EEH_STATE_MMIO_ENABLED |
+			  EEH_STATE_DMA_ENABLED);
 		return result;
 	}
 
-	/* Parse result out */
-	result = 0;
+	/*
+	 * Fetch PE state from hardware. If the PHB
+	 * supports compound PE, let it handle that.
+	 */
+	if (phb->get_pe_state) {
+		fstate = phb->get_pe_state(phb, pe->addr);
+	} else {
+		rc = opal_pci_eeh_freeze_status(phb->opal_id,
+						pe->addr,
+						&fstate,
+						&pcierr,
+						NULL);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n",
+				__func__, rc, phb->hose->global_number, pe->addr);
+			return EEH_STATE_NOT_SUPPORT;
+		}
+	}
+
+	/* Figure out state */
 	switch (fstate) {
 	case OPAL_EEH_STOPPED_NOT_FROZEN:
-		result &= ~EEH_STATE_RESET_ACTIVE;
-		result |= EEH_STATE_MMIO_ACTIVE;
-		result |= EEH_STATE_DMA_ACTIVE;
-		result |= EEH_STATE_MMIO_ENABLED;
-		result |= EEH_STATE_DMA_ENABLED;
+		result = (EEH_STATE_MMIO_ACTIVE  |
+			  EEH_STATE_DMA_ACTIVE   |
+			  EEH_STATE_MMIO_ENABLED |
+			  EEH_STATE_DMA_ENABLED);
 		break;
 	case OPAL_EEH_STOPPED_MMIO_FREEZE:
-		result &= ~EEH_STATE_RESET_ACTIVE;
-		result |= EEH_STATE_DMA_ACTIVE;
-		result |= EEH_STATE_DMA_ENABLED;
+		result = (EEH_STATE_DMA_ACTIVE |
+			  EEH_STATE_DMA_ENABLED);
 		break;
 	case OPAL_EEH_STOPPED_DMA_FREEZE:
-		result &= ~EEH_STATE_RESET_ACTIVE;
-		result |= EEH_STATE_MMIO_ACTIVE;
-		result |= EEH_STATE_MMIO_ENABLED;
+		result = (EEH_STATE_MMIO_ACTIVE |
+			  EEH_STATE_MMIO_ENABLED);
 		break;
 	case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE:
-		result &= ~EEH_STATE_RESET_ACTIVE;
+		result = 0;
 		break;
 	case OPAL_EEH_STOPPED_RESET:
-		result |= EEH_STATE_RESET_ACTIVE;
+		result = EEH_STATE_RESET_ACTIVE;
 		break;
 	case OPAL_EEH_STOPPED_TEMP_UNAVAIL:
-		result |= EEH_STATE_UNAVAILABLE;
+		result = EEH_STATE_UNAVAILABLE;
 		break;
 	case OPAL_EEH_STOPPED_PERM_UNAVAIL:
-		result |= EEH_STATE_NOT_SUPPORT;
+		result = EEH_STATE_NOT_SUPPORT;
 		break;
 	default:
-		pr_warning("%s: Unexpected EEH status 0x%x "
-			   "on PHB#%x-PE#%x\n",
-			   __func__, fstate, hose->global_number, pe_no);
+		result = EEH_STATE_NOT_SUPPORT;
+		pr_warn("%s: Invalid PHB#%x-PE#%x state %x\n",
+			__func__, phb->hose->global_number,
+			pe->addr, fstate);
 	}
 
-	/* Dump PHB diag-data for frozen PE */
-	if (result != EEH_STATE_NOT_SUPPORT &&
-	    (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
-	    (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
+	/*
+	 * If PHB supports compound PE, to freeze all
+	 * slave PEs for consistency.
+	 *
+	 * If the PE is switching to frozen state for the
+	 * first time, to dump the PHB diag-data.
+	 */
+	if (!(result & EEH_STATE_NOT_SUPPORT) &&
+	    !(result & EEH_STATE_UNAVAILABLE) &&
+	    !(result & EEH_STATE_MMIO_ACTIVE) &&
+	    !(result & EEH_STATE_DMA_ACTIVE)  &&
 	    !(pe->state & EEH_PE_ISOLATED)) {
+		if (phb->freeze_pe)
+			phb->freeze_pe(phb, pe->addr);
+
 		eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
-		ioda_eeh_phb_diag(hose);
+		ioda_eeh_phb_diag(pe);
 	}
 
 	return result;
 }
 
+/**
+ * ioda_eeh_get_state - Retrieve the state of PE
+ * @pe: EEH PE
+ *
+ * The PE's state should be retrieved from the PEEV, PEST
+ * IODA tables. Since the OPAL has exported the function
+ * to do it, it'd better to use that.
+ */
+static int ioda_eeh_get_state(struct eeh_pe *pe)
+{
+	struct pnv_phb *phb = pe->phb->private_data;
+
+	/* Sanity check on PE number. PHB PE should have 0 */
+	if (pe->addr < 0 ||
+	    pe->addr >= phb->ioda.total_pe) {
+		pr_warn("%s: PHB#%x-PE#%x out of range [0, %x]\n",
+			__func__, phb->hose->global_number,
+			pe->addr, phb->ioda.total_pe);
+		return EEH_STATE_NOT_SUPPORT;
+	}
+
+	if (pe->type & EEH_PE_PHB)
+		return ioda_eeh_get_phb_state(pe);
+
+	return ioda_eeh_get_pe_state(pe);
+}
+
 static s64 ioda_eeh_phb_poll(struct pnv_phb *phb)
 {
 	s64 rc = OPAL_HARDWARE;
@@ -589,6 +619,24 @@ static int ioda_eeh_reset(struct eeh_pe
 }
 
 /**
+ * ioda_eeh_get_log - Retrieve error log
+ * @pe: frozen PE
+ * @severity: permanent or temporary error
+ * @drv_log: device driver log
+ * @len: length of device driver log
+ *
+ * Retrieve error log, which contains log from device driver
+ * and firmware.
+ */
+int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
+		     char *drv_log, unsigned long len)
+{
+	pnv_pci_dump_phb_diag_data(pe->phb, pe->data);
+
+	return 0;
+}
+
+/**
  * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
  * @pe: EEH PE
  *
@@ -605,18 +653,24 @@ static int ioda_eeh_configure_bridge(str
 static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 {
 	/* GEM */
-	pr_info("  GEM XFIR:        %016llx\n", data->gemXfir);
-	pr_info("  GEM RFIR:        %016llx\n", data->gemRfir);
-	pr_info("  GEM RIRQFIR:     %016llx\n", data->gemRirqfir);
-	pr_info("  GEM Mask:        %016llx\n", data->gemMask);
-	pr_info("  GEM RWOF:        %016llx\n", data->gemRwof);
+	if (data->gemXfir || data->gemRfir ||
+	    data->gemRirqfir || data->gemMask || data->gemRwof)
+		pr_info("  GEM: %016llx %016llx %016llx %016llx %016llx\n",
+			be64_to_cpu(data->gemXfir),
+			be64_to_cpu(data->gemRfir),
+			be64_to_cpu(data->gemRirqfir),
+			be64_to_cpu(data->gemMask),
+			be64_to_cpu(data->gemRwof));
 
 	/* LEM */
-	pr_info("  LEM FIR:         %016llx\n", data->lemFir);
-	pr_info("  LEM Error Mask:  %016llx\n", data->lemErrMask);
-	pr_info("  LEM Action 0:    %016llx\n", data->lemAction0);
-	pr_info("  LEM Action 1:    %016llx\n", data->lemAction1);
-	pr_info("  LEM WOF:         %016llx\n", data->lemWof);
+	if (data->lemFir || data->lemErrMask ||
+	    data->lemAction0 || data->lemAction1 || data->lemWof)
+		pr_info("  LEM: %016llx %016llx %016llx %016llx %016llx\n",
+			be64_to_cpu(data->lemFir),
+			be64_to_cpu(data->lemErrMask),
+			be64_to_cpu(data->lemAction0),
+			be64_to_cpu(data->lemAction1),
+			be64_to_cpu(data->lemWof));
 }
 
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
@@ -627,8 +681,8 @@ static void ioda_eeh_hub_diag(struct pci
 
 	rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
 	if (rc != OPAL_SUCCESS) {
-		pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
-			   __func__, phb->hub_id, rc);
+		pr_warn("%s: Failed to get HUB#%llx diag-data (%ld)\n",
+			__func__, phb->hub_id, rc);
 		return;
 	}
 
@@ -636,24 +690,31 @@ static void ioda_eeh_hub_diag(struct pci
 	case OPAL_P7IOC_DIAG_TYPE_RGC:
 		pr_info("P7IOC diag-data for RGC\n\n");
 		ioda_eeh_hub_diag_common(data);
-		pr_info("  RGC Status:      %016llx\n", data->rgc.rgcStatus);
-		pr_info("  RGC LDCP:        %016llx\n", data->rgc.rgcLdcp);
+		if (data->rgc.rgcStatus || data->rgc.rgcLdcp)
+			pr_info("  RGC: %016llx %016llx\n",
+				be64_to_cpu(data->rgc.rgcStatus),
+				be64_to_cpu(data->rgc.rgcLdcp));
 		break;
 	case OPAL_P7IOC_DIAG_TYPE_BI:
 		pr_info("P7IOC diag-data for BI %s\n\n",
 			data->bi.biDownbound ? "Downbound" : "Upbound");
 		ioda_eeh_hub_diag_common(data);
-		pr_info("  BI LDCP 0:       %016llx\n", data->bi.biLdcp0);
-		pr_info("  BI LDCP 1:       %016llx\n", data->bi.biLdcp1);
-		pr_info("  BI LDCP 2:       %016llx\n", data->bi.biLdcp2);
-		pr_info("  BI Fence Status: %016llx\n", data->bi.biFenceStatus);
+		if (data->bi.biLdcp0 || data->bi.biLdcp1 ||
+		    data->bi.biLdcp2 || data->bi.biFenceStatus)
+			pr_info("  BI:  %016llx %016llx %016llx %016llx\n",
+				be64_to_cpu(data->bi.biLdcp0),
+				be64_to_cpu(data->bi.biLdcp1),
+				be64_to_cpu(data->bi.biLdcp2),
+				be64_to_cpu(data->bi.biFenceStatus));
 		break;
 	case OPAL_P7IOC_DIAG_TYPE_CI:
-		pr_info("P7IOC diag-data for CI Port %d\\nn",
+		pr_info("P7IOC diag-data for CI Port %d\n\n",
 			data->ci.ciPort);
 		ioda_eeh_hub_diag_common(data);
-		pr_info("  CI Port Status:  %016llx\n", data->ci.ciPortStatus);
-		pr_info("  CI Port LDCP:    %016llx\n", data->ci.ciPortLdcp);
+		if (data->ci.ciPortStatus || data->ci.ciPortLdcp)
+			pr_info("  CI:  %016llx %016llx\n",
+				be64_to_cpu(data->ci.ciPortStatus),
+				be64_to_cpu(data->ci.ciPortLdcp));
 		break;
 	case OPAL_P7IOC_DIAG_TYPE_MISC:
 		pr_info("P7IOC diag-data for MISC\n\n");
@@ -664,30 +725,51 @@ static void ioda_eeh_hub_diag(struct pci
 		ioda_eeh_hub_diag_common(data);
 		break;
 	default:
-		pr_warning("%s: Invalid type of HUB#%llx diag-data (%d)\n",
-			   __func__, phb->hub_id, data->type);
+		pr_warn("%s: Invalid type of HUB#%llx diag-data (%d)\n",
+			__func__, phb->hub_id, data->type);
 	}
 }
 
 static int ioda_eeh_get_pe(struct pci_controller *hose,
 			   u16 pe_no, struct eeh_pe **pe)
 {
-	struct eeh_pe *phb_pe, *dev_pe;
-	struct eeh_dev dev;
+	struct pnv_phb *phb = hose->private_data;
+	struct pnv_ioda_pe *pnv_pe;
+	struct eeh_pe *dev_pe;
+	struct eeh_dev edev;
 
-	/* Find the PHB PE */
-	phb_pe = eeh_phb_pe_get(hose);
-	if (!phb_pe)
-		return -EEXIST;
+	/*
+	 * If PHB supports compound PE, to fetch
+	 * the master PE because slave PE is invisible
+	 * to EEH core.
+	 */
+	if (phb->get_pe_state) {
+		pnv_pe = &phb->ioda.pe_array[pe_no];
+		if (pnv_pe->flags & PNV_IODA_PE_SLAVE) {
+			pnv_pe = pnv_pe->master;
+			WARN_ON(!pnv_pe ||
+				!(pnv_pe->flags & PNV_IODA_PE_MASTER));
+			pe_no = pnv_pe->pe_number;
+		}
+	}
 
 	/* Find the PE according to PE# */
-	memset(&dev, 0, sizeof(struct eeh_dev));
-	dev.phb = hose;
-	dev.pe_config_addr = pe_no;
-	dev_pe = eeh_pe_get(&dev);
-	if (!dev_pe) return -EEXIST;
+	memset(&edev, 0, sizeof(struct eeh_dev));
+	edev.phb = hose;
+	edev.pe_config_addr = pe_no;
+	dev_pe = eeh_pe_get(&edev);
+	if (!dev_pe)
+		return -EEXIST;
 
+	/*
+	 * At this point, we're sure the compound PE should
+	 * be put into frozen state.
+	 */
 	*pe = dev_pe;
+	if (phb->freeze_pe &&
+	    !(dev_pe->state & EEH_PE_ISOLATED))
+		phb->freeze_pe(phb, pe_no);
+
 	return 0;
 }
 
@@ -792,7 +874,8 @@ static int ioda_eeh_next_error(struct ee
 					"detected, location: %s\n",
 					hose->global_number,
 					eeh_pe_loc_get(phb_pe));
-				ioda_eeh_phb_diag(hose);
+				ioda_eeh_phb_diag(phb_pe);
+				pnv_pci_dump_phb_diag_data(hose, phb_pe->data);
 				ret = EEH_NEXT_ERR_NONE;
 			}
 
@@ -812,7 +895,8 @@ static int ioda_eeh_next_error(struct ee
 				opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no,
 					OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
 				ret = EEH_NEXT_ERR_NONE;
-			} else if ((*pe)->state & EEH_PE_ISOLATED) {
+			} else if ((*pe)->state & EEH_PE_ISOLATED ||
+				   eeh_pe_passed(*pe)) {
 				ret = EEH_NEXT_ERR_NONE;
 			} else {
 				pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
@@ -839,7 +923,7 @@ static int ioda_eeh_next_error(struct ee
 		    ret == EEH_NEXT_ERR_FENCED_PHB) &&
 		    !((*pe)->state & EEH_PE_ISOLATED)) {
 			eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
-			ioda_eeh_phb_diag(hose);
+			ioda_eeh_phb_diag(*pe);
 		}
 
 		/*
@@ -885,6 +969,7 @@ struct pnv_eeh_ops ioda_eeh_ops = {
 	.set_option		= ioda_eeh_set_option,
 	.get_state		= ioda_eeh_get_state,
 	.reset			= ioda_eeh_reset,
+	.get_log		= ioda_eeh_get_log,
 	.configure_bridge	= ioda_eeh_configure_bridge,
 	.next_error		= ioda_eeh_next_error
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,14 +45,31 @@
  */
 static int powernv_eeh_init(void)
 {
+	struct pci_controller *hose;
+	struct pnv_phb *phb;
+
 	/* We require OPALv3 */
 	if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
-		pr_warning("%s: OPALv3 is required !\n", __func__);
+		pr_warn("%s: OPALv3 is required !\n",
+			__func__);
 		return -EINVAL;
 	}
 
-	/* Set EEH probe mode */
-	eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
+	/* Set probe mode */
+	eeh_add_flag(EEH_PROBE_MODE_DEV);
+
+	/*
+	 * P7IOC blocks PCI config access to frozen PE, but PHB3
+	 * doesn't do that. So we have to selectively enable I/O
+	 * prior to collecting error log.
+	 */
+	list_for_each_entry(hose, &hose_list, list_node) {
+		phb = hose->private_data;
+
+		if (phb->model == PNV_PHB_MODEL_P7IOC)
+			eeh_add_flag(EEH_ENABLE_IO_FOR_LOG);
+		break;
+	}
 
 	return 0;
 }
@@ -107,6 +124,7 @@ static int powernv_eeh_dev_probe(struct
 	struct pnv_phb *phb = hose->private_data;
 	struct device_node *dn = pci_device_to_OF_node(dev);
 	struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+	int ret;
 
 	/*
 	 * When probing the root bridge, which doesn't have any
@@ -143,13 +161,27 @@ static int powernv_eeh_dev_probe(struct
 	edev->pe_config_addr	= phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff);
 
 	/* Create PE */
-	eeh_add_to_parent_pe(edev);
+	ret = eeh_add_to_parent_pe(edev);
+	if (ret) {
+		pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n",
+			__func__, pci_name(dev), ret);
+		return ret;
+	}
+
+	/*
+	 * Cache the PE primary bus, which can't be fetched when
+	 * full hotplug is in progress. In that case, all child
+	 * PCI devices of the PE are expected to be removed prior
+	 * to PE reset.
+	 */
+	if (!edev->pe->bus)
+		edev->pe->bus = dev->bus;
 
 	/*
 	 * Enable EEH explicitly so that we will do EEH check
 	 * while accessing I/O stuff
 	 */
-	eeh_set_enable(true);
+	eeh_add_flag(EEH_ENABLED);
 
 	/* Save memory bars */
 	eeh_save_bars(edev);
@@ -273,8 +305,8 @@ static int powernv_eeh_wait_state(struct
 
 		max_wait -= mwait;
 		if (max_wait <= 0) {
-			pr_warning("%s: Timeout getting PE#%x's state (%d)\n",
-				   __func__, pe->addr, max_wait);
+			pr_warn("%s: Timeout getting PE#%x's state (%d)\n",
+				__func__, pe->addr, max_wait);
 			return EEH_STATE_NOT_SUPPORT;
 		}
 
@@ -294,7 +326,7 @@ static int powernv_eeh_wait_state(struct
  * Retrieve the temporary or permanent error from the PE.
  */
 static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
-			char *drv_log, unsigned long len)
+			       char *drv_log, unsigned long len)
 {
 	struct pci_controller *hose = pe->phb;
 	struct pnv_phb *phb = hose->private_data;
@@ -398,9 +430,7 @@ static int __init eeh_powernv_init(void)
 {
 	int ret = -EINVAL;
 
-	if (!machine_is(powernv))
-		return ret;
-
+	eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE);
 	ret = eeh_ops_register(&powernv_eeh_ops);
 	if (!ret)
 		pr_info("EEH: PowerNV platform initialized\n");
@@ -409,5 +439,4 @@ static int __init eeh_powernv_init(void)
 
 	return ret;
 }
-
-early_initcall(eeh_powernv_init);
+machine_early_initcall(powernv, eeh_powernv_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/Makefile linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/Makefile
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,10 +1,11 @@
 obj-y			+= setup.o opal-wrappers.o opal.o opal-async.o
 obj-y			+= opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
 obj-y			+= rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
-obj-y			+= opal-msglog.o
+obj-y			+= opal-msglog.o opal-hmi.o
 
 obj-$(CONFIG_SMP)	+= smp.o subcore.o subcore-asm.o
 obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o pci-ioda.o
 obj-$(CONFIG_EEH)	+= eeh-ioda.o eeh-powernv.o
 obj-$(CONFIG_PPC_SCOM)	+= opal-xscom.o
 obj-$(CONFIG_MEMORY_FAILURE)	+= opal-memory-errors.o
+obj-$(CONFIG_TRACEPOINTS)	+= opal-tracepoints.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-async.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-async.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-async.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-async.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/wait.h>
 #include <linux/gfp.h>
 #include <linux/of.h>
+#include <asm/machdep.h>
 #include <asm/opal.h>
 
 #define N_ASYNC_COMPLETIONS	64
@@ -201,4 +202,4 @@ out_opal_node:
 out:
 	return err;
 }
-subsys_initcall(opal_async_comp_init);
+machine_subsys_initcall(powernv, opal_async_comp_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,8 @@
 #include <linux/kobject.h>
 #include <linux/delay.h>
 #include <linux/memblock.h>
+
+#include <asm/machdep.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
 #include <asm/mce.h>
@@ -192,16 +194,12 @@ static int __init opal_register_exceptio
 	 * fwnmi area at 0x7000 to provide the glue space to OPAL
 	 */
 	glue = 0x7000;
-	opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
-					0, glue);
-	glue += 128;
 	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
 #endif
 
 	return 0;
 }
-
-early_initcall(opal_register_exception_handlers);
+machine_early_initcall(powernv, opal_register_exception_handlers);
 
 int opal_notifier_register(struct notifier_block *nb)
 {
@@ -368,7 +366,7 @@ static int __init opal_message_init(void
 	}
 	return 0;
 }
-early_initcall(opal_message_init);
+machine_early_initcall(powernv, opal_message_init);
 
 int opal_get_chars(uint32_t vtermno, char *buf, int count)
 {
@@ -513,6 +511,46 @@ int opal_machine_check(struct pt_regs *r
 	return 0;
 }
 
+/* Early hmi handler called in real mode. */
+int opal_hmi_exception_early(struct pt_regs *regs)
+{
+	s64 rc;
+
+	/*
+	 * call opal hmi handler. Pass paca address as token.
+	 * The return value OPAL_SUCCESS is an indication that there is
+	 * an HMI event generated waiting to pull by Linux.
+	 */
+	rc = opal_handle_hmi();
+	if (rc == OPAL_SUCCESS) {
+		local_paca->hmi_event_available = 1;
+		return 1;
+	}
+	return 0;
+}
+
+/* HMI exception handler called in virtual mode during check_irq_replay. */
+int opal_handle_hmi_exception(struct pt_regs *regs)
+{
+	s64 rc;
+	__be64 evt = 0;
+
+	/*
+	 * Check if HMI event is available.
+	 * if Yes, then call opal_poll_events to pull opal messages and
+	 * process them.
+	 */
+	if (!local_paca->hmi_event_available)
+		return 0;
+
+	local_paca->hmi_event_available = 0;
+	rc = opal_poll_events(&evt);
+	if (rc == OPAL_SUCCESS && evt)
+		opal_do_notifier(be64_to_cpu(evt));
+
+	return 1;
+}
+
 static uint64_t find_recovery_address(uint64_t nip)
 {
 	int i;
@@ -567,6 +605,24 @@ static int opal_sysfs_init(void)
 	return 0;
 }
 
+static void __init opal_dump_region_init(void)
+{
+	void *addr;
+	uint64_t size;
+	int rc;
+
+	/* Register kernel log buffer */
+	addr = log_buf_addr_get();
+	size = log_buf_len_get();
+	rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF,
+				       __pa(addr), size);
+	/* Don't warn if this is just an older OPAL that doesn't
+	 * know about that call
+	 */
+	if (rc && rc != OPAL_UNSUPPORTED)
+		pr_warn("DUMP: Failed to register kernel log buffer. "
+			"rc = %d\n", rc);
+}
 static int __init opal_init(void)
 {
 	struct device_node *np, *consoles;
@@ -616,6 +672,8 @@ static int __init opal_init(void)
 	/* Create "opal" kobject under /sys/firmware */
 	rc = opal_sysfs_init();
 	if (rc == 0) {
+		/* Setup dump region interface */
+		opal_dump_region_init();
 		/* Setup error log interface */
 		rc = opal_elog_init();
 		/* Setup code update interface */
@@ -630,7 +688,7 @@ static int __init opal_init(void)
 
 	return 0;
 }
-subsys_initcall(opal_init);
+machine_subsys_initcall(powernv, opal_init);
 
 void opal_shutdown(void)
 {
@@ -656,6 +714,9 @@ void opal_shutdown(void)
 		else
 			mdelay(10);
 	}
+
+	/* Unregister memory dump region */
+	opal_unregister_dump_region(OPAL_DUMP_REGION_LOG_BUF);
 }
 
 /* Export this so that test modules can use it */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-dump.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-dump.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-dump.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-dump.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,9 +102,9 @@ static ssize_t dump_ack_store(struct dum
  * due to the dynamic size of the dump
  */
 static struct dump_attribute id_attribute =
-	__ATTR(id, 0666, dump_id_show, NULL);
+	__ATTR(id, S_IRUGO, dump_id_show, NULL);
 static struct dump_attribute type_attribute =
-	__ATTR(type, 0666, dump_type_show, NULL);
+	__ATTR(type, S_IRUGO, dump_type_show, NULL);
 static struct dump_attribute ack_attribute =
 	__ATTR(acknowledge, 0660, dump_ack_show, dump_ack_store);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-elog.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-elog.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-elog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-elog.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,9 +82,9 @@ static ssize_t elog_ack_store(struct elo
 }
 
 static struct elog_attribute id_attribute =
-	__ATTR(id, 0666, elog_id_show, NULL);
+	__ATTR(id, S_IRUGO, elog_id_show, NULL);
 static struct elog_attribute type_attribute =
-	__ATTR(type, 0666, elog_type_show, NULL);
+	__ATTR(type, S_IRUGO, elog_type_show, NULL);
 static struct elog_attribute ack_attribute =
 	__ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-hmi.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-hmi.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-hmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-hmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,189 @@
+/*
+ * OPAL hypervisor Maintenance interrupt handling support in PowreNV.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/>.
+ *
+ * Copyright 2014 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/opal.h>
+#include <asm/cputable.h>
+#include <asm/machdep.h>
+
+static int opal_hmi_handler_nb_init;
+struct OpalHmiEvtNode {
+	struct list_head list;
+	struct OpalHMIEvent hmi_evt;
+};
+static LIST_HEAD(opal_hmi_evt_list);
+static DEFINE_SPINLOCK(opal_hmi_evt_lock);
+
+static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt)
+{
+	const char *level, *sevstr, *error_info;
+	static const char *hmi_error_types[] = {
+		"Malfunction Alert",
+		"Processor Recovery done",
+		"Processor recovery occurred again",
+		"Processor recovery occurred for masked error",
+		"Timer facility experienced an error",
+		"TFMR SPR is corrupted",
+		"UPS (Uniterrupted Power System) Overflow indication",
+		"An XSCOM operation failure",
+		"An XSCOM operation completed",
+		"SCOM has set a reserved FIR bit to cause recovery",
+		"Debug trigger has set a reserved FIR bit to cause recovery",
+		"A hypervisor resource error occurred"
+	};
+
+	/* Print things out */
+	if (hmi_evt->version != OpalHMIEvt_V1) {
+		pr_err("HMI Interrupt, Unknown event version %d !\n",
+			hmi_evt->version);
+		return;
+	}
+	switch (hmi_evt->severity) {
+	case OpalHMI_SEV_NO_ERROR:
+		level = KERN_INFO;
+		sevstr = "Harmless";
+		break;
+	case OpalHMI_SEV_WARNING:
+		level = KERN_WARNING;
+		sevstr = "";
+		break;
+	case OpalHMI_SEV_ERROR_SYNC:
+		level = KERN_ERR;
+		sevstr = "Severe";
+		break;
+	case OpalHMI_SEV_FATAL:
+	default:
+		level = KERN_ERR;
+		sevstr = "Fatal";
+		break;
+	}
+
+	printk("%s%s Hypervisor Maintenance interrupt [%s]\n",
+		level, sevstr,
+		hmi_evt->disposition == OpalHMI_DISPOSITION_RECOVERED ?
+		"Recovered" : "Not recovered");
+	error_info = hmi_evt->type < ARRAY_SIZE(hmi_error_types) ?
+			hmi_error_types[hmi_evt->type]
+			: "Unknown";
+	printk("%s Error detail: %s\n", level, error_info);
+	printk("%s	HMER: %016llx\n", level, be64_to_cpu(hmi_evt->hmer));
+	if ((hmi_evt->type == OpalHMI_ERROR_TFAC) ||
+		(hmi_evt->type == OpalHMI_ERROR_TFMR_PARITY))
+		printk("%s	TFMR: %016llx\n", level,
+						be64_to_cpu(hmi_evt->tfmr));
+}
+
+static void hmi_event_handler(struct work_struct *work)
+{
+	unsigned long flags;
+	struct OpalHMIEvent *hmi_evt;
+	struct OpalHmiEvtNode *msg_node;
+	uint8_t disposition;
+
+	spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+	while (!list_empty(&opal_hmi_evt_list)) {
+		msg_node = list_entry(opal_hmi_evt_list.next,
+					   struct OpalHmiEvtNode, list);
+		list_del(&msg_node->list);
+		spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+
+		hmi_evt = (struct OpalHMIEvent *) &msg_node->hmi_evt;
+		print_hmi_event_info(hmi_evt);
+		disposition = hmi_evt->disposition;
+		kfree(msg_node);
+
+		/*
+		 * Check if HMI event has been recovered or not. If not
+		 * then we can't continue, invoke panic.
+		 */
+		if (disposition != OpalHMI_DISPOSITION_RECOVERED)
+			panic("Unrecoverable HMI exception");
+
+		spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+	}
+	spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+}
+
+static DECLARE_WORK(hmi_event_work, hmi_event_handler);
+/*
+ * opal_handle_hmi_event - notifier handler that queues up HMI events
+ * to be preocessed later.
+ */
+static int opal_handle_hmi_event(struct notifier_block *nb,
+			  unsigned long msg_type, void *msg)
+{
+	unsigned long flags;
+	struct OpalHMIEvent *hmi_evt;
+	struct opal_msg *hmi_msg = msg;
+	struct OpalHmiEvtNode *msg_node;
+
+	/* Sanity Checks */
+	if (msg_type != OPAL_MSG_HMI_EVT)
+		return 0;
+
+	/* HMI event info starts from param[0] */
+	hmi_evt = (struct OpalHMIEvent *)&hmi_msg->params[0];
+
+	/* Delay the logging of HMI events to workqueue. */
+	msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC);
+	if (!msg_node) {
+		pr_err("HMI: out of memory, Opal message event not handled\n");
+		return -ENOMEM;
+	}
+	memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(struct OpalHMIEvent));
+
+	spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+	list_add(&msg_node->list, &opal_hmi_evt_list);
+	spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+
+	schedule_work(&hmi_event_work);
+	return 0;
+}
+
+static struct notifier_block opal_hmi_handler_nb = {
+	.notifier_call	= opal_handle_hmi_event,
+	.next		= NULL,
+	.priority	= 0,
+};
+
+static int __init opal_hmi_handler_init(void)
+{
+	int ret;
+
+	if (!opal_hmi_handler_nb_init) {
+		ret = opal_message_notifier_register(
+				OPAL_MSG_HMI_EVT, &opal_hmi_handler_nb);
+		if (ret) {
+			pr_err("%s: Can't register OPAL event notifier (%d)\n",
+			       __func__, ret);
+			return ret;
+		}
+		opal_hmi_handler_nb_init = 1;
+	}
+	return 0;
+}
+machine_subsys_initcall(powernv, opal_hmi_handler_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-lpc.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-lpc.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-lpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-lpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -324,7 +324,7 @@ static int opal_lpc_init_debugfs(void)
 	rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW);
 	return rc;
 }
-device_initcall(opal_lpc_init_debugfs);
+machine_device_initcall(powernv, opal_lpc_init_debugfs);
 #endif  /* CONFIG_DEBUG_FS */
 
 void opal_lpc_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-memory-errors.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-memory-errors.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-memory-errors.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-memory-errors.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
+#include <asm/machdep.h>
 #include <asm/opal.h>
 #include <asm/cputable.h>
 
@@ -143,4 +144,4 @@ static int __init opal_mem_err_init(void
 	}
 	return 0;
 }
-subsys_initcall(opal_mem_err_init);
+machine_subsys_initcall(powernv, opal_mem_err_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,84 @@
+#include <linux/percpu.h>
+#include <linux/jump_label.h>
+#include <asm/trace.h>
+
+#ifdef CONFIG_JUMP_LABEL
+struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
+
+void opal_tracepoint_regfunc(void)
+{
+	static_key_slow_inc(&opal_tracepoint_key);
+}
+
+void opal_tracepoint_unregfunc(void)
+{
+	static_key_slow_dec(&opal_tracepoint_key);
+}
+#else
+/*
+ * We optimise OPAL calls by placing opal_tracepoint_refcount
+ * directly in the TOC so we can check if the opal tracepoints are
+ * enabled via a single load.
+ */
+
+/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
+extern long opal_tracepoint_refcount;
+
+void opal_tracepoint_regfunc(void)
+{
+	opal_tracepoint_refcount++;
+}
+
+void opal_tracepoint_unregfunc(void)
+{
+	opal_tracepoint_refcount--;
+}
+#endif
+
+/*
+ * Since the tracing code might execute OPAL calls we need to guard against
+ * recursion.
+ */
+static DEFINE_PER_CPU(unsigned int, opal_trace_depth);
+
+void __trace_opal_entry(unsigned long opcode, unsigned long *args)
+{
+	unsigned long flags;
+	unsigned int *depth;
+
+	local_irq_save(flags);
+
+	depth = &__get_cpu_var(opal_trace_depth);
+
+	if (*depth)
+		goto out;
+
+	(*depth)++;
+	preempt_disable();
+	trace_opal_entry(opcode, args);
+	(*depth)--;
+
+out:
+	local_irq_restore(flags);
+}
+
+void __trace_opal_exit(long opcode, unsigned long retval)
+{
+	unsigned long flags;
+	unsigned int *depth;
+
+	local_irq_save(flags);
+
+	depth = &__get_cpu_var(opal_trace_depth);
+
+	if (*depth)
+		goto out;
+
+	(*depth)++;
+	trace_opal_exit(opcode, retval);
+	preempt_enable();
+	(*depth)--;
+
+out:
+	local_irq_restore(flags);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2014-09-28 17:29:07.000000000 -0400
@@ -13,30 +13,69 @@
 #include <asm/hvcall.h>
 #include <asm/asm-offsets.h>
 #include <asm/opal.h>
+#include <asm/jump_label.h>
+
+	.section	".text"
+
+#ifdef CONFIG_TRACEPOINTS
+#ifdef CONFIG_JUMP_LABEL
+#define OPAL_BRANCH(LABEL)					\
+	ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key)
+#else
+
+	.section	".toc","aw"
+
+	.globl opal_tracepoint_refcount
+opal_tracepoint_refcount:
+	.llong	0
+
+	.section	".text"
+
+/*
+ * We branch around this in early init by using an unconditional cpu
+ * feature.
+ */
+#define OPAL_BRANCH(LABEL)					\
+BEGIN_FTR_SECTION;						\
+	b	1f;						\
+END_FTR_SECTION(0, 1);						\
+	ld	r12,opal_tracepoint_refcount@toc(r2);		\
+	std	r12,32(r1);					\
+	cmpdi	r12,0;						\
+	bne-	LABEL;						\
+1:
+
+#endif
+
+#else
+#define OPAL_BRANCH(LABEL)
+#endif
 
 /* TODO:
  *
  * - Trace irqs in/off (needs saving/restoring all args, argh...)
  * - Get r11 feed up by Dave so I can have better register usage
  */
+
 #define OPAL_CALL(name, token)		\
  _GLOBAL(name);				\
 	mflr	r0;			\
-	mfcr	r12;			\
 	std	r0,16(r1);		\
+	li	r0,token;		\
+	OPAL_BRANCH(opal_tracepoint_entry) \
+	mfcr	r12;			\
 	stw	r12,8(r1);		\
 	std	r1,PACAR1(r13);		\
-	li	r0,0;			\
+	li	r11,0;			\
 	mfmsr	r12;			\
-	ori	r0,r0,MSR_EE;		\
+	ori	r11,r11,MSR_EE;		\
 	std	r12,PACASAVEDMSR(r13);	\
-	andc	r12,r12,r0;		\
+	andc	r12,r12,r11;		\
 	mtmsrd	r12,1;			\
-	LOAD_REG_ADDR(r0,opal_return);	\
-	mtlr	r0;			\
-	li	r0,MSR_DR|MSR_IR|MSR_LE;\
-	andc	r12,r12,r0;		\
-	li	r0,token;		\
+	LOAD_REG_ADDR(r11,opal_return);	\
+	mtlr	r11;			\
+	li	r11,MSR_DR|MSR_IR|MSR_LE;\
+	andc	r12,r12,r11;		\
 	mtspr	SPRN_HSRR1,r12;		\
 	LOAD_REG_ADDR(r11,opal);	\
 	ld	r12,8(r11);		\
@@ -61,6 +100,64 @@ opal_return:
 	mtcr	r4;
 	rfid
 
+#ifdef CONFIG_TRACEPOINTS
+opal_tracepoint_entry:
+	stdu	r1,-STACKFRAMESIZE(r1)
+	std	r0,STK_REG(R23)(r1)
+	std	r3,STK_REG(R24)(r1)
+	std	r4,STK_REG(R25)(r1)
+	std	r5,STK_REG(R26)(r1)
+	std	r6,STK_REG(R27)(r1)
+	std	r7,STK_REG(R28)(r1)
+	std	r8,STK_REG(R29)(r1)
+	std	r9,STK_REG(R30)(r1)
+	std	r10,STK_REG(R31)(r1)
+	mr	r3,r0
+	addi	r4,r1,STK_REG(R24)
+	bl	__trace_opal_entry
+	ld	r0,STK_REG(R23)(r1)
+	ld	r3,STK_REG(R24)(r1)
+	ld	r4,STK_REG(R25)(r1)
+	ld	r5,STK_REG(R26)(r1)
+	ld	r6,STK_REG(R27)(r1)
+	ld	r7,STK_REG(R28)(r1)
+	ld	r8,STK_REG(R29)(r1)
+	ld	r9,STK_REG(R30)(r1)
+	ld	r10,STK_REG(R31)(r1)
+	LOAD_REG_ADDR(r11,opal_tracepoint_return)
+	mfcr	r12
+	std	r11,16(r1)
+	stw	r12,8(r1)
+	std	r1,PACAR1(r13)
+	li	r11,0
+	mfmsr	r12
+	ori	r11,r11,MSR_EE
+	std	r12,PACASAVEDMSR(r13)
+	andc	r12,r12,r11
+	mtmsrd	r12,1
+	LOAD_REG_ADDR(r11,opal_return)
+	mtlr	r11
+	li	r11,MSR_DR|MSR_IR|MSR_LE
+	andc	r12,r12,r11
+	mtspr	SPRN_HSRR1,r12
+	LOAD_REG_ADDR(r11,opal)
+	ld	r12,8(r11)
+	ld	r2,0(r11)
+	mtspr	SPRN_HSRR0,r12
+	hrfid
+
+opal_tracepoint_return:
+	std	r3,STK_REG(R31)(r1)
+	mr	r4,r3
+	ld	r0,STK_REG(R23)(r1)
+	bl	__trace_opal_exit
+	ld	r3,STK_REG(R31)(r1)
+	addi	r1,r1,STACKFRAMESIZE
+	ld	r0,16(r1)
+	mtlr	r0
+	blr
+#endif
+
 OPAL_CALL(opal_invalid_call,			OPAL_INVALID_CALL);
 OPAL_CALL(opal_console_write,			OPAL_CONSOLE_WRITE);
 OPAL_CALL(opal_console_read,			OPAL_CONSOLE_READ);
@@ -86,6 +183,7 @@ OPAL_CALL(opal_get_xive,			OPAL_GET_XIVE
 OPAL_CALL(opal_register_exception_handler,	OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
 OPAL_CALL(opal_pci_eeh_freeze_status,		OPAL_PCI_EEH_FREEZE_STATUS);
 OPAL_CALL(opal_pci_eeh_freeze_clear,		OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_eeh_freeze_set,		OPAL_PCI_EEH_FREEZE_SET);
 OPAL_CALL(opal_pci_shpc,			OPAL_PCI_SHPC);
 OPAL_CALL(opal_pci_phb_mmio_enable,		OPAL_PCI_PHB_MMIO_ENABLE);
 OPAL_CALL(opal_pci_set_phb_mem_window,		OPAL_PCI_SET_PHB_MEM_WINDOW);
@@ -146,3 +244,6 @@ OPAL_CALL(opal_sync_host_reboot,		OPAL_S
 OPAL_CALL(opal_sensor_read,			OPAL_SENSOR_READ);
 OPAL_CALL(opal_get_param,			OPAL_GET_PARAM);
 OPAL_CALL(opal_set_param,			OPAL_SET_PARAM);
+OPAL_CALL(opal_handle_hmi,			OPAL_HANDLE_HMI);
+OPAL_CALL(opal_register_dump_region,		OPAL_REGISTER_DUMP_REGION);
+OPAL_CALL(opal_unregister_dump_region,		OPAL_UNREGISTER_DUMP_REGION);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-xscom.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-xscom.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/opal-xscom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/opal-xscom.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,4 +130,4 @@ static int opal_xscom_init(void)
 		scom_init(&opal_scom_controller);
 	return 0;
 }
-arch_initcall(opal_xscom_init);
+machine_arch_initcall(powernv, opal_xscom_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,61 +132,78 @@ static void pnv_pci_dump_p7ioc_diag_data
 
 	data = (struct OpalIoP7IOCPhbErrorData *)common;
 	pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n",
-		hose->global_number, common->version);
+		hose->global_number, be32_to_cpu(common->version));
 
 	if (data->brdgCtl)
 		pr_info("brdgCtl:     %08x\n",
-			data->brdgCtl);
+			be32_to_cpu(data->brdgCtl));
 	if (data->portStatusReg || data->rootCmplxStatus ||
 	    data->busAgentStatus)
 		pr_info("UtlSts:      %08x %08x %08x\n",
-			data->portStatusReg, data->rootCmplxStatus,
-			data->busAgentStatus);
+			be32_to_cpu(data->portStatusReg),
+			be32_to_cpu(data->rootCmplxStatus),
+			be32_to_cpu(data->busAgentStatus));
 	if (data->deviceStatus || data->slotStatus   ||
 	    data->linkStatus   || data->devCmdStatus ||
 	    data->devSecStatus)
 		pr_info("RootSts:     %08x %08x %08x %08x %08x\n",
-			data->deviceStatus, data->slotStatus,
-			data->linkStatus, data->devCmdStatus,
-			data->devSecStatus);
+			be32_to_cpu(data->deviceStatus),
+			be32_to_cpu(data->slotStatus),
+			be32_to_cpu(data->linkStatus),
+			be32_to_cpu(data->devCmdStatus),
+			be32_to_cpu(data->devSecStatus));
 	if (data->rootErrorStatus   || data->uncorrErrorStatus ||
 	    data->corrErrorStatus)
 		pr_info("RootErrSts:  %08x %08x %08x\n",
-			data->rootErrorStatus, data->uncorrErrorStatus,
-			data->corrErrorStatus);
+			be32_to_cpu(data->rootErrorStatus),
+			be32_to_cpu(data->uncorrErrorStatus),
+			be32_to_cpu(data->corrErrorStatus));
 	if (data->tlpHdr1 || data->tlpHdr2 ||
 	    data->tlpHdr3 || data->tlpHdr4)
 		pr_info("RootErrLog:  %08x %08x %08x %08x\n",
-			data->tlpHdr1, data->tlpHdr2,
-			data->tlpHdr3, data->tlpHdr4);
+			be32_to_cpu(data->tlpHdr1),
+			be32_to_cpu(data->tlpHdr2),
+			be32_to_cpu(data->tlpHdr3),
+			be32_to_cpu(data->tlpHdr4));
 	if (data->sourceId || data->errorClass ||
 	    data->correlator)
 		pr_info("RootErrLog1: %08x %016llx %016llx\n",
-			data->sourceId, data->errorClass,
-			data->correlator);
+			be32_to_cpu(data->sourceId),
+			be64_to_cpu(data->errorClass),
+			be64_to_cpu(data->correlator));
 	if (data->p7iocPlssr || data->p7iocCsr)
 		pr_info("PhbSts:      %016llx %016llx\n",
-			data->p7iocPlssr, data->p7iocCsr);
+			be64_to_cpu(data->p7iocPlssr),
+			be64_to_cpu(data->p7iocCsr));
 	if (data->lemFir)
 		pr_info("Lem:         %016llx %016llx %016llx\n",
-			data->lemFir, data->lemErrorMask,
-			data->lemWOF);
+			be64_to_cpu(data->lemFir),
+			be64_to_cpu(data->lemErrorMask),
+			be64_to_cpu(data->lemWOF));
 	if (data->phbErrorStatus)
 		pr_info("PhbErr:      %016llx %016llx %016llx %016llx\n",
-			data->phbErrorStatus, data->phbFirstErrorStatus,
-			data->phbErrorLog0, data->phbErrorLog1);
+			be64_to_cpu(data->phbErrorStatus),
+			be64_to_cpu(data->phbFirstErrorStatus),
+			be64_to_cpu(data->phbErrorLog0),
+			be64_to_cpu(data->phbErrorLog1));
 	if (data->mmioErrorStatus)
 		pr_info("OutErr:      %016llx %016llx %016llx %016llx\n",
-			data->mmioErrorStatus, data->mmioFirstErrorStatus,
-			data->mmioErrorLog0, data->mmioErrorLog1);
+			be64_to_cpu(data->mmioErrorStatus),
+			be64_to_cpu(data->mmioFirstErrorStatus),
+			be64_to_cpu(data->mmioErrorLog0),
+			be64_to_cpu(data->mmioErrorLog1));
 	if (data->dma0ErrorStatus)
 		pr_info("InAErr:      %016llx %016llx %016llx %016llx\n",
-			data->dma0ErrorStatus, data->dma0FirstErrorStatus,
-			data->dma0ErrorLog0, data->dma0ErrorLog1);
+			be64_to_cpu(data->dma0ErrorStatus),
+			be64_to_cpu(data->dma0FirstErrorStatus),
+			be64_to_cpu(data->dma0ErrorLog0),
+			be64_to_cpu(data->dma0ErrorLog1));
 	if (data->dma1ErrorStatus)
 		pr_info("InBErr:      %016llx %016llx %016llx %016llx\n",
-			data->dma1ErrorStatus, data->dma1FirstErrorStatus,
-			data->dma1ErrorLog0, data->dma1ErrorLog1);
+			be64_to_cpu(data->dma1ErrorStatus),
+			be64_to_cpu(data->dma1FirstErrorStatus),
+			be64_to_cpu(data->dma1ErrorLog0),
+			be64_to_cpu(data->dma1ErrorLog1));
 
 	for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
 		if ((data->pestA[i] >> 63) == 0 &&
@@ -194,7 +211,8 @@ static void pnv_pci_dump_p7ioc_diag_data
 			continue;
 
 		pr_info("PE[%3d] A/B: %016llx %016llx\n",
-			i, data->pestA[i], data->pestB[i]);
+			i, be64_to_cpu(data->pestA[i]),
+			be64_to_cpu(data->pestB[i]));
 	}
 }
 
@@ -319,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct p
 static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
 {
 	unsigned long flags, rc;
-	int has_diag;
+	int has_diag, ret = 0;
 
 	spin_lock_irqsave(&phb->lock, flags);
 
+	/* Fetch PHB diag-data */
 	rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
 					 PNV_PCI_DIAG_BUF_SIZE);
 	has_diag = (rc == OPAL_SUCCESS);
 
-	rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+	/* If PHB supports compound PE, to handle it */
+	if (phb->unfreeze_pe) {
+		ret = phb->unfreeze_pe(phb,
+				       pe_no,
 				       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
-	if (rc) {
-		pr_warning("PCI %d: Failed to clear EEH freeze state"
-			   " for PE#%d, err %ld\n",
-			   phb->hose->global_number, pe_no, rc);
-
-		/* For now, let's only display the diag buffer when we fail to clear
-		 * the EEH status. We'll do more sensible things later when we have
-		 * proper EEH support. We need to make sure we don't pollute ourselves
-		 * with the normal errors generated when probing empty slots
-		 */
-		if (has_diag)
-			pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
-		else
-			pr_warning("PCI %d: No diag data available\n",
-				   phb->hose->global_number);
+	} else {
+		rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+					     pe_no,
+					     OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+		if (rc) {
+			pr_warn("%s: Failure %ld clearing frozen "
+				"PHB#%x-PE#%x\n",
+				__func__, rc, phb->hose->global_number,
+				pe_no);
+			ret = -EIO;
+		}
 	}
 
+	/*
+	 * For now, let's only display the diag buffer when we fail to clear
+	 * the EEH status. We'll do more sensible things later when we have
+	 * proper EEH support. We need to make sure we don't pollute ourselves
+	 * with the normal errors generated when probing empty slots
+	 */
+	if (has_diag && ret)
+		pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
+
 	spin_unlock_irqrestore(&phb->lock, flags);
 }
 
 static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
 				     struct device_node *dn)
 {
-	s64	rc;
 	u8	fstate;
 	__be16	pcierr;
-	u32	pe_no;
+	int	pe_no;
+	s64	rc;
 
 	/*
 	 * Get the PE#. During the PCI probe stage, we might not
@@ -370,20 +397,42 @@ static void pnv_pci_config_check_eeh(str
 			pe_no = phb->ioda.reserved_pe;
 	}
 
-	/* Read freeze status */
-	rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
-					NULL);
-	if (rc) {
-		pr_warning("%s: Can't read EEH status (PE#%d) for "
-			   "%s, err %lld\n",
-			   __func__, pe_no, dn->full_name, rc);
-		return;
+	/*
+	 * Fetch frozen state. If the PHB support compound PE,
+	 * we need handle that case.
+	 */
+	if (phb->get_pe_state) {
+		fstate = phb->get_pe_state(phb, pe_no);
+	} else {
+		rc = opal_pci_eeh_freeze_status(phb->opal_id,
+						pe_no,
+						&fstate,
+						&pcierr,
+						NULL);
+		if (rc) {
+			pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n",
+				__func__, rc, phb->hose->global_number, pe_no);
+			return;
+		}
 	}
+
 	cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
 		(PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn),
 		pe_no, fstate);
-	if (fstate != 0)
+
+	/* Clear the frozen state if applicable */
+	if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
+	    fstate == OPAL_EEH_STOPPED_DMA_FREEZE  ||
+	    fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) {
+		/*
+		 * If PHB supports compound PE, freeze it for
+		 * consistency.
+		 */
+		if (phb->freeze_pe)
+			phb->freeze_pe(phb, pe_no);
+
 		pnv_pci_handle_eeh_config(phb, pe_no);
+	}
 }
 
 int pnv_pci_cfg_read(struct device_node *dn,
@@ -564,10 +613,11 @@ static int pnv_tce_build(struct iommu_ta
 		proto_tce |= TCE_PCI_WRITE;
 
 	tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
-	rpn = __pa(uaddr) >> TCE_SHIFT;
+	rpn = __pa(uaddr) >> tbl->it_page_shift;
 
 	while (npages--)
-		*(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT));
+		*(tcep++) = cpu_to_be64(proto_tce |
+				(rpn++ << tbl->it_page_shift));
 
 	/* Some implementations won't cache invalid TCEs and thus may not
 	 * need that flush. We'll probably turn it_type into a bit mask
@@ -627,11 +677,11 @@ static void pnv_tce_free_rm(struct iommu
 
 void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 			       void *tce_mem, u64 tce_size,
-			       u64 dma_offset)
+			       u64 dma_offset, unsigned page_shift)
 {
 	tbl->it_blocksize = 16;
 	tbl->it_base = (unsigned long)tce_mem;
-	tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
+	tbl->it_page_shift = page_shift;
 	tbl->it_offset = dma_offset >> tbl->it_page_shift;
 	tbl->it_index = 0;
 	tbl->it_size = tce_size >> 3;
@@ -656,7 +706,7 @@ static struct iommu_table *pnv_pci_setup
 	if (WARN_ON(!tbl))
 		return NULL;
 	pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
-				  be32_to_cpup(sizep), 0);
+				  be32_to_cpup(sizep), 0, IOMMU_PAGE_SHIFT_4K);
 	iommu_init_table(tbl, hose->node);
 	iommu_register_group(tbl, pci_domain_nr(hose->bus), 0);
 
@@ -842,5 +892,4 @@ static int __init tce_iommu_bus_notifier
 	bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
 	return 0;
 }
-
-subsys_initcall_sync(tce_iommu_bus_notifier_init);
+machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci.h linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci.h
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,8 @@ enum pnv_phb_model {
 #define PNV_IODA_PE_DEV		(1 << 0)	/* PE has single PCI device	*/
 #define PNV_IODA_PE_BUS		(1 << 1)	/* PE has primary PCI bus	*/
 #define PNV_IODA_PE_BUS_ALL	(1 << 2)	/* PE has subordinate buses	*/
+#define PNV_IODA_PE_MASTER	(1 << 3)	/* Master PE in compound case	*/
+#define PNV_IODA_PE_SLAVE	(1 << 4)	/* Slave PE in compound case	*/
 
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_phb;
@@ -64,6 +66,10 @@ struct pnv_ioda_pe {
 	 */
 	int			mve_number;
 
+	/* PEs in compound case */
+	struct pnv_ioda_pe	*master;
+	struct list_head	slaves;
+
 	/* Link in list of PE#s */
 	struct list_head	dma_link;
 	struct list_head	list;
@@ -119,6 +125,12 @@ struct pnv_phb {
 	void (*fixup_phb)(struct pci_controller *hose);
 	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
 	void (*shutdown)(struct pnv_phb *phb);
+	int (*init_m64)(struct pnv_phb *phb);
+	void (*alloc_m64_pe)(struct pnv_phb *phb);
+	int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all);
+	int (*get_pe_state)(struct pnv_phb *phb, int pe_no);
+	void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
+	int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt);
 
 	union {
 		struct {
@@ -129,9 +141,20 @@ struct pnv_phb {
 			/* Global bridge info */
 			unsigned int		total_pe;
 			unsigned int		reserved_pe;
+
+			/* 32-bit MMIO window */
 			unsigned int		m32_size;
 			unsigned int		m32_segsize;
 			unsigned int		m32_pci_base;
+
+			/* 64-bit MMIO window */
+			unsigned int		m64_bar_idx;
+			unsigned long		m64_size;
+			unsigned long		m64_segsize;
+			unsigned long		m64_base;
+			unsigned long		m64_bar_alloc;
+
+			/* IO ports */
 			unsigned int		io_size;
 			unsigned int		io_segsize;
 			unsigned int		io_pci_base;
@@ -198,7 +221,7 @@ int pnv_pci_cfg_write(struct device_node
 		      int where, int size, u32 val);
 extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 				      void *tce_mem, u64 tce_size,
-				      u64 dma_offset);
+				      u64 dma_offset, unsigned page_shift);
 extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
 extern void pnv_pci_init_ioda_hub(struct device_node *np);
 extern void pnv_pci_init_ioda2_phb(struct device_node *np);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci-ioda.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include <asm/tce.h>
 #include <asm/xics.h>
 #include <asm/debug.h>
+#include <asm/firmware.h>
 
 #include "powernv.h"
 #include "pci.h"
@@ -82,6 +83,12 @@ static inline void __raw_rm_writeq(u64 v
 		: : "r" (val), "r" (paddr) : "memory");
 }
 
+static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
+{
+	return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
+		(IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
+}
+
 static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
 	unsigned long pe;
@@ -106,6 +113,380 @@ static void pnv_ioda_free_pe(struct pnv_
 	clear_bit(pe, phb->ioda.pe_alloc);
 }
 
+/* The default M64 BAR is shared by all PEs */
+static int pnv_ioda2_init_m64(struct pnv_phb *phb)
+{
+	const char *desc;
+	struct resource *r;
+	s64 rc;
+
+	/* Configure the default M64 BAR */
+	rc = opal_pci_set_phb_mem_window(phb->opal_id,
+					 OPAL_M64_WINDOW_TYPE,
+					 phb->ioda.m64_bar_idx,
+					 phb->ioda.m64_base,
+					 0, /* unused */
+					 phb->ioda.m64_size);
+	if (rc != OPAL_SUCCESS) {
+		desc = "configuring";
+		goto fail;
+	}
+
+	/* Enable the default M64 BAR */
+	rc = opal_pci_phb_mmio_enable(phb->opal_id,
+				      OPAL_M64_WINDOW_TYPE,
+				      phb->ioda.m64_bar_idx,
+				      OPAL_ENABLE_M64_SPLIT);
+	if (rc != OPAL_SUCCESS) {
+		desc = "enabling";
+		goto fail;
+	}
+
+	/* Mark the M64 BAR assigned */
+	set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc);
+
+	/*
+	 * Strip off the segment used by the reserved PE, which is
+	 * expected to be 0 or last one of PE capabicity.
+	 */
+	r = &phb->hose->mem_resources[1];
+	if (phb->ioda.reserved_pe == 0)
+		r->start += phb->ioda.m64_segsize;
+	else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1))
+		r->end -= phb->ioda.m64_segsize;
+	else
+		pr_warn("  Cannot strip M64 segment for reserved PE#%d\n",
+			phb->ioda.reserved_pe);
+
+	return 0;
+
+fail:
+	pr_warn("  Failure %lld %s M64 BAR#%d\n",
+		rc, desc, phb->ioda.m64_bar_idx);
+	opal_pci_phb_mmio_enable(phb->opal_id,
+				 OPAL_M64_WINDOW_TYPE,
+				 phb->ioda.m64_bar_idx,
+				 OPAL_DISABLE_M64);
+	return -EIO;
+}
+
+static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb)
+{
+	resource_size_t sgsz = phb->ioda.m64_segsize;
+	struct pci_dev *pdev;
+	struct resource *r;
+	int base, step, i;
+
+	/*
+	 * Root bus always has full M64 range and root port has
+	 * M64 range used in reality. So we're checking root port
+	 * instead of root bus.
+	 */
+	list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) {
+		for (i = PCI_BRIDGE_RESOURCES;
+		     i <= PCI_BRIDGE_RESOURCE_END; i++) {
+			r = &pdev->resource[i];
+			if (!r->parent ||
+			    !pnv_pci_is_mem_pref_64(r->flags))
+				continue;
+
+			base = (r->start - phb->ioda.m64_base) / sgsz;
+			for (step = 0; step < resource_size(r) / sgsz; step++)
+				set_bit(base + step, phb->ioda.pe_alloc);
+		}
+	}
+}
+
+static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb,
+				 struct pci_bus *bus, int all)
+{
+	resource_size_t segsz = phb->ioda.m64_segsize;
+	struct pci_dev *pdev;
+	struct resource *r;
+	struct pnv_ioda_pe *master_pe, *pe;
+	unsigned long size, *pe_alloc;
+	bool found;
+	int start, i, j;
+
+	/* Root bus shouldn't use M64 */
+	if (pci_is_root_bus(bus))
+		return IODA_INVALID_PE;
+
+	/* We support only one M64 window on each bus */
+	found = false;
+	pci_bus_for_each_resource(bus, r, i) {
+		if (r && r->parent &&
+		    pnv_pci_is_mem_pref_64(r->flags)) {
+			found = true;
+			break;
+		}
+	}
+
+	/* No M64 window found ? */
+	if (!found)
+		return IODA_INVALID_PE;
+
+	/* Allocate bitmap */
+	size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
+	pe_alloc = kzalloc(size, GFP_KERNEL);
+	if (!pe_alloc) {
+		pr_warn("%s: Out of memory !\n",
+			__func__);
+		return IODA_INVALID_PE;
+	}
+
+	/*
+	 * Figure out reserved PE numbers by the PE
+	 * the its child PEs.
+	 */
+	start = (r->start - phb->ioda.m64_base) / segsz;
+	for (i = 0; i < resource_size(r) / segsz; i++)
+		set_bit(start + i, pe_alloc);
+
+	if (all)
+		goto done;
+
+	/*
+	 * If the PE doesn't cover all subordinate buses,
+	 * we need subtract from reserved PEs for children.
+	 */
+	list_for_each_entry(pdev, &bus->devices, bus_list) {
+		if (!pdev->subordinate)
+			continue;
+
+		pci_bus_for_each_resource(pdev->subordinate, r, i) {
+			if (!r || !r->parent ||
+			    !pnv_pci_is_mem_pref_64(r->flags))
+				continue;
+
+			start = (r->start - phb->ioda.m64_base) / segsz;
+			for (j = 0; j < resource_size(r) / segsz ; j++)
+				clear_bit(start + j, pe_alloc);
+                }
+        }
+
+	/*
+	 * the current bus might not own M64 window and that's all
+	 * contributed by its child buses. For the case, we needn't
+	 * pick M64 dependent PE#.
+	 */
+	if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) {
+		kfree(pe_alloc);
+		return IODA_INVALID_PE;
+	}
+
+	/*
+	 * Figure out the master PE and put all slave PEs to master
+	 * PE's list to form compound PE.
+	 */
+done:
+	master_pe = NULL;
+	i = -1;
+	while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) <
+		phb->ioda.total_pe) {
+		pe = &phb->ioda.pe_array[i];
+		pe->phb = phb;
+		pe->pe_number = i;
+
+		if (!master_pe) {
+			pe->flags |= PNV_IODA_PE_MASTER;
+			INIT_LIST_HEAD(&pe->slaves);
+			master_pe = pe;
+		} else {
+			pe->flags |= PNV_IODA_PE_SLAVE;
+			pe->master = master_pe;
+			list_add_tail(&pe->list, &master_pe->slaves);
+		}
+	}
+
+	kfree(pe_alloc);
+	return master_pe->pe_number;
+}
+
+static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
+{
+	struct pci_controller *hose = phb->hose;
+	struct device_node *dn = hose->dn;
+	struct resource *res;
+	const u32 *r;
+	u64 pci_addr;
+
+	if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
+		pr_info("  Firmware too old to support M64 window\n");
+		return;
+	}
+
+	r = of_get_property(dn, "ibm,opal-m64-window", NULL);
+	if (!r) {
+		pr_info("  No <ibm,opal-m64-window> on %s\n",
+			dn->full_name);
+		return;
+	}
+
+	/* FIXME: Support M64 for P7IOC */
+	if (phb->type != PNV_PHB_IODA2) {
+		pr_info("  Not support M64 window\n");
+		return;
+	}
+
+	res = &hose->mem_resources[1];
+	res->start = of_translate_address(dn, r + 2);
+	res->end = res->start + of_read_number(r + 4, 2) - 1;
+	res->flags = (IORESOURCE_MEM | IORESOURCE_MEM_64 | IORESOURCE_PREFETCH);
+	pci_addr = of_read_number(r, 2);
+	hose->mem_offset[1] = res->start - pci_addr;
+
+	phb->ioda.m64_size = resource_size(res);
+	phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe;
+	phb->ioda.m64_base = pci_addr;
+
+	/* Use last M64 BAR to cover M64 window */
+	phb->ioda.m64_bar_idx = 15;
+	phb->init_m64 = pnv_ioda2_init_m64;
+	phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe;
+	phb->pick_m64_pe = pnv_ioda2_pick_m64_pe;
+}
+
+static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no)
+{
+	struct pnv_ioda_pe *pe = &phb->ioda.pe_array[pe_no];
+	struct pnv_ioda_pe *slave;
+	s64 rc;
+
+	/* Fetch master PE */
+	if (pe->flags & PNV_IODA_PE_SLAVE) {
+		pe = pe->master;
+		WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+		pe_no = pe->pe_number;
+	}
+
+	/* Freeze master PE */
+	rc = opal_pci_eeh_freeze_set(phb->opal_id,
+				     pe_no,
+				     OPAL_EEH_ACTION_SET_FREEZE_ALL);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n",
+			__func__, rc, phb->hose->global_number, pe_no);
+		return;
+	}
+
+	/* Freeze slave PEs */
+	if (!(pe->flags & PNV_IODA_PE_MASTER))
+		return;
+
+	list_for_each_entry(slave, &pe->slaves, list) {
+		rc = opal_pci_eeh_freeze_set(phb->opal_id,
+					     slave->pe_number,
+					     OPAL_EEH_ACTION_SET_FREEZE_ALL);
+		if (rc != OPAL_SUCCESS)
+			pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n",
+				__func__, rc, phb->hose->global_number,
+				slave->pe_number);
+	}
+}
+
+int pnv_ioda_unfreeze_pe(struct pnv_phb *phb, int pe_no, int opt)
+{
+	struct pnv_ioda_pe *pe, *slave;
+	s64 rc;
+
+	/* Find master PE */
+	pe = &phb->ioda.pe_array[pe_no];
+	if (pe->flags & PNV_IODA_PE_SLAVE) {
+		pe = pe->master;
+		WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+		pe_no = pe->pe_number;
+	}
+
+	/* Clear frozen state for master PE */
+	rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, opt);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n",
+			__func__, rc, opt, phb->hose->global_number, pe_no);
+		return -EIO;
+	}
+
+	if (!(pe->flags & PNV_IODA_PE_MASTER))
+		return 0;
+
+	/* Clear frozen state for slave PEs */
+	list_for_each_entry(slave, &pe->slaves, list) {
+		rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+					     slave->pe_number,
+					     opt);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n",
+				__func__, rc, opt, phb->hose->global_number,
+				slave->pe_number);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no)
+{
+	struct pnv_ioda_pe *slave, *pe;
+	u8 fstate, state;
+	__be16 pcierr;
+	s64 rc;
+
+	/* Sanity check on PE number */
+	if (pe_no < 0 || pe_no >= phb->ioda.total_pe)
+		return OPAL_EEH_STOPPED_PERM_UNAVAIL;
+
+	/*
+	 * Fetch the master PE and the PE instance might be
+	 * not initialized yet.
+	 */
+	pe = &phb->ioda.pe_array[pe_no];
+	if (pe->flags & PNV_IODA_PE_SLAVE) {
+		pe = pe->master;
+		WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+		pe_no = pe->pe_number;
+	}
+
+	/* Check the master PE */
+	rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no,
+					&state, &pcierr, NULL);
+	if (rc != OPAL_SUCCESS) {
+		pr_warn("%s: Failure %lld getting "
+			"PHB#%x-PE#%x state\n",
+			__func__, rc,
+			phb->hose->global_number, pe_no);
+		return OPAL_EEH_STOPPED_TEMP_UNAVAIL;
+	}
+
+	/* Check the slave PE */
+	if (!(pe->flags & PNV_IODA_PE_MASTER))
+		return state;
+
+	list_for_each_entry(slave, &pe->slaves, list) {
+		rc = opal_pci_eeh_freeze_status(phb->opal_id,
+						slave->pe_number,
+						&fstate,
+						&pcierr,
+						NULL);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("%s: Failure %lld getting "
+				"PHB#%x-PE#%x state\n",
+				__func__, rc,
+				phb->hose->global_number, slave->pe_number);
+			return OPAL_EEH_STOPPED_TEMP_UNAVAIL;
+		}
+
+		/*
+		 * Override the result based on the ascending
+		 * priority.
+		 */
+		if (fstate > state)
+			state = fstate;
+	}
+
+	return state;
+}
+
 /* Currently those 2 are only used when MSIs are enabled, this will change
  * but in the meantime, we need to protect them to avoid warnings
  */
@@ -363,9 +744,16 @@ static void pnv_ioda_setup_bus_PE(struct
 	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct pnv_phb *phb = hose->private_data;
 	struct pnv_ioda_pe *pe;
-	int pe_num;
+	int pe_num = IODA_INVALID_PE;
+
+	/* Check if PE is determined by M64 */
+	if (phb->pick_m64_pe)
+		pe_num = phb->pick_m64_pe(phb, bus, all);
+
+	/* The PE number isn't pinned by M64 */
+	if (pe_num == IODA_INVALID_PE)
+		pe_num = pnv_ioda_alloc_pe(phb);
 
-	pe_num = pnv_ioda_alloc_pe(phb);
 	if (pe_num == IODA_INVALID_PE) {
 		pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
 			__func__, pci_domain_nr(bus), bus->number);
@@ -373,7 +761,7 @@ static void pnv_ioda_setup_bus_PE(struct
 	}
 
 	pe = &phb->ioda.pe_array[pe_num];
-	pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
+	pe->flags |= (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
 	pe->pbus = bus;
 	pe->pdev = NULL;
 	pe->tce32_seg = -1;
@@ -441,8 +829,15 @@ static void pnv_ioda_setup_PEs(struct pc
 static void pnv_pci_ioda_setup_PEs(void)
 {
 	struct pci_controller *hose, *tmp;
+	struct pnv_phb *phb;
 
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		phb = hose->private_data;
+
+		/* M64 layout might affect PE allocation */
+		if (phb->alloc_m64_pe)
+			phb->alloc_m64_pe(phb);
+
 		pnv_ioda_setup_PEs(hose->bus);
 	}
 }
@@ -462,7 +857,7 @@ static void pnv_pci_ioda_dma_dev_setup(s
 
 	pe = &phb->ioda.pe_array[pdn->pe_number];
 	WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops);
-	set_iommu_table_base(&pdev->dev, &pe->tce32_table);
+	set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
 }
 
 static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb,
@@ -491,17 +886,26 @@ static int pnv_pci_ioda_dma_set_mask(str
 		set_dma_ops(&pdev->dev, &dma_iommu_ops);
 		set_iommu_table_base(&pdev->dev, &pe->tce32_table);
 	}
+	*pdev->dev.dma_mask = dma_mask;
 	return 0;
 }
 
-static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
+static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
+				   struct pci_bus *bus,
+				   bool add_to_iommu_group)
 {
 	struct pci_dev *dev;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table);
+		if (add_to_iommu_group)
+			set_iommu_table_base_and_group(&dev->dev,
+						       &pe->tce32_table);
+		else
+			set_iommu_table_base(&dev->dev, &pe->tce32_table);
+
 		if (dev->subordinate)
-			pnv_ioda_setup_bus_dma(pe, dev->subordinate);
+			pnv_ioda_setup_bus_dma(pe, dev->subordinate,
+					       add_to_iommu_group);
 	}
 }
 
@@ -513,15 +917,16 @@ static void pnv_pci_ioda1_tce_invalidate
 		(__be64 __iomem *)pe->tce_inval_reg_phys :
 		(__be64 __iomem *)tbl->it_index;
 	unsigned long start, end, inc;
+	const unsigned shift = tbl->it_page_shift;
 
 	start = __pa(startp);
 	end = __pa(endp);
 
 	/* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */
 	if (tbl->it_busno) {
-		start <<= 12;
-		end <<= 12;
-		inc = 128 << 12;
+		start <<= shift;
+		end <<= shift;
+		inc = 128ull << shift;
 		start |= tbl->it_busno;
 		end |= tbl->it_busno;
 	} else if (tbl->it_type & TCE_PCI_SWINV_PAIR) {
@@ -559,18 +964,19 @@ static void pnv_pci_ioda2_tce_invalidate
 	__be64 __iomem *invalidate = rm ?
 		(__be64 __iomem *)pe->tce_inval_reg_phys :
 		(__be64 __iomem *)tbl->it_index;
+	const unsigned shift = tbl->it_page_shift;
 
 	/* We'll invalidate DMA address in PE scope */
-	start = 0x2ul << 60;
+	start = 0x2ull << 60;
 	start |= (pe->pe_number & 0xFF);
 	end = start;
 
 	/* Figure out the start, end and step */
 	inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64));
-	start |= (inc << 12);
+	start |= (inc << shift);
 	inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64));
-	end |= (inc << 12);
-	inc = (0x1ul << 12);
+	end |= (inc << shift);
+	inc = (0x1ull << shift);
 	mb();
 
 	while (start <= end) {
@@ -654,7 +1060,7 @@ static void pnv_pci_ioda_setup_dma_pe(st
 	/* Setup linux iommu table */
 	tbl = &pe->tce32_table;
 	pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs,
-				  base << 28);
+				  base << 28, IOMMU_PAGE_SHIFT_4K);
 
 	/* OPAL variant of P7IOC SW invalidated TCEs */
 	swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
@@ -677,7 +1083,7 @@ static void pnv_pci_ioda_setup_dma_pe(st
 	if (pe->pdev)
 		set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
 	else
-		pnv_ioda_setup_bus_dma(pe, pe->pbus);
+		pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
 
 	return;
  fail:
@@ -713,11 +1119,15 @@ static void pnv_pci_ioda2_set_bypass(str
 						     0);
 
 		/*
-		 * We might want to reset the DMA ops of all devices on
-		 * this PE. However in theory, that shouldn't be necessary
-		 * as this is used for VFIO/KVM pass-through and the device
-		 * hasn't yet been returned to its kernel driver
+		 * EEH needs the mapping between IOMMU table and group
+		 * of those VFIO/KVM pass-through devices. We can postpone
+		 * resetting DMA ops until the DMA mask is configured in
+		 * host side.
 		 */
+		if (pe->pdev)
+			set_iommu_table_base(&pe->pdev->dev, tbl);
+		else
+			pnv_ioda_setup_bus_dma(pe, pe->pbus, false);
 	}
 	if (rc)
 		pe_err(pe, "OPAL error %lld configuring bypass window\n", rc);
@@ -784,7 +1194,8 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 
 	/* Setup linux iommu table */
 	tbl = &pe->tce32_table;
-	pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0);
+	pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0,
+			IOMMU_PAGE_SHIFT_4K);
 
 	/* OPAL variant of PHB3 invalidated TCEs */
 	swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
@@ -805,7 +1216,7 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 	if (pe->pdev)
 		set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
 	else
-		pnv_ioda_setup_bus_dma(pe, pe->pbus);
+		pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
 
 	/* Also create a bypass window */
 	pnv_pci_ioda2_setup_bypass_pe(phb, pe);
@@ -1055,9 +1466,6 @@ static void pnv_ioda_setup_pe_seg(struct
 				index++;
 			}
 		} else if (res->flags & IORESOURCE_MEM) {
-			/* WARNING: Assumes M32 is mem region 0 in PHB. We need to
-			 * harden that algorithm when we start supporting M64
-			 */
 			region.start = res->start -
 				       hose->mem_offset[0] -
 				       phb->ioda.m32_pci_base;
@@ -1141,9 +1549,8 @@ static void pnv_pci_ioda_fixup(void)
 	pnv_pci_ioda_create_dbgfs();
 
 #ifdef CONFIG_EEH
-	eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
-	eeh_addr_cache_build();
 	eeh_init();
+	eeh_addr_cache_build();
 #endif
 }
 
@@ -1178,7 +1585,10 @@ static resource_size_t pnv_pci_window_al
 		bridge = bridge->bus->self;
 	}
 
-	/* We need support prefetchable memory window later */
+	/* We fail back to M32 if M64 isn't supported */
+	if (phb->ioda.m64_segsize &&
+	    pnv_pci_is_mem_pref_64(type))
+		return phb->ioda.m64_segsize;
 	if (type & IORESOURCE_MEM)
 		return phb->ioda.m32_segsize;
 
@@ -1299,6 +1709,10 @@ void __init pnv_pci_init_ioda_phb(struct
 	prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL);
 	if (prop32)
 		phb->ioda.reserved_pe = be32_to_cpup(prop32);
+
+	/* Parse 64-bit MMIO range */
+	pnv_ioda_parse_m64_window(phb);
+
 	phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
 	/* FW Has already off top 64k of M32 space (MSI space) */
 	phb->ioda.m32_size += 0x10000;
@@ -1334,14 +1748,6 @@ void __init pnv_pci_init_ioda_phb(struct
 	/* Calculate how many 32-bit TCE segments we have */
 	phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28;
 
-	/* Clear unusable m64 */
-	hose->mem_resources[1].flags = 0;
-	hose->mem_resources[1].start = 0;
-	hose->mem_resources[1].end = 0;
-	hose->mem_resources[2].flags = 0;
-	hose->mem_resources[2].start = 0;
-	hose->mem_resources[2].end = 0;
-
 #if 0 /* We should really do that ... */
 	rc = opal_pci_set_phb_mem_window(opal->phb_id,
 					 window_type,
@@ -1351,14 +1757,21 @@ void __init pnv_pci_init_ioda_phb(struct
 					 segment_size);
 #endif
 
-	pr_info("  %d (%d) PE's M32: 0x%x [segment=0x%x]"
-		" IO: 0x%x [segment=0x%x]\n",
-		phb->ioda.total_pe,
-		phb->ioda.reserved_pe,
-		phb->ioda.m32_size, phb->ioda.m32_segsize,
-		phb->ioda.io_size, phb->ioda.io_segsize);
+	pr_info("  %03d (%03d) PE's M32: 0x%x [segment=0x%x]\n",
+		phb->ioda.total_pe, phb->ioda.reserved_pe,
+		phb->ioda.m32_size, phb->ioda.m32_segsize);
+	if (phb->ioda.m64_size)
+		pr_info("                 M64: 0x%lx [segment=0x%lx]\n",
+			phb->ioda.m64_size, phb->ioda.m64_segsize);
+	if (phb->ioda.io_size)
+		pr_info("                  IO: 0x%x [segment=0x%x]\n",
+			phb->ioda.io_size, phb->ioda.io_segsize);
+
 
 	phb->hose->ops = &pnv_pci_ops;
+	phb->get_pe_state = pnv_ioda_get_pe_state;
+	phb->freeze_pe = pnv_ioda_freeze_pe;
+	phb->unfreeze_pe = pnv_ioda_unfreeze_pe;
 #ifdef CONFIG_EEH
 	phb->eeh_ops = &ioda_eeh_ops;
 #endif
@@ -1404,6 +1817,10 @@ void __init pnv_pci_init_ioda_phb(struct
 		ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
 		ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
 	}
+
+	/* Configure M64 window */
+	if (phb->init_m64 && phb->init_m64(phb))
+		hose->mem_resources[1].flags = 0;
 }
 
 void __init pnv_pci_init_ioda2_phb(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c	2014-09-28 17:29:07.000000000 -0400
@@ -172,7 +172,8 @@ static void __init pnv_pci_init_p5ioc2_p
 	/* Setup TCEs */
 	phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
 	pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
-				  tce_mem, tce_size, 0);
+				  tce_mem, tce_size, 0,
+				  IOMMU_PAGE_SHIFT_4K);
 }
 
 void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/rng.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/rng.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/rng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/rng.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,4 +123,4 @@ static __init int rng_init(void)
 
 	return 0;
 }
-subsys_initcall(rng_init);
+machine_subsys_initcall(powernv, rng_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/powernv/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/powernv/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -264,6 +264,8 @@ static void __init pnv_setup_machdep_opa
 	ppc_md.halt = pnv_halt;
 	ppc_md.machine_check_exception = opal_machine_check;
 	ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
+	ppc_md.hmi_exception_early = opal_hmi_exception_early;
+	ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
 }
 
 #ifdef CONFIG_PPC_POWERNV_RTAS
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/dlpar.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/dlpar.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/dlpar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/dlpar.c	2014-09-28 17:29:07.000000000 -0400
@@ -400,10 +400,10 @@ out:
 static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
 {
 	struct device_node *dn, *parent;
-	unsigned long drc_index;
+	u32 drc_index;
 	int rc;
 
-	rc = strict_strtoul(buf, 0, &drc_index);
+	rc = kstrtou32(buf, 0, &drc_index);
 	if (rc)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/dtl.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/dtl.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/dtl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/dtl.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@
 #include <asm/lppaca.h>
 #include <asm/debug.h>
 #include <asm/plpar_wrappers.h>
+#include <asm/machdep.h>
 
 struct dtl {
 	struct dtl_entry	*buf;
@@ -391,4 +392,4 @@ err_remove_dir:
 err:
 	return rc;
 }
-arch_initcall(dtl_init);
+machine_arch_initcall(pseries, dtl_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2014-09-28 17:29:07.000000000 -0400
@@ -89,26 +89,26 @@ static int pseries_eeh_init(void)
 	 * of domain/bus/slot/function for EEH RTAS operations.
 	 */
 	if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",
+		pr_warn("%s: RTAS service <ibm,set-eeh-option> invalid\n",
 			__func__);
 		return -EINVAL;
 	} else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n",
+		pr_warn("%s: RTAS service <ibm,set-slot-reset> invalid\n",
 			__func__);
 		return -EINVAL;
 	} else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
 		   ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and "
+		pr_warn("%s: RTAS service <ibm,read-slot-reset-state2> and "
 			"<ibm,read-slot-reset-state> invalid\n",
 			__func__);
 		return -EINVAL;
 	} else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",
+		pr_warn("%s: RTAS service <ibm,slot-error-detail> invalid\n",
 			__func__);
 		return -EINVAL;
 	} else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
 		   ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: RTAS service <ibm,configure-pe> and "
+		pr_warn("%s: RTAS service <ibm,configure-pe> and "
 			"<ibm,configure-bridge> invalid\n",
 			__func__);
 		return -EINVAL;
@@ -118,17 +118,17 @@ static int pseries_eeh_init(void)
 	spin_lock_init(&slot_errbuf_lock);
 	eeh_error_buf_size = rtas_token("rtas-error-log-max");
 	if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {
-		pr_warning("%s: unknown EEH error log size\n",
+		pr_warn("%s: unknown EEH error log size\n",
 			__func__);
 		eeh_error_buf_size = 1024;
 	} else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
-		pr_warning("%s: EEH error log size %d exceeds the maximal %d\n",
+		pr_warn("%s: EEH error log size %d exceeds the maximal %d\n",
 			__func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX);
 		eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
 	}
 
 	/* Set EEH probe mode */
-	eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE);
+	eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG);
 
 	return 0;
 }
@@ -270,7 +270,7 @@ static void *pseries_eeh_of_probe(struct
 	/* Retrieve the device address */
 	regs = of_get_property(dn, "reg", NULL);
 	if (!regs) {
-		pr_warning("%s: OF node property %s::reg not found\n",
+		pr_warn("%s: OF node property %s::reg not found\n",
 			__func__, dn->full_name);
 		return NULL;
 	}
@@ -297,7 +297,7 @@ static void *pseries_eeh_of_probe(struct
 			enable = 1;
 
 		if (enable) {
-			eeh_set_enable(true);
+			eeh_add_flag(EEH_ENABLED);
 			eeh_add_to_parent_pe(edev);
 
 			pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
@@ -398,7 +398,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_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+			pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
 				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
@@ -411,7 +411,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_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+			pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
 				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
@@ -584,17 +584,17 @@ static int pseries_eeh_wait_state(struct
 			return ret;
 
 		if (max_wait <= 0) {
-			pr_warning("%s: Timeout when getting PE's state (%d)\n",
+			pr_warn("%s: Timeout when getting PE's state (%d)\n",
 				__func__, max_wait);
 			return EEH_STATE_NOT_SUPPORT;
 		}
 
 		if (mwait <= 0) {
-			pr_warning("%s: Firmware returned bad wait value %d\n",
+			pr_warn("%s: Firmware returned bad wait value %d\n",
 				__func__, mwait);
 			mwait = EEH_STATE_MIN_WAIT_TIME;
 		} else if (mwait > EEH_STATE_MAX_WAIT_TIME) {
-			pr_warning("%s: Firmware returned too long wait value %d\n",
+			pr_warn("%s: Firmware returned too long wait value %d\n",
 				__func__, mwait);
 			mwait = EEH_STATE_MAX_WAIT_TIME;
 		}
@@ -675,7 +675,7 @@ static int pseries_eeh_configure_bridge(
 	}
 
 	if (ret)
-		pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+		pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
 			__func__, pe->phb->global_number, pe->addr, ret);
 
 	return ret;
@@ -743,10 +743,7 @@ static struct eeh_ops pseries_eeh_ops =
  */
 static int __init eeh_pseries_init(void)
 {
-	int ret = -EINVAL;
-
-	if (!machine_is(pseries))
-		return ret;
+	int ret;
 
 	ret = eeh_ops_register(&pseries_eeh_ops);
 	if (!ret)
@@ -757,5 +754,4 @@ static int __init eeh_pseries_init(void)
 
 	return ret;
 }
-
-early_initcall(eeh_pseries_init);
+machine_early_initcall(pseries, eeh_pseries_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,7 +113,7 @@ out:
 static int pseries_remove_mem_node(struct device_node *np)
 {
 	const char *type;
-	const unsigned int *regs;
+	const __be32 *regs;
 	unsigned long base;
 	unsigned int lmb_size;
 	int ret = -EINVAL;
@@ -132,8 +132,8 @@ static int pseries_remove_mem_node(struc
 	if (!regs)
 		return ret;
 
-	base = *(unsigned long *)regs;
-	lmb_size = regs[3];
+	base = be64_to_cpu(*(unsigned long *)regs);
+	lmb_size = be32_to_cpu(regs[3]);
 
 	pseries_remove_memblock(base, lmb_size);
 	return 0;
@@ -146,14 +146,14 @@ static inline int pseries_remove_membloc
 }
 static inline int pseries_remove_mem_node(struct device_node *np)
 {
-	return -EOPNOTSUPP;
+	return 0;
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
 static int pseries_add_mem_node(struct device_node *np)
 {
 	const char *type;
-	const unsigned int *regs;
+	const __be32 *regs;
 	unsigned long base;
 	unsigned int lmb_size;
 	int ret = -EINVAL;
@@ -172,8 +172,8 @@ static int pseries_add_mem_node(struct d
 	if (!regs)
 		return ret;
 
-	base = *(unsigned long *)regs;
-	lmb_size = regs[3];
+	base = be64_to_cpu(*(unsigned long *)regs);
+	lmb_size = be32_to_cpu(regs[3]);
 
 	/*
 	 * Update memory region to represent the memory add
@@ -187,14 +187,14 @@ static int pseries_update_drconf_memory(
 	struct of_drconf_cell *new_drmem, *old_drmem;
 	unsigned long memblock_size;
 	u32 entries;
-	u32 *p;
+	__be32 *p;
 	int i, rc = -EINVAL;
 
 	memblock_size = pseries_memory_block_size();
 	if (!memblock_size)
 		return -EINVAL;
 
-	p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
+	p = (__be32 *) pr->old_prop->value;
 	if (!p)
 		return -EINVAL;
 
@@ -203,28 +203,30 @@ static int pseries_update_drconf_memory(
 	 * entries. Get the niumber of entries and skip to the array of
 	 * of_drconf_cell's.
 	 */
-	entries = *p++;
+	entries = be32_to_cpu(*p++);
 	old_drmem = (struct of_drconf_cell *)p;
 
-	p = (u32 *)pr->prop->value;
+	p = (__be32 *)pr->prop->value;
 	p++;
 	new_drmem = (struct of_drconf_cell *)p;
 
 	for (i = 0; i < entries; i++) {
-		if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
-		    (!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
-			rc = pseries_remove_memblock(old_drmem[i].base_addr,
+		if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
+		    (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
+			rc = pseries_remove_memblock(
+				be64_to_cpu(old_drmem[i].base_addr),
 						     memblock_size);
 			break;
-		} else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
-			   (new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
-			rc = memblock_add(old_drmem[i].base_addr,
+		} else if ((!(be32_to_cpu(old_drmem[i].flags) &
+			    DRCONF_MEM_ASSIGNED)) &&
+			    (be32_to_cpu(new_drmem[i].flags) &
+			    DRCONF_MEM_ASSIGNED)) {
+			rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
 					  memblock_size);
 			rc = (rc < 0) ? -EINVAL : 0;
 			break;
 		}
 	}
-
 	return rc;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvCall_inst.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvCall_inst.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvCall_inst.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <asm/firmware.h>
 #include <asm/cputable.h>
 #include <asm/trace.h>
+#include <asm/machdep.h>
 
 DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats);
 
@@ -162,4 +163,4 @@ static int __init hcall_inst_init(void)
 
 	return 0;
 }
-__initcall(hcall_inst_init);
+machine_device_initcall(pseries, hcall_inst_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvCall.S linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvCall.S
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvCall.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvCall.S	2014-09-28 17:29:07.000000000 -0400
@@ -12,9 +12,13 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
+#include <asm/jump_label.h>
+
+	.section	".text"
 	
 #ifdef CONFIG_TRACEPOINTS
 
+#ifndef CONFIG_JUMP_LABEL
 	.section	".toc","aw"
 
 	.globl hcall_tracepoint_refcount
@@ -22,21 +26,13 @@ hcall_tracepoint_refcount:
 	.llong	0
 
 	.section	".text"
+#endif
 
 /*
  * precall must preserve all registers.  use unused STK_PARAM()
- * areas to save snapshots and opcode. We branch around this
- * in early init (eg when populating the MMU hashtable) by using an
- * unconditional cpu feature.
+ * areas to save snapshots and opcode.
  */
 #define HCALL_INST_PRECALL(FIRST_REG)				\
-BEGIN_FTR_SECTION;						\
-	b	1f;						\
-END_FTR_SECTION(0, 1);						\
-	ld      r12,hcall_tracepoint_refcount@toc(r2);		\
-	std	r12,32(r1);					\
-	cmpdi	r12,0;						\
-	beq+	1f;						\
 	mflr	r0;						\
 	std	r3,STK_PARAM(R3)(r1);				\
 	std	r4,STK_PARAM(R4)(r1);				\
@@ -50,45 +46,29 @@ END_FTR_SECTION(0, 1);						\
 	addi	r4,r1,STK_PARAM(FIRST_REG);			\
 	stdu	r1,-STACK_FRAME_OVERHEAD(r1);			\
 	bl	__trace_hcall_entry;				\
-	addi	r1,r1,STACK_FRAME_OVERHEAD;			\
-	ld	r0,16(r1);					\
-	ld	r3,STK_PARAM(R3)(r1);				\
-	ld	r4,STK_PARAM(R4)(r1);				\
-	ld	r5,STK_PARAM(R5)(r1);				\
-	ld	r6,STK_PARAM(R6)(r1);				\
-	ld	r7,STK_PARAM(R7)(r1);				\
-	ld	r8,STK_PARAM(R8)(r1);				\
-	ld	r9,STK_PARAM(R9)(r1);				\
-	ld	r10,STK_PARAM(R10)(r1);				\
-	mtlr	r0;						\
-1:
+	ld	r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
+	ld	r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1);	\
+	ld	r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1);	\
+	ld	r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1);	\
+	ld	r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1);	\
+	ld	r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1);	\
+	ld	r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1);	\
+	ld	r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
 
 /*
  * postcall is performed immediately before function return which
- * allows liberal use of volatile registers.  We branch around this
- * in early init (eg when populating the MMU hashtable) by using an
- * unconditional cpu feature.
+ * allows liberal use of volatile registers.
  */
 #define __HCALL_INST_POSTCALL					\
-BEGIN_FTR_SECTION;						\
-	b	1f;						\
-END_FTR_SECTION(0, 1);						\
-	ld      r12,32(r1);					\
-	cmpdi	r12,0;						\
-	beq+	1f;						\
-	mflr	r0;						\
-	ld	r6,STK_PARAM(R3)(r1);				\
-	std	r3,STK_PARAM(R3)(r1);				\
+	ld	r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
+	std	r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
 	mr	r4,r3;						\
-	mr	r3,r6;						\
-	std	r0,16(r1);					\
-	stdu	r1,-STACK_FRAME_OVERHEAD(r1);			\
+	mr	r3,r0;						\
 	bl	__trace_hcall_exit;				\
+	ld	r0,STACK_FRAME_OVERHEAD+16(r1);			\
 	addi	r1,r1,STACK_FRAME_OVERHEAD;			\
-	ld	r0,16(r1);					\
 	ld	r3,STK_PARAM(R3)(r1);				\
-	mtlr	r0;						\
-1:
+	mtlr	r0
 
 #define HCALL_INST_POSTCALL_NORETS				\
 	li	r5,0;						\
@@ -98,37 +78,62 @@ END_FTR_SECTION(0, 1);						\
 	mr	r5,BUFREG;					\
 	__HCALL_INST_POSTCALL
 
+#ifdef CONFIG_JUMP_LABEL
+#define HCALL_BRANCH(LABEL)					\
+	ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
+#else
+
+/*
+ * We branch around this in early init (eg when populating the MMU
+ * hashtable) by using an unconditional cpu feature.
+ */
+#define HCALL_BRANCH(LABEL)					\
+BEGIN_FTR_SECTION;						\
+	b	1f;						\
+END_FTR_SECTION(0, 1);						\
+	ld	r12,hcall_tracepoint_refcount@toc(r2);		\
+	std	r12,32(r1);					\
+	cmpdi	r12,0;						\
+	bne-	LABEL;						\
+1:
+#endif
+
 #else
 #define HCALL_INST_PRECALL(FIRST_ARG)
 #define HCALL_INST_POSTCALL_NORETS
 #define HCALL_INST_POSTCALL(BUFREG)
+#define HCALL_BRANCH(LABEL)
 #endif
 
-	.text
-
 _GLOBAL_TOC(plpar_hcall_norets)
 	HMT_MEDIUM
 
 	mfcr	r0
 	stw	r0,8(r1)
-
-	HCALL_INST_PRECALL(R4)
-
+	HCALL_BRANCH(plpar_hcall_norets_trace)
 	HVSC				/* invoke the hypervisor */
 
-	HCALL_INST_POSTCALL_NORETS
-
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 	blr				/* return r3 = status */
 
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall_norets_trace:
+	HCALL_INST_PRECALL(R4)
+	HVSC
+	HCALL_INST_POSTCALL_NORETS
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+	blr
+#endif
+
 _GLOBAL_TOC(plpar_hcall)
 	HMT_MEDIUM
 
 	mfcr	r0
 	stw	r0,8(r1)
 
-	HCALL_INST_PRECALL(R5)
+	HCALL_BRANCH(plpar_hcall_trace)
 
 	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
@@ -147,12 +152,40 @@ _GLOBAL_TOC(plpar_hcall)
 	std	r6, 16(r12)
 	std	r7, 24(r12)
 
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+
+	blr				/* return r3 = status */
+
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall_trace:
+	HCALL_INST_PRECALL(R5)
+
+	std	r4,STK_PARAM(R4)(r1)
+	mr	r0,r4
+
+	mr	r4,r5
+	mr	r5,r6
+	mr	r6,r7
+	mr	r7,r8
+	mr	r8,r9
+	mr	r9,r10
+
+	HVSC
+
+	ld	r12,STK_PARAM(R4)(r1)
+	std	r4,0(r12)
+	std	r5,8(r12)
+	std	r6,16(r12)
+	std	r7,24(r12)
+
 	HCALL_INST_POSTCALL(r12)
 
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 
-	blr				/* return r3 = status */
+	blr
+#endif
 
 /*
  * plpar_hcall_raw can be called in real mode. kexec/kdump need some
@@ -194,7 +227,7 @@ _GLOBAL_TOC(plpar_hcall9)
 	mfcr	r0
 	stw	r0,8(r1)
 
-	HCALL_INST_PRECALL(R5)
+	HCALL_BRANCH(plpar_hcall9_trace)
 
 	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
@@ -222,12 +255,49 @@ _GLOBAL_TOC(plpar_hcall9)
 	std	r11,56(r12)
 	std	r0, 64(r12)
 
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+
+	blr				/* return r3 = status */
+
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall9_trace:
+	HCALL_INST_PRECALL(R5)
+
+	std	r4,STK_PARAM(R4)(r1)
+	mr	r0,r4
+
+	mr	r4,r5
+	mr	r5,r6
+	mr	r6,r7
+	mr	r7,r8
+	mr	r8,r9
+	mr	r9,r10
+	ld	r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
+	ld	r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
+	ld	r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
+
+	HVSC
+
+	mr	r0,r12
+	ld	r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
+	std	r4,0(r12)
+	std	r5,8(r12)
+	std	r6,16(r12)
+	std	r7,24(r12)
+	std	r8,32(r12)
+	std	r9,40(r12)
+	std	r10,48(r12)
+	std	r11,56(r12)
+	std	r0,64(r12)
+
 	HCALL_INST_POSTCALL(r12)
 
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 
-	blr				/* return r3 = status */
+	blr
+#endif
 
 /* See plpar_hcall_raw to see why this is needed */
 _GLOBAL(plpar_hcall9_raw)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvcserver.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvcserver.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/hvcserver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/hvcserver.c	2014-09-28 17:29:07.000000000 -0400
@@ -163,8 +163,8 @@ int hvcs_get_partner_info(uint32_t unit_
 			return retval;
 		}
 
-		last_p_partition_ID = pi_buff[0];
-		last_p_unit_address = pi_buff[1];
+		last_p_partition_ID = be64_to_cpu(pi_buff[0]);
+		last_p_unit_address = be64_to_cpu(pi_buff[1]);
 
 		/* This indicates that there are no further partners */
 		if (last_p_partition_ID == ~0UL
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/iommu.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -721,13 +721,13 @@ static int __init disable_ddw_setup(char
 
 early_param("disable_ddw", disable_ddw_setup);
 
-static void remove_ddw(struct device_node *np)
+static void remove_ddw(struct device_node *np, bool remove_prop)
 {
 	struct dynamic_dma_window_prop *dwp;
 	struct property *win64;
 	const u32 *ddw_avail;
 	u64 liobn;
-	int len, ret;
+	int len, ret = 0;
 
 	ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len);
 	win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
@@ -761,7 +761,8 @@ static void remove_ddw(struct device_nod
 			np->full_name, ret, ddw_avail[2], liobn);
 
 delprop:
-	ret = of_remove_property(np, win64);
+	if (remove_prop)
+		ret = of_remove_property(np, win64);
 	if (ret)
 		pr_warning("%s: failed to remove direct window property: %d\n",
 			np->full_name, ret);
@@ -805,7 +806,7 @@ static int find_existing_ddw_windows(voi
 		window = kzalloc(sizeof(*window), GFP_KERNEL);
 		if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
 			kfree(window);
-			remove_ddw(pdn);
+			remove_ddw(pdn, true);
 			continue;
 		}
 
@@ -1045,7 +1046,7 @@ out_free_window:
 	kfree(window);
 
 out_clear_window:
-	remove_ddw(pdn);
+	remove_ddw(pdn, true);
 
 out_free_prop:
 	kfree(win64->name);
@@ -1255,7 +1256,14 @@ static int iommu_reconfig_notifier(struc
 
 	switch (action) {
 	case OF_RECONFIG_DETACH_NODE:
-		remove_ddw(np);
+		/*
+		 * Removing the property will invoke the reconfig
+		 * notifier again, which causes dead-lock on the
+		 * read-write semaphore of the notifier chain. So
+		 * we have to remove the property when releasing
+		 * the device node.
+		 */
+		remove_ddw(np, false);
 		if (pci && pci->iommu_table)
 			iommu_free_table(pci->iommu_table, np->full_name);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/lpar.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/lpar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/lpar.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/console.h>
 #include <linux/export.h>
+#include <linux/static_key.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/page.h>
@@ -430,16 +431,17 @@ static void __pSeries_lpar_hugepage_inva
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm,
-				       unsigned char *hpte_slot_array,
-				       unsigned long addr, int psize)
+static void pSeries_lpar_hugepage_invalidate(unsigned long vsid,
+					     unsigned long addr,
+					     unsigned char *hpte_slot_array,
+					     int psize, int ssize)
 {
-	int ssize = 0, i, index = 0;
+	int i, index = 0;
 	unsigned long s_addr = addr;
 	unsigned int max_hpte_count, valid;
 	unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH];
 	unsigned long slot_array[PPC64_HUGE_HPTE_BATCH];
-	unsigned long shift, hidx, vpn = 0, vsid, hash, slot;
+	unsigned long shift, hidx, vpn = 0, hash, slot;
 
 	shift = mmu_psize_defs[psize].shift;
 	max_hpte_count = 1U << (PMD_SHIFT - shift);
@@ -452,15 +454,6 @@ static void pSeries_lpar_hugepage_invali
 
 		/* get the vpn */
 		addr = s_addr + (i * (1ul << shift));
-		if (!is_kernel_addr(addr)) {
-			ssize = user_segment_size(addr);
-			vsid = get_vsid(mm->context.id, addr, ssize);
-			WARN_ON(vsid == 0);
-		} else {
-			vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
-			ssize = mmu_kernel_ssize;
-		}
-
 		vpn = hpt_vpn(addr, vsid, ssize);
 		hash = hpt_hash(vpn, shift, ssize);
 		if (hidx & _PTEIDX_SECONDARY)
@@ -649,6 +642,19 @@ EXPORT_SYMBOL(arch_free_page);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
+#ifdef CONFIG_JUMP_LABEL
+struct static_key hcall_tracepoint_key = STATIC_KEY_INIT;
+
+void hcall_tracepoint_regfunc(void)
+{
+	static_key_slow_inc(&hcall_tracepoint_key);
+}
+
+void hcall_tracepoint_unregfunc(void)
+{
+	static_key_slow_dec(&hcall_tracepoint_key);
+}
+#else
 /*
  * We optimise our hcall path by placing hcall_tracepoint_refcount
  * directly in the TOC so we can check if the hcall tracepoints are
@@ -658,13 +664,6 @@ EXPORT_SYMBOL(arch_free_page);
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long hcall_tracepoint_refcount;
 
-/* 
- * Since the tracing code might execute hcalls we need to guard against
- * recursion. One example of this are spinlocks calling H_YIELD on
- * shared processor partitions.
- */
-static DEFINE_PER_CPU(unsigned int, hcall_trace_depth);
-
 void hcall_tracepoint_regfunc(void)
 {
 	hcall_tracepoint_refcount++;
@@ -674,6 +673,15 @@ void hcall_tracepoint_unregfunc(void)
 {
 	hcall_tracepoint_refcount--;
 }
+#endif
+
+/*
+ * Since the tracing code might execute hcalls we need to guard against
+ * recursion. One example of this are spinlocks calling H_YIELD on
+ * shared processor partitions.
+ */
+static DEFINE_PER_CPU(unsigned int, hcall_trace_depth);
+
 
 void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/mobility.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/mobility.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/mobility.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/mobility.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 
+#include <asm/machdep.h>
 #include <asm/rtas.h>
 #include "pseries.h"
 
@@ -319,7 +320,7 @@ static ssize_t migrate_store(struct clas
 	u64 streamid;
 	int rc;
 
-	rc = strict_strtoull(buf, 0, &streamid);
+	rc = kstrtou64(buf, 0, &streamid);
 	if (rc)
 		return rc;
 
@@ -362,4 +363,4 @@ static int __init mobility_sysfs_init(vo
 
 	return rc;
 }
-device_initcall(mobility_sysfs_init);
+machine_device_initcall(pseries, mobility_sysfs_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/msi.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/msi.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/msi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/msi.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
 #include <asm/rtas.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
+#include <asm/machdep.h>
 
 static int query_token, change_token;
 
@@ -532,5 +533,4 @@ static int rtas_msi_init(void)
 
 	return 0;
 }
-arch_initcall(rtas_msi_init);
-
+machine_arch_initcall(pseries, rtas_msi_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2014-09-28 17:29:07.000000000 -0400
@@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_contro
 		}
 	}
 
-	/* Unregister the bridge device from sysfs and remove the PCI bus */
-	device_unregister(b->bridge);
+	/* Remove the PCI bus and unregister the bridge device from sysfs */
 	phb->bus = NULL;
 	pci_remove_bus(b);
+	device_unregister(b->bridge);
 
 	/* Now release the IO resource */
 	if (res->flags & IORESOURCE_IO)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/power.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/power.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/power.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <asm/machdep.h>
 
 unsigned long rtas_poweron_auto; /* default and normal state is 0 */
 
@@ -71,11 +72,11 @@ static int __init pm_init(void)
 		return -ENOMEM;
 	return sysfs_create_group(power_kobj, &attr_group);
 }
-core_initcall(pm_init);
+machine_core_initcall(pseries, pm_init);
 #else
 static int __init apo_pm_init(void)
 {
 	return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr));
 }
-__initcall(apo_pm_init);
+machine_device_initcall(pseries, apo_pm_init);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/ras.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/ras.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/ras.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/ras.c	2014-09-28 17:29:07.000000000 -0400
@@ -71,7 +71,7 @@ static int __init init_ras_IRQ(void)
 
 	return 0;
 }
-subsys_initcall(init_ras_IRQ);
+machine_subsys_initcall(pseries, init_ras_IRQ);
 
 #define EPOW_SHUTDOWN_NORMAL				1
 #define EPOW_SHUTDOWN_ON_UPS				2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/reconfig.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/reconfig.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/reconfig.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/reconfig.c	2014-09-28 17:29:07.000000000 -0400
@@ -446,13 +446,10 @@ static int proc_ppc64_create_ofdt(void)
 {
 	struct proc_dir_entry *ent;
 
-	if (!machine_is(pseries))
-		return 0;
-
 	ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops);
 	if (ent)
 		proc_set_size(ent, 0);
 
 	return 0;
 }
-__initcall(proc_ppc64_create_ofdt);
+machine_device_initcall(pseries, proc_ppc64_create_ofdt);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/rng.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/rng.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/rng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/rng.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,4 +42,4 @@ static __init int rng_init(void)
 
 	return 0;
 }
-subsys_initcall(rng_init);
+machine_subsys_initcall(pseries, rng_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -232,8 +232,7 @@ static void __init pseries_discover_pic(
 	struct device_node *np;
 	const char *typep;
 
-	for (np = NULL; (np = of_find_node_by_name(np,
-						   "interrupt-controller"));) {
+	for_each_node_by_name(np, "interrupt-controller") {
 		typep = of_get_property(np, "compatible", NULL);
 		if (strstr(typep, "open-pic")) {
 			pSeries_mpic_node = of_node_get(np);
@@ -351,7 +350,7 @@ static int alloc_dispatch_log_kmem_cache
 
 	return alloc_dispatch_logs();
 }
-early_initcall(alloc_dispatch_log_kmem_cache);
+machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache);
 
 static void pseries_lpar_idle(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/suspend.c linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/suspend.c
--- linux-libre-3.16-gnu/arch/powerpc/platforms/pseries/suspend.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/platforms/pseries/suspend.c	2014-09-28 17:29:07.000000000 -0400
@@ -265,7 +265,7 @@ static int __init pseries_suspend_init(v
 {
 	int rc;
 
-	if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR))
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
 		return 0;
 
 	suspend_data.token = rtas_token("ibm,suspend-me");
@@ -280,5 +280,4 @@ static int __init pseries_suspend_init(v
 	suspend_set_ops(&pseries_suspend_ops);
 	return 0;
 }
-
-__initcall(pseries_suspend_init);
+machine_device_initcall(pseries, pseries_suspend_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/sysdev/fsl_pci.c linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/fsl_pci.c
--- linux-libre-3.16-gnu/arch/powerpc/sysdev/fsl_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/fsl_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -853,8 +853,8 @@ u64 fsl_pci_immrbar_base(struct pci_cont
 		in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
 		for (i = 0; i < 4; i++) {
 			/* not enabled, skip */
-			if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
-				 continue;
+			if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN))
+				continue;
 
 			if (get_immrbase() == in_le32(&in[i].tar))
 				return (u64)in_le32(&in[i].barh) << 32 |
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/sysdev/micropatch.c linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/micropatch.c
--- linux-libre-3.16-gnu/arch/powerpc/sysdev/micropatch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/micropatch.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <asm/irq.h>
-#include <asm/mpc8xx.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/8xx_immap.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/sysdev/mpic_msgr.c linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/mpic_msgr.c
--- linux-libre-3.16-gnu/arch/powerpc/sysdev/mpic_msgr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/sysdev/mpic_msgr.c	2014-09-28 17:29:07.000000000 -0400
@@ -184,7 +184,7 @@ static int mpic_msgr_probe(struct platfo
 		dev_info(&dev->dev, "Found %d message registers\n",
 				mpic_msgr_count);
 
-		mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
+		mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs),
 							 GFP_KERNEL);
 		if (!mpic_msgrs) {
 			dev_err(&dev->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/powerpc/xmon/xmon.c linux-libre-3.17-rc7-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-3.16-gnu/arch/powerpc/xmon/xmon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/powerpc/xmon/xmon.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/bug.h>
+#include <linux/nmi.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -374,6 +375,7 @@ static int xmon_core(struct pt_regs *reg
 #endif
 
 	local_irq_save(flags);
+	hard_irq_disable();
 
 	bp = in_breakpoint_table(regs->nip, &offset);
 	if (bp != NULL) {
@@ -558,6 +560,7 @@ static int xmon_core(struct pt_regs *reg
 #endif
 	insert_cpu_bpts();
 
+	touch_nmi_watchdog();
 	local_irq_restore(flags);
 
 	return cmd != 'X' && cmd != EOF;
@@ -2058,10 +2061,6 @@ static void dump_one_paca(int cpu)
 	DUMP(p, kernel_toc, "lx");
 	DUMP(p, kernelbase, "lx");
 	DUMP(p, kernel_msr, "lx");
-#ifdef CONFIG_PPC_STD_MMU_64
-	DUMP(p, stab_real, "lx");
-	DUMP(p, stab_addr, "lx");
-#endif
 	DUMP(p, emergency_sp, "p");
 #ifdef CONFIG_PPC_BOOK3S_64
 	DUMP(p, mc_emergency_sp, "p");
@@ -2694,7 +2693,7 @@ static void xmon_print_symbol(unsigned l
 }
 
 #ifdef CONFIG_PPC_BOOK3S_64
-static void dump_slb(void)
+void dump_segments(void)
 {
 	int i;
 	unsigned long esid,vsid,valid;
@@ -2726,34 +2725,6 @@ static void dump_slb(void)
 		}
 	}
 }
-
-static void dump_stab(void)
-{
-	int i;
-	unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
-
-	printf("Segment table contents of cpu 0x%x\n", smp_processor_id());
-
-	for (i = 0; i < PAGE_SIZE/16; i++) {
-		unsigned long a, b;
-
-		a = *tmp++;
-		b = *tmp++;
-
-		if (a || b) {
-			printf("%03d %016lx ", i, a);
-			printf("%016lx\n", b);
-		}
-	}
-}
-
-void dump_segments(void)
-{
-	if (mmu_has_feature(MMU_FTR_SLB))
-		dump_slb();
-	else
-		dump_stab();
-}
 #endif
 
 #ifdef CONFIG_PPC_STD_MMU_32
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/configs/default_defconfig linux-libre-3.17-rc7-gnu/arch/s390/configs/default_defconfig
--- linux-libre-3.16-gnu/arch/s390/configs/default_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/configs/default_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,7 @@ CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
@@ -366,7 +367,6 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_ENCLOSURE_SERVICES=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
@@ -380,7 +380,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_ISCSI_TCP=m
 CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/configs/gcov_defconfig linux-libre-3.17-rc7-gnu/arch/s390/configs/gcov_defconfig
--- linux-libre-3.16-gnu/arch/s390/configs/gcov_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/configs/gcov_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,7 @@ CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
@@ -363,7 +364,6 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_ENCLOSURE_SERVICES=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
@@ -377,7 +377,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_ISCSI_TCP=m
 CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/configs/performance_defconfig linux-libre-3.17-rc7-gnu/arch/s390/configs/performance_defconfig
--- linux-libre-3.16-gnu/arch/s390/configs/performance_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/configs/performance_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,7 @@ CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
@@ -361,7 +362,6 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_ENCLOSURE_SERVICES=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
@@ -375,7 +375,6 @@ CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
 CONFIG_ISCSI_TCP=m
 CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/configs/zfcpdump_defconfig linux-libre-3.17-rc7-gnu/arch/s390/configs/zfcpdump_defconfig
--- linux-libre-3.16-gnu/arch/s390/configs/zfcpdump_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/configs/zfcpdump_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@ CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_IUCV is not set
+CONFIG_NET=y
 CONFIG_ATM=y
 CONFIG_ATM_LANE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/defconfig linux-libre-3.17-rc7-gnu/arch/s390/defconfig
--- linux-libre-3.16-gnu/arch/s390/defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@ CONFIG_CMA=y
 CONFIG_CRASH_DUMP=y
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/ipl.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/ipl.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/ipl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/ipl.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,12 +17,12 @@
 #define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
 			      sizeof(struct ipl_block_fcp))
 
-#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 8)
+#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 16)
 
 #define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
 			      sizeof(struct ipl_block_ccw))
 
-#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 8)
+#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 16)
 
 #define IPL_MAX_SUPPORTED_VERSION (0)
 
@@ -38,10 +38,11 @@ struct ipl_list_hdr {
 	u8  pbt;
 	u8  flags;
 	u16 reserved2;
+	u8  loadparm[8];
 } __attribute__((packed));
 
 struct ipl_block_fcp {
-	u8  reserved1[313-1];
+	u8  reserved1[305-1];
 	u8  opt;
 	u8  reserved2[3];
 	u16 reserved3;
@@ -62,7 +63,6 @@ struct ipl_block_fcp {
 				 offsetof(struct ipl_block_fcp, scp_data)))
 
 struct ipl_block_ccw {
-	u8  load_parm[8];
 	u8  reserved1[84];
 	u8  reserved2[2];
 	u16 devno;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/s390/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/s390/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -4,4 +4,5 @@ generic-y += clkdev.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -305,7 +305,6 @@ struct kvm_s390_local_interrupt {
 	struct list_head list;
 	atomic_t active;
 	struct kvm_s390_float_interrupt *float_int;
-	int timer_due; /* event indicator for waitqueue below */
 	wait_queue_head_t *wq;
 	atomic_t *cpuflags;
 	unsigned int action_bits;
@@ -367,7 +366,6 @@ struct kvm_vcpu_arch {
 	s390_fp_regs      guest_fpregs;
 	struct kvm_s390_local_interrupt local_int;
 	struct hrtimer    ckc_timer;
-	struct tasklet_struct tasklet;
 	struct kvm_s390_pgm_info pgm;
 	union  {
 		struct cpuid	cpu_id;
@@ -418,6 +416,7 @@ struct kvm_arch{
 	int css_support;
 	int use_irqchip;
 	int use_cmma;
+	int user_cpu_state_ctrl;
 	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
 	wait_queue_head_t ipte_wq;
 	spinlock_t start_stop_lock;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/page.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -162,6 +162,4 @@ static inline int devmem_is_allowed(unsi
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
 
-#define __HAVE_ARCH_GATE_AREA 1
-
 #endif /* _S390_PAGE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -287,7 +287,14 @@ extern unsigned long MODULES_END;
 #define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */
 #define _SEGMENT_ENTRY_COMMON	0x10	/* common segment bit		    */
 #define _SEGMENT_ENTRY_PTL	0x0f	/* page table length		    */
-#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_PROTECT
+
+#define _SEGMENT_ENTRY_DIRTY	0	/* No sw dirty bit for 31-bit */
+#define _SEGMENT_ENTRY_YOUNG	0	/* No sw young bit for 31-bit */
+#define _SEGMENT_ENTRY_READ	0	/* No sw read bit for 31-bit */
+#define _SEGMENT_ENTRY_WRITE	0	/* No sw write bit for 31-bit */
+#define _SEGMENT_ENTRY_LARGE	0	/* No large pages for 31-bit */
+#define _SEGMENT_ENTRY_BITS_LARGE 0
+#define _SEGMENT_ENTRY_ORIGIN_LARGE 0
 
 #define _SEGMENT_ENTRY		(_SEGMENT_ENTRY_PTL)
 #define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)
@@ -350,7 +357,7 @@ extern unsigned long MODULES_END;
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_BITS	0xfffffffffffffe33UL
-#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff1ff33UL
+#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
 #define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */
 #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
 #define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */
@@ -359,30 +366,34 @@ extern unsigned long MODULES_END;
 #define _SEGMENT_ENTRY		(0)
 #define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)
 
-#define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */
-#define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */
-#define _SEGMENT_ENTRY_SPLIT	0x001	/* THP splitting bit */
-#define _SEGMENT_ENTRY_YOUNG	0x002	/* SW segment young bit */
-#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_YOUNG
+#define _SEGMENT_ENTRY_DIRTY	0x2000	/* SW segment dirty bit */
+#define _SEGMENT_ENTRY_YOUNG	0x1000	/* SW segment young bit */
+#define _SEGMENT_ENTRY_SPLIT	0x0800	/* THP splitting bit */
+#define _SEGMENT_ENTRY_LARGE	0x0400	/* STE-format control, large page */
+#define _SEGMENT_ENTRY_CO	0x0100	/* change-recording override   */
+#define _SEGMENT_ENTRY_READ	0x0002	/* SW segment read bit */
+#define _SEGMENT_ENTRY_WRITE	0x0001	/* SW segment write bit */
 
 /*
  * Segment table entry encoding (R = read-only, I = invalid, y = young bit):
- *			..R...I...y.
- * prot-none, old	..0...1...1.
- * prot-none, young	..1...1...1.
- * read-only, old	..1...1...0.
- * read-only, young	..1...0...1.
- * read-write, old	..0...1...0.
- * read-write, young	..0...0...1.
+ *				dy..R...I...wr
+ * prot-none, clean, old	00..1...1...00
+ * prot-none, clean, young	01..1...1...00
+ * prot-none, dirty, old	10..1...1...00
+ * prot-none, dirty, young	11..1...1...00
+ * read-only, clean, old	00..1...1...01
+ * read-only, clean, young	01..1...0...01
+ * read-only, dirty, old	10..1...1...01
+ * read-only, dirty, young	11..1...0...01
+ * read-write, clean, old	00..1...1...11
+ * read-write, clean, young	01..1...0...11
+ * read-write, dirty, old	10..0...1...11
+ * read-write, dirty, young	11..0...0...11
  * The segment table origin is used to distinguish empty (origin==0) from
  * read-write, old segment table entries (origin!=0)
  */
 
-#define _SEGMENT_ENTRY_SPLIT_BIT 0	/* THP splitting bit number */
-
-/* Set of bits not changed in pmd_modify */
-#define _SEGMENT_CHG_MASK	(_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \
-				 | _SEGMENT_ENTRY_SPLIT | _SEGMENT_ENTRY_CO)
+#define _SEGMENT_ENTRY_SPLIT_BIT 11	/* THP splitting bit number */
 
 /* Page status table bits for virtualization */
 #define PGSTE_ACC_BITS	0xf000000000000000UL
@@ -455,10 +466,11 @@ extern unsigned long MODULES_END;
  * Segment entry (large page) protection definitions.
  */
 #define SEGMENT_NONE	__pgprot(_SEGMENT_ENTRY_INVALID | \
-				 _SEGMENT_ENTRY_NONE)
-#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_INVALID | \
 				 _SEGMENT_ENTRY_PROTECT)
-#define SEGMENT_WRITE	__pgprot(_SEGMENT_ENTRY_INVALID)
+#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_PROTECT | \
+				 _SEGMENT_ENTRY_READ)
+#define SEGMENT_WRITE	__pgprot(_SEGMENT_ENTRY_READ | \
+				 _SEGMENT_ENTRY_WRITE)
 
 static inline int mm_has_pgste(struct mm_struct *mm)
 {
@@ -569,25 +581,23 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline int pmd_large(pmd_t pmd)
 {
-#ifdef CONFIG_64BIT
 	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
-#else
-	return 0;
-#endif
 }
 
-static inline int pmd_prot_none(pmd_t pmd)
+static inline int pmd_pfn(pmd_t pmd)
 {
-	return (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) &&
-		(pmd_val(pmd) & _SEGMENT_ENTRY_NONE);
+	unsigned long origin_mask;
+
+	origin_mask = _SEGMENT_ENTRY_ORIGIN;
+	if (pmd_large(pmd))
+		origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
+	return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
 }
 
 static inline int pmd_bad(pmd_t pmd)
 {
-#ifdef CONFIG_64BIT
 	if (pmd_large(pmd))
 		return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
-#endif
 	return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
 }
 
@@ -607,20 +617,22 @@ extern int pmdp_clear_flush_young(struct
 #define __HAVE_ARCH_PMD_WRITE
 static inline int pmd_write(pmd_t pmd)
 {
-	if (pmd_prot_none(pmd))
-		return 0;
-	return (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) == 0;
+	return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0;
+}
+
+static inline int pmd_dirty(pmd_t pmd)
+{
+	int dirty = 1;
+	if (pmd_large(pmd))
+		dirty = (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
+	return dirty;
 }
 
 static inline int pmd_young(pmd_t pmd)
 {
-	int young = 0;
-#ifdef CONFIG_64BIT
-	if (pmd_prot_none(pmd))
-		young = (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) != 0;
-	else
+	int young = 1;
+	if (pmd_large(pmd))
 		young = (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0;
-#endif
 	return young;
 }
 
@@ -1115,7 +1127,7 @@ static inline int ptep_test_and_clear_yo
 					    unsigned long addr, pte_t *ptep)
 {
 	pgste_t pgste;
-	pte_t pte;
+	pte_t pte, oldpte;
 	int young;
 
 	if (mm_has_pgste(vma->vm_mm)) {
@@ -1123,12 +1135,13 @@ static inline int ptep_test_and_clear_yo
 		pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste);
 	}
 
-	pte = *ptep;
+	oldpte = pte = *ptep;
 	ptep_flush_direct(vma->vm_mm, addr, ptep);
 	young = pte_young(pte);
 	pte = pte_mkold(pte);
 
 	if (mm_has_pgste(vma->vm_mm)) {
+		pgste = pgste_update_all(&oldpte, pgste, vma->vm_mm);
 		pgste = pgste_set_pte(ptep, pgste, pte);
 		pgste_set_unlock(ptep, pgste);
 	} else
@@ -1318,6 +1331,7 @@ static inline int ptep_set_access_flags(
 	ptep_flush_direct(vma->vm_mm, address, ptep);
 
 	if (mm_has_pgste(vma->vm_mm)) {
+		pgste_set_key(ptep, pgste, entry, vma->vm_mm);
 		pgste = pgste_set_pte(ptep, pgste, entry);
 		pgste_set_unlock(ptep, pgste);
 	} else
@@ -1391,7 +1405,7 @@ static inline pmd_t *pmd_offset(pud_t *p
 #define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
 #define pte_page(x) pfn_to_page(pte_pfn(x))
 
-#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))
 
 /* Find an entry in the lowest level page table.. */
 #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
@@ -1413,41 +1427,75 @@ static inline unsigned long massage_pgpr
 	return pgprot_val(SEGMENT_WRITE);
 }
 
-static inline pmd_t pmd_mkyoung(pmd_t pmd)
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
 {
-#ifdef CONFIG_64BIT
-	if (pmd_prot_none(pmd)) {
+	pmd_val(pmd) &= ~_SEGMENT_ENTRY_WRITE;
+	pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+	return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+	pmd_val(pmd) |= _SEGMENT_ENTRY_WRITE;
+	if (pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
+		return pmd;
+	pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
+	return pmd;
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+	if (pmd_large(pmd)) {
+		pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY;
 		pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
-	} else {
+	}
+	return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+	if (pmd_large(pmd)) {
+		pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY;
+		if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE)
+			pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
+	}
+	return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+	if (pmd_large(pmd)) {
 		pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
-		pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID;
+		if (pmd_val(pmd) & _SEGMENT_ENTRY_READ)
+			pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID;
 	}
-#endif
 	return pmd;
 }
 
 static inline pmd_t pmd_mkold(pmd_t pmd)
 {
-#ifdef CONFIG_64BIT
-	if (pmd_prot_none(pmd)) {
-		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
-	} else {
+	if (pmd_large(pmd)) {
 		pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG;
 		pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
 	}
-#endif
 	return pmd;
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 {
-	int young;
-
-	young = pmd_young(pmd);
-	pmd_val(pmd) &= _SEGMENT_CHG_MASK;
+	if (pmd_large(pmd)) {
+		pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE |
+			_SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG |
+			_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SPLIT;
+		pmd_val(pmd) |= massage_pgprot_pmd(newprot);
+		if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
+			pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+		if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG))
+			pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
+		return pmd;
+	}
+	pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN;
 	pmd_val(pmd) |= massage_pgprot_pmd(newprot);
-	if (young)
-		pmd = pmd_mkyoung(pmd);
 	return pmd;
 }
 
@@ -1455,16 +1503,9 @@ static inline pmd_t mk_pmd_phys(unsigned
 {
 	pmd_t __pmd;
 	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
-	return pmd_mkyoung(__pmd);
+	return __pmd;
 }
 
-static inline pmd_t pmd_mkwrite(pmd_t pmd)
-{
-	/* Do not clobber PROT_NONE segments! */
-	if (!pmd_prot_none(pmd))
-		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
-	return pmd;
-}
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */
 
 static inline void __pmdp_csp(pmd_t *pmdp)
@@ -1555,34 +1596,21 @@ extern pgtable_t pgtable_trans_huge_with
 
 static inline int pmd_trans_splitting(pmd_t pmd)
 {
-	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
+	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) &&
+		(pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT);
 }
 
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 			      pmd_t *pmdp, pmd_t entry)
 {
-	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INVALID) && MACHINE_HAS_EDAT1)
-		pmd_val(entry) |= _SEGMENT_ENTRY_CO;
 	*pmdp = entry;
 }
 
 static inline pmd_t pmd_mkhuge(pmd_t pmd)
 {
 	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
-	return pmd;
-}
-
-static inline pmd_t pmd_wrprotect(pmd_t pmd)
-{
-	/* Do not clobber PROT_NONE segments! */
-	if (!pmd_prot_none(pmd))
-		pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
-	return pmd;
-}
-
-static inline pmd_t pmd_mkdirty(pmd_t pmd)
-{
-	/* No dirty bit in the segment table entry. */
+	pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
+	pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
 	return pmd;
 }
 
@@ -1647,11 +1675,6 @@ static inline int has_transparent_hugepa
 {
 	return MACHINE_HAS_HPAGE ? 1 : 0;
 }
-
-static inline unsigned long pmd_pfn(pmd_t pmd)
-{
-	return pmd_val(pmd) >> PAGE_SHIFT;
-}
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -217,7 +217,7 @@ static inline void cpu_relax(void)
 	barrier();
 }
 
-#define arch_mutex_cpu_relax()  barrier()
+#define cpu_relax_lowlatency()  barrier()
 
 static inline void psw_set_key(unsigned int key)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/qdio.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/qdio.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/qdio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/qdio.h	2014-09-28 17:29:07.000000000 -0400
@@ -415,6 +415,10 @@ struct qdio_brinfo_entry_l2 {
 #define QDIO_FLAG_SYNC_OUTPUT		0x02
 #define QDIO_FLAG_PCI_OUT		0x10
 
+int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count);
+void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count);
+void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count);
+
 extern int qdio_allocate(struct qdio_initialize *);
 extern int qdio_establish(struct qdio_initialize *);
 extern int qdio_activate(struct ccw_device *);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/asm/syscall.h linux-libre-3.17-rc7-gnu/arch/s390/include/asm/syscall.h
--- linux-libre-3.16-gnu/arch/s390/include/asm/syscall.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/asm/syscall.h	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ static inline void syscall_set_return_va
 					    struct pt_regs *regs,
 					    int error, long val)
 {
-	regs->gprs[2] = error ? -error : val;
+	regs->gprs[2] = error ? error : val;
 }
 
 static inline void syscall_get_arguments(struct task_struct *task,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/uapi/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/Kbuild
--- linux-libre-3.16-gnu/arch/s390/include/uapi/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@ header-y += ioctls.h
 header-y += ipcbuf.h
 header-y += kvm.h
 header-y += kvm_para.h
+header-y += kvm_perf.h
 header-y += kvm_virtio.h
 header-y += mman.h
 header-y += monwriter.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/uapi/asm/kvm_perf.h linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/kvm_perf.h
--- linux-libre-3.16-gnu/arch/s390/include/uapi/asm/kvm_perf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/kvm_perf.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Definitions for perf-kvm on s390
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Alexander Yarygin <yarygin@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 (version 2 only)
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_KVM_PERF_S390_H
+#define __LINUX_KVM_PERF_S390_H
+
+#include <asm/sie.h>
+
+#define DECODE_STR_LEN 40
+
+#define VCPU_ID "id"
+
+#define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter"
+#define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit"
+#define KVM_EXIT_REASON "icptcode"
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/uapi/asm/sie.h linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/sie.h
--- linux-libre-3.16-gnu/arch/s390/include/uapi/asm/sie.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/sie.h	2014-09-28 17:29:07.000000000 -0400
@@ -108,6 +108,7 @@
 	exit_code_ipa0(0xB2, 0x17, "STETR"),	\
 	exit_code_ipa0(0xB2, 0x18, "PC"),	\
 	exit_code_ipa0(0xB2, 0x20, "SERVC"),	\
+	exit_code_ipa0(0xB2, 0x21, "IPTE"),	\
 	exit_code_ipa0(0xB2, 0x28, "PT"),	\
 	exit_code_ipa0(0xB2, 0x29, "ISKE"),	\
 	exit_code_ipa0(0xB2, 0x2a, "RRBE"),	\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/s390/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -283,7 +283,10 @@
 #define __NR_sched_setattr	345
 #define __NR_sched_getattr	346
 #define __NR_renameat2		347
-#define NR_syscalls 348
+#define __NR_seccomp		348
+#define __NR_getrandom		349
+#define __NR_memfd_create	350
+#define NR_syscalls 351
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/Kconfig linux-libre-3.17-rc7-gnu/arch/s390/Kconfig
--- linux-libre-3.16-gnu/arch/s390/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -92,6 +92,7 @@ config S390
 	select ARCH_INLINE_WRITE_UNLOCK_IRQ
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
+	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select BUILDTIME_EXTABLE_SORT
@@ -116,7 +117,6 @@ config S390
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FUTEX_CMPXCHG if FUTEX
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_GZIP
@@ -137,7 +137,6 @@ config S390
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_UID16 if 32BIT
 	select HAVE_VIRT_CPU_ACCOUNTING
-	select KTIME_SCALAR if 32BIT
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
 	select OLD_SIGACTION
@@ -146,6 +145,7 @@ config S390
 	select TTY
 	select VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
+	select ARCH_HAS_SG_CHAIN
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/compat_signal.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/compat_signal.c
--- linux-libre-3.16-gnu/arch/s390/kernel/compat_signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/compat_signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -320,38 +320,39 @@ static inline int map_signal(int sig)
 		return sig;
 }
 
-static int setup_frame32(int sig, struct k_sigaction *ka,
-			sigset_t *set, struct pt_regs * regs)
+static int setup_frame32(struct ksignal *ksig, sigset_t *set,
+			 struct pt_regs *regs)
 {
-	sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
+	int sig = ksig->sig;
+	sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
 
 	if (frame == (void __user *) -1UL)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (save_sigregs32(regs, &frame->sregs))
-		goto give_sigsegv;
+		return -EFAULT;
 	if (save_sigregs_gprs_high(regs, frame->gprs_high))
-		goto give_sigsegv;
+		return -EFAULT;
 	if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
 	} else {
 		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
 			       (u16 __force __user *)(frame->retcode)))
-			goto give_sigsegv;
+			return -EFAULT;
         }
 
 	/* Set up backchain. */
 	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (__force __u64) frame;
@@ -359,7 +360,7 @@ static int setup_frame32(int sig, struct
 	regs->psw.mask = PSW_MASK_BA |
 		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
-	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
+	regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler;
 
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (__force __u64) &frame->sc;
@@ -376,25 +377,21 @@ static int setup_frame32(int sig, struct
 
 	/* Place signal number on stack to allow backtrace from handler.  */
 	if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
-		goto give_sigsegv;
+		return -EFAULT;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs * regs)
+static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
+			    struct pt_regs *regs)
 {
 	int err = 0;
-	rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
+	rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
 
 	if (frame == (void __user *) -1UL)
-		goto give_sigsegv;
+		return -EFAULT;
 
-	if (copy_siginfo_to_user32(&frame->info, info))
-		goto give_sigsegv;
+	if (copy_siginfo_to_user32(&frame->info, &ksig->info))
+		return -EFAULT;
 
 	/* Create the ucontext.  */
 	err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
@@ -404,22 +401,22 @@ static int setup_rt_frame32(int sig, str
 	err |= save_sigregs_gprs_high(regs, frame->gprs_high);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
 	} else {
 		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
 			       (u16 __force __user *)(frame->retcode)))
-			goto give_sigsegv;
+			return -EFAULT;
 	}
 
 	/* Set up backchain. */
 	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (__force __u64) frame;
@@ -427,36 +424,30 @@ static int setup_rt_frame32(int sig, str
 	regs->psw.mask = PSW_MASK_BA |
 		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
-	regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
+	regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;
 
-	regs->gprs[2] = map_signal(sig);
+	regs->gprs[2] = map_signal(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;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */	
 
-void handle_signal32(unsigned long sig, struct k_sigaction *ka,
-		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
+		     struct pt_regs *regs)
 {
 	int ret;
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame32(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame32(ksig, oldset, regs);
 	else
-		ret = setup_frame32(sig, ka, oldset, regs);
-	if (ret)
-		return;
-	signal_delivered(sig, info, ka, regs,
-				 test_thread_flag(TIF_SINGLE_STEP));
+		ret = setup_frame32(ksig, oldset, regs);
+
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/compat_wrapper.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/compat_wrapper.c
--- linux-libre-3.16-gnu/arch/s390/kernel/compat_wrapper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/compat_wrapper.c	2014-09-28 17:29:07.000000000 -0400
@@ -214,3 +214,6 @@ COMPAT_SYSCALL_WRAP3(finit_module, int,
 COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
 COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
 COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
+COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
+COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/entry.h linux-libre-3.17-rc7-gnu/arch/s390/kernel/entry.h
--- linux-libre-3.16-gnu/arch/s390/kernel/entry.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/entry.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,8 +48,8 @@ void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
 void do_signal(struct pt_regs *regs);
-void handle_signal32(unsigned long sig, struct k_sigaction *ka,
-		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
+		     struct pt_regs *regs);
 void do_notify_resume(struct pt_regs *regs);
 
 void __init init_IRQ(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/ipl.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/ipl.c
--- linux-libre-3.16-gnu/arch/s390/kernel/ipl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/ipl.c	2014-09-28 17:29:07.000000000 -0400
@@ -455,22 +455,6 @@ DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%
 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
 		   IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
 
-static struct attribute *ipl_fcp_attrs[] = {
-	&sys_ipl_type_attr.attr,
-	&sys_ipl_device_attr.attr,
-	&sys_ipl_fcp_wwpn_attr.attr,
-	&sys_ipl_fcp_lun_attr.attr,
-	&sys_ipl_fcp_bootprog_attr.attr,
-	&sys_ipl_fcp_br_lba_attr.attr,
-	NULL,
-};
-
-static struct attribute_group ipl_fcp_attr_group = {
-	.attrs = ipl_fcp_attrs,
-};
-
-/* CCW ipl device attributes */
-
 static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 				     struct kobj_attribute *attr, char *page)
 {
@@ -487,6 +471,23 @@ static ssize_t ipl_ccw_loadparm_show(str
 static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
 	__ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 
+static struct attribute *ipl_fcp_attrs[] = {
+	&sys_ipl_type_attr.attr,
+	&sys_ipl_device_attr.attr,
+	&sys_ipl_fcp_wwpn_attr.attr,
+	&sys_ipl_fcp_lun_attr.attr,
+	&sys_ipl_fcp_bootprog_attr.attr,
+	&sys_ipl_fcp_br_lba_attr.attr,
+	&sys_ipl_ccw_loadparm_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_fcp_attr_group = {
+	.attrs = ipl_fcp_attrs,
+};
+
+/* CCW ipl device attributes */
+
 static struct attribute *ipl_ccw_attrs_vm[] = {
 	&sys_ipl_type_attr.attr,
 	&sys_ipl_device_attr.attr,
@@ -765,28 +766,10 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%
 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
 		   reipl_block_fcp->ipl_info.fcp.devno);
 
-static struct attribute *reipl_fcp_attrs[] = {
-	&sys_reipl_fcp_device_attr.attr,
-	&sys_reipl_fcp_wwpn_attr.attr,
-	&sys_reipl_fcp_lun_attr.attr,
-	&sys_reipl_fcp_bootprog_attr.attr,
-	&sys_reipl_fcp_br_lba_attr.attr,
-	NULL,
-};
-
-static struct attribute_group reipl_fcp_attr_group = {
-	.attrs = reipl_fcp_attrs,
-};
-
-/* CCW reipl device attributes */
-
-DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-	reipl_block_ccw->ipl_info.ccw.devno);
-
 static void reipl_get_ascii_loadparm(char *loadparm,
 				     struct ipl_parameter_block *ibp)
 {
-	memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
+	memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
 	EBCASC(loadparm, LOADPARM_LEN);
 	loadparm[LOADPARM_LEN] = 0;
 	strim(loadparm);
@@ -821,13 +804,50 @@ static ssize_t reipl_generic_loadparm_st
 		return -EINVAL;
 	}
 	/* initialize loadparm with blanks */
-	memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
+	memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
 	/* copy and convert to ebcdic */
-	memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
-	ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
+	memcpy(ipb->hdr.loadparm, buf, lp_len);
+	ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
 	return len;
 }
 
+/* FCP wrapper */
+static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *page)
+{
+	return reipl_generic_loadparm_show(reipl_block_fcp, page);
+}
+
+static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
+					struct kobj_attribute *attr,
+					const char *buf, size_t len)
+{
+	return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
+	__ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
+					    reipl_fcp_loadparm_store);
+
+static struct attribute *reipl_fcp_attrs[] = {
+	&sys_reipl_fcp_device_attr.attr,
+	&sys_reipl_fcp_wwpn_attr.attr,
+	&sys_reipl_fcp_lun_attr.attr,
+	&sys_reipl_fcp_bootprog_attr.attr,
+	&sys_reipl_fcp_br_lba_attr.attr,
+	&sys_reipl_fcp_loadparm_attr.attr,
+	NULL,
+};
+
+static struct attribute_group reipl_fcp_attr_group = {
+	.attrs = reipl_fcp_attrs,
+};
+
+/* CCW reipl device attributes */
+
+DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+	reipl_block_ccw->ipl_info.ccw.devno);
+
 /* NSS wrapper */
 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
 				       struct kobj_attribute *attr, char *page)
@@ -1125,11 +1145,10 @@ static void reipl_block_ccw_fill_parms(s
 	/* LOADPARM */
 	/* check if read scp info worked and set loadparm */
 	if (sclp_ipl_info.is_valid)
-		memcpy(ipb->ipl_info.ccw.load_parm,
-				&sclp_ipl_info.loadparm, LOADPARM_LEN);
+		memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
 	else
 		/* read scp info failed: set empty loadparm (EBCDIC blanks) */
-		memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
+		memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
 	ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
 
 	/* VM PARM */
@@ -1251,9 +1270,16 @@ static int __init reipl_fcp_init(void)
 		return rc;
 	}
 
-	if (ipl_info.type == IPL_TYPE_FCP)
+	if (ipl_info.type == IPL_TYPE_FCP) {
 		memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
-	else {
+		/*
+		 * Fix loadparm: There are systems where the (SCSI) LOADPARM
+		 * is invalid in the SCSI IPL parameter block, so take it
+		 * always from sclp_ipl_info.
+		 */
+		memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
+		       LOADPARM_LEN);
+	} else {
 		reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
 		reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
 		reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
@@ -1864,7 +1890,23 @@ static void __init shutdown_actions_init
 
 static int __init s390_ipl_init(void)
 {
+	char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
+
 	sclp_get_ipl_info(&sclp_ipl_info);
+	/*
+	 * Fix loadparm: There are systems where the (SCSI) LOADPARM
+	 * returned by read SCP info is invalid (contains EBCDIC blanks)
+	 * when the system has been booted via diag308. In that case we use
+	 * the value from diag308, if available.
+	 *
+	 * There are also systems where diag308 store does not work in
+	 * case the system is booted from HMC. Fortunately in this case
+	 * READ SCP info provides the correct value.
+	 */
+	if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
+	    diag308_set_works)
+		memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
+		       LOADPARM_LEN);
 	shutdown_actions_init();
 	shutdown_triggers_init();
 	return 0;
@@ -2060,6 +2102,13 @@ void s390_reset_system(void (*func)(void
 	S390_lowcore.program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
+	/*
+	 * Clear subchannel ID and number to signal new kernel that no CCW or
+	 * SCSI IPL has been done (for kexec and kdump)
+	 */
+	S390_lowcore.subchannel_id = 0;
+	S390_lowcore.subchannel_nr = 0;
+
 	/* Store status at absolute zero */
 	store_status();
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/irq.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/irq.c
--- linux-libre-3.16-gnu/arch/s390/kernel/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct irq
 EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
 
 struct irq_class {
+	int irq;
 	char *name;
 	char *desc;
 };
@@ -45,9 +46,9 @@ struct irq_class {
  * up with having a sum which accounts each interrupt twice.
  */
 static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
-	[EXT_INTERRUPT]  = {.name = "EXT"},
-	[IO_INTERRUPT]	 = {.name = "I/O"},
-	[THIN_INTERRUPT] = {.name = "AIO"},
+	{.irq = EXT_INTERRUPT,	.name = "EXT"},
+	{.irq = IO_INTERRUPT,	.name = "I/O"},
+	{.irq = THIN_INTERRUPT, .name = "AIO"},
 };
 
 /*
@@ -56,38 +57,38 @@ static const struct irq_class irqclass_m
  * In addition this list contains non external / I/O events like NMIs.
  */
 static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
-	[IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
-	[IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
-	[IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
-	[IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
-	[IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
-	[IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
-	[IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
-	[IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
-	[IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
-	[IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
-	[IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
-	[IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
-	[IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
-	[IRQIO_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
-	[IRQIO_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
-	[IRQIO_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
-	[IRQIO_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
-	[IRQIO_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
-	[IRQIO_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
-	[IRQIO_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
-	[IRQIO_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
-	[IRQIO_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
-	[IRQIO_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
-	[IRQIO_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
-	[IRQIO_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
-	[IRQIO_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
-	[IRQIO_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
-	[IRQIO_MSI]  = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
-	[IRQIO_VIR]  = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
-	[IRQIO_VAI]  = {.name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
-	[NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},
-	[CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},
+	{.irq = IRQEXT_CLK, .name = "CLK", .desc = "[EXT] Clock Comparator"},
+	{.irq = IRQEXT_EXC, .name = "EXC", .desc = "[EXT] External Call"},
+	{.irq = IRQEXT_EMS, .name = "EMS", .desc = "[EXT] Emergency Signal"},
+	{.irq = IRQEXT_TMR, .name = "TMR", .desc = "[EXT] CPU Timer"},
+	{.irq = IRQEXT_TLA, .name = "TAL", .desc = "[EXT] Timing Alert"},
+	{.irq = IRQEXT_PFL, .name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
+	{.irq = IRQEXT_DSD, .name = "DSD", .desc = "[EXT] DASD Diag"},
+	{.irq = IRQEXT_VRT, .name = "VRT", .desc = "[EXT] Virtio"},
+	{.irq = IRQEXT_SCP, .name = "SCP", .desc = "[EXT] Service Call"},
+	{.irq = IRQEXT_IUC, .name = "IUC", .desc = "[EXT] IUCV"},
+	{.irq = IRQEXT_CMS, .name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
+	{.irq = IRQEXT_CMC, .name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
+	{.irq = IRQEXT_CMR, .name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+	{.irq = IRQIO_CIO,  .name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
+	{.irq = IRQIO_QAI,  .name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
+	{.irq = IRQIO_DAS,  .name = "DAS", .desc = "[I/O] DASD"},
+	{.irq = IRQIO_C15,  .name = "C15", .desc = "[I/O] 3215"},
+	{.irq = IRQIO_C70,  .name = "C70", .desc = "[I/O] 3270"},
+	{.irq = IRQIO_TAP,  .name = "TAP", .desc = "[I/O] Tape"},
+	{.irq = IRQIO_VMR,  .name = "VMR", .desc = "[I/O] Unit Record Devices"},
+	{.irq = IRQIO_LCS,  .name = "LCS", .desc = "[I/O] LCS"},
+	{.irq = IRQIO_CLW,  .name = "CLW", .desc = "[I/O] CLAW"},
+	{.irq = IRQIO_CTC,  .name = "CTC", .desc = "[I/O] CTC"},
+	{.irq = IRQIO_APB,  .name = "APB", .desc = "[I/O] AP Bus"},
+	{.irq = IRQIO_ADM,  .name = "ADM", .desc = "[I/O] EADM Subchannel"},
+	{.irq = IRQIO_CSC,  .name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+	{.irq = IRQIO_PCI,  .name = "PCI", .desc = "[I/O] PCI Interrupt" },
+	{.irq = IRQIO_MSI,  .name = "MSI", .desc = "[I/O] MSI Interrupt" },
+	{.irq = IRQIO_VIR,  .name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
+	{.irq = IRQIO_VAI,  .name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
+	{.irq = NMI_NMI,    .name = "NMI", .desc = "[NMI] Machine Check"},
+	{.irq = CPU_RST,    .name = "RST", .desc = "[CPU] CPU Restart"},
 };
 
 void __init init_IRQ(void)
@@ -116,33 +117,37 @@ void do_IRQ(struct pt_regs *regs, int ir
  */
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int irq = *(loff_t *) v;
-	int cpu;
+	int index = *(loff_t *) v;
+	int cpu, irq;
 
 	get_online_cpus();
-	if (irq == 0) {
+	if (index == 0) {
 		seq_puts(p, "           ");
 		for_each_online_cpu(cpu)
 			seq_printf(p, "CPU%d       ", cpu);
 		seq_putc(p, '\n');
 		goto out;
 	}
-	if (irq < NR_IRQS) {
-		if (irq >= NR_IRQS_BASE)
+	if (index < NR_IRQS) {
+		if (index >= NR_IRQS_BASE)
 			goto out;
-		seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
+		/* Adjust index to process irqclass_main_desc array entries */
+		index--;
+		seq_printf(p, "%s: ", irqclass_main_desc[index].name);
+		irq = irqclass_main_desc[index].irq;
 		for_each_online_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
 		seq_putc(p, '\n');
 		goto out;
 	}
-	for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
-		seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
+	for (index = 0; index < NR_ARCH_IRQS; index++) {
+		seq_printf(p, "%s: ", irqclass_sub_desc[index].name);
+		irq = irqclass_sub_desc[index].irq;
 		for_each_online_cpu(cpu)
 			seq_printf(p, "%10u ",
 				   per_cpu(irq_stat, cpu).irqs[irq]);
-		if (irqclass_sub_desc[irq].desc)
-			seq_printf(p, "  %s", irqclass_sub_desc[irq].desc);
+		if (irqclass_sub_desc[index].desc)
+			seq_printf(p, "  %s", irqclass_sub_desc[index].desc);
 		seq_putc(p, '\n');
 	}
 out:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/mcount64.S linux-libre-3.17-rc7-gnu/arch/s390/kernel/mcount64.S
--- linux-libre-3.16-gnu/arch/s390/kernel/mcount64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/mcount64.S	2014-09-28 17:29:07.000000000 -0400
@@ -20,9 +20,6 @@ ENTRY(_mcount)
 
 ENTRY(ftrace_caller)
 #endif
-	larl	%r1,function_trace_stop
-	icm	%r1,0xf,0(%r1)
-	bnzr	%r14
 	stmg	%r2,%r5,32(%r15)
 	stg	%r14,112(%r15)
 	lgr	%r1,%r15
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/mcount.S linux-libre-3.17-rc7-gnu/arch/s390/kernel/mcount.S
--- linux-libre-3.16-gnu/arch/s390/kernel/mcount.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/mcount.S	2014-09-28 17:29:07.000000000 -0400
@@ -21,13 +21,9 @@ ENTRY(_mcount)
 ENTRY(ftrace_caller)
 #endif
 	stm	%r2,%r5,16(%r15)
-	bras	%r1,2f
+	bras	%r1,1f
 0:	.long	ftrace_trace_function
-1:	.long	function_trace_stop
-2:	l	%r2,1b-0b(%r1)
-	icm	%r2,0xf,0(%r2)
-	jnz	3f
-	st	%r14,56(%r15)
+1:	st	%r14,56(%r15)
 	lr	%r0,%r15
 	ahi	%r15,-96
 	l	%r3,100(%r15)
@@ -50,7 +46,7 @@ ENTRY(ftrace_graph_caller)
 #endif
 	ahi	%r15,96
 	l	%r14,56(%r15)
-3:	lm	%r2,%r5,16(%r15)
+	lm	%r2,%r5,16(%r15)
 	br	%r14
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/perf_cpum_cf.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/perf_cpum_cf.c
--- linux-libre-3.16-gnu/arch/s390/kernel/perf_cpum_cf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/perf_cpum_cf.c	2014-09-28 17:29:07.000000000 -0400
@@ -411,12 +411,6 @@ static int cpumf_pmu_event_init(struct p
 	case PERF_TYPE_HARDWARE:
 	case PERF_TYPE_HW_CACHE:
 	case PERF_TYPE_RAW:
-		/* The CPU measurement counter facility does not have overflow
-		 * interrupts to do sampling.  Sampling must be provided by
-		 * external means, for example, by timers.
-		 */
-		if (is_sampling_event(event))
-			return -ENOENT;
 		err = __hw_perf_event_init(event);
 		break;
 	default:
@@ -681,6 +675,12 @@ static int __init cpumf_pmu_init(void)
 		goto out;
 	}
 
+	/* The CPU measurement counter facility does not have overflow
+	 * interrupts to do sampling.  Sampling must be provided by
+	 * external means, for example, by timers.
+	 */
+	cpumf_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	cpumf_pmu.attr_groups = cpumf_cf_event_group();
 	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
 	if (rc) {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/setup.c
--- linux-libre-3.16-gnu/arch/s390/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
+#include <linux/random.h>
 #include <linux/user.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
@@ -61,6 +62,7 @@
 #include <asm/diag.h>
 #include <asm/os_info.h>
 #include <asm/sclp.h>
+#include <asm/sysinfo.h>
 #include "entry.h"
 
 /*
@@ -501,6 +503,8 @@ static int kdump_mem_notifier(struct not
 {
 	struct memory_notify *arg = data;
 
+	if (action != MEM_GOING_OFFLINE)
+		return NOTIFY_OK;
 	if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
 		return NOTIFY_BAD;
 	if (arg->start_pfn > PFN_DOWN(crashk_res.end))
@@ -764,6 +768,7 @@ static void __init setup_hwcaps(void)
 #endif
 
 	get_cpu_id(&cpu_id);
+	add_device_randomness(&cpu_id, sizeof(cpu_id));
 	switch (cpu_id.machine) {
 	case 0x9672:
 #if !defined(CONFIG_64BIT)
@@ -802,6 +807,19 @@ static void __init setup_hwcaps(void)
 }
 
 /*
+ * Add system information as device randomness
+ */
+static void __init setup_randomness(void)
+{
+	struct sysinfo_3_2_2 *vmms;
+
+	vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL);
+	if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count)
+		add_device_randomness(&vmms, vmms->count);
+	free_page((unsigned long) vmms);
+}
+
+/*
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
@@ -899,6 +917,9 @@ void __init setup_arch(char **cmdline_p)
 
 	/* Setup zfcpdump support */
 	setup_zfcpdump();
+
+	/* Add system specific data to the random pool */
+	setup_randomness();
 }
 
 #ifdef CONFIG_32BIT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/signal.c
--- linux-libre-3.16-gnu/arch/s390/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k
 	frame = get_sigframe(ka, regs, sizeof(sigframe));
 
 	if (frame == (void __user *) -1UL)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (save_sigregs(regs, &frame->sregs))
-		goto give_sigsegv;
+		return -EFAULT;
 	if (__put_user(&frame->sregs, &frame->sc.sregs))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k
 			frame->retcode | PSW_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
 	                       (u16 __user *)(frame->retcode)))
-			goto give_sigsegv;
+			return -EFAULT;
 	}
 
 	/* Set up backchain. */
 	if (__put_user(regs->gprs[15], (addr_t __user *) frame))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k
 
 	/* Place signal number on stack to allow backtrace from handler.  */
 	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
-		goto give_sigsegv;
+		return -EFAULT;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs * regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	int err = 0;
 	rt_sigframe __user *frame;
 
-	frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
+	frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
 
 	if (frame == (void __user *) -1UL)
-		goto give_sigsegv;
+		return -EFAULT;
 
-	if (copy_siginfo_to_user(&frame->info, info))
-		goto give_sigsegv;
+	if (copy_siginfo_to_user(&frame->info, &ksig->info))
+		return -EFAULT;
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struc
 	err |= save_sigregs(regs, &frame->uc.uc_mcontext);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
                 regs->gprs[14] = (unsigned long)
-			ka->sa.sa_restorer | PSW_ADDR_AMODE;
+			ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
 	} else {
                 regs->gprs[14] = (unsigned long)
 			frame->retcode | PSW_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
 			       (u16 __user *)(frame->retcode)))
-			goto give_sigsegv;
+			return -EFAULT;
 	}
 
 	/* Set up backchain. */
 	if (__put_user(regs->gprs[15], (addr_t __user *) frame))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struc
 	regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
 		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
-	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
+	regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE;
 
-	regs->gprs[2] = map_signal(sig);
+	regs->gprs[2] = map_signal(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;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
-			 siginfo_t *info, sigset_t *oldset,
-			 struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, sigset_t *oldset,
+			  struct pt_regs *regs)
 {
 	int ret;
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
-	if (ret)
-		return;
-	signal_delivered(sig, info, ka, regs,
-				 test_thread_flag(TIF_SINGLE_STEP));
+		ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs);
+
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
 }
 
 /*
@@ -345,9 +334,7 @@ static void handle_signal(unsigned long
  */
 void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 	sigset_t *oldset = sigmask_to_save();
 
 	/*
@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs)
 	 */
 	current_thread_info()->system_call =
 		test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
 		if (current_thread_info()->system_call) {
 			regs->int_code = current_thread_info()->system_call;
@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs)
 				regs->gprs[2] = -EINTR;
 				break;
 			case -ERESTARTSYS:
-				if (!(ka.sa.sa_flags & SA_RESTART)) {
+				if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
 					regs->gprs[2] = -EINTR;
 					break;
 				}
@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs)
 		clear_pt_regs_flag(regs, PIF_SYSCALL);
 
 		if (is_compat_task())
-			handle_signal32(signr, &ka, &info, oldset, regs);
+			handle_signal32(&ksig, oldset, regs);
 		else
-			handle_signal(signr, &ka, &info, oldset, regs);
+			handle_signal(&ksig, oldset, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/syscalls.S linux-libre-3.17-rc7-gnu/arch/s390/kernel/syscalls.S
--- linux-libre-3.16-gnu/arch/s390/kernel/syscalls.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/syscalls.S	2014-09-28 17:29:07.000000000 -0400
@@ -356,3 +356,6 @@ SYSCALL(sys_finit_module,sys_finit_modul
 SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
 SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
 SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
+SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
+SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
+SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/time.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/time.c
--- linux-libre-3.16-gnu/arch/s390/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -214,26 +214,26 @@ void update_vsyscall(struct timekeeper *
 {
 	u64 nsecps;
 
-	if (tk->clock != &clocksource_tod)
+	if (tk->tkr.clock != &clocksource_tod)
 		return;
 
 	/* Make userspace gettimeofday spin until we're done. */
 	++vdso_data->tb_update_count;
 	smp_wmb();
-	vdso_data->xtime_tod_stamp = tk->clock->cycle_last;
+	vdso_data->xtime_tod_stamp = tk->tkr.cycle_last;
 	vdso_data->xtime_clock_sec = tk->xtime_sec;
-	vdso_data->xtime_clock_nsec = tk->xtime_nsec;
+	vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
 	vdso_data->wtom_clock_sec =
 		tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
-	vdso_data->wtom_clock_nsec = tk->xtime_nsec +
-		+ ((u64) tk->wall_to_monotonic.tv_nsec << tk->shift);
-	nsecps = (u64) NSEC_PER_SEC << tk->shift;
+	vdso_data->wtom_clock_nsec = tk->tkr.xtime_nsec +
+		+ ((u64) tk->wall_to_monotonic.tv_nsec << tk->tkr.shift);
+	nsecps = (u64) NSEC_PER_SEC << tk->tkr.shift;
 	while (vdso_data->wtom_clock_nsec >= nsecps) {
 		vdso_data->wtom_clock_nsec -= nsecps;
 		vdso_data->wtom_clock_sec++;
 	}
-	vdso_data->tk_mult = tk->mult;
-	vdso_data->tk_shift = tk->shift;
+	vdso_data->tk_mult = tk->tkr.mult;
+	vdso_data->tk_shift = tk->tkr.shift;
 	smp_wmb();
 	++vdso_data->tb_update_count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/vdso32/clock_gettime.S linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso32/clock_gettime.S
--- linux-libre-3.16-gnu/arch/s390/kernel/vdso32/clock_gettime.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso32/clock_gettime.S	2014-09-28 17:29:07.000000000 -0400
@@ -22,13 +22,11 @@ __kernel_clock_gettime:
 	basr	%r5,0
 0:	al	%r5,21f-0b(%r5)			/* get &_vdso_data */
 	chi	%r2,__CLOCK_REALTIME
-	je	10f
+	je	11f
 	chi	%r2,__CLOCK_MONOTONIC
 	jne	19f
 
 	/* CLOCK_MONOTONIC */
-	ltr	%r3,%r3
-	jz	9f				/* tp == NULL */
 1:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
 	tml	%r4,0x0001			/* pending update ? loop */
 	jnz	1b
@@ -67,12 +65,10 @@ __kernel_clock_gettime:
 	j	6b
 8:	st	%r2,0(%r3)			/* store tp->tv_sec */
 	st	%r1,4(%r3)			/* store tp->tv_nsec */
-9:	lhi	%r2,0
+	lhi	%r2,0
 	br	%r14
 
 	/* CLOCK_REALTIME */
-10:	ltr	%r3,%r3				/* tp == NULL */
-	jz	18f
 11:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
 	tml	%r4,0x0001			/* pending update ? loop */
 	jnz	11b
@@ -111,7 +107,7 @@ __kernel_clock_gettime:
 	j	15b
 17:	st	%r2,0(%r3)			/* store tp->tv_sec */
 	st	%r1,4(%r3)			/* store tp->tv_nsec */
-18:	lhi	%r2,0
+	lhi	%r2,0
 	br	%r14
 
 	/* Fallback to system call */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/vdso64/clock_gettime.S linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso64/clock_gettime.S
--- linux-libre-3.16-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,7 @@ __kernel_clock_gettime:
 	.cfi_startproc
 	larl	%r5,_vdso_data
 	cghi	%r2,__CLOCK_REALTIME
-	je	4f
+	je	5f
 	cghi	%r2,__CLOCK_THREAD_CPUTIME_ID
 	je	9f
 	cghi	%r2,-2		/* Per-thread CPUCLOCK with PID=0, VIRT=1 */
@@ -30,8 +30,6 @@ __kernel_clock_gettime:
 	jne	12f
 
 	/* CLOCK_MONOTONIC */
-	ltgr	%r3,%r3
-	jz	3f				/* tp == NULL */
 0:	lg	%r4,__VDSO_UPD_COUNT(%r5)	/* load update counter */
 	tmll	%r4,0x0001			/* pending update ? loop */
 	jnz	0b
@@ -53,12 +51,10 @@ __kernel_clock_gettime:
 	j	1b
 2:	stg	%r0,0(%r3)			/* store tp->tv_sec */
 	stg	%r1,8(%r3)			/* store tp->tv_nsec */
-3:	lghi	%r2,0
+	lghi	%r2,0
 	br	%r14
 
 	/* CLOCK_REALTIME */
-4:	ltr	%r3,%r3				/* tp == NULL */
-	jz	8f
 5:	lg	%r4,__VDSO_UPD_COUNT(%r5)	/* load update counter */
 	tmll	%r4,0x0001			/* pending update ? loop */
 	jnz	5b
@@ -80,7 +76,7 @@ __kernel_clock_gettime:
 	j	6b
 7:	stg	%r0,0(%r3)			/* store tp->tv_sec */
 	stg	%r1,8(%r3)			/* store tp->tv_nsec */
-8:	lghi	%r2,0
+	lghi	%r2,0
 	br	%r14
 
 	/* CLOCK_THREAD_CPUTIME_ID for this thread */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kernel/vdso.c linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso.c
--- linux-libre-3.16-gnu/arch/s390/kernel/vdso.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kernel/vdso.c	2014-09-28 17:29:07.000000000 -0400
@@ -316,18 +316,3 @@ static int __init vdso_init(void)
 	return 0;
 }
 early_initcall(vdso_init);
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/diag.c linux-libre-3.17-rc7-gnu/arch/s390/kvm/diag.c
--- linux-libre-3.16-gnu/arch/s390/kvm/diag.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/diag.c	2014-09-28 17:29:07.000000000 -0400
@@ -176,7 +176,8 @@ static int __diag_ipl_functions(struct k
 		return -EOPNOTSUPP;
 	}
 
-	kvm_s390_vcpu_stop(vcpu);
+	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+		kvm_s390_vcpu_stop(vcpu);
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/intercept.c linux-libre-3.17-rc7-gnu/arch/s390/kvm/intercept.c
--- linux-libre-3.16-gnu/arch/s390/kvm/intercept.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/intercept.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,32 +56,26 @@ static int handle_noop(struct kvm_vcpu *
 static int handle_stop(struct kvm_vcpu *vcpu)
 {
 	int rc = 0;
+	unsigned int action_bits;
 
 	vcpu->stat.exit_stop_request++;
-	spin_lock_bh(&vcpu->arch.local_int.lock);
-
 	trace_kvm_s390_stop_request(vcpu->arch.local_int.action_bits);
 
-	if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
-		kvm_s390_vcpu_stop(vcpu);
-		vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
-		VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
-		rc = -EOPNOTSUPP;
-	}
+	action_bits = vcpu->arch.local_int.action_bits;
 
-	if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
-		vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
-		/* store status must be called unlocked. Since local_int.lock
-		 * only protects local_int.* and not guest memory we can give
-		 * up the lock here */
-		spin_unlock_bh(&vcpu->arch.local_int.lock);
+	if (!(action_bits & ACTION_STOP_ON_STOP))
+		return 0;
+
+	if (action_bits & ACTION_STORE_ON_STOP) {
 		rc = kvm_s390_vcpu_store_status(vcpu,
 						KVM_S390_STORE_STATUS_NOADDR);
-		if (rc >= 0)
-			rc = -EOPNOTSUPP;
-	} else
-		spin_unlock_bh(&vcpu->arch.local_int.lock);
-	return rc;
+		if (rc)
+			return rc;
+	}
+
+	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+		kvm_s390_vcpu_stop(vcpu);
+	return -EOPNOTSUPP;
 }
 
 static int handle_validity(struct kvm_vcpu *vcpu)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/interrupt.c linux-libre-3.17-rc7-gnu/arch/s390/kvm/interrupt.c
--- linux-libre-3.16-gnu/arch/s390/kvm/interrupt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/interrupt.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,6 +158,9 @@ static void __reset_intercept_indicators
 					       LCTL_CR10 | LCTL_CR11);
 		vcpu->arch.sie_block->ictl |= (ICTL_STCTL | ICTL_PINT);
 	}
+
+	if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP)
+		atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
 }
 
 static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
@@ -544,13 +547,13 @@ int kvm_cpu_has_interrupt(struct kvm_vcp
 	int rc = 0;
 
 	if (atomic_read(&li->active)) {
-		spin_lock_bh(&li->lock);
+		spin_lock(&li->lock);
 		list_for_each_entry(inti, &li->list, list)
 			if (__interrupt_is_deliverable(vcpu, inti)) {
 				rc = 1;
 				break;
 			}
-		spin_unlock_bh(&li->lock);
+		spin_unlock(&li->lock);
 	}
 
 	if ((!rc) && atomic_read(&fi->active)) {
@@ -585,88 +588,56 @@ int kvm_cpu_has_pending_timer(struct kvm
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
 {
 	u64 now, sltime;
-	DECLARE_WAITQUEUE(wait, current);
 
 	vcpu->stat.exit_wait_state++;
-	if (kvm_cpu_has_interrupt(vcpu))
-		return 0;
 
-	__set_cpu_idle(vcpu);
-	spin_lock_bh(&vcpu->arch.local_int.lock);
-	vcpu->arch.local_int.timer_due = 0;
-	spin_unlock_bh(&vcpu->arch.local_int.lock);
+	/* fast path */
+	if (kvm_cpu_has_pending_timer(vcpu) || kvm_arch_vcpu_runnable(vcpu))
+		return 0;
 
 	if (psw_interrupts_disabled(vcpu)) {
 		VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
-		__unset_cpu_idle(vcpu);
 		return -EOPNOTSUPP; /* disabled wait */
 	}
 
+	__set_cpu_idle(vcpu);
 	if (!ckc_interrupts_enabled(vcpu)) {
 		VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
 		goto no_timer;
 	}
 
 	now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
-	if (vcpu->arch.sie_block->ckc < now) {
-		__unset_cpu_idle(vcpu);
-		return 0;
-	}
-
 	sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
-
 	hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
 	VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
 no_timer:
 	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
-	spin_lock(&vcpu->arch.local_int.float_int->lock);
-	spin_lock_bh(&vcpu->arch.local_int.lock);
-	add_wait_queue(&vcpu->wq, &wait);
-	while (list_empty(&vcpu->arch.local_int.list) &&
-		list_empty(&vcpu->arch.local_int.float_int->list) &&
-		(!vcpu->arch.local_int.timer_due) &&
-		!signal_pending(current) &&
-		!kvm_s390_si_ext_call_pending(vcpu)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_bh(&vcpu->arch.local_int.lock);
-		spin_unlock(&vcpu->arch.local_int.float_int->lock);
-		schedule();
-		spin_lock(&vcpu->arch.local_int.float_int->lock);
-		spin_lock_bh(&vcpu->arch.local_int.lock);
-	}
+	kvm_vcpu_block(vcpu);
 	__unset_cpu_idle(vcpu);
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&vcpu->wq, &wait);
-	spin_unlock_bh(&vcpu->arch.local_int.lock);
-	spin_unlock(&vcpu->arch.local_int.float_int->lock);
 	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
 	hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
 	return 0;
 }
 
-void kvm_s390_tasklet(unsigned long parm)
+void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
 {
-	struct kvm_vcpu *vcpu = (struct kvm_vcpu *) parm;
-
-	spin_lock(&vcpu->arch.local_int.lock);
-	vcpu->arch.local_int.timer_due = 1;
-	if (waitqueue_active(&vcpu->wq))
+	if (waitqueue_active(&vcpu->wq)) {
+		/*
+		 * The vcpu gave up the cpu voluntarily, mark it as a good
+		 * yield-candidate.
+		 */
+		vcpu->preempted = true;
 		wake_up_interruptible(&vcpu->wq);
-	spin_unlock(&vcpu->arch.local_int.lock);
+	}
 }
 
-/*
- * low level hrtimer wake routine. Because this runs in hardirq context
- * we schedule a tasklet to do the real work.
- */
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
 {
 	struct kvm_vcpu *vcpu;
 
 	vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
-	vcpu->preempted = true;
-	tasklet_schedule(&vcpu->arch.tasklet);
+	kvm_s390_vcpu_wakeup(vcpu);
 
 	return HRTIMER_NORESTART;
 }
@@ -676,13 +647,13 @@ void kvm_s390_clear_local_irqs(struct kv
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 	struct kvm_s390_interrupt_info  *n, *inti = NULL;
 
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	list_for_each_entry_safe(inti, n, &li->list, list) {
 		list_del(&inti->list);
 		kfree(inti);
 	}
 	atomic_set(&li->active, 0);
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 
 	/* clear pending external calls set by sigp interpretation facility */
 	atomic_clear_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags);
@@ -701,7 +672,7 @@ void kvm_s390_deliver_pending_interrupts
 	if (atomic_read(&li->active)) {
 		do {
 			deliver = 0;
-			spin_lock_bh(&li->lock);
+			spin_lock(&li->lock);
 			list_for_each_entry_safe(inti, n, &li->list, list) {
 				if (__interrupt_is_deliverable(vcpu, inti)) {
 					list_del(&inti->list);
@@ -712,7 +683,7 @@ void kvm_s390_deliver_pending_interrupts
 			}
 			if (list_empty(&li->list))
 				atomic_set(&li->active, 0);
-			spin_unlock_bh(&li->lock);
+			spin_unlock(&li->lock);
 			if (deliver) {
 				__do_deliver_interrupt(vcpu, inti);
 				kfree(inti);
@@ -758,7 +729,7 @@ void kvm_s390_deliver_pending_machine_ch
 	if (atomic_read(&li->active)) {
 		do {
 			deliver = 0;
-			spin_lock_bh(&li->lock);
+			spin_lock(&li->lock);
 			list_for_each_entry_safe(inti, n, &li->list, list) {
 				if ((inti->type == KVM_S390_MCHK) &&
 				    __interrupt_is_deliverable(vcpu, inti)) {
@@ -770,7 +741,7 @@ void kvm_s390_deliver_pending_machine_ch
 			}
 			if (list_empty(&li->list))
 				atomic_set(&li->active, 0);
-			spin_unlock_bh(&li->lock);
+			spin_unlock(&li->lock);
 			if (deliver) {
 				__do_deliver_interrupt(vcpu, inti);
 				kfree(inti);
@@ -817,11 +788,11 @@ int kvm_s390_inject_program_int(struct k
 
 	VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
 	trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1);
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	list_add(&inti->list, &li->list);
 	atomic_set(&li->active, 1);
 	BUG_ON(waitqueue_active(li->wq));
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 	return 0;
 }
 
@@ -842,11 +813,11 @@ int kvm_s390_inject_prog_irq(struct kvm_
 
 	inti->type = KVM_S390_PROGRAM_INT;
 	memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm));
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	list_add(&inti->list, &li->list);
 	atomic_set(&li->active, 1);
 	BUG_ON(waitqueue_active(li->wq));
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 	return 0;
 }
 
@@ -934,12 +905,10 @@ static int __inject_vm(struct kvm *kvm,
 	}
 	dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
 	li = &dst_vcpu->arch.local_int;
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
-	if (waitqueue_active(li->wq))
-		wake_up_interruptible(li->wq);
-	kvm_get_vcpu(kvm, sigcpu)->preempted = true;
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
+	kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu));
 unlock_fi:
 	spin_unlock(&fi->lock);
 	mutex_unlock(&kvm->lock);
@@ -1081,7 +1050,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu
 
 	mutex_lock(&vcpu->kvm->lock);
 	li = &vcpu->arch.local_int;
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	if (inti->type == KVM_S390_PROGRAM_INT)
 		list_add(&inti->list, &li->list);
 	else
@@ -1090,11 +1059,9 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu
 	if (inti->type == KVM_S390_SIGP_STOP)
 		li->action_bits |= ACTION_STOP_ON_STOP;
 	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
-	if (waitqueue_active(&vcpu->wq))
-		wake_up_interruptible(&vcpu->wq);
-	vcpu->preempted = true;
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 	mutex_unlock(&vcpu->kvm->lock);
+	kvm_s390_vcpu_wakeup(vcpu);
 	return 0;
 }
 
@@ -1589,8 +1556,7 @@ static int set_adapter_int(struct kvm_ke
 	return ret;
 }
 
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
-			  struct kvm_kernel_irq_routing_entry *e,
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
 			  const struct kvm_irq_routing_entry *ue)
 {
 	int ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/Kconfig linux-libre-3.17-rc7-gnu/arch/s390/kvm/Kconfig
--- linux-libre-3.16-gnu/arch/s390/kvm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@ config KVM
 	select KVM_ASYNC_PF
 	select KVM_ASYNC_PF_SYNC
 	select HAVE_KVM_IRQCHIP
+	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQ_ROUTING
 	---help---
 	  Support hosting paravirtualized guest machines using the SIE
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/kvm-s390.c linux-libre-3.17-rc7-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-3.16-gnu/arch/s390/kvm/kvm-s390.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/kvm-s390.c	2014-09-28 17:29:07.000000000 -0400
@@ -146,7 +146,7 @@ long kvm_arch_dev_ioctl(struct file *fil
 	return -EINVAL;
 }
 
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 	int r;
 
@@ -166,7 +166,9 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_IOEVENTFD:
 	case KVM_CAP_DEVICE_CTRL:
 	case KVM_CAP_ENABLE_CAP_VM:
+	case KVM_CAP_S390_IRQCHIP:
 	case KVM_CAP_VM_ATTRIBUTES:
+	case KVM_CAP_MP_STATE:
 		r = 1;
 		break;
 	case KVM_CAP_NR_VCPUS:
@@ -595,7 +597,8 @@ static void kvm_s390_vcpu_initial_reset(
 	vcpu->arch.sie_block->pp = 0;
 	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
 	kvm_clear_async_pf_completion_queue(vcpu);
-	kvm_s390_vcpu_stop(vcpu);
+	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+		kvm_s390_vcpu_stop(vcpu);
 	kvm_s390_clear_local_irqs(vcpu);
 }
 
@@ -647,8 +650,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 			return rc;
 	}
 	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
-	tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
-		     (unsigned long) vcpu);
 	vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
 	get_cpu_id(&vcpu->arch.cpu_id);
 	vcpu->arch.cpu_id.version = 0xff;
@@ -926,7 +927,7 @@ static int kvm_arch_vcpu_ioctl_set_initi
 {
 	int rc = 0;
 
-	if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
+	if (!is_vcpu_stopped(vcpu))
 		rc = -EBUSY;
 	else {
 		vcpu->run->psw_mask = psw.mask;
@@ -980,13 +981,34 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
-	return -EINVAL; /* not implemented yet */
+	/* CHECK_STOP and LOAD are not supported yet */
+	return is_vcpu_stopped(vcpu) ? KVM_MP_STATE_STOPPED :
+				       KVM_MP_STATE_OPERATING;
 }
 
 int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
-	return -EINVAL; /* not implemented yet */
+	int rc = 0;
+
+	/* user space knows about this interface - let it control the state */
+	vcpu->kvm->arch.user_cpu_state_ctrl = 1;
+
+	switch (mp_state->mp_state) {
+	case KVM_MP_STATE_STOPPED:
+		kvm_s390_vcpu_stop(vcpu);
+		break;
+	case KVM_MP_STATE_OPERATING:
+		kvm_s390_vcpu_start(vcpu);
+		break;
+	case KVM_MP_STATE_LOAD:
+	case KVM_MP_STATE_CHECK_STOP:
+		/* fall through - CHECK_STOP and LOAD are not supported yet */
+	default:
+		rc = -ENXIO;
+	}
+
+	return rc;
 }
 
 bool kvm_s390_cmma_enabled(struct kvm *kvm)
@@ -1045,6 +1067,9 @@ retry:
 		goto retry;
 	}
 
+	/* nothing to do, just clear the request */
+	clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+
 	return 0;
 }
 
@@ -1284,19 +1309,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
-	kvm_s390_vcpu_start(vcpu);
-
-	switch (kvm_run->exit_reason) {
-	case KVM_EXIT_S390_SIEIC:
-	case KVM_EXIT_UNKNOWN:
-	case KVM_EXIT_INTR:
-	case KVM_EXIT_S390_RESET:
-	case KVM_EXIT_S390_UCONTROL:
-	case KVM_EXIT_S390_TSCH:
-	case KVM_EXIT_DEBUG:
-		break;
-	default:
-		BUG();
+	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) {
+		kvm_s390_vcpu_start(vcpu);
+	} else if (is_vcpu_stopped(vcpu)) {
+		pr_err_ratelimited("kvm-s390: can't run stopped vcpu %d\n",
+				   vcpu->vcpu_id);
+		return -EINVAL;
 	}
 
 	vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
@@ -1413,11 +1431,6 @@ int kvm_s390_vcpu_store_status(struct kv
 	return kvm_s390_store_status_unloaded(vcpu, addr);
 }
 
-static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
-{
-	return atomic_read(&(vcpu)->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
-}
-
 static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
 {
 	kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);
@@ -1451,7 +1464,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu
 
 	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1);
 	/* Only one cpu at a time may enter/leave the STOPPED state. */
-	spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
+	spin_lock(&vcpu->kvm->arch.start_stop_lock);
 	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
 
 	for (i = 0; i < online_vcpus; i++) {
@@ -1477,7 +1490,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu
 	 * Let's play safe and flush the VCPU at startup.
 	 */
 	vcpu->arch.sie_block->ihcpu  = 0xffff;
-	spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
+	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
 	return;
 }
 
@@ -1491,10 +1504,18 @@ void kvm_s390_vcpu_stop(struct kvm_vcpu
 
 	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0);
 	/* Only one cpu at a time may enter/leave the STOPPED state. */
-	spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
+	spin_lock(&vcpu->kvm->arch.start_stop_lock);
 	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
 
+	/* Need to lock access to action_bits to avoid a SIGP race condition */
+	spin_lock(&vcpu->arch.local_int.lock);
 	atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
+
+	/* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */
+	vcpu->arch.local_int.action_bits &=
+				 ~(ACTION_STOP_ON_STOP | ACTION_STORE_ON_STOP);
+	spin_unlock(&vcpu->arch.local_int.lock);
+
 	__disable_ibs_on_vcpu(vcpu);
 
 	for (i = 0; i < online_vcpus; i++) {
@@ -1512,7 +1533,7 @@ void kvm_s390_vcpu_stop(struct kvm_vcpu
 		__enable_ibs_on_vcpu(started_vcpu);
 	}
 
-	spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
+	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
 	return;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/kvm-s390.h linux-libre-3.17-rc7-gnu/arch/s390/kvm/kvm-s390.h
--- linux-libre-3.16-gnu/arch/s390/kvm/kvm-s390.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/kvm-s390.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,9 +45,9 @@ do { \
 	  d_args); \
 } while (0)
 
-static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
+static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
 {
-	return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
+	return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
 }
 
 static inline int kvm_is_ucontrol(struct kvm *kvm)
@@ -129,9 +129,15 @@ static inline void kvm_s390_set_psw_cc(s
 	vcpu->arch.sie_block->gpsw.mask |= cc << 44;
 }
 
+/* are cpu states controlled by user space */
+static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
+{
+	return kvm->arch.user_cpu_state_ctrl != 0;
+}
+
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
+void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
-void kvm_s390_tasklet(unsigned long parm);
 void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
 void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu);
 void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/kvm/sigp.c linux-libre-3.17-rc7-gnu/arch/s390/kvm/sigp.c
--- linux-libre-3.16-gnu/arch/s390/kvm/sigp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/kvm/sigp.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,8 +125,9 @@ static int __sigp_external_call(struct k
 	return rc ? rc : SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
-static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
+static int __inject_sigp_stop(struct kvm_vcpu *dst_vcpu, int action)
 {
+	struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int;
 	struct kvm_s390_interrupt_info *inti;
 	int rc = SIGP_CC_ORDER_CODE_ACCEPTED;
 
@@ -135,7 +136,13 @@ static int __inject_sigp_stop(struct kvm
 		return -ENOMEM;
 	inti->type = KVM_S390_SIGP_STOP;
 
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
+	if (li->action_bits & ACTION_STOP_ON_STOP) {
+		/* another SIGP STOP is pending */
+		kfree(inti);
+		rc = SIGP_CC_BUSY;
+		goto out;
+	}
 	if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
 		kfree(inti);
 		if ((action & ACTION_STORE_ON_STOP) != 0)
@@ -144,19 +151,17 @@ static int __inject_sigp_stop(struct kvm
 	}
 	list_add_tail(&inti->list, &li->list);
 	atomic_set(&li->active, 1);
-	atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
 	li->action_bits |= action;
-	if (waitqueue_active(li->wq))
-		wake_up_interruptible(li->wq);
+	atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
+	kvm_s390_vcpu_wakeup(dst_vcpu);
 out:
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 
 	return rc;
 }
 
 static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
 {
-	struct kvm_s390_local_interrupt *li;
 	struct kvm_vcpu *dst_vcpu = NULL;
 	int rc;
 
@@ -166,9 +171,8 @@ static int __sigp_stop(struct kvm_vcpu *
 	dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
 	if (!dst_vcpu)
 		return SIGP_CC_NOT_OPERATIONAL;
-	li = &dst_vcpu->arch.local_int;
 
-	rc = __inject_sigp_stop(li, action);
+	rc = __inject_sigp_stop(dst_vcpu, action);
 
 	VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
 
@@ -238,7 +242,7 @@ static int __sigp_set_prefix(struct kvm_
 	if (!inti)
 		return SIGP_CC_BUSY;
 
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	/* cpu must be in stopped state */
 	if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
 		*reg &= 0xffffffff00000000UL;
@@ -253,13 +257,12 @@ static int __sigp_set_prefix(struct kvm_
 
 	list_add_tail(&inti->list, &li->list);
 	atomic_set(&li->active, 1);
-	if (waitqueue_active(li->wq))
-		wake_up_interruptible(li->wq);
+	kvm_s390_vcpu_wakeup(dst_vcpu);
 	rc = SIGP_CC_ORDER_CODE_ACCEPTED;
 
 	VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address);
 out_li:
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 	return rc;
 }
 
@@ -275,9 +278,9 @@ static int __sigp_store_status_at_addr(s
 	if (!dst_vcpu)
 		return SIGP_CC_NOT_OPERATIONAL;
 
-	spin_lock_bh(&dst_vcpu->arch.local_int.lock);
+	spin_lock(&dst_vcpu->arch.local_int.lock);
 	flags = atomic_read(dst_vcpu->arch.local_int.cpuflags);
-	spin_unlock_bh(&dst_vcpu->arch.local_int.lock);
+	spin_unlock(&dst_vcpu->arch.local_int.lock);
 	if (!(flags & CPUSTAT_STOPPED)) {
 		*reg &= 0xffffffff00000000UL;
 		*reg |= SIGP_STATUS_INCORRECT_STATE;
@@ -338,10 +341,10 @@ static int sigp_check_callable(struct kv
 	if (!dst_vcpu)
 		return SIGP_CC_NOT_OPERATIONAL;
 	li = &dst_vcpu->arch.local_int;
-	spin_lock_bh(&li->lock);
+	spin_lock(&li->lock);
 	if (li->action_bits & ACTION_STOP_ON_STOP)
 		rc = SIGP_CC_BUSY;
-	spin_unlock_bh(&li->lock);
+	spin_unlock(&li->lock);
 
 	return rc;
 }
@@ -461,12 +464,7 @@ int kvm_s390_handle_sigp_pei(struct kvm_
 		dest_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
 		BUG_ON(dest_vcpu == NULL);
 
-		spin_lock_bh(&dest_vcpu->arch.local_int.lock);
-		if (waitqueue_active(&dest_vcpu->wq))
-			wake_up_interruptible(&dest_vcpu->wq);
-		dest_vcpu->preempted = true;
-		spin_unlock_bh(&dest_vcpu->arch.local_int.lock);
-
+		kvm_s390_vcpu_wakeup(dest_vcpu);
 		kvm_s390_set_psw_cc(vcpu, SIGP_CC_ORDER_CODE_ACCEPTED);
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/mm/hugetlbpage.c linux-libre-3.17-rc7-gnu/arch/s390/mm/hugetlbpage.c
--- linux-libre-3.16-gnu/arch/s390/mm/hugetlbpage.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/mm/hugetlbpage.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,42 +10,33 @@
 
 static inline pmd_t __pte_to_pmd(pte_t pte)
 {
-	int none, young, prot;
 	pmd_t pmd;
 
 	/*
-	 * Convert encoding		  pte bits	  pmd bits
-	 *				.IR...wrdytp	..R...I...y.
-	 * empty			.10...000000 -> ..0...1...0.
-	 * prot-none, clean, old	.11...000001 -> ..0...1...1.
-	 * prot-none, clean, young	.11...000101 -> ..1...1...1.
-	 * prot-none, dirty, old	.10...001001 -> ..0...1...1.
-	 * prot-none, dirty, young	.10...001101 -> ..1...1...1.
-	 * read-only, clean, old	.11...010001 -> ..1...1...0.
-	 * read-only, clean, young	.01...010101 -> ..1...0...1.
-	 * read-only, dirty, old	.11...011001 -> ..1...1...0.
-	 * read-only, dirty, young	.01...011101 -> ..1...0...1.
-	 * read-write, clean, old	.11...110001 -> ..0...1...0.
-	 * read-write, clean, young	.01...110101 -> ..0...0...1.
-	 * read-write, dirty, old	.10...111001 -> ..0...1...0.
-	 * read-write, dirty, young	.00...111101 -> ..0...0...1.
-	 * Huge ptes are dirty by definition, a clean pte is made dirty
-	 * by the conversion.
+	 * Convert encoding		  pte bits	   pmd bits
+	 *				.IR...wrdytp	dy..R...I...wr
+	 * empty			.10...000000 -> 00..0...1...00
+	 * prot-none, clean, old	.11...000001 -> 00..1...1...00
+	 * prot-none, clean, young	.11...000101 -> 01..1...1...00
+	 * prot-none, dirty, old	.10...001001 -> 10..1...1...00
+	 * prot-none, dirty, young	.10...001101 -> 11..1...1...00
+	 * read-only, clean, old	.11...010001 -> 00..1...1...01
+	 * read-only, clean, young	.01...010101 -> 01..1...0...01
+	 * read-only, dirty, old	.11...011001 -> 10..1...1...01
+	 * read-only, dirty, young	.01...011101 -> 11..1...0...01
+	 * read-write, clean, old	.11...110001 -> 00..0...1...11
+	 * read-write, clean, young	.01...110101 -> 01..0...0...11
+	 * read-write, dirty, old	.10...111001 -> 10..0...1...11
+	 * read-write, dirty, young	.00...111101 -> 11..0...0...11
 	 */
 	if (pte_present(pte)) {
 		pmd_val(pmd) = pte_val(pte) & PAGE_MASK;
-		if (pte_val(pte) & _PAGE_INVALID)
-			pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
-		none = (pte_val(pte) & _PAGE_PRESENT) &&
-			!(pte_val(pte) & _PAGE_READ) &&
-			!(pte_val(pte) & _PAGE_WRITE);
-		prot = (pte_val(pte) & _PAGE_PROTECT) &&
-			!(pte_val(pte) & _PAGE_WRITE);
-		young = pte_val(pte) & _PAGE_YOUNG;
-		if (none || young)
-			pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
-		if (prot || (none && young))
-			pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_READ) >> 4;
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_WRITE) >> 4;
+		pmd_val(pmd) |=	(pte_val(pte) & _PAGE_INVALID) >> 5;
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_PROTECT);
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
 	} else
 		pmd_val(pmd) = _SEGMENT_ENTRY_INVALID;
 	return pmd;
@@ -56,34 +47,31 @@ static inline pte_t __pmd_to_pte(pmd_t p
 	pte_t pte;
 
 	/*
-	 * Convert encoding	  pmd bits	  pte bits
-	 *			..R...I...y.	.IR...wrdytp
-	 * empty		..0...1...0. -> .10...000000
-	 * prot-none, old	..0...1...1. -> .10...001001
-	 * prot-none, young	..1...1...1. -> .10...001101
-	 * read-only, old	..1...1...0. -> .11...011001
-	 * read-only, young	..1...0...1. -> .01...011101
-	 * read-write, old	..0...1...0. -> .10...111001
-	 * read-write, young	..0...0...1. -> .00...111101
-	 * Huge ptes are dirty by definition
+	 * Convert encoding		   pmd bits	    pte bits
+	 *				dy..R...I...wr	  .IR...wrdytp
+	 * empty			00..0...1...00 -> .10...001100
+	 * prot-none, clean, old	00..0...1...00 -> .10...000001
+	 * prot-none, clean, young	01..0...1...00 -> .10...000101
+	 * prot-none, dirty, old	10..0...1...00 -> .10...001001
+	 * prot-none, dirty, young	11..0...1...00 -> .10...001101
+	 * read-only, clean, old	00..1...1...01 -> .11...010001
+	 * read-only, clean, young	01..1...1...01 -> .11...010101
+	 * read-only, dirty, old	10..1...1...01 -> .11...011001
+	 * read-only, dirty, young	11..1...1...01 -> .11...011101
+	 * read-write, clean, old	00..0...1...11 -> .10...110001
+	 * read-write, clean, young	01..0...1...11 -> .10...110101
+	 * read-write, dirty, old	10..0...1...11 -> .10...111001
+	 * read-write, dirty, young	11..0...1...11 -> .10...111101
 	 */
 	if (pmd_present(pmd)) {
-		pte_val(pte) = _PAGE_PRESENT | _PAGE_LARGE | _PAGE_DIRTY |
-			(pmd_val(pmd) & PAGE_MASK);
-		if (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID)
-			pte_val(pte) |= _PAGE_INVALID;
-		if (pmd_prot_none(pmd)) {
-			if (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT)
-				pte_val(pte) |= _PAGE_YOUNG;
-		} else {
-			pte_val(pte) |= _PAGE_READ;
-			if (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT)
-				pte_val(pte) |= _PAGE_PROTECT;
-			else
-				pte_val(pte) |= _PAGE_WRITE;
-			if (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG)
-				pte_val(pte) |= _PAGE_YOUNG;
-		}
+		pte_val(pte) = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN_LARGE;
+		pte_val(pte) |= _PAGE_LARGE | _PAGE_PRESENT;
+		pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_READ) << 4;
+		pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) << 4;
+		pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) << 5;
+		pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT);
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
+		pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
 	} else
 		pte_val(pte) = _PAGE_INVALID;
 	return pte;
@@ -96,6 +84,7 @@ void set_huge_pte_at(struct mm_struct *m
 
 	pmd = __pte_to_pmd(pte);
 	if (!MACHINE_HAS_HPAGE) {
+		/* Emulated huge ptes loose the dirty and young bit */
 		pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
 		pmd_val(pmd) |= pte_page(pte)[1].index;
 	} else
@@ -113,6 +102,8 @@ pte_t huge_ptep_get(pte_t *ptep)
 		origin = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
 		pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
 		pmd_val(pmd) |= *(unsigned long *) origin;
+		/* Emulated huge ptes are young and dirty by definition */
+		pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG | _SEGMENT_ENTRY_DIRTY;
 	}
 	return __pmd_to_pte(pmd);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/mm/init.c linux-libre-3.17-rc7-gnu/arch/s390/mm/init.c
--- linux-libre-3.16-gnu/arch/s390/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,6 +43,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __att
 
 unsigned long empty_zero_page, zero_page_mask;
 EXPORT_SYMBOL(empty_zero_page);
+EXPORT_SYMBOL(zero_page_mask);
 
 static void __init setup_zero_pages(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/mm/pgtable.c linux-libre-3.17-rc7-gnu/arch/s390/mm/pgtable.c
--- linux-libre-3.16-gnu/arch/s390/mm/pgtable.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/mm/pgtable.c	2014-09-28 17:29:07.000000000 -0400
@@ -986,11 +986,21 @@ int set_guest_storage_key(struct mm_stru
 	pte_t *ptep;
 
 	down_read(&mm->mmap_sem);
+retry:
 	ptep = get_locked_pte(current->mm, addr, &ptl);
 	if (unlikely(!ptep)) {
 		up_read(&mm->mmap_sem);
 		return -EFAULT;
 	}
+	if (!(pte_val(*ptep) & _PAGE_INVALID) &&
+	     (pte_val(*ptep) & _PAGE_PROTECT)) {
+			pte_unmap_unlock(*ptep, ptl);
+			if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
+				up_read(&mm->mmap_sem);
+				return -EFAULT;
+			}
+			goto retry;
+		}
 
 	new = old = pgste_get_lock(ptep);
 	pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
@@ -1279,6 +1289,7 @@ static unsigned long page_table_realloc_
 {
 	unsigned long next, *table, *new;
 	struct page *page;
+	spinlock_t *ptl;
 	pmd_t *pmd;
 
 	pmd = pmd_offset(pud, addr);
@@ -1296,7 +1307,7 @@ again:
 		if (!new)
 			return -ENOMEM;
 
-		spin_lock(&mm->page_table_lock);
+		ptl = pmd_lock(mm, pmd);
 		if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
 			/* Nuke pmd entry pointing to the "short" page table */
 			pmdp_flush_lazy(mm, addr, pmd);
@@ -1310,7 +1321,7 @@ again:
 			page_table_free_rcu(tlb, table);
 			new = NULL;
 		}
-		spin_unlock(&mm->page_table_lock);
+		spin_unlock(ptl);
 		if (new) {
 			page_table_free_pgste(new);
 			goto again;
@@ -1432,6 +1443,9 @@ int pmdp_set_access_flags(struct vm_area
 {
 	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
 
+	entry = pmd_mkyoung(entry);
+	if (dirty)
+		entry = pmd_mkdirty(entry);
 	if (pmd_same(*pmdp, entry))
 		return 0;
 	pmdp_invalidate(vma, address, pmdp);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/net/bpf_jit_comp.c linux-libre-3.17-rc7-gnu/arch/s390/net/bpf_jit_comp.c
--- linux-libre-3.16-gnu/arch/s390/net/bpf_jit_comp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/net/bpf_jit_comp.c	2014-09-28 17:29:07.000000000 -0400
@@ -812,7 +812,7 @@ static struct bpf_binary_header *bpf_all
 	return header;
 }
 
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
 {
 	struct bpf_binary_header *header = NULL;
 	unsigned long size, prg_len, lit_len;
@@ -875,7 +875,7 @@ out:
 	kfree(addrs);
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
 	struct bpf_binary_header *header = (void *)addr;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,8 @@
  *   Thomas Klein
  */
 
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci_clp.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_clp.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci_clp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_clp.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,8 +5,8 @@
  *   Jan Glauber <jang@linux.vnet.ibm.com>
  */
 
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci_debug.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_debug.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci_debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,8 +5,8 @@
  *    Jan Glauber <jang@linux.vnet.ibm.com>
  */
 
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/seq_file.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci_dma.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_dma.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,13 @@
 
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
+static int s390_iommu_strict;
+
+static int zpci_refresh_global(struct zpci_dev *zdev)
+{
+	return zpci_refresh_trans((u64) zdev->fh << 32, zdev->start_dma,
+				  zdev->iommu_pages * PAGE_SIZE);
+}
 
 static unsigned long *dma_alloc_cpu_table(void)
 {
@@ -155,18 +162,15 @@ static int dma_update_trans(struct zpci_
 	}
 
 	/*
-	 * rpcit is not required to establish new translations when previously
-	 * invalid translation-table entries are validated, however it is
-	 * required when altering previously valid entries.
+	 * 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
+	 * 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 &&
-	    ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID))
-		/*
-		 * TODO: also need to check that the old entry is indeed INVALID
-		 * and not only for one page but for the whole range...
-		 * -> now we WARN_ON in that case but with lazy unmap that
-		 * needs to be redone!
-		 */
+			(!s390_iommu_strict ||
+			((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)))
 		goto no_refresh;
 
 	rc = zpci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
@@ -220,16 +224,21 @@ static unsigned long __dma_alloc_iommu(s
 static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size)
 {
 	unsigned long offset, flags;
+	int wrap = 0;
 
 	spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
 	offset = __dma_alloc_iommu(zdev, zdev->next_bit, size);
-	if (offset == -1)
+	if (offset == -1) {
+		/* wrap-around */
 		offset = __dma_alloc_iommu(zdev, 0, size);
+		wrap = 1;
+	}
 
 	if (offset != -1) {
 		zdev->next_bit = offset + size;
-		if (zdev->next_bit >= zdev->iommu_pages)
-			zdev->next_bit = 0;
+		if (!zdev->tlb_refresh && !s390_iommu_strict && wrap)
+			/* global flush after wrap-around with lazy unmap */
+			zpci_refresh_global(zdev);
 	}
 	spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
 	return offset;
@@ -243,7 +252,11 @@ static void dma_free_iommu(struct zpci_d
 	if (!zdev->iommu_bitmap)
 		goto out;
 	bitmap_clear(zdev->iommu_bitmap, offset, size);
-	if (offset >= zdev->next_bit)
+	/*
+	 * Lazy flush for unmap: need to move next_bit to avoid address re-use
+	 * until wrap-around.
+	 */
+	if (!s390_iommu_strict && offset >= zdev->next_bit)
 		zdev->next_bit = offset + size;
 out:
 	spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
@@ -504,3 +517,12 @@ struct dma_map_ops s390_dma_ops = {
 	/* dma_supported is unconditionally true without a callback */
 };
 EXPORT_SYMBOL_GPL(s390_dma_ops);
+
+static int __init s390_iommu_setup(char *str)
+{
+	if (!strncmp(str, "strict", 6))
+		s390_iommu_strict = 1;
+	return 0;
+}
+
+__setup("s390_iommu=", s390_iommu_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci_event.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_event.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,8 +5,8 @@
  *    Jan Glauber <jang@linux.vnet.ibm.com>
  */
 
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/s390/pci/pci_sysfs.c linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_sysfs.c
--- linux-libre-3.16-gnu/arch/s390/pci/pci_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/s390/pci/pci_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,8 +5,8 @@
  *   Jan Glauber <jang@linux.vnet.ibm.com>
  */
 
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/score/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/score/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/score/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/score/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -8,5 +8,6 @@ generic-y += cputime.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += xor.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/score/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/score/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/score/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/score/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@ 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-3.16-gnu/arch/score/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/score/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/score/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/score/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_SCATTERLIST_H
-#define _ASM_SCORE_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCORE_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/score/include/uapi/asm/ptrace.h linux-libre-3.17-rc7-gnu/arch/score/include/uapi/asm/ptrace.h
--- linux-libre-3.16-gnu/arch/score/include/uapi/asm/ptrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/score/include/uapi/asm/ptrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,17 +4,6 @@
 #define PTRACE_GETREGS		12
 #define PTRACE_SETREGS		13
 
-#define PC		32
-#define CONDITION	33
-#define ECR		34
-#define EMA		35
-#define CEH		36
-#define CEL		37
-#define COUNTER		38
-#define LDCR		39
-#define STCR		40
-#define PSR		41
-
 #define SINGLESTEP16_INSN	0x7006
 #define SINGLESTEP32_INSN	0x840C8000
 #define BREAKPOINT16_INSN	0x7002		/* work on SPG300 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/score/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/score/kernel/signal.c
--- linux-libre-3.16-gnu/arch/score/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/score/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,15 +173,15 @@ badframe:
 	return 0;
 }
 
-static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
-		int signr, sigset_t *set, siginfo_t *info)
+static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
+			  sigset_t *set)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/*
 	 * Set up the return code ...
@@ -194,7 +194,7 @@ static int setup_rt_frame(struct k_sigac
 	err |= __put_user(0x80008002, frame->rs_code + 1);
 	flush_cache_sigtramp((unsigned long) frame->rs_code);
 
-	err |= copy_siginfo_to_user(&frame->rs_info, info);
+	err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
 	err |= __put_user(NULL, &frame->rs_uc.uc_link);
 	err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]);
@@ -202,26 +202,23 @@ static int setup_rt_frame(struct k_sigac
 	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	regs->regs[0] = (unsigned long) frame;
 	regs->regs[3] = (unsigned long) frame->rs_code;
-	regs->regs[4] = signr;
+	regs->regs[4] = ksig->sig;
 	regs->regs[5] = (unsigned long) &frame->rs_info;
 	regs->regs[6] = (unsigned long) &frame->rs_uc;
-	regs->regs[29] = (unsigned long) ka->sa.sa_handler;
-	regs->cp0_epc = (unsigned long) ka->sa.sa_handler;
+	regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler;
+	regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler;
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(signr, current);
-	return -EFAULT;
 }
 
-static void handle_signal(unsigned long sig, siginfo_t *info,
-	struct k_sigaction *ka, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
+	int ret;
+
 	if (regs->is_syscall) {
 		switch (regs->regs[4]) {
 		case ERESTART_RESTARTBLOCK:
@@ -229,7 +226,7 @@ static void handle_signal(unsigned long
 			regs->regs[4] = EINTR;
 			break;
 		case ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->regs[4] = EINTR;
 				break;
 			}
@@ -245,17 +242,14 @@ static void handle_signal(unsigned long
 	/*
 	 * Set up the stack frame
 	 */
-	if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
-		return;
+	ret = setup_rt_frame(ksig, regs, sigmask_to_save());
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 static void do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which is why we may in certain
@@ -265,10 +259,9 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/boards/Kconfig linux-libre-3.17-rc7-gnu/arch/sh/boards/Kconfig
--- linux-libre-3.16-gnu/arch/sh/boards/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/boards/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -371,7 +371,7 @@ if SH_MAGIC_PANEL_R2
 menu "Magic Panel R2 options"
 
 config SH_MAGIC_PANEL_R2_VERSION
-	int SH_MAGIC_PANEL_R2_VERSION
+	int "Magic Panel R2 Version"
 	default "3"
 	help
 	  Set the version of the Magic Panel R2
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/boards/mach-ecovec24/setup.c linux-libre-3.17-rc7-gnu/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-3.16-gnu/arch/sh/boards/mach-ecovec24/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/boards/mach-ecovec24/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210
 	.name	= "asoc-simple-card",
 	.dev	= {
 		.platform_data	= &fsi_da7210_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/configs/sdk7780_defconfig linux-libre-3.17-rc7-gnu/arch/sh/configs/sdk7780_defconfig
--- linux-libre-3.16-gnu/arch/sh/configs/sdk7780_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/configs/sdk7780_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,7 @@ CONFIG_PCI_DEBUG=y
 CONFIG_PCCARD=y
 CONFIG_YENTA=y
 CONFIG_HOTPLUG_PCI=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/configs/sh2007_defconfig linux-libre-3.17-rc7-gnu/arch/sh/configs/sh2007_defconfig
--- linux-libre-3.16-gnu/arch/sh/configs/sh2007_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/configs/sh2007_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@ CONFIG_CMDLINE_OVERWRITE=y
 CONFIG_CMDLINE="console=ttySC1,115200 ip=dhcp root=/dev/nfs rw nfsroot=/nfs/rootfs,rsize=1024,wsize=1024 earlyprintk=sh-sci.1"
 CONFIG_PCCARD=y
 CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
@@ -52,7 +53,6 @@ CONFIG_CDROM_PKTCDVD=y
 # CONFIG_MISC_DEVICES is not set
 CONFIG_RAID_ATTRS=y
 CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/drivers/dma/dma-sh.c linux-libre-3.17-rc7-gnu/arch/sh/drivers/dma/dma-sh.c
--- linux-libre-3.16-gnu/arch/sh/drivers/dma/dma-sh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/drivers/dma/dma-sh.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
  * Define the default configuration for dual address memory-memory transfer.
  * The 0x400 value represents auto-request, external->external.
  */
-#define RS_DUAL	(DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
+#define RS_DUAL	(DM_INC | SM_INC | RS_AUTO | TS_INDEX2VAL(XMIT_SZ_32BIT))
 
 static unsigned long dma_find_base(unsigned int chan)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/drivers/dma/Kconfig linux-libre-3.17-rc7-gnu/arch/sh/drivers/dma/Kconfig
--- linux-libre-3.16-gnu/arch/sh/drivers/dma/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/drivers/dma/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -12,9 +12,8 @@ config SH_DMA_IRQ_MULTI
 	default y if CPU_SUBTYPE_SH7750  || CPU_SUBTYPE_SH7751  || \
 		     CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || \
 		     CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7091  || \
-		     CPU_SUBTYPE_SH7763  || CPU_SUBTYPE_SH7764  || \
-		     CPU_SUBTYPE_SH7780  || CPU_SUBTYPE_SH7785  || \
-		     CPU_SUBTYPE_SH7760
+		     CPU_SUBTYPE_SH7763  || CPU_SUBTYPE_SH7780  || \
+		     CPU_SUBTYPE_SH7785  || CPU_SUBTYPE_SH7760
 
 config SH_DMA_API
 	depends on SH_DMA
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/include/asm/dma-register.h linux-libre-3.17-rc7-gnu/arch/sh/include/asm/dma-register.h
--- linux-libre-3.16-gnu/arch/sh/include/asm/dma-register.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/asm/dma-register.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,17 +13,17 @@
 #ifndef DMA_REGISTER_H
 #define DMA_REGISTER_H
 
-/* DMA register */
-#define SAR	0x00
-#define DAR	0x04
-#define TCR	0x08
-#define CHCR	0x0C
-#define DMAOR	0x40
+/* DMA registers */
+#define SAR	0x00	/* Source Address Register */
+#define DAR	0x04	/* Destination Address Register */
+#define TCR	0x08	/* Transfer Count Register */
+#define CHCR	0x0C	/* Channel Control Register */
+#define DMAOR	0x40	/* DMA Operation Register */
 
 /* DMAOR definitions */
-#define DMAOR_AE	0x00000004
+#define DMAOR_AE	0x00000004	/* Address Error Flag */
 #define DMAOR_NMIF	0x00000002
-#define DMAOR_DME	0x00000001
+#define DMAOR_DME	0x00000001	/* DMA Master Enable */
 
 /* Definitions for the SuperH DMAC */
 #define REQ_L	0x00000000
@@ -34,18 +34,20 @@
 #define ACK_W	0x00020000
 #define ACK_H	0x00000000
 #define ACK_L	0x00010000
-#define DM_INC	0x00004000
-#define DM_DEC	0x00008000
-#define DM_FIX	0x0000c000
-#define SM_INC	0x00001000
-#define SM_DEC	0x00002000
-#define SM_FIX	0x00003000
+#define DM_INC	0x00004000	/* Destination addresses are incremented */
+#define DM_DEC	0x00008000	/* Destination addresses are decremented */
+#define DM_FIX	0x0000c000	/* Destination address is fixed */
+#define SM_INC	0x00001000	/* Source addresses are incremented */
+#define SM_DEC	0x00002000	/* Source addresses are decremented */
+#define SM_FIX	0x00003000	/* Source address is fixed */
 #define RS_IN	0x00000200
 #define RS_OUT	0x00000300
+#define RS_AUTO	0x00000400	/* Auto Request */
+#define RS_ERS	0x00000800	/* DMA extended resource selector */
 #define TS_BLK	0x00000040
 #define TM_BUR	0x00000020
-#define CHCR_DE	0x00000001
-#define CHCR_TE	0x00000002
-#define CHCR_IE	0x00000004
+#define CHCR_DE	0x00000001	/* DMA Enable */
+#define CHCR_TE	0x00000002	/* Transfer End Flag */
+#define CHCR_IE	0x00000004	/* Interrupt Enable */
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/include/asm/io_noioport.h linux-libre-3.17-rc7-gnu/arch/sh/include/asm/io_noioport.h
--- linux-libre-3.16-gnu/arch/sh/include/asm/io_noioport.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/asm/io_noioport.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,17 @@ static inline void outl(unsigned int x,
 	BUG();
 }
 
+static inline void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+	BUG();
+	return NULL;
+}
+
+static inline void ioport_unmap(void __iomem *addr)
+{
+	BUG();
+}
+
 #define inb_p(addr)	inb(addr)
 #define inw_p(addr)	inw(addr)
 #define inl_p(addr)	inl(addr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/sh/include/asm/page.h
--- linux-libre-3.16-gnu/arch/sh/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -186,11 +186,6 @@ typedef struct page *pgtable_t;
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
 
-/* vDSO support */
-#ifdef CONFIG_VSYSCALL
-#define __HAVE_ARCH_GATE_AREA
-#endif
-
 /*
  * Some drivers need to perform DMA into kmalloc'ed buffers
  * and so we have to increase the kmalloc minalign for this.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/sh/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/sh/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,6 +97,7 @@ 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-3.16-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h linux-libre-3.17-rc7-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h
--- linux-libre-3.16-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,6 @@
 #define CHCR_TS_HIGH_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7780) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define CHCR_TS_LOW_MASK	0x00000018
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/include/cpu-sh4a/cpu/dma.h linux-libre-3.17-rc7-gnu/arch/sh/include/cpu-sh4a/cpu/dma.h
--- linux-libre-3.16-gnu/arch/sh/include/cpu-sh4a/cpu/dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/include/cpu-sh4a/cpu/dma.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,8 +14,7 @@
 #define DMTE4_IRQ	evt2irq(0xb80)
 #define DMAE0_IRQ	evt2irq(0xbc0)	/* DMA Error IRQ*/
 #define SH_DMAC_BASE0	0xFE008020
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-	defined(CONFIG_CPU_SUBTYPE_SH7764)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define DMTE0_IRQ	evt2irq(0x640)
 #define DMTE4_IRQ	evt2irq(0x780)
 #define DMAE0_IRQ	evt2irq(0x6c0)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/Kconfig linux-libre-3.17-rc7-gnu/arch/sh/Kconfig
--- linux-libre-3.16-gnu/arch/sh/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,6 @@ config SUPERH32
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select HAVE_FUNCTION_GRAPH_TRACER
@@ -173,6 +172,7 @@ menu "System type"
 #
 config CPU_SH2
 	bool
+	select SH_INTC
 
 config CPU_SH2A
 	bool
@@ -183,6 +183,7 @@ config CPU_SH3
 	bool
 	select CPU_HAS_INTEVT
 	select CPU_HAS_SR_RB
+	select SH_INTC
 	select SYS_SUPPORTS_SH_TMU
 
 config CPU_SH4
@@ -190,6 +191,7 @@ config CPU_SH4
 	select CPU_HAS_INTEVT
 	select CPU_HAS_SR_RB
 	select CPU_HAS_FPU if !CPU_SH4AL_DSP
+	select SH_INTC
 	select SYS_SUPPORTS_SH_TMU
 	select SYS_SUPPORTS_HUGETLBFS if MMU
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
--- linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	2014-09-28 17:29:07.000000000 -0400
@@ -307,7 +307,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]),
 	CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]),
 
-	CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[HWBLK_CMT]),
+	CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
 	CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
 	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
 
@@ -332,6 +332,8 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]),
 	CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[HWBLK_USB1]),
 	CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[HWBLK_USB0]),
+	CLKDEV_CON_ID("usb1", &mstp_clks[HWBLK_USB1]),
+	CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB0]),
 	CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]),
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
--- linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,62 +30,62 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF0_TX,
 		.addr		= 0xffe0000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x21,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF0_RX,
 		.addr		= 0xffe00014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x22,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF1_TX,
 		.addr		= 0xffe1000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x25,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF1_RX,
 		.addr		= 0xffe10014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x26,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
 		.addr		= 0xffe2000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x29,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
 		.addr		= 0xffe20014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2a,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SIUA_TX,
 		.addr		= 0xa454c098,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xb1,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SIUA_RX,
 		.addr		= 0xa454c090,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xb2,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SIUB_TX,
 		.addr		= 0xa454c09c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xb5,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SIUB_RX,
 		.addr		= 0xa454c094,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xb6,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_TX,
 		.addr		= 0x04ce0030,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc1,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_RX,
 		.addr		= 0x04ce0030,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc2,
 	},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
--- linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,122 +36,122 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF0_TX,
 		.addr		= 0xffe0000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x21,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF0_RX,
 		.addr		= 0xffe00014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x22,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF1_TX,
 		.addr		= 0xffe1000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x25,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF1_RX,
 		.addr		= 0xffe10014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x26,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
 		.addr		= 0xffe2000c,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x29,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
 		.addr		= 0xffe20014,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2a,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF3_TX,
 		.addr		= 0xa4e30020,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2d,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF3_RX,
 		.addr		= 0xa4e30024,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2e,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF4_TX,
 		.addr		= 0xa4e40020,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x31,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF4_RX,
 		.addr		= 0xa4e40024,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x32,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF5_TX,
 		.addr		= 0xa4e50020,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x35,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SCIF5_RX,
 		.addr		= 0xa4e50024,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x36,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB0D0_TX,
 		.addr		= 0xA4D80100,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0x73,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB0D0_RX,
 		.addr		= 0xA4D80100,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0x73,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB0D1_TX,
 		.addr		= 0xA4D80120,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0x77,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB0D1_RX,
 		.addr		= 0xA4D80120,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0x77,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB1D0_TX,
 		.addr		= 0xA4D90100,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xab,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB1D0_RX,
 		.addr		= 0xA4D90100,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xab,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB1D1_TX,
 		.addr		= 0xA4D90120,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xaf,
 	}, {
 		.slave_id	= SHDMA_SLAVE_USB1D1_RX,
 		.addr		= 0xA4D90120,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xaf,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_TX,
 		.addr		= 0x04ce0030,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc1,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_RX,
 		.addr		= 0x04ce0030,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc2,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI1_TX,
 		.addr		= 0x04cf0030,
-		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc9,
 	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI1_RX,
 		.addr		= 0x04cf0030,
-		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.chcr		= DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xca,
 	},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
--- linux-libre-3.16-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,28 +123,28 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_SDHI_TX,
 		.addr		= 0x1fe50030,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc5,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SDHI_RX,
 		.addr		= 0x1fe50030,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc6,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
 		.addr		= 0x1fcb0034,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xd3,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
 		.addr		= 0x1fcb0034,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_32BIT),
 		.mid_rid	= 0xd7,
 	},
@@ -154,56 +154,56 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
 		.addr		= 0x1f4b000c,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x21,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
 		.addr		= 0x1f4b0014,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x22,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF3_TX,
 		.addr		= 0x1f4c000c,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x29,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF3_RX,
 		.addr		= 0x1f4c0014,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2a,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF4_TX,
 		.addr		= 0x1f4d000c,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x41,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_SCIF4_RX,
 		.addr		= 0x1f4d0014,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x42,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RSPI_TX,
 		.addr		= 0xfe480004,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc1,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RSPI_RX,
 		.addr		= 0xfe480004,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xc2,
 	},
@@ -213,70 +213,70 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC0_TX,
 		.addr		= 0x1e500012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x21,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC0_RX,
 		.addr		= 0x1e500013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x22,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC1_TX,
 		.addr		= 0x1e510012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x29,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC1_RX,
 		.addr		= 0x1e510013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2a,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC2_TX,
 		.addr		= 0x1e520012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xa1,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC2_RX,
 		.addr		= 0x1e520013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xa2,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC3_TX,
 		.addr		= 0x1e530012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xa9,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC3_RX,
 		.addr		= 0x1e530013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xaf,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC4_TX,
 		.addr		= 0x1e540012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xc5,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC4_RX,
 		.addr		= 0x1e540013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0xc6,
 	},
@@ -286,70 +286,70 @@ static const struct sh_dmae_slave_config
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC5_TX,
 		.addr		= 0x1e550012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x21,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC5_RX,
 		.addr		= 0x1e550013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x22,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC6_TX,
 		.addr		= 0x1e560012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x29,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC6_RX,
 		.addr		= 0x1e560013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x2a,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC7_TX,
 		.addr		= 0x1e570012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x41,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC7_RX,
 		.addr		= 0x1e570013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x42,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC8_TX,
 		.addr		= 0x1e580012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x45,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC8_RX,
 		.addr		= 0x1e580013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x46,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC9_TX,
 		.addr		= 0x1e590012,
-		.chcr		= SM_INC | 0x800 | 0x40000000 |
+		.chcr		= SM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x51,
 	},
 	{
 		.slave_id	= SHDMA_SLAVE_RIIC9_RX,
 		.addr		= 0x1e590013,
-		.chcr		= DM_INC | 0x800 | 0x40000000 |
+		.chcr		= DM_INC | RS_ERS | 0x40000000 |
 				  TS_INDEX2VAL(XMIT_SZ_8BIT),
 		.mid_rid	= 0x52,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/sh/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -344,6 +344,9 @@ void prepare_ftrace_return(unsigned long
 	struct ftrace_graph_ent trace;
 	unsigned long return_hooker = (unsigned long)&return_to_handler;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/perf_event.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/perf_event.c
--- linux-libre-3.16-gnu/arch/sh/kernel/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,14 +129,6 @@ static int __hw_perf_event_init(struct p
 		return -ENODEV;
 
 	/*
-	 * All of the on-chip counters are "limited", in that they have
-	 * no interrupts, and are therefore unable to do sampling without
-	 * further work and timer assistance.
-	 */
-	if (hwc->sample_period)
-		return -EINVAL;
-
-	/*
 	 * See if we need to reserve the counter.
 	 *
 	 * If no events are currently in use, then we have to take a
@@ -392,6 +384,13 @@ int register_sh_pmu(struct sh_pmu *_pmu)
 
 	pr_info("Performance Events: %s support registered\n", _pmu->name);
 
+	/*
+	 * All of the on-chip counters are "limited", in that they have
+	 * no interrupts, and are therefore unable to do sampling without
+	 * further work and timer assistance.
+	 */
+	pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
 	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
 	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/signal_32.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/signal_32.c
--- linux-libre-3.16-gnu/arch/sh/kernel/signal_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/signal_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, uns
 extern void __kernel_sigreturn(void);
 extern void __kernel_rt_sigreturn(void);
 
-static int setup_frame(int sig, struct k_sigaction *ka,
-			sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+		       struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 
-	frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->pr = (unsigned long) ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
 #ifdef CONFIG_VSYSCALL
 	} else if (likely(current->mm->context.vdso)) {
 		regs->pr = VDSO_SYM(&__kernel_sigreturn);
@@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->regs[15] = (unsigned long) frame;
@@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k
 
 	if (current->personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
 
 		err |= __get_user(regs->pc, &funcptr->text);
 		err |= __get_user(regs->regs[12], &funcptr->GOT);
 	} else
-		regs->pc = (unsigned long)ka->sa.sa_handler;
+		regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	set_fs(USER_DS);
 
@@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k
 		 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 
-	frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struc
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -371,8 +367,8 @@ static int setup_rt_frame(int sig, struc
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->pr = (unsigned long) ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
 #ifdef CONFIG_VSYSCALL
 	} else if (likely(current->mm->context.vdso)) {
 		regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
@@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struc
 	}
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up registers for signal handler */
 	regs->regs[15] = (unsigned long) frame;
@@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struc
 
 	if (current->personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
 
 		err |= __get_user(regs->pc, &funcptr->text);
 		err |= __get_user(regs->regs[12], &funcptr->GOT);
 	} else
-		regs->pc = (unsigned long)ka->sa.sa_handler;
+		regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	set_fs(USER_DS);
 
@@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struc
 		 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 static inline void
@@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long sav
  * OK, we're invoking a handler
  */
 static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs *regs, unsigned int save_r0)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, unsigned int save_r0)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(ksig, oldset, regs);
 
-	if (ret)
-		return;
-	signal_delivered(sig, info, ka, regs,
-			test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct
  */
 static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which
@@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_syscall_restart(save_r0, regs, &ka.sa);
+	if (get_signal(&ksig)) {
+		handle_syscall_restart(save_r0, regs, &ksig.ka.sa);
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, regs, save_r0);
+		handle_signal(&ksig, regs, save_r0);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/signal_64.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/signal_64.c
--- linux-libre-3.16-gnu/arch/sh/kernel/signal_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/signal_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,7 @@
 #define DEBUG_SIG 0
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-		struct pt_regs * regs);
+handle_signal(struct ksignal *ksig, struct pt_regs *regs);
 
 static inline void
 handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
@@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *r
  */
 static void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which
@@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, 0);
-	if (signr > 0) {
-		handle_syscall_restart(regs, &ka.sa);
+	if (get_signal(&ksig)) {
+		handle_syscall_restart(regs, &ksig.ka.sa);
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, regs);
+		handle_signal(&ksig, regs);
 		return;
 	}
 
@@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, uns
 void sa_default_restorer(void);		/* See comments below */
 void sa_default_rt_restorer(void);	/* See comments below */
 
-static int setup_frame(int sig, struct k_sigaction *ka,
-		       sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 
-	frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k
 
 	/* Give up earlier as i386, in case */
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	if (_NSIG_WORDS > 1) {
 		err |= __copy_to_user(frame->extramask, &set->sig[1],
@@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k
 
 	/* Give up earlier as i386, in case */
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
 		/*
 		 * On SH5 all edited pointers are subject to NEFF
 		 */
 		DEREF_REG_PR = neff_sign_extend((unsigned long)
-			ka->sa.sa_restorer | 0x1);
+			ksig->ka->sa.sa_restorer | 0x1);
 	} else {
 		/*
 		 * Different approach on SH5.
@@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k
 
 		if (__copy_to_user(frame->retcode,
 			(void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
-			goto give_sigsegv;
+			return -EFAULT;
 
 		/* Cohere the trampoline with the I-cache. */
 		flush_cache_sigtramp(DEREF_REG_PR-1);
@@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k
 	regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
 	regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
 
-	regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
+	regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
 
 	set_fs(USER_DS);
 
@@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k
 		 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *kig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 
-	frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 	signal = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struc
 
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Give up earlier as i386, in case */
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struc
 
 	/* Give up earlier as i386, in case */
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->sa.sa_flags & SA_RESTORER) {
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
 		/*
 		 * On SH5 all edited pointers are subject to NEFF
 		 */
 		DEREF_REG_PR = neff_sign_extend((unsigned long)
-			ka->sa.sa_restorer | 0x1);
+			ksig->ka.sa.sa_restorer | 0x1);
 	} else {
 		/*
 		 * Different approach on SH5.
@@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struc
 
 		if (__copy_to_user(frame->retcode,
 			(void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
-			goto give_sigsegv;
+			return -EFAULT;
 
 		/* Cohere the trampoline with the I-cache. */
 		flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
@@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struc
 	regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
 	regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
 	regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
-	regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
+	regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
 
 	set_fs(USER_DS);
 
@@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struc
 		 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */
 static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-		struct pt_regs * regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 
 	/* Set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
-
-	if (ret)
-		return;
+		ret = setup_frame(ksig, oldset, regs);
 
-	signal_delivered(sig, info, ka, regs,
-			test_thread_flag(TIF_SINGLESTEP));
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/time.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/time.c
--- linux-libre-3.16-gnu/arch/sh/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,10 +80,8 @@ static int __init rtc_generic_init(void)
 		return -ENODEV;
 
 	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 module_init(rtc_generic_init);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/kernel/vsyscall/vsyscall.c linux-libre-3.17-rc7-gnu/arch/sh/kernel/vsyscall/vsyscall.c
--- linux-libre-3.16-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,18 +92,3 @@ const char *arch_vma_name(struct vm_area
 
 	return NULL;
 }
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long address)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long address)
-{
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/lib/mcount.S linux-libre-3.17-rc7-gnu/arch/sh/lib/mcount.S
--- linux-libre-3.16-gnu/arch/sh/lib/mcount.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/lib/mcount.S	2014-09-28 17:29:07.000000000 -0400
@@ -92,13 +92,6 @@ mcount:
 	rts
 	 nop
 #else
-#ifndef CONFIG_DYNAMIC_FTRACE
-	mov.l	.Lfunction_trace_stop, r0
-	mov.l	@r0, r0
-	tst	r0, r0
-	bf	ftrace_stub
-#endif
-
 	MCOUNT_ENTER()
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -174,11 +167,6 @@ ftrace_graph_call:
 
 	.globl ftrace_caller
 ftrace_caller:
-	mov.l	.Lfunction_trace_stop, r0
-	mov.l	@r0, r0
-	tst	r0, r0
-	bf	ftrace_stub
-
 	MCOUNT_ENTER()
 
 	.globl ftrace_call
@@ -196,8 +184,6 @@ ftrace_call:
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 	.align 2
-.Lfunction_trace_stop:
-	.long	function_trace_stop
 
 /*
  * NOTE: From here on the locations of the .Lftrace_stub label and
@@ -217,12 +203,7 @@ ftrace_stub:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	.globl	ftrace_graph_caller
 ftrace_graph_caller:
-	mov.l	2f, r0
-	mov.l	@r0, r0
-	tst	r0, r0
-	bt	1f
-
-	mov.l	3f, r1
+	mov.l	2f, r1
 	jmp	@r1
 	 nop
 1:
@@ -242,8 +223,7 @@ ftrace_graph_caller:
 	MCOUNT_LEAVE()
 
 	.align 2
-2:	.long	function_trace_stop
-3:	.long	skip_trace
+2:	.long	skip_trace
 .Lprepare_ftrace_return:
 	.long	prepare_ftrace_return
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/mm/asids-debugfs.c linux-libre-3.17-rc7-gnu/arch/sh/mm/asids-debugfs.c
--- linux-libre-3.16-gnu/arch/sh/mm/asids-debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/mm/asids-debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,10 +67,8 @@ static int __init asids_debugfs_init(voi
 					   NULL, &asids_debugfs_fops);
 	if (!asids_dentry)
 		return -ENOMEM;
-	if (IS_ERR(asids_dentry))
-		return PTR_ERR(asids_dentry);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(asids_dentry);
 }
 module_init(asids_debugfs_init);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/mm/cache.c linux-libre-3.17-rc7-gnu/arch/sh/mm/cache.c
--- linux-libre-3.16-gnu/arch/sh/mm/cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/mm/cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -229,6 +229,7 @@ void flush_icache_range(unsigned long st
 
 	cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/mm/gup.c linux-libre-3.17-rc7-gnu/arch/sh/mm/gup.c
--- linux-libre-3.16-gnu/arch/sh/mm/gup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/mm/gup.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,6 +105,8 @@ static noinline int gup_pte_range(pmd_t
 		VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 		page = pte_page(pte);
 		get_page(page);
+		__flush_anon_page(page, addr);
+		flush_dcache_page(page);
 		pages[*nr] = page;
 		(*nr)++;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sh/mm/init.c linux-libre-3.17-rc7-gnu/arch/sh/mm/init.c
--- linux-libre-3.16-gnu/arch/sh/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sh/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -495,8 +495,9 @@ int arch_add_memory(int nid, u64 start,
 	pgdat = NODE_DATA(nid);
 
 	/* We only have ZONE_NORMAL, so this is easy.. */
-	ret = __add_pages(nid, pgdat->node_zones + ZONE_NORMAL,
-				start_pfn, nr_pages);
+	ret = __add_pages(nid, pgdat->node_zones +
+			zone_for_memory(nid, start, size, ZONE_NORMAL),
+			start_pfn, nr_pages);
 	if (unlikely(ret))
 		printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/boot/install.sh linux-libre-3.17-rc7-gnu/arch/sparc/boot/install.sh
--- linux-libre-3.16-gnu/arch/sparc/boot/install.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/sparc/boot/install.sh	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# 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) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for SPARC architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+verify () {
+	if [ ! -f "$1" ]; then
+		echo ""                                                   1>&2
+		echo " *** Missing file: $1"                              1>&2
+		echo ' *** You need to run "make" before "make install".' 1>&2
+		echo ""                                                   1>&2
+		exit 1
+	fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+# Default install - same as make zlilo
+
+if [ -f $4/vmlinuz ]; then
+	mv $4/vmlinuz $4/vmlinuz.old
+fi
+
+if [ -f $4/System.map ]; then
+	mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinuz
+cp $3 $4/System.map
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/boot/Makefile linux-libre-3.17-rc7-gnu/arch/sparc/boot/Makefile
--- linux-libre-3.16-gnu/arch/sparc/boot/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/boot/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -69,3 +69,7 @@ $(obj)/image: vmlinux FORCE
 $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
 	$(call if_changed,elftoaout)
 	$(call if_changed,piggy)
+
+install:
+	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/zImage \
+		System.map "$(INSTALL_PATH)"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/configs/sparc64_defconfig linux-libre-3.17-rc7-gnu/arch/sparc/configs/sparc64_defconfig
--- linux-libre-3.16-gnu/arch/sparc/configs/sparc64_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/configs/sparc64_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@ CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=m
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/asm/io_64.h linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/io_64.h
--- linux-libre-3.16-gnu/arch/sparc/include/asm/io_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/io_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,125 +9,99 @@
 #include <asm/asi.h>
 #include <asm-generic/pci_iomap.h>
 
-/* PC crapola... */
-#define __SLOW_DOWN_IO	do { } while (0)
-#define SLOW_DOWN_IO	do { } while (0)
-
 /* BIO layer definitions. */
 extern unsigned long kern_base, kern_size;
 
-static inline u8 _inb(unsigned long addr)
+/* __raw_{read,write}{b,w,l,q} uses direct access.
+ * Access the memory as big endian bypassing the cache
+ * by using ASI_PHYS_BYPASS_EC_E
+ */
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
 	u8 ret;
 
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 
 	return ret;
 }
 
-static inline u16 _inw(unsigned long addr)
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
 	u16 ret;
 
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 
 	return ret;
 }
 
-static inline u32 _inl(unsigned long addr)
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
 	u32 ret;
 
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 
 	return ret;
 }
 
-static inline void _outb(u8 b, unsigned long addr)
-{
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _outw(u16 w, unsigned long addr)
-{
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _outl(u32 l, unsigned long addr)
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-#define inb(__addr)		(_inb((unsigned long)(__addr)))
-#define inw(__addr)		(_inw((unsigned long)(__addr)))
-#define inl(__addr)		(_inl((unsigned long)(__addr)))
-#define outb(__b, __addr)	(_outb((u8)(__b), (unsigned long)(__addr)))
-#define outw(__w, __addr)	(_outw((u16)(__w), (unsigned long)(__addr)))
-#define outl(__l, __addr)	(_outl((u32)(__l), (unsigned long)(__addr)))
-
-#define inb_p(__addr) 		inb(__addr)
-#define outb_p(__b, __addr)	outb(__b, __addr)
-#define inw_p(__addr)		inw(__addr)
-#define outw_p(__w, __addr)	outw(__w, __addr)
-#define inl_p(__addr)		inl(__addr)
-#define outl_p(__l, __addr)	outl(__l, __addr)
+	u64 ret;
 
-void outsb(unsigned long, const void *, unsigned long);
-void outsw(unsigned long, const void *, unsigned long);
-void outsl(unsigned long, const void *, unsigned long);
-void insb(unsigned long, void *, unsigned long);
-void insw(unsigned long, void *, unsigned long);
-void insl(unsigned long, void *, unsigned long);
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 
-static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insb((unsigned long __force)port, buf, count);
-}
-static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insw((unsigned long __force)port, buf, count);
+	return ret;
 }
 
-static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 b, const volatile void __iomem *addr)
 {
-	insl((unsigned long __force)port, buf, count);
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 w, const volatile void __iomem *addr)
 {
-	outsb((unsigned long __force)port, buf, count);
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 l, const volatile void __iomem *addr)
 {
-	outsw((unsigned long __force)port, buf, count);
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 q, const volatile void __iomem *addr)
 {
-	outsl((unsigned long __force)port, buf, count);
+	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
+			     : /* no outputs */
+			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-/* Memory functions, same as I/O accesses on Ultra. */
-static inline u8 _readb(const volatile void __iomem *addr)
+/* Memory functions, same as I/O accesses on Ultra.
+ * Access memory as little endian bypassing
+ * the cache by using ASI_PHYS_BYPASS_EC_E_L
+ */
+#define readb readb
+static inline u8 readb(const volatile void __iomem *addr)
 {	u8 ret;
 
 	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
@@ -137,7 +111,8 @@ static inline u8 _readb(const volatile v
 	return ret;
 }
 
-static inline u16 _readw(const volatile void __iomem *addr)
+#define readw readw
+static inline u16 readw(const volatile void __iomem *addr)
 {	u16 ret;
 
 	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
@@ -148,7 +123,8 @@ static inline u16 _readw(const volatile
 	return ret;
 }
 
-static inline u32 _readl(const volatile void __iomem *addr)
+#define readl readl
+static inline u32 readl(const volatile void __iomem *addr)
 {	u32 ret;
 
 	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
@@ -159,7 +135,8 @@ static inline u32 _readl(const volatile
 	return ret;
 }
 
-static inline u64 _readq(const volatile void __iomem *addr)
+#define readq readq
+static inline u64 readq(const volatile void __iomem *addr)
 {	u64 ret;
 
 	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
@@ -170,7 +147,8 @@ static inline u64 _readq(const volatile
 	return ret;
 }
 
-static inline void _writeb(u8 b, volatile void __iomem *addr)
+#define writeb writeb
+static inline void writeb(u8 b, volatile void __iomem *addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
 			     : /* no outputs */
@@ -178,7 +156,8 @@ static inline void _writeb(u8 b, volatil
 			     : "memory");
 }
 
-static inline void _writew(u16 w, volatile void __iomem *addr)
+#define writew writew
+static inline void writew(u16 w, volatile void __iomem *addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
 			     : /* no outputs */
@@ -186,7 +165,8 @@ static inline void _writew(u16 w, volati
 			     : "memory");
 }
 
-static inline void _writel(u32 l, volatile void __iomem *addr)
+#define writel writel
+static inline void writel(u32 l, volatile void __iomem *addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
 			     : /* no outputs */
@@ -194,7 +174,8 @@ static inline void _writel(u32 l, volati
 			     : "memory");
 }
 
-static inline void _writeq(u64 q, volatile void __iomem *addr)
+#define writeq writeq
+static inline void writeq(u64 q, volatile void __iomem *addr)
 {
 	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
 			     : /* no outputs */
@@ -202,100 +183,91 @@ static inline void _writeq(u64 q, volati
 			     : "memory");
 }
 
-#define readb(__addr)		_readb(__addr)
-#define readw(__addr)		_readw(__addr)
-#define readl(__addr)		_readl(__addr)
-#define readq(__addr)		_readq(__addr)
-#define readb_relaxed(__addr)	_readb(__addr)
-#define readw_relaxed(__addr)	_readw(__addr)
-#define readl_relaxed(__addr)	_readl(__addr)
-#define readq_relaxed(__addr)	_readq(__addr)
-#define writeb(__b, __addr)	_writeb(__b, __addr)
-#define writew(__w, __addr)	_writew(__w, __addr)
-#define writel(__l, __addr)	_writel(__l, __addr)
-#define writeq(__q, __addr)	_writeq(__q, __addr)
 
-/* Now versions without byte-swapping. */
-static inline u8 _raw_readb(unsigned long addr)
+#define inb inb
+static inline u8 inb(unsigned long addr)
 {
-	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
+	return readb((volatile void __iomem *)addr);
 }
 
-static inline u16 _raw_readw(unsigned long addr)
+#define inw inw
+static inline u16 inw(unsigned long addr)
 {
-	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
+	return readw((volatile void __iomem *)addr);
 }
 
-static inline u32 _raw_readl(unsigned long addr)
+#define inl inl
+static inline u32 inl(unsigned long addr)
 {
-	u32 ret;
+	return readl((volatile void __iomem *)addr);
+}
 
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+#define outb outb
+static inline void outb(u8 b, unsigned long addr)
+{
+	writeb(b, (volatile void __iomem *)addr);
+}
 
-	return ret;
+#define outw outw
+static inline void outw(u16 w, unsigned long addr)
+{
+	writew(w, (volatile void __iomem *)addr);
 }
 
-static inline u64 _raw_readq(unsigned long addr)
+#define outl outl
+static inline void outl(u32 l, unsigned long addr)
 {
-	u64 ret;
+	writel(l, (volatile void __iomem *)addr);
+}
 
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 
-	return ret;
+#define inb_p(__addr) 		inb(__addr)
+#define outb_p(__b, __addr)	outb(__b, __addr)
+#define inw_p(__addr)		inw(__addr)
+#define outw_p(__w, __addr)	outw(__w, __addr)
+#define inl_p(__addr)		inl(__addr)
+#define outl_p(__l, __addr)	outl(__l, __addr)
+
+void outsb(unsigned long, const void *, unsigned long);
+void outsw(unsigned long, const void *, unsigned long);
+void outsl(unsigned long, const void *, unsigned long);
+void insb(unsigned long, void *, unsigned long);
+void insw(unsigned long, void *, unsigned long);
+void insl(unsigned long, void *, unsigned long);
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insw((unsigned long __force)port, buf, count);
 }
 
-static inline void _raw_writeb(u8 b, unsigned long addr)
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
 {
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	insl((unsigned long __force)port, buf, count);
 }
 
-static inline void _raw_writew(u16 w, unsigned long addr)
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
 {
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	outsb((unsigned long __force)port, buf, count);
 }
 
-static inline void _raw_writel(u32 l, unsigned long addr)
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
 {
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	outsw((unsigned long __force)port, buf, count);
 }
 
-static inline void _raw_writeq(u64 q, unsigned long addr)
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
 {
-	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
-			     : /* no outputs */
-			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	outsl((unsigned long __force)port, buf, count);
 }
 
-#define __raw_readb(__addr)		(_raw_readb((unsigned long)(__addr)))
-#define __raw_readw(__addr)		(_raw_readw((unsigned long)(__addr)))
-#define __raw_readl(__addr)		(_raw_readl((unsigned long)(__addr)))
-#define __raw_readq(__addr)		(_raw_readq((unsigned long)(__addr)))
-#define __raw_writeb(__b, __addr)	(_raw_writeb((u8)(__b), (unsigned long)(__addr)))
-#define __raw_writew(__w, __addr)	(_raw_writew((u16)(__w), (unsigned long)(__addr)))
-#define __raw_writel(__l, __addr)	(_raw_writel((u32)(__l), (unsigned long)(__addr)))
-#define __raw_writeq(__q, __addr)	(_raw_writeq((u64)(__q), (unsigned long)(__addr)))
+#define readb_relaxed(__addr)	readb(__addr)
+#define readw_relaxed(__addr)	readw(__addr)
+#define readl_relaxed(__addr)	readl(__addr)
+#define readq_relaxed(__addr)	readq(__addr)
 
 /* Valid I/O Space regions are anywhere, because each PCI bus supported
  * can live in an arbitrary area of the physical address range.
@@ -305,96 +277,47 @@ static inline void _raw_writeq(u64 q, un
 /* Now, SBUS variants, only difference from PCI is that we do
  * not use little-endian ASIs.
  */
-static inline u8 _sbus_readb(const volatile void __iomem *addr)
+static inline u8 sbus_readb(const volatile void __iomem *addr)
 {
-	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
+	return __raw_readb(addr);
 }
 
-static inline u16 _sbus_readw(const volatile void __iomem *addr)
+static inline u16 sbus_readw(const volatile void __iomem *addr)
 {
-	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
+	return __raw_readw(addr);
 }
 
-static inline u32 _sbus_readl(const volatile void __iomem *addr)
+static inline u32 sbus_readl(const volatile void __iomem *addr)
 {
-	u32 ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
+	return __raw_readl(addr);
 }
 
-static inline u64 _sbus_readq(const volatile void __iomem *addr)
+static inline u64 sbus_readq(const volatile void __iomem *addr)
 {
-	u64 ret;
-
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* sbus_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
+	return __raw_readq(addr);
 }
 
-static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
+static inline void sbus_writeb(u8 b, volatile void __iomem *addr)
 {
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
+	__raw_writeb(b, addr);
 }
 
-static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
+static inline void sbus_writew(u16 w, volatile void __iomem *addr)
 {
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
+	__raw_writew(w, addr);
 }
 
-static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
+static inline void sbus_writel(u32 l, volatile void __iomem *addr)
 {
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
+	__raw_writel(l, addr);
 }
 
-static inline void _sbus_writeq(u64 l, volatile void __iomem *addr)
+static inline void sbus_writeq(u64 q, volatile void __iomem *addr)
 {
-	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
+	__raw_writeq(q, addr);
 }
 
-#define sbus_readb(__addr)		_sbus_readb(__addr)
-#define sbus_readw(__addr)		_sbus_readw(__addr)
-#define sbus_readl(__addr)		_sbus_readl(__addr)
-#define sbus_readq(__addr)		_sbus_readq(__addr)
-#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
-#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
-#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
-#define sbus_writeq(__l, __addr)	_sbus_writeq(__l, __addr)
-
-static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+static inline void sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
 {
 	while(n--) {
 		sbus_writeb(c, dst);
@@ -402,10 +325,7 @@ static inline void _sbus_memset_io(volat
 	}
 }
 
-#define sbus_memset_io(d,c,sz)	_sbus_memset_io(d,c,sz)
-
-static inline void
-_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+static inline void memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
 {
 	volatile void __iomem *d = dst;
 
@@ -415,11 +335,8 @@ _memset_io(volatile void __iomem *dst, i
 	}
 }
 
-#define memset_io(d,c,sz)	_memset_io(d,c,sz)
-
-static inline void
-_sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
-		    __kernel_size_t n)
+static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
+				      __kernel_size_t n)
 {
 	char *d = dst;
 
@@ -430,10 +347,9 @@ _sbus_memcpy_fromio(void *dst, const vol
 	}
 }
 
-#define sbus_memcpy_fromio(d, s, sz)	_sbus_memcpy_fromio(d, s, sz)
 
-static inline void
-_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+				 __kernel_size_t n)
 {
 	char *d = dst;
 
@@ -444,11 +360,8 @@ _memcpy_fromio(void *dst, const volatile
 	}
 }
 
-#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
-
-static inline void
-_sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
-		  __kernel_size_t n)
+static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
+				    __kernel_size_t n)
 {
 	const char *s = src;
 	volatile void __iomem *d = dst;
@@ -460,10 +373,8 @@ _sbus_memcpy_toio(volatile void __iomem
 	}
 }
 
-#define sbus_memcpy_toio(d, s, sz)	_sbus_memcpy_toio(d, s, sz)
-
-static inline void
-_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+			       __kernel_size_t n)
 {
 	const char *s = src;
 	volatile void __iomem *d = dst;
@@ -475,8 +386,6 @@ _memcpy_toio(volatile void __iomem *dst,
 	}
 }
 
-#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
-
 #define mmiowb()
 
 #ifdef __KERNEL__
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/sparc/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@ generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += mutex.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/asm/processor_32.h linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/processor_32.h
--- linux-libre-3.16-gnu/arch/sparc/include/asm/processor_32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/processor_32.h	2014-09-28 17:29:07.000000000 -0400
@@ -119,6 +119,8 @@ 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);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/asm/processor_64.h linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/processor_64.h
--- linux-libre-3.16-gnu/arch/sparc/include/asm/processor_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/processor_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -216,6 +216,7 @@ 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-3.16-gnu/arch/sparc/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/sparc/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#ifndef _SPARC_SCATTERLIST_H
-#define _SPARC_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* !(_SPARC_SCATTERLIST_H) */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/asm/tlbflush_64.h linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/tlbflush_64.h
--- linux-libre-3.16-gnu/arch/sparc/include/asm/tlbflush_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/asm/tlbflush_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,8 @@ static inline void flush_tlb_range(struc
 {
 }
 
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
 #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 
 void flush_tlb_pending(void);
@@ -48,11 +50,6 @@ void __flush_tlb_kernel_range(unsigned l
 
 #ifndef CONFIG_SMP
 
-#define flush_tlb_kernel_range(start,end) \
-do {	flush_tsb_kernel_range(start,end); \
-	__flush_tlb_kernel_range(start,end); \
-} while (0)
-
 static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
 {
 	__flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
@@ -63,11 +60,6 @@ static inline void global_flush_tlb_page
 void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
 void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
 
-#define flush_tlb_kernel_range(start, end) \
-do {	flush_tsb_kernel_range(start,end); \
-	smp_flush_tlb_kernel_range(start, end); \
-} while (0)
-
 #define global_flush_tlb_page(mm, vaddr) \
 	smp_flush_tlb_page(mm, vaddr)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/sparc/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/sparc/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -411,8 +411,11 @@
 #define __NR_sched_setattr	343
 #define __NR_sched_getattr	344
 #define __NR_renameat2		345
+#define __NR_seccomp		346
+#define __NR_getrandom		347
+#define __NR_memfd_create	348
 
-#define NR_syscalls		346
+#define NR_syscalls		349
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK	0x00000001
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/Kconfig linux-libre-3.17-rc7-gnu/arch/sparc/Kconfig
--- linux-libre-3.16-gnu/arch/sparc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,7 @@ config SPARC
 	select MODULES_USE_ELF_RELA
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
+	select ARCH_HAS_SG_CHAIN
 
 config SPARC32
 	def_bool !64BIT
@@ -55,7 +56,6 @@ config SPARC64
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_GRAPH_FP_TEST
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_KRETPROBES
 	select HAVE_KPROBES
 	select HAVE_RCU_TABLE_FREE if SMP
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/ldc.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/ldc.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/ldc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/ldc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1336,7 +1336,7 @@ int ldc_connect(struct ldc_channel *lp)
 	if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
 	    !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
 	    lp->hs_state != LDC_HS_OPEN)
-		err = -EINVAL;
+		err = ((lp->hs_state > LDC_HS_OPEN) ? 0 : -EINVAL);
 	else
 		err = start_handshake(lp);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/mdesc.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/mdesc.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/mdesc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/mdesc.c	2014-09-28 17:29:07.000000000 -0400
@@ -906,29 +906,85 @@ void mdesc_fill_in_cpu_data(cpumask_t *m
 	smp_fill_in_sib_core_maps();
 }
 
-static ssize_t mdesc_read(struct file *file, char __user *buf,
-			  size_t len, loff_t *offp)
+/* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
+ * opened. Hold this reference until /dev/mdesc is closed to ensure
+ * mdesc data structure is not released underneath us. Store the
+ * pointer to mdesc structure in private_data for read and seek to use
+ */
+static int mdesc_open(struct inode *inode, struct file *file)
 {
 	struct mdesc_handle *hp = mdesc_grab();
-	int err;
 
 	if (!hp)
 		return -ENODEV;
 
-	err = hp->handle_size;
-	if (len < hp->handle_size)
-		err = -EMSGSIZE;
-	else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
-		err = -EFAULT;
-	mdesc_release(hp);
+	file->private_data = hp;
 
-	return err;
+	return 0;
+}
+
+static ssize_t mdesc_read(struct file *file, char __user *buf,
+			  size_t len, loff_t *offp)
+{
+	struct mdesc_handle *hp = file->private_data;
+	unsigned char *mdesc;
+	int bytes_left, count = len;
+
+	if (*offp >= hp->handle_size)
+		return 0;
+
+	bytes_left = hp->handle_size - *offp;
+	if (count > bytes_left)
+		count = bytes_left;
+
+	mdesc = (unsigned char *)&hp->mdesc;
+	mdesc += *offp;
+	if (!copy_to_user(buf, mdesc, count)) {
+		*offp += count;
+		return count;
+	} else {
+		return -EFAULT;
+	}
+}
+
+static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
+{
+	struct mdesc_handle *hp;
+
+	switch (whence) {
+	case SEEK_CUR:
+		offset += file->f_pos;
+		break;
+	case SEEK_SET:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	hp = file->private_data;
+	if (offset > hp->handle_size)
+		return -EINVAL;
+	else
+		file->f_pos = offset;
+
+	return offset;
+}
+
+/* mdesc_close() - /dev/mdesc is being closed, release the reference to
+ * mdesc structure.
+ */
+static int mdesc_close(struct inode *inode, struct file *file)
+{
+	mdesc_release(file->private_data);
+	return 0;
 }
 
 static const struct file_operations mdesc_fops = {
-	.read	= mdesc_read,
-	.owner	= THIS_MODULE,
-	.llseek = noop_llseek,
+	.open    = mdesc_open,
+	.read	 = mdesc_read,
+	.llseek  = mdesc_llseek,
+	.release = mdesc_close,
+	.owner	 = THIS_MODULE,
 };
 
 static struct miscdevice mdesc_misc = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/nmi.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/nmi.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/nmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/nmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,7 +130,6 @@ static inline unsigned int get_nmi_count
 
 static __init void nmi_cpu_busy(void *data)
 {
-	local_irq_enable_in_hardirq();
 	while (endflag == 0)
 		mb();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/pci.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/pci.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -432,6 +432,11 @@ static void of_scan_pci_bridge(struct pc
 		       node->full_name);
 		return;
 	}
+
+	if (ofpci_verbose)
+		printk("    Bridge bus range [%u --> %u]\n",
+		       busrange[0], busrange[1]);
+
 	ranges = of_get_property(node, "ranges", &len);
 	simba = 0;
 	if (ranges == NULL) {
@@ -451,6 +456,10 @@ static void of_scan_pci_bridge(struct pc
 	pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
 	bus->bridge_ctl = 0;
 
+	if (ofpci_verbose)
+		printk("    Bridge ranges[%p] simba[%d]\n",
+		       ranges, simba);
+
 	/* parse ranges property, or cook one up by hand for Simba */
 	/* PCI #address-cells == 3 and #size-cells == 2 always */
 	res = &dev->resource[PCI_BRIDGE_RESOURCES];
@@ -468,10 +477,29 @@ static void of_scan_pci_bridge(struct pc
 	}
 	i = 1;
 	for (; len >= 32; len -= 32, ranges += 8) {
+		u64 start;
+
+		if (ofpci_verbose)
+			printk("    RAW Range[%08x:%08x:%08x:%08x:%08x:%08x:"
+			       "%08x:%08x]\n",
+			       ranges[0], ranges[1], ranges[2], ranges[3],
+			       ranges[4], ranges[5], ranges[6], ranges[7]);
+
 		flags = pci_parse_of_flags(ranges[0]);
 		size = GET_64BIT(ranges, 6);
 		if (flags == 0 || size == 0)
 			continue;
+
+		/* On PCI-Express systems, PCI bridges that have no devices downstream
+		 * have a bogus size value where the first 32-bit cell is 0xffffffff.
+		 * This results in a bogus range where start + size overflows.
+		 *
+		 * Just skip these otherwise the kernel will complain when the resource
+		 * tries to be claimed.
+		 */
+		if (size >> 32 == 0xffffffff)
+			continue;
+
 		if (flags & IORESOURCE_IO) {
 			res = bus->resource[0];
 			if (res->flags) {
@@ -490,8 +518,13 @@ static void of_scan_pci_bridge(struct pc
 		}
 
 		res->flags = flags;
-		region.start = GET_64BIT(ranges, 1);
+		region.start = start = GET_64BIT(ranges, 1);
 		region.end = region.start + size - 1;
+
+		if (ofpci_verbose)
+			printk("      Using flags[%08x] start[%016llx] size[%016llx]\n",
+			       flags, start, size);
+
 		pcibios_bus_to_resource(dev->bus, res, &region);
 	}
 after_ranges:
@@ -584,6 +617,36 @@ static void pci_bus_register_of_sysfs(st
 		pci_bus_register_of_sysfs(child_bus);
 }
 
+static void pci_claim_bus_resources(struct pci_bus *bus)
+{
+	struct pci_bus *child_bus;
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+
+			if (ofpci_verbose)
+				printk("PCI: Claiming %s: "
+				       "Resource %d: %016llx..%016llx [%x]\n",
+				       pci_name(dev), i,
+				       (unsigned long long)r->start,
+				       (unsigned long long)r->end,
+				       (unsigned int)r->flags);
+
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &bus->children, node)
+		pci_claim_bus_resources(child_bus);
+}
+
 struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
 				 struct device *parent)
 {
@@ -614,6 +677,8 @@ struct pci_bus *pci_scan_one_pbm(struct
 	pci_bus_add_devices(bus);
 	pci_bus_register_of_sysfs(bus);
 
+	pci_claim_bus_resources(bus);
+
 	return bus;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/perf_event.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/perf_event.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/perf_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/perf_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -1671,9 +1671,12 @@ static bool __init supported_pmu(void)
 
 static int __init init_hw_perf_events(void)
 {
+	int err;
+
 	pr_info("Performance events: ");
 
-	if (!supported_pmu()) {
+	err = pcr_arch_init();
+	if (err || !supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
 		return 0;
 	}
@@ -1685,7 +1688,7 @@ static int __init init_hw_perf_events(vo
 
 	return 0;
 }
-early_initcall(init_hw_perf_events);
+pure_initcall(init_hw_perf_events);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/process_64.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/process_64.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/process_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/process_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -312,6 +312,9 @@ static void __global_pmu_self(int this_c
 	struct global_pmu_snapshot *pp;
 	int i, num;
 
+	if (!pcr_ops)
+		return;
+
 	pp = &global_cpu_snapshot[this_cpu].pmu;
 
 	num = 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/smp_32.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/smp_32.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/smp_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/smp_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ void smp_store_cpu_info(int id)
 	mid = cpu_get_hwmid(cpu_node);
 
 	if (mid < 0) {
-		printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node);
+		printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08x", id, cpu_node);
 		mid = 0;
 	}
 	cpu_data(id).mid = mid;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/smp_64.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/smp_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/smp_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -1383,7 +1383,6 @@ void __cpu_die(unsigned int cpu)
 
 void __init smp_cpus_done(unsigned int max_cpus)
 {
-	pcr_arch_init();
 }
 
 void smp_send_reschedule(int cpu)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/systbls_32.S linux-libre-3.17-rc7-gnu/arch/sparc/kernel/systbls_32.S
--- linux-libre-3.16-gnu/arch/sparc/kernel/systbls_32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/systbls_32.S	2014-09-28 17:29:07.000000000 -0400
@@ -86,4 +86,4 @@ sys_call_table:
 /*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/	.long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-/*345*/	.long sys_renameat2
+/*345*/	.long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/systbls_64.S linux-libre-3.17-rc7-gnu/arch/sparc/kernel/systbls_64.S
--- linux-libre-3.16-gnu/arch/sparc/kernel/systbls_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/systbls_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -87,7 +87,7 @@ sys_call_table32:
 /*330*/	.word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
 	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 /*340*/	.word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-	.word sys32_renameat2
+	.word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
 
 #endif /* CONFIG_COMPAT */
 
@@ -166,4 +166,4 @@ sys_call_table:
 /*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/	.word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-	.word sys_renameat2
+	.word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/kernel/unaligned_32.c linux-libre-3.17-rc7-gnu/arch/sparc/kernel/unaligned_32.c
--- linux-libre-3.16-gnu/arch/sparc/kernel/unaligned_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/kernel/unaligned_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,7 +166,7 @@ unsigned long safe_compute_effective_add
 /* This is just to make gcc think panic does return... */
 static void unaligned_panic(char *str)
 {
-	panic(str);
+	panic("%s", str);
 }
 
 /* una_asm.S */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/lib/mcount.S linux-libre-3.17-rc7-gnu/arch/sparc/lib/mcount.S
--- linux-libre-3.16-gnu/arch/sparc/lib/mcount.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/lib/mcount.S	2014-09-28 17:29:07.000000000 -0400
@@ -24,10 +24,7 @@ mcount:
 #ifdef CONFIG_DYNAMIC_FTRACE
 	/* Do nothing, the retl/nop below is all we need.  */
 #else
-	sethi		%hi(function_trace_stop), %g1
-	lduw		[%g1 + %lo(function_trace_stop)], %g2
-	brnz,pn		%g2, 2f
-	 sethi		%hi(ftrace_trace_function), %g1
+	sethi		%hi(ftrace_trace_function), %g1
 	sethi		%hi(ftrace_stub), %g2
 	ldx		[%g1 + %lo(ftrace_trace_function)], %g1
 	or		%g2, %lo(ftrace_stub), %g2
@@ -80,11 +77,8 @@ ftrace_stub:
 	.globl		ftrace_caller
 	.type		ftrace_caller,#function
 ftrace_caller:
-	sethi		%hi(function_trace_stop), %g1
 	mov		%i7, %g2
-	lduw		[%g1 + %lo(function_trace_stop)], %g1
-	brnz,pn		%g1, ftrace_stub
-	 mov		%fp, %g3
+	mov		%fp, %g3
 	save		%sp, -176, %sp
 	mov		%g2, %o1
 	mov		%g2, %l0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/lib/PeeCeeI.c linux-libre-3.17-rc7-gnu/arch/sparc/lib/PeeCeeI.c
--- linux-libre-3.16-gnu/arch/sparc/lib/PeeCeeI.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/lib/PeeCeeI.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,7 @@ void outsb(unsigned long __addr, const v
 	const u8 *p = src;
 
 	while (count--)
-		outb(*p++, addr);
+		__raw_writeb(*p++, addr);
 }
 EXPORT_SYMBOL(outsb);
 
@@ -93,21 +93,21 @@ void insb(unsigned long __addr, void *ds
 		u8 *pb = dst;
 
 		while ((((unsigned long)pb) & 0x3) && count--)
-			*pb++ = inb(addr);
+			*pb++ = __raw_readb(addr);
 		pi = (u32 *)pb;
 		while (count >= 4) {
 			u32 w;
 
-			w  = (inb(addr) << 24);
-			w |= (inb(addr) << 16);
-			w |= (inb(addr) << 8);
-			w |= (inb(addr) << 0);
+			w  = (__raw_readb(addr) << 24);
+			w |= (__raw_readb(addr) << 16);
+			w |= (__raw_readb(addr) << 8);
+			w |= (__raw_readb(addr) << 0);
 			*pi++ = w;
 			count -= 4;
 		}
 		pb = (u8 *)pi;
 		while (count--)
-			*pb++ = inb(addr);
+			*pb++ = __raw_readb(addr);
 	}
 }
 EXPORT_SYMBOL(insb);
@@ -121,21 +121,21 @@ void insw(unsigned long __addr, void *ds
 		u32 *pi;
 
 		if (((unsigned long)ps) & 0x2) {
-			*ps++ = le16_to_cpu(inw(addr));
+			*ps++ = __raw_readw(addr);
 			count--;
 		}
 		pi = (u32 *)ps;
 		while (count >= 2) {
 			u32 w;
 
-			w  = (le16_to_cpu(inw(addr)) << 16);
-			w |= (le16_to_cpu(inw(addr)) << 0);
+			w  = __raw_readw(addr) << 16;
+			w |= __raw_readw(addr) << 0;
 			*pi++ = w;
 			count -= 2;
 		}
 		ps = (u16 *)pi;
 		if (count)
-			*ps = le16_to_cpu(inw(addr));
+			*ps = __raw_readw(addr);
 	}
 }
 EXPORT_SYMBOL(insw);
@@ -148,7 +148,7 @@ void insl(unsigned long __addr, void *ds
 		if ((((unsigned long)dst) & 0x3) == 0) {
 			u32 *pi = dst;
 			while (count--)
-				*pi++ = le32_to_cpu(inl(addr));
+				*pi++ = __raw_readl(addr);
 		} else {
 			u32 l = 0, l2, *pi;
 			u16 *ps;
@@ -158,11 +158,11 @@ void insl(unsigned long __addr, void *ds
 			case 0x2:
 				ps = dst;
 				count -= 1;
-				l = le32_to_cpu(inl(addr));
+				l = __raw_readl(addr);
 				*ps++ = l;
 				pi = (u32 *)ps;
 				while (count--) {
-					l2 = le32_to_cpu(inl(addr));
+					l2 = __raw_readl(addr);
 					*pi++ = (l << 16) | (l2 >> 16);
 					l = l2;
 				}
@@ -173,13 +173,13 @@ void insl(unsigned long __addr, void *ds
 			case 0x1:
 				pb = dst;
 				count -= 1;
-				l = le32_to_cpu(inl(addr));
+				l = __raw_readl(addr);
 				*pb++ = l >> 24;
 				ps = (u16 *)pb;
 				*ps++ = ((l >> 8) & 0xffff);
 				pi = (u32 *)ps;
 				while (count--) {
-					l2 = le32_to_cpu(inl(addr));
+					l2 = __raw_readl(addr);
 					*pi++ = (l << 24) | (l2 >> 8);
 					l = l2;
 				}
@@ -190,11 +190,11 @@ void insl(unsigned long __addr, void *ds
 			case 0x3:
 				pb = (u8 *)dst;
 				count -= 1;
-				l = le32_to_cpu(inl(addr));
+				l = __raw_readl(addr);
 				*pb++ = l >> 24;
 				pi = (u32 *)pb;
 				while (count--) {
-					l2 = le32_to_cpu(inl(addr));
+					l2 = __raw_readl(addr);
 					*pi++ = (l << 8) | (l2 >> 24);
 					l = l2;
 				}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/Makefile linux-libre-3.17-rc7-gnu/arch/sparc/Makefile
--- linux-libre-3.16-gnu/arch/sparc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,9 @@ all: zImage
 image zImage uImage tftpboot.img vmlinux.aout: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
+install:
+	$(Q)$(MAKE) $(build)=$(boot) $@
+
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/math-emu/math_32.c linux-libre-3.17-rc7-gnu/arch/sparc/math-emu/math_32.c
--- linux-libre-3.16-gnu/arch/sparc/math-emu/math_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/math-emu/math_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -499,7 +499,7 @@ static int do_one_mathemu(u32 insn, unsi
 		case 0: fsr = *pfsr;
 			if (IR == -1) IR = 2;
 			/* fcc is always fcc0 */
-			fsr &= ~0xc00; fsr |= (IR << 10); break;
+			fsr &= ~0xc00; fsr |= (IR << 10);
 			*pfsr = fsr;
 			break;
 		case 1: rd->s = IR; break;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/mm/init_64.c linux-libre-3.17-rc7-gnu/arch/sparc/mm/init_64.c
--- linux-libre-3.16-gnu/arch/sparc/mm/init_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/mm/init_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/kprobes.h>
 #include <linux/cache.h>
 #include <linux/sort.h>
+#include <linux/ioport.h>
 #include <linux/percpu.h>
 #include <linux/memblock.h>
 #include <linux/mmzone.h>
@@ -351,6 +352,10 @@ void update_mmu_cache(struct vm_area_str
 
 	mm = vma->vm_mm;
 
+	/* Don't insert a non-valid PTE into the TSB, we'll deadlock.  */
+	if (!pte_accessible(mm, pte))
+		return;
+
 	spin_lock_irqsave(&mm->context.lock, flags);
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
@@ -2619,6 +2624,10 @@ void update_mmu_cache_pmd(struct vm_area
 
 	pte = pmd_val(entry);
 
+	/* Don't insert a non-valid PMD into the TSB, we'll deadlock.  */
+	if (!(pte & _PAGE_VALID))
+		return;
+
 	/* We are fabricating 8MB pages using 4MB real hw pages.  */
 	pte |= (addr & (1UL << REAL_HPAGE_SHIFT));
 
@@ -2699,3 +2708,90 @@ void hugetlb_setup(struct pt_regs *regs)
 	}
 }
 #endif
+
+static struct resource code_resource = {
+	.name	= "Kernel code",
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource data_resource = {
+	.name	= "Kernel data",
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource bss_resource = {
+	.name	= "Kernel bss",
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static inline resource_size_t compute_kern_paddr(void *addr)
+{
+	return (resource_size_t) (addr - KERNBASE + kern_base);
+}
+
+static void __init kernel_lds_init(void)
+{
+	code_resource.start = compute_kern_paddr(_text);
+	code_resource.end   = compute_kern_paddr(_etext - 1);
+	data_resource.start = compute_kern_paddr(_etext);
+	data_resource.end   = compute_kern_paddr(_edata - 1);
+	bss_resource.start  = compute_kern_paddr(__bss_start);
+	bss_resource.end    = compute_kern_paddr(_end - 1);
+}
+
+static int __init report_memory(void)
+{
+	int i;
+	struct resource *res;
+
+	kernel_lds_init();
+
+	for (i = 0; i < pavail_ents; i++) {
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+
+		if (!res) {
+			pr_warn("Failed to allocate source.\n");
+			break;
+		}
+
+		res->name = "System RAM";
+		res->start = pavail[i].phys_addr;
+		res->end = pavail[i].phys_addr + pavail[i].reg_size - 1;
+		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+
+		if (insert_resource(&iomem_resource, res) < 0) {
+			pr_warn("Resource insertion failed.\n");
+			break;
+		}
+
+		insert_resource(res, &code_resource);
+		insert_resource(res, &data_resource);
+		insert_resource(res, &bss_resource);
+	}
+
+	return 0;
+}
+device_initcall(report_memory);
+
+#ifdef CONFIG_SMP
+#define do_flush_tlb_kernel_range	smp_flush_tlb_kernel_range
+#else
+#define do_flush_tlb_kernel_range	__flush_tlb_kernel_range
+#endif
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) {
+		if (start < LOW_OBP_ADDRESS) {
+			flush_tsb_kernel_range(start, LOW_OBP_ADDRESS);
+			do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS);
+		}
+		if (end > HI_OBP_ADDRESS) {
+			flush_tsb_kernel_range(end, HI_OBP_ADDRESS);
+			do_flush_tlb_kernel_range(end, HI_OBP_ADDRESS);
+		}
+	} else {
+		flush_tsb_kernel_range(start, end);
+		do_flush_tlb_kernel_range(start, end);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/net/bpf_jit_asm.S linux-libre-3.17-rc7-gnu/arch/sparc/net/bpf_jit_asm.S
--- linux-libre-3.16-gnu/arch/sparc/net/bpf_jit_asm.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/net/bpf_jit_asm.S	2014-09-28 17:29:07.000000000 -0400
@@ -6,10 +6,12 @@
 #define SAVE_SZ		176
 #define SCRATCH_OFF	STACK_BIAS + 128
 #define BE_PTR(label)	be,pn %xcc, label
+#define SIGN_EXTEND(reg)	sra reg, 0, reg
 #else
 #define SAVE_SZ		96
 #define SCRATCH_OFF	72
 #define BE_PTR(label)	be label
+#define SIGN_EXTEND(reg)
 #endif
 
 #define SKF_MAX_NEG_OFF	(-0x200000) /* SKF_LL_OFF from filter.h */
@@ -135,6 +137,7 @@ bpf_slow_path_byte_msh:
 	save	%sp, -SAVE_SZ, %sp;			\
 	mov	%i0, %o0;				\
 	mov	r_OFF, %o1;				\
+	SIGN_EXTEND(%o1);				\
 	call	bpf_internal_load_pointer_neg_helper;	\
 	 mov	(LEN), %o2;				\
 	mov	%o0, r_TMP;				\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/sparc/net/bpf_jit_comp.c linux-libre-3.17-rc7-gnu/arch/sparc/net/bpf_jit_comp.c
--- linux-libre-3.16-gnu/arch/sparc/net/bpf_jit_comp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/sparc/net/bpf_jit_comp.c	2014-09-28 17:29:07.000000000 -0400
@@ -184,7 +184,7 @@ do {								\
 	 */
 #define emit_alu_K(OPCODE, K)					\
 do {								\
-	if (K) {						\
+	if (K || OPCODE == AND || OPCODE == MUL) {		\
 		unsigned int _insn = OPCODE;			\
 		_insn |= RS1(r_A) | RD(r_A);			\
 		if (is_simm13(K)) {				\
@@ -234,12 +234,18 @@ do {	BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, F
 	__emit_load8(BASE, STRUCT, FIELD, DEST);			\
 } while (0)
 
-#define emit_ldmem(OFF, DEST)					\
-do {	*prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST);	\
+#ifdef CONFIG_SPARC64
+#define BIAS (STACK_BIAS - 4)
+#else
+#define BIAS (-4)
+#endif
+
+#define emit_ldmem(OFF, DEST)						\
+do {	*prog++ = LD32I | RS1(SP) | S13(BIAS - (OFF)) | RD(DEST);	\
 } while (0)
 
-#define emit_stmem(OFF, SRC)					\
-do {	*prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC);	\
+#define emit_stmem(OFF, SRC)						\
+do {	*prog++ = ST32I | RS1(SP) | S13(BIAS - (OFF)) | RD(SRC);	\
 } while (0)
 
 #ifdef CONFIG_SMP
@@ -354,7 +360,7 @@ do {	*prog++ = BR_OPC | WDISP22(OFF);		\
  * emit_jump() calls with adjusted offsets.
  */
 
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
 {
 	unsigned int cleanup_addr, proglen, oldproglen = 0;
 	u32 temp[8], *prog, *func, seen = 0, pass;
@@ -615,10 +621,11 @@ void bpf_jit_compile(struct sk_filter *f
 			case BPF_ANC | SKF_AD_VLAN_TAG:
 			case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
 				emit_skb_load16(vlan_tci, r_A);
-				if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
-					emit_andi(r_A, VLAN_VID_MASK, r_A);
+				if (code != (BPF_ANC | SKF_AD_VLAN_TAG)) {
+					emit_alu_K(SRL, 12);
+					emit_andi(r_A, 1, r_A);
 				} else {
-					emit_loadimm(VLAN_TAG_PRESENT, r_TMP);
+					emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
 					emit_and(r_A, r_TMP, r_A);
 				}
 				break;
@@ -630,15 +637,19 @@ void bpf_jit_compile(struct sk_filter *f
 				emit_loadimm(K, r_X);
 				break;
 			case BPF_LD | BPF_MEM:
+				seen |= SEEN_MEM;
 				emit_ldmem(K * 4, r_A);
 				break;
 			case BPF_LDX | BPF_MEM:
+				seen |= SEEN_MEM | SEEN_XREG;
 				emit_ldmem(K * 4, r_X);
 				break;
 			case BPF_ST:
+				seen |= SEEN_MEM;
 				emit_stmem(K * 4, r_A);
 				break;
 			case BPF_STX:
+				seen |= SEEN_MEM | SEEN_XREG;
 				emit_stmem(K * 4, r_X);
 				break;
 
@@ -808,7 +819,7 @@ out:
 	return;
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
 		module_free(NULL, fp->bpf_func);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/configs/tilegx_defconfig linux-libre-3.17-rc7-gnu/arch/tile/configs/tilegx_defconfig
--- linux-libre-3.16-gnu/arch/tile/configs/tilegx_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/configs/tilegx_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -170,7 +170,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/configs/tilepro_defconfig linux-libre-3.17-rc7-gnu/arch/tile/configs/tilepro_defconfig
--- linux-libre-3.16-gnu/arch/tile/configs/tilepro_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/configs/tilepro_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -301,7 +301,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/include/asm/compat.h linux-libre-3.17-rc7-gnu/arch/tile/include/asm/compat.h
--- linux-libre-3.16-gnu/arch/tile/include/asm/compat.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/include/asm/compat.h	2014-09-28 17:29:07.000000000 -0400
@@ -267,8 +267,7 @@ static inline int is_compat_task(void)
 	return current_thread_info()->status & TS_COMPAT;
 }
 
-extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
-				 siginfo_t *info, sigset_t *set,
+extern int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 				 struct pt_regs *regs);
 
 /* Compat syscalls. */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/include/asm/hardwall.h linux-libre-3.17-rc7-gnu/arch/tile/include/asm/hardwall.h
--- linux-libre-3.16-gnu/arch/tile/include/asm/hardwall.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/include/asm/hardwall.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 struct proc_dir_entry;
 #ifdef CONFIG_HARDWALL
 void proc_tile_hardwall_init(struct proc_dir_entry *root);
-int proc_pid_hardwall(struct task_struct *task, char *buffer);
+int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task);
 #else
 static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/tile/include/asm/page.h
--- linux-libre-3.16-gnu/arch/tile/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,12 +39,6 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 
 /*
- * We do define AT_SYSINFO_EHDR to support vDSO,
- * but don't use the gate mechanism.
- */
-#define __HAVE_ARCH_GATE_AREA		1
-
-/*
  * If the Kconfig doesn't specify, set a maximum zone order that
  * is enough so that we can create huge pages from small pages given
  * the respective sizes of the two page types.  See <linux/mmzone.h>.
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/tile/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/tile/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -266,6 +266,8 @@ 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-3.16-gnu/arch/tile/Kconfig linux-libre-3.17-rc7-gnu/arch/tile/Kconfig
--- linux-libre-3.16-gnu/arch/tile/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -128,7 +128,6 @@ config TILEGX
 	select SPARSE_IRQ
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/compat_signal.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/compat_signal.c
--- linux-libre-3.16-gnu/arch/tile/kernel/compat_signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/compat_signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,18 +190,18 @@ static inline void __user *compat_get_si
 	return (void __user *) sp;
 }
 
-int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			  sigset_t *set, struct pt_regs *regs)
+int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	unsigned long restorer;
 	struct compat_rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int usig;
 
-	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+	frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		goto err;
 
 	usig = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -210,12 +210,12 @@ int compat_setup_rt_frame(int sig, struc
 		: sig;
 
 	/* Always write at least the signal number for the stack backtracer. */
-	if (ka->sa.sa_flags & SA_SIGINFO) {
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
 		/* At sigreturn time, restore the callee-save registers too. */
-		err |= copy_siginfo_to_user32(&frame->info, info);
+		err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
 		regs->flags |= PT_FLAGS_RESTORE_REGS;
 	} else {
-		err |= __put_user(info->si_signo, &frame->info.si_signo);
+		err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
 	}
 
 	/* Create the ucontext.  */
@@ -226,11 +226,11 @@ int compat_setup_rt_frame(int sig, struc
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		goto err;
 
 	restorer = VDSO_SYM(&__vdso_rt_sigreturn);
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
 
 	/*
 	 * Set up registers for signal handler.
@@ -239,7 +239,7 @@ int compat_setup_rt_frame(int sig, struc
 	 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
 	 * since some things rely on this (e.g. glibc's debug/segfault.c).
 	 */
-	regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
+	regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
 	regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
 	regs->sp = ptr_to_compat_reg(frame);
 	regs->lr = restorer;
@@ -249,7 +249,8 @@ int compat_setup_rt_frame(int sig, struc
 	regs->flags |= PT_FLAGS_CALLER_SAVES;
 	return 0;
 
-give_sigsegv:
-	signal_fault("bad setup frame", regs, frame, sig);
+err:
+	trace_unhandled_signal("bad sigreturn frame", regs,
+			      (unsigned long)frame, SIGSEGV);
 	return -EFAULT;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/hardwall.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/hardwall.c
--- linux-libre-3.16-gnu/arch/tile/kernel/hardwall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/hardwall.c	2014-09-28 17:29:07.000000000 -0400
@@ -947,15 +947,15 @@ static void hardwall_remove_proc(struct
 	remove_proc_entry(buf, info->type->proc_dir);
 }
 
-int proc_pid_hardwall(struct task_struct *task, char *buffer)
+int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns,
+		      struct pid *pid, struct task_struct *task)
 {
 	int i;
 	int n = 0;
 	for (i = 0; i < HARDWALL_TYPES; ++i) {
 		struct hardwall_info *info = task->thread.hardwall[i].info;
 		if (info)
-			n += sprintf(&buffer[n], "%s: %d\n",
-				     info->type->name, info->id);
+			seq_printf(m, "%s: %d\n", info->type->name, info->id);
 	}
 	return n;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/mcount_64.S linux-libre-3.17-rc7-gnu/arch/tile/kernel/mcount_64.S
--- linux-libre-3.16-gnu/arch/tile/kernel/mcount_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/mcount_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -77,15 +77,6 @@ STD_ENDPROC(__mcount)
 
 	.align	64
 STD_ENTRY(ftrace_caller)
-	moveli	r11, hw2_last(function_trace_stop)
-	{ shl16insli	r11, r11, hw1(function_trace_stop); move r12, lr }
-	{ shl16insli	r11, r11, hw0(function_trace_stop); move lr, r10 }
-	ld	r11, r11
-	beqz	r11, 1f
-	jrp	r12
-
-1:
-	{ move	r10, lr; move	lr, r12 }
 	MCOUNT_SAVE_REGS
 
 	/* arg1: self return address */
@@ -119,15 +110,6 @@ STD_ENDPROC(ftrace_caller)
 
 	.align	64
 STD_ENTRY(__mcount)
-	moveli	r11, hw2_last(function_trace_stop)
-	{ shl16insli	r11, r11, hw1(function_trace_stop); move r12, lr }
-	{ shl16insli	r11, r11, hw0(function_trace_stop); move lr, r10 }
-	ld	r11, r11
-	beqz	r11, 1f
-	jrp	r12
-
-1:
-	{ move	r10, lr; move	lr, r12 }
 	{
 	 moveli	r11, hw2_last(ftrace_trace_function)
 	 moveli	r13, hw2_last(ftrace_stub)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/module.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/module.c
--- linux-libre-3.16-gnu/arch/tile/kernel/module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/module.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ void *module_alloc(unsigned long size)
 	area->nr_pages = npages;
 	area->pages = pages;
 
-	if (map_vm_area(area, prot_rwx, &pages)) {
+	if (map_vm_area(area, prot_rwx, pages)) {
 		vunmap(area->addr);
 		goto error;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/signal.c
--- linux-libre-3.16-gnu/arch/tile/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -153,18 +153,18 @@ static inline void __user *get_sigframe(
 	return (void __user *) sp;
 }
 
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	unsigned long restorer;
 	struct rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int usig;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		goto err;
 
 	usig = current_thread_info()->exec_domain
 		&& current_thread_info()->exec_domain->signal_invmap
@@ -173,12 +173,12 @@ static int setup_rt_frame(int sig, struc
 		: sig;
 
 	/* Always write at least the signal number for the stack backtracer. */
-	if (ka->sa.sa_flags & SA_SIGINFO) {
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
 		/* At sigreturn time, restore the callee-save registers too. */
-		err |= copy_siginfo_to_user(&frame->info, info);
+		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 		regs->flags |= PT_FLAGS_RESTORE_REGS;
 	} else {
-		err |= __put_user(info->si_signo, &frame->info.si_signo);
+		err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
 	}
 
 	/* Create the ucontext.  */
@@ -189,11 +189,11 @@ static int setup_rt_frame(int sig, struc
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		goto give_sigsegv;
+		goto err;
 
 	restorer = VDSO_SYM(&__vdso_rt_sigreturn);
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = (unsigned long) ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		restorer = (unsigned long) ksig->ka.sa.sa_restorer;
 
 	/*
 	 * Set up registers for signal handler.
@@ -202,7 +202,7 @@ static int setup_rt_frame(int sig, struc
 	 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
 	 * since some things rely on this (e.g. glibc's debug/segfault.c).
 	 */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
 	regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
 	regs->sp = (unsigned long) frame;
 	regs->lr = restorer;
@@ -212,8 +212,9 @@ static int setup_rt_frame(int sig, struc
 	regs->flags |= PT_FLAGS_CALLER_SAVES;
 	return 0;
 
-give_sigsegv:
-	signal_fault("bad setup frame", regs, frame, sig);
+err:
+	trace_unhandled_signal("bad sigreturn frame", regs,
+			      (unsigned long)frame, SIGSEGV);
 	return -EFAULT;
 }
 
@@ -221,9 +222,7 @@ give_sigsegv:
  * OK, we're invoking a handler
  */
 
-static void handle_signal(unsigned long sig, siginfo_t *info,
-			 struct k_sigaction *ka,
-			 struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
@@ -238,7 +237,7 @@ static void handle_signal(unsigned long
 			break;
 
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->regs[0] = -EINTR;
 				break;
 			}
@@ -254,14 +253,12 @@ static void handle_signal(unsigned long
 	/* Set up the stack frame */
 #ifdef CONFIG_COMPAT
 	if (is_compat_task())
-		ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
+		ret = compat_setup_rt_frame(ksig, oldset, regs);
 	else
 #endif
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
-	if (ret)
-		return;
-	signal_delivered(sig, info, ka, regs,
-			test_thread_flag(TIF_SINGLESTEP));
+		ret = setup_rt_frame(ksig, oldset, regs);
+
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -271,9 +268,7 @@ static void handle_signal(unsigned long
  */
 void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/*
 	 * i386 will check if we're coming from kernel mode and bail out
@@ -282,10 +277,9 @@ void do_signal(struct pt_regs *regs)
 	 * helpful, we can reinstate the check on "!user_mode(regs)".
 	 */
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		/* Whee! Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, regs);
+		handle_signal(&ksig, regs);
 		goto done;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/smp.c
--- linux-libre-3.16-gnu/arch/tile/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -183,6 +183,7 @@ void flush_icache_range(unsigned long st
 		preempt_enable();
 	}
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 
 /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/time.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/time.c
--- linux-libre-3.16-gnu/arch/tile/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -260,9 +260,8 @@ void update_vsyscall_tz(void)
 
 void update_vsyscall(struct timekeeper *tk)
 {
-	struct timespec wall_time = tk_xtime(tk);
 	struct timespec *wtm = &tk->wall_to_monotonic;
-	struct clocksource *clock = tk->clock;
+	struct clocksource *clock = tk->tkr.clock;
 
 	if (clock != &cycle_counter_cs)
 		return;
@@ -270,13 +269,13 @@ void update_vsyscall(struct timekeeper *
 	/* Userspace gettimeofday will spin while this value is odd. */
 	++vdso_data->tb_update_count;
 	smp_wmb();
-	vdso_data->xtime_tod_stamp = clock->cycle_last;
-	vdso_data->xtime_clock_sec = wall_time.tv_sec;
-	vdso_data->xtime_clock_nsec = wall_time.tv_nsec;
+	vdso_data->xtime_tod_stamp = tk->tkr.cycle_last;
+	vdso_data->xtime_clock_sec = tk->xtime_sec;
+	vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
 	vdso_data->wtom_clock_sec = wtm->tv_sec;
 	vdso_data->wtom_clock_nsec = wtm->tv_nsec;
-	vdso_data->mult = clock->mult;
-	vdso_data->shift = clock->shift;
+	vdso_data->mult = tk->tkr.mult;
+	vdso_data->shift = tk->tkr.shift;
 	smp_wmb();
 	++vdso_data->tb_update_count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/vdso/vgettimeofday.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/vdso/vgettimeofday.c
--- linux-libre-3.16-gnu/arch/tile/kernel/vdso/vgettimeofday.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/vdso/vgettimeofday.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,10 +83,11 @@ int __vdso_gettimeofday(struct timeval *
 		if (count & 1)
 			continue;
 
-		cycles = (get_cycles() - vdso_data->xtime_tod_stamp);
-		ns = (cycles * vdso_data->mult) >> vdso_data->shift;
 		sec = vdso_data->xtime_clock_sec;
-		ns += vdso_data->xtime_clock_nsec;
+		cycles = get_cycles() - vdso_data->xtime_tod_stamp;
+		ns = (cycles * vdso_data->mult) + vdso_data->xtime_clock_nsec;
+		ns >>= vdso_data->shift;
+
 		if (ns >= NSEC_PER_SEC) {
 			ns -= NSEC_PER_SEC;
 			sec += 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/tile/kernel/vdso.c linux-libre-3.17-rc7-gnu/arch/tile/kernel/vdso.c
--- linux-libre-3.16-gnu/arch/tile/kernel/vdso.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/tile/kernel/vdso.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,21 +121,6 @@ const char *arch_vma_name(struct vm_area
 	return NULL;
 }
 
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long address)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long address)
-{
-	return 0;
-}
-
 int setup_vdso_pages(void)
 {
 	struct page **pagelist;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/um/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/um/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/um/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/um/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@ generic-y += param.h
 generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += switch_to.h
 generic-y += topology.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/um/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/um/include/asm/page.h
--- linux-libre-3.16-gnu/arch/um/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/um/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -119,4 +119,9 @@ extern unsigned long uml_physmem;
 #include <asm-generic/getorder.h>
 
 #endif	/* __ASSEMBLY__ */
+
+#ifdef CONFIG_X86_32
+#define __HAVE_ARCH_GATE_AREA 1
+#endif
+
 #endif	/* __UM_PAGE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/um/include/shared/frame_kern.h linux-libre-3.17-rc7-gnu/arch/um/include/shared/frame_kern.h
--- linux-libre-3.16-gnu/arch/um/include/shared/frame_kern.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/um/include/shared/frame_kern.h	2014-09-28 17:29:07.000000000 -0400
@@ -6,14 +6,10 @@
 #ifndef __FRAME_KERN_H_
 #define __FRAME_KERN_H_
 
-extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
-				 struct k_sigaction *ka,
-				 struct pt_regs *regs,
-				 sigset_t *mask);
-extern int setup_signal_stack_si(unsigned long stack_top, int sig,
-				 struct k_sigaction *ka,
-				 struct pt_regs *regs, struct siginfo *info,
-				 sigset_t *mask);
+extern int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
+				 struct pt_regs *regs, sigset_t *mask);
+extern int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+				 struct pt_regs *regs, sigset_t *mask);
 
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/um/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/um/kernel/signal.c
--- linux-libre-3.16-gnu/arch/um/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/um/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,8 +18,7 @@ EXPORT_SYMBOL(unblock_signals);
 /*
  * OK, we're invoking a handler
  */
-static void handle_signal(struct pt_regs *regs, unsigned long signr,
-			 struct k_sigaction *ka, struct siginfo *info)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int singlestep = 0;
@@ -39,7 +38,7 @@ static void handle_signal(struct pt_regs
 			break;
 
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				PT_REGS_SYSCALL_RET(regs) = -EINTR;
 				break;
 			}
@@ -52,32 +51,28 @@ static void handle_signal(struct pt_regs
 	}
 
 	sp = PT_REGS_SP(regs);
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+	if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
-	if (!(ka->sa.sa_flags & SA_SIGINFO))
-		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
+	if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
+		err = setup_signal_stack_sc(sp, ksig, regs, oldset);
 	else
 #endif
-		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
+		err = setup_signal_stack_si(sp, ksig, regs, oldset);
 
-	if (err)
-		force_sigsegv(signr, current);
-	else
-		signal_delivered(signr, info, ka, regs, singlestep);
+	signal_setup_done(err, ksig, singlestep);
 }
 
 static int kern_do_signal(struct pt_regs *regs)
 {
-	struct k_sigaction ka_copy;
-	struct siginfo info;
-	int sig, handled_sig = 0;
+	struct ksignal ksig;
+	int handled_sig = 0;
 
-	while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
+	while (get_signal(&ksig)) {
 		handled_sig = 1;
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(regs, sig, &ka_copy, &info);
+		handle_signal(&ksig, regs);
 	}
 
 	/* Did we come from a system call? */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/unicore32/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/unicore32/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/unicore32/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/unicore32/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -71,6 +71,7 @@ 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-3.16-gnu/arch/unicore32/kernel/puv3-core.c linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/puv3-core.c
--- linux-libre-3.16-gnu/arch/unicore32/kernel/puv3-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/puv3-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -272,7 +272,7 @@ void __init puv3_core_init(void)
 	platform_device_register_simple("PKUnity-v3-UART", 1,
 			puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
 	platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
-	platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+	platform_device_register_resndata(NULL, "musb_hdrc", -1,
 			puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
 			&puv3_usb_plat, sizeof(puv3_usb_plat));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/unicore32/kernel/puv3-nb0916.c linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/puv3-nb0916.c
--- linux-libre-3.16-gnu/arch/unicore32/kernel/puv3-nb0916.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/puv3-nb0916.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,13 +112,13 @@ int __init mach_nb0916_init(void)
 	platform_device_register_simple("PKUnity-v3-I2C", -1,
 			puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
 
-	platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+	platform_device_register_data(NULL, "pwm-backlight", -1,
 			&nb0916_backlight_data, sizeof(nb0916_backlight_data));
 
-	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+	platform_device_register_data(NULL, "gpio-keys", -1,
 			&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
 
-	platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+	platform_device_register_resndata(NULL, "physmap-flash", -1,
 			&physmap_flash_resource, 1,
 			&physmap_flash_data, sizeof(physmap_flash_data));
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/unicore32/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/signal.c
--- linux-libre-3.16-gnu/arch/unicore32/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/unicore32/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -238,10 +238,10 @@ static int setup_return(struct pt_regs *
 	return 0;
 }
 
-static int setup_frame(int usig, struct k_sigaction *ka,
-		sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+		       struct pt_regs *regs)
 {
-	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
+	struct sigframe __user *frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
 	int err = 0;
 
 	if (!frame)
@@ -254,29 +254,31 @@ static int setup_frame(int usig, struct
 
 	err |= setup_sigframe(frame, regs, set);
 	if (err == 0)
-		err |= setup_return(regs, ka, frame->retcode, frame, usig);
+		err |= setup_return(regs, &ksig->ka, frame->retcode, frame,
+				    ksig->sig);
 
 	return err;
 }
 
-static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame =
-			get_sigframe(ka, regs, sizeof(*frame));
+			get_sigframe(&ksig->ka, regs, sizeof(*frame));
 	int err = 0;
 
 	if (!frame)
 		return 1;
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	err |= __put_user(0, &frame->sig.uc.uc_flags);
 	err |= __put_user(NULL, &frame->sig.uc.uc_link);
 	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp);
 	err |= setup_sigframe(&frame->sig, regs, set);
 	if (err == 0)
-		err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
+		err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame,
+				    ksig->sig);
 
 	if (err == 0) {
 		/*
@@ -299,13 +301,12 @@ static inline void setup_syscall_restart
 /*
  * OK, we're invoking a handler
  */
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
-	      siginfo_t *info, struct pt_regs *regs, int syscall)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
+			  int syscall)
 {
 	struct thread_info *thread = current_thread_info();
-	struct task_struct *tsk = current;
 	sigset_t *oldset = sigmask_to_save();
-	int usig = sig;
+	int usig = ksig->sig;
 	int ret;
 
 	/*
@@ -318,7 +319,7 @@ static void handle_signal(unsigned long
 			regs->UCreg_00 = -EINTR;
 			break;
 		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 				regs->UCreg_00 = -EINTR;
 				break;
 			}
@@ -338,22 +339,17 @@ static void handle_signal(unsigned long
 	/*
 	 * Set up the stack frame
 	 */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(usig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(usig, ka, oldset, regs);
+		ret = setup_frame(ksig, oldset, regs);
 
 	/*
 	 * Check that the resulting registers are actually sane.
 	 */
 	ret |= !valid_user_regs(regs);
 
-	if (ret != 0) {
-		force_sigsegv(sig, tsk);
-		return;
-	}
-
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 /*
@@ -367,9 +363,7 @@ static void handle_signal(unsigned long
  */
 static void do_signal(struct pt_regs *regs, int syscall)
 {
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
+	struct ksignal ksig;
 
 	/*
 	 * We want the common case to go fast, which
@@ -380,9 +374,8 @@ static void do_signal(struct pt_regs *re
 	if (!user_mode(regs))
 		return;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &ka, &info, regs, syscall);
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig, regs, syscall);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/boot/code16gcc.h linux-libre-3.17-rc7-gnu/arch/x86/boot/code16gcc.h
--- linux-libre-3.16-gnu/arch/x86/boot/code16gcc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/boot/code16gcc.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,15 +1,11 @@
-/*
- * code16gcc.h
- *
- * This file is -include'd when compiling 16-bit C code.
- * Note: this asm() needs to be emitted before gcc emits any code.
- * Depending on gcc version, this requires -fno-unit-at-a-time or
- * -fno-toplevel-reorder.
- *
- * Hopefully gcc will eventually have a real -m16 option so we can
- * drop this hack long term.
- */
+#
+# code16gcc.h
+#
+# This file is added to the assembler via -Wa when compiling 16-bit C code.
+# This is done this way instead via asm() to make sure gcc does not reorder
+# things around us.
+#
+# gcc 4.9+ has a real -m16 option so we can drop this hack long term.
+#
 
-#ifndef __ASSEMBLY__
-asm(".code16gcc");
-#endif
+	.code16gcc
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/boot/compressed/aslr.c linux-libre-3.17-rc7-gnu/arch/x86/boot/compressed/aslr.c
--- linux-libre-3.16-gnu/arch/x86/boot/compressed/aslr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/boot/compressed/aslr.c	2014-09-28 17:29:07.000000000 -0400
@@ -183,12 +183,27 @@ static void mem_avoid_init(unsigned long
 static bool mem_avoid_overlap(struct mem_vector *img)
 {
 	int i;
+	struct setup_data *ptr;
 
 	for (i = 0; i < MEM_AVOID_MAX; i++) {
 		if (mem_overlaps(img, &mem_avoid[i]))
 			return true;
 	}
 
+	/* Avoid all entries in the setup_data linked list. */
+	ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data;
+	while (ptr) {
+		struct mem_vector avoid;
+
+		avoid.start = (u64)ptr;
+		avoid.size = sizeof(*ptr) + ptr->len;
+
+		if (mem_overlaps(img, &avoid))
+			return true;
+
+		ptr = (struct setup_data *)(unsigned long)ptr->next;
+	}
+
 	return false;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/boot/compressed/eboot.c linux-libre-3.17-rc7-gnu/arch/x86/boot/compressed/eboot.c
--- linux-libre-3.16-gnu/arch/x86/boot/compressed/eboot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/boot/compressed/eboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,8 +48,7 @@ static void setup_boot_services##bits(st
 BOOT_SERVICES(32);
 BOOT_SERVICES(64);
 
-static void efi_printk(efi_system_table_t *, char *);
-static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 static efi_status_t
 __file_size32(void *__fh, efi_char16_t *filename_16,
@@ -156,7 +155,7 @@ grow:
 
 	return status;
 }
-static efi_status_t
+efi_status_t
 efi_file_size(efi_system_table_t *sys_table, void *__fh,
 	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
 {
@@ -166,7 +165,7 @@ efi_file_size(efi_system_table_t *sys_ta
 	return __file_size32(__fh, filename_16, handle, file_sz);
 }
 
-static inline efi_status_t
+efi_status_t
 efi_file_read(void *handle, unsigned long *size, void *addr)
 {
 	unsigned long func;
@@ -184,7 +183,7 @@ efi_file_read(void *handle, unsigned lon
 	}
 }
 
-static inline efi_status_t efi_file_close(void *handle)
+efi_status_t efi_file_close(void *handle)
 {
 	if (efi_early->is64) {
 		efi_file_handle_64_t *fh = handle;
@@ -249,7 +248,7 @@ static inline efi_status_t __open_volume
 	return status;
 }
 
-static inline efi_status_t
+efi_status_t
 efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
 {
 	if (efi_early->is64)
@@ -258,7 +257,7 @@ efi_open_volume(efi_system_table_t *sys_
 	return __open_volume32(__image, __fh);
 }
 
-static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
 {
 	unsigned long output_string;
 	size_t offset;
@@ -269,22 +268,24 @@ static void efi_char16_printk(efi_system
 
 		offset = offsetof(typeof(*out), output_string);
 		output_string = efi_early->text_output + offset;
+		out = (typeof(out))(unsigned long)efi_early->text_output;
 		func = (u64 *)output_string;
 
-		efi_early->call(*func, efi_early->text_output, str);
+		efi_early->call(*func, out, str);
 	} else {
 		struct efi_simple_text_output_protocol_32 *out;
 		u32 *func;
 
 		offset = offsetof(typeof(*out), output_string);
 		output_string = efi_early->text_output + offset;
+		out = (typeof(out))(unsigned long)efi_early->text_output;
 		func = (u32 *)output_string;
 
-		efi_early->call(*func, efi_early->text_output, str);
+		efi_early->call(*func, out, str);
 	}
 }
 
-#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
+#include "../../../../drivers/firmware/efi/libstub/efi-stub-helper.c"
 
 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
 {
@@ -366,7 +367,7 @@ free_struct:
 	return status;
 }
 
-static efi_status_t
+static void
 setup_efi_pci32(struct boot_params *params, void **pci_handle,
 		unsigned long size)
 {
@@ -409,8 +410,6 @@ setup_efi_pci32(struct boot_params *para
 		data = (struct setup_data *)rom;
 
 	}
-
-	return status;
 }
 
 static efi_status_t
@@ -469,7 +468,7 @@ free_struct:
 
 }
 
-static efi_status_t
+static void
 setup_efi_pci64(struct boot_params *params, void **pci_handle,
 		unsigned long size)
 {
@@ -512,11 +511,18 @@ setup_efi_pci64(struct boot_params *para
 		data = (struct setup_data *)rom;
 
 	}
-
-	return status;
 }
 
-static efi_status_t setup_efi_pci(struct boot_params *params)
+/*
+ * There's no way to return an informative status from this function,
+ * because any analysis (and printing of error messages) needs to be
+ * done directly at the EFI function call-site.
+ *
+ * For example, EFI_INVALID_PARAMETER could indicate a bug or maybe we
+ * just didn't find any PCI devices, but there's no way to tell outside
+ * the context of the call.
+ */
+static void setup_efi_pci(struct boot_params *params)
 {
 	efi_status_t status;
 	void **pci_handle = NULL;
@@ -533,7 +539,7 @@ static efi_status_t setup_efi_pci(struct
 					size, (void **)&pci_handle);
 
 		if (status != EFI_SUCCESS)
-			return status;
+			return;
 
 		status = efi_call_early(locate_handle,
 					EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -544,13 +550,12 @@ static efi_status_t setup_efi_pci(struct
 		goto free_handle;
 
 	if (efi_early->is64)
-		status = setup_efi_pci64(params, pci_handle, size);
+		setup_efi_pci64(params, pci_handle, size);
 	else
-		status = setup_efi_pci32(params, pci_handle, size);
+		setup_efi_pci32(params, pci_handle, size);
 
 free_handle:
 	efi_call_early(free_pool, pci_handle);
-	return status;
 }
 
 static void
@@ -1104,10 +1109,22 @@ struct boot_params *make_boot_params(str
 				      (char *)(unsigned long)hdr->cmd_line_ptr,
 				      "initrd=", hdr->initrd_addr_max,
 				      &ramdisk_addr, &ramdisk_size);
+
+	if (status != EFI_SUCCESS &&
+	    hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
+		efi_printk(sys_table, "Trying to load files to higher address\n");
+		status = handle_cmdline_files(sys_table, image,
+				      (char *)(unsigned long)hdr->cmd_line_ptr,
+				      "initrd=", -1UL,
+				      &ramdisk_addr, &ramdisk_size);
+	}
+
 	if (status != EFI_SUCCESS)
 		goto fail2;
-	hdr->ramdisk_image = ramdisk_addr;
-	hdr->ramdisk_size = ramdisk_size;
+	hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
+	hdr->ramdisk_size  = ramdisk_size & 0xffffffff;
+	boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
+	boot_params->ext_ramdisk_size  = (u64)ramdisk_size >> 32;
 
 	return boot_params;
 fail2:
@@ -1401,16 +1418,20 @@ struct boot_params *efi_main(struct efi_
 					     hdr->init_size, hdr->init_size,
 					     hdr->pref_address,
 					     hdr->kernel_alignment);
-		if (status != EFI_SUCCESS)
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
 			goto fail;
+		}
 
 		hdr->pref_address = hdr->code32_start;
 		hdr->code32_start = bzimage_addr;
 	}
 
 	status = exit_boot(boot_params, handle, is64);
-	if (status != EFI_SUCCESS)
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table, "exit_boot() failed!\n");
 		goto fail;
+	}
 
 	memset((char *)gdt->address, 0x0, gdt->size);
 	desc = (struct desc_struct *)gdt->address;
@@ -1470,5 +1491,6 @@ struct boot_params *efi_main(struct efi_
 
 	return boot_params;
 fail:
+	efi_printk(sys_table, "efi_main() failed!\n");
 	return NULL;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/boot/header.S linux-libre-3.17-rc7-gnu/arch/x86/boot/header.S
--- linux-libre-3.16-gnu/arch/x86/boot/header.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/boot/header.S	2014-09-28 17:29:07.000000000 -0400
@@ -154,7 +154,7 @@ extra_header_fields:
 #else
 	.quad	0				# ImageBase
 #endif
-	.long	0x20				# SectionAlignment
+	.long	CONFIG_PHYSICAL_ALIGN		# SectionAlignment
 	.long	0x20				# FileAlignment
 	.word	0				# MajorOperatingSystemVersion
 	.word	0				# MinorOperatingSystemVersion
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/aes_ctrby8_avx-x86_64.S linux-libre-3.17-rc7-gnu/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
--- linux-libre-3.16-gnu/arch/x86/crypto/aes_ctrby8_avx-x86_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/aes_ctrby8_avx-x86_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,546 @@
+/*
+ *	Implement AES CTR mode by8 optimization with AVX instructions. (x86_64)
+ *
+ * This is AES128/192/256 CTR mode optimization implementation. It requires
+ * the support of Intel(R) AESNI and AVX instructions.
+ *
+ * This work was inspired by the AES CTR mode optimization published
+ * in Intel Optimized IPSEC Cryptograhpic library.
+ * Additional information on it can be found at:
+ *    http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=22972
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * Contact Information:
+ * James Guilford <james.guilford@intel.com>
+ * Sean Gulley <sean.m.gulley@intel.com>
+ * Chandramouli Narayanan <mouli@linux.intel.com>
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/inst.h>
+
+#define CONCAT(a,b)	a##b
+#define VMOVDQ		vmovdqu
+
+#define xdata0		%xmm0
+#define xdata1		%xmm1
+#define xdata2		%xmm2
+#define xdata3		%xmm3
+#define xdata4		%xmm4
+#define xdata5		%xmm5
+#define xdata6		%xmm6
+#define xdata7		%xmm7
+#define xcounter	%xmm8
+#define xbyteswap	%xmm9
+#define xkey0		%xmm10
+#define xkey3		%xmm11
+#define xkey6		%xmm12
+#define xkey9		%xmm13
+#define xkey4		%xmm11
+#define xkey8		%xmm12
+#define xkey12		%xmm13
+#define xkeyA		%xmm14
+#define xkeyB		%xmm15
+
+#define p_in		%rdi
+#define p_iv		%rsi
+#define p_keys		%rdx
+#define p_out		%rcx
+#define num_bytes	%r8
+
+#define tmp		%r10
+#define	DDQ(i)		CONCAT(ddq_add_,i)
+#define	XMM(i)		CONCAT(%xmm, i)
+#define	DDQ_DATA	0
+#define	XDATA		1
+#define KEY_128		1
+#define KEY_192		2
+#define KEY_256		3
+
+.section .rodata
+.align 16
+
+byteswap_const:
+	.octa 0x000102030405060708090A0B0C0D0E0F
+ddq_add_1:
+	.octa 0x00000000000000000000000000000001
+ddq_add_2:
+	.octa 0x00000000000000000000000000000002
+ddq_add_3:
+	.octa 0x00000000000000000000000000000003
+ddq_add_4:
+	.octa 0x00000000000000000000000000000004
+ddq_add_5:
+	.octa 0x00000000000000000000000000000005
+ddq_add_6:
+	.octa 0x00000000000000000000000000000006
+ddq_add_7:
+	.octa 0x00000000000000000000000000000007
+ddq_add_8:
+	.octa 0x00000000000000000000000000000008
+
+.text
+
+/* generate a unique variable for ddq_add_x */
+
+.macro setddq n
+	var_ddq_add = DDQ(\n)
+.endm
+
+/* generate a unique variable for xmm register */
+.macro setxdata n
+	var_xdata = XMM(\n)
+.endm
+
+/* club the numeric 'id' to the symbol 'name' */
+
+.macro club name, id
+.altmacro
+	.if \name == DDQ_DATA
+		setddq %\id
+	.elseif \name == XDATA
+		setxdata %\id
+	.endif
+.noaltmacro
+.endm
+
+/*
+ * do_aes num_in_par load_keys key_len
+ * This increments p_in, but not p_out
+ */
+.macro do_aes b, k, key_len
+	.set by, \b
+	.set load_keys, \k
+	.set klen, \key_len
+
+	.if (load_keys)
+		vmovdqa	0*16(p_keys), xkey0
+	.endif
+
+	vpshufb	xbyteswap, xcounter, xdata0
+
+	.set i, 1
+	.rept (by - 1)
+		club DDQ_DATA, i
+		club XDATA, i
+		vpaddd	var_ddq_add(%rip), xcounter, var_xdata
+		vpshufb	xbyteswap, var_xdata, var_xdata
+		.set i, (i +1)
+	.endr
+
+	vmovdqa	1*16(p_keys), xkeyA
+
+	vpxor	xkey0, xdata0, xdata0
+	club DDQ_DATA, by
+	vpaddd	var_ddq_add(%rip), xcounter, xcounter
+
+	.set i, 1
+	.rept (by - 1)
+		club XDATA, i
+		vpxor	xkey0, var_xdata, var_xdata
+		.set i, (i +1)
+	.endr
+
+	vmovdqa	2*16(p_keys), xkeyB
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyA, var_xdata, var_xdata		/* key 1 */
+		.set i, (i +1)
+	.endr
+
+	.if (klen == KEY_128)
+		.if (load_keys)
+			vmovdqa	3*16(p_keys), xkeyA
+		.endif
+	.else
+		vmovdqa	3*16(p_keys), xkeyA
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyB, var_xdata, var_xdata		/* key 2 */
+		.set i, (i +1)
+	.endr
+
+	add	$(16*by), p_in
+
+	.if (klen == KEY_128)
+		vmovdqa	4*16(p_keys), xkey4
+	.else
+		.if (load_keys)
+			vmovdqa	4*16(p_keys), xkey4
+		.endif
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyA, var_xdata, var_xdata		/* key 3 */
+		.set i, (i +1)
+	.endr
+
+	vmovdqa	5*16(p_keys), xkeyA
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkey4, var_xdata, var_xdata		/* key 4 */
+		.set i, (i +1)
+	.endr
+
+	.if (klen == KEY_128)
+		.if (load_keys)
+			vmovdqa	6*16(p_keys), xkeyB
+		.endif
+	.else
+		vmovdqa	6*16(p_keys), xkeyB
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyA, var_xdata, var_xdata		/* key 5 */
+		.set i, (i +1)
+	.endr
+
+	vmovdqa	7*16(p_keys), xkeyA
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyB, var_xdata, var_xdata		/* key 6 */
+		.set i, (i +1)
+	.endr
+
+	.if (klen == KEY_128)
+		vmovdqa	8*16(p_keys), xkey8
+	.else
+		.if (load_keys)
+			vmovdqa	8*16(p_keys), xkey8
+		.endif
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyA, var_xdata, var_xdata		/* key 7 */
+		.set i, (i +1)
+	.endr
+
+	.if (klen == KEY_128)
+		.if (load_keys)
+			vmovdqa	9*16(p_keys), xkeyA
+		.endif
+	.else
+		vmovdqa	9*16(p_keys), xkeyA
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkey8, var_xdata, var_xdata		/* key 8 */
+		.set i, (i +1)
+	.endr
+
+	vmovdqa	10*16(p_keys), xkeyB
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		vaesenc	xkeyA, var_xdata, var_xdata		/* key 9 */
+		.set i, (i +1)
+	.endr
+
+	.if (klen != KEY_128)
+		vmovdqa	11*16(p_keys), xkeyA
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		/* key 10 */
+		.if (klen == KEY_128)
+			vaesenclast	xkeyB, var_xdata, var_xdata
+		.else
+			vaesenc	xkeyB, var_xdata, var_xdata
+		.endif
+		.set i, (i +1)
+	.endr
+
+	.if (klen != KEY_128)
+		.if (load_keys)
+			vmovdqa	12*16(p_keys), xkey12
+		.endif
+
+		.set i, 0
+		.rept by
+			club XDATA, i
+			vaesenc	xkeyA, var_xdata, var_xdata	/* key 11 */
+			.set i, (i +1)
+		.endr
+
+		.if (klen == KEY_256)
+			vmovdqa	13*16(p_keys), xkeyA
+		.endif
+
+		.set i, 0
+		.rept by
+			club XDATA, i
+			.if (klen == KEY_256)
+				/* key 12 */
+				vaesenc	xkey12, var_xdata, var_xdata
+			.else
+				vaesenclast xkey12, var_xdata, var_xdata
+			.endif
+			.set i, (i +1)
+		.endr
+
+		.if (klen == KEY_256)
+			vmovdqa	14*16(p_keys), xkeyB
+
+			.set i, 0
+			.rept by
+				club XDATA, i
+				/* key 13 */
+				vaesenc	xkeyA, var_xdata, var_xdata
+				.set i, (i +1)
+			.endr
+
+			.set i, 0
+			.rept by
+				club XDATA, i
+				/* key 14 */
+				vaesenclast	xkeyB, var_xdata, var_xdata
+				.set i, (i +1)
+			.endr
+		.endif
+	.endif
+
+	.set i, 0
+	.rept (by / 2)
+		.set j, (i+1)
+		VMOVDQ	(i*16 - 16*by)(p_in), xkeyA
+		VMOVDQ	(j*16 - 16*by)(p_in), xkeyB
+		club XDATA, i
+		vpxor	xkeyA, var_xdata, var_xdata
+		club XDATA, j
+		vpxor	xkeyB, var_xdata, var_xdata
+		.set i, (i+2)
+	.endr
+
+	.if (i < by)
+		VMOVDQ	(i*16 - 16*by)(p_in), xkeyA
+		club XDATA, i
+		vpxor	xkeyA, var_xdata, var_xdata
+	.endif
+
+	.set i, 0
+	.rept by
+		club XDATA, i
+		VMOVDQ	var_xdata, i*16(p_out)
+		.set i, (i+1)
+	.endr
+.endm
+
+.macro do_aes_load val, key_len
+	do_aes \val, 1, \key_len
+.endm
+
+.macro do_aes_noload val, key_len
+	do_aes \val, 0, \key_len
+.endm
+
+/* main body of aes ctr load */
+
+.macro do_aes_ctrmain key_len
+
+	cmp	$16, num_bytes
+	jb	.Ldo_return2\key_len
+
+	vmovdqa	byteswap_const(%rip), xbyteswap
+	vmovdqu	(p_iv), xcounter
+	vpshufb	xbyteswap, xcounter, xcounter
+
+	mov	num_bytes, tmp
+	and	$(7*16), tmp
+	jz	.Lmult_of_8_blks\key_len
+
+	/* 1 <= tmp <= 7 */
+	cmp	$(4*16), tmp
+	jg	.Lgt4\key_len
+	je	.Leq4\key_len
+
+.Llt4\key_len:
+	cmp	$(2*16), tmp
+	jg	.Leq3\key_len
+	je	.Leq2\key_len
+
+.Leq1\key_len:
+	do_aes_load	1, \key_len
+	add	$(1*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Leq2\key_len:
+	do_aes_load	2, \key_len
+	add	$(2*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+
+.Leq3\key_len:
+	do_aes_load	3, \key_len
+	add	$(3*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Leq4\key_len:
+	do_aes_load	4, \key_len
+	add	$(4*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Lgt4\key_len:
+	cmp	$(6*16), tmp
+	jg	.Leq7\key_len
+	je	.Leq6\key_len
+
+.Leq5\key_len:
+	do_aes_load	5, \key_len
+	add	$(5*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Leq6\key_len:
+	do_aes_load	6, \key_len
+	add	$(6*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Leq7\key_len:
+	do_aes_load	7, \key_len
+	add	$(7*16), p_out
+	and	$(~7*16), num_bytes
+	jz	.Ldo_return2\key_len
+	jmp	.Lmain_loop2\key_len
+
+.Lmult_of_8_blks\key_len:
+	.if (\key_len != KEY_128)
+		vmovdqa	0*16(p_keys), xkey0
+		vmovdqa	4*16(p_keys), xkey4
+		vmovdqa	8*16(p_keys), xkey8
+		vmovdqa	12*16(p_keys), xkey12
+	.else
+		vmovdqa	0*16(p_keys), xkey0
+		vmovdqa	3*16(p_keys), xkey4
+		vmovdqa	6*16(p_keys), xkey8
+		vmovdqa	9*16(p_keys), xkey12
+	.endif
+.align 16
+.Lmain_loop2\key_len:
+	/* num_bytes is a multiple of 8 and >0 */
+	do_aes_noload	8, \key_len
+	add	$(8*16), p_out
+	sub	$(8*16), num_bytes
+	jne	.Lmain_loop2\key_len
+
+.Ldo_return2\key_len:
+	/* return updated IV */
+	vpshufb	xbyteswap, xcounter, xcounter
+	vmovdqu	xcounter, (p_iv)
+	ret
+.endm
+
+/*
+ * routine to do AES128 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_128_avx_by8(void *in, void *iv, void *keys, void *out,
+ *			unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_128_avx_by8)
+	/* call the aes main loop */
+	do_aes_ctrmain KEY_128
+
+ENDPROC(aes_ctr_enc_128_avx_by8)
+
+/*
+ * routine to do AES192 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_192_avx_by8(void *in, void *iv, void *keys, void *out,
+ *			unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_192_avx_by8)
+	/* call the aes main loop */
+	do_aes_ctrmain KEY_192
+
+ENDPROC(aes_ctr_enc_192_avx_by8)
+
+/*
+ * routine to do AES256 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_256_avx_by8(void *in, void *iv, void *keys, void *out,
+ *			unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_256_avx_by8)
+	/* call the aes main loop */
+	do_aes_ctrmain KEY_256
+
+ENDPROC(aes_ctr_enc_256_avx_by8)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-3.17-rc7-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-3.16-gnu/arch/x86/crypto/aesni-intel_glue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/aesni-intel_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,6 +105,9 @@ void crypto_fpu_exit(void);
 #define AVX_GEN4_OPTSIZE 4096
 
 #ifdef CONFIG_X86_64
+
+static void (*aesni_ctr_enc_tfm)(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len, u8 *iv);
 asmlinkage void aesni_ctr_enc(struct crypto_aes_ctx *ctx, u8 *out,
 			      const u8 *in, unsigned int len, u8 *iv);
 
@@ -155,6 +158,12 @@ asmlinkage void aesni_gcm_dec(void *ctx,
 
 
 #ifdef CONFIG_AS_AVX
+asmlinkage void aes_ctr_enc_128_avx_by8(const u8 *in, u8 *iv,
+		void *keys, u8 *out, unsigned int num_bytes);
+asmlinkage void aes_ctr_enc_192_avx_by8(const u8 *in, u8 *iv,
+		void *keys, u8 *out, unsigned int num_bytes);
+asmlinkage void aes_ctr_enc_256_avx_by8(const u8 *in, u8 *iv,
+		void *keys, u8 *out, unsigned int num_bytes);
 /*
  * asmlinkage void aesni_gcm_precomp_avx_gen2()
  * gcm_data *my_ctx_data, context data
@@ -472,6 +481,25 @@ static void ctr_crypt_final(struct crypt
 	crypto_inc(ctrblk, AES_BLOCK_SIZE);
 }
 
+#if 0	/* temporary disabled due to failing crypto tests */
+static void aesni_ctr_enc_avx_tfm(struct crypto_aes_ctx *ctx, u8 *out,
+			      const u8 *in, unsigned int len, u8 *iv)
+{
+	/*
+	 * based on key length, override with the by8 version
+	 * of ctr mode encryption/decryption for improved performance
+	 * aes_set_key_common() ensures that key length is one of
+	 * {128,192,256}
+	 */
+	if (ctx->key_length == AES_KEYSIZE_128)
+		aes_ctr_enc_128_avx_by8(in, iv, (void *)ctx, out, len);
+	else if (ctx->key_length == AES_KEYSIZE_192)
+		aes_ctr_enc_192_avx_by8(in, iv, (void *)ctx, out, len);
+	else
+		aes_ctr_enc_256_avx_by8(in, iv, (void *)ctx, out, len);
+}
+#endif
+
 static int ctr_crypt(struct blkcipher_desc *desc,
 		     struct scatterlist *dst, struct scatterlist *src,
 		     unsigned int nbytes)
@@ -486,8 +514,8 @@ static int ctr_crypt(struct blkcipher_de
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
-		aesni_ctr_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
-			      nbytes & AES_BLOCK_MASK, walk.iv);
+		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);
 	}
@@ -1493,6 +1521,14 @@ static int __init aesni_init(void)
 		aesni_gcm_enc_tfm = aesni_gcm_enc;
 		aesni_gcm_dec_tfm = aesni_gcm_dec;
 	}
+	aesni_ctr_enc_tfm = aesni_ctr_enc;
+#if 0	/* temporary disabled due to failing crypto tests */
+	if (cpu_has_avx) {
+		/* optimize performance of ctr mode encryption transform */
+		aesni_ctr_enc_tfm = aesni_ctr_enc_avx_tfm;
+		pr_info("AES CTR mode by8 optimization enabled\n");
+	}
+#endif
 #endif
 
 	err = crypto_fpu_init();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/crc32c-pcl-intel-asm_64.S linux-libre-3.17-rc7-gnu/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
--- linux-libre-3.16-gnu/arch/x86/crypto/crc32c-pcl-intel-asm_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/crc32c-pcl-intel-asm_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -72,6 +72,7 @@
 
 # unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
 
+.text
 ENTRY(crc_pcl)
 #define    bufp		%rdi
 #define    bufp_dw	%edi
@@ -216,15 +217,11 @@ LABEL crc_ %i
 	## 4) Combine three results:
 	################################################################
 
-	lea	(K_table-16)(%rip), bufp	# first entry is for idx 1
+	lea	(K_table-8)(%rip), bufp		# first entry is for idx 1
 	shlq    $3, %rax			# rax *= 8
-	subq    %rax, tmp			# tmp -= rax*8
-	shlq    $1, %rax
-	subq    %rax, tmp			# tmp -= rax*16
-						# (total tmp -= rax*24)
-	addq    %rax, bufp
-
-	movdqa  (bufp), %xmm0			# 2 consts: K1:K2
+	pmovzxdq (bufp,%rax), %xmm0		# 2 consts: K1:K2
+	leal	(%eax,%eax,2), %eax		# rax *= 3 (total *24)
+	subq    %rax, tmp			# tmp -= rax*24
 
 	movq    crc_init, %xmm1			# CRC for block 1
 	PCLMULQDQ 0x00,%xmm0,%xmm1		# Multiply by K2
@@ -238,9 +235,9 @@ LABEL crc_ %i
 	mov     crc2, crc_init
 	crc32   %rax, crc_init
 
-################################################################
-## 5) Check for end:
-################################################################
+	################################################################
+	## 5) Check for end:
+	################################################################
 
 LABEL crc_ 0
 	mov     tmp, len
@@ -331,136 +328,136 @@ ENDPROC(crc_pcl)
 
 	################################################################
 	## PCLMULQDQ tables
-	## Table is 128 entries x 2 quad words each
+	## Table is 128 entries x 2 words (8 bytes) each
 	################################################################
-.data
-.align 64
+.section	.rotata, "a", %progbits
+.align 8
 K_table:
-        .quad 0x14cd00bd6,0x105ec76f0
-        .quad 0x0ba4fc28e,0x14cd00bd6
-        .quad 0x1d82c63da,0x0f20c0dfe
-        .quad 0x09e4addf8,0x0ba4fc28e
-        .quad 0x039d3b296,0x1384aa63a
-        .quad 0x102f9b8a2,0x1d82c63da
-        .quad 0x14237f5e6,0x01c291d04
-        .quad 0x00d3b6092,0x09e4addf8
-        .quad 0x0c96cfdc0,0x0740eef02
-        .quad 0x18266e456,0x039d3b296
-        .quad 0x0daece73e,0x0083a6eec
-        .quad 0x0ab7aff2a,0x102f9b8a2
-        .quad 0x1248ea574,0x1c1733996
-        .quad 0x083348832,0x14237f5e6
-        .quad 0x12c743124,0x02ad91c30
-        .quad 0x0b9e02b86,0x00d3b6092
-        .quad 0x018b33a4e,0x06992cea2
-        .quad 0x1b331e26a,0x0c96cfdc0
-        .quad 0x17d35ba46,0x07e908048
-        .quad 0x1bf2e8b8a,0x18266e456
-        .quad 0x1a3e0968a,0x11ed1f9d8
-        .quad 0x0ce7f39f4,0x0daece73e
-        .quad 0x061d82e56,0x0f1d0f55e
-        .quad 0x0d270f1a2,0x0ab7aff2a
-        .quad 0x1c3f5f66c,0x0a87ab8a8
-        .quad 0x12ed0daac,0x1248ea574
-        .quad 0x065863b64,0x08462d800
-        .quad 0x11eef4f8e,0x083348832
-        .quad 0x1ee54f54c,0x071d111a8
-        .quad 0x0b3e32c28,0x12c743124
-        .quad 0x0064f7f26,0x0ffd852c6
-        .quad 0x0dd7e3b0c,0x0b9e02b86
-        .quad 0x0f285651c,0x0dcb17aa4
-        .quad 0x010746f3c,0x018b33a4e
-        .quad 0x1c24afea4,0x0f37c5aee
-        .quad 0x0271d9844,0x1b331e26a
-        .quad 0x08e766a0c,0x06051d5a2
-        .quad 0x093a5f730,0x17d35ba46
-        .quad 0x06cb08e5c,0x11d5ca20e
-        .quad 0x06b749fb2,0x1bf2e8b8a
-        .quad 0x1167f94f2,0x021f3d99c
-        .quad 0x0cec3662e,0x1a3e0968a
-        .quad 0x19329634a,0x08f158014
-        .quad 0x0e6fc4e6a,0x0ce7f39f4
-        .quad 0x08227bb8a,0x1a5e82106
-        .quad 0x0b0cd4768,0x061d82e56
-        .quad 0x13c2b89c4,0x188815ab2
-        .quad 0x0d7a4825c,0x0d270f1a2
-        .quad 0x10f5ff2ba,0x105405f3e
-        .quad 0x00167d312,0x1c3f5f66c
-        .quad 0x0f6076544,0x0e9adf796
-        .quad 0x026f6a60a,0x12ed0daac
-        .quad 0x1a2adb74e,0x096638b34
-        .quad 0x19d34af3a,0x065863b64
-        .quad 0x049c3cc9c,0x1e50585a0
-        .quad 0x068bce87a,0x11eef4f8e
-        .quad 0x1524fa6c6,0x19f1c69dc
-        .quad 0x16cba8aca,0x1ee54f54c
-        .quad 0x042d98888,0x12913343e
-        .quad 0x1329d9f7e,0x0b3e32c28
-        .quad 0x1b1c69528,0x088f25a3a
-        .quad 0x02178513a,0x0064f7f26
-        .quad 0x0e0ac139e,0x04e36f0b0
-        .quad 0x0170076fa,0x0dd7e3b0c
-        .quad 0x141a1a2e2,0x0bd6f81f8
-        .quad 0x16ad828b4,0x0f285651c
-        .quad 0x041d17b64,0x19425cbba
-        .quad 0x1fae1cc66,0x010746f3c
-        .quad 0x1a75b4b00,0x18db37e8a
-        .quad 0x0f872e54c,0x1c24afea4
-        .quad 0x01e41e9fc,0x04c144932
-        .quad 0x086d8e4d2,0x0271d9844
-        .quad 0x160f7af7a,0x052148f02
-        .quad 0x05bb8f1bc,0x08e766a0c
-        .quad 0x0a90fd27a,0x0a3c6f37a
-        .quad 0x0b3af077a,0x093a5f730
-        .quad 0x04984d782,0x1d22c238e
-        .quad 0x0ca6ef3ac,0x06cb08e5c
-        .quad 0x0234e0b26,0x063ded06a
-        .quad 0x1d88abd4a,0x06b749fb2
-        .quad 0x04597456a,0x04d56973c
-        .quad 0x0e9e28eb4,0x1167f94f2
-        .quad 0x07b3ff57a,0x19385bf2e
-        .quad 0x0c9c8b782,0x0cec3662e
-        .quad 0x13a9cba9e,0x0e417f38a
-        .quad 0x093e106a4,0x19329634a
-        .quad 0x167001a9c,0x14e727980
-        .quad 0x1ddffc5d4,0x0e6fc4e6a
-        .quad 0x00df04680,0x0d104b8fc
-        .quad 0x02342001e,0x08227bb8a
-        .quad 0x00a2a8d7e,0x05b397730
-        .quad 0x168763fa6,0x0b0cd4768
-        .quad 0x1ed5a407a,0x0e78eb416
-        .quad 0x0d2c3ed1a,0x13c2b89c4
-        .quad 0x0995a5724,0x1641378f0
-        .quad 0x19b1afbc4,0x0d7a4825c
-        .quad 0x109ffedc0,0x08d96551c
-        .quad 0x0f2271e60,0x10f5ff2ba
-        .quad 0x00b0bf8ca,0x00bf80dd2
-        .quad 0x123888b7a,0x00167d312
-        .quad 0x1e888f7dc,0x18dcddd1c
-        .quad 0x002ee03b2,0x0f6076544
-        .quad 0x183e8d8fe,0x06a45d2b2
-        .quad 0x133d7a042,0x026f6a60a
-        .quad 0x116b0f50c,0x1dd3e10e8
-        .quad 0x05fabe670,0x1a2adb74e
-        .quad 0x130004488,0x0de87806c
-        .quad 0x000bcf5f6,0x19d34af3a
-        .quad 0x18f0c7078,0x014338754
-        .quad 0x017f27698,0x049c3cc9c
-        .quad 0x058ca5f00,0x15e3e77ee
-        .quad 0x1af900c24,0x068bce87a
-        .quad 0x0b5cfca28,0x0dd07448e
-        .quad 0x0ded288f8,0x1524fa6c6
-        .quad 0x059f229bc,0x1d8048348
-        .quad 0x06d390dec,0x16cba8aca
-        .quad 0x037170390,0x0a3e3e02c
-        .quad 0x06353c1cc,0x042d98888
-        .quad 0x0c4584f5c,0x0d73c7bea
-        .quad 0x1f16a3418,0x1329d9f7e
-        .quad 0x0531377e2,0x185137662
-        .quad 0x1d8d9ca7c,0x1b1c69528
-        .quad 0x0b25b29f2,0x18a08b5bc
-        .quad 0x19fb2a8b0,0x02178513a
-        .quad 0x1a08fe6ac,0x1da758ae0
-        .quad 0x045cddf4e,0x0e0ac139e
-        .quad 0x1a91647f2,0x169cf9eb0
-        .quad 0x1a0f717c4,0x0170076fa
+	.long 0x493c7d27, 0x00000001
+	.long 0xba4fc28e, 0x493c7d27
+	.long 0xddc0152b, 0xf20c0dfe
+	.long 0x9e4addf8, 0xba4fc28e
+	.long 0x39d3b296, 0x3da6d0cb
+	.long 0x0715ce53, 0xddc0152b
+	.long 0x47db8317, 0x1c291d04
+	.long 0x0d3b6092, 0x9e4addf8
+	.long 0xc96cfdc0, 0x740eef02
+	.long 0x878a92a7, 0x39d3b296
+	.long 0xdaece73e, 0x083a6eec
+	.long 0xab7aff2a, 0x0715ce53
+	.long 0x2162d385, 0xc49f4f67
+	.long 0x83348832, 0x47db8317
+	.long 0x299847d5, 0x2ad91c30
+	.long 0xb9e02b86, 0x0d3b6092
+	.long 0x18b33a4e, 0x6992cea2
+	.long 0xb6dd949b, 0xc96cfdc0
+	.long 0x78d9ccb7, 0x7e908048
+	.long 0xbac2fd7b, 0x878a92a7
+	.long 0xa60ce07b, 0x1b3d8f29
+	.long 0xce7f39f4, 0xdaece73e
+	.long 0x61d82e56, 0xf1d0f55e
+	.long 0xd270f1a2, 0xab7aff2a
+	.long 0xc619809d, 0xa87ab8a8
+	.long 0x2b3cac5d, 0x2162d385
+	.long 0x65863b64, 0x8462d800
+	.long 0x1b03397f, 0x83348832
+	.long 0xebb883bd, 0x71d111a8
+	.long 0xb3e32c28, 0x299847d5
+	.long 0x064f7f26, 0xffd852c6
+	.long 0xdd7e3b0c, 0xb9e02b86
+	.long 0xf285651c, 0xdcb17aa4
+	.long 0x10746f3c, 0x18b33a4e
+	.long 0xc7a68855, 0xf37c5aee
+	.long 0x271d9844, 0xb6dd949b
+	.long 0x8e766a0c, 0x6051d5a2
+	.long 0x93a5f730, 0x78d9ccb7
+	.long 0x6cb08e5c, 0x18b0d4ff
+	.long 0x6b749fb2, 0xbac2fd7b
+	.long 0x1393e203, 0x21f3d99c
+	.long 0xcec3662e, 0xa60ce07b
+	.long 0x96c515bb, 0x8f158014
+	.long 0xe6fc4e6a, 0xce7f39f4
+	.long 0x8227bb8a, 0xa00457f7
+	.long 0xb0cd4768, 0x61d82e56
+	.long 0x39c7ff35, 0x8d6d2c43
+	.long 0xd7a4825c, 0xd270f1a2
+	.long 0x0ab3844b, 0x00ac29cf
+	.long 0x0167d312, 0xc619809d
+	.long 0xf6076544, 0xe9adf796
+	.long 0x26f6a60a, 0x2b3cac5d
+	.long 0xa741c1bf, 0x96638b34
+	.long 0x98d8d9cb, 0x65863b64
+	.long 0x49c3cc9c, 0xe0e9f351
+	.long 0x68bce87a, 0x1b03397f
+	.long 0x57a3d037, 0x9af01f2d
+	.long 0x6956fc3b, 0xebb883bd
+	.long 0x42d98888, 0x2cff42cf
+	.long 0x3771e98f, 0xb3e32c28
+	.long 0xb42ae3d9, 0x88f25a3a
+	.long 0x2178513a, 0x064f7f26
+	.long 0xe0ac139e, 0x4e36f0b0
+	.long 0x170076fa, 0xdd7e3b0c
+	.long 0x444dd413, 0xbd6f81f8
+	.long 0x6f345e45, 0xf285651c
+	.long 0x41d17b64, 0x91c9bd4b
+	.long 0xff0dba97, 0x10746f3c
+	.long 0xa2b73df1, 0x885f087b
+	.long 0xf872e54c, 0xc7a68855
+	.long 0x1e41e9fc, 0x4c144932
+	.long 0x86d8e4d2, 0x271d9844
+	.long 0x651bd98b, 0x52148f02
+	.long 0x5bb8f1bc, 0x8e766a0c
+	.long 0xa90fd27a, 0xa3c6f37a
+	.long 0xb3af077a, 0x93a5f730
+	.long 0x4984d782, 0xd7c0557f
+	.long 0xca6ef3ac, 0x6cb08e5c
+	.long 0x234e0b26, 0x63ded06a
+	.long 0xdd66cbbb, 0x6b749fb2
+	.long 0x4597456a, 0x4d56973c
+	.long 0xe9e28eb4, 0x1393e203
+	.long 0x7b3ff57a, 0x9669c9df
+	.long 0xc9c8b782, 0xcec3662e
+	.long 0x3f70cc6f, 0xe417f38a
+	.long 0x93e106a4, 0x96c515bb
+	.long 0x62ec6c6d, 0x4b9e0f71
+	.long 0xd813b325, 0xe6fc4e6a
+	.long 0x0df04680, 0xd104b8fc
+	.long 0x2342001e, 0x8227bb8a
+	.long 0x0a2a8d7e, 0x5b397730
+	.long 0x6d9a4957, 0xb0cd4768
+	.long 0xe8b6368b, 0xe78eb416
+	.long 0xd2c3ed1a, 0x39c7ff35
+	.long 0x995a5724, 0x61ff0e01
+	.long 0x9ef68d35, 0xd7a4825c
+	.long 0x0c139b31, 0x8d96551c
+	.long 0xf2271e60, 0x0ab3844b
+	.long 0x0b0bf8ca, 0x0bf80dd2
+	.long 0x2664fd8b, 0x0167d312
+	.long 0xed64812d, 0x8821abed
+	.long 0x02ee03b2, 0xf6076544
+	.long 0x8604ae0f, 0x6a45d2b2
+	.long 0x363bd6b3, 0x26f6a60a
+	.long 0x135c83fd, 0xd8d26619
+	.long 0x5fabe670, 0xa741c1bf
+	.long 0x35ec3279, 0xde87806c
+	.long 0x00bcf5f6, 0x98d8d9cb
+	.long 0x8ae00689, 0x14338754
+	.long 0x17f27698, 0x49c3cc9c
+	.long 0x58ca5f00, 0x5bd2011f
+	.long 0xaa7c7ad5, 0x68bce87a
+	.long 0xb5cfca28, 0xdd07448e
+	.long 0xded288f8, 0x57a3d037
+	.long 0x59f229bc, 0xdde8f5b9
+	.long 0x6d390dec, 0x6956fc3b
+	.long 0x37170390, 0xa3e3e02c
+	.long 0x6353c1cc, 0x42d98888
+	.long 0xc4584f5c, 0xd73c7bea
+	.long 0xf48642e9, 0x3771e98f
+	.long 0x531377e2, 0x80ff0093
+	.long 0xdd35bc8d, 0xb42ae3d9
+	.long 0xb25b29f2, 0x8fe4c34d
+	.long 0x9a5ede41, 0x2178513a
+	.long 0xa563905d, 0xdf99fc11
+	.long 0x45cddf4e, 0xe0ac139e
+	.long 0xacfa3103, 0x6c23e841
+	.long 0xa51b6135, 0x170076fa
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/des3_ede-asm_64.S linux-libre-3.17-rc7-gnu/arch/x86/crypto/des3_ede-asm_64.S
--- linux-libre-3.16-gnu/arch/x86/crypto/des3_ede-asm_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/des3_ede-asm_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,805 @@
+/*
+ * des3_ede-asm_64.S  -  x86-64 assembly implementation of 3DES cipher
+ *
+ * Copyright Â© 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+
+.file "des3_ede-asm_64.S"
+.text
+
+#define s1 .L_s1
+#define s2 ((s1) + (64*8))
+#define s3 ((s2) + (64*8))
+#define s4 ((s3) + (64*8))
+#define s5 ((s4) + (64*8))
+#define s6 ((s5) + (64*8))
+#define s7 ((s6) + (64*8))
+#define s8 ((s7) + (64*8))
+
+/* register macros */
+#define CTX %rdi
+
+#define RL0 %r8
+#define RL1 %r9
+#define RL2 %r10
+
+#define RL0d %r8d
+#define RL1d %r9d
+#define RL2d %r10d
+
+#define RR0 %r11
+#define RR1 %r12
+#define RR2 %r13
+
+#define RR0d %r11d
+#define RR1d %r12d
+#define RR2d %r13d
+
+#define RW0 %rax
+#define RW1 %rbx
+#define RW2 %rcx
+
+#define RW0d %eax
+#define RW1d %ebx
+#define RW2d %ecx
+
+#define RW0bl %al
+#define RW1bl %bl
+#define RW2bl %cl
+
+#define RW0bh %ah
+#define RW1bh %bh
+#define RW2bh %ch
+
+#define RT0 %r15
+#define RT1 %rbp
+#define RT2 %r14
+#define RT3 %rdx
+
+#define RT0d %r15d
+#define RT1d %ebp
+#define RT2d %r14d
+#define RT3d %edx
+
+/***********************************************************************
+ * 1-way 3DES
+ ***********************************************************************/
+#define do_permutation(a, b, offset, mask) \
+	movl a, RT0d; \
+	shrl $(offset), RT0d; \
+	xorl b, RT0d; \
+	andl $(mask), RT0d; \
+	xorl RT0d, b; \
+	shll $(offset), RT0d; \
+	xorl RT0d, a;
+
+#define expand_to_64bits(val, mask) \
+	movl val##d, RT0d; \
+	rorl $4, RT0d; \
+	shlq $32, RT0; \
+	orq RT0, val; \
+	andq mask, val;
+
+#define compress_to_64bits(val) \
+	movq val, RT0; \
+	shrq $32, RT0; \
+	roll $4, RT0d; \
+	orl RT0d, val##d;
+
+#define initial_permutation(left, right) \
+	do_permutation(left##d, right##d,  4, 0x0f0f0f0f); \
+	do_permutation(left##d, right##d, 16, 0x0000ffff); \
+	do_permutation(right##d, left##d,  2, 0x33333333); \
+	do_permutation(right##d, left##d,  8, 0x00ff00ff); \
+	movabs $0x3f3f3f3f3f3f3f3f, RT3; \
+	movl left##d, RW0d; \
+	roll $1, right##d; \
+	xorl right##d, RW0d; \
+	andl $0xaaaaaaaa, RW0d; \
+	xorl RW0d, left##d; \
+	xorl RW0d, right##d; \
+	roll $1, left##d; \
+	expand_to_64bits(right, RT3); \
+	expand_to_64bits(left, RT3);
+
+#define final_permutation(left, right) \
+	compress_to_64bits(right); \
+	compress_to_64bits(left); \
+	movl right##d, RW0d; \
+	rorl $1, left##d; \
+	xorl left##d, RW0d; \
+	andl $0xaaaaaaaa, RW0d; \
+	xorl RW0d, right##d; \
+	xorl RW0d, left##d; \
+	rorl $1, right##d; \
+	do_permutation(right##d, left##d,  8, 0x00ff00ff); \
+	do_permutation(right##d, left##d,  2, 0x33333333); \
+	do_permutation(left##d, right##d, 16, 0x0000ffff); \
+	do_permutation(left##d, right##d,  4, 0x0f0f0f0f);
+
+#define round1(n, from, to, load_next_key) \
+	xorq from, RW0; \
+	\
+	movzbl RW0bl, RT0d; \
+	movzbl RW0bh, RT1d; \
+	shrq $16, RW0; \
+	movzbl RW0bl, RT2d; \
+	movzbl RW0bh, RT3d; \
+	shrq $16, RW0; \
+	movq s8(, RT0, 8), RT0; \
+	xorq s6(, RT1, 8), to; \
+	movzbl RW0bl, RL1d; \
+	movzbl RW0bh, RT1d; \
+	shrl $16, RW0d; \
+	xorq s4(, RT2, 8), RT0; \
+	xorq s2(, RT3, 8), to; \
+	movzbl RW0bl, RT2d; \
+	movzbl RW0bh, RT3d; \
+	xorq s7(, RL1, 8), RT0; \
+	xorq s5(, RT1, 8), to; \
+	xorq s3(, RT2, 8), RT0; \
+	load_next_key(n, RW0); \
+	xorq RT0, to; \
+	xorq s1(, RT3, 8), to; \
+
+#define load_next_key(n, RWx) \
+	movq (((n) + 1) * 8)(CTX), RWx;
+
+#define dummy2(a, b) /*_*/
+
+#define read_block(io, left, right) \
+	movl    (io), left##d; \
+	movl   4(io), right##d; \
+	bswapl left##d; \
+	bswapl right##d;
+
+#define write_block(io, left, right) \
+	bswapl left##d; \
+	bswapl right##d; \
+	movl   left##d,   (io); \
+	movl   right##d, 4(io);
+
+ENTRY(des3_ede_x86_64_crypt_blk)
+	/* input:
+	 *	%rdi: round keys, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	pushq %r12;
+	pushq %r13;
+	pushq %r14;
+	pushq %r15;
+
+	read_block(%rdx, RL0, RR0);
+	initial_permutation(RL0, RR0);
+
+	movq (CTX), RW0;
+
+	round1(0, RR0, RL0, load_next_key);
+	round1(1, RL0, RR0, load_next_key);
+	round1(2, RR0, RL0, load_next_key);
+	round1(3, RL0, RR0, load_next_key);
+	round1(4, RR0, RL0, load_next_key);
+	round1(5, RL0, RR0, load_next_key);
+	round1(6, RR0, RL0, load_next_key);
+	round1(7, RL0, RR0, load_next_key);
+	round1(8, RR0, RL0, load_next_key);
+	round1(9, RL0, RR0, load_next_key);
+	round1(10, RR0, RL0, load_next_key);
+	round1(11, RL0, RR0, load_next_key);
+	round1(12, RR0, RL0, load_next_key);
+	round1(13, RL0, RR0, load_next_key);
+	round1(14, RR0, RL0, load_next_key);
+	round1(15, RL0, RR0, load_next_key);
+
+	round1(16+0, RL0, RR0, load_next_key);
+	round1(16+1, RR0, RL0, load_next_key);
+	round1(16+2, RL0, RR0, load_next_key);
+	round1(16+3, RR0, RL0, load_next_key);
+	round1(16+4, RL0, RR0, load_next_key);
+	round1(16+5, RR0, RL0, load_next_key);
+	round1(16+6, RL0, RR0, load_next_key);
+	round1(16+7, RR0, RL0, load_next_key);
+	round1(16+8, RL0, RR0, load_next_key);
+	round1(16+9, RR0, RL0, load_next_key);
+	round1(16+10, RL0, RR0, load_next_key);
+	round1(16+11, RR0, RL0, load_next_key);
+	round1(16+12, RL0, RR0, load_next_key);
+	round1(16+13, RR0, RL0, load_next_key);
+	round1(16+14, RL0, RR0, load_next_key);
+	round1(16+15, RR0, RL0, load_next_key);
+
+	round1(32+0, RR0, RL0, load_next_key);
+	round1(32+1, RL0, RR0, load_next_key);
+	round1(32+2, RR0, RL0, load_next_key);
+	round1(32+3, RL0, RR0, load_next_key);
+	round1(32+4, RR0, RL0, load_next_key);
+	round1(32+5, RL0, RR0, load_next_key);
+	round1(32+6, RR0, RL0, load_next_key);
+	round1(32+7, RL0, RR0, load_next_key);
+	round1(32+8, RR0, RL0, load_next_key);
+	round1(32+9, RL0, RR0, load_next_key);
+	round1(32+10, RR0, RL0, load_next_key);
+	round1(32+11, RL0, RR0, load_next_key);
+	round1(32+12, RR0, RL0, load_next_key);
+	round1(32+13, RL0, RR0, load_next_key);
+	round1(32+14, RR0, RL0, load_next_key);
+	round1(32+15, RL0, RR0, dummy2);
+
+	final_permutation(RR0, RL0);
+	write_block(%rsi, RR0, RL0);
+
+	popq %r15;
+	popq %r14;
+	popq %r13;
+	popq %r12;
+	popq %rbx;
+	popq %rbp;
+
+	ret;
+ENDPROC(des3_ede_x86_64_crypt_blk)
+
+/***********************************************************************
+ * 3-way 3DES
+ ***********************************************************************/
+#define expand_to_64bits(val, mask) \
+	movl val##d, RT0d; \
+	rorl $4, RT0d; \
+	shlq $32, RT0; \
+	orq RT0, val; \
+	andq mask, val;
+
+#define compress_to_64bits(val) \
+	movq val, RT0; \
+	shrq $32, RT0; \
+	roll $4, RT0d; \
+	orl RT0d, val##d;
+
+#define initial_permutation3(left, right) \
+	do_permutation(left##0d, right##0d,  4, 0x0f0f0f0f); \
+	do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
+	  do_permutation(left##1d, right##1d,  4, 0x0f0f0f0f); \
+	  do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
+	    do_permutation(left##2d, right##2d,  4, 0x0f0f0f0f); \
+	    do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
+	    \
+	do_permutation(right##0d, left##0d,  2, 0x33333333); \
+	do_permutation(right##0d, left##0d,  8, 0x00ff00ff); \
+	  do_permutation(right##1d, left##1d,  2, 0x33333333); \
+	  do_permutation(right##1d, left##1d,  8, 0x00ff00ff); \
+	    do_permutation(right##2d, left##2d,  2, 0x33333333); \
+	    do_permutation(right##2d, left##2d,  8, 0x00ff00ff); \
+	    \
+	movabs $0x3f3f3f3f3f3f3f3f, RT3; \
+	    \
+	movl left##0d, RW0d; \
+	roll $1, right##0d; \
+	xorl right##0d, RW0d; \
+	andl $0xaaaaaaaa, RW0d; \
+	xorl RW0d, left##0d; \
+	xorl RW0d, right##0d; \
+	roll $1, left##0d; \
+	expand_to_64bits(right##0, RT3); \
+	expand_to_64bits(left##0, RT3); \
+	  movl left##1d, RW1d; \
+	  roll $1, right##1d; \
+	  xorl right##1d, RW1d; \
+	  andl $0xaaaaaaaa, RW1d; \
+	  xorl RW1d, left##1d; \
+	  xorl RW1d, right##1d; \
+	  roll $1, left##1d; \
+	  expand_to_64bits(right##1, RT3); \
+	  expand_to_64bits(left##1, RT3); \
+	    movl left##2d, RW2d; \
+	    roll $1, right##2d; \
+	    xorl right##2d, RW2d; \
+	    andl $0xaaaaaaaa, RW2d; \
+	    xorl RW2d, left##2d; \
+	    xorl RW2d, right##2d; \
+	    roll $1, left##2d; \
+	    expand_to_64bits(right##2, RT3); \
+	    expand_to_64bits(left##2, RT3);
+
+#define final_permutation3(left, right) \
+	compress_to_64bits(right##0); \
+	compress_to_64bits(left##0); \
+	movl right##0d, RW0d; \
+	rorl $1, left##0d; \
+	xorl left##0d, RW0d; \
+	andl $0xaaaaaaaa, RW0d; \
+	xorl RW0d, right##0d; \
+	xorl RW0d, left##0d; \
+	rorl $1, right##0d; \
+	  compress_to_64bits(right##1); \
+	  compress_to_64bits(left##1); \
+	  movl right##1d, RW1d; \
+	  rorl $1, left##1d; \
+	  xorl left##1d, RW1d; \
+	  andl $0xaaaaaaaa, RW1d; \
+	  xorl RW1d, right##1d; \
+	  xorl RW1d, left##1d; \
+	  rorl $1, right##1d; \
+	    compress_to_64bits(right##2); \
+	    compress_to_64bits(left##2); \
+	    movl right##2d, RW2d; \
+	    rorl $1, left##2d; \
+	    xorl left##2d, RW2d; \
+	    andl $0xaaaaaaaa, RW2d; \
+	    xorl RW2d, right##2d; \
+	    xorl RW2d, left##2d; \
+	    rorl $1, right##2d; \
+	    \
+	do_permutation(right##0d, left##0d,  8, 0x00ff00ff); \
+	do_permutation(right##0d, left##0d,  2, 0x33333333); \
+	  do_permutation(right##1d, left##1d,  8, 0x00ff00ff); \
+	  do_permutation(right##1d, left##1d,  2, 0x33333333); \
+	    do_permutation(right##2d, left##2d,  8, 0x00ff00ff); \
+	    do_permutation(right##2d, left##2d,  2, 0x33333333); \
+	    \
+	do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
+	do_permutation(left##0d, right##0d,  4, 0x0f0f0f0f); \
+	  do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
+	  do_permutation(left##1d, right##1d,  4, 0x0f0f0f0f); \
+	    do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
+	    do_permutation(left##2d, right##2d,  4, 0x0f0f0f0f);
+
+#define round3(n, from, to, load_next_key, do_movq) \
+	xorq from##0, RW0; \
+	movzbl RW0bl, RT3d; \
+	movzbl RW0bh, RT1d; \
+	shrq $16, RW0; \
+	xorq s8(, RT3, 8), to##0; \
+	xorq s6(, RT1, 8), to##0; \
+	movzbl RW0bl, RT3d; \
+	movzbl RW0bh, RT1d; \
+	shrq $16, RW0; \
+	xorq s4(, RT3, 8), to##0; \
+	xorq s2(, RT1, 8), to##0; \
+	movzbl RW0bl, RT3d; \
+	movzbl RW0bh, RT1d; \
+	shrl $16, RW0d; \
+	xorq s7(, RT3, 8), to##0; \
+	xorq s5(, RT1, 8), to##0; \
+	movzbl RW0bl, RT3d; \
+	movzbl RW0bh, RT1d; \
+	load_next_key(n, RW0); \
+	xorq s3(, RT3, 8), to##0; \
+	xorq s1(, RT1, 8), to##0; \
+		xorq from##1, RW1; \
+		movzbl RW1bl, RT3d; \
+		movzbl RW1bh, RT1d; \
+		shrq $16, RW1; \
+		xorq s8(, RT3, 8), to##1; \
+		xorq s6(, RT1, 8), to##1; \
+		movzbl RW1bl, RT3d; \
+		movzbl RW1bh, RT1d; \
+		shrq $16, RW1; \
+		xorq s4(, RT3, 8), to##1; \
+		xorq s2(, RT1, 8), to##1; \
+		movzbl RW1bl, RT3d; \
+		movzbl RW1bh, RT1d; \
+		shrl $16, RW1d; \
+		xorq s7(, RT3, 8), to##1; \
+		xorq s5(, RT1, 8), to##1; \
+		movzbl RW1bl, RT3d; \
+		movzbl RW1bh, RT1d; \
+		do_movq(RW0, RW1); \
+		xorq s3(, RT3, 8), to##1; \
+		xorq s1(, RT1, 8), to##1; \
+			xorq from##2, RW2; \
+			movzbl RW2bl, RT3d; \
+			movzbl RW2bh, RT1d; \
+			shrq $16, RW2; \
+			xorq s8(, RT3, 8), to##2; \
+			xorq s6(, RT1, 8), to##2; \
+			movzbl RW2bl, RT3d; \
+			movzbl RW2bh, RT1d; \
+			shrq $16, RW2; \
+			xorq s4(, RT3, 8), to##2; \
+			xorq s2(, RT1, 8), to##2; \
+			movzbl RW2bl, RT3d; \
+			movzbl RW2bh, RT1d; \
+			shrl $16, RW2d; \
+			xorq s7(, RT3, 8), to##2; \
+			xorq s5(, RT1, 8), to##2; \
+			movzbl RW2bl, RT3d; \
+			movzbl RW2bh, RT1d; \
+			do_movq(RW0, RW2); \
+			xorq s3(, RT3, 8), to##2; \
+			xorq s1(, RT1, 8), to##2;
+
+#define __movq(src, dst) \
+	movq src, dst;
+
+ENTRY(des3_ede_x86_64_crypt_blk_3way)
+	/* input:
+	 *	%rdi: ctx, round keys
+	 *	%rsi: dst (3 blocks)
+	 *	%rdx: src (3 blocks)
+	 */
+
+	pushq %rbp;
+	pushq %rbx;
+	pushq %r12;
+	pushq %r13;
+	pushq %r14;
+	pushq %r15;
+
+	/* load input */
+	movl 0 * 4(%rdx), RL0d;
+	movl 1 * 4(%rdx), RR0d;
+	movl 2 * 4(%rdx), RL1d;
+	movl 3 * 4(%rdx), RR1d;
+	movl 4 * 4(%rdx), RL2d;
+	movl 5 * 4(%rdx), RR2d;
+
+	bswapl RL0d;
+	bswapl RR0d;
+	bswapl RL1d;
+	bswapl RR1d;
+	bswapl RL2d;
+	bswapl RR2d;
+
+	initial_permutation3(RL, RR);
+
+	movq 0(CTX), RW0;
+	movq RW0, RW1;
+	movq RW0, RW2;
+
+	round3(0, RR, RL, load_next_key, __movq);
+	round3(1, RL, RR, load_next_key, __movq);
+	round3(2, RR, RL, load_next_key, __movq);
+	round3(3, RL, RR, load_next_key, __movq);
+	round3(4, RR, RL, load_next_key, __movq);
+	round3(5, RL, RR, load_next_key, __movq);
+	round3(6, RR, RL, load_next_key, __movq);
+	round3(7, RL, RR, load_next_key, __movq);
+	round3(8, RR, RL, load_next_key, __movq);
+	round3(9, RL, RR, load_next_key, __movq);
+	round3(10, RR, RL, load_next_key, __movq);
+	round3(11, RL, RR, load_next_key, __movq);
+	round3(12, RR, RL, load_next_key, __movq);
+	round3(13, RL, RR, load_next_key, __movq);
+	round3(14, RR, RL, load_next_key, __movq);
+	round3(15, RL, RR, load_next_key, __movq);
+
+	round3(16+0, RL, RR, load_next_key, __movq);
+	round3(16+1, RR, RL, load_next_key, __movq);
+	round3(16+2, RL, RR, load_next_key, __movq);
+	round3(16+3, RR, RL, load_next_key, __movq);
+	round3(16+4, RL, RR, load_next_key, __movq);
+	round3(16+5, RR, RL, load_next_key, __movq);
+	round3(16+6, RL, RR, load_next_key, __movq);
+	round3(16+7, RR, RL, load_next_key, __movq);
+	round3(16+8, RL, RR, load_next_key, __movq);
+	round3(16+9, RR, RL, load_next_key, __movq);
+	round3(16+10, RL, RR, load_next_key, __movq);
+	round3(16+11, RR, RL, load_next_key, __movq);
+	round3(16+12, RL, RR, load_next_key, __movq);
+	round3(16+13, RR, RL, load_next_key, __movq);
+	round3(16+14, RL, RR, load_next_key, __movq);
+	round3(16+15, RR, RL, load_next_key, __movq);
+
+	round3(32+0, RR, RL, load_next_key, __movq);
+	round3(32+1, RL, RR, load_next_key, __movq);
+	round3(32+2, RR, RL, load_next_key, __movq);
+	round3(32+3, RL, RR, load_next_key, __movq);
+	round3(32+4, RR, RL, load_next_key, __movq);
+	round3(32+5, RL, RR, load_next_key, __movq);
+	round3(32+6, RR, RL, load_next_key, __movq);
+	round3(32+7, RL, RR, load_next_key, __movq);
+	round3(32+8, RR, RL, load_next_key, __movq);
+	round3(32+9, RL, RR, load_next_key, __movq);
+	round3(32+10, RR, RL, load_next_key, __movq);
+	round3(32+11, RL, RR, load_next_key, __movq);
+	round3(32+12, RR, RL, load_next_key, __movq);
+	round3(32+13, RL, RR, load_next_key, __movq);
+	round3(32+14, RR, RL, load_next_key, __movq);
+	round3(32+15, RL, RR, dummy2, dummy2);
+
+	final_permutation3(RR, RL);
+
+	bswapl RR0d;
+	bswapl RL0d;
+	bswapl RR1d;
+	bswapl RL1d;
+	bswapl RR2d;
+	bswapl RL2d;
+
+	movl RR0d, 0 * 4(%rsi);
+	movl RL0d, 1 * 4(%rsi);
+	movl RR1d, 2 * 4(%rsi);
+	movl RL1d, 3 * 4(%rsi);
+	movl RR2d, 4 * 4(%rsi);
+	movl RL2d, 5 * 4(%rsi);
+
+	popq %r15;
+	popq %r14;
+	popq %r13;
+	popq %r12;
+	popq %rbx;
+	popq %rbp;
+
+	ret;
+ENDPROC(des3_ede_x86_64_crypt_blk_3way)
+
+.data
+.align 16
+.L_s1:
+	.quad 0x0010100001010400, 0x0000000000000000
+	.quad 0x0000100000010000, 0x0010100001010404
+	.quad 0x0010100001010004, 0x0000100000010404
+	.quad 0x0000000000000004, 0x0000100000010000
+	.quad 0x0000000000000400, 0x0010100001010400
+	.quad 0x0010100001010404, 0x0000000000000400
+	.quad 0x0010000001000404, 0x0010100001010004
+	.quad 0x0010000001000000, 0x0000000000000004
+	.quad 0x0000000000000404, 0x0010000001000400
+	.quad 0x0010000001000400, 0x0000100000010400
+	.quad 0x0000100000010400, 0x0010100001010000
+	.quad 0x0010100001010000, 0x0010000001000404
+	.quad 0x0000100000010004, 0x0010000001000004
+	.quad 0x0010000001000004, 0x0000100000010004
+	.quad 0x0000000000000000, 0x0000000000000404
+	.quad 0x0000100000010404, 0x0010000001000000
+	.quad 0x0000100000010000, 0x0010100001010404
+	.quad 0x0000000000000004, 0x0010100001010000
+	.quad 0x0010100001010400, 0x0010000001000000
+	.quad 0x0010000001000000, 0x0000000000000400
+	.quad 0x0010100001010004, 0x0000100000010000
+	.quad 0x0000100000010400, 0x0010000001000004
+	.quad 0x0000000000000400, 0x0000000000000004
+	.quad 0x0010000001000404, 0x0000100000010404
+	.quad 0x0010100001010404, 0x0000100000010004
+	.quad 0x0010100001010000, 0x0010000001000404
+	.quad 0x0010000001000004, 0x0000000000000404
+	.quad 0x0000100000010404, 0x0010100001010400
+	.quad 0x0000000000000404, 0x0010000001000400
+	.quad 0x0010000001000400, 0x0000000000000000
+	.quad 0x0000100000010004, 0x0000100000010400
+	.quad 0x0000000000000000, 0x0010100001010004
+.L_s2:
+	.quad 0x0801080200100020, 0x0800080000000000
+	.quad 0x0000080000000000, 0x0001080200100020
+	.quad 0x0001000000100000, 0x0000000200000020
+	.quad 0x0801000200100020, 0x0800080200000020
+	.quad 0x0800000200000020, 0x0801080200100020
+	.quad 0x0801080000100000, 0x0800000000000000
+	.quad 0x0800080000000000, 0x0001000000100000
+	.quad 0x0000000200000020, 0x0801000200100020
+	.quad 0x0001080000100000, 0x0001000200100020
+	.quad 0x0800080200000020, 0x0000000000000000
+	.quad 0x0800000000000000, 0x0000080000000000
+	.quad 0x0001080200100020, 0x0801000000100000
+	.quad 0x0001000200100020, 0x0800000200000020
+	.quad 0x0000000000000000, 0x0001080000100000
+	.quad 0x0000080200000020, 0x0801080000100000
+	.quad 0x0801000000100000, 0x0000080200000020
+	.quad 0x0000000000000000, 0x0001080200100020
+	.quad 0x0801000200100020, 0x0001000000100000
+	.quad 0x0800080200000020, 0x0801000000100000
+	.quad 0x0801080000100000, 0x0000080000000000
+	.quad 0x0801000000100000, 0x0800080000000000
+	.quad 0x0000000200000020, 0x0801080200100020
+	.quad 0x0001080200100020, 0x0000000200000020
+	.quad 0x0000080000000000, 0x0800000000000000
+	.quad 0x0000080200000020, 0x0801080000100000
+	.quad 0x0001000000100000, 0x0800000200000020
+	.quad 0x0001000200100020, 0x0800080200000020
+	.quad 0x0800000200000020, 0x0001000200100020
+	.quad 0x0001080000100000, 0x0000000000000000
+	.quad 0x0800080000000000, 0x0000080200000020
+	.quad 0x0800000000000000, 0x0801000200100020
+	.quad 0x0801080200100020, 0x0001080000100000
+.L_s3:
+	.quad 0x0000002000000208, 0x0000202008020200
+	.quad 0x0000000000000000, 0x0000200008020008
+	.quad 0x0000002008000200, 0x0000000000000000
+	.quad 0x0000202000020208, 0x0000002008000200
+	.quad 0x0000200000020008, 0x0000000008000008
+	.quad 0x0000000008000008, 0x0000200000020000
+	.quad 0x0000202008020208, 0x0000200000020008
+	.quad 0x0000200008020000, 0x0000002000000208
+	.quad 0x0000000008000000, 0x0000000000000008
+	.quad 0x0000202008020200, 0x0000002000000200
+	.quad 0x0000202000020200, 0x0000200008020000
+	.quad 0x0000200008020008, 0x0000202000020208
+	.quad 0x0000002008000208, 0x0000202000020200
+	.quad 0x0000200000020000, 0x0000002008000208
+	.quad 0x0000000000000008, 0x0000202008020208
+	.quad 0x0000002000000200, 0x0000000008000000
+	.quad 0x0000202008020200, 0x0000000008000000
+	.quad 0x0000200000020008, 0x0000002000000208
+	.quad 0x0000200000020000, 0x0000202008020200
+	.quad 0x0000002008000200, 0x0000000000000000
+	.quad 0x0000002000000200, 0x0000200000020008
+	.quad 0x0000202008020208, 0x0000002008000200
+	.quad 0x0000000008000008, 0x0000002000000200
+	.quad 0x0000000000000000, 0x0000200008020008
+	.quad 0x0000002008000208, 0x0000200000020000
+	.quad 0x0000000008000000, 0x0000202008020208
+	.quad 0x0000000000000008, 0x0000202000020208
+	.quad 0x0000202000020200, 0x0000000008000008
+	.quad 0x0000200008020000, 0x0000002008000208
+	.quad 0x0000002000000208, 0x0000200008020000
+	.quad 0x0000202000020208, 0x0000000000000008
+	.quad 0x0000200008020008, 0x0000202000020200
+.L_s4:
+	.quad 0x1008020000002001, 0x1000020800002001
+	.quad 0x1000020800002001, 0x0000000800000000
+	.quad 0x0008020800002000, 0x1008000800000001
+	.quad 0x1008000000000001, 0x1000020000002001
+	.quad 0x0000000000000000, 0x0008020000002000
+	.quad 0x0008020000002000, 0x1008020800002001
+	.quad 0x1000000800000001, 0x0000000000000000
+	.quad 0x0008000800000000, 0x1008000000000001
+	.quad 0x1000000000000001, 0x0000020000002000
+	.quad 0x0008000000000000, 0x1008020000002001
+	.quad 0x0000000800000000, 0x0008000000000000
+	.quad 0x1000020000002001, 0x0000020800002000
+	.quad 0x1008000800000001, 0x1000000000000001
+	.quad 0x0000020800002000, 0x0008000800000000
+	.quad 0x0000020000002000, 0x0008020800002000
+	.quad 0x1008020800002001, 0x1000000800000001
+	.quad 0x0008000800000000, 0x1008000000000001
+	.quad 0x0008020000002000, 0x1008020800002001
+	.quad 0x1000000800000001, 0x0000000000000000
+	.quad 0x0000000000000000, 0x0008020000002000
+	.quad 0x0000020800002000, 0x0008000800000000
+	.quad 0x1008000800000001, 0x1000000000000001
+	.quad 0x1008020000002001, 0x1000020800002001
+	.quad 0x1000020800002001, 0x0000000800000000
+	.quad 0x1008020800002001, 0x1000000800000001
+	.quad 0x1000000000000001, 0x0000020000002000
+	.quad 0x1008000000000001, 0x1000020000002001
+	.quad 0x0008020800002000, 0x1008000800000001
+	.quad 0x1000020000002001, 0x0000020800002000
+	.quad 0x0008000000000000, 0x1008020000002001
+	.quad 0x0000000800000000, 0x0008000000000000
+	.quad 0x0000020000002000, 0x0008020800002000
+.L_s5:
+	.quad 0x0000001000000100, 0x0020001002080100
+	.quad 0x0020000002080000, 0x0420001002000100
+	.quad 0x0000000000080000, 0x0000001000000100
+	.quad 0x0400000000000000, 0x0020000002080000
+	.quad 0x0400001000080100, 0x0000000000080000
+	.quad 0x0020001002000100, 0x0400001000080100
+	.quad 0x0420001002000100, 0x0420000002080000
+	.quad 0x0000001000080100, 0x0400000000000000
+	.quad 0x0020000002000000, 0x0400000000080000
+	.quad 0x0400000000080000, 0x0000000000000000
+	.quad 0x0400001000000100, 0x0420001002080100
+	.quad 0x0420001002080100, 0x0020001002000100
+	.quad 0x0420000002080000, 0x0400001000000100
+	.quad 0x0000000000000000, 0x0420000002000000
+	.quad 0x0020001002080100, 0x0020000002000000
+	.quad 0x0420000002000000, 0x0000001000080100
+	.quad 0x0000000000080000, 0x0420001002000100
+	.quad 0x0000001000000100, 0x0020000002000000
+	.quad 0x0400000000000000, 0x0020000002080000
+	.quad 0x0420001002000100, 0x0400001000080100
+	.quad 0x0020001002000100, 0x0400000000000000
+	.quad 0x0420000002080000, 0x0020001002080100
+	.quad 0x0400001000080100, 0x0000001000000100
+	.quad 0x0020000002000000, 0x0420000002080000
+	.quad 0x0420001002080100, 0x0000001000080100
+	.quad 0x0420000002000000, 0x0420001002080100
+	.quad 0x0020000002080000, 0x0000000000000000
+	.quad 0x0400000000080000, 0x0420000002000000
+	.quad 0x0000001000080100, 0x0020001002000100
+	.quad 0x0400001000000100, 0x0000000000080000
+	.quad 0x0000000000000000, 0x0400000000080000
+	.quad 0x0020001002080100, 0x0400001000000100
+.L_s6:
+	.quad 0x0200000120000010, 0x0204000020000000
+	.quad 0x0000040000000000, 0x0204040120000010
+	.quad 0x0204000020000000, 0x0000000100000010
+	.quad 0x0204040120000010, 0x0004000000000000
+	.quad 0x0200040020000000, 0x0004040100000010
+	.quad 0x0004000000000000, 0x0200000120000010
+	.quad 0x0004000100000010, 0x0200040020000000
+	.quad 0x0200000020000000, 0x0000040100000010
+	.quad 0x0000000000000000, 0x0004000100000010
+	.quad 0x0200040120000010, 0x0000040000000000
+	.quad 0x0004040000000000, 0x0200040120000010
+	.quad 0x0000000100000010, 0x0204000120000010
+	.quad 0x0204000120000010, 0x0000000000000000
+	.quad 0x0004040100000010, 0x0204040020000000
+	.quad 0x0000040100000010, 0x0004040000000000
+	.quad 0x0204040020000000, 0x0200000020000000
+	.quad 0x0200040020000000, 0x0000000100000010
+	.quad 0x0204000120000010, 0x0004040000000000
+	.quad 0x0204040120000010, 0x0004000000000000
+	.quad 0x0000040100000010, 0x0200000120000010
+	.quad 0x0004000000000000, 0x0200040020000000
+	.quad 0x0200000020000000, 0x0000040100000010
+	.quad 0x0200000120000010, 0x0204040120000010
+	.quad 0x0004040000000000, 0x0204000020000000
+	.quad 0x0004040100000010, 0x0204040020000000
+	.quad 0x0000000000000000, 0x0204000120000010
+	.quad 0x0000000100000010, 0x0000040000000000
+	.quad 0x0204000020000000, 0x0004040100000010
+	.quad 0x0000040000000000, 0x0004000100000010
+	.quad 0x0200040120000010, 0x0000000000000000
+	.quad 0x0204040020000000, 0x0200000020000000
+	.quad 0x0004000100000010, 0x0200040120000010
+.L_s7:
+	.quad 0x0002000000200000, 0x2002000004200002
+	.quad 0x2000000004000802, 0x0000000000000000
+	.quad 0x0000000000000800, 0x2000000004000802
+	.quad 0x2002000000200802, 0x0002000004200800
+	.quad 0x2002000004200802, 0x0002000000200000
+	.quad 0x0000000000000000, 0x2000000004000002
+	.quad 0x2000000000000002, 0x0000000004000000
+	.quad 0x2002000004200002, 0x2000000000000802
+	.quad 0x0000000004000800, 0x2002000000200802
+	.quad 0x2002000000200002, 0x0000000004000800
+	.quad 0x2000000004000002, 0x0002000004200000
+	.quad 0x0002000004200800, 0x2002000000200002
+	.quad 0x0002000004200000, 0x0000000000000800
+	.quad 0x2000000000000802, 0x2002000004200802
+	.quad 0x0002000000200800, 0x2000000000000002
+	.quad 0x0000000004000000, 0x0002000000200800
+	.quad 0x0000000004000000, 0x0002000000200800
+	.quad 0x0002000000200000, 0x2000000004000802
+	.quad 0x2000000004000802, 0x2002000004200002
+	.quad 0x2002000004200002, 0x2000000000000002
+	.quad 0x2002000000200002, 0x0000000004000000
+	.quad 0x0000000004000800, 0x0002000000200000
+	.quad 0x0002000004200800, 0x2000000000000802
+	.quad 0x2002000000200802, 0x0002000004200800
+	.quad 0x2000000000000802, 0x2000000004000002
+	.quad 0x2002000004200802, 0x0002000004200000
+	.quad 0x0002000000200800, 0x0000000000000000
+	.quad 0x2000000000000002, 0x2002000004200802
+	.quad 0x0000000000000000, 0x2002000000200802
+	.quad 0x0002000004200000, 0x0000000000000800
+	.quad 0x2000000004000002, 0x0000000004000800
+	.quad 0x0000000000000800, 0x2002000000200002
+.L_s8:
+	.quad 0x0100010410001000, 0x0000010000001000
+	.quad 0x0000000000040000, 0x0100010410041000
+	.quad 0x0100000010000000, 0x0100010410001000
+	.quad 0x0000000400000000, 0x0100000010000000
+	.quad 0x0000000400040000, 0x0100000010040000
+	.quad 0x0100010410041000, 0x0000010000041000
+	.quad 0x0100010010041000, 0x0000010400041000
+	.quad 0x0000010000001000, 0x0000000400000000
+	.quad 0x0100000010040000, 0x0100000410000000
+	.quad 0x0100010010001000, 0x0000010400001000
+	.quad 0x0000010000041000, 0x0000000400040000
+	.quad 0x0100000410040000, 0x0100010010041000
+	.quad 0x0000010400001000, 0x0000000000000000
+	.quad 0x0000000000000000, 0x0100000410040000
+	.quad 0x0100000410000000, 0x0100010010001000
+	.quad 0x0000010400041000, 0x0000000000040000
+	.quad 0x0000010400041000, 0x0000000000040000
+	.quad 0x0100010010041000, 0x0000010000001000
+	.quad 0x0000000400000000, 0x0100000410040000
+	.quad 0x0000010000001000, 0x0000010400041000
+	.quad 0x0100010010001000, 0x0000000400000000
+	.quad 0x0100000410000000, 0x0100000010040000
+	.quad 0x0100000410040000, 0x0100000010000000
+	.quad 0x0000000000040000, 0x0100010410001000
+	.quad 0x0000000000000000, 0x0100010410041000
+	.quad 0x0000000400040000, 0x0100000410000000
+	.quad 0x0100000010040000, 0x0100010010001000
+	.quad 0x0100010410001000, 0x0000000000000000
+	.quad 0x0100010410041000, 0x0000010000041000
+	.quad 0x0000010000041000, 0x0000010400001000
+	.quad 0x0000010400001000, 0x0000000400040000
+	.quad 0x0100000010000000, 0x0100010010041000
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/des3_ede_glue.c linux-libre-3.17-rc7-gnu/arch/x86/crypto/des3_ede_glue.c
--- linux-libre-3.16-gnu/arch/x86/crypto/des3_ede_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/des3_ede_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,509 @@
+/*
+ * Glue Code for assembler optimized version of 3DES
+ *
+ * Copyright Â© 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/processor.h>
+#include <crypto/des.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+struct des3_ede_x86_ctx {
+	u32 enc_expkey[DES3_EDE_EXPKEY_WORDS];
+	u32 dec_expkey[DES3_EDE_EXPKEY_WORDS];
+};
+
+/* regular block cipher functions */
+asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst,
+					  const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst,
+					       const u8 *src);
+
+static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
+				    const u8 *src)
+{
+	u32 *enc_ctx = ctx->enc_expkey;
+
+	des3_ede_x86_64_crypt_blk(enc_ctx, dst, src);
+}
+
+static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
+				    const u8 *src)
+{
+	u32 *dec_ctx = ctx->dec_expkey;
+
+	des3_ede_x86_64_crypt_blk(dec_ctx, dst, src);
+}
+
+static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	u32 *enc_ctx = ctx->enc_expkey;
+
+	des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src);
+}
+
+static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	u32 *dec_ctx = ctx->dec_expkey;
+
+	des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src);
+}
+
+static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     const u32 *expkey)
+{
+	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process four block batch */
+		if (nbytes >= bsize * 3) {
+			do {
+				des3_ede_x86_64_crypt_blk_3way(expkey, wdst,
+							       wsrc);
+
+				wsrc += bsize * 3;
+				wdst += bsize * 3;
+				nbytes -= bsize * 3;
+			} while (nbytes >= bsize * 3);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, ctx->enc_expkey);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, ctx->dec_expkey);
+}
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 *iv = (u64 *)walk->iv;
+
+	do {
+		*dst = *src ^ *iv;
+		des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	*(u64 *)walk->iv = *iv;
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ivs[3 - 1];
+	u64 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			nbytes -= bsize * 3 - bsize;
+			src -= 3 - 1;
+			dst -= 3 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+
+			des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+			dst[1] ^= ivs[0];
+			dst[2] ^= ivs[1];
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			*dst ^= *(src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 3);
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		*dst ^= *(src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	*dst ^= *(u64 *)walk->iv;
+	*(u64 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static void ctr_crypt_final(struct des3_ede_x86_ctx *ctx,
+			    struct blkcipher_walk *walk)
+{
+	u8 *ctrblk = walk->iv;
+	u8 keystream[DES3_EDE_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	des3_ede_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, DES3_EDE_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	__be64 *src = (__be64 *)walk->src.virt.addr;
+	__be64 *dst = (__be64 *)walk->dst.virt.addr;
+	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+	__be64 ctrblocks[3];
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			/* create ctrblks for parallel encrypt */
+			ctrblocks[0] = cpu_to_be64(ctrblk++);
+			ctrblocks[1] = cpu_to_be64(ctrblk++);
+			ctrblocks[2] = cpu_to_be64(ctrblk++);
+
+			des3_ede_enc_blk_3way(ctx, (u8 *)ctrblocks,
+					      (u8 *)ctrblocks);
+
+			dst[0] = src[0] ^ ctrblocks[0];
+			dst[1] = src[1] ^ ctrblocks[1];
+			dst[2] = src[2] ^ ctrblocks[2];
+
+			src += 3;
+			dst += 3;
+		} while ((nbytes -= bsize * 3) >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+		des3_ede_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+
+		dst[0] = src[0] ^ ctrblocks[0];
+
+		src += 1;
+		dst += 1;
+	} while ((nbytes -= bsize) >= bsize);
+
+done:
+	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, DES3_EDE_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= DES3_EDE_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key,
+			       unsigned int keylen)
+{
+	struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 i, j, tmp;
+	int err;
+
+	/* Generate encryption context using generic implementation. */
+	err = __des3_ede_setkey(ctx->enc_expkey, &tfm->crt_flags, key, keylen);
+	if (err < 0)
+		return err;
+
+	/* Fix encryption context for this implementation and form decryption
+	 * context. */
+	j = DES3_EDE_EXPKEY_WORDS - 2;
+	for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) {
+		tmp = ror32(ctx->enc_expkey[i + 1], 4);
+		ctx->enc_expkey[i + 1] = tmp;
+
+		ctx->dec_expkey[j + 0] = ctx->enc_expkey[i + 0];
+		ctx->dec_expkey[j + 1] = tmp;
+	}
+
+	return 0;
+}
+
+static struct crypto_alg des3_ede_algs[4] = { {
+	.cra_name		= "des3_ede",
+	.cra_driver_name	= "des3_ede-asm",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
+	.cra_alignmask		= 0,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.cipher = {
+			.cia_min_keysize	= DES3_EDE_KEY_SIZE,
+			.cia_max_keysize	= DES3_EDE_KEY_SIZE,
+			.cia_setkey		= des3_ede_x86_setkey,
+			.cia_encrypt		= des3_ede_x86_encrypt,
+			.cia_decrypt		= des3_ede_x86_decrypt,
+		}
+	}
+}, {
+	.cra_name		= "ecb(des3_ede)",
+	.cra_driver_name	= "ecb-des3_ede-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES3_EDE_KEY_SIZE,
+			.max_keysize	= DES3_EDE_KEY_SIZE,
+			.setkey		= des3_ede_x86_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(des3_ede)",
+	.cra_driver_name	= "cbc-des3_ede-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES3_EDE_KEY_SIZE,
+			.max_keysize	= DES3_EDE_KEY_SIZE,
+			.ivsize		= DES3_EDE_BLOCK_SIZE,
+			.setkey		= des3_ede_x86_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ctr(des3_ede)",
+	.cra_driver_name	= "ctr-des3_ede-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES3_EDE_KEY_SIZE,
+			.max_keysize	= DES3_EDE_KEY_SIZE,
+			.ivsize		= DES3_EDE_BLOCK_SIZE,
+			.setkey		= des3_ede_x86_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+} };
+
+static bool is_blacklisted_cpu(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return false;
+
+	if (boot_cpu_data.x86 == 0x0f) {
+		/*
+		 * On Pentium 4, des3_ede-x86_64 is slower than generic C
+		 * implementation because use of 64bit rotates (which are really
+		 * slow on P4). Therefore blacklist P4s.
+		 */
+		return true;
+	}
+
+	return false;
+}
+
+static int force;
+module_param(force, int, 0);
+MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
+
+static int __init des3_ede_x86_init(void)
+{
+	if (!force && is_blacklisted_cpu()) {
+		pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n");
+		return -ENODEV;
+	}
+
+	return crypto_register_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs));
+}
+
+static void __exit des3_ede_x86_fini(void)
+{
+	crypto_unregister_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs));
+}
+
+module_init(des3_ede_x86_init);
+module_exit(des3_ede_x86_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized");
+MODULE_ALIAS("des3_ede");
+MODULE_ALIAS("des3_ede-asm");
+MODULE_ALIAS("des");
+MODULE_ALIAS("des-asm");
+MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/crypto/Makefile linux-libre-3.17-rc7-gnu/arch/x86/crypto/Makefile
--- linux-libre-3.16-gnu/arch/x86/crypto/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/crypto/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@ obj-$(CONFIG_CRYPTO_SALSA20_586) += sals
 obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_DES3_EDE_X86_64) += des3_ede-x86_64.o
 obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
 obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
@@ -52,6 +53,7 @@ salsa20-i586-y := salsa20-i586-asm_32.o
 serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+des3_ede-x86_64-y := des3_ede-asm_64.o des3_ede_glue.o
 camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
 blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
@@ -76,7 +78,7 @@ ifeq ($(avx2_supported),yes)
 endif
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
-aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o
+aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o aes_ctrby8_avx-x86_64.o
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
 ifeq ($(avx2_supported),yes)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/acenv.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/acenv.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/acenv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/acenv.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,8 +18,6 @@
 
 #define ACPI_FLUSH_CPU_CACHE()	wbinvd()
 
-#ifdef CONFIG_ACPI
-
 int __acpi_acquire_global_lock(unsigned int *lock);
 int __acpi_release_global_lock(unsigned int *lock);
 
@@ -44,6 +42,4 @@ int __acpi_release_global_lock(unsigned
 	    : "=r"(n_hi), "=r"(n_lo)	\
 	    : "0"(n_hi), "1"(n_lo))
 
-#endif
-
 #endif /* _ASM_X86_ACENV_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/acpi.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/acpi.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/acpi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/acpi.h	2014-09-28 17:29:07.000000000 -0400
@@ -121,6 +121,11 @@ static inline void arch_acpi_set_pdc_bit
 		buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
 }
 
+static inline bool acpi_has_cpu_in_madt(void)
+{
+	return !!acpi_lapic;
+}
+
 #else /* !CONFIG_ACPI */
 
 #define acpi_lapic 0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/alternative.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/alternative.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/alternative.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/alternative.h	2014-09-28 17:29:07.000000000 -0400
@@ -161,6 +161,20 @@ static inline int alternatives_text_rese
 	asm volatile (ALTERNATIVE(oldinstr, newinstr, feature)		\
 		: : "i" (0), ## input)
 
+/*
+ * This is similar to alternative_input. But it has two features and
+ * respective instructions.
+ *
+ * If CPU has feature2, newinstr2 is used.
+ * Otherwise, if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+#define alternative_input_2(oldinstr, newinstr1, feature1, newinstr2,	     \
+			   feature2, input...)				     \
+	asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1,	     \
+		newinstr2, feature2)					     \
+		: : "i" (0), ## input)
+
 /* Like alternative_input, but with a single output argument */
 #define alternative_io(oldinstr, newinstr, feature, output, input...)	\
 	asm volatile (ALTERNATIVE(oldinstr, newinstr, feature)		\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/apic.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/apic.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/apic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/apic.h	2014-09-28 17:29:07.000000000 -0400
@@ -85,21 +85,13 @@ static inline bool apic_from_smp_config(
 #include <asm/paravirt.h>
 #endif
 
-#ifdef CONFIG_X86_64
-extern int is_vsmp_box(void);
-#else
-static inline int is_vsmp_box(void)
-{
-	return 0;
-}
-#endif
 extern int setup_profiling_timer(unsigned int);
 
 static inline void native_apic_mem_write(u32 reg, u32 v)
 {
 	volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
 
-	alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
+	alternative_io("movl %0, %1", "xchgl %0, %1", X86_BUG_11AP,
 		       ASM_OUTPUT2("=r" (v), "=m" (*addr)),
 		       ASM_OUTPUT2("0" (v), "m" (*addr)));
 }
@@ -300,7 +292,6 @@ struct apic {
 
 	int dest_logical;
 	unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
-	unsigned long (*check_apicid_present)(int apicid);
 
 	void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
 					 const struct cpumask *mask);
@@ -309,21 +300,11 @@ struct apic {
 	void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
 
 	void (*setup_apic_routing)(void);
-	int (*multi_timer_check)(int apic, int irq);
 	int (*cpu_present_to_apicid)(int mps_cpu);
 	void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
-	void (*setup_portio_remap)(void);
 	int (*check_phys_apicid_present)(int phys_apicid);
-	void (*enable_apic_mode)(void);
 	int (*phys_pkg_id)(int cpuid_apic, int index_msb);
 
-	/*
-	 * When one of the next two hooks returns 1 the apic
-	 * is switched to this. Essentially they are additional
-	 * probe functions:
-	 */
-	int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
-
 	unsigned int (*get_apic_id)(unsigned long x);
 	unsigned long (*set_apic_id)(unsigned int id);
 	unsigned long apic_id_mask;
@@ -343,11 +324,7 @@ struct apic {
 	/* wakeup_secondary_cpu */
 	int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
 
-	int trampoline_phys_low;
-	int trampoline_phys_high;
-
 	bool wait_for_init_deassert;
-	void (*smp_callin_clear_local_apic)(void);
 	void (*inquire_remote_apic)(int apicid);
 
 	/* apic ops */
@@ -378,14 +355,6 @@ struct apic {
 	 * won't be applied properly during early boot in this case.
 	 */
 	int (*x86_32_early_logical_apicid)(int cpu);
-
-	/*
-	 * Optional method called from setup_local_APIC() after logical
-	 * apicid is guaranteed to be known to initialize apicid -> node
-	 * mapping if NUMA initialization hasn't done so already.  Don't
-	 * add new users.
-	 */
-	int (*x86_32_numa_cpu_node)(int cpu);
 #endif
 };
 
@@ -496,14 +465,12 @@ static inline unsigned default_get_apic_
 }
 
 /*
- * Warm reset vector default position:
+ * Warm reset vector position:
  */
-#define DEFAULT_TRAMPOLINE_PHYS_LOW		0x467
-#define DEFAULT_TRAMPOLINE_PHYS_HIGH		0x469
+#define TRAMPOLINE_PHYS_LOW		0x467
+#define TRAMPOLINE_PHYS_HIGH		0x469
 
 #ifdef CONFIG_X86_64
-extern int default_acpi_madt_oem_check(char *, char *);
-
 extern void apic_send_IPI_self(int vector);
 
 DECLARE_PER_CPU(int, x2apic_extra_bits);
@@ -552,6 +519,8 @@ static inline int default_apic_id_valid(
 	return (apicid < 255);
 }
 
+extern int default_acpi_madt_oem_check(char *, char *);
+
 extern void default_setup_apic_routing(void);
 
 extern struct apic apic_noop;
@@ -635,11 +604,6 @@ static inline unsigned long default_chec
 	return physid_isset(apicid, *map);
 }
 
-static inline unsigned long default_check_apicid_present(int bit)
-{
-	return physid_isset(bit, phys_cpu_present_map);
-}
-
 static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
 {
 	*retmap = *phys_map;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/barrier.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/barrier.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/barrier.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/barrier.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@
 #if defined(CONFIG_X86_PPRO_FENCE)
 
 /*
- * For either of these options x86 doesn't have a strong TSO memory
+ * For this option x86 doesn't have a strong TSO memory
  * model and we should fall back to full barriers.
  */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/bitops.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/bitops.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/bitops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/bitops.h	2014-09-28 17:29:07.000000000 -0400
@@ -497,8 +497,6 @@ static __always_inline int fls64(__u64 x
 
 #include <asm-generic/bitops/sched.h>
 
-#define ARCH_HAS_FAST_MULTIPLIER 1
-
 #include <asm/arch_hweight.h>
 
 #include <asm-generic/bitops/const_hweight.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg_32.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg_32.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg_32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg_32.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,8 +34,6 @@ static inline void set_64bit(volatile u6
 		     : "memory");
 }
 
-#define __HAVE_ARCH_CMPXCHG 1
-
 #ifdef CONFIG_X86_CMPXCHG64
 #define cmpxchg64(ptr, o, n)						\
 	((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg_64.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg_64.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -6,8 +6,6 @@ static inline void set_64bit(volatile u6
 	*ptr = val;
 }
 
-#define __HAVE_ARCH_CMPXCHG 1
-
 #define cmpxchg64(ptr, o, n)						\
 ({									\
 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/cmpxchg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cmpxchg.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,8 @@
 #include <linux/compiler.h>
 #include <asm/alternative.h> /* Provides LOCK_PREFIX */
 
+#define __HAVE_ARCH_CMPXCHG 1
+
 /*
  * Non-existant functions to indicate usage errors at link time
  * (or compile-time if the compiler implements __compiletime_error().
@@ -143,7 +145,6 @@ extern void __add_wrong_size(void)
 # include <asm/cmpxchg_64.h>
 #endif
 
-#ifdef __HAVE_ARCH_CMPXCHG
 #define cmpxchg(ptr, old, new)						\
 	__cmpxchg(ptr, old, new, sizeof(*(ptr)))
 
@@ -152,7 +153,6 @@ extern void __add_wrong_size(void)
 
 #define cmpxchg_local(ptr, old, new)					\
 	__cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
-#endif
 
 /*
  * xadd() adds "inc" to "*ptr" and atomically returns the previous
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/cpufeature.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/cpufeature.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/cpufeature.h	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,7 @@
 #include <asm/required-features.h>
 #endif
 
-#define NCAPINTS	10	/* N 32-bit words worth of info */
+#define NCAPINTS	11	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -18,213 +18,218 @@
  */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
-#define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME		(0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE		(0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE		(0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers */
-#define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Exception */
-#define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR	(0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE		(0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA		(0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV	(0*32+15) /* CMOV instructions */
+#define X86_FEATURE_FPU		( 0*32+ 0) /* Onboard FPU */
+#define X86_FEATURE_VME		( 0*32+ 1) /* Virtual Mode Extensions */
+#define X86_FEATURE_DE		( 0*32+ 2) /* Debugging Extensions */
+#define X86_FEATURE_PSE		( 0*32+ 3) /* Page Size Extensions */
+#define X86_FEATURE_TSC		( 0*32+ 4) /* Time Stamp Counter */
+#define X86_FEATURE_MSR		( 0*32+ 5) /* Model-Specific Registers */
+#define X86_FEATURE_PAE		( 0*32+ 6) /* Physical Address Extensions */
+#define X86_FEATURE_MCE		( 0*32+ 7) /* Machine Check Exception */
+#define X86_FEATURE_CX8		( 0*32+ 8) /* CMPXCHG8 instruction */
+#define X86_FEATURE_APIC	( 0*32+ 9) /* Onboard APIC */
+#define X86_FEATURE_SEP		( 0*32+11) /* SYSENTER/SYSEXIT */
+#define X86_FEATURE_MTRR	( 0*32+12) /* Memory Type Range Registers */
+#define X86_FEATURE_PGE		( 0*32+13) /* Page Global Enable */
+#define X86_FEATURE_MCA		( 0*32+14) /* Machine Check Architecture */
+#define X86_FEATURE_CMOV	( 0*32+15) /* CMOV instructions */
 					  /* (plus FCMOVcc, FCOMI with FPU) */
-#define X86_FEATURE_PAT		(0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36	(0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN		(0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLUSH	(0*32+19) /* CLFLUSH instruction */
-#define X86_FEATURE_DS		(0*32+21) /* "dts" Debug Store */
-#define X86_FEATURE_ACPI	(0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX		(0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR	(0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
-#define X86_FEATURE_XMM		(0*32+25) /* "sse" */
-#define X86_FEATURE_XMM2	(0*32+26) /* "sse2" */
-#define X86_FEATURE_SELFSNOOP	(0*32+27) /* "ss" CPU self snoop */
-#define X86_FEATURE_HT		(0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC		(0*32+29) /* "tm" Automatic clock control */
-#define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
-#define X86_FEATURE_PBE		(0*32+31) /* Pending Break Enable */
+#define X86_FEATURE_PAT		( 0*32+16) /* Page Attribute Table */
+#define X86_FEATURE_PSE36	( 0*32+17) /* 36-bit PSEs */
+#define X86_FEATURE_PN		( 0*32+18) /* Processor serial number */
+#define X86_FEATURE_CLFLUSH	( 0*32+19) /* CLFLUSH instruction */
+#define X86_FEATURE_DS		( 0*32+21) /* "dts" Debug Store */
+#define X86_FEATURE_ACPI	( 0*32+22) /* ACPI via MSR */
+#define X86_FEATURE_MMX		( 0*32+23) /* Multimedia Extensions */
+#define X86_FEATURE_FXSR	( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
+#define X86_FEATURE_XMM		( 0*32+25) /* "sse" */
+#define X86_FEATURE_XMM2	( 0*32+26) /* "sse2" */
+#define X86_FEATURE_SELFSNOOP	( 0*32+27) /* "ss" CPU self snoop */
+#define X86_FEATURE_HT		( 0*32+28) /* Hyper-Threading */
+#define X86_FEATURE_ACC		( 0*32+29) /* "tm" Automatic clock control */
+#define X86_FEATURE_IA64	( 0*32+30) /* IA-64 processor */
+#define X86_FEATURE_PBE		( 0*32+31) /* Pending Break Enable */
 
 /* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
 /* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MP		(1*32+19) /* MP Capable. */
-#define X86_FEATURE_NX		(1*32+20) /* Execute Disable */
-#define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT	(1*32+25) /* FXSAVE/FXRSTOR optimizations */
-#define X86_FEATURE_GBPAGES	(1*32+26) /* "pdpe1gb" GB pages */
-#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW	(1*32+31) /* 3DNow! */
+#define X86_FEATURE_SYSCALL	( 1*32+11) /* SYSCALL/SYSRET */
+#define X86_FEATURE_MP		( 1*32+19) /* MP Capable. */
+#define X86_FEATURE_NX		( 1*32+20) /* Execute Disable */
+#define X86_FEATURE_MMXEXT	( 1*32+22) /* AMD MMX extensions */
+#define X86_FEATURE_FXSR_OPT	( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
+#define X86_FEATURE_GBPAGES	( 1*32+26) /* "pdpe1gb" GB pages */
+#define X86_FEATURE_RDTSCP	( 1*32+27) /* RDTSCP */
+#define X86_FEATURE_LM		( 1*32+29) /* Long Mode (x86-64) */
+#define X86_FEATURE_3DNOWEXT	( 1*32+30) /* AMD 3DNow! extensions */
+#define X86_FEATURE_3DNOW	( 1*32+31) /* 3DNow! */
 
 /* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY	(2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN	(2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI	(2*32+ 3) /* LongRun table interface */
+#define X86_FEATURE_RECOVERY	( 2*32+ 0) /* CPU in recovery mode */
+#define X86_FEATURE_LONGRUN	( 2*32+ 1) /* Longrun power control */
+#define X86_FEATURE_LRTI	( 2*32+ 3) /* LongRun table interface */
 
 /* Other features, Linux-defined mapping, word 3 */
 /* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX	(3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
+#define X86_FEATURE_CXMMX	( 3*32+ 0) /* Cyrix MMX extensions */
+#define X86_FEATURE_K6_MTRR	( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
+#define X86_FEATURE_CYRIX_ARR	( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
+#define X86_FEATURE_CENTAUR_MCR	( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
 /* cpu types for specific tunings: */
-#define X86_FEATURE_K8		(3*32+ 4) /* "" Opteron, Athlon64 */
-#define X86_FEATURE_K7		(3*32+ 5) /* "" Athlon */
-#define X86_FEATURE_P3		(3*32+ 6) /* "" P3 */
-#define X86_FEATURE_P4		(3*32+ 7) /* "" P4 */
-#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
-#define X86_FEATURE_UP		(3*32+ 9) /* smp kernel running on up */
-#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* "" FXSAVE leaks FOP/FIP/FOP */
-#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS	(3*32+12) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS		(3*32+13) /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32	(3*32+14) /* "" syscall in ia32 userspace */
-#define X86_FEATURE_SYSENTER32	(3*32+15) /* "" sysenter in ia32 userspace */
-#define X86_FEATURE_REP_GOOD	(3*32+16) /* rep microcode works well */
-#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* "" Mfence synchronizes RDTSC */
-#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* "" Lfence synchronizes RDTSC */
-#define X86_FEATURE_11AP	(3*32+19) /* "" Bad local APIC aka 11AP */
-#define X86_FEATURE_NOPL	(3*32+20) /* The NOPL (0F 1F) instructions */
-#define X86_FEATURE_ALWAYS	(3*32+21) /* "" Always-present feature */
-#define X86_FEATURE_XTOPOLOGY	(3*32+22) /* cpu topology enum extensions */
-#define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */
-#define X86_FEATURE_NONSTOP_TSC	(3*32+24) /* TSC does not stop in C states */
-#define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */
-#define X86_FEATURE_EXTD_APICID	(3*32+26) /* has extended APICID (8 bits) */
-#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_K8		( 3*32+ 4) /* "" Opteron, Athlon64 */
+#define X86_FEATURE_K7		( 3*32+ 5) /* "" Athlon */
+#define X86_FEATURE_P3		( 3*32+ 6) /* "" P3 */
+#define X86_FEATURE_P4		( 3*32+ 7) /* "" P4 */
+#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
+#define X86_FEATURE_UP		( 3*32+ 9) /* smp kernel running on up */
+/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */
+#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS	( 3*32+12) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS		( 3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_SYSCALL32	( 3*32+14) /* "" syscall in ia32 userspace */
+#define X86_FEATURE_SYSENTER32	( 3*32+15) /* "" sysenter in ia32 userspace */
+#define X86_FEATURE_REP_GOOD	( 3*32+16) /* rep microcode works well */
+#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */
+#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */
+/* free, was #define X86_FEATURE_11AP	( 3*32+19) * "" Bad local APIC aka 11AP */
+#define X86_FEATURE_NOPL	( 3*32+20) /* The NOPL (0F 1F) instructions */
+#define X86_FEATURE_ALWAYS	( 3*32+21) /* "" Always-present feature */
+#define X86_FEATURE_XTOPOLOGY	( 3*32+22) /* cpu topology enum extensions */
+#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
+#define X86_FEATURE_NONSTOP_TSC	( 3*32+24) /* TSC does not stop in C states */
+/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
+#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 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3	(4*32+ 0) /* "pni" SSE-3 */
-#define X86_FEATURE_PCLMULQDQ	(4*32+ 1) /* PCLMULQDQ instruction */
-#define X86_FEATURE_DTES64	(4*32+ 2) /* 64-bit Debug Store */
-#define X86_FEATURE_MWAIT	(4*32+ 3) /* "monitor" Monitor/Mwait support */
-#define X86_FEATURE_DSCPL	(4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
-#define X86_FEATURE_VMX		(4*32+ 5) /* Hardware virtualization */
-#define X86_FEATURE_SMX		(4*32+ 6) /* Safer mode */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_SSSE3	(4*32+ 9) /* Supplemental SSE-3 */
-#define X86_FEATURE_CID		(4*32+10) /* Context ID */
-#define X86_FEATURE_FMA		(4*32+12) /* Fused multiply-add */
-#define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
-#define X86_FEATURE_PDCM	(4*32+15) /* Performance Capabilities */
-#define X86_FEATURE_PCID	(4*32+17) /* Process Context Identifiers */
-#define X86_FEATURE_DCA		(4*32+18) /* Direct Cache Access */
-#define X86_FEATURE_XMM4_1	(4*32+19) /* "sse4_1" SSE-4.1 */
-#define X86_FEATURE_XMM4_2	(4*32+20) /* "sse4_2" SSE-4.2 */
-#define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
-#define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
-#define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
-#define X86_FEATURE_TSC_DEADLINE_TIMER	(4*32+24) /* Tsc deadline timer */
-#define X86_FEATURE_AES		(4*32+25) /* AES instructions */
-#define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
-#define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
-#define X86_FEATURE_AVX		(4*32+28) /* Advanced Vector Extensions */
-#define X86_FEATURE_F16C	(4*32+29) /* 16-bit fp conversions */
-#define X86_FEATURE_RDRAND	(4*32+30) /* The RDRAND instruction */
-#define X86_FEATURE_HYPERVISOR	(4*32+31) /* Running on a hypervisor */
+#define X86_FEATURE_XMM3	( 4*32+ 0) /* "pni" SSE-3 */
+#define X86_FEATURE_PCLMULQDQ	( 4*32+ 1) /* PCLMULQDQ instruction */
+#define X86_FEATURE_DTES64	( 4*32+ 2) /* 64-bit Debug Store */
+#define X86_FEATURE_MWAIT	( 4*32+ 3) /* "monitor" Monitor/Mwait support */
+#define X86_FEATURE_DSCPL	( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
+#define X86_FEATURE_VMX		( 4*32+ 5) /* Hardware virtualization */
+#define X86_FEATURE_SMX		( 4*32+ 6) /* Safer mode */
+#define X86_FEATURE_EST		( 4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2		( 4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_SSSE3	( 4*32+ 9) /* Supplemental SSE-3 */
+#define X86_FEATURE_CID		( 4*32+10) /* Context ID */
+#define X86_FEATURE_FMA		( 4*32+12) /* Fused multiply-add */
+#define X86_FEATURE_CX16	( 4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR	( 4*32+14) /* Send Task Priority Messages */
+#define X86_FEATURE_PDCM	( 4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID	( 4*32+17) /* Process Context Identifiers */
+#define X86_FEATURE_DCA		( 4*32+18) /* Direct Cache Access */
+#define X86_FEATURE_XMM4_1	( 4*32+19) /* "sse4_1" SSE-4.1 */
+#define X86_FEATURE_XMM4_2	( 4*32+20) /* "sse4_2" SSE-4.2 */
+#define X86_FEATURE_X2APIC	( 4*32+21) /* x2APIC */
+#define X86_FEATURE_MOVBE	( 4*32+22) /* MOVBE instruction */
+#define X86_FEATURE_POPCNT      ( 4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER	( 4*32+24) /* Tsc deadline timer */
+#define X86_FEATURE_AES		( 4*32+25) /* AES instructions */
+#define X86_FEATURE_XSAVE	( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
+#define X86_FEATURE_OSXSAVE	( 4*32+27) /* "" XSAVE enabled in the OS */
+#define X86_FEATURE_AVX		( 4*32+28) /* Advanced Vector Extensions */
+#define X86_FEATURE_F16C	( 4*32+29) /* 16-bit fp conversions */
+#define X86_FEATURE_RDRAND	( 4*32+30) /* The RDRAND instruction */
+#define X86_FEATURE_HYPERVISOR	( 4*32+31) /* Running on a hypervisor */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE	(5*32+ 2) /* "rng" RNG present (xstore) */
-#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* "rng_en" RNG enabled */
-#define X86_FEATURE_XCRYPT	(5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
-#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* "ace_en" on-CPU crypto enabled */
-#define X86_FEATURE_ACE2	(5*32+ 8) /* Advanced Cryptography Engine v2 */
-#define X86_FEATURE_ACE2_EN	(5*32+ 9) /* ACE v2 enabled */
-#define X86_FEATURE_PHE		(5*32+10) /* PadLock Hash Engine */
-#define X86_FEATURE_PHE_EN	(5*32+11) /* PHE enabled */
-#define X86_FEATURE_PMM		(5*32+12) /* PadLock Montgomery Multiplier */
-#define X86_FEATURE_PMM_EN	(5*32+13) /* PMM enabled */
+#define X86_FEATURE_XSTORE	( 5*32+ 2) /* "rng" RNG present (xstore) */
+#define X86_FEATURE_XSTORE_EN	( 5*32+ 3) /* "rng_en" RNG enabled */
+#define X86_FEATURE_XCRYPT	( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
+#define X86_FEATURE_XCRYPT_EN	( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
+#define X86_FEATURE_ACE2	( 5*32+ 8) /* Advanced Cryptography Engine v2 */
+#define X86_FEATURE_ACE2_EN	( 5*32+ 9) /* ACE v2 enabled */
+#define X86_FEATURE_PHE		( 5*32+10) /* PadLock Hash Engine */
+#define X86_FEATURE_PHE_EN	( 5*32+11) /* PHE enabled */
+#define X86_FEATURE_PMM		( 5*32+12) /* PadLock Montgomery Multiplier */
+#define X86_FEATURE_PMM_EN	( 5*32+13) /* PMM enabled */
 
 /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
-#define X86_FEATURE_SVM		(6*32+ 2) /* Secure virtual machine */
-#define X86_FEATURE_EXTAPIC	(6*32+ 3) /* Extended APIC space */
-#define X86_FEATURE_CR8_LEGACY	(6*32+ 4) /* CR8 in 32-bit mode */
-#define X86_FEATURE_ABM		(6*32+ 5) /* Advanced bit manipulation */
-#define X86_FEATURE_SSE4A	(6*32+ 6) /* SSE-4A */
-#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE mode */
-#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
-#define X86_FEATURE_OSVW	(6*32+ 9) /* OS Visible Workaround */
-#define X86_FEATURE_IBS		(6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_XOP		(6*32+11) /* extended AVX instructions */
-#define X86_FEATURE_SKINIT	(6*32+12) /* SKINIT/STGI instructions */
-#define X86_FEATURE_WDT		(6*32+13) /* Watchdog timer */
-#define X86_FEATURE_LWP		(6*32+15) /* Light Weight Profiling */
-#define X86_FEATURE_FMA4	(6*32+16) /* 4 operands MAC instructions */
-#define X86_FEATURE_TCE		(6*32+17) /* translation cache extension */
-#define X86_FEATURE_NODEID_MSR	(6*32+19) /* NodeId MSR */
-#define X86_FEATURE_TBM		(6*32+21) /* trailing bit manipulations */
-#define X86_FEATURE_TOPOEXT	(6*32+22) /* topology extensions CPUID leafs */
-#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
-#define X86_FEATURE_PERFCTR_NB  (6*32+24) /* NB performance counter extensions */
-#define X86_FEATURE_PERFCTR_L2	(6*32+28) /* L2 performance counter extensions */
+#define X86_FEATURE_LAHF_LM	( 6*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY	( 6*32+ 1) /* If yes HyperThreading not valid */
+#define X86_FEATURE_SVM		( 6*32+ 2) /* Secure virtual machine */
+#define X86_FEATURE_EXTAPIC	( 6*32+ 3) /* Extended APIC space */
+#define X86_FEATURE_CR8_LEGACY	( 6*32+ 4) /* CR8 in 32-bit mode */
+#define X86_FEATURE_ABM		( 6*32+ 5) /* Advanced bit manipulation */
+#define X86_FEATURE_SSE4A	( 6*32+ 6) /* SSE-4A */
+#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
+#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
+#define X86_FEATURE_OSVW	( 6*32+ 9) /* OS Visible Workaround */
+#define X86_FEATURE_IBS		( 6*32+10) /* Instruction Based Sampling */
+#define X86_FEATURE_XOP		( 6*32+11) /* extended AVX instructions */
+#define X86_FEATURE_SKINIT	( 6*32+12) /* SKINIT/STGI instructions */
+#define X86_FEATURE_WDT		( 6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP		( 6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4	( 6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE		( 6*32+17) /* translation cache extension */
+#define X86_FEATURE_NODEID_MSR	( 6*32+19) /* NodeId MSR */
+#define X86_FEATURE_TBM		( 6*32+21) /* trailing bit manipulations */
+#define X86_FEATURE_TOPOEXT	( 6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB  ( 6*32+24) /* NB performance counter extensions */
+#define X86_FEATURE_PERFCTR_L2	( 6*32+28) /* L2 performance counter extensions */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
  * CPUID levels like 0x6, 0xA etc, word 7
  */
-#define X86_FEATURE_IDA		(7*32+ 0) /* Intel Dynamic Acceleration */
-#define X86_FEATURE_ARAT	(7*32+ 1) /* Always Running APIC Timer */
-#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_XSAVEOPT	(7*32+ 4) /* Optimized Xsave */
-#define X86_FEATURE_PLN		(7*32+ 5) /* Intel Power Limit Notification */
-#define X86_FEATURE_PTS		(7*32+ 6) /* Intel Package Thermal Status */
-#define X86_FEATURE_DTHERM	(7*32+ 7) /* Digital Thermal Sensor */
-#define X86_FEATURE_HW_PSTATE	(7*32+ 8) /* AMD HW-PState */
-#define X86_FEATURE_PROC_FEEDBACK (7*32+ 9) /* AMD ProcFeedbackInterface */
+#define X86_FEATURE_IDA		( 7*32+ 0) /* Intel Dynamic Acceleration */
+#define X86_FEATURE_ARAT	( 7*32+ 1) /* Always Running APIC Timer */
+#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_PLN		( 7*32+ 5) /* Intel Power Limit Notification */
+#define X86_FEATURE_PTS		( 7*32+ 6) /* Intel Package Thermal Status */
+#define X86_FEATURE_DTHERM	( 7*32+ 7) /* Digital Thermal Sensor */
+#define X86_FEATURE_HW_PSTATE	( 7*32+ 8) /* AMD HW-PState */
+#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 
 /* Virtualization flags: Linux defined, word 8 */
-#define X86_FEATURE_TPR_SHADOW  (8*32+ 0) /* Intel TPR Shadow */
-#define X86_FEATURE_VNMI        (8*32+ 1) /* Intel Virtual NMI */
-#define X86_FEATURE_FLEXPRIORITY (8*32+ 2) /* Intel FlexPriority */
-#define X86_FEATURE_EPT         (8*32+ 3) /* Intel Extended Page Table */
-#define X86_FEATURE_VPID        (8*32+ 4) /* Intel Virtual Processor ID */
-#define X86_FEATURE_NPT		(8*32+ 5) /* AMD Nested Page Table support */
-#define X86_FEATURE_LBRV	(8*32+ 6) /* AMD LBR Virtualization support */
-#define X86_FEATURE_SVML	(8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
-#define X86_FEATURE_NRIPS	(8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
-#define X86_FEATURE_TSCRATEMSR  (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
-#define X86_FEATURE_VMCBCLEAN   (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
-#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */
-#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */
-#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */
-#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */
+#define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
+#define X86_FEATURE_VNMI        ( 8*32+ 1) /* Intel Virtual NMI */
+#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */
+#define X86_FEATURE_EPT         ( 8*32+ 3) /* Intel Extended Page Table */
+#define X86_FEATURE_VPID        ( 8*32+ 4) /* Intel Virtual Processor ID */
+#define X86_FEATURE_NPT		( 8*32+ 5) /* AMD Nested Page Table support */
+#define X86_FEATURE_LBRV	( 8*32+ 6) /* AMD LBR Virtualization support */
+#define X86_FEATURE_SVML	( 8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
+#define X86_FEATURE_NRIPS	( 8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR  ( 8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN   ( 8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID ( 8*32+11) /* AMD flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS ( 8*32+12) /* AMD Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */
 
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
-#define X86_FEATURE_FSGSBASE	(9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
-#define X86_FEATURE_TSC_ADJUST	(9*32+ 1) /* TSC adjustment MSR 0x3b */
-#define X86_FEATURE_BMI1	(9*32+ 3) /* 1st group bit manipulation extensions */
-#define X86_FEATURE_HLE		(9*32+ 4) /* Hardware Lock Elision */
-#define X86_FEATURE_AVX2	(9*32+ 5) /* AVX2 instructions */
-#define X86_FEATURE_SMEP	(9*32+ 7) /* Supervisor Mode Execution Protection */
-#define X86_FEATURE_BMI2	(9*32+ 8) /* 2nd group bit manipulation extensions */
-#define X86_FEATURE_ERMS	(9*32+ 9) /* Enhanced REP MOVSB/STOSB */
-#define X86_FEATURE_INVPCID	(9*32+10) /* Invalidate Processor Context ID */
-#define X86_FEATURE_RTM		(9*32+11) /* Restricted Transactional Memory */
-#define X86_FEATURE_MPX		(9*32+14) /* Memory Protection Extension */
-#define X86_FEATURE_AVX512F	(9*32+16) /* AVX-512 Foundation */
-#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_CLFLUSHOPT	(9*32+23) /* CLFLUSHOPT instruction */
-#define X86_FEATURE_AVX512PF	(9*32+26) /* AVX-512 Prefetch */
-#define X86_FEATURE_AVX512ER	(9*32+27) /* AVX-512 Exponential and Reciprocal */
-#define X86_FEATURE_AVX512CD	(9*32+28) /* AVX-512 Conflict Detection */
+#define X86_FEATURE_FSGSBASE	( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
+#define X86_FEATURE_TSC_ADJUST	( 9*32+ 1) /* TSC adjustment MSR 0x3b */
+#define X86_FEATURE_BMI1	( 9*32+ 3) /* 1st group bit manipulation extensions */
+#define X86_FEATURE_HLE		( 9*32+ 4) /* Hardware Lock Elision */
+#define X86_FEATURE_AVX2	( 9*32+ 5) /* AVX2 instructions */
+#define X86_FEATURE_SMEP	( 9*32+ 7) /* Supervisor Mode Execution Protection */
+#define X86_FEATURE_BMI2	( 9*32+ 8) /* 2nd group bit manipulation extensions */
+#define X86_FEATURE_ERMS	( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
+#define X86_FEATURE_INVPCID	( 9*32+10) /* Invalidate Processor Context ID */
+#define X86_FEATURE_RTM		( 9*32+11) /* Restricted Transactional Memory */
+#define X86_FEATURE_MPX		( 9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_AVX512F	( 9*32+16) /* AVX-512 Foundation */
+#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_CLFLUSHOPT	( 9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_AVX512PF	( 9*32+26) /* AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER	( 9*32+27) /* AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD	( 9*32+28) /* AVX-512 Conflict Detection */
+
+/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
+#define X86_FEATURE_XSAVEOPT	(10*32+ 0) /* XSAVEOPT */
+#define X86_FEATURE_XSAVEC	(10*32+ 1) /* XSAVEC */
+#define X86_FEATURE_XGETBV1	(10*32+ 2) /* XGETBV with ECX = 1 */
+#define X86_FEATURE_XSAVES	(10*32+ 3) /* XSAVES/XRSTORS */
 
 /*
  * BUG word(s)
@@ -234,8 +239,11 @@
 #define X86_BUG_F00F		X86_BUG(0) /* Intel F00F */
 #define X86_BUG_FDIV		X86_BUG(1) /* FPU FDIV */
 #define X86_BUG_COMA		X86_BUG(2) /* Cyrix 6x86 coma */
-#define X86_BUG_AMD_TLB_MMATCH	X86_BUG(3) /* AMD Erratum 383 */
-#define X86_BUG_AMD_APIC_C1E	X86_BUG(4) /* AMD Erratum 400 */
+#define X86_BUG_AMD_TLB_MMATCH	X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
+#define X86_BUG_AMD_APIC_C1E	X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
+#define X86_BUG_11AP		X86_BUG(5) /* Bad local APIC aka 11AP */
+#define X86_BUG_FXSAVE_LEAK	X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
+#define X86_BUG_CLFLUSH_MONITOR	X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
@@ -245,6 +253,12 @@
 extern const char * const x86_cap_flags[NCAPINTS*32];
 extern const char * const x86_power_flags[32];
 
+/*
+ * In order to save room, we index into this array by doing
+ * X86_BUG_<name> - NCAPINTS*32.
+ */
+extern const char * const x86_bug_flags[NBUGINTS*32];
+
 #define test_cpu_cap(c, bit)						\
 	 test_bit(bit, (unsigned long *)((c)->x86_capability))
 
@@ -301,7 +315,6 @@ extern const char * const x86_power_flag
 #define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX)
 #define cpu_has_avx2		boot_cpu_has(X86_FEATURE_AVX2)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
-#define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
 #define cpu_has_k6_mtrr		boot_cpu_has(X86_FEATURE_K6_MTRR)
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
@@ -328,6 +341,7 @@ extern const char * const x86_power_flag
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
 #define cpu_has_xsaveopt	boot_cpu_has(X86_FEATURE_XSAVEOPT)
+#define cpu_has_xsaves		boot_cpu_has(X86_FEATURE_XSAVES)
 #define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
@@ -347,9 +361,6 @@ extern const char * const x86_power_flag
 #undef  cpu_has_pae
 #define cpu_has_pae		___BUG___
 
-#undef  cpu_has_mp
-#define cpu_has_mp		1
-
 #undef  cpu_has_k6_mtrr
 #define cpu_has_k6_mtrr		0
 
@@ -539,20 +550,20 @@ static __always_inline __pure bool _stat
 #define static_cpu_has_safe(bit)	boot_cpu_has(bit)
 #endif
 
-#define cpu_has_bug(c, bit)	cpu_has(c, (bit))
-#define set_cpu_bug(c, bit)	set_cpu_cap(c, (bit))
-#define clear_cpu_bug(c, bit)	clear_cpu_cap(c, (bit));
+#define cpu_has_bug(c, bit)		cpu_has(c, (bit))
+#define set_cpu_bug(c, bit)		set_cpu_cap(c, (bit))
+#define clear_cpu_bug(c, bit)		clear_cpu_cap(c, (bit))
 
-#define static_cpu_has_bug(bit)	static_cpu_has((bit))
-#define boot_cpu_has_bug(bit)	cpu_has_bug(&boot_cpu_data, (bit))
+#define static_cpu_has_bug(bit)		static_cpu_has((bit))
+#define static_cpu_has_bug_safe(bit)	static_cpu_has_safe((bit))
+#define boot_cpu_has_bug(bit)		cpu_has_bug(&boot_cpu_data, (bit))
 
-#define MAX_CPU_FEATURES	(NCAPINTS * 32)
-#define cpu_have_feature	boot_cpu_has
+#define MAX_CPU_FEATURES		(NCAPINTS * 32)
+#define cpu_have_feature		boot_cpu_has
 
-#define CPU_FEATURE_TYPEFMT	"x86,ven%04Xfam%04Xmod%04X"
-#define CPU_FEATURE_TYPEVAL	boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
-				boot_cpu_data.x86_model
+#define CPU_FEATURE_TYPEFMT		"x86,ven%04Xfam%04Xmod%04X"
+#define CPU_FEATURE_TYPEVAL		boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
+					boot_cpu_data.x86_model
 
 #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
-
 #endif /* _ASM_X86_CPUFEATURE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/crash.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/crash.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/crash.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/crash.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef _ASM_X86_CRASH_H
+#define _ASM_X86_CRASH_H
+
+int crash_load_segments(struct kimage *image);
+int crash_copy_backup_region(struct kimage *image);
+int crash_setup_memmap_entries(struct kimage *image,
+		struct boot_params *params);
+
+#endif /* _ASM_X86_CRASH_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/efi.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/efi.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/efi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/efi.h	2014-09-28 17:29:07.000000000 -0400
@@ -104,6 +104,8 @@ extern void __init runtime_code_page_mke
 extern void __init efi_runtime_mkexec(void);
 extern void __init efi_dump_pagetable(void);
 extern void __init efi_apply_memmap_quirks(void);
+extern int __init efi_reuse_config(u64 tables, int nr_tables);
+extern void efi_delete_dummy_variable(void);
 
 struct efi_setup_data {
 	u64 fw_vendor;
@@ -156,6 +158,9 @@ static inline efi_status_t efi_thunk_set
 	return EFI_SUCCESS;
 }
 #endif /* CONFIG_EFI_MIXED */
+
+extern bool efi_reboot_required(void);
+
 #else
 /*
  * IF EFI is not configured, have the EFI calls return -ENOSYS.
@@ -168,6 +173,10 @@ static inline efi_status_t efi_thunk_set
 #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5)		(-ENOSYS)
 #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6)	(-ENOSYS)
 static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
+static inline bool efi_reboot_required(void)
+{
+	return false;
+}
 #endif /* CONFIG_EFI */
 
 #endif /* _ASM_X86_EFI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/fixmap.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/fixmap.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/fixmap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/fixmap.h	2014-09-28 17:29:07.000000000 -0400
@@ -106,14 +106,14 @@ enum fixed_addresses {
 	__end_of_permanent_fixed_addresses,
 
 	/*
-	 * 256 temporary boot-time mappings, used by early_ioremap(),
+	 * 512 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
 	 *
-	 * If necessary we round it up to the next 256 pages boundary so
+	 * If necessary we round it up to the next 512 pages boundary so
 	 * that we can have a single pgd entry and a single pte table:
 	 */
 #define NR_FIX_BTMAPS		64
-#define FIX_BTMAPS_SLOTS	4
+#define FIX_BTMAPS_SLOTS	8
 #define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
 	FIX_BTMAP_END =
 	 (__end_of_permanent_fixed_addresses ^
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/fpu-internal.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/fpu-internal.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/fpu-internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/fpu-internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -293,7 +293,7 @@ static inline int restore_fpu_checking(s
 	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
 	   is pending.  Clear the x87 state here by setting it to fixed
 	   values. "m" is a random variable that should be in L1 */
-	if (unlikely(static_cpu_has_safe(X86_FEATURE_FXSAVE_LEAK))) {
+	if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) {
 		asm volatile(
 			"fnclex\n\t"
 			"emms\n\t"
@@ -508,9 +508,12 @@ static inline void user_fpu_begin(void)
 
 static inline void __save_fpu(struct task_struct *tsk)
 {
-	if (use_xsave())
-		xsave_state(&tsk->thread.fpu.state->xsave, -1);
-	else
+	if (use_xsave()) {
+		if (unlikely(system_state == SYSTEM_BOOTING))
+			xsave_state_booting(&tsk->thread.fpu.state->xsave, -1);
+		else
+			xsave_state(&tsk->thread.fpu.state->xsave, -1);
+	} else
 		fpu_fxsave(&tsk->thread.fpu);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/ftrace.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/ftrace.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/ftrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/ftrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,8 @@ struct dyn_arch_ftrace {
 
 int ftrace_int3_handler(struct pt_regs *regs);
 
+#define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR
+
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/hardirq.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/hardirq.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/hardirq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/hardirq.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,6 @@ typedef struct {
 
 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
 
-/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
-#define MAX_HARDIRQS_PER_CPU NR_VECTORS
-
 #define __ARCH_IRQ_STAT
 
 #define inc_irq_stat(member)	this_cpu_inc(irq_stat.member)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/i8259.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/i8259.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/i8259.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/i8259.h	2014-09-28 17:29:07.000000000 -0400
@@ -67,4 +67,9 @@ struct legacy_pic {
 extern struct legacy_pic *legacy_pic;
 extern struct legacy_pic null_legacy_pic;
 
+static inline int nr_legacy_irqs(void)
+{
+	return legacy_pic->nr_legacy_irqs;
+}
+
 #endif /* _ASM_X86_I8259_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/io_apic.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/io_apic.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/io_apic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/io_apic.h	2014-09-28 17:29:07.000000000 -0400
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
 #define IOAPIC_LEVEL    1
+#define	IOAPIC_MAP_ALLOC		0x1
+#define	IOAPIC_MAP_CHECK		0x2
 
 #ifdef CONFIG_X86_IO_APIC
 
@@ -118,9 +120,6 @@ extern int mp_irq_entries;
 /* MP IRQ source entries */
 extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
 
-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
 /* Older SiS APIC requires we rewrite the index register */
 extern int sis_apic_bug;
 
@@ -133,9 +132,6 @@ extern int noioapicquirk;
 /* -1 if "noapic" boot option passed */
 extern int noioapicreroute;
 
-/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
-extern int timer_through_8259;
-
 /*
  * If we use the IO-APIC for IRQ routing, disable automatic
  * assignment of PCI IRQ's.
@@ -145,24 +141,17 @@ extern int timer_through_8259;
 
 struct io_apic_irq_attr;
 struct irq_cfg;
-extern int io_apic_set_pci_routing(struct device *dev, int irq,
-		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
 extern void ioapic_insert_resources(void);
 
 extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
 				     unsigned int, int,
 				     struct io_apic_irq_attr *);
-extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
-				     unsigned int, int,
-				     struct io_apic_irq_attr *);
 extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);
 
 extern void native_compose_msi_msg(struct pci_dev *pdev,
 				   unsigned int irq, unsigned int dest,
 				   struct msi_msg *msg, u8 hpet_id);
 extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
 
 extern int save_ioapic_entries(void);
 extern void mask_ioapic_entries(void);
@@ -171,15 +160,40 @@ extern int restore_ioapic_entries(void);
 extern void setup_ioapic_ids_from_mpc(void);
 extern void setup_ioapic_ids_from_mpc_nocheck(void);
 
+enum ioapic_domain_type {
+	IOAPIC_DOMAIN_INVALID,
+	IOAPIC_DOMAIN_LEGACY,
+	IOAPIC_DOMAIN_STRICT,
+	IOAPIC_DOMAIN_DYNAMIC,
+};
+
+struct device_node;
+struct irq_domain;
+struct irq_domain_ops;
+
+struct ioapic_domain_cfg {
+	enum ioapic_domain_type		type;
+	const struct irq_domain_ops	*ops;
+	struct device_node		*dev;
+};
+
 struct mp_ioapic_gsi{
 	u32 gsi_base;
 	u32 gsi_end;
 };
-extern struct mp_ioapic_gsi  mp_gsi_routing[];
 extern u32 gsi_top;
-int mp_find_ioapic(u32 gsi);
-int mp_find_ioapic_pin(int ioapic, u32 gsi);
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+
+extern int mp_find_ioapic(u32 gsi);
+extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern u32 mp_pin_to_gsi(int ioapic, int pin);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern void mp_unmap_irq(int irq);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+				      struct ioapic_domain_cfg *cfg);
+extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+			    irq_hw_number_t hwirq);
+extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
 extern void __init pre_init_apic_IRQ0(void);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
@@ -213,18 +227,19 @@ static inline void io_apic_modify(unsign
 
 extern void io_apic_eoi(unsigned int apic, unsigned int vector);
 
+extern bool mp_should_keep_irq(struct device *dev);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
 #define setup_ioapic_ids_from_mpc x86_init_noop
-static const int timer_through_8259 = 0;
 static inline void ioapic_insert_resources(void) { }
 #define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
-
-struct io_apic_irq_attr;
-static inline int io_apic_set_pci_routing(struct device *dev, int irq,
-		 struct io_apic_irq_attr *irq_attr) { return 0; }
+static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline void mp_unmap_irq(int irq) { }
+static inline bool mp_should_keep_irq(struct device *dev) { return 1; }
 
 static inline int save_ioapic_entries(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/x86/include/asm/Kbuild
--- linux-libre-3.16-gnu/arch/x86/include/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
 
 generic-y += clkdev.h
-generic-y += early_ioremap.h
 generic-y += cputime.h
+generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
+generic-y += scatterlist.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/kexec-bzimage64.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kexec-bzimage64.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/kexec-bzimage64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kexec-bzimage64.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef _ASM_KEXEC_BZIMAGE64_H
+#define _ASM_KEXEC_BZIMAGE64_H
+
+extern struct kexec_file_ops kexec_bzImage64_ops;
+
+#endif  /* _ASM_KEXE_BZIMAGE64_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/kexec.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kexec.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/kexec.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kexec.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,9 @@
 
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/bootparam.h>
+
+struct kimage;
 
 /*
  * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -61,6 +64,10 @@
 # define KEXEC_ARCH KEXEC_ARCH_X86_64
 #endif
 
+/* Memory to backup during crash kdump */
+#define KEXEC_BACKUP_SRC_START	(0UL)
+#define KEXEC_BACKUP_SRC_END	(640 * 1024UL)	/* 640K */
+
 /*
  * CPU does not save ss and sp on stack if execution is already
  * running in kernel mode at the time of NMI occurrence. This code
@@ -160,6 +167,44 @@ struct kimage_arch {
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
+	/* Details of backup region */
+	unsigned long backup_src_start;
+	unsigned long backup_src_sz;
+
+	/* Physical address of backup segment */
+	unsigned long backup_load_addr;
+
+	/* Core ELF header buffer */
+	void *elf_headers;
+	unsigned long elf_headers_sz;
+	unsigned long elf_load_addr;
+};
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_X86_64
+/*
+ * Number of elements and order of elements in this structure should match
+ * with the ones in arch/x86/purgatory/entry64.S. If you make a change here
+ * make an appropriate change in purgatory too.
+ */
+struct kexec_entry64_regs {
+	uint64_t rax;
+	uint64_t rcx;
+	uint64_t rdx;
+	uint64_t rbx;
+	uint64_t rsp;
+	uint64_t rbp;
+	uint64_t rsi;
+	uint64_t rdi;
+	uint64_t r8;
+	uint64_t r9;
+	uint64_t r10;
+	uint64_t r11;
+	uint64_t r12;
+	uint64_t r13;
+	uint64_t r14;
+	uint64_t r15;
+	uint64_t rip;
 };
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/kvm_emulate.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/kvm_emulate.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kvm_emulate.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,7 @@ struct x86_instruction_info {
 	u8  modrm_reg;          /* index of register used               */
 	u8  modrm_rm;		/* rm part of modrm			*/
 	u64 src_val;            /* value of source operand              */
+	u64 dst_val;            /* value of destination operand         */
 	u8  src_bytes;          /* size of source operand               */
 	u8  dst_bytes;          /* size of destination operand          */
 	u8  ad_bytes;           /* size of src/dst address              */
@@ -194,6 +195,7 @@ struct x86_emulate_ops {
 	int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
 	int (*set_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data);
 	int (*get_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata);
+	int (*check_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc);
 	int (*read_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc, u64 *pdata);
 	void (*halt)(struct x86_emulate_ctxt *ctxt);
 	void (*wbinvd)(struct x86_emulate_ctxt *ctxt);
@@ -231,7 +233,7 @@ struct operand {
 	union {
 		unsigned long val;
 		u64 val64;
-		char valptr[sizeof(unsigned long) + 2];
+		char valptr[sizeof(sse128_t)];
 		sse128_t vec_val;
 		u64 mm_val;
 		void *data;
@@ -240,8 +242,8 @@ struct operand {
 
 struct fetch_cache {
 	u8 data[15];
-	unsigned long start;
-	unsigned long end;
+	u8 *ptr;
+	u8 *end;
 };
 
 struct read_cache {
@@ -286,30 +288,36 @@ struct x86_emulate_ctxt {
 	u8 opcode_len;
 	u8 b;
 	u8 intercept;
-	u8 lock_prefix;
-	u8 rep_prefix;
 	u8 op_bytes;
 	u8 ad_bytes;
-	u8 rex_prefix;
 	struct operand src;
 	struct operand src2;
 	struct operand dst;
-	bool has_seg_override;
-	u8 seg_override;
-	u64 d;
 	int (*execute)(struct x86_emulate_ctxt *ctxt);
 	int (*check_perm)(struct x86_emulate_ctxt *ctxt);
+	/*
+	 * The following six fields are cleared together,
+	 * the rest are initialized unconditionally in x86_decode_insn
+	 * or elsewhere
+	 */
+	bool rip_relative;
+	u8 rex_prefix;
+	u8 lock_prefix;
+	u8 rep_prefix;
+	/* bitmaps of registers in _regs[] that can be read */
+	u32 regs_valid;
+	/* bitmaps of registers in _regs[] that have been written */
+	u32 regs_dirty;
 	/* modrm */
 	u8 modrm;
 	u8 modrm_mod;
 	u8 modrm_reg;
 	u8 modrm_rm;
 	u8 modrm_seg;
-	bool rip_relative;
+	u8 seg_override;
+	u64 d;
 	unsigned long _eip;
 	struct operand memop;
-	u32 regs_valid;  /* bitmaps of registers in _regs[] that can be read */
-	u32 regs_dirty;  /* bitmaps of registers in _regs[] that have been written */
 	/* Fields above regs are cleared together. */
 	unsigned long _regs[NR_VCPU_REGS];
 	struct operand *memopp;
@@ -407,6 +415,7 @@ bool x86_page_table_writing_insn(struct
 #define EMULATION_OK 0
 #define EMULATION_RESTART 1
 #define EMULATION_INTERCEPTED 2
+void init_decode_cache(struct x86_emulate_ctxt *ctxt);
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 			 u16 tss_selector, int idt_index, int reason,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/kvm_host.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/kvm_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/kvm_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,7 @@ static inline gfn_t gfn_to_index(gfn_t g
 #define KVM_REFILL_PAGES 25
 #define KVM_MAX_CPUID_ENTRIES 80
 #define KVM_NR_FIXED_MTRR_REGION 88
-#define KVM_NR_VAR_MTRR 10
+#define KVM_NR_VAR_MTRR 8
 
 #define ASYNC_PF_PER_VCPU 64
 
@@ -152,14 +152,16 @@ enum {
 
 #define DR6_BD		(1 << 13)
 #define DR6_BS		(1 << 14)
-#define DR6_FIXED_1	0xffff0ff0
-#define DR6_VOLATILE	0x0000e00f
+#define DR6_RTM		(1 << 16)
+#define DR6_FIXED_1	0xfffe0ff0
+#define DR6_INIT	0xffff0ff0
+#define DR6_VOLATILE	0x0001e00f
 
 #define DR7_BP_EN_MASK	0x000000ff
 #define DR7_GE		(1 << 9)
 #define DR7_GD		(1 << 13)
 #define DR7_FIXED_1	0x00000400
-#define DR7_VOLATILE	0xffff23ff
+#define DR7_VOLATILE	0xffff2bff
 
 /* apic attention bits */
 #define KVM_APIC_CHECK_VAPIC	0
@@ -448,7 +450,7 @@ struct kvm_vcpu_arch {
 	u64 tsc_offset_adjustment;
 	u64 this_tsc_nsec;
 	u64 this_tsc_write;
-	u8  this_tsc_generation;
+	u64 this_tsc_generation;
 	bool tsc_catchup;
 	bool tsc_always_catchup;
 	s8 virtual_tsc_shift;
@@ -591,7 +593,7 @@ struct kvm_arch {
 	u64 cur_tsc_nsec;
 	u64 cur_tsc_write;
 	u64 cur_tsc_offset;
-	u8  cur_tsc_generation;
+	u64 cur_tsc_generation;
 	int nr_vcpus_matched_tsc;
 
 	spinlock_t pvclock_gtod_sync_lock;
@@ -717,7 +719,7 @@ struct kvm_x86_ops {
 	int (*handle_exit)(struct kvm_vcpu *vcpu);
 	void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
 	void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
-	u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
+	u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
 	void (*patch_hypercall)(struct kvm_vcpu *vcpu,
 				unsigned char *hypercall_addr);
 	void (*set_irq)(struct kvm_vcpu *vcpu);
@@ -1070,6 +1072,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcp
 bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr);
 int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
 int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
+int kvm_pmu_check_pmc(struct kvm_vcpu *vcpu, unsigned pmc);
 int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data);
 void kvm_handle_pmu_event(struct kvm_vcpu *vcpu);
 void kvm_deliver_pmi(struct kvm_vcpu *vcpu);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/mc146818rtc.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mc146818rtc.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/mc146818rtc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mc146818rtc.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@
 #define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
 #endif
 
-#if defined(CONFIG_X86_32) && defined(__HAVE_ARCH_CMPXCHG)
+#if defined(CONFIG_X86_32)
 /*
  * This lock provides nmi access to the CMOS/RTC registers.  It has some
  * special properties.  It is owned by a CPU and stores the index register
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/mmu_context.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mmu_context.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/mmu_context.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mmu_context.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,10 @@
 
 #include <asm/desc.h>
 #include <linux/atomic.h>
+#include <linux/mm_types.h>
+
+#include <trace/events/tlb.h>
+
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/paravirt.h>
@@ -44,6 +48,7 @@ static inline void switch_mm(struct mm_s
 
 		/* Re-load page tables */
 		load_cr3(next->pgd);
+		trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
 
 		/* Stop flush ipis for the previous mm */
 		cpumask_clear_cpu(cpu, mm_cpumask(prev));
@@ -71,6 +76,7 @@ static inline void switch_mm(struct mm_s
 			 * to make sure to use no freed page tables.
 			 */
 			load_cr3(next->pgd);
+			trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
 			load_LDT_nolock(&next->context);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/mpspec.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mpspec.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/mpspec.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mpspec.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSS
 extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 extern unsigned int boot_cpu_physical_apicid;
-extern unsigned int max_physical_apicid;
-extern int mpc_default_type;
 extern unsigned long mp_lapic_addr;
 
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -88,15 +86,6 @@ static inline void early_reserve_e820_mp
 #endif
 
 int generic_processor_info(int apicid, int version);
-#ifdef CONFIG_ACPI
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
-extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
-				   u32 gsi);
-extern void mp_config_acpi_legacy_irqs(void);
-struct device;
-extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
-				 int active_high_low);
-#endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_LOCAL_APIC)
 
@@ -161,8 +150,4 @@ static inline void physid_set_mask_of_ph
 
 extern physid_mask_t phys_cpu_present_map;
 
-extern int generic_mps_oem_check(struct mpc_table *, char *, char *);
-
-extern int default_acpi_madt_oem_check(char *, char *);
-
 #endif /* _ASM_X86_MPSPEC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/mutex_32.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mutex_32.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/mutex_32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mutex_32.h	2014-09-28 17:29:07.000000000 -0400
@@ -100,23 +100,11 @@ do {								\
 static inline int __mutex_fastpath_trylock(atomic_t *count,
 					   int (*fail_fn)(atomic_t *))
 {
-	/*
-	 * We have two variants here. The cmpxchg based one is the best one
-	 * because it never induce a false contention state.  It is included
-	 * here because architectures using the inc/dec algorithms over the
-	 * xchg ones are much more likely to support cmpxchg natively.
-	 *
-	 * If not we fall back to the spinlock based variant - that is
-	 * just as efficient (and simpler) as a 'destructive' probing of
-	 * the mutex state would be.
-	 */
-#ifdef __HAVE_ARCH_CMPXCHG
+	/* cmpxchg because it never induces a false contention state. */
 	if (likely(atomic_cmpxchg(count, 1, 0) == 1))
 		return 1;
+
 	return 0;
-#else
-	return fail_fn(count);
-#endif
 }
 
 #endif /* _ASM_X86_MUTEX_32_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/mwait.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mwait.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/mwait.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/mwait.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@ static inline void __mwait(unsigned long
 static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
 {
 	if (!current_set_polling_and_test()) {
-		if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
+		if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
 			mb();
 			clflush((void *)&current_thread_info()->flags);
 			mb();
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/page_64.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/page_64.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/page_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/page_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,4 +39,6 @@ void copy_page(void *to, void *from);
 
 #endif	/* !__ASSEMBLY__ */
 
+#define __HAVE_ARCH_GATE_AREA 1
+
 #endif /* _ASM_X86_PAGE_64_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/page.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,6 @@ extern bool __virt_addr_valid(unsigned l
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
 
-#define __HAVE_ARCH_GATE_AREA 1
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #endif	/* __KERNEL__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/percpu.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/percpu.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/percpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/percpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,10 +52,9 @@
  * Compared to the generic __my_cpu_offset version, the following
  * saves one instruction and avoids clobbering a temp register.
  */
-#define raw_cpu_ptr(ptr)				\
+#define arch_raw_cpu_ptr(ptr)				\
 ({							\
 	unsigned long tcp_ptr__;			\
-	__verify_pcpu_ptr(ptr);				\
 	asm volatile("add " __percpu_arg(1) ", %0"	\
 		     : "=r" (tcp_ptr__)			\
 		     : "m" (this_cpu_off), "0" (ptr));	\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/pgtable_64.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pgtable_64.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/pgtable_64.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pgtable_64.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ extern pud_t level3_ident_pgt[512];
 extern pmd_t level2_kernel_pgt[512];
 extern pmd_t level2_fixmap_pgt[512];
 extern pmd_t level2_ident_pgt[512];
+extern pte_t level1_fixmap_pgt[512];
 extern pgd_t init_level4_pgt[];
 
 #define swapper_pg_dir init_level4_pgt
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -131,8 +131,13 @@ static inline int pte_exec(pte_t pte)
 
 static inline int pte_special(pte_t pte)
 {
-	return (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_SPECIAL)) ==
-				 (_PAGE_PRESENT|_PAGE_SPECIAL);
+	/*
+	 * See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h.
+	 * On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 ==
+	 * __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL.
+	 */
+	return (pte_flags(pte) & _PAGE_SPECIAL) &&
+		(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE));
 }
 
 static inline unsigned long pte_pfn(pte_t pte)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/platform_sst_audio.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/platform_sst_audio.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/platform_sst_audio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/platform_sst_audio.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * platform_sst_audio.h:  sst audio platform data header file
+ *
+ * Copyright (C) 2012-14 Intel Corporation
+ * Author: Jeeja KP <jeeja.kp@intel.com>
+ * 	Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ *	Vinod Koul ,vinod.koul@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.
+ */
+#ifndef _PLATFORM_SST_AUDIO_H_
+#define _PLATFORM_SST_AUDIO_H_
+
+#include <linux/sfi.h>
+
+enum sst_audio_task_id_mrfld {
+	SST_TASK_ID_NONE = 0,
+	SST_TASK_ID_SBA = 1,
+	SST_TASK_ID_MEDIA = 3,
+	SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
+};
+
+/* Device IDs for Merrifield are Pipe IDs,
+ * ref: DSP spec v0.75 */
+enum sst_audio_device_id_mrfld {
+	/* Output pipeline IDs */
+	PIPE_ID_OUT_START = 0x0,
+	PIPE_CODEC_OUT0 = 0x2,
+	PIPE_CODEC_OUT1 = 0x3,
+	PIPE_SPROT_LOOP_OUT = 0x4,
+	PIPE_MEDIA_LOOP1_OUT = 0x5,
+	PIPE_MEDIA_LOOP2_OUT = 0x6,
+	PIPE_VOIP_OUT = 0xC,
+	PIPE_PCM0_OUT = 0xD,
+	PIPE_PCM1_OUT = 0xE,
+	PIPE_PCM2_OUT = 0xF,
+	PIPE_MEDIA0_OUT = 0x12,
+	PIPE_MEDIA1_OUT = 0x13,
+/* Input Pipeline IDs */
+	PIPE_ID_IN_START = 0x80,
+	PIPE_CODEC_IN0 = 0x82,
+	PIPE_CODEC_IN1 = 0x83,
+	PIPE_SPROT_LOOP_IN = 0x84,
+	PIPE_MEDIA_LOOP1_IN = 0x85,
+	PIPE_MEDIA_LOOP2_IN = 0x86,
+	PIPE_VOIP_IN = 0x8C,
+	PIPE_PCM0_IN = 0x8D,
+	PIPE_PCM1_IN = 0x8E,
+	PIPE_MEDIA0_IN = 0x8F,
+	PIPE_MEDIA1_IN = 0x90,
+	PIPE_MEDIA2_IN = 0x91,
+	PIPE_RSVD = 0xFF,
+};
+
+/* The stream map for each platform consists of an array of the below
+ * stream map structure.
+ */
+struct sst_dev_stream_map {
+	u8 dev_num;		/* device id */
+	u8 subdev_num;		/* substream */
+	u8 direction;
+	u8 device_id;		/* fw id */
+	u8 task_id;		/* fw task */
+	u8 status;
+};
+
+struct sst_platform_data {
+	/* Intel software platform id*/
+	struct sst_dev_stream_map *pdev_strm_map;
+	unsigned int strm_map_size;
+};
+
+int add_sst_platform_device(void);
+#endif
+
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/pmc_atom.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pmc_atom.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/pmc_atom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/pmc_atom.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * Intel Atom SOC Power Management Controller Header File
+ * Copyright (c) 2014, 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 PMC_ATOM_H
+#define PMC_ATOM_H
+
+/* ValleyView Power Control Unit PCI Device ID */
+#define	PCI_DEVICE_ID_VLV_PMC	0x0F1C
+
+/* PMC Memory mapped IO registers */
+#define	PMC_BASE_ADDR_OFFSET	0x44
+#define	PMC_BASE_ADDR_MASK	0xFFFFFE00
+#define	PMC_MMIO_REG_LEN	0x100
+#define	PMC_REG_BIT_WIDTH	32
+
+/* BIOS uses FUNC_DIS to disable specific function */
+#define	PMC_FUNC_DIS		0x34
+#define	PMC_FUNC_DIS_2		0x38
+
+/* S0ix wake event control */
+#define	PMC_S0IX_WAKE_EN	0x3C
+
+#define	BIT_LPC_CLOCK_RUN		BIT(4)
+#define	BIT_SHARED_IRQ_GPSC		BIT(5)
+#define	BIT_ORED_DEDICATED_IRQ_GPSS	BIT(18)
+#define	BIT_ORED_DEDICATED_IRQ_GPSC	BIT(19)
+#define	BIT_SHARED_IRQ_GPSS		BIT(20)
+
+#define	PMC_WAKE_EN_SETTING	~(BIT_LPC_CLOCK_RUN | \
+				BIT_SHARED_IRQ_GPSC | \
+				BIT_ORED_DEDICATED_IRQ_GPSS | \
+				BIT_ORED_DEDICATED_IRQ_GPSC | \
+				BIT_SHARED_IRQ_GPSS)
+
+/* The timers acumulate time spent in sleep state */
+#define	PMC_S0IR_TMR		0x80
+#define	PMC_S0I1_TMR		0x84
+#define	PMC_S0I2_TMR		0x88
+#define	PMC_S0I3_TMR		0x8C
+#define	PMC_S0_TMR		0x90
+/* Sleep state counter is in units of of 32us */
+#define	PMC_TMR_SHIFT		5
+
+/* These registers reflect D3 status of functions */
+#define	PMC_D3_STS_0		0xA0
+
+#define	BIT_LPSS1_F0_DMA	BIT(0)
+#define	BIT_LPSS1_F1_PWM1	BIT(1)
+#define	BIT_LPSS1_F2_PWM2	BIT(2)
+#define	BIT_LPSS1_F3_HSUART1	BIT(3)
+#define	BIT_LPSS1_F4_HSUART2	BIT(4)
+#define	BIT_LPSS1_F5_SPI	BIT(5)
+#define	BIT_LPSS1_F6_XXX	BIT(6)
+#define	BIT_LPSS1_F7_XXX	BIT(7)
+#define	BIT_SCC_EMMC		BIT(8)
+#define	BIT_SCC_SDIO		BIT(9)
+#define	BIT_SCC_SDCARD		BIT(10)
+#define	BIT_SCC_MIPI		BIT(11)
+#define	BIT_HDA			BIT(12)
+#define	BIT_LPE			BIT(13)
+#define	BIT_OTG			BIT(14)
+#define	BIT_USH			BIT(15)
+#define	BIT_GBE			BIT(16)
+#define	BIT_SATA		BIT(17)
+#define	BIT_USB_EHCI		BIT(18)
+#define	BIT_SEC			BIT(19)
+#define	BIT_PCIE_PORT0		BIT(20)
+#define	BIT_PCIE_PORT1		BIT(21)
+#define	BIT_PCIE_PORT2		BIT(22)
+#define	BIT_PCIE_PORT3		BIT(23)
+#define	BIT_LPSS2_F0_DMA	BIT(24)
+#define	BIT_LPSS2_F1_I2C1	BIT(25)
+#define	BIT_LPSS2_F2_I2C2	BIT(26)
+#define	BIT_LPSS2_F3_I2C3	BIT(27)
+#define	BIT_LPSS2_F4_I2C4	BIT(28)
+#define	BIT_LPSS2_F5_I2C5	BIT(29)
+#define	BIT_LPSS2_F6_I2C6	BIT(30)
+#define	BIT_LPSS2_F7_I2C7	BIT(31)
+
+#define	PMC_D3_STS_1		0xA4
+#define	BIT_SMB			BIT(0)
+#define	BIT_OTG_SS_PHY		BIT(1)
+#define	BIT_USH_SS_PHY		BIT(2)
+#define	BIT_DFX			BIT(3)
+
+/* PMC I/O Registers */
+#define	ACPI_BASE_ADDR_OFFSET	0x40
+#define	ACPI_BASE_ADDR_MASK	0xFFFFFE00
+#define	ACPI_MMIO_REG_LEN	0x100
+
+#define	PM1_CNT			0x4
+#define	SLEEP_TYPE_MASK		0xFFFFECFF
+#define	SLEEP_TYPE_S5		0x1C00
+#define	SLEEP_ENABLE		0x2000
+#endif /* PMC_ATOM_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,6 @@ extern u16 __read_mostly tlb_lld_4k[NR_I
 extern u16 __read_mostly tlb_lld_2m[NR_INFO];
 extern u16 __read_mostly tlb_lld_4m[NR_INFO];
 extern u16 __read_mostly tlb_lld_1g[NR_INFO];
-extern s8  __read_mostly tlb_flushall_shift;
 
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
@@ -386,8 +385,8 @@ struct bndcsr_struct {
 
 struct xsave_hdr_struct {
 	u64 xstate_bv;
-	u64 reserved1[2];
-	u64 reserved2[5];
+	u64 xcomp_bv;
+	u64 reserved[6];
 } __attribute__((packed));
 
 struct xsave_struct {
@@ -696,6 +695,8 @@ static inline void cpu_relax(void)
 	rep_nop();
 }
 
+#define cpu_relax_lowlatency() cpu_relax()
+
 /* Stop speculative execution and prefetching of modified code. */
 static inline void sync_core(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/prom.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/prom.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/prom.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/prom.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,12 +26,10 @@
 extern int of_ioapic;
 extern u64 initial_dtb;
 extern void add_dtb(u64 data);
-extern void x86_add_irq_domains(void);
 void x86_of_pci_init(void);
 void x86_dtb_init(void);
 #else
 static inline void add_dtb(u64 data) { }
-static inline void x86_add_irq_domains(void) { }
 static inline void x86_of_pci_init(void) { }
 static inline void x86_dtb_init(void) { }
 #define of_ioapic 0
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/qrwlock.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/qrwlock.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/qrwlock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/qrwlock.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <asm-generic/qrwlock_types.h>
 
-#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
+#ifndef CONFIG_X86_PPRO_FENCE
 #define queue_write_unlock queue_write_unlock
 static inline void queue_write_unlock(struct qrwlock *lock)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/scatterlist.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/scatterlist.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/scatterlist.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/scatterlist.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#ifndef _ASM_X86_SCATTERLIST_H
-#define _ASM_X86_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_X86_SCATTERLIST_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/smpboot_hooks.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/smpboot_hooks.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/smpboot_hooks.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/smpboot_hooks.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,11 +17,11 @@ static inline void smpboot_setup_warm_re
 	spin_unlock_irqrestore(&rtc_lock, flags);
 	local_flush_tlb();
 	pr_debug("1.\n");
-	*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) =
-								 start_eip >> 4;
+	*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
+							start_eip >> 4;
 	pr_debug("2.\n");
-	*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_low)) =
-							 start_eip & 0xf;
+	*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
+							start_eip & 0xf;
 	pr_debug("3.\n");
 }
 
@@ -42,7 +42,7 @@ static inline void smpboot_restore_warm_
 	CMOS_WRITE(0, 0xf);
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
-	*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
+	*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
 }
 
 static inline void __init smpboot_setup_io_apic(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/uv/uv_bau.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/uv/uv_bau.h	2014-09-28 17:29:07.000000000 -0400
@@ -73,6 +73,7 @@
 #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD	(is_uv1_hub() ?			\
 		UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD :			\
 		UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD)
+/* assuming UV3 is the same */
 
 #define BAU_MISC_CONTROL_MULT_MASK	3
 
@@ -93,6 +94,8 @@
 #define SOFTACK_MSHIFT UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT
 #define SOFTACK_PSHIFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
 #define SOFTACK_TIMEOUT_PERIOD UV_INTD_SOFT_ACK_TIMEOUT_PERIOD
+#define PREFETCH_HINT_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_PREFETCH_HINT_SHFT
+#define SB_STATUS_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
 #define write_gmmr	uv_write_global_mmr64
 #define write_lmmr	uv_write_local_mmr
 #define read_lmmr	uv_read_local_mmr
@@ -322,8 +325,9 @@ struct uv1_bau_msg_header {
 /*
  * UV2 Message header:  16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
  * see figure 9-2 of harp_sys.pdf
+ * assuming UV3 is the same
  */
-struct uv2_bau_msg_header {
+struct uv2_3_bau_msg_header {
 	unsigned int	base_dest_nasid:15;	/* nasid of the first bit */
 	/* bits 14:0 */				/* in uvhub map */
 	unsigned int	dest_subnodeid:5;	/* must be 0x10, for the LB */
@@ -395,7 +399,7 @@ struct bau_desc {
 	 */
 	union bau_msg_header {
 		struct uv1_bau_msg_header	uv1_hdr;
-		struct uv2_bau_msg_header	uv2_hdr;
+		struct uv2_3_bau_msg_header	uv2_3_hdr;
 	} header;
 
 	struct bau_msg_payload			payload;
@@ -631,11 +635,6 @@ struct bau_control {
 	struct hub_and_pnode	*thp;
 };
 
-static inline unsigned long read_mmr_uv2_status(void)
-{
-	return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
-}
-
 static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
@@ -760,7 +759,11 @@ static inline int atomic_read_short(cons
  */
 static inline int atom_asr(short i, struct atomic_short *v)
 {
-	return i + xadd(&v->counter, i);
+	short __i = i;
+	asm volatile(LOCK_PREFIX "xaddw %0, %1"
+			: "+r" (i), "+m" (v->counter)
+			: : "memory");
+	return i + __i;
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/vdso.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vdso.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/vdso.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vdso.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,15 +18,15 @@ struct vdso_image {
 
 	unsigned long alt, alt_len;
 
-	unsigned long sym_end_mapping;  /* Total size of the mapping */
+	long sym_vvar_start;  /* Negative offset to the vvar area */
 
-	unsigned long sym_vvar_page;
-	unsigned long sym_hpet_page;
-	unsigned long sym_VDSO32_NOTE_MASK;
-	unsigned long sym___kernel_sigreturn;
-	unsigned long sym___kernel_rt_sigreturn;
-	unsigned long sym___kernel_vsyscall;
-	unsigned long sym_VDSO32_SYSENTER_RETURN;
+	long sym_vvar_page;
+	long sym_hpet_page;
+	long sym_VDSO32_NOTE_MASK;
+	long sym___kernel_sigreturn;
+	long sym___kernel_rt_sigreturn;
+	long sym___kernel_vsyscall;
+	long sym_VDSO32_SYSENTER_RETURN;
 };
 
 #ifdef CONFIG_X86_64
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/vga.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vga.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/vga.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vga.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,10 +17,4 @@
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))
 
-#ifdef CONFIG_FB_EFI
-#define __ARCH_HAS_VGA_DEFAULT_DEVICE
-extern struct pci_dev *vga_default_device(void);
-extern void vga_set_default_device(struct pci_dev *pdev);
-#endif
-
 #endif /* _ASM_X86_VGA_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/vmx.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vmx.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/vmx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/vmx.h	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,9 @@
 #define CPU_BASED_MONITOR_EXITING               0x20000000
 #define CPU_BASED_PAUSE_EXITING                 0x40000000
 #define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS   0x80000000
+
+#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR	0x0401e172
+
 /*
  * Definitions of Secondary Processor-Based VM-Execution Controls.
  */
@@ -76,7 +79,7 @@
 
 #define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR	0x00000016
 
-#define VM_EXIT_SAVE_DEBUG_CONTROLS             0x00000002
+#define VM_EXIT_SAVE_DEBUG_CONTROLS             0x00000004
 #define VM_EXIT_HOST_ADDR_SPACE_SIZE            0x00000200
 #define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL      0x00001000
 #define VM_EXIT_ACK_INTR_ON_EXIT                0x00008000
@@ -89,7 +92,7 @@
 
 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR	0x00036dff
 
-#define VM_ENTRY_LOAD_DEBUG_CONTROLS            0x00000002
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS            0x00000004
 #define VM_ENTRY_IA32E_MODE                     0x00000200
 #define VM_ENTRY_SMM                            0x00000400
 #define VM_ENTRY_DEACT_DUAL_MONITOR             0x00000800
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/asm/xsave.h linux-libre-3.17-rc7-gnu/arch/x86/include/asm/xsave.h
--- linux-libre-3.16-gnu/arch/x86/include/asm/xsave.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/asm/xsave.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,24 +52,170 @@ extern void xsave_init(void);
 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
 extern int init_fpu(struct task_struct *child);
 
-static inline int fpu_xrstor_checking(struct xsave_struct *fx)
+/* These macros all use (%edi)/(%rdi) as the single memory argument. */
+#define XSAVE		".byte " REX_PREFIX "0x0f,0xae,0x27"
+#define XSAVEOPT	".byte " REX_PREFIX "0x0f,0xae,0x37"
+#define XSAVES		".byte " REX_PREFIX "0x0f,0xc7,0x2f"
+#define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
+#define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"
+
+#define xstate_fault	".section .fixup,\"ax\"\n"	\
+			"3:  movl $-1,%[err]\n"		\
+			"    jmp  2b\n"			\
+			".previous\n"			\
+			_ASM_EXTABLE(1b, 3b)		\
+			: [err] "=r" (err)
+
+/*
+ * This function is called only during boot time when x86 caps are not set
+ * up and alternative can not be used yet.
+ */
+static inline int xsave_state_booting(struct xsave_struct *fx, u64 mask)
 {
-	int err;
+	u32 lmask = mask;
+	u32 hmask = mask >> 32;
+	int err = 0;
 
-	asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
-		     "2:\n"
-		     ".section .fixup,\"ax\"\n"
-		     "3:  movl $-1,%[err]\n"
-		     "    jmp  2b\n"
-		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [err] "=r" (err)
-		     : "D" (fx), "m" (*fx), "a" (-1), "d" (-1), "0" (0)
+	WARN_ON(system_state != SYSTEM_BOOTING);
+
+	if (boot_cpu_has(X86_FEATURE_XSAVES))
+		asm volatile("1:"XSAVES"\n\t"
+			"2:\n\t"
+			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			:   "memory");
+	else
+		asm volatile("1:"XSAVE"\n\t"
+			"2:\n\t"
+			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			:   "memory");
+
+	asm volatile(xstate_fault
+		     : "0" (0)
+		     : "memory");
+
+	return err;
+}
+
+/*
+ * This function is called only during boot time when x86 caps are not set
+ * up and alternative can not be used yet.
+ */
+static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask)
+{
+	u32 lmask = mask;
+	u32 hmask = mask >> 32;
+	int err = 0;
+
+	WARN_ON(system_state != SYSTEM_BOOTING);
+
+	if (boot_cpu_has(X86_FEATURE_XSAVES))
+		asm volatile("1:"XRSTORS"\n\t"
+			"2:\n\t"
+			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			:   "memory");
+	else
+		asm volatile("1:"XRSTOR"\n\t"
+			"2:\n\t"
+			: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+			:   "memory");
+
+	asm volatile(xstate_fault
+		     : "0" (0)
 		     : "memory");
 
 	return err;
 }
 
+/*
+ * Save processor xstate to xsave area.
+ */
+static inline int xsave_state(struct xsave_struct *fx, u64 mask)
+{
+	u32 lmask = mask;
+	u32 hmask = mask >> 32;
+	int err = 0;
+
+	/*
+	 * If xsaves is enabled, xsaves replaces xsaveopt because
+	 * it supports compact format and supervisor states in addition to
+	 * modified optimization in xsaveopt.
+	 *
+	 * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
+	 * because xsaveopt supports modified optimization which is not
+	 * supported by xsave.
+	 *
+	 * If none of xsaves and xsaveopt is enabled, use xsave.
+	 */
+	alternative_input_2(
+		"1:"XSAVE,
+		"1:"XSAVEOPT,
+		X86_FEATURE_XSAVEOPT,
+		"1:"XSAVES,
+		X86_FEATURE_XSAVES,
+		[fx] "D" (fx), "a" (lmask), "d" (hmask) :
+		"memory");
+	asm volatile("2:\n\t"
+		     xstate_fault
+		     : "0" (0)
+		     : "memory");
+
+	return err;
+}
+
+/*
+ * Restore processor xstate from xsave area.
+ */
+static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
+{
+	int err = 0;
+	u32 lmask = mask;
+	u32 hmask = mask >> 32;
+
+	/*
+	 * Use xrstors to restore context if it is enabled. xrstors supports
+	 * compacted format of xsave area which is not supported by xrstor.
+	 */
+	alternative_input(
+		"1: " XRSTOR,
+		"1: " XRSTORS,
+		X86_FEATURE_XSAVES,
+		"D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+		: "memory");
+
+	asm volatile("2:\n"
+		     xstate_fault
+		     : "0" (0)
+		     : "memory");
+
+	return err;
+}
+
+/*
+ * Save xstate context for old process during context switch.
+ */
+static inline void fpu_xsave(struct fpu *fpu)
+{
+	xsave_state(&fpu->state->xsave, -1);
+}
+
+/*
+ * Restore xstate context for new process during context switch.
+ */
+static inline int fpu_xrstor_checking(struct xsave_struct *fx)
+{
+	return xrstor_state(fx, -1);
+}
+
+/*
+ * Save xstate to user space xsave area.
+ *
+ * We don't use modified optimization because xrstor/xrstors might track
+ * a different application.
+ *
+ * We don't use compacted format xsave area for
+ * backward compatibility for old applications which don't understand
+ * compacted format of xsave area.
+ */
 static inline int xsave_user(struct xsave_struct __user *buf)
 {
 	int err;
@@ -83,69 +229,34 @@ static inline int xsave_user(struct xsav
 		return -EFAULT;
 
 	__asm__ __volatile__(ASM_STAC "\n"
-			     "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
+			     "1:"XSAVE"\n"
 			     "2: " ASM_CLAC "\n"
-			     ".section .fixup,\"ax\"\n"
-			     "3:  movl $-1,%[err]\n"
-			     "    jmp  2b\n"
-			     ".previous\n"
-			     _ASM_EXTABLE(1b,3b)
-			     : [err] "=r" (err)
+			     xstate_fault
 			     : "D" (buf), "a" (-1), "d" (-1), "0" (0)
 			     : "memory");
 	return err;
 }
 
+/*
+ * Restore xstate from user space xsave area.
+ */
 static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
 {
-	int err;
+	int err = 0;
 	struct xsave_struct *xstate = ((__force struct xsave_struct *)buf);
 	u32 lmask = mask;
 	u32 hmask = mask >> 32;
 
 	__asm__ __volatile__(ASM_STAC "\n"
-			     "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
+			     "1:"XRSTOR"\n"
 			     "2: " ASM_CLAC "\n"
-			     ".section .fixup,\"ax\"\n"
-			     "3:  movl $-1,%[err]\n"
-			     "    jmp  2b\n"
-			     ".previous\n"
-			     _ASM_EXTABLE(1b,3b)
-			     : [err] "=r" (err)
+			     xstate_fault
 			     : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
 			     : "memory");	/* memory required? */
 	return err;
 }
 
-static inline void xrstor_state(struct xsave_struct *fx, u64 mask)
-{
-	u32 lmask = mask;
-	u32 hmask = mask >> 32;
-
-	asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
-		     : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
-		     :   "memory");
-}
-
-static inline void xsave_state(struct xsave_struct *fx, u64 mask)
-{
-	u32 lmask = mask;
-	u32 hmask = mask >> 32;
-
-	asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
-		     : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
-		     :   "memory");
-}
+void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
+void setup_xstate_comp(void);
 
-static inline void fpu_xsave(struct fpu *fpu)
-{
-	/* This, however, we can work around by forcing the compiler to select
-	   an addressing mode that doesn't require extended registers. */
-	alternative_input(
-		".byte " REX_PREFIX "0x0f,0xae,0x27",
-		".byte " REX_PREFIX "0x0f,0xae,0x37",
-		X86_FEATURE_XSAVEOPT,
-		[fx] "D" (&fpu->state->xsave), "a" (-1), "d" (-1) :
-		"memory");
-}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/uapi/asm/Kbuild linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/Kbuild
--- linux-libre-3.16-gnu/arch/x86/include/uapi/asm/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@ header-y += ipcbuf.h
 header-y += ist.h
 header-y += kvm.h
 header-y += kvm_para.h
+header-y += kvm_perf.h
 header-y += ldt.h
 header-y += mce.h
 header-y += mman.h
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/uapi/asm/kvm.h linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/kvm.h
--- linux-libre-3.16-gnu/arch/x86/include/uapi/asm/kvm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/kvm.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,10 @@
 #define GP_VECTOR 13
 #define PF_VECTOR 14
 #define MF_VECTOR 16
+#define AC_VECTOR 17
 #define MC_VECTOR 18
+#define XM_VECTOR 19
+#define VE_VECTOR 20
 
 /* Select x86 specific features in <linux/kvm.h> */
 #define __KVM_HAVE_PIT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/uapi/asm/kvm_perf.h linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/kvm_perf.h
--- linux-libre-3.16-gnu/arch/x86/include/uapi/asm/kvm_perf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/kvm_perf.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef _ASM_X86_KVM_PERF_H
+#define _ASM_X86_KVM_PERF_H
+
+#include <asm/svm.h>
+#include <asm/vmx.h>
+#include <asm/kvm.h>
+
+#define DECODE_STR_LEN 20
+
+#define VCPU_ID "vcpu_id"
+
+#define KVM_ENTRY_TRACE "kvm:kvm_entry"
+#define KVM_EXIT_TRACE "kvm:kvm_exit"
+#define KVM_EXIT_REASON "exit_reason"
+
+#endif /* _ASM_X86_KVM_PERF_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/include/uapi/asm/msr-index.h linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/msr-index.h
--- linux-libre-3.16-gnu/arch/x86/include/uapi/asm/msr-index.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/include/uapi/asm/msr-index.h	2014-09-28 17:29:07.000000000 -0400
@@ -149,6 +149,9 @@
 
 #define MSR_CORE_C1_RES			0x00000660
 
+#define MSR_CC6_DEMOTION_POLICY_CONFIG	0x00000668
+#define MSR_MC6_DEMOTION_POLICY_CONFIG	0x00000669
+
 #define MSR_AMD64_MC0_MASK		0xc0010044
 
 #define MSR_IA32_MCx_CTL(x)		(MSR_IA32_MC0_CTL + 4*(x))
@@ -297,6 +300,8 @@
 #define MSR_IA32_TSC_ADJUST             0x0000003b
 #define MSR_IA32_BNDCFGS		0x00000d90
 
+#define MSR_IA32_XSS			0x00000da0
+
 #define FEATURE_CONTROL_LOCKED				(1<<0)
 #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX	(1<<1)
 #define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX	(1<<2)
@@ -558,6 +563,7 @@
 
 /* VMX_BASIC bits and bitmasks */
 #define VMX_BASIC_VMCS_SIZE_SHIFT	32
+#define VMX_BASIC_TRUE_CTLS		(1ULL << 55)
 #define VMX_BASIC_64		0x0001000000000000LLU
 #define VMX_BASIC_MEM_TYPE_SHIFT	50
 #define VMX_BASIC_MEM_TYPE_MASK	0x003c000000000000LLU
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/Kbuild linux-libre-3.17-rc7-gnu/arch/x86/Kbuild
--- linux-libre-3.16-gnu/arch/x86/Kbuild	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/Kbuild	2014-09-28 17:29:07.000000000 -0400
@@ -16,3 +16,5 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/
 
 obj-y += platform/
 obj-y += net/
+
+obj-$(CONFIG_KEXEC_FILE) += purgatory/
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/Kconfig linux-libre-3.17-rc7-gnu/arch/x86/Kconfig
--- linux-libre-3.16-gnu/arch/x86/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,9 @@ config X86_64
 ### Arch settings
 config X86
 	def_bool y
+	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
+	select ARCH_HAS_FAST_MULTIPLIER
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select HAVE_AOUT if X86_32
@@ -54,7 +56,6 @@ config X86
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_GRAPH_FP_TEST
-	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_SYSCALL_TRACEPOINTS
 	select SYSCTL_EXCEPTION_TRACE
 	select HAVE_KVM
@@ -96,6 +97,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select HAVE_BPF_JIT if X86_64
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select ARCH_HAS_SG_CHAIN
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_IOMAP
@@ -109,9 +111,9 @@ config X86
 	select CLOCKSOURCE_WATCHDOG
 	select GENERIC_CLOCKEVENTS
 	select ARCH_CLOCKSOURCE_DATA
+	select CLOCKSOURCE_VALIDATE_LAST_CYCLE
 	select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
 	select GENERIC_TIME_VSYSCALL
-	select KTIME_SCALAR if X86_32
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select HAVE_CONTEXT_TRACKING if X86_64
@@ -132,6 +134,9 @@ config X86
 	select GENERIC_CPU_AUTOPROBE
 	select HAVE_ARCH_AUDITSYSCALL
 	select ARCH_SUPPORTS_ATOMIC_RMW
+	select HAVE_ACPI_APEI if ACPI
+	select HAVE_ACPI_APEI_NMI if ACPI
+	select ACPI_LEGACY_TABLES_LOOKUP if ACPI
 
 config INSTRUCTION_DECODER
 	def_bool y
@@ -430,6 +435,7 @@ config X86_INTEL_CE
 	bool "CE4100 TV platform"
 	depends on PCI
 	depends on PCI_GODIRECT
+	depends on X86_IO_APIC
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
 	select X86_REBOOTFIXUPS
@@ -836,6 +842,7 @@ config X86_IO_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+	select IRQ_DOMAIN
 
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 	bool "Reroute for broken boot IRQs"
@@ -1523,6 +1530,7 @@ config EFI
 	bool "EFI runtime service support"
 	depends on ACPI
 	select UCS2_STRING
+	select EFI_RUNTIME_WRAPPERS
 	---help---
 	  This enables the kernel to use EFI runtime services that are
 	  available (such as the EFI variable services).
@@ -1536,7 +1544,8 @@ config EFI
 
 config EFI_STUB
        bool "EFI stub support"
-       depends on EFI
+       depends on EFI && !X86_USE_3DNOW
+       select RELOCATABLE
        ---help---
           This kernel feature allows a bzImage to be loaded directly
 	  by EFI firmware without the use of a bootloader.
@@ -1591,6 +1600,41 @@ config KEXEC
 	  interface is strongly in flux, so no good recommendation can be
 	  made.
 
+config KEXEC_FILE
+	bool "kexec file based system call"
+	select BUILD_BIN2C
+	depends on KEXEC
+	depends on X86_64
+	depends on CRYPTO=y
+	depends on CRYPTO_SHA256=y
+	---help---
+	  This is new version of kexec system call. This system call is
+	  file based and takes file descriptors as system call argument
+	  for kernel and initramfs as opposed to list of segments as
+	  accepted by previous system call.
+
+config KEXEC_VERIFY_SIG
+	bool "Verify kernel signature during kexec_file_load() syscall"
+	depends on KEXEC_FILE
+	---help---
+	  This option makes kernel signature verification mandatory for
+	  kexec_file_load() syscall. If kernel is signature can not be
+	  verified, kexec_file_load() will fail.
+
+	  This option enforces signature verification at generic level.
+	  One needs to enable signature verification for type of kernel
+	  image being loaded to make sure it works. For example, enable
+	  bzImage signature verification option to be able to load and
+	  verify signatures of bzImage. Otherwise kernel loading will fail.
+
+config KEXEC_BZIMAGE_VERIFY_SIG
+	bool "Enable bzImage signature verification support"
+	depends on KEXEC_VERIFY_SIG
+	depends on SIGNED_PE_FILE_VERIFICATION
+	select SYSTEM_TRUSTED_KEYRING
+	---help---
+	  Enable bzImage signature verification support.
+
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	depends on X86_64 || (X86_32 && HIGHMEM)
@@ -2404,6 +2448,10 @@ config IOSF_MBI
 	default m
 	depends on PCI
 
+config PMC_ATOM
+	def_bool y
+        depends on PCI
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/acpi/apei.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/apei.c
--- linux-libre-3.16-gnu/arch/x86/kernel/acpi/apei.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/apei.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Arch-specific APEI-related functions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 <acpi/apei.h>
+
+#include <asm/mce.h>
+#include <asm/tlbflush.h>
+
+int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data)
+{
+#ifdef CONFIG_X86_MCE
+	int i;
+	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;
+
+	/*
+	 * We expect HEST to provide a list of MC banks that report errors
+	 * in firmware first mode. Otherwise, return non-zero value to
+	 * indicate that we are done parsing HEST.
+	 */
+	if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) ||
+	    !cmc->num_hardware_banks)
+		return 1;
+
+	pr_info("HEST: Enabling Firmware First mode for corrected errors.\n");
+
+	mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1);
+	for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++)
+		mce_disable_bank(mc_bank->bank_number);
+#endif
+	return 1;
+}
+
+void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
+{
+#ifdef CONFIG_X86_MCE
+	apei_mce_report_mem_error(sev, mem_err);
+#endif
+}
+
+void arch_apei_flush_tlb_one(unsigned long addr)
+{
+	__flush_tlb_one(addr);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/acpi/boot.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/boot.c
--- linux-libre-3.16-gnu/arch/x86/kernel/acpi/boot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/boot.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/dmi.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
@@ -43,6 +44,7 @@
 #include <asm/io.h>
 #include <asm/mpspec.h>
 #include <asm/smp.h>
+#include <asm/i8259.h>
 
 #include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
 static int __initdata acpi_force = 0;
@@ -74,10 +76,6 @@ int acpi_fix_pin2_polarity __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
-#ifndef __HAVE_ARCH_CMPXCHG
-#warning ACPI uses CMPXCHG, i486 and later hardware
-#endif
-
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
@@ -97,44 +95,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY
 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
 };
 
-static unsigned int gsi_to_irq(unsigned int gsi)
-{
-	unsigned int irq = gsi + NR_IRQS_LEGACY;
-	unsigned int i;
-
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		if (isa_irq_to_gsi[i] == gsi) {
-			return i;
-		}
-	}
-
-	/* Provide an identity mapping of gsi == irq
-	 * except on truly weird platforms that have
-	 * non isa irqs in the first 16 gsis.
-	 */
-	if (gsi >= NR_IRQS_LEGACY)
-		irq = gsi;
-	else
-		irq = gsi_top + gsi;
-
-	return irq;
-}
-
-static u32 irq_to_gsi(int irq)
-{
-	unsigned int gsi;
-
-	if (irq < NR_IRQS_LEGACY)
-		gsi = isa_irq_to_gsi[irq];
-	else if (irq < gsi_top)
-		gsi = irq;
-	else if (irq < (gsi_top + NR_IRQS_LEGACY))
-		gsi = irq - gsi_top;
-	else
-		gsi = 0xffffffff;
-
-	return gsi;
-}
+#define	ACPI_INVALID_GSI		INT_MIN
 
 /*
  * This is just a simple wrapper around early_ioremap(),
@@ -345,11 +306,145 @@ acpi_parse_lapic_nmi(struct acpi_subtabl
 #endif				/*CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_IO_APIC
+#define MP_ISA_BUS		0
+
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+					  u32 gsi)
+{
+	int ioapic;
+	int pin;
+	struct mpc_intsrc mp_irq;
+
+	/*
+	 * Convert 'gsi' to 'ioapic.pin'.
+	 */
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0)
+		return;
+	pin = mp_find_ioapic_pin(ioapic, gsi);
+
+	/*
+	 * TBD: This check is for faulty timer entries, where the override
+	 *      erroneously sets the trigger to level, resulting in a HUGE
+	 *      increase of timer interrupts!
+	 */
+	if ((bus_irq == 0) && (trigger == 3))
+		trigger = 1;
+
+	mp_irq.type = MP_INTSRC;
+	mp_irq.irqtype = mp_INT;
+	mp_irq.irqflag = (trigger << 2) | polarity;
+	mp_irq.srcbus = MP_ISA_BUS;
+	mp_irq.srcbusirq = bus_irq;	/* IRQ */
+	mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
+	mp_irq.dstirq = pin;	/* INTIN# */
+
+	mp_save_irq(&mp_irq);
+
+	/*
+	 * Reset default identity mapping if gsi is also an legacy IRQ,
+	 * otherwise there will be more than one entry with the same GSI
+	 * and acpi_isa_irq_to_gsi() may give wrong result.
+	 */
+	if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
+		isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
+	isa_irq_to_gsi[bus_irq] = gsi;
+}
+
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+			int polarity)
+{
+#ifdef CONFIG_X86_MPPARSE
+	struct mpc_intsrc mp_irq;
+	struct pci_dev *pdev;
+	unsigned char number;
+	unsigned int devfn;
+	int ioapic;
+	u8 pin;
+
+	if (!acpi_ioapic)
+		return 0;
+	if (!dev || !dev_is_pci(dev))
+		return 0;
+
+	pdev = to_pci_dev(dev);
+	number = pdev->bus->number;
+	devfn = pdev->devfn;
+	pin = pdev->pin;
+	/* print the entry should happen on mptable identically */
+	mp_irq.type = MP_INTSRC;
+	mp_irq.irqtype = mp_INT;
+	mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	mp_irq.srcbus = number;
+	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	mp_irq.dstapic = mpc_ioapic_id(ioapic);
+	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+	mp_save_irq(&mp_irq);
+#endif
+	return 0;
+}
+
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+			   int polarity)
+{
+	int irq, node;
+
+	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+		return gsi;
+
+	/* Don't set up the ACPI SCI because it's already set up */
+	if (acpi_gbl_FADT.sci_interrupt == gsi)
+		return gsi;
+
+	trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
+	polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
+	node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+	if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
+		pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+		return -1;
+	}
+
+	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+	if (irq < 0)
+		return irq;
+
+	if (enable_update_mptable)
+		mp_config_acpi_gsi(dev, gsi, trigger, polarity);
+
+	return irq;
+}
+
+static void mp_unregister_gsi(u32 gsi)
+{
+	int irq;
+
+	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+		return;
+
+	if (acpi_gbl_FADT.sci_interrupt == gsi)
+		return;
+
+	irq = mp_map_gsi_to_irq(gsi, 0);
+	if (irq > 0)
+		mp_unmap_irq(irq);
+}
+
+static struct irq_domain_ops acpi_irqdomain_ops = {
+	.map = mp_irqdomain_map,
+	.unmap = mp_irqdomain_unmap,
+};
 
 static int __init
 acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 {
 	struct acpi_madt_io_apic *ioapic = NULL;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &acpi_irqdomain_ops,
+	};
 
 	ioapic = (struct acpi_madt_io_apic *)header;
 
@@ -358,8 +453,12 @@ acpi_parse_ioapic(struct acpi_subtable_h
 
 	acpi_table_print_madt_entry(header);
 
-	mp_register_ioapic(ioapic->id,
-			   ioapic->address, ioapic->global_irq_base);
+	/* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
+	if (ioapic->global_irq_base < nr_legacy_irqs())
+		cfg.type = IOAPIC_DOMAIN_LEGACY;
+
+	mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
+			   &cfg);
 
 	return 0;
 }
@@ -382,11 +481,6 @@ static void __init acpi_sci_ioapic_setup
 	if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
 		polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
 
-	/*
-	 * mp_config_acpi_legacy_irqs() already setup IRQs < 16
-	 * If GSI is < 16, this will update its flags,
-	 * else it will create a new mp_irqs[] entry.
-	 */
 	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
@@ -508,25 +602,28 @@ void __init acpi_pic_sci_set_trigger(uns
 	outb(new >> 8, 0x4d1);
 }
 
-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	*irq = gsi_to_irq(gsi);
+	int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
 
-#ifdef CONFIG_X86_IO_APIC
-	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
-#endif
+	if (irq >= 0) {
+		*irqp = irq;
+		return 0;
+	}
 
-	return 0;
+	return -1;
 }
 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
 int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
 {
-	if (isa_irq >= 16)
-		return -1;
-	*gsi = irq_to_gsi(isa_irq);
-	return 0;
+	if (isa_irq < nr_legacy_irqs() &&
+	    isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
+		*gsi = isa_irq_to_gsi[isa_irq];
+		return 0;
+	}
+
+	return -1;
 }
 
 static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
@@ -546,15 +643,25 @@ static int acpi_register_gsi_pic(struct
 static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 				    int trigger, int polarity)
 {
+	int irq = gsi;
+
 #ifdef CONFIG_X86_IO_APIC
-	gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+	irq = mp_register_gsi(dev, gsi, trigger, polarity);
 #endif
 
-	return gsi;
+	return irq;
+}
+
+static void acpi_unregister_gsi_ioapic(u32 gsi)
+{
+#ifdef CONFIG_X86_IO_APIC
+	mp_unregister_gsi(gsi);
+#endif
 }
 
 int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
 			   int trigger, int polarity) = acpi_register_gsi_pic;
+void (*__acpi_unregister_gsi)(u32 gsi) = NULL;
 
 #ifdef CONFIG_ACPI_SLEEP
 int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@ -568,32 +675,22 @@ int (*acpi_suspend_lowlevel)(void);
  */
 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 {
-	unsigned int irq;
-	unsigned int plat_gsi = gsi;
-
-	plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
-	irq = gsi_to_irq(plat_gsi);
-
-	return irq;
+	return __acpi_register_gsi(dev, gsi, trigger, polarity);
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
 void acpi_unregister_gsi(u32 gsi)
 {
+	if (__acpi_unregister_gsi)
+		__acpi_unregister_gsi(gsi);
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
-void __init acpi_set_irq_model_pic(void)
-{
-	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
-	__acpi_register_gsi = acpi_register_gsi_pic;
-	acpi_ioapic = 0;
-}
-
-void __init acpi_set_irq_model_ioapic(void)
+static void __init acpi_set_irq_model_ioapic(void)
 {
 	acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
 	__acpi_register_gsi = acpi_register_gsi_ioapic;
+	__acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
 	acpi_ioapic = 1;
 }
 
@@ -829,9 +926,8 @@ static int __init early_acpi_parse_madt_
 	 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
 	 */
 
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
-				  acpi_parse_lapic_addr_ovr, 0);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+				      acpi_parse_lapic_addr_ovr, 0);
 	if (count < 0) {
 		printk(KERN_ERR PREFIX
 		       "Error parsing LAPIC address override entry\n");
@@ -856,9 +952,8 @@ static int __init acpi_parse_madt_lapic_
 	 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
 	 */
 
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
-				  acpi_parse_lapic_addr_ovr, 0);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+				      acpi_parse_lapic_addr_ovr, 0);
 	if (count < 0) {
 		printk(KERN_ERR PREFIX
 		       "Error parsing LAPIC address override entry\n");
@@ -886,11 +981,10 @@ static int __init acpi_parse_madt_lapic_
 		return count;
 	}
 
-	x2count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
-				  acpi_parse_x2apic_nmi, 0);
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+	x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+					acpi_parse_x2apic_nmi, 0);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+				      acpi_parse_lapic_nmi, 0);
 	if (count < 0 || x2count < 0) {
 		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
 		/* TBD: Cleanup to allow fallback to MPS */
@@ -901,44 +995,7 @@ static int __init acpi_parse_madt_lapic_
 #endif				/* CONFIG_X86_LOCAL_APIC */
 
 #ifdef	CONFIG_X86_IO_APIC
-#define MP_ISA_BUS		0
-
-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
-{
-	int ioapic;
-	int pin;
-	struct mpc_intsrc mp_irq;
-
-	/*
-	 * Convert 'gsi' to 'ioapic.pin'.
-	 */
-	ioapic = mp_find_ioapic(gsi);
-	if (ioapic < 0)
-		return;
-	pin = mp_find_ioapic_pin(ioapic, gsi);
-
-	/*
-	 * TBD: This check is for faulty timer entries, where the override
-	 *      erroneously sets the trigger to level, resulting in a HUGE
-	 *      increase of timer interrupts!
-	 */
-	if ((bus_irq == 0) && (trigger == 3))
-		trigger = 1;
-
-	mp_irq.type = MP_INTSRC;
-	mp_irq.irqtype = mp_INT;
-	mp_irq.irqflag = (trigger << 2) | polarity;
-	mp_irq.srcbus = MP_ISA_BUS;
-	mp_irq.srcbusirq = bus_irq;	/* IRQ */
-	mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
-	mp_irq.dstirq = pin;	/* INTIN# */
-
-	mp_save_irq(&mp_irq);
-
-	isa_irq_to_gsi[bus_irq] = gsi;
-}
-
-void __init mp_config_acpi_legacy_irqs(void)
+static void __init mp_config_acpi_legacy_irqs(void)
 {
 	int i;
 	struct mpc_intsrc mp_irq;
@@ -956,7 +1013,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	 * Use the default configuration for the IRQs 0-15.  Unless
 	 * overridden by (MADT) interrupt source override entries.
 	 */
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < nr_legacy_irqs(); i++) {
 		int ioapic, pin;
 		unsigned int dstapic;
 		int idx;
@@ -1004,84 +1061,6 @@ void __init mp_config_acpi_legacy_irqs(v
 	}
 }
 
-static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
-			int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
-	struct mpc_intsrc mp_irq;
-	struct pci_dev *pdev;
-	unsigned char number;
-	unsigned int devfn;
-	int ioapic;
-	u8 pin;
-
-	if (!acpi_ioapic)
-		return 0;
-	if (!dev || !dev_is_pci(dev))
-		return 0;
-
-	pdev = to_pci_dev(dev);
-	number = pdev->bus->number;
-	devfn = pdev->devfn;
-	pin = pdev->pin;
-	/* print the entry should happen on mptable identically */
-	mp_irq.type = MP_INTSRC;
-	mp_irq.irqtype = mp_INT;
-	mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
-				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
-	mp_irq.srcbus = number;
-	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
-	ioapic = mp_find_ioapic(gsi);
-	mp_irq.dstapic = mpc_ioapic_id(ioapic);
-	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-
-	mp_save_irq(&mp_irq);
-#endif
-	return 0;
-}
-
-int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
-{
-	int ioapic;
-	int ioapic_pin;
-	struct io_apic_irq_attr irq_attr;
-	int ret;
-
-	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
-		return gsi;
-
-	/* Don't set up the ACPI SCI because it's already set up */
-	if (acpi_gbl_FADT.sci_interrupt == gsi)
-		return gsi;
-
-	ioapic = mp_find_ioapic(gsi);
-	if (ioapic < 0) {
-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
-		return gsi;
-	}
-
-	ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
-	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
-		       "%d-%d\n", mpc_ioapic_id(ioapic),
-		       ioapic_pin);
-		return gsi;
-	}
-
-	if (enable_update_mptable)
-		mp_config_acpi_gsi(dev, gsi, trigger, polarity);
-
-	set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
-			     trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
-			     polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-	ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
-	if (ret < 0)
-		gsi = INT_MIN;
-
-	return gsi;
-}
-
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
@@ -1111,9 +1090,8 @@ static int __init acpi_parse_madt_ioapic
 		return -ENODEV;
 	}
 
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
-				  MAX_IO_APICS);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+				      MAX_IO_APICS);
 	if (!count) {
 		printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
 		return -ENODEV;
@@ -1122,9 +1100,8 @@ static int __init acpi_parse_madt_ioapic
 		return count;
 	}
 
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
-				  nr_irqs);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+				      acpi_parse_int_src_ovr, nr_irqs);
 	if (count < 0) {
 		printk(KERN_ERR PREFIX
 		       "Error parsing interrupt source overrides entry\n");
@@ -1143,9 +1120,8 @@ static int __init acpi_parse_madt_ioapic
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
 
-	count =
-	    acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
-				  nr_irqs);
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+				      acpi_parse_nmi_src, nr_irqs);
 	if (count < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
 		/* TBD: Cleanup to allow fallback to MPS */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/acpi/Makefile linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/Makefile
--- linux-libre-3.16-gnu/arch/x86/kernel/acpi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/acpi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,6 @@
 obj-$(CONFIG_ACPI)		+= boot.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup_$(BITS).o
+obj-$(CONFIG_ACPI_APEI)		+= apei.o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
 obj-y				+= cstate.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/apic.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/apic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apic
 /*
  * The highest APIC ID seen during enumeration.
  */
-unsigned int max_physical_apicid;
+static unsigned int max_physical_apicid;
 
 /*
  * Bitmask of physically existing CPUs:
@@ -1342,17 +1342,6 @@ void setup_local_APIC(void)
 	/* always use the value from LDR */
 	early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
 		logical_smp_processor_id();
-
-	/*
-	 * Some NUMA implementations (NUMAQ) don't initialize apicid to
-	 * node mapping during NUMA init.  Now that logical apicid is
-	 * guaranteed to be known, give it another chance.  This is already
-	 * a bit too late - percpu allocation has already happened without
-	 * proper NUMA affinity.
-	 */
-	if (apic->x86_32_numa_cpu_node)
-		set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu),
-				   apic->x86_32_numa_cpu_node(cpu));
 #endif
 
 	/*
@@ -2053,8 +2042,6 @@ void __init connect_bsp_APIC(void)
 		imcr_pic_to_apic();
 	}
 #endif
-	if (apic->enable_apic_mode)
-		apic->enable_apic_mode();
 }
 
 /**
@@ -2451,51 +2438,6 @@ static void apic_pm_activate(void) { }
 
 #ifdef CONFIG_X86_64
 
-static int apic_cluster_num(void)
-{
-	int i, clusters, zeros;
-	unsigned id;
-	u16 *bios_cpu_apicid;
-	DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
-
-	bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
-	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		/* are we being called early in kernel startup? */
-		if (bios_cpu_apicid) {
-			id = bios_cpu_apicid[i];
-		} else if (i < nr_cpu_ids) {
-			if (cpu_present(i))
-				id = per_cpu(x86_bios_cpu_apicid, i);
-			else
-				continue;
-		} else
-			break;
-
-		if (id != BAD_APICID)
-			__set_bit(APIC_CLUSTERID(id), clustermap);
-	}
-
-	/* Problem:  Partially populated chassis may not have CPUs in some of
-	 * the APIC clusters they have been allocated.  Only present CPUs have
-	 * x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap.
-	 * Since clusters are allocated sequentially, count zeros only if
-	 * they are bounded by ones.
-	 */
-	clusters = 0;
-	zeros = 0;
-	for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
-		if (test_bit(i, clustermap)) {
-			clusters += 1 + zeros;
-			zeros = 0;
-		} else
-			++zeros;
-	}
-
-	return clusters;
-}
-
 static int multi_checked;
 static int multi;
 
@@ -2540,20 +2482,7 @@ static void dmi_check_multi(void)
 int apic_is_clustered_box(void)
 {
 	dmi_check_multi();
-	if (multi)
-		return 1;
-
-	if (!is_vsmp_box())
-		return 0;
-
-	/*
-	 * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
-	 * not guaranteed to be synced between boards
-	 */
-	if (apic_cluster_num() > 1)
-		return 1;
-
-	return 0;
+	return multi;
 }
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_flat_64.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_flat_64.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_flat_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_flat_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -168,21 +168,16 @@ static struct apic apic_flat =  {
 	.disable_esr			= 0,
 	.dest_logical			= APIC_DEST_LOGICAL,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= flat_vector_allocation_domain,
 	.init_apic_ldr			= flat_init_apic_ldr,
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= flat_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= flat_get_apic_id,
 	.set_apic_id			= set_apic_id,
@@ -196,10 +191,7 @@ static struct apic apic_flat =  {
 	.send_IPI_all			= flat_send_IPI_all,
 	.send_IPI_self			= apic_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
 	.read				= native_apic_mem_read,
@@ -283,7 +275,6 @@ static struct apic apic_physflat =  {
 	.disable_esr			= 0,
 	.dest_logical			= 0,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= default_vector_allocation_domain,
 	/* not needed, but shouldn't hurt: */
@@ -291,14 +282,10 @@ static struct apic apic_physflat =  {
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= flat_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= flat_get_apic_id,
 	.set_apic_id			= set_apic_id,
@@ -312,10 +299,7 @@ static struct apic apic_physflat =  {
 	.send_IPI_all			= physflat_send_IPI_all,
 	.send_IPI_self			= apic_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
 	.read				= native_apic_mem_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_noop.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_noop.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_noop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_noop.c	2014-09-28 17:29:07.000000000 -0400
@@ -89,16 +89,6 @@ static const struct cpumask *noop_target
 	return cpumask_of(0);
 }
 
-static unsigned long noop_check_apicid_used(physid_mask_t *map, int apicid)
-{
-	return physid_isset(apicid, *map);
-}
-
-static unsigned long noop_check_apicid_present(int bit)
-{
-	return physid_isset(bit, phys_cpu_present_map);
-}
-
 static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
 					  const struct cpumask *mask)
 {
@@ -133,27 +123,21 @@ struct apic apic_noop = {
 	.target_cpus			= noop_target_cpus,
 	.disable_esr			= 0,
 	.dest_logical			= APIC_DEST_LOGICAL,
-	.check_apicid_used		= noop_check_apicid_used,
-	.check_apicid_present		= noop_check_apicid_present,
+	.check_apicid_used		= default_check_apicid_used,
 
 	.vector_allocation_domain	= noop_vector_allocation_domain,
 	.init_apic_ldr			= noop_init_apic_ldr,
 
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 
 	.phys_pkg_id			= noop_phys_pkg_id,
 
-	.mps_oem_check			= NULL,
-
 	.get_apic_id			= noop_get_apic_id,
 	.set_apic_id			= NULL,
 	.apic_id_mask			= 0x0F << 24,
@@ -168,12 +152,7 @@ struct apic apic_noop = {
 
 	.wakeup_secondary_cpu		= noop_wakeup_secondary_cpu,
 
-	/* should be safe */
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
 	.read				= noop_apic_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_numachip.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_numachip.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/apic_numachip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/apic_numachip.c	2014-09-28 17:29:07.000000000 -0400
@@ -217,21 +217,16 @@ static const struct apic apic_numachip _
 	.disable_esr			= 0,
 	.dest_logical			= 0,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= default_vector_allocation_domain,
 	.init_apic_ldr			= flat_init_apic_ldr,
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= numachip_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= get_apic_id,
 	.set_apic_id			= set_apic_id,
@@ -246,10 +241,7 @@ static const struct apic apic_numachip _
 	.send_IPI_self			= numachip_send_IPI_self,
 
 	.wakeup_secondary_cpu		= numachip_wakeup_secondary,
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL, /* REMRD not supported */
 
 	.read				= native_apic_mem_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/bigsmp_32.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/bigsmp_32.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/bigsmp_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/bigsmp_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,11 +31,6 @@ static unsigned long bigsmp_check_apicid
 	return 0;
 }
 
-static unsigned long bigsmp_check_apicid_present(int bit)
-{
-	return 1;
-}
-
 static int bigsmp_early_logical_apicid(int cpu)
 {
 	/* on bigsmp, logical apicid is the same as physical */
@@ -168,21 +163,16 @@ static struct apic apic_bigsmp = {
 	.disable_esr			= 1,
 	.dest_logical			= 0,
 	.check_apicid_used		= bigsmp_check_apicid_used,
-	.check_apicid_present		= bigsmp_check_apicid_present,
 
 	.vector_allocation_domain	= default_vector_allocation_domain,
 	.init_apic_ldr			= bigsmp_init_apic_ldr,
 
 	.ioapic_phys_id_map		= bigsmp_ioapic_phys_id_map,
 	.setup_apic_routing		= bigsmp_setup_apic_routing,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= bigsmp_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= bigsmp_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= bigsmp_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= bigsmp_get_apic_id,
 	.set_apic_id			= NULL,
@@ -196,11 +186,7 @@ static struct apic apic_bigsmp = {
 	.send_IPI_all			= bigsmp_send_IPI_all,
 	.send_IPI_self			= default_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
 	.wait_for_init_deassert		= true,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
 	.read				= native_apic_mem_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/io_apic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/io_apic.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
 #include <linux/freezer.h>
@@ -62,6 +63,16 @@
 
 #define __apicdebuginit(type) static type __init
 
+#define	for_each_ioapic(idx)		\
+	for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
+#define	for_each_ioapic_reverse(idx)	\
+	for ((idx) = nr_ioapics - 1; (idx) >= 0; (idx)--)
+#define	for_each_pin(idx, pin)		\
+	for ((pin) = 0; (pin) < ioapics[(idx)].nr_registers; (pin)++)
+#define	for_each_ioapic_pin(idx, pin)	\
+	for_each_ioapic((idx))		\
+		for_each_pin((idx), (pin))
+
 #define for_each_irq_pin(entry, head) \
 	for (entry = head; entry; entry = entry->next)
 
@@ -73,6 +84,17 @@ int sis_apic_bug = -1;
 
 static DEFINE_RAW_SPINLOCK(ioapic_lock);
 static DEFINE_RAW_SPINLOCK(vector_lock);
+static DEFINE_MUTEX(ioapic_mutex);
+static unsigned int ioapic_dynirq_base;
+static int ioapic_initialized;
+
+struct mp_pin_info {
+	int trigger;
+	int polarity;
+	int node;
+	int set;
+	u32 count;
+};
 
 static struct ioapic {
 	/*
@@ -87,7 +109,9 @@ static struct ioapic {
 	struct mpc_ioapic mp_config;
 	/* IO APIC gsi routing info */
 	struct mp_ioapic_gsi  gsi_config;
-	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+	struct ioapic_domain_cfg irqdomain_cfg;
+	struct irq_domain *irqdomain;
+	struct mp_pin_info *pin_info;
 } ioapics[MAX_IO_APICS];
 
 #define mpc_ioapic_ver(ioapic_idx)	ioapics[ioapic_idx].mp_config.apicver
@@ -107,6 +131,41 @@ struct mp_ioapic_gsi *mp_ioapic_gsi_rout
 	return &ioapics[ioapic_idx].gsi_config;
 }
 
+static inline int mp_ioapic_pin_count(int ioapic)
+{
+	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+	return gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
+}
+
+u32 mp_pin_to_gsi(int ioapic, int pin)
+{
+	return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
+}
+
+/*
+ * Initialize all legacy IRQs and all pins on the first IOAPIC
+ * if we have legacy interrupt controller. Kernel boot option "pirq="
+ * may rely on non-legacy pins on the first IOAPIC.
+ */
+static inline int mp_init_irq_at_boot(int ioapic, int irq)
+{
+	if (!nr_legacy_irqs())
+		return 0;
+
+	return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
+}
+
+static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin)
+{
+	return ioapics[ioapic_idx].pin_info + pin;
+}
+
+static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
+{
+	return ioapics[ioapic].irqdomain;
+}
+
 int nr_ioapics;
 
 /* The one past the highest gsi number used */
@@ -118,9 +177,6 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCE
 /* # of MP IRQ source entries */
 int mp_irq_entries;
 
-/* GSI interrupts */
-static int nr_irqs_gsi = NR_IRQS_LEGACY;
-
 #ifdef CONFIG_EISA
 int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
@@ -149,8 +205,7 @@ static int __init parse_noapic(char *str
 }
 early_param("noapic", parse_noapic);
 
-static int io_apic_setup_irq_pin(unsigned int irq, int node,
-				 struct io_apic_irq_attr *attr);
+static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node);
 
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
@@ -182,19 +237,15 @@ static struct irq_pin_list *alloc_irq_pi
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
-	int count, node, i;
+	int i, node = cpu_to_node(0);
 
-	if (!legacy_pic->nr_legacy_irqs)
+	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
 
-	for (i = 0; i < nr_ioapics; i++) {
+	for_each_ioapic(i) {
 		ioapics[i].saved_registers =
 			kzalloc(sizeof(struct IO_APIC_route_entry) *
 				ioapics[i].nr_registers, GFP_KERNEL);
@@ -202,28 +253,20 @@ int __init arch_early_irq_init(void)
 			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
 	}
 
-	cfg = irq_cfgx;
-	count = ARRAY_SIZE(irq_cfgx);
-	node = cpu_to_node(0);
-
-	for (i = 0; i < count; i++) {
-		irq_set_chip_data(i, &cfg[i]);
-		zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
-		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
-		/*
-		 * For legacy IRQ's, start with assigning irq0 to irq15 to
-		 * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
-		 */
-		if (i < legacy_pic->nr_legacy_irqs) {
-			cfg[i].vector = IRQ0_VECTOR + i;
-			cpumask_setall(cfg[i].domain);
-		}
+	/*
+	 * For legacy IRQ's, start with assigning irq0 to irq15 to
+	 * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+	 */
+	for (i = 0; i < nr_legacy_irqs(); i++) {
+		cfg = alloc_irq_and_cfg_at(i, node);
+		cfg->vector = IRQ0_VECTOR + i;
+		cpumask_setall(cfg->domain);
 	}
 
 	return 0;
 }
 
-static struct irq_cfg *irq_cfg(unsigned int irq)
+static inline struct irq_cfg *irq_cfg(unsigned int irq)
 {
 	return irq_get_chip_data(irq);
 }
@@ -265,7 +308,7 @@ static struct irq_cfg *alloc_irq_and_cfg
 	if (res < 0) {
 		if (res != -EEXIST)
 			return NULL;
-		cfg = irq_get_chip_data(at);
+		cfg = irq_cfg(at);
 		if (cfg)
 			return cfg;
 	}
@@ -425,6 +468,21 @@ static int __add_pin_to_irq_node(struct
 	return 0;
 }
 
+static void __remove_pin_from_irq(struct irq_cfg *cfg, int apic, int pin)
+{
+	struct irq_pin_list **last, *entry;
+
+	last = &cfg->irq_2_pin;
+	for_each_irq_pin(entry, cfg->irq_2_pin)
+		if (entry->apic == apic && entry->pin == pin) {
+			*last = entry->next;
+			kfree(entry);
+			return;
+		} else {
+			last = &entry->next;
+		}
+}
+
 static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
 	if (__add_pin_to_irq_node(cfg, node, apic, pin))
@@ -627,9 +685,8 @@ static void clear_IO_APIC (void)
 {
 	int apic, pin;
 
-	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
-			clear_IO_APIC_pin(apic, pin);
+	for_each_ioapic_pin(apic, pin)
+		clear_IO_APIC_pin(apic, pin);
 }
 
 #ifdef CONFIG_X86_32
@@ -678,13 +735,13 @@ int save_ioapic_entries(void)
 	int apic, pin;
 	int err = 0;
 
-	for (apic = 0; apic < nr_ioapics; apic++) {
+	for_each_ioapic(apic) {
 		if (!ioapics[apic].saved_registers) {
 			err = -ENOMEM;
 			continue;
 		}
 
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+		for_each_pin(apic, pin)
 			ioapics[apic].saved_registers[pin] =
 				ioapic_read_entry(apic, pin);
 	}
@@ -699,11 +756,11 @@ void mask_ioapic_entries(void)
 {
 	int apic, pin;
 
-	for (apic = 0; apic < nr_ioapics; apic++) {
+	for_each_ioapic(apic) {
 		if (!ioapics[apic].saved_registers)
 			continue;
 
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
+		for_each_pin(apic, pin) {
 			struct IO_APIC_route_entry entry;
 
 			entry = ioapics[apic].saved_registers[pin];
@@ -722,11 +779,11 @@ int restore_ioapic_entries(void)
 {
 	int apic, pin;
 
-	for (apic = 0; apic < nr_ioapics; apic++) {
+	for_each_ioapic(apic) {
 		if (!ioapics[apic].saved_registers)
 			continue;
 
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+		for_each_pin(apic, pin)
 			ioapic_write_entry(apic, pin,
 					   ioapics[apic].saved_registers[pin]);
 	}
@@ -785,7 +842,7 @@ static int __init find_isa_irq_apic(int
 	if (i < mp_irq_entries) {
 		int ioapic_idx;
 
-		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		for_each_ioapic(ioapic_idx)
 			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
 				return ioapic_idx;
 	}
@@ -799,7 +856,7 @@ static int __init find_isa_irq_apic(int
  */
 static int EISA_ELCR(unsigned int irq)
 {
-	if (irq < legacy_pic->nr_legacy_irqs) {
+	if (irq < nr_legacy_irqs()) {
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
@@ -939,29 +996,106 @@ static int irq_trigger(int idx)
 	return trigger;
 }
 
-static int pin_2_irq(int idx, int apic, int pin)
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
+{
+	int irq = -1;
+	int ioapic = (int)(long)domain->host_data;
+	int type = ioapics[ioapic].irqdomain_cfg.type;
+
+	switch (type) {
+	case IOAPIC_DOMAIN_LEGACY:
+		/*
+		 * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
+		 * GSIs on some weird platforms.
+		 */
+		if (gsi < nr_legacy_irqs())
+			irq = irq_create_mapping(domain, pin);
+		else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+			irq = gsi;
+		break;
+	case IOAPIC_DOMAIN_STRICT:
+		if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+			irq = gsi;
+		break;
+	case IOAPIC_DOMAIN_DYNAMIC:
+		irq = irq_create_mapping(domain, pin);
+		break;
+	default:
+		WARN(1, "ioapic: unknown irqdomain type %d\n", type);
+		break;
+	}
+
+	return irq > 0 ? irq : -1;
+}
+
+static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
+			     unsigned int flags)
 {
 	int irq;
-	int bus = mp_irqs[idx].srcbus;
-	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
+	struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+	struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+
+	if (!domain)
+		return -1;
+
+	mutex_lock(&ioapic_mutex);
 
 	/*
-	 * Debugging check, we are in big trouble if this message pops up!
+	 * Don't use irqdomain to manage ISA IRQs because there may be
+	 * multiple IOAPIC pins sharing the same ISA IRQ number and
+	 * irqdomain only supports 1:1 mapping between IOAPIC pin and
+	 * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
+	 * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
+	 * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
+	 * available, and some BIOSes may use MP Interrupt Source records
+	 * to override IRQ numbers for PIRQs instead of reprogramming
+	 * the interrupt routing logic. Thus there may be multiple pins
+	 * sharing the same legacy IRQ number when ACPI is disabled.
 	 */
-	if (mp_irqs[idx].dstirq != pin)
-		pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
-
-	if (test_bit(bus, mp_bus_not_pci)) {
+	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
+		if (flags & IOAPIC_MAP_ALLOC) {
+			if (info->count == 0 &&
+			    mp_irqdomain_map(domain, irq, pin) != 0)
+				irq = -1;
+
+			/* special handling for timer IRQ0 */
+			if (irq == 0)
+				info->count++;
+		}
 	} else {
-		u32 gsi = gsi_cfg->gsi_base + pin;
+		irq = irq_find_mapping(domain, pin);
+		if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
+			irq = alloc_irq_from_domain(domain, gsi, pin);
+	}
 
-		if (gsi >= NR_IRQS_LEGACY)
-			irq = gsi;
-		else
-			irq = gsi_top + gsi;
+	if (flags & IOAPIC_MAP_ALLOC) {
+		/* special handling for legacy IRQs */
+		if (irq < nr_legacy_irqs() && info->count == 1 &&
+		    mp_irqdomain_map(domain, irq, pin) != 0)
+			irq = -1;
+
+		if (irq > 0)
+			info->count++;
+		else if (info->count == 0)
+			info->set = 0;
 	}
 
+	mutex_unlock(&ioapic_mutex);
+
+	return irq > 0 ? irq : -1;
+}
+
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
+{
+	u32 gsi = mp_pin_to_gsi(ioapic, pin);
+
+	/*
+	 * Debugging check, we are in big trouble if this message pops up!
+	 */
+	if (mp_irqs[idx].dstirq != pin)
+		pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
+
 #ifdef CONFIG_X86_32
 	/*
 	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -972,16 +1106,58 @@ static int pin_2_irq(int idx, int apic,
 				apic_printk(APIC_VERBOSE, KERN_DEBUG
 						"disabling PIRQ%d\n", pin-16);
 			} else {
-				irq = pirq_entries[pin-16];
+				int irq = pirq_entries[pin-16];
 				apic_printk(APIC_VERBOSE, KERN_DEBUG
 						"using PIRQ%d -> IRQ %d\n",
 						pin-16, irq);
+				return irq;
 			}
 		}
 	}
 #endif
 
-	return irq;
+	return  mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}
+
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+{
+	int ioapic, pin, idx;
+
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0)
+		return -1;
+
+	pin = mp_find_ioapic_pin(ioapic, gsi);
+	idx = find_irq_entry(ioapic, pin, mp_INT);
+	if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
+		return -1;
+
+	return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}
+
+void mp_unmap_irq(int irq)
+{
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct mp_pin_info *info;
+	int ioapic, pin;
+
+	if (!data || !data->domain)
+		return;
+
+	ioapic = (int)(long)data->domain->host_data;
+	pin = (int)data->hwirq;
+	info = mp_pin_info(ioapic, pin);
+
+	mutex_lock(&ioapic_mutex);
+	if (--info->count == 0) {
+		info->set = 0;
+		if (irq < nr_legacy_irqs() &&
+		    ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY)
+			mp_irqdomain_unmap(data->domain, irq);
+		else
+			irq_dispose_mapping(irq);
+	}
+	mutex_unlock(&ioapic_mutex);
 }
 
 /*
@@ -991,7 +1167,7 @@ static int pin_2_irq(int idx, int apic,
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
 				struct io_apic_irq_attr *irq_attr)
 {
-	int ioapic_idx, i, best_guess = -1;
+	int irq, i, best_ioapic = -1, best_idx = -1;
 
 	apic_printk(APIC_DEBUG,
 		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1001,44 +1177,56 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 			    "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
 	}
+
 	for (i = 0; i < mp_irq_entries; i++) {
 		int lbus = mp_irqs[i].srcbus;
+		int ioapic_idx, found = 0;
 
-		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		if (bus != lbus || mp_irqs[i].irqtype != mp_INT ||
+		    slot != ((mp_irqs[i].srcbusirq >> 2) & 0x1f))
+			continue;
+
+		for_each_ioapic(ioapic_idx)
 			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
-			    mp_irqs[i].dstapic == MP_APIC_ALL)
+			    mp_irqs[i].dstapic == MP_APIC_ALL) {
+				found = 1;
 				break;
+			}
+		if (!found)
+			continue;
 
-		if (!test_bit(lbus, mp_bus_not_pci) &&
-		    !mp_irqs[i].irqtype &&
-		    (bus == lbus) &&
-		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
+		/* Skip ISA IRQs */
+		irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq, 0);
+		if (irq > 0 && !IO_APIC_IRQ(irq))
+			continue;
 
-			if (!(ioapic_idx || IO_APIC_IRQ(irq)))
-				continue;
+		if (pin == (mp_irqs[i].srcbusirq & 3)) {
+			best_idx = i;
+			best_ioapic = ioapic_idx;
+			goto out;
+		}
 
-			if (pin == (mp_irqs[i].srcbusirq & 3)) {
-				set_io_apic_irq_attr(irq_attr, ioapic_idx,
-						     mp_irqs[i].dstirq,
-						     irq_trigger(i),
-						     irq_polarity(i));
-				return irq;
-			}
-			/*
-			 * Use the first all-but-pin matching entry as a
-			 * best-guess fuzzy result for broken mptables.
-			 */
-			if (best_guess < 0) {
-				set_io_apic_irq_attr(irq_attr, ioapic_idx,
-						     mp_irqs[i].dstirq,
-						     irq_trigger(i),
-						     irq_polarity(i));
-				best_guess = irq;
-			}
+		/*
+		 * Use the first all-but-pin matching entry as a
+		 * best-guess fuzzy result for broken mptables.
+		 */
+		if (best_idx < 0) {
+			best_idx = i;
+			best_ioapic = ioapic_idx;
 		}
 	}
-	return best_guess;
+	if (best_idx < 0)
+		return -1;
+
+out:
+	irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq,
+			IOAPIC_MAP_ALLOC);
+	if (irq > 0)
+		set_io_apic_irq_attr(irq_attr, best_ioapic,
+				     mp_irqs[best_idx].dstirq,
+				     irq_trigger(best_idx),
+				     irq_polarity(best_idx));
+	return irq;
 }
 EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 
@@ -1198,7 +1386,7 @@ void __setup_vector_irq(int cpu)
 	raw_spin_lock(&vector_lock);
 	/* Mark the inuse vectors */
 	for_each_active_irq(irq) {
-		cfg = irq_get_chip_data(irq);
+		cfg = irq_cfg(irq);
 		if (!cfg)
 			continue;
 
@@ -1227,12 +1415,10 @@ static inline int IO_APIC_irq_trigger(in
 {
 	int apic, idx, pin;
 
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
-			idx = find_irq_entry(apic, pin, mp_INT);
-			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-				return irq_trigger(idx);
-		}
+	for_each_ioapic_pin(apic, pin) {
+		idx = find_irq_entry(apic, pin, mp_INT);
+		if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
+			return irq_trigger(idx);
 	}
 	/*
          * nonexistent IRQs are edge default
@@ -1330,95 +1516,29 @@ static void setup_ioapic_irq(unsigned in
 	}
 
 	ioapic_register_intr(irq, cfg, attr->trigger);
-	if (irq < legacy_pic->nr_legacy_irqs)
+	if (irq < nr_legacy_irqs())
 		legacy_pic->mask(irq);
 
 	ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
 }
 
-static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin)
-{
-	if (idx != -1)
-		return false;
-
-	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
-		    mpc_ioapic_id(ioapic_idx), pin);
-	return true;
-}
-
-static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
-{
-	int idx, node = cpu_to_node(0);
-	struct io_apic_irq_attr attr;
-	unsigned int pin, irq;
-
-	for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
-		idx = find_irq_entry(ioapic_idx, pin, mp_INT);
-		if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
-			continue;
-
-		irq = pin_2_irq(idx, ioapic_idx, pin);
-
-		if ((ioapic_idx > 0) && (irq > 16))
-			continue;
-
-		/*
-		 * Skip the timer IRQ if there's a quirk handler
-		 * installed and if it returns 1:
-		 */
-		if (apic->multi_timer_check &&
-		    apic->multi_timer_check(ioapic_idx, irq))
-			continue;
-
-		set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
-				     irq_polarity(idx));
-
-		io_apic_setup_irq_pin(irq, node, &attr);
-	}
-}
-
 static void __init setup_IO_APIC_irqs(void)
 {
-	unsigned int ioapic_idx;
+	unsigned int ioapic, pin;
+	int idx;
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
-		__io_apic_setup_irqs(ioapic_idx);
-}
-
-/*
- * for the gsit that is not in first ioapic
- * but could not use acpi_register_gsi()
- * like some special sci in IBM x3330
- */
-void setup_IO_APIC_irq_extra(u32 gsi)
-{
-	int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
-	struct io_apic_irq_attr attr;
-
-	/*
-	 * Convert 'gsi' to 'ioapic.pin'.
-	 */
-	ioapic_idx = mp_find_ioapic(gsi);
-	if (ioapic_idx < 0)
-		return;
-
-	pin = mp_find_ioapic_pin(ioapic_idx, gsi);
-	idx = find_irq_entry(ioapic_idx, pin, mp_INT);
-	if (idx == -1)
-		return;
-
-	irq = pin_2_irq(idx, ioapic_idx, pin);
-
-	/* Only handle the non legacy irqs on secondary ioapics */
-	if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
-		return;
-
-	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
-			     irq_polarity(idx));
-
-	io_apic_setup_irq_pin_once(irq, node, &attr);
+	for_each_ioapic_pin(ioapic, pin) {
+		idx = find_irq_entry(ioapic, pin, mp_INT);
+		if (idx < 0)
+			apic_printk(APIC_VERBOSE,
+				    KERN_DEBUG " apic %d pin %d not connected\n",
+				    mpc_ioapic_id(ioapic), pin);
+		else
+			pin_2_irq(idx, ioapic, pin,
+				  ioapic ? 0 : IOAPIC_MAP_ALLOC);
+	}
 }
 
 /*
@@ -1586,7 +1706,7 @@ __apicdebuginit(void) print_IO_APICs(voi
 	struct irq_chip *chip;
 
 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
-	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+	for_each_ioapic(ioapic_idx)
 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
 		       mpc_ioapic_id(ioapic_idx),
 		       ioapics[ioapic_idx].nr_registers);
@@ -1597,7 +1717,7 @@ __apicdebuginit(void) print_IO_APICs(voi
 	 */
 	printk(KERN_INFO "testing the IO APIC.......................\n");
 
-	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+	for_each_ioapic(ioapic_idx)
 		print_IO_APIC(ioapic_idx);
 
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
@@ -1608,7 +1728,7 @@ __apicdebuginit(void) print_IO_APICs(voi
 		if (chip != &ioapic_chip)
 			continue;
 
-		cfg = irq_get_chip_data(irq);
+		cfg = irq_cfg(irq);
 		if (!cfg)
 			continue;
 		entry = cfg->irq_2_pin;
@@ -1758,7 +1878,7 @@ __apicdebuginit(void) print_PIC(void)
 	unsigned int v;
 	unsigned long flags;
 
-	if (!legacy_pic->nr_legacy_irqs)
+	if (!nr_legacy_irqs())
 		return;
 
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1828,26 +1948,22 @@ static struct { int pin, apic; } ioapic_
 void __init enable_IO_APIC(void)
 {
 	int i8259_apic, i8259_pin;
-	int apic;
+	int apic, pin;
 
-	if (!legacy_pic->nr_legacy_irqs)
+	if (!nr_legacy_irqs())
 		return;
 
-	for(apic = 0; apic < nr_ioapics; apic++) {
-		int pin;
+	for_each_ioapic_pin(apic, pin) {
 		/* See if any of the pins is in ExtINT mode */
-		for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
-			struct IO_APIC_route_entry entry;
-			entry = ioapic_read_entry(apic, pin);
+		struct IO_APIC_route_entry entry = ioapic_read_entry(apic, pin);
 
-			/* If the interrupt line is enabled and in ExtInt mode
-			 * I have found the pin where the i8259 is connected.
-			 */
-			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
-				ioapic_i8259.apic = apic;
-				ioapic_i8259.pin  = pin;
-				goto found_i8259;
-			}
+		/* If the interrupt line is enabled and in ExtInt mode
+		 * I have found the pin where the i8259 is connected.
+		 */
+		if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+			ioapic_i8259.apic = apic;
+			ioapic_i8259.pin  = pin;
+			goto found_i8259;
 		}
 	}
  found_i8259:
@@ -1919,7 +2035,7 @@ void disable_IO_APIC(void)
 	 */
 	clear_IO_APIC();
 
-	if (!legacy_pic->nr_legacy_irqs)
+	if (!nr_legacy_irqs())
 		return;
 
 	x86_io_apic_ops.disable();
@@ -1950,7 +2066,7 @@ void __init setup_ioapic_ids_from_mpc_no
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
 	 */
-	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
+	for_each_ioapic(ioapic_idx) {
 		/* Read the register 0 value */
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		reg_00.raw = io_apic_read(ioapic_idx, 0);
@@ -2123,7 +2239,7 @@ static unsigned int startup_ioapic_irq(s
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	if (irq < legacy_pic->nr_legacy_irqs) {
+	if (irq < nr_legacy_irqs()) {
 		legacy_pic->mask(irq);
 		if (legacy_pic->irq_pending(irq))
 			was_pending = 1;
@@ -2225,7 +2341,7 @@ asmlinkage __visible void smp_irq_move_c
 			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
 			goto unlock;
 		}
-		__this_cpu_write(vector_irq[vector], -1);
+		__this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
 unlock:
 		raw_spin_unlock(&desc->lock);
 	}
@@ -2253,7 +2369,7 @@ static void irq_complete_move(struct irq
 
 void irq_force_complete_move(int irq)
 {
-	struct irq_cfg *cfg = irq_get_chip_data(irq);
+	struct irq_cfg *cfg = irq_cfg(irq);
 
 	if (!cfg)
 		return;
@@ -2514,26 +2630,15 @@ static inline void init_IO_APIC_traps(vo
 	struct irq_cfg *cfg;
 	unsigned int irq;
 
-	/*
-	 * NOTE! The local APIC isn't very good at handling
-	 * multiple interrupts at the same interrupt level.
-	 * As the interrupt level is determined by taking the
-	 * vector number and shifting that right by 4, we
-	 * want to spread these out a bit so that they don't
-	 * all fall in the same interrupt level.
-	 *
-	 * Also, we've got to be careful not to trash gate
-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
-	 */
 	for_each_active_irq(irq) {
-		cfg = irq_get_chip_data(irq);
+		cfg = irq_cfg(irq);
 		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
 			 * so default to an old-fashioned 8259
 			 * interrupt if we can..
 			 */
-			if (irq < legacy_pic->nr_legacy_irqs)
+			if (irq < nr_legacy_irqs())
 				legacy_pic->make_irq(irq);
 			else
 				/* Strange. Oh, well.. */
@@ -2649,8 +2754,6 @@ static int __init disable_timer_pin_setu
 }
 early_param("disable_timer_pin_1", disable_timer_pin_setup);
 
-int timer_through_8259 __initdata;
-
 /*
  * This code may look a bit paranoid, but it's supposed to cooperate with
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
@@ -2661,7 +2764,7 @@ int timer_through_8259 __initdata;
  */
 static inline void __init check_timer(void)
 {
-	struct irq_cfg *cfg = irq_get_chip_data(0);
+	struct irq_cfg *cfg = irq_cfg(0);
 	int node = cpu_to_node(0);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
@@ -2755,7 +2858,6 @@ static inline void __init check_timer(vo
 		legacy_pic->unmask(0);
 		if (timer_irq_works()) {
 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
-			timer_through_8259 = 1;
 			goto out;
 		}
 		/*
@@ -2827,15 +2929,54 @@ out:
  */
 #define PIC_IRQS	(1UL << PIC_CASCADE_IR)
 
+static int mp_irqdomain_create(int ioapic)
+{
+	size_t size;
+	int hwirqs = mp_ioapic_pin_count(ioapic);
+	struct ioapic *ip = &ioapics[ioapic];
+	struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
+	struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+	size = sizeof(struct mp_pin_info) * mp_ioapic_pin_count(ioapic);
+	ip->pin_info = kzalloc(size, GFP_KERNEL);
+	if (!ip->pin_info)
+		return -ENOMEM;
+
+	if (cfg->type == IOAPIC_DOMAIN_INVALID)
+		return 0;
+
+	ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
+					      (void *)(long)ioapic);
+	if(!ip->irqdomain) {
+		kfree(ip->pin_info);
+		ip->pin_info = NULL;
+		return -ENOMEM;
+	}
+
+	if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
+	    cfg->type == IOAPIC_DOMAIN_STRICT)
+		ioapic_dynirq_base = max(ioapic_dynirq_base,
+					 gsi_cfg->gsi_end + 1);
+
+	if (gsi_cfg->gsi_base == 0)
+		irq_set_default_host(ip->irqdomain);
+
+	return 0;
+}
+
 void __init setup_IO_APIC(void)
 {
+	int ioapic;
 
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
-	io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+	io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;
 
 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+	for_each_ioapic(ioapic)
+		BUG_ON(mp_irqdomain_create(ioapic));
+
 	/*
          * Set up IO-APIC IRQ routing.
          */
@@ -2844,8 +2985,10 @@ void __init setup_IO_APIC(void)
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
-	if (legacy_pic->nr_legacy_irqs)
+	if (nr_legacy_irqs())
 		check_timer();
+
+	ioapic_initialized = 1;
 }
 
 /*
@@ -2880,7 +3023,7 @@ static void ioapic_resume(void)
 {
 	int ioapic_idx;
 
-	for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+	for_each_ioapic_reverse(ioapic_idx)
 		resume_ioapic_id(ioapic_idx);
 
 	restore_ioapic_entries();
@@ -2926,7 +3069,7 @@ int arch_setup_hwirq(unsigned int irq, i
 
 void arch_teardown_hwirq(unsigned int irq)
 {
-	struct irq_cfg *cfg = irq_get_chip_data(irq);
+	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long flags;
 
 	free_remapped_irq(irq);
@@ -3053,7 +3196,7 @@ int setup_msi_irq(struct pci_dev *dev, s
 	if (!irq_offset)
 		write_msi_msg(irq, &msg);
 
-	setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+	setup_remapped_irq(irq, irq_cfg(irq), chip);
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 
@@ -3192,7 +3335,7 @@ int default_setup_hpet_msi(unsigned int
 
 	hpet_msi_write(irq_get_handler_data(irq), &msg);
 	irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-	setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+	setup_remapped_irq(irq, irq_cfg(irq), chip);
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 	return 0;
@@ -3303,27 +3446,6 @@ io_apic_setup_irq_pin(unsigned int irq,
 	return ret;
 }
 
-int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-			       struct io_apic_irq_attr *attr)
-{
-	unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
-	int ret;
-	struct IO_APIC_route_entry orig_entry;
-
-	/* Avoid redundant programming */
-	if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n", mpc_ioapic_id(ioapic_idx), pin);
-		orig_entry = ioapic_read_entry(attr->ioapic, pin);
-		if (attr->trigger == orig_entry.trigger && attr->polarity == orig_entry.polarity)
-			return 0;
-		return -EBUSY;
-	}
-	ret = io_apic_setup_irq_pin(irq, node, attr);
-	if (!ret)
-		set_bit(pin, ioapics[ioapic_idx].pin_programmed);
-	return ret;
-}
-
 static int __init io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
@@ -3340,20 +3462,13 @@ static int __init io_apic_get_redir_entr
 	return reg_01.bits.entries + 1;
 }
 
-static void __init probe_nr_irqs_gsi(void)
-{
-	int nr;
-
-	nr = gsi_top + NR_IRQS_LEGACY;
-	if (nr > nr_irqs_gsi)
-		nr_irqs_gsi = nr;
-
-	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
-}
-
 unsigned int arch_dynirq_lower_bound(unsigned int from)
 {
-	return from < nr_irqs_gsi ? nr_irqs_gsi : from;
+	/*
+	 * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
+	 * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
+	 */
+	return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
 }
 
 int __init arch_probe_nr_irqs(void)
@@ -3363,33 +3478,17 @@ int __init arch_probe_nr_irqs(void)
 	if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
 		nr_irqs = NR_VECTORS * nr_cpu_ids;
 
-	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+	nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 16;
+	nr += gsi_top * 16;
 #endif
 	if (nr < nr_irqs)
 		nr_irqs = nr;
 
-	return NR_IRQS_LEGACY;
-}
-
-int io_apic_set_pci_routing(struct device *dev, int irq,
-			    struct io_apic_irq_attr *irq_attr)
-{
-	int node;
-
-	if (!IO_APIC_IRQ(irq)) {
-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
-			    irq_attr->ioapic);
-		return -EINVAL;
-	}
-
-	node = dev ? dev_to_node(dev) : cpu_to_node(0);
-
-	return io_apic_setup_irq_pin_once(irq, node, irq_attr);
+	return 0;
 }
 
 #ifdef CONFIG_X86_32
@@ -3483,9 +3582,8 @@ static u8 __init io_apic_unique_id(u8 id
 	DECLARE_BITMAP(used, 256);
 
 	bitmap_zero(used, 256);
-	for (i = 0; i < nr_ioapics; i++) {
+	for_each_ioapic(i)
 		__set_bit(mpc_ioapic_id(i), used);
-	}
 	if (!test_bit(id, used))
 		return id;
 	return find_first_zero_bit(used, 256);
@@ -3543,14 +3641,13 @@ void __init setup_ioapic_dest(void)
 	if (skip_ioapic_setup == 1)
 		return;
 
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
-	for (pin = 0; pin < ioapics[ioapic].nr_registers; pin++) {
+	for_each_ioapic_pin(ioapic, pin) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
-		irq = pin_2_irq(irq_entry, ioapic, pin);
 
-		if ((ioapic > 0) && (irq > 16))
+		irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+		if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
 			continue;
 
 		idata = irq_get_irq_data(irq);
@@ -3573,29 +3670,33 @@ void __init setup_ioapic_dest(void)
 
 static struct resource *ioapic_resources;
 
-static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+static struct resource * __init ioapic_setup_resources(void)
 {
 	unsigned long n;
 	struct resource *res;
 	char *mem;
-	int i;
+	int i, num = 0;
 
-	if (nr_ioapics <= 0)
+	for_each_ioapic(i)
+		num++;
+	if (num == 0)
 		return NULL;
 
 	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
-	n *= nr_ioapics;
+	n *= num;
 
 	mem = alloc_bootmem(n);
 	res = (void *)mem;
 
-	mem += sizeof(struct resource) * nr_ioapics;
+	mem += sizeof(struct resource) * num;
 
-	for (i = 0; i < nr_ioapics; i++) {
-		res[i].name = mem;
-		res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	num = 0;
+	for_each_ioapic(i) {
+		res[num].name = mem;
+		res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 		snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
 		mem += IOAPIC_RESOURCE_NAME_SIZE;
+		num++;
 	}
 
 	ioapic_resources = res;
@@ -3609,8 +3710,8 @@ void __init native_io_apic_init_mappings
 	struct resource *ioapic_res;
 	int i;
 
-	ioapic_res = ioapic_setup_resources(nr_ioapics);
-	for (i = 0; i < nr_ioapics; i++) {
+	ioapic_res = ioapic_setup_resources();
+	for_each_ioapic(i) {
 		if (smp_found_config) {
 			ioapic_phys = mpc_ioapic_addr(i);
 #ifdef CONFIG_X86_32
@@ -3641,8 +3742,6 @@ fake_ioapic_page:
 		ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
 		ioapic_res++;
 	}
-
-	probe_nr_irqs_gsi();
 }
 
 void __init ioapic_insert_resources(void)
@@ -3657,7 +3756,7 @@ void __init ioapic_insert_resources(void
 		return;
 	}
 
-	for (i = 0; i < nr_ioapics; i++) {
+	for_each_ioapic(i) {
 		insert_resource(&iomem_resource, r);
 		r++;
 	}
@@ -3665,16 +3764,15 @@ void __init ioapic_insert_resources(void
 
 int mp_find_ioapic(u32 gsi)
 {
-	int i = 0;
+	int i;
 
 	if (nr_ioapics == 0)
 		return -1;
 
 	/* Find the IOAPIC that manages this GSI. */
-	for (i = 0; i < nr_ioapics; i++) {
+	for_each_ioapic(i) {
 		struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i);
-		if ((gsi >= gsi_cfg->gsi_base)
-		    && (gsi <= gsi_cfg->gsi_end))
+		if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
 			return i;
 	}
 
@@ -3686,7 +3784,7 @@ int mp_find_ioapic_pin(int ioapic, u32 g
 {
 	struct mp_ioapic_gsi *gsi_cfg;
 
-	if (WARN_ON(ioapic == -1))
+	if (WARN_ON(ioapic < 0))
 		return -1;
 
 	gsi_cfg = mp_ioapic_gsi_routing(ioapic);
@@ -3729,7 +3827,8 @@ static __init int bad_ioapic_register(in
 	return 0;
 }
 
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			       struct ioapic_domain_cfg *cfg)
 {
 	int idx = 0;
 	int entries;
@@ -3743,6 +3842,8 @@ void __init mp_register_ioapic(int id, u
 	ioapics[idx].mp_config.type = MP_IOAPIC;
 	ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
 	ioapics[idx].mp_config.apicaddr = address;
+	ioapics[idx].irqdomain = NULL;
+	ioapics[idx].irqdomain_cfg = *cfg;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
 
@@ -3779,6 +3880,97 @@ void __init mp_register_ioapic(int id, u
 	nr_ioapics++;
 }
 
+int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+		     irq_hw_number_t hwirq)
+{
+	int ioapic = (int)(long)domain->host_data;
+	struct mp_pin_info *info = mp_pin_info(ioapic, hwirq);
+	struct io_apic_irq_attr attr;
+
+	/* Get default attribute if not set by caller yet */
+	if (!info->set) {
+		u32 gsi = mp_pin_to_gsi(ioapic, hwirq);
+
+		if (acpi_get_override_irq(gsi, &info->trigger,
+					  &info->polarity) < 0) {
+			/*
+			 * PCI interrupts are always polarity one level
+			 * triggered.
+			 */
+			info->trigger = 1;
+			info->polarity = 1;
+		}
+		info->node = NUMA_NO_NODE;
+
+		/*
+		 * setup_IO_APIC_irqs() programs all legacy IRQs with default
+		 * trigger and polarity attributes. Don't set the flag for that
+		 * case so the first legacy IRQ user could reprogram the pin
+		 * with real trigger and polarity attributes.
+		 */
+		if (virq >= nr_legacy_irqs() || info->count)
+			info->set = 1;
+	}
+	set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
+			     info->polarity);
+
+	return io_apic_setup_irq_pin(virq, info->node, &attr);
+}
+
+void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq)
+{
+	struct irq_data *data = irq_get_irq_data(virq);
+	struct irq_cfg *cfg = irq_cfg(virq);
+	int ioapic = (int)(long)domain->host_data;
+	int pin = (int)data->hwirq;
+
+	ioapic_mask_entry(ioapic, pin);
+	__remove_pin_from_irq(cfg, ioapic, pin);
+	WARN_ON(cfg->irq_2_pin != NULL);
+	arch_teardown_hwirq(virq);
+}
+
+int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
+{
+	int ret = 0;
+	int ioapic, pin;
+	struct mp_pin_info *info;
+
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0)
+		return -ENODEV;
+
+	pin = mp_find_ioapic_pin(ioapic, gsi);
+	info = mp_pin_info(ioapic, pin);
+	trigger = trigger ? 1 : 0;
+	polarity = polarity ? 1 : 0;
+
+	mutex_lock(&ioapic_mutex);
+	if (!info->set) {
+		info->trigger = trigger;
+		info->polarity = polarity;
+		info->node = node;
+		info->set = 1;
+	} else if (info->trigger != trigger || info->polarity != polarity) {
+		ret = -EBUSY;
+	}
+	mutex_unlock(&ioapic_mutex);
+
+	return ret;
+}
+
+bool mp_should_keep_irq(struct device *dev)
+{
+	if (dev->power.is_prepared)
+		return true;
+#ifdef	CONFIG_PM_RUNTIME
+	if (dev->power.runtime_status == RPM_SUSPENDING)
+		return true;
+#endif
+
+	return false;
+}
+
 /* Enable IOAPIC early just for system timer */
 void __init pre_init_apic_IRQ0(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/probe_32.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/probe_32.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/probe_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/probe_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,21 +88,16 @@ static struct apic apic_default = {
 	.disable_esr			= 0,
 	.dest_logical			= APIC_DEST_LOGICAL,
 	.check_apicid_used		= default_check_apicid_used,
-	.check_apicid_present		= default_check_apicid_present,
 
 	.vector_allocation_domain	= flat_vector_allocation_domain,
 	.init_apic_ldr			= default_init_apic_ldr,
 
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= setup_apic_flat_routing,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= default_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= default_get_apic_id,
 	.set_apic_id			= NULL,
@@ -116,11 +111,7 @@ static struct apic apic_default = {
 	.send_IPI_all			= default_send_IPI_all,
 	.send_IPI_self			= default_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
 	.wait_for_init_deassert		= true,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= default_inquire_remote_apic,
 
 	.read				= native_apic_mem_read,
@@ -214,29 +205,7 @@ void __init generic_apic_probe(void)
 	printk(KERN_INFO "Using APIC driver %s\n", apic->name);
 }
 
-/* These functions can switch the APIC even after the initial ->probe() */
-
-int __init
-generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
-{
-	struct apic **drv;
-
-	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
-		if (!((*drv)->mps_oem_check))
-			continue;
-		if (!(*drv)->mps_oem_check(mpc, oem, productid))
-			continue;
-
-		if (!cmdline_apic) {
-			apic = *drv;
-			printk(KERN_INFO "Switched to APIC driver `%s'.\n",
-			       apic->name);
-		}
-		return 1;
-	}
-	return 0;
-}
-
+/* This function can switch the APIC even after the initial ->probe() */
 int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
 	struct apic **drv;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_cluster.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_cluster.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2014-09-28 17:29:07.000000000 -0400
@@ -249,21 +249,16 @@ static struct apic apic_x2apic_cluster =
 	.disable_esr			= 0,
 	.dest_logical			= APIC_DEST_LOGICAL,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= cluster_vector_allocation_domain,
 	.init_apic_ldr			= init_x2apic_ldr,
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= x2apic_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= x2apic_get_apic_id,
 	.set_apic_id			= x2apic_set_apic_id,
@@ -277,10 +272,7 @@ static struct apic apic_x2apic_cluster =
 	.send_IPI_all			= x2apic_send_IPI_all,
 	.send_IPI_self			= x2apic_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
 	.read				= native_apic_msr_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_phys.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_phys.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_phys.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_phys.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,21 +103,16 @@ static struct apic apic_x2apic_phys = {
 	.disable_esr			= 0,
 	.dest_logical			= 0,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= default_vector_allocation_domain,
 	.init_apic_ldr			= init_x2apic_ldr,
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= x2apic_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= x2apic_get_apic_id,
 	.set_apic_id			= x2apic_set_apic_id,
@@ -131,10 +126,7 @@ static struct apic apic_x2apic_phys = {
 	.send_IPI_all			= x2apic_send_IPI_all,
 	.send_IPI_self			= x2apic_send_IPI_self,
 
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
 	.read				= native_apic_msr_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-3.16-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2014-09-28 17:29:07.000000000 -0400
@@ -365,21 +365,16 @@ static struct apic __refdata apic_x2apic
 	.disable_esr			= 0,
 	.dest_logical			= APIC_DEST_LOGICAL,
 	.check_apicid_used		= NULL,
-	.check_apicid_present		= NULL,
 
 	.vector_allocation_domain	= default_vector_allocation_domain,
 	.init_apic_ldr			= uv_init_apic_ldr,
 
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
-	.multi_timer_check		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
-	.setup_portio_remap		= NULL,
 	.check_phys_apicid_present	= default_check_phys_apicid_present,
-	.enable_apic_mode		= NULL,
 	.phys_pkg_id			= uv_phys_pkg_id,
-	.mps_oem_check			= NULL,
 
 	.get_apic_id			= x2apic_get_apic_id,
 	.set_apic_id			= set_apic_id,
@@ -394,10 +389,7 @@ static struct apic __refdata apic_x2apic
 	.send_IPI_self			= uv_send_IPI_self,
 
 	.wakeup_secondary_cpu		= uv_wakeup_secondary,
-	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
-	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
 	.wait_for_init_deassert		= false,
-	.smp_callin_clear_local_apic	= NULL,
 	.inquire_remote_apic		= NULL,
 
 	.read				= native_apic_msr_read,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/amd.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/amd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/amd.c	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 #include <asm/processor.h>
 #include <asm/apic.h>
 #include <asm/cpu.h>
+#include <asm/smp.h>
 #include <asm/pci-direct.h>
 
 #ifdef CONFIG_X86_64
@@ -50,7 +51,6 @@ static inline int wrmsrl_amd_safe(unsign
 	return wrmsr_safe_regs(gprs);
 }
 
-#ifdef CONFIG_X86_32
 /*
  *	B step AMD K6 before B 9730xxxx have hardware bugs that can cause
  *	misexecution of code under Linux. Owners of such processors should
@@ -70,6 +70,7 @@ __asm__(".globl vide\n\t.align 4\nvide:
 
 static void init_amd_k5(struct cpuinfo_x86 *c)
 {
+#ifdef CONFIG_X86_32
 /*
  * General Systems BIOSen alias the cpu frequency registers
  * of the Elan at 0x000df000. Unfortuantly, one of the Linux
@@ -83,11 +84,12 @@ static void init_amd_k5(struct cpuinfo_x
 		if (inl(CBAR) & CBAR_ENB)
 			outl(0 | CBAR_KEY, CBAR);
 	}
+#endif
 }
 
-
 static void init_amd_k6(struct cpuinfo_x86 *c)
 {
+#ifdef CONFIG_X86_32
 	u32 l, h;
 	int mbytes = get_num_physpages() >> (20-PAGE_SHIFT);
 
@@ -176,10 +178,44 @@ static void init_amd_k6(struct cpuinfo_x
 		/* placeholder for any needed mods */
 		return;
 	}
+#endif
 }
 
-static void amd_k7_smp_check(struct cpuinfo_x86 *c)
+static void init_amd_k7(struct cpuinfo_x86 *c)
 {
+#ifdef CONFIG_X86_32
+	u32 l, h;
+
+	/*
+	 * Bit 15 of Athlon specific MSR 15, needs to be 0
+	 * to enable SSE on Palomino/Morgan/Barton CPU's.
+	 * If the BIOS didn't enable it already, enable it here.
+	 */
+	if (c->x86_model >= 6 && c->x86_model <= 10) {
+		if (!cpu_has(c, X86_FEATURE_XMM)) {
+			printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
+			msr_clear_bit(MSR_K7_HWCR, 15);
+			set_cpu_cap(c, X86_FEATURE_XMM);
+		}
+	}
+
+	/*
+	 * It's been determined by AMD that Athlons since model 8 stepping 1
+	 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
+	 * As per AMD technical note 27212 0.2
+	 */
+	if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+		rdmsr(MSR_K7_CLK_CTL, l, h);
+		if ((l & 0xfff00000) != 0x20000000) {
+			printk(KERN_INFO
+			    "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
+					l, ((l & 0x000fffff)|0x20000000));
+			wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
+		}
+	}
+
+	set_cpu_cap(c, X86_FEATURE_K7);
+
 	/* calling is from identify_secondary_cpu() ? */
 	if (!c->cpu_index)
 		return;
@@ -207,7 +243,7 @@ static void amd_k7_smp_check(struct cpui
 	if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
 	    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
 	     (c->x86_model > 7))
-		if (cpu_has_mp)
+		if (cpu_has(c, X86_FEATURE_MP))
 			return;
 
 	/* If we get here, not a certified SMP capable AMD system. */
@@ -219,45 +255,8 @@ static void amd_k7_smp_check(struct cpui
 	WARN_ONCE(1, "WARNING: This combination of AMD"
 		" processors is not suitable for SMP.\n");
 	add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
-}
-
-static void init_amd_k7(struct cpuinfo_x86 *c)
-{
-	u32 l, h;
-
-	/*
-	 * Bit 15 of Athlon specific MSR 15, needs to be 0
-	 * to enable SSE on Palomino/Morgan/Barton CPU's.
-	 * If the BIOS didn't enable it already, enable it here.
-	 */
-	if (c->x86_model >= 6 && c->x86_model <= 10) {
-		if (!cpu_has(c, X86_FEATURE_XMM)) {
-			printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
-			msr_clear_bit(MSR_K7_HWCR, 15);
-			set_cpu_cap(c, X86_FEATURE_XMM);
-		}
-	}
-
-	/*
-	 * It's been determined by AMD that Athlons since model 8 stepping 1
-	 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
-	 * As per AMD technical note 27212 0.2
-	 */
-	if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
-		rdmsr(MSR_K7_CLK_CTL, l, h);
-		if ((l & 0xfff00000) != 0x20000000) {
-			printk(KERN_INFO
-			    "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
-					l, ((l & 0x000fffff)|0x20000000));
-			wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
-		}
-	}
-
-	set_cpu_cap(c, X86_FEATURE_K7);
-
-	amd_k7_smp_check(c);
-}
 #endif
+}
 
 #ifdef CONFIG_NUMA
 /*
@@ -446,6 +445,26 @@ static void early_init_amd_mc(struct cpu
 
 static void bsp_init_amd(struct cpuinfo_x86 *c)
 {
+
+#ifdef CONFIG_X86_64
+	if (c->x86 >= 0xf) {
+		unsigned long long tseg;
+
+		/*
+		 * Split up direct mapping around the TSEG SMM area.
+		 * Don't do it for gbpages because there seems very little
+		 * benefit in doing so.
+		 */
+		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
+			unsigned long pfn = tseg >> PAGE_SHIFT;
+
+			printk(KERN_DEBUG "tseg: %010llx\n", tseg);
+			if (pfn_range_is_mapped(pfn, pfn + 1))
+				set_memory_4k((unsigned long)__va(tseg), 1);
+		}
+	}
+#endif
+
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
 
 		if (c->x86 > 0x10 ||
@@ -515,101 +534,74 @@ 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);
 
-static void init_amd(struct cpuinfo_x86 *c)
+static void init_amd_k8(struct cpuinfo_x86 *c)
 {
-	u32 dummy;
-	unsigned long long value;
-
-#ifdef CONFIG_SMP
-	/*
-	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
-	 * bit 6 of msr C001_0015
-	 *
-	 * Errata 63 for SH-B3 steppings
-	 * Errata 122 for all steppings (F+ have it disabled by default)
-	 */
-	if (c->x86 == 0xf)
-		msr_set_bit(MSR_K7_HWCR, 6);
-#endif
+	u32 level;
+	u64 value;
 
-	early_init_amd(c);
+	/* On C+ stepping K8 rep microcode works well for copy/memset */
+	level = cpuid_eax(1);
+	if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
+		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
 
 	/*
-	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
-	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+	 * Some BIOSes incorrectly force this feature, but only K8 revision D
+	 * (model = 0x14) and later actually support it.
+	 * (AMD Erratum #110, docId: 25759).
 	 */
-	clear_cpu_cap(c, 0*32+31);
-
-#ifdef CONFIG_X86_64
-	/* On C+ stepping K8 rep microcode works well for copy/memset */
-	if (c->x86 == 0xf) {
-		u32 level;
-
-		level = cpuid_eax(1);
-		if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
-			set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-
-		/*
-		 * Some BIOSes incorrectly force this feature, but only K8
-		 * revision D (model = 0x14) and later actually support it.
-		 * (AMD Erratum #110, docId: 25759).
-		 */
-		if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
-			clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
-			if (!rdmsrl_amd_safe(0xc001100d, &value)) {
-				value &= ~(1ULL << 32);
-				wrmsrl_amd_safe(0xc001100d, value);
-			}
+	if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
+		clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
+		if (!rdmsrl_amd_safe(0xc001100d, &value)) {
+			value &= ~BIT_64(32);
+			wrmsrl_amd_safe(0xc001100d, value);
 		}
-
 	}
-	if (c->x86 >= 0x10)
-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
 
-	/* get apicid instead of initial apic id from cpuid */
-	c->apicid = hard_smp_processor_id();
-#else
+	if (!c->x86_model_id[0])
+		strcpy(c->x86_model_id, "Hammer");
+}
+
+static void init_amd_gh(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+	/* do this for boot cpu */
+	if (c == &boot_cpu_data)
+		check_enable_amd_mmconf_dmi();
+
+	fam10h_check_enable_mmcfg();
+#endif
 
 	/*
-	 *	FIXME: We should handle the K5 here. Set up the write
-	 *	range and also turn on MSR 83 bits 4 and 31 (write alloc,
-	 *	no bus pipeline)
+	 * Disable GART TLB Walk Errors on Fam10h. We do this here because this
+	 * is always needed when GART is enabled, even in a kernel which has no
+	 * MCE support built in. BIOS should disable GartTlbWlk Errors already.
+	 * If it doesn't, we do it here as suggested by the BKDG.
+	 *
+	 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
 	 */
+	msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
 
-	switch (c->x86) {
-	case 4:
-		init_amd_k5(c);
-		break;
-	case 5:
-		init_amd_k6(c);
-		break;
-	case 6: /* An Athlon/Duron */
-		init_amd_k7(c);
-		break;
-	}
-
-	/* K6s reports MCEs but don't actually have all the MSRs */
-	if (c->x86 < 6)
-		clear_cpu_cap(c, X86_FEATURE_MCE);
-#endif
+	/*
+	 * On family 10h BIOS may not have properly enabled WC+ support, causing
+	 * it to be converted to CD memtype. This may result in performance
+	 * degradation for certain nested-paging guests. Prevent this conversion
+	 * by clearing bit 24 in MSR_AMD64_BU_CFG2.
+	 *
+	 * NOTE: we want to use the _safe accessors so as not to #GP kvm
+	 * guests on older kvm hosts.
+	 */
+	msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
 
-	/* Enable workaround for FXSAVE leak */
-	if (c->x86 >= 6)
-		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
+	if (cpu_has_amd_erratum(c, amd_erratum_383))
+		set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
+}
 
-	if (!c->x86_model_id[0]) {
-		switch (c->x86) {
-		case 0xf:
-			/* Should distinguish Models here, but this is only
-			   a fallback anyways. */
-			strcpy(c->x86_model_id, "Hammer");
-			break;
-		}
-	}
+static void init_amd_bd(struct cpuinfo_x86 *c)
+{
+	u64 value;
 
 	/* re-enable TopologyExtensions if switched off by BIOS */
-	if ((c->x86 == 0x15) &&
-	    (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+	if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
 	    !cpu_has(c, X86_FEATURE_TOPOEXT)) {
 
 		if (msr_set_bit(0xc0011005, 54) > 0) {
@@ -625,14 +617,60 @@ static void init_amd(struct cpuinfo_x86
 	 * The way access filter has a performance penalty on some workloads.
 	 * Disable it on the affected CPUs.
 	 */
-	if ((c->x86 == 0x15) &&
-	    (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
-
+	if ((c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
 		if (!rdmsrl_safe(0xc0011021, &value) && !(value & 0x1E)) {
 			value |= 0x1E;
 			wrmsrl_safe(0xc0011021, value);
 		}
 	}
+}
+
+static void init_amd(struct cpuinfo_x86 *c)
+{
+	u32 dummy;
+
+#ifdef CONFIG_SMP
+	/*
+	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
+	 * bit 6 of msr C001_0015
+	 *
+	 * Errata 63 for SH-B3 steppings
+	 * Errata 122 for all steppings (F+ have it disabled by default)
+	 */
+	if (c->x86 == 0xf)
+		msr_set_bit(MSR_K7_HWCR, 6);
+#endif
+
+	early_init_amd(c);
+
+	/*
+	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+	 */
+	clear_cpu_cap(c, 0*32+31);
+
+	if (c->x86 >= 0x10)
+		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+
+	/* get apicid instead of initial apic id from cpuid */
+	c->apicid = hard_smp_processor_id();
+
+	/* K6s reports MCEs but don't actually have all the MSRs */
+	if (c->x86 < 6)
+		clear_cpu_cap(c, X86_FEATURE_MCE);
+
+	switch (c->x86) {
+	case 4:    init_amd_k5(c); break;
+	case 5:    init_amd_k6(c); break;
+	case 6:	   init_amd_k7(c); break;
+	case 0xf:  init_amd_k8(c); break;
+	case 0x10: init_amd_gh(c); break;
+	case 0x15: init_amd_bd(c); break;
+	}
+
+	/* Enable workaround for FXSAVE leak */
+	if (c->x86 >= 6)
+		set_cpu_bug(c, X86_BUG_FXSAVE_LEAK);
 
 	cpu_detect_cache_sizes(c);
 
@@ -656,33 +694,6 @@ static void init_amd(struct cpuinfo_x86
 		set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 	}
 
-#ifdef CONFIG_X86_64
-	if (c->x86 == 0x10) {
-		/* do this for boot cpu */
-		if (c == &boot_cpu_data)
-			check_enable_amd_mmconf_dmi();
-
-		fam10h_check_enable_mmcfg();
-	}
-
-	if (c == &boot_cpu_data && c->x86 >= 0xf) {
-		unsigned long long tseg;
-
-		/*
-		 * Split up direct mapping around the TSEG SMM area.
-		 * Don't do it for gbpages because there seems very little
-		 * benefit in doing so.
-		 */
-		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
-			unsigned long pfn = tseg >> PAGE_SHIFT;
-
-			printk(KERN_DEBUG "tseg: %010llx\n", tseg);
-			if (pfn_range_is_mapped(pfn, pfn + 1))
-				set_memory_4k((unsigned long)__va(tseg), 1);
-		}
-	}
-#endif
-
 	/*
 	 * Family 0x12 and above processors have APIC timer
 	 * running in deep C states.
@@ -690,34 +701,6 @@ static void init_amd(struct cpuinfo_x86
 	if (c->x86 > 0x11)
 		set_cpu_cap(c, X86_FEATURE_ARAT);
 
-	if (c->x86 == 0x10) {
-		/*
-		 * Disable GART TLB Walk Errors on Fam10h. We do this here
-		 * because this is always needed when GART is enabled, even in a
-		 * kernel which has no MCE support built in.
-		 * BIOS should disable GartTlbWlk Errors already. If
-		 * it doesn't, do it here as suggested by the BKDG.
-		 *
-		 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
-		 */
-		msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
-
-		/*
-		 * On family 10h BIOS may not have properly enabled WC+ support,
-		 * causing it to be converted to CD memtype. This may result in
-		 * performance degradation for certain nested-paging guests.
-		 * Prevent this conversion by clearing bit 24 in
-		 * MSR_AMD64_BU_CFG2.
-		 *
-		 * NOTE: we want to use the _safe accessors so as not to #GP kvm
-		 * guests on older kvm hosts.
-		 */
-		msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
-
-		if (cpu_has_amd_erratum(c, amd_erratum_383))
-			set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
-	}
-
 	if (cpu_has_amd_erratum(c, amd_erratum_400))
 		set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
 
@@ -741,11 +724,6 @@ static unsigned int amd_size_cache(struc
 }
 #endif
 
-static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c)
-{
-	tlb_flushall_shift = 6;
-}
-
 static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
 {
 	u32 ebx, eax, ecx, edx;
@@ -793,8 +771,6 @@ static void cpu_detect_tlb_amd(struct cp
 		tlb_lli_2m[ENTRIES] = eax & mask;
 
 	tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1;
-
-	cpu_set_tlb_flushall_shift(c);
 }
 
 static const struct cpu_dev amd_cpu_dev = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/common.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,6 +148,7 @@ static int __init x86_xsave_setup(char *
 {
 	setup_clear_cpu_cap(X86_FEATURE_XSAVE);
 	setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
+	setup_clear_cpu_cap(X86_FEATURE_XSAVES);
 	setup_clear_cpu_cap(X86_FEATURE_AVX);
 	setup_clear_cpu_cap(X86_FEATURE_AVX2);
 	return 1;
@@ -161,6 +162,13 @@ static int __init x86_xsaveopt_setup(cha
 }
 __setup("noxsaveopt", x86_xsaveopt_setup);
 
+static int __init x86_xsaves_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_XSAVES);
+	return 1;
+}
+__setup("noxsaves", x86_xsaves_setup);
+
 #ifdef CONFIG_X86_32
 static int cachesize_override = -1;
 static int disable_x86_serial_nr = 1;
@@ -481,26 +489,17 @@ u16 __read_mostly tlb_lld_2m[NR_INFO];
 u16 __read_mostly tlb_lld_4m[NR_INFO];
 u16 __read_mostly tlb_lld_1g[NR_INFO];
 
-/*
- * tlb_flushall_shift shows the balance point in replacing cr3 write
- * with multiple 'invlpg'. It will do this replacement when
- *   flush_tlb_lines <= active_lines/2^tlb_flushall_shift.
- * If tlb_flushall_shift is -1, means the replacement will be disabled.
- */
-s8  __read_mostly tlb_flushall_shift = -1;
-
 void cpu_detect_tlb(struct cpuinfo_x86 *c)
 {
 	if (this_cpu->c_detect_tlb)
 		this_cpu->c_detect_tlb(c);
 
 	printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n"
-		"Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n"
-		"tlb_flushall_shift: %d\n",
+		"Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n",
 		tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES],
 		tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES],
 		tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES],
-		tlb_lld_1g[ENTRIES], tlb_flushall_shift);
+		tlb_lld_1g[ENTRIES]);
 }
 
 void detect_ht(struct cpuinfo_x86 *c)
@@ -634,6 +633,15 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 		c->x86_capability[9] = ebx;
 	}
 
+	/* Extended state features: level 0x0000000d */
+	if (c->cpuid_level >= 0x0000000d) {
+		u32 eax, ebx, ecx, edx;
+
+		cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
+
+		c->x86_capability[10] = eax;
+	}
+
 	/* AMD-defined flags: level 0x80000001 */
 	xlvl = cpuid_eax(0x80000000);
 	c->extended_cpuid_level = xlvl;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/intel.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/intel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/intel.c	2014-09-28 17:29:07.000000000 -0400
@@ -253,7 +253,7 @@ static void intel_workarounds(struct cpu
 	 */
 	if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
 	    (c->x86_mask < 0x6 || c->x86_mask == 0xb))
-		set_cpu_cap(c, X86_FEATURE_11AP);
+		set_cpu_bug(c, X86_BUG_11AP);
 
 
 #ifdef CONFIG_X86_INTEL_USERCOPY
@@ -402,7 +402,7 @@ static void init_intel(struct cpuinfo_x8
 
 	if (c->x86 == 6 && cpu_has_clflush &&
 	    (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
-		set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
+		set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
 
 #ifdef CONFIG_X86_64
 	if (c->x86 == 15)
@@ -634,31 +634,6 @@ static void intel_tlb_lookup(const unsig
 	}
 }
 
-static void intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c)
-{
-	switch ((c->x86 << 8) + c->x86_model) {
-	case 0x60f: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
-	case 0x616: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
-	case 0x617: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
-	case 0x61d: /* six-core 45 nm xeon "Dunnington" */
-		tlb_flushall_shift = -1;
-		break;
-	case 0x63a: /* Ivybridge */
-		tlb_flushall_shift = 2;
-		break;
-	case 0x61a: /* 45 nm nehalem, "Bloomfield" */
-	case 0x61e: /* 45 nm nehalem, "Lynnfield" */
-	case 0x625: /* 32 nm nehalem, "Clarkdale" */
-	case 0x62c: /* 32 nm nehalem, "Gulftown" */
-	case 0x62e: /* 45 nm nehalem-ex, "Beckton" */
-	case 0x62f: /* 32 nm Xeon E7 */
-	case 0x62a: /* SandyBridge */
-	case 0x62d: /* SandyBridge, "Romely-EP" */
-	default:
-		tlb_flushall_shift = 6;
-	}
-}
-
 static void intel_detect_tlb(struct cpuinfo_x86 *c)
 {
 	int i, j, n;
@@ -683,7 +658,6 @@ static void intel_detect_tlb(struct cpui
 		for (j = 1 ; j < 16 ; j++)
 			intel_tlb_lookup(desc[j]);
 	}
-	intel_tlb_flushall_shift_set(c);
 }
 
 static const struct cpu_dev intel_cpu_dev = {
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2014-09-28 17:29:07.000000000 -0400
@@ -461,7 +461,7 @@ static ssize_t store_cache_disable(struc
 
 	cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
 
-	if (strict_strtoul(buf, 10, &val) < 0)
+	if (kstrtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 
 	err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
@@ -511,7 +511,7 @@ store_subcaches(struct _cpuid4_info *thi
 	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
 		return -EINVAL;
 
-	if (strict_strtoul(buf, 16, &val) < 0)
+	if (kstrtoul(buf, 16, &val) < 0)
 		return -EINVAL;
 
 	if (amd_set_subcaches(cpu, val))
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2014-09-28 17:29:07.000000000 -0400
@@ -353,7 +353,7 @@ store_interrupt_enable(struct threshold_
 	if (!b->interrupt_capable)
 		return -EINVAL;
 
-	if (strict_strtoul(buf, 0, &new) < 0)
+	if (kstrtoul(buf, 0, &new) < 0)
 		return -EINVAL;
 
 	b->interrupt_enable = !!new;
@@ -372,7 +372,7 @@ store_threshold_limit(struct threshold_b
 	struct thresh_restart tr;
 	unsigned long new;
 
-	if (strict_strtoul(buf, 0, &new) < 0)
+	if (kstrtoul(buf, 0, &new) < 0)
 		return -EINVAL;
 
 	if (new > THRESHOLD_MAX)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2014-09-28 17:29:07.000000000 -0400
@@ -2136,7 +2136,7 @@ static ssize_t set_bank(struct device *s
 {
 	u64 new;
 
-	if (strict_strtoull(buf, 0, &new) < 0)
+	if (kstrtou64(buf, 0, &new) < 0)
 		return -EINVAL;
 
 	attr_to_bank(attr)->ctl = new;
@@ -2174,7 +2174,7 @@ static ssize_t set_ignore_ce(struct devi
 {
 	u64 new;
 
-	if (strict_strtoull(buf, 0, &new) < 0)
+	if (kstrtou64(buf, 0, &new) < 0)
 		return -EINVAL;
 
 	if (mca_cfg.ignore_ce ^ !!new) {
@@ -2198,7 +2198,7 @@ static ssize_t set_cmci_disabled(struct
 {
 	u64 new;
 
-	if (strict_strtoull(buf, 0, &new) < 0)
+	if (kstrtou64(buf, 0, &new) < 0)
 		return -EINVAL;
 
 	if (mca_cfg.cmci_disabled ^ !!new) {
@@ -2385,6 +2385,10 @@ mce_cpu_callback(struct notifier_block *
 			threshold_cpu_callback(action, cpu);
 		mce_device_remove(cpu);
 		mce_intel_hcpu_update(cpu);
+
+		/* 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);
@@ -2396,11 +2400,6 @@ mce_cpu_callback(struct notifier_block *
 		break;
 	}
 
-	if (action == CPU_POST_DEAD) {
-		/* intentionally ignoring frozen here */
-		cmci_rediscover();
-	}
-
 	return NOTIFY_OK;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_b
  * cmci_discover_lock protects against parallel discovery attempts
  * which could race against each other.
  */
-static DEFINE_SPINLOCK(cmci_discover_lock);
+static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
 
 #define CMCI_THRESHOLD		1
 #define CMCI_POLL_INTERVAL	(30 * HZ)
@@ -144,14 +144,14 @@ static void cmci_storm_disable_banks(voi
 	int bank;
 	u64 val;
 
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	owned = __get_cpu_var(mce_banks_owned);
 	for_each_set_bit(bank, owned, MAX_NR_BANKS) {
 		rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
 		val &= ~MCI_CTL2_CMCI_EN;
 		wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
 static bool cmci_storm_detect(void)
@@ -211,7 +211,7 @@ static void cmci_discover(int banks)
 	int i;
 	int bios_wrong_thresh = 0;
 
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++) {
 		u64 val;
 		int bios_zero_thresh = 0;
@@ -266,7 +266,7 @@ static void cmci_discover(int banks)
 			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
 		}
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 	if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) {
 		pr_info_once(
 			"bios_cmci_threshold: Some banks do not have valid thresholds set\n");
@@ -316,10 +316,10 @@ void cmci_clear(void)
 
 	if (!cmci_supported(&banks))
 		return;
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++)
 		__cmci_disable_bank(i);
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
 static void cmci_rediscover_work_func(void *arg)
@@ -360,9 +360,9 @@ void cmci_disable_bank(int bank)
 	if (!cmci_supported(&banks))
 		return;
 
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	__cmci_disable_bank(bank);
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
 static void intel_init_cmci(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/mkcapflags.sh linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mkcapflags.sh
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/mkcapflags.sh	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/mkcapflags.sh	2014-09-28 17:29:07.000000000 -0400
@@ -1,23 +1,25 @@
 #!/bin/sh
 #
-# Generate the x86_cap_flags[] array from include/asm/cpufeature.h
+# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h
 #
 
 IN=$1
 OUT=$2
 
-TABS="$(printf '\t\t\t\t\t')"
-trap 'rm "$OUT"' EXIT
+function dump_array()
+{
+	ARRAY=$1
+	SIZE=$2
+	PFX=$3
+	POSTFIX=$4
 
-(
-	echo "#ifndef _ASM_X86_CPUFEATURE_H"
-	echo "#include <asm/cpufeature.h>"
-	echo "#endif"
-	echo ""
-	echo "const char * const x86_cap_flags[NCAPINTS*32] = {"
+	PFX_SZ=$(echo $PFX | wc -c)
+	TABS="$(printf '\t\t\t\t\t')"
 
-	# Iterate through any input lines starting with #define X86_FEATURE_
-	sed -n -e 's/\t/ /g' -e 's/^ *# *define *X86_FEATURE_//p' $IN |
+	echo "const char * const $ARRAY[$SIZE] = {"
+
+	# Iterate through any input lines starting with #define $PFX
+	sed -n -e 's/\t/ /g' -e "s/^ *# *define *$PFX//p" $IN |
 	while read i
 	do
 		# Name is everything up to the first whitespace
@@ -31,11 +33,32 @@ trap 'rm "$OUT"' EXIT
 		# Name is uppercase, VALUE is all lowercase
 		VALUE="$(echo "$VALUE" | tr A-Z a-z)"
 
-		TABCOUNT=$(( ( 5*8 - 14 - $(echo "$NAME" | wc -c) ) / 8 ))
-		printf "\t[%s]%.*s = %s,\n" \
-			"X86_FEATURE_$NAME" "$TABCOUNT" "$TABS" "$VALUE"
+        if [ -n "$POSTFIX" ]; then
+            T=$(( $PFX_SZ + $(echo $POSTFIX | wc -c) + 2 ))
+	        TABS="$(printf '\t\t\t\t\t\t')"
+		    TABCOUNT=$(( ( 6*8 - ($T + 1) - $(echo "$NAME" | wc -c) ) / 8 ))
+		    printf "\t[%s - %s]%.*s = %s,\n" "$PFX$NAME" "$POSTFIX" "$TABCOUNT" "$TABS" "$VALUE"
+        else
+		    TABCOUNT=$(( ( 5*8 - ($PFX_SZ + 1) - $(echo "$NAME" | wc -c) ) / 8 ))
+            printf "\t[%s]%.*s = %s,\n" "$PFX$NAME" "$TABCOUNT" "$TABS" "$VALUE"
+        fi
 	done
 	echo "};"
+}
+
+trap 'rm "$OUT"' EXIT
+
+(
+	echo "#ifndef _ASM_X86_CPUFEATURE_H"
+	echo "#include <asm/cpufeature.h>"
+	echo "#endif"
+	echo ""
+
+	dump_array "x86_cap_flags" "NCAPINTS*32" "X86_FEATURE_" ""
+	echo ""
+
+	dump_array "x86_bug_flags" "NBUGINTS*32" "X86_BUG_" "NCAPINTS*32"
+
 ) > $OUT
 
 trap - EXIT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/perf_event_amd_uncore.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/perf_event_amd_uncore.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/perf_event_amd_uncore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/perf_event_amd_uncore.c	2014-09-28 17:29:07.000000000 -0400
@@ -294,31 +294,41 @@ static struct amd_uncore *amd_uncore_all
 			cpu_to_node(cpu));
 }
 
-static void amd_uncore_cpu_up_prepare(unsigned int cpu)
+static int amd_uncore_cpu_up_prepare(unsigned int cpu)
 {
-	struct amd_uncore *uncore;
+	struct amd_uncore *uncore_nb = NULL, *uncore_l2;
 
 	if (amd_uncore_nb) {
-		uncore = amd_uncore_alloc(cpu);
-		uncore->cpu = cpu;
-		uncore->num_counters = NUM_COUNTERS_NB;
-		uncore->rdpmc_base = RDPMC_BASE_NB;
-		uncore->msr_base = MSR_F15H_NB_PERF_CTL;
-		uncore->active_mask = &amd_nb_active_mask;
-		uncore->pmu = &amd_nb_pmu;
-		*per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
+		uncore_nb = amd_uncore_alloc(cpu);
+		if (!uncore_nb)
+			goto fail;
+		uncore_nb->cpu = cpu;
+		uncore_nb->num_counters = NUM_COUNTERS_NB;
+		uncore_nb->rdpmc_base = RDPMC_BASE_NB;
+		uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
+		uncore_nb->active_mask = &amd_nb_active_mask;
+		uncore_nb->pmu = &amd_nb_pmu;
+		*per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
 	}
 
 	if (amd_uncore_l2) {
-		uncore = amd_uncore_alloc(cpu);
-		uncore->cpu = cpu;
-		uncore->num_counters = NUM_COUNTERS_L2;
-		uncore->rdpmc_base = RDPMC_BASE_L2;
-		uncore->msr_base = MSR_F16H_L2I_PERF_CTL;
-		uncore->active_mask = &amd_l2_active_mask;
-		uncore->pmu = &amd_l2_pmu;
-		*per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
+		uncore_l2 = amd_uncore_alloc(cpu);
+		if (!uncore_l2)
+			goto fail;
+		uncore_l2->cpu = cpu;
+		uncore_l2->num_counters = NUM_COUNTERS_L2;
+		uncore_l2->rdpmc_base = RDPMC_BASE_L2;
+		uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
+		uncore_l2->active_mask = &amd_l2_active_mask;
+		uncore_l2->pmu = &amd_l2_pmu;
+		*per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
 	}
+
+	return 0;
+
+fail:
+	kfree(uncore_nb);
+	return -ENOMEM;
 }
 
 static struct amd_uncore *
@@ -441,7 +451,7 @@ static void uncore_dead(unsigned int cpu
 
 	if (!--uncore->refcnt)
 		kfree(uncore);
-	*per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
+	*per_cpu_ptr(uncores, cpu) = NULL;
 }
 
 static void amd_uncore_cpu_dead(unsigned int cpu)
@@ -461,7 +471,8 @@ amd_uncore_cpu_notifier(struct notifier_
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_UP_PREPARE:
-		amd_uncore_cpu_up_prepare(cpu);
+		if (amd_uncore_cpu_up_prepare(cpu))
+			return notifier_from_errno(-ENOMEM);
 		break;
 
 	case CPU_STARTING:
@@ -501,20 +512,33 @@ static void __init init_cpu_already_onli
 	amd_uncore_cpu_online(cpu);
 }
 
+static void cleanup_cpu_online(void *dummy)
+{
+	unsigned int cpu = smp_processor_id();
+
+	amd_uncore_cpu_dead(cpu);
+}
+
 static int __init amd_uncore_init(void)
 {
-	unsigned int cpu;
+	unsigned int cpu, cpu2;
 	int ret = -ENODEV;
 
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-		return -ENODEV;
+		goto fail_nodev;
 
 	if (!cpu_has_topoext)
-		return -ENODEV;
+		goto fail_nodev;
 
 	if (cpu_has_perfctr_nb) {
 		amd_uncore_nb = alloc_percpu(struct amd_uncore *);
-		perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
+		if (!amd_uncore_nb) {
+			ret = -ENOMEM;
+			goto fail_nb;
+		}
+		ret = perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
+		if (ret)
+			goto fail_nb;
 
 		printk(KERN_INFO "perf: AMD NB counters detected\n");
 		ret = 0;
@@ -522,20 +546,28 @@ static int __init amd_uncore_init(void)
 
 	if (cpu_has_perfctr_l2) {
 		amd_uncore_l2 = alloc_percpu(struct amd_uncore *);
-		perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
+		if (!amd_uncore_l2) {
+			ret = -ENOMEM;
+			goto fail_l2;
+		}
+		ret = perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
+		if (ret)
+			goto fail_l2;
 
 		printk(KERN_INFO "perf: AMD L2I counters detected\n");
 		ret = 0;
 	}
 
 	if (ret)
-		return -ENODEV;
+		goto fail_nodev;
 
 	cpu_notifier_register_begin();
 
 	/* init cpus already online before registering for hotplug notifier */
 	for_each_online_cpu(cpu) {
-		amd_uncore_cpu_up_prepare(cpu);
+		ret = amd_uncore_cpu_up_prepare(cpu);
+		if (ret)
+			goto fail_online;
 		smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
 	}
 
@@ -543,5 +575,30 @@ static int __init amd_uncore_init(void)
 	cpu_notifier_register_done();
 
 	return 0;
+
+
+fail_online:
+	for_each_online_cpu(cpu2) {
+		if (cpu2 == cpu)
+			break;
+		smp_call_function_single(cpu, cleanup_cpu_online, NULL, 1);
+	}
+	cpu_notifier_register_done();
+
+	/* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */
+	amd_uncore_nb = amd_uncore_l2 = NULL;
+	if (cpu_has_perfctr_l2)
+		perf_pmu_unregister(&amd_l2_pmu);
+fail_l2:
+	if (cpu_has_perfctr_nb)
+		perf_pmu_unregister(&amd_nb_pmu);
+	if (amd_uncore_l2)
+		free_percpu(amd_uncore_l2);
+fail_nb:
+	if (amd_uncore_nb)
+		free_percpu(amd_uncore_nb);
+
+fail_nodev:
+	return ret;
 }
 device_initcall(amd_uncore_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/perf_event_intel_uncore.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/perf_event_intel_uncore.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/perf_event_intel_uncore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/perf_event_intel_uncore.c	2014-09-28 17:29:07.000000000 -0400
@@ -945,7 +945,7 @@ static struct intel_uncore_type *snbep_p
 	NULL,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = {
+static const struct pci_device_id snbep_uncore_pci_ids[] = {
 	{ /* Home Agent */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
 		.driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
@@ -1510,7 +1510,7 @@ static struct intel_uncore_type *ivt_pci
 	NULL,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = {
+static const struct pci_device_id ivt_uncore_pci_ids[] = {
 	{ /* Home Agent 0 */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
 		.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_HA, 0),
@@ -1985,7 +1985,7 @@ static struct intel_uncore_type *snb_pci
 	NULL,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = {
+static const struct pci_device_id snb_uncore_pci_ids[] = {
 	{ /* IMC */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
 		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -1993,7 +1993,7 @@ static DEFINE_PCI_DEVICE_TABLE(snb_uncor
 	{ /* end: all zeroes */ },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = {
+static const struct pci_device_id ivb_uncore_pci_ids[] = {
 	{ /* IMC */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
 		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -2001,7 +2001,7 @@ static DEFINE_PCI_DEVICE_TABLE(ivb_uncor
 	{ /* end: all zeroes */ },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(hsw_uncore_pci_ids) = {
+static const struct pci_device_id hsw_uncore_pci_ids[] = {
 	{ /* IMC */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
 		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -2947,10 +2947,7 @@ again:
 		 * extra registers. If we failed to take an extra
 		 * register, try the alternative.
 		 */
-		if (idx % 2)
-			idx--;
-		else
-			idx++;
+		idx ^= 1;
 		if (idx != reg1->idx % 6) {
 			if (idx == 2)
 				config1 >>= 8;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/proc.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/proc.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,6 +97,14 @@ static int show_cpuinfo(struct seq_file
 		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
 			seq_printf(m, " %s", x86_cap_flags[i]);
 
+	seq_printf(m, "\nbugs\t\t:");
+	for (i = 0; i < 32*NBUGINTS; i++) {
+		unsigned int bug_bit = 32*NCAPINTS + i;
+
+		if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i])
+			seq_printf(m, " %s", x86_bug_flags[i]);
+	}
+
 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
 		   c->loops_per_jiffy/(500000/HZ),
 		   (c->loops_per_jiffy/(5000/HZ)) % 100);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/cpu/scattered.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/scattered.c
--- linux-libre-3.16-gnu/arch/x86/kernel/cpu/scattered.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/cpu/scattered.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,6 @@ void init_scattered_cpuid_features(struc
 		{ X86_FEATURE_PTS,		CR_EAX, 6, 0x00000006, 0 },
 		{ X86_FEATURE_APERFMPERF,	CR_ECX, 0, 0x00000006, 0 },
 		{ X86_FEATURE_EPB,		CR_ECX, 3, 0x00000006, 0 },
-		{ X86_FEATURE_XSAVEOPT,		CR_EAX,	0, 0x0000000d, 1 },
 		{ 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 },
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/crash.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/crash.c
--- linux-libre-3.16-gnu/arch/x86/kernel/crash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/crash.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,9 +4,14 @@
  * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
  *
  * Copyright (C) IBM Corporation, 2004. All rights reserved.
+ * Copyright (C) Red Hat Inc., 2014. All rights reserved.
+ * Authors:
+ *      Vivek Goyal <vgoyal@redhat.com>
  *
  */
 
+#define pr_fmt(fmt)	"kexec: " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
@@ -16,6 +21,7 @@
 #include <linux/elf.h>
 #include <linux/elfcore.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 #include <asm/processor.h>
 #include <asm/hardirq.h>
@@ -28,6 +34,45 @@
 #include <asm/reboot.h>
 #include <asm/virtext.h>
 
+/* Alignment required for elf header segment */
+#define ELF_CORE_HEADER_ALIGN   4096
+
+/* This primarily represents number of split ranges due to exclusion */
+#define CRASH_MAX_RANGES	16
+
+struct crash_mem_range {
+	u64 start, end;
+};
+
+struct crash_mem {
+	unsigned int nr_ranges;
+	struct crash_mem_range ranges[CRASH_MAX_RANGES];
+};
+
+/* Misc data about ram ranges needed to prepare elf headers */
+struct crash_elf_data {
+	struct kimage *image;
+	/*
+	 * Total number of ram ranges we have after various adjustments for
+	 * GART, crash reserved region etc.
+	 */
+	unsigned int max_nr_ranges;
+	unsigned long gart_start, gart_end;
+
+	/* Pointer to elf header */
+	void *ehdr;
+	/* Pointer to next phdr */
+	void *bufp;
+	struct crash_mem mem;
+};
+
+/* Used while preparing memory map entries for second kernel */
+struct crash_memmap_data {
+	struct boot_params *params;
+	/* Type of memory */
+	unsigned int type;
+};
+
 int in_crash_kexec;
 
 /*
@@ -39,6 +84,7 @@ int in_crash_kexec;
  */
 crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL;
 EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
+unsigned long crash_zero_bytes;
 
 static inline void cpu_crash_vmclear_loaded_vmcss(void)
 {
@@ -135,3 +181,518 @@ void native_machine_crash_shutdown(struc
 #endif
 	crash_save_cpu(regs, safe_smp_processor_id());
 }
+
+#ifdef CONFIG_KEXEC_FILE
+static int get_nr_ram_ranges_callback(unsigned long start_pfn,
+				unsigned long nr_pfn, void *arg)
+{
+	int *nr_ranges = arg;
+
+	(*nr_ranges)++;
+	return 0;
+}
+
+static int get_gart_ranges_callback(u64 start, u64 end, void *arg)
+{
+	struct crash_elf_data *ced = arg;
+
+	ced->gart_start = start;
+	ced->gart_end = end;
+
+	/* Not expecting more than 1 gart aperture */
+	return 1;
+}
+
+
+/* Gather all the required information to prepare elf headers for ram regions */
+static void fill_up_crash_elf_data(struct crash_elf_data *ced,
+				   struct kimage *image)
+{
+	unsigned int nr_ranges = 0;
+
+	ced->image = image;
+
+	walk_system_ram_range(0, -1, &nr_ranges,
+				get_nr_ram_ranges_callback);
+
+	ced->max_nr_ranges = nr_ranges;
+
+	/*
+	 * We don't create ELF headers for GART aperture as an attempt
+	 * to dump this memory in second kernel leads to hang/crash.
+	 * If gart aperture is present, one needs to exclude that region
+	 * and that could lead to need of extra phdr.
+	 */
+	walk_iomem_res("GART", IORESOURCE_MEM, 0, -1,
+				ced, get_gart_ranges_callback);
+
+	/*
+	 * If we have gart region, excluding that could potentially split
+	 * a memory range, resulting in extra header. Account for  that.
+	 */
+	if (ced->gart_end)
+		ced->max_nr_ranges++;
+
+	/* Exclusion of crash region could split memory ranges */
+	ced->max_nr_ranges++;
+
+	/* If crashk_low_res is not 0, another range split possible */
+	if (crashk_low_res.end != 0)
+		ced->max_nr_ranges++;
+}
+
+static int exclude_mem_range(struct crash_mem *mem,
+		unsigned long long mstart, unsigned long long mend)
+{
+	int i, j;
+	unsigned long long start, end;
+	struct crash_mem_range temp_range = {0, 0};
+
+	for (i = 0; i < mem->nr_ranges; i++) {
+		start = mem->ranges[i].start;
+		end = mem->ranges[i].end;
+
+		if (mstart > end || mend < start)
+			continue;
+
+		/* Truncate any area outside of range */
+		if (mstart < start)
+			mstart = start;
+		if (mend > end)
+			mend = end;
+
+		/* Found completely overlapping range */
+		if (mstart == start && mend == end) {
+			mem->ranges[i].start = 0;
+			mem->ranges[i].end = 0;
+			if (i < mem->nr_ranges - 1) {
+				/* Shift rest of the ranges to left */
+				for (j = i; j < mem->nr_ranges - 1; j++) {
+					mem->ranges[j].start =
+						mem->ranges[j+1].start;
+					mem->ranges[j].end =
+							mem->ranges[j+1].end;
+				}
+			}
+			mem->nr_ranges--;
+			return 0;
+		}
+
+		if (mstart > start && mend < end) {
+			/* Split original range */
+			mem->ranges[i].end = mstart - 1;
+			temp_range.start = mend + 1;
+			temp_range.end = end;
+		} else if (mstart != start)
+			mem->ranges[i].end = mstart - 1;
+		else
+			mem->ranges[i].start = mend + 1;
+		break;
+	}
+
+	/* If a split happend, add the split to array */
+	if (!temp_range.end)
+		return 0;
+
+	/* Split happened */
+	if (i == CRASH_MAX_RANGES - 1) {
+		pr_err("Too many crash ranges after split\n");
+		return -ENOMEM;
+	}
+
+	/* Location where new range should go */
+	j = i + 1;
+	if (j < mem->nr_ranges) {
+		/* Move over all ranges one slot towards the end */
+		for (i = mem->nr_ranges - 1; i >= j; i--)
+			mem->ranges[i + 1] = mem->ranges[i];
+	}
+
+	mem->ranges[j].start = temp_range.start;
+	mem->ranges[j].end = temp_range.end;
+	mem->nr_ranges++;
+	return 0;
+}
+
+/*
+ * Look for any unwanted ranges between mstart, mend and remove them. This
+ * might lead to split and split ranges are put in ced->mem.ranges[] array
+ */
+static int elf_header_exclude_ranges(struct crash_elf_data *ced,
+		unsigned long long mstart, unsigned long long mend)
+{
+	struct crash_mem *cmem = &ced->mem;
+	int ret = 0;
+
+	memset(cmem->ranges, 0, sizeof(cmem->ranges));
+
+	cmem->ranges[0].start = mstart;
+	cmem->ranges[0].end = mend;
+	cmem->nr_ranges = 1;
+
+	/* Exclude crashkernel region */
+	ret = exclude_mem_range(cmem, crashk_res.start, crashk_res.end);
+	if (ret)
+		return ret;
+
+	ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
+	if (ret)
+		return ret;
+
+	/* Exclude GART region */
+	if (ced->gart_end) {
+		ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int prepare_elf64_ram_headers_callback(u64 start, u64 end, void *arg)
+{
+	struct crash_elf_data *ced = arg;
+	Elf64_Ehdr *ehdr;
+	Elf64_Phdr *phdr;
+	unsigned long mstart, mend;
+	struct kimage *image = ced->image;
+	struct crash_mem *cmem;
+	int ret, i;
+
+	ehdr = ced->ehdr;
+
+	/* Exclude unwanted mem ranges */
+	ret = elf_header_exclude_ranges(ced, start, end);
+	if (ret)
+		return ret;
+
+	/* Go through all the ranges in ced->mem.ranges[] and prepare phdr */
+	cmem = &ced->mem;
+
+	for (i = 0; i < cmem->nr_ranges; i++) {
+		mstart = cmem->ranges[i].start;
+		mend = cmem->ranges[i].end;
+
+		phdr = ced->bufp;
+		ced->bufp += sizeof(Elf64_Phdr);
+
+		phdr->p_type = PT_LOAD;
+		phdr->p_flags = PF_R|PF_W|PF_X;
+		phdr->p_offset  = mstart;
+
+		/*
+		 * If a range matches backup region, adjust offset to backup
+		 * segment.
+		 */
+		if (mstart == image->arch.backup_src_start &&
+		    (mend - mstart + 1) == image->arch.backup_src_sz)
+			phdr->p_offset = image->arch.backup_load_addr;
+
+		phdr->p_paddr = mstart;
+		phdr->p_vaddr = (unsigned long long) __va(mstart);
+		phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
+		phdr->p_align = 0;
+		ehdr->e_phnum++;
+		pr_debug("Crash PT_LOAD elf header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n",
+			phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
+			ehdr->e_phnum, phdr->p_offset);
+	}
+
+	return ret;
+}
+
+static int prepare_elf64_headers(struct crash_elf_data *ced,
+		void **addr, unsigned long *sz)
+{
+	Elf64_Ehdr *ehdr;
+	Elf64_Phdr *phdr;
+	unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
+	unsigned char *buf, *bufp;
+	unsigned int cpu;
+	unsigned long long notes_addr;
+	int ret;
+
+	/* extra phdr for vmcoreinfo elf note */
+	nr_phdr = nr_cpus + 1;
+	nr_phdr += ced->max_nr_ranges;
+
+	/*
+	 * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
+	 * area on x86_64 (ffffffff80000000 - ffffffffa0000000).
+	 * I think this is required by tools like gdb. So same physical
+	 * memory will be mapped in two elf headers. One will contain kernel
+	 * text virtual addresses and other will have __va(physical) addresses.
+	 */
+
+	nr_phdr++;
+	elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
+	elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
+
+	buf = vzalloc(elf_sz);
+	if (!buf)
+		return -ENOMEM;
+
+	bufp = buf;
+	ehdr = (Elf64_Ehdr *)bufp;
+	bufp += sizeof(Elf64_Ehdr);
+	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+	ehdr->e_ident[EI_OSABI] = ELF_OSABI;
+	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
+	ehdr->e_type = ET_CORE;
+	ehdr->e_machine = ELF_ARCH;
+	ehdr->e_version = EV_CURRENT;
+	ehdr->e_phoff = sizeof(Elf64_Ehdr);
+	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
+	ehdr->e_phentsize = sizeof(Elf64_Phdr);
+
+	/* Prepare one phdr of type PT_NOTE for each present cpu */
+	for_each_present_cpu(cpu) {
+		phdr = (Elf64_Phdr *)bufp;
+		bufp += sizeof(Elf64_Phdr);
+		phdr->p_type = PT_NOTE;
+		notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
+		phdr->p_offset = phdr->p_paddr = notes_addr;
+		phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
+		(ehdr->e_phnum)++;
+	}
+
+	/* Prepare one PT_NOTE header for vmcoreinfo */
+	phdr = (Elf64_Phdr *)bufp;
+	bufp += sizeof(Elf64_Phdr);
+	phdr->p_type = PT_NOTE;
+	phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
+	phdr->p_filesz = phdr->p_memsz = sizeof(vmcoreinfo_note);
+	(ehdr->e_phnum)++;
+
+#ifdef CONFIG_X86_64
+	/* Prepare PT_LOAD type program header for kernel text region */
+	phdr = (Elf64_Phdr *)bufp;
+	bufp += sizeof(Elf64_Phdr);
+	phdr->p_type = PT_LOAD;
+	phdr->p_flags = PF_R|PF_W|PF_X;
+	phdr->p_vaddr = (Elf64_Addr)_text;
+	phdr->p_filesz = phdr->p_memsz = _end - _text;
+	phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
+	(ehdr->e_phnum)++;
+#endif
+
+	/* Prepare PT_LOAD headers for system ram chunks. */
+	ced->ehdr = ehdr;
+	ced->bufp = bufp;
+	ret = walk_system_ram_res(0, -1, ced,
+			prepare_elf64_ram_headers_callback);
+	if (ret < 0)
+		return ret;
+
+	*addr = buf;
+	*sz = elf_sz;
+	return 0;
+}
+
+/* Prepare elf headers. Return addr and size */
+static int prepare_elf_headers(struct kimage *image, void **addr,
+					unsigned long *sz)
+{
+	struct crash_elf_data *ced;
+	int ret;
+
+	ced = kzalloc(sizeof(*ced), GFP_KERNEL);
+	if (!ced)
+		return -ENOMEM;
+
+	fill_up_crash_elf_data(ced, image);
+
+	/* By default prepare 64bit headers */
+	ret =  prepare_elf64_headers(ced, addr, sz);
+	kfree(ced);
+	return ret;
+}
+
+static int add_e820_entry(struct boot_params *params, struct e820entry *entry)
+{
+	unsigned int nr_e820_entries;
+
+	nr_e820_entries = params->e820_entries;
+	if (nr_e820_entries >= E820MAX)
+		return 1;
+
+	memcpy(&params->e820_map[nr_e820_entries], entry,
+			sizeof(struct e820entry));
+	params->e820_entries++;
+	return 0;
+}
+
+static int memmap_entry_callback(u64 start, u64 end, void *arg)
+{
+	struct crash_memmap_data *cmd = arg;
+	struct boot_params *params = cmd->params;
+	struct e820entry ei;
+
+	ei.addr = start;
+	ei.size = end - start + 1;
+	ei.type = cmd->type;
+	add_e820_entry(params, &ei);
+
+	return 0;
+}
+
+static int memmap_exclude_ranges(struct kimage *image, struct crash_mem *cmem,
+				 unsigned long long mstart,
+				 unsigned long long mend)
+{
+	unsigned long start, end;
+	int ret = 0;
+
+	cmem->ranges[0].start = mstart;
+	cmem->ranges[0].end = mend;
+	cmem->nr_ranges = 1;
+
+	/* Exclude Backup region */
+	start = image->arch.backup_load_addr;
+	end = start + image->arch.backup_src_sz - 1;
+	ret = exclude_mem_range(cmem, start, end);
+	if (ret)
+		return ret;
+
+	/* Exclude elf header region */
+	start = image->arch.elf_load_addr;
+	end = start + image->arch.elf_headers_sz - 1;
+	return exclude_mem_range(cmem, start, end);
+}
+
+/* Prepare memory map for crash dump kernel */
+int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
+{
+	int i, ret = 0;
+	unsigned long flags;
+	struct e820entry ei;
+	struct crash_memmap_data cmd;
+	struct crash_mem *cmem;
+
+	cmem = vzalloc(sizeof(struct crash_mem));
+	if (!cmem)
+		return -ENOMEM;
+
+	memset(&cmd, 0, sizeof(struct crash_memmap_data));
+	cmd.params = params;
+
+	/* Add first 640K segment */
+	ei.addr = image->arch.backup_src_start;
+	ei.size = image->arch.backup_src_sz;
+	ei.type = E820_RAM;
+	add_e820_entry(params, &ei);
+
+	/* Add ACPI tables */
+	cmd.type = E820_ACPI;
+	flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd,
+		       memmap_entry_callback);
+
+	/* Add ACPI Non-volatile Storage */
+	cmd.type = E820_NVS;
+	walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd,
+			memmap_entry_callback);
+
+	/* Add crashk_low_res region */
+	if (crashk_low_res.end) {
+		ei.addr = crashk_low_res.start;
+		ei.size = crashk_low_res.end - crashk_low_res.start + 1;
+		ei.type = E820_RAM;
+		add_e820_entry(params, &ei);
+	}
+
+	/* Exclude some ranges from crashk_res and add rest to memmap */
+	ret = memmap_exclude_ranges(image, cmem, crashk_res.start,
+						crashk_res.end);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < cmem->nr_ranges; i++) {
+		ei.size = cmem->ranges[i].end - cmem->ranges[i].start + 1;
+
+		/* If entry is less than a page, skip it */
+		if (ei.size < PAGE_SIZE)
+			continue;
+		ei.addr = cmem->ranges[i].start;
+		ei.type = E820_RAM;
+		add_e820_entry(params, &ei);
+	}
+
+out:
+	vfree(cmem);
+	return ret;
+}
+
+static int determine_backup_region(u64 start, u64 end, void *arg)
+{
+	struct kimage *image = arg;
+
+	image->arch.backup_src_start = start;
+	image->arch.backup_src_sz = end - start + 1;
+
+	/* Expecting only one range for backup region */
+	return 1;
+}
+
+int crash_load_segments(struct kimage *image)
+{
+	unsigned long src_start, src_sz, elf_sz;
+	void *elf_addr;
+	int ret;
+
+	/*
+	 * Determine and load a segment for backup area. First 640K RAM
+	 * region is backup source
+	 */
+
+	ret = walk_system_ram_res(KEXEC_BACKUP_SRC_START, KEXEC_BACKUP_SRC_END,
+				image, determine_backup_region);
+
+	/* Zero or postive return values are ok */
+	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) {
+		/*
+		 * 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);
+		if (ret)
+			return ret;
+		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);
+	}
+
+	/* Prepare elf headers and add a segment */
+	ret = prepare_elf_headers(image, &elf_addr, &elf_sz);
+	if (ret)
+		return ret;
+
+	image->arch.elf_headers = elf_addr;
+	image->arch.elf_headers_sz = elf_sz;
+
+	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
+			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
+			&image->arch.elf_load_addr);
+	if (ret) {
+		vfree((void *)image->arch.elf_headers);
+		return ret;
+	}
+	pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+		 image->arch.elf_load_addr, elf_sz, elf_sz);
+
+	return ret;
+}
+#endif /* CONFIG_KEXEC_FILE */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/devicetree.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/devicetree.c
--- linux-libre-3.16-gnu/arch/x86/kernel/devicetree.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/devicetree.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include <asm/apic.h>
 #include <asm/pci_x86.h>
 #include <asm/setup.h>
+#include <asm/i8259.h>
 
 __initdata u64 initial_dtb;
 char __initdata cmd_line[COMMAND_LINE_SIZE];
@@ -165,82 +166,6 @@ static void __init dtb_lapic_setup(void)
 #ifdef CONFIG_X86_IO_APIC
 static unsigned int ioapic_id;
 
-static void __init dtb_add_ioapic(struct device_node *dn)
-{
-	struct resource r;
-	int ret;
-
-	ret = of_address_to_resource(dn, 0, &r);
-	if (ret) {
-		printk(KERN_ERR "Can't obtain address from node %s.\n",
-				dn->full_name);
-		return;
-	}
-	mp_register_ioapic(++ioapic_id, r.start, gsi_top);
-}
-
-static void __init dtb_ioapic_setup(void)
-{
-	struct device_node *dn;
-
-	for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
-		dtb_add_ioapic(dn);
-
-	if (nr_ioapics) {
-		of_ioapic = 1;
-		return;
-	}
-	printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
-}
-#else
-static void __init dtb_ioapic_setup(void) {}
-#endif
-
-static void __init dtb_apic_setup(void)
-{
-	dtb_lapic_setup();
-	dtb_ioapic_setup();
-}
-
-#ifdef CONFIG_OF_FLATTREE
-static void __init x86_flattree_get_config(void)
-{
-	u32 size, map_len;
-	void *dt;
-
-	if (!initial_dtb)
-		return;
-
-	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
-
-	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
-	size = of_get_flat_dt_size();
-	if (map_len < size) {
-		early_iounmap(dt, map_len);
-		initial_boot_params = dt = early_memremap(initial_dtb, size);
-		map_len = size;
-	}
-
-	unflatten_and_copy_device_tree();
-	early_iounmap(dt, map_len);
-}
-#else
-static inline void x86_flattree_get_config(void) { }
-#endif
-
-void __init x86_dtb_init(void)
-{
-	x86_flattree_get_config();
-
-	if (!of_have_populated_dt())
-		return;
-
-	dtb_setup_hpet();
-	dtb_apic_setup();
-}
-
-#ifdef CONFIG_X86_IO_APIC
-
 struct of_ioapic_type {
 	u32 out_type;
 	u32 trigger;
@@ -276,10 +201,8 @@ static int ioapic_xlate(struct irq_domai
 			const u32 *intspec, u32 intsize,
 			irq_hw_number_t *out_hwirq, u32 *out_type)
 {
-	struct io_apic_irq_attr attr;
 	struct of_ioapic_type *it;
-	u32 line, idx;
-	int rc;
+	u32 line, idx, gsi;
 
 	if (WARN_ON(intsize < 2))
 		return -EINVAL;
@@ -291,13 +214,10 @@ static int ioapic_xlate(struct irq_domai
 
 	it = &of_ioapic_type[intspec[1]];
 
-	idx = (u32) domain->host_data;
-	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
-
-	rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
-					cpu_to_node(0), &attr);
-	if (rc)
-		return rc;
+	idx = (u32)(long)domain->host_data;
+	gsi = mp_pin_to_gsi(idx, line);
+	if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
+		return -EBUSY;
 
 	*out_hwirq = line;
 	*out_type = it->out_type;
@@ -305,81 +225,86 @@ static int ioapic_xlate(struct irq_domai
 }
 
 const struct irq_domain_ops ioapic_irq_domain_ops = {
+	.map = mp_irqdomain_map,
+	.unmap = mp_irqdomain_unmap,
 	.xlate = ioapic_xlate,
 };
 
-static void dt_add_ioapic_domain(unsigned int ioapic_num,
-		struct device_node *np)
+static void __init dtb_add_ioapic(struct device_node *dn)
 {
-	struct irq_domain *id;
-	struct mp_ioapic_gsi *gsi_cfg;
+	struct resource r;
 	int ret;
-	int num;
-
-	gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
-	num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
-
-	id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
-			(void *)ioapic_num);
-	BUG_ON(!id);
-	if (gsi_cfg->gsi_base == 0) {
-		/*
-		 * The first NR_IRQS_LEGACY irq descs are allocated in
-		 * early_irq_init() and need just a mapping. The
-		 * remaining irqs need both. All of them are preallocated
-		 * and assigned so we can keep the 1:1 mapping which the ioapic
-		 * is having.
-		 */
-		irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &ioapic_irq_domain_ops,
+		.dev = dn,
+	};
 
-		if (num > NR_IRQS_LEGACY) {
-			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
-					NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
-			if (ret)
-				pr_err("Error creating mapping for the "
-						"remaining IRQs: %d\n", ret);
-		}
-		irq_set_default_host(id);
-	} else {
-		ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
-		if (ret)
-			pr_err("Error creating IRQ mapping: %d\n", ret);
+	ret = of_address_to_resource(dn, 0, &r);
+	if (ret) {
+		printk(KERN_ERR "Can't obtain address from node %s.\n",
+				dn->full_name);
+		return;
 	}
+	mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
 }
 
-static void __init ioapic_add_ofnode(struct device_node *np)
+static void __init dtb_ioapic_setup(void)
 {
-	struct resource r;
-	int i, ret;
+	struct device_node *dn;
 
-	ret = of_address_to_resource(np, 0, &r);
-	if (ret) {
-		printk(KERN_ERR "Failed to obtain address for %s\n",
-				np->full_name);
+	for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+		dtb_add_ioapic(dn);
+
+	if (nr_ioapics) {
+		of_ioapic = 1;
 		return;
 	}
+	printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
 
-	for (i = 0; i < nr_ioapics; i++) {
-		if (r.start == mpc_ioapic_addr(i)) {
-			dt_add_ioapic_domain(i, np);
-			return;
-		}
-	}
-	printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+static void __init dtb_apic_setup(void)
+{
+	dtb_lapic_setup();
+	dtb_ioapic_setup();
 }
 
-void __init x86_add_irq_domains(void)
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
 {
-	struct device_node *dp;
+	u32 size, map_len;
+	void *dt;
 
-	if (!of_have_populated_dt())
+	if (!initial_dtb)
 		return;
 
-	for_each_node_with_property(dp, "interrupt-controller") {
-		if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
-			ioapic_add_ofnode(dp);
+	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
+
+	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+	size = of_get_flat_dt_size();
+	if (map_len < size) {
+		early_iounmap(dt, map_len);
+		initial_boot_params = dt = early_memremap(initial_dtb, size);
+		map_len = size;
 	}
+
+	unflatten_and_copy_device_tree();
+	early_iounmap(dt, map_len);
 }
 #else
-void __init x86_add_irq_domains(void) { }
+static inline void x86_flattree_get_config(void) { }
 #endif
+
+void __init x86_dtb_init(void)
+{
+	x86_flattree_get_config();
+
+	if (!of_have_populated_dt())
+		return;
+
+	dtb_setup_hpet();
+	dtb_apic_setup();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/entry_32.S linux-libre-3.17-rc7-gnu/arch/x86/kernel/entry_32.S
--- linux-libre-3.16-gnu/arch/x86/kernel/entry_32.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/entry_32.S	2014-09-28 17:29:07.000000000 -0400
@@ -683,7 +683,7 @@ END(syscall_badsys)
 sysenter_badsys:
 	movl $-ENOSYS,%eax
 	jmp sysenter_after_call
-END(syscall_badsys)
+END(sysenter_badsys)
 	CFI_ENDPROC
 
 .macro FIXUP_ESPFIX_STACK
@@ -1059,9 +1059,6 @@ ENTRY(mcount)
 END(mcount)
 
 ENTRY(ftrace_caller)
-	cmpl $0, function_trace_stop
-	jne  ftrace_stub
-
 	pushl %eax
 	pushl %ecx
 	pushl %edx
@@ -1093,8 +1090,6 @@ END(ftrace_caller)
 
 ENTRY(ftrace_regs_caller)
 	pushf	/* push flags before compare (in cs location) */
-	cmpl $0, function_trace_stop
-	jne ftrace_restore_flags
 
 	/*
 	 * i386 does not save SS and ESP when coming from kernel.
@@ -1153,7 +1148,6 @@ GLOBAL(ftrace_regs_call)
 	popf			/* Pop flags at end (no addl to corrupt flags) */
 	jmp ftrace_ret
 
-ftrace_restore_flags:
 	popf
 	jmp  ftrace_stub
 #else /* ! CONFIG_DYNAMIC_FTRACE */
@@ -1162,9 +1156,6 @@ ENTRY(mcount)
 	cmpl $__PAGE_OFFSET, %esp
 	jb ftrace_stub		/* Paging not enabled yet? */
 
-	cmpl $0, function_trace_stop
-	jne  ftrace_stub
-
 	cmpl $ftrace_stub, ftrace_trace_function
 	jnz trace
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/entry_64.S linux-libre-3.17-rc7-gnu/arch/x86/kernel/entry_64.S
--- linux-libre-3.16-gnu/arch/x86/kernel/entry_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/entry_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -207,7 +207,6 @@ ENDPROC(native_usergs_sysret64)
  */
 	.macro XCPT_FRAME start=1 offset=0
 	INTR_FRAME \start, RIP+\offset-ORIG_RAX
-	/*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
 	.endm
 
 /*
@@ -287,21 +286,21 @@ ENDPROC(native_usergs_sysret64)
 ENTRY(save_paranoid)
 	XCPT_FRAME 1 RDI+8
 	cld
-	movq_cfi rdi, RDI+8
-	movq_cfi rsi, RSI+8
+	movq %rdi, RDI+8(%rsp)
+	movq %rsi, RSI+8(%rsp)
 	movq_cfi rdx, RDX+8
 	movq_cfi rcx, RCX+8
 	movq_cfi rax, RAX+8
-	movq_cfi r8, R8+8
-	movq_cfi r9, R9+8
-	movq_cfi r10, R10+8
-	movq_cfi r11, R11+8
+	movq %r8, R8+8(%rsp)
+	movq %r9, R9+8(%rsp)
+	movq %r10, R10+8(%rsp)
+	movq %r11, R11+8(%rsp)
 	movq_cfi rbx, RBX+8
-	movq_cfi rbp, RBP+8
-	movq_cfi r12, R12+8
-	movq_cfi r13, R13+8
-	movq_cfi r14, R14+8
-	movq_cfi r15, R15+8
+	movq %rbp, RBP+8(%rsp)
+	movq %r12, R12+8(%rsp)
+	movq %r13, R13+8(%rsp)
+	movq %r14, R14+8(%rsp)
+	movq %r15, R15+8(%rsp)
 	movl $1,%ebx
 	movl $MSR_GS_BASE,%ecx
 	rdmsr
@@ -1387,21 +1386,21 @@ ENTRY(error_entry)
 	CFI_ADJUST_CFA_OFFSET 15*8
 	/* oldrax contains error code */
 	cld
-	movq_cfi rdi, RDI+8
-	movq_cfi rsi, RSI+8
-	movq_cfi rdx, RDX+8
-	movq_cfi rcx, RCX+8
-	movq_cfi rax, RAX+8
-	movq_cfi  r8,  R8+8
-	movq_cfi  r9,  R9+8
-	movq_cfi r10, R10+8
-	movq_cfi r11, R11+8
+	movq %rdi, RDI+8(%rsp)
+	movq %rsi, RSI+8(%rsp)
+	movq %rdx, RDX+8(%rsp)
+	movq %rcx, RCX+8(%rsp)
+	movq %rax, RAX+8(%rsp)
+	movq  %r8,  R8+8(%rsp)
+	movq  %r9,  R9+8(%rsp)
+	movq %r10, R10+8(%rsp)
+	movq %r11, R11+8(%rsp)
 	movq_cfi rbx, RBX+8
-	movq_cfi rbp, RBP+8
-	movq_cfi r12, R12+8
-	movq_cfi r13, R13+8
-	movq_cfi r14, R14+8
-	movq_cfi r15, R15+8
+	movq %rbp, RBP+8(%rsp)
+	movq %r12, R12+8(%rsp)
+	movq %r13, R13+8(%rsp)
+	movq %r14, R14+8(%rsp)
+	movq %r15, R15+8(%rsp)
 	xorl %ebx,%ebx
 	testl $3,CS+8(%rsp)
 	je error_kernelspace
@@ -1419,6 +1418,7 @@ error_sti:
  * compat mode. Check for these here too.
  */
 error_kernelspace:
+	CFI_REL_OFFSET rcx, RCX+8
 	incl %ebx
 	leaq native_irq_return_iret(%rip),%rcx
 	cmpq %rcx,RIP+8(%rsp)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/ftrace.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/ftrace.c
--- linux-libre-3.16-gnu/arch/x86/kernel/ftrace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/ftrace.c	2014-09-28 17:29:07.000000000 -0400
@@ -703,6 +703,9 @@ void prepare_ftrace_return(unsigned long
 	unsigned long return_hooker = (unsigned long)
 				&return_to_handler;
 
+	if (unlikely(ftrace_graph_is_dead()))
+		return;
+
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/i387.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/i387.c
--- linux-libre-3.16-gnu/arch/x86/kernel/i387.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/i387.c	2014-09-28 17:29:07.000000000 -0400
@@ -375,7 +375,7 @@ int xstateregs_set(struct task_struct *t
 	/*
 	 * These bits must be zero.
 	 */
-	xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+	memset(xsave_hdr->reserved, 0, 48);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/iosf_mbi.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/iosf_mbi.c
--- linux-libre-3.16-gnu/arch/x86/kernel/iosf_mbi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/iosf_mbi.c	2014-09-28 17:29:07.000000000 -0400
@@ -202,7 +202,7 @@ static int iosf_mbi_probe(struct pci_dev
 	return 0;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
+static const struct pci_device_id iosf_mbi_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) },
 	{ 0, },
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/irqinit.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/irqinit.c
--- linux-libre-3.16-gnu/arch/x86/kernel/irqinit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/irqinit.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,7 @@ void __init init_ISA_irqs(void)
 #endif
 	legacy_pic->init(0);
 
-	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+	for (i = 0; i < nr_legacy_irqs(); i++)
 		irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
 }
 
@@ -87,12 +87,6 @@ void __init init_IRQ(void)
 	int i;
 
 	/*
-	 * We probably need a better place for this, but it works for
-	 * now ...
-	 */
-	x86_add_irq_domains();
-
-	/*
 	 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
 	 * If these IRQ's are handled by legacy interrupt-controllers like PIC,
 	 * then this configuration will likely be static after the boot. If
@@ -100,7 +94,7 @@ void __init init_IRQ(void)
 	 * then this vector space can be freed and re-used dynamically as the
 	 * irq's migrate etc.
 	 */
-	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+	for (i = 0; i < nr_legacy_irqs(); i++)
 		per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
 
 	x86_init.irqs.intr_init();
@@ -121,7 +115,7 @@ void setup_vector_irq(int cpu)
 	 * legacy PIC, for the new cpu that is coming online, setup the static
 	 * legacy vector to irq mapping:
 	 */
-	for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
+	for (irq = 0; irq < nr_legacy_irqs(); irq++)
 		per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
 #endif
 
@@ -209,7 +203,7 @@ void __init native_init_IRQ(void)
 		set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
 	}
 
-	if (!acpi_ioapic && !of_ioapic)
+	if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs())
 		setup_irq(2, &irq2);
 
 #ifdef CONFIG_X86_32
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/kexec-bzimage64.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/kexec-bzimage64.c
--- linux-libre-3.16-gnu/arch/x86/kernel/kexec-bzimage64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/kexec-bzimage64.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,553 @@
+/*
+ * Kexec bzImage loader
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ * Authors:
+ *      Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#define pr_fmt(fmt)	"kexec-bzImage64: " fmt
+
+#include <linux/string.h>
+#include <linux/printk.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/efi.h>
+#include <linux/verify_pefile.h>
+#include <keys/system_keyring.h>
+
+#include <asm/bootparam.h>
+#include <asm/setup.h>
+#include <asm/crash.h>
+#include <asm/efi.h>
+
+#define MAX_ELFCOREHDR_STR_LEN	30	/* elfcorehdr=0x<64bit-value> */
+
+/*
+ * Defines lowest physical address for various segments. Not sure where
+ * exactly these limits came from. Current bzimage64 loader in kexec-tools
+ * uses these so I am retaining it. It can be changed over time as we gain
+ * more insight.
+ */
+#define MIN_PURGATORY_ADDR	0x3000
+#define MIN_BOOTPARAM_ADDR	0x3000
+#define MIN_KERNEL_LOAD_ADDR	0x100000
+#define MIN_INITRD_LOAD_ADDR	0x1000000
+
+/*
+ * This is a place holder for all boot loader specific data structure which
+ * gets allocated in one call but gets freed much later during cleanup
+ * time. Right now there is only one field but it can grow as need be.
+ */
+struct bzimage64_data {
+	/*
+	 * Temporary buffer to hold bootparams buffer. This should be
+	 * freed once the bootparam segment has been loaded.
+	 */
+	void *bootparams_buf;
+};
+
+static int setup_initrd(struct boot_params *params,
+		unsigned long initrd_load_addr, unsigned long initrd_len)
+{
+	params->hdr.ramdisk_image = initrd_load_addr & 0xffffffffUL;
+	params->hdr.ramdisk_size = initrd_len & 0xffffffffUL;
+
+	params->ext_ramdisk_image = initrd_load_addr >> 32;
+	params->ext_ramdisk_size = initrd_len >> 32;
+
+	return 0;
+}
+
+static int setup_cmdline(struct kimage *image, struct boot_params *params,
+			 unsigned long bootparams_load_addr,
+			 unsigned long cmdline_offset, char *cmdline,
+			 unsigned long cmdline_len)
+{
+	char *cmdline_ptr = ((char *)params) + cmdline_offset;
+	unsigned long cmdline_ptr_phys, len;
+	uint32_t cmdline_low_32, cmdline_ext_32;
+
+	memcpy(cmdline_ptr, cmdline, cmdline_len);
+	if (image->type == KEXEC_TYPE_CRASH) {
+		len = sprintf(cmdline_ptr + cmdline_len - 1,
+			" elfcorehdr=0x%lx", image->arch.elf_load_addr);
+		cmdline_len += len;
+	}
+	cmdline_ptr[cmdline_len - 1] = '\0';
+
+	pr_debug("Final command line is: %s\n", cmdline_ptr);
+	cmdline_ptr_phys = bootparams_load_addr + cmdline_offset;
+	cmdline_low_32 = cmdline_ptr_phys & 0xffffffffUL;
+	cmdline_ext_32 = cmdline_ptr_phys >> 32;
+
+	params->hdr.cmd_line_ptr = cmdline_low_32;
+	if (cmdline_ext_32)
+		params->ext_cmd_line_ptr = cmdline_ext_32;
+
+	return 0;
+}
+
+static int setup_e820_entries(struct boot_params *params)
+{
+	unsigned int nr_e820_entries;
+
+	nr_e820_entries = e820_saved.nr_map;
+
+	/* TODO: Pass entries more than E820MAX in bootparams setup data */
+	if (nr_e820_entries > E820MAX)
+		nr_e820_entries = E820MAX;
+
+	params->e820_entries = nr_e820_entries;
+	memcpy(&params->e820_map, &e820_saved.map,
+	       nr_e820_entries * sizeof(struct e820entry));
+
+	return 0;
+}
+
+#ifdef CONFIG_EFI
+static int setup_efi_info_memmap(struct boot_params *params,
+				  unsigned long params_load_addr,
+				  unsigned int efi_map_offset,
+				  unsigned int efi_map_sz)
+{
+	void *efi_map = (void *)params + efi_map_offset;
+	unsigned long efi_map_phys_addr = params_load_addr + efi_map_offset;
+	struct efi_info *ei = &params->efi_info;
+
+	if (!efi_map_sz)
+		return 0;
+
+	efi_runtime_map_copy(efi_map, efi_map_sz);
+
+	ei->efi_memmap = efi_map_phys_addr & 0xffffffff;
+	ei->efi_memmap_hi = efi_map_phys_addr >> 32;
+	ei->efi_memmap_size = efi_map_sz;
+
+	return 0;
+}
+
+static int
+prepare_add_efi_setup_data(struct boot_params *params,
+		       unsigned long params_load_addr,
+		       unsigned int efi_setup_data_offset)
+{
+	unsigned long setup_data_phys;
+	struct setup_data *sd = (void *)params + efi_setup_data_offset;
+	struct efi_setup_data *esd = (void *)sd + sizeof(struct setup_data);
+
+	esd->fw_vendor = efi.fw_vendor;
+	esd->runtime = efi.runtime;
+	esd->tables = efi.config_table;
+	esd->smbios = efi.smbios;
+
+	sd->type = SETUP_EFI;
+	sd->len = sizeof(struct efi_setup_data);
+
+	/* Add setup data */
+	setup_data_phys = params_load_addr + efi_setup_data_offset;
+	sd->next = params->hdr.setup_data;
+	params->hdr.setup_data = setup_data_phys;
+
+	return 0;
+}
+
+static int
+setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
+		unsigned int efi_map_offset, unsigned int efi_map_sz,
+		unsigned int efi_setup_data_offset)
+{
+	struct efi_info *current_ei = &boot_params.efi_info;
+	struct efi_info *ei = &params->efi_info;
+
+	if (!current_ei->efi_memmap_size)
+		return 0;
+
+	/*
+	 * If 1:1 mapping is not enabled, second kernel can not setup EFI
+	 * and use EFI run time services. User space will have to pass
+	 * acpi_rsdp=<addr> on kernel command line to make second kernel boot
+	 * without efi.
+	 */
+	if (efi_enabled(EFI_OLD_MEMMAP))
+		return 0;
+
+	ei->efi_loader_signature = current_ei->efi_loader_signature;
+	ei->efi_systab = current_ei->efi_systab;
+	ei->efi_systab_hi = current_ei->efi_systab_hi;
+
+	ei->efi_memdesc_version = current_ei->efi_memdesc_version;
+	ei->efi_memdesc_size = efi_get_runtime_map_desc_size();
+
+	setup_efi_info_memmap(params, params_load_addr, efi_map_offset,
+			      efi_map_sz);
+	prepare_add_efi_setup_data(params, params_load_addr,
+				   efi_setup_data_offset);
+	return 0;
+}
+#endif /* CONFIG_EFI */
+
+static int
+setup_boot_parameters(struct kimage *image, struct boot_params *params,
+		      unsigned long params_load_addr,
+		      unsigned int efi_map_offset, unsigned int efi_map_sz,
+		      unsigned int efi_setup_data_offset)
+{
+	unsigned int nr_e820_entries;
+	unsigned long long mem_k, start, end;
+	int i, ret = 0;
+
+	/* Get subarch from existing bootparams */
+	params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch;
+
+	/* Copying screen_info will do? */
+	memcpy(&params->screen_info, &boot_params.screen_info,
+				sizeof(struct screen_info));
+
+	/* Fill in memsize later */
+	params->screen_info.ext_mem_k = 0;
+	params->alt_mem_k = 0;
+
+	/* Default APM info */
+	memset(&params->apm_bios_info, 0, sizeof(params->apm_bios_info));
+
+	/* Default drive info */
+	memset(&params->hd0_info, 0, sizeof(params->hd0_info));
+	memset(&params->hd1_info, 0, sizeof(params->hd1_info));
+
+	/* Default sysdesc table */
+	params->sys_desc_table.length = 0;
+
+	if (image->type == KEXEC_TYPE_CRASH) {
+		ret = crash_setup_memmap_entries(image, params);
+		if (ret)
+			return ret;
+	} else
+		setup_e820_entries(params);
+
+	nr_e820_entries = params->e820_entries;
+
+	for (i = 0; i < nr_e820_entries; i++) {
+		if (params->e820_map[i].type != E820_RAM)
+			continue;
+		start = params->e820_map[i].addr;
+		end = params->e820_map[i].addr + params->e820_map[i].size - 1;
+
+		if ((start <= 0x100000) && end > 0x100000) {
+			mem_k = (end >> 10) - (0x100000 >> 10);
+			params->screen_info.ext_mem_k = mem_k;
+			params->alt_mem_k = mem_k;
+			if (mem_k > 0xfc00)
+				params->screen_info.ext_mem_k = 0xfc00; /* 64M*/
+			if (mem_k > 0xffffffff)
+				params->alt_mem_k = 0xffffffff;
+		}
+	}
+
+#ifdef CONFIG_EFI
+	/* Setup EFI state */
+	setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
+			efi_setup_data_offset);
+#endif
+
+	/* Setup EDD info */
+	memcpy(params->eddbuf, boot_params.eddbuf,
+				EDDMAXNR * sizeof(struct edd_info));
+	params->eddbuf_entries = boot_params.eddbuf_entries;
+
+	memcpy(params->edd_mbr_sig_buffer, boot_params.edd_mbr_sig_buffer,
+	       EDD_MBR_SIG_MAX * sizeof(unsigned int));
+
+	return ret;
+}
+
+int bzImage64_probe(const char *buf, unsigned long len)
+{
+	int ret = -ENOEXEC;
+	struct setup_header *header;
+
+	/* kernel should be atleast two sectors long */
+	if (len < 2 * 512) {
+		pr_err("File is too short to be a bzImage\n");
+		return ret;
+	}
+
+	header = (struct setup_header *)(buf + offsetof(struct boot_params, hdr));
+	if (memcmp((char *)&header->header, "HdrS", 4) != 0) {
+		pr_err("Not a bzImage\n");
+		return ret;
+	}
+
+	if (header->boot_flag != 0xAA55) {
+		pr_err("No x86 boot sector present\n");
+		return ret;
+	}
+
+	if (header->version < 0x020C) {
+		pr_err("Must be at least protocol version 2.12\n");
+		return ret;
+	}
+
+	if (!(header->loadflags & LOADED_HIGH)) {
+		pr_err("zImage not a bzImage\n");
+		return ret;
+	}
+
+	if (!(header->xloadflags & XLF_KERNEL_64)) {
+		pr_err("Not a bzImage64. XLF_KERNEL_64 is not set.\n");
+		return ret;
+	}
+
+	if (!(header->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)) {
+		pr_err("XLF_CAN_BE_LOADED_ABOVE_4G is not set.\n");
+		return ret;
+	}
+
+	/*
+	 * Can't handle 32bit EFI as it does not allow loading kernel
+	 * above 4G. This should be handled by 32bit bzImage loader
+	 */
+	if (efi_enabled(EFI_RUNTIME_SERVICES) && !efi_enabled(EFI_64BIT)) {
+		pr_debug("EFI is 32 bit. Can't load kernel above 4G.\n");
+		return ret;
+	}
+
+	/* I've got a bzImage */
+	pr_debug("It's a relocatable bzImage64\n");
+	ret = 0;
+
+	return ret;
+}
+
+void *bzImage64_load(struct kimage *image, char *kernel,
+		     unsigned long kernel_len, char *initrd,
+		     unsigned long initrd_len, char *cmdline,
+		     unsigned long cmdline_len)
+{
+
+	struct setup_header *header;
+	int setup_sects, kern16_size, ret = 0;
+	unsigned long setup_header_size, params_cmdline_sz, params_misc_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;
+
+	header = (struct setup_header *)(kernel + setup_hdr_offset);
+	setup_sects = header->setup_sects;
+	if (setup_sects == 0)
+		setup_sects = 4;
+
+	kern16_size = (setup_sects + 1) * 512;
+	if (kernel_len < kern16_size) {
+		pr_err("bzImage truncated\n");
+		return ERR_PTR(-ENOEXEC);
+	}
+
+	if (cmdline_len > header->cmdline_size) {
+		pr_err("Kernel command line too long\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * In case of crash dump, we will append elfcorehdr=<addr> to
+	 * command line. Make sure it does not overflow
+	 */
+	if (cmdline_len + MAX_ELFCOREHDR_STR_LEN > header->cmdline_size) {
+		pr_debug("Appending elfcorehdr=<addr> to command line exceeds maximum allowed length\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Allocate and load backup region */
+	if (image->type == KEXEC_TYPE_CRASH) {
+		ret = crash_load_segments(image);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	/*
+	 * Load purgatory. For 64bit entry point, purgatory  code can be
+	 * anywhere.
+	 */
+	ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1,
+				   &purgatory_load_addr);
+	if (ret) {
+		pr_err("Loading purgatory failed\n");
+		return ERR_PTR(ret);
+	}
+
+	pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+
+
+	/*
+	 * Load Bootparams and cmdline and space for efi stuff.
+	 *
+	 * Allocate memory together for multiple data structures so
+	 * that they all can go in single area/segment and we don't
+	 * have to create separate segment for each. Keeps things
+	 * little bit simple
+	 */
+	efi_map_sz = efi_get_runtime_map_size();
+	efi_map_sz = ALIGN(efi_map_sz, 16);
+	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 +
+				sizeof(struct setup_data) +
+				sizeof(struct efi_setup_data);
+
+	params = kzalloc(params_misc_sz, GFP_KERNEL);
+	if (!params)
+		return ERR_PTR(-ENOMEM);
+	efi_map_offset = params_cmdline_sz;
+	efi_setup_data_offset = efi_map_offset + efi_map_sz;
+
+	/* Copy setup header onto bootparams. Documentation/x86/boot.txt */
+	setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset;
+
+	/* 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);
+	if (ret)
+		goto out_free_params;
+	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);
+
+	/* 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);
+	if (ret)
+		goto out_free_params;
+
+	pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+		 kernel_load_addr, kernel_memsz, kernel_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);
+		if (ret)
+			goto out_free_params;
+
+		pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+				initrd_load_addr, initrd_len, initrd_len);
+
+		setup_initrd(params, initrd_load_addr, initrd_len);
+	}
+
+	setup_cmdline(image, params, bootparam_load_addr,
+		      sizeof(struct boot_params), cmdline, cmdline_len);
+
+	/* bootloader info. Do we need a separate ID for kexec kernel loader? */
+	params->hdr.type_of_loader = 0x0D << 4;
+	params->hdr.loadflags = 0;
+
+	/* Setup purgatory regs for entry */
+	ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", &regs64,
+					     sizeof(regs64), 1);
+	if (ret)
+		goto out_free_params;
+
+	regs64.rbx = 0; /* Bootstrap Processor */
+	regs64.rsi = bootparam_load_addr;
+	regs64.rip = kernel_load_addr + 0x200;
+	stack = kexec_purgatory_get_symbol_addr(image, "stack_end");
+	if (IS_ERR(stack)) {
+		pr_err("Could not find address of symbol stack_end\n");
+		ret = -EINVAL;
+		goto out_free_params;
+	}
+
+	regs64.rsp = (unsigned long)stack;
+	ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", &regs64,
+					     sizeof(regs64), 0);
+	if (ret)
+		goto out_free_params;
+
+	ret = setup_boot_parameters(image, params, bootparam_load_addr,
+				    efi_map_offset, efi_map_sz,
+				    efi_setup_data_offset);
+	if (ret)
+		goto out_free_params;
+
+	/* Allocate loader specific data */
+	ldata = kzalloc(sizeof(struct bzimage64_data), GFP_KERNEL);
+	if (!ldata) {
+		ret = -ENOMEM;
+		goto out_free_params;
+	}
+
+	/*
+	 * Store pointer to params so that it could be freed after loading
+	 * params segment has been loaded and contents have been copied
+	 * somewhere else.
+	 */
+	ldata->bootparams_buf = params;
+	return ldata;
+
+out_free_params:
+	kfree(params);
+	return ERR_PTR(ret);
+}
+
+/* This cleanup function is called after various segments have been loaded */
+int bzImage64_cleanup(void *loader_data)
+{
+	struct bzimage64_data *ldata = loader_data;
+
+	if (!ldata)
+		return 0;
+
+	kfree(ldata->bootparams_buf);
+	ldata->bootparams_buf = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
+int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
+{
+	bool trusted;
+	int ret;
+
+	ret = verify_pefile_signature(kernel, kernel_len,
+				      system_trusted_keyring, &trusted);
+	if (ret < 0)
+		return ret;
+	if (!trusted)
+		return -EKEYREJECTED;
+	return 0;
+}
+#endif
+
+struct kexec_file_ops kexec_bzImage64_ops = {
+	.probe = bzImage64_probe,
+	.load = bzImage64_load,
+	.cleanup = bzImage64_cleanup,
+#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
+	.verify_sig = bzImage64_verify_sig,
+#endif
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/kprobes/opt.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/kprobes/opt.c
--- linux-libre-3.16-gnu/arch/x86/kernel/kprobes/opt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/kprobes/opt.c	2014-09-28 17:29:07.000000000 -0400
@@ -338,8 +338,10 @@ int arch_prepare_optimized_kprobe(struct
 	 * a relative jump.
 	 */
 	rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
-	if (abs(rel) > 0x7fffffff)
+	if (abs(rel) > 0x7fffffff) {
+		__arch_remove_optimized_kprobe(op, 0);
 		return -ERANGE;
+	}
 
 	buf = (u8 *)op->optinsn.insn;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/machine_kexec_64.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/machine_kexec_64.c
--- linux-libre-3.16-gnu/arch/x86/kernel/machine_kexec_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/machine_kexec_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,8 @@
  * Version 2.  See the file COPYING for more details.
  */
 
+#define pr_fmt(fmt)	"kexec: " fmt
+
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/string.h>
@@ -21,6 +23,13 @@
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/debugreg.h>
+#include <asm/kexec-bzimage64.h>
+
+#ifdef CONFIG_KEXEC_FILE
+static struct kexec_file_ops *kexec_file_loaders[] = {
+		&kexec_bzImage64_ops,
+};
+#endif
 
 static void free_transition_pgtable(struct kimage *image)
 {
@@ -171,6 +180,45 @@ static void load_segments(void)
 		);
 }
 
+#ifdef CONFIG_KEXEC_FILE
+/* Update purgatory as needed after various image segments have been prepared */
+static int arch_update_purgatory(struct kimage *image)
+{
+	int ret = 0;
+
+	if (!image->file_mode)
+		return 0;
+
+	/* Setup copying of backup region */
+	if (image->type == KEXEC_TYPE_CRASH) {
+		ret = kexec_purgatory_get_set_symbol(image, "backup_dest",
+				&image->arch.backup_load_addr,
+				sizeof(image->arch.backup_load_addr), 0);
+		if (ret)
+			return ret;
+
+		ret = kexec_purgatory_get_set_symbol(image, "backup_src",
+				&image->arch.backup_src_start,
+				sizeof(image->arch.backup_src_start), 0);
+		if (ret)
+			return ret;
+
+		ret = kexec_purgatory_get_set_symbol(image, "backup_sz",
+				&image->arch.backup_src_sz,
+				sizeof(image->arch.backup_src_sz), 0);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+#else /* !CONFIG_KEXEC_FILE */
+static inline int arch_update_purgatory(struct kimage *image)
+{
+	return 0;
+}
+#endif /* CONFIG_KEXEC_FILE */
+
 int machine_kexec_prepare(struct kimage *image)
 {
 	unsigned long start_pgtable;
@@ -184,6 +232,11 @@ int machine_kexec_prepare(struct kimage
 	if (result)
 		return result;
 
+	/* update purgatory as needed */
+	result = arch_update_purgatory(image);
+	if (result)
+		return result;
+
 	return 0;
 }
 
@@ -283,3 +336,200 @@ void arch_crash_save_vmcoreinfo(void)
 			      (unsigned long)&_text - __START_KERNEL);
 }
 
+/* arch-dependent functionality related to kexec file-based syscall */
+
+#ifdef CONFIG_KEXEC_FILE
+int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
+				  unsigned long buf_len)
+{
+	int i, ret = -ENOEXEC;
+	struct kexec_file_ops *fops;
+
+	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)
+{
+	vfree(image->arch.elf_headers);
+	image->arch.elf_headers = NULL;
+
+	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);
+}
+
+int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel,
+				 unsigned long kernel_len)
+{
+	if (!image->fops || !image->fops->verify_sig) {
+		pr_debug("kernel loader does not support signature verification.");
+		return -EKEYREJECTED;
+	}
+
+	return image->fops->verify_sig(kernel, kernel_len);
+}
+
+/*
+ * Apply purgatory relocations.
+ *
+ * ehdr: Pointer to elf headers
+ * sechdrs: Pointer to section headers.
+ * relsec: section index of SHT_RELA section.
+ *
+ * TODO: Some of the code belongs to generic code. Move that in kexec.c.
+ */
+int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
+				     Elf64_Shdr *sechdrs, unsigned int relsec)
+{
+	unsigned int i;
+	Elf64_Rela *rel;
+	Elf64_Sym *sym;
+	void *location;
+	Elf64_Shdr *section, *symtabsec;
+	unsigned long address, sec_base, value;
+	const char *strtab, *name, *shstrtab;
+
+	/*
+	 * ->sh_offset has been modified to keep the pointer to section
+	 * contents in memory
+	 */
+	rel = (void *)sechdrs[relsec].sh_offset;
+
+	/* Section to which relocations apply */
+	section = &sechdrs[sechdrs[relsec].sh_info];
+
+	pr_debug("Applying relocate section %u to %u\n", relsec,
+		 sechdrs[relsec].sh_info);
+
+	/* Associated symbol table */
+	symtabsec = &sechdrs[sechdrs[relsec].sh_link];
+
+	/* String table */
+	if (symtabsec->sh_link >= ehdr->e_shnum) {
+		/* Invalid strtab section number */
+		pr_err("Invalid string table section index %d\n",
+		       symtabsec->sh_link);
+		return -ENOEXEC;
+	}
+
+	strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset;
+
+	/* section header string table */
+	shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset;
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+
+		/*
+		 * rel[i].r_offset contains byte offset from beginning
+		 * of section to the storage unit affected.
+		 *
+		 * This is location to update (->sh_offset). This is temporary
+		 * buffer where section is currently loaded. This will finally
+		 * be loaded to a different address later, pointed to by
+		 * ->sh_addr. kexec takes care of moving it
+		 *  (kexec_load_segment()).
+		 */
+		location = (void *)(section->sh_offset + rel[i].r_offset);
+
+		/* Final address of the location */
+		address = section->sh_addr + rel[i].r_offset;
+
+		/*
+		 * rel[i].r_info contains information about symbol table index
+		 * w.r.t which relocation must be made and type of relocation
+		 * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
+		 * these respectively.
+		 */
+		sym = (Elf64_Sym *)symtabsec->sh_offset +
+				ELF64_R_SYM(rel[i].r_info);
+
+		if (sym->st_name)
+			name = strtab + sym->st_name;
+		else
+			name = shstrtab + sechdrs[sym->st_shndx].sh_name;
+
+		pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n",
+			 name, sym->st_info, sym->st_shndx, sym->st_value,
+			 sym->st_size);
+
+		if (sym->st_shndx == SHN_UNDEF) {
+			pr_err("Undefined symbol: %s\n", name);
+			return -ENOEXEC;
+		}
+
+		if (sym->st_shndx == SHN_COMMON) {
+			pr_err("symbol '%s' in common section\n", name);
+			return -ENOEXEC;
+		}
+
+		if (sym->st_shndx == SHN_ABS)
+			sec_base = 0;
+		else if (sym->st_shndx >= ehdr->e_shnum) {
+			pr_err("Invalid section %d for symbol %s\n",
+			       sym->st_shndx, name);
+			return -ENOEXEC;
+		} else
+			sec_base = sechdrs[sym->st_shndx].sh_addr;
+
+		value = sym->st_value;
+		value += sec_base;
+		value += rel[i].r_addend;
+
+		switch (ELF64_R_TYPE(rel[i].r_info)) {
+		case R_X86_64_NONE:
+			break;
+		case R_X86_64_64:
+			*(u64 *)location = value;
+			break;
+		case R_X86_64_32:
+			*(u32 *)location = value;
+			if (value != *(u32 *)location)
+				goto overflow;
+			break;
+		case R_X86_64_32S:
+			*(s32 *)location = value;
+			if ((s64)value != *(s32 *)location)
+				goto overflow;
+			break;
+		case R_X86_64_PC32:
+			value -= (u64)address;
+			*(u32 *)location = value;
+			break;
+		default:
+			pr_err("Unknown rela relocation: %llu\n",
+			       ELF64_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+
+overflow:
+	pr_err("Overflow in relocation type %d value 0x%lx\n",
+	       (int)ELF64_R_TYPE(rel[i].r_info), value);
+	return -ENOEXEC;
+}
+#endif /* CONFIG_KEXEC_FILE */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/Makefile linux-libre-3.17-rc7-gnu/arch/x86/kernel/Makefile
--- linux-libre-3.16-gnu/arch/x86/kernel/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -71,6 +71,7 @@ obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.
 obj-$(CONFIG_X86_TSC)		+= trace_clock.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC)		+= relocate_kernel_$(BITS).o crash.o
+obj-$(CONFIG_KEXEC_FILE)	+= kexec-bzimage64.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_$(BITS).o
 obj-y				+= kprobes/
 obj-$(CONFIG_MODULES)		+= module.o
@@ -106,6 +107,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 obj-$(CONFIG_IOSF_MBI)			+= iosf_mbi.o
+obj-$(CONFIG_PMC_ATOM)			+= pmc_atom.o
 
 ###
 # 64 bit specific files
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/mcount_64.S linux-libre-3.17-rc7-gnu/arch/x86/kernel/mcount_64.S
--- linux-libre-3.16-gnu/arch/x86/kernel/mcount_64.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/mcount_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -46,10 +46,6 @@ END(function_hook)
 .endm
 
 ENTRY(ftrace_caller)
-	/* Check if tracing was disabled (quick check) */
-	cmpl $0, function_trace_stop
-	jne  ftrace_stub
-
 	ftrace_caller_setup
 	/* regs go into 4th parameter (but make it NULL) */
 	movq $0, %rcx
@@ -73,10 +69,6 @@ ENTRY(ftrace_regs_caller)
 	/* Save the current flags before compare (in SS location)*/
 	pushfq
 
-	/* Check if tracing was disabled (quick check) */
-	cmpl $0, function_trace_stop
-	jne  ftrace_restore_flags
-
 	/* skip=8 to skip flags saved in SS */
 	ftrace_caller_setup 8
 
@@ -131,7 +123,7 @@ GLOBAL(ftrace_regs_call)
 	popfq
 
 	jmp ftrace_return
-ftrace_restore_flags:
+
 	popfq
 	jmp  ftrace_stub
 
@@ -141,9 +133,6 @@ END(ftrace_regs_caller)
 #else /* ! CONFIG_DYNAMIC_FTRACE */
 
 ENTRY(function_hook)
-	cmpl $0, function_trace_stop
-	jne  ftrace_stub
-
 	cmpq $ftrace_stub, ftrace_trace_function
 	jnz trace
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/mpparse.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/mpparse.c
--- linux-libre-3.16-gnu/arch/x86/kernel/mpparse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/mpparse.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/pci.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
@@ -67,7 +68,7 @@ static void __init MP_processor_info(str
 		boot_cpu_physical_apicid = m->apicid;
 	}
 
-	printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+	pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
 	generic_processor_info(apicid, m->apicver);
 }
 
@@ -87,9 +88,8 @@ static void __init MP_bus_info(struct mp
 
 #if MAX_MP_BUSSES < 256
 	if (m->busid >= MAX_MP_BUSSES) {
-		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
-		       " is too large, max. supported is %d\n",
-		       m->busid, str, MAX_MP_BUSSES - 1);
+		pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",
+			m->busid, str, MAX_MP_BUSSES - 1);
 		return;
 	}
 #endif
@@ -110,19 +110,29 @@ static void __init MP_bus_info(struct mp
 		mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
 #endif
 	} else
-		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+		pr_warn("Unknown bustype %s - ignoring\n", str);
 }
 
+static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
+	.map = mp_irqdomain_map,
+	.unmap = mp_irqdomain_unmap,
+};
+
 static void __init MP_ioapic_info(struct mpc_ioapic *m)
 {
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_LEGACY,
+		.ops = &mp_ioapic_irqdomain_ops,
+	};
+
 	if (m->flags & MPC_APIC_USABLE)
-		mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
+		mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);
 }
 
 static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
 {
-	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+	apic_printk(APIC_VERBOSE,
+		"Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",
 		mp_irq->irqtype, mp_irq->irqflag & 3,
 		(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
 		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
@@ -135,8 +145,8 @@ static inline void __init MP_ioapic_info
 
 static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
 {
-	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+	apic_printk(APIC_VERBOSE,
+		"Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",
 		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
 		m->srcbusirq, m->destapic, m->destapiclint);
 }
@@ -148,34 +158,33 @@ static int __init smp_check_mpc(struct m
 {
 
 	if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
-		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+		pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",
 		       mpc->signature[0], mpc->signature[1],
 		       mpc->signature[2], mpc->signature[3]);
 		return 0;
 	}
 	if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
-		printk(KERN_ERR "MPTABLE: checksum error!\n");
+		pr_err("MPTABLE: checksum error!\n");
 		return 0;
 	}
 	if (mpc->spec != 0x01 && mpc->spec != 0x04) {
-		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
-		       mpc->spec);
+		pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);
 		return 0;
 	}
 	if (!mpc->lapic) {
-		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+		pr_err("MPTABLE: null local APIC address!\n");
 		return 0;
 	}
 	memcpy(oem, mpc->oem, 8);
 	oem[8] = 0;
-	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+	pr_info("MPTABLE: OEM ID: %s\n", oem);
 
 	memcpy(str, mpc->productid, 12);
 	str[12] = 0;
 
-	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+	pr_info("MPTABLE: Product ID: %s\n", str);
 
-	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+	pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic);
 
 	return 1;
 }
@@ -188,8 +197,8 @@ static void skip_entry(unsigned char **p
 
 static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
 {
-	printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
-		"type %x\n", *mpt);
+	pr_err("Your mptable is wrong, contact your HW vendor!\n");
+	pr_cont("type %x\n", *mpt);
 	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
 			1, mpc, mpc->length, 1);
 }
@@ -207,9 +216,6 @@ static int __init smp_read_mpc(struct mp
 	if (!smp_check_mpc(mpc, oem, str))
 		return 0;
 
-#ifdef CONFIG_X86_32
-	generic_mps_oem_check(mpc, oem, str);
-#endif
 	/* Initialize the lapic mapping */
 	if (!acpi_lapic)
 		register_lapic_address(mpc->lapic);
@@ -259,7 +265,7 @@ static int __init smp_read_mpc(struct mp
 	}
 
 	if (!num_processors)
-		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+		pr_err("MPTABLE: no processors registered!\n");
 	return num_processors;
 }
 
@@ -295,16 +301,13 @@ static void __init construct_default_ioi
 	 *  If it does, we assume it's valid.
 	 */
 	if (mpc_default_type == 5) {
-		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
-		       "falling back to ELCR\n");
+		pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
 
 		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
 		    ELCR_trigger(13))
-			printk(KERN_ERR "ELCR contains invalid data... "
-			       "not using ELCR\n");
+			pr_err("ELCR contains invalid data... not using ELCR\n");
 		else {
-			printk(KERN_INFO
-			       "Using ELCR to identify PCI interrupts\n");
+			pr_info("Using ELCR to identify PCI interrupts\n");
 			ELCR_fallback = 1;
 		}
 	}
@@ -353,7 +356,7 @@ static void __init construct_ioapic_tabl
 	bus.busid = 0;
 	switch (mpc_default_type) {
 	default:
-		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+		pr_err("???\nUnknown standard configuration %d\n",
 		       mpc_default_type);
 		/* fall through */
 	case 1:
@@ -462,8 +465,8 @@ static int __init check_physptr(struct m
 #ifdef CONFIG_X86_LOCAL_APIC
 		smp_found_config = 0;
 #endif
-		printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
-			"... disabling SMP support. (tell your hw vendor)\n");
+		pr_err("BIOS bug, MP table errors detected!...\n");
+		pr_cont("... disabling SMP support. (tell your hw vendor)\n");
 		early_iounmap(mpc, size);
 		return -1;
 	}
@@ -481,8 +484,7 @@ static int __init check_physptr(struct m
 	if (!mp_irq_entries) {
 		struct mpc_bus bus;
 
-		printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
-		       "using default mptable. (tell your hw vendor)\n");
+		pr_err("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
 
 		bus.type = MP_BUS;
 		bus.busid = 0;
@@ -516,14 +518,14 @@ void __init default_get_smp_config(unsig
 	if (acpi_lapic && acpi_ioapic)
 		return;
 
-	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
-	       mpf->specification);
+	pr_info("Intel MultiProcessor Specification v1.%d\n",
+		mpf->specification);
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
 	if (mpf->feature2 & (1 << 7)) {
-		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+		pr_info("    IMCR and PIC compatibility mode.\n");
 		pic_mode = 1;
 	} else {
-		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
+		pr_info("    Virtual Wire compatibility mode.\n");
 		pic_mode = 0;
 	}
 #endif
@@ -539,8 +541,7 @@ void __init default_get_smp_config(unsig
 			return;
 		}
 
-		printk(KERN_INFO "Default MP configuration #%d\n",
-		       mpf->feature1);
+		pr_info("Default MP configuration #%d\n", mpf->feature1);
 		construct_default_ISA_mptable(mpf->feature1);
 
 	} else if (mpf->physptr) {
@@ -550,7 +551,7 @@ void __init default_get_smp_config(unsig
 		BUG();
 
 	if (!early)
-		printk(KERN_INFO "Processors: %d\n", num_processors);
+		pr_info("Processors: %d\n", num_processors);
 	/*
 	 * Only use the first configuration found.
 	 */
@@ -583,10 +584,10 @@ static int __init smp_scan_config(unsign
 #endif
 			mpf_found = mpf;
 
-			printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
-			       (unsigned long long) virt_to_phys(mpf),
-			       (unsigned long long) virt_to_phys(mpf) +
-			       sizeof(*mpf) - 1, mpf);
+			pr_info("found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
+				(unsigned long long) virt_to_phys(mpf),
+				(unsigned long long) virt_to_phys(mpf) +
+				sizeof(*mpf) - 1, mpf);
 
 			mem = virt_to_phys(mpf);
 			memblock_reserve(mem, sizeof(*mpf));
@@ -735,7 +736,7 @@ static int  __init replace_intsrc_all(st
 	int nr_m_spare = 0;
 	unsigned char *mpt = ((unsigned char *)mpc) + count;
 
-	printk(KERN_INFO "mpc_length %x\n", mpc->length);
+	pr_info("mpc_length %x\n", mpc->length);
 	while (count < mpc->length) {
 		switch (*mpt) {
 		case MP_PROCESSOR:
@@ -862,13 +863,13 @@ static int __init update_mp_table(void)
 	if (!smp_check_mpc(mpc, oem, str))
 		return 0;
 
-	printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
-	printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+	pr_info("mpf: %llx\n", (u64)virt_to_phys(mpf));
+	pr_info("physptr: %x\n", mpf->physptr);
 
 	if (mpc_new_phys && mpc->length > mpc_new_length) {
 		mpc_new_phys = 0;
-		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
-			 mpc_new_length);
+		pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
+			mpc_new_length);
 	}
 
 	if (!mpc_new_phys) {
@@ -879,10 +880,10 @@ static int __init update_mp_table(void)
 		mpc->checksum = 0xff;
 		new = mpf_checksum((unsigned char *)mpc, mpc->length);
 		if (old == new) {
-			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+			pr_info("mpc is readonly, please try alloc_mptable instead\n");
 			return 0;
 		}
-		printk(KERN_INFO "use in-position replacing\n");
+		pr_info("use in-position replacing\n");
 	} else {
 		mpf->physptr = mpc_new_phys;
 		mpc_new = phys_to_virt(mpc_new_phys);
@@ -892,7 +893,7 @@ static int __init update_mp_table(void)
 		if (mpc_new_phys - mpf->physptr) {
 			struct mpf_intel *mpf_new;
 			/* steal 16 bytes from [0, 1k) */
-			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+			pr_info("mpf new: %x\n", 0x400 - 16);
 			mpf_new = phys_to_virt(0x400 - 16);
 			memcpy(mpf_new, mpf, 16);
 			mpf = mpf_new;
@@ -900,7 +901,7 @@ static int __init update_mp_table(void)
 		}
 		mpf->checksum = 0;
 		mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
-		printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+		pr_info("physptr new: %x\n", mpf->physptr);
 	}
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/pmc_atom.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/pmc_atom.c
--- linux-libre-3.16-gnu/arch/x86/kernel/pmc_atom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/pmc_atom.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,321 @@
+/*
+ * Intel Atom SOC Power Management Controller Driver
+ * Copyright (c) 2014, 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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/io.h>
+
+#include <asm/pmc_atom.h>
+
+#define	DRIVER_NAME	KBUILD_MODNAME
+
+struct pmc_dev {
+	u32 base_addr;
+	void __iomem *regmap;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dbgfs_dir;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+static struct pmc_dev pmc_device;
+static u32 acpi_base_addr;
+
+struct pmc_dev_map {
+	const char *name;
+	u32 bit_mask;
+};
+
+static const struct pmc_dev_map dev_map[] = {
+	{"0  - LPSS1_F0_DMA",		BIT_LPSS1_F0_DMA},
+	{"1  - LPSS1_F1_PWM1",		BIT_LPSS1_F1_PWM1},
+	{"2  - LPSS1_F2_PWM2",		BIT_LPSS1_F2_PWM2},
+	{"3  - LPSS1_F3_HSUART1",	BIT_LPSS1_F3_HSUART1},
+	{"4  - LPSS1_F4_HSUART2",	BIT_LPSS1_F4_HSUART2},
+	{"5  - LPSS1_F5_SPI",		BIT_LPSS1_F5_SPI},
+	{"6  - LPSS1_F6_Reserved",	BIT_LPSS1_F6_XXX},
+	{"7  - LPSS1_F7_Reserved",	BIT_LPSS1_F7_XXX},
+	{"8  - SCC_EMMC",		BIT_SCC_EMMC},
+	{"9  - SCC_SDIO",		BIT_SCC_SDIO},
+	{"10 - SCC_SDCARD",		BIT_SCC_SDCARD},
+	{"11 - SCC_MIPI",		BIT_SCC_MIPI},
+	{"12 - HDA",			BIT_HDA},
+	{"13 - LPE",			BIT_LPE},
+	{"14 - OTG",			BIT_OTG},
+	{"15 - USH",			BIT_USH},
+	{"16 - GBE",			BIT_GBE},
+	{"17 - SATA",			BIT_SATA},
+	{"18 - USB_EHCI",		BIT_USB_EHCI},
+	{"19 - SEC",			BIT_SEC},
+	{"20 - PCIE_PORT0",		BIT_PCIE_PORT0},
+	{"21 - PCIE_PORT1",		BIT_PCIE_PORT1},
+	{"22 - PCIE_PORT2",		BIT_PCIE_PORT2},
+	{"23 - PCIE_PORT3",		BIT_PCIE_PORT3},
+	{"24 - LPSS2_F0_DMA",		BIT_LPSS2_F0_DMA},
+	{"25 - LPSS2_F1_I2C1",		BIT_LPSS2_F1_I2C1},
+	{"26 - LPSS2_F2_I2C2",		BIT_LPSS2_F2_I2C2},
+	{"27 - LPSS2_F3_I2C3",		BIT_LPSS2_F3_I2C3},
+	{"28 - LPSS2_F3_I2C4",		BIT_LPSS2_F4_I2C4},
+	{"29 - LPSS2_F5_I2C5",		BIT_LPSS2_F5_I2C5},
+	{"30 - LPSS2_F6_I2C6",		BIT_LPSS2_F6_I2C6},
+	{"31 - LPSS2_F7_I2C7",		BIT_LPSS2_F7_I2C7},
+	{"32 - SMB",			BIT_SMB},
+	{"33 - OTG_SS_PHY",		BIT_OTG_SS_PHY},
+	{"34 - USH_SS_PHY",		BIT_USH_SS_PHY},
+	{"35 - DFX",			BIT_DFX},
+};
+
+static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)
+{
+	return readl(pmc->regmap + reg_offset);
+}
+
+static inline void pmc_reg_write(struct pmc_dev *pmc, int reg_offset, u32 val)
+{
+	writel(val, pmc->regmap + reg_offset);
+}
+
+static void pmc_power_off(void)
+{
+	u16	pm1_cnt_port;
+	u32	pm1_cnt_value;
+
+	pr_info("Preparing to enter system sleep state S5\n");
+
+	pm1_cnt_port = acpi_base_addr + PM1_CNT;
+
+	pm1_cnt_value = inl(pm1_cnt_port);
+	pm1_cnt_value &= SLEEP_TYPE_MASK;
+	pm1_cnt_value |= SLEEP_TYPE_S5;
+	pm1_cnt_value |= SLEEP_ENABLE;
+
+	outl(pm1_cnt_value, pm1_cnt_port);
+}
+
+static void pmc_hw_reg_setup(struct pmc_dev *pmc)
+{
+	/*
+	 * Disable PMC S0IX_WAKE_EN events coming from:
+	 * - LPC clock run
+	 * - GPIO_SUS ored dedicated IRQs
+	 * - GPIO_SCORE ored dedicated IRQs
+	 * - GPIO_SUS shared IRQ
+	 * - GPIO_SCORE shared IRQ
+	 */
+	pmc_reg_write(pmc, PMC_S0IX_WAKE_EN, (u32)PMC_WAKE_EN_SETTING);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int pmc_dev_state_show(struct seq_file *s, void *unused)
+{
+	struct pmc_dev *pmc = s->private;
+	u32 func_dis, func_dis_2, func_dis_index;
+	u32 d3_sts_0, d3_sts_1, d3_sts_index;
+	int dev_num, dev_index, reg_index;
+
+	func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS);
+	func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2);
+	d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0);
+	d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1);
+
+	dev_num = ARRAY_SIZE(dev_map);
+
+	for (dev_index = 0; dev_index < dev_num; dev_index++) {
+		reg_index = dev_index / PMC_REG_BIT_WIDTH;
+		if (reg_index) {
+			func_dis_index = func_dis_2;
+			d3_sts_index = d3_sts_1;
+		} else {
+			func_dis_index = func_dis;
+			d3_sts_index = d3_sts_0;
+		}
+
+		seq_printf(s, "Dev: %-32s\tState: %s [%s]\n",
+			dev_map[dev_index].name,
+			dev_map[dev_index].bit_mask & func_dis_index ?
+			"Disabled" : "Enabled ",
+			dev_map[dev_index].bit_mask & d3_sts_index ?
+			"D3" : "D0");
+	}
+	return 0;
+}
+
+static int pmc_dev_state_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pmc_dev_state_show, inode->i_private);
+}
+
+static const struct file_operations pmc_dev_state_ops = {
+	.open		= pmc_dev_state_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int pmc_sleep_tmr_show(struct seq_file *s, void *unused)
+{
+	struct pmc_dev *pmc = s->private;
+	u64 s0ir_tmr, s0i1_tmr, s0i2_tmr, s0i3_tmr, s0_tmr;
+
+	s0ir_tmr = (u64)pmc_reg_read(pmc, PMC_S0IR_TMR) << PMC_TMR_SHIFT;
+	s0i1_tmr = (u64)pmc_reg_read(pmc, PMC_S0I1_TMR) << PMC_TMR_SHIFT;
+	s0i2_tmr = (u64)pmc_reg_read(pmc, PMC_S0I2_TMR) << PMC_TMR_SHIFT;
+	s0i3_tmr = (u64)pmc_reg_read(pmc, PMC_S0I3_TMR) << PMC_TMR_SHIFT;
+	s0_tmr = (u64)pmc_reg_read(pmc, PMC_S0_TMR) << PMC_TMR_SHIFT;
+
+	seq_printf(s, "S0IR Residency:\t%lldus\n", s0ir_tmr);
+	seq_printf(s, "S0I1 Residency:\t%lldus\n", s0i1_tmr);
+	seq_printf(s, "S0I2 Residency:\t%lldus\n", s0i2_tmr);
+	seq_printf(s, "S0I3 Residency:\t%lldus\n", s0i3_tmr);
+	seq_printf(s, "S0   Residency:\t%lldus\n", s0_tmr);
+	return 0;
+}
+
+static int pmc_sleep_tmr_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pmc_sleep_tmr_show, inode->i_private);
+}
+
+static const struct file_operations pmc_sleep_tmr_ops = {
+	.open		= pmc_sleep_tmr_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void pmc_dbgfs_unregister(struct pmc_dev *pmc)
+{
+	if (!pmc->dbgfs_dir)
+		return;
+
+	debugfs_remove_recursive(pmc->dbgfs_dir);
+	pmc->dbgfs_dir = NULL;
+}
+
+static int pmc_dbgfs_register(struct pmc_dev *pmc, struct pci_dev *pdev)
+{
+	struct dentry *dir, *f;
+
+	dir = debugfs_create_dir("pmc_atom", NULL);
+	if (!dir)
+		return -ENOMEM;
+
+	f = debugfs_create_file("dev_state", S_IFREG | S_IRUGO,
+				dir, pmc, &pmc_dev_state_ops);
+	if (!f) {
+		dev_err(&pdev->dev, "dev_states register failed\n");
+		goto err;
+	}
+	f = debugfs_create_file("sleep_state", S_IFREG | S_IRUGO,
+				dir, pmc, &pmc_sleep_tmr_ops);
+	if (!f) {
+		dev_err(&pdev->dev, "sleep_state register failed\n");
+		goto err;
+	}
+	pmc->dbgfs_dir = dir;
+	return 0;
+err:
+	pmc_dbgfs_unregister(pmc);
+	return -ENODEV;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static int pmc_setup_dev(struct pci_dev *pdev)
+{
+	struct pmc_dev *pmc = &pmc_device;
+	int ret;
+
+	/* Obtain ACPI base address */
+	pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr);
+	acpi_base_addr &= ACPI_BASE_ADDR_MASK;
+
+	/* Install power off function */
+	if (acpi_base_addr != 0 && pm_power_off == NULL)
+		pm_power_off = pmc_power_off;
+
+	pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr);
+	pmc->base_addr &= PMC_BASE_ADDR_MASK;
+
+	pmc->regmap = ioremap_nocache(pmc->base_addr, PMC_MMIO_REG_LEN);
+	if (!pmc->regmap) {
+		dev_err(&pdev->dev, "error: ioremap failed\n");
+		return -ENOMEM;
+	}
+
+	/* PMC hardware registers setup */
+	pmc_hw_reg_setup(pmc);
+
+#ifdef CONFIG_DEBUG_FS
+	ret = pmc_dbgfs_register(pmc, pdev);
+	if (ret) {
+		iounmap(pmc->regmap);
+		return ret;
+	}
+#endif /* CONFIG_DEBUG_FS */
+	return 0;
+}
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because lpc_ich will register
+ * a driver on the same PCI id.
+ */
+static const struct pci_device_id pmc_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VLV_PMC) },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, pmc_pci_ids);
+
+static int __init pmc_atom_init(void)
+{
+	int err = -ENODEV;
+	struct pci_dev *pdev = NULL;
+	const struct pci_device_id *ent;
+
+	/* We look for our device - PCU PMC
+	 * we assume that there is max. one device.
+	 *
+	 * We can't use plain pci_driver mechanism,
+	 * as the device is really a multiple function device,
+	 * main driver that binds to the pci_device is lpc_ich
+	 * and have to find & bind to the device this way.
+	 */
+	for_each_pci_dev(pdev) {
+		ent = pci_match_id(pmc_pci_ids, pdev);
+		if (ent) {
+			err = pmc_setup_dev(pdev);
+			goto out;
+		}
+	}
+	/* Device not found. */
+out:
+	return err;
+}
+
+module_init(pmc_atom_init);
+/* no module_exit, this driver shouldn't be unloaded */
+
+MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Atom SOC Power Management Controller Interface");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/process.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/process.c
--- linux-libre-3.16-gnu/arch/x86/kernel/process.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/process.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,6 +93,7 @@ void arch_task_cache_init(void)
         	kmem_cache_create("task_xstate", xstate_size,
 				  __alignof__(union thread_xstate),
 				  SLAB_PANIC | SLAB_NOTRACK, NULL);
+	setup_xstate_comp();
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/reboot.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/reboot.c
--- linux-libre-3.16-gnu/arch/x86/kernel/reboot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/reboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/mc146818rtc.h>
 #include <asm/realmode.h>
 #include <asm/x86_init.h>
+#include <asm/efi.h>
 
 /*
  * Power off function, if any
@@ -401,12 +402,25 @@ static struct dmi_system_id __initdata r
 
 static int __init reboot_init(void)
 {
+	int rv;
+
 	/*
 	 * Only do the DMI check if reboot_type hasn't been overridden
 	 * on the command line
 	 */
-	if (reboot_default)
-		dmi_check_system(reboot_dmi_table);
+	if (!reboot_default)
+		return 0;
+
+	/*
+	 * The DMI quirks table takes precedence. If no quirks entry
+	 * matches and the ACPI Hardware Reduced bit is set, force EFI
+	 * reboot.
+	 */
+	rv = dmi_check_system(reboot_dmi_table);
+
+	if (!rv && efi_reboot_required())
+		reboot_type = BOOT_EFI;
+
 	return 0;
 }
 core_initcall(reboot_init);
@@ -528,11 +542,7 @@ static void native_machine_emergency_res
 			break;
 
 		case BOOT_EFI:
-			if (efi_enabled(EFI_RUNTIME_SERVICES))
-				efi.reset_system(reboot_mode == REBOOT_WARM ?
-						 EFI_RESET_WARM :
-						 EFI_RESET_COLD,
-						 EFI_SUCCESS, 0, NULL);
+			efi_reboot(reboot_mode, NULL);
 			reboot_type = BOOT_BIOS;
 			break;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/resource.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/resource.c
--- linux-libre-3.16-gnu/arch/x86/kernel/resource.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/resource.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,10 +37,12 @@ static void remove_e820_regions(struct r
 
 void arch_remove_reservations(struct resource *avail)
 {
-	/* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+	/*
+	 * Trim out BIOS area (high 2MB) and E820 regions. We do not remove
+	 * the low 1MB unconditionally, as this area is needed for some ISA
+	 * cards requiring a memory range, e.g. the i82365 PCMCIA controller.
+	 */
 	if (avail->flags & IORESOURCE_MEM) {
-		if (avail->start < BIOS_END)
-			avail->start = BIOS_END;
 		resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
 
 		remove_e820_regions(avail);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/setup.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/setup.c
--- linux-libre-3.16-gnu/arch/x86/kernel/setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -924,10 +924,10 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #ifdef CONFIG_EFI
 	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
-		     "EL32", 4)) {
+		     EFI32_LOADER_SIGNATURE, 4)) {
 		set_bit(EFI_BOOT, &efi.flags);
 	} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
-		     "EL64", 4)) {
+		     EFI64_LOADER_SIGNATURE, 4)) {
 		set_bit(EFI_BOOT, &efi.flags);
 		set_bit(EFI_64BIT, &efi.flags);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/smpboot.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-3.16-gnu/arch/x86/kernel/smpboot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/smpboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -168,10 +168,6 @@ static void smp_callin(void)
 	 * CPU, first the APIC. (this is probably redundant on most
 	 * boards)
 	 */
-
-	pr_debug("CALLIN, before setup_local_APIC()\n");
-	if (apic->smp_callin_clear_local_apic)
-		apic->smp_callin_clear_local_apic();
 	setup_local_APIC();
 	end_local_APIC_setup();
 
@@ -1143,10 +1139,6 @@ void __init native_smp_prepare_cpus(unsi
 		enable_IO_APIC();
 
 	bsp_end_local_APIC_setup();
-
-	if (apic->setup_portio_remap)
-		apic->setup_portio_remap();
-
 	smpboot_setup_io_apic();
 	/*
 	 * Set up local APIC timer on boot CPU.
@@ -1292,6 +1284,9 @@ static void remove_siblinginfo(int cpu)
 
 	for_each_cpu(sibling, cpu_sibling_mask(cpu))
 		cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling));
+	for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
+		cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling));
+	cpumask_clear(cpu_llc_shared_mask(cpu));
 	cpumask_clear(cpu_sibling_mask(cpu));
 	cpumask_clear(cpu_core_mask(cpu));
 	c->phys_proc_id = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/time.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/time.c
--- linux-libre-3.16-gnu/arch/x86/kernel/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,8 @@ static struct irqaction irq0  = {
 
 void __init setup_default_timer_irq(void)
 {
+	if (!nr_legacy_irqs())
+		return;
 	setup_irq(0, &irq0);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/tsc.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/tsc.c
--- linux-libre-3.16-gnu/arch/x86/kernel/tsc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/tsc.c	2014-09-28 17:29:07.000000000 -0400
@@ -234,9 +234,6 @@ static inline unsigned long long cycles_
 	return ns;
 }
 
-/* XXX surely we already have this someplace in the kernel?! */
-#define DIV_ROUND(n, d) (((n) + ((d) / 2)) / (d))
-
 static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
 {
 	unsigned long long tsc_now, ns_now;
@@ -259,7 +256,9 @@ static void set_cyc2ns_scale(unsigned lo
 	 * time function is continuous; see the comment near struct
 	 * cyc2ns_data.
 	 */
-	data->cyc2ns_mul = DIV_ROUND(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR, cpu_khz);
+	data->cyc2ns_mul =
+		DIV_ROUND_CLOSEST(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR,
+				  cpu_khz);
 	data->cyc2ns_shift = CYC2NS_SCALE_FACTOR;
 	data->cyc2ns_offset = ns_now -
 		mul_u64_u32_shr(tsc_now, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR);
@@ -951,7 +950,7 @@ core_initcall(cpufreq_tsc);
 static struct clocksource clocksource_tsc;
 
 /*
- * We compare the TSC to the cycle_last value in the clocksource
+ * 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
  * very small window right after one CPU updated cycle_last under
  * xtime/vsyscall_gtod lock and the other CPU reads a TSC value which
@@ -961,26 +960,23 @@ static struct clocksource clocksource_ts
  * due to the unsigned delta calculation of the time keeping core
  * code, which is necessary to support wrapping clocksources like pm
  * timer.
+ *
+ * This sanity check is now done in the core timekeeping code.
+ * 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)
 {
-	cycle_t ret = (cycle_t)get_cycles();
-
-	return ret >= clocksource_tsc.cycle_last ?
-		ret : clocksource_tsc.cycle_last;
-}
-
-static void resume_tsc(struct clocksource *cs)
-{
-	if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
-		clocksource_tsc.cycle_last = 0;
+	return (cycle_t)get_cycles();
 }
 
+/*
+ * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc()
+ */
 static struct clocksource clocksource_tsc = {
 	.name                   = "tsc",
 	.rating                 = 300,
 	.read                   = read_tsc,
-	.resume			= resume_tsc,
 	.mask                   = CLOCKSOURCE_MASK(64),
 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/vsmp_64.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsmp_64.c
--- linux-libre-3.16-gnu/arch/x86/kernel/vsmp_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsmp_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -152,7 +152,7 @@ static void __init detect_vsmp_box(void)
 		is_vsmp = 1;
 }
 
-int is_vsmp_box(void)
+static int is_vsmp_box(void)
 {
 	if (is_vsmp != -1)
 		return is_vsmp;
@@ -166,7 +166,7 @@ int is_vsmp_box(void)
 static void __init detect_vsmp_box(void)
 {
 }
-int is_vsmp_box(void)
+static int is_vsmp_box(void)
 {
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/vsyscall_64.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsyscall_64.c
--- linux-libre-3.16-gnu/arch/x86/kernel/vsyscall_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsyscall_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,10 +81,10 @@ static void warn_bad_vsyscall(const char
 	if (!show_unhandled_signals)
 		return;
 
-	pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
-			      level, current->comm, task_pid_nr(current),
-			      message, regs->ip, regs->cs,
-			      regs->sp, regs->ax, regs->si, regs->di);
+	printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+			   level, current->comm, task_pid_nr(current),
+			   message, regs->ip, regs->cs,
+			   regs->sp, regs->ax, regs->si, regs->di);
 }
 
 static int addr_to_vsyscall_nr(unsigned long addr)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/vsyscall_gtod.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsyscall_gtod.c
--- linux-libre-3.16-gnu/arch/x86/kernel/vsyscall_gtod.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/vsyscall_gtod.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,29 +31,30 @@ void update_vsyscall(struct timekeeper *
 	gtod_write_begin(vdata);
 
 	/* copy vsyscall data */
-	vdata->vclock_mode	= tk->clock->archdata.vclock_mode;
-	vdata->cycle_last	= tk->clock->cycle_last;
-	vdata->mask		= tk->clock->mask;
-	vdata->mult		= tk->mult;
-	vdata->shift		= tk->shift;
+	vdata->vclock_mode	= tk->tkr.clock->archdata.vclock_mode;
+	vdata->cycle_last	= tk->tkr.cycle_last;
+	vdata->mask		= tk->tkr.mask;
+	vdata->mult		= tk->tkr.mult;
+	vdata->shift		= tk->tkr.shift;
 
 	vdata->wall_time_sec		= tk->xtime_sec;
-	vdata->wall_time_snsec		= tk->xtime_nsec;
+	vdata->wall_time_snsec		= tk->tkr.xtime_nsec;
 
 	vdata->monotonic_time_sec	= tk->xtime_sec
 					+ tk->wall_to_monotonic.tv_sec;
-	vdata->monotonic_time_snsec	= tk->xtime_nsec
+	vdata->monotonic_time_snsec	= tk->tkr.xtime_nsec
 					+ ((u64)tk->wall_to_monotonic.tv_nsec
-						<< tk->shift);
+						<< tk->tkr.shift);
 	while (vdata->monotonic_time_snsec >=
-					(((u64)NSEC_PER_SEC) << tk->shift)) {
+					(((u64)NSEC_PER_SEC) << tk->tkr.shift)) {
 		vdata->monotonic_time_snsec -=
-					((u64)NSEC_PER_SEC) << tk->shift;
+					((u64)NSEC_PER_SEC) << tk->tkr.shift;
 		vdata->monotonic_time_sec++;
 	}
 
 	vdata->wall_time_coarse_sec	= tk->xtime_sec;
-	vdata->wall_time_coarse_nsec	= (long)(tk->xtime_nsec >> tk->shift);
+	vdata->wall_time_coarse_nsec	= (long)(tk->tkr.xtime_nsec >>
+						 tk->tkr.shift);
 
 	vdata->monotonic_time_coarse_sec =
 		vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kernel/xsave.c linux-libre-3.17-rc7-gnu/arch/x86/kernel/xsave.c
--- linux-libre-3.16-gnu/arch/x86/kernel/xsave.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kernel/xsave.c	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
 
 #include <linux/bootmem.h>
 #include <linux/compat.h>
+#include <linux/cpu.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/sigframe.h>
@@ -24,7 +25,9 @@ u64 pcntxt_mask;
 struct xsave_struct *init_xstate_buf;
 
 static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
-static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
+static unsigned int *xstate_offsets, *xstate_sizes;
+static unsigned int xstate_comp_offsets[sizeof(pcntxt_mask)*8];
+static unsigned int xstate_features;
 
 /*
  * If a processor implementation discern that a processor state component is
@@ -283,7 +286,7 @@ sanitize_restored_xstate(struct task_str
 
 	if (use_xsave()) {
 		/* These bits must be zero. */
-		xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+		memset(xsave_hdr->reserved, 0, 48);
 
 		/*
 		 * Init the state that is not present in the memory
@@ -479,6 +482,52 @@ static void __init setup_xstate_features
 }
 
 /*
+ * This function sets up offsets and sizes of all extended states in
+ * xsave area. This supports both standard format and compacted format
+ * of the xsave aread.
+ *
+ * Input: void
+ * Output: void
+ */
+void setup_xstate_comp(void)
+{
+	unsigned int xstate_comp_sizes[sizeof(pcntxt_mask)*8];
+	int i;
+
+	/*
+	 * The FP xstates and SSE xstates are legacy states. They are always
+	 * in the fixed offsets in the xsave area in either compacted form
+	 * or standard form.
+	 */
+	xstate_comp_offsets[0] = 0;
+	xstate_comp_offsets[1] = offsetof(struct i387_fxsave_struct, xmm_space);
+
+	if (!cpu_has_xsaves) {
+		for (i = 2; i < xstate_features; i++) {
+			if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
+				xstate_comp_offsets[i] = xstate_offsets[i];
+				xstate_comp_sizes[i] = xstate_sizes[i];
+			}
+		}
+		return;
+	}
+
+	xstate_comp_offsets[2] = FXSAVE_SIZE + XSAVE_HDR_SIZE;
+
+	for (i = 2; i < xstate_features; i++) {
+		if (test_bit(i, (unsigned long *)&pcntxt_mask))
+			xstate_comp_sizes[i] = xstate_sizes[i];
+		else
+			xstate_comp_sizes[i] = 0;
+
+		if (i > 2)
+			xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
+					+ xstate_comp_sizes[i-1];
+
+	}
+}
+
+/*
  * setup the xstate image representing the init state
  */
 static void __init setup_init_fpu_buf(void)
@@ -496,15 +545,21 @@ static void __init setup_init_fpu_buf(vo
 
 	setup_xstate_features();
 
+	if (cpu_has_xsaves) {
+		init_xstate_buf->xsave_hdr.xcomp_bv =
+						(u64)1 << 63 | pcntxt_mask;
+		init_xstate_buf->xsave_hdr.xstate_bv = pcntxt_mask;
+	}
+
 	/*
 	 * Init all the features state with header_bv being 0x0
 	 */
-	xrstor_state(init_xstate_buf, -1);
+	xrstor_state_booting(init_xstate_buf, -1);
 	/*
 	 * Dump the init state again. This is to identify the init state
 	 * of any feature which is not represented by all zero's.
 	 */
-	xsave_state(init_xstate_buf, -1);
+	xsave_state_booting(init_xstate_buf, -1);
 }
 
 static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO;
@@ -520,6 +575,30 @@ static int __init eager_fpu_setup(char *
 }
 __setup("eagerfpu=", eager_fpu_setup);
 
+
+/*
+ * Calculate total size of enabled xstates in XCR0/pcntxt_mask.
+ */
+static void __init init_xstate_size(void)
+{
+	unsigned int eax, ebx, ecx, edx;
+	int i;
+
+	if (!cpu_has_xsaves) {
+		cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
+		xstate_size = ebx;
+		return;
+	}
+
+	xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
+	for (i = 2; i < 64; i++) {
+		if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
+			cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
+			xstate_size += eax;
+		}
+	}
+}
+
 /*
  * Enable and initialize the xsave feature.
  */
@@ -551,8 +630,7 @@ static void __init xstate_enable_boot_cp
 	/*
 	 * Recompute the context size for enabled features
 	 */
-	cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
-	xstate_size = ebx;
+	init_xstate_size();
 
 	update_regset_xstate_info(xstate_size, pcntxt_mask);
 	prepare_fx_sw_frame();
@@ -572,8 +650,9 @@ static void __init xstate_enable_boot_cp
 		}
 	}
 
-	pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
-		pcntxt_mask, xstate_size);
+	pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x using %s\n",
+		pcntxt_mask, xstate_size,
+		cpu_has_xsaves ? "compacted form" : "standard form");
 }
 
 /*
@@ -635,3 +714,26 @@ void eager_fpu_init(void)
 	else
 		fxrstor_checking(&init_xstate_buf->i387);
 }
+
+/*
+ * Given the xsave area and a state inside, this function returns the
+ * address of the state.
+ *
+ * This is the API that is called to get xstate address in either
+ * standard format or compacted format of xsave area.
+ *
+ * Inputs:
+ *	xsave: base address of the xsave area;
+ *	xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
+ *	etc.)
+ * Output:
+ *	address of the state in the xsave area.
+ */
+void *get_xsave_addr(struct xsave_struct *xsave, int xstate)
+{
+	int feature = fls64(xstate) - 1;
+	if (!test_bit(feature, (unsigned long *)&pcntxt_mask))
+		return NULL;
+
+	return (void *)xsave + xstate_comp_offsets[feature];
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/cpuid.h linux-libre-3.17-rc7-gnu/arch/x86/kvm/cpuid.h
--- linux-libre-3.16-gnu/arch/x86/kvm/cpuid.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/cpuid.h	2014-09-28 17:29:07.000000000 -0400
@@ -95,4 +95,12 @@ static inline bool guest_cpuid_has_gbpag
 	best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
 	return best && (best->edx & bit(X86_FEATURE_GBPAGES));
 }
+
+static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_RTM));
+}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/emulate.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/emulate.c
--- linux-libre-3.16-gnu/arch/x86/kvm/emulate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/emulate.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,6 +162,10 @@
 #define NoWrite     ((u64)1 << 45)  /* No writeback */
 #define SrcWrite    ((u64)1 << 46)  /* Write back src operand */
 #define NoMod	    ((u64)1 << 47)  /* Mod field is ignored */
+#define Intercept   ((u64)1 << 48)  /* Has valid intercept field */
+#define CheckPerm   ((u64)1 << 49)  /* Has valid check_perm field */
+#define NoBigReal   ((u64)1 << 50)  /* No big real mode */
+#define PrivUD      ((u64)1 << 51)  /* #UD instead of #GP on CPL > 0 */
 
 #define DstXacc     (DstAccLo | SrcAccHi | SrcWrite)
 
@@ -426,6 +430,7 @@ static int emulator_check_intercept(stru
 		.modrm_reg  = ctxt->modrm_reg,
 		.modrm_rm   = ctxt->modrm_rm,
 		.src_val    = ctxt->src.val64,
+		.dst_val    = ctxt->dst.val64,
 		.src_bytes  = ctxt->src.bytes,
 		.dst_bytes  = ctxt->dst.bytes,
 		.ad_bytes   = ctxt->ad_bytes,
@@ -511,12 +516,6 @@ static u32 desc_limit_scaled(struct desc
 	return desc->g ? (limit << 12) | 0xfff : limit;
 }
 
-static void set_seg_override(struct x86_emulate_ctxt *ctxt, int seg)
-{
-	ctxt->has_seg_override = true;
-	ctxt->seg_override = seg;
-}
-
 static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg)
 {
 	if (ctxt->mode == X86EMUL_MODE_PROT64 && seg < VCPU_SREG_FS)
@@ -525,14 +524,6 @@ static unsigned long seg_base(struct x86
 	return ctxt->ops->get_cached_segment_base(ctxt, seg);
 }
 
-static unsigned seg_override(struct x86_emulate_ctxt *ctxt)
-{
-	if (!ctxt->has_seg_override)
-		return 0;
-
-	return ctxt->seg_override;
-}
-
 static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
 			     u32 error, bool valid)
 {
@@ -651,7 +642,12 @@ static int __linearize(struct x86_emulat
 		if (!fetch && (desc.type & 8) && !(desc.type & 2))
 			goto bad;
 		lim = desc_limit_scaled(&desc);
-		if ((desc.type & 8) || !(desc.type & 4)) {
+		if ((ctxt->mode == X86EMUL_MODE_REAL) && !fetch &&
+		    (ctxt->d & NoBigReal)) {
+			/* la is between zero and 0xffff */
+			if (la > 0xffff || (u32)(la + size - 1) > 0xffff)
+				goto bad;
+		} else if ((desc.type & 8) || !(desc.type & 4)) {
 			/* expand-up segment */
 			if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
 				goto bad;
@@ -716,68 +712,71 @@ static int segmented_read_std(struct x86
 }
 
 /*
- * Fetch the next byte of the instruction being emulated which is pointed to
- * by ctxt->_eip, then increment ctxt->_eip.
- *
- * Also prefetch the remaining bytes of the instruction without crossing page
+ * Prefetch the remaining bytes of the instruction without crossing page
  * boundary if they are not in fetch_cache yet.
  */
-static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt, u8 *dest)
+static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 {
-	struct fetch_cache *fc = &ctxt->fetch;
 	int rc;
-	int size, cur_size;
+	unsigned size;
+	unsigned long linear;
+	int cur_size = ctxt->fetch.end - ctxt->fetch.data;
+	struct segmented_address addr = { .seg = VCPU_SREG_CS,
+					   .ea = ctxt->eip + cur_size };
 
-	if (ctxt->_eip == fc->end) {
-		unsigned long linear;
-		struct segmented_address addr = { .seg = VCPU_SREG_CS,
-						  .ea  = ctxt->_eip };
-		cur_size = fc->end - fc->start;
-		size = min(15UL - cur_size,
-			   PAGE_SIZE - offset_in_page(ctxt->_eip));
-		rc = __linearize(ctxt, addr, size, false, true, &linear);
-		if (unlikely(rc != X86EMUL_CONTINUE))
-			return rc;
-		rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
-				      size, &ctxt->exception);
-		if (unlikely(rc != X86EMUL_CONTINUE))
-			return rc;
-		fc->end += size;
-	}
-	*dest = fc->data[ctxt->_eip - fc->start];
-	ctxt->_eip++;
-	return X86EMUL_CONTINUE;
-}
+	size = 15UL ^ cur_size;
+	rc = __linearize(ctxt, addr, size, false, true, &linear);
+	if (unlikely(rc != X86EMUL_CONTINUE))
+		return rc;
 
-static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
-			 void *dest, unsigned size)
-{
-	int rc;
+	size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
 
-	/* x86 instructions are limited to 15 bytes. */
-	if (unlikely(ctxt->_eip + size - ctxt->eip > 15))
+	/*
+	 * One instruction can only straddle two pages,
+	 * and one has been loaded at the beginning of
+	 * x86_decode_insn.  So, if not enough bytes
+	 * still, we must have hit the 15-byte boundary.
+	 */
+	if (unlikely(size < op_size))
 		return X86EMUL_UNHANDLEABLE;
-	while (size--) {
-		rc = do_insn_fetch_byte(ctxt, dest++);
-		if (rc != X86EMUL_CONTINUE)
-			return rc;
-	}
+	rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end,
+			      size, &ctxt->exception);
+	if (unlikely(rc != X86EMUL_CONTINUE))
+		return rc;
+	ctxt->fetch.end += size;
 	return X86EMUL_CONTINUE;
 }
 
+static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
+					       unsigned size)
+{
+	if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
+		return __do_insn_fetch_bytes(ctxt, size);
+	else
+		return X86EMUL_CONTINUE;
+}
+
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch(_type, _ctxt)					\
-({	unsigned long _x;						\
-	rc = do_insn_fetch(_ctxt, &_x, sizeof(_type));			\
+({	_type _x;							\
+									\
+	rc = do_insn_fetch_bytes(_ctxt, sizeof(_type));			\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
-	(_type)_x;							\
+	ctxt->_eip += sizeof(_type);					\
+	_x = *(_type __aligned(1) *) ctxt->fetch.ptr;			\
+	ctxt->fetch.ptr += sizeof(_type);				\
+	_x;								\
 })
 
 #define insn_fetch_arr(_arr, _size, _ctxt)				\
-({	rc = do_insn_fetch(_ctxt, _arr, (_size));			\
+({									\
+	rc = do_insn_fetch_bytes(_ctxt, _size);				\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
+	ctxt->_eip += (_size);						\
+	memcpy(_arr, ctxt->fetch.ptr, _size);				\
+	ctxt->fetch.ptr += (_size);					\
 })
 
 /*
@@ -1063,19 +1062,17 @@ static int decode_modrm(struct x86_emula
 			struct operand *op)
 {
 	u8 sib;
-	int index_reg = 0, base_reg = 0, scale;
+	int index_reg, base_reg, scale;
 	int rc = X86EMUL_CONTINUE;
 	ulong modrm_ea = 0;
 
-	if (ctxt->rex_prefix) {
-		ctxt->modrm_reg = (ctxt->rex_prefix & 4) << 1;	/* REX.R */
-		index_reg = (ctxt->rex_prefix & 2) << 2; /* REX.X */
-		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
-	}
+	ctxt->modrm_reg = ((ctxt->rex_prefix << 1) & 8); /* REX.R */
+	index_reg = (ctxt->rex_prefix << 2) & 8; /* REX.X */
+	base_reg = (ctxt->rex_prefix << 3) & 8; /* REX.B */
 
-	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
+	ctxt->modrm_mod = (ctxt->modrm & 0xc0) >> 6;
 	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
-	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
+	ctxt->modrm_rm = base_reg | (ctxt->modrm & 0x07);
 	ctxt->modrm_seg = VCPU_SREG_DS;
 
 	if (ctxt->modrm_mod == 3 || (ctxt->d & NoMod)) {
@@ -1093,7 +1090,7 @@ static int decode_modrm(struct x86_emula
 		if (ctxt->d & Mmx) {
 			op->type = OP_MM;
 			op->bytes = 8;
-			op->addr.xmm = ctxt->modrm_rm & 7;
+			op->addr.mm = ctxt->modrm_rm & 7;
 			return rc;
 		}
 		fetch_register_operand(op);
@@ -1190,6 +1187,9 @@ static int decode_modrm(struct x86_emula
 		}
 	}
 	op->addr.mem.ea = modrm_ea;
+	if (ctxt->ad_bytes != 8)
+		ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
+
 done:
 	return rc;
 }
@@ -1220,12 +1220,14 @@ static void fetch_bit_operand(struct x86
 	long sv = 0, mask;
 
 	if (ctxt->dst.type == OP_MEM && ctxt->src.type == OP_REG) {
-		mask = ~(ctxt->dst.bytes * 8 - 1);
+		mask = ~((long)ctxt->dst.bytes * 8 - 1);
 
 		if (ctxt->src.bytes == 2)
 			sv = (s16)ctxt->src.val & (s16)mask;
 		else if (ctxt->src.bytes == 4)
 			sv = (s32)ctxt->src.val & (s32)mask;
+		else
+			sv = (s64)ctxt->src.val & (s64)mask;
 
 		ctxt->dst.addr.mem.ea += (sv >> 3);
 	}
@@ -1315,8 +1317,7 @@ static int pio_in_emulated(struct x86_em
 		in_page = (ctxt->eflags & EFLG_DF) ?
 			offset_in_page(reg_read(ctxt, VCPU_REGS_RDI)) :
 			PAGE_SIZE - offset_in_page(reg_read(ctxt, VCPU_REGS_RDI));
-		n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
-			count);
+		n = min3(in_page, (unsigned int)sizeof(rc->data) / size, count);
 		if (n == 0)
 			n = 1;
 		rc->pos = rc->end = 0;
@@ -1358,17 +1359,19 @@ static void get_descriptor_table_ptr(str
 				     u16 selector, struct desc_ptr *dt)
 {
 	const struct x86_emulate_ops *ops = ctxt->ops;
+	u32 base3 = 0;
 
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
 		u16 sel;
 
 		memset (dt, 0, sizeof *dt);
-		if (!ops->get_segment(ctxt, &sel, &desc, NULL, VCPU_SREG_LDTR))
+		if (!ops->get_segment(ctxt, &sel, &desc, &base3,
+				      VCPU_SREG_LDTR))
 			return;
 
 		dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
-		dt->address = get_desc_base(&desc);
+		dt->address = get_desc_base(&desc) | ((u64)base3 << 32);
 	} else
 		ops->get_gdt(ctxt, dt);
 }
@@ -1422,6 +1425,7 @@ static int __load_segment_descriptor(str
 	ulong desc_addr;
 	int ret;
 	u16 dummy;
+	u32 base3 = 0;
 
 	memset(&seg_desc, 0, sizeof seg_desc);
 
@@ -1487,9 +1491,6 @@ static int __load_segment_descriptor(str
 			goto exception;
 		break;
 	case VCPU_SREG_CS:
-		if (in_task_switch && rpl != dpl)
-			goto exception;
-
 		if (!(seg_desc.type & 8))
 			goto exception;
 
@@ -1538,9 +1539,14 @@ static int __load_segment_descriptor(str
 		ret = write_segment_descriptor(ctxt, selector, &seg_desc);
 		if (ret != X86EMUL_CONTINUE)
 			return ret;
+	} else if (ctxt->mode == X86EMUL_MODE_PROT64) {
+		ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3,
+				sizeof(base3), &ctxt->exception);
+		if (ret != X86EMUL_CONTINUE)
+			return ret;
 	}
 load:
-	ctxt->ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
+	ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
 	return X86EMUL_CONTINUE;
 exception:
 	emulate_exception(ctxt, err_vec, err_code, true);
@@ -1575,34 +1581,28 @@ static void write_register_operand(struc
 
 static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
 {
-	int rc;
-
 	switch (op->type) {
 	case OP_REG:
 		write_register_operand(op);
 		break;
 	case OP_MEM:
 		if (ctxt->lock_prefix)
-			rc = segmented_cmpxchg(ctxt,
+			return segmented_cmpxchg(ctxt,
+						 op->addr.mem,
+						 &op->orig_val,
+						 &op->val,
+						 op->bytes);
+		else
+			return segmented_write(ctxt,
 					       op->addr.mem,
-					       &op->orig_val,
 					       &op->val,
 					       op->bytes);
-		else
-			rc = segmented_write(ctxt,
-					     op->addr.mem,
-					     &op->val,
-					     op->bytes);
-		if (rc != X86EMUL_CONTINUE)
-			return rc;
 		break;
 	case OP_MEM_STR:
-		rc = segmented_write(ctxt,
-				op->addr.mem,
-				op->data,
-				op->bytes * op->count);
-		if (rc != X86EMUL_CONTINUE)
-			return rc;
+		return segmented_write(ctxt,
+				       op->addr.mem,
+				       op->data,
+				       op->bytes * op->count);
 		break;
 	case OP_XMM:
 		write_sse_reg(ctxt, &op->vec_val, op->addr.xmm);
@@ -1671,7 +1671,7 @@ static int emulate_popf(struct x86_emula
 		return rc;
 
 	change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
-		| EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
+		| EFLG_TF | EFLG_DF | EFLG_NT | EFLG_AC | EFLG_ID;
 
 	switch(ctxt->mode) {
 	case X86EMUL_MODE_PROT64:
@@ -1754,6 +1754,9 @@ static int em_pop_sreg(struct x86_emulat
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
+	if (ctxt->modrm_reg == VCPU_SREG_SS)
+		ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
+
 	rc = load_segment_descriptor(ctxt, (u16)selector, seg);
 	return rc;
 }
@@ -1991,6 +1994,9 @@ static int em_cmpxchg8b(struct x86_emula
 {
 	u64 old = ctxt->dst.orig_val64;
 
+	if (ctxt->dst.bytes == 16)
+		return X86EMUL_UNHANDLEABLE;
+
 	if (((u32) (old >> 0) != (u32) reg_read(ctxt, VCPU_REGS_RAX)) ||
 	    ((u32) (old >> 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {
 		*reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old >> 0);
@@ -2017,6 +2023,7 @@ static int em_ret_far(struct x86_emulate
 {
 	int rc;
 	unsigned long cs;
+	int cpl = ctxt->ops->cpl(ctxt);
 
 	rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
@@ -2026,6 +2033,9 @@ static int em_ret_far(struct x86_emulate
 	rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
+	/* Outer-privilege level return is not implemented */
+	if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
+		return X86EMUL_UNHANDLEABLE;
 	rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
 	return rc;
 }
@@ -2044,8 +2054,10 @@ static int em_ret_far_imm(struct x86_emu
 static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
 {
 	/* Save real source value, then compare EAX against destination. */
+	ctxt->dst.orig_val = ctxt->dst.val;
+	ctxt->dst.val = reg_read(ctxt, VCPU_REGS_RAX);
 	ctxt->src.orig_val = ctxt->src.val;
-	ctxt->src.val = reg_read(ctxt, VCPU_REGS_RAX);
+	ctxt->src.val = ctxt->dst.orig_val;
 	fastop(ctxt, em_cmp);
 
 	if (ctxt->eflags & EFLG_ZF) {
@@ -2055,6 +2067,7 @@ static int em_cmpxchg(struct x86_emulate
 		/* Failure: write the value we saw to EAX. */
 		ctxt->dst.type = OP_REG;
 		ctxt->dst.addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
+		ctxt->dst.val = ctxt->dst.orig_val;
 	}
 	return X86EMUL_CONTINUE;
 }
@@ -2194,7 +2207,7 @@ static int em_syscall(struct x86_emulate
 	*reg_write(ctxt, VCPU_REGS_RCX) = ctxt->_eip;
 	if (efer & EFER_LMA) {
 #ifdef CONFIG_X86_64
-		*reg_write(ctxt, VCPU_REGS_R11) = ctxt->eflags & ~EFLG_RF;
+		*reg_write(ctxt, VCPU_REGS_R11) = ctxt->eflags;
 
 		ops->get_msr(ctxt,
 			     ctxt->mode == X86EMUL_MODE_PROT64 ?
@@ -2202,14 +2215,14 @@ static int em_syscall(struct x86_emulate
 		ctxt->_eip = msr_data;
 
 		ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
-		ctxt->eflags &= ~(msr_data | EFLG_RF);
+		ctxt->eflags &= ~msr_data;
 #endif
 	} else {
 		/* legacy mode */
 		ops->get_msr(ctxt, MSR_STAR, &msr_data);
 		ctxt->_eip = (u32)msr_data;
 
-		ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+		ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
 	}
 
 	return X86EMUL_CONTINUE;
@@ -2258,7 +2271,7 @@ static int em_sysenter(struct x86_emulat
 		break;
 	}
 
-	ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+	ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
 	cs_sel = (u16)msr_data;
 	cs_sel &= ~SELECTOR_RPL_MASK;
 	ss_sel = cs_sel + 8;
@@ -2964,7 +2977,7 @@ static int em_rdpmc(struct x86_emulate_c
 
 static int em_mov(struct x86_emulate_ctxt *ctxt)
 {
-	memcpy(ctxt->dst.valptr, ctxt->src.valptr, ctxt->op_bytes);
+	memcpy(ctxt->dst.valptr, ctxt->src.valptr, sizeof(ctxt->src.valptr));
 	return X86EMUL_CONTINUE;
 }
 
@@ -3221,7 +3234,8 @@ static int em_lidt(struct x86_emulate_ct
 
 static int em_smsw(struct x86_emulate_ctxt *ctxt)
 {
-	ctxt->dst.bytes = 2;
+	if (ctxt->dst.type == OP_MEM)
+		ctxt->dst.bytes = 2;
 	ctxt->dst.val = ctxt->ops->get_cr(ctxt, 0);
 	return X86EMUL_CONTINUE;
 }
@@ -3496,7 +3510,7 @@ static int check_rdpmc(struct x86_emulat
 	u64 rcx = reg_read(ctxt, VCPU_REGS_RCX);
 
 	if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt)) ||
-	    (rcx > 3))
+	    ctxt->ops->check_pmc(ctxt, rcx))
 		return emulate_gp(ctxt, 0);
 
 	return X86EMUL_CONTINUE;
@@ -3521,9 +3535,9 @@ static int check_perm_out(struct x86_emu
 }
 
 #define D(_y) { .flags = (_y) }
-#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
-#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
-		      .check_perm = (_p) }
+#define DI(_y, _i) { .flags = (_y)|Intercept, .intercept = x86_intercept_##_i }
+#define DIP(_y, _i, _p) { .flags = (_y)|Intercept|CheckPerm, \
+		      .intercept = x86_intercept_##_i, .check_perm = (_p) }
 #define N    D(NotImpl)
 #define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
 #define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) }
@@ -3532,10 +3546,10 @@ static int check_perm_out(struct x86_emu
 #define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
 #define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) }
 #define II(_f, _e, _i) \
-	{ .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i }
+	{ .flags = (_f)|Intercept, .u.execute = (_e), .intercept = x86_intercept_##_i }
 #define IIP(_f, _e, _i, _p) \
-	{ .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i, \
-	  .check_perm = (_p) }
+	{ .flags = (_f)|Intercept|CheckPerm, .u.execute = (_e), \
+	  .intercept = x86_intercept_##_i, .check_perm = (_p) }
 #define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) }
 
 #define D2bv(_f)      D((_f) | ByteOp), D(_f)
@@ -3634,8 +3648,8 @@ static const struct opcode group6[] = {
 };
 
 static const struct group_dual group7 = { {
-	II(Mov | DstMem | Priv,			em_sgdt, sgdt),
-	II(Mov | DstMem | Priv,			em_sidt, sidt),
+	II(Mov | DstMem,			em_sgdt, sgdt),
+	II(Mov | DstMem,			em_sidt, sidt),
 	II(SrcMem | Priv,			em_lgdt, lgdt),
 	II(SrcMem | Priv,			em_lidt, lidt),
 	II(SrcNone | DstMem | Mov,		em_smsw, smsw), N,
@@ -3899,7 +3913,7 @@ static const struct opcode twobyte_table
 	N, N,
 	N, N, N, N, N, N, N, N,
 	/* 0x40 - 0x4F */
-	X16(D(DstReg | SrcMem | ModRM | Mov)),
+	X16(D(DstReg | SrcMem | ModRM)),
 	/* 0x50 - 0x5F */
 	N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
 	/* 0x60 - 0x6F */
@@ -4061,12 +4075,12 @@ static int decode_operand(struct x86_emu
 	mem_common:
 		*op = ctxt->memop;
 		ctxt->memopp = op;
-		if ((ctxt->d & BitOp) && op == &ctxt->dst)
+		if (ctxt->d & BitOp)
 			fetch_bit_operand(ctxt);
 		op->orig_val = op->val;
 		break;
 	case OpMem64:
-		ctxt->memop.bytes = 8;
+		ctxt->memop.bytes = (ctxt->op_bytes == 8) ? 16 : 8;
 		goto mem_common;
 	case OpAcc:
 		op->type = OP_REG;
@@ -4150,7 +4164,7 @@ static int decode_operand(struct x86_emu
 		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
 		op->addr.mem.ea =
 			register_address(ctxt, reg_read(ctxt, VCPU_REGS_RSI));
-		op->addr.mem.seg = seg_override(ctxt);
+		op->addr.mem.seg = ctxt->seg_override;
 		op->val = 0;
 		op->count = 1;
 		break;
@@ -4161,7 +4175,7 @@ static int decode_operand(struct x86_emu
 			register_address(ctxt,
 				reg_read(ctxt, VCPU_REGS_RBX) +
 				(reg_read(ctxt, VCPU_REGS_RAX) & 0xff));
-		op->addr.mem.seg = seg_override(ctxt);
+		op->addr.mem.seg = ctxt->seg_override;
 		op->val = 0;
 		break;
 	case OpImmFAddr:
@@ -4208,16 +4222,22 @@ int x86_decode_insn(struct x86_emulate_c
 	int mode = ctxt->mode;
 	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
 	bool op_prefix = false;
+	bool has_seg_override = false;
 	struct opcode opcode;
 
 	ctxt->memop.type = OP_NONE;
 	ctxt->memopp = NULL;
 	ctxt->_eip = ctxt->eip;
-	ctxt->fetch.start = ctxt->_eip;
-	ctxt->fetch.end = ctxt->fetch.start + insn_len;
+	ctxt->fetch.ptr = ctxt->fetch.data;
+	ctxt->fetch.end = ctxt->fetch.data + insn_len;
 	ctxt->opcode_len = 1;
 	if (insn_len > 0)
 		memcpy(ctxt->fetch.data, insn, insn_len);
+	else {
+		rc = __do_insn_fetch_bytes(ctxt, 1);
+		if (rc != X86EMUL_CONTINUE)
+			return rc;
+	}
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
@@ -4261,11 +4281,13 @@ int x86_decode_insn(struct x86_emulate_c
 		case 0x2e:	/* CS override */
 		case 0x36:	/* SS override */
 		case 0x3e:	/* DS override */
-			set_seg_override(ctxt, (ctxt->b >> 3) & 3);
+			has_seg_override = true;
+			ctxt->seg_override = (ctxt->b >> 3) & 3;
 			break;
 		case 0x64:	/* FS override */
 		case 0x65:	/* GS override */
-			set_seg_override(ctxt, ctxt->b & 7);
+			has_seg_override = true;
+			ctxt->seg_override = ctxt->b & 7;
 			break;
 		case 0x40 ... 0x4f: /* REX */
 			if (mode != X86EMUL_MODE_PROT64)
@@ -4314,6 +4336,13 @@ done_prefixes:
 	if (ctxt->d & ModRM)
 		ctxt->modrm = insn_fetch(u8, ctxt);
 
+	/* vex-prefix instructions are not implemented */
+	if (ctxt->opcode_len == 1 && (ctxt->b == 0xc5 || ctxt->b == 0xc4) &&
+	    (mode == X86EMUL_MODE_PROT64 ||
+	    (mode >= X86EMUL_MODE_PROT16 && (ctxt->modrm & 0x80)))) {
+		ctxt->d = NotImpl;
+	}
+
 	while (ctxt->d & GroupMask) {
 		switch (ctxt->d & GroupMask) {
 		case Group:
@@ -4356,49 +4385,59 @@ done_prefixes:
 		ctxt->d |= opcode.flags;
 	}
 
-	ctxt->execute = opcode.u.execute;
-	ctxt->check_perm = opcode.check_perm;
-	ctxt->intercept = opcode.intercept;
-
 	/* Unrecognised? */
-	if (ctxt->d == 0 || (ctxt->d & NotImpl))
+	if (ctxt->d == 0)
 		return EMULATION_FAILED;
 
-	if (!(ctxt->d & EmulateOnUD) && ctxt->ud)
+	ctxt->execute = opcode.u.execute;
+
+	if (unlikely(ctxt->ud) && likely(!(ctxt->d & EmulateOnUD)))
 		return EMULATION_FAILED;
 
-	if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
-		ctxt->op_bytes = 8;
+	if (unlikely(ctxt->d &
+		     (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) {
+		/*
+		 * These are copied unconditionally here, and checked unconditionally
+		 * in x86_emulate_insn.
+		 */
+		ctxt->check_perm = opcode.check_perm;
+		ctxt->intercept = opcode.intercept;
 
-	if (ctxt->d & Op3264) {
-		if (mode == X86EMUL_MODE_PROT64)
+		if (ctxt->d & NotImpl)
+			return EMULATION_FAILED;
+
+		if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
 			ctxt->op_bytes = 8;
-		else
-			ctxt->op_bytes = 4;
-	}
 
-	if (ctxt->d & Sse)
-		ctxt->op_bytes = 16;
-	else if (ctxt->d & Mmx)
-		ctxt->op_bytes = 8;
+		if (ctxt->d & Op3264) {
+			if (mode == X86EMUL_MODE_PROT64)
+				ctxt->op_bytes = 8;
+			else
+				ctxt->op_bytes = 4;
+		}
+
+		if (ctxt->d & Sse)
+			ctxt->op_bytes = 16;
+		else if (ctxt->d & Mmx)
+			ctxt->op_bytes = 8;
+	}
 
 	/* ModRM and SIB bytes. */
 	if (ctxt->d & ModRM) {
 		rc = decode_modrm(ctxt, &ctxt->memop);
-		if (!ctxt->has_seg_override)
-			set_seg_override(ctxt, ctxt->modrm_seg);
+		if (!has_seg_override) {
+			has_seg_override = true;
+			ctxt->seg_override = ctxt->modrm_seg;
+		}
 	} else if (ctxt->d & MemAbs)
 		rc = decode_abs(ctxt, &ctxt->memop);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
-	if (!ctxt->has_seg_override)
-		set_seg_override(ctxt, VCPU_SREG_DS);
-
-	ctxt->memop.addr.mem.seg = seg_override(ctxt);
+	if (!has_seg_override)
+		ctxt->seg_override = VCPU_SREG_DS;
 
-	if (ctxt->memop.type == OP_MEM && ctxt->ad_bytes != 8)
-		ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
+	ctxt->memop.addr.mem.seg = ctxt->seg_override;
 
 	/*
 	 * Decode and fetch the source operand: register, memory
@@ -4420,7 +4459,7 @@ done_prefixes:
 	rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
 done:
-	if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
+	if (ctxt->rip_relative)
 		ctxt->memopp->addr.mem.ea += ctxt->_eip;
 
 	return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
@@ -4495,6 +4534,16 @@ static int fastop(struct x86_emulate_ctx
 	return X86EMUL_CONTINUE;
 }
 
+void init_decode_cache(struct x86_emulate_ctxt *ctxt)
+{
+	memset(&ctxt->rip_relative, 0,
+	       (void *)&ctxt->modrm - (void *)&ctxt->rip_relative);
+
+	ctxt->io_read.pos = 0;
+	ctxt->io_read.end = 0;
+	ctxt->mem_read.end = 0;
+}
+
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 {
 	const struct x86_emulate_ops *ops = ctxt->ops;
@@ -4503,12 +4552,6 @@ int x86_emulate_insn(struct x86_emulate_
 
 	ctxt->mem_read.pos = 0;
 
-	if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
-			(ctxt->d & Undefined)) {
-		rc = emulate_ud(ctxt);
-		goto done;
-	}
-
 	/* LOCK prefix is allowed only with some instructions */
 	if (ctxt->lock_prefix && (!(ctxt->d & Lock) || ctxt->dst.type != OP_MEM)) {
 		rc = emulate_ud(ctxt);
@@ -4520,69 +4563,82 @@ int x86_emulate_insn(struct x86_emulate_
 		goto done;
 	}
 
-	if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
-	    || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
-		rc = emulate_ud(ctxt);
-		goto done;
-	}
-
-	if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
-		rc = emulate_nm(ctxt);
-		goto done;
-	}
+	if (unlikely(ctxt->d &
+		     (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
+		if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
+				(ctxt->d & Undefined)) {
+			rc = emulate_ud(ctxt);
+			goto done;
+		}
 
-	if (ctxt->d & Mmx) {
-		rc = flush_pending_x87_faults(ctxt);
-		if (rc != X86EMUL_CONTINUE)
+		if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
+		    || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
+			rc = emulate_ud(ctxt);
 			goto done;
-		/*
-		 * Now that we know the fpu is exception safe, we can fetch
-		 * operands from it.
-		 */
-		fetch_possible_mmx_operand(ctxt, &ctxt->src);
-		fetch_possible_mmx_operand(ctxt, &ctxt->src2);
-		if (!(ctxt->d & Mov))
-			fetch_possible_mmx_operand(ctxt, &ctxt->dst);
-	}
+		}
 
-	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
-		rc = emulator_check_intercept(ctxt, ctxt->intercept,
-					      X86_ICPT_PRE_EXCEPT);
-		if (rc != X86EMUL_CONTINUE)
+		if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
+			rc = emulate_nm(ctxt);
 			goto done;
-	}
+		}
 
-	/* Privileged instruction can be executed only in CPL=0 */
-	if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
-		rc = emulate_gp(ctxt, 0);
-		goto done;
-	}
+		if (ctxt->d & Mmx) {
+			rc = flush_pending_x87_faults(ctxt);
+			if (rc != X86EMUL_CONTINUE)
+				goto done;
+			/*
+			 * Now that we know the fpu is exception safe, we can fetch
+			 * operands from it.
+			 */
+			fetch_possible_mmx_operand(ctxt, &ctxt->src);
+			fetch_possible_mmx_operand(ctxt, &ctxt->src2);
+			if (!(ctxt->d & Mov))
+				fetch_possible_mmx_operand(ctxt, &ctxt->dst);
+		}
 
-	/* Instruction can only be executed in protected mode */
-	if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
-		rc = emulate_ud(ctxt);
-		goto done;
-	}
+		if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
+			rc = emulator_check_intercept(ctxt, ctxt->intercept,
+						      X86_ICPT_PRE_EXCEPT);
+			if (rc != X86EMUL_CONTINUE)
+				goto done;
+		}
 
-	/* Do instruction specific permission checks */
-	if (ctxt->check_perm) {
-		rc = ctxt->check_perm(ctxt);
-		if (rc != X86EMUL_CONTINUE)
+		/* Privileged instruction can be executed only in CPL=0 */
+		if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
+			if (ctxt->d & PrivUD)
+				rc = emulate_ud(ctxt);
+			else
+				rc = emulate_gp(ctxt, 0);
 			goto done;
-	}
+		}
 
-	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
-		rc = emulator_check_intercept(ctxt, ctxt->intercept,
-					      X86_ICPT_POST_EXCEPT);
-		if (rc != X86EMUL_CONTINUE)
+		/* Instruction can only be executed in protected mode */
+		if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
+			rc = emulate_ud(ctxt);
 			goto done;
-	}
+		}
 
-	if (ctxt->rep_prefix && (ctxt->d & String)) {
-		/* All REP prefixes have the same first termination condition */
-		if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
-			ctxt->eip = ctxt->_eip;
-			goto done;
+		/* Do instruction specific permission checks */
+		if (ctxt->d & CheckPerm) {
+			rc = ctxt->check_perm(ctxt);
+			if (rc != X86EMUL_CONTINUE)
+				goto done;
+		}
+
+		if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
+			rc = emulator_check_intercept(ctxt, ctxt->intercept,
+						      X86_ICPT_POST_EXCEPT);
+			if (rc != X86EMUL_CONTINUE)
+				goto done;
+		}
+
+		if (ctxt->rep_prefix && (ctxt->d & String)) {
+			/* All REP prefixes have the same first termination condition */
+			if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
+				ctxt->eip = ctxt->_eip;
+				ctxt->eflags &= ~EFLG_RF;
+				goto done;
+			}
 		}
 	}
 
@@ -4616,13 +4672,18 @@ int x86_emulate_insn(struct x86_emulate_
 
 special_insn:
 
-	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+	if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
 		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_POST_MEMACCESS);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
+	if (ctxt->rep_prefix && (ctxt->d & String))
+		ctxt->eflags |= EFLG_RF;
+	else
+		ctxt->eflags &= ~EFLG_RF;
+
 	if (ctxt->execute) {
 		if (ctxt->d & Fastop) {
 			void (*fop)(struct fastop *) = (void *)ctxt->execute;
@@ -4657,8 +4718,9 @@ special_insn:
 		break;
 	case 0x90 ... 0x97: /* nop / xchg reg, rax */
 		if (ctxt->dst.addr.reg == reg_rmw(ctxt, VCPU_REGS_RAX))
-			break;
-		rc = em_xchg(ctxt);
+			ctxt->dst.type = OP_NONE;
+		else
+			rc = em_xchg(ctxt);
 		break;
 	case 0x98: /* cbw/cwde/cdqe */
 		switch (ctxt->op_bytes) {
@@ -4709,17 +4771,17 @@ special_insn:
 		goto done;
 
 writeback:
-	if (!(ctxt->d & NoWrite)) {
-		rc = writeback(ctxt, &ctxt->dst);
-		if (rc != X86EMUL_CONTINUE)
-			goto done;
-	}
 	if (ctxt->d & SrcWrite) {
 		BUG_ON(ctxt->src.type == OP_MEM || ctxt->src.type == OP_MEM_STR);
 		rc = writeback(ctxt, &ctxt->src);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
+	if (!(ctxt->d & NoWrite)) {
+		rc = writeback(ctxt, &ctxt->dst);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
+	}
 
 	/*
 	 * restore dst type in case the decoding will be reused
@@ -4761,6 +4823,7 @@ writeback:
 			}
 			goto done; /* skip rip writeback */
 		}
+		ctxt->eflags &= ~EFLG_RF;
 	}
 
 	ctxt->eip = ctxt->_eip;
@@ -4793,8 +4856,10 @@ twobyte_insn:
 		ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
 		break;
 	case 0x40 ... 0x4f:	/* cmov */
-		ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val;
-		if (!test_cc(ctxt->b, ctxt->eflags))
+		if (test_cc(ctxt->b, ctxt->eflags))
+			ctxt->dst.val = ctxt->src.val;
+		else if (ctxt->mode != X86EMUL_MODE_PROT64 ||
+			 ctxt->op_bytes != 4)
 			ctxt->dst.type = OP_NONE; /* no writeback */
 		break;
 	case 0x80 ... 0x8f: /* jnz rel, etc*/
@@ -4818,8 +4883,8 @@ twobyte_insn:
 		break;
 	case 0xc3:		/* movnti */
 		ctxt->dst.bytes = ctxt->op_bytes;
-		ctxt->dst.val = (ctxt->op_bytes == 4) ? (u32) ctxt->src.val :
-							(u64) ctxt->src.val;
+		ctxt->dst.val = (ctxt->op_bytes == 8) ? (u64) ctxt->src.val :
+							(u32) ctxt->src.val;
 		break;
 	default:
 		goto cannot_emulate;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/irq.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/irq.c
--- linux-libre-3.16-gnu/arch/x86/kvm/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,7 +108,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcp
 
 	vector = kvm_cpu_get_extint(v);
 
-	if (kvm_apic_vid_enabled(v->kvm) || vector != -1)
+	if (vector != -1)
 		return vector;			/* PIC */
 
 	return kvm_get_apic_interrupt(v);	/* APIC */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/Kconfig linux-libre-3.17-rc7-gnu/arch/x86/kvm/Kconfig
--- linux-libre-3.16-gnu/arch/x86/kvm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ config KVM
 	select MMU_NOTIFIER
 	select ANON_INODES
 	select HAVE_KVM_IRQCHIP
+	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQ_ROUTING
 	select HAVE_KVM_EVENTFD
 	select KVM_APIC_ARCHITECTURE
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/lapic.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/lapic.c
--- linux-libre-3.16-gnu/arch/x86/kvm/lapic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/lapic.c	2014-09-28 17:29:07.000000000 -0400
@@ -352,25 +352,46 @@ static inline int apic_find_highest_irr(
 
 static inline void apic_clear_irr(int vec, struct kvm_lapic *apic)
 {
-	apic->irr_pending = false;
+	struct kvm_vcpu *vcpu;
+
+	vcpu = apic->vcpu;
+
 	apic_clear_vector(vec, apic->regs + APIC_IRR);
-	if (apic_search_irr(apic) != -1)
-		apic->irr_pending = true;
+	if (unlikely(kvm_apic_vid_enabled(vcpu->kvm)))
+		/* try to update RVI */
+		kvm_make_request(KVM_REQ_EVENT, vcpu);
+	else {
+		vec = apic_search_irr(apic);
+		apic->irr_pending = (vec != -1);
+	}
 }
 
 static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
 {
-	/* Note that we never get here with APIC virtualization enabled.  */
+	struct kvm_vcpu *vcpu;
+
+	if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
+		return;
+
+	vcpu = apic->vcpu;
 
-	if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
-		++apic->isr_count;
-	BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
 	/*
-	 * ISR (in service register) bit is set when injecting an interrupt.
-	 * The highest vector is injected. Thus the latest bit set matches
-	 * the highest bit in ISR.
+	 * With APIC virtualization enabled, all caching is disabled
+	 * because the processor can modify ISR under the hood.  Instead
+	 * just set SVI.
 	 */
-	apic->highest_isr_cache = vec;
+	if (unlikely(kvm_apic_vid_enabled(vcpu->kvm)))
+		kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec);
+	else {
+		++apic->isr_count;
+		BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
+		/*
+		 * ISR (in service register) bit is set when injecting an interrupt.
+		 * The highest vector is injected. Thus the latest bit set matches
+		 * the highest bit in ISR.
+		 */
+		apic->highest_isr_cache = vec;
+	}
 }
 
 static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -1451,7 +1472,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vc
 	vcpu->arch.apic_arb_prio = 0;
 	vcpu->arch.apic_attention = 0;
 
-	apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
+	apic_debug("%s: vcpu=%p, id=%d, base_msr="
 		   "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
 		   vcpu, kvm_apic_id(apic),
 		   vcpu->arch.apic_base, apic->base_address);
@@ -1627,11 +1648,16 @@ int kvm_get_apic_interrupt(struct kvm_vc
 	int vector = kvm_apic_has_interrupt(vcpu);
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	/* Note that we never get here with APIC virtualization enabled.  */
-
 	if (vector == -1)
 		return -1;
 
+	/*
+	 * We get here even with APIC virtualization enabled, if doing
+	 * nested virtualization and L1 runs with the "acknowledge interrupt
+	 * on exit" mode.  Then we cannot inject the interrupt via RVI,
+	 * because the process would deliver it through the IDT.
+	 */
+
 	apic_set_isr(vector, apic);
 	apic_update_ppr(apic);
 	apic_clear_irr(vector, apic);
@@ -1895,7 +1921,7 @@ void kvm_apic_accept_events(struct kvm_v
 		/* evaluate pending_events before reading the vector */
 		smp_rmb();
 		sipi_vector = apic->sipi_vector;
-		pr_debug("vcpu %d received sipi with vector # %x\n",
+		apic_debug("vcpu %d received sipi with vector # %x\n",
 			 vcpu->vcpu_id, sipi_vector);
 		kvm_vcpu_deliver_sipi_vector(vcpu, sipi_vector);
 		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/mmu_audit.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/mmu_audit.c
--- linux-libre-3.16-gnu/arch/x86/kvm/mmu_audit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/mmu_audit.c	2014-09-28 17:29:07.000000000 -0400
@@ -273,7 +273,7 @@ static int mmu_audit_set(const char *val
 	int ret;
 	unsigned long enable;
 
-	ret = strict_strtoul(val, 10, &enable);
+	ret = kstrtoul(val, 10, &enable);
 	if (ret < 0)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/mmutrace.h linux-libre-3.17-rc7-gnu/arch/x86/kvm/mmutrace.h
--- linux-libre-3.16-gnu/arch/x86/kvm/mmutrace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/mmutrace.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@
 	__entry->unsync = sp->unsync;
 
 #define KVM_MMU_PAGE_PRINTK() ({				        \
-	const char *ret = p->buffer + p->len;				\
+	const u32 saved_len = p->len;					\
 	static const char *access_str[] = {			        \
 		"---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux"  \
 	};							        \
@@ -41,7 +41,7 @@
 			 role.nxe ? "" : "!",				\
 			 __entry->root_count,				\
 			 __entry->unsync ? "unsync" : "sync", 0);	\
-	ret;								\
+	p->buffer + saved_len;						\
 		})
 
 #define kvm_mmu_trace_pferr_flags       \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/pmu.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/pmu.c
--- linux-libre-3.16-gnu/arch/x86/kvm/pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -428,6 +428,15 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcp
 	return 1;
 }
 
+int kvm_pmu_check_pmc(struct kvm_vcpu *vcpu, unsigned pmc)
+{
+	struct kvm_pmu *pmu = &vcpu->arch.pmu;
+	bool fixed = pmc & (1u << 30);
+	pmc &= ~(3u << 30);
+	return (!fixed && pmc >= pmu->nr_arch_gp_counters) ||
+		(fixed && pmc >= pmu->nr_arch_fixed_counters);
+}
+
 int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data)
 {
 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/svm.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/svm.c
--- linux-libre-3.16-gnu/arch/x86/kvm/svm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/svm.c	2014-09-28 17:29:07.000000000 -0400
@@ -486,14 +486,14 @@ static int is_external_interrupt(u32 inf
 	return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
 }
 
-static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u32 ret = 0;
 
 	if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
-		ret |= KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
-	return ret & mask;
+		ret = KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
+	return ret;
 }
 
 static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
@@ -1415,7 +1415,16 @@ static void svm_get_segment(struct kvm_v
 	var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
 	var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
 	var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
-	var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+
+	/*
+	 * AMD CPUs circa 2014 track the G bit for all segments except CS.
+	 * However, the SVM spec states that the G bit is not observed by the
+	 * CPU, and some VMware virtual CPUs drop the G bit for all segments.
+	 * So let's synthesize a legal G bit for all segments, this helps
+	 * running KVM nested. It also helps cross-vendor migration, because
+	 * Intel's vmentry has a check on the 'G' bit.
+	 */
+	var->g = s->limit > 0xfffff;
 
 	/*
 	 * AMD's VMCB does not have an explicit unusable field, so emulate it
@@ -1424,14 +1433,6 @@ static void svm_get_segment(struct kvm_v
 	var->unusable = !var->present || (var->type == 0);
 
 	switch (seg) {
-	case VCPU_SREG_CS:
-		/*
-		 * SVM always stores 0 for the 'G' bit in the CS selector in
-		 * the VMCB on a VMEXIT. This hurts cross-vendor migration:
-		 * Intel's VMENTRY has a check on the 'G' bit.
-		 */
-		var->g = s->limit > 0xfffff;
-		break;
 	case VCPU_SREG_TR:
 		/*
 		 * Work around a bug where the busy flag in the tr selector
@@ -2116,22 +2117,27 @@ static void nested_svm_unmap(struct page
 
 static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
 {
-	unsigned port;
-	u8 val, bit;
+	unsigned port, size, iopm_len;
+	u16 val, mask;
+	u8 start_bit;
 	u64 gpa;
 
 	if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
 		return NESTED_EXIT_HOST;
 
 	port = svm->vmcb->control.exit_info_1 >> 16;
+	size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >>
+		SVM_IOIO_SIZE_SHIFT;
 	gpa  = svm->nested.vmcb_iopm + (port / 8);
-	bit  = port % 8;
-	val  = 0;
+	start_bit = port % 8;
+	iopm_len = (start_bit + size > 8) ? 2 : 1;
+	mask = (0xf >> (4 - size)) << start_bit;
+	val = 0;
 
-	if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1))
-		val &= (1 << bit);
+	if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, iopm_len))
+		return NESTED_EXIT_DONE;
 
-	return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
+	return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
 }
 
 static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
@@ -4205,7 +4211,8 @@ static int svm_check_intercept(struct kv
 		if (info->intercept == x86_intercept_cr_write)
 			icpt_info.exit_code += info->modrm_reg;
 
-		if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0)
+		if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0 ||
+		    info->intercept == x86_intercept_clts)
 			break;
 
 		intercept = svm->nested.intercept;
@@ -4250,14 +4257,14 @@ static int svm_check_intercept(struct kv
 		u64 exit_info;
 		u32 bytes;
 
-		exit_info = (vcpu->arch.regs[VCPU_REGS_RDX] & 0xffff) << 16;
-
 		if (info->intercept == x86_intercept_in ||
 		    info->intercept == x86_intercept_ins) {
-			exit_info |= SVM_IOIO_TYPE_MASK;
-			bytes = info->src_bytes;
-		} else {
+			exit_info = ((info->src_val & 0xffff) << 16) |
+				SVM_IOIO_TYPE_MASK;
 			bytes = info->dst_bytes;
+		} else {
+			exit_info = (info->dst_val & 0xffff) << 16;
+			bytes = info->src_bytes;
 		}
 
 		if (info->intercept == x86_intercept_outs ||
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/trace.h linux-libre-3.17-rc7-gnu/arch/x86/kvm/trace.h
--- linux-libre-3.16-gnu/arch/x86/kvm/trace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/trace.h	2014-09-28 17:29:07.000000000 -0400
@@ -721,10 +721,10 @@ TRACE_EVENT(kvm_emulate_insn,
 		),
 
 	TP_fast_assign(
-		__entry->rip = vcpu->arch.emulate_ctxt.fetch.start;
 		__entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
-		__entry->len = vcpu->arch.emulate_ctxt._eip
-			       - vcpu->arch.emulate_ctxt.fetch.start;
+		__entry->len = vcpu->arch.emulate_ctxt.fetch.ptr
+			       - vcpu->arch.emulate_ctxt.fetch.data;
+		__entry->rip = vcpu->arch.emulate_ctxt._eip - __entry->len;
 		memcpy(__entry->insn,
 		       vcpu->arch.emulate_ctxt.fetch.data,
 		       15);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/vmx.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/vmx.c
--- linux-libre-3.16-gnu/arch/x86/kvm/vmx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/vmx.c	2014-09-28 17:29:07.000000000 -0400
@@ -383,6 +383,9 @@ struct nested_vmx {
 
 	struct hrtimer preemption_timer;
 	bool preemption_timer_expired;
+
+	/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
+	u64 vmcs01_debugctl;
 };
 
 #define POSTED_INTR_ON  0
@@ -740,7 +743,6 @@ static u32 vmx_segment_access_rights(str
 static void vmx_sync_pir_to_irr_dummy(struct kvm_vcpu *vcpu);
 static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx);
 static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
-static bool vmx_mpx_supported(void);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -820,7 +822,6 @@ static const u32 vmx_msr_index[] = {
 #endif
 	MSR_EFER, MSR_TSC_AUX, MSR_STAR,
 };
-#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
 static inline bool is_page_fault(u32 intr_info)
 {
@@ -1940,7 +1941,7 @@ static void vmx_set_rflags(struct kvm_vc
 	vmcs_writel(GUEST_RFLAGS, rflags);
 }
 
-static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu)
 {
 	u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
 	int ret = 0;
@@ -1950,7 +1951,7 @@ static u32 vmx_get_interrupt_shadow(stru
 	if (interruptibility & GUEST_INTR_STATE_MOV_SS)
 		ret |= KVM_X86_SHADOW_INT_MOV_SS;
 
-	return ret & mask;
+	return ret;
 }
 
 static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
@@ -2239,10 +2240,13 @@ static inline bool nested_vmx_allowed(st
  * or other means.
  */
 static u32 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high;
+static u32 nested_vmx_true_procbased_ctls_low;
 static u32 nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high;
 static u32 nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high;
 static u32 nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high;
+static u32 nested_vmx_true_exit_ctls_low;
 static u32 nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high;
+static u32 nested_vmx_true_entry_ctls_low;
 static u32 nested_vmx_misc_low, nested_vmx_misc_high;
 static u32 nested_vmx_ept_caps;
 static __init void nested_vmx_setup_ctls_msrs(void)
@@ -2265,21 +2269,13 @@ static __init void nested_vmx_setup_ctls
 	/* pin-based controls */
 	rdmsr(MSR_IA32_VMX_PINBASED_CTLS,
 	      nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high);
-	/*
-	 * According to the Intel spec, if bit 55 of VMX_BASIC is off (as it is
-	 * in our case), bits 1, 2 and 4 (i.e., 0x16) must be 1 in this MSR.
-	 */
 	nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 	nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK |
 		PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS;
 	nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
 		PIN_BASED_VMX_PREEMPTION_TIMER;
 
-	/*
-	 * Exit controls
-	 * If bit 55 of VMX_BASIC is off, bits 0-8 and 10, 11, 13, 14, 16 and
-	 * 17 must be 1.
-	 */
+	/* exit controls */
 	rdmsr(MSR_IA32_VMX_EXIT_CTLS,
 		nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high);
 	nested_vmx_exit_ctls_low = VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
@@ -2296,10 +2292,13 @@ static __init void nested_vmx_setup_ctls
 	if (vmx_mpx_supported())
 		nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
 
+	/* We support free control of debug control saving. */
+	nested_vmx_true_exit_ctls_low = nested_vmx_exit_ctls_low &
+		~VM_EXIT_SAVE_DEBUG_CONTROLS;
+
 	/* entry controls */
 	rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
 		nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high);
-	/* If bit 55 of VMX_BASIC is off, bits 0-8 and 12 must be 1. */
 	nested_vmx_entry_ctls_low = VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
 	nested_vmx_entry_ctls_high &=
 #ifdef CONFIG_X86_64
@@ -2311,10 +2310,14 @@ static __init void nested_vmx_setup_ctls
 	if (vmx_mpx_supported())
 		nested_vmx_entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
 
+	/* We support free control of debug control loading. */
+	nested_vmx_true_entry_ctls_low = nested_vmx_entry_ctls_low &
+		~VM_ENTRY_LOAD_DEBUG_CONTROLS;
+
 	/* cpu-based controls */
 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
 		nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high);
-	nested_vmx_procbased_ctls_low = 0;
+	nested_vmx_procbased_ctls_low = CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 	nested_vmx_procbased_ctls_high &=
 		CPU_BASED_VIRTUAL_INTR_PENDING |
 		CPU_BASED_VIRTUAL_NMI_PENDING | CPU_BASED_USE_TSC_OFFSETING |
@@ -2335,7 +2338,12 @@ static __init void nested_vmx_setup_ctls
 	 * can use it to avoid exits to L1 - even when L0 runs L2
 	 * without MSR bitmaps.
 	 */
-	nested_vmx_procbased_ctls_high |= CPU_BASED_USE_MSR_BITMAPS;
+	nested_vmx_procbased_ctls_high |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
+		CPU_BASED_USE_MSR_BITMAPS;
+
+	/* We support free control of CR3 access interception. */
+	nested_vmx_true_procbased_ctls_low = nested_vmx_procbased_ctls_low &
+		~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
 
 	/* secondary cpu-based controls */
 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
@@ -2394,7 +2402,7 @@ static int vmx_get_vmx_msr(struct kvm_vc
 		 * guest, and the VMCS structure we give it - not about the
 		 * VMX support of the underlying hardware.
 		 */
-		*pdata = VMCS12_REVISION |
+		*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);
 		break;
@@ -2404,16 +2412,25 @@ static int vmx_get_vmx_msr(struct kvm_vc
 					nested_vmx_pinbased_ctls_high);
 		break;
 	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_true_procbased_ctls_low,
+					nested_vmx_procbased_ctls_high);
+		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS:
 		*pdata = vmx_control_msr(nested_vmx_procbased_ctls_low,
 					nested_vmx_procbased_ctls_high);
 		break;
 	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_true_exit_ctls_low,
+					nested_vmx_exit_ctls_high);
+		break;
 	case MSR_IA32_VMX_EXIT_CTLS:
 		*pdata = vmx_control_msr(nested_vmx_exit_ctls_low,
 					nested_vmx_exit_ctls_high);
 		break;
 	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_true_entry_ctls_low,
+					nested_vmx_entry_ctls_high);
+		break;
 	case MSR_IA32_VMX_ENTRY_CTLS:
 		*pdata = vmx_control_msr(nested_vmx_entry_ctls_low,
 					nested_vmx_entry_ctls_high);
@@ -2442,7 +2459,7 @@ static int vmx_get_vmx_msr(struct kvm_vc
 		*pdata = -1ULL;
 		break;
 	case MSR_IA32_VMX_VMCS_ENUM:
-		*pdata = 0x1f;
+		*pdata = 0x2e; /* highest index: VMX_PREEMPTION_TIMER_VALUE */
 		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS2:
 		*pdata = vmx_control_msr(nested_vmx_secondary_ctls_low,
@@ -3653,7 +3670,7 @@ static void vmx_set_segment(struct kvm_v
 	vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
 
 out:
-	vmx->emulation_required |= emulation_required(vcpu);
+	vmx->emulation_required = emulation_required(vcpu);
 }
 
 static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
@@ -4422,7 +4439,7 @@ static int vmx_vcpu_setup(struct vcpu_vm
 		vmx->vcpu.arch.pat = host_pat;
 	}
 
-	for (i = 0; i < NR_VMX_MSR; ++i) {
+	for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) {
 		u32 index = vmx_msr_index[i];
 		u32 data_low, data_high;
 		int j = vmx->nmsrs;
@@ -4873,7 +4890,7 @@ static int handle_exception(struct kvm_v
 		if (!(vcpu->guest_debug &
 		      (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
 			vcpu->arch.dr6 &= ~15;
-			vcpu->arch.dr6 |= dr6;
+			vcpu->arch.dr6 |= dr6 | DR6_RTM;
 			if (!(dr6 & ~DR6_RESERVED)) /* icebp */
 				skip_emulated_instruction(vcpu);
 
@@ -5039,7 +5056,7 @@ static int handle_cr(struct kvm_vcpu *vc
 	reg = (exit_qualification >> 8) & 15;
 	switch ((exit_qualification >> 4) & 3) {
 	case 0: /* mov to cr */
-		val = kvm_register_read(vcpu, reg);
+		val = kvm_register_readl(vcpu, reg);
 		trace_kvm_cr_write(cr, val);
 		switch (cr) {
 		case 0:
@@ -5056,7 +5073,7 @@ static int handle_cr(struct kvm_vcpu *vc
 			return 1;
 		case 8: {
 				u8 cr8_prev = kvm_get_cr8(vcpu);
-				u8 cr8 = kvm_register_read(vcpu, reg);
+				u8 cr8 = (u8)val;
 				err = kvm_set_cr8(vcpu, cr8);
 				kvm_complete_insn_gp(vcpu, err);
 				if (irqchip_in_kernel(vcpu->kvm))
@@ -5132,7 +5149,7 @@ static int handle_dr(struct kvm_vcpu *vc
 			return 0;
 		} else {
 			vcpu->arch.dr7 &= ~DR7_GD;
-			vcpu->arch.dr6 |= DR6_BD;
+			vcpu->arch.dr6 |= DR6_BD | DR6_RTM;
 			vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
 			kvm_queue_exception(vcpu, DB_VECTOR);
 			return 1;
@@ -5165,7 +5182,7 @@ static int handle_dr(struct kvm_vcpu *vc
 			return 1;
 		kvm_register_write(vcpu, reg, val);
 	} else
-		if (kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)))
+		if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
 			return 1;
 
 	skip_emulated_instruction(vcpu);
@@ -5621,7 +5638,7 @@ static int handle_invalid_guest_state(st
 	cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
 	intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
 
-	while (!guest_state_valid(vcpu) && count-- != 0) {
+	while (vmx->emulation_required && count-- != 0) {
 		if (intr_window_requested && vmx_interrupt_allowed(vcpu))
 			return handle_interrupt_window(&vmx->vcpu);
 
@@ -5655,7 +5672,6 @@ static int handle_invalid_guest_state(st
 			schedule();
 	}
 
-	vmx->emulation_required = emulation_required(vcpu);
 out:
 	return ret;
 }
@@ -5754,22 +5770,27 @@ static void nested_free_vmcs02(struct vc
 
 /*
  * Free all VMCSs saved for this vcpu, except the one pointed by
- * vmx->loaded_vmcs. These include the VMCSs in vmcs02_pool (except the one
- * currently used, if running L2), and vmcs01 when running L2.
+ * vmx->loaded_vmcs. We must be running L1, so vmx->loaded_vmcs
+ * must be &vmx->vmcs01.
  */
 static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
 {
 	struct vmcs02_list *item, *n;
+
+	WARN_ON(vmx->loaded_vmcs != &vmx->vmcs01);
 	list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
-		if (vmx->loaded_vmcs != &item->vmcs02)
-			free_loaded_vmcs(&item->vmcs02);
+		/*
+		 * Something will leak if the above WARN triggers.  Better than
+		 * a use-after-free.
+		 */
+		if (vmx->loaded_vmcs == &item->vmcs02)
+			continue;
+
+		free_loaded_vmcs(&item->vmcs02);
 		list_del(&item->list);
 		kfree(item);
+		vmx->nested.vmcs02_num--;
 	}
-	vmx->nested.vmcs02_num = 0;
-
-	if (vmx->loaded_vmcs != &vmx->vmcs01)
-		free_loaded_vmcs(&vmx->vmcs01);
 }
 
 /*
@@ -5918,7 +5939,7 @@ static int nested_vmx_check_vmptr(struct
 		 * which replaces physical address width with 32
 		 *
 		 */
-		if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failInvalid(vcpu);
 			skip_emulated_instruction(vcpu);
 			return 1;
@@ -5936,7 +5957,7 @@ static int nested_vmx_check_vmptr(struct
 		vmx->nested.vmxon_ptr = vmptr;
 		break;
 	case EXIT_REASON_VMCLEAR:
-		if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failValid(vcpu,
 					     VMXERR_VMCLEAR_INVALID_ADDRESS);
 			skip_emulated_instruction(vcpu);
@@ -5951,7 +5972,7 @@ static int nested_vmx_check_vmptr(struct
 		}
 		break;
 	case EXIT_REASON_VMPTRLD:
-		if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failValid(vcpu,
 					     VMXERR_VMPTRLD_INVALID_ADDRESS);
 			skip_emulated_instruction(vcpu);
@@ -6086,20 +6107,27 @@ static int nested_vmx_check_permission(s
 static inline void nested_release_vmcs12(struct vcpu_vmx *vmx)
 {
 	u32 exec_control;
+	if (vmx->nested.current_vmptr == -1ull)
+		return;
+
+	/* current_vmptr and current_vmcs12 are always set/reset together */
+	if (WARN_ON(vmx->nested.current_vmcs12 == NULL))
+		return;
+
 	if (enable_shadow_vmcs) {
-		if (vmx->nested.current_vmcs12 != NULL) {
-			/* copy to memory all shadowed fields in case
-			   they were modified */
-			copy_shadow_to_vmcs12(vmx);
-			vmx->nested.sync_shadow_vmcs = false;
-			exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
-			exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
-			vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
-			vmcs_write64(VMCS_LINK_POINTER, -1ull);
-		}
+		/* copy to memory all shadowed fields in case
+		   they were modified */
+		copy_shadow_to_vmcs12(vmx);
+		vmx->nested.sync_shadow_vmcs = false;
+		exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+		exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
+		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+		vmcs_write64(VMCS_LINK_POINTER, -1ull);
 	}
 	kunmap(vmx->nested.current_vmcs12_page);
 	nested_release_page(vmx->nested.current_vmcs12_page);
+	vmx->nested.current_vmptr = -1ull;
+	vmx->nested.current_vmcs12 = NULL;
 }
 
 /*
@@ -6110,12 +6138,9 @@ static void free_nested(struct vcpu_vmx
 {
 	if (!vmx->nested.vmxon)
 		return;
+
 	vmx->nested.vmxon = false;
-	if (vmx->nested.current_vmptr != -1ull) {
-		nested_release_vmcs12(vmx);
-		vmx->nested.current_vmptr = -1ull;
-		vmx->nested.current_vmcs12 = NULL;
-	}
+	nested_release_vmcs12(vmx);
 	if (enable_shadow_vmcs)
 		free_vmcs(vmx->nested.current_shadow_vmcs);
 	/* Unpin physical memory we referred to in current vmcs02 */
@@ -6152,11 +6177,8 @@ static int handle_vmclear(struct kvm_vcp
 	if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr))
 		return 1;
 
-	if (vmptr == vmx->nested.current_vmptr) {
+	if (vmptr == vmx->nested.current_vmptr)
 		nested_release_vmcs12(vmx);
-		vmx->nested.current_vmptr = -1ull;
-		vmx->nested.current_vmcs12 = NULL;
-	}
 
 	page = nested_get_page(vcpu, vmptr);
 	if (page == NULL) {
@@ -6384,7 +6406,7 @@ static int handle_vmread(struct kvm_vcpu
 		return 1;
 
 	/* Decode instruction info and find the field to read */
-	field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+	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)) {
 		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
@@ -6397,7 +6419,7 @@ static int handle_vmread(struct kvm_vcpu
 	 * on the guest's mode (32 or 64 bit), not on the given field's length.
 	 */
 	if (vmx_instruction_info & (1u << 10)) {
-		kvm_register_write(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+		kvm_register_writel(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
 			field_value);
 	} else {
 		if (get_vmx_mem_address(vcpu, exit_qualification,
@@ -6434,21 +6456,21 @@ static int handle_vmwrite(struct kvm_vcp
 		return 1;
 
 	if (vmx_instruction_info & (1u << 10))
-		field_value = kvm_register_read(vcpu,
+		field_value = kvm_register_readl(vcpu,
 			(((vmx_instruction_info) >> 3) & 0xf));
 	else {
 		if (get_vmx_mem_address(vcpu, exit_qualification,
 				vmx_instruction_info, &gva))
 			return 1;
 		if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
-			   &field_value, (is_long_mode(vcpu) ? 8 : 4), &e)) {
+			   &field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
 			kvm_inject_page_fault(vcpu, &e);
 			return 1;
 		}
 	}
 
 
-	field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+	field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
 	if (vmcs_field_readonly(field)) {
 		nested_vmx_failValid(vcpu,
 			VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
@@ -6498,9 +6520,8 @@ static int handle_vmptrld(struct kvm_vcp
 			skip_emulated_instruction(vcpu);
 			return 1;
 		}
-		if (vmx->nested.current_vmptr != -1ull)
-			nested_release_vmcs12(vmx);
 
+		nested_release_vmcs12(vmx);
 		vmx->nested.current_vmptr = vmptr;
 		vmx->nested.current_vmcs12 = new_vmcs12;
 		vmx->nested.current_vmcs12_page = page;
@@ -6571,7 +6592,7 @@ static int handle_invept(struct kvm_vcpu
 	}
 
 	vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
-	type = kvm_register_read(vcpu, (vmx_instruction_info >> 28) & 0xf);
+	type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
 
 	types = (nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
 
@@ -6751,7 +6772,7 @@ static bool nested_vmx_exit_handled_cr(s
 	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 	int cr = exit_qualification & 15;
 	int reg = (exit_qualification >> 8) & 15;
-	unsigned long val = kvm_register_read(vcpu, reg);
+	unsigned long val = kvm_register_readl(vcpu, reg);
 
 	switch ((exit_qualification >> 4) & 3) {
 	case 0: /* mov to cr */
@@ -7112,7 +7133,26 @@ static void vmx_hwapic_irr_update(struct
 	if (max_irr == -1)
 		return;
 
-	vmx_set_rvi(max_irr);
+	/*
+	 * If a vmexit is needed, vmx_check_nested_events handles it.
+	 */
+	if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+		return;
+
+	if (!is_guest_mode(vcpu)) {
+		vmx_set_rvi(max_irr);
+		return;
+	}
+
+	/*
+	 * Fall back to pre-APICv interrupt injection since L2
+	 * is run without virtual interrupt delivery.
+	 */
+	if (!kvm_event_needs_reinjection(vcpu) &&
+	    vmx_interrupt_allowed(vcpu)) {
+		kvm_queue_interrupt(vcpu, max_irr, false);
+		vmx_inject_irq(vcpu);
+	}
 }
 
 static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
@@ -7520,13 +7560,31 @@ static void __noclone vmx_vcpu_run(struc
 	vmx_complete_interrupts(vmx);
 }
 
+static void vmx_load_vmcs01(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	int cpu;
+
+	if (vmx->loaded_vmcs == &vmx->vmcs01)
+		return;
+
+	cpu = get_cpu();
+	vmx->loaded_vmcs = &vmx->vmcs01;
+	vmx_vcpu_put(vcpu);
+	vmx_vcpu_load(vcpu, cpu);
+	vcpu->cpu = cpu;
+	put_cpu();
+}
+
 static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	free_vpid(vmx);
-	free_loaded_vmcs(vmx->loaded_vmcs);
+	leave_guest_mode(vcpu);
+	vmx_load_vmcs01(vcpu);
 	free_nested(vmx);
+	free_loaded_vmcs(vmx->loaded_vmcs);
 	kfree(vmx->guest_msrs);
 	kvm_vcpu_uninit(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, vmx);
@@ -7548,6 +7606,9 @@ static struct kvm_vcpu *vmx_create_vcpu(
 		goto free_vcpu;
 
 	vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
+		     > PAGE_SIZE);
+
 	err = -ENOMEM;
 	if (!vmx->guest_msrs) {
 		goto uninit_vcpu;
@@ -7836,7 +7897,13 @@ static void prepare_vmcs02(struct kvm_vc
 	vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
 	vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
 
-	vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+	if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) {
+		kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
+		vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+	} else {
+		kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
+		vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl);
+	}
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
 		vmcs12->vm_entry_intr_info_field);
 	vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
@@ -7846,7 +7913,6 @@ static void prepare_vmcs02(struct kvm_vc
 	vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
 		vmcs12->guest_interruptibility_info);
 	vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
-	kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
 	vmx_set_rflags(vcpu, vmcs12->guest_rflags);
 	vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
 		vmcs12->guest_pending_dbg_exceptions);
@@ -8113,14 +8179,14 @@ static int nested_vmx_run(struct kvm_vcp
 	}
 
 	if ((vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_MSR_BITMAPS) &&
-			!IS_ALIGNED(vmcs12->msr_bitmap, PAGE_SIZE)) {
+			!PAGE_ALIGNED(vmcs12->msr_bitmap)) {
 		/*TODO: Also verify bits beyond physical address width are 0*/
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 		return 1;
 	}
 
 	if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
-			!IS_ALIGNED(vmcs12->apic_access_addr, PAGE_SIZE)) {
+			!PAGE_ALIGNED(vmcs12->apic_access_addr)) {
 		/*TODO: Also verify bits beyond physical address width are 0*/
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 		return 1;
@@ -8136,15 +8202,18 @@ static int nested_vmx_run(struct kvm_vcp
 	}
 
 	if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
-	      nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high) ||
+				nested_vmx_true_procbased_ctls_low,
+				nested_vmx_procbased_ctls_high) ||
 	    !vmx_control_verify(vmcs12->secondary_vm_exec_control,
 	      nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high) ||
 	    !vmx_control_verify(vmcs12->pin_based_vm_exec_control,
 	      nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) ||
 	    !vmx_control_verify(vmcs12->vm_exit_controls,
-	      nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) ||
+				nested_vmx_true_exit_ctls_low,
+				nested_vmx_exit_ctls_high) ||
 	    !vmx_control_verify(vmcs12->vm_entry_controls,
-	      nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high))
+				nested_vmx_true_entry_ctls_low,
+				nested_vmx_entry_ctls_high))
 	{
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 		return 1;
@@ -8221,6 +8290,9 @@ static int nested_vmx_run(struct kvm_vcp
 
 	vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET);
 
+	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
+		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+
 	cpu = get_cpu();
 	vmx->loaded_vmcs = vmcs02;
 	vmx_vcpu_put(vcpu);
@@ -8398,7 +8470,6 @@ static void prepare_vmcs12(struct kvm_vc
 	vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
 	vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
 
-	kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
 	vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
 	vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
 	vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
@@ -8477,9 +8548,13 @@ static void prepare_vmcs12(struct kvm_vc
 		(vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
 		(vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
 
+	if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS) {
+		kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
+		vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+	}
+
 	/* TODO: These cannot have changed unless we have MSR bitmaps and
 	 * the relevant bit asks not to trap the change */
-	vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
 	if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT)
 		vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
 	if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
@@ -8670,7 +8745,6 @@ static void nested_vmx_vmexit(struct kvm
 			      unsigned long exit_qualification)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	int cpu;
 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
 	/* trying to cancel vmlaunch/vmresume is a bug */
@@ -8680,6 +8754,8 @@ static void nested_vmx_vmexit(struct kvm
 	prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
 		       exit_qualification);
 
+	vmx_load_vmcs01(vcpu);
+
 	if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
 	    && nested_exit_intr_ack_set(vcpu)) {
 		int irq = kvm_cpu_get_interrupt(vcpu);
@@ -8695,13 +8771,6 @@ static void nested_vmx_vmexit(struct kvm
 				       vmcs12->vm_exit_intr_error_code,
 				       KVM_ISA_VMX);
 
-	cpu = get_cpu();
-	vmx->loaded_vmcs = &vmx->vmcs01;
-	vmx_vcpu_put(vcpu);
-	vmx_vcpu_load(vcpu, cpu);
-	vcpu->cpu = cpu;
-	put_cpu();
-
 	vm_entry_controls_init(vmx, vmcs_read32(VM_ENTRY_CONTROLS));
 	vm_exit_controls_init(vmx, vmcs_read32(VM_EXIT_CONTROLS));
 	vmx_segment_cache_clear(vmx);
@@ -8890,7 +8959,7 @@ static int __init vmx_init(void)
 
 	rdmsrl_safe(MSR_EFER, &host_efer);
 
-	for (i = 0; i < NR_VMX_MSR; ++i)
+	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);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/x86.c linux-libre-3.17-rc7-gnu/arch/x86/kvm/x86.c
--- linux-libre-3.16-gnu/arch/x86/kvm/x86.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/x86.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,7 @@ static u64 __read_mostly efer_reserved_b
 
 static void update_cr8_intercept(struct kvm_vcpu *vcpu);
 static void process_nmi(struct kvm_vcpu *vcpu);
+static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
 
 struct kvm_x86_ops *kvm_x86_ops;
 EXPORT_SYMBOL_GPL(kvm_x86_ops);
@@ -211,6 +212,7 @@ static void shared_msr_update(unsigned s
 
 void kvm_define_shared_msr(unsigned slot, u32 msr)
 {
+	BUG_ON(slot >= KVM_NR_SHARED_MSRS);
 	if (slot >= shared_msrs_global.nr)
 		shared_msrs_global.nr = slot + 1;
 	shared_msrs_global.msrs[slot] = msr;
@@ -310,6 +312,31 @@ static int exception_class(int vector)
 	return EXCPT_BENIGN;
 }
 
+#define EXCPT_FAULT		0
+#define EXCPT_TRAP		1
+#define EXCPT_ABORT		2
+#define EXCPT_INTERRUPT		3
+
+static int exception_type(int vector)
+{
+	unsigned int mask;
+
+	if (WARN_ON(vector > 31 || vector == NMI_VECTOR))
+		return EXCPT_INTERRUPT;
+
+	mask = 1 << vector;
+
+	/* #DB is trap, as instruction watchpoints are handled elsewhere */
+	if (mask & ((1 << DB_VECTOR) | (1 << BP_VECTOR) | (1 << OF_VECTOR)))
+		return EXCPT_TRAP;
+
+	if (mask & ((1 << DF_VECTOR) | (1 << MC_VECTOR)))
+		return EXCPT_ABORT;
+
+	/* Reserved exceptions will result in fault */
+	return EXCPT_FAULT;
+}
+
 static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
 		unsigned nr, bool has_error, u32 error_code,
 		bool reinject)
@@ -758,6 +785,15 @@ static void kvm_update_dr7(struct kvm_vc
 		vcpu->arch.switch_db_regs |= KVM_DEBUGREG_BP_ENABLED;
 }
 
+static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu)
+{
+	u64 fixed = DR6_FIXED_1;
+
+	if (!guest_cpuid_has_rtm(vcpu))
+		fixed |= DR6_RTM;
+	return fixed;
+}
+
 static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
 	switch (dr) {
@@ -773,7 +809,7 @@ static int __kvm_set_dr(struct kvm_vcpu
 	case 6:
 		if (val & 0xffffffff00000000ULL)
 			return -1; /* #GP */
-		vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
+		vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu);
 		kvm_update_dr6(vcpu);
 		break;
 	case 5:
@@ -984,9 +1020,8 @@ struct pvclock_gtod_data {
 		u32	shift;
 	} clock;
 
-	/* open coded 'struct timespec' */
-	u64		monotonic_time_snsec;
-	time_t		monotonic_time_sec;
+	u64		boot_ns;
+	u64		nsec_base;
 };
 
 static struct pvclock_gtod_data pvclock_gtod_data;
@@ -994,27 +1029,21 @@ static struct pvclock_gtod_data pvclock_
 static void update_pvclock_gtod(struct timekeeper *tk)
 {
 	struct pvclock_gtod_data *vdata = &pvclock_gtod_data;
+	u64 boot_ns;
+
+	boot_ns = ktime_to_ns(ktime_add(tk->tkr.base_mono, tk->offs_boot));
 
 	write_seqcount_begin(&vdata->seq);
 
 	/* copy pvclock gtod data */
-	vdata->clock.vclock_mode	= tk->clock->archdata.vclock_mode;
-	vdata->clock.cycle_last		= tk->clock->cycle_last;
-	vdata->clock.mask		= tk->clock->mask;
-	vdata->clock.mult		= tk->mult;
-	vdata->clock.shift		= tk->shift;
+	vdata->clock.vclock_mode	= tk->tkr.clock->archdata.vclock_mode;
+	vdata->clock.cycle_last		= tk->tkr.cycle_last;
+	vdata->clock.mask		= tk->tkr.mask;
+	vdata->clock.mult		= tk->tkr.mult;
+	vdata->clock.shift		= tk->tkr.shift;
 
-	vdata->monotonic_time_sec	= tk->xtime_sec
-					+ tk->wall_to_monotonic.tv_sec;
-	vdata->monotonic_time_snsec	= tk->xtime_nsec
-					+ (tk->wall_to_monotonic.tv_nsec
-						<< tk->shift);
-	while (vdata->monotonic_time_snsec >=
-					(((u64)NSEC_PER_SEC) << tk->shift)) {
-		vdata->monotonic_time_snsec -=
-					((u64)NSEC_PER_SEC) << tk->shift;
-		vdata->monotonic_time_sec++;
-	}
+	vdata->boot_ns			= boot_ns;
+	vdata->nsec_base		= tk->tkr.xtime_nsec;
 
 	write_seqcount_end(&vdata->seq);
 }
@@ -1109,11 +1138,7 @@ static void kvm_get_time_scale(uint32_t
 
 static inline u64 get_kernel_ns(void)
 {
-	struct timespec ts;
-
-	ktime_get_ts(&ts);
-	monotonic_to_bootbased(&ts);
-	return timespec_to_ns(&ts);
+	return ktime_get_boot_ns();
 }
 
 #ifdef CONFIG_X86_64
@@ -1215,6 +1240,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu
 	unsigned long flags;
 	s64 usdiff;
 	bool matched;
+	bool already_matched;
 	u64 data = msr->data;
 
 	raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
@@ -1279,6 +1305,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu
 			pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
 		}
 		matched = true;
+		already_matched = (vcpu->arch.this_tsc_generation == kvm->arch.cur_tsc_generation);
 	} else {
 		/*
 		 * We split periods of matched TSC writes into generations.
@@ -1294,7 +1321,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu
 		kvm->arch.cur_tsc_write = data;
 		kvm->arch.cur_tsc_offset = offset;
 		matched = false;
-		pr_debug("kvm: new tsc generation %u, clock %llu\n",
+		pr_debug("kvm: new tsc generation %llu, clock %llu\n",
 			 kvm->arch.cur_tsc_generation, data);
 	}
 
@@ -1319,10 +1346,11 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu
 	raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 
 	spin_lock(&kvm->arch.pvclock_gtod_sync_lock);
-	if (matched)
-		kvm->arch.nr_vcpus_matched_tsc++;
-	else
+	if (!matched) {
 		kvm->arch.nr_vcpus_matched_tsc = 0;
+	} else if (!already_matched) {
+		kvm->arch.nr_vcpus_matched_tsc++;
+	}
 
 	kvm_track_tsc_matching(vcpu);
 	spin_unlock(&kvm->arch.pvclock_gtod_sync_lock);
@@ -1375,23 +1403,22 @@ static inline u64 vgettsc(cycle_t *cycle
 	return v * gtod->clock.mult;
 }
 
-static int do_monotonic(struct timespec *ts, cycle_t *cycle_now)
+static int do_monotonic_boot(s64 *t, cycle_t *cycle_now)
 {
+	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
 	unsigned long seq;
-	u64 ns;
 	int mode;
-	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+	u64 ns;
 
-	ts->tv_nsec = 0;
 	do {
 		seq = read_seqcount_begin(&gtod->seq);
 		mode = gtod->clock.vclock_mode;
-		ts->tv_sec = gtod->monotonic_time_sec;
-		ns = gtod->monotonic_time_snsec;
+		ns = gtod->nsec_base;
 		ns += vgettsc(cycle_now);
 		ns >>= gtod->clock.shift;
+		ns += gtod->boot_ns;
 	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
-	timespec_add_ns(ts, ns);
+	*t = ns;
 
 	return mode;
 }
@@ -1399,19 +1426,11 @@ static int do_monotonic(struct timespec
 /* returns true if host is using tsc clocksource */
 static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
 {
-	struct timespec ts;
-
 	/* checked again under seqlock below */
 	if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
 		return false;
 
-	if (do_monotonic(&ts, cycle_now) != VCLOCK_TSC)
-		return false;
-
-	monotonic_to_bootbased(&ts);
-	*kernel_ns = timespec_to_ns(&ts);
-
-	return true;
+	return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
 }
 #endif
 
@@ -2032,6 +2051,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		data &= ~(u64)0x40;	/* ignore flush filter disable */
 		data &= ~(u64)0x100;	/* ignore ignne emulation enable */
 		data &= ~(u64)0x8;	/* ignore TLB cache disable */
+		data &= ~(u64)0x40000;  /* ignore Mc status write enable */
 		if (data != 0) {
 			vcpu_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n",
 				    data);
@@ -2616,7 +2636,7 @@ out:
 	return r;
 }
 
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 	int r;
 
@@ -2974,9 +2994,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_
 		vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft;
 	events->interrupt.nr = vcpu->arch.interrupt.nr;
 	events->interrupt.soft = 0;
-	events->interrupt.shadow =
-		kvm_x86_ops->get_interrupt_shadow(vcpu,
-			KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI);
+	events->interrupt.shadow = kvm_x86_ops->get_interrupt_shadow(vcpu);
 
 	events->nmi.injected = vcpu->arch.nmi_injected;
 	events->nmi.pending = vcpu->arch.nmi_pending != 0;
@@ -4082,7 +4100,8 @@ static int kvm_read_guest_virt_helper(gv
 
 		if (gpa == UNMAPPED_GVA)
 			return X86EMUL_PROPAGATE_FAULT;
-		ret = kvm_read_guest(vcpu->kvm, gpa, data, toread);
+		ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, data,
+					  offset, toread);
 		if (ret < 0) {
 			r = X86EMUL_IO_NEEDED;
 			goto out;
@@ -4103,10 +4122,24 @@ static int kvm_fetch_guest_virt(struct x
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	unsigned offset;
+	int ret;
 
-	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
-					  access | PFERR_FETCH_MASK,
-					  exception);
+	/* Inline kvm_read_guest_virt_helper for speed.  */
+	gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr, access|PFERR_FETCH_MASK,
+						    exception);
+	if (unlikely(gpa == UNMAPPED_GVA))
+		return X86EMUL_PROPAGATE_FAULT;
+
+	offset = addr & (PAGE_SIZE-1);
+	if (WARN_ON(offset + bytes > PAGE_SIZE))
+		bytes = (unsigned)PAGE_SIZE - offset;
+	ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, val,
+				  offset, bytes);
+	if (unlikely(ret < 0))
+		return X86EMUL_IO_NEEDED;
+
+	return X86EMUL_CONTINUE;
 }
 
 int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
@@ -4730,7 +4763,6 @@ static void emulator_set_segment(struct
 	if (desc->g)
 		var.limit = (var.limit << 12) | 0xfff;
 	var.type = desc->type;
-	var.present = desc->p;
 	var.dpl = desc->dpl;
 	var.db = desc->d;
 	var.s = desc->s;
@@ -4762,6 +4794,12 @@ static int emulator_set_msr(struct x86_e
 	return kvm_set_msr(emul_to_vcpu(ctxt), &msr);
 }
 
+static int emulator_check_pmc(struct x86_emulate_ctxt *ctxt,
+			      u32 pmc)
+{
+	return kvm_pmu_check_pmc(emul_to_vcpu(ctxt), pmc);
+}
+
 static int emulator_read_pmc(struct x86_emulate_ctxt *ctxt,
 			     u32 pmc, u64 *pdata)
 {
@@ -4838,6 +4876,7 @@ static const struct x86_emulate_ops emul
 	.set_dr              = emulator_set_dr,
 	.set_msr             = emulator_set_msr,
 	.get_msr             = emulator_get_msr,
+	.check_pmc	     = emulator_check_pmc,
 	.read_pmc            = emulator_read_pmc,
 	.halt                = emulator_halt,
 	.wbinvd              = emulator_wbinvd,
@@ -4850,7 +4889,7 @@ static const struct x86_emulate_ops emul
 
 static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
 {
-	u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu, mask);
+	u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu);
 	/*
 	 * an sti; sti; sequence only disable interrupts for the first
 	 * instruction. So, if the last instruction, be it emulated or
@@ -4858,8 +4897,13 @@ static void toggle_interruptibility(stru
 	 * means that the last instruction is an sti. We should not
 	 * leave the flag on in this case. The same goes for mov ss
 	 */
-	if (!(int_shadow & mask))
+	if (int_shadow & mask)
+		mask = 0;
+	if (unlikely(int_shadow || mask)) {
 		kvm_x86_ops->set_interrupt_shadow(vcpu, mask);
+		if (!mask)
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
+	}
 }
 
 static void inject_emulated_exception(struct kvm_vcpu *vcpu)
@@ -4874,19 +4918,6 @@ static void inject_emulated_exception(st
 		kvm_queue_exception(vcpu, ctxt->exception.vector);
 }
 
-static void init_decode_cache(struct x86_emulate_ctxt *ctxt)
-{
-	memset(&ctxt->opcode_len, 0,
-	       (void *)&ctxt->_regs - (void *)&ctxt->opcode_len);
-
-	ctxt->fetch.start = 0;
-	ctxt->fetch.end = 0;
-	ctxt->io_read.pos = 0;
-	ctxt->io_read.end = 0;
-	ctxt->mem_read.pos = 0;
-	ctxt->mem_read.end = 0;
-}
-
 static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 {
 	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
@@ -5085,23 +5116,22 @@ static int kvm_vcpu_check_hw_bp(unsigned
 	return dr6;
 }
 
-static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, int *r)
+static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r)
 {
 	struct kvm_run *kvm_run = vcpu->run;
 
 	/*
-	 * Use the "raw" value to see if TF was passed to the processor.
-	 * Note that the new value of the flags has not been saved yet.
+	 * rflags is the old, "raw" value of the flags.  The new value has
+	 * not been saved yet.
 	 *
 	 * This is correct even for TF set by the guest, because "the
 	 * processor will not generate this exception after the instruction
 	 * that sets the TF flag".
 	 */
-	unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
-
 	if (unlikely(rflags & X86_EFLAGS_TF)) {
 		if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
-			kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1;
+			kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 |
+						  DR6_RTM;
 			kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
 			kvm_run->debug.arch.exception = DB_VECTOR;
 			kvm_run->exit_reason = KVM_EXIT_DEBUG;
@@ -5114,7 +5144,7 @@ static void kvm_vcpu_check_singlestep(st
 			 * cleared by the processor".
 			 */
 			vcpu->arch.dr6 &= ~15;
-			vcpu->arch.dr6 |= DR6_BS;
+			vcpu->arch.dr6 |= DR6_BS | DR6_RTM;
 			kvm_queue_exception(vcpu, DB_VECTOR);
 		}
 	}
@@ -5133,7 +5163,7 @@ static bool kvm_vcpu_check_breakpoint(st
 					   vcpu->arch.eff_db);
 
 		if (dr6 != 0) {
-			kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+			kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM;
 			kvm_run->debug.arch.pc = kvm_rip_read(vcpu) +
 				get_segment_base(vcpu, VCPU_SREG_CS);
 
@@ -5144,14 +5174,15 @@ static bool kvm_vcpu_check_breakpoint(st
 		}
 	}
 
-	if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK)) {
+	if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK) &&
+	    !(kvm_get_rflags(vcpu) & X86_EFLAGS_RF)) {
 		dr6 = kvm_vcpu_check_hw_bp(eip, 0,
 					   vcpu->arch.dr7,
 					   vcpu->arch.db);
 
 		if (dr6 != 0) {
 			vcpu->arch.dr6 &= ~15;
-			vcpu->arch.dr6 |= dr6;
+			vcpu->arch.dr6 |= dr6 | DR6_RTM;
 			kvm_queue_exception(vcpu, DB_VECTOR);
 			*r = EMULATE_DONE;
 			return true;
@@ -5215,6 +5246,8 @@ int x86_emulate_instruction(struct kvm_v
 
 	if (emulation_type & EMULTYPE_SKIP) {
 		kvm_rip_write(vcpu, ctxt->_eip);
+		if (ctxt->eflags & X86_EFLAGS_RF)
+			kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
 		return EMULATE_DONE;
 	}
 
@@ -5265,13 +5298,22 @@ restart:
 		r = EMULATE_DONE;
 
 	if (writeback) {
+		unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
-		kvm_make_request(KVM_REQ_EVENT, vcpu);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 		kvm_rip_write(vcpu, ctxt->eip);
 		if (r == EMULATE_DONE)
-			kvm_vcpu_check_singlestep(vcpu, &r);
-		kvm_set_rflags(vcpu, ctxt->eflags);
+			kvm_vcpu_check_singlestep(vcpu, rflags, &r);
+		__kvm_set_rflags(vcpu, ctxt->eflags);
+
+		/*
+		 * For STI, interrupts are shadowed; so KVM_REQ_EVENT will
+		 * do nothing, and it will be requested again as soon as
+		 * the shadow expires.  But we still need to check here,
+		 * because POPF has no interrupt shadow.
+		 */
+		if (unlikely((ctxt->eflags & ~rflags) & X86_EFLAGS_IF))
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
 	} else
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
 
@@ -5662,7 +5704,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vc
 	u64 param, ingpa, outgpa, ret;
 	uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
 	bool fast, longmode;
-	int cs_db, cs_l;
 
 	/*
 	 * hypercall generates UD from non zero cpl and real mode
@@ -5673,8 +5714,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vc
 		return 0;
 	}
 
-	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
-	longmode = is_long_mode(vcpu) && cs_l == 1;
+	longmode = is_64_bit_mode(vcpu);
 
 	if (!longmode) {
 		param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
@@ -5739,7 +5779,7 @@ static void kvm_pv_kick_cpu_op(struct kv
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 {
 	unsigned long nr, a0, a1, a2, a3, ret;
-	int r = 1;
+	int op_64_bit, r = 1;
 
 	if (kvm_hv_hypercall_enabled(vcpu->kvm))
 		return kvm_hv_hypercall(vcpu);
@@ -5752,7 +5792,8 @@ int kvm_emulate_hypercall(struct kvm_vcp
 
 	trace_kvm_hypercall(nr, a0, a1, a2, a3);
 
-	if (!is_long_mode(vcpu)) {
+	op_64_bit = is_64_bit_mode(vcpu);
+	if (!op_64_bit) {
 		nr &= 0xFFFFFFFF;
 		a0 &= 0xFFFFFFFF;
 		a1 &= 0xFFFFFFFF;
@@ -5778,6 +5819,8 @@ int kvm_emulate_hypercall(struct kvm_vcp
 		break;
 	}
 out:
+	if (!op_64_bit)
+		ret = (u32)ret;
 	kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
 	++vcpu->stat.hypercalls;
 	return r;
@@ -5856,6 +5899,11 @@ static int inject_pending_event(struct k
 		trace_kvm_inj_exception(vcpu->arch.exception.nr,
 					vcpu->arch.exception.has_error_code,
 					vcpu->arch.exception.error_code);
+
+		if (exception_type(vcpu->arch.exception.nr) == EXCPT_FAULT)
+			__kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) |
+					     X86_EFLAGS_RF);
+
 		kvm_x86_ops->queue_exception(vcpu, vcpu->arch.exception.nr,
 					  vcpu->arch.exception.has_error_code,
 					  vcpu->arch.exception.error_code,
@@ -6847,9 +6895,11 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcp
 	atomic_set(&vcpu->arch.nmi_queued, 0);
 	vcpu->arch.nmi_pending = 0;
 	vcpu->arch.nmi_injected = false;
+	kvm_clear_interrupt_queue(vcpu);
+	kvm_clear_exception_queue(vcpu);
 
 	memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
-	vcpu->arch.dr6 = DR6_FIXED_1;
+	vcpu->arch.dr6 = DR6_INIT;
 	kvm_update_dr6(vcpu);
 	vcpu->arch.dr7 = DR7_FIXED_1;
 	kvm_update_dr7(vcpu);
@@ -7405,12 +7455,17 @@ unsigned long kvm_get_rflags(struct kvm_
 }
 EXPORT_SYMBOL_GPL(kvm_get_rflags);
 
-void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
 	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP &&
 	    kvm_is_linear_rip(vcpu, vcpu->arch.singlestep_rip))
 		rflags |= X86_EFLAGS_TF;
 	kvm_x86_ops->set_rflags(vcpu, rflags);
+}
+
+void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+	__kvm_set_rflags(vcpu, rflags);
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_set_rflags);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/kvm/x86.h linux-libre-3.17-rc7-gnu/arch/x86/kvm/x86.h
--- linux-libre-3.16-gnu/arch/x86/kvm/x86.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/kvm/x86.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,16 @@ static inline int is_long_mode(struct kv
 #endif
 }
 
+static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu)
+{
+	int cs_db, cs_l;
+
+	if (!is_long_mode(vcpu))
+		return false;
+	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+	return cs_l;
+}
+
 static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu;
@@ -108,6 +118,23 @@ static inline bool vcpu_match_mmio_gpa(s
 	return false;
 }
 
+static inline unsigned long kvm_register_readl(struct kvm_vcpu *vcpu,
+					       enum kvm_reg reg)
+{
+	unsigned long val = kvm_register_read(vcpu, reg);
+
+	return is_64_bit_mode(vcpu) ? val : (u32)val;
+}
+
+static inline void kvm_register_writel(struct kvm_vcpu *vcpu,
+				       enum kvm_reg reg,
+				       unsigned long val)
+{
+	if (!is_64_bit_mode(vcpu))
+		val = (u32)val;
+	return kvm_register_write(vcpu, reg, val);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/Makefile linux-libre-3.17-rc7-gnu/arch/x86/Makefile
--- linux-libre-3.16-gnu/arch/x86/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -15,12 +15,9 @@ endif
 # that way we can complain to the user if the CPU is insufficient.
 #
 # The -m16 option is supported by GCC >= 4.9 and clang >= 3.5. For
-# older versions of GCC, we need to play evil and unreliable tricks to
-# attempt to ensure that our asm(".code16gcc") is first in the asm
-# output.
-CODE16GCC_CFLAGS := -m32 -include $(srctree)/arch/x86/boot/code16gcc.h \
-		    $(call cc-option, -fno-toplevel-reorder,\
-		      $(call cc-option, -fno-unit-at-a-time))
+# older versions of GCC, include an *assembly* header to make sure that
+# gcc doesn't play any games behind our back.
+CODE16GCC_CFLAGS := -m32 -Wa,$(srctree)/arch/x86/boot/code16gcc.h
 M16_CFLAGS	 := $(call cc-option, -m16, $(CODE16GCC_CFLAGS))
 
 REALMODE_CFLAGS	:= $(M16_CFLAGS) -g -Os -D__KERNEL__ \
@@ -186,6 +183,11 @@ archscripts: scripts_basic
 archheaders:
 	$(Q)$(MAKE) $(build)=arch/x86/syscalls all
 
+archprepare:
+ifeq ($(CONFIG_KEXEC_FILE),y)
+	$(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
+endif
+
 ###
 # Kernel objects
 
@@ -249,6 +251,7 @@ archclean:
 	$(Q)rm -rf $(objtree)/arch/x86_64
 	$(Q)$(MAKE) $(clean)=$(boot)
 	$(Q)$(MAKE) $(clean)=arch/x86/tools
+	$(Q)$(MAKE) $(clean)=arch/x86/purgatory
 
 PHONY += kvmconfig
 kvmconfig:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/dump_pagetables.c linux-libre-3.17-rc7-gnu/arch/x86/mm/dump_pagetables.c
--- linux-libre-3.16-gnu/arch/x86/mm/dump_pagetables.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/dump_pagetables.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,9 @@ enum address_markers_idx {
 	LOW_KERNEL_NR,
 	VMALLOC_START_NR,
 	VMEMMAP_START_NR,
+# ifdef CONFIG_X86_ESPFIX64
 	ESPFIX_START_NR,
+# endif
 	HIGH_KERNEL_NR,
 	MODULES_VADDR_NR,
 	MODULES_END_NR,
@@ -71,7 +73,9 @@ static struct addr_marker address_marker
 	{ PAGE_OFFSET,		"Low Kernel Mapping" },
 	{ VMALLOC_START,        "vmalloc() Area" },
 	{ VMEMMAP_START,        "Vmemmap" },
+# ifdef CONFIG_X86_ESPFIX64
 	{ ESPFIX_BASE_ADDR,	"ESPfix Area", 16 },
+# endif
 	{ __START_KERNEL_map,   "High Kernel Mapping" },
 	{ MODULES_VADDR,        "Modules" },
 	{ MODULES_END,          "End Modules" },
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/fault.c linux-libre-3.17-rc7-gnu/arch/x86/mm/fault.c
--- linux-libre-3.16-gnu/arch/x86/mm/fault.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/fault.c	2014-09-28 17:29:07.000000000 -0400
@@ -577,6 +577,8 @@ static int is_f00f_bug(struct pt_regs *r
 
 static const char nx_warning[] = KERN_CRIT
 "kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
+static const char smep_warning[] = KERN_CRIT
+"unable to execute userspace code (SMEP?) (uid: %d)\n";
 
 static void
 show_fault_oops(struct pt_regs *regs, unsigned long error_code,
@@ -597,6 +599,10 @@ show_fault_oops(struct pt_regs *regs, un
 
 		if (pte && pte_present(*pte) && !pte_exec(*pte))
 			printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
+		if (pte && pte_present(*pte) && pte_exec(*pte) &&
+				(pgd_flags(*pgd) & _PAGE_USER) &&
+				(read_cr4() & X86_CR4_SMEP))
+			printk(smep_warning, from_kuid(&init_user_ns, current_uid()));
 	}
 
 	printk(KERN_ALERT "BUG: unable to handle kernel ");
@@ -1212,7 +1218,8 @@ good_area:
 	/*
 	 * If for any reason at all we couldn't handle the fault,
 	 * make sure we exit gracefully rather than endlessly redo
-	 * the fault:
+	 * the fault.  Since we never set FAULT_FLAG_RETRY_NOWAIT, if
+	 * we get VM_FAULT_RETRY back, the mmap_sem has been unlocked.
 	 */
 	fault = handle_mm_fault(mm, vma, address, flags);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/init_32.c linux-libre-3.17-rc7-gnu/arch/x86/mm/init_32.c
--- linux-libre-3.16-gnu/arch/x86/mm/init_32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/init_32.c	2014-09-28 17:29:07.000000000 -0400
@@ -825,7 +825,8 @@ void __init mem_init(void)
 int arch_add_memory(int nid, u64 start, u64 size)
 {
 	struct pglist_data *pgdata = NODE_DATA(nid);
-	struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
+	struct zone *zone = pgdata->node_zones +
+		zone_for_memory(nid, start, size, ZONE_HIGHMEM);
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/init_64.c linux-libre-3.17-rc7-gnu/arch/x86/mm/init_64.c
--- linux-libre-3.16-gnu/arch/x86/mm/init_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/init_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -691,7 +691,8 @@ static void  update_end_of_memory_vars(u
 int arch_add_memory(int nid, u64 start, u64 size)
 {
 	struct pglist_data *pgdat = NODE_DATA(nid);
-	struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+	struct zone *zone = pgdat->node_zones +
+		zone_for_memory(nid, start, size, ZONE_NORMAL);
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 	int ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/init.c linux-libre-3.17-rc7-gnu/arch/x86/mm/init.c
--- linux-libre-3.16-gnu/arch/x86/mm/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,13 @@
 #include <asm/dma.h>		/* for MAX_DMA_PFN */
 #include <asm/microcode.h>
 
+/*
+ * We need to define the tracepoints somewhere, and tlb.c
+ * is only compied when SMP=y.
+ */
+#define CREATE_TRACE_POINTS
+#include <trace/events/tlb.h>
+
 #include "mm_internal.h"
 
 static unsigned long __initdata pgt_buf_start;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/mmap.c linux-libre-3.17-rc7-gnu/arch/x86/mm/mmap.c
--- linux-libre-3.16-gnu/arch/x86/mm/mmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/mmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@
 #include <linux/sched.h>
 #include <asm/elf.h>
 
-struct __read_mostly va_alignment va_align = {
+struct va_alignment __read_mostly va_align = {
 	.flags = -1,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/mm/tlb.c linux-libre-3.17-rc7-gnu/arch/x86/mm/tlb.c
--- linux-libre-3.16-gnu/arch/x86/mm/tlb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/mm/tlb.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,6 +49,13 @@ void leave_mm(int cpu)
 	if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) {
 		cpumask_clear_cpu(cpu, mm_cpumask(active_mm));
 		load_cr3(swapper_pg_dir);
+		/*
+		 * This gets called in the idle path where RCU
+		 * functions differently.  Tracing normally
+		 * uses RCU, so we have to call the tracepoint
+		 * specially here.
+		 */
+		trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
 	}
 }
 EXPORT_SYMBOL_GPL(leave_mm);
@@ -102,20 +109,24 @@ static void flush_tlb_func(void *info)
 
 	if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
 		return;
+	if (!f->flush_end)
+		f->flush_end = f->flush_start + PAGE_SIZE;
 
 	count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
 	if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
-		if (f->flush_end == TLB_FLUSH_ALL)
+		if (f->flush_end == TLB_FLUSH_ALL) {
 			local_flush_tlb();
-		else if (!f->flush_end)
-			__flush_tlb_single(f->flush_start);
-		else {
+			trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, TLB_FLUSH_ALL);
+		} else {
 			unsigned long addr;
+			unsigned long nr_pages =
+				f->flush_end - f->flush_start / PAGE_SIZE;
 			addr = f->flush_start;
 			while (addr < f->flush_end) {
 				__flush_tlb_single(addr);
 				addr += PAGE_SIZE;
 			}
+			trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, nr_pages);
 		}
 	} else
 		leave_mm(smp_processor_id());
@@ -153,46 +164,45 @@ void flush_tlb_current_task(void)
 
 	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
 	local_flush_tlb();
+	trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
 	preempt_enable();
 }
 
+/*
+ * See Documentation/x86/tlb.txt for details.  We choose 33
+ * because it is large enough to cover the vast majority (at
+ * least 95%) of allocations, and is small enough that we are
+ * confident it will not cause too much overhead.  Each single
+ * flush is about 100 ns, so this caps the maximum overhead at
+ * _about_ 3,000 ns.
+ *
+ * This is in units of pages.
+ */
+static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
+
 void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 				unsigned long end, unsigned long vmflag)
 {
 	unsigned long addr;
-	unsigned act_entries, tlb_entries = 0;
-	unsigned long nr_base_pages;
+	/* do a global flush by default */
+	unsigned long base_pages_to_flush = TLB_FLUSH_ALL;
 
 	preempt_disable();
 	if (current->active_mm != mm)
-		goto flush_all;
+		goto out;
 
 	if (!current->mm) {
 		leave_mm(smp_processor_id());
-		goto flush_all;
-	}
-
-	if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
-					|| vmflag & VM_HUGETLB) {
-		local_flush_tlb();
-		goto flush_all;
+		goto out;
 	}
 
-	/* In modern CPU, last level tlb used for both data/ins */
-	if (vmflag & VM_EXEC)
-		tlb_entries = tlb_lli_4k[ENTRIES];
-	else
-		tlb_entries = tlb_lld_4k[ENTRIES];
-
-	/* Assume all of TLB entries was occupied by this task */
-	act_entries = tlb_entries >> tlb_flushall_shift;
-	act_entries = mm->total_vm > act_entries ? act_entries : mm->total_vm;
-	nr_base_pages = (end - start) >> PAGE_SHIFT;
+	if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB))
+		base_pages_to_flush = (end - start) >> PAGE_SHIFT;
 
-	/* tlb_flushall_shift is on balance point, details in commit log */
-	if (nr_base_pages > act_entries) {
+	if (base_pages_to_flush > tlb_single_page_flush_ceiling) {
+		base_pages_to_flush = TLB_FLUSH_ALL;
 		count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
 		local_flush_tlb();
 	} else {
@@ -201,17 +211,15 @@ void flush_tlb_mm_range(struct mm_struct
 			count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
 			__flush_tlb_single(addr);
 		}
-
-		if (cpumask_any_but(mm_cpumask(mm),
-				smp_processor_id()) < nr_cpu_ids)
-			flush_tlb_others(mm_cpumask(mm), mm, start, end);
-		preempt_enable();
-		return;
 	}
-
-flush_all:
+	trace_tlb_flush(TLB_LOCAL_MM_SHOOTDOWN, base_pages_to_flush);
+out:
+	if (base_pages_to_flush == TLB_FLUSH_ALL) {
+		start = 0UL;
+		end = TLB_FLUSH_ALL;
+	}
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
-		flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
+		flush_tlb_others(mm_cpumask(mm), mm, start, end);
 	preempt_enable();
 }
 
@@ -260,32 +268,26 @@ static void do_kernel_range_flush(void *
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
-	unsigned act_entries;
-	struct flush_tlb_info info;
-
-	/* In modern CPU, last level tlb used for both data/ins */
-	act_entries = tlb_lld_4k[ENTRIES];
 
 	/* Balance as user space task's flush, a bit conservative */
-	if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 ||
-		(end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift)
-
+	if (end == TLB_FLUSH_ALL ||
+	    (end - start) > tlb_single_page_flush_ceiling * PAGE_SIZE) {
 		on_each_cpu(do_flush_tlb_all, NULL, 1);
-	else {
+	} else {
+		struct flush_tlb_info info;
 		info.flush_start = start;
 		info.flush_end = end;
 		on_each_cpu(do_kernel_range_flush, &info, 1);
 	}
 }
 
-#ifdef CONFIG_DEBUG_TLBFLUSH
 static ssize_t tlbflush_read_file(struct file *file, char __user *user_buf,
 			     size_t count, loff_t *ppos)
 {
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%hd\n", tlb_flushall_shift);
+	len = sprintf(buf, "%ld\n", tlb_single_page_flush_ceiling);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -294,20 +296,20 @@ static ssize_t tlbflush_write_file(struc
 {
 	char buf[32];
 	ssize_t len;
-	s8 shift;
+	int ceiling;
 
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len))
 		return -EFAULT;
 
 	buf[len] = '\0';
-	if (kstrtos8(buf, 0, &shift))
+	if (kstrtoint(buf, 0, &ceiling))
 		return -EINVAL;
 
-	if (shift < -1 || shift >= BITS_PER_LONG)
+	if (ceiling < 0)
 		return -EINVAL;
 
-	tlb_flushall_shift = shift;
+	tlb_single_page_flush_ceiling = ceiling;
 	return count;
 }
 
@@ -317,11 +319,10 @@ static const struct file_operations fops
 	.llseek = default_llseek,
 };
 
-static int __init create_tlb_flushall_shift(void)
+static int __init create_tlb_single_page_flush_ceiling(void)
 {
-	debugfs_create_file("tlb_flushall_shift", S_IRUSR | S_IWUSR,
+	debugfs_create_file("tlb_single_page_flush_ceiling", S_IRUSR | S_IWUSR,
 			    arch_debugfs_dir, NULL, &fops_tlbflush);
 	return 0;
 }
-late_initcall(create_tlb_flushall_shift);
-#endif
+late_initcall(create_tlb_single_page_flush_ceiling);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-3.17-rc7-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-3.16-gnu/arch/x86/net/bpf_jit_comp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/net/bpf_jit_comp.c	2014-09-28 17:29:07.000000000 -0400
@@ -211,10 +211,10 @@ struct jit_context {
 	bool seen_ld_abs;
 };
 
-static int do_jit(struct sk_filter *bpf_prog, int *addrs, u8 *image,
+static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
 		  int oldproglen, struct jit_context *ctx)
 {
-	struct sock_filter_int *insn = bpf_prog->insnsi;
+	struct bpf_insn *insn = bpf_prog->insnsi;
 	int insn_cnt = bpf_prog->len;
 	u8 temp[64];
 	int i;
@@ -235,7 +235,7 @@ static int do_jit(struct sk_filter *bpf_
 	/* mov qword ptr [rbp-X],rbx */
 	EMIT3_off32(0x48, 0x89, 0x9D, -stacksize);
 
-	/* sk_convert_filter() maps classic BPF register X to R7 and uses R8
+	/* bpf_convert_filter() maps classic BPF register X to R7 and uses R8
 	 * as temporary, so all tcpdump filters need to spill/fill R7(r13) and
 	 * R8(r14). R9(r15) spill could be made conditional, but there is only
 	 * one 'bpf_error' return path out of helper functions inside bpf_jit.S
@@ -841,7 +841,7 @@ common_load:		ctx->seen_ld_abs = true;
 			/* By design x64 JIT should support all BPF instructions
 			 * This error will be seen if new instruction was added
 			 * to interpreter, but not to JIT
-			 * or if there is junk in sk_filter
+			 * or if there is junk in bpf_prog
 			 */
 			pr_err("bpf_jit: unknown opcode %02x\n", insn->code);
 			return -EINVAL;
@@ -862,11 +862,11 @@ common_load:		ctx->seen_ld_abs = true;
 	return proglen;
 }
 
-void bpf_jit_compile(struct sk_filter *prog)
+void bpf_jit_compile(struct bpf_prog *prog)
 {
 }
 
-void bpf_int_jit_compile(struct sk_filter *prog)
+void bpf_int_jit_compile(struct bpf_prog *prog)
 {
 	struct bpf_binary_header *header = NULL;
 	int proglen, oldproglen = 0;
@@ -932,7 +932,7 @@ out:
 
 static void bpf_jit_free_deferred(struct work_struct *work)
 {
-	struct sk_filter *fp = container_of(work, struct sk_filter, work);
+	struct bpf_prog *fp = container_of(work, struct bpf_prog, work);
 	unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
 	struct bpf_binary_header *header = (void *)addr;
 
@@ -941,7 +941,7 @@ static void bpf_jit_free_deferred(struct
 	kfree(fp);
 }
 
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited) {
 		INIT_WORK(&fp->work, bpf_jit_free_deferred);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/acpi.c linux-libre-3.17-rc7-gnu/arch/x86/pci/acpi.c
--- linux-libre-3.16-gnu/arch/x86/pci/acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -448,7 +448,7 @@ static void probe_pci_root_info(struct p
 		return;
 
 	size = sizeof(*info->res) * info->res_num;
-	info->res = kzalloc(size, GFP_KERNEL);
+	info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
 	if (!info->res) {
 		info->res_num = 0;
 		return;
@@ -456,7 +456,7 @@ static void probe_pci_root_info(struct p
 
 	size = sizeof(*info->res_offset) * info->res_num;
 	info->res_num = 0;
-	info->res_offset = kzalloc(size, GFP_KERNEL);
+	info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
 	if (!info->res_offset) {
 		kfree(info->res);
 		info->res = NULL;
@@ -499,7 +499,7 @@ struct pci_bus *pci_acpi_scan_root(struc
 	if (node != NUMA_NO_NODE && !node_online(node))
 		node = NUMA_NO_NODE;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
 	if (!info) {
 		printk(KERN_WARNING "pci_bus %04x:%02x: "
 		       "ignored (out of memory)\n", domain, busnum);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/fixup.c linux-libre-3.17-rc7-gnu/arch/x86/pci/fixup.c
--- linux-libre-3.16-gnu/arch/x86/pci/fixup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/fixup.c	2014-09-28 17:29:07.000000000 -0400
@@ -350,8 +350,7 @@ static void pci_fixup_video(struct pci_d
 		pci_read_config_word(pdev, PCI_COMMAND, &config);
 		if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 			pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-			dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
-			vga_set_default_device(pdev);
+			dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
 		}
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/i386.c linux-libre-3.17-rc7-gnu/arch/x86/pci/i386.c
--- linux-libre-3.16-gnu/arch/x86/pci/i386.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/i386.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,6 +162,10 @@ pcibios_align_resource(void *data, const
 			return start;
 		if (start & 0x300)
 			start = (start + 0x3ff) & ~0x3ff;
+	} else if (res->flags & IORESOURCE_MEM) {
+		/* The low 1MB range is reserved for ISA cards */
+		if (start < BIOS_END)
+			start = BIOS_END;
 	}
 	return start;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/intel_mid_pci.c linux-libre-3.17-rc7-gnu/arch/x86/pci/intel_mid_pci.c
--- linux-libre-3.16-gnu/arch/x86/pci/intel_mid_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/intel_mid_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,27 +208,31 @@ static int pci_write(struct pci_bus *bus
 
 static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
-	u8 pin;
-	struct io_apic_irq_attr irq_attr;
+	int polarity;
 
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
+		polarity = 0; /* active high */
+	else
+		polarity = 1; /* active low */
 
 	/*
 	 * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
 	 * IOAPIC RTE entries, so we just enable RTE for the device.
 	 */
-	irq_attr.ioapic = mp_find_ioapic(dev->irq);
-	irq_attr.ioapic_pin = dev->irq;
-	irq_attr.trigger = 1; /* level */
-	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
-		irq_attr.polarity = 0; /* active high */
-	else
-		irq_attr.polarity = 1; /* active low */
-	io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
+	if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
+		return -EBUSY;
+	if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+		return -EBUSY;
 
 	return 0;
 }
 
+static void intel_mid_pci_irq_disable(struct pci_dev *dev)
+{
+	if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
+		mp_unmap_irq(dev->irq);
+}
+
 struct pci_ops intel_mid_pci_ops = {
 	.read = pci_read,
 	.write = pci_write,
@@ -245,6 +249,7 @@ int __init intel_mid_pci_init(void)
 	pr_info("Intel MID platform detected, using MID PCI ops\n");
 	pci_mmcfg_late_init();
 	pcibios_enable_irq = intel_mid_pci_irq_enable;
+	pcibios_disable_irq = intel_mid_pci_irq_disable;
 	pci_root_ops = intel_mid_pci_ops;
 	pci_soc_mode = 1;
 	/* Continue with standard init */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/irq.c linux-libre-3.17-rc7-gnu/arch/x86/pci/irq.c
--- linux-libre-3.16-gnu/arch/x86/pci/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@ static int acer_tm360_irqrouting;
 static struct irq_routing_table *pirq_table;
 
 static int pirq_enable_irq(struct pci_dev *dev);
+static void pirq_disable_irq(struct pci_dev *dev);
 
 /*
  * Never use: 0, 1, 2 (timer, keyboard, and cascade)
@@ -53,7 +54,7 @@ struct irq_router_handler {
 };
 
 int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;
 
 /*
  *  Check passed address for the PCI IRQ Routing Table signature
@@ -1186,7 +1187,7 @@ void pcibios_penalize_isa_irq(int irq, i
 
 static int pirq_enable_irq(struct pci_dev *dev)
 {
-	u8 pin;
+	u8 pin = 0;
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1)) {
@@ -1227,8 +1228,6 @@ static int pirq_enable_irq(struct pci_de
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
-				io_apic_set_pci_routing(&dev->dev, irq,
-							 &irq_attr);
 				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
@@ -1254,3 +1253,12 @@ static int pirq_enable_irq(struct pci_de
 	}
 	return 0;
 }
+
+static void pirq_disable_irq(struct pci_dev *dev)
+{
+	if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
+	    dev->irq) {
+		mp_unmap_irq(dev->irq);
+		dev->irq = 0;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/pci/xen.c linux-libre-3.17-rc7-gnu/arch/x86/pci/xen.c
--- linux-libre-3.16-gnu/arch/x86/pci/xen.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/pci/xen.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@
 #include <xen/features.h>
 #include <xen/events.h>
 #include <asm/xen/pci.h>
+#include <asm/i8259.h>
 
 static int xen_pcifront_enable_irq(struct pci_dev *dev)
 {
@@ -40,7 +41,7 @@ static int xen_pcifront_enable_irq(struc
 	/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
 	pirq = gsi;
 
-	if (gsi < NR_IRQS_LEGACY)
+	if (gsi < nr_legacy_irqs())
 		share = 0;
 
 	rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
@@ -511,7 +512,7 @@ int __init pci_xen_initial_domain(void)
 	xen_setup_acpi_sci();
 	__acpi_register_gsi = acpi_register_gsi_xen;
 	/* Pre-allocate legacy irqs */
-	for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+	for (irq = 0; irq < nr_legacy_irqs(); irq++) {
 		int trigger, polarity;
 
 		if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
@@ -522,7 +523,7 @@ int __init pci_xen_initial_domain(void)
 			true /* Map GSI to PIRQ */);
 	}
 	if (0 == nr_ioapics) {
-		for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+		for (irq = 0; irq < nr_legacy_irqs(); irq++)
 			xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/ce4100/ce4100.c linux-libre-3.17-rc7-gnu/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-3.16-gnu/arch/x86/platform/ce4100/ce4100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/ce4100/ce4100.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,14 +135,10 @@ static void __init sdv_arch_setup(void)
 	sdv_serial_fixup();
 }
 
-#ifdef CONFIG_X86_IO_APIC
 static void sdv_pci_init(void)
 {
 	x86_of_pci_init();
-	/* We can't set this earlier, because we need to calibrate the timer */
-	legacy_pic = &null_legacy_pic;
 }
-#endif
 
 /*
  * CE4100 specific x86_init function overrides and early setup
@@ -155,7 +151,9 @@ void __init x86_ce4100_early_setup(void)
 	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;
+	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 	x86_init.pci.init = ce4100_pci_init;
+	x86_init.pci.init_irq = sdv_pci_init;
 
 	/*
 	 * By default, the reboot method is ACPI which is supported by the
@@ -166,10 +164,5 @@ void __init x86_ce4100_early_setup(void)
 	 */
 	reboot_type = BOOT_KBD;
 
-#ifdef CONFIG_X86_IO_APIC
-	x86_init.pci.init_irq = sdv_pci_init;
-	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
-#endif
-
 	pm_power_off = ce4100_power_off;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/efi/efi.c linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/efi.c
--- linux-libre-3.16-gnu/arch/x86/platform/efi/efi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,13 +56,6 @@
 
 #define EFI_DEBUG
 
-#define EFI_MIN_RESERVE 5120
-
-#define EFI_DUMMY_GUID \
-	EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
-
-static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
-
 struct efi_memory_map memmap;
 
 static struct efi efi_phys __initdata;
@@ -95,139 +88,6 @@ static int __init setup_add_efi_memmap(c
 }
 early_param("add_efi_memmap", setup_add_efi_memmap);
 
-static bool efi_no_storage_paranoia;
-
-static int __init setup_storage_paranoia(char *arg)
-{
-	efi_no_storage_paranoia = true;
-	return 0;
-}
-early_param("efi_no_storage_paranoia", setup_storage_paranoia);
-
-static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
-{
-	unsigned long flags;
-	efi_status_t status;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	status = efi_call_virt(get_time, tm, tc);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return status;
-}
-
-static efi_status_t virt_efi_set_time(efi_time_t *tm)
-{
-	unsigned long flags;
-	efi_status_t status;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	status = efi_call_virt(set_time, tm);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return status;
-}
-
-static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
-					     efi_bool_t *pending,
-					     efi_time_t *tm)
-{
-	unsigned long flags;
-	efi_status_t status;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return status;
-}
-
-static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
-{
-	unsigned long flags;
-	efi_status_t status;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	status = efi_call_virt(set_wakeup_time, enabled, tm);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return status;
-}
-
-static efi_status_t virt_efi_get_variable(efi_char16_t *name,
-					  efi_guid_t *vendor,
-					  u32 *attr,
-					  unsigned long *data_size,
-					  void *data)
-{
-	return efi_call_virt(get_variable,
-			     name, vendor, attr,
-			     data_size, data);
-}
-
-static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
-					       efi_char16_t *name,
-					       efi_guid_t *vendor)
-{
-	return efi_call_virt(get_next_variable,
-			     name_size, name, vendor);
-}
-
-static efi_status_t virt_efi_set_variable(efi_char16_t *name,
-					  efi_guid_t *vendor,
-					  u32 attr,
-					  unsigned long data_size,
-					  void *data)
-{
-	return efi_call_virt(set_variable,
-			     name, vendor, attr,
-			     data_size, data);
-}
-
-static efi_status_t virt_efi_query_variable_info(u32 attr,
-						 u64 *storage_space,
-						 u64 *remaining_space,
-						 u64 *max_variable_size)
-{
-	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
-		return EFI_UNSUPPORTED;
-
-	return efi_call_virt(query_variable_info, attr, storage_space,
-			     remaining_space, max_variable_size);
-}
-
-static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
-{
-	return efi_call_virt(get_next_high_mono_count, count);
-}
-
-static void virt_efi_reset_system(int reset_type,
-				  efi_status_t status,
-				  unsigned long data_size,
-				  efi_char16_t *data)
-{
-	__efi_call_virt(reset_system, reset_type, status,
-			data_size, data);
-}
-
-static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
-					    unsigned long count,
-					    unsigned long sg_list)
-{
-	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
-		return EFI_UNSUPPORTED;
-
-	return efi_call_virt(update_capsule, capsules, count, sg_list);
-}
-
-static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
-						unsigned long count,
-						u64 *max_size,
-						int *reset_type)
-{
-	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
-		return EFI_UNSUPPORTED;
-
-	return efi_call_virt(query_capsule_caps, capsules, count, max_size,
-			     reset_type);
-}
-
 static efi_status_t __init phys_efi_set_virtual_address_map(
 	unsigned long memory_map_size,
 	unsigned long descriptor_size,
@@ -244,42 +104,6 @@ static efi_status_t __init phys_efi_set_
 	return status;
 }
 
-int efi_set_rtc_mmss(const struct timespec *now)
-{
-	unsigned long nowtime = now->tv_sec;
-	efi_status_t	status;
-	efi_time_t	eft;
-	efi_time_cap_t	cap;
-	struct rtc_time	tm;
-
-	status = efi.get_time(&eft, &cap);
-	if (status != EFI_SUCCESS) {
-		pr_err("Oops: efitime: can't read time!\n");
-		return -1;
-	}
-
-	rtc_time_to_tm(nowtime, &tm);
-	if (!rtc_valid_tm(&tm)) {
-		eft.year = tm.tm_year + 1900;
-		eft.month = tm.tm_mon + 1;
-		eft.day = tm.tm_mday;
-		eft.minute = tm.tm_min;
-		eft.second = tm.tm_sec;
-		eft.nanosecond = 0;
-	} else {
-		pr_err("%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
-		       __func__, nowtime);
-		return -1;
-	}
-
-	status = efi.set_time(&eft);
-	if (status != EFI_SUCCESS) {
-		pr_err("Oops: efitime: can't write time!\n");
-		return -1;
-	}
-	return 0;
-}
-
 void efi_get_time(struct timespec *now)
 {
 	efi_status_t status;
@@ -350,6 +174,9 @@ int __init efi_memblock_x86_reserve_rang
 	struct efi_info *e = &boot_params.efi_info;
 	unsigned long pmap;
 
+	if (efi_enabled(EFI_PARAVIRT))
+		return 0;
+
 #ifdef CONFIG_X86_32
 	/* Can't handle data above 4GB at this time */
 	if (e->efi_memmap_hi) {
@@ -392,69 +219,15 @@ static void __init print_efi_memmap(void
 #endif  /*  EFI_DEBUG  */
 }
 
-void __init efi_reserve_boot_services(void)
-{
-	void *p;
-
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
-		u64 start = md->phys_addr;
-		u64 size = md->num_pages << EFI_PAGE_SHIFT;
-
-		if (md->type != EFI_BOOT_SERVICES_CODE &&
-		    md->type != EFI_BOOT_SERVICES_DATA)
-			continue;
-		/* Only reserve where possible:
-		 * - Not within any already allocated areas
-		 * - Not over any memory area (really needed, if above?)
-		 * - Not within any part of the kernel
-		 * - Not the bios reserved area
-		*/
-		if ((start + size > __pa_symbol(_text)
-				&& start <= __pa_symbol(_end)) ||
-			!e820_all_mapped(start, start+size, E820_RAM) ||
-			memblock_is_region_reserved(start, size)) {
-			/* Could not reserve, skip it */
-			md->num_pages = 0;
-			memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
-				     start, start+size-1);
-		} else
-			memblock_reserve(start, size);
-	}
-}
-
 void __init efi_unmap_memmap(void)
 {
 	clear_bit(EFI_MEMMAP, &efi.flags);
 	if (memmap.map) {
-		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
 		memmap.map = NULL;
 	}
 }
 
-void __init efi_free_boot_services(void)
-{
-	void *p;
-
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
-		unsigned long long start = md->phys_addr;
-		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
-
-		if (md->type != EFI_BOOT_SERVICES_CODE &&
-		    md->type != EFI_BOOT_SERVICES_DATA)
-			continue;
-
-		/* Could not reserve boot area */
-		if (!size)
-			continue;
-
-		free_bootmem_late(start, size);
-	}
-
-	efi_unmap_memmap();
-}
-
 static int __init efi_systab_init(void *phys)
 {
 	if (efi_enabled(EFI_64BIT)) {
@@ -467,12 +240,12 @@ static int __init efi_systab_init(void *
 			if (!data)
 				return -ENOMEM;
 		}
-		systab64 = early_ioremap((unsigned long)phys,
+		systab64 = early_memremap((unsigned long)phys,
 					 sizeof(*systab64));
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
-				early_iounmap(data, sizeof(*data));
+				early_memunmap(data, sizeof(*data));
 			return -ENOMEM;
 		}
 
@@ -504,9 +277,9 @@ static int __init efi_systab_init(void *
 					   systab64->tables;
 		tmp |= data ? data->tables : systab64->tables;
 
-		early_iounmap(systab64, sizeof(*systab64));
+		early_memunmap(systab64, sizeof(*systab64));
 		if (data)
-			early_iounmap(data, sizeof(*data));
+			early_memunmap(data, sizeof(*data));
 #ifdef CONFIG_X86_32
 		if (tmp >> 32) {
 			pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -516,7 +289,7 @@ static int __init efi_systab_init(void *
 	} else {
 		efi_system_table_32_t *systab32;
 
-		systab32 = early_ioremap((unsigned long)phys,
+		systab32 = early_memremap((unsigned long)phys,
 					 sizeof(*systab32));
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
@@ -537,7 +310,7 @@ static int __init efi_systab_init(void *
 		efi_systab.nr_tables = systab32->nr_tables;
 		efi_systab.tables = systab32->tables;
 
-		early_iounmap(systab32, sizeof(*systab32));
+		early_memunmap(systab32, sizeof(*systab32));
 	}
 
 	efi.systab = &efi_systab;
@@ -563,7 +336,7 @@ static int __init efi_runtime_init32(voi
 {
 	efi_runtime_services_32_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_32_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -578,7 +351,7 @@ static int __init efi_runtime_init32(voi
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_32_t));
 
 	return 0;
 }
@@ -587,7 +360,7 @@ static int __init efi_runtime_init64(voi
 {
 	efi_runtime_services_64_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_64_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -602,7 +375,7 @@ static int __init efi_runtime_init64(voi
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_64_t));
 
 	return 0;
 }
@@ -616,14 +389,24 @@ static int __init efi_runtime_init(void)
 	 * the runtime services table so that we can grab the physical
 	 * address of several of the EFI runtime functions, needed to
 	 * set the firmware into virtual mode.
+	 *
+	 * When EFI_PARAVIRT is in force then we could not map runtime
+	 * service memory region because we do not have direct access to it.
+	 * However, runtime services are available through proxy functions
+	 * (e.g. in case of Xen dom0 EFI implementation they call special
+	 * hypercall which executes relevant EFI functions) and that is why
+	 * they are always enabled.
 	 */
-	if (efi_enabled(EFI_64BIT))
-		rv = efi_runtime_init64();
-	else
-		rv = efi_runtime_init32();
 
-	if (rv)
-		return rv;
+	if (!efi_enabled(EFI_PARAVIRT)) {
+		if (efi_enabled(EFI_64BIT))
+			rv = efi_runtime_init64();
+		else
+			rv = efi_runtime_init32();
+
+		if (rv)
+			return rv;
+	}
 
 	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 
@@ -632,8 +415,11 @@ static int __init efi_runtime_init(void)
 
 static int __init efi_memmap_init(void)
 {
+	if (efi_enabled(EFI_PARAVIRT))
+		return 0;
+
 	/* Map the EFI memory map */
-	memmap.map = early_ioremap((unsigned long)memmap.phys_map,
+	memmap.map = early_memremap((unsigned long)memmap.phys_map,
 				   memmap.nr_map * memmap.desc_size);
 	if (memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
@@ -649,62 +435,6 @@ static int __init efi_memmap_init(void)
 	return 0;
 }
 
-/*
- * A number of config table entries get remapped to virtual addresses
- * after entering EFI virtual mode. However, the kexec kernel requires
- * their physical addresses therefore we pass them via setup_data and
- * correct those entries to their respective physical addresses here.
- *
- * Currently only handles smbios which is necessary for some firmware
- * implementation.
- */
-static int __init efi_reuse_config(u64 tables, int nr_tables)
-{
-	int i, sz, ret = 0;
-	void *p, *tablep;
-	struct efi_setup_data *data;
-
-	if (!efi_setup)
-		return 0;
-
-	if (!efi_enabled(EFI_64BIT))
-		return 0;
-
-	data = early_memremap(efi_setup, sizeof(*data));
-	if (!data) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (!data->smbios)
-		goto out_memremap;
-
-	sz = sizeof(efi_config_table_64_t);
-
-	p = tablep = early_memremap(tables, nr_tables * sz);
-	if (!p) {
-		pr_err("Could not map Configuration table!\n");
-		ret = -ENOMEM;
-		goto out_memremap;
-	}
-
-	for (i = 0; i < efi.systab->nr_tables; i++) {
-		efi_guid_t guid;
-
-		guid = ((efi_config_table_64_t *)p)->guid;
-
-		if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
-			((efi_config_table_64_t *)p)->table = data->smbios;
-		p += sz;
-	}
-	early_iounmap(tablep, nr_tables * sz);
-
-out_memremap:
-	early_iounmap(data, sizeof(*data));
-out:
-	return ret;
-}
-
 void __init efi_init(void)
 {
 	efi_char16_t *c16;
@@ -728,8 +458,6 @@ void __init efi_init(void)
 	if (efi_systab_init(efi_phys.systab))
 		return;
 
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
 	efi.config_table = (unsigned long)efi.systab->tables;
 	efi.fw_vendor	 = (unsigned long)efi.systab->fw_vendor;
 	efi.runtime	 = (unsigned long)efi.systab->runtime;
@@ -737,14 +465,14 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
 		vendor[i] = '\0';
 	} else
 		pr_err("Could not map the firmware vendor!\n");
-	early_iounmap(tmp, 2);
+	early_memunmap(tmp, 2);
 
 	pr_info("EFI v%u.%.02u by %s\n",
 		efi.systab->hdr.revision >> 16,
@@ -770,8 +498,6 @@ void __init efi_init(void)
 	if (efi_memmap_init())
 		return;
 
-	set_bit(EFI_MEMMAP, &efi.flags);
-
 	print_efi_memmap();
 }
 
@@ -847,22 +573,6 @@ void __init old_map_region(efi_memory_de
 		       (unsigned long long)md->phys_addr);
 }
 
-static void native_runtime_setup(void)
-{
-	efi.get_time = virt_efi_get_time;
-	efi.set_time = virt_efi_set_time;
-	efi.get_wakeup_time = virt_efi_get_wakeup_time;
-	efi.set_wakeup_time = virt_efi_set_wakeup_time;
-	efi.get_variable = virt_efi_get_variable;
-	efi.get_next_variable = virt_efi_get_next_variable;
-	efi.set_variable = virt_efi_set_variable;
-	efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
-	efi.reset_system = virt_efi_reset_system;
-	efi.query_variable_info = virt_efi_query_variable_info;
-	efi.update_capsule = virt_efi_update_capsule;
-	efi.query_capsule_caps = virt_efi_query_capsule_caps;
-}
-
 /* Merge contiguous regions of the same type and attribute */
 static void __init efi_merge_regions(void)
 {
@@ -1049,7 +759,7 @@ static void __init kexec_enter_virtual_m
 	 */
 	efi.runtime_version = efi_systab.hdr.revision;
 
-	native_runtime_setup();
+	efi_native_runtime_setup();
 
 	efi.set_virtual_address_map = NULL;
 
@@ -1057,11 +767,7 @@ static void __init kexec_enter_virtual_m
 		runtime_code_page_mkexec();
 
 	/* clean DUMMY object */
-	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-			 EFI_VARIABLE_NON_VOLATILE |
-			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
-			 EFI_VARIABLE_RUNTIME_ACCESS,
-			 0, NULL);
+	efi_delete_dummy_variable();
 #endif
 }
 
@@ -1142,7 +848,7 @@ static void __init __efi_enter_virtual_m
 	efi.runtime_version = efi_systab.hdr.revision;
 
 	if (efi_is_native())
-		native_runtime_setup();
+		efi_native_runtime_setup();
 	else
 		efi_thunk_runtime_setup();
 
@@ -1179,15 +885,14 @@ static void __init __efi_enter_virtual_m
 	free_pages((unsigned long)new_memmap, pg_shift);
 
 	/* clean DUMMY object */
-	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-			 EFI_VARIABLE_NON_VOLATILE |
-			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
-			 EFI_VARIABLE_RUNTIME_ACCESS,
-			 0, NULL);
+	efi_delete_dummy_variable();
 }
 
 void __init efi_enter_virtual_mode(void)
 {
+	if (efi_enabled(EFI_PARAVIRT))
+		return;
+
 	if (efi_setup)
 		kexec_enter_virtual_mode();
 	else
@@ -1220,6 +925,9 @@ u64 efi_mem_attributes(unsigned long phy
 	efi_memory_desc_t *md;
 	void *p;
 
+	if (!efi_enabled(EFI_MEMMAP))
+		return 0;
+
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 		md = p;
 		if ((md->phys_addr <= phys_addr) &&
@@ -1230,86 +938,6 @@ u64 efi_mem_attributes(unsigned long phy
 	return 0;
 }
 
-/*
- * Some firmware implementations refuse to boot if there's insufficient space
- * in the variable store. Ensure that we never use more than a safe limit.
- *
- * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
- * store.
- */
-efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
-{
-	efi_status_t status;
-	u64 storage_size, remaining_size, max_size;
-
-	if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
-		return 0;
-
-	status = efi.query_variable_info(attributes, &storage_size,
-					 &remaining_size, &max_size);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	/*
-	 * We account for that by refusing the write if permitting it would
-	 * reduce the available space to under 5KB. This figure was provided by
-	 * Samsung, so should be safe.
-	 */
-	if ((remaining_size - size < EFI_MIN_RESERVE) &&
-		!efi_no_storage_paranoia) {
-
-		/*
-		 * Triggering garbage collection may require that the firmware
-		 * generate a real EFI_OUT_OF_RESOURCES error. We can force
-		 * that by attempting to use more space than is available.
-		 */
-		unsigned long dummy_size = remaining_size + 1024;
-		void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
-
-		if (!dummy)
-			return EFI_OUT_OF_RESOURCES;
-
-		status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-					  EFI_VARIABLE_NON_VOLATILE |
-					  EFI_VARIABLE_BOOTSERVICE_ACCESS |
-					  EFI_VARIABLE_RUNTIME_ACCESS,
-					  dummy_size, dummy);
-
-		if (status == EFI_SUCCESS) {
-			/*
-			 * This should have failed, so if it didn't make sure
-			 * that we delete it...
-			 */
-			efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-					 EFI_VARIABLE_NON_VOLATILE |
-					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
-					 EFI_VARIABLE_RUNTIME_ACCESS,
-					 0, dummy);
-		}
-
-		kfree(dummy);
-
-		/*
-		 * The runtime code may now have triggered a garbage collection
-		 * run, so check the variable info again
-		 */
-		status = efi.query_variable_info(attributes, &storage_size,
-						 &remaining_size, &max_size);
-
-		if (status != EFI_SUCCESS)
-			return status;
-
-		/*
-		 * There still isn't enough room, so return an error
-		 */
-		if (remaining_size - size < EFI_MIN_RESERVE)
-			return EFI_OUT_OF_RESOURCES;
-	}
-
-	return EFI_SUCCESS;
-}
-EXPORT_SYMBOL_GPL(efi_query_variable_store);
-
 static int __init parse_efi_cmdline(char *str)
 {
 	if (*str == '=')
@@ -1321,22 +949,3 @@ static int __init parse_efi_cmdline(char
 	return 0;
 }
 early_param("efi", parse_efi_cmdline);
-
-void __init efi_apply_memmap_quirks(void)
-{
-	/*
-	 * Once setup is done earlier, unmap the EFI memory map on mismatched
-	 * firmware/kernel architectures since there is no support for runtime
-	 * services.
-	 */
-	if (!efi_runtime_supported()) {
-		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
-		efi_unmap_memmap();
-	}
-
-	/*
-	 * UV doesn't support the new EFI pagetable mapping yet.
-	 */
-	if (is_uv_system())
-		set_bit(EFI_OLD_MEMMAP, &efi.flags);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/efi/Makefile linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/Makefile
--- linux-libre-3.16-gnu/arch/x86/platform/efi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,4 @@
-obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
+obj-$(CONFIG_EFI) 		+= quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
 obj-$(CONFIG_EARLY_PRINTK_EFI)	+= early_printk.o
 obj-$(CONFIG_EFI_MIXED)		+= efi_thunk_$(BITS).o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/efi/quirks.c linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/quirks.c
--- linux-libre-3.16-gnu/arch/x86/platform/efi/quirks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/efi/quirks.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,290 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/acpi.h>
+#include <asm/efi.h>
+#include <asm/uv/uv.h>
+
+#define EFI_MIN_RESERVE 5120
+
+#define EFI_DUMMY_GUID \
+	EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
+
+static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
+
+static bool efi_no_storage_paranoia;
+
+/*
+ * Some firmware implementations refuse to boot if there's insufficient
+ * space in the variable store. The implementation of garbage collection
+ * in some FW versions causes stale (deleted) variables to take up space
+ * longer than intended and space is only freed once the store becomes
+ * almost completely full.
+ *
+ * Enabling this option disables the space checks in
+ * efi_query_variable_store() and forces garbage collection.
+ *
+ * Only enable this option if deleting EFI variables does not free up
+ * space in your variable store, e.g. if despite deleting variables
+ * you're unable to create new ones.
+ */
+static int __init setup_storage_paranoia(char *arg)
+{
+	efi_no_storage_paranoia = true;
+	return 0;
+}
+early_param("efi_no_storage_paranoia", setup_storage_paranoia);
+
+/*
+ * Deleting the dummy variable which kicks off garbage collection
+*/
+void efi_delete_dummy_variable(void)
+{
+	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+			 EFI_VARIABLE_NON_VOLATILE |
+			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
+			 EFI_VARIABLE_RUNTIME_ACCESS,
+			 0, NULL);
+}
+
+/*
+ * Some firmware implementations refuse to boot if there's insufficient space
+ * in the variable store. Ensure that we never use more than a safe limit.
+ *
+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
+ * store.
+ */
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+	efi_status_t status;
+	u64 storage_size, remaining_size, max_size;
+
+	if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
+		return 0;
+
+	status = efi.query_variable_info(attributes, &storage_size,
+					 &remaining_size, &max_size);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	/*
+	 * We account for that by refusing the write if permitting it would
+	 * reduce the available space to under 5KB. This figure was provided by
+	 * Samsung, so should be safe.
+	 */
+	if ((remaining_size - size < EFI_MIN_RESERVE) &&
+		!efi_no_storage_paranoia) {
+
+		/*
+		 * Triggering garbage collection may require that the firmware
+		 * generate a real EFI_OUT_OF_RESOURCES error. We can force
+		 * that by attempting to use more space than is available.
+		 */
+		unsigned long dummy_size = remaining_size + 1024;
+		void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
+
+		if (!dummy)
+			return EFI_OUT_OF_RESOURCES;
+
+		status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+					  EFI_VARIABLE_NON_VOLATILE |
+					  EFI_VARIABLE_BOOTSERVICE_ACCESS |
+					  EFI_VARIABLE_RUNTIME_ACCESS,
+					  dummy_size, dummy);
+
+		if (status == EFI_SUCCESS) {
+			/*
+			 * This should have failed, so if it didn't make sure
+			 * that we delete it...
+			 */
+			efi_delete_dummy_variable();
+		}
+
+		kfree(dummy);
+
+		/*
+		 * The runtime code may now have triggered a garbage collection
+		 * run, so check the variable info again
+		 */
+		status = efi.query_variable_info(attributes, &storage_size,
+						 &remaining_size, &max_size);
+
+		if (status != EFI_SUCCESS)
+			return status;
+
+		/*
+		 * There still isn't enough room, so return an error
+		 */
+		if (remaining_size - size < EFI_MIN_RESERVE)
+			return EFI_OUT_OF_RESOURCES;
+	}
+
+	return EFI_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(efi_query_variable_store);
+
+/*
+ * The UEFI specification makes it clear that the operating system is free to do
+ * whatever it wants with boot services code after ExitBootServices() has been
+ * called. Ignoring this recommendation a significant bunch of EFI implementations 
+ * continue calling into boot services code (SetVirtualAddressMap). In order to 
+ * work around such buggy implementations we reserve boot services region during 
+ * EFI init and make sure it stays executable. Then, after SetVirtualAddressMap(), it
+* is discarded.
+*/
+void __init efi_reserve_boot_services(void)
+{
+	void *p;
+
+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+		efi_memory_desc_t *md = p;
+		u64 start = md->phys_addr;
+		u64 size = md->num_pages << EFI_PAGE_SHIFT;
+
+		if (md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA)
+			continue;
+		/* Only reserve where possible:
+		 * - Not within any already allocated areas
+		 * - Not over any memory area (really needed, if above?)
+		 * - Not within any part of the kernel
+		 * - Not the bios reserved area
+		*/
+		if ((start + size > __pa_symbol(_text)
+				&& start <= __pa_symbol(_end)) ||
+			!e820_all_mapped(start, start+size, E820_RAM) ||
+			memblock_is_region_reserved(start, size)) {
+			/* Could not reserve, skip it */
+			md->num_pages = 0;
+			memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
+				     start, start+size-1);
+		} else
+			memblock_reserve(start, size);
+	}
+}
+
+void __init efi_free_boot_services(void)
+{
+	void *p;
+
+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+		efi_memory_desc_t *md = p;
+		unsigned long long start = md->phys_addr;
+		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+
+		if (md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA)
+			continue;
+
+		/* Could not reserve boot area */
+		if (!size)
+			continue;
+
+		free_bootmem_late(start, size);
+	}
+
+	efi_unmap_memmap();
+}
+
+/*
+ * A number of config table entries get remapped to virtual addresses
+ * after entering EFI virtual mode. However, the kexec kernel requires
+ * their physical addresses therefore we pass them via setup_data and
+ * correct those entries to their respective physical addresses here.
+ *
+ * Currently only handles smbios which is necessary for some firmware
+ * implementation.
+ */
+int __init efi_reuse_config(u64 tables, int nr_tables)
+{
+	int i, sz, ret = 0;
+	void *p, *tablep;
+	struct efi_setup_data *data;
+
+	if (!efi_setup)
+		return 0;
+
+	if (!efi_enabled(EFI_64BIT))
+		return 0;
+
+	data = early_memremap(efi_setup, sizeof(*data));
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (!data->smbios)
+		goto out_memremap;
+
+	sz = sizeof(efi_config_table_64_t);
+
+	p = tablep = early_memremap(tables, nr_tables * sz);
+	if (!p) {
+		pr_err("Could not map Configuration table!\n");
+		ret = -ENOMEM;
+		goto out_memremap;
+	}
+
+	for (i = 0; i < efi.systab->nr_tables; i++) {
+		efi_guid_t guid;
+
+		guid = ((efi_config_table_64_t *)p)->guid;
+
+		if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
+			((efi_config_table_64_t *)p)->table = data->smbios;
+		p += sz;
+	}
+	early_memunmap(tablep, nr_tables * sz);
+
+out_memremap:
+	early_memunmap(data, sizeof(*data));
+out:
+	return ret;
+}
+
+void __init efi_apply_memmap_quirks(void)
+{
+	/*
+	 * Once setup is done earlier, unmap the EFI memory map on mismatched
+	 * firmware/kernel architectures since there is no support for runtime
+	 * services.
+	 */
+	if (!efi_runtime_supported()) {
+		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+		efi_unmap_memmap();
+	}
+
+	/*
+	 * UV doesn't support the new EFI pagetable mapping yet.
+	 */
+	if (is_uv_system())
+		set_bit(EFI_OLD_MEMMAP, &efi.flags);
+}
+
+/*
+ * For most modern platforms the preferred method of powering off is via
+ * ACPI. However, there are some that are known to require the use of
+ * EFI runtime services and for which ACPI does not work at all.
+ *
+ * Using EFI is a last resort, to be used only if no other option
+ * exists.
+ */
+bool efi_reboot_required(void)
+{
+	if (!acpi_gbl_reduced_hardware)
+		return false;
+
+	efi_reboot_quirk_mode = EFI_RESET_WARM;
+	return true;
+}
+
+bool efi_poweroff_required(void)
+{
+	return !!acpi_gbl_reduced_hardware;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/intel-mid/device_libs/platform_wdt.c linux-libre-3.17-rc7-gnu/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
--- linux-libre-3.16-gnu/arch/x86/platform/intel-mid/device_libs/platform_wdt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/intel-mid/device_libs/platform_wdt.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,28 +26,18 @@ static struct platform_device wdt_dev =
 
 static int tangier_probe(struct platform_device *pdev)
 {
-	int ioapic;
-	int irq;
+	int gsi;
 	struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
-	struct io_apic_irq_attr irq_attr = { 0 };
 
 	if (!pdata)
 		return -EINVAL;
 
-	irq = pdata->irq;
-	ioapic = mp_find_ioapic(irq);
-	if (ioapic >= 0) {
-		int ret;
-		irq_attr.ioapic = ioapic;
-		irq_attr.ioapic_pin = irq;
-		irq_attr.trigger = 1;
-		/* irq_attr.polarity = 0; -> Active high */
-		ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
-		if (ret)
-			return ret;
-	} else {
+	/* IOAPIC builds identity mapping between GSI and IRQ on MID */
+	gsi = pdata->irq;
+	if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
+	    mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
 		dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
-			 irq);
+			 gsi);
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/intel-mid/sfi.c linux-libre-3.17-rc7-gnu/arch/x86/platform/intel-mid/sfi.c
--- linux-libre-3.16-gnu/arch/x86/platform/intel-mid/sfi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/intel-mid/sfi.c	2014-09-28 17:29:07.000000000 -0400
@@ -432,9 +432,8 @@ static int __init sfi_parse_devs(struct
 	struct sfi_table_simple *sb;
 	struct sfi_device_table_entry *pentry;
 	struct devs_id *dev = NULL;
-	int num, i;
-	int ioapic;
-	struct io_apic_irq_attr irq_attr;
+	int num, i, ret;
+	int polarity;
 
 	sb = (struct sfi_table_simple *)table;
 	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -448,35 +447,30 @@ static int __init sfi_parse_devs(struct
 			 * devices, but they have separate RTE entry in IOAPIC
 			 * so we have to enable them one by one here
 			 */
-			ioapic = mp_find_ioapic(irq);
-			if (ioapic >= 0) {
-				irq_attr.ioapic = ioapic;
-				irq_attr.ioapic_pin = irq;
-				irq_attr.trigger = 1;
-				if (intel_mid_identify_cpu() ==
-						INTEL_MID_CPU_CHIP_TANGIER) {
-					if (!strncmp(pentry->name,
-							"r69001-ts-i2c", 13))
-						/* active low */
-						irq_attr.polarity = 1;
-					else if (!strncmp(pentry->name,
-							"synaptics_3202", 14))
-						/* active low */
-						irq_attr.polarity = 1;
-					else if (irq == 41)
-						/* fast_int_1 */
-						irq_attr.polarity = 1;
-					else
-						/* active high */
-						irq_attr.polarity = 0;
-				} else {
-					/* PNW and CLV go with active low */
-					irq_attr.polarity = 1;
-				}
-				io_apic_set_pci_routing(NULL, irq, &irq_attr);
+			if (intel_mid_identify_cpu() ==
+					INTEL_MID_CPU_CHIP_TANGIER) {
+				if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
+					/* active low */
+					polarity = 1;
+				else if (!strncmp(pentry->name,
+						"synaptics_3202", 14))
+					/* active low */
+					polarity = 1;
+				else if (irq == 41)
+					/* fast_int_1 */
+					polarity = 1;
+				else
+					/* active high */
+					polarity = 0;
+			} else {
+				/* PNW and CLV go with active low */
+				polarity = 1;
 			}
-		} else {
-			irq = 0; /* No irq */
+
+			ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
+			if (ret == 0)
+				ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+			WARN_ON(ret < 0);
 		}
 
 		dev = get_device_id(pentry->type, pentry->name);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/sfi/sfi.c linux-libre-3.17-rc7-gnu/arch/x86/platform/sfi/sfi.c
--- linux-libre-3.16-gnu/arch/x86/platform/sfi/sfi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/sfi/sfi.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/io_apic.h>
 #include <asm/mpspec.h>
@@ -70,19 +71,26 @@ static int __init sfi_parse_cpus(struct
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_IO_APIC
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
+	.map = mp_irqdomain_map,
+};
 
 static int __init sfi_parse_ioapic(struct sfi_table_header *table)
 {
 	struct sfi_table_simple *sb;
 	struct sfi_apic_table_entry *pentry;
 	int i, num;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_STRICT,
+		.ops = &sfi_ioapic_irqdomain_ops,
+	};
 
 	sb = (struct sfi_table_simple *)table;
 	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
 	pentry = (struct sfi_apic_table_entry *)sb->pentry;
 
 	for (i = 0; i < num; i++) {
-		mp_register_ioapic(i, pentry->phys_addr, gsi_top);
+		mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
 		pentry++;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/ts5500/ts5500.c linux-libre-3.17-rc7-gnu/arch/x86/platform/ts5500/ts5500.c
--- linux-libre-3.16-gnu/arch/x86/platform/ts5500/ts5500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/ts5500/ts5500.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Technologic Systems TS-5500 Single Board Computer support
  *
- * Copyright (C) 2013 Savoir-faire Linux Inc.
+ * Copyright (C) 2013-2014 Savoir-faire Linux Inc.
  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  *
  * This program is free software; you can redistribute it and/or modify it under
@@ -15,8 +15,8 @@
  * state or available options. For further information about sysfs entries, see
  * Documentation/ABI/testing/sysfs-platform-ts5500.
  *
- * This code actually supports the TS-5500 platform, but it may be extended to
- * support similar Technologic Systems x86-based platforms, such as the TS-5600.
+ * This code may be extended to support similar x86-based platforms.
+ * Actually, the TS-5500 and TS-5400 are supported.
  */
 
 #include <linux/delay.h>
@@ -32,6 +32,7 @@
 /* Product code register */
 #define TS5500_PRODUCT_CODE_ADDR	0x74
 #define TS5500_PRODUCT_CODE		0x60	/* TS-5500 product code */
+#define TS5400_PRODUCT_CODE		0x40	/* TS-5400 product code */
 
 /* SRAM/RS-485/ADC options, and RS-485 RTS/Automatic RS-485 flags register */
 #define TS5500_SRAM_RS485_ADC_ADDR	0x75
@@ -66,6 +67,7 @@
 
 /**
  * struct ts5500_sbc - TS-5500 board description
+ * @name:	Board model name.
  * @id:		Board product ID.
  * @sram:	Flag for SRAM option.
  * @rs485:	Flag for RS-485 option.
@@ -75,6 +77,7 @@
  * @jumpers:	Bitfield for jumpers' state.
  */
 struct ts5500_sbc {
+	const char *name;
 	int	id;
 	bool	sram;
 	bool	rs485;
@@ -122,13 +125,16 @@ static int __init ts5500_detect_config(s
 	if (!request_region(TS5500_PRODUCT_CODE_ADDR, 4, "ts5500"))
 		return -EBUSY;
 
-	tmp = inb(TS5500_PRODUCT_CODE_ADDR);
-	if (tmp != TS5500_PRODUCT_CODE) {
-		pr_err("This platform is not a TS-5500 (found ID 0x%x)\n", tmp);
+	sbc->id = inb(TS5500_PRODUCT_CODE_ADDR);
+	if (sbc->id == TS5500_PRODUCT_CODE) {
+		sbc->name = "TS-5500";
+	} else if (sbc->id == TS5400_PRODUCT_CODE) {
+		sbc->name = "TS-5400";
+	} else {
+		pr_err("ts5500: unknown product code 0x%x\n", sbc->id);
 		ret = -ENODEV;
 		goto cleanup;
 	}
-	sbc->id = tmp;
 
 	tmp = inb(TS5500_SRAM_RS485_ADC_ADDR);
 	sbc->sram = tmp & TS5500_SRAM;
@@ -147,48 +153,52 @@ cleanup:
 	return ret;
 }
 
-static ssize_t ts5500_show_id(struct device *dev,
-			      struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct ts5500_sbc *sbc = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", sbc->name);
+}
+static DEVICE_ATTR_RO(name);
+
+static ssize_t id_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct ts5500_sbc *sbc = dev_get_drvdata(dev);
 
 	return sprintf(buf, "0x%.2x\n", sbc->id);
 }
+static DEVICE_ATTR_RO(id);
 
-static ssize_t ts5500_show_jumpers(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf)
+static ssize_t jumpers_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct ts5500_sbc *sbc = dev_get_drvdata(dev);
 
 	return sprintf(buf, "0x%.2x\n", sbc->jumpers >> 1);
 }
+static DEVICE_ATTR_RO(jumpers);
 
-#define TS5500_SHOW(field)					\
-	static ssize_t ts5500_show_##field(struct device *dev,	\
-			struct device_attribute *attr,		\
-			char *buf)				\
-	{							\
-		struct ts5500_sbc *sbc = dev_get_drvdata(dev);	\
-		return sprintf(buf, "%d\n", sbc->field);	\
-	}
-
-TS5500_SHOW(sram)
-TS5500_SHOW(rs485)
-TS5500_SHOW(adc)
-TS5500_SHOW(ereset)
-TS5500_SHOW(itr)
+#define TS5500_ATTR_BOOL(_field)					\
+	static ssize_t _field##_show(struct device *dev,		\
+			struct device_attribute *attr, char *buf)	\
+	{								\
+		struct ts5500_sbc *sbc = dev_get_drvdata(dev);		\
+									\
+		return sprintf(buf, "%d\n", sbc->_field);		\
+	}								\
+	static DEVICE_ATTR_RO(_field)
 
-static DEVICE_ATTR(id, S_IRUGO, ts5500_show_id, NULL);
-static DEVICE_ATTR(jumpers, S_IRUGO, ts5500_show_jumpers, NULL);
-static DEVICE_ATTR(sram, S_IRUGO, ts5500_show_sram, NULL);
-static DEVICE_ATTR(rs485, S_IRUGO, ts5500_show_rs485, NULL);
-static DEVICE_ATTR(adc, S_IRUGO, ts5500_show_adc, NULL);
-static DEVICE_ATTR(ereset, S_IRUGO, ts5500_show_ereset, NULL);
-static DEVICE_ATTR(itr, S_IRUGO, ts5500_show_itr, NULL);
+TS5500_ATTR_BOOL(sram);
+TS5500_ATTR_BOOL(rs485);
+TS5500_ATTR_BOOL(adc);
+TS5500_ATTR_BOOL(ereset);
+TS5500_ATTR_BOOL(itr);
 
 static struct attribute *ts5500_attributes[] = {
 	&dev_attr_id.attr,
+	&dev_attr_name.attr,
 	&dev_attr_jumpers.attr,
 	&dev_attr_sram.attr,
 	&dev_attr_rs485.attr,
@@ -311,12 +321,14 @@ static int __init ts5500_init(void)
 	if (err)
 		goto error;
 
-	ts5500_dio1_pdev.dev.parent = &pdev->dev;
-	if (platform_device_register(&ts5500_dio1_pdev))
-		dev_warn(&pdev->dev, "DIO1 block registration failed\n");
-	ts5500_dio2_pdev.dev.parent = &pdev->dev;
-	if (platform_device_register(&ts5500_dio2_pdev))
-		dev_warn(&pdev->dev, "DIO2 block registration failed\n");
+	if (sbc->id == TS5500_PRODUCT_CODE) {
+		ts5500_dio1_pdev.dev.parent = &pdev->dev;
+		if (platform_device_register(&ts5500_dio1_pdev))
+			dev_warn(&pdev->dev, "DIO1 block registration failed\n");
+		ts5500_dio2_pdev.dev.parent = &pdev->dev;
+		if (platform_device_register(&ts5500_dio2_pdev))
+			dev_warn(&pdev->dev, "DIO2 block registration failed\n");
+	}
 
 	if (led_classdev_register(&pdev->dev, &ts5500_led_cdev))
 		dev_warn(&pdev->dev, "LED registration failed\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-3.17-rc7-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-3.16-gnu/arch/x86/platform/uv/tlb_uv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/platform/uv/tlb_uv.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *	SGI UltraViolet TLB flush routines.
  *
- *	(c) 2008-2012 Cliff Wickman <cpw@sgi.com>, SGI.
+ *	(c) 2008-2014 Cliff Wickman <cpw@sgi.com>, SGI.
  *
  *	This code is released under the GNU General Public License version 2 or
  *	later.
@@ -451,7 +451,7 @@ static inline unsigned long long cycles_
 
 /*
  * The reverse of the above; converts a duration in ns to a duration in cycles.
- */ 
+ */
 static inline unsigned long long ns_2_cycles(unsigned long long ns)
 {
 	struct cyc2ns_data *data = cyc2ns_read_begin();
@@ -563,7 +563,7 @@ static int uv1_wait_completion(struct ba
  * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register.
  * But not currently used.
  */
-static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc)
+static unsigned long uv2_3_read_status(unsigned long offset, int rshft, int desc)
 {
 	unsigned long descriptor_status;
 
@@ -606,7 +606,7 @@ int handle_uv2_busy(struct bau_control *
 	return FLUSH_GIVEUP;
 }
 
-static int uv2_wait_completion(struct bau_desc *bau_desc,
+static int uv2_3_wait_completion(struct bau_desc *bau_desc,
 				unsigned long mmr_offset, int right_shift,
 				struct bau_control *bcp, long try)
 {
@@ -616,7 +616,7 @@ static int uv2_wait_completion(struct ba
 	long busy_reps = 0;
 	struct ptc_stats *stat = bcp->statp;
 
-	descriptor_stat = uv2_read_status(mmr_offset, right_shift, desc);
+	descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
 
 	/* spin on the status MMR, waiting for it to go idle */
 	while (descriptor_stat != UV2H_DESC_IDLE) {
@@ -658,8 +658,7 @@ static int uv2_wait_completion(struct ba
 				/* not to hammer on the clock */
 				busy_reps = 0;
 				ttm = get_cycles();
-				if ((ttm - bcp->send_message) >
-						bcp->timeout_interval)
+				if ((ttm - bcp->send_message) > bcp->timeout_interval)
 					return handle_uv2_busy(bcp);
 			}
 			/*
@@ -667,8 +666,7 @@ static int uv2_wait_completion(struct ba
 			 */
 			cpu_relax();
 		}
-		descriptor_stat = uv2_read_status(mmr_offset, right_shift,
-									desc);
+		descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
 	}
 	bcp->conseccompletes++;
 	return FLUSH_COMPLETE;
@@ -679,8 +677,7 @@ static int uv2_wait_completion(struct ba
  * which register to read and position in that register based on cpu in
  * current hub.
  */
-static int wait_completion(struct bau_desc *bau_desc,
-				struct bau_control *bcp, long try)
+static int wait_completion(struct bau_desc *bau_desc, struct bau_control *bcp, long try)
 {
 	int right_shift;
 	unsigned long mmr_offset;
@@ -695,11 +692,9 @@ static int wait_completion(struct bau_de
 	}
 
 	if (bcp->uvhub_version == 1)
-		return uv1_wait_completion(bau_desc, mmr_offset, right_shift,
-								bcp, try);
+		return uv1_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try);
 	else
-		return uv2_wait_completion(bau_desc, mmr_offset, right_shift,
-								bcp, try);
+		return uv2_3_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try);
 }
 
 /*
@@ -888,7 +883,7 @@ int uv_flush_send_and_wait(struct cpumas
 	struct ptc_stats *stat = bcp->statp;
 	struct bau_control *hmaster = bcp->uvhub_master;
 	struct uv1_bau_msg_header *uv1_hdr = NULL;
-	struct uv2_bau_msg_header *uv2_hdr = NULL;
+	struct uv2_3_bau_msg_header *uv2_3_hdr = NULL;
 
 	if (bcp->uvhub_version == 1) {
 		uv1 = 1;
@@ -902,27 +897,28 @@ int uv_flush_send_and_wait(struct cpumas
 	if (uv1)
 		uv1_hdr = &bau_desc->header.uv1_hdr;
 	else
-		uv2_hdr = &bau_desc->header.uv2_hdr;
+		/* uv2 and uv3 */
+		uv2_3_hdr = &bau_desc->header.uv2_3_hdr;
 
 	do {
 		if (try == 0) {
 			if (uv1)
 				uv1_hdr->msg_type = MSG_REGULAR;
 			else
-				uv2_hdr->msg_type = MSG_REGULAR;
+				uv2_3_hdr->msg_type = MSG_REGULAR;
 			seq_number = bcp->message_number++;
 		} else {
 			if (uv1)
 				uv1_hdr->msg_type = MSG_RETRY;
 			else
-				uv2_hdr->msg_type = MSG_RETRY;
+				uv2_3_hdr->msg_type = MSG_RETRY;
 			stat->s_retry_messages++;
 		}
 
 		if (uv1)
 			uv1_hdr->sequence = seq_number;
 		else
-			uv2_hdr->sequence = seq_number;
+			uv2_3_hdr->sequence = seq_number;
 		index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu;
 		bcp->send_message = get_cycles();
 
@@ -1080,8 +1076,10 @@ static int set_distrib_bits(struct cpuma
  * done.  The returned pointer is valid till preemption is re-enabled.
  */
 const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
-				struct mm_struct *mm, unsigned long start,
-				unsigned long end, unsigned int cpu)
+						struct mm_struct *mm,
+						unsigned long start,
+						unsigned long end,
+						unsigned int cpu)
 {
 	int locals = 0;
 	int remotes = 0;
@@ -1268,6 +1266,7 @@ void uv_bau_message_interrupt(struct pt_
 		if (bcp->uvhub_version == 2)
 			process_uv2_message(&msgdesc, bcp);
 		else
+			/* no error workaround for uv1 or uv3 */
 			bau_process_message(&msgdesc, bcp, 1);
 
 		msg++;
@@ -1325,8 +1324,12 @@ static void __init enable_timeouts(void)
 		 */
 		mmr_image |= (1L << SOFTACK_MSHIFT);
 		if (is_uv2_hub()) {
+			/* do not touch the legacy mode bit */
 			/* hw bug workaround; do not use extended status */
 			mmr_image &= ~(1L << UV2_EXT_SHFT);
+		} else if (is_uv3_hub()) {
+			mmr_image &= ~(1L << PREFETCH_HINT_SHFT);
+			mmr_image |= (1L << SB_STATUS_SHFT);
 		}
 		write_mmr_misc_control(pnode, mmr_image);
 	}
@@ -1476,7 +1479,7 @@ static ssize_t ptc_proc_write(struct fil
 		return count;
 	}
 
-	if (strict_strtol(optstr, 10, &input_arg) < 0) {
+	if (kstrtol(optstr, 10, &input_arg) < 0) {
 		printk(KERN_DEBUG "%s is invalid\n", optstr);
 		return -EINVAL;
 	}
@@ -1692,7 +1695,7 @@ static void activation_descriptor_init(i
 	struct bau_desc *bau_desc;
 	struct bau_desc *bd2;
 	struct uv1_bau_msg_header *uv1_hdr;
-	struct uv2_bau_msg_header *uv2_hdr;
+	struct uv2_3_bau_msg_header *uv2_3_hdr;
 	struct bau_control *bcp;
 
 	/*
@@ -1739,15 +1742,15 @@ static void activation_descriptor_init(i
 			 */
 		} else {
 			/*
-			 * BIOS uses legacy mode, but UV2 hardware always
+			 * BIOS uses legacy mode, but uv2 and uv3 hardware always
 			 * uses native mode for selective broadcasts.
 			 */
-			uv2_hdr = &bd2->header.uv2_hdr;
-			uv2_hdr->swack_flag =	1;
-			uv2_hdr->base_dest_nasid =
+			uv2_3_hdr = &bd2->header.uv2_3_hdr;
+			uv2_3_hdr->swack_flag =	1;
+			uv2_3_hdr->base_dest_nasid =
 						UV_PNODE_TO_NASID(base_pnode);
-			uv2_hdr->dest_subnodeid =	UV_LB_SUBNODEID;
-			uv2_hdr->command =		UV_NET_ENDPOINT_INTD;
+			uv2_3_hdr->dest_subnodeid =	UV_LB_SUBNODEID;
+			uv2_3_hdr->command =		UV_NET_ENDPOINT_INTD;
 		}
 	}
 	for_each_present_cpu(cpu) {
@@ -1858,6 +1861,7 @@ static int calculate_destination_timeout
 		ts_ns *= (mult1 * mult2);
 		ret = ts_ns / 1000;
 	} else {
+		/* same destination timeout for uv2 and uv3 */
 		/* 4 bits  0/1 for 10/80us base, 3 bits of multiplier */
 		mmr_image = uv_read_local_mmr(UVH_LB_BAU_MISC_CONTROL);
 		mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT;
@@ -2012,8 +2016,10 @@ static int scan_sock(struct socket_desc
 			bcp->uvhub_version = 1;
 		else if (is_uv2_hub())
 			bcp->uvhub_version = 2;
+		else if (is_uv3_hub())
+			bcp->uvhub_version = 3;
 		else {
-			printk(KERN_EMERG "uvhub version not 1 or 2\n");
+			printk(KERN_EMERG "uvhub version not 1, 2 or 3\n");
 			return 1;
 		}
 		bcp->uvhub_master = *hmasterp;
@@ -2138,9 +2144,10 @@ static int __init uv_bau_init(void)
 	}
 
 	vector = UV_BAU_MESSAGE;
-	for_each_possible_blade(uvhub)
+	for_each_possible_blade(uvhub) {
 		if (uv_blade_nr_possible_cpus(uvhub))
 			init_uvhub(uvhub, vector, uv_base_pnode);
+	}
 
 	alloc_intr_gate(vector, uv_bau_message_intr1);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/power/cpu.c linux-libre-3.17-rc7-gnu/arch/x86/power/cpu.c
--- linux-libre-3.16-gnu/arch/x86/power/cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/power/cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -165,7 +165,7 @@ static void fix_processor_context(void)
  *		by __save_processor_state()
  *	@ctxt - structure to load the registers contents from
  */
-static void __restore_processor_state(struct saved_context *ctxt)
+static void notrace __restore_processor_state(struct saved_context *ctxt)
 {
 	if (ctxt->misc_enable_saved)
 		wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
@@ -239,7 +239,7 @@ static void __restore_processor_state(st
 }
 
 /* Needed by apm.c */
-void restore_processor_state(void)
+void notrace restore_processor_state(void)
 {
 	__restore_processor_state(&saved_context);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/entry64.S linux-libre-3.17-rc7-gnu/arch/x86/purgatory/entry64.S
--- linux-libre-3.16-gnu/arch/x86/purgatory/entry64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/entry64.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2003,2004  Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2014  Red Hat Inc.
+
+ * Author(s): Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This code has been taken from kexec-tools.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+	.text
+	.balign 16
+	.code64
+	.globl entry64, entry64_regs
+
+
+entry64:
+	/* Setup a gdt that should be preserved */
+	lgdt gdt(%rip)
+
+	/* load the data segments */
+	movl    $0x18, %eax     /* data segment */
+	movl    %eax, %ds
+	movl    %eax, %es
+	movl    %eax, %ss
+	movl    %eax, %fs
+	movl    %eax, %gs
+
+	/* Setup new stack */
+	leaq    stack_init(%rip), %rsp
+	pushq   $0x10 /* CS */
+	leaq    new_cs_exit(%rip), %rax
+	pushq   %rax
+	lretq
+new_cs_exit:
+
+	/* Load the registers */
+	movq	rax(%rip), %rax
+	movq	rbx(%rip), %rbx
+	movq	rcx(%rip), %rcx
+	movq	rdx(%rip), %rdx
+	movq	rsi(%rip), %rsi
+	movq	rdi(%rip), %rdi
+	movq    rsp(%rip), %rsp
+	movq	rbp(%rip), %rbp
+	movq	r8(%rip), %r8
+	movq	r9(%rip), %r9
+	movq	r10(%rip), %r10
+	movq	r11(%rip), %r11
+	movq	r12(%rip), %r12
+	movq	r13(%rip), %r13
+	movq	r14(%rip), %r14
+	movq	r15(%rip), %r15
+
+	/* Jump to the new code... */
+	jmpq	*rip(%rip)
+
+	.section ".rodata"
+	.balign 4
+entry64_regs:
+rax:	.quad 0x0
+rcx:	.quad 0x0
+rdx:	.quad 0x0
+rbx:	.quad 0x0
+rsp:	.quad 0x0
+rbp:	.quad 0x0
+rsi:	.quad 0x0
+rdi:	.quad 0x0
+r8:	.quad 0x0
+r9:	.quad 0x0
+r10:	.quad 0x0
+r11:	.quad 0x0
+r12:	.quad 0x0
+r13:	.quad 0x0
+r14:	.quad 0x0
+r15:	.quad 0x0
+rip:	.quad 0x0
+	.size entry64_regs, . - entry64_regs
+
+	/* GDT */
+	.section ".rodata"
+	.balign 16
+gdt:
+	/* 0x00 unusable segment
+	 * 0x08 unused
+	 * so use them as gdt ptr
+	 */
+	.word gdt_end - gdt - 1
+	.quad gdt
+	.word 0, 0, 0
+
+	/* 0x10 4GB flat code segment */
+	.word 0xFFFF, 0x0000, 0x9A00, 0x00AF
+
+	/* 0x18 4GB flat data segment */
+	.word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+stack:	.quad   0, 0
+stack_init:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/Makefile linux-libre-3.17-rc7-gnu/arch/x86/purgatory/Makefile
--- linux-libre-3.16-gnu/arch/x86/purgatory/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
+
+targets += $(purgatory-y)
+PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+
+LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
+targets += purgatory.ro
+
+# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
+# in turn leaves some undefined symbols like __fentry__ in purgatory and not
+# sure how to relocate those. Like kexec-tools, use custom flags.
+
+KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
+KBUILD_CFLAGS += -m$(BITS)
+
+$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
+		$(call if_changed,ld)
+
+targets += kexec-purgatory.c
+
+quiet_cmd_bin2c = BIN2C   $@
+      cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c
+
+$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
+	$(call if_changed,bin2c)
+
+
+obj-$(CONFIG_KEXEC_FILE)	+= kexec-purgatory.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/purgatory.c linux-libre-3.17-rc7-gnu/arch/x86/purgatory/purgatory.c
--- linux-libre-3.16-gnu/arch/x86/purgatory/purgatory.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/purgatory.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * purgatory: Runs between two kernels
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * Author:
+ *       Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include "sha256.h"
+#include "../boot/string.h"
+
+struct sha_region {
+	unsigned long start;
+	unsigned long len;
+};
+
+unsigned long backup_dest = 0;
+unsigned long backup_src = 0;
+unsigned long backup_sz = 0;
+
+u8 sha256_digest[SHA256_DIGEST_SIZE] = { 0 };
+
+struct sha_region sha_regions[16] = {};
+
+/*
+ * On x86, second kernel requries first 640K of memory to boot. Copy
+ * first 640K to a backup region in reserved memory range so that second
+ * kernel can use first 640K.
+ */
+static int copy_backup_region(void)
+{
+	if (backup_dest)
+		memcpy((void *)backup_dest, (void *)backup_src, backup_sz);
+
+	return 0;
+}
+
+int verify_sha256_digest(void)
+{
+	struct sha_region *ptr, *end;
+	u8 digest[SHA256_DIGEST_SIZE];
+	struct sha256_state sctx;
+
+	sha256_init(&sctx);
+	end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])];
+	for (ptr = sha_regions; ptr < end; ptr++)
+		sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
+
+	sha256_final(&sctx, digest);
+
+	if (memcmp(digest, sha256_digest, sizeof(digest)))
+		return 1;
+
+	return 0;
+}
+
+void purgatory(void)
+{
+	int ret;
+
+	ret = verify_sha256_digest();
+	if (ret) {
+		/* loop forever */
+		for (;;)
+			;
+	}
+	copy_backup_region();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/setup-x86_64.S linux-libre-3.17-rc7-gnu/arch/x86/purgatory/setup-x86_64.S
--- linux-libre-3.16-gnu/arch/x86/purgatory/setup-x86_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/setup-x86_64.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ * purgatory:  setup code
+ *
+ * Copyright (C) 2003,2004  Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This code has been taken from kexec-tools.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+	.text
+	.globl purgatory_start
+	.balign 16
+purgatory_start:
+	.code64
+
+	/* Load a gdt so I know what the segment registers are */
+	lgdt	gdt(%rip)
+
+	/* load the data segments */
+	movl	$0x18, %eax	/* data segment */
+	movl	%eax, %ds
+	movl	%eax, %es
+	movl	%eax, %ss
+	movl	%eax, %fs
+	movl	%eax, %gs
+
+	/* Setup a stack */
+	leaq	lstack_end(%rip), %rsp
+
+	/* Call the C code */
+	call purgatory
+	jmp	entry64
+
+	.section ".rodata"
+	.balign 16
+gdt:	/* 0x00 unusable segment
+	 * 0x08 unused
+	 * so use them as the gdt ptr
+	 */
+	.word	gdt_end - gdt - 1
+	.quad	gdt
+	.word	0, 0, 0
+
+	/* 0x10 4GB flat code segment */
+	.word	0xFFFF, 0x0000, 0x9A00, 0x00AF
+
+	/* 0x18 4GB flat data segment */
+	.word	0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+	.bss
+	.balign 4096
+lstack:
+	.skip 4096
+lstack_end:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/sha256.c linux-libre-3.17-rc7-gnu/arch/x86/purgatory/sha256.c
--- linux-libre-3.16-gnu/arch/x86/purgatory/sha256.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/sha256.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,283 @@
+/*
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include "sha256.h"
+#include "../boot/string.h"
+
+static inline u32 Ch(u32 x, u32 y, u32 z)
+{
+	return z ^ (x & (y ^ z));
+}
+
+static inline u32 Maj(u32 x, u32 y, u32 z)
+{
+	return (x & y) | (z & (x | y));
+}
+
+#define e0(x)       (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
+#define e1(x)       (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
+#define s0(x)       (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
+#define s1(x)       (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+	W[I] = __be32_to_cpu(((__be32 *)(input))[I]);
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha256_transform(u32 *state, const u8 *input)
+{
+	u32 a, b, c, d, e, f, g, h, t1, t2;
+	u32 W[64];
+	int i;
+
+	/* load the input */
+	for (i = 0; i < 16; i++)
+		LOAD_OP(i, W, input);
+
+	/* now blend */
+	for (i = 16; i < 64; i++)
+		BLEND_OP(i, W);
+
+	/* load the state into our registers */
+	a = state[0];  b = state[1];  c = state[2];  d = state[3];
+	e = state[4];  f = state[5];  g = state[6];  h = state[7];
+
+	/* now iterate */
+	t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56];
+	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1+t2;
+	t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57];
+	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1+t2;
+	t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58];
+	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1+t2;
+	t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59];
+	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1+t2;
+	t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60];
+	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1+t2;
+	t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61];
+	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1+t2;
+	t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62];
+	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1+t2;
+	t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63];
+	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1+t2;
+
+	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+	/* clear any sensitive info... */
+	a = b = c = d = e = f = g = h = t1 = t2 = 0;
+	memset(W, 0, 64 * sizeof(u32));
+}
+
+int sha256_init(struct sha256_state *sctx)
+{
+	sctx->state[0] = SHA256_H0;
+	sctx->state[1] = SHA256_H1;
+	sctx->state[2] = SHA256_H2;
+	sctx->state[3] = SHA256_H3;
+	sctx->state[4] = SHA256_H4;
+	sctx->state[5] = SHA256_H5;
+	sctx->state[6] = SHA256_H6;
+	sctx->state[7] = SHA256_H7;
+	sctx->count = 0;
+
+	return 0;
+}
+
+int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
+{
+	unsigned int partial, done;
+	const u8 *src;
+
+	partial = sctx->count & 0x3f;
+	sctx->count += len;
+	done = 0;
+	src = data;
+
+	if ((partial + len) > 63) {
+		if (partial) {
+			done = -partial;
+			memcpy(sctx->buf + partial, data, done + 64);
+			src = sctx->buf;
+		}
+
+		do {
+			sha256_transform(sctx->state, src);
+			done += 64;
+			src = data + done;
+		} while (done + 63 < len);
+
+		partial = 0;
+	}
+	memcpy(sctx->buf + partial, src, len - done);
+
+	return 0;
+}
+
+int sha256_final(struct sha256_state *sctx, u8 *out)
+{
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	unsigned int index, pad_len;
+	int i;
+	static const u8 padding[64] = { 0x80, };
+
+	/* Save number of bits */
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64. */
+	index = sctx->count & 0x3f;
+	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
+	sha256_update(sctx, padding, pad_len);
+
+	/* Append length (before padding) */
+	sha256_update(sctx, (const u8 *)&bits, sizeof(bits));
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Zeroize sensitive information. */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/sha256.h linux-libre-3.17-rc7-gnu/arch/x86/purgatory/sha256.h
--- linux-libre-3.16-gnu/arch/x86/purgatory/sha256.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/sha256.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2014 Red Hat Inc.
+ *
+ *  Author: Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#ifndef SHA256_H
+#define SHA256_H
+
+
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+extern int sha256_init(struct sha256_state *sctx);
+extern int sha256_update(struct sha256_state *sctx, const u8 *input,
+				unsigned int length);
+extern int sha256_final(struct sha256_state *sctx, u8 *hash);
+
+#endif /* SHA256_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/stack.S linux-libre-3.17-rc7-gnu/arch/x86/purgatory/stack.S
--- linux-libre-3.16-gnu/arch/x86/purgatory/stack.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/stack.S	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * purgatory:  stack
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+	/* A stack for the loaded kernel.
+	 * Seperate and in the data section so it can be prepopulated.
+	 */
+	.data
+	.balign 4096
+	.globl stack, stack_end
+
+stack:
+	.skip 4096
+stack_end:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/purgatory/string.c linux-libre-3.17-rc7-gnu/arch/x86/purgatory/string.c
--- linux-libre-3.16-gnu/arch/x86/purgatory/string.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/purgatory/string.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,13 @@
+/*
+ * Simple string functions.
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * Author:
+ *       Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include "../boot/string.c"
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/syscalls/syscall_32.tbl linux-libre-3.17-rc7-gnu/arch/x86/syscalls/syscall_32.tbl
--- linux-libre-3.16-gnu/arch/x86/syscalls/syscall_32.tbl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/syscalls/syscall_32.tbl	2014-09-28 17:29:07.000000000 -0400
@@ -360,3 +360,6 @@
 351	i386	sched_setattr		sys_sched_setattr
 352	i386	sched_getattr		sys_sched_getattr
 353	i386	renameat2		sys_renameat2
+354	i386	seccomp			sys_seccomp
+355	i386	getrandom		sys_getrandom
+356	i386	memfd_create		sys_memfd_create
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/syscalls/syscall_64.tbl linux-libre-3.17-rc7-gnu/arch/x86/syscalls/syscall_64.tbl
--- linux-libre-3.16-gnu/arch/x86/syscalls/syscall_64.tbl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/syscalls/syscall_64.tbl	2014-09-28 17:29:07.000000000 -0400
@@ -323,6 +323,10 @@
 314	common	sched_setattr		sys_sched_setattr
 315	common	sched_getattr		sys_sched_getattr
 316	common	renameat2		sys_renameat2
+317	common	seccomp			sys_seccomp
+318	common	getrandom		sys_getrandom
+319	common	memfd_create		sys_memfd_create
+320	common	kexec_file_load		sys_kexec_file_load
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/um/asm/elf.h linux-libre-3.17-rc7-gnu/arch/x86/um/asm/elf.h
--- linux-libre-3.16-gnu/arch/x86/um/asm/elf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/um/asm/elf.h	2014-09-28 17:29:07.000000000 -0400
@@ -216,6 +216,5 @@ extern long elf_aux_hwcap;
 #define ELF_HWCAP (elf_aux_hwcap)
 
 #define SET_PERSONALITY(ex) do ; while(0)
-#define __HAVE_ARCH_GATE_AREA 1
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/um/asm/processor.h linux-libre-3.17-rc7-gnu/arch/x86/um/asm/processor.h
--- linux-libre-3.16-gnu/arch/x86/um/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/um/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,8 @@ static inline void rep_nop(void)
 	__asm__ __volatile__("rep;nop": : :"memory");
 }
 
-#define cpu_relax()	rep_nop()
+#define cpu_relax()		rep_nop()
+#define cpu_relax_lowlatency()	cpu_relax()
 
 #include <asm/processor-generic.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/um/mem_64.c linux-libre-3.17-rc7-gnu/arch/x86/um/mem_64.c
--- linux-libre-3.16-gnu/arch/x86/um/mem_64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/um/mem_64.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,18 +9,3 @@ const char *arch_vma_name(struct vm_area
 
 	return NULL;
 }
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/um/signal.c linux-libre-3.17-rc7-gnu/arch/x86/um/signal.c
--- linux-libre-3.16-gnu/arch/x86/um/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/um/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -370,13 +370,12 @@ struct rt_sigframe
 	char retcode[8];
 };
 
-int setup_signal_stack_sc(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  sigset_t *mask)
+int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
+			  struct pt_regs *regs, sigset_t *mask)
 {
 	struct sigframe __user *frame;
 	void __user *restorer;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 
 	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
 	stack_top = ((stack_top + 4) & -16UL) - 4;
@@ -385,8 +384,8 @@ int setup_signal_stack_sc(unsigned long
 		return 1;
 
 	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		restorer = ksig->ka.sa.sa_restorer;
 
 	err |= __put_user(restorer, &frame->pretcode);
 	err |= __put_user(sig, &frame->sig);
@@ -410,20 +409,19 @@ int setup_signal_stack_sc(unsigned long
 		return err;
 
 	PT_REGS_SP(regs) = (unsigned long) frame;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
 	PT_REGS_AX(regs) = (unsigned long) sig;
 	PT_REGS_DX(regs) = (unsigned long) 0;
 	PT_REGS_CX(regs) = (unsigned long) 0;
 	return 0;
 }
 
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  siginfo_t *info, sigset_t *mask)
+int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+			  struct pt_regs *regs, sigset_t *mask)
 {
 	struct rt_sigframe __user *frame;
 	void __user *restorer;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 
 	stack_top &= -8UL;
 	frame = (struct rt_sigframe __user *) stack_top - 1;
@@ -431,14 +429,14 @@ int setup_signal_stack_si(unsigned long
 		return 1;
 
 	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		restorer = ksig->ka.sa.sa_restorer;
 
 	err |= __put_user(restorer, &frame->pretcode);
 	err |= __put_user(sig, &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
 					PT_REGS_SP(regs));
 
@@ -457,7 +455,7 @@ int setup_signal_stack_si(unsigned long
 		return err;
 
 	PT_REGS_SP(regs) = (unsigned long) frame;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
 	PT_REGS_AX(regs) = (unsigned long) sig;
 	PT_REGS_DX(regs) = (unsigned long) &frame->info;
 	PT_REGS_CX(regs) = (unsigned long) &frame->uc;
@@ -502,12 +500,11 @@ struct rt_sigframe
 	struct _fpstate fpstate;
 };
 
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs * regs,
-			  siginfo_t *info, sigset_t *set)
+int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+			  struct pt_regs *regs, sigset_t *set)
 {
 	struct rt_sigframe __user *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 
 	frame = (struct rt_sigframe __user *)
 		round_down(stack_top - sizeof(struct rt_sigframe), 16);
@@ -517,8 +514,8 @@ int setup_signal_stack_si(unsigned long
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto out;
 
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 		if (err)
 			goto out;
 	}
@@ -543,8 +540,8 @@ int setup_signal_stack_si(unsigned long
 	 * already in userspace.
 	 */
 	/* x86-64 should always use SA_RESTORER. */
-	if (ka->sa.sa_flags & SA_RESTORER)
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		err |= __put_user(ksig->ka.sa.sa_restorer, &frame->pretcode);
 	else
 		/* could use a vstub here */
 		return err;
@@ -570,7 +567,7 @@ int setup_signal_stack_si(unsigned long
 	 */
 	PT_REGS_SI(regs) = (unsigned long) &frame->info;
 	PT_REGS_DX(regs) = (unsigned long) &frame->uc;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
  out:
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/Makefile linux-libre-3.17-rc7-gnu/arch/x86/vdso/Makefile
--- linux-libre-3.16-gnu/arch/x86/vdso/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@ VDSO32-$(CONFIG_X86_32)		:= y
 VDSO32-$(CONFIG_COMPAT)		:= y
 
 # files to link into the vdso
-vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vdso-fakesections.o
+vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
 
 # files to link into kernel
 obj-y				+= vma.o
@@ -37,7 +37,8 @@ vdso_img_sodbg := $(vdso_img-y:%=vdso%.s
 obj-y += $(vdso_img_objs)
 targets += $(vdso_img_cfiles)
 targets += $(vdso_img_sodbg)
-.SECONDARY: $(vdso_img-y:%=$(obj)/vdso-image-%.c)
+.SECONDARY: $(vdso_img-y:%=$(obj)/vdso-image-%.c) \
+	$(vdso_img-y:%=$(obj)/vdso%.so)
 
 export CPPFLAGS_vdso.lds += -P -C
 
@@ -54,10 +55,10 @@ hostprogs-y			+= vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
 define cmd_vdso2c
-	$(obj)/vdso2c $< $@
+	$(obj)/vdso2c $< $(<:%.dbg=%) $@
 endef
 
-$(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso2c FORCE
+$(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE
 	$(call if_changed,vdso2c)
 
 #
@@ -113,6 +114,10 @@ $(obj)/%-x32.o: $(obj)/%.o FORCE
 
 targets += vdsox32.lds $(vobjx32s-y)
 
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg
+	$(call if_changed,objcopy)
+
 $(obj)/vdsox32.so.dbg: $(src)/vdsox32.lds $(vobjx32s) FORCE
 	$(call if_changed,vdso)
 
@@ -134,7 +139,7 @@ override obj-dirs = $(dir $(obj)) $(obj)
 
 targets += vdso32/vdso32.lds
 targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o)
-targets += vdso32/vclock_gettime.o vdso32/vdso-fakesections.o
+targets += vdso32/vclock_gettime.o
 
 $(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%)
 
@@ -156,7 +161,6 @@ $(vdso32-images:%=$(obj)/%.dbg): KBUILD_
 $(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
 				 $(obj)/vdso32/vdso32.lds \
 				 $(obj)/vdso32/vclock_gettime.o \
-				 $(obj)/vdso32/vdso-fakesections.o \
 				 $(obj)/vdso32/note.o \
 				 $(obj)/vdso32/%.o
 	$(call if_changed,vdso)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vdso2c.c linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso2c.c
--- linux-libre-3.16-gnu/arch/x86/vdso/vdso2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,53 @@
+/*
+ * vdso2c - A vdso image preparation tool
+ * Copyright (c) 2014 Andy Lutomirski and others
+ * Licensed under the GPL v2
+ *
+ * vdso2c requires stripped and unstripped input.  It would be trivial
+ * to fully strip the input in here, but, for reasons described below,
+ * we need to write a section table.  Doing this is more or less
+ * equivalent to dropping all non-allocatable sections, but it's
+ * easier to let objcopy handle that instead of doing it ourselves.
+ * If we ever need to do something fancier than what objcopy provides,
+ * it would be straightforward to add here.
+ *
+ * We're keep a section table for a few reasons:
+ *
+ * The Go runtime had a couple of bugs: it would read the section
+ * table to try to figure out how many dynamic symbols there were (it
+ * shouldn't have looked at the section table at all) and, if there
+ * were no SHT_SYNDYM section table entry, it would use an
+ * uninitialized value for the number of symbols.  An empty DYNSYM
+ * table would work, but I see no reason not to write a valid one (and
+ * keep full performance for old Go programs).  This hack is only
+ * needed on x86_64.
+ *
+ * The bug was introduced on 2012-08-31 by:
+ * https://code.google.com/p/go/source/detail?r=56ea40aac72b
+ * and was fixed on 2014-06-13 by:
+ * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
+ *
+ * Binutils has issues debugging the vDSO: it reads the section table to
+ * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
+ * would break build-id if we removed the section table.  Binutils
+ * also requires that shstrndx != 0.  See:
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
+ *
+ * elfutils might not look for PT_NOTE if there is a section table at
+ * all.  I don't know whether this matters for any practical purpose.
+ *
+ * For simplicity, rather than hacking up a partial section table, we
+ * just write a mostly complete one.  We omit non-dynamic symbols,
+ * though, since they're rather large.
+ *
+ * Once binutils gets fixed, we might be able to drop this for all but
+ * the 64-bit vdso, since build-id only works in kernel RPMs, and
+ * systems that update to new enough kernel RPMs will likely update
+ * binutils in sync.  build-id has never worked for home-built kernel
+ * RPMs without manual symlinking, and I suspect that no one ever does
+ * that.
+ */
+
 #include <inttypes.h>
 #include <stdint.h>
 #include <unistd.h>
@@ -20,9 +70,9 @@ const char *outfilename;
 
 /* Symbols that we need in vdso2c. */
 enum {
+	sym_vvar_start,
 	sym_vvar_page,
 	sym_hpet_page,
-	sym_end_mapping,
 	sym_VDSO_FAKE_SECTION_TABLE_START,
 	sym_VDSO_FAKE_SECTION_TABLE_END,
 };
@@ -38,9 +88,9 @@ struct vdso_sym {
 };
 
 struct vdso_sym required_syms[] = {
+	[sym_vvar_start] = {"vvar_start", true},
 	[sym_vvar_page] = {"vvar_page", true},
 	[sym_hpet_page] = {"hpet_page", true},
-	[sym_end_mapping] = {"end_mapping", true},
 	[sym_VDSO_FAKE_SECTION_TABLE_START] = {
 		"VDSO_FAKE_SECTION_TABLE_START", false
 	},
@@ -61,7 +111,8 @@ static void fail(const char *format, ...
 	va_start(ap, format);
 	fprintf(stderr, "Error: ");
 	vfprintf(stderr, format, ap);
-	unlink(outfilename);
+	if (outfilename)
+		unlink(outfilename);
 	exit(1);
 	va_end(ap);
 }
@@ -96,9 +147,11 @@ extern void bad_put_le(void);
 
 #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
 
-#define BITSFUNC3(name, bits) name##bits
-#define BITSFUNC2(name, bits) BITSFUNC3(name, bits)
-#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS)
+#define BITSFUNC3(name, bits, suffix) name##bits##suffix
+#define BITSFUNC2(name, bits, suffix) BITSFUNC3(name, bits, suffix)
+#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS, )
+
+#define INT_BITS BITSFUNC2(int, ELF_BITS, _t)
 
 #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
 #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
@@ -112,30 +165,53 @@ extern void bad_put_le(void);
 #include "vdso2c.h"
 #undef ELF_BITS
 
-static void go(void *addr, size_t len, FILE *outfile, const char *name)
+static void go(void *raw_addr, size_t raw_len,
+	       void *stripped_addr, size_t stripped_len,
+	       FILE *outfile, const char *name)
 {
-	Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr;
+	Elf64_Ehdr *hdr = (Elf64_Ehdr *)raw_addr;
 
 	if (hdr->e_ident[EI_CLASS] == ELFCLASS64) {
-		go64(addr, len, outfile, name);
+		go64(raw_addr, raw_len, stripped_addr, stripped_len,
+		     outfile, name);
 	} else if (hdr->e_ident[EI_CLASS] == ELFCLASS32) {
-		go32(addr, len, outfile, name);
+		go32(raw_addr, raw_len, stripped_addr, stripped_len,
+		     outfile, name);
 	} else {
 		fail("unknown ELF class\n");
 	}
 }
 
+static void map_input(const char *name, void **addr, size_t *len, int prot)
+{
+	off_t tmp_len;
+
+	int fd = open(name, O_RDONLY);
+	if (fd == -1)
+		err(1, "%s", name);
+
+	tmp_len = lseek(fd, 0, SEEK_END);
+	if (tmp_len == (off_t)-1)
+		err(1, "lseek");
+	*len = (size_t)tmp_len;
+
+	*addr = mmap(NULL, tmp_len, prot, MAP_PRIVATE, fd, 0);
+	if (*addr == MAP_FAILED)
+		err(1, "mmap");
+
+	close(fd);
+}
+
 int main(int argc, char **argv)
 {
-	int fd;
-	off_t len;
-	void *addr;
+	size_t raw_len, stripped_len;
+	void *raw_addr, *stripped_addr;
 	FILE *outfile;
 	char *name, *tmp;
 	int namelen;
 
-	if (argc != 3) {
-		printf("Usage: vdso2c INPUT OUTPUT\n");
+	if (argc != 4) {
+		printf("Usage: vdso2c RAW_INPUT STRIPPED_INPUT OUTPUT\n");
 		return 1;
 	}
 
@@ -143,7 +219,7 @@ int main(int argc, char **argv)
 	 * Figure out the struct name.  If we're writing to a .so file,
 	 * generate raw output insted.
 	 */
-	name = strdup(argv[2]);
+	name = strdup(argv[3]);
 	namelen = strlen(name);
 	if (namelen >= 3 && !strcmp(name + namelen - 3, ".so")) {
 		name = NULL;
@@ -159,26 +235,18 @@ int main(int argc, char **argv)
 				*tmp = '_';
 	}
 
-	fd = open(argv[1], O_RDONLY);
-	if (fd == -1)
-		err(1, "%s", argv[1]);
-
-	len = lseek(fd, 0, SEEK_END);
-	if (len == (off_t)-1)
-		err(1, "lseek");
-
-	addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-	if (addr == MAP_FAILED)
-		err(1, "mmap");
+	map_input(argv[1], &raw_addr, &raw_len, PROT_READ);
+	map_input(argv[2], &stripped_addr, &stripped_len, PROT_READ);
 
-	outfilename = argv[2];
+	outfilename = argv[3];
 	outfile = fopen(outfilename, "w");
 	if (!outfile)
 		err(1, "%s", argv[2]);
 
-	go(addr, (size_t)len, outfile, name);
+	go(raw_addr, raw_len, stripped_addr, stripped_len, outfile, name);
 
-	munmap(addr, len);
+	munmap(raw_addr, raw_len);
+	munmap(stripped_addr, stripped_len);
 	fclose(outfile);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vdso2c.h linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso2c.h
--- linux-libre-3.16-gnu/arch/x86/vdso/vdso2c.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso2c.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,139 +4,23 @@
  * are built for 32-bit userspace.
  */
 
-/*
- * We're writing a section table for a few reasons:
- *
- * The Go runtime had a couple of bugs: it would read the section
- * table to try to figure out how many dynamic symbols there were (it
- * shouldn't have looked at the section table at all) and, if there
- * were no SHT_SYNDYM section table entry, it would use an
- * uninitialized value for the number of symbols.  An empty DYNSYM
- * table would work, but I see no reason not to write a valid one (and
- * keep full performance for old Go programs).  This hack is only
- * needed on x86_64.
- *
- * The bug was introduced on 2012-08-31 by:
- * https://code.google.com/p/go/source/detail?r=56ea40aac72b
- * and was fixed on 2014-06-13 by:
- * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
- *
- * Binutils has issues debugging the vDSO: it reads the section table to
- * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
- * would break build-id if we removed the section table.  Binutils
- * also requires that shstrndx != 0.  See:
- * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
- *
- * elfutils might not look for PT_NOTE if there is a section table at
- * all.  I don't know whether this matters for any practical purpose.
- *
- * For simplicity, rather than hacking up a partial section table, we
- * just write a mostly complete one.  We omit non-dynamic symbols,
- * though, since they're rather large.
- *
- * Once binutils gets fixed, we might be able to drop this for all but
- * the 64-bit vdso, since build-id only works in kernel RPMs, and
- * systems that update to new enough kernel RPMs will likely update
- * binutils in sync.  build-id has never worked for home-built kernel
- * RPMs without manual symlinking, and I suspect that no one ever does
- * that.
- */
-struct BITSFUNC(fake_sections)
-{
-	ELF(Shdr) *table;
-	unsigned long table_offset;
-	int count, max_count;
-
-	int in_shstrndx;
-	unsigned long shstr_offset;
-	const char *shstrtab;
-	size_t shstrtab_len;
-
-	int out_shstrndx;
-};
-
-static unsigned int BITSFUNC(find_shname)(struct BITSFUNC(fake_sections) *out,
-					  const char *name)
-{
-	const char *outname = out->shstrtab;
-	while (outname - out->shstrtab < out->shstrtab_len) {
-		if (!strcmp(name, outname))
-			return (outname - out->shstrtab) + out->shstr_offset;
-		outname += strlen(outname) + 1;
-	}
-
-	if (*name)
-		printf("Warning: could not find output name \"%s\"\n", name);
-	return out->shstr_offset + out->shstrtab_len - 1;  /* Use a null. */
-}
-
-static void BITSFUNC(init_sections)(struct BITSFUNC(fake_sections) *out)
-{
-	if (!out->in_shstrndx)
-		fail("didn't find the fake shstrndx\n");
-
-	memset(out->table, 0, out->max_count * sizeof(ELF(Shdr)));
-
-	if (out->max_count < 1)
-		fail("we need at least two fake output sections\n");
-
-	PUT_LE(&out->table[0].sh_type, SHT_NULL);
-	PUT_LE(&out->table[0].sh_name, BITSFUNC(find_shname)(out, ""));
-
-	out->count = 1;
-}
-
-static void BITSFUNC(copy_section)(struct BITSFUNC(fake_sections) *out,
-				   int in_idx, const ELF(Shdr) *in,
-				   const char *name)
-{
-	uint64_t flags = GET_LE(&in->sh_flags);
-
-	bool copy = flags & SHF_ALLOC &&
-		(GET_LE(&in->sh_size) ||
-		 (GET_LE(&in->sh_type) != SHT_RELA &&
-		  GET_LE(&in->sh_type) != SHT_REL)) &&
-		strcmp(name, ".altinstructions") &&
-		strcmp(name, ".altinstr_replacement");
-
-	if (!copy)
-		return;
-
-	if (out->count >= out->max_count)
-		fail("too many copied sections (max = %d)\n", out->max_count);
-
-	if (in_idx == out->in_shstrndx)
-		out->out_shstrndx = out->count;
-
-	out->table[out->count] = *in;
-	PUT_LE(&out->table[out->count].sh_name,
-	       BITSFUNC(find_shname)(out, name));
-
-	/* elfutils requires that a strtab have the correct type. */
-	if (!strcmp(name, ".fake_shstrtab"))
-		PUT_LE(&out->table[out->count].sh_type, SHT_STRTAB);
-
-	out->count++;
-}
-
-static void BITSFUNC(go)(void *addr, size_t len,
+static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
+			 void *stripped_addr, size_t stripped_len,
 			 FILE *outfile, const char *name)
 {
 	int found_load = 0;
 	unsigned long load_size = -1;  /* Work around bogus warning */
-	unsigned long data_size;
-	ELF(Ehdr) *hdr = (ELF(Ehdr) *)addr;
+	unsigned long mapping_size;
+	ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
 	int i;
 	unsigned long j;
 	ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
 		*alt_sec = NULL;
 	ELF(Dyn) *dyn = 0, *dyn_end = 0;
 	const char *secstrings;
-	uint64_t syms[NSYMS] = {};
-
-	struct BITSFUNC(fake_sections) fake_sections = {};
+	INT_BITS syms[NSYMS] = {};
 
-	ELF(Phdr) *pt = (ELF(Phdr) *)(addr + GET_LE(&hdr->e_phoff));
+	ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_LE(&hdr->e_phoff));
 
 	/* Walk the segment table. */
 	for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
@@ -154,14 +38,16 @@ static void BITSFUNC(go)(void *addr, siz
 			load_size = GET_LE(&pt[i].p_memsz);
 			found_load = 1;
 		} else if (GET_LE(&pt[i].p_type) == PT_DYNAMIC) {
-			dyn = addr + GET_LE(&pt[i].p_offset);
-			dyn_end = addr + GET_LE(&pt[i].p_offset) +
+			dyn = raw_addr + GET_LE(&pt[i].p_offset);
+			dyn_end = raw_addr + GET_LE(&pt[i].p_offset) +
 				GET_LE(&pt[i].p_memsz);
 		}
 	}
 	if (!found_load)
 		fail("no PT_LOAD seg\n");
-	data_size = (load_size + 4095) / 4096 * 4096;
+
+	if (stripped_len < load_size)
+		fail("stripped input is too short\n");
 
 	/* Walk the dynamic table */
 	for (i = 0; dyn + i < dyn_end &&
@@ -173,11 +59,11 @@ static void BITSFUNC(go)(void *addr, siz
 	}
 
 	/* Walk the section table */
-	secstrings_hdr = addr + GET_LE(&hdr->e_shoff) +
+	secstrings_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
 		GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx);
-	secstrings = addr + GET_LE(&secstrings_hdr->sh_offset);
+	secstrings = raw_addr + GET_LE(&secstrings_hdr->sh_offset);
 	for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
-		ELF(Shdr) *sh = addr + GET_LE(&hdr->e_shoff) +
+		ELF(Shdr) *sh = raw_addr + GET_LE(&hdr->e_shoff) +
 			GET_LE(&hdr->e_shentsize) * i;
 		if (GET_LE(&sh->sh_type) == SHT_SYMTAB)
 			symtab_hdr = sh;
@@ -190,7 +76,7 @@ static void BITSFUNC(go)(void *addr, siz
 	if (!symtab_hdr)
 		fail("no symbol table\n");
 
-	strtab_hdr = addr + GET_LE(&hdr->e_shoff) +
+	strtab_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
 		GET_LE(&hdr->e_shentsize) * GET_LE(&symtab_hdr->sh_link);
 
 	/* Walk the symbol table */
@@ -198,9 +84,9 @@ static void BITSFUNC(go)(void *addr, siz
 	     i < GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize);
 	     i++) {
 		int k;
-		ELF(Sym) *sym = addr + GET_LE(&symtab_hdr->sh_offset) +
+		ELF(Sym) *sym = raw_addr + GET_LE(&symtab_hdr->sh_offset) +
 			GET_LE(&symtab_hdr->sh_entsize) * i;
-		const char *name = addr + GET_LE(&strtab_hdr->sh_offset) +
+		const char *name = raw_addr + GET_LE(&strtab_hdr->sh_offset) +
 			GET_LE(&sym->st_name);
 
 		for (k = 0; k < NSYMS; k++) {
@@ -209,52 +95,18 @@ static void BITSFUNC(go)(void *addr, siz
 					fail("duplicate symbol %s\n",
 					     required_syms[k].name);
 				}
+
+				/*
+				 * Careful: we use negative addresses, but
+				 * st_value is unsigned, so we rely
+				 * on syms[k] being a signed type of the
+				 * correct width.
+				 */
 				syms[k] = GET_LE(&sym->st_value);
 			}
 		}
-
-		if (!strcmp(name, "fake_shstrtab")) {
-			ELF(Shdr) *sh;
-
-			fake_sections.in_shstrndx = GET_LE(&sym->st_shndx);
-			fake_sections.shstrtab = addr + GET_LE(&sym->st_value);
-			fake_sections.shstrtab_len = GET_LE(&sym->st_size);
-			sh = addr + GET_LE(&hdr->e_shoff) +
-				GET_LE(&hdr->e_shentsize) *
-				fake_sections.in_shstrndx;
-			fake_sections.shstr_offset = GET_LE(&sym->st_value) -
-				GET_LE(&sh->sh_addr);
-		}
 	}
 
-	/* Build the output section table. */
-	if (!syms[sym_VDSO_FAKE_SECTION_TABLE_START] ||
-	    !syms[sym_VDSO_FAKE_SECTION_TABLE_END])
-		fail("couldn't find fake section table\n");
-	if ((syms[sym_VDSO_FAKE_SECTION_TABLE_END] -
-	     syms[sym_VDSO_FAKE_SECTION_TABLE_START]) % sizeof(ELF(Shdr)))
-		fail("fake section table size isn't a multiple of sizeof(Shdr)\n");
-	fake_sections.table = addr + syms[sym_VDSO_FAKE_SECTION_TABLE_START];
-	fake_sections.table_offset = syms[sym_VDSO_FAKE_SECTION_TABLE_START];
-	fake_sections.max_count = (syms[sym_VDSO_FAKE_SECTION_TABLE_END] -
-				   syms[sym_VDSO_FAKE_SECTION_TABLE_START]) /
-		sizeof(ELF(Shdr));
-
-	BITSFUNC(init_sections)(&fake_sections);
-	for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
-		ELF(Shdr) *sh = addr + GET_LE(&hdr->e_shoff) +
-			GET_LE(&hdr->e_shentsize) * i;
-		BITSFUNC(copy_section)(&fake_sections, i, sh,
-				       secstrings + GET_LE(&sh->sh_name));
-	}
-	if (!fake_sections.out_shstrndx)
-		fail("didn't generate shstrndx?!?\n");
-
-	PUT_LE(&hdr->e_shoff, fake_sections.table_offset);
-	PUT_LE(&hdr->e_shentsize, sizeof(ELF(Shdr)));
-	PUT_LE(&hdr->e_shnum, fake_sections.count);
-	PUT_LE(&hdr->e_shstrndx, fake_sections.out_shstrndx);
-
 	/* Validate mapping addresses. */
 	for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) {
 		if (!syms[i])
@@ -263,21 +115,23 @@ static void BITSFUNC(go)(void *addr, siz
 		if (syms[i] % 4096)
 			fail("%s must be a multiple of 4096\n",
 			     required_syms[i].name);
-		if (syms[i] < data_size)
-			fail("%s must be after the text mapping\n",
+		if (syms[sym_vvar_start] > syms[i] + 4096)
+			fail("%s underruns begin_vvar\n",
 			     required_syms[i].name);
-		if (syms[sym_end_mapping] < syms[i] + 4096)
-			fail("%s overruns end_mapping\n",
+		if (syms[i] + 4096 > 0)
+			fail("%s is on the wrong side of the vdso text\n",
 			     required_syms[i].name);
 	}
-	if (syms[sym_end_mapping] % 4096)
-		fail("end_mapping must be a multiple of 4096\n");
+	if (syms[sym_vvar_start] % 4096)
+		fail("vvar_begin must be a multiple of 4096\n");
 
 	if (!name) {
-		fwrite(addr, load_size, 1, outfile);
+		fwrite(stripped_addr, stripped_len, 1, outfile);
 		return;
 	}
 
+	mapping_size = (stripped_len + 4095) / 4096 * 4096;
+
 	fprintf(outfile, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
 	fprintf(outfile, "#include <linux/linkage.h>\n");
 	fprintf(outfile, "#include <asm/page_types.h>\n");
@@ -285,20 +139,21 @@ static void BITSFUNC(go)(void *addr, siz
 	fprintf(outfile, "\n");
 	fprintf(outfile,
 		"static unsigned char raw_data[%lu] __page_aligned_data = {",
-		data_size);
-	for (j = 0; j < load_size; j++) {
+		mapping_size);
+	for (j = 0; j < stripped_len; j++) {
 		if (j % 10 == 0)
 			fprintf(outfile, "\n\t");
-		fprintf(outfile, "0x%02X, ", (int)((unsigned char *)addr)[j]);
+		fprintf(outfile, "0x%02X, ",
+			(int)((unsigned char *)stripped_addr)[j]);
 	}
 	fprintf(outfile, "\n};\n\n");
 
 	fprintf(outfile, "static struct page *pages[%lu];\n\n",
-		data_size / 4096);
+		mapping_size / 4096);
 
 	fprintf(outfile, "const struct vdso_image %s = {\n", name);
 	fprintf(outfile, "\t.data = raw_data,\n");
-	fprintf(outfile, "\t.size = %lu,\n", data_size);
+	fprintf(outfile, "\t.size = %lu,\n", mapping_size);
 	fprintf(outfile, "\t.text_mapping = {\n");
 	fprintf(outfile, "\t\t.name = \"[vdso]\",\n");
 	fprintf(outfile, "\t\t.pages = pages,\n");
@@ -311,8 +166,8 @@ static void BITSFUNC(go)(void *addr, siz
 	}
 	for (i = 0; i < NSYMS; i++) {
 		if (required_syms[i].export && syms[i])
-			fprintf(outfile, "\t.sym_%s = 0x%" PRIx64 ",\n",
-				required_syms[i].name, syms[i]);
+			fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
+				required_syms[i].name, (int64_t)syms[i]);
 	}
 	fprintf(outfile, "};\n");
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vdso32-setup.c linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso32-setup.c
--- linux-libre-3.16-gnu/arch/x86/vdso/vdso32-setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso32-setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -115,23 +115,6 @@ static __init int ia32_binfmt_init(void)
 	return 0;
 }
 __initcall(ia32_binfmt_init);
-#endif
-
-#else  /* CONFIG_X86_32 */
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
+#endif /* CONFIG_SYSCTL */
 
 #endif	/* CONFIG_X86_64 */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vdso-fakesections.c linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso-fakesections.c
--- linux-libre-3.16-gnu/arch/x86/vdso/vdso-fakesections.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso-fakesections.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright 2014 Andy Lutomirski
- * Subject to the GNU Public License, v.2
- *
- * String table for loadable section headers.  See vdso2c.h for why
- * this exists.
- */
-
-const char fake_shstrtab[] __attribute__((section(".fake_shstrtab"))) =
-	".hash\0"
-	".dynsym\0"
-	".dynstr\0"
-	".gnu.version\0"
-	".gnu.version_d\0"
-	".dynamic\0"
-	".rodata\0"
-	".fake_shstrtab\0"  /* Yay, self-referential code. */
-	".note\0"
-	".eh_frame_hdr\0"
-	".eh_frame\0"
-	".text";
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vdso-layout.lds.S linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso-layout.lds.S
--- linux-libre-3.16-gnu/arch/x86/vdso/vdso-layout.lds.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vdso-layout.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,25 @@
 
 SECTIONS
 {
+	/*
+	 * User/kernel shared data is before the vDSO.  This may be a little
+	 * uglier than putting it after the vDSO, but it avoids issues with
+	 * non-allocatable things that dangle past the end of the PT_LOAD
+	 * segment.
+	 */
+
+	vvar_start = . - 2 * PAGE_SIZE;
+	vvar_page = vvar_start;
+
+	/* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
+#define __VVAR_KERNEL_LDS
+#include <asm/vvar.h>
+#undef __VVAR_KERNEL_LDS
+#undef EMIT_VVAR
+
+	hpet_page = vvar_start + PAGE_SIZE;
+
 	. = SIZEOF_HEADERS;
 
 	.hash		: { *(.hash) }			:text
@@ -74,31 +93,6 @@ SECTIONS
 	.altinstructions	: { *(.altinstructions) }	:text
 	.altinstr_replacement	: { *(.altinstr_replacement) }	:text
 
-	/*
-	 * The remainder of the vDSO consists of special pages that are
-	 * shared between the kernel and userspace.  It needs to be at the
-	 * end so that it doesn't overlap the mapping of the actual
-	 * vDSO image.
-	 */
-
-	. = ALIGN(PAGE_SIZE);
-	vvar_page = .;
-
-	/* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
-#define __VVAR_KERNEL_LDS
-#include <asm/vvar.h>
-#undef __VVAR_KERNEL_LDS
-#undef EMIT_VVAR
-
-	. = vvar_page + PAGE_SIZE;
-
-	hpet_page = .;
-	. = . + PAGE_SIZE;
-
-	. = ALIGN(PAGE_SIZE);
-	end_mapping = .;
-
 	/DISCARD/ : {
 		*(.discard)
 		*(.discard.*)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/vdso/vma.c linux-libre-3.17-rc7-gnu/arch/x86/vdso/vma.c
--- linux-libre-3.16-gnu/arch/x86/vdso/vma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/vdso/vma.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,7 +93,7 @@ static int map_vdso(const struct vdso_im
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long addr;
+	unsigned long addr, text_start;
 	int ret = 0;
 	static struct page *no_pages[] = {NULL};
 	static struct vm_special_mapping vvar_mapping = {
@@ -103,26 +103,28 @@ static int map_vdso(const struct vdso_im
 
 	if (calculate_addr) {
 		addr = vdso_addr(current->mm->start_stack,
-				 image->sym_end_mapping);
+				 image->size - image->sym_vvar_start);
 	} else {
 		addr = 0;
 	}
 
 	down_write(&mm->mmap_sem);
 
-	addr = get_unmapped_area(NULL, addr, image->sym_end_mapping, 0, 0);
+	addr = get_unmapped_area(NULL, addr,
+				 image->size - image->sym_vvar_start, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
 	}
 
-	current->mm->context.vdso = (void __user *)addr;
+	text_start = addr - image->sym_vvar_start;
+	current->mm->context.vdso = (void __user *)text_start;
 
 	/*
 	 * MAYWRITE to allow gdb to COW and set breakpoints
 	 */
 	vma = _install_special_mapping(mm,
-				       addr,
+				       text_start,
 				       image->size,
 				       VM_READ|VM_EXEC|
 				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
@@ -134,9 +136,9 @@ static int map_vdso(const struct vdso_im
 	}
 
 	vma = _install_special_mapping(mm,
-				       addr + image->size,
-				       image->sym_end_mapping - image->size,
-				       VM_READ,
+				       addr,
+				       -image->sym_vvar_start,
+				       VM_READ|VM_MAYREAD,
 				       &vvar_mapping);
 
 	if (IS_ERR(vma)) {
@@ -146,7 +148,7 @@ static int map_vdso(const struct vdso_im
 
 	if (image->sym_vvar_page)
 		ret = remap_pfn_range(vma,
-				      addr + image->sym_vvar_page,
+				      text_start + image->sym_vvar_page,
 				      __pa_symbol(&__vvar_page) >> PAGE_SHIFT,
 				      PAGE_SIZE,
 				      PAGE_READONLY);
@@ -157,7 +159,7 @@ static int map_vdso(const struct vdso_im
 #ifdef CONFIG_HPET_TIMER
 	if (hpet_address && image->sym_hpet_page) {
 		ret = io_remap_pfn_range(vma,
-			addr + image->sym_hpet_page,
+			text_start + image->sym_hpet_page,
 			hpet_address >> PAGE_SHIFT,
 			PAGE_SIZE,
 			pgprot_noncached(PAGE_READONLY));
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/efi.c linux-libre-3.17-rc7-gnu/arch/x86/xen/efi.c
--- linux-libre-3.16-gnu/arch/x86/xen/efi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Oracle Co., Daniel Kiper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/efi.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <xen/xen-ops.h>
+
+#include <asm/setup.h>
+
+void __init xen_efi_init(void)
+{
+	efi_system_table_t *efi_systab_xen;
+
+	efi_systab_xen = xen_efi_probe();
+
+	if (efi_systab_xen == NULL)
+		return;
+
+	strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen",
+			sizeof(boot_params.efi_info.efi_loader_signature));
+	boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
+	boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);
+
+	set_bit(EFI_BOOT, &efi.flags);
+	set_bit(EFI_PARAVIRT, &efi.flags);
+	set_bit(EFI_64BIT, &efi.flags);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/enlighten.c linux-libre-3.17-rc7-gnu/arch/x86/xen/enlighten.c
--- linux-libre-3.16-gnu/arch/x86/xen/enlighten.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/enlighten.c	2014-09-28 17:29:07.000000000 -0400
@@ -1718,6 +1718,8 @@ asmlinkage __visible void __init xen_sta
 
 	xen_setup_runstate_info(0);
 
+	xen_efi_init();
+
 	/* Start the world */
 #ifdef CONFIG_X86_32
 	i386_start_kernel();
@@ -1826,8 +1828,19 @@ static void __init xen_hvm_guest_init(vo
 	xen_hvm_init_mmu_ops();
 }
 
+static bool xen_nopv = false;
+static __init int xen_parse_nopv(char *arg)
+{
+       xen_nopv = true;
+       return 0;
+}
+early_param("xen_nopv", xen_parse_nopv);
+
 static uint32_t __init xen_hvm_platform(void)
 {
+	if (xen_nopv)
+		return 0;
+
 	if (xen_pv_domain())
 		return 0;
 
@@ -1836,6 +1849,8 @@ static uint32_t __init xen_hvm_platform(
 
 bool xen_hvm_need_lapic(void)
 {
+	if (xen_nopv)
+		return false;
 	if (xen_pv_domain())
 		return false;
 	if (!xen_hvm_domain())
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/grant-table.c linux-libre-3.17-rc7-gnu/arch/x86/xen/grant-table.c
--- linux-libre-3.16-gnu/arch/x86/xen/grant-table.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/grant-table.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,7 @@
 static struct gnttab_vm_area {
 	struct vm_struct *area;
 	pte_t **ptes;
-} gnttab_shared_vm_area, gnttab_status_vm_area;
+} gnttab_shared_vm_area;
 
 int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
 			   unsigned long max_nr_gframes,
@@ -73,43 +73,16 @@ int arch_gnttab_map_shared(unsigned long
 	return 0;
 }
 
-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
-			   unsigned long max_nr_gframes,
-			   grant_status_t **__shared)
-{
-	grant_status_t *shared = *__shared;
-	unsigned long addr;
-	unsigned long i;
-
-	if (shared == NULL)
-		*__shared = shared = gnttab_status_vm_area.area->addr;
-
-	addr = (unsigned long)shared;
-
-	for (i = 0; i < nr_gframes; i++) {
-		set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i],
-			   mfn_pte(frames[i], PAGE_KERNEL));
-		addr += PAGE_SIZE;
-	}
-
-	return 0;
-}
-
 void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
 {
-	pte_t **ptes;
 	unsigned long addr;
 	unsigned long i;
 
-	if (shared == gnttab_status_vm_area.area->addr)
-		ptes = gnttab_status_vm_area.ptes;
-	else
-		ptes = gnttab_shared_vm_area.ptes;
-
 	addr = (unsigned long)shared;
 
 	for (i = 0; i < nr_gframes; i++) {
-		set_pte_at(&init_mm, addr, ptes[i], __pte(0));
+		set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i],
+			   __pte(0));
 		addr += PAGE_SIZE;
 	}
 }
@@ -129,35 +102,12 @@ static int arch_gnttab_valloc(struct gnt
 	return 0;
 }
 
-static void arch_gnttab_vfree(struct gnttab_vm_area *area)
-{
-	free_vm_area(area->area);
-	kfree(area->ptes);
-}
-
-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
+int arch_gnttab_init(unsigned long nr_shared)
 {
-	int ret;
-
 	if (!xen_pv_domain())
 		return 0;
 
-	ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * Always allocate the space for the status frames in case
-	 * we're migrated to a host with V2 support.
-	 */
-	ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status);
-	if (ret < 0)
-		goto err;
-
-	return 0;
-  err:
-	arch_gnttab_vfree(&gnttab_shared_vm_area);
-	return -ENOMEM;
+	return arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
 }
 
 #ifdef CONFIG_XEN_PVH
@@ -168,6 +118,7 @@ static int __init xlated_setup_gnttab_pa
 {
 	struct page **pages;
 	xen_pfn_t *pfns;
+	void *vaddr;
 	int rc;
 	unsigned int i;
 	unsigned long nr_grant_frames = gnttab_max_grant_frames();
@@ -193,21 +144,20 @@ static int __init xlated_setup_gnttab_pa
 	for (i = 0; i < nr_grant_frames; i++)
 		pfns[i] = page_to_pfn(pages[i]);
 
-	rc = arch_gnttab_map_shared(pfns, nr_grant_frames, nr_grant_frames,
-				    &xen_auto_xlat_grant_frames.vaddr);
-
-	if (rc) {
+	vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL);
+	if (!vaddr) {
 		pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__,
 			nr_grant_frames, rc);
 		free_xenballooned_pages(nr_grant_frames, pages);
 		kfree(pages);
 		kfree(pfns);
-		return rc;
+		return -ENOMEM;
 	}
 	kfree(pages);
 
 	xen_auto_xlat_grant_frames.pfn = pfns;
 	xen_auto_xlat_grant_frames.count = nr_grant_frames;
+	xen_auto_xlat_grant_frames.vaddr = vaddr;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/Makefile linux-libre-3.17-rc7-gnu/arch/x86/xen/Makefile
--- linux-libre-3.16-gnu/arch/x86/xen/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -22,3 +22,4 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinl
 obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o
 obj-$(CONFIG_XEN_DOM0)		+= apic.o vga.o
 obj-$(CONFIG_SWIOTLB_XEN)	+= pci-swiotlb-xen.o
+obj-$(CONFIG_XEN_EFI)		+= efi.o
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/mmu.c linux-libre-3.17-rc7-gnu/arch/x86/xen/mmu.c
--- linux-libre-3.16-gnu/arch/x86/xen/mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1866,12 +1866,11 @@ static void __init check_pt_base(unsigne
  *
  * We can construct this by grafting the Xen provided pagetable into
  * head_64.S's preconstructed pagetables.  We copy the Xen L2's into
- * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt.  This
- * means that only the kernel has a physical mapping to start with -
- * but that's enough to get __va working.  We need to fill in the rest
- * of the physical mapping once some sort of allocator has been set
- * up.
- * NOTE: for PVH, the page tables are native.
+ * level2_ident_pgt, and level2_kernel_pgt.  This means that only the
+ * kernel has a physical mapping to start with - but that's enough to
+ * get __va working.  We need to fill in the rest of the physical
+ * mapping once some sort of allocator has been set up.  NOTE: for
+ * PVH, the page tables are native.
  */
 void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
@@ -1902,8 +1901,11 @@ void __init xen_setup_kernel_pagetable(p
 		/* L3_i[0] -> level2_ident_pgt */
 		convert_pfn_mfn(level3_ident_pgt);
 		/* L3_k[510] -> level2_kernel_pgt
-		 * L3_i[511] -> level2_fixmap_pgt */
+		 * L3_k[511] -> level2_fixmap_pgt */
 		convert_pfn_mfn(level3_kernel_pgt);
+
+		/* L3_k[511][506] -> level1_fixmap_pgt */
+		convert_pfn_mfn(level2_fixmap_pgt);
 	}
 	/* We get [511][511] and have Xen's version of level2_kernel_pgt */
 	l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
@@ -1913,21 +1915,15 @@ void __init xen_setup_kernel_pagetable(p
 	addr[1] = (unsigned long)l3;
 	addr[2] = (unsigned long)l2;
 	/* Graft it onto L4[272][0]. Note that we creating an aliasing problem:
-	 * Both L4[272][0] and L4[511][511] have entries that point to the same
+	 * Both L4[272][0] and L4[511][510] have entries that point to the same
 	 * L2 (PMD) tables. Meaning that if you modify it in __va space
 	 * it will be also modified in the __ka space! (But if you just
 	 * modify the PMD table to point to other PTE's or none, then you
 	 * are OK - which is what cleanup_highmap does) */
 	copy_page(level2_ident_pgt, l2);
-	/* Graft it onto L4[511][511] */
+	/* Graft it onto L4[511][510] */
 	copy_page(level2_kernel_pgt, l2);
 
-	/* Get [511][510] and graft that in level2_fixmap_pgt */
-	l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd);
-	l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud);
-	copy_page(level2_fixmap_pgt, l2);
-	/* Note that we don't do anything with level1_fixmap_pgt which
-	 * we don't need. */
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 		/* Make pagetable pieces RO */
 		set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
@@ -1937,6 +1933,7 @@ void __init xen_setup_kernel_pagetable(p
 		set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
 		set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
 		set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+		set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
 
 		/* Pin down new L4 */
 		pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/p2m.c linux-libre-3.17-rc7-gnu/arch/x86/xen/p2m.c
--- linux-libre-3.16-gnu/arch/x86/xen/p2m.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/p2m.c	2014-09-28 17:29:07.000000000 -0400
@@ -841,10 +841,9 @@ unsigned long __init set_phys_range_iden
 			pfn = ALIGN(pfn, P2M_PER_PAGE);
 	}
 
-	if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
+	WARN((pfn - pfn_s) != (pfn_e - pfn_s),
 		"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
-		(pfn_e - pfn_s) - (pfn - pfn_s)))
-		printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
+		(pfn_e - pfn_s) - (pfn - pfn_s));
 
 	return pfn - pfn_s;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/time.c linux-libre-3.17-rc7-gnu/arch/x86/xen/time.c
--- linux-libre-3.16-gnu/arch/x86/xen/time.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/time.c	2014-09-28 17:29:07.000000000 -0400
@@ -444,7 +444,7 @@ void xen_setup_timer(int cpu)
 
 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
 				      IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER|
-				      IRQF_FORCE_RESUME,
+				      IRQF_FORCE_RESUME|IRQF_EARLY_RESUME,
 				      name, NULL);
 	(void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/x86/xen/xen-ops.h linux-libre-3.17-rc7-gnu/arch/x86/xen/xen-ops.h
--- linux-libre-3.16-gnu/arch/x86/xen/xen-ops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/x86/xen/xen-ops.h	2014-09-28 17:29:07.000000000 -0400
@@ -105,6 +105,14 @@ static inline void __init xen_init_apic(
 }
 #endif
 
+#ifdef CONFIG_XEN_EFI
+extern void xen_efi_init(void);
+#else
+static inline void __init xen_efi_init(void)
+{
+}
+#endif
+
 /* Declare an asm function, along with symbols needed to make it
    inlineable */
 #define DECL_ASM(ret, name, ...)		\
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/boot/dts/kc705.dts linux-libre-3.17-rc7-gnu/arch/xtensa/boot/dts/kc705.dts
--- linux-libre-3.16-gnu/arch/xtensa/boot/dts/kc705.dts	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/boot/dts/kc705.dts	2014-09-28 17:29:07.000000000 -0400
@@ -4,8 +4,11 @@
 
 / {
 	compatible = "cdns,xtensa-kc705";
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000";
+	};
 	memory@0 {
 		device_type = "memory";
-		reg = <0x00000000 0x08000000>;
+		reg = <0x00000000 0x38000000>;
 	};
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/configs/common_defconfig linux-libre-3.17-rc7-gnu/arch/xtensa/configs/common_defconfig
--- linux-libre-3.16-gnu/arch/xtensa/configs/common_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/configs/common_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -66,7 +66,6 @@ CONFIG_XTENSA_ARCH_LINUX_BE=y
 CONFIG_MMU=y
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
 # CONFIG_HIGHMEM is not set
 
 #
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/configs/iss_defconfig linux-libre-3.17-rc7-gnu/arch/xtensa/configs/iss_defconfig
--- linux-libre-3.16-gnu/arch/xtensa/configs/iss_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/configs/iss_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -146,7 +146,6 @@ CONFIG_XTENSA_VARIANT_FSF=y
 # CONFIG_XTENSA_VARIANT_S6000 is not set
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
 CONFIG_XTENSA_CALIBRATE_CCOUNT=y
 CONFIG_SERIAL_CONSOLE=y
 CONFIG_XTENSA_ISS_NETWORK=y
@@ -308,7 +307,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
-CONFIG_HAVE_IDE=y
+# CONFIG_HAVE_IDE is not set
 # CONFIG_IDE is not set
 
 #
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/configs/s6105_defconfig linux-libre-3.17-rc7-gnu/arch/xtensa/configs/s6105_defconfig
--- linux-libre-3.16-gnu/arch/xtensa/configs/s6105_defconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/configs/s6105_defconfig	2014-09-28 17:29:07.000000000 -0400
@@ -109,7 +109,6 @@ CONFIG_VARIANT_IRQ_SWITCH=y
 CONFIG_XTENSA_VARIANT_S6000=y
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 CONFIG_PREEMPT=y
-# CONFIG_MATH_EMULATION is not set
 # CONFIG_HIGHMEM is not set
 CONFIG_XTENSA_CALIBRATE_CCOUNT=y
 CONFIG_SERIAL_CONSOLE=y
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/cacheflush.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/cacheflush.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/cacheflush.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/cacheflush.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,7 @@
  * specials for cache aliasing:
  *
  * __flush_invalidate_dcache_page_alias(vaddr,paddr)
+ * __invalidate_dcache_page_alias(vaddr,paddr)
  * __invalidate_icache_page_alias(vaddr,paddr)
  */
 
@@ -62,6 +63,7 @@ extern void __flush_invalidate_dcache_ra
 
 #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
 extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long);
+extern void __invalidate_dcache_page_alias(unsigned long, unsigned long);
 #else
 static inline void __flush_invalidate_dcache_page_alias(unsigned long virt,
 							unsigned long phys) { }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/fixmap.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/fixmap.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/fixmap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/fixmap.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,8 @@
  * Here we define all the compile-time 'special' virtual
  * addresses. The point is to have a constant address at
  * compile time, but to set the physical address only
- * in the boot process. We allocate these special  addresses
- * from the end of the consistent memory region backwards.
+ * in the boot process. We allocate these special addresses
+ * from the start of the consistent memory region upwards.
  * Also this lets us do fail-safe vmalloc(), we
  * can guarantee that these special addresses and
  * vmalloc()-ed addresses never overlap.
@@ -38,7 +38,8 @@ enum fixed_addresses {
 #ifdef CONFIG_HIGHMEM
 	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_BEGIN,
-	FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+	FIX_KMAP_END = FIX_KMAP_BEGIN +
+		(KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1,
 #endif
 	__end_of_fixed_addresses
 };
@@ -47,7 +48,28 @@ enum fixed_addresses {
 #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
 
-#include <asm-generic/fixmap.h>
+#define __fix_to_virt(x)	(FIXADDR_START + ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)	(((x) - FIXADDR_START) >> PAGE_SHIFT)
+
+#ifndef __ASSEMBLY__
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without translation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#endif
 
 #define kmap_get_fixmap_pte(vaddr) \
 	pte_offset_kernel( \
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/highmem.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/highmem.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/highmem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/highmem.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,19 +12,55 @@
 #ifndef _XTENSA_HIGHMEM_H
 #define _XTENSA_HIGHMEM_H
 
+#include <linux/wait.h>
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kmap_types.h>
 #include <asm/pgtable.h>
 
-#define PKMAP_BASE		(FIXADDR_START - PMD_SIZE)
-#define LAST_PKMAP		PTRS_PER_PTE
+#define PKMAP_BASE		((FIXADDR_START - \
+				  (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK)
+#define LAST_PKMAP		(PTRS_PER_PTE * DCACHE_N_COLORS)
 #define LAST_PKMAP_MASK		(LAST_PKMAP - 1)
 #define PKMAP_NR(virt)		(((virt) - PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)		(PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
 #define kmap_prot		PAGE_KERNEL
 
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+#define get_pkmap_color get_pkmap_color
+static inline int get_pkmap_color(struct page *page)
+{
+	return DCACHE_ALIAS(page_to_phys(page));
+}
+
+extern unsigned int last_pkmap_nr_arr[];
+
+static inline unsigned int get_next_pkmap_nr(unsigned int color)
+{
+	last_pkmap_nr_arr[color] =
+		(last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK;
+	return last_pkmap_nr_arr[color] + color;
+}
+
+static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color)
+{
+	return pkmap_nr < DCACHE_N_COLORS;
+}
+
+static inline int get_pkmap_entries_count(unsigned int color)
+{
+	return LAST_PKMAP / DCACHE_N_COLORS;
+}
+
+extern wait_queue_head_t pkmap_map_wait_arr[];
+
+static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color)
+{
+	return pkmap_map_wait_arr + color;
+}
+#endif
+
 extern pte_t *pkmap_page_table;
 
 void *kmap_high(struct page *page);
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/page.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/page.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/page.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/page.h	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,9 @@
 # define DCACHE_ALIAS_EQ(a,b)	((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
 #else
 # define DCACHE_ALIAS_ORDER	0
+# define DCACHE_ALIAS(a)	((void)(a), 0)
 #endif
+#define DCACHE_N_COLORS		(1 << DCACHE_ALIAS_ORDER)
 
 #if ICACHE_WAY_SIZE > PAGE_SIZE
 # define ICACHE_ALIAS_ORDER	(ICACHE_WAY_SHIFT - PAGE_SHIFT)
@@ -134,6 +136,7 @@ static inline __attribute_const__ int ge
 #endif
 
 struct page;
+struct vm_area_struct;
 extern void clear_page(void *page);
 extern void copy_page(void *to, void *from);
 
@@ -143,8 +146,15 @@ extern void copy_page(void *to, void *fr
  */
 
 #if DCACHE_WAY_SIZE > PAGE_SIZE
-extern void clear_user_page(void*, unsigned long, struct page*);
-extern void copy_user_page(void*, void*, unsigned long, struct page*);
+extern void clear_page_alias(void *vaddr, unsigned long paddr);
+extern void copy_page_alias(void *to, void *from,
+			    unsigned long to_paddr, unsigned long from_paddr);
+
+#define clear_user_highpage clear_user_highpage
+void clear_user_highpage(struct page *page, unsigned long vaddr);
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+void copy_user_highpage(struct page *to, struct page *from,
+			unsigned long vaddr, struct vm_area_struct *vma);
 #else
 # define clear_user_page(page, vaddr, pg)	clear_page(page)
 # define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/pgtable.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/pgtable.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/pgtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/pgtable.h	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,12 @@
 #define VMALLOC_START		0xC0000000
 #define VMALLOC_END		0xC7FEFFFF
 #define TLBTEMP_BASE_1		0xC7FF0000
-#define TLBTEMP_BASE_2		0xC7FF8000
+#define TLBTEMP_BASE_2		(TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
+#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
+#define TLBTEMP_SIZE		(2 * DCACHE_WAY_SIZE)
+#else
+#define TLBTEMP_SIZE		ICACHE_WAY_SIZE
+#endif
 
 /*
  * For the Xtensa architecture, the PTE layout is as follows:
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/asm/processor.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/processor.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/processor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/processor.h	2014-09-28 17:29:07.000000000 -0400
@@ -182,6 +182,7 @@ 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-3.16-gnu/arch/xtensa/include/asm/uaccess.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/uaccess.h
--- linux-libre-3.16-gnu/arch/xtensa/include/asm/uaccess.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/asm/uaccess.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,12 @@
  */
 	.macro	get_fs	ad, sp
 	GET_CURRENT(\ad,\sp)
+#if THREAD_CURRENT_DS > 1020
+	addi	\ad, \ad, TASK_THREAD
+	l32i	\ad, \ad, THREAD_CURRENT_DS - TASK_THREAD
+#else
 	l32i	\ad, \ad, THREAD_CURRENT_DS
+#endif
 	.endm
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/uapi/asm/ioctls.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/uapi/asm/ioctls.h
--- linux-libre-3.16-gnu/arch/xtensa/include/uapi/asm/ioctls.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/uapi/asm/ioctls.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,17 +28,17 @@
 #define TCSETSW		0x5403
 #define TCSETSF		0x5404
 
-#define TCGETA		_IOR('t', 23, struct termio)
-#define TCSETA		_IOW('t', 24, struct termio)
-#define TCSETAW		_IOW('t', 25, struct termio)
-#define TCSETAF		_IOW('t', 28, struct termio)
+#define TCGETA		0x80127417	/* _IOR('t', 23, struct termio) */
+#define TCSETA		0x40127418	/* _IOW('t', 24, struct termio) */
+#define TCSETAW		0x40127419	/* _IOW('t', 25, struct termio) */
+#define TCSETAF		0x4012741C	/* _IOW('t', 28, struct termio) */
 
 #define TCSBRK		_IO('t', 29)
 #define TCXONC		_IO('t', 30)
 #define TCFLSH		_IO('t', 31)
 
-#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
-#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
+#define TIOCSWINSZ	0x40087467	/* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ	0x80087468	/* _IOR('t', 104, struct winsize) */
 #define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
 #define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
 #define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
@@ -88,7 +88,6 @@
 #define TIOCSETD	_IOW('T', 35, int)
 #define TIOCGETD	_IOR('T', 36, int)
 #define TCSBRKP		_IOW('T', 37, int)   /* Needed for POSIX tcsendbreak()*/
-#define TIOCTTYGSTRUCT	_IOR('T', 38, struct tty_struct) /* For debugging only*/
 #define TIOCSBRK	_IO('T', 39) 	     /* BSD compatibility */
 #define TIOCCBRK	_IO('T', 40)	     /* BSD compatibility */
 #define TIOCGSID	_IOR('T', 41, pid_t) /* Return the session ID of FD*/
@@ -114,8 +113,10 @@
 #define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* Get line status reg. */
   /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 # define TIOCSER_TEMT    0x01		     /* Transmitter physically empty */
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config  */
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
+#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config  */
+			/* _IOR('T', 90, struct serial_multiport_struct) */
+#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */
+			/* _IOW('T', 91, struct serial_multiport_struct) */
 
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/include/uapi/asm/unistd.h linux-libre-3.17-rc7-gnu/arch/xtensa/include/uapi/asm/unistd.h
--- linux-libre-3.16-gnu/arch/xtensa/include/uapi/asm/unistd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/include/uapi/asm/unistd.h	2014-09-28 17:29:07.000000000 -0400
@@ -739,7 +739,10 @@ __SYSCALL(334, sys_sched_setattr, 2)
 #define __NR_sched_getattr			335
 __SYSCALL(335, sys_sched_getattr, 3)
 
-#define __NR_syscall_count			336
+#define __NR_renameat2				336
+__SYSCALL(336, sys_renameat2, 5)
+
+#define __NR_syscall_count			337
 
 /*
  * sysxtensa syscall handler
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/Kconfig linux-libre-3.17-rc7-gnu/arch/xtensa/Kconfig
--- linux-libre-3.16-gnu/arch/xtensa/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,24 +4,23 @@ config ZONE_DMA
 config XTENSA
 	def_bool y
 	select ARCH_WANT_FRAME_POINTERS
-	select HAVE_IDE
-	select GENERIC_ATOMIC64
-	select GENERIC_CLOCKEVENTS
-	select VIRT_TO_BUS
-	select GENERIC_IRQ_SHOW
-	select GENERIC_SCHED_CLOCK
-	select MODULES_USE_ELF_RELA
-	select GENERIC_PCI_IOMAP
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select BUILDTIME_EXTABLE_SORT
 	select CLONE_BACKWARDS
-	select IRQ_DOMAIN
-	select HAVE_OPROFILE
+	select COMMON_CLK
+	select GENERIC_ATOMIC64
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_SHOW
+	select GENERIC_PCI_IOMAP
+	select GENERIC_SCHED_CLOCK
 	select HAVE_FUNCTION_TRACER
 	select HAVE_IRQ_TIME_ACCOUNTING
+	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
-	select COMMON_CLK
+	select IRQ_DOMAIN
+	select MODULES_USE_ELF_RELA
+	select VIRT_TO_BUS
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
@@ -62,7 +61,9 @@ config TRACE_IRQFLAGS_SUPPORT
 	def_bool y
 
 config MMU
-	def_bool n
+	bool
+	default n if !XTENSA_VARIANT_CUSTOM
+	default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM
 
 config VARIANT_IRQ_SWITCH
 	def_bool n
@@ -102,8 +103,40 @@ config XTENSA_VARIANT_S6000
 	select VARIANT_IRQ_SWITCH
 	select ARCH_REQUIRE_GPIOLIB
 	select XTENSA_CALIBRATE_CCOUNT
+
+config XTENSA_VARIANT_CUSTOM
+	bool "Custom Xtensa processor configuration"
+	select MAY_HAVE_SMP
+	select HAVE_XTENSA_GPIO32
+	help
+	  Select this variant to use a custom Xtensa processor configuration.
+	  You will be prompted for a processor variant CORENAME.
 endchoice
 
+config XTENSA_VARIANT_CUSTOM_NAME
+	string "Xtensa Processor Custom Core Variant Name"
+	depends on XTENSA_VARIANT_CUSTOM
+	help
+	  Provide the name of a custom Xtensa processor variant.
+	  This CORENAME selects arch/xtensa/variant/CORENAME.
+	  Dont forget you have to select MMU if you have one.
+
+config XTENSA_VARIANT_NAME
+	string
+	default "dc232b"			if XTENSA_VARIANT_DC232B
+	default "dc233c"			if XTENSA_VARIANT_DC233C
+	default "fsf"				if XTENSA_VARIANT_FSF
+	default "s6000"				if XTENSA_VARIANT_S6000
+	default XTENSA_VARIANT_CUSTOM_NAME	if XTENSA_VARIANT_CUSTOM
+
+config XTENSA_VARIANT_MMU
+	bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)"
+	depends on XTENSA_VARIANT_CUSTOM
+	default y
+	help
+	  Build a Conventional Kernel with full MMU support,
+	  ie: it supports a TLB with auto-loading, page protection.
+
 config XTENSA_UNALIGNED_USER
 	bool "Unaligned memory access in use space"
 	help
@@ -156,13 +189,9 @@ config HOTPLUG_CPU
 
 	  Say N if you want to disable CPU hotplug.
 
-config MATH_EMULATION
-	bool "Math emulation"
-	help
-	Can we use information of configuration file?
-
 config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 	bool "Initialize Xtensa MMU inside the Linux kernel code"
+	depends on MMU
 	default y
 	help
 	  Earlier version initialized the MMU in the exception vector
@@ -192,6 +221,7 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLI
 
 config HIGHMEM
 	bool "High Memory Support"
+	depends on MMU
 	help
 	  Linux can use the full amount of RAM in the system by
 	  default. However, the default MMUv2 setup only maps the
@@ -208,6 +238,32 @@ config HIGHMEM
 
 	  If unsure, say Y.
 
+config FAST_SYSCALL_XTENSA
+	bool "Enable fast atomic syscalls"
+	default n
+	help
+	  fast_syscall_xtensa is a syscall that can make atomic operations
+	  on UP kernel when processor has no s32c1i support.
+
+	  This syscall is deprecated. It may have issues when called with
+	  invalid arguments. It is provided only for backwards compatibility.
+	  Only enable it if your userspace software requires it.
+
+	  If unsure, say N.
+
+config FAST_SYSCALL_SPILL_REGISTERS
+	bool "Enable spill registers syscall"
+	default n
+	help
+	  fast_syscall_spill_registers is a syscall that spills all active
+	  register windows of a calling userspace task onto its stack.
+
+	  This syscall is deprecated. It may have issues when called with
+	  invalid arguments. It is provided only for backwards compatibility.
+	  Only enable it if your userspace software requires it.
+
+	  If unsure, say N.
+
 endmenu
 
 config XTENSA_CALIBRATE_CCOUNT
@@ -250,12 +306,14 @@ config XTENSA_PLATFORM_ISS
 
 config XTENSA_PLATFORM_XT2000
 	bool "XT2000"
+	select HAVE_IDE
 	help
 	  XT2000 is the name of Tensilica's feature-rich emulation platform.
 	  This hardware is capable of running a full Linux distribution.
 
 config XTENSA_PLATFORM_S6105
 	bool "S6105"
+	select HAVE_IDE
 	select SERIAL_CONSOLE
 	select NO_IOPORT_MAP
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/align.S linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/align.S
--- linux-libre-3.16-gnu/arch/xtensa/kernel/align.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/align.S	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,7 @@
  * this archive for more details.
  *
  * Copyright (C) 2001 - 2005 Tensilica, Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  *
  * Rewritten by Chris Zankel <chris@zankel.net>
  *
@@ -174,6 +175,10 @@ ENTRY(fast_unaligned)
 	s32i	a0, a2, PT_AREG2
 	s32i	a3, a2, PT_AREG3
 
+	rsr	a3, excsave1
+	movi	a4, fast_unaligned_fixup
+	s32i	a4, a3, EXC_TABLE_FIXUP
+
 	/* Keep value of SAR in a0 */
 
 	rsr	a0, sar
@@ -225,10 +230,6 @@ ENTRY(fast_unaligned)
 	addx8	a5, a6, a5
 	jx	a5			# jump into table
 
-	/* Invalid instruction, CRITICAL! */
-.Linvalid_instruction_load:
-	j	.Linvalid_instruction
-
 	/* Load: Load memory address. */
 
 .Lload: movi	a3, ~3
@@ -272,18 +273,6 @@ ENTRY(fast_unaligned)
 	/* Set target register. */
 
 1:
-
-#if XCHAL_HAVE_LOOPS
-	rsr	a5, lend		# check if we reached LEND
-	bne	a7, a5, 1f
-	rsr	a5, lcount		# and LCOUNT != 0
-	beqz	a5, 1f
-	addi	a5, a5, -1		# decrement LCOUNT and set
-	rsr	a7, lbeg		# set PC to LBEGIN
-	wsr	a5, lcount
-#endif
-
-1:	wsr	a7, epc1		# skip load instruction
 	extui	a4, a4, INSN_T, 4	# extract target register
 	movi	a5, .Lload_table
 	addx8	a4, a4, a5
@@ -326,6 +315,35 @@ ENTRY(fast_unaligned)
 	mov	a3, a14		;	_j 1f;	.align 8
 	mov	a3, a15		;	_j 1f;	.align 8
 
+	/* We cannot handle this exception. */
+
+	.extern _kernel_exception
+.Linvalid_instruction_load:
+.Linvalid_instruction_store:
+
+	movi	a4, 0
+	rsr	a3, excsave1
+	s32i	a4, a3, EXC_TABLE_FIXUP
+
+	/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+
+	l32i	a8, a2, PT_AREG8
+	l32i	a7, a2, PT_AREG7
+	l32i	a6, a2, PT_AREG6
+	l32i	a5, a2, PT_AREG5
+	l32i	a4, a2, PT_AREG4
+	wsr	a0, sar
+	mov	a1, a2
+
+	rsr	a0, ps
+	bbsi.l  a0, PS_UM_BIT, 2f     # jump if user mode
+
+	movi	a0, _kernel_exception
+	jx	a0
+
+2:	movi	a0, _user_exception
+	jx	a0
+
 1: 	# a7: instruction pointer, a4: instruction, a3: value
 
 	movi	a6, 0			# mask: ffffffff:00000000
@@ -353,17 +371,6 @@ ENTRY(fast_unaligned)
 	/* Get memory address */
 
 1:
-#if XCHAL_HAVE_LOOPS
-	rsr	a4, lend		# check if we reached LEND
-	bne	a7, a4, 1f
-	rsr	a4, lcount		# and LCOUNT != 0
-	beqz	a4, 1f
-	addi	a4, a4, -1		# decrement LCOUNT and set
-	rsr	a7, lbeg		# set PC to LBEGIN
-	wsr	a4, lcount
-#endif
-
-1:	wsr	a7, epc1		# skip store instruction
 	movi	a4, ~3
 	and	a4, a4, a8		# align memory address
 
@@ -375,25 +382,25 @@ ENTRY(fast_unaligned)
 #endif
 
 	__ssa8r a8
-	__src_b	a7, a5, a6		# lo-mask  F..F0..0 (BE) 0..0F..F (LE)
+	__src_b	a8, a5, a6		# lo-mask  F..F0..0 (BE) 0..0F..F (LE)
 	__src_b	a6, a6, a5		# hi-mask  0..0F..F (BE) F..F0..0 (LE)
 #ifdef UNALIGNED_USER_EXCEPTION
 	l32e	a5, a4, -8
 #else
 	l32i	a5, a4, 0		# load lower address word
 #endif
-	and	a5, a5, a7		# mask
-	__sh	a7, a3 			# shift value
-	or	a5, a5, a7		# or with original value
+	and	a5, a5, a8		# mask
+	__sh	a8, a3 			# shift value
+	or	a5, a5, a8		# or with original value
 #ifdef UNALIGNED_USER_EXCEPTION
 	s32e	a5, a4, -8
-	l32e	a7, a4, -4
+	l32e	a8, a4, -4
 #else
 	s32i	a5, a4, 0		# store
-	l32i	a7, a4, 4		# same for upper address word
+	l32i	a8, a4, 4		# same for upper address word
 #endif
 	__sl	a5, a3
-	and	a6, a7, a6
+	and	a6, a8, a6
 	or	a6, a6, a5
 #ifdef UNALIGNED_USER_EXCEPTION
 	s32e	a6, a4, -4
@@ -401,9 +408,27 @@ ENTRY(fast_unaligned)
 	s32i	a6, a4, 4
 #endif
 
-	/* Done. restore stack and return */
-
 .Lexit:
+#if XCHAL_HAVE_LOOPS
+	rsr	a4, lend		# check if we reached LEND
+	bne	a7, a4, 1f
+	rsr	a4, lcount		# and LCOUNT != 0
+	beqz	a4, 1f
+	addi	a4, a4, -1		# decrement LCOUNT and set
+	rsr	a7, lbeg		# set PC to LBEGIN
+	wsr	a4, lcount
+#endif
+
+1:	wsr	a7, epc1		# skip emulated instruction
+
+	/* Update icount if we're single-stepping in userspace. */
+	rsr	a4, icountlevel
+	beqz	a4, 1f
+	bgeui	a4, LOCKLEVEL + 1, 1f
+	rsr	a4, icount
+	addi	a4, a4, 1
+	wsr	a4, icount
+1:
 	movi	a4, 0
 	rsr	a3, excsave1
 	s32i	a4, a3, EXC_TABLE_FIXUP
@@ -424,31 +449,40 @@ ENTRY(fast_unaligned)
 	l32i	a2, a2, PT_AREG2
 	rfe
 
-	/* We cannot handle this exception. */
+ENDPROC(fast_unaligned)
 
-	.extern _kernel_exception
-.Linvalid_instruction_store:
-.Linvalid_instruction:
+ENTRY(fast_unaligned_fixup)
 
-	/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+	l32i	a2, a3, EXC_TABLE_DOUBLE_SAVE
+	wsr	a3, excsave1
 
 	l32i	a8, a2, PT_AREG8
 	l32i	a7, a2, PT_AREG7
 	l32i	a6, a2, PT_AREG6
 	l32i	a5, a2, PT_AREG5
 	l32i	a4, a2, PT_AREG4
+	l32i	a0, a2, PT_AREG2
+	xsr	a0, depc			# restore depc and a0
 	wsr	a0, sar
-	mov	a1, a2
+
+	rsr	a0, exccause
+	s32i	a0, a2, PT_DEPC			# mark as a regular exception
 
 	rsr	a0, ps
-	bbsi.l  a2, PS_UM_BIT, 1f     # jump if user mode
+	bbsi.l  a0, PS_UM_BIT, 1f		# jump if user mode
 
-	movi	a0, _kernel_exception
+	rsr	a0, exccause
+	addx4	a0, a0, a3              	# find entry in table
+	l32i	a0, a0, EXC_TABLE_FAST_KERNEL   # load handler
+	l32i	a3, a2, PT_AREG3
 	jx	a0
-
-1:	movi	a0, _user_exception
+1:
+	rsr	a0, exccause
+	addx4	a0, a0, a3              	# find entry in table
+	l32i	a0, a0, EXC_TABLE_FAST_USER     # load handler
+	l32i	a3, a2, PT_AREG3
 	jx	a0
 
-ENDPROC(fast_unaligned)
+ENDPROC(fast_unaligned_fixup)
 
 #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/entry.S linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/entry.S
--- linux-libre-3.16-gnu/arch/xtensa/kernel/entry.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/entry.S	2014-09-28 17:29:07.000000000 -0400
@@ -986,6 +986,8 @@ ENDPROC(fast_syscall_unrecoverable)
  *		j done
  */
 
+#ifdef CONFIG_FAST_SYSCALL_XTENSA
+
 #define TRY								\
 	.section __ex_table, "a";					\
 	.word	66f, 67f;						\
@@ -1001,9 +1003,8 @@ ENTRY(fast_syscall_xtensa)
 	movi	a7, 4			# sizeof(unsigned int)
 	access_ok a3, a7, a0, a2, .Leac	# a0: scratch reg, a2: sp
 
-	addi	a6, a6, -1		# assuming SYS_XTENSA_ATOMIC_SET = 1
-	_bgeui	a6, SYS_XTENSA_COUNT - 1, .Lill
-	_bnei	a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
+	_bgeui	a6, SYS_XTENSA_COUNT, .Lill
+	_bnei	a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp
 
 	/* Fall through for ATOMIC_CMP_SWP. */
 
@@ -1015,27 +1016,26 @@ TRY	s32i	a5, a3, 0		# different, modify
 	l32i	a7, a2, PT_AREG7	# restore a7
 	l32i	a0, a2, PT_AREG0	# restore a0
 	movi	a2, 1			# and return 1
-	addi	a6, a6, 1		# restore a6 (really necessary?)
 	rfe
 
 1:	l32i	a7, a2, PT_AREG7	# restore a7
 	l32i	a0, a2, PT_AREG0	# restore a0
 	movi	a2, 0			# return 0 (note that we cannot set
-	addi	a6, a6, 1		# restore a6 (really necessary?)
 	rfe
 
 .Lnswp:	/* Atomic set, add, and exg_add. */
 
 TRY	l32i	a7, a3, 0		# orig
+	addi	a6, a6, -SYS_XTENSA_ATOMIC_SET
 	add	a0, a4, a7		# + arg
 	moveqz	a0, a4, a6		# set
+	addi	a6, a6, SYS_XTENSA_ATOMIC_SET
 TRY	s32i	a0, a3, 0		# write new value
 
 	mov	a0, a2
 	mov	a2, a7
 	l32i	a7, a0, PT_AREG7	# restore a7
 	l32i	a0, a0, PT_AREG0	# restore a0
-	addi	a6, a6, 1		# restore a6 (really necessary?)
 	rfe
 
 CATCH
@@ -1044,13 +1044,25 @@ CATCH
 	movi	a2, -EFAULT
 	rfe
 
-.Lill:	l32i	a7, a2, PT_AREG0	# restore a7
+.Lill:	l32i	a7, a2, PT_AREG7	# restore a7
 	l32i	a0, a2, PT_AREG0	# restore a0
 	movi	a2, -EINVAL
 	rfe
 
 ENDPROC(fast_syscall_xtensa)
 
+#else /* CONFIG_FAST_SYSCALL_XTENSA */
+
+ENTRY(fast_syscall_xtensa)
+
+	l32i    a0, a2, PT_AREG0        # restore a0
+	movi	a2, -ENOSYS
+	rfe
+
+ENDPROC(fast_syscall_xtensa)
+
+#endif /* CONFIG_FAST_SYSCALL_XTENSA */
+
 
 /* fast_syscall_spill_registers.
  *
@@ -1066,6 +1078,8 @@ ENDPROC(fast_syscall_xtensa)
  * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
  */
 
+#ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS
+
 ENTRY(fast_syscall_spill_registers)
 
 	/* Register a FIXUP handler (pass current wb as a parameter) */
@@ -1400,6 +1414,18 @@ ENTRY(fast_syscall_spill_registers_fixup
 
 ENDPROC(fast_syscall_spill_registers_fixup_return)
 
+#else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
+
+ENTRY(fast_syscall_spill_registers)
+
+	l32i    a0, a2, PT_AREG0        # restore a0
+	movi	a2, -ENOSYS
+	rfe
+
+ENDPROC(fast_syscall_spill_registers)
+
+#endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
+
 #ifdef CONFIG_MMU
 /*
  * We should never get here. Bail out!
@@ -1565,7 +1591,7 @@ ENTRY(fast_second_level_miss)
 	rsr	a0, excvaddr
 	bltu	a0, a3, 2f
 
-	addi	a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
+	addi	a1, a0, -TLBTEMP_SIZE
 	bgeu	a1, a3, 2f
 
 	/* Check if we have to restore an ITLB mapping. */
@@ -1820,7 +1846,6 @@ ENTRY(_switch_to)
 
 	entry	a1, 16
 
-	mov	a10, a2			# preserve 'prev' (a2)
 	mov	a11, a3			# and 'next' (a3)
 
 	l32i	a4, a2, TASK_THREAD_INFO
@@ -1828,8 +1853,14 @@ ENTRY(_switch_to)
 
 	save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
-	s32i	a0, a10, THREAD_RA	# save return address
-	s32i	a1, a10, THREAD_SP	# save stack pointer
+#if THREAD_RA > 1020 || THREAD_SP > 1020
+	addi	a10, a2, TASK_THREAD
+	s32i	a0, a10, THREAD_RA - TASK_THREAD	# save return address
+	s32i	a1, a10, THREAD_SP - TASK_THREAD	# save stack pointer
+#else
+	s32i	a0, a2, THREAD_RA	# save return address
+	s32i	a1, a2, THREAD_SP	# save stack pointer
+#endif
 
 	/* Disable ints while we manipulate the stack pointer. */
 
@@ -1870,7 +1901,6 @@ ENTRY(_switch_to)
 	load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
 	wsr	a14, ps
-	mov	a2, a10			# return 'prev'
 	rsync
 
 	retw
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/pci-dma.c linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/pci-dma.c
--- linux-libre-3.16-gnu/arch/xtensa/kernel/pci-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/pci-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,si
 
 	/* We currently don't support coherent memory outside KSEG */
 
-	if (ret < XCHAL_KSEG_CACHED_VADDR
-	    || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
-		BUG();
+	BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
+	       ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
 
 	if (ret != 0) {
@@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent);
 void dma_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+	unsigned long addr = (unsigned long)vaddr +
+		XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
 
-	if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
-		BUG();
+	BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR ||
+	       addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
 	free_pages(addr, get_order(size));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/signal.c linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/signal.c
--- linux-libre-3.16-gnu/arch/xtensa/kernel/signal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/signal.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,17 +331,17 @@ gen_return_code(unsigned char *codemem)
 }
 
 
-static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-		       sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+		       struct pt_regs *regs)
 {
 	struct rt_sigframe *frame;
-	int err = 0;
+	int err = 0, sig = ksig->sig;
 	int signal;
 	unsigned long sp, ra, tp;
 
 	sp = regs->areg[1];
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
+	if ((ksig->ka.sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
 		sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
@@ -351,7 +351,7 @@ static int setup_frame(int sig, struct k
 		panic ("Double exception sys_sigreturn\n");
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
-		goto give_sigsegv;
+		return -EFAULT;
 	}
 
 	signal = current_thread_info()->exec_domain
@@ -360,8 +360,8 @@ static int setup_frame(int sig, struct k
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	}
 
 	/* Create the user context.  */
@@ -372,8 +372,8 @@ static int setup_frame(int sig, struct k
 	err |= setup_sigcontext(frame, regs);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		ra = (unsigned long)ka->sa.sa_restorer;
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		ra = (unsigned long)ksig->ka.sa.sa_restorer;
 	} else {
 
 		/* Create sys_rt_sigreturn syscall in stack frame */
@@ -381,7 +381,7 @@ static int setup_frame(int sig, struct k
 		err |= gen_return_code(frame->retcode);
 
 		if (err) {
-			goto give_sigsegv;
+			return -EFAULT;
 		}
 		ra = (unsigned long) frame->retcode;
 	}
@@ -393,7 +393,7 @@ static int setup_frame(int sig, struct k
 
 	/* Set up registers for signal handler; preserve the threadptr */
 	tp = regs->threadptr;
-	start_thread(regs, (unsigned long) ka->sa.sa_handler,
+	start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
 		     (unsigned long) frame);
 
 	/* Set up a stack frame for a call4
@@ -416,10 +416,6 @@ static int setup_frame(int sig, struct k
 #endif
 
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 
 /*
@@ -433,15 +429,11 @@ give_sigsegv:
  */
 static void do_signal(struct pt_regs *regs)
 {
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	task_pt_regs(current)->icountlevel = 0;
 
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
 		int ret;
 
 		/* Are we from a system call? */
@@ -457,7 +449,7 @@ static void do_signal(struct pt_regs *re
 					break;
 
 				case -ERESTARTSYS:
-					if (!(ka.sa.sa_flags & SA_RESTART)) {
+					if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
 						regs->areg[2] = -EINTR;
 						break;
 					}
@@ -476,11 +468,8 @@ static void do_signal(struct pt_regs *re
 
 		/* Whee!  Actually deliver the signal.  */
 		/* Set up the stack frame */
-		ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs);
-		if (ret)
-			return;
-
-		signal_delivered(signr, &info, &ka, regs, 0);
+		ret = setup_frame(&ksig, sigmask_to_save(), regs);
+		signal_setup_done(ret, &ksig, 0);
 		if (current->ptrace & PT_SINGLESTEP)
 			task_pt_regs(current)->icountlevel = 1;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/smp.c linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/smp.c
--- linux-libre-3.16-gnu/arch/xtensa/kernel/smp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/smp.c	2014-09-28 17:29:07.000000000 -0400
@@ -571,6 +571,7 @@ void flush_icache_range(unsigned long st
 	};
 	on_each_cpu(ipi_flush_icache_range, &fd, 1);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 /* ------------------------------------------------------------------------- */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/traps.c linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/traps.c
--- linux-libre-3.16-gnu/arch/xtensa/kernel/traps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/traps.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 #ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,		USER,	   fast_unaligned },
-#else
-{ EXCCAUSE_UNALIGNED,		0,	   do_unaligned_user },
 #endif
+{ EXCCAUSE_UNALIGNED,		0,	   do_unaligned_user },
 { EXCCAUSE_UNALIGNED,		KRNL,	   fast_unaligned },
 #endif
 #ifdef CONFIG_MMU
@@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *r
  */
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifndef CONFIG_XTENSA_UNALIGNED_USER
 void
 do_unaligned_user (struct pt_regs *regs)
 {
@@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs)
 
 }
 #endif
-#endif
 
 void
 do_debug(struct pt_regs *regs)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/vectors.S linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/vectors.S
--- linux-libre-3.16-gnu/arch/xtensa/kernel/vectors.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/vectors.S	2014-09-28 17:29:07.000000000 -0400
@@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow:
 	s32i	a0, a2, PT_DEPC
 
 _DoubleExceptionVector_handle_exception:
+	addi	a0, a0, -EXCCAUSE_UNALIGNED
+	beqz	a0, 2f
 	addx4	a0, a0, a3
-	l32i	a0, a0, EXC_TABLE_FAST_USER
+	l32i	a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED
+	xsr	a3, excsave1
+	jx	a0
+2:
+	movi	a0, user_exception
 	xsr	a3, excsave1
 	jx	a0
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/kernel/vmlinux.lds.S linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/vmlinux.lds.S
--- linux-libre-3.16-gnu/arch/xtensa/kernel/vmlinux.lds.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/kernel/vmlinux.lds.S	2014-09-28 17:29:07.000000000 -0400
@@ -269,13 +269,13 @@ SECTIONS
 		  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
 		  .DoubleExceptionVector.literal,
-		  DOUBLEEXC_VECTOR_VADDR - 40,
+		  DOUBLEEXC_VECTOR_VADDR - 48,
 		  SIZEOF(.UserExceptionVector.text),
 		  .UserExceptionVector.text)
   SECTION_VECTOR (_DoubleExceptionVector_text,
 		  .DoubleExceptionVector.text,
 		  DOUBLEEXC_VECTOR_VADDR,
-		  40,
+		  48,
 		  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/Makefile linux-libre-3.17-rc7-gnu/arch/xtensa/Makefile
--- linux-libre-3.16-gnu/arch/xtensa/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
 # for more details.
 #
 # Copyright (C) 2001 - 2005  Tensilica Inc.
+# Copyright (C) 2014 Cadence Design Systems Inc.
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
@@ -13,11 +14,7 @@
 # Core configuration.
 # (Use VAR=<xtensa_config> to use another default compiler.)
 
-variant-$(CONFIG_XTENSA_VARIANT_FSF)		:= fsf
-variant-$(CONFIG_XTENSA_VARIANT_DC232B)		:= dc232b
-variant-$(CONFIG_XTENSA_VARIANT_DC233C)		:= dc233c
-variant-$(CONFIG_XTENSA_VARIANT_S6000)		:= s6000
-variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM)	:= custom
+variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME))
 
 VARIANT = $(variant-y)
 export VARIANT
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/mm/cache.c linux-libre-3.17-rc7-gnu/arch/xtensa/mm/cache.c
--- linux-libre-3.16-gnu/arch/xtensa/mm/cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/mm/cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,9 +59,68 @@
  *
  */
 
-#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM)
-#error "HIGHMEM is not supported on cores with aliasing cache."
-#endif
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+static inline void kmap_invalidate_coherent(struct page *page,
+					    unsigned long vaddr)
+{
+	if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
+		unsigned long kvaddr;
+
+		if (!PageHighMem(page)) {
+			kvaddr = (unsigned long)page_to_virt(page);
+
+			__invalidate_dcache_page(kvaddr);
+		} else {
+			kvaddr = TLBTEMP_BASE_1 +
+				(page_to_phys(page) & DCACHE_ALIAS_MASK);
+
+			__invalidate_dcache_page_alias(kvaddr,
+						       page_to_phys(page));
+		}
+	}
+}
+
+static inline void *coherent_kvaddr(struct page *page, unsigned long base,
+				    unsigned long vaddr, unsigned long *paddr)
+{
+	if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
+		*paddr = page_to_phys(page);
+		return (void *)(base + (vaddr & DCACHE_ALIAS_MASK));
+	} else {
+		*paddr = 0;
+		return page_to_virt(page);
+	}
+}
+
+void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+	unsigned long paddr;
+	void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
+
+	pagefault_disable();
+	kmap_invalidate_coherent(page, vaddr);
+	set_bit(PG_arch_1, &page->flags);
+	clear_page_alias(kvaddr, paddr);
+	pagefault_enable();
+}
+
+void copy_user_highpage(struct page *dst, struct page *src,
+			unsigned long vaddr, struct vm_area_struct *vma)
+{
+	unsigned long dst_paddr, src_paddr;
+	void *dst_vaddr = coherent_kvaddr(dst, TLBTEMP_BASE_1, vaddr,
+					  &dst_paddr);
+	void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
+					  &src_paddr);
+
+	pagefault_disable();
+	kmap_invalidate_coherent(dst, vaddr);
+	set_bit(PG_arch_1, &dst->flags);
+	copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
+	pagefault_enable();
+}
+
+#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
 
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
@@ -103,7 +162,8 @@ void flush_dcache_page(struct page *page
 		if (!alias && !mapping)
 			return;
 
-		__flush_invalidate_dcache_page((long)page_address(page));
+		virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
+		__flush_invalidate_dcache_page_alias(virt, phys);
 
 		virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK);
 
@@ -168,13 +228,12 @@ update_mmu_cache(struct vm_area_struct *
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
 	if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
-
-		unsigned long paddr = (unsigned long) page_address(page);
 		unsigned long phys = page_to_phys(page);
-		unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
-
-		__flush_invalidate_dcache_page(paddr);
+		unsigned long tmp;
 
+		tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
+		__flush_invalidate_dcache_page_alias(tmp, phys);
+		tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
 		__flush_invalidate_dcache_page_alias(tmp, phys);
 		__invalidate_icache_page_alias(tmp, phys);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/mm/highmem.c linux-libre-3.17-rc7-gnu/arch/xtensa/mm/highmem.c
--- linux-libre-3.16-gnu/arch/xtensa/mm/highmem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/mm/highmem.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,23 +14,45 @@
 
 static pte_t *kmap_pte;
 
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
+wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
+
+static void __init kmap_waitqueues_init(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
+		init_waitqueue_head(pkmap_map_wait_arr + i);
+}
+#else
+static inline void kmap_waitqueues_init(void)
+{
+}
+#endif
+
+static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
+{
+	return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS +
+		color;
+}
+
 void *kmap_atomic(struct page *page)
 {
 	enum fixed_addresses idx;
 	unsigned long vaddr;
-	int type;
 
 	pagefault_disable();
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	type = kmap_atomic_idx_push();
-	idx = type + KM_TYPE_NR * smp_processor_id();
+	idx = kmap_idx(kmap_atomic_idx_push(),
+		       DCACHE_ALIAS(page_to_phys(page)));
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
-	BUG_ON(!pte_none(*(kmap_pte - idx)));
+	BUG_ON(!pte_none(*(kmap_pte + idx)));
 #endif
-	set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
+	set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC));
 
 	return (void *)vaddr;
 }
@@ -38,12 +60,10 @@ EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
-	int idx, type;
-
 	if (kvaddr >= (void *)FIXADDR_START &&
 	    kvaddr < (void *)FIXADDR_TOP) {
-		type = kmap_atomic_idx();
-		idx = type + KM_TYPE_NR * smp_processor_id();
+		int idx = kmap_idx(kmap_atomic_idx(),
+				   DCACHE_ALIAS((unsigned long)kvaddr));
 
 		/*
 		 * Force other mappings to Oops if they'll try to access this
@@ -51,7 +71,7 @@ void __kunmap_atomic(void *kvaddr)
 		 * is a bad idea also, in case the page changes cacheability
 		 * attributes or becomes a protected page in a hypervisor.
 		 */
-		pte_clear(&init_mm, kvaddr, kmap_pte - idx);
+		pte_clear(&init_mm, kvaddr, kmap_pte + idx);
 		local_flush_tlb_kernel_range((unsigned long)kvaddr,
 					     (unsigned long)kvaddr + PAGE_SIZE);
 
@@ -69,4 +89,5 @@ void __init kmap_init(void)
 	/* cache the first kmap pte */
 	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
 	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+	kmap_waitqueues_init();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/mm/misc.S linux-libre-3.17-rc7-gnu/arch/xtensa/mm/misc.S
--- linux-libre-3.16-gnu/arch/xtensa/mm/misc.S	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/mm/misc.S	2014-09-28 17:29:07.000000000 -0400
@@ -110,41 +110,24 @@ ENTRY(__tlbtemp_mapping_start)
 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
 
 /*
- * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
- *                     a2              a3                 a4
+ * clear_page_alias(void *addr, unsigned long paddr)
+ *                     a2              a3
  */
 
-ENTRY(clear_user_page)
+ENTRY(clear_page_alias)
 
 	entry	a1, 32
 
-	/* Mark page dirty and determine alias. */
-
-	movi	a7, (1 << PG_ARCH_1)
-	l32i	a5, a4, PAGE_FLAGS
-	xor	a6, a2, a3
-	extui	a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-	extui	a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-	or	a5, a5, a7
-	slli	a3, a3, PAGE_SHIFT
-	s32i	a5, a4, PAGE_FLAGS
-
-	/* Skip setting up a temporary DTLB if not aliased. */
-
-	beqz	a6, 1f
-
-	/* Invalidate kernel page. */
-
-	mov	a10, a2
-	call8	__invalidate_dcache_page
+	/* Skip setting up a temporary DTLB if not aliased low page. */
 
-	/* Setup a temporary DTLB with the color of the VPN */
+	movi	a5, PAGE_OFFSET
+	movi	a6, 0
+	beqz	a3, 1f
 
-	movi	a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
-	movi	a5, TLBTEMP_BASE_1			# virt
-	add	a6, a2, a4				# ppn
-	add	a2, a5, a3				# add 'color'
+	/* Setup a temporary DTLB for the addr. */
 
+	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
+	mov	a4, a2
 	wdtlb	a6, a2
 	dsync
 
@@ -165,62 +148,43 @@ ENTRY(clear_user_page)
 
 	/* We need to invalidate the temporary idtlb entry, if any. */
 
-1:	addi	a2, a2, -PAGE_SIZE
-	idtlb	a2
+1:	idtlb	a4
 	dsync
 
 	retw
 
-ENDPROC(clear_user_page)
+ENDPROC(clear_page_alias)
 
 /*
- * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
- *                    a2          a3	        a4		    a5
+ * copy_page_alias(void *to, void *from,
+ *			a2	  a3
+ *                 unsigned long to_paddr, unsigned long from_paddr)
+ *	        		 a4			 a5
  */
 
-ENTRY(copy_user_page)
+ENTRY(copy_page_alias)
 
 	entry	a1, 32
 
-	/* Mark page dirty and determine alias for destination. */
-
-	movi	a8, (1 << PG_ARCH_1)
-	l32i	a9, a5, PAGE_FLAGS
-	xor	a6, a2, a4
-	xor	a7, a3, a4
-	extui	a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-	extui	a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-	extui	a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-	or	a9, a9, a8
-	slli	a4, a4, PAGE_SHIFT
-	s32i	a9, a5, PAGE_FLAGS
-	movi	a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
-
-	beqz	a6, 1f
-
-	/* Invalidate dcache */
-
-	mov	a10, a2
-	call8	__invalidate_dcache_page
+	/* Skip setting up a temporary DTLB for destination if not aliased. */
 
-	/* Setup a temporary DTLB with a matching color. */
+	movi	a6, 0
+	movi	a7, 0
+	beqz	a4, 1f
 
-	movi	a8, TLBTEMP_BASE_1			# base
-	add	a6, a2, a5				# ppn
-	add	a2, a8, a4				# add 'color'
+	/* Setup a temporary DTLB for destination. */
 
+	addi	a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
 	wdtlb	a6, a2
 	dsync
 
-	/* Skip setting up a temporary DTLB for destination if not aliased. */
+	/* Skip setting up a temporary DTLB for source if not aliased. */
 
-1:	beqz	a7, 1f
+1:	beqz	a5, 1f
 
-	/* Setup a temporary DTLB with a matching color. */
+	/* Setup a temporary DTLB for source. */
 
-	movi	a8, TLBTEMP_BASE_2			# base
-	add	a7, a3, a5				# ppn
-	add	a3, a8, a4
+	addi	a7, a5, PAGE_KERNEL
 	addi	a8, a3, 1				# way1
 
 	wdtlb	a7, a8
@@ -271,7 +235,7 @@ ENTRY(copy_user_page)
 
 	retw
 
-ENDPROC(copy_user_page)
+ENDPROC(copy_page_alias)
 
 #endif
 
@@ -300,6 +264,30 @@ ENTRY(__flush_invalidate_dcache_page_ali
 	retw
 
 ENDPROC(__flush_invalidate_dcache_page_alias)
+
+/*
+ * void __invalidate_dcache_page_alias (addr, phys)
+ *                                       a2    a3
+ */
+
+ENTRY(__invalidate_dcache_page_alias)
+
+	entry	sp, 16
+
+	movi	a7, 0			# required for exception handler
+	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
+	mov	a4, a2
+	wdtlb	a6, a2
+	dsync
+
+	___invalidate_dcache_page a2 a3
+
+	idtlb	a4
+	dsync
+
+	retw
+
+ENDPROC(__invalidate_dcache_page_alias)
 #endif
 
 ENTRY(__tlbtemp_mapping_itlb)
diff -druNp --no-dereference linux-libre-3.16-gnu/arch/xtensa/mm/mmu.c linux-libre-3.17-rc7-gnu/arch/xtensa/mm/mmu.c
--- linux-libre-3.16-gnu/arch/xtensa/mm/mmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/arch/xtensa/mm/mmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,32 +18,38 @@
 #include <asm/io.h>
 
 #if defined(CONFIG_HIGHMEM)
-static void * __init init_pmd(unsigned long vaddr)
+static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
 {
 	pgd_t *pgd = pgd_offset_k(vaddr);
 	pmd_t *pmd = pmd_offset(pgd, vaddr);
+	pte_t *pte;
+	unsigned long i;
 
-	if (pmd_none(*pmd)) {
-		unsigned i;
-		pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
+	n_pages = ALIGN(n_pages, PTRS_PER_PTE);
 
-		for (i = 0; i < 1024; i++)
-			pte_clear(NULL, 0, pte + i);
+	pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n",
+		 __func__, vaddr, n_pages);
 
-		set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
-		BUG_ON(pte != pte_offset_kernel(pmd, 0));
-		pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
-			 __func__, vaddr, pmd, pte);
-		return pte;
-	} else {
-		return pte_offset_kernel(pmd, 0);
+	pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t));
+
+	for (i = 0; i < n_pages; ++i)
+		pte_clear(NULL, 0, pte + i);
+
+	for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) {
+		pte_t *cur_pte = pte + i;
+
+		BUG_ON(!pmd_none(*pmd));
+		set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK));
+		BUG_ON(cur_pte != pte_offset_kernel(pmd, 0));
+		pr_debug("%s: pmd: 0x%p, pte: 0x%p\n",
+			 __func__, pmd, cur_pte);
 	}
+	return pte;
 }
 
 static void __init fixedrange_init(void)
 {
-	BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
-	init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
+	init_pmd(__fix_to_virt(0), __end_of_fixed_addresses);
 }
 #endif
 
@@ -52,7 +58,7 @@ void __init paging_init(void)
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
 #ifdef CONFIG_HIGHMEM
 	fixedrange_init();
-	pkmap_page_table = init_pmd(PKMAP_BASE);
+	pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP);
 	kmap_init();
 #endif
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/block/bio.c linux-libre-3.17-rc7-gnu/block/bio.c
--- linux-libre-3.16-gnu/block/bio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/bio.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,7 +112,8 @@ static struct kmem_cache *bio_find_or_cr
 	bslab = &bio_slabs[entry];
 
 	snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry);
-	slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL);
+	slab = kmem_cache_create(bslab->name, sz, ARCH_KMALLOC_MINALIGN,
+				 SLAB_HWCACHE_ALIGN, NULL);
 	if (!slab)
 		goto out_unlock;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/block/bio-integrity.c linux-libre-3.17-rc7-gnu/block/bio-integrity.c
--- linux-libre-3.16-gnu/block/bio-integrity.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/bio-integrity.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,8 +70,10 @@ struct bio_integrity_payload *bio_integr
 					  bs->bvec_integrity_pool);
 		if (!bip->bip_vec)
 			goto err;
+		bip->bip_max_vcnt = bvec_nr_vecs(idx);
 	} else {
 		bip->bip_vec = bip->bip_inline_vecs;
+		bip->bip_max_vcnt = inline_vecs;
 	}
 
 	bip->bip_slab = idx;
@@ -114,14 +116,6 @@ void bio_integrity_free(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_integrity_free);
 
-static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip)
-{
-	if (bip->bip_slab == BIO_POOL_NONE)
-		return BIP_INLINE_VECS;
-
-	return bvec_nr_vecs(bip->bip_slab);
-}
-
 /**
  * bio_integrity_add_page - Attach integrity metadata
  * @bio:	bio to update
@@ -137,7 +131,7 @@ int bio_integrity_add_page(struct bio *b
 	struct bio_integrity_payload *bip = bio->bi_integrity;
 	struct bio_vec *iv;
 
-	if (bip->bip_vcnt >= bip_integrity_vecs(bip)) {
+	if (bip->bip_vcnt >= bip->bip_max_vcnt) {
 		printk(KERN_ERR "%s: bip_vec full\n", __func__);
 		return 0;
 	}
@@ -526,7 +520,7 @@ void bio_integrity_endio(struct bio *bio
 	 */
 	if (error) {
 		bio->bi_end_io = bip->bip_end_io;
-		bio_endio(bio, error);
+		bio_endio_nodec(bio, error);
 
 		return;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-cgroup.c linux-libre-3.17-rc7-gnu/block/blk-cgroup.c
--- linux-libre-3.16-gnu/block/blk-cgroup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-cgroup.c	2014-09-28 17:29:07.000000000 -0400
@@ -928,7 +928,15 @@ struct cgroup_subsys blkio_cgrp_subsys =
 	.css_offline = blkcg_css_offline,
 	.css_free = blkcg_css_free,
 	.can_attach = blkcg_can_attach,
-	.base_cftypes = blkcg_files,
+	.legacy_cftypes = blkcg_files,
+#ifdef CONFIG_MEMCG
+	/*
+	 * This ensures that, if available, memcg is automatically enabled
+	 * together on the default hierarchy so that the owner cgroup can
+	 * be retrieved from writeback pages.
+	 */
+	.depends_on = 1 << memory_cgrp_id,
+#endif
 };
 EXPORT_SYMBOL_GPL(blkio_cgrp_subsys);
 
@@ -1120,7 +1128,8 @@ int blkcg_policy_register(struct blkcg_p
 
 	/* everything is in place, add intf files for the new policy */
 	if (pol->cftypes)
-		WARN_ON(cgroup_add_cftypes(&blkio_cgrp_subsys, pol->cftypes));
+		WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
+						  pol->cftypes));
 	ret = 0;
 out_unlock:
 	mutex_unlock(&blkcg_pol_mutex);
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-core.c linux-libre-3.17-rc7-gnu/block/blk-core.c
--- linux-libre-3.16-gnu/block/blk-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -438,14 +438,17 @@ static void __blk_drain_queue(struct req
  */
 void blk_queue_bypass_start(struct request_queue *q)
 {
-	bool drain;
-
 	spin_lock_irq(q->queue_lock);
-	drain = !q->bypass_depth++;
+	q->bypass_depth++;
 	queue_flag_set(QUEUE_FLAG_BYPASS, q);
 	spin_unlock_irq(q->queue_lock);
 
-	if (drain) {
+	/*
+	 * Queues start drained.  Skip actual draining till init is
+	 * complete.  This avoids lenghty delays during queue init which
+	 * can happen many times during boot.
+	 */
+	if (blk_queue_init_done(q)) {
 		spin_lock_irq(q->queue_lock);
 		__blk_drain_queue(q, false);
 		spin_unlock_irq(q->queue_lock);
@@ -511,7 +514,7 @@ void blk_cleanup_queue(struct request_qu
 	 * prevent that q->request_fn() gets invoked after draining finished.
 	 */
 	if (q->mq_ops) {
-		blk_mq_drain_queue(q);
+		blk_mq_freeze_queue(q);
 		spin_lock_irq(lock);
 	} else {
 		spin_lock_irq(lock);
@@ -1249,7 +1252,6 @@ void blk_rq_set_block_pc(struct request
 	rq->__sector = (sector_t) -1;
 	rq->bio = rq->biotail = NULL;
 	memset(rq->__cmd, 0, sizeof(rq->__cmd));
-	rq->cmd = rq->__cmd;
 }
 EXPORT_SYMBOL(blk_rq_set_block_pc);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-exec.c linux-libre-3.17-rc7-gnu/block/blk-exec.c
--- linux-libre-3.16-gnu/block/blk-exec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-exec.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,7 @@ void blk_execute_rq_nowait(struct reques
 	bool is_pm_resume;
 
 	WARN_ON(irqs_disabled());
+	WARN_ON(rq->cmd_type == REQ_TYPE_FS);
 
 	rq->rq_disk = bd_disk;
 	rq->end_io = done;
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-merge.c linux-libre-3.17-rc7-gnu/block/blk-merge.c
--- linux-libre-3.16-gnu/block/blk-merge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-merge.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,10 +10,11 @@
 #include "blk.h"
 
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
-					     struct bio *bio)
+					     struct bio *bio,
+					     bool no_sg_merge)
 {
 	struct bio_vec bv, bvprv = { NULL };
-	int cluster, high, highprv = 1, no_sg_merge;
+	int cluster, high, highprv = 1;
 	unsigned int seg_size, nr_phys_segs;
 	struct bio *fbio, *bbio;
 	struct bvec_iter iter;
@@ -35,7 +36,6 @@ static unsigned int __blk_recalc_rq_segm
 	cluster = blk_queue_cluster(q);
 	seg_size = 0;
 	nr_phys_segs = 0;
-	no_sg_merge = test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags);
 	high = 0;
 	for_each_bio(bio) {
 		bio_for_each_segment(bv, bio, iter) {
@@ -88,18 +88,23 @@ new_segment:
 
 void blk_recalc_rq_segments(struct request *rq)
 {
-	rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio);
+	bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE,
+			&rq->q->queue_flags);
+
+	rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio,
+			no_sg_merge);
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-	if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags))
+	if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) &&
+			bio->bi_vcnt < queue_max_segments(q))
 		bio->bi_phys_segments = bio->bi_vcnt;
 	else {
 		struct bio *nxt = bio->bi_next;
 
 		bio->bi_next = NULL;
-		bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio);
+		bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, false);
 		bio->bi_next = nxt;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-mq.c linux-libre-3.17-rc7-gnu/block/blk-mq.c
--- linux-libre-3.16-gnu/block/blk-mq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-mq.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,83 +78,74 @@ static void blk_mq_hctx_clear_pending(st
 
 static int blk_mq_queue_enter(struct request_queue *q)
 {
-	int ret;
-
-	__percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
-	smp_wmb();
-
-	/* we have problems freezing the queue if it's initializing */
-	if (!blk_queue_dying(q) &&
-	    (!blk_queue_bypass(q) || !blk_queue_init_done(q)))
-		return 0;
-
-	__percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
+	while (true) {
+		int ret;
 
-	spin_lock_irq(q->queue_lock);
-	ret = wait_event_interruptible_lock_irq(q->mq_freeze_wq,
-		!blk_queue_bypass(q) || blk_queue_dying(q),
-		*q->queue_lock);
-	/* inc usage with lock hold to avoid freeze_queue runs here */
-	if (!ret && !blk_queue_dying(q))
-		__percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
-	else if (blk_queue_dying(q))
-		ret = -ENODEV;
-	spin_unlock_irq(q->queue_lock);
+		if (percpu_ref_tryget_live(&q->mq_usage_counter))
+			return 0;
 
-	return ret;
+		ret = wait_event_interruptible(q->mq_freeze_wq,
+				!q->mq_freeze_depth || blk_queue_dying(q));
+		if (blk_queue_dying(q))
+			return -ENODEV;
+		if (ret)
+			return ret;
+	}
 }
 
 static void blk_mq_queue_exit(struct request_queue *q)
 {
-	__percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
+	percpu_ref_put(&q->mq_usage_counter);
 }
 
-void blk_mq_drain_queue(struct request_queue *q)
+static void blk_mq_usage_counter_release(struct percpu_ref *ref)
 {
-	while (true) {
-		s64 count;
-
-		spin_lock_irq(q->queue_lock);
-		count = percpu_counter_sum(&q->mq_usage_counter);
-		spin_unlock_irq(q->queue_lock);
+	struct request_queue *q =
+		container_of(ref, struct request_queue, mq_usage_counter);
 
-		if (count == 0)
-			break;
-		blk_mq_start_hw_queues(q);
-		msleep(10);
-	}
+	wake_up_all(&q->mq_freeze_wq);
 }
 
 /*
  * Guarantee no request is in use, so we can change any data structure of
  * the queue afterward.
  */
-static void blk_mq_freeze_queue(struct request_queue *q)
+void blk_mq_freeze_queue(struct request_queue *q)
 {
-	bool drain;
+	bool freeze;
 
 	spin_lock_irq(q->queue_lock);
-	drain = !q->bypass_depth++;
-	queue_flag_set(QUEUE_FLAG_BYPASS, q);
+	freeze = !q->mq_freeze_depth++;
 	spin_unlock_irq(q->queue_lock);
 
-	if (drain)
-		blk_mq_drain_queue(q);
+	if (freeze) {
+		/*
+		 * XXX: Temporary kludge to work around SCSI blk-mq stall.
+		 * SCSI synchronously creates and destroys many queues
+		 * back-to-back during probe leading to lengthy stalls.
+		 * This will be fixed by keeping ->mq_usage_counter in
+		 * atomic mode until genhd registration, but, for now,
+		 * let's work around using expedited synchronization.
+		 */
+		__percpu_ref_kill_expedited(&q->mq_usage_counter);
+
+		blk_mq_run_queues(q, false);
+	}
+	wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
 }
 
 static void blk_mq_unfreeze_queue(struct request_queue *q)
 {
-	bool wake = false;
+	bool wake;
 
 	spin_lock_irq(q->queue_lock);
-	if (!--q->bypass_depth) {
-		queue_flag_clear(QUEUE_FLAG_BYPASS, q);
-		wake = true;
-	}
-	WARN_ON_ONCE(q->bypass_depth < 0);
+	wake = !--q->mq_freeze_depth;
+	WARN_ON_ONCE(q->mq_freeze_depth < 0);
 	spin_unlock_irq(q->queue_lock);
-	if (wake)
+	if (wake) {
+		percpu_ref_reinit(&q->mq_usage_counter);
 		wake_up_all(&q->mq_freeze_wq);
+	}
 }
 
 bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx)
@@ -194,6 +185,8 @@ static void blk_mq_rq_ctx_init(struct re
 	/* tag was already set */
 	rq->errors = 0;
 
+	rq->cmd = rq->__cmd;
+
 	rq->extra_len = 0;
 	rq->sense_len = 0;
 	rq->resid_len = 0;
@@ -219,7 +212,6 @@ __blk_mq_alloc_request(struct blk_mq_all
 	if (tag != BLK_MQ_TAG_FAIL) {
 		rq = data->hctx->tags->rqs[tag];
 
-		rq->cmd_flags = 0;
 		if (blk_mq_tag_busy(data->hctx)) {
 			rq->cmd_flags = REQ_MQ_INFLIGHT;
 			atomic_inc(&data->hctx->nr_active);
@@ -274,6 +266,7 @@ static void __blk_mq_free_request(struct
 
 	if (rq->cmd_flags & REQ_MQ_INFLIGHT)
 		atomic_dec(&hctx->nr_active);
+	rq->cmd_flags = 0;
 
 	clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
 	blk_mq_put_tag(hctx, tag, &ctx->last_tag);
@@ -409,6 +402,12 @@ static void blk_mq_start_request(struct
 	blk_add_timer(rq);
 
 	/*
+	 * Ensure that ->deadline is visible before set the started
+	 * flag and clear the completed flag.
+	 */
+	smp_mb__before_atomic();
+
+	/*
 	 * Mark us as started and clear complete. Complete might have been
 	 * set if requeue raced with timeout, which then marked it as
 	 * complete. So be sure to clear complete again when we start
@@ -489,7 +488,11 @@ static void blk_mq_requeue_work(struct w
 		blk_mq_insert_request(rq, false, false, false);
 	}
 
-	blk_mq_run_queues(q, 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);
 }
 
 void blk_mq_add_to_requeue_list(struct request *rq, bool at_head)
@@ -973,14 +976,9 @@ void blk_mq_insert_request(struct reques
 
 	hctx = q->mq_ops->map_queue(q, ctx->cpu);
 
-	if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA) &&
-	    !(rq->cmd_flags & (REQ_FLUSH_SEQ))) {
-		blk_insert_flush(rq);
-	} else {
-		spin_lock(&ctx->lock);
-		__blk_mq_insert_request(hctx, rq, at_head);
-		spin_unlock(&ctx->lock);
-	}
+	spin_lock(&ctx->lock);
+	__blk_mq_insert_request(hctx, rq, at_head);
+	spin_unlock(&ctx->lock);
 
 	if (run_queue)
 		blk_mq_run_hw_queue(hctx, async);
@@ -1090,13 +1088,17 @@ static void blk_mq_bio_to_request(struct
 		blk_account_io_start(rq, 1);
 }
 
+static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
+{
+	return (hctx->flags & BLK_MQ_F_SHOULD_MERGE) &&
+		!blk_queue_nomerges(hctx->queue);
+}
+
 static inline bool blk_mq_merge_queue_io(struct blk_mq_hw_ctx *hctx,
 					 struct blk_mq_ctx *ctx,
 					 struct request *rq, struct bio *bio)
 {
-	struct request_queue *q = hctx->queue;
-
-	if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE)) {
+	if (!hctx_allow_merges(hctx)) {
 		blk_mq_bio_to_request(rq, bio);
 		spin_lock(&ctx->lock);
 insert_rq:
@@ -1104,6 +1106,8 @@ insert_rq:
 		spin_unlock(&ctx->lock);
 		return false;
 	} else {
+		struct request_queue *q = hctx->queue;
+
 		spin_lock(&ctx->lock);
 		if (!blk_mq_attempt_merge(q, ctx, bio)) {
 			blk_mq_bio_to_request(rq, bio);
@@ -1331,6 +1335,7 @@ static void blk_mq_free_rq_map(struct bl
 				continue;
 			set->ops->exit_request(set->driver_data, tags->rqs[i],
 						hctx_idx, i);
+			tags->rqs[i] = NULL;
 		}
 	}
 
@@ -1364,8 +1369,9 @@ static struct blk_mq_tags *blk_mq_init_r
 
 	INIT_LIST_HEAD(&tags->page_list);
 
-	tags->rqs = kmalloc_node(set->queue_depth * sizeof(struct request *),
-					GFP_KERNEL, set->numa_node);
+	tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
+				 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+				 set->numa_node);
 	if (!tags->rqs) {
 		blk_mq_free_tags(tags);
 		return NULL;
@@ -1389,8 +1395,9 @@ static struct blk_mq_tags *blk_mq_init_r
 			this_order--;
 
 		do {
-			page = alloc_pages_node(set->numa_node, GFP_KERNEL,
-						this_order);
+			page = alloc_pages_node(set->numa_node,
+				GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+				this_order);
 			if (page)
 				break;
 			if (!this_order--)
@@ -1411,11 +1418,15 @@ static struct blk_mq_tags *blk_mq_init_r
 		left -= to_do * rq_size;
 		for (j = 0; j < to_do; j++) {
 			tags->rqs[i] = p;
+			tags->rqs[i]->atomic_flags = 0;
+			tags->rqs[i]->cmd_flags = 0;
 			if (set->ops->init_request) {
 				if (set->ops->init_request(set->driver_data,
 						tags->rqs[i], hctx_idx, i,
-						set->numa_node))
+						set->numa_node)) {
+					tags->rqs[i] = NULL;
 					goto fail;
+				}
 			}
 
 			p += rq_size;
@@ -1426,7 +1437,6 @@ static struct blk_mq_tags *blk_mq_init_r
 	return tags;
 
 fail:
-	pr_warn("%s: failed to allocate requests\n", __func__);
 	blk_mq_free_rq_map(set, tags, hctx_idx);
 	return NULL;
 }
@@ -1596,7 +1606,7 @@ static int blk_mq_init_hw_queues(struct
 		hctx->tags = set->tags[i];
 
 		/*
-		 * Allocate space for all possible cpus to avoid allocation in
+		 * Allocate space for all possible cpus to avoid allocation at
 		 * runtime
 		 */
 		hctx->ctxs = kmalloc_node(nr_cpu_ids * sizeof(void *),
@@ -1684,8 +1694,8 @@ static void blk_mq_map_swqueue(struct re
 
 	queue_for_each_hw_ctx(q, hctx, i) {
 		/*
-		 * If not software queues are mapped to this hardware queue,
-		 * disable it and free the request entries
+		 * If no software queues are mapped to this hardware queue,
+		 * disable it and free the request entries.
 		 */
 		if (!hctx->nr_ctx) {
 			struct blk_mq_tag_set *set = q->tag_set;
@@ -1735,14 +1745,10 @@ static void blk_mq_del_queue_tag_set(str
 {
 	struct blk_mq_tag_set *set = q->tag_set;
 
-	blk_mq_freeze_queue(q);
-
 	mutex_lock(&set->tag_list_lock);
 	list_del_init(&q->tag_set_list);
 	blk_mq_update_tag_set_depth(set);
 	mutex_unlock(&set->tag_list_lock);
-
-	blk_mq_unfreeze_queue(q);
 }
 
 static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
@@ -1798,7 +1804,7 @@ struct request_queue *blk_mq_init_queue(
 	if (!q)
 		goto err_hctxs;
 
-	if (percpu_counter_init(&q->mq_usage_counter, 0))
+	if (percpu_ref_init(&q->mq_usage_counter, blk_mq_usage_counter_release))
 		goto err_map;
 
 	setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
@@ -1891,7 +1897,7 @@ void blk_mq_free_queue(struct request_qu
 	blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
 	blk_mq_free_hw_queues(q, set);
 
-	percpu_counter_destroy(&q->mq_usage_counter);
+	percpu_ref_exit(&q->mq_usage_counter);
 
 	free_percpu(q->queue_ctx);
 	kfree(q->queue_hw_ctx);
@@ -1950,6 +1956,60 @@ static int blk_mq_queue_reinit_notify(st
 	return NOTIFY_OK;
 }
 
+static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
+{
+	int i;
+
+	for (i = 0; i < set->nr_hw_queues; i++) {
+		set->tags[i] = blk_mq_init_rq_map(set, i);
+		if (!set->tags[i])
+			goto out_unwind;
+	}
+
+	return 0;
+
+out_unwind:
+	while (--i >= 0)
+		blk_mq_free_rq_map(set, set->tags[i], i);
+
+	return -ENOMEM;
+}
+
+/*
+ * Allocate the request maps associated with this tag_set. Note that this
+ * may reduce the depth asked for, if memory is tight. set->queue_depth
+ * will be updated to reflect the allocated depth.
+ */
+static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
+{
+	unsigned int depth;
+	int err;
+
+	depth = set->queue_depth;
+	do {
+		err = __blk_mq_alloc_rq_maps(set);
+		if (!err)
+			break;
+
+		set->queue_depth >>= 1;
+		if (set->queue_depth < set->reserved_tags + BLK_MQ_TAG_MIN) {
+			err = -ENOMEM;
+			break;
+		}
+	} while (set->queue_depth);
+
+	if (!set->queue_depth || err) {
+		pr_err("blk-mq: failed to allocate request map\n");
+		return -ENOMEM;
+	}
+
+	if (depth != set->queue_depth)
+		pr_info("blk-mq: reduced tag depth (%u -> %u)\n",
+						depth, set->queue_depth);
+
+	return 0;
+}
+
 /*
  * Alloc a tag set to be associated with one or more request queues.
  * May fail with EINVAL for various error conditions. May adjust the
@@ -1958,8 +2018,6 @@ static int blk_mq_queue_reinit_notify(st
  */
 int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
 {
-	int i;
-
 	if (!set->nr_hw_queues)
 		return -EINVAL;
 	if (!set->queue_depth)
@@ -1980,23 +2038,18 @@ int blk_mq_alloc_tag_set(struct blk_mq_t
 				 sizeof(struct blk_mq_tags *),
 				 GFP_KERNEL, set->numa_node);
 	if (!set->tags)
-		goto out;
+		return -ENOMEM;
 
-	for (i = 0; i < set->nr_hw_queues; i++) {
-		set->tags[i] = blk_mq_init_rq_map(set, i);
-		if (!set->tags[i])
-			goto out_unwind;
-	}
+	if (blk_mq_alloc_rq_maps(set))
+		goto enomem;
 
 	mutex_init(&set->tag_list_lock);
 	INIT_LIST_HEAD(&set->tag_list);
 
 	return 0;
-
-out_unwind:
-	while (--i >= 0)
-		blk_mq_free_rq_map(set, set->tags[i], i);
-out:
+enomem:
+	kfree(set->tags);
+	set->tags = NULL;
 	return -ENOMEM;
 }
 EXPORT_SYMBOL(blk_mq_alloc_tag_set);
@@ -2011,6 +2064,7 @@ void blk_mq_free_tag_set(struct blk_mq_t
 	}
 
 	kfree(set->tags);
+	set->tags = NULL;
 }
 EXPORT_SYMBOL(blk_mq_free_tag_set);
 
@@ -2050,8 +2104,7 @@ static int __init blk_mq_init(void)
 {
 	blk_mq_cpu_init();
 
-	/* Must be called after percpu_counter_hotcpu_callback() */
-	hotcpu_notifier(blk_mq_queue_reinit_notify, -10);
+	hotcpu_notifier(blk_mq_queue_reinit_notify, 0);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-mq.h linux-libre-3.17-rc7-gnu/block/blk-mq.h
--- linux-libre-3.16-gnu/block/blk-mq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-mq.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@ struct blk_mq_ctx {
 void __blk_mq_complete_request(struct request *rq);
 void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
 void blk_mq_init_flush(struct request_queue *q);
-void blk_mq_drain_queue(struct request_queue *q);
+void blk_mq_freeze_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
 void blk_mq_clone_flush_request(struct request *flush_rq,
 		struct request *orig_rq);
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-sysfs.c linux-libre-3.17-rc7-gnu/block/blk-sysfs.c
--- linux-libre-3.16-gnu/block/blk-sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -554,8 +554,10 @@ int blk_register_queue(struct gendisk *d
 	 * Initialization must be complete by now.  Finish the initial
 	 * bypass from queue allocation.
 	 */
-	blk_queue_bypass_end(q);
-	queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
+	if (!blk_queue_init_done(q)) {
+		queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
+		blk_queue_bypass_end(q);
+	}
 
 	ret = blk_trace_init_sysfs(dev);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/block/blk-throttle.c linux-libre-3.17-rc7-gnu/block/blk-throttle.c
--- linux-libre-3.16-gnu/block/blk-throttle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/blk-throttle.c	2014-09-28 17:29:07.000000000 -0400
@@ -412,13 +412,13 @@ static void throtl_pd_init(struct blkcg_
 	int rw;
 
 	/*
-	 * If sane_hierarchy is enabled, we switch to properly hierarchical
+	 * If on the default hierarchy, we switch to properly hierarchical
 	 * behavior where limits on a given throtl_grp are applied to the
 	 * whole subtree rather than just the group itself.  e.g. If 16M
 	 * read_bps limit is set on the root group, the whole system can't
 	 * exceed 16M for the device.
 	 *
-	 * If sane_hierarchy is not enabled, the broken flat hierarchy
+	 * If not on the default hierarchy, the broken flat hierarchy
 	 * behavior is retained where all throtl_grps are treated as if
 	 * they're all separate root groups right below throtl_data.
 	 * Limits of a group don't interact with limits of other groups
@@ -426,7 +426,7 @@ static void throtl_pd_init(struct blkcg_
 	 */
 	parent_sq = &td->service_queue;
 
-	if (cgroup_sane_behavior(blkg->blkcg->css.cgroup) && blkg->parent)
+	if (cgroup_on_dfl(blkg->blkcg->css.cgroup) && blkg->parent)
 		parent_sq = &blkg_to_tg(blkg->parent)->service_queue;
 
 	throtl_service_queue_init(&tg->service_queue, parent_sq);
diff -druNp --no-dereference linux-libre-3.16-gnu/block/cfq-iosched.c linux-libre-3.17-rc7-gnu/block/cfq-iosched.c
--- linux-libre-3.16-gnu/block/cfq-iosched.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/cfq-iosched.c	2014-09-28 17:29:07.000000000 -0400
@@ -1272,15 +1272,22 @@ __cfq_group_service_tree_add(struct cfq_
 	rb_insert_color(&cfqg->rb_node, &st->rb);
 }
 
+/*
+ * This has to be called only on activation of cfqg
+ */
 static void
 cfq_update_group_weight(struct cfq_group *cfqg)
 {
-	BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
-
 	if (cfqg->new_weight) {
 		cfqg->weight = cfqg->new_weight;
 		cfqg->new_weight = 0;
 	}
+}
+
+static void
+cfq_update_group_leaf_weight(struct cfq_group *cfqg)
+{
+	BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
 	if (cfqg->new_leaf_weight) {
 		cfqg->leaf_weight = cfqg->new_leaf_weight;
@@ -1299,7 +1306,12 @@ cfq_group_service_tree_add(struct cfq_rb
 	/* add to the service tree */
 	BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
-	cfq_update_group_weight(cfqg);
+	/*
+	 * Update leaf_weight.  We cannot update weight at this point
+	 * because cfqg might already have been activated and is
+	 * contributing its current weight to the parent's child_weight.
+	 */
+	cfq_update_group_leaf_weight(cfqg);
 	__cfq_group_service_tree_add(st, cfqg);
 
 	/*
@@ -1323,6 +1335,7 @@ cfq_group_service_tree_add(struct cfq_rb
 	 */
 	while ((parent = cfqg_parent(pos))) {
 		if (propagate) {
+			cfq_update_group_weight(pos);
 			propagate = !parent->nr_active++;
 			parent->children_weight += pos->weight;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/block/compat_ioctl.c linux-libre-3.17-rc7-gnu/block/compat_ioctl.c
--- linux-libre-3.16-gnu/block/compat_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/compat_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -663,6 +663,7 @@ long compat_blkdev_ioctl(struct file *fi
 	fmode_t mode = file->f_mode;
 	struct backing_dev_info *bdi;
 	loff_t size;
+	unsigned int max_sectors;
 
 	/*
 	 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
@@ -719,8 +720,9 @@ long compat_blkdev_ioctl(struct file *fi
 	case BLKSSZGET: /* get block device hardware sector size */
 		return compat_put_int(arg, bdev_logical_block_size(bdev));
 	case BLKSECTGET:
-		return compat_put_ushort(arg,
-					 queue_max_sectors(bdev_get_queue(bdev)));
+		max_sectors = min_t(unsigned int, USHRT_MAX,
+				    queue_max_sectors(bdev_get_queue(bdev)));
+		return compat_put_ushort(arg, max_sectors);
 	case BLKROTATIONAL:
 		return compat_put_ushort(arg,
 					 !blk_queue_nonrot(bdev_get_queue(bdev)));
diff -druNp --no-dereference linux-libre-3.16-gnu/block/genhd.c linux-libre-3.17-rc7-gnu/block/genhd.c
--- linux-libre-3.16-gnu/block/genhd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/genhd.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,10 +28,10 @@ struct kobject *block_depr;
 /* for extended dynamic devt allocation, currently only one major is used */
 #define NR_EXT_DEVT		(1 << MINORBITS)
 
-/* For extended devt allocation.  ext_devt_mutex prevents look up
+/* For extended devt allocation.  ext_devt_lock prevents look up
  * results from going away underneath its user.
  */
-static DEFINE_MUTEX(ext_devt_mutex);
+static DEFINE_SPINLOCK(ext_devt_lock);
 static DEFINE_IDR(ext_devt_idr);
 
 static struct device_type disk_type;
@@ -420,9 +420,13 @@ int blk_alloc_devt(struct hd_struct *par
 	}
 
 	/* allocate ext devt */
-	mutex_lock(&ext_devt_mutex);
-	idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL);
-	mutex_unlock(&ext_devt_mutex);
+	idr_preload(GFP_KERNEL);
+
+	spin_lock(&ext_devt_lock);
+	idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT);
+	spin_unlock(&ext_devt_lock);
+
+	idr_preload_end();
 	if (idx < 0)
 		return idx == -ENOSPC ? -EBUSY : idx;
 
@@ -441,15 +445,13 @@ int blk_alloc_devt(struct hd_struct *par
  */
 void blk_free_devt(dev_t devt)
 {
-	might_sleep();
-
 	if (devt == MKDEV(0, 0))
 		return;
 
 	if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
-		mutex_lock(&ext_devt_mutex);
+		spin_lock(&ext_devt_lock);
 		idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
-		mutex_unlock(&ext_devt_mutex);
+		spin_unlock(&ext_devt_lock);
 	}
 }
 
@@ -665,7 +667,6 @@ void del_gendisk(struct gendisk *disk)
 		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 	pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
 	device_del(disk_to_dev(disk));
-	blk_free_devt(disk_to_dev(disk)->devt);
 }
 EXPORT_SYMBOL(del_gendisk);
 
@@ -690,13 +691,13 @@ struct gendisk *get_gendisk(dev_t devt,
 	} else {
 		struct hd_struct *part;
 
-		mutex_lock(&ext_devt_mutex);
+		spin_lock(&ext_devt_lock);
 		part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
 		if (part && get_disk(part_to_disk(part))) {
 			*partno = part->partno;
 			disk = part_to_disk(part);
 		}
-		mutex_unlock(&ext_devt_mutex);
+		spin_unlock(&ext_devt_lock);
 	}
 
 	return disk;
@@ -1098,6 +1099,7 @@ static void disk_release(struct device *
 {
 	struct gendisk *disk = dev_to_disk(dev);
 
+	blk_free_devt(dev->devt);
 	disk_release_events(disk);
 	kfree(disk->random);
 	disk_replace_part_tbl(disk, NULL);
diff -druNp --no-dereference linux-libre-3.16-gnu/block/ioctl.c linux-libre-3.17-rc7-gnu/block/ioctl.c
--- linux-libre-3.16-gnu/block/ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -278,6 +278,7 @@ int blkdev_ioctl(struct block_device *bd
 	struct backing_dev_info *bdi;
 	loff_t size;
 	int ret, n;
+	unsigned int max_sectors;
 
 	switch(cmd) {
 	case BLKFLSBUF:
@@ -375,7 +376,9 @@ int blkdev_ioctl(struct block_device *bd
 	case BLKDISCARDZEROES:
 		return put_uint(arg, bdev_discard_zeroes_data(bdev));
 	case BLKSECTGET:
-		return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev)));
+		max_sectors = min_t(unsigned int, USHRT_MAX,
+				    queue_max_sectors(bdev_get_queue(bdev)));
+		return put_ushort(arg, max_sectors);
 	case BLKROTATIONAL:
 		return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev)));
 	case BLKRASET:
diff -druNp --no-dereference linux-libre-3.16-gnu/block/partition-generic.c linux-libre-3.17-rc7-gnu/block/partition-generic.c
--- linux-libre-3.16-gnu/block/partition-generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/partition-generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -211,6 +211,7 @@ static const struct attribute_group *par
 static void part_release(struct device *dev)
 {
 	struct hd_struct *p = dev_to_part(dev);
+	blk_free_devt(dev->devt);
 	free_part_stats(p);
 	free_part_info(p);
 	kfree(p);
@@ -253,7 +254,6 @@ void delete_partition(struct gendisk *di
 	rcu_assign_pointer(ptbl->last_lookup, NULL);
 	kobject_put(part->holder_dir);
 	device_del(part_to_dev(part));
-	blk_free_devt(part_devt(part));
 
 	hd_struct_put(part);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/block/partitions/aix.c linux-libre-3.17-rc7-gnu/block/partitions/aix.c
--- linux-libre-3.16-gnu/block/partitions/aix.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/partitions/aix.c	2014-09-28 17:29:07.000000000 -0400
@@ -215,7 +215,7 @@ int aix_partition(struct parsed_partitio
 		numlvs = be16_to_cpu(p->numlvs);
 		put_dev_sector(sect);
 	}
-	lvip = kzalloc(sizeof(struct lv_info) * state->limit, GFP_KERNEL);
+	lvip = kcalloc(state->limit, sizeof(struct lv_info), GFP_KERNEL);
 	if (!lvip)
 		return 0;
 	if (numlvs && (d = read_part_sector(state, vgda_sector + 1, &sect))) {
@@ -253,7 +253,7 @@ int aix_partition(struct parsed_partitio
 				continue;
 			}
 			lv_ix = be16_to_cpu(p->lv_ix) - 1;
-			if (lv_ix > state->limit) {
+			if (lv_ix >= state->limit) {
 				cur_lv_ix = -1;
 				continue;
 			}
diff -druNp --no-dereference linux-libre-3.16-gnu/block/partitions/amiga.c linux-libre-3.17-rc7-gnu/block/partitions/amiga.c
--- linux-libre-3.16-gnu/block/partitions/amiga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/partitions/amiga.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,8 @@
  *  Re-organised Feb 1998 Russell King
  */
 
+#define pr_fmt(fmt) fmt
+
 #include <linux/types.h>
 #include <linux/affs_hardblocks.h>
 
@@ -40,7 +42,7 @@ int amiga_partition(struct parsed_partit
 		data = read_part_sector(state, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
-				printk("Dev %s: unable to read RDB block %d\n",
+				pr_err("Dev %s: unable to read RDB block %d\n",
 				       bdevname(state->bdev, b), blk);
 			res = -1;
 			goto rdb_done;
@@ -57,12 +59,12 @@ int amiga_partition(struct parsed_partit
 		*(__be32 *)(data+0xdc) = 0;
 		if (checksum_block((__be32 *)data,
 				be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
-			printk("Warning: Trashed word at 0xd0 in block %d "
-				"ignored in checksum calculation\n",blk);
+			pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n",
+			       blk);
 			break;
 		}
 
-		printk("Dev %s: RDB in block %d has bad checksum\n",
+		pr_err("Dev %s: RDB in block %d has bad checksum\n",
 		       bdevname(state->bdev, b), blk);
 	}
 
@@ -83,7 +85,7 @@ int amiga_partition(struct parsed_partit
 		data = read_part_sector(state, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
-				printk("Dev %s: unable to read partition block %d\n",
+				pr_err("Dev %s: unable to read partition block %d\n",
 				       bdevname(state->bdev, b), blk);
 			res = -1;
 			goto rdb_done;
diff -druNp --no-dereference linux-libre-3.16-gnu/block/partitions/efi.c linux-libre-3.17-rc7-gnu/block/partitions/efi.c
--- linux-libre-3.16-gnu/block/partitions/efi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/partitions/efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,7 +121,7 @@ __setup("gpt", force_gpt_fn);
 /**
  * efi_crc32() - EFI version of crc32 function
  * @buf: buffer to calculate crc32 of
- * @len - length of buf
+ * @len: length of buf
  *
  * Description: Returns EFI-style CRC32 value for @buf
  * 
@@ -240,10 +240,10 @@ done:
 
 /**
  * read_lba(): Read bytes from disk, starting at given LBA
- * @state
- * @lba
- * @buffer
- * @size_t
+ * @state: disk parsed partitions
+ * @lba: the Logical Block Address of the partition table
+ * @buffer: destination buffer
+ * @count: bytes to read
  *
  * Description: Reads @count bytes from @state->bdev into @buffer.
  * Returns number of bytes read on success, 0 on error.
@@ -277,8 +277,8 @@ static size_t read_lba(struct parsed_par
 
 /**
  * alloc_read_gpt_entries(): reads partition entries from disk
- * @state
- * @gpt - GPT header
+ * @state: disk parsed partitions
+ * @gpt: GPT header
  * 
  * Description: Returns ptes on success,  NULL on error.
  * Allocates space for PTEs based on information found in @gpt.
@@ -312,8 +312,8 @@ static gpt_entry *alloc_read_gpt_entries
 
 /**
  * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
- * @state
- * @lba is the Logical Block Address of the partition table
+ * @state: disk parsed partitions
+ * @lba: the Logical Block Address of the partition table
  * 
  * Description: returns GPT header on success, NULL on error.   Allocates
  * and fills a GPT header starting at @ from @state->bdev.
@@ -340,10 +340,10 @@ static gpt_header *alloc_read_gpt_header
 
 /**
  * is_gpt_valid() - tests one GPT header and PTEs for validity
- * @state
- * @lba is the logical block address of the GPT header to test
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
+ * @state: disk parsed partitions
+ * @lba: logical block address of the GPT header to test
+ * @gpt: GPT header ptr, filled on return.
+ * @ptes: PTEs ptr, filled on return.
  *
  * Description: returns 1 if valid,  0 on error.
  * If valid, returns pointers to newly allocated GPT header and PTEs.
@@ -461,8 +461,8 @@ static int is_gpt_valid(struct parsed_pa
 
 /**
  * is_pte_valid() - tests one PTE for validity
- * @pte is the pte to check
- * @lastlba is last lba of the disk
+ * @pte:pte to check
+ * @lastlba: last lba of the disk
  *
  * Description: returns 1 if valid,  0 on error.
  */
@@ -478,9 +478,10 @@ is_pte_valid(const gpt_entry *pte, const
 
 /**
  * compare_gpts() - Search disk for valid GPT headers and PTEs
- * @pgpt is the primary GPT header
- * @agpt is the alternate GPT header
- * @lastlba is the last LBA number
+ * @pgpt: primary GPT header
+ * @agpt: alternate GPT header
+ * @lastlba: last LBA number
+ *
  * Description: Returns nothing.  Sanity checks pgpt and agpt fields
  * and prints warnings on discrepancies.
  * 
@@ -572,9 +573,10 @@ compare_gpts(gpt_header *pgpt, gpt_heade
 
 /**
  * find_valid_gpt() - Search disk for valid GPT headers and PTEs
- * @state
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
+ * @state: disk parsed partitions
+ * @gpt: GPT header ptr, filled on return.
+ * @ptes: PTEs ptr, filled on return.
+ *
  * Description: Returns 1 if valid, 0 on error.
  * If valid, returns pointers to newly allocated GPT header and PTEs.
  * Validity depends on PMBR being valid (or being overridden by the
@@ -663,7 +665,7 @@ static int find_valid_gpt(struct parsed_
 
 /**
  * efi_partition(struct parsed_partitions *state)
- * @state
+ * @state: disk parsed partitions
  *
  * Description: called from check.c, if the disk contains GPT
  * partitions, sets up partition entries in the kernel.
diff -druNp --no-dereference linux-libre-3.16-gnu/block/partitions/msdos.c linux-libre-3.17-rc7-gnu/block/partitions/msdos.c
--- linux-libre-3.16-gnu/block/partitions/msdos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/partitions/msdos.c	2014-09-28 17:29:07.000000000 -0400
@@ -159,8 +159,9 @@ static void parse_extended(struct parsed
 		/*
 		 * First process the data partition(s)
 		 */
-		for (i=0; i<4; i++, p++) {
+		for (i = 0; i < 4; i++, p++) {
 			sector_t offs, size, next;
+
 			if (!nr_sects(p) || is_extended_partition(p))
 				continue;
 
@@ -194,7 +195,7 @@ static void parse_extended(struct parsed
 		 * It should be a link to the next logical partition.
 		 */
 		p -= 4;
-		for (i=0; i<4; i++, p++)
+		for (i = 0; i < 4; i++, p++)
 			if (nr_sects(p) && is_extended_partition(p))
 				break;
 		if (i == 4)
@@ -243,8 +244,8 @@ static void parse_solaris_x86(struct par
 		return;
 	}
 	/* Ensure we can handle previous case of VTOC with 8 entries gracefully */
-	max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
-	for (i=0; i<max_nparts && state->next<state->limit; i++) {
+	max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
+	for (i = 0; i < max_nparts && state->next < state->limit; i++) {
 		struct solaris_x86_slice *s = &v->v_slice[i];
 		char tmp[3 + 10 + 1 + 1];
 
@@ -409,7 +410,7 @@ static void parse_minix(struct parsed_pa
 	/* The first sector of a Minix partition can have either
 	 * a secondary MBR describing its subpartitions, or
 	 * the normal boot sector. */
-	if (msdos_magic_present (data + 510) &&
+	if (msdos_magic_present(data + 510) &&
 	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
 		char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];
 
@@ -527,6 +528,7 @@ int msdos_partition(struct parsed_partit
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {
 		sector_t start = start_sect(p)*sector_size;
 		sector_t size = nr_sects(p)*sector_size;
+
 		if (!size)
 			continue;
 		if (is_extended_partition(p)) {
@@ -537,6 +539,7 @@ int msdos_partition(struct parsed_partit
 			 * sector, although it may not be enough/proper.
 			 */
 			sector_t n = 2;
+
 			n = min(size, max(sector_size, n));
 			put_partition(state, slot, start, n);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/block/scsi_ioctl.c linux-libre-3.17-rc7-gnu/block/scsi_ioctl.c
--- linux-libre-3.16-gnu/block/scsi_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/block/scsi_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,9 +82,18 @@ static int sg_set_timeout(struct request
 	return err;
 }
 
+static int max_sectors_bytes(struct request_queue *q)
+{
+	unsigned int max_sectors = queue_max_sectors(q);
+
+	max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
+
+	return max_sectors << 9;
+}
+
 static int sg_get_reserved_size(struct request_queue *q, int __user *p)
 {
-	unsigned val = min(q->sg_reserved_size, queue_max_sectors(q) << 9);
+	int val = min_t(int, q->sg_reserved_size, max_sectors_bytes(q));
 
 	return put_user(val, p);
 }
@@ -98,10 +107,8 @@ static int sg_set_reserved_size(struct r
 
 	if (size < 0)
 		return -EINVAL;
-	if (size > (queue_max_sectors(q) << 9))
-		size = queue_max_sectors(q) << 9;
 
-	q->sg_reserved_size = size;
+	q->sg_reserved_size = min(size, max_sectors_bytes(q));
 	return 0;
 }
 
@@ -272,7 +279,6 @@ static int blk_complete_sghdr_rq(struct
 	r = blk_rq_unmap_user(bio);
 	if (!ret)
 		ret = r;
-	blk_put_request(rq);
 
 	return ret;
 }
@@ -283,14 +289,13 @@ static int sg_io(struct request_queue *q
 	unsigned long start_time;
 	ssize_t ret = 0;
 	int writing = 0;
+	int at_head = 0;
 	struct request *rq;
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	struct bio *bio;
 
 	if (hdr->interface_id != 'S')
 		return -EINVAL;
-	if (hdr->cmd_len > BLK_MAX_CDB)
-		return -EINVAL;
 
 	if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
 		return -EIO;
@@ -306,17 +311,26 @@ static int sg_io(struct request_queue *q
 		case SG_DXFER_FROM_DEV:
 			break;
 		}
+	if (hdr->flags & SG_FLAG_Q_AT_HEAD)
+		at_head = 1;
 
+	ret = -ENOMEM;
 	rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
 	if (!rq)
-		return -ENOMEM;
+		goto out;
 	blk_rq_set_block_pc(rq);
 
-	if (blk_fill_sghdr_rq(q, rq, hdr, mode)) {
-		blk_put_request(rq);
-		return -EFAULT;
+	if (hdr->cmd_len > BLK_MAX_CDB) {
+		rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
+		if (!rq->cmd)
+			goto out_put_request;
 	}
 
+	ret = -EFAULT;
+	if (blk_fill_sghdr_rq(q, rq, hdr, mode))
+		goto out_free_cdb;
+
+	ret = 0;
 	if (hdr->iovec_count) {
 		size_t iov_data_len;
 		struct iovec *iov = NULL;
@@ -325,7 +339,7 @@ static int sg_io(struct request_queue *q
 					    0, NULL, &iov);
 		if (ret < 0) {
 			kfree(iov);
-			goto out;
+			goto out_free_cdb;
 		}
 
 		iov_data_len = ret;
@@ -348,7 +362,7 @@ static int sg_io(struct request_queue *q
 				      GFP_KERNEL);
 
 	if (ret)
-		goto out;
+		goto out_free_cdb;
 
 	bio = rq->bio;
 	memset(sense, 0, sizeof(sense));
@@ -362,13 +376,18 @@ static int sg_io(struct request_queue *q
 	 * (if he doesn't check that is his problem).
 	 * N.B. a non-zero SCSI status is _not_ necessarily an error.
 	 */
-	blk_execute_rq(q, bd_disk, rq, 0);
+	blk_execute_rq(q, bd_disk, rq, at_head);
 
 	hdr->duration = jiffies_to_msecs(jiffies - start_time);
 
-	return blk_complete_sghdr_rq(rq, hdr, bio);
-out:
+	ret = blk_complete_sghdr_rq(rq, hdr, bio);
+
+out_free_cdb:
+	if (rq->cmd != rq->__cmd)
+		kfree(rq->cmd);
+out_put_request:
 	blk_put_request(rq);
+out:
 	return ret;
 }
 
@@ -438,6 +457,11 @@ int sg_scsi_ioctl(struct request_queue *
 	}
 
 	rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
+	if (!rq) {
+		err = -ENOMEM;
+		goto error;
+	}
+	blk_rq_set_block_pc(rq);
 
 	cmdlen = COMMAND_SIZE(opcode);
 
@@ -491,7 +515,6 @@ int sg_scsi_ioctl(struct request_queue *
 	memset(sense, 0, sizeof(sense));
 	rq->sense = sense;
 	rq->sense_len = 0;
-	blk_rq_set_block_pc(rq);
 
 	blk_execute_rq(q, disk, rq, 0);
 
@@ -511,7 +534,8 @@ out:
 	
 error:
 	kfree(buffer);
-	blk_put_request(rq);
+	if (rq)
+		blk_put_request(rq);
 	return err;
 }
 EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
diff -druNp --no-dereference linux-libre-3.16-gnu/CREDITS linux-libre-3.17-rc7-gnu/CREDITS
--- linux-libre-3.16-gnu/CREDITS	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/CREDITS	2014-09-28 17:29:07.000000000 -0400
@@ -1381,6 +1381,9 @@ S: 17 rue Danton
 S: F - 94270 Le Kremlin-BicÃªtre
 S: France
 
+N: Jack Hammer
+D: IBM ServeRAID RAID (ips) driver maintenance
+
 N: Greg Hankins
 E: gregh@cc.gatech.edu
 D: fixed keyboard driver to separate LED and locking status
@@ -1691,6 +1694,10 @@ S: Reading
 S: RG6 2NU
 S: United Kingdom
 
+N: Dave Jeffery
+E: dhjeffery@gmail.com
+D: SCSI hacks and IBM ServeRAID RAID driver maintenance
+
 N: Jakub Jelinek
 E: jakub@redhat.com
 W: http://sunsite.mff.cuni.cz/~jj
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/algapi.c linux-libre-3.17-rc7-gnu/crypto/algapi.c
--- linux-libre-3.16-gnu/crypto/algapi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/algapi.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,20 @@ static inline int crypto_set_driver_name
 	return 0;
 }
 
+static inline void crypto_check_module_sig(struct module *mod)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+	if (fips_enabled && mod && !mod->sig_ok)
+		panic("Module %s signature verification failed in FIPS mode\n",
+		      mod->name);
+#endif
+	return;
+}
+
 static int crypto_check_alg(struct crypto_alg *alg)
 {
+	crypto_check_module_sig(alg->cra_module);
+
 	if (alg->cra_alignmask & (alg->cra_alignmask + 1))
 		return -EINVAL;
 
@@ -430,6 +442,8 @@ int crypto_register_template(struct cryp
 
 	down_write(&crypto_alg_sem);
 
+	crypto_check_module_sig(tmpl->module);
+
 	list_for_each_entry(q, &crypto_template_list, list) {
 		if (q == tmpl)
 			goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/asymmetric_keys.h linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/asymmetric_keys.h
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/asymmetric_keys.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/asymmetric_keys.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,8 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+int asymmetric_keyid_match(const char *kid, const char *id);
+
 static inline const char *asymmetric_key_id(const struct key *key)
 {
 	return key->type_data.p[1];
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/asymmetric_type.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/asymmetric_type.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/asymmetric_type.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/asymmetric_type.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,35 @@ static LIST_HEAD(asymmetric_key_parsers)
 static DECLARE_RWSEM(asymmetric_key_parsers_sem);
 
 /*
+ * Match asymmetric key id with partial match
+ * @id:		key id to match in a form "id:<id>"
+ */
+int asymmetric_keyid_match(const char *kid, const char *id)
+{
+	size_t idlen, kidlen;
+
+	if (!kid || !id)
+		return 0;
+
+	/* make it possible to use id as in the request: "id:<id>" */
+	if (strncmp(id, "id:", 3) == 0)
+		id += 3;
+
+	/* Anything after here requires a partial match on the ID string */
+	idlen = strlen(id);
+	kidlen = strlen(kid);
+	if (idlen > kidlen)
+		return 0;
+
+	kid += kidlen - idlen;
+	if (strcasecmp(id, kid) != 0)
+		return 0;
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
+
+/*
  * Match asymmetric keys on (part of) their name
  * We have some shorthand methods for matching keys.  We allow:
  *
@@ -34,9 +63,8 @@ static int asymmetric_key_match(const st
 {
 	const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
 	const char *spec = description;
-	const char *id, *kid;
+	const char *id;
 	ptrdiff_t speclen;
-	size_t idlen, kidlen;
 
 	if (!subtype || !spec || !*spec)
 		return 0;
@@ -55,23 +83,8 @@ static int asymmetric_key_match(const st
 	speclen = id - spec;
 	id++;
 
-	/* Anything after here requires a partial match on the ID string */
-	kid = asymmetric_key_id(key);
-	if (!kid)
-		return 0;
-
-	idlen = strlen(id);
-	kidlen = strlen(kid);
-	if (idlen > kidlen)
-		return 0;
-
-	kid += kidlen - idlen;
-	if (strcasecmp(id, kid) != 0)
-		return 0;
-
-	if (speclen == 2 &&
-	    memcmp(spec, "id", 2) == 0)
-		return 1;
+	if (speclen == 2 && memcmp(spec, "id", 2) == 0)
+		return asymmetric_keyid_match(asymmetric_key_id(key), id);
 
 	if (speclen == subtype->name_len &&
 	    memcmp(spec, subtype->name, speclen) == 0)
@@ -156,7 +169,7 @@ static void asymmetric_key_free_preparse
 	pr_devel("==>%s()\n", __func__);
 
 	if (subtype) {
-		subtype->destroy(prep->payload);
+		subtype->destroy(prep->payload[0]);
 		module_put(subtype->owner);
 	}
 	kfree(prep->type_data[1]);
@@ -164,29 +177,6 @@ static void asymmetric_key_free_preparse
 }
 
 /*
- * Instantiate a asymmetric_key defined key.  The key was preparsed, so we just
- * have to transfer the data here.
- */
-static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-{
-	int ret;
-
-	pr_devel("==>%s()\n", __func__);
-
-	ret = key_payload_reserve(key, prep->quotalen);
-	if (ret == 0) {
-		key->type_data.p[0] = prep->type_data[0];
-		key->type_data.p[1] = prep->type_data[1];
-		key->payload.data = prep->payload;
-		prep->type_data[0] = NULL;
-		prep->type_data[1] = NULL;
-		prep->payload = NULL;
-	}
-	pr_devel("<==%s() = %d\n", __func__, ret);
-	return ret;
-}
-
-/*
  * dispose of the data dangling from the corpse of a asymmetric key
  */
 static void asymmetric_key_destroy(struct key *key)
@@ -205,7 +195,7 @@ struct key_type key_type_asymmetric = {
 	.name		= "asymmetric",
 	.preparse	= asymmetric_key_preparse,
 	.free_preparse	= asymmetric_key_free_preparse,
-	.instantiate	= asymmetric_key_instantiate,
+	.instantiate	= generic_key_instantiate,
 	.match		= asymmetric_key_match,
 	.destroy	= asymmetric_key_destroy,
 	.describe	= asymmetric_key_describe,
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/Kconfig linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/Kconfig
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 
 config PUBLIC_KEY_ALGO_RSA
 	tristate "RSA public-key algorithm"
-	select MPILIB_EXTRA
 	select MPILIB
 	help
 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
@@ -33,8 +32,39 @@ config X509_CERTIFICATE_PARSER
 	select ASN1
 	select OID_REGISTRY
 	help
-	  This option procides support for parsing X.509 format blobs for key
+	  This option provides support for parsing X.509 format blobs for key
 	  data and provides the ability to instantiate a crypto key from a
 	  public key packet found inside the certificate.
 
+config PKCS7_MESSAGE_PARSER
+	tristate "PKCS#7 message parser"
+	depends on X509_CERTIFICATE_PARSER
+	select ASN1
+	select OID_REGISTRY
+	help
+	  This option provides support for parsing PKCS#7 format messages for
+	  signature data and provides the ability to verify the signature.
+
+config PKCS7_TEST_KEY
+	tristate "PKCS#7 testing key type"
+	depends on PKCS7_MESSAGE_PARSER
+	select SYSTEM_TRUSTED_KEYRING
+	help
+	  This option provides a type of key that can be loaded up from a
+	  PKCS#7 message - provided the message is signed by a trusted key.  If
+	  it is, the PKCS#7 wrapper is discarded and reading the key returns
+	  just the payload.  If it isn't, adding the key will fail with an
+	  error.
+
+	  This is intended for testing the PKCS#7 parser.
+
+config SIGNED_PE_FILE_VERIFICATION
+	bool "Support for PE file signature verification"
+	depends on PKCS7_MESSAGE_PARSER=y
+	select ASN1
+	select OID_REGISTRY
+	help
+	  This option provides support for verifying the signature(s) on a
+	  signed PE binary.
+
 endif # ASYMMETRIC_KEY_TYPE
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/Makefile linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/Makefile
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -25,3 +25,40 @@ $(obj)/x509_rsakey-asn1.o: $(obj)/x509_r
 
 clean-files	+= x509-asn1.c x509-asn1.h
 clean-files	+= x509_rsakey-asn1.c x509_rsakey-asn1.h
+
+#
+# PKCS#7 message handling
+#
+obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
+pkcs7_message-y := \
+	pkcs7-asn1.o \
+	pkcs7_parser.o \
+	pkcs7_trust.o \
+	pkcs7_verify.o
+
+$(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h
+$(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h
+
+clean-files	+= pkcs7-asn1.c pkcs7-asn1.h
+
+#
+# PKCS#7 parser testing key
+#
+obj-$(CONFIG_PKCS7_TEST_KEY) += pkcs7_test_key.o
+pkcs7_test_key-y := \
+	pkcs7_key_type.o
+
+#
+# Signed PE binary-wrapped key handling
+#
+obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o
+
+verify_signed_pefile-y := \
+	verify_pefile.o \
+	mscode_parser.o \
+	mscode-asn1.o
+
+$(obj)/mscode_parser.o: $(obj)/mscode-asn1.h $(obj)/mscode-asn1.h
+$(obj)/mscode-asn1.o: $(obj)/mscode-asn1.c $(obj)/mscode-asn1.h
+
+clean-files	+= mscode-asn1.c mscode-asn1.h
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/mscode.asn1 linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/mscode.asn1
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/mscode.asn1	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/mscode.asn1	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+--- Microsoft individual code signing data blob parser
+---
+--- Copyright (C) 2012 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.
+---
+
+MSCode ::= SEQUENCE {
+	type			SEQUENCE {
+		contentType	ContentType,
+		parameters	ANY
+	},
+	content			SEQUENCE {
+		digestAlgorithm	DigestAlgorithmIdentifier,
+		digest		OCTET STRING ({ mscode_note_digest })
+	}
+}
+
+ContentType ::= OBJECT IDENTIFIER ({ mscode_note_content_type })
+
+DigestAlgorithmIdentifier ::= SEQUENCE {
+	algorithm   OBJECT IDENTIFIER ({ mscode_note_digest_algo }),
+	parameters  ANY OPTIONAL
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/mscode_parser.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/mscode_parser.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/mscode_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/mscode_parser.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,126 @@
+/* Parse a Microsoft Individual Code Signing blob
+ *
+ * Copyright (C) 2014 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.
+ */
+
+#define pr_fmt(fmt) "MSCODE: "fmt
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#include <crypto/pkcs7.h>
+#include "verify_pefile.h"
+#include "mscode-asn1.h"
+
+/*
+ * Parse a Microsoft Individual Code Signing blob
+ */
+int mscode_parse(struct pefile_context *ctx)
+{
+	const void *content_data;
+	size_t data_len;
+	int ret;
+
+	ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
+
+	if (ret) {
+		pr_debug("PKCS#7 message does not contain data\n");
+		return ret;
+	}
+
+	pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
+		 content_data);
+
+	return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len);
+}
+
+/*
+ * Check the content type OID
+ */
+int mscode_note_content_type(void *context, size_t hdrlen,
+			     unsigned char tag,
+			     const void *value, size_t vlen)
+{
+	enum OID oid;
+
+	oid = look_up_OID(value, vlen);
+	if (oid == OID__NR) {
+		char buffer[50];
+
+		sprint_oid(value, vlen, buffer, sizeof(buffer));
+		pr_err("Unknown OID: %s\n", buffer);
+		return -EBADMSG;
+	}
+
+	/*
+	 * pesign utility had a bug where it was putting
+	 * OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
+	 * So allow both OIDs.
+	 */
+	if (oid != OID_msPeImageDataObjId &&
+	    oid != OID_msIndividualSPKeyPurpose) {
+		pr_err("Unexpected content type OID %u\n", oid);
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+/*
+ * Note the digest algorithm OID
+ */
+int mscode_note_digest_algo(void *context, size_t hdrlen,
+			    unsigned char tag,
+			    const void *value, size_t vlen)
+{
+	struct pefile_context *ctx = context;
+	char buffer[50];
+	enum OID oid;
+
+	oid = look_up_OID(value, vlen);
+	switch (oid) {
+	case OID_md4:
+		ctx->digest_algo = HASH_ALGO_MD4;
+		break;
+	case OID_md5:
+		ctx->digest_algo = HASH_ALGO_MD5;
+		break;
+	case OID_sha1:
+		ctx->digest_algo = HASH_ALGO_SHA1;
+		break;
+	case OID_sha256:
+		ctx->digest_algo = HASH_ALGO_SHA256;
+		break;
+
+	case OID__NR:
+		sprint_oid(value, vlen, buffer, sizeof(buffer));
+		pr_err("Unknown OID: %s\n", buffer);
+		return -EBADMSG;
+
+	default:
+		pr_err("Unsupported content type: %u\n", oid);
+		return -ENOPKG;
+	}
+
+	return 0;
+}
+
+/*
+ * Note the digest we're guaranteeing with this certificate
+ */
+int mscode_note_digest(void *context, size_t hdrlen,
+		       unsigned char tag,
+		       const void *value, size_t vlen)
+{
+	struct pefile_context *ctx = context;
+
+	ctx->digest = value;
+	ctx->digest_len = vlen;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7.asn1 linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7.asn1
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7.asn1	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7.asn1	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,127 @@
+PKCS7ContentInfo ::= SEQUENCE {
+	contentType	ContentType,
+	content		[0] EXPLICIT SignedData OPTIONAL
+}
+
+ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID })
+
+SignedData ::= SEQUENCE {
+	version			INTEGER,
+	digestAlgorithms	DigestAlgorithmIdentifiers,
+	contentInfo		ContentInfo,
+	certificates		CHOICE {
+		certSet		[0] IMPLICIT ExtendedCertificatesAndCertificates,
+		certSequence	[2] IMPLICIT Certificates
+	} OPTIONAL ({ pkcs7_note_certificate_list }),
+	crls CHOICE {
+		crlSet		[1] IMPLICIT CertificateRevocationLists,
+		crlSequence	[3] IMPLICIT CRLSequence
+	} OPTIONAL,
+	signerInfos		SignerInfos
+}
+
+ContentInfo ::= SEQUENCE {
+	contentType	ContentType,
+	content		[0] EXPLICIT Data OPTIONAL
+}
+
+Data ::= ANY ({ pkcs7_note_data })
+
+DigestAlgorithmIdentifiers ::= CHOICE {
+	daSet			SET OF DigestAlgorithmIdentifier,
+	daSequence		SEQUENCE OF DigestAlgorithmIdentifier
+}
+
+DigestAlgorithmIdentifier ::= SEQUENCE {
+	algorithm   OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+	parameters  ANY OPTIONAL
+}
+
+--
+-- Certificates and certificate lists
+--
+ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate
+
+ExtendedCertificateOrCertificate ::= CHOICE {
+  certificate		Certificate,				-- X.509
+  extendedCertificate	[0] IMPLICIT ExtendedCertificate	-- PKCS#6
+}
+
+ExtendedCertificate ::= Certificate -- cheating
+
+Certificates ::= SEQUENCE OF Certificate
+
+CertificateRevocationLists ::= SET OF CertificateList
+
+CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly
+
+CRLSequence ::= SEQUENCE OF CertificateList
+
+Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509
+
+--
+-- Signer information
+--
+SignerInfos ::= CHOICE {
+	siSet		SET OF SignerInfo,
+	siSequence	SEQUENCE OF SignerInfo
+}
+
+SignerInfo ::= SEQUENCE {
+	version			INTEGER,
+	issuerAndSerialNumber	IssuerAndSerialNumber,
+	digestAlgorithm		DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
+	authenticatedAttributes	CHOICE {
+		aaSet		[0] IMPLICIT SetOfAuthenticatedAttribute
+					({ pkcs7_sig_note_set_of_authattrs }),
+		aaSequence	[2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
+			-- Explicit because easier to compute digest on
+			-- sequence of attributes and then reuse encoded
+			-- sequence in aaSequence.
+	} OPTIONAL,
+	digestEncryptionAlgorithm
+				DigestEncryptionAlgorithmIdentifier ({ pkcs7_sig_note_pkey_algo }),
+	encryptedDigest		EncryptedDigest,
+	unauthenticatedAttributes CHOICE {
+		uaSet		[1] IMPLICIT SET OF UnauthenticatedAttribute,
+		uaSequence	[3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute
+	} OPTIONAL
+} ({ pkcs7_note_signed_info })
+
+IssuerAndSerialNumber ::= SEQUENCE {
+	issuer			Name ({ pkcs7_sig_note_issuer }),
+	serialNumber		CertificateSerialNumber ({ pkcs7_sig_note_serial })
+}
+
+CertificateSerialNumber ::= INTEGER
+
+SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
+
+AuthenticatedAttribute ::= SEQUENCE {
+	type			OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+	values			SET OF ANY ({ pkcs7_sig_note_authenticated_attr })
+}
+
+UnauthenticatedAttribute ::= SEQUENCE {
+	type			OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+	values			SET OF ANY
+}
+
+DigestEncryptionAlgorithmIdentifier ::= SEQUENCE {
+	algorithm		OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+	parameters		ANY OPTIONAL
+}
+
+EncryptedDigest ::= OCTET STRING ({ pkcs7_sig_note_signature })
+
+---
+--- X.500 Name
+---
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+	attributeType		OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+	attributeValue		ANY
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_key_type.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_key_type.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_key_type.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_key_type.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,100 @@
+/* Testing module to load key from trusted PKCS#7 message
+ *
+ * Copyright (C) 2014 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.
+ */
+
+#define pr_fmt(fmt) "PKCS7key: "fmt
+#include <linux/key.h>
+#include <linux/err.h>
+#include <linux/key-type.h>
+#include <crypto/pkcs7.h>
+#include <keys/user-type.h>
+#include <keys/system_keyring.h>
+#include "pkcs7_parser.h"
+
+/*
+ * Preparse a PKCS#7 wrapped and validated data blob.
+ */
+static int pkcs7_preparse(struct key_preparsed_payload *prep)
+{
+	struct pkcs7_message *pkcs7;
+	const void *data, *saved_prep_data;
+	size_t datalen, saved_prep_datalen;
+	bool trusted;
+	int ret;
+
+	kenter("");
+
+	saved_prep_data = prep->data;
+	saved_prep_datalen = prep->datalen;
+	pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
+	if (IS_ERR(pkcs7)) {
+		ret = PTR_ERR(pkcs7);
+		goto error;
+	}
+
+	ret = pkcs7_verify(pkcs7);
+	if (ret < 0)
+		goto error_free;
+
+	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
+	if (ret < 0)
+		goto error_free;
+	if (!trusted)
+		pr_warn("PKCS#7 message doesn't chain back to a trusted key\n");
+
+	ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false);
+	if (ret < 0)
+		goto error_free;
+
+	prep->data = data;
+	prep->datalen = datalen;
+	ret = user_preparse(prep);
+	prep->data = saved_prep_data;
+	prep->datalen = saved_prep_datalen;
+
+error_free:
+	pkcs7_free_message(pkcs7);
+error:
+	kleave(" = %d", ret);
+	return ret;
+}
+
+/*
+ * user defined keys take an arbitrary string as the description and an
+ * arbitrary blob of data as the payload
+ */
+static struct key_type key_type_pkcs7 = {
+	.name			= "pkcs7_test",
+	.def_lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
+	.preparse		= pkcs7_preparse,
+	.free_preparse		= user_free_preparse,
+	.instantiate		= generic_key_instantiate,
+	.match			= user_match,
+	.revoke			= user_revoke,
+	.destroy		= user_destroy,
+	.describe		= user_describe,
+	.read			= user_read,
+};
+
+/*
+ * Module stuff
+ */
+static int __init pkcs7_key_init(void)
+{
+	return register_key_type(&key_type_pkcs7);
+}
+
+static void __exit pkcs7_key_cleanup(void)
+{
+	unregister_key_type(&key_type_pkcs7);
+}
+
+module_init(pkcs7_key_init);
+module_exit(pkcs7_key_cleanup);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_parser.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_parser.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_parser.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,396 @@
+/* PKCS#7 parser
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+#include "pkcs7-asn1.h"
+
+struct pkcs7_parse_context {
+	struct pkcs7_message	*msg;		/* Message being constructed */
+	struct pkcs7_signed_info *sinfo;	/* SignedInfo being constructed */
+	struct pkcs7_signed_info **ppsinfo;
+	struct x509_certificate *certs;		/* Certificate cache */
+	struct x509_certificate **ppcerts;
+	unsigned long	data;			/* Start of data */
+	enum OID	last_oid;		/* Last OID encountered */
+	unsigned	x509_index;
+	unsigned	sinfo_index;
+};
+
+/**
+ * pkcs7_free_message - Free a PKCS#7 message
+ * @pkcs7: The PKCS#7 message to free
+ */
+void pkcs7_free_message(struct pkcs7_message *pkcs7)
+{
+	struct x509_certificate *cert;
+	struct pkcs7_signed_info *sinfo;
+
+	if (pkcs7) {
+		while (pkcs7->certs) {
+			cert = pkcs7->certs;
+			pkcs7->certs = cert->next;
+			x509_free_certificate(cert);
+		}
+		while (pkcs7->crl) {
+			cert = pkcs7->crl;
+			pkcs7->crl = cert->next;
+			x509_free_certificate(cert);
+		}
+		while (pkcs7->signed_infos) {
+			sinfo = pkcs7->signed_infos;
+			pkcs7->signed_infos = sinfo->next;
+			mpi_free(sinfo->sig.mpi[0]);
+			kfree(sinfo->sig.digest);
+			kfree(sinfo);
+		}
+		kfree(pkcs7);
+	}
+}
+EXPORT_SYMBOL_GPL(pkcs7_free_message);
+
+/**
+ * pkcs7_parse_message - Parse a PKCS#7 message
+ * @data: The raw binary ASN.1 encoded message to be parsed
+ * @datalen: The size of the encoded message
+ */
+struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
+{
+	struct pkcs7_parse_context *ctx;
+	struct pkcs7_message *msg;
+	long ret;
+
+	ret = -ENOMEM;
+	msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
+	if (!msg)
+		goto error_no_sig;
+	ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
+	if (!ctx)
+		goto error_no_ctx;
+	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+	if (!ctx->sinfo)
+		goto error_no_sinfo;
+
+	ctx->msg = msg;
+	ctx->data = (unsigned long)data;
+	ctx->ppcerts = &ctx->certs;
+	ctx->ppsinfo = &ctx->msg->signed_infos;
+
+	/* Attempt to decode the signature */
+	ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
+	if (ret < 0)
+		goto error_decode;
+
+	while (ctx->certs) {
+		struct x509_certificate *cert = ctx->certs;
+		ctx->certs = cert->next;
+		x509_free_certificate(cert);
+	}
+	mpi_free(ctx->sinfo->sig.mpi[0]);
+	kfree(ctx->sinfo->sig.digest);
+	kfree(ctx->sinfo);
+	kfree(ctx);
+	return msg;
+
+error_decode:
+	mpi_free(ctx->sinfo->sig.mpi[0]);
+	kfree(ctx->sinfo->sig.digest);
+	kfree(ctx->sinfo);
+error_no_sinfo:
+	kfree(ctx);
+error_no_ctx:
+	pkcs7_free_message(msg);
+error_no_sig:
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pkcs7_parse_message);
+
+/**
+ * pkcs7_get_content_data - Get access to the PKCS#7 content
+ * @pkcs7: The preparsed PKCS#7 message to access
+ * @_data: Place to return a pointer to the data
+ * @_data_len: Place to return the data length
+ * @want_wrapper: True if the ASN.1 object header should be included in the data
+ *
+ * Get access to the data content of the PKCS#7 message, including, optionally,
+ * the header of the ASN.1 object that contains it.  Returns -ENODATA if the
+ * data object was missing from the message.
+ */
+int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
+			   const void **_data, size_t *_data_len,
+			   bool want_wrapper)
+{
+	size_t wrapper;
+
+	if (!pkcs7->data)
+		return -ENODATA;
+
+	wrapper = want_wrapper ? pkcs7->data_hdrlen : 0;
+	*_data = pkcs7->data - wrapper;
+	*_data_len = pkcs7->data_len + wrapper;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
+
+/*
+ * Note an OID when we find one for later processing when we know how
+ * to interpret it.
+ */
+int pkcs7_note_OID(void *context, size_t hdrlen,
+		   unsigned char tag,
+		   const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	ctx->last_oid = look_up_OID(value, vlen);
+	if (ctx->last_oid == OID__NR) {
+		char buffer[50];
+		sprint_oid(value, vlen, buffer, sizeof(buffer));
+		printk("PKCS7: Unknown OID: [%lu] %s\n",
+		       (unsigned long)value - ctx->data, buffer);
+	}
+	return 0;
+}
+
+/*
+ * Note the digest algorithm for the signature.
+ */
+int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
+			       unsigned char tag,
+			       const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	switch (ctx->last_oid) {
+	case OID_md4:
+		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
+		break;
+	case OID_md5:
+		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
+		break;
+	case OID_sha1:
+		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
+		break;
+	case OID_sha256:
+		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
+		break;
+	default:
+		printk("Unsupported digest algo: %u\n", ctx->last_oid);
+		return -ENOPKG;
+	}
+	return 0;
+}
+
+/*
+ * Note the public key algorithm for the signature.
+ */
+int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
+			     unsigned char tag,
+			     const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	switch (ctx->last_oid) {
+	case OID_rsaEncryption:
+		ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
+		break;
+	default:
+		printk("Unsupported pkey algo: %u\n", ctx->last_oid);
+		return -ENOPKG;
+	}
+	return 0;
+}
+
+/*
+ * Extract a certificate and store it in the context.
+ */
+int pkcs7_extract_cert(void *context, size_t hdrlen,
+		       unsigned char tag,
+		       const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+	struct x509_certificate *x509;
+
+	if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
+		pr_debug("Cert began with tag %02x at %lu\n",
+			 tag, (unsigned long)ctx - ctx->data);
+		return -EBADMSG;
+	}
+
+	/* We have to correct for the header so that the X.509 parser can start
+	 * from the beginning.  Note that since X.509 stipulates DER, there
+	 * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which
+	 * stipulates BER).
+	 */
+	value -= hdrlen;
+	vlen += hdrlen;
+
+	if (((u8*)value)[1] == 0x80)
+		vlen += 2; /* Indefinite length - there should be an EOC */
+
+	x509 = x509_cert_parse(value, vlen);
+	if (IS_ERR(x509))
+		return PTR_ERR(x509);
+
+	pr_debug("Got cert for %s\n", x509->subject);
+	pr_debug("- fingerprint %s\n", x509->fingerprint);
+
+	x509->index = ++ctx->x509_index;
+	*ctx->ppcerts = x509;
+	ctx->ppcerts = &x509->next;
+	return 0;
+}
+
+/*
+ * Save the certificate list
+ */
+int pkcs7_note_certificate_list(void *context, size_t hdrlen,
+				unsigned char tag,
+				const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	pr_devel("Got cert list (%02x)\n", tag);
+
+	*ctx->ppcerts = ctx->msg->certs;
+	ctx->msg->certs = ctx->certs;
+	ctx->certs = NULL;
+	ctx->ppcerts = &ctx->certs;
+	return 0;
+}
+
+/*
+ * Extract the data from the message and store that and its content type OID in
+ * the context.
+ */
+int pkcs7_note_data(void *context, size_t hdrlen,
+		    unsigned char tag,
+		    const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	pr_debug("Got data\n");
+
+	ctx->msg->data = value;
+	ctx->msg->data_len = vlen;
+	ctx->msg->data_hdrlen = hdrlen;
+	ctx->msg->data_type = ctx->last_oid;
+	return 0;
+}
+
+/*
+ * Parse authenticated attributes
+ */
+int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
+				      unsigned char tag,
+				      const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
+
+	switch (ctx->last_oid) {
+	case OID_messageDigest:
+		if (tag != ASN1_OTS)
+			return -EBADMSG;
+		ctx->sinfo->msgdigest = value;
+		ctx->sinfo->msgdigest_len = vlen;
+		return 0;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * Note the set of auth attributes for digestion purposes [RFC2315 9.3]
+ */
+int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
+				    unsigned char tag,
+				    const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	/* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
+	ctx->sinfo->authattrs = value - (hdrlen - 1);
+	ctx->sinfo->authattrs_len = vlen + (hdrlen - 1);
+	return 0;
+}
+
+/*
+ * Note the issuing certificate serial number
+ */
+int pkcs7_sig_note_serial(void *context, size_t hdrlen,
+			  unsigned char tag,
+			  const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+	ctx->sinfo->raw_serial = value;
+	ctx->sinfo->raw_serial_size = vlen;
+	return 0;
+}
+
+/*
+ * Note the issuer's name
+ */
+int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
+			  unsigned char tag,
+			  const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+	ctx->sinfo->raw_issuer = value;
+	ctx->sinfo->raw_issuer_size = vlen;
+	return 0;
+}
+
+/*
+ * Note the signature data
+ */
+int pkcs7_sig_note_signature(void *context, size_t hdrlen,
+			     unsigned char tag,
+			     const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+	MPI mpi;
+
+	BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
+
+	mpi = mpi_read_raw_data(value, vlen);
+	if (!mpi)
+		return -ENOMEM;
+
+	ctx->sinfo->sig.mpi[0] = mpi;
+	ctx->sinfo->sig.nr_mpi = 1;
+	return 0;
+}
+
+/*
+ * Note a signature information block
+ */
+int pkcs7_note_signed_info(void *context, size_t hdrlen,
+			   unsigned char tag,
+			   const void *value, size_t vlen)
+{
+	struct pkcs7_parse_context *ctx = context;
+
+	ctx->sinfo->index = ++ctx->sinfo_index;
+	*ctx->ppsinfo = ctx->sinfo;
+	ctx->ppsinfo = &ctx->sinfo->next;
+	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+	if (!ctx->sinfo)
+		return -ENOMEM;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_parser.h linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_parser.h
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_parser.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_parser.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+/* PKCS#7 crypto data parser internal definitions
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/oid_registry.h>
+#include <crypto/pkcs7.h>
+#include "x509_parser.h"
+
+#define kenter(FMT, ...) \
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+struct pkcs7_signed_info {
+	struct pkcs7_signed_info *next;
+	struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
+	unsigned index;
+	bool trusted;
+
+	/* Message digest - the digest of the Content Data (or NULL) */
+	const void	*msgdigest;
+	unsigned	msgdigest_len;
+
+	/* Authenticated Attribute data (or NULL) */
+	unsigned	authattrs_len;
+	const void	*authattrs;
+
+	/* Issuing cert serial number and issuer's name */
+	const void	*raw_serial;
+	unsigned	raw_serial_size;
+	unsigned	raw_issuer_size;
+	const void	*raw_issuer;
+
+	/* Message signature.
+	 *
+	 * This contains the generated digest of _either_ the Content Data or
+	 * the Authenticated Attributes [RFC2315 9.3].  If the latter, one of
+	 * the attributes contains the digest of the the Content Data within
+	 * it.
+	 */
+	struct public_key_signature sig;
+};
+
+struct pkcs7_message {
+	struct x509_certificate *certs;	/* Certificate list */
+	struct x509_certificate *crl;	/* Revocation list */
+	struct pkcs7_signed_info *signed_infos;
+
+	/* Content Data (or NULL) */
+	enum OID	data_type;	/* Type of Data */
+	size_t		data_len;	/* Length of Data */
+	size_t		data_hdrlen;	/* Length of Data ASN.1 header */
+	const void	*data;		/* Content Data (or 0) */
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_trust.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_trust.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_trust.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_trust.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,166 @@
+/* Validate the trust chain of a PKCS#7 message.
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/asn1.h>
+#include <linux/key.h>
+#include <keys/asymmetric-type.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+
+/**
+ * Check the trust on one PKCS#7 SignedInfo block.
+ */
+int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
+			     struct pkcs7_signed_info *sinfo,
+			     struct key *trust_keyring)
+{
+	struct public_key_signature *sig = &sinfo->sig;
+	struct x509_certificate *x509, *last = NULL, *p;
+	struct key *key;
+	bool trusted;
+	int ret;
+
+	kenter(",%u,", sinfo->index);
+
+	for (x509 = sinfo->signer; x509; x509 = x509->signer) {
+		if (x509->seen) {
+			if (x509->verified) {
+				trusted = x509->trusted;
+				goto verified;
+			}
+			kleave(" = -ENOKEY [cached]");
+			return -ENOKEY;
+		}
+		x509->seen = true;
+
+		/* Look to see if this certificate is present in the trusted
+		 * keys.
+		 */
+		key = x509_request_asymmetric_key(trust_keyring, x509->subject,
+						  x509->fingerprint);
+		if (!IS_ERR(key))
+			/* One of the X.509 certificates in the PKCS#7 message
+			 * is apparently the same as one we already trust.
+			 * Verify that the trusted variant can also validate
+			 * the signature on the descendant.
+			 */
+			goto matched;
+		if (key == ERR_PTR(-ENOMEM))
+			return -ENOMEM;
+
+		 /* Self-signed certificates form roots of their own, and if we
+		  * don't know them, then we can't accept them.
+		  */
+		if (x509->next == x509) {
+			kleave(" = -ENOKEY [unknown self-signed]");
+			return -ENOKEY;
+		}
+
+		might_sleep();
+		last = x509;
+		sig = &last->sig;
+	}
+
+	/* No match - see if the root certificate has a signer amongst the
+	 * trusted keys.
+	 */
+	if (!last || !last->issuer || !last->authority) {
+		kleave(" = -ENOKEY [no backref]");
+		return -ENOKEY;
+	}
+
+	key = x509_request_asymmetric_key(trust_keyring, last->issuer,
+					  last->authority);
+	if (IS_ERR(key))
+		return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY;
+	x509 = last;
+
+matched:
+	ret = verify_signature(key, sig);
+	trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags);
+	key_put(key);
+	if (ret < 0) {
+		if (ret == -ENOMEM)
+			return ret;
+		kleave(" = -EKEYREJECTED [verify %d]", ret);
+		return -EKEYREJECTED;
+	}
+
+verified:
+	x509->verified = true;
+	for (p = sinfo->signer; p != x509; p = p->signer) {
+		p->verified = true;
+		p->trusted = trusted;
+	}
+	sinfo->trusted = trusted;
+	kleave(" = 0");
+	return 0;
+}
+
+/**
+ * pkcs7_validate_trust - Validate PKCS#7 trust chain
+ * @pkcs7: The PKCS#7 certificate to validate
+ * @trust_keyring: Signing certificates to use as starting points
+ * @_trusted: Set to true if trustworth, false otherwise
+ *
+ * Validate that the certificate chain inside the PKCS#7 message intersects
+ * keys we already know and trust.
+ *
+ * Returns, in order of descending priority:
+ *
+ *  (*) -EKEYREJECTED if a signature failed to match for which we have a valid
+ *	key, or:
+ *
+ *  (*) 0 if at least one signature chain intersects with the keys in the trust
+ *	keyring, or:
+ *
+ *  (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
+ *	chain.
+ *
+ *  (*) -ENOKEY if we couldn't find a match for any of the signature chains in
+ *	the message.
+ *
+ * May also return -ENOMEM.
+ */
+int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
+			 struct key *trust_keyring,
+			 bool *_trusted)
+{
+	struct pkcs7_signed_info *sinfo;
+	struct x509_certificate *p;
+	int cached_ret = 0, ret;
+
+	for (p = pkcs7->certs; p; p = p->next)
+		p->seen = false;
+
+	for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
+		ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring);
+		if (ret < 0) {
+			if (ret == -ENOPKG) {
+				cached_ret = -ENOPKG;
+			} else if (ret == -ENOKEY) {
+				if (cached_ret == 0)
+					cached_ret = -ENOKEY;
+			} else {
+				return ret;
+			}
+		}
+		*_trusted |= sinfo->trusted;
+	}
+
+	return cached_ret;
+}
+EXPORT_SYMBOL_GPL(pkcs7_validate_trust);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_verify.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_verify.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/pkcs7_verify.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/pkcs7_verify.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,321 @@
+/* Verify the signature on a PKCS#7 message.
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/asn1.h>
+#include <crypto/hash.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+
+/*
+ * Digest the relevant parts of the PKCS#7 data
+ */
+static int pkcs7_digest(struct pkcs7_message *pkcs7,
+			struct pkcs7_signed_info *sinfo)
+{
+	struct crypto_shash *tfm;
+	struct shash_desc *desc;
+	size_t digest_size, desc_size;
+	void *digest;
+	int ret;
+
+	kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo);
+
+	if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
+	    !hash_algo_name[sinfo->sig.pkey_hash_algo])
+		return -ENOPKG;
+
+	/* Allocate the hashing algorithm we're going to need and find out how
+	 * big the hash operational data will be.
+	 */
+	tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo],
+				 0, 0);
+	if (IS_ERR(tfm))
+		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
+
+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+	sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm);
+
+	ret = -ENOMEM;
+	digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
+	if (!digest)
+		goto error_no_desc;
+
+	desc = digest + digest_size;
+	desc->tfm   = tfm;
+	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	/* Digest the message [RFC2315 9.3] */
+	ret = crypto_shash_init(desc);
+	if (ret < 0)
+		goto error;
+	ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest);
+	if (ret < 0)
+		goto error;
+	pr_devel("MsgDigest = [%*ph]\n", 8, digest);
+
+	/* However, if there are authenticated attributes, there must be a
+	 * message digest attribute amongst them which corresponds to the
+	 * digest we just calculated.
+	 */
+	if (sinfo->msgdigest) {
+		u8 tag;
+
+		if (sinfo->msgdigest_len != sinfo->sig.digest_size) {
+			pr_debug("Sig %u: Invalid digest size (%u)\n",
+				 sinfo->index, sinfo->msgdigest_len);
+			ret = -EBADMSG;
+			goto error;
+		}
+
+		if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) {
+			pr_debug("Sig %u: Message digest doesn't match\n",
+				 sinfo->index);
+			ret = -EKEYREJECTED;
+			goto error;
+		}
+
+		/* We then calculate anew, using the authenticated attributes
+		 * as the contents of the digest instead.  Note that we need to
+		 * convert the attributes from a CONT.0 into a SET before we
+		 * hash it.
+		 */
+		memset(digest, 0, sinfo->sig.digest_size);
+
+		ret = crypto_shash_init(desc);
+		if (ret < 0)
+			goto error;
+		tag = ASN1_CONS_BIT | ASN1_SET;
+		ret = crypto_shash_update(desc, &tag, 1);
+		if (ret < 0)
+			goto error;
+		ret = crypto_shash_finup(desc, sinfo->authattrs,
+					 sinfo->authattrs_len, digest);
+		if (ret < 0)
+			goto error;
+		pr_devel("AADigest = [%*ph]\n", 8, digest);
+	}
+
+	sinfo->sig.digest = digest;
+	digest = NULL;
+
+error:
+	kfree(digest);
+error_no_desc:
+	crypto_free_shash(tfm);
+	kleave(" = %d", ret);
+	return ret;
+}
+
+/*
+ * Find the key (X.509 certificate) to use to verify a PKCS#7 message.  PKCS#7
+ * uses the issuer's name and the issuing certificate serial number for
+ * matching purposes.  These must match the certificate issuer's name (not
+ * subject's name) and the certificate serial number [RFC 2315 6.7].
+ */
+static int pkcs7_find_key(struct pkcs7_message *pkcs7,
+			  struct pkcs7_signed_info *sinfo)
+{
+	struct x509_certificate *x509;
+	unsigned certix = 1;
+
+	kenter("%u,%u,%u",
+	       sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size);
+
+	for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
+		/* I'm _assuming_ that the generator of the PKCS#7 message will
+		 * encode the fields from the X.509 cert in the same way in the
+		 * PKCS#7 message - but I can't be 100% sure of that.  It's
+		 * possible this will need element-by-element comparison.
+		 */
+		if (x509->raw_serial_size != sinfo->raw_serial_size ||
+		    memcmp(x509->raw_serial, sinfo->raw_serial,
+			   sinfo->raw_serial_size) != 0)
+			continue;
+		pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
+			 sinfo->index, certix);
+
+		if (x509->raw_issuer_size != sinfo->raw_issuer_size ||
+		    memcmp(x509->raw_issuer, sinfo->raw_issuer,
+			   sinfo->raw_issuer_size) != 0) {
+			pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n",
+				sinfo->index);
+			continue;
+		}
+
+		if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
+			pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
+				sinfo->index);
+			continue;
+		}
+
+		sinfo->signer = x509;
+		return 0;
+	}
+	pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n",
+		sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial);
+	return -ENOKEY;
+}
+
+/*
+ * Verify the internal certificate chain as best we can.
+ */
+static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
+				  struct pkcs7_signed_info *sinfo)
+{
+	struct x509_certificate *x509 = sinfo->signer, *p;
+	int ret;
+
+	kenter("");
+
+	for (p = pkcs7->certs; p; p = p->next)
+		p->seen = false;
+
+	for (;;) {
+		pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
+		x509->seen = true;
+		ret = x509_get_sig_params(x509);
+		if (ret < 0)
+			return ret;
+
+		pr_debug("- issuer %s\n", x509->issuer);
+		if (x509->authority)
+			pr_debug("- authkeyid %s\n", x509->authority);
+
+		if (!x509->authority ||
+		    strcmp(x509->subject, x509->issuer) == 0) {
+			/* If there's no authority certificate specified, then
+			 * the certificate must be self-signed and is the root
+			 * of the chain.  Likewise if the cert is its own
+			 * authority.
+			 */
+			pr_debug("- no auth?\n");
+			if (x509->raw_subject_size != x509->raw_issuer_size ||
+			    memcmp(x509->raw_subject, x509->raw_issuer,
+				   x509->raw_issuer_size) != 0)
+				return 0;
+
+			ret = x509_check_signature(x509->pub, x509);
+			if (ret < 0)
+				return ret;
+			x509->signer = x509;
+			pr_debug("- self-signed\n");
+			return 0;
+		}
+
+		/* Look through the X.509 certificates in the PKCS#7 message's
+		 * list to see if the next one is there.
+		 */
+		pr_debug("- want %s\n", x509->authority);
+		for (p = pkcs7->certs; p; p = p->next) {
+			pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint);
+			if (p->raw_subject_size == x509->raw_issuer_size &&
+			    strcmp(p->fingerprint, x509->authority) == 0 &&
+			    memcmp(p->raw_subject, x509->raw_issuer,
+				   x509->raw_issuer_size) == 0)
+				goto found_issuer;
+		}
+
+		/* We didn't find the root of this chain */
+		pr_debug("- top\n");
+		return 0;
+
+	found_issuer:
+		pr_debug("- issuer %s\n", p->subject);
+		if (p->seen) {
+			pr_warn("Sig %u: X.509 chain contains loop\n",
+				sinfo->index);
+			return 0;
+		}
+		ret = x509_check_signature(p->pub, x509);
+		if (ret < 0)
+			return ret;
+		x509->signer = p;
+		if (x509 == p) {
+			pr_debug("- self-signed\n");
+			return 0;
+		}
+		x509 = p;
+		might_sleep();
+	}
+}
+
+/*
+ * Verify one signed information block from a PKCS#7 message.
+ */
+static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
+			    struct pkcs7_signed_info *sinfo)
+{
+	int ret;
+
+	kenter(",%u", sinfo->index);
+
+	/* First of all, digest the data in the PKCS#7 message and the
+	 * signed information block
+	 */
+	ret = pkcs7_digest(pkcs7, sinfo);
+	if (ret < 0)
+		return ret;
+
+	/* Find the key for the signature */
+	ret = pkcs7_find_key(pkcs7, sinfo);
+	if (ret < 0)
+		return ret;
+
+	pr_devel("Using X.509[%u] for sig %u\n",
+		 sinfo->signer->index, sinfo->index);
+
+	/* Verify the PKCS#7 binary against the key */
+	ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
+	if (ret < 0)
+		return ret;
+
+	pr_devel("Verified signature %u\n", sinfo->index);
+
+	/* Verify the internal certificate chain */
+	return pkcs7_verify_sig_chain(pkcs7, sinfo);
+}
+
+/**
+ * pkcs7_verify - Verify a PKCS#7 message
+ * @pkcs7: The PKCS#7 message to be verified
+ */
+int pkcs7_verify(struct pkcs7_message *pkcs7)
+{
+	struct pkcs7_signed_info *sinfo;
+	struct x509_certificate *x509;
+	int ret, n;
+
+	kenter("");
+
+	for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) {
+		ret = x509_get_sig_params(x509);
+		if (ret < 0)
+			return ret;
+		pr_debug("X.509[%u] %s\n", n, x509->authority);
+	}
+
+	for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
+		ret = pkcs7_verify_one(pkcs7, sinfo);
+		if (ret < 0) {
+			kleave(" = %d", ret);
+			return ret;
+		}
+	}
+
+	kleave(" = 0");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_verify);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/public_key.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/public_key.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/public_key.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/public_key.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,6 +121,7 @@ static int public_key_verify_signature_2
 struct asymmetric_key_subtype public_key_subtype = {
 	.owner			= THIS_MODULE,
 	.name			= "public_key",
+	.name_len		= sizeof("public_key") - 1,
 	.describe		= public_key_describe,
 	.destroy		= public_key_destroy,
 	.verify_signature	= public_key_verify_signature_2,
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/verify_pefile.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/verify_pefile.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/verify_pefile.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/verify_pefile.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,474 @@
+/* Parse a signed PE binary
+ *
+ * Copyright (C) 2014 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.
+ */
+
+#define pr_fmt(fmt) "PEFILE: "fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pe.h>
+#include <linux/asn1.h>
+#include <crypto/pkcs7.h>
+#include <crypto/hash.h>
+#include "verify_pefile.h"
+
+/*
+ * Parse a PE binary.
+ */
+static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
+			       struct pefile_context *ctx)
+{
+	const struct mz_hdr *mz = pebuf;
+	const struct pe_hdr *pe;
+	const struct pe32_opt_hdr *pe32;
+	const struct pe32plus_opt_hdr *pe64;
+	const struct data_directory *ddir;
+	const struct data_dirent *dde;
+	const struct section_header *secs, *sec;
+	size_t cursor, datalen = pelen;
+
+	kenter("");
+
+#define chkaddr(base, x, s)						\
+	do {								\
+		if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \
+			return -ELIBBAD;				\
+	} while (0)
+
+	chkaddr(0, 0, sizeof(*mz));
+	if (mz->magic != MZ_MAGIC)
+		return -ELIBBAD;
+	cursor = sizeof(*mz);
+
+	chkaddr(cursor, mz->peaddr, sizeof(*pe));
+	pe = pebuf + mz->peaddr;
+	if (pe->magic != PE_MAGIC)
+		return -ELIBBAD;
+	cursor = mz->peaddr + sizeof(*pe);
+
+	chkaddr(0, cursor, sizeof(pe32->magic));
+	pe32 = pebuf + cursor;
+	pe64 = pebuf + cursor;
+
+	switch (pe32->magic) {
+	case PE_OPT_MAGIC_PE32:
+		chkaddr(0, cursor, sizeof(*pe32));
+		ctx->image_checksum_offset =
+			(unsigned long)&pe32->csum - (unsigned long)pebuf;
+		ctx->header_size = pe32->header_size;
+		cursor += sizeof(*pe32);
+		ctx->n_data_dirents = pe32->data_dirs;
+		break;
+
+	case PE_OPT_MAGIC_PE32PLUS:
+		chkaddr(0, cursor, sizeof(*pe64));
+		ctx->image_checksum_offset =
+			(unsigned long)&pe64->csum - (unsigned long)pebuf;
+		ctx->header_size = pe64->header_size;
+		cursor += sizeof(*pe64);
+		ctx->n_data_dirents = pe64->data_dirs;
+		break;
+
+	default:
+		pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
+		return -ELIBBAD;
+	}
+
+	pr_debug("checksum @ %x\n", ctx->image_checksum_offset);
+	pr_debug("header size = %x\n", ctx->header_size);
+
+	if (cursor >= ctx->header_size || ctx->header_size >= datalen)
+		return -ELIBBAD;
+
+	if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde))
+		return -ELIBBAD;
+
+	ddir = pebuf + cursor;
+	cursor += sizeof(*dde) * ctx->n_data_dirents;
+
+	ctx->cert_dirent_offset =
+		(unsigned long)&ddir->certs - (unsigned long)pebuf;
+	ctx->certs_size = ddir->certs.size;
+
+	if (!ddir->certs.virtual_address || !ddir->certs.size) {
+		pr_debug("Unsigned PE binary\n");
+		return -EKEYREJECTED;
+	}
+
+	chkaddr(ctx->header_size, ddir->certs.virtual_address,
+		ddir->certs.size);
+	ctx->sig_offset = ddir->certs.virtual_address;
+	ctx->sig_len = ddir->certs.size;
+	pr_debug("cert = %x @%x [%*ph]\n",
+		 ctx->sig_len, ctx->sig_offset,
+		 ctx->sig_len, pebuf + ctx->sig_offset);
+
+	ctx->n_sections = pe->sections;
+	if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec))
+		return -ELIBBAD;
+	ctx->secs = secs = pebuf + cursor;
+
+	return 0;
+}
+
+/*
+ * Check and strip the PE wrapper from around the signature and check that the
+ * remnant looks something like PKCS#7.
+ */
+static int pefile_strip_sig_wrapper(const void *pebuf,
+				    struct pefile_context *ctx)
+{
+	struct win_certificate wrapper;
+	const u8 *pkcs7;
+	unsigned len;
+
+	if (ctx->sig_len < sizeof(wrapper)) {
+		pr_debug("Signature wrapper too short\n");
+		return -ELIBBAD;
+	}
+
+	memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper));
+	pr_debug("sig wrapper = { %x, %x, %x }\n",
+		 wrapper.length, wrapper.revision, wrapper.cert_type);
+
+	/* Both pesign and sbsign round up the length of certificate table
+	 * (in optional header data directories) to 8 byte alignment.
+	 */
+	if (round_up(wrapper.length, 8) != ctx->sig_len) {
+		pr_debug("Signature wrapper len wrong\n");
+		return -ELIBBAD;
+	}
+	if (wrapper.revision != WIN_CERT_REVISION_2_0) {
+		pr_debug("Signature is not revision 2.0\n");
+		return -ENOTSUPP;
+	}
+	if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+		pr_debug("Signature certificate type is not PKCS\n");
+		return -ENOTSUPP;
+	}
+
+	/* It looks like the pkcs signature length in wrapper->length and the
+	 * size obtained from the data dir entries, which lists the total size
+	 * of certificate table, are both aligned to an octaword boundary, so
+	 * we may have to deal with some padding.
+	 */
+	ctx->sig_len = wrapper.length;
+	ctx->sig_offset += sizeof(wrapper);
+	ctx->sig_len -= sizeof(wrapper);
+	if (ctx->sig_len < 4) {
+		pr_debug("Signature data missing\n");
+		return -EKEYREJECTED;
+	}
+
+	/* What's left should be a PKCS#7 cert */
+	pkcs7 = pebuf + ctx->sig_offset;
+	if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
+		goto not_pkcs7;
+
+	switch (pkcs7[1]) {
+	case 0 ... 0x7f:
+		len = pkcs7[1] + 2;
+		goto check_len;
+	case ASN1_INDEFINITE_LENGTH:
+		return 0;
+	case 0x81:
+		len = pkcs7[2] + 3;
+		goto check_len;
+	case 0x82:
+		len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
+		goto check_len;
+	case 0x83 ... 0xff:
+		return -EMSGSIZE;
+	default:
+		goto not_pkcs7;
+	}
+
+check_len:
+	if (len <= ctx->sig_len) {
+		/* There may be padding */
+		ctx->sig_len = len;
+		return 0;
+	}
+not_pkcs7:
+	pr_debug("Signature data not PKCS#7\n");
+	return -ELIBBAD;
+}
+
+/*
+ * Compare two sections for canonicalisation.
+ */
+static int pefile_compare_shdrs(const void *a, const void *b)
+{
+	const struct section_header *shdra = a;
+	const struct section_header *shdrb = b;
+	int rc;
+
+	if (shdra->data_addr > shdrb->data_addr)
+		return 1;
+	if (shdrb->data_addr > shdra->data_addr)
+		return -1;
+
+	if (shdra->virtual_address > shdrb->virtual_address)
+		return 1;
+	if (shdrb->virtual_address > shdra->virtual_address)
+		return -1;
+
+	rc = strcmp(shdra->name, shdrb->name);
+	if (rc != 0)
+		return rc;
+
+	if (shdra->virtual_size > shdrb->virtual_size)
+		return 1;
+	if (shdrb->virtual_size > shdra->virtual_size)
+		return -1;
+
+	if (shdra->raw_data_size > shdrb->raw_data_size)
+		return 1;
+	if (shdrb->raw_data_size > shdra->raw_data_size)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Load the contents of the PE binary into the digest, leaving out the image
+ * checksum and the certificate data block.
+ */
+static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,
+				     struct pefile_context *ctx,
+				     struct shash_desc *desc)
+{
+	unsigned *canon, tmp, loop, i, hashed_bytes;
+	int ret;
+
+	/* Digest the header and data directory, but leave out the image
+	 * checksum and the data dirent for the signature.
+	 */
+	ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset);
+	if (ret < 0)
+		return ret;
+
+	tmp = ctx->image_checksum_offset + sizeof(uint32_t);
+	ret = crypto_shash_update(desc, pebuf + tmp,
+				  ctx->cert_dirent_offset - tmp);
+	if (ret < 0)
+		return ret;
+
+	tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent);
+	ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp);
+	if (ret < 0)
+		return ret;
+
+	canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL);
+	if (!canon)
+		return -ENOMEM;
+
+	/* We have to canonicalise the section table, so we perform an
+	 * insertion sort.
+	 */
+	canon[0] = 0;
+	for (loop = 1; loop < ctx->n_sections; loop++) {
+		for (i = 0; i < loop; i++) {
+			if (pefile_compare_shdrs(&ctx->secs[canon[i]],
+						 &ctx->secs[loop]) > 0) {
+				memmove(&canon[i + 1], &canon[i],
+					(loop - i) * sizeof(canon[0]));
+				break;
+			}
+		}
+		canon[i] = loop;
+	}
+
+	hashed_bytes = ctx->header_size;
+	for (loop = 0; loop < ctx->n_sections; loop++) {
+		i = canon[loop];
+		if (ctx->secs[i].raw_data_size == 0)
+			continue;
+		ret = crypto_shash_update(desc,
+					  pebuf + ctx->secs[i].data_addr,
+					  ctx->secs[i].raw_data_size);
+		if (ret < 0) {
+			kfree(canon);
+			return ret;
+		}
+		hashed_bytes += ctx->secs[i].raw_data_size;
+	}
+	kfree(canon);
+
+	if (pelen > hashed_bytes) {
+		tmp = hashed_bytes + ctx->certs_size;
+		ret = crypto_shash_update(desc,
+					  pebuf + hashed_bytes,
+					  pelen - tmp);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Digest the contents of the PE binary, leaving out the image checksum and the
+ * certificate data block.
+ */
+static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
+			    struct pefile_context *ctx)
+{
+	struct crypto_shash *tfm;
+	struct shash_desc *desc;
+	size_t digest_size, desc_size;
+	void *digest;
+	int ret;
+
+	kenter(",%u", ctx->digest_algo);
+
+	/* Allocate the hashing algorithm we're going to need and find out how
+	 * big the hash operational data will be.
+	 */
+	tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0);
+	if (IS_ERR(tfm))
+		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
+
+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+	digest_size = crypto_shash_digestsize(tfm);
+
+	if (digest_size != ctx->digest_len) {
+		pr_debug("Digest size mismatch (%zx != %x)\n",
+			 digest_size, ctx->digest_len);
+		ret = -EBADMSG;
+		goto error_no_desc;
+	}
+	pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size);
+
+	ret = -ENOMEM;
+	desc = kzalloc(desc_size + digest_size, GFP_KERNEL);
+	if (!desc)
+		goto error_no_desc;
+
+	desc->tfm   = tfm;
+	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = crypto_shash_init(desc);
+	if (ret < 0)
+		goto error;
+
+	ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc);
+	if (ret < 0)
+		goto error;
+
+	digest = (void *)desc + desc_size;
+	ret = crypto_shash_final(desc, digest);
+	if (ret < 0)
+		goto error;
+
+	pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest);
+
+	/* Check that the PE file digest matches that in the MSCODE part of the
+	 * PKCS#7 certificate.
+	 */
+	if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
+		pr_debug("Digest mismatch\n");
+		ret = -EKEYREJECTED;
+	} else {
+		pr_debug("The digests match!\n");
+	}
+
+error:
+	kfree(desc);
+error_no_desc:
+	crypto_free_shash(tfm);
+	kleave(" = %d", ret);
+	return ret;
+}
+
+/**
+ * verify_pefile_signature - Verify the signature on a PE binary image
+ * @pebuf: Buffer containing the PE binary image
+ * @pelen: Length of the binary image
+ * @trust_keyring: Signing certificates to use as starting points
+ * @_trusted: Set to true if trustworth, false otherwise
+ *
+ * Validate that the certificate chain inside the PKCS#7 message inside the PE
+ * binary image intersects keys we already know and trust.
+ *
+ * Returns, in order of descending priority:
+ *
+ *  (*) -ELIBBAD if the image cannot be parsed, or:
+ *
+ *  (*) -EKEYREJECTED if a signature failed to match for which we have a valid
+ *	key, or:
+ *
+ *  (*) 0 if at least one signature chain intersects with the keys in the trust
+ *	keyring, or:
+ *
+ *  (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
+ *	chain.
+ *
+ *  (*) -ENOKEY if we couldn't find a match for any of the signature chains in
+ *	the message.
+ *
+ * May also return -ENOMEM.
+ */
+int verify_pefile_signature(const void *pebuf, unsigned pelen,
+			    struct key *trusted_keyring, bool *_trusted)
+{
+	struct pkcs7_message *pkcs7;
+	struct pefile_context ctx;
+	const void *data;
+	size_t datalen;
+	int ret;
+
+	kenter("");
+
+	memset(&ctx, 0, sizeof(ctx));
+	ret = pefile_parse_binary(pebuf, pelen, &ctx);
+	if (ret < 0)
+		return ret;
+
+	ret = pefile_strip_sig_wrapper(pebuf, &ctx);
+	if (ret < 0)
+		return ret;
+
+	pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len);
+	if (IS_ERR(pkcs7))
+		return PTR_ERR(pkcs7);
+	ctx.pkcs7 = pkcs7;
+
+	ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false);
+	if (ret < 0 || datalen == 0) {
+		pr_devel("PKCS#7 message does not contain data\n");
+		ret = -EBADMSG;
+		goto error;
+	}
+
+	ret = mscode_parse(&ctx);
+	if (ret < 0)
+		goto error;
+
+	pr_debug("Digest: %u [%*ph]\n",
+		 ctx.digest_len, ctx.digest_len, ctx.digest);
+
+	/* Generate the digest and check against the PKCS7 certificate
+	 * contents.
+	 */
+	ret = pefile_digest_pe(pebuf, pelen, &ctx);
+	if (ret < 0)
+		goto error;
+
+	ret = pkcs7_verify(pkcs7);
+	if (ret < 0)
+		goto error;
+
+	ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted);
+
+error:
+	pkcs7_free_message(ctx.pkcs7);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/verify_pefile.h linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/verify_pefile.h
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/verify_pefile.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/verify_pefile.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+/* PE Binary parser bits
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/verify_pefile.h>
+#include <crypto/pkcs7.h>
+#include <crypto/hash_info.h>
+
+struct pefile_context {
+	unsigned	header_size;
+	unsigned	image_checksum_offset;
+	unsigned	cert_dirent_offset;
+	unsigned	n_data_dirents;
+	unsigned	n_sections;
+	unsigned	certs_size;
+	unsigned	sig_offset;
+	unsigned	sig_len;
+	const struct section_header *secs;
+	struct pkcs7_message *pkcs7;
+
+	/* PKCS#7 MS Individual Code Signing content */
+	const void	*digest;		/* Digest */
+	unsigned	digest_len;		/* Digest length */
+	enum hash_algo	digest_algo;		/* Digest algorithm */
+};
+
+#define kenter(FMT, ...)					\
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+/*
+ * mscode_parser.c
+ */
+extern int mscode_parse(struct pefile_context *ctx);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/x509.asn1 linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509.asn1
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/x509.asn1	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509.asn1	2014-09-28 17:29:07.000000000 -0400
@@ -6,7 +6,7 @@ Certificate ::= SEQUENCE {
 
 TBSCertificate ::= SEQUENCE {
 	version           [ 0 ]	Version DEFAULT,
-	serialNumber		CertificateSerialNumber,
+	serialNumber		CertificateSerialNumber ({ x509_note_serial }),
 	signature		AlgorithmIdentifier ({ x509_note_pkey_algo }),
 	issuer			Name ({ x509_note_issuer }),
 	validity		Validity,
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_cert_parser.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_cert_parser.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_cert_parser.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_cert_parser.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
 
 #define pr_fmt(fmt) "X.509: "fmt
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/oid_registry.h>
@@ -52,6 +53,7 @@ void x509_free_certificate(struct x509_c
 		kfree(cert);
 	}
 }
+EXPORT_SYMBOL_GPL(x509_free_certificate);
 
 /*
  * Parse an X.509 certificate
@@ -97,6 +99,7 @@ error_no_ctx:
 error_no_cert:
 	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(x509_cert_parse);
 
 /*
  * Note an OID when we find one for later processing when we know how
@@ -211,6 +214,19 @@ int x509_note_signature(void *context, s
 }
 
 /*
+ * Note the certificate serial number
+ */
+int x509_note_serial(void *context, size_t hdrlen,
+		     unsigned char tag,
+		     const void *value, size_t vlen)
+{
+	struct x509_parse_context *ctx = context;
+	ctx->cert->raw_serial = value;
+	ctx->cert->raw_serial_size = vlen;
+	return 0;
+}
+
+/*
  * Note some of the name segments from which we'll fabricate a name.
  */
 int x509_extract_name_segment(void *context, size_t hdrlen,
@@ -322,6 +338,8 @@ int x509_note_issuer(void *context, size
 		     const void *value, size_t vlen)
 {
 	struct x509_parse_context *ctx = context;
+	ctx->cert->raw_issuer = value;
+	ctx->cert->raw_issuer_size = vlen;
 	return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen);
 }
 
@@ -330,6 +348,8 @@ int x509_note_subject(void *context, siz
 		      const void *value, size_t vlen)
 {
 	struct x509_parse_context *ctx = context;
+	ctx->cert->raw_subject = value;
+	ctx->cert->raw_subject_size = vlen;
 	return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_parser.h linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_parser.h
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_parser.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_parser.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,9 @@
 
 struct x509_certificate {
 	struct x509_certificate *next;
+	struct x509_certificate *signer;	/* Certificate that signed this one */
 	struct public_key *pub;			/* Public key details */
+	struct public_key_signature sig;	/* Signature parameters */
 	char		*issuer;		/* Name of certificate issuer */
 	char		*subject;		/* Name of certificate subject */
 	char		*fingerprint;		/* Key fingerprint as hex */
@@ -25,7 +27,16 @@ struct x509_certificate {
 	unsigned	tbs_size;		/* Size of signed data */
 	unsigned	raw_sig_size;		/* Size of sigature */
 	const void	*raw_sig;		/* Signature data */
-	struct public_key_signature sig;	/* Signature parameters */
+	const void	*raw_serial;		/* Raw serial number in ASN.1 */
+	unsigned	raw_serial_size;
+	unsigned	raw_issuer_size;
+	const void	*raw_issuer;		/* Raw issuer name in ASN.1 */
+	const void	*raw_subject;		/* Raw subject name in ASN.1 */
+	unsigned	raw_subject_size;
+	unsigned	index;
+	bool		seen;			/* Infinite recursion prevention */
+	bool		verified;
+	bool		trusted;
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_public_key.c linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_public_key.c
--- linux-libre-3.16-gnu/crypto/asymmetric_keys/x509_public_key.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/asymmetric_keys/x509_public_key.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,11 +18,86 @@
 #include <linux/asn1_decoder.h>
 #include <keys/asymmetric-subtype.h>
 #include <keys/asymmetric-parser.h>
+#include <keys/system_keyring.h>
 #include <crypto/hash.h>
 #include "asymmetric_keys.h"
 #include "public_key.h"
 #include "x509_parser.h"
 
+static bool use_builtin_keys;
+static char *ca_keyid;
+
+#ifndef MODULE
+static int __init ca_keys_setup(char *str)
+{
+	if (!str)		/* default system keyring */
+		return 1;
+
+	if (strncmp(str, "id:", 3) == 0)
+		ca_keyid = str;	/* owner key 'id:xxxxxx' */
+	else if (strcmp(str, "builtin") == 0)
+		use_builtin_keys = true;
+
+	return 1;
+}
+__setup("ca_keys=", ca_keys_setup);
+#endif
+
+/**
+ * x509_request_asymmetric_key - Request a key by X.509 certificate params.
+ * @keyring: The keys to search.
+ * @subject: The name of the subject to whom the key belongs.
+ * @key_id: The subject key ID as a hex string.
+ *
+ * Find a key in the given keyring by subject name and key ID.  These might,
+ * for instance, be the issuer name and the authority key ID of an X.509
+ * certificate that needs to be verified.
+ */
+struct key *x509_request_asymmetric_key(struct key *keyring,
+					const char *subject,
+					const char *key_id)
+{
+	key_ref_t key;
+	size_t subject_len = strlen(subject), key_id_len = strlen(key_id);
+	char *id;
+
+	/* Construct an identifier "<subjname>:<keyid>". */
+	id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL);
+	if (!id)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(id, subject, subject_len);
+	id[subject_len + 0] = ':';
+	id[subject_len + 1] = ' ';
+	memcpy(id + subject_len + 2, key_id, key_id_len);
+	id[subject_len + 2 + key_id_len] = 0;
+
+	pr_debug("Look up: \"%s\"\n", id);
+
+	key = keyring_search(make_key_ref(keyring, 1),
+			     &key_type_asymmetric, id);
+	if (IS_ERR(key))
+		pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key));
+	kfree(id);
+
+	if (IS_ERR(key)) {
+		switch (PTR_ERR(key)) {
+			/* Hide some search errors */
+		case -EACCES:
+		case -ENOTDIR:
+		case -EAGAIN:
+			return ERR_PTR(-ENOKEY);
+		default:
+			return ERR_CAST(key);
+		}
+	}
+
+	pr_devel("<==%s() = 0 [%x]\n", __func__,
+		 key_serial(key_ref_to_ptr(key)));
+	return key_ref_to_ptr(key);
+}
+EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
+
 /*
  * Set up the signature parameters in an X.509 certificate.  This involves
  * digesting the signed data and extracting the signature.
@@ -103,6 +178,38 @@ int x509_check_signature(const struct pu
 EXPORT_SYMBOL_GPL(x509_check_signature);
 
 /*
+ * Check the new certificate against the ones in the trust keyring.  If one of
+ * those is the signing key and validates the new certificate, then mark the
+ * new certificate as being trusted.
+ *
+ * Return 0 if the new certificate was successfully validated, 1 if we couldn't
+ * find a matching parent certificate in the trusted list and an error if there
+ * is a matching certificate but the signature check fails.
+ */
+static int x509_validate_trust(struct x509_certificate *cert,
+			       struct key *trust_keyring)
+{
+	struct key *key;
+	int ret = 1;
+
+	if (!trust_keyring)
+		return -EOPNOTSUPP;
+
+	if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid))
+		return -EPERM;
+
+	key = x509_request_asymmetric_key(trust_keyring,
+					  cert->issuer, cert->authority);
+	if (!IS_ERR(key))  {
+		if (!use_builtin_keys
+		    || test_bit(KEY_FLAG_BUILTIN, &key->flags))
+			ret = x509_check_signature(key->payload.data, cert);
+		key_put(key);
+	}
+	return ret;
+}
+
+/*
  * Attempt to parse a data blob for a key as an X509 certificate.
  */
 static int x509_key_preparse(struct key_preparsed_payload *prep)
@@ -155,9 +262,13 @@ static int x509_key_preparse(struct key_
 	/* Check the signature on the key if it appears to be self-signed */
 	if (!cert->authority ||
 	    strcmp(cert->fingerprint, cert->authority) == 0) {
-		ret = x509_check_signature(cert->pub, cert);
+		ret = x509_check_signature(cert->pub, cert); /* self-signed */
 		if (ret < 0)
 			goto error_free_cert;
+	} else if (!prep->trusted) {
+		ret = x509_validate_trust(cert, get_system_trusted_keyring());
+		if (!ret)
+			prep->trusted = 1;
 	}
 
 	/* Propose a description */
@@ -177,7 +288,7 @@ static int x509_key_preparse(struct key_
 	__module_get(public_key_subtype.owner);
 	prep->type_data[0] = &public_key_subtype;
 	prep->type_data[1] = cert->fingerprint;
-	prep->payload = cert->pub;
+	prep->payload[0] = cert->pub;
 	prep->description = desc;
 	prep->quotalen = 100;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/cryptd.c linux-libre-3.17-rc7-gnu/crypto/cryptd.c
--- linux-libre-3.16-gnu/crypto/cryptd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/cryptd.c	2014-09-28 17:29:07.000000000 -0400
@@ -233,7 +233,7 @@ static void cryptd_blkcipher_decrypt(str
 }
 
 static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
-				    crypto_completion_t complete)
+				    crypto_completion_t compl)
 {
 	struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
 	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
@@ -241,7 +241,7 @@ static int cryptd_blkcipher_enqueue(stru
 
 	queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm));
 	rctx->complete = req->base.complete;
-	req->base.complete = complete;
+	req->base.complete = compl;
 
 	return cryptd_enqueue_request(queue, &req->base);
 }
@@ -414,7 +414,7 @@ static int cryptd_hash_setkey(struct cry
 }
 
 static int cryptd_hash_enqueue(struct ahash_request *req,
-				crypto_completion_t complete)
+				crypto_completion_t compl)
 {
 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -422,7 +422,7 @@ static int cryptd_hash_enqueue(struct ah
 		cryptd_get_queue(crypto_ahash_tfm(tfm));
 
 	rctx->complete = req->base.complete;
-	req->base.complete = complete;
+	req->base.complete = compl;
 
 	return cryptd_enqueue_request(queue, &req->base);
 }
@@ -667,14 +667,14 @@ static void cryptd_aead_decrypt(struct c
 }
 
 static int cryptd_aead_enqueue(struct aead_request *req,
-				    crypto_completion_t complete)
+				    crypto_completion_t compl)
 {
 	struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
 
 	rctx->complete = req->base.complete;
-	req->base.complete = complete;
+	req->base.complete = compl;
 	return cryptd_enqueue_request(queue, &req->base);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/des_generic.c linux-libre-3.17-rc7-gnu/crypto/des_generic.c
--- linux-libre-3.16-gnu/crypto/des_generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/des_generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -859,13 +859,10 @@ static void des_decrypt(struct crypto_tf
  *   property.
  *
  */
-static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
-			   unsigned int keylen)
+int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key,
+		      unsigned int keylen)
 {
 	const u32 *K = (const u32 *)key;
-	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
-	u32 *expkey = dctx->expkey;
-	u32 *flags = &tfm->crt_flags;
 
 	if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
 		     !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
@@ -880,6 +877,17 @@ static int des3_ede_setkey(struct crypto
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__des3_ede_setkey);
+
+static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
+			   unsigned int keylen)
+{
+	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+	u32 *expkey = dctx->expkey;
+
+	return __des3_ede_setkey(expkey, flags, key, keylen);
+}
 
 static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
@@ -945,6 +953,8 @@ static void des3_ede_decrypt(struct cryp
 
 static struct crypto_alg des_algs[2] = { {
 	.cra_name		=	"des",
+	.cra_driver_name	=	"des-generic",
+	.cra_priority		=	100,
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct des_ctx),
@@ -958,6 +968,8 @@ static struct crypto_alg des_algs[2] = {
 	.cia_decrypt		=	des_decrypt } }
 }, {
 	.cra_name		=	"des3_ede",
+	.cra_driver_name	=	"des3_ede-generic",
+	.cra_priority		=	100,
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES3_EDE_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct des3_ede_ctx),
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/drbg.c linux-libre-3.17-rc7-gnu/crypto/drbg.c
--- linux-libre-3.16-gnu/crypto/drbg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/crypto/drbg.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2041 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ *       Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ *       properties:
+ *		* CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ *		* Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ *		* HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ *		* with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+/*
+ * The order of the DRBG definitions here matter: every DRBG is registered
+ * as stdrng. Each DRBG receives an increasing cra_priority values the later
+ * they are defined in this array (see drbg_fill_array).
+ *
+ * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and
+ * the SHA256 / AES 256 over other ciphers. Thus, the favored
+ * DRBGs are the latest entries in this array.
+ */
+static const struct drbg_core drbg_cores[] = {
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+	{
+		.flags = DRBG_CTR | DRBG_STRENGTH128,
+		.statelen = 32, /* 256 bits as defined in 10.2.1 */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 16,
+		.cra_name = "ctr_aes128",
+		.backend_cra_name = "ecb(aes)",
+	}, {
+		.flags = DRBG_CTR | DRBG_STRENGTH192,
+		.statelen = 40, /* 320 bits as defined in 10.2.1 */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 16,
+		.cra_name = "ctr_aes192",
+		.backend_cra_name = "ecb(aes)",
+	}, {
+		.flags = DRBG_CTR | DRBG_STRENGTH256,
+		.statelen = 48, /* 384 bits as defined in 10.2.1 */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 16,
+		.cra_name = "ctr_aes256",
+		.backend_cra_name = "ecb(aes)",
+	},
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+	{
+		.flags = DRBG_HASH | DRBG_STRENGTH128,
+		.statelen = 55, /* 440 bits */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 20,
+		.cra_name = "sha1",
+		.backend_cra_name = "sha1",
+	}, {
+		.flags = DRBG_HASH | DRBG_STRENGTH256,
+		.statelen = 111, /* 888 bits */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 48,
+		.cra_name = "sha384",
+		.backend_cra_name = "sha384",
+	}, {
+		.flags = DRBG_HASH | DRBG_STRENGTH256,
+		.statelen = 111, /* 888 bits */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 64,
+		.cra_name = "sha512",
+		.backend_cra_name = "sha512",
+	}, {
+		.flags = DRBG_HASH | DRBG_STRENGTH256,
+		.statelen = 55, /* 440 bits */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 32,
+		.cra_name = "sha256",
+		.backend_cra_name = "sha256",
+	},
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+	{
+		.flags = DRBG_HMAC | DRBG_STRENGTH128,
+		.statelen = 20, /* block length of cipher */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 20,
+		.cra_name = "hmac_sha1",
+		.backend_cra_name = "hmac(sha1)",
+	}, {
+		.flags = DRBG_HMAC | DRBG_STRENGTH256,
+		.statelen = 48, /* block length of cipher */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 48,
+		.cra_name = "hmac_sha384",
+		.backend_cra_name = "hmac(sha384)",
+	}, {
+		.flags = DRBG_HMAC | DRBG_STRENGTH256,
+		.statelen = 64, /* block length of cipher */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 64,
+		.cra_name = "hmac_sha512",
+		.backend_cra_name = "hmac(sha512)",
+	}, {
+		.flags = DRBG_HMAC | DRBG_STRENGTH256,
+		.statelen = 32, /* block length of cipher */
+		.max_addtllen = 35,
+		.max_bits = 19,
+		.max_req = 48,
+		.blocklen_bytes = 32,
+		.cra_name = "hmac_sha256",
+		.backend_cra_name = "hmac(sha256)",
+	},
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ *	   to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+	switch (flags & DRBG_STRENGTH_MASK) {
+	case DRBG_STRENGTH128:
+		return 16;
+	case DRBG_STRENGTH192:
+		return 24;
+	case DRBG_STRENGTH256:
+		return 32;
+	default:
+		return 32;
+	}
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ *	true on success
+ *	false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+				      const unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+	int ret = 0;
+	/* skip test if we test the overall system */
+	if (drbg->test_data)
+		return true;
+	/* only perform test in FIPS mode */
+	if (0 == fips_enabled)
+		return true;
+	if (!drbg->fips_primed) {
+		/* Priming of FIPS test */
+		memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+		drbg->fips_primed = true;
+		/* return false due to priming, i.e. another round is needed */
+		return false;
+	}
+	ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+	memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+	/* the test shall pass when the two compared values are not equal */
+	return ret != 0;
+#else
+	return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+				 size_t buflen)
+{
+	unsigned char *byte;
+	uint64_t i;
+
+	byte = buf + (buflen - 1);
+	for (i = 0; i < buflen; i++)
+		*(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+				const unsigned char *add, size_t addlen)
+{
+	/* implied: dstlen > addlen */
+	unsigned char *dstptr;
+	const unsigned char *addptr;
+	unsigned int remainder = 0;
+	size_t len = addlen;
+
+	dstptr = dst + (dstlen-1);
+	addptr = add + (addlen-1);
+	while (len) {
+		remainder += *dstptr + *addptr;
+		*dstptr = remainder & 0xff;
+		remainder >>= 8;
+		len--; dstptr--; addptr--;
+	}
+	len = dstlen - addlen;
+	while (len && remainder > 0) {
+		remainder = *dstptr + 1;
+		*dstptr = remainder & 0xff;
+		remainder >>= 8;
+		len--; dstptr--;
+	}
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+#define CRYPTO_DRBG_CTR_STRING "CTR "
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+			  unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+			unsigned char *out, const unsigned char *key,
+			struct list_head *in)
+{
+	int ret = 0;
+	struct drbg_string *curr = NULL;
+	struct drbg_string data;
+	short cnt = 0;
+
+	drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+	/* 10.4.3 step 1 */
+	memset(out, 0, drbg_blocklen(drbg));
+
+	/* 10.4.3 step 2 / 4 */
+	list_for_each_entry(curr, in, list) {
+		const unsigned char *pos = curr->buf;
+		size_t len = curr->len;
+		/* 10.4.3 step 4.1 */
+		while (len) {
+			/* 10.4.3 step 4.2 */
+			if (drbg_blocklen(drbg) == cnt) {
+				cnt = 0;
+				ret = drbg_kcapi_sym(drbg, key, out, &data);
+				if (ret)
+					return ret;
+			}
+			out[cnt] ^= *pos;
+			pos++;
+			cnt++;
+			len--;
+		}
+	}
+	/* 10.4.3 step 4.2 for last block */
+	if (cnt)
+		ret = drbg_kcapi_sym(drbg, key, out, &data);
+
+	return ret;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
+ * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
+ * the scratchpad is used as follows:
+ * drbg_ctr_update:
+ *	temp
+ *		start: drbg->scratchpad
+ *		length: drbg_statelen(drbg) + drbg_blocklen(drbg)
+ *			note: the cipher writing into this variable works
+ *			blocklen-wise. Now, when the statelen is not a multiple
+ *			of blocklen, the generateion loop below "spills over"
+ *			by at most blocklen. Thus, we need to give sufficient
+ *			memory.
+ *	df_data
+ *		start: drbg->scratchpad +
+ *				drbg_statelen(drbg) + drbg_blocklen(drbg)
+ *		length: drbg_statelen(drbg)
+ *
+ * drbg_ctr_df:
+ *	pad
+ *		start: df_data + drbg_statelen(drbg)
+ *		length: drbg_blocklen(drbg)
+ *	iv
+ *		start: pad + drbg_blocklen(drbg)
+ *		length: drbg_blocklen(drbg)
+ *	temp
+ *		start: iv + drbg_blocklen(drbg)
+ *		length: drbg_satelen(drbg) + drbg_blocklen(drbg)
+ *			note: temp is the buffer that the BCC function operates
+ *			on. BCC operates blockwise. drbg_statelen(drbg)
+ *			is sufficient when the DRBG state length is a multiple
+ *			of the block size. For AES192 (and maybe other ciphers)
+ *			this is not correct and the length for temp is
+ *			insufficient (yes, that also means for such ciphers,
+ *			the final output of all BCC rounds are truncated).
+ *			Therefore, add drbg_blocklen(drbg) to cover all
+ *			possibilities.
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+		       unsigned char *df_data, size_t bytes_to_return,
+		       struct list_head *seedlist)
+{
+	int ret = -EFAULT;
+	unsigned char L_N[8];
+	/* S3 is input */
+	struct drbg_string S1, S2, S4, cipherin;
+	LIST_HEAD(bcc_list);
+	unsigned char *pad = df_data + drbg_statelen(drbg);
+	unsigned char *iv = pad + drbg_blocklen(drbg);
+	unsigned char *temp = iv + drbg_blocklen(drbg);
+	size_t padlen = 0;
+	unsigned int templen = 0;
+	/* 10.4.2 step 7 */
+	unsigned int i = 0;
+	/* 10.4.2 step 8 */
+	const unsigned char *K = (unsigned char *)
+			   "\x00\x01\x02\x03\x04\x05\x06\x07"
+			   "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			   "\x10\x11\x12\x13\x14\x15\x16\x17"
+			   "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+	unsigned char *X;
+	size_t generated_len = 0;
+	size_t inputlen = 0;
+	struct drbg_string *seed = NULL;
+
+	memset(pad, 0, drbg_blocklen(drbg));
+	memset(iv, 0, drbg_blocklen(drbg));
+	memset(temp, 0, drbg_statelen(drbg));
+
+	/* 10.4.2 step 1 is implicit as we work byte-wise */
+
+	/* 10.4.2 step 2 */
+	if ((512/8) < bytes_to_return)
+		return -EINVAL;
+
+	/* 10.4.2 step 2 -- calculate the entire length of all input data */
+	list_for_each_entry(seed, seedlist, list)
+		inputlen += seed->len;
+	drbg_int2byte(&L_N[0], inputlen, 4);
+
+	/* 10.4.2 step 3 */
+	drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+	/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+	padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+	/* wrap the padlen appropriately */
+	if (padlen)
+		padlen = drbg_blocklen(drbg) - padlen;
+	/*
+	 * pad / padlen contains the 0x80 byte and the following zero bytes.
+	 * As the calculated padlen value only covers the number of zero
+	 * bytes, this value has to be incremented by one for the 0x80 byte.
+	 */
+	padlen++;
+	pad[0] = 0x80;
+
+	/* 10.4.2 step 4 -- first fill the linked list and then order it */
+	drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+	list_add_tail(&S1.list, &bcc_list);
+	drbg_string_fill(&S2, L_N, sizeof(L_N));
+	list_add_tail(&S2.list, &bcc_list);
+	list_splice_tail(seedlist, &bcc_list);
+	drbg_string_fill(&S4, pad, padlen);
+	list_add_tail(&S4.list, &bcc_list);
+
+	/* 10.4.2 step 9 */
+	while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+		/*
+		 * 10.4.2 step 9.1 - the padding is implicit as the buffer
+		 * holds zeros after allocation -- even the increment of i
+		 * is irrelevant as the increment remains within length of i
+		 */
+		drbg_int2byte(iv, i, 4);
+		/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+		ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
+		if (ret)
+			goto out;
+		/* 10.4.2 step 9.3 */
+		i++;
+		templen += drbg_blocklen(drbg);
+	}
+
+	/* 10.4.2 step 11 */
+	X = temp + (drbg_keylen(drbg));
+	drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+	/* 10.4.2 step 12: overwriting of outval is implemented in next step */
+
+	/* 10.4.2 step 13 */
+	while (generated_len < bytes_to_return) {
+		short blocklen = 0;
+		/*
+		 * 10.4.2 step 13.1: the truncation of the key length is
+		 * implicit as the key is only drbg_blocklen in size based on
+		 * the implementation of the cipher function callback
+		 */
+		ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+		if (ret)
+			goto out;
+		blocklen = (drbg_blocklen(drbg) <
+				(bytes_to_return - generated_len)) ?
+			    drbg_blocklen(drbg) :
+				(bytes_to_return - generated_len);
+		/* 10.4.2 step 13.2 and 14 */
+		memcpy(df_data + generated_len, X, blocklen);
+		generated_len += blocklen;
+	}
+
+	ret = 0;
+
+out:
+	memset(iv, 0, drbg_blocklen(drbg));
+	memset(temp, 0, drbg_statelen(drbg));
+	memset(pad, 0, drbg_blocklen(drbg));
+	return ret;
+}
+
+/*
+ * update function of CTR DRBG as defined in 10.2.1.2
+ *
+ * The reseed variable has an enhanced meaning compared to the update
+ * functions of the other DRBGs as follows:
+ * 0 => initial seed from initialization
+ * 1 => reseed via drbg_seed
+ * 2 => first invocation from drbg_ctr_update when addtl is present. In
+ *      this case, the df_data scratchpad is not deleted so that it is
+ *      available for another calls to prevent calling the DF function
+ *      again.
+ * 3 => second invocation from drbg_ctr_update. When the update function
+ *      was called with addtl, the df_data memory already contains the
+ *      DFed addtl information and we do not need to call DF again.
+ */
+static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
+			   int reseed)
+{
+	int ret = -EFAULT;
+	/* 10.2.1.2 step 1 */
+	unsigned char *temp = drbg->scratchpad;
+	unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+				 drbg_blocklen(drbg);
+	unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+	unsigned int len = 0;
+	struct drbg_string cipherin;
+	unsigned char prefix = DRBG_PREFIX1;
+
+	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+	if (3 > reseed)
+		memset(df_data, 0, drbg_statelen(drbg));
+
+	/* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+	if (seed) {
+		ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
+		if (ret)
+			goto out;
+	}
+
+	drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+	/*
+	 * 10.2.1.3.2 steps 2 and 3 are already covered as the allocation
+	 * zeroizes all memory during initialization
+	 */
+	while (len < (drbg_statelen(drbg))) {
+		/* 10.2.1.2 step 2.1 */
+		drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+		/*
+		 * 10.2.1.2 step 2.2 */
+		ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+		if (ret)
+			goto out;
+		/* 10.2.1.2 step 2.3 and 3 */
+		len += drbg_blocklen(drbg);
+	}
+
+	/* 10.2.1.2 step 4 */
+	temp_p = temp;
+	df_data_p = df_data;
+	for (len = 0; len < drbg_statelen(drbg); len++) {
+		*temp_p ^= *df_data_p;
+		df_data_p++; temp_p++;
+	}
+
+	/* 10.2.1.2 step 5 */
+	memcpy(drbg->C, temp, drbg_keylen(drbg));
+	/* 10.2.1.2 step 6 */
+	memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+	ret = 0;
+
+out:
+	memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+	if (2 != reseed)
+		memset(df_data, 0, drbg_statelen(drbg));
+	return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static int drbg_ctr_generate(struct drbg_state *drbg,
+			     unsigned char *buf, unsigned int buflen,
+			     struct list_head *addtl)
+{
+	int len = 0;
+	int ret = 0;
+	struct drbg_string data;
+	unsigned char prefix = DRBG_PREFIX1;
+
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+	/* 10.2.1.5.2 step 2 */
+	if (addtl && !list_empty(addtl)) {
+		ret = drbg_ctr_update(drbg, addtl, 2);
+		if (ret)
+			return 0;
+	}
+
+	/* 10.2.1.5.2 step 4.1 */
+	drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+	drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+	while (len < buflen) {
+		int outlen = 0;
+		/* 10.2.1.5.2 step 4.2 */
+		ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
+		if (ret) {
+			len = ret;
+			goto out;
+		}
+		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+			  drbg_blocklen(drbg) : (buflen - len);
+		if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+			/* 10.2.1.5.2 step 6 */
+			drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+			continue;
+		}
+		/* 10.2.1.5.2 step 4.3 */
+		memcpy(buf + len, drbg->scratchpad, outlen);
+		len += outlen;
+		/* 10.2.1.5.2 step 6 */
+		if (len < buflen)
+			drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+	}
+
+	/* 10.2.1.5.2 step 6 */
+	ret = drbg_ctr_update(drbg, NULL, 3);
+	if (ret)
+		len = ret;
+
+out:
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+	return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+	.update		= drbg_ctr_update,
+	.generate	= drbg_ctr_generate,
+	.crypto_init	= drbg_init_sym_kernel,
+	.crypto_fini	= drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+			   unsigned char *outval, const struct list_head *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+#define CRYPTO_DRBG_HMAC_STRING "HMAC "
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
+			    int reseed)
+{
+	int ret = -EFAULT;
+	int i = 0;
+	struct drbg_string seed1, seed2, vdata;
+	LIST_HEAD(seedlist);
+	LIST_HEAD(vdatalist);
+
+	if (!reseed) {
+		/* 10.1.2.3 step 2 */
+		memset(drbg->C, 0, drbg_statelen(drbg));
+		memset(drbg->V, 1, drbg_statelen(drbg));
+	}
+
+	drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&seed1.list, &seedlist);
+	/* buffer of seed2 will be filled in for loop below with one byte */
+	drbg_string_fill(&seed2, NULL, 1);
+	list_add_tail(&seed2.list, &seedlist);
+	/* input data of seed is allowed to be NULL at this point */
+	if (seed)
+		list_splice_tail(seed, &seedlist);
+
+	drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&vdata.list, &vdatalist);
+	for (i = 2; 0 < i; i--) {
+		/* first round uses 0x0, second 0x1 */
+		unsigned char prefix = DRBG_PREFIX0;
+		if (1 == i)
+			prefix = DRBG_PREFIX1;
+		/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+		seed2.buf = &prefix;
+		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
+		if (ret)
+			return ret;
+
+		/* 10.1.2.2 step 2 and 5 -- HMAC for V */
+		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
+		if (ret)
+			return ret;
+
+		/* 10.1.2.2 step 3 */
+		if (!seed)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static int drbg_hmac_generate(struct drbg_state *drbg,
+			      unsigned char *buf,
+			      unsigned int buflen,
+			      struct list_head *addtl)
+{
+	int len = 0;
+	int ret = 0;
+	struct drbg_string data;
+	LIST_HEAD(datalist);
+
+	/* 10.1.2.5 step 2 */
+	if (addtl && !list_empty(addtl)) {
+		ret = drbg_hmac_update(drbg, addtl, 1);
+		if (ret)
+			return ret;
+	}
+
+	drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&data.list, &datalist);
+	while (len < buflen) {
+		unsigned int outlen = 0;
+		/* 10.1.2.5 step 4.1 */
+		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
+		if (ret)
+			return ret;
+		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+			  drbg_blocklen(drbg) : (buflen - len);
+		if (!drbg_fips_continuous_test(drbg, drbg->V))
+			continue;
+
+		/* 10.1.2.5 step 4.2 */
+		memcpy(buf + len, drbg->V, outlen);
+		len += outlen;
+	}
+
+	/* 10.1.2.5 step 6 */
+	if (addtl && !list_empty(addtl))
+		ret = drbg_hmac_update(drbg, addtl, 1);
+	else
+		ret = drbg_hmac_update(drbg, NULL, 1);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+	.update		= drbg_hmac_update,
+	.generate	= drbg_hmac_generate,
+	.crypto_init	= drbg_init_hash_kernel,
+	.crypto_fini	= drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+#define CRYPTO_DRBG_HASH_STRING "HASH "
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ *	start: drbg->scratchpad
+ *	length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ *	start: drbg->scratchpad + drbg_statelen(drbg)
+ *	length: drbg_blocklen(drbg)
+ *
+ * drbg_hash_process_addtl uses the scratchpad, but fully completes
+ * before either of the functions mentioned before are invoked. Therefore,
+ * drbg_hash_process_addtl does not need to be specifically considered.
+ */
+
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+			unsigned char *outval, size_t outlen,
+			struct list_head *entropylist)
+{
+	int ret = 0;
+	size_t len = 0;
+	unsigned char input[5];
+	unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+	struct drbg_string data;
+
+	memset(tmp, 0, drbg_blocklen(drbg));
+
+	/* 10.4.1 step 3 */
+	input[0] = 1;
+	drbg_int2byte(&input[1], (outlen * 8), 4);
+
+	/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+	drbg_string_fill(&data, input, 5);
+	list_add(&data.list, entropylist);
+
+	/* 10.4.1 step 4 */
+	while (len < outlen) {
+		short blocklen = 0;
+		/* 10.4.1 step 4.1 */
+		ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
+		if (ret)
+			goto out;
+		/* 10.4.1 step 4.2 */
+		input[0]++;
+		blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+			    drbg_blocklen(drbg) : (outlen - len);
+		memcpy(outval + len, tmp, blocklen);
+		len += blocklen;
+	}
+
+out:
+	memset(tmp, 0, drbg_blocklen(drbg));
+	return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
+			    int reseed)
+{
+	int ret = 0;
+	struct drbg_string data1, data2;
+	LIST_HEAD(datalist);
+	LIST_HEAD(datalist2);
+	unsigned char *V = drbg->scratchpad;
+	unsigned char prefix = DRBG_PREFIX1;
+
+	memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+	if (!seed)
+		return -EINVAL;
+
+	if (reseed) {
+		/* 10.1.1.3 step 1 */
+		memcpy(V, drbg->V, drbg_statelen(drbg));
+		drbg_string_fill(&data1, &prefix, 1);
+		list_add_tail(&data1.list, &datalist);
+		drbg_string_fill(&data2, V, drbg_statelen(drbg));
+		list_add_tail(&data2.list, &datalist);
+	}
+	list_splice_tail(seed, &datalist);
+
+	/* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+	ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
+	if (ret)
+		goto out;
+
+	/* 10.1.1.2 / 10.1.1.3 step 4  */
+	prefix = DRBG_PREFIX0;
+	drbg_string_fill(&data1, &prefix, 1);
+	list_add_tail(&data1.list, &datalist2);
+	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&data2.list, &datalist2);
+	/* 10.1.1.2 / 10.1.1.3 step 4 */
+	ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
+
+out:
+	memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+	return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+				   struct list_head *addtl)
+{
+	int ret = 0;
+	struct drbg_string data1, data2;
+	LIST_HEAD(datalist);
+	unsigned char prefix = DRBG_PREFIX2;
+
+	/* this is value w as per documentation */
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+	/* 10.1.1.4 step 2 */
+	if (!addtl || list_empty(addtl))
+		return 0;
+
+	/* 10.1.1.4 step 2a */
+	drbg_string_fill(&data1, &prefix, 1);
+	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&data1.list, &datalist);
+	list_add_tail(&data2.list, &datalist);
+	list_splice_tail(addtl, &datalist);
+	ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+	if (ret)
+		goto out;
+
+	/* 10.1.1.4 step 2b */
+	drbg_add_buf(drbg->V, drbg_statelen(drbg),
+		     drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+	return ret;
+}
+
+/* Hashgen defined in 10.1.1.4 */
+static int drbg_hash_hashgen(struct drbg_state *drbg,
+			     unsigned char *buf,
+			     unsigned int buflen)
+{
+	int len = 0;
+	int ret = 0;
+	unsigned char *src = drbg->scratchpad;
+	unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+	struct drbg_string data;
+	LIST_HEAD(datalist);
+	unsigned char prefix = DRBG_PREFIX1;
+
+	memset(src, 0, drbg_statelen(drbg));
+	memset(dst, 0, drbg_blocklen(drbg));
+
+	/* 10.1.1.4 step hashgen 2 */
+	memcpy(src, drbg->V, drbg_statelen(drbg));
+
+	drbg_string_fill(&data, src, drbg_statelen(drbg));
+	list_add_tail(&data.list, &datalist);
+	while (len < buflen) {
+		unsigned int outlen = 0;
+		/* 10.1.1.4 step hashgen 4.1 */
+		ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
+		if (ret) {
+			len = ret;
+			goto out;
+		}
+		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+			  drbg_blocklen(drbg) : (buflen - len);
+		if (!drbg_fips_continuous_test(drbg, dst)) {
+			drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+			continue;
+		}
+		/* 10.1.1.4 step hashgen 4.2 */
+		memcpy(buf + len, dst, outlen);
+		len += outlen;
+		/* 10.1.1.4 hashgen step 4.3 */
+		if (len < buflen)
+			drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+	}
+
+out:
+	memset(drbg->scratchpad, 0,
+	       (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+	return len;
+}
+
+/* generate function for Hash DRBG as defined in  10.1.1.4 */
+static int drbg_hash_generate(struct drbg_state *drbg,
+			      unsigned char *buf, unsigned int buflen,
+			      struct list_head *addtl)
+{
+	int len = 0;
+	int ret = 0;
+	unsigned char req[8];
+	unsigned char prefix = DRBG_PREFIX3;
+	struct drbg_string data1, data2;
+	LIST_HEAD(datalist);
+
+	/* 10.1.1.4 step 2 */
+	ret = drbg_hash_process_addtl(drbg, addtl);
+	if (ret)
+		return ret;
+	/* 10.1.1.4 step 3 */
+	len = drbg_hash_hashgen(drbg, buf, buflen);
+
+	/* this is the value H as documented in 10.1.1.4 */
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+	/* 10.1.1.4 step 4 */
+	drbg_string_fill(&data1, &prefix, 1);
+	list_add_tail(&data1.list, &datalist);
+	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+	list_add_tail(&data2.list, &datalist);
+	ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+	if (ret) {
+		len = ret;
+		goto out;
+	}
+
+	/* 10.1.1.4 step 5 */
+	drbg_add_buf(drbg->V, drbg_statelen(drbg),
+		     drbg->scratchpad, drbg_blocklen(drbg));
+	drbg_add_buf(drbg->V, drbg_statelen(drbg),
+		     drbg->C, drbg_statelen(drbg));
+	drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+	drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+	memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+	return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+	.update		= drbg_hash_update,
+	.generate	= drbg_hash_generate,
+	.crypto_init	= drbg_init_hash_kernel,
+	.crypto_fini	= drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ *	0 on success
+ *	error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+		     bool reseed)
+{
+	int ret = 0;
+	unsigned char *entropy = NULL;
+	size_t entropylen = 0;
+	struct drbg_string data1;
+	LIST_HEAD(seedlist);
+
+	/* 9.1 / 9.2 / 9.3.1 step 3 */
+	if (pers && pers->len > (drbg_max_addtl(drbg))) {
+		pr_devel("DRBG: personalization string too long %zu\n",
+			 pers->len);
+		return -EINVAL;
+	}
+
+	if (drbg->test_data && drbg->test_data->testentropy) {
+		drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+				 drbg->test_data->testentropy->len);
+		pr_devel("DRBG: using test entropy\n");
+	} else {
+		/*
+		 * Gather entropy equal to the security strength of the DRBG.
+		 * With a derivation function, a nonce is required in addition
+		 * to the entropy. A nonce must be at least 1/2 of the security
+		 * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+		 * of the strength. The consideration of a nonce is only
+		 * applicable during initial seeding.
+		 */
+		entropylen = drbg_sec_strength(drbg->core->flags);
+		if (!entropylen)
+			return -EFAULT;
+		if (!reseed)
+			entropylen = ((entropylen + 1) / 2) * 3;
+		pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+			 entropylen);
+		entropy = kzalloc(entropylen, GFP_KERNEL);
+		if (!entropy)
+			return -ENOMEM;
+		get_random_bytes(entropy, entropylen);
+		drbg_string_fill(&data1, entropy, entropylen);
+	}
+	list_add_tail(&data1.list, &seedlist);
+
+	/*
+	 * concatenation of entropy with personalization str / addtl input)
+	 * the variable pers is directly handed in by the caller, so check its
+	 * contents whether it is appropriate
+	 */
+	if (pers && pers->buf && 0 < pers->len) {
+		list_add_tail(&pers->list, &seedlist);
+		pr_devel("DRBG: using personalization string\n");
+	}
+
+	ret = drbg->d_ops->update(drbg, &seedlist, reseed);
+	if (ret)
+		goto out;
+
+	drbg->seeded = true;
+	/* 10.1.1.2 / 10.1.1.3 step 5 */
+	drbg->reseed_ctr = 1;
+
+out:
+	if (entropy)
+		kzfree(entropy);
+	return ret;
+}
+
+/* Free all substructures in a DRBG state without the DRBG state structure */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+	if (!drbg)
+		return;
+	if (drbg->V)
+		kzfree(drbg->V);
+	drbg->V = NULL;
+	if (drbg->C)
+		kzfree(drbg->C);
+	drbg->C = NULL;
+	if (drbg->scratchpad)
+		kzfree(drbg->scratchpad);
+	drbg->scratchpad = NULL;
+	drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+	if (drbg->prev)
+		kzfree(drbg->prev);
+	drbg->prev = NULL;
+	drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state.
+ * The DRBG state structure must already be allocated.
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+	int ret = -ENOMEM;
+	unsigned int sb_size = 0;
+
+	if (!drbg)
+		return -EINVAL;
+
+	drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+	if (!drbg->V)
+		goto err;
+	drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+	if (!drbg->C)
+		goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+	drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+	if (!drbg->prev)
+		goto err;
+	drbg->fips_primed = false;
+#endif
+	/* scratchpad is only generated for CTR and Hash */
+	if (drbg->core->flags & DRBG_HMAC)
+		sb_size = 0;
+	else if (drbg->core->flags & DRBG_CTR)
+		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+			  drbg_statelen(drbg) +	/* df_data */
+			  drbg_blocklen(drbg) +	/* pad */
+			  drbg_blocklen(drbg) +	/* iv */
+			  drbg_statelen(drbg) + drbg_blocklen(drbg); /* temp */
+	else
+		sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+	if (0 < sb_size) {
+		drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+		if (!drbg->scratchpad)
+			goto err;
+	}
+	spin_lock_init(&drbg->drbg_lock);
+	return 0;
+
+err:
+	drbg_dealloc_state(drbg);
+	return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+				  struct drbg_state *dst)
+{
+	if (!src || !dst)
+		return;
+	memcpy(dst->V, src->V, drbg_statelen(src));
+	memcpy(dst->C, src->C, drbg_statelen(src));
+	dst->reseed_ctr = src->reseed_ctr;
+	dst->seeded = src->seeded;
+	dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+	dst->fips_primed = src->fips_primed;
+	memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+	/*
+	 * Not copied:
+	 * scratchpad is initialized drbg_alloc_state;
+	 * priv_data is initialized with call to crypto_init;
+	 * d_ops and core are set outside, as these parameters are const;
+	 * test_data is set outside to prevent it being copied back.
+	 */
+}
+
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+	int ret = -ENOMEM;
+	struct drbg_state *tmp = NULL;
+
+	if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+		pr_devel("DRBG: attempt to generate shadow copy for "
+			 "uninitialized DRBG state rejected\n");
+		return -EINVAL;
+	}
+	/* HMAC does not have a scratchpad */
+	if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+		return -EINVAL;
+
+	tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	/* read-only data as they are defined as const, no lock needed */
+	tmp->core = drbg->core;
+	tmp->d_ops = drbg->d_ops;
+
+	ret = drbg_alloc_state(tmp);
+	if (ret)
+		goto err;
+
+	spin_lock_bh(&drbg->drbg_lock);
+	drbg_copy_drbg(drbg, tmp);
+	/* only make a link to the test buffer, as we only read that data */
+	tmp->test_data = drbg->test_data;
+	spin_unlock_bh(&drbg->drbg_lock);
+	*shadow = tmp;
+	return 0;
+
+err:
+	if (tmp)
+		kzfree(tmp);
+	return ret;
+}
+
+static void drbg_restore_shadow(struct drbg_state *drbg,
+				struct drbg_state **shadow)
+{
+	struct drbg_state *tmp = *shadow;
+
+	spin_lock_bh(&drbg->drbg_lock);
+	drbg_copy_drbg(tmp, drbg);
+	spin_unlock_bh(&drbg->drbg_lock);
+	drbg_dealloc_state(tmp);
+	kzfree(tmp);
+	*shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ *      be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ *	   bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ *	  the entropy is pulled by the DRBG internally unconditionally
+ *	  as defined in SP800-90A. The additional input is mixed into
+ *	  the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static int drbg_generate(struct drbg_state *drbg,
+			 unsigned char *buf, unsigned int buflen,
+			 struct drbg_string *addtl)
+{
+	int len = 0;
+	struct drbg_state *shadow = NULL;
+	LIST_HEAD(addtllist);
+	struct drbg_string timestamp;
+	union {
+		cycles_t cycles;
+		unsigned char char_cycles[sizeof(cycles_t)];
+	} now;
+
+	if (0 == buflen || !buf) {
+		pr_devel("DRBG: no output buffer provided\n");
+		return -EINVAL;
+	}
+	if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+		pr_devel("DRBG: wrong format of additional information\n");
+		return -EINVAL;
+	}
+
+	len = drbg_make_shadow(drbg, &shadow);
+	if (len) {
+		pr_devel("DRBG: shadow copy cannot be generated\n");
+		return len;
+	}
+
+	/* 9.3.1 step 2 */
+	len = -EINVAL;
+	if (buflen > (drbg_max_request_bytes(shadow))) {
+		pr_devel("DRBG: requested random numbers too large %u\n",
+			 buflen);
+		goto err;
+	}
+
+	/* 9.3.1 step 3 is implicit with the chosen DRBG */
+
+	/* 9.3.1 step 4 */
+	if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+		pr_devel("DRBG: additional information string too long %zu\n",
+			 addtl->len);
+		goto err;
+	}
+	/* 9.3.1 step 5 is implicit with the chosen DRBG */
+
+	/*
+	 * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented
+	 * here. The spec is a bit convoluted here, we make it simpler.
+	 */
+	if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+		shadow->seeded = false;
+
+	/* allocate cipher handle */
+	if (shadow->d_ops->crypto_init) {
+		len = shadow->d_ops->crypto_init(shadow);
+		if (len)
+			goto err;
+	}
+
+	if (shadow->pr || !shadow->seeded) {
+		pr_devel("DRBG: reseeding before generation (prediction "
+			 "resistance: %s, state %s)\n",
+			 drbg->pr ? "true" : "false",
+			 drbg->seeded ? "seeded" : "unseeded");
+		/* 9.3.1 steps 7.1 through 7.3 */
+		len = drbg_seed(shadow, addtl, true);
+		if (len)
+			goto err;
+		/* 9.3.1 step 7.4 */
+		addtl = NULL;
+	}
+
+	/*
+	 * Mix the time stamp into the DRBG state if the DRBG is not in
+	 * test mode. If there are two callers invoking the DRBG at the same
+	 * time, i.e. before the first caller merges its shadow state back,
+	 * both callers would obtain the same random number stream without
+	 * changing the state here.
+	 */
+	if (!drbg->test_data) {
+		now.cycles = random_get_entropy();
+		drbg_string_fill(&timestamp, now.char_cycles, sizeof(cycles_t));
+		list_add_tail(&timestamp.list, &addtllist);
+	}
+	if (addtl && 0 < addtl->len)
+		list_add_tail(&addtl->list, &addtllist);
+	/* 9.3.1 step 8 and 10 */
+	len = shadow->d_ops->generate(shadow, buf, buflen, &addtllist);
+
+	/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+	shadow->reseed_ctr++;
+	if (0 >= len)
+		goto err;
+
+	/*
+	 * Section 11.3.3 requires to re-perform self tests after some
+	 * generated random numbers. The chosen value after which self
+	 * test is performed is arbitrary, but it should be reasonable.
+	 * However, we do not perform the self tests because of the following
+	 * reasons: it is mathematically impossible that the initial self tests
+	 * were successfully and the following are not. If the initial would
+	 * pass and the following would not, the kernel integrity is violated.
+	 * In this case, the entire kernel operation is questionable and it
+	 * is unlikely that the integrity violation only affects the
+	 * correct operation of the DRBG.
+	 *
+	 * Albeit the following code is commented out, it is provided in
+	 * case somebody has a need to implement the test of 11.3.3.
+	 */
+#if 0
+	if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+		int err = 0;
+		pr_devel("DRBG: start to perform self test\n");
+		if (drbg->core->flags & DRBG_HMAC)
+			err = alg_test("drbg_pr_hmac_sha256",
+				       "drbg_pr_hmac_sha256", 0, 0);
+		else if (drbg->core->flags & DRBG_CTR)
+			err = alg_test("drbg_pr_ctr_aes128",
+				       "drbg_pr_ctr_aes128", 0, 0);
+		else
+			err = alg_test("drbg_pr_sha256",
+				       "drbg_pr_sha256", 0, 0);
+		if (err) {
+			pr_err("DRBG: periodical self test failed\n");
+			/*
+			 * uninstantiate implies that from now on, only errors
+			 * are returned when reusing this DRBG cipher handle
+			 */
+			drbg_uninstantiate(drbg);
+			drbg_dealloc_state(shadow);
+			kzfree(shadow);
+			return 0;
+		} else {
+			pr_devel("DRBG: self test successful\n");
+		}
+	}
+#endif
+
+err:
+	if (shadow->d_ops->crypto_fini)
+		shadow->d_ops->crypto_fini(shadow);
+	drbg_restore_shadow(drbg, &shadow);
+	return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ *		 the entire drbg_generate_long request fails
+ */
+static int drbg_generate_long(struct drbg_state *drbg,
+			      unsigned char *buf, unsigned int buflen,
+			      struct drbg_string *addtl)
+{
+	int len = 0;
+	unsigned int slice = 0;
+	do {
+		int tmplen = 0;
+		unsigned int chunk = 0;
+		slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+		chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+		tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+		if (0 >= tmplen)
+			return tmplen;
+		len += tmplen;
+	} while (slice > 0 && (len < buflen));
+	return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ *	 the entropy is pulled by the DRBG internally unconditionally
+ *	 as defined in SP800-90A. The additional input is mixed into
+ *	 the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ *	0 on success
+ *	error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+			    int coreref, bool pr)
+{
+	int ret = -ENOMEM;
+
+	pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+		 "%s\n", coreref, pr ? "enabled" : "disabled");
+	drbg->core = &drbg_cores[coreref];
+	drbg->pr = pr;
+	drbg->seeded = false;
+	switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+	case DRBG_HMAC:
+		drbg->d_ops = &drbg_hmac_ops;
+		break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+	case DRBG_HASH:
+		drbg->d_ops = &drbg_hash_ops;
+		break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+	case DRBG_CTR:
+		drbg->d_ops = &drbg_ctr_ops;
+		break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	/* 9.1 step 1 is implicit with the selected DRBG type */
+
+	/*
+	 * 9.1 step 2 is implicit as caller can select prediction resistance
+	 * and the flag is copied into drbg->flags --
+	 * all DRBG types support prediction resistance
+	 */
+
+	/* 9.1 step 4 is implicit in  drbg_sec_strength */
+
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+		goto err;
+	ret = drbg_seed(drbg, pers, false);
+	if (drbg->d_ops->crypto_fini)
+		drbg->d_ops->crypto_fini(drbg);
+	if (ret)
+		goto err;
+
+	return 0;
+
+err:
+	drbg_dealloc_state(drbg);
+	return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ *	0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+	spin_lock_bh(&drbg->drbg_lock);
+	drbg_dealloc_state(drbg);
+	/* no scrubbing of test_data -- this shall survive an uninstantiate */
+	spin_unlock_bh(&drbg->drbg_lock);
+	return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+				     struct drbg_test_data *test_data)
+{
+	if (!test_data || !test_data->testentropy)
+		return;
+	spin_lock_bh(&drbg->drbg_lock);
+	drbg->test_data = test_data;
+	spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto API cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+	struct sdesc *sdesc;
+	struct crypto_shash *tfm;
+
+	tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_info("DRBG: could not allocate digest TFM handle\n");
+		return PTR_ERR(tfm);
+	}
+	BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+	sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+			GFP_KERNEL);
+	if (!sdesc) {
+		crypto_free_shash(tfm);
+		return -ENOMEM;
+	}
+
+	sdesc->shash.tfm = tfm;
+	sdesc->shash.flags = 0;
+	drbg->priv_data = sdesc;
+	return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+	if (sdesc) {
+		crypto_free_shash(sdesc->shash.tfm);
+		kzfree(sdesc);
+	}
+	drbg->priv_data = NULL;
+	return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+			   unsigned char *outval, const struct list_head *in)
+{
+	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+	struct drbg_string *input = NULL;
+
+	if (key)
+		crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+	crypto_shash_init(&sdesc->shash);
+	list_for_each_entry(input, in, list)
+		crypto_shash_update(&sdesc->shash, input->buf, input->len);
+	return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+	int ret = 0;
+	struct crypto_blkcipher *tfm;
+
+	tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_info("DRBG: could not allocate cipher TFM handle\n");
+		return PTR_ERR(tfm);
+	}
+	BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
+	drbg->priv_data = tfm;
+	return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+	struct crypto_blkcipher *tfm =
+		(struct crypto_blkcipher *)drbg->priv_data;
+	if (tfm)
+		crypto_free_blkcipher(tfm);
+	drbg->priv_data = NULL;
+	return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+			  unsigned char *outval, const struct drbg_string *in)
+{
+	int ret = 0;
+	struct scatterlist sg_in, sg_out;
+	struct blkcipher_desc desc;
+	struct crypto_blkcipher *tfm =
+		(struct crypto_blkcipher *)drbg->priv_data;
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+	crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+	/* there is only component in *in */
+	sg_init_one(&sg_in, in->buf, in->len);
+	sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+	ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+	return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the drbg_cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ *  the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_driver_name,
+					 int *coreref, bool *pr)
+{
+	int i = 0;
+	size_t start = 0;
+	int len = 0;
+
+	*pr = true;
+	/* disassemble the names */
+	if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
+		start = 10;
+		*pr = false;
+	} else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
+		start = 8;
+	} else {
+		return;
+	}
+
+	/* remove the first part */
+	len = strlen(cra_driver_name) - start;
+	for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
+		if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
+			    len)) {
+			*coreref = i;
+			return;
+		}
+	}
+}
+
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+	struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+	bool pr = false;
+	int coreref = 0;
+
+	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm), &coreref, &pr);
+	/*
+	 * when personalization string is needed, the caller must call reset
+	 * and provide the personalization string as seed information
+	 */
+	return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+	drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+			     unsigned int dlen)
+{
+	struct drbg_state *drbg = crypto_rng_ctx(tfm);
+	if (0 < dlen) {
+		return drbg_generate_long(drbg, rdata, dlen, NULL);
+	} else {
+		struct drbg_gen *data = (struct drbg_gen *)rdata;
+		struct drbg_string addtl;
+		/* catch NULL pointer */
+		if (!data)
+			return 0;
+		drbg_set_testdata(drbg, data->test_data);
+		/* linked list variable is now local to allow modification */
+		drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len);
+		return drbg_generate_long(drbg, data->outbuf, data->outlen,
+					  &addtl);
+	}
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+	struct drbg_state *drbg = crypto_rng_ctx(tfm);
+	struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+	bool pr = false;
+	struct drbg_string seed_string;
+	int coreref = 0;
+
+	drbg_uninstantiate(drbg);
+	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
+			      &pr);
+	if (0 < slen) {
+		drbg_string_fill(&seed_string, seed, slen);
+		return drbg_instantiate(drbg, &seed_string, coreref, pr);
+	} else {
+		struct drbg_gen *data = (struct drbg_gen *)seed;
+		/* allow invocation of API call with NULL, 0 */
+		if (!data)
+			return drbg_instantiate(drbg, NULL, coreref, pr);
+		drbg_set_testdata(drbg, data->test_data);
+		/* linked list variable is now local to allow modification */
+		drbg_string_fill(&seed_string, data->addtl->buf,
+				 data->addtl->len);
+		return drbg_instantiate(drbg, &seed_string, coreref, pr);
+	}
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note: testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ *
+ * Note 2: There is no sensible way of testing the reseed counter
+ * enforcement, so skip it.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+	int len = 0;
+#define OUTBUFLEN 16
+	unsigned char buf[OUTBUFLEN];
+	struct drbg_state *drbg = NULL;
+	int ret = -EFAULT;
+	int rc = -EFAULT;
+	bool pr = false;
+	int coreref = 0;
+	struct drbg_string addtl;
+	size_t max_addtllen, max_request_bytes;
+
+	/* only perform test in FIPS mode */
+	if (!fips_enabled)
+		return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+	drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+	drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
+#else
+	drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref, &pr);
+#endif
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return -ENOMEM;
+
+	/*
+	 * if the following tests fail, it is likely that there is a buffer
+	 * overflow as buf is much smaller than the requested or provided
+	 * string lengths -- in case the error handling does not succeed
+	 * we may get an OOPS. And we want to get an OOPS as this is a
+	 * grave bug.
+	 */
+
+	/* get a valid instance of DRBG for following tests */
+	ret = drbg_instantiate(drbg, NULL, coreref, pr);
+	if (ret) {
+		rc = ret;
+		goto outbuf;
+	}
+	max_addtllen = drbg_max_addtl(drbg);
+	max_request_bytes = drbg_max_request_bytes(drbg);
+	drbg_string_fill(&addtl, buf, max_addtllen + 1);
+	/* overflow addtllen with additonal info string */
+	len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+	BUG_ON(0 < len);
+	/* overflow max_bits */
+	len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+	BUG_ON(0 < len);
+	drbg_uninstantiate(drbg);
+
+	/* overflow max addtllen with personalization string */
+	ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+	BUG_ON(0 == ret);
+	/* all tests passed */
+	rc = 0;
+
+	pr_devel("DRBG: Sanity tests for failure code paths successfully "
+		 "completed\n");
+
+	drbg_uninstantiate(drbg);
+outbuf:
+	kzfree(drbg);
+	return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+	return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from drbg_cores[] is used.
+ */
+static inline void __init drbg_fill_array(struct crypto_alg *alg,
+					  const struct drbg_core *core, int pr)
+{
+	int pos = 0;
+	static int priority = 100;
+
+	memset(alg, 0, sizeof(struct crypto_alg));
+	memcpy(alg->cra_name, "stdrng", 6);
+	if (pr) {
+		memcpy(alg->cra_driver_name, "drbg_pr_", 8);
+		pos = 8;
+	} else {
+		memcpy(alg->cra_driver_name, "drbg_nopr_", 10);
+		pos = 10;
+	}
+	memcpy(alg->cra_driver_name + pos, core->cra_name,
+	       strlen(core->cra_name));
+
+	alg->cra_priority = priority;
+	priority++;
+	/*
+	 * If FIPS mode enabled, the selected DRBG shall have the
+	 * highest cra_priority over other stdrng instances to ensure
+	 * it is selected.
+	 */
+	if (fips_enabled)
+		alg->cra_priority += 200;
+
+	alg->cra_flags		= CRYPTO_ALG_TYPE_RNG;
+	alg->cra_ctxsize 	= sizeof(struct drbg_state);
+	alg->cra_type		= &crypto_rng_type;
+	alg->cra_module		= THIS_MODULE;
+	alg->cra_init		= drbg_kcapi_init;
+	alg->cra_exit		= drbg_kcapi_cleanup;
+	alg->cra_u.rng.rng_make_random	= drbg_kcapi_random;
+	alg->cra_u.rng.rng_reset	= drbg_kcapi_reset;
+	alg->cra_u.rng.seedsize	= 0;
+}
+
+static int __init drbg_init(void)
+{
+	unsigned int i = 0; /* pointer to drbg_algs */
+	unsigned int j = 0; /* pointer to drbg_cores */
+	int ret = -EFAULT;
+
+	ret = drbg_healthcheck_sanity();
+	if (ret)
+		return ret;
+
+	if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
+		pr_info("DRBG: Cannot register all DRBG types"
+			"(slots needed: %zu, slots available: %zu)\n",
+			ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
+		return ret;
+	}
+
+	/*
+	 * each DRBG definition can be used with PR and without PR, thus
+	 * we instantiate each DRBG in drbg_cores[] twice.
+	 *
+	 * As the order of placing them into the drbg_algs array matters
+	 * (the later DRBGs receive a higher cra_priority) we register the
+	 * prediction resistance DRBGs first as the should not be too
+	 * interesting.
+	 */
+	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
+	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
+	return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+static void __exit drbg_exit(void)
+{
+	crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+#ifndef CRYPTO_DRBG_HASH_STRING
+#define CRYPTO_DRBG_HASH_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_HMAC_STRING
+#define CRYPTO_DRBG_HMAC_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_CTR_STRING
+#define CRYPTO_DRBG_CTR_STRING ""
+#endif
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
+		   "using following cores: "
+		   CRYPTO_DRBG_HASH_STRING
+		   CRYPTO_DRBG_HMAC_STRING
+		   CRYPTO_DRBG_CTR_STRING);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/eseqiv.c linux-libre-3.17-rc7-gnu/crypto/eseqiv.c
--- linux-libre-3.16-gnu/crypto/eseqiv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/eseqiv.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ static int eseqiv_givencrypt(struct skci
 	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
 	struct ablkcipher_request *subreq;
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	void *data;
 	struct scatterlist *osrc, *odst;
 	struct scatterlist *dst;
@@ -86,7 +86,7 @@ static int eseqiv_givencrypt(struct skci
 	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
 
 	giv = req->giv;
-	complete = req->creq.base.complete;
+	compl = req->creq.base.complete;
 	data = req->creq.base.data;
 
 	osrc = req->creq.src;
@@ -101,11 +101,11 @@ static int eseqiv_givencrypt(struct skci
 	if (vsrc != giv + ivsize && vdst != giv + ivsize) {
 		giv = PTR_ALIGN((u8 *)reqctx->tail,
 				crypto_ablkcipher_alignmask(geniv) + 1);
-		complete = eseqiv_complete;
+		compl = eseqiv_complete;
 		data = req;
 	}
 
-	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+	ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
 					data);
 
 	sg_init_table(reqctx->src, 2);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/gcm.c linux-libre-3.17-rc7-gnu/crypto/gcm.c
--- linux-libre-3.16-gnu/crypto/gcm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/gcm.c	2014-09-28 17:29:07.000000000 -0400
@@ -228,14 +228,14 @@ static void gcm_hash_final_done(struct c
 
 static int gcm_hash_update(struct aead_request *req,
 			   struct crypto_gcm_req_priv_ctx *pctx,
-			   crypto_completion_t complete,
+			   crypto_completion_t compl,
 			   struct scatterlist *src,
 			   unsigned int len)
 {
 	struct ahash_request *ahreq = &pctx->u.ahreq;
 
 	ahash_request_set_callback(ahreq, aead_request_flags(req),
-				   complete, req);
+				   compl, req);
 	ahash_request_set_crypt(ahreq, src, NULL, len);
 
 	return crypto_ahash_update(ahreq);
@@ -244,12 +244,12 @@ static int gcm_hash_update(struct aead_r
 static int gcm_hash_remain(struct aead_request *req,
 			   struct crypto_gcm_req_priv_ctx *pctx,
 			   unsigned int remain,
-			   crypto_completion_t complete)
+			   crypto_completion_t compl)
 {
 	struct ahash_request *ahreq = &pctx->u.ahreq;
 
 	ahash_request_set_callback(ahreq, aead_request_flags(req),
-				   complete, req);
+				   compl, req);
 	sg_init_one(pctx->src, gcm_zeroes, remain);
 	ahash_request_set_crypt(ahreq, pctx->src, NULL, remain);
 
@@ -375,14 +375,14 @@ static void __gcm_hash_assoc_remain_done
 {
 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	unsigned int remain = 0;
 
 	if (!err && gctx->cryptlen) {
 		remain = gcm_remain(gctx->cryptlen);
-		complete = remain ? gcm_hash_crypt_done :
+		compl = remain ? gcm_hash_crypt_done :
 			gcm_hash_crypt_remain_done;
-		err = gcm_hash_update(req, pctx, complete,
+		err = gcm_hash_update(req, pctx, compl,
 				      gctx->src, gctx->cryptlen);
 		if (err == -EINPROGRESS || err == -EBUSY)
 			return;
@@ -429,14 +429,14 @@ static void gcm_hash_assoc_done(struct c
 static void __gcm_hash_init_done(struct aead_request *req, int err)
 {
 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	unsigned int remain = 0;
 
 	if (!err && req->assoclen) {
 		remain = gcm_remain(req->assoclen);
-		complete = remain ? gcm_hash_assoc_done :
+		compl = remain ? gcm_hash_assoc_done :
 			gcm_hash_assoc_remain_done;
-		err = gcm_hash_update(req, pctx, complete,
+		err = gcm_hash_update(req, pctx, compl,
 				      req->assoc, req->assoclen);
 		if (err == -EINPROGRESS || err == -EBUSY)
 			return;
@@ -462,7 +462,7 @@ static int gcm_hash(struct aead_request
 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
 	struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
 	unsigned int remain;
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	int err;
 
 	ahash_request_set_tfm(ahreq, ctx->ghash);
@@ -473,8 +473,8 @@ static int gcm_hash(struct aead_request
 	if (err)
 		return err;
 	remain = gcm_remain(req->assoclen);
-	complete = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
-	err = gcm_hash_update(req, pctx, complete, req->assoc, req->assoclen);
+	compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
+	err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen);
 	if (err)
 		return err;
 	if (remain) {
@@ -484,8 +484,8 @@ static int gcm_hash(struct aead_request
 			return err;
 	}
 	remain = gcm_remain(gctx->cryptlen);
-	complete = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
-	err = gcm_hash_update(req, pctx, complete, gctx->src, gctx->cryptlen);
+	compl = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
+	err = gcm_hash_update(req, pctx, compl, gctx->src, gctx->cryptlen);
 	if (err)
 		return err;
 	if (remain) {
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/Kconfig linux-libre-3.17-rc7-gnu/crypto/Kconfig
--- linux-libre-3.16-gnu/crypto/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,8 @@ comment "Crypto core or helper"
 
 config CRYPTO_FIPS
 	bool "FIPS 200 compliance"
-	depends on CRYPTO_ANSI_CPRNG && !CRYPTO_MANAGER_DISABLE_TESTS
+	depends on (CRYPTO_ANSI_CPRNG || CRYPTO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
+	depends on MODULE_SIG
 	help
 	  This options enables the fips boot option which is
 	  required if you want to system to operate in a FIPS 200
@@ -540,6 +541,17 @@ config CRYPTO_SHA1_ARM
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
 	  using optimized ARM assembler.
 
+config CRYPTO_SHA1_ARM_NEON
+	tristate "SHA1 digest algorithm (ARM NEON)"
+	depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+	select CRYPTO_SHA1_ARM
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using optimized ARM NEON assembly, when NEON instructions are
+	  available.
+
 config CRYPTO_SHA1_PPC
 	tristate "SHA1 digest algorithm (powerpc)"
 	depends on PPC
@@ -589,6 +601,21 @@ config CRYPTO_SHA512_SPARC64
 	  SHA-512 secure hash standard (DFIPS 180-2) implemented
 	  using sparc64 crypto instructions, when available.
 
+config CRYPTO_SHA512_ARM_NEON
+	tristate "SHA384 and SHA512 digest algorithm (ARM NEON)"
+	depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+	select CRYPTO_SHA512
+	select CRYPTO_HASH
+	help
+	  SHA-512 secure hash standard (DFIPS 180-2) implemented
+	  using ARM NEON instructions, when available.
+
+	  This version of SHA implements a 512 bit hash with 256 bits of
+	  security against collision attacks.
+
+	  This code also includes SHA-384, a 384 bit hash with 192 bits
+	  of security against collision attacks.
+
 config CRYPTO_TGR192
 	tristate "Tiger digest algorithms"
 	select CRYPTO_HASH
@@ -1019,6 +1046,19 @@ config CRYPTO_DES_SPARC64
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3),
 	  optimized using SPARC64 crypto opcodes.
 
+config CRYPTO_DES3_EDE_X86_64
+	tristate "Triple DES EDE cipher algorithm (x86-64)"
+	depends on X86 && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_DES
+	help
+	  Triple DES EDE (FIPS 46-3) algorithm.
+
+	  This module provides implementation of the Triple DES EDE cipher
+	  algorithm that is optimized for x86-64 processors. Two versions of
+	  algorithm are provided; regular processing one input block and
+	  one that processes three blocks parallel.
+
 config CRYPTO_FCRYPT
 	tristate "FCrypt cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -1380,6 +1420,40 @@ config CRYPTO_ANSI_CPRNG
 	  ANSI X9.31 A.2.4. Note that this option must be enabled if
 	  CRYPTO_FIPS is selected
 
+menuconfig CRYPTO_DRBG_MENU
+	tristate "NIST SP800-90A DRBG"
+	help
+	  NIST SP800-90A compliant DRBG. In the following submenu, one or
+	  more of the DRBG types must be selected.
+
+if CRYPTO_DRBG_MENU
+
+config CRYPTO_DRBG_HMAC
+	bool "Enable HMAC DRBG"
+	default y
+	select CRYPTO_HMAC
+	help
+	  Enable the HMAC DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_HASH
+	bool "Enable Hash DRBG"
+	select CRYPTO_HASH
+	help
+	  Enable the Hash DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_CTR
+	bool "Enable CTR DRBG"
+	select CRYPTO_AES
+	help
+	  Enable the CTR DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG
+	tristate
+	default CRYPTO_DRBG_MENU if (CRYPTO_DRBG_HMAC || CRYPTO_DRBG_HASH || CRYPTO_DRBG_CTR)
+	select CRYPTO_RNG
+
+endif	# if CRYPTO_DRBG_MENU
+
 config CRYPTO_USER_API
 	tristate
 
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/lzo.c linux-libre-3.17-rc7-gnu/crypto/lzo.c
--- linux-libre-3.16-gnu/crypto/lzo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/lzo.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/lzo.h>
 
 struct lzo_ctx {
@@ -30,7 +31,10 @@ static int lzo_init(struct crypto_tfm *t
 {
 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
+	ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
+				    GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+	if (!ctx->lzo_comp_mem)
+		ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
 	if (!ctx->lzo_comp_mem)
 		return -ENOMEM;
 
@@ -41,7 +45,7 @@ static void lzo_exit(struct crypto_tfm *
 {
 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	vfree(ctx->lzo_comp_mem);
+	kvfree(ctx->lzo_comp_mem);
 }
 
 static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/Makefile linux-libre-3.17-rc7-gnu/crypto/Makefile
--- linux-libre-3.16-gnu/crypto/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -92,6 +92,7 @@ obj-$(CONFIG_CRYPTO_842) += 842.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
+obj-$(CONFIG_CRYPTO_DRBG) += drbg.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
 obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/seqiv.c linux-libre-3.17-rc7-gnu/crypto/seqiv.c
--- linux-libre-3.16-gnu/crypto/seqiv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/seqiv.c	2014-09-28 17:29:07.000000000 -0400
@@ -100,7 +100,7 @@ static int seqiv_givencrypt(struct skcip
 	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
 	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	void *data;
 	u8 *info;
 	unsigned int ivsize;
@@ -108,7 +108,7 @@ static int seqiv_givencrypt(struct skcip
 
 	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
 
-	complete = req->creq.base.complete;
+	compl = req->creq.base.complete;
 	data = req->creq.base.data;
 	info = req->creq.info;
 
@@ -122,11 +122,11 @@ static int seqiv_givencrypt(struct skcip
 		if (!info)
 			return -ENOMEM;
 
-		complete = seqiv_complete;
+		compl = seqiv_complete;
 		data = req;
 	}
 
-	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+	ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
 					data);
 	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
 				     req->creq.nbytes, info);
@@ -146,7 +146,7 @@ static int seqiv_aead_givencrypt(struct
 	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
 	struct aead_request *areq = &req->areq;
 	struct aead_request *subreq = aead_givcrypt_reqctx(req);
-	crypto_completion_t complete;
+	crypto_completion_t compl;
 	void *data;
 	u8 *info;
 	unsigned int ivsize;
@@ -154,7 +154,7 @@ static int seqiv_aead_givencrypt(struct
 
 	aead_request_set_tfm(subreq, aead_geniv_base(geniv));
 
-	complete = areq->base.complete;
+	compl = areq->base.complete;
 	data = areq->base.data;
 	info = areq->iv;
 
@@ -168,11 +168,11 @@ static int seqiv_aead_givencrypt(struct
 		if (!info)
 			return -ENOMEM;
 
-		complete = seqiv_aead_complete;
+		compl = seqiv_aead_complete;
 		data = req;
 	}
 
-	aead_request_set_callback(subreq, areq->base.flags, complete, data);
+	aead_request_set_callback(subreq, areq->base.flags, compl, data);
 	aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
 			       info);
 	aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/tcrypt.c linux-libre-3.17-rc7-gnu/crypto/tcrypt.c
--- linux-libre-3.16-gnu/crypto/tcrypt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/tcrypt.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,11 @@
 #define DECRYPT 0
 
 /*
+ * return a string with the driver name
+ */
+#define get_driver_name(tfm_type, tfm) crypto_tfm_alg_driver_name(tfm_type ## _tfm(tfm))
+
+/*
  * Used by test_cipher_speed()
  */
 static unsigned int sec;
@@ -68,13 +73,13 @@ static char *check[] = {
 };
 
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
-			       struct scatterlist *sg, int blen, int sec)
+			       struct scatterlist *sg, int blen, int secs)
 {
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		if (enc)
 			ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
@@ -86,7 +91,7 @@ static int test_cipher_jiffies(struct bl
 	}
 
 	printk("%d operations in %d seconds (%ld bytes)\n",
-	       bcount, sec, (long)bcount * blen);
+	       bcount, secs, (long)bcount * blen);
 	return 0;
 }
 
@@ -138,13 +143,13 @@ out:
 }
 
 static int test_aead_jiffies(struct aead_request *req, int enc,
-				int blen, int sec)
+				int blen, int secs)
 {
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		if (enc)
 			ret = crypto_aead_encrypt(req);
@@ -156,7 +161,7 @@ static int test_aead_jiffies(struct aead
 	}
 
 	printk("%d operations in %d seconds (%ld bytes)\n",
-	       bcount, sec, (long)bcount * blen);
+	       bcount, secs, (long)bcount * blen);
 	return 0;
 }
 
@@ -260,7 +265,7 @@ static void sg_init_aead(struct scatterl
 	}
 }
 
-static void test_aead_speed(const char *algo, int enc, unsigned int sec,
+static void test_aead_speed(const char *algo, int enc, unsigned int secs,
 			    struct aead_speed_template *template,
 			    unsigned int tcount, u8 authsize,
 			    unsigned int aad_size, u8 *keysize)
@@ -305,9 +310,6 @@ static void test_aead_speed(const char *
 	asg = &sg[8];
 	sgout = &asg[8];
 
-
-	printk(KERN_INFO "\ntesting speed of %s %s\n", algo, e);
-
 	tfm = crypto_alloc_aead(algo, 0, 0);
 
 	if (IS_ERR(tfm)) {
@@ -316,6 +318,9 @@ static void test_aead_speed(const char *
 		goto out_notfm;
 	}
 
+	printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+			get_driver_name(crypto_aead, tfm), e);
+
 	req = aead_request_alloc(tfm, GFP_KERNEL);
 	if (!req) {
 		pr_err("alg: aead: Failed to allocate request for %s\n",
@@ -374,8 +379,9 @@ static void test_aead_speed(const char *
 			aead_request_set_crypt(req, sg, sgout, *b_size, iv);
 			aead_request_set_assoc(req, asg, aad_size);
 
-			if (sec)
-				ret = test_aead_jiffies(req, enc, *b_size, sec);
+			if (secs)
+				ret = test_aead_jiffies(req, enc, *b_size,
+							secs);
 			else
 				ret = test_aead_cycles(req, enc, *b_size);
 
@@ -405,7 +411,7 @@ out_noxbuf:
 	return;
 }
 
-static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
 			      struct cipher_speed_template *template,
 			      unsigned int tcount, u8 *keysize)
 {
@@ -422,8 +428,6 @@ static void test_cipher_speed(const char
 	else
 		e = "decryption";
 
-	printk("\ntesting speed of %s %s\n", algo, e);
-
 	tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
 
 	if (IS_ERR(tfm)) {
@@ -434,6 +438,9 @@ static void test_cipher_speed(const char
 	desc.tfm = tfm;
 	desc.flags = 0;
 
+	printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+			get_driver_name(crypto_blkcipher, tfm), e);
+
 	i = 0;
 	do {
 
@@ -483,9 +490,9 @@ static void test_cipher_speed(const char
 				crypto_blkcipher_set_iv(tfm, iv, iv_len);
 			}
 
-			if (sec)
+			if (secs)
 				ret = test_cipher_jiffies(&desc, enc, sg,
-							  *b_size, sec);
+							  *b_size, secs);
 			else
 				ret = test_cipher_cycles(&desc, enc, sg,
 							 *b_size);
@@ -506,13 +513,13 @@ out:
 
 static int test_hash_jiffies_digest(struct hash_desc *desc,
 				    struct scatterlist *sg, int blen,
-				    char *out, int sec)
+				    char *out, int secs)
 {
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		ret = crypto_hash_digest(desc, sg, blen, out);
 		if (ret)
@@ -520,22 +527,22 @@ static int test_hash_jiffies_digest(stru
 	}
 
 	printk("%6u opers/sec, %9lu bytes/sec\n",
-	       bcount / sec, ((long)bcount * blen) / sec);
+	       bcount / secs, ((long)bcount * blen) / secs);
 
 	return 0;
 }
 
 static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
-			     int blen, int plen, char *out, int sec)
+			     int blen, int plen, char *out, int secs)
 {
 	unsigned long start, end;
 	int bcount, pcount;
 	int ret;
 
 	if (plen == blen)
-		return test_hash_jiffies_digest(desc, sg, blen, out, sec);
+		return test_hash_jiffies_digest(desc, sg, blen, out, secs);
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		ret = crypto_hash_init(desc);
 		if (ret)
@@ -552,7 +559,7 @@ static int test_hash_jiffies(struct hash
 	}
 
 	printk("%6u opers/sec, %9lu bytes/sec\n",
-	       bcount / sec, ((long)bcount * blen) / sec);
+	       bcount / secs, ((long)bcount * blen) / secs);
 
 	return 0;
 }
@@ -673,7 +680,7 @@ static void test_hash_sg_init(struct sca
 	}
 }
 
-static void test_hash_speed(const char *algo, unsigned int sec,
+static void test_hash_speed(const char *algo, unsigned int secs,
 			    struct hash_speed *speed)
 {
 	struct scatterlist sg[TVMEMSIZE];
@@ -683,8 +690,6 @@ static void test_hash_speed(const char *
 	int i;
 	int ret;
 
-	printk(KERN_INFO "\ntesting speed of %s\n", algo);
-
 	tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
 
 	if (IS_ERR(tfm)) {
@@ -693,6 +698,9 @@ static void test_hash_speed(const char *
 		return;
 	}
 
+	printk(KERN_INFO "\ntesting speed of %s (%s)\n", algo,
+			get_driver_name(crypto_hash, tfm));
+
 	desc.tfm = tfm;
 	desc.flags = 0;
 
@@ -718,9 +726,9 @@ static void test_hash_speed(const char *
 		       "(%5u byte blocks,%5u bytes per update,%4u updates): ",
 		       i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
 
-		if (sec)
+		if (secs)
 			ret = test_hash_jiffies(&desc, sg, speed[i].blen,
-						speed[i].plen, output, sec);
+						speed[i].plen, output, secs);
 		else
 			ret = test_hash_cycles(&desc, sg, speed[i].blen,
 					       speed[i].plen, output);
@@ -765,13 +773,13 @@ static inline int do_one_ahash_op(struct
 }
 
 static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
-				     char *out, int sec)
+				     char *out, int secs)
 {
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		ret = do_one_ahash_op(req, crypto_ahash_digest(req));
 		if (ret)
@@ -779,22 +787,22 @@ static int test_ahash_jiffies_digest(str
 	}
 
 	printk("%6u opers/sec, %9lu bytes/sec\n",
-	       bcount / sec, ((long)bcount * blen) / sec);
+	       bcount / secs, ((long)bcount * blen) / secs);
 
 	return 0;
 }
 
 static int test_ahash_jiffies(struct ahash_request *req, int blen,
-			      int plen, char *out, int sec)
+			      int plen, char *out, int secs)
 {
 	unsigned long start, end;
 	int bcount, pcount;
 	int ret;
 
 	if (plen == blen)
-		return test_ahash_jiffies_digest(req, blen, out, sec);
+		return test_ahash_jiffies_digest(req, blen, out, secs);
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		ret = crypto_ahash_init(req);
 		if (ret)
@@ -811,7 +819,7 @@ static int test_ahash_jiffies(struct aha
 	}
 
 	pr_cont("%6u opers/sec, %9lu bytes/sec\n",
-		bcount / sec, ((long)bcount * blen) / sec);
+		bcount / secs, ((long)bcount * blen) / secs);
 
 	return 0;
 }
@@ -911,7 +919,7 @@ out:
 	return 0;
 }
 
-static void test_ahash_speed(const char *algo, unsigned int sec,
+static void test_ahash_speed(const char *algo, unsigned int secs,
 			     struct hash_speed *speed)
 {
 	struct scatterlist sg[TVMEMSIZE];
@@ -921,8 +929,6 @@ static void test_ahash_speed(const char
 	static char output[1024];
 	int i, ret;
 
-	printk(KERN_INFO "\ntesting speed of async %s\n", algo);
-
 	tfm = crypto_alloc_ahash(algo, 0, 0);
 	if (IS_ERR(tfm)) {
 		pr_err("failed to load transform for %s: %ld\n",
@@ -930,6 +936,9 @@ static void test_ahash_speed(const char
 		return;
 	}
 
+	printk(KERN_INFO "\ntesting speed of async %s (%s)\n", algo,
+			get_driver_name(crypto_ahash, tfm));
+
 	if (crypto_ahash_digestsize(tfm) > sizeof(output)) {
 		pr_err("digestsize(%u) > outputbuffer(%zu)\n",
 		       crypto_ahash_digestsize(tfm), sizeof(output));
@@ -960,9 +969,9 @@ static void test_ahash_speed(const char
 
 		ahash_request_set_crypt(req, sg, output, speed[i].plen);
 
-		if (sec)
+		if (secs)
 			ret = test_ahash_jiffies(req, speed[i].blen,
-						 speed[i].plen, output, sec);
+						 speed[i].plen, output, secs);
 		else
 			ret = test_ahash_cycles(req, speed[i].blen,
 						speed[i].plen, output);
@@ -994,13 +1003,13 @@ static inline int do_one_acipher_op(stru
 }
 
 static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
-				int blen, int sec)
+				int blen, int secs)
 {
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		if (enc)
 			ret = do_one_acipher_op(req,
@@ -1014,7 +1023,7 @@ static int test_acipher_jiffies(struct a
 	}
 
 	pr_cont("%d operations in %d seconds (%ld bytes)\n",
-		bcount, sec, (long)bcount * blen);
+		bcount, secs, (long)bcount * blen);
 	return 0;
 }
 
@@ -1065,7 +1074,7 @@ out:
 	return ret;
 }
 
-static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
 			       struct cipher_speed_template *template,
 			       unsigned int tcount, u8 *keysize)
 {
@@ -1083,8 +1092,6 @@ static void test_acipher_speed(const cha
 	else
 		e = "decryption";
 
-	pr_info("\ntesting speed of async %s %s\n", algo, e);
-
 	init_completion(&tresult.completion);
 
 	tfm = crypto_alloc_ablkcipher(algo, 0, 0);
@@ -1095,6 +1102,9 @@ static void test_acipher_speed(const cha
 		return;
 	}
 
+	pr_info("\ntesting speed of async %s (%s) %s\n", algo,
+			get_driver_name(crypto_ablkcipher, tfm), e);
+
 	req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
 	if (!req) {
 		pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
@@ -1168,9 +1178,9 @@ static void test_acipher_speed(const cha
 
 			ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv);
 
-			if (sec)
+			if (secs)
 				ret = test_acipher_jiffies(req, enc,
-							   *b_size, sec);
+							   *b_size, secs);
 			else
 				ret = test_acipher_cycles(req, enc,
 							  *b_size);
@@ -1585,6 +1595,12 @@ static int do_test(int m)
 		test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
 				des3_speed_template, DES3_SPEED_VECTORS,
 				speed_template_24);
+		test_cipher_speed("ctr(des3_ede)", ENCRYPT, sec,
+				des3_speed_template, DES3_SPEED_VECTORS,
+				speed_template_24);
+		test_cipher_speed("ctr(des3_ede)", DECRYPT, sec,
+				des3_speed_template, DES3_SPEED_VECTORS,
+				speed_template_24);
 		break;
 
 	case 202:
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/testmgr.c linux-libre-3.17-rc7-gnu/crypto/testmgr.c
--- linux-libre-3.16-gnu/crypto/testmgr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/testmgr.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <crypto/rng.h>
+#include <crypto/drbg.h>
 
 #include "internal.h"
 
@@ -108,6 +109,11 @@ struct cprng_test_suite {
 	unsigned int count;
 };
 
+struct drbg_test_suite {
+	struct drbg_testvec *vecs;
+	unsigned int count;
+};
+
 struct alg_test_desc {
 	const char *alg;
 	int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -121,6 +127,7 @@ struct alg_test_desc {
 		struct pcomp_test_suite pcomp;
 		struct hash_test_suite hash;
 		struct cprng_test_suite cprng;
+		struct drbg_test_suite drbg;
 	} suite;
 };
 
@@ -191,13 +198,20 @@ static int __test_hash(struct crypto_aha
 	const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
 	unsigned int i, j, k, temp;
 	struct scatterlist sg[8];
-	char result[64];
+	char *result;
+	char *key;
 	struct ahash_request *req;
 	struct tcrypt_result tresult;
 	void *hash_buff;
 	char *xbuf[XBUFSIZE];
 	int ret = -ENOMEM;
 
+	result = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
+	if (!result)
+		return ret;
+	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+	if (!key)
+		goto out_nobuf;
 	if (testmgr_alloc_buf(xbuf))
 		goto out_nobuf;
 
@@ -222,7 +236,7 @@ static int __test_hash(struct crypto_aha
 			goto out;
 
 		j++;
-		memset(result, 0, 64);
+		memset(result, 0, MAX_DIGEST_SIZE);
 
 		hash_buff = xbuf[0];
 		hash_buff += align_offset;
@@ -232,8 +246,14 @@ static int __test_hash(struct crypto_aha
 
 		if (template[i].ksize) {
 			crypto_ahash_clear_flags(tfm, ~0);
-			ret = crypto_ahash_setkey(tfm, template[i].key,
-						  template[i].ksize);
+			if (template[i].ksize > MAX_KEYLEN) {
+				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+				       j, algo, template[i].ksize, MAX_KEYLEN);
+				ret = -EINVAL;
+				goto out;
+			}
+			memcpy(key, template[i].key, template[i].ksize);
+			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
 			if (ret) {
 				printk(KERN_ERR "alg: hash: setkey failed on "
 				       "test %d for %s: ret=%d\n", j, algo,
@@ -293,7 +313,7 @@ static int __test_hash(struct crypto_aha
 
 		if (template[i].np) {
 			j++;
-			memset(result, 0, 64);
+			memset(result, 0, MAX_DIGEST_SIZE);
 
 			temp = 0;
 			sg_init_table(sg, template[i].np);
@@ -312,8 +332,16 @@ static int __test_hash(struct crypto_aha
 			}
 
 			if (template[i].ksize) {
+				if (template[i].ksize > MAX_KEYLEN) {
+					pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+					       j, algo, template[i].ksize,
+					       MAX_KEYLEN);
+					ret = -EINVAL;
+					goto out;
+				}
 				crypto_ahash_clear_flags(tfm, ~0);
-				ret = crypto_ahash_setkey(tfm, template[i].key,
+				memcpy(key, template[i].key, template[i].ksize);
+				ret = crypto_ahash_setkey(tfm, key,
 							  template[i].ksize);
 
 				if (ret) {
@@ -365,6 +393,8 @@ out:
 out_noreq:
 	testmgr_free_buf(xbuf);
 out_nobuf:
+	kfree(key);
+	kfree(result);
 	return ret;
 }
 
@@ -422,6 +452,9 @@ static int __test_aead(struct crypto_aea
 	iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
 	if (!iv)
 		return ret;
+	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+	if (!key)
+		goto out_noxbuf;
 	if (testmgr_alloc_buf(xbuf))
 		goto out_noxbuf;
 	if (testmgr_alloc_buf(axbuf))
@@ -486,7 +519,14 @@ static int __test_aead(struct crypto_aea
 				crypto_aead_set_flags(
 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 
-			key = template[i].key;
+			if (template[i].klen > MAX_KEYLEN) {
+				pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+				       d, j, algo, template[i].klen,
+				       MAX_KEYLEN);
+				ret = -EINVAL;
+				goto out;
+			}
+			memcpy(key, template[i].key, template[i].klen);
 
 			ret = crypto_aead_setkey(tfm, key,
 						 template[i].klen);
@@ -587,7 +627,14 @@ static int __test_aead(struct crypto_aea
 			if (template[i].wk)
 				crypto_aead_set_flags(
 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-			key = template[i].key;
+			if (template[i].klen > MAX_KEYLEN) {
+				pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+				       d, j, algo, template[i].klen,
+				       MAX_KEYLEN);
+				ret = -EINVAL;
+				goto out;
+			}
+			memcpy(key, template[i].key, template[i].klen);
 
 			ret = crypto_aead_setkey(tfm, key, template[i].klen);
 			if (!ret == template[i].fail) {
@@ -769,6 +816,7 @@ out_nooutbuf:
 out_noaxbuf:
 	testmgr_free_buf(xbuf);
 out_noxbuf:
+	kfree(key);
 	kfree(iv);
 	return ret;
 }
@@ -1715,6 +1763,100 @@ static int alg_test_cprng(const struct a
 	return err;
 }
 
+
+static int drbg_cavs_test(struct drbg_testvec *test, int pr,
+			  const char *driver, u32 type, u32 mask)
+{
+	int ret = -EAGAIN;
+	struct crypto_rng *drng;
+	struct drbg_test_data test_data;
+	struct drbg_string addtl, pers, testentropy;
+	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	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);
+		kzfree(buf);
+		return -ENOMEM;
+	}
+
+	test_data.testentropy = &testentropy;
+	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
+	drbg_string_fill(&pers, test->pers, test->perslen);
+	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
+	if (ret) {
+		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
+		goto outbuf;
+	}
+
+	drbg_string_fill(&addtl, test->addtla, test->addtllen);
+	if (pr) {
+		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
+		ret = crypto_drbg_get_bytes_addtl_test(drng,
+			buf, test->expectedlen, &addtl,	&test_data);
+	} else {
+		ret = crypto_drbg_get_bytes_addtl(drng,
+			buf, test->expectedlen, &addtl);
+	}
+	if (ret <= 0) {
+		printk(KERN_ERR "alg: drbg: could not obtain random data for "
+		       "driver %s\n", driver);
+		goto outbuf;
+	}
+
+	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
+	if (pr) {
+		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
+		ret = crypto_drbg_get_bytes_addtl_test(drng,
+			buf, test->expectedlen, &addtl, &test_data);
+	} else {
+		ret = crypto_drbg_get_bytes_addtl(drng,
+			buf, test->expectedlen, &addtl);
+	}
+	if (ret <= 0) {
+		printk(KERN_ERR "alg: drbg: could not obtain random data for "
+		       "driver %s\n", driver);
+		goto outbuf;
+	}
+
+	ret = memcmp(test->expected, buf, test->expectedlen);
+
+outbuf:
+	crypto_free_rng(drng);
+	kzfree(buf);
+	return ret;
+}
+
+
+static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
+			 u32 type, u32 mask)
+{
+	int err = 0;
+	int pr = 0;
+	int i = 0;
+	struct drbg_testvec *template = desc->suite.drbg.vecs;
+	unsigned int tcount = desc->suite.drbg.count;
+
+	if (0 == memcmp(driver, "drbg_pr_", 8))
+		pr = 1;
+
+	for (i = 0; i < tcount; i++) {
+		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
+		if (err) {
+			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
+			       i, driver);
+			err = -EINVAL;
+			break;
+		}
+	}
+	return err;
+
+}
+
 static int alg_test_null(const struct alg_test_desc *desc,
 			     const char *driver, u32 type, u32 mask)
 {
@@ -2458,6 +2600,152 @@ static const struct alg_test_desc alg_te
 		.alg = "digest_null",
 		.test = alg_test_null,
 	}, {
+		.alg = "drbg_nopr_ctr_aes128",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_nopr_ctr_aes128_tv_template,
+				.count = ARRAY_SIZE(drbg_nopr_ctr_aes128_tv_template)
+			}
+		}
+	}, {
+		.alg = "drbg_nopr_ctr_aes192",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_nopr_ctr_aes192_tv_template,
+				.count = ARRAY_SIZE(drbg_nopr_ctr_aes192_tv_template)
+			}
+		}
+	}, {
+		.alg = "drbg_nopr_ctr_aes256",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_nopr_ctr_aes256_tv_template,
+				.count = ARRAY_SIZE(drbg_nopr_ctr_aes256_tv_template)
+			}
+		}
+	}, {
+		/*
+		 * There is no need to specifically test the DRBG with every
+		 * backend cipher -- covered by drbg_nopr_hmac_sha256 test
+		 */
+		.alg = "drbg_nopr_hmac_sha1",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_nopr_hmac_sha256",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_nopr_hmac_sha256_tv_template,
+				.count =
+				ARRAY_SIZE(drbg_nopr_hmac_sha256_tv_template)
+			}
+		}
+	}, {
+		/* covered by drbg_nopr_hmac_sha256 test */
+		.alg = "drbg_nopr_hmac_sha384",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_nopr_hmac_sha512",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "drbg_nopr_sha1",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_nopr_sha256",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_nopr_sha256_tv_template,
+				.count = ARRAY_SIZE(drbg_nopr_sha256_tv_template)
+			}
+		}
+	}, {
+		/* covered by drbg_nopr_sha256 test */
+		.alg = "drbg_nopr_sha384",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_nopr_sha512",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_ctr_aes128",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_pr_ctr_aes128_tv_template,
+				.count = ARRAY_SIZE(drbg_pr_ctr_aes128_tv_template)
+			}
+		}
+	}, {
+		/* covered by drbg_pr_ctr_aes128 test */
+		.alg = "drbg_pr_ctr_aes192",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_ctr_aes256",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_hmac_sha1",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_hmac_sha256",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_pr_hmac_sha256_tv_template,
+				.count = ARRAY_SIZE(drbg_pr_hmac_sha256_tv_template)
+			}
+		}
+	}, {
+		/* covered by drbg_pr_hmac_sha256 test */
+		.alg = "drbg_pr_hmac_sha384",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_hmac_sha512",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "drbg_pr_sha1",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_sha256",
+		.test = alg_test_drbg,
+		.fips_allowed = 1,
+		.suite = {
+			.drbg = {
+				.vecs = drbg_pr_sha256_tv_template,
+				.count = ARRAY_SIZE(drbg_pr_sha256_tv_template)
+			}
+		}
+	}, {
+		/* covered by drbg_pr_sha256 test */
+		.alg = "drbg_pr_sha384",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
+		.alg = "drbg_pr_sha512",
+		.fips_allowed = 1,
+		.test = alg_test_null,
+	}, {
 		.alg = "ecb(__aes-aesni)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/testmgr.h linux-libre-3.17-rc7-gnu/crypto/testmgr.h
--- linux-libre-3.16-gnu/crypto/testmgr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/testmgr.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@
 #define MAX_DIGEST_SIZE		64
 #define MAX_TAP			8
 
-#define MAX_KEYLEN		56
+#define MAX_KEYLEN		160
 #define MAX_IVLEN		32
 
 struct hash_testvec {
@@ -92,6 +92,21 @@ struct cprng_testvec {
 	unsigned short loops;
 };
 
+struct drbg_testvec {
+	unsigned char *entropy;
+	size_t entropylen;
+	unsigned char *entpra;
+	unsigned char *entprb;
+	size_t entprlen;
+	unsigned char *addtla;
+	unsigned char *addtlb;
+	size_t addtllen;
+	unsigned char *pers;
+	size_t perslen;
+	unsigned char *expected;
+	size_t expectedlen;
+};
+
 static char zeroed_string[48];
 
 /*
@@ -1807,18 +1822,59 @@ static struct hash_testvec tgr128_tv_tem
 	},
 };
 
-#define GHASH_TEST_VECTORS 1
+#define GHASH_TEST_VECTORS 5
 
 static struct hash_testvec ghash_tv_template[] =
 {
 	{
-
-		.key	= "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03\xff\xca\xff\x95\xf8\x30\xf0\x61",
+		.key	= "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03"
+			  "\xff\xca\xff\x95\xf8\x30\xf0\x61",
 		.ksize	= 16,
-		.plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+		.plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+			     "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
 		.psize	= 16,
 		.digest	= "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
 			  "\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+	}, {
+		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+			  "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+		.ksize	= 16,
+		.plaintext = "what do ya want for nothing?",
+		.psize	= 28,
+		.digest	= "\x3e\x1f\x5c\x4d\x65\xf0\xef\xce"
+			  "\x0d\x61\x06\x27\x66\x51\xd5\xe2",
+		.np	= 2,
+		.tap	= {14, 14}
+	}, {
+		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+		.ksize	= 16,
+		.plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+		.psize	= 50,
+		.digest	= "\xfb\x49\x8a\x36\xe1\x96\xe1\x96"
+			  "\xe1\x96\xe1\x96\xe1\x96\xe1\x96",
+	}, {
+		.key	= "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
+			  "\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+		.ksize	= 16,
+		.plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+		.psize	= 50,
+		.digest	= "\x2b\x5c\x0c\x7f\x52\xd1\x60\xc2"
+			  "\x49\xed\x6e\x32\x7a\xa9\xbe\x08",
+	}, {
+		.key	= "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+			  "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+		.ksize	= 16,
+		.plaintext = "Test With Truncation",
+		.psize	= 20,
+		.digest	= "\xf8\x94\x87\x2a\x4b\x63\x99\x28"
+			  "\x23\xf7\x93\xf7\x19\xf5\x96\xd9",
 	},
 };
 
@@ -3097,8 +3153,8 @@ static struct cipher_testvec des_enc_tv_
 			  "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	},
 };
 
@@ -3207,8 +3263,8 @@ static struct cipher_testvec des_dec_tv_
 			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	},
 };
 
@@ -3333,8 +3389,8 @@ static struct cipher_testvec des_cbc_enc
 			  "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	},
 };
 
@@ -3442,8 +3498,8 @@ static struct cipher_testvec des_cbc_dec
 			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	},
 };
 
@@ -3517,8 +3573,8 @@ static struct cipher_testvec des_ctr_enc
 			  "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
 		.klen	= 8,
@@ -3663,8 +3719,8 @@ static struct cipher_testvec des_ctr_dec
 			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
 		.rlen	= 248,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 248 - 8, 8 },
+		.np	= 3,
+		.tap	= { 248 - 10, 2, 8 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
 		.klen	= 8,
@@ -3899,8 +3955,8 @@ static struct cipher_testvec des3_ede_en
 			  "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -4064,8 +4120,8 @@ static struct cipher_testvec des3_ede_de
 			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -4244,8 +4300,8 @@ static struct cipher_testvec des3_ede_cb
 			  "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -4424,8 +4480,8 @@ static struct cipher_testvec des3_ede_cb
 			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -4564,8 +4620,8 @@ static struct cipher_testvec des3_ede_ct
 			  "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
 			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -4842,8 +4898,8 @@ static struct cipher_testvec des3_ede_ct
 			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
 			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -5182,8 +5238,8 @@ static struct cipher_testvec bf_enc_tv_t
 			  "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
 		.rlen	= 504,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 504 - 8, 8 },
+		.np	= 3,
+		.tap	= { 504 - 10, 2, 8 },
 	},
 };
 
@@ -5374,8 +5430,8 @@ static struct cipher_testvec bf_dec_tv_t
 			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
 		.rlen	= 504,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 504 - 8, 8 },
+		.np	= 3,
+		.tap	= { 504 - 10, 2, 8 },
 	},
 };
 
@@ -5531,8 +5587,8 @@ static struct cipher_testvec bf_cbc_enc_
 			  "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
 		.rlen	= 504,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 504 - 8, 8 },
+		.np	= 3,
+		.tap	= { 504 - 10, 2, 8 },
 	},
 };
 
@@ -5688,8 +5744,8 @@ static struct cipher_testvec bf_cbc_dec_
 			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
 		.rlen	= 504,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 504 - 8, 8 },
+		.np	= 3,
+		.tap	= { 504 - 10, 2, 8 },
 	},
 };
 
@@ -6694,8 +6750,8 @@ static struct cipher_testvec tf_enc_tv_t
 			  "\x2C\x75\x64\xC4\xCA\xC1\x7E\xD5",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -6862,8 +6918,8 @@ static struct cipher_testvec tf_dec_tv_t
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -7045,8 +7101,8 @@ static struct cipher_testvec tf_cbc_enc_
 			  "\x0A\xA3\x30\x10\x26\x25\x41\x2C",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -7228,8 +7284,8 @@ static struct cipher_testvec tf_cbc_dec_
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -8302,8 +8358,8 @@ static struct cipher_testvec tf_lrw_enc_
 			  "\x11\xd7\xb8\x6e\xea\xe1\x80\x30",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -8555,8 +8611,8 @@ static struct cipher_testvec tf_lrw_dec_
 			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -8897,8 +8953,8 @@ static struct cipher_testvec tf_xts_enc_
 			  "\x37\x30\xe1\x91\x8d\xb3\x2a\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -9240,8 +9296,8 @@ static struct cipher_testvec tf_xts_dec_
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -9438,8 +9494,8 @@ static struct cipher_testvec serpent_enc
 			  "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -9664,8 +9720,8 @@ static struct cipher_testvec serpent_dec
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -9846,8 +9902,8 @@ static struct cipher_testvec serpent_cbc
 			  "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -9987,8 +10043,8 @@ static struct cipher_testvec serpent_cbc
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -11061,8 +11117,8 @@ static struct cipher_testvec serpent_lrw
 			  "\xd9\x51\x0f\xd7\x94\x2f\xc5\xa7",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -11314,8 +11370,8 @@ static struct cipher_testvec serpent_lrw
 			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -11656,8 +11712,8 @@ static struct cipher_testvec serpent_xts
 			  "\xd4\xa0\x91\x98\x11\x5f\x4d\xb1",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -11999,8 +12055,8 @@ static struct cipher_testvec serpent_xts
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -12182,8 +12238,8 @@ static struct cipher_testvec cast6_enc_t
 			  "\x11\x74\x93\x57\xB4\x7E\xC6\x00",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -12353,8 +12409,8 @@ static struct cipher_testvec cast6_dec_t
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -12494,8 +12550,8 @@ static struct cipher_testvec cast6_cbc_e
 			  "\x22\x46\x89\x2D\x0F\x2B\x08\x24",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -12635,8 +12691,8 @@ static struct cipher_testvec cast6_cbc_d
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -12792,8 +12848,8 @@ static struct cipher_testvec cast6_ctr_e
 			  "\xF9\xC5\xDD\x27\xB3\x39\xCB\xCB",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -12949,8 +13005,8 @@ static struct cipher_testvec cast6_ctr_d
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -13096,8 +13152,8 @@ static struct cipher_testvec cast6_lrw_e
 			  "\xC4\xF5\x99\x61\xBC\xBB\x5B\x46",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -13243,8 +13299,8 @@ static struct cipher_testvec cast6_lrw_d
 			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -13392,8 +13448,8 @@ static struct cipher_testvec cast6_xts_e
 			  "\x22\x60\x4E\xE8\xA4\x5D\x85\xB9",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -13541,8 +13597,8 @@ static struct cipher_testvec cast6_xts_d
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -13749,8 +13805,8 @@ static struct cipher_testvec aes_enc_tv_
 			  "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -13921,8 +13977,8 @@ static struct cipher_testvec aes_dec_tv_
 			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -14140,8 +14196,8 @@ static struct cipher_testvec aes_cbc_enc
 			  "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -14359,8 +14415,8 @@ static struct cipher_testvec aes_cbc_dec
 			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -16265,8 +16321,8 @@ static struct cipher_testvec aes_lrw_enc
 			  "\x74\x3f\x7d\x58\x88\x75\xde\x3e",
 		.rlen   = 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	}
 };
 
@@ -16519,8 +16575,8 @@ static struct cipher_testvec aes_lrw_dec
 			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
 		.rlen   = 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	}
 };
 
@@ -16861,8 +16917,8 @@ static struct cipher_testvec aes_xts_enc
 			  "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	}
 };
 
@@ -17203,8 +17259,8 @@ static struct cipher_testvec aes_xts_dec
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	}
 };
 
@@ -17420,8 +17476,8 @@ static struct cipher_testvec aes_ctr_enc
 			  "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
 			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -17775,8 +17831,8 @@ static struct cipher_testvec aes_ctr_dec
 			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
 			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -20743,6 +20799,834 @@ static struct cprng_testvec ansi_cprng_a
 	},
 };
 
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG with prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_pr_sha256_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86"
+			"\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf"
+			"\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6"
+			"\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62"
+			"\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f"
+			"\x67\xb0\x67\x7a\x5e\x9e\x0c\x62",
+		.entprb = (unsigned char *)
+			"\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf"
+			"\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0"
+			"\x8c\xee\xeb\x9c\xf5\x31\x98\x31",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7"
+			"\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49"
+			"\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d"
+			"\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe"
+			"\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1"
+			"\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5"
+			"\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf"
+			"\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6"
+			"\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5"
+			"\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce"
+			"\x30\x81\xa6\x8f\x27\x14\xf8\x1c",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
+			"\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
+			"\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
+			"\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
+			"\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
+			"\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
+		.entprb = (unsigned char *)
+			"\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
+			"\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
+			"\x76\xaa\x55\x04\x8b\x0a\x72\x95",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
+			"\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
+			"\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
+			"\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
+			"\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
+			"\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
+			"\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
+			"\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
+			"\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
+			"\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
+			"\x50\x47\xa3\x63\x81\x16\xaf\x19",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
+			"\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
+			"\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
+		.addtlb = (unsigned char *)
+			"\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
+			"\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
+			"\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
+		.addtllen = 32,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85"
+			"\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72"
+			"\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8"
+			"\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9"
+			"\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60"
+			"\xba\x0a\xde\x57\x5b\x4b\x9f\x29",
+		.entprb = (unsigned char *)
+			"\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd"
+			"\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4"
+			"\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25"
+			"\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde"
+			"\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5"
+			"\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9"
+			"\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c"
+			"\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e"
+			"\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c"
+			"\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae"
+			"\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c"
+			"\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe"
+			"\x90\x35\x0d\x4c\x4d\x85\xe7\x13",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7"
+			"\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90"
+			"\xa4\x1b\xe1\xe2\x53\xcc\x61\x47",
+		.perslen = 32,
+	}, {
+		.entropy = (unsigned char *)
+			"\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6"
+			"\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4"
+			"\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87"
+			"\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c"
+			"\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12"
+			"\x19\xaf\x97\x2d\x5f\xf9\xff\xfc",
+		.entprb = (unsigned char *)
+			"\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73"
+			"\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6"
+			"\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31"
+			"\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65"
+			"\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18"
+			"\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42"
+			"\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50"
+			"\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b"
+			"\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f"
+			"\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0"
+			"\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda"
+			"\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44"
+			"\x63\x4a\x68\x72\xe9\xf5\x55\xfe",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c"
+			"\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff"
+			"\x4a\x85\xca\x80\xfe\x0d\x1c\xd0",
+		.addtlb = (unsigned char *)
+			"\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2"
+			"\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89"
+			"\x42\x58\x9e\xd6\xcc\xad\x7b\x1e",
+		.addtllen = 32,
+		.pers = (unsigned char *)
+			"\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1"
+			"\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52"
+			"\x82\x4c\xdc\x19\xb8\xf8\x92\x5c",
+		.perslen = 32,
+	},
+};
+
+static struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a"
+			"\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96"
+			"\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46"
+			"\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92"
+			"\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46"
+			"\xe2\x9a\x29\x51\x81\x56\x9f\x54",
+		.entprb = (unsigned char *)
+			"\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc"
+			"\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65"
+			"\x8a\x2a\x77\xa8\x69\x90\x89\xf4",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2"
+			"\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1"
+			"\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4"
+			"\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf"
+			"\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc"
+			"\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8"
+			"\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b"
+			"\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e"
+			"\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22"
+			"\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc"
+			"\xb1\xcd\x09\xd6\x92\xd0\x28\x3f",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f"
+			"\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f"
+			"\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05"
+			"\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4"
+			"\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26"
+			"\x46\xd9\x26\xa2\x19\xd4\x94\x43",
+		.entprb = (unsigned char *)
+			"\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79"
+			"\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98"
+			"\x51\x78\x72\xb2\x79\xfd\x2c\xff",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7"
+			"\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda"
+			"\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa"
+			"\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40"
+			"\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda"
+			"\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37"
+			"\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70"
+			"\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b"
+			"\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5"
+			"\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd"
+			"\xcd\x66\xb5\x01\x69\x66\xa0\x3c",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3"
+			"\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56"
+			"\x6d\x99\x3b\xc6\x58\xda\x03\xf6",
+		.addtlb = (unsigned char *)
+			"\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c"
+			"\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44"
+			"\xc6\x03\xa2\xfb\x13\x20\x19\xb7",
+		.addtllen = 32,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
+			"\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
+			"\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
+			"\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
+			"\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
+			"\x20\x28\xad\xf2\x60\xd7\xcd\x45",
+		.entprb = (unsigned char *)
+			"\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
+			"\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
+			"\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
+			"\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
+			"\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
+			"\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
+			"\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
+			"\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
+			"\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
+			"\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
+			"\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
+			"\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
+			"\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
+			"\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
+			"\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
+		.perslen = 32,
+	}, {
+		.entropy = (unsigned char *)
+			"\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd"
+			"\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01"
+			"\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15"
+			"\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb",
+		.entropylen = 48,
+		.entpra = (unsigned char *)
+			"\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a"
+			"\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96"
+			"\xbb\x81\x6a\xcc\xb5\xae\x55\xb6",
+		.entprb = (unsigned char *)
+			"\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2"
+			"\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e"
+			"\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1",
+		.entprlen = 32,
+		.expected = (unsigned char *)
+			"\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14"
+			"\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6"
+			"\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7"
+			"\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77"
+			"\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5"
+			"\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6"
+			"\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1"
+			"\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40"
+			"\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8"
+			"\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72"
+			"\xda\x3f\xad\x2b\xba\x00\x6b\xd1",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03"
+			"\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6"
+			"\x86\x88\x55\x28\xc1\x69\xdd\x76",
+		.addtlb = (unsigned char *)
+			"\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7"
+			"\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa"
+			"\x00\x99\x2a\xdd\x0a\x00\x50\x82",
+		.addtllen = 32,
+		.pers = (unsigned char *)
+			"\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8"
+			"\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda"
+			"\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
+		.perslen = 32,
+	},
+};
+
+static struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42"
+			"\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2",
+		.entropylen = 24,
+		.entpra = (unsigned char *)
+			"\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15"
+			"\xb4\xec\x80\xb1",
+		.entprb = (unsigned char *)
+			"\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9"
+			"\x28\x07\xeb\xc2",
+		.entprlen = 16,
+		.expected = (unsigned char *)
+			"\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe"
+			"\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc"
+			"\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18"
+			"\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce"
+			"\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b"
+			"\x8a\xf1\x23\xa8",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77"
+			"\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94",
+		.entropylen = 24,
+		.entpra = (unsigned char *)
+			"\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73"
+			"\x67\xd1\x08\xf8",
+		.entprb = (unsigned char *)
+			"\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc"
+			"\xd4\xba\x04\x58",
+		.entprlen = 16,
+		.expected = (unsigned char *)
+			"\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d"
+			"\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc"
+			"\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7"
+			"\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc"
+			"\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c"
+			"\xc1\x02\x41\x82",
+		.expectedlen = 64,
+		.addtla = (unsigned char *)
+			"\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8"
+			"\xeb\xb3\x01\x76",
+		.addtlb = (unsigned char *)
+			"\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25"
+			"\xd0\x7f\xcc\x43",
+		.addtllen = 16,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b"
+			"\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8",
+		.entropylen = 24,
+		.entpra = (unsigned char *)
+			"\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66"
+			"\xc3\x0f\xe3\xb0",
+		.entprb = (unsigned char *)
+			"\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8"
+			"\xd6\x9c\x9d\xe8",
+		.entprlen = 16,
+		.expected = (unsigned char *)
+			"\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b"
+			"\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10"
+			"\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69"
+			"\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc"
+			"\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f"
+			"\x72\x82\x0c\xcf",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed"
+			"\x21\x52\xb3\xad",
+		.perslen = 16,
+	}, {
+		.entropy = (unsigned char *)
+			"\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
+			"\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
+		.entropylen = 24,
+		.entpra = (unsigned char *)
+			"\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
+			"\xc4\x2c\xe8\x10",
+		.entprb = (unsigned char *)
+			"\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
+			"\x08\xf7\xa5\x01",
+		.entprlen = 16,
+		.expected = (unsigned char *)
+			"\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
+			"\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
+			"\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
+			"\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
+			"\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
+			"\x23\xc5\x1f\x68",
+		.expectedlen = 64,
+		.addtla = (unsigned char *)
+			"\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
+			"\x23\x6d\xad\x1d",
+		.addtlb = (unsigned char *)
+			"\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
+			"\xbc\x59\x31\x8c",
+		.addtllen = 16,
+		.pers = (unsigned char *)
+			"\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
+			"\x37\x3c\x5c\x0b",
+		.perslen = 16,
+	},
+};
+
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG without prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3"
+			"\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19"
+			"\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31"
+			"\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64"
+			"\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5"
+			"\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3"
+			"\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11"
+			"\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81"
+			"\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63"
+			"\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7"
+			"\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c"
+			"\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91"
+			"\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d"
+			"\xd4\x31\xf4\xc9\xf7\x04\x27\xdf",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
+			"\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
+			"\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
+			"\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
+			"\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
+			"\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
+			"\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
+			"\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
+			"\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
+			"\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
+			"\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
+			"\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
+			"\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
+			"\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
+			"\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
+			"\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
+		.addtlb = (unsigned char *)
+			"\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
+			"\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
+			"\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
+		.addtllen = 32,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb"
+			"\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4"
+			"\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1"
+			"\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28"
+			"\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b"
+			"\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46"
+			"\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6"
+			"\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72"
+			"\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1"
+			"\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77"
+			"\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9"
+			"\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e"
+			"\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16"
+			"\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1"
+			"\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda"
+			"\x57\x6b\xce\xa4\x1c\x66\x3d\xbc",
+		.perslen = 32,
+	}, {
+		.entropy = (unsigned char *)
+			"\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a"
+			"\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74"
+			"\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc"
+			"\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb"
+			"\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13"
+			"\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6"
+			"\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36"
+			"\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64"
+			"\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea"
+			"\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95"
+			"\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e"
+			"\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd"
+			"\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06"
+			"\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2"
+			"\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e"
+			"\x77\xc5\x3d\x9e\x03\xe3\xa5\x78",
+		.addtlb = (unsigned char *)
+			"\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a"
+			"\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b"
+			"\x74\x7f\xa6\xf6\x80\xcd\x9b\x21",
+		.addtllen = 32,
+		.pers = (unsigned char *)
+			"\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20"
+			"\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73"
+			"\xa9\x65\xb1\x10\xc1\xdc\x77\x7c",
+		.perslen = 32,
+	},
+};
+
+static struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
+			"\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
+			"\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c"
+			"\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75"
+			"\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6"
+			"\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97"
+			"\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60"
+			"\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf"
+			"\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99"
+			"\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19"
+			"\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68"
+			"\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0"
+			"\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd"
+			"\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94"
+			"\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15"
+			"\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4"
+			"\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5"
+			"\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf"
+			"\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d"
+			"\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6"
+			"\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16"
+			"\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62"
+			"\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d"
+			"\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4"
+			"\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec"
+			"\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f"
+			"\x50\x9a\x8c\x85\x90\x87\x03\x9c",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d"
+			"\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf"
+			"\x2f\xf3\x00\x34\xd8\x26\x8e\x3b",
+		.addtlb = (unsigned char *)
+			"\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9"
+			"\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14"
+			"\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0",
+		.addtllen = 32,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
+			"\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
+			"\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
+			"\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
+			"\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
+			"\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
+			"\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
+			"\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
+			"\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
+			"\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
+			"\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
+			"\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
+			"\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
+			"\x10\x37\x41\x03\x0c\xcc\x3a\x56",
+		.expectedlen = 128,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
+			"\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
+			"\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
+		.perslen = 32,
+	}, {
+		.entropy = (unsigned char *)
+			"\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78"
+			"\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11"
+			"\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb"
+			"\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0"
+			"\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37"
+			"\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae"
+			"\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0"
+			"\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad"
+			"\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82"
+			"\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7"
+			"\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4"
+			"\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49"
+			"\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30"
+			"\x35\x24\xcc\x9c\xc5\xea\x54\xa1",
+		.expectedlen = 128,
+		.addtla = (unsigned char *)
+			"\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96"
+			"\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62"
+			"\xd3\x13\x3b\x83\xe4\x9c\x82\x0b",
+		.addtlb = (unsigned char *)
+			"\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2"
+			"\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25"
+			"\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1",
+		.addtllen = 32,
+		.pers = (unsigned char *)
+			"\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8"
+			"\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15"
+			"\x36\x60\x3b\xca\x37\xc9\xee\x29",
+		.perslen = 32,
+	},
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9"
+			"\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40"
+			"\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9"
+			"\xac\x9b\xbb\x00",
+		.entropylen = 40,
+		.expected = (unsigned char *)
+			"\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17"
+			"\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33"
+			"\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48"
+			"\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79"
+			"\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf"
+			"\x9a\x9d\xf1\x0d",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	},
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f"
+			"\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec"
+			"\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0"
+			"\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb",
+		.entropylen = 48,
+		.expected = (unsigned char *)
+			"\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6"
+			"\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3"
+			"\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf"
+			"\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16"
+			"\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f"
+			"\xb4\xf0\x7e\x1d",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	},
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
+	{
+		.entropy = (unsigned char *)
+			"\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8"
+			"\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f",
+		.entropylen = 24,
+		.expected = (unsigned char *)
+			"\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1"
+			"\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a"
+			"\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3"
+			"\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e"
+			"\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8"
+			"\xcb\x2d\xd6\xb0",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74"
+			"\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd",
+		.entropylen = 24,
+		.expected = (unsigned char *)
+			"\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34"
+			"\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21"
+			"\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e"
+			"\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1"
+			"\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc"
+			"\xc3\xdf\xb3\x81",
+		.expectedlen = 64,
+		.addtla = (unsigned char *)
+			"\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6"
+			"\x91\x4d\x81\x56",
+		.addtlb = (unsigned char *)
+			"\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb"
+			"\x4a\x55\xd1\xc6",
+		.addtllen = 16,
+		.pers = NULL,
+		.perslen = 0,
+	}, {
+		.entropy = (unsigned char *)
+			"\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9"
+			"\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9",
+		.entropylen = 24,
+		.expected = (unsigned char *)
+			"\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e"
+			"\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75"
+			"\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee"
+			"\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb"
+			"\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45"
+			"\x34\x30\x0c\x3d",
+		.expectedlen = 64,
+		.addtla = NULL,
+		.addtlb = NULL,
+		.addtllen = 0,
+		.pers = (unsigned char *)
+			"\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a"
+			"\x0b\xc6\x97\x54",
+		.perslen = 16,
+	}, {
+		.entropy = (unsigned char *)
+			"\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
+			"\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
+		.entropylen = 24,
+		.expected = (unsigned char *)
+			"\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
+			"\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
+			"\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
+			"\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
+			"\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
+			"\x2b\x49\x1e\x5c",
+		.expectedlen = 64,
+		.addtla = (unsigned char *)
+			"\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
+			"\x44\x85\xe7\xfe",
+		.addtlb = (unsigned char *)
+			"\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
+			"\x82\x16\x62\x7f",
+		.addtllen = 16,
+		.pers = (unsigned char *)
+			"\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
+			"\x8e\xcf\xe0\x02",
+		.perslen = 16,
+	},
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS		4
 #define CAST5_DEC_TEST_VECTORS		4
@@ -20907,8 +21791,8 @@ static struct cipher_testvec cast5_enc_t
 			  "\xF5\xBC\x25\xD6\x02\x56\x57\x1C",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -21068,8 +21952,8 @@ static struct cipher_testvec cast5_dec_t
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -21206,8 +22090,8 @@ static struct cipher_testvec cast5_cbc_e
 			  "\x1D\x18\x66\x44\x5B\x8F\x14\xEB",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -21344,8 +22228,8 @@ static struct cipher_testvec cast5_cbc_d
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -21495,8 +22379,8 @@ static struct cipher_testvec cast5_ctr_e
 			  "\xC0\x0D\x96\xAA\x23\xF8\xFE\x13",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -21646,8 +22530,8 @@ static struct cipher_testvec cast5_ctr_d
 			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
 		.rlen	= 496,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 496 - 16, 16 },
+		.np	= 3,
+		.tap	= { 496 - 20, 4, 16 },
 	},
 };
 
@@ -22805,8 +23689,8 @@ static struct cipher_testvec camellia_en
 			  "\x33\x1A\xBB\xD3\xA2\x7E\x97\x66",
 		.rlen	= 1008,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 1008 - 16, 16 },
+		.np	= 3,
+		.tap	= { 1008 - 20, 4, 16 },
 	},
 };
 
@@ -23105,8 +23989,8 @@ static struct cipher_testvec camellia_de
 			  "\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
 		.rlen	= 1008,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 1008 - 16, 16 },
+		.np	= 3,
+		.tap	= { 1008 - 20, 4, 16 },
 	},
 };
 
@@ -23401,8 +24285,8 @@ static struct cipher_testvec camellia_cb
 			  "\x70\xC5\xB9\x0B\x3B\x7A\x6E\x6C",
 		.rlen	= 1008,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 1008 - 16, 16 },
+		.np	= 3,
+		.tap	= { 1008 - 20, 4, 16 },
 	},
 };
 
@@ -23697,8 +24581,8 @@ static struct cipher_testvec camellia_cb
 			  "\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
 		.rlen	= 1008,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 1008 - 16, 16 },
+		.np	= 3,
+		.tap	= { 1008 - 20, 4, 16 },
 	},
 };
 
@@ -25283,8 +26167,8 @@ static struct cipher_testvec camellia_lr
 			  "\x5a\xa8\x92\x7f\xba\xe6\x0c\x95",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -25536,8 +26420,8 @@ static struct cipher_testvec camellia_lr
 			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -25878,8 +26762,8 @@ static struct cipher_testvec camellia_xt
 			  "\xd5\xc6\x99\xcc\x4e\x6c\x94\x95",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
@@ -26221,8 +27105,8 @@ static struct cipher_testvec camellia_xt
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen	= 512,
 		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 512 - 16, 16 },
+		.np	= 3,
+		.tap	= { 512 - 20, 4, 16 },
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/crypto/zlib.c linux-libre-3.17-rc7-gnu/crypto/zlib.c
--- linux-libre-3.16-gnu/crypto/zlib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/crypto/zlib.c	2014-09-28 17:29:07.000000000 -0400
@@ -168,7 +168,7 @@ static int zlib_compress_update(struct c
 	}
 
 	ret = req->avail_out - stream->avail_out;
-	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+	pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
 		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
@@ -198,7 +198,7 @@ static int zlib_compress_final(struct cr
 	}
 
 	ret = req->avail_out - stream->avail_out;
-	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+	pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
 		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
@@ -283,7 +283,7 @@ static int zlib_decompress_update(struct
 	}
 
 	ret = req->avail_out - stream->avail_out;
-	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+	pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
 		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
@@ -331,7 +331,7 @@ static int zlib_decompress_final(struct
 	}
 
 	ret = req->avail_out - stream->avail_out;
-	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+	pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
 		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/stable/sysfs-bus-usb linux-libre-3.17-rc7-gnu/Documentation/ABI/stable/sysfs-bus-usb
--- linux-libre-3.16-gnu/Documentation/ABI/stable/sysfs-bus-usb	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/stable/sysfs-bus-usb	2014-09-28 17:29:07.000000000 -0400
@@ -3,13 +3,13 @@ Date:		May 2007
 KernelVersion:	2.6.23
 Contact:	Alan Stern <stern@rowland.harvard.edu>
 Description:
-		If CONFIG_USB_PERSIST is set, then each USB device directory
-		will contain a file named power/persist.  The file holds a
-		boolean value (0 or 1) indicating whether or not the
-		"USB-Persist" facility is enabled for the device.  Since the
-		facility is inherently dangerous, it is disabled by default
-		for all devices except hubs.  For more information, see
-		Documentation/usb/persist.txt.
+		USB device directories can contain a file named power/persist.
+		The file holds a boolean value (0 or 1) indicating whether or
+		not the "USB-Persist" facility is enabled for the device.  For
+		hubs this facility is always enabled and their device
+		directories will not contain this file.
+
+		For more information, see Documentation/usb/persist.txt.
 
 What:		/sys/bus/usb/devices/.../power/autosuspend
 Date:		March 2007
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/ima_policy linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/ima_policy
--- linux-libre-3.16-gnu/Documentation/ABI/testing/ima_policy	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/ima_policy	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@ Description:
 			option:	[[appraise_type=]] [permit_directio]
 
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
+				[FIRMWARE_CHECK]
 			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
 			fsmagic:= hex value
 			fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
@@ -57,7 +58,8 @@ Description:
 			measure func=BPRM_CHECK
 			measure func=FILE_MMAP mask=MAY_EXEC
 			measure func=FILE_CHECK mask=MAY_READ uid=0
-			measure func=MODULE_CHECK uid=0
+			measure func=MODULE_CHECK
+			measure func=FIRMWARE_CHECK
 			appraise fowner=0
 
 		The default policy measures all executables in bprm_check,
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-iio linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-iio
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-iio	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-iio	2014-09-28 17:29:07.000000000 -0400
@@ -260,6 +260,10 @@ What:		/sys/bus/iio/devices/iio:deviceX/
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_x_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_y_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_z_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_tilt_comp_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_scale
 KernelVersion:	2.6.35
@@ -447,6 +451,14 @@ What:		/sys/.../iio:deviceX/events/in_ma
 What:		/sys/.../iio:deviceX/events/in_magn_y_thresh_falling_en
 What:		/sys/.../iio:deviceX/events/in_magn_z_thresh_rising_en
 What:		/sys/.../iio:deviceX/events/in_magn_z_thresh_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_thresh_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_thresh_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_thresh_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_thresh_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_thresh_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_thresh_falling_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_supply_thresh_rising_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_supply_thresh_falling_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en
@@ -492,6 +504,14 @@ What:		/sys/.../iio:deviceX/events/in_ma
 What:		/sys/.../iio:deviceX/events/in_magn_y_roc_falling_en
 What:		/sys/.../iio:deviceX/events/in_magn_z_roc_rising_en
 What:		/sys/.../iio:deviceX/events/in_magn_z_roc_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_roc_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_roc_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_roc_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_roc_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_roc_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_roc_falling_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_roc_rising_en
+What:		/sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_roc_falling_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_supply_roc_rising_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_supply_roc_falling_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_roc_rising_en
@@ -538,6 +558,14 @@ What:		/sys/.../events/in_magn_y_raw_thr
 What:		/sys/.../events/in_magn_y_raw_thresh_falling_value
 What:		/sys/.../events/in_magn_z_raw_thresh_rising_value
 What:		/sys/.../events/in_magn_z_raw_thresh_falling_value
+What:		/sys/.../events/in_rot_from_north_magnetic_raw_thresh_rising_value
+What:		/sys/.../events/in_rot_from_north_magnetic_raw_thresh_falling_value
+What:		/sys/.../events/in_rot_from_north_true_raw_thresh_rising_value
+What:		/sys/.../events/in_rot_from_north_true_raw_thresh_falling_value
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_thresh_rising_value
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_thresh_falling_value
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_raw_thresh_rising_value
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_raw_thresh_falling_value
 What:		/sys/.../events/in_voltageY_supply_raw_thresh_rising_value
 What:		/sys/.../events/in_voltageY_supply_raw_thresh_falling_value
 What:		/sys/.../events/in_voltageY_raw_thresh_rising_value
@@ -588,6 +616,18 @@ What:		/sys/.../events/in_magn_y_thresh_
 What:		/sys/.../events/in_magn_z_thresh_rising_hysteresis
 What:		/sys/.../events/in_magn_z_thresh_falling_hysteresis
 What:		/sys/.../events/in_magn_z_thresh_either_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_thresh_rising_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_thresh_falling_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_thresh_either_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_thresh_rising_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_thresh_falling_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_thresh_either_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_hysteresis
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_either_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_thresh_rising_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_thresh_falling_hysteresis
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_thresh_either_hysteresis
 What:		/sys/.../events/in_voltageY_thresh_rising_hysteresis
 What:		/sys/.../events/in_voltageY_thresh_falling_hysteresis
 What:		/sys/.../events/in_voltageY_thresh_either_hysteresis
@@ -635,6 +675,14 @@ What:		/sys/.../events/in_magn_y_raw_roc
 What:		/sys/.../events/in_magn_y_raw_roc_falling_value
 What:		/sys/.../events/in_magn_z_raw_roc_rising_value
 What:		/sys/.../events/in_magn_z_raw_roc_falling_value
+What:		/sys/.../events/in_rot_from_north_magnetic_raw_roc_rising_value
+What:		/sys/.../events/in_rot_from_north_magnetic_raw_roc_falling_value
+What:		/sys/.../events/in_rot_from_north_true_raw_roc_rising_value
+What:		/sys/.../events/in_rot_from_north_true_raw_roc_falling_value
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_roc_rising_value
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_roc_falling_value
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_raw_roc_rising_value
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_raw_roc_falling_value
 What:		/sys/.../events/in_voltageY_supply_raw_roc_rising_value
 What:		/sys/.../events/in_voltageY_supply_raw_roc_falling_value
 What:		/sys/.../events/in_voltageY_raw_roc_rising_value
@@ -690,6 +738,22 @@ What:		/sys/.../events/in_magn_z_thresh_
 What:		/sys/.../events/in_magn_z_thresh_falling_period
 What:		/sys/.../events/in_magn_z_roc_rising_period
 What:		/sys/.../events/in_magn_z_roc_falling_period
+What:		/sys/.../events/in_rot_from_north_magnetic_thresh_rising_period
+What:		/sys/.../events/in_rot_from_north_magnetic_thresh_falling_period
+What:		/sys/.../events/in_rot_from_north_magnetic_roc_rising_period
+What:		/sys/.../events/in_rot_from_north_magnetic_roc_falling_period
+What:		/sys/.../events/in_rot_from_north_true_thresh_rising_period
+What:		/sys/.../events/in_rot_from_north_true_thresh_falling_period
+What:		/sys/.../events/in_rot_from_north_true_roc_rising_period
+What:		/sys/.../events/in_rot_from_north_true_roc_falling_period
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_period
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_period
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_roc_rising_period
+What:		/sys/.../events/in_rot_from_north_magnetic_tilt_comp_roc_falling_period
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_thresh_rising_period
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_thresh_falling_period
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_roc_rising_period
+What:		/sys/.../events/in_rot_from_north_true_tilt_comp_roc_falling_period
 What:		/sys/.../events/in_voltageY_supply_thresh_rising_period
 What:		/sys/.../events/in_voltageY_supply_thresh_falling_period
 What:		/sys/.../events/in_voltageY_supply_roc_rising_period
@@ -787,6 +851,10 @@ What:		/sys/.../iio:deviceX/scan_element
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_x_en
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_y_en
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_z_en
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_en
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_en
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_en
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_en
 What:		/sys/.../iio:deviceX/scan_elements/in_timestamp_en
 What:		/sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en
 What:		/sys/.../iio:deviceX/scan_elements/in_voltageY_en
@@ -853,6 +921,10 @@ What:		/sys/.../iio:deviceX/scan_element
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_x_index
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_y_index
 What:		/sys/.../iio:deviceX/scan_elements/in_magn_z_index
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_index
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_index
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_index
+What:		/sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_index
 What:		/sys/.../iio:deviceX/scan_elements/in_incli_x_index
 What:		/sys/.../iio:deviceX/scan_elements/in_incli_y_index
 What:		/sys/.../iio:deviceX/scan_elements/in_timestamp_index
@@ -895,6 +967,19 @@ Description:
 		on-chip EEPROM. After power-up or chip reset the device will
 		automatically load the saved configuration.
 
+What:		/sys/.../iio:deviceX/in_proximity_raw
+What:		/sys/.../iio:deviceX/in_proximity_input
+What:		/sys/.../iio:deviceX/in_proximityY_raw
+KernelVersion:	3.4
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Proximity measurement indicating that some
+		object is near the sensor, usually be observing
+		reflectivity of infrared or ultrasound emitted.
+		Often these sensors are unit less and as such conversion
+		to SI units is not possible.  Where it is, the units should
+		be meters.
+
 What:		/sys/.../iio:deviceX/in_illuminanceY_input
 What:		/sys/.../iio:deviceX/in_illuminanceY_raw
 What:		/sys/.../iio:deviceX/in_illuminanceY_mean_raw
@@ -933,3 +1018,13 @@ Description:
 		x y z w. Here x, y, and z component represents the axis about
 		which a rotation will occur and w component represents the
 		amount of rotation.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_tilt_comp_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_raw
+KernelVersion:	3.15
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw value of rotation from true/magnetic north measured with
+		or without compensation from tilt sensors.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,11 @@
+What:		/sys/bus/iio/devices/triggerX/trigger_now
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This file is provided by the iio-trig-sysfs stand-alone trigger
+		driver. Writing this file with any value triggers an event
+		driven driver, associated with this trigger, to capture data
+		into an in kernel buffer. This approach can be valuable during
+		automated testing or in situations, where other trigger methods
+		are not applicable. For example no RTC or spare GPIOs.
+		X is the IIO index of the trigger.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-platform linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-platform
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-platform	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-platform	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,20 @@
+What:		/sys/bus/platform/devices/.../driver_override
+Date:		April 2014
+Contact:	Kim Phillips <kim.phillips@freescale.com>
+Description:
+		This file allows the driver for a device to be specified which
+		will override standard OF, ACPI, ID table, and name matching.
+		When specified, only a driver with a name matching the value
+		written to driver_override will have an opportunity to bind
+		to the device.  The override is specified by writing a string
+		to the driver_override file (echo vfio-platform > \
+		driver_override) and may be cleared with an empty string
+		(echo > driver_override).  This returns the device to standard
+		matching rules binding.  Writing to driver_override does not
+		automatically unbind the device from its current driver or make
+		any attempt to automatically load the specified driver.  If no
+		driver with a matching name is currently loaded in the kernel,
+		the device will not bind to any driver.  This also allows
+		devices to opt-out of driver binding using a driver_override
+		name such as "none".  Only a single driver may be specified in
+		the override, there is no support for parsing delimiters.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-rbd linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-rbd
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2014-09-28 17:29:07.000000000 -0400
@@ -94,5 +94,5 @@ current_snap
 
 parent
 
-	Information identifying the pool, image, and snapshot id for
-	the parent image in a layered rbd image (format 2 only).
+	Information identifying the chain of parent images in a layered rbd
+	image.  Entries are separated by empty lines.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-usb-lvstest linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-usb-lvstest
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-bus-usb-lvstest	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-bus-usb-lvstest	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+Link Layer Validation Device is a standard device for testing of Super
+Speed Link Layer tests. These nodes are available in sysfs only when lvs
+driver is bound with root hub device.
+
+What:		/sys/bus/usb/devices/.../get_dev_desc
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Write to this node to issue "Get Device Descriptor"
+		for Link Layer Validation device. It is needed for TD.7.06.
+
+What:		/sys/bus/usb/devices/.../u1_timeout
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Set "U1 timeout" for the downstream port where Link Layer
+		Validation device is connected. Timeout value must be between 0
+		and 127. It is needed for TD.7.18, TD.7.19, TD.7.20 and TD.7.21.
+
+What:		/sys/bus/usb/devices/.../u2_timeout
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Set "U2 timeout" for the downstream port where Link Layer
+		Validation device is connected. Timeout value must be between 0
+		and 127. It is needed for TD.7.18, TD.7.19, TD.7.20 and TD.7.21.
+
+What:		/sys/bus/usb/devices/.../hot_reset
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Write to this node to issue "Reset" for Link Layer Validation
+		device. It is needed for TD.7.29, TD.7.31, TD.7.34 and TD.7.35.
+
+What:		/sys/bus/usb/devices/.../u3_entry
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Write to this node to issue "U3 entry" for Link Layer
+		Validation device. It is needed for TD.7.35 and TD.7.36.
+
+What:		/sys/bus/usb/devices/.../u3_exit
+Date:		March 2014
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+		Write to this node to issue "U3 exit" for Link Layer
+		Validation device. It is needed for TD.7.36.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,17 @@
+What:		/sys/class/iommu/<iommu>/devices/
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		IOMMU drivers are able to link devices managed by a
+		given IOMMU here to allow association of IOMMU to
+		device.
+
+What:		/sys/devices/.../iommu
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		IOMMU drivers are able to link the IOMMU for a
+		given device here to allow association of device to
+		IOMMU.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+What:		/sys/class/iommu/<iommu>/amd-iommu/cap
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		IOMMU capability header as documented in the AMD IOMMU
+		specification.  Format: %x
+
+What:		/sys/class/iommu/<iommu>/amd-iommu/features
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		Extended features of the IOMMU.  Format: %llx
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,32 @@
+What:		/sys/class/iommu/<iommu>/intel-iommu/address
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		Physical address of the VT-d DRHD for this IOMMU.
+		Format: %llx.  This allows association of a sysfs
+		intel-iommu with a DMAR DRHD table entry.
+
+What:		/sys/class/iommu/<iommu>/intel-iommu/cap
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		The cached hardware capability register value
+		of this DRHD unit.  Format: %llx.
+
+What:		/sys/class/iommu/<iommu>/intel-iommu/ecap
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		The cached hardware extended capability register
+		value of this DRHD unit.  Format: %llx.
+
+What:		/sys/class/iommu/<iommu>/intel-iommu/version
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	Alex Williamson <alex.williamson@redhat.com>
+Description:
+		The architecture version as reported from the
+		VT-d VER_REG.  Format: %d:%d, major:minor
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-leds-gt683r linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-leds-gt683r
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-leds-gt683r	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-leds-gt683r	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+What:		/sys/class/leds/<led>/gt683r/mode
+Date:		Jun 2014
+KernelVersion:	3.17
+Contact:	Janne Kanniainen <janne.kanniainen@gmail.com>
+Description:
+		Set the mode of LEDs. You should notice that changing the mode
+		of one LED will update the mode of its two sibling devices as
+		well.
+
+		0 - normal
+		1 - audio
+		2 - breathing
+
+		Normal: LEDs are fully on when enabled
+		Audio:  LEDs brightness depends on sound level
+		Breathing: LEDs brightness varies at human breathing rate
\ No newline at end of file
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-mei linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-mei
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-mei	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-mei	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+What:		/sys/class/mei/
+Date:		May 2014
+KernelVersion:	3.17
+Contact:	Tomas Winkler <tomas.winkler@intel.com>
+Description:
+		The mei/ class sub-directory belongs to mei device class
+
+
+What:		/sys/class/mei/meiN/
+Date:		May 2014
+KernelVersion:	3.17
+Contact:	Tomas Winkler <tomas.winkler@intel.com>
+Description:
+		The /sys/class/mei/meiN directory is created for
+		each probed mei device
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-mtd linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-mtd
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-mtd	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-mtd	2014-09-28 17:29:07.000000000 -0400
@@ -184,3 +184,41 @@ Description:
 
 		It will always be a non-negative integer.  In the case of
 		devices lacking any ECC capability, it is 0.
+
+What:		/sys/class/mtd/mtdX/ecc_failures
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The number of failures reported by this device's ECC. Typically,
+		these failures are associated with failed read operations.
+
+		It will always be a non-negative integer.  In the case of
+		devices lacking any ECC capability, it is 0.
+
+What:		/sys/class/mtd/mtdX/corrected_bits
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The number of bits that have been corrected by means of the
+		device's ECC.
+
+		It will always be a non-negative integer.  In the case of
+		devices lacking any ECC capability, it is 0.
+
+What:		/sys/class/mtd/mtdX/bad_blocks
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The number of blocks marked as bad, if any, in this partition.
+
+What:		/sys/class/mtd/mtdX/bbt_blocks
+Date:		June 2014
+KernelVersion:	3.17
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The number of blocks that are marked as reserved, if any, in
+		this partition. These are typically used to store the in-flash
+		bad block table (BBT).
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-net linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-net
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-class-net	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-class-net	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,14 @@
+What:		/sys/class/net/<iface>/name_assign_type
+Date:		July 2014
+KernelVersion:	3.17
+Contact:	netdev@vger.kernel.org
+Description:
+		Indicates the name assignment type. Possible values are:
+		1: enumerated by the kernel, possibly in an unpredictable way
+		2: predictably named by the kernel
+		3: named by userspace
+		4: renamed
+
 What:		/sys/class/net/<iface>/addr_assign_type
 Date:		July 2010
 KernelVersion:	3.2
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-genwqe linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-genwqe
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-genwqe	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-genwqe	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,15 @@ Date:           Oct 2013
 Contact:        haver@linux.vnet.ibm.com
 Description:    Interface to set the next bitstream to be used.
 
+What:           /sys/class/genwqe/genwqe<n>_card/reload_bitstream
+Date:           May 2014
+Contact:        klebers@linux.vnet.ibm.com
+Description:    Interface to trigger a PCIe card reset to reload the bitstream.
+                  sudo sh -c 'echo 1 > \
+                    /sys/class/genwqe/genwqe0_card/reload_bitstream'
+                If successfully, the card will come back with the bitstream set
+                on 'next_bitstream'.
+
 What:           /sys/class/genwqe/genwqe<n>_card/tempsens
 Date:           Oct 2013
 Contact:        haver@linux.vnet.ibm.com
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,50 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_to_select
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
+		is being controlled by press_speed.
+		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
+		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html
+		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
+		a left or right mouse button click.
+		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	This file contains the trackpoint sensitivity.
+		Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity).
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed
+Date:		July 2011
+Contact:	linux-input@vger.kernel.org
+Description:	This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
+		Values are decimal integers from 1 (slowest) to 255 (fastest).
+		Applies to Thinkpad USB Keyboard with TrackPoint.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fn_lock
+Date:		July 2014
+Contact:	linux-input@vger.kernel.org
+Description:	This setting controls whether Fn Lock is enabled on the keyboard (i.e. if F1 is Mute or F1)
+		Values are 0 or 1
+		Applies to ThinkPad Compact (USB|Bluetooth) Keyboard with TrackPoint.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_to_select
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
-		is being controlled by press_speed.
-		Values are 0 or 1.
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
-		Values are 0 or 1.
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html
-		Values are 0 or 1.
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
-		a left or right mouse button click.
-		Values are 0 or 1.
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	This file contains the trackpoint sensitivity.
-		Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity).
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed
-Date:		July 2011
-Contact:	linux-input@vger.kernel.org
-Description:	This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
-		Values are decimal integers from 1 (slowest) to 255 (fastest).
-
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-pciback linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-pciback
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-pciback	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-pciback	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,13 @@
+What:           /sys/bus/pci/drivers/pciback/quirks
+Date:           Oct 2011
+KernelVersion:  3.1
+Contact:        xen-devel@lists.xenproject.org
+Description:
+                If the permissive attribute is set, then writing a string in
+                the format of DDDD:BB:DD.F-REG:SIZE:MASK will allow the guest
+                to write and read from the PCI device. That is Domain:Bus:
+                Device.Function-Register:Size:Mask (Domain is optional).
+                For example:
+                #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks
+                will allow the guest to read and write to the configuration
+                register 0x0E.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-tegra-fuse linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-tegra-fuse
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-tegra-fuse	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-tegra-fuse	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,11 @@
+What:		/sys/devices/*/<our-device>/fuse
+Date:		February 2014
+Contact:	Peter De Schrijver <pdeschrijver@nvidia.com>
+Description:	read-only access to the efuses on Tegra20, Tegra30, Tegra114
+		and Tegra124 SoC's from NVIDIA. The efuses contain write once
+		data programmed at the factory. The data is layed out in 32bit
+		words in LSB first format. Each bit represents a single value
+		as decoded from the fuse registers. Bits order/assignment
+		exactly matches the HW registers, including any unused bits.
+Users:		any user space application which wants to read the efuses on
+		Tegra SoC's
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-wacom linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-wacom
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-driver-wacom	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-driver-wacom	2014-09-28 17:29:07.000000000 -0400
@@ -1,48 +1,27 @@
-WWhat:		/sys/class/hidraw/hidraw*/device/oled*_img
-Date:		June 2012
-Contact:	linux-bluetooth@vger.kernel.org
-Description:
-		The /sys/class/hidraw/hidraw*/device/oled*_img files control
-		OLED mocro displays on Intuos4 Wireless tablet. Accepted image
-		has to contain 256 bytes (64x32 px 1 bit colour). The format
-		is the same as PBM image 62x32px without header (64 bits per
-		horizontal line, 32 lines). An example of setting OLED No. 0:
-		dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img
-		The attribute is read only and no local copy of the image is
-		stored.
-
-What:		/sys/class/hidraw/hidraw*/device/speed
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed
 Date:		April 2010
 Kernel Version:	2.6.35
 Contact:	linux-bluetooth@vger.kernel.org
 Description:
-		The /sys/class/hidraw/hidraw*/device/speed file controls
-		reporting speed of Wacom bluetooth tablet. Reading from
-		this file returns 1 if tablet reports in high speed mode
+		The /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed file
+		controls reporting speed of Wacom bluetooth tablet. Reading
+		from this file returns 1 if tablet reports in high speed mode
 		or 0 otherwise. Writing to this file one of these values
 		switches reporting speed.
 
-What:		/sys/class/leds/0005\:056A\:00BD.0001\:selector\:*/
-Date:		May 2012
-Kernel Version:	3.5
-Contact:	linux-bluetooth@vger.kernel.org
-Description:
-		LED selector for Intuos4 WL. There are 4 leds, but only one LED
-		can be lit at a time. Max brightness is 127.
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/led
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Attribute group for control of the status LEDs and the OLEDs.
 		This attribute group is only available for Intuos 4 M, L,
-		and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq
-		21UX2 and Cintiq 24HD (LEDs only). Therefore its presence
-		implicitly signifies the presence of said LEDs and OLEDs on the
-		tablet device.
+		and XL (with LEDs and OLEDs), Intuos 4 WL, Intuos 5 (LEDs only),
+		Intuos Pro (LEDs only) and Cintiq 21UX2 and Cintiq 24HD
+		(LEDs only). Therefore its presence implicitly signifies the
+		presence of said LEDs and OLEDs on the tablet device.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status0_luminance
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Writing to this file sets the status LED luminance (1..127)
@@ -50,16 +29,16 @@ Description:
 		button is pressed on the stylus. This luminance level is
 		normally lower than the level when a button is pressed.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status1_luminance
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Writing to this file sets the status LED luminance (1..127)
 		when the stylus touches the tablet surface, or any button is
 		pressed on the stylus.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led0_select
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Writing to this file sets which one of the four (for Intuos 4
@@ -67,23 +46,23 @@ Description:
 		24HD) status LEDs is active (0..3). The other three LEDs on the
 		same side are always inactive.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
-Date:		September 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led1_select
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Writing to this file sets which one of the left four (for Cintiq 21UX2
 		and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on
 		the left are always inactive.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/buttons_luminance
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		Writing to this file sets the overall luminance level (0..15)
 		of all eight button OLED displays.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
-Date:		August 2011
+What:		/sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/button<n>_rawimg
+Date:		August 2014
 Contact:	linux-input@vger.kernel.org
 Description:
 		When writing a 1024 byte raw image in Wacom Intuos 4
@@ -93,3 +72,8 @@ Description:
 		byte chunk encodes the image data for two consecutive lines on
 		the display. The low nibble of each byte contains the first
 		line, and the high nibble contains the second line.
+		When the Wacom Intuos 4 is connected over Bluetooth, the
+		image has to contain 256 bytes (64x32 px 1 bit colour).
+		The format is also scrambled, like in the USB mode, and it can
+		be summarized by converting 76543210 into GECA6420.
+					    HGFEDCBA      HFDB7531
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-fs-nilfs2 linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-fs-nilfs2
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-fs-nilfs2	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-fs-nilfs2	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,269 @@
+
+What:		/sys/fs/nilfs2/features/revision
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show current revision of NILFS file system driver.
+		This value informs about file system revision that
+		driver is ready to support.
+
+What:		/sys/fs/nilfs2/features/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/features group.
+
+What:		/sys/fs/nilfs2/<device>/revision
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show NILFS file system revision on volume.
+		This value informs about metadata structures'
+		revision on mounted volume.
+
+What:		/sys/fs/nilfs2/<device>/blocksize
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show volume's block size in bytes.
+
+What:		/sys/fs/nilfs2/<device>/device_size
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show volume size in bytes.
+
+What:		/sys/fs/nilfs2/<device>/free_blocks
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show count of free blocks on volume.
+
+What:		/sys/fs/nilfs2/<device>/uuid
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show volume's UUID (Universally Unique Identifier).
+
+What:		/sys/fs/nilfs2/<device>/volume_name
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show volume's label.
+
+What:		/sys/fs/nilfs2/<device>/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device> group.
+
+What:		/sys/fs/nilfs2/<device>/superblock/sb_write_time
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show last write time of super block in human-readable
+		format.
+
+What:		/sys/fs/nilfs2/<device>/superblock/sb_write_time_secs
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show last write time of super block in seconds.
+
+What:		/sys/fs/nilfs2/<device>/superblock/sb_write_count
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show current write count of super block.
+
+What:		/sys/fs/nilfs2/<device>/superblock/sb_update_frequency
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show/Set interval of periodical update of superblock
+		(in seconds).
+
+What:		/sys/fs/nilfs2/<device>/superblock/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device>/superblock
+		group.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_pseg_block
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show start block number of the latest segment.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_seg_sequence
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show sequence value of the latest segment.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_seg_checkpoint
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show checkpoint number of the latest segment.
+
+What:		/sys/fs/nilfs2/<device>/segctor/current_seg_sequence
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show segment sequence counter.
+
+What:		/sys/fs/nilfs2/<device>/segctor/current_last_full_seg
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show index number of the latest full segment.
+
+What:		/sys/fs/nilfs2/<device>/segctor/next_full_seg
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show index number of the full segment index
+		to be used next.
+
+What:		/sys/fs/nilfs2/<device>/segctor/next_pseg_offset
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show offset of next partial segment in the current
+		full segment.
+
+What:		/sys/fs/nilfs2/<device>/segctor/next_checkpoint
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show next checkpoint number.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_seg_write_time
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show write time of the last segment in
+		human-readable format.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_seg_write_time_secs
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show write time of the last segment in seconds.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_nongc_write_time
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show write time of the last segment not for cleaner
+		operation in human-readable format.
+
+What:		/sys/fs/nilfs2/<device>/segctor/last_nongc_write_time_secs
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show write time of the last segment not for cleaner
+		operation in seconds.
+
+What:		/sys/fs/nilfs2/<device>/segctor/dirty_data_blocks_count
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of dirty data blocks.
+
+What:		/sys/fs/nilfs2/<device>/segctor/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device>/segctor
+		group.
+
+What:		/sys/fs/nilfs2/<device>/segments/segments_number
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of segments on a volume.
+
+What:		/sys/fs/nilfs2/<device>/segments/blocks_per_segment
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of blocks in segment.
+
+What:		/sys/fs/nilfs2/<device>/segments/clean_segments
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show count of clean segments.
+
+What:		/sys/fs/nilfs2/<device>/segments/dirty_segments
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show count of dirty segments.
+
+What:		/sys/fs/nilfs2/<device>/segments/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device>/segments
+		group.
+
+What:		/sys/fs/nilfs2/<device>/checkpoints/checkpoints_number
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of checkpoints on volume.
+
+What:		/sys/fs/nilfs2/<device>/checkpoints/snapshots_number
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of snapshots on volume.
+
+What:		/sys/fs/nilfs2/<device>/checkpoints/last_seg_checkpoint
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show checkpoint number of the latest segment.
+
+What:		/sys/fs/nilfs2/<device>/checkpoints/next_checkpoint
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show next checkpoint number.
+
+What:		/sys/fs/nilfs2/<device>/checkpoints/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device>/checkpoints
+		group.
+
+What:		/sys/fs/nilfs2/<device>/mounted_snapshots/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe content of /sys/fs/nilfs2/<device>/mounted_snapshots
+		group.
+
+What:		/sys/fs/nilfs2/<device>/mounted_snapshots/<id>/inodes_count
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of inodes for snapshot.
+
+What:		/sys/fs/nilfs2/<device>/mounted_snapshots/<id>/blocks_count
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Show number of blocks for snapshot.
+
+What:		/sys/fs/nilfs2/<device>/mounted_snapshots/<id>/README
+Date:		April 2014
+Contact:	"Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+		Describe attributes of /sys/fs/nilfs2/<device>/mounted_snapshots/<id>
+		group.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-fs-xfs linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-fs-xfs
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-fs-xfs	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-fs-xfs	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+What:		/sys/fs/xfs/<disk>/log/log_head_lsn
+Date:		July 2014
+KernelVersion:	3.17
+Contact:	xfs@oss.sgi.com
+Description:
+		The log sequence number (LSN) of the current head of the
+		log. The LSN is exported in "cycle:basic block" format.
+Users:		xfstests
+
+What:		/sys/fs/xfs/<disk>/log/log_tail_lsn
+Date:		July 2014
+KernelVersion:	3.17
+Contact:	xfs@oss.sgi.com
+Description:
+		The log sequence number (LSN) of the current tail of the
+		log. The LSN is exported in "cycle:basic block" format.
+
+What:		/sys/fs/xfs/<disk>/log/reserve_grant_head
+Date:		July 2014
+KernelVersion:	3.17
+Contact:	xfs@oss.sgi.com
+Description:
+		The current state of the log reserve grant head. It
+		represents the total log reservation of all currently
+		outstanding transactions. The grant head is exported in
+		"cycle:bytes" format.
+Users:		xfstests
+
+What:		/sys/fs/xfs/<disk>/log/write_grant_head
+Date:		July 2014
+KernelVersion:	3.17
+Contact:	xfs@oss.sgi.com
+Description:
+		The current state of the log write grant head. It
+		represents the total log reservation of all currently
+		oustanding transactions, including regrants due to
+		rolling transactions. The grant head is exported in
+		"cycle:bytes" format.
+Users:		xfstests
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-platform-ts5500 linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-platform-ts5500
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-platform-ts5500	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-platform-ts5500	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,13 @@ Description:
 		the corresponding bit is set. For instance, 0x0e means jumpers
 		2, 3 and 4 are set.
 
+What:		/sys/devices/platform/ts5500/name
+Date:		July 2014
+KernelVersion:	3.16
+Contact:	"Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
+Description:
+		Model name of the TS board, e.g. "TS-5500".
+
 What:		/sys/devices/platform/ts5500/rs485
 Date:		January 2013
 KernelVersion:	3.7
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-tty linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-tty
--- linux-libre-3.16-gnu/Documentation/ABI/testing/sysfs-tty	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ABI/testing/sysfs-tty	2014-09-28 17:29:07.000000000 -0400
@@ -138,3 +138,19 @@ Description:
 
 		 These sysfs values expose the TIOCGSERIAL interface via
 		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/rx_trig_bytes
+Date:		May 2014
+Contact:	Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
+Description:
+		 Shows current RX interrupt trigger bytes or sets the
+		 user specified value to change it for the FIFO buffer.
+		 Users can show or set this value regardless of opening the
+		 serial device file or not.
+
+		 The RX trigger can be set one of four kinds of values for UART
+		 serials. When users input a meaning less value to this I/F,
+		 the RX trigger is changed to the nearest lower value for the
+		 device specification. For example, when user sets 7bytes on
+		 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
+		 automatically changed to 4 bytes.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm/CCN.txt linux-libre-3.17-rc7-gnu/Documentation/arm/CCN.txt
--- linux-libre-3.16-gnu/Documentation/arm/CCN.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/arm/CCN.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,52 @@
+ARM Cache Coherent Network
+==========================
+
+CCN-504 is a ring-bus interconnect consisting of 11 crosspoints
+(XPs), with each crosspoint supporting up to two device ports,
+so nodes (devices) 0 and 1 are connected to crosspoint 0,
+nodes 2 and 3 to crosspoint 1 etc.
+
+PMU (perf) driver
+-----------------
+
+The CCN driver registers a perf PMU driver, which provides
+description of available events and configuration options
+in sysfs, see /sys/bus/event_source/devices/ccn*.
+
+The "format" directory describes format of the config, config1
+and config2 fields of the perf_event_attr structure. The "events"
+directory provides configuration templates for all documented
+events, that can be used with perf tool. For example "xp_valid_flit"
+is an equivalent of "type=0x8,event=0x4". Other parameters must be
+explicitly specified. For events originating from device, "node"
+defines its index. All crosspoint events require "xp" (index),
+"port" (device port number) and "vc" (virtual channel ID) and
+"dir" (direction). Watchpoints (special "event" value 0xfe) also
+require comparator values ("cmp_l" and "cmp_h") and "mask", being
+index of the comparator mask.
+
+Masks are defined separately from the event description
+(due to limited number of the config values) in the "cmp_mask"
+directory, with first 8 configurable by user and additional
+4 hardcoded for the most frequent use cases.
+
+Cycle counter is described by a "type" value 0xff and does
+not require any other settings.
+
+Example of perf tool use:
+
+/ # perf list | grep ccn
+  ccn/cycles/                                        [Kernel PMU event]
+<...>
+  ccn/xp_valid_flit/                                 [Kernel PMU event]
+<...>
+
+/ # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \
+                                                                       sleep 1
+
+The driver does not support sampling, therefore "perf record" will
+not work. Also notice that only single cpu is being selected
+("-C 0") - this is because perf framework does not support
+"non-CPU related" counters (yet?) so system-wide session ("-a")
+would try (and in most cases fail) to set up the same event
+per each CPU.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm/Marvell/README linux-libre-3.17-rc7-gnu/Documentation/arm/Marvell/README
--- linux-libre-3.16-gnu/Documentation/arm/Marvell/README	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/arm/Marvell/README	2014-09-28 17:29:07.000000000 -0400
@@ -53,8 +53,8 @@ Kirkwood family
                 Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
   Homepage: http://www.marvell.com/embedded-processors/kirkwood/
   Core: Feroceon ARMv5 compatible
-  Linux kernel mach directory: arch/arm/mach-kirkwood
-  Linux kernel plat directory: arch/arm/plat-orion
+  Linux kernel mach directory: arch/arm/mach-mvebu
+  Linux kernel plat directory: none
 
 Discovery family
 ----------------
@@ -83,7 +83,9 @@ EBU Armada family
         88F6710
         88F6707
         88F6W11
-    Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
+    Product Brief:   http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
+    Hardware Spec:   http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-datasheet.pdf
+    Functional Spec: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
 
   Armada 375 Flavors:
 	88F6720
@@ -100,8 +102,7 @@ EBU Armada family
         MV78460
     NOTE: not to be confused with the non-SMP 78xx0 SoCs
     Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
-
-  No public datasheet available.
+    Functional Spec: http://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
 
   Core: Sheeva ARMv7 compatible
 
@@ -135,7 +136,9 @@ Dove family (application processor)
                 Functional Spec : http://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf
   Homepage: http://www.marvell.com/application-processors/armada-500/
   Core: ARMv7 compatible
-  Directory: arch/arm/mach-dove
+
+  Directory: arch/arm/mach-mvebu (DT enabled platforms)
+             arch/arm/mach-dove (non-DT enabled platforms)
 
 PXA 2xx/3xx/93x/95x family
 --------------------------
@@ -253,10 +256,10 @@ Berlin family (Digital Entertainment)
 Long-term plans
 ---------------
 
- * Unify the mach-dove/, mach-mv78xx0/, mach-orion5x/ and
-   mach-kirkwood/ into the mach-mvebu/ to support all SoCs from the
-   Marvell EBU (Engineering Business Unit) in a single mach-<foo>
-   directory. The plat-orion/ would therefore disappear.
+ * Unify the mach-dove/, mach-mv78xx0/, mach-orion5x/ into the
+   mach-mvebu/ to support all SoCs from the Marvell EBU (Engineering
+   Business Unit) in a single mach-<foo> directory. The plat-orion/
+   would therefore disappear.
 
  * Unify the mach-mmp/ and mach-pxa/ into the same mach-pxa
    directory. The plat-pxa/ would therefore disappear.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm/Samsung/clksrc-change-registers.awk linux-libre-3.17-rc7-gnu/Documentation/arm/Samsung/clksrc-change-registers.awk
--- linux-libre-3.16-gnu/Documentation/arm/Samsung/clksrc-change-registers.awk	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/arm/Samsung/clksrc-change-registers.awk	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,6 @@ BEGIN {
 
     while (getline line < ARGV[1] > 0) {
 	if (line ~ /\#define.*_MASK/ &&
-	    !(line ~ /S5PC100_EPLL_MASK/) &&
 	    !(line ~ /USB_SIG_MASK/)) {
 	    splitdefine(line, fields)
 	    name = fields[0]
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm/Samsung/Overview.txt linux-libre-3.17-rc7-gnu/Documentation/arm/Samsung/Overview.txt
--- linux-libre-3.16-gnu/Documentation/arm/Samsung/Overview.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/arm/Samsung/Overview.txt	2014-09-28 17:29:07.000000000 -0400
@@ -13,8 +13,6 @@ Introduction
 
   - S3C24XX: See Documentation/arm/Samsung-S3C24XX/Overview.txt for full list
   - S3C64XX: S3C6400 and S3C6410
-  - S5P6440
-  - S5PC100
   - S5PC110 / S5PV210
 
 
@@ -34,8 +32,6 @@ Configuration
   A number of configurations are supplied, as there is no current way of
   unifying all the SoCs into one kernel.
 
-  s5p6440_defconfig - S5P6440 specific default configuration
-  s5pc100_defconfig - S5PC100 specific default configuration
   s5pc110_defconfig - S5PC110 specific default configuration
   s5pv210_defconfig - S5PV210 specific default configuration
 
@@ -67,13 +63,6 @@ Layout changes
   where to simplify the include and dependency issues involved with having
   so many different platform directories.
 
-  It was decided to remove plat-s5pc1xx as some of the support was already
-  in plat-s5p or plat-samsung, with the S5PC110 support added with S5PV210
-  the only user was the S5PC100. The S5PC100 specific items where moved to
-  arch/arm/mach-s5pc100.
-
-
-
 
 Port Contributors
 -----------------
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm64/booting.txt linux-libre-3.17-rc7-gnu/Documentation/arm64/booting.txt
--- linux-libre-3.16-gnu/Documentation/arm64/booting.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/arm64/booting.txt	2014-09-28 17:29:07.000000000 -0400
@@ -72,27 +72,54 @@ The decompressed kernel image contains a
 
   u32 code0;			/* Executable code */
   u32 code1;			/* Executable code */
-  u64 text_offset;		/* Image load offset */
-  u64 res0	= 0;		/* reserved */
-  u64 res1	= 0;		/* reserved */
+  u64 text_offset;		/* Image load offset, little endian */
+  u64 image_size;		/* Effective Image size, little endian */
+  u64 flags;			/* kernel flags, little endian */
   u64 res2	= 0;		/* reserved */
   u64 res3	= 0;		/* reserved */
   u64 res4	= 0;		/* reserved */
   u32 magic	= 0x644d5241;	/* Magic number, little endian, "ARM\x64" */
-  u32 res5 = 0;      		/* reserved */
+  u32 res5;      		/* reserved (used for PE COFF offset) */
 
 
 Header notes:
 
+- As of v3.17, all fields are little endian unless stated otherwise.
+
 - code0/code1 are responsible for branching to stext.
+
 - when booting through EFI, code0/code1 are initially skipped.
   res5 is an offset to the PE header and the PE header has the EFI
-  entry point (efi_stub_entry). When the stub has done its work, it
+  entry point (efi_stub_entry).  When the stub has done its work, it
   jumps to code0 to resume the normal boot process.
 
-The image must be placed at the specified offset (currently 0x80000)
-from the start of the system RAM and called there. The start of the
-system RAM must be aligned to 2MB.
+- Prior to v3.17, the endianness of text_offset was not specified.  In
+  these cases image_size is zero and text_offset is 0x80000 in the
+  endianness of the kernel.  Where image_size is non-zero image_size is
+  little-endian and must be respected.  Where image_size is zero,
+  text_offset can be assumed to be 0x80000.
+
+- The flags field (introduced in v3.17) is a little-endian 64-bit field
+  composed as follows:
+  Bit 0: 	Kernel endianness.  1 if BE, 0 if LE.
+  Bits 1-63:	Reserved.
+
+- When image_size is zero, a bootloader should attempt to keep as much
+  memory as possible free for use by the kernel immediately after the
+  end of the kernel image. The amount of space required will vary
+  depending on selected features, and is effectively unbound.
+
+The Image must be placed text_offset bytes from a 2MB aligned base
+address near the start of usable system RAM and called there. Memory
+below that base address is currently unusable by Linux, and therefore it
+is strongly recommended that this location is the start of system RAM.
+At least image_size bytes from the start of the image must be free for
+use by the kernel.
+
+Any memory described to the kernel (even that below the 2MB aligned base
+address) which is not marked as reserved from the kernel e.g. with a
+memreserve region in the device tree) will be considered as available to
+the kernel.
 
 Before jumping into the kernel, the following conditions must be met:
 
@@ -141,6 +168,14 @@ Before jumping into the kernel, the foll
   the kernel image will be entered must be initialised by software at a
   higher exception level to prevent execution in an UNKNOWN state.
 
+  For systems with a GICv3 interrupt controller:
+  - If EL3 is present:
+    ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1.
+    ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
+  - If the kernel is entered at EL1:
+    ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1
+    ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1.
+
 The requirements described above for CPU mode, caches, MMUs, architected
 timers, coherency and system registers apply to all CPUs.  All CPUs must
 enter the kernel in the same exception level.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/arm64/memory.txt linux-libre-3.17-rc7-gnu/Documentation/arm64/memory.txt
--- linux-libre-3.16-gnu/Documentation/arm64/memory.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/arm64/memory.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2,18 +2,18 @@
 		     ==============================
 
 Author: Catalin Marinas <catalin.marinas@arm.com>
-Date  : 20 February 2012
 
 This document describes the virtual memory layout used by the AArch64
 Linux kernel. The architecture allows up to 4 levels of translation
 tables with a 4KB page size and up to 3 levels with a 64KB page size.
 
-AArch64 Linux uses 3 levels of translation tables with the 4KB page
-configuration, allowing 39-bit (512GB) virtual addresses for both user
-and kernel. With 64KB pages, only 2 levels of translation tables are
-used but the memory layout is the same.
+AArch64 Linux uses either 3 levels or 4 levels of translation tables
+with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit
+(256TB) virtual addresses, respectively, for both user and kernel. With
+64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB)
+virtual address, are used but the memory layout is the same.
 
-User addresses have bits 63:39 set to 0 while the kernel addresses have
+User addresses have bits 63:48 set to 0 while the kernel addresses have
 the same bits set to 1. TTBRx selection is given by bit 63 of the
 virtual address. The swapper_pg_dir contains only kernel (global)
 mappings while the user pgd contains only user (non-global) mappings.
@@ -21,58 +21,40 @@ The swapper_pgd_dir address is written t
 TTBR0.
 
 
-AArch64 Linux memory layout with 4KB pages:
+AArch64 Linux memory layout with 4KB pages + 3 levels:
 
 Start			End			Size		Use
 -----------------------------------------------------------------------
 0000000000000000	0000007fffffffff	 512GB		user
+ffffff8000000000	ffffffffffffffff	 512GB		kernel
 
-ffffff8000000000	ffffffbbfffeffff	~240GB		vmalloc
-
-ffffffbbffff0000	ffffffbbffffffff	  64KB		[guard page]
-
-ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
-
-ffffffbe00000000	ffffffbffbbfffff	  ~8GB		[guard, future vmmemap]
-
-ffffffbffa000000	ffffffbffaffffff	  16MB		PCI I/O space
-
-ffffffbffb000000	ffffffbffbbfffff	  12MB		[guard]
-
-ffffffbffbc00000	ffffffbffbdfffff	   2MB		fixed mappings
-
-ffffffbffbe00000	ffffffbffbffffff	   2MB		[guard]
 
-ffffffbffc000000	ffffffbfffffffff	  64MB		modules
+AArch64 Linux memory layout with 4KB pages + 4 levels:
 
-ffffffc000000000	ffffffffffffffff	 256GB		kernel logical memory map
+Start			End			Size		Use
+-----------------------------------------------------------------------
+0000000000000000	0000ffffffffffff	 256TB		user
+ffff000000000000	ffffffffffffffff	 256TB		kernel
 
 
-AArch64 Linux memory layout with 64KB pages:
+AArch64 Linux memory layout with 64KB pages + 2 levels:
 
 Start			End			Size		Use
 -----------------------------------------------------------------------
 0000000000000000	000003ffffffffff	   4TB		user
+fffffc0000000000	ffffffffffffffff	   4TB		kernel
 
-fffffc0000000000	fffffdfbfffeffff	  ~2TB		vmalloc
-
-fffffdfbffff0000	fffffdfbffffffff	  64KB		[guard page]
-
-fffffdfc00000000	fffffdfdffffffff	   8GB		vmemmap
-
-fffffdfe00000000	fffffdfffbbfffff	  ~8GB		[guard, future vmmemap]
-
-fffffdfffa000000	fffffdfffaffffff	  16MB		PCI I/O space
-
-fffffdfffb000000	fffffdfffbbfffff	  12MB		[guard]
 
-fffffdfffbc00000	fffffdfffbdfffff	   2MB		fixed mappings
+AArch64 Linux memory layout with 64KB pages + 3 levels:
 
-fffffdfffbe00000	fffffdfffbffffff	   2MB		[guard]
+Start			End			Size		Use
+-----------------------------------------------------------------------
+0000000000000000	0000ffffffffffff	 256TB		user
+ffff000000000000	ffffffffffffffff	 256TB		kernel
 
-fffffdfffc000000	fffffdffffffffff	  64MB		modules
 
-fffffe0000000000	ffffffffffffffff	   2TB		kernel logical memory map
+For details of the virtual kernel memory layout please see the kernel
+booting log.
 
 
 Translation table lookup with 4KB pages:
@@ -86,7 +68,7 @@ Translation table lookup with 4KB pages:
  |                 |         |         |         +-> [20:12] L3 index
  |                 |         |         +-----------> [29:21] L2 index
  |                 |         +---------------------> [38:30] L1 index
- |                 +-------------------------------> [47:39] L0 index (not used)
+ |                 +-------------------------------> [47:39] L0 index
  +-------------------------------------------------> [63] TTBR0/1
 
 
@@ -99,10 +81,11 @@ Translation table lookup with 64KB pages
  |                 |    |               |              v
  |                 |    |               |            [15:0]  in-page offset
  |                 |    |               +----------> [28:16] L3 index
- |                 |    +--------------------------> [41:29] L2 index (only 38:29 used)
- |                 +-------------------------------> [47:42] L1 index (not used)
+ |                 |    +--------------------------> [41:29] L2 index
+ |                 +-------------------------------> [47:42] L1 index
  +-------------------------------------------------> [63] TTBR0/1
 
+
 When using KVM, the hypervisor maps kernel pages in EL2, at a fixed
 offset from the kernel VA (top 24bits of the kernel VA set to zero):
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/cgroups/cgroups.txt linux-libre-3.17-rc7-gnu/Documentation/cgroups/cgroups.txt
--- linux-libre-3.16-gnu/Documentation/cgroups/cgroups.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/cgroups/cgroups.txt	2014-09-28 17:29:07.000000000 -0400
@@ -599,6 +599,20 @@ fork. If this method returns 0 (success)
 while the caller holds cgroup_mutex and it is ensured that either
 attach() or cancel_attach() will be called in future.
 
+void css_reset(struct cgroup_subsys_state *css)
+(cgroup_mutex held by caller)
+
+An optional operation which should restore @css's configuration to the
+initial state.  This is currently only used on the unified hierarchy
+when a subsystem is disabled on a cgroup through
+"cgroup.subtree_control" but should remain enabled because other
+subsystems depend on it.  cgroup core makes such a css invisible by
+removing the associated interface files and invokes this callback so
+that the hidden subsystem can return to the initial neutral state.
+This prevents unexpected resource control from a hidden css and
+ensures that the configuration is in the initial state when it is made
+visible again later.
+
 void cancel_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 (cgroup_mutex held by caller)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/cgroups/cpusets.txt linux-libre-3.17-rc7-gnu/Documentation/cgroups/cpusets.txt
--- linux-libre-3.16-gnu/Documentation/cgroups/cpusets.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/cgroups/cpusets.txt	2014-09-28 17:29:07.000000000 -0400
@@ -345,14 +345,14 @@ the named feature on.
 The implementation is simple.
 
 Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
-PF_SPREAD_PAGE for each task that is in that cpuset or subsequently
+PFA_SPREAD_PAGE for each task that is in that cpuset or subsequently
 joins that cpuset.  The page allocation calls for the page cache
-is modified to perform an inline check for this PF_SPREAD_PAGE task
+is modified to perform an inline check for this PFA_SPREAD_PAGE task
 flag, and if set, a call to a new routine cpuset_mem_spread_node()
 returns the node to prefer for the allocation.
 
 Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
-PF_SPREAD_SLAB, and appropriately marked slab caches will allocate
+PFA_SPREAD_SLAB, and appropriately marked slab caches will allocate
 pages from the node returned by cpuset_mem_spread_node().
 
 The cpuset_mem_spread_node() routine is also simple.  It uses the
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/cgroups/memcg_test.txt linux-libre-3.17-rc7-gnu/Documentation/cgroups/memcg_test.txt
--- linux-libre-3.16-gnu/Documentation/cgroups/memcg_test.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/cgroups/memcg_test.txt	2014-09-28 17:29:07.000000000 -0400
@@ -24,64 +24,27 @@ Please note that implementation details
 
    a page/swp_entry may be charged (usage += PAGE_SIZE) at
 
-	mem_cgroup_charge_anon()
-	  Called at new page fault and Copy-On-Write.
-
-	mem_cgroup_try_charge_swapin()
-	  Called at do_swap_page() (page fault on swap entry) and swapoff.
-	  Followed by charge-commit-cancel protocol. (With swap accounting)
-	  At commit, a charge recorded in swap_cgroup is removed.
-
-	mem_cgroup_charge_file()
-	  Called at add_to_page_cache()
-
-	mem_cgroup_cache_charge_swapin()
-	  Called at shmem's swapin.
-
-	mem_cgroup_prepare_migration()
-	  Called before migration. "extra" charge is done and followed by
-	  charge-commit-cancel protocol.
-	  At commit, charge against oldpage or newpage will be committed.
+	mem_cgroup_try_charge()
 
 2. Uncharge
   a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by
 
-	mem_cgroup_uncharge_page()
-	  Called when an anonymous page is fully unmapped. I.e., mapcount goes
-	  to 0. If the page is SwapCache, uncharge is delayed until
-	  mem_cgroup_uncharge_swapcache().
-
-	mem_cgroup_uncharge_cache_page()
-	  Called when a page-cache is deleted from radix-tree. If the page is
-	  SwapCache, uncharge is delayed until mem_cgroup_uncharge_swapcache().
-
-	mem_cgroup_uncharge_swapcache()
-	  Called when SwapCache is removed from radix-tree. The charge itself
-	  is moved to swap_cgroup. (If mem+swap controller is disabled, no
-	  charge to swap occurs.)
+	mem_cgroup_uncharge()
+	  Called when a page's refcount goes down to 0.
 
 	mem_cgroup_uncharge_swap()
 	  Called when swp_entry's refcnt goes down to 0. A charge against swap
 	  disappears.
 
-	mem_cgroup_end_migration(old, new)
-	At success of migration old is uncharged (if necessary), a charge
-	to new page is committed. At failure, charge to old page is committed.
-
 3. charge-commit-cancel
-	In some case, we can't know this "charge" is valid or not at charging
-	(because of races).
-	To handle such case, there are charge-commit-cancel functions.
-		mem_cgroup_try_charge_XXX
-		mem_cgroup_commit_charge_XXX
-		mem_cgroup_cancel_charge_XXX
-	these are used in swap-in and migration.
+	Memcg pages are charged in two steps:
+		mem_cgroup_try_charge()
+		mem_cgroup_commit_charge() or mem_cgroup_cancel_charge()
 
 	At try_charge(), there are no flags to say "this page is charged".
 	at this point, usage += PAGE_SIZE.
 
-	At commit(), the function checks the page should be charged or not
-	and set flags or avoid charging.(usage -= PAGE_SIZE)
+	At commit(), the page is associated with the memcg.
 
 	At cancel(), simply usage -= PAGE_SIZE.
 
@@ -91,18 +54,6 @@ Under below explanation, we assume CONFI
 	Anonymous page is newly allocated at
 		  - page fault into MAP_ANONYMOUS mapping.
 		  - Copy-On-Write.
- 	It is charged right after it's allocated before doing any page table
-	related operations. Of course, it's uncharged when another page is used
-	for the fault address.
-
-	At freeing anonymous page (by exit() or munmap()), zap_pte() is called
-	and pages for ptes are freed one by one.(see mm/memory.c). Uncharges
-	are done at page_remove_rmap() when page_mapcount() goes down to 0.
-
-	Another page freeing is by page-reclaim (vmscan.c) and anonymous
-	pages are swapped out. In this case, the page is marked as
-	PageSwapCache(). uncharge() routine doesn't uncharge the page marked
-	as SwapCache(). It's delayed until __delete_from_swap_cache().
 
 	4.1 Swap-in.
 	At swap-in, the page is taken from swap-cache. There are 2 cases.
@@ -111,41 +62,6 @@ Under below explanation, we assume CONFI
 	(b) If the SwapCache has been mapped by processes, it has been
 	    charged already.
 
-	This swap-in is one of the most complicated work. In do_swap_page(),
-	following events occur when pte is unchanged.
-
-	(1) the page (SwapCache) is looked up.
-	(2) lock_page()
-	(3) try_charge_swapin()
-	(4) reuse_swap_page() (may call delete_swap_cache())
-	(5) commit_charge_swapin()
-	(6) swap_free().
-
-	Considering following situation for example.
-
-	(A) The page has not been charged before (2) and reuse_swap_page()
-	    doesn't call delete_from_swap_cache().
-	(B) The page has not been charged before (2) and reuse_swap_page()
-	    calls delete_from_swap_cache().
-	(C) The page has been charged before (2) and reuse_swap_page() doesn't
-	    call delete_from_swap_cache().
-	(D) The page has been charged before (2) and reuse_swap_page() calls
-	    delete_from_swap_cache().
-
-	    memory.usage/memsw.usage changes to this page/swp_entry will be
-	 Case          (A)      (B)       (C)     (D)
-         Event
-       Before (2)     0/ 1     0/ 1      1/ 1    1/ 1
-          ===========================================
-          (3)        +1/+1    +1/+1     +1/+1   +1/+1
-          (4)          -       0/ 0       -     -1/ 0
-          (5)         0/-1     0/ 0     -1/-1    0/ 0
-          (6)          -       0/-1       -      0/-1
-          ===========================================
-       Result         1/ 1     1/ 1      1/ 1    1/ 1
-
-       In any cases, charges to this page should be 1/ 1.
-
 	4.2 Swap-out.
 	At swap-out, typical state transition is below.
 
@@ -158,28 +74,20 @@ Under below explanation, we assume CONFI
 	    swp_entry's refcnt -= 1.
 
 
-	At (b), the page is marked as SwapCache and not uncharged.
-	At (d), the page is removed from SwapCache and a charge in page_cgroup
-	is moved to swap_cgroup.
-
 	Finally, at task exit,
 	(e) zap_pte() is called and swp_entry's refcnt -=1 -> 0.
-	Here, a charge in swap_cgroup disappears.
 
 5. Page Cache
    	Page Cache is charged at
 	- add_to_page_cache_locked().
 
-	uncharged at
-	- __remove_from_page_cache().
-
 	The logic is very clear. (About migration, see below)
 	Note: __remove_from_page_cache() is called by remove_from_page_cache()
 	and __remove_mapping().
 
 6. Shmem(tmpfs) Page Cache
-	Memcg's charge/uncharge have special handlers of shmem. The best way
-	to understand shmem's page state transition is to read mm/shmem.c.
+	The best way to understand shmem's page state transition is to read
+	mm/shmem.c.
 	But brief explanation of the behavior of memcg around shmem will be
 	helpful to understand the logic.
 
@@ -192,56 +100,10 @@ Under below explanation, we assume CONFI
 	It's charged when...
 	- A new page is added to shmem's radix-tree.
 	- A swp page is read. (move a charge from swap_cgroup to page_cgroup)
-	It's uncharged when
-	- A page is removed from radix-tree and not SwapCache.
-	- When SwapCache is removed, a charge is moved to swap_cgroup.
-	- When swp_entry's refcnt goes down to 0, a charge in swap_cgroup
-	  disappears.
 
 7. Page Migration
-   	One of the most complicated functions is page-migration-handler.
-	Memcg has 2 routines. Assume that we are migrating a page's contents
-	from OLDPAGE to NEWPAGE.
 
-	Usual migration logic is..
-	(a) remove the page from LRU.
-	(b) allocate NEWPAGE (migration target)
-	(c) lock by lock_page().
-	(d) unmap all mappings.
-	(e-1) If necessary, replace entry in radix-tree.
-	(e-2) move contents of a page.
-	(f) map all mappings again.
-	(g) pushback the page to LRU.
-	(-) OLDPAGE will be freed.
-
-	Before (g), memcg should complete all necessary charge/uncharge to
-	NEWPAGE/OLDPAGE.
-
-	The point is....
-	- If OLDPAGE is anonymous, all charges will be dropped at (d) because
-          try_to_unmap() drops all mapcount and the page will not be
-	  SwapCache.
-
-	- If OLDPAGE is SwapCache, charges will be kept at (g) because
-	  __delete_from_swap_cache() isn't called at (e-1)
-
-	- If OLDPAGE is page-cache, charges will be kept at (g) because
-	  remove_from_swap_cache() isn't called at (e-1)
-
-	memcg provides following hooks.
-
-	- mem_cgroup_prepare_migration(OLDPAGE)
-	  Called after (b) to account a charge (usage += PAGE_SIZE) against
-	  memcg which OLDPAGE belongs to.
-
-        - mem_cgroup_end_migration(OLDPAGE, NEWPAGE)
-	  Called after (f) before (g).
-	  If OLDPAGE is used, commit OLDPAGE again. If OLDPAGE is already
-	  charged, a charge by prepare_migration() is automatically canceled.
-	  If NEWPAGE is used, commit NEWPAGE and uncharge OLDPAGE.
-
-	  But zap_pte() (by exit or munmap) can be called while migration,
-	  we have to check if OLDPAGE/NEWPAGE is a valid page after commit().
+	mem_cgroup_migrate()
 
 8. LRU
         Each memcg has its own private LRU. Now, its handling is under global
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/cgroups/unified-hierarchy.txt linux-libre-3.17-rc7-gnu/Documentation/cgroups/unified-hierarchy.txt
--- linux-libre-3.16-gnu/Documentation/cgroups/unified-hierarchy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/cgroups/unified-hierarchy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -94,12 +94,35 @@ change soon.
 
  mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT
 
-All controllers which are not bound to other hierarchies are
-automatically bound to unified hierarchy and show up at the root of
-it.  Controllers which are enabled only in the root of unified
-hierarchy can be bound to other hierarchies at any time.  This allows
-mixing unified hierarchy with the traditional multiple hierarchies in
-a fully backward compatible way.
+All controllers which support the unified hierarchy and are not bound
+to other hierarchies are automatically bound to unified hierarchy and
+show up at the root of it.  Controllers which are enabled only in the
+root of unified hierarchy can be bound to other hierarchies.  This
+allows mixing unified hierarchy with the traditional multiple
+hierarchies in a fully backward compatible way.
+
+For development purposes, the following boot parameter makes all
+controllers to appear on the unified hierarchy whether supported or
+not.
+
+ cgroup__DEVEL__legacy_files_on_dfl
+
+A controller can be moved across hierarchies only after the controller
+is no longer referenced in its current hierarchy.  Because per-cgroup
+controller states are destroyed asynchronously and controllers may
+have lingering references, a controller may not show up immediately on
+the unified hierarchy after the final umount of the previous
+hierarchy.  Similarly, a controller should be fully disabled to be
+moved out of the unified hierarchy and it may take some time for the
+disabled controller to become available for other hierarchies;
+furthermore, due to dependencies among controllers, other controllers
+may need to be disabled too.
+
+While useful for development and manual configurations, dynamically
+moving controllers between the unified and other hierarchies is
+strongly discouraged for production use.  It is recommended to decide
+the hierarchies and controller associations before starting using the
+controllers.
 
 
 2-2. cgroup.subtree_control
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/device-mapper/switch.txt linux-libre-3.17-rc7-gnu/Documentation/device-mapper/switch.txt
--- linux-libre-3.16-gnu/Documentation/device-mapper/switch.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/device-mapper/switch.txt	2014-09-28 17:29:07.000000000 -0400
@@ -106,6 +106,11 @@ which paths.
     The path number in the range 0 ... (<num_paths> - 1).
     Expressed in hexadecimal (WITHOUT any prefix like 0x).
 
+R<n>,<m>
+    This parameter allows repetitive patterns to be loaded quickly. <n> and <m>
+    are hexadecimal numbers. The last <n> mappings are repeated in the next <m>
+    slots.
+
 Status
 ======
 
@@ -124,3 +129,10 @@ Create a switch device with 64kB region
 Set mappings for the first 7 entries to point to devices switch0, switch1,
 switch2, switch0, switch1, switch2, switch1:
     dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1
+
+Set repetitive mapping. This command:
+    dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10
+is equivalent to:
+    dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \
+	:1 :2 :1 :2 :1 :2 :1 :2 :1 :2
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/adapteva.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/adapteva.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/adapteva.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/adapteva.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+Adapteva Platforms Device Tree Bindings
+---------------------------------------
+
+Parallella board
+
+Required root node properties:
+    - compatible = "adapteva,parallella";
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+Marvell Armada 38x CA9 MPcore SoC Controller
+============================================
+
+Required properties:
+
+- compatible: Should be "marvell,armada-380-mpcore-soc-ctrl".
+
+- reg: should be the register base and length as documented in the
+  datasheet for the CA9 MPcore SoC Control registers
+
+mpcore-soc-ctrl@20d20 {
+	compatible = "marvell,armada-380-mpcore-soc-ctrl";
+	reg = <0x20d20 0x6c>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/arm-boards linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/arm-boards
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/arm-boards	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/arm-boards	2014-09-28 17:29:07.000000000 -0400
@@ -86,3 +86,9 @@ Interrupt controllers:
 	compatible = "arm,versatile-sic";
 	interrupt-controller;
 	#interrupt-cells = <1>;
+
+Required nodes:
+
+- core-module: the root node to the Versatile platforms must have
+  a core-module with regs and the compatible strings
+  "arm,core-module-versatile", "syscon"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/atmel-aic.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/atmel-aic.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/atmel-aic.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/atmel-aic.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-* Advanced Interrupt Controller (AIC)
-
-Required properties:
-- compatible: Should be "atmel,<chip>-aic"
-  <chip> can be "at91rm9200" or "sama5d3"
-- interrupt-controller: Identifies the node as an interrupt controller.
-- interrupt-parent: For single AIC system, it is an empty property.
-- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
-  The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
-  The second cell is used to specify flags:
-    bits[3:0] trigger type and level flags:
-      1 = low-to-high edge triggered.
-      2 = high-to-low edge triggered.
-      4 = active high level-sensitive.
-      8 = active low level-sensitive.
-      Valid combinations are 1, 2, 3, 4, 8.
-      Default flag for internal sources should be set to 4 (active high).
-  The third cell is used to specify the irq priority from 0 (lowest) to 7
-  (highest).
-- reg: Should contain AIC registers location and length
-- atmel,external-irqs: u32 array of external irqs.
-
-Examples:
-	/*
-	 * AIC
-	 */
-	aic: interrupt-controller@fffff000 {
-		compatible = "atmel,at91rm9200-aic";
-		interrupt-controller;
-		interrupt-parent;
-		#interrupt-cells = <3>;
-		reg = <0xfffff000 0x200>;
-	};
-
-	/*
-	 * An interrupt generating device that is wired to an AIC.
-	 */
-	dma: dma-controller@ffffec00 {
-		compatible = "atmel,at91sam9g45-dma";
-		reg = <0xffffec00 0x200>;
-		interrupts = <21 4 5>;
-	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/atmel-pmc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/atmel-pmc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/atmel-pmc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/atmel-pmc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,10 @@
 * Power Management Controller (PMC)
 
 Required properties:
-- compatible: Should be "atmel,at91rm9200-pmc"
+- compatible: Should be "atmel,<chip>-pmc".
+	<chip> can be: at91rm9200, at91sam9260, at91sam9g45, at91sam9n12,
+	at91sam9x5, sama5d3
+
 - reg: Should contain PMC registers location and length
 
 Examples:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+Broadcom Kona Family CPU Enable Method
+--------------------------------------
+This binding defines the enable method used for starting secondary
+CPUs in the following Broadcom SoCs:
+  BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664
+
+The enable method is specified by defining the following required
+properties in the "cpus" device tree node:
+  - enable-method = "brcm,bcm11351-cpu-method";
+  - secondary-boot-reg = <...>;
+
+The secondary-boot-reg property is a u32 value that specifies the
+physical address of the register used to request the ROM holding pen
+code release a secondary CPU.  The value written to the register is
+formed by encoding the target CPU id into the low bits of the
+physical start address it should jump to.
+
+Example:
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "brcm,bcm11351-cpu-method";
+		secondary-boot-reg = <0x3500417c>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,95 @@
+ARM Broadcom STB platforms Device Tree Bindings
+-----------------------------------------------
+Boards with Broadcom Brahma15 ARM-based BCMxxxx (generally BCM7xxx variants)
+SoC shall have the following DT organization:
+
+Required root node properties:
+    - compatible: "brcm,bcm<chip_id>", "brcm,brcmstb"
+
+example:
+/ {
+    #address-cells = <2>;
+    #size-cells = <2>;
+    model = "Broadcom STB (bcm7445)";
+    compatible = "brcm,bcm7445", "brcm,brcmstb";
+
+Further, syscon nodes that map platform-specific registers used for general
+system control is required:
+
+    - compatible: "brcm,bcm<chip_id>-sun-top-ctrl", "syscon"
+    - compatible: "brcm,bcm<chip_id>-hif-cpubiuctrl", "syscon"
+    - compatible: "brcm,bcm<chip_id>-hif-continuation", "syscon"
+
+example:
+    rdb {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        compatible = "simple-bus";
+        ranges = <0 0x00 0xf0000000 0x1000000>;
+
+        sun_top_ctrl: syscon@404000 {
+            compatible = "brcm,bcm7445-sun-top-ctrl", "syscon";
+            reg = <0x404000 0x51c>;
+        };
+
+        hif_cpubiuctrl: syscon@3e2400 {
+            compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon";
+            reg = <0x3e2400 0x5b4>;
+        };
+
+        hif_continuation: syscon@452000 {
+            compatible = "brcm,bcm7445-hif-continuation", "syscon";
+            reg = <0x452000 0x100>;
+        };
+    };
+
+Lastly, nodes that allow for support of SMP initialization and reboot are
+required:
+
+smpboot
+-------
+Required properties:
+
+    - compatible
+        The string "brcm,brcmstb-smpboot".
+
+    - syscon-cpu
+        A phandle / integer array property which lets the BSP know the location
+        of certain CPU power-on registers.
+
+        The layout of the property is as follows:
+            o a phandle to the "hif_cpubiuctrl" syscon node
+            o offset to the base CPU power zone register
+            o offset to the base CPU reset register
+
+    - syscon-cont
+        A phandle pointing to the syscon node which describes the CPU boot
+        continuation registers.
+            o a phandle to the "hif_continuation" syscon node
+
+example:
+    smpboot {
+        compatible = "brcm,brcmstb-smpboot";
+        syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+        syscon-cont = <&hif_continuation>;
+    };
+
+reboot
+-------
+Required properties
+
+    - compatible
+        The string property "brcm,brcmstb-reboot".
+
+    - syscon
+        A phandle / integer array that points to the syscon node which describes
+        the general system reset registers.
+            o a phandle to "sun_top_ctrl"
+            o offset to the "reset source enable" register
+            o offset to the "software master reset" register
+
+example:
+    reboot {
+        compatible = "brcm,brcmstb-reboot";
+        syscon = <&sun_top_ctrl 0x304 0x308>;
+    };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/ccn.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/ccn.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/ccn.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/ccn.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,21 @@
+* ARM CCN (Cache Coherent Network)
+
+Required properties:
+
+- compatible: (standard compatible string) should be one of:
+	"arm,ccn-504"
+	"arm,ccn-508"
+
+- reg: (standard registers property) physical address and size
+	(16MB) of the configuration registers block
+
+- interrupts: (standard interrupt property) single interrupt
+	generated by the control block
+
+Example:
+
+	ccn@0x2000000000 {
+		compatible = "arm,ccn-504";
+		reg = <0x20 0x00000000 0 0x1000000>;
+		interrupts = <0 181 4>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+========================================================
+Secondary CPU enable-method "marvell,berlin-smp" binding
+========================================================
+
+This document describes the "marvell,berlin-smp" method for enabling secondary
+CPUs. To apply to all CPUs, a single "marvell,berlin-smp" enable method should
+be defined in the "cpus" node.
+
+Enable method name:	"marvell,berlin-smp"
+Compatible machines:	"marvell,berlin2" and "marvell,berlin2q"
+Compatible CPUs:	"marvell,pj4b" and "arm,cortex-a9"
+Related properties:	(none)
+
+Note:
+This enable method needs valid nodes compatible with "arm,cortex-a9-scu" and
+"marvell,berlin-cpu-ctrl"[1].
+
+Example:
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "marvell,berlin-smp";
+
+		cpu@0 {
+			compatible = "marvell,pj4b";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "marvell,pj4b";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <1>;
+		};
+	};
+
+--
+[1] arm/marvell,berlin.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/cpus.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/cpus.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/cpus.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/cpus.txt	2014-09-28 17:29:07.000000000 -0400
@@ -152,7 +152,9 @@ nodes to be present and contain the prop
 			    "arm,cortex-a7"
 			    "arm,cortex-a8"
 			    "arm,cortex-a9"
+			    "arm,cortex-a12"
 			    "arm,cortex-a15"
+			    "arm,cortex-a17"
 			    "arm,cortex-a53"
 			    "arm,cortex-a57"
 			    "arm,cortex-m0"
@@ -163,6 +165,7 @@ nodes to be present and contain the prop
 			    "arm,cortex-r4"
 			    "arm,cortex-r5"
 			    "arm,cortex-r7"
+			    "brcm,brahma-b15"
 			    "faraday,fa526"
 			    "intel,sa110"
 			    "intel,sa1100"
@@ -184,6 +187,7 @@ nodes to be present and contain the prop
 			  can be one of:
 			    "allwinner,sun6i-a31"
 			    "arm,psci"
+			    "brcm,brahma-b15"
 			    "marvell,armada-375-smp"
 			    "marvell,armada-380-smp"
 			    "marvell,armada-xp-smp"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/gic.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/gic.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/gic.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/gic.txt	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@ Main node required properties:
 	"arm,cortex-a9-gic"
 	"arm,cortex-a7-gic"
 	"arm,arm11mp-gic"
+	"brcm,brahma-b15-gic"
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
   interrupt source.  The type shall be a <u32> and the value shall be 3.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/gic-v3.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/gic-v3.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/gic-v3.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/gic-v3.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,79 @@
+* ARM Generic Interrupt Controller, version 3
+
+AArch64 SMP cores are often associated with a GICv3, providing Private
+Peripheral Interrupts (PPI), Shared Peripheral Interrupts (SPI),
+Software Generated Interrupts (SGI), and Locality-specific Peripheral
+Interrupts (LPI).
+
+Main node required properties:
+
+- compatible : should at least contain  "arm,gic-v3".
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. Must be a single cell with a value of at least 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts. Other values are reserved for future use.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987]. PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = edge triggered
+		4 = level triggered
+
+  Cells 4 and beyond are reserved for future use. When the 1st cell
+  has a value of 0 or 1, cells 4 and beyond act as padding, and may be
+  ignored. It is recommended that padding cells have a value of 0.
+
+- reg : Specifies base physical address(s) and size of the GIC
+  registers, in the following order:
+  - GIC Distributor interface (GICD)
+  - GIC Redistributors (GICR), one range per redistributor region
+  - GIC CPU interface (GICC)
+  - GIC Hypervisor interface (GICH)
+  - GIC Virtual CPU interface (GICV)
+
+  GICC, GICH and GICV are optional.
+
+- interrupts : Interrupt source of the VGIC maintenance interrupt.
+
+Optional
+
+- redistributor-stride : If using padding pages, specifies the stride
+  of consecutive redistributors. Must be a multiple of 64kB.
+
+- #redistributor-regions: The number of independent contiguous regions
+  occupied by the redistributors. Required if more than one such
+  region is present.
+
+Examples:
+
+	gic: interrupt-controller@2cf00000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x2f000000 0 0x10000>,	// GICD
+		      <0x0 0x2f100000 0 0x200000>,	// GICR
+		      <0x0 0x2c000000 0 0x2000>,	// GICC
+		      <0x0 0x2c010000 0 0x2000>,	// GICH
+		      <0x0 0x2c020000 0 0x2000>;	// GICV
+		interrupts = <1 9 4>;
+	};
+
+	gic: interrupt-controller@2c010000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		redistributor-stride = <0x0 0x40000>;	// 256kB stride
+		#redistributor-regions = <2>;
+		reg = <0x0 0x2c010000 0 0x10000>,	// GICD
+		      <0x0 0x2d000000 0 0x800000>,	// GICR 1: CPUs 0-31
+		      <0x0 0x2e000000 0 0x800000>;	// GICR 2: CPUs 32-63
+		      <0x0 0x2c040000 0 0x2000>,	// GICC
+		      <0x0 0x2c060000 0 0x2000>,	// GICH
+		      <0x0 0x2c080000 0 0x2000>;	// GICV
+		interrupts = <1 9 4>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,17 @@ Example:
 		reboot-offset = <0x4>;
 	};
 
+-----------------------------------------------------------------------
+Hisilicon CPU controller
+
+Required properties:
+- compatible : "hisilicon,cpuctrl"
+- reg : Register address and size
+
+The clock registers and power registers of secondary cores are defined
+in CPU controller, especially in HIX5HD2 SoC.
+
+-----------------------------------------------------------------------
 PCTRL: Peripheral misc control register
 
 Required Properties:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/marvell,berlin.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/marvell,berlin.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/marvell,berlin.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/marvell,berlin.txt	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,22 @@ SoC and board used. Currently known SoC
 	...
 }
 
+* Marvell Berlin CPU control bindings
+
+CPU control register allows various operations on CPUs, like resetting them
+independently.
+
+Required properties:
+- compatible: should be "marvell,berlin-cpu-ctrl"
+- reg: address and length of the register set
+
+Example:
+
+cpu-ctrl@f7dd0000 {
+	compatible = "marvell,berlin-cpu-ctrl";
+	reg = <0xf7dd0000 0x10000>;
+};
+
 * Marvell Berlin2 chip control binding
 
 Marvell Berlin SoCs have a chip control register set providing several
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/mediatek.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/mediatek.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/mediatek.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/mediatek.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,8 @@
+Mediatek MT6589 Platforms Device Tree Bindings
+
+Boards with a SoC of the Mediatek MT6589 shall have the following property:
+
+Required root node property:
+
+compatible: must contain "mediatek,mt6589"
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@ Required properties:
 - compatible : Should be "ti,irq-crossbar"
 - reg: Base address and the size of the crossbar registers.
 - ti,max-irqs: Total number of irqs available at the interrupt controller.
+- ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed.
 - ti,reg-size: Size of a individual register in bytes. Every individual
 	    register is assumed to be of same size. Valid sizes are 1, 2, 4.
 - ti,irqs-reserved: List of the reserved irq lines that are not muxed using
@@ -17,11 +18,46 @@ Required properties:
 		 so crossbar bar driver should not consider them as free
 		 lines.
 
+Optional properties:
+- ti,irqs-skip: This is similar to "ti,irqs-reserved", but these are for
+  SOC-specific hard-wiring of those irqs which unexpectedly bypasses the
+  crossbar. These irqs have a crossbar register, but still cannot be used.
+
+- ti,irqs-safe-map: integer which maps to a safe configuration to use
+  when the interrupt controller irq is unused (when not provided, default is 0)
+
 Examples:
 		crossbar_mpu: @4a020000 {
 			compatible = "ti,irq-crossbar";
 			reg = <0x4a002a48 0x130>;
 			ti,max-irqs = <160>;
+			ti,max-crossbar-sources = <400>;
 			ti,reg-size = <2>;
 			ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+			ti,irqs-skip = <10 133 139 140>;
 		};
+
+Consumer:
+========
+See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
+Documentation/devicetree/bindings/arm/gic.txt for further details.
+
+An interrupt consumer on an SoC using crossbar will use:
+	interrupts = <GIC_SPI request_number interrupt_level>
+When the request number is between 0 to that described by
+"ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the
+request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
+quirky hardware mapping direct to GIC.
+
+Example:
+	device_x@0x4a023000 {
+		/* Crossbar 8 used */
+		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+		...
+	};
+
+	device_y@0x4a033000 {
+		/* Direct mapped GIC SPI 1 used */
+		interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
+		...
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2014-09-28 17:29:07.000000000 -0400
@@ -129,6 +129,9 @@ Boards:
 - AM437x GP EVM
   compatible = "ti,am437x-gp-evm", "ti,am4372", "ti,am43"
 
+- AM437x SK EVM: AM437x StarterKit Evaluation Module
+  compatible = "ti,am437x-sk-evm", "ti,am4372", "ti,am43"
+
 - DRA742 EVM:  Software Development Board for DRA742
   compatible = "ti,dra7-evm", "ti,dra742", "ti,dra74", "ti,dra7"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/prcm.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/prcm.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/omap/prcm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/omap/prcm.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,65 @@
+OMAP PRCM bindings
+
+Power Reset and Clock Manager lists the device clocks and clockdomains under
+a DT hierarchy. Each TI SoC can have multiple PRCM entities listed for it,
+each describing one module and the clock hierarchy under it. see [1] for
+documentation about the individual clock/clockdomain nodes.
+
+[1] Documentation/devicetree/bindings/clock/ti/*
+
+Required properties:
+- compatible:	Must be one of:
+		"ti,am3-prcm"
+		"ti,am3-scrm"
+		"ti,am4-prcm"
+		"ti,am4-scrm"
+		"ti,omap2-prcm"
+		"ti,omap2-scrm"
+		"ti,omap3-prm"
+		"ti,omap3-cm"
+		"ti,omap3-scrm"
+		"ti,omap4-cm1"
+		"ti,omap4-prm"
+		"ti,omap4-cm2"
+		"ti,omap4-scrm"
+		"ti,omap5-prm"
+		"ti,omap5-cm-core-aon"
+		"ti,omap5-scrm"
+		"ti,omap5-cm-core"
+		"ti,dra7-prm"
+		"ti,dra7-cm-core-aon"
+		"ti,dra7-cm-core"
+- reg:		Contains PRCM module register address range
+		(base address and length)
+- clocks:	clocks for this module
+- clockdomains:	clockdomains for this module
+
+Example:
+
+cm: cm@48004000 {
+	compatible = "ti,omap3-cm";
+	reg = <0x48004000 0x4000>;
+
+	cm_clocks: clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	cm_clockdomains: clockdomains {
+	};
+}
+
+&cm_clocks {
+	omap2_32k_fck: omap_32k_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+};
+
+&cm_clockdomains {
+	core_l3_clkdm: core_l3_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&sdrc_ick>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -14,14 +14,21 @@ Required properties:
 				for exynos4412/5250 controllers.
 			Must be "samsung,exynos-adc-v2" for
 				future controllers.
+			Must be "samsung,exynos3250-adc" for
+				controllers compatible with ADC of Exynos3250.
 - reg:			Contains ADC register address range (base address and
 			length) and the address of the phy enable register.
 - interrupts: 		Contains the interrupt information for the timer. The
 			format is being dependent on which interrupt controller
 			the Samsung device uses.
 - #io-channel-cells = <1>; As ADC has multiple outputs
-- clocks		From common clock binding: handle to adc clock.
-- clock-names		From common clock binding: Shall be "adc".
+- clocks		From common clock bindings: handles to clocks specified
+			in "clock-names" property, in the same order.
+- clock-names		From common clock bindings: list of clock input names
+			used by ADC block:
+			- "adc" : ADC bus clock
+			- "sclk" : ADC special clock (only for Exynos3250 and
+				   compatible ADC block)
 - vdd-supply		VDD input supply.
 
 Note: child nodes can be added for auto probing from device tree.
@@ -41,6 +48,20 @@ adc: adc@12D10000 {
 	vdd-supply = <&buck5_reg>;
 };
 
+Example: adding device info in dtsi file for Exynos3250 with additional sclk
+
+adc: adc@126C0000 {
+	compatible = "samsung,exynos3250-adc", "samsung,exynos-adc-v2;
+	reg = <0x126C0000 0x100>, <0x10020718 0x4>;
+	interrupts = <0 137 0>;
+	#io-channel-cells = <1>;
+	io-channel-ranges;
+
+	clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
+	clock-names = "adc", "sclk";
+
+	vdd-supply = <&buck5_reg>;
+};
 
 Example: Adding child nodes in dts file
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/samsung/pmu.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/samsung/pmu.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/samsung/pmu.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/samsung/pmu.txt	2014-09-28 17:29:07.000000000 -0400
@@ -7,13 +7,45 @@ Properties:
 		   - "samsung,exynos4212-pmu" - for Exynos4212 SoC,
 		   - "samsung,exynos4412-pmu" - for Exynos4412 SoC,
 		   - "samsung,exynos5250-pmu" - for Exynos5250 SoC,
+		   - "samsung,exynos5260-pmu" - for Exynos5260 SoC.
+		   - "samsung,exynos5410-pmu" - for Exynos5410 SoC,
 		   - "samsung,exynos5420-pmu" - for Exynos5420 SoC.
 		second value must be always "syscon".
 
  - reg : offset and length of the register set.
 
+ - #clock-cells : must be <1>, since PMU requires once cell as clock specifier.
+		The single specifier cell is used as index to list of clocks
+		provided by PMU, which is currently:
+			0 : SoC clock output (CLKOUT pin)
+
+ - clock-names : list of clock names for particular CLKOUT mux inputs in
+		following format:
+			"clkoutN", where N is a decimal number corresponding to
+			CLKOUT mux control bits value for given input, e.g.
+				"clkout0", "clkout7", "clkout15".
+
+ - clocks : list of phandles and specifiers to all input clocks listed in
+		clock-names property.
+
 Example :
 pmu_system_controller: system-controller@10040000 {
 	compatible = "samsung,exynos5250-pmu", "syscon";
 	reg = <0x10040000 0x5000>;
+	#clock-cells = <1>;
+	clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+			"clkout4", "clkout8", "clkout9";
+	clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+		<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+		<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+		<&clock CLK_XUSBXTI>;
+};
+
+Example of clock consumer :
+
+usb3503: usb3503@08 {
+	/* ... */
+	clock-names = "refclk";
+	clocks = <&pmu_system_controller 0>;
+	/* ... */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+SPEAr Misc configuration
+===========================
+SPEAr SOCs have some miscellaneous registers which are used to configure
+few properties of different peripheral controllers.
+
+misc node required properties:
+
+- compatible Should be	"st,spear1340-misc", "syscon".
+- reg: Address range of misc space upto 8K
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/tegra.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/tegra.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/tegra.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/tegra.txt	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,8 @@ board-specific compatible values:
   nvidia,seaboard
   nvidia,ventana
   nvidia,whistler
+  toradex,apalis_t30
+  toradex,apalis_t30-eval
   toradex,colibri_t20-512
   toradex,iris
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/xilinx.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/xilinx.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/arm/xilinx.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/arm/xilinx.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
-Xilinx Zynq EP107 Emulation Platform board
+Xilinx Zynq Platforms Device Tree Bindings
 
-This board is an emulation platform for the Zynq product which is
-based on an ARM Cortex A9 processor.
+Boards with Zynq-7000 SOC based on an ARM Cortex A9 processor
+shall have the following properties.
 
 Required root node properties:
-    - compatible = "xlnx,zynq-ep107";
+    - compatible = "xlnx,zynq-7000";
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/ahci-platform.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/ahci-platform.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/ahci-platform.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/ahci-platform.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,28 +3,43 @@
 SATA nodes are defined to describe on-chip Serial ATA controllers.
 Each SATA controller should have its own node.
 
+It is possible, but not required, to represent each port as a sub-node.
+It allows to enable each port independently when dealing with multiple
+PHYs.
+
 Required properties:
 - compatible        : compatible string, one of:
   - "allwinner,sun4i-a10-ahci"
-  - "fsl,imx53-ahci"
-  - "fsl,imx6q-ahci"
   - "hisilicon,hisi-ahci"
   - "ibm,476gtr-ahci"
   - "marvell,armada-380-ahci"
   - "snps,dwc-ahci"
   - "snps,exynos5440-ahci"
   - "snps,spear-ahci"
+  - "generic-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
+Please note that when using "generic-ahci" you must also specify a SoC specific
+compatible:
+	compatible = "manufacturer,soc-model-ahci", "generic-ahci";
+
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
 - clocks            : a list of phandle + clock specifier pairs
 - target-supply     : regulator for SATA target power
+- phys              : reference to the SATA PHY node
+- phy-names         : must be "sata-phy"
+
+Required properties when using sub-nodes:
+- #address-cells    : number of cells to encode an address
+- #size-cells       : number of cells representing the size of an address
+
+
+Sub-nodes required properties:
+- reg               : the port number
+- phys              : reference to the SATA PHY node
 
-"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
-- clocks            : must contain the sata, sata_ref and ahb clocks
-- clock-names       : must contain "ahb" for the ahb clock
 
 Examples:
         sata@ffe08000 {
@@ -40,3 +55,23 @@ Examples:
 		clocks = <&pll6 0>, <&ahb_gates 25>;
 		target-supply = <&reg_ahci_5v>;
 	};
+
+With sub-nodes:
+	sata@f7e90000 {
+		compatible = "marvell,berlin2q-achi", "generic-ahci";
+		reg = <0xe90000 0x1000>;
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&chip CLKID_SATA>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sata0: sata-port@0 {
+			reg = <0>;
+			phys = <&sata_phy 0>;
+		};
+
+		sata1: sata-port@1 {
+			reg = <1>;
+			phys = <&sata_phy 1>;
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,31 @@
+STMicroelectronics STi SATA controller
+
+This binding describes a SATA device.
+
+Required properties:
+ - compatible	   : Must be "st,sti-ahci"
+ - reg		   : Physical base addresses and length of register sets
+ - interrupts	   : Interrupt associated with the SATA device
+ - interrupt-names :   Associated name must be; "hostc"
+ - resets	   : The power-down and soft-reset lines of SATA IP
+ - reset-names	   :   Associated names must be; "pwr-dwn" and "sw-rst"
+ - clocks	   : The phandle for the clock
+ - clock-names	   :   Associated name must be; "ahci_clk"
+ - phys		   : The phandle for the PHY device
+ - phy-names	   :   Associated name must be; "ahci_phy"
+
+Example:
+
+	sata0: sata@fe380000 {
+		compatible      = "st,sti-ahci";
+		reg             = <0xfe380000 0x1000>;
+		interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
+		interrupt-names = "hostc";
+		phys	        = <&miphy365x_phy MIPHY_PORT_0 MIPHY_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";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/imx-sata.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/imx-sata.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/imx-sata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/imx-sata.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+* Freescale i.MX AHCI SATA Controller
+
+The Freescale i.MX SATA controller mostly conforms to the AHCI interface
+with some special extensions at integration level.
+
+Required properties:
+- compatible : should be one of the following:
+   - "fsl,imx53-ahci" for i.MX53 SATA controller
+   - "fsl,imx6q-ahci" for i.MX6Q SATA controller
+- interrupts : interrupt mapping for SATA IRQ
+- reg : registers mapping
+- clocks : list of clock specifiers, must contain an entry for each
+  required entry in clock-names
+- clock-names : should include "sata", "sata_ref" and "ahb" entries
+
+Optional properties:
+- fsl,transmit-level-mV : transmit voltage level, in millivolts.
+- fsl,transmit-boost-mdB : transmit boost level, in milli-decibels
+- fsl,transmit-atten-16ths : transmit attenuation, in 16ths
+- fsl,receive-eq-mdB : receive equalisation, in milli-decibels
+  Please refer to the technical documentation or the driver source code
+  for the list of legal values for these options.
+- fsl,no-spread-spectrum : disable spread-spectrum clocking on the SATA
+  link.
+
+Examples:
+
+sata@02200000 {
+	compatible = "fsl,imx6q-ahci";
+	reg = <0x02200000 0x4000>;
+	interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks IMX6QDL_CLK_SATA>,
+		 <&clks IMX6QDL_CLK_SATA_REF_100M>,
+		 <&clks IMX6QDL_CLK_AHB>;
+	clock-names = "sata", "sata_ref", "ahb";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+Tegra124 SoC SATA AHCI controller
+
+Required properties :
+- compatible : "nvidia,tegra124-ahci".
+- reg : Should contain 2 entries:
+  - AHCI register set (SATA BAR5)
+  - SATA register set
+- interrupts : Defines the interrupt used by SATA
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - sata
+  - sata-oob
+  - cml1
+  - pll_e
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - sata
+  - sata-oob
+  - sata-cold
+- phys : Must contain an entry for each entry in phy-names.
+  See ../phy/phy-bindings.txt for details.
+- phy-names : Must include the following entries:
+  - sata-phy : XUSB PADCTL SATA PHY
+- hvdd-supply : Defines the SATA HVDD regulator
+- vddio-supply : Defines the SATA VDDIO regulator
+- avdd-supply : Defines the SATA AVDD regulator
+- target-5v-supply : Defines the SATA 5V power regulator
+- target-12v-supply : Defines the SATA 12V power regulator
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/arm-integrator.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/arm-integrator.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/arm-integrator.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/arm-integrator.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,4 @@
-Clock bindings for ARM Integrator Core Module clocks
+Clock bindings for ARM Integrator and Versatile Core Module clocks
 
 Auxilary Oscillator Clock
 
@@ -12,7 +12,7 @@ parent node.
 
 
 Required properties:
-- compatible: must be "arm,integrator-cm-auxosc"
+- compatible: must be "arm,integrator-cm-auxosc" or "arm,versatile-cm-auxosc"
 - #clock-cells: must be <0>
 
 Optional properties:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,35 @@
+* Palmas 32KHz clocks *
+
+Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
+
+This binding uses the common clock binding ./clock-bindings.txt.
+
+Required properties:
+- compatible :	"ti,palmas-clk32kg" for clk32kg clock
+		"ti,palmas-clk32kgaudio" for clk32kgaudio clock
+- #clock-cells : shall be set to 0.
+
+Optional property:
+- ti,external-sleep-control: The external enable input pins controlled the
+	enable/disable of clocks.  The external enable input pins ENABLE1,
+	ENABLE2 and NSLEEP. The valid values for the external pins are:
+		PALMAS_EXT_CONTROL_PIN_ENABLE1 for ENABLE1 pin
+		PALMAS_EXT_CONTROL_PIN_ENABLE2 for ENABLE2 pin
+		PALMAS_EXT_CONTROL_PIN_NSLEEP for NSLEEP pin
+	Option 0 or missing this property means the clock is enabled/disabled
+	via register access and these pins do not have any control.
+	The macros of external control pins for DTS is defined at
+	dt-bindings/mfd/palmas.h
+
+Example:
+	#include <dt-bindings/mfd/palmas.h>
+	...
+	palmas: tps65913@58 {
+		...
+		clk32kg: palmas_clk32k@0 {
+			compatible = "ti,palmas-clk32kg";
+			#clock-cells = <0>;
+			ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>;
+		};
+		...
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,53 @@
+* Samsung Audio Subsystem Clock Controller
+
+The Samsung Audio Subsystem clock controller generates and supplies clocks
+to Audio Subsystem block available in the S5PV210 and compatible SoCs.
+
+Required Properties:
+
+- compatible: should be "samsung,s5pv210-audss-clock".
+- reg: physical base address and length of the controller's register set.
+
+- #clock-cells: should be 1.
+
+- clocks:
+  - hclk: AHB bus clock of the Audio Subsystem.
+  - xxti: Optional fixed rate PLL reference clock, parent of mout_audss. If
+    not specified (i.e. xusbxti is used for PLL reference), it is fixed to
+    a clock named "xxti".
+  - fout_epll: Input PLL to the AudioSS block, parent of mout_audss.
+  - iiscdclk0: Optional external i2s clock, parent of mout_i2s. If not
+    specified, it is fixed to a clock named "iiscdclk0".
+  - sclk_audio0: Audio bus clock, parent of mout_i2s.
+
+- clock-names: Aliases for the above clocks. They should be "hclk",
+  "xxti", "fout_epll", "iiscdclk0", and "sclk_audio0" respectively.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s5pv210-audss-clk.h header and can be used in device
+tree sources.
+
+Example: Clock controller node.
+
+	clk_audss: clock-controller@c0900000 {
+		compatible = "samsung,s5pv210-audss-clock";
+		reg = <0xc0900000 0x1000>;
+		#clock-cells = <1>;
+		clock-names = "hclk", "xxti",
+				"fout_epll", "sclk_audio0";
+		clocks = <&clocks DOUT_HCLKP>, <&xxti>,
+				<&clocks FOUT_EPLL>, <&clocks SCLK_AUDIO0>;
+	};
+
+Example: I2S controller node that consumes the clock generated by the clock
+	 controller. Refer to the standard clock bindings for information
+         about 'clocks' and 'clock-names' property.
+
+	i2s0: i2s@03830000 {
+		/* ... */
+		clock-names = "iis", "i2s_opclk0",
+				"i2s_opclk1";
+		clocks = <&clk_audss CLK_I2S>, <&clk_audss CLK_I2S>,
+				<&clk_audss CLK_DOUT_AUD_BUS>;
+		/* ... */
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clock-bindings.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clock-bindings.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clock-bindings.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clock-bindings.txt	2014-09-28 17:29:07.000000000 -0400
@@ -131,3 +131,39 @@ clock signal, and a UART.
   ("pll" and "pll-switched").
 * The UART has its baud clock connected the external oscillator and its
   register clock connected to the PLL clock (the "pll-switched" signal)
+
+==Assigned clock parents and rates==
+
+Some platforms may require initial configuration of default parent clocks
+and clock frequencies. Such a configuration can be specified in a device tree
+node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
+properties. The assigned-clock-parents property should contain a list of parent
+clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
+property the list of assigned clock frequency values - corresponding to clocks
+listed in the assigned-clocks property.
+
+To skip setting parent or rate of a clock its corresponding entry should be
+set to 0, or can be omitted if it is not followed by any non-zero entry.
+
+    uart@a000 {
+        compatible = "fsl,imx-uart";
+        reg = <0xa000 0x1000>;
+        ...
+        clocks = <&osc 0>, <&pll 1>;
+        clock-names = "baud", "register";
+
+        assigned-clocks = <&clkcon 0>, <&pll 2>;
+        assigned-clock-parents = <&pll 2>;
+        assigned-clock-rates = <0>, <460800>;
+    };
+
+In this example the <&pll 2> clock is set as parent of clock <&clkcon 0> and
+the <&pll 2> clock is assigned a frequency value of 460800 Hz.
+
+Configuring a clock's parent and rate through the device node that consumes
+the clock can be done only for clocks that have a single user. Specifying
+conflicting parent or rate configuration in multiple consumer nodes for
+a shared clock is forbidden.
+
+Configuration of common clocks, which affect multiple consumer devices can
+be similarly specified in the clock provider node.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clps711x-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clps711x-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/clps711x-clock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/clps711x-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+* Clock bindings for the Cirrus Logic CLPS711X CPUs
+
+Required properties:
+- compatible       : Shall contain "cirrus,clps711x-clk".
+- reg              : Address of the internal register set.
+- startup-frequency: Factory set CPU startup frequency in HZ.
+- #clock-cells     : Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/clps711x-clock.h
+for the full list of CLPS711X clock IDs.
+
+Example:
+	clks: clks@80000000 {
+		#clock-cells = <1>;
+		compatible = "cirrus,ep7312-clk", "cirrus,clps711x-clk";
+		reg = <0x80000000 0xc000>;
+		startup-frequency = <73728000>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx1-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx1-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx1-clock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx1-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+* Clock bindings for Freescale i.MX1 CPUs
+
+Required properties:
+- compatible: Should be "fsl,imx1-ccm".
+- reg: Address and length of the register set.
+- #clock-cells: Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx1-clock.h
+for the full list of i.MX1 clock IDs.
+
+Examples:
+	clks: ccm@0021b000 {
+		#clock-cells = <1>;
+		compatible = "fsl,imx1-ccm";
+		reg = <0x0021b000 0x1000>;
+	};
+
+	pwm: pwm@00208000 {
+		#pwm-cells = <2>;
+		compatible = "fsl,imx1-pwm";
+		reg = <0x00208000 0x1000>;
+		interrupts = <34>;
+		clocks = <&clks IMX1_CLK_DUMMY>, <&clks IMX1_CLK_PER1>;
+		clock-names = "ipg", "per";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx21-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx21-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx21-clock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx21-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+* Clock bindings for Freescale i.MX21
+
+Required properties:
+- compatible  : Should be "fsl,imx21-ccm".
+- reg         : Address and length of the register set.
+- interrupts  : Should contain CCM interrupt.
+- #clock-cells: Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx21-clock.h
+for the full list of i.MX21 clock IDs.
+
+Examples:
+	clks: ccm@10027000{
+		compatible = "fsl,imx21-ccm";
+		reg = <0x10027000 0x800>;
+		#clock-cells = <1>;
+	};
+
+	uart1: serial@1000a000 {
+		compatible = "fsl,imx21-uart";
+		reg = <0x1000a000 0x1000>;
+		interrupts = <20>;
+		clocks = <&clks IMX21_CLK_UART1_IPG_GATE>,
+			 <&clks IMX21_CLK_PER1>;
+		clock-names = "ipg", "per";
+		status = "disabled";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx27-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx27-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx27-clock.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx27-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -7,117 +7,22 @@ Required properties:
 - #clock-cells: Should be <1>
 
 The clock consumer should specify the desired clock by having the clock
-ID in its "clocks" phandle cell.  The following is a full list of i.MX27
-clocks and IDs.
-
-	Clock		    ID
-	-----------------------
-	dummy                0
-	ckih                 1
-	ckil                 2
-	mpll                 3
-	spll                 4
-	mpll_main2           5
-	ahb                  6
-	ipg                  7
-	nfc_div              8
-	per1_div             9
-	per2_div             10
-	per3_div             11
-	per4_div             12
-	vpu_sel              13
-	vpu_div              14
-	usb_div              15
-	cpu_sel              16
-	clko_sel             17
-	cpu_div              18
-	clko_div             19
-	ssi1_sel             20
-	ssi2_sel             21
-	ssi1_div             22
-	ssi2_div             23
-	clko_en              24
-	ssi2_ipg_gate        25
-	ssi1_ipg_gate        26
-	slcdc_ipg_gate       27
-	sdhc3_ipg_gate       28
-	sdhc2_ipg_gate       29
-	sdhc1_ipg_gate       30
-	scc_ipg_gate         31
-	sahara_ipg_gate      32
-	rtc_ipg_gate         33
-	pwm_ipg_gate         34
-	owire_ipg_gate       35
-	lcdc_ipg_gate        36
-	kpp_ipg_gate         37
-	iim_ipg_gate         38
-	i2c2_ipg_gate        39
-	i2c1_ipg_gate        40
-	gpt6_ipg_gate        41
-	gpt5_ipg_gate        42
-	gpt4_ipg_gate        43
-	gpt3_ipg_gate        44
-	gpt2_ipg_gate        45
-	gpt1_ipg_gate        46
-	gpio_ipg_gate        47
-	fec_ipg_gate         48
-	emma_ipg_gate        49
-	dma_ipg_gate         50
-	cspi3_ipg_gate       51
-	cspi2_ipg_gate       52
-	cspi1_ipg_gate       53
-	nfc_baud_gate        54
-	ssi2_baud_gate       55
-	ssi1_baud_gate       56
-	vpu_baud_gate        57
-	per4_gate            58
-	per3_gate            59
-	per2_gate            60
-	per1_gate            61
-	usb_ahb_gate         62
-	slcdc_ahb_gate       63
-	sahara_ahb_gate      64
-	lcdc_ahb_gate        65
-	vpu_ahb_gate         66
-	fec_ahb_gate         67
-	emma_ahb_gate        68
-	emi_ahb_gate         69
-	dma_ahb_gate         70
-	csi_ahb_gate         71
-	brom_ahb_gate        72
-	ata_ahb_gate         73
-	wdog_ipg_gate        74
-	usb_ipg_gate         75
-	uart6_ipg_gate       76
-	uart5_ipg_gate       77
-	uart4_ipg_gate       78
-	uart3_ipg_gate       79
-	uart2_ipg_gate       80
-	uart1_ipg_gate       81
-	ckih_div1p5          82
-	fpm                  83
-	mpll_osc_sel         84
-	mpll_sel             85
-	spll_gate            86
-	mshc_div             87
-	rtic_ipg_gate        88
-	mshc_ipg_gate        89
-	rtic_ahb_gate        90
-	mshc_baud_gate       91
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx27-clock.h
+for the full list of i.MX27 clock IDs.
 
 Examples:
+	clks: ccm@10027000{
+		compatible = "fsl,imx27-ccm";
+		reg = <0x10027000 0x1000>;
+		#clock-cells = <1>;
+	};
 
-clks: ccm@10027000{
-	compatible = "fsl,imx27-ccm";
-	reg = <0x10027000 0x1000>;
-	#clock-cells = <1>;
-};
-
-uart1: serial@1000a000 {
-	compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-	reg = <0x1000a000 0x1000>;
-	interrupts = <20>;
-	clocks = <&clks 81>, <&clks 61>;
-	clock-names = "ipg", "per";
-	status = "disabled";
-};
+	uart1: serial@1000a000 {
+		compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+		reg = <0x1000a000 0x1000>;
+		interrupts = <20>;
+		clocks = <&clks IMX27_CLK_UART1_IPG_GATE>,
+			 <&clks IMX27_CLK_PER1_GATE>;
+		clock-names = "ipg", "per";
+		status = "disabled";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx6q-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx6q-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/imx6q-clock.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/imx6q-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -7,223 +7,13 @@ Required properties:
 - #clock-cells: Should be <1>
 
 The clock consumer should specify the desired clock by having the clock
-ID in its "clocks" phandle cell.  The following is a full list of i.MX6Q
-clocks and IDs.
-
-	Clock			ID
-	---------------------------
-	dummy			0
-	ckil			1
-	ckih			2
-	osc			3
-	pll2_pfd0_352m		4
-	pll2_pfd1_594m		5
-	pll2_pfd2_396m		6
-	pll3_pfd0_720m		7
-	pll3_pfd1_540m		8
-	pll3_pfd2_508m		9
-	pll3_pfd3_454m		10
-	pll2_198m		11
-	pll3_120m		12
-	pll3_80m		13
-	pll3_60m		14
-	twd			15
-	step			16
-	pll1_sw			17
-	periph_pre		18
-	periph2_pre		19
-	periph_clk2_sel		20
-	periph2_clk2_sel	21
-	axi_sel			22
-	esai_sel		23
-	asrc_sel		24
-	spdif_sel		25
-	gpu2d_axi		26
-	gpu3d_axi		27
-	gpu2d_core_sel		28
-	gpu3d_core_sel		29
-	gpu3d_shader_sel	30
-	ipu1_sel		31
-	ipu2_sel		32
-	ldb_di0_sel		33
-	ldb_di1_sel		34
-	ipu1_di0_pre_sel	35
-	ipu1_di1_pre_sel	36
-	ipu2_di0_pre_sel	37
-	ipu2_di1_pre_sel	38
-	ipu1_di0_sel		39
-	ipu1_di1_sel		40
-	ipu2_di0_sel		41
-	ipu2_di1_sel		42
-	hsi_tx_sel		43
-	pcie_axi_sel		44
-	ssi1_sel		45
-	ssi2_sel		46
-	ssi3_sel		47
-	usdhc1_sel		48
-	usdhc2_sel		49
-	usdhc3_sel		50
-	usdhc4_sel		51
-	enfc_sel		52
-	emi_sel			53
-	emi_slow_sel		54
-	vdo_axi_sel		55
-	vpu_axi_sel		56
-	cko1_sel		57
-	periph			58
-	periph2			59
-	periph_clk2		60
-	periph2_clk2		61
-	ipg			62
-	ipg_per			63
-	esai_pred		64
-	esai_podf		65
-	asrc_pred		66
-	asrc_podf		67
-	spdif_pred		68
-	spdif_podf		69
-	can_root		70
-	ecspi_root		71
-	gpu2d_core_podf		72
-	gpu3d_core_podf		73
-	gpu3d_shader		74
-	ipu1_podf		75
-	ipu2_podf		76
-	ldb_di0_podf		77
-	ldb_di1_podf		78
-	ipu1_di0_pre		79
-	ipu1_di1_pre		80
-	ipu2_di0_pre		81
-	ipu2_di1_pre		82
-	hsi_tx_podf		83
-	ssi1_pred		84
-	ssi1_podf		85
-	ssi2_pred		86
-	ssi2_podf		87
-	ssi3_pred		88
-	ssi3_podf		89
-	uart_serial_podf	90
-	usdhc1_podf		91
-	usdhc2_podf		92
-	usdhc3_podf		93
-	usdhc4_podf		94
-	enfc_pred		95
-	enfc_podf		96
-	emi_podf		97
-	emi_slow_podf		98
-	vpu_axi_podf		99
-	cko1_podf		100
-	axi			101
-	mmdc_ch0_axi_podf	102
-	mmdc_ch1_axi_podf	103
-	arm			104
-	ahb			105
-	apbh_dma		106
-	asrc			107
-	can1_ipg		108
-	can1_serial		109
-	can2_ipg		110
-	can2_serial		111
-	ecspi1			112
-	ecspi2			113
-	ecspi3			114
-	ecspi4			115
-	ecspi5			116
-	enet			117
-	esai			118
-	gpt_ipg			119
-	gpt_ipg_per		120
-	gpu2d_core		121
-	gpu3d_core		122
-	hdmi_iahb		123
-	hdmi_isfr		124
-	i2c1			125
-	i2c2			126
-	i2c3			127
-	iim			128
-	enfc			129
-	ipu1			130
-	ipu1_di0		131
-	ipu1_di1		132
-	ipu2			133
-	ipu2_di0		134
-	ldb_di0			135
-	ldb_di1			136
-	ipu2_di1		137
-	hsi_tx			138
-	mlb			139
-	mmdc_ch0_axi		140
-	mmdc_ch1_axi		141
-	ocram			142
-	openvg_axi		143
-	pcie_axi		144
-	pwm1			145
-	pwm2			146
-	pwm3			147
-	pwm4			148
-	per1_bch		149
-	gpmi_bch_apb		150
-	gpmi_bch		151
-	gpmi_io			152
-	gpmi_apb		153
-	sata			154
-	sdma			155
-	spba			156
-	ssi1			157
-	ssi2			158
-	ssi3			159
-	uart_ipg		160
-	uart_serial		161
-	usboh3			162
-	usdhc1			163
-	usdhc2			164
-	usdhc3			165
-	usdhc4			166
-	vdo_axi			167
-	vpu_axi			168
-	cko1			169
-	pll1_sys		170
-	pll2_bus		171
-	pll3_usb_otg		172
-	pll4_audio		173
-	pll5_video		174
-	pll8_mlb		175
-	pll7_usb_host		176
-	pll6_enet		177
-	ssi1_ipg		178
-	ssi2_ipg		179
-	ssi3_ipg		180
-	rom			181
-	usbphy1			182
-	usbphy2			183
-	ldb_di0_div_3_5		184
-	ldb_di1_div_3_5		185
-	sata_ref		186
-	sata_ref_100m		187
-	pcie_ref		188
-	pcie_ref_125m		189
-	enet_ref		190
-	usbphy1_gate		191
-	usbphy2_gate		192
-	pll4_post_div		193
-	pll5_post_div		194
-	pll5_video_div		195
-	eim_slow      		196
-	spdif      		197
-	cko2_sel      		198
-	cko2_podf      		199
-	cko2      		200
-	cko      		201
-	vdoa      		202
-	pll4_audio_div		203
-	lvds1_sel		204
-	lvds2_sel		205
-	lvds1_gate		206
-	lvds2_gate		207
-	esai_ahb		208
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx6qdl-clock.h
+for the full list of i.MX6 Quad and DualLite clock IDs.
 
 Examples:
 
+#include <dt-bindings/clock/imx6qdl-clock.h>
+
 clks: ccm@020c4000 {
 	compatible = "fsl,imx6q-ccm";
 	reg = <0x020c4000 0x4000>;
@@ -235,7 +25,7 @@ uart1: serial@02020000 {
 	compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 	reg = <0x02020000 0x4000>;
 	interrupts = <0 26 0x04>;
-	clocks = <&clks 160>, <&clks 161>;
+	clocks = <&clks IMX6QDL_CLK_UART_IPG>, <&clks IMX6QDL_CLK_UART_SERIAL>;
 	clock-names = "ipg", "per";
 	status = "disabled";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,14 +3,15 @@ Device Tree Clock bindings for cpu clock
 Required properties:
 - compatible : shall be one of the following:
 	"marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP
-- reg : Address and length of the clock complex register set
+- reg : Address and length of the clock complex register set, followed
+        by address and length of the PMU DFS registers
 - #clock-cells : should be set to 1.
 - clocks : shall be the input parent clock phandle for the clock.
 
 cpuclk: clock-complex@d0018700 {
 	#clock-cells = <1>;
 	compatible = "marvell,armada-xp-cpu-clock";
-	reg = <0xd0018700 0xA0>;
+	reg = <0xd0018700 0xA0>, <0x1c054 0x10>;
 	clocks = <&coreclk 1>;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,8 @@ Required properties :
 - compatible : shall contain only one of the following:
 
 			"qcom,gcc-apq8064"
+			"qcom,gcc-apq8084"
+			"qcom,gcc-ipq8064"
 			"qcom,gcc-msm8660"
 			"qcom,gcc-msm8960"
 			"qcom,gcc-msm8974"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/qcom,mmcc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/qcom,mmcc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/qcom,mmcc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,8 @@ Qualcomm Multimedia Clock & Reset Contro
 Required properties :
 - compatible : shall contain only one of the following:
 
+			"qcom,mmcc-apq8064"
+			"qcom,mmcc-apq8084"
 			"qcom,mmcc-msm8660"
 			"qcom,mmcc-msm8960"
 			"qcom,mmcc-msm8974"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+* Rockchip RK3188/RK3066 Clock and Reset Unit
+
+The RK3188/RK3066 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,rk3188-cru", "rockchip,rk3188a-cru" or
+			"rockchip,rk3066a-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 changable, 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/rk3188-cru.h and
+dt-bindings/clock/rk3066-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,
+ - "xin32k" - rtc clock - optional,
+ - "xin27m" - 27mhz crystal input on rk3066 - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_cif0" - external camera clock - optional,
+ - "ext_rmii" - external RMII clock - optional,
+ - "ext_jtag" - externalJTAG clock - optional
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3188-cru";
+		reg = <0x20000000 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@10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clocks = <&cru SCLK_UART0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+* Rockchip RK3288 Clock and Reset Unit
+
+The RK3288 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,rk3288-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 changable, 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/rk3288-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,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_edp_24m" - external display port clock - optional,
+ - "ext_vip" - external VIP clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3188-cru";
+		reg = <0x20000000 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@10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clocks = <&cru SCLK_UART0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/rockchip.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/rockchip.txt	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,9 @@ This binding uses the common clock bindi
 
 == Gate clocks ==
 
+These bindings are deprecated!
+Please use the soc specific CRU bindings instead.
+
 The gate registers form a continuos block which makes the dt node
 structure a matter of taste, as either all gates can be put into
 one gate clock spanning all registers or they can be divided into
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,78 @@
+* Samsung S5P6442/S5PC110/S5PV210 Clock Controller
+
+Samsung S5P6442, S5PC110 and S5PV210 SoCs contain integrated clock
+controller, which generates and supplies clock to various controllers
+within the SoC.
+
+Required Properties:
+
+- compatible: should be one of following:
+	- "samsung,s5pv210-clock" : for clock controller of Samsung
+	  S5PC110/S5PV210 SoCs,
+	- "samsung,s5p6442-clock" : for clock controller of Samsung
+	  S5P6442 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s5pv210.h header and can be used in device tree sources.
+
+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:
+ - "xxti": external crystal oscillator connected to XXTI and XXTO pins of
+the SoC,
+ - "xusbxti": external crystal oscillator connected to XUSBXTI and XUSBXTO
+pins of the SoC,
+
+A subset of above clocks available on given board shall be specified in
+board device tree, including the system base clock, as selected by XOM[0]
+pin of the SoC. Refer to generic fixed rate clock bindings
+documentation[1] for more information how to specify these clocks.
+
+[1] Documentation/devicetree/bindings/clock/fixed-clock.txt
+
+Example: Clock controller node:
+
+	clock: clock-controller@7e00f000 {
+		compatible = "samsung,s5pv210-clock";
+		reg = <0x7e00f000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+Example: Required external clocks:
+
+	xxti: clock-xxti {
+		compatible = "fixed-clock";
+		clock-output-names = "xxti";
+		clock-frequency = <24000000>;
+		#clock-cells = <0>;
+	};
+
+	xusbxti: clock-xusbxti {
+		compatible = "fixed-clock";
+		clock-output-names = "xusbxti";
+		clock-frequency = <24000000>;
+		#clock-cells = <0>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller (refer to the standard clock bindings for information about
+  "clocks" and "clock-names" properties):
+
+	uart0: serial@e2900000 {
+		compatible = "samsung,s5pv210-uart";
+		reg = <0xe2900000 0x400>;
+		interrupt-parent = <&vic1>;
+		interrupts = <10>;
+		clock-names = "uart", "clk_uart_baud0",
+				"clk_uart_baud1";
+		clocks = <&clocks UART0>, <&clocks UART0>,
+				<&clocks SCLK_UART0>;
+		status = "disabled";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt	2014-09-28 17:29:07.000000000 -0400
@@ -24,26 +24,26 @@ Required properties:
 
 Example:
 
-	clockgenA@fd345000 {
+	clockgen-a@fd345000 {
 		reg = <0xfd345000 0xb50>;
 
-		CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+		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 */
+			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";
+			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";
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,7 @@ Required properties:
 	"st,stih416-clkgenf-vcc-sd",	"st,clkgen-mux"
 	"st,stih415-clkgen-a9-mux",	"st,clkgen-mux"
 	"st,stih416-clkgen-a9-mux",	"st,clkgen-mux"
-
+	"st,stih407-clkgen-a9-mux",	"st,clkgen-mux"
 
 - #clock-cells : from common clock binding; shall be set to 0.
 
@@ -27,10 +27,10 @@ Required properties:
 
 Example:
 
-	CLK_M_HVA: CLK_M_HVA {
+	clk_m_hva: clk-m-hva@fd690868 {
 		#clock-cells = <0>;
 		compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
 		reg = <0xfd690868 4>;
 
-		clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+		clocks = <&clockgen_f 1>, <&clk_m_a1_div0 3>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt	2014-09-28 17:29:07.000000000 -0400
@@ -19,11 +19,14 @@ Required properties:
 	"st,stih415-plls-c32-ddr",	"st,clkgen-plls-c32"
 	"st,stih416-plls-c32-a9",	"st,clkgen-plls-c32"
 	"st,stih416-plls-c32-ddr",	"st,clkgen-plls-c32"
+	"st,stih407-plls-c32-a0",	"st,clkgen-plls-c32"
+	"st,stih407-plls-c32-a9",	"st,clkgen-plls-c32"
+	"st,stih407-plls-c32-c0_0",	"st,clkgen-plls-c32"
+	"st,stih407-plls-c32-c0_1",	"st,clkgen-plls-c32"
 
 	"st,stih415-gpu-pll-c32",	"st,clkgengpu-pll-c32"
 	"st,stih416-gpu-pll-c32",	"st,clkgengpu-pll-c32"
 
-
 - #clock-cells : From common clock binding; shall be set to 1.
 
 - clocks : From common clock binding
@@ -32,17 +35,17 @@ Required properties:
 
 Example:
 
-	clockgenA@fee62000 {
+	clockgen-a@fee62000 {
 		reg = <0xfee62000 0xb48>;
 
-		CLK_S_A0_PLL: CLK_S_A0_PLL {
+		clk_s_a0_pll: clk-s-a0-pll {
 			#clock-cells = <1>;
 			compatible = "st,clkgena-plls-c65";
 
-			clocks = <&CLK_SYSIN>;
+			clocks = <&clk_sysin>;
 
-			clock-output-names = "CLK_S_A0_PLL0_HS",
-					     "CLK_S_A0_PLL0_LS",
-					     "CLK_S_A0_PLL1";
+			clock-output-names = "clk-s-a0-pll0-hs",
+					     "clk-s-a0-pll0-ls",
+					     "clk-s-a0-pll1";
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt	2014-09-28 17:29:07.000000000 -0400
@@ -20,17 +20,17 @@ Required properties:
 
 Example:
 
-	clockgenA@fd345000 {
+	clockgen-a@fd345000 {
 		reg = <0xfd345000 0xb50>;
 
-		CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+		clk_m_a2_osc_prediv: clk-m-a2-osc-prediv {
 			#clock-cells = <0>;
 			compatible = "st,clkgena-prediv-c32",
 				     "st,clkgena-prediv";
 
-			clocks = <&CLK_SYSIN>;
+			clocks = <&clk_sysin>;
 
-			clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			clock-output-names = "clk-m-a2-osc-prediv";
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt	2014-09-28 17:29:07.000000000 -0400
@@ -24,60 +24,77 @@ address is common of all subnode.
 		quadfs_node {
 			...
 		};
+
+		mux_node {
+			...
+		};
+
+		vcc_node {
+			...
+		};
+
+		flexgen_node {
+			...
+		};
 		...
 	};
 
 This binding uses the common clock binding[1].
-Each subnode should use the binding discribe in [2]..[4]
+Each subnode should use the binding discribe in [2]..[7]
 
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/st,quadfs.txt
-[3] Documentation/devicetree/bindings/clock/st,quadfs.txt
-[4] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
+[3] Documentation/devicetree/bindings/clock/st,clkgen-mux.txt
+[4] Documentation/devicetree/bindings/clock/st,clkgen-pll.txt
+[5] Documentation/devicetree/bindings/clock/st,clkgen-prediv.txt
+[6] Documentation/devicetree/bindings/clock/st,vcc.txt
+[7] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[8] Documentation/devicetree/bindings/clock/st,flexgen.txt
+
 
 Required properties:
 - reg : A Base address and length of the register set.
 
 Example:
 
-	clockgenA@fee62000 {
+	clockgen-a@fee62000 {
 
 		reg = <0xfee62000 0xb48>;
 
-		CLK_S_A0_PLL: CLK_S_A0_PLL {
+		clk_s_a0_pll: clk-s-a0-pll {
 			#clock-cells = <1>;
 			compatible = "st,clkgena-plls-c65";
 
-			clocks = <&CLK_SYSIN>;
+			clocks = <&clk-sysin>;
 
-			clock-output-names = "CLK_S_A0_PLL0_HS",
-					     "CLK_S_A0_PLL0_LS",
-					     "CLK_S_A0_PLL1";
+			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 {
+		clk_s_a0_osc_prediv: clk-s-a0-osc-prediv {
 			#clock-cells = <0>;
 			compatible = "st,clkgena-prediv-c65",
 				     "st,clkgena-prediv";
 
-			clocks = <&CLK_SYSIN>;
+			clocks = <&clk_sysin>;
 
-			clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			clock-output-names = "clk-s-a0-osc-prediv";
 		};
 
-		CLK_S_A0_HS: CLK_S_A0_HS {
+		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 */
+			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 */
+			clock-output-names = "clk-s-fdma-0",
+					     "clk-s-fdma-1",
+					     ""; /* clk-s-jit-sense */
+					     /* fourth output unused */
 		};
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -32,22 +32,30 @@ Required properties:
 
 Example:
 
-	CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+	clockgen_c_vcc: clockgen-c-vcc@0xfe8308ac {
 		#clock-cells = <1>;
 		compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
 		reg = <0xfe8308ac 12>;
 
-		clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
-			<&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
+		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";
+		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";
 	};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,flexgen.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,flexgen.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,flexgen.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,119 @@
+Binding for a type of flexgen structure found on certain
+STMicroelectronics consumer electronics SoC devices
+
+This structure includes:
+- a clock cross bar (represented by a mux element)
+- a pre and final dividers (represented by a divider and gate elements)
+
+Flexgen structure is a part of Clockgen[1].
+
+Please find an example below:
+
+    Clockgen block diagram
+    -------------------------------------------------------------------
+   |                     Flexgen stucture                              |
+   |                  ---------------------------------------------    |
+   |                 |    -------       --------       --------    |   |
+clk_sysin            |   |       |     |        |     |        |   |   |
+---|-----------------|-->|       |     |        |     |        |   |   |
+   | |               |   |       |     |        |     |        |   |   |
+   | |   -------     |   |       |     |Pre     |     |Final   |   |   |
+   | |  |PLL0   |    |   |       |     |Dividers|     |Dividers|   |   |
+   | |->|       |    |   |       |     |  x32   |     |  x32   |   |   |
+   | |  |  odf_0|----|-->|       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |   -------     |   |       |     |        |     |        |   |   |
+   | |               |   |       |     |        |     |        |   |   |
+   | |   -------     |   | Clock |     |        |     |        |   |   |
+   | |  |PLL1   |    |   |       |     |        |     |        |   |   |
+   | |->|       |    |   | Cross |     |        |     |        |   |   |
+   | |  |  odf_0|----|-->|       |     |        |     |        | CLK_DIV[31:0]
+   | |  |       |    |   | Bar   |====>|        |====>|        |===|=========>
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |  |       |    |   |       |     |        |     |        |   |   |
+   | |   -------     |   |       |     |        |     |        |   |   |
+   | |               |   |       |     |        |     |        |   |   |
+   | |   -------     |   |       |     |        |     |        |   |   |
+   | |  |QUADFS |    |   |       |     |        |     |        |   |   |
+   | |->|    ch0|----|-->|       |     |        |     |        |   |   |
+   |    |       |    |   |       |     |        |     |        |   |   |
+   |    |    ch1|----|-->|       |     |        |     |        |   |   |
+   |    |       |    |   |       |     |        |     |        |   |   |
+   |    |    ch2|----|-->|       |     | DIV    |     | DIV    |   |   |
+   |    |       |    |   |       |     |  1 to  |     |  1 to  |   |   |
+   |    |    ch3|----|-->|       |     |   1024 |     |     64 |   |   |
+   |     -------     |   |       |     |        |     |        |   |   |
+   |                 |    -------       --------       --------    |   |
+   |                   --------------------------------------------    |
+   |                                                                   |
+    -------------------------------------------------------------------
+
+This binding uses the common clock binding[2].
+
+[1] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be:
+  "st,flexgen"
+
+- #clock-cells : from common clock binding; shall be set to 1 (multiple clock
+  outputs).
+
+- clocks : must be set to the parent's phandle. it's could be output clocks of
+  a quadsfs or/and a pll or/and clk_sysin (up to 7 clocks)
+
+- clock-output-names : List of strings used to name the clock outputs.
+
+Example:
+
+	clk_s_c0_flexgen: clk-s-c0-flexgen {
+
+		#clock-cells = <1>;
+		compatible = "st,flexgen";
+
+		clocks = <&clk_s_c0_pll0 0>,
+			 <&clk_s_c0_pll1 0>,
+			 <&clk_s_c0_quadfs 0>,
+			 <&clk_s_c0_quadfs 1>,
+			 <&clk_s_c0_quadfs 2>,
+			 <&clk_s_c0_quadfs 3>,
+			 <&clk_sysin>;
+
+		clock-output-names = "clk-icn-gpu",
+				     "clk-fdma",
+				     "clk-nand",
+				     "clk-hva",
+				     "clk-proc-stfe",
+				     "clk-proc-tp",
+				     "clk-rx-icn-dmu",
+				     "clk-rx-icn-hva",
+				     "clk-icn-cpu",
+				     "clk-tx-icn-dmu",
+				     "clk-mmc-0",
+				     "clk-mmc-1",
+				     "clk-jpegdec",
+				     "clk-ext2fa9",
+				     "clk-ic-bdisp-0",
+				     "clk-ic-bdisp-1",
+				     "clk-pp-dmu",
+				     "clk-vid-dmu",
+				     "clk-dss-lpc",
+				     "clk-st231-aud-0",
+				     "clk-st231-gp-1",
+				     "clk-st231-dmu",
+				     "clk-icn-lmi",
+				     "clk-tx-icn-disp-1",
+				     "clk-icn-sbc",
+				     "clk-stfe-frc2",
+				     "clk-eth-phy",
+				     "clk-eth-ref-phyclk",
+				     "clk-flash-promip",
+				     "clk-main-disp",
+				     "clk-aux-disp",
+				     "clk-compo-dvp";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,quadfs.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/st/st,quadfs.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/st/st,quadfs.txt	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,9 @@ Required properties:
   "st,stih416-quadfs432",	"st,quadfs"
   "st,stih416-quadfs660-E",	"st,quadfs"
   "st,stih416-quadfs660-F",	"st,quadfs"
+  "st,stih407-quadfs660-C",	"st,quadfs"
+  "st,stih407-quadfs660-D",	"st,quadfs"
+
 
 - #clock-cells : from common clock binding; shall be set to 1.
 
@@ -32,14 +35,14 @@ Required properties:
 
 Example:
 
-	CLOCKGEN_E: CLOCKGEN_E {
+	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";
+                clocks = <&clk_sysin>;
+                clock-output-names = "clk-m-pix-mdtp-0",
+				     "clk-m-pix-mdtp-1",
+				     "clk-m-pix-mdtp-2",
+				     "clk-m-mpelpc";
         };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/sunxi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/sunxi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/clock/sunxi.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/clock/sunxi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,11 +9,13 @@ Required properties:
 	"allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
 	"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
 	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
+	"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
 	"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
 	"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
 	"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
 	"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
 	"allwinner,sun4i-a10-axi-clk" - for the AXI clock
+	"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
 	"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
 	"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
 	"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
@@ -23,13 +25,16 @@ Required properties:
 	"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
 	"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
 	"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
+	"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
 	"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
 	"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
+	"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
 	"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
 	"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
 	"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
 	"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
 	"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
+	"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
 	"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
 	"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
 	"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
@@ -37,8 +42,10 @@ Required properties:
 	"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
 	"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
 	"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
+	"allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23
 	"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
+	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/crypto/amd-ccp.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/crypto/amd-ccp.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/crypto/amd-ccp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/crypto/amd-ccp.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+* AMD Cryptographic Coprocessor driver (ccp)
+
+Required properties:
+- compatible: Should be "amd,ccp-seattle-v1a"
+- reg: Address and length of the register set for the device
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- interrupts: Should contain the CCP interrupt
+
+Optional properties:
+- dma-coherent: Present if dma operations are coherent
+
+Example:
+	ccp@e0100000 {
+		compatible = "amd,ccp-seattle-v1a";
+		reg = <0 0xe0100000 0 0x10000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 3 4>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/crypto/qcom-qce.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/crypto/qcom-qce.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/crypto/qcom-qce.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/crypto/qcom-qce.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,25 @@
+Qualcomm crypto engine driver
+
+Required properties:
+
+- compatible  : should be "qcom,crypto-v5.1"
+- reg         : specifies base physical address and size of the registers map
+- clocks      : phandle to clock-controller plus clock-specifier pair
+- clock-names : "iface" clocks register interface
+                "bus" clocks data transfer interface
+                "core" clocks rest of the crypto block
+- dmas        : DMA specifiers for tx and rx dma channels. For more see
+                Documentation/devicetree/bindings/dma/dma.txt
+- dma-names   : DMA request names should be "rx" and "tx"
+
+Example:
+	crypto@fd45a000 {
+		compatible = "qcom,crypto-v5.1";
+		reg = <0xfd45a000 0x6000>;
+		clocks = <&gcc GCC_CE2_AHB_CLK>,
+			 <&gcc GCC_CE2_AXI_CLK>,
+			 <&gcc GCC_CE2_CLK>;
+		clock-names = "iface", "bus", "core";
+		dmas = <&cryptobam 2>, <&cryptobam 3>;
+		dma-names = "rx", "tx";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt	2014-08-07 04:47:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt	2014-09-28 21:27:51.000000000 -0400
@@ -47,6 +47,7 @@ The full ID of peripheral types can be f
 	20	ASRC
 	21	ESAI
 	22	SSI Dual FIFO	(needs firmware ver >= 2)
+	23	Shared ASRC
 
 The third cell specifies the transfer priority as below.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/mpc512x-dma.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/mpc512x-dma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/mpc512x-dma.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+* Freescale MPC512x and MPC8308 DMA Controller
+
+The DMA controller in Freescale MPC512x and MPC8308 SoCs can move
+blocks of memory contents between memory and peripherals or
+from memory to memory.
+
+Refer to "Generic DMA Controller and DMA request bindings" in
+the dma/dma.txt file for a more detailed description of binding.
+
+Required properties:
+- compatible: should be "fsl,mpc5121-dma" or "fsl,mpc8308-dma";
+- reg: should contain the DMA controller registers location and length;
+- interrupt for the DMA controller: syntax of interrupt client node
+	is described in interrupt-controller/interrupts.txt file.
+- #dma-cells: the length of the DMA specifier, must be <1>.
+	Each channel of this DMA controller has a peripheral request line,
+	the assignment is fixed in hardware. This one cell
+	in dmas property of a client device represents the channel number.
+
+Example:
+
+	dma0: dma@14000 {
+		compatible = "fsl,mpc5121-dma";
+		reg = <0x14000 0x1800>;
+		interrupts = <65 0x8>;
+		#dma-cells = <1>;
+	};
+
+DMA clients must use the format described in dma/dma.txt file.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+* Renesas "Type-AXI" NBPFAXI* DMA controllers
+
+* DMA controller
+
+Required properties
+
+- compatible:	must be one of
+		"renesas,nbpfaxi64dmac1b4"
+		"renesas,nbpfaxi64dmac1b8"
+		"renesas,nbpfaxi64dmac1b16"
+		"renesas,nbpfaxi64dmac4b4"
+		"renesas,nbpfaxi64dmac4b8"
+		"renesas,nbpfaxi64dmac4b16"
+		"renesas,nbpfaxi64dmac8b4"
+		"renesas,nbpfaxi64dmac8b8"
+		"renesas,nbpfaxi64dmac8b16"
+- #dma-cells:	must be 2: the first integer is a terminal number, to which this
+		slave is connected, the second one is flags. Flags is a bitmask
+		with the following bits defined:
+
+#define NBPF_SLAVE_RQ_HIGH	1
+#define NBPF_SLAVE_RQ_LOW	2
+#define NBPF_SLAVE_RQ_LEVEL	4
+
+Optional properties:
+
+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.
+
+Example:
+
+	dma: dma-controller@48000000 {
+		compatible = "renesas,nbpfaxi64dmac8b4";
+		reg = <0x48000000 0x400>;
+		interrupts = <0 12 0x4
+			      0 13 0x4
+			      0 14 0x4
+			      0 15 0x4
+			      0 16 0x4
+			      0 17 0x4
+			      0 18 0x4
+			      0 19 0x4>;
+		#dma-cells = <2>;
+		dma-channels = <8>;
+		dma-requests = <8>;
+	};
+
+* DMA client
+
+Required properties:
+
+dmas and dma-names are required, as described in dma.txt.
+
+Example:
+
+#include <dt-bindings/dma/nbpfaxi.h>
+
+...
+		dmas = <&dma 0 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)
+			&dma 1 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)>;
+		dma-names = "rx", "tx";
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/rcar-audmapp.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/rcar-audmapp.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/rcar-audmapp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/rcar-audmapp.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+* R-Car Audio DMAC peri peri Device Tree bindings
+
+Required properties:
+- compatible:	should be "renesas,rcar-audmapp"
+- #dma-cells:	should be <1>, see "dmas" property below
+
+Example:
+	audmapp: audio-dma-pp@0xec740000 {
+		compatible = "renesas,rcar-audmapp";
+		#dma-cells = <1>;
+
+		reg = <0 0xec740000 0 0x200>;
+	};
+
+
+* DMA client
+
+Required properties:
+- dmas:		a list of <[DMA multiplexer phandle] [SRS << 8 | DRS]> pairs.
+		where SRS/DRS are specified in the SoC manual.
+		It will be written into PDMACHCR as high 16-bit parts.
+- dma-names:	a list of DMA channel names, one per "dmas" entry
+
+Example:
+
+	dmas = <&audmapp 0x2d00
+		&audmapp 0x3700>;
+	dma-names =  "src0_ssiu0",
+		     "dvc0_ssiu0";
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,98 @@
+* Renesas R-Car DMA Controller Device Tree bindings
+
+Renesas R-Car Generation 2 SoCs have have multiple multi-channel DMA
+controller instances named DMAC capable of serving multiple clients. Channels
+can be dedicated to specific clients or shared between a large number of
+clients.
+
+DMA clients are connected to the DMAC ports referenced by an 8-bit identifier
+called MID/RID.
+
+Each DMA client is connected to one dedicated port of the DMAC, identified by
+an 8-bit port number called the MID/RID. A DMA controller can thus serve up to
+256 clients in total. When the number of hardware channels is lower than the
+number of clients to be served, channels must be shared between multiple DMA
+clients. The association of DMA clients to DMAC channels is fully dynamic and
+not described in these device tree bindings.
+
+Required Properties:
+
+- compatible: must contain "renesas,rcar-dmac"
+
+- reg: base address and length of the registers block for the DMAC
+
+- interrupts: interrupt specifiers for the DMAC, one for each entry in
+  interrupt-names.
+- interrupt-names: one entry per channel, named "ch%u", where %u is the
+  channel number ranging from zero to the number of channels minus one.
+
+- clock-names: "fck" for the functional clock
+- clocks: a list of phandle + clock-specifier pairs, one for each entry
+  in clock-names.
+- clock-names: must contain "fck" for the functional clock.
+
+- #dma-cells: must be <1>, the cell specifies the MID/RID of the DMAC port
+  connected to the DMA client
+- dma-channels: number of DMA channels
+
+Example: R8A7790 (R-Car H2) SYS-DMACs
+
+	dmac0: dma-controller@e6700000 {
+		compatible = "renesas,rcar-dmac";
+		reg = <0 0xe6700000 0 0x20000>;
+		interrupts = <0 197 IRQ_TYPE_LEVEL_HIGH
+			      0 200 IRQ_TYPE_LEVEL_HIGH
+			      0 201 IRQ_TYPE_LEVEL_HIGH
+			      0 202 IRQ_TYPE_LEVEL_HIGH
+			      0 203 IRQ_TYPE_LEVEL_HIGH
+			      0 204 IRQ_TYPE_LEVEL_HIGH
+			      0 205 IRQ_TYPE_LEVEL_HIGH
+			      0 206 IRQ_TYPE_LEVEL_HIGH
+			      0 207 IRQ_TYPE_LEVEL_HIGH
+			      0 208 IRQ_TYPE_LEVEL_HIGH
+			      0 209 IRQ_TYPE_LEVEL_HIGH
+			      0 210 IRQ_TYPE_LEVEL_HIGH
+			      0 211 IRQ_TYPE_LEVEL_HIGH
+			      0 212 IRQ_TYPE_LEVEL_HIGH
+			      0 213 IRQ_TYPE_LEVEL_HIGH
+			      0 214 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error",
+				"ch0", "ch1", "ch2", "ch3",
+				"ch4", "ch5", "ch6", "ch7",
+				"ch8", "ch9", "ch10", "ch11",
+				"ch12", "ch13", "ch14";
+		clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC0>;
+		clock-names = "fck";
+		#dma-cells = <1>;
+		dma-channels = <15>;
+	};
+
+	dmac1: dma-controller@e6720000 {
+		compatible = "renesas,rcar-dmac";
+		reg = <0 0xe6720000 0 0x20000>;
+		interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
+			      0 216 IRQ_TYPE_LEVEL_HIGH
+			      0 217 IRQ_TYPE_LEVEL_HIGH
+			      0 218 IRQ_TYPE_LEVEL_HIGH
+			      0 219 IRQ_TYPE_LEVEL_HIGH
+			      0 308 IRQ_TYPE_LEVEL_HIGH
+			      0 309 IRQ_TYPE_LEVEL_HIGH
+			      0 310 IRQ_TYPE_LEVEL_HIGH
+			      0 311 IRQ_TYPE_LEVEL_HIGH
+			      0 312 IRQ_TYPE_LEVEL_HIGH
+			      0 313 IRQ_TYPE_LEVEL_HIGH
+			      0 314 IRQ_TYPE_LEVEL_HIGH
+			      0 315 IRQ_TYPE_LEVEL_HIGH
+			      0 316 IRQ_TYPE_LEVEL_HIGH
+			      0 317 IRQ_TYPE_LEVEL_HIGH
+			      0 318 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error",
+				"ch0", "ch1", "ch2", "ch3",
+				"ch4", "ch5", "ch6", "ch7",
+				"ch8", "ch9", "ch10", "ch11",
+				"ch12", "ch13", "ch14";
+		clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC1>;
+		clock-names = "fck";
+		#dma-cells = <1>;
+		dma-channels = <15>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/ste-dma40.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/ste-dma40.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/ste-dma40.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/ste-dma40.txt	2014-09-28 17:29:07.000000000 -0400
@@ -35,9 +35,11 @@ Required properties:
 
 Each dmas request consists of 4 cells:
   1. A phandle pointing to the DMA controller
-  2. Device Type
+  2. Device signal number, the signal line for single and burst requests
+     connected from the device to the DMA40 engine
   3. The DMA request line number (only when 'use fixed channel' is set)
-  4. A 32bit mask specifying; mode, direction and endianness [NB: This list will grow]
+  4. A 32bit mask specifying; mode, direction and endianness
+     [NB: This list will grow]
         0x00000001: Mode:
                 Logical channel when unset
                 Physical channel when set
@@ -54,6 +56,74 @@ Each dmas request consists of 4 cells:
                 Normal priority when unset
                 High priority when set
 
+Existing signal numbers for the DB8500 ASIC. Unless specified, the signals are
+bidirectional, i.e. the same for RX and TX operations:
+
+0:  SPI controller 0
+1:  SD/MMC controller 0 (unused)
+2:  SD/MMC controller 1 (unused)
+3:  SD/MMC controller 2 (unused)
+4:  I2C port 1
+5:  I2C port 3
+6:  I2C port 2
+7:  I2C port 4
+8:  Synchronous Serial Port SSP0
+9:  Synchronous Serial Port SSP1
+10: Multi-Channel Display Engine MCDE RX
+11: UART port 2
+12: UART port 1
+13: UART port 0
+14: Multirate Serial Port MSP2
+15: I2C port 0
+16: USB OTG in/out endpoints 7 & 15
+17: USB OTG in/out endpoints 6 & 14
+18: USB OTG in/out endpoints 5 & 13
+19: USB OTG in/out endpoints 4 & 12
+20: SLIMbus or HSI channel 0
+21: SLIMbus or HSI channel 1
+22: SLIMbus or HSI channel 2
+23: SLIMbus or HSI channel 3
+24: Multimedia DSP SXA0
+25: Multimedia DSP SXA1
+26: Multimedia DSP SXA2
+27: Multimedia DSP SXA3
+28: SD/MM controller 2
+29: SD/MM controller 0
+30: MSP port 1 on DB8500 v1, MSP port 3 on DB8500 v2
+31: MSP port 0 or SLIMbus channel 0
+32: SD/MM controller 1
+33: SPI controller 2
+34: i2c3 RX2 TX2
+35: SPI controller 1
+36: USB OTG in/out endpoints 3 & 11
+37: USB OTG in/out endpoints 2 & 10
+38: USB OTG in/out endpoints 1 & 9
+39: USB OTG in/out endpoints 8
+40: SPI controller 3
+41: SD/MM controller 3
+42: SD/MM controller 4
+43: SD/MM controller 5
+44: Multimedia DSP SXA4
+45: Multimedia DSP SXA5
+46: SLIMbus channel 8 or Multimedia DSP SXA6
+47: SLIMbus channel 9 or Multimedia DSP SXA7
+48: Crypto Accelerator 1
+49: Crypto Accelerator 1 TX or Hash Accelerator 1 TX
+50: Hash Accelerator 1 TX
+51: memcpy TX (to be used by the DMA driver for memcpy operations)
+52: SLIMbus or HSI channel 4
+53: SLIMbus or HSI channel 5
+54: SLIMbus or HSI channel 6
+55: SLIMbus or HSI channel 7
+56: memcpy (to be used by the DMA driver for memcpy operations)
+57: memcpy (to be used by the DMA driver for memcpy operations)
+58: memcpy (to be used by the DMA driver for memcpy operations)
+59: memcpy (to be used by the DMA driver for memcpy operations)
+60: memcpy (to be used by the DMA driver for memcpy operations)
+61: Crypto Accelerator 0
+62: Crypto Accelerator 0 TX or Hash Accelerator 0 TX
+63: Hash Accelerator 0 TX
+
 Example:
 
 	uart@80120000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/sun6i-dma.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/sun6i-dma.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/dma/sun6i-dma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/dma/sun6i-dma.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,45 @@
+Allwinner A31 DMA Controller
+
+This driver follows the generic DMA bindings defined in dma.txt.
+
+Required properties:
+
+- compatible:	Must be "allwinner,sun6i-a31-dma"
+- reg:		Should contain the registers base address and length
+- interrupts:	Should contain a reference to the interrupt used by this device
+- clocks:	Should contain a reference to the parent AHB clock
+- resets:	Should contain a reference to the reset controller asserting
+		this device in reset
+- #dma-cells :	Should be 1, a single cell holding a line request number
+
+Example:
+	dma: dma-controller@01c02000 {
+		compatible = "allwinner,sun6i-a31-dma";
+		reg = <0x01c02000 0x1000>;
+		interrupts = <0 50 4>;
+		clocks = <&ahb1_gates 6>;
+		resets = <&ahb1_rst 6>;
+		#dma-cells = <1>;
+	};
+
+Clients:
+
+DMA clients connected to the A31 DMA controller must use the format
+described in the dma.txt file, using a two-cell specifier for each
+channel: a phandle plus one integer cells.
+The two cells in order are:
+
+1. A phandle pointing to the DMA controller.
+2. The port ID as specified in the datasheet
+
+Example:
+spi2: spi@01c6a000 {
+	compatible = "allwinner,sun6i-a31-spi";
+	reg = <0x01c6a000 0x1000>;
+	interrupts = <0 67 4>;
+	clocks = <&ahb1_gates 22>, <&spi2_clk>;
+	clock-names = "ahb", "mod";
+	dmas = <&dma 25>, <&dma 25>;
+	dma-names = "rx", "tx";
+	resets = <&ahb1_rst 22>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+Device Tree bindings for Armada DRM CRTC driver
+
+Required properties:
+ - compatible: value should be "marvell,dove-lcd".
+ - reg: base address and size of the LCD controller
+ - interrupts: single interrupt number for the LCD controller
+ - port: video output port with endpoints, as described by graph.txt
+
+Optional properties:
+
+ - clocks: as described by clock-bindings.txt
+ - clock-names: as described by clock-bindings.txt
+	"axiclk" - axi bus clock for pixel clock
+	"plldivider" - pll divider clock for pixel clock
+	"ext_ref_clk0" - external clock 0 for pixel clock
+	"ext_ref_clk1" - external clock 1 for pixel clock
+
+Note: all clocks are optional but at least one must be specified.
+Further clocks may be added in the future according to requirements of
+different SoCs.
+
+Example:
+
+	lcd0: lcd-controller@820000 {
+		compatible = "marvell,dove-lcd";
+		reg = <0x820000 0x1000>;
+		interrupts = <47>;
+		clocks = <&si5351 0>;
+		clock-names = "ext_ref_clk_1";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/i2c/tda998x.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/i2c/tda998x.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/i2c/tda998x.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,8 @@ Device-Tree bindings for the NXP TDA998x
 Required properties;
   - compatible: must be "nxp,tda998x"
 
+  - reg: I2C address
+
 Optional properties:
   - interrupts: interrupt number and trigger type
 	default: polling
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/gpu.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/gpu.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/gpu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/gpu.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,52 @@
+Qualcomm adreno/snapdragon GPU
+
+Required properties:
+- compatible: "qcom,adreno-3xx"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt signal from the gpu.
+- clocks: device clocks
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+  * "core_clk"
+  * "iface_clk"
+  * "mem_iface_clk"
+- qcom,chipid: gpu chip-id.  Note this may become optional for future
+  devices if we can reliably read the chipid from hw
+- qcom,gpu-pwrlevels: list of operating points
+  - compatible: "qcom,gpu-pwrlevels"
+  - for each qcom,gpu-pwrlevel:
+    - qcom,gpu-freq: requested gpu clock speed
+    - NOTE: downstream android driver defines additional parameters to
+      configure memory bandwidth scaling per OPP.
+
+Example:
+
+/ {
+	...
+
+	gpu: qcom,kgsl-3d0@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_iface_clk";
+		clocks =
+		    <&mmcc GFX3D_CLK>,
+		    <&mmcc GFX3D_AHB_CLK>,
+		    <&mmcc MMSS_IMEM_AHB_CLK>;
+		qcom,chipid = <0x03020100>;
+		qcom,gpu-pwrlevels {
+			compatible = "qcom,gpu-pwrlevels";
+			qcom,gpu-pwrlevel@0 {
+				qcom,gpu-freq = <450000000>;
+			};
+			qcom,gpu-pwrlevel@1 {
+				qcom,gpu-freq = <27000000>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/hdmi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/hdmi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/hdmi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/hdmi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,46 @@
+Qualcomm adreno/snapdragon hdmi output
+
+Required properties:
+- compatible: one of the following
+   * "qcom,hdmi-tx-8660"
+   * "qcom,hdmi-tx-8960"
+- reg: Physical base address and length of the controller's registers
+- reg-names: "core_physical"
+- interrupts: The interrupt signal from the hdmi block.
+- clocks: device clocks
+  See ../clocks/clock-bindings.txt for details.
+- qcom,hdmi-tx-ddc-clk-gpio: ddc clk pin
+- qcom,hdmi-tx-ddc-data-gpio: ddc data pin
+- qcom,hdmi-tx-hpd-gpio: hpd pin
+- core-vdda-supply: phandle to supply regulator
+- hdmi-mux-supply: phandle to mux regulator
+
+Optional properties:
+- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin
+- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin
+
+Example:
+
+/ {
+	...
+
+	hdmi: qcom,hdmi-tx-8960@4a00000 {
+		compatible = "qcom,hdmi-tx-8960";
+		reg-names = "core_physical";
+		reg = <0x04a00000 0x1000>;
+		interrupts = <GIC_SPI 79 0>;
+		clock-names =
+		    "core_clk",
+		    "master_iface_clk",
+		    "slave_iface_clk";
+		clocks =
+		    <&mmcc HDMI_APP_CLK>,
+		    <&mmcc HDMI_M_AHB_CLK>,
+		    <&mmcc HDMI_S_AHB_CLK>;
+		qcom,hdmi-tx-ddc-clk = <&msmgpio 70 GPIO_ACTIVE_HIGH>;
+		qcom,hdmi-tx-ddc-data = <&msmgpio 71 GPIO_ACTIVE_HIGH>;
+		qcom,hdmi-tx-hpd = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
+		core-vdda-supply = <&pm8921_hdmi_mvs>;
+		hdmi-mux-supply = <&ext_3p3v>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/mdp.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/mdp.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/drm/msm/mdp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/drm/msm/mdp.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,48 @@
+Qualcomm adreno/snapdragon display controller
+
+Required properties:
+- compatible:
+  * "qcom,mdp" - mdp4
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt signal from the display controller.
+- connectors: array of phandles for output device(s)
+- clocks: device clocks
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+  * "core_clk"
+  * "iface_clk"
+  * "lut_clk"
+  * "src_clk"
+  * "hdmi_clk"
+  * "mpd_clk"
+
+Optional properties:
+- gpus: phandle for gpu device
+
+Example:
+
+/ {
+	...
+
+	mdp: qcom,mdp@5100000 {
+		compatible = "qcom,mdp";
+		reg = <0x05100000 0xf0000>;
+		interrupts = <GIC_SPI 75 0>;
+		connectors = <&hdmi>;
+		gpus = <&gpu>;
+		clock-names =
+		    "core_clk",
+		    "iface_clk",
+		    "lut_clk",
+		    "src_clk",
+		    "hdmi_clk",
+		    "mdp_clk";
+		clocks =
+		    <&mmcc MDP_SRC>,
+		    <&mmcc MDP_AHB_CLK>,
+		    <&mmcc MDP_LUT_CLK>,
+		    <&mmcc TV_SRC>,
+		    <&mmcc HDMI_TV_CLK>,
+		    <&mmcc MDP_TV_CLK>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+
+* SM5502 MUIC (Micro-USB Interface Controller) device
+
+The Silicon Mitus SM5502 is a MUIC (Micro-USB Interface Controller) device
+which can detect the state of external accessory when external accessory is
+attached or detached and button is pressed or released. It is interfaced to
+the host controller using an I2C interface.
+
+Required properties:
+- compatible: Should be "siliconmitus,sm5502-muic"
+- reg: Specifies the I2C slave address of the MUIC block. It should be 0x25
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from sm5502 are delivered to.
+- interrupts: Interrupt specifiers for detection interrupt sources.
+
+Example:
+
+	sm5502@25 {
+		compatible = "siliconmitus,sm5502-muic";
+		interrupt-parent = <&gpx1>;
+		interrupts = <5 0>;
+		reg = <0x25>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,40 @@
+NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 fuse block.
+
+Required properties:
+- compatible : should be:
+	"nvidia,tegra20-efuse"
+	"nvidia,tegra30-efuse"
+	"nvidia,tegra114-efuse"
+	"nvidia,tegra124-efuse"
+  Details:
+  nvidia,tegra20-efuse: Tegra20 requires using APB DMA to read the fuse data
+	due to a hardware bug. Tegra20 also lacks certain information which is
+	available in later generations such as fab code, lot code, wafer id,..
+  nvidia,tegra30-efuse, nvidia,tegra114-efuse and nvidia,tegra124-efuse:
+	The differences between these SoCs are the size of the efuse array,
+	the location of the spare (OEM programmable) bits and the location of
+	the speedo data.
+- reg: Should contain 1 entry: the entry gives the physical address and length
+       of the fuse registers.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - fuse
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+ - fuse
+
+Example:
+
+	fuse@7000f800 {
+		compatible = "nvidia,tegra20-efuse";
+		reg = <0x7000F800 0x400>,
+		      <0x70000000 0x400>;
+		clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+		clock-names = "fuse";
+		resets = <&tegra_car 39>;
+		reset-names = "fuse";
+	};
+
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpio/gpio-zynq.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpio/gpio-zynq.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpio/gpio-zynq.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpio/gpio-zynq.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+Xilinx Zynq GPIO controller Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- #gpio-cells 		: Should be two
+			  - First cell is the GPIO line number
+			  - Second cell is used to specify optional
+			    parameters (unused)
+- compatible		: Should be "xlnx,zynq-gpio-1.0"
+- clocks		: Clock specifier (see clock bindings for details)
+- gpio-controller	: Marks the device node as a GPIO controller.
+- interrupts		: Interrupt specifier (see interrupt bindings for
+			  details)
+- interrupt-parent	: Must be core interrupt controller
+- reg			: Address and length of the register set for the device
+
+Example:
+	gpio@e000a000 {
+		#gpio-cells = <2>;
+		compatible = "xlnx,zynq-gpio-1.0";
+		clocks = <&clkc 42>;
+		gpio-controller;
+		interrupt-parent = <&intc>;
+		interrupts = <0 20 4>;
+		reg = <0xe000a000 0x1000>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+NVIDIA GK20A Graphics Processing Unit
+
+Required properties:
+- compatible: "nvidia,<chip>-<gpu>"
+  Currently recognized values:
+  - nvidia,tegra124-gk20a
+- reg: Physical base address and length of the controller's registers.
+  Must contain two entries:
+  - first entry for bar0
+  - second entry for bar1
+- interrupts: Must contain an entry for each entry in interrupt-names.
+  See ../interrupt-controller/interrupts.txt for details.
+- interrupt-names: Must include the following entries:
+  - stall
+  - nonstall
+- vdd-supply: regulator for supply voltage.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - gpu
+  - pwr
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - gpu
+
+Example:
+
+	gpu@0,57000000 {
+		compatible = "nvidia,gk20a";
+		reg = <0x0 0x57000000 0x0 0x01000000>,
+		      <0x0 0x58000000 0x0 0x01000000>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "stall", "nonstall";
+		vdd-supply = <&vdd_gpu>;
+		clocks = <&tegra_car TEGRA124_CLK_GPU>,
+			 <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
+		clock-names = "gpu", "pwr";
+		resets = <&tegra_car 184>;
+		reset-names = "gpu";
+		status = "disabled";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpu/st,stih4xx.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/gpu/st,stih4xx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/gpu/st,stih4xx.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,189 @@
+STMicroelectronics stih4xx platforms
+
+- sti-vtg: video timing generator
+  Required properties:
+  - compatible: "st,vtg"
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  Optional properties:
+  - interrupts : VTG interrupt number to the CPU.
+  - st,slave: phandle on a slave vtg
+
+- sti-vtac: video timing advanced inter dye communication Rx and TX
+  Required properties:
+  - compatible: "st,vtac-main" or "st,vtac-aux"
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  - clocks: from common clock binding: handle hardware IP needed clocks, the
+    number of clocks may depend of the SoC type.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: names of the clocks listed in clocks property in the same
+    order.
+
+- sti-display-subsystem: Master device for DRM sub-components
+  This device must be the parent of all the sub-components and is responsible
+  of bind them.
+  Required properties:
+  - compatible: "st,sti-display-subsystem"
+  - ranges: to allow probing of subdevices
+
+- sti-compositor: frame compositor engine
+  must be a child of sti-display-subsystem
+  Required properties:
+  - compatible: "st,stih<chip>-compositor"
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  - clocks: from common clock binding: handle hardware IP needed clocks, the
+    number of clocks may depend of the SoC type.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: names of the clocks listed in clocks property in the same
+    order.
+  - resets: resets to be used by the device
+    See ../reset/reset.txt for details.
+  - reset-names: names of the resets listed in resets property in the same
+    order.
+  - st,vtg: phandle(s) on vtg device (main and aux) nodes.
+
+- sti-tvout: video out hardware block
+  must be a child of sti-display-subsystem
+  Required properties:
+  - compatible: "st,stih<chip>-tvout"
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  - reg-names: names of the mapped memory regions listed in regs property in
+    the same order.
+  - resets: resets to be used by the device
+    See ../reset/reset.txt for details.
+  - reset-names: names of the resets listed in resets property in the same
+    order.
+  - ranges: to allow probing of subdevices
+
+- sti-hdmi: hdmi output block
+  must be a child of sti-tvout
+  Required properties:
+  - compatible: "st,stih<chip>-hdmi";
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  - reg-names: names of the mapped memory regions listed in regs property in
+    the same order.
+  - interrupts : HDMI interrupt number to the CPU.
+  - interrupt-names: name of the interrupts listed in interrupts property in
+    the same order
+  - clocks: from common clock binding: handle hardware IP needed clocks, the
+    number of clocks may depend of the SoC type.
+  - clock-names: names of the clocks listed in clocks property in the same
+    order.
+  - hdmi,hpd-gpio: gpio id to detect if an hdmi cable is plugged or not.
+
+sti-hda:
+  Required properties:
+  must be a child of sti-tvout
+  - compatible: "st,stih<chip>-hda"
+  - reg: Physical base address of the IP registers and length of memory mapped region.
+  - reg-names: names of the mapped memory regions listed in regs property in
+    the same order.
+  - clocks: from common clock binding: handle hardware IP needed clocks, the
+    number of clocks may depend of the SoC type.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: names of the clocks listed in clocks property in the same
+    order.
+
+Example:
+
+/ {
+	...
+
+	vtg_main_slave: sti-vtg-main-slave@fe85A800 {
+		compatible	= "st,vtg";
+		reg		= <0xfe85A800 0x300>;
+		interrupts	= <GIC_SPI 175 IRQ_TYPE_NONE>;
+	};
+
+	vtg_main: sti-vtg-main-master@fd348000 {
+		compatible	= "st,vtg";
+		reg		= <0xfd348000 0x400>;
+		st,slave	= <&vtg_main_slave>;
+	};
+
+	vtg_aux_slave: sti-vtg-aux-slave@fd348400 {
+		compatible	= "st,vtg";
+		reg		= <0xfe858200 0x300>;
+		interrupts	= <GIC_SPI 176 IRQ_TYPE_NONE>;
+	};
+
+	vtg_aux: sti-vtg-aux-master@fd348400 {
+		compatible	= "st,vtg";
+		reg		= <0xfd348400 0x400>;
+		st,slave	= <&vtg_aux_slave>;
+	};
+
+
+	sti-vtac-rx-main@fee82800 {
+		compatible	= "st,vtac-main";
+		reg		= <0xfee82800 0x200>;
+		clock-names     = "vtac";
+		clocks          = <&clk_m_a2_div0 CLK_M_VTAC_MAIN_PHY>;
+	};
+
+	sti-vtac-rx-aux@fee82a00 {
+		compatible	= "st,vtac-aux";
+		reg		= <0xfee82a00 0x200>;
+		clock-names     = "vtac";
+		clocks          = <&clk_m_a2_div0 CLK_M_VTAC_AUX_PHY>;
+	};
+
+	sti-vtac-tx-main@fd349000 {
+		compatible	= "st,vtac-main";
+		reg		= <0xfd349000 0x200>, <0xfd320000 0x10000>;
+		clock-names     = "vtac";
+		clocks           = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
+	};
+
+	sti-vtac-tx-aux@fd349200 {
+		compatible	= "st,vtac-aux";
+		reg		= <0xfd349200 0x200>, <0xfd320000 0x10000>;
+		clock-names     = "vtac";
+		clocks          = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
+	};
+
+	sti-display-subsystem {
+		compatible = "st,sti-display-subsystem";
+		ranges;
+
+		sti-compositor@fd340000 {
+			compatible	= "st,stih416-compositor";
+			reg		= <0xfd340000 0x1000>;
+			clock-names	= "compo_main", "compo_aux",
+			                  "pix_main", "pix_aux";
+			clocks          = <&clk_m_a2_div1 CLK_M_COMPO_MAIN>, <&clk_m_a2_div1 CLK_M_COMPO_AUX>,
+					  <&clockgen_c_vcc CLK_S_PIX_MAIN>, <&clockgen_c_vcc CLK_S_PIX_AUX>;
+			reset-names     = "compo-main", "compo-aux";
+			resets          = <&softreset STIH416_COMPO_M_SOFTRESET>, <&softreset STIH416_COMPO_A_SOFTRESET>;
+			st,vtg		= <&vtg_main>, <&vtg_aux>;
+		};
+
+		sti-tvout@fe000000 {
+			compatible	= "st,stih416-tvout";
+			reg		= <0xfe000000 0x1000>, <0xfe85a000 0x400>, <0xfe830000 0x10000>;
+			reg-names	= "tvout-reg", "hda-reg", "syscfg";
+			reset-names     = "tvout";
+			resets          = <&softreset STIH416_HDTVOUT_SOFTRESET>;
+			ranges;
+
+			sti-hdmi@fe85c000 {
+				compatible	= "st,stih416-hdmi";
+				reg		= <0xfe85c000 0x1000>, <0xfe830000 0x10000>;
+				reg-names	= "hdmi-reg", "syscfg";
+				interrupts	= <GIC_SPI 173 IRQ_TYPE_NONE>;
+				interrupt-names	= "irq";
+				clock-names	= "pix", "tmds", "phy", "audio";
+				clocks          = <&clockgen_c_vcc CLK_S_PIX_HDMI>, <&clockgen_c_vcc CLK_S_TMDS_HDMI>, <&clockgen_c_vcc CLK_S_HDMI_REJECT_PLL>, <&clockgen_b1 CLK_S_PCM_0>;
+				hdmi,hpd-gpio	= <&PIO2 5>;
+			};
+
+			sti-hda@fe85a000 {
+				compatible	= "st,stih416-hda";
+				reg		= <0xfe85a000 0x400>, <0xfe83085c 0x4>;
+				reg-names	= "hda-reg", "video-dacs-ctrl";
+				clock-names	= "pix", "hddac";
+				clocks          = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
+			};
+		};
+	};
+	...
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+IBM POWERNV platform sensors
+----------------------------
+
+Required node properties:
+- compatible: must be one of
+		"ibm,opal-sensor-cooling-fan"
+		"ibm,opal-sensor-amb-temp"
+		"ibm,opal-sensor-power-supply"
+		"ibm,opal-sensor-power"
+- sensor-id: an opaque id provided by the firmware to the kernel, identifies a
+	     given sensor and its attribute data
+
+Example sensors node:
+
+cooling-fan#8-data {
+	sensor-id = <0x7052107>;
+	compatible = "ibm,opal-sensor-cooling-fan";
+};
+
+amb-temp#1-thrs {
+	sensor-id = <0x5096000>;
+	compatible = "ibm,opal-sensor-amb-temp";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@ NTC Thermistor hwmon sensors
 
 Requires node properties:
 - "compatible" value : one of
+	"epcos,b57330v2103"
 	"murata,ncp15wb473"
 	"murata,ncp18wb473"
 	"murata,ncp21wb473"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/pwm-fan.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/hwmon/pwm-fan.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/hwmon/pwm-fan.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,12 @@
+Bindings for a fan connected to the PWM lines
+
+Required properties:
+- compatible	: "pwm-fan"
+- pwms		: the PWM that is used to control the PWM fan
+
+Example:
+	pwm-fan {
+		compatible = "pwm-fan";
+		status = "okay";
+		pwms = <&pwm 0 10000 0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/i2c/i2c-efm32.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/i2c/i2c-efm32.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/i2c/i2c-efm32.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/i2c/i2c-efm32.txt	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@ Required properties :
 Recommended properties :
 
  - clock-frequency : maximal I2C bus clock frequency in Hz.
- - efm32,location : Decides the location of the USART I/O pins.
+ - energymicro,location : Decides the location of the USART I/O pins.
    Allowed range : [0 .. 6]
 
 Example:
@@ -23,7 +23,7 @@ Example:
 		clocks = <&cmu clk_HFPERCLKI2C0>;
 		clock-frequency = <100000>;
 		status = "ok";
-		efm32,location = <3>;
+		energymicro,location = <3>;
 
 		eeprom@50 {
 			compatible = "microchip,24c02";
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@ epson,rx8581		I2C-BUS INTERFACE REAL TIM
 fsl,mag3110		MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
 fsl,mc13892		MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
 fsl,mma8450		MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
+fsl,mma8452		MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer
 fsl,mpr121		MPR121: Proximity Capacitive Touch Sensor Controller
 fsl,sgtl5000		SGTL5000: Ultra Low-Power Audio Codec
 gmt,g751		G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
@@ -69,6 +70,7 @@ nuvoton,npct501		i2c trusted platform mo
 nxp,pca9556		Octal SMBus and I2C registered interface
 nxp,pca9557		8-bit I2C-bus and SMBus I/O port with reset
 nxp,pcf8563		Real-time clock/calendar
+nxp,pcf85063		Tiny Real-Time Clock
 ovti,ov5642		OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus
 pericom,pt7c4338	Real-time Clock Module
 plx,pex8648		48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
@@ -83,5 +85,6 @@ stm,m41t80		M41T80 - SERIAL ACCESS RTC W
 taos,tsl2550		Ambient Light Sensor with SMBUS/Two Wire Serial Interface
 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,wpct301		i2c trusted platform module (TPM)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+* Maxim 1027/1029/1031 Analog to Digital Converter (ADC)
+
+Required properties:
+  - compatible: Should be "maxim,max1027" or "maxim,max1029" or "maxim,max1031"
+  - reg: SPI chip select number for the device
+  - interrupt-parent: phandle to the parent interrupt controller
+  see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+  - interrupts: IRQ line for the ADC
+  see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+adc@0 {
+	compatible = "maxim,max1027";
+	reg = <0>;
+	interrupt-parent = <&gpio5>;
+	interrupts = <15 IRQ_TYPE_EDGE_RISING>;
+	spi-max-frequency = <1000000>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,10 @@
 Required properties:
 
   - compatible : should be "honeywell,hmc5843"
+  Other models which are supported with driver are:
+	"honeywell,hmc5883"
+	"honeywell,hmc5883l"
+	"honeywell,hmc5983"
   - reg : the I2C address of the magnetometer - typically 0x1e
 
 Optional properties:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,54 @@
+STMicroelectronics MEMS sensors
+
+The STMicroelectronics sensor devices are pretty straight-forward I2C or
+SPI devices, all sharing the same device tree descriptions no matter what
+type of sensor it is.
+
+Required properties:
+- compatible: see the list of valid compatible strings below
+- reg: the I2C or SPI address the device will respond to
+
+Optional properties:
+- vdd-supply: an optional regulator that needs to be on to provide VDD
+  power to the sensor.
+- vddio-supply: an optional regulator that needs to be on to provide the
+  VDD IO power to the sensor.
+- st,drdy-int-pin: the pin on the package that will be used to signal
+  "data ready" (valid values: 1 or 2). This property is not configurable
+  on all sensors.
+
+Sensors may also have applicable pin control settings, those use the
+standard bindings from pinctrl/pinctrl-bindings.txt.
+
+Valid compatible strings:
+
+Accelerometers:
+- st,lsm303dlh-accel
+- st,lsm303dlhc-accel
+- st,lis3dh-accel
+- st,lsm330d-accel
+- st,lsm330dl-accel
+- st,lsm330dlc-accel
+- st,lis331dlh-accel
+- st,lsm303dl-accel
+- st,lsm303dlm-accel
+- st,lsm330-accel
+
+Gyroscopes:
+- st,l3g4200d-gyro
+- st,lsm330d-gyro
+- st,lsm330dl-gyro
+- st,lsm330dlc-gyro
+- st,l3gd20-gyro
+- st,l3g4is-gyro
+- st,lsm330-gyro
+
+Magnetometers:
+- st,lsm303dlhc-magn
+- st,lsm303dlm-magn
+- st,lis3mdl-magn
+
+Pressure sensors:
+- st,lps001wp-press
+- st,lps25h-press
+- st,lps331ap-press
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/atmel,maxtouch.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/atmel,maxtouch.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/atmel,maxtouch.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,32 @@
+Atmel maXTouch touchscreen/touchpad
+
+Required properties:
+- compatible:
+    atmel,maxtouch
+
+- reg: The I2C address of the device
+
+- interrupts: The sink for the touchpad's IRQ output
+    See ../interrupt-controller/interrupts.txt
+
+Optional properties for main touchpad device:
+
+- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages
+    on GPIO bit changes. An array of up to 8 entries can be provided
+    indicating the Linux keycode mapped to each bit of the status byte,
+    starting at the LSB. Linux keycodes are defined in
+    <dt-bindings/input/input.h>.
+
+    Note: the numbering of the GPIOs and the bit they start at varies between
+    maXTouch devices. You must either refer to the documentation, or
+    experiment to determine which bit corresponds to which input. Use
+    KEY_RESERVED for unused padding values.
+
+Example:
+
+	touch@4b {
+		compatible = "atmel,maxtouch";
+		reg = <0x4b>;
+		interrupt-parent = <&gpio>;
+		interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_LOW>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/cap1106.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/cap1106.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/cap1106.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/cap1106.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,53 @@
+Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
+
+The node for this driver must be a child of a I2C controller node, as the
+device communication via I2C only.
+
+Required properties:
+
+	compatible:		Must be "microchip,cap1106"
+
+	reg:			The I2C slave address of the device.
+				Only 0x28 is valid.
+
+	interrupts:		Property describing the interrupt line the
+				device's ALERT#/CM_IRQ# pin is connected to.
+				The device only has one interrupt source.
+
+Optional properties:
+
+	autorepeat:		Enables the Linux input system's autorepeat
+				feature on the input device.
+
+	microchip,sensor-gain:	Defines the gain of the sensor circuitry. This
+				effectively controls the sensitivity, as a
+				smaller delta capacitance is required to
+				generate the same delta count values.
+				Valid values are 1, 2, 4, and 8.
+				By default, a gain of 1 is set.
+
+	linux,keycodes:		Specifies an array of numeric keycode values to
+				be used for the channels. If this property is
+				omitted, KEY_A, KEY_B, etc are used as
+				defaults. The array must have exactly six
+				entries.
+
+Example:
+
+i2c_controller {
+	cap1106@28 {
+		compatible = "microchip,cap1106";
+		interrupt-parent = <&gpio1>;
+		interrupts = <0 0>;
+		reg = <0x28>;
+		autorepeat;
+		microchip,sensor-gain = <2>;
+
+		linux,keycodes = <103		/* KEY_UP */
+				  106		/* KEY_RIGHT */
+				  108		/* KEY_DOWN */
+				  105		/* KEY_LEFT */
+				  109		/* KEY_PAGEDOWN */
+				  104>;		/* KEY_PAGEUP */
+	};
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+* Pixcir I2C touchscreen controllers
+
+Required properties:
+- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- attb-gpio: GPIO connected to the ATTB line of the chip
+- touchscreen-size-x: horizontal resolution of touchscreen (in pixels)
+- touchscreen-size-y: vertical resolution of touchscreen (in pixels)
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		pixcir_ts@5c {
+			compatible = "pixcir,pixcir_ts";
+			reg = <0x5c>;
+			interrupts = <2 0>;
+			attb-gpio = <&gpf 2 0 2>;
+			touchscreen-size-x = <800>;
+			touchscreen-size-y = <600>;
+		};
+
+		/* ... */
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,9 @@ Required properties:
 - x-size: horizontal resolution of touchscreen
 - y-size: vertical resolution of touchscreen
 
+Optional properties:
+- vdd-supply: Regulator controlling the controller supply
+
 Example:
 
 	i2c@00000000 {
@@ -18,6 +21,7 @@ Example:
 			compatible = "neonode,zforce";
 			reg = <0x50>;
 			interrupts = <2 0>;
+			vdd-supply = <&reg_zforce_vdd>;
 
 			gpios = <&gpio5 6 0>, /* INT */
 				<&gpio5 9 0>; /* RST */
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+* Advanced Interrupt Controller (AIC)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-aic"
+  <chip> can be "at91rm9200" or "sama5d3"
+- interrupt-controller: Identifies the node as an interrupt controller.
+- interrupt-parent: For single AIC system, it is an empty property.
+- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
+  The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+      Valid combinations are 1, 2, 3, 4, 8.
+      Default flag for internal sources should be set to 4 (active high).
+  The third cell is used to specify the irq priority from 0 (lowest) to 7
+  (highest).
+- reg: Should contain AIC registers location and length
+- atmel,external-irqs: u32 array of external irqs.
+
+Examples:
+	/*
+	 * AIC
+	 */
+	aic: interrupt-controller@fffff000 {
+		compatible = "atmel,at91rm9200-aic";
+		interrupt-controller;
+		interrupt-parent;
+		#interrupt-cells = <3>;
+		reg = <0xfffff000 0x200>;
+	};
+
+	/*
+	 * An interrupt generating device that is wired to an AIC.
+	 */
+	dma: dma-controller@ffffec00 {
+		compatible = "atmel,at91sam9g45-dma";
+		reg = <0xffffec00 0x200>;
+		interrupts = <21 4 5>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,11 +4,13 @@ Specifying interrupt information for dev
 1) Interrupt client nodes
 -------------------------
 
-Nodes that describe devices which generate interrupts must contain an either an
-"interrupts" property or an "interrupts-extended" property. These properties
-contain a list of interrupt specifiers, one per output interrupt. The format of
-the interrupt specifier is determined by the interrupt controller to which the
-interrupts are routed; see section 2 below for details.
+Nodes that describe devices which generate interrupts must contain an
+"interrupts" property, an "interrupts-extended" property, or both. If both are
+present, the latter should take precedence; the former may be provided simply
+for compatibility with software that does not recognize the latter. These
+properties contain a list of interrupt specifiers, one per output interrupt. The
+format of the interrupt specifier is determined by the interrupt controller to
+which the interrupts are routed; see section 2 below for details.
 
   Example:
 	interrupt-parent = <&intc1>;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+OpenRISC 1000 Programmable Interrupt Controller
+
+Required properties:
+
+- compatible : should be "opencores,or1k-pic-level" for variants with
+  level triggered interrupt lines, "opencores,or1k-pic-edge" for variants with
+  edge triggered interrupt lines or "opencores,or1200-pic" for machines
+  with the non-spec compliant or1200 type implementation.
+
+  "opencores,or1k-pic" is also provided as an alias to "opencores,or1200-pic",
+  but this is only for backwards compatibility.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "opencores,or1k-pic-level";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt	2014-09-28 17:29:07.000000000 -0400
@@ -42,12 +42,6 @@ conditions.
 
 ** System MMU optional properties:
 
-- smmu-parent   : When multiple SMMUs are chained together, this
-                  property can be used to provide a phandle to the
-                  parent SMMU (that is the next SMMU on the path going
-                  from the mmu-masters towards memory) node for this
-                  SMMU.
-
 - calxeda,smmu-secure-config-access : Enable proper handling of buggy
                   implementations that always use secure access to
                   SMMU configuration registers. In this case non-secure
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/iommu/iommu.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iommu/iommu.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/iommu/iommu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/iommu/iommu.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,182 @@
+This document describes the generic device tree binding for IOMMUs and their
+master(s).
+
+
+IOMMU device node:
+==================
+
+An IOMMU can provide the following services:
+
+* Remap address space to allow devices to access physical memory ranges that
+  they otherwise wouldn't be capable of accessing.
+
+  Example: 32-bit DMA to 64-bit physical addresses
+
+* Implement scatter-gather at page level granularity so that the device does
+  not have to.
+
+* Provide system protection against "rogue" DMA by forcing all accesses to go
+  through the IOMMU and faulting when encountering accesses to unmapped
+  address regions.
+
+* Provide address space isolation between multiple contexts.
+
+  Example: Virtualization
+
+Device nodes compatible with this binding represent hardware with some of the
+above capabilities.
+
+IOMMUs can be single-master or multiple-master. Single-master IOMMU devices
+typically have a fixed association to the master device, whereas multiple-
+master IOMMU devices can translate accesses from more than one master.
+
+The device tree node of the IOMMU device's parent bus must contain a valid
+"dma-ranges" property that describes how the physical address space of the
+IOMMU maps to memory. An empty "dma-ranges" property means that there is a
+1:1 mapping from IOMMU to memory.
+
+Required properties:
+--------------------
+- #iommu-cells: The number of cells in an IOMMU specifier needed to encode an
+  address.
+
+The meaning of the IOMMU specifier is defined by the device tree binding of
+the specific IOMMU. Below are a few examples of typical use-cases:
+
+- #iommu-cells = <0>: Single master IOMMU devices are not configurable and
+  therefore no additional information needs to be encoded in the specifier.
+  This may also apply to multiple master IOMMU devices that do not allow the
+  association of masters to be configured. Note that an IOMMU can by design
+  be multi-master yet only expose a single master in a given configuration.
+  In such cases the number of cells will usually be 1 as in the next case.
+- #iommu-cells = <1>: Multiple master IOMMU devices may need to be configured
+  in order to enable translation for a given master. In such cases the single
+  address cell corresponds to the master device's ID. In some cases more than
+  one cell can be required to represent a single master ID.
+- #iommu-cells = <4>: Some IOMMU devices allow the DMA window for masters to
+  be configured. The first cell of the address in this may contain the master
+  device's ID for example, while the second cell could contain the start of
+  the DMA window for the given device. The length of the DMA window is given
+  by the third and fourth cells.
+
+Note that these are merely examples and real-world use-cases may use different
+definitions to represent their individual needs. Always refer to the specific
+IOMMU binding for the exact meaning of the cells that make up the specifier.
+
+
+IOMMU master node:
+==================
+
+Devices that access memory through an IOMMU are called masters. A device can
+have multiple master interfaces (to one or more IOMMU devices).
+
+Required properties:
+--------------------
+- iommus: A list of phandle and IOMMU specifier pairs that describe the IOMMU
+  master interfaces of the device. One entry in the list describes one master
+  interface of the device.
+
+When an "iommus" property is specified in a device tree node, the IOMMU will
+be used for address translation. If a "dma-ranges" property exists in the
+device's parent node it will be ignored. An exception to this rule is if the
+referenced IOMMU is disabled, in which case the "dma-ranges" property of the
+parent shall take effect. Note that merely disabling a device tree node does
+not guarantee that the IOMMU is really disabled since the hardware may not
+have a means to turn off translation. But it is invalid in such cases to
+disable the IOMMU's device tree node in the first place because it would
+prevent any driver from properly setting up the translations.
+
+
+Notes:
+======
+
+One possible extension to the above is to use an "iommus" property along with
+a "dma-ranges" property in a bus device node (such as PCI host bridges). This
+can be useful to describe how children on the bus relate to the IOMMU if they
+are not explicitly listed in the device tree (e.g. PCI devices). However, the
+requirements of that use-case haven't been fully determined yet. Implementing
+this is therefore not recommended without further discussion and extension of
+this binding.
+
+
+Examples:
+=========
+
+Single-master IOMMU:
+--------------------
+
+	iommu {
+		#iommu-cells = <0>;
+	};
+
+	master {
+		iommus = <&{/iommu}>;
+	};
+
+Multiple-master IOMMU with fixed associations:
+----------------------------------------------
+
+	/* multiple-master IOMMU */
+	iommu {
+		/*
+		 * Masters are statically associated with this IOMMU and share
+		 * the same address translations because the IOMMU does not
+		 * have sufficient information to distinguish between masters.
+		 *
+		 * Consequently address translation is always on or off for
+		 * all masters at any given point in time.
+		 */
+		#iommu-cells = <0>;
+	};
+
+	/* static association with IOMMU */
+	master@1 {
+		reg = <1>;
+		iommus = <&{/iommu}>;
+	};
+
+	/* static association with IOMMU */
+	master@2 {
+		reg = <2>;
+		iommus = <&{/iommu}>;
+	};
+
+Multiple-master IOMMU:
+----------------------
+
+	iommu {
+		/* the specifier represents the ID of the master */
+		#iommu-cells = <1>;
+	};
+
+	master@1 {
+		/* device has master ID 42 in the IOMMU */
+		iommus = <&{/iommu} 42>;
+	};
+
+	master@2 {
+		/* device has master IDs 23 and 24 in the IOMMU */
+		iommus = <&{/iommu} 23>, <&{/iommu} 24>;
+	};
+
+Multiple-master IOMMU with configurable DMA window:
+---------------------------------------------------
+
+	/ {
+		iommu {
+			/*
+			 * One cell for the master ID and one cell for the
+			 * address of the DMA window. The length of the DMA
+			 * window is encoded in two cells.
+			 *
+			 * The DMA window is the range addressable by the
+			 * master (i.e. the I/O virtual address space).
+			 */
+			#iommu-cells = <4>;
+		};
+
+		master {
+			/* master ID 42, 4 GiB DMA window starting at 0 */
+			iommus = <&{/iommu}  42  0  0x1 0x0>;
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/leds/pca963x.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/leds/pca963x.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/leds/pca963x.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/leds/pca963x.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,18 +1,19 @@
 LEDs connected to pca9632, pca9633 or pca9634
 
 Required properties:
-- compatible : should be : "nxp,pca9632", "nxp,pca9633" or "nxp,pca9634"
+- compatible : should be : "nxp,pca9632", "nxp,pca9633", "nxp,pca9634" or "nxp,pca9635"
 
 Optional properties:
-- nxp,totem-pole : use totem pole (push-pull) instead of default open-drain
+- 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
 
 Each led is represented as a sub-node of the nxp,pca963x device.
 
 LED sub-node properties:
 - label : (optional) see Documentation/devicetree/bindings/leds/common.txt
-- reg : number of LED line (could be from 0 to 3  in pca9632 or pca9633
-		or 0 to 7 in pca9634)
+- reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633,
+		0 to 7 in pca9634, or 0 to 15 in pca9635)
 - linux,default-trigger : (optional)
    see Documentation/devicetree/bindings/leds/common.txt
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/leds/tca6507.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/leds/tca6507.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/leds/tca6507.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/leds/tca6507.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,7 @@ Required properties:
 
 Optional properties:
 - gpio-controller: allows lines to be used as output-only GPIOs.
-- #gpio-cells: if present, must be 0.
+- #gpio-cells: if present, must not be 0.
 
 Each led is represented as a sub-node of the ti,tca6507 device.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/atmel-isi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/atmel-isi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/atmel-isi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/atmel-isi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,51 @@
+Atmel Image Sensor Interface (ISI) SoC Camera Subsystem
+----------------------------------------------
+
+Required properties:
+- compatible: must be "atmel,at91sam9g45-isi"
+- reg: physical base address and length of the registers set for the device;
+- interrupts: should contain IRQ line for the ISI;
+- clocks: list of clock specifiers, corresponding to entries in
+          the clock-names property;
+- clock-names: must contain "isi_clk", which is the isi peripherial clock.
+
+ISI supports a single port node with parallel bus. It should contain one
+'port' child node with child 'endpoint' node. Please refer to the bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+	isi: isi@f0034000 {
+		compatible = "atmel,at91sam9g45-isi";
+		reg = <0xf0034000 0x4000>;
+		interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>;
+
+		clocks = <&isi_clk>;
+		clock-names = "isi_clk";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_isi>;
+
+		port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			isi_0: endpoint {
+				remote-endpoint = <&ov2640_0>;
+				bus-width = <8>;
+			};
+		};
+	};
+
+	i2c1: i2c@f0018000 {
+		ov2640: camera@0x30 {
+			compatible = "omnivision,ov2640";
+			reg = <0x30>;
+
+			port {
+				ov2640_0: endpoint {
+					remote-endpoint = <&isi_0>;
+					bus-width = <8>;
+				};
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,9 +3,13 @@ Samsung S5P/EXYNOS SoC series JPEG codec
 Required properties:
 
 - compatible	: should be one of:
-		  "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg";
+		  "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
+		  "samsung,exynos3250-jpeg";
 - reg		: address and length of the JPEG codec IP register set;
 - interrupts	: specifies the JPEG codec IP interrupt;
-- clocks	: should contain the JPEG codec IP gate clock specifier, from the
-		  common clock bindings;
-- clock-names	: should contain "jpeg" entry.
+- clock-names   : should contain:
+		   - "jpeg" for the core gate clock,
+		   - "sclk" for the special clock (optional).
+- clocks	: should contain the clock specifier and clock ID list
+		  matching entries in the clock-names property; from
+		  the common clock bindings.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/i2c/mt9m111.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/i2c/mt9m111.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/i2c/mt9m111.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/i2c/mt9m111.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+Micron 1.3Mp CMOS Digital Image Sensor
+
+The Micron MT9M111 is a CMOS active pixel digital image sensor with an active
+array size of 1280H x 1024V. It is programmable through a simple two-wire serial
+interface.
+
+Required Properties:
+- compatible: value should be "micron,mt9m111"
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+	i2c_master {
+		mt9m111@5d {
+			compatible = "micron,mt9m111";
+			reg = <0x5d>;
+
+			remote = <&pxa_camera>;
+			port {
+				mt9m111_1: endpoint {
+					bus-width = <8>;
+					remote-endpoint = <&pxa_camera>;
+				};
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/pxa-camera.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/pxa-camera.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/pxa-camera.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/pxa-camera.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+Marvell PXA camera host interface
+
+Required properties:
+ - compatible: Should be "marvell,pxa270-qci"
+ - reg: register base and size
+ - interrupts: the interrupt number
+ - any required generic properties defined in video-interfaces.txt
+
+Optional properties:
+ - clocks: input clock (see clock-bindings.txt)
+ - clock-output-names: should contain the name of the clock driving the
+                       sensor master clock MCLK
+ - clock-frequency: host interface is driving MCLK, and MCLK rate is this rate
+
+Example:
+
+	pxa_camera: pxa_camera@50000000 {
+		compatible = "marvell,pxa270-qci";
+		reg = <0x50000000 0x1000>;
+		interrupts = <33>;
+
+		clocks = <&pxa2xx_clks 24>;
+		clock-names = "ciclk";
+		clock-frequency = <50000000>;
+		clock-output-names = "qci_mclk";
+
+		status = "okay";
+
+		port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* Parallel bus endpoint */
+			qci: endpoint@0 {
+				reg = <0>;		/* Local endpoint # */
+				remote-endpoint = <&mt9m111_1>;
+				bus-width = <8>;	/* Used data lines */
+				hsync-active = <0>;	/* Active low */
+				vsync-active = <0>;	/* Active low */
+				pclk-sample = <1>;	/* Rising */
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,86 @@
+Renesas RCar Video Input driver (rcar_vin)
+------------------------------------------
+
+The rcar_vin device provides video input capabilities for the Renesas R-Car
+family of devices. The current blocks are always slaves and suppot one input
+channel which can be either RGB, YUYV or BT656.
+
+ - compatible: Must be one of the following
+   - "renesas,vin-r8a7791" for the R8A7791 device
+   - "renesas,vin-r8a7790" for the R8A7790 device
+   - "renesas,vin-r8a7779" for the R8A7779 device
+   - "renesas,vin-r8a7778" for the R8A7778 device
+ - reg: the register base and size for the device registers
+ - interrupts: the interrupt for the device
+ - clocks: Reference to the parent clock
+
+Additionally, an alias named vinX will need to be created to specify
+which video input device this is.
+
+The per-board settings:
+ - port sub-node describing a single endpoint connected to the vin
+   as described in video-interfaces.txt[1]. Only the first one will
+   be considered as each vin interface has one input port.
+
+   These settings are used to work out video input format and widths
+   into the system.
+
+
+Device node example
+-------------------
+
+	aliases {
+	       vin0 = &vin0;
+	};
+
+        vin0: vin@0xe6ef0000 {
+                compatible = "renesas,vin-r8a7790";
+                clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
+                reg = <0 0xe6ef0000 0 0x1000>;
+                interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
+                status = "disabled";
+        };
+
+Board setup example (vin1 composite video input)
+------------------------------------------------
+
+&i2c2   {
+        status = "ok";
+        pinctrl-0 = <&i2c2_pins>;
+        pinctrl-names = "default";
+
+        adv7180@20 {
+                compatible = "adi,adv7180";
+                reg = <0x20>;
+                remote = <&vin1>;
+
+                port {
+                        adv7180: endpoint {
+                                bus-width = <8>;
+                                remote-endpoint = <&vin1ep0>;
+                        };
+                };
+        };
+};
+
+/* composite video input */
+&vin1 {
+        pinctrl-0 = <&vin1_pins>;
+        pinctrl-names = "default";
+
+        status = "ok";
+
+        port {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                vin1ep0: endpoint {
+                        remote-endpoint = <&adv7180>;
+                        bus-width = <8>;
+                };
+        };
+};
+
+
+
+[1] video-interfaces.txt common video media interface
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/sunxi-ir.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/sunxi-ir.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/media/sunxi-ir.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/media/sunxi-ir.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
+
+Required properties:
+- compatible	    : should be "allwinner,sun4i-a10-ir";
+- clocks	    : list of clock specifiers, corresponding to
+		      entries in clock-names property;
+- clock-names	    : should contain "apb" and "ir" entries;
+- interrupts	    : should contain IR IRQ number;
+- reg		    : should contain IO map address for IR.
+
+Optional properties:
+- linux,rc-map-name : Remote control map name.
+
+Example:
+
+ir0: ir@01c21800 {
+	compatible = "allwinner,sun4i-a10-ir";
+	clocks = <&apb0_gates 6>, <&ir0_clk>;
+	clock-names = "apb", "ir";
+	interrupts = <0 5 1>;
+	reg = <0x01C21800 0x40>;
+	linux,rc-map-name = "rc-rc6-mce";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/arizona.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/arizona.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/arizona.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/arizona.txt	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,16 @@ Optional properties:
     the chip default will be used.  If present exactly five values must
     be specified.
 
+  - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
+    they are being externally supplied. As covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt
+
+Optional subnodes:
+  - ldo1 : Initial data for the LDO1 regulator, as covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt
+  - micvdd : Initial data for the MICVDD regulator, as covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt
+
 Example:
 
 codec: wm5102@1a {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/as3722.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/as3722.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/as3722.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/as3722.txt	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,14 @@ Required properties:
   The second cell is the flags, encoded as the trigger masks from binding document
 	interrupts.txt, using dt-bindings/irq.
 
+Optional properties:
+--------------------
+- ams,enable-internal-int-pullup: Boolean property, to enable internal pullup on
+	interrupt pin. Missing this will disable internal pullup on INT pin.
+- ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
+	i2c scl/sda pins. Missing this will disable internal pullup on i2c
+	scl/sda lines.
+
 Optional submodule and their properties:
 =======================================
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/palmas.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/palmas.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/palmas.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/palmas.txt	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@ twl6037 (palmas)
 tps65913 (palmas)
 tps65914 (palmas)
 tps659038
+tps65917
 
 Required properties:
 - compatible : Should be from the list
@@ -16,6 +17,7 @@ Required properties:
   ti,tps65914
   ti,tps80036
   ti,tps659038
+  ti,tps65917
 and also the generic series names
   ti,palmas
 - interrupt-controller : palmas has its own internal IRQs
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/s2mps11.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/s2mps11.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/s2mps11.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/s2mps11.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 
-* Samsung S2MPS11 and S2MPS14 Voltage and Current Regulator
+* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
 
 The Samsung S2MPS11 is a multi-function device which includes voltage and
 current regulators, RTC, charger controller and other sub-blocks. It is
@@ -7,7 +7,8 @@ interfaced to the host controller using
 addressed by the host system using different I2C slave addresses.
 
 Required properties:
-- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic".
+- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic"
+              or "samsung,s2mpu02-pmic".
 - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
 
 Optional properties:
@@ -81,11 +82,13 @@ as per the datasheet of s2mps11.
 		  - valid values for n are:
 			- S2MPS11: 1 to 38
 			- S2MPS14: 1 to 25
-		  - Example: LDO1, LD02, LDO28
+			- S2MPU02: 1 to 28
+		  - Example: LDO1, LDO2, LDO28
 	- BUCKn
 		  - valid values for n are:
 			- S2MPS11: 1 to 10
 			- S2MPS14: 1 to 5
+			- S2MPU02: 1 to 7
 		  - Example: BUCK1, BUCK2, BUCK9
 
 Example:
@@ -96,7 +99,7 @@ Example:
 
 		s2m_osc: clocks {
 			compatible = "samsung,s2mps11-clk";
-			#clock-cells = 1;
+			#clock-cells = <1>;
 			clock-output-names = "xx", "yy", "zz";
 		};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,7 @@ PRCM is an MFD device exposing several P
 (like clks and reset controllers).
 
 Required properties:
- - compatible: "allwinner,sun6i-a31-prcm"
+ - compatible: "allwinner,sun6i-a31-prcm" or "allwinner,sun8i-a23-prcm"
  - reg: The PRCM registers range
 
 The prcm node may contain several subdevices definitions:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/tc3589x.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/tc3589x.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mfd/tc3589x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mfd/tc3589x.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,107 @@
+* Toshiba TC3589x multi-purpose expander
+
+The Toshiba TC3589x series are I2C-based MFD devices which may expose the
+following built-in devices: gpio, keypad, rotator (vibrator), PWM (for
+e.g. LEDs or vibrators) The included models are:
+
+- TC35890
+- TC35892
+- TC35893
+- TC35894
+- TC35895
+- TC35896
+
+Required properties:
+ - compatible : must be "toshiba,tc35890", "toshiba,tc35892", "toshiba,tc35893",
+   "toshiba,tc35894", "toshiba,tc35895" or "toshiba,tc35896"
+ - reg : I2C address of the device
+ - interrupt-parent : specifies which IRQ controller we're connected to
+ - interrupts : the interrupt on the parent the controller is connected to
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <1>, the first cell is the IRQ offset on this
+   TC3589x interrupt controller.
+
+Optional nodes:
+
+- GPIO
+  This GPIO module inside the TC3589x has 24 (TC35890, TC35892) or 20
+  (other models) GPIO lines.
+ - compatible : must be "toshiba,tc3589x-gpio"
+ - interrupts : interrupt on the parent, which must be the tc3589x MFD device
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <2>, the first cell is the IRQ offset on this
+   TC3589x GPIO interrupt controller, the second cell is the interrupt flags
+   in accordance with <dt-bindings/interrupt-controller/irq.h>. The following
+   flags are valid:
+   - IRQ_TYPE_LEVEL_LOW
+   - IRQ_TYPE_LEVEL_HIGH
+   - IRQ_TYPE_EDGE_RISING
+   - IRQ_TYPE_EDGE_FALLING
+   - IRQ_TYPE_EDGE_BOTH
+ - gpio-controller : marks the device node as a GPIO controller
+ - #gpio-cells : should be <2>, the first cell is the GPIO offset on this
+   GPIO controller, the second cell is the flags.
+
+- Keypad
+  This keypad is the same on all variants, supporting up to 96 different
+  keys. The linux-specific properties are modeled on those already existing
+  in other input drivers.
+ - compatible : must be "toshiba,tc3589x-keypad"
+ - debounce-delay-ms : debounce interval in milliseconds
+ - keypad,num-rows : number of rows in the matrix, see
+   bindings/input/matrix-keymap.txt
+ - keypad,num-columns : number of columns in the matrix, see
+   bindings/input/matrix-keymap.txt
+ - linux,keymap: the definition can be found in
+   bindings/input/matrix-keymap.txt
+ - linux,no-autorepeat: do no enable autorepeat feature.
+ - linux,wakeup: use any event on keypad as wakeup event.
+
+Example:
+
+tc35893@44 {
+	compatible = "toshiba,tc35893";
+	reg = <0x44>;
+	interrupt-parent = <&gpio6>;
+	interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	tc3589x_gpio {
+		compatible = "toshiba,tc3589x-gpio";
+		interrupts = <0>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+	tc3589x_keypad {
+		compatible = "toshiba,tc3589x-keypad";
+		interrupts = <6>;
+		debounce-delay-ms = <4>;
+		keypad,num-columns = <8>;
+		keypad,num-rows = <8>;
+		linux,no-autorepeat;
+		linux,wakeup;
+		linux,keymap = <0x0301006b
+				0x04010066
+				0x06040072
+				0x040200d7
+				0x0303006a
+				0x0205000e
+				0x0607008b
+				0x0500001c
+				0x0403000b
+				0x03040034
+				0x05020067
+				0x0305006c
+				0x040500e7
+				0x0005009e
+				0x06020073
+				0x01030039
+				0x07060069
+				0x050500d9>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,13 @@
+NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 apbmisc block
+
+Required properties:
+- compatible : should be:
+       "nvidia,tegra20-apbmisc"
+       "nvidia,tegra30-apbmisc"
+       "nvidia,tegra114-apbmisc"
+       "nvidia,tegra124-apbmisc"
+- reg: Should contain 2 entries: the first entry gives the physical address
+       and length of the registers which contain revision and debug features.
+       The second entry gives the physical address and length of the
+       registers indicating the strapping options.
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -46,13 +46,14 @@ Required Properties:
       - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
         phase shift clocks should be 0.
 
-Required properties for a slot:
+Required properties for a slot (Deprecated - Recommend to use one slot per host):
 
 * gpios: specifies a list of gpios used for command, clock and data bus. The
   first gpio is the command line and the second gpio is the clock line. The
   rest of the gpios (depending on the bus-width property) are the data lines in
   no particular order. The format of the gpio specifier depends on the gpio
   controller.
+(Deprecated - Refer to Documentation/devicetree/binding/pinctrl/samsung-pinctrl.txt)
 
 Example:
 
@@ -69,21 +70,13 @@ Example:
 
 	dwmmc0@12200000 {
 		num-slots = <1>;
-		supports-highspeed;
+		cap-mmc-highspeed;
+		cap-sd-highspeed;
 		broken-cd;
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
-
-		slot@0 {
-			reg = <0>;
-			bus-width = <8>;
-			gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
-				<&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
-				<&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
-				<&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
-				<&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
-		};
+		bus-width = <8>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -34,13 +34,11 @@ Example:
 		num-slots = <1>;
 		vmmc-supply = <&ldo12>;
 		fifo-depth = <0x100>;
-		supports-highspeed;
 		pinctrl-names = "default";
 		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
-		slot@0 {
-			reg = <0>;
-			bus-width = <4>;
-			disable-wp;
-			cd-gpios = <&gpio10 3 0>;
-		};
+		bus-width = <4>;
+		disable-wp;
+		cd-gpios = <&gpio10 3 0>;
+		cap-mmc-highspeed;
+		cap-sd-highspeed;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/mmc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/mmc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/mmc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/mmc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -34,8 +34,8 @@ Optional properties:
 - cap-power-off-card: powering off the card is safe
 - cap-sdio-irq: enable SDIO IRQ signalling on this interface
 - full-pwr-cycle: full power cycle of the card is supported
-- mmc-highspeed-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
-- mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
+- mmc-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
+- mmc-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
 - mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,32 @@
+* Renesas Multi Media Card Interface (MMCIF) Controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the MMCIF device.
+
+
+Required properties:
+
+- compatible: must contain one of the following
+	- "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
+	- "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
+	- "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
+	- "renesas,sh-mmcif" for the generic MMCIF
+
+- clocks: reference to the functional clock
+
+- dmas: reference to the DMA channels, one per channel name listed in the
+  dma-names property.
+- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the
+  receive DMA channel.
+
+
+Example: R8A7790 (R-Car H2) MMCIF0
+
+	mmcif0: mmc@ee200000 {
+		compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
+		reg = <0 0xee200000 0 0x80>;
+		interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
+		dma-names = "tx", "rx";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt	2014-09-28 17:29:07.000000000 -0400
@@ -27,8 +27,8 @@ Example:
 		bus-width = <8>;
 		non-removable;
 
-		vmmc = <&pm8941_l20>;
-		vqmmc = <&pm8941_s3>;
+		vmmc-supply = <&pm8941_l20>;
+		vqmmc-supply = <&pm8941_s3>;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>;
@@ -44,8 +44,8 @@ Example:
 		bus-width = <4>;
 		cd-gpios = <&msmgpio 62 0x1>;
 
-		vmmc = <&pm8941_l21>;
-		vqmmc = <&pm8941_l13>;
+		vmmc-supply = <&pm8941_l21>;
+		vqmmc-supply = <&pm8941_l13>;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,33 @@
+* STMicroelectronics sdhci-st MMC/SD controller
+
+This file documents the differences between the core properties in
+Documentation/devicetree/bindings/mmc/mmc.txt and the properties
+used by the sdhci-st driver.
+
+Required properties:
+- compatible :  Must be "st,sdhci"
+- clock-names : Should be "mmc"
+                See: Documentation/devicetree/bindings/resource-names.txt
+- clocks :      Phandle of the clock used by the sdhci controler
+                See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional properties:
+- non-removable: non-removable slot
+                 See: Documentation/devicetree/bindings/mmc/mmc.txt
+- bus-width: Number of data lines
+                 See: Documentation/devicetree/bindings/mmc/mmc.txt
+
+Example:
+
+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>;
+	bus-width       = <8>
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,8 @@ Optional properties:
 * card-detect-delay: Delay in milli-seconds before detecting card after card
   insert event. The default value is 0.
 
-* supports-highspeed: Enables support for high speed cards (up to 50MHz)
+* 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.
 
@@ -98,14 +99,11 @@ board specific portions as listed below.
 		clock-frequency = <400000000>;
 		clock-freq-min-max = <400000 200000000>;
 		num-slots = <1>;
-		supports-highspeed;
 		broken-cd;
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		vmmc-supply = <&buck8>;
-
-		slot@0 {
-			reg = <0>;
-			bus-width = <8>;
-		};
+		bus-width = <8>;
+		cap-mmc-highspeed;
+		cap-sd-highspeed;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@ Required properties:
  Should be "ti,omap3-hsmmc", for OMAP3 controllers
  Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0
  Should be "ti,omap4-hsmmc", for OMAP4 controllers
+ Should be "ti,am33xx-hsmmc", for AM335x controllers
 - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
 
 Optional properties:
@@ -56,3 +57,56 @@ Examples:
 			&edma 25>;
 		dma-names = "tx", "rx";
 	};
+
+[workaround for missing swakeup on am33xx]
+
+This SOC is missing the swakeup line, it will not detect SDIO irq
+while in suspend.
+
+                             ------
+                             | PRCM |
+                              ------
+                               ^ |
+                       swakeup | | fclk
+                               | v
+       ------                -------               -----
+      | card | -- CIRQ -->  | hsmmc | -- IRQ -->  | CPU |
+       ------                -------               -----
+
+In suspend the fclk is off and the module is disfunctional. Even register reads
+will fail. A small logic in the host will request fclk restore, when an
+external event is detected. Once the clock is restored, the host detects the
+event normally. Since am33xx doesn't have this line it never wakes from
+suspend.
+
+The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make
+this work, we need to set the named pinctrl states "default" and "idle".
+Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio
+dat1. The MMC driver will then toggle between idle and default state during
+runtime.
+
+In summary:
+1. select matching 'compatible' section, see example below.
+2. specify pinctrl states "default" and "idle", "sleep" is optional.
+3. specify the gpio irq used for detecting sdio irq in suspend
+
+If configuration is incomplete, a warning message is emitted "falling back to
+polling". Also check the "sdio irq mode" in /sys/kernel/debug/mmc0/regs. Mind
+not every application needs SDIO irq, e.g. MMC cards.
+
+	mmc1: mmc@48060100 {
+		compatible = "ti,am33xx-hsmmc";
+		...
+		pinctrl-names = "default", "idle", "sleep"
+		pinctrl-0 = <&mmc1_pins>;
+		pinctrl-1 = <&mmc1_idle>;
+		pinctrl-2 = <&mmc1_sleep>;
+		...
+		interrupts-extended = <&intc 64 &gpio2 28 0>;
+	};
+
+	mmc1_idle : pinmux_cirq_pin {
+		pinctrl-single,pins = <
+		        0x0f8 0x3f      /* GPIO2_28 */
+		>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@ Required properties:
 		"renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
 		"renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC
 		"renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC
+		"renesas,sdhi-r8a7791" - SDHI IP on R8A7791 SoC
 
 Optional properties:
 - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@ Optional properties:
 				width of 8 is assumed.
 
  - ti,nand-ecc-opt:		A string setting the ECC layout to use. One of:
-		"sw"		<deprecated> use "ham1" instead
+		"sw"		1-bit Hamming ecc code via software
 		"hw"		<deprecated> use "ham1" instead
 		"hw-romcode"	<deprecated> use "ham1" instead
 		"ham1"		1-bit Hamming ecc code
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/mtd/gpmi-nand.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/mtd/gpmi-nand.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/mtd/gpmi-nand.txt	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,16 @@ Optional properties:
                        discoverable or this property is not enabled,
                        the software may chooses an implementation-defined
                        ECC scheme.
+  - fsl,no-blockmark-swap: Don't swap the bad block marker from the OOB
+                       area with the byte in the data area but rely on the
+                       flash based BBT for identifying bad blocks.
+                       NOTE: this is only valid in conjunction with
+                             'nand-on-flash-bbt'.
+                       WARNING: on i.MX28 blockmark swapping cannot be
+                       disabled for the BootROM in the FCB. Thus,
+                       partitions written from Linux with this feature
+                       turned on may not be accessible by the BootROM
+                       code.
 
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,10 +8,16 @@ Required properties:
    - SerDes integration registers (1/2)
    - SerDes integration registers (2/2)
 
+Optional properties:
+- amd,speed-set: Speed capabilities of the device
+    0 - 1GbE and 10GbE (default)
+    1 - 2.5GbE and 10GbE
+
 Example:
 	xgbe_phy@e1240800 {
 		compatible = "amd,xgbe-phy-seattle-v1a", "ethernet-phy-ieee802.3-c45";
 		reg = <0 0xe1240800 0 0x00400>,
 		      <0 0xe1250000 0 0x00060>,
 		      <0 0xe1250080 0 0x00004>;
+		amd,speed-set = <0>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/amd-xgbe.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/amd-xgbe.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/amd-xgbe.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/amd-xgbe.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,16 +8,21 @@ Required properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
 - interrupts: Should contain the amd-xgbe interrupt
-- clocks: Should be the DMA clock for the amd-xgbe device (used for
-  calculating the correct Rx interrupt watchdog timer value on a DMA
-  channel for coalescing)
-- clock-names: Should be the name of the DMA clock, "dma_clk"
+- clocks:
+   - DMA clock for the amd-xgbe device (used for calculating the
+     correct Rx interrupt watchdog timer value on a DMA channel
+     for coalescing)
+   - PTP clock for the amd-xgbe device
+- clock-names: Should be the names of the clocks
+   - "dma_clk" for the DMA clock
+   - "ptp_clk" for the PTP clock
 - phy-handle: See ethernet.txt file in the same directory
 - phy-mode: See ethernet.txt file in the same directory
 
 Optional properties:
 - mac-address: mac address to be assigned to the device. Can be overridden
   by UEFI.
+- dma-coherent: Present if dma operations are coherent
 
 Example:
 	xgbe@e0700000 {
@@ -26,8 +31,8 @@ Example:
 		      <0 0xe0780000 0 0x80000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 325 4>;
-		clocks = <&xgbe_clk>;
-		clock-names = "dma_clk";
+		clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>;
+		clock-names = "dma_clk", "ptp_clk";
 		phy-handle = <&phy>;
 		phy-mode = "xgmii";
 		mac-address = [ 02 a1 a2 a3 a4 a5 ];
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,66 @@
+APM X-Gene SoC Ethernet nodes
+
+Ethernet nodes are defined to describe on-chip ethernet interfaces in
+APM X-Gene SoC.
+
+Required properties:
+- compatible: Should be "apm,xgene-enet"
+- 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: Should contain the register set names
+  - "enet_csr": Ethernet control and status register address space
+  - "ring_csr": Descriptor ring control and status register address space
+  - "ring_cmd": Descriptor ring command register address space
+- interrupts: Ethernet main interrupt
+- clocks: Reference to the clock entry.
+- local-mac-address: MAC address assigned to this device
+- phy-connection-type: Interface type between ethernet device and PHY device
+- phy-handle: Reference to a PHY node connected to this device
+
+- mdio: Device tree subnode with the following required properties:
+  - compatible: Must be "apm,xgene-mdio".
+  - #address-cells: Must be <1>.
+  - #size-cells: Must be <0>.
+
+  For the phy on the mdio bus, there must be a node with the following fields:
+  - compatible: PHY identifier.  Please refer ./phy.txt for the format.
+  - reg: The ID number for the phy.
+
+Optional properties:
+- status: Should be "ok" or "disabled" for enabled/disabled. Default is "ok".
+
+Example:
+	menetclk: menetclk {
+		compatible = "apm,xgene-device-clock";
+		clock-output-names = "menetclk";
+		status = "ok";
+	};
+
+	menet: ethernet@17020000 {
+		compatible = "apm,xgene-enet";
+		status = "disabled";
+		reg = <0x0 0x17020000 0x0 0xd100>,
+		      <0x0 0X17030000 0x0 0X400>,
+		      <0x0 0X10000000 0x0 0X200>;
+		reg-names = "enet_csr", "ring_csr", "ring_cmd";
+		interrupts = <0x0 0x3c 0x4>;
+		clocks = <&menetclk 0>;
+		local-mac-address = [00 01 73 00 00 01];
+		phy-connection-type = "rgmii";
+		phy-handle = <&menetphy>;
+		mdio {
+			compatible = "apm,xgene-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			menetphy: menetphy@3 {
+				compatible = "ethernet-phy-id001c.c915";
+				reg = <0x3>;
+			};
+
+		};
+	};
+
+/* Board-specific peripheral configurations */
+&menet {
+        status = "ok";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/broadcom-systemport.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/broadcom-systemport.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/broadcom-systemport.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/broadcom-systemport.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,8 @@ Required properties:
 - compatible: should be one of "brcm,systemport-v1.00" or "brcm,systemport"
 - reg: address and length of the register set for the device.
 - interrupts: interrupts for the device, first cell must be for the the rx
-  interrupts, and the second cell should be for the transmit queues
+  interrupts, and the second cell should be for the transmit queues. An
+  optional third interrupt cell for Wake-on-LAN can be specified
 - local-mac-address: Ethernet MAC address (48 bits) of this adapter
 - phy-mode: Should be a string describing the PHY interface to the
   Ethernet switch/PHY, see Documentation/devicetree/bindings/net/ethernet.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/davinci-mdio.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/davinci-mdio.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/davinci-mdio.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/davinci-mdio.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,8 @@
-TI SoC Davinci MDIO Controller Device Tree Bindings
+TI SoC Davinci/Keystone2 MDIO Controller Device Tree Bindings
 ---------------------------------------------------
 
 Required properties:
-- compatible		: Should be "ti,davinci_mdio"
+- compatible		: Should be "ti,davinci_mdio" or "ti,keystone_mdio"
 - reg			: physical base address and size of the davinci mdio
 			  registers map
 - bus_freq		: Mdio Bus frequency
@@ -19,7 +19,7 @@ file.
 Examples:
 
 	mdio: davinci_mdio@4A101000 {
-		compatible = "ti,cpsw";
+		compatible = "ti,davinci_mdio";
 		reg = <0x4A101000 0x1000>;
 		bus_freq = <1000000>;
 	};
@@ -27,7 +27,7 @@ Examples:
 (or)
 
 	mdio: davinci_mdio@4A101000 {
-		compatible = "ti,cpsw";
+		compatible = "ti,davinci_mdio";
 		ti,hwmods = "davinci_mdio";
 		bus_freq = <1000000>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/fsl-fec.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/fsl-fec.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/fsl-fec.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/fsl-fec.txt	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,14 @@ Optional properties:
   only if property "phy-reset-gpios" is available.  Missing the property
   will have the duration be 1 millisecond.  Numbers greater than 1000 are
   invalid and 1 millisecond will be used instead.
-- phy-supply: regulator that powers the Ethernet PHY.
+- phy-supply : regulator that powers the Ethernet PHY.
+- phy-handle : phandle to the PHY device connected to this device.
+- fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
+  Use instead of phy-handle.
+
+Optional subnodes:
+- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
+  according to phy.txt in the same directory
 
 Example:
 
@@ -25,3 +32,23 @@ ethernet@83fec000 {
 	local-mac-address = [00 04 9F 01 1B B9];
 	phy-supply = <&reg_fec_supply>;
 };
+
+Example with phy specified:
+
+ethernet@83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
+	local-mac-address = [00 04 9F 01 1B B9];
+	phy-supply = <&reg_fec_supply>;
+	phy-handle = <&ethphy>;
+	mdio {
+		ethphy: ethernet-phy@6 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <6>;
+			max-speed = <100>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+*CC2520 IEEE 802.15.4 Compatible Radio*
+
+Required properties:
+	- compatible: 		should be "ti,cc2520"
+	- spi-max-frequency:	maximal bus speed (8000000), should be set to 4000000 depends
+				sync or async operation mode
+	- reg:			the chipselect index
+	- pinctrl-0: 		pin control group to be used for this controller.
+	- pinctrl-names: 	must contain a "default" entry.
+	- fifo-gpio:		GPIO spec for the FIFO pin
+	- fifop-gpio:		GPIO spec for the FIFOP pin
+	- sfd-gpio:		GPIO spec for the SFD pin
+	- cca-gpio:		GPIO spec for the CCA pin
+	- vreg-gpio:		GPIO spec for the VREG pin
+	- reset-gpio:		GPIO spec for the RESET pin
+Example:
+	cc2520@0 {
+		compatible = "ti,cc2520";
+		reg = <0>;
+		spi-max-frequency = <4000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&cc2520_cape_pins>;
+		fifo-gpio = <&gpio1 18 0>;
+		fifop-gpio = <&gpio1 19 0>;
+		sfd-gpio = <&gpio1 13 0>;
+		cca-gpio = <&gpio1 16 0>;
+		vreg-gpio = <&gpio0 31 0>;
+		reset-gpio = <&gpio1 12 0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/marvell-pp2.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/marvell-pp2.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/marvell-pp2.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/marvell-pp2.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,61 @@
+* Marvell Armada 375 Ethernet Controller (PPv2)
+
+Required properties:
+
+- compatible: should be "marvell,armada-375-pp2"
+- reg: addresses and length of the register sets for the device.
+  Must contain the following register sets:
+	- common controller registers
+	- LMS registers
+  In addition, at least one port register set is required.
+- clocks: a pointer to the reference clocks for this device, consequently:
+	- main controller clock
+	- GOP clock
+- clock-names: names of used clocks, must be "pp_clk" and "gop_clk".
+
+The ethernet ports are represented by subnodes. At least one port is
+required.
+
+Required properties (port):
+
+- interrupts: interrupt for the port
+- port-id: should be '0' or '1' for ethernet ports, and '2' for the
+           loopback port
+- phy-mode: See ethernet.txt file in the same directory
+
+Optional properties (port):
+
+- marvell,loopback: port is loopback mode
+- phy: a phandle to a phy node defining the PHY address (as the reg
+  property, a single integer). Note: if this property isn't present,
+  then fixed link is assumed, and the 'fixed-link' property is
+  mandatory.
+
+Example:
+
+ethernet@f0000 {
+	compatible = "marvell,armada-375-pp2";
+	reg = <0xf0000 0xa000>,
+	      <0xc0000 0x3060>,
+	      <0xc4000 0x100>,
+	      <0xc5000 0x100>;
+	clocks = <&gateclk 3>, <&gateclk 19>;
+	clock-names = "pp_clk", "gop_clk";
+	status = "okay";
+
+	eth0: eth0@c4000 {
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		port-id = <0>;
+		status = "okay";
+		phy = <&phy0>;
+		phy-mode = "gmii";
+	};
+
+	eth1: eth1@c5000 {
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		port-id = <1>;
+		status = "okay";
+		phy = <&phy3>;
+		phy-mode = "gmii";
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,33 @@
+* STMicroelectronics SAS. ST21NFCB NFC Controller
+
+Required properties:
+- compatible: Should be "st,st21nfcb_i2c".
+- clock-frequency: IÂ²C work frequency.
+- reg: address on the bus
+- interrupt-parent: phandle for the interrupt gpio controller
+- interrupts: GPIO interrupt to which the chip is connected
+- reset-gpios: Output GPIO pin used to reset the ST21NFCB
+
+Optional SoC Specific Properties:
+- pinctrl-names: Contains only one value - "default".
+- pintctrl-0: Specifies the pin control groups used for this controller.
+
+Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
+
+&i2c2 {
+
+	status = "okay";
+
+	st21nfcb: st21nfcb@8 {
+
+		compatible = "st,st21nfcb_i2c";
+
+		reg = <0x08>;
+		clock-frequency = <400000>;
+
+		interrupt-parent = <&gpio5>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+		reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/sh_eth.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/sh_eth.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/sh_eth.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/sh_eth.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@ Required properties:
 	      "renesas,ether-r8a7779"  if the device is a part of R8A7779 SoC.
 	      "renesas,ether-r8a7790"  if the device is a part of R8A7790 SoC.
 	      "renesas,ether-r8a7791"  if the device is a part of R8A7791 SoC.
+	      "renesas,ether-r8a7794"  if the device is a part of R8A7794 SoC.
 	      "renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
 - reg: offset and length of (1) the E-DMAC/feLic register block (required),
        (2) the TSU register block (optional).
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/stmmac.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/stmmac.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,10 @@ Required properties:
 - snps,force_sf_dma_mode	Force DMA to use the Store and Forward
 				mode for both tx and rx. This flag is
 				ignored if force_thresh_dma_mode is set.
+- snps,multicast-filter-bins:	Number of multicast filter hash bins
+				supported by this device instance
+- snps,perfect-filter-entries:	Number of perfect filter entries supported
+				by this device instance
 
 Optional properties:
 - resets: Should contain a phandle to the STMMAC reset signal, if any
@@ -35,6 +39,10 @@ Optional properties:
   further clocks may be specified in derived bindings.
 - clock-names: One name for each entry in the clocks property, the
   first one should be "stmmaceth".
+- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
+  available this clock is used for programming the Timestamp Addend Register.
+  If not passed then the system clock will be used and this is fine on some
+  platforms.
 
 Examples:
 
@@ -47,6 +55,8 @@ Examples:
 		mac-address = [000000000000]; /* Filled in by U-Boot */
 		max-frame-size = <3800>;
 		phy-mode = "gmii";
+		snps,multicast-filter-bins = <256>;
+		snps,perfect-filter-entries = <128>;
 		clocks = <&clock>;
 		clock-names = "stmmaceth">;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+Broadcom BCM43xx Fullmac wireless SDIO devices
+
+This node provides properties for controlling the Broadcom 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 "brcm,bcm4329-fmac".
+
+Optional properties:
+ - brcm,drive-strength : drive strength used for SDIO pins on device in mA
+	(default = 6).
+ - interrupt-parent : the phandle for the interrupt controller to which the
+	device interrupts are connected.
+ - interrupts : specifies attributes for the out-of-band interrupt (host-wake).
+	When not specified the device will use in-band SDIO interrupts.
+ - interrupt-names : name of the out-of-band interrupt, which must be set
+	to "host-wake".
+
+Example:
+
+mmc3: mmc@01c12000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins_a>;
+	vmmc-supply = <&reg_vmmc3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+		interrupt-parent = <&pio>;
+		interrupts = <10 8>; /* PH10 / EINT10 */
+		interrupt-names = "host-wake";
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/panel/auo,b133htn01.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/auo,b133htn01.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/panel/auo,b133htn01.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/auo,b133htn01.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+
+Required properties:
+- compatible: should be "auo,b133htn01"
+
+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-3.16-gnu/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+Foxlink Group 5" WVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "foxlink,fl500wvr00-a0t"
+
+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-3.16-gnu/Documentation/devicetree/bindings/panel/innolux,n116bge.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/innolux,n116bge.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/panel/innolux,n116bge.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/innolux,n116bge.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,n116bge"
+
+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-3.16-gnu/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+InnoLux 15.6" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,n156bge-l21"
+
+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-3.16-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,10 @@
 
 Required properties:
 - compatible: should contain "snps,dw-pcie" to identify the core.
+- reg: Should contain the configuration address space.
+- reg-names: Must be "config" for the PCIe configuration space.
+    (The old way of getting the configuration address space from "ranges"
+    is deprecated and should be avoided.)
 - #address-cells: set to <3>
 - #size-cells: set to <2>
 - device_type: set to "pci"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2014-09-28 17:29:07.000000000 -0400
@@ -14,9 +14,6 @@ Required properties:
 - interrupt-names: Must include the following entries:
   "intr": The Tegra interrupt that is asserted for controller interrupts
   "msi": The Tegra interrupt that is asserted when an MSI is received
-- pex-clk-supply: Supply voltage for internal reference clock
-- vdd-supply: Power supply for controller (1.05V)
-- avdd-supply: Power supply for controller (1.05V) (not required for Tegra20)
 - bus-range: Range of bus numbers associated with this controller
 - #address-cells: Address representation for root ports (must be 3)
   - cell 0 specifies the bus and device numbers of the root port:
@@ -60,6 +57,33 @@ Required properties:
   - afi
   - pcie_x
 
+Power supplies for Tegra20:
+- avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+- vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+- avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
+  supply 1.05 V.
+- avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
+  supply 1.05 V.
+- vddio-pex-clk-supply: Power supply for PCIe clock. Must supply 3.3 V.
+
+Power supplies for Tegra30:
+- Required:
+  - avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
+    supply 1.05 V.
+  - avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
+    supply 1.05 V.
+  - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must
+    supply 1.8 V.
+  - hvdd-pex-supply: High-voltage supply for PCIe I/O and PCIe output clocks.
+    Must supply 3.3 V.
+- Optional:
+  - If lanes 0 to 3 are used:
+    - avdd-pexa-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+    - vdd-pexa-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+  - If lanes 4 or 5 are used:
+    - avdd-pexb-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+    - vdd-pexb-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+
 Root ports are defined as subnodes of the PCIe controller node.
 
 Required properties:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+SPEAr13XX PCIe DT detail:
+================================
+
+SPEAr13XX uses synopsis designware PCIe controller and ST MiPHY as phy
+controller.
+
+Required properties:
+- compatible : should be "st,spear1340-pcie", "snps,dw-pcie".
+- phys		    : phandle to phy node associated with pcie controller
+- phy-names	    : must be "pcie-phy"
+- All other definitions as per generic PCI bindings
+
+ Optional properties:
+- st,pcie-is-gen1 indicates that forced gen1 initialization is needed.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/ti-pci.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/ti-pci.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pci/ti-pci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pci/ti-pci.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,59 @@
+TI PCI Controllers
+
+PCIe Designware Controller
+ - compatible: Should be "ti,dra7-pcie""
+ - reg : Two register ranges as listed in the reg-names property
+ - reg-names : The first entry must be "ti-conf" for the TI specific registers
+	       The second entry must be "rc-dbics" for the designware pcie
+	       registers
+	       The third entry must be "config" for the PCIe configuration space
+ - phys : list of PHY specifiers (used by generic PHY framework)
+ - phy-names : must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
+	       number of PHYs as specified in *phys* property.
+ - ti,hwmods : Name of the hwmod associated to the pcie, "pcie<X>",
+	       where <X> is the instance number of the pcie from the HW spec.
+ - interrupts : Two interrupt entries must be specified. The first one is for
+		main interrupt line and the second for MSI interrupt line.
+ - #address-cells,
+   #size-cells,
+   #interrupt-cells,
+   device_type,
+   ranges,
+   num-lanes,
+   interrupt-map-mask,
+   interrupt-map : as specified in ../designware-pcie.txt
+
+Example:
+axi {
+	compatible = "simple-bus";
+	#size-cells = <1>;
+	#address-cells = <1>;
+	ranges = <0x51000000 0x51000000 0x3000
+		  0x0	     0x20000000 0x10000000>;
+	pcie@51000000 {
+		compatible = "ti,dra7-pcie";
+		reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
+		reg-names = "rc_dbics", "ti_conf", "config";
+		interrupts = <0 232 0x4>, <0 233 0x4>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		ranges = <0x81000000 0 0          0x03000 0 0x00010000
+			  0x82000000 0 0x20013000 0x13000 0 0xffed000>;
+		#interrupt-cells = <1>;
+		num-lanes = <1>;
+		ti,hwmods = "pcie1";
+		phys = <&pcie1_phy>;
+		phy-names = "pcie-phy0";
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie_intc 1>,
+				<0 0 0 2 &pcie_intc 2>,
+				<0 0 0 3 &pcie_intc 3>,
+				<0 0 0 4 &pcie_intc 4>;
+		pcie_intc: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,34 @@
+Berlin SATA PHY
+---------------
+
+Required properties:
+- compatible: should be "marvell,berlin2q-sata-phy"
+- address-cells: should be 1
+- size-cells: should be 0
+- phy-cells: from the generic PHY bindings, must be 1
+- reg: address and length of the register
+- clocks: reference to the clock entry
+
+Sub-nodes:
+Each PHY should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: the PHY number
+
+Example:
+	sata_phy: phy@f7e900a0 {
+		compatible = "marvell,berlin2q-sata-phy";
+		reg = <0xf7e900a0 0x200>;
+		clocks = <&chip CLKID_SATA>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#phy-cells = <1>;
+
+		sata-phy@0 {
+			reg = <0>;
+		};
+
+		sata-phy@1 {
+			reg = <1>;
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+Hisilicon hix5hd2 SATA PHY
+-----------------------
+
+Required properties:
+- compatible: should be "hisilicon,hix5hd2-sata-phy"
+- reg: offset and length of the PHY registers
+- #phy-cells: must be 0
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Optional Properties:
+- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
+- hisilicon,power-reg: offset and bit number within peripheral-syscon,
+	register of controlling sata power supply.
+
+Example:
+	sata_phy: phy@f9900000 {
+		compatible = "hisilicon,hix5hd2-sata-phy";
+		reg = <0xf9900000 0x10000>;
+		#phy-cells = <0>;
+		hisilicon,peripheral-syscon = <&peripheral_ctrl>;
+		hisilicon,power-reg = <0x8 10>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/phy-bindings.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/phy-bindings.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/phy-bindings.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/phy-bindings.txt	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,10 @@ Required Properties:
 		provider can use the values in cells to find the appropriate
 		PHY.
 
+Optional Properties:
+phy-supply:	Phandle to a regulator that provides power to the PHY. This
+		regulator will be managed during the PHY power on/off sequence.
+
 For example:
 
 phys: phy {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/phy-miphy365x.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/phy-miphy365x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/phy-miphy365x.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,76 @@
+STMicroelectronics STi MIPHY365x PHY binding
+============================================
+
+This binding describes a miphy device that is used to control PHY hardware
+for SATA and PCIe.
+
+Required properties (controller (parent) node):
+- compatible    : Should be "st,miphy365x-phy"
+- st,syscfg     : Should be a phandle of the system configuration register group
+		  which contain the SATA, PCIe mode setting bits
+
+Required nodes	:  A sub-node is required for each channel the controller
+		   provides. Address range information including the usual
+		   'reg' and 'reg-names' properties are used inside these
+		   nodes to describe the controller's topology. These nodes
+		   are translated by the driver's .xlate() function.
+
+Required properties (port (child) node):
+- #phy-cells 	: Should be 1 (See second example)
+		  Cell after port phandle is device type from:
+			- MIPHY_TYPE_SATA
+			- MIPHY_TYPE_PCI
+- reg        	: Address and length of register sets for each device in
+		  "reg-names"
+- reg-names     : The names of the register addresses corresponding to the
+		  registers filled in "reg":
+			- sata:   For SATA devices
+			- pcie:   For PCIe devices
+			- syscfg: To specify the syscfg based config register
+
+Optional properties (port (child) node):
+- st,sata-gen	     :	Generation of locally attached SATA IP. Expected values
+			are {1,2,3). If not supplied generation 1 hardware will
+			be expected
+- st,pcie-tx-pol-inv :	Bool property to invert the polarity PCIe Tx (Txn/Txp)
+- st,sata-tx-pol-inv :	Bool property to invert the polarity SATA Tx (Txn/Txp)
+
+Example:
+
+	miphy365x_phy: miphy365x@fe382000 {
+		compatible      = "st,miphy365x-phy";
+		st,syscfg  	= <&syscfg_rear>;
+		#address-cells	= <1>;
+		#size-cells	= <1>;
+		ranges;
+
+		phy_port0: port@fe382000 {
+			reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>;
+			reg-names = "sata", "pcie", "syscfg";
+			#phy-cells = <1>;
+			st,sata-gen = <3>;
+		};
+
+		phy_port1: port@fe38a000 {
+			reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;;
+			reg-names = "sata", "pcie", "syscfg";
+			#phy-cells = <1>;
+			st,pcie-tx-pol-inv;
+		};
+	};
+
+Specifying phy control of devices
+=================================
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type.
+
+Example:
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+	sata0: sata@fe380000 {
+		...
+		phys	  = <&phy_port0 MIPHY_TYPE_SATA>;
+		...
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,24 @@
+Qualcomm APQ8064 SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,apq8064-sata-phy".
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+  clock-names.
+- clock-names: must be "cfg" for phy config clock.
+
+Example:
+	sata_phy: sata-phy@1b400000 {
+		compatible = "qcom,apq8064-sata-phy";
+		reg = <0x1b400000 0x200>;
+
+		clocks = <&gcc SATA_PHY_CFG_CLK>;
+		clock-names = "cfg";
+
+		#phy-cells = <0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+Qualcomm IPQ806x SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,ipq806x-sata-phy"
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: must be exactly one entry
+- clock-names: must be "cfg"
+
+Example:
+	sata_phy: sata-phy@1b400000 {
+		compatible = "qcom,ipq806x-sata-phy";
+		reg = <0x1b400000 0x200>;
+
+		clocks = <&gcc SATA_PHY_CFG_CLK>;
+		clock-names = "cfg";
+
+		#phy-cells = <0>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -26,9 +26,11 @@ Samsung S5P/EXYNOS SoC series USB PHY
 
 Required properties:
 - compatible : should be one of the listed compatibles:
+	- "samsung,exynos3250-usb2-phy"
 	- "samsung,exynos4210-usb2-phy"
 	- "samsung,exynos4x12-usb2-phy"
 	- "samsung,exynos5250-usb2-phy"
+	- "samsung,s5pv210-usb2-phy"
 - reg : a list of registers used by phy driver
 	- first and obligatory is the location of phy modules registers
 - samsung,sysreg-phandle - handle to syscon used to control the system registers
@@ -46,6 +48,7 @@ and Exynos 4212) it is as follows:
   1 - USB host ("host"),
   2 - HSIC0 ("hsic0"),
   3 - HSIC1 ("hsic1"),
+Exynos3250 has only USB device phy available as phy 0.
 
 Exynos 4210 and Exynos 4212 use mode switching and require that mode switch
 register is supplied.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/st-spear-miphy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/st-spear-miphy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/st-spear-miphy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/st-spear-miphy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,15 @@
+ST SPEAr miphy DT details
+=========================
+
+ST Microelectronics SPEAr miphy is a phy controller supporting PCIe and SATA.
+
+Required properties:
+- compatible : should be "st,spear1310-miphy" or "st,spear1340-miphy"
+- reg : offset and length of the PHY register set.
+- misc: phandle for the syscon node to access misc registers
+- #phy-cells : from the generic PHY bindings, must be 1.
+	- cell[1]: 0 if phy used for SATA, 1 for PCIe.
+
+Optional properties:
+- phy-id: Instance id of the phy. Only required when there are multiple phys
+  present on a implementation.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/ti-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/ti-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/phy/ti-phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/phy/ti-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,15 +9,17 @@ Required properties:
                         e.g. USB2_PHY on OMAP5.
  "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
                         e.g. USB3 PHY and SATA PHY on OMAP5.
+ "ti,control-phy-pcie" - for pcie to support external clock for pcie and to
+			set PCS delay value.
+			e.g. PCIE PHY in DRA7x
  "ti,control-phy-usb2-dra7" - if it has power down register like USB2 PHY on
                         DRA7 platform.
  "ti,control-phy-usb2-am437" - if it has power down register like USB2 PHY on
                         AM437 platform.
- - reg : Address and length of the register set for the device. It contains
-   the address of "otghs_control" for control-phy-otghs or "power" register
-   for other types.
- - reg-names: should be "otghs_control" control-phy-otghs and "power" for
-   other types.
+ - reg : register ranges as listed in the reg-names property
+ - reg-names: "otghs_control" for control-phy-otghs
+	      "power", "pcie_pcs" and "control_sma" for control-phy-pcie
+	      "power" for all other types
 
 omap_control_usb: omap-control-usb@4a002300 {
         compatible = "ti,control-phy-otghs";
@@ -56,8 +58,8 @@ usb2phy@4a0ad080 {
 TI PIPE3 PHY
 
 Required properties:
- - compatible: Should be "ti,phy-usb3" or "ti,phy-pipe3-sata".
-   "ti,omap-usb3" is deprecated.
+ - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
+   "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
  - reg : Address and length of the register set for the device.
  - reg-names: The names of the register addresses corresponding to the registers
    filled in "reg".
@@ -69,10 +71,17 @@ Required properties:
    * "wkupclk" - wakeup clock.
    * "sysclk" - system clock.
    * "refclk" - reference clock.
+   * "dpll_ref" - external dpll ref clk
+   * "dpll_ref_m2" - external dpll ref clk
+   * "phy-div" - divider for apll
+   * "div-clk" - apll clock
 
 Optional properties:
  - ctrl-module : phandle of the control module used by PHY driver to power on
    the PHY.
+ - id: If there are multiple instance of the same type, in order to
+   differentiate between each instance "id" can be used (e.g., multi-lane PCIe
+   PHY). If "id" is not provided, it is set to default value of '1'.
 
 This is usually a subnode of ocp2scp to which it is connected.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,8 @@ Required properties:
   "allwinner,sun6i-a31-pinctrl"
   "allwinner,sun6i-a31-r-pinctrl"
   "allwinner,sun7i-a20-pinctrl"
+  "allwinner,sun8i-a23-pinctrl"
+  "allwinner,sun8i-a23-r-pinctrl"
 - reg: Should contain the register physical address and length for the
   pin controller.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,127 @@
+Device tree binding for NVIDIA Tegra XUSB pad controller
+========================================================
+
+The Tegra XUSB pad controller manages a set of lanes, each of which can be
+assigned to one out of a set of different pads. Some of these pads have an
+associated PHY that must be powered up before the pad can be used.
+
+This document defines the device-specific binding for the XUSB pad controller.
+
+Refer to pinctrl-bindings.txt in this directory for generic information about
+pin controller device tree bindings and ../phy/phy-bindings.txt for details on
+how to describe and reference PHYs in device trees.
+
+Required properties:
+--------------------
+- compatible: should be "nvidia,tegra124-xusb-padctl"
+- reg: Physical base address and length of the controller's registers.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - padctl
+- #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
+  See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
+
+Lane muxing:
+------------
+
+Child nodes contain the pinmux configurations following the conventions from
+the pinctrl-bindings.txt document. Typically a single, static configuration is
+given and applied at boot time.
+
+Each subnode describes groups of lanes along with parameters and pads that
+they should be assigned to. The name of these subnodes is not important. All
+subnodes should be parsed solely based on their content.
+
+Each subnode only applies the parameters that are explicitly listed. In other
+words, if a subnode that lists a function but no pin configuration parameters
+implies no information about any pin configuration parameters. Similarly, a
+subnode that describes only an IDDQ parameter implies no information about
+what function the pins are assigned to. For this reason even seemingly boolean
+values are actually tristates in this binding: unspecified, off or on.
+Unspecified is represented as an absent property, and off/on are represented
+as integer values 0 and 1.
+
+Required properties:
+- nvidia,lanes: An array of strings. Each string is the name of a lane.
+
+Optional properties:
+- nvidia,function: A string that is the name of the function (pad) that the
+  pin or group should be assigned to. Valid values for function names are
+  listed below.
+- nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
+
+Note that not all of these properties are valid for all lanes. Lanes can be
+divided into three groups:
+
+  - otg-0, otg-1, otg-2:
+
+    Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
+
+    The nvidia,iddq property does not apply to this group.
+
+  - ulpi-0, hsic-0, hsic-1:
+
+    Valid functions for this group are: "snps", "xusb".
+
+    The nvidia,iddq property does not apply to this group.
+
+  - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
+
+    Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
+
+
+Example:
+========
+
+SoC file extract:
+-----------------
+
+	padctl@0,7009f000 {
+		compatible = "nvidia,tegra124-xusb-padctl";
+		reg = <0x0 0x7009f000 0x0 0x1000>;
+		resets = <&tegra_car 142>;
+		reset-names = "padctl";
+
+		#phy-cells = <1>;
+	};
+
+Board file extract:
+-------------------
+
+	pcie-controller@0,01003000 {
+		...
+
+		phys = <&padctl 0>;
+		phy-names = "pcie";
+
+		...
+	};
+
+	...
+
+	padctl: padctl@0,7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		padctl_default: pinmux {
+			usb3 {
+				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+			};
+
+			pcie {
+				nvidia,lanes = "pcie-2", "pcie-3",
+					       "pcie-4";
+				nvidia,function = "pcie";
+				nvidia,iddq = <0>;
+			};
+
+			sata {
+				nvidia,lanes = "sata-0";
+				nvidia,function = "sata";
+				nvidia,iddq = <0>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ Valid values for pins are:
   gpio0-gpio89
 
 Valid values for function are:
-  cam_mclk, codec_mic_i2s, codec_spkr_i2s, gsbi1, gsbi2, gsbi3, gsbi4,
+  cam_mclk, codec_mic_i2s, codec_spkr_i2s, gpio, gsbi1, gsbi2, gsbi3, gsbi4,
   gsbi4_cam_i2c, gsbi5, gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6,
   gsbi6_spi_cs1, gsbi6_spi_cs2, gsbi6_spi_cs3, gsbi7, gsbi7_spi_cs1,
   gsbi7_spi_cs2, gsbi7_spi_cs3, gsbi_cam_i2c, hdmi, mi2s, riva_bt, riva_fm,
@@ -62,7 +62,7 @@ Example:
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		interrupts = <0 32 0x4>;
+		interrupts = <0 16 0x4>;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&gsbi5_uart_default>;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ Valid values for qcom,pins are:
 
 
 Valid values for function are:
-  mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gsbi1, gsbi2, gsbi4, gsbi5,
+  mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gpio, gsbi1, gsbi2, gsbi4, gsbi5,
   gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6, gsbi7, nss_spi, sdc1,
   spdif, nand, tsif1, tsif2, usb_fs_n, usb_fs, usb2_hsic, rgmii2, sata,
   pcie1_rst, pcie1_prsnt, pcie1_pwren_n, pcie1_pwren, pcie1_pwrflt,
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,181 @@
+Qualcomm MSM8960 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8960 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,msm8960-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 abitrary 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-gpio151,
+		    sdc1_clk,
+		    sdc1_cmd,
+		    sdc1_data
+		    sdc3_clk,
+		    sdc3_cmd,
+		    sdc3_data
+
+- 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_pcm, bt, cam_mclk0, cam_mclk1, cam_mclk2,
+		    codec_mic_i2s, codec_spkr_i2s, ext_gps, fm, gps_blanking,
+		    gps_pps_in, gps_pps_out, gp_clk_0a, gp_clk_0b, gp_clk_1a,
+		    gp_clk_1b, gp_clk_2a, gp_clk_2b, gp_mn, gp_pdm_0a,
+		    gp_pdm_0b, gp_pdm_1a, gp_pdm_1b, gp_pdm_2a, gp_pdm_2b, gpio,
+		    gsbi1, gsbi1_spi_cs1_n, gsbi1_spi_cs2a_n, gsbi1_spi_cs2b_n,
+		    gsbi1_spi_cs3_n, gsbi2, gsbi2_spi_cs1_n, gsbi2_spi_cs2_n,
+		    gsbi2_spi_cs3_n, gsbi3, gsbi4, gsbi4_3d_cam_i2c_l,
+		    gsbi4_3d_cam_i2c_r, gsbi5, gsbi5_3d_cam_i2c_l,
+		    gsbi5_3d_cam_i2c_r, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10,
+		    gsbi11, gsbi11_spi_cs1a_n, gsbi11_spi_cs1b_n,
+		    gsbi11_spi_cs2a_n, gsbi11_spi_cs2b_n, gsbi11_spi_cs3_n,
+		    gsbi12, hdmi_cec, hdmi_ddc_clock, hdmi_ddc_data,
+		    hdmi_hot_plug_detect, hsic, mdp_vsync, mi2s, mic_i2s,
+		    pmb_clk, pmb_ext_ctrl, ps_hold, rpm_wdog, sdc2, sdc4, sdc5,
+		    slimbus1, slimbus2, spkr_i2s, ssbi1, ssbi2, ssbi_ext_gps,
+		    ssbi_pmic2, ssbi_qpa1, ssbi_ts, tsif1, tsif2, ts_eoc,
+		    usb_fs1, usb_fs1_oe, usb_fs1_oe_n, usb_fs2, usb_fs2_oe,
+		    usb_fs2_oe_n, vfe_camif_timer1_a, vfe_camif_timer1_b,
+		    vfe_camif_timer2, vfe_camif_timer3_a, vfe_camif_timer3_b,
+		    vfe_camif_timer4_a, vfe_camif_timer4_b, vfe_camif_timer4_c,
+		    vfe_camif_timer5_a, vfe_camif_timer5_b, vfe_camif_timer6_a,
+		    vfe_camif_timer6_b, vfe_camif_timer6_c, vfe_camif_timer7_a,
+		    vfe_camif_timer7_b, vfe_camif_timer7_c, wlan
+
+- 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@800000 {
+		compatible = "qcom,msm8960-pinctrl";
+		reg = <0x800000 0x4000>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupts = <0 16 0x4>;
+
+		gsbi8_uart: gsbi8-uart {
+			mux {
+				pins = "gpio34", "gpio35";
+				function = "gsbi8";
+			};
+
+			tx {
+				pins = "gpio34";
+				drive-strength = <4>;
+				bias-disable;
+			};
+
+			rx {
+				pins = "gpio35";
+				drive-strength = <2>;
+				bias-pull-up;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ Valid values for function are:
   cam_mckl0, cam_mclk1, cam_mclk2, cam_mclk3, mdp_vsync, hdmi_cec, hdmi_ddc,
   hdmi_hpd, edp_hpd, gp_pdm0, gp_pdm1, gp_pdm2, gp_pdm3, gp0_clk, gp1_clk,
   gp_mn, tsif1, tsif2, hsic, grfc, audio_ref_clk, qua_mi2s, pri_mi2s, spkr_mi2s,
-  ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus
+  ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus, gpio
 
   (Note that this is not yet the complete list of functions)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@ Required Properties:
     - "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller.
     - "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
     - "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
+    - "renesas,pfc-r8a7791": for R8A7791 (R-Car M2) compatible pin-controller.
     - "renesas,pfc-sh7372": for SH7372 (SH-Mobile AP4) compatible pin-controller.
     - "renesas,pfc-sh73a0": for SH73A0 (SH-Mobile AG5) compatible pin-controller.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@ defined as gpio sub-nodes of the pinmux
 Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
 		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
+		       "rockchip,rk3288-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
 	 "general register files"
 
@@ -36,7 +37,7 @@ Deprecated properties for iomux controll
 	 Use rockchip,grf and rockchip,pmu described above instead.
 
 Required properties for gpio sub nodes:
-  - compatible: "rockchip,gpio-bank", "rockchip,rk3188-gpio-bank0"
+  - compatible: "rockchip,gpio-bank"
   - reg: register of the gpio bank (different than the iomux registerset)
   - interrupts: base interrupt of the gpio bank in the interrupt controller
   - clocks: clock that drives this bank
@@ -50,6 +51,7 @@ Required properties for gpio sub nodes:
     bindings/interrupt-controller/interrupts.txt
 
 Deprecated properties for gpio sub nodes:
+  - compatible: "rockchip,rk3188-gpio-bank0"
   - reg: second element: separate pull register for rk3188 bank0, use
 	 rockchip,pmu described above instead
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,11 @@ Required Properties:
 - Pin mux/config groups as child nodes: The pin mux (selecting pin function
   mode) and pin config (pull up/down, driver strength) settings are represented
   as child nodes of the pin-controller node. There should be atleast one
-  child node and there is no limit on the count of these child nodes.
+  child node and there is no limit on the count of these child nodes. It is
+  also possible for a child node to consist of several further child nodes
+  to allow grouping multiple pinctrl groups into one. The format of second
+  level child nodes is exactly the same as for first level ones and is
+  described below.
 
   The child node should contain a list of pin(s) on which a particular pin
   function selection or pin configuration (or both) have to applied. This
@@ -71,6 +75,7 @@ Required Properties:
   "samsung,pins" property of the child node. The following pin configuration
   properties are supported.
 
+  - samsung,pin-val: Initial value of pin output buffer.
   - samsung,pin-pud: Pull up/down configuration.
   - samsung,pin-drv: Drive strength configuration.
   - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
@@ -249,6 +254,23 @@ Example 1: A pin-controller node with pi
 			samsung,pin-pud = <3>;
 			samsung,pin-drv = <0>;
 		};
+
+		sd4_bus8: sd4-bus-width8 {
+			part-1 {
+				samsung,pins = "gpk0-3", "gpk0-4",
+						"gpk0-5", "gpk0-6";
+				samsung,pin-function = <3>;
+				samsung,pin-pud = <3>;
+				samsung,pin-drv = <3>;
+			};
+			part-2 {
+				samsung,pins = "gpk1-3", "gpk1-4",
+						"gpk1-5", "gpk1-6";
+				samsung,pin-function = <4>;
+				samsung,pin-pud = <4>;
+				samsung,pin-drv = <3>;
+			};
+		};
 	};
 
 Example 2: A pin-controller node with external wakeup interrupt controller node.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/power/rx51-battery.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/power/rx51-battery.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/power/rx51-battery.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/power/rx51-battery.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,25 @@
+Binding for Nokia N900 battery
+
+The Nokia N900 battery status can be read via the TWL4030's A/D converter.
+
+Required properties:
+- compatible: Should contain one of the following:
+ * "nokia,n900-battery"
+- io-channels: Should contain IIO channel specifiers
+               for each element in io-channel-names.
+- io-channel-names: Should contain the following values:
+ * "temp" - The ADC channel for temperature reading
+ * "bsi"  - The ADC channel for battery size identification
+ * "vbat" - The ADC channel to measure the battery voltage
+
+Example from Nokia N900:
+
+battery: n900-battery {
+	compatible = "nokia,n900-battery";
+	io-channels = <&twl4030_madc 0>,
+		      <&twl4030_madc 4>,
+		      <&twl4030_madc 12>;
+	io-channel-names = "temp",
+			   "bsi",
+			   "vbat";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2014-09-28 17:29:07.000000000 -0400
@@ -84,3 +84,19 @@ Example:
 		compatible = "fsl,bsc9132qds-fpga", "fsl,fpga-qixis-i2c";
 		reg = <0x66>;
 	};
+
+* Freescale on-board CPLD
+
+Some Freescale boards like T1040RDB have an on board CPLD connected.
+
+Required properties:
+- compatible: Should be a board-specific string like "fsl,<board>-cpld"
+  Example:
+	"fsl,t1040rdb-cpld", "fsl,t1042rdb-cpld", "fsl,t1042rdb_pi-cpld"
+- reg: should describe CPLD registers
+
+Example:
+	cpld@3,0 {
+		compatible = "fsl,t1040rdb-cpld";
+		reg = <3 0 0x300>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,20 @@
+Rockchip PWM controller
+
+Required properties:
+ - compatible: should be "rockchip,<name>-pwm"
+   "rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
+   "rockchip,rk3288-pwm": found on RK3288 SoC
+   "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
+ - reg: physical base address and length of the controller's registers
+ - clocks: phandle and clock specifier of the PWM reference clock
+ - #pwm-cells: should be 2. See pwm.txt in this directory for a
+   description of the cell format.
+
+Example:
+
+	pwm0: pwm@20030000 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20030000 0x10>;
+		clocks = <&cru PCLK_PWM01>;
+		#pwm-cells = <2>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/pwm/pwm-st.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pwm/pwm-st.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/pwm/pwm-st.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/pwm/pwm-st.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+STMicroelectronics PWM driver bindings
+--------------------------------------
+
+Required parameters:
+- compatible :		"st,pwm"
+- #pwm-cells : 		Number of cells used to specify a PWM. First cell
+			specifies the per-chip index of the PWM to use and the
+			second cell is the period in nanoseconds - fixed to 2
+			for STiH41x.
+- reg :			Physical base address and length of the controller's
+			registers.
+- pinctrl-names: 	Set to "default".
+- pinctrl-0: 		List of phandles pointing to pin configuration nodes
+			for PWM module.
+			For Pinctrl properties, please refer to [1].
+- clock-names: 		Set to "pwm".
+- clocks: 		phandle of the clock used by the PWM module.
+			For Clk properties, please refer to [2].
+
+Optional properties:
+- st,pwm-num-chan:	Number of available channels. If not passed, the driver
+			will consider single channel by default.
+
+[1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Example:
+
+pwm1: pwm@fe510000 {
+	compatible = "st,pwm";
+	reg = <0xfe510000 0x68>;
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1_chan0_default
+		     &pinctrl_pwm1_chan1_default
+		     &pinctrl_pwm1_chan2_default
+		     &pinctrl_pwm1_chan3_default>;
+	clocks = <&clk_sysin>;
+	clock-names = "pwm";
+	st,pwm-num-chan = <4>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/act8865-regulator.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/act8865-regulator.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/act8865-regulator.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,16 @@
-ACT8865 regulator
+ACT88xx regulators
 -------------------
 
 Required properties:
-- compatible: "active-semi,act8865"
+- compatible: "active-semi,act8846" or "active-semi,act8865"
 - reg: I2C slave address
 
 Any standard regulator properties can be used to configure the single regulator.
 
 The valid names for regulators are:
+	- for act8846:
+	REG1, REG2, REG3, REG4, REG5, REG6, REG7, REG8, REG9, REG10, REG11, REG12
+	- for act8865:
 	DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4.
 
 Example:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@ Required properties:
   ti,twl6037-pmic
   ti,tps65913-pmic
   ti,tps65914-pmic
+  ti,tps65917-pmic
 and also the generic series names
   ti,palmas-pmic
 - interrupt-parent : The parent interrupt controller which is palmas.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@ as per the datasheet of s5m8767.
 
 	- LDOn
 		  - valid values for n are 1 to 28
-		  - Example: LDO1, LD02, LDO28
+		  - Example: LDO1, LDO2, LDO28
 	- BUCKn
 		  - valid values for n are 1 to 9.
 		  - Example: BUCK1, BUCK2, BUCK9
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/tps65090.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/tps65090.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/tps65090.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/tps65090.txt	2014-09-28 17:29:07.000000000 -0400
@@ -45,8 +45,8 @@ Example:
 		infet5-supply = <&some_reg>;
 		infet6-supply = <&some_reg>;
 		infet7-supply = <&some_reg>;
-		vsys_l1-supply = <&some_reg>;
-		vsys_l2-supply = <&some_reg>;
+		vsys-l1-supply = <&some_reg>;
+		vsys-l2-supply = <&some_reg>;
 
 		regulators {
 			dcdc1 {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+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
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+	xyz: regulator@0 {
+		compatible = "ti,tps65218-dcdc1";
+		regulator-min-microvolt  = <1000000>;
+		regulator-max-microvolt  = <3000000>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/cdns,uart.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/cdns,uart.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/cdns,uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/cdns,uart.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,20 @@
+Binding for Cadence UART Controller
+
+Required properties:
+- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- reg: Should contain UART controller registers location and length.
+- interrupts: Should contain UART controller interrupts.
+- clocks: Must contain phandles to the UART clocks
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Tuple to identify input clocks, must contain "uart_clk" and "pclk"
+  See ../clocks/clock-bindings.txt for details.
+
+
+Example:
+	uart@e0000000 {
+		compatible = "cdns,uart-r1p8";
+		clocks = <&clkc 23>, <&clkc 40>;
+		clock-names = "uart_clk", "pclk";
+		reg = <0xE0000000 0x1000>;
+		interrupts = <0 27 4>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/efm32-uart.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/efm32-uart.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/efm32-uart.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/efm32-uart.txt	2014-09-28 17:29:07.000000000 -0400
@@ -6,7 +6,7 @@ Required properties:
 - interrupts : Should contain uart interrupt
 
 Optional properties:
-- efm32,location : Decides the location of the USART I/O pins.
+- energymicro,location : Decides the location of the USART I/O pins.
   Allowed range : [0 .. 5]
   Default: 0
 
@@ -16,5 +16,5 @@ uart@0x4000c400 {
 	compatible = "energymicro,efm32-uart";
 	reg = <0x4000c400 0x400>;
 	interrupts = <15>;
-	efm32,location = <0>;
+	energymicro,location = <0>;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/fsl-lpuart.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/fsl-lpuart.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/fsl-lpuart.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,11 @@
 * Freescale low power universal asynchronous receiver/transmitter (lpuart)
 
 Required properties:
-- compatible : Should be "fsl,<soc>-lpuart"
+- compatible :
+  - "fsl,vf610-lpuart" for lpuart compatible with the one integrated
+    on Vybrid vf610 SoC with 8-bit register organization
+  - "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
+    on LS1021A SoC with 32-bit big-endian register organization
 - reg : Address and length of the register set for the device
 - interrupts : Should contain uart interrupt
 - clocks : phandle + clock specifier pairs, one for each entry in clock-names
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/samsung_uart.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/samsung_uart.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/samsung_uart.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/samsung_uart.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,14 +1,58 @@
 * Samsung's UART Controller
 
-The Samsung's UART controller is used for interfacing SoC with serial communicaion
-devices.
+The Samsung's UART controller is used for interfacing SoC with serial
+communicaion devices.
 
 Required properties:
-- compatible: should be
-  - "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
+- compatible: should be one of following:
+  - "samsung,exynos4210-uart" -  Exynos4210 SoC,
+  - "samsung,s3c2410-uart" - compatible with ports present on S3C2410 SoC,
+  - "samsung,s3c2412-uart" - compatible with ports present on S3C2412 SoC,
+  - "samsung,s3c2440-uart" - compatible with ports present on S3C2440 SoC,
+  - "samsung,s3c6400-uart" - compatible with ports present on S3C6400 SoC,
+  - "samsung,s5pv210-uart" - compatible with ports present on S5PV210 SoC.
 
 - reg: base physical address of the controller and length of memory mapped
   region.
 
-- interrupts: interrupt number to the cpu. The interrupt specifier format depends
-  on the interrupt controller parent.
+- interrupts: a single interrupt signal to SoC interrupt controller,
+  according to interrupt bindings documentation [1].
+
+- clock-names: input names of clocks used by the controller:
+  - "uart" - controller bus clock,
+  - "clk_uart_baudN" - Nth baud base clock input (N = 0, 1, ...),
+    according to SoC User's Manual (only N = 0 is allowedfor SoCs without
+    internal baud clock mux).
+- clocks: phandles and specifiers for all clocks specified in "clock-names"
+  property, in the same order, according to clock bindings documentation [2].
+
+[1] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional properties:
+- samsung,uart-fifosize: The fifo size supported by the UART channel
+
+Note: Each Samsung UART should have an alias correctly numbered in the
+"aliases" node, according to serialN format, where N is the port number
+(non-negative decimal integer) as specified by User's Manual of respective
+SoC.
+
+Example:
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+Example:
+	uart1: serial@7f005400 {
+		compatible = "samsung,s3c6400-uart";
+		reg = <0x7f005400 0x100>;
+		interrupt-parent = <&vic1>;
+		interrupts = <6>;
+		clock-names = "uart", "clk_uart_baud2",
+				"clk_uart_baud3";
+		clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+				<&clocks SCLK_UART>;
+		samsung,uart-fifosize = <16>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,9 +4,18 @@ Required properties:
 - compatible : "snps,dw-apb-uart"
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
+
+Clock handling:
+The clock rate of the input clock needs to be supplied by one of
 - clock-frequency : the input clock frequency for the UART.
+- clocks : phandle to the input clock
+
+The supplying peripheral clock can also be handled, needing a second property
+- clock-names: tuple listing input clock names.
+	Required elements: "baudclk", "apb_pclk"
 
 Optional properties:
+- resets : phandle to the parent reset controller.
 - reg-shift : quantity to shift the register offsets by.  If this property is
   not present then the register offsets are not shifted.
 - reg-io-width : the size (in bytes) of the IO accesses that should be
@@ -22,4 +31,27 @@ Example:
 		interrupts = <10>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
+	};
+
+Example with one clock:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clocks = <&baudclk>;
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+Example with two clocks:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clocks = <&baudclk>, <&apb_pclk>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 ADI AXI-SPDIF controller
 
 Required properties:
- - compatible : Must be "adi,axi-spdif-1.00.a"
+ - compatible : Must be "adi,axi-spdif-tx-1.00.a"
  - reg : Must contain SPDIF core's registers location and length
  - clocks : Pairs of phandle and specifier referencing the controller's clocks.
    The controller expects two clocks, the clock used for the AXI interface and
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/ak5386.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/ak5386.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/ak5386.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/ak5386.txt	2014-09-28 17:29:07.000000000 -0400
@@ -10,10 +10,14 @@ Optional properties:
 
   - reset-gpio : a GPIO spec for the reset/power down pin.
 		 If specified, it will be deasserted at probe time.
+  - va-supply : a regulator spec, providing 5.0V
+  - vd-supply : a regulator spec, providing 3.3V
 
 Example:
 
 spdif: ak5386@0 {
 	compatible = "asahi-kasei,ak5386";
 	reset-gpio = <&gpio0 23>;
+	va-supply = <&vdd_5v0_reg>;
+	vd-supply = <&vdd_3v3_reg>;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/cs4265.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/cs4265.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/cs4265.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/cs4265.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+CS4265 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "cirrus,cs4265"
+
+  - reg : the I2C address of the device for I2C. The I2C address depends on
+          the state of the AD0 pin.  If AD0 is high, the i2c address is 0x4f.
+          If it is low, the i2c address is 0x4e.
+
+Optional properties:
+
+  - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the codec starts.
+
+Examples:
+
+codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
+	compatible = "cirrus,cs4265";
+	reg = <0x4f>;
+};
+
+
+codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
+	compatible = "cirrus,cs4265";
+	reg = <0x4e>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/fsl,asrc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/fsl,asrc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/fsl,asrc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/fsl,asrc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,60 @@
+Freescale Asynchronous Sample Rate Converter (ASRC) Controller
+
+The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
+signal associated with an input clock into a signal associated with a different
+output clock. The driver currently works as a Front End of DPCM with other Back
+Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
+three substreams within totally 10 channels.
+
+Required properties:
+
+  - compatible		: Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
+
+  - reg			: Offset and length of the register set for the device.
+
+  - interrupts		: Contains the spdif interrupt.
+
+  - dmas		: Generic dma devicetree binding as described in
+			  Documentation/devicetree/bindings/dma/dma.txt.
+
+  - dma-names		: Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
+
+  - clocks		: Contains an entry for each entry in clock-names.
+
+  - clock-names		: Contains the following entries
+	"mem"		  Peripheral access clock to access registers.
+	"ipg"		  Peripheral clock to driver module.
+	"asrck_<0-f>"	  Clock sources for input and output clock.
+
+   - big-endian		: If this property is absent, the little endian mode
+			  will be in use as default. Otherwise, the big endian
+			  mode will be in use for all the device registers.
+
+   - fsl,asrc-rate	: Defines a mutual sample rate used by DPCM Back Ends.
+
+   - fsl,asrc-width	: Defines a mutual sample width used by DPCM Back Ends.
+
+Example:
+
+asrc: asrc@02034000 {
+	compatible = "fsl,imx53-asrc";
+	reg = <0x02034000 0x4000>;
+	interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks 107>, <&clks 107>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 107>, <&clks 0>, <&clks 0>;
+	clock-names = "mem", "ipg", "asrck0",
+		"asrck_1", "asrck_2", "asrck_3", "asrck_4",
+		"asrck_5", "asrck_6", "asrck_7", "asrck_8",
+		"asrck_9", "asrck_a", "asrck_b", "asrck_c",
+		"asrck_d", "asrck_e", "asrck_f";
+	dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+	     <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+	dma-names = "rxa", "rxb", "rxc",
+		"txa", "txb", "txc";
+	fsl,asrc-rate  = <48000>;
+	fsl,asrc-width = <16>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/max98090.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/max98090.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/max98090.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/max98090.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,7 @@ This device supports I2C only.
 
 Required properties:
 
-- compatible : "maxim,max98090".
+- compatible : "maxim,max98090" or "maxim,max98091".
 
 - reg : The I2C address of the device.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/renesas,rsnd.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/renesas,rsnd.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/renesas,rsnd.txt	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,9 @@ Required properties:
 - rcar_sound,src		: Should contain SRC feature.
 				  The number of SRC subnode should be same as HW.
 				  see below for detail.
+- rcar_sound,dvc		: Should contain DVC feature.
+				  The number of DVC subnode should be same as HW.
+				  see below for detail.
 - rcar_sound,dai		: DAI contents.
 				  The number of DAI subnode should be same as HW.
 				  see below for detail.
@@ -21,6 +24,7 @@ SSI subnode properties:
 - interrupts			: Should contain SSI interrupt for PIO transfer
 - shared-pin			: if shared clock pin
 - pio-transfer			: use PIO transfer mode
+- no-busif			: BUSIF is not ussed when [mem -> SSI] via DMA case
 
 SRC subnode properties:
 no properties at this point
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
 		<0 0xec540000 0 0x1000>, /* SSIU */
 		<0 0xec541000 0 0x1280>; /* SSI */
 
+	rcar_sound,dvc {
+		dvc0: dvc@0 { };
+		dvc1: dvc@1 { };
+	};
+
 	rcar_sound,src {
 		src0: src@0 { };
 		src1: src@1 { };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/rockchip-i2s.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/rockchip-i2s.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/rockchip-i2s.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,37 @@
+* Rockchip I2S controller
+
+The I2S bus (Inter-IC sound bus) is a serial link for digital
+audio data transfer between devices in the system.
+
+Required properties:
+
+- compatible: should be one of the followings
+   - "rockchip,rk3066-i2s": for rk3066
+   - "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+   - "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: should contain the I2S interrupt.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "tx" and "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
+- clock-names: should contain followings:
+   - "i2s_hclk": clock for I2S BUS
+   - "i2s_clk" : clock for I2S controller
+
+Example for rk3288 I2S controller:
+
+i2s@ff890000 {
+	compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
+	reg = <0xff890000 0x10000>;
+	interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	dmas = <&pdma1 0>, <&pdma1 1>;
+	dma-names = "tx", "rx";
+	clock-names = "i2s_hclk", "i2s_clk";
+	clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,35 @@
+Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
+
+Required properties:
+ - compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
+		"samsung,odroidu3-audio" - for Odroid U3 board
+ - samsung,model : the user-visible name of this sound complex
+ - samsung,i2s-controller : the phandle of the I2S controller
+ - samsung,audio-codec : the phandle of the MAX98090 audio codec
+ - 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 MAX98090's pins (as
+   documented in its binding), and the jacks on the board
+   For Odroid X2:
+     * Headphone Jack
+     * Mic Jack
+     * DMIC
+
+   For Odroid U3:
+     * Headphone Jack
+     * Speakers
+
+Example:
+
+sound {
+	compatible = "samsung,odroidu3-audio";
+	samsung,i2s-controller = <&i2s0>;
+	samsung,audio-codec = <&max98090>;
+	samsung,model = "Odroid-X2";
+	samsung,audio-routing =
+		"Headphone Jack", "HPL",
+		"Headphone Jack", "HPR",
+		"IN1", "Mic Jack",
+		"Mic Jack", "MICBIAS";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/sirf-usp.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/sirf-usp.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/sirf-usp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/sirf-usp.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,27 @@
+* SiRF SoC USP module
+
+Required properties:
+- compatible: "sirf,prima2-usp-pcm"
+- reg: Base address and size entries:
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+
+  One of the DMA channels will be responsible for transmission (should be
+  named "tx") and one for reception (should be named "rx").
+
+- clocks: USP controller clock source
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+
+Example:
+usp0: usp@b0080000 {
+	compatible = "sirf,prima2-usp-pcm";
+	reg = <0xb0080000 0x10000>;
+	clocks = <&clks 28>;
+	dmas = <&dmac1 1>, <&dmac1 2>;
+	dma-names = "rx", "tx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usp0_only_utfs_pins_a>;
+};
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/snow.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/snow.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/snow.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/snow.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,15 +3,20 @@ Audio Binding for Snow boards
 Required properties:
 - compatible : Can be one of the following,
 			"google,snow-audio-max98090" or
+			"google,snow-audio-max98091" or
 			"google,snow-audio-max98095"
 - samsung,i2s-controller: The phandle of the Samsung I2S controller
 - samsung,audio-codec: The phandle of the audio codec
 
+Optional:
+- samsung,model: The name of the sound-card
+
 Example:
 
 sound {
 		compatible = "google,snow-audio-max98095";
 
+		samsung,model = "Snow-I2S-MAX98095";
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&max98095>;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/tas2552.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/tas2552.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/tas2552.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/tas2552.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+Texas Instruments - tas2552 Codec module
+
+The tas2552 serial control bus communicates through I2C protocols
+
+Required properties:
+	- compatible - One of:
+		"ti,tas2552" - TAS2552
+	- reg -  I2C slave address
+	- supply-*: Required supply regulators are:
+		"vbat"		battery voltage
+		"iovdd"		I/O Voltage
+		"avdd"		Analog DAC Voltage
+
+Optional properties:
+	- enable-gpio - gpio pin to enable/disable the device
+
+Example:
+
+tas2552: tas2552@41 {
+	compatible = "ti,tas2552";
+	reg = <0x41>;
+	enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+};
+
+For more product information please see the link below:
+http://www.ti.com/product/TAS2552
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/ti,tas5086.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/ti,tas5086.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/ti,tas5086.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/ti,tas5086.txt	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,9 @@ Optional properties:
 
 			Most systems should not set any of these properties.
 
+ - avdd-supply:         Power supply for AVDD, providing 3.3V
+ - dvdd-supply:         Power supply for DVDD, providing 3.3V
+
 Examples:
 
 	i2c_bus {
@@ -39,5 +42,7 @@ Examples:
 			reg = <0x1b>;
 			reset-gpio = <&gpio 23 0>;
 			ti,charge-period = <156000>;
+			avdd-supply = <&vdd_3v3_reg>;
+			dvdd-supply = <&vdd_3v3_reg>;
 		};
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/wm8904.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/wm8904.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/sound/wm8904.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/sound/wm8904.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,33 @@
+WM8904 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+  - compatible: "wlf,wm8904"
+  - reg: the I2C address of the device.
+  - clock-names: "mclk"
+  - clocks: reference to
+    <Documentation/devicetree/bindings/clock/clock-bindings.txt>
+
+Pins on the device (for linking into audio routes):
+
+  * IN1L
+  * IN1R
+  * IN2L
+  * IN2R
+  * IN3L
+  * IN3R
+  * HPOUTL
+  * HPOUTR
+  * LINEOUTL
+  * LINEOUTR
+  * MICBIAS
+
+Examples:
+
+codec: wm8904@1a {
+	compatible = "wlf,wm8904";
+	reg = <0x1a>;
+	clocks = <&pck0>;
+	clock-names = "mclk";
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/efm32-spi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/efm32-spi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/efm32-spi.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/efm32-spi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -10,11 +10,12 @@ Required properties:
 - cs-gpios: see spi-bus.txt
 
 Recommended properties :
-- efm32,location: Value to write to the ROUTE register's LOCATION bitfield to
-                  configure the pinmux for the device, see datasheet for values.
-                  If "efm32,location" property is not provided, keeping what is
-                  already configured in the hardware, so its either the reset
-                  default 0 or whatever the bootloader did.
+- energymicro,location: Value to write to the ROUTE register's LOCATION
+                        bitfield to configure the pinmux for the device, see
+                        datasheet for values.
+                        If this property is not provided, keeping what is
+                        already configured in the hardware, so its either the
+                        reset default 0 or whatever the bootloader did.
 
 Example:
 
@@ -26,7 +27,7 @@ spi1: spi@0x4000c400 { /* USART1 */
 	interrupts = <15 16>;
 	clocks = <&cmu 20>;
 	cs-gpios = <&gpio 51 1>; // D3
-	efm32,location = <1>;
+	energymicro,location = <1>;
 	status = "ok";
 
 	ks8851@0 {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz,
 data path from 4 bits to 32 bits and numerous protocol variants.
 
 Required properties:
-- compatible:     Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1"
+- compatible:     Should contain:
+		  "qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064.
+		  "qcom,spi-qup-v2.1.1" for 8974 and later
+		  "qcom,spi-qup-v2.2.1" for 8974 v2 and later.
+
 - reg:            Should contain base register location and length
 - interrupts:     Interrupt number used by this controller
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
+
+Required properties:
+- compatible : "snps,dw-apb-ssi"
+- reg : The register base for the controller.
+- interrupts : One interrupt, used by the controller.
+- #address-cells : <1>, as required by generic SPI binding.
+- #size-cells : <0>, also as required by generic SPI binding.
+
+Optional properties:
+- cs-gpios : Specifies the gpio pis to be used for chipselects.
+- num-cs : The number of chipselects. If omitted, this will default to 4.
+
+Child nodes as per the generic SPI binding.
+
+Example:
+
+	spi@fff00000 {
+		compatible = "snps,dw-apb-ssi";
+		reg = <0xfff00000 0x1000>;
+		interrupts = <0 154 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		num-cs = <2>;
+		cs-gpios = <&gpio0 13 0>,
+			   <&gpio0 14 0>;
+	};
+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-davinci.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-davinci.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-davinci.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-davinci.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,8 @@ Required properties:
 	- "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family
 	- "ti,da830-spi" for SPI used similar to that on DA8xx SoC family
 - reg: Offset and length of SPI controller register space
-- num-cs: Number of chip selects
+- num-cs: Number of chip selects. This includes internal as well as
+	GPIO chip selects.
 - ti,davinci-spi-intr-line: interrupt line used to connect the SPI
 	IP to the interrupt controller within the SoC. Possible values
 	are 0 and 1. Manual says one of the two possible interrupt
@@ -17,6 +18,12 @@ Required properties:
 - interrupts: interrupt number mapped to CPU.
 - clocks: spi clk phandle
 
+Optional:
+- cs-gpios: gpio chip selects
+	For example to have 3 internal CS and 2 GPIO CS, user could define
+	cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>;
+	where first three are internal CS and last two are GPIO CS.
+
 Example of a NOR flash slave device (n25q032) connected to DaVinci
 SPI controller device over the SPI bus.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-rockchip.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-rockchip.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-rockchip.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-rockchip.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+* Rockchip SPI Controller
+
+The Rockchip SPI controller is used to interface with various devices such as flash
+and display controllers using the SPI communication interface.
+
+Required Properties:
+
+- compatible: should be one of the following.
+    "rockchip,rk3066-spi" for rk3066.
+    "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
+    "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
+- reg: physical base address of the controller and length of memory mapped
+       region.
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+              depends on the interrupt controller.
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Shall be "spiclk" for the transfer-clock, and "apb_pclk" for
+			   the peripheral clock.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+
+Optional Properties:
+
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+		Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "tx" and "rx" if present.
+
+
+Example:
+
+	spi0: spi@ff110000 {
+		compatible = "rockchip,rk3066-spi";
+		reg = <0xff110000 0x1000>;
+		dmas = <&pdma1 11>, <&pdma1 12>;
+		dma-names = "tx", "rx";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-samsung.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-samsung.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/spi/spi-samsung.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/spi/spi-samsung.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,6 @@ Required SoC Specific Properties:
 - compatible: should be one of the following.
     - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
     - samsung,s3c6410-spi: for s3c6410 platforms
-    - samsung,s5p6440-spi: for s5p6440 and s5p6450 platforms
     - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
     - samsung,exynos4210-spi: for exynos4 and exynos5 platforms
 
@@ -18,14 +17,11 @@ Required SoC Specific Properties:
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
   depends on the interrupt controller.
 
-[PRELIMINARY: the dma channel allocation will change once there are
-official DMA bindings]
-
-- tx-dma-channel: The dma channel specifier for tx operations. The format of
-  the dma specifier depends on the dma controller.
+- dmas : Two or more DMA channel specifiers following the convention outlined
+  in bindings/dma/dma.txt
 
-- rx-dma-channel: The dma channel specifier for rx operations. The format of
-  the dma specifier depends on the dma controller.
+- dma-names: Names for the dma channels. There must be at least one channel
+  named "tx" for transmit and named "rx" for receive.
 
 Required Board Specific Properties:
 
@@ -42,15 +38,13 @@ Optional Board Specific Properties:
 - num-cs: Specifies the number of chip select lines supported. If
   not specified, the default number of chip select lines is set to 1.
 
+- cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt)
+
 SPI Controller specific data in SPI slave nodes:
 
 - The spi slave nodes should provide the following information which is required
   by the spi controller.
 
-  - cs-gpio: A gpio specifier that specifies the gpio line used as
-    the slave select line by the spi controller. The format of the gpio
-    specifier depends on the gpio controller.
-
   - samsung,spi-feedback-delay: The sampling phase shift to be applied on the
     miso line (to account for any lag in the miso line). The following are the
     valid values.
@@ -74,8 +68,11 @@ Example:
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x12d20000 0x100>;
 		interrupts = <0 66 0>;
-		tx-dma-channel = <&pdma0 5>;
-		rx-dma-channel = <&pdma0 4>;
+		dmas = <&pdma0 5
+			&pdma0 4>;
+		dma-names = "tx", "rx";
+		#address-cells = <1>;
+		#size-cells = <0>;
 	};
 
 - Board Specific Portion:
@@ -85,6 +82,7 @@ Example:
 		#size-cells = <0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi0_bus>;
+		cs-gpios = <&gpa2 5 0>;
 
 		w25q80bw@0 {
 			#address-cells = <1>;
@@ -94,7 +92,6 @@ Example:
 			spi-max-frequency = <10000>;
 
 			controller-data {
-				cs-gpio = <&gpa2 5 1 0 3>;
 				samsung,spi-feedback-delay = <0>;
 			};
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,9 @@ Required properties:
  - fsl,data-width : should be <18> or <24>
  - port: A port node with endpoint definitions as defined in
    Documentation/devicetree/bindings/media/video-interfaces.txt.
+   On i.MX5, the internal two-input-multiplexer is used.
+   Due to hardware limitations, only one port (port@[0,1])
+   can be used for each channel (lvds-channel@[0,1], respectively)
    On i.MX6, there should be four ports (port@[0-3]) that correspond
    to the four LVDS multiplexer inputs.
 
@@ -78,6 +81,8 @@ ldb: ldb@53fa8008 {
 		      "di0", "di1";
 
 	lvds-channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		reg = <0>;
 		fsl,data-mapping = "spwg";
 		fsl,data-width = <24>;
@@ -86,7 +91,9 @@ ldb: ldb@53fa8008 {
 			/* ... */
 		};
 
-		port {
+		port@0 {
+			reg = <0>;
+
 			lvds0_in: endpoint {
 				remote-endpoint = <&ipu_di0_lvds0>;
 			};
@@ -94,6 +101,8 @@ ldb: ldb@53fa8008 {
 	};
 
 	lvds-channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		reg = <1>;
 		fsl,data-mapping = "spwg";
 		fsl,data-width = <24>;
@@ -102,7 +111,9 @@ ldb: ldb@53fa8008 {
 			/* ... */
 		};
 
-		port {
+		port@1 {
+			reg = <1>;
+
 			lvds1_in: endpoint {
 				remote-endpoint = <&ipu_di1_lvds1>;
 			};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/exynos-thermal.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/exynos-thermal.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/exynos-thermal.txt	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@
 ** Required properties:
 
 - compatible : One of the following:
+	       "samsung,exynos3250-tmu"
 	       "samsung,exynos4412-tmu"
 	       "samsung,exynos4210-tmu"
 	       "samsung,exynos5250-tmu"
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,13 @@
 * Renesas R-Car Thermal
 
 Required properties:
-- compatible		: "renesas,rcar-thermal"
+- compatible		: "renesas,thermal-<soctype>", "renesas,rcar-thermal"
+			  as fallback.
+			  Examples with soctypes are:
+			    - "renesas,thermal-r8a73a4" (R-Mobile AP6)
+			    - "renesas,thermal-r8a7779" (R-Car H1)
+			    - "renesas,thermal-r8a7790" (R-Car H2)
+			    - "renesas,thermal-r8a7791" (R-Car M2)
 - reg			: Address range of the thermal registers.
 			  The 1st reg will be recognized as common register
 			  if it has "interrupts".
@@ -12,18 +18,18 @@ Option properties:
 
 Example (non interrupt support):
 
-thermal@e61f0100 {
-	compatible = "renesas,rcar-thermal";
-	reg = <0xe61f0100 0x38>;
+thermal@ffc48000 {
+	compatible = "renesas,thermal-r8a7779", "renesas,rcar-thermal";
+	reg = <0xffc48000 0x38>;
 };
 
 Example (interrupt support):
 
 thermal@e61f0000 {
-	compatible = "renesas,rcar-thermal";
+	compatible = "renesas,thermal-r8a73a4", "renesas,rcar-thermal";
 	reg = <0xe61f0000 0x14
 		0xe61f0100 0x38
 		0xe61f0200 0x38
 		0xe61f0300 0x38>;
-	interrupts = <0 69 4>;
+	interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+Binding for Thermal Sensor driver for STMicroelectronics STi series of SoCs.
+
+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.
+clock-names : 	Should be "thermal".
+		  See: Documentation/devicetree/bindings/resource-names.txt
+clocks : 	Phandle of the clock used by the thermal sensor.
+		  See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+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>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+* Cirrus Logic CLPS711X Timer Counter
+
+Required properties:
+- compatible: Shall contain "cirrus,clps711x-timer".
+- reg       : Address and length of the register set.
+- interrupts: The interrupt number of the timer.
+- clocks    : phandle of timer reference clock.
+
+Note: Each timer should have an alias correctly numbered in "aliases" node.
+
+Example:
+	aliases {
+		timer0 = &timer1;
+		timer1 = &timer2;
+	};
+
+	timer1: timer@80000300 {
+		compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
+		reg = <0x80000300 0x4>;
+		interrupts = <8>;
+		clocks = <&clks 5>;
+	};
+
+	timer2: timer@80000340 {
+		compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
+		reg = <0x80000340 0x4>;
+		interrupts = <9>;
+		clocks = <&clks 6>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,17 @@
+Mediatek MT6577, MT6572 and MT6589 Timers
+---------------------------------------
+
+Required properties:
+- compatible: Should be "mediatek,mt6577-timer"
+- reg: Should contain location and length for timers register.
+- clocks: Clocks driving the timer hardware. This list should include two
+	clocks. The order is system clock and as second clock the RTC clock.
+
+Examples:
+
+	timer@10008000 {
+		compatible = "mediatek,mt6577-timer";
+		reg = <0x10008000 0x80>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&system_clk>, <&rtc_clk>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,cmt.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,cmt.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,cmt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,cmt.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
+inputs and programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channel indices represent the hardware
+position of the channel in the CMT and don't match the channel numbers in the
+datasheets.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
+    - "renesas,cmt-32" for the 32-bit CMT
+		(CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+		(CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48" for the 48-bit CMT
+		(CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+		(CMT[01] on r8a73a4, r8a7790 and r8a7791)
+
+  - reg: base address and length of the registers block for the timer module.
+  - interrupts: interrupt-specifier for the timer, one per channel.
+  - clocks: a list of phandle + clock-specifier pairs, one for each entry
+    in clock-names.
+  - clock-names: must contain "fck" for the functional clock.
+
+  - renesas,channels-mask: bitmask of the available channels.
+
+
+Example: R8A7790 (R-Car H2) CMT0 node
+
+	CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
+	them channels 0 and 1 in the documentation.
+
+	cmt0: timer@ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+		clock-names = "fck";
+
+		renesas,channels-mask = <0x60>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,mtu2.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,mtu2.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,mtu2.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,mtu2.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+* Renesas R-Car Multi-Function Timer Pulse Unit 2 (MTU2)
+
+The MTU2 is a multi-purpose, multi-channel timer/counter with configurable
+clock inputs and programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. The MTU2 hardware supports five channels indexed from 0 to 4.
+
+Required Properties:
+
+  - compatible: must contain "renesas,mtu2"
+
+  - reg: base address and length of the registers block for the timer module.
+
+  - interrupts: interrupt specifiers for the timer, one for each entry in
+    interrupt-names.
+  - interrupt-names: must contain one entry named "tgi?a" for each enabled
+    channel, where "?" is the channel index expressed as one digit from "0" to
+    "4".
+
+  - clocks: a list of phandle + clock-specifier pairs, one for each entry
+    in clock-names.
+  - clock-names: must contain "fck" for the functional clock.
+
+
+Example: R7S72100 (RZ/A1H) MTU2 node
+
+	mtu2: timer@fcff0000 {
+		compatible = "renesas,mtu2";
+		reg = <0xfcff0000 0x400>;
+		interrupts = <0 139 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 146 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 150 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 154 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 159 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tgi0a", "tgi1a", "tgi2a", "tgi3a", "tgi4a";
+		clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
+		clock-names = "fck";
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,tmu.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,tmu.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/timer/renesas,tmu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/timer/renesas,tmu.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+* Renesas R-Car Timer Unit (TMU)
+
+The TMU is a 32-bit timer/counter with configurable clock inputs and
+programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. The TMU hardware supports up to three channels.
+
+Required Properties:
+
+  - compatible: must contain "renesas,tmu"
+
+  - reg: base address and length of the registers block for the timer module.
+
+  - interrupts: interrupt-specifier for the timer, one per channel.
+
+  - clocks: a list of phandle + clock-specifier pairs, one for each entry
+    in clock-names.
+  - clock-names: must contain "fck" for the functional clock.
+
+Optional Properties:
+
+  - #renesas,channels: number of channels implemented by the timer, must be 2
+    or 3 (if not specified the value defaults to 3).
+
+
+Example: R8A7779 (R-Car H1) TMU0 node
+
+	tmu0: timer@ffd80000 {
+		compatible = "renesas,tmu";
+		reg = <0xffd80000 0x30>;
+		interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 33 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 34 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
+		clock-names = "fck";
+
+		#renesas,channels = <3>;
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be "fsl,imx27-usb"
 - reg: Should contain registers location and length
 - interrupts: Should contain controller interrupt
+- fsl,usbphy: phandle of usb phy that connects to the port
 
 Recommended properies:
 - phy_type: the type of the phy connected to the core. Should be one
@@ -12,7 +13,6 @@ Recommended properies:
 - dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
 
 Optional properties:
-- fsl,usbphy: phandler of usb phy that connects to the only one port
 - fsl,usbmisc: phandler of non-core register device, with one argument
   that indicate usb controller index
 - vbus-supply: regulator for vbus
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/mxs-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/mxs-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/mxs-phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/mxs-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ Required properties:
 	* "fsl,imx23-usbphy" for imx23 and imx28
 	* "fsl,imx6q-usbphy" for imx6dq and imx6dl
 	* "fsl,imx6sl-usbphy" for imx6sl
+	* "fsl,imx6sx-usbphy" for imx6sx
   "fsl,imx23-usbphy" is still a fallback for other strings
 - reg: Should contain registers location and length
 - interrupts: Should contain phy interrupt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,12 @@ Required properties :
      Present if phy_type == utmi.
    - ulpi-link: The clock Tegra provides to the ULPI PHY (cdev2).
      Present if phy_type == ulpi, and ULPI link mode is in use.
+ - resets : Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+ - reset-names : Must include the following entries:
+   - usb: The PHY's own reset signal.
+   - utmi-pads: The reset of the PHY containing the chip-wide UTMI pad control
+     registers. Required even if phy_type == ulpi.
 
 Required properties for phy_type == ulpi:
   - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
@@ -56,6 +62,8 @@ Optional properties:
       host means this is a host controller
       peripheral means it is device controller
       otg means it can operate as either ("on the go")
+  - nvidia,has-utmi-pad-registers : boolean indicates whether this controller
+    contains the UTMI pad control registers common to all USB controllers.
 
 VBUS control (required for dr_mode == otg, optional for dr_mode == host):
   - vbus-supply: regulator for VBUS
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,8 +9,9 @@ Required properties:
     register set for the device.
   - interrupts: one XHCI interrupt should be described here.
 
-Optional property:
+Optional properties:
   - clocks: reference to a clock
+  - usb3-lpm-capable: determines if platform is USB3 LPM capable
 
 Example:
 	usb@f0931000 {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@ using them to avoid name-space collision
 abilis	Abilis Systems
 active-semi	Active-Semi International Inc
 ad	Avionic Design GmbH
+adapteva	Adapteva, Inc.
 adi	Analog Devices, Inc.
 aeroflexgaisler	Aeroflex Gaisler AB
 ak	Asahi Kasei Corp.
@@ -42,6 +43,7 @@ dmo	Data Modul AG
 ebv	EBV Elektronik
 edt	Emerging Display Technologies
 emmicro	EM Microelectronic
+epcos	EPCOS AG
 epfl	Ecole Polytechnique FÃ©dÃ©rale de Lausanne
 epson	Seiko Epson Corp.
 est	ESTeem Wireless Modems
@@ -71,12 +73,14 @@ karo	Ka-Ro electronics GmbH
 keymile	Keymile GmbH
 lacie	LaCie
 lantiq	Lantiq Semiconductor
+lenovo	Lenovo Group Ltd.
 lg	LG Corporation
 linux	Linux-specific binding
 lsi	LSI Corp. (LSI Logic)
 lltc	Linear Technology Corporation
 marvell	Marvell Technology Group Ltd.
 maxim	Maxim Integrated Products
+mediatek	MediaTek Inc.
 micrel	Micrel Inc.
 microchip	Microchip Technology Inc.
 mosaixtech	Mosaix Technologies, Inc.
@@ -99,6 +103,7 @@ panasonic	Panasonic Corporation
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
+pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
@@ -122,6 +127,7 @@ sii	Seiko Instruments, Inc.
 sirf	SiRF Technology, Inc.
 smsc	Standard Microsystems Corporation
 snps 	Synopsys, Inc.
+solidrun	SolidRun
 spansion	Spansion Inc.
 st	STMicroelectronics
 ste	ST-Ericsson
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/analog-tv-connector.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/analog-tv-connector.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/analog-tv-connector.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/analog-tv-connector.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@ Analog TV Connector
 ===================
 
 Required properties:
-- compatible: "composite-connector" or "svideo-connector"
+- compatible: "composite-video-connector" or "svideo-connector"
 
 Optional properties:
 - label: a symbolic name for the connector
@@ -14,7 +14,7 @@ Example
 -------
 
 tv: connector {
-	compatible = "composite-connector";
+	compatible = "composite-video-connector";
 	label = "tv";
 
 	port {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/arm,pl11x.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/arm,pl11x.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/arm,pl11x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/arm,pl11x.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,109 @@
+* ARM PrimeCell Color LCD Controller PL110/PL111
+
+See also Documentation/devicetree/bindings/arm/primecell.txt
+
+Required properties:
+
+- compatible: must be one of:
+	"arm,pl110", "arm,primecell"
+	"arm,pl111", "arm,primecell"
+
+- reg: base address and size of the control registers block
+
+- interrupt-names: either the single entry "combined" representing a
+	combined interrupt output (CLCDINTR), or the four entries
+	"mbe", "vcomp", "lnbu", "fuf" representing the individual
+	CLCDMBEINTR, CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR interrupts
+
+- interrupts: contains an interrupt specifier for each entry in
+	interrupt-names
+
+- clock-names: should contain "clcdclk" and "apb_pclk"
+
+- clocks: contains phandle and clock specifier pairs for the entries
+	in the clock-names property. See
+	Documentation/devicetree/binding/clock/clock-bindings.txt
+
+Optional properties:
+
+- memory-region: phandle to a node describing memory (see
+	Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt)
+	to be used for the framebuffer; if not present, the framebuffer
+	may be located anywhere in the memory
+
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+	cell's memory interface can handle; if not present, the memory
+	interface is fast enough to handle all possible video modes
+
+Required sub-nodes:
+
+- port: describes LCD panel signals, following the common binding
+	for video transmitter interfaces; see
+	Documentation/devicetree/bindings/media/video-interfaces.txt;
+	when it is a TFT panel, the port's endpoint must define the
+	following property:
+
+	- arm,pl11x,tft-r0g0b0-pads: an array of three 32-bit values,
+		defining the way CLD pads are wired up; first value
+		contains index of the "CLD" external pin (pad) used
+		as R0 (first bit of the red component), second value
+	        index of the pad used as G0, third value index of the
+		pad used as B0, see also "LCD panel signal multiplexing
+		details" paragraphs in the PL110/PL111 Technical
+		Reference Manuals; this implicitly defines available
+		color modes, for example:
+		- PL111 TFT 4:4:4 panel:
+			arm,pl11x,tft-r0g0b0-pads = <4 15 20>;
+		- PL110 TFT (1:)5:5:5 panel:
+			arm,pl11x,tft-r0g0b0-pads = <1 7 13>;
+		- PL111 TFT (1:)5:5:5 panel:
+			arm,pl11x,tft-r0g0b0-pads = <3 11 19>;
+		- PL111 TFT 5:6:5 panel:
+			arm,pl11x,tft-r0g0b0-pads = <3 10 19>;
+		- PL110 and PL111 TFT 8:8:8 panel:
+			arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+		- PL110 and PL111 TFT 8:8:8 panel, R & B components swapped:
+			arm,pl11x,tft-r0g0b0-pads = <16 8 0>;
+
+
+Example:
+
+	clcd@10020000 {
+		compatible = "arm,pl111", "arm,primecell";
+		reg = <0x10020000 0x1000>;
+		interrupt-names = "combined";
+		interrupts = <0 44 4>;
+		clocks = <&oscclk1>, <&oscclk2>;
+		clock-names = "clcdclk", "apb_pclk";
+		max-memory-bandwidth = <94371840>; /* Bps, 1024x768@60 16bpp */
+
+		port {
+			clcd_pads: endpoint {
+				remote-endpoint = <&clcd_panel>;
+				arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+			};
+		};
+
+	};
+
+	panel {
+		compatible = "panel-dpi";
+
+		port {
+			clcd_panel: endpoint {
+				remote-endpoint = <&clcd_pads>;
+			};
+		};
+
+		panel-timing {
+			clock-frequency = <25175000>;
+			hactive = <640>;
+			hback-porch = <40>;
+			hfront-porch = <24>;
+			hsync-len = <96>;
+			vactive = <480>;
+			vback-porch = <32>;
+			vfront-porch = <11>;
+			vsync-len = <2>;
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/atmel,lcdc.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/atmel,lcdc.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/atmel,lcdc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/atmel,lcdc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,7 @@ Required properties (as per of_videomode
 
 Optional properties (as per of_videomode_helper):
  - atmel,lcdcon-backlight: enable backlight
+ - atmel,lcdcon-backlight-inverted: invert backlight PWM polarity
  - atmel,lcd-wiring-mode: lcd wiring mode "RGB" or "BRG"
  - atmel,power-control-gpio: gpio to power on or off the LCD (as many as needed)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+* Currus Logic CLPS711X Framebuffer
+
+Required properties:
+- compatible: Shall contain "cirrus,clps711x-fb".
+- reg       : Physical base address and length of the controller's registers +
+              location and size of the framebuffer memory.
+- clocks    : phandle + clock specifier pair of the FB reference clock.
+- display   : phandle to a display node as described in
+              Documentation/devicetree/bindings/video/display-timing.txt.
+              Additionally, the display node has to define properties:
+  - bits-per-pixel: Bits per pixel.
+  - ac-prescale   : LCD AC bias frequency. This frequency is the required
+                    AC bias frequency for a given manufacturer's LCD plate.
+  - cmap-invert   : Invert the color levels (Optional).
+
+Optional properties:
+- lcd-supply: Regulator for LCD supply voltage.
+
+Example:
+	fb: fb@800002c0 {
+		compatible = "cirrus,ep7312-fb", "cirrus,clps711x-fb";
+		reg = <0x800002c0 0xd44>, <0x60000000 0xc000>;
+		clocks = <&clks 2>;
+		lcd-supply = <&reg5v0>;
+		display = <&display>;
+	};
+
+	display: display {
+		model = "320x240x4";
+		native-mode = <&timing0>;
+		bits-per-pixel = <4>;
+		ac-prescale = <17>;
+
+		display-timings {
+			timing0: 320x240 {
+				hactive = <320>;
+				hback-porch = <0>;
+				hfront-porch = <0>;
+				hsync-len = <0>;
+				vactive = <240>;
+				vback-porch = <0>;
+				vfront-porch = <0>;
+				vsync-len = <0>;
+				clock-frequency = <6500000>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/exynos_dsim.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/exynos_dsim.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/exynos_dsim.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/exynos_dsim.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,9 @@
 Exynos MIPI DSI Master
 
 Required properties:
-  - compatible: "samsung,exynos4210-mipi-dsi"
+  - compatible: value should be one of the following
+		"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
+		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
   - reg: physical base address and length of the registers set for the device
   - interrupts: should contain DSI interrupt
   - clocks: list of clock specifiers, must contain an entry for each required
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/exynos_mixer.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/exynos_mixer.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/exynos_mixer.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/exynos_mixer.txt	2014-09-28 17:29:07.000000000 -0400
@@ -4,8 +4,9 @@ Required properties:
 - compatible: value should be one of the following:
 	1) "samsung,exynos5-mixer" <DEPRECATED>
 	2) "samsung,exynos4210-mixer"
-	3) "samsung,exynos5250-mixer"
-	4) "samsung,exynos5420-mixer"
+	3) "samsung,exynos4212-mixer"
+	4) "samsung,exynos5250-mixer"
+	5) "samsung,exynos5420-mixer"
 
 - reg: physical base address of the mixer and length of memory mapped
 	region.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/samsung-fimd.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/samsung-fimd.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/video/samsung-fimd.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/video/samsung-fimd.txt	2014-09-28 17:29:07.000000000 -0400
@@ -8,8 +8,6 @@ Required properties:
 - compatible: value should be one of the following
 		"samsung,s3c2443-fimd"; /* for S3C24XX SoCs */
 		"samsung,s3c6400-fimd"; /* for S3C64XX SoCs */
-		"samsung,s5p6440-fimd"; /* for S5P64X0 SoCs */
-		"samsung,s5pc100-fimd"; /* for S5PC100 SoC  */
 		"samsung,s5pv210-fimd"; /* for S5PV210 SoC */
 		"samsung,exynos4210-fimd"; /* for Exynos4 SoCs */
 		"samsung,exynos5250-fimd"; /* for Exynos5 SoCs */
@@ -44,6 +42,34 @@ Optional Properties:
 - display-timings: timing settings for FIMD, as described in document [1].
 		Can be used in case timings cannot be provided otherwise
 		or to override timings provided by the panel.
+- samsung,sysreg: handle to syscon used to control the system registers
+- i80-if-timings: timing configuration for lcd i80 interface support.
+  - cs-setup: clock cycles for the active period of address signal is enabled
+              until chip select is enabled.
+              If not specified, the default value(0) will be used.
+  - wr-setup: clock cycles for the active period of CS signal is enabled until
+              write signal is enabled.
+              If not specified, the default value(0) will be used.
+  - wr-active: clock cycles for the active period of CS is enabled.
+               If not specified, the default value(1) will be used.
+  - wr-hold: clock cycles for the active period of CS is disabled until write
+             signal is disabled.
+             If not specified, the default value(0) will be used.
+
+  The parameters are defined as:
+
+    VCLK(internal)  __|??????|_____|??????|_____|??????|_____|??????|_____|??
+                      :            :            :            :            :
+    Address Output  --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
+                      | cs-setup+1 |            :            :            :
+                      |<---------->|            :            :            :
+    Chip Select     ???????????????|____________:____________:____________|??
+                                   | wr-setup+1 |            | wr-hold+1  |
+                                   |<---------->|            |<---------->|
+    Write Enable    ????????????????????????????|____________|???????????????
+                                                | wr-active+1|
+                                                |<---------->|
+    Video Data      ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
 
 The device node can contain 'port' child nodes according to the bindings defined
 in [2]. The following are properties specific to those nodes:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt	2014-09-28 17:29:07.000000000 -0400
@@ -5,10 +5,15 @@ Required properties:
 - reg : Should contain WDT registers location and length
 - interrupts : Should contain WDT interrupt
 
+Optional property:
+- big-endian: If present the watchdog device's registers are implemented
+  in big endian mode, otherwise in little mode.
+
 Examples:
 
 wdt@73f98000 {
 	compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 	reg = <0x73f98000 0x4000>;
 	interrupts = <58>;
+	big-endian;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/changesets.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/changesets.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/changesets.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/changesets.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,40 @@
+A DT changeset is a method which allows one to apply changes
+in the live tree in such a way that either the full set of changes
+will be applied, or none of them will be. If an error occurs partway
+through applying the changeset, then the tree will be rolled back to the
+previous state. A changeset can also be removed after it has been
+applied.
+
+When a changeset is applied, all of the changes get applied to the tree
+at once before emitting OF_RECONFIG notifiers. This is so that the
+receiver sees a complete and consistent state of the tree when it
+receives the notifier.
+
+The sequence of a changeset is as follows.
+
+1. of_changeset_init() - initializes a changeset
+
+2. A number of DT tree change calls, of_changeset_attach_node(),
+of_changeset_detach_node(), of_changeset_add_property(),
+of_changeset_remove_property, of_changeset_update_property() to prepare
+a set of changes. No changes to the active tree are made at this point.
+All the change operations are recorded in the of_changeset 'entries'
+list.
+
+3. mutex_lock(of_mutex) - starts a changeset; The global of_mutex
+ensures there can only be one editor at a time.
+
+4. of_changeset_apply() - Apply the changes to the tree. Either the
+entire changeset will get applied, or if there is an error the tree will
+be restored to the previous state
+
+5. mutex_unlock(of_mutex) - All operations complete, release the mutex
+
+If a successfully applied changeset needs to be removed, it can be done
+with the following sequence.
+
+1. mutex_lock(of_mutex)
+
+2. of_changeset_revert()
+
+3. mutex_unlock(of_mutex)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/of_selftest.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/of_selftest.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/of_selftest.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/of_selftest.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,211 @@
+Open Firmware Device Tree Selftest
+----------------------------------
+
+Author: Gaurav Minocha <gaurav.minocha.os@gmail.com>
+
+1. Introduction
+
+This document explains how the test data required for executing OF selftest
+is attached to the live tree dynamically, independent of the machine's
+architecture.
+
+It is recommended to read the following documents before moving ahead.
+
+[1] Documentation/devicetree/usage-model.txt
+[2] http://www.devicetree.org/Device_Tree_Usage
+
+OF Selftest has been designed to test the interface (include/linux/of.h)
+provided to device driver developers to fetch the device information..etc.
+from the unflattened device tree data structure. This interface is used by
+most of the device drivers in various use cases.
+
+
+2. Test-data
+
+The Device Tree Source file (drivers/of/testcase-data/testcases.dts) contains
+the test data required for executing the unit tests automated in
+drivers/of/selftests.c. Currently, following Device Tree Source Include files
+(.dtsi) are included in testcase.dts:
+
+drivers/of/testcase-data/tests-interrupts.dtsi
+drivers/of/testcase-data/tests-platform.dtsi
+drivers/of/testcase-data/tests-phandle.dtsi
+drivers/of/testcase-data/tests-match.dtsi
+
+When the kernel is build with OF_SELFTEST enabled, then the following make rule
+
+$(obj)/%.dtb: $(src)/%.dts FORCE
+	$(call if_changed_dep, dtc)
+
+is used to compile the DT source file (testcase.dts) into a binary blob
+(testcase.dtb), also referred as flattened DT.
+
+After that, using the following rule the binary blob above is wrapped as an
+assembly file (testcase.dtb.S).
+
+$(obj)/%.dtb.S: $(obj)/%.dtb
+	$(call cmd, dt_S_dtb)
+
+The assembly file is compiled into an object file (testcase.dtb.o), and is
+linked into the kernel image.
+
+
+2.1. Adding the test data
+
+Un-flattened device tree structure:
+
+Un-flattened device tree consists of connected device_node(s) in form of a tree
+structure described below.
+
+// following struct members are used to construct the tree
+struct device_node {
+    ...
+    struct  device_node *parent;
+    struct  device_node *child;
+    struct  device_node *sibling;
+    struct  device_node *allnext;   /* next in list of all nodes */
+    ...
+ };
+
+Figure 1, describes a generic structure of machineâ€™s un-flattened device tree
+considering only child and sibling pointers. There exists another pointer,
+*parent, that is used to traverse the tree in the reverse direction. So, at
+a particular level the child node and all the sibling nodes will have a parent
+pointer pointing to a common node (e.g. child1, sibling2, sibling3, sibling4â€™s
+parent points to root node)
+
+root (â€˜/â€™)
+   |
+child1 -> sibling2 -> sibling3 -> sibling4 -> null
+   |         |           |           |
+   |         |           |          null
+   |         |           |
+   |         |        child31 -> sibling32 -> null
+   |         |           |          |
+   |         |          null       null
+   |         |
+   |      child21 -> sibling22 -> sibling23 -> null
+   |         |          |            |
+   |        null       null         null
+   |
+child11 -> sibling12 -> sibling13 -> sibling14 -> null
+   |           |           |            |
+   |           |           |           null
+   |           |           |
+  null        null       child131 -> null
+                           |
+                          null
+
+Figure 1: Generic structure of un-flattened device tree
+
+
+*allnext: it is used to link all the nodes of DT into a list. So, for the
+ above tree the list would be as follows:
+
+root->child1->child11->sibling12->sibling13->child131->sibling14->sibling2->
+child21->sibling22->sibling23->sibling3->child31->sibling32->sibling4->null
+
+Before executing OF selftest, it is required to attach the test data to
+machine's device tree (if present). So, when selftest_data_add() is called,
+at first it reads the flattened device tree data linked into the kernel image
+via the following kernel symbols:
+
+__dtb_testcases_begin - address marking the start of test data blob
+__dtb_testcases_end   - address marking the end of test data blob
+
+Secondly, it calls of_fdt_unflatten_device_tree() to unflatten the flattened
+blob. And finally, if the machineâ€™s device tree (i.e live tree) is present,
+then it attaches the unflattened test data tree to the live tree, else it
+attaches itself as a live device tree.
+
+attach_node_and_children() uses of_attach_node() to attach the nodes into the
+live tree as explained below. To explain the same, the test data tree described
+ in Figure 2 is attached to the live tree described in Figure 1.
+
+root (â€˜/â€™)
+    |
+ testcase-data
+    |
+ test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null
+    |               |                |                |
+ test-child01      null             null             null
+
+
+allnext list:
+
+root->testcase-data->test-child0->test-child01->test-sibling1->test-sibling2
+->test-sibling3->null
+
+Figure 2: Example test data tree to be attached to live tree.
+
+According to the scenario above, the live tree is already present so it isnâ€™t
+required to attach the root(â€˜/â€™) node. All other nodes are attached by calling
+of_attach_node() on each node.
+
+In the function of_attach_node(), the new node is attached as the child of the
+given parent in live tree. But, if parent already has a child then the new node
+replaces the current child and turns it into its sibling. So, when the testcase
+data node is attached to the live tree above (Figure 1), the final structure is
+ as shown in Figure 3.
+
+root (â€˜/â€™)
+   |
+testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
+   |               |          |           |           |
+ (...)             |          |           |          null
+                   |          |         child31 -> sibling32 -> null
+                   |          |           |           |
+                   |          |          null        null
+                   |          |
+                   |        child21 -> sibling22 -> sibling23 -> null
+                   |          |           |            |
+                   |         null        null         null
+                   |
+                child11 -> sibling12 -> sibling13 -> sibling14 -> null
+                   |          |            |            |
+                  null       null          |           null
+                                           |
+                                        child131 -> null
+                                           |
+                                          null
+-----------------------------------------------------------------------
+
+root (â€˜/â€™)
+   |
+testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
+   |               |          |           |           |
+   |             (...)      (...)       (...)        null
+   |
+test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null
+   |                |                   |                |
+  null             null                null         test-child01
+
+
+Figure 3: Live device tree structure after attaching the testcase-data.
+
+
+Astute readers would have noticed that test-child0 node becomes the last
+sibling compared to the earlier structure (Figure 2). After attaching first
+test-child0 the test-sibling1 is attached that pushes the child node
+(i.e. test-child0) to become a sibling and makes itself a child node,
+ as mentioned above.
+
+If a duplicate node is found (i.e. if a node with same full_name property is
+already present in the live tree), then the node isnâ€™t attached rather its
+properties are updated to the live treeâ€™s node by calling the function
+update_node_properties().
+
+
+2.2. Removing the test data
+
+Once the test case execution is complete, selftest_data_remove is called in
+order to remove the device nodes attached initially (first the leaf nodes are
+detached and then moving up the parent nodes are removed, and eventually the
+whole tree). selftest_data_remove() calls detach_node_and_children() that uses
+of_detach_node() to detach the nodes from the live device tree.
+
+To detach a node, of_detach_node() first updates all_next linked list, by
+attaching the previous nodeâ€™s allnext to current nodeâ€™s allnext pointer. And
+then, it either updates the child pointer of given nodeâ€™s parent to its
+sibling or attaches the previous sibling to the given nodeâ€™s sibling, as
+appropriate. That is it :)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/devicetree/todo.txt linux-libre-3.17-rc7-gnu/Documentation/devicetree/todo.txt
--- linux-libre-3.16-gnu/Documentation/devicetree/todo.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/devicetree/todo.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,11 @@
+Todo list for devicetree:
+
+=== General structure ===
+- Switch from custom lists to (h)list_head for nodes and properties structure
+- Remove of_allnodes list and iterate using list of child nodes alone
+
+=== CONFIG_OF_DYNAMIC ===
+- Switch to RCU for tree updates and get rid of global spinlock
+- Document node lifecycle for CONFIG_OF_DYNAMIC
+- Always set ->full_name at of_attach_node() time
+- pseries: Get rid of open-coded tree modification from arch/powerpc/platforms/pseries/dlpar.c
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/dma-buf-sharing.txt linux-libre-3.17-rc7-gnu/Documentation/dma-buf-sharing.txt
--- linux-libre-3.16-gnu/Documentation/dma-buf-sharing.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/dma-buf-sharing.txt	2014-09-28 17:29:07.000000000 -0400
@@ -56,10 +56,10 @@ The dma_buf buffer sharing API usage con
 				     size_t size, int flags,
 				     const char *exp_name)
 
-   If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a
-   pointer to the same. It also associates an anonymous file with this buffer,
-   so it can be exported. On failure to allocate the dma_buf object, it returns
-   NULL.
+   If this succeeds, dma_buf_export_named allocates a dma_buf structure, and
+   returns a pointer to the same. It also associates an anonymous file with this
+   buffer, so it can be exported. On failure to allocate the dma_buf object,
+   it returns NULL.
 
    'exp_name' is the name of exporter - to facilitate information while
    debugging.
@@ -76,7 +76,7 @@ The dma_buf buffer sharing API usage con
    drivers and/or processes.
 
    Interface:
-      int dma_buf_fd(struct dma_buf *dmabuf)
+      int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 
    This API installs an fd for the anonymous file associated with this buffer;
    returns either 'fd', or error.
@@ -157,7 +157,9 @@ to request use of buffer for allocation.
    "dma_buf->ops->" indirection from the users of this interface.
 
    In struct dma_buf_ops, unmap_dma_buf is defined as
-      void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *);
+      void (*unmap_dma_buf)(struct dma_buf_attachment *,
+                            struct sg_table *,
+                            enum dma_data_direction);
 
    unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like
    map_dma_buf, this API also must be implemented by the exporter.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/dmaengine.txt linux-libre-3.17-rc7-gnu/Documentation/dmaengine.txt
--- linux-libre-3.16-gnu/Documentation/dmaengine.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/dmaengine.txt	2014-09-28 17:29:07.000000000 -0400
@@ -84,31 +84,32 @@ The slave DMA usage consists of followin
    the given transaction.
 
    Interface:
-	struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)(
+	struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
 		struct dma_chan *chan, struct scatterlist *sgl,
 		unsigned int sg_len, enum dma_data_direction direction,
 		unsigned long flags);
 
-	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+	struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
-	struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
+	struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma(
 		struct dma_chan *chan, struct dma_interleaved_template *xt,
 		unsigned long flags);
 
    The peripheral driver is expected to have mapped the scatterlist for
    the DMA operation prior to calling device_prep_slave_sg, and must
    keep the scatterlist mapped until the DMA operation has completed.
-   The scatterlist must be mapped using the DMA struct device.  So,
-   normal setup should look like this:
+   The scatterlist must be mapped using the DMA struct device.
+   If a mapping needs to be synchronized later, dma_sync_*_for_*() must be
+   called using the DMA struct device, too.
+   So, normal setup should look like this:
 
 	nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len);
 	if (nr_sg == 0)
 		/* error */
 
-	desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg,
-			direction, flags);
+	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
@@ -188,7 +189,7 @@ Further APIs:
    description of this API.
 
    This can be used in conjunction with dma_async_is_complete() and
-   the cookie returned from 'descriptor->submit()' to check for
+   the cookie returned from dmaengine_submit() to check for
    completion of a specific DMA transaction.
 
    Note:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/device-drivers.tmpl linux-libre-3.17-rc7-gnu/Documentation/DocBook/device-drivers.tmpl
--- linux-libre-3.16-gnu/Documentation/DocBook/device-drivers.tmpl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/device-drivers.tmpl	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@
 !Ikernel/sched/cpupri.c
 !Ikernel/sched/fair.c
 !Iinclude/linux/completion.h
-!Ekernel/timer.c
+!Ekernel/time/timer.c
      </sect1>
      <sect1><title>Wait queues and Wake events</title>
 !Iinclude/linux/wait.h
@@ -63,7 +63,7 @@
      <sect1><title>High-resolution timers</title>
 !Iinclude/linux/ktime.h
 !Iinclude/linux/hrtimer.h
-!Ekernel/hrtimer.c
+!Ekernel/time/hrtimer.c
      </sect1>
      <sect1><title>Workqueues and Kevents</title>
 !Ekernel/workqueue.c
@@ -128,8 +128,12 @@ X!Edrivers/base/interface.c
 !Edrivers/base/bus.c
      </sect1>
      <sect1><title>Device Drivers DMA Management</title>
-!Edrivers/base/dma-buf.c
-!Edrivers/base/reservation.c
+!Edrivers/dma-buf/dma-buf.c
+!Edrivers/dma-buf/fence.c
+!Edrivers/dma-buf/seqno-fence.c
+!Iinclude/linux/fence.h
+!Iinclude/linux/seqno-fence.h
+!Edrivers/dma-buf/reservation.c
 !Iinclude/linux/reservation.h
 !Edrivers/base/dma-coherent.c
 !Edrivers/base/dma-mapping.c
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/drm.tmpl linux-libre-3.17-rc7-gnu/Documentation/DocBook/drm.tmpl
--- linux-libre-3.16-gnu/Documentation/DocBook/drm.tmpl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/drm.tmpl	2014-09-28 17:29:07.000000000 -0400
@@ -315,7 +315,7 @@ char *date;</synopsis>
         <function>drm_dev_unregister()</function> followed by a call to
         <function>drm_dev_unref()</function>.
       </para>
-!Edrivers/gpu/drm/drm_stub.c
+!Edrivers/gpu/drm/drm_drv.c
     </sect2>
     <sect2>
       <title>Driver Load</title>
@@ -1610,7 +1610,7 @@ int max_width, max_height;</synopsis>
           The connector is then registered with a call to
           <function>drm_connector_init</function> with a pointer to the connector
           functions and a connector type, and exposed through sysfs with a call to
-          <function>drm_sysfs_connector_add</function>.
+          <function>drm_connector_register</function>.
         </para>
         <para>
           Supported connector types are
@@ -1768,7 +1768,7 @@ int max_width, max_height;</synopsis>
 	(<function>drm_encoder_cleanup</function>) and connectors
 	(<function>drm_connector_cleanup</function>). Furthermore, connectors
 	that have been added to sysfs must be removed by a call to
-	<function>drm_sysfs_connector_remove</function> before calling
+	<function>drm_connector_unregister</function> before calling
 	<function>drm_connector_cleanup</function>.
       </para>
       <para>
@@ -1813,7 +1813,7 @@ void intel_crt_init(struct drm_device *d
 	drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 }]]></programlisting>
       <para>
         In the example above (taken from the i915 driver), a CRTC, connector and
@@ -2338,6 +2338,12 @@ void intel_crt_init(struct drm_device *d
 !Edrivers/gpu/drm/drm_dp_helper.c
     </sect2>
     <sect2>
+      <title>Display Port MST Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
+!Iinclude/drm/drm_dp_mst_helper.h
+!Edrivers/gpu/drm/drm_dp_mst_topology.c
+    </sect2>
+    <sect2>
       <title>EDID Helper Functions Reference</title>
 !Edrivers/gpu/drm/drm_edid.c
     </sect2>
@@ -2502,7 +2508,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >Description/Restrictions</td>
 	</tr>
 	<tr>
-	<td rowspan="20" valign="top" >DRM</td>
+	<td rowspan="21" valign="top" >DRM</td>
 	<td rowspan="2" valign="top" >Generic</td>
 	<td valign="top" >â€œEDIDâ€�</td>
 	<td valign="top" >BLOB | IMMUTABLE</td>
@@ -2633,7 +2639,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="2" valign="top" >Optional</td>
+	<td rowspan="3" valign="top" >Optional</td>
 	<td valign="top" >â€œscaling modeâ€�</td>
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
@@ -2641,6 +2647,15 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
+	<td valign="top" >"aspect ratio"</td>
+	<td valign="top" >ENUM</td>
+	<td valign="top" >{ "None", "4:3", "16:9" }</td>
+	<td valign="top" >Connector</td>
+	<td valign="top" >DRM property to set aspect ratio from user space app.
+		This enum is made generic to allow addition of custom aspect
+		ratios.</td>
+	</tr>
+	<tr>
 	<td valign="top" >â€œdirtyâ€�</td>
 	<td valign="top" >ENUM | IMMUTABLE</td>
 	<td valign="top" >{ "Off", "On", "Annotate" }</td>
@@ -2649,7 +2664,7 @@ void intel_crt_init(struct drm_device *d
 	</tr>
 	<tr>
 	<td rowspan="21" valign="top" >i915</td>
-	<td rowspan="3" valign="top" >Generic</td>
+	<td rowspan="2" valign="top" >Generic</td>
 	<td valign="top" >"Broadcast RGB"</td>
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
@@ -2664,10 +2679,11 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td valign="top" >Standard name as in DRM</td>
-	<td valign="top" >Standard type as in DRM</td>
-	<td valign="top" >Standard value as in DRM</td>
-	<td valign="top" >Standard Object as in DRM</td>
+	<td rowspan="1" valign="top" >Plane</td>
+	<td valign="top" >â€œrotationâ€�</td>
+	<td valign="top" >BITMASK</td>
+	<td valign="top" >{ 0, "rotate-0" }, { 2, "rotate-180" }</td>
+	<td valign="top" >Plane</td>
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
@@ -2799,8 +2815,8 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="3" valign="top" >CDV gma-500</td>
-	<td rowspan="3" valign="top" >Generic</td>
+	<td rowspan="2" valign="top" >CDV gma-500</td>
+	<td rowspan="2" valign="top" >Generic</td>
 	<td valign="top" >"Broadcast RGB"</td>
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ â€œFullâ€�, â€œLimited 16:235â€� }</td>
@@ -2815,15 +2831,8 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td valign="top" >Standard name as in DRM</td>
-	<td valign="top" >Standard type as in DRM</td>
-	<td valign="top" >Standard value as in DRM</td>
-	<td valign="top" >Standard Object as in DRM</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
-	<td rowspan="20" valign="top" >Poulsbo</td>
-	<td rowspan="2" valign="top" >Generic</td>
+	<td rowspan="19" valign="top" >Poulsbo</td>
+	<td rowspan="1" valign="top" >Generic</td>
 	<td valign="top" >â€œbacklightâ€�</td>
 	<td valign="top" >RANGE</td>
 	<td valign="top" >Min=0, Max=100</td>
@@ -2831,13 +2840,6 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td valign="top" >Standard name as in DRM</td>
-	<td valign="top" >Standard type as in DRM</td>
-	<td valign="top" >Standard value as in DRM</td>
-	<td valign="top" >Standard Object as in DRM</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
 	<td rowspan="17" valign="top" >SDVO-TV</td>
 	<td valign="top" >â€œmodeâ€�</td>
 	<td valign="top" >ENUM</td>
@@ -3064,7 +3066,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="3" valign="top" >i2c/ch7006_drv</td>
+	<td rowspan="2" valign="top" >i2c/ch7006_drv</td>
 	<td valign="top" >Generic</td>
 	<td valign="top" >â€œscaleâ€�</td>
 	<td valign="top" >RANGE</td>
@@ -3073,14 +3075,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="2" valign="top" >TV</td>
-	<td valign="top" >Standard names as in DRM</td>
-	<td valign="top" >Standard types as in DRM</td>
-	<td valign="top" >Standard Values as in DRM</td>
-	<td valign="top" >Standard object as in DRM</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
+	<td rowspan="1" valign="top" >TV</td>
 	<td valign="top" >â€œmodeâ€�</td>
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ "PAL", "PAL-M","PAL-N"}, â€�PAL-Nc"
@@ -3089,7 +3084,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="16" valign="top" >nouveau</td>
+	<td rowspan="15" valign="top" >nouveau</td>
 	<td rowspan="6" valign="top" >NV10 Overlay</td>
 	<td valign="top" >"colorkey"</td>
 	<td valign="top" >RANGE</td>
@@ -3198,14 +3193,6 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td valign="top" >Generic</td>
-	<td valign="top" >Standard name as in DRM</td>
-	<td valign="top" >Standard type as in DRM</td>
-	<td valign="top" >Standard value as in DRM</td>
-	<td valign="top" >Standard Object as in DRM</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
 	<td rowspan="2" valign="top" >omap</td>
 	<td rowspan="2" valign="top" >Generic</td>
 	<td valign="top" >â€œrotationâ€�</td>
@@ -3236,7 +3223,7 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td rowspan="10" valign="top" >radeon</td>
+	<td rowspan="9" valign="top" >radeon</td>
 	<td valign="top" >DVI-I</td>
 	<td valign="top" >â€œcoherentâ€�</td>
 	<td valign="top" >RANGE</td>
@@ -3308,14 +3295,6 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >TBD</td>
 	</tr>
 	<tr>
-	<td valign="top" >Generic</td>
-	<td valign="top" >Standard name as in DRM</td>
-	<td valign="top" >Standard type as in DRM</td>
-	<td valign="top" >Standard value as in DRM</td>
-	<td valign="top" >Standard Object as in DRM</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
 	<td rowspan="3" valign="top" >rcar-du</td>
 	<td rowspan="3" valign="top" >Generic</td>
 	<td valign="top" >"alpha"</td>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/gadget.tmpl linux-libre-3.17-rc7-gnu/Documentation/DocBook/gadget.tmpl
--- linux-libre-3.16-gnu/Documentation/DocBook/gadget.tmpl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/gadget.tmpl	2014-09-28 17:29:07.000000000 -0400
@@ -556,11 +556,11 @@ been converted to this framework.
 Near-term plans include converting all of them, except for "gadgetfs".
 </para>
 
-!Edrivers/usb/gadget/f_acm.c
-!Edrivers/usb/gadget/f_ecm.c
-!Edrivers/usb/gadget/f_subset.c
-!Edrivers/usb/gadget/f_obex.c
-!Edrivers/usb/gadget/f_serial.c
+!Edrivers/usb/gadget/function/f_acm.c
+!Edrivers/usb/gadget/function/f_ecm.c
+!Edrivers/usb/gadget/function/f_subset.c
+!Edrivers/usb/gadget/function/f_obex.c
+!Edrivers/usb/gadget/function/f_serial.c
 
 </sect1>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml	2014-09-28 17:29:07.000000000 -0400
@@ -555,10 +555,46 @@ typedef enum fe_delivery_system {
 		</section>
 		<section id="DTV-ISDBT-LAYER-TIME-INTERLEAVING">
 			<title><constant>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</constant></title>
-			<para>Possible values: 0, 1, 2, 3, -1 (AUTO)</para>
-			<para>Note: The real inter-leaver depth-names depend on the mode (fft-size); the values
-				here are referring to what can be found in the TMCC-structure -
-				independent of the mode.</para>
+			<para>Valid values: 0, 1, 2, 4, -1 (AUTO)</para>
+			<para>when DTV_ISDBT_SOUND_BROADCASTING is active, value 8 is also valid.</para>
+			<para>Note: The real time interleaving length depends on the mode (fft-size). The values
+				here are referring to what can be found in the TMCC-structure, as shown in the table below.</para>
+			<informaltable id="isdbt-layer-interleaving-table">
+				<tgroup cols="4" align="center">
+					<tbody>
+						<row>
+							<entry>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</entry>
+							<entry>Mode 1 (2K FFT)</entry>
+							<entry>Mode 2 (4K FFT)</entry>
+							<entry>Mode 3 (8K FFT)</entry>
+						</row>
+						<row>
+							<entry>0</entry>
+							<entry>0</entry>
+							<entry>0</entry>
+							<entry>0</entry>
+						</row>
+						<row>
+							<entry>1</entry>
+							<entry>4</entry>
+							<entry>2</entry>
+							<entry>1</entry>
+						</row>
+						<row>
+							<entry>2</entry>
+							<entry>8</entry>
+							<entry>4</entry>
+							<entry>2</entry>
+						</row>
+						<row>
+							<entry>4</entry>
+							<entry>16</entry>
+							<entry>8</entry>
+							<entry>4</entry>
+						</row>
+					</tbody>
+				</tgroup>
+			</informaltable>
 		</section>
 		<section id="DTV-ATSCMH-FIC-VER">
 			<title><constant>DTV_ATSCMH_FIC_VER</constant></title>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/Makefile linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/Makefile
--- linux-libre-3.16-gnu/Documentation/DocBook/media/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -174,7 +174,7 @@ FILENAME = \
 DOCUMENTED = \
 	-e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
 	-e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
-	-e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+	-e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
 	-e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
 	-e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/compat.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/compat.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/compat.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/compat.xml	2014-09-28 17:29:07.000000000 -0400
@@ -2545,6 +2545,30 @@ fields changed from _s32 to _u32.
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 3.16</title>
+      <orderedlist>
+        <listitem>
+	  <para>Added event V4L2_EVENT_SOURCE_CHANGE.
+	  </para>
+        </listitem>
+      </orderedlist>
+    </section>
+
+    <section>
+      <title>V4L2 in Linux 3.17</title>
+      <orderedlist>
+        <listitem>
+	  <para>Extended &v4l2-pix-format;. Added format flags.
+	  </para>
+        </listitem>
+        <listitem>
+	  <para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;.
+	  </para>
+        </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/controls.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/controls.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/controls.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/controls.xml	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,19 @@ correctly with any device.</para>
     <para>All controls are accessed using an ID value. V4L2 defines
 several IDs for specific purposes. Drivers can also implement their
 own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
+<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
+is problematic because different drivers may use the same
+<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
+This makes it hard to programatically set such controls since the meaning
+of the control with that ID is driver dependent. In order to resolve this
+drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs are mapped to those unique IDs by the kernel. Consider these
+<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
+IDs.</para>
+<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
+flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
+is still around.</para></footnote>
 and higher values. The pre-defined control IDs have the prefix
 <constant>V4L2_CID_</constant>, and are listed in <xref
 linkend="control-id" />. The ID is used when querying the attributes of
@@ -31,25 +44,22 @@ the current video input or output, tuner
 or output. Different in the sense of other bounds, another default and
 current value, step size or other menu items. A control with a certain
 <emphasis>custom</emphasis> ID can also change name and
-type.<footnote>
-	<para>It will be more convenient for applications if drivers
-make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
-that was never required.</para>
-      </footnote> Control values are stored globally, they do not
+type.</para>
+
+    <para>If a control is not applicable to the current configuration
+of the device (for example, it doesn't apply to the current video input)
+drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
+
+    <para>Control values are stored globally, they do not
 change when switching except to stay within the reported bounds. They
 also do not change &eg; when the device is opened or closed, when the
 tuner radio frequency is changed or generally never without
-application request. Since V4L2 specifies no event mechanism, panel
-applications intended to cooperate with other panel applications (be
-they built into a larger application, as a TV viewer) may need to
-regularly poll control values to update their user
-interface.<footnote>
-	<para>Applications could call an ioctl to request events.
-After another process called &VIDIOC-S-CTRL; or another ioctl changing
-shared properties the &func-select; function would indicate
-readability until any ioctl (querying the properties) is
-called.</para>
-      </footnote></para>
+application request.</para>
+
+    <para>V4L2 specifies an event mechanism to notify applications
+when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
+<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
+use of that in order to always reflect the correct control value.</para>
 
     <para>
       All controls use machine endianness.
@@ -398,14 +408,17 @@ to work.</entry>
 	  <row id="v4l2-alpha-component">
 	    <entry><constant>V4L2_CID_ALPHA_COMPONENT</constant></entry>
 	    <entry>integer</entry>
-	    <entry> Sets the alpha color component on the capture device or on
-	    the capture buffer queue of a mem-to-mem device. When a mem-to-mem
-	    device produces frame format that includes an alpha component
+	    <entry>Sets the alpha color component. When a capture device (or
+	    capture queue of a mem-to-mem device) produces a frame format that
+	    includes an alpha component
 	    (e.g. <link linkend="rgb-formats">packed RGB image formats</link>)
-	    and the alpha value is not defined by the mem-to-mem input data
-	    this control lets you select the alpha component value of all
-	    pixels. It is applicable to any pixel format that contains an alpha
-	    component.
+	    and the alpha value is not defined by the device or the mem-to-mem
+	    input data this control lets you select the alpha component value of
+	    all pixels. When an output device (or output queue of a mem-to-mem
+	    device) consumes a frame format that doesn't include an alpha
+	    component and the device supports alpha channel processing this
+	    control lets you set the alpha component value of all pixels for
+	    further processing in the device.
 	    </entry>
 	  </row>
 	  <row>
@@ -434,127 +447,152 @@ Drivers must implement <constant>VIDIOC_
 controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
 more menu type controls.</para>
 
-    <example>
-      <title>Enumerating all controls</title>
+    <example id="enum_all_controls">
+      <title>Enumerating all user controls</title>
 
       <programlisting>
 &v4l2-queryctrl; queryctrl;
 &v4l2-querymenu; querymenu;
 
-static void
-enumerate_menu (void)
+static void enumerate_menu(void)
 {
-	printf ("  Menu items:\n");
+	printf("  Menu items:\n");
 
-	memset (&amp;querymenu, 0, sizeof (querymenu));
+	memset(&amp;querymenu, 0, sizeof(querymenu));
 	querymenu.id = queryctrl.id;
 
 	for (querymenu.index = queryctrl.minimum;
 	     querymenu.index &lt;= queryctrl.maximum;
-	      querymenu.index++) {
-		if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
-			printf ("  %s\n", querymenu.name);
+	     querymenu.index++) {
+		if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
+			printf("  %s\n", querymenu.name);
 		}
 	}
 }
 
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
 
 for (queryctrl.id = V4L2_CID_BASE;
      queryctrl.id &lt; V4L2_CID_LASTP1;
      queryctrl.id++) {
-	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
 			continue;
 
-		printf ("Control %s\n", queryctrl.name);
+		printf("Control %s\n", queryctrl.name);
 
 		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-			enumerate_menu ();
+			enumerate_menu();
 	} else {
 		if (errno == EINVAL)
 			continue;
 
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 
 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
      queryctrl.id++) {
-	if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 		if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
 			continue;
 
-		printf ("Control %s\n", queryctrl.name);
+		printf("Control %s\n", queryctrl.name);
 
 		if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-			enumerate_menu ();
+			enumerate_menu();
 	} else {
 		if (errno == EINVAL)
 			break;
 
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 </programlisting>
     </example>
 
     <example>
+      <title>Enumerating all user controls (alternative)</title>
+	<programlisting>
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
+
+queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+	if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
+		break;
+	if (queryctrl.flags &amp; 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);
+}
+</programlisting>
+    </example>
+
+    <example>
       <title>Changing controls</title>
 
       <programlisting>
 &v4l2-queryctrl; queryctrl;
 &v4l2-control; control;
 
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
 queryctrl.id = V4L2_CID_BRIGHTNESS;
 
-if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
 	if (errno != EINVAL) {
-		perror ("VIDIOC_QUERYCTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYCTRL");
+		exit(EXIT_FAILURE);
 	} else {
-		printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+		printf("V4L2_CID_BRIGHTNESS is not supported\n");
 	}
 } else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
-	printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+	printf("V4L2_CID_BRIGHTNESS is not supported\n");
 } else {
-	memset (&amp;control, 0, sizeof (control));
+	memset(&amp;control, 0, sizeof (control));
 	control.id = V4L2_CID_BRIGHTNESS;
 	control.value = queryctrl.default_value;
 
-	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
-		perror ("VIDIOC_S_CTRL");
-		exit (EXIT_FAILURE);
+	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
+		perror("VIDIOC_S_CTRL");
+		exit(EXIT_FAILURE);
 	}
 }
 
-memset (&amp;control, 0, sizeof (control));
+memset(&amp;control, 0, sizeof(control));
 control.id = V4L2_CID_CONTRAST;
 
-if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
+if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
 	control.value += 1;
 
 	/* The driver may clamp the value or return ERANGE, ignored here */
 
-	if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
+	if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
 	    &amp;&amp; errno != ERANGE) {
-		perror ("VIDIOC_S_CTRL");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_S_CTRL");
+		exit(EXIT_FAILURE);
 	}
 /* Ignore if V4L2_CID_CONTRAST is unsupported */
 } else if (errno != EINVAL) {
-	perror ("VIDIOC_G_CTRL");
-	exit (EXIT_FAILURE);
+	perror("VIDIOC_G_CTRL");
+	exit(EXIT_FAILURE);
 }
 
 control.id = V4L2_CID_AUDIO_MUTE;
-control.value = TRUE; /* silence */
+control.value = 1; /* silence */
 
 /* Errors ignored */
-ioctl (fd, VIDIOC_S_CTRL, &amp;control);
+ioctl(fd, VIDIOC_S_CTRL, &amp;control);
 </programlisting>
     </example>
   </section>
@@ -625,16 +663,29 @@ supported.</para>
 &v4l2-control;, except for the fact that it also allows for 64-bit
 values and pointers to be passed.</para>
 
+      <para>Since the &v4l2-ext-control; supports pointers it is now
+also possible to have controls with compound types such as N-dimensional arrays
+and/or structures. You need to specify the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+when enumerating controls to actually be able to see such compound controls.
+In other words, these controls with compound types should only be used
+programmatically.</para>
+
+      <para>Since such compound controls need to expose more information
+about themselves than is possible with &VIDIOC-QUERYCTRL; the
+&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
+the dimensions of the N-dimensional array if this control consists of more than
+one element.</para>
+
       <para>It is important to realize that due to the flexibility of
 controls it is necessary to check whether the control you want to set
 actually is supported in the driver and what the valid range of values
-is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
-check this. Also note that it is possible that some of the menu
-indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
-may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
-return an error). A good example is the list of supported MPEG audio
-bitrates. Some drivers only support one or two bitrates, others
-support a wider range.</para>
+is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
+&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
+that some of the menu indices in a control of type
+<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
+(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
+example is the list of supported MPEG audio bitrates. Some drivers only
+support one or two bitrates, others support a wider range.</para>
 
       <para>
 	All controls use machine endianness.
@@ -675,12 +726,12 @@ control class is found:</para>
       <informalexample>
 	<programlisting>
 qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
-	if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
+	if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
 		break;
 		/* ... */
-		qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-	}
+	qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
 </programlisting>
       </informalexample>
 
@@ -700,7 +751,7 @@ ID based on a control ID.</para>
 <constant>VIDIOC_QUERYCTRL</constant> will fail when used in
 combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
 that case the old method of enumerating control should be used (see
-1.8). But if it is supported, then it is guaranteed to enumerate over
+<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
 all controls, including driver-private controls.</para>
     </section>
 
@@ -4000,6 +4051,68 @@ to find receivers which can scroll strin
 with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
 	  </row>
 	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_MONO_STEREO</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the Mono/Stereo bit of the Decoder Identification code. If set,
+then the audio was recorded as stereo.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_ARTIFICIAL_HEAD</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the
+<ulink url="http://en.wikipedia.org/wiki/Artificial_head">Artificial Head</ulink> bit of the Decoder
+Identification code. If set, then the audio was recorded using an artificial head.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_COMPRESSED</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the Compressed bit of the Decoder Identification code. If set,
+then the audio is compressed.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_DYNAMIC_PTY</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the Dynamic PTY bit of the Decoder Identification code. If set,
+then the PTY code is dynamically switched.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_MUSIC_SPEECH</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
+broadcasts speech. If the transmitter doesn't make this distinction, then it should be set.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS_ENABLE</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then transmit alternate frequencies.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS</constant>&nbsp;</entry>
+	    <entry>__u32 array</entry>
+	  </row>
+	  <row><entry spanname="descr">The alternate frequencies in kHz units. The RDS standard allows
+for up to 25 frequencies to be defined. Drivers may support fewer frequencies so check
+the array size.</entry>
+	  </row>
+	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_AUDIO_LIMITER_ENABLED</constant>&nbsp;</entry>
 	    <entry>boolean</entry>
 	  </row>
@@ -4976,6 +5089,57 @@ description of this control class.</entr
           </row><row><entry spanname="descr">Enables/disables RDS
 	  reception by the radio tuner</entry>
           </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_PTY</constant>&nbsp;</entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row><entry spanname="descr">Gets RDS Programme Type field.
+This encodes up to 31 pre-defined programme types.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_PS_NAME</constant>&nbsp;</entry>
+	    <entry>string</entry>
+	  </row>
+	  <row><entry spanname="descr">Gets the Programme Service name (PS_NAME).
+It is intended for static display on a receiver. It is the primary aid to listeners in programme service
+identification and selection.  In Annex E of <xref linkend="iec62106" />, the RDS specification,
+there is a full description of the correct character encoding for Programme Service name strings.
+Also from RDS specification, PS is usually a single eight character text. However, it is also possible
+to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
+with steps of 8 characters. The result is it must always contain a string with size multiple of 8.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_RADIO_TEXT</constant>&nbsp;</entry>
+	    <entry>string</entry>
+	  </row>
+	  <row><entry spanname="descr">Gets the Radio Text info. It is a textual description of
+what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
+programme-related information or any other text. In these cases, RadioText can be used in addition to
+<constant>V4L2_CID_RDS_RX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
+in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
+used to transmit it, either 32 (2A block) or 64 (2B block).  However, it is also possible
+to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
+with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_RDS_RX_MUSIC_SPEECH</constant>&nbsp;</entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
+broadcasts speech. If the transmitter doesn't make this distinction, then it will be set.</entry>
+	  </row>
           <row>
 	    <entry spanname="id"><constant>V4L2_CID_TUNE_DEEMPHASIS</constant>&nbsp;</entry>
 	    <entry>enum v4l2_deemphasis</entry>
@@ -5007,6 +5171,102 @@ defines possible values for de-emphasis.
         </tbody>
       </tgroup>
       </table>
+    </section>
+
+    <section id="detect-controls">
+      <title>Detect Control Reference</title>
+
+      <para>The Detect class includes controls for common features of
+      various motion or object detection capable devices.</para>
+
+      <table pgwide="1" frame="none" id="detect-control-id">
+      <title>Detect Control IDs</title>
+
+      <tgroup cols="4">
+        <colspec colname="c1" colwidth="1*" />
+        <colspec colname="c2" colwidth="6*" />
+        <colspec colname="c3" colwidth="2*" />
+        <colspec colname="c4" colwidth="6*" />
+        <spanspec namest="c1" nameend="c2" spanname="id" />
+        <spanspec namest="c2" nameend="c4" spanname="descr" />
+        <thead>
+          <row>
+            <entry spanname="id" align="left">ID</entry>
+            <entry align="left">Type</entry>
+          </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+          </row>
+        </thead>
+        <tbody valign="top">
+          <row><entry></entry></row>
+          <row>
+            <entry spanname="id"><constant>V4L2_CID_DETECT_CLASS</constant>&nbsp;</entry>
+            <entry>class</entry>
+          </row><row><entry spanname="descr">The Detect class
+descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
+description of this control class.</entry>
+          </row>
+          <row>
+            <entry spanname="id"><constant>V4L2_CID_DETECT_MD_MODE</constant>&nbsp;</entry>
+            <entry>menu</entry>
+          </row><row><entry spanname="descr">Sets the motion detection mode.</entry>
+          </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_DETECT_MD_MODE_DISABLED</constant>
+		  </entry><entry>Disable motion detection.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_DETECT_MD_MODE_GLOBAL</constant>
+		  </entry><entry>Use a single motion detection threshold.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+		  </entry><entry>The image is divided into a grid, each cell with its own
+		  motion detection threshold. These thresholds are set through the
+		  <constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant> matrix control.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+		  </entry><entry>The image is divided into a grid, each cell with its own
+		  region value that specifies which per-region motion detection thresholds
+		  should be used. Each region has its own thresholds. How these per-region
+		  thresholds are set up is driver-specific. The region values for the grid are set
+		  through the <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> matrix
+		  control.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+          <row>
+	    <entry spanname="id"><constant>V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD</constant>&nbsp;</entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the global motion detection threshold to be
+	  used with the <constant>V4L2_DETECT_MD_MODE_GLOBAL</constant> motion detection mode.</entry>
+          </row>
+          <row>
+	    <entry spanname="id"><constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant>&nbsp;</entry>
+	    <entry>__u16 matrix</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the motion detection thresholds for each cell in the grid.
+	  To be used with the <constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+	  motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+	  grid.</entry>
+          </row>
+          <row>
+	    <entry spanname="id"><constant>V4L2_CID_DETECT_MD_REGION_GRID</constant>&nbsp;</entry>
+	    <entry>__u8 matrix</entry>
+	  </row>
+	  <row><entry spanname="descr">Sets the motion detection region value for each cell in the grid.
+	  To be used with the <constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+	  motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+	  grid.</entry>
+          </row>
+        </tbody>
+      </tgroup>
+      </table>
 
       </section>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml	2014-09-28 17:29:07.000000000 -0400
@@ -150,9 +150,15 @@ signal. Drivers shall not convert the sa
 	      <entry>This is the scanning system line number
 associated with the first line of the VBI image, of the first and the
 second field respectively. See <xref linkend="vbi-525" /> and
-<xref linkend="vbi-625" /> for valid values. VBI input drivers can
-return start values 0 if the hardware cannot reliable identify
-scanning lines, VBI acquisition may not require this
+<xref linkend="vbi-625" /> for valid values.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start line
+numbers for each field for each 525 or 625 line format as a convenience.
+Don't forget that ITU line numbering starts at 1, not 0.
+VBI input drivers can return start values 0 if the hardware cannot
+reliable identify scanning lines, VBI acquisition may not require this
 information.</entry>
 	    </row>
 	    <row>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml	2014-09-28 17:29:07.000000000 -0400
@@ -72,9 +72,12 @@ To use the <link linkend="format">format
 <constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> and use the &v4l2-sdr-format;
 <structfield>sdr</structfield> member of the <structfield>fmt</structfield>
 union as needed per the desired operation.
-Currently only the <structfield>pixelformat</structfield> field of
-&v4l2-sdr-format; is used. The content of that field is the V4L2 fourcc code
-of the data format.
+Currently there is two fields, <structfield>pixelformat</structfield> and
+<structfield>buffersize</structfield>, of struct &v4l2-sdr-format; which are
+used. Content of the <structfield>pixelformat</structfield> is V4L2 FourCC
+code of the data format. The <structfield>buffersize</structfield> field is
+maximum buffer size in bytes required for data transfer, set by the driver in
+order to inform application.
     </para>
 
     <table pgwide="1" frame="none" id="v4l2-sdr-format">
@@ -92,8 +95,15 @@ V4L2 defines SDR formats in <xref linken
            </entry>
           </row>
           <row>
+            <entry>__u32</entry>
+            <entry><structfield>buffersize</structfield></entry>
+            <entry>
+Maximum size in bytes required for data. Value is set by the driver.
+           </entry>
+          </row>
+          <row>
             <entry>__u8</entry>
-            <entry><structfield>reserved[28]</structfield></entry>
+            <entry><structfield>reserved[24]</structfield></entry>
             <entry>This array is reserved for future extensions.
 Drivers and applications must set it to zero.</entry>
           </row>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml	2014-09-28 17:29:07.000000000 -0400
@@ -185,7 +185,14 @@ tables, sigh. --></para></entry>
 	    <entry></entry>
 	    <entry spanname="hspan">Drivers must set
 <structfield>service_lines</structfield>[0][0] and
-<structfield>service_lines</structfield>[1][0] to zero.</entry>
+<structfield>service_lines</structfield>[1][0] to zero.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start
+line numbers for each field for each 525 or 625 line format as a
+convenience.  Don't forget that ITU line numbering starts at 1, not 0.
+</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/func-poll.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/func-poll.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/func-poll.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/func-poll.xml	2014-09-28 17:29:07.000000000 -0400
@@ -29,9 +29,12 @@ can suspend execution until the driver h
 to accept data for output.</para>
 
     <para>When streaming I/O has been negotiated this function waits
-until a buffer has been filled or displayed and can be dequeued with
-the &VIDIOC-DQBUF; ioctl. When buffers are already in the outgoing
-queue of the driver the function returns immediately.</para>
+until a buffer has been filled by the capture device and can be dequeued
+with the &VIDIOC-DQBUF; ioctl. For output devices this function waits
+until the device is ready to accept a new buffer to be queued up with
+the &VIDIOC-QBUF; ioctl for display. When buffers are already in the outgoing
+queue of the driver (capture) or the incoming queue isn't full (display)
+the function returns immediately.</para>
 
     <para>On success <function>poll()</function> returns the number of
 file descriptors that have been selected (that is, file descriptors
@@ -44,10 +47,22 @@ Capture devices set the <constant>POLLIN
 flags. When the function timed out it returns a value of zero, on
 failure it returns <returnvalue>-1</returnvalue> and the
 <varname>errno</varname> variable is set appropriately. When the
-application did not call &VIDIOC-QBUF; or &VIDIOC-STREAMON; yet the
+application did not call &VIDIOC-STREAMON; the
 <function>poll()</function> function succeeds, but sets the
 <constant>POLLERR</constant> flag in the
-<structfield>revents</structfield> field.</para>
+<structfield>revents</structfield> field. When the
+application has called &VIDIOC-STREAMON; for a capture device but hasn't
+yet called &VIDIOC-QBUF;, the <function>poll()</function> function
+succeeds and sets the <constant>POLLERR</constant> flag in the
+<structfield>revents</structfield> field. For output devices this
+same situation will cause <function>poll()</function> to succeed
+as well, but it sets the <constant>POLLOUT</constant> and
+<constant>POLLWRNORM</constant> flags in the <structfield>revents</structfield>
+field.</para>
+
+    <para>If an event occurred (see &VIDIOC-DQEVENT;) then
+<constant>POLLPRI</constant> will be set in the <structfield>revents</structfield>
+field and <function>poll()</function> will return.</para>
 
     <para>When use of the <function>read()</function> function has
 been negotiated and the driver does not capture yet, the
@@ -58,10 +73,18 @@ continuously (as opposed to, for example
 may return immediately.</para>
 
     <para>When use of the <function>write()</function> function has
-been negotiated the <function>poll</function> function just waits
+been negotiated and the driver does not stream yet, the
+<function>poll</function> function starts streaming. When that fails
+it returns a <constant>POLLERR</constant> as above. Otherwise it waits
 until the driver is ready for a non-blocking
 <function>write()</function> call.</para>
 
+    <para>If the caller is only interested in events (just
+<constant>POLLPRI</constant> is set in the <structfield>events</structfield>
+field), then <function>poll()</function> will <emphasis>not</emphasis>
+start streaming if the driver does not stream yet. This makes it
+possible to just poll for events and not for buffers.</para>
+
     <para>All drivers implementing the <function>read()</function> or
 <function>write()</function> function or streaming I/O must also
 support the <function>poll()</function> function.</para>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/io.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/io.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/io.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/io.xml	2014-09-28 17:29:07.000000000 -0400
@@ -870,7 +870,8 @@ should set this to 0.</entry>
 	      If the application sets this to 0 for an output stream, then
 	      <structfield>bytesused</structfield> will be set to the size of the
 	      plane (see the <structfield>length</structfield> field of this struct)
-	      by the driver.</entry>
+	      by the driver. Note that the actual image data starts at
+	      <structfield>data_offset</structfield> which may not be 0.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -919,6 +920,10 @@ should set this to 0.</entry>
 	    <entry>Offset in bytes to video data in the plane.
 	      Drivers must set this field when <structfield>type</structfield>
 	      refers to an input stream, applications when it refers to an output stream.
+	      Note that data_offset is included in <structfield>bytesused</structfield>.
+	      So the size of the image in the plane is
+	      <structfield>bytesused</structfield>-<structfield>data_offset</structfield> at
+	      offset <structfield>data_offset</structfield> from the start of the plane.
 	    </entry>
 	  </row>
 	  <row>
@@ -1066,7 +1071,7 @@ state, in the application domain so to s
 	  <entry>Drivers set or clear this flag when calling the
 <constant>VIDIOC_DQBUF</constant> ioctl. It may be set by video
 capture devices when the buffer contains a compressed image which is a
-key frame (or field), &ie; can be decompressed on its own. Also know as
+key frame (or field), &ie; can be decompressed on its own. Also known as
 an I-frame.  Applications can set this bit when <structfield>type</structfield>
 refers to an output stream.</entry>
 	  </row>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-09-28 17:29:07.000000000 -0400
@@ -15,9 +15,6 @@ typical PC graphics frame buffers. They
 per pixel. These are all packed-pixel formats, meaning all the data
 for a pixel lie next to each other in memory.</para>
 
-    <para>When one of these formats is used, drivers shall report the
-colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
-
     <table pgwide="1" frame="none" id="rgb-formats">
       <title>Packed RGB Image Formats</title>
       <tgroup cols="37" align="center">
@@ -130,9 +127,9 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
-	  <row id="V4L2-PIX-FMT-RGB444">
-	    <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
-	    <entry>'R444'</entry>
+	  <row id="V4L2-PIX-FMT-ARGB444">
+	    <entry><constant>V4L2_PIX_FMT_ARGB444</constant></entry>
+	    <entry>'AR12'</entry>
 	    <entry></entry>
 	    <entry>g<subscript>3</subscript></entry>
 	    <entry>g<subscript>2</subscript></entry>
@@ -152,9 +149,31 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>r<subscript>1</subscript></entry>
 	    <entry>r<subscript>0</subscript></entry>
 	  </row>
-	  <row id="V4L2-PIX-FMT-RGB555">
-	    <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
-	    <entry>'RGBO'</entry>
+	  <row id="V4L2-PIX-FMT-XRGB444">
+	    <entry><constant>V4L2_PIX_FMT_XRGB444</constant></entry>
+	    <entry>'XR12'</entry>
+	    <entry></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-ARGB555">
+	    <entry><constant>V4L2_PIX_FMT_ARGB555</constant></entry>
+	    <entry>'AR15'</entry>
 	    <entry></entry>
 	    <entry>g<subscript>2</subscript></entry>
 	    <entry>g<subscript>1</subscript></entry>
@@ -174,6 +193,28 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>g<subscript>4</subscript></entry>
 	    <entry>g<subscript>3</subscript></entry>
 	  </row>
+	  <row id="V4L2-PIX-FMT-XRGB555">
+	    <entry><constant>V4L2_PIX_FMT_XRGB555</constant></entry>
+	    <entry>'XR15'</entry>
+	    <entry></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>-</entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	  </row>
 	  <row id="V4L2-PIX-FMT-RGB565">
 	    <entry><constant>V4L2_PIX_FMT_RGB565</constant></entry>
 	    <entry>'RGBP'</entry>
@@ -341,9 +382,9 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
-	  <row id="V4L2-PIX-FMT-BGR32">
-	    <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
-	    <entry>'BGR4'</entry>
+	  <row id="V4L2-PIX-FMT-ABGR32">
+	    <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
+	    <entry>'AR24'</entry>
 	    <entry></entry>
 	    <entry>b<subscript>7</subscript></entry>
 	    <entry>b<subscript>6</subscript></entry>
@@ -381,9 +422,49 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>a<subscript>1</subscript></entry>
 	    <entry>a<subscript>0</subscript></entry>
 	  </row>
-	  <row id="V4L2-PIX-FMT-RGB32">
-	    <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
-	    <entry>'RGB4'</entry>
+	  <row id="V4L2-PIX-FMT-XBGR32">
+	    <entry><constant>V4L2_PIX_FMT_XBGR32</constant></entry>
+	    <entry>'XR24'</entry>
+	    <entry></entry>
+	    <entry>b<subscript>7</subscript></entry>
+	    <entry>b<subscript>6</subscript></entry>
+	    <entry>b<subscript>5</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>g<subscript>7</subscript></entry>
+	    <entry>g<subscript>6</subscript></entry>
+	    <entry>g<subscript>5</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>r<subscript>7</subscript></entry>
+	    <entry>r<subscript>6</subscript></entry>
+	    <entry>r<subscript>5</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-ARGB32">
+	    <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry>
+	    <entry>'AX24'</entry>
 	    <entry></entry>
 	    <entry>a<subscript>7</subscript></entry>
 	    <entry>a<subscript>6</subscript></entry>
@@ -421,18 +502,76 @@ colorspace <constant>V4L2_COLORSPACE_SRG
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
+	  <row id="V4L2-PIX-FMT-XRGB32">
+	    <entry><constant>V4L2_PIX_FMT_XRGB32</constant></entry>
+	    <entry>'BX24'</entry>
+	    <entry></entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry></entry>
+	    <entry>r<subscript>7</subscript></entry>
+	    <entry>r<subscript>6</subscript></entry>
+	    <entry>r<subscript>5</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>g<subscript>7</subscript></entry>
+	    <entry>g<subscript>6</subscript></entry>
+	    <entry>g<subscript>5</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>b<subscript>7</subscript></entry>
+	    <entry>b<subscript>6</subscript></entry>
+	    <entry>b<subscript>5</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
 
-    <para>Bit 7 is the most significant bit. The value of the a = alpha
-bits is undefined when reading from the driver, ignored when writing
-to the driver, except when alpha blending has been negotiated for a
-<link linkend="overlay">Video Overlay</link> or <link linkend="osd">
-Video Output Overlay</link> or when the alpha component has been configured
-for a <link linkend="capture">Video Capture</link> by means of <link
-linkend="v4l2-alpha-component"> <constant>V4L2_CID_ALPHA_COMPONENT
-</constant> </link> control.</para>
+    <para>Bit 7 is the most significant bit.</para>
+
+    <para>The usage and value of the alpha bits (a) in the ARGB and ABGR formats
+    (collectively referred to as alpha formats) depend on the device type and
+    hardware operation. <link linkend="capture">Capture</link> devices
+    (including capture queues of mem-to-mem devices) fill the alpha component in
+    memory. When the device outputs an alpha channel the alpha component will
+    have a meaningful value. Otherwise, when the device doesn't output an alpha
+    channel but can set the alpha bit to a user-configurable value, the <link
+    linkend="v4l2-alpha-component"><constant>V4L2_CID_ALPHA_COMPONENT</constant>
+    </link> control is used to specify that alpha value, and the alpha component
+    of all pixels will be set to the value specified by that control. Otherwise
+    a corresponding format without an alpha component (XRGB or XBGR) must be
+    used instead of an alpha format.</para>
+
+    <para><link linkend="output">Output</link> devices (including output queues
+    of mem-to-mem devices and <link linkend="osd">video output overlay</link>
+    devices) read the alpha component from memory. When the device processes the
+    alpha channel the alpha component must be filled with meaningful values by
+    applications. Otherwise a corresponding format without an alpha component
+    (XRGB or XBGR) must be used instead of an alpha format.</para>
+
+    <para>The XRGB and XBGR formats contain undefined bits (-). Applications,
+    devices and drivers must ignore those bits, for both <link
+    linkend="capture">capture</link> and <link linkend="output">output</link>
+    devices.</para>
 
     <example>
       <title><constant>V4L2_PIX_FMT_BGR24</constant> 4 &times; 4 pixel
@@ -512,6 +651,239 @@ image</title>
       </formalpara>
     </example>
 
+    <para>Formats defined in <xref linkend="rgb-formats-deprecated"/> are
+    deprecated and must not be used by new drivers. They are documented here for
+    reference. The meaning of their alpha bits (a) is ill-defined and
+    interpreted as in either the corresponding ARGB or XRGB format, depending on
+    the driver.</para>
+
+    <table pgwide="1" frame="none" id="rgb-formats-deprecated">
+      <title>Deprecated Packed RGB Image Formats</title>
+      <tgroup cols="37" align="center">
+	<colspec colname="id" align="left" />
+	<colspec colname="fourcc" />
+	<colspec colname="bit" />
+
+	<colspec colnum="4" colname="b07" align="center" />
+	<colspec colnum="5" colname="b06" align="center" />
+	<colspec colnum="6" colname="b05" align="center" />
+	<colspec colnum="7" colname="b04" align="center" />
+	<colspec colnum="8" colname="b03" align="center" />
+	<colspec colnum="9" colname="b02" align="center" />
+	<colspec colnum="10" colname="b01" align="center" />
+	<colspec colnum="11" colname="b00" align="center" />
+
+	<colspec colnum="13" colname="b17" align="center" />
+	<colspec colnum="14" colname="b16" align="center" />
+	<colspec colnum="15" colname="b15" align="center" />
+	<colspec colnum="16" colname="b14" align="center" />
+	<colspec colnum="17" colname="b13" align="center" />
+	<colspec colnum="18" colname="b12" align="center" />
+	<colspec colnum="19" colname="b11" align="center" />
+	<colspec colnum="20" colname="b10" align="center" />
+
+	<colspec colnum="22" colname="b27" align="center" />
+	<colspec colnum="23" colname="b26" align="center" />
+	<colspec colnum="24" colname="b25" align="center" />
+	<colspec colnum="25" colname="b24" align="center" />
+	<colspec colnum="26" colname="b23" align="center" />
+	<colspec colnum="27" colname="b22" align="center" />
+	<colspec colnum="28" colname="b21" align="center" />
+	<colspec colnum="29" colname="b20" align="center" />
+
+	<colspec colnum="31" colname="b37" align="center" />
+	<colspec colnum="32" colname="b36" align="center" />
+	<colspec colnum="33" colname="b35" align="center" />
+	<colspec colnum="34" colname="b34" align="center" />
+	<colspec colnum="35" colname="b33" align="center" />
+	<colspec colnum="36" colname="b32" align="center" />
+	<colspec colnum="37" colname="b31" align="center" />
+	<colspec colnum="38" colname="b30" align="center" />
+
+	<spanspec namest="b07" nameend="b00" spanname="b0" />
+	<spanspec namest="b17" nameend="b10" spanname="b1" />
+	<spanspec namest="b27" nameend="b20" spanname="b2" />
+	<spanspec namest="b37" nameend="b30" spanname="b3" />
+	<thead>
+	  <row>
+	    <entry>Identifier</entry>
+	    <entry>Code</entry>
+	    <entry>&nbsp;</entry>
+	    <entry spanname="b0">Byte&nbsp;0 in memory</entry>
+	    <entry spanname="b1">Byte&nbsp;1</entry>
+	    <entry spanname="b2">Byte&nbsp;2</entry>
+	    <entry spanname="b3">Byte&nbsp;3</entry>
+	  </row>
+	  <row>
+	    <entry>&nbsp;</entry>
+	    <entry>&nbsp;</entry>
+	    <entry>Bit</entry>
+	    <entry>7</entry>
+	    <entry>6</entry>
+	    <entry>5</entry>
+	    <entry>4</entry>
+	    <entry>3</entry>
+	    <entry>2</entry>
+	    <entry>1</entry>
+	    <entry>0</entry>
+	    <entry>&nbsp;</entry>
+	    <entry>7</entry>
+	    <entry>6</entry>
+	    <entry>5</entry>
+	    <entry>4</entry>
+	    <entry>3</entry>
+	    <entry>2</entry>
+	    <entry>1</entry>
+	    <entry>0</entry>
+	    <entry>&nbsp;</entry>
+	    <entry>7</entry>
+	    <entry>6</entry>
+	    <entry>5</entry>
+	    <entry>4</entry>
+	    <entry>3</entry>
+	    <entry>2</entry>
+	    <entry>1</entry>
+	    <entry>0</entry>
+	    <entry>&nbsp;</entry>
+	    <entry>7</entry>
+	    <entry>6</entry>
+	    <entry>5</entry>
+	    <entry>4</entry>
+	    <entry>3</entry>
+	    <entry>2</entry>
+	    <entry>1</entry>
+	    <entry>0</entry>
+	  </row>
+	</thead>
+	<tbody>
+	  <row id="V4L2-PIX-FMT-RGB444">
+	    <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
+	    <entry>'R444'</entry>
+	    <entry></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>a<subscript>3</subscript></entry>
+	    <entry>a<subscript>2</subscript></entry>
+	    <entry>a<subscript>1</subscript></entry>
+	    <entry>a<subscript>0</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-RGB555">
+	    <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
+	    <entry>'RGBO'</entry>
+	    <entry></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>a</entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-BGR32">
+	    <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
+	    <entry>'BGR4'</entry>
+	    <entry></entry>
+	    <entry>b<subscript>7</subscript></entry>
+	    <entry>b<subscript>6</subscript></entry>
+	    <entry>b<subscript>5</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>g<subscript>7</subscript></entry>
+	    <entry>g<subscript>6</subscript></entry>
+	    <entry>g<subscript>5</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>r<subscript>7</subscript></entry>
+	    <entry>r<subscript>6</subscript></entry>
+	    <entry>r<subscript>5</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>a<subscript>7</subscript></entry>
+	    <entry>a<subscript>6</subscript></entry>
+	    <entry>a<subscript>5</subscript></entry>
+	    <entry>a<subscript>4</subscript></entry>
+	    <entry>a<subscript>3</subscript></entry>
+	    <entry>a<subscript>2</subscript></entry>
+	    <entry>a<subscript>1</subscript></entry>
+	    <entry>a<subscript>0</subscript></entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-RGB32">
+	    <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
+	    <entry>'RGB4'</entry>
+	    <entry></entry>
+	    <entry>a<subscript>7</subscript></entry>
+	    <entry>a<subscript>6</subscript></entry>
+	    <entry>a<subscript>5</subscript></entry>
+	    <entry>a<subscript>4</subscript></entry>
+	    <entry>a<subscript>3</subscript></entry>
+	    <entry>a<subscript>2</subscript></entry>
+	    <entry>a<subscript>1</subscript></entry>
+	    <entry>a<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>r<subscript>7</subscript></entry>
+	    <entry>r<subscript>6</subscript></entry>
+	    <entry>r<subscript>5</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>g<subscript>7</subscript></entry>
+	    <entry>g<subscript>6</subscript></entry>
+	    <entry>g<subscript>5</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>b<subscript>7</subscript></entry>
+	    <entry>b<subscript>6</subscript></entry>
+	    <entry>b<subscript>5</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
     <para>A test utility to determine which RGB formats a driver
 actually supports is available from the LinuxTV v4l-dvb repository.
 See &v4l-dvb; for access instructions.</para>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,44 @@
+<refentry id="V4L2-SDR-FMT-CS08">
+  <refmeta>
+    <refentrytitle>V4L2_SDR_FMT_CS8 ('CS08')</refentrytitle>
+    &manvol;
+  </refmeta>
+    <refnamediv>
+      <refname>
+        <constant>V4L2_SDR_FMT_CS8</constant>
+      </refname>
+      <refpurpose>Complex signed 8-bit IQ sample</refpurpose>
+    </refnamediv>
+    <refsect1>
+      <title>Description</title>
+      <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 8 bit signed number. I value comes first and Q value after
+that.
+      </para>
+    <example>
+      <title><constant>V4L2_SDR_FMT_CS8</constant> 1 sample</title>
+      <formalpara>
+        <title>Byte Order.</title>
+        <para>Each cell is one byte.
+          <informaltable frame="none">
+            <tgroup cols="2" align="center">
+              <colspec align="left" colwidth="2*" />
+              <tbody valign="top">
+                <row>
+                  <entry>start&nbsp;+&nbsp;0:</entry>
+                  <entry>I'<subscript>0</subscript></entry>
+                </row>
+                <row>
+                  <entry>start&nbsp;+&nbsp;1:</entry>
+                  <entry>Q'<subscript>0</subscript></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+<refentry id="V4L2-SDR-FMT-CS14LE">
+  <refmeta>
+    <refentrytitle>V4L2_SDR_FMT_CS14LE ('CS14')</refentrytitle>
+    &manvol;
+  </refmeta>
+    <refnamediv>
+      <refname>
+        <constant>V4L2_SDR_FMT_CS14LE</constant>
+      </refname>
+      <refpurpose>Complex signed 14-bit little endian IQ sample</refpurpose>
+    </refnamediv>
+    <refsect1>
+      <title>Description</title>
+      <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 14 bit signed little endian number. I value comes first
+and Q value after that. 14 bit value is stored in 16 bit space with unused
+high bits padded with 0.
+      </para>
+    <example>
+      <title><constant>V4L2_SDR_FMT_CS14LE</constant> 1 sample</title>
+      <formalpara>
+        <title>Byte Order.</title>
+        <para>Each cell is one byte.
+          <informaltable frame="none">
+            <tgroup cols="3" align="center">
+              <colspec align="left" colwidth="2*" />
+              <tbody valign="top">
+                <row>
+                  <entry>start&nbsp;+&nbsp;0:</entry>
+                  <entry>I'<subscript>0[7:0]</subscript></entry>
+                  <entry>I'<subscript>0[13:8]</subscript></entry>
+                </row>
+                <row>
+                  <entry>start&nbsp;+&nbsp;2:</entry>
+                  <entry>Q'<subscript>0[7:0]</subscript></entry>
+                  <entry>Q'<subscript>0[13:8]</subscript></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,40 @@
+<refentry id="V4L2-SDR-FMT-RU12LE">
+  <refmeta>
+    <refentrytitle>V4L2_SDR_FMT_RU12LE ('RU12')</refentrytitle>
+    &manvol;
+  </refmeta>
+    <refnamediv>
+      <refname>
+        <constant>V4L2_SDR_FMT_RU12LE</constant>
+      </refname>
+      <refpurpose>Real unsigned 12-bit little endian sample</refpurpose>
+    </refnamediv>
+    <refsect1>
+      <title>Description</title>
+      <para>
+This format contains sequence of real number samples. Each sample is
+represented as a 12 bit unsigned little endian number. Sample is stored
+in 16 bit space with unused high bits padded with 0.
+      </para>
+    <example>
+      <title><constant>V4L2_SDR_FMT_RU12LE</constant> 1 sample</title>
+      <formalpara>
+        <title>Byte Order.</title>
+        <para>Each cell is one byte.
+          <informaltable frame="none">
+            <tgroup cols="3" align="center">
+              <colspec align="left" colwidth="2*" />
+              <tbody valign="top">
+                <row>
+                  <entry>start&nbsp;+&nbsp;0:</entry>
+                  <entry>I'<subscript>0[7:0]</subscript></entry>
+                  <entry>I'<subscript>0[11:8]</subscript></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,7 @@
 	<title>Description</title>
 
 	<para>The following four pixel formats are raw sRGB / Bayer formats with
-12 bits per colour. Each colour component is stored in a 16-bit word, with 6
+12 bits per colour. Each colour component is stored in a 16-bit word, with 4
 unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
 and n/2 blue or red samples, with alternating red and blue rows. Bytes are
 stored in memory in little endian order. They are conventionally described
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/pixfmt.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/pixfmt.xml	2014-09-28 17:29:07.000000000 -0400
@@ -112,9 +112,34 @@ see <xref linkend="colorspaces" />.</ent
 	<row>
 	  <entry>__u32</entry>
 	  <entry><structfield>priv</structfield></entry>
-	  <entry>Reserved for custom (driver defined) additional
-information about formats. When not used drivers and applications must
-set this field to zero.</entry>
+	  <entry><para>This field indicates whether the remaining fields of the
+<structname>v4l2_pix_format</structname> structure, also called the extended
+fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
+indicates that the extended fields have been correctly initialized. When set to
+any other value it indicates that the extended fields contain undefined values.
+</para>
+<para>Applications that wish to use the pixel format extended fields must first
+ensure that the feature is supported by querying the device for the
+<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
+capability. If the capability isn't set the pixel format extended fields are not
+supported and using the extended fields will lead to undefined results.</para>
+<para>To use the extended fields, applications must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
+and zero the unused bytes of the <structname>v4l2_format</structname>
+<structfield>raw_data</structfield> field.</para>
+<para>When the <structfield>priv</structfield> field isn't set to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
+extended fields were set to zero. On return drivers must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended fields to
+applicable values.</para></entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>flags</structfield></entry>
+	    <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
 	</row>
       </tbody>
     </tgroup>
@@ -201,9 +226,15 @@ codes can be used.</entry>
           and the number of valid entries in the
           <structfield>plane_fmt</structfield> array.</entry>
         </row>
+	<row>
+	  <entry>__u8</entry>
+	  <entry><structfield>flags</structfield></entry>
+	  <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
+	</row>
         <row>
           <entry>__u8</entry>
-          <entry><structfield>reserved[11]</structfield></entry>
+          <entry><structfield>reserved[10]</structfield></entry>
           <entry>Reserved for future extensions. Should be zeroed by the
            application.</entry>
         </row>
@@ -248,7 +279,7 @@ has just as many pad bytes after it as t
 
     <para>In V4L2 each format has an identifier which looks like
 <constant>PIX_FMT_XXX</constant>, defined in the <link
-linkend="videodev">videodev.h</link> header file. These identifiers
+linkend="videodev">videodev2.h</link> header file. These identifiers
 represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
 which are also listed below, however they are not the same as those
 used in the Windows world.</para>
@@ -828,6 +859,9 @@ interface only.</para>
 
     &sub-sdr-cu08;
     &sub-sdr-cu16le;
+    &sub-sdr-cs08;
+    &sub-sdr-cs14le;
+    &sub-sdr-ru12le;
 
   </section>
 
@@ -1059,5 +1093,22 @@ concatenated to form the JPEG stream. </
 	  </row>
 	</tbody>
       </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="format-flags">
+      <title>Format Flags</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_PIX_FMT_FLAG_PREMUL_ALPHA</constant></entry>
+	    <entry>0x00000001</entry>
+	    <entry>The color values are premultiplied by the alpha channel
+value. For example, if a light blue pixel with 50% transparency was described by
+RGBA values (128, 192, 255, 128), the same pixel described with premultiplied
+colors would be described by RGBA values (64, 96, 128, 128) </entry>
+	  </row>
+	</tbody>
+      </tgroup>
     </table>
   </section>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/selection-api.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/selection-api.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/selection-api.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/selection-api.xml	2014-09-28 17:29:07.000000000 -0400
@@ -86,47 +86,47 @@ selection targets available for a video
 configure the cropping targets before to the composing targets.</para>
 
 <para>The range of coordinates of the top left corner, width and height of
-areas that can be sampled is given by the <constant> V4L2_SEL_TGT_CROP_BOUNDS
-</constant> target. It is recommended for the driver developers to put the
-top/left corner at position <constant> (0,0) </constant>.  The rectangle's
+areas that can be sampled is given by the <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>
+target. It is recommended for the driver developers to put the
+top/left corner at position <constant>(0,0)</constant>.  The rectangle's
 coordinates are expressed in pixels.</para>
 
 <para>The top left corner, width and height of the source rectangle, that is
-the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP
-</constant> target. It uses the same coordinate system as <constant>
-V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
-completely inside the capture boundaries. The driver may further adjust the
-requested size and/or position according to hardware limitations.</para>
+the area actually sampled, is given by the <constant>V4L2_SEL_TGT_CROP</constant>
+target. It uses the same coordinate system as <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
+The active cropping area must lie completely inside the capture boundaries. The
+driver may further adjust the requested size and/or position according to hardware
+limitations.</para>
 
 <para>Each capture device has a default source rectangle, given by the
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant> target. This rectangle shall
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant> target. This rectangle shall
 over what the driver writer considers the complete picture.  Drivers shall set
 the active crop rectangle to the default when the driver is first loaded, but
 not later.</para>
 
 <para>The composing targets refer to a memory buffer. The limits of composing
-coordinates are obtained using <constant> V4L2_SEL_TGT_COMPOSE_BOUNDS
-</constant>.  All coordinates are expressed in pixels. The rectangle's top/left
-corner must be located at position <constant> (0,0) </constant>. The width and
-height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant>.
+All coordinates are expressed in pixels. The rectangle's top/left
+corner must be located at position <constant>(0,0)</constant>. The width and
+height are equal to the image size set by <constant>VIDIOC_S_FMT</constant>.
 </para>
 
 <para>The part of a buffer into which the image is inserted by the hardware is
-controlled by the <constant> V4L2_SEL_TGT_COMPOSE </constant> target.
+controlled by the <constant>V4L2_SEL_TGT_COMPOSE</constant> target.
 The rectangle's coordinates are also expressed in the same coordinate system as
 the bounds rectangle. The composing rectangle must lie completely inside bounds
 rectangle. The driver must adjust the composing rectangle to fit to the
 bounding limits. Moreover, the driver can perform other adjustments according
 to hardware limitations. The application can control rounding behaviour using
-<link linkend="v4l2-selection-flags"> constraint flags </link>.</para>
+<link linkend="v4l2-selection-flags"> constraint flags</link>.</para>
 
 <para>For capture devices the default composing rectangle is queried using
-<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant>. It is usually equal to the
 bounding rectangle.</para>
 
 <para>The part of a buffer that is modified by the hardware is given by
-<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
-defined using <constant> V4L2_SEL_TGT_COMPOSE </constant> plus all
+<constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>. It contains all pixels
+defined using <constant>V4L2_SEL_TGT_COMPOSE</constant> plus all
 padding data modified by hardware during insertion process. All pixels outside
 this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
 content of pixels that lie inside the padded area but outside active area is
@@ -140,52 +140,51 @@ where the rubbish pixels are located and
    <title>Configuration of video output</title>
 
 <para>For output devices targets and ioctls are used similarly to the video
-capture case. The <emphasis> composing </emphasis> rectangle refers to the
+capture case. The <emphasis>composing</emphasis> rectangle refers to the
 insertion of an image into a video signal. The cropping rectangles refer to a
 memory buffer. It is recommended to configure the composing targets before to
 the cropping targets.</para>
 
 <para>The cropping targets refer to the memory buffer that contains an image to
 be inserted into a video signal or graphical screen. The limits of cropping
-coordinates are obtained using <constant> V4L2_SEL_TGT_CROP_BOUNDS </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
 All coordinates are expressed in pixels. The top/left corner is always point
-<constant> (0,0) </constant>.  The width and height is equal to the image size
-specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
+<constant>(0,0)</constant>.  The width and height is equal to the image size
+specified using <constant>VIDIOC_S_FMT</constant> ioctl.</para>
 
 <para>The top left corner, width and height of the source rectangle, that is
 the area from which image date are processed by the hardware, is given by the
-<constant> V4L2_SEL_TGT_CROP </constant>. Its coordinates are expressed
+<constant>V4L2_SEL_TGT_CROP</constant>. Its coordinates are expressed
 in in the same coordinate system as the bounds rectangle. The active cropping
 area must lie completely inside the crop boundaries and the driver may further
 adjust the requested size and/or position according to hardware
 limitations.</para>
 
 <para>For output devices the default cropping rectangle is queried using
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant>. It is usually equal to the
 bounding rectangle.</para>
 
 <para>The part of a video signal or graphics display where the image is
-inserted by the hardware is controlled by <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target.  The rectangle's coordinates
-are expressed in pixels. The composing rectangle must lie completely inside the
-bounds rectangle.  The driver must adjust the area to fit to the bounding
-limits.  Moreover, the driver can perform other adjustments according to
-hardware limitations. </para>
+inserted by the hardware is controlled by <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target.  The rectangle's coordinates are expressed in pixels. The composing
+rectangle must lie completely inside the bounds rectangle.  The driver must
+adjust the area to fit to the bounding limits.  Moreover, the driver can
+perform other adjustments according to hardware limitations.</para>
 
-<para>The device has a default composing rectangle, given by the <constant>
-V4L2_SEL_TGT_COMPOSE_DEFAULT </constant> target. This rectangle shall cover what
+<para>The device has a default composing rectangle, given by the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant> target. This rectangle shall cover what
 the driver writer considers the complete picture. It is recommended for the
-driver developers to put the top/left corner at position <constant> (0,0)
-</constant>. Drivers shall set the active composing rectangle to the default
+driver developers to put the top/left corner at position <constant>(0,0)</constant>.
+Drivers shall set the active composing rectangle to the default
 one when the driver is first loaded.</para>
 
 <para>The devices may introduce additional content to video signal other than
 an image from memory buffers.  It includes borders around an image. However,
 such a padded area is driver-dependent feature not covered by this document.
 Driver developers are encouraged to keep padded rectangle equal to active one.
-The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
-</constant> identifier.  It must contain all pixels from the <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target.</para>
+The padded target is accessed by the <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>
+identifier.  It must contain all pixels from the <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target.</para>
 
    </section>
 
@@ -194,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE </constant> target.
      <title>Scaling control</title>
 
 <para>An application can detect if scaling is performed by comparing the width
-and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
-</constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
+and the height of rectangles obtained using <constant>V4L2_SEL_TGT_CROP</constant>
+and <constant>V4L2_SEL_TGT_COMPOSE</constant> targets. If
 these are not equal then the scaling is applied. The application can compute
 the scaling ratios using these values.</para>
 
@@ -208,7 +207,7 @@ the scaling ratios using these values.</
     <title>Comparison with old cropping API</title>
 
 <para>The selection API was introduced to cope with deficiencies of previous
-<link linkend="crop"> API </link>, that was designed to control simple capture
+<link linkend="crop"> API</link>, that was designed to control simple capture
 devices. Later the cropping API was adopted by video output drivers. The ioctls
 are used to select a part of the display were the video signal is inserted. It
 should be considered as an API abuse because the described operation is
@@ -220,7 +219,7 @@ part of an image by abusing V4L2 API.  C
 one is achieved by setting the field
 &v4l2-pix-format;<structfield>::bytesperline</structfield>.  Introducing an image offsets
 could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield>
-before calling <constant> VIDIOC_QBUF </constant>. Those
+before calling <constant>VIDIOC_QBUF</constant>. Those
 operations should be avoided because they are not portable (endianness), and do
 not work for macroblock and Bayer formats and mmap buffers.  The selection API
 deals with configuration of buffer cropping/composing in a clear, intuitive and
@@ -229,7 +228,7 @@ and constraints flags are introduced.  F
 have no reserved fields. Therefore there is no way to extend their functionality.
 The new &v4l2-selection; provides a lot of place for future
 extensions.  Driver developers are encouraged to implement only selection API.
-The former cropping API would be simulated using the new one. </para>
+The former cropping API would be simulated using the new one.</para>
 
   </section>
 
@@ -238,9 +237,9 @@ The former cropping API would be simulat
       <example>
 	<title>Resetting the cropping parameters</title>
 
-	<para>(A video capture device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_CAPTURE </constant> for other devices; change target to
-<constant> V4L2_SEL_TGT_COMPOSE_* </constant> family to configure composing
+	<para>(A video capture device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other devices; change target to
+<constant>V4L2_SEL_TGT_COMPOSE_*</constant> family to configure composing
 area)</para>
 
 	<programlisting>
@@ -292,8 +291,8 @@ area)</para>
 
       <example>
 	<title>Querying for scaling factors</title>
-	<para>A video output device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
+	<para>A video output device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> for other devices</para>
 	<programlisting>
 
 	&v4l2-selection; compose = {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/v4l2.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/v4l2.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/v4l2.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/v4l2.xml	2014-09-28 17:29:07.000000000 -0400
@@ -152,6 +152,15 @@ structs, ioctls) must be noted in more d
 applications. -->
 
       <revision>
+	<revnumber>3.17</revnumber>
+	<date>2014-08-04</date>
+	<authorinitials>lp, hv</authorinitials>
+	<revremark>Extended &v4l2-pix-format;. Added format flags. Added compound control types
+and VIDIOC_QUERY_EXT_CTRL.
+	</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.15</revnumber>
 	<date>2014-02-03</date>
 	<authorinitials>hv, ap</authorinitials>
@@ -530,7 +539,7 @@ and discussions on the V4L mailing list.
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.14</subtitle>
+ <subtitle>Revision 3.17</subtitle>
 
   <chapter id="common">
     &sub-common;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2014-09-28 17:29:07.000000000 -0400
@@ -94,6 +94,18 @@
 	  </row>
 	  <row>
 	    <entry></entry>
+	    <entry>&v4l2-event-motion-det;</entry>
+            <entry><structfield>motion_det</structfield></entry>
+	    <entry>Event data for event V4L2_EVENT_MOTION_DET.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>&v4l2-event-src-change;</entry>
+            <entry><structfield>src_change</structfield></entry>
+	    <entry>Event data for event V4L2_EVENT_SOURCE_CHANGE.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
 	    <entry>__u8</entry>
             <entry><structfield>data</structfield>[64]</entry>
 	    <entry>Event data. Defined by the event type. The union
@@ -255,6 +267,44 @@
 	    </entry>
 	  </row>
 	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-motion-det">
+      <title>struct <structname>v4l2_event_motion_det</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>
+	      Currently only one flag is available: if <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant>
+	      is set, then the <structfield>frame_sequence</structfield> field is valid,
+	      otherwise that field should be ignored.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>frame_sequence</structfield></entry>
+	    <entry>
+	      The sequence number of the frame being received. Only valid if the
+	      <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant> flag was set.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>region_mask</structfield></entry>
+	    <entry>
+	      The bitmask of the regions that reported motion. There is at least one
+	      region. If this field is 0, then no motion was detected at all.
+	      If there is no <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> control
+	      (see <xref linkend="detect-controls" />) to assign a different region
+	      to each cell in the motion detection grid, then that all cells
+	      are automatically assigned to the default region 0.
+	    </entry>
+	  </row>
+	</tbody>
       </tgroup>
     </table>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml	2014-09-28 17:29:07.000000000 -0400
@@ -72,23 +72,30 @@ initialize the <structfield>id</structfi
 <structfield>size</structfield> and <structfield>reserved2</structfield> fields
 of each &v4l2-ext-control; and call the
 <constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
-must also set the <structfield>string</structfield> field.</para>
+must also set the <structfield>string</structfield> field. Controls
+of compound types (<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set)
+must set the <structfield>ptr</structfield> field.</para>
 
     <para>If the <structfield>size</structfield> is too small to
 receive the control result (only relevant for pointer-type controls
 like strings), then the driver will set <structfield>size</structfield>
 to a valid value and return an &ENOSPC;. You should re-allocate the
-string memory to this new size and try again. It is possible that the
-same issue occurs again if the string has grown in the meantime. It is
+memory to this new size and try again. For the string type it is possible that
+the same issue occurs again if the string has grown in the meantime. It is
 recommended to call &VIDIOC-QUERYCTRL; first and use
 <structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
 value. It is guaranteed that that is sufficient memory.
 </para>
 
+    <para>N-dimensional arrays are set and retrieved row-by-row. You cannot set a partial
+array, all elements have to be set or retrieved. The total size is calculated
+as <structfield>elems</structfield> * <structfield>elem_size</structfield>.
+These values can be obtained by calling &VIDIOC-QUERY-EXT-CTRL;.</para>
+
     <para>To change the value of a set of controls applications
 initialize the <structfield>id</structfield>, <structfield>size</structfield>,
 <structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
 call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
 will only be set if <emphasis>all</emphasis> control values are
 valid.</para>
@@ -96,7 +103,7 @@ valid.</para>
     <para>To check if a set of controls have correct values applications
 initialize the <structfield>id</structfield>, <structfield>size</structfield>,
 <structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
 call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
 the driver whether wrong values are automatically adjusted to a valid
 value or if an error is returned.</para>
@@ -158,19 +165,47 @@ applications must set the array to zero.
 	    <entry></entry>
 	    <entry>__s32</entry>
 	    <entry><structfield>value</structfield></entry>
-	    <entry>New value or current value.</entry>
+	    <entry>New value or current value. Valid if this control is not of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>__s64</entry>
 	    <entry><structfield>value64</structfield></entry>
-	    <entry>New value or current value.</entry>
+	    <entry>New value or current value. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>char *</entry>
 	    <entry><structfield>string</structfield></entry>
-	    <entry>A pointer to a string.</entry>
+	    <entry>A pointer to a string. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u8 *</entry>
+	    <entry><structfield>p_u8</structfield></entry>
+	    <entry>A pointer to a matrix control of unsigned 8-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U8</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u16 *</entry>
+	    <entry><structfield>p_u16</structfield></entry>
+	    <entry>A pointer to a matrix control of unsigned 16-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U16</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>void *</entry>
+	    <entry><structfield>ptr</structfield></entry>
+	    <entry>A pointer to a compound type which can be an N-dimensional array and/or a
+compound type (the control's type is >= <constant>V4L2_CTRL_COMPOUND_TYPES</constant>).
+Valid if <constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set for this control.
+</entry>
 	  </row>
 	</tbody>
       </tgroup>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml	2014-09-28 17:29:07.000000000 -0400
@@ -152,13 +152,10 @@ a valid base address, so applications ca
 framebuffer device (see <xref linkend="osd" />).</entry>
 	  </row>
 	  <row>
-	    <entry>&v4l2-pix-format;</entry>
+	    <entry>struct</entry>
 	    <entry><structfield>fmt</structfield></entry>
 	    <entry></entry>
-	    <entry>Layout of the frame buffer. The
-<structname>v4l2_pix_format</structname> structure is defined in <xref
-linkend="pixfmt" />, for clarification the fields and acceptable values
-	    are listed below:</entry>
+	    <entry>Layout of the frame buffer.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
@@ -276,9 +273,8 @@ see <xref linkend="colorspaces" />.</ent
 	    <entry></entry>
 	    <entry>__u32</entry>
 	    <entry><structfield>priv</structfield></entry>
-	    <entry>Reserved for additional information about custom
-(driver defined) formats. When not used drivers and applications must
-set this field to zero.</entry>
+	    <entry>Reserved. Drivers and applications must set this field to
+zero.</entry>
 	  </row>
 	</tbody>
       </tgroup>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml	2014-09-28 17:29:07.000000000 -0400
@@ -58,17 +58,16 @@
 
     <para>The ioctls are used to query and configure selection rectangles.</para>
 
-<para> To query the cropping (composing) rectangle set &v4l2-selection;
+<para>To query the cropping (composing) rectangle set &v4l2-selection;
 <structfield> type </structfield> field to the respective buffer type.
-Do not use multiplanar buffers.  Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>.  Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>.  The next step is
+Do not use multiplanar buffers.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>.  Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.  The next step is
 setting the value of &v4l2-selection; <structfield>target</structfield> field
-to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>).  Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets.  The <structfield>flags</structfield> and <structfield>reserved
+to <constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets.  The <structfield>flags</structfield> and <structfield>reserved
 </structfield> fields of &v4l2-selection; are ignored and they must be filled
 with zeros.  The driver fills the rest of the structure or
 returns &EINVAL; if incorrect buffer type or target was used. If cropping
@@ -77,19 +76,18 @@ always equal to the bounds rectangle.  F
 <structfield>r</structfield> rectangle is filled with the current cropping
 (composing) coordinates. The coordinates are expressed in driver-dependent
 units. The only exception are rectangles for images in raw formats, whose
-coordinates are always expressed in pixels.  </para>
+coordinates are always expressed in pixels.</para>
 
-<para> To change the cropping (composing) rectangle set the &v4l2-selection;
+<para>To change the cropping (composing) rectangle set the &v4l2-selection;
 <structfield>type</structfield> field to the respective buffer type.  Do not
-use multiplanar buffers.  Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>.  Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>.  The next step is
+use multiplanar buffers.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>.  Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.  The next step is
 setting the value of &v4l2-selection; <structfield>target</structfield> to
-<constant>V4L2_SEL_TGT_CROP</constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets.  The &v4l2-rect; <structfield>r</structfield> rectangle need to be
+<constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets.  The &v4l2-rect; <structfield>r</structfield> rectangle need to be
 set to the desired active area. Field &v4l2-selection; <structfield> reserved
 </structfield> is ignored and must be filled with zeros.  The driver may adjust
 coordinates of the requested rectangle. An application may
@@ -149,8 +147,8 @@ On success the &v4l2-rect; <structfield>
 the adjusted rectangle. When the parameters are unsuitable the application may
 modify the cropping (composing) or image parameters and repeat the cycle until
 satisfactory parameters have been negotiated. If constraints flags have to be
-violated at then ERANGE is returned. The error indicates that <emphasis> there
-exist no rectangle </emphasis> that satisfies the constraints.</para>
+violated at then ERANGE is returned. The error indicates that <emphasis>there
+exist no rectangle</emphasis> that satisfies the constraints.</para>
 
   <para>Selection targets and flags are documented in <xref
   linkend="v4l2-selections-common"/>.</para>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-querycap.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-querycap.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-querycap.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-querycap.xml	2014-09-28 17:29:07.000000000 -0400
@@ -302,6 +302,12 @@ modulator programming see
 <link linkend="sdr">SDR Capture</link> interface.</entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></entry>
+	    <entry>0x00200000</entry>
+	    <entry>The device supports the &v4l2-pix-format; extended
+fields.</entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_CAP_READWRITE</constant></entry>
 	    <entry>0x01000000</entry>
 	    <entry>The device supports the <link
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2014-09-28 17:29:07.000000000 -0400
@@ -1,11 +1,12 @@
 <refentry id="vidioc-queryctrl">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_QUERYCTRL</refname>
+    <refname>VIDIOC_QUERY_EXT_CTRL</refname>
     <refname>VIDIOC_QUERYMENU</refname>
     <refpurpose>Enumerate controls and menu control items</refpurpose>
   </refnamediv>
@@ -24,6 +25,14 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
 	<paramdef>struct v4l2_querymenu *<parameter>argp</parameter></paramdef>
       </funcprototype>
     </funcsynopsis>
@@ -42,7 +51,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</para>
+	  <para>VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -67,7 +76,7 @@ structure. The driver fills the rest of
 <constant>VIDIOC_QUERYCTRL</constant> with successive
 <structfield>id</structfield> values starting from
 <constant>V4L2_CID_BASE</constant> up to and exclusive
-<constant>V4L2_CID_BASE_LASTP1</constant>. Drivers may return
+<constant>V4L2_CID_LASTP1</constant>. Drivers may return
 <errorcode>EINVAL</errorcode> if a control in this range is not
 supported. Further applications can enumerate private controls, which
 are not defined in this specification, by starting at
@@ -89,9 +98,23 @@ prematurely end the enumeration).</para>
 
     <para>When the application ORs <structfield>id</structfield> with
 <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
-next supported control, or <errorcode>EINVAL</errorcode> if there is
-none. Drivers which do not support this flag yet always return
-<errorcode>EINVAL</errorcode>.</para>
+next supported non-compound control, or <errorcode>EINVAL</errorcode>
+if there is none. In addition, the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+flag can be specified to enumerate all compound controls (i.e. controls
+with type &ge; <constant>V4L2_CTRL_COMPOUND_TYPES</constant>). Specify both
+<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
+<constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> in order to enumerate
+all controls, compound or not. Drivers which do not support these flags yet
+always return <errorcode>EINVAL</errorcode>.</para>
+
+    <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
+introduced in order to better support controls that can use compound
+types, and to expose additional control information that cannot be
+returned in &v4l2-queryctrl; since that structure is full.</para>
+
+    <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
+same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
+<structfield>reserved</structfield> array must be zeroed as well.</para>
 
     <para>Additional information is required for menu controls: the
 names of the menu items. To query them applications set the
@@ -142,38 +165,23 @@ string. This information is intended for
 	    <entry>__s32</entry>
 	    <entry><structfield>minimum</structfield></entry>
 	    <entry>Minimum value, inclusive. This field gives a lower
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
-gives the minimum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
 	  </row>
 	  <row>
 	    <entry>__s32</entry>
 	    <entry><structfield>maximum</structfield></entry>
 	    <entry>Maximum value, inclusive. This field gives an upper
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
-controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
-set of usable bits.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
-gives the maximum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
 	  </row>
 	  <row>
 	    <entry>__s32</entry>
 	    <entry><structfield>step</structfield></entry>
-	    <entry><para>This field gives a step size for
-<constant>V4L2_CTRL_TYPE_INTEGER</constant> controls. For
-<constant>V4L2_CTRL_TYPE_STRING</constant> controls this field refers to
-the string length that has to be a multiple of this step size.
-It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant>
-controls.</para><para>Generally drivers should not scale hardware
+	    <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 32-bit value.
+</para><para>Generally drivers should not scale hardware
 control values. It may be necessary for example when the
 <structfield>name</structfield> or <structfield>id</structfield> imply
 a particular unit and the hardware actually accepts only multiples of
@@ -192,10 +200,11 @@ be always positive.</para></entry>
 	    <entry><structfield>default_value</structfield></entry>
 	    <entry>The default value of a
 <constant>V4L2_CTRL_TYPE_INTEGER</constant>,
-<constant>_BOOLEAN</constant> or <constant>_MENU</constant> control.
-Not valid for other types of controls. Drivers reset controls only
-when the driver is loaded, not later, in particular not when the
-func-open; is called.</entry>
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -213,6 +222,126 @@ the array to zero.</entry>
       </tgroup>
     </table>
 
+    <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
+      <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>id</structfield></entry>
+	    <entry>Identifies the control, set by the application. See
+<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
+with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
+flag and returns the first non-compound control with a higher ID. When the
+ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> the driver
+clears the flag and returns the first compound control with a higher ID.
+Set both to get the first control (compound or not) with a higher ID.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>Type of control, see <xref
+		linkend="v4l2-ctrl-type" />.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>name</structfield>[32]</entry>
+	    <entry>Name of the control, a NUL-terminated ASCII
+string. This information is intended for the user.</entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>minimum</structfield></entry>
+	    <entry>Minimum value, inclusive. This field gives a lower
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>maximum</structfield></entry>
+	    <entry>Maximum value, inclusive. This field gives an upper
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+	  </row>
+	  <row>
+	    <entry>__u64</entry>
+	    <entry><structfield>step</structfield></entry>
+	    <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 64-bit value.
+</para><para>Generally drivers should not scale hardware
+control values. It may be necessary for example when the
+<structfield>name</structfield> or <structfield>id</structfield> imply
+a particular unit and the hardware actually accepts only multiples of
+said unit. If so, drivers must take care values are properly rounded
+when scaling, such that errors will not accumulate on repeated
+read-write cycles.</para><para>This field gives the smallest change of
+an integer control actually affecting hardware. Often the information
+is needed when the user can change controls by keyboard or GUI
+buttons, rather than a slider. When for example a hardware register
+accepts values 0-511 and the driver reports 0-65535, step should be
+128.</para></entry>
+	  </row>
+	  <row>
+	    <entry>__s64</entry>
+	    <entry><structfield>default_value</structfield></entry>
+	    <entry>The default value of a
+<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant>, <constant>_INTEGER_MENU</constant>,
+<constant>_U8</constant> or <constant>_U16</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.
+</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Control flags, see <xref
+		linkend="control-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>elem_size</structfield></entry>
+	    <entry>The size in bytes of a single element of the array.
+Given a char pointer <constant>p</constant> to a 3-dimensional array you can find the
+position of cell <constant>(z, y, x)</constant> as follows:
+<constant>p + ((z * dims[1] + y) * dims[0] + x) * elem_size</constant>. <structfield>elem_size</structfield>
+is always valid, also when the control isn't an array. For string controls
+<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
+</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>elems</structfield></entry>
+	    <entry>The number of elements in the N-dimensional array. If this control
+is not an array, then <structfield>elems</structfield> is 1. The <structfield>elems</structfield>
+field can never be 0.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>nr_of_dims</structfield></entry>
+	    <entry>The number of dimension in the N-dimensional array. If this control
+is not an array, then this field is 0.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>dims[V4L2_CTRL_MAX_DIMS]</structfield></entry>
+	    <entry>The size of each dimension. The first <structfield>nr_of_dims</structfield>
+elements of this array must be non-zero, all remaining elements must be zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[32]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers
+must set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
     <table pgwide="1" frame="none" id="v4l2-querymenu">
       <title>struct <structname>v4l2_querymenu</structname></title>
       <tgroup cols="4">
@@ -347,11 +476,14 @@ Drivers must ignore the value passed wit
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
-	    <entry>n/a</entry>
-	    <entry>n/a</entry>
-	    <entry>n/a</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
 	    <entry>A 64-bit integer valued control. Minimum, maximum
-and step size cannot be queried.</entry>
+and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
+Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
+min/max/step values, they should be interpreted as n/a when using
+<constant>VIDIOC_QUERYCTRL</constant>.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
@@ -379,6 +511,26 @@ ioctl returns the name of the control cl
 Older drivers which do not support this feature return an
 &EINVAL;.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_TYPE_U8</constant></entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>An unsigned 8-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_TYPE_U16</constant></entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>any</entry>
+	    <entry>An unsigned 16-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
@@ -450,6 +602,14 @@ is in auto-gain mode. In such a case the
 the lighting conditions which can change over time. Note that setting a new value for
 a volatile control will have no effect. The new value will just be ignored.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
+	    <entry>0x0100</entry>
+	    <entry>This control has a pointer type, so its value has to be accessed
+using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
+that are an array, string, or have a compound type. In all cases you have to set a
+pointer to memory containing the payload of the control.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml	2014-09-28 17:29:07.000000000 -0400
@@ -119,7 +119,7 @@
 	  </row>
 	  <row>
 	    <entry>&v4l2-rect;</entry>
-	    <entry><structfield>rect</structfield></entry>
+	    <entry><structfield>r</structfield></entry>
 	    <entry>Selection rectangle, in pixels.</entry>
 	  </row>
 	  <row>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
--- linux-libre-3.16-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2014-09-28 17:29:07.000000000 -0400
@@ -175,6 +175,14 @@
 	    </entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
+	    <entry>5</entry>
+	    <entry>
+	      <para>Triggered whenever the motion detection state for one or more of the regions
+	      changes. This event has a &v4l2-event-motion-det; associated with it.</para>
+	    </entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
 	    <entry>0x08000000</entry>
 	    <entry>Base event number for driver-private events.</entry>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/driver-model/devres.txt linux-libre-3.17-rc7-gnu/Documentation/driver-model/devres.txt
--- linux-libre-3.16-gnu/Documentation/driver-model/devres.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/driver-model/devres.txt	2014-09-28 17:29:07.000000000 -0400
@@ -233,66 +233,78 @@ certainly invest a bit more effort into
   6. List of managed interfaces
   -----------------------------
 
-MEM
-  devm_kzalloc()
-  devm_kfree()
-  devm_kmemdup()
-  devm_get_free_pages()
-  devm_free_pages()
+CLOCK
+  devm_clk_get()
+  devm_clk_put()
+
+DMA
+  dmam_alloc_coherent()
+  dmam_alloc_noncoherent()
+  dmam_declare_coherent_memory()
+  dmam_free_coherent()
+  dmam_free_noncoherent()
+  dmam_pool_create()
+  dmam_pool_destroy()
+
+GPIO
+  devm_gpiod_get()
+  devm_gpiod_get_index()
+  devm_gpiod_get_index_optional()
+  devm_gpiod_get_optional()
+  devm_gpiod_put()
 
 IIO
   devm_iio_device_alloc()
   devm_iio_device_free()
-  devm_iio_trigger_alloc()
-  devm_iio_trigger_free()
   devm_iio_device_register()
   devm_iio_device_unregister()
+  devm_iio_trigger_alloc()
+  devm_iio_trigger_free()
 
 IO region
-  devm_request_region()
-  devm_request_mem_region()
-  devm_release_region()
   devm_release_mem_region()
-
-IRQ
-  devm_request_irq()
-  devm_free_irq()
-
-DMA
-  dmam_alloc_coherent()
-  dmam_free_coherent()
-  dmam_alloc_noncoherent()
-  dmam_free_noncoherent()
-  dmam_declare_coherent_memory()
-  dmam_pool_create()
-  dmam_pool_destroy()
-
-PCI
-  pcim_enable_device()	: after success, all PCI ops become managed
-  pcim_pin_device()	: keep PCI device enabled after release
+  devm_release_region()
+  devm_request_mem_region()
+  devm_request_region()
 
 IOMAP
   devm_ioport_map()
   devm_ioport_unmap()
   devm_ioremap()
   devm_ioremap_nocache()
-  devm_iounmap()
   devm_ioremap_resource() : checks resource, requests memory region, ioremaps
-  devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
+  devm_iounmap()
   pcim_iomap()
-  pcim_iounmap()
-  pcim_iomap_table()	: array of mapped addresses indexed by BAR
   pcim_iomap_regions()	: do request_region() and iomap() on multiple BARs
+  pcim_iomap_table()	: array of mapped addresses indexed by BAR
+  pcim_iounmap()
 
-REGULATOR
-  devm_regulator_get()
-  devm_regulator_put()
-  devm_regulator_bulk_get()
-  devm_regulator_register()
+IRQ
+  devm_free_irq()
+  devm_request_irq()
 
-CLOCK
-  devm_clk_get()
-  devm_clk_put()
+MDIO
+  devm_mdiobus_alloc()
+  devm_mdiobus_alloc_size()
+  devm_mdiobus_free()
+
+MEM
+  devm_free_pages()
+  devm_get_free_pages()
+  devm_kcalloc()
+  devm_kfree()
+  devm_kmalloc()
+  devm_kmalloc_array()
+  devm_kmemdup()
+  devm_kzalloc()
+
+PCI
+  pcim_enable_device()	: after success, all PCI ops become managed
+  pcim_pin_device()	: keep PCI device enabled after release
+
+PHY
+  devm_usb_get_phy()
+  devm_usb_put_phy()
 
 PINCTRL
   devm_pinctrl_get()
@@ -302,24 +314,14 @@ PWM
   devm_pwm_get()
   devm_pwm_put()
 
-PHY
-  devm_usb_get_phy()
-  devm_usb_put_phy()
+REGULATOR
+  devm_regulator_bulk_get()
+  devm_regulator_get()
+  devm_regulator_put()
+  devm_regulator_register()
 
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
 
 SPI
   devm_spi_register_master()
-
-GPIO
-  devm_gpiod_get()
-  devm_gpiod_get_index()
-  devm_gpiod_get_optional()
-  devm_gpiod_get_index_optional()
-  devm_gpiod_put()
-
-MDIO
-  devm_mdiobus_alloc()
-  devm_mdiobus_alloc_size()
-  devm_mdiobus_free()
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/caching/operations.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/caching/operations.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/caching/operations.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/caching/operations.txt	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,7 @@ operations:
      to be cleared before proceeding:
 
 		wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
-			    fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+			    TASK_UNINTERRUPTIBLE);
 
 
  (2) The operation may be fast asynchronous (FSCACHE_OP_FAST), in which case it
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/cifs/AUTHORS linux-libre-3.17-rc7-gnu/Documentation/filesystems/cifs/AUTHORS
--- linux-libre-3.16-gnu/Documentation/filesystems/cifs/AUTHORS	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/cifs/AUTHORS	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,7 @@ Gunter Kukkukk (testing and suggestions
 Igor Mammedov (DFS support)
 Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
 Scott Lovenberg
+Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
 
 Test case and Bug Report contributors
 -------------------------------------
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/cifs/TODO linux-libre-3.17-rc7-gnu/Documentation/filesystems/cifs/TODO
--- linux-libre-3.16-gnu/Documentation/filesystems/cifs/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/cifs/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,4 @@
-Version 1.53 May 20, 2008
+Version 2.03 August 1, 2014
 
 A Partial List of Missing Features
 ==================================
@@ -7,63 +7,49 @@ Contributions are welcome.  There are pl
 for visible, important contributions to this module.  Here
 is a partial list of the known problems and missing features:
 
-a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown
-so that these operations can be supported to Windows servers
-
-b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS
-SecurityDescriptors
-
-c) Better pam/winbind integration (e.g. to handle uid mapping
-better)
-
-d) Cleanup now unneeded SessSetup code in
-fs/cifs/connect.c and add back in NTLMSSP code if any servers
-need it
+a) SMB3 (and SMB3.02) missing optional features:
+   - RDMA
+   - multichannel (started)
+   - directory leases (improved metadata caching)
+   - T10 copy offload (copy chunk is only mechanism supported)
+   - encrypted shares
 
-e) fix NTLMv2 signing when two mounts with different users to same
-server.
+b) improved sparse file support
 
-f) Directory entry caching relies on a 1 second timer, rather than 
+c) Directory entry caching relies on a 1 second timer, rather than
 using FindNotify or equivalent.  - (started)
 
-g) quota support (needs minor kernel change since quota calls
+d) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-h) investigate sync behavior (including syncpage) and check  
-for proper behavior of intr/nointr
-
-i) improve support for very old servers (OS/2 and Win9x for example)
+e) improve support for very old servers (OS/2 and Win9x for example)
 Including support for changing the time remotely (utimes command).
 
-j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+f) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
 extra copy in/out of the socket buffers in some cases.
 
-k) Better optimize open (and pathbased setfilesize) to reduce the
+g) Better optimize open (and pathbased setfilesize) to reduce the
 oplock breaks coming from windows srv.  Piggyback identical file
 opens on top of each other by incrementing reference count rather
 than resending (helps reduce server resource utilization and avoid
 spurious oplock breaks).
 
-l) Improve performance of readpages by sending more than one read
-at a time when 8 pages or more are requested. In conjuntion
-add support for async_cifs_readpages.
-
-m) Add support for storing symlink info to Windows servers 
+h) Add support for storing symlink info to Windows servers
 in the Extended Attribute format their SFU clients would recognize.
 
-n) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+i) Finish inotify support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
 vfs change to support removing D_NOTIFY on a file.   
 
-o) Add GUI tool to configure /proc/fs/cifs settings and for display of
+j) Add GUI tool to configure /proc/fs/cifs settings and for display of
 the CIFS statistics (started)
 
-p) implement support for security and trusted categories of xattrs
+k) implement support for security and trusted categories of xattrs
 (requires minor protocol extension) to enable better support for SELINUX
 
-q) Implement O_DIRECT flag on open (already supported on mount)
+l) Implement O_DIRECT flag on open (already supported on mount)
 
-r) Create UID mapping facility so server UIDs can be mapped on a per
+m) Create UID mapping facility so server UIDs can be mapped on a per
 mount or a per server basis to client UIDs or nobody if no mapping
 exists.  This is helpful when Unix extensions are negotiated to
 allow better permission checking when UIDs differ on the server
@@ -71,28 +57,29 @@ and client.  Add new protocol request to
 standard for asking the server for the corresponding name of a
 particular uid.
 
-s) Add support for CIFS Unix and also the newer POSIX extensions to the
-server side for Samba 4.
+n) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
 
-t) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) 
-need to add ability to set time to server (utimes command)
+o) mount check for unmatched uids
 
-u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+p) Add support for new vfs entry point for fallocate
 
-v) mount check for unmatched uids
+q) Add tools to take advantage of cifs/smb3 specific ioctls and features
+such as "CopyChunk" (fast server side file copy)
 
-w) Add support for new vfs entry point for fallocate
+r) encrypted file support
 
-x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of 
-processes can proceed better in parallel (on the server)
+s) improved stats gathering, tools (perhaps integration with nfsometer?)
 
-y) Fix Samba 3 to handle reads/writes over 127K (and remove the cifs mount
-restriction of wsize max being 127K) 
+t) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
+file attribute via chflags)
 
-KNOWN BUGS (updated April 24, 2007)
+u) mount helper GUI (to simplify the various configuration options on mount)
+
+
+KNOWN BUGS
 ====================================
 See http://bugzilla.samba.org - search on product "CifsVFS" for
-current bug list.
+current bug list.  Also check http://bugzilla.kernel.org (Product = File System, Component = CIFS)
 
 1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
@@ -100,30 +87,18 @@ support the CIFS Unix extensions, althou
 overly restrict the pathnames.
 2) follow_link and readdir code does not follow dfs junctions
 but recognizes them
-3) create of new files to FAT partitions on Windows servers can
-succeed but still return access denied (appears to be Windows 
-server not cifs client problem) and has not been reproduced recently.
-NTFS partitions do not have this problem.
-4) Unix/POSIX capabilities are reset after reconnection, and affect
-a few fields in the tree connection but we do do not know which
-superblocks to apply these changes to.  We should probably walk
-the list of superblocks to set these.  Also need to check the
-flags on the second mount to the same share, and see if we
-can do the same trick that NFS does to remount duplicate shares.
 
 Misc testing to do
 ==================
 1) check out max path names and max path name components against various server
 types. Try nested symlinks (8 deep). Return max path name in stat -f information
 
-2) Modify file portion of ltp so it can run against a mounted network
-share and run it against cifs vfs in automated fashion.
+2) Improve xfstest's cifs enablement and adapt xfstests where needed to test
+cifs better
 
 3) Additional performance testing and optimization using iozone and similar - 
 there are some easy changes that can be done to parallelize sequential writes,
 and when signing is disabled to request larger read sizes (larger than 
 negotiated size) and send larger write sizes to modern servers.
 
-4) More exhaustively test against less common servers.  More testing
-against Windows 9x, Windows ME servers.
-
+4) More exhaustively test against less common servers
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/f2fs.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/f2fs.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/f2fs.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/f2fs.txt	2014-09-28 17:29:07.000000000 -0400
@@ -126,6 +126,11 @@ flush_merge	       Merge concurrent cach
                        to eliminate redundant command issues. If the underlying
 		       device handles the cache_flush command relatively slowly,
 		       recommend to enable this option.
+nobarrier              This option can be used if underlying storage guarantees
+                       its cached data should be written to the novolatile area.
+		       If this option is set, no cache_flush commands are issued
+		       but f2fs still guarantees the write ordering of all the
+		       data writes.
 
 ================================================================================
 DEBUGFS ENTRIES
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/Locking linux-libre-3.17-rc7-gnu/Documentation/filesystems/Locking
--- linux-libre-3.16-gnu/Documentation/filesystems/Locking	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/Locking	2014-09-28 17:29:07.000000000 -0400
@@ -349,7 +349,11 @@ prototypes:
 locking rules:
 			inode->i_lock	may block
 fl_copy_lock:		yes		no
-fl_release_private:	maybe		no
+fl_release_private:	maybe		maybe[1]
+
+[1]:	->fl_release_private for flock or POSIX locks is currently allowed
+to block. Leases however can still be freed while the i_lock is held and
+so fl_release_private called on a lease should not block.
 
 ----------------------- lock_manager_operations ---------------------------
 prototypes:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/nfs/Exporting linux-libre-3.17-rc7-gnu/Documentation/filesystems/nfs/Exporting
--- linux-libre-3.16-gnu/Documentation/filesystems/nfs/Exporting	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/nfs/Exporting	2014-09-28 17:29:07.000000000 -0400
@@ -66,23 +66,31 @@ b/ A per-superblock list "s_anon" of den
 
 c/ Helper routines to allocate anonymous dentries, and to help attach
    loose directory dentries at lookup time. They are:
-    d_alloc_anon(inode) will return a dentry for the given inode.
+    d_obtain_alias(inode) will return a dentry for the given inode.
       If the inode already has a dentry, one of those is returned.
       If it doesn't, a new anonymous (IS_ROOT and
         DCACHE_DISCONNECTED) dentry is allocated and attached.
       In the case of a directory, care is taken that only one dentry
       can ever be attached.
-    d_splice_alias(inode, dentry) will make sure that there is a
-      dentry with the same name and parent as the given dentry, and
-      which refers to the given inode.
-      If the inode is a directory and already has a dentry, then that
-      dentry is d_moved over the given dentry.
-      If the passed dentry gets attached, care is taken that this is
-      mutually exclusive to a d_alloc_anon operation.
-      If the passed dentry is used, NULL is returned, else the used
-      dentry is returned.  This corresponds to the calling pattern of
-      ->lookup.
-  
+    d_splice_alias(inode, dentry) or d_materialise_unique(dentry, inode)
+      will introduce a new dentry into the tree; either the passed-in
+      dentry or a preexisting alias for the given inode (such as an
+      anonymous one created by d_obtain_alias), if appropriate.  The two
+      functions differ in their handling of directories with preexisting
+      aliases:
+        d_splice_alias will use any existing IS_ROOT dentry, but it will
+	  return -EIO rather than try to move a dentry with a different
+	  parent.  This is appropriate for local filesystems, which
+	  should never see such an alias unless the filesystem is
+	  corrupted somehow (for example, if two on-disk directory
+	  entries refer to the same directory.)
+	d_materialise_unique will attempt to move any dentry.  This is
+	  appropriate for distributed filesystems, where finding a
+	  directory other than where we last cached it may be a normal
+	  consequence of concurrent operations on other hosts.
+      Both functions return NULL when the passed-in dentry is used,
+      following the calling convention of ->lookup.
+
  
 Filesystem Issues
 -----------------
@@ -120,12 +128,12 @@ struct which has the following members:
 
   fh_to_dentry (mandatory)
     Given a filehandle fragment, this should find the implied object and
-    create a dentry for it (possibly with d_alloc_anon).
+    create a dentry for it (possibly with d_obtain_alias).
 
   fh_to_parent (optional but strongly recommended)
     Given a filehandle fragment, this should find the parent of the
-    implied object and create a dentry for it (possibly with d_alloc_anon).
-    May fail if the filehandle fragment is too small.
+    implied object and create a dentry for it (possibly with
+    d_obtain_alias).  May fail if the filehandle fragment is too small.
 
   get_parent (optional but strongly recommended)
     When given a dentry for a directory, this should return  a dentry for
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/nfs/nfs-rdma.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/nfs/nfs-rdma.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/nfs/nfs-rdma.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/nfs/nfs-rdma.txt	2014-09-28 17:29:07.000000000 -0400
@@ -138,9 +138,9 @@ Installation
   - Build, install, reboot
 
     The NFS/RDMA code will be enabled automatically if NFS and RDMA
-    are turned on. The NFS/RDMA client and server are configured via the hidden
-    SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The
-    value of SUNRPC_XPRT_RDMA will be:
+    are turned on. The NFS/RDMA client and server are configured via the
+    SUNRPC_XPRT_RDMA_CLIENT and SUNRPC_XPRT_RDMA_SERVER config options that both
+    depend on SUNRPC and INFINIBAND. The default value of both options will be:
 
      - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client
        and server will not be built
@@ -235,8 +235,9 @@ NFS/RDMA Setup
 
   - Start the NFS server
 
-    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
-    kernel config), load the RDMA transport module:
+    If the NFS/RDMA server was built as a module
+    (CONFIG_SUNRPC_XPRT_RDMA_SERVER=m in kernel config), load the RDMA
+    transport module:
 
     $ modprobe svcrdma
 
@@ -255,8 +256,9 @@ NFS/RDMA Setup
 
   - On the client system
 
-    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
-    kernel config), load the RDMA client module:
+    If the NFS/RDMA client was built as a module
+    (CONFIG_SUNRPC_XPRT_RDMA_CLIENT=m in kernel config), load the RDMA client
+    module:
 
     $ modprobe xprtrdma.ko
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/proc.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/proc.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/proc.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/proc.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1743,6 +1743,25 @@ pair provide additional information part
 	While the first three lines are mandatory and always printed, the rest is
 	optional and may be omitted if no marks created yet.
 
+	Timerfd files
+	~~~~~~~~~~~~~
+
+	pos:	0
+	flags:	02
+	mnt_id:	9
+	clockid: 0
+	ticks: 0
+	settime flags: 01
+	it_value: (0, 49406829)
+	it_interval: (1, 0)
+
+	where 'clockid' is the clock type and 'ticks' is the number of the timer expirations
+	that have occurred [see timerfd_create(2) for details]. 'settime flags' are
+	flags in octal form been used to setup the timer [see timerfd_settime(2) for
+	details]. 'it_value' is remaining time until the timer exiration.
+	'it_interval' is the interval for the timer. Note the timer might be set up
+	with TIMER_ABSTIME option which will be shown in 'settime flags', but 'it_value'
+	still exhibits timer's remaining time.
 
 ------------------------------------------------------------------------------
 Configuring procfs
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/seq_file.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/seq_file.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/seq_file.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/seq_file.txt	2014-09-28 17:29:07.000000000 -0400
@@ -235,6 +235,39 @@ be used for more than one file, you can
 private field of the seq_file structure; that value can then be retrieved
 by the iterator functions.
 
+There is also a wrapper function to seq_open() called seq_open_private(). It
+kmallocs a zero filled block of memory and stores a pointer to it in the
+private field of the seq_file structure, returning 0 on success. The
+block size is specified in a third parameter to the function, e.g.:
+
+	static int ct_open(struct inode *inode, struct file *file)
+	{
+		return seq_open_private(file, &ct_seq_ops,
+					sizeof(struct mystruct));
+	}
+
+There is also a variant function, __seq_open_private(), which is functionally
+identical except that, if successful, it returns the pointer to the allocated
+memory block, allowing further initialisation e.g.:
+
+	static int ct_open(struct inode *inode, struct file *file)
+	{
+		struct mystruct *p =
+			__seq_open_private(file, &ct_seq_ops, sizeof(*p));
+
+		if (!p)
+			return -ENOMEM;
+
+		p->foo = bar; /* initialize my stuff */
+			...
+		p->baz = true;
+
+		return 0;
+	}
+
+A corresponding close function, seq_release_private() is available which
+frees the memory allocated in the corresponding open.
+
 The other operations of interest - read(), llseek(), and release() - are
 all implemented by the seq_file code itself. So a virtual file's
 file_operations structure will look like:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/filesystems/vfs.txt linux-libre-3.17-rc7-gnu/Documentation/filesystems/vfs.txt
--- linux-libre-3.16-gnu/Documentation/filesystems/vfs.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/filesystems/vfs.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1053,7 +1053,8 @@ struct dentry_operations {
 	If the 'rcu_walk' parameter is true, then the caller is doing a
 	pathwalk in RCU-walk mode.  Sleeping is not permitted in this mode,
 	and the caller can be asked to leave it and call again by returning
-	-ECHILD.
+	-ECHILD.  -EISDIR may also be returned to tell pathwalk to
+	ignore d_automount or any mounts.
 
 	This function is only used if DCACHE_MANAGE_TRANSIT is set on the
 	dentry being transited from.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/firmware_class/README linux-libre-3.17-rc7-gnu/Documentation/firmware_class/README
--- linux-libre-3.16-gnu/Documentation/firmware_class/README	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/firmware_class/README	2014-09-28 17:29:07.000000000 -0400
@@ -64,7 +64,7 @@
 
 	 if(request_firmware(&fw_entry, $FIRMWARE, device) == 0)
 	 	copy_fw_to_device(fw_entry->data, fw_entry->size);
-	 release(fw_entry);
+	 release_firmware(fw_entry);
 
  Sample/simple hotplug script:
  ============================
@@ -74,7 +74,7 @@
 	HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
 	echo 1 > /sys/$DEVPATH/loading
-	cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+	cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
 	echo 0 > /sys/$DEVPATH/loading
 
  Random notes:
@@ -123,6 +123,6 @@
  --------------------
  After firmware cache mechanism is introduced during system sleep,
  request_firmware can be called safely inside device's suspend and
- resume callback, and callers need't cache the firmware by
+ resume callback, and callers needn't cache the firmware by
  themselves any more for dealing with firmware loss during system
  resume.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/gpio/board.txt linux-libre-3.17-rc7-gnu/Documentation/gpio/board.txt
--- linux-libre-3.16-gnu/Documentation/gpio/board.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/gpio/board.txt	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,7 @@ Platform Data
 Finally, GPIOs can be bound to devices and functions using platform data. Board
 files that desire to do so need to include the following header:
 
-	#include <linux/gpio/driver.h>
+	#include <linux/gpio/machine.h>
 
 GPIOs are mapped by the means of tables of lookups, containing instances of the
 gpiod_lookup structure. Two macros are defined to help declaring such mappings:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/gpio/consumer.txt linux-libre-3.17-rc7-gnu/Documentation/gpio/consumer.txt
--- linux-libre-3.16-gnu/Documentation/gpio/consumer.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/gpio/consumer.txt	2014-09-28 17:29:07.000000000 -0400
@@ -29,28 +29,63 @@ gpiod_get() functions. Like many other k
 device that will use the GPIO and the function the requested GPIO is supposed to
 fulfill:
 
-	struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
+	struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
+				    enum gpiod_flags flags)
 
 If a function is implemented by using several GPIOs together (e.g. a simple LED
 device that displays digits), an additional index argument can be specified:
 
 	struct gpio_desc *gpiod_get_index(struct device *dev,
-					  const char *con_id, unsigned int idx)
+					  const char *con_id, unsigned int idx,
+					  enum gpiod_flags flags)
+
+The flags parameter is used to optionally specify a direction and initial value
+for the GPIO. Values can be:
+
+* GPIOD_ASIS or 0 to not initialize the GPIO at all. The direction must be set
+  later with one of the dedicated functions.
+* GPIOD_IN to initialize the GPIO as input.
+* GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0.
+* GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1.
 
 Both functions return either a valid GPIO descriptor, or an error code checkable
 with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned
 if and only if no GPIO has been assigned to the device/function/index triplet,
 other error codes are used for cases where a GPIO has been assigned but an error
 occurred while trying to acquire it. This is useful to discriminate between mere
-errors and an absence of GPIO for optional GPIO parameters.
+errors and an absence of GPIO for optional GPIO parameters. For the common
+pattern where a GPIO is optional, the gpiod_get_optional() and
+gpiod_get_index_optional() functions can be used. These functions return NULL
+instead of -ENOENT if no GPIO has been assigned to the requested function:
+
+
+	struct gpio_desc *gpiod_get_optional(struct device *dev,
+					     const char *con_id,
+					     enum gpiod_flags flags)
+
+	struct gpio_desc *gpiod_get_index_optional(struct device *dev,
+						   const char *con_id,
+						   unsigned int index,
+						   enum gpiod_flags flags)
 
 Device-managed variants of these functions are also defined:
 
-	struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
+	struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
+					 enum gpiod_flags flags)
 
 	struct gpio_desc *devm_gpiod_get_index(struct device *dev,
 					       const char *con_id,
-					       unsigned int idx)
+					       unsigned int idx,
+					       enum gpiod_flags flags)
+
+	struct gpio_desc *devm_gpiod_get_optional(struct device *dev,
+						  const char *con_id,
+						  enum gpiod_flags flags)
+
+	struct gpio_desc * devm_gpiod_get_index_optional(struct device *dev,
+							const char *con_id,
+							unsigned int index,
+							enum gpiod_flags flags)
 
 A GPIO descriptor can be disposed of using the gpiod_put() function:
 
@@ -67,8 +102,9 @@ Using GPIOs
 
 Setting Direction
 -----------------
-The first thing a driver must do with a GPIO is setting its direction. This is
-done by invoking one of the gpiod_direction_*() functions:
+The first thing a driver must do with a GPIO is setting its direction. If no
+direction-setting flags have been given to gpiod_get*(), this is done by
+invoking one of the gpiod_direction_*() functions:
 
 	int gpiod_direction_input(struct gpio_desc *desc)
 	int gpiod_direction_output(struct gpio_desc *desc, int value)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/gpio/driver.txt linux-libre-3.17-rc7-gnu/Documentation/gpio/driver.txt
--- linux-libre-3.16-gnu/Documentation/gpio/driver.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/gpio/driver.txt	2014-09-28 17:29:07.000000000 -0400
@@ -157,13 +157,34 @@ Locking IRQ usage
 Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
 to mark the GPIO as being used as an IRQ:
 
-	int gpiod_lock_as_irq(struct gpio_desc *desc)
+	int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 
 This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
 is released:
 
-	void gpiod_unlock_as_irq(struct gpio_desc *desc)
+	void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 
 When implementing an irqchip inside a GPIO driver, these two functions should
 typically be called in the .startup() and .shutdown() callbacks from the
 irqchip.
+
+
+Requesting self-owned GPIO pins
+-------------------------------
+
+Sometimes it is useful to allow a GPIO chip driver to request its own GPIO
+descriptors through the gpiolib API. Using gpio_request() for this purpose
+does not help since it pins the module to the kernel forever (it calls
+try_module_get()). A GPIO driver can use the following functions instead
+to request and free descriptors without being pinned to the kernel forever.
+
+	int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
+
+	void gpiochip_free_own_desc(struct gpio_desc *desc)
+
+Descriptors requested with gpiochip_request_own_desc() must be released with
+gpiochip_free_own_desc().
+
+These functions must be used with care since they do not affect module use
+count. Do not use the functions to request gpio descriptors not owned by the
+calling driver.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/ibmpowernv linux-libre-3.17-rc7-gnu/Documentation/hwmon/ibmpowernv
--- linux-libre-3.16-gnu/Documentation/hwmon/ibmpowernv	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/ibmpowernv	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+Kernel Driver IBMPOWERNV
+========================
+
+Supported systems:
+  * Any recent IBM P servers based on POWERNV platform
+
+Author: Neelesh Gupta
+
+Description
+-----------
+
+This driver implements reading the platform sensors data like temperature/fan/
+voltage/power for 'POWERNV' platform.
+
+The driver uses the platform device infrastructure. It probes the device tree
+for sensor devices during the __init phase and registers them with the 'hwmon'.
+'hwmon' populates the 'sysfs' tree having attribute files, each for a given
+sensor type and its attribute data.
+
+All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in
+the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'
+which the driver uses to make an OPAL call to the firmware.
+
+Usage notes
+-----------
+The driver is built statically with the kernel by enabling the config
+CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.
+
+Sysfs attributes
+----------------
+
+fanX_input		Measured RPM value.
+fanX_min		Threshold RPM for alert generation.
+fanX_fault		0: No fail condition
+			1: Failing fan
+tempX_input		Measured ambient temperature.
+tempX_max		Threshold ambient temperature for alert generation.
+inX_input		Measured power supply voltage
+inX_fault		0: No fail condition.
+			1: Failing power supply.
+power1_input		System power consumption (microWatt)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/lm75 linux-libre-3.17-rc7-gnu/Documentation/hwmon/lm75
--- linux-libre-3.16-gnu/Documentation/hwmon/lm75	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/lm75	2014-09-28 17:29:07.000000000 -0400
@@ -42,13 +42,14 @@ Supported chips:
     Addresses scanned: none
     Datasheet: Publicly available at the ST website
                http://www.st.com/internet/analog/product/121769.jsp
-  * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275
-    Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275'
+  * Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75, TMP175, TMP275
+    Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp112', 'tmp175', 'tmp75', 'tmp275'
     Addresses scanned: none
     Datasheet: Publicly available at the Texas Instruments website
                http://www.ti.com/product/tmp100
                http://www.ti.com/product/tmp101
                http://www.ti.com/product/tmp105
+               http://www.ti.com/product/tmp112
                http://www.ti.com/product/tmp75
                http://www.ti.com/product/tmp175
                http://www.ti.com/product/tmp275
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/ntc_thermistor linux-libre-3.17-rc7-gnu/Documentation/hwmon/ntc_thermistor
--- linux-libre-3.16-gnu/Documentation/hwmon/ntc_thermistor	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/ntc_thermistor	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,11 @@ Supported thermistors from Murata:
   Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333'
   Datasheet: Publicly available at Murata
 
+Supported thermistors from EPCOS:
+* EPCOS NTC Thermistors B57330V2103
+  Prefixes: b57330v2103
+  Datasheet: Publicly available at EPCOS
+
 Other NTC thermistors can be supported simply by adding compensation
 tables; e.g., NCP15WL333 support is added by the table ncpXXwl333.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/pmbus linux-libre-3.17-rc7-gnu/Documentation/hwmon/pmbus
--- linux-libre-3.16-gnu/Documentation/hwmon/pmbus	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/pmbus	2014-09-28 17:29:07.000000000 -0400
@@ -23,12 +23,11 @@ Supported chips:
 	http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
 	http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
 	http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
-  * Texas Instruments TPS40400, TPS40422
-    Prefixes: 'tps40400', 'tps40422'
+  * Texas Instruments TPS40400
+    Prefixes: 'tps40400'
     Addresses scanned: -
     Datasheets:
 	http://www.ti.com/lit/gpn/tps40400
-	http://www.ti.com/lit/gpn/tps40422
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/powr1220 linux-libre-3.17-rc7-gnu/Documentation/hwmon/powr1220
--- linux-libre-3.16-gnu/Documentation/hwmon/powr1220	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/powr1220	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,45 @@
+Kernel driver powr1220
+==================
+
+Supported chips:
+  * Lattice POWR1220AT8
+    Prefix: 'powr1220'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Lattice website
+               http://www.latticesemi.com/
+
+Author: Scott Kanowitz <scott.kanowitz@gmail.com>
+
+Description
+-----------
+
+This driver supports the Lattice POWR1220AT8 chip. The POWR1220
+includes voltage monitoring for 14 inputs as well as trim settings
+for output voltages and GPIOs. This driver implements the voltage
+monitoring portion of the chip.
+
+Voltages are sampled by a 12-bit ADC with a step size of 2 mV.
+An in-line attenuator allows measurements from 0 to 6 V. The
+attenuator is enabled or disabled depending on the setting of the
+input's max value. The driver will enable the attenuator for any
+value over the low measurement range maximum of 2 V.
+
+The input naming convention is as follows:
+
+driver name    pin name
+in0            VMON1
+in1            VMON2
+in2            VMON3
+in2            VMON4
+in4            VMON5
+in5            VMON6
+in6            VMON7
+in7            VMON8
+in8            VMON9
+in9            VMON10
+in10           VMON11
+in11           VMON12
+in12           VCCA
+in13           VCCINP
+
+The ADC readings are updated on request with a minimum period of 1s.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/pwm-fan linux-libre-3.17-rc7-gnu/Documentation/hwmon/pwm-fan
--- linux-libre-3.16-gnu/Documentation/hwmon/pwm-fan	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/pwm-fan	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,17 @@
+Kernel driver pwm-fan
+=====================
+
+This driver enables the use of a PWM module to drive a fan. It uses the
+generic PWM interface thus it is hardware independent. It can be used on
+many SoCs, as long as the SoC supplies a PWM line driver that exposes
+the generic PWM API.
+
+Author: Kamil Debski <k.debski@samsung.com>
+
+Description
+-----------
+
+The driver implements a simple interface for driving a fan connected to
+a PWM output. It uses the generic PWM interface, thus it can be used with
+a range of SoCs. The driver exposes the fan to the user space through
+the hwmon's sysfs interface.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/tmp103 linux-libre-3.17-rc7-gnu/Documentation/hwmon/tmp103
--- linux-libre-3.16-gnu/Documentation/hwmon/tmp103	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/tmp103	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+Kernel driver tmp103
+====================
+
+Supported chips:
+  * Texas Instruments TMP103
+    Prefix: 'tmp103'
+    Addresses scanned: none
+    Product info and datasheet: http://www.ti.com/product/tmp103
+
+Author:
+	Heiko Schocher <hs@denx.de>
+
+Description
+-----------
+
+The TMP103 is a digital output temperature sensor in a four-ball
+wafer chip-scale package (WCSP). The TMP103 is capable of reading
+temperatures to a resolution of 1Â°C. The TMP103 is specified for
+operation over a temperature range of â€“40Â°C to +125Â°C.
+
+Resolution: 8 Bits
+Accuracy: Â±1Â°C Typ (â€“10Â°C to +100Â°C)
+
+The driver provides the common sysfs-interface for temperatures (see
+Documentation/hwmon/sysfs-interface under Temperatures).
+
+Please refer how to instantiate this driver:
+Documentation/i2c/instantiating-devices
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/tmp421 linux-libre-3.17-rc7-gnu/Documentation/hwmon/tmp421
--- linux-libre-3.16-gnu/Documentation/hwmon/tmp421	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/tmp421	2014-09-28 17:29:07.000000000 -0400
@@ -8,12 +8,20 @@ Supported chips:
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
   * Texas Instruments TMP422
     Prefix: 'tmp422'
-    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Addresses scanned: I2C 0x4c, 0x4d, 0x4e and 0x4f
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
   * Texas Instruments TMP423
     Prefix: 'tmp423'
-    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+  * Texas Instruments TMP441
+    Prefix: 'tmp441'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://www.ti.com/product/tmp441
+  * Texas Instruments TMP442
+    Prefix: 'tmp442'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: http://www.ti.com/product/tmp442
 
 Authors:
 	Andre Prendel <andre.prendel@gmx.de>
@@ -21,13 +29,13 @@ Authors:
 Description
 -----------
 
-This driver implements support for Texas Instruments TMP421, TMP422
-and TMP423 temperature sensor chips. These chips implement one local
-and up to one (TMP421), up to two (TMP422) or up to three (TMP423)
-remote sensors. Temperature is measured in degrees Celsius. The chips
-are wired over I2C/SMBus and specified over a temperature range of -40
-to +125 degrees Celsius. Resolution for both the local and remote
-channels is 0.0625 degree C.
+This driver implements support for Texas Instruments TMP421, TMP422,
+TMP423, TMP441, and TMP442 temperature sensor chips. These chips
+implement one local and up to one (TMP421, TMP441), up to two (TMP422,
+TMP442) or up to three (TMP423) remote sensors. Temperature is measured
+in degrees Celsius. The chips are wired over I2C/SMBus and specified
+over a temperature range of -40 to +125 degrees Celsius. Resolution
+for both the local and remote channels is 0.0625 degree C.
 
 The chips support only temperature measurement. The driver exports
 the temperature values via the following sysfs files:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/hwmon/tps40422 linux-libre-3.17-rc7-gnu/Documentation/hwmon/tps40422
--- linux-libre-3.16-gnu/Documentation/hwmon/tps40422	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/hwmon/tps40422	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,64 @@
+Kernel driver tps40422
+======================
+
+Supported chips:
+  * TI TPS40422
+    Prefix: 'tps40422'
+    Addresses scanned: -
+    Datasheet: http://www.ti.com/lit/gpn/tps40422
+
+Author: Zhu Laiwen <richard.zhu@nsn.com>
+
+
+Description
+-----------
+
+This driver supports TI TPS40422 Dual-Output or Two-Phase Synchronous Buck
+Controller with PMBus
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported.
+
+in[1-2]_label		"vout[1-2]"
+in[1-2]_input		Measured voltage. From READ_VOUT register.
+in[1-2]_alarm		voltage alarm.
+
+curr[1-2]_input		Measured current. From READ_IOUT register.
+curr[1-2]_label		"iout[1-2]"
+curr1_max		Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr1_crit		Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr1_max_alarm		Current high alarm. From IOUT_OC_WARN_LIMIT status.
+curr1_crit_alarm	Current critical high alarm. From IOUT_OC_FAULT status.
+curr2_alarm		Current high alarm. From IOUT_OC_WARNING status.
+
+temp1_input		Measured temperature. From READ_TEMPERATURE_2 register on page 0.
+temp1_max		Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit		Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm		Chip temperature high alarm. Set by comparing
+			READ_TEMPERATURE_2 on page 0 with OT_WARN_LIMIT if TEMP_OT_WARNING
+			status is set.
+temp1_crit_alarm	Chip temperature critical high alarm. Set by comparing
+			READ_TEMPERATURE_2 on page 0 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+			status is set.
+temp2_input		Measured temperature. From READ_TEMPERATURE_2 register on page 1.
+temp2_alarm		Chip temperature alarm on page 1.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/i2c/busses/i2c-i801 linux-libre-3.17-rc7-gnu/Documentation/i2c/busses/i2c-i801
--- linux-libre-3.16-gnu/Documentation/i2c/busses/i2c-i801	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/i2c/busses/i2c-i801	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@ Supported adapters:
   * Intel Avoton (SOC)
   * Intel Wellsburg (PCH)
   * Intel Coleto Creek (PCH)
+  * Intel Wildcat Point (PCH)
   * Intel Wildcat Point-LP (PCH)
   * Intel BayTrail (SOC)
    Datasheets: Publicly available at the Intel website
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/i2c/dev-interface linux-libre-3.17-rc7-gnu/Documentation/i2c/dev-interface
--- linux-libre-3.16-gnu/Documentation/i2c/dev-interface	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/i2c/dev-interface	2014-09-28 17:29:07.000000000 -0400
@@ -57,12 +57,12 @@ Well, you are all set up now. You can no
 I2C to communicate with your device. SMBus commands are preferred if
 the device supports them. Both are illustrated below.
 
-  __u8 register = 0x10; /* Device register to access */
+  __u8 reg = 0x10; /* Device register to access */
   __s32 res;
   char buf[10];
 
   /* Using SMBus commands */
-  res = i2c_smbus_read_word_data(file, register);
+  res = i2c_smbus_read_word_data(file, reg);
   if (res < 0) {
     /* ERROR HANDLING: i2c transaction failed */
   } else {
@@ -70,11 +70,11 @@ the device supports them. Both are illus
   }
 
   /* Using I2C Write, equivalent of 
-     i2c_smbus_write_word_data(file, register, 0x6543) */
-  buf[0] = register;
+     i2c_smbus_write_word_data(file, reg, 0x6543) */
+  buf[0] = reg;
   buf[1] = 0x43;
   buf[2] = 0x65;
-  if (write(file, buf, 3) ! =3) {
+  if (write(file, buf, 3) != 3) {
     /* ERROR HANDLING: i2c transaction failed */
   }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/i2c/i2c-stub linux-libre-3.17-rc7-gnu/Documentation/i2c/i2c-stub
--- linux-libre-3.16-gnu/Documentation/i2c/i2c-stub	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/i2c/i2c-stub	2014-09-28 17:29:07.000000000 -0400
@@ -2,9 +2,9 @@ MODULE: i2c-stub
 
 DESCRIPTION:
 
-This module is a very simple fake I2C/SMBus driver.  It implements five
+This module is a very simple fake I2C/SMBus driver.  It implements six
 types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, (r/w)
-word data, and (r/w) I2C block data.
+word data, (r/w) I2C block data, and (r/w) SMBus block data.
 
 You need to provide chip addresses as a module parameter when loading this
 driver, which will then only react to SMBus commands to these addresses.
@@ -19,6 +19,14 @@ A pointer register with auto-increment i
 operations.  This allows for continuous byte reads like those supported by
 EEPROMs, among others.
 
+SMBus block command support is disabled by default, and must be enabled
+explicitly by setting the respective bits (0x03000000) in the functionality
+module parameter.
+
+SMBus block commands must be written to configure an SMBus command for
+SMBus block operations. Writes can be partial. Block read commands always
+return the number of bytes selected with the largest write so far.
+
 The typical use-case is like this:
 	1. load this module
 	2. use i2cset (from the i2c-tools project) to pre-load some data
@@ -39,15 +47,18 @@ unsigned long functionality:
 	value 0x1f0000 would only enable the quick, byte and byte data
 	commands.
 
+u8 bank_reg[10]
+u8 bank_mask[10]
+u8 bank_start[10]
+u8 bank_end[10]:
+	Optional bank settings. They tell which bits in which register
+	select the active bank, as well as the range of banked registers.
+
 CAVEATS:
 
 If your target driver polls some byte or word waiting for it to change, the
 stub could lock it up.  Use i2cset to unlock it.
 
-If the hardware for your driver has banked registers (e.g. Winbond sensors
-chips) this module will not work well - although it could be extended to
-support that pretty easily.
-
 If you spam it hard enough, printk can be lossy.  This module really wants
 something like relayfs.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/infiniband/user_mad.txt linux-libre-3.17-rc7-gnu/Documentation/infiniband/user_mad.txt
--- linux-libre-3.16-gnu/Documentation/infiniband/user_mad.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/infiniband/user_mad.txt	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,11 @@ Creating MAD agents
   ioctl.  Also, all agents registered through a file descriptor will
   be unregistered when the descriptor is closed.
 
+  2014 -- a new registration ioctl is now provided which allows additional
+       fields to be provided during registration.
+       Users of this registration call are implicitly setting the use of
+       pkey_index (see below).
+
 Receiving MADs
 
   MADs are received using read().  The receive side now supports
@@ -104,10 +109,10 @@ P_Key Index Handling
   The old ib_umad interface did not allow setting the P_Key index for
   MADs that are sent and did not provide a way for obtaining the P_Key
   index of received MADs.  A new layout for struct ib_user_mad_hdr
-  with a pkey_index member has been defined; however, to preserve
-  binary compatibility with older applications, this new layout will
-  not be used unless the IB_USER_MAD_ENABLE_PKEY ioctl is called
-  before a file descriptor is used for anything else.
+  with a pkey_index member has been defined; however, to preserve binary
+  compatibility with older applications, this new layout will not be used
+  unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's
+  are called before a file descriptor is used for anything else.
 
   In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
   to 6, the new layout of struct ib_user_mad_hdr will be used by
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ioctl/00-INDEX linux-libre-3.17-rc7-gnu/Documentation/ioctl/00-INDEX
--- linux-libre-3.16-gnu/Documentation/ioctl/00-INDEX	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ioctl/00-INDEX	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,7 @@
 00-INDEX
 	- this file
+botching-up-ioctls.txt
+	- how to avoid botching up ioctls
 cdrom.txt
 	- summary of CDROM ioctl calls
 hdio.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ioctl/botching-up-ioctls.txt linux-libre-3.17-rc7-gnu/Documentation/ioctl/botching-up-ioctls.txt
--- linux-libre-3.16-gnu/Documentation/ioctl/botching-up-ioctls.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/ioctl/botching-up-ioctls.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,219 @@
+(How to avoid) Botching up ioctls
+=================================
+
+From: http://blog.ffwll.ch/2013/11/botching-up-ioctls.html
+
+By: Daniel Vetter, Copyright Â© 2013 Intel Corporation
+
+One clear insight kernel graphics hackers gained in the past few years is that
+trying to come up with a unified interface to manage the execution units and
+memory on completely different GPUs is a futile effort. So nowadays every
+driver has its own set of ioctls to allocate memory and submit work to the GPU.
+Which is nice, since there's no more insanity in the form of fake-generic, but
+actually only used once interfaces. But the clear downside is that there's much
+more potential to screw things up.
+
+To avoid repeating all the same mistakes again I've written up some of the
+lessons learned while botching the job for the drm/i915 driver. Most of these
+only cover technicalities and not the big-picture issues like what the command
+submission ioctl exactly should look like. Learning these lessons is probably
+something every GPU driver has to do on its own.
+
+
+Prerequisites
+-------------
+
+First the prerequisites. Without these you have already failed, because you
+will need to add a a 32-bit compat layer:
+
+ * Only use fixed sized integers. To avoid conflicts with typedefs in userspace
+   the kernel has special types like __u32, __s64. Use them.
+
+ * Align everything to the natural size and use explicit padding. 32-bit
+   platforms don't necessarily align 64-bit values to 64-bit boundaries, but
+   64-bit platforms do. So we always need padding to the natural size to get
+   this right.
+
+ * Pad the entire struct to a multiple of 64-bits - the structure size will
+   otherwise differ on 32-bit versus 64-bit. Having a different structure size
+   hurts when passing arrays of structures to the kernel, or if the kernel
+   checks the structure size, which e.g. the drm core does.
+
+ * Pointers are __u64, cast from/to a uintprt_t on the userspace side and
+   from/to a void __user * in the kernel. Try really hard not to delay this
+   conversion or worse, fiddle the raw __u64 through your code since that
+   diminishes the checking tools like sparse can provide.
+
+
+Basics
+------
+
+With the joys of writing a compat layer avoided we can take a look at the basic
+fumbles. Neglecting these will make backward and forward compatibility a real
+pain. And since getting things wrong on the first attempt is guaranteed you
+will have a second iteration or at least an extension for any given interface.
+
+ * Have a clear way for userspace to figure out whether your new ioctl or ioctl
+   extension is supported on a given kernel. If you can't rely on old kernels
+   rejecting the new flags/modes or ioctls (since doing that was botched in the
+   past) then you need a driver feature flag or revision number somewhere.
+
+ * Have a plan for extending ioctls with new flags or new fields at the end of
+   the structure. The drm core checks the passed-in size for each ioctl call
+   and zero-extends any mismatches between kernel and userspace. That helps,
+   but isn't a complete solution since newer userspace on older kernels won't
+   notice that the newly added fields at the end get ignored. So this still
+   needs a new driver feature flags.
+
+ * Check all unused fields and flags and all the padding for whether it's 0,
+   and reject the ioctl if that's not the case. Otherwise your nice plan for
+   future extensions is going right down the gutters since someone will submit
+   an ioctl struct with random stack garbage in the yet unused parts. Which
+   then bakes in the ABI that those fields can never be used for anything else
+   but garbage.
+
+ * Have simple testcases for all of the above.
+
+
+Fun with Error Paths
+--------------------
+
+Nowadays we don't have any excuse left any more for drm drivers being neat
+little root exploits. This means we both need full input validation and solid
+error handling paths - GPUs will die eventually in the oddmost corner cases
+anyway:
+
+ * The ioctl must check for array overflows. Also it needs to check for
+   over/underflows and clamping issues of integer values in general. The usual
+   example is sprite positioning values fed directly into the hardware with the
+   hardware just having 12 bits or so. Works nicely until some odd display
+   server doesn't bother with clamping itself and the cursor wraps around the
+   screen.
+
+ * Have simple testcases for every input validation failure case in your ioctl.
+   Check that the error code matches your expectations. And finally make sure
+   that you only test for one single error path in each subtest by submitting
+   otherwise perfectly valid data. Without this an earlier check might reject
+   the ioctl already and shadow the codepath you actually want to test, hiding
+   bugs and regressions.
+
+ * Make all your ioctls restartable. First X really loves signals and second
+   this will allow you to test 90% of all error handling paths by just
+   interrupting your main test suite constantly with signals. Thanks to X's
+   love for signal you'll get an excellent base coverage of all your error
+   paths pretty much for free for graphics drivers. Also, be consistent with
+   how you handle ioctl restarting - e.g. drm has a tiny drmIoctl helper in its
+   userspace library. The i915 driver botched this with the set_tiling ioctl,
+   now we're stuck forever with some arcane semantics in both the kernel and
+   userspace.
+
+ * If you can't make a given codepath restartable make a stuck task at least
+   killable. GPUs just die and your users won't like you more if you hang their
+   entire box (by means of an unkillable X process). If the state recovery is
+   still too tricky have a timeout or hangcheck safety net as a last-ditch
+   effort in case the hardware has gone bananas.
+
+ * Have testcases for the really tricky corner cases in your error recovery code
+   - it's way too easy to create a deadlock between your hangcheck code and
+   waiters.
+
+
+Time, Waiting and Missing it
+----------------------------
+
+GPUs do most everything asynchronously, so we have a need to time operations and
+wait for oustanding ones. This is really tricky business; at the moment none of
+the ioctls supported by the drm/i915 get this fully right, which means there's
+still tons more lessons to learn here.
+
+ * Use CLOCK_MONOTONIC as your reference time, always. It's what alsa, drm and
+   v4l use by default nowadays. But let userspace know which timestamps are
+   derived from different clock domains like your main system clock (provided
+   by the kernel) or some independent hardware counter somewhere else. Clocks
+   will mismatch if you look close enough, but if performance measuring tools
+   have this information they can at least compensate. If your userspace can
+   get at the raw values of some clocks (e.g. through in-command-stream
+   performance counter sampling instructions) consider exposing those also.
+
+ * Use __s64 seconds plus __u64 nanoseconds to specify time. It's not the most
+   convenient time specification, but it's mostly the standard.
+
+ * Check that input time values are normalized and reject them if not. Note
+   that the kernel native struct ktime has a signed integer for both seconds
+   and nanoseconds, so beware here.
+
+ * For timeouts, use absolute times. If you're a good fellow and made your
+   ioctl restartable relative timeouts tend to be too coarse and can
+   indefinitely extend your wait time due to rounding on each restart.
+   Especially if your reference clock is something really slow like the display
+   frame counter. With a spec laywer hat on this isn't a bug since timeouts can
+   always be extended - but users will surely hate you if their neat animations
+   starts to stutter due to this.
+
+ * Consider ditching any synchronous wait ioctls with timeouts and just deliver
+   an asynchronous event on a pollable file descriptor. It fits much better
+   into event driven applications' main loop.
+
+ * Have testcases for corner-cases, especially whether the return values for
+   already-completed events, successful waits and timed-out waits are all sane
+   and suiting to your needs.
+
+
+Leaking Resources, Not
+----------------------
+
+A full-blown drm driver essentially implements a little OS, but specialized to
+the given GPU platforms. This means a driver needs to expose tons of handles
+for different objects and other resources to userspace. Doing that right
+entails its own little set of pitfalls:
+
+ * Always attach the lifetime of your dynamically created resources to the
+   lifetime of a file descriptor. Consider using a 1:1 mapping if your resource
+   needs to be shared across processes -  fd-passing over unix domain sockets
+   also simplifies lifetime management for userspace.
+
+ * Always have O_CLOEXEC support.
+
+ * Ensure that you have sufficient insulation between different clients. By
+   default pick a private per-fd namespace which forces any sharing to be done
+   explictly. Only go with a more global per-device namespace if the objects
+   are truly device-unique. One counterexample in the drm modeset interfaces is
+   that the per-device modeset objects like connectors share a namespace with
+   framebuffer objects, which mostly are not shared at all. A separate
+   namespace, private by default, for framebuffers would have been more
+   suitable.
+
+ * Think about uniqueness requirements for userspace handles. E.g. for most drm
+   drivers it's a userspace bug to submit the same object twice in the same
+   command submission ioctl. But then if objects are shareable userspace needs
+   to know whether it has seen an imported object from a different process
+   already or not. I haven't tried this myself yet due to lack of a new class
+   of objects, but consider using inode numbers on your shared file descriptors
+   as unique identifiers - it's how real files are told apart, too.
+   Unfortunately this requires a full-blown virtual filesystem in the kernel.
+
+
+Last, but not Least
+-------------------
+
+Not every problem needs a new ioctl:
+
+ * Think hard whether you really want a driver-private interface. Of course
+   it's much quicker to push a driver-private interface than engaging in
+   lengthy discussions for a more generic solution. And occasionally doing a
+   private interface to spearhead a new concept is what's required. But in the
+   end, once the generic interface comes around you'll end up maintainer two
+   interfaces. Indefinitely.
+
+ * Consider other interfaces than ioctls. A sysfs attribute is much better for
+   per-device settings, or for child objects with fairly static lifetimes (like
+   output connectors in drm with all the detection override attributes). Or
+   maybe only your testsuite needs this interface, and then debugfs with its
+   disclaimer of not having a stable ABI would be better.
+
+Finally, the name of the game is to get it right on the first attempt, since if
+your driver proves popular and your hardware platforms long-lived then you'll
+be stuck with a given ioctl essentially forever. You can try to deprecate
+horrible ioctls on newer iterations of your hardware, but generally it takes
+years to accomplish this. And then again years until the last user able to
+complain about regressions disappears, too.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/ioctl/ioctl-number.txt linux-libre-3.17-rc7-gnu/Documentation/ioctl/ioctl-number.txt
--- linux-libre-3.16-gnu/Documentation/ioctl/ioctl-number.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/ioctl/ioctl-number.txt	2014-09-28 17:29:07.000000000 -0400
@@ -197,6 +197,7 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:gregkh@linuxfoundation.org>
 'a'	all	linux/atm*.h, linux/sonet.h	ATM on linux
 					<http://lrcwww.epfl.ch/>
+'a'	00-0F	drivers/crypto/qat/qat_common/adf_cfg_common.h	conflict! qat driver
 'b'	00-FF				conflict! bit3 vme host bridge
 					<mailto:natalia@nikhefk.nikhef.nl>
 'c'	all	linux/cm4000_cs.h	conflict!
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/kbuild/00-INDEX linux-libre-3.17-rc7-gnu/Documentation/kbuild/00-INDEX
--- linux-libre-3.16-gnu/Documentation/kbuild/00-INDEX	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/kbuild/00-INDEX	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,7 @@
 00-INDEX
 	- this file: info on the kernel build process
+headers_install.txt
+	- how to export Linux headers for use by userspace
 kbuild.txt
 	- developer information on kbuild
 kconfig.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/kbuild/headers_install.txt linux-libre-3.17-rc7-gnu/Documentation/kbuild/headers_install.txt
--- linux-libre-3.16-gnu/Documentation/kbuild/headers_install.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/kbuild/headers_install.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+Exporting kernel headers for use by userspace
+=============================================
+
+The "make headers_install" command exports the kernel's header files in a
+form suitable for use by userspace programs.
+
+The linux kernel's exported header files describe the API for user space
+programs attempting to use kernel services.  These kernel header files are
+used by the system's C library (such as glibc or uClibc) to define available
+system calls, as well as constants and structures to be used with these
+system calls.  The C library's header files include the kernel header files
+from the "linux" subdirectory.  The system's libc headers are usually
+installed at the default location /usr/include and the kernel headers in
+subdirectories under that (most notably /usr/include/linux and
+/usr/include/asm).
+
+Kernel headers are backwards compatible, but not forwards compatible.  This
+means that a program built against a C library using older kernel headers
+should run on a newer kernel (although it may not have access to new
+features), but a program built against newer kernel headers may not work on an
+older kernel.
+
+The "make headers_install" command can be run in the top level directory of the
+kernel source code (or using a standard out-of-tree build).  It takes two
+optional arguments:
+
+  make headers_install ARCH=i386 INSTALL_HDR_PATH=/usr/include
+
+ARCH indicates which architecture to produce headers for, and defaults to the
+current architecture.  The linux/asm directory of the exported kernel headers
+is platform-specific, to see a complete list of supported architectures use
+the command:
+
+  ls -d include/asm-* | sed 's/.*-//'
+
+INSTALL_HDR_PATH indicates where to install the headers.  It defaults to
+"./usr/include".
+
+The command "make headers_install_all" exports headers for all architectures
+simultaneously.  (This is mostly of interest to distribution maintainers,
+who create an architecture-independent tarball from the resulting include
+directory.)  You also can use HDR_ARCH_LIST to specify list of architectures.
+Remember to provide the appropriate linux/asm directory via "mv" or "ln -s"
+before building a C library with headers exported this way.
+
+The kernel header export infrastructure is maintained by David Woodhouse
+<dwmw2@infradead.org>.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/kbuild/makefiles.txt linux-libre-3.17-rc7-gnu/Documentation/kbuild/makefiles.txt
--- linux-libre-3.16-gnu/Documentation/kbuild/makefiles.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/kbuild/makefiles.txt	2014-09-28 17:29:07.000000000 -0400
@@ -23,11 +23,10 @@ This document describes the Linux kernel
 	=== 4 Host Program support
 	   --- 4.1 Simple Host Program
 	   --- 4.2 Composite Host Programs
-	   --- 4.3 Defining shared libraries
-	   --- 4.4 Using C++ for host programs
-	   --- 4.5 Controlling compiler options for host programs
-	   --- 4.6 When host programs are actually built
-	   --- 4.7 Using hostprogs-$(CONFIG_FOO)
+	   --- 4.3 Using C++ for host programs
+	   --- 4.4 Controlling compiler options for host programs
+	   --- 4.5 When host programs are actually built
+	   --- 4.6 Using hostprogs-$(CONFIG_FOO)
 
 	=== 5 Kbuild clean infrastructure
 
@@ -643,29 +642,7 @@ Both possibilities are described in the
 	Finally, the two .o files are linked to the executable, lxdialog.
 	Note: The syntax <executable>-y is not permitted for host-programs.
 
---- 4.3 Defining shared libraries
-
-	Objects with extension .so are considered shared libraries, and
-	will be compiled as position independent objects.
-	Kbuild provides support for shared libraries, but the usage
-	shall be restricted.
-	In the following example the libkconfig.so shared library is used
-	to link the executable conf.
-
-	Example:
-		#scripts/kconfig/Makefile
-		hostprogs-y     := conf
-		conf-objs       := conf.o libkconfig.so
-		libkconfig-objs := expr.o type.o
-
-	Shared libraries always require a corresponding -objs line, and
-	in the example above the shared library libkconfig is composed by
-	the two objects expr.o and type.o.
-	expr.o and type.o will be built as position independent code and
-	linked as a shared library libkconfig.so. C++ is not supported for
-	shared libraries.
-
---- 4.4 Using C++ for host programs
+--- 4.3 Using C++ for host programs
 
 	kbuild offers support for host programs written in C++. This was
 	introduced solely to support kconfig, and is not recommended
@@ -688,7 +665,7 @@ Both possibilities are described in the
 		qconf-cxxobjs := qconf.o
 		qconf-objs    := check.o
 
---- 4.5 Controlling compiler options for host programs
+--- 4.4 Controlling compiler options for host programs
 
 	When compiling host programs, it is possible to set specific flags.
 	The programs will always be compiled utilising $(HOSTCC) passed
@@ -716,7 +693,7 @@ Both possibilities are described in the
 	When linking qconf, it will be passed the extra option
 	"-L$(QTDIR)/lib".
 
---- 4.6 When host programs are actually built
+--- 4.5 When host programs are actually built
 
 	Kbuild will only build host-programs when they are referenced
 	as a prerequisite.
@@ -747,7 +724,7 @@ Both possibilities are described in the
 	This will tell kbuild to build lxdialog even if not referenced in
 	any rule.
 
---- 4.7 Using hostprogs-$(CONFIG_FOO)
+--- 4.6 Using hostprogs-$(CONFIG_FOO)
 
 	A typical pattern in a Kbuild file looks like this:
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/kdump/kdump.txt linux-libre-3.17-rc7-gnu/Documentation/kdump/kdump.txt
--- linux-libre-3.16-gnu/Documentation/kdump/kdump.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/kdump/kdump.txt	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,7 @@ memory image to a dump file on the local
 a remote system.
 
 Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64,
-and s390x architectures.
+s390x and arm architectures.
 
 When the system kernel boots, it reserves a small section of memory for
 the dump-capture kernel. This ensures that ongoing Direct Memory Access
@@ -112,7 +112,7 @@ There are two possible methods of using
 2) Or use the system kernel binary itself as dump-capture kernel and there is
    no need to build a separate dump-capture kernel. This is possible
    only with the architectures which support a relocatable kernel. As
-   of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
+   of today, i386, x86_64, ppc64, ia64 and arm architectures support relocatable
    kernel.
 
 Building a relocatable kernel is advantageous from the point of view that
@@ -241,6 +241,13 @@ Dump-capture kernel config options (Arch
   kernel will be aligned to 64Mb, so if the start address is not then
   any space below the alignment point will be wasted.
 
+Dump-capture kernel config options (Arch Dependent, arm)
+----------------------------------------------------------
+
+-   To use a relocatable kernel,
+    Enable "AUTO_ZRELADDR" support under "Boot" options:
+
+    AUTO_ZRELADDR=y
 
 Extended crashkernel syntax
 ===========================
@@ -256,6 +263,10 @@ The syntax is:
     crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
     range=start-[end]
 
+Please note, on arm, the offset is required.
+    crashkernel=<range1>:<size1>[,<range2>:<size2>,...]@offset
+    range=start-[end]
+
     'start' is inclusive and 'end' is exclusive.
 
 For example:
@@ -296,6 +307,12 @@ Boot into System Kernel
    on the memory consumption of the kdump system. In general this is not
    dependent on the memory size of the production system.
 
+   On arm, use "crashkernel=Y@X". Note that the start address of the kernel
+   will be aligned to 128MiB (0x08000000), so if the start address is not then
+   any space below the alignment point may be overwritten by the dump-capture kernel,
+   which means it is possible that the vmcore is not that precise as expected.
+
+
 Load the Dump-capture Kernel
 ============================
 
@@ -315,7 +332,8 @@ For ia64:
 	- Use vmlinux or vmlinuz.gz
 For s390x:
 	- Use image or bzImage
-
+For arm:
+	- Use zImage
 
 If you are using a uncompressed vmlinux image then use following command
 to load dump-capture kernel.
@@ -331,6 +349,15 @@ to load dump-capture kernel.
    --initrd=<initrd-for-dump-capture-kernel> \
    --append="root=<root-dev> <arch-specific-options>"
 
+If you are using a compressed zImage, then use following command
+to load dump-capture kernel.
+
+   kexec --type zImage -p <dump-capture-kernel-bzImage> \
+   --initrd=<initrd-for-dump-capture-kernel> \
+   --dtb=<dtb-for-dump-capture-kernel> \
+   --append="root=<root-dev> <arch-specific-options>"
+
+
 Please note, that --args-linux does not need to be specified for ia64.
 It is planned to make this a no-op on that architecture, but for now
 it should be omitted
@@ -347,6 +374,9 @@ For ppc64:
 For s390x:
 	"1 maxcpus=1 cgroup_disable=memory"
 
+For arm:
+	"1 maxcpus=1 reset_devices"
+
 Notes on loading the dump-capture kernel:
 
 * By default, the ELF headers are stored in ELF64 format to support
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/kernel-parameters.txt linux-libre-3.17-rc7-gnu/Documentation/kernel-parameters.txt
--- linux-libre-3.16-gnu/Documentation/kernel-parameters.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/kernel-parameters.txt	2014-09-28 17:29:07.000000000 -0400
@@ -566,6 +566,17 @@ bytes respectively. Such letter suffixes
 			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.
 
@@ -1097,6 +1108,12 @@ bytes respectively. Such letter suffixes
 			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)
@@ -1313,6 +1330,23 @@ bytes respectively. Such letter suffixes
 			Formats: { "ima" | "ima-ng" }
 			Default: "ima-ng"
 
+	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
@@ -1416,10 +1450,6 @@ bytes respectively. Such letter suffixes
 	ip=		[IP_PNP]
 			See Documentation/filesystems/nfs/nfsroot.txt.
 
-	ip2=		[HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
-			See comment before ip2_setup() in
-			drivers/char/ip2/ip2base.c.
-
 	irqfixup	[HW]
 			When an interrupt is not handled search all handlers
 			for it. Intended to get systems with badly broken
@@ -1692,8 +1722,12 @@ bytes respectively. Such letter suffixes
 			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.  The default
-			size is set in the kernel config file.
+			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
@@ -2166,6 +2200,21 @@ bytes respectively. Such letter suffixes
 			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.
+
 	eagerfpu=	[X86]
 			on	enable eager fpu restore
 			off	disable eager fpu restore
@@ -2807,6 +2856,13 @@ bytes respectively. Such letter suffixes
 			quiescent states.  Units are jiffies, minimum
 			value is one, and maximum value is HZ.
 
+	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.
@@ -3023,6 +3079,13 @@ bytes respectively. Such letter suffixes
 
 	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.
 
@@ -3478,6 +3541,7 @@ bytes respectively. Such letter suffixes
 					bogus residue values);
 				s = SINGLE_LUN (the device has only one
 					Logical Unit);
+				u = IGNORE_UAS (don't bind to the uas driver);
 				w = NO_WP_DETECT (don't test whether the
 					medium is write-protected).
 			Example: quirks=0419:aaf5:rl,0421:0433:rc
@@ -3697,6 +3761,10 @@ bytes respectively. Such letter suffixes
 			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-3.16-gnu/Documentation/laptops/00-INDEX linux-libre-3.17-rc7-gnu/Documentation/laptops/00-INDEX
--- linux-libre-3.16-gnu/Documentation/laptops/00-INDEX	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/laptops/00-INDEX	2014-09-28 17:29:07.000000000 -0400
@@ -18,3 +18,5 @@ sonypi.txt
 	- info on Linux Sony Programmable I/O Device support.
 thinkpad-acpi.txt
 	- information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
+toshiba_haps.txt
+	- information on the Toshiba HDD Active Protection Sensor driver.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/laptops/freefall.c linux-libre-3.17-rc7-gnu/Documentation/laptops/freefall.c
--- linux-libre-3.16-gnu/Documentation/laptops/freefall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/laptops/freefall.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,15 +29,12 @@ static const char app_name[] = "FREE FAL
 
 static int set_unload_heads_path(char *device)
 {
-	char devname[64];
-
 	if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
 		return -EINVAL;
-	strncpy(devname, device + 5, sizeof(devname) - 1);
 	strncpy(device_path, device, sizeof(device_path) - 1);
 
 	snprintf(unload_heads_path, sizeof(unload_heads_path) - 1,
-				"/sys/block/%s/device/unload_heads", devname);
+				"/sys/block/%s/device/unload_heads", device+5);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/laptops/toshiba_haps.txt linux-libre-3.17-rc7-gnu/Documentation/laptops/toshiba_haps.txt
--- linux-libre-3.16-gnu/Documentation/laptops/toshiba_haps.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/laptops/toshiba_haps.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,76 @@
+Kernel driver toshiba_haps
+Toshiba HDD Active Protection Sensor
+====================================
+
+Author: Azael Avalos <coproscefalo@gmail.com>
+
+
+0. Contents
+-----------
+
+1. Description
+2. Interface
+3. Accelerometer axes
+4. Supported devices
+5. Usage
+
+
+1. Description
+--------------
+
+This driver provides support for the accelerometer found in various Toshiba
+laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy,
+and detects laptops automatically with this device.
+On Windows, Toshiba provided software monitors this device and provides
+automatic HDD protection (head unload) on sudden moves or harsh vibrations,
+however, this driver only provides a notification via a sysfs file to let
+userspace tools or daemons act accordingly, as well as providing a sysfs
+file to set the desired protection level or sensor sensibility.
+
+
+2. Interface
+------------
+
+This device comes with 3 methods:
+_STA -  Checks existence of the device, returning Zero if the device does not
+	exists or is not supported.
+PTLV -  Sets the desired protection level.
+RSSS -  Shuts down the HDD protection interface for a few seconds,
+	then restores normal operation.
+
+Note:
+The presence of Solid State Drives (SSD) can make this driver to fail loading,
+given the fact that such drives have no movable parts, and thus, not requiring
+any "protection" as well as failing during the evaluation of the _STA method
+found under this device.
+
+
+3. Accelerometer axes
+---------------------
+
+This device does not report any axes, however, to query the sensor position
+a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are
+provided to query such information, handled by the kernel module toshiba_acpi
+since kernel version 3.15.
+
+
+4. Supported devices
+--------------------
+
+This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop
+with this device is supported, given the fact that they have the presence of
+conventional HDD and not only SSD, or a combination of both HDD and SSD.
+
+
+5. Usage
+--------
+
+The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are:
+protection_level - The protection_level is readable and writeable, and
+		   provides a way to let userspace query the current protection
+		   level, as well as set the desired protection level, the
+		   available protection levels are:
+		   0 - Disabled | 1 - Low | 2 - Medium | 3 - High
+reset_protection - The reset_protection entry is writeable only, being "1"
+		   the only parameter it accepts, it is used to trigger
+		   a reset of the protection interface.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/make/headers_install.txt linux-libre-3.17-rc7-gnu/Documentation/make/headers_install.txt
--- linux-libre-3.16-gnu/Documentation/make/headers_install.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/make/headers_install.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-Exporting kernel headers for use by userspace
-=============================================
-
-The "make headers_install" command exports the kernel's header files in a
-form suitable for use by userspace programs.
-
-The linux kernel's exported header files describe the API for user space
-programs attempting to use kernel services.  These kernel header files are
-used by the system's C library (such as glibc or uClibc) to define available
-system calls, as well as constants and structures to be used with these
-system calls.  The C library's header files include the kernel header files
-from the "linux" subdirectory.  The system's libc headers are usually
-installed at the default location /usr/include and the kernel headers in
-subdirectories under that (most notably /usr/include/linux and
-/usr/include/asm).
-
-Kernel headers are backwards compatible, but not forwards compatible.  This
-means that a program built against a C library using older kernel headers
-should run on a newer kernel (although it may not have access to new
-features), but a program built against newer kernel headers may not work on an
-older kernel.
-
-The "make headers_install" command can be run in the top level directory of the
-kernel source code (or using a standard out-of-tree build).  It takes two
-optional arguments:
-
-  make headers_install ARCH=i386 INSTALL_HDR_PATH=/usr/include
-
-ARCH indicates which architecture to produce headers for, and defaults to the
-current architecture.  The linux/asm directory of the exported kernel headers
-is platform-specific, to see a complete list of supported architectures use
-the command:
-
-  ls -d include/asm-* | sed 's/.*-//'
-
-INSTALL_HDR_PATH indicates where to install the headers.  It defaults to
-"./usr/include".
-
-The command "make headers_install_all" exports headers for all architectures
-simultaneously.  (This is mostly of interest to distribution maintainers,
-who create an architecture-independent tarball from the resulting include
-directory.)  You also can use HDR_ARCH_LIST to specify list of architectures.
-Remember to provide the appropriate linux/asm directory via "mv" or "ln -s"
-before building a C library with headers exported this way.
-
-The kernel header export infrastructure is maintained by David Woodhouse
-<dwmw2@infradead.org>.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/memory-barriers.txt linux-libre-3.17-rc7-gnu/Documentation/memory-barriers.txt
--- linux-libre-3.16-gnu/Documentation/memory-barriers.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/memory-barriers.txt	2014-09-28 17:29:07.000000000 -0400
@@ -757,10 +757,14 @@ SMP BARRIER PAIRING
 When dealing with CPU-CPU interactions, certain types of memory barrier should
 always be paired.  A lack of appropriate pairing is almost certainly an error.
 
-A write barrier should always be paired with a data dependency barrier or read
-barrier, though a general barrier would also be viable.  Similarly a read
-barrier or a data dependency barrier should always be paired with at least an
-write barrier, though, again, a general barrier is viable:
+General barriers pair with each other, though they also pair with
+most other types of barriers, albeit without transitivity.  An acquire
+barrier pairs with a release barrier, but both may also pair with other
+barriers, including of course general barriers.  A write barrier pairs
+with a data dependency barrier, an acquire barrier, a release barrier,
+a read barrier, or a general barrier.  Similarly a read barrier or a
+data dependency barrier pairs with a write barrier, an acquire barrier,
+a release barrier, or a general barrier:
 
 	CPU 1		      CPU 2
 	===============	      ===============
@@ -1893,6 +1897,21 @@ between the STORE to indicate the event
 	    <general barrier>		  STORE current->state
 	LOAD event_indicated
 
+To repeat, this write memory barrier is present if and only if something
+is actually awakened.  To see this, consider the following sequence of
+events, where X and Y are both initially zero:
+
+	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
+
+In contrast, if a wakeup does occur, CPU 2's load from X would be guaranteed
+to see 1.
+
 The available waker functions include:
 
 	complete();
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/mic/mic_overview.txt linux-libre-3.17-rc7-gnu/Documentation/mic/mic_overview.txt
--- linux-libre-3.16-gnu/Documentation/mic/mic_overview.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/mic/mic_overview.txt	2014-09-28 17:29:07.000000000 -0400
@@ -17,35 +17,50 @@ for applications. A key benefit of our s
 the standard virtio framework for network, disk and console devices,
 though in our case the virtio framework is used across a PCIe bus.
 
+MIC PCIe card has a dma controller with 8 channels. These channels are
+shared between the host s/w and the card s/w. 0 to 3 are used by host
+and 4 to 7 by card. As the dma device doesn't show up as PCIe device,
+a virtual bus called mic bus is created and virtual dma devices are
+created on it by the host/card drivers. On host the channels are private
+and used only by the host driver to transfer data for the virtio devices.
+
 Here is a block diagram of the various components described above. The
 virtio backends are situated on the host rather than the card given better
 single threaded performance for the host compared to MIC, the ability of
 the host to initiate DMA's to/from the card using the MIC DMA engine and
 the fact that the virtio block storage backend can only be on the host.
 
-                              |
-       +----------+           |             +----------+
-       | Card OS  |           |             | Host OS  |
-       +----------+           |             +----------+
-                              |
-+-------+ +--------+ +------+ | +---------+  +--------+ +--------+
-| Virtio| |Virtio  | |Virtio| | |Virtio   |  |Virtio  | |Virtio  |
-| Net   | |Console | |Block | | |Net      |  |Console | |Block   |
-| Driver| |Driver  | |Driver| | |backend  |  |backend | |backend |
-+-------+ +--------+ +------+ | +---------+  +--------+ +--------+
-    |         |         |     |      |            |         |
-    |         |         |     |User  |            |         |
-    |         |         |     |------|------------|---------|-------
-    +-------------------+     |Kernel +--------------------------+
-              |               |       | Virtio over PCIe IOCTLs  |
-              |               |       +--------------------------+
-      +--------------+        |                   |
-      |Intel MIC     |        |            +---------------+
-      |Card Driver   |        |            |Intel MIC      |
-      +--------------+        |            |Host Driver    |
-              |               |            +---------------+
-              |               |                   |
-     +-------------------------------------------------------------+
-     |                                                             |
-     |                    PCIe Bus                                 |
-     +-------------------------------------------------------------+
+                                      |
+               +----------+           |             +----------+
+               | Card OS  |           |             | Host OS  |
+               +----------+           |             +----------+
+                                      |
+        +-------+ +--------+ +------+ | +---------+  +--------+ +--------+
+        | Virtio| |Virtio  | |Virtio| | |Virtio   |  |Virtio  | |Virtio  |
+        | Net   | |Console | |Block | | |Net      |  |Console | |Block   |
+        | Driver| |Driver  | |Driver| | |backend  |  |backend | |backend |
+        +-------+ +--------+ +------+ | +---------+  +--------+ +--------+
+            |         |         |     |      |            |         |
+            |         |         |     |User  |            |         |
+            |         |         |     |------|------------|---------|-------
+            +-------------------+     |Kernel +--------------------------+
+                      |               |       | Virtio over PCIe IOCTLs  |
+                      |               |       +--------------------------+
++-----------+         |               |                   |  +-----------+
+| MIC DMA   |         |               |                   |  | MIC DMA   |
+| Driver    |         |               |                   |  | Driver    |
++-----------+         |               |                   |  +-----------+
+      |               |               |                   |        |
++---------------+     |               |                   |  +----------------+
+|MIC virtual Bus|     |               |                   |  |MIC virtual Bus |
++---------------+     |               |                   |  +----------------+
+      |               |               |                   |              |
+      |   +--------------+            |            +---------------+     |
+      |   |Intel MIC     |            |            |Intel MIC      |     |
+      +---|Card Driver   |            |            |Host Driver    |     |
+          +--------------+            |            +---------------+-----+
+                      |               |                   |
+             +-------------------------------------------------------------+
+             |                                                             |
+             |                    PCIe Bus                                 |
+             +-------------------------------------------------------------+
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/mic/mpssd/mpss linux-libre-3.17-rc7-gnu/Documentation/mic/mpssd/mpss
--- linux-libre-3.16-gnu/Documentation/mic/mpssd/mpss	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/mic/mpssd/mpss	2014-09-28 17:29:07.000000000 -0400
@@ -48,18 +48,18 @@ start()
 	fi
 
 	echo -e $"Starting MPSS Stack"
-	echo -e $"Loading MIC_HOST Module"
+	echo -e $"Loading MIC_X100_DMA & MIC_HOST Modules"
 
-	# Ensure the driver is loaded
-	if [ ! -d "$sysfs" ]; then
-		modprobe mic_host
+	for f in "mic_host" "mic_x100_dma"
+	do
+		modprobe $f
 		RETVAL=$?
 		if [ $RETVAL -ne 0 ]; then
 			failure
 			echo
 			return $RETVAL
 		fi
-	fi
+	done
 
 	# Start the daemon
 	echo -n $"Starting MPSSD "
@@ -170,8 +170,8 @@ unload()
 	stop
 
 	sleep 5
-	echo -n $"Removing MIC_HOST Module: "
-	modprobe -r mic_host
+	echo -n $"Removing MIC_HOST & MIC_X100_DMA Modules: "
+	modprobe -r mic_host mic_x100_dma
 	RETVAL=$?
 	[ $RETVAL -ne 0 ] && failure || success
 	echo
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/misc-devices/lis3lv02d linux-libre-3.17-rc7-gnu/Documentation/misc-devices/lis3lv02d
--- linux-libre-3.16-gnu/Documentation/misc-devices/lis3lv02d	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/misc-devices/lis3lv02d	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ acts similar to /dev/rtc and reacts on f
 from the device. It supports blocking operations, poll/select and
 fasync operation modes. You must read 1 bytes from the device.  The
 result is number of free-fall interrupts since the last successful
-read (or 255 if number of interrupts would not fit). See the hpfall.c
+read (or 255 if number of interrupts would not fit). See the freefall.c
 file for an example on using the device.
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/bonding.txt linux-libre-3.17-rc7-gnu/Documentation/networking/bonding.txt
--- linux-libre-3.16-gnu/Documentation/networking/bonding.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/bonding.txt	2014-09-28 17:29:07.000000000 -0400
@@ -542,10 +542,10 @@ mode
 
 		XOR policy: Transmit based on the selected transmit
 		hash policy.  The default policy is a simple [(source
-		MAC address XOR'd with destination MAC address) modulo
-		slave count].  Alternate transmit policies may be
-		selected via the xmit_hash_policy option, described
-		below.
+		MAC address XOR'd with destination MAC address XOR
+		packet type ID) modulo slave count].  Alternate transmit
+		policies may be	selected via the xmit_hash_policy option,
+		described below.
 
 		This mode provides load balancing and fault tolerance.
 
@@ -801,10 +801,11 @@ xmit_hash_policy
 
 	layer2
 
-		Uses XOR of hardware MAC addresses to generate the
-		hash.  The formula is
+		Uses XOR of hardware MAC addresses and packet type ID
+		field to generate the hash. The formula is
 
-		(source MAC XOR destination MAC) modulo slave count
+		hash = source MAC XOR destination MAC XOR packet type ID
+		slave number = hash modulo slave count
 
 		This algorithm will place all traffic to a particular
 		network peer on the same slave.
@@ -819,7 +820,7 @@ xmit_hash_policy
 		Uses XOR of hardware MAC addresses and IP addresses to
 		generate the hash.  The formula is
 
-		hash = source MAC XOR destination MAC
+		hash = source MAC XOR destination MAC XOR packet type ID
 		hash = hash XOR source IP XOR destination IP
 		hash = hash XOR (hash RSHIFT 16)
 		hash = hash XOR (hash RSHIFT 8)
@@ -2301,13 +2302,13 @@ broadcast: Like active-backup, there is
 	bandwidth.  
 
 	Additionally, the linux bonding 802.3ad implementation
-	distributes traffic by peer (using an XOR of MAC addresses),
-	so in a "gatewayed" configuration, all outgoing traffic will
-	generally use the same device.  Incoming traffic may also end
-	up on a single device, but that is dependent upon the
-	balancing policy of the peer's 8023.ad implementation.  In a
-	"local" configuration, traffic will be distributed across the
-	devices in the bond.
+	distributes traffic by peer (using an XOR of MAC addresses
+	and packet type ID), so in a "gatewayed" configuration, all
+	outgoing traffic will generally use the same device.  Incoming
+	traffic may also end up on a single device, but that is
+	dependent upon the balancing policy of the peer's 8023.ad
+	implementation.  In a "local" configuration, traffic will be
+	distributed across the devices in the bond.
 
 	Finally, the 802.3ad mode mandates the use of the MII monitor,
 	therefore, the ARP monitor is not available in this mode.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/filter.txt linux-libre-3.17-rc7-gnu/Documentation/networking/filter.txt
--- linux-libre-3.16-gnu/Documentation/networking/filter.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/filter.txt	2014-09-28 17:29:07.000000000 -0400
@@ -462,9 +462,9 @@ JIT compiler
 ------------
 
 The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC,
-ARM and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler is
-transparently invoked for each attached filter from user space or for internal
-kernel users if it has been previously enabled by root:
+ARM, MIPS and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler
+is transparently invoked for each attached filter from user space or for
+internal kernel users if it has been previously enabled by root:
 
   echo 1 > /proc/sys/net/core/bpf_jit_enable
 
@@ -586,12 +586,12 @@ team driver's classifier for its load-ba
 extension, PTP dissector/classifier, and much more. They are all internally
 converted by the kernel into the new instruction set representation and run
 in the eBPF interpreter. For in-kernel handlers, this all works transparently
-by using sk_unattached_filter_create() for setting up the filter, resp.
-sk_unattached_filter_destroy() for destroying it. The macro
-SK_RUN_FILTER(filter, ctx) transparently invokes eBPF interpreter or JITed
-code to run the filter. 'filter' is a pointer to struct sk_filter that we
-got from sk_unattached_filter_create(), and 'ctx' the given context (e.g.
-skb pointer). All constraints and restrictions from sk_chk_filter() apply
+by using bpf_prog_create() for setting up the filter, resp.
+bpf_prog_destroy() for destroying it. The macro
+BPF_PROG_RUN(filter, ctx) transparently invokes eBPF interpreter or JITed
+code to run the filter. 'filter' is a pointer to struct bpf_prog that we
+got from bpf_prog_create(), and 'ctx' the given context (e.g.
+skb pointer). All constraints and restrictions from bpf_check_classic() apply
 before a conversion to the new layout is being done behind the scenes!
 
 Currently, the classic BPF format is being used for JITing on most of the
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/i40e.txt linux-libre-3.17-rc7-gnu/Documentation/networking/i40e.txt
--- linux-libre-3.16-gnu/Documentation/networking/i40e.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/i40e.txt	2014-09-28 17:29:07.000000000 -0400
@@ -69,8 +69,11 @@ Additional Configurations
 
   FCoE
   ----
-  Fiber Channel over Ethernet (FCoE) hardware offload is not currently
-  supported.
+  The driver supports Fiber Channel over Ethernet (FCoE) and Data Center
+  Bridging (DCB) functionality. Configuring DCB and FCoE is outside the scope
+  of this driver doc. Refer to http://www.open-fcoe.org/ for FCoE project
+  information and http://www.open-lldp.org/ or email list
+  e1000-eedc@lists.sourceforge.net for DCB information.
 
   MAC and VLAN anti-spoofing feature
   ----------------------------------
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/ip-sysctl.txt linux-libre-3.17-rc7-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-3.16-gnu/Documentation/networking/ip-sysctl.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/ip-sysctl.txt	2014-09-28 17:29:07.000000000 -0400
@@ -101,19 +101,17 @@ ipfrag_high_thresh - INTEGER
 	Maximum memory used to reassemble IP fragments. When
 	ipfrag_high_thresh bytes of memory is allocated for this purpose,
 	the fragment handler will toss packets until ipfrag_low_thresh
-	is reached.
+	is reached. This also serves as a maximum limit to namespaces
+	different from the initial one.
 
 ipfrag_low_thresh - INTEGER
-	See ipfrag_high_thresh
+	Maximum memory used to reassemble IP fragments before the kernel
+	begins to remove incomplete fragment queues to free up resources.
+	The kernel still accepts new fragments for defragmentation.
 
 ipfrag_time - INTEGER
 	Time in seconds to keep an IP fragment in memory.
 
-ipfrag_secret_interval - INTEGER
-	Regeneration interval (in seconds) of the hash secret (or lifetime
-	for the hash secret) for IP fragments.
-	Default: 600
-
 ipfrag_max_dist - INTEGER
 	ipfrag_max_dist is a non-negative integer value which defines the
 	maximum "disorder" which is allowed among fragments which share a
@@ -1132,6 +1130,15 @@ flowlabel_consistency - BOOLEAN
 	FALSE: disabled
 	Default: TRUE
 
+auto_flowlabels - BOOLEAN
+	Automatically generate flow labels based based on a flow hash
+	of the packet. This allows intermediate devices, such as routers,
+	to idenfify packet flows for mechanisms like Equal Cost Multipath
+	Routing (see RFC 6438).
+	TRUE: enabled
+	FALSE: disabled
+	Default: false
+
 anycast_src_echo_reply - BOOLEAN
 	Controls the use of anycast addresses as source addresses for ICMPv6
 	echo reply
@@ -1153,11 +1160,6 @@ ip6frag_low_thresh - INTEGER
 ip6frag_time - INTEGER
 	Time in seconds to keep an IPv6 fragment in memory.
 
-ip6frag_secret_interval - INTEGER
-	Regeneration interval (in seconds) of the hash secret (or lifetime
-	for the hash secret) for IPv6 fragments.
-	Default: 600
-
 conf/default/*:
 	Change the interface-specific default settings.
 
@@ -1210,6 +1212,18 @@ accept_ra_defrtr - BOOLEAN
 	Functional default: enabled if accept_ra is enabled.
 			    disabled if accept_ra is disabled.
 
+accept_ra_from_local - BOOLEAN
+	Accept RA with source-address that is found on local machine
+        if the RA is otherwise proper and able to be accepted.
+        Default is to NOT accept these as it may be an un-intended
+        network loop.
+
+	Functional default:
+           enabled if accept_ra_from_local is enabled
+               on a specific interface.
+	   disabled if accept_ra_from_local is disabled
+               on a specific interface.
+
 accept_ra_pinfo - BOOLEAN
 	Learn Prefix Information in Router Advertisement.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/packet_mmap.txt linux-libre-3.17-rc7-gnu/Documentation/networking/packet_mmap.txt
--- linux-libre-3.16-gnu/Documentation/networking/packet_mmap.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/packet_mmap.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1008,14 +1008,9 @@ hardware timestamps to be used. Note: yo
 of hardware timestamps with SIOCSHWTSTAMP (see related information from
 Documentation/networking/timestamping.txt).
 
-PACKET_TIMESTAMP accepts the same integer bit field as
-SO_TIMESTAMPING.  However, only the SOF_TIMESTAMPING_SYS_HARDWARE
-and SOF_TIMESTAMPING_RAW_HARDWARE values are recognized by
-PACKET_TIMESTAMP.  SOF_TIMESTAMPING_SYS_HARDWARE takes precedence over
-SOF_TIMESTAMPING_RAW_HARDWARE if both bits are set.
+PACKET_TIMESTAMP accepts the same integer bit field as SO_TIMESTAMPING:
 
-    int req = 0;
-    req |= SOF_TIMESTAMPING_SYS_HARDWARE;
+    int req = SOF_TIMESTAMPING_RAW_HARDWARE;
     setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req))
 
 For the mmap(2)ed ring buffers, such timestamps are stored in the
@@ -1023,14 +1018,13 @@ tpacket{,2,3}_hdr structure's tp_sec and
 what kind of timestamp has been reported, the tp_status field is binary |'ed
 with the following possible bits ...
 
-    TP_STATUS_TS_SYS_HARDWARE
     TP_STATUS_TS_RAW_HARDWARE
     TP_STATUS_TS_SOFTWARE
 
 ... that are equivalent to its SOF_TIMESTAMPING_* counterparts. For the
-RX_RING, if none of those 3 are set (i.e. PACKET_TIMESTAMP is not set),
-then this means that a software fallback was invoked *within* PF_PACKET's
-processing code (less precise).
+RX_RING, if neither is set (i.e. PACKET_TIMESTAMP is not set), then a
+software fallback was invoked *within* PF_PACKET's processing code (less
+precise).
 
 Getting timestamps for the TX_RING works as follows: i) fill the ring frames,
 ii) call sendto() e.g. in blocking mode, iii) wait for status of relevant
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/phy.txt linux-libre-3.17-rc7-gnu/Documentation/networking/phy.txt
--- linux-libre-3.16-gnu/Documentation/networking/phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -272,6 +272,8 @@ Writing a PHY driver
    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
+   read_mmd_indirect: Read PHY MMD indirect register
+   write_mmd_indirect: Write PHY MMD indirect register
 
  Of these, only config_aneg and read_status are required to be
  assigned by the driver code.  The rest are optional.  Also, it is
@@ -284,7 +286,21 @@ Writing a PHY driver
 
  Feel free to look at the Marvell, Cicada, and Davicom drivers in
  drivers/net/phy/ for examples (the lxt and qsemi drivers have
- not been tested as of this writing)
+ not been tested as of this writing).
+
+ The PHY's MMD register accesses are handled by the PAL framework
+ by default, but can be overridden by a specific PHY driver if
+ required. This could be the case if a PHY was released for
+ manufacturing before the MMD PHY register definitions were
+ standardized by the IEEE. Most modern PHYs will be able to use
+ the generic PAL framework for accessing the PHY's MMD registers.
+ An example of such usage is for Energy Efficient Ethernet support,
+ implemented in the PAL. This support uses the PAL to access MMD
+ registers for EEE query and configuration if the PHY supports
+ the IEEE standard access mechanisms, or can use the PHY's specific
+ access interfaces if overridden by the specific PHY driver. See
+ the Micrel driver in drivers/net/phy/ for an example of how this
+ can be implemented.
 
 Board Fixups
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/pktgen.txt linux-libre-3.17-rc7-gnu/Documentation/networking/pktgen.txt
--- linux-libre-3.16-gnu/Documentation/networking/pktgen.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/pktgen.txt	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,34 @@ For monitoring and control pktgen create
         /proc/net/pktgen/ethX
 
 
+Tuning NIC for max performance
+==============================
+
+The default NIC setting are (likely) not tuned for pktgen's artificial
+overload type of benchmarking, as this could hurt the normal use-case.
+
+Specifically increasing the TX ring buffer in the NIC:
+ # ethtool -G ethX tx 1024
+
+A larger TX ring can improve pktgen's performance, while it can hurt
+in the general case, 1) because the TX ring buffer might get larger
+than the CPUs L1/L2 cache, 2) because it allow more queueing in the
+NIC HW layer (which is bad for bufferbloat).
+
+One should be careful to conclude, that packets/descriptors in the HW
+TX ring cause delay.  Drivers usually delay cleaning up the
+ring-buffers (for various performance reasons), thus packets stalling
+the TX ring, might just be waiting for cleanup.
+
+This cleanup issues is specifically the case, for the driver ixgbe
+(Intel 82599 chip).  This driver (ixgbe) combine TX+RX ring cleanups,
+and the cleanup interval is affected by the ethtool --coalesce setting
+of parameter "rx-usecs".
+
+For ixgbe use e.g "30" resulting in approx 33K interrupts/sec (1/30*10^6):
+ # ethtool -C ethX rx-usecs 30
+
+
 Viewing threads
 ===============
 /proc/net/pktgen/kpktgend_0 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/timestamping/timestamping.c linux-libre-3.17-rc7-gnu/Documentation/networking/timestamping/timestamping.c
--- linux-libre-3.16-gnu/Documentation/networking/timestamping/timestamping.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/timestamping/timestamping.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,6 @@ static void usage(const char *error)
 	       "  SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
 	       "  SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
 	       "  SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
-	       "  SOF_TIMESTAMPING_SYS_HARDWARE - request reporting of transformed HW time stamps\n"
 	       "  SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
 	       "  SIOCGSTAMP - check last socket time stamp\n"
 	       "  SIOCGSTAMPNS - more accurate socket time stamp\n");
@@ -202,9 +201,7 @@ static void printpacket(struct msghdr *m
 				       (long)stamp->tv_sec,
 				       (long)stamp->tv_nsec);
 				stamp++;
-				printf("HW transformed %ld.%09ld ",
-				       (long)stamp->tv_sec,
-				       (long)stamp->tv_nsec);
+				/* skip deprecated HW transformed */
 				stamp++;
 				printf("HW raw %ld.%09ld",
 				       (long)stamp->tv_sec,
@@ -361,8 +358,6 @@ int main(int argc, char **argv)
 			so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
 		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
 			so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
-		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SYS_HARDWARE"))
-			so_timestamping_flags |= SOF_TIMESTAMPING_SYS_HARDWARE;
 		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
 			so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
 		else
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/networking/timestamping.txt linux-libre-3.17-rc7-gnu/Documentation/networking/timestamping.txt
--- linux-libre-3.16-gnu/Documentation/networking/timestamping.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/networking/timestamping.txt	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@ the set bits correspond to data that is
 message will not be generated:
 
 SOF_TIMESTAMPING_SOFTWARE:     report systime if available
-SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available
+SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available (deprecated)
 SOF_TIMESTAMPING_RAW_HARDWARE: report hwtimeraw if available
 
 It is worth noting that timestamps may be collected for reasons other
@@ -88,13 +88,12 @@ hwtimeraw is the original hardware time
 SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its
 relation to system time should be made.
 
-hwtimetrans is the hardware time stamp transformed so that it
-corresponds as good as possible to system time. This correlation is
-not perfect; as a consequence, sorting packets received via different
-NICs by their hwtimetrans may differ from the order in which they were
-received. hwtimetrans may be non-monotonic even for the same NIC.
-Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
-by the network device and will be empty without that support.
+hwtimetrans is always zero. This field is deprecated. It used to hold
+hw timestamps converted to system time. Instead, expose the hardware
+clock device on the NIC directly as a HW PTP clock source, to allow
+time conversion in userspace and optionally synchronize system time
+with a userspace PTP stack such as linuxptp. For the PTP clock API,
+see Documentation/ptp/ptp.txt.
 
 
 SIOCSHWTSTAMP, SIOCGHWTSTAMP:
@@ -185,7 +184,6 @@ struct skb_shared_hwtstamps {
 	 * since arbitrary point in time
 	 */
 	ktime_t	hwtstamp;
-	ktime_t	syststamp; /* hwtstamp transformed to system time base */
 };
 
 Time stamps for outgoing packets are to be generated as follows:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/oops-tracing.txt linux-libre-3.17-rc7-gnu/Documentation/oops-tracing.txt
--- linux-libre-3.16-gnu/Documentation/oops-tracing.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/oops-tracing.txt	2014-09-28 17:29:07.000000000 -0400
@@ -268,6 +268,8 @@ characters, each representing a particul
  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.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/PCI/MSI-HOWTO.txt linux-libre-3.17-rc7-gnu/Documentation/PCI/MSI-HOWTO.txt
--- linux-libre-3.16-gnu/Documentation/PCI/MSI-HOWTO.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/PCI/MSI-HOWTO.txt	2014-09-28 17:29:07.000000000 -0400
@@ -576,7 +576,7 @@ Some devices are known to have faulty MS
 is handled in the individual device driver, but occasionally it's necessary
 to handle this with a quirk.  Some drivers have an option to disable use
 of MSI.  While this is a convenient workaround for the driver author,
-it is not good practise, and should not be emulated.
+it is not good practice, and should not be emulated.
 
 5.4. Finding why MSIs are disabled on a device
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/phy.txt linux-libre-3.17-rc7-gnu/Documentation/phy.txt
--- linux-libre-3.16-gnu/Documentation/phy.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/phy.txt	2014-09-28 17:29:07.000000000 -0400
@@ -53,10 +53,12 @@ unregister the PHY.
 The PHY driver should create the PHY in order for other peripheral controllers
 to make use of it. The PHY framework provides 2 APIs to create the PHY.
 
-struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
-        struct phy_init_data *init_data);
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data);
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+			    const struct phy_ops *ops,
+			    struct phy_init_data *init_data);
 
 The PHY drivers can use one of the above 2 APIs to create the PHY by passing
 the device pointer, phy ops and init_data.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/opp.txt linux-libre-3.17-rc7-gnu/Documentation/power/opp.txt
--- linux-libre-3.16-gnu/Documentation/power/opp.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/opp.txt	2014-09-28 17:29:07.000000000 -0400
@@ -51,9 +51,6 @@ Typical usage of the OPP library is as f
 SoC framework	-> modifies on required cases certain OPPs	-> OPP layer
 		-> queries to search/retrieve information	->
 
-Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP
-to make the OPP layer available.
-
 OPP layer expects each domain to be represented by a unique device pointer. SoC
 framework registers a set of initial OPPs per device with the OPP layer. This
 list is expected to be an optimally small number typically around 5 per device.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/power_supply_class.txt linux-libre-3.17-rc7-gnu/Documentation/power/power_supply_class.txt
--- linux-libre-3.16-gnu/Documentation/power/power_supply_class.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/power_supply_class.txt	2014-09-28 17:29:07.000000000 -0400
@@ -118,6 +118,10 @@ relative, time-based measurements.
 CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger.
 CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the
 power supply object.
+INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates
+the current drawn from a charging source.
+CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge
+condition.
 
 CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
 CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
@@ -140,6 +144,8 @@ TEMP_ALERT_MAX - maximum battery tempera
 TEMP_AMBIENT - ambient temperature.
 TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert.
 TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert.
+TEMP_MIN - minimum operatable temperature
+TEMP_MAX - maximum operatable temperature
 
 TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
 while battery powers a load)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/regulator/consumer.txt linux-libre-3.17-rc7-gnu/Documentation/power/regulator/consumer.txt
--- linux-libre-3.16-gnu/Documentation/power/regulator/consumer.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/regulator/consumer.txt	2014-09-28 17:29:07.000000000 -0400
@@ -143,8 +143,9 @@ This will cause the core to recalculate
 on all its consumers) and change operating mode (if necessary and permitted)
 to best match the current operating load.
 
-The load_uA value can be determined from the consumers datasheet. e.g.most
-datasheets have tables showing the max current consumed in certain situations.
+The load_uA value can be determined from the consumer's datasheet. e.g. most
+datasheets have tables showing the maximum current consumed in certain
+situations.
 
 Most consumers will use indirect operating mode control since they have no
 knowledge of the regulator or whether the regulator is shared with other
@@ -173,10 +174,45 @@ Consumers can register interest in regul
 int regulator_register_notifier(struct regulator *regulator,
 			      struct notifier_block *nb);
 
-Consumers can uregister interest by calling :-
+Consumers can unregister interest by calling :-
 
 int regulator_unregister_notifier(struct regulator *regulator,
 				struct notifier_block *nb);
 
 Regulators use the kernel notifier framework to send event to their interested
 consumers.
+
+7. Regulator Direct Register Access
+===================================
+Some kinds of power management hardware or firmware are designed such that
+they need to do low-level hardware access to regulators, with no involvement
+from the kernel. Examples of such devices are:
+
+- clocksource with a voltage-controlled oscillator and control logic to change
+  the supply voltage over I2C to achieve a desired output clock rate
+- thermal management firmware that can issue an arbitrary I2C transaction to
+  perform system poweroff during overtemperature conditions
+
+To set up such a device/firmware, various parameters like I2C address of the
+regulator, addresses of various regulator registers etc. need to be configured
+to it. The regulator framework provides the following helpers for querying
+these details.
+
+Bus-specific details, like I2C addresses or transfer rates are handled by the
+regmap framework. To get the regulator's regmap (if supported), use :-
+
+struct regmap *regulator_get_regmap(struct regulator *regulator);
+
+To obtain the hardware register offset and bitmask for the regulator's voltage
+selector register, use :-
+
+int regulator_get_hardware_vsel_register(struct regulator *regulator,
+					 unsigned *vsel_reg,
+					 unsigned *vsel_mask);
+
+To convert a regulator framework voltage selector code (used by
+regulator_list_voltage) to a hardware-specific voltage selector that can be
+directly written to the voltage selector register, use :-
+
+int regulator_list_hardware_vsel(struct regulator *regulator,
+				 unsigned selector);
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/regulator/design.txt linux-libre-3.17-rc7-gnu/Documentation/power/regulator/design.txt
--- linux-libre-3.16-gnu/Documentation/power/regulator/design.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/regulator/design.txt	2014-09-28 17:29:07.000000000 -0400
@@ -9,14 +9,14 @@ Safety
 
  - Errors in regulator configuration can have very serious consequences
    for the system, potentially including lasting hardware damage.
- - It is not possible to automatically determine the power confugration
+ - It is not possible to automatically determine the power configuration
    of the system - software-equivalent variants of the same chip may
-   have different power requirments, and not all components with power
+   have different power requirements, and not all components with power
    requirements are visible to software.
 
   => The API should make no changes to the hardware state unless it has
-     specific knowledge that these changes are safe to do perform on
-     this particular system.
+     specific knowledge that these changes are safe to perform on this
+     particular system.
 
 Consumer use cases
 ------------------
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/regulator/machine.txt linux-libre-3.17-rc7-gnu/Documentation/power/regulator/machine.txt
--- linux-libre-3.16-gnu/Documentation/power/regulator/machine.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/regulator/machine.txt	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,7 @@ Consider the following machine :-
                +-> [Consumer B @ 3.3V]
 
 The drivers for consumers A & B must be mapped to the correct regulator in
-order to control their power supply. This mapping can be achieved in machine
+order to control their power supplies. This mapping can be achieved in machine
 initialisation code by creating a struct regulator_consumer_supply for
 each regulator.
 
@@ -39,7 +39,7 @@ to the 'Vcc' supply for Consumer A.
 
 Constraints can now be registered by defining a struct regulator_init_data
 for each regulator power domain. This structure also maps the consumers
-to their supply regulator :-
+to their supply regulators :-
 
 static struct regulator_init_data regulator1_data = {
 	.constraints = {
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/regulator/overview.txt linux-libre-3.17-rc7-gnu/Documentation/power/regulator/overview.txt
--- linux-libre-3.16-gnu/Documentation/power/regulator/overview.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/regulator/overview.txt	2014-09-28 17:29:07.000000000 -0400
@@ -36,11 +36,11 @@ Some terms used in this document:-
                    Consumers can be classified into two types:-
 
                    Static: consumer does not change its supply voltage or
-                   current limit. It only needs to enable or disable it's
+                   current limit. It only needs to enable or disable its
                    power supply. Its supply voltage is set by the hardware,
                    bootloader, firmware or kernel board initialisation code.
 
-                   Dynamic: consumer needs to change it's supply voltage or
+                   Dynamic: consumer needs to change its supply voltage or
                    current limit to meet operation demands.
 
 
@@ -156,7 +156,7 @@ relevant to non SoC devices and is split
       This interface is for machine specific code and allows the creation of
       voltage/current domains (with constraints) for each regulator. It can
       provide regulator constraints that will prevent device damage through
-      overvoltage or over current caused by buggy client drivers. It also
+      overvoltage or overcurrent caused by buggy client drivers. It also
       allows the creation of a regulator tree whereby some regulators are
       supplied by others (similar to a clock tree).
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/power/regulator/regulator.txt linux-libre-3.17-rc7-gnu/Documentation/power/regulator/regulator.txt
--- linux-libre-3.16-gnu/Documentation/power/regulator/regulator.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/power/regulator/regulator.txt	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@ Drivers can register a regulator by call
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
 					 const struct regulator_config *config);
 
-This will register the regulators capabilities and operations to the regulator
+This will register the regulator's capabilities and operations to the regulator
 core.
 
 Regulators can be unregistered by calling :-
@@ -23,8 +23,8 @@ void regulator_unregister(struct regulat
 
 Regulator Events
 ================
-Regulators can send events (e.g. over temp, under voltage, etc) to consumer
-drivers by calling :-
+Regulators can send events (e.g. overtemperature, undervoltage, etc) to
+consumer drivers by calling :-
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
 				  unsigned long event, void *data);
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/powerpc/00-INDEX linux-libre-3.17-rc7-gnu/Documentation/powerpc/00-INDEX
--- linux-libre-3.16-gnu/Documentation/powerpc/00-INDEX	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/powerpc/00-INDEX	2014-09-28 17:29:07.000000000 -0400
@@ -17,8 +17,6 @@ firmware-assisted-dump.txt
 	- Documentation on the firmware assisted dump mechanism "fadump".
 hvcs.txt
 	- IBM "Hypervisor Virtual Console Server" Installation Guide
-kvm_440.txt
-	- Various notes on the implementation of KVM for PowerPC 440.
 mpc52xx.txt
 	- Linux 2.6.x on MPC52xx family
 pmu-ebb.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/powerpc/kvm_440.txt linux-libre-3.17-rc7-gnu/Documentation/powerpc/kvm_440.txt
--- linux-libre-3.16-gnu/Documentation/powerpc/kvm_440.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/powerpc/kvm_440.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-Hollis Blanchard <hollisb@us.ibm.com>
-15 Apr 2008
-
-Various notes on the implementation of KVM for PowerPC 440:
-
-To enforce isolation, host userspace, guest kernel, and guest userspace all
-run at user privilege level. Only the host kernel runs in supervisor mode.
-Executing privileged instructions in the guest traps into KVM (in the host
-kernel), where we decode and emulate them. Through this technique, unmodified
-440 Linux kernels can be run (slowly) as guests. Future performance work will
-focus on reducing the overhead and frequency of these traps.
-
-The usual code flow is started from userspace invoking an "run" ioctl, which
-causes KVM to switch into guest context. We use IVPR to hijack the host
-interrupt vectors while running the guest, which allows us to direct all
-interrupts to kvmppc_handle_interrupt(). At this point, we could either
-- handle the interrupt completely (e.g. emulate "mtspr SPRG0"), or
-- let the host interrupt handler run (e.g. when the decrementer fires), or
-- return to host userspace (e.g. when the guest performs device MMIO)
-
-Address spaces: We take advantage of the fact that Linux doesn't use the AS=1
-address space (in host or guest), which gives us virtual address space to use
-for guest mappings. While the guest is running, the host kernel remains mapped
-in AS=0, but the guest can only use AS=1 mappings.
-
-TLB entries: The TLB entries covering the host linear mapping remain
-present while running the guest. This reduces the overhead of lightweight
-exits, which are handled by KVM running in the host kernel. We keep three
-copies of the TLB:
- - guest TLB: contents of the TLB as the guest sees it
- - shadow TLB: the TLB that is actually in hardware while guest is running
- - host TLB: to restore TLB state when context switching guest -> host
-When a TLB miss occurs because a mapping was not present in the shadow TLB,
-but was present in the guest TLB, KVM handles the fault without invoking the
-guest. Large guest pages are backed by multiple 4KB shadow pages through this
-mechanism.
-
-IO: MMIO and DCR accesses are emulated by userspace. We use virtio for network
-and block IO, so those drivers must be enabled in the guest. It's possible
-that some qemu device emulation (e.g. e1000 or rtl8139) may also work with
-little effort.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/rapidio/tsi721.txt linux-libre-3.17-rc7-gnu/Documentation/rapidio/tsi721.txt
--- linux-libre-3.16-gnu/Documentation/rapidio/tsi721.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/rapidio/tsi721.txt	2014-09-28 17:29:07.000000000 -0400
@@ -20,13 +20,26 @@ II. Known problems
 
   None.
 
-III. To do
+III. DMA Engine Support
 
- Add DMA data transfers (non-messaging).
- Add inbound region (SRIO-to-PCIe) mapping.
+Tsi721 mport driver supports DMA data transfers between local system memory and
+remote RapidIO devices. This functionality is implemented according to SLAVE
+mode API defined by common Linux kernel DMA Engine framework.
+
+Depending on system requirements RapidIO DMA operations can be included/excluded
+by setting CONFIG_RAPIDIO_DMA_ENGINE option. Tsi721 miniport driver uses seven
+out of eight available BDMA channels to support DMA data transfers.
+One BDMA channel is reserved for generation of maintenance read/write requests.
+
+If Tsi721 mport driver have been built with RAPIDIO_DMA_ENGINE support included,
+this driver will accept DMA-specific module parameter:
+  "dma_desc_per_channel" - defines number of hardware buffer descriptors used by
+                           each BDMA channel of Tsi721 (by default - 128).
 
 IV. Version History
 
+  1.1.0 - DMA operations re-worked to support data scatter/gather lists larger
+          than hardware buffer descriptors ring.
   1.0.0 - Initial driver release.
 
 V.  License
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/RCU/rcuref.txt linux-libre-3.17-rc7-gnu/Documentation/RCU/rcuref.txt
--- linux-libre-3.16-gnu/Documentation/RCU/rcuref.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/RCU/rcuref.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,14 @@
 Reference-count design for elements of lists/arrays protected by RCU.
 
+
+Please note that the percpu-ref feature is likely your first
+stop if you need to combine reference counts and RCU.  Please see
+include/linux/percpu-refcount.h for more information.  However, in
+those unusual cases where percpu-ref would consume too much memory,
+please read on.
+
+------------------------------------------------------------------------
+
 Reference counting on elements of lists which are protected by traditional
 reader/writer spinlocks or semaphores are straightforward:
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/RCU/RTFP.txt linux-libre-3.17-rc7-gnu/Documentation/RCU/RTFP.txt
--- linux-libre-3.16-gnu/Documentation/RCU/RTFP.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/RCU/RTFP.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2451,8 +2451,8 @@ lot of {Linux} into your technology!!!"
 ,month="February"
 ,year="2010"
 ,note="Available:
-\url{http://kerneltrap.com/mailarchive/linux-netdev/2010/2/26/6270589}
-[Viewed March 20, 2011]"
+\url{http://thread.gmane.org/gmane.linux.network/153338}
+[Viewed June 9, 2014]"
 ,annotation={
 	Use a pair of list_head structures to support RCU-protected
 	resizable hash tables.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/RCU/whatisRCU.txt linux-libre-3.17-rc7-gnu/Documentation/RCU/whatisRCU.txt
--- linux-libre-3.16-gnu/Documentation/RCU/whatisRCU.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/RCU/whatisRCU.txt	2014-09-28 17:29:07.000000000 -0400
@@ -818,7 +818,7 @@ RCU pointer/list update:
 	list_add_tail_rcu
 	list_del_rcu
 	list_replace_rcu
-	hlist_add_after_rcu
+	hlist_add_behind_rcu
 	hlist_add_before_rcu
 	hlist_add_head_rcu
 	hlist_del_rcu
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/scsi/ncr53c8xx.txt linux-libre-3.17-rc7-gnu/Documentation/scsi/ncr53c8xx.txt
--- linux-libre-3.16-gnu/Documentation/scsi/ncr53c8xx.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/scsi/ncr53c8xx.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1095,7 +1095,7 @@ SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(default:
 SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
 	If defined, master parity checking is enabled.
 
-SCSI_NCR_SETUP_MASTER_PARITY	(default: defined)
+SCSI_NCR_SETUP_SCSI_PARITY	(default: defined)
 	If defined, SCSI parity checking is enabled.
 
 SCSI_NCR_PROFILE_SUPPORT	(default: not defined)
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/scsi/tmscsim.txt linux-libre-3.17-rc7-gnu/Documentation/scsi/tmscsim.txt
--- linux-libre-3.16-gnu/Documentation/scsi/tmscsim.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/scsi/tmscsim.txt	2014-09-28 17:29:07.000000000 -0400
@@ -317,8 +317,6 @@ Each of the parameters is a number, cont
     4	 0x10	   16	  Immediate return on BIOS seek command. (Not used)
  (*)5	 0x20	   32	  Check for LUNs >= 1.
   
-  The default for LUN Check depends on CONFIG_SCSI_MULTI_LUN.
-
 * TaggedCmnds is a number indicating the maximum number of Tagged Commands.
   It is the binary logarithm - 1 of the actual number. Max is 4 (32).
    Value  Number of Tagged Commands
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/security/keys.txt linux-libre-3.17-rc7-gnu/Documentation/security/keys.txt
--- linux-libre-3.16-gnu/Documentation/security/keys.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/security/keys.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1150,20 +1150,24 @@ The structure has a number of fields, so
 		const void	*data;
 		size_t		datalen;
 		size_t		quotalen;
+		time_t		expiry;
 	};
 
      Before calling the method, the caller will fill in data and datalen with
      the payload blob parameters; quotalen will be filled in with the default
-     quota size from the key type and the rest will be cleared.
+     quota size from the key type; expiry will be set to TIME_T_MAX and the
+     rest will be cleared.
 
      If a description can be proposed from the payload contents, that should be
      attached as a string to the description field.  This will be used for the
      key description if the caller of add_key() passes NULL or "".
 
      The method can attach anything it likes to type_data[] and payload.  These
-     are merely passed along to the instantiate() or update() operations.
+     are merely passed along to the instantiate() or update() operations.  If
+     set, the expiry time will be applied to the key if it is instantiated from
+     this data.
 
-     The method should return 0 if success ful or a negative error code
+     The method should return 0 if successful or a negative error code
      otherwise.
 
      
@@ -1172,7 +1176,9 @@ The structure has a number of fields, so
      This method is only required if the preparse() method is provided,
      otherwise it is unused.  It cleans up anything attached to the
      description, type_data and payload fields of the key_preparsed_payload
-     struct as filled in by the preparse() method.
+     struct as filled in by the preparse() method.  It will always be called
+     after preparse() returns successfully, even if instantiate() or update()
+     succeed.
 
 
  (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/security/LSM.txt linux-libre-3.17-rc7-gnu/Documentation/security/LSM.txt
--- linux-libre-3.16-gnu/Documentation/security/LSM.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/security/LSM.txt	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@ system, building their checks on top of
 For more details on capabilities, see capabilities(7) in the Linux
 man-pages project.
 
-Based on http://kerneltrap.org/Linux/Documenting_Security_Module_Intent,
+Based on https://lkml.org/lkml/2007/10/26/215,
 a new LSM is accepted into the kernel when its intent (a description of
 what it tries to protect against and in what cases one would expect to
 use it) has been appropriately documented in Documentation/security/.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-3.17-rc7-gnu/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-3.16-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2014-08-07 05:02:59.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2014-09-28 21:46:08.000000000 -0400
@@ -2017,8 +2017,8 @@ Prior to version 0.9.0rc4 options had a
   -------------------
 
     Module for sound cards based on the Asus AV66/AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
-    HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+    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.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-3.17-rc7-gnu/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-3.16-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2014-09-28 17:29:07.000000000 -0400
@@ -284,6 +284,11 @@ STAC92HD83*
   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
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/stable_kernel_rules.txt linux-libre-3.17-rc7-gnu/Documentation/stable_kernel_rules.txt
--- linux-libre-3.16-gnu/Documentation/stable_kernel_rules.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/stable_kernel_rules.txt	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,9 @@ Rules on what kind of patches are accept
 
 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
  - 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
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/SubmittingDrivers linux-libre-3.17-rc7-gnu/Documentation/SubmittingDrivers
--- linux-libre-3.16-gnu/Documentation/SubmittingDrivers	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/SubmittingDrivers	2014-09-28 17:29:07.000000000 -0400
@@ -146,10 +146,6 @@ LWN.net:
 	Porting drivers from prior kernels to 2.6:
 		http://lwn.net/Articles/driver-porting/
 
-KernelTrap:
-	Occasional Linux kernel articles and developer interviews
-	http://kerneltrap.org/
-
 KernelNewbies:
 	Documentation and assistance for new kernel programmers
 	http://kernelnewbies.org/
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/SubmittingPatches linux-libre-3.17-rc7-gnu/Documentation/SubmittingPatches
--- linux-libre-3.16-gnu/Documentation/SubmittingPatches	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/SubmittingPatches	2014-09-28 17:29:07.000000000 -0400
@@ -84,18 +84,42 @@ is another popular alternative.
 
 2) Describe your changes.
 
-Describe the technical detail of the change(s) your patch includes.
+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.
 
-Be as specific as possible.  The WORST descriptions possible include
-things like "update driver X", "bug fix for driver X", or "this patch
-includes updates for subsystem X.  Please apply."
+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 #15, below.
 
-If your description starts to get long, that's a sign that you probably
-need to split up your patch.  See #3, next.
+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 #3, next.
 
 When you submit or resubmit a patch or patch series, include the
 complete patch description and justification for it.  Don't just
@@ -396,13 +420,13 @@ you are responsible for last-minute chan
 	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
 	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
 
-This practise is particularly helpful if you maintain a stable branch and
+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 practise
+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 2.6-stable :
@@ -770,6 +794,7 @@ Greg Kroah-Hartman, "How to piss off a k
   <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>
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/sysctl/kernel.txt linux-libre-3.17-rc7-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-3.16-gnu/Documentation/sysctl/kernel.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/sysctl/kernel.txt	2014-09-28 17:29:07.000000000 -0400
@@ -826,6 +826,7 @@ can be ORed together:
 4096 - An out-of-tree module has been loaded.
 8192 - An unsigned module has been loaded in a kernel supporting module
        signature.
+16384 - A soft lockup has previously occurred on the system.
 
 ==============================================================
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/this_cpu_ops.txt linux-libre-3.17-rc7-gnu/Documentation/this_cpu_ops.txt
--- linux-libre-3.16-gnu/Documentation/this_cpu_ops.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/this_cpu_ops.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2,26 +2,26 @@ this_cpu operations
 -------------------
 
 this_cpu operations are a way of optimizing access to per cpu
-variables associated with the *currently* executing processor through
-the use of segment registers (or a dedicated register where the cpu
-permanently stored the beginning of the per cpu area for a specific
-processor).
+variables associated with the *currently* executing processor. This is
+done through the use of segment registers (or a dedicated register where
+the cpu permanently stored the beginning of the per cpu	area for a
+specific processor).
 
-The this_cpu operations add a per cpu variable offset to the processor
-specific percpu base and encode that operation in the instruction
+this_cpu operations add a per cpu variable offset to the processor
+specific per cpu base and encode that operation in the instruction
 operating on the per cpu variable.
 
-This means there are no atomicity issues between the calculation of
+This means that there are no atomicity issues between the calculation of
 the offset and the operation on the data. Therefore it is not
-necessary to disable preempt or interrupts to ensure that the
+necessary to disable preemption or interrupts to ensure that the
 processor is not changed between the calculation of the address and
 the operation on the data.
 
 Read-modify-write operations are of particular interest. Frequently
 processors have special lower latency instructions that can operate
-without the typical synchronization overhead but still provide some
-sort of relaxed atomicity guarantee. The x86 for example can execute
-RMV (Read Modify Write) instructions like inc/dec/cmpxchg without the
+without the typical synchronization overhead, but still provide some
+sort of relaxed atomicity guarantees. The x86, for example, can execute
+RMW (Read Modify Write) instructions like inc/dec/cmpxchg without the
 lock prefix and the associated latency penalty.
 
 Access to the variable without the lock prefix is not synchronized but
@@ -30,6 +30,38 @@ data specific to the currently executing
 processor should be accessing that variable and therefore there are no
 concurrency issues with other processors in the system.
 
+Please note that accesses by remote processors to a per cpu area are
+exceptional situations and may impact performance and/or correctness
+(remote write operations) of local RMW operations via this_cpu_*.
+
+The main use of the this_cpu operations has been to optimize counter
+operations.
+
+The following this_cpu() operations with implied preemption protection
+are defined. These operations can be used without worrying about
+preemption and interrupts.
+
+	this_cpu_add()
+	this_cpu_read(pcp)
+	this_cpu_write(pcp, val)
+	this_cpu_add(pcp, val)
+	this_cpu_and(pcp, val)
+	this_cpu_or(pcp, val)
+	this_cpu_add_return(pcp, val)
+	this_cpu_xchg(pcp, nval)
+	this_cpu_cmpxchg(pcp, oval, nval)
+	this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+	this_cpu_sub(pcp, val)
+	this_cpu_inc(pcp)
+	this_cpu_dec(pcp)
+	this_cpu_sub_return(pcp, val)
+	this_cpu_inc_return(pcp)
+	this_cpu_dec_return(pcp)
+
+
+Inner working of this_cpu operations
+------------------------------------
+
 On x86 the fs: or the gs: segment registers contain the base of the
 per cpu area. It is then possible to simply use the segment override
 to relocate a per cpu relative address to the proper per cpu area for
@@ -48,22 +80,21 @@ results in a single instruction
 	mov ax, gs:[x]
 
 instead of a sequence of calculation of the address and then a fetch
-from that address which occurs with the percpu operations. Before
+from that address which occurs with the per cpu operations. Before
 this_cpu_ops such sequence also required preempt disable/enable to
 prevent the kernel from moving the thread to a different processor
 while the calculation is performed.
 
-The main use of the this_cpu operations has been to optimize counter
-operations.
+Consider the following this_cpu operation:
 
 	this_cpu_inc(x)
 
-results in the following single instruction (no lock prefix!)
+The above results in the following single instruction (no lock prefix!)
 
 	inc gs:[x]
 
 instead of the following operations required if there is no segment
-register.
+register:
 
 	int *y;
 	int cpu;
@@ -73,10 +104,10 @@ register.
 	(*y)++;
 	put_cpu();
 
-Note that these operations can only be used on percpu data that is
+Note that these operations can only be used on per cpu data that is
 reserved for a specific processor. Without disabling preemption in the
 surrounding code this_cpu_inc() will only guarantee that one of the
-percpu counters is correctly incremented. However, there is no
+per cpu counters is correctly incremented. However, there is no
 guarantee that the OS will not move the process directly before or
 after the this_cpu instruction is executed. In general this means that
 the value of the individual counters for each processor are
@@ -86,9 +117,9 @@ that is of interest.
 Per cpu variables are used for performance reasons. Bouncing cache
 lines can be avoided if multiple processors concurrently go through
 the same code paths.  Since each processor has its own per cpu
-variables no concurrent cacheline updates take place. The price that
+variables no concurrent cache line updates take place. The price that
 has to be paid for this optimization is the need to add up the per cpu
-counters when the value of the counter is needed.
+counters when the value of a counter is needed.
 
 
 Special operations:
@@ -100,33 +131,39 @@ Takes the offset of a per cpu variable (
 of the per cpu variable that belongs to the currently executing
 processor.  this_cpu_ptr avoids multiple steps that the common
 get_cpu/put_cpu sequence requires. No processor number is
-available. Instead the offset of the local per cpu area is simply
-added to the percpu offset.
+available. Instead, the offset of the local per cpu area is simply
+added to the per cpu offset.
 
+Note that this operation is usually used in a code segment when
+preemption has been disabled. The pointer is then used to
+access local per cpu data in a critical section. When preemption
+is re-enabled this pointer is usually no longer useful since it may
+no longer point to per cpu data of the current processor.
 
 
 Per cpu variables and offsets
 -----------------------------
 
-Per cpu variables have *offsets* to the beginning of the percpu
+Per cpu variables have *offsets* to the beginning of the per cpu
 area. They do not have addresses although they look like that in the
 code. Offsets cannot be directly dereferenced. The offset must be
-added to a base pointer of a percpu area of a processor in order to
+added to a base pointer of a per cpu area of a processor in order to
 form a valid address.
 
 Therefore the use of x or &x outside of the context of per cpu
 operations is invalid and will generally be treated like a NULL
 pointer dereference.
 
-In the context of per cpu operations
+	DEFINE_PER_CPU(int, x);
 
-	x is a per cpu variable. Most this_cpu operations take a cpu
-	variable.
+In the context of per cpu operations the above implies that x is a per
+cpu variable. Most this_cpu operations take a cpu variable.
 
-	&x is the *offset* a per cpu variable. this_cpu_ptr() takes
-	the offset of a per cpu variable which makes this look a bit
-	strange.
+	int __percpu *p = &x;
 
+&x and hence p is the *offset* of a per cpu variable. this_cpu_ptr()
+takes the offset of a per cpu variable which makes this look a bit
+strange.
 
 
 Operations on a field of a per cpu structure
@@ -152,7 +189,7 @@ If we have an offset to struct s:
 
 	struct s __percpu *ps = &p;
 
-	z = this_cpu_dec(ps->m);
+	this_cpu_dec(ps->m);
 
 	z = this_cpu_inc_return(ps->n);
 
@@ -172,29 +209,52 @@ if we do not make use of this_cpu ops la
 Variants of this_cpu ops
 -------------------------
 
-this_cpu ops are interrupt safe. Some architecture do not support
+this_cpu ops are interrupt safe. Some architectures do not support
 these per cpu local operations. In that case the operation must be
 replaced by code that disables interrupts, then does the operations
-that are guaranteed to be atomic and then reenable interrupts. Doing
+that are guaranteed to be atomic and then re-enable interrupts. Doing
 so is expensive. If there are other reasons why the scheduler cannot
 change the processor we are executing on then there is no reason to
-disable interrupts. For that purpose the __this_cpu operations are
-provided. For example.
+disable interrupts. For that purpose the following __this_cpu operations
+are provided.
 
-	__this_cpu_inc(x);
+These operations have no guarantee against concurrent interrupts or
+preemption. If a per cpu variable is not used in an interrupt context
+and the scheduler cannot preempt, then they are safe. If any interrupts
+still occur while an operation is in progress and if the interrupt too
+modifies the variable, then RMW actions can not be guaranteed to be
+safe.
 
-Will increment x and will not fallback to code that disables
+	__this_cpu_add()
+	__this_cpu_read(pcp)
+	__this_cpu_write(pcp, val)
+	__this_cpu_add(pcp, val)
+	__this_cpu_and(pcp, val)
+	__this_cpu_or(pcp, val)
+	__this_cpu_add_return(pcp, val)
+	__this_cpu_xchg(pcp, nval)
+	__this_cpu_cmpxchg(pcp, oval, nval)
+	__this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+	__this_cpu_sub(pcp, val)
+	__this_cpu_inc(pcp)
+	__this_cpu_dec(pcp)
+	__this_cpu_sub_return(pcp, val)
+	__this_cpu_inc_return(pcp)
+	__this_cpu_dec_return(pcp)
+
+
+Will increment x and will not fall-back to code that disables
 interrupts on platforms that cannot accomplish atomicity through
 address relocation and a Read-Modify-Write operation in the same
 instruction.
 
 
-
 &this_cpu_ptr(pp)->n vs this_cpu_ptr(&pp->n)
 --------------------------------------------
 
 The first operation takes the offset and forms an address and then
-adds the offset of the n field.
+adds the offset of the n field. This may result in two add
+instructions emitted by the compiler.
 
 The second one first adds the two offsets and then does the
 relocation.  IMHO the second form looks cleaner and has an easier time
@@ -202,4 +262,73 @@ with (). The second form also is consist
 this_cpu_read() and friends are used.
 
 
-Christoph Lameter, April 3rd, 2013
+Remote access to per cpu data
+------------------------------
+
+Per cpu data structures are designed to be used by one cpu exclusively.
+If you use the variables as intended, this_cpu_ops() are guaranteed to
+be "atomic" as no other CPU has access to these data structures.
+
+There are special cases where you might need to access per cpu data
+structures remotely. It is usually safe to do a remote read access
+and that is frequently done to summarize counters. Remote write access
+something which could be problematic because this_cpu ops do not
+have lock semantics. A remote write may interfere with a this_cpu
+RMW operation.
+
+Remote write accesses to percpu data structures are highly discouraged
+unless absolutely necessary. Please consider using an IPI to wake up
+the remote CPU and perform the update to its per cpu area.
+
+To access per-cpu data structure remotely, typically the per_cpu_ptr()
+function is used:
+
+
+	DEFINE_PER_CPU(struct data, datap);
+
+	struct data *p = per_cpu_ptr(&datap, cpu);
+
+This makes it explicit that we are getting ready to access a percpu
+area remotely.
+
+You can also do the following to convert the datap offset to an address
+
+	struct data *p = this_cpu_ptr(&datap);
+
+but, passing of pointers calculated via this_cpu_ptr to other cpus is
+unusual and should be avoided.
+
+Remote access are typically only for reading the status of another cpus
+per cpu data. Write accesses can cause unique problems due to the
+relaxed synchronization requirements for this_cpu operations.
+
+One example that illustrates some concerns with write operations is
+the following scenario that occurs because two per cpu variables
+share a cache-line but the relaxed synchronization is applied to
+only one process updating the cache-line.
+
+Consider the following example
+
+
+	struct test {
+		atomic_t a;
+		int b;
+	};
+
+	DEFINE_PER_CPU(struct test, onecacheline);
+
+There is some concern about what would happen if the field 'a' is updated
+remotely from one processor and the local processor would use this_cpu ops
+to update field b. Care should be taken that such simultaneous accesses to
+data within the same cache line are avoided. Also costly synchronization
+may be necessary. IPIs are generally recommended in such scenarios instead
+of a remote write to the per cpu area of another processor.
+
+Even in cases where the remote writes are rare, please bear in
+mind that a remote write will evict the cache line from the processor
+that most likely will access it. If the processor wakes up and finds a
+missing local cache line of a per cpu area, its performance and hence
+the wake up times will be affected.
+
+Christoph Lameter, August 4th, 2014
+Pranith Kumar, Aug 2nd, 2014
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/timers/00-INDEX linux-libre-3.17-rc7-gnu/Documentation/timers/00-INDEX
--- linux-libre-3.16-gnu/Documentation/timers/00-INDEX	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/timers/00-INDEX	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,8 @@ Makefile
 	- Build and link hpet_example
 NO_HZ.txt
 	- Summary of the different methods for the scheduler clock-interrupts management.
+timekeeping.txt
+	- Clock sources, clock events, sched_clock() and delay timer notes
 timers-howto.txt
 	- how to insert delays in the kernel the right (tm) way.
 timer_stats.txt
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/timers/timekeeping.txt linux-libre-3.17-rc7-gnu/Documentation/timers/timekeeping.txt
--- linux-libre-3.16-gnu/Documentation/timers/timekeeping.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/timers/timekeeping.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,179 @@
+Clock sources, Clock events, sched_clock() and delay timers
+-----------------------------------------------------------
+
+This document tries to briefly explain some basic kernel timekeeping
+abstractions. It partly pertains to the drivers usually found in
+drivers/clocksource in the kernel tree, but the code may be spread out
+across the kernel.
+
+If you grep through the kernel source you will find a number of architecture-
+specific implementations of clock sources, clockevents and several likewise
+architecture-specific overrides of the sched_clock() function and some
+delay timers.
+
+To provide timekeeping for your platform, the clock source provides
+the basic timeline, whereas clock events shoot interrupts on certain points
+on this timeline, providing facilities such as high-resolution timers.
+sched_clock() is used for scheduling and timestamping, and delay timers
+provide an accurate delay source using hardware counters.
+
+
+Clock sources
+-------------
+
+The purpose of the clock source is to provide a timeline for the system that
+tells you where you are in time. For example issuing the command 'date' on
+a Linux system will eventually read the clock source to determine exactly
+what time it is.
+
+Typically the clock source is a monotonic, atomic counter which will provide
+n bits which count from 0 to 2^(n-1) and then wraps around to 0 and start over.
+It will ideally NEVER stop ticking as long as the system is running. It
+may stop during system suspend.
+
+The clock source shall have as high resolution as possible, and the frequency
+shall be as stable and correct as possible as compared to a real-world wall
+clock. It should not move unpredictably back and forth in time or miss a few
+cycles here and there.
+
+It must be immune to the kind of effects that occur in hardware where e.g.
+the counter register is read in two phases on the bus lowest 16 bits first
+and the higher 16 bits in a second bus cycle with the counter bits
+potentially being updated in between leading to the risk of very strange
+values from the counter.
+
+When the wall-clock accuracy of the clock source isn't satisfactory, there
+are various quirks and layers in the timekeeping code for e.g. synchronizing
+the user-visible time to RTC clocks in the system or against networked time
+servers using NTP, but all they do basically is update an offset against
+the clock source, which provides the fundamental timeline for the system.
+These measures does not affect the clock source per se, they only adapt the
+system to the shortcomings of it.
+
+The clock source struct shall provide means to translate the provided counter
+into a nanosecond value as an unsigned long long (unsigned 64 bit) number.
+Since this operation may be invoked very often, doing this in a strict
+mathematical sense is not desirable: instead the number is taken as close as
+possible to a nanosecond value using only the arithmetic operations
+multiply and shift, so in clocksource_cyc2ns() you find:
+
+  ns ~= (clocksource * mult) >> shift
+
+You will find a number of helper functions in the clock source code intended
+to aid in providing these mult and shift values, such as
+clocksource_khz2mult(), clocksource_hz2mult() that help determine the
+mult factor from a fixed shift, and clocksource_register_hz() and
+clocksource_register_khz() which will help out assigning both shift and mult
+factors using the frequency of the clock source as the only input.
+
+For real simple clock sources accessed from a single I/O memory location
+there is nowadays even clocksource_mmio_init() which will take a memory
+location, bit width, a parameter telling whether the counter in the
+register counts up or down, and the timer clock rate, and then conjure all
+necessary parameters.
+
+Since a 32-bit counter at say 100 MHz will wrap around to zero after some 43
+seconds, the code handling the clock source will have to compensate for this.
+That is the reason why the clock source struct also contains a 'mask'
+member telling how many bits of the source are valid. This way the timekeeping
+code knows when the counter will wrap around and can insert the necessary
+compensation code on both sides of the wrap point so that the system timeline
+remains monotonic.
+
+
+Clock events
+------------
+
+Clock events are the conceptual reverse of clock sources: they take a
+desired time specification value and calculate the values to poke into
+hardware timer registers.
+
+Clock events are orthogonal to clock sources. The same hardware
+and register range may be used for the clock event, but it is essentially
+a different thing. The hardware driving clock events has to be able to
+fire interrupts, so as to trigger events on the system timeline. On an SMP
+system, it is ideal (and customary) to have one such event driving timer per
+CPU core, so that each core can trigger events independently of any other
+core.
+
+You will notice that the clock event device code is based on the same basic
+idea about translating counters to nanoseconds using mult and shift
+arithmetic, and you find the same family of helper functions again for
+assigning these values. The clock event driver does not need a 'mask'
+attribute however: the system will not try to plan events beyond the time
+horizon of the clock event.
+
+
+sched_clock()
+-------------
+
+In addition to the clock sources and clock events there is a special weak
+function in the kernel called sched_clock(). This function shall return the
+number of nanoseconds since the system was started. An architecture may or
+may not provide an implementation of sched_clock() on its own. If a local
+implementation is not provided, the system jiffy counter will be used as
+sched_clock().
+
+As the name suggests, sched_clock() is used for scheduling the system,
+determining the absolute timeslice for a certain process in the CFS scheduler
+for example. It is also used for printk timestamps when you have selected to
+include time information in printk for things like bootcharts.
+
+Compared to clock sources, sched_clock() has to be very fast: it is called
+much more often, especially by the scheduler. If you have to do trade-offs
+between accuracy compared to the clock source, you may sacrifice accuracy
+for speed in sched_clock(). It however requires some of the same basic
+characteristics as the clock source, i.e. it should be monotonic.
+
+The sched_clock() function may wrap only on unsigned long long boundaries,
+i.e. after 64 bits. Since this is a nanosecond value this will mean it wraps
+after circa 585 years. (For most practical systems this means "never".)
+
+If an architecture does not provide its own implementation of this function,
+it will fall back to using jiffies, making its maximum resolution 1/HZ of the
+jiffy frequency for the architecture. This will affect scheduling accuracy
+and will likely show up in system benchmarks.
+
+The clock driving sched_clock() may stop or reset to zero during system
+suspend/sleep. This does not matter to the function it serves of scheduling
+events on the system. However it may result in interesting timestamps in
+printk().
+
+The sched_clock() function should be callable in any context, IRQ- and
+NMI-safe and return a sane value in any context.
+
+Some architectures may have a limited set of time sources and lack a nice
+counter to derive a 64-bit nanosecond value, so for example on the ARM
+architecture, special helper functions have been created to provide a
+sched_clock() nanosecond base from a 16- or 32-bit counter. Sometimes the
+same counter that is also used as clock source is used for this purpose.
+
+On SMP systems, it is crucial for performance that sched_clock() can be called
+independently on each CPU without any synchronization performance hits.
+Some hardware (such as the x86 TSC) will cause the sched_clock() function to
+drift between the CPUs on the system. The kernel can work around this by
+enabling the CONFIG_HAVE_UNSTABLE_SCHED_CLOCK option. This is another aspect
+that makes sched_clock() different from the ordinary clock source.
+
+
+Delay timers (some architectures only)
+--------------------------------------
+
+On systems with variable CPU frequency, the various kernel delay() functions
+will sometimes behave strangely. Basically these delays usually use a hard
+loop to delay a certain number of jiffy fractions using a "lpj" (loops per
+jiffy) value, calibrated on boot.
+
+Let's hope that your system is running on maximum frequency when this value
+is calibrated: as an effect when the frequency is geared down to half the
+full frequency, any delay() will be twice as long. Usually this does not
+hurt, as you're commonly requesting that amount of delay *or more*. But
+basically the semantics are quite unpredictable on such systems.
+
+Enter timer-based delays. Using these, a timer read may be used instead of
+a hard-coded loop for providing the desired delay.
+
+This is done by declaring a struct delay_timer and assigning the appropriate
+function pointers and rate settings for this delay timer.
+
+This is available on some architectures like OpenRISC or ARM.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/trace/ftrace-design.txt linux-libre-3.17-rc7-gnu/Documentation/trace/ftrace-design.txt
--- linux-libre-3.16-gnu/Documentation/trace/ftrace-design.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/trace/ftrace-design.txt	2014-09-28 17:29:07.000000000 -0400
@@ -102,30 +102,6 @@ extern void mcount(void);
 EXPORT_SYMBOL(mcount);
 
 
-HAVE_FUNCTION_TRACE_MCOUNT_TEST
--------------------------------
-
-This is an optional optimization for the normal case when tracing is turned off
-in the system.  If you do not enable this Kconfig option, the common ftrace
-code will take care of doing the checking for you.
-
-To support this feature, you only need to check the function_trace_stop
-variable in the mcount function.  If it is non-zero, there is no tracing to be
-done at all, so you can return.
-
-This additional pseudo code would simply be:
-void mcount(void)
-{
-	/* save any bare state needed in order to do initial checking */
-
-+	if (function_trace_stop)
-+		return;
-
-	extern void (*ftrace_trace_function)(unsigned long, unsigned long);
-	if (ftrace_trace_function != ftrace_stub)
-...
-
-
 HAVE_FUNCTION_GRAPH_TRACER
 --------------------------
 
@@ -328,8 +304,6 @@ void mcount(void)
 
 void ftrace_caller(void)
 {
-	/* implement HAVE_FUNCTION_TRACE_MCOUNT_TEST if you desire */
-
 	/* save all state needed by the ABI (see paragraph above) */
 
 	unsigned long frompc = ...;
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/trace/ftrace.txt linux-libre-3.17-rc7-gnu/Documentation/trace/ftrace.txt
--- linux-libre-3.16-gnu/Documentation/trace/ftrace.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/trace/ftrace.txt	2014-09-28 17:29:07.000000000 -0400
@@ -1515,7 +1515,7 @@ Doing the same with chrt -r 5 and functi
   <idle>-0       3d.h4    1us+:      0:120:R   + [003]  2448: 94:R sleep
   <idle>-0       3d.h4    2us : ttwu_do_activate.constprop.87 <-try_to_wake_up
   <idle>-0       3d.h3    3us : check_preempt_curr <-ttwu_do_wakeup
-  <idle>-0       3d.h3    3us : resched_task <-check_preempt_curr
+  <idle>-0       3d.h3    3us : resched_curr <-check_preempt_curr
   <idle>-0       3dNh3    4us : task_woken_rt <-ttwu_do_wakeup
   <idle>-0       3dNh3    4us : _raw_spin_unlock <-try_to_wake_up
   <idle>-0       3dNh3    4us : sub_preempt_count <-_raw_spin_unlock
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl linux-libre-3.17-rc7-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
--- linux-libre-3.16-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,10 @@ use constant HIGH_KSWAPD_REWAKEUP		=> 21
 use constant HIGH_NR_SCANNED			=> 22;
 use constant HIGH_NR_TAKEN			=> 23;
 use constant HIGH_NR_RECLAIMED			=> 24;
+use constant HIGH_NR_FILE_SCANNED		=> 25;
+use constant HIGH_NR_ANON_SCANNED		=> 26;
+use constant HIGH_NR_FILE_RECLAIMED		=> 27;
+use constant HIGH_NR_ANON_RECLAIMED		=> 28;
 
 my %perprocesspid;
 my %perprocess;
@@ -56,14 +60,18 @@ my $opt_read_procstat;
 
 my $total_wakeup_kswapd;
 my ($total_direct_reclaim, $total_direct_nr_scanned);
+my ($total_direct_nr_file_scanned, $total_direct_nr_anon_scanned);
 my ($total_direct_latency, $total_kswapd_latency);
 my ($total_direct_nr_reclaimed);
+my ($total_direct_nr_file_reclaimed, $total_direct_nr_anon_reclaimed);
 my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async);
 my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async);
 my ($total_kswapd_nr_scanned, $total_kswapd_wake);
+my ($total_kswapd_nr_file_scanned, $total_kswapd_nr_anon_scanned);
 my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async);
 my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async);
 my ($total_kswapd_nr_reclaimed);
+my ($total_kswapd_nr_file_reclaimed, $total_kswapd_nr_anon_reclaimed);
 
 # Catch sigint and exit on request
 my $sigint_report = 0;
@@ -374,6 +382,7 @@ EVENT_PROCESS:
 			}
 			my $isolate_mode = $1;
 			my $nr_scanned = $4;
+			my $file = $6;
 
 			# To closer match vmstat scanning statistics, only count isolate_both
 			# and isolate_inactive as scanning. isolate_active is rotation
@@ -382,6 +391,11 @@ EVENT_PROCESS:
 			# isolate_both     == 3
 			if ($isolate_mode != 2) {
 				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+				if ($file == 1) {
+					$perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED} += $nr_scanned;
+				} else {
+					$perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED} += $nr_scanned;
+				}
 			}
 		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
 			$details = $6;
@@ -391,8 +405,19 @@ EVENT_PROCESS:
 				print "         $regex_lru_shrink_inactive/o\n";
 				next;
 			}
+
 			my $nr_reclaimed = $4;
+			my $flags = $6;
+			my $file = 0;
+			if ($flags =~ /RECLAIM_WB_FILE/) {
+				$file = 1;
+			}
 			$perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed;
+			if ($file) {
+				$perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED} += $nr_reclaimed;
+			} else {
+				$perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED} += $nr_reclaimed;
+			}
 		} elsif ($tracepoint eq "mm_vmscan_writepage") {
 			$details = $6;
 			if ($details !~ /$regex_writepage/o) {
@@ -493,7 +518,11 @@ sub dump_stats {
 		$total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
 		$total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
 		$total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+		$total_direct_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
+		$total_direct_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
 		$total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
+		$total_direct_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+		$total_direct_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
 		$total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -513,7 +542,11 @@ sub dump_stats {
 			$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN},
 			$stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD},
 			$stats{$process_pid}->{HIGH_NR_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
 			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
+			$stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
+			$stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC},
 			$this_reclaim_delay / 1000);
@@ -552,7 +585,11 @@ sub dump_stats {
 
 		$total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
 		$total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+		$total_kswapd_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
+		$total_kswapd_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
 		$total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
+		$total_kswapd_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+		$total_kswapd_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
 		$total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -563,7 +600,11 @@ sub dump_stats {
 			$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE},
 			$stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP},
 			$stats{$process_pid}->{HIGH_NR_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
 			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
+			$stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
+			$stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC});
 
@@ -594,7 +635,11 @@ sub dump_stats {
 	print "\nSummary\n";
 	print "Direct reclaims:     			$total_direct_reclaim\n";
 	print "Direct reclaim pages scanned:		$total_direct_nr_scanned\n";
+	print "Direct reclaim file pages scanned:	$total_direct_nr_file_scanned\n";
+	print "Direct reclaim anon pages scanned:	$total_direct_nr_anon_scanned\n";
 	print "Direct reclaim pages reclaimed:		$total_direct_nr_reclaimed\n";
+	print "Direct reclaim file pages reclaimed:	$total_direct_nr_file_reclaimed\n";
+	print "Direct reclaim anon pages reclaimed:	$total_direct_nr_anon_reclaimed\n";
 	print "Direct reclaim write file sync I/O:	$total_direct_writepage_file_sync\n";
 	print "Direct reclaim write anon sync I/O:	$total_direct_writepage_anon_sync\n";
 	print "Direct reclaim write file async I/O:	$total_direct_writepage_file_async\n";
@@ -604,7 +649,11 @@ sub dump_stats {
 	print "\n";
 	print "Kswapd wakeups:				$total_kswapd_wake\n";
 	print "Kswapd pages scanned:			$total_kswapd_nr_scanned\n";
+	print "Kswapd file pages scanned:		$total_kswapd_nr_file_scanned\n";
+	print "Kswapd anon pages scanned:		$total_kswapd_nr_anon_scanned\n";
 	print "Kswapd pages reclaimed:			$total_kswapd_nr_reclaimed\n";
+	print "Kswapd file pages reclaimed:		$total_kswapd_nr_file_reclaimed\n";
+	print "Kswapd anon pages reclaimed:		$total_kswapd_nr_anon_reclaimed\n";
 	print "Kswapd reclaim write file sync I/O:	$total_kswapd_writepage_file_sync\n";
 	print "Kswapd reclaim write anon sync I/O:	$total_kswapd_writepage_anon_sync\n";
 	print "Kswapd reclaim write file async I/O:	$total_kswapd_writepage_file_async\n";
@@ -629,7 +678,11 @@ sub aggregate_perprocesspid() {
 		$perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
 		$perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP};
 		$perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED};
+		$perprocess{$process}->{HIGH_NR_FILE_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED};
+		$perprocess{$process}->{HIGH_NR_ANON_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED};
 		$perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED};
+		$perprocess{$process}->{HIGH_NR_FILE_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+		$perprocess{$process}->{HIGH_NR_ANON_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/usb/hotplug.txt linux-libre-3.17-rc7-gnu/Documentation/usb/hotplug.txt
--- linux-libre-3.16-gnu/Documentation/usb/hotplug.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/usb/hotplug.txt	2014-09-28 17:29:07.000000000 -0400
@@ -105,13 +105,13 @@ macros such as these, and use driver_inf
 A short example, for a driver that supports several specific USB devices
 and their quirks, might have a MODULE_DEVICE_TABLE like this:
 
-    static const struct usb_device_id mydriver_id_table = {
+    static const struct usb_device_id mydriver_id_table[] = {
 	{ USB_DEVICE (0x9999, 0xaaaa), driver_info: QUIRK_X },
 	{ USB_DEVICE (0xbbbb, 0x8888), driver_info: QUIRK_Y|QUIRK_Z },
 	...
 	{ } /* end with an all-zeroes entry */
-    }
-    MODULE_DEVICE_TABLE (usb, mydriver_id_table);
+    };
+    MODULE_DEVICE_TABLE(usb, mydriver_id_table);
 
 Most USB device drivers should pass these tables to the USB subsystem as
 well as to the module management subsystem.  Not all, though: some driver
@@ -134,7 +134,7 @@ something like this:
 	if exposing any operations through usbdevfs:
 	    .ioctl		= my_ioctl,
 	*/
-    }
+    };
 
 When the USB subsystem knows about a driver's device ID table, it's used when
 choosing drivers to probe().  The thread doing new device processing checks
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/usb/power-management.txt linux-libre-3.17-rc7-gnu/Documentation/usb/power-management.txt
--- linux-libre-3.16-gnu/Documentation/usb/power-management.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/usb/power-management.txt	2014-09-28 17:29:07.000000000 -0400
@@ -2,9 +2,28 @@
 
 		 Alan Stern <stern@rowland.harvard.edu>
 
-			    October 28, 2010
+		       Last-updated: February 2014
 
 
+	Contents:
+	---------
+	* What is Power Management?
+	* What is Remote Wakeup?
+	* When is a USB device idle?
+	* Forms of dynamic PM
+	* The user interface for dynamic PM
+	* Changing the default idle-delay time
+	* Warnings
+	* The driver interface for Power Management
+	* The driver interface for autosuspend and autoresume
+	* Other parts of the driver interface
+	* Mutual exclusion
+	* Interaction between dynamic PM and system PM
+	* xHCI hardware link PM
+	* USB Port Power Control
+	* User Interface for Port Power Control
+	* Suggested Userspace Port Power Policy
+
 
 	What is Power Management?
 	-------------------------
@@ -516,3 +535,225 @@ relevant attribute files is usb2_hardwar
 		driver will enable hardware LPM	for the device. You
 		can write y/Y/1 or n/N/0 to the file to	enable/disable
 		USB2 hardware LPM manually. This is for	test purpose mainly.
+
+
+	USB Port Power Control
+	----------------------
+
+In addition to suspending endpoint devices and enabling hardware
+controlled link power management, the USB subsystem also has the
+capability to disable power to ports under some conditions.  Power is
+controlled through Set/ClearPortFeature(PORT_POWER) requests to a hub.
+In the case of a root or platform-internal hub the host controller
+driver translates PORT_POWER requests into platform firmware (ACPI)
+method calls to set the port power state. For more background see the
+Linux Plumbers Conference 2012 slides [1] and video [2]:
+
+Upon receiving a ClearPortFeature(PORT_POWER) request a USB port is
+logically off, and may trigger the actual loss of VBUS to the port [3].
+VBUS may be maintained in the case where a hub gangs multiple ports into
+a shared power well causing power to remain until all ports in the gang
+are turned off.  VBUS may also be maintained by hub ports configured for
+a charging application.  In any event a logically off port will lose
+connection with its device, not respond to hotplug events, and not
+respond to remote wakeup events*.
+
+WARNING: turning off a port may result in the inability to hot add a device.
+Please see "User Interface for Port Power Control" for details.
+
+As far as the effect on the device itself it is similar to what a device
+goes through during system suspend, i.e. the power session is lost.  Any
+USB device or driver that misbehaves with system suspend will be
+similarly affected by a port power cycle event.  For this reason the
+implementation shares the same device recovery path (and honors the same
+quirks) as the system resume path for the hub.
+
+[1]: http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
+[2]: http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
+[3]: USB 3.1 Section 10.12
+* wakeup note: if a device is configured to send wakeup events the port
+  power control implementation will block poweroff attempts on that
+  port.
+
+
+	User Interface for Port Power Control
+	-------------------------------------
+
+The port power control mechanism uses the PM runtime system.  Poweroff is
+requested by clearing the power/pm_qos_no_power_off flag of the port device
+(defaults to 1).  If the port is disconnected it will immediately receive a
+ClearPortFeature(PORT_POWER) request.  Otherwise, it will honor the pm runtime
+rules and require the attached child device and all descendants to be suspended.
+This mechanism is dependent on the hub advertising port power switching in its
+hub descriptor (wHubCharacteristics logical power switching mode field).
+
+Note, some interface devices/drivers do not support autosuspend.  Userspace may
+need to unbind the interface drivers before the usb_device will suspend.  An
+unbound interface device is suspended by default.  When unbinding, be careful
+to unbind interface drivers, not the driver of the parent usb device.  Also,
+leave hub interface drivers bound.  If the driver for the usb device (not
+interface) is unbound the kernel is no longer able to resume the device.  If a
+hub interface driver is unbound, control of its child ports is lost and all
+attached child-devices will disconnect.  A good rule of thumb is that if the
+'driver/module' link for a device points to /sys/module/usbcore then unbinding
+it will interfere with port power control.
+
+Example of the relevant files for port power control.  Note, in this example
+these files are relative to a usb hub device (prefix).
+
+     prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
+
+                      attached child device +
+                  hub port device +         |
+     hub interface device +       |         |
+                          v       v         v
+                  $prefix/3-1:1.0/3-1-port1/device
+
+     $prefix/3-1:1.0/3-1-port1/power/pm_qos_no_power_off
+     $prefix/3-1:1.0/3-1-port1/device/power/control
+     $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf0>/driver/unbind
+     $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf1>/driver/unbind
+     ...
+     $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intfN>/driver/unbind
+
+In addition to these files some ports may have a 'peer' link to a port on
+another hub.  The expectation is that all superspeed ports have a
+hi-speed peer.
+
+$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
+../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
+
+Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
+peer ports are simply the hi-speed and superspeed interface pins that
+are combined into a single usb3 connector.  Peer ports share the same
+ancestor XHCI device.
+
+While a superspeed port is powered off a device may downgrade its
+connection and attempt to connect to the hi-speed pins.  The
+implementation takes steps to prevent this:
+
+1/ Port suspend is sequenced to guarantee that hi-speed ports are powered-off
+   before their superspeed peer is permitted to power-off.  The implication is
+   that the setting pm_qos_no_power_off to zero on a superspeed port may not cause
+   the port to power-off until its highspeed peer has gone to its runtime suspend
+   state.  Userspace must take care to order the suspensions if it wants to
+   guarantee that a superspeed port will power-off.
+
+2/ Port resume is sequenced to force a superspeed port to power-on prior to its
+   highspeed peer.
+
+3/ Port resume always triggers an attached child device to resume.  After a
+   power session is lost the device may have been removed, or need reset.
+   Resuming the child device when the parent port regains power resolves those
+   states and clamps the maximum port power cycle frequency at the rate the child
+   device can suspend (autosuspend-delay) and resume (reset-resume latency).
+
+Sysfs files relevant for port power control:
+	<hubdev-portX>/power/pm_qos_no_power_off:
+		This writable flag controls the state of an idle port.
+		Once all children and descendants have suspended the
+		port may suspend/poweroff provided that
+		pm_qos_no_power_off is '0'.  If pm_qos_no_power_off is
+		'1' the port will remain active/powered regardless of
+		the stats of descendants.  Defaults to 1.
+
+	<hubdev-portX>/power/runtime_status:
+		This file reflects whether the port is 'active' (power is on)
+		or 'suspended' (logically off).  There is no indication to
+		userspace whether VBUS is still supplied.
+
+	<hubdev-portX>/connect_type:
+		An advisory read-only flag to userspace indicating the
+		location and connection type of the port.  It returns
+		one of four values 'hotplug', 'hardwired', 'not used',
+		and 'unknown'.  All values, besides unknown, are set by
+		platform firmware.
+
+		"hotplug" indicates an externally connectable/visible
+		port on the platform.  Typically userspace would choose
+		to keep such a port powered to handle new device
+		connection events.
+
+		"hardwired" refers to a port that is not visible but
+		connectable. Examples are internal ports for USB
+		bluetooth that can be disconnected via an external
+		switch or a port with a hardwired USB camera.  It is
+		expected to be safe to allow these ports to suspend
+		provided pm_qos_no_power_off is coordinated with any
+		switch that gates connections.  Userspace must arrange
+		for the device to be connected prior to the port
+		powering off, or to activate the port prior to enabling
+		connection via a switch.
+
+		"not used" refers to an internal port that is expected
+		to never have a device connected to it.  These may be
+		empty internal ports, or ports that are not physically
+		exposed on a platform.  Considered safe to be
+		powered-off at all times.
+
+		"unknown" means platform firmware does not provide
+		information for this port.  Most commonly refers to
+		external hub ports which should be considered 'hotplug'
+		for policy decisions.
+
+		NOTE1: since we are relying on the BIOS to get this ACPI
+		information correct, the USB port descriptions may be
+		missing or wrong.
+
+		NOTE2: Take care in clearing pm_qos_no_power_off.  Once
+		power is off this port will
+		not respond to new connect events.
+
+	Once a child device is attached additional constraints are
+	applied before the port is allowed to poweroff.
+
+	<child>/power/control:
+		Must be 'auto', and the port will not
+		power down until <child>/power/runtime_status
+		reflects the 'suspended' state.  Default
+		value is controlled by child device driver.
+
+	<child>/power/persist:
+		This defaults to '1' for most devices and indicates if
+		kernel can persist the device's configuration across a
+		power session loss (suspend / port-power event).  When
+		this value is '0' (quirky devices), port poweroff is
+		disabled.
+
+	<child>/driver/unbind:
+		Wakeup capable devices will block port poweroff.  At
+		this time the only mechanism to clear the usb-internal
+		wakeup-capability for an interface device is to unbind
+		its driver.
+
+Summary of poweroff pre-requisite settings relative to a port device:
+
+	echo 0 > power/pm_qos_no_power_off
+	echo 0 > peer/power/pm_qos_no_power_off # if it exists
+	echo auto > power/control # this is the default value
+	echo auto > <child>/power/control
+	echo 1 > <child>/power/persist # this is the default value
+
+	Suggested Userspace Port Power Policy
+	-------------------------------------
+
+As noted above userspace needs to be careful and deliberate about what
+ports are enabled for poweroff.
+
+The default configuration is that all ports start with
+power/pm_qos_no_power_off set to '1' causing ports to always remain
+active.
+
+Given confidence in the platform firmware's description of the ports
+(ACPI _PLD record for a port populates 'connect_type') userspace can
+clear pm_qos_no_power_off for all 'not used' ports.  The same can be
+done for 'hardwired' ports provided poweroff is coordinated with any
+connection switch for the port.
+
+A more aggressive userspace policy is to enable USB port power off for
+all ports (set <hubdev-portX>/power/pm_qos_no_power_off to '0') when
+some external factor indicates the user has stopped interacting with the
+system.  For example, a distro may want to enable power off all USB
+ports when the screen blanks, and re-power them when the screen becomes
+active.  Smart phones and tablets may want to power off USB ports when
+the user pushes the power button.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/vfio.txt linux-libre-3.17-rc7-gnu/Documentation/vfio.txt
--- linux-libre-3.16-gnu/Documentation/vfio.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/vfio.txt	2014-09-28 17:29:07.000000000 -0400
@@ -305,7 +305,15 @@ faster, the map/unmap handling has been
 an excellent performance which has limitations such as inability to do
 locked pages accounting in real time.
 
-So 3 additional ioctls have been added:
+4) According to sPAPR specification, A Partitionable Endpoint (PE) is an I/O
+subtree that can be treated as a unit for the purposes of partitioning and
+error recovery. A PE may be a single or multi-function IOA (IO Adapter), a
+function of a multi-function IOA, or multiple IOAs (possibly including switch
+and bridge structures above the multiple IOAs). PPC64 guests detect PCI errors
+and recover from them via EEH RTAS services, which works on the basis of
+additional ioctl commands.
+
+So 4 additional ioctls have been added:
 
 	VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start
 		of the DMA window on the PCI bus.
@@ -316,9 +324,12 @@ So 3 additional ioctls have been added:
 
 	VFIO_IOMMU_DISABLE - disables the container.
 
+	VFIO_EEH_PE_OP - provides an API for EEH setup, error detection and recovery.
 
 The code flow from the example above should be slightly changed:
 
+	struct vfio_eeh_pe_op pe_op = { .argsz = sizeof(pe_op), .flags = 0 };
+
 	.....
 	/* Add the group to the container */
 	ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);
@@ -342,9 +353,79 @@ The code flow from the example above sho
 	dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
 
 	/* Check here is .iova/.size are within DMA window from spapr_iommu_info */
-
 	ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
-	.....
+
+	/* Get a file descriptor for the device */
+	device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:06:0d.0");
+
+	....
+
+	/* Gratuitous device reset and go... */
+	ioctl(device, VFIO_DEVICE_RESET);
+
+	/* Make sure EEH is supported */
+	ioctl(container, VFIO_CHECK_EXTENSION, VFIO_EEH);
+
+	/* Enable the EEH functionality on the device */
+	pe_op.op = VFIO_EEH_PE_ENABLE;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/* You're suggested to create additional data struct to represent
+	 * PE, and put child devices belonging to same IOMMU group to the
+	 * PE instance for later reference.
+	 */
+
+	/* Check the PE's state and make sure it's in functional state */
+	pe_op.op = VFIO_EEH_PE_GET_STATE;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/* Save device state using pci_save_state().
+	 * EEH should be enabled on the specified device.
+	 */
+
+	....
+
+	/* When 0xFF's returned from reading PCI config space or IO BARs
+	 * of the PCI device. Check the PE's state to see if that has been
+	 * frozen.
+	 */
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/* Waiting for pending PCI transactions to be completed and don't
+	 * produce any more PCI traffic from/to the affected PE until
+	 * recovery is finished.
+	 */
+
+	/* Enable IO for the affected PE and collect logs. Usually, the
+	 * standard part of PCI config space, AER registers are dumped
+	 * as logs for further analysis.
+	 */
+	pe_op.op = VFIO_EEH_PE_UNFREEZE_IO;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/*
+	 * Issue PE reset: hot or fundamental reset. Usually, hot reset
+	 * is enough. However, the firmware of some PCI adapters would
+	 * require fundamental reset.
+	 */
+	pe_op.op = VFIO_EEH_PE_RESET_HOT;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+	pe_op.op = VFIO_EEH_PE_RESET_DEACTIVATE;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/* Configure the PCI bridges for the affected PE */
+	pe_op.op = VFIO_EEH_PE_CONFIGURE;
+	ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+	/* Restored state we saved at initialization time. pci_restore_state()
+	 * is good enough as an example.
+	 */
+
+	/* Hopefully, error is recovered successfully. Now, you can resume to
+	 * start PCI traffic to/from the affected PE.
+	 */
+
+	....
 
 -------------------------------------------------------------------------------
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/video4linux/CARDLIST.cx23885 linux-libre-3.17-rc7-gnu/Documentation/video4linux/CARDLIST.cx23885
--- linux-libre-3.16-gnu/Documentation/video4linux/CARDLIST.cx23885	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/video4linux/CARDLIST.cx23885	2014-09-28 17:29:07.000000000 -0400
@@ -41,3 +41,5 @@
  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]
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/video4linux/CARDLIST.em28xx linux-libre-3.17-rc7-gnu/Documentation/video4linux/CARDLIST.em28xx
--- linux-libre-3.16-gnu/Documentation/video4linux/CARDLIST.em28xx	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/video4linux/CARDLIST.em28xx	2014-09-28 17:29:07.000000000 -0400
@@ -77,7 +77,7 @@
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
  77 -> EM2874 Leadership ISDBT                  (em2874)
  78 -> PCTV nanoStick T2 290e                   (em28174)
- 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad,0ccd:10b6]
+ 79 -> Terratec Cinergy H5                      (em2884)        [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6]
  80 -> PCTV DVB-S2 Stick (460e)                 (em28174)
  81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
  82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/video4linux/v4l2-controls.txt linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-controls.txt
--- linux-libre-3.16-gnu/Documentation/video4linux/v4l2-controls.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-controls.txt	2014-09-28 17:29:07.000000000 -0400
@@ -77,9 +77,9 @@ Basic usage for V4L2 and sub-device driv
 
   Where foo->v4l2_dev is of type struct v4l2_device.
 
-  Finally, remove all control functions from your v4l2_ioctl_ops:
-  vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl,
-  vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
+  Finally, remove all control functions from your v4l2_ioctl_ops (if any):
+  vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl,
+  vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
   Those are now no longer needed.
 
 1.3.2) For sub-device drivers do this:
@@ -258,8 +258,8 @@ The new control value has already been v
 to actually update the hardware registers.
 
 You're done! And this is sufficient for most of the drivers we have. No need
-to do any validation of control values, or implement QUERYCTRL/QUERYMENU. And
-G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
+to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL
+and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
 
 
 ==============================================================================
@@ -288,30 +288,45 @@ of v4l2_device.
 Accessing Control Values
 ========================
 
-The v4l2_ctrl struct contains these two unions:
+The following union is used inside the control framework to access control
+values:
 
-	/* The current control value. */
-	union {
+union v4l2_ctrl_ptr {
+	s32 *p_s32;
+	s64 *p_s64;
+	char *p_char;
+	void *p;
+};
+
+The v4l2_ctrl struct contains these fields that can be used to access both
+current and new values:
+
+	s32 val;
+	struct {
 		s32 val;
-		s64 val64;
-		char *string;
 	} cur;
 
-	/* The new control value. */
-	union {
-		s32 val;
-		s64 val64;
-		char *string;
-	};
 
-Within the control ops you can freely use these. The val and val64 speak for
-themselves. The string pointers point to character buffers of length
+	union v4l2_ctrl_ptr p_new;
+	union v4l2_ctrl_ptr p_cur;
+
+If the control has a simple s32 type type, then:
+
+	&ctrl->val == ctrl->p_new.p_s32
+	&ctrl->cur.val == ctrl->p_cur.p_s32
+
+For all other types use ctrl->p_cur.p<something>. Basically the val
+and cur.val fields can be considered an alias since these are used so often.
+
+Within the control ops you can freely use these. The val and cur.val speak for
+themselves. The p_char pointers point to character buffers of length
 ctrl->maximum + 1, and are always 0-terminated.
 
-In most cases 'cur' contains the current cached control value. When you create
-a new control this value is made identical to the default value. After calling
-v4l2_ctrl_handler_setup() this value is passed to the hardware. It is generally
-a good idea to call this function.
+Unless the control is marked volatile the p_cur field points to the the
+current cached control value. When you create a new control this value is made
+identical to the default value. After calling v4l2_ctrl_handler_setup() this
+value is passed to the hardware. It is generally a good idea to call this
+function.
 
 Whenever a new value is set that new value is automatically cached. This means
 that most drivers do not need to implement the g_volatile_ctrl() op. The
@@ -362,8 +377,8 @@ will result in a deadlock since these he
 You can also take the handler lock yourself:
 
 	mutex_lock(&state->ctrl_handler.lock);
-	printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string);
-	printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val);
+	pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
+	pr_info("Integer value is '%s'\n", ctrl2->cur.val);
 	mutex_unlock(&state->ctrl_handler.lock);
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/video4linux/v4l2-framework.txt linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-framework.txt
--- linux-libre-3.16-gnu/Documentation/video4linux/v4l2-framework.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-framework.txt	2014-09-28 17:29:07.000000000 -0400
@@ -675,11 +675,6 @@ You should also set these fields:
   video_device is initialized you *do* know which parent PCI device to use and
   so you set dev_device to the correct PCI device.
 
-- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
-  handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
-  v4l2_fh. Eventually this flag will disappear once all drivers use the core
-  priority handling. But for now it has to be set explicitly.
-
 If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2
 in your v4l2_file_operations struct.
 
@@ -909,8 +904,7 @@ struct v4l2_fh
 
 struct v4l2_fh provides a way to easily keep file handle specific data
 that is used by the V4L2 framework. New drivers must use struct v4l2_fh
-since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY)
-if the video_device flag V4L2_FL_USE_FH_PRIO is also set.
+since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY).
 
 The users of v4l2_fh (in the V4L2 framework, not the driver) know
 whether a driver uses v4l2_fh as its file->private_data pointer by
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/video4linux/v4l2-pci-skeleton.c linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-pci-skeleton.c
--- linux-libre-3.16-gnu/Documentation/video4linux/v4l2-pci-skeleton.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/video4linux/v4l2-pci-skeleton.c	2014-09-28 17:29:07.000000000 -0400
@@ -883,11 +883,6 @@ static int skeleton_probe(struct pci_dev
 	vdev->v4l2_dev = &skel->v4l2_dev;
 	/* Supported SDTV standards, if any */
 	vdev->tvnorms = SKEL_TVNORMS;
-	/* If this bit is set, then the v4l2 core will provide the support
-	 * for the VIDIOC_G/S_PRIORITY ioctls. This flag will eventually
-	 * go away once all drivers have been converted to use struct v4l2_fh.
-	 */
-	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
 	video_set_drvdata(vdev, skel);
 
 	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/virtual/kvm/api.txt linux-libre-3.17-rc7-gnu/Documentation/virtual/kvm/api.txt
--- linux-libre-3.16-gnu/Documentation/virtual/kvm/api.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/virtual/kvm/api.txt	2014-09-28 17:29:07.000000000 -0400
@@ -148,9 +148,9 @@ of banks, as set via the KVM_X86_SETUP_M
 
 4.4 KVM_CHECK_EXTENSION
 
-Capability: basic
+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
 Architectures: all
-Type: system ioctl
+Type: system ioctl, vm ioctl
 Parameters: extension identifier (KVM_CAP_*)
 Returns: 0 if unsupported; 1 (or some other positive integer) if supported
 
@@ -160,6 +160,9 @@ receives an integer that describes the e
 Generally 0 means no and 1 means yes, but some extensions may report
 additional information in the integer return value.
 
+Based on their initialization different VMs may have different capabilities.
+It is thus encouraged to use the vm ioctl to query for capabilities (available
+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
 
 4.5 KVM_GET_VCPU_MMAP_SIZE
 
@@ -297,6 +300,15 @@ struct kvm_regs {
 	__u64 rip, rflags;
 };
 
+/* mips */
+struct kvm_regs {
+	/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+	__u64 gpr[32];
+	__u64 hi;
+	__u64 lo;
+	__u64 pc;
+};
+
 
 4.12 KVM_SET_REGS
 
@@ -378,7 +390,7 @@ struct kvm_translation {
 4.16 KVM_INTERRUPT
 
 Capability: basic
-Architectures: x86, ppc
+Architectures: x86, ppc, mips
 Type: vcpu ioctl
 Parameters: struct kvm_interrupt (in)
 Returns: 0 on success, -1 on error
@@ -423,6 +435,11 @@ c) KVM_INTERRUPT_SET_LEVEL
 Note that any value for 'irq' other than the ones stated above is invalid
 and incurs unexpected behavior.
 
+MIPS:
+
+Queues an external interrupt to be injected into the virtual CPU. A negative
+interrupt number dequeues the interrupt.
+
 
 4.17 KVM_DEBUG_GUEST
 
@@ -512,7 +529,7 @@ struct kvm_cpuid {
 4.21 KVM_SET_SIGNAL_MASK
 
 Capability: basic
-Architectures: x86
+Architectures: all
 Type: vcpu ioctl
 Parameters: struct kvm_signal_mask (in)
 Returns: 0 on success, -1 on error
@@ -974,7 +991,7 @@ for vm-wide capabilities.
 4.38 KVM_GET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
-Architectures: x86, ia64
+Architectures: x86, ia64, s390
 Type: vcpu ioctl
 Parameters: struct kvm_mp_state (out)
 Returns: 0 on success; -1 on error
@@ -988,24 +1005,32 @@ uniprocessor guests).
 
 Possible values are:
 
- - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running
+ - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86, ia64]
  - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
-                                 which has not yet received an INIT signal
+                                 which has not yet received an INIT signal [x86,
+                                 ia64]
  - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
-                                 now ready for a SIPI
+                                 now ready for a SIPI [x86, ia64]
  - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
-                                 is waiting for an interrupt
+                                 is waiting for an interrupt [x86, ia64]
  - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
-                                 accessible via KVM_GET_VCPU_EVENTS)
+                                 accessible via KVM_GET_VCPU_EVENTS) [x86, ia64]
+ - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390]
+ - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
+ - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
+                                 [s390]
+ - KVM_MP_STATE_LOAD:            the vcpu is in a special load/startup state
+                                 [s390]
 
-This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
-irqchip, the multiprocessing state must be maintained by userspace.
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
 
 
 4.39 KVM_SET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
-Architectures: x86, ia64
+Architectures: x86, ia64, s390
 Type: vcpu ioctl
 Parameters: struct kvm_mp_state (in)
 Returns: 0 on success; -1 on error
@@ -1013,8 +1038,9 @@ Returns: 0 on success; -1 on error
 Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
 arguments.
 
-This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
-irqchip, the multiprocessing state must be maintained by userspace.
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
 
 
 4.40 KVM_SET_IDENTITY_MAP_ADDR
@@ -1774,122 +1800,152 @@ and architecture specific registers. Eac
 and their own constants and width. To keep track of the implemented
 registers, find a list below:
 
-  Arch  |       Register        | Width (bits)
-        |                       |
-  PPC   | KVM_REG_PPC_HIOR      | 64
-  PPC   | KVM_REG_PPC_IAC1      | 64
-  PPC   | KVM_REG_PPC_IAC2      | 64
-  PPC   | KVM_REG_PPC_IAC3      | 64
-  PPC   | KVM_REG_PPC_IAC4      | 64
-  PPC   | KVM_REG_PPC_DAC1      | 64
-  PPC   | KVM_REG_PPC_DAC2      | 64
-  PPC   | KVM_REG_PPC_DABR      | 64
-  PPC   | KVM_REG_PPC_DSCR      | 64
-  PPC   | KVM_REG_PPC_PURR      | 64
-  PPC   | KVM_REG_PPC_SPURR     | 64
-  PPC   | KVM_REG_PPC_DAR       | 64
-  PPC   | KVM_REG_PPC_DSISR     | 32
-  PPC   | KVM_REG_PPC_AMR       | 64
-  PPC   | KVM_REG_PPC_UAMOR     | 64
-  PPC   | KVM_REG_PPC_MMCR0     | 64
-  PPC   | KVM_REG_PPC_MMCR1     | 64
-  PPC   | KVM_REG_PPC_MMCRA     | 64
-  PPC   | KVM_REG_PPC_MMCR2     | 64
-  PPC   | KVM_REG_PPC_MMCRS     | 64
-  PPC   | KVM_REG_PPC_SIAR      | 64
-  PPC   | KVM_REG_PPC_SDAR      | 64
-  PPC   | KVM_REG_PPC_SIER      | 64
-  PPC   | KVM_REG_PPC_PMC1      | 32
-  PPC   | KVM_REG_PPC_PMC2      | 32
-  PPC   | KVM_REG_PPC_PMC3      | 32
-  PPC   | KVM_REG_PPC_PMC4      | 32
-  PPC   | KVM_REG_PPC_PMC5      | 32
-  PPC   | KVM_REG_PPC_PMC6      | 32
-  PPC   | KVM_REG_PPC_PMC7      | 32
-  PPC   | KVM_REG_PPC_PMC8      | 32
-  PPC   | KVM_REG_PPC_FPR0      | 64
+  Arch  |           Register            | Width (bits)
+        |                               |
+  PPC   | KVM_REG_PPC_HIOR              | 64
+  PPC   | KVM_REG_PPC_IAC1              | 64
+  PPC   | KVM_REG_PPC_IAC2              | 64
+  PPC   | KVM_REG_PPC_IAC3              | 64
+  PPC   | KVM_REG_PPC_IAC4              | 64
+  PPC   | KVM_REG_PPC_DAC1              | 64
+  PPC   | KVM_REG_PPC_DAC2              | 64
+  PPC   | KVM_REG_PPC_DABR              | 64
+  PPC   | KVM_REG_PPC_DSCR              | 64
+  PPC   | KVM_REG_PPC_PURR              | 64
+  PPC   | KVM_REG_PPC_SPURR             | 64
+  PPC   | KVM_REG_PPC_DAR               | 64
+  PPC   | KVM_REG_PPC_DSISR             | 32
+  PPC   | KVM_REG_PPC_AMR               | 64
+  PPC   | KVM_REG_PPC_UAMOR             | 64
+  PPC   | KVM_REG_PPC_MMCR0             | 64
+  PPC   | KVM_REG_PPC_MMCR1             | 64
+  PPC   | KVM_REG_PPC_MMCRA             | 64
+  PPC   | KVM_REG_PPC_MMCR2             | 64
+  PPC   | KVM_REG_PPC_MMCRS             | 64
+  PPC   | KVM_REG_PPC_SIAR              | 64
+  PPC   | KVM_REG_PPC_SDAR              | 64
+  PPC   | KVM_REG_PPC_SIER              | 64
+  PPC   | KVM_REG_PPC_PMC1              | 32
+  PPC   | KVM_REG_PPC_PMC2              | 32
+  PPC   | KVM_REG_PPC_PMC3              | 32
+  PPC   | KVM_REG_PPC_PMC4              | 32
+  PPC   | KVM_REG_PPC_PMC5              | 32
+  PPC   | KVM_REG_PPC_PMC6              | 32
+  PPC   | KVM_REG_PPC_PMC7              | 32
+  PPC   | KVM_REG_PPC_PMC8              | 32
+  PPC   | KVM_REG_PPC_FPR0              | 64
           ...
-  PPC   | KVM_REG_PPC_FPR31     | 64
-  PPC   | KVM_REG_PPC_VR0       | 128
+  PPC   | KVM_REG_PPC_FPR31             | 64
+  PPC   | KVM_REG_PPC_VR0               | 128
           ...
-  PPC   | KVM_REG_PPC_VR31      | 128
-  PPC   | KVM_REG_PPC_VSR0      | 128
+  PPC   | KVM_REG_PPC_VR31              | 128
+  PPC   | KVM_REG_PPC_VSR0              | 128
           ...
-  PPC   | KVM_REG_PPC_VSR31     | 128
-  PPC   | KVM_REG_PPC_FPSCR     | 64
-  PPC   | KVM_REG_PPC_VSCR      | 32
-  PPC   | KVM_REG_PPC_VPA_ADDR  | 64
-  PPC   | KVM_REG_PPC_VPA_SLB   | 128
-  PPC   | KVM_REG_PPC_VPA_DTL   | 128
-  PPC   | KVM_REG_PPC_EPCR	| 32
-  PPC   | KVM_REG_PPC_EPR	| 32
-  PPC   | KVM_REG_PPC_TCR	| 32
-  PPC   | KVM_REG_PPC_TSR	| 32
-  PPC   | KVM_REG_PPC_OR_TSR	| 32
-  PPC   | KVM_REG_PPC_CLEAR_TSR	| 32
-  PPC   | KVM_REG_PPC_MAS0	| 32
-  PPC   | KVM_REG_PPC_MAS1	| 32
-  PPC   | KVM_REG_PPC_MAS2	| 64
-  PPC   | KVM_REG_PPC_MAS7_3	| 64
-  PPC   | KVM_REG_PPC_MAS4	| 32
-  PPC   | KVM_REG_PPC_MAS6	| 32
-  PPC   | KVM_REG_PPC_MMUCFG	| 32
-  PPC   | KVM_REG_PPC_TLB0CFG	| 32
-  PPC   | KVM_REG_PPC_TLB1CFG	| 32
-  PPC   | KVM_REG_PPC_TLB2CFG	| 32
-  PPC   | KVM_REG_PPC_TLB3CFG	| 32
-  PPC   | KVM_REG_PPC_TLB0PS	| 32
-  PPC   | KVM_REG_PPC_TLB1PS	| 32
-  PPC   | KVM_REG_PPC_TLB2PS	| 32
-  PPC   | KVM_REG_PPC_TLB3PS	| 32
-  PPC   | KVM_REG_PPC_EPTCFG	| 32
-  PPC   | KVM_REG_PPC_ICP_STATE | 64
-  PPC   | KVM_REG_PPC_TB_OFFSET	| 64
-  PPC   | KVM_REG_PPC_SPMC1	| 32
-  PPC   | KVM_REG_PPC_SPMC2	| 32
-  PPC   | KVM_REG_PPC_IAMR	| 64
-  PPC   | KVM_REG_PPC_TFHAR	| 64
-  PPC   | KVM_REG_PPC_TFIAR	| 64
-  PPC   | KVM_REG_PPC_TEXASR	| 64
-  PPC   | KVM_REG_PPC_FSCR	| 64
-  PPC   | KVM_REG_PPC_PSPB	| 32
-  PPC   | KVM_REG_PPC_EBBHR	| 64
-  PPC   | KVM_REG_PPC_EBBRR	| 64
-  PPC   | KVM_REG_PPC_BESCR	| 64
-  PPC   | KVM_REG_PPC_TAR	| 64
-  PPC   | KVM_REG_PPC_DPDES	| 64
-  PPC   | KVM_REG_PPC_DAWR	| 64
-  PPC   | KVM_REG_PPC_DAWRX	| 64
-  PPC   | KVM_REG_PPC_CIABR	| 64
-  PPC   | KVM_REG_PPC_IC	| 64
-  PPC   | KVM_REG_PPC_VTB	| 64
-  PPC   | KVM_REG_PPC_CSIGR	| 64
-  PPC   | KVM_REG_PPC_TACR	| 64
-  PPC   | KVM_REG_PPC_TCSCR	| 64
-  PPC   | KVM_REG_PPC_PID	| 64
-  PPC   | KVM_REG_PPC_ACOP	| 64
-  PPC   | KVM_REG_PPC_VRSAVE	| 32
-  PPC   | KVM_REG_PPC_LPCR	| 64
-  PPC   | KVM_REG_PPC_PPR	| 64
-  PPC   | KVM_REG_PPC_ARCH_COMPAT 32
-  PPC   | KVM_REG_PPC_DABRX     | 32
-  PPC   | KVM_REG_PPC_WORT      | 64
-  PPC   | KVM_REG_PPC_TM_GPR0	| 64
+  PPC   | KVM_REG_PPC_VSR31             | 128
+  PPC   | KVM_REG_PPC_FPSCR             | 64
+  PPC   | KVM_REG_PPC_VSCR              | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR          | 64
+  PPC   | KVM_REG_PPC_VPA_SLB           | 128
+  PPC   | KVM_REG_PPC_VPA_DTL           | 128
+  PPC   | KVM_REG_PPC_EPCR              | 32
+  PPC   | KVM_REG_PPC_EPR               | 32
+  PPC   | KVM_REG_PPC_TCR               | 32
+  PPC   | KVM_REG_PPC_TSR               | 32
+  PPC   | KVM_REG_PPC_OR_TSR            | 32
+  PPC   | KVM_REG_PPC_CLEAR_TSR         | 32
+  PPC   | KVM_REG_PPC_MAS0              | 32
+  PPC   | KVM_REG_PPC_MAS1              | 32
+  PPC   | KVM_REG_PPC_MAS2              | 64
+  PPC   | KVM_REG_PPC_MAS7_3            | 64
+  PPC   | KVM_REG_PPC_MAS4              | 32
+  PPC   | KVM_REG_PPC_MAS6              | 32
+  PPC   | KVM_REG_PPC_MMUCFG            | 32
+  PPC   | KVM_REG_PPC_TLB0CFG           | 32
+  PPC   | KVM_REG_PPC_TLB1CFG           | 32
+  PPC   | KVM_REG_PPC_TLB2CFG           | 32
+  PPC   | KVM_REG_PPC_TLB3CFG           | 32
+  PPC   | KVM_REG_PPC_TLB0PS            | 32
+  PPC   | KVM_REG_PPC_TLB1PS            | 32
+  PPC   | KVM_REG_PPC_TLB2PS            | 32
+  PPC   | KVM_REG_PPC_TLB3PS            | 32
+  PPC   | KVM_REG_PPC_EPTCFG            | 32
+  PPC   | KVM_REG_PPC_ICP_STATE         | 64
+  PPC   | KVM_REG_PPC_TB_OFFSET         | 64
+  PPC   | KVM_REG_PPC_SPMC1             | 32
+  PPC   | KVM_REG_PPC_SPMC2             | 32
+  PPC   | KVM_REG_PPC_IAMR              | 64
+  PPC   | KVM_REG_PPC_TFHAR             | 64
+  PPC   | KVM_REG_PPC_TFIAR             | 64
+  PPC   | KVM_REG_PPC_TEXASR            | 64
+  PPC   | KVM_REG_PPC_FSCR              | 64
+  PPC   | KVM_REG_PPC_PSPB              | 32
+  PPC   | KVM_REG_PPC_EBBHR             | 64
+  PPC   | KVM_REG_PPC_EBBRR             | 64
+  PPC   | KVM_REG_PPC_BESCR             | 64
+  PPC   | KVM_REG_PPC_TAR               | 64
+  PPC   | KVM_REG_PPC_DPDES             | 64
+  PPC   | KVM_REG_PPC_DAWR              | 64
+  PPC   | KVM_REG_PPC_DAWRX             | 64
+  PPC   | KVM_REG_PPC_CIABR             | 64
+  PPC   | KVM_REG_PPC_IC                | 64
+  PPC   | KVM_REG_PPC_VTB               | 64
+  PPC   | KVM_REG_PPC_CSIGR             | 64
+  PPC   | KVM_REG_PPC_TACR              | 64
+  PPC   | KVM_REG_PPC_TCSCR             | 64
+  PPC   | KVM_REG_PPC_PID               | 64
+  PPC   | KVM_REG_PPC_ACOP              | 64
+  PPC   | KVM_REG_PPC_VRSAVE            | 32
+  PPC   | KVM_REG_PPC_LPCR              | 32
+  PPC   | KVM_REG_PPC_LPCR_64           | 64
+  PPC   | KVM_REG_PPC_PPR               | 64
+  PPC   | KVM_REG_PPC_ARCH_COMPAT       | 32
+  PPC   | KVM_REG_PPC_DABRX             | 32
+  PPC   | KVM_REG_PPC_WORT              | 64
+  PPC   | KVM_REG_PPC_TM_GPR0           | 64
           ...
-  PPC   | KVM_REG_PPC_TM_GPR31	| 64
-  PPC   | KVM_REG_PPC_TM_VSR0	| 128
+  PPC   | KVM_REG_PPC_TM_GPR31          | 64
+  PPC   | KVM_REG_PPC_TM_VSR0           | 128
           ...
-  PPC   | KVM_REG_PPC_TM_VSR63	| 128
-  PPC   | KVM_REG_PPC_TM_CR	| 64
-  PPC   | KVM_REG_PPC_TM_LR	| 64
-  PPC   | KVM_REG_PPC_TM_CTR	| 64
-  PPC   | KVM_REG_PPC_TM_FPSCR	| 64
-  PPC   | KVM_REG_PPC_TM_AMR	| 64
-  PPC   | KVM_REG_PPC_TM_PPR	| 64
-  PPC   | KVM_REG_PPC_TM_VRSAVE	| 64
-  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_VSR63          | 128
+  PPC   | KVM_REG_PPC_TM_CR             | 64
+  PPC   | KVM_REG_PPC_TM_LR             | 64
+  PPC   | KVM_REG_PPC_TM_CTR            | 64
+  PPC   | KVM_REG_PPC_TM_FPSCR          | 64
+  PPC   | KVM_REG_PPC_TM_AMR            | 64
+  PPC   | KVM_REG_PPC_TM_PPR            | 64
+  PPC   | KVM_REG_PPC_TM_VRSAVE         | 64
+  PPC   | KVM_REG_PPC_TM_VSCR           | 32
+  PPC   | KVM_REG_PPC_TM_DSCR           | 64
+  PPC   | KVM_REG_PPC_TM_TAR            | 64
+        |                               |
+  MIPS  | KVM_REG_MIPS_R0               | 64
+          ...
+  MIPS  | KVM_REG_MIPS_R31              | 64
+  MIPS  | KVM_REG_MIPS_HI               | 64
+  MIPS  | KVM_REG_MIPS_LO               | 64
+  MIPS  | KVM_REG_MIPS_PC               | 64
+  MIPS  | KVM_REG_MIPS_CP0_INDEX        | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONTEXT      | 64
+  MIPS  | KVM_REG_MIPS_CP0_USERLOCAL    | 64
+  MIPS  | KVM_REG_MIPS_CP0_PAGEMASK     | 32
+  MIPS  | KVM_REG_MIPS_CP0_WIRED        | 32
+  MIPS  | KVM_REG_MIPS_CP0_HWRENA       | 32
+  MIPS  | KVM_REG_MIPS_CP0_BADVADDR     | 64
+  MIPS  | KVM_REG_MIPS_CP0_COUNT        | 32
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYHI      | 64
+  MIPS  | KVM_REG_MIPS_CP0_COMPARE      | 32
+  MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
+  MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
+  MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
+  MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
+  MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
+  MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
 
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 is the register group type, or coprocessor number:
@@ -1928,6 +1984,22 @@ arm64 CCSIDR registers are demultiplexed
 arm64 system registers have the following id bit patterns:
   0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
 
+
+MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
+the register group type:
+
+MIPS core registers (see above) have the following id bit patterns:
+  0x7030 0000 0000 <reg:16>
+
+MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
+patterns depending on whether they're 32-bit or 64-bit registers:
+  0x7020 0000 0001 00 <reg:5> <sel:3>   (32-bit)
+  0x7030 0000 0001 00 <reg:5> <sel:3>   (64-bit)
+
+MIPS KVM control registers (see above) have the following id bit patterns:
+  0x7030 0000 0002 <reg:16>
+
+
 4.69 KVM_GET_ONE_REG
 
 Capability: KVM_CAP_ONE_REG
@@ -2415,7 +2487,7 @@ in VCPU matching underlying host.
 4.84 KVM_GET_REG_LIST
 
 Capability: basic
-Architectures: arm, arm64
+Architectures: arm, arm64, mips
 Type: vcpu ioctl
 Parameters: struct kvm_reg_list (in/out)
 Returns: 0 on success; -1 on error
@@ -2609,8 +2681,8 @@ The 'data' member contains, in its first
 appear if the VCPU performed a load or store of the appropriate width directly
 to the byte array.
 
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR,
-      KVM_EXIT_PAPR and KVM_EXIT_EPR the corresponding
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
+      KVM_EXIT_EPR the corresponding
 operations are complete (and guest state is consistent) only after userspace
 has re-entered the kernel with KVM_RUN.  The kernel side will first finish
 incomplete operations and then check for pending signals.  Userspace
@@ -2681,7 +2753,7 @@ Principles of Operation Book in the Chap
 			__u8  is_write;
 		} dcr;
 
-powerpc specific.
+Deprecated - was used for 440 KVM.
 
 		/* KVM_EXIT_OSI */
 		struct {
@@ -2863,18 +2935,21 @@ The fields in each entry are defined as
          this function/index combination
 
 
-6. Capabilities that can be enabled
------------------------------------
+6. Capabilities that can be enabled on vCPUs
+--------------------------------------------
 
-There are certain capabilities that change the behavior of the virtual CPU when
-enabled. To enable them, please see section 4.37. Below you can find a list of
-capabilities and what their effect on the vCPU is when enabling them.
+There are certain capabilities that change the behavior of the virtual CPU or
+the virtual machine when enabled. To enable them, please see section 4.37.
+Below you can find a list of capabilities and what their effect on the vCPU or
+the virtual machine is when enabling them.
 
 The following information is provided along with the description:
 
   Architectures: which instruction set architectures provide this ioctl.
       x86 includes both i386 and x86_64.
 
+  Target: whether this is a per-vcpu or per-vm capability.
+
   Parameters: what parameters are accepted by the capability.
 
   Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
@@ -2884,6 +2959,7 @@ The following information is provided al
 6.1 KVM_CAP_PPC_OSI
 
 Architectures: ppc
+Target: vcpu
 Parameters: none
 Returns: 0 on success; -1 on error
 
@@ -2898,6 +2974,7 @@ When this capability is enabled, KVM_EXI
 6.2 KVM_CAP_PPC_PAPR
 
 Architectures: ppc
+Target: vcpu
 Parameters: none
 Returns: 0 on success; -1 on error
 
@@ -2917,6 +2994,7 @@ When this capability is enabled, KVM_EXI
 6.3 KVM_CAP_SW_TLB
 
 Architectures: ppc
+Target: vcpu
 Parameters: args[0] is the address of a struct kvm_config_tlb
 Returns: 0 on success; -1 on error
 
@@ -2959,6 +3037,7 @@ For mmu types KVM_MMU_FSL_BOOKE_NOHV and
 6.4 KVM_CAP_S390_CSS_SUPPORT
 
 Architectures: s390
+Target: vcpu
 Parameters: none
 Returns: 0 on success; -1 on error
 
@@ -2970,9 +3049,13 @@ handled in-kernel, while the other I/O i
 When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
 SUBCHANNEL intercepts.
 
+Note that even though this capability is enabled per-vcpu, the complete
+virtual machine is affected.
+
 6.5 KVM_CAP_PPC_EPR
 
 Architectures: ppc
+Target: vcpu
 Parameters: args[0] defines whether the proxy facility is active
 Returns: 0 on success; -1 on error
 
@@ -2998,7 +3081,57 @@ This capability connects the vcpu to an
 6.7 KVM_CAP_IRQ_XICS
 
 Architectures: ppc
+Target: vcpu
 Parameters: args[0] is the XICS device fd
             args[1] is the XICS CPU number (server ID) for this vcpu
 
 This capability connects the vcpu to an in-kernel XICS device.
+
+6.8 KVM_CAP_S390_IRQCHIP
+
+Architectures: s390
+Target: vm
+Parameters: none
+
+This capability enables the in-kernel irqchip for s390. Please refer to
+"4.24 KVM_CREATE_IRQCHIP" for details.
+
+7. Capabilities that can be enabled on VMs
+------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual
+machine when enabled. To enable them, please see section 4.37. Below
+you can find a list of capabilities and what their effect on the VM
+is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+7.1 KVM_CAP_PPC_ENABLE_HCALL
+
+Architectures: ppc
+Parameters: args[0] is the sPAPR hcall number
+	    args[1] is 0 to disable, 1 to enable in-kernel handling
+
+This capability controls whether individual sPAPR hypercalls (hcalls)
+get handled by the kernel or not.  Enabling or disabling in-kernel
+handling of an hcall is effective across the VM.  On creation, an
+initial set of hcalls are enabled for in-kernel handling, which
+consists of those hcalls for which in-kernel handlers were implemented
+before this capability was implemented.  If disabled, the kernel will
+not to attempt to handle the hcall, but will always exit to userspace
+to handle it.  Note that it may not make sense to enable some and
+disable others of a group of related hcalls, but KVM does not prevent
+userspace from doing that.
+
+If the hcall number specified is not one that has an in-kernel
+implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
+error.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/w1/slaves/w1_ds2406 linux-libre-3.17-rc7-gnu/Documentation/w1/slaves/w1_ds2406
--- linux-libre-3.16-gnu/Documentation/w1/slaves/w1_ds2406	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/w1/slaves/w1_ds2406	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,25 @@
+w1_ds2406 kernel driver
+=======================
+
+Supported chips:
+  * Maxim DS2406 (and other family 0x12) addressable switches
+
+Author: Scott Alfter <scott@alfter.us>
+
+Description
+-----------
+
+The w1_ds2406 driver allows connected devices to be switched on and off. 
+These chips also provide 128 bytes of OTP EPROM, but reading/writing it is
+not supported.  In TSOC-6 form, the DS2406 provides two switch outputs and
+can be provided with power on a dedicated input.  In TO-92 form, it provides
+one output and uses parasitic power only.
+
+The driver provides two sysfs files.  state is readable; it gives the
+current state of each switch, with PIO A in bit 0 and PIO B in bit 1.  The
+driver ORs this state with 0x30, so shell scripts get an ASCII 0/1/2/3 to
+work with.  output is writable; bits 0 and 1 control PIO A and B,
+respectively.  Bits 2-7 are ignored, so it's safe to write ASCII data.
+
+CRCs are checked on read and write.  Failed checks cause an I/O error to be
+returned.  On a failed write, the switch status is not changed.
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/watchdog/watchdog-api.txt linux-libre-3.17-rc7-gnu/Documentation/watchdog/watchdog-api.txt
--- linux-libre-3.16-gnu/Documentation/watchdog/watchdog-api.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/watchdog/watchdog-api.txt	2014-09-28 17:29:07.000000000 -0400
@@ -118,7 +118,7 @@ resets.
 Note that the pretimeout is the number of seconds before the time
 when the timeout will go off.  It is not the number of seconds until
 the pretimeout.  So, for instance, if you set the timeout to 60 seconds
-and the pretimeout to 10 seconds, the pretimout will go of in 50
+and the pretimeout to 10 seconds, the pretimeout will go off in 50
 seconds.  Setting a pretimeout to zero disables it.
 
 There is also a get function for getting the pretimeout:
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/x86/tlb.txt linux-libre-3.17-rc7-gnu/Documentation/x86/tlb.txt
--- linux-libre-3.16-gnu/Documentation/x86/tlb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/Documentation/x86/tlb.txt	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,75 @@
+When the kernel unmaps or modified the attributes of a range of
+memory, it has two choices:
+ 1. Flush the entire TLB with a two-instruction sequence.  This is
+    a quick operation, but it causes collateral damage: TLB entries
+    from areas other than the one we are trying to flush will be
+    destroyed and must be refilled later, at some cost.
+ 2. Use the invlpg instruction to invalidate a single page at a
+    time.  This could potentialy cost many more instructions, but
+    it is a much more precise operation, causing no collateral
+    damage to other TLB entries.
+
+Which method to do depends on a few things:
+ 1. The size of the flush being performed.  A flush of the entire
+    address space is obviously better performed by flushing the
+    entire TLB than doing 2^48/PAGE_SIZE individual flushes.
+ 2. The contents of the TLB.  If the TLB is empty, then there will
+    be no collateral damage caused by doing the global flush, and
+    all of the individual flush will have ended up being wasted
+    work.
+ 3. The size of the TLB.  The larger the TLB, the more collateral
+    damage we do with a full flush.  So, the larger the TLB, the
+    more attrative an individual flush looks.  Data and
+    instructions have separate TLBs, as do different page sizes.
+ 4. The microarchitecture.  The TLB has become a multi-level
+    cache on modern CPUs, and the global flushes have become more
+    expensive relative to single-page flushes.
+
+There is obviously no way the kernel can know all these things,
+especially the contents of the TLB during a given flush.  The
+sizes of the flush will vary greatly depending on the workload as
+well.  There is essentially no "right" point to choose.
+
+You may be doing too many individual invalidations if you see the
+invlpg instruction (or instructions _near_ it) show up high in
+profiles.  If you believe that individual invalidations being
+called too often, you can lower the tunable:
+
+	/sys/kernel/debug/x86/tlb_single_page_flush_ceiling
+
+This will cause us to do the global flush for more cases.
+Lowering it to 0 will disable the use of the individual flushes.
+Setting it to 1 is a very conservative setting and it should
+never need to be 0 under normal circumstances.
+
+Despite the fact that a single individual flush on x86 is
+guaranteed to flush a full 2MB [1], hugetlbfs always uses the full
+flushes.  THP is treated exactly the same as normal memory.
+
+You might see invlpg inside of flush_tlb_mm_range() show up in
+profiles, or you can use the trace_tlb_flush() tracepoints. to
+determine how long the flush operations are taking.
+
+Essentially, you are balancing the cycles you spend doing invlpg
+with the cycles that you spend refilling the TLB later.
+
+You can measure how expensive TLB refills are by using
+performance counters and 'perf stat', like this:
+
+perf stat -e
+	cpu/event=0x8,umask=0x84,name=dtlb_load_misses_walk_duration/,
+	cpu/event=0x8,umask=0x82,name=dtlb_load_misses_walk_completed/,
+	cpu/event=0x49,umask=0x4,name=dtlb_store_misses_walk_duration/,
+	cpu/event=0x49,umask=0x2,name=dtlb_store_misses_walk_completed/,
+	cpu/event=0x85,umask=0x4,name=itlb_misses_walk_duration/,
+	cpu/event=0x85,umask=0x2,name=itlb_misses_walk_completed/
+
+That works on an IvyBridge-era CPU (i5-3320M).  Different CPUs
+may have differently-named counters, but they should at least
+be there in some form.  You can use pmu-tools 'ocperf list'
+(https://github.com/andikleen/pmu-tools) to find the right
+counters for a given CPU.
+
+1. A footnote in Intel's SDM "4.10.4.2 Recommended Invalidation"
+   says: "One execution of INVLPG is sufficient even for a page
+   with size greater than 4 KBytes."
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/zh_CN/SubmittingDrivers linux-libre-3.17-rc7-gnu/Documentation/zh_CN/SubmittingDrivers
--- linux-libre-3.16-gnu/Documentation/zh_CN/SubmittingDrivers	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/zh_CN/SubmittingDrivers	2014-09-28 17:29:07.000000000 -0400
@@ -150,10 +150,6 @@ LWN.net:
 	å°†æ—§ç‰ˆå†…æ ¸çš„é©±åŠ¨ç¨‹åº�ç§»æ¤�åˆ° 2.6 ç‰ˆï¼š
 		http://lwn.net/Articles/driver-porting/
 
-KernelTrapï¼š
-	Linux å†…æ ¸çš„æœ€æ–°åŠ¨æ€�ä»¥å�Šå¼€å�‘è€…è®¿è°ˆ
-	http://kerneltrap.org/
-
 å†…æ ¸æ–°æ‰‹(KernelNewbies):
 	ä¸ºæ–°çš„å†…æ ¸å¼€å�‘è€…æ��ä¾›æ–‡æ¡£å’Œå¸®åŠ©
 	http://kernelnewbies.org/
diff -druNp --no-dereference linux-libre-3.16-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt linux-libre-3.17-rc7-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt
--- linux-libre-3.16-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt	2014-09-28 17:29:07.000000000 -0400
@@ -580,11 +580,6 @@ ä½ åº”è¯¥è®¾ç½®è¿™äº›åŸŸï¼š
   v4l2_device æ— æ³•ä¸Žç‰¹å®šçš„ PCI è®¾å¤‡å…³è�”ï¼Œæ‰€æœ‰æ²¡æœ‰è®¾ç½®çˆ¶è®¾å¤‡ã€‚ä½†å½“
   video_device é…�ç½®å�Žï¼Œå°±çŸ¥é�“ä½¿ç”¨å“ªä¸ªçˆ¶ PCI è®¾å¤‡äº†ã€‚
 
-- flagsï¼šå�¯é€‰ã€‚å¦‚æžœä½ è¦�è®©æ¡†æž¶å¤„ç�†è®¾ç½® VIDIOC_G/S_PRIORITY ioctlsï¼Œ
-  è¯·è®¾ç½® V4L2_FL_USE_FH_PRIOã€‚è¿™è¦�æ±‚ä½ ä½¿ç”¨ v4l2_fh ç»“æž„ä½“ã€‚
-  ä¸€æ—¦æ‰€æœ‰é©±åŠ¨ä½¿ç”¨äº†æ ¸å¿ƒçš„ä¼˜å…ˆçº§å¤„ç�†ï¼Œæœ€ç»ˆè¿™ä¸ªæ ‡å¿—å°†æ¶ˆå¤±ã€‚ä½†çŽ°åœ¨å®ƒ
-  å¿…é¡»è¢«æ˜¾å¼�è®¾ç½®ã€‚
-
 å¦‚æžœä½ ä½¿ç”¨ v4l2_ioctl_opsï¼Œåˆ™åº”è¯¥åœ¨ v4l2_file_operations ç»“æž„ä½“ä¸­
 è®¾ç½® .unlocked_ioctl æŒ‡å�‘ video_ioctl2ã€‚
 
@@ -789,7 +784,7 @@ v4l2_fh ç»“æž„ä½“
 -------------
 
 v4l2_fh ç»“æž„ä½“æ��ä¾›ä¸€ä¸ªä¿�å­˜ç”¨äºŽ V4L2 æ¡†æž¶çš„æ–‡ä»¶å�¥æŸ„ç‰¹å®šæ•°æ�®çš„ç®€å�•æ–¹æ³•ã€‚
-å¦‚æžœ video_device çš„ flag è®¾ç½®äº† V4L2_FL_USE_FH_PRIO æ ‡å¿—ï¼Œæ–°é©±åŠ¨
+å¦‚æžœ video_device æ ‡å¿—ï¼Œæ–°é©±åŠ¨
 å¿…é¡»ä½¿ç”¨ v4l2_fh ç»“æž„ä½“ï¼Œå› ä¸ºå®ƒä¹Ÿç”¨äºŽå®žçŽ°ä¼˜å…ˆçº§å¤„ç�†ï¼ˆVIDIOC_G/S_PRIORITYï¼‰ã€‚
 
 v4l2_fh çš„ç”¨æˆ·ï¼ˆä½�äºŽ V4l2 æ¡†æž¶ä¸­ï¼Œå¹¶é�žé©±åŠ¨ï¼‰å�¯é€šè¿‡æµ‹è¯•
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acapps.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acapps.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acapps.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acapps.h	2014-09-28 17:29:07.000000000 -0400
@@ -79,10 +79,13 @@
 /* Macros for usage messages */
 
 #define ACPI_USAGE_HEADER(usage) \
-	printf ("Usage: %s\nOptions:\n", usage);
+	acpi_os_printf ("Usage: %s\nOptions:\n", usage);
+
+#define ACPI_USAGE_TEXT(description) \
+	acpi_os_printf (description);
 
 #define ACPI_OPTION(name, description) \
-	printf ("  %-18s%s\n", name, description);
+	acpi_os_printf (" %-18s%s\n", name, description);
 
 #define FILE_SUFFIX_DISASSEMBLY     "dsl"
 #define ACPI_TABLE_FILE_SUFFIX      ".dat"
@@ -102,7 +105,7 @@ extern char *acpi_gbl_optarg;
 /*
  * cmfsize - Common get file size function
  */
-u32 cm_get_file_size(FILE * file);
+u32 cm_get_file_size(ACPI_FILE file);
 
 #ifndef ACPI_DUMP_APP
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acdebug.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acdebug.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acdebug.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acdebug.h	2014-09-28 17:29:07.000000000 -0400
@@ -233,9 +233,6 @@ acpi_status acpi_db_load_acpi_table(char
 acpi_status
 acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table);
 
-acpi_status
-acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table);
-
 /*
  * dbhistry - debugger HISTORY command
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acglobal.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acglobal.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acglobal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acglobal.h	2014-09-28 17:29:07.000000000 -0400
@@ -297,7 +297,7 @@ ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_laye
  *
  ****************************************************************************/
 
-ACPI_GLOBAL(u8, acpi_gbl_db_output_flags);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT);
 
 #ifdef ACPI_DISASSEMBLER
 
@@ -362,6 +362,12 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects);
 #ifdef ACPI_APPLICATION
 
 ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
+ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL);
+
+/* Print buffer */
+
+ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock);	/* For print buffer */
+ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]);
 
 #endif				/* ACPI_APPLICATION */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/aclocal.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/aclocal.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/aclocal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/aclocal.h	2014-09-28 17:29:07.000000000 -0400
@@ -254,6 +254,7 @@ struct acpi_create_field_info {
 	u32 field_bit_position;
 	u32 field_bit_length;
 	u16 resource_length;
+	u16 pin_number_index;
 	u8 field_flags;
 	u8 attribute;
 	u8 field_type;
@@ -730,12 +731,13 @@ union acpi_parse_value {
 #define ACPI_DASM_STRING                0x02	/* Buffer is a ASCII string */
 #define ACPI_DASM_UNICODE               0x03	/* Buffer is a Unicode string */
 #define ACPI_DASM_PLD_METHOD            0x04	/* Buffer is a _PLD method bit-packed buffer */
-#define ACPI_DASM_EISAID                0x05	/* Integer is an EISAID */
-#define ACPI_DASM_MATCHOP               0x06	/* Parent opcode is a Match() operator */
-#define ACPI_DASM_LNOT_PREFIX           0x07	/* Start of a Lnot_equal (etc.) pair of opcodes */
-#define ACPI_DASM_LNOT_SUFFIX           0x08	/* End  of a Lnot_equal (etc.) pair of opcodes */
-#define ACPI_DASM_HID_STRING            0x09	/* String is a _HID or _CID */
-#define ACPI_DASM_IGNORE                0x0A	/* Not used at this time */
+#define ACPI_DASM_UUID                  0x05	/* Buffer is a UUID/GUID */
+#define ACPI_DASM_EISAID                0x06	/* Integer is an EISAID */
+#define ACPI_DASM_MATCHOP               0x07	/* Parent opcode is a Match() operator */
+#define ACPI_DASM_LNOT_PREFIX           0x08	/* Start of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_LNOT_SUFFIX           0x09	/* End  of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_HID_STRING            0x0A	/* String is a _HID or _CID */
+#define ACPI_DASM_IGNORE                0x0B	/* Not used at this time */
 
 /*
  * Generic operation (for example:  If, While, Store)
@@ -1154,4 +1156,9 @@ struct ah_device_id {
 	char *description;
 };
 
+struct ah_uuid {
+	char *description;
+	char *string;
+};
+
 #endif				/* __ACLOCAL_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acobject.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acobject.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acobject.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acobject.h	2014-09-28 17:29:07.000000000 -0400
@@ -264,6 +264,7 @@ struct acpi_object_region_field {
 	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
 	union acpi_operand_object *region_obj;	/* Containing op_region object */
 	u8 *resource_buffer;	/* resource_template for serial regions/fields */
+	u16 pin_number_index;	/* Index relative to previous Connection/Template */
 };
 
 struct acpi_object_bank_field {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acpredef.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acpredef.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acpredef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acpredef.h	2014-09-28 17:29:07.000000000 -0400
@@ -105,6 +105,11 @@
  *      count = 0 (optional)
  *      (Used for _DLM)
  *
+ * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID
+ *      defines the format of the package. Zero-length parent package is
+ *      allowed.
+ *      (Used for _DSD)
+ *
  *****************************************************************************/
 
 enum acpi_return_package_types {
@@ -117,7 +122,8 @@ enum acpi_return_package_types {
 	ACPI_PTYPE2_FIXED = 7,
 	ACPI_PTYPE2_MIN = 8,
 	ACPI_PTYPE2_REV_FIXED = 9,
-	ACPI_PTYPE2_FIX_VAR = 10
+	ACPI_PTYPE2_FIX_VAR = 10,
+	ACPI_PTYPE2_UUID_PAIR = 11
 };
 
 /* Support macros for users of the predefined info table */
@@ -364,6 +370,9 @@ const union acpi_predefined_info acpi_gb
 	{{"_CBA", METHOD_0ARGS,
 	  METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},	/* See PCI firmware spec 3.0 */
 
+	{{"_CCA", METHOD_0ARGS,
+	  METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},	/* ACPI 5.1 */
+
 	{{"_CDM", METHOD_0ARGS,
 	  METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
 
@@ -436,6 +445,11 @@ const union acpi_predefined_info acpi_gb
 	{{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER),
 	  METHOD_NO_RETURN_VALUE}},
 
+	{{"_DSD", METHOD_0ARGS,
+	  METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}},	/* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */
+	PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1,
+		     ACPI_RTYPE_PACKAGE, 1, 0),
+
 	{{"_DSM",
 	  METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER,
 		       ACPI_TYPE_PACKAGE),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/acutils.h linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acutils.h
--- linux-libre-3.16-gnu/drivers/acpi/acpica/acutils.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/acutils.h	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,6 @@ extern const char *acpi_gbl_pt_decode[];
 #ifdef ACPI_ASL_COMPILER
 
 #include <stdio.h>
-extern FILE *acpi_gbl_output_file;
 
 #define ACPI_MSG_REDIRECT_BEGIN \
 	FILE                            *output_file = acpi_gbl_output_file; \
@@ -195,6 +194,8 @@ char *acpi_ut_get_event_name(u32 event_i
 
 char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
 
+u8 acpi_ut_ascii_char_to_hex(int hex_char);
+
 u8 acpi_ut_valid_object_type(acpi_object_type type);
 
 /*
@@ -211,6 +212,8 @@ void acpi_ut_subsystem_shutdown(void);
 
 acpi_size acpi_ut_strlen(const char *string);
 
+char *acpi_ut_strchr(const char *string, int ch);
+
 char *acpi_ut_strcpy(char *dst_string, const char *src_string);
 
 char *acpi_ut_strncpy(char *dst_string,
@@ -257,7 +260,7 @@ extern const u8 _acpi_ctype[];
 #define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
 #define ACPI_IS_UPPER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP))
 #define ACPI_IS_LOWER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
-#define ACPI_IS_PRINT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
+#define ACPI_IS_PRINT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU))
 #define ACPI_IS_ALPHA(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
 
 #endif				/* !ACPI_USE_SYSTEM_CLIBRARY */
@@ -352,6 +355,13 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u3
 
 void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
 
+#ifdef ACPI_APPLICATION
+void
+acpi_ut_dump_buffer_to_file(ACPI_FILE file,
+			    u8 *buffer,
+			    u32 count, u32 display, u32 base_offset);
+#endif
+
 void acpi_ut_report_error(char *module_name, u32 line_number);
 
 void acpi_ut_report_info(char *module_name, u32 line_number);
@@ -394,6 +404,14 @@ acpi_ut_execute_power_methods(struct acp
 			      u8 method_count, u8 *out_values);
 
 /*
+ * utfileio - file operations
+ */
+#ifdef ACPI_APPLICATION
+acpi_status
+acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table);
+#endif
+
+/*
  * utids - device ID support
  */
 acpi_status
@@ -743,4 +761,30 @@ const struct ah_predefined_name *acpi_ah
 
 const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
 
+const char *acpi_ah_match_uuid(u8 *data);
+
+/*
+ * utprint - printf/vprintf output functions
+ */
+const char *acpi_ut_scan_number(const char *string, u64 *number_ptr);
+
+const char *acpi_ut_print_number(char *string, u64 number);
+
+int
+acpi_ut_vsnprintf(char *string,
+		  acpi_size size, const char *format, va_list args);
+
+int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...);
+
+#ifdef ACPI_APPLICATION
+int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args);
+
+int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...);
+#endif
+
+/*
+ * utuuid -- UUID support functions
+ */
+void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer);
+
 #endif				/* _ACUTILS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/dsfield.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/dsfield.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/dsfield.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/dsfield.c	2014-09-28 17:29:07.000000000 -0400
@@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_crea
 			 */
 			info->resource_buffer = NULL;
 			info->connection_node = NULL;
+			info->pin_number_index = 0;
 
 			/*
 			 * A Connection() is either an actual resource descriptor (buffer)
@@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_crea
 			}
 
 			info->field_bit_position += info->field_bit_length;
+			info->pin_number_index++;	/* Index relative to previous Connection() */
 			break;
 
 		default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/evgpe.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evgpe.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/evgpe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evgpe.c	2014-09-28 17:29:07.000000000 -0400
@@ -698,21 +698,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespa
 	}
 
 	/*
-	 * If edge-triggered, clear the GPE status bit now. Note that
-	 * level-triggered events are cleared after the GPE is serviced.
-	 */
-	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
-	    ACPI_GPE_EDGE_TRIGGERED) {
-		status = acpi_hw_clear_gpe(gpe_event_info);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to clear GPE %02X",
-					gpe_number));
-			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
-		}
-	}
-
-	/*
 	 * Always disable the GPE so that it does not keep firing before
 	 * any asynchronous activity completes (either from the execution
 	 * of a GPE method or an asynchronous GPE handler.)
@@ -729,6 +714,23 @@ acpi_ev_gpe_dispatch(struct acpi_namespa
 	}
 
 	/*
+	 * If edge-triggered, clear the GPE status bit now. Note that
+	 * level-triggered events are cleared after the GPE is serviced.
+	 */
+	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
+	    ACPI_GPE_EDGE_TRIGGERED) {
+		status = acpi_hw_clear_gpe(gpe_event_info);
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Unable to clear GPE %02X",
+					gpe_number));
+			(void)acpi_hw_low_set_gpe(gpe_event_info,
+						  ACPI_GPE_CONDITIONAL_ENABLE);
+			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
+		}
+	}
+
+	/*
 	 * Dispatch the GPE to either an installed handler or the control
 	 * method associated with this GPE (_Lxx or _Exx). If a handler
 	 * exists, we invoke it and do not attempt to run the method.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/evregion.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evregion.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/evregion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evregion.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acp
 	union acpi_operand_object *region_obj2;
 	void *region_context = NULL;
 	struct acpi_connection_info *context;
+	acpi_physical_address address;
 
 	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
 
@@ -231,25 +232,32 @@ acpi_ev_address_space_dispatch(union acp
 	/* We have everything we need, we can invoke the address space handler */
 
 	handler = handler_desc->address_space.handler;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
-			  &region_obj->region.handler->address_space, handler,
-			  ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
-						  region_offset),
-			  acpi_ut_get_region_name(region_obj->region.
-						  space_id)));
+	address = (region_obj->region.address + region_offset);
 
 	/*
 	 * Special handling for generic_serial_bus and general_purpose_io:
 	 * There are three extra parameters that must be passed to the
 	 * handler via the context:
-	 *   1) Connection buffer, a resource template from Connection() op.
-	 *   2) Length of the above buffer.
-	 *   3) Actual access length from the access_as() op.
+	 *   1) Connection buffer, a resource template from Connection() op
+	 *   2) Length of the above buffer
+	 *   3) Actual access length from the access_as() op
+	 *
+	 * In addition, for general_purpose_io, the Address and bit_width fields
+	 * are defined as follows:
+	 *   1) Address is the pin number index of the field (bit offset from
+	 *      the previous Connection)
+	 *   2) bit_width is the actual bit length of the field (number of pins)
 	 */
-	if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
-	     (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
+	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
+	    context && field_obj) {
+
+		/* Get the Connection (resource_template) buffer */
+
+		context->connection = field_obj->field.resource_buffer;
+		context->length = field_obj->field.resource_length;
+		context->access_length = field_obj->field.access_length;
+	}
+	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
 	    context && field_obj) {
 
 		/* Get the Connection (resource_template) buffer */
@@ -257,8 +265,17 @@ acpi_ev_address_space_dispatch(union acp
 		context->connection = field_obj->field.resource_buffer;
 		context->length = field_obj->field.resource_length;
 		context->access_length = field_obj->field.access_length;
+		address = field_obj->field.pin_number_index;
+		bit_width = field_obj->field.bit_length;
 	}
 
+	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+			  &region_obj->region.handler->address_space, handler,
+			  ACPI_FORMAT_NATIVE_UINT(address),
+			  acpi_ut_get_region_name(region_obj->region.
+						  space_id)));
+
 	if (!(handler_desc->address_space.handler_flags &
 	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
@@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acp
 
 	/* Call the handler */
 
-	status = handler(function,
-			 (region_obj->region.address + region_offset),
-			 bit_width, value, context,
+	status = handler(function, address, bit_width, value, context,
 			 region_obj2->extra.region_context);
 
 	if (ACPI_FAILURE(status)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/evxfgpe.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evxfgpe.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/evxfgpe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/evxfgpe.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,11 +126,19 @@ acpi_status acpi_enable_gpe(acpi_handle
 
 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 
-	/* Ensure that we have a valid GPE number */
-
+	/*
+	 * Ensure that we have a valid GPE number and that there is some way
+	 * of handling the GPE (handler or a GPE method). In other words, we
+	 * won't allow a valid GPE to be enabled if there is no way to handle it.
+	 */
 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 	if (gpe_event_info) {
-		status = acpi_ev_add_gpe_reference(gpe_event_info);
+		if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
+		    ACPI_GPE_DISPATCH_NONE) {
+			status = acpi_ev_add_gpe_reference(gpe_event_info);
+		} else {
+			status = AE_NO_HANDLER;
+		}
 	}
 
 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
@@ -179,6 +187,53 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_mark_gpe_for_wake
+ *
+ * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number          - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
+ *              sets the ACPI_GPE_CAN_WAKE flag.
+ *
+ * Some potential callers of acpi_setup_gpe_for_wake may know in advance that
+ * there won't be any notify handlers installed for device wake notifications
+ * from the given GPE (one example is a button GPE in Linux). For these cases,
+ * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
+ * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
+ * setup implicit wake notification for it (since there's no handler method).
+ *
+ ******************************************************************************/
+acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
+{
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_status status = AE_BAD_PARAMETER;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (gpe_event_info) {
+
+		/* Mark the GPE as a possible wake event */
+
+		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+		status = AE_OK;
+	}
+
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_setup_gpe_for_wake
  *
  * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/exdebug.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exdebug.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/exdebug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exdebug.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,6 +75,7 @@ acpi_ex_do_debug_object(union acpi_opera
 			u32 level, u32 index)
 {
 	u32 i;
+	u32 timer;
 
 	ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
 
@@ -86,11 +87,19 @@ acpi_ex_do_debug_object(union acpi_opera
 	}
 
 	/*
+	 * We will emit the current timer value (in microseconds) with each
+	 * debug output. Only need the lower 26 bits. This allows for 67
+	 * million microseconds or 67 seconds before rollover.
+	 */
+	timer = ((u32)acpi_os_get_timer() / 10);	/* (100 nanoseconds to microseconds) */
+	timer &= 0x03FFFFFF;
+
+	/*
 	 * Print line header as long as we are not in the middle of an
 	 * object display
 	 */
 	if (!((level > 0) && index == 0)) {
-		acpi_os_printf("[ACPI Debug] %*s", level, " ");
+		acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " ");
 	}
 
 	/* Display the index for package output only */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/exdump.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exdump.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/exdump.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exdump.c	2014-09-28 17:29:07.000000000 -0400
@@ -494,7 +494,7 @@ acpi_ex_dump_object(union acpi_operand_o
 				}
 			}
 
-			acpi_os_printf("\n", next);
+			acpi_os_printf("\n");
 			break;
 
 		case ACPI_EXD_HDLR_LIST:
@@ -528,7 +528,7 @@ acpi_ex_dump_object(union acpi_operand_o
 				}
 			}
 
-			acpi_os_printf("\n", next);
+			acpi_os_printf("\n");
 			break;
 
 		case ACPI_EXD_RGN_LIST:
@@ -562,7 +562,7 @@ acpi_ex_dump_object(union acpi_operand_o
 				}
 			}
 
-			acpi_os_printf("\n", next);
+			acpi_os_printf("\n");
 			break;
 
 		case ACPI_EXD_NODE:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/exfield.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exfield.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/exfield.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exfield.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@ acpi_ex_get_serial_access_length(u32 acc
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_serial_access_bytes
+ * FUNCTION:    acpi_ex_get_serial_access_length
  *
  * PARAMETERS:  accessor_type   - The type of the protocol indicated by region
  *                                field access attributes
@@ -103,7 +103,7 @@ acpi_ex_get_serial_access_length(u32 acc
 	case AML_FIELD_ATTRIB_BLOCK_CALL:
 	default:
 
-		length = ACPI_GSBUS_BUFFER_SIZE;
+		length = ACPI_GSBUS_BUFFER_SIZE - 2;
 		break;
 	}
 
@@ -186,12 +186,11 @@ acpi_ex_read_data_from_field(struct acpi
 								  access_length);
 
 			/*
-			 * Add additional 2 bytes for modeled generic_serial_bus data buffer:
-			 * typedef struct {
-			 *     BYTEStatus; // Byte 0 of the data buffer
-			 *     BYTELength; // Byte 1 of the data buffer
-			 *     BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
-			 * }
+			 * Add additional 2 bytes for the generic_serial_bus data buffer:
+			 *
+			 *     Status;      (Byte 0 of the data buffer)
+			 *     Length;      (Byte 1 of the data buffer)
+			 *     Data[x-1];   (Bytes 2-x of the arbitrary length data buffer)
 			 */
 			length += 2;
 			function = ACPI_READ | (accessor_type << 16);
@@ -254,6 +253,37 @@ acpi_ex_read_data_from_field(struct acpi
 		buffer = &buffer_desc->integer.value;
 	}
 
+	if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+	    (obj_desc->field.region_obj->region.space_id ==
+	     ACPI_ADR_SPACE_GPIO)) {
+		/*
+		 * For GPIO (general_purpose_io), the Address will be the bit offset
+		 * from the previous Connection() operator, making it effectively a
+		 * pin number index. The bit_length is the length of the field, which
+		 * is thus the number of pins.
+		 */
+		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+				  "GPIO FieldRead [FROM]:  Pin %u Bits %u\n",
+				  obj_desc->field.pin_number_index,
+				  obj_desc->field.bit_length));
+
+		/* Lock entire transaction if requested */
+
+		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+		/* Perform the write */
+
+		status = acpi_ex_access_region(obj_desc, 0,
+					       (u64 *)buffer, ACPI_READ);
+		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+		if (ACPI_FAILURE(status)) {
+			acpi_ut_remove_reference(buffer_desc);
+		} else {
+			*ret_buffer_desc = buffer_desc;
+		}
+		return_ACPI_STATUS(status);
+	}
+
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 			  "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
 			  obj_desc, obj_desc->common.type, buffer,
@@ -368,12 +398,11 @@ acpi_ex_write_data_to_field(union acpi_o
 								  access_length);
 
 			/*
-			 * Add additional 2 bytes for modeled generic_serial_bus data buffer:
-			 * typedef struct {
-			 *     BYTEStatus; // Byte 0 of the data buffer
-			 *     BYTELength; // Byte 1 of the data buffer
-			 *     BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
-			 * }
+			 * Add additional 2 bytes for the generic_serial_bus data buffer:
+			 *
+			 *     Status;      (Byte 0 of the data buffer)
+			 *     Length;      (Byte 1 of the data buffer)
+			 *     Data[x-1];   (Bytes 2-x of the arbitrary length data buffer)
 			 */
 			length += 2;
 			function = ACPI_WRITE | (accessor_type << 16);
@@ -415,6 +444,42 @@ acpi_ex_write_data_to_field(union acpi_o
 
 		*result_desc = buffer_desc;
 		return_ACPI_STATUS(status);
+	} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+		   (obj_desc->field.region_obj->region.space_id ==
+		    ACPI_ADR_SPACE_GPIO)) {
+		/*
+		 * For GPIO (general_purpose_io), we will bypass the entire field
+		 * mechanism and handoff the bit address and bit width directly to
+		 * the handler. The Address will be the bit offset
+		 * from the previous Connection() operator, making it effectively a
+		 * pin number index. The bit_length is the length of the field, which
+		 * is thus the number of pins.
+		 */
+		if (source_desc->common.type != ACPI_TYPE_INTEGER) {
+			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+				  "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X  [TO]:  Pin %u Bits %u\n",
+				  acpi_ut_get_type_name(source_desc->common.
+							type),
+				  source_desc->common.type,
+				  (u32)source_desc->integer.value,
+				  obj_desc->field.pin_number_index,
+				  obj_desc->field.bit_length));
+
+		buffer = &source_desc->integer.value;
+
+		/* Lock entire transaction if requested */
+
+		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
+
+		/* Perform the write */
+
+		status = acpi_ex_access_region(obj_desc, 0,
+					       (u64 *)buffer, ACPI_WRITE);
+		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
+		return_ACPI_STATUS(status);
 	}
 
 	/* Get a pointer to the data to be written */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/exprep.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exprep.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/exprep.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/exprep.c	2014-09-28 17:29:07.000000000 -0400
@@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(str
 			obj_desc->field.resource_length = info->resource_length;
 		}
 
+		obj_desc->field.pin_number_index = info->pin_number_index;
+
 		/* Allow full data read from EC address space */
 
 		if ((obj_desc->field.region_obj->region.space_id ==
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/hwregs.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/hwregs.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/hwregs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/hwregs.c	2014-09-28 17:29:07.000000000 -0400
@@ -278,8 +278,9 @@ acpi_status acpi_hw_clear_acpi_status(vo
 
 	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 
-	if (ACPI_FAILURE(status))
+	if (ACPI_FAILURE(status)) {
 		goto exit;
+	}
 
 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/Makefile linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/Makefile
--- linux-libre-3.16-gnu/drivers/acpi/acpica/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for ACPICA Core interpreter
 #
 
-ccflags-y			:= -Os
+ccflags-y			:= -Os -DBUILDING_ACPICA
 ccflags-$(CONFIG_ACPI_DEBUG)	+= -DACPI_DEBUG_OUTPUT
 
 # use acpi.o to put all files here into acpi.o modparam namespace
@@ -157,6 +157,7 @@ acpi-y +=		\
 	uterror.o	\
 	uteval.o	\
 	utglobal.o	\
+	uthex.o		\
 	utids.o		\
 	utinit.o	\
 	utlock.o	\
@@ -175,5 +176,10 @@ acpi-y +=		\
 	utxferror.o	\
 	utxfmutex.o
 
-acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o
+acpi-$(ACPI_FUTURE_USAGE) +=	\
+	utcache.o		\
+	utfileio.o		\
+	utprint.o		\
+	uttrack.o		\
+	utuuid.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/nsobject.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/nsobject.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/nsobject.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/nsobject.c	2014-09-28 17:29:07.000000000 -0400
@@ -237,6 +237,16 @@ void acpi_ns_detach_object(struct acpi_n
 		    (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
 			node->object = node->object->common.next_object;
 		}
+
+		/*
+		 * Detach the object from any data objects (which are still held by
+		 * the namespace node)
+		 */
+		if (obj_desc->common.next_object &&
+		    ((obj_desc->common.next_object)->common.type ==
+		     ACPI_TYPE_LOCAL_DATA)) {
+			obj_desc->common.next_object = NULL;
+		}
 	}
 
 	/* Reset the node type to untyped */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/nsprepkg.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/nsprepkg.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/nsprepkg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/nsprepkg.c	2014-09-28 17:29:07.000000000 -0400
@@ -316,6 +316,45 @@ acpi_ns_check_package(struct acpi_evalua
 		    acpi_ns_check_package_list(info, package, elements, count);
 		break;
 
+	case ACPI_PTYPE2_UUID_PAIR:
+
+		/* The package must contain pairs of (UUID + type) */
+
+		if (count & 1) {
+			expected_count = count + 1;
+			goto package_too_small;
+		}
+
+		while (count > 0) {
+			status = acpi_ns_check_object_type(info, elements,
+							   package->ret_info.
+							   object_type1, 0);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+
+			/* Validate length of the UUID buffer */
+
+			if ((*elements)->buffer.length != 16) {
+				ACPI_WARN_PREDEFINED((AE_INFO,
+						      info->full_pathname,
+						      info->node_flags,
+						      "Invalid length for UUID Buffer"));
+				return (AE_AML_OPERAND_VALUE);
+			}
+
+			status = acpi_ns_check_object_type(info, elements + 1,
+							   package->ret_info.
+							   object_type2, 0);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+
+			elements += 2;
+			count -= 2;
+		}
+		break;
+
 	default:
 
 		/* Should not get here if predefined info table is correct */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utbuffer.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utbuffer.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utbuffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utbuffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,3 +199,131 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u3
 
 	acpi_ut_dump_buffer(buffer, count, display, 0);
 }
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_buffer_to_file
+ *
+ * PARAMETERS:  file                - File descriptor
+ *              buffer              - Buffer to dump
+ *              count               - Amount to dump, in bytes
+ *              display             - BYTE, WORD, DWORD, or QWORD display:
+ *                                      DB_BYTE_DISPLAY
+ *                                      DB_WORD_DISPLAY
+ *                                      DB_DWORD_DISPLAY
+ *                                      DB_QWORD_DISPLAY
+ *              base_offset         - Beginning buffer offset (display only)
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Generic dump buffer in both hex and ascii to a file.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_dump_buffer_to_file(ACPI_FILE file,
+			    u8 *buffer, u32 count, u32 display, u32 base_offset)
+{
+	u32 i = 0;
+	u32 j;
+	u32 temp32;
+	u8 buf_char;
+
+	if (!buffer) {
+		acpi_ut_file_printf(file,
+				    "Null Buffer Pointer in DumpBuffer!\n");
+		return;
+	}
+
+	if ((count < 4) || (count & 0x01)) {
+		display = DB_BYTE_DISPLAY;
+	}
+
+	/* Nasty little dump buffer routine! */
+
+	while (i < count) {
+
+		/* Print current offset */
+
+		acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i));
+
+		/* Print 16 hex chars */
+
+		for (j = 0; j < 16;) {
+			if (i + j >= count) {
+
+				/* Dump fill spaces */
+
+				acpi_ut_file_printf(file, "%*s",
+						    ((display * 2) + 1), " ");
+				j += display;
+				continue;
+			}
+
+			switch (display) {
+			case DB_BYTE_DISPLAY:
+			default:	/* Default is BYTE display */
+
+				acpi_ut_file_printf(file, "%02X ",
+						    buffer[(acpi_size) i + j]);
+				break;
+
+			case DB_WORD_DISPLAY:
+
+				ACPI_MOVE_16_TO_32(&temp32,
+						   &buffer[(acpi_size) i + j]);
+				acpi_ut_file_printf(file, "%04X ", temp32);
+				break;
+
+			case DB_DWORD_DISPLAY:
+
+				ACPI_MOVE_32_TO_32(&temp32,
+						   &buffer[(acpi_size) i + j]);
+				acpi_ut_file_printf(file, "%08X ", temp32);
+				break;
+
+			case DB_QWORD_DISPLAY:
+
+				ACPI_MOVE_32_TO_32(&temp32,
+						   &buffer[(acpi_size) i + j]);
+				acpi_ut_file_printf(file, "%08X", temp32);
+
+				ACPI_MOVE_32_TO_32(&temp32,
+						   &buffer[(acpi_size) i + j +
+							   4]);
+				acpi_ut_file_printf(file, "%08X ", temp32);
+				break;
+			}
+
+			j += display;
+		}
+
+		/*
+		 * Print the ASCII equivalent characters but watch out for the bad
+		 * unprintable ones (printable chars are 0x20 through 0x7E)
+		 */
+		acpi_ut_file_printf(file, " ");
+		for (j = 0; j < 16; j++) {
+			if (i + j >= count) {
+				acpi_ut_file_printf(file, "\n");
+				return;
+			}
+
+			buf_char = buffer[(acpi_size) i + j];
+			if (ACPI_IS_PRINT(buf_char)) {
+				acpi_ut_file_printf(file, "%c", buf_char);
+			} else {
+				acpi_ut_file_printf(file, ".");
+			}
+		}
+
+		/* Done with that line. */
+
+		acpi_ut_file_printf(file, "\n");
+		i += 16;
+	}
+
+	return;
+}
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utcopy.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utcopy.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utcopy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utcopy.c	2014-09-28 17:29:07.000000000 -0400
@@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union ac
 		status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
 	}
 
+	/* Delete the allocated object if copy failed */
+
+	if (ACPI_FAILURE(status)) {
+		acpi_ut_remove_reference(*dest_desc);
+	}
+
 	return_ACPI_STATUS(status);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utdebug.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utdebug.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utdebug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utdebug.c	2014-09-28 17:29:07.000000000 -0400
@@ -561,3 +561,29 @@ acpi_ut_ptr_exit(u32 line_number,
 }
 
 #endif
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_log_error
+ *
+ * PARAMETERS:  format              - Printf format field
+ *              ...                 - Optional printf arguments
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print error message to the console, used by applications.
+ *
+ ******************************************************************************/
+
+void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	(void)acpi_ut_file_vprintf(ACPI_FILE_ERR, format, args);
+	va_end(args);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_log_error)
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utdecode.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utdecode.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utdecode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utdecode.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,33 +88,6 @@ const u8 acpi_gbl_ns_properties[ACPI_NUM
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_hex_to_ascii_char
- *
- * PARAMETERS:  integer             - Contains the hex digit
- *              position            - bit position of the digit within the
- *                                    integer (multiple of 4)
- *
- * RETURN:      The converted Ascii character
- *
- * DESCRIPTION: Convert a hex digit to an Ascii character
- *
- ******************************************************************************/
-
-/* Hex to ASCII conversion table */
-
-static const char acpi_gbl_hex_to_ascii[] = {
-	'0', '1', '2', '3', '4', '5', '6', '7',
-	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
-{
-
-	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ut_get_region_name
  *
  * PARAMETERS:  Space ID            - ID for the region
@@ -475,7 +448,8 @@ static const char *acpi_gbl_generic_noti
 	/* 09 */ "Device PLD Check",
 	/* 0A */ "Reserved",
 	/* 0B */ "System Locality Update",
-	/* 0C */ "Shutdown Request"
+	/* 0C */ "Shutdown Request",
+	/* 0D */ "System Resource Affinity Update"
 };
 
 static const char *acpi_gbl_device_notify[4] = {
@@ -502,7 +476,7 @@ static const char *acpi_gbl_thermal_noti
 const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
 {
 
-	/* 00 - 0C are common to all object types */
+	/* 00 - 0D are common to all object types */
 
 	if (notify_value <= ACPI_NOTIFY_MAX) {
 		return (acpi_gbl_generic_notify[notify_value]);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utfileio.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utfileio.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utfileio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utfileio.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ *
+ * Module Name: utfileio - simple file I/O routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "actables.h"
+#include "acapps.h"
+
+#ifdef ACPI_ASL_COMPILER
+#include "aslcompiler.h"
+#endif
+
+#define _COMPONENT          ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("utfileio")
+
+#ifdef ACPI_APPLICATION
+/* Local prototypes */
+static acpi_status
+acpi_ut_check_text_mode_corruption(u8 *table,
+				   u32 table_length, u32 file_length);
+
+static acpi_status
+acpi_ut_read_table(FILE * fp,
+		   struct acpi_table_header **table, u32 *table_length);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_check_text_mode_corruption
+ *
+ * PARAMETERS:  table           - Table buffer
+ *              table_length    - Length of table from the table header
+ *              file_length     - Length of the file that contains the table
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Check table for text mode file corruption where all linefeed
+ *              characters (LF) have been replaced by carriage return linefeed
+ *              pairs (CR/LF).
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length)
+{
+	u32 i;
+	u32 pairs = 0;
+
+	if (table_length != file_length) {
+		ACPI_WARNING((AE_INFO,
+			      "File length (0x%X) is not the same as the table length (0x%X)",
+			      file_length, table_length));
+	}
+
+	/* Scan entire table to determine if each LF has been prefixed with a CR */
+
+	for (i = 1; i < file_length; i++) {
+		if (table[i] == 0x0A) {
+			if (table[i - 1] != 0x0D) {
+
+				/* The LF does not have a preceding CR, table not corrupted */
+
+				return (AE_OK);
+			} else {
+				/* Found a CR/LF pair */
+
+				pairs++;
+			}
+			i++;
+		}
+	}
+
+	if (!pairs) {
+		return (AE_OK);
+	}
+
+	/*
+	 * Entire table scanned, each CR is part of a CR/LF pair --
+	 * meaning that the table was treated as a text file somewhere.
+	 *
+	 * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
+	 * original table are left untouched by the text conversion process --
+	 * meaning that we cannot simply replace CR/LF pairs with LFs.
+	 */
+	acpi_os_printf("Table has been corrupted by text mode conversion\n");
+	acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs);
+	acpi_os_printf("Table cannot be repaired!\n");
+	return (AE_BAD_VALUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_read_table
+ *
+ * PARAMETERS:  fp              - File that contains table
+ *              table           - Return value, buffer with table
+ *              table_length    - Return value, length of table
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Load the DSDT from the file pointer
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_read_table(FILE * fp,
+		   struct acpi_table_header **table, u32 *table_length)
+{
+	struct acpi_table_header table_header;
+	u32 actual;
+	acpi_status status;
+	u32 file_size;
+	u8 standard_header = TRUE;
+	s32 count;
+
+	/* Get the file size */
+
+	file_size = cm_get_file_size(fp);
+	if (file_size == ACPI_UINT32_MAX) {
+		return (AE_ERROR);
+	}
+
+	if (file_size < 4) {
+		return (AE_BAD_HEADER);
+	}
+
+	/* Read the signature */
+
+	fseek(fp, 0, SEEK_SET);
+
+	count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
+	if (count != sizeof(struct acpi_table_header)) {
+		acpi_os_printf("Could not read the table header\n");
+		return (AE_BAD_HEADER);
+	}
+
+	/* The RSDP table does not have standard ACPI header */
+
+	if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) {
+		*table_length = file_size;
+		standard_header = FALSE;
+	} else {
+
+#if 0
+		/* Validate the table header/length */
+
+		status = acpi_tb_validate_table_header(&table_header);
+		if (ACPI_FAILURE(status)) {
+			acpi_os_printf("Table header is invalid!\n");
+			return (status);
+		}
+#endif
+
+		/* File size must be at least as long as the Header-specified length */
+
+		if (table_header.length > file_size) {
+			acpi_os_printf
+			    ("TableHeader length [0x%X] greater than the input file size [0x%X]\n",
+			     table_header.length, file_size);
+
+#ifdef ACPI_ASL_COMPILER
+			status = fl_check_for_ascii(fp, NULL, FALSE);
+			if (ACPI_SUCCESS(status)) {
+				acpi_os_printf
+				    ("File appears to be ASCII only, must be binary\n");
+			}
+#endif
+			return (AE_BAD_HEADER);
+		}
+#ifdef ACPI_OBSOLETE_CODE
+		/* We only support a limited number of table types */
+
+		if (!ACPI_COMPARE_NAME
+		    ((char *)table_header.signature, ACPI_SIG_DSDT)
+		    && !ACPI_COMPARE_NAME((char *)table_header.signature,
+					  ACPI_SIG_PSDT)
+		    && !ACPI_COMPARE_NAME((char *)table_header.signature,
+					  ACPI_SIG_SSDT)) {
+			acpi_os_printf
+			    ("Table signature [%4.4s] is invalid or not supported\n",
+			     (char *)table_header.signature);
+			ACPI_DUMP_BUFFER(&table_header,
+					 sizeof(struct acpi_table_header));
+			return (AE_ERROR);
+		}
+#endif
+
+		*table_length = table_header.length;
+	}
+
+	/* Allocate a buffer for the table */
+
+	*table = acpi_os_allocate((size_t) file_size);
+	if (!*table) {
+		acpi_os_printf
+		    ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
+		     table_header.signature, *table_length);
+		return (AE_NO_MEMORY);
+	}
+
+	/* Get the rest of the table */
+
+	fseek(fp, 0, SEEK_SET);
+	actual = fread(*table, 1, (size_t) file_size, fp);
+	if (actual == file_size) {
+		if (standard_header) {
+
+			/* Now validate the checksum */
+
+			status = acpi_tb_verify_checksum((void *)*table,
+							 ACPI_CAST_PTR(struct
+								       acpi_table_header,
+								       *table)->
+							 length);
+
+			if (status == AE_BAD_CHECKSUM) {
+				status =
+				    acpi_ut_check_text_mode_corruption((u8 *)
+								       *table,
+								       file_size,
+								       (*table)->
+								       length);
+				return (status);
+			}
+		}
+		return (AE_OK);
+	}
+
+	if (actual > 0) {
+		acpi_os_printf("Warning - reading table, asked for %X got %X\n",
+			       file_size, actual);
+		return (AE_OK);
+	}
+
+	acpi_os_printf("Error - could not read the table file\n");
+	acpi_os_free(*table);
+	*table = NULL;
+	*table_length = 0;
+	return (AE_ERROR);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_read_table_from_file
+ *
+ * PARAMETERS:  filename         - File where table is located
+ *              table            - Where a pointer to the table is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get an ACPI table from a file
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
+{
+	FILE *file;
+	u32 file_size;
+	u32 table_length;
+	acpi_status status = AE_ERROR;
+
+	/* Open the file, get current size */
+
+	file = fopen(filename, "rb");
+	if (!file) {
+		perror("Could not open input file");
+		return (status);
+	}
+
+	file_size = cm_get_file_size(file);
+	if (file_size == ACPI_UINT32_MAX) {
+		goto exit;
+	}
+
+	/* Get the entire file */
+
+	fprintf(stderr,
+		"Loading Acpi table from file %10s - Length %.8u (%06X)\n",
+		filename, file_size, file_size);
+
+	status = acpi_ut_read_table(file, table, &table_length);
+	if (ACPI_FAILURE(status)) {
+		acpi_os_printf("Could not get table from the file\n");
+	}
+
+exit:
+	fclose(file);
+	return (status);
+}
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utglobal.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utglobal.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utglobal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utglobal.c	2014-09-28 17:29:07.000000000 -0400
@@ -214,152 +214,6 @@ struct acpi_fixed_event_info acpi_gbl_fi
 };
 #endif				/* !ACPI_REDUCED_HARDWARE */
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_init_globals
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Initialize ACPICA globals. All globals that require specific
- *              initialization should be initialized here. This allows for
- *              a warm restart.
- *
- ******************************************************************************/
-
-acpi_status acpi_ut_init_globals(void)
-{
-	acpi_status status;
-	u32 i;
-
-	ACPI_FUNCTION_TRACE(ut_init_globals);
-
-	/* Create all memory caches */
-
-	status = acpi_ut_create_caches();
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/* Address Range lists */
-
-	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
-		acpi_gbl_address_range_list[i] = NULL;
-	}
-
-	/* Mutex locked flags */
-
-	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
-		acpi_gbl_mutex_info[i].mutex = NULL;
-		acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
-		acpi_gbl_mutex_info[i].use_count = 0;
-	}
-
-	for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
-		acpi_gbl_owner_id_mask[i] = 0;
-	}
-
-	/* Last owner_ID is never valid */
-
-	acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
-
-	/* Event counters */
-
-	acpi_method_count = 0;
-	acpi_sci_count = 0;
-	acpi_gpe_count = 0;
-
-	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
-		acpi_fixed_event_count[i] = 0;
-	}
-
-#if (!ACPI_REDUCED_HARDWARE)
-
-	/* GPE/SCI support */
-
-	acpi_gbl_all_gpes_initialized = FALSE;
-	acpi_gbl_gpe_xrupt_list_head = NULL;
-	acpi_gbl_gpe_fadt_blocks[0] = NULL;
-	acpi_gbl_gpe_fadt_blocks[1] = NULL;
-	acpi_current_gpe_count = 0;
-
-	acpi_gbl_global_event_handler = NULL;
-	acpi_gbl_sci_handler_list = NULL;
-
-#endif				/* !ACPI_REDUCED_HARDWARE */
-
-	/* Global handlers */
-
-	acpi_gbl_global_notify[0].handler = NULL;
-	acpi_gbl_global_notify[1].handler = NULL;
-	acpi_gbl_exception_handler = NULL;
-	acpi_gbl_init_handler = NULL;
-	acpi_gbl_table_handler = NULL;
-	acpi_gbl_interface_handler = NULL;
-
-	/* Global Lock support */
-
-	acpi_gbl_global_lock_semaphore = NULL;
-	acpi_gbl_global_lock_mutex = NULL;
-	acpi_gbl_global_lock_acquired = FALSE;
-	acpi_gbl_global_lock_handle = 0;
-	acpi_gbl_global_lock_present = FALSE;
-
-	/* Miscellaneous variables */
-
-	acpi_gbl_DSDT = NULL;
-	acpi_gbl_cm_single_step = FALSE;
-	acpi_gbl_shutdown = FALSE;
-	acpi_gbl_ns_lookup_count = 0;
-	acpi_gbl_ps_find_count = 0;
-	acpi_gbl_acpi_hardware_present = TRUE;
-	acpi_gbl_last_owner_id_index = 0;
-	acpi_gbl_next_owner_id_offset = 0;
-	acpi_gbl_trace_dbg_level = 0;
-	acpi_gbl_trace_dbg_layer = 0;
-	acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
-	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
-	acpi_gbl_osi_mutex = NULL;
-	acpi_gbl_reg_methods_executed = FALSE;
-
-	/* Hardware oriented */
-
-	acpi_gbl_events_initialized = FALSE;
-	acpi_gbl_system_awake_and_running = TRUE;
-
-	/* Namespace */
-
-	acpi_gbl_module_code_list = NULL;
-	acpi_gbl_root_node = NULL;
-	acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
-	acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
-	acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
-	acpi_gbl_root_node_struct.parent = NULL;
-	acpi_gbl_root_node_struct.child = NULL;
-	acpi_gbl_root_node_struct.peer = NULL;
-	acpi_gbl_root_node_struct.object = NULL;
-
-#ifdef ACPI_DISASSEMBLER
-	acpi_gbl_external_list = NULL;
-	acpi_gbl_num_external_methods = 0;
-	acpi_gbl_resolved_external_methods = 0;
-#endif
-
-#ifdef ACPI_DEBUG_OUTPUT
-	acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX);
-#endif
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-	acpi_gbl_display_final_mem_stats = FALSE;
-	acpi_gbl_disable_mem_tracking = FALSE;
-#endif
-
-	ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
-
-	return_ACPI_STATUS(AE_OK);
-}
-
 /* Public globals */
 
 ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/uthex.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/uthex.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/uthex.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/uthex.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * Module Name: uthex -- Hex/ASCII support functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_COMPILER
+ACPI_MODULE_NAME("uthex")
+
+/* Hex to ASCII conversion table */
+static char acpi_gbl_hex_to_ascii[] = {
+	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+	    'E', 'F'
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_hex_to_ascii_char
+ *
+ * PARAMETERS:  integer             - Contains the hex digit
+ *              position            - bit position of the digit within the
+ *                                    integer (multiple of 4)
+ *
+ * RETURN:      The converted Ascii character
+ *
+ * DESCRIPTION: Convert a hex digit to an Ascii character
+ *
+ ******************************************************************************/
+
+char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
+{
+
+	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_hex_char_to_value
+ *
+ * PARAMETERS:  ascii_char            - Hex character in Ascii
+ *
+ * RETURN:      The binary value of the ascii/hex character
+ *
+ * DESCRIPTION: Perform ascii-to-hex translation
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_ascii_char_to_hex(int hex_char)
+{
+
+	if (hex_char <= 0x39) {
+		return ((u8)(hex_char - 0x30));
+	}
+
+	if (hex_char <= 0x46) {
+		return ((u8)(hex_char - 0x37));
+	}
+
+	return ((u8)(hex_char - 0x57));
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utinit.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utinit.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utinit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utinit.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,6 +102,151 @@ static void acpi_ut_free_gpe_lists(void)
 }
 #endif				/* !ACPI_REDUCED_HARDWARE */
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_init_globals
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize ACPICA globals. All globals that require specific
+ *              initialization should be initialized here. This allows for
+ *              a warm restart.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_init_globals(void)
+{
+	acpi_status status;
+	u32 i;
+
+	ACPI_FUNCTION_TRACE(ut_init_globals);
+
+	/* Create all memory caches */
+
+	status = acpi_ut_create_caches();
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Address Range lists */
+
+	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+		acpi_gbl_address_range_list[i] = NULL;
+	}
+
+	/* Mutex locked flags */
+
+	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
+		acpi_gbl_mutex_info[i].mutex = NULL;
+		acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+		acpi_gbl_mutex_info[i].use_count = 0;
+	}
+
+	for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
+		acpi_gbl_owner_id_mask[i] = 0;
+	}
+
+	/* Last owner_ID is never valid */
+
+	acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
+
+	/* Event counters */
+
+	acpi_method_count = 0;
+	acpi_sci_count = 0;
+	acpi_gpe_count = 0;
+
+	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+		acpi_fixed_event_count[i] = 0;
+	}
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+	/* GPE/SCI support */
+
+	acpi_gbl_all_gpes_initialized = FALSE;
+	acpi_gbl_gpe_xrupt_list_head = NULL;
+	acpi_gbl_gpe_fadt_blocks[0] = NULL;
+	acpi_gbl_gpe_fadt_blocks[1] = NULL;
+	acpi_current_gpe_count = 0;
+
+	acpi_gbl_global_event_handler = NULL;
+	acpi_gbl_sci_handler_list = NULL;
+
+#endif				/* !ACPI_REDUCED_HARDWARE */
+
+	/* Global handlers */
+
+	acpi_gbl_global_notify[0].handler = NULL;
+	acpi_gbl_global_notify[1].handler = NULL;
+	acpi_gbl_exception_handler = NULL;
+	acpi_gbl_init_handler = NULL;
+	acpi_gbl_table_handler = NULL;
+	acpi_gbl_interface_handler = NULL;
+
+	/* Global Lock support */
+
+	acpi_gbl_global_lock_semaphore = NULL;
+	acpi_gbl_global_lock_mutex = NULL;
+	acpi_gbl_global_lock_acquired = FALSE;
+	acpi_gbl_global_lock_handle = 0;
+	acpi_gbl_global_lock_present = FALSE;
+
+	/* Miscellaneous variables */
+
+	acpi_gbl_DSDT = NULL;
+	acpi_gbl_cm_single_step = FALSE;
+	acpi_gbl_shutdown = FALSE;
+	acpi_gbl_ns_lookup_count = 0;
+	acpi_gbl_ps_find_count = 0;
+	acpi_gbl_acpi_hardware_present = TRUE;
+	acpi_gbl_last_owner_id_index = 0;
+	acpi_gbl_next_owner_id_offset = 0;
+	acpi_gbl_trace_dbg_level = 0;
+	acpi_gbl_trace_dbg_layer = 0;
+	acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
+	acpi_gbl_osi_mutex = NULL;
+	acpi_gbl_reg_methods_executed = FALSE;
+
+	/* Hardware oriented */
+
+	acpi_gbl_events_initialized = FALSE;
+	acpi_gbl_system_awake_and_running = TRUE;
+
+	/* Namespace */
+
+	acpi_gbl_module_code_list = NULL;
+	acpi_gbl_root_node = NULL;
+	acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
+	acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
+	acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
+	acpi_gbl_root_node_struct.parent = NULL;
+	acpi_gbl_root_node_struct.child = NULL;
+	acpi_gbl_root_node_struct.peer = NULL;
+	acpi_gbl_root_node_struct.object = NULL;
+
+#ifdef ACPI_DISASSEMBLER
+	acpi_gbl_external_list = NULL;
+	acpi_gbl_num_external_methods = 0;
+	acpi_gbl_resolved_external_methods = 0;
+#endif
+
+#ifdef ACPI_DEBUG_OUTPUT
+	acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX);
+#endif
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+	acpi_gbl_display_final_mem_stats = FALSE;
+	acpi_gbl_disable_mem_tracking = FALSE;
+#endif
+
+	ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
+
+	return_ACPI_STATUS(AE_OK);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_ut_terminate
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utprint.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utprint.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utprint.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utprint.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,664 @@
+/******************************************************************************
+ *
+ * Module Name: utprint - Formatted printing routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utprint")
+
+#define ACPI_FORMAT_SIGN            0x01
+#define ACPI_FORMAT_SIGN_PLUS       0x02
+#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
+#define ACPI_FORMAT_ZERO            0x08
+#define ACPI_FORMAT_LEFT            0x10
+#define ACPI_FORMAT_UPPER           0x20
+#define ACPI_FORMAT_PREFIX          0x40
+/* Local prototypes */
+static acpi_size
+acpi_ut_bound_string_length(const char *string, acpi_size count);
+
+static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
+
+static char *acpi_ut_format_number(char *string,
+				   char *end,
+				   u64 number,
+				   u8 base, s32 width, s32 precision, u8 type);
+
+static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
+
+/* Module globals */
+
+static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
+static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_bound_string_length
+ *
+ * PARAMETERS:  string              - String with boundary
+ *              count               - Boundary of the string
+ *
+ * RETURN:      Length of the string. Less than or equal to Count.
+ *
+ * DESCRIPTION: Calculate the length of a string with boundary.
+ *
+ ******************************************************************************/
+
+static acpi_size
+acpi_ut_bound_string_length(const char *string, acpi_size count)
+{
+	u32 length = 0;
+
+	while (*string && count) {
+		length++;
+		string++;
+		count--;
+	}
+
+	return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_bound_string_output
+ *
+ * PARAMETERS:  string              - String with boundary
+ *              end                 - Boundary of the string
+ *              c                   - Character to be output to the string
+ *
+ * RETURN:      Updated position for next valid character
+ *
+ * DESCRIPTION: Output a character into a string with boundary check.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
+{
+
+	if (string < end) {
+		*string = c;
+	}
+
+	++string;
+	return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_put_number
+ *
+ * PARAMETERS:  string              - Buffer to hold reverse-ordered string
+ *              number              - Integer to be converted
+ *              base                - Base of the integer
+ *              upper               - Whether or not using upper cased digits
+ *
+ * RETURN:      Updated position for next valid character
+ *
+ * DESCRIPTION: Convert an integer into a string, note that, the string holds a
+ *              reversed ordered number without the trailing zero.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
+{
+	const char *digits;
+	u64 digit_index;
+	char *pos;
+
+	pos = string;
+	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
+
+	if (number == 0) {
+		*(pos++) = '0';
+	} else {
+		while (number) {
+			(void)acpi_ut_divide(number, base, &number,
+					     &digit_index);
+			*(pos++) = digits[digit_index];
+		}
+	}
+
+	/* *(Pos++) = '0'; */
+	return (pos);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_scan_number
+ *
+ * PARAMETERS:  string              - String buffer
+ *              number_ptr          - Where the number is returned
+ *
+ * RETURN:      Updated position for next valid character
+ *
+ * DESCRIPTION: Scan a string for a decimal integer.
+ *
+ ******************************************************************************/
+
+const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
+{
+	u64 number = 0;
+
+	while (ACPI_IS_DIGIT(*string)) {
+		number *= 10;
+		number += *(string++) - '0';
+	}
+
+	*number_ptr = number;
+	return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_print_number
+ *
+ * PARAMETERS:  string              - String buffer
+ *              number              - The number to be converted
+ *
+ * RETURN:      Updated position for next valid character
+ *
+ * DESCRIPTION: Print a decimal integer into a string.
+ *
+ ******************************************************************************/
+
+const char *acpi_ut_print_number(char *string, u64 number)
+{
+	char ascii_string[20];
+	const char *pos1;
+	char *pos2;
+
+	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
+	pos2 = string;
+
+	while (pos1 != ascii_string) {
+		*(pos2++) = *(--pos1);
+	}
+
+	*pos2 = 0;
+	return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_format_number
+ *
+ * PARAMETERS:  string              - String buffer with boundary
+ *              end                 - Boundary of the string
+ *              number              - The number to be converted
+ *              base                - Base of the integer
+ *              width               - Field width
+ *              precision           - Precision of the integer
+ *              type                - Special printing flags
+ *
+ * RETURN:      Updated position for next valid character
+ *
+ * DESCRIPTION: Print an integer into a string with any base and any precision.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_format_number(char *string,
+				   char *end,
+				   u64 number,
+				   u8 base, s32 width, s32 precision, u8 type)
+{
+	char *pos;
+	char sign;
+	char zero;
+	u8 need_prefix;
+	u8 upper;
+	s32 i;
+	char reversed_string[66];
+
+	/* Parameter validation */
+
+	if (base < 2 || base > 16) {
+		return (NULL);
+	}
+
+	if (type & ACPI_FORMAT_LEFT) {
+		type &= ~ACPI_FORMAT_ZERO;
+	}
+
+	need_prefix = ((type & ACPI_FORMAT_PREFIX)
+		       && base != 10) ? TRUE : FALSE;
+	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
+	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
+
+	/* Calculate size according to sign and prefix */
+
+	sign = '\0';
+	if (type & ACPI_FORMAT_SIGN) {
+		if ((s64) number < 0) {
+			sign = '-';
+			number = -(s64) number;
+			width--;
+		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
+			sign = '+';
+			width--;
+		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
+			sign = ' ';
+			width--;
+		}
+	}
+	if (need_prefix) {
+		width--;
+		if (base == 16) {
+			width--;
+		}
+	}
+
+	/* Generate full string in reverse order */
+
+	pos = acpi_ut_put_number(reversed_string, number, base, upper);
+	i = ACPI_PTR_DIFF(pos, reversed_string);
+
+	/* Printing 100 using %2d gives "100", not "00" */
+
+	if (i > precision) {
+		precision = i;
+	}
+
+	width -= precision;
+
+	/* Output the string */
+
+	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
+		while (--width >= 0) {
+			string = acpi_ut_bound_string_output(string, end, ' ');
+		}
+	}
+	if (sign) {
+		string = acpi_ut_bound_string_output(string, end, sign);
+	}
+	if (need_prefix) {
+		string = acpi_ut_bound_string_output(string, end, '0');
+		if (base == 16) {
+			string = acpi_ut_bound_string_output(string, end,
+							     upper ? 'X' : 'x');
+		}
+	}
+	if (!(type & ACPI_FORMAT_LEFT)) {
+		while (--width >= 0) {
+			string = acpi_ut_bound_string_output(string, end, zero);
+		}
+	}
+
+	while (i <= --precision) {
+		string = acpi_ut_bound_string_output(string, end, '0');
+	}
+	while (--i >= 0) {
+		string = acpi_ut_bound_string_output(string, end,
+						     reversed_string[i]);
+	}
+	while (--width >= 0) {
+		string = acpi_ut_bound_string_output(string, end, ' ');
+	}
+
+	return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_vsnprintf
+ *
+ * PARAMETERS:  string              - String with boundary
+ *              size                - Boundary of the string
+ *              format              - Standard printf format
+ *              args                - Argument list
+ *
+ * RETURN:      Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a string using argument list pointer.
+ *
+ ******************************************************************************/
+
+int
+acpi_ut_vsnprintf(char *string,
+		  acpi_size size, const char *format, va_list args)
+{
+	u8 base = 10;
+	u8 type = 0;
+	s32 width = -1;
+	s32 precision = -1;
+	char qualifier = 0;
+	u64 number;
+	char *pos;
+	char *end;
+	char c;
+	const char *s;
+	const void *p;
+	s32 length;
+	int i;
+
+	pos = string;
+	end = string + size;
+
+	for (; *format; ++format) {
+		if (*format != '%') {
+			pos = acpi_ut_bound_string_output(pos, end, *format);
+			continue;
+		}
+
+		/* Process sign */
+
+		do {
+			++format;
+			if (*format == '#') {
+				type |= ACPI_FORMAT_PREFIX;
+			} else if (*format == '0') {
+				type |= ACPI_FORMAT_ZERO;
+			} else if (*format == '+') {
+				type |= ACPI_FORMAT_SIGN_PLUS;
+			} else if (*format == ' ') {
+				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
+			} else if (*format == '-') {
+				type |= ACPI_FORMAT_LEFT;
+			} else {
+				break;
+			}
+		} while (1);
+
+		/* Process width */
+
+		width = -1;
+		if (ACPI_IS_DIGIT(*format)) {
+			format = acpi_ut_scan_number(format, &number);
+			width = (s32) number;
+		} else if (*format == '*') {
+			++format;
+			width = va_arg(args, int);
+			if (width < 0) {
+				width = -width;
+				type |= ACPI_FORMAT_LEFT;
+			}
+		}
+
+		/* Process precision */
+
+		precision = -1;
+		if (*format == '.') {
+			++format;
+			if (ACPI_IS_DIGIT(*format)) {
+				format = acpi_ut_scan_number(format, &number);
+				precision = (s32) number;
+			} else if (*format == '*') {
+				++format;
+				precision = va_arg(args, int);
+			}
+			if (precision < 0) {
+				precision = 0;
+			}
+		}
+
+		/* Process qualifier */
+
+		qualifier = -1;
+		if (*format == 'h' || *format == 'l' || *format == 'L') {
+			qualifier = *format;
+			++format;
+
+			if (qualifier == 'l' && *format == 'l') {
+				qualifier = 'L';
+				++format;
+			}
+		}
+
+		switch (*format) {
+		case '%':
+
+			pos = acpi_ut_bound_string_output(pos, end, '%');
+			continue;
+
+		case 'c':
+
+			if (!(type & ACPI_FORMAT_LEFT)) {
+				while (--width > 0) {
+					pos =
+					    acpi_ut_bound_string_output(pos,
+									end,
+									' ');
+				}
+			}
+
+			c = (char)va_arg(args, int);
+			pos = acpi_ut_bound_string_output(pos, end, c);
+
+			while (--width > 0) {
+				pos =
+				    acpi_ut_bound_string_output(pos, end, ' ');
+			}
+			continue;
+
+		case 's':
+
+			s = va_arg(args, char *);
+			if (!s) {
+				s = "<NULL>";
+			}
+			length = acpi_ut_bound_string_length(s, precision);
+			if (!(type & ACPI_FORMAT_LEFT)) {
+				while (length < width--) {
+					pos =
+					    acpi_ut_bound_string_output(pos,
+									end,
+									' ');
+				}
+			}
+			for (i = 0; i < length; ++i) {
+				pos = acpi_ut_bound_string_output(pos, end, *s);
+				++s;
+			}
+			while (length < width--) {
+				pos =
+				    acpi_ut_bound_string_output(pos, end, ' ');
+			}
+			continue;
+
+		case 'o':
+
+			base = 8;
+			break;
+
+		case 'X':
+
+			type |= ACPI_FORMAT_UPPER;
+
+		case 'x':
+
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+
+			type |= ACPI_FORMAT_SIGN;
+
+		case 'u':
+
+			break;
+
+		case 'p':
+
+			if (width == -1) {
+				width = 2 * sizeof(void *);
+				type |= ACPI_FORMAT_ZERO;
+			}
+
+			p = va_arg(args, void *);
+			pos = acpi_ut_format_number(pos, end,
+						    ACPI_TO_INTEGER(p), 16,
+						    width, precision, type);
+			continue;
+
+		default:
+
+			pos = acpi_ut_bound_string_output(pos, end, '%');
+			if (*format) {
+				pos =
+				    acpi_ut_bound_string_output(pos, end,
+								*format);
+			} else {
+				--format;
+			}
+			continue;
+		}
+
+		if (qualifier == 'L') {
+			number = va_arg(args, u64);
+			if (type & ACPI_FORMAT_SIGN) {
+				number = (s64) number;
+			}
+		} else if (qualifier == 'l') {
+			number = va_arg(args, unsigned long);
+			if (type & ACPI_FORMAT_SIGN) {
+				number = (s32) number;
+			}
+		} else if (qualifier == 'h') {
+			number = (u16)va_arg(args, int);
+			if (type & ACPI_FORMAT_SIGN) {
+				number = (s16) number;
+			}
+		} else {
+			number = va_arg(args, unsigned int);
+			if (type & ACPI_FORMAT_SIGN) {
+				number = (signed int)number;
+			}
+		}
+
+		pos = acpi_ut_format_number(pos, end, number, base,
+					    width, precision, type);
+	}
+
+	if (size > 0) {
+		if (pos < end) {
+			*pos = '\0';
+		} else {
+			end[-1] = '\0';
+		}
+	}
+
+	return (ACPI_PTR_DIFF(pos, string));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_snprintf
+ *
+ * PARAMETERS:  string              - String with boundary
+ *              size                - Boundary of the string
+ *              Format, ...         - Standard printf format
+ *
+ * RETURN:      Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a string.
+ *
+ ******************************************************************************/
+
+int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
+{
+	va_list args;
+	int length;
+
+	va_start(args, format);
+	length = acpi_ut_vsnprintf(string, size, format, args);
+	va_end(args);
+
+	return (length);
+}
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_file_vprintf
+ *
+ * PARAMETERS:  file                - File descriptor
+ *              format              - Standard printf format
+ *              args                - Argument list
+ *
+ * RETURN:      Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a file using argument list pointer.
+ *
+ ******************************************************************************/
+
+int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
+{
+	acpi_cpu_flags flags;
+	int length;
+
+	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
+	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
+				   sizeof(acpi_gbl_print_buffer), format, args);
+
+	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
+	acpi_os_release_lock(acpi_gbl_print_lock, flags);
+
+	return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_file_printf
+ *
+ * PARAMETERS:  file                - File descriptor
+ *              Format, ...         - Standard printf format
+ *
+ * RETURN:      Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a file.
+ *
+ ******************************************************************************/
+
+int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
+{
+	va_list args;
+	int length;
+
+	va_start(args, format);
+	length = acpi_ut_file_vprintf(file, format, args);
+	va_end(args);
+
+	return (length);
+}
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpica/utuuid.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utuuid.c
--- linux-libre-3.16-gnu/drivers/acpi/acpica/utuuid.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpica/utuuid.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Module Name: utuuid -- UUID support functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_COMPILER
+ACPI_MODULE_NAME("utuuid")
+
+/*
+ * UUID support functions.
+ *
+ * This table is used to convert an input UUID ascii string to a 16 byte
+ * buffer and the reverse. The table maps a UUID buffer index 0-15 to
+ * the index within the 36-byte UUID string where the associated 2-byte
+ * hex value can be found.
+ *
+ * 36-byte UUID strings are of the form:
+ *     aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
+ * Where aa-pp are one byte hex numbers, made up of two hex digits
+ *
+ * Note: This table is basically the inverse of the string-to-offset table
+ * found in the ACPI spec in the description of the to_UUID macro.
+ */
+const u8 acpi_gbl_map_to_uuid_offset[UUID_BUFFER_LENGTH] = {
+	6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_convert_string_to_uuid
+ *
+ * PARAMETERS:  in_string           - 36-byte formatted UUID string
+ *              uuid_buffer         - Where the 16-byte UUID buffer is returned
+ *
+ * RETURN:      None. Output data is returned in the uuid_buffer
+ *
+ * DESCRIPTION: Convert a 36-byte formatted UUID string to 16-byte UUID buffer
+ *
+ ******************************************************************************/
+
+void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer)
+{
+	u32 i;
+
+	for (i = 0; i < UUID_BUFFER_LENGTH; i++) {
+		uuid_buffer[i] =
+		    (acpi_ut_ascii_char_to_hex
+		     (in_string[acpi_gbl_map_to_uuid_offset[i]]) << 4);
+
+		uuid_buffer[i] |=
+		    acpi_ut_ascii_char_to_hex(in_string
+					      [acpi_gbl_map_to_uuid_offset[i] +
+					       1]);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpi_cmos_rtc.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_cmos_rtc.c
--- linux-libre-3.16-gnu/drivers/acpi/acpi_cmos_rtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_cmos_rtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@ acpi_cmos_rtc_space_handler(u32 function
 		      void *handler_context, void *region_context)
 {
 	int i;
-	u8 *value = (u8 *)&value64;
+	u8 *value = (u8 *)value64;
 
 	if (address > 0xff || !value64)
 		return AE_BAD_PARAMETER;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpi_extlog.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_extlog.c
--- linux-libre-3.16-gnu/drivers/acpi/acpi_extlog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_extlog.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,10 +12,12 @@
 #include <linux/cper.h>
 #include <linux/ratelimit.h>
 #include <linux/edac.h>
+#include <linux/ras.h>
 #include <asm/cpu.h>
 #include <asm/mce.h>
 
 #include "apei/apei-internal.h"
+#include <ras/ras_event.h>
 
 #define EXT_ELOG_ENTRY_MASK	GENMASK_ULL(51, 0) /* elog entry address mask */
 
@@ -69,11 +71,11 @@ static u32 l1_percpu_entry;
 #define ELOG_ENTRY_ADDR(phyaddr) \
 	(phyaddr - elog_base + (u8 *)elog_addr)
 
-static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank)
+static struct acpi_hest_generic_status *extlog_elog_entry_check(int cpu, int bank)
 {
 	int idx;
 	u64 data;
-	struct acpi_generic_status *estatus;
+	struct acpi_hest_generic_status *estatus;
 
 	WARN_ON(cpu < 0);
 	idx = ELOG_IDX(cpu, bank);
@@ -82,7 +84,7 @@ static struct acpi_generic_status *extlo
 		return NULL;
 
 	data &= EXT_ELOG_ENTRY_MASK;
-	estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data);
+	estatus = (struct acpi_hest_generic_status *)ELOG_ENTRY_ADDR(data);
 
 	/* if no valid data in elog entry, just return */
 	if (estatus->block_status == 0)
@@ -92,7 +94,7 @@ static struct acpi_generic_status *extlo
 }
 
 static void __print_extlog_rcd(const char *pfx,
-			       struct acpi_generic_status *estatus, int cpu)
+			       struct acpi_hest_generic_status *estatus, int cpu)
 {
 	static atomic_t seqno;
 	unsigned int curr_seqno;
@@ -111,7 +113,7 @@ static void __print_extlog_rcd(const cha
 }
 
 static int print_extlog_rcd(const char *pfx,
-			    struct acpi_generic_status *estatus, int cpu)
+			    struct acpi_hest_generic_status *estatus, int cpu)
 {
 	/* Not more than 2 messages every 5 seconds */
 	static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -137,8 +139,12 @@ static int extlog_print(struct notifier_
 	struct mce *mce = (struct mce *)data;
 	int	bank = mce->bank;
 	int	cpu = mce->extcpu;
-	struct acpi_generic_status *estatus;
-	int rc;
+	struct acpi_hest_generic_status *estatus, *tmp;
+	struct acpi_hest_generic_data *gdata;
+	const uuid_le *fru_id = &NULL_UUID_LE;
+	char *fru_text = "";
+	uuid_le *sec_type;
+	static u32 err_seq;
 
 	estatus = extlog_elog_entry_check(cpu, bank);
 	if (estatus == NULL)
@@ -148,8 +154,29 @@ static int extlog_print(struct notifier_
 	/* clear record status to enable BIOS to update it again */
 	estatus->block_status = 0;
 
-	rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu);
+	tmp = (struct acpi_hest_generic_status *)elog_buf;
+
+	if (!ras_userspace_consumers()) {
+		print_extlog_rcd(NULL, tmp, cpu);
+		goto out;
+	}
+
+	/* log event via trace */
+	err_seq++;
+	gdata = (struct acpi_hest_generic_data *)(tmp + 1);
+	if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+		fru_id = (uuid_le *)gdata->fru_id;
+	if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+		fru_text = gdata->fru_text;
+	sec_type = (uuid_le *)gdata->section_type;
+	if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
+		struct cper_sec_mem_err *mem = (void *)(gdata + 1);
+		if (gdata->error_data_length >= sizeof(*mem))
+			trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
+					       (u8)gdata->error_severity);
+	}
 
+out:
 	return NOTIFY_STOP;
 }
 
@@ -196,19 +223,16 @@ static int __init extlog_init(void)
 	u64 cap;
 	int rc;
 
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+
+	if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr())
+		return -ENODEV;
+
 	if (get_edac_report_status() == EDAC_REPORTING_FORCE) {
 		pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n");
 		return -EPERM;
 	}
 
-	rc = -ENODEV;
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	if (!(cap & MCG_ELOG_P))
-		return rc;
-
-	if (!extlog_get_l1addr())
-		return rc;
-
 	rc = -EINVAL;
 	/* get L1 header to fetch necessary information */
 	l1_hdr_size = sizeof(struct extlog_l1_head);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpi_lpss.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_lpss.c
--- linux-libre-3.16-gnu/drivers/acpi/acpi_lpss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_lpss.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,6 +113,14 @@ static void lpss_i2c_setup(struct lpss_p
 	writel(val, pdata->mmio_base + offset);
 }
 
+static struct lpss_device_desc wpt_dev_desc = {
+	.clk_required = true,
+	.prv_offset = 0x800,
+	.ltr_required = true,
+	.clk_divider = true,
+	.clk_gate = true,
+};
+
 static struct lpss_device_desc lpt_dev_desc = {
 	.clk_required = true,
 	.prv_offset = 0x800,
@@ -188,6 +196,17 @@ static struct lpss_device_desc byt_i2c_d
 	.setup = lpss_i2c_setup,
 };
 
+static struct lpss_shared_clock bsw_pwm_clock = {
+	.name = "pwm_clk",
+	.rate = 19200000,
+};
+
+static struct lpss_device_desc bsw_pwm_dev_desc = {
+	.clk_required = true,
+	.save_ctx = true,
+	.shared_clock = &bsw_pwm_clock,
+};
+
 #else
 
 #define LPSS_ADDR(desc) (0UL)
@@ -217,6 +236,12 @@ static const struct acpi_device_id acpi_
 	{ "INT33B2", },
 	{ "INT33FC", },
 
+	/* Braswell LPSS devices */
+	{ "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
+	{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
+	{ "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
+	{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
+
 	{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
 	{ "INT3431", LPSS_ADDR(lpt_dev_desc) },
 	{ "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
@@ -226,6 +251,8 @@ static const struct acpi_device_id acpi_
 	{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
 	{ "INT3437", },
 
+	{ "INT3438", LPSS_ADDR(wpt_dev_desc) },
+
 	{ }
 };
 
@@ -392,7 +419,6 @@ static int acpi_lpss_create_device(struc
 	adev->driver_data = pdata;
 	pdev = acpi_create_platform_device(adev);
 	if (!IS_ERR_OR_NULL(pdev)) {
-		device_enable_async_suspend(&pdev->dev);
 		return 1;
 	}
 
@@ -583,7 +609,7 @@ static int acpi_lpss_suspend_late(struct
 	return acpi_dev_suspend_late(dev);
 }
 
-static int acpi_lpss_restore_early(struct device *dev)
+static int acpi_lpss_resume_early(struct device *dev)
 {
 	int ret = acpi_dev_resume_early(dev);
 
@@ -623,15 +649,15 @@ static int acpi_lpss_runtime_resume(stru
 static struct dev_pm_domain acpi_lpss_pm_domain = {
 	.ops = {
 #ifdef CONFIG_PM_SLEEP
-		.suspend_late = acpi_lpss_suspend_late,
-		.restore_early = acpi_lpss_restore_early,
 		.prepare = acpi_subsys_prepare,
 		.complete = acpi_subsys_complete,
 		.suspend = acpi_subsys_suspend,
-		.resume_early = acpi_subsys_resume_early,
+		.suspend_late = acpi_lpss_suspend_late,
+		.resume_early = acpi_lpss_resume_early,
 		.freeze = acpi_subsys_freeze,
 		.poweroff = acpi_subsys_suspend,
-		.poweroff_late = acpi_subsys_suspend_late,
+		.poweroff_late = acpi_lpss_suspend_late,
+		.restore_early = acpi_lpss_resume_early,
 #endif
 #ifdef CONFIG_PM_RUNTIME
 		.runtime_suspend = acpi_lpss_runtime_suspend,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpi_pnp.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_pnp.c
--- linux-libre-3.16-gnu/drivers/acpi/acpi_pnp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_pnp.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
 
 #include <linux/acpi.h>
 #include <linux/module.h>
+#include <linux/ctype.h>
 
 static const struct acpi_device_id acpi_pnp_device_ids[] = {
 	/* soc_button_array */
@@ -320,11 +321,6 @@ static const struct acpi_device_id acpi_
 	{""},
 };
 
-static bool is_hex_digit(char c)
-{
-	return (c >= 0 && c <= '9') || (c >= 'A' && c <= 'F');
-}
-
 static bool matching_id(char *idstr, char *list_id)
 {
 	int i;
@@ -335,7 +331,7 @@ static bool matching_id(char *idstr, cha
 	for (i = 3; i < 7; i++) {
 		char c = toupper(idstr[i]);
 
-		if (!is_hex_digit(c)
+		if (!isxdigit(c)
 		    || (list_id[i] != 'X' && c != toupper(list_id[i])))
 			return false;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/acpi_processor.c linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_processor.c
--- linux-libre-3.16-gnu/drivers/acpi/acpi_processor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/acpi_processor.c	2014-09-28 17:29:07.000000000 -0400
@@ -268,7 +268,7 @@ static int acpi_processor_get_info(struc
 	pr->apic_id = apic_id;
 
 	cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
-	if (!cpu0_initialized && !acpi_lapic) {
+	if (!cpu0_initialized && !acpi_has_cpu_in_madt()) {
 		cpu0_initialized = 1;
 		/* Handle UP system running SMP kernel, with no LAPIC in MADT */
 		if ((cpu_index == -1) && (num_online_cpus() == 1))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/apei/apei-base.c linux-libre-3.17-rc7-gnu/drivers/acpi/apei/apei-base.c
--- linux-libre-3.16-gnu/drivers/acpi/apei/apei-base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/apei/apei-base.c	2014-09-28 17:29:07.000000000 -0400
@@ -745,6 +745,19 @@ struct dentry *apei_get_debugfs_dir(void
 }
 EXPORT_SYMBOL_GPL(apei_get_debugfs_dir);
 
+int __weak arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr,
+				  void *data)
+{
+	return 1;
+}
+EXPORT_SYMBOL_GPL(arch_apei_enable_cmcff);
+
+void __weak arch_apei_report_mem_error(int sev,
+				       struct cper_sec_mem_err *mem_err)
+{
+}
+EXPORT_SYMBOL_GPL(arch_apei_report_mem_error);
+
 int apei_osc_setup(void)
 {
 	static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c";
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/apei/apei-internal.h linux-libre-3.17-rc7-gnu/drivers/acpi/apei/apei-internal.h
--- linux-libre-3.16-gnu/drivers/acpi/apei/apei-internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/apei/apei-internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -121,11 +121,11 @@ struct dentry;
 struct dentry *apei_get_debugfs_dir(void);
 
 #define apei_estatus_for_each_section(estatus, section)			\
-	for (section = (struct acpi_generic_data *)(estatus + 1);	\
+	for (section = (struct acpi_hest_generic_data *)(estatus + 1);	\
 	     (void *)section - (void *)estatus < estatus->data_length;	\
 	     section = (void *)(section+1) + section->error_data_length)
 
-static inline u32 cper_estatus_len(struct acpi_generic_status *estatus)
+static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus)
 {
 	if (estatus->raw_data_length)
 		return estatus->raw_data_offset + \
@@ -135,9 +135,9 @@ static inline u32 cper_estatus_len(struc
 }
 
 void cper_estatus_print(const char *pfx,
-			const struct acpi_generic_status *estatus);
-int cper_estatus_check_header(const struct acpi_generic_status *estatus);
-int cper_estatus_check(const struct acpi_generic_status *estatus);
+			const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check(const struct acpi_hest_generic_status *estatus);
 
 int apei_osc_setup(void);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/apei/ghes.c linux-libre-3.17-rc7-gnu/drivers/acpi/apei/ghes.c
--- linux-libre-3.16-gnu/drivers/acpi/apei/ghes.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/apei/ghes.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,11 +47,11 @@
 #include <linux/genalloc.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
+#include <linux/nmi.h>
 
 #include <acpi/ghes.h>
-#include <asm/mce.h>
+#include <acpi/apei.h>
 #include <asm/tlbflush.h>
-#include <asm/nmi.h>
 
 #include "apei-internal.h"
 
@@ -74,20 +74,18 @@
 #define GHES_ESTATUS_CACHE_LEN(estatus_len)			\
 	(sizeof(struct ghes_estatus_cache) + (estatus_len))
 #define GHES_ESTATUS_FROM_CACHE(estatus_cache)			\
-	((struct acpi_generic_status *)				\
+	((struct acpi_hest_generic_status *)				\
 	 ((struct ghes_estatus_cache *)(estatus_cache) + 1))
 
 #define GHES_ESTATUS_NODE_LEN(estatus_len)			\
 	(sizeof(struct ghes_estatus_node) + (estatus_len))
 #define GHES_ESTATUS_FROM_NODE(estatus_node)			\
-	((struct acpi_generic_status *)				\
+	((struct acpi_hest_generic_status *)				\
 	 ((struct ghes_estatus_node *)(estatus_node) + 1))
 
 bool ghes_disable;
 module_param_named(disable, ghes_disable, bool, 0);
 
-static int ghes_panic_timeout	__read_mostly = 30;
-
 /*
  * All error sources notified with SCI shares one notifier function,
  * so they need to be linked and checked one by one.  This is applied
@@ -97,16 +95,9 @@ static int ghes_panic_timeout	__read_mos
  * list changing, not for traversing.
  */
 static LIST_HEAD(ghes_sci);
-static LIST_HEAD(ghes_nmi);
 static DEFINE_MUTEX(ghes_list_mutex);
 
 /*
- * NMI may be triggered on any CPU, so ghes_nmi_lock is used for
- * mutual exclusion.
- */
-static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
-
-/*
  * Because the memory area used to transfer hardware error information
  * from BIOS to Linux can be determined only in NMI, IRQ or timer
  * handler, but general ioremap can not be used in atomic context, so
@@ -114,12 +105,16 @@ static DEFINE_RAW_SPINLOCK(ghes_nmi_lock
  */
 
 /*
- * Two virtual pages are used, one for NMI context, the other for
- * IRQ/PROCESS context
+ * Two virtual pages are used, one for IRQ/PROCESS context, the other for
+ * NMI context (optionally).
  */
-#define GHES_IOREMAP_PAGES		2
-#define GHES_IOREMAP_NMI_PAGE(base)	(base)
-#define GHES_IOREMAP_IRQ_PAGE(base)	((base) + PAGE_SIZE)
+#ifdef CONFIG_HAVE_ACPI_APEI_NMI
+#define GHES_IOREMAP_PAGES           2
+#else
+#define GHES_IOREMAP_PAGES           1
+#endif
+#define GHES_IOREMAP_IRQ_PAGE(base)	(base)
+#define GHES_IOREMAP_NMI_PAGE(base)	((base) + PAGE_SIZE)
 
 /* virtual memory area for atomic ioremap */
 static struct vm_struct *ghes_ioremap_area;
@@ -130,18 +125,8 @@ static struct vm_struct *ghes_ioremap_ar
 static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
 static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
 
-/*
- * printk is not safe in NMI context.  So in NMI handler, we allocate
- * required memory from lock-less memory allocator
- * (ghes_estatus_pool), save estatus into it, put them into lock-less
- * list (ghes_estatus_llist), then delay printk into IRQ context via
- * irq_work (ghes_proc_irq_work).  ghes_estatus_size_request record
- * required pool size by all NMI error source.
- */
 static struct gen_pool *ghes_estatus_pool;
 static unsigned long ghes_estatus_pool_size_request;
-static struct llist_head ghes_estatus_llist;
-static struct irq_work ghes_proc_irq_work;
 
 struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
 static atomic_t ghes_estatus_cache_alloced;
@@ -192,7 +177,7 @@ static void ghes_iounmap_nmi(void __iome
 
 	BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
 	unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
-	__flush_tlb_one(vaddr);
+	arch_apei_flush_tlb_one(vaddr);
 }
 
 static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
@@ -202,7 +187,7 @@ static void ghes_iounmap_irq(void __iome
 
 	BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
 	unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
-	__flush_tlb_one(vaddr);
+	arch_apei_flush_tlb_one(vaddr);
 }
 
 static int ghes_estatus_pool_init(void)
@@ -249,11 +234,6 @@ static int ghes_estatus_pool_expand(unsi
 	return 0;
 }
 
-static void ghes_estatus_pool_shrink(unsigned long len)
-{
-	ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
-}
-
 static struct ghes *ghes_new(struct acpi_hest_generic *generic)
 {
 	struct ghes *ghes;
@@ -408,7 +388,7 @@ static void ghes_clear_estatus(struct gh
 	ghes->flags &= ~GHES_TO_CLEAR;
 }
 
-static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
+static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
 {
 #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
 	unsigned long pfn;
@@ -441,10 +421,10 @@ static void ghes_handle_memory_failure(s
 }
 
 static void ghes_do_proc(struct ghes *ghes,
-			 const struct acpi_generic_status *estatus)
+			 const struct acpi_hest_generic_status *estatus)
 {
 	int sev, sec_sev;
-	struct acpi_generic_data *gdata;
+	struct acpi_hest_generic_data *gdata;
 
 	sev = ghes_severity(estatus->error_severity);
 	apei_estatus_for_each_section(estatus, gdata) {
@@ -455,9 +435,7 @@ static void ghes_do_proc(struct ghes *gh
 			mem_err = (struct cper_sec_mem_err *)(gdata+1);
 			ghes_edac_report_mem_error(ghes, sev, mem_err);
 
-#ifdef CONFIG_X86_MCE
-			apei_mce_report_mem_error(sev, mem_err);
-#endif
+			arch_apei_report_mem_error(sev, mem_err);
 			ghes_handle_memory_failure(gdata, sev);
 		}
 #ifdef CONFIG_ACPI_APEI_PCIEAER
@@ -498,7 +476,7 @@ static void ghes_do_proc(struct ghes *gh
 
 static void __ghes_print_estatus(const char *pfx,
 				 const struct acpi_hest_generic *generic,
-				 const struct acpi_generic_status *estatus)
+				 const struct acpi_hest_generic_status *estatus)
 {
 	static atomic_t seqno;
 	unsigned int curr_seqno;
@@ -520,7 +498,7 @@ static void __ghes_print_estatus(const c
 
 static int ghes_print_estatus(const char *pfx,
 			      const struct acpi_hest_generic *generic,
-			      const struct acpi_generic_status *estatus)
+			      const struct acpi_hest_generic_status *estatus)
 {
 	/* Not more than 2 messages every 5 seconds */
 	static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -542,13 +520,13 @@ static int ghes_print_estatus(const char
  * GHES error status reporting throttle, to report more kinds of
  * errors, instead of just most frequently occurred errors.
  */
-static int ghes_estatus_cached(struct acpi_generic_status *estatus)
+static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus)
 {
 	u32 len;
 	int i, cached = 0;
 	unsigned long long now;
 	struct ghes_estatus_cache *cache;
-	struct acpi_generic_status *cache_estatus;
+	struct acpi_hest_generic_status *cache_estatus;
 
 	len = cper_estatus_len(estatus);
 	rcu_read_lock();
@@ -573,12 +551,12 @@ static int ghes_estatus_cached(struct ac
 
 static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
 	struct acpi_hest_generic *generic,
-	struct acpi_generic_status *estatus)
+	struct acpi_hest_generic_status *estatus)
 {
 	int alloced;
 	u32 len, cache_len;
 	struct ghes_estatus_cache *cache;
-	struct acpi_generic_status *cache_estatus;
+	struct acpi_hest_generic_status *cache_estatus;
 
 	alloced = atomic_add_return(1, &ghes_estatus_cache_alloced);
 	if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) {
@@ -621,7 +599,7 @@ static void ghes_estatus_cache_rcu_free(
 
 static void ghes_estatus_cache_add(
 	struct acpi_hest_generic *generic,
-	struct acpi_generic_status *estatus)
+	struct acpi_hest_generic_status *estatus)
 {
 	int i, slot = -1, count;
 	unsigned long long now, duration, period, max_period = 0;
@@ -734,6 +712,32 @@ static int ghes_notify_sci(struct notifi
 	return ret;
 }
 
+static struct notifier_block ghes_notifier_sci = {
+	.notifier_call = ghes_notify_sci,
+};
+
+#ifdef CONFIG_HAVE_ACPI_APEI_NMI
+/*
+ * printk is not safe in NMI context.  So in NMI handler, we allocate
+ * required memory from lock-less memory allocator
+ * (ghes_estatus_pool), save estatus into it, put them into lock-less
+ * list (ghes_estatus_llist), then delay printk into IRQ context via
+ * irq_work (ghes_proc_irq_work).  ghes_estatus_size_request record
+ * required pool size by all NMI error source.
+ */
+static struct llist_head ghes_estatus_llist;
+static struct irq_work ghes_proc_irq_work;
+
+/*
+ * NMI may be triggered on any CPU, so ghes_nmi_lock is used for
+ * mutual exclusion.
+ */
+static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
+
+static LIST_HEAD(ghes_nmi);
+
+static int ghes_panic_timeout	__read_mostly = 30;
+
 static struct llist_node *llist_nodes_reverse(struct llist_node *llnode)
 {
 	struct llist_node *next, *tail = NULL;
@@ -753,7 +757,7 @@ static void ghes_proc_in_irq(struct irq_
 	struct llist_node *llnode, *next;
 	struct ghes_estatus_node *estatus_node;
 	struct acpi_hest_generic *generic;
-	struct acpi_generic_status *estatus;
+	struct acpi_hest_generic_status *estatus;
 	u32 len, node_len;
 
 	llnode = llist_del_all(&ghes_estatus_llist);
@@ -786,7 +790,7 @@ static void ghes_print_queued_estatus(vo
 	struct llist_node *llnode;
 	struct ghes_estatus_node *estatus_node;
 	struct acpi_hest_generic *generic;
-	struct acpi_generic_status *estatus;
+	struct acpi_hest_generic_status *estatus;
 	u32 len, node_len;
 
 	llnode = llist_del_all(&ghes_estatus_llist);
@@ -845,7 +849,7 @@ static int ghes_notify_nmi(unsigned int
 #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
 		u32 len, node_len;
 		struct ghes_estatus_node *estatus_node;
-		struct acpi_generic_status *estatus;
+		struct acpi_hest_generic_status *estatus;
 #endif
 		if (!(ghes->flags & GHES_TO_CLEAR))
 			continue;
@@ -877,10 +881,6 @@ out:
 	return ret;
 }
 
-static struct notifier_block ghes_notifier_sci = {
-	.notifier_call = ghes_notify_sci,
-};
-
 static unsigned long ghes_esource_prealloc_size(
 	const struct acpi_hest_generic *generic)
 {
@@ -896,11 +896,71 @@ static unsigned long ghes_esource_preall
 	return prealloc_size;
 }
 
+static void ghes_estatus_pool_shrink(unsigned long len)
+{
+	ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
+}
+
+static void ghes_nmi_add(struct ghes *ghes)
+{
+	unsigned long len;
+
+	len = ghes_esource_prealloc_size(ghes->generic);
+	ghes_estatus_pool_expand(len);
+	mutex_lock(&ghes_list_mutex);
+	if (list_empty(&ghes_nmi))
+		register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, "ghes");
+	list_add_rcu(&ghes->list, &ghes_nmi);
+	mutex_unlock(&ghes_list_mutex);
+}
+
+static void ghes_nmi_remove(struct ghes *ghes)
+{
+	unsigned long len;
+
+	mutex_lock(&ghes_list_mutex);
+	list_del_rcu(&ghes->list);
+	if (list_empty(&ghes_nmi))
+		unregister_nmi_handler(NMI_LOCAL, "ghes");
+	mutex_unlock(&ghes_list_mutex);
+	/*
+	 * To synchronize with NMI handler, ghes can only be
+	 * freed after NMI handler finishes.
+	 */
+	synchronize_rcu();
+	len = ghes_esource_prealloc_size(ghes->generic);
+	ghes_estatus_pool_shrink(len);
+}
+
+static void ghes_nmi_init_cxt(void)
+{
+	init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
+}
+#else /* CONFIG_HAVE_ACPI_APEI_NMI */
+static inline void ghes_nmi_add(struct ghes *ghes)
+{
+	pr_err(GHES_PFX "ID: %d, trying to add NMI notification which is not supported!\n",
+	       ghes->generic->header.source_id);
+	BUG();
+}
+
+static inline void ghes_nmi_remove(struct ghes *ghes)
+{
+	pr_err(GHES_PFX "ID: %d, trying to remove NMI notification which is not supported!\n",
+	       ghes->generic->header.source_id);
+	BUG();
+}
+
+static inline void ghes_nmi_init_cxt(void)
+{
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_NMI */
+
 static int ghes_probe(struct platform_device *ghes_dev)
 {
 	struct acpi_hest_generic *generic;
 	struct ghes *ghes = NULL;
-	unsigned long len;
+
 	int rc = -EINVAL;
 
 	generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
@@ -911,7 +971,13 @@ static int ghes_probe(struct platform_de
 	case ACPI_HEST_NOTIFY_POLLED:
 	case ACPI_HEST_NOTIFY_EXTERNAL:
 	case ACPI_HEST_NOTIFY_SCI:
+		break;
 	case ACPI_HEST_NOTIFY_NMI:
+		if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
+			pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
+				generic->header.source_id);
+			goto err;
+		}
 		break;
 	case ACPI_HEST_NOTIFY_LOCAL:
 		pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
@@ -925,7 +991,7 @@ static int ghes_probe(struct platform_de
 
 	rc = -EIO;
 	if (generic->error_block_length <
-	    sizeof(struct acpi_generic_status)) {
+	    sizeof(struct acpi_hest_generic_status)) {
 		pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n",
 			   generic->error_block_length,
 			   generic->header.source_id);
@@ -972,14 +1038,7 @@ static int ghes_probe(struct platform_de
 		mutex_unlock(&ghes_list_mutex);
 		break;
 	case ACPI_HEST_NOTIFY_NMI:
-		len = ghes_esource_prealloc_size(generic);
-		ghes_estatus_pool_expand(len);
-		mutex_lock(&ghes_list_mutex);
-		if (list_empty(&ghes_nmi))
-			register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
-						"ghes");
-		list_add_rcu(&ghes->list, &ghes_nmi);
-		mutex_unlock(&ghes_list_mutex);
+		ghes_nmi_add(ghes);
 		break;
 	default:
 		BUG();
@@ -1001,7 +1060,6 @@ static int ghes_remove(struct platform_d
 {
 	struct ghes *ghes;
 	struct acpi_hest_generic *generic;
-	unsigned long len;
 
 	ghes = platform_get_drvdata(ghes_dev);
 	generic = ghes->generic;
@@ -1022,18 +1080,7 @@ static int ghes_remove(struct platform_d
 		mutex_unlock(&ghes_list_mutex);
 		break;
 	case ACPI_HEST_NOTIFY_NMI:
-		mutex_lock(&ghes_list_mutex);
-		list_del_rcu(&ghes->list);
-		if (list_empty(&ghes_nmi))
-			unregister_nmi_handler(NMI_LOCAL, "ghes");
-		mutex_unlock(&ghes_list_mutex);
-		/*
-		 * To synchronize with NMI handler, ghes can only be
-		 * freed after NMI handler finishes.
-		 */
-		synchronize_rcu();
-		len = ghes_esource_prealloc_size(generic);
-		ghes_estatus_pool_shrink(len);
+		ghes_nmi_remove(ghes);
 		break;
 	default:
 		BUG();
@@ -1077,7 +1124,7 @@ static int __init ghes_init(void)
 		return -EINVAL;
 	}
 
-	init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
+	ghes_nmi_init_cxt();
 
 	rc = ghes_ioremap_init();
 	if (rc)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/apei/hest.c linux-libre-3.17-rc7-gnu/drivers/acpi/apei/hest.c
--- linux-libre-3.16-gnu/drivers/acpi/apei/hest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/apei/hest.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,6 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <acpi/apei.h>
-#include <asm/mce.h>
 
 #include "apei-internal.h"
 
@@ -128,33 +127,7 @@ EXPORT_SYMBOL_GPL(apei_hest_parse);
  */
 static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
 {
-#ifdef CONFIG_X86_MCE
-	int i;
-	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;
-
-	/*
-	 * We expect HEST to provide a list of MC banks that report errors
-	 * in firmware first mode. Otherwise, return non-zero value to
-	 * indicate that we are done parsing HEST.
-	 */
-	if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) || !cmc->num_hardware_banks)
-		return 1;
-
-	pr_info(HEST_PFX "Enabling Firmware First mode for corrected errors.\n");
-
-	mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1);
-	for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++)
-		mce_disable_bank(mc_bank->bank_number);
-#endif
-	return 1;
+	return arch_apei_enable_cmcff(hest_hdr, data);
 }
 
 struct ghes_arr {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/apei/Kconfig linux-libre-3.17-rc7-gnu/drivers/acpi/apei/Kconfig
--- linux-libre-3.16-gnu/drivers/acpi/apei/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/apei/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,15 @@
+config HAVE_ACPI_APEI
+	bool
+
+config HAVE_ACPI_APEI_NMI
+	bool
+
 config ACPI_APEI
 	bool "ACPI Platform Error Interface (APEI)"
 	select MISC_FILESYSTEMS
 	select PSTORE
 	select UEFI_CPER
-	depends on X86
+	depends on HAVE_ACPI_APEI
 	help
 	  APEI allows to report errors (for example from the chipset)
 	  to the operating system. This improves NMI handling
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/battery.c linux-libre-3.17-rc7-gnu/drivers/acpi/battery.c
--- linux-libre-3.16-gnu/drivers/acpi/battery.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/battery.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
-#include <linux/delay.h>
 #include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
@@ -535,20 +534,6 @@ static int acpi_battery_get_state(struct
 			" invalid.\n");
 	}
 
-	/*
-	 * When fully charged, some batteries wrongly report
-	 * capacity_now = design_capacity instead of = full_charge_capacity
-	 */
-	if (battery->capacity_now > battery->full_charge_capacity
-	    && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) {
-		battery->capacity_now = battery->full_charge_capacity;
-		if (battery->capacity_now != battery->design_capacity)
-			printk_once(KERN_WARNING FW_BUG
-				"battery: reported current charge level (%d) "
-				"is higher than reported maximum charge level (%d).\n",
-				battery->capacity_now, battery->full_charge_capacity);
-	}
-
 	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
 	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
 		battery->capacity_now = (battery->capacity_now *
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/blacklist.c linux-libre-3.17-rc7-gnu/drivers/acpi/blacklist.c
--- linux-libre-3.16-gnu/drivers/acpi/blacklist.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/blacklist.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,75 +247,11 @@ static struct dmi_system_id acpi_osi_dmi
 	},
 
 	/*
-	 * The following machines have broken backlight support when reporting
-	 * the Windows 2012 OSI, so disable it until their support is fixed.
+	 * These machines will power on immediately after shutdown when
+	 * reporting the Windows 2012 OSI.
 	 */
 	{
 	.callback = dmi_disable_osi_win8,
-	.ident = "ASUS Zenbook Prime UX31A",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "ThinkPad Edge E530",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "ThinkPad Edge E530",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "ThinkPad Edge E530",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Acer Aspire V5-573G",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Acer Aspire V5-572G",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "ThinkPad T431s",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "ThinkPad T430",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
 	.ident = "Dell Inspiron 7737",
 	.matches = {
 		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/bus.c linux-libre-3.17-rc7-gnu/drivers/acpi/bus.c
--- linux-libre-3.16-gnu/drivers/acpi/bus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,16 +177,6 @@ void acpi_bus_detach_private_data(acpi_h
 }
 EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data);
 
-void acpi_bus_no_hotplug(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
-	if (adev)
-		adev->flags.no_hotplug = true;
-}
-EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
-
 static void acpi_print_osc_error(acpi_handle handle,
 	struct acpi_osc_context *context, char *error)
 {
@@ -477,9 +467,6 @@ static int __init acpi_bus_init_irq(void
 	return 0;
 }
 
-u8 acpi_gbl_permanent_mmap;
-
-
 void __init acpi_early_init(void)
 {
 	acpi_status status;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/button.c linux-libre-3.17-rc7-gnu/drivers/acpi/button.c
--- linux-libre-3.16-gnu/drivers/acpi/button.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/button.c	2014-09-28 17:29:07.000000000 -0400
@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acp
 static void acpi_button_notify(struct acpi_device *device, u32 event);
 
 #ifdef CONFIG_PM_SLEEP
+static int acpi_button_suspend(struct device *dev);
 static int acpi_button_resume(struct device *dev);
 #else
+#define acpi_button_suspend NULL
 #define acpi_button_resume NULL
 #endif
-static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
+static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
 
 static struct acpi_driver acpi_button_driver = {
 	.name = "button",
@@ -102,6 +104,7 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	bool suspended;
 };
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -293,15 +296,19 @@ static void acpi_button_notify(struct ac
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
 			acpi_lid_send_state(device);
 		} else {
-			int keycode = test_bit(KEY_SLEEP, input->keybit) ?
-						KEY_SLEEP : KEY_POWER;
+			int keycode;
+
+			pm_wakeup_event(&device->dev, 0);
+			if (button->suspended)
+				break;
 
+			keycode = test_bit(KEY_SLEEP, input->keybit) ?
+						KEY_SLEEP : KEY_POWER;
 			input_report_key(input, keycode, 1);
 			input_sync(input);
 			input_report_key(input, keycode, 0);
 			input_sync(input);
 
-			pm_wakeup_event(&device->dev, 0);
 			acpi_bus_generate_netlink_event(
 					device->pnp.device_class,
 					dev_name(&device->dev),
@@ -316,11 +323,21 @@ static void acpi_button_notify(struct ac
 }
 
 #ifdef CONFIG_PM_SLEEP
+static int acpi_button_suspend(struct device *dev)
+{
+	struct acpi_device *device = to_acpi_device(dev);
+	struct acpi_button *button = acpi_driver_data(device);
+
+	button->suspended = true;
+	return 0;
+}
+
 static int acpi_button_resume(struct device *dev)
 {
 	struct acpi_device *device = to_acpi_device(dev);
 	struct acpi_button *button = acpi_driver_data(device);
 
+	button->suspended = false;
 	if (button->type == ACPI_BUTTON_TYPE_LID)
 		return acpi_lid_send_state(device);
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/container.c linux-libre-3.17-rc7-gnu/drivers/acpi/container.c
--- linux-libre-3.16-gnu/drivers/acpi/container.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/container.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,13 @@ static void container_device_detach(stru
 		device_unregister(dev);
 }
 
+static void container_device_online(struct acpi_device *adev)
+{
+	struct device *dev = acpi_driver_data(adev);
+
+	kobject_uevent(&dev->kobj, KOBJ_ONLINE);
+}
+
 static struct acpi_scan_handler container_handler = {
 	.ids = container_device_ids,
 	.attach = container_device_attach,
@@ -106,6 +113,7 @@ static struct acpi_scan_handler containe
 	.hotplug = {
 		.enabled = true,
 		.demand_offline = true,
+		.notify_online = container_device_online,
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/device_pm.c linux-libre-3.17-rc7-gnu/drivers/acpi/device_pm.c
--- linux-libre-3.16-gnu/drivers/acpi/device_pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/device_pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable)
 #ifdef CONFIG_PM
 static DEFINE_MUTEX(acpi_pm_notifier_lock);
 
+static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
+{
+	struct acpi_device *adev;
+
+	if (val != ACPI_NOTIFY_DEVICE_WAKE)
+		return;
+
+	adev = acpi_bus_get_acpi_device(handle);
+	if (!adev)
+		return;
+
+	mutex_lock(&acpi_pm_notifier_lock);
+
+	if (adev->wakeup.flags.notifier_present) {
+		__pm_wakeup_event(adev->wakeup.ws, 0);
+		if (adev->wakeup.context.work.func)
+			queue_pm_work(&adev->wakeup.context.work);
+	}
+
+	mutex_unlock(&acpi_pm_notifier_lock);
+
+	acpi_bus_put_acpi_device(adev);
+}
+
 /**
- * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
- * @adev: ACPI device to add the notifier for.
- * @context: Context information to pass to the notifier routine.
+ * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
+ * @adev: ACPI device to add the notify handler for.
+ * @dev: Device to generate a wakeup event for while handling the notification.
+ * @work_func: Work function to execute when handling the notification.
  *
  * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
  * PM wakeup events.  For example, wakeup events may be generated for bridges
  * if one of the devices below the bridge is signaling wakeup, even if the
  * bridge itself doesn't have a wakeup GPE associated with it.
  */
-acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
-				 acpi_notify_handler handler, void *context)
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
+				 void (*work_func)(struct work_struct *work))
 {
 	acpi_status status = AE_ALREADY_EXISTS;
 
+	if (!dev && !work_func)
+		return AE_BAD_PARAMETER;
+
 	mutex_lock(&acpi_pm_notifier_lock);
 
 	if (adev->wakeup.flags.notifier_present)
 		goto out;
 
-	status = acpi_install_notify_handler(adev->handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handler, context);
+	adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
+	adev->wakeup.context.dev = dev;
+	if (work_func)
+		INIT_WORK(&adev->wakeup.context.work, work_func);
+
+	status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
+					     acpi_pm_notify_handler, NULL);
 	if (ACPI_FAILURE(status))
 		goto out;
 
@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct
  * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
  * @adev: ACPI device to remove the notifier from.
  */
-acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
-				    acpi_notify_handler handler)
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
 {
 	acpi_status status = AE_BAD_PARAMETER;
 
@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(stru
 
 	status = acpi_remove_notify_handler(adev->handle,
 					    ACPI_SYSTEM_NOTIFY,
-					    handler);
+					    acpi_pm_notify_handler);
 	if (ACPI_FAILURE(status))
 		goto out;
 
+	if (adev->wakeup.context.work.func) {
+		cancel_work_sync(&adev->wakeup.context.work);
+		adev->wakeup.context.work.func = NULL;
+	}
+	adev->wakeup.context.dev = NULL;
+	wakeup_source_unregister(adev->wakeup.ws);
+
 	adev->wakeup.flags.notifier_present = false;
 
  out:
@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct
  */
 int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
 {
-	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_device *adev;
 	int ret, d_min, d_max;
 
@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct de
 			d_max_in = ACPI_STATE_D3_HOT;
 	}
 
-	if (!handle || acpi_bus_get_device(handle, &adev)) {
-		dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+	adev = ACPI_COMPANION(dev);
+	if (!adev) {
+		dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
 		return -ENODEV;
 	}
 
@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct de
 }
 EXPORT_SYMBOL(acpi_pm_device_sleep_state);
 
-#ifdef CONFIG_PM_RUNTIME
 /**
- * acpi_wakeup_device - Wakeup notification handler for ACPI devices.
- * @handle: ACPI handle of the device the notification is for.
- * @event: Type of the signaled event.
- * @context: Device corresponding to @handle.
+ * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
+ * @work: Work item to handle.
  */
-static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
+static void acpi_pm_notify_work_func(struct work_struct *work)
 {
-	struct device *dev = context;
+	struct device *dev;
 
-	if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) {
+	dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
+	if (dev) {
 		pm_wakeup_event(dev, 0);
 		pm_runtime_resume(dev);
 	}
 }
 
 /**
- * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device.
- * @adev: ACPI device to enable/disable the remote wakeup for.
+ * acpi_device_wakeup - Enable/disable wakeup functionality for device.
+ * @adev: ACPI device to enable/disable wakeup functionality for.
+ * @target_state: State the system is transitioning into.
  * @enable: Whether to enable or disable the wakeup functionality.
  *
  * Enable/disable the GPE associated with @adev so that it can generate
@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_hand
  * Callers must ensure that @adev is a valid ACPI device node before executing
  * this function.
  */
-int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
+static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state,
+			      bool enable)
 {
 	struct acpi_device_wakeup *wakeup = &adev->wakeup;
 
@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_d
 		acpi_status res;
 		int error;
 
-		error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
+		error = acpi_enable_wakeup_device_power(adev, target_state);
 		if (error)
 			return error;
 
@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_d
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 /**
  * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
  * @dev: Device to enable/disable the platform to wake up.
@@ -661,63 +700,42 @@ int __acpi_device_run_wake(struct acpi_d
 int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
 {
 	struct acpi_device *adev;
-	acpi_handle handle;
 
 	if (!device_run_wake(phys_dev))
 		return -EINVAL;
 
-	handle = ACPI_HANDLE(phys_dev);
-	if (!handle || acpi_bus_get_device(handle, &adev)) {
-		dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
-			__func__);
+	adev = ACPI_COMPANION(phys_dev);
+	if (!adev) {
+		dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__);
 		return -ENODEV;
 	}
 
-	return __acpi_device_run_wake(adev, enable);
+	return acpi_device_wakeup(adev, enable, ACPI_STATE_S0);
 }
 EXPORT_SYMBOL(acpi_pm_device_run_wake);
-#else
-static inline void acpi_wakeup_device(acpi_handle handle, u32 event,
-				      void *context) {}
 #endif /* CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM_SLEEP
 /**
- * __acpi_device_sleep_wake - Enable or disable device to wake up the system.
- * @dev: Device to enable/desible to wake up the system.
- * @target_state: System state the device is supposed to wake up from.
- * @enable: Whether to enable or disable @dev to wake up the system.
- */
-int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
-			     bool enable)
-{
-	return enable ?
-		acpi_enable_wakeup_device_power(adev, target_state) :
-		acpi_disable_wakeup_device_power(adev);
-}
-
-/**
  * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
  * @dev: Device to enable/desible to wake up the system from sleep states.
  * @enable: Whether to enable or disable @dev to wake up the system.
  */
 int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
-	acpi_handle handle;
 	struct acpi_device *adev;
 	int error;
 
 	if (!device_can_wakeup(dev))
 		return -EINVAL;
 
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev)) {
-		dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+	adev = ACPI_COMPANION(dev);
+	if (!adev) {
+		dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
 		return -ENODEV;
 	}
 
-	error = __acpi_device_sleep_wake(adev, acpi_target_system_state(),
-					 enable);
+	error = acpi_device_wakeup(adev, acpi_target_system_state(), enable);
 	if (!error)
 		dev_info(dev, "System wakeup %s by ACPI\n",
 				enable ? "enabled" : "disabled");
@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct devi
 
 	remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
 				PM_QOS_FLAGS_NONE;
-	error = __acpi_device_run_wake(adev, remote_wakeup);
+	error = acpi_device_wakeup(adev, ACPI_STATE_S0, remote_wakeup);
 	if (remote_wakeup && error)
 		return -EAGAIN;
 
 	error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
 	if (error)
-		__acpi_device_run_wake(adev, false);
+		acpi_device_wakeup(adev, ACPI_STATE_S0, false);
 
 	return error;
 }
@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct devic
 		return 0;
 
 	error = acpi_dev_pm_full_power(adev);
-	__acpi_device_run_wake(adev, false);
+	acpi_device_wakeup(adev, ACPI_STATE_S0, false);
 	return error;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device
 
 	target_state = acpi_target_system_state();
 	wakeup = device_may_wakeup(dev);
-	error = __acpi_device_sleep_wake(adev, target_state, wakeup);
+	error = acpi_device_wakeup(adev, target_state, wakeup);
 	if (wakeup && error)
 		return error;
 
 	error = acpi_dev_pm_low_power(dev, adev, target_state);
 	if (error)
-		__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+		acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
 
 	return error;
 }
@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device
 		return 0;
 
 	error = acpi_dev_pm_full_power(adev);
-	__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+	acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
 	return error;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *de
 	if (dev->pm_domain)
 		return -EEXIST;
 
-	acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
+	acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
 	dev->pm_domain = &acpi_general_pm_domain;
 	if (power_on) {
 		acpi_dev_pm_full_power(adev);
-		__acpi_device_run_wake(adev, false);
+		acpi_device_wakeup(adev, ACPI_STATE_S0, false);
 	}
 	return 0;
 }
@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *d
 
 	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
 		dev->pm_domain = NULL;
-		acpi_remove_pm_notifier(adev, acpi_wakeup_device);
+		acpi_remove_pm_notifier(adev);
 		if (power_off) {
 			/*
 			 * If the device's PM QoS resume latency limit or flags
@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *d
 			 */
 			dev_pm_qos_hide_latency_limit(dev);
 			dev_pm_qos_hide_flags(dev);
-			__acpi_device_run_wake(adev, false);
+			acpi_device_wakeup(adev, ACPI_STATE_S0, false);
 			acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/ec.c linux-libre-3.17-rc7-gnu/drivers/acpi/ec.c
--- linux-libre-3.16-gnu/drivers/acpi/ec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/ec.c	2014-09-28 17:29:07.000000000 -0400
@@ -197,6 +197,8 @@ static bool advance_transaction(struct a
 				t->rdata[t->ri++] = acpi_ec_read_data(ec);
 				if (t->rlen == t->ri) {
 					t->flags |= ACPI_EC_COMMAND_COMPLETE;
+					if (t->command == ACPI_EC_COMMAND_QUERY)
+						pr_debug("hardware QR_EC completion\n");
 					wakeup = true;
 				}
 			} else
@@ -208,7 +210,20 @@ static bool advance_transaction(struct a
 		}
 		return wakeup;
 	} else {
-		if ((status & ACPI_EC_FLAG_IBF) == 0) {
+		/*
+		 * There is firmware refusing to respond QR_EC when SCI_EVT
+		 * is not set, for which case, we complete the QR_EC
+		 * without issuing it to the firmware.
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=86211
+		 */
+		if (!(status & ACPI_EC_FLAG_SCI) &&
+		    (t->command == ACPI_EC_COMMAND_QUERY)) {
+			t->flags |= ACPI_EC_COMMAND_POLL;
+			t->rdata[t->ri++] = 0x00;
+			t->flags |= ACPI_EC_COMMAND_COMPLETE;
+			pr_debug("software QR_EC completion\n");
+			wakeup = true;
+		} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
 			acpi_ec_write_cmd(ec, t->command);
 			t->flags |= ACPI_EC_COMMAND_POLL;
 		} else
@@ -288,11 +303,11 @@ static int acpi_ec_transaction_unlocked(
 	/* following two actions should be kept atomic */
 	ec->curr = t;
 	start_transaction(ec);
-	if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
-		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	spin_unlock_irqrestore(&ec->lock, tmp);
 	ret = ec_poll(ec);
 	spin_lock_irqsave(&ec->lock, tmp);
+	if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
+		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	ec->curr = NULL;
 	spin_unlock_irqrestore(&ec->lock, tmp);
 	return ret;
@@ -1015,6 +1030,10 @@ static struct dmi_system_id ec_dmi_table
 	DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
 	DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL},
 	{
+	ec_flag_msi, "Clevo W350etq", {
+	DMI_MATCH(DMI_SYS_VENDOR, "CLEVO CO."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "W35_37ET"),}, NULL},
+	{
 	ec_validate_ecdt, "ASUS hardware", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
 	{
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/internal.h linux-libre-3.17-rc7-gnu/drivers/acpi/internal.h
--- linux-libre-3.16-gnu/drivers/acpi/internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -84,8 +84,6 @@ void acpi_init_device_object(struct acpi
 			     int type, unsigned long long sta);
 void acpi_device_add_finalize(struct acpi_device *device);
 void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
-int acpi_bind_one(struct device *dev, struct acpi_device *adev);
-int acpi_unbind_one(struct device *dev);
 bool acpi_device_is_present(struct acpi_device *adev);
 bool acpi_device_is_battery(struct acpi_device *adev);
 
@@ -108,7 +106,12 @@ int acpi_power_transition(struct acpi_de
 int acpi_device_update_power(struct acpi_device *device, int *state_p);
 
 int acpi_wakeup_device_init(void);
+
+#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
 void acpi_early_processor_set_pdc(void);
+#else
+static inline void acpi_early_processor_set_pdc(void) {}
+#endif
 
 /* --------------------------------------------------------------------------
                                   Embedded Controller
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/Kconfig linux-libre-3.17-rc7-gnu/drivers/acpi/Kconfig
--- linux-libre-3.16-gnu/drivers/acpi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,12 @@ menuconfig ACPI
 
 if ACPI
 
+config ACPI_LEGACY_TABLES_LOOKUP
+	bool
+
+config ARCH_MIGHT_HAVE_ACPI_PDC
+	bool
+
 config ACPI_SLEEP
 	bool
 	depends on SUSPEND || HIBERNATION
@@ -370,6 +376,7 @@ config ACPI_EXTLOG
 	tristate "Extended Error Log support"
 	depends on X86_MCE && X86_LOCAL_APIC
 	select UEFI_CPER
+	select RAS
 	default n
 	help
 	  Certain usages such as Predictive Failure Analysis (PFA) require
@@ -384,6 +391,7 @@ config ACPI_EXTLOG
 
 	  Enhanced MCA Logging allows firmware to provide additional error
 	  information to system software, synchronous with MCE or CMCI. This
-	  driver adds support for that functionality.
+	  driver adds support for that functionality with corresponding
+	  tracepoint which carries that information to userspace.
 
 endif	# ACPI
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/Makefile linux-libre-3.17-rc7-gnu/drivers/acpi/Makefile
--- linux-libre-3.16-gnu/drivers/acpi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@ acpi-y				+= scan.o
 acpi-y				+= resource.o
 acpi-y				+= acpi_processor.o
 acpi-y				+= processor_core.o
+acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/osl.c linux-libre-3.17-rc7-gnu/drivers/acpi/osl.c
--- linux-libre-3.16-gnu/drivers/acpi/osl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/osl.c	2014-09-28 17:29:07.000000000 -0400
@@ -259,12 +259,14 @@ acpi_physical_address __init acpi_os_get
 			       "System description tables not found\n");
 			return 0;
 		}
-	} else {
+	} else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) {
 		acpi_physical_address pa = 0;
 
 		acpi_find_root_pointer(&pa);
 		return pa;
 	}
+
+	return 0;
 }
 
 /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/pci_irq.c linux-libre-3.17-rc7-gnu/drivers/acpi/pci_irq.c
--- linux-libre-3.16-gnu/drivers/acpi/pci_irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/pci_irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -481,6 +481,14 @@ void acpi_pci_irq_disable(struct pci_dev
 	if (!pin)
 		return;
 
+	/* Keep IOAPIC pin configuration when suspending */
+	if (dev->dev.power.is_prepared)
+		return;
+#ifdef	CONFIG_PM_RUNTIME
+	if (dev->dev.power.runtime_status == RPM_SUSPENDING)
+		return;
+#endif
+
 	entry = acpi_pci_irq_lookup(dev, pin);
 	if (!entry)
 		return;
@@ -498,5 +506,6 @@ void acpi_pci_irq_disable(struct pci_dev
 	 */
 
 	dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
-	acpi_unregister_gsi(gsi);
+	if (gsi >= 0 && dev->irq > 0)
+		acpi_unregister_gsi(gsi);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/pci_root.c linux-libre-3.17-rc7-gnu/drivers/acpi/pci_root.c
--- linux-libre-3.16-gnu/drivers/acpi/pci_root.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/pci_root.c	2014-09-28 17:29:07.000000000 -0400
@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi
 	if (no_aspm)
 		pcie_no_aspm();
 
-	pci_acpi_add_bus_pm_notifier(device, root->bus);
+	pci_acpi_add_bus_pm_notifier(device);
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(root->bus->bridge, true);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/processor_core.c linux-libre-3.17-rc7-gnu/drivers/acpi/processor_core.c
--- linux-libre-3.16-gnu/drivers/acpi/processor_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/processor_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,17 +4,11 @@
  *
  *	Alex Chiang <achiang@hp.com>
  *	- Unified x86/ia64 implementations
- *	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- *	- Added _PDC for platforms with Intel CPUs
  */
 #include <linux/export.h>
-#include <linux/dmi.h>
-#include <linux/slab.h>
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 
-#include "internal.h"
-
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
@@ -135,6 +129,8 @@ static int map_mat_entry(acpi_handle han
 		map_lapic_id(header, acpi_id, &apic_id);
 	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
 		map_lsapic_id(header, type, acpi_id, &apic_id);
+	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+		map_x2apic_id(header, type, acpi_id, &apic_id);
 	}
 
 exit:
@@ -208,195 +204,3 @@ int acpi_get_cpuid(acpi_handle handle, i
 	return acpi_map_cpuid(apic_id, acpi_id);
 }
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
-
-static bool __init processor_physically_present(acpi_handle handle)
-{
-	int cpuid, type;
-	u32 acpi_id;
-	acpi_status status;
-	acpi_object_type acpi_type;
-	unsigned long long tmp;
-	union acpi_object object = { 0 };
-	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
-	status = acpi_get_type(handle, &acpi_type);
-	if (ACPI_FAILURE(status))
-		return false;
-
-	switch (acpi_type) {
-	case ACPI_TYPE_PROCESSOR:
-		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
-		if (ACPI_FAILURE(status))
-			return false;
-		acpi_id = object.processor.proc_id;
-		break;
-	case ACPI_TYPE_DEVICE:
-		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
-		if (ACPI_FAILURE(status))
-			return false;
-		acpi_id = tmp;
-		break;
-	default:
-		return false;
-	}
-
-	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
-	cpuid = acpi_get_cpuid(handle, type, acpi_id);
-
-	if (cpuid == -1)
-		return false;
-
-	return true;
-}
-
-static void acpi_set_pdc_bits(u32 *buf)
-{
-	buf[0] = ACPI_PDC_REVISION_ID;
-	buf[1] = 1;
-
-	/* Enable coordination with firmware's _TSD info */
-	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
-
-	/* Twiddle arch-specific bits needed for _PDC */
-	arch_acpi_set_pdc_bits(buf);
-}
-
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
-{
-	struct acpi_object_list *obj_list;
-	union acpi_object *obj;
-	u32 *buf;
-
-	/* allocate and initialize pdc. It will be used later. */
-	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-	if (!obj_list) {
-		printk(KERN_ERR "Memory allocation error\n");
-		return NULL;
-	}
-
-	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-	if (!obj) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj_list);
-		return NULL;
-	}
-
-	buf = kmalloc(12, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj);
-		kfree(obj_list);
-		return NULL;
-	}
-
-	acpi_set_pdc_bits(buf);
-
-	obj->type = ACPI_TYPE_BUFFER;
-	obj->buffer.length = 12;
-	obj->buffer.pointer = (u8 *) buf;
-	obj_list->count = 1;
-	obj_list->pointer = obj;
-
-	return obj_list;
-}
-
-/*
- * _PDC is required for a BIOS-OS handshake for most of the newer
- * ACPI processor features.
- */
-static acpi_status
-acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
-{
-	acpi_status status = AE_OK;
-
-	if (boot_option_idle_override == IDLE_NOMWAIT) {
-		/*
-		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
-		 * mode will be disabled in the parameter of _PDC object.
-		 * Of course C1_FFH access mode will also be disabled.
-		 */
-		union acpi_object *obj;
-		u32 *buffer = NULL;
-
-		obj = pdc_in->pointer;
-		buffer = (u32 *)(obj->buffer.pointer);
-		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
-	}
-	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
-
-	if (ACPI_FAILURE(status))
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-		    "Could not evaluate _PDC, using legacy perf. control.\n"));
-
-	return status;
-}
-
-void acpi_processor_set_pdc(acpi_handle handle)
-{
-	struct acpi_object_list *obj_list;
-
-	if (arch_has_acpi_pdc() == false)
-		return;
-
-	obj_list = acpi_processor_alloc_pdc();
-	if (!obj_list)
-		return;
-
-	acpi_processor_eval_pdc(handle, obj_list);
-
-	kfree(obj_list->pointer->buffer.pointer);
-	kfree(obj_list->pointer);
-	kfree(obj_list);
-}
-
-static acpi_status __init
-early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	if (processor_physically_present(handle) == false)
-		return AE_OK;
-
-	acpi_processor_set_pdc(handle);
-	return AE_OK;
-}
-
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
-static int __init set_no_mwait(const struct dmi_system_id *id)
-{
-	pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n",
-		  id->ident);
-	boot_option_idle_override = IDLE_NOMWAIT;
-	return 0;
-}
-
-static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
-	{
-	set_no_mwait, "Extensa 5220", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
-	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
-	{},
-};
-
-static void __init processor_dmi_check(void)
-{
-	/*
-	 * Check whether the system is DMI table. If yes, OSPM
-	 * should not use mwait for CPU-states.
-	 */
-	dmi_check_system(processor_idle_dmi_table);
-}
-#else
-static inline void processor_dmi_check(void) {}
-#endif
-
-void __init acpi_early_processor_set_pdc(void)
-{
-	processor_dmi_check();
-
-	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    early_init_pdc, NULL, NULL, NULL);
-	acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/processor_driver.c linux-libre-3.17-rc7-gnu/drivers/acpi/processor_driver.c
--- linux-libre-3.16-gnu/drivers/acpi/processor_driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/processor_driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,6 +120,7 @@ static int acpi_cpu_soft_notify(struct n
 	unsigned int cpu = (unsigned long)hcpu;
 	struct acpi_processor *pr = per_cpu(processors, cpu);
 	struct acpi_device *device;
+	action &= ~CPU_TASKS_FROZEN;
 
 	/*
 	 * CPU_STARTING and CPU_DYING must not sleep. Return here since
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/processor_idle.c linux-libre-3.17-rc7-gnu/drivers/acpi/processor_idle.c
--- linux-libre-3.16-gnu/drivers/acpi/processor_idle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/processor_idle.c	2014-09-28 17:29:07.000000000 -0400
@@ -1071,9 +1071,9 @@ int acpi_processor_cst_has_changed(struc
 
 	if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) {
 
-		cpuidle_pause_and_lock();
 		/* Protect against cpu-hotplug */
 		get_online_cpus();
+		cpuidle_pause_and_lock();
 
 		/* Disable all cpuidle devices */
 		for_each_online_cpu(cpu) {
@@ -1100,8 +1100,8 @@ int acpi_processor_cst_has_changed(struc
 				cpuidle_enable_device(dev);
 			}
 		}
-		put_online_cpus();
 		cpuidle_resume_and_unlock();
+		put_online_cpus();
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/processor_pdc.c linux-libre-3.17-rc7-gnu/drivers/acpi/processor_pdc.c
--- linux-libre-3.16-gnu/drivers/acpi/processor_pdc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/processor_pdc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2005 Intel Corporation
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *      - Added _PDC for platforms with Intel CPUs
+ */
+
+#define pr_fmt(fmt) "ACPI: " fmt
+
+#include <linux/dmi.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+
+#include "internal.h"
+
+#define _COMPONENT              ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME("processor_pdc");
+
+static bool __init processor_physically_present(acpi_handle handle)
+{
+	int cpuid, type;
+	u32 acpi_id;
+	acpi_status status;
+	acpi_object_type acpi_type;
+	unsigned long long tmp;
+	union acpi_object object = { 0 };
+	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+
+	status = acpi_get_type(handle, &acpi_type);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	switch (acpi_type) {
+	case ACPI_TYPE_PROCESSOR:
+		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+		if (ACPI_FAILURE(status))
+			return false;
+		acpi_id = object.processor.proc_id;
+		break;
+	case ACPI_TYPE_DEVICE:
+		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
+		if (ACPI_FAILURE(status))
+			return false;
+		acpi_id = tmp;
+		break;
+	default:
+		return false;
+	}
+
+	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
+	cpuid = acpi_get_cpuid(handle, type, acpi_id);
+
+	if (cpuid == -1)
+		return false;
+
+	return true;
+}
+
+static void acpi_set_pdc_bits(u32 *buf)
+{
+	buf[0] = ACPI_PDC_REVISION_ID;
+	buf[1] = 1;
+
+	/* Enable coordination with firmware's _TSD info */
+	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
+
+	/* Twiddle arch-specific bits needed for _PDC */
+	arch_acpi_set_pdc_bits(buf);
+}
+
+static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+{
+	struct acpi_object_list *obj_list;
+	union acpi_object *obj;
+	u32 *buf;
+
+	/* allocate and initialize pdc. It will be used later. */
+	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+	if (!obj_list)
+		goto out;
+
+	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+	if (!obj) {
+		kfree(obj_list);
+		goto out;
+	}
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf) {
+		kfree(obj);
+		kfree(obj_list);
+		goto out;
+	}
+
+	acpi_set_pdc_bits(buf);
+
+	obj->type = ACPI_TYPE_BUFFER;
+	obj->buffer.length = 12;
+	obj->buffer.pointer = (u8 *) buf;
+	obj_list->count = 1;
+	obj_list->pointer = obj;
+
+	return obj_list;
+out:
+	pr_err("Memory allocation error\n");
+	return NULL;
+}
+
+/*
+ * _PDC is required for a BIOS-OS handshake for most of the newer
+ * ACPI processor features.
+ */
+static acpi_status
+acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
+{
+	acpi_status status = AE_OK;
+
+	if (boot_option_idle_override == IDLE_NOMWAIT) {
+		/*
+		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
+		 * mode will be disabled in the parameter of _PDC object.
+		 * Of course C1_FFH access mode will also be disabled.
+		 */
+		union acpi_object *obj;
+		u32 *buffer = NULL;
+
+		obj = pdc_in->pointer;
+		buffer = (u32 *)(obj->buffer.pointer);
+		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
+
+	}
+	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
+
+	if (ACPI_FAILURE(status))
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		    "Could not evaluate _PDC, using legacy perf. control.\n"));
+
+	return status;
+}
+
+void acpi_processor_set_pdc(acpi_handle handle)
+{
+	struct acpi_object_list *obj_list;
+
+	if (arch_has_acpi_pdc() == false)
+		return;
+
+	obj_list = acpi_processor_alloc_pdc();
+	if (!obj_list)
+		return;
+
+	acpi_processor_eval_pdc(handle, obj_list);
+
+	kfree(obj_list->pointer->buffer.pointer);
+	kfree(obj_list->pointer);
+	kfree(obj_list);
+}
+
+static acpi_status __init
+early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	if (processor_physically_present(handle) == false)
+		return AE_OK;
+
+	acpi_processor_set_pdc(handle);
+	return AE_OK;
+}
+
+static int __init set_no_mwait(const struct dmi_system_id *id)
+{
+	pr_notice("%s detected - disabling mwait for CPU C-states\n",
+		  id->ident);
+	boot_option_idle_override = IDLE_NOMWAIT;
+	return 0;
+}
+
+static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
+	{
+	set_no_mwait, "Extensa 5220", {
+	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+	{},
+};
+
+static void __init processor_dmi_check(void)
+{
+	/*
+	 * Check whether the system is DMI table. If yes, OSPM
+	 * should not use mwait for CPU-states.
+	 */
+	dmi_check_system(processor_idle_dmi_table);
+}
+
+void __init acpi_early_processor_set_pdc(void)
+{
+	processor_dmi_check();
+
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+			    ACPI_UINT32_MAX,
+			    early_init_pdc, NULL, NULL, NULL);
+	acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/scan.c linux-libre-3.17-rc7-gnu/drivers/acpi/scan.c
--- linux-libre-3.16-gnu/drivers/acpi/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,7 +77,9 @@ void acpi_initialize_hp_context(struct a
 				void (*uevent)(struct acpi_device *, u32))
 {
 	acpi_lock_hp_context();
-	acpi_set_hp_context(adev, hp, notify, uevent, NULL);
+	hp->notify = notify;
+	hp->uevent = uevent;
+	acpi_set_hp_context(adev, hp);
 	acpi_unlock_hp_context();
 }
 EXPORT_SYMBOL_GPL(acpi_initialize_hp_context);
@@ -128,7 +130,7 @@ static int create_modalias(struct acpi_d
 	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
 		count = snprintf(&modalias[len], size, "%s:", id->id);
 		if (count < 0)
-			return EINVAL;
+			return -EINVAL;
 		if (count >= size)
 			return -ENOMEM;
 		len += count;
@@ -351,7 +353,8 @@ static int acpi_scan_hot_remove(struct a
 	unsigned long long sta;
 	acpi_status status;
 
-	if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) {
+	if (device->handler && device->handler->hotplug.demand_offline
+	    && !acpi_force_hot_remove) {
 		if (!acpi_scan_is_offline(device, true))
 			return -EBUSY;
 	} else {
@@ -664,8 +667,14 @@ static ssize_t
 acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
 		     char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	acpi_status status;
+	unsigned long long sun;
 
-	return sprintf(buf, "%lu\n", acpi_dev->pnp.sun);
+	status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	return sprintf(buf, "%llu\n", sun);
 }
 static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
 
@@ -687,7 +696,6 @@ static int acpi_device_setup_files(struc
 {
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_status status;
-	unsigned long long sun;
 	int result = 0;
 
 	/*
@@ -728,14 +736,10 @@ static int acpi_device_setup_files(struc
 	if (dev->pnp.unique_id)
 		result = device_create_file(&dev->dev, &dev_attr_uid);
 
-	status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun);
-	if (ACPI_SUCCESS(status)) {
-		dev->pnp.sun = (unsigned long)sun;
+	if (acpi_has_method(dev->handle, "_SUN")) {
 		result = device_create_file(&dev->dev, &dev_attr_sun);
 		if (result)
 			goto end;
-	} else {
-		dev->pnp.sun = (unsigned long)-1;
 	}
 
 	if (acpi_has_method(dev->handle, "_STA")) {
@@ -919,12 +923,17 @@ static void acpi_device_notify(acpi_hand
 	device->driver->ops.notify(device, event);
 }
 
-static acpi_status acpi_device_notify_fixed(void *data)
+static void acpi_device_notify_fixed(void *data)
 {
 	struct acpi_device *device = data;
 
 	/* Fixed hardware devices have no handles */
 	acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
+}
+
+static acpi_status acpi_device_fixed_event(void *data)
+{
+	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
 	return AE_OK;
 }
 
@@ -935,12 +944,12 @@ static int acpi_device_install_notify_ha
 	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
 		status =
 		    acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-						     acpi_device_notify_fixed,
+						     acpi_device_fixed_event,
 						     device);
 	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
 		status =
 		    acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-						     acpi_device_notify_fixed,
+						     acpi_device_fixed_event,
 						     device);
 	else
 		status = acpi_install_notify_handler(device->handle,
@@ -957,10 +966,10 @@ static void acpi_device_remove_notify_ha
 {
 	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
 		acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-						acpi_device_notify_fixed);
+						acpi_device_fixed_event);
 	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
 		acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-						acpi_device_notify_fixed);
+						acpi_device_fixed_event);
 	else
 		acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
 					   acpi_device_notify);
@@ -972,7 +981,7 @@ static int acpi_device_probe(struct devi
 	struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
 	int ret;
 
-	if (acpi_dev->handler)
+	if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
 		return -EINVAL;
 
 	if (!acpi_drv->ops.add)
@@ -1421,14 +1430,13 @@ static int acpi_bus_extract_wakeup_devic
 			wakeup->sleep_state = sleep_state;
 		}
 	}
-	acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
 
  out:
 	kfree(buffer.pointer);
 	return err;
 }
 
-static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
+static void acpi_wakeup_gpe_init(struct acpi_device *device)
 {
 	struct acpi_device_id button_device_ids[] = {
 		{"PNP0C0C", 0},
@@ -1436,29 +1444,33 @@ static void acpi_bus_set_run_wake_flags(
 		{"PNP0C0E", 0},
 		{"", 0},
 	};
+	struct acpi_device_wakeup *wakeup = &device->wakeup;
 	acpi_status status;
 	acpi_event_status event_status;
 
-	device->wakeup.flags.notifier_present = 0;
+	wakeup->flags.notifier_present = 0;
 
 	/* Power button, Lid switch always enable wakeup */
 	if (!acpi_match_device_ids(device, button_device_ids)) {
-		device->wakeup.flags.run_wake = 1;
+		wakeup->flags.run_wake = 1;
 		if (!acpi_match_device_ids(device, &button_device_ids[1])) {
 			/* Do not use Lid/sleep button for S5 wakeup */
-			if (device->wakeup.sleep_state == ACPI_STATE_S5)
-				device->wakeup.sleep_state = ACPI_STATE_S4;
+			if (wakeup->sleep_state == ACPI_STATE_S5)
+				wakeup->sleep_state = ACPI_STATE_S4;
 		}
+		acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
 		device_set_wakeup_capable(&device->dev, true);
 		return;
 	}
 
-	status = acpi_get_gpe_status(device->wakeup.gpe_device,
-					device->wakeup.gpe_number,
-						&event_status);
-	if (status == AE_OK)
-		device->wakeup.flags.run_wake =
-				!!(event_status & ACPI_EVENT_FLAG_HANDLE);
+	acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device,
+				wakeup->gpe_number);
+	status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number,
+				     &event_status);
+	if (ACPI_FAILURE(status))
+		return;
+
+	wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE);
 }
 
 static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
@@ -1478,7 +1490,7 @@ static void acpi_bus_get_wakeup_device_f
 
 	device->wakeup.flags.valid = 1;
 	device->wakeup.prepare_count = 0;
-	acpi_bus_set_run_wake_flags(device);
+	acpi_wakeup_gpe_init(device);
 	/* Call _PSW/_DSW object to disable its ability to wake the sleeping
 	 * system for the ACPI device with the _PRW object.
 	 * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
@@ -2177,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_
  ok:
 	list_for_each_entry(child, &device->children, node)
 		acpi_bus_attach(child);
+
+	if (device->handler && device->handler->hotplug.notify_online)
+		device->handler->hotplug.notify_online(device);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/sleep.c linux-libre-3.17-rc7-gnu/drivers/acpi/sleep.c
--- linux-libre-3.16-gnu/drivers/acpi/sleep.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/sleep.c	2014-09-28 17:29:07.000000000 -0400
@@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dm
 
 static void acpi_sleep_dmi_check(void)
 {
+	int year;
+
+	if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
+		acpi_nvs_nosave_s3();
+
 	dmi_check_system(acpisleep_dmi_table);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/acpi/video.c linux-libre-3.17-rc7-gnu/drivers/acpi/video.c
--- linux-libre-3.16-gnu/drivers/acpi/video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/acpi/video.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,9 +82,9 @@ module_param(allow_duplicates, bool, 064
  * For Windows 8 systems: used to decide if video module
  * should skip registering backlight interface of its own.
  */
-static int use_native_backlight_param = 1;
+static int use_native_backlight_param = -1;
 module_param_named(use_native_backlight, use_native_backlight_param, int, 0444);
-static bool use_native_backlight_dmi = false;
+static bool use_native_backlight_dmi = true;
 
 static int register_count;
 static struct mutex video_list_lock;
@@ -204,6 +204,8 @@ struct acpi_video_device {
 	struct acpi_video_device_flags flags;
 	struct acpi_video_device_cap cap;
 	struct list_head entry;
+	struct delayed_work switch_brightness_work;
+	int switch_brightness_event;
 	struct acpi_video_bus *video;
 	struct acpi_device *dev;
 	struct acpi_video_device_brightness *brightness;
@@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_lev
 			unsigned long long *level, bool raw);
 static int acpi_video_get_next_level(struct acpi_video_device *device,
 				     u32 level_current, u32 event);
-static int acpi_video_switch_brightness(struct acpi_video_device *device,
-					 int event);
+static void acpi_video_switch_brightness(struct work_struct *work);
 
 static bool acpi_video_use_native_backlight(void)
 {
@@ -275,6 +276,7 @@ static int acpi_video_set_brightness(str
 	int request_level = bd->props.brightness + 2;
 	struct acpi_video_device *vd = bl_get_data(bd);
 
+	cancel_delayed_work(&vd->switch_brightness_work);
 	return acpi_video_device_lcd_set_level(vd,
 				vd->brightness->levels[request_level]);
 }
@@ -415,6 +417,12 @@ static int __init video_set_use_native_b
 	return 0;
 }
 
+static int __init video_disable_native_backlight(const struct dmi_system_id *d)
+{
+	use_native_backlight_dmi = false;
+	return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
 	/*
 	 * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -461,6 +469,14 @@ static struct dmi_system_id video_dmi_ta
 	},
 	{
 	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad X230",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
 	 .ident = "ThinkPad T430 and T430s",
 	 .matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -469,10 +485,42 @@ static struct dmi_system_id video_dmi_ta
 	},
 	{
 	 .callback = video_set_use_native_backlight,
-	 .ident = "ThinkPad X230",
+	 .ident = "ThinkPad T430",
 	 .matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad T431s",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad Edge E530",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad Edge E530",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad Edge E530",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
 		},
 	},
 	{
@@ -572,6 +620,30 @@ static struct dmi_system_id video_dmi_ta
 		},
 	},
 	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Acer Aspire V5-572G",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Acer Aspire V5-573G",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ASUS Zenbook Prime UX31A",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
+		},
+	},
+	{
 	.callback = video_set_use_native_backlight,
 	.ident = "HP ProBook 4340s",
 	.matches = {
@@ -607,6 +679,15 @@ static struct dmi_system_id video_dmi_ta
 	},
 	{
 	.callback = video_set_use_native_backlight,
+	.ident = "HP EliteBook 2014 models",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+		DMI_MATCH(DMI_PRODUCT_NAME, " G2"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
 	.ident = "HP ZBook 14",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -645,6 +726,49 @@ static struct dmi_system_id video_dmi_ta
 		DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
 		},
 	},
+
+	/*
+	 * These models have a working acpi_video backlight control, and using
+	 * native backlight causes a regression where backlight does not work
+	 * when userspace is not handling brightness key events. Disable
+	 * native_backlight on these to fix this:
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=81691
+	 */
+	{
+	 .callback = video_disable_native_backlight,
+	 .ident = "ThinkPad T420",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"),
+		},
+	},
+	{
+	 .callback = video_disable_native_backlight,
+	 .ident = "ThinkPad T520",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
+		},
+	},
+	{
+	 .callback = video_disable_native_backlight,
+	 .ident = "ThinkPad X201s",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
+		},
+	},
+
+	/* The native backlight controls do not work on some older machines */
+	{
+	 /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */
+	 .callback = video_disable_native_backlight,
+	 .ident = "HP ENVY 15 Notebook",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"),
+		},
+	},
 	{}
 };
 
@@ -1188,6 +1312,8 @@ acpi_video_bus_get_one_device(struct acp
 	data->device_id = device_id;
 	data->video = video;
 	data->dev = device;
+	INIT_DELAYED_WORK(&data->switch_brightness_work,
+			  acpi_video_switch_brightness);
 
 	attribute = acpi_video_get_device_attr(video, device_id);
 
@@ -1410,15 +1536,18 @@ acpi_video_get_next_level(struct acpi_vi
 	}
 }
 
-static int
-acpi_video_switch_brightness(struct acpi_video_device *device, int event)
+static void
+acpi_video_switch_brightness(struct work_struct *work)
 {
+	struct acpi_video_device *device = container_of(to_delayed_work(work),
+			     struct acpi_video_device, switch_brightness_work);
 	unsigned long long level_current, level_next;
+	int event = device->switch_brightness_event;
 	int result = -EINVAL;
 
 	/* no warning message if acpi_backlight=vendor or a quirk is used */
 	if (!acpi_video_verify_backlight_support())
-		return 0;
+		return;
 
 	if (!device->brightness)
 		goto out;
@@ -1440,8 +1569,6 @@ acpi_video_switch_brightness(struct acpi
 out:
 	if (result)
 		printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
-
-	return result;
 }
 
 int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
@@ -1609,6 +1736,16 @@ static void acpi_video_bus_notify(struct
 	return;
 }
 
+static void brightness_switch_event(struct acpi_video_device *video_device,
+				    u32 event)
+{
+	if (!brightness_switch_enabled)
+		return;
+
+	video_device->switch_brightness_event = event;
+	schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10);
+}
+
 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct acpi_video_device *video_device = data;
@@ -1626,28 +1763,23 @@ static void acpi_video_device_notify(acp
 
 	switch (event) {
 	case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:	/* Cycle brightness */
-		if (brightness_switch_enabled)
-			acpi_video_switch_brightness(video_device, event);
+		brightness_switch_event(video_device, event);
 		keycode = KEY_BRIGHTNESS_CYCLE;
 		break;
 	case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:	/* Increase brightness */
-		if (brightness_switch_enabled)
-			acpi_video_switch_brightness(video_device, event);
+		brightness_switch_event(video_device, event);
 		keycode = KEY_BRIGHTNESSUP;
 		break;
 	case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:	/* Decrease brightness */
-		if (brightness_switch_enabled)
-			acpi_video_switch_brightness(video_device, event);
+		brightness_switch_event(video_device, event);
 		keycode = KEY_BRIGHTNESSDOWN;
 		break;
 	case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:	/* zero brightness */
-		if (brightness_switch_enabled)
-			acpi_video_switch_brightness(video_device, event);
+		brightness_switch_event(video_device, event);
 		keycode = KEY_BRIGHTNESS_ZERO;
 		break;
 	case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:	/* display device off */
-		if (brightness_switch_enabled)
-			acpi_video_switch_brightness(video_device, event);
+		brightness_switch_event(video_device, event);
 		keycode = KEY_DISPLAY_OFF;
 		break;
 	default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/amba/tegra-ahb.c linux-libre-3.17-rc7-gnu/drivers/amba/tegra-ahb.c
--- linux-libre-3.16-gnu/drivers/amba/tegra-ahb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/amba/tegra-ahb.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/tegra-ahb.h>
+
+#include <soc/tegra/ahb.h>
 
 #define DRV_NAME "tegra-ahb"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/acard-ahci.c linux-libre-3.17-rc7-gnu/drivers/ata/acard-ahci.c
--- linux-libre-3.16-gnu/drivers/ata/acard-ahci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/acard-ahci.c	2014-09-28 17:29:07.000000000 -0400
@@ -441,7 +441,7 @@ static int acard_ahci_init_one(struct pc
 	hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
 
 	/* save initial config */
-	ahci_save_initial_config(&pdev->dev, hpriv, 0, 0);
+	ahci_save_initial_config(&pdev->dev, hpriv);
 
 	/* prepare host */
 	if (hpriv->cap & HOST_CAP_NCQ)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci.c
--- linux-libre-3.16-gnu/drivers/ata/ahci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci.c	2014-09-28 17:29:07.000000000 -0400
@@ -305,6 +305,14 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -442,6 +450,8 @@ static const struct pci_device_id ahci_p
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
+	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
@@ -526,8 +536,7 @@ static void ahci_pci_save_initial_config
 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
 	}
 
-	ahci_save_initial_config(&pdev->dev, hpriv, force_port_map,
-				 mask_port_map);
+	ahci_save_initial_config(&pdev->dev, hpriv);
 }
 
 static int ahci_pci_reset_controller(struct ata_host *host)
@@ -1330,6 +1339,18 @@ static int ahci_init_one(struct pci_dev
 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
 
+	/*
+	 * The JMicron chip 361/363 contains one SATA controller and one
+	 * PATA controller,for powering on these both controllers, we must
+	 * follow the sequence one by one, otherwise one of them can not be
+	 * powered on successfully, so here we disable the async suspend
+	 * method for these chips.
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
+		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
+		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
+		device_disable_async_suspend(&pdev->dev);
+
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_da850.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_da850.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_da850.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_da850.c	2014-09-28 17:29:07.000000000 -0400
@@ -85,8 +85,7 @@ static int ahci_da850_probe(struct platf
 
 	da850_sata_init(dev, pwrdn_reg, hpriv->mmio);
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
-				     0, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info);
 	if (rc)
 		goto disable_resources;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci.h linux-libre-3.17-rc7-gnu/drivers/ata/ahci.h
--- linux-libre-3.16-gnu/drivers/ata/ahci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci.h	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@
 
 enum {
 	AHCI_MAX_PORTS		= 32,
-	AHCI_MAX_CLKS		= 3,
+	AHCI_MAX_CLKS		= 4,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_MAX_CMDS		= 32,
@@ -316,8 +316,12 @@ struct ahci_port_priv {
 };
 
 struct ahci_host_priv {
-	void __iomem *		mmio;		/* bus-independent mem map */
+	/* Input fields */
 	unsigned int		flags;		/* AHCI_HFLAG_* */
+	u32			force_port_map;	/* force port map */
+	u32			mask_port_map;	/* mask out particular bits */
+
+	void __iomem *		mmio;		/* bus-independent mem map */
 	u32			cap;		/* cap to use */
 	u32			cap2;		/* cap2 to use */
 	u32			port_map;	/* port map to use */
@@ -330,7 +334,12 @@ struct ahci_host_priv {
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	struct regulator	*target_pwr;	/* Optional */
-	struct phy		*phy;		/* If platform uses phy */
+	/*
+	 * If platform uses PHYs. There is a 1:1 relation between the port number and
+	 * the PHY position in this array.
+	 */
+	struct phy		**phys;
+	unsigned		nports;		/* Number of ports */
 	void			*plat_data;	/* Other platform data */
 	/*
 	 * Optional ahci_start_engine override, if not set this gets set to the
@@ -361,9 +370,7 @@ unsigned int ahci_dev_classify(struct at
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
 			u32 opts);
 void ahci_save_initial_config(struct device *dev,
-			      struct ahci_host_priv *hpriv,
-			      unsigned int force_port_map,
-			      unsigned int mask_port_map);
+			      struct ahci_host_priv *hpriv);
 void ahci_init_controller(struct ata_host *host);
 int ahci_reset_controller(struct ata_host *host);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_imx.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_imx.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -64,6 +64,7 @@ struct imx_ahci_priv {
 	struct regmap *gpr;
 	bool no_device;
 	bool first_time;
+	u32 phy_params;
 };
 
 static int ahci_imx_hotplug;
@@ -248,14 +249,7 @@ static int imx_sata_enable(struct ahci_h
 				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
 				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
-				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
-				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
-				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
-				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
-				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
-				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
-				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
-				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
+				   imxpriv->phy_params);
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -265,7 +259,7 @@ static int imx_sata_enable(struct ahci_h
 		ret = imx_sata_phy_reset(hpriv);
 		if (ret) {
 			dev_err(dev, "failed to reset phy: %d\n", ret);
-			goto disable_regulator;
+			goto disable_clk;
 		}
 	}
 
@@ -273,6 +267,8 @@ static int imx_sata_enable(struct ahci_h
 
 	return 0;
 
+disable_clk:
+	clk_disable_unprepare(imxpriv->sata_ref_clk);
 disable_regulator:
 	if (hpriv->target_pwr)
 		regulator_disable(hpriv->target_pwr);
@@ -369,6 +365,165 @@ static const struct of_device_id imx_ahc
 };
 MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
 
+struct reg_value {
+	u32 of_value;
+	u32 reg_value;
+};
+
+struct reg_property {
+	const char *name;
+	const struct reg_value *values;
+	size_t num_values;
+	u32 def_value;
+	u32 set_value;
+};
+
+static const struct reg_value gpr13_tx_level[] = {
+	{  937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
+	{  947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
+	{  957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
+	{  966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
+	{  976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
+	{  986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
+	{  996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
+	{ 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
+	{ 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
+	{ 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
+	{ 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
+	{ 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
+	{ 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
+	{ 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
+	{ 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
+	{ 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
+	{ 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
+	{ 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
+	{ 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
+	{ 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
+	{ 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
+	{ 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
+	{ 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
+	{ 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
+	{ 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
+	{ 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
+	{ 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
+	{ 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
+	{ 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
+	{ 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
+	{ 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
+	{ 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
+};
+
+static const struct reg_value gpr13_tx_boost[] = {
+	{    0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
+	{  370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
+	{  740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
+	{ 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
+	{ 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
+	{ 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
+	{ 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
+	{ 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
+	{ 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
+	{ 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
+	{ 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
+	{ 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
+	{ 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
+	{ 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
+	{ 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
+	{ 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
+};
+
+static const struct reg_value gpr13_tx_atten[] = {
+	{  8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
+	{  9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
+	{ 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
+	{ 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
+	{ 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
+	{ 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
+};
+
+static const struct reg_value gpr13_rx_eq[] = {
+	{  500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
+	{ 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
+	{ 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
+	{ 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
+	{ 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
+	{ 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
+	{ 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
+	{ 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
+};
+
+static const struct reg_property gpr13_props[] = {
+	{
+		.name = "fsl,transmit-level-mV",
+		.values = gpr13_tx_level,
+		.num_values = ARRAY_SIZE(gpr13_tx_level),
+		.def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
+	}, {
+		.name = "fsl,transmit-boost-mdB",
+		.values = gpr13_tx_boost,
+		.num_values = ARRAY_SIZE(gpr13_tx_boost),
+		.def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
+	}, {
+		.name = "fsl,transmit-atten-16ths",
+		.values = gpr13_tx_atten,
+		.num_values = ARRAY_SIZE(gpr13_tx_atten),
+		.def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
+	}, {
+		.name = "fsl,receive-eq-mdB",
+		.values = gpr13_rx_eq,
+		.num_values = ARRAY_SIZE(gpr13_rx_eq),
+		.def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
+	}, {
+		.name = "fsl,no-spread-spectrum",
+		.def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
+		.set_value = 0,
+	},
+};
+
+static u32 imx_ahci_parse_props(struct device *dev,
+				const struct reg_property *prop, size_t num)
+{
+	struct device_node *np = dev->of_node;
+	u32 reg_value = 0;
+	int i, j;
+
+	for (i = 0; i < num; i++, prop++) {
+		u32 of_val;
+
+		if (prop->num_values == 0) {
+			if (of_property_read_bool(np, prop->name))
+				reg_value |= prop->set_value;
+			else
+				reg_value |= prop->def_value;
+			continue;
+		}
+
+		if (of_property_read_u32(np, prop->name, &of_val)) {
+			dev_info(dev, "%s not specified, using %08x\n",
+				prop->name, prop->def_value);
+			reg_value |= prop->def_value;
+			continue;
+		}
+
+		for (j = 0; j < prop->num_values; j++) {
+			if (prop->values[j].of_value == of_val) {
+				dev_info(dev, "%s value %u, using %08x\n",
+					prop->name, of_val, prop->values[j].reg_value);
+				reg_value |= prop->values[j].reg_value;
+				break;
+			}
+		}
+
+		if (j == prop->num_values) {
+			dev_err(dev, "DT property %s is not a valid value\n",
+				prop->name);
+			reg_value |= prop->def_value;
+		}
+	}
+
+	return reg_value;
+}
+
 static int imx_ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -410,6 +565,8 @@ static int imx_ahci_probe(struct platfor
 	}
 
 	if (imxpriv->type == AHCI_IMX6Q) {
+		u32 reg_value;
+
 		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
 							"fsl,imx6q-iomuxc-gpr");
 		if (IS_ERR(imxpriv->gpr)) {
@@ -417,6 +574,15 @@ static int imx_ahci_probe(struct platfor
 				"failed to find fsl,imx6q-iomux-gpr regmap\n");
 			return PTR_ERR(imxpriv->gpr);
 		}
+
+		reg_value = imx_ahci_parse_props(dev, gpr13_props,
+						 ARRAY_SIZE(gpr13_props));
+
+		imxpriv->phy_params =
+				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+				   reg_value;
 	}
 
 	hpriv = ahci_platform_get_resources(pdev);
@@ -454,8 +620,7 @@ static int imx_ahci_probe(struct platfor
 	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
 	writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
 
-	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
-				      0, 0, 0);
+	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info);
 	if (ret)
 		goto disable_sata;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_mvebu.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_mvebu.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_mvebu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_mvebu.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,8 +88,7 @@ static int ahci_mvebu_probe(struct platf
 	ahci_mvebu_mbus_config(hpriv, dram);
 	ahci_mvebu_regret_option(hpriv);
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
-				     0, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info);
 	if (rc)
 		goto disable_resources;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_platform.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_platform.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,6 @@ static int ahci_probe(struct platform_de
 	struct device *dev = &pdev->dev;
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ahci_host_priv *hpriv;
-	unsigned long hflags = 0;
 	int rc;
 
 	hpriv = ahci_platform_get_resources(pdev);
@@ -58,10 +57,9 @@ static int ahci_probe(struct platform_de
 	}
 
 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
-		hflags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
+		hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
-				     hflags, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info);
 	if (rc)
 		goto pdata_exit;
 
@@ -78,6 +76,8 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ah
 			 ahci_platform_resume);
 
 static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "generic-ahci", },
+	/* Keep the following compatibles for device tree compatibility */
 	{ .compatible = "snps,spear-ahci", },
 	{ .compatible = "snps,exynos5440-ahci", },
 	{ .compatible = "ibm,476gtr-ahci", },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_st.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_st.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_st.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_st.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,7 +166,7 @@ static int st_ahci_probe(struct platform
 	if (err)
 		return err;
 
-	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0, 0, 0);
+	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info);
 	if (err) {
 		ahci_platform_disable_resources(hpriv);
 		return err;
@@ -221,7 +221,7 @@ static int st_ahci_resume(struct device
 
 static SIMPLE_DEV_PM_OPS(st_ahci_pm_ops, st_ahci_suspend, st_ahci_resume);
 
-static struct of_device_id st_ahci_match[] = {
+static const struct of_device_id st_ahci_match[] = {
 	{ .compatible = "st,ahci", },
 	{},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_sunxi.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_sunxi.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_sunxi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_sunxi.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,7 +167,6 @@ static int ahci_sunxi_probe(struct platf
 {
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
-	unsigned long hflags;
 	int rc;
 
 	hpriv = ahci_platform_get_resources(pdev);
@@ -184,11 +183,10 @@ static int ahci_sunxi_probe(struct platf
 	if (rc)
 		goto disable_resources;
 
-	hflags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
-		 AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
+	hpriv->flags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+		       AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info,
-				     hflags, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info);
 	if (rc)
 		goto disable_resources;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_tegra.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_tegra.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_tegra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,382 @@
+/*
+ * drivers/ata/ahci_tegra.c
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author:
+ *	Mikko Perttunen <mperttunen@nvidia.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
+
+#include "ahci.h"
+
+#define SATA_CONFIGURATION_0				0x180
+#define SATA_CONFIGURATION_EN_FPCI			BIT(0)
+
+#define SCFG_OFFSET					0x1000
+
+#define T_SATA0_CFG_1					0x04
+#define T_SATA0_CFG_1_IO_SPACE				BIT(0)
+#define T_SATA0_CFG_1_MEMORY_SPACE			BIT(1)
+#define T_SATA0_CFG_1_BUS_MASTER			BIT(2)
+#define T_SATA0_CFG_1_SERR				BIT(8)
+
+#define T_SATA0_CFG_9					0x24
+#define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT		13
+
+#define SATA_FPCI_BAR5					0x94
+#define SATA_FPCI_BAR5_START_SHIFT			4
+
+#define SATA_INTR_MASK					0x188
+#define SATA_INTR_MASK_IP_INT_MASK			BIT(16)
+
+#define T_SATA0_AHCI_HBA_CAP_BKDR			0x300
+
+#define T_SATA0_BKDOOR_CC				0x4a4
+
+#define T_SATA0_CFG_SATA				0x54c
+#define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN		BIT(12)
+
+#define T_SATA0_CFG_MISC				0x550
+
+#define T_SATA0_INDEX					0x680
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN1			0x690
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK		0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT		0
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK		(0xff << 8)
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT	8
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN2			0x694
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK		0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT		0
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK		(0xff << 12)
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT	12
+
+#define T_SATA0_CHX_PHY_CTRL2				0x69c
+#define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1		0x23
+
+#define T_SATA0_CHX_PHY_CTRL11				0x6d0
+#define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ		(0x2800 << 16)
+
+#define FUSE_SATA_CALIB					0x124
+#define FUSE_SATA_CALIB_MASK				0x3
+
+struct sata_pad_calibration {
+	u8 gen1_tx_amp;
+	u8 gen1_tx_peak;
+	u8 gen2_tx_amp;
+	u8 gen2_tx_peak;
+};
+
+static const struct sata_pad_calibration tegra124_pad_calibration[] = {
+	{0x18, 0x04, 0x18, 0x0a},
+	{0x0e, 0x04, 0x14, 0x0a},
+	{0x0e, 0x07, 0x1a, 0x0e},
+	{0x14, 0x0e, 0x1a, 0x0e},
+};
+
+struct tegra_ahci_priv {
+	struct platform_device	   *pdev;
+	void __iomem		   *sata_regs;
+	struct reset_control	   *sata_rst;
+	struct reset_control	   *sata_oob_rst;
+	struct reset_control	   *sata_cold_rst;
+	/* Needs special handling, cannot use ahci_platform */
+	struct clk		   *sata_clk;
+	struct regulator_bulk_data supplies[5];
+};
+
+static int tegra_ahci_power_on(struct ahci_host_priv *hpriv)
+{
+	struct tegra_ahci_priv *tegra = hpriv->plat_data;
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies),
+				    tegra->supplies);
+	if (ret)
+		return ret;
+
+	ret = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SATA,
+						tegra->sata_clk,
+						tegra->sata_rst);
+	if (ret)
+		goto disable_regulators;
+
+	reset_control_assert(tegra->sata_oob_rst);
+	reset_control_assert(tegra->sata_cold_rst);
+
+	ret = ahci_platform_enable_resources(hpriv);
+	if (ret)
+		goto disable_power;
+
+	reset_control_deassert(tegra->sata_cold_rst);
+	reset_control_deassert(tegra->sata_oob_rst);
+
+	return 0;
+
+disable_power:
+	clk_disable_unprepare(tegra->sata_clk);
+
+	tegra_powergate_power_off(TEGRA_POWERGATE_SATA);
+
+disable_regulators:
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+
+	return ret;
+}
+
+static void tegra_ahci_power_off(struct ahci_host_priv *hpriv)
+{
+	struct tegra_ahci_priv *tegra = hpriv->plat_data;
+
+	ahci_platform_disable_resources(hpriv);
+
+	reset_control_assert(tegra->sata_rst);
+	reset_control_assert(tegra->sata_oob_rst);
+	reset_control_assert(tegra->sata_cold_rst);
+
+	clk_disable_unprepare(tegra->sata_clk);
+	tegra_powergate_power_off(TEGRA_POWERGATE_SATA);
+
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+}
+
+static int tegra_ahci_controller_init(struct ahci_host_priv *hpriv)
+{
+	struct tegra_ahci_priv *tegra = hpriv->plat_data;
+	int ret;
+	unsigned int val;
+	struct sata_pad_calibration calib;
+
+	ret = tegra_ahci_power_on(hpriv);
+	if (ret) {
+		dev_err(&tegra->pdev->dev,
+			"failed to power on AHCI controller: %d\n", ret);
+		return ret;
+	}
+
+	val = readl(tegra->sata_regs + SATA_CONFIGURATION_0);
+	val |= SATA_CONFIGURATION_EN_FPCI;
+	writel(val, tegra->sata_regs + SATA_CONFIGURATION_0);
+
+	/* Pad calibration */
+
+	ret = tegra_fuse_readl(FUSE_SATA_CALIB, &val);
+	if (ret) {
+		dev_err(&tegra->pdev->dev,
+			"failed to read calibration fuse: %d\n", ret);
+		return ret;
+	}
+
+	calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK];
+
+	writel(BIT(0), tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX);
+
+	val = readl(tegra->sata_regs +
+		SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1);
+	val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK;
+	val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK;
+	val |= calib.gen1_tx_amp <<
+			T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT;
+	val |= calib.gen1_tx_peak <<
+			T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT;
+	writel(val, tegra->sata_regs + SCFG_OFFSET +
+		T_SATA0_CHX_PHY_CTRL1_GEN1);
+
+	val = readl(tegra->sata_regs +
+			SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2);
+	val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK;
+	val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK;
+	val |= calib.gen2_tx_amp <<
+			T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT;
+	val |= calib.gen2_tx_peak <<
+			T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT;
+	writel(val, tegra->sata_regs + SCFG_OFFSET +
+		T_SATA0_CHX_PHY_CTRL1_GEN2);
+
+	writel(T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ,
+		tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11);
+	writel(T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1,
+		tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2);
+
+	writel(0, tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX);
+
+	/* Program controller device ID */
+
+	val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+	val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+	writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+
+	writel(0x01060100, tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC);
+
+	val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+	val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+	writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+
+	/* Enable IO & memory access, bus master mode */
+
+	val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1);
+	val |= T_SATA0_CFG_1_IO_SPACE | T_SATA0_CFG_1_MEMORY_SPACE |
+		T_SATA0_CFG_1_BUS_MASTER | T_SATA0_CFG_1_SERR;
+	writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1);
+
+	/* Program SATA MMIO */
+
+	writel(0x10000 << SATA_FPCI_BAR5_START_SHIFT,
+	       tegra->sata_regs + SATA_FPCI_BAR5);
+
+	writel(0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT,
+	       tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_9);
+
+	/* Unmask SATA interrupts */
+
+	val = readl(tegra->sata_regs + SATA_INTR_MASK);
+	val |= SATA_INTR_MASK_IP_INT_MASK;
+	writel(val, tegra->sata_regs + SATA_INTR_MASK);
+
+	return 0;
+}
+
+static void tegra_ahci_controller_deinit(struct ahci_host_priv *hpriv)
+{
+	tegra_ahci_power_off(hpriv);
+}
+
+static void tegra_ahci_host_stop(struct ata_host *host)
+{
+	struct ahci_host_priv *hpriv = host->private_data;
+
+	tegra_ahci_controller_deinit(hpriv);
+}
+
+static struct ata_port_operations ahci_tegra_port_ops = {
+	.inherits	= &ahci_ops,
+	.host_stop	= tegra_ahci_host_stop,
+};
+
+static const struct ata_port_info ahci_tegra_port_info = {
+	.flags		= AHCI_FLAG_COMMON,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_tegra_port_ops,
+};
+
+static const struct of_device_id tegra_ahci_of_match[] = {
+	{ .compatible = "nvidia,tegra124-ahci" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tegra_ahci_of_match);
+
+static int tegra_ahci_probe(struct platform_device *pdev)
+{
+	struct ahci_host_priv *hpriv;
+	struct tegra_ahci_priv *tegra;
+	struct resource *res;
+	int ret;
+
+	hpriv = ahci_platform_get_resources(pdev);
+	if (IS_ERR(hpriv))
+		return PTR_ERR(hpriv);
+
+	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+
+	hpriv->plat_data = tegra;
+
+	tegra->pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	tegra->sata_regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->sata_regs))
+		return PTR_ERR(tegra->sata_regs);
+
+	tegra->sata_rst = devm_reset_control_get(&pdev->dev, "sata");
+	if (IS_ERR(tegra->sata_rst)) {
+		dev_err(&pdev->dev, "Failed to get sata reset\n");
+		return PTR_ERR(tegra->sata_rst);
+	}
+
+	tegra->sata_oob_rst = devm_reset_control_get(&pdev->dev, "sata-oob");
+	if (IS_ERR(tegra->sata_oob_rst)) {
+		dev_err(&pdev->dev, "Failed to get sata-oob reset\n");
+		return PTR_ERR(tegra->sata_oob_rst);
+	}
+
+	tegra->sata_cold_rst = devm_reset_control_get(&pdev->dev, "sata-cold");
+	if (IS_ERR(tegra->sata_cold_rst)) {
+		dev_err(&pdev->dev, "Failed to get sata-cold reset\n");
+		return PTR_ERR(tegra->sata_cold_rst);
+	}
+
+	tegra->sata_clk = devm_clk_get(&pdev->dev, "sata");
+	if (IS_ERR(tegra->sata_clk)) {
+		dev_err(&pdev->dev, "Failed to get sata clock\n");
+		return PTR_ERR(tegra->sata_clk);
+	}
+
+	tegra->supplies[0].supply = "avdd";
+	tegra->supplies[1].supply = "hvdd";
+	tegra->supplies[2].supply = "vddio";
+	tegra->supplies[3].supply = "target-5v";
+	tegra->supplies[4].supply = "target-12v";
+
+	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies),
+				      tegra->supplies);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to get regulators\n");
+		return ret;
+	}
+
+	ret = tegra_ahci_controller_init(hpriv);
+	if (ret)
+		return ret;
+
+	ret = ahci_platform_init_host(pdev, hpriv, &ahci_tegra_port_info);
+	if (ret)
+		goto deinit_controller;
+
+	return 0;
+
+deinit_controller:
+	tegra_ahci_controller_deinit(hpriv);
+
+	return ret;
+};
+
+static struct platform_driver tegra_ahci_driver = {
+	.probe = tegra_ahci_probe,
+	.remove = ata_platform_remove_one,
+	.driver = {
+		.name = "tegra-ahci",
+		.of_match_table = tegra_ahci_of_match,
+	},
+	/* LP0 suspend support not implemented */
+};
+module_platform_driver(tegra_ahci_driver);
+
+MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
+MODULE_DESCRIPTION("Tegra124 AHCI SATA driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ahci_xgene.c linux-libre-3.17-rc7-gnu/drivers/ata/ahci_xgene.c
--- linux-libre-3.16-gnu/drivers/ata/ahci_xgene.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ahci_xgene.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,9 @@
 #define PORTAXICFG			0x000000bc
 #define PORTAXICFG_OUTTRANS_SET(dst, src) \
 		(((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000))
+#define PORTRANSCFG			0x000000c8
+#define PORTRANSCFG_RXWM_SET(dst, src)		\
+		(((dst) & ~0x0000007f) | (((u32)(src)) & 0x0000007f))
 
 /* SATA host controller AXI CSR */
 #define INT_SLV_TMOMASK			0x00000010
@@ -75,6 +78,9 @@
 #define CFG_MEM_RAM_SHUTDOWN		0x00000070
 #define BLOCK_MEM_RDY			0x00000074
 
+/* Max retry for link down */
+#define MAX_LINK_DOWN_RETRY 3
+
 struct xgene_ahci_context {
 	struct ahci_host_priv *hpriv;
 	struct device *dev;
@@ -142,6 +148,14 @@ static unsigned int xgene_ahci_qc_issue(
 	return rc;
 }
 
+static bool xgene_ahci_is_memram_inited(struct xgene_ahci_context *ctx)
+{
+	void __iomem *diagcsr = ctx->csr_diag;
+
+	return (readl(diagcsr + CFG_MEM_RAM_SHUTDOWN) == 0 &&
+	        readl(diagcsr + BLOCK_MEM_RDY) == 0xFFFFFFFF);
+}
+
 /**
  * xgene_ahci_read_id - Read ID data from the specified device
  * @dev: device
@@ -193,11 +207,11 @@ static void xgene_ahci_set_phy_cfg(struc
 	/* Disable fix rate */
 	writel(0x0001fffe, mmio + PORTPHY1CFG);
 	readl(mmio + PORTPHY1CFG); /* Force a barrier */
-	writel(0x5018461c, mmio + PORTPHY2CFG);
+	writel(0x28183219, mmio + PORTPHY2CFG);
 	readl(mmio + PORTPHY2CFG); /* Force a barrier */
-	writel(0x1c081907, mmio + PORTPHY3CFG);
+	writel(0x13081008, mmio + PORTPHY3CFG);
 	readl(mmio + PORTPHY3CFG); /* Force a barrier */
-	writel(0x1c080815, mmio + PORTPHY4CFG);
+	writel(0x00480815, mmio + PORTPHY4CFG);
 	readl(mmio + PORTPHY4CFG); /* Force a barrier */
 	/* Set window negotiation */
 	val = readl(mmio + PORTPHY5CFG);
@@ -209,6 +223,10 @@ static void xgene_ahci_set_phy_cfg(struc
 	val = PORTAXICFG_OUTTRANS_SET(val, 0xe); /* Set outstanding */
 	writel(val, mmio + PORTAXICFG);
 	readl(mmio + PORTAXICFG); /* Force a barrier */
+	/* Set the watermark threshold of the receive FIFO */
+	val = readl(mmio + PORTRANSCFG);
+	val = PORTRANSCFG_RXWM_SET(val, 0x30);
+	writel(val, mmio + PORTRANSCFG);
 }
 
 /**
@@ -222,8 +240,11 @@ static void xgene_ahci_set_phy_cfg(struc
  * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will
  * report disparity error and etc. In addition, during COMRESET, there can
  * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and
- * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following
- * algorithm is followed to proper configure the hardware PHY during COMRESET:
+ * SERR_10B_8B_ERR, the PHY receiver line must be reseted. Also during long
+ * reboot cycle regression, sometimes the PHY reports link down even if the
+ * device is present because of speed negotiation failure. so need to retry
+ * the COMRESET to get the link up. The following algorithm is followed to
+ * proper configure the hardware PHY during COMRESET:
  *
  * Alg Part 1:
  * 1. Start the PHY at Gen3 speed (default setting)
@@ -239,9 +260,15 @@ static void xgene_ahci_set_phy_cfg(struc
  * Alg Part 2:
  * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error
  *    reported in the register PORT_SCR_ERR, then reset the PHY receiver line
- * 2. Go to Alg Part 3
+ * 2. Go to Alg Part 4
  *
  * Alg Part 3:
+ * 1. Check the PORT_SCR_STAT to see whether device presence detected but PHY
+ *    communication establishment failed and maximum link down attempts are
+ *    less than Max attempts 3 then goto Alg Part 1.
+ * 2. Go to Alg Part 4.
+ *
+ * Alg Part 4:
  * 1. Clear any pending from register PORT_SCR_ERR.
  *
  * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition
@@ -260,19 +287,27 @@ static int xgene_ahci_do_hardreset(struc
 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 	void __iomem *port_mmio = ahci_port_base(ap);
 	struct ata_taskfile tf;
+	int link_down_retry = 0;
 	int rc;
-	u32 val;
+	u32 val, sstatus;
 
-	/* clear D2H reception area to properly wait for D2H FIS */
-	ata_tf_init(link->device, &tf);
-	tf.command = ATA_BUSY;
-	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
-	rc = sata_link_hardreset(link, timing, deadline, online,
+	do {
+		/* clear D2H reception area to properly wait for D2H FIS */
+		ata_tf_init(link->device, &tf);
+		tf.command = ATA_BUSY;
+		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+		rc = sata_link_hardreset(link, timing, deadline, online,
 				 ahci_check_ready);
+		if (*online) {
+			val = readl(port_mmio + PORT_SCR_ERR);
+			if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
+				dev_warn(ctx->dev, "link has error\n");
+			break;
+		}
 
-	val = readl(port_mmio + PORT_SCR_ERR);
-	if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
-		dev_warn(ctx->dev, "link has error\n");
+		sata_scr_read(link, SCR_STATUS, &sstatus);
+	} while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
+		 (sstatus & 0xff) == 0x1);
 
 	/* clear all errors if any pending */
 	val = readl(port_mmio + PORT_SCR_ERR);
@@ -337,7 +372,7 @@ static struct ata_port_operations xgene_
 };
 
 static const struct ata_port_info xgene_ahci_port_info = {
-	.flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+	.flags = AHCI_FLAG_COMMON,
 	.pio_mask = ATA_PIO4,
 	.udma_mask = ATA_UDMA6,
 	.port_ops = &xgene_ahci_ops,
@@ -415,7 +450,6 @@ static int xgene_ahci_probe(struct platf
 	struct ahci_host_priv *hpriv;
 	struct xgene_ahci_context *ctx;
 	struct resource *res;
-	unsigned long hflags;
 	int rc;
 
 	hpriv = ahci_platform_get_resources(pdev);
@@ -461,6 +495,11 @@ static int xgene_ahci_probe(struct platf
 		return -ENODEV;
 	}
 
+	if (xgene_ahci_is_memram_inited(ctx)) {
+		dev_info(dev, "skip clock and PHY initialization\n");
+		goto skip_clk_phy;
+	}
+
 	/* Due to errata, HW requires full toggle transition */
 	rc = ahci_platform_enable_clks(hpriv);
 	if (rc)
@@ -473,21 +512,10 @@ static int xgene_ahci_probe(struct platf
 
 	/* Configure the host controller */
 	xgene_ahci_hw_init(hpriv);
+skip_clk_phy:
+	hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
 
-	/*
-	 * Setup DMA mask. This is preliminary until the DMA range is sorted
-	 * out.
-	 */
-	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
-	if (rc) {
-		dev_err(dev, "Unable to set dma mask\n");
-		goto disable_resources;
-	}
-
-	hflags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
-
-	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info,
-				     hflags, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info);
 	if (rc)
 		goto disable_resources;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/ata_piix.c linux-libre-3.17-rc7-gnu/drivers/ata/ata_piix.c
--- linux-libre-3.16-gnu/drivers/ata/ata_piix.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/ata_piix.c	2014-09-28 17:29:07.000000000 -0400
@@ -340,6 +340,14 @@ static const struct pci_device_id piix_p
 	{ 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
 	/* SATA Controller IDE (Coleto Creek) */
 	{ 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (9 Series) */
+	{ 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
+	/* SATA Controller IDE (9 Series) */
+	{ 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
+	/* SATA Controller IDE (9 Series) */
+	{ 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+	/* SATA Controller IDE (9 Series) */
+	{ 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 
 	{ }	/* terminate list */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/Kconfig linux-libre-3.17-rc7-gnu/drivers/ata/Kconfig
--- linux-libre-3.16-gnu/drivers/ata/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@ menuconfig ATA
 	depends on BLOCK
 	depends on !(M32R || M68K || S390) || BROKEN
 	select SCSI
+	select GLOB
 	---help---
 	  If you want to use an ATA hard disk, ATA tape drive, ATA CD-ROM or
 	  any other ATA device under Linux, say Y and make sure that you know
@@ -140,6 +141,15 @@ config AHCI_SUNXI
 	  onboard AHCI SATA.
 
 	  If unsure, say N.
+
+config AHCI_TEGRA
+	tristate "NVIDIA Tegra124 AHCI SATA support"
+	depends on ARCH_TEGRA
+	help
+	  This option enables support for the NVIDIA Tegra124 SoC's
+	  onboard AHCI SATA.
+
+	  If unsure, say N.
 
 config AHCI_XGENE
 	tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/libahci.c linux-libre-3.17-rc7-gnu/drivers/ata/libahci.c
--- linux-libre-3.16-gnu/drivers/ata/libahci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/libahci.c	2014-09-28 17:29:07.000000000 -0400
@@ -382,8 +382,6 @@ static ssize_t ahci_show_em_supported(st
  *	ahci_save_initial_config - Save and fixup initial config values
  *	@dev: target AHCI device
  *	@hpriv: host private area to store config values
- *	@force_port_map: force port map to a specified value
- *	@mask_port_map: mask out particular bits from port map
  *
  *	Some registers containing configuration info might be setup by
  *	BIOS and might be cleared on reset.  This function saves the
@@ -398,10 +396,7 @@ static ssize_t ahci_show_em_supported(st
  *	LOCKING:
  *	None.
  */
-void ahci_save_initial_config(struct device *dev,
-			      struct ahci_host_priv *hpriv,
-			      unsigned int force_port_map,
-			      unsigned int mask_port_map)
+void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 {
 	void __iomem *mmio = hpriv->mmio;
 	u32 cap, cap2, vers, port_map;
@@ -468,17 +463,17 @@ void ahci_save_initial_config(struct dev
 		cap &= ~HOST_CAP_FBS;
 	}
 
-	if (force_port_map && port_map != force_port_map) {
+	if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
 		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
-			 port_map, force_port_map);
-		port_map = force_port_map;
+			 port_map, hpriv->force_port_map);
+		port_map = hpriv->force_port_map;
 	}
 
-	if (mask_port_map) {
+	if (hpriv->mask_port_map) {
 		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
 			port_map,
-			port_map & mask_port_map);
-		port_map &= mask_port_map;
+			port_map & hpriv->mask_port_map);
+		port_map &= hpriv->mask_port_map;
 	}
 
 	/* cross check port_map and cap.n_ports */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/libahci_platform.c linux-libre-3.17-rc7-gnu/drivers/ata/libahci_platform.c
--- linux-libre-3.16-gnu/drivers/ata/libahci_platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/libahci_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,67 @@ static struct scsi_host_template ahci_pl
 };
 
 /**
+ * ahci_platform_enable_phys - Enable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the PHYs found in hpriv->phys, if any.
+ * If a PHY fails to be enabled, it disables all the PHYs already
+ * enabled in reverse order and returns an error.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
+{
+	int rc, i;
+
+	for (i = 0; i < hpriv->nports; i++) {
+		if (!hpriv->phys[i])
+			continue;
+
+		rc = phy_init(hpriv->phys[i]);
+		if (rc)
+			goto disable_phys;
+
+		rc = phy_power_on(hpriv->phys[i]);
+		if (rc) {
+			phy_exit(hpriv->phys[i]);
+			goto disable_phys;
+		}
+	}
+
+	return 0;
+
+disable_phys:
+	while (--i >= 0) {
+		phy_power_off(hpriv->phys[i]);
+		phy_exit(hpriv->phys[i]);
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
+
+/**
+ * ahci_platform_disable_phys - Disable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all PHYs found in hpriv->phys.
+ */
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
+{
+	int i;
+
+	for (i = 0; i < hpriv->nports; i++) {
+		if (!hpriv->phys[i])
+			continue;
+
+		phy_power_off(hpriv->phys[i]);
+		phy_exit(hpriv->phys[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
+
+/**
  * ahci_platform_enable_clks - Enable platform clocks
  * @hpriv: host private area to store config values
  *
@@ -92,7 +153,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_
  * following order:
  * 1) Regulator
  * 2) Clocks (through ahci_platform_enable_clks)
- * 3) Phy
+ * 3) Phys
  *
  * If resource enabling fails at any point the previous enabled resources
  * are disabled in reverse order.
@@ -114,17 +175,9 @@ int ahci_platform_enable_resources(struc
 	if (rc)
 		goto disable_regulator;
 
-	if (hpriv->phy) {
-		rc = phy_init(hpriv->phy);
-		if (rc)
-			goto disable_clks;
-
-		rc = phy_power_on(hpriv->phy);
-		if (rc) {
-			phy_exit(hpriv->phy);
-			goto disable_clks;
-		}
-	}
+	rc = ahci_platform_enable_phys(hpriv);
+	if (rc)
+		goto disable_clks;
 
 	return 0;
 
@@ -144,16 +197,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_r
  *
  * This function disables all ahci_platform managed resources in the
  * following order:
- * 1) Phy
+ * 1) Phys
  * 2) Clocks (through ahci_platform_disable_clks)
  * 3) Regulator
  */
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
-	if (hpriv->phy) {
-		phy_power_off(hpriv->phy);
-		phy_exit(hpriv->phy);
-	}
+	ahci_platform_disable_phys(hpriv);
 
 	ahci_platform_disable_clks(hpriv);
 
@@ -187,7 +237,7 @@ static void ahci_platform_put_resources(
  * 2) regulator for controlling the targets power (optional)
  * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
  *    or for non devicetree enabled platforms a single clock
- *	4) phy (optional)
+ *	4) phys (optional)
  *
  * RETURNS:
  * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -197,7 +247,9 @@ struct ahci_host_priv *ahci_platform_get
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
 	struct clk *clk;
-	int i, rc = -ENOMEM;
+	struct device_node *child;
+	int i, enabled_ports = 0, rc = -ENOMEM;
+	u32 mask_port_map = 0;
 
 	if (!devres_open_group(dev, NULL, GFP_KERNEL))
 		return ERR_PTR(-ENOMEM);
@@ -246,28 +298,89 @@ struct ahci_host_priv *ahci_platform_get
 		hpriv->clks[i] = clk;
 	}
 
-	hpriv->phy = devm_phy_get(dev, "sata-phy");
-	if (IS_ERR(hpriv->phy)) {
-		rc = PTR_ERR(hpriv->phy);
-		switch (rc) {
-		case -ENOSYS:
-			/* No PHY support. Check if PHY is required. */
-			if (of_find_property(dev->of_node, "phys", NULL)) {
-				dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+	hpriv->nports = of_get_child_count(dev->of_node);
+
+	if (hpriv->nports) {
+		hpriv->phys = devm_kzalloc(dev,
+					   hpriv->nports * sizeof(*hpriv->phys),
+					   GFP_KERNEL);
+		if (!hpriv->phys) {
+			rc = -ENOMEM;
+			goto err_out;
+		}
+
+		for_each_child_of_node(dev->of_node, child) {
+			u32 port;
+
+			if (!of_device_is_available(child))
+				continue;
+
+			if (of_property_read_u32(child, "reg", &port)) {
+				rc = -EINVAL;
 				goto err_out;
 			}
-		case -ENODEV:
-			/* continue normally */
-			hpriv->phy = NULL;
-			break;
 
-		case -EPROBE_DEFER:
-			goto err_out;
+			if (port >= hpriv->nports) {
+				dev_warn(dev, "invalid port number %d\n", port);
+				continue;
+			}
 
-		default:
-			dev_err(dev, "couldn't get sata-phy\n");
+			mask_port_map |= BIT(port);
+
+			hpriv->phys[port] = devm_of_phy_get(dev, child, NULL);
+			if (IS_ERR(hpriv->phys[port])) {
+				rc = PTR_ERR(hpriv->phys[port]);
+				dev_err(dev,
+					"couldn't get PHY in node %s: %d\n",
+					child->name, rc);
+				goto err_out;
+			}
+
+			enabled_ports++;
+		}
+		if (!enabled_ports) {
+			dev_warn(dev, "No port enabled\n");
+			rc = -ENODEV;
 			goto err_out;
 		}
+
+		if (!hpriv->mask_port_map)
+			hpriv->mask_port_map = mask_port_map;
+	} else {
+		/*
+		 * If no sub-node was found, keep this for device tree
+		 * compatibility
+		 */
+		struct phy *phy = devm_phy_get(dev, "sata-phy");
+		if (!IS_ERR(phy)) {
+			hpriv->phys = devm_kzalloc(dev, sizeof(*hpriv->phys),
+						   GFP_KERNEL);
+			if (!hpriv->phys) {
+				rc = -ENOMEM;
+				goto err_out;
+			}
+
+			hpriv->phys[0] = phy;
+			hpriv->nports = 1;
+		} else {
+			rc = PTR_ERR(phy);
+			switch (rc) {
+				case -ENOSYS:
+					/* No PHY support. Check if PHY is required. */
+					if (of_find_property(dev->of_node, "phys", NULL)) {
+						dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+						goto err_out;
+					}
+				case -ENODEV:
+					/* continue normally */
+					hpriv->phys = NULL;
+					break;
+
+				default:
+					goto err_out;
+
+			}
+		}
 	}
 
 	pm_runtime_enable(dev);
@@ -288,12 +401,9 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_reso
  * @pdev: platform device pointer for the host
  * @hpriv: ahci-host private data for the host
  * @pi_template: template for the ata_port_info to use
- * @host_flags: ahci host flags used in ahci_host_priv
- * @force_port_map: param passed to ahci_save_initial_config
- * @mask_port_map: param passed to ahci_save_initial_config
  *
  * This function does all the usual steps needed to bring up an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
  * must be initialized / enabled before calling this.
  *
  * RETURNS:
@@ -301,10 +411,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_reso
  */
 int ahci_platform_init_host(struct platform_device *pdev,
 			    struct ahci_host_priv *hpriv,
-			    const struct ata_port_info *pi_template,
-			    unsigned long host_flags,
-			    unsigned int force_port_map,
-			    unsigned int mask_port_map)
+			    const struct ata_port_info *pi_template)
 {
 	struct device *dev = &pdev->dev;
 	struct ata_port_info pi = *pi_template;
@@ -319,10 +426,9 @@ int ahci_platform_init_host(struct platf
 	}
 
 	/* prepare host */
-	pi.private_data = (void *)host_flags;
-	hpriv->flags |= host_flags;
+	pi.private_data = (void *)(unsigned long)hpriv->flags;
 
-	ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+	ahci_save_initial_config(dev, hpriv);
 
 	if (hpriv->cap & HOST_CAP_NCQ)
 		pi.flags |= ATA_FLAG_NCQ;
@@ -369,6 +475,19 @@ int ahci_platform_init_host(struct platf
 			ap->ops = &ata_dummy_port_ops;
 	}
 
+	if (hpriv->cap & HOST_CAP_64) {
+		rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
+		if (rc) {
+			rc = dma_coerce_mask_and_coherent(dev,
+							  DMA_BIT_MASK(32));
+			if (rc) {
+				dev_err(dev, "Failed to enable 64-bit DMA.\n");
+				return rc;
+			}
+			dev_warn(dev, "Enable 32-bit DMA instead of 64-bit.\n");
+		}
+	}
+
 	rc = ahci_reset_controller(host);
 	if (rc)
 		return rc;
@@ -399,7 +518,7 @@ static void ahci_host_stop(struct ata_ho
  * @dev: device pointer for the host
  *
  * This function does all the usual steps needed to suspend an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
  * must be disabled after calling this.
  *
  * RETURNS:
@@ -436,7 +555,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_
  * @dev: device pointer for the host
  *
  * This function does all the usual steps needed to resume an ahci-platform
- * host, note any necessary resources (ie clks, phy, etc.)  must be
+ * host, note any necessary resources (ie clks, phys, etc.)  must be
  * initialized / enabled before calling this.
  *
  * RETURNS:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/libata-core.c linux-libre-3.17-rc7-gnu/drivers/ata/libata-core.c
--- linux-libre-3.16-gnu/drivers/ata/libata-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/libata-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,7 @@
 #include <linux/async.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
+#include <linux/glob.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -4227,7 +4228,7 @@ static const struct ata_blacklist_entry
 	{ "Micron_M500*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
 	{ "Crucial_CT???M500SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
 	{ "Micron_M550*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
-	{ "Crucial_CT???M550SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Crucial_CT*M550SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
 
 	/*
 	 * Some WD SATA-I drives spin up and down erratically when the link
@@ -4250,73 +4251,6 @@ static const struct ata_blacklist_entry
 	{ }
 };
 
-/**
- *	glob_match - match a text string against a glob-style pattern
- *	@text: the string to be examined
- *	@pattern: the glob-style pattern to be matched against
- *
- *	Either/both of text and pattern can be empty strings.
- *
- *	Match text against a glob-style pattern, with wildcards and simple sets:
- *
- *		?	matches any single character.
- *		*	matches any run of characters.
- *		[xyz]	matches a single character from the set: x, y, or z.
- *		[a-d]	matches a single character from the range: a, b, c, or d.
- *		[a-d0-9] matches a single character from either range.
- *
- *	The special characters ?, [, -, or *, can be matched using a set, eg. [*]
- *	Behaviour with malformed patterns is undefined, though generally reasonable.
- *
- *	Sample patterns:  "SD1?",  "SD1[0-5]",  "*R0",  "SD*1?[012]*xx"
- *
- *	This function uses one level of recursion per '*' in pattern.
- *	Since it calls _nothing_ else, and has _no_ explicit local variables,
- *	this will not cause stack problems for any reasonable use here.
- *
- *	RETURNS:
- *	0 on match, 1 otherwise.
- */
-static int glob_match (const char *text, const char *pattern)
-{
-	do {
-		/* Match single character or a '?' wildcard */
-		if (*text == *pattern || *pattern == '?') {
-			if (!*pattern++)
-				return 0;  /* End of both strings: match */
-		} else {
-			/* Match single char against a '[' bracketed ']' pattern set */
-			if (!*text || *pattern != '[')
-				break;  /* Not a pattern set */
-			while (*++pattern && *pattern != ']' && *text != *pattern) {
-				if (*pattern == '-' && *(pattern - 1) != '[')
-					if (*text > *(pattern - 1) && *text < *(pattern + 1)) {
-						++pattern;
-						break;
-					}
-			}
-			if (!*pattern || *pattern == ']')
-				return 1;  /* No match */
-			while (*pattern && *pattern++ != ']');
-		}
-	} while (*++text && *pattern);
-
-	/* Match any run of chars against a '*' wildcard */
-	if (*pattern == '*') {
-		if (!*++pattern)
-			return 0;  /* Match: avoid recursion at end of pattern */
-		/* Loop to handle additional pattern chars after the wildcard */
-		while (*text) {
-			if (glob_match(text, pattern) == 0)
-				return 0;  /* Remainder matched */
-			++text;  /* Absorb (match) this char and try again */
-		}
-	}
-	if (!*text && !*pattern)
-		return 0;  /* End of both strings: match */
-	return 1;  /* No match */
-}
-
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -4327,10 +4261,10 @@ static unsigned long ata_dev_blacklisted
 	ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
 
 	while (ad->model_num) {
-		if (!glob_match(model_num, ad->model_num)) {
+		if (glob_match(model_num, ad->model_num)) {
 			if (ad->model_rev == NULL)
 				return ad->horkage;
-			if (!glob_match(model_rev, ad->model_rev))
+			if (glob_match(model_rev, ad->model_rev))
 				return ad->horkage;
 		}
 		ad++;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/libata.h linux-libre-3.17-rc7-gnu/drivers/ata/libata.h
--- linux-libre-3.16-gnu/drivers/ata/libata.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/libata.h	2014-09-28 17:29:07.000000000 -0400
@@ -144,7 +144,7 @@ extern void ata_schedule_scsi_eh(struct
 extern void ata_scsi_dev_rescan(struct work_struct *work);
 extern int ata_bus_probe(struct ata_port *ap);
 extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-			      unsigned int id, unsigned int lun);
+			      unsigned int id, u64 lun);
 
 
 /* libata-eh.c */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/libata-scsi.c linux-libre-3.17-rc7-gnu/drivers/ata/libata-scsi.c
--- linux-libre-3.16-gnu/drivers/ata/libata-scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/libata-scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -3945,7 +3945,7 @@ void ata_scsi_hotplug(struct work_struct
  *	Zero.
  */
 int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-		       unsigned int id, unsigned int lun)
+		       unsigned int id, u64 lun)
 {
 	struct ata_port *ap = ata_shost_to_port(shost);
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/Makefile linux-libre-3.17-rc7-gnu/drivers/ata/Makefile
--- linux-libre-3.16-gnu/drivers/ata/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@ obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o li
 obj-$(CONFIG_AHCI_MVEBU)	+= ahci_mvebu.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_SUNXI)	+= ahci_sunxi.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_ST)		+= ahci_st.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_TEGRA)	+= ahci_tegra.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_XGENE)	+= ahci_xgene.o libahci.o libahci_platform.o
 
 # SFF w/ custom DMA
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/pata_jmicron.c linux-libre-3.17-rc7-gnu/drivers/ata/pata_jmicron.c
--- linux-libre-3.16-gnu/drivers/ata/pata_jmicron.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/pata_jmicron.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,6 +143,18 @@ static int jmicron_init_one (struct pci_
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
+	/*
+	 * The JMicron chip 361/363 contains one SATA controller and one
+	 * PATA controller,for powering on these both controllers, we must
+	 * follow the sequence one by one, otherwise one of them can not be
+	 * powered on successfully, so here we disable the async suspend
+	 * method for these chips.
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
+		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
+		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
+		device_disable_async_suspend(&pdev->dev);
+
 	return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/pata_samsung_cf.c linux-libre-3.17-rc7-gnu/drivers/ata/pata_samsung_cf.c
--- linux-libre-3.16-gnu/drivers/ata/pata_samsung_cf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/pata_samsung_cf.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,6 @@
 
 enum s3c_cpu_type {
 	TYPE_S3C64XX,
-	TYPE_S5PC100,
 	TYPE_S5PV210,
 };
 
@@ -361,7 +360,7 @@ static int pata_s3c_wait_after_reset(str
 /*
  * pata_s3c_bus_softreset - PATA device software reset
  */
-static unsigned int pata_s3c_bus_softreset(struct ata_port *ap,
+static int pata_s3c_bus_softreset(struct ata_port *ap,
 		unsigned long deadline)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -476,10 +475,6 @@ static void pata_s3c_hwinit(struct s3c_i
 		writel(0x1b, info->ide_addr + S3C_ATA_IRQ_MSK);
 		break;
 
-	case TYPE_S5PC100:
-		pata_s3c_cfg_mode(info->sfr_addr);
-		/* FALLTHROUGH */
-
 	case TYPE_S5PV210:
 		/* Configure as little endian */
 		pata_s3c_set_endian(info->ide_addr, 0);
@@ -549,11 +544,6 @@ static int __init pata_s3c_probe(struct
 		info->sfr_addr = info->ide_addr + 0x1800;
 		info->ide_addr += 0x1900;
 		info->fifo_status_reg = 0x94;
-	} else if (cpu_type == TYPE_S5PC100) {
-		ap->ops = &pata_s5p_port_ops;
-		info->sfr_addr = info->ide_addr + 0x1800;
-		info->ide_addr += 0x1900;
-		info->fifo_status_reg = 0x84;
 	} else {
 		ap->ops = &pata_s5p_port_ops;
 		info->fifo_status_reg = 0x84;
@@ -653,9 +643,6 @@ static struct platform_device_id pata_s3
 		.name		= "s3c64xx-pata",
 		.driver_data	= TYPE_S3C64XX,
 	}, {
-		.name		= "s5pc100-pata",
-		.driver_data	= TYPE_S5PC100,
-	}, {
 		.name		= "s5pv210-pata",
 		.driver_data	= TYPE_S5PV210,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/pata_scc.c linux-libre-3.17-rc7-gnu/drivers/ata/pata_scc.c
--- linux-libre-3.16-gnu/drivers/ata/pata_scc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/pata_scc.c	2014-09-28 17:29:07.000000000 -0400
@@ -585,7 +585,7 @@ static int scc_wait_after_reset(struct a
  *	Note: Original code is ata_bus_softreset().
  */
 
-static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
+static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
                                       unsigned long deadline)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -599,9 +599,7 @@ static unsigned int scc_bus_softreset(st
 	udelay(20);
 	out_be32(ioaddr->ctl_addr, ap->ctl);
 
-	scc_wait_after_reset(&ap->link, devmask, deadline);
-
-	return 0;
+	return scc_wait_after_reset(&ap->link, devmask, deadline);
 }
 
 /**
@@ -618,7 +616,8 @@ static int scc_softreset(struct ata_link
 {
 	struct ata_port *ap = link->ap;
 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
-	unsigned int devmask = 0, err_mask;
+	unsigned int devmask = 0;
+	int rc;
 	u8 err;
 
 	DPRINTK("ENTER\n");
@@ -634,9 +633,9 @@ static int scc_softreset(struct ata_link
 
 	/* issue bus reset */
 	DPRINTK("about to softreset, devmask=%x\n", devmask);
-	err_mask = scc_bus_softreset(ap, devmask, deadline);
-	if (err_mask) {
-		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask);
+	rc = scc_bus_softreset(ap, devmask, deadline);
+	if (rc) {
+		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc);
 		return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/sata_fsl.c linux-libre-3.17-rc7-gnu/drivers/ata/sata_fsl.c
--- linux-libre-3.16-gnu/drivers/ata/sata_fsl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/sata_fsl.c	2014-09-28 17:29:07.000000000 -0400
@@ -734,13 +734,12 @@ static int sata_fsl_port_start(struct at
 	if (!pp)
 		return -ENOMEM;
 
-	mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
-				 GFP_KERNEL);
+	mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+				  GFP_KERNEL);
 	if (!mem) {
 		kfree(pp);
 		return -ENOMEM;
 	}
-	memset(mem, 0, SATA_FSL_PORT_PRIV_DMA_SZ);
 
 	pp->cmdslot = mem;
 	pp->cmdslot_paddr = mem_dma;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/sata_highbank.c linux-libre-3.17-rc7-gnu/drivers/ata/sata_highbank.c
--- linux-libre-3.16-gnu/drivers/ata/sata_highbank.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/sata_highbank.c	2014-09-28 17:29:07.000000000 -0400
@@ -512,7 +512,7 @@ static int ahci_highbank_probe(struct pl
 		return rc;
 
 
-	ahci_save_initial_config(dev, hpriv, 0, 0);
+	ahci_save_initial_config(dev, hpriv);
 
 	/* prepare host */
 	if (hpriv->cap & HOST_CAP_NCQ)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ata/sata_sil24.c linux-libre-3.17-rc7-gnu/drivers/ata/sata_sil24.c
--- linux-libre-3.16-gnu/drivers/ata/sata_sil24.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ata/sata_sil24.c	2014-09-28 17:29:07.000000000 -0400
@@ -1154,8 +1154,8 @@ static irqreturn_t sil24_interrupt(int i
 	status = readl(host_base + HOST_IRQ_STAT);
 
 	if (status == 0xffffffff) {
-		printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
-		       "PCI fault or device removal?\n");
+		dev_err(host->dev, "IRQ status == 0xffffffff, "
+			"PCI fault or device removal?\n");
 		goto out;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/atm/atmtcp.c linux-libre-3.17-rc7-gnu/drivers/atm/atmtcp.c
--- linux-libre-3.16-gnu/drivers/atm/atmtcp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/atm/atmtcp.c	2014-09-28 17:29:07.000000000 -0400
@@ -299,6 +299,7 @@ static int atmtcp_c_send(struct atm_vcc
 	out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci));
 	read_unlock(&vcc_sklist_lock);
 	if (!out_vcc) {
+		result = -EUNATCH;
 		atomic_inc(&vcc->stats->tx_err);
 		goto done;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/atm/eni.c linux-libre-3.17-rc7-gnu/drivers/atm/eni.c
--- linux-libre-3.16-gnu/drivers/atm/eni.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/atm/eni.c	2014-09-28 17:29:07.000000000 -0400
@@ -2155,7 +2155,7 @@ static int eni_proc_read(struct atm_dev
 
 		if (!tx->send) continue;
 		if (!--left) {
-			return sprintf(page,"tx[%d]:    0x%ld-0x%ld "
+			return sprintf(page, "tx[%d]:    0x%lx-0x%lx "
 			    "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
 			    (unsigned long) (tx->send - eni_dev->ram),
 			    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
@@ -2181,7 +2181,7 @@ static int eni_proc_read(struct atm_dev
 			if (--left) continue;
 			length = sprintf(page,"vcc %4d: ",vcc->vci);
 			if (eni_vcc->rx) {
-				length += sprintf(page+length,"0x%ld-0x%ld "
+				length += sprintf(page+length, "0x%lx-0x%lx "
 				    "(%6ld bytes)",
 				    (unsigned long) (eni_vcc->recv - eni_dev->ram),
 				    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/atm/he.c linux-libre-3.17-rc7-gnu/drivers/atm/he.c
--- linux-libre-3.16-gnu/drivers/atm/he.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/atm/he.c	2014-09-28 17:29:07.000000000 -0400
@@ -533,14 +533,13 @@ static void he_init_tx_lbfp(struct he_de
 
 static int he_init_tpdrq(struct he_dev *he_dev)
 {
-	he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
-		CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
+	he_dev->tpdrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+						   CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
+						   &he_dev->tpdrq_phys);
 	if (he_dev->tpdrq_base == NULL) {
 		hprintk("failed to alloc tpdrq\n");
 		return -ENOMEM;
 	}
-	memset(he_dev->tpdrq_base, 0,
-				CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
 
 	he_dev->tpdrq_tail = he_dev->tpdrq_base;
 	he_dev->tpdrq_head = he_dev->tpdrq_base;
@@ -804,13 +803,13 @@ static int he_init_group(struct he_dev *
 		goto out_free_rbpl_virt;
 	}
 
-	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
-		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
+	he_dev->rbpl_base = pci_zalloc_consistent(he_dev->pci_dev,
+						  CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+						  &he_dev->rbpl_phys);
 	if (he_dev->rbpl_base == NULL) {
 		hprintk("failed to alloc rbpl_base\n");
 		goto out_destroy_rbpl_pool;
 	}
-	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
 
 	INIT_LIST_HEAD(&he_dev->rbpl_outstanding);
 
@@ -843,13 +842,13 @@ static int he_init_group(struct he_dev *
 
 	/* rx buffer ready queue */
 
-	he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
-		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
+	he_dev->rbrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+						  CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+						  &he_dev->rbrq_phys);
 	if (he_dev->rbrq_base == NULL) {
 		hprintk("failed to allocate rbrq\n");
 		goto out_free_rbpl;
 	}
-	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 
 	he_dev->rbrq_head = he_dev->rbrq_base;
 	he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
@@ -867,13 +866,13 @@ static int he_init_group(struct he_dev *
 
 	/* tx buffer ready queue */
 
-	he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
-		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
+	he_dev->tbrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+						  CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+						  &he_dev->tbrq_phys);
 	if (he_dev->tbrq_base == NULL) {
 		hprintk("failed to allocate tbrq\n");
 		goto out_free_rbpq_base;
 	}
-	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 
 	he_dev->tbrq_head = he_dev->tbrq_base;
 
@@ -1460,13 +1459,13 @@ static int he_start(struct atm_dev *dev)
 
 	/* host status page */
 
-	he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
-				sizeof(struct he_hsp), &he_dev->hsp_phys);
+	he_dev->hsp = pci_zalloc_consistent(he_dev->pci_dev,
+					    sizeof(struct he_hsp),
+					    &he_dev->hsp_phys);
 	if (he_dev->hsp == NULL) {
 		hprintk("failed to allocate host status page\n");
 		return -ENOMEM;
 	}
-	memset(he_dev->hsp, 0, sizeof(struct he_hsp));
 	he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
 
 	/* initialize framer */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/atm/idt77252.c linux-libre-3.17-rc7-gnu/drivers/atm/idt77252.c
--- linux-libre-3.16-gnu/drivers/atm/idt77252.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/atm/idt77252.c	2014-09-28 17:29:07.000000000 -0400
@@ -641,13 +641,11 @@ alloc_scq(struct idt77252_dev *card, int
 	scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
 	if (!scq)
 		return NULL;
-	scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE,
-					 &scq->paddr);
+	scq->base = pci_zalloc_consistent(card->pcidev, SCQ_SIZE, &scq->paddr);
 	if (scq->base == NULL) {
 		kfree(scq);
 		return NULL;
 	}
-	memset(scq->base, 0, SCQ_SIZE);
 
 	scq->next = scq->base;
 	scq->last = scq->base + (SCQ_ENTRIES - 1);
@@ -972,13 +970,12 @@ init_rsq(struct idt77252_dev *card)
 {
 	struct rsq_entry *rsqe;
 
-	card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE,
-					      &card->rsq.paddr);
+	card->rsq.base = pci_zalloc_consistent(card->pcidev, RSQSIZE,
+					       &card->rsq.paddr);
 	if (card->rsq.base == NULL) {
 		printk("%s: can't allocate RSQ.\n", card->name);
 		return -1;
 	}
-	memset(card->rsq.base, 0, RSQSIZE);
 
 	card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;
 	card->rsq.next = card->rsq.last;
@@ -3400,14 +3397,14 @@ static int init_card(struct atm_dev *dev
 	writel(0, SAR_REG_GP);
 
 	/* Initialize RAW Cell Handle Register  */
-	card->raw_cell_hnd = pci_alloc_consistent(card->pcidev, 2 * sizeof(u32),
-						  &card->raw_cell_paddr);
+	card->raw_cell_hnd = pci_zalloc_consistent(card->pcidev,
+						   2 * sizeof(u32),
+						   &card->raw_cell_paddr);
 	if (!card->raw_cell_hnd) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
-	memset(card->raw_cell_hnd, 0, 2 * sizeof(u32));
 	writel(card->raw_cell_paddr, SAR_REG_RAWHND);
 	IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name,
 		card->raw_cell_hnd);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/atm/solos-pci.c linux-libre-3.17-rc7-gnu/drivers/atm/solos-pci.c
--- linux-libre-3.16-gnu/drivers/atm/solos-pci.c	2014-08-07 04:45:35.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/atm/solos-pci.c	2014-09-28 21:26:07.000000000 -0400
@@ -1276,6 +1276,7 @@ static int fpga_probe(struct pci_dev *de
 			card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
 			if (!card->dma_bounce) {
 				dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
+				err = -ENOMEM;
 				/* Fallback to MMIO doesn't work */
 				goto out_unmap_both;
 			}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/component.c linux-libre-3.17-rc7-gnu/drivers/base/component.c
--- linux-libre-3.16-gnu/drivers/base/component.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/component.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,15 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 
+struct component_match {
+	size_t alloc;
+	size_t num;
+	struct {
+		void *data;
+		int (*fn)(struct device *, void *);
+	} compare[0];
+};
+
 struct master {
 	struct list_head node;
 	struct list_head components;
@@ -25,6 +34,7 @@ struct master {
 
 	const struct component_master_ops *ops;
 	struct device *dev;
+	struct component_match *match;
 };
 
 struct component {
@@ -69,6 +79,11 @@ static void component_detach_master(stru
 	c->master = NULL;
 }
 
+/*
+ * Add a component to a master, finding the component via the compare
+ * function and compare data.  This is safe to call for duplicate matches
+ * and will not result in the same component being added multiple times.
+ */
 int component_master_add_child(struct master *master,
 	int (*compare)(struct device *, void *), void *compare_data)
 {
@@ -76,11 +91,12 @@ int component_master_add_child(struct ma
 	int ret = -ENXIO;
 
 	list_for_each_entry(c, &component_list, node) {
-		if (c->master)
+		if (c->master && c->master != master)
 			continue;
 
 		if (compare(c->dev, compare_data)) {
-			component_attach_master(master, c);
+			if (!c->master)
+				component_attach_master(master, c);
 			ret = 0;
 			break;
 		}
@@ -90,6 +106,34 @@ int component_master_add_child(struct ma
 }
 EXPORT_SYMBOL_GPL(component_master_add_child);
 
+static int find_components(struct master *master)
+{
+	struct component_match *match = master->match;
+	size_t i;
+	int ret = 0;
+
+	if (!match) {
+		/*
+		 * Search the list of components, looking for components that
+		 * belong to this master, and attach them to the master.
+		 */
+		return master->ops->add_components(master->dev, master);
+	}
+
+	/*
+	 * Scan the array of match functions and attach
+	 * any components which are found to this master.
+	 */
+	for (i = 0; i < match->num; i++) {
+		ret = component_master_add_child(master,
+						 match->compare[i].fn,
+						 match->compare[i].data);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
 /* Detach all attached components from this master */
 static void master_remove_components(struct master *master)
 {
@@ -113,44 +157,44 @@ static void master_remove_components(str
 static int try_to_bring_up_master(struct master *master,
 	struct component *component)
 {
-	int ret = 0;
+	int ret;
 
-	if (!master->bound) {
-		/*
-		 * Search the list of components, looking for components that
-		 * belong to this master, and attach them to the master.
-		 */
-		if (master->ops->add_components(master->dev, master)) {
-			/* Failed to find all components */
-			master_remove_components(master);
-			ret = 0;
-			goto out;
-		}
+	if (master->bound)
+		return 0;
 
-		if (component && component->master != master) {
-			master_remove_components(master);
-			ret = 0;
-			goto out;
-		}
+	/*
+	 * Search the list of components, looking for components that
+	 * belong to this master, and attach them to the master.
+	 */
+	if (find_components(master)) {
+		/* Failed to find all components */
+		ret = 0;
+		goto out;
+	}
 
-		if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
-			ret = -ENOMEM;
-			goto out;
-		}
+	if (component && component->master != master) {
+		ret = 0;
+		goto out;
+	}
 
-		/* Found all components */
-		ret = master->ops->bind(master->dev);
-		if (ret < 0) {
-			devres_release_group(master->dev, NULL);
-			dev_info(master->dev, "master bind failed: %d\n", ret);
-			master_remove_components(master);
-			goto out;
-		}
+	if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
-		master->bound = true;
-		ret = 1;
+	/* Found all components */
+	ret = master->ops->bind(master->dev);
+	if (ret < 0) {
+		devres_release_group(master->dev, NULL);
+		dev_info(master->dev, "master bind failed: %d\n", ret);
+		goto out;
 	}
+
+	master->bound = true;
+	return 1;
+
 out:
+	master_remove_components(master);
 
 	return ret;
 }
@@ -180,18 +224,89 @@ static void take_down_master(struct mast
 	master_remove_components(master);
 }
 
-int component_master_add(struct device *dev,
-	const struct component_master_ops *ops)
+static size_t component_match_size(size_t num)
+{
+	return offsetof(struct component_match, compare[num]);
+}
+
+static struct component_match *component_match_realloc(struct device *dev,
+	struct component_match *match, size_t num)
+{
+	struct component_match *new;
+
+	if (match && match->alloc == num)
+		return match;
+
+	new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+	if (match) {
+		memcpy(new, match, component_match_size(min(match->num, num)));
+		devm_kfree(dev, match);
+	} else {
+		new->num = 0;
+	}
+
+	new->alloc = num;
+
+	return new;
+}
+
+/*
+ * Add a component to be matched.
+ *
+ * The match array is first created or extended if necessary.
+ */
+void component_match_add(struct device *dev, struct component_match **matchptr,
+	int (*compare)(struct device *, void *), void *compare_data)
+{
+	struct component_match *match = *matchptr;
+
+	if (IS_ERR(match))
+		return;
+
+	if (!match || match->num == match->alloc) {
+		size_t new_size = match ? match->alloc + 16 : 15;
+
+		match = component_match_realloc(dev, match, new_size);
+
+		*matchptr = match;
+
+		if (IS_ERR(match))
+			return;
+	}
+
+	match->compare[match->num].fn = compare;
+	match->compare[match->num].data = compare_data;
+	match->num++;
+}
+EXPORT_SYMBOL(component_match_add);
+
+int component_master_add_with_match(struct device *dev,
+	const struct component_master_ops *ops,
+	struct component_match *match)
 {
 	struct master *master;
 	int ret;
 
+	if (ops->add_components && match)
+		return -EINVAL;
+
+	if (match) {
+		/* Reallocate the match array for its true size */
+		match = component_match_realloc(dev, match, match->num);
+		if (IS_ERR(match))
+			return PTR_ERR(match);
+	}
+
 	master = kzalloc(sizeof(*master), GFP_KERNEL);
 	if (!master)
 		return -ENOMEM;
 
 	master->dev = dev;
 	master->ops = ops;
+	master->match = match;
 	INIT_LIST_HEAD(&master->components);
 
 	/* Add to the list of available masters. */
@@ -209,6 +324,13 @@ int component_master_add(struct device *
 
 	return ret < 0 ? ret : 0;
 }
+EXPORT_SYMBOL_GPL(component_master_add_with_match);
+
+int component_master_add(struct device *dev,
+	const struct component_master_ops *ops)
+{
+	return component_master_add_with_match(dev, ops, NULL);
+}
 EXPORT_SYMBOL_GPL(component_master_add);
 
 void component_master_del(struct device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/devres.c linux-libre-3.17-rc7-gnu/drivers/base/devres.c
--- linux-libre-3.16-gnu/drivers/base/devres.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/devres.c	2014-09-28 17:29:07.000000000 -0400
@@ -817,6 +817,61 @@ char *devm_kstrdup(struct device *dev, c
 EXPORT_SYMBOL_GPL(devm_kstrdup);
 
 /**
+ * devm_kvasprintf - Allocate resource managed space
+ *			for the formatted string.
+ * @dev: Device to allocate memory for
+ * @gfp: the GFP mask used in the devm_kmalloc() call when
+ *       allocating memory
+ * @fmt: the formatted string to duplicate
+ * @ap: the list of tokens to be placed in the formatted string
+ * RETURNS:
+ * Pointer to allocated string on success, NULL on failure.
+ */
+char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
+		      va_list ap)
+{
+	unsigned int len;
+	char *p;
+	va_list aq;
+
+	va_copy(aq, ap);
+	len = vsnprintf(NULL, 0, fmt, aq);
+	va_end(aq);
+
+	p = devm_kmalloc(dev, len+1, gfp);
+	if (!p)
+		return NULL;
+
+	vsnprintf(p, len+1, fmt, ap);
+
+	return p;
+}
+EXPORT_SYMBOL(devm_kvasprintf);
+
+/**
+ * devm_kasprintf - Allocate resource managed space
+ *		and copy an existing formatted string into that
+ * @dev: Device to allocate memory for
+ * @gfp: the GFP mask used in the devm_kmalloc() call when
+ *       allocating memory
+ * @fmt: the string to duplicate
+ * RETURNS:
+ * Pointer to allocated string on success, NULL on failure.
+ */
+char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...)
+{
+	va_list ap;
+	char *p;
+
+	va_start(ap, fmt);
+	p = devm_kvasprintf(dev, gfp, fmt, ap);
+	va_end(ap);
+
+	return p;
+}
+EXPORT_SYMBOL_GPL(devm_kasprintf);
+
+/**
  * devm_kfree - Resource-managed kfree
  * @dev: Device this memory belongs to
  * @p: Memory to free
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/dma-buf.c linux-libre-3.17-rc7-gnu/drivers/base/dma-buf.c
--- linux-libre-3.16-gnu/drivers/base/dma-buf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/dma-buf.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,743 +0,0 @@
-/*
- * Framework for buffer objects that can be shared across devices/subsystems.
- *
- * Copyright(C) 2011 Linaro Limited. All rights reserved.
- * Author: Sumit Semwal <sumit.semwal@ti.com>
- *
- * Many thanks to linaro-mm-sig list, and specially
- * Arnd Bergmann <arnd@arndb.de>, Rob Clark <rob@ti.com> and
- * Daniel Vetter <daniel@ffwll.ch> for their support in creation and
- * refining of this idea.
- *
- * This program is free software; you can 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/fs.h>
-#include <linux/slab.h>
-#include <linux/dma-buf.h>
-#include <linux/anon_inodes.h>
-#include <linux/export.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static inline int is_dma_buf_file(struct file *);
-
-struct dma_buf_list {
-	struct list_head head;
-	struct mutex lock;
-};
-
-static struct dma_buf_list db_list;
-
-static int dma_buf_release(struct inode *inode, struct file *file)
-{
-	struct dma_buf *dmabuf;
-
-	if (!is_dma_buf_file(file))
-		return -EINVAL;
-
-	dmabuf = file->private_data;
-
-	BUG_ON(dmabuf->vmapping_counter);
-
-	dmabuf->ops->release(dmabuf);
-
-	mutex_lock(&db_list.lock);
-	list_del(&dmabuf->list_node);
-	mutex_unlock(&db_list.lock);
-
-	kfree(dmabuf);
-	return 0;
-}
-
-static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
-{
-	struct dma_buf *dmabuf;
-
-	if (!is_dma_buf_file(file))
-		return -EINVAL;
-
-	dmabuf = file->private_data;
-
-	/* check for overflowing the buffer's size */
-	if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
-	    dmabuf->size >> PAGE_SHIFT)
-		return -EINVAL;
-
-	return dmabuf->ops->mmap(dmabuf, vma);
-}
-
-static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
-{
-	struct dma_buf *dmabuf;
-	loff_t base;
-
-	if (!is_dma_buf_file(file))
-		return -EBADF;
-
-	dmabuf = file->private_data;
-
-	/* only support discovering the end of the buffer,
-	   but also allow SEEK_SET to maintain the idiomatic
-	   SEEK_END(0), SEEK_CUR(0) pattern */
-	if (whence == SEEK_END)
-		base = dmabuf->size;
-	else if (whence == SEEK_SET)
-		base = 0;
-	else
-		return -EINVAL;
-
-	if (offset != 0)
-		return -EINVAL;
-
-	return base + offset;
-}
-
-static const struct file_operations dma_buf_fops = {
-	.release	= dma_buf_release,
-	.mmap		= dma_buf_mmap_internal,
-	.llseek		= dma_buf_llseek,
-};
-
-/*
- * is_dma_buf_file - Check if struct file* is associated with dma_buf
- */
-static inline int is_dma_buf_file(struct file *file)
-{
-	return file->f_op == &dma_buf_fops;
-}
-
-/**
- * dma_buf_export_named - Creates a new dma_buf, and associates an anon file
- * with this buffer, so it can be exported.
- * Also connect the allocator specific data and ops to the buffer.
- * Additionally, provide a name string for exporter; useful in debugging.
- *
- * @priv:	[in]	Attach private data of allocator to this buffer
- * @ops:	[in]	Attach allocator-defined dma buf ops to the new buffer.
- * @size:	[in]	Size of the buffer
- * @flags:	[in]	mode flags for the file.
- * @exp_name:	[in]	name of the exporting module - useful for debugging.
- *
- * Returns, on success, a newly created dma_buf object, which wraps the
- * supplied private data and operations for dma_buf_ops. On either missing
- * ops, or error in allocating struct dma_buf, will return negative error.
- *
- */
-struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
-				size_t size, int flags, const char *exp_name)
-{
-	struct dma_buf *dmabuf;
-	struct file *file;
-
-	if (WARN_ON(!priv || !ops
-			  || !ops->map_dma_buf
-			  || !ops->unmap_dma_buf
-			  || !ops->release
-			  || !ops->kmap_atomic
-			  || !ops->kmap
-			  || !ops->mmap)) {
-		return ERR_PTR(-EINVAL);
-	}
-
-	dmabuf = kzalloc(sizeof(struct dma_buf), GFP_KERNEL);
-	if (dmabuf == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	dmabuf->priv = priv;
-	dmabuf->ops = ops;
-	dmabuf->size = size;
-	dmabuf->exp_name = exp_name;
-
-	file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
-	if (IS_ERR(file)) {
-		kfree(dmabuf);
-		return ERR_CAST(file);
-	}
-
-	file->f_mode |= FMODE_LSEEK;
-	dmabuf->file = file;
-
-	mutex_init(&dmabuf->lock);
-	INIT_LIST_HEAD(&dmabuf->attachments);
-
-	mutex_lock(&db_list.lock);
-	list_add(&dmabuf->list_node, &db_list.head);
-	mutex_unlock(&db_list.lock);
-
-	return dmabuf;
-}
-EXPORT_SYMBOL_GPL(dma_buf_export_named);
-
-
-/**
- * dma_buf_fd - returns a file descriptor for the given dma_buf
- * @dmabuf:	[in]	pointer to dma_buf for which fd is required.
- * @flags:      [in]    flags to give to fd
- *
- * On success, returns an associated 'fd'. Else, returns error.
- */
-int dma_buf_fd(struct dma_buf *dmabuf, int flags)
-{
-	int fd;
-
-	if (!dmabuf || !dmabuf->file)
-		return -EINVAL;
-
-	fd = get_unused_fd_flags(flags);
-	if (fd < 0)
-		return fd;
-
-	fd_install(fd, dmabuf->file);
-
-	return fd;
-}
-EXPORT_SYMBOL_GPL(dma_buf_fd);
-
-/**
- * dma_buf_get - returns the dma_buf structure related to an fd
- * @fd:	[in]	fd associated with the dma_buf to be returned
- *
- * On success, returns the dma_buf structure associated with an fd; uses
- * file's refcounting done by fget to increase refcount. returns ERR_PTR
- * otherwise.
- */
-struct dma_buf *dma_buf_get(int fd)
-{
-	struct file *file;
-
-	file = fget(fd);
-
-	if (!file)
-		return ERR_PTR(-EBADF);
-
-	if (!is_dma_buf_file(file)) {
-		fput(file);
-		return ERR_PTR(-EINVAL);
-	}
-
-	return file->private_data;
-}
-EXPORT_SYMBOL_GPL(dma_buf_get);
-
-/**
- * dma_buf_put - decreases refcount of the buffer
- * @dmabuf:	[in]	buffer to reduce refcount of
- *
- * Uses file's refcounting done implicitly by fput()
- */
-void dma_buf_put(struct dma_buf *dmabuf)
-{
-	if (WARN_ON(!dmabuf || !dmabuf->file))
-		return;
-
-	fput(dmabuf->file);
-}
-EXPORT_SYMBOL_GPL(dma_buf_put);
-
-/**
- * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
- * calls attach() of dma_buf_ops to allow device-specific attach functionality
- * @dmabuf:	[in]	buffer to attach device to.
- * @dev:	[in]	device to be attached.
- *
- * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
- * error.
- */
-struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
-					  struct device *dev)
-{
-	struct dma_buf_attachment *attach;
-	int ret;
-
-	if (WARN_ON(!dmabuf || !dev))
-		return ERR_PTR(-EINVAL);
-
-	attach = kzalloc(sizeof(struct dma_buf_attachment), GFP_KERNEL);
-	if (attach == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	attach->dev = dev;
-	attach->dmabuf = dmabuf;
-
-	mutex_lock(&dmabuf->lock);
-
-	if (dmabuf->ops->attach) {
-		ret = dmabuf->ops->attach(dmabuf, dev, attach);
-		if (ret)
-			goto err_attach;
-	}
-	list_add(&attach->node, &dmabuf->attachments);
-
-	mutex_unlock(&dmabuf->lock);
-	return attach;
-
-err_attach:
-	kfree(attach);
-	mutex_unlock(&dmabuf->lock);
-	return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(dma_buf_attach);
-
-/**
- * dma_buf_detach - Remove the given attachment from dmabuf's attachments list;
- * optionally calls detach() of dma_buf_ops for device-specific detach
- * @dmabuf:	[in]	buffer to detach from.
- * @attach:	[in]	attachment to be detached; is free'd after this call.
- *
- */
-void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
-{
-	if (WARN_ON(!dmabuf || !attach))
-		return;
-
-	mutex_lock(&dmabuf->lock);
-	list_del(&attach->node);
-	if (dmabuf->ops->detach)
-		dmabuf->ops->detach(dmabuf, attach);
-
-	mutex_unlock(&dmabuf->lock);
-	kfree(attach);
-}
-EXPORT_SYMBOL_GPL(dma_buf_detach);
-
-/**
- * dma_buf_map_attachment - Returns the scatterlist table of the attachment;
- * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
- * dma_buf_ops.
- * @attach:	[in]	attachment whose scatterlist is to be returned
- * @direction:	[in]	direction of DMA transfer
- *
- * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- * on error.
- */
-struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
-					enum dma_data_direction direction)
-{
-	struct sg_table *sg_table = ERR_PTR(-EINVAL);
-
-	might_sleep();
-
-	if (WARN_ON(!attach || !attach->dmabuf))
-		return ERR_PTR(-EINVAL);
-
-	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
-	if (!sg_table)
-		sg_table = ERR_PTR(-ENOMEM);
-
-	return sg_table;
-}
-EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
-
-/**
- * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
- * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
- * dma_buf_ops.
- * @attach:	[in]	attachment to unmap buffer from
- * @sg_table:	[in]	scatterlist info of the buffer to unmap
- * @direction:  [in]    direction of DMA transfer
- *
- */
-void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
-				struct sg_table *sg_table,
-				enum dma_data_direction direction)
-{
-	might_sleep();
-
-	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
-		return;
-
-	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,
-						direction);
-}
-EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
-
-
-/**
- * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the
- * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific
- * preparations. Coherency is only guaranteed in the specified range for the
- * specified access direction.
- * @dmabuf:	[in]	buffer to prepare cpu access for.
- * @start:	[in]	start of range for cpu access.
- * @len:	[in]	length of range for cpu access.
- * @direction:	[in]	length of range for cpu access.
- *
- * Can return negative error values, returns 0 on success.
- */
-int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
-			     enum dma_data_direction direction)
-{
-	int ret = 0;
-
-	if (WARN_ON(!dmabuf))
-		return -EINVAL;
-
-	if (dmabuf->ops->begin_cpu_access)
-		ret = dmabuf->ops->begin_cpu_access(dmabuf, start, len, direction);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
-
-/**
- * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the
- * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific
- * actions. Coherency is only guaranteed in the specified range for the
- * specified access direction.
- * @dmabuf:	[in]	buffer to complete cpu access for.
- * @start:	[in]	start of range for cpu access.
- * @len:	[in]	length of range for cpu access.
- * @direction:	[in]	length of range for cpu access.
- *
- * This call must always succeed.
- */
-void dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
-			    enum dma_data_direction direction)
-{
-	WARN_ON(!dmabuf);
-
-	if (dmabuf->ops->end_cpu_access)
-		dmabuf->ops->end_cpu_access(dmabuf, start, len, direction);
-}
-EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
-
-/**
- * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
- * space. The same restrictions as for kmap_atomic and friends apply.
- * @dmabuf:	[in]	buffer to map page from.
- * @page_num:	[in]	page in PAGE_SIZE units to map.
- *
- * This call must always succeed, any necessary preparations that might fail
- * need to be done in begin_cpu_access.
- */
-void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
-{
-	WARN_ON(!dmabuf);
-
-	return dmabuf->ops->kmap_atomic(dmabuf, page_num);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
-
-/**
- * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
- * @dmabuf:	[in]	buffer to unmap page from.
- * @page_num:	[in]	page in PAGE_SIZE units to unmap.
- * @vaddr:	[in]	kernel space pointer obtained from dma_buf_kmap_atomic.
- *
- * This call must always succeed.
- */
-void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
-			   void *vaddr)
-{
-	WARN_ON(!dmabuf);
-
-	if (dmabuf->ops->kunmap_atomic)
-		dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
-
-/**
- * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
- * same restrictions as for kmap and friends apply.
- * @dmabuf:	[in]	buffer to map page from.
- * @page_num:	[in]	page in PAGE_SIZE units to map.
- *
- * This call must always succeed, any necessary preparations that might fail
- * need to be done in begin_cpu_access.
- */
-void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
-{
-	WARN_ON(!dmabuf);
-
-	return dmabuf->ops->kmap(dmabuf, page_num);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kmap);
-
-/**
- * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
- * @dmabuf:	[in]	buffer to unmap page from.
- * @page_num:	[in]	page in PAGE_SIZE units to unmap.
- * @vaddr:	[in]	kernel space pointer obtained from dma_buf_kmap.
- *
- * This call must always succeed.
- */
-void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
-		    void *vaddr)
-{
-	WARN_ON(!dmabuf);
-
-	if (dmabuf->ops->kunmap)
-		dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kunmap);
-
-
-/**
- * dma_buf_mmap - Setup up a userspace mmap with the given vma
- * @dmabuf:	[in]	buffer that should back the vma
- * @vma:	[in]	vma for the mmap
- * @pgoff:	[in]	offset in pages where this mmap should start within the
- * 			dma-buf buffer.
- *
- * This function adjusts the passed in vma so that it points at the file of the
- * dma_buf operation. It also adjusts the starting pgoff and does bounds
- * checking on the size of the vma. Then it calls the exporters mmap function to
- * set up the mapping.
- *
- * Can return negative error values, returns 0 on success.
- */
-int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
-		 unsigned long pgoff)
-{
-	struct file *oldfile;
-	int ret;
-
-	if (WARN_ON(!dmabuf || !vma))
-		return -EINVAL;
-
-	/* check for offset overflow */
-	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)
-		return -EOVERFLOW;
-
-	/* check for overflowing the buffer's size */
-	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
-	    dmabuf->size >> PAGE_SHIFT)
-		return -EINVAL;
-
-	/* readjust the vma */
-	get_file(dmabuf->file);
-	oldfile = vma->vm_file;
-	vma->vm_file = dmabuf->file;
-	vma->vm_pgoff = pgoff;
-
-	ret = dmabuf->ops->mmap(dmabuf, vma);
-	if (ret) {
-		/* restore old parameters on failure */
-		vma->vm_file = oldfile;
-		fput(dmabuf->file);
-	} else {
-		if (oldfile)
-			fput(oldfile);
-	}
-	return ret;
-
-}
-EXPORT_SYMBOL_GPL(dma_buf_mmap);
-
-/**
- * dma_buf_vmap - Create virtual mapping for the buffer object into kernel
- * address space. Same restrictions as for vmap and friends apply.
- * @dmabuf:	[in]	buffer to vmap
- *
- * This call may fail due to lack of virtual mapping address space.
- * These calls are optional in drivers. The intended use for them
- * is for mapping objects linear in kernel space for high use objects.
- * Please attempt to use kmap/kunmap before thinking about these interfaces.
- *
- * Returns NULL on error.
- */
-void *dma_buf_vmap(struct dma_buf *dmabuf)
-{
-	void *ptr;
-
-	if (WARN_ON(!dmabuf))
-		return NULL;
-
-	if (!dmabuf->ops->vmap)
-		return NULL;
-
-	mutex_lock(&dmabuf->lock);
-	if (dmabuf->vmapping_counter) {
-		dmabuf->vmapping_counter++;
-		BUG_ON(!dmabuf->vmap_ptr);
-		ptr = dmabuf->vmap_ptr;
-		goto out_unlock;
-	}
-
-	BUG_ON(dmabuf->vmap_ptr);
-
-	ptr = dmabuf->ops->vmap(dmabuf);
-	if (WARN_ON_ONCE(IS_ERR(ptr)))
-		ptr = NULL;
-	if (!ptr)
-		goto out_unlock;
-
-	dmabuf->vmap_ptr = ptr;
-	dmabuf->vmapping_counter = 1;
-
-out_unlock:
-	mutex_unlock(&dmabuf->lock);
-	return ptr;
-}
-EXPORT_SYMBOL_GPL(dma_buf_vmap);
-
-/**
- * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
- * @dmabuf:	[in]	buffer to vunmap
- * @vaddr:	[in]	vmap to vunmap
- */
-void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
-{
-	if (WARN_ON(!dmabuf))
-		return;
-
-	BUG_ON(!dmabuf->vmap_ptr);
-	BUG_ON(dmabuf->vmapping_counter == 0);
-	BUG_ON(dmabuf->vmap_ptr != vaddr);
-
-	mutex_lock(&dmabuf->lock);
-	if (--dmabuf->vmapping_counter == 0) {
-		if (dmabuf->ops->vunmap)
-			dmabuf->ops->vunmap(dmabuf, vaddr);
-		dmabuf->vmap_ptr = NULL;
-	}
-	mutex_unlock(&dmabuf->lock);
-}
-EXPORT_SYMBOL_GPL(dma_buf_vunmap);
-
-#ifdef CONFIG_DEBUG_FS
-static int dma_buf_describe(struct seq_file *s)
-{
-	int ret;
-	struct dma_buf *buf_obj;
-	struct dma_buf_attachment *attach_obj;
-	int count = 0, attach_count;
-	size_t size = 0;
-
-	ret = mutex_lock_interruptible(&db_list.lock);
-
-	if (ret)
-		return ret;
-
-	seq_puts(s, "\nDma-buf Objects:\n");
-	seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
-
-	list_for_each_entry(buf_obj, &db_list.head, list_node) {
-		ret = mutex_lock_interruptible(&buf_obj->lock);
-
-		if (ret) {
-			seq_puts(s,
-				 "\tERROR locking buffer object: skipping\n");
-			continue;
-		}
-
-		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n",
-				buf_obj->size,
-				buf_obj->file->f_flags, buf_obj->file->f_mode,
-				(long)(buf_obj->file->f_count.counter),
-				buf_obj->exp_name);
-
-		seq_puts(s, "\tAttached Devices:\n");
-		attach_count = 0;
-
-		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
-			seq_puts(s, "\t");
-
-			seq_printf(s, "%s\n", dev_name(attach_obj->dev));
-			attach_count++;
-		}
-
-		seq_printf(s, "Total %d devices attached\n\n",
-				attach_count);
-
-		count++;
-		size += buf_obj->size;
-		mutex_unlock(&buf_obj->lock);
-	}
-
-	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
-
-	mutex_unlock(&db_list.lock);
-	return 0;
-}
-
-static int dma_buf_show(struct seq_file *s, void *unused)
-{
-	void (*func)(struct seq_file *) = s->private;
-	func(s);
-	return 0;
-}
-
-static int dma_buf_debug_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, dma_buf_show, inode->i_private);
-}
-
-static const struct file_operations dma_buf_debug_fops = {
-	.open           = dma_buf_debug_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-static struct dentry *dma_buf_debugfs_dir;
-
-static int dma_buf_init_debugfs(void)
-{
-	int err = 0;
-	dma_buf_debugfs_dir = debugfs_create_dir("dma_buf", NULL);
-	if (IS_ERR(dma_buf_debugfs_dir)) {
-		err = PTR_ERR(dma_buf_debugfs_dir);
-		dma_buf_debugfs_dir = NULL;
-		return err;
-	}
-
-	err = dma_buf_debugfs_create_file("bufinfo", dma_buf_describe);
-
-	if (err)
-		pr_debug("dma_buf: debugfs: failed to create node bufinfo\n");
-
-	return err;
-}
-
-static void dma_buf_uninit_debugfs(void)
-{
-	if (dma_buf_debugfs_dir)
-		debugfs_remove_recursive(dma_buf_debugfs_dir);
-}
-
-int dma_buf_debugfs_create_file(const char *name,
-				int (*write)(struct seq_file *))
-{
-	struct dentry *d;
-
-	d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir,
-			write, &dma_buf_debug_fops);
-
-	return PTR_ERR_OR_ZERO(d);
-}
-#else
-static inline int dma_buf_init_debugfs(void)
-{
-	return 0;
-}
-static inline void dma_buf_uninit_debugfs(void)
-{
-}
-#endif
-
-static int __init dma_buf_init(void)
-{
-	mutex_init(&db_list.lock);
-	INIT_LIST_HEAD(&db_list.head);
-	dma_buf_init_debugfs();
-	return 0;
-}
-subsys_initcall(dma_buf_init);
-
-static void __exit dma_buf_deinit(void)
-{
-	dma_buf_uninit_debugfs();
-}
-__exitcall(dma_buf_deinit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/dma-contiguous.c linux-libre-3.17-rc7-gnu/drivers/base/dma-contiguous.c
--- linux-libre-3.16-gnu/drivers/base/dma-contiguous.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/dma-contiguous.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,23 +24,9 @@
 
 #include <linux/memblock.h>
 #include <linux/err.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/page-isolation.h>
 #include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
-
-struct cma {
-	unsigned long	base_pfn;
-	unsigned long	count;
-	unsigned long	*bitmap;
-	struct mutex	lock;
-};
-
-struct cma *dma_contiguous_default_area;
+#include <linux/cma.h>
 
 #ifdef CONFIG_CMA_SIZE_MBYTES
 #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
@@ -48,6 +34,8 @@ struct cma *dma_contiguous_default_area;
 #define CMA_SIZE_MBYTES 0
 #endif
 
+struct cma *dma_contiguous_default_area;
+
 /*
  * Default global CMA area size can be defined in kernel's .config.
  * This is useful mainly for distro maintainers to create a kernel
@@ -154,65 +142,6 @@ void __init dma_contiguous_reserve(phys_
 	}
 }
 
-static DEFINE_MUTEX(cma_mutex);
-
-static int __init cma_activate_area(struct cma *cma)
-{
-	int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
-	unsigned long base_pfn = cma->base_pfn, pfn = base_pfn;
-	unsigned i = cma->count >> pageblock_order;
-	struct zone *zone;
-
-	cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-
-	if (!cma->bitmap)
-		return -ENOMEM;
-
-	WARN_ON_ONCE(!pfn_valid(pfn));
-	zone = page_zone(pfn_to_page(pfn));
-
-	do {
-		unsigned j;
-		base_pfn = pfn;
-		for (j = pageblock_nr_pages; j; --j, pfn++) {
-			WARN_ON_ONCE(!pfn_valid(pfn));
-			/*
-			 * alloc_contig_range requires the pfn range
-			 * specified to be in the same zone. Make this
-			 * simple by forcing the entire CMA resv range
-			 * to be in the same zone.
-			 */
-			if (page_zone(pfn_to_page(pfn)) != zone)
-				goto err;
-		}
-		init_cma_reserved_pageblock(pfn_to_page(base_pfn));
-	} while (--i);
-
-	mutex_init(&cma->lock);
-	return 0;
-
-err:
-	kfree(cma->bitmap);
-	return -EINVAL;
-}
-
-static struct cma cma_areas[MAX_CMA_AREAS];
-static unsigned cma_area_count;
-
-static int __init cma_init_reserved_areas(void)
-{
-	int i;
-
-	for (i = 0; i < cma_area_count; i++) {
-		int ret = cma_activate_area(&cma_areas[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-core_initcall(cma_init_reserved_areas);
-
 /**
  * dma_contiguous_reserve_area() - reserve custom contiguous area
  * @size: Size of the reserved area (in bytes),
@@ -234,72 +163,17 @@ int __init dma_contiguous_reserve_area(p
 				       phys_addr_t limit, struct cma **res_cma,
 				       bool fixed)
 {
-	struct cma *cma = &cma_areas[cma_area_count];
-	phys_addr_t alignment;
-	int ret = 0;
-
-	pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
-		 (unsigned long)size, (unsigned long)base,
-		 (unsigned long)limit);
-
-	/* Sanity checks */
-	if (cma_area_count == ARRAY_SIZE(cma_areas)) {
-		pr_err("Not enough slots for CMA reserved regions!\n");
-		return -ENOSPC;
-	}
-
-	if (!size)
-		return -EINVAL;
-
-	/* Sanitise input arguments */
-	alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
-	base = ALIGN(base, alignment);
-	size = ALIGN(size, alignment);
-	limit &= ~(alignment - 1);
-
-	/* Reserve memory */
-	if (base && fixed) {
-		if (memblock_is_region_reserved(base, size) ||
-		    memblock_reserve(base, size) < 0) {
-			ret = -EBUSY;
-			goto err;
-		}
-	} else {
-		phys_addr_t addr = memblock_alloc_range(size, alignment, base,
-							limit);
-		if (!addr) {
-			ret = -ENOMEM;
-			goto err;
-		} else {
-			base = addr;
-		}
-	}
-
-	/*
-	 * Each reserved area must be initialised later, when more kernel
-	 * subsystems (like slab allocator) are available.
-	 */
-	cma->base_pfn = PFN_DOWN(base);
-	cma->count = size >> PAGE_SHIFT;
-	*res_cma = cma;
-	cma_area_count++;
+	int ret;
 
-	pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
-		(unsigned long)base);
+	ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
+	if (ret)
+		return ret;
 
 	/* Architecture specific contiguous memory fixup. */
-	dma_contiguous_early_fixup(base, size);
-	return 0;
-err:
-	pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
-	return ret;
-}
+	dma_contiguous_early_fixup(cma_get_base(*res_cma),
+				cma_get_size(*res_cma));
 
-static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count)
-{
-	mutex_lock(&cma->lock);
-	bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count);
-	mutex_unlock(&cma->lock);
+	return 0;
 }
 
 /**
@@ -316,62 +190,10 @@ static void clear_cma_bitmap(struct cma
 struct page *dma_alloc_from_contiguous(struct device *dev, int count,
 				       unsigned int align)
 {
-	unsigned long mask, pfn, pageno, start = 0;
-	struct cma *cma = dev_get_cma_area(dev);
-	struct page *page = NULL;
-	int ret;
-
-	if (!cma || !cma->count)
-		return NULL;
-
 	if (align > CONFIG_CMA_ALIGNMENT)
 		align = CONFIG_CMA_ALIGNMENT;
 
-	pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
-		 count, align);
-
-	if (!count)
-		return NULL;
-
-	mask = (1 << align) - 1;
-
-
-	for (;;) {
-		mutex_lock(&cma->lock);
-		pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
-						    start, count, mask);
-		if (pageno >= cma->count) {
-			mutex_unlock(&cma->lock);
-			break;
-		}
-		bitmap_set(cma->bitmap, pageno, count);
-		/*
-		 * It's safe to drop the lock here. We've marked this region for
-		 * our exclusive use. If the migration fails we will take the
-		 * lock again and unmark it.
-		 */
-		mutex_unlock(&cma->lock);
-
-		pfn = cma->base_pfn + pageno;
-		mutex_lock(&cma_mutex);
-		ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
-		mutex_unlock(&cma_mutex);
-		if (ret == 0) {
-			page = pfn_to_page(pfn);
-			break;
-		} else if (ret != -EBUSY) {
-			clear_cma_bitmap(cma, pfn, count);
-			break;
-		}
-		clear_cma_bitmap(cma, pfn, count);
-		pr_debug("%s(): memory range at %p is busy, retrying\n",
-			 __func__, pfn_to_page(pfn));
-		/* try again with a bit different memory target */
-		start = pageno + mask + 1;
-	}
-
-	pr_debug("%s(): returned %p\n", __func__, page);
-	return page;
+	return cma_alloc(dev_get_cma_area(dev), count, align);
 }
 
 /**
@@ -387,23 +209,5 @@ struct page *dma_alloc_from_contiguous(s
 bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 				 int count)
 {
-	struct cma *cma = dev_get_cma_area(dev);
-	unsigned long pfn;
-
-	if (!cma || !pages)
-		return false;
-
-	pr_debug("%s(page %p)\n", __func__, (void *)pages);
-
-	pfn = page_to_pfn(pages);
-
-	if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
-		return false;
-
-	VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
-
-	free_contig_range(pfn, count);
-	clear_cma_bitmap(cma, pfn, count);
-
-	return true;
+	return cma_release(dev_get_cma_area(dev), pages, count);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/firmware_class.c linux-libre-3.17-rc7-gnu/drivers/base/firmware_class.c
--- linux-libre-3.16-gnu/drivers/base/firmware_class.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/firmware_class.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
+#include <linux/security.h>
 
 #include <generated/utsrelease.h>
 
@@ -100,10 +101,16 @@ static inline long firmware_loading_time
 #define FW_OPT_UEVENT	(1U << 0)
 #define FW_OPT_NOWAIT	(1U << 1)
 #ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_FALLBACK	(1U << 2)
+#define FW_OPT_USERHELPER	(1U << 2)
 #else
-#define FW_OPT_FALLBACK	0
+#define FW_OPT_USERHELPER	0
+#endif
+#ifdef CONFIG_FW_LOADER_USER_HELPER_FALLBACK
+#define FW_OPT_FALLBACK		FW_OPT_USERHELPER
+#else
+#define FW_OPT_FALLBACK		0
 #endif
+#define FW_OPT_NO_WARN	(1U << 3)
 
 struct firmware_cache {
 	/* firmware_buf instance will be added into the below list */
@@ -279,26 +286,15 @@ 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");
 
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline_for_stack int fw_file_size(struct file *file)
-{
-	struct kstat st;
-	if (vfs_getattr(&file->f_path, &st))
-		return -1;
-	if (!S_ISREG(st.mode))
-		return -1;
-	if (st.size != (int)st.size)
-		return -1;
-	return st.size;
-}
-
 static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
 {
 	int size;
 	char *buf;
 	int rc;
 
-	size = fw_file_size(file);
+	if (!S_ISREG(file_inode(file)->i_mode))
+		return -EINVAL;
+	size = i_size_read(file_inode(file));
 	if (size <= 0)
 		return -EINVAL;
 	buf = vmalloc(size);
@@ -308,12 +304,17 @@ static int fw_read_file_contents(struct
 	if (rc != size) {
 		if (rc > 0)
 			rc = -EIO;
-		vfree(buf);
-		return rc;
+		goto fail;
 	}
+	rc = security_kernel_fw_from_file(file, buf, size);
+	if (rc)
+		goto fail;
 	fw_buf->data = buf;
 	fw_buf->size = size;
 	return 0;
+fail:
+	vfree(buf);
+	return rc;
 }
 
 static int fw_get_filesystem_firmware(struct device *device,
@@ -617,6 +618,7 @@ static ssize_t firmware_loading_store(st
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
 	struct firmware_buf *fw_buf;
+	ssize_t written = count;
 	int loading = simple_strtol(buf, NULL, 10);
 	int i;
 
@@ -640,6 +642,8 @@ static ssize_t firmware_loading_store(st
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+			int rc;
+
 			set_bit(FW_STATUS_DONE, &fw_buf->status);
 			clear_bit(FW_STATUS_LOADING, &fw_buf->status);
 
@@ -649,10 +653,23 @@ static ssize_t firmware_loading_store(st
 			 * see the mapped 'buf->data' once the loading
 			 * is completed.
 			 * */
-			if (fw_map_pages_buf(fw_buf))
+			rc = fw_map_pages_buf(fw_buf);
+			if (rc)
 				dev_err(dev, "%s: map pages failed\n",
 					__func__);
+			else
+				rc = security_kernel_fw_from_file(NULL,
+						fw_buf->data, fw_buf->size);
+
+			/*
+			 * Same logic as fw_load_abort, only the DONE bit
+			 * is ignored and we set ABORT only on failure.
+			 */
 			list_del_init(&fw_buf->pending_list);
+			if (rc) {
+				set_bit(FW_STATUS_ABORT, &fw_buf->status);
+				written = rc;
+			}
 			complete_all(&fw_buf->completion);
 			break;
 		}
@@ -666,7 +683,7 @@ static ssize_t firmware_loading_store(st
 	}
 out:
 	mutex_unlock(&fw_lock);
-	return count;
+	return written;
 }
 
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
@@ -718,7 +735,7 @@ out:
 static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
 	struct firmware_buf *buf = fw_priv->buf;
-	int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
+	int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
 
 	/* If the array of pages is too small, grow it... */
 	if (buf->page_array_size < pages_needed) {
@@ -911,7 +928,9 @@ static int _request_firmware_load(struct
 	wait_for_completion(&buf->completion);
 
 	cancel_delayed_work_sync(&fw_priv->timeout_work);
-	if (!buf->data)
+	if (is_fw_load_aborted(buf))
+		retval = -EAGAIN;
+	else if (!buf->data)
 		retval = -ENOMEM;
 
 	device_remove_file(f_dev, &dev_attr_loading);
@@ -1111,10 +1130,11 @@ _request_firmware(const struct firmware
 
 	ret = fw_get_filesystem_firmware(device, fw->priv);
 	if (ret) {
-		if (opt_flags & FW_OPT_FALLBACK) {
+		if (!(opt_flags & FW_OPT_NO_WARN))
 			dev_warn(device,
-				 "Direct firmware load failed with error %d\n",
-				 ret);
+				 "Direct firmware load for %s failed with error %d\n",
+				 name, ret);
+		if (opt_flags & FW_OPT_USERHELPER) {
 			dev_warn(device, "Falling back to user helper\n");
 			ret = fw_load_from_user_helper(fw, name, device,
 						       opt_flags, timeout);
@@ -1171,7 +1191,6 @@ request_firmware(const struct firmware *
 }
 EXPORT_SYMBOL(request_firmware);
 
-#ifdef CONFIG_FW_LOADER_USER_HELPER
 /**
  * request_firmware: - load firmware directly without usermode helper
  * @firmware_p: pointer to firmware image
@@ -1188,12 +1207,12 @@ int request_firmware_direct(const struct
 {
 	int ret;
 	__module_get(THIS_MODULE);
-	ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT);
+	ret = _request_firmware(firmware_p, name, device,
+				FW_OPT_UEVENT | FW_OPT_NO_WARN);
 	module_put(THIS_MODULE);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(request_firmware_direct);
-#endif
 
 /**
  * release_firmware: - release the resource associated with a firmware image
@@ -1277,7 +1296,7 @@ request_firmware_nowait(
 	fw_work->context = context;
 	fw_work->cont = cont;
 	fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
-		(uevent ? FW_OPT_UEVENT : 0);
+		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
 
 	if (!try_module_get(module)) {
 		kfree(fw_work);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/Kconfig linux-libre-3.17-rc7-gnu/drivers/base/Kconfig
--- linux-libre-3.16-gnu/drivers/base/Kconfig	2014-08-07 05:03:09.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/Kconfig	2014-09-28 21:46:18.000000000 -0400
@@ -149,15 +149,21 @@ config EXTRA_FIRMWARE_DIR
 	  some other directory containing the firmware files.
 
 config FW_LOADER_USER_HELPER
+	bool
+
+config FW_LOADER_USER_HELPER_FALLBACK
 	bool "Fallback user-helper invocation for firmware loading"
 	depends on FW_LOADER
-	default y
+	select FW_LOADER_USER_HELPER
 	help
 	  This option enables / disables the invocation of user-helper
 	  (e.g. udev) for loading firmware files as a fallback after the
 	  direct file loading in kernel fails.  The user-mode helper is
 	  no longer required unless you have a special firmware file that
-	  resides in a non-standard path.
+	  resides in a non-standard path. Moreover, the udev support has
+	  been deprecated upstream.
+
+	  If you are unsure about this, say N here.
 
 config DEBUG_DRIVER
 	bool "Driver Core verbose debug messages"
@@ -208,6 +214,15 @@ 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"
+	depends on DMA_SHARED_BUFFER
+	help
+	  Enable the 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.
+
 config DMA_CMA
 	bool "DMA Contiguous Memory Allocator"
 	depends on HAVE_DMA_CONTIGUOUS && CMA
@@ -274,16 +289,6 @@ config CMA_ALIGNMENT
 
 	  If unsure, leave the default value "8".
 
-config CMA_AREAS
-	int "Maximum count of the CMA device-private areas"
-	default 7
-	help
-	  CMA allows to create CMA areas for particular devices. This parameter
-	  sets the maximum number of such device private CMA areas in the
-	  system.
-
-	  If unsure, leave the default value "7".
-
 endif
 
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/Makefile linux-libre-3.17-rc7-gnu/drivers/base/Makefile
--- linux-libre-3.16-gnu/drivers/base/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,6 @@ obj-$(CONFIG_DMA_CMA) += dma-contiguous.
 obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o reservation.o
 obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/memory.c linux-libre-3.17-rc7-gnu/drivers/base/memory.c
--- linux-libre-3.16-gnu/drivers/base/memory.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/memory.c	2014-09-28 17:29:07.000000000 -0400
@@ -284,7 +284,7 @@ static int memory_subsys_online(struct d
 	 * attribute and need to set the online_type.
 	 */
 	if (mem->online_type < 0)
-		mem->online_type = ONLINE_KEEP;
+		mem->online_type = MMOP_ONLINE_KEEP;
 
 	ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
 
@@ -315,23 +315,23 @@ store_mem_state(struct device *dev,
 	if (ret)
 		return ret;
 
-	if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
-		online_type = ONLINE_KERNEL;
-	else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
-		online_type = ONLINE_MOVABLE;
-	else if (!strncmp(buf, "online", min_t(int, count, 6)))
-		online_type = ONLINE_KEEP;
-	else if (!strncmp(buf, "offline", min_t(int, count, 7)))
-		online_type = -1;
+	if (sysfs_streq(buf, "online_kernel"))
+		online_type = MMOP_ONLINE_KERNEL;
+	else if (sysfs_streq(buf, "online_movable"))
+		online_type = MMOP_ONLINE_MOVABLE;
+	else if (sysfs_streq(buf, "online"))
+		online_type = MMOP_ONLINE_KEEP;
+	else if (sysfs_streq(buf, "offline"))
+		online_type = MMOP_OFFLINE;
 	else {
 		ret = -EINVAL;
 		goto err;
 	}
 
 	switch (online_type) {
-	case ONLINE_KERNEL:
-	case ONLINE_MOVABLE:
-	case ONLINE_KEEP:
+	case MMOP_ONLINE_KERNEL:
+	case MMOP_ONLINE_MOVABLE:
+	case MMOP_ONLINE_KEEP:
 		/*
 		 * mem->online_type is not protected so there can be a
 		 * race here.  However, when racing online, the first
@@ -342,7 +342,7 @@ store_mem_state(struct device *dev,
 		mem->online_type = online_type;
 		ret = device_online(&mem->dev);
 		break;
-	case -1:
+	case MMOP_OFFLINE:
 		ret = device_offline(&mem->dev);
 		break;
 	default:
@@ -406,7 +406,9 @@ memory_probe_store(struct device *dev, s
 	int i, ret;
 	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
 
-	phys_addr = simple_strtoull(buf, NULL, 0);
+	ret = kstrtoull(buf, 0, &phys_addr);
+	if (ret)
+		return ret;
 
 	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/node.c linux-libre-3.17-rc7-gnu/drivers/base/node.c
--- linux-libre-3.16-gnu/drivers/base/node.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/node.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,7 @@ static ssize_t node_read_meminfo(struct
 		       nid, K(node_page_state(nid, NR_FILE_PAGES)),
 		       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
 		       nid, K(node_page_state(nid, NR_ANON_PAGES)),
-		       nid, K(node_page_state(nid, NR_SHMEM)),
+		       nid, K(i.sharedram),
 		       nid, node_page_state(nid, NR_KERNEL_STACK) *
 				THREAD_SIZE / 1024,
 		       nid, K(node_page_state(nid, NR_PAGETABLE)),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/platform.c linux-libre-3.17-rc7-gnu/drivers/base/platform.c
--- linux-libre-3.16-gnu/drivers/base/platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/idr.h>
 #include <linux/acpi.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/limits.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -175,7 +177,7 @@ EXPORT_SYMBOL_GPL(platform_add_devices);
 
 struct platform_object {
 	struct platform_device pdev;
-	char name[1];
+	char name[];
 };
 
 /**
@@ -201,6 +203,7 @@ static void platform_device_release(stru
 	kfree(pa->pdev.dev.platform_data);
 	kfree(pa->pdev.mfd_cell);
 	kfree(pa->pdev.resource);
+	kfree(pa->pdev.driver_override);
 	kfree(pa);
 }
 
@@ -216,7 +219,7 @@ struct platform_device *platform_device_
 {
 	struct platform_object *pa;
 
-	pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
+	pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
 	if (pa) {
 		strcpy(pa->name, name);
 		pa->pdev.name = pa->name;
@@ -499,6 +502,10 @@ static int platform_drv_probe(struct dev
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
+	ret = of_clk_set_defaults(_dev->of_node, false);
+	if (ret < 0)
+		return ret;
+
 	acpi_dev_pm_attach(_dev, true);
 
 	ret = drv->probe(dev);
@@ -708,8 +715,49 @@ static ssize_t modalias_show(struct devi
 }
 static DEVICE_ATTR_RO(modalias);
 
+static ssize_t driver_override_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	char *driver_override, *old = pdev->driver_override, *cp;
+
+	if (count > PATH_MAX)
+		return -EINVAL;
+
+	driver_override = kstrndup(buf, count, GFP_KERNEL);
+	if (!driver_override)
+		return -ENOMEM;
+
+	cp = strchr(driver_override, '\n');
+	if (cp)
+		*cp = '\0';
+
+	if (strlen(driver_override)) {
+		pdev->driver_override = driver_override;
+	} else {
+		kfree(driver_override);
+		pdev->driver_override = NULL;
+	}
+
+	kfree(old);
+
+	return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	return sprintf(buf, "%s\n", pdev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
+
 static struct attribute *platform_dev_attrs[] = {
 	&dev_attr_modalias.attr,
+	&dev_attr_driver_override.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(platform_dev);
@@ -765,6 +813,10 @@ static int platform_match(struct device
 	struct platform_device *pdev = to_platform_device(dev);
 	struct platform_driver *pdrv = to_platform_driver(drv);
 
+	/* When driver_override is set, only bind to the matching driver */
+	if (pdev->driver_override)
+		return !strcmp(pdev->driver_override, drv->name);
+
 	/* Attempt an OF style match first */
 	if (of_driver_match_device(dev, drv))
 		return 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/power/main.c linux-libre-3.17-rc7-gnu/drivers/base/power/main.c
--- linux-libre-3.16-gnu/drivers/base/power/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/power/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -465,6 +465,7 @@ static void dpm_watchdog_clear(struct dp
  * device_resume_noirq - Execute an "early resume" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
+ * @async: If true, the device is being resumed asynchronously.
  *
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
@@ -594,6 +595,7 @@ static void dpm_resume_noirq(pm_message_
  * device_resume_early - Execute an "early resume" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
+ * @async: If true, the device is being resumed asynchronously.
  *
  * Runtime PM is disabled for @dev while this function is being executed.
  */
@@ -1004,6 +1006,7 @@ static pm_message_t resume_event(pm_mess
  * device_suspend_noirq - Execute a "late suspend" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
+ * @async: If true, the device is being suspended asynchronously.
  *
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
@@ -1144,6 +1147,7 @@ static int dpm_suspend_noirq(pm_message_
  * device_suspend_late - Execute a "late suspend" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
+ * @async: If true, the device is being suspended asynchronously.
  *
  * Runtime PM is disabled for @dev while this function is being executed.
  */
@@ -1298,6 +1302,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
  * @dev: Device to suspend.
  * @state: PM transition of the system being carried out.
  * @cb: Suspend callback to execute.
+ * @info: string description of caller.
  */
 static int legacy_suspend(struct device *dev, pm_message_t state,
 			  int (*cb)(struct device *dev, pm_message_t state),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/regmap/internal.h linux-libre-3.17-rc7-gnu/drivers/base/regmap/internal.h
--- linux-libre-3.16-gnu/drivers/base/regmap/internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/regmap/internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -146,6 +146,9 @@ struct regcache_ops {
 	enum regcache_type type;
 	int (*init)(struct regmap *map);
 	int (*exit)(struct regmap *map);
+#ifdef CONFIG_DEBUG_FS
+	void (*debugfs_init)(struct regmap *map);
+#endif
 	int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
 	int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
 	int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/regmap/regcache.c linux-libre-3.17-rc7-gnu/drivers/base/regmap/regcache.c
--- linux-libre-3.16-gnu/drivers/base/regmap/regcache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/regmap/regcache.c	2014-09-28 17:29:07.000000000 -0400
@@ -698,7 +698,7 @@ int regcache_sync_block(struct regmap *m
 			unsigned int block_base, unsigned int start,
 			unsigned int end)
 {
-	if (regmap_can_raw_write(map))
+	if (regmap_can_raw_write(map) && !map->use_single_rw)
 		return regcache_sync_block_raw(map, block, cache_present,
 					       block_base, start, end);
 	else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/regmap/regcache-rbtree.c linux-libre-3.17-rc7-gnu/drivers/base/regmap/regcache-rbtree.c
--- linux-libre-3.16-gnu/drivers/base/regmap/regcache-rbtree.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/regmap/regcache-rbtree.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,10 +194,6 @@ static void rbtree_debugfs_init(struct r
 {
 	debugfs_create_file("rbtree", 0400, map->debugfs, map, &rbtree_fops);
 }
-#else
-static void rbtree_debugfs_init(struct regmap *map)
-{
-}
 #endif
 
 static int regcache_rbtree_init(struct regmap *map)
@@ -222,8 +218,6 @@ static int regcache_rbtree_init(struct r
 			goto err;
 	}
 
-	rbtree_debugfs_init(map);
-
 	return 0;
 
 err:
@@ -532,6 +526,9 @@ struct regcache_ops regcache_rbtree_ops
 	.name = "rbtree",
 	.init = regcache_rbtree_init,
 	.exit = regcache_rbtree_exit,
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init = rbtree_debugfs_init,
+#endif
 	.read = regcache_rbtree_read,
 	.write = regcache_rbtree_write,
 	.sync = regcache_rbtree_sync,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/regmap/regmap.c linux-libre-3.17-rc7-gnu/drivers/base/regmap/regmap.c
--- linux-libre-3.16-gnu/drivers/base/regmap/regmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/regmap/regmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -109,7 +109,7 @@ bool regmap_readable(struct regmap *map,
 
 bool regmap_volatile(struct regmap *map, unsigned int reg)
 {
-	if (!regmap_readable(map, reg))
+	if (!map->format.format_write && !regmap_readable(map, reg))
 		return false;
 
 	if (map->volatile_reg)
@@ -1073,6 +1073,19 @@ struct regmap *dev_get_regmap(struct dev
 }
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
+/**
+ * regmap_get_device(): Obtain the device from a regmap
+ *
+ * @map: Register map to operate on.
+ *
+ * Returns the underlying device that the regmap has been created for.
+ */
+struct device *regmap_get_device(struct regmap *map)
+{
+	return map->dev;
+}
+EXPORT_SYMBOL_GPL(regmap_get_device);
+
 static int _regmap_select_page(struct regmap *map, unsigned int *reg,
 			       struct regmap_range_node *range,
 			       unsigned int val_num)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/regmap/regmap-debugfs.c linux-libre-3.17-rc7-gnu/drivers/base/regmap/regmap-debugfs.c
--- linux-libre-3.16-gnu/drivers/base/regmap/regmap-debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/regmap/regmap-debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -512,7 +512,14 @@ void regmap_debugfs_init(struct regmap *
 			    map, &regmap_reg_ranges_fops);
 
 	if (map->max_register || regmap_readable(map, 0)) {
-		debugfs_create_file("registers", 0400, map->debugfs,
+		umode_t registers_mode;
+
+		if (IS_ENABLED(REGMAP_ALLOW_WRITE_DEBUGFS))
+			registers_mode = 0600;
+		else
+			registers_mode = 0400;
+
+		debugfs_create_file("registers", registers_mode, map->debugfs,
 				    map, &regmap_map_fops);
 		debugfs_create_file("access", 0400, map->debugfs,
 				    map, &regmap_access_fops);
@@ -538,6 +545,9 @@ void regmap_debugfs_init(struct regmap *
 
 		next = rb_next(&range_node->node);
 	}
+
+	if (map->cache_ops && map->cache_ops->debugfs_init)
+		map->cache_ops->debugfs_init(map);
 }
 
 void regmap_debugfs_exit(struct regmap *map)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/base/reservation.c linux-libre-3.17-rc7-gnu/drivers/base/reservation.c
--- linux-libre-3.16-gnu/drivers/base/reservation.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/base/reservation.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Canonical Ltd
- *
- * Based on bo.c which bears the following copyright notice,
- * but is dual licensed:
- *
- * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
- */
-
-#include <linux/reservation.h>
-#include <linux/export.h>
-
-DEFINE_WW_CLASS(reservation_ww_class);
-EXPORT_SYMBOL(reservation_ww_class);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/driver_chipcommon_pmu.c linux-libre-3.17-rc7-gnu/drivers/bcma/driver_chipcommon_pmu.c
--- linux-libre-3.16-gnu/drivers/bcma/driver_chipcommon_pmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/driver_chipcommon_pmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -603,6 +603,8 @@ void bcma_pmu_spuravoid_pllupdate(struct
 		tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
 		break;
 
+	case BCMA_CHIP_ID_BCM43131:
+	case BCMA_CHIP_ID_BCM43217:
 	case BCMA_CHIP_ID_BCM43227:
 	case BCMA_CHIP_ID_BCM43228:
 	case BCMA_CHIP_ID_BCM43428:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/driver_gpio.c linux-libre-3.17-rc7-gnu/drivers/bcma/driver_gpio.c
--- linux-libre-3.16-gnu/drivers/bcma/driver_gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/driver_gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -220,6 +220,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c
 #endif
 	switch (cc->core->bus->chipinfo.id) {
 	case BCMA_CHIP_ID_BCM5357:
+	case BCMA_CHIP_ID_BCM53572:
 		chip->ngpio	= 32;
 		break;
 	default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/driver_pcie2.c linux-libre-3.17-rc7-gnu/drivers/bcma/driver_pcie2.c
--- linux-libre-3.16-gnu/drivers/bcma/driver_pcie2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/driver_pcie2.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ * Broadcom specific AMBA
+ * PCIe Gen 2 Core
+ *
+ * Copyright 2014, Broadcom Corporation
+ * Copyright 2014, RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+#if 0
+static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr)
+{
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
+	pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR);
+	return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
+}
+#endif
+
+static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr,
+				      u32 val)
+{
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val);
+}
+
+/**************************************************
+ * Init.
+ **************************************************/
+
+static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2,
+						bool enable)
+{
+	u32 val;
+
+	/* restore back to default */
+	val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
+	val |= PCIE2_CLKC_DLYPERST;
+	val &= ~PCIE2_CLKC_DISSPROMLD;
+	if (enable) {
+		val &= ~PCIE2_CLKC_DLYPERST;
+		val |= PCIE2_CLKC_DISSPROMLD;
+	}
+	pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val);
+	/* flush */
+	return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
+}
+
+static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2)
+{
+	/* LTR0 */
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844);
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c);
+	/* LTR1 */
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848);
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864);
+	/* LTR2 */
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C);
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003);
+}
+
+static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2)
+{
+	u8 core_rev = pcie2->core->id.rev;
+	u32 devstsctr2;
+
+	if (core_rev < 2 || core_rev == 10 || core_rev > 13)
+		return;
+
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+		      PCIE2_CAP_DEVSTSCTRL2_OFFSET);
+	devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
+	if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) {
+		/* force the right LTR values */
+		bcma_core_pcie2_set_ltr_vals(pcie2);
+
+		/* TODO:
+		si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */
+
+		/* enable the LTR */
+		devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB;
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+			      PCIE2_CAP_DEVSTSCTRL2_OFFSET);
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2);
+
+		/* set the LTR state to be active */
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
+			      PCIE2_LTR_ACTIVE);
+		usleep_range(1000, 2000);
+
+		/* set the LTR state to be sleep */
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
+			      PCIE2_LTR_SLEEP);
+		usleep_range(1000, 2000);
+	}
+}
+
+static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2)
+{
+	u8 core_rev = pcie2->core->id.rev;
+	bool pciewar160, pciewar162;
+
+	pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11;
+	pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 ||
+		     core_rev == 9 || core_rev == 11;
+
+	if (!pciewar160 && !pciewar162)
+		return;
+
+/* TODO */
+#if 0
+	pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL,
+		    PCIE_DISABLE_L1CLK_GATING);
+#if 0
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+		      PCIEGEN2_COE_PVT_TL_CTRL_0);
+	pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA,
+		     ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT));
+#endif
+#endif
+}
+
+static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2)
+{
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP);
+	pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f);
+}
+
+static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2)
+{
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX);
+	pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0);
+}
+
+static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2)
+{
+	struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc;
+	u8 core_rev = pcie2->core->id.rev;
+	u32 alp_khz, pm_value;
+
+	if (core_rev <= 13) {
+		alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000;
+		pm_value = (1000000 * 2) / alp_khz;
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+			      PCIE2_PVT_REG_PM_CLK_PERIOD);
+		pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value);
+	}
+}
+
+void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2)
+{
+	struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo;
+	u32 tmp;
+
+	tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54));
+	if ((tmp & 0xe) >> 1 == 2)
+		bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17);
+
+	/* TODO: Do we need pcie_reqsize? */
+
+	if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3)
+		bcma_core_pcie2_war_delay_perst_enab(pcie2, true);
+	bcma_core_pcie2_hw_ltr_war(pcie2);
+	pciedev_crwlpciegen2(pcie2);
+	pciedev_reg_pm_clk_period(pcie2);
+	pciedev_crwlpciegen2_180(pcie2);
+	pciedev_crwlpciegen2_182(pcie2);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/host_pci.c linux-libre-3.17-rc7-gnu/drivers/bcma/host_pci.c
--- linux-libre-3.16-gnu/drivers/bcma/host_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/host_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -279,7 +279,10 @@ static const struct pci_device_id bcma_p
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },	/* 0xA8DB */
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/main.c linux-libre-3.17-rc7-gnu/drivers/bcma/main.c
--- linux-libre-3.16-gnu/drivers/bcma/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bc
 		case BCMA_CORE_CHIPCOMMON:
 		case BCMA_CORE_PCI:
 		case BCMA_CORE_PCIE:
+		case BCMA_CORE_PCIE2:
 		case BCMA_CORE_MIPS_74K:
 		case BCMA_CORE_4706_MAC_GBIT_COMMON:
 			continue;
@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *b
 		bcma_core_pci_init(&bus->drv_pci[1]);
 	}
 
+	/* Init PCIe Gen 2 core */
+	core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0);
+	if (core) {
+		bus->drv_pcie2.core = core;
+		bcma_core_pcie2_init(&bus->drv_pcie2);
+	}
+
 	/* Init GBIT MAC COMMON core */
 	core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
 	if (core) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/Makefile linux-libre-3.17-rc7-gnu/drivers/bcma/Makefile
--- linux-libre-3.16-gnu/drivers/bcma/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@ bcma-y					+= driver_chipcommon.o driver
 bcma-$(CONFIG_BCMA_SFLASH)		+= driver_chipcommon_sflash.o
 bcma-$(CONFIG_BCMA_NFLASH)		+= driver_chipcommon_nflash.o
 bcma-y					+= driver_pci.o
+bcma-y					+= driver_pcie2.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
 bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
 bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN)	+= driver_gmac_cmn.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/scan.c linux-libre-3.17-rc7-gnu/drivers/bcma/scan.c
--- linux-libre-3.16-gnu/drivers/bcma/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,17 +32,17 @@ static const struct bcma_device_id_name
 	{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
 	{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
 	{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
-	{ BCMA_CORE_PCIEG2, "PCIe Gen 2" },
-	{ BCMA_CORE_DMA, "DMA" },
-	{ BCMA_CORE_SDIO3, "SDIO3" },
-	{ BCMA_CORE_USB20, "USB 2.0" },
-	{ BCMA_CORE_USB30, "USB 3.0" },
-	{ BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" },
-	{ BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" },
-	{ BCMA_CORE_ROM, "ROM" },
-	{ BCMA_CORE_NAND, "NAND flash controller" },
-	{ BCMA_CORE_QSPI, "SPI flash controller" },
-	{ BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" },
+	{ BCMA_CORE_NS_PCIEG2, "PCIe Gen 2" },
+	{ BCMA_CORE_NS_DMA, "DMA" },
+	{ BCMA_CORE_NS_SDIO3, "SDIO3" },
+	{ BCMA_CORE_NS_USB20, "USB 2.0" },
+	{ BCMA_CORE_NS_USB30, "USB 3.0" },
+	{ BCMA_CORE_NS_A9JTAG, "ARM Cortex A9 JTAG" },
+	{ BCMA_CORE_NS_DDR23, "Denali DDR2/DDR3 memory controller" },
+	{ BCMA_CORE_NS_ROM, "ROM" },
+	{ BCMA_CORE_NS_NAND, "NAND flash controller" },
+	{ BCMA_CORE_NS_QSPI, "SPI flash controller" },
+	{ BCMA_CORE_NS_CHIPCOMMON_B, "Chipcommon B" },
 	{ BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
 	{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
 	{ BCMA_CORE_ALTA, "ALTA (I2S)" },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bcma/sprom.c linux-libre-3.17-rc7-gnu/drivers/bcma/sprom.c
--- linux-libre-3.16-gnu/drivers/bcma/sprom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bcma/sprom.c	2014-09-28 17:29:07.000000000 -0400
@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_
 		SPEX(_field[7], _offset + 14, _mask, _shift);	\
 	} while (0)
 
+static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift)
+{
+	u16 v;
+	u8 gain;
+
+	v = in[SPOFF(offset)];
+	gain = (v & mask) >> shift;
+	if (gain == 0xFF) {
+		gain = 8; /* If unset use 2dBm */
+	} else {
+		/* Q5.2 Fractional part is stored in 0xC0 */
+		gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
+	}
+
+	return (s8)gain;
+}
+
 static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 {
 	u16 v, o;
@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct
 	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
-	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
-	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
-	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
-	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
-	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
-	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
-	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+	bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom,
+							   SSB_SPROM8_AGAIN01,
+							   SSB_SPROM8_AGAIN0,
+							   SSB_SPROM8_AGAIN0_SHIFT);
+	bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom,
+							   SSB_SPROM8_AGAIN01,
+							   SSB_SPROM8_AGAIN1,
+							   SSB_SPROM8_AGAIN1_SHIFT);
+	bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom,
+							   SSB_SPROM8_AGAIN23,
+							   SSB_SPROM8_AGAIN2,
+							   SSB_SPROM8_AGAIN2_SHIFT);
+	bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom,
+							   SSB_SPROM8_AGAIN23,
+							   SSB_SPROM8_AGAIN3,
+							   SSB_SPROM8_AGAIN3_SHIFT);
 
 	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
 	     SSB_SPROM8_LEDDC_ON_SHIFT);
@@ -509,6 +534,8 @@ static bool bcma_sprom_onchip_available(
 		/* for these chips OTP is always available */
 		present = true;
 		break;
+	case BCMA_CHIP_ID_BCM43131:
+	case BCMA_CHIP_ID_BCM43217:
 	case BCMA_CHIP_ID_BCM43227:
 	case BCMA_CHIP_ID_BCM43228:
 	case BCMA_CHIP_ID_BCM43428:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/brd.c linux-libre-3.17-rc7-gnu/drivers/block/brd.c
--- linux-libre-3.16-gnu/drivers/block/brd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/brd.c	2014-09-28 17:29:07.000000000 -0400
@@ -442,12 +442,15 @@ static int rd_nr;
 int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
 static int max_part;
 static int part_shift;
+static int part_show = 0;
 module_param(rd_nr, int, S_IRUGO);
 MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
 module_param(rd_size, int, S_IRUGO);
 MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
 module_param(max_part, int, S_IRUGO);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
+module_param(part_show, int, S_IRUGO);
+MODULE_PARM_DESC(part_show, "Control RAM disk visibility in /proc/partitions");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
 MODULE_ALIAS("rd");
@@ -501,7 +504,8 @@ static struct brd_device *brd_alloc(int
 	disk->fops		= &brd_fops;
 	disk->private_data	= brd;
 	disk->queue		= brd->brd_queue;
-	disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
+	if (!part_show)
+		disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
 	sprintf(disk->disk_name, "ram%d", i);
 	set_capacity(disk, rd_size * 2);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/cciss.c linux-libre-3.17-rc7-gnu/drivers/block/cciss.c
--- linux-libre-3.16-gnu/drivers/block/cciss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/cciss.c	2014-09-28 17:29:07.000000000 -0400
@@ -1014,24 +1014,21 @@ static CommandList_struct *cmd_special_a
 	u64bit temp64;
 	dma_addr_t cmd_dma_handle, err_dma_handle;
 
-	c = (CommandList_struct *) pci_alloc_consistent(h->pdev,
-		sizeof(CommandList_struct), &cmd_dma_handle);
+	c = pci_zalloc_consistent(h->pdev, sizeof(CommandList_struct),
+				  &cmd_dma_handle);
 	if (c == NULL)
 		return NULL;
-	memset(c, 0, sizeof(CommandList_struct));
 
 	c->cmdindex = -1;
 
-	c->err_info = (ErrorInfo_struct *)
-	    pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
-		    &err_dma_handle);
+	c->err_info = pci_zalloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
+					    &err_dma_handle);
 
 	if (c->err_info == NULL) {
 		pci_free_consistent(h->pdev,
 			sizeof(CommandList_struct), c, cmd_dma_handle);
 		return NULL;
 	}
-	memset(c->err_info, 0, sizeof(ErrorInfo_struct));
 
 	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (__u32) cmd_dma_handle;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/DAC960.c linux-libre-3.17-rc7-gnu/drivers/block/DAC960.c
--- linux-libre-3.16-gnu/drivers/block/DAC960.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/DAC960.c	2014-09-28 17:29:07.000000000 -0400
@@ -6741,11 +6741,11 @@ static long DAC960_gam_ioctl(struct file
 	ErrorCode = -ENOMEM;
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-				DataTransferLength, &DataTransferBufferDMA);
+	    DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+                                                       DataTransferLength,
+                                                       &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL)
 	    	break;
-	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
@@ -6877,11 +6877,11 @@ static long DAC960_gam_ioctl(struct file
     	ErrorCode = -ENOMEM;
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-				DataTransferLength, &DataTransferBufferDMA);
+	    DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+                                                       DataTransferLength,
+                                                       &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL)
 	    	break;
-	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
@@ -6899,14 +6899,14 @@ static long DAC960_gam_ioctl(struct file
 	RequestSenseLength = UserCommand.RequestSenseLength;
 	if (RequestSenseLength > 0)
 	  {
-	    RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
-			RequestSenseLength, &RequestSenseBufferDMA);
+	    RequestSenseBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+                                                       RequestSenseLength,
+                                                       &RequestSenseBufferDMA);
 	    if (RequestSenseBuffer == NULL)
 	      {
 		ErrorCode = -ENOMEM;
 		goto Failure2;
 	      }
-	    memset(RequestSenseBuffer, 0, RequestSenseLength);
 	  }
 	spin_lock_irqsave(&Controller->queue_lock, flags);
 	while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_actlog.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_actlog.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_actlog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_actlog.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,34 +92,26 @@ struct __packed al_transaction_on_disk {
 	__be32	context[AL_CONTEXT_PER_TRANSACTION];
 };
 
-struct update_odbm_work {
-	struct drbd_work w;
-	struct drbd_device *device;
-	unsigned int enr;
-};
-
-struct update_al_work {
-	struct drbd_work w;
-	struct drbd_device *device;
-	struct completion event;
-	int err;
-};
-
-
-void *drbd_md_get_buffer(struct drbd_device *device)
+void *drbd_md_get_buffer(struct drbd_device *device, const char *intent)
 {
 	int r;
 
 	wait_event(device->misc_wait,
-		   (r = atomic_cmpxchg(&device->md_io_in_use, 0, 1)) == 0 ||
+		   (r = atomic_cmpxchg(&device->md_io.in_use, 0, 1)) == 0 ||
 		   device->state.disk <= D_FAILED);
 
-	return r ? NULL : page_address(device->md_io_page);
+	if (r)
+		return NULL;
+
+	device->md_io.current_use = intent;
+	device->md_io.start_jif = jiffies;
+	device->md_io.submit_jif = device->md_io.start_jif - 1;
+	return page_address(device->md_io.page);
 }
 
 void drbd_md_put_buffer(struct drbd_device *device)
 {
-	if (atomic_dec_and_test(&device->md_io_in_use))
+	if (atomic_dec_and_test(&device->md_io.in_use))
 		wake_up(&device->misc_wait);
 }
 
@@ -145,10 +137,11 @@ void wait_until_done_or_force_detached(s
 
 static int _drbd_md_sync_page_io(struct drbd_device *device,
 				 struct drbd_backing_dev *bdev,
-				 struct page *page, sector_t sector,
-				 int rw, int size)
+				 sector_t sector, int rw)
 {
 	struct bio *bio;
+	/* we do all our meta data IO in aligned 4k blocks. */
+	const int size = 4096;
 	int err;
 
 	device->md_io.done = 0;
@@ -156,15 +149,15 @@ static int _drbd_md_sync_page_io(struct
 
 	if ((rw & WRITE) && !test_bit(MD_NO_FUA, &device->flags))
 		rw |= REQ_FUA | REQ_FLUSH;
-	rw |= REQ_SYNC;
+	rw |= REQ_SYNC | REQ_NOIDLE;
 
 	bio = bio_alloc_drbd(GFP_NOIO);
 	bio->bi_bdev = bdev->md_bdev;
 	bio->bi_iter.bi_sector = sector;
 	err = -EIO;
-	if (bio_add_page(bio, page, size, 0) != size)
+	if (bio_add_page(bio, device->md_io.page, size, 0) != size)
 		goto out;
-	bio->bi_private = &device->md_io;
+	bio->bi_private = device;
 	bio->bi_end_io = drbd_md_io_complete;
 	bio->bi_rw = rw;
 
@@ -179,7 +172,8 @@ static int _drbd_md_sync_page_io(struct
 	}
 
 	bio_get(bio); /* one bio_put() is in the completion handler */
-	atomic_inc(&device->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
+	atomic_inc(&device->md_io.in_use); /* drbd_md_put_buffer() is in the completion handler */
+	device->md_io.submit_jif = jiffies;
 	if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
 		bio_endio(bio, -EIO);
 	else
@@ -197,9 +191,7 @@ int drbd_md_sync_page_io(struct drbd_dev
 			 sector_t sector, int rw)
 {
 	int err;
-	struct page *iop = device->md_io_page;
-
-	D_ASSERT(device, atomic_read(&device->md_io_in_use) == 1);
+	D_ASSERT(device, atomic_read(&device->md_io.in_use) == 1);
 
 	BUG_ON(!bdev->md_bdev);
 
@@ -214,8 +206,7 @@ int drbd_md_sync_page_io(struct drbd_dev
 		     current->comm, current->pid, __func__,
 		     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
 
-	/* we do all our meta data IO in aligned 4k blocks. */
-	err = _drbd_md_sync_page_io(device, bdev, iop, sector, rw, 4096);
+	err = _drbd_md_sync_page_io(device, bdev, sector, rw);
 	if (err) {
 		drbd_err(device, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
 		    (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err);
@@ -297,26 +288,12 @@ bool drbd_al_begin_io_prepare(struct drb
 	return need_transaction;
 }
 
-static int al_write_transaction(struct drbd_device *device, bool delegate);
-
-/* When called through generic_make_request(), we must delegate
- * activity log I/O to the worker thread: a further request
- * submitted via generic_make_request() within the same task
- * would be queued on current->bio_list, and would only start
- * after this function returns (see generic_make_request()).
- *
- * However, if we *are* the worker, we must not delegate to ourselves.
- */
+static int al_write_transaction(struct drbd_device *device);
 
-/*
- * @delegate:   delegate activity log I/O to the worker thread
- */
-void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
+void drbd_al_begin_io_commit(struct drbd_device *device)
 {
 	bool locked = false;
 
-	BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
-
 	/* Serialize multiple transactions.
 	 * This uses test_and_set_bit, memory barrier is implicit.
 	 */
@@ -335,7 +312,7 @@ void drbd_al_begin_io_commit(struct drbd
 			rcu_read_unlock();
 
 			if (write_al_updates)
-				al_write_transaction(device, delegate);
+				al_write_transaction(device);
 			spin_lock_irq(&device->al_lock);
 			/* FIXME
 			if (err)
@@ -352,12 +329,10 @@ void drbd_al_begin_io_commit(struct drbd
 /*
  * @delegate:   delegate activity log I/O to the worker thread
  */
-void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate)
+void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i)
 {
-	BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
-
 	if (drbd_al_begin_io_prepare(device, i))
-		drbd_al_begin_io_commit(device, delegate);
+		drbd_al_begin_io_commit(device);
 }
 
 int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
@@ -380,8 +355,19 @@ int drbd_al_begin_io_nonblock(struct drb
 	/* We want all necessary updates for a given request within the same transaction
 	 * We could first check how many updates are *actually* needed,
 	 * and use that instead of the worst-case nr_al_extents */
-	if (available_update_slots < nr_al_extents)
-		return -EWOULDBLOCK;
+	if (available_update_slots < nr_al_extents) {
+		/* Too many activity log extents are currently "hot".
+		 *
+		 * If we have accumulated pending changes already,
+		 * we made progress.
+		 *
+		 * If we cannot get even a single pending change through,
+		 * stop the fast path until we made some progress,
+		 * or requests to "cold" extents could be starved. */
+		if (!al->pending_changes)
+			__set_bit(__LC_STARVING, &device->act_log->flags);
+		return -ENOBUFS;
+	}
 
 	/* Is resync active in this area? */
 	for (enr = first; enr <= last; enr++) {
@@ -452,15 +438,6 @@ static unsigned int al_extent_to_bm_page
 		 (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT));
 }
 
-static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
-{
-	return rs_enr >>
-		/* bit to page */
-		((PAGE_SHIFT + 3) -
-		/* resync extent number to bit */
-		 (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
-}
-
 static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device)
 {
 	const unsigned int stripes = device->ldev->md.al_stripes;
@@ -479,8 +456,7 @@ static sector_t al_tr_number_to_on_disk_
 	return device->ldev->md.md_offset + device->ldev->md.al_offset + t;
 }
 
-static int
-_al_write_transaction(struct drbd_device *device)
+int al_write_transaction(struct drbd_device *device)
 {
 	struct al_transaction_on_disk *buffer;
 	struct lc_element *e;
@@ -505,7 +481,8 @@ _al_write_transaction(struct drbd_device
 		return -EIO;
 	}
 
-	buffer = drbd_md_get_buffer(device); /* protects md_io_buffer, al_tr_cycle, ... */
+	/* protects md_io_buffer, al_tr_cycle, ... */
+	buffer = drbd_md_get_buffer(device, __func__);
 	if (!buffer) {
 		drbd_err(device, "disk failed while waiting for md_io buffer\n");
 		put_ldev(device);
@@ -590,38 +567,6 @@ _al_write_transaction(struct drbd_device
 	return err;
 }
 
-
-static int w_al_write_transaction(struct drbd_work *w, int unused)
-{
-	struct update_al_work *aw = container_of(w, struct update_al_work, w);
-	struct drbd_device *device = aw->device;
-	int err;
-
-	err = _al_write_transaction(device);
-	aw->err = err;
-	complete(&aw->event);
-
-	return err != -EIO ? err : 0;
-}
-
-/* Calls from worker context (see w_restart_disk_io()) need to write the
-   transaction directly. Others came through generic_make_request(),
-   those need to delegate it to the worker. */
-static int al_write_transaction(struct drbd_device *device, bool delegate)
-{
-	if (delegate) {
-		struct update_al_work al_work;
-		init_completion(&al_work.event);
-		al_work.w.cb = w_al_write_transaction;
-		al_work.device = device;
-		drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
-				      &al_work.w);
-		wait_for_completion(&al_work.event);
-		return al_work.err;
-	} else
-		return _al_write_transaction(device);
-}
-
 static int _try_lc_del(struct drbd_device *device, struct lc_element *al_ext)
 {
 	int rv;
@@ -682,72 +627,56 @@ int drbd_initialize_al(struct drbd_devic
 	return 0;
 }
 
-static int w_update_odbm(struct drbd_work *w, int unused)
-{
-	struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w);
-	struct drbd_device *device = udw->device;
-	struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
-
-	if (!get_ldev(device)) {
-		if (__ratelimit(&drbd_ratelimit_state))
-			drbd_warn(device, "Can not update on disk bitmap, local IO disabled.\n");
-		kfree(udw);
-		return 0;
-	}
-
-	drbd_bm_write_page(device, rs_extent_to_bm_page(udw->enr));
-	put_ldev(device);
-
-	kfree(udw);
-
-	if (drbd_bm_total_weight(device) <= device->rs_failed) {
-		switch (device->state.conn) {
-		case C_SYNC_SOURCE:  case C_SYNC_TARGET:
-		case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_T:
-			drbd_resync_finished(device);
-		default:
-			/* nothing to do */
-			break;
-		}
-	}
-	drbd_bcast_event(device, &sib);
-
-	return 0;
-}
-
+static const char *drbd_change_sync_fname[] = {
+	[RECORD_RS_FAILED] = "drbd_rs_failed_io",
+	[SET_IN_SYNC] = "drbd_set_in_sync",
+	[SET_OUT_OF_SYNC] = "drbd_set_out_of_sync"
+};
 
 /* ATTENTION. The AL's extents are 4MB each, while the extents in the
  * resync LRU-cache are 16MB each.
  * The caller of this function has to hold an get_ldev() reference.
  *
+ * Adjusts the caching members ->rs_left (success) or ->rs_failed (!success),
+ * potentially pulling in (and recounting the corresponding bits)
+ * this resync extent into the resync extent lru cache.
+ *
+ * Returns whether all bits have been cleared for this resync extent,
+ * precisely: (rs_left <= rs_failed)
+ *
  * TODO will be obsoleted once we have a caching lru of the on disk bitmap
  */
-static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t sector,
-				      int count, int success)
+static bool update_rs_extent(struct drbd_device *device,
+		unsigned int enr, int count,
+		enum update_sync_bits_mode mode)
 {
 	struct lc_element *e;
-	struct update_odbm_work *udw;
-
-	unsigned int enr;
 
 	D_ASSERT(device, atomic_read(&device->local_cnt));
 
-	/* I simply assume that a sector/size pair never crosses
-	 * a 16 MB extent border. (Currently this is true...) */
-	enr = BM_SECT_TO_EXT(sector);
-
-	e = lc_get(device->resync, enr);
+	/* When setting out-of-sync bits,
+	 * we don't need it cached (lc_find).
+	 * But if it is present in the cache,
+	 * we should update the cached bit count.
+	 * Otherwise, that extent should be in the resync extent lru cache
+	 * already -- or we want to pull it in if necessary -- (lc_get),
+	 * then update and check rs_left and rs_failed. */
+	if (mode == SET_OUT_OF_SYNC)
+		e = lc_find(device->resync, enr);
+	else
+		e = lc_get(device->resync, enr);
 	if (e) {
 		struct bm_extent *ext = lc_entry(e, struct bm_extent, lce);
 		if (ext->lce.lc_number == enr) {
-			if (success)
+			if (mode == SET_IN_SYNC)
 				ext->rs_left -= count;
+			else if (mode == SET_OUT_OF_SYNC)
+				ext->rs_left += count;
 			else
 				ext->rs_failed += count;
 			if (ext->rs_left < ext->rs_failed) {
-				drbd_warn(device, "BAD! sector=%llus enr=%u rs_left=%d "
+				drbd_warn(device, "BAD! enr=%u rs_left=%d "
 				    "rs_failed=%d count=%d cstate=%s\n",
-				     (unsigned long long)sector,
 				     ext->lce.lc_number, ext->rs_left,
 				     ext->rs_failed, count,
 				     drbd_conn_str(device->state.conn));
@@ -781,34 +710,27 @@ static void drbd_try_clear_on_disk_bm(st
 				     ext->lce.lc_number, ext->rs_failed);
 			}
 			ext->rs_left = rs_left;
-			ext->rs_failed = success ? 0 : count;
+			ext->rs_failed = (mode == RECORD_RS_FAILED) ? count : 0;
 			/* we don't keep a persistent log of the resync lru,
 			 * we can commit any change right away. */
 			lc_committed(device->resync);
 		}
-		lc_put(device->resync, &ext->lce);
+		if (mode != SET_OUT_OF_SYNC)
+			lc_put(device->resync, &ext->lce);
 		/* no race, we are within the al_lock! */
 
-		if (ext->rs_left == ext->rs_failed) {
+		if (ext->rs_left <= ext->rs_failed) {
 			ext->rs_failed = 0;
-
-			udw = kmalloc(sizeof(*udw), GFP_ATOMIC);
-			if (udw) {
-				udw->enr = ext->lce.lc_number;
-				udw->w.cb = w_update_odbm;
-				udw->device = device;
-				drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
-						      &udw->w);
-			} else {
-				drbd_warn(device, "Could not kmalloc an udw\n");
-			}
+			return true;
 		}
-	} else {
+	} else if (mode != SET_OUT_OF_SYNC) {
+		/* be quiet if lc_find() did not find it. */
 		drbd_err(device, "lc_get() failed! locked=%d/%d flags=%lu\n",
 		    device->resync_locked,
 		    device->resync->nr_elements,
 		    device->resync->flags);
 	}
+	return false;
 }
 
 void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go)
@@ -827,105 +749,105 @@ void drbd_advance_rs_marks(struct drbd_d
 	}
 }
 
-/* clear the bit corresponding to the piece of storage in question:
- * size byte of data starting from sector.  Only clear a bits of the affected
- * one ore more _aligned_ BM_BLOCK_SIZE blocks.
- *
- * called by worker on C_SYNC_TARGET and receiver on SyncSource.
- *
- */
-void __drbd_set_in_sync(struct drbd_device *device, sector_t sector, int size,
-		       const char *file, const unsigned int line)
+/* It is called lazy update, so don't do write-out too often. */
+static bool lazy_bitmap_update_due(struct drbd_device *device)
 {
-	/* Is called from worker and receiver context _only_ */
-	unsigned long sbnr, ebnr, lbnr;
-	unsigned long count = 0;
-	sector_t esector, nr_sectors;
-	int wake_up = 0;
-	unsigned long flags;
+	return time_after(jiffies, device->rs_last_bcast + 2*HZ);
+}
 
-	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
-		drbd_err(device, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
-				(unsigned long long)sector, size);
+static void maybe_schedule_on_disk_bitmap_update(struct drbd_device *device, bool rs_done)
+{
+	if (rs_done)
+		set_bit(RS_DONE, &device->flags);
+		/* and also set RS_PROGRESS below */
+	else if (!lazy_bitmap_update_due(device))
 		return;
-	}
 
-	if (!get_ldev(device))
-		return; /* no disk, no metadata, no bitmap to clear bits in */
-
-	nr_sectors = drbd_get_capacity(device->this_bdev);
-	esector = sector + (size >> 9) - 1;
-
-	if (!expect(sector < nr_sectors))
-		goto out;
-	if (!expect(esector < nr_sectors))
-		esector = nr_sectors - 1;
-
-	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
-
-	/* we clear it (in sync).
-	 * round up start sector, round down end sector.  we make sure we only
-	 * clear full, aligned, BM_BLOCK_SIZE (4K) blocks */
-	if (unlikely(esector < BM_SECT_PER_BIT-1))
-		goto out;
-	if (unlikely(esector == (nr_sectors-1)))
-		ebnr = lbnr;
-	else
-		ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
-	sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
-
-	if (sbnr > ebnr)
-		goto out;
+	drbd_device_post_work(device, RS_PROGRESS);
+}
 
+static int update_sync_bits(struct drbd_device *device,
+		unsigned long sbnr, unsigned long ebnr,
+		enum update_sync_bits_mode mode)
+{
 	/*
-	 * ok, (capacity & 7) != 0 sometimes, but who cares...
-	 * we count rs_{total,left} in bits, not sectors.
+	 * We keep a count of set bits per resync-extent in the ->rs_left
+	 * caching member, so we need to loop and work within the resync extent
+	 * alignment. Typically this loop will execute exactly once.
 	 */
-	count = drbd_bm_clear_bits(device, sbnr, ebnr);
-	if (count) {
-		drbd_advance_rs_marks(device, drbd_bm_total_weight(device));
-		spin_lock_irqsave(&device->al_lock, flags);
-		drbd_try_clear_on_disk_bm(device, sector, count, true);
-		spin_unlock_irqrestore(&device->al_lock, flags);
+	unsigned long flags;
+	unsigned long count = 0;
+	unsigned int cleared = 0;
+	while (sbnr <= ebnr) {
+		/* set temporary boundary bit number to last bit number within
+		 * the resync extent of the current start bit number,
+		 * but cap at provided end bit number */
+		unsigned long tbnr = min(ebnr, sbnr | BM_BLOCKS_PER_BM_EXT_MASK);
+		unsigned long c;
 
-		/* just wake_up unconditional now, various lc_chaged(),
-		 * lc_put() in drbd_try_clear_on_disk_bm(). */
-		wake_up = 1;
+		if (mode == RECORD_RS_FAILED)
+			/* Only called from drbd_rs_failed_io(), bits
+			 * supposedly still set.  Recount, maybe some
+			 * of the bits have been successfully cleared
+			 * by application IO meanwhile.
+			 */
+			c = drbd_bm_count_bits(device, sbnr, tbnr);
+		else if (mode == SET_IN_SYNC)
+			c = drbd_bm_clear_bits(device, sbnr, tbnr);
+		else /* if (mode == SET_OUT_OF_SYNC) */
+			c = drbd_bm_set_bits(device, sbnr, tbnr);
+
+		if (c) {
+			spin_lock_irqsave(&device->al_lock, flags);
+			cleared += update_rs_extent(device, BM_BIT_TO_EXT(sbnr), c, mode);
+			spin_unlock_irqrestore(&device->al_lock, flags);
+			count += c;
+		}
+		sbnr = tbnr + 1;
 	}
-out:
-	put_ldev(device);
-	if (wake_up)
+	if (count) {
+		if (mode == SET_IN_SYNC) {
+			unsigned long still_to_go = drbd_bm_total_weight(device);
+			bool rs_is_done = (still_to_go <= device->rs_failed);
+			drbd_advance_rs_marks(device, still_to_go);
+			if (cleared || rs_is_done)
+				maybe_schedule_on_disk_bitmap_update(device, rs_is_done);
+		} else if (mode == RECORD_RS_FAILED)
+			device->rs_failed += count;
 		wake_up(&device->al_wait);
+	}
+	return count;
 }
 
-/*
- * this is intended to set one request worth of data out of sync.
- * affects at least 1 bit,
- * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits.
+/* clear the bit corresponding to the piece of storage in question:
+ * size byte of data starting from sector.  Only clear a bits of the affected
+ * one ore more _aligned_ BM_BLOCK_SIZE blocks.
+ *
+ * called by worker on C_SYNC_TARGET and receiver on SyncSource.
  *
- * called by tl_clear and drbd_send_dblock (==drbd_make_request).
- * so this can be _any_ process.
  */
-int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector, int size,
-			    const char *file, const unsigned int line)
+int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
+		enum update_sync_bits_mode mode,
+		const char *file, const unsigned int line)
 {
-	unsigned long sbnr, ebnr, flags;
+	/* Is called from worker and receiver context _only_ */
+	unsigned long sbnr, ebnr, lbnr;
+	unsigned long count = 0;
 	sector_t esector, nr_sectors;
-	unsigned int enr, count = 0;
-	struct lc_element *e;
 
-	/* this should be an empty REQ_FLUSH */
-	if (size == 0)
+	/* This would be an empty REQ_FLUSH, be silent. */
+	if ((mode == SET_OUT_OF_SYNC) && size == 0)
 		return 0;
 
-	if (size < 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
-		drbd_err(device, "sector: %llus, size: %d\n",
-			(unsigned long long)sector, size);
+	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
+		drbd_err(device, "%s: sector=%llus size=%d nonsense!\n",
+				drbd_change_sync_fname[mode],
+				(unsigned long long)sector, size);
 		return 0;
 	}
 
 	if (!get_ldev(device))
-		return 0; /* no disk, no metadata, no bitmap to set bits in */
+		return 0; /* no disk, no metadata, no bitmap to manipulate bits in */
 
 	nr_sectors = drbd_get_capacity(device->this_bdev);
 	esector = sector + (size >> 9) - 1;
@@ -935,25 +857,28 @@ int __drbd_set_out_of_sync(struct drbd_d
 	if (!expect(esector < nr_sectors))
 		esector = nr_sectors - 1;
 
-	/* we set it out of sync,
-	 * we do not need to round anything here */
-	sbnr = BM_SECT_TO_BIT(sector);
-	ebnr = BM_SECT_TO_BIT(esector);
-
-	/* ok, (capacity & 7) != 0 sometimes, but who cares...
-	 * we count rs_{total,left} in bits, not sectors.  */
-	spin_lock_irqsave(&device->al_lock, flags);
-	count = drbd_bm_set_bits(device, sbnr, ebnr);
+	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
 
-	enr = BM_SECT_TO_EXT(sector);
-	e = lc_find(device->resync, enr);
-	if (e)
-		lc_entry(e, struct bm_extent, lce)->rs_left += count;
-	spin_unlock_irqrestore(&device->al_lock, flags);
+	if (mode == SET_IN_SYNC) {
+		/* Round up start sector, round down end sector.  We make sure
+		 * we only clear full, aligned, BM_BLOCK_SIZE blocks. */
+		if (unlikely(esector < BM_SECT_PER_BIT-1))
+			goto out;
+		if (unlikely(esector == (nr_sectors-1)))
+			ebnr = lbnr;
+		else
+			ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
+		sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
+	} else {
+		/* We set it out of sync, or record resync failure.
+		 * Should not round anything here. */
+		sbnr = BM_SECT_TO_BIT(sector);
+		ebnr = BM_SECT_TO_BIT(esector);
+	}
 
+	count = update_sync_bits(device, sbnr, ebnr, mode);
 out:
 	put_ldev(device);
-
 	return count;
 }
 
@@ -1075,6 +1000,15 @@ int drbd_try_rs_begin_io(struct drbd_dev
 	struct lc_element *e;
 	struct bm_extent *bm_ext;
 	int i;
+	bool throttle = drbd_rs_should_slow_down(device, sector, true);
+
+	/* If we need to throttle, a half-locked (only marked BME_NO_WRITES,
+	 * not yet BME_LOCKED) extent needs to be kicked out explicitly if we
+	 * need to throttle. There is at most one such half-locked extent,
+	 * which is remembered in resync_wenr. */
+
+	if (throttle && device->resync_wenr != enr)
+		return -EAGAIN;
 
 	spin_lock_irq(&device->al_lock);
 	if (device->resync_wenr != LC_FREE && device->resync_wenr != enr) {
@@ -1098,8 +1032,10 @@ int drbd_try_rs_begin_io(struct drbd_dev
 			D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
 			clear_bit(BME_NO_WRITES, &bm_ext->flags);
 			device->resync_wenr = LC_FREE;
-			if (lc_put(device->resync, &bm_ext->lce) == 0)
+			if (lc_put(device->resync, &bm_ext->lce) == 0) {
+				bm_ext->flags = 0;
 				device->resync_locked--;
+			}
 			wake_up(&device->al_wait);
 		} else {
 			drbd_alert(device, "LOGIC BUG\n");
@@ -1161,8 +1097,20 @@ proceed:
 	return 0;
 
 try_again:
-	if (bm_ext)
-		device->resync_wenr = enr;
+	if (bm_ext) {
+		if (throttle) {
+			D_ASSERT(device, !test_bit(BME_LOCKED, &bm_ext->flags));
+			D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
+			clear_bit(BME_NO_WRITES, &bm_ext->flags);
+			device->resync_wenr = LC_FREE;
+			if (lc_put(device->resync, &bm_ext->lce) == 0) {
+				bm_ext->flags = 0;
+				device->resync_locked--;
+			}
+			wake_up(&device->al_wait);
+		} else
+			device->resync_wenr = enr;
+	}
 	spin_unlock_irq(&device->al_lock);
 	return -EAGAIN;
 }
@@ -1270,69 +1218,3 @@ int drbd_rs_del_all(struct drbd_device *
 
 	return 0;
 }
-
-/**
- * drbd_rs_failed_io() - Record information on a failure to resync the specified blocks
- * @device:	DRBD device.
- * @sector:	The sector number.
- * @size:	Size of failed IO operation, in byte.
- */
-void drbd_rs_failed_io(struct drbd_device *device, sector_t sector, int size)
-{
-	/* Is called from worker and receiver context _only_ */
-	unsigned long sbnr, ebnr, lbnr;
-	unsigned long count;
-	sector_t esector, nr_sectors;
-	int wake_up = 0;
-
-	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
-		drbd_err(device, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
-				(unsigned long long)sector, size);
-		return;
-	}
-	nr_sectors = drbd_get_capacity(device->this_bdev);
-	esector = sector + (size >> 9) - 1;
-
-	if (!expect(sector < nr_sectors))
-		return;
-	if (!expect(esector < nr_sectors))
-		esector = nr_sectors - 1;
-
-	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
-
-	/*
-	 * round up start sector, round down end sector.  we make sure we only
-	 * handle full, aligned, BM_BLOCK_SIZE (4K) blocks */
-	if (unlikely(esector < BM_SECT_PER_BIT-1))
-		return;
-	if (unlikely(esector == (nr_sectors-1)))
-		ebnr = lbnr;
-	else
-		ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
-	sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
-
-	if (sbnr > ebnr)
-		return;
-
-	/*
-	 * ok, (capacity & 7) != 0 sometimes, but who cares...
-	 * we count rs_{total,left} in bits, not sectors.
-	 */
-	spin_lock_irq(&device->al_lock);
-	count = drbd_bm_count_bits(device, sbnr, ebnr);
-	if (count) {
-		device->rs_failed += count;
-
-		if (get_ldev(device)) {
-			drbd_try_clear_on_disk_bm(device, sector, count, false);
-			put_ldev(device);
-		}
-
-		/* just wake_up unconditional now, various lc_chaged(),
-		 * lc_put() in drbd_try_clear_on_disk_bm(). */
-		wake_up = 1;
-	}
-	spin_unlock_irq(&device->al_lock);
-	if (wake_up)
-		wake_up(&device->al_wait);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_bitmap.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_bitmap.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_bitmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_bitmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,8 @@
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
@@ -353,9 +355,8 @@ static void bm_free_pages(struct page **
 
 	for (i = 0; i < number; i++) {
 		if (!pages[i]) {
-			printk(KERN_ALERT "drbd: bm_free_pages tried to free "
-					  "a NULL pointer; i=%lu n=%lu\n",
-					  i, number);
+			pr_alert("bm_free_pages tried to free a NULL pointer; i=%lu n=%lu\n",
+				 i, number);
 			continue;
 		}
 		__free_page(pages[i]);
@@ -592,7 +593,7 @@ static void bm_memset(struct drbd_bitmap
 	end = offset + len;
 
 	if (end > b->bm_words) {
-		printk(KERN_ALERT "drbd: bm_memset end > bm_words\n");
+		pr_alert("bm_memset end > bm_words\n");
 		return;
 	}
 
@@ -602,7 +603,7 @@ static void bm_memset(struct drbd_bitmap
 		p_addr = bm_map_pidx(b, idx);
 		bm = p_addr + MLPP(offset);
 		if (bm+do_now > p_addr + LWPP) {
-			printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
+			pr_alert("BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
 			       p_addr, bm, (int)do_now);
 		} else
 			memset(bm, c, do_now * sizeof(long));
@@ -927,22 +928,14 @@ void drbd_bm_clear_all(struct drbd_devic
 	spin_unlock_irq(&b->bm_lock);
 }
 
-struct bm_aio_ctx {
-	struct drbd_device *device;
-	atomic_t in_flight;
-	unsigned int done;
-	unsigned flags;
-#define BM_AIO_COPY_PAGES	1
-#define BM_AIO_WRITE_HINTED	2
-#define BM_WRITE_ALL_PAGES	4
-	int error;
-	struct kref kref;
-};
-
-static void bm_aio_ctx_destroy(struct kref *kref)
+static void drbd_bm_aio_ctx_destroy(struct kref *kref)
 {
-	struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref);
+	struct drbd_bm_aio_ctx *ctx = container_of(kref, struct drbd_bm_aio_ctx, kref);
+	unsigned long flags;
 
+	spin_lock_irqsave(&ctx->device->resource->req_lock, flags);
+	list_del(&ctx->list);
+	spin_unlock_irqrestore(&ctx->device->resource->req_lock, flags);
 	put_ldev(ctx->device);
 	kfree(ctx);
 }
@@ -950,7 +943,7 @@ static void bm_aio_ctx_destroy(struct kr
 /* bv_page may be a copy, or may be the original */
 static void bm_async_io_complete(struct bio *bio, int error)
 {
-	struct bm_aio_ctx *ctx = bio->bi_private;
+	struct drbd_bm_aio_ctx *ctx = bio->bi_private;
 	struct drbd_device *device = ctx->device;
 	struct drbd_bitmap *b = device->bitmap;
 	unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page);
@@ -993,17 +986,18 @@ static void bm_async_io_complete(struct
 	if (atomic_dec_and_test(&ctx->in_flight)) {
 		ctx->done = 1;
 		wake_up(&device->misc_wait);
-		kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+		kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
 	}
 }
 
-static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local)
+static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_hold(local)
 {
 	struct bio *bio = bio_alloc_drbd(GFP_NOIO);
 	struct drbd_device *device = ctx->device;
 	struct drbd_bitmap *b = device->bitmap;
 	struct page *page;
 	unsigned int len;
+	unsigned int rw = (ctx->flags & BM_AIO_READ) ? READ : WRITE;
 
 	sector_t on_disk_sector =
 		device->ldev->md.md_offset + device->ldev->md.bm_offset;
@@ -1049,9 +1043,9 @@ static void bm_page_io_async(struct bm_a
 /*
  * bm_rw: read/write the whole bitmap from/to its on disk location.
  */
-static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
+static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
 {
-	struct bm_aio_ctx *ctx;
+	struct drbd_bm_aio_ctx *ctx;
 	struct drbd_bitmap *b = device->bitmap;
 	int num_pages, i, count = 0;
 	unsigned long now;
@@ -1067,12 +1061,13 @@ static int bm_rw(struct drbd_device *dev
 	 * as we submit copies of pages anyways.
 	 */
 
-	ctx = kmalloc(sizeof(struct bm_aio_ctx), GFP_NOIO);
+	ctx = kmalloc(sizeof(struct drbd_bm_aio_ctx), GFP_NOIO);
 	if (!ctx)
 		return -ENOMEM;
 
-	*ctx = (struct bm_aio_ctx) {
+	*ctx = (struct drbd_bm_aio_ctx) {
 		.device = device,
+		.start_jif = jiffies,
 		.in_flight = ATOMIC_INIT(1),
 		.done = 0,
 		.flags = flags,
@@ -1080,15 +1075,21 @@ static int bm_rw(struct drbd_device *dev
 		.kref = { ATOMIC_INIT(2) },
 	};
 
-	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
+	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in drbd_bm_aio_ctx_destroy() */
 		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n");
 		kfree(ctx);
 		return -ENODEV;
 	}
+	/* Here D_ATTACHING is sufficient since drbd_bm_read() is called only from
+	   drbd_adm_attach(), after device->ldev was assigned. */
 
-	if (!ctx->flags)
+	if (0 == (ctx->flags & ~BM_AIO_READ))
 		WARN_ON(!(BM_LOCKED_MASK & b->bm_flags));
 
+	spin_lock_irq(&device->resource->req_lock);
+	list_add_tail(&ctx->list, &device->pending_bitmap_io);
+	spin_unlock_irq(&device->resource->req_lock);
+
 	num_pages = b->bm_number_of_pages;
 
 	now = jiffies;
@@ -1098,13 +1099,13 @@ static int bm_rw(struct drbd_device *dev
 		/* ignore completely unchanged pages */
 		if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
 			break;
-		if (rw & WRITE) {
+		if (!(flags & BM_AIO_READ)) {
 			if ((flags & BM_AIO_WRITE_HINTED) &&
 			    !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT,
 				    &page_private(b->bm_pages[i])))
 				continue;
 
-			if (!(flags & BM_WRITE_ALL_PAGES) &&
+			if (!(flags & BM_AIO_WRITE_ALL_PAGES) &&
 			    bm_test_page_unchanged(b->bm_pages[i])) {
 				dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i);
 				continue;
@@ -1118,7 +1119,7 @@ static int bm_rw(struct drbd_device *dev
 			}
 		}
 		atomic_inc(&ctx->in_flight);
-		bm_page_io_async(ctx, i, rw);
+		bm_page_io_async(ctx, i);
 		++count;
 		cond_resched();
 	}
@@ -1134,12 +1135,12 @@ static int bm_rw(struct drbd_device *dev
 	if (!atomic_dec_and_test(&ctx->in_flight))
 		wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
 	else
-		kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+		kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
 
 	/* summary for global bitmap IO */
 	if (flags == 0)
 		drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n",
-			 rw == WRITE ? "WRITE" : "READ",
+			 (flags & BM_AIO_READ) ? "READ" : "WRITE",
 			 count, jiffies - now);
 
 	if (ctx->error) {
@@ -1152,20 +1153,18 @@ static int bm_rw(struct drbd_device *dev
 		err = -EIO; /* Disk timeout/force-detach during IO... */
 
 	now = jiffies;
-	if (rw == WRITE) {
-		drbd_md_flush(device);
-	} else /* rw == READ */ {
+	if (flags & BM_AIO_READ) {
 		b->bm_set = bm_count_bits(b);
 		drbd_info(device, "recounting of set bits took additional %lu jiffies\n",
 		     jiffies - now);
 	}
 	now = b->bm_set;
 
-	if (flags == 0)
+	if ((flags & ~BM_AIO_READ) == 0)
 		drbd_info(device, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
 		     ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
 
-	kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+	kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
 	return err;
 }
 
@@ -1175,7 +1174,7 @@ static int bm_rw(struct drbd_device *dev
  */
 int drbd_bm_read(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(device, READ, 0, 0);
+	return bm_rw(device, BM_AIO_READ, 0);
 }
 
 /**
@@ -1186,7 +1185,7 @@ int drbd_bm_read(struct drbd_device *dev
  */
 int drbd_bm_write(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(device, WRITE, 0, 0);
+	return bm_rw(device, 0, 0);
 }
 
 /**
@@ -1197,7 +1196,17 @@ int drbd_bm_write(struct drbd_device *de
  */
 int drbd_bm_write_all(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(device, WRITE, BM_WRITE_ALL_PAGES, 0);
+	return bm_rw(device, BM_AIO_WRITE_ALL_PAGES, 0);
+}
+
+/**
+ * drbd_bm_write_lazy() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
+ * @device:	DRBD device.
+ * @upper_idx:	0: write all changed pages; +ve: page index to stop scanning for changed pages
+ */
+int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local)
+{
+	return bm_rw(device, BM_AIO_COPY_PAGES, upper_idx);
 }
 
 /**
@@ -1213,7 +1222,7 @@ int drbd_bm_write_all(struct drbd_device
  */
 int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(device, WRITE, BM_AIO_COPY_PAGES, 0);
+	return bm_rw(device, BM_AIO_COPY_PAGES, 0);
 }
 
 /**
@@ -1222,62 +1231,7 @@ int drbd_bm_write_copy_pages(struct drbd
  */
 int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local)
 {
-	return bm_rw(device, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
-}
-
-/**
- * drbd_bm_write_page() - Writes a PAGE_SIZE aligned piece of bitmap
- * @device:	DRBD device.
- * @idx:	bitmap page index
- *
- * We don't want to special case on logical_block_size of the backend device,
- * so we submit PAGE_SIZE aligned pieces.
- * Note that on "most" systems, PAGE_SIZE is 4k.
- *
- * In case this becomes an issue on systems with larger PAGE_SIZE,
- * we may want to change this again to write 4k aligned 4k pieces.
- */
-int drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local)
-{
-	struct bm_aio_ctx *ctx;
-	int err;
-
-	if (bm_test_page_unchanged(device->bitmap->bm_pages[idx])) {
-		dynamic_drbd_dbg(device, "skipped bm page write for idx %u\n", idx);
-		return 0;
-	}
-
-	ctx = kmalloc(sizeof(struct bm_aio_ctx), GFP_NOIO);
-	if (!ctx)
-		return -ENOMEM;
-
-	*ctx = (struct bm_aio_ctx) {
-		.device = device,
-		.in_flight = ATOMIC_INIT(1),
-		.done = 0,
-		.flags = BM_AIO_COPY_PAGES,
-		.error = 0,
-		.kref = { ATOMIC_INIT(2) },
-	};
-
-	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in bm_aio_ctx_destroy() */
-		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in drbd_bm_write_page()\n");
-		kfree(ctx);
-		return -ENODEV;
-	}
-
-	bm_page_io_async(ctx, idx, WRITE_SYNC);
-	wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
-
-	if (ctx->error)
-		drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
-		/* that causes us to detach, so the in memory bitmap will be
-		 * gone in a moment as well. */
-
-	device->bm_writ_cnt++;
-	err = atomic_read(&ctx->in_flight) ? -EIO : ctx->error;
-	kref_put(&ctx->kref, &bm_aio_ctx_destroy);
-	return err;
+	return bm_rw(device, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
 }
 
 /* NOTE
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_debugfs.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_debugfs.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,958 @@
+#define pr_fmt(fmt) "drbd debugfs: " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/stat.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+
+#include "drbd_int.h"
+#include "drbd_req.h"
+#include "drbd_debugfs.h"
+
+
+/**********************************************************************
+ * Whenever you change the file format, remember to bump the version. *
+ **********************************************************************/
+
+static struct dentry *drbd_debugfs_root;
+static struct dentry *drbd_debugfs_version;
+static struct dentry *drbd_debugfs_resources;
+static struct dentry *drbd_debugfs_minors;
+
+static void seq_print_age_or_dash(struct seq_file *m, bool valid, unsigned long dt)
+{
+	if (valid)
+		seq_printf(m, "\t%d", jiffies_to_msecs(dt));
+	else
+		seq_printf(m, "\t-");
+}
+
+static void __seq_print_rq_state_bit(struct seq_file *m,
+	bool is_set, char *sep, const char *set_name, const char *unset_name)
+{
+	if (is_set && set_name) {
+		seq_putc(m, *sep);
+		seq_puts(m, set_name);
+		*sep = '|';
+	} else if (!is_set && unset_name) {
+		seq_putc(m, *sep);
+		seq_puts(m, unset_name);
+		*sep = '|';
+	}
+}
+
+static void seq_print_rq_state_bit(struct seq_file *m,
+	bool is_set, char *sep, const char *set_name)
+{
+	__seq_print_rq_state_bit(m, is_set, sep, set_name, NULL);
+}
+
+/* pretty print enum drbd_req_state_bits req->rq_state */
+static void seq_print_request_state(struct seq_file *m, struct drbd_request *req)
+{
+	unsigned int s = req->rq_state;
+	char sep = ' ';
+	seq_printf(m, "\t0x%08x", s);
+	seq_printf(m, "\tmaster: %s", req->master_bio ? "pending" : "completed");
+
+	/* RQ_WRITE ignored, already reported */
+	seq_puts(m, "\tlocal:");
+	seq_print_rq_state_bit(m, s & RQ_IN_ACT_LOG, &sep, "in-AL");
+	seq_print_rq_state_bit(m, s & RQ_POSTPONED, &sep, "postponed");
+	seq_print_rq_state_bit(m, s & RQ_COMPLETION_SUSP, &sep, "suspended");
+	sep = ' ';
+	seq_print_rq_state_bit(m, s & RQ_LOCAL_PENDING, &sep, "pending");
+	seq_print_rq_state_bit(m, s & RQ_LOCAL_COMPLETED, &sep, "completed");
+	seq_print_rq_state_bit(m, s & RQ_LOCAL_ABORTED, &sep, "aborted");
+	seq_print_rq_state_bit(m, s & RQ_LOCAL_OK, &sep, "ok");
+	if (sep == ' ')
+		seq_puts(m, " -");
+
+	/* for_each_connection ... */
+	seq_printf(m, "\tnet:");
+	sep = ' ';
+	seq_print_rq_state_bit(m, s & RQ_NET_PENDING, &sep, "pending");
+	seq_print_rq_state_bit(m, s & RQ_NET_QUEUED, &sep, "queued");
+	seq_print_rq_state_bit(m, s & RQ_NET_SENT, &sep, "sent");
+	seq_print_rq_state_bit(m, s & RQ_NET_DONE, &sep, "done");
+	seq_print_rq_state_bit(m, s & RQ_NET_SIS, &sep, "sis");
+	seq_print_rq_state_bit(m, s & RQ_NET_OK, &sep, "ok");
+	if (sep == ' ')
+		seq_puts(m, " -");
+
+	seq_printf(m, " :");
+	sep = ' ';
+	seq_print_rq_state_bit(m, s & RQ_EXP_RECEIVE_ACK, &sep, "B");
+	seq_print_rq_state_bit(m, s & RQ_EXP_WRITE_ACK, &sep, "C");
+	seq_print_rq_state_bit(m, s & RQ_EXP_BARR_ACK, &sep, "barr");
+	if (sep == ' ')
+		seq_puts(m, " -");
+	seq_printf(m, "\n");
+}
+
+static void seq_print_one_request(struct seq_file *m, struct drbd_request *req, unsigned long now)
+{
+	/* change anything here, fixup header below! */
+	unsigned int s = req->rq_state;
+
+#define RQ_HDR_1 "epoch\tsector\tsize\trw"
+	seq_printf(m, "0x%x\t%llu\t%u\t%s",
+		req->epoch,
+		(unsigned long long)req->i.sector, req->i.size >> 9,
+		(s & RQ_WRITE) ? "W" : "R");
+
+#define RQ_HDR_2 "\tstart\tin AL\tsubmit"
+	seq_printf(m, "\t%d", jiffies_to_msecs(now - req->start_jif));
+	seq_print_age_or_dash(m, s & RQ_IN_ACT_LOG, now - req->in_actlog_jif);
+	seq_print_age_or_dash(m, s & RQ_LOCAL_PENDING, now - req->pre_submit_jif);
+
+#define RQ_HDR_3 "\tsent\tacked\tdone"
+	seq_print_age_or_dash(m, s & RQ_NET_SENT, now - req->pre_send_jif);
+	seq_print_age_or_dash(m, (s & RQ_NET_SENT) && !(s & RQ_NET_PENDING), now - req->acked_jif);
+	seq_print_age_or_dash(m, s & RQ_NET_DONE, now - req->net_done_jif);
+
+#define RQ_HDR_4 "\tstate\n"
+	seq_print_request_state(m, req);
+}
+#define RQ_HDR RQ_HDR_1 RQ_HDR_2 RQ_HDR_3 RQ_HDR_4
+
+static void seq_print_minor_vnr_req(struct seq_file *m, struct drbd_request *req, unsigned long now)
+{
+	seq_printf(m, "%u\t%u\t", req->device->minor, req->device->vnr);
+	seq_print_one_request(m, req, now);
+}
+
+static void seq_print_resource_pending_meta_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+	struct drbd_device *device;
+	unsigned int i;
+
+	seq_puts(m, "minor\tvnr\tstart\tsubmit\tintent\n");
+	rcu_read_lock();
+	idr_for_each_entry(&resource->devices, device, i) {
+		struct drbd_md_io tmp;
+		/* In theory this is racy,
+		 * in the sense that there could have been a
+		 * drbd_md_put_buffer(); drbd_md_get_buffer();
+		 * between accessing these members here.  */
+		tmp = device->md_io;
+		if (atomic_read(&tmp.in_use)) {
+			seq_printf(m, "%u\t%u\t%d\t",
+				device->minor, device->vnr,
+				jiffies_to_msecs(now - tmp.start_jif));
+			if (time_before(tmp.submit_jif, tmp.start_jif))
+				seq_puts(m, "-\t");
+			else
+				seq_printf(m, "%d\t", jiffies_to_msecs(now - tmp.submit_jif));
+			seq_printf(m, "%s\n", tmp.current_use);
+		}
+	}
+	rcu_read_unlock();
+}
+
+static void seq_print_waiting_for_AL(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+	struct drbd_device *device;
+	unsigned int i;
+
+	seq_puts(m, "minor\tvnr\tage\t#waiting\n");
+	rcu_read_lock();
+	idr_for_each_entry(&resource->devices, device, i) {
+		unsigned long jif;
+		struct drbd_request *req;
+		int n = atomic_read(&device->ap_actlog_cnt);
+		if (n) {
+			spin_lock_irq(&device->resource->req_lock);
+			req = list_first_entry_or_null(&device->pending_master_completion[1],
+				struct drbd_request, req_pending_master_completion);
+			/* if the oldest request does not wait for the activity log
+			 * it is not interesting for us here */
+			if (req && !(req->rq_state & RQ_IN_ACT_LOG))
+				jif = req->start_jif;
+			else
+				req = NULL;
+			spin_unlock_irq(&device->resource->req_lock);
+		}
+		if (n) {
+			seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
+			if (req)
+				seq_printf(m, "%u\t", jiffies_to_msecs(now - jif));
+			else
+				seq_puts(m, "-\t");
+			seq_printf(m, "%u\n", n);
+		}
+	}
+	rcu_read_unlock();
+}
+
+static void seq_print_device_bitmap_io(struct seq_file *m, struct drbd_device *device, unsigned long now)
+{
+	struct drbd_bm_aio_ctx *ctx;
+	unsigned long start_jif;
+	unsigned int in_flight;
+	unsigned int flags;
+	spin_lock_irq(&device->resource->req_lock);
+	ctx = list_first_entry_or_null(&device->pending_bitmap_io, struct drbd_bm_aio_ctx, list);
+	if (ctx && ctx->done)
+		ctx = NULL;
+	if (ctx) {
+		start_jif = ctx->start_jif;
+		in_flight = atomic_read(&ctx->in_flight);
+		flags = ctx->flags;
+	}
+	spin_unlock_irq(&device->resource->req_lock);
+	if (ctx) {
+		seq_printf(m, "%u\t%u\t%c\t%u\t%u\n",
+			device->minor, device->vnr,
+			(flags & BM_AIO_READ) ? 'R' : 'W',
+			jiffies_to_msecs(now - start_jif),
+			in_flight);
+	}
+}
+
+static void seq_print_resource_pending_bitmap_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+	struct drbd_device *device;
+	unsigned int i;
+
+	seq_puts(m, "minor\tvnr\trw\tage\t#in-flight\n");
+	rcu_read_lock();
+	idr_for_each_entry(&resource->devices, device, i) {
+		seq_print_device_bitmap_io(m, device, now);
+	}
+	rcu_read_unlock();
+}
+
+/* pretty print enum peer_req->flags */
+static void seq_print_peer_request_flags(struct seq_file *m, struct drbd_peer_request *peer_req)
+{
+	unsigned long f = peer_req->flags;
+	char sep = ' ';
+
+	__seq_print_rq_state_bit(m, f & EE_SUBMITTED, &sep, "submitted", "preparing");
+	__seq_print_rq_state_bit(m, f & EE_APPLICATION, &sep, "application", "internal");
+	seq_print_rq_state_bit(m, f & EE_CALL_AL_COMPLETE_IO, &sep, "in-AL");
+	seq_print_rq_state_bit(m, f & EE_SEND_WRITE_ACK, &sep, "C");
+	seq_print_rq_state_bit(m, f & EE_MAY_SET_IN_SYNC, &sep, "set-in-sync");
+
+	if (f & EE_IS_TRIM) {
+		seq_putc(m, sep);
+		sep = '|';
+		if (f & EE_IS_TRIM_USE_ZEROOUT)
+			seq_puts(m, "zero-out");
+		else
+			seq_puts(m, "trim");
+	}
+	seq_putc(m, '\n');
+}
+
+static void seq_print_peer_request(struct seq_file *m,
+	struct drbd_device *device, struct list_head *lh,
+	unsigned long now)
+{
+	bool reported_preparing = false;
+	struct drbd_peer_request *peer_req;
+	list_for_each_entry(peer_req, lh, w.list) {
+		if (reported_preparing && !(peer_req->flags & EE_SUBMITTED))
+			continue;
+
+		if (device)
+			seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
+
+		seq_printf(m, "%llu\t%u\t%c\t%u\t",
+			(unsigned long long)peer_req->i.sector, peer_req->i.size >> 9,
+			(peer_req->flags & EE_WRITE) ? 'W' : 'R',
+			jiffies_to_msecs(now - peer_req->submit_jif));
+		seq_print_peer_request_flags(m, peer_req);
+		if (peer_req->flags & EE_SUBMITTED)
+			break;
+		else
+			reported_preparing = true;
+	}
+}
+
+static void seq_print_device_peer_requests(struct seq_file *m,
+	struct drbd_device *device, unsigned long now)
+{
+	seq_puts(m, "minor\tvnr\tsector\tsize\trw\tage\tflags\n");
+	spin_lock_irq(&device->resource->req_lock);
+	seq_print_peer_request(m, device, &device->active_ee, now);
+	seq_print_peer_request(m, device, &device->read_ee, now);
+	seq_print_peer_request(m, device, &device->sync_ee, now);
+	spin_unlock_irq(&device->resource->req_lock);
+	if (test_bit(FLUSH_PENDING, &device->flags)) {
+		seq_printf(m, "%u\t%u\t-\t-\tF\t%u\tflush\n",
+			device->minor, device->vnr,
+			jiffies_to_msecs(now - device->flush_jif));
+	}
+}
+
+static void seq_print_resource_pending_peer_requests(struct seq_file *m,
+	struct drbd_resource *resource, unsigned long now)
+{
+	struct drbd_device *device;
+	unsigned int i;
+
+	rcu_read_lock();
+	idr_for_each_entry(&resource->devices, device, i) {
+		seq_print_device_peer_requests(m, device, now);
+	}
+	rcu_read_unlock();
+}
+
+static void seq_print_resource_transfer_log_summary(struct seq_file *m,
+	struct drbd_resource *resource,
+	struct drbd_connection *connection,
+	unsigned long now)
+{
+	struct drbd_request *req;
+	unsigned int count = 0;
+	unsigned int show_state = 0;
+
+	seq_puts(m, "n\tdevice\tvnr\t" RQ_HDR);
+	spin_lock_irq(&resource->req_lock);
+	list_for_each_entry(req, &connection->transfer_log, tl_requests) {
+		unsigned int tmp = 0;
+		unsigned int s;
+		++count;
+
+		/* don't disable irq "forever" */
+		if (!(count & 0x1ff)) {
+			struct drbd_request *req_next;
+			kref_get(&req->kref);
+			spin_unlock_irq(&resource->req_lock);
+			cond_resched();
+			spin_lock_irq(&resource->req_lock);
+			req_next = list_next_entry(req, tl_requests);
+			if (kref_put(&req->kref, drbd_req_destroy))
+				req = req_next;
+			if (&req->tl_requests == &connection->transfer_log)
+				break;
+		}
+
+		s = req->rq_state;
+
+		/* This is meant to summarize timing issues, to be able to tell
+		 * local disk problems from network problems.
+		 * Skip requests, if we have shown an even older request with
+		 * similar aspects already.  */
+		if (req->master_bio == NULL)
+			tmp |= 1;
+		if ((s & RQ_LOCAL_MASK) && (s & RQ_LOCAL_PENDING))
+			tmp |= 2;
+		if (s & RQ_NET_MASK) {
+			if (!(s & RQ_NET_SENT))
+				tmp |= 4;
+			if (s & RQ_NET_PENDING)
+				tmp |= 8;
+			if (!(s & RQ_NET_DONE))
+				tmp |= 16;
+		}
+		if ((tmp & show_state) == tmp)
+			continue;
+		show_state |= tmp;
+		seq_printf(m, "%u\t", count);
+		seq_print_minor_vnr_req(m, req, now);
+		if (show_state == 0x1f)
+			break;
+	}
+	spin_unlock_irq(&resource->req_lock);
+}
+
+/* TODO: transfer_log and friends should be moved to resource */
+static int in_flight_summary_show(struct seq_file *m, void *pos)
+{
+	struct drbd_resource *resource = m->private;
+	struct drbd_connection *connection;
+	unsigned long jif = jiffies;
+
+	connection = first_connection(resource);
+	/* This does not happen, actually.
+	 * But be robust and prepare for future code changes. */
+	if (!connection || !kref_get_unless_zero(&connection->kref))
+		return -ESTALE;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	seq_puts(m, "oldest bitmap IO\n");
+	seq_print_resource_pending_bitmap_io(m, resource, jif);
+	seq_putc(m, '\n');
+
+	seq_puts(m, "meta data IO\n");
+	seq_print_resource_pending_meta_io(m, resource, jif);
+	seq_putc(m, '\n');
+
+	seq_puts(m, "socket buffer stats\n");
+	/* for each connection ... once we have more than one */
+	rcu_read_lock();
+	if (connection->data.socket) {
+		/* open coded SIOCINQ, the "relevant" part */
+		struct tcp_sock *tp = tcp_sk(connection->data.socket->sk);
+		int answ = tp->rcv_nxt - tp->copied_seq;
+		seq_printf(m, "unread receive buffer: %u Byte\n", answ);
+		/* open coded SIOCOUTQ, the "relevant" part */
+		answ = tp->write_seq - tp->snd_una;
+		seq_printf(m, "unacked send buffer: %u Byte\n", answ);
+	}
+	rcu_read_unlock();
+	seq_putc(m, '\n');
+
+	seq_puts(m, "oldest peer requests\n");
+	seq_print_resource_pending_peer_requests(m, resource, jif);
+	seq_putc(m, '\n');
+
+	seq_puts(m, "application requests waiting for activity log\n");
+	seq_print_waiting_for_AL(m, resource, jif);
+	seq_putc(m, '\n');
+
+	seq_puts(m, "oldest application requests\n");
+	seq_print_resource_transfer_log_summary(m, resource, connection, jif);
+	seq_putc(m, '\n');
+
+	jif = jiffies - jif;
+	if (jif)
+		seq_printf(m, "generated in %d ms\n", jiffies_to_msecs(jif));
+	kref_put(&connection->kref, drbd_destroy_connection);
+	return 0;
+}
+
+/* simple_positive(file->f_dentry) respectively debugfs_positive(),
+ * but neither is "reachable" from here.
+ * So we have our own inline version of it above.  :-( */
+static inline int debugfs_positive(struct dentry *dentry)
+{
+        return dentry->d_inode && !d_unhashed(dentry);
+}
+
+/* make sure at *open* time that the respective object won't go away. */
+static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, void *),
+		                void *data, struct kref *kref,
+				void (*release)(struct kref *))
+{
+	struct dentry *parent;
+	int ret = -ESTALE;
+
+	/* Are we still linked,
+	 * or has debugfs_remove() already been called? */
+	parent = file->f_dentry->d_parent;
+	/* not sure if this can happen: */
+	if (!parent || !parent->d_inode)
+		goto out;
+	/* serialize with d_delete() */
+	mutex_lock(&parent->d_inode->i_mutex);
+	/* Make sure the object is still alive */
+	if (debugfs_positive(file->f_dentry)
+	&& kref_get_unless_zero(kref))
+		ret = 0;
+	mutex_unlock(&parent->d_inode->i_mutex);
+	if (!ret) {
+		ret = single_open(file, show, data);
+		if (ret)
+			kref_put(kref, release);
+	}
+out:
+	return ret;
+}
+
+static int in_flight_summary_open(struct inode *inode, struct file *file)
+{
+	struct drbd_resource *resource = inode->i_private;
+	return drbd_single_open(file, in_flight_summary_show, resource,
+				&resource->kref, drbd_destroy_resource);
+}
+
+static int in_flight_summary_release(struct inode *inode, struct file *file)
+{
+	struct drbd_resource *resource = inode->i_private;
+	kref_put(&resource->kref, drbd_destroy_resource);
+	return single_release(inode, file);
+}
+
+static const struct file_operations in_flight_summary_fops = {
+	.owner		= THIS_MODULE,
+	.open		= in_flight_summary_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= in_flight_summary_release,
+};
+
+void drbd_debugfs_resource_add(struct drbd_resource *resource)
+{
+	struct dentry *dentry;
+	if (!drbd_debugfs_resources)
+		return;
+
+	dentry = debugfs_create_dir(resource->name, drbd_debugfs_resources);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	resource->debugfs_res = dentry;
+
+	dentry = debugfs_create_dir("volumes", resource->debugfs_res);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	resource->debugfs_res_volumes = dentry;
+
+	dentry = debugfs_create_dir("connections", resource->debugfs_res);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	resource->debugfs_res_connections = dentry;
+
+	dentry = debugfs_create_file("in_flight_summary", S_IRUSR|S_IRGRP,
+			resource->debugfs_res, resource,
+			&in_flight_summary_fops);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	resource->debugfs_res_in_flight_summary = dentry;
+	return;
+
+fail:
+	drbd_debugfs_resource_cleanup(resource);
+	drbd_err(resource, "failed to create debugfs dentry\n");
+}
+
+static void drbd_debugfs_remove(struct dentry **dp)
+{
+	debugfs_remove(*dp);
+	*dp = NULL;
+}
+
+void drbd_debugfs_resource_cleanup(struct drbd_resource *resource)
+{
+	/* it is ok to call debugfs_remove(NULL) */
+	drbd_debugfs_remove(&resource->debugfs_res_in_flight_summary);
+	drbd_debugfs_remove(&resource->debugfs_res_connections);
+	drbd_debugfs_remove(&resource->debugfs_res_volumes);
+	drbd_debugfs_remove(&resource->debugfs_res);
+}
+
+static void seq_print_one_timing_detail(struct seq_file *m,
+	const struct drbd_thread_timing_details *tdp,
+	unsigned long now)
+{
+	struct drbd_thread_timing_details td;
+	/* No locking...
+	 * use temporary assignment to get at consistent data. */
+	do {
+		td = *tdp;
+	} while (td.cb_nr != tdp->cb_nr);
+	if (!td.cb_addr)
+		return;
+	seq_printf(m, "%u\t%d\t%s:%u\t%ps\n",
+			td.cb_nr,
+			jiffies_to_msecs(now - td.start_jif),
+			td.caller_fn, td.line,
+			td.cb_addr);
+}
+
+static void seq_print_timing_details(struct seq_file *m,
+		const char *title,
+		unsigned int cb_nr, struct drbd_thread_timing_details *tdp, unsigned long now)
+{
+	unsigned int start_idx;
+	unsigned int i;
+
+	seq_printf(m, "%s\n", title);
+	/* If not much is going on, this will result in natural ordering.
+	 * If it is very busy, we will possibly skip events, or even see wrap
+	 * arounds, which could only be avoided with locking.
+	 */
+	start_idx = cb_nr % DRBD_THREAD_DETAILS_HIST;
+	for (i = start_idx; i < DRBD_THREAD_DETAILS_HIST; i++)
+		seq_print_one_timing_detail(m, tdp+i, now);
+	for (i = 0; i < start_idx; i++)
+		seq_print_one_timing_detail(m, tdp+i, now);
+}
+
+static int callback_history_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_connection *connection = m->private;
+	unsigned long jif = jiffies;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	seq_puts(m, "n\tage\tcallsite\tfn\n");
+	seq_print_timing_details(m, "worker", connection->w_cb_nr, connection->w_timing_details, jif);
+	seq_print_timing_details(m, "receiver", connection->r_cb_nr, connection->r_timing_details, jif);
+	return 0;
+}
+
+static int callback_history_open(struct inode *inode, struct file *file)
+{
+	struct drbd_connection *connection = inode->i_private;
+	return drbd_single_open(file, callback_history_show, connection,
+				&connection->kref, drbd_destroy_connection);
+}
+
+static int callback_history_release(struct inode *inode, struct file *file)
+{
+	struct drbd_connection *connection = inode->i_private;
+	kref_put(&connection->kref, drbd_destroy_connection);
+	return single_release(inode, file);
+}
+
+static const struct file_operations connection_callback_history_fops = {
+	.owner		= THIS_MODULE,
+	.open		= callback_history_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= callback_history_release,
+};
+
+static int connection_oldest_requests_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_connection *connection = m->private;
+	unsigned long now = jiffies;
+	struct drbd_request *r1, *r2;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	spin_lock_irq(&connection->resource->req_lock);
+	r1 = connection->req_next;
+	if (r1)
+		seq_print_minor_vnr_req(m, r1, now);
+	r2 = connection->req_ack_pending;
+	if (r2 && r2 != r1) {
+		r1 = r2;
+		seq_print_minor_vnr_req(m, r1, now);
+	}
+	r2 = connection->req_not_net_done;
+	if (r2 && r2 != r1)
+		seq_print_minor_vnr_req(m, r2, now);
+	spin_unlock_irq(&connection->resource->req_lock);
+	return 0;
+}
+
+static int connection_oldest_requests_open(struct inode *inode, struct file *file)
+{
+	struct drbd_connection *connection = inode->i_private;
+	return drbd_single_open(file, connection_oldest_requests_show, connection,
+				&connection->kref, drbd_destroy_connection);
+}
+
+static int connection_oldest_requests_release(struct inode *inode, struct file *file)
+{
+	struct drbd_connection *connection = inode->i_private;
+	kref_put(&connection->kref, drbd_destroy_connection);
+	return single_release(inode, file);
+}
+
+static const struct file_operations connection_oldest_requests_fops = {
+	.owner		= THIS_MODULE,
+	.open		= connection_oldest_requests_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= connection_oldest_requests_release,
+};
+
+void drbd_debugfs_connection_add(struct drbd_connection *connection)
+{
+	struct dentry *conns_dir = connection->resource->debugfs_res_connections;
+	struct dentry *dentry;
+	if (!conns_dir)
+		return;
+
+	/* Once we enable mutliple peers,
+	 * these connections will have descriptive names.
+	 * For now, it is just the one connection to the (only) "peer". */
+	dentry = debugfs_create_dir("peer", conns_dir);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	connection->debugfs_conn = dentry;
+
+	dentry = debugfs_create_file("callback_history", S_IRUSR|S_IRGRP,
+			connection->debugfs_conn, connection,
+			&connection_callback_history_fops);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	connection->debugfs_conn_callback_history = dentry;
+
+	dentry = debugfs_create_file("oldest_requests", S_IRUSR|S_IRGRP,
+			connection->debugfs_conn, connection,
+			&connection_oldest_requests_fops);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	connection->debugfs_conn_oldest_requests = dentry;
+	return;
+
+fail:
+	drbd_debugfs_connection_cleanup(connection);
+	drbd_err(connection, "failed to create debugfs dentry\n");
+}
+
+void drbd_debugfs_connection_cleanup(struct drbd_connection *connection)
+{
+	drbd_debugfs_remove(&connection->debugfs_conn_callback_history);
+	drbd_debugfs_remove(&connection->debugfs_conn_oldest_requests);
+	drbd_debugfs_remove(&connection->debugfs_conn);
+}
+
+static void resync_dump_detail(struct seq_file *m, struct lc_element *e)
+{
+       struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
+
+       seq_printf(m, "%5d %s %s %s\n", bme->rs_left,
+		  test_bit(BME_NO_WRITES, &bme->flags) ? "NO_WRITES" : "---------",
+		  test_bit(BME_LOCKED, &bme->flags) ? "LOCKED" : "------",
+		  test_bit(BME_PRIORITY, &bme->flags) ? "PRIORITY" : "--------"
+		  );
+}
+
+static int device_resync_extents_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_device *device = m->private;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	if (get_ldev_if_state(device, D_FAILED)) {
+		lc_seq_printf_stats(m, device->resync);
+		lc_seq_dump_details(m, device->resync, "rs_left flags", resync_dump_detail);
+		put_ldev(device);
+	}
+	return 0;
+}
+
+static int device_act_log_extents_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_device *device = m->private;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	if (get_ldev_if_state(device, D_FAILED)) {
+		lc_seq_printf_stats(m, device->act_log);
+		lc_seq_dump_details(m, device->act_log, "", NULL);
+		put_ldev(device);
+	}
+	return 0;
+}
+
+static int device_oldest_requests_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_device *device = m->private;
+	struct drbd_resource *resource = device->resource;
+	unsigned long now = jiffies;
+	struct drbd_request *r1, *r2;
+	int i;
+
+	/* BUMP me if you change the file format/content/presentation */
+	seq_printf(m, "v: %u\n\n", 0);
+
+	seq_puts(m, RQ_HDR);
+	spin_lock_irq(&resource->req_lock);
+	/* WRITE, then READ */
+	for (i = 1; i >= 0; --i) {
+		r1 = list_first_entry_or_null(&device->pending_master_completion[i],
+			struct drbd_request, req_pending_master_completion);
+		r2 = list_first_entry_or_null(&device->pending_completion[i],
+			struct drbd_request, req_pending_local);
+		if (r1)
+			seq_print_one_request(m, r1, now);
+		if (r2 && r2 != r1)
+			seq_print_one_request(m, r2, now);
+	}
+	spin_unlock_irq(&resource->req_lock);
+	return 0;
+}
+
+static int device_data_gen_id_show(struct seq_file *m, void *ignored)
+{
+	struct drbd_device *device = m->private;
+	struct drbd_md *md;
+	enum drbd_uuid_index idx;
+
+	if (!get_ldev_if_state(device, D_FAILED))
+		return -ENODEV;
+
+	md = &device->ldev->md;
+	spin_lock_irq(&md->uuid_lock);
+	for (idx = UI_CURRENT; idx <= UI_HISTORY_END; idx++) {
+		seq_printf(m, "0x%016llX\n", md->uuid[idx]);
+	}
+	spin_unlock_irq(&md->uuid_lock);
+	put_ldev(device);
+	return 0;
+}
+
+#define drbd_debugfs_device_attr(name)						\
+static int device_ ## name ## _open(struct inode *inode, struct file *file)	\
+{										\
+	struct drbd_device *device = inode->i_private;				\
+	return drbd_single_open(file, device_ ## name ## _show, device,		\
+				&device->kref, drbd_destroy_device);		\
+}										\
+static int device_ ## name ## _release(struct inode *inode, struct file *file)	\
+{										\
+	struct drbd_device *device = inode->i_private;				\
+	kref_put(&device->kref, drbd_destroy_device);				\
+	return single_release(inode, file);					\
+}										\
+static const struct file_operations device_ ## name ## _fops = {		\
+	.owner		= THIS_MODULE,						\
+	.open		= device_ ## name ## _open,				\
+	.read		= seq_read,						\
+	.llseek		= seq_lseek,						\
+	.release	= device_ ## name ## _release,				\
+};
+
+drbd_debugfs_device_attr(oldest_requests)
+drbd_debugfs_device_attr(act_log_extents)
+drbd_debugfs_device_attr(resync_extents)
+drbd_debugfs_device_attr(data_gen_id)
+
+void drbd_debugfs_device_add(struct drbd_device *device)
+{
+	struct dentry *vols_dir = device->resource->debugfs_res_volumes;
+	char minor_buf[8]; /* MINORMASK, MINORBITS == 20; */
+	char vnr_buf[8];   /* volume number vnr is even 16 bit only; */
+	char *slink_name = NULL;
+
+	struct dentry *dentry;
+	if (!vols_dir || !drbd_debugfs_minors)
+		return;
+
+	snprintf(vnr_buf, sizeof(vnr_buf), "%u", device->vnr);
+	dentry = debugfs_create_dir(vnr_buf, vols_dir);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	device->debugfs_vol = dentry;
+
+	snprintf(minor_buf, sizeof(minor_buf), "%u", device->minor);
+	slink_name = kasprintf(GFP_KERNEL, "../resources/%s/volumes/%u",
+			device->resource->name, device->vnr);
+	if (!slink_name)
+		goto fail;
+	dentry = debugfs_create_symlink(minor_buf, drbd_debugfs_minors, slink_name);
+	kfree(slink_name);
+	slink_name = NULL;
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	device->debugfs_minor = dentry;
+
+#define DCF(name)	do {					\
+	dentry = debugfs_create_file(#name, S_IRUSR|S_IRGRP,	\
+			device->debugfs_vol, device,		\
+			&device_ ## name ## _fops);		\
+	if (IS_ERR_OR_NULL(dentry))				\
+		goto fail;					\
+	device->debugfs_vol_ ## name = dentry;			\
+	} while (0)
+
+	DCF(oldest_requests);
+	DCF(act_log_extents);
+	DCF(resync_extents);
+	DCF(data_gen_id);
+#undef DCF
+	return;
+
+fail:
+	drbd_debugfs_device_cleanup(device);
+	drbd_err(device, "failed to create debugfs entries\n");
+}
+
+void drbd_debugfs_device_cleanup(struct drbd_device *device)
+{
+	drbd_debugfs_remove(&device->debugfs_minor);
+	drbd_debugfs_remove(&device->debugfs_vol_oldest_requests);
+	drbd_debugfs_remove(&device->debugfs_vol_act_log_extents);
+	drbd_debugfs_remove(&device->debugfs_vol_resync_extents);
+	drbd_debugfs_remove(&device->debugfs_vol_data_gen_id);
+	drbd_debugfs_remove(&device->debugfs_vol);
+}
+
+void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device)
+{
+	struct dentry *conn_dir = peer_device->connection->debugfs_conn;
+	struct dentry *dentry;
+	char vnr_buf[8];
+
+	if (!conn_dir)
+		return;
+
+	snprintf(vnr_buf, sizeof(vnr_buf), "%u", peer_device->device->vnr);
+	dentry = debugfs_create_dir(vnr_buf, conn_dir);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	peer_device->debugfs_peer_dev = dentry;
+	return;
+
+fail:
+	drbd_debugfs_peer_device_cleanup(peer_device);
+	drbd_err(peer_device, "failed to create debugfs entries\n");
+}
+
+void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device)
+{
+	drbd_debugfs_remove(&peer_device->debugfs_peer_dev);
+}
+
+static int drbd_version_show(struct seq_file *m, void *ignored)
+{
+	seq_printf(m, "# %s\n", drbd_buildtag());
+	seq_printf(m, "VERSION=%s\n", REL_VERSION);
+	seq_printf(m, "API_VERSION=%u\n", API_VERSION);
+	seq_printf(m, "PRO_VERSION_MIN=%u\n", PRO_VERSION_MIN);
+	seq_printf(m, "PRO_VERSION_MAX=%u\n", PRO_VERSION_MAX);
+	return 0;
+}
+
+static int drbd_version_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, drbd_version_show, NULL);
+}
+
+static struct file_operations drbd_version_fops = {
+	.owner = THIS_MODULE,
+	.open = drbd_version_open,
+	.llseek = seq_lseek,
+	.read = seq_read,
+	.release = single_release,
+};
+
+/* not __exit, may be indirectly called
+ * from the module-load-failure path as well. */
+void drbd_debugfs_cleanup(void)
+{
+	drbd_debugfs_remove(&drbd_debugfs_resources);
+	drbd_debugfs_remove(&drbd_debugfs_minors);
+	drbd_debugfs_remove(&drbd_debugfs_version);
+	drbd_debugfs_remove(&drbd_debugfs_root);
+}
+
+int __init drbd_debugfs_init(void)
+{
+	struct dentry *dentry;
+
+	dentry = debugfs_create_dir("drbd", NULL);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	drbd_debugfs_root = dentry;
+
+	dentry = debugfs_create_file("version", 0444, drbd_debugfs_root, NULL, &drbd_version_fops);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	drbd_debugfs_version = dentry;
+
+	dentry = debugfs_create_dir("resources", drbd_debugfs_root);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	drbd_debugfs_resources = dentry;
+
+	dentry = debugfs_create_dir("minors", drbd_debugfs_root);
+	if (IS_ERR_OR_NULL(dentry))
+		goto fail;
+	drbd_debugfs_minors = dentry;
+	return 0;
+
+fail:
+	drbd_debugfs_cleanup();
+	if (dentry)
+		return PTR_ERR(dentry);
+	else
+		return -EINVAL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_debugfs.h linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_debugfs.h
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_debugfs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_debugfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+
+#include "drbd_int.h"
+
+#ifdef CONFIG_DEBUG_FS
+int __init drbd_debugfs_init(void);
+void drbd_debugfs_cleanup(void);
+
+void drbd_debugfs_resource_add(struct drbd_resource *resource);
+void drbd_debugfs_resource_cleanup(struct drbd_resource *resource);
+
+void drbd_debugfs_connection_add(struct drbd_connection *connection);
+void drbd_debugfs_connection_cleanup(struct drbd_connection *connection);
+
+void drbd_debugfs_device_add(struct drbd_device *device);
+void drbd_debugfs_device_cleanup(struct drbd_device *device);
+
+void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device);
+void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device);
+#else
+
+static inline int __init drbd_debugfs_init(void) { return -ENODEV; }
+static inline void drbd_debugfs_cleanup(void) { }
+
+static inline void drbd_debugfs_resource_add(struct drbd_resource *resource) { }
+static inline void drbd_debugfs_resource_cleanup(struct drbd_resource *resource) { }
+
+static inline void drbd_debugfs_connection_add(struct drbd_connection *connection) { }
+static inline void drbd_debugfs_connection_cleanup(struct drbd_connection *connection) { }
+
+static inline void drbd_debugfs_device_add(struct drbd_device *device) { }
+static inline void drbd_debugfs_device_cleanup(struct drbd_device *device) { }
+
+static inline void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device) { }
+static inline void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device) { }
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_interval.h linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_interval.h
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_interval.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_interval.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,9 @@ struct drbd_interval {
 	unsigned int size;	/* size in bytes */
 	sector_t end;		/* highest interval end in subtree */
 	int local:1		/* local or remote request? */;
-	int waiting:1;
+	int waiting:1;		/* someone is waiting for this to complete */
+	int completed:1;	/* this has been completed already;
+				 * ignore for conflict detection */
 };
 
 static inline void drbd_clear_interval(struct drbd_interval *i)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_int.h linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_int.h
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_int.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_int.h	2014-09-28 17:29:07.000000000 -0400
@@ -317,7 +317,63 @@ struct drbd_request {
 
 	struct list_head tl_requests; /* ring list in the transfer log */
 	struct bio *master_bio;       /* master bio pointer */
-	unsigned long start_time;
+
+	/* see struct drbd_device */
+	struct list_head req_pending_master_completion;
+	struct list_head req_pending_local;
+
+	/* for generic IO accounting */
+	unsigned long start_jif;
+
+	/* for DRBD internal statistics */
+
+	/* Minimal set of time stamps to determine if we wait for activity log
+	 * transactions, local disk or peer.  32 bit "jiffies" are good enough,
+	 * we don't expect a DRBD request to be stalled for several month.
+	 */
+
+	/* before actual request processing */
+	unsigned long in_actlog_jif;
+
+	/* local disk */
+	unsigned long pre_submit_jif;
+
+	/* per connection */
+	unsigned long pre_send_jif;
+	unsigned long acked_jif;
+	unsigned long net_done_jif;
+
+	/* Possibly even more detail to track each phase:
+	 *  master_completion_jif
+	 *      how long did it take to complete the master bio
+	 *      (application visible latency)
+	 *  allocated_jif
+	 *      how long the master bio was blocked until we finally allocated
+	 *      a tracking struct
+	 *  in_actlog_jif
+	 *      how long did we wait for activity log transactions
+	 *
+	 *  net_queued_jif
+	 *      when did we finally queue it for sending
+	 *  pre_send_jif
+	 *      when did we start sending it
+	 *  post_send_jif
+	 *      how long did we block in the network stack trying to send it
+	 *  acked_jif
+	 *      when did we receive (or fake, in protocol A) a remote ACK
+	 *  net_done_jif
+	 *      when did we receive final acknowledgement (P_BARRIER_ACK),
+	 *      or decide, e.g. on connection loss, that we do no longer expect
+	 *      anything from this peer for this request.
+	 *
+	 *  pre_submit_jif
+	 *  post_sub_jif
+	 *      when did we start submiting to the lower level device,
+	 *      and how long did we block in that submit function
+	 *  local_completion_jif
+	 *      how long did it take the lower level device to complete this request
+	 */
+
 
 	/* once it hits 0, we may complete the master_bio */
 	atomic_t completion_ref;
@@ -366,6 +422,7 @@ struct drbd_peer_request {
 	struct drbd_interval i;
 	/* see comments on ee flag bits below */
 	unsigned long flags;
+	unsigned long submit_jif;
 	union {
 		u64 block_id;
 		struct digest_info *digest;
@@ -408,6 +465,17 @@ enum {
 
 	/* Is set when net_conf had two_primaries set while creating this peer_req */
 	__EE_IN_INTERVAL_TREE,
+
+	/* for debugfs: */
+	/* has this been submitted, or does it still wait for something else? */
+	__EE_SUBMITTED,
+
+	/* this is/was a write request */
+	__EE_WRITE,
+
+	/* this originates from application on peer
+	 * (not some resync or verify or other DRBD internal request) */
+	__EE_APPLICATION,
 };
 #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
 #define EE_MAY_SET_IN_SYNC     (1<<__EE_MAY_SET_IN_SYNC)
@@ -419,6 +487,9 @@ enum {
 #define EE_RESTART_REQUESTS	(1<<__EE_RESTART_REQUESTS)
 #define EE_SEND_WRITE_ACK	(1<<__EE_SEND_WRITE_ACK)
 #define EE_IN_INTERVAL_TREE	(1<<__EE_IN_INTERVAL_TREE)
+#define EE_SUBMITTED		(1<<__EE_SUBMITTED)
+#define EE_WRITE		(1<<__EE_WRITE)
+#define EE_APPLICATION		(1<<__EE_APPLICATION)
 
 /* flag bits per device */
 enum {
@@ -433,11 +504,11 @@ enum {
 	CONSIDER_RESYNC,
 
 	MD_NO_FUA,		/* Users wants us to not use FUA/FLUSH on meta data dev */
+
 	SUSPEND_IO,		/* suspend application io */
 	BITMAP_IO,		/* suspend application io;
 				   once no more io in flight, start bitmap io */
 	BITMAP_IO_QUEUED,       /* Started bitmap IO */
-	GO_DISKLESS,		/* Disk is being detached, on io-error or admin request. */
 	WAS_IO_ERROR,		/* Local disk failed, returned IO error */
 	WAS_READ_ERROR,		/* Local disk READ failed (set additionally to the above) */
 	FORCE_DETACH,		/* Force-detach from local disk, aborting any pending local IO */
@@ -450,6 +521,20 @@ enum {
 	B_RS_H_DONE,		/* Before resync handler done (already executed) */
 	DISCARD_MY_DATA,	/* discard_my_data flag per volume */
 	READ_BALANCE_RR,
+
+	FLUSH_PENDING,		/* if set, device->flush_jif is when we submitted that flush
+				 * from drbd_flush_after_epoch() */
+
+	/* cleared only after backing device related structures have been destroyed. */
+	GOING_DISKLESS,		/* Disk is being detached, because of io-error, or admin request. */
+
+	/* to be used in drbd_device_post_work() */
+	GO_DISKLESS,		/* tell worker to schedule cleanup before detach */
+	DESTROY_DISK,		/* tell worker to close backing devices and destroy related structures. */
+	MD_SYNC,		/* tell worker to call drbd_md_sync() */
+	RS_START,		/* tell worker to start resync/OV */
+	RS_PROGRESS,		/* tell worker that resync made significant progress */
+	RS_DONE,		/* tell worker that resync is done */
 };
 
 struct drbd_bitmap; /* opaque for drbd_device */
@@ -531,6 +616,11 @@ struct drbd_backing_dev {
 };
 
 struct drbd_md_io {
+	struct page *page;
+	unsigned long start_jif;	/* last call to drbd_md_get_buffer */
+	unsigned long submit_jif;	/* last _drbd_md_sync_page_io() submit */
+	const char *current_use;
+	atomic_t in_use;
 	unsigned int done;
 	int error;
 };
@@ -577,10 +667,18 @@ enum {
 				 * and potentially deadlock on, this drbd worker.
 				 */
 	DISCONNECT_SENT,
+
+	DEVICE_WORK_PENDING,	/* tell worker that some device has pending work */
 };
 
 struct drbd_resource {
 	char *name;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_res;
+	struct dentry *debugfs_res_volumes;
+	struct dentry *debugfs_res_connections;
+	struct dentry *debugfs_res_in_flight_summary;
+#endif
 	struct kref kref;
 	struct idr devices;		/* volume number to device mapping */
 	struct list_head connections;
@@ -594,12 +692,28 @@ struct drbd_resource {
 	unsigned susp_nod:1;		/* IO suspended because no data */
 	unsigned susp_fen:1;		/* IO suspended because fence peer handler runs */
 
+	enum write_ordering_e write_ordering;
+
 	cpumask_var_t cpu_mask;
 };
 
+struct drbd_thread_timing_details
+{
+	unsigned long start_jif;
+	void *cb_addr;
+	const char *caller_fn;
+	unsigned int line;
+	unsigned int cb_nr;
+};
+
 struct drbd_connection {
 	struct list_head connections;
 	struct drbd_resource *resource;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_conn;
+	struct dentry *debugfs_conn_callback_history;
+	struct dentry *debugfs_conn_oldest_requests;
+#endif
 	struct kref kref;
 	struct idr peer_devices;	/* volume number to peer device mapping */
 	enum drbd_conns cstate;		/* Only C_STANDALONE to C_WF_REPORT_PARAMS */
@@ -636,7 +750,6 @@ struct drbd_connection {
 	struct drbd_epoch *current_epoch;
 	spinlock_t epoch_lock;
 	unsigned int epochs;
-	enum write_ordering_e write_ordering;
 	atomic_t current_tle_nr;	/* transfer log epoch number */
 	unsigned current_tle_writes;	/* writes seen within this tl epoch */
 
@@ -645,9 +758,22 @@ struct drbd_connection {
 	struct drbd_thread worker;
 	struct drbd_thread asender;
 
+	/* cached pointers,
+	 * so we can look up the oldest pending requests more quickly.
+	 * protected by resource->req_lock */
+	struct drbd_request *req_next; /* DRBD 9: todo.req_next */
+	struct drbd_request *req_ack_pending;
+	struct drbd_request *req_not_net_done;
+
 	/* sender side */
 	struct drbd_work_queue sender_work;
 
+#define DRBD_THREAD_DETAILS_HIST	16
+	unsigned int w_cb_nr; /* keeps counting up */
+	unsigned int r_cb_nr; /* keeps counting up */
+	struct drbd_thread_timing_details w_timing_details[DRBD_THREAD_DETAILS_HIST];
+	struct drbd_thread_timing_details r_timing_details[DRBD_THREAD_DETAILS_HIST];
+
 	struct {
 		/* whether this sender thread
 		 * has processed a single write yet. */
@@ -663,11 +789,22 @@ struct drbd_connection {
 	} send;
 };
 
+void __update_timing_details(
+		struct drbd_thread_timing_details *tdp,
+		unsigned int *cb_nr,
+		void *cb,
+		const char *fn, const unsigned int line);
+
+#define update_worker_timing_details(c, cb) \
+	__update_timing_details(c->w_timing_details, &c->w_cb_nr, cb, __func__ , __LINE__ )
+#define update_receiver_timing_details(c, cb) \
+	__update_timing_details(c->r_timing_details, &c->r_cb_nr, cb, __func__ , __LINE__ )
+
 struct submit_worker {
 	struct workqueue_struct *wq;
 	struct work_struct worker;
 
-	spinlock_t lock;
+	/* protected by ..->resource->req_lock */
 	struct list_head writes;
 };
 
@@ -675,12 +812,29 @@ struct drbd_peer_device {
 	struct list_head peer_devices;
 	struct drbd_device *device;
 	struct drbd_connection *connection;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_peer_dev;
+#endif
 };
 
 struct drbd_device {
 	struct drbd_resource *resource;
 	struct list_head peer_devices;
-	int vnr;			/* volume number within the connection */
+	struct list_head pending_bitmap_io;
+
+	unsigned long flush_jif;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_minor;
+	struct dentry *debugfs_vol;
+	struct dentry *debugfs_vol_oldest_requests;
+	struct dentry *debugfs_vol_act_log_extents;
+	struct dentry *debugfs_vol_resync_extents;
+	struct dentry *debugfs_vol_data_gen_id;
+#endif
+
+	unsigned int vnr;	/* volume number within the connection */
+	unsigned int minor;	/* device minor number */
+
 	struct kref kref;
 
 	/* things that are stored as / read from meta data on disk */
@@ -697,19 +851,10 @@ struct drbd_device {
 	unsigned long last_reattach_jif;
 	struct drbd_work resync_work;
 	struct drbd_work unplug_work;
-	struct drbd_work go_diskless;
-	struct drbd_work md_sync_work;
-	struct drbd_work start_resync_work;
 	struct timer_list resync_timer;
 	struct timer_list md_sync_timer;
 	struct timer_list start_resync_timer;
 	struct timer_list request_timer;
-#ifdef DRBD_DEBUG_MD_SYNC
-	struct {
-		unsigned int line;
-		const char* func;
-	} last_md_mark_dirty;
-#endif
 
 	/* Used after attach while negotiating new disk state. */
 	union drbd_state new_state_tmp;
@@ -724,6 +869,7 @@ struct drbd_device {
 	unsigned int al_writ_cnt;
 	unsigned int bm_writ_cnt;
 	atomic_t ap_bio_cnt;	 /* Requests we need to complete */
+	atomic_t ap_actlog_cnt;  /* Requests waiting for activity log */
 	atomic_t ap_pending_cnt; /* AP data packets on the wire, ack expected */
 	atomic_t rs_pending_cnt; /* RS request/data packets on the wire */
 	atomic_t unacked_cnt;	 /* Need to send replies for */
@@ -733,6 +879,13 @@ struct drbd_device {
 	struct rb_root read_requests;
 	struct rb_root write_requests;
 
+	/* for statistics and timeouts */
+	/* [0] read, [1] write */
+	struct list_head pending_master_completion[2];
+	struct list_head pending_completion[2];
+
+	/* use checksums for *this* resync */
+	bool use_csums;
 	/* blocks to resync in this run [unit BM_BLOCK_SIZE] */
 	unsigned long rs_total;
 	/* number of resync blocks that failed in this run */
@@ -788,9 +941,7 @@ struct drbd_device {
 	atomic_t pp_in_use;		/* allocated from page pool */
 	atomic_t pp_in_use_by_net;	/* sendpage()d, still referenced by tcp */
 	wait_queue_head_t ee_wait;
-	struct page *md_io_page;	/* one page buffer for md_io */
 	struct drbd_md_io md_io;
-	atomic_t md_io_in_use;		/* protects the md_io, md_io_page and md_io_tmpp */
 	spinlock_t al_lock;
 	wait_queue_head_t al_wait;
 	struct lru_cache *act_log;	/* activity log */
@@ -800,7 +951,6 @@ struct drbd_device {
 	atomic_t packet_seq;
 	unsigned int peer_seq;
 	spinlock_t peer_seq_lock;
-	unsigned int minor;
 	unsigned long comm_bm_set; /* communicated number of set bits. */
 	struct bm_io_work bm_io_work;
 	u64 ed_uuid; /* UUID of the exposed data */
@@ -824,6 +974,21 @@ struct drbd_device {
 	struct submit_worker submit;
 };
 
+struct drbd_bm_aio_ctx {
+	struct drbd_device *device;
+	struct list_head list; /* on device->pending_bitmap_io */;
+	unsigned long start_jif;
+	atomic_t in_flight;
+	unsigned int done;
+	unsigned flags;
+#define BM_AIO_COPY_PAGES	1
+#define BM_AIO_WRITE_HINTED	2
+#define BM_AIO_WRITE_ALL_PAGES	4
+#define BM_AIO_READ		8
+	int error;
+	struct kref kref;
+};
+
 struct drbd_config_context {
 	/* assigned from drbd_genlmsghdr */
 	unsigned int minor;
@@ -949,7 +1114,7 @@ extern int drbd_send_ov_request(struct d
 extern int drbd_send_bitmap(struct drbd_device *device);
 extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
 extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode);
-extern void drbd_free_bc(struct drbd_backing_dev *ldev);
+extern void drbd_free_ldev(struct drbd_backing_dev *ldev);
 extern void drbd_device_cleanup(struct drbd_device *device);
 void drbd_print_uuids(struct drbd_device *device, const char *text);
 
@@ -966,13 +1131,7 @@ extern void __drbd_uuid_set(struct drbd_
 extern void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
 extern void drbd_md_clear_flag(struct drbd_device *device, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
-#ifndef DRBD_DEBUG_MD_SYNC
 extern void drbd_md_mark_dirty(struct drbd_device *device);
-#else
-#define drbd_md_mark_dirty(m)	drbd_md_mark_dirty_(m, __LINE__ , __func__ )
-extern void drbd_md_mark_dirty_(struct drbd_device *device,
-		unsigned int line, const char *func);
-#endif
 extern void drbd_queue_bitmap_io(struct drbd_device *device,
 				 int (*io_fn)(struct drbd_device *),
 				 void (*done)(struct drbd_device *, int),
@@ -983,9 +1142,8 @@ extern int drbd_bitmap_io(struct drbd_de
 extern int drbd_bitmap_io_from_worker(struct drbd_device *device,
 		int (*io_fn)(struct drbd_device *),
 		char *why, enum bm_flag flags);
-extern int drbd_bmio_set_n_write(struct drbd_device *device);
-extern int drbd_bmio_clear_n_write(struct drbd_device *device);
-extern void drbd_ldev_destroy(struct drbd_device *device);
+extern int drbd_bmio_set_n_write(struct drbd_device *device) __must_hold(local);
+extern int drbd_bmio_clear_n_write(struct drbd_device *device) __must_hold(local);
 
 /* Meta data layout
  *
@@ -1105,17 +1263,21 @@ struct bm_extent {
 /* in which _bitmap_ extent (resp. sector) the bit for a certain
  * _storage_ sector is located in */
 #define BM_SECT_TO_EXT(x)   ((x)>>(BM_EXT_SHIFT-9))
+#define BM_BIT_TO_EXT(x)    ((x) >> (BM_EXT_SHIFT - BM_BLOCK_SHIFT))
 
-/* how much _storage_ sectors we have per bitmap sector */
+/* first storage sector a bitmap extent corresponds to */
 #define BM_EXT_TO_SECT(x)   ((sector_t)(x) << (BM_EXT_SHIFT-9))
+/* how much _storage_ sectors we have per bitmap extent */
 #define BM_SECT_PER_EXT     BM_EXT_TO_SECT(1)
+/* how many bits are covered by one bitmap extent (resync extent) */
+#define BM_BITS_PER_EXT     (1UL << (BM_EXT_SHIFT - BM_BLOCK_SHIFT))
+
+#define BM_BLOCKS_PER_BM_EXT_MASK  (BM_BITS_PER_EXT - 1)
+
 
 /* in one sector of the bitmap, we have this many activity_log extents. */
 #define AL_EXT_PER_BM_SECT  (1 << (BM_EXT_SHIFT - AL_EXTENT_SHIFT))
 
-#define BM_BLOCKS_PER_BM_EXT_B (BM_EXT_SHIFT - BM_BLOCK_SHIFT)
-#define BM_BLOCKS_PER_BM_EXT_MASK  ((1<<BM_BLOCKS_PER_BM_EXT_B) - 1)
-
 /* the extent in "PER_EXTENT" below is an activity log extent
  * we need that many (long words/bytes) to store the bitmap
  *		     of one AL_EXTENT_SIZE chunk of storage.
@@ -1195,11 +1357,11 @@ extern void _drbd_bm_set_bits(struct drb
 		const unsigned long s, const unsigned long e);
 extern int  drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
 extern int  drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
-extern int  drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local);
 extern int  drbd_bm_read(struct drbd_device *device) __must_hold(local);
 extern void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
 extern int  drbd_bm_write(struct drbd_device *device) __must_hold(local);
 extern int  drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
+extern int  drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local);
 extern int drbd_bm_write_all(struct drbd_device *device) __must_hold(local);
 extern int  drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local);
 extern size_t	     drbd_bm_words(struct drbd_device *device);
@@ -1213,7 +1375,6 @@ extern unsigned long _drbd_bm_find_next(
 extern unsigned long _drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo);
 extern unsigned long _drbd_bm_total_weight(struct drbd_device *device);
 extern unsigned long drbd_bm_total_weight(struct drbd_device *device);
-extern int drbd_bm_rs_done(struct drbd_device *device);
 /* for receive_bitmap */
 extern void drbd_bm_merge_lel(struct drbd_device *device, size_t offset,
 		size_t number, unsigned long *buffer);
@@ -1312,7 +1473,7 @@ enum determine_dev_size {
 extern enum determine_dev_size
 drbd_determine_dev_size(struct drbd_device *, enum dds_flags, struct resize_parms *) __must_hold(local);
 extern void resync_after_online_grow(struct drbd_device *);
-extern void drbd_reconsider_max_bio_size(struct drbd_device *device);
+extern void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backing_dev *bdev);
 extern enum drbd_state_rv drbd_set_role(struct drbd_device *device,
 					enum drbd_role new_role,
 					int force);
@@ -1333,7 +1494,7 @@ extern void resume_next_sg(struct drbd_d
 extern void suspend_other_sg(struct drbd_device *device);
 extern int drbd_resync_finished(struct drbd_device *device);
 /* maybe rather drbd_main.c ? */
-extern void *drbd_md_get_buffer(struct drbd_device *device);
+extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent);
 extern void drbd_md_put_buffer(struct drbd_device *device);
 extern int drbd_md_sync_page_io(struct drbd_device *device,
 		struct drbd_backing_dev *bdev, sector_t sector, int rw);
@@ -1380,7 +1541,8 @@ extern void drbd_endio_write_sec_final(s
 extern int drbd_receiver(struct drbd_thread *thi);
 extern int drbd_asender(struct drbd_thread *thi);
 extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
-extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector);
+extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
+		bool throttle_if_app_is_waiting);
 extern int drbd_submit_peer_request(struct drbd_device *,
 				    struct drbd_peer_request *, const unsigned,
 				    const int);
@@ -1464,10 +1626,7 @@ static inline void drbd_generic_make_req
 {
 	__release(local);
 	if (!bio->bi_bdev) {
-		printk(KERN_ERR "drbd%d: drbd_generic_make_request: "
-				"bio->bi_bdev == NULL\n",
-		       device_to_minor(device));
-		dump_stack();
+		drbd_err(device, "drbd_generic_make_request: bio->bi_bdev == NULL\n");
 		bio_endio(bio, -ENODEV);
 		return;
 	}
@@ -1478,7 +1637,8 @@ static inline void drbd_generic_make_req
 		generic_make_request(bio);
 }
 
-void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
+			      enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
@@ -1489,9 +1649,9 @@ extern const char *drbd_role_str(enum dr
 /* drbd_actlog.c */
 extern bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval *i);
 extern int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate);
+extern void drbd_al_begin_io_commit(struct drbd_device *device);
 extern bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate);
+extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i);
 extern void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i);
 extern void drbd_rs_complete_io(struct drbd_device *device, sector_t sector);
 extern int drbd_rs_begin_io(struct drbd_device *device, sector_t sector);
@@ -1501,14 +1661,17 @@ extern int drbd_rs_del_all(struct drbd_d
 extern void drbd_rs_failed_io(struct drbd_device *device,
 		sector_t sector, int size);
 extern void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go);
-extern void __drbd_set_in_sync(struct drbd_device *device, sector_t sector,
-		int size, const char *file, const unsigned int line);
+
+enum update_sync_bits_mode { RECORD_RS_FAILED, SET_OUT_OF_SYNC, SET_IN_SYNC };
+extern int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
+		enum update_sync_bits_mode mode,
+		const char *file, const unsigned int line);
 #define drbd_set_in_sync(device, sector, size) \
-	__drbd_set_in_sync(device, sector, size, __FILE__, __LINE__)
-extern int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector,
-		int size, const char *file, const unsigned int line);
+	__drbd_change_sync(device, sector, size, SET_IN_SYNC, __FILE__, __LINE__)
 #define drbd_set_out_of_sync(device, sector, size) \
-	__drbd_set_out_of_sync(device, sector, size, __FILE__, __LINE__)
+	__drbd_change_sync(device, sector, size, SET_OUT_OF_SYNC, __FILE__, __LINE__)
+#define drbd_rs_failed_io(device, sector, size) \
+	__drbd_change_sync(device, sector, size, RECORD_RS_FAILED, __FILE__, __LINE__)
 extern void drbd_al_shrink(struct drbd_device *device);
 extern int drbd_initialize_al(struct drbd_device *, void *);
 
@@ -1764,25 +1927,38 @@ static inline sector_t drbd_md_ss(struct
 }
 
 static inline void
-drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
+drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&q->q_lock, flags);
-	list_add(&w->list, &q->q);
+	list_add_tail(&w->list, &q->q);
 	spin_unlock_irqrestore(&q->q_lock, flags);
 	wake_up(&q->q_wait);
 }
 
 static inline void
-drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
+drbd_queue_work_if_unqueued(struct drbd_work_queue *q, struct drbd_work *w)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&q->q_lock, flags);
-	list_add_tail(&w->list, &q->q);
+	if (list_empty_careful(&w->list))
+		list_add_tail(&w->list, &q->q);
 	spin_unlock_irqrestore(&q->q_lock, flags);
 	wake_up(&q->q_wait);
 }
 
+static inline void
+drbd_device_post_work(struct drbd_device *device, int work_bit)
+{
+	if (!test_and_set_bit(work_bit, &device->flags)) {
+		struct drbd_connection *connection =
+			first_peer_device(device)->connection;
+		struct drbd_work_queue *q = &connection->sender_work;
+		if (!test_and_set_bit(DEVICE_WORK_PENDING, &connection->flags))
+			wake_up(&q->q_wait);
+	}
+}
+
 extern void drbd_flush_workqueue(struct drbd_work_queue *work_queue);
 
 static inline void wake_asender(struct drbd_connection *connection)
@@ -1859,7 +2035,7 @@ static inline void inc_ap_pending(struct
 			func, line,					\
 			atomic_read(&device->which))
 
-#define dec_ap_pending(device) _dec_ap_pending(device, __FUNCTION__, __LINE__)
+#define dec_ap_pending(device) _dec_ap_pending(device, __func__, __LINE__)
 static inline void _dec_ap_pending(struct drbd_device *device, const char *func, int line)
 {
 	if (atomic_dec_and_test(&device->ap_pending_cnt))
@@ -1878,7 +2054,7 @@ static inline void inc_rs_pending(struct
 	atomic_inc(&device->rs_pending_cnt);
 }
 
-#define dec_rs_pending(device) _dec_rs_pending(device, __FUNCTION__, __LINE__)
+#define dec_rs_pending(device) _dec_rs_pending(device, __func__, __LINE__)
 static inline void _dec_rs_pending(struct drbd_device *device, const char *func, int line)
 {
 	atomic_dec(&device->rs_pending_cnt);
@@ -1899,20 +2075,29 @@ static inline void inc_unacked(struct dr
 	atomic_inc(&device->unacked_cnt);
 }
 
-#define dec_unacked(device) _dec_unacked(device, __FUNCTION__, __LINE__)
+#define dec_unacked(device) _dec_unacked(device, __func__, __LINE__)
 static inline void _dec_unacked(struct drbd_device *device, const char *func, int line)
 {
 	atomic_dec(&device->unacked_cnt);
 	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
-#define sub_unacked(device, n) _sub_unacked(device, n, __FUNCTION__, __LINE__)
+#define sub_unacked(device, n) _sub_unacked(device, n, __func__, __LINE__)
 static inline void _sub_unacked(struct drbd_device *device, int n, const char *func, int line)
 {
 	atomic_sub(n, &device->unacked_cnt);
 	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
+static inline bool is_sync_state(enum drbd_conns connection_state)
+{
+	return
+	   (connection_state == C_SYNC_SOURCE
+	||  connection_state == C_SYNC_TARGET
+	||  connection_state == C_PAUSED_SYNC_S
+	||  connection_state == C_PAUSED_SYNC_T);
+}
+
 /**
  * get_ldev() - Increase the ref count on device->ldev. Returns 0 if there is no ldev
  * @M:		DRBD device.
@@ -1924,6 +2109,11 @@ static inline void _sub_unacked(struct d
 
 static inline void put_ldev(struct drbd_device *device)
 {
+	enum drbd_disk_state ds = device->state.disk;
+	/* We must check the state *before* the atomic_dec becomes visible,
+	 * or we have a theoretical race where someone hitting zero,
+	 * while state still D_FAILED, will then see D_DISKLESS in the
+	 * condition below and calling into destroy, where he must not, yet. */
 	int i = atomic_dec_return(&device->local_cnt);
 
 	/* This may be called from some endio handler,
@@ -1932,15 +2122,13 @@ static inline void put_ldev(struct drbd_
 	__release(local);
 	D_ASSERT(device, i >= 0);
 	if (i == 0) {
-		if (device->state.disk == D_DISKLESS)
+		if (ds == D_DISKLESS)
 			/* even internal references gone, safe to destroy */
-			drbd_ldev_destroy(device);
-		if (device->state.disk == D_FAILED) {
+			drbd_device_post_work(device, DESTROY_DISK);
+		if (ds == D_FAILED)
 			/* all application IO references gone. */
-			if (!test_and_set_bit(GO_DISKLESS, &device->flags))
-				drbd_queue_work(&first_peer_device(device)->connection->sender_work,
-						&device->go_diskless);
-		}
+			if (!test_and_set_bit(GOING_DISKLESS, &device->flags))
+				drbd_device_post_work(device, GO_DISKLESS);
 		wake_up(&device->misc_wait);
 	}
 }
@@ -1964,54 +2152,6 @@ static inline int _get_ldev_if_state(str
 extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins);
 #endif
 
-/* you must have an "get_ldev" reference */
-static inline void drbd_get_syncer_progress(struct drbd_device *device,
-		unsigned long *bits_left, unsigned int *per_mil_done)
-{
-	/* this is to break it at compile time when we change that, in case we
-	 * want to support more than (1<<32) bits on a 32bit arch. */
-	typecheck(unsigned long, device->rs_total);
-
-	/* note: both rs_total and rs_left are in bits, i.e. in
-	 * units of BM_BLOCK_SIZE.
-	 * for the percentage, we don't care. */
-
-	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
-		*bits_left = device->ov_left;
-	else
-		*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
-	/* >> 10 to prevent overflow,
-	 * +1 to prevent division by zero */
-	if (*bits_left > device->rs_total) {
-		/* doh. maybe a logic bug somewhere.
-		 * may also be just a race condition
-		 * between this and a disconnect during sync.
-		 * for now, just prevent in-kernel buffer overflow.
-		 */
-		smp_rmb();
-		drbd_warn(device, "cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n",
-				drbd_conn_str(device->state.conn),
-				*bits_left, device->rs_total, device->rs_failed);
-		*per_mil_done = 0;
-	} else {
-		/* Make sure the division happens in long context.
-		 * We allow up to one petabyte storage right now,
-		 * at a granularity of 4k per bit that is 2**38 bits.
-		 * After shift right and multiplication by 1000,
-		 * this should still fit easily into a 32bit long,
-		 * so we don't need a 64bit division on 32bit arch.
-		 * Note: currently we don't support such large bitmaps on 32bit
-		 * arch anyways, but no harm done to be prepared for it here.
-		 */
-		unsigned int shift = device->rs_total > UINT_MAX ? 16 : 10;
-		unsigned long left = *bits_left >> shift;
-		unsigned long total = 1UL + (device->rs_total >> shift);
-		unsigned long tmp = 1000UL - left * 1000UL/total;
-		*per_mil_done = tmp;
-	}
-}
-
-
 /* this throttles on-the-fly application requests
  * according to max_buffers settings;
  * maybe re-implement using semaphores? */
@@ -2201,25 +2341,6 @@ static inline int drbd_queue_order_type(
 	return QUEUE_ORDERED_NONE;
 }
 
-static inline void drbd_md_flush(struct drbd_device *device)
-{
-	int r;
-
-	if (device->ldev == NULL) {
-		drbd_warn(device, "device->ldev == NULL in drbd_md_flush\n");
-		return;
-	}
-
-	if (test_bit(MD_NO_FUA, &device->flags))
-		return;
-
-	r = blkdev_issue_flush(device->ldev->md_bdev, GFP_NOIO, NULL);
-	if (r) {
-		set_bit(MD_NO_FUA, &device->flags);
-		drbd_err(device, "meta data flush failed with status %d, disabling md-flushes\n", r);
-	}
-}
-
 static inline struct drbd_connection *first_connection(struct drbd_resource *resource)
 {
 	return list_first_entry_or_null(&resource->connections,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_main.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_main.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,10 @@
 
  */
 
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
+#include <linux/jiffies.h>
 #include <linux/drbd.h>
 #include <asm/uaccess.h>
 #include <asm/types.h>
@@ -54,16 +57,14 @@
 #include "drbd_int.h"
 #include "drbd_protocol.h"
 #include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */
-
 #include "drbd_vli.h"
+#include "drbd_debugfs.h"
 
 static DEFINE_MUTEX(drbd_main_mutex);
 static int drbd_open(struct block_device *bdev, fmode_t mode);
 static void drbd_release(struct gendisk *gd, fmode_t mode);
-static int w_md_sync(struct drbd_work *w, int unused);
 static void md_sync_timer_fn(unsigned long data);
 static int w_bitmap_io(struct drbd_work *w, int unused);
-static int w_go_diskless(struct drbd_work *w, int unused);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
 	      "Lars Ellenberg <lars@linbit.com>");
@@ -264,7 +265,7 @@ bail:
 
 /**
  * _tl_restart() - Walks the transfer log, and applies an action to all requests
- * @device:	DRBD device.
+ * @connection:	DRBD connection to operate on.
  * @what:       The action/event to perform with all request objects
  *
  * @what might be one of CONNECTION_LOST_WHILE_PENDING, RESEND, FAIL_FROZEN_DISK_IO,
@@ -662,6 +663,11 @@ static int __send_command(struct drbd_co
 			    msg_flags);
 	if (data && !err)
 		err = drbd_send_all(connection, sock->socket, data, size, 0);
+	/* DRBD protocol "pings" are latency critical.
+	 * This is supposed to trigger tcp_push_pending_frames() */
+	if (!err && (cmd == P_PING || cmd == P_PING_ACK))
+		drbd_tcp_nodelay(sock->socket);
+
 	return err;
 }
 
@@ -1636,7 +1642,10 @@ int drbd_send_dblock(struct drbd_peer_de
 	if (peer_device->connection->agreed_pro_version >= 100) {
 		if (req->rq_state & RQ_EXP_RECEIVE_ACK)
 			dp_flags |= DP_SEND_RECEIVE_ACK;
-		if (req->rq_state & RQ_EXP_WRITE_ACK)
+		/* During resync, request an explicit write ack,
+		 * even in protocol != C */
+		if (req->rq_state & RQ_EXP_WRITE_ACK
+		|| (dp_flags & DP_MAY_SET_IN_SYNC))
 			dp_flags |= DP_SEND_WRITE_ACK;
 	}
 	p->dp_flags = cpu_to_be32(dp_flags);
@@ -1900,6 +1909,7 @@ void drbd_init_set_defaults(struct drbd_
 	drbd_set_defaults(device);
 
 	atomic_set(&device->ap_bio_cnt, 0);
+	atomic_set(&device->ap_actlog_cnt, 0);
 	atomic_set(&device->ap_pending_cnt, 0);
 	atomic_set(&device->rs_pending_cnt, 0);
 	atomic_set(&device->unacked_cnt, 0);
@@ -1908,7 +1918,7 @@ void drbd_init_set_defaults(struct drbd_
 	atomic_set(&device->rs_sect_in, 0);
 	atomic_set(&device->rs_sect_ev, 0);
 	atomic_set(&device->ap_in_flight, 0);
-	atomic_set(&device->md_io_in_use, 0);
+	atomic_set(&device->md_io.in_use, 0);
 
 	mutex_init(&device->own_state_mutex);
 	device->state_mutex = &device->own_state_mutex;
@@ -1924,17 +1934,15 @@ void drbd_init_set_defaults(struct drbd_
 	INIT_LIST_HEAD(&device->resync_reads);
 	INIT_LIST_HEAD(&device->resync_work.list);
 	INIT_LIST_HEAD(&device->unplug_work.list);
-	INIT_LIST_HEAD(&device->go_diskless.list);
-	INIT_LIST_HEAD(&device->md_sync_work.list);
-	INIT_LIST_HEAD(&device->start_resync_work.list);
 	INIT_LIST_HEAD(&device->bm_io_work.w.list);
+	INIT_LIST_HEAD(&device->pending_master_completion[0]);
+	INIT_LIST_HEAD(&device->pending_master_completion[1]);
+	INIT_LIST_HEAD(&device->pending_completion[0]);
+	INIT_LIST_HEAD(&device->pending_completion[1]);
 
 	device->resync_work.cb  = w_resync_timer;
 	device->unplug_work.cb  = w_send_write_hint;
-	device->go_diskless.cb  = w_go_diskless;
-	device->md_sync_work.cb = w_md_sync;
 	device->bm_io_work.w.cb = w_bitmap_io;
-	device->start_resync_work.cb = w_start_resync;
 
 	init_timer(&device->resync_timer);
 	init_timer(&device->md_sync_timer);
@@ -1992,7 +2000,7 @@ void drbd_device_cleanup(struct drbd_dev
 		drbd_bm_cleanup(device);
 	}
 
-	drbd_free_bc(device->ldev);
+	drbd_free_ldev(device->ldev);
 	device->ldev = NULL;
 
 	clear_bit(AL_SUSPENDED, &device->flags);
@@ -2006,7 +2014,6 @@ void drbd_device_cleanup(struct drbd_dev
 	D_ASSERT(device, list_empty(&first_peer_device(device)->connection->sender_work.q));
 	D_ASSERT(device, list_empty(&device->resync_work.list));
 	D_ASSERT(device, list_empty(&device->unplug_work.list));
-	D_ASSERT(device, list_empty(&device->go_diskless.list));
 
 	drbd_set_defaults(device);
 }
@@ -2129,20 +2136,6 @@ Enomem:
 	return -ENOMEM;
 }
 
-static int drbd_notify_sys(struct notifier_block *this, unsigned long code,
-	void *unused)
-{
-	/* just so we have it.  you never know what interesting things we
-	 * might want to do here some day...
-	 */
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block drbd_notifier = {
-	.notifier_call = drbd_notify_sys,
-};
-
 static void drbd_release_all_peer_reqs(struct drbd_device *device)
 {
 	int rr;
@@ -2173,7 +2166,7 @@ void drbd_destroy_device(struct kref *kr
 {
 	struct drbd_device *device = container_of(kref, struct drbd_device, kref);
 	struct drbd_resource *resource = device->resource;
-	struct drbd_connection *connection;
+	struct drbd_peer_device *peer_device, *tmp_peer_device;
 
 	del_timer_sync(&device->request_timer);
 
@@ -2187,7 +2180,7 @@ void drbd_destroy_device(struct kref *kr
 	if (device->this_bdev)
 		bdput(device->this_bdev);
 
-	drbd_free_bc(device->ldev);
+	drbd_free_ldev(device->ldev);
 	device->ldev = NULL;
 
 	drbd_release_all_peer_reqs(device);
@@ -2200,15 +2193,20 @@ void drbd_destroy_device(struct kref *kr
 
 	if (device->bitmap) /* should no longer be there. */
 		drbd_bm_cleanup(device);
-	__free_page(device->md_io_page);
+	__free_page(device->md_io.page);
 	put_disk(device->vdisk);
 	blk_cleanup_queue(device->rq_queue);
 	kfree(device->rs_plan_s);
-	kfree(first_peer_device(device));
-	kfree(device);
 
-	for_each_connection(connection, resource)
-		kref_put(&connection->kref, drbd_destroy_connection);
+	/* not for_each_connection(connection, resource):
+	 * those may have been cleaned up and disassociated already.
+	 */
+	for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
+		kref_put(&peer_device->connection->kref, drbd_destroy_connection);
+		kfree(peer_device);
+	}
+	memset(device, 0xfd, sizeof(*device));
+	kfree(device);
 	kref_put(&resource->kref, drbd_destroy_resource);
 }
 
@@ -2236,7 +2234,7 @@ static void do_retry(struct work_struct
 	list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
 		struct drbd_device *device = req->device;
 		struct bio *bio = req->master_bio;
-		unsigned long start_time = req->start_time;
+		unsigned long start_jif = req->start_jif;
 		bool expected;
 
 		expected =
@@ -2271,10 +2269,12 @@ static void do_retry(struct work_struct
 		/* We are not just doing generic_make_request(),
 		 * as we want to keep the start_time information. */
 		inc_ap_bio(device);
-		__drbd_make_request(device, bio, start_time);
+		__drbd_make_request(device, bio, start_jif);
 	}
 }
 
+/* called via drbd_req_put_completion_ref(),
+ * holds resource->req_lock */
 void drbd_restart_request(struct drbd_request *req)
 {
 	unsigned long flags;
@@ -2298,6 +2298,7 @@ void drbd_destroy_resource(struct kref *
 	idr_destroy(&resource->devices);
 	free_cpumask_var(resource->cpu_mask);
 	kfree(resource->name);
+	memset(resource, 0xf2, sizeof(*resource));
 	kfree(resource);
 }
 
@@ -2307,8 +2308,10 @@ void drbd_free_resource(struct drbd_reso
 
 	for_each_connection_safe(connection, tmp, resource) {
 		list_del(&connection->connections);
+		drbd_debugfs_connection_cleanup(connection);
 		kref_put(&connection->kref, drbd_destroy_connection);
 	}
+	drbd_debugfs_resource_cleanup(resource);
 	kref_put(&resource->kref, drbd_destroy_resource);
 }
 
@@ -2318,8 +2321,6 @@ static void drbd_cleanup(void)
 	struct drbd_device *device;
 	struct drbd_resource *resource, *tmp;
 
-	unregister_reboot_notifier(&drbd_notifier);
-
 	/* first remove proc,
 	 * drbdsetup uses it's presence to detect
 	 * whether DRBD is loaded.
@@ -2335,6 +2336,7 @@ static void drbd_cleanup(void)
 		destroy_workqueue(retry.wq);
 
 	drbd_genl_unregister();
+	drbd_debugfs_cleanup();
 
 	idr_for_each_entry(&drbd_devices, device, i)
 		drbd_delete_device(device);
@@ -2350,7 +2352,7 @@ static void drbd_cleanup(void)
 
 	idr_destroy(&drbd_devices);
 
-	printk(KERN_INFO "drbd: module cleanup done.\n");
+	pr_info("module cleanup done.\n");
 }
 
 /**
@@ -2539,6 +2541,20 @@ int set_resource_options(struct drbd_res
 	if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
 		err = bitmap_parse(res_opts->cpu_mask, DRBD_CPU_MASK_SIZE,
 				   cpumask_bits(new_cpu_mask), nr_cpu_ids);
+		if (err == -EOVERFLOW) {
+			/* So what. mask it out. */
+			cpumask_var_t tmp_cpu_mask;
+			if (zalloc_cpumask_var(&tmp_cpu_mask, GFP_KERNEL)) {
+				cpumask_setall(tmp_cpu_mask);
+				cpumask_and(new_cpu_mask, new_cpu_mask, tmp_cpu_mask);
+				drbd_warn(resource, "Overflow in bitmap_parse(%.12s%s), truncating to %u bits\n",
+					res_opts->cpu_mask,
+					strlen(res_opts->cpu_mask) > 12 ? "..." : "",
+					nr_cpu_ids);
+				free_cpumask_var(tmp_cpu_mask);
+				err = 0;
+			}
+		}
 		if (err) {
 			drbd_warn(resource, "bitmap_parse() failed with %d\n", err);
 			/* retcode = ERR_CPU_MASK_PARSE; */
@@ -2579,10 +2595,12 @@ struct drbd_resource *drbd_create_resour
 	kref_init(&resource->kref);
 	idr_init(&resource->devices);
 	INIT_LIST_HEAD(&resource->connections);
+	resource->write_ordering = WO_bdev_flush;
 	list_add_tail_rcu(&resource->resources, &drbd_resources);
 	mutex_init(&resource->conf_update);
 	mutex_init(&resource->adm_mutex);
 	spin_lock_init(&resource->req_lock);
+	drbd_debugfs_resource_add(resource);
 	return resource;
 
 fail_free_name:
@@ -2593,7 +2611,7 @@ fail:
 	return NULL;
 }
 
-/* caller must be under genl_lock() */
+/* caller must be under adm_mutex */
 struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
 {
 	struct drbd_resource *resource;
@@ -2617,7 +2635,6 @@ struct drbd_connection *conn_create(cons
 	INIT_LIST_HEAD(&connection->current_epoch->list);
 	connection->epochs = 1;
 	spin_lock_init(&connection->epoch_lock);
-	connection->write_ordering = WO_bdev_flush;
 
 	connection->send.seen_any_write_yet = false;
 	connection->send.current_epoch_nr = 0;
@@ -2652,6 +2669,7 @@ struct drbd_connection *conn_create(cons
 
 	kref_get(&resource->kref);
 	list_add_tail_rcu(&connection->connections, &resource->connections);
+	drbd_debugfs_connection_add(connection);
 	return connection;
 
 fail_resource:
@@ -2680,6 +2698,7 @@ void drbd_destroy_connection(struct kref
 	drbd_free_socket(&connection->data);
 	kfree(connection->int_dig_in);
 	kfree(connection->int_dig_vv);
+	memset(connection, 0xfc, sizeof(*connection));
 	kfree(connection);
 	kref_put(&resource->kref, drbd_destroy_resource);
 }
@@ -2694,7 +2713,6 @@ static int init_submitter(struct drbd_de
 		return -ENOMEM;
 
 	INIT_WORK(&device->submit.worker, do_submit);
-	spin_lock_init(&device->submit.lock);
 	INIT_LIST_HEAD(&device->submit.writes);
 	return 0;
 }
@@ -2764,8 +2782,8 @@ enum drbd_ret_code drbd_create_device(st
 	blk_queue_merge_bvec(q, drbd_merge_bvec);
 	q->queue_lock = &resource->req_lock;
 
-	device->md_io_page = alloc_page(GFP_KERNEL);
-	if (!device->md_io_page)
+	device->md_io.page = alloc_page(GFP_KERNEL);
+	if (!device->md_io.page)
 		goto out_no_io_page;
 
 	if (drbd_bm_init(device))
@@ -2794,6 +2812,7 @@ enum drbd_ret_code drbd_create_device(st
 	kref_get(&device->kref);
 
 	INIT_LIST_HEAD(&device->peer_devices);
+	INIT_LIST_HEAD(&device->pending_bitmap_io);
 	for_each_connection(connection, resource) {
 		peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
 		if (!peer_device)
@@ -2829,7 +2848,10 @@ enum drbd_ret_code drbd_create_device(st
 		for_each_peer_device(peer_device, device)
 			drbd_connected(peer_device);
 	}
-
+	/* move to create_peer_device() */
+	for_each_peer_device(peer_device, device)
+		drbd_debugfs_peer_device_add(peer_device);
+	drbd_debugfs_device_add(device);
 	return NO_ERROR;
 
 out_idr_remove_vol:
@@ -2853,7 +2875,7 @@ out_idr_remove_minor:
 out_no_minor_idr:
 	drbd_bm_cleanup(device);
 out_no_bitmap:
-	__free_page(device->md_io_page);
+	__free_page(device->md_io.page);
 out_no_io_page:
 	put_disk(disk);
 out_no_disk:
@@ -2868,8 +2890,13 @@ void drbd_delete_device(struct drbd_devi
 {
 	struct drbd_resource *resource = device->resource;
 	struct drbd_connection *connection;
+	struct drbd_peer_device *peer_device;
 	int refs = 3;
 
+	/* move to free_peer_device() */
+	for_each_peer_device(peer_device, device)
+		drbd_debugfs_peer_device_cleanup(peer_device);
+	drbd_debugfs_device_cleanup(device);
 	for_each_connection(connection, resource) {
 		idr_remove(&connection->peer_devices, device->vnr);
 		refs++;
@@ -2881,13 +2908,12 @@ void drbd_delete_device(struct drbd_devi
 	kref_sub(&device->kref, refs, drbd_destroy_device);
 }
 
-int __init drbd_init(void)
+static int __init drbd_init(void)
 {
 	int err;
 
 	if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
-		printk(KERN_ERR
-		       "drbd: invalid minor_count (%d)\n", minor_count);
+		pr_err("invalid minor_count (%d)\n", minor_count);
 #ifdef MODULE
 		return -EINVAL;
 #else
@@ -2897,14 +2923,11 @@ int __init drbd_init(void)
 
 	err = register_blkdev(DRBD_MAJOR, "drbd");
 	if (err) {
-		printk(KERN_ERR
-		       "drbd: unable to register block device major %d\n",
+		pr_err("unable to register block device major %d\n",
 		       DRBD_MAJOR);
 		return err;
 	}
 
-	register_reboot_notifier(&drbd_notifier);
-
 	/*
 	 * allocate all necessary structs
 	 */
@@ -2918,7 +2941,7 @@ int __init drbd_init(void)
 
 	err = drbd_genl_register();
 	if (err) {
-		printk(KERN_ERR "drbd: unable to register generic netlink family\n");
+		pr_err("unable to register generic netlink family\n");
 		goto fail;
 	}
 
@@ -2929,38 +2952,39 @@ int __init drbd_init(void)
 	err = -ENOMEM;
 	drbd_proc = proc_create_data("drbd", S_IFREG | S_IRUGO , NULL, &drbd_proc_fops, NULL);
 	if (!drbd_proc)	{
-		printk(KERN_ERR "drbd: unable to register proc file\n");
+		pr_err("unable to register proc file\n");
 		goto fail;
 	}
 
 	retry.wq = create_singlethread_workqueue("drbd-reissue");
 	if (!retry.wq) {
-		printk(KERN_ERR "drbd: unable to create retry workqueue\n");
+		pr_err("unable to create retry workqueue\n");
 		goto fail;
 	}
 	INIT_WORK(&retry.worker, do_retry);
 	spin_lock_init(&retry.lock);
 	INIT_LIST_HEAD(&retry.writes);
 
-	printk(KERN_INFO "drbd: initialized. "
+	if (drbd_debugfs_init())
+		pr_notice("failed to initialize debugfs -- will not be available\n");
+
+	pr_info("initialized. "
 	       "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n",
 	       API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX);
-	printk(KERN_INFO "drbd: %s\n", drbd_buildtag());
-	printk(KERN_INFO "drbd: registered as block device major %d\n",
-		DRBD_MAJOR);
-
+	pr_info("%s\n", drbd_buildtag());
+	pr_info("registered as block device major %d\n", DRBD_MAJOR);
 	return 0; /* Success! */
 
 fail:
 	drbd_cleanup();
 	if (err == -ENOMEM)
-		printk(KERN_ERR "drbd: ran out of memory\n");
+		pr_err("ran out of memory\n");
 	else
-		printk(KERN_ERR "drbd: initialization failure\n");
+		pr_err("initialization failure\n");
 	return err;
 }
 
-void drbd_free_bc(struct drbd_backing_dev *ldev)
+void drbd_free_ldev(struct drbd_backing_dev *ldev)
 {
 	if (ldev == NULL)
 		return;
@@ -2972,24 +2996,29 @@ void drbd_free_bc(struct drbd_backing_de
 	kfree(ldev);
 }
 
-void drbd_free_sock(struct drbd_connection *connection)
+static void drbd_free_one_sock(struct drbd_socket *ds)
 {
-	if (connection->data.socket) {
-		mutex_lock(&connection->data.mutex);
-		kernel_sock_shutdown(connection->data.socket, SHUT_RDWR);
-		sock_release(connection->data.socket);
-		connection->data.socket = NULL;
-		mutex_unlock(&connection->data.mutex);
-	}
-	if (connection->meta.socket) {
-		mutex_lock(&connection->meta.mutex);
-		kernel_sock_shutdown(connection->meta.socket, SHUT_RDWR);
-		sock_release(connection->meta.socket);
-		connection->meta.socket = NULL;
-		mutex_unlock(&connection->meta.mutex);
+	struct socket *s;
+	mutex_lock(&ds->mutex);
+	s = ds->socket;
+	ds->socket = NULL;
+	mutex_unlock(&ds->mutex);
+	if (s) {
+		/* so debugfs does not need to mutex_lock() */
+		synchronize_rcu();
+		kernel_sock_shutdown(s, SHUT_RDWR);
+		sock_release(s);
 	}
 }
 
+void drbd_free_sock(struct drbd_connection *connection)
+{
+	if (connection->data.socket)
+		drbd_free_one_sock(&connection->data);
+	if (connection->meta.socket)
+		drbd_free_one_sock(&connection->meta);
+}
+
 /* meta data management */
 
 void conn_md_sync(struct drbd_connection *connection)
@@ -3093,7 +3122,7 @@ void drbd_md_sync(struct drbd_device *de
 	if (!get_ldev_if_state(device, D_FAILED))
 		return;
 
-	buffer = drbd_md_get_buffer(device);
+	buffer = drbd_md_get_buffer(device, __func__);
 	if (!buffer)
 		goto out;
 
@@ -3253,7 +3282,7 @@ int drbd_md_read(struct drbd_device *dev
 	if (device->state.disk != D_DISKLESS)
 		return ERR_DISK_CONFIGURED;
 
-	buffer = drbd_md_get_buffer(device);
+	buffer = drbd_md_get_buffer(device, __func__);
 	if (!buffer)
 		return ERR_NOMEM;
 
@@ -3466,23 +3495,19 @@ void drbd_uuid_set_bm(struct drbd_device
  *
  * Sets all bits in the bitmap and writes the whole bitmap to stable storage.
  */
-int drbd_bmio_set_n_write(struct drbd_device *device)
+int drbd_bmio_set_n_write(struct drbd_device *device) __must_hold(local)
 {
 	int rv = -EIO;
 
-	if (get_ldev_if_state(device, D_ATTACHING)) {
-		drbd_md_set_flag(device, MDF_FULL_SYNC);
-		drbd_md_sync(device);
-		drbd_bm_set_all(device);
-
-		rv = drbd_bm_write(device);
+	drbd_md_set_flag(device, MDF_FULL_SYNC);
+	drbd_md_sync(device);
+	drbd_bm_set_all(device);
 
-		if (!rv) {
-			drbd_md_clear_flag(device, MDF_FULL_SYNC);
-			drbd_md_sync(device);
-		}
+	rv = drbd_bm_write(device);
 
-		put_ldev(device);
+	if (!rv) {
+		drbd_md_clear_flag(device, MDF_FULL_SYNC);
+		drbd_md_sync(device);
 	}
 
 	return rv;
@@ -3494,18 +3519,11 @@ int drbd_bmio_set_n_write(struct drbd_de
  *
  * Clears all bits in the bitmap and writes the whole bitmap to stable storage.
  */
-int drbd_bmio_clear_n_write(struct drbd_device *device)
+int drbd_bmio_clear_n_write(struct drbd_device *device) __must_hold(local)
 {
-	int rv = -EIO;
-
 	drbd_resume_al(device);
-	if (get_ldev_if_state(device, D_ATTACHING)) {
-		drbd_bm_clear_all(device);
-		rv = drbd_bm_write(device);
-		put_ldev(device);
-	}
-
-	return rv;
+	drbd_bm_clear_all(device);
+	return drbd_bm_write(device);
 }
 
 static int w_bitmap_io(struct drbd_work *w, int unused)
@@ -3537,61 +3555,6 @@ static int w_bitmap_io(struct drbd_work
 	return 0;
 }
 
-void drbd_ldev_destroy(struct drbd_device *device)
-{
-	lc_destroy(device->resync);
-	device->resync = NULL;
-	lc_destroy(device->act_log);
-	device->act_log = NULL;
-	__no_warn(local,
-		drbd_free_bc(device->ldev);
-		device->ldev = NULL;);
-
-	clear_bit(GO_DISKLESS, &device->flags);
-}
-
-static int w_go_diskless(struct drbd_work *w, int unused)
-{
-	struct drbd_device *device =
-		container_of(w, struct drbd_device, go_diskless);
-
-	D_ASSERT(device, device->state.disk == D_FAILED);
-	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
-	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
-	 * the protected members anymore, though, so once put_ldev reaches zero
-	 * again, it will be safe to free them. */
-
-	/* Try to write changed bitmap pages, read errors may have just
-	 * set some bits outside the area covered by the activity log.
-	 *
-	 * If we have an IO error during the bitmap writeout,
-	 * we will want a full sync next time, just in case.
-	 * (Do we want a specific meta data flag for this?)
-	 *
-	 * If that does not make it to stable storage either,
-	 * we cannot do anything about that anymore.
-	 *
-	 * We still need to check if both bitmap and ldev are present, we may
-	 * end up here after a failed attach, before ldev was even assigned.
-	 */
-	if (device->bitmap && device->ldev) {
-		/* An interrupted resync or similar is allowed to recounts bits
-		 * while we detach.
-		 * Any modifications would not be expected anymore, though.
-		 */
-		if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
-					"detach", BM_LOCKED_TEST_ALLOWED)) {
-			if (test_bit(WAS_READ_ERROR, &device->flags)) {
-				drbd_md_set_flag(device, MDF_FULL_SYNC);
-				drbd_md_sync(device);
-			}
-		}
-	}
-
-	drbd_force_state(device, NS(disk, D_DISKLESS));
-	return 0;
-}
-
 /**
  * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
  * @device:	DRBD device.
@@ -3603,6 +3566,9 @@ static int w_go_diskless(struct drbd_wor
  * that drbd_set_out_of_sync() can not be called. This function MAY ONLY be
  * called from worker context. It MUST NOT be used while a previous such
  * work is still pending!
+ *
+ * Its worker function encloses the call of io_fn() by get_ldev() and
+ * put_ldev().
  */
 void drbd_queue_bitmap_io(struct drbd_device *device,
 			  int (*io_fn)(struct drbd_device *),
@@ -3685,25 +3651,7 @@ int drbd_md_test_flag(struct drbd_backin
 static void md_sync_timer_fn(unsigned long data)
 {
 	struct drbd_device *device = (struct drbd_device *) data;
-
-	/* must not double-queue! */
-	if (list_empty(&device->md_sync_work.list))
-		drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
-				      &device->md_sync_work);
-}
-
-static int w_md_sync(struct drbd_work *w, int unused)
-{
-	struct drbd_device *device =
-		container_of(w, struct drbd_device, md_sync_work);
-
-	drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
-#ifdef DEBUG
-	drbd_warn(device, "last md_mark_dirty: %s:%u\n",
-		device->last_md_mark_dirty.func, device->last_md_mark_dirty.line);
-#endif
-	drbd_md_sync(device);
-	return 0;
+	drbd_device_post_work(device, MD_SYNC);
 }
 
 const char *cmdname(enum drbd_packet cmd)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_nl.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_nl.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_nl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_nl.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,8 @@
 
  */
 
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/drbd.h>
 #include <linux/in.h>
@@ -85,7 +87,7 @@ static void drbd_adm_send_reply(struct s
 {
 	genlmsg_end(skb, genlmsg_data(nlmsg_data(nlmsg_hdr(skb))));
 	if (genlmsg_reply(skb, info))
-		printk(KERN_ERR "drbd: error sending genl reply\n");
+		pr_err("error sending genl reply\n");
 }
 
 /* Used on a fresh "drbd_adm_prepare"d reply_skb, this cannot fail: The only
@@ -558,8 +560,10 @@ void conn_try_outdate_peer_async(struct
 }
 
 enum drbd_state_rv
-drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
+drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int force)
 {
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
 	const int max_tries = 4;
 	enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
 	struct net_conf *nc;
@@ -607,7 +611,7 @@ drbd_set_role(struct drbd_device *device
 		    device->state.disk == D_CONSISTENT && mask.pdsk == 0) {
 			D_ASSERT(device, device->state.pdsk == D_UNKNOWN);
 
-			if (conn_try_outdate_peer(first_peer_device(device)->connection)) {
+			if (conn_try_outdate_peer(connection)) {
 				val.disk = D_UP_TO_DATE;
 				mask.disk = D_MASK;
 			}
@@ -617,7 +621,7 @@ drbd_set_role(struct drbd_device *device
 		if (rv == SS_NOTHING_TO_DO)
 			goto out;
 		if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
-			if (!conn_try_outdate_peer(first_peer_device(device)->connection) && force) {
+			if (!conn_try_outdate_peer(connection) && force) {
 				drbd_warn(device, "Forced into split brain situation!\n");
 				mask.pdsk = D_MASK;
 				val.pdsk  = D_OUTDATED;
@@ -630,7 +634,7 @@ drbd_set_role(struct drbd_device *device
 			   retry at most once more in this case. */
 			int timeo;
 			rcu_read_lock();
-			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+			nc = rcu_dereference(connection->net_conf);
 			timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
 			rcu_read_unlock();
 			schedule_timeout_interruptible(timeo);
@@ -659,19 +663,17 @@ drbd_set_role(struct drbd_device *device
 	/* FIXME also wait for all pending P_BARRIER_ACK? */
 
 	if (new_role == R_SECONDARY) {
-		set_disk_ro(device->vdisk, true);
 		if (get_ldev(device)) {
 			device->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
 			put_ldev(device);
 		}
 	} else {
-		/* Called from drbd_adm_set_role only.
-		 * We are still holding the conf_update mutex. */
-		nc = first_peer_device(device)->connection->net_conf;
+		mutex_lock(&device->resource->conf_update);
+		nc = connection->net_conf;
 		if (nc)
 			nc->discard_my_data = 0; /* without copy; single bit op is atomic */
+		mutex_unlock(&device->resource->conf_update);
 
-		set_disk_ro(device->vdisk, false);
 		if (get_ldev(device)) {
 			if (((device->state.conn < C_CONNECTED ||
 			       device->state.pdsk <= D_FAILED)
@@ -689,12 +691,12 @@ drbd_set_role(struct drbd_device *device
 	if (device->state.conn >= C_WF_REPORT_PARAMS) {
 		/* if this was forced, we should consider sync */
 		if (forced)
-			drbd_send_uuids(first_peer_device(device));
-		drbd_send_current_state(first_peer_device(device));
+			drbd_send_uuids(peer_device);
+		drbd_send_current_state(peer_device);
 	}
 
 	drbd_md_sync(device);
-
+	set_disk_ro(device->vdisk, new_role == R_SECONDARY);
 	kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
 out:
 	mutex_unlock(device->state_mutex);
@@ -891,7 +893,7 @@ drbd_determine_dev_size(struct drbd_devi
 	 * still lock the act_log to not trigger ASSERTs there.
 	 */
 	drbd_suspend_io(device);
-	buffer = drbd_md_get_buffer(device); /* Lock meta-data IO */
+	buffer = drbd_md_get_buffer(device, __func__); /* Lock meta-data IO */
 	if (!buffer) {
 		drbd_resume_io(device);
 		return DS_ERROR;
@@ -971,6 +973,10 @@ drbd_determine_dev_size(struct drbd_devi
 	if (la_size_changed || md_moved || rs) {
 		u32 prev_flags;
 
+		/* We do some synchronous IO below, which may take some time.
+		 * Clear the timer, to avoid scary "timer expired!" messages,
+		 * "Superblock" is written out at least twice below, anyways. */
+		del_timer(&device->md_sync_timer);
 		drbd_al_shrink(device); /* All extents inactive. */
 
 		prev_flags = md->flags;
@@ -1116,15 +1122,16 @@ static int drbd_check_al_size(struct drb
 	return 0;
 }
 
-static void drbd_setup_queue_param(struct drbd_device *device, unsigned int max_bio_size)
+static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
+				   unsigned int max_bio_size)
 {
 	struct request_queue * const q = device->rq_queue;
 	unsigned int max_hw_sectors = max_bio_size >> 9;
 	unsigned int max_segments = 0;
 	struct request_queue *b = NULL;
 
-	if (get_ldev_if_state(device, D_ATTACHING)) {
-		b = device->ldev->backing_bdev->bd_disk->queue;
+	if (bdev) {
+		b = bdev->backing_bdev->bd_disk->queue;
 
 		max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
 		rcu_read_lock();
@@ -1169,11 +1176,10 @@ static void drbd_setup_queue_param(struc
 				 b->backing_dev_info.ra_pages);
 			q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
 		}
-		put_ldev(device);
 	}
 }
 
-void drbd_reconsider_max_bio_size(struct drbd_device *device)
+void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backing_dev *bdev)
 {
 	unsigned int now, new, local, peer;
 
@@ -1181,10 +1187,9 @@ void drbd_reconsider_max_bio_size(struct
 	local = device->local_max_bio_size; /* Eventually last known value, from volatile memory */
 	peer = device->peer_max_bio_size; /* Eventually last known value, from meta data */
 
-	if (get_ldev_if_state(device, D_ATTACHING)) {
-		local = queue_max_hw_sectors(device->ldev->backing_bdev->bd_disk->queue) << 9;
+	if (bdev) {
+		local = queue_max_hw_sectors(bdev->backing_bdev->bd_disk->queue) << 9;
 		device->local_max_bio_size = local;
-		put_ldev(device);
 	}
 	local = min(local, DRBD_MAX_BIO_SIZE);
 
@@ -1217,7 +1222,7 @@ void drbd_reconsider_max_bio_size(struct
 	if (new != now)
 		drbd_info(device, "max BIO size = %u\n", new);
 
-	drbd_setup_queue_param(device, new);
+	drbd_setup_queue_param(device, bdev, new);
 }
 
 /* Starts the worker thread */
@@ -1299,6 +1304,13 @@ static unsigned int drbd_al_extents_max(
 	return (al_size_4k - 1) * AL_CONTEXT_PER_TRANSACTION;
 }
 
+static bool write_ordering_changed(struct disk_conf *a, struct disk_conf *b)
+{
+	return	a->disk_barrier != b->disk_barrier ||
+		a->disk_flushes != b->disk_flushes ||
+		a->disk_drain != b->disk_drain;
+}
+
 int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 {
 	struct drbd_config_context adm_ctx;
@@ -1405,7 +1417,8 @@ int drbd_adm_disk_opts(struct sk_buff *s
 	else
 		set_bit(MD_NO_FUA, &device->flags);
 
-	drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
+	if (write_ordering_changed(old_disk_conf, new_disk_conf))
+		drbd_bump_write_ordering(device->resource, NULL, WO_bdev_flush);
 
 	drbd_md_sync(device);
 
@@ -1440,6 +1453,8 @@ int drbd_adm_attach(struct sk_buff *skb,
 {
 	struct drbd_config_context adm_ctx;
 	struct drbd_device *device;
+	struct drbd_peer_device *peer_device;
+	struct drbd_connection *connection;
 	int err;
 	enum drbd_ret_code retcode;
 	enum determine_dev_size dd;
@@ -1462,7 +1477,9 @@ int drbd_adm_attach(struct sk_buff *skb,
 
 	device = adm_ctx.device;
 	mutex_lock(&adm_ctx.resource->adm_mutex);
-	conn_reconfig_start(first_peer_device(device)->connection);
+	peer_device = first_peer_device(device);
+	connection = peer_device ? peer_device->connection : NULL;
+	conn_reconfig_start(connection);
 
 	/* if you want to reconfigure, please tear down first */
 	if (device->state.disk > D_DISKLESS) {
@@ -1473,7 +1490,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 	 * drbd_ldev_destroy is done already, we may end up here very fast,
 	 * e.g. if someone calls attach from the on-io-error handler,
 	 * to realize a "hot spare" feature (not that I'd recommend that) */
-	wait_event(device->misc_wait, !atomic_read(&device->local_cnt));
+	wait_event(device->misc_wait, !test_bit(GOING_DISKLESS, &device->flags));
 
 	/* make sure there is no leftover from previous force-detach attempts */
 	clear_bit(FORCE_DETACH, &device->flags);
@@ -1529,7 +1546,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 		goto fail;
 
 	rcu_read_lock();
-	nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+	nc = rcu_dereference(connection->net_conf);
 	if (nc) {
 		if (new_disk_conf->fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) {
 			rcu_read_unlock();
@@ -1649,7 +1666,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 	 */
 	wait_event(device->misc_wait, !atomic_read(&device->ap_pending_cnt) || drbd_suspended(device));
 	/* and for any other previously queued work */
-	drbd_flush_workqueue(&first_peer_device(device)->connection->sender_work);
+	drbd_flush_workqueue(&connection->sender_work);
 
 	rv = _drbd_request_state(device, NS(disk, D_ATTACHING), CS_VERBOSE);
 	retcode = rv;  /* FIXME: Type mismatch. */
@@ -1710,7 +1727,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 	new_disk_conf = NULL;
 	new_plan = NULL;
 
-	drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
+	drbd_bump_write_ordering(device->resource, device->ldev, WO_bdev_flush);
 
 	if (drbd_md_test_flag(device->ldev, MDF_CRASHED_PRIMARY))
 		set_bit(CRASHED_PRIMARY, &device->flags);
@@ -1726,7 +1743,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 	device->read_cnt = 0;
 	device->writ_cnt = 0;
 
-	drbd_reconsider_max_bio_size(device);
+	drbd_reconsider_max_bio_size(device, device->ldev);
 
 	/* If I am currently not R_PRIMARY,
 	 * but meta data primary indicator is set,
@@ -1845,7 +1862,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 
 	kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
 	put_ldev(device);
-	conn_reconfig_done(first_peer_device(device)->connection);
+	conn_reconfig_done(connection);
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
 	drbd_adm_finish(&adm_ctx, info, retcode);
 	return 0;
@@ -1856,7 +1873,7 @@ int drbd_adm_attach(struct sk_buff *skb,
 	drbd_force_state(device, NS(disk, D_DISKLESS));
 	drbd_md_sync(device);
  fail:
-	conn_reconfig_done(first_peer_device(device)->connection);
+	conn_reconfig_done(connection);
 	if (nbc) {
 		if (nbc->backing_bdev)
 			blkdev_put(nbc->backing_bdev,
@@ -1888,7 +1905,7 @@ static int adm_detach(struct drbd_device
 	}
 
 	drbd_suspend_io(device); /* so no-one is stuck in drbd_al_begin_io */
-	drbd_md_get_buffer(device); /* make sure there is no in-flight meta-data IO */
+	drbd_md_get_buffer(device, __func__); /* make sure there is no in-flight meta-data IO */
 	retcode = drbd_request_state(device, NS(disk, D_FAILED));
 	drbd_md_put_buffer(device);
 	/* D_FAILED will transition to DISKLESS. */
@@ -2654,8 +2671,13 @@ int drbd_adm_invalidate(struct sk_buff *
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mutex_lock(&adm_ctx.resource->adm_mutex);
 	device = adm_ctx.device;
+	if (!get_ldev(device)) {
+		retcode = ERR_NO_DISK;
+		goto out;
+	}
+
+	mutex_lock(&adm_ctx.resource->adm_mutex);
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
@@ -2679,6 +2701,7 @@ int drbd_adm_invalidate(struct sk_buff *
 		retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_T));
 	drbd_resume_io(device);
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
+	put_ldev(device);
 out:
 	drbd_adm_finish(&adm_ctx, info, retcode);
 	return 0;
@@ -2704,7 +2727,7 @@ out:
 	return 0;
 }
 
-static int drbd_bmio_set_susp_al(struct drbd_device *device)
+static int drbd_bmio_set_susp_al(struct drbd_device *device) __must_hold(local)
 {
 	int rv;
 
@@ -2725,8 +2748,13 @@ int drbd_adm_invalidate_peer(struct sk_b
 	if (retcode != NO_ERROR)
 		goto out;
 
-	mutex_lock(&adm_ctx.resource->adm_mutex);
 	device = adm_ctx.device;
+	if (!get_ldev(device)) {
+		retcode = ERR_NO_DISK;
+		goto out;
+	}
+
+	mutex_lock(&adm_ctx.resource->adm_mutex);
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
@@ -2753,6 +2781,7 @@ int drbd_adm_invalidate_peer(struct sk_b
 		retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_S));
 	drbd_resume_io(device);
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
+	put_ldev(device);
 out:
 	drbd_adm_finish(&adm_ctx, info, retcode);
 	return 0;
@@ -2892,7 +2921,7 @@ static struct drbd_connection *the_only_
 	return list_first_entry(&resource->connections, struct drbd_connection, connections);
 }
 
-int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
+static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
 		const struct sib_info *sib)
 {
 	struct drbd_resource *resource = device->resource;
@@ -3622,13 +3651,6 @@ void drbd_bcast_event(struct drbd_device
 	unsigned seq;
 	int err = -ENOMEM;
 
-	if (sib->sib_reason == SIB_SYNC_PROGRESS) {
-		if (time_after(jiffies, device->rs_last_bcast + HZ))
-			device->rs_last_bcast = jiffies;
-		else
-			return;
-	}
-
 	seq = atomic_inc_return(&drbd_genl_seq);
 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_NOIO);
 	if (!msg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_proc.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_proc.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,20 +60,65 @@ static void seq_printf_with_thousands_gr
 		seq_printf(seq, "%ld", v);
 }
 
+static void drbd_get_syncer_progress(struct drbd_device *device,
+		union drbd_dev_state state, unsigned long *rs_total,
+		unsigned long *bits_left, unsigned int *per_mil_done)
+{
+	/* this is to break it at compile time when we change that, in case we
+	 * want to support more than (1<<32) bits on a 32bit arch. */
+	typecheck(unsigned long, device->rs_total);
+	*rs_total = device->rs_total;
+
+	/* note: both rs_total and rs_left are in bits, i.e. in
+	 * units of BM_BLOCK_SIZE.
+	 * for the percentage, we don't care. */
+
+	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
+		*bits_left = device->ov_left;
+	else
+		*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
+	/* >> 10 to prevent overflow,
+	 * +1 to prevent division by zero */
+	if (*bits_left > *rs_total) {
+		/* D'oh. Maybe a logic bug somewhere.  More likely just a race
+		 * between state change and reset of rs_total.
+		 */
+		*bits_left = *rs_total;
+		*per_mil_done = *rs_total ? 0 : 1000;
+	} else {
+		/* Make sure the division happens in long context.
+		 * We allow up to one petabyte storage right now,
+		 * at a granularity of 4k per bit that is 2**38 bits.
+		 * After shift right and multiplication by 1000,
+		 * this should still fit easily into a 32bit long,
+		 * so we don't need a 64bit division on 32bit arch.
+		 * Note: currently we don't support such large bitmaps on 32bit
+		 * arch anyways, but no harm done to be prepared for it here.
+		 */
+		unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
+		unsigned long left = *bits_left >> shift;
+		unsigned long total = 1UL + (*rs_total >> shift);
+		unsigned long tmp = 1000UL - left * 1000UL/total;
+		*per_mil_done = tmp;
+	}
+}
+
+
 /*lge
  * progress bars shamelessly adapted from driver/md/md.c
  * output looks like
  *	[=====>..............] 33.5% (23456/123456)
  *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
  */
-static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq)
+static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
+		union drbd_dev_state state)
 {
-	unsigned long db, dt, dbdt, rt, rs_left;
+	unsigned long db, dt, dbdt, rt, rs_total, rs_left;
 	unsigned int res;
 	int i, x, y;
 	int stalled = 0;
 
-	drbd_get_syncer_progress(device, &rs_left, &res);
+	drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
 
 	x = res/50;
 	y = 20-x;
@@ -85,21 +130,21 @@ static void drbd_syncer_progress(struct
 		seq_printf(seq, ".");
 	seq_printf(seq, "] ");
 
-	if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
+	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
 		seq_printf(seq, "verified:");
 	else
 		seq_printf(seq, "sync'ed:");
 	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
 
 	/* if more than a few GB, display in MB */
-	if (device->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
+	if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
 		seq_printf(seq, "(%lu/%lu)M",
 			    (unsigned long) Bit2KB(rs_left >> 10),
-			    (unsigned long) Bit2KB(device->rs_total >> 10));
+			    (unsigned long) Bit2KB(rs_total >> 10));
 	else
 		seq_printf(seq, "(%lu/%lu)K\n\t",
 			    (unsigned long) Bit2KB(rs_left),
-			    (unsigned long) Bit2KB(device->rs_total));
+			    (unsigned long) Bit2KB(rs_total));
 
 	/* see drivers/md/md.c
 	 * We do not want to overflow, so the order of operands and
@@ -150,13 +195,13 @@ static void drbd_syncer_progress(struct
 	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
 	if (dt == 0)
 		dt = 1;
-	db = device->rs_total - rs_left;
+	db = rs_total - rs_left;
 	dbdt = Bit2KB(db/dt);
 	seq_printf_with_thousands_grouping(seq, dbdt);
 	seq_printf(seq, ")");
 
-	if (device->state.conn == C_SYNC_TARGET ||
-	    device->state.conn == C_VERIFY_S) {
+	if (state.conn == C_SYNC_TARGET ||
+	    state.conn == C_VERIFY_S) {
 		seq_printf(seq, " want: ");
 		seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
 	}
@@ -168,8 +213,8 @@ static void drbd_syncer_progress(struct
 		unsigned long bm_bits = drbd_bm_bits(device);
 		unsigned long bit_pos;
 		unsigned long long stop_sector = 0;
-		if (device->state.conn == C_VERIFY_S ||
-		    device->state.conn == C_VERIFY_T) {
+		if (state.conn == C_VERIFY_S ||
+		    state.conn == C_VERIFY_T) {
 			bit_pos = bm_bits - device->ov_left;
 			if (verify_can_do_stop_sector(device))
 				stop_sector = device->ov_stop_sector;
@@ -188,22 +233,13 @@ static void drbd_syncer_progress(struct
 	}
 }
 
-static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
-{
-	struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
-
-	seq_printf(seq, "%5d %s %s\n", bme->rs_left,
-		   bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
-		   bme->flags & BME_LOCKED ? "LOCKED" : "------"
-		   );
-}
-
 static int drbd_seq_show(struct seq_file *seq, void *v)
 {
 	int i, prev_i = -1;
 	const char *sn;
 	struct drbd_device *device;
 	struct net_conf *nc;
+	union drbd_dev_state state;
 	char wp;
 
 	static char write_ordering_chars[] = {
@@ -241,11 +277,12 @@ static int drbd_seq_show(struct seq_file
 			seq_printf(seq, "\n");
 		prev_i = i;
 
-		sn = drbd_conn_str(device->state.conn);
+		state = device->state;
+		sn = drbd_conn_str(state.conn);
 
-		if (device->state.conn == C_STANDALONE &&
-		    device->state.disk == D_DISKLESS &&
-		    device->state.role == R_SECONDARY) {
+		if (state.conn == C_STANDALONE &&
+		    state.disk == D_DISKLESS &&
+		    state.role == R_SECONDARY) {
 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 		} else {
 			/* reset device->congestion_reason */
@@ -258,15 +295,15 @@ static int drbd_seq_show(struct seq_file
 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
 			   i, sn,
-			   drbd_role_str(device->state.role),
-			   drbd_role_str(device->state.peer),
-			   drbd_disk_str(device->state.disk),
-			   drbd_disk_str(device->state.pdsk),
+			   drbd_role_str(state.role),
+			   drbd_role_str(state.peer),
+			   drbd_disk_str(state.disk),
+			   drbd_disk_str(state.pdsk),
 			   wp,
 			   drbd_suspended(device) ? 's' : 'r',
-			   device->state.aftr_isp ? 'a' : '-',
-			   device->state.peer_isp ? 'p' : '-',
-			   device->state.user_isp ? 'u' : '-',
+			   state.aftr_isp ? 'a' : '-',
+			   state.peer_isp ? 'p' : '-',
+			   state.user_isp ? 'u' : '-',
 			   device->congestion_reason ?: '-',
 			   test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
 			   device->send_cnt/2,
@@ -281,17 +318,17 @@ static int drbd_seq_show(struct seq_file
 			   atomic_read(&device->unacked_cnt),
 			   atomic_read(&device->ap_bio_cnt),
 			   first_peer_device(device)->connection->epochs,
-			   write_ordering_chars[first_peer_device(device)->connection->write_ordering]
+			   write_ordering_chars[device->resource->write_ordering]
 			);
 			seq_printf(seq, " oos:%llu\n",
 				   Bit2KB((unsigned long long)
 					   drbd_bm_total_weight(device)));
 		}
-		if (device->state.conn == C_SYNC_SOURCE ||
-		    device->state.conn == C_SYNC_TARGET ||
-		    device->state.conn == C_VERIFY_S ||
-		    device->state.conn == C_VERIFY_T)
-			drbd_syncer_progress(device, seq);
+		if (state.conn == C_SYNC_SOURCE ||
+		    state.conn == C_SYNC_TARGET ||
+		    state.conn == C_VERIFY_S ||
+		    state.conn == C_VERIFY_T)
+			drbd_syncer_progress(device, seq, state);
 
 		if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
 			lc_seq_printf_stats(seq, device->resync);
@@ -299,12 +336,8 @@ static int drbd_seq_show(struct seq_file
 			put_ldev(device);
 		}
 
-		if (proc_details >= 2) {
-			if (device->resync) {
-				lc_seq_dump_details(seq, device->resync, "rs_left",
-					resync_dump_detail);
-			}
-		}
+		if (proc_details >= 2)
+			seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
 	}
 	rcu_read_unlock();
 
@@ -316,7 +349,7 @@ static int drbd_proc_open(struct inode *
 	int err;
 
 	if (try_module_get(THIS_MODULE)) {
-		err = single_open(file, drbd_seq_show, PDE_DATA(inode));
+		err = single_open(file, drbd_seq_show, NULL);
 		if (err)
 			module_put(THIS_MODULE);
 		return err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_receiver.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_receiver.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_receiver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_receiver.c	2014-09-28 17:29:07.000000000 -0400
@@ -362,17 +362,14 @@ drbd_alloc_peer_req(struct drbd_peer_dev
 			goto fail;
 	}
 
+	memset(peer_req, 0, sizeof(*peer_req));
+	INIT_LIST_HEAD(&peer_req->w.list);
 	drbd_clear_interval(&peer_req->i);
 	peer_req->i.size = data_size;
 	peer_req->i.sector = sector;
-	peer_req->i.local = false;
-	peer_req->i.waiting = false;
-
-	peer_req->epoch = NULL;
+	peer_req->submit_jif = jiffies;
 	peer_req->peer_device = peer_device;
 	peer_req->pages = page;
-	atomic_set(&peer_req->pending_bios, 0);
-	peer_req->flags = 0;
 	/*
 	 * The block_id is opaque to the receiver.  It is not endianness
 	 * converted, and sent back to the sender unchanged.
@@ -389,11 +386,16 @@ drbd_alloc_peer_req(struct drbd_peer_dev
 void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req,
 		       int is_net)
 {
+	might_sleep();
 	if (peer_req->flags & EE_HAS_DIGEST)
 		kfree(peer_req->digest);
 	drbd_free_pages(device, peer_req->pages, is_net);
 	D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0);
 	D_ASSERT(device, drbd_interval_empty(&peer_req->i));
+	if (!expect(!(peer_req->flags & EE_CALL_AL_COMPLETE_IO))) {
+		peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
+		drbd_al_complete_io(device, &peer_req->i);
+	}
 	mempool_free(peer_req, drbd_ee_mempool);
 }
 
@@ -791,8 +793,18 @@ static int receive_first_packet(struct d
 {
 	unsigned int header_size = drbd_header_size(connection);
 	struct packet_info pi;
+	struct net_conf *nc;
 	int err;
 
+	rcu_read_lock();
+	nc = rcu_dereference(connection->net_conf);
+	if (!nc) {
+		rcu_read_unlock();
+		return -EIO;
+	}
+	sock->sk->sk_rcvtimeo = nc->ping_timeo * 4 * HZ / 10;
+	rcu_read_unlock();
+
 	err = drbd_recv_short(sock, connection->data.rbuf, header_size, 0);
 	if (err != header_size) {
 		if (err >= 0)
@@ -809,7 +821,7 @@ static int receive_first_packet(struct d
  * drbd_socket_okay() - Free the socket if its connection is not okay
  * @sock:	pointer to the pointer to the socket.
  */
-static int drbd_socket_okay(struct socket **sock)
+static bool drbd_socket_okay(struct socket **sock)
 {
 	int rr;
 	char tb[4];
@@ -827,6 +839,30 @@ static int drbd_socket_okay(struct socke
 		return false;
 	}
 }
+
+static bool connection_established(struct drbd_connection *connection,
+				   struct socket **sock1,
+				   struct socket **sock2)
+{
+	struct net_conf *nc;
+	int timeout;
+	bool ok;
+
+	if (!*sock1 || !*sock2)
+		return false;
+
+	rcu_read_lock();
+	nc = rcu_dereference(connection->net_conf);
+	timeout = (nc->sock_check_timeo ?: nc->ping_timeo) * HZ / 10;
+	rcu_read_unlock();
+	schedule_timeout_interruptible(timeout);
+
+	ok = drbd_socket_okay(sock1);
+	ok = drbd_socket_okay(sock2) && ok;
+
+	return ok;
+}
+
 /* Gets called if a connection is established, or if a new minor gets created
    in a connection */
 int drbd_connected(struct drbd_peer_device *peer_device)
@@ -868,8 +904,8 @@ static int conn_connect(struct drbd_conn
 	struct drbd_socket sock, msock;
 	struct drbd_peer_device *peer_device;
 	struct net_conf *nc;
-	int vnr, timeout, h, ok;
-	bool discard_my_data;
+	int vnr, timeout, h;
+	bool discard_my_data, ok;
 	enum drbd_state_rv rv;
 	struct accept_wait_data ad = {
 		.connection = connection,
@@ -913,17 +949,8 @@ static int conn_connect(struct drbd_conn
 			}
 		}
 
-		if (sock.socket && msock.socket) {
-			rcu_read_lock();
-			nc = rcu_dereference(connection->net_conf);
-			timeout = nc->ping_timeo * HZ / 10;
-			rcu_read_unlock();
-			schedule_timeout_interruptible(timeout);
-			ok = drbd_socket_okay(&sock.socket);
-			ok = drbd_socket_okay(&msock.socket) && ok;
-			if (ok)
-				break;
-		}
+		if (connection_established(connection, &sock.socket, &msock.socket))
+			break;
 
 retry:
 		s = drbd_wait_for_connect(connection, &ad);
@@ -969,8 +996,7 @@ randomize:
 				goto out_release_sockets;
 		}
 
-		ok = drbd_socket_okay(&sock.socket);
-		ok = drbd_socket_okay(&msock.socket) && ok;
+		ok = connection_established(connection, &sock.socket, &msock.socket);
 	} while (!ok);
 
 	if (ad.s_listen)
@@ -1151,7 +1177,7 @@ static void drbd_flush(struct drbd_conne
 	struct drbd_peer_device *peer_device;
 	int vnr;
 
-	if (connection->write_ordering >= WO_bdev_flush) {
+	if (connection->resource->write_ordering >= WO_bdev_flush) {
 		rcu_read_lock();
 		idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
 			struct drbd_device *device = peer_device->device;
@@ -1161,14 +1187,22 @@ static void drbd_flush(struct drbd_conne
 			kref_get(&device->kref);
 			rcu_read_unlock();
 
+			/* Right now, we have only this one synchronous code path
+			 * for flushes between request epochs.
+			 * We may want to make those asynchronous,
+			 * or at least parallelize the flushes to the volume devices.
+			 */
+			device->flush_jif = jiffies;
+			set_bit(FLUSH_PENDING, &device->flags);
 			rv = blkdev_issue_flush(device->ldev->backing_bdev,
 					GFP_NOIO, NULL);
+			clear_bit(FLUSH_PENDING, &device->flags);
 			if (rv) {
 				drbd_info(device, "local disk flush failed with status %d\n", rv);
 				/* would rather check on EOPNOTSUPP, but that is not reliable.
 				 * don't try again for ANY return value != 0
 				 * if (rv == -EOPNOTSUPP) */
-				drbd_bump_write_ordering(connection, WO_drain_io);
+				drbd_bump_write_ordering(connection->resource, NULL, WO_drain_io);
 			}
 			put_ldev(device);
 			kref_put(&device->kref, drbd_destroy_device);
@@ -1257,15 +1291,30 @@ static enum finish_epoch drbd_may_finish
 	return rv;
 }
 
+static enum write_ordering_e
+max_allowed_wo(struct drbd_backing_dev *bdev, enum write_ordering_e wo)
+{
+	struct disk_conf *dc;
+
+	dc = rcu_dereference(bdev->disk_conf);
+
+	if (wo == WO_bdev_flush && !dc->disk_flushes)
+		wo = WO_drain_io;
+	if (wo == WO_drain_io && !dc->disk_drain)
+		wo = WO_none;
+
+	return wo;
+}
+
 /**
  * drbd_bump_write_ordering() - Fall back to an other write ordering method
  * @connection:	DRBD connection.
  * @wo:		Write ordering method to try.
  */
-void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo)
+void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
+			      enum write_ordering_e wo)
 {
-	struct disk_conf *dc;
-	struct drbd_peer_device *peer_device;
+	struct drbd_device *device;
 	enum write_ordering_e pwo;
 	int vnr;
 	static char *write_ordering_str[] = {
@@ -1274,26 +1323,27 @@ void drbd_bump_write_ordering(struct drb
 		[WO_bdev_flush] = "flush",
 	};
 
-	pwo = connection->write_ordering;
-	wo = min(pwo, wo);
+	pwo = resource->write_ordering;
+	if (wo != WO_bdev_flush)
+		wo = min(pwo, wo);
 	rcu_read_lock();
-	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
-		struct drbd_device *device = peer_device->device;
+	idr_for_each_entry(&resource->devices, device, vnr) {
+		if (get_ldev(device)) {
+			wo = max_allowed_wo(device->ldev, wo);
+			if (device->ldev == bdev)
+				bdev = NULL;
+			put_ldev(device);
+		}
+	}
 
-		if (!get_ldev_if_state(device, D_ATTACHING))
-			continue;
-		dc = rcu_dereference(device->ldev->disk_conf);
+	if (bdev)
+		wo = max_allowed_wo(bdev, wo);
 
-		if (wo == WO_bdev_flush && !dc->disk_flushes)
-			wo = WO_drain_io;
-		if (wo == WO_drain_io && !dc->disk_drain)
-			wo = WO_none;
-		put_ldev(device);
-	}
 	rcu_read_unlock();
-	connection->write_ordering = wo;
-	if (pwo != connection->write_ordering || wo == WO_bdev_flush)
-		drbd_info(connection, "Method to ensure write ordering: %s\n", write_ordering_str[connection->write_ordering]);
+
+	resource->write_ordering = wo;
+	if (pwo != resource->write_ordering || wo == WO_bdev_flush)
+		drbd_info(resource, "Method to ensure write ordering: %s\n", write_ordering_str[resource->write_ordering]);
 }
 
 /**
@@ -1330,6 +1380,13 @@ int drbd_submit_peer_request(struct drbd
 		/* wait for all pending IO completions, before we start
 		 * zeroing things out. */
 		conn_wait_active_ee_empty(first_peer_device(device)->connection);
+		/* add it to the active list now,
+		 * so we can find it to present it in debugfs */
+		peer_req->submit_jif = jiffies;
+		peer_req->flags |= EE_SUBMITTED;
+		spin_lock_irq(&device->resource->req_lock);
+		list_add_tail(&peer_req->w.list, &device->active_ee);
+		spin_unlock_irq(&device->resource->req_lock);
 		if (blkdev_issue_zeroout(device->ldev->backing_bdev,
 			sector, ds >> 9, GFP_NOIO))
 			peer_req->flags |= EE_WAS_ERROR;
@@ -1398,6 +1455,9 @@ submit:
 	D_ASSERT(device, page == NULL);
 
 	atomic_set(&peer_req->pending_bios, n_bios);
+	/* for debugfs: update timestamp, mark as submitted */
+	peer_req->submit_jif = jiffies;
+	peer_req->flags |= EE_SUBMITTED;
 	do {
 		bio = bios;
 		bios = bios->bi_next;
@@ -1471,7 +1531,7 @@ static int receive_Barrier(struct drbd_c
 	 * R_PRIMARY crashes now.
 	 * Therefore we must send the barrier_ack after the barrier request was
 	 * completed. */
-	switch (connection->write_ordering) {
+	switch (connection->resource->write_ordering) {
 	case WO_none:
 		if (rv == FE_RECYCLED)
 			return 0;
@@ -1498,7 +1558,8 @@ static int receive_Barrier(struct drbd_c
 
 		return 0;
 	default:
-		drbd_err(connection, "Strangeness in connection->write_ordering %d\n", connection->write_ordering);
+		drbd_err(connection, "Strangeness in connection->write_ordering %d\n",
+			 connection->resource->write_ordering);
 		return -EIO;
 	}
 
@@ -1531,7 +1592,7 @@ read_in_block(struct drbd_peer_device *p
 	struct drbd_peer_request *peer_req;
 	struct page *page;
 	int dgs, ds, err;
-	int data_size = pi->size;
+	unsigned int data_size = pi->size;
 	void *dig_in = peer_device->connection->int_dig_in;
 	void *dig_vv = peer_device->connection->int_dig_vv;
 	unsigned long *data;
@@ -1578,6 +1639,7 @@ read_in_block(struct drbd_peer_device *p
 	if (!peer_req)
 		return NULL;
 
+	peer_req->flags |= EE_WRITE;
 	if (trim)
 		return peer_req;
 
@@ -1734,9 +1796,10 @@ static int recv_resync_read(struct drbd_
 	 * respective _drbd_clear_done_ee */
 
 	peer_req->w.cb = e_end_resync_block;
+	peer_req->submit_jif = jiffies;
 
 	spin_lock_irq(&device->resource->req_lock);
-	list_add(&peer_req->w.list, &device->sync_ee);
+	list_add_tail(&peer_req->w.list, &device->sync_ee);
 	spin_unlock_irq(&device->resource->req_lock);
 
 	atomic_add(pi->size >> 9, &device->rs_sect_ev);
@@ -1889,6 +1952,7 @@ static int e_end_block(struct drbd_work
 		}
 		dec_unacked(device);
 	}
+
 	/* we delete from the conflict detection hash _after_ we sent out the
 	 * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right.  */
 	if (peer_req->flags & EE_IN_INTERVAL_TREE) {
@@ -2115,6 +2179,8 @@ static int handle_write_conflicts(struct
 	drbd_for_each_overlap(i, &device->write_requests, sector, size) {
 		if (i == &peer_req->i)
 			continue;
+		if (i->completed)
+			continue;
 
 		if (!i->local) {
 			/*
@@ -2147,7 +2213,6 @@ static int handle_write_conflicts(struct
 					  (unsigned long long)sector, size,
 					  superseded ? "local" : "remote");
 
-			inc_unacked(device);
 			peer_req->w.cb = superseded ? e_send_superseded :
 						   e_send_retry_write;
 			list_add_tail(&peer_req->w.list, &device->done_ee);
@@ -2206,6 +2271,7 @@ static int receive_Data(struct drbd_conn
 {
 	struct drbd_peer_device *peer_device;
 	struct drbd_device *device;
+	struct net_conf *nc;
 	sector_t sector;
 	struct drbd_peer_request *peer_req;
 	struct p_data *p = pi->data;
@@ -2245,6 +2311,8 @@ static int receive_Data(struct drbd_conn
 	}
 
 	peer_req->w.cb = e_end_block;
+	peer_req->submit_jif = jiffies;
+	peer_req->flags |= EE_APPLICATION;
 
 	dp_flags = be32_to_cpu(p->dp_flags);
 	rw |= wire_flags_to_bio(dp_flags);
@@ -2271,9 +2339,36 @@ static int receive_Data(struct drbd_conn
 	spin_unlock(&connection->epoch_lock);
 
 	rcu_read_lock();
-	tp = rcu_dereference(peer_device->connection->net_conf)->two_primaries;
+	nc = rcu_dereference(peer_device->connection->net_conf);
+	tp = nc->two_primaries;
+	if (peer_device->connection->agreed_pro_version < 100) {
+		switch (nc->wire_protocol) {
+		case DRBD_PROT_C:
+			dp_flags |= DP_SEND_WRITE_ACK;
+			break;
+		case DRBD_PROT_B:
+			dp_flags |= DP_SEND_RECEIVE_ACK;
+			break;
+		}
+	}
 	rcu_read_unlock();
+
+	if (dp_flags & DP_SEND_WRITE_ACK) {
+		peer_req->flags |= EE_SEND_WRITE_ACK;
+		inc_unacked(device);
+		/* corresponding dec_unacked() in e_end_block()
+		 * respective _drbd_clear_done_ee */
+	}
+
+	if (dp_flags & DP_SEND_RECEIVE_ACK) {
+		/* I really don't like it that the receiver thread
+		 * sends on the msock, but anyways */
+		drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
+	}
+
 	if (tp) {
+		/* two primaries implies protocol C */
+		D_ASSERT(device, dp_flags & DP_SEND_WRITE_ACK);
 		peer_req->flags |= EE_IN_INTERVAL_TREE;
 		err = wait_for_and_update_peer_seq(peer_device, peer_seq);
 		if (err)
@@ -2297,44 +2392,18 @@ static int receive_Data(struct drbd_conn
 	 * active_ee to become empty in drbd_submit_peer_request();
 	 * better not add ourselves here. */
 	if ((peer_req->flags & EE_IS_TRIM_USE_ZEROOUT) == 0)
-		list_add(&peer_req->w.list, &device->active_ee);
+		list_add_tail(&peer_req->w.list, &device->active_ee);
 	spin_unlock_irq(&device->resource->req_lock);
 
 	if (device->state.conn == C_SYNC_TARGET)
 		wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req));
 
-	if (peer_device->connection->agreed_pro_version < 100) {
-		rcu_read_lock();
-		switch (rcu_dereference(peer_device->connection->net_conf)->wire_protocol) {
-		case DRBD_PROT_C:
-			dp_flags |= DP_SEND_WRITE_ACK;
-			break;
-		case DRBD_PROT_B:
-			dp_flags |= DP_SEND_RECEIVE_ACK;
-			break;
-		}
-		rcu_read_unlock();
-	}
-
-	if (dp_flags & DP_SEND_WRITE_ACK) {
-		peer_req->flags |= EE_SEND_WRITE_ACK;
-		inc_unacked(device);
-		/* corresponding dec_unacked() in e_end_block()
-		 * respective _drbd_clear_done_ee */
-	}
-
-	if (dp_flags & DP_SEND_RECEIVE_ACK) {
-		/* I really don't like it that the receiver thread
-		 * sends on the msock, but anyways */
-		drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
-	}
-
 	if (device->state.pdsk < D_INCONSISTENT) {
 		/* In case we have the only disk of the cluster, */
 		drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size);
-		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
 		peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
-		drbd_al_begin_io(device, &peer_req->i, true);
+		drbd_al_begin_io(device, &peer_req->i);
+		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
 	}
 
 	err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR);
@@ -2347,8 +2416,10 @@ static int receive_Data(struct drbd_conn
 	list_del(&peer_req->w.list);
 	drbd_remove_epoch_entry_interval(device, peer_req);
 	spin_unlock_irq(&device->resource->req_lock);
-	if (peer_req->flags & EE_CALL_AL_COMPLETE_IO)
+	if (peer_req->flags & EE_CALL_AL_COMPLETE_IO) {
+		peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
 		drbd_al_complete_io(device, &peer_req->i);
+	}
 
 out_interrupted:
 	drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT + EV_CLEANUP);
@@ -2368,13 +2439,14 @@ out_interrupted:
  * The current sync rate used here uses only the most recent two step marks,
  * to have a short time average so we can react faster.
  */
-bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector)
+bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
+		bool throttle_if_app_is_waiting)
 {
 	struct lc_element *tmp;
-	bool throttle = true;
+	bool throttle = drbd_rs_c_min_rate_throttle(device);
 
-	if (!drbd_rs_c_min_rate_throttle(device))
-		return false;
+	if (!throttle || throttle_if_app_is_waiting)
+		return throttle;
 
 	spin_lock_irq(&device->al_lock);
 	tmp = lc_find(device->resync, BM_SECT_TO_EXT(sector));
@@ -2382,7 +2454,8 @@ bool drbd_rs_should_slow_down(struct drb
 		struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce);
 		if (test_bit(BME_PRIORITY, &bm_ext->flags))
 			throttle = false;
-		/* Do not slow down if app IO is already waiting for this extent */
+		/* Do not slow down if app IO is already waiting for this extent,
+		 * and our progress is necessary for application IO to complete. */
 	}
 	spin_unlock_irq(&device->al_lock);
 
@@ -2407,7 +2480,9 @@ bool drbd_rs_c_min_rate_throttle(struct
 	curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
 		      (int)part_stat_read(&disk->part0, sectors[1]) -
 			atomic_read(&device->rs_sect_ev);
-	if (!device->rs_last_events || curr_events - device->rs_last_events > 64) {
+
+	if (atomic_read(&device->ap_actlog_cnt)
+	    || !device->rs_last_events || curr_events - device->rs_last_events > 64) {
 		unsigned long rs_left;
 		int i;
 
@@ -2508,6 +2583,7 @@ static int receive_DataRequest(struct dr
 		peer_req->w.cb = w_e_end_data_req;
 		fault_type = DRBD_FAULT_DT_RD;
 		/* application IO, don't drbd_rs_begin_io */
+		peer_req->flags |= EE_APPLICATION;
 		goto submit;
 
 	case P_RS_DATA_REQUEST:
@@ -2538,6 +2614,8 @@ static int receive_DataRequest(struct dr
 			peer_req->w.cb = w_e_end_csum_rs_req;
 			/* used in the sector offset progress display */
 			device->bm_resync_fo = BM_SECT_TO_BIT(sector);
+			/* remember to report stats in drbd_resync_finished */
+			device->use_csums = true;
 		} else if (pi->cmd == P_OV_REPLY) {
 			/* track progress, we may need to throttle */
 			atomic_add(size >> 9, &device->rs_sect_in);
@@ -2595,8 +2673,20 @@ static int receive_DataRequest(struct dr
 	 * we would also throttle its application reads.
 	 * In that case, throttling is done on the SyncTarget only.
 	 */
-	if (device->state.peer != R_PRIMARY && drbd_rs_should_slow_down(device, sector))
+
+	/* Even though this may be a resync request, we do add to "read_ee";
+	 * "sync_ee" is only used for resync WRITEs.
+	 * Add to list early, so debugfs can find this request
+	 * even if we have to sleep below. */
+	spin_lock_irq(&device->resource->req_lock);
+	list_add_tail(&peer_req->w.list, &device->read_ee);
+	spin_unlock_irq(&device->resource->req_lock);
+
+	update_receiver_timing_details(connection, drbd_rs_should_slow_down);
+	if (device->state.peer != R_PRIMARY
+	&& drbd_rs_should_slow_down(device, sector, false))
 		schedule_timeout_uninterruptible(HZ/10);
+	update_receiver_timing_details(connection, drbd_rs_begin_io);
 	if (drbd_rs_begin_io(device, sector))
 		goto out_free_e;
 
@@ -2604,22 +2694,20 @@ submit_for_resync:
 	atomic_add(size >> 9, &device->rs_sect_ev);
 
 submit:
+	update_receiver_timing_details(connection, drbd_submit_peer_request);
 	inc_unacked(device);
-	spin_lock_irq(&device->resource->req_lock);
-	list_add_tail(&peer_req->w.list, &device->read_ee);
-	spin_unlock_irq(&device->resource->req_lock);
-
 	if (drbd_submit_peer_request(device, peer_req, READ, fault_type) == 0)
 		return 0;
 
 	/* don't care for the reason here */
 	drbd_err(device, "submit failed, triggering re-connect\n");
+
+out_free_e:
 	spin_lock_irq(&device->resource->req_lock);
 	list_del(&peer_req->w.list);
 	spin_unlock_irq(&device->resource->req_lock);
 	/* no drbd_rs_complete_io(), we are dropping the connection anyways */
 
-out_free_e:
 	put_ldev(device);
 	drbd_free_peer_req(device, peer_req);
 	return -EIO;
@@ -2842,8 +2930,10 @@ static void drbd_uuid_dump(struct drbd_d
 -1091   requires proto 91
 -1096   requires proto 96
  */
-static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_hold(local)
+static int drbd_uuid_compare(struct drbd_device *const device, int *rule_nr) __must_hold(local)
 {
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
 	u64 self, peer;
 	int i, j;
 
@@ -2869,7 +2959,7 @@ static int drbd_uuid_compare(struct drbd
 
 		if (device->p_uuid[UI_BITMAP] == (u64)0 && device->ldev->md.uuid[UI_BITMAP] != (u64)0) {
 
-			if (first_peer_device(device)->connection->agreed_pro_version < 91)
+			if (connection->agreed_pro_version < 91)
 				return -1091;
 
 			if ((device->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (device->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
@@ -2892,7 +2982,7 @@ static int drbd_uuid_compare(struct drbd
 
 		if (device->ldev->md.uuid[UI_BITMAP] == (u64)0 && device->p_uuid[UI_BITMAP] != (u64)0) {
 
-			if (first_peer_device(device)->connection->agreed_pro_version < 91)
+			if (connection->agreed_pro_version < 91)
 				return -1091;
 
 			if ((device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (device->p_uuid[UI_BITMAP] & ~((u64)1)) &&
@@ -2925,7 +3015,7 @@ static int drbd_uuid_compare(struct drbd
 		case 1: /*  self_pri && !peer_pri */ return 1;
 		case 2: /* !self_pri &&  peer_pri */ return -1;
 		case 3: /*  self_pri &&  peer_pri */
-			dc = test_bit(RESOLVE_CONFLICTS, &first_peer_device(device)->connection->flags);
+			dc = test_bit(RESOLVE_CONFLICTS, &connection->flags);
 			return dc ? -1 : 1;
 		}
 	}
@@ -2938,14 +3028,14 @@ static int drbd_uuid_compare(struct drbd
 	*rule_nr = 51;
 	peer = device->p_uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+		if (connection->agreed_pro_version < 96 ?
 		    (device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
 		    (device->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
 		    peer + UUID_NEW_BM_OFFSET == (device->p_uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of the peer's UUIDs. */
 
-			if (first_peer_device(device)->connection->agreed_pro_version < 91)
+			if (connection->agreed_pro_version < 91)
 				return -1091;
 
 			device->p_uuid[UI_BITMAP] = device->p_uuid[UI_HISTORY_START];
@@ -2975,14 +3065,14 @@ static int drbd_uuid_compare(struct drbd
 	*rule_nr = 71;
 	self = device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+		if (connection->agreed_pro_version < 96 ?
 		    (device->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
 		    (device->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
 		    self + UUID_NEW_BM_OFFSET == (device->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of our UUIDs. */
 
-			if (first_peer_device(device)->connection->agreed_pro_version < 91)
+			if (connection->agreed_pro_version < 91)
 				return -1091;
 
 			__drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_HISTORY_START]);
@@ -3352,8 +3442,7 @@ disconnect:
  * return: NULL (alg name was "")
  *         ERR_PTR(error) if something goes wrong
  *         or the crypto hash ptr, if it worked out ok. */
-static
-struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device,
+static struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device,
 		const char *alg, const char *name)
 {
 	struct crypto_hash *tfm;
@@ -3639,7 +3728,7 @@ static int receive_sizes(struct drbd_con
 	struct drbd_device *device;
 	struct p_sizes *p = pi->data;
 	enum determine_dev_size dd = DS_UNCHANGED;
-	sector_t p_size, p_usize, my_usize;
+	sector_t p_size, p_usize, p_csize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
 
@@ -3650,6 +3739,7 @@ static int receive_sizes(struct drbd_con
 
 	p_size = be64_to_cpu(p->d_size);
 	p_usize = be64_to_cpu(p->u_size);
+	p_csize = be64_to_cpu(p->c_size);
 
 	/* just store the peer's disk size for now.
 	 * we still need to figure out whether we accept that. */
@@ -3710,7 +3800,6 @@ static int receive_sizes(struct drbd_con
 	}
 
 	device->peer_max_bio_size = be32_to_cpu(p->max_bio_size);
-	drbd_reconsider_max_bio_size(device);
 	/* Leave drbd_reconsider_max_bio_size() before drbd_determine_dev_size().
 	   In case we cleared the QUEUE_FLAG_DISCARD from our queue in
 	   drbd_reconsider_max_bio_size(), we can be sure that after
@@ -3718,14 +3807,28 @@ static int receive_sizes(struct drbd_con
 
 	ddsf = be16_to_cpu(p->dds_flags);
 	if (get_ldev(device)) {
+		drbd_reconsider_max_bio_size(device, device->ldev);
 		dd = drbd_determine_dev_size(device, ddsf, NULL);
 		put_ldev(device);
 		if (dd == DS_ERROR)
 			return -EIO;
 		drbd_md_sync(device);
 	} else {
-		/* I am diskless, need to accept the peer's size. */
-		drbd_set_my_capacity(device, p_size);
+		/*
+		 * I am diskless, need to accept the peer's *current* size.
+		 * I must NOT accept the peers backing disk size,
+		 * it may have been larger than mine all along...
+		 *
+		 * At this point, the peer knows more about my disk, or at
+		 * least about what we last agreed upon, than myself.
+		 * So if his c_size is less than his d_size, the most likely
+		 * reason is that *my* d_size was smaller last time we checked.
+		 *
+		 * However, if he sends a zero current size,
+		 * take his (user-capped or) backing disk size anyways.
+		 */
+		drbd_reconsider_max_bio_size(device, NULL);
+		drbd_set_my_capacity(device, p_csize ?: p_usize ?: p_size);
 	}
 
 	if (get_ldev(device)) {
@@ -4501,6 +4604,7 @@ static void drbdd(struct drbd_connection
 		struct data_cmd *cmd;
 
 		drbd_thread_current_set_cpu(&connection->receiver);
+		update_receiver_timing_details(connection, drbd_recv_header);
 		if (drbd_recv_header(connection, &pi))
 			goto err_out;
 
@@ -4519,12 +4623,14 @@ static void drbdd(struct drbd_connection
 		}
 
 		if (shs) {
+			update_receiver_timing_details(connection, drbd_recv_all_warn);
 			err = drbd_recv_all_warn(connection, pi.data, shs);
 			if (err)
 				goto err_out;
 			pi.size -= shs;
 		}
 
+		update_receiver_timing_details(connection, cmd->fn);
 		err = cmd->fn(connection, &pi);
 		if (err) {
 			drbd_err(connection, "error receiving %s, e: %d l: %d!\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_req.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_req.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_req.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_req.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ static void _drbd_start_io_acct(struct d
 static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req)
 {
 	int rw = bio_data_dir(req->master_bio);
-	unsigned long duration = jiffies - req->start_time;
+	unsigned long duration = jiffies - req->start_jif;
 	int cpu;
 	cpu = part_stat_lock();
 	part_stat_add(cpu, &device->vdisk->part0, ticks[rw], duration);
@@ -66,7 +66,7 @@ static struct drbd_request *drbd_req_new
 {
 	struct drbd_request *req;
 
-	req = mempool_alloc(drbd_request_mempool, GFP_NOIO);
+	req = mempool_alloc(drbd_request_mempool, GFP_NOIO | __GFP_ZERO);
 	if (!req)
 		return NULL;
 
@@ -84,6 +84,8 @@ static struct drbd_request *drbd_req_new
 
 	INIT_LIST_HEAD(&req->tl_requests);
 	INIT_LIST_HEAD(&req->w.list);
+	INIT_LIST_HEAD(&req->req_pending_master_completion);
+	INIT_LIST_HEAD(&req->req_pending_local);
 
 	/* one reference to be put by __drbd_make_request */
 	atomic_set(&req->completion_ref, 1);
@@ -92,6 +94,19 @@ static struct drbd_request *drbd_req_new
 	return req;
 }
 
+static void drbd_remove_request_interval(struct rb_root *root,
+					 struct drbd_request *req)
+{
+	struct drbd_device *device = req->device;
+	struct drbd_interval *i = &req->i;
+
+	drbd_remove_interval(root, i);
+
+	/* Wake up any processes waiting for this request to complete.  */
+	if (i->waiting)
+		wake_up(&device->misc_wait);
+}
+
 void drbd_req_destroy(struct kref *kref)
 {
 	struct drbd_request *req = container_of(kref, struct drbd_request, kref);
@@ -107,14 +122,30 @@ void drbd_req_destroy(struct kref *kref)
 		return;
 	}
 
-	/* remove it from the transfer log.
-	 * well, only if it had been there in the first
-	 * place... if it had not (local only or conflicting
-	 * and never sent), it should still be "empty" as
-	 * initialized in drbd_req_new(), so we can list_del() it
-	 * here unconditionally */
+	/* If called from mod_rq_state (expected normal case) or
+	 * drbd_send_and_submit (the less likely normal path), this holds the
+	 * req_lock, and req->tl_requests will typicaly be on ->transfer_log,
+	 * though it may be still empty (never added to the transfer log).
+	 *
+	 * If called from do_retry(), we do NOT hold the req_lock, but we are
+	 * still allowed to unconditionally list_del(&req->tl_requests),
+	 * because it will be on a local on-stack list only. */
 	list_del_init(&req->tl_requests);
 
+	/* finally remove the request from the conflict detection
+	 * respective block_id verification interval tree. */
+	if (!drbd_interval_empty(&req->i)) {
+		struct rb_root *root;
+
+		if (s & RQ_WRITE)
+			root = &device->write_requests;
+		else
+			root = &device->read_requests;
+		drbd_remove_request_interval(root, req);
+	} else if (s & (RQ_NET_MASK & ~RQ_NET_DONE) && req->i.size != 0)
+		drbd_err(device, "drbd_req_destroy: Logic BUG: interval empty, but: rq_state=0x%x, sect=%llu, size=%u\n",
+			s, (unsigned long long)req->i.sector, req->i.size);
+
 	/* if it was a write, we may have to set the corresponding
 	 * bit(s) out-of-sync first. If it had a local part, we need to
 	 * release the reference to the activity log. */
@@ -188,19 +219,6 @@ void complete_master_bio(struct drbd_dev
 }
 
 
-static void drbd_remove_request_interval(struct rb_root *root,
-					 struct drbd_request *req)
-{
-	struct drbd_device *device = req->device;
-	struct drbd_interval *i = &req->i;
-
-	drbd_remove_interval(root, i);
-
-	/* Wake up any processes waiting for this request to complete.  */
-	if (i->waiting)
-		wake_up(&device->misc_wait);
-}
-
 /* Helper for __req_mod().
  * Set m->bio to the master bio, if it is fit to be completed,
  * or leave it alone (it is initialized to NULL in __req_mod),
@@ -254,18 +272,6 @@ void drbd_req_complete(struct drbd_reque
 	ok = (s & RQ_LOCAL_OK) || (s & RQ_NET_OK);
 	error = PTR_ERR(req->private_bio);
 
-	/* remove the request from the conflict detection
-	 * respective block_id verification hash */
-	if (!drbd_interval_empty(&req->i)) {
-		struct rb_root *root;
-
-		if (rw == WRITE)
-			root = &device->write_requests;
-		else
-			root = &device->read_requests;
-		drbd_remove_request_interval(root, req);
-	}
-
 	/* Before we can signal completion to the upper layers,
 	 * we may need to close the current transfer log epoch.
 	 * We are within the request lock, so we can simply compare
@@ -301,9 +307,24 @@ void drbd_req_complete(struct drbd_reque
 		m->error = ok ? 0 : (error ?: -EIO);
 		m->bio = req->master_bio;
 		req->master_bio = NULL;
+		/* We leave it in the tree, to be able to verify later
+		 * write-acks in protocol != C during resync.
+		 * But we mark it as "complete", so it won't be counted as
+		 * conflict in a multi-primary setup. */
+		req->i.completed = true;
 	}
+
+	if (req->i.waiting)
+		wake_up(&device->misc_wait);
+
+	/* Either we are about to complete to upper layers,
+	 * or we will restart this request.
+	 * In either case, the request object will be destroyed soon,
+	 * so better remove it from all lists. */
+	list_del_init(&req->req_pending_master_completion);
 }
 
+/* still holds resource->req_lock */
 static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
 {
 	struct drbd_device *device = req->device;
@@ -324,12 +345,91 @@ static int drbd_req_put_completion_ref(s
 	return 1;
 }
 
+static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_next == NULL)
+		connection->req_next = req;
+}
+
+static void advance_conn_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_next != req)
+		return;
+	list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+		const unsigned s = req->rq_state;
+		if (s & RQ_NET_QUEUED)
+			break;
+	}
+	if (&req->tl_requests == &connection->transfer_log)
+		req = NULL;
+	connection->req_next = req;
+}
+
+static void set_if_null_req_ack_pending(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_ack_pending == NULL)
+		connection->req_ack_pending = req;
+}
+
+static void advance_conn_req_ack_pending(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_ack_pending != req)
+		return;
+	list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+		const unsigned s = req->rq_state;
+		if ((s & RQ_NET_SENT) && (s & RQ_NET_PENDING))
+			break;
+	}
+	if (&req->tl_requests == &connection->transfer_log)
+		req = NULL;
+	connection->req_ack_pending = req;
+}
+
+static void set_if_null_req_not_net_done(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_not_net_done == NULL)
+		connection->req_not_net_done = req;
+}
+
+static void advance_conn_req_not_net_done(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+	if (!connection)
+		return;
+	if (connection->req_not_net_done != req)
+		return;
+	list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+		const unsigned s = req->rq_state;
+		if ((s & RQ_NET_SENT) && !(s & RQ_NET_DONE))
+			break;
+	}
+	if (&req->tl_requests == &connection->transfer_log)
+		req = NULL;
+	connection->req_not_net_done = req;
+}
+
 /* I'd like this to be the only place that manipulates
  * req->completion_ref and req->kref. */
 static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		int clear, int set)
 {
 	struct drbd_device *device = req->device;
+	struct drbd_peer_device *peer_device = first_peer_device(device);
 	unsigned s = req->rq_state;
 	int c_put = 0;
 	int k_put = 0;
@@ -356,14 +456,23 @@ static void mod_rq_state(struct drbd_req
 		atomic_inc(&req->completion_ref);
 	}
 
-	if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED))
+	if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED)) {
 		atomic_inc(&req->completion_ref);
+		set_if_null_req_next(peer_device, req);
+	}
 
 	if (!(s & RQ_EXP_BARR_ACK) && (set & RQ_EXP_BARR_ACK))
 		kref_get(&req->kref); /* wait for the DONE */
 
-	if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT))
-		atomic_add(req->i.size >> 9, &device->ap_in_flight);
+	if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT)) {
+		/* potentially already completed in the asender thread */
+		if (!(s & RQ_NET_DONE)) {
+			atomic_add(req->i.size >> 9, &device->ap_in_flight);
+			set_if_null_req_not_net_done(peer_device, req);
+		}
+		if (s & RQ_NET_PENDING)
+			set_if_null_req_ack_pending(peer_device, req);
+	}
 
 	if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
 		atomic_inc(&req->completion_ref);
@@ -386,20 +495,34 @@ static void mod_rq_state(struct drbd_req
 			++k_put;
 		else
 			++c_put;
+		list_del_init(&req->req_pending_local);
 	}
 
 	if ((s & RQ_NET_PENDING) && (clear & RQ_NET_PENDING)) {
 		dec_ap_pending(device);
 		++c_put;
+		req->acked_jif = jiffies;
+		advance_conn_req_ack_pending(peer_device, req);
 	}
 
-	if ((s & RQ_NET_QUEUED) && (clear & RQ_NET_QUEUED))
+	if ((s & RQ_NET_QUEUED) && (clear & RQ_NET_QUEUED)) {
 		++c_put;
+		advance_conn_req_next(peer_device, req);
+	}
 
-	if ((s & RQ_EXP_BARR_ACK) && !(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
-		if (req->rq_state & RQ_NET_SENT)
+	if (!(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
+		if (s & RQ_NET_SENT)
 			atomic_sub(req->i.size >> 9, &device->ap_in_flight);
-		++k_put;
+		if (s & RQ_EXP_BARR_ACK)
+			++k_put;
+		req->net_done_jif = jiffies;
+
+		/* in ahead/behind mode, or just in case,
+		 * before we finally destroy this request,
+		 * the caching pointers must not reference it anymore */
+		advance_conn_req_next(peer_device, req);
+		advance_conn_req_ack_pending(peer_device, req);
+		advance_conn_req_not_net_done(peer_device, req);
 	}
 
 	/* potentially complete and destroy */
@@ -439,6 +562,19 @@ static void drbd_report_io_error(struct
 			bdevname(device->ldev->backing_bdev, b));
 }
 
+/* Helper for HANDED_OVER_TO_NETWORK.
+ * Is this a protocol A write (neither WRITE_ACK nor RECEIVE_ACK expected)?
+ * Is it also still "PENDING"?
+ * --> If so, clear PENDING and set NET_OK below.
+ * If it is a protocol A write, but not RQ_PENDING anymore, neg-ack was faster
+ * (and we must not set RQ_NET_OK) */
+static inline bool is_pending_write_protocol_A(struct drbd_request *req)
+{
+	return (req->rq_state &
+		   (RQ_WRITE|RQ_NET_PENDING|RQ_EXP_WRITE_ACK|RQ_EXP_RECEIVE_ACK))
+		== (RQ_WRITE|RQ_NET_PENDING);
+}
+
 /* obviously this could be coded as many single functions
  * instead of one huge switch,
  * or by putting the code directly in the respective locations
@@ -454,7 +590,9 @@ static void drbd_report_io_error(struct
 int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m)
 {
-	struct drbd_device *device = req->device;
+	struct drbd_device *const device = req->device;
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
 	struct net_conf *nc;
 	int p, rv = 0;
 
@@ -477,7 +615,7 @@ int __req_mod(struct drbd_request *req,
 		 * and from w_read_retry_remote */
 		D_ASSERT(device, !(req->rq_state & RQ_NET_MASK));
 		rcu_read_lock();
-		nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+		nc = rcu_dereference(connection->net_conf);
 		p = nc->wire_protocol;
 		rcu_read_unlock();
 		req->rq_state |=
@@ -549,7 +687,7 @@ int __req_mod(struct drbd_request *req,
 		D_ASSERT(device, (req->rq_state & RQ_LOCAL_MASK) == 0);
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
 		req->w.cb = w_send_read_req;
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+		drbd_queue_work(&connection->sender_work,
 				&req->w);
 		break;
 
@@ -585,23 +723,23 @@ int __req_mod(struct drbd_request *req,
 		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED|RQ_EXP_BARR_ACK);
 		req->w.cb =  w_send_dblock;
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+		drbd_queue_work(&connection->sender_work,
 				&req->w);
 
 		/* close the epoch, in case it outgrew the limit */
 		rcu_read_lock();
-		nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+		nc = rcu_dereference(connection->net_conf);
 		p = nc->max_epoch_size;
 		rcu_read_unlock();
-		if (first_peer_device(device)->connection->current_tle_writes >= p)
-			start_new_tl_epoch(first_peer_device(device)->connection);
+		if (connection->current_tle_writes >= p)
+			start_new_tl_epoch(connection);
 
 		break;
 
 	case QUEUE_FOR_SEND_OOS:
 		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
 		req->w.cb =  w_send_out_of_sync;
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+		drbd_queue_work(&connection->sender_work,
 				&req->w);
 		break;
 
@@ -615,18 +753,16 @@ int __req_mod(struct drbd_request *req,
 
 	case HANDED_OVER_TO_NETWORK:
 		/* assert something? */
-		if (bio_data_dir(req->master_bio) == WRITE &&
-		    !(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK))) {
+		if (is_pending_write_protocol_A(req))
 			/* this is what is dangerous about protocol A:
 			 * pretend it was successfully written on the peer. */
-			if (req->rq_state & RQ_NET_PENDING)
-				mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
-			/* else: neg-ack was faster... */
-			/* it is still not yet RQ_NET_DONE until the
-			 * corresponding epoch barrier got acked as well,
-			 * so we know what to dirty on connection loss */
-		}
-		mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_SENT);
+			mod_rq_state(req, m, RQ_NET_QUEUED|RQ_NET_PENDING,
+						RQ_NET_SENT|RQ_NET_OK);
+		else
+			mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_SENT);
+		/* It is still not yet RQ_NET_DONE until the
+		 * corresponding epoch barrier got acked as well,
+		 * so we know what to dirty on connection loss. */
 		break;
 
 	case OOS_HANDED_TO_NETWORK:
@@ -658,12 +794,13 @@ int __req_mod(struct drbd_request *req,
 	case WRITE_ACKED_BY_PEER_AND_SIS:
 		req->rq_state |= RQ_NET_SIS;
 	case WRITE_ACKED_BY_PEER:
-		D_ASSERT(device, req->rq_state & RQ_EXP_WRITE_ACK);
-		/* protocol C; successfully written on peer.
+		/* Normal operation protocol C: successfully written on peer.
+		 * During resync, even in protocol != C,
+		 * we requested an explicit write ack anyways.
+		 * Which means we cannot even assert anything here.
 		 * Nothing more to do here.
 		 * We want to keep the tl in place for all protocols, to cater
 		 * for volatile write-back caches on lower level devices. */
-
 		goto ack_common;
 	case RECV_ACKED_BY_PEER:
 		D_ASSERT(device, req->rq_state & RQ_EXP_RECEIVE_ACK);
@@ -671,7 +808,6 @@ int __req_mod(struct drbd_request *req,
 		 * see also notes above in HANDED_OVER_TO_NETWORK about
 		 * protocol != C */
 	ack_common:
-		D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
 		break;
 
@@ -714,7 +850,7 @@ int __req_mod(struct drbd_request *req,
 
 		get_ldev(device); /* always succeeds in this call path */
 		req->w.cb = w_restart_disk_io;
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+		drbd_queue_work(&connection->sender_work,
 				&req->w);
 		break;
 
@@ -736,7 +872,8 @@ int __req_mod(struct drbd_request *req,
 
 			mod_rq_state(req, m, RQ_COMPLETION_SUSP, RQ_NET_QUEUED|RQ_NET_PENDING);
 			if (req->w.cb) {
-				drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+				/* w.cb expected to be w_send_dblock, or w_send_read_req */
+				drbd_queue_work(&connection->sender_work,
 						&req->w);
 				rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
 			} /* else: FIXME can this happen? */
@@ -769,7 +906,7 @@ int __req_mod(struct drbd_request *req,
 		break;
 
 	case QUEUE_AS_DRBD_BARRIER:
-		start_new_tl_epoch(first_peer_device(device)->connection);
+		start_new_tl_epoch(connection);
 		mod_rq_state(req, m, 0, RQ_NET_OK|RQ_NET_DONE);
 		break;
 	};
@@ -886,6 +1023,9 @@ static void maybe_pull_ahead(struct drbd
 	    connection->agreed_pro_version < 96)
 		return;
 
+	if (on_congestion == OC_PULL_AHEAD && device->state.conn == C_AHEAD)
+		return; /* nothing to do ... */
+
 	/* If I don't even have good local storage, we can not reasonably try
 	 * to pull ahead of the peer. We also need the local reference to make
 	 * sure device->act_log is there.
@@ -1021,6 +1161,7 @@ drbd_submit_req_private_bio(struct drbd_
 	 * stable storage, and this is a WRITE, we may not even submit
 	 * this bio. */
 	if (get_ldev(device)) {
+		req->pre_submit_jif = jiffies;
 		if (drbd_insert_fault(device,
 				      rw == WRITE ? DRBD_FAULT_DT_WR
 				    : rw == READ  ? DRBD_FAULT_DT_RD
@@ -1035,10 +1176,14 @@ drbd_submit_req_private_bio(struct drbd_
 
 static void drbd_queue_write(struct drbd_device *device, struct drbd_request *req)
 {
-	spin_lock(&device->submit.lock);
+	spin_lock_irq(&device->resource->req_lock);
 	list_add_tail(&req->tl_requests, &device->submit.writes);
-	spin_unlock(&device->submit.lock);
+	list_add_tail(&req->req_pending_master_completion,
+			&device->pending_master_completion[1 /* WRITE */]);
+	spin_unlock_irq(&device->resource->req_lock);
 	queue_work(device->submit.wq, &device->submit.worker);
+	/* do_submit() may sleep internally on al_wait, too */
+	wake_up(&device->al_wait);
 }
 
 /* returns the new drbd_request pointer, if the caller is expected to
@@ -1047,7 +1192,7 @@ static void drbd_queue_write(struct drbd
  * Returns ERR_PTR(-ENOMEM) if we cannot allocate a drbd_request.
  */
 static struct drbd_request *
-drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long start_time)
+drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long start_jif)
 {
 	const int rw = bio_data_dir(bio);
 	struct drbd_request *req;
@@ -1062,7 +1207,7 @@ drbd_request_prepare(struct drbd_device
 		bio_endio(bio, -ENOMEM);
 		return ERR_PTR(-ENOMEM);
 	}
-	req->start_time = start_time;
+	req->start_jif = start_jif;
 
 	if (!get_ldev(device)) {
 		bio_put(req->private_bio);
@@ -1075,10 +1220,12 @@ drbd_request_prepare(struct drbd_device
 	if (rw == WRITE && req->private_bio && req->i.size
 	&& !test_bit(AL_SUSPENDED, &device->flags)) {
 		if (!drbd_al_begin_io_fastpath(device, &req->i)) {
+			atomic_inc(&device->ap_actlog_cnt);
 			drbd_queue_write(device, req);
 			return NULL;
 		}
 		req->rq_state |= RQ_IN_ACT_LOG;
+		req->in_actlog_jif = jiffies;
 	}
 
 	return req;
@@ -1086,11 +1233,13 @@ drbd_request_prepare(struct drbd_device
 
 static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req)
 {
+	struct drbd_resource *resource = device->resource;
 	const int rw = bio_rw(req->master_bio);
 	struct bio_and_error m = { NULL, };
 	bool no_remote = false;
+	bool submit_private_bio = false;
 
-	spin_lock_irq(&device->resource->req_lock);
+	spin_lock_irq(&resource->req_lock);
 	if (rw == WRITE) {
 		/* This may temporarily give up the req_lock,
 		 * but will re-aquire it before it returns here.
@@ -1148,13 +1297,18 @@ static void drbd_send_and_submit(struct
 			no_remote = true;
 	}
 
+	/* If it took the fast path in drbd_request_prepare, add it here.
+	 * The slow path has added it already. */
+	if (list_empty(&req->req_pending_master_completion))
+		list_add_tail(&req->req_pending_master_completion,
+			&device->pending_master_completion[rw == WRITE]);
 	if (req->private_bio) {
 		/* needs to be marked within the same spinlock */
+		list_add_tail(&req->req_pending_local,
+			&device->pending_completion[rw == WRITE]);
 		_req_mod(req, TO_BE_SUBMITTED);
 		/* but we need to give up the spinlock to submit */
-		spin_unlock_irq(&device->resource->req_lock);
-		drbd_submit_req_private_bio(req);
-		spin_lock_irq(&device->resource->req_lock);
+		submit_private_bio = true;
 	} else if (no_remote) {
 nodata:
 		if (__ratelimit(&drbd_ratelimit_state))
@@ -1167,15 +1321,23 @@ nodata:
 out:
 	if (drbd_req_put_completion_ref(req, &m, 1))
 		kref_put(&req->kref, drbd_req_destroy);
-	spin_unlock_irq(&device->resource->req_lock);
+	spin_unlock_irq(&resource->req_lock);
 
+	/* Even though above is a kref_put(), this is safe.
+	 * As long as we still need to submit our private bio,
+	 * we hold a completion ref, and the request cannot disappear.
+	 * If however this request did not even have a private bio to submit
+	 * (e.g. remote read), req may already be invalid now.
+	 * That's why we cannot check on req->private_bio. */
+	if (submit_private_bio)
+		drbd_submit_req_private_bio(req);
 	if (m.bio)
 		complete_master_bio(device, &m);
 }
 
-void __drbd_make_request(struct drbd_device *device, struct bio *bio, unsigned long start_time)
+void __drbd_make_request(struct drbd_device *device, struct bio *bio, unsigned long start_jif)
 {
-	struct drbd_request *req = drbd_request_prepare(device, bio, start_time);
+	struct drbd_request *req = drbd_request_prepare(device, bio, start_jif);
 	if (IS_ERR_OR_NULL(req))
 		return;
 	drbd_send_and_submit(device, req);
@@ -1194,6 +1356,8 @@ static void submit_fast_path(struct drbd
 				continue;
 
 			req->rq_state |= RQ_IN_ACT_LOG;
+			req->in_actlog_jif = jiffies;
+			atomic_dec(&device->ap_actlog_cnt);
 		}
 
 		list_del_init(&req->tl_requests);
@@ -1203,7 +1367,8 @@ static void submit_fast_path(struct drbd
 
 static bool prepare_al_transaction_nonblock(struct drbd_device *device,
 					    struct list_head *incoming,
-					    struct list_head *pending)
+					    struct list_head *pending,
+					    struct list_head *later)
 {
 	struct drbd_request *req, *tmp;
 	int wake = 0;
@@ -1212,45 +1377,105 @@ static bool prepare_al_transaction_nonbl
 	spin_lock_irq(&device->al_lock);
 	list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
 		err = drbd_al_begin_io_nonblock(device, &req->i);
+		if (err == -ENOBUFS)
+			break;
 		if (err == -EBUSY)
 			wake = 1;
 		if (err)
-			continue;
-		req->rq_state |= RQ_IN_ACT_LOG;
-		list_move_tail(&req->tl_requests, pending);
+			list_move_tail(&req->tl_requests, later);
+		else
+			list_move_tail(&req->tl_requests, pending);
 	}
 	spin_unlock_irq(&device->al_lock);
 	if (wake)
 		wake_up(&device->al_wait);
-
 	return !list_empty(pending);
 }
 
+void send_and_submit_pending(struct drbd_device *device, struct list_head *pending)
+{
+	struct drbd_request *req, *tmp;
+
+	list_for_each_entry_safe(req, tmp, pending, tl_requests) {
+		req->rq_state |= RQ_IN_ACT_LOG;
+		req->in_actlog_jif = jiffies;
+		atomic_dec(&device->ap_actlog_cnt);
+		list_del_init(&req->tl_requests);
+		drbd_send_and_submit(device, req);
+	}
+}
+
 void do_submit(struct work_struct *ws)
 {
 	struct drbd_device *device = container_of(ws, struct drbd_device, submit.worker);
-	LIST_HEAD(incoming);
-	LIST_HEAD(pending);
-	struct drbd_request *req, *tmp;
+	LIST_HEAD(incoming);	/* from drbd_make_request() */
+	LIST_HEAD(pending);	/* to be submitted after next AL-transaction commit */
+	LIST_HEAD(busy);	/* blocked by resync requests */
+
+	/* grab new incoming requests */
+	spin_lock_irq(&device->resource->req_lock);
+	list_splice_tail_init(&device->submit.writes, &incoming);
+	spin_unlock_irq(&device->resource->req_lock);
 
 	for (;;) {
-		spin_lock(&device->submit.lock);
-		list_splice_tail_init(&device->submit.writes, &incoming);
-		spin_unlock(&device->submit.lock);
+		DEFINE_WAIT(wait);
 
+		/* move used-to-be-busy back to front of incoming */
+		list_splice_init(&busy, &incoming);
 		submit_fast_path(device, &incoming);
 		if (list_empty(&incoming))
 			break;
 
-skip_fast_path:
-		wait_event(device->al_wait, prepare_al_transaction_nonblock(device, &incoming, &pending));
-		/* Maybe more was queued, while we prepared the transaction?
-		 * Try to stuff them into this transaction as well.
-		 * Be strictly non-blocking here, no wait_event, we already
-		 * have something to commit.
-		 * Stop if we don't make any more progres.
-		 */
 		for (;;) {
+			prepare_to_wait(&device->al_wait, &wait, TASK_UNINTERRUPTIBLE);
+
+			list_splice_init(&busy, &incoming);
+			prepare_al_transaction_nonblock(device, &incoming, &pending, &busy);
+			if (!list_empty(&pending))
+				break;
+
+			schedule();
+
+			/* If all currently "hot" activity log extents are kept busy by
+			 * incoming requests, we still must not totally starve new
+			 * requests to "cold" extents.
+			 * Something left on &incoming means there had not been
+			 * enough update slots available, and the activity log
+			 * has been marked as "starving".
+			 *
+			 * Try again now, without looking for new requests,
+			 * effectively blocking all new requests until we made
+			 * at least _some_ progress with what we currently have.
+			 */
+			if (!list_empty(&incoming))
+				continue;
+
+			/* Nothing moved to pending, but nothing left
+			 * on incoming: all moved to busy!
+			 * Grab new and iterate. */
+			spin_lock_irq(&device->resource->req_lock);
+			list_splice_tail_init(&device->submit.writes, &incoming);
+			spin_unlock_irq(&device->resource->req_lock);
+		}
+		finish_wait(&device->al_wait, &wait);
+
+		/* If the transaction was full, before all incoming requests
+		 * had been processed, skip ahead to commit, and iterate
+		 * without splicing in more incoming requests from upper layers.
+		 *
+		 * Else, if all incoming have been processed,
+		 * they have become either "pending" (to be submitted after
+		 * next transaction commit) or "busy" (blocked by resync).
+		 *
+		 * Maybe more was queued, while we prepared the transaction?
+		 * Try to stuff those into this transaction as well.
+		 * Be strictly non-blocking here,
+		 * we already have something to commit.
+		 *
+		 * Commit if we don't make any more progres.
+		 */
+
+		while (list_empty(&incoming)) {
 			LIST_HEAD(more_pending);
 			LIST_HEAD(more_incoming);
 			bool made_progress;
@@ -1260,55 +1485,32 @@ skip_fast_path:
 			if (list_empty(&device->submit.writes))
 				break;
 
-			spin_lock(&device->submit.lock);
+			spin_lock_irq(&device->resource->req_lock);
 			list_splice_tail_init(&device->submit.writes, &more_incoming);
-			spin_unlock(&device->submit.lock);
+			spin_unlock_irq(&device->resource->req_lock);
 
 			if (list_empty(&more_incoming))
 				break;
 
-			made_progress = prepare_al_transaction_nonblock(device, &more_incoming, &more_pending);
+			made_progress = prepare_al_transaction_nonblock(device, &more_incoming, &more_pending, &busy);
 
 			list_splice_tail_init(&more_pending, &pending);
 			list_splice_tail_init(&more_incoming, &incoming);
-
 			if (!made_progress)
 				break;
 		}
-		drbd_al_begin_io_commit(device, false);
-
-		list_for_each_entry_safe(req, tmp, &pending, tl_requests) {
-			list_del_init(&req->tl_requests);
-			drbd_send_and_submit(device, req);
-		}
 
-		/* If all currently hot activity log extents are kept busy by
-		 * incoming requests, we still must not totally starve new
-		 * requests to cold extents. In that case, prepare one request
-		 * in blocking mode. */
-		list_for_each_entry_safe(req, tmp, &incoming, tl_requests) {
-			list_del_init(&req->tl_requests);
-			req->rq_state |= RQ_IN_ACT_LOG;
-			if (!drbd_al_begin_io_prepare(device, &req->i)) {
-				/* Corresponding extent was hot after all? */
-				drbd_send_and_submit(device, req);
-			} else {
-				/* Found a request to a cold extent.
-				 * Put on "pending" list,
-				 * and try to cumulate with more. */
-				list_add(&req->tl_requests, &pending);
-				goto skip_fast_path;
-			}
-		}
+		drbd_al_begin_io_commit(device);
+		send_and_submit_pending(device, &pending);
 	}
 }
 
 void drbd_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct drbd_device *device = (struct drbd_device *) q->queuedata;
-	unsigned long start_time;
+	unsigned long start_jif;
 
-	start_time = jiffies;
+	start_jif = jiffies;
 
 	/*
 	 * what we "blindly" assume:
@@ -1316,7 +1518,7 @@ void drbd_make_request(struct request_qu
 	D_ASSERT(device, IS_ALIGNED(bio->bi_iter.bi_size, 512));
 
 	inc_ap_bio(device);
-	__drbd_make_request(device, bio, start_time);
+	__drbd_make_request(device, bio, start_jif);
 }
 
 /* This is called by bio_add_page().
@@ -1353,36 +1555,13 @@ int drbd_merge_bvec(struct request_queue
 	return limit;
 }
 
-static void find_oldest_requests(
-		struct drbd_connection *connection,
-		struct drbd_device *device,
-		struct drbd_request **oldest_req_waiting_for_peer,
-		struct drbd_request **oldest_req_waiting_for_disk)
-{
-	struct drbd_request *r;
-	*oldest_req_waiting_for_peer = NULL;
-	*oldest_req_waiting_for_disk = NULL;
-	list_for_each_entry(r, &connection->transfer_log, tl_requests) {
-		const unsigned s = r->rq_state;
-		if (!*oldest_req_waiting_for_peer
-		&& ((s & RQ_NET_MASK) && !(s & RQ_NET_DONE)))
-			*oldest_req_waiting_for_peer = r;
-
-		if (!*oldest_req_waiting_for_disk
-		&& (s & RQ_LOCAL_PENDING) && r->device == device)
-			*oldest_req_waiting_for_disk = r;
-
-		if (*oldest_req_waiting_for_peer && *oldest_req_waiting_for_disk)
-			break;
-	}
-}
-
 void request_timer_fn(unsigned long data)
 {
 	struct drbd_device *device = (struct drbd_device *) data;
 	struct drbd_connection *connection = first_peer_device(device)->connection;
-	struct drbd_request *req_disk, *req_peer; /* oldest request */
+	struct drbd_request *req_read, *req_write, *req_peer; /* oldest request */
 	struct net_conf *nc;
+	unsigned long oldest_submit_jif;
 	unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */
 	unsigned long now;
 
@@ -1403,14 +1582,31 @@ void request_timer_fn(unsigned long data
 		return; /* Recurring timer stopped */
 
 	now = jiffies;
+	nt = now + et;
 
 	spin_lock_irq(&device->resource->req_lock);
-	find_oldest_requests(connection, device, &req_peer, &req_disk);
-	if (req_peer == NULL && req_disk == NULL) {
-		spin_unlock_irq(&device->resource->req_lock);
-		mod_timer(&device->request_timer, now + et);
-		return;
-	}
+	req_read = list_first_entry_or_null(&device->pending_completion[0], struct drbd_request, req_pending_local);
+	req_write = list_first_entry_or_null(&device->pending_completion[1], struct drbd_request, req_pending_local);
+	req_peer = connection->req_not_net_done;
+	/* maybe the oldest request waiting for the peer is in fact still
+	 * blocking in tcp sendmsg */
+	if (!req_peer && connection->req_next && connection->req_next->pre_send_jif)
+		req_peer = connection->req_next;
+
+	/* evaluate the oldest peer request only in one timer! */
+	if (req_peer && req_peer->device != device)
+		req_peer = NULL;
+
+	/* do we have something to evaluate? */
+	if (req_peer == NULL && req_write == NULL && req_read == NULL)
+		goto out;
+
+	oldest_submit_jif =
+		(req_write && req_read)
+		? ( time_before(req_write->pre_submit_jif, req_read->pre_submit_jif)
+		  ? req_write->pre_submit_jif : req_read->pre_submit_jif )
+		: req_write ? req_write->pre_submit_jif
+		: req_read ? req_read->pre_submit_jif : now;
 
 	/* The request is considered timed out, if
 	 * - we have some effective timeout from the configuration,
@@ -1429,13 +1625,13 @@ void request_timer_fn(unsigned long data
 	 * to expire twice (worst case) to become effective. Good enough.
 	 */
 	if (ent && req_peer &&
-		 time_after(now, req_peer->start_time + ent) &&
+		 time_after(now, req_peer->pre_send_jif + ent) &&
 		!time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) {
 		drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
 		_drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
 	}
-	if (dt && req_disk &&
-		 time_after(now, req_disk->start_time + dt) &&
+	if (dt && oldest_submit_jif != now &&
+		 time_after(now, oldest_submit_jif + dt) &&
 		!time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) {
 		drbd_warn(device, "Local backing device failed to meet the disk-timeout\n");
 		__drbd_chk_io_error(device, DRBD_FORCE_DETACH);
@@ -1443,11 +1639,12 @@ void request_timer_fn(unsigned long data
 
 	/* Reschedule timer for the nearest not already expired timeout.
 	 * Fallback to now + min(effective network timeout, disk timeout). */
-	ent = (ent && req_peer && time_before(now, req_peer->start_time + ent))
-		? req_peer->start_time + ent : now + et;
-	dt = (dt && req_disk && time_before(now, req_disk->start_time + dt))
-		? req_disk->start_time + dt : now + et;
+	ent = (ent && req_peer && time_before(now, req_peer->pre_send_jif + ent))
+		? req_peer->pre_send_jif + ent : now + et;
+	dt = (dt && oldest_submit_jif != now && time_before(now, oldest_submit_jif + dt))
+		? oldest_submit_jif + dt : now + et;
 	nt = time_before(ent, dt) ? ent : dt;
+out:
 	spin_unlock_irq(&connection->resource->req_lock);
 	mod_timer(&device->request_timer, nt);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_req.h linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_req.h
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_req.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_req.h	2014-09-28 17:29:07.000000000 -0400
@@ -288,6 +288,7 @@ extern void complete_master_bio(struct d
 extern void request_timer_fn(unsigned long data);
 extern void tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
 extern void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
+extern void tl_abort_disk_io(struct drbd_device *device);
 
 /* this is in drbd_main.c */
 extern void drbd_restart_request(struct drbd_request *req);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_state.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_state.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_state.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_state.c	2014-09-28 17:29:07.000000000 -0400
@@ -410,7 +410,7 @@ _drbd_request_state(struct drbd_device *
 	return rv;
 }
 
-static void print_st(struct drbd_device *device, char *name, union drbd_state ns)
+static void print_st(struct drbd_device *device, const char *name, union drbd_state ns)
 {
 	drbd_err(device, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c%c%c }\n",
 	    name,
@@ -952,11 +952,12 @@ enum drbd_state_rv
 __drbd_set_state(struct drbd_device *device, union drbd_state ns,
 	         enum chg_state_flags flags, struct completion *done)
 {
+	struct drbd_peer_device *peer_device = first_peer_device(device);
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
 	union drbd_state os;
 	enum drbd_state_rv rv = SS_SUCCESS;
 	enum sanitize_state_warnings ssw;
 	struct after_state_chg_work *ascw;
-	bool did_remote, should_do_remote;
 
 	os = drbd_read_state(device);
 
@@ -978,9 +979,9 @@ __drbd_set_state(struct drbd_device *dev
 			   this happen...*/
 
 			if (is_valid_state(device, os) == rv)
-				rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
+				rv = is_valid_soft_transition(os, ns, connection);
 		} else
-			rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
+			rv = is_valid_soft_transition(os, ns, connection);
 	}
 
 	if (rv < SS_SUCCESS) {
@@ -997,7 +998,7 @@ __drbd_set_state(struct drbd_device *dev
 	   sanitize_state(). Only display it here if we where not called from
 	   _conn_request_state() */
 	if (!(flags & CS_DC_SUSP))
-		conn_pr_state_change(first_peer_device(device)->connection, os, ns,
+		conn_pr_state_change(connection, os, ns,
 				     (flags & ~CS_DC_MASK) | CS_DC_SUSP);
 
 	/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
@@ -1008,28 +1009,35 @@ __drbd_set_state(struct drbd_device *dev
 	    (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
 		atomic_inc(&device->local_cnt);
 
-	did_remote = drbd_should_do_remote(device->state);
+	if (!is_sync_state(os.conn) && is_sync_state(ns.conn))
+		clear_bit(RS_DONE, &device->flags);
+
+	/* changes to local_cnt and device flags should be visible before
+	 * changes to state, which again should be visible before anything else
+	 * depending on that change happens. */
+	smp_wmb();
 	device->state.i = ns.i;
-	should_do_remote = drbd_should_do_remote(device->state);
 	device->resource->susp = ns.susp;
 	device->resource->susp_nod = ns.susp_nod;
 	device->resource->susp_fen = ns.susp_fen;
+	smp_wmb();
 
 	/* put replicated vs not-replicated requests in seperate epochs */
-	if (did_remote != should_do_remote)
-		start_new_tl_epoch(first_peer_device(device)->connection);
+	if (drbd_should_do_remote((union drbd_dev_state)os.i) !=
+	    drbd_should_do_remote((union drbd_dev_state)ns.i))
+		start_new_tl_epoch(connection);
 
 	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
 		drbd_print_uuids(device, "attached to UUIDs");
 
 	/* Wake up role changes, that were delayed because of connection establishing */
 	if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS &&
-	    no_peer_wf_report_params(first_peer_device(device)->connection))
-		clear_bit(STATE_SENT, &first_peer_device(device)->connection->flags);
+	    no_peer_wf_report_params(connection))
+		clear_bit(STATE_SENT, &connection->flags);
 
 	wake_up(&device->misc_wait);
 	wake_up(&device->state_wait);
-	wake_up(&first_peer_device(device)->connection->ping_wait);
+	wake_up(&connection->ping_wait);
 
 	/* Aborted verify run, or we reached the stop sector.
 	 * Log the last position, unless end-of-device. */
@@ -1118,21 +1126,21 @@ __drbd_set_state(struct drbd_device *dev
 
 	/* Receiver should clean up itself */
 	if (os.conn != C_DISCONNECTING && ns.conn == C_DISCONNECTING)
-		drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
+		drbd_thread_stop_nowait(&connection->receiver);
 
 	/* Now the receiver finished cleaning up itself, it should die */
 	if (os.conn != C_STANDALONE && ns.conn == C_STANDALONE)
-		drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
+		drbd_thread_stop_nowait(&connection->receiver);
 
 	/* Upon network failure, we need to restart the receiver. */
 	if (os.conn > C_WF_CONNECTION &&
 	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
-		drbd_thread_restart_nowait(&first_peer_device(device)->connection->receiver);
+		drbd_thread_restart_nowait(&connection->receiver);
 
 	/* Resume AL writing if we get a connection */
 	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
 		drbd_resume_al(device);
-		first_peer_device(device)->connection->connect_cnt++;
+		connection->connect_cnt++;
 	}
 
 	/* remember last attach time so request_timer_fn() won't
@@ -1150,7 +1158,7 @@ __drbd_set_state(struct drbd_device *dev
 		ascw->w.cb = w_after_state_ch;
 		ascw->device = device;
 		ascw->done = done;
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+		drbd_queue_work(&connection->sender_work,
 				&ascw->w);
 	} else {
 		drbd_err(device, "Could not kmalloc an ascw\n");
@@ -1222,13 +1230,16 @@ static void after_state_ch(struct drbd_d
 			   union drbd_state ns, enum chg_state_flags flags)
 {
 	struct drbd_resource *resource = device->resource;
+	struct drbd_peer_device *peer_device = first_peer_device(device);
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
 	struct sib_info sib;
 
 	sib.sib_reason = SIB_STATE_CHANGE;
 	sib.os = os;
 	sib.ns = ns;
 
-	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
+	if ((os.disk != D_UP_TO_DATE || os.pdsk != D_UP_TO_DATE)
+	&&  (ns.disk == D_UP_TO_DATE && ns.pdsk == D_UP_TO_DATE)) {
 		clear_bit(CRASHED_PRIMARY, &device->flags);
 		if (device->p_uuid)
 			device->p_uuid[UI_FLAGS] &= ~((u64)2);
@@ -1245,7 +1256,6 @@ static void after_state_ch(struct drbd_d
 	   state change. This function might sleep */
 
 	if (ns.susp_nod) {
-		struct drbd_connection *connection = first_peer_device(device)->connection;
 		enum drbd_req_event what = NOTHING;
 
 		spin_lock_irq(&device->resource->req_lock);
@@ -1267,8 +1277,6 @@ static void after_state_ch(struct drbd_d
 	}
 
 	if (ns.susp_fen) {
-		struct drbd_connection *connection = first_peer_device(device)->connection;
-
 		spin_lock_irq(&device->resource->req_lock);
 		if (resource->susp_fen && conn_lowest_conn(connection) >= C_CONNECTED) {
 			/* case2: The connection was established again: */
@@ -1294,8 +1302,8 @@ static void after_state_ch(struct drbd_d
 	 * which is unexpected. */
 	if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
 	    (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
-	    first_peer_device(device)->connection->agreed_pro_version >= 96 && get_ldev(device)) {
-		drbd_gen_and_send_sync_uuid(first_peer_device(device));
+	    connection->agreed_pro_version >= 96 && get_ldev(device)) {
+		drbd_gen_and_send_sync_uuid(peer_device);
 		put_ldev(device);
 	}
 
@@ -1309,8 +1317,8 @@ static void after_state_ch(struct drbd_d
 		atomic_set(&device->rs_pending_cnt, 0);
 		drbd_rs_cancel_all(device);
 
-		drbd_send_uuids(first_peer_device(device));
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_uuids(peer_device);
+		drbd_send_state(peer_device, ns);
 	}
 	/* No point in queuing send_bitmap if we don't have a connection
 	 * anymore, so check also the _current_ state, not only the new state
@@ -1335,7 +1343,7 @@ static void after_state_ch(struct drbd_d
 					set_bit(NEW_CUR_UUID, &device->flags);
 				} else {
 					drbd_uuid_new_current(device);
-					drbd_send_uuids(first_peer_device(device));
+					drbd_send_uuids(peer_device);
 				}
 			}
 			put_ldev(device);
@@ -1346,7 +1354,7 @@ static void after_state_ch(struct drbd_d
 		if (os.peer == R_SECONDARY && ns.peer == R_PRIMARY &&
 		    device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
 			drbd_uuid_new_current(device);
-			drbd_send_uuids(first_peer_device(device));
+			drbd_send_uuids(peer_device);
 		}
 		/* D_DISKLESS Peer becomes secondary */
 		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1373,16 +1381,16 @@ static void after_state_ch(struct drbd_d
 	/* Last part of the attaching process ... */
 	if (ns.conn >= C_CONNECTED &&
 	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
-		drbd_send_sizes(first_peer_device(device), 0, 0);  /* to start sync... */
-		drbd_send_uuids(first_peer_device(device));
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_sizes(peer_device, 0, 0);  /* to start sync... */
+		drbd_send_uuids(peer_device);
+		drbd_send_state(peer_device, ns);
 	}
 
 	/* We want to pause/continue resync, tell peer. */
 	if (ns.conn >= C_CONNECTED &&
 	     ((os.aftr_isp != ns.aftr_isp) ||
 	      (os.user_isp != ns.user_isp)))
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	/* In case one of the isp bits got set, suspend other devices. */
 	if ((!os.aftr_isp && !os.peer_isp && !os.user_isp) &&
@@ -1392,10 +1400,10 @@ static void after_state_ch(struct drbd_d
 	/* Make sure the peer gets informed about eventual state
 	   changes (ISP bits) while we were in WFReportParams. */
 	if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	/* We are in the progress to start a full sync... */
 	if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
@@ -1449,7 +1457,7 @@ static void after_state_ch(struct drbd_d
 					drbd_disk_str(device->state.disk));
 
 			if (ns.conn >= C_CONNECTED)
-				drbd_send_state(first_peer_device(device), ns);
+				drbd_send_state(peer_device, ns);
 
 			drbd_rs_cancel_all(device);
 
@@ -1473,7 +1481,7 @@ static void after_state_ch(struct drbd_d
 				 drbd_disk_str(device->state.disk));
 
 		if (ns.conn >= C_CONNECTED)
-			drbd_send_state(first_peer_device(device), ns);
+			drbd_send_state(peer_device, ns);
 		/* corresponding get_ldev in __drbd_set_state
 		 * this may finally trigger drbd_ldev_destroy. */
 		put_ldev(device);
@@ -1481,7 +1489,7 @@ static void after_state_ch(struct drbd_d
 
 	/* Notify peer that I had a local IO error, and did not detached.. */
 	if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT && ns.conn >= C_CONNECTED)
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	/* Disks got bigger while they were detached */
 	if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING &&
@@ -1499,14 +1507,14 @@ static void after_state_ch(struct drbd_d
 	/* sync target done with resync.  Explicitly notify peer, even though
 	 * it should (at least for non-empty resyncs) already know itself. */
 	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	/* Verify finished, or reached stop sector.  Peer did not know about
 	 * the stop sector, and we may even have changed the stop sector during
 	 * verify to interrupt/stop early.  Send the new state. */
 	if (os.conn == C_VERIFY_S && ns.conn == C_CONNECTED
 	&& verify_can_do_stop_sector(device))
-		drbd_send_state(first_peer_device(device), ns);
+		drbd_send_state(peer_device, ns);
 
 	/* This triggers bitmap writeout of potentially still unwritten pages
 	 * if the resync finished cleanly, or aborted because of peer disk
@@ -1563,7 +1571,7 @@ static int w_after_conn_state_ch(struct
 		old_conf = connection->net_conf;
 		connection->my_addr_len = 0;
 		connection->peer_addr_len = 0;
-		rcu_assign_pointer(connection->net_conf, NULL);
+		RCU_INIT_POINTER(connection->net_conf, NULL);
 		conn_free_crypto(connection);
 		mutex_unlock(&connection->resource->conf_update);
 
@@ -1599,7 +1607,7 @@ static int w_after_conn_state_ch(struct
 	return 0;
 }
 
-void conn_old_common_state(struct drbd_connection *connection, union drbd_state *pcs, enum chg_state_flags *pf)
+static void conn_old_common_state(struct drbd_connection *connection, union drbd_state *pcs, enum chg_state_flags *pf)
 {
 	enum chg_state_flags flags = ~0;
 	struct drbd_peer_device *peer_device;
@@ -1688,7 +1696,7 @@ conn_is_valid_transition(struct drbd_con
 	return rv;
 }
 
-void
+static void
 conn_set_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
 	       union drbd_state *pns_min, union drbd_state *pns_max, enum chg_state_flags flags)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/drbd_worker.c linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_worker.c
--- linux-libre-3.16-gnu/drivers/block/drbd/drbd_worker.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/drbd_worker.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,13 +67,10 @@ rwlock_t global_state_lock;
  */
 void drbd_md_io_complete(struct bio *bio, int error)
 {
-	struct drbd_md_io *md_io;
 	struct drbd_device *device;
 
-	md_io = (struct drbd_md_io *)bio->bi_private;
-	device = container_of(md_io, struct drbd_device, md_io);
-
-	md_io->error = error;
+	device = bio->bi_private;
+	device->md_io.error = error;
 
 	/* We grabbed an extra reference in _drbd_md_sync_page_io() to be able
 	 * to timeout on the lower level device, and eventually detach from it.
@@ -87,7 +84,7 @@ void drbd_md_io_complete(struct bio *bio
 	 * ASSERT(atomic_read(&device->md_io_in_use) == 1) there.
 	 */
 	drbd_md_put_buffer(device);
-	md_io->done = 1;
+	device->md_io.done = 1;
 	wake_up(&device->misc_wait);
 	bio_put(bio);
 	if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
@@ -135,6 +132,7 @@ void drbd_endio_write_sec_final(struct d
 	i = peer_req->i;
 	do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
 	block_id = peer_req->block_id;
+	peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
 
 	spin_lock_irqsave(&device->resource->req_lock, flags);
 	device->writ_cnt += peer_req->i.size >> 9;
@@ -398,9 +396,6 @@ static int read_for_csum(struct drbd_pee
 	if (!get_ldev(device))
 		return -EIO;
 
-	if (drbd_rs_should_slow_down(device, sector))
-		goto defer;
-
 	/* GFP_TRY, because if there is no memory available right now, this may
 	 * be rescheduled for later. It is "only" background resync, after all. */
 	peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER /* unused */, sector,
@@ -410,7 +405,7 @@ static int read_for_csum(struct drbd_pee
 
 	peer_req->w.cb = w_e_send_csum;
 	spin_lock_irq(&device->resource->req_lock);
-	list_add(&peer_req->w.list, &device->read_ee);
+	list_add_tail(&peer_req->w.list, &device->read_ee);
 	spin_unlock_irq(&device->resource->req_lock);
 
 	atomic_add(size >> 9, &device->rs_sect_ev);
@@ -452,9 +447,9 @@ void resync_timer_fn(unsigned long data)
 {
 	struct drbd_device *device = (struct drbd_device *) data;
 
-	if (list_empty(&device->resync_work.list))
-		drbd_queue_work(&first_peer_device(device)->connection->sender_work,
-				&device->resync_work);
+	drbd_queue_work_if_unqueued(
+		&first_peer_device(device)->connection->sender_work,
+		&device->resync_work);
 }
 
 static void fifo_set(struct fifo_buffer *fb, int value)
@@ -504,9 +499,9 @@ struct fifo_buffer *fifo_alloc(int fifo_
 static int drbd_rs_controller(struct drbd_device *device, unsigned int sect_in)
 {
 	struct disk_conf *dc;
-	unsigned int want;     /* The number of sectors we want in the proxy */
+	unsigned int want;     /* The number of sectors we want in-flight */
 	int req_sect; /* Number of sectors to request in this turn */
-	int correction; /* Number of sectors more we need in the proxy*/
+	int correction; /* Number of sectors more we need in-flight */
 	int cps; /* correction per invocation of drbd_rs_controller() */
 	int steps; /* Number of time steps to plan ahead */
 	int curr_corr;
@@ -577,20 +572,27 @@ static int drbd_rs_number_requests(struc
 	 * potentially causing a distributed deadlock on congestion during
 	 * online-verify or (checksum-based) resync, if max-buffers,
 	 * socket buffer sizes and resync rate settings are mis-configured. */
-	if (mxb - device->rs_in_flight < number)
-		number = mxb - device->rs_in_flight;
+
+	/* note that "number" is in units of "BM_BLOCK_SIZE" (which is 4k),
+	 * mxb (as used here, and in drbd_alloc_pages on the peer) is
+	 * "number of pages" (typically also 4k),
+	 * but "rs_in_flight" is in "sectors" (512 Byte). */
+	if (mxb - device->rs_in_flight/8 < number)
+		number = mxb - device->rs_in_flight/8;
 
 	return number;
 }
 
-static int make_resync_request(struct drbd_device *device, int cancel)
+static int make_resync_request(struct drbd_device *const device, int cancel)
 {
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
 	unsigned long bit;
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(device->this_bdev);
 	int max_bio_size;
 	int number, rollback_i, size;
-	int align, queued, sndbuf;
+	int align, requeue = 0;
 	int i = 0;
 
 	if (unlikely(cancel))
@@ -617,17 +619,22 @@ static int make_resync_request(struct dr
 		goto requeue;
 
 	for (i = 0; i < number; i++) {
-		/* Stop generating RS requests, when half of the send buffer is filled */
-		mutex_lock(&first_peer_device(device)->connection->data.mutex);
-		if (first_peer_device(device)->connection->data.socket) {
-			queued = first_peer_device(device)->connection->data.socket->sk->sk_wmem_queued;
-			sndbuf = first_peer_device(device)->connection->data.socket->sk->sk_sndbuf;
-		} else {
-			queued = 1;
-			sndbuf = 0;
-		}
-		mutex_unlock(&first_peer_device(device)->connection->data.mutex);
-		if (queued > sndbuf / 2)
+		/* Stop generating RS requests when half of the send buffer is filled,
+		 * but notify TCP that we'd like to have more space. */
+		mutex_lock(&connection->data.mutex);
+		if (connection->data.socket) {
+			struct sock *sk = connection->data.socket->sk;
+			int queued = sk->sk_wmem_queued;
+			int sndbuf = sk->sk_sndbuf;
+			if (queued > sndbuf / 2) {
+				requeue = 1;
+				if (sk->sk_socket)
+					set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+			}
+		} else
+			requeue = 1;
+		mutex_unlock(&connection->data.mutex);
+		if (requeue)
 			goto requeue;
 
 next_sector:
@@ -642,8 +649,7 @@ next_sector:
 
 		sector = BM_BIT_TO_SECT(bit);
 
-		if (drbd_rs_should_slow_down(device, sector) ||
-		    drbd_try_rs_begin_io(device, sector)) {
+		if (drbd_try_rs_begin_io(device, sector)) {
 			device->bm_resync_fo = bit;
 			goto requeue;
 		}
@@ -696,9 +702,9 @@ next_sector:
 		/* adjust very last sectors, in case we are oddly sized */
 		if (sector + (size>>9) > capacity)
 			size = (capacity-sector)<<9;
-		if (first_peer_device(device)->connection->agreed_pro_version >= 89 &&
-		    first_peer_device(device)->connection->csums_tfm) {
-			switch (read_for_csum(first_peer_device(device), sector, size)) {
+
+		if (device->use_csums) {
+			switch (read_for_csum(peer_device, sector, size)) {
 			case -EIO: /* Disk failure */
 				put_ldev(device);
 				return -EIO;
@@ -717,7 +723,7 @@ next_sector:
 			int err;
 
 			inc_rs_pending(device);
-			err = drbd_send_drequest(first_peer_device(device), P_RS_DATA_REQUEST,
+			err = drbd_send_drequest(peer_device, P_RS_DATA_REQUEST,
 						 sector, size, ID_SYNCER);
 			if (err) {
 				drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
@@ -774,8 +780,7 @@ static int make_ov_request(struct drbd_d
 
 		size = BM_BLOCK_SIZE;
 
-		if (drbd_rs_should_slow_down(device, sector) ||
-		    drbd_try_rs_begin_io(device, sector)) {
+		if (drbd_try_rs_begin_io(device, sector)) {
 			device->ov_position = sector;
 			goto requeue;
 		}
@@ -911,7 +916,7 @@ int drbd_resync_finished(struct drbd_dev
 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
 			khelper_cmd = "after-resync-target";
 
-		if (first_peer_device(device)->connection->csums_tfm && device->rs_total) {
+		if (device->use_csums && device->rs_total) {
 			const unsigned long s = device->rs_same_csum;
 			const unsigned long t = device->rs_total;
 			const int ratio =
@@ -1351,13 +1356,15 @@ int w_send_out_of_sync(struct drbd_work
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
 	struct drbd_device *device = req->device;
-	struct drbd_connection *connection = first_peer_device(device)->connection;
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *const connection = peer_device->connection;
 	int err;
 
 	if (unlikely(cancel)) {
 		req_mod(req, SEND_CANCELED);
 		return 0;
 	}
+	req->pre_send_jif = jiffies;
 
 	/* this time, no connection->send.current_epoch_writes++;
 	 * If it was sent, it was the closing barrier for the last
@@ -1365,7 +1372,7 @@ int w_send_out_of_sync(struct drbd_work
 	 * No more barriers will be sent, until we leave AHEAD mode again. */
 	maybe_send_barrier(connection, req->epoch);
 
-	err = drbd_send_out_of_sync(first_peer_device(device), req);
+	err = drbd_send_out_of_sync(peer_device, req);
 	req_mod(req, OOS_HANDED_TO_NETWORK);
 
 	return err;
@@ -1380,19 +1387,21 @@ int w_send_dblock(struct drbd_work *w, i
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
 	struct drbd_device *device = req->device;
-	struct drbd_connection *connection = first_peer_device(device)->connection;
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *connection = peer_device->connection;
 	int err;
 
 	if (unlikely(cancel)) {
 		req_mod(req, SEND_CANCELED);
 		return 0;
 	}
+	req->pre_send_jif = jiffies;
 
 	re_init_if_first_write(connection, req->epoch);
 	maybe_send_barrier(connection, req->epoch);
 	connection->send.current_epoch_writes++;
 
-	err = drbd_send_dblock(first_peer_device(device), req);
+	err = drbd_send_dblock(peer_device, req);
 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
 
 	return err;
@@ -1407,19 +1416,21 @@ int w_send_read_req(struct drbd_work *w,
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
 	struct drbd_device *device = req->device;
-	struct drbd_connection *connection = first_peer_device(device)->connection;
+	struct drbd_peer_device *const peer_device = first_peer_device(device);
+	struct drbd_connection *connection = peer_device->connection;
 	int err;
 
 	if (unlikely(cancel)) {
 		req_mod(req, SEND_CANCELED);
 		return 0;
 	}
+	req->pre_send_jif = jiffies;
 
 	/* Even read requests may close a write epoch,
 	 * if there was any yet. */
 	maybe_send_barrier(connection, req->epoch);
 
-	err = drbd_send_drequest(first_peer_device(device), P_DATA_REQUEST, req->i.sector, req->i.size,
+	err = drbd_send_drequest(peer_device, P_DATA_REQUEST, req->i.sector, req->i.size,
 				 (unsigned long)req);
 
 	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
@@ -1433,7 +1444,7 @@ int w_restart_disk_io(struct drbd_work *
 	struct drbd_device *device = req->device;
 
 	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
-		drbd_al_begin_io(device, &req->i, false);
+		drbd_al_begin_io(device, &req->i);
 
 	drbd_req_make_private_bio(req, req->master_bio);
 	req->private_bio->bi_bdev = device->ldev->backing_bdev;
@@ -1601,26 +1612,32 @@ void drbd_rs_controller_reset(struct drb
 void start_resync_timer_fn(unsigned long data)
 {
 	struct drbd_device *device = (struct drbd_device *) data;
-
-	drbd_queue_work(&first_peer_device(device)->connection->sender_work,
-			&device->start_resync_work);
+	drbd_device_post_work(device, RS_START);
 }
 
-int w_start_resync(struct drbd_work *w, int cancel)
+static void do_start_resync(struct drbd_device *device)
 {
-	struct drbd_device *device =
-		container_of(w, struct drbd_device, start_resync_work);
-
 	if (atomic_read(&device->unacked_cnt) || atomic_read(&device->rs_pending_cnt)) {
-		drbd_warn(device, "w_start_resync later...\n");
+		drbd_warn(device, "postponing start_resync ...\n");
 		device->start_resync_timer.expires = jiffies + HZ/10;
 		add_timer(&device->start_resync_timer);
-		return 0;
+		return;
 	}
 
 	drbd_start_resync(device, C_SYNC_SOURCE);
 	clear_bit(AHEAD_TO_SYNC_SOURCE, &device->flags);
-	return 0;
+}
+
+static bool use_checksum_based_resync(struct drbd_connection *connection, struct drbd_device *device)
+{
+	bool csums_after_crash_only;
+	rcu_read_lock();
+	csums_after_crash_only = rcu_dereference(connection->net_conf)->csums_after_crash_only;
+	rcu_read_unlock();
+	return connection->agreed_pro_version >= 89 &&		/* supported? */
+		connection->csums_tfm &&			/* configured? */
+		(csums_after_crash_only == 0			/* use for each resync? */
+		 || test_bit(CRASHED_PRIMARY, &device->flags));	/* or only after Primary crash? */
 }
 
 /**
@@ -1633,6 +1650,8 @@ int w_start_resync(struct drbd_work *w,
  */
 void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
 {
+	struct drbd_peer_device *peer_device = first_peer_device(device);
+	struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
 	union drbd_state ns;
 	int r;
 
@@ -1651,7 +1670,7 @@ void drbd_start_resync(struct drbd_devic
 			if (r > 0) {
 				drbd_info(device, "before-resync-target handler returned %d, "
 					 "dropping connection.\n", r);
-				conn_request_state(first_peer_device(device)->connection, NS(conn, C_DISCONNECTING), CS_HARD);
+				conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
 				return;
 			}
 		} else /* C_SYNC_SOURCE */ {
@@ -1664,7 +1683,7 @@ void drbd_start_resync(struct drbd_devic
 				} else {
 					drbd_info(device, "before-resync-source handler returned %d, "
 						 "dropping connection.\n", r);
-					conn_request_state(first_peer_device(device)->connection,
+					conn_request_state(connection,
 							   NS(conn, C_DISCONNECTING), CS_HARD);
 					return;
 				}
@@ -1672,7 +1691,7 @@ void drbd_start_resync(struct drbd_devic
 		}
 	}
 
-	if (current == first_peer_device(device)->connection->worker.task) {
+	if (current == connection->worker.task) {
 		/* The worker should not sleep waiting for state_mutex,
 		   that can take long */
 		if (!mutex_trylock(device->state_mutex)) {
@@ -1733,11 +1752,20 @@ void drbd_start_resync(struct drbd_devic
 			device->rs_mark_time[i] = now;
 		}
 		_drbd_pause_after(device);
+		/* Forget potentially stale cached per resync extent bit-counts.
+		 * Open coded drbd_rs_cancel_all(device), we already have IRQs
+		 * disabled, and know the disk state is ok. */
+		spin_lock(&device->al_lock);
+		lc_reset(device->resync);
+		device->resync_locked = 0;
+		device->resync_wenr = LC_FREE;
+		spin_unlock(&device->al_lock);
 	}
 	write_unlock(&global_state_lock);
 	spin_unlock_irq(&device->resource->req_lock);
 
 	if (r == SS_SUCCESS) {
+		wake_up(&device->al_wait); /* for lc_reset() above */
 		/* reset rs_last_bcast when a resync or verify is started,
 		 * to deal with potential jiffies wrap. */
 		device->rs_last_bcast = jiffies - HZ;
@@ -1746,8 +1774,12 @@ void drbd_start_resync(struct drbd_devic
 		     drbd_conn_str(ns.conn),
 		     (unsigned long) device->rs_total << (BM_BLOCK_SHIFT-10),
 		     (unsigned long) device->rs_total);
-		if (side == C_SYNC_TARGET)
+		if (side == C_SYNC_TARGET) {
 			device->bm_resync_fo = 0;
+			device->use_csums = use_checksum_based_resync(connection, device);
+		} else {
+			device->use_csums = 0;
+		}
 
 		/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
 		 * with w_send_oos, or the sync target will get confused as to
@@ -1756,12 +1788,10 @@ void drbd_start_resync(struct drbd_devic
 		 * drbd_resync_finished from here in that case.
 		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
 		 * and from after_state_ch otherwise. */
-		if (side == C_SYNC_SOURCE &&
-		    first_peer_device(device)->connection->agreed_pro_version < 96)
-			drbd_gen_and_send_sync_uuid(first_peer_device(device));
+		if (side == C_SYNC_SOURCE && connection->agreed_pro_version < 96)
+			drbd_gen_and_send_sync_uuid(peer_device);
 
-		if (first_peer_device(device)->connection->agreed_pro_version < 95 &&
-		    device->rs_total == 0) {
+		if (connection->agreed_pro_version < 95 && device->rs_total == 0) {
 			/* This still has a race (about when exactly the peers
 			 * detect connection loss) that can lead to a full sync
 			 * on next handshake. In 8.3.9 we fixed this with explicit
@@ -1777,7 +1807,7 @@ void drbd_start_resync(struct drbd_devic
 				int timeo;
 
 				rcu_read_lock();
-				nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+				nc = rcu_dereference(connection->net_conf);
 				timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
 				rcu_read_unlock();
 				schedule_timeout_interruptible(timeo);
@@ -1799,10 +1829,165 @@ void drbd_start_resync(struct drbd_devic
 	mutex_unlock(device->state_mutex);
 }
 
+static void update_on_disk_bitmap(struct drbd_device *device, bool resync_done)
+{
+	struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
+	device->rs_last_bcast = jiffies;
+
+	if (!get_ldev(device))
+		return;
+
+	drbd_bm_write_lazy(device, 0);
+	if (resync_done && is_sync_state(device->state.conn))
+		drbd_resync_finished(device);
+
+	drbd_bcast_event(device, &sib);
+	/* update timestamp, in case it took a while to write out stuff */
+	device->rs_last_bcast = jiffies;
+	put_ldev(device);
+}
+
+static void drbd_ldev_destroy(struct drbd_device *device)
+{
+	lc_destroy(device->resync);
+	device->resync = NULL;
+	lc_destroy(device->act_log);
+	device->act_log = NULL;
+	__no_warn(local,
+		drbd_free_ldev(device->ldev);
+		device->ldev = NULL;);
+	clear_bit(GOING_DISKLESS, &device->flags);
+	wake_up(&device->misc_wait);
+}
+
+static void go_diskless(struct drbd_device *device)
+{
+	D_ASSERT(device, device->state.disk == D_FAILED);
+	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
+	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
+	 * the protected members anymore, though, so once put_ldev reaches zero
+	 * again, it will be safe to free them. */
+
+	/* Try to write changed bitmap pages, read errors may have just
+	 * set some bits outside the area covered by the activity log.
+	 *
+	 * If we have an IO error during the bitmap writeout,
+	 * we will want a full sync next time, just in case.
+	 * (Do we want a specific meta data flag for this?)
+	 *
+	 * If that does not make it to stable storage either,
+	 * we cannot do anything about that anymore.
+	 *
+	 * We still need to check if both bitmap and ldev are present, we may
+	 * end up here after a failed attach, before ldev was even assigned.
+	 */
+	if (device->bitmap && device->ldev) {
+		/* An interrupted resync or similar is allowed to recounts bits
+		 * while we detach.
+		 * Any modifications would not be expected anymore, though.
+		 */
+		if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
+					"detach", BM_LOCKED_TEST_ALLOWED)) {
+			if (test_bit(WAS_READ_ERROR, &device->flags)) {
+				drbd_md_set_flag(device, MDF_FULL_SYNC);
+				drbd_md_sync(device);
+			}
+		}
+	}
+
+	drbd_force_state(device, NS(disk, D_DISKLESS));
+}
+
+static int do_md_sync(struct drbd_device *device)
+{
+	drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+	drbd_md_sync(device);
+	return 0;
+}
+
+/* only called from drbd_worker thread, no locking */
+void __update_timing_details(
+		struct drbd_thread_timing_details *tdp,
+		unsigned int *cb_nr,
+		void *cb,
+		const char *fn, const unsigned int line)
+{
+	unsigned int i = *cb_nr % DRBD_THREAD_DETAILS_HIST;
+	struct drbd_thread_timing_details *td = tdp + i;
+
+	td->start_jif = jiffies;
+	td->cb_addr = cb;
+	td->caller_fn = fn;
+	td->line = line;
+	td->cb_nr = *cb_nr;
+
+	i = (i+1) % DRBD_THREAD_DETAILS_HIST;
+	td = tdp + i;
+	memset(td, 0, sizeof(*td));
+
+	++(*cb_nr);
+}
+
+#define WORK_PENDING(work_bit, todo)	(todo & (1UL << work_bit))
+static void do_device_work(struct drbd_device *device, const unsigned long todo)
+{
+	if (WORK_PENDING(MD_SYNC, todo))
+		do_md_sync(device);
+	if (WORK_PENDING(RS_DONE, todo) ||
+	    WORK_PENDING(RS_PROGRESS, todo))
+		update_on_disk_bitmap(device, WORK_PENDING(RS_DONE, todo));
+	if (WORK_PENDING(GO_DISKLESS, todo))
+		go_diskless(device);
+	if (WORK_PENDING(DESTROY_DISK, todo))
+		drbd_ldev_destroy(device);
+	if (WORK_PENDING(RS_START, todo))
+		do_start_resync(device);
+}
+
+#define DRBD_DEVICE_WORK_MASK	\
+	((1UL << GO_DISKLESS)	\
+	|(1UL << DESTROY_DISK)	\
+	|(1UL << MD_SYNC)	\
+	|(1UL << RS_START)	\
+	|(1UL << RS_PROGRESS)	\
+	|(1UL << RS_DONE)	\
+	)
+
+static unsigned long get_work_bits(unsigned long *flags)
+{
+	unsigned long old, new;
+	do {
+		old = *flags;
+		new = old & ~DRBD_DEVICE_WORK_MASK;
+	} while (cmpxchg(flags, old, new) != old);
+	return old & DRBD_DEVICE_WORK_MASK;
+}
+
+static void do_unqueued_work(struct drbd_connection *connection)
+{
+	struct drbd_peer_device *peer_device;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+		struct drbd_device *device = peer_device->device;
+		unsigned long todo = get_work_bits(&device->flags);
+		if (!todo)
+			continue;
+
+		kref_get(&device->kref);
+		rcu_read_unlock();
+		do_device_work(device, todo);
+		kref_put(&device->kref, drbd_destroy_device);
+		rcu_read_lock();
+	}
+	rcu_read_unlock();
+}
+
 static bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
 {
 	spin_lock_irq(&queue->q_lock);
-	list_splice_init(&queue->q, work_list);
+	list_splice_tail_init(&queue->q, work_list);
 	spin_unlock_irq(&queue->q_lock);
 	return !list_empty(work_list);
 }
@@ -1851,7 +2036,7 @@ static void wait_for_work(struct drbd_co
 		/* dequeue single item only,
 		 * we still use drbd_queue_work_front() in some places */
 		if (!list_empty(&connection->sender_work.q))
-			list_move(connection->sender_work.q.next, work_list);
+			list_splice_tail_init(&connection->sender_work.q, work_list);
 		spin_unlock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
 		if (!list_empty(work_list) || signal_pending(current)) {
 			spin_unlock_irq(&connection->resource->req_lock);
@@ -1873,6 +2058,14 @@ static void wait_for_work(struct drbd_co
 		if (send_barrier)
 			maybe_send_barrier(connection,
 					connection->send.current_epoch_nr + 1);
+
+		if (test_bit(DEVICE_WORK_PENDING, &connection->flags))
+			break;
+
+		/* drbd_send() may have called flush_signals() */
+		if (get_t_state(&connection->worker) != RUNNING)
+			break;
+
 		schedule();
 		/* may be woken up for other things but new work, too,
 		 * e.g. if the current epoch got closed.
@@ -1906,10 +2099,15 @@ int drbd_worker(struct drbd_thread *thi)
 	while (get_t_state(thi) == RUNNING) {
 		drbd_thread_current_set_cpu(thi);
 
-		/* as long as we use drbd_queue_work_front(),
-		 * we may only dequeue single work items here, not batches. */
-		if (list_empty(&work_list))
+		if (list_empty(&work_list)) {
+			update_worker_timing_details(connection, wait_for_work);
 			wait_for_work(connection, &work_list);
+		}
+
+		if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
+			update_worker_timing_details(connection, do_unqueued_work);
+			do_unqueued_work(connection);
+		}
 
 		if (signal_pending(current)) {
 			flush_signals(current);
@@ -1926,6 +2124,7 @@ int drbd_worker(struct drbd_thread *thi)
 		while (!list_empty(&work_list)) {
 			w = list_first_entry(&work_list, struct drbd_work, list);
 			list_del_init(&w->list);
+			update_worker_timing_details(connection, w->cb);
 			if (w->cb(w, connection->cstate < C_WF_REPORT_PARAMS) == 0)
 				continue;
 			if (connection->cstate >= C_WF_REPORT_PARAMS)
@@ -1934,13 +2133,18 @@ int drbd_worker(struct drbd_thread *thi)
 	}
 
 	do {
+		if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
+			update_worker_timing_details(connection, do_unqueued_work);
+			do_unqueued_work(connection);
+		}
 		while (!list_empty(&work_list)) {
 			w = list_first_entry(&work_list, struct drbd_work, list);
 			list_del_init(&w->list);
+			update_worker_timing_details(connection, w->cb);
 			w->cb(w, 1);
 		}
 		dequeue_work_batch(&connection->sender_work, &work_list);
-	} while (!list_empty(&work_list));
+	} while (!list_empty(&work_list) || test_bit(DEVICE_WORK_PENDING, &connection->flags));
 
 	rcu_read_lock();
 	idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/drbd/Makefile linux-libre-3.17-rc7-gnu/drivers/block/drbd/Makefile
--- linux-libre-3.16-gnu/drivers/block/drbd/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/drbd/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,5 +3,6 @@ drbd-y += drbd_worker.o drbd_receiver.o
 drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
 drbd-y += drbd_interval.o drbd_state.o
 drbd-y += drbd_nla.o
+drbd-$(CONFIG_DEBUG_FS) += drbd_debugfs.o
 
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/mtip32xx/mtip32xx.c linux-libre-3.17-rc7-gnu/drivers/block/mtip32xx/mtip32xx.c
--- linux-libre-3.16-gnu/drivers/block/mtip32xx/mtip32xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/mtip32xx/mtip32xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -3918,7 +3918,6 @@ skip_create_disk:
 	if (rv) {
 		dev_err(&dd->pdev->dev,
 			"Unable to allocate request queue\n");
-		rv = -ENOMEM;
 		goto block_queue_alloc_init_error;
 	}
 
@@ -4632,7 +4631,7 @@ static void mtip_pci_shutdown(struct pci
 }
 
 /* Table of device ids supported by this driver. */
-static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
+static const struct pci_device_id mtip_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/null_blk.c linux-libre-3.17-rc7-gnu/drivers/block/null_blk.c
--- linux-libre-3.16-gnu/drivers/block/null_blk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/null_blk.c	2014-09-28 17:29:07.000000000 -0400
@@ -462,17 +462,21 @@ static int null_add_dev(void)
 	struct gendisk *disk;
 	struct nullb *nullb;
 	sector_t size;
+	int rv;
 
 	nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node);
-	if (!nullb)
+	if (!nullb) {
+		rv = -ENOMEM;
 		goto out;
+	}
 
 	spin_lock_init(&nullb->lock);
 
 	if (queue_mode == NULL_Q_MQ && use_per_node_hctx)
 		submit_queues = nr_online_nodes;
 
-	if (setup_queues(nullb))
+	rv = setup_queues(nullb);
+	if (rv)
 		goto out_free_nullb;
 
 	if (queue_mode == NULL_Q_MQ) {
@@ -484,22 +488,29 @@ static int null_add_dev(void)
 		nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
 		nullb->tag_set.driver_data = nullb;
 
-		if (blk_mq_alloc_tag_set(&nullb->tag_set))
+		rv = blk_mq_alloc_tag_set(&nullb->tag_set);
+		if (rv)
 			goto out_cleanup_queues;
 
 		nullb->q = blk_mq_init_queue(&nullb->tag_set);
-		if (!nullb->q)
+		if (!nullb->q) {
+			rv = -ENOMEM;
 			goto out_cleanup_tags;
+		}
 	} else if (queue_mode == NULL_Q_BIO) {
 		nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
-		if (!nullb->q)
+		if (!nullb->q) {
+			rv = -ENOMEM;
 			goto out_cleanup_queues;
+		}
 		blk_queue_make_request(nullb->q, null_queue_bio);
 		init_driver_queues(nullb);
 	} else {
 		nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
-		if (!nullb->q)
+		if (!nullb->q) {
+			rv = -ENOMEM;
 			goto out_cleanup_queues;
+		}
 		blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
 		blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
 		init_driver_queues(nullb);
@@ -509,8 +520,10 @@ static int null_add_dev(void)
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
 
 	disk = nullb->disk = alloc_disk_node(1, home_node);
-	if (!disk)
+	if (!disk) {
+		rv = -ENOMEM;
 		goto out_cleanup_blk_queue;
+	}
 
 	mutex_lock(&lock);
 	list_add_tail(&nullb->list, &nullb_list);
@@ -544,7 +557,7 @@ out_cleanup_queues:
 out_free_nullb:
 	kfree(nullb);
 out:
-	return -ENOMEM;
+	return rv;
 }
 
 static int __init null_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/rbd.c linux-libre-3.17-rc7-gnu/drivers/block/rbd.c
--- linux-libre-3.16-gnu/drivers/block/rbd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/rbd.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,7 @@
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include "rbd_types.h"
 
@@ -332,7 +333,10 @@ struct rbd_device {
 
 	char			name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
 
+	struct list_head	rq_queue;	/* incoming rq queue */
 	spinlock_t		lock;		/* queue, flags, open_count */
+	struct workqueue_struct	*rq_wq;
+	struct work_struct	rq_work;
 
 	struct rbd_image_header	header;
 	unsigned long		flags;		/* possibly lock protected */
@@ -514,7 +518,8 @@ static void rbd_dev_remove_parent(struct
 
 static int rbd_dev_refresh(struct rbd_device *rbd_dev);
 static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
-static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev);
+static int rbd_dev_header_info(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
 static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
 					u64 snap_id);
 static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -971,12 +976,6 @@ static int rbd_header_from_disk(struct r
 	header->snap_names = snap_names;
 	header->snap_sizes = snap_sizes;
 
-	/* Make sure mapping size is consistent with header info */
-
-	if (rbd_dev->spec->snap_id == CEPH_NOSNAP || first_time)
-		if (rbd_dev->mapping.size != header->image_size)
-			rbd_dev->mapping.size = header->image_size;
-
 	return 0;
 out_2big:
 	ret = -EIO;
@@ -1139,6 +1138,13 @@ static void rbd_dev_mapping_clear(struct
 	rbd_dev->mapping.features = 0;
 }
 
+static void rbd_segment_name_free(const char *name)
+{
+	/* The explicit cast here is needed to drop the const qualifier */
+
+	kmem_cache_free(rbd_segment_name_cache, (void *)name);
+}
+
 static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
 {
 	char *name;
@@ -1158,20 +1164,13 @@ static const char *rbd_segment_name(stru
 	if (ret < 0 || ret > CEPH_MAX_OID_NAME_LEN) {
 		pr_err("error formatting segment name for #%llu (%d)\n",
 			segment, ret);
-		kfree(name);
+		rbd_segment_name_free(name);
 		name = NULL;
 	}
 
 	return name;
 }
 
-static void rbd_segment_name_free(const char *name)
-{
-	/* The explicit cast here is needed to drop the const qualifier */
-
-	kmem_cache_free(rbd_segment_name_cache, (void *)name);
-}
-
 static u64 rbd_segment_offset(struct rbd_device *rbd_dev, u64 offset)
 {
 	u64 segment_size = (u64) 1 << rbd_dev->header.obj_order;
@@ -1371,7 +1370,7 @@ static void obj_request_img_data_set(str
 		struct rbd_device *rbd_dev;
 
 		rbd_dev = obj_request->img_request->rbd_dev;
-		rbd_warn(rbd_dev, "obj_request %p already marked img_data\n",
+		rbd_warn(rbd_dev, "obj_request %p already marked img_data",
 			obj_request);
 	}
 }
@@ -1389,7 +1388,7 @@ static void obj_request_done_set(struct
 
 		if (obj_request_img_data_test(obj_request))
 			rbd_dev = obj_request->img_request->rbd_dev;
-		rbd_warn(rbd_dev, "obj_request %p already marked done\n",
+		rbd_warn(rbd_dev, "obj_request %p already marked done",
 			obj_request);
 	}
 }
@@ -1527,11 +1526,37 @@ static bool obj_request_type_valid(enum
 static int rbd_obj_request_submit(struct ceph_osd_client *osdc,
 				struct rbd_obj_request *obj_request)
 {
-	dout("%s: osdc %p obj %p\n", __func__, osdc, obj_request);
-
+	dout("%s %p\n", __func__, obj_request);
 	return ceph_osdc_start_request(osdc, obj_request->osd_req, false);
 }
 
+static void rbd_obj_request_end(struct rbd_obj_request *obj_request)
+{
+	dout("%s %p\n", __func__, obj_request);
+	ceph_osdc_cancel_request(obj_request->osd_req);
+}
+
+/*
+ * Wait for an object request to complete.  If interrupted, cancel the
+ * underlying osd request.
+ */
+static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
+{
+	int ret;
+
+	dout("%s %p\n", __func__, obj_request);
+
+	ret = wait_for_completion_interruptible(&obj_request->completion);
+	if (ret < 0) {
+		dout("%s %p interrupted\n", __func__, obj_request);
+		rbd_obj_request_end(obj_request);
+		return ret;
+	}
+
+	dout("%s %p done\n", __func__, obj_request);
+	return 0;
+}
+
 static void rbd_img_request_complete(struct rbd_img_request *img_request)
 {
 
@@ -1558,15 +1583,6 @@ static void rbd_img_request_complete(str
 		rbd_img_request_put(img_request);
 }
 
-/* Caller is responsible for rbd_obj_request_destroy(obj_request) */
-
-static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
-{
-	dout("%s: obj %p\n", __func__, obj_request);
-
-	return wait_for_completion_interruptible(&obj_request->completion);
-}
-
 /*
  * The default/initial value for all image request flags is 0.  Each
  * is conditionally set to 1 at image request initialization time
@@ -1763,7 +1779,7 @@ static void rbd_osd_req_callback(struct
 		rbd_osd_trivial_callback(obj_request);
 		break;
 	default:
-		rbd_warn(NULL, "%s: unsupported op %hu\n",
+		rbd_warn(NULL, "%s: unsupported op %hu",
 			obj_request->object_name, (unsigned short) opcode);
 		break;
 	}
@@ -1998,7 +2014,7 @@ static void rbd_dev_parent_put(struct rb
 	if (!counter)
 		rbd_dev_unparent(rbd_dev);
 	else
-		rbd_warn(rbd_dev, "parent reference underflow\n");
+		rbd_warn(rbd_dev, "parent reference underflow");
 }
 
 /*
@@ -2028,7 +2044,7 @@ static bool rbd_dev_parent_get(struct rb
 	/* Image was flattened, but parent is not yet torn down */
 
 	if (counter < 0)
-		rbd_warn(rbd_dev, "parent reference overflow\n");
+		rbd_warn(rbd_dev, "parent reference overflow");
 
 	return false;
 }
@@ -2045,7 +2061,7 @@ static struct rbd_img_request *rbd_img_r
 {
 	struct rbd_img_request *img_request;
 
-	img_request = kmem_cache_alloc(rbd_img_request_cache, GFP_ATOMIC);
+	img_request = kmem_cache_alloc(rbd_img_request_cache, GFP_NOIO);
 	if (!img_request)
 		return NULL;
 
@@ -2161,11 +2177,11 @@ static bool rbd_img_obj_end_request(stru
 	if (result) {
 		struct rbd_device *rbd_dev = img_request->rbd_dev;
 
-		rbd_warn(rbd_dev, "%s %llx at %llx (%llx)\n",
+		rbd_warn(rbd_dev, "%s %llx at %llx (%llx)",
 			img_request_write_test(img_request) ? "write" : "read",
 			obj_request->length, obj_request->img_offset,
 			obj_request->offset);
-		rbd_warn(rbd_dev, "  result %d xferred %x\n",
+		rbd_warn(rbd_dev, "  result %d xferred %x",
 			result, xferred);
 		if (!img_request->result)
 			img_request->result = result;
@@ -2946,154 +2962,135 @@ static void rbd_watch_cb(u64 ver, u64 no
 	dout("%s: \"%s\" notify_id %llu opcode %u\n", __func__,
 		rbd_dev->header_name, (unsigned long long)notify_id,
 		(unsigned int)opcode);
+
+	/*
+	 * Until adequate refresh error handling is in place, there is
+	 * not much we can do here, except warn.
+	 *
+	 * See http://tracker.ceph.com/issues/5040
+	 */
 	ret = rbd_dev_refresh(rbd_dev);
 	if (ret)
-		rbd_warn(rbd_dev, "header refresh error (%d)\n", ret);
+		rbd_warn(rbd_dev, "refresh failed: %d", ret);
 
-	rbd_obj_notify_ack_sync(rbd_dev, notify_id);
+	ret = rbd_obj_notify_ack_sync(rbd_dev, notify_id);
+	if (ret)
+		rbd_warn(rbd_dev, "notify_ack ret %d", ret);
 }
 
 /*
- * Initiate a watch request, synchronously.
+ * Send a (un)watch request and wait for the ack.  Return a request
+ * with a ref held on success or error.
  */
-static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
+static struct rbd_obj_request *rbd_obj_watch_request_helper(
+						struct rbd_device *rbd_dev,
+						bool watch)
 {
 	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
 	struct rbd_obj_request *obj_request;
 	int ret;
 
-	rbd_assert(!rbd_dev->watch_event);
-	rbd_assert(!rbd_dev->watch_request);
-
-	ret = ceph_osdc_create_event(osdc, rbd_watch_cb, rbd_dev,
-				     &rbd_dev->watch_event);
-	if (ret < 0)
-		return ret;
-
-	rbd_assert(rbd_dev->watch_event);
-
 	obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
 					     OBJ_REQUEST_NODATA);
-	if (!obj_request) {
-		ret = -ENOMEM;
-		goto out_cancel;
-	}
+	if (!obj_request)
+		return ERR_PTR(-ENOMEM);
 
 	obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1,
 						  obj_request);
 	if (!obj_request->osd_req) {
 		ret = -ENOMEM;
-		goto out_put;
+		goto out;
 	}
 
-	ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
-
 	osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
-			      rbd_dev->watch_event->cookie, 0, 1);
+			      rbd_dev->watch_event->cookie, 0, watch);
 	rbd_osd_req_format_write(obj_request);
 
+	if (watch)
+		ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
+
 	ret = rbd_obj_request_submit(osdc, obj_request);
 	if (ret)
-		goto out_linger;
+		goto out;
 
 	ret = rbd_obj_request_wait(obj_request);
 	if (ret)
-		goto out_linger;
+		goto out;
 
 	ret = obj_request->result;
-	if (ret)
-		goto out_linger;
-
-	/*
-	 * A watch request is set to linger, so the underlying osd
-	 * request won't go away until we unregister it.  We retain
-	 * a pointer to the object request during that time (in
-	 * rbd_dev->watch_request), so we'll keep a reference to
-	 * it.  We'll drop that reference (below) after we've
-	 * unregistered it.
-	 */
-	rbd_dev->watch_request = obj_request;
+	if (ret) {
+		if (watch)
+			rbd_obj_request_end(obj_request);
+		goto out;
+	}
 
-	return 0;
+	return obj_request;
 
-out_linger:
-	ceph_osdc_unregister_linger_request(osdc, obj_request->osd_req);
-out_put:
+out:
 	rbd_obj_request_put(obj_request);
-out_cancel:
-	ceph_osdc_cancel_event(rbd_dev->watch_event);
-	rbd_dev->watch_event = NULL;
-
-	return ret;
+	return ERR_PTR(ret);
 }
 
 /*
- * Tear down a watch request, synchronously.
+ * Initiate a watch request, synchronously.
  */
-static int __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
 {
 	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
 	struct rbd_obj_request *obj_request;
 	int ret;
 
-	rbd_assert(rbd_dev->watch_event);
-	rbd_assert(rbd_dev->watch_request);
+	rbd_assert(!rbd_dev->watch_event);
+	rbd_assert(!rbd_dev->watch_request);
 
-	obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
-					     OBJ_REQUEST_NODATA);
-	if (!obj_request) {
-		ret = -ENOMEM;
-		goto out_cancel;
-	}
+	ret = ceph_osdc_create_event(osdc, rbd_watch_cb, rbd_dev,
+				     &rbd_dev->watch_event);
+	if (ret < 0)
+		return ret;
 
-	obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1,
-						  obj_request);
-	if (!obj_request->osd_req) {
-		ret = -ENOMEM;
-		goto out_put;
+	obj_request = rbd_obj_watch_request_helper(rbd_dev, true);
+	if (IS_ERR(obj_request)) {
+		ceph_osdc_cancel_event(rbd_dev->watch_event);
+		rbd_dev->watch_event = NULL;
+		return PTR_ERR(obj_request);
 	}
 
-	osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
-			      rbd_dev->watch_event->cookie, 0, 0);
-	rbd_osd_req_format_write(obj_request);
-
-	ret = rbd_obj_request_submit(osdc, obj_request);
-	if (ret)
-		goto out_put;
+	/*
+	 * A watch request is set to linger, so the underlying osd
+	 * request won't go away until we unregister it.  We retain
+	 * a pointer to the object request during that time (in
+	 * rbd_dev->watch_request), so we'll keep a reference to it.
+	 * We'll drop that reference after we've unregistered it in
+	 * rbd_dev_header_unwatch_sync().
+	 */
+	rbd_dev->watch_request = obj_request;
 
-	ret = rbd_obj_request_wait(obj_request);
-	if (ret)
-		goto out_put;
+	return 0;
+}
 
-	ret = obj_request->result;
-	if (ret)
-		goto out_put;
+/*
+ * Tear down a watch request, synchronously.
+ */
+static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+{
+	struct rbd_obj_request *obj_request;
 
-	/* We have successfully torn down the watch request */
+	rbd_assert(rbd_dev->watch_event);
+	rbd_assert(rbd_dev->watch_request);
 
-	ceph_osdc_unregister_linger_request(osdc,
-					    rbd_dev->watch_request->osd_req);
+	rbd_obj_request_end(rbd_dev->watch_request);
 	rbd_obj_request_put(rbd_dev->watch_request);
 	rbd_dev->watch_request = NULL;
 
-out_put:
-	rbd_obj_request_put(obj_request);
-out_cancel:
+	obj_request = rbd_obj_watch_request_helper(rbd_dev, false);
+	if (!IS_ERR(obj_request))
+		rbd_obj_request_put(obj_request);
+	else
+		rbd_warn(rbd_dev, "unable to tear down watch request (%ld)",
+			 PTR_ERR(obj_request));
+
 	ceph_osdc_cancel_event(rbd_dev->watch_event);
 	rbd_dev->watch_event = NULL;
-
-	return ret;
-}
-
-static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
-{
-	int ret;
-
-	ret = __rbd_dev_header_unwatch_sync(rbd_dev);
-	if (ret) {
-		rbd_warn(rbd_dev, "unable to tear down watch request: %d\n",
-			 ret);
-	}
 }
 
 /*
@@ -3183,102 +3180,129 @@ out:
 	return ret;
 }
 
-static void rbd_request_fn(struct request_queue *q)
-		__releases(q->queue_lock) __acquires(q->queue_lock)
+static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq)
 {
-	struct rbd_device *rbd_dev = q->queuedata;
-	struct request *rq;
+	struct rbd_img_request *img_request;
+	u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
+	u64 length = blk_rq_bytes(rq);
+	bool wr = rq_data_dir(rq) == WRITE;
 	int result;
 
-	while ((rq = blk_fetch_request(q))) {
-		bool write_request = rq_data_dir(rq) == WRITE;
-		struct rbd_img_request *img_request;
-		u64 offset;
-		u64 length;
+	/* Ignore/skip any zero-length requests */
 
-		/* Ignore any non-FS requests that filter through. */
+	if (!length) {
+		dout("%s: zero-length request\n", __func__);
+		result = 0;
+		goto err_rq;
+	}
 
-		if (rq->cmd_type != REQ_TYPE_FS) {
-			dout("%s: non-fs request type %d\n", __func__,
-				(int) rq->cmd_type);
-			__blk_end_request_all(rq, 0);
-			continue;
+	/* Disallow writes to a read-only device */
+
+	if (wr) {
+		if (rbd_dev->mapping.read_only) {
+			result = -EROFS;
+			goto err_rq;
 		}
+		rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
+	}
 
-		/* Ignore/skip any zero-length requests */
+	/*
+	 * Quit early if the mapped snapshot no longer exists.  It's
+	 * still possible the snapshot will have disappeared by the
+	 * time our request arrives at the osd, but there's no sense in
+	 * sending it if we already know.
+	 */
+	if (!test_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags)) {
+		dout("request for non-existent snapshot");
+		rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
+		result = -ENXIO;
+		goto err_rq;
+	}
 
-		offset = (u64) blk_rq_pos(rq) << SECTOR_SHIFT;
-		length = (u64) blk_rq_bytes(rq);
+	if (offset && length > U64_MAX - offset + 1) {
+		rbd_warn(rbd_dev, "bad request range (%llu~%llu)", offset,
+			 length);
+		result = -EINVAL;
+		goto err_rq;	/* Shouldn't happen */
+	}
 
-		if (!length) {
-			dout("%s: zero-length request\n", __func__);
-			__blk_end_request_all(rq, 0);
-			continue;
-		}
+	if (offset + length > rbd_dev->mapping.size) {
+		rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset,
+			 length, rbd_dev->mapping.size);
+		result = -EIO;
+		goto err_rq;
+	}
 
-		spin_unlock_irq(q->queue_lock);
+	img_request = rbd_img_request_create(rbd_dev, offset, length, wr);
+	if (!img_request) {
+		result = -ENOMEM;
+		goto err_rq;
+	}
+	img_request->rq = rq;
 
-		/* Disallow writes to a read-only device */
+	result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, rq->bio);
+	if (result)
+		goto err_img_request;
 
-		if (write_request) {
-			result = -EROFS;
-			if (rbd_dev->mapping.read_only)
-				goto end_request;
-			rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
-		}
+	result = rbd_img_request_submit(img_request);
+	if (result)
+		goto err_img_request;
 
-		/*
-		 * Quit early if the mapped snapshot no longer
-		 * exists.  It's still possible the snapshot will
-		 * have disappeared by the time our request arrives
-		 * at the osd, but there's no sense in sending it if
-		 * we already know.
-		 */
-		if (!test_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags)) {
-			dout("request for non-existent snapshot");
-			rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
-			result = -ENXIO;
-			goto end_request;
-		}
+	return;
 
-		result = -EINVAL;
-		if (offset && length > U64_MAX - offset + 1) {
-			rbd_warn(rbd_dev, "bad request range (%llu~%llu)\n",
-				offset, length);
-			goto end_request;	/* Shouldn't happen */
-		}
+err_img_request:
+	rbd_img_request_put(img_request);
+err_rq:
+	if (result)
+		rbd_warn(rbd_dev, "%s %llx at %llx result %d",
+			 wr ? "write" : "read", length, offset, result);
+	blk_end_request_all(rq, result);
+}
 
-		result = -EIO;
-		if (offset + length > rbd_dev->mapping.size) {
-			rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)\n",
-				offset, length, rbd_dev->mapping.size);
-			goto end_request;
-		}
+static void rbd_request_workfn(struct work_struct *work)
+{
+	struct rbd_device *rbd_dev =
+	    container_of(work, struct rbd_device, rq_work);
+	struct request *rq, *next;
+	LIST_HEAD(requests);
 
-		result = -ENOMEM;
-		img_request = rbd_img_request_create(rbd_dev, offset, length,
-							write_request);
-		if (!img_request)
-			goto end_request;
+	spin_lock_irq(&rbd_dev->lock); /* rq->q->queue_lock */
+	list_splice_init(&rbd_dev->rq_queue, &requests);
+	spin_unlock_irq(&rbd_dev->lock);
 
-		img_request->rq = rq;
+	list_for_each_entry_safe(rq, next, &requests, queuelist) {
+		list_del_init(&rq->queuelist);
+		rbd_handle_request(rbd_dev, rq);
+	}
+}
 
-		result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
-						rq->bio);
-		if (!result)
-			result = rbd_img_request_submit(img_request);
-		if (result)
-			rbd_img_request_put(img_request);
-end_request:
-		spin_lock_irq(q->queue_lock);
-		if (result < 0) {
-			rbd_warn(rbd_dev, "%s %llx at %llx result %d\n",
-				write_request ? "write" : "read",
-				length, offset, result);
+/*
+ * Called with q->queue_lock held and interrupts disabled, possibly on
+ * the way to schedule().  Do not sleep here!
+ */
+static void rbd_request_fn(struct request_queue *q)
+{
+	struct rbd_device *rbd_dev = q->queuedata;
+	struct request *rq;
+	int queued = 0;
 
-			__blk_end_request_all(rq, result);
+	rbd_assert(rbd_dev);
+
+	while ((rq = blk_fetch_request(q))) {
+		/* Ignore any non-FS requests that filter through. */
+		if (rq->cmd_type != REQ_TYPE_FS) {
+			dout("%s: non-fs request type %d\n", __func__,
+				(int) rq->cmd_type);
+			__blk_end_request_all(rq, 0);
+			continue;
 		}
+
+		list_add_tail(&rq->queuelist, &rbd_dev->rq_queue);
+		queued++;
 	}
+
+	if (queued)
+		queue_work(rbd_dev->rq_wq, &rbd_dev->rq_work);
 }
 
 /*
@@ -3517,24 +3541,37 @@ static int rbd_dev_refresh(struct rbd_de
 	u64 mapping_size;
 	int ret;
 
-	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 	down_write(&rbd_dev->header_rwsem);
 	mapping_size = rbd_dev->mapping.size;
-	if (rbd_dev->image_format == 1)
-		ret = rbd_dev_v1_header_info(rbd_dev);
-	else
-		ret = rbd_dev_v2_header_info(rbd_dev);
 
-	/* If it's a mapped snapshot, validate its EXISTS flag */
+	ret = rbd_dev_header_info(rbd_dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * If there is a parent, see if it has disappeared due to the
+	 * mapped image getting flattened.
+	 */
+	if (rbd_dev->parent) {
+		ret = rbd_dev_v2_parent_info(rbd_dev);
+		if (ret)
+			return ret;
+	}
+
+	if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
+		if (rbd_dev->mapping.size != rbd_dev->header.image_size)
+			rbd_dev->mapping.size = rbd_dev->header.image_size;
+	} else {
+		/* validate mapped snapshot's EXISTS flag */
+		rbd_exists_validate(rbd_dev);
+	}
 
-	rbd_exists_validate(rbd_dev);
 	up_write(&rbd_dev->header_rwsem);
 
-	if (mapping_size != rbd_dev->mapping.size) {
+	if (mapping_size != rbd_dev->mapping.size)
 		rbd_dev_update_size(rbd_dev);
-	}
 
-	return ret;
+	return 0;
 }
 
 static int rbd_init_disk(struct rbd_device *rbd_dev)
@@ -3696,46 +3733,36 @@ static ssize_t rbd_snap_show(struct devi
 }
 
 /*
- * For an rbd v2 image, shows the pool id, image id, and snapshot id
- * for the parent image.  If there is no parent, simply shows
- * "(no parent image)".
+ * For a v2 image, shows the chain of parent images, separated by empty
+ * lines.  For v1 images or if there is no parent, shows "(no parent
+ * image)".
  */
 static ssize_t rbd_parent_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
+			       struct device_attribute *attr,
+			       char *buf)
 {
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
-	struct rbd_spec *spec = rbd_dev->parent_spec;
-	int count;
-	char *bufp = buf;
+	ssize_t count = 0;
 
-	if (!spec)
+	if (!rbd_dev->parent)
 		return sprintf(buf, "(no parent image)\n");
 
-	count = sprintf(bufp, "pool_id %llu\npool_name %s\n",
-			(unsigned long long) spec->pool_id, spec->pool_name);
-	if (count < 0)
-		return count;
-	bufp += count;
-
-	count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id,
-			spec->image_name ? spec->image_name : "(unknown)");
-	if (count < 0)
-		return count;
-	bufp += count;
-
-	count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n",
-			(unsigned long long) spec->snap_id, spec->snap_name);
-	if (count < 0)
-		return count;
-	bufp += count;
+	for ( ; rbd_dev->parent; rbd_dev = rbd_dev->parent) {
+		struct rbd_spec *spec = rbd_dev->parent_spec;
 
-	count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap);
-	if (count < 0)
-		return count;
-	bufp += count;
+		count += sprintf(&buf[count], "%s"
+			    "pool_id %llu\npool_name %s\n"
+			    "image_id %s\nimage_name %s\n"
+			    "snap_id %llu\nsnap_name %s\n"
+			    "overlap %llu\n",
+			    !count ? "" : "\n", /* first? */
+			    spec->pool_id, spec->pool_name,
+			    spec->image_id, spec->image_name ?: "(unknown)",
+			    spec->snap_id, spec->snap_name,
+			    rbd_dev->parent_overlap);
+	}
 
-	return (ssize_t) (bufp - buf);
+	return count;
 }
 
 static ssize_t rbd_image_refresh(struct device *dev,
@@ -3748,9 +3775,9 @@ static ssize_t rbd_image_refresh(struct
 
 	ret = rbd_dev_refresh(rbd_dev);
 	if (ret)
-		rbd_warn(rbd_dev, ": manual header refresh error (%d)\n", ret);
+		return ret;
 
-	return ret < 0 ? ret : size;
+	return size;
 }
 
 static DEVICE_ATTR(size, S_IRUGO, rbd_size_show, NULL);
@@ -3822,6 +3849,9 @@ static struct rbd_spec *rbd_spec_alloc(v
 	spec = kzalloc(sizeof (*spec), GFP_KERNEL);
 	if (!spec)
 		return NULL;
+
+	spec->pool_id = CEPH_NOPOOL;
+	spec->snap_id = CEPH_NOSNAP;
 	kref_init(&spec->kref);
 
 	return spec;
@@ -3848,6 +3878,8 @@ static struct rbd_device *rbd_dev_create
 		return NULL;
 
 	spin_lock_init(&rbd_dev->lock);
+	INIT_LIST_HEAD(&rbd_dev->rq_queue);
+	INIT_WORK(&rbd_dev->rq_work, rbd_request_workfn);
 	rbd_dev->flags = 0;
 	atomic_set(&rbd_dev->parent_ref, 0);
 	INIT_LIST_HEAD(&rbd_dev->node);
@@ -4021,7 +4053,7 @@ static int rbd_dev_v2_parent_info(struct
 		goto out_err;
 	}
 
-	snapid = cpu_to_le64(CEPH_NOSNAP);
+	snapid = cpu_to_le64(rbd_dev->spec->snap_id);
 	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
 				"rbd", "get_parent",
 				&snapid, sizeof (snapid),
@@ -4059,7 +4091,7 @@ static int rbd_dev_v2_parent_info(struct
 
 	ret = -EIO;
 	if (pool_id > (u64)U32_MAX) {
-		rbd_warn(NULL, "parent pool id too large (%llu > %u)\n",
+		rbd_warn(NULL, "parent pool id too large (%llu > %u)",
 			(unsigned long long)pool_id, U32_MAX);
 		goto out_err;
 	}
@@ -4083,6 +4115,8 @@ static int rbd_dev_v2_parent_info(struct
 		parent_spec->snap_id = snap_id;
 		rbd_dev->parent_spec = parent_spec;
 		parent_spec = NULL;	/* rbd_dev now owns this */
+	} else {
+		kfree(image_id);
 	}
 
 	/*
@@ -4110,8 +4144,7 @@ static int rbd_dev_v2_parent_info(struct
 			 * overlap is zero we just pretend there was
 			 * no parent image.
 			 */
-			rbd_warn(rbd_dev, "ignoring parent of "
-						"clone with overlap 0\n");
+			rbd_warn(rbd_dev, "ignoring parent with overlap 0");
 		}
 	}
 out:
@@ -4279,18 +4312,38 @@ static u64 rbd_snap_id_by_name(struct rb
 }
 
 /*
- * When an rbd image has a parent image, it is identified by the
- * pool, image, and snapshot ids (not names).  This function fills
- * in the names for those ids.  (It's OK if we can't figure out the
- * name for an image id, but the pool and snapshot ids should always
- * exist and have names.)  All names in an rbd spec are dynamically
- * allocated.
+ * An image being mapped will have everything but the snap id.
+ */
+static int rbd_spec_fill_snap_id(struct rbd_device *rbd_dev)
+{
+	struct rbd_spec *spec = rbd_dev->spec;
+
+	rbd_assert(spec->pool_id != CEPH_NOPOOL && spec->pool_name);
+	rbd_assert(spec->image_id && spec->image_name);
+	rbd_assert(spec->snap_name);
+
+	if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) {
+		u64 snap_id;
+
+		snap_id = rbd_snap_id_by_name(rbd_dev, spec->snap_name);
+		if (snap_id == CEPH_NOSNAP)
+			return -ENOENT;
+
+		spec->snap_id = snap_id;
+	} else {
+		spec->snap_id = CEPH_NOSNAP;
+	}
+
+	return 0;
+}
+
+/*
+ * A parent image will have all ids but none of the names.
  *
- * When an image being mapped (not a parent) is probed, we have the
- * pool name and pool id, image name and image id, and the snapshot
- * name.  The only thing we're missing is the snapshot id.
+ * All names in an rbd spec are dynamically allocated.  It's OK if we
+ * can't figure out the name for an image id.
  */
-static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
+static int rbd_spec_fill_names(struct rbd_device *rbd_dev)
 {
 	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
 	struct rbd_spec *spec = rbd_dev->spec;
@@ -4299,24 +4352,9 @@ static int rbd_dev_spec_update(struct rb
 	const char *snap_name;
 	int ret;
 
-	/*
-	 * An image being mapped will have the pool name (etc.), but
-	 * we need to look up the snapshot id.
-	 */
-	if (spec->pool_name) {
-		if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) {
-			u64 snap_id;
-
-			snap_id = rbd_snap_id_by_name(rbd_dev, spec->snap_name);
-			if (snap_id == CEPH_NOSNAP)
-				return -ENOENT;
-			spec->snap_id = snap_id;
-		} else {
-			spec->snap_id = CEPH_NOSNAP;
-		}
-
-		return 0;
-	}
+	rbd_assert(spec->pool_id != CEPH_NOPOOL);
+	rbd_assert(spec->image_id);
+	rbd_assert(spec->snap_id != CEPH_NOSNAP);
 
 	/* Get the pool name; we have to make our own copy of this */
 
@@ -4335,7 +4373,7 @@ static int rbd_dev_spec_update(struct rb
 	if (!image_name)
 		rbd_warn(rbd_dev, "unable to get image name");
 
-	/* Look up the snapshot name, and make a copy */
+	/* Fetch the snapshot name */
 
 	snap_name = rbd_snap_name(rbd_dev, spec->snap_id);
 	if (IS_ERR(snap_name)) {
@@ -4348,10 +4386,10 @@ static int rbd_dev_spec_update(struct rb
 	spec->snap_name = snap_name;
 
 	return 0;
+
 out_err:
 	kfree(image_name);
 	kfree(pool_name);
-
 	return ret;
 }
 
@@ -4483,43 +4521,22 @@ static int rbd_dev_v2_header_info(struct
 			return ret;
 	}
 
-	/*
-	 * If the image supports layering, get the parent info.  We
-	 * need to probe the first time regardless.  Thereafter we
-	 * only need to if there's a parent, to see if it has
-	 * disappeared due to the mapped image getting flattened.
-	 */
-	if (rbd_dev->header.features & RBD_FEATURE_LAYERING &&
-			(first_time || rbd_dev->parent_spec)) {
-		bool warn;
-
-		ret = rbd_dev_v2_parent_info(rbd_dev);
-		if (ret)
-			return ret;
-
-		/*
-		 * Print a warning if this is the initial probe and
-		 * the image has a parent.  Don't print it if the
-		 * image now being probed is itself a parent.  We
-		 * can tell at this point because we won't know its
-		 * pool name yet (just its pool id).
-		 */
-		warn = rbd_dev->parent_spec && rbd_dev->spec->pool_name;
-		if (first_time && warn)
-			rbd_warn(rbd_dev, "WARNING: kernel layering "
-					"is EXPERIMENTAL!");
-	}
-
-	if (rbd_dev->spec->snap_id == CEPH_NOSNAP)
-		if (rbd_dev->mapping.size != rbd_dev->header.image_size)
-			rbd_dev->mapping.size = rbd_dev->header.image_size;
-
 	ret = rbd_dev_v2_snap_context(rbd_dev);
 	dout("rbd_dev_v2_snap_context returned %d\n", ret);
 
 	return ret;
 }
 
+static int rbd_dev_header_info(struct rbd_device *rbd_dev)
+{
+	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
+
+	if (rbd_dev->image_format == 1)
+		return rbd_dev_v1_header_info(rbd_dev);
+
+	return rbd_dev_v2_header_info(rbd_dev);
+}
+
 static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
 {
 	struct device *dev;
@@ -5066,12 +5083,19 @@ static int rbd_dev_device_setup(struct r
 	ret = rbd_dev_mapping_set(rbd_dev);
 	if (ret)
 		goto err_out_disk;
+
 	set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
 	set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
 
+	rbd_dev->rq_wq = alloc_workqueue("%s", 0, 0, rbd_dev->disk->disk_name);
+	if (!rbd_dev->rq_wq) {
+		ret = -ENOMEM;
+		goto err_out_mapping;
+	}
+
 	ret = rbd_bus_add_dev(rbd_dev);
 	if (ret)
-		goto err_out_mapping;
+		goto err_out_workqueue;
 
 	/* Everything's ready.  Announce the disk to the world. */
 
@@ -5083,6 +5107,9 @@ static int rbd_dev_device_setup(struct r
 
 	return ret;
 
+err_out_workqueue:
+	destroy_workqueue(rbd_dev->rq_wq);
+	rbd_dev->rq_wq = NULL;
 err_out_mapping:
 	rbd_dev_mapping_clear(rbd_dev);
 err_out_disk:
@@ -5155,8 +5182,6 @@ static int rbd_dev_image_probe(struct rb
 	ret = rbd_dev_image_id(rbd_dev);
 	if (ret)
 		return ret;
-	rbd_assert(rbd_dev->spec->image_id);
-	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 
 	ret = rbd_dev_header_name(rbd_dev);
 	if (ret)
@@ -5168,25 +5193,45 @@ static int rbd_dev_image_probe(struct rb
 			goto out_header_name;
 	}
 
-	if (rbd_dev->image_format == 1)
-		ret = rbd_dev_v1_header_info(rbd_dev);
-	else
-		ret = rbd_dev_v2_header_info(rbd_dev);
+	ret = rbd_dev_header_info(rbd_dev);
 	if (ret)
 		goto err_out_watch;
 
-	ret = rbd_dev_spec_update(rbd_dev);
+	/*
+	 * If this image is the one being mapped, we have pool name and
+	 * id, image name and id, and snap name - need to fill snap id.
+	 * Otherwise this is a parent image, identified by pool, image
+	 * and snap ids - need to fill in names for those ids.
+	 */
+	if (mapping)
+		ret = rbd_spec_fill_snap_id(rbd_dev);
+	else
+		ret = rbd_spec_fill_names(rbd_dev);
 	if (ret)
 		goto err_out_probe;
 
+	if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
+		ret = rbd_dev_v2_parent_info(rbd_dev);
+		if (ret)
+			goto err_out_probe;
+
+		/*
+		 * Need to warn users if this image is the one being
+		 * mapped and has a parent.
+		 */
+		if (mapping && rbd_dev->parent_spec)
+			rbd_warn(rbd_dev,
+				 "WARNING: kernel layering is EXPERIMENTAL!");
+	}
+
 	ret = rbd_dev_probe_parent(rbd_dev);
 	if (ret)
 		goto err_out_probe;
 
 	dout("discovered format %u image, header name is %s\n",
 		rbd_dev->image_format, rbd_dev->header_name);
-
 	return 0;
+
 err_out_probe:
 	rbd_dev_unprobe(rbd_dev);
 err_out_watch:
@@ -5199,9 +5244,6 @@ err_out_format:
 	rbd_dev->image_format = 0;
 	kfree(rbd_dev->spec->image_id);
 	rbd_dev->spec->image_id = NULL;
-
-	dout("probe failed, returning %d\n", ret);
-
 	return ret;
 }
 
@@ -5243,7 +5285,7 @@ static ssize_t do_rbd_add(struct bus_typ
 	/* The ceph file layout needs to fit pool id in 32 bits */
 
 	if (spec->pool_id > (u64)U32_MAX) {
-		rbd_warn(NULL, "pool id too large (%llu > %u)\n",
+		rbd_warn(NULL, "pool id too large (%llu > %u)",
 				(unsigned long long)spec->pool_id, U32_MAX);
 		rc = -EIO;
 		goto err_out_client;
@@ -5314,6 +5356,7 @@ static void rbd_dev_device_release(struc
 {
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
+	destroy_workqueue(rbd_dev->rq_wq);
 	rbd_free_disk(rbd_dev);
 	clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
 	rbd_dev_mapping_clear(rbd_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/rsxx/core.c linux-libre-3.17-rc7-gnu/drivers/block/rsxx/core.c
--- linux-libre-3.16-gnu/drivers/block/rsxx/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/rsxx/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1137,7 +1137,7 @@ static const struct pci_error_handlers r
 	.slot_reset     = rsxx_slot_reset,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = {
+static const struct pci_device_id rsxx_pci_ids[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)},
 	{PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)},
 	{0,},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/skd_main.c linux-libre-3.17-rc7-gnu/drivers/block/skd_main.c
--- linux-libre-3.16-gnu/drivers/block/skd_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/skd_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -4112,16 +4112,14 @@ static int skd_cons_skcomp(struct skd_de
 		 skdev->name, __func__, __LINE__,
 		 nbytes, SKD_N_COMPLETION_ENTRY);
 
-	skcomp = pci_alloc_consistent(skdev->pdev, nbytes,
-				      &skdev->cq_dma_address);
+	skcomp = pci_zalloc_consistent(skdev->pdev, nbytes,
+				       &skdev->cq_dma_address);
 
 	if (skcomp == NULL) {
 		rc = -ENOMEM;
 		goto err_out;
 	}
 
-	memset(skcomp, 0, nbytes);
-
 	skdev->skcomp_table = skcomp;
 	skdev->skerr_table = (struct fit_comp_error_info *)((char *)skcomp +
 							   sizeof(*skcomp) *
@@ -4304,15 +4302,14 @@ static int skd_cons_skspcl(struct skd_de
 
 		nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
 
-		skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
-						       &skspcl->mb_dma_address);
+		skspcl->msg_buf =
+			pci_zalloc_consistent(skdev->pdev, nbytes,
+					      &skspcl->mb_dma_address);
 		if (skspcl->msg_buf == NULL) {
 			rc = -ENOMEM;
 			goto err_out;
 		}
 
-		memset(skspcl->msg_buf, 0, nbytes);
-
 		skspcl->req.sg = kzalloc(sizeof(struct scatterlist) *
 					 SKD_N_SG_PER_SPECIAL, GFP_KERNEL);
 		if (skspcl->req.sg == NULL) {
@@ -4353,25 +4350,21 @@ static int skd_cons_sksb(struct skd_devi
 
 	nbytes = SKD_N_INTERNAL_BYTES;
 
-	skspcl->data_buf = pci_alloc_consistent(skdev->pdev, nbytes,
-						&skspcl->db_dma_address);
+	skspcl->data_buf = pci_zalloc_consistent(skdev->pdev, nbytes,
+						 &skspcl->db_dma_address);
 	if (skspcl->data_buf == NULL) {
 		rc = -ENOMEM;
 		goto err_out;
 	}
 
-	memset(skspcl->data_buf, 0, nbytes);
-
 	nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
-	skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
-					       &skspcl->mb_dma_address);
+	skspcl->msg_buf = pci_zalloc_consistent(skdev->pdev, nbytes,
+						&skspcl->mb_dma_address);
 	if (skspcl->msg_buf == NULL) {
 		rc = -ENOMEM;
 		goto err_out;
 	}
 
-	memset(skspcl->msg_buf, 0, nbytes);
-
 	skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1,
 						 &skspcl->req.sksg_dma_address);
 	if (skspcl->req.sksg_list == NULL) {
@@ -4773,7 +4766,7 @@ static const struct block_device_operati
  *****************************************************************************
  */
 
-static DEFINE_PCI_DEVICE_TABLE(skd_pci_tbl) = {
+static const struct pci_device_id skd_pci_tbl[] = {
 	{ PCI_VENDOR_ID_STEC, PCI_DEVICE_ID_S1120,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{ 0 }                     /* terminate list */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/virtio_blk.c linux-libre-3.17-rc7-gnu/drivers/block/virtio_blk.c
--- linux-libre-3.16-gnu/drivers/block/virtio_blk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/virtio_blk.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,17 +15,22 @@
 #include <linux/numa.h>
 
 #define PART_BITS 4
+#define VQ_NAME_LEN 16
 
 static int major;
 static DEFINE_IDA(vd_index_ida);
 
 static struct workqueue_struct *virtblk_wq;
 
+struct virtio_blk_vq {
+	struct virtqueue *vq;
+	spinlock_t lock;
+	char name[VQ_NAME_LEN];
+} ____cacheline_aligned_in_smp;
+
 struct virtio_blk
 {
 	struct virtio_device *vdev;
-	struct virtqueue *vq;
-	spinlock_t vq_lock;
 
 	/* The disk structure for the kernel. */
 	struct gendisk *disk;
@@ -47,6 +52,10 @@ struct virtio_blk
 
 	/* Ida index - used to track minor number allocations. */
 	int index;
+
+	/* num of vqs */
+	int num_vqs;
+	struct virtio_blk_vq *vqs;
 };
 
 struct virtblk_req
@@ -133,14 +142,15 @@ static void virtblk_done(struct virtqueu
 {
 	struct virtio_blk *vblk = vq->vdev->priv;
 	bool req_done = false;
+	int qid = vq->index;
 	struct virtblk_req *vbr;
 	unsigned long flags;
 	unsigned int len;
 
-	spin_lock_irqsave(&vblk->vq_lock, flags);
+	spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
 	do {
 		virtqueue_disable_cb(vq);
-		while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
+		while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
 			blk_mq_complete_request(vbr->req);
 			req_done = true;
 		}
@@ -151,7 +161,7 @@ static void virtblk_done(struct virtqueu
 	/* In case queue is stopped waiting for more buffers. */
 	if (req_done)
 		blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
-	spin_unlock_irqrestore(&vblk->vq_lock, flags);
+	spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
 }
 
 static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
@@ -160,6 +170,7 @@ static int virtio_queue_rq(struct blk_mq
 	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
 	unsigned long flags;
 	unsigned int num;
+	int qid = hctx->queue_num;
 	const bool last = (req->cmd_flags & REQ_END) != 0;
 	int err;
 	bool notify = false;
@@ -202,12 +213,12 @@ static int virtio_queue_rq(struct blk_mq
 			vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
 	}
 
-	spin_lock_irqsave(&vblk->vq_lock, flags);
-	err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num);
+	spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
+	err = __virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
 	if (err) {
-		virtqueue_kick(vblk->vq);
+		virtqueue_kick(vblk->vqs[qid].vq);
 		blk_mq_stop_hw_queue(hctx);
-		spin_unlock_irqrestore(&vblk->vq_lock, flags);
+		spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
 		/* Out of mem doesn't actually happen, since we fall back
 		 * to direct descriptors */
 		if (err == -ENOMEM || err == -ENOSPC)
@@ -215,12 +226,12 @@ static int virtio_queue_rq(struct blk_mq
 		return BLK_MQ_RQ_QUEUE_ERROR;
 	}
 
-	if (last && virtqueue_kick_prepare(vblk->vq))
+	if (last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
 		notify = true;
-	spin_unlock_irqrestore(&vblk->vq_lock, flags);
+	spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
 
 	if (notify)
-		virtqueue_notify(vblk->vq);
+		virtqueue_notify(vblk->vqs[qid].vq);
 	return BLK_MQ_RQ_QUEUE_OK;
 }
 
@@ -377,12 +388,64 @@ static void virtblk_config_changed(struc
 static int init_vq(struct virtio_blk *vblk)
 {
 	int err = 0;
+	int i;
+	vq_callback_t **callbacks;
+	const char **names;
+	struct virtqueue **vqs;
+	unsigned short num_vqs;
+	struct virtio_device *vdev = vblk->vdev;
 
-	/* We expect one virtqueue, for output. */
-	vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
-	if (IS_ERR(vblk->vq))
-		err = PTR_ERR(vblk->vq);
+	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_MQ,
+				   struct virtio_blk_config, num_queues,
+				   &num_vqs);
+	if (err)
+		num_vqs = 1;
+
+	vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL);
+	if (!vblk->vqs) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL);
+	if (!names)
+		goto err_names;
+
+	callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL);
+	if (!callbacks)
+		goto err_callbacks;
+
+	vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL);
+	if (!vqs)
+		goto err_vqs;
+
+	for (i = 0; i < num_vqs; i++) {
+		callbacks[i] = virtblk_done;
+		snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req.%d", i);
+		names[i] = vblk->vqs[i].name;
+	}
+
+	/* Discover virtqueues and write information to configuration.  */
+	err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names);
+	if (err)
+		goto err_find_vqs;
+
+	for (i = 0; i < num_vqs; i++) {
+		spin_lock_init(&vblk->vqs[i].lock);
+		vblk->vqs[i].vq = vqs[i];
+	}
+	vblk->num_vqs = num_vqs;
 
+ err_find_vqs:
+	kfree(vqs);
+ err_vqs:
+	kfree(callbacks);
+ err_callbacks:
+	kfree(names);
+ err_names:
+	if (err)
+		kfree(vblk->vqs);
+ out:
 	return err;
 }
 
@@ -551,7 +614,6 @@ static int virtblk_probe(struct virtio_d
 	err = init_vq(vblk);
 	if (err)
 		goto out_free_vblk;
-	spin_lock_init(&vblk->vq_lock);
 
 	/* FIXME: How many partitions?  How long is a piece of string? */
 	vblk->disk = alloc_disk(1 << PART_BITS);
@@ -562,7 +624,7 @@ static int virtblk_probe(struct virtio_d
 
 	/* Default queue sizing is to fill the ring. */
 	if (!virtblk_queue_depth) {
-		virtblk_queue_depth = vblk->vq->num_free;
+		virtblk_queue_depth = vblk->vqs[0].vq->num_free;
 		/* ... but without indirect descs, we use 2 descs per req */
 		if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
 			virtblk_queue_depth /= 2;
@@ -570,7 +632,6 @@ static int virtblk_probe(struct virtio_d
 
 	memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
 	vblk->tag_set.ops = &virtio_mq_ops;
-	vblk->tag_set.nr_hw_queues = 1;
 	vblk->tag_set.queue_depth = virtblk_queue_depth;
 	vblk->tag_set.numa_node = NUMA_NO_NODE;
 	vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
@@ -578,6 +639,7 @@ static int virtblk_probe(struct virtio_d
 		sizeof(struct virtblk_req) +
 		sizeof(struct scatterlist) * sg_elems;
 	vblk->tag_set.driver_data = vblk;
+	vblk->tag_set.nr_hw_queues = vblk->num_vqs;
 
 	err = blk_mq_alloc_tag_set(&vblk->tag_set);
 	if (err)
@@ -727,6 +789,7 @@ static void virtblk_remove(struct virtio
 	refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
 	put_disk(vblk->disk);
 	vdev->config->del_vqs(vdev);
+	kfree(vblk->vqs);
 	kfree(vblk);
 
 	/* Only free device id if we don't have any users */
@@ -777,7 +840,8 @@ static const struct virtio_device_id id_
 static unsigned int features[] = {
 	VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
 	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
-	VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
+	VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
+	VIRTIO_BLK_F_MQ,
 };
 
 static struct virtio_driver virtio_blk = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/xsysace.c linux-libre-3.17-rc7-gnu/drivers/block/xsysace.c
--- linux-libre-3.16-gnu/drivers/block/xsysace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/xsysace.c	2014-09-28 17:29:07.000000000 -0400
@@ -1203,7 +1203,6 @@ static struct platform_driver ace_platfo
 	.probe = ace_probe,
 	.remove = ace_remove,
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "xsysace",
 		.of_match_table = ace_of_match,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/zram/zram_drv.c linux-libre-3.17-rc7-gnu/drivers/block/zram/zram_drv.c
--- linux-libre-3.16-gnu/drivers/block/zram/zram_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/zram/zram_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -183,19 +183,32 @@ static ssize_t comp_algorithm_store(stru
 static int zram_test_flag(struct zram_meta *meta, u32 index,
 			enum zram_pageflags flag)
 {
-	return meta->table[index].flags & BIT(flag);
+	return meta->table[index].value & BIT(flag);
 }
 
 static void zram_set_flag(struct zram_meta *meta, u32 index,
 			enum zram_pageflags flag)
 {
-	meta->table[index].flags |= BIT(flag);
+	meta->table[index].value |= BIT(flag);
 }
 
 static void zram_clear_flag(struct zram_meta *meta, u32 index,
 			enum zram_pageflags flag)
 {
-	meta->table[index].flags &= ~BIT(flag);
+	meta->table[index].value &= ~BIT(flag);
+}
+
+static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
+{
+	return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+}
+
+static void zram_set_obj_size(struct zram_meta *meta,
+					u32 index, size_t size)
+{
+	unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
+
+	meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
 }
 
 static inline int is_partial_io(struct bio_vec *bvec)
@@ -255,7 +268,6 @@ static struct zram_meta *zram_meta_alloc
 		goto free_table;
 	}
 
-	rwlock_init(&meta->tb_lock);
 	return meta;
 
 free_table:
@@ -304,7 +316,12 @@ static void handle_zero_page(struct bio_
 	flush_dcache_page(page);
 }
 
-/* NOTE: caller should hold meta->tb_lock with write-side */
+
+/*
+ * To protect concurrent access to the same index entry,
+ * caller should hold this table index entry's bit_spinlock to
+ * indicate this index entry is accessing.
+ */
 static void zram_free_page(struct zram *zram, size_t index)
 {
 	struct zram_meta *meta = zram->meta;
@@ -324,11 +341,12 @@ static void zram_free_page(struct zram *
 
 	zs_free(meta->mem_pool, handle);
 
-	atomic64_sub(meta->table[index].size, &zram->stats.compr_data_size);
+	atomic64_sub(zram_get_obj_size(meta, index),
+			&zram->stats.compr_data_size);
 	atomic64_dec(&zram->stats.pages_stored);
 
 	meta->table[index].handle = 0;
-	meta->table[index].size = 0;
+	zram_set_obj_size(meta, index, 0);
 }
 
 static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
@@ -337,14 +355,14 @@ static int zram_decompress_page(struct z
 	unsigned char *cmem;
 	struct zram_meta *meta = zram->meta;
 	unsigned long handle;
-	u16 size;
+	size_t size;
 
-	read_lock(&meta->tb_lock);
+	bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 	handle = meta->table[index].handle;
-	size = meta->table[index].size;
+	size = zram_get_obj_size(meta, index);
 
 	if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
-		read_unlock(&meta->tb_lock);
+		bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 		clear_page(mem);
 		return 0;
 	}
@@ -355,12 +373,11 @@ static int zram_decompress_page(struct z
 	else
 		ret = zcomp_decompress(zram->comp, cmem, size, mem);
 	zs_unmap_object(meta->mem_pool, handle);
-	read_unlock(&meta->tb_lock);
+	bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 
 	/* Should NEVER happen. Return bio error if it does. */
 	if (unlikely(ret)) {
 		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
-		atomic64_inc(&zram->stats.failed_reads);
 		return ret;
 	}
 
@@ -376,14 +393,14 @@ static int zram_bvec_read(struct zram *z
 	struct zram_meta *meta = zram->meta;
 	page = bvec->bv_page;
 
-	read_lock(&meta->tb_lock);
+	bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 	if (unlikely(!meta->table[index].handle) ||
 			zram_test_flag(meta, index, ZRAM_ZERO)) {
-		read_unlock(&meta->tb_lock);
+		bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 		handle_zero_page(bvec);
 		return 0;
 	}
-	read_unlock(&meta->tb_lock);
+	bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 
 	if (is_partial_io(bvec))
 		/* Use  a temporary buffer to decompress the page */
@@ -461,10 +478,10 @@ static int zram_bvec_write(struct zram *
 	if (page_zero_filled(uncmem)) {
 		kunmap_atomic(user_mem);
 		/* Free memory associated with this sector now. */
-		write_lock(&zram->meta->tb_lock);
+		bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 		zram_free_page(zram, index);
 		zram_set_flag(meta, index, ZRAM_ZERO);
-		write_unlock(&zram->meta->tb_lock);
+		bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 
 		atomic64_inc(&zram->stats.zero_pages);
 		ret = 0;
@@ -514,12 +531,12 @@ static int zram_bvec_write(struct zram *
 	 * Free memory associated with this sector
 	 * before overwriting unused sectors.
 	 */
-	write_lock(&zram->meta->tb_lock);
+	bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 	zram_free_page(zram, index);
 
 	meta->table[index].handle = handle;
-	meta->table[index].size = clen;
-	write_unlock(&zram->meta->tb_lock);
+	zram_set_obj_size(meta, index, clen);
+	bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 
 	/* Update stats */
 	atomic64_add(clen, &zram->stats.compr_data_size);
@@ -529,8 +546,6 @@ out:
 		zcomp_strm_release(zram->comp, zstrm);
 	if (is_partial_io(bvec))
 		kfree(uncmem);
-	if (ret)
-		atomic64_inc(&zram->stats.failed_writes);
 	return ret;
 }
 
@@ -548,6 +563,13 @@ static int zram_bvec_rw(struct zram *zra
 		ret = zram_bvec_write(zram, bvec, index, offset);
 	}
 
+	if (unlikely(ret)) {
+		if (rw == READ)
+			atomic64_inc(&zram->stats.failed_reads);
+		else
+			atomic64_inc(&zram->stats.failed_writes);
+	}
+
 	return ret;
 }
 
@@ -560,6 +582,7 @@ static void zram_bio_discard(struct zram
 			     int offset, struct bio *bio)
 {
 	size_t n = bio->bi_iter.bi_size;
+	struct zram_meta *meta = zram->meta;
 
 	/*
 	 * zram manages data in physical block size units. Because logical block
@@ -580,13 +603,9 @@ static void zram_bio_discard(struct zram
 	}
 
 	while (n >= PAGE_SIZE) {
-		/*
-		 * Discard request can be large so the lock hold times could be
-		 * lengthy.  So take the lock once per page.
-		 */
-		write_lock(&zram->meta->tb_lock);
+		bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 		zram_free_page(zram, index);
-		write_unlock(&zram->meta->tb_lock);
+		bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 		index++;
 		n -= PAGE_SIZE;
 	}
@@ -821,9 +840,9 @@ static void zram_slot_free_notify(struct
 	zram = bdev->bd_disk->private_data;
 	meta = zram->meta;
 
-	write_lock(&meta->tb_lock);
+	bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
 	zram_free_page(zram, index);
-	write_unlock(&meta->tb_lock);
+	bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
 	atomic64_inc(&zram->stats.notify_free);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/block/zram/zram_drv.h linux-libre-3.17-rc7-gnu/drivers/block/zram/zram_drv.h
--- linux-libre-3.16-gnu/drivers/block/zram/zram_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/block/zram/zram_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,6 @@ static const size_t max_zpage_size = PAG
 /*-- End of configurable params */
 
 #define SECTOR_SHIFT		9
-#define SECTOR_SIZE		(1 << SECTOR_SHIFT)
 #define SECTORS_PER_PAGE_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
 #define SECTORS_PER_PAGE	(1 << SECTORS_PER_PAGE_SHIFT)
 #define ZRAM_LOGICAL_BLOCK_SHIFT 12
@@ -51,10 +50,24 @@ static const size_t max_zpage_size = PAG
 #define ZRAM_SECTOR_PER_LOGICAL_BLOCK	\
 	(1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
 
-/* Flags for zram pages (table[page_no].flags) */
+
+/*
+ * The lower ZRAM_FLAG_SHIFT bits of table.value is for
+ * object size (excluding header), the higher bits is for
+ * zram_pageflags.
+ *
+ * zram is mainly used for memory efficiency so we want to keep memory
+ * footprint small so we can squeeze size and flags into a field.
+ * The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header),
+ * the higher bits is for zram_pageflags.
+ */
+#define ZRAM_FLAG_SHIFT 24
+
+/* Flags for zram pages (table[page_no].value) */
 enum zram_pageflags {
 	/* Page consists entirely of zeros */
-	ZRAM_ZERO,
+	ZRAM_ZERO = ZRAM_FLAG_SHIFT + 1,
+	ZRAM_ACCESS,	/* page in now accessed */
 
 	__NR_ZRAM_PAGEFLAGS,
 };
@@ -62,17 +75,16 @@ enum zram_pageflags {
 /*-- Data structures */
 
 /* Allocated for each disk page */
-struct table {
+struct zram_table_entry {
 	unsigned long handle;
-	u16 size;	/* object size (excluding header) */
-	u8 flags;
-} __aligned(4);
+	unsigned long value;
+};
 
 struct zram_stats {
 	atomic64_t compr_data_size;	/* compressed size of pages stored */
 	atomic64_t num_reads;	/* failed + successful */
 	atomic64_t num_writes;	/* --do-- */
-	atomic64_t failed_reads;	/* should NEVER! happen */
+	atomic64_t failed_reads;	/* can happen when memory is too low */
 	atomic64_t failed_writes;	/* can happen when memory is too low */
 	atomic64_t invalid_io;	/* non-page-aligned I/O requests */
 	atomic64_t notify_free;	/* no. of swap slot free notifications */
@@ -81,8 +93,7 @@ struct zram_stats {
 };
 
 struct zram_meta {
-	rwlock_t tb_lock;	/* protect table */
-	struct table *table;
+	struct zram_table_entry *table;
 	struct zs_pool *mem_pool;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/ath3k.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-3.16-gnu/drivers/bluetooth/ath3k.c	2014-08-07 04:57:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/ath3k.c	2014-09-28 21:40:12.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/usb.h>
+#include <asm/unaligned.h>
 #include <net/bluetooth/bluetooth.h>
 
 #define VERSION "1.0"
@@ -50,12 +51,12 @@
 #define ATH3K_NAME_LEN				0xFF
 
 struct ath3k_version {
-	unsigned int	rom_version;
-	unsigned int	build_version;
-	unsigned int	ram_version;
-	unsigned char	ref_clock;
-	unsigned char	reserved[0x07];
-};
+	__le32	rom_version;
+	__le32	build_version;
+	__le32	ram_version;
+	__u8	ref_clock;
+	__u8	reserved[7];
+} __packed;
 
 static const struct usb_device_id ath3k_table[] = {
 	/* Atheros AR3011 */
@@ -103,6 +104,7 @@ static const struct usb_device_id ath3k_
 	{ USB_DEVICE(0x13d3, 0x3375) },
 	{ USB_DEVICE(0x13d3, 0x3393) },
 	{ USB_DEVICE(0x13d3, 0x3402) },
+	{ USB_DEVICE(0x13d3, 0x3432) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
@@ -152,6 +154,7 @@ static const struct usb_device_id ath3k_
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
@@ -288,10 +291,10 @@ static int ath3k_load_fwfile(struct usb_
 	sent += size;
 	count -= size;
 
+	pipe = usb_sndbulkpipe(udev, 0x02);
+
 	while (count) {
 		size = min_t(uint, count, BULK_SIZE);
-		pipe = usb_sndbulkpipe(udev, 0x02);
-
 		memcpy(send_buf, firmware->data + sent, size);
 
 		err = usb_bulk_msg(udev, pipe, send_buf, size,
@@ -347,7 +350,8 @@ static int ath3k_load_patch(struct usb_d
 	unsigned char fw_state;
 	char filename[ATH3K_NAME_LEN] = {0};
 	const struct firmware *firmware;
-	struct ath3k_version fw_version, pt_version;
+	struct ath3k_version fw_version;
+	__u32 pt_rom_version, pt_build_version;
 	int ret;
 
 	ret = ath3k_get_state(udev, &fw_state);
@@ -368,7 +372,7 @@ static int ath3k_load_patch(struct usb_d
 	}
 
 	snprintf(filename, ATH3K_NAME_LEN, "/*(DEBLOBBED)*/",
-		le32_to_cpu(fw_version.rom_version));
+		 le32_to_cpu(fw_version.rom_version));
 
 	ret = reject_firmware(&firmware, filename, &udev->dev);
 	if (ret < 0) {
@@ -376,12 +380,13 @@ static int ath3k_load_patch(struct usb_d
 		return ret;
 	}
 
-	pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
-	pt_version.build_version = *(int *)
-		(firmware->data + firmware->size - 4);
+	pt_rom_version = get_unaligned_le32(firmware->data +
+					    firmware->size - 8);
+	pt_build_version = get_unaligned_le32(firmware->data +
+					      firmware->size - 4);
 
-	if ((pt_version.rom_version != fw_version.rom_version) ||
-		(pt_version.build_version <= fw_version.build_version)) {
+	if (pt_rom_version != le32_to_cpu(fw_version.rom_version) ||
+	    pt_build_version <= le32_to_cpu(fw_version.build_version)) {
 		BT_ERR("Patch file version did not match with firmware");
 		release_firmware(firmware);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_drv.h linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_drv.h
--- linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,7 @@ struct btmrvl_adapter {
 	u8 hs_state;
 	u8 wakeup_tries;
 	wait_queue_head_t cmd_wait_q;
+	wait_queue_head_t event_hs_wait_q;
 	u8 cmd_complete;
 	bool is_suspended;
 };
@@ -89,6 +90,8 @@ struct btmrvl_private {
 #define MRVL_VENDOR_PKT			0xFE
 
 /* Vendor specific Bluetooth commands */
+#define BT_CMD_PSCAN_WIN_REPORT_ENABLE	0xFC03
+#define BT_CMD_SET_BDADDR		0xFC22
 #define BT_CMD_AUTO_SLEEP_MODE		0xFC23
 #define BT_CMD_HOST_SLEEP_CONFIG	0xFC59
 #define BT_CMD_HOST_SLEEP_ENABLE	0xFC5A
@@ -143,6 +146,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_p
 int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
 
 int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);
+int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd);
 int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
 int btmrvl_enable_ps(struct btmrvl_private *priv);
 int btmrvl_prepare_command(struct btmrvl_private *priv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_main.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_main.c
--- linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_p
 			adapter->hs_state = HS_ACTIVATED;
 			if (adapter->psmode)
 				adapter->ps_state = PS_SLEEP;
+			wake_up_interruptible(&adapter->event_hs_wait_q);
 			BT_DBG("HS ACTIVATED!");
 		} else {
 			BT_DBG("HS Enable failed");
@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct bt
 }
 EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
 
+int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd)
+{
+	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
+	int ret;
+
+	if (!card->support_pscan_win_report)
+		return 0;
+
+	ret = btmrvl_send_sync_cmd(priv, BT_CMD_PSCAN_WIN_REPORT_ENABLE,
+				   &subcmd, 1);
+	if (ret)
+		BT_ERR("PSCAN_WIN_REPORT_ENABLE command failed: %#x", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(btmrvl_pscan_window_reporting);
+
 int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
 {
 	int ret;
@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
 
 int btmrvl_enable_hs(struct btmrvl_private *priv)
 {
+	struct btmrvl_adapter *adapter = priv->adapter;
 	int ret;
 
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
-	if (ret)
+	if (ret) {
 		BT_ERR("Host sleep enable command failed\n");
+		return ret;
+	}
+
+	ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
+					       adapter->hs_state,
+			msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
+	if (ret < 0) {
+		BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
+		       ret, adapter->hs_state, adapter->ps_state,
+		       adapter->wakeup_tries);
+	} else if (!ret) {
+		BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state,
+		       adapter->ps_state, adapter->wakeup_tries);
+		ret = -ETIMEDOUT;
+	} else {
+		BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state,
+		       adapter->ps_state, adapter->wakeup_tries);
+		ret = 0;
+	}
 
 	return ret;
 }
@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct b
 	}
 
 	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	init_waitqueue_head(&priv->adapter->event_hs_wait_q);
 }
 
 static void btmrvl_free_adapter(struct btmrvl_private *priv)
@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *
 
 	btmrvl_cal_data_dt(priv);
 
+	btmrvl_pscan_window_reporting(priv, 0x01);
+
 	priv->btmrvl_dev.psmode = 1;
 	btmrvl_enable_ps(priv);
 
@@ -498,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *
 	return 0;
 }
 
+static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+	struct sk_buff *skb;
+	long ret;
+	u8 buf[8];
+
+	buf[0] = MRVL_VENDOR_PKT;
+	buf[1] = sizeof(bdaddr_t);
+	memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+	skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: changing btmrvl device address failed (%ld)",
+		       hdev->name, ret);
+		return ret;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
 /*
  * This function handles the event generated by firmware, rx data
  * received from firmware, and tx data sent from kernel.
@@ -591,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_p
 	hdev->flush = btmrvl_flush;
 	hdev->send  = btmrvl_send_frame;
 	hdev->setup = btmrvl_setup;
+	hdev->set_bdaddr = btmrvl_set_bdaddr;
 
 	hdev->dev_type = priv->btmrvl_dev.dev_type;
 
@@ -645,12 +710,17 @@ struct btmrvl_private *btmrvl_add_card(v
 	init_waitqueue_head(&priv->main_thread.wait_q);
 	priv->main_thread.task = kthread_run(btmrvl_service_main_thread,
 				&priv->main_thread, "btmrvl_main_service");
+	if (IS_ERR(priv->main_thread.task))
+		goto err_thread;
 
 	priv->btmrvl_dev.card = card;
 	priv->btmrvl_dev.tx_dnld_rdy = true;
 
 	return priv;
 
+err_thread:
+	btmrvl_free_adapter(priv);
+
 err_adapter:
 	kfree(priv);
 
@@ -666,6 +736,7 @@ int btmrvl_remove_card(struct btmrvl_pri
 	hdev = priv->btmrvl_dev.hcidev;
 
 	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	wake_up_interruptible(&priv->adapter->event_hs_wait_q);
 
 	kthread_stop(priv->main_thread.task);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_sdio.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_sdio.c
--- linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_sdio.c	2014-08-07 04:57:58.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_sdio.c	2014-09-28 21:40:28.000000000 -0400
@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device b
 	.helper		= "/*(DEBLOBBED)*/",
 	.firmware	= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_8688,
+	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 64,
 };
 
@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device b
 	.helper		= NULL,
 	.firmware	= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_87xx,
+	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 256,
 };
 
@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device b
 	.helper		= NULL,
 	.firmware	= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_87xx,
+	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 256,
 };
 
@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device b
 	.helper		= NULL,
 	.firmware	= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_88xx,
+	.support_pscan_win_report = true,
 	.sd_blksz_fw_dl	= 256,
 };
 
@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio
 		card->firmware = data->firmware;
 		card->reg = data->reg;
 		card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
+		card->support_pscan_win_report = data->support_pscan_win_report;
 	}
 
 	if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1164,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct de
 	}
 
 	priv = card->priv;
+	hcidev = priv->btmrvl_dev.hcidev;
+	BT_DBG("%s: SDIO suspend", hcidev->name);
+	hci_suspend_dev(hcidev);
+	skb_queue_purge(&priv->adapter->tx_queue);
 
 	if (priv->adapter->hs_state != HS_ACTIVATED) {
 		if (btmrvl_enable_hs(priv)) {
@@ -1171,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct de
 			return -EBUSY;
 		}
 	}
-	hcidev = priv->btmrvl_dev.hcidev;
-	BT_DBG("%s: SDIO suspend", hcidev->name);
-	hci_suspend_dev(hcidev);
-	skb_queue_purge(&priv->adapter->tx_queue);
 
 	priv->adapter->is_suspended = true;
 
@@ -1216,13 +1221,13 @@ static int btmrvl_sdio_resume(struct dev
 		return 0;
 	}
 
-	priv->adapter->is_suspended = false;
-	hcidev = priv->btmrvl_dev.hcidev;
-	BT_DBG("%s: SDIO resume", hcidev->name);
-	hci_resume_dev(hcidev);
 	priv->hw_wakeup_firmware(priv);
 	priv->adapter->hs_state = HS_DEACTIVATED;
+	hcidev = priv->btmrvl_dev.hcidev;
 	BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
+	priv->adapter->is_suspended = false;
+	BT_DBG("%s: SDIO resume", hcidev->name);
+	hci_resume_dev(hcidev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_sdio.h linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_sdio.h
--- linux-libre-3.16-gnu/drivers/bluetooth/btmrvl_sdio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/btmrvl_sdio.h	2014-09-28 17:29:07.000000000 -0400
@@ -89,6 +89,7 @@ struct btmrvl_sdio_card {
 	const char *helper;
 	const char *firmware;
 	const struct btmrvl_sdio_card_reg *reg;
+	bool support_pscan_win_report;
 	u16 sd_blksz_fw_dl;
 	u8 rx_unit;
 	struct btmrvl_private *priv;
@@ -98,6 +99,7 @@ struct btmrvl_sdio_device {
 	const char *helper;
 	const char *firmware;
 	const struct btmrvl_sdio_card_reg *reg;
+	const bool support_pscan_win_report;
 	u16 sd_blksz_fw_dl;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/btusb.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/btusb.c
--- linux-libre-3.16-gnu/drivers/bluetooth/btusb.c	2014-08-07 04:57:56.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/btusb.c	2014-09-28 21:40:24.000000000 -0400
@@ -30,9 +30,6 @@
 
 #define VERSION "0.6"
 
-static bool ignore_dga;
-static bool ignore_csr;
-static bool ignore_sniffer;
 static bool disable_scofix;
 static bool force_scofix;
 
@@ -49,7 +46,9 @@ static struct usb_driver btusb_driver;
 #define BTUSB_WRONG_SCO_MTU	0x40
 #define BTUSB_ATH3012		0x80
 #define BTUSB_INTEL		0x100
-#define BTUSB_BCM_PATCHRAM	0x200
+#define BTUSB_INTEL_BOOT	0x200
+#define BTUSB_BCM_PATCHRAM	0x400
+#define BTUSB_MARVELL		0x800
 
 static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -115,12 +114,19 @@ static const struct usb_device_id btusb_
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
 	  .driver_info = BTUSB_BCM_PATCHRAM },
 
+	/* ASUSTek Computer - Broadcom based */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
+
 	/* Belkin F8065bf - Broadcom based */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
 
 	/* IMC Networks - Broadcom based */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
 
+	/* Intel Bluetooth USB Bootloader (RAM module) */
+	{ USB_DEVICE(0x8087, 0x0a5a),
+	  .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
+
 	{ }	/* Terminating entry */
 };
 
@@ -175,6 +181,7 @@ static const struct usb_device_id blackl
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -228,15 +235,21 @@ static const struct usb_device_id blackl
 	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
 
 	/* CSR BlueCore Bluetooth Sniffer */
-	{ USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
+	{ USB_DEVICE(0x0a12, 0x0002),
+	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
 
 	/* Frontline ComProbe Bluetooth Sniffer */
-	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
+	{ USB_DEVICE(0x16d3, 0x0002),
+	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
 
 	/* Intel Bluetooth device */
 	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
 	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
 
+	/* Marvell device */
+	{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
+	{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
+
 	{ }	/* Terminating entry */
 };
 
@@ -1182,6 +1195,51 @@ static int btusb_setup_intel_patching(st
 	return 0;
 }
 
+#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
+
+static int btusb_check_bdaddr_intel(struct hci_dev *hdev)
+{
+	struct sk_buff *skb;
+	struct hci_rp_read_bd_addr *rp;
+
+	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		BT_ERR("%s reading Intel device address failed (%ld)",
+		       hdev->name, PTR_ERR(skb));
+		return PTR_ERR(skb);
+	}
+
+	if (skb->len != sizeof(*rp)) {
+		BT_ERR("%s Intel device address length mismatch", hdev->name);
+		kfree_skb(skb);
+		return -EIO;
+	}
+
+	rp = (struct hci_rp_read_bd_addr *) skb->data;
+	if (rp->status) {
+		BT_ERR("%s Intel device address result failed (%02x)",
+		       hdev->name, rp->status);
+		kfree_skb(skb);
+		return -bt_to_errno(rp->status);
+	}
+
+	/* For some Intel based controllers, the default Bluetooth device
+	 * address 00:03:19:9E:8B:00 can be found. These controllers are
+	 * fully operational, but have the danger of duplicate addresses
+	 * and that in turn can cause problems with Bluetooth operation.
+	 */
+	if (!bacmp(&rp->bdaddr, BDADDR_INTEL)) {
+		BT_ERR("%s found Intel default device address (%pMR)",
+		       hdev->name, &rp->bdaddr);
+		set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+	}
+
+	kfree_skb(skb);
+
+	return 0;
+}
+
 static int btusb_setup_intel(struct hci_dev *hdev)
 {
 	struct sk_buff *skb;
@@ -1254,6 +1312,7 @@ static int btusb_setup_intel(struct hci_
 		BT_INFO("%s: Intel device is already patched. patch num: %02x",
 			hdev->name, ver->fw_patch_num);
 		kfree_skb(skb);
+		btusb_check_bdaddr_intel(hdev);
 		return 0;
 	}
 
@@ -1266,6 +1325,7 @@ static int btusb_setup_intel(struct hci_
 	fw = btusb_setup_intel_get_fw(hdev, ver);
 	if (!fw) {
 		kfree_skb(skb);
+		btusb_check_bdaddr_intel(hdev);
 		return 0;
 	}
 	fw_ptr = fw->data;
@@ -1345,6 +1405,7 @@ static int btusb_setup_intel(struct hci_
 	BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
 		hdev->name);
 
+	btusb_check_bdaddr_intel(hdev);
 	return 0;
 
 exit_mfg_disable:
@@ -1359,6 +1420,8 @@ exit_mfg_disable:
 	kfree_skb(skb);
 
 	BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
+
+	btusb_check_bdaddr_intel(hdev);
 	return 0;
 
 exit_mfg_deactivate:
@@ -1379,9 +1442,52 @@ exit_mfg_deactivate:
 	BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
 		hdev->name);
 
+	btusb_check_bdaddr_intel(hdev);
 	return 0;
 }
 
+static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+	struct sk_buff *skb;
+	long ret;
+
+	skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: changing Intel device address failed (%ld)",
+			hdev->name, ret);
+		return ret;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
+				    const bdaddr_t *bdaddr)
+{
+	struct sk_buff *skb;
+	u8 buf[8];
+	long ret;
+
+	buf[0] = 0xfe;
+	buf[1] = sizeof(bdaddr_t);
+	memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+	skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: changing Marvell device address failed (%ld)",
+		       hdev->name, ret);
+		return ret;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
+
 static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -1395,6 +1501,7 @@ static int btusb_setup_bcm_patchram(stru
 	u16 opcode;
 	struct sk_buff *skb;
 	struct hci_rp_read_local_version *ver;
+	struct hci_rp_read_bd_addr *bda;
 	long ret;
 
 	snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
@@ -1404,8 +1511,7 @@ static int btusb_setup_bcm_patchram(stru
 
 	ret = reject_firmware(&fw, fw_name, &hdev->dev);
 	if (ret < 0) {
-		BT_INFO("%s: BCM: patch %s not found", hdev->name,
-			fw_name);
+		BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
 		return 0;
 	}
 
@@ -1524,12 +1630,67 @@ reset_fw:
 		ver->lmp_ver, ver->lmp_subver);
 	kfree_skb(skb);
 
+	/* Read BD Address */
+	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)",
+			hdev->name, ret);
+		goto done;
+	}
+
+	if (skb->len != sizeof(*bda)) {
+		BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch",
+			hdev->name);
+		kfree_skb(skb);
+		ret = -EIO;
+		goto done;
+	}
+
+	bda = (struct hci_rp_read_bd_addr *) skb->data;
+	if (bda->status) {
+		BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)",
+		       hdev->name, bda->status);
+		kfree_skb(skb);
+		ret = -bt_to_errno(bda->status);
+		goto done;
+	}
+
+	/* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
+	 * with no configured address.
+	 */
+	if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) {
+		BT_INFO("%s: BCM: using default device address (%pMR)",
+			hdev->name, &bda->bdaddr);
+		set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+	}
+
+	kfree_skb(skb);
+
 done:
 	release_firmware(fw);
 
 	return ret;
 }
 
+static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+	struct sk_buff *skb;
+	long ret;
+
+	skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: BCM: Change address command failed (%ld)",
+			hdev->name, ret);
+		return ret;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
 static int btusb_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
@@ -1554,15 +1715,6 @@ static int btusb_probe(struct usb_interf
 	if (id->driver_info == BTUSB_IGNORE)
 		return -ENODEV;
 
-	if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
-		return -ENODEV;
-
-	if (ignore_csr && id->driver_info & BTUSB_CSR)
-		return -ENODEV;
-
-	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
-		return -ENODEV;
-
 	if (id->driver_info & BTUSB_ATH3012) {
 		struct usb_device *udev = interface_to_usbdev(intf);
 
@@ -1635,11 +1787,21 @@ static int btusb_probe(struct usb_interf
 	if (id->driver_info & BTUSB_BCM92035)
 		hdev->setup = btusb_setup_bcm92035;
 
-	if (id->driver_info & BTUSB_BCM_PATCHRAM)
+	if (id->driver_info & BTUSB_BCM_PATCHRAM) {
 		hdev->setup = btusb_setup_bcm_patchram;
+		hdev->set_bdaddr = btusb_set_bdaddr_bcm;
+	}
 
-	if (id->driver_info & BTUSB_INTEL)
+	if (id->driver_info & BTUSB_INTEL) {
 		hdev->setup = btusb_setup_intel;
+		hdev->set_bdaddr = btusb_set_bdaddr_intel;
+	}
+
+	if (id->driver_info & BTUSB_MARVELL)
+		hdev->set_bdaddr = btusb_set_bdaddr_marvell;
+
+	if (id->driver_info & BTUSB_INTEL_BOOT)
+		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
 
 	/* Interface numbers are hardcoded in the specification */
 	data->isoc = usb_ifnum_to_if(data->udev, 1);
@@ -1679,8 +1841,18 @@ static int btusb_probe(struct usb_interf
 		/* New sniffer firmware has crippled HCI interface */
 		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
 			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+	}
 
-		data->isoc = NULL;
+	if (id->driver_info & BTUSB_INTEL_BOOT) {
+		/* A bug in the bootloader causes that interrupt interface is
+		 * only enabled after receiving SetInterface(0, AltSetting=0).
+		 */
+		err = usb_set_interface(data->udev, 0, 0);
+		if (err < 0) {
+			BT_ERR("failed to set interface 0, alt 0 %d", err);
+			hci_free_dev(hdev);
+			return err;
+		}
 	}
 
 	if (data->isoc) {
@@ -1845,15 +2017,6 @@ static struct usb_driver btusb_driver =
 
 module_usb_driver(btusb_driver);
 
-module_param(ignore_dga, bool, 0644);
-MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
-
-module_param(ignore_csr, bool, 0644);
-MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
-
-module_param(ignore_sniffer, bool, 0644);
-MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
-
 module_param(disable_scofix, bool, 0644);
 MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/hci_h5.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_h5.c
--- linux-libre-3.16-gnu/drivers/bluetooth/hci_h5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_h5.c	2014-09-28 17:29:07.000000000 -0400
@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hc
 
 static int h5_rx_crc(struct hci_uart *hu, unsigned char c)
 {
-	struct h5 *h5 = hu->priv;
-
 	h5_complete_rx_pkt(hu);
-	h5_reset_rx(h5);
 
 	return 0;
 }
@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart
 		h5->rx_pending = 2;
 	} else {
 		h5_complete_rx_pkt(hu);
-		h5_reset_rx(h5);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/hci_ldisc.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_ldisc.c
--- linux-libre-3.16-gnu/drivers/bluetooth/hci_ldisc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_ldisc.c	2014-09-28 17:29:07.000000000 -0400
@@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct
 	if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
 		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
 
+	if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
+		set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
+
 	if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
 		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
 
@@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci
 	return 0;
 }
 
+static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
+{
+	unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) |
+				    BIT(HCI_UART_RESET_ON_INIT) |
+				    BIT(HCI_UART_CREATE_AMP) |
+				    BIT(HCI_UART_INIT_PENDING) |
+				    BIT(HCI_UART_EXT_CONFIG);
+
+	if ((flags & ~valid_flags))
+		return -EINVAL;
+
+	hu->hdev_flags = flags;
+
+	return 0;
+}
+
 /* hci_uart_tty_ioctl()
  *
  *    Process IOCTL system call for the tty device.
@@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty
 		return -EUNATCH;
 
 	case HCIUARTGETDEVICE:
-		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+		if (test_bit(HCI_UART_REGISTERED, &hu->flags))
 			return hu->hdev->id;
 		return -EUNATCH;
 
 	case HCIUARTSETFLAGS:
 		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
 			return -EBUSY;
-		hu->hdev_flags = arg;
+		err = hci_uart_set_flags(hu, arg);
+		if (err)
+			return err;
 		break;
 
 	case HCIUARTGETFLAGS:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/hci_uart.h linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_uart.h
--- linux-libre-3.16-gnu/drivers/bluetooth/hci_uart.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_uart.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,7 @@
 #define HCI_UART_RESET_ON_INIT	1
 #define HCI_UART_CREATE_AMP	2
 #define HCI_UART_INIT_PENDING	3
+#define HCI_UART_EXT_CONFIG	4
 
 struct hci_uart;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/hci_vhci.c linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_vhci.c
--- linux-libre-3.16-gnu/drivers/bluetooth/hci_vhci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/hci_vhci.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#define VERSION "1.4"
+#define VERSION "1.5"
 
 static bool amp;
 
@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_de
 	return 0;
 }
 
-static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
+static int vhci_create_device(struct vhci_data *data, __u8 opcode)
 {
 	struct hci_dev *hdev;
 	struct sk_buff *skb;
+	__u8 dev_type;
+
+	/* bits 0-1 are dev_type (BR/EDR or AMP) */
+	dev_type = opcode & 0x03;
+
+	if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
+		return -EINVAL;
+
+	/* bits 2-5 are reserved (must be zero) */
+	if (opcode & 0x3c)
+		return -EINVAL;
 
 	skb = bt_skb_alloc(4, GFP_KERNEL);
 	if (!skb)
@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhc
 	hdev->flush = vhci_flush;
 	hdev->send  = vhci_send_frame;
 
+	/* bit 6 is for external configuration */
+	if (opcode & 0x40)
+		set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
+
+	/* bit 7 is for raw device */
+	if (opcode & 0x80)
+		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
 		hci_free_dev(hdev);
@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhc
 	bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
 
 	*skb_put(skb, 1) = 0xff;
-	*skb_put(skb, 1) = dev_type;
+	*skb_put(skb, 1) = opcode;
 	put_unaligned_le16(hdev->id, skb_put(skb, 2));
 	skb_queue_tail(&data->readq, skb);
 
@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(stru
 {
 	size_t len = iov_length(iov, count);
 	struct sk_buff *skb;
-	__u8 pkt_type, dev_type;
+	__u8 pkt_type, opcode;
 	unsigned long i;
 	int ret;
 
@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(stru
 
 		cancel_delayed_work_sync(&data->open_timeout);
 
-		dev_type = *((__u8 *) skb->data);
+		opcode = *((__u8 *) skb->data);
 		skb_pull(skb, 1);
 
 		if (skb->len > 0) {
@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(stru
 
 		kfree_skb(skb);
 
-		if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
-			return -EINVAL;
-
-		ret = vhci_create_device(data, dev_type);
+		ret = vhci_create_device(data, opcode);
 		break;
 
 	default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bluetooth/Kconfig linux-libre-3.17-rc7-gnu/drivers/bluetooth/Kconfig
--- linux-libre-3.16-gnu/drivers/bluetooth/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bluetooth/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -30,8 +30,8 @@ config BT_HCIUART
 	help
 	  Bluetooth HCI UART driver.
 	  This driver is required if you want to use Bluetooth devices with
-	  serial port interface. You will also need this driver if you have 
-	  UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card 
+	  serial port interface. You will also need this driver if you have
+	  UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
 	  adapter and BrainBoxes Bluetooth PC Card.
 
 	  Say Y here to compile support for Bluetooth UART devices into the
@@ -41,9 +41,9 @@ config BT_HCIUART_H4
 	bool "UART (H4) protocol support"
 	depends on BT_HCIUART
 	help
-	  UART (H4) is serial protocol for communication between Bluetooth 
-	  device and host. This protocol is required for most Bluetooth devices 
-	  with UART interface, including PCMCIA and CF cards. 
+	  UART (H4) is serial protocol for communication between Bluetooth
+	  device and host. This protocol is required for most Bluetooth devices
+	  with UART interface, including PCMCIA and CF cards.
 
 	  Say Y here to compile support for HCI UART (H4) protocol.
 
@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP
 	depends on BT_HCIUART
 	select BITREVERSE
 	help
-	  BCSP (BlueCore Serial Protocol) is serial protocol for communication 
+	  BCSP (BlueCore Serial Protocol) is serial protocol for communication
 	  between Bluetooth device and host. This protocol is required for non
 	  USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
 	  CF cards.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/arm-cci.c linux-libre-3.17-rc7-gnu/drivers/bus/arm-cci.c
--- linux-libre-3.16-gnu/drivers/bus/arm-cci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/arm-cci.c	2014-09-28 17:29:07.000000000 -0400
@@ -397,7 +397,8 @@ static irqreturn_t pmu_handle_irq(int ir
 		hw_counter = &event->hw;
 
 		/* Did this counter overflow? */
-		if (!pmu_read_register(idx, CCI_PMU_OVRFLW) & CCI_PMU_OVRFLW_FLAG)
+		if (!(pmu_read_register(idx, CCI_PMU_OVRFLW) &
+		      CCI_PMU_OVRFLW_FLAG))
 			continue;
 
 		pmu_write_register(CCI_PMU_OVRFLW_FLAG, idx, CCI_PMU_OVRFLW);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/arm-ccn.c linux-libre-3.17-rc7-gnu/drivers/bus/arm-ccn.c
--- linux-libre-3.16-gnu/drivers/bus/arm-ccn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/bus/arm-ccn.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1390 @@
+/*
+ * This program is free software; you can 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) 2014 ARM Limited
+ */
+
+#include <linux/ctype.h>
+#include <linux/hrtimer.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define CCN_NUM_XP_PORTS 2
+#define CCN_NUM_VCS 4
+#define CCN_NUM_REGIONS	256
+#define CCN_REGION_SIZE	0x10000
+
+#define CCN_ALL_OLY_ID			0xff00
+#define CCN_ALL_OLY_ID__OLY_ID__SHIFT			0
+#define CCN_ALL_OLY_ID__OLY_ID__MASK			0x1f
+#define CCN_ALL_OLY_ID__NODE_ID__SHIFT			8
+#define CCN_ALL_OLY_ID__NODE_ID__MASK			0x3f
+
+#define CCN_MN_ERRINT_STATUS		0x0008
+#define CCN_MN_ERRINT_STATUS__INTREQ__DESSERT		0x11
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__ENABLE	0x02
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLED	0x20
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE	0x22
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_ENABLE	0x04
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLED	0x40
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLE	0x44
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE	0x08
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED	0x80
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE	0x88
+#define CCN_MN_OLY_COMP_LIST_63_0	0x01e0
+#define CCN_MN_ERR_SIG_VAL_63_0		0x0300
+#define CCN_MN_ERR_SIG_VAL_63_0__DT			(1 << 1)
+
+#define CCN_DT_ACTIVE_DSM		0x0000
+#define CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(n)		((n) * 8)
+#define CCN_DT_ACTIVE_DSM__DSM_ID__MASK			0xff
+#define CCN_DT_CTL			0x0028
+#define CCN_DT_CTL__DT_EN				(1 << 0)
+#define CCN_DT_PMEVCNT(n)		(0x0100 + (n) * 0x8)
+#define CCN_DT_PMCCNTR			0x0140
+#define CCN_DT_PMCCNTRSR		0x0190
+#define CCN_DT_PMOVSR			0x0198
+#define CCN_DT_PMOVSR_CLR		0x01a0
+#define CCN_DT_PMCR			0x01a8
+#define CCN_DT_PMCR__OVFL_INTR_EN			(1 << 6)
+#define CCN_DT_PMCR__PMU_EN				(1 << 0)
+#define CCN_DT_PMSR			0x01b0
+#define CCN_DT_PMSR_REQ			0x01b8
+#define CCN_DT_PMSR_CLR			0x01c0
+
+#define CCN_HNF_PMU_EVENT_SEL		0x0600
+#define CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(n)		((n) * 4)
+#define CCN_HNF_PMU_EVENT_SEL__ID__MASK			0xf
+
+#define CCN_XP_DT_CONFIG		0x0300
+#define CCN_XP_DT_CONFIG__DT_CFG__SHIFT(n)		((n) * 4)
+#define CCN_XP_DT_CONFIG__DT_CFG__MASK			0xf
+#define CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH		0x0
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT_0_OR_1	0x1
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(n)		(0x2 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(n)	(0x4 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(d, n) (0x8 + (d) * 4 + (n))
+#define CCN_XP_DT_INTERFACE_SEL		0x0308
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(n)	(0 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK	0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(n)	(1 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK	0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(n)	(2 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK	0x3
+#define CCN_XP_DT_CMP_VAL_L(n)		(0x0310 + (n) * 0x40)
+#define CCN_XP_DT_CMP_VAL_H(n)		(0x0318 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_L(n)		(0x0320 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_H(n)		(0x0328 + (n) * 0x40)
+#define CCN_XP_DT_CONTROL		0x0370
+#define CCN_XP_DT_CONTROL__DT_ENABLE			(1 << 0)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(n)		(12 + (n) * 4)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__MASK		0xf
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS		0xf
+#define CCN_XP_PMU_EVENT_SEL		0x0600
+#define CCN_XP_PMU_EVENT_SEL__ID__SHIFT(n)		((n) * 7)
+#define CCN_XP_PMU_EVENT_SEL__ID__MASK			0x3f
+
+#define CCN_SBAS_PMU_EVENT_SEL		0x0600
+#define CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(n)		((n) * 4)
+#define CCN_SBAS_PMU_EVENT_SEL__ID__MASK		0xf
+
+#define CCN_RNI_PMU_EVENT_SEL		0x0600
+#define CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(n)		((n) * 4)
+#define CCN_RNI_PMU_EVENT_SEL__ID__MASK			0xf
+
+#define CCN_TYPE_MN	0x01
+#define CCN_TYPE_DT	0x02
+#define CCN_TYPE_HNF	0x04
+#define CCN_TYPE_HNI	0x05
+#define CCN_TYPE_XP	0x08
+#define CCN_TYPE_SBSX	0x0c
+#define CCN_TYPE_SBAS	0x10
+#define CCN_TYPE_RNI_1P	0x14
+#define CCN_TYPE_RNI_2P	0x15
+#define CCN_TYPE_RNI_3P	0x16
+#define CCN_TYPE_RND_1P	0x18 /* RN-D = RN-I + DVM */
+#define CCN_TYPE_RND_2P	0x19
+#define CCN_TYPE_RND_3P	0x1a
+#define CCN_TYPE_CYCLES	0xff /* Pseudotype */
+
+#define CCN_EVENT_WATCHPOINT 0xfe /* Pseudoevent */
+
+#define CCN_NUM_PMU_EVENTS		4
+#define CCN_NUM_XP_WATCHPOINTS		2 /* See DT.dbg_id.num_watchpoints */
+#define CCN_NUM_PMU_EVENT_COUNTERS	8 /* See DT.dbg_id.num_pmucntr */
+#define CCN_IDX_PMU_CYCLE_COUNTER	CCN_NUM_PMU_EVENT_COUNTERS
+
+#define CCN_NUM_PREDEFINED_MASKS	4
+#define CCN_IDX_MASK_ANY		(CCN_NUM_PMU_EVENT_COUNTERS + 0)
+#define CCN_IDX_MASK_EXACT		(CCN_NUM_PMU_EVENT_COUNTERS + 1)
+#define CCN_IDX_MASK_ORDER		(CCN_NUM_PMU_EVENT_COUNTERS + 2)
+#define CCN_IDX_MASK_OPCODE		(CCN_NUM_PMU_EVENT_COUNTERS + 3)
+
+struct arm_ccn_component {
+	void __iomem *base;
+	u32 type;
+
+	DECLARE_BITMAP(pmu_events_mask, CCN_NUM_PMU_EVENTS);
+	union {
+		struct {
+			DECLARE_BITMAP(dt_cmp_mask, CCN_NUM_XP_WATCHPOINTS);
+		} xp;
+	};
+};
+
+#define pmu_to_arm_ccn(_pmu) container_of(container_of(_pmu, \
+	struct arm_ccn_dt, pmu), struct arm_ccn, dt)
+
+struct arm_ccn_dt {
+	int id;
+	void __iomem *base;
+
+	spinlock_t config_lock;
+
+	DECLARE_BITMAP(pmu_counters_mask, CCN_NUM_PMU_EVENT_COUNTERS + 1);
+	struct {
+		struct arm_ccn_component *source;
+		struct perf_event *event;
+	} pmu_counters[CCN_NUM_PMU_EVENT_COUNTERS + 1];
+
+	struct {
+	       u64 l, h;
+	} cmp_mask[CCN_NUM_PMU_EVENT_COUNTERS + CCN_NUM_PREDEFINED_MASKS];
+
+	struct hrtimer hrtimer;
+
+	struct pmu pmu;
+};
+
+struct arm_ccn {
+	struct device *dev;
+	void __iomem *base;
+	unsigned irq_used:1;
+	unsigned sbas_present:1;
+	unsigned sbsx_present:1;
+
+	int num_nodes;
+	struct arm_ccn_component *node;
+
+	int num_xps;
+	struct arm_ccn_component *xp;
+
+	struct arm_ccn_dt dt;
+};
+
+
+static int arm_ccn_node_to_xp(int node)
+{
+	return node / CCN_NUM_XP_PORTS;
+}
+
+static int arm_ccn_node_to_xp_port(int node)
+{
+	return node % CCN_NUM_XP_PORTS;
+}
+
+
+/*
+ * Bit shifts and masks in these defines must be kept in sync with
+ * arm_ccn_pmu_config_set() and CCN_FORMAT_ATTRs below!
+ */
+#define CCN_CONFIG_NODE(_config)	(((_config) >> 0) & 0xff)
+#define CCN_CONFIG_XP(_config)		(((_config) >> 0) & 0xff)
+#define CCN_CONFIG_TYPE(_config)	(((_config) >> 8) & 0xff)
+#define CCN_CONFIG_EVENT(_config)	(((_config) >> 16) & 0xff)
+#define CCN_CONFIG_PORT(_config)	(((_config) >> 24) & 0x3)
+#define CCN_CONFIG_VC(_config)		(((_config) >> 26) & 0x7)
+#define CCN_CONFIG_DIR(_config)		(((_config) >> 29) & 0x1)
+#define CCN_CONFIG_MASK(_config)	(((_config) >> 30) & 0xf)
+
+static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port)
+{
+	*config &= ~((0xff << 0) | (0xff << 8) | (0xff << 24));
+	*config |= (node_xp << 0) | (type << 8) | (port << 24);
+}
+
+static ssize_t arm_ccn_pmu_format_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dev_ext_attribute *ea = container_of(attr,
+			struct dev_ext_attribute, attr);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", (char *)ea->var);
+}
+
+#define CCN_FORMAT_ATTR(_name, _config) \
+	struct dev_ext_attribute arm_ccn_pmu_format_attr_##_name = \
+			{ __ATTR(_name, S_IRUGO, arm_ccn_pmu_format_show, \
+			NULL), _config }
+
+static CCN_FORMAT_ATTR(node, "config:0-7");
+static CCN_FORMAT_ATTR(xp, "config:0-7");
+static CCN_FORMAT_ATTR(type, "config:8-15");
+static CCN_FORMAT_ATTR(event, "config:16-23");
+static CCN_FORMAT_ATTR(port, "config:24-25");
+static CCN_FORMAT_ATTR(vc, "config:26-28");
+static CCN_FORMAT_ATTR(dir, "config:29-29");
+static CCN_FORMAT_ATTR(mask, "config:30-33");
+static CCN_FORMAT_ATTR(cmp_l, "config1:0-62");
+static CCN_FORMAT_ATTR(cmp_h, "config2:0-59");
+
+static struct attribute *arm_ccn_pmu_format_attrs[] = {
+	&arm_ccn_pmu_format_attr_node.attr.attr,
+	&arm_ccn_pmu_format_attr_xp.attr.attr,
+	&arm_ccn_pmu_format_attr_type.attr.attr,
+	&arm_ccn_pmu_format_attr_event.attr.attr,
+	&arm_ccn_pmu_format_attr_port.attr.attr,
+	&arm_ccn_pmu_format_attr_vc.attr.attr,
+	&arm_ccn_pmu_format_attr_dir.attr.attr,
+	&arm_ccn_pmu_format_attr_mask.attr.attr,
+	&arm_ccn_pmu_format_attr_cmp_l.attr.attr,
+	&arm_ccn_pmu_format_attr_cmp_h.attr.attr,
+	NULL
+};
+
+static struct attribute_group arm_ccn_pmu_format_attr_group = {
+	.name = "format",
+	.attrs = arm_ccn_pmu_format_attrs,
+};
+
+
+struct arm_ccn_pmu_event {
+	struct device_attribute attr;
+	u32 type;
+	u32 event;
+	int num_ports;
+	int num_vcs;
+	const char *def;
+	int mask;
+};
+
+#define CCN_EVENT_ATTR(_name) \
+	__ATTR(_name, S_IRUGO, arm_ccn_pmu_event_show, NULL)
+
+/*
+ * Events defined in TRM for MN, HN-I and SBSX are actually watchpoints set on
+ * their ports in XP they are connected to. For the sake of usability they are
+ * explicitly defined here (and translated into a relevant watchpoint in
+ * arm_ccn_pmu_event_init()) so the user can easily request them without deep
+ * knowledge of the flit format.
+ */
+
+#define CCN_EVENT_MN(_name, _def, _mask) { .attr = CCN_EVENT_ATTR(mn_##_name), \
+		.type = CCN_TYPE_MN, .event = CCN_EVENT_WATCHPOINT, \
+		.num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, \
+		.def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNI(_name, _def, _mask) { \
+		.attr = CCN_EVENT_ATTR(hni_##_name), .type = CCN_TYPE_HNI, \
+		.event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+		.num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_SBSX(_name, _def, _mask) { \
+		.attr = CCN_EVENT_ATTR(sbsx_##_name), .type = CCN_TYPE_SBSX, \
+		.event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+		.num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNF(_name, _event) { .attr = CCN_EVENT_ATTR(hnf_##_name), \
+		.type = CCN_TYPE_HNF, .event = _event, }
+
+#define CCN_EVENT_XP(_name, _event) { .attr = CCN_EVENT_ATTR(xp_##_name), \
+		.type = CCN_TYPE_XP, .event = _event, \
+		.num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, }
+
+/*
+ * RN-I & RN-D (RN-D = RN-I + DVM) nodes have different type ID depending
+ * on configuration. One of them is picked to represent the whole group,
+ * as they all share the same event types.
+ */
+#define CCN_EVENT_RNI(_name, _event) { .attr = CCN_EVENT_ATTR(rni_##_name), \
+		.type = CCN_TYPE_RNI_3P, .event = _event, }
+
+#define CCN_EVENT_SBAS(_name, _event) { .attr = CCN_EVENT_ATTR(sbas_##_name), \
+		.type = CCN_TYPE_SBAS, .event = _event, }
+
+#define CCN_EVENT_CYCLES(_name) { .attr = CCN_EVENT_ATTR(_name), \
+		.type = CCN_TYPE_CYCLES }
+
+
+static ssize_t arm_ccn_pmu_event_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arm_ccn_pmu_event *event = container_of(attr,
+			struct arm_ccn_pmu_event, attr);
+	ssize_t res;
+
+	res = snprintf(buf, PAGE_SIZE, "type=0x%x", event->type);
+	if (event->event)
+		res += snprintf(buf + res, PAGE_SIZE - res, ",event=0x%x",
+				event->event);
+	if (event->def)
+		res += snprintf(buf + res, PAGE_SIZE - res, ",%s",
+				event->def);
+	if (event->mask)
+		res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x",
+				event->mask);
+	res += snprintf(buf + res, PAGE_SIZE - res, "\n");
+
+	return res;
+}
+
+static umode_t arm_ccn_pmu_events_is_visible(struct kobject *kobj,
+				     struct attribute *attr, int index)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+	struct device_attribute *dev_attr = container_of(attr,
+			struct device_attribute, attr);
+	struct arm_ccn_pmu_event *event = container_of(dev_attr,
+			struct arm_ccn_pmu_event, attr);
+
+	if (event->type == CCN_TYPE_SBAS && !ccn->sbas_present)
+		return 0;
+	if (event->type == CCN_TYPE_SBSX && !ccn->sbsx_present)
+		return 0;
+
+	return attr->mode;
+}
+
+static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = {
+	CCN_EVENT_MN(eobarrier, "dir=0,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_MN(ecbarrier, "dir=0,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_MN(dvmop, "dir=0,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+	CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+	CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+	CCN_EVENT_HNI(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+	CCN_EVENT_HNI(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+			CCN_IDX_MASK_ORDER),
+	CCN_EVENT_SBSX(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+	CCN_EVENT_SBSX(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+	CCN_EVENT_SBSX(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+	CCN_EVENT_SBSX(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+	CCN_EVENT_SBSX(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+			CCN_IDX_MASK_ORDER),
+	CCN_EVENT_HNF(cache_miss, 0x1),
+	CCN_EVENT_HNF(l3_sf_cache_access, 0x02),
+	CCN_EVENT_HNF(cache_fill, 0x3),
+	CCN_EVENT_HNF(pocq_retry, 0x4),
+	CCN_EVENT_HNF(pocq_reqs_recvd, 0x5),
+	CCN_EVENT_HNF(sf_hit, 0x6),
+	CCN_EVENT_HNF(sf_evictions, 0x7),
+	CCN_EVENT_HNF(snoops_sent, 0x8),
+	CCN_EVENT_HNF(snoops_broadcast, 0x9),
+	CCN_EVENT_HNF(l3_eviction, 0xa),
+	CCN_EVENT_HNF(l3_fill_invalid_way, 0xb),
+	CCN_EVENT_HNF(mc_retries, 0xc),
+	CCN_EVENT_HNF(mc_reqs, 0xd),
+	CCN_EVENT_HNF(qos_hh_retry, 0xe),
+	CCN_EVENT_RNI(rdata_beats_p0, 0x1),
+	CCN_EVENT_RNI(rdata_beats_p1, 0x2),
+	CCN_EVENT_RNI(rdata_beats_p2, 0x3),
+	CCN_EVENT_RNI(rxdat_flits, 0x4),
+	CCN_EVENT_RNI(txdat_flits, 0x5),
+	CCN_EVENT_RNI(txreq_flits, 0x6),
+	CCN_EVENT_RNI(txreq_flits_retried, 0x7),
+	CCN_EVENT_RNI(rrt_full, 0x8),
+	CCN_EVENT_RNI(wrt_full, 0x9),
+	CCN_EVENT_RNI(txreq_flits_replayed, 0xa),
+	CCN_EVENT_XP(upload_starvation, 0x1),
+	CCN_EVENT_XP(download_starvation, 0x2),
+	CCN_EVENT_XP(respin, 0x3),
+	CCN_EVENT_XP(valid_flit, 0x4),
+	CCN_EVENT_XP(watchpoint, CCN_EVENT_WATCHPOINT),
+	CCN_EVENT_SBAS(rdata_beats_p0, 0x1),
+	CCN_EVENT_SBAS(rxdat_flits, 0x4),
+	CCN_EVENT_SBAS(txdat_flits, 0x5),
+	CCN_EVENT_SBAS(txreq_flits, 0x6),
+	CCN_EVENT_SBAS(txreq_flits_retried, 0x7),
+	CCN_EVENT_SBAS(rrt_full, 0x8),
+	CCN_EVENT_SBAS(wrt_full, 0x9),
+	CCN_EVENT_SBAS(txreq_flits_replayed, 0xa),
+	CCN_EVENT_CYCLES(cycles),
+};
+
+/* Populated in arm_ccn_init() */
+static struct attribute
+		*arm_ccn_pmu_events_attrs[ARRAY_SIZE(arm_ccn_pmu_events) + 1];
+
+static struct attribute_group arm_ccn_pmu_events_attr_group = {
+	.name = "events",
+	.is_visible = arm_ccn_pmu_events_is_visible,
+	.attrs = arm_ccn_pmu_events_attrs,
+};
+
+
+static u64 *arm_ccn_pmu_get_cmp_mask(struct arm_ccn *ccn, const char *name)
+{
+	unsigned long i;
+
+	if (WARN_ON(!name || !name[0] || !isxdigit(name[0]) || !name[1]))
+		return NULL;
+	i = isdigit(name[0]) ? name[0] - '0' : 0xa + tolower(name[0]) - 'a';
+
+	switch (name[1]) {
+	case 'l':
+		return &ccn->dt.cmp_mask[i].l;
+	case 'h':
+		return &ccn->dt.cmp_mask[i].h;
+	default:
+		return NULL;
+	}
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+	u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+
+	return mask ? snprintf(buf, PAGE_SIZE, "0x%016llx\n", *mask) : -EINVAL;
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+	u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+	int err = -EINVAL;
+
+	if (mask)
+		err = kstrtoull(buf, 0, mask);
+
+	return err ? err : count;
+}
+
+#define CCN_CMP_MASK_ATTR(_name) \
+	struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+			__ATTR(_name, S_IRUGO | S_IWUSR, \
+			arm_ccn_pmu_cmp_mask_show, arm_ccn_pmu_cmp_mask_store)
+
+#define CCN_CMP_MASK_ATTR_RO(_name) \
+	struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+			__ATTR(_name, S_IRUGO, arm_ccn_pmu_cmp_mask_show, NULL)
+
+static CCN_CMP_MASK_ATTR(0l);
+static CCN_CMP_MASK_ATTR(0h);
+static CCN_CMP_MASK_ATTR(1l);
+static CCN_CMP_MASK_ATTR(1h);
+static CCN_CMP_MASK_ATTR(2l);
+static CCN_CMP_MASK_ATTR(2h);
+static CCN_CMP_MASK_ATTR(3l);
+static CCN_CMP_MASK_ATTR(3h);
+static CCN_CMP_MASK_ATTR(4l);
+static CCN_CMP_MASK_ATTR(4h);
+static CCN_CMP_MASK_ATTR(5l);
+static CCN_CMP_MASK_ATTR(5h);
+static CCN_CMP_MASK_ATTR(6l);
+static CCN_CMP_MASK_ATTR(6h);
+static CCN_CMP_MASK_ATTR(7l);
+static CCN_CMP_MASK_ATTR(7h);
+static CCN_CMP_MASK_ATTR_RO(8l);
+static CCN_CMP_MASK_ATTR_RO(8h);
+static CCN_CMP_MASK_ATTR_RO(9l);
+static CCN_CMP_MASK_ATTR_RO(9h);
+static CCN_CMP_MASK_ATTR_RO(al);
+static CCN_CMP_MASK_ATTR_RO(ah);
+static CCN_CMP_MASK_ATTR_RO(bl);
+static CCN_CMP_MASK_ATTR_RO(bh);
+
+static struct attribute *arm_ccn_pmu_cmp_mask_attrs[] = {
+	&arm_ccn_pmu_cmp_mask_attr_0l.attr, &arm_ccn_pmu_cmp_mask_attr_0h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_1l.attr, &arm_ccn_pmu_cmp_mask_attr_1h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_2l.attr, &arm_ccn_pmu_cmp_mask_attr_2h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_3l.attr, &arm_ccn_pmu_cmp_mask_attr_3h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_4l.attr, &arm_ccn_pmu_cmp_mask_attr_4h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_5l.attr, &arm_ccn_pmu_cmp_mask_attr_5h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_6l.attr, &arm_ccn_pmu_cmp_mask_attr_6h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_7l.attr, &arm_ccn_pmu_cmp_mask_attr_7h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_8l.attr, &arm_ccn_pmu_cmp_mask_attr_8h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_9l.attr, &arm_ccn_pmu_cmp_mask_attr_9h.attr,
+	&arm_ccn_pmu_cmp_mask_attr_al.attr, &arm_ccn_pmu_cmp_mask_attr_ah.attr,
+	&arm_ccn_pmu_cmp_mask_attr_bl.attr, &arm_ccn_pmu_cmp_mask_attr_bh.attr,
+	NULL
+};
+
+static struct attribute_group arm_ccn_pmu_cmp_mask_attr_group = {
+	.name = "cmp_mask",
+	.attrs = arm_ccn_pmu_cmp_mask_attrs,
+};
+
+
+/*
+ * Default poll period is 10ms, which is way over the top anyway,
+ * as in the worst case scenario (an event every cycle), with 1GHz
+ * clocked bus, the smallest, 32 bit counter will overflow in
+ * more than 4s.
+ */
+static unsigned int arm_ccn_pmu_poll_period_us = 10000;
+module_param_named(pmu_poll_period_us, arm_ccn_pmu_poll_period_us, uint,
+		S_IRUGO | S_IWUSR);
+
+static ktime_t arm_ccn_pmu_timer_period(void)
+{
+	return ns_to_ktime((u64)arm_ccn_pmu_poll_period_us * 1000);
+}
+
+
+static const struct attribute_group *arm_ccn_pmu_attr_groups[] = {
+	&arm_ccn_pmu_events_attr_group,
+	&arm_ccn_pmu_format_attr_group,
+	&arm_ccn_pmu_cmp_mask_attr_group,
+	NULL
+};
+
+
+static int arm_ccn_pmu_alloc_bit(unsigned long *bitmap, unsigned long size)
+{
+	int bit;
+
+	do {
+		bit = find_first_zero_bit(bitmap, size);
+		if (bit >= size)
+			return -EAGAIN;
+	} while (test_and_set_bit(bit, bitmap));
+
+	return bit;
+}
+
+/* All RN-I and RN-D nodes have identical PMUs */
+static int arm_ccn_pmu_type_eq(u32 a, u32 b)
+{
+	if (a == b)
+		return 1;
+
+	switch (a) {
+	case CCN_TYPE_RNI_1P:
+	case CCN_TYPE_RNI_2P:
+	case CCN_TYPE_RNI_3P:
+	case CCN_TYPE_RND_1P:
+	case CCN_TYPE_RND_2P:
+	case CCN_TYPE_RND_3P:
+		switch (b) {
+		case CCN_TYPE_RNI_1P:
+		case CCN_TYPE_RNI_2P:
+		case CCN_TYPE_RNI_3P:
+		case CCN_TYPE_RND_1P:
+		case CCN_TYPE_RND_2P:
+		case CCN_TYPE_RND_3P:
+			return 1;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void arm_ccn_pmu_event_destroy(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+
+	if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+		clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask);
+	} else {
+		struct arm_ccn_component *source =
+				ccn->dt.pmu_counters[hw->idx].source;
+
+		if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP &&
+				CCN_CONFIG_EVENT(event->attr.config) ==
+				CCN_EVENT_WATCHPOINT)
+			clear_bit(hw->config_base, source->xp.dt_cmp_mask);
+		else
+			clear_bit(hw->config_base, source->pmu_events_mask);
+		clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+	}
+
+	ccn->dt.pmu_counters[hw->idx].source = NULL;
+	ccn->dt.pmu_counters[hw->idx].event = NULL;
+}
+
+static int arm_ccn_pmu_event_init(struct perf_event *event)
+{
+	struct arm_ccn *ccn;
+	struct hw_perf_event *hw = &event->hw;
+	u32 node_xp, type, event_id;
+	int valid, bit;
+	struct arm_ccn_component *source;
+	int i;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	ccn = pmu_to_arm_ccn(event->pmu);
+	event->destroy = arm_ccn_pmu_event_destroy;
+
+	if (hw->sample_period) {
+		dev_warn(ccn->dev, "Sampling not supported!\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (has_branch_stack(event) || event->attr.exclude_user ||
+			event->attr.exclude_kernel || event->attr.exclude_hv ||
+			event->attr.exclude_idle) {
+		dev_warn(ccn->dev, "Can't exclude execution levels!\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (event->cpu < 0) {
+		dev_warn(ccn->dev, "Can't provide per-task data!\n");
+		return -EOPNOTSUPP;
+	}
+
+	node_xp = CCN_CONFIG_NODE(event->attr.config);
+	type = CCN_CONFIG_TYPE(event->attr.config);
+	event_id = CCN_CONFIG_EVENT(event->attr.config);
+
+	/* Validate node/xp vs topology */
+	switch (type) {
+	case CCN_TYPE_XP:
+		if (node_xp >= ccn->num_xps) {
+			dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp);
+			return -EINVAL;
+		}
+		break;
+	case CCN_TYPE_CYCLES:
+		break;
+	default:
+		if (node_xp >= ccn->num_nodes) {
+			dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp);
+			return -EINVAL;
+		}
+		if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) {
+			dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n",
+					type, node_xp);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	/* Validate event ID vs available for the type */
+	for (i = 0, valid = 0; i < ARRAY_SIZE(arm_ccn_pmu_events) && !valid;
+			i++) {
+		struct arm_ccn_pmu_event *e = &arm_ccn_pmu_events[i];
+		u32 port = CCN_CONFIG_PORT(event->attr.config);
+		u32 vc = CCN_CONFIG_VC(event->attr.config);
+
+		if (!arm_ccn_pmu_type_eq(type, e->type))
+			continue;
+		if (event_id != e->event)
+			continue;
+		if (e->num_ports && port >= e->num_ports) {
+			dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n",
+					port, node_xp);
+			return -EINVAL;
+		}
+		if (e->num_vcs && vc >= e->num_vcs) {
+			dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n",
+					vc, node_xp);
+			return -EINVAL;
+		}
+		valid = 1;
+	}
+	if (!valid) {
+		dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n",
+				event_id, node_xp);
+		return -EINVAL;
+	}
+
+	/* Watchpoint-based event for a node is actually set on XP */
+	if (event_id == CCN_EVENT_WATCHPOINT && type != CCN_TYPE_XP) {
+		u32 port;
+
+		type = CCN_TYPE_XP;
+		port = arm_ccn_node_to_xp_port(node_xp);
+		node_xp = arm_ccn_node_to_xp(node_xp);
+
+		arm_ccn_pmu_config_set(&event->attr.config,
+				node_xp, type, port);
+	}
+
+	/* Allocate the cycle counter */
+	if (type == CCN_TYPE_CYCLES) {
+		if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER,
+				ccn->dt.pmu_counters_mask))
+			return -EAGAIN;
+
+		hw->idx = CCN_IDX_PMU_CYCLE_COUNTER;
+		ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event;
+
+		return 0;
+	}
+
+	/* Allocate an event counter */
+	hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask,
+			CCN_NUM_PMU_EVENT_COUNTERS);
+	if (hw->idx < 0) {
+		dev_warn(ccn->dev, "No more counters available!\n");
+		return -EAGAIN;
+	}
+
+	if (type == CCN_TYPE_XP)
+		source = &ccn->xp[node_xp];
+	else
+		source = &ccn->node[node_xp];
+	ccn->dt.pmu_counters[hw->idx].source = source;
+
+	/* Allocate an event source or a watchpoint */
+	if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT)
+		bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask,
+				CCN_NUM_XP_WATCHPOINTS);
+	else
+		bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask,
+				CCN_NUM_PMU_EVENTS);
+	if (bit < 0) {
+		dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n",
+				node_xp);
+		clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+		return -EAGAIN;
+	}
+	hw->config_base = bit;
+
+	ccn->dt.pmu_counters[hw->idx].event = event;
+
+	return 0;
+}
+
+static u64 arm_ccn_pmu_read_counter(struct arm_ccn *ccn, int idx)
+{
+	u64 res;
+
+	if (idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+#ifdef readq
+		res = readq(ccn->dt.base + CCN_DT_PMCCNTR);
+#else
+		/* 40 bit counter, can do snapshot and read in two parts */
+		writel(0x1, ccn->dt.base + CCN_DT_PMSR_REQ);
+		while (!(readl(ccn->dt.base + CCN_DT_PMSR) & 0x1))
+			;
+		writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+		res = readl(ccn->dt.base + CCN_DT_PMCCNTRSR + 4) & 0xff;
+		res <<= 32;
+		res |= readl(ccn->dt.base + CCN_DT_PMCCNTRSR);
+#endif
+	} else {
+		res = readl(ccn->dt.base + CCN_DT_PMEVCNT(idx));
+	}
+
+	return res;
+}
+
+static void arm_ccn_pmu_event_update(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	u64 prev_count, new_count, mask;
+
+	do {
+		prev_count = local64_read(&hw->prev_count);
+		new_count = arm_ccn_pmu_read_counter(ccn, hw->idx);
+	} while (local64_xchg(&hw->prev_count, new_count) != prev_count);
+
+	mask = (1LLU << (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER ? 40 : 32)) - 1;
+
+	local64_add((new_count - prev_count) & mask, &event->count);
+}
+
+static void arm_ccn_pmu_xp_dt_config(struct perf_event *event, int enable)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	struct arm_ccn_component *xp;
+	u32 val, dt_cfg;
+
+	if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+		xp = &ccn->xp[CCN_CONFIG_XP(event->attr.config)];
+	else
+		xp = &ccn->xp[arm_ccn_node_to_xp(
+				CCN_CONFIG_NODE(event->attr.config))];
+
+	if (enable)
+		dt_cfg = hw->event_base;
+	else
+		dt_cfg = CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH;
+
+	spin_lock(&ccn->dt.config_lock);
+
+	val = readl(xp->base + CCN_XP_DT_CONFIG);
+	val &= ~(CCN_XP_DT_CONFIG__DT_CFG__MASK <<
+			CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx));
+	val |= dt_cfg << CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx);
+	writel(val, xp->base + CCN_XP_DT_CONFIG);
+
+	spin_unlock(&ccn->dt.config_lock);
+}
+
+static void arm_ccn_pmu_event_start(struct perf_event *event, int flags)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+
+	local64_set(&event->hw.prev_count,
+			arm_ccn_pmu_read_counter(ccn, hw->idx));
+	hw->state = 0;
+
+	if (!ccn->irq_used)
+		hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
+				HRTIMER_MODE_REL);
+
+	/* Set the DT bus input, engaging the counter */
+	arm_ccn_pmu_xp_dt_config(event, 1);
+}
+
+static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	u64 timeout;
+
+	/* Disable counting, setting the DT bus to pass-through mode */
+	arm_ccn_pmu_xp_dt_config(event, 0);
+
+	if (!ccn->irq_used)
+		hrtimer_cancel(&ccn->dt.hrtimer);
+
+	/* Let the DT bus drain */
+	timeout = arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) +
+			ccn->num_xps;
+	while (arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) <
+			timeout)
+		cpu_relax();
+
+	if (flags & PERF_EF_UPDATE)
+		arm_ccn_pmu_event_update(event);
+
+	hw->state |= PERF_HES_STOPPED;
+}
+
+static void arm_ccn_pmu_xp_watchpoint_config(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	struct arm_ccn_component *source =
+			ccn->dt.pmu_counters[hw->idx].source;
+	unsigned long wp = hw->config_base;
+	u32 val;
+	u64 cmp_l = event->attr.config1;
+	u64 cmp_h = event->attr.config2;
+	u64 mask_l = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].l;
+	u64 mask_h = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].h;
+
+	hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(wp);
+
+	/* Direction (RX/TX), device (port) & virtual channel */
+	val = readl(source->base + CCN_XP_DT_INTERFACE_SEL);
+	val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK <<
+			CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp));
+	val |= CCN_CONFIG_DIR(event->attr.config) <<
+			CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp);
+	val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK <<
+			CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp));
+	val |= CCN_CONFIG_PORT(event->attr.config) <<
+			CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp);
+	val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK <<
+			CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp));
+	val |= CCN_CONFIG_VC(event->attr.config) <<
+			CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp);
+	writel(val, source->base + CCN_XP_DT_INTERFACE_SEL);
+
+	/* Comparison values */
+	writel(cmp_l & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_L(wp));
+	writel((cmp_l >> 32) & 0xefffffff,
+			source->base + CCN_XP_DT_CMP_VAL_L(wp) + 4);
+	writel(cmp_h & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_H(wp));
+	writel((cmp_h >> 32) & 0x0fffffff,
+			source->base + CCN_XP_DT_CMP_VAL_H(wp) + 4);
+
+	/* Mask */
+	writel(mask_l & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_L(wp));
+	writel((mask_l >> 32) & 0xefffffff,
+			source->base + CCN_XP_DT_CMP_MASK_L(wp) + 4);
+	writel(mask_h & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_H(wp));
+	writel((mask_h >> 32) & 0x0fffffff,
+			source->base + CCN_XP_DT_CMP_MASK_H(wp) + 4);
+}
+
+static void arm_ccn_pmu_xp_event_config(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	struct arm_ccn_component *source =
+			ccn->dt.pmu_counters[hw->idx].source;
+	u32 val, id;
+
+	hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(hw->config_base);
+
+	id = (CCN_CONFIG_VC(event->attr.config) << 4) |
+			(CCN_CONFIG_PORT(event->attr.config) << 3) |
+			(CCN_CONFIG_EVENT(event->attr.config) << 0);
+
+	val = readl(source->base + CCN_XP_PMU_EVENT_SEL);
+	val &= ~(CCN_XP_PMU_EVENT_SEL__ID__MASK <<
+			CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+	val |= id << CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+	writel(val, source->base + CCN_XP_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_node_event_config(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	struct arm_ccn_component *source =
+			ccn->dt.pmu_counters[hw->idx].source;
+	u32 type = CCN_CONFIG_TYPE(event->attr.config);
+	u32 val, port;
+
+	port = arm_ccn_node_to_xp_port(CCN_CONFIG_NODE(event->attr.config));
+	hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(port,
+			hw->config_base);
+
+	/* These *_event_sel regs should be identical, but let's make sure... */
+	BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL != CCN_SBAS_PMU_EVENT_SEL);
+	BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL != CCN_RNI_PMU_EVENT_SEL);
+	BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(1) !=
+			CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1));
+	BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1) !=
+			CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(1));
+	BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__MASK !=
+			CCN_SBAS_PMU_EVENT_SEL__ID__MASK);
+	BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__MASK !=
+			CCN_RNI_PMU_EVENT_SEL__ID__MASK);
+	if (WARN_ON(type != CCN_TYPE_HNF && type != CCN_TYPE_SBAS &&
+			!arm_ccn_pmu_type_eq(type, CCN_TYPE_RNI_3P)))
+		return;
+
+	/* Set the event id for the pre-allocated counter */
+	val = readl(source->base + CCN_HNF_PMU_EVENT_SEL);
+	val &= ~(CCN_HNF_PMU_EVENT_SEL__ID__MASK <<
+		CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+	val |= CCN_CONFIG_EVENT(event->attr.config) <<
+		CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+	writel(val, source->base + CCN_HNF_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_event_config(struct perf_event *event)
+{
+	struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+	struct hw_perf_event *hw = &event->hw;
+	u32 xp, offset, val;
+
+	/* Cycle counter requires no setup */
+	if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER)
+		return;
+
+	if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+		xp = CCN_CONFIG_XP(event->attr.config);
+	else
+		xp = arm_ccn_node_to_xp(CCN_CONFIG_NODE(event->attr.config));
+
+	spin_lock(&ccn->dt.config_lock);
+
+	/* Set the DT bus "distance" register */
+	offset = (hw->idx / 4) * 4;
+	val = readl(ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+	val &= ~(CCN_DT_ACTIVE_DSM__DSM_ID__MASK <<
+			CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4));
+	val |= xp << CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4);
+	writel(val, ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+
+	if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP) {
+		if (CCN_CONFIG_EVENT(event->attr.config) ==
+				CCN_EVENT_WATCHPOINT)
+			arm_ccn_pmu_xp_watchpoint_config(event);
+		else
+			arm_ccn_pmu_xp_event_config(event);
+	} else {
+		arm_ccn_pmu_node_event_config(event);
+	}
+
+	spin_unlock(&ccn->dt.config_lock);
+}
+
+static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hw = &event->hw;
+
+	arm_ccn_pmu_event_config(event);
+
+	hw->state = PERF_HES_STOPPED;
+
+	if (flags & PERF_EF_START)
+		arm_ccn_pmu_event_start(event, PERF_EF_UPDATE);
+
+	return 0;
+}
+
+static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
+{
+	arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void arm_ccn_pmu_event_read(struct perf_event *event)
+{
+	arm_ccn_pmu_event_update(event);
+}
+
+static irqreturn_t arm_ccn_pmu_overflow_handler(struct arm_ccn_dt *dt)
+{
+	u32 pmovsr = readl(dt->base + CCN_DT_PMOVSR);
+	int idx;
+
+	if (!pmovsr)
+		return IRQ_NONE;
+
+	writel(pmovsr, dt->base + CCN_DT_PMOVSR_CLR);
+
+	BUILD_BUG_ON(CCN_IDX_PMU_CYCLE_COUNTER != CCN_NUM_PMU_EVENT_COUNTERS);
+
+	for (idx = 0; idx < CCN_NUM_PMU_EVENT_COUNTERS + 1; idx++) {
+		struct perf_event *event = dt->pmu_counters[idx].event;
+		int overflowed = pmovsr & BIT(idx);
+
+		WARN_ON_ONCE(overflowed && !event);
+
+		if (!event || !overflowed)
+			continue;
+
+		arm_ccn_pmu_event_update(event);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
+{
+	struct arm_ccn_dt *dt = container_of(hrtimer, struct arm_ccn_dt,
+			hrtimer);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	arm_ccn_pmu_overflow_handler(dt);
+	local_irq_restore(flags);
+
+	hrtimer_forward_now(hrtimer, arm_ccn_pmu_timer_period());
+	return HRTIMER_RESTART;
+}
+
+
+static DEFINE_IDA(arm_ccn_pmu_ida);
+
+static int arm_ccn_pmu_init(struct arm_ccn *ccn)
+{
+	int i;
+	char *name;
+
+	/* Initialize DT subsystem */
+	ccn->dt.base = ccn->base + CCN_REGION_SIZE;
+	spin_lock_init(&ccn->dt.config_lock);
+	writel(CCN_DT_CTL__DT_EN, ccn->dt.base + CCN_DT_CTL);
+	writel(CCN_DT_PMCR__OVFL_INTR_EN | CCN_DT_PMCR__PMU_EN,
+			ccn->dt.base + CCN_DT_PMCR);
+	writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+	for (i = 0; i < ccn->num_xps; i++) {
+		writel(0, ccn->xp[i].base + CCN_XP_DT_CONFIG);
+		writel((CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+				CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(0)) |
+				(CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+				CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(1)) |
+				CCN_XP_DT_CONTROL__DT_ENABLE,
+				ccn->xp[i].base + CCN_XP_DT_CONTROL);
+	}
+	ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].l = ~0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].h = ~0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].l = 0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].h = 0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].l = ~0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].h = ~(0x1 << 15);
+	ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].l = ~0;
+	ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].h = ~(0x1f << 9);
+
+	/* Get a convenient /sys/event_source/devices/ name */
+	ccn->dt.id = ida_simple_get(&arm_ccn_pmu_ida, 0, 0, GFP_KERNEL);
+	if (ccn->dt.id == 0) {
+		name = "ccn";
+	} else {
+		int len = snprintf(NULL, 0, "ccn_%d", ccn->dt.id);
+
+		name = devm_kzalloc(ccn->dev, len + 1, GFP_KERNEL);
+		snprintf(name, len + 1, "ccn_%d", ccn->dt.id);
+	}
+
+	/* Perf driver registration */
+	ccn->dt.pmu = (struct pmu) {
+		.attr_groups = arm_ccn_pmu_attr_groups,
+		.task_ctx_nr = perf_invalid_context,
+		.event_init = arm_ccn_pmu_event_init,
+		.add = arm_ccn_pmu_event_add,
+		.del = arm_ccn_pmu_event_del,
+		.start = arm_ccn_pmu_event_start,
+		.stop = arm_ccn_pmu_event_stop,
+		.read = arm_ccn_pmu_event_read,
+	};
+
+	/* No overflow interrupt? Have to use a timer instead. */
+	if (!ccn->irq_used) {
+		dev_info(ccn->dev, "No access to interrupts, using timer.\n");
+		hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC,
+				HRTIMER_MODE_REL);
+		ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler;
+	}
+
+	return perf_pmu_register(&ccn->dt.pmu, name, -1);
+}
+
+static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
+{
+	int i;
+
+	for (i = 0; i < ccn->num_xps; i++)
+		writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
+	writel(0, ccn->dt.base + CCN_DT_PMCR);
+	perf_pmu_unregister(&ccn->dt.pmu);
+	ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
+}
+
+
+static int arm_ccn_for_each_valid_region(struct arm_ccn *ccn,
+		int (*callback)(struct arm_ccn *ccn, int region,
+		void __iomem *base, u32 type, u32 id))
+{
+	int region;
+
+	for (region = 0; region < CCN_NUM_REGIONS; region++) {
+		u32 val, type, id;
+		void __iomem *base;
+		int err;
+
+		val = readl(ccn->base + CCN_MN_OLY_COMP_LIST_63_0 +
+				4 * (region / 32));
+		if (!(val & (1 << (region % 32))))
+			continue;
+
+		base = ccn->base + region * CCN_REGION_SIZE;
+		val = readl(base + CCN_ALL_OLY_ID);
+		type = (val >> CCN_ALL_OLY_ID__OLY_ID__SHIFT) &
+				CCN_ALL_OLY_ID__OLY_ID__MASK;
+		id = (val >> CCN_ALL_OLY_ID__NODE_ID__SHIFT) &
+				CCN_ALL_OLY_ID__NODE_ID__MASK;
+
+		err = callback(ccn, region, base, type, id);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int arm_ccn_get_nodes_num(struct arm_ccn *ccn, int region,
+		void __iomem *base, u32 type, u32 id)
+{
+
+	if (type == CCN_TYPE_XP && id >= ccn->num_xps)
+		ccn->num_xps = id + 1;
+	else if (id >= ccn->num_nodes)
+		ccn->num_nodes = id + 1;
+
+	return 0;
+}
+
+static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region,
+		void __iomem *base, u32 type, u32 id)
+{
+	struct arm_ccn_component *component;
+
+	dev_dbg(ccn->dev, "Region %d: id=%u, type=0x%02x\n", region, id, type);
+
+	switch (type) {
+	case CCN_TYPE_MN:
+	case CCN_TYPE_DT:
+		return 0;
+	case CCN_TYPE_XP:
+		component = &ccn->xp[id];
+		break;
+	case CCN_TYPE_SBSX:
+		ccn->sbsx_present = 1;
+		component = &ccn->node[id];
+		break;
+	case CCN_TYPE_SBAS:
+		ccn->sbas_present = 1;
+		/* Fall-through */
+	default:
+		component = &ccn->node[id];
+		break;
+	}
+
+	component->base = base;
+	component->type = type;
+
+	return 0;
+}
+
+
+static irqreturn_t arm_ccn_error_handler(struct arm_ccn *ccn,
+		const u32 *err_sig_val)
+{
+	/* This should be really handled by firmware... */
+	dev_err(ccn->dev, "Error reported in %08x%08x%08x%08x%08x%08x.\n",
+			err_sig_val[5], err_sig_val[4], err_sig_val[3],
+			err_sig_val[2], err_sig_val[1], err_sig_val[0]);
+	dev_err(ccn->dev, "Disabling interrupt generation for all errors.\n");
+	writel(CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE,
+			ccn->base + CCN_MN_ERRINT_STATUS);
+
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t arm_ccn_irq_handler(int irq, void *dev_id)
+{
+	irqreturn_t res = IRQ_NONE;
+	struct arm_ccn *ccn = dev_id;
+	u32 err_sig_val[6];
+	u32 err_or;
+	int i;
+
+	/* PMU overflow is a special case */
+	err_or = err_sig_val[0] = readl(ccn->base + CCN_MN_ERR_SIG_VAL_63_0);
+	if (err_or & CCN_MN_ERR_SIG_VAL_63_0__DT) {
+		err_or &= ~CCN_MN_ERR_SIG_VAL_63_0__DT;
+		res = arm_ccn_pmu_overflow_handler(&ccn->dt);
+	}
+
+	/* Have to read all err_sig_vals to clear them */
+	for (i = 1; i < ARRAY_SIZE(err_sig_val); i++) {
+		err_sig_val[i] = readl(ccn->base +
+				CCN_MN_ERR_SIG_VAL_63_0 + i * 4);
+		err_or |= err_sig_val[i];
+	}
+	if (err_or)
+		res |= arm_ccn_error_handler(ccn, err_sig_val);
+
+	if (res != IRQ_NONE)
+		writel(CCN_MN_ERRINT_STATUS__INTREQ__DESSERT,
+				ccn->base + CCN_MN_ERRINT_STATUS);
+
+	return res;
+}
+
+
+static int arm_ccn_probe(struct platform_device *pdev)
+{
+	struct arm_ccn *ccn;
+	struct resource *res;
+	int err;
+
+	ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL);
+	if (!ccn)
+		return -ENOMEM;
+	ccn->dev = &pdev->dev;
+	platform_set_drvdata(pdev, ccn);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(ccn->dev, res->start,
+			resource_size(res), pdev->name))
+		return -EBUSY;
+
+	ccn->base = devm_ioremap(ccn->dev, res->start,
+				resource_size(res));
+	if (!ccn->base)
+		return -EFAULT;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res)
+		return -EINVAL;
+
+	/* Check if we can use the interrupt */
+	writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE,
+			ccn->base + CCN_MN_ERRINT_STATUS);
+	if (readl(ccn->base + CCN_MN_ERRINT_STATUS) &
+			CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED) {
+		/* Can set 'disable' bits, so can acknowledge interrupts */
+		writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE,
+				ccn->base + CCN_MN_ERRINT_STATUS);
+		err = devm_request_irq(ccn->dev, res->start,
+				arm_ccn_irq_handler, 0, dev_name(ccn->dev),
+				ccn);
+		if (err)
+			return err;
+
+		ccn->irq_used = 1;
+	}
+
+
+	/* Build topology */
+
+	err = arm_ccn_for_each_valid_region(ccn, arm_ccn_get_nodes_num);
+	if (err)
+		return err;
+
+	ccn->node = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_nodes,
+		GFP_KERNEL);
+	ccn->xp = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_xps,
+		GFP_KERNEL);
+	if (!ccn->node || !ccn->xp)
+		return -ENOMEM;
+
+	err = arm_ccn_for_each_valid_region(ccn, arm_ccn_init_nodes);
+	if (err)
+		return err;
+
+	return arm_ccn_pmu_init(ccn);
+}
+
+static int arm_ccn_remove(struct platform_device *pdev)
+{
+	struct arm_ccn *ccn = platform_get_drvdata(pdev);
+
+	arm_ccn_pmu_cleanup(ccn);
+
+	return 0;
+}
+
+static const struct of_device_id arm_ccn_match[] = {
+	{ .compatible = "arm,ccn-504", },
+	{},
+};
+
+static struct platform_driver arm_ccn_driver = {
+	.driver = {
+		.name = "arm-ccn",
+		.of_match_table = arm_ccn_match,
+	},
+	.probe = arm_ccn_probe,
+	.remove = arm_ccn_remove,
+};
+
+static int __init arm_ccn_init(void)
+{
+	int i;
+
+	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);
+}
+
+static void __exit arm_ccn_exit(void)
+{
+	platform_driver_unregister(&arm_ccn_driver);
+}
+
+module_init(arm_ccn_init);
+module_exit(arm_ccn_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/brcmstb_gisb.c linux-libre-3.17-rc7-gnu/drivers/bus/brcmstb_gisb.c
--- linux-libre-3.16-gnu/drivers/bus/brcmstb_gisb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/brcmstb_gisb.c	2014-09-28 17:29:07.000000000 -0400
@@ -212,9 +212,9 @@ static int brcmstb_gisb_arb_probe(struct
 	mutex_init(&gdev->lock);
 	INIT_LIST_HEAD(&gdev->next);
 
-	gdev->base = devm_request_and_ioremap(&pdev->dev, r);
-	if (!gdev->base)
-		return -ENOMEM;
+	gdev->base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(gdev->base))
+		return PTR_ERR(gdev->base);
 
 	err = devm_request_irq(&pdev->dev, timeout_irq,
 				brcmstb_gisb_timeout_handler, 0, pdev->name,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/imx-weim.c linux-libre-3.17-rc7-gnu/drivers/bus/imx-weim.c
--- linux-libre-3.16-gnu/drivers/bus/imx-weim.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/imx-weim.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,7 +162,9 @@ static int __init weim_parse_dt(struct p
 		}
 	}
 
-	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	ret = of_platform_populate(pdev->dev.of_node,
+				   of_default_bus_match_table,
+				   NULL, &pdev->dev);
 	if (ret)
 		dev_err(&pdev->dev, "%s fail to create devices.\n",
 			pdev->dev.of_node->full_name);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/Kconfig linux-libre-3.17-rc7-gnu/drivers/bus/Kconfig
--- linux-libre-3.16-gnu/drivers/bus/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,14 @@ config ARM_CCI
 	  Driver supporting the CCI cache coherent interconnect for ARM
 	  platforms.
 
+config ARM_CCN
+	bool "ARM CCN driver support"
+	depends on ARM || ARM64
+	depends on PERF_EVENTS
+	help
+	  PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
+	  interconnect.
+
 config VEXPRESS_CONFIG
 	bool "Versatile Express configuration bus"
 	default y if ARCH_VEXPRESS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/Makefile linux-libre-3.17-rc7-gnu/drivers/bus/Makefile
--- linux-libre-3.16-gnu/drivers/bus/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,7 +9,9 @@ obj-$(CONFIG_OMAP_OCP2SCP)	+= omap-ocp2s
 
 # Interconnect bus driver for OMAP SoCs.
 obj-$(CONFIG_OMAP_INTERCONNECT)	+= omap_l3_smx.o omap_l3_noc.o
-# CCI cache coherent interconnect for ARM platforms
+
+# Interconnect bus drivers for ARM platforms
 obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
+obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/bus/omap_l3_noc.h linux-libre-3.17-rc7-gnu/drivers/bus/omap_l3_noc.h
--- linux-libre-3.16-gnu/drivers/bus/omap_l3_noc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/bus/omap_l3_noc.h	2014-09-28 17:29:07.000000000 -0400
@@ -188,31 +188,31 @@ static struct l3_flagmux_data omap_l3_fl
 };
 
 static struct l3_masters_data omap_l3_masters[] = {
-	{ 0x0 , "MPU"},
-	{ 0x10, "CS_ADP"},
-	{ 0x14, "xxx"},
-	{ 0x20, "DSP"},
-	{ 0x30, "IVAHD"},
-	{ 0x40, "ISS"},
-	{ 0x44, "DucatiM3"},
-	{ 0x48, "FaceDetect"},
-	{ 0x50, "SDMA_Rd"},
-	{ 0x54, "SDMA_Wr"},
-	{ 0x58, "xxx"},
-	{ 0x5C, "xxx"},
-	{ 0x60, "SGX"},
-	{ 0x70, "DSS"},
-	{ 0x80, "C2C"},
-	{ 0x88, "xxx"},
-	{ 0x8C, "xxx"},
-	{ 0x90, "HSI"},
-	{ 0xA0, "MMC1"},
-	{ 0xA4, "MMC2"},
-	{ 0xA8, "MMC6"},
-	{ 0xB0, "UNIPRO1"},
-	{ 0xC0, "USBHOSTHS"},
-	{ 0xC4, "USBOTGHS"},
-	{ 0xC8, "USBHOSTFS"}
+	{ 0x00, "MPU"},
+	{ 0x04, "CS_ADP"},
+	{ 0x05, "xxx"},
+	{ 0x08, "DSP"},
+	{ 0x0C, "IVAHD"},
+	{ 0x10, "ISS"},
+	{ 0x11, "DucatiM3"},
+	{ 0x12, "FaceDetect"},
+	{ 0x14, "SDMA_Rd"},
+	{ 0x15, "SDMA_Wr"},
+	{ 0x16, "xxx"},
+	{ 0x17, "xxx"},
+	{ 0x18, "SGX"},
+	{ 0x1C, "DSS"},
+	{ 0x20, "C2C"},
+	{ 0x22, "xxx"},
+	{ 0x23, "xxx"},
+	{ 0x24, "HSI"},
+	{ 0x28, "MMC1"},
+	{ 0x29, "MMC2"},
+	{ 0x2A, "MMC6"},
+	{ 0x2C, "UNIPRO1"},
+	{ 0x30, "USBHOSTHS"},
+	{ 0x31, "USBOTGHS"},
+	{ 0x32, "USBHOSTFS"}
 };
 
 static struct l3_flagmux_data *omap_l3_flagmux[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/agp/frontend.c linux-libre-3.17-rc7-gnu/drivers/char/agp/frontend.c
--- linux-libre-3.16-gnu/drivers/char/agp/frontend.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/agp/frontend.c	2014-09-28 17:29:07.000000000 -0400
@@ -710,19 +710,6 @@ static int agp_open(struct inode *inode,
 	return 0;
 }
 
-
-static ssize_t agp_read(struct file *file, char __user *buf,
-			size_t count, loff_t * ppos)
-{
-	return -EINVAL;
-}
-
-static ssize_t agp_write(struct file *file, const char __user *buf,
-			 size_t count, loff_t * ppos)
-{
-	return -EINVAL;
-}
-
 static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
 {
 	struct agp_info userinfo;
@@ -1047,8 +1034,6 @@ static const struct file_operations agp_
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
-	.read		= agp_read,
-	.write		= agp_write,
 	.unlocked_ioctl	= agp_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_agp_ioctl,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/bsr.c linux-libre-3.17-rc7-gnu/drivers/char/bsr.c
--- linux-libre-3.16-gnu/drivers/char/bsr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/bsr.c	2014-09-28 17:29:07.000000000 -0400
@@ -259,7 +259,7 @@ static int bsr_add_node(struct device_no
 		}
 
 		cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
-						cur, cur->bsr_name);
+						cur, "%s", cur->bsr_name);
 		if (IS_ERR(cur->bsr_device)) {
 			printk(KERN_ERR "device_create failed for %s\n",
 			       cur->bsr_name);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/dsp56k.c linux-libre-3.17-rc7-gnu/drivers/char/dsp56k.c
--- linux-libre-3.16-gnu/drivers/char/dsp56k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/dsp56k.c	2014-09-28 17:29:07.000000000 -0400
@@ -383,7 +383,7 @@ static long dsp56k_ioctl(struct file *fi
 			return put_user(status, &hf->status);
 		}
 		case DSP56K_HOST_CMD:
-			if (arg > 31 || arg < 0)
+			if (arg > 31)
 				return -EINVAL;
 			mutex_lock(&dsp56k_mutex);
 			dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/hangcheck-timer.c linux-libre-3.17-rc7-gnu/drivers/char/hangcheck-timer.c
--- linux-libre-3.16-gnu/drivers/char/hangcheck-timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/hangcheck-timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,7 @@
 #include <asm/uaccess.h>
 #include <linux/sysrq.h>
 #include <linux/timer.h>
-#include <linux/time.h>
+#include <linux/hrtimer.h>
 
 #define VERSION_STR "0.9.1"
 
@@ -117,24 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_S390)
-# define HAVE_MONOTONIC
-# define TIMER_FREQ 1000000000ULL
-#else
-# define TIMER_FREQ 1000000000ULL
-#endif
-
-#ifdef HAVE_MONOTONIC
-extern unsigned long long monotonic_clock(void);
-#else
-static inline unsigned long long monotonic_clock(void)
-{
-	struct timespec ts;
-	getrawmonotonic(&ts);
-	return timespec_to_ns(&ts);
-}
-#endif  /* HAVE_MONOTONIC */
-
+#define TIMER_FREQ 1000000000ULL
 
 /* Last time scheduled */
 static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
@@ -143,12 +126,11 @@ static void hangcheck_fire(unsigned long
 
 static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
 
-
 static void hangcheck_fire(unsigned long data)
 {
 	unsigned long long cur_tsc, tsc_diff;
 
-	cur_tsc = monotonic_clock();
+	cur_tsc = ktime_get_ns();
 
 	if (cur_tsc > hangcheck_tsc)
 		tsc_diff = cur_tsc - hangcheck_tsc;
@@ -177,7 +159,7 @@ static void hangcheck_fire(unsigned long
 			tsc_diff, tsc_diff - hangcheck_tick*TIMER_FREQ);
 #endif
 	mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
-	hangcheck_tsc = monotonic_clock();
+	hangcheck_tsc = ktime_get_ns();
 }
 
 
@@ -185,16 +167,11 @@ static int __init hangcheck_init(void)
 {
 	printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
 	       VERSION_STR, hangcheck_tick, hangcheck_margin);
-#if defined (HAVE_MONOTONIC)
-	printk("Hangcheck: Using monotonic_clock().\n");
-#else
-	printk("Hangcheck: Using getrawmonotonic().\n");
-#endif  /* HAVE_MONOTONIC */
 	hangcheck_tsc_margin =
 		(unsigned long long)(hangcheck_margin + hangcheck_tick);
 	hangcheck_tsc_margin *= (unsigned long long)TIMER_FREQ;
 
-	hangcheck_tsc = monotonic_clock();
+	hangcheck_tsc = ktime_get_ns();
 	mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/hw_random/core.c linux-libre-3.17-rc7-gnu/drivers/char/hw_random/core.c
--- linux-libre-3.16-gnu/drivers/char/hw_random/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/hw_random/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/miscdevice.h>
+#include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/random.h>
@@ -50,10 +51,22 @@
 
 
 static struct hwrng *current_rng;
+static struct task_struct *hwrng_fill;
 static LIST_HEAD(rng_list);
 static DEFINE_MUTEX(rng_mutex);
 static int data_avail;
-static u8 *rng_buffer;
+static u8 *rng_buffer, *rng_fillbuf;
+static unsigned short current_quality;
+static unsigned short default_quality; /* = 0; default to "off" */
+
+module_param(current_quality, ushort, 0644);
+MODULE_PARM_DESC(current_quality,
+		 "current hwrng entropy estimation per mill");
+module_param(default_quality, ushort, 0644);
+MODULE_PARM_DESC(default_quality,
+		 "default entropy content of hwrng per mill");
+
+static void start_khwrngd(void);
 
 static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
 			       int wait);
@@ -68,12 +81,6 @@ static void add_early_randomness(struct
 	unsigned char bytes[16];
 	int bytes_read;
 
-	/*
-	 * Currently only virtio-rng cannot return data during device
-	 * probe, and that's handled in virtio-rng.c itself.  If there
-	 * are more such devices, this call to rng_get_data can be
-	 * made conditional here instead of doing it per-device.
-	 */
 	bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
 	if (bytes_read > 0)
 		add_device_randomness(bytes, bytes_read);
@@ -89,6 +96,15 @@ static inline int hwrng_init(struct hwrn
 			return ret;
 	}
 	add_early_randomness(rng);
+
+	current_quality = rng->quality ? : default_quality;
+	current_quality &= 1023;
+
+	if (current_quality == 0 && hwrng_fill)
+		kthread_stop(hwrng_fill);
+	if (current_quality > 0 && !hwrng_fill)
+		start_khwrngd();
+
 	return 0;
 }
 
@@ -325,6 +341,36 @@ err_misc_dereg:
 	goto out;
 }
 
+static int hwrng_fillfn(void *unused)
+{
+	long rc;
+
+	while (!kthread_should_stop()) {
+		if (!current_rng)
+			break;
+		rc = rng_get_data(current_rng, rng_fillbuf,
+				  rng_buffer_size(), 1);
+		if (rc <= 0) {
+			pr_warn("hwrng: no data available\n");
+			msleep_interruptible(10000);
+			continue;
+		}
+		add_hwgenerator_randomness((void *)rng_fillbuf, rc,
+					   rc * current_quality * 8 >> 10);
+	}
+	hwrng_fill = NULL;
+	return 0;
+}
+
+static void start_khwrngd(void)
+{
+	hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
+	if (hwrng_fill == ERR_PTR(-ENOMEM)) {
+		pr_err("hwrng_fill thread creation failed");
+		hwrng_fill = NULL;
+	}
+}
+
 int hwrng_register(struct hwrng *rng)
 {
 	int err = -EINVAL;
@@ -343,6 +389,13 @@ int hwrng_register(struct hwrng *rng)
 		if (!rng_buffer)
 			goto out_unlock;
 	}
+	if (!rng_fillbuf) {
+		rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL);
+		if (!rng_fillbuf) {
+			kfree(rng_buffer);
+			goto out_unlock;
+		}
+	}
 
 	/* Must not register two RNGs with the same name. */
 	err = -EEXIST;
@@ -406,8 +459,11 @@ void hwrng_unregister(struct hwrng *rng)
 				current_rng = NULL;
 		}
 	}
-	if (list_empty(&rng_list))
+	if (list_empty(&rng_list)) {
 		unregister_miscdev();
+		if (hwrng_fill)
+			kthread_stop(hwrng_fill);
+	}
 
 	mutex_unlock(&rng_mutex);
 }
@@ -418,6 +474,7 @@ static void __exit hwrng_exit(void)
 	mutex_lock(&rng_mutex);
 	BUG_ON(current_rng);
 	kfree(rng_buffer);
+	kfree(rng_fillbuf);
 	mutex_unlock(&rng_mutex);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/hw_random/virtio-rng.c linux-libre-3.17-rc7-gnu/drivers/char/hw_random/virtio-rng.c
--- linux-libre-3.16-gnu/drivers/char/hw_random/virtio-rng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/hw_random/virtio-rng.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,17 +28,17 @@
 static DEFINE_IDA(rng_index_ida);
 
 struct virtrng_info {
-	struct virtio_device *vdev;
 	struct hwrng hwrng;
 	struct virtqueue *vq;
-	unsigned int data_avail;
 	struct completion have_data;
-	bool busy;
 	char name[25];
+	unsigned int data_avail;
 	int index;
+	bool busy;
+	bool hwrng_register_done;
+	bool hwrng_removed;
 };
 
-static bool probe_done;
 
 static void random_recv_done(struct virtqueue *vq)
 {
@@ -69,12 +69,8 @@ static int virtio_read(struct hwrng *rng
 	int ret;
 	struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
 
-	/*
-	 * Don't ask host for data till we're setup.  This call can
-	 * happen during hwrng_register(), after commit d9e7972619.
-	 */
-	if (unlikely(!probe_done))
-		return 0;
+	if (vi->hwrng_removed)
+		return -ENODEV;
 
 	if (!vi->busy) {
 		vi->busy = true;
@@ -124,6 +120,7 @@ static int probe_common(struct virtio_de
 		.cleanup = virtio_cleanup,
 		.priv = (unsigned long)vi,
 		.name = vi->name,
+		.quality = 1000,
 	};
 	vdev->priv = vi;
 
@@ -137,25 +134,20 @@ static int probe_common(struct virtio_de
 		return err;
 	}
 
-	err = hwrng_register(&vi->hwrng);
-	if (err) {
-		vdev->config->del_vqs(vdev);
-		vi->vq = NULL;
-		kfree(vi);
-		ida_simple_remove(&rng_index_ida, index);
-		return err;
-	}
-
-	probe_done = true;
 	return 0;
 }
 
 static void remove_common(struct virtio_device *vdev)
 {
 	struct virtrng_info *vi = vdev->priv;
+
+	vi->hwrng_removed = true;
+	vi->data_avail = 0;
+	complete(&vi->have_data);
 	vdev->config->reset(vdev);
 	vi->busy = false;
-	hwrng_unregister(&vi->hwrng);
+	if (vi->hwrng_register_done)
+		hwrng_unregister(&vi->hwrng);
 	vdev->config->del_vqs(vdev);
 	ida_simple_remove(&rng_index_ida, vi->index);
 	kfree(vi);
@@ -171,6 +163,16 @@ static void virtrng_remove(struct virtio
 	remove_common(vdev);
 }
 
+static void virtrng_scan(struct virtio_device *vdev)
+{
+	struct virtrng_info *vi = vdev->priv;
+	int err;
+
+	err = hwrng_register(&vi->hwrng);
+	if (!err)
+		vi->hwrng_register_done = true;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int virtrng_freeze(struct virtio_device *vdev)
 {
@@ -195,6 +197,7 @@ static struct virtio_driver virtio_rng_d
 	.id_table =	id_table,
 	.probe =	virtrng_probe,
 	.remove =	virtrng_remove,
+	.scan =		virtrng_scan,
 #ifdef CONFIG_PM_SLEEP
 	.freeze =	virtrng_freeze,
 	.restore =	virtrng_restore,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/i8k.c linux-libre-3.17-rc7-gnu/drivers/char/i8k.c
--- linux-libre-3.16-gnu/drivers/char/i8k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/i8k.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,6 +65,8 @@ static char bios_version[4];
 static struct device *i8k_hwmon_dev;
 static u32 i8k_hwmon_flags;
 static int i8k_fan_mult;
+static int i8k_pwm_mult;
+static int i8k_fan_max = I8K_FAN_HIGH;
 
 #define I8K_HWMON_HAVE_TEMP1	(1 << 0)
 #define I8K_HWMON_HAVE_TEMP2	(1 << 1)
@@ -97,6 +99,10 @@ static int fan_mult = I8K_FAN_MULT;
 module_param(fan_mult, int, 0);
 MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
 
+static int fan_max = I8K_FAN_HIGH;
+module_param(fan_max, int, 0);
+MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed");
+
 static int i8k_open_fs(struct inode *inode, struct file *file);
 static long i8k_ioctl(struct file *, unsigned int, unsigned long);
 
@@ -276,7 +282,7 @@ static int i8k_set_fan(int fan, int spee
 {
 	struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
 
-	speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+	speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
 	regs.ebx = (fan & 0xff) | (speed << 8);
 
 	return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
@@ -521,7 +527,7 @@ static ssize_t i8k_hwmon_show_pwm(struct
 	status = i8k_get_fan_status(index);
 	if (status < 0)
 		return -EIO;
-	return sprintf(buf, "%d\n", clamp_val(status * 128, 0, 255));
+	return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
 }
 
 static ssize_t i8k_hwmon_set_pwm(struct device *dev,
@@ -535,7 +541,7 @@ static ssize_t i8k_hwmon_set_pwm(struct
 	err = kstrtoul(buf, 10, &val);
 	if (err)
 		return err;
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 128), 0, 2);
+	val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
 
 	mutex_lock(&i8k_mutex);
 	err = i8k_set_fan(index, val);
@@ -544,20 +550,6 @@ static ssize_t i8k_hwmon_set_pwm(struct
 	return err < 0 ? -EIO : count;
 }
 
-static ssize_t i8k_hwmon_show_label(struct device *dev,
-				    struct device_attribute *devattr,
-				    char *buf)
-{
-	static const char *labels[3] = {
-		"CPU",
-		"Left Fan",
-		"Right Fan",
-	};
-	int index = to_sensor_dev_attr(devattr)->index;
-
-	return sprintf(buf, "%s\n", labels[index]);
-}
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
 static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
@@ -570,41 +562,34 @@ static SENSOR_DEVICE_ATTR(fan2_input, S_
 			  I8K_FAN_RIGHT);
 static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
 			  i8k_hwmon_set_pwm, I8K_FAN_RIGHT);
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2);
 
 static struct attribute *i8k_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,	/* 0 */
-	&sensor_dev_attr_temp1_label.dev_attr.attr,	/* 1 */
-	&sensor_dev_attr_temp2_input.dev_attr.attr,	/* 2 */
-	&sensor_dev_attr_temp3_input.dev_attr.attr,	/* 3 */
-	&sensor_dev_attr_temp4_input.dev_attr.attr,	/* 4 */
-	&sensor_dev_attr_fan1_input.dev_attr.attr,	/* 5 */
-	&sensor_dev_attr_pwm1.dev_attr.attr,		/* 6 */
-	&sensor_dev_attr_fan1_label.dev_attr.attr,	/* 7 */
-	&sensor_dev_attr_fan2_input.dev_attr.attr,	/* 8 */
-	&sensor_dev_attr_pwm2.dev_attr.attr,		/* 9 */
-	&sensor_dev_attr_fan2_label.dev_attr.attr,	/* 10 */
+	&sensor_dev_attr_temp2_input.dev_attr.attr,	/* 1 */
+	&sensor_dev_attr_temp3_input.dev_attr.attr,	/* 2 */
+	&sensor_dev_attr_temp4_input.dev_attr.attr,	/* 3 */
+	&sensor_dev_attr_fan1_input.dev_attr.attr,	/* 4 */
+	&sensor_dev_attr_pwm1.dev_attr.attr,		/* 5 */
+	&sensor_dev_attr_fan2_input.dev_attr.attr,	/* 6 */
+	&sensor_dev_attr_pwm2.dev_attr.attr,		/* 7 */
 	NULL
 };
 
 static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
 			      int index)
 {
-	if ((index == 0 || index == 1) &&
-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
+	if (index == 0 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
 		return 0;
-	if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
+	if (index == 1 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
 		return 0;
-	if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
+	if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
 		return 0;
-	if (index == 4 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
+	if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
 		return 0;
-	if (index >= 5 && index <= 7 &&
+	if (index >= 4 && index <= 5 &&
 	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
 		return 0;
-	if (index >= 8 && index <= 10 &&
+	if (index >= 6 && index <= 7 &&
 	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
 		return 0;
 
@@ -659,6 +644,37 @@ static int __init i8k_init_hwmon(void)
 	return 0;
 }
 
+struct i8k_config_data {
+	int fan_mult;
+	int fan_max;
+};
+
+enum i8k_configs {
+	DELL_LATITUDE_D520,
+	DELL_PRECISION_490,
+	DELL_STUDIO,
+	DELL_XPS_M140,
+};
+
+static const struct i8k_config_data i8k_config_data[] = {
+	[DELL_LATITUDE_D520] = {
+		.fan_mult = 1,
+		.fan_max = I8K_FAN_TURBO,
+	},
+	[DELL_PRECISION_490] = {
+		.fan_mult = 1,
+		.fan_max = I8K_FAN_TURBO,
+	},
+	[DELL_STUDIO] = {
+		.fan_mult = 1,
+		.fan_max = I8K_FAN_HIGH,
+	},
+	[DELL_XPS_M140] = {
+		.fan_mult = 1,
+		.fan_max = I8K_FAN_HIGH,
+	},
+};
+
 static struct dmi_system_id i8k_dmi_table[] __initdata = {
 	{
 		.ident = "Dell Inspiron",
@@ -682,6 +698,14 @@ static struct dmi_system_id i8k_dmi_tabl
 		},
 	},
 	{
+		.ident = "Dell Latitude D520",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
+		},
+		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
+	},
+	{
 		.ident = "Dell Latitude 2",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -703,6 +727,15 @@ static struct dmi_system_id i8k_dmi_tabl
 		},
 	},
 	{
+		.ident = "Dell Precision 490",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME,
+				  "Precision WorkStation 490"),
+		},
+		.driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
+	},
+	{
 		.ident = "Dell Precision",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -729,7 +762,7 @@ static struct dmi_system_id i8k_dmi_tabl
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
 		},
-		.driver_data = (void *)1,	/* fan multiplier override */
+		.driver_data = (void *)&i8k_config_data[DELL_STUDIO],
 	},
 	{
 		.ident = "Dell XPS M140",
@@ -737,7 +770,7 @@ static struct dmi_system_id i8k_dmi_tabl
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
 		},
-		.driver_data = (void *)1,	/* fan multiplier override */
+		.driver_data = (void *)&i8k_config_data[DELL_XPS_M140],
 	},
 	{ }
 };
@@ -777,9 +810,17 @@ static int __init i8k_probe(void)
 	}
 
 	i8k_fan_mult = fan_mult;
+	i8k_fan_max = fan_max ? : I8K_FAN_HIGH;	/* Must not be 0 */
 	id = dmi_first_match(i8k_dmi_table);
-	if (id && fan_mult == I8K_FAN_MULT && id->driver_data)
-		i8k_fan_mult = (unsigned long)id->driver_data;
+	if (id && id->driver_data) {
+		const struct i8k_config_data *conf = id->driver_data;
+
+		if (fan_mult == I8K_FAN_MULT && conf->fan_mult)
+			i8k_fan_mult = conf->fan_mult;
+		if (fan_max == I8K_FAN_HIGH && conf->fan_max)
+			i8k_fan_max = conf->fan_max;
+	}
+	i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/pcmcia/synclink_cs.c linux-libre-3.17-rc7-gnu/drivers/char/pcmcia/synclink_cs.c
--- linux-libre-3.16-gnu/drivers/char/pcmcia/synclink_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/pcmcia/synclink_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_stru
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 			 __FILE__, __LINE__, info->device_name, port->count);
 
-	WARN_ON(!port->count);
-
 	if (tty_port_close_start(port, tty, filp) == 0)
 		goto cleanup;
 
@@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct
 			 __FILE__, __LINE__, tty->driver->name, port->count);
 
 	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
+	if (port->flags & ASYNC_CLOSING){
 		wait_event_interruptible_tty(tty, port->close_wait,
 					     !(port->flags & ASYNC_CLOSING));
 		retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/random.c linux-libre-3.17-rc7-gnu/drivers/char/random.c
--- linux-libre-3.16-gnu/drivers/char/random.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/random.c	2014-09-28 17:29:07.000000000 -0400
@@ -250,6 +250,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/kthread.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
 #include <linux/fips.h>
@@ -257,6 +258,8 @@
 #include <linux/kmemcheck.h>
 #include <linux/workqueue.h>
 #include <linux/irq.h>
+#include <linux/syscalls.h>
+#include <linux/completion.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -267,6 +270,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/random.h>
 
+/* #define ADD_INTERRUPT_BENCH */
+
 /*
  * Configuration information
  */
@@ -401,6 +406,7 @@ static struct poolinfo {
  */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
 static struct fasync_struct *fasync;
 
 /**********************************************************************
@@ -481,9 +487,9 @@ static __u32 const twist_table[8] = {
  * the entropy is concentrated in the low-order bits.
  */
 static void _mix_pool_bytes(struct entropy_store *r, const void *in,
-			    int nbytes, __u8 out[64])
+			    int nbytes)
 {
-	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+	unsigned long i, tap1, tap2, tap3, tap4, tap5;
 	int input_rotate;
 	int wordmask = r->poolinfo->poolwords - 1;
 	const char *bytes = in;
@@ -495,9 +501,8 @@ static void _mix_pool_bytes(struct entro
 	tap4 = r->poolinfo->tap4;
 	tap5 = r->poolinfo->tap5;
 
-	smp_rmb();
-	input_rotate = ACCESS_ONCE(r->input_rotate);
-	i = ACCESS_ONCE(r->add_ptr);
+	input_rotate = r->input_rotate;
+	i = r->add_ptr;
 
 	/* mix one byte at a time to simplify size handling and churn faster */
 	while (nbytes--) {
@@ -524,39 +529,33 @@ static void _mix_pool_bytes(struct entro
 		input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
 	}
 
-	ACCESS_ONCE(r->input_rotate) = input_rotate;
-	ACCESS_ONCE(r->add_ptr) = i;
-	smp_wmb();
-
-	if (out)
-		for (j = 0; j < 16; j++)
-			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+	r->input_rotate = input_rotate;
+	r->add_ptr = i;
 }
 
 static void __mix_pool_bytes(struct entropy_store *r, const void *in,
-			     int nbytes, __u8 out[64])
+			     int nbytes)
 {
 	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
-	_mix_pool_bytes(r, in, nbytes, out);
+	_mix_pool_bytes(r, in, nbytes);
 }
 
 static void mix_pool_bytes(struct entropy_store *r, const void *in,
-			   int nbytes, __u8 out[64])
+			   int nbytes)
 {
 	unsigned long flags;
 
 	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
 	spin_lock_irqsave(&r->lock, flags);
-	_mix_pool_bytes(r, in, nbytes, out);
+	_mix_pool_bytes(r, in, nbytes);
 	spin_unlock_irqrestore(&r->lock, flags);
 }
 
 struct fast_pool {
 	__u32		pool[4];
 	unsigned long	last;
-	unsigned short	count;
-	unsigned char	rotate;
-	unsigned char	last_timer_intr;
+	unsigned short	reg_idx;
+	unsigned char	count;
 };
 
 /*
@@ -564,25 +563,29 @@ struct fast_pool {
  * collector.  It's hardcoded for an 128 bit pool and assumes that any
  * locks that might be needed are taken by the caller.
  */
-static void fast_mix(struct fast_pool *f, __u32 input[4])
+static void fast_mix(struct fast_pool *f)
 {
-	__u32		w;
-	unsigned	input_rotate = f->rotate;
+	__u32 a = f->pool[0],	b = f->pool[1];
+	__u32 c = f->pool[2],	d = f->pool[3];
 
-	w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
-	f->pool[0] = (w >> 3) ^ twist_table[w & 7];
-	input_rotate = (input_rotate + 14) & 31;
-	w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
-	f->pool[1] = (w >> 3) ^ twist_table[w & 7];
-	input_rotate = (input_rotate + 7) & 31;
-	w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
-	f->pool[2] = (w >> 3) ^ twist_table[w & 7];
-	input_rotate = (input_rotate + 7) & 31;
-	w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
-	f->pool[3] = (w >> 3) ^ twist_table[w & 7];
-	input_rotate = (input_rotate + 7) & 31;
+	a += b;			c += d;
+	b = rol32(a, 6);	d = rol32(c, 27);
+	d ^= a;			b ^= c;
 
-	f->rotate = input_rotate;
+	a += b;			c += d;
+	b = rol32(a, 16);	d = rol32(c, 14);
+	d ^= a;			b ^= c;
+
+	a += b;			c += d;
+	b = rol32(a, 6);	d = rol32(c, 27);
+	d ^= a;			b ^= c;
+
+	a += b;			c += d;
+	b = rol32(a, 16);	d = rol32(c, 14);
+	d ^= a;			b ^= c;
+
+	f->pool[0] = a;  f->pool[1] = b;
+	f->pool[2] = c;  f->pool[3] = d;
 	f->count++;
 }
 
@@ -657,6 +660,7 @@ retry:
 		r->entropy_total = 0;
 		if (r == &nonblocking_pool) {
 			prandom_reseed_late();
+			wake_up_interruptible(&urandom_init_wait);
 			pr_notice("random: %s pool is initialized\n", r->name);
 		}
 	}
@@ -739,13 +743,13 @@ void add_device_randomness(const void *b
 
 	trace_add_device_randomness(size, _RET_IP_);
 	spin_lock_irqsave(&input_pool.lock, flags);
-	_mix_pool_bytes(&input_pool, buf, size, NULL);
-	_mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+	_mix_pool_bytes(&input_pool, buf, size);
+	_mix_pool_bytes(&input_pool, &time, sizeof(time));
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 
 	spin_lock_irqsave(&nonblocking_pool.lock, flags);
-	_mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
-	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
+	_mix_pool_bytes(&nonblocking_pool, buf, size);
+	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time));
 	spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
 }
 EXPORT_SYMBOL(add_device_randomness);
@@ -778,7 +782,7 @@ static void add_timer_randomness(struct
 	sample.cycles = random_get_entropy();
 	sample.num = num;
 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
-	mix_pool_bytes(r, &sample, sizeof(sample), NULL);
+	mix_pool_bytes(r, &sample, sizeof(sample));
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
@@ -835,6 +839,38 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
 
 static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
 
+#ifdef ADD_INTERRUPT_BENCH
+static unsigned long avg_cycles, avg_deviation;
+
+#define AVG_SHIFT 8     /* Exponential average factor k=1/256 */
+#define FIXED_1_2 (1 << (AVG_SHIFT-1))
+
+static void add_interrupt_bench(cycles_t start)
+{
+        long delta = random_get_entropy() - start;
+
+        /* Use a weighted moving average */
+        delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
+        avg_cycles += delta;
+        /* And average deviation */
+        delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
+        avg_deviation += delta;
+}
+#else
+#define add_interrupt_bench(x)
+#endif
+
+static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
+{
+	__u32 *ptr = (__u32 *) regs;
+
+	if (regs == NULL)
+		return 0;
+	if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
+		f->reg_idx = 0;
+	return *(ptr + f->reg_idx++);
+}
+
 void add_interrupt_randomness(int irq, int irq_flags)
 {
 	struct entropy_store	*r;
@@ -842,55 +878,52 @@ void add_interrupt_randomness(int irq, i
 	struct pt_regs		*regs = get_irq_regs();
 	unsigned long		now = jiffies;
 	cycles_t		cycles = random_get_entropy();
-	__u32			input[4], c_high, j_high;
+	__u32			c_high, j_high;
 	__u64			ip;
 	unsigned long		seed;
-	int			credit;
+	int			credit = 0;
 
+	if (cycles == 0)
+		cycles = get_reg(fast_pool, regs);
 	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
 	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
-	input[0] = cycles ^ j_high ^ irq;
-	input[1] = now ^ c_high;
+	fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
+	fast_pool->pool[1] ^= now ^ c_high;
 	ip = regs ? instruction_pointer(regs) : _RET_IP_;
-	input[2] = ip;
-	input[3] = ip >> 32;
+	fast_pool->pool[2] ^= ip;
+	fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
+		get_reg(fast_pool, regs);
 
-	fast_mix(fast_pool, input);
+	fast_mix(fast_pool);
+	add_interrupt_bench(cycles);
 
-	if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+	if ((fast_pool->count < 64) &&
+	    !time_after(now, fast_pool->last + HZ))
 		return;
 
-	fast_pool->last = now;
-
 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
-	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+	if (!spin_trylock(&r->lock))
+		return;
 
-	/*
-	 * If we don't have a valid cycle counter, and we see
-	 * back-to-back timer interrupts, then skip giving credit for
-	 * any entropy, otherwise credit 1 bit.
-	 */
-	credit = 1;
-	if (cycles == 0) {
-		if (irq_flags & __IRQF_TIMER) {
-			if (fast_pool->last_timer_intr)
-				credit = 0;
-			fast_pool->last_timer_intr = 1;
-		} else
-			fast_pool->last_timer_intr = 0;
-	}
+	fast_pool->last = now;
+	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
 
 	/*
 	 * If we have architectural seed generator, produce a seed and
-	 * add it to the pool.  For the sake of paranoia count it as
-	 * 50% entropic.
+	 * add it to the pool.  For the sake of paranoia don't let the
+	 * architectural seed generator dominate the input from the
+	 * interrupt noise.
 	 */
 	if (arch_get_random_seed_long(&seed)) {
-		__mix_pool_bytes(r, &seed, sizeof(seed), NULL);
-		credit += sizeof(seed) * 4;
+		__mix_pool_bytes(r, &seed, sizeof(seed));
+		credit = 1;
 	}
+	spin_unlock(&r->lock);
 
-	credit_entropy_bits(r, credit);
+	fast_pool->count = 0;
+
+	/* award one bit for the contents of the fast pool */
+	credit_entropy_bits(r, credit + 1);
 }
 
 #ifdef CONFIG_BLOCK
@@ -922,6 +955,11 @@ static ssize_t extract_entropy(struct en
 static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
 static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
+	if (!r->pull ||
+	    r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
+	    r->entropy_count > r->poolinfo->poolfracbits)
+		return;
+
 	if (r->limit == 0 && random_min_urandom_seed) {
 		unsigned long now = jiffies;
 
@@ -930,10 +968,8 @@ static void xfer_secondary_pool(struct e
 			return;
 		r->last_pulled = now;
 	}
-	if (r->pull &&
-	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
-	    r->entropy_count < r->poolinfo->poolfracbits)
-		_xfer_secondary_pool(r, nbytes);
+
+	_xfer_secondary_pool(r, nbytes);
 }
 
 static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
@@ -953,7 +989,7 @@ static void _xfer_secondary_pool(struct
 				  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
 	bytes = extract_entropy(r->pull, tmp, bytes,
 				random_read_wakeup_bits / 8, rsvd_bytes);
-	mix_pool_bytes(r, tmp, bytes, NULL);
+	mix_pool_bytes(r, tmp, bytes);
 	credit_entropy_bits(r, bytes*8);
 }
 
@@ -1039,7 +1075,6 @@ static void extract_buf(struct entropy_s
 		unsigned long l[LONGS(20)];
 	} hash;
 	__u32 workspace[SHA_WORKSPACE_WORDS];
-	__u8 extract[64];
 	unsigned long flags;
 
 	/*
@@ -1068,15 +1103,9 @@ static void extract_buf(struct entropy_s
 	 * brute-forcing the feedback as hard as brute-forcing the
 	 * hash.
 	 */
-	__mix_pool_bytes(r, hash.w, sizeof(hash.w), extract);
+	__mix_pool_bytes(r, hash.w, sizeof(hash.w));
 	spin_unlock_irqrestore(&r->lock, flags);
 
-	/*
-	 * To avoid duplicates, we atomically extract a portion of the
-	 * pool while mixing, and hash one final time.
-	 */
-	sha_transform(hash.w, extract, workspace);
-	memset(extract, 0, sizeof(extract));
 	memset(workspace, 0, sizeof(workspace));
 
 	/*
@@ -1160,13 +1189,14 @@ static ssize_t extract_entropy_user(stru
 {
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
+	int large_request = (nbytes > 256);
 
 	trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, 0, 0);
 
 	while (nbytes) {
-		if (need_resched()) {
+		if (large_request && need_resched()) {
 			if (signal_pending(current)) {
 				if (ret == 0)
 					ret = -ERESTARTSYS;
@@ -1263,14 +1293,14 @@ static void init_std_data(struct entropy
 	unsigned long rv;
 
 	r->last_pulled = jiffies;
-	mix_pool_bytes(r, &now, sizeof(now), NULL);
+	mix_pool_bytes(r, &now, sizeof(now));
 	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
 		if (!arch_get_random_seed_long(&rv) &&
 		    !arch_get_random_long(&rv))
 			rv = random_get_entropy();
-		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+		mix_pool_bytes(r, &rv, sizeof(rv));
 	}
-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
+	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
 }
 
 /*
@@ -1309,39 +1339,8 @@ void rand_initialize_disk(struct gendisk
 }
 #endif
 
-/*
- * Attempt an emergency refill using arch_get_random_seed_long().
- *
- * As with add_interrupt_randomness() be paranoid and only
- * credit the output as 50% entropic.
- */
-static int arch_random_refill(void)
-{
-	const unsigned int nlongs = 64;	/* Arbitrary number */
-	unsigned int n = 0;
-	unsigned int i;
-	unsigned long buf[nlongs];
-
-	if (!arch_has_random_seed())
-		return 0;
-
-	for (i = 0; i < nlongs; i++) {
-		if (arch_get_random_seed_long(&buf[n]))
-			n++;
-	}
-
-	if (n) {
-		unsigned int rand_bytes = n * sizeof(unsigned long);
-
-		mix_pool_bytes(&input_pool, buf, rand_bytes, NULL);
-		credit_entropy_bits(&input_pool, rand_bytes*4);
-	}
-
-	return n;
-}
-
 static ssize_t
-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+_random_read(int nonblock, char __user *buf, size_t nbytes)
 {
 	ssize_t n;
 
@@ -1360,12 +1359,7 @@ random_read(struct file *file, char __us
 			return n;
 
 		/* Pool is (near) empty.  Maybe wait and retry. */
-
-		/* First try an emergency refill */
-		if (arch_random_refill())
-			continue;
-
-		if (file->f_flags & O_NONBLOCK)
+		if (nonblock)
 			return -EAGAIN;
 
 		wait_event_interruptible(random_read_wait,
@@ -1377,6 +1371,12 @@ random_read(struct file *file, char __us
 }
 
 static ssize_t
+random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+{
+	return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static ssize_t
 urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
 	int ret;
@@ -1424,7 +1424,7 @@ write_pool(struct entropy_store *r, cons
 		count -= bytes;
 		p += bytes;
 
-		mix_pool_bytes(r, buf, bytes, NULL);
+		mix_pool_bytes(r, buf, bytes);
 		cond_resched();
 	}
 
@@ -1520,6 +1520,29 @@ const struct file_operations urandom_fop
 	.llseek = noop_llseek,
 };
 
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_RANDOM)
+		return _random_read(flags & GRND_NONBLOCK, buf, count);
+
+	if (unlikely(nonblocking_pool.initialized == 0)) {
+		if (flags & GRND_NONBLOCK)
+			return -EAGAIN;
+		wait_event_interruptible(urandom_init_wait,
+					 nonblocking_pool.initialized);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+	return urandom_read(NULL, buf, count, NULL);
+}
+
 /***************************************************************
  * Random UUID interface
  *
@@ -1663,6 +1686,22 @@ struct ctl_table random_table[] = {
 		.mode		= 0444,
 		.proc_handler	= proc_do_uuid,
 	},
+#ifdef ADD_INTERRUPT_BENCH
+	{
+		.procname	= "add_interrupt_avg_cycles",
+		.data		= &avg_cycles,
+		.maxlen		= sizeof(avg_cycles),
+		.mode		= 0444,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
+	{
+		.procname	= "add_interrupt_avg_deviation",
+		.data		= &avg_deviation,
+		.maxlen		= sizeof(avg_deviation),
+		.mode		= 0444,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
+#endif
 	{ }
 };
 #endif 	/* CONFIG_SYSCTL */
@@ -1719,3 +1758,23 @@ randomize_range(unsigned long start, uns
 		return 0;
 	return PAGE_ALIGN(get_random_int() % range + start);
 }
+
+/* Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy)
+{
+	struct entropy_store *poolp = &input_pool;
+
+	/* Suspend writing if we're above the trickle threshold.
+	 * We'll be woken up again once below random_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
+			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+	mix_pool_bytes(poolp, buffer, count);
+	credit_entropy_bits(poolp, entropy);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/tpm/tpm_eventlog.c linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_eventlog.c
--- linux-libre-3.16-gnu/drivers/char/tpm/tpm_eventlog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_eventlog.c	2014-09-28 17:29:07.000000000 -0400
@@ -235,7 +235,6 @@ static int tpm_bios_measurements_release
 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
 {
 	int len = 0;
-	int i;
 	char *eventname;
 	struct tcpa_event *event = v;
 	unsigned char *event_entry =
@@ -251,8 +250,7 @@ static int tpm_ascii_bios_measurements_s
 	seq_printf(m, "%2d ", event->pcr_index);
 
 	/* 2nd: SHA1 */
-	for (i = 0; i < 20; i++)
-		seq_printf(m, "%02x", event->pcr_value[i]);
+	seq_printf(m, "%20phN", event->pcr_value);
 
 	/* 3rd: event type identifier */
 	seq_printf(m, " %02x", event->event_type);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/tpm/tpm_i2c_stm_st33.c linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_i2c_stm_st33.c
--- linux-libre-3.16-gnu/drivers/char/tpm/tpm_i2c_stm_st33.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_i2c_stm_st33.c	2014-09-28 17:29:07.000000000 -0400
@@ -714,6 +714,7 @@ tpm_st33_i2c_probe(struct i2c_client *cl
 	}
 
 	tpm_get_timeouts(chip);
+	tpm_do_selftest(chip);
 
 	dev_info(chip->dev, "TPM I2C Initialized\n");
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/tpm/tpm-interface.c linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm-interface.c
--- linux-libre-3.16-gnu/drivers/char/tpm/tpm-interface.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm-interface.c	2014-09-28 17:29:07.000000000 -0400
@@ -491,11 +491,10 @@ static int tpm_startup(struct tpm_chip *
 int tpm_get_timeouts(struct tpm_chip *chip)
 {
 	struct tpm_cmd_t tpm_cmd;
-	struct timeout_t *timeout_cap;
+	unsigned long new_timeout[4];
+	unsigned long old_timeout[4];
 	struct duration_t *duration_cap;
 	ssize_t rc;
-	u32 timeout;
-	unsigned int scale = 1;
 
 	tpm_cmd.header.in = tpm_getcap_header;
 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -529,25 +528,46 @@ int tpm_get_timeouts(struct tpm_chip *ch
 	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
 		return -EINVAL;
 
-	timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
-	/* Don't overwrite default if value is 0 */
-	timeout = be32_to_cpu(timeout_cap->a);
-	if (timeout && timeout < 1000) {
-		/* timeouts in msec rather usec */
-		scale = 1000;
-		chip->vendor.timeout_adjusted = true;
+	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);
+	memcpy(new_timeout, old_timeout, sizeof(new_timeout));
+
+	/*
+	 * Provide ability for vendor overrides of timeout values in case
+	 * of misreporting.
+	 */
+	if (chip->ops->update_timeouts != NULL)
+		chip->vendor.timeout_adjusted =
+			chip->ops->update_timeouts(chip, new_timeout);
+
+	if (!chip->vendor.timeout_adjusted) {
+		/* Don't overwrite default if value is 0 */
+		if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
+			int i;
+
+			/* timeouts in msec rather usec */
+			for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
+				new_timeout[i] *= 1000;
+			chip->vendor.timeout_adjusted = true;
+		}
+	}
+
+	/* Report adjusted timeouts */
+	if (chip->vendor.timeout_adjusted) {
+		dev_info(chip->dev,
+			 HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
+			 old_timeout[0], new_timeout[0],
+			 old_timeout[1], new_timeout[1],
+			 old_timeout[2], new_timeout[2],
+			 old_timeout[3], new_timeout[3]);
 	}
-	if (timeout)
-		chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
-	timeout = be32_to_cpu(timeout_cap->b);
-	if (timeout)
-		chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
-	timeout = be32_to_cpu(timeout_cap->c);
-	if (timeout)
-		chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
-	timeout = be32_to_cpu(timeout_cap->d);
-	if (timeout)
-		chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
+
+	chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]);
+	chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]);
+	chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]);
+	chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]);
 
 duration:
 	tpm_cmd.header.in = tpm_getcap_header;
@@ -991,13 +1011,13 @@ int tpm_get_random(u32 chip_num, u8 *out
 	int err, total = 0, retries = 5;
 	u8 *dest = out;
 
+	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+		return -EINVAL;
+
 	chip = tpm_chip_find_get(chip_num);
 	if (chip == NULL)
 		return -ENODEV;
 
-	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
-		return -EINVAL;
-
 	do {
 		tpm_cmd.header.in = tpm_getrandom_header;
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
@@ -1016,6 +1036,7 @@ int tpm_get_random(u32 chip_num, u8 *out
 		num_bytes -= recd;
 	} while (retries-- && total < max);
 
+	tpm_chip_put(chip);
 	return total ? total : -EIO;
 }
 EXPORT_SYMBOL_GPL(tpm_get_random);
@@ -1095,7 +1116,7 @@ struct tpm_chip *tpm_register_hardware(s
 		goto del_misc;
 
 	if (tpm_add_ppi(&dev->kobj))
-		goto del_misc;
+		goto del_sysfs;
 
 	chip->bios_dir = tpm_bios_log_setup(chip->devname);
 
@@ -1106,6 +1127,8 @@ struct tpm_chip *tpm_register_hardware(s
 
 	return chip;
 
+del_sysfs:
+	tpm_sysfs_del_device(chip);
 del_misc:
 	tpm_dev_del_device(chip);
 put_device:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/tpm/tpm_tis.c linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_tis.c
--- linux-libre-3.16-gnu/drivers/char/tpm/tpm_tis.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/tpm/tpm_tis.c	2014-09-28 17:29:07.000000000 -0400
@@ -373,6 +373,36 @@ out_err:
 	return rc;
 }
 
+struct tis_vendor_timeout_override {
+	u32 did_vid;
+	unsigned long timeout_us[4];
+};
+
+static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
+	/* Atmel 3204 */
+	{ 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000),
+			(TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } },
+};
+
+static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
+				    unsigned long *timeout_cap)
+{
+	int i;
+	u32 did_vid;
+
+	did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+
+	for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
+		if (vendor_timeout_overrides[i].did_vid != did_vid)
+			continue;
+		memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
+		       sizeof(vendor_timeout_overrides[i].timeout_us));
+		return true;
+	}
+
+	return false;
+}
+
 /*
  * Early probing for iTPM with STS_DATA_EXPECT flaw.
  * Try sending command without itpm flag set and if that
@@ -437,6 +467,7 @@ static const struct tpm_class_ops tpm_ti
 	.recv = tpm_tis_recv,
 	.send = tpm_tis_send,
 	.cancel = tpm_tis_ready,
+	.update_timeouts = tpm_tis_update_timeouts,
 	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 	.req_canceled = tpm_tis_req_canceled,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/virtio_console.c linux-libre-3.17-rc7-gnu/drivers/char/virtio_console.c
--- linux-libre-3.16-gnu/drivers/char/virtio_console.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/virtio_console.c	2014-09-28 17:29:07.000000000 -0400
@@ -2262,8 +2262,7 @@ static int __init init(void)
 unregister:
 	unregister_virtio_driver(&virtio_console);
 free:
-	if (pdrvdata.debugfs_dir)
-		debugfs_remove_recursive(pdrvdata.debugfs_dir);
+	debugfs_remove_recursive(pdrvdata.debugfs_dir);
 	class_destroy(pdrvdata.class);
 	return err;
 }
@@ -2276,8 +2275,7 @@ static void __exit fini(void)
 	unregister_virtio_driver(&virtio_rproc_serial);
 
 	class_destroy(pdrvdata.class);
-	if (pdrvdata.debugfs_dir)
-		debugfs_remove_recursive(pdrvdata.debugfs_dir);
+	debugfs_remove_recursive(pdrvdata.debugfs_dir);
 }
 module_init(init);
 module_exit(fini);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c linux-libre-3.17-rc7-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c
--- linux-libre-3.16-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2014-09-28 17:29:07.000000000 -0400
@@ -661,6 +661,7 @@ static int hwicap_setup(struct device *d
 	drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
 	if (!drvdata->base_address) {
 		dev_err(dev, "ioremap() failed\n");
+		retval = -ENOMEM;
 		goto failed2;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/at91/clk-main.c linux-libre-3.17-rc7-gnu/drivers/clk/at91/clk-main.c
--- linux-libre-3.16-gnu/drivers/clk/at91/clk-main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/at91/clk-main.c	2014-09-28 17:29:07.000000000 -0400
@@ -388,6 +388,7 @@ static unsigned long clk_main_recalc_rat
 	if (parent_rate)
 		return parent_rate;
 
+	pr_warn("Main crystal frequency not set, using approximate value\n");
 	tmp = pmc_read(pmc, AT91_CKGR_MCFR);
 	if (!(tmp & AT91_PMC_MAINRDY))
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/at91/clk-slow.c linux-libre-3.17-rc7-gnu/drivers/clk/at91/clk-slow.c
--- linux-libre-3.16-gnu/drivers/clk/at91/clk-slow.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/at91/clk-slow.c	2014-09-28 17:29:07.000000000 -0400
@@ -447,7 +447,7 @@ void __init of_at91sam9260_clk_slow_setu
 	int i;
 
 	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
-	if (num_parents <= 0 || num_parents > 1)
+	if (num_parents != 2)
 		return;
 
 	for (i = 0; i < num_parents; ++i) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk.c linux-libre-3.17-rc7-gnu/drivers/clk/clk.c
--- linux-libre-3.16-gnu/drivers/clk/clk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@
  */
 
 #include <linux/clk-private.h>
+#include <linux/clk/clk-conf.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -98,9 +99,19 @@ static void clk_enable_unlock(unsigned l
 #include <linux/debugfs.h>
 
 static struct dentry *rootdir;
-static struct dentry *orphandir;
 static int inited = 0;
 
+static struct hlist_head *all_lists[] = {
+	&clk_root_list,
+	&clk_orphan_list,
+	NULL,
+};
+
+static struct hlist_head *orphan_list[] = {
+	&clk_orphan_list,
+	NULL,
+};
+
 static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 {
 	if (!c)
@@ -130,17 +141,16 @@ static void clk_summary_show_subtree(str
 static int clk_summary_show(struct seq_file *s, void *data)
 {
 	struct clk *c;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
 
 	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy\n");
 	seq_puts(s, "--------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
-	hlist_for_each_entry(c, &clk_root_list, child_node)
-		clk_summary_show_subtree(s, c, 0);
-
-	hlist_for_each_entry(c, &clk_orphan_list, child_node)
-		clk_summary_show_subtree(s, c, 0);
+	for (; *lists; lists++)
+		hlist_for_each_entry(c, *lists, child_node)
+			clk_summary_show_subtree(s, c, 0);
 
 	clk_prepare_unlock();
 
@@ -193,21 +203,19 @@ static int clk_dump(struct seq_file *s,
 {
 	struct clk *c;
 	bool first_node = true;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
 
 	seq_printf(s, "{");
 
 	clk_prepare_lock();
 
-	hlist_for_each_entry(c, &clk_root_list, child_node) {
-		if (!first_node)
-			seq_printf(s, ",");
-		first_node = false;
-		clk_dump_subtree(s, c, 0);
-	}
-
-	hlist_for_each_entry(c, &clk_orphan_list, child_node) {
-		seq_printf(s, ",");
-		clk_dump_subtree(s, c, 0);
+	for (; *lists; lists++) {
+		hlist_for_each_entry(c, *lists, child_node) {
+			if (!first_node)
+				seq_puts(s, ",");
+			first_node = false;
+			clk_dump_subtree(s, c, 0);
+		}
 	}
 
 	clk_prepare_unlock();
@@ -276,9 +284,11 @@ static int clk_debug_create_one(struct c
 	if (!d)
 		goto err_out;
 
-	if (clk->ops->debug_init)
-		if (clk->ops->debug_init(clk->hw, clk->dentry))
+	if (clk->ops->debug_init) {
+		ret = clk->ops->debug_init(clk->hw, clk->dentry);
+		if (ret)
 			goto err_out;
+	}
 
 	ret = 0;
 	goto out;
@@ -305,7 +315,7 @@ static int clk_debug_create_subtree(stru
 		goto out;
 
 	hlist_for_each_entry(child, &clk->children, child_node)
-		clk_debug_create_subtree(child, clk->dentry);
+		clk_debug_create_subtree(child, pdentry);
 
 	ret = 0;
 out:
@@ -325,31 +335,12 @@ out:
  */
 static int clk_debug_register(struct clk *clk)
 {
-	struct clk *parent;
-	struct dentry *pdentry;
 	int ret = 0;
 
 	if (!inited)
 		goto out;
 
-	parent = clk->parent;
-
-	/*
-	 * Check to see if a clk is a root clk.  Also check that it is
-	 * safe to add this clk to debugfs
-	 */
-	if (!parent)
-		if (clk->flags & CLK_IS_ROOT)
-			pdentry = rootdir;
-		else
-			pdentry = orphandir;
-	else
-		if (parent->dentry)
-			pdentry = parent->dentry;
-		else
-			goto out;
-
-	ret = clk_debug_create_subtree(clk, pdentry);
+	ret = clk_debug_create_subtree(clk, rootdir);
 
 out:
 	return ret;
@@ -370,38 +361,17 @@ static void clk_debug_unregister(struct
 	debugfs_remove_recursive(clk->dentry);
 }
 
-/**
- * clk_debug_reparent - reparent clk node in the debugfs clk tree
- * @clk: the clk being reparented
- * @new_parent: the new clk parent, may be NULL
- *
- * Rename clk entry in the debugfs clk tree if debugfs has been
- * initialized.  Otherwise it bails out early since the debugfs clk tree
- * will be created lazily by clk_debug_init as part of a late_initcall.
- *
- * Caller must hold prepare_lock.
- */
-static void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+				void *data, const struct file_operations *fops)
 {
-	struct dentry *d;
-	struct dentry *new_parent_d;
-
-	if (!inited)
-		return;
+	struct dentry *d = NULL;
 
-	if (new_parent)
-		new_parent_d = new_parent->dentry;
-	else
-		new_parent_d = orphandir;
+	if (clk->dentry)
+		d = debugfs_create_file(name, mode, clk->dentry, data, fops);
 
-	d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
-			new_parent_d, clk->name);
-	if (d)
-		clk->dentry = d;
-	else
-		pr_debug("%s: failed to rename debugfs entry for %s\n",
-				__func__, clk->name);
+	return d;
 }
+EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
 
 /**
  * clk_debug_init - lazily create the debugfs clk tree visualization
@@ -425,19 +395,24 @@ static int __init clk_debug_init(void)
 	if (!rootdir)
 		return -ENOMEM;
 
-	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL,
+	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
 				&clk_summary_fops);
 	if (!d)
 		return -ENOMEM;
 
-	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL,
+	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
 				&clk_dump_fops);
 	if (!d)
 		return -ENOMEM;
 
-	orphandir = debugfs_create_dir("orphans", rootdir);
+	d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
+				&orphan_list, &clk_summary_fops);
+	if (!d)
+		return -ENOMEM;
 
-	if (!orphandir)
+	d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
+				&orphan_list, &clk_dump_fops);
+	if (!d)
 		return -ENOMEM;
 
 	clk_prepare_lock();
@@ -446,7 +421,7 @@ static int __init clk_debug_init(void)
 		clk_debug_create_subtree(clk, rootdir);
 
 	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
-		clk_debug_create_subtree(clk, orphandir);
+		clk_debug_create_subtree(clk, rootdir);
 
 	inited = 1;
 
@@ -1284,9 +1259,6 @@ static void __clk_set_parent_after(struc
 		clk_disable(old_parent);
 		__clk_unprepare(old_parent);
 	}
-
-	/* update debugfs with new clk tree topology */
-	clk_debug_reparent(clk, parent);
 }
 
 static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
@@ -1495,6 +1467,7 @@ static struct clk *clk_propagate_rate_ch
 static void clk_change_rate(struct clk *clk)
 {
 	struct clk *child;
+	struct hlist_node *tmp;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
 	bool skip_set_rate = false;
@@ -1530,7 +1503,11 @@ static void clk_change_rate(struct clk *
 	if (clk->notifier_count && old_rate != clk->rate)
 		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	/*
+	 * Use safe iteration, as change_rate can actually swap parents
+	 * for certain clock types.
+	 */
+	hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
 		/* Skip children who will be reparented to another clock */
 		if (child->new_parent && child->new_parent != clk)
 			continue;
@@ -1683,7 +1660,6 @@ out:
 void __clk_reparent(struct clk *clk, struct clk *new_parent)
 {
 	clk_reparent(clk, new_parent);
-	clk_debug_reparent(clk, new_parent);
 	__clk_recalc_accuracies(clk);
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
@@ -2414,6 +2390,7 @@ int of_clk_add_provider(struct device_no
 			void *data)
 {
 	struct of_clk_provider *cp;
+	int ret;
 
 	cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
 	if (!cp)
@@ -2428,7 +2405,11 @@ int of_clk_add_provider(struct device_no
 	mutex_unlock(&of_clk_mutex);
 	pr_debug("Added clock from %s\n", np->full_name);
 
-	return 0;
+	ret = of_clk_set_defaults(np, true);
+	if (ret < 0)
+		of_clk_del_provider(np);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(of_clk_add_provider);
 
@@ -2605,7 +2586,10 @@ void __init of_clk_init(const struct of_
 		list_for_each_entry_safe(clk_provider, next,
 					&clk_provider_list, node) {
 			if (force || parent_ready(clk_provider->np)) {
+
 				clk_provider->clk_init_cb(clk_provider->np);
+				of_clk_set_defaults(clk_provider->np, true);
+
 				list_del(&clk_provider->node);
 				kfree(clk_provider);
 				is_init_done = true;
@@ -2620,7 +2604,6 @@ void __init of_clk_init(const struct of_
 		 */
 		if (!is_init_done)
 			force = true;
-
 	}
 }
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-clps711x.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-clps711x.c
--- linux-libre-3.16-gnu/drivers/clk/clk-clps711x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-clps711x.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,192 @@
+/*
+ *  Cirrus Logic CLPS711X CLK driver
+ *
+ *  Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon/clps711x.h>
+
+#include <dt-bindings/clock/clps711x-clock.h>
+
+#define CLPS711X_SYSCON1	(0x0100)
+#define CLPS711X_SYSCON2	(0x1100)
+#define CLPS711X_SYSFLG2	(CLPS711X_SYSCON2 + SYSFLG_OFFSET)
+#define CLPS711X_PLLR		(0xa5a8)
+
+#define CLPS711X_EXT_FREQ	(13000000)
+#define CLPS711X_OSC_FREQ	(3686400)
+
+static const struct clk_div_table spi_div_table[] = {
+	{ .val = 0, .div = 32, },
+	{ .val = 1, .div = 8, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 1, },
+};
+
+static const struct clk_div_table timer_div_table[] = {
+	{ .val = 0, .div = 256, },
+	{ .val = 1, .div = 1, },
+};
+
+struct clps711x_clk {
+	struct clk_onecell_data	clk_data;
+	spinlock_t		lock;
+	struct clk		*clks[CLPS711X_CLK_MAX];
+};
+
+static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
+						       u32 fref)
+{
+	u32 tmp, f_cpu, f_pll, f_bus, f_tim, f_pwm, f_spi;
+	struct clps711x_clk *clps711x_clk;
+	unsigned i;
+
+	if (!base)
+		return ERR_PTR(-ENOMEM);
+
+	clps711x_clk = kzalloc(sizeof(*clps711x_clk), GFP_KERNEL);
+	if (!clps711x_clk)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock_init(&clps711x_clk->lock);
+
+	/* Read PLL multiplier value and sanity check */
+	tmp = readl(base + CLPS711X_PLLR) >> 24;
+	if (((tmp >= 10) && (tmp <= 50)) || !fref)
+		f_pll = DIV_ROUND_UP(CLPS711X_OSC_FREQ * tmp, 2);
+	else
+		f_pll = fref;
+
+	tmp = readl(base + CLPS711X_SYSFLG2);
+	if (tmp & SYSFLG2_CKMODE) {
+		f_cpu = CLPS711X_EXT_FREQ;
+		f_bus = CLPS711X_EXT_FREQ;
+		f_spi = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 96);
+		f_pll = 0;
+		f_pwm = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 128);
+	} else {
+		f_cpu = f_pll;
+		if (f_cpu > 36864000)
+			f_bus = DIV_ROUND_UP(f_cpu, 2);
+		else
+			f_bus = 36864000 / 2;
+		f_spi = DIV_ROUND_CLOSEST(f_cpu, 576);
+		f_pwm = DIV_ROUND_CLOSEST(f_cpu, 768);
+	}
+
+	if (tmp & SYSFLG2_CKMODE) {
+		if (readl(base + CLPS711X_SYSCON2) & SYSCON2_OSTB)
+			f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 26);
+		else
+			f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 24);
+	} else
+		f_tim = DIV_ROUND_CLOSEST(f_cpu, 144);
+
+	tmp = readl(base + CLPS711X_SYSCON1);
+	/* Timer1 in free running mode.
+	 * Counter will wrap around to 0xffff when it underflows
+	 * and will continue to count down.
+	 */
+	tmp &= ~(SYSCON1_TC1M | SYSCON1_TC1S);
+	/* Timer2 in prescale mode.
+	 * Value writen is automatically re-loaded when
+	 * the counter underflows.
+	 */
+	tmp |= SYSCON1_TC2M | SYSCON1_TC2S;
+	writel(tmp, base + CLPS711X_SYSCON1);
+
+	clps711x_clk->clks[CLPS711X_CLK_DUMMY] =
+		clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0);
+	clps711x_clk->clks[CLPS711X_CLK_CPU] =
+		clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu);
+	clps711x_clk->clks[CLPS711X_CLK_BUS] =
+		clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus);
+	clps711x_clk->clks[CLPS711X_CLK_PLL] =
+		clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll);
+	clps711x_clk->clks[CLPS711X_CLK_TIMERREF] =
+		clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT,
+					f_tim);
+	clps711x_clk->clks[CLPS711X_CLK_TIMER1] =
+		clk_register_divider_table(NULL, "timer1", "timer_ref", 0,
+					   base + CLPS711X_SYSCON1, 5, 1, 0,
+					   timer_div_table, &clps711x_clk->lock);
+	clps711x_clk->clks[CLPS711X_CLK_TIMER2] =
+		clk_register_divider_table(NULL, "timer2", "timer_ref", 0,
+					   base + CLPS711X_SYSCON1, 7, 1, 0,
+					   timer_div_table, &clps711x_clk->lock);
+	clps711x_clk->clks[CLPS711X_CLK_PWM] =
+		clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm);
+	clps711x_clk->clks[CLPS711X_CLK_SPIREF] =
+		clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT,
+					f_spi);
+	clps711x_clk->clks[CLPS711X_CLK_SPI] =
+		clk_register_divider_table(NULL, "spi", "spi_ref", 0,
+					   base + CLPS711X_SYSCON1, 16, 2, 0,
+					   spi_div_table, &clps711x_clk->lock);
+	clps711x_clk->clks[CLPS711X_CLK_UART] =
+		clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10);
+	clps711x_clk->clks[CLPS711X_CLK_TICK] =
+		clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64);
+
+	for (i = 0; i < CLPS711X_CLK_MAX; i++)
+		if (IS_ERR(clps711x_clk->clks[i]))
+			pr_err("clk %i: register failed with %ld\n",
+			       i, PTR_ERR(clps711x_clk->clks[i]));
+
+	return clps711x_clk;
+}
+
+void __init clps711x_clk_init(void __iomem *base)
+{
+	struct clps711x_clk *clps711x_clk;
+
+	clps711x_clk = _clps711x_clk_init(base, 73728000);
+
+	BUG_ON(IS_ERR(clps711x_clk));
+
+	/* Clocksource */
+	clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER1],
+			    NULL, "clps711x-timer.0");
+	clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER2],
+			    NULL, "clps711x-timer.1");
+
+	/* Drivers */
+	clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_PWM],
+			    NULL, "clps711x-pwm");
+	clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
+			    NULL, "clps711x-uart.0");
+	clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
+			    NULL, "clps711x-uart.1");
+}
+
+#ifdef CONFIG_OF
+static void __init clps711x_clk_init_dt(struct device_node *np)
+{
+	void __iomem *base = of_iomap(np, 0);
+	struct clps711x_clk *clps711x_clk;
+	u32 fref = 0;
+
+	WARN_ON(of_property_read_u32(np, "startup-frequency", &fref));
+
+	clps711x_clk = _clps711x_clk_init(base, fref);
+	BUG_ON(IS_ERR(clps711x_clk));
+
+	clps711x_clk->clk_data.clks = clps711x_clk->clks;
+	clps711x_clk->clk_data.clk_num = CLPS711X_CLK_MAX;
+	of_clk_add_provider(np, of_clk_src_onecell_get,
+			    &clps711x_clk->clk_data);
+}
+CLK_OF_DECLARE(clps711x, "cirrus,clps711x-clk", clps711x_clk_init_dt);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-composite.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-composite.c
--- linux-libre-3.16-gnu/drivers/clk/clk-composite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-composite.c	2014-09-28 17:29:07.000000000 -0400
@@ -64,11 +64,56 @@ static long clk_composite_determine_rate
 	const struct clk_ops *mux_ops = composite->mux_ops;
 	struct clk_hw *rate_hw = composite->rate_hw;
 	struct clk_hw *mux_hw = composite->mux_hw;
+	struct clk *parent;
+	unsigned long parent_rate;
+	long tmp_rate, best_rate = 0;
+	unsigned long rate_diff;
+	unsigned long best_rate_diff = ULONG_MAX;
+	int i;
 
 	if (rate_hw && rate_ops && rate_ops->determine_rate) {
 		rate_hw->clk = hw->clk;
 		return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
 						best_parent_p);
+	} else if (rate_hw && rate_ops && rate_ops->round_rate &&
+		   mux_hw && mux_ops && mux_ops->set_parent) {
+		*best_parent_p = NULL;
+
+		if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
+			*best_parent_p = clk_get_parent(mux_hw->clk);
+			*best_parent_rate = __clk_get_rate(*best_parent_p);
+
+			return rate_ops->round_rate(rate_hw, rate,
+						    best_parent_rate);
+		}
+
+		for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
+			parent = clk_get_parent_by_index(mux_hw->clk, i);
+			if (!parent)
+				continue;
+
+			parent_rate = __clk_get_rate(parent);
+
+			tmp_rate = rate_ops->round_rate(rate_hw, rate,
+							&parent_rate);
+			if (tmp_rate < 0)
+				continue;
+
+			rate_diff = abs(rate - tmp_rate);
+
+			if (!rate_diff || !*best_parent_p
+				       || best_rate_diff > rate_diff) {
+				*best_parent_p = parent;
+				*best_parent_rate = parent_rate;
+				best_rate_diff = rate_diff;
+				best_rate = tmp_rate;
+			}
+
+			if (!rate_diff)
+				return rate;
+		}
+
+		return best_rate;
 	} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
 		mux_hw->clk = hw->clk;
 		return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
@@ -162,7 +207,7 @@ struct clk *clk_register_composite(struc
 	clk_composite_ops = &composite->ops;
 
 	if (mux_hw && mux_ops) {
-		if (!mux_ops->get_parent || !mux_ops->set_parent) {
+		if (!mux_ops->get_parent) {
 			clk = ERR_PTR(-EINVAL);
 			goto err;
 		}
@@ -170,7 +215,8 @@ struct clk *clk_register_composite(struc
 		composite->mux_hw = mux_hw;
 		composite->mux_ops = mux_ops;
 		clk_composite_ops->get_parent = clk_composite_get_parent;
-		clk_composite_ops->set_parent = clk_composite_set_parent;
+		if (mux_ops->set_parent)
+			clk_composite_ops->set_parent = clk_composite_set_parent;
 		if (mux_ops->determine_rate)
 			clk_composite_ops->determine_rate = clk_composite_determine_rate;
 	}
@@ -180,24 +226,27 @@ struct clk *clk_register_composite(struc
 			clk = ERR_PTR(-EINVAL);
 			goto err;
 		}
+		clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
 
-		/* .round_rate is a prerequisite for .set_rate */
-		if (rate_ops->round_rate) {
-			clk_composite_ops->round_rate = clk_composite_round_rate;
-			if (rate_ops->set_rate) {
-				clk_composite_ops->set_rate = clk_composite_set_rate;
-			}
-		} else {
-			WARN(rate_ops->set_rate,
-				"%s: missing round_rate op is required\n",
-				__func__);
+		if (rate_ops->determine_rate)
+			clk_composite_ops->determine_rate =
+				clk_composite_determine_rate;
+		else if (rate_ops->round_rate)
+			clk_composite_ops->round_rate =
+				clk_composite_round_rate;
+
+		/* .set_rate requires either .round_rate or .determine_rate */
+		if (rate_ops->set_rate) {
+			if (rate_ops->determine_rate || rate_ops->round_rate)
+				clk_composite_ops->set_rate =
+						clk_composite_set_rate;
+			else
+				WARN(1, "%s: missing round_rate op is required\n",
+						__func__);
 		}
 
 		composite->rate_hw = rate_hw;
 		composite->rate_ops = rate_ops;
-		clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
-		if (rate_ops->determine_rate)
-			clk_composite_ops->determine_rate = clk_composite_determine_rate;
 	}
 
 	if (gate_hw && gate_ops) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-conf.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-conf.c
--- linux-libre-3.16-gnu/drivers/clk/clk-conf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-conf.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/printk.h>
+#include "clk.h"
+
+static int __set_clk_parents(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	int index, rc, num_parents;
+	struct clk *clk, *pclk;
+
+	num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+						 "#clock-cells");
+	if (num_parents == -EINVAL)
+		pr_err("clk: invalid value of clock-parents property at %s\n",
+		       node->full_name);
+
+	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 rc;
+		}
+		if (clkspec.np == node && !clk_supplier)
+			return 0;
+		pclk = of_clk_get_by_clkspec(&clkspec);
+		if (IS_ERR(pclk)) {
+			pr_warn("clk: couldn't get parent clock %d for %s\n",
+				index, node->full_name);
+			return PTR_ERR(pclk);
+		}
+
+		rc = of_parse_phandle_with_args(node, "assigned-clocks",
+					"#clock-cells", index, &clkspec);
+		if (rc < 0)
+			goto err;
+		if (clkspec.np == node && !clk_supplier) {
+			rc = 0;
+			goto err;
+		}
+		clk = of_clk_get_by_clkspec(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_warn("clk: couldn't get parent clock %d for %s\n",
+				index, node->full_name);
+			rc = PTR_ERR(clk);
+			goto err;
+		}
+
+		rc = clk_set_parent(clk, pclk);
+		if (rc < 0)
+			pr_err("clk: failed to reparent %s to %s: %d\n",
+			       __clk_get_name(clk), __clk_get_name(pclk), rc);
+		clk_put(clk);
+		clk_put(pclk);
+	}
+	return 0;
+err:
+	clk_put(pclk);
+	return rc;
+}
+
+static int __set_clk_rates(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	struct property	*prop;
+	const __be32 *cur;
+	int rc, index = 0;
+	struct clk *clk;
+	u32 rate;
+
+	of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
+		if (rate) {
+			rc = of_parse_phandle_with_args(node, "assigned-clocks",
+					"#clock-cells",	index, &clkspec);
+			if (rc < 0) {
+				/* skip empty (null) phandles */
+				if (rc == -ENOENT)
+					continue;
+				else
+					return rc;
+			}
+			if (clkspec.np == node && !clk_supplier)
+				return 0;
+
+			clk = of_clk_get_by_clkspec(&clkspec);
+			if (IS_ERR(clk)) {
+				pr_warn("clk: couldn't get clock %d for %s\n",
+					index, node->full_name);
+				return PTR_ERR(clk);
+			}
+
+			rc = clk_set_rate(clk, rate);
+			if (rc < 0)
+				pr_err("clk: couldn't set %s clock rate: %d\n",
+				       __clk_get_name(clk), rc);
+			clk_put(clk);
+		}
+		index++;
+	}
+	return 0;
+}
+
+/**
+ * of_clk_set_defaults() - parse and set assigned clocks configuration
+ * @node: device node to apply clock settings for
+ * @clk_supplier: true if clocks supplied by @node should also be considered
+ *
+ * This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
+ * and sets any specified clock parents and rates. The @clk_supplier argument
+ * should be set to true if @node may be also a clock supplier of any clock
+ * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
+ * If @clk_supplier is false the function exits returnning 0 as soon as it
+ * determines the @node is also a supplier of any of the clocks.
+ */
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
+{
+	int rc;
+
+	if (!node)
+		return 0;
+
+	rc = __set_clk_parents(node, clk_supplier);
+	if (rc < 0)
+		return rc;
+
+	return __set_clk_rates(node, clk_supplier);
+}
+EXPORT_SYMBOL_GPL(of_clk_set_defaults);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clkdev.c linux-libre-3.17-rc7-gnu/drivers/clk/clkdev.c
--- linux-libre-3.16-gnu/drivers/clk/clkdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clkdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,8 +101,9 @@ struct clk *of_clk_get_by_name(struct de
 		if (!IS_ERR(clk))
 			break;
 		else if (name && index >= 0) {
-			pr_err("ERROR: could not get clock %s:%s(%i)\n",
-				np->full_name, name ? name : "", index);
+			if (PTR_ERR(clk) != -EPROBE_DEFER)
+				pr_err("ERROR: could not get clock %s:%s(%i)\n",
+					np->full_name, name ? name : "", index);
 			return clk;
 		}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-efm32gg.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-efm32gg.c
--- linux-libre-3.16-gnu/drivers/clk/clk-efm32gg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-efm32gg.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@ static struct clk_onecell_data clk_data
 	.clk_num = ARRAY_SIZE(clk),
 };
 
-static int __init efm32gg_cmu_init(struct device_node *np)
+static void __init efm32gg_cmu_init(struct device_node *np)
 {
 	int i;
 	void __iomem *base;
@@ -33,7 +33,7 @@ static int __init efm32gg_cmu_init(struc
 	base = of_iomap(np, 0);
 	if (!base) {
 		pr_warn("Failed to map address range for efm32gg,cmu node\n");
-		return -EADDRNOTAVAIL;
+		return;
 	}
 
 	clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL,
@@ -76,6 +76,6 @@ static int __init efm32gg_cmu_init(struc
 	clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0",
 			"HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
 
-	return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 }
 CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-palmas.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-palmas.c
--- linux-libre-3.16-gnu/drivers/clk/clk-palmas.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-palmas.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,307 @@
+/*
+ * Clock driver for Palmas device.
+ *
+ * Copyright (c) 2013, NVIDIA Corporation.
+ * Copyright (c) 2013-2014 Texas Instruments, Inc.
+ *
+ * Author:	Laxman Dewangan <ldewangan@nvidia.com>
+ *		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 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/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/palmas.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1	1
+#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2	2
+#define PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP	3
+
+struct palmas_clk32k_desc {
+	const char *clk_name;
+	unsigned int control_reg;
+	unsigned int enable_mask;
+	unsigned int sleep_mask;
+	unsigned int sleep_reqstr_id;
+	int delay;
+};
+
+struct palmas_clock_info {
+	struct device *dev;
+	struct clk *clk;
+	struct clk_hw hw;
+	struct palmas *palmas;
+	struct palmas_clk32k_desc *clk_desc;
+	int ext_control_pin;
+};
+
+static inline struct palmas_clock_info *to_palmas_clks_info(struct clk_hw *hw)
+{
+	return container_of(hw, struct palmas_clock_info, hw);
+}
+
+static unsigned long palmas_clks_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	return 32768;
+}
+
+static int palmas_clks_prepare(struct clk_hw *hw)
+{
+	struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+	int ret;
+
+	ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+				 cinfo->clk_desc->control_reg,
+				 cinfo->clk_desc->enable_mask,
+				 cinfo->clk_desc->enable_mask);
+	if (ret < 0)
+		dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+			cinfo->clk_desc->control_reg, ret);
+	else if (cinfo->clk_desc->delay)
+		udelay(cinfo->clk_desc->delay);
+
+	return ret;
+}
+
+static void palmas_clks_unprepare(struct clk_hw *hw)
+{
+	struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+	int ret;
+
+	/*
+	 * Clock can be disabled through external pin if it is externally
+	 * controlled.
+	 */
+	if (cinfo->ext_control_pin)
+		return;
+
+	ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+				 cinfo->clk_desc->control_reg,
+				 cinfo->clk_desc->enable_mask, 0);
+	if (ret < 0)
+		dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+			cinfo->clk_desc->control_reg, ret);
+}
+
+static int palmas_clks_is_prepared(struct clk_hw *hw)
+{
+	struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+	int ret;
+	u32 val;
+
+	if (cinfo->ext_control_pin)
+		return 1;
+
+	ret = palmas_read(cinfo->palmas, PALMAS_RESOURCE_BASE,
+			  cinfo->clk_desc->control_reg, &val);
+	if (ret < 0) {
+		dev_err(cinfo->dev, "Reg 0x%02x read failed, %d\n",
+			cinfo->clk_desc->control_reg, ret);
+		return ret;
+	}
+	return !!(val & cinfo->clk_desc->enable_mask);
+}
+
+static struct clk_ops palmas_clks_ops = {
+	.prepare	= palmas_clks_prepare,
+	.unprepare	= palmas_clks_unprepare,
+	.is_prepared	= palmas_clks_is_prepared,
+	.recalc_rate	= palmas_clks_recalc_rate,
+};
+
+struct palmas_clks_of_match_data {
+	struct clk_init_data init;
+	struct palmas_clk32k_desc desc;
+};
+
+static struct palmas_clks_of_match_data palmas_of_clk32kg = {
+	.init = {
+		.name = "clk32kg",
+		.ops = &palmas_clks_ops,
+		.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+	},
+	.desc = {
+		.clk_name = "clk32kg",
+		.control_reg = PALMAS_CLK32KG_CTRL,
+		.enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+		.sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+		.sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KG,
+		.delay = 200,
+	},
+};
+
+static struct palmas_clks_of_match_data palmas_of_clk32kgaudio = {
+	.init = {
+		.name = "clk32kgaudio",
+		.ops = &palmas_clks_ops,
+		.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+	},
+	.desc = {
+		.clk_name = "clk32kgaudio",
+		.control_reg = PALMAS_CLK32KGAUDIO_CTRL,
+		.enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+		.sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+		.sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO,
+		.delay = 200,
+	},
+};
+
+static struct of_device_id palmas_clks_of_match[] = {
+	{
+		.compatible = "ti,palmas-clk32kg",
+		.data = &palmas_of_clk32kg,
+	},
+	{
+		.compatible = "ti,palmas-clk32kgaudio",
+		.data = &palmas_of_clk32kgaudio,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, palmas_clks_of_match);
+
+static void palmas_clks_get_clk_data(struct platform_device *pdev,
+				     struct palmas_clock_info *cinfo)
+{
+	struct device_node *node = pdev->dev.of_node;
+	unsigned int prop;
+	int ret;
+
+	ret = of_property_read_u32(node, "ti,external-sleep-control",
+				   &prop);
+	if (ret)
+		return;
+
+	switch (prop) {
+	case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1:
+		prop = PALMAS_EXT_CONTROL_ENABLE1;
+		break;
+	case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2:
+		prop = PALMAS_EXT_CONTROL_ENABLE2;
+		break;
+	case PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP:
+		prop = PALMAS_EXT_CONTROL_NSLEEP;
+		break;
+	default:
+		dev_warn(&pdev->dev, "%s: Invalid ext control option: %u\n",
+			 node->name, prop);
+		prop = 0;
+		break;
+	}
+	cinfo->ext_control_pin = prop;
+}
+
+static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
+{
+	int ret;
+
+	ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+				 cinfo->clk_desc->control_reg,
+				 cinfo->clk_desc->sleep_mask, 0);
+	if (ret < 0) {
+		dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+			cinfo->clk_desc->control_reg, ret);
+		return ret;
+	}
+
+	if (cinfo->ext_control_pin) {
+		ret = clk_prepare(cinfo->clk);
+		if (ret < 0) {
+			dev_err(cinfo->dev, "Clock prep failed, %d\n", ret);
+			return ret;
+		}
+
+		ret = palmas_ext_control_req_config(cinfo->palmas,
+					cinfo->clk_desc->sleep_reqstr_id,
+					cinfo->ext_control_pin, true);
+		if (ret < 0) {
+			dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
+				cinfo->clk_desc->clk_name, ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+static int palmas_clks_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *node = pdev->dev.of_node;
+	struct palmas_clks_of_match_data *match_data;
+	const struct of_device_id *match;
+	struct palmas_clock_info *cinfo;
+	struct clk *clk;
+	int ret;
+
+	match = of_match_device(palmas_clks_of_match, &pdev->dev);
+	match_data = (struct palmas_clks_of_match_data *)match->data;
+
+	cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	palmas_clks_get_clk_data(pdev, cinfo);
+	platform_set_drvdata(pdev, cinfo);
+
+	cinfo->dev = &pdev->dev;
+	cinfo->palmas = palmas;
+
+	cinfo->clk_desc = &match_data->desc;
+	cinfo->hw.init = &match_data->init;
+	clk = devm_clk_register(&pdev->dev, &cinfo->hw);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		dev_err(&pdev->dev, "Fail to register clock %s, %d\n",
+			match_data->desc.clk_name, ret);
+		return ret;
+	}
+
+	cinfo->clk = clk;
+	ret = palmas_clks_init_configure(cinfo);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Clock config failed, %d\n", ret);
+		return ret;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, cinfo->clk);
+	if (ret < 0)
+		dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
+	return ret;
+}
+
+static int palmas_clks_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver palmas_clks_driver = {
+	.driver = {
+		.name = "palmas-clk",
+		.owner = THIS_MODULE,
+		.of_match_table = palmas_clks_of_match,
+	},
+	.probe = palmas_clks_probe,
+	.remove = palmas_clks_remove,
+};
+
+module_platform_driver(palmas_clks_driver);
+
+MODULE_DESCRIPTION("Clock driver for Palmas Series Devices");
+MODULE_ALIAS("platform:palmas-clk");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-ppc-corenet.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-ppc-corenet.c
--- linux-libre-3.16-gnu/drivers/clk/clk-ppc-corenet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-ppc-corenet.c	2014-09-28 17:29:07.000000000 -0400
@@ -291,7 +291,7 @@ static const struct of_device_id ppc_clk
 	{}
 };
 
-static struct platform_driver ppc_corenet_clk_driver = {
+static struct platform_driver ppc_corenet_clk_driver __initdata = {
 	.driver = {
 		.name = "ppc_corenet_clock",
 		.owner = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/clk-s2mps11.c linux-libre-3.17-rc7-gnu/drivers/clk/clk-s2mps11.c
--- linux-libre-3.16-gnu/drivers/clk/clk-s2mps11.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/clk-s2mps11.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,6 @@ struct s2mps11_clk {
 	struct clk *clk;
 	struct clk_lookup *lookup;
 	u32 mask;
-	bool enabled;
 	unsigned int reg;
 };
 
@@ -63,8 +62,6 @@ static int s2mps11_clk_prepare(struct cl
 	ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
 				 s2mps11->reg,
 				 s2mps11->mask, s2mps11->mask);
-	if (!ret)
-		s2mps11->enabled = true;
 
 	return ret;
 }
@@ -76,32 +73,32 @@ static void s2mps11_clk_unprepare(struct
 
 	ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
 			   s2mps11->mask, ~s2mps11->mask);
-
-	if (!ret)
-		s2mps11->enabled = false;
 }
 
-static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+static int s2mps11_clk_is_prepared(struct clk_hw *hw)
 {
+	int ret;
+	u32 val;
 	struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 
-	return s2mps11->enabled;
+	ret = regmap_read(s2mps11->iodev->regmap_pmic,
+				s2mps11->reg, &val);
+	if (ret < 0)
+		return -EINVAL;
+
+	return val & s2mps11->mask;
 }
 
 static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
 					     unsigned long parent_rate)
 {
-	struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
-	if (s2mps11->enabled)
-		return 32768;
-	else
-		return 0;
+	return 32768;
 }
 
 static struct clk_ops s2mps11_clk_ops = {
 	.prepare	= s2mps11_clk_prepare,
 	.unprepare	= s2mps11_clk_unprepare,
-	.is_enabled	= s2mps11_clk_is_enabled,
+	.is_prepared	= s2mps11_clk_is_prepared,
 	.recalc_rate	= s2mps11_clk_recalc_rate,
 };
 
@@ -169,7 +166,6 @@ static int s2mps11_clk_probe(struct plat
 	unsigned int s2mps11_reg;
 	struct clk_init_data *clks_init;
 	int i, ret = 0;
-	u32 val;
 
 	s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
 					S2MPS11_CLKS_NUM, GFP_KERNEL);
@@ -214,13 +210,6 @@ static int s2mps11_clk_probe(struct plat
 		s2mps11_clk->mask = 1 << i;
 		s2mps11_clk->reg = s2mps11_reg;
 
-		ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
-				  s2mps11_clk->reg, &val);
-		if (ret < 0)
-			goto err_reg;
-
-		s2mps11_clk->enabled = val & s2mps11_clk->mask;
-
 		s2mps11_clk->clk = devm_clk_register(&pdev->dev,
 							&s2mps11_clk->hw);
 		if (IS_ERR(s2mps11_clk->clk)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/Kconfig linux-libre-3.17-rc7-gnu/drivers/clk/Kconfig
--- linux-libre-3.16-gnu/drivers/clk/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -102,6 +102,13 @@ config COMMON_CLK_KEYSTONE
           Supports clock drivers for Keystone based SOCs. These SOCs have local
 	  a power sleep control module that gate the clock to the IPs and PLLs.
 
+config COMMON_CLK_PALMAS
+	tristate "Clock driver for TI Palmas devices"
+	depends on MFD_PALMAS
+	---help---
+	  This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
+	  using common clock framework.
+
 source "drivers/clk/qcom/Kconfig"
 
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/Makefile
--- linux-libre-3.16-gnu/drivers/clk/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,12 +9,16 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-gate.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-mux.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-composite.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-fractional-divider.o
+ifeq ($(CONFIG_OF), y)
+obj-$(CONFIG_COMMON_CLK)	+= clk-conf.o
+endif
 
 # hardware specific clock types
 # please keep this section sorted lexicographically by file/directory path name
 obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN)	+= clk-axi-clkgen.o
 obj-$(CONFIG_ARCH_AXXIA)		+= clk-axm5516.o
 obj-$(CONFIG_ARCH_BCM2835)		+= clk-bcm2835.o
+obj-$(CONFIG_ARCH_CLPS711X)		+= clk-clps711x.o
 obj-$(CONFIG_ARCH_EFM32)		+= clk-efm32gg.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_MACH_LOONGSON1)		+= clk-ls1x.o
@@ -22,6 +26,7 @@ obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_PPC_CORENET)		+= clk-ppc-corenet.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/mvebu/clk-cpu.c linux-libre-3.17-rc7-gnu/drivers/clk/mvebu/clk-cpu.c
--- linux-libre-3.16-gnu/drivers/clk/mvebu/clk-cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/mvebu/clk-cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,10 +16,19 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/mvebu-pmsu.h>
+#include <asm/smp_plat.h>
 
-#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET    0x0
-#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET   0xC
-#define SYS_CTRL_CLK_DIVIDER_MASK	    0x3F
+#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET               0x0
+#define   SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL          0xff
+#define   SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT        8
+#define SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET              0x8
+#define   SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT 16
+#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET              0xC
+#define SYS_CTRL_CLK_DIVIDER_MASK                      0x3F
+
+#define PMU_DFS_RATIO_SHIFT 16
+#define PMU_DFS_RATIO_MASK  0x3F
 
 #define MAX_CPU	    4
 struct cpu_clk {
@@ -28,6 +37,7 @@ struct cpu_clk {
 	const char *clk_name;
 	const char *parent_name;
 	void __iomem *reg_base;
+	void __iomem *pmu_dfs;
 };
 
 static struct clk **clks;
@@ -62,8 +72,9 @@ static long clk_cpu_round_rate(struct cl
 	return *parent_rate / div;
 }
 
-static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
-			    unsigned long parent_rate)
+static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
+				unsigned long parent_rate)
+
 {
 	struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
 	u32 reg, div;
@@ -95,6 +106,58 @@ static int clk_cpu_set_rate(struct clk_h
 	return 0;
 }
 
+static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	u32 reg;
+	unsigned long fabric_div, target_div, cur_rate;
+	struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+
+	/*
+	 * PMU DFS registers are not mapped, Device Tree does not
+	 * describes them. We cannot change the frequency dynamically.
+	 */
+	if (!cpuclk->pmu_dfs)
+		return -ENODEV;
+
+	cur_rate = __clk_get_rate(hwclk->clk);
+
+	reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
+	fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
+		SYS_CTRL_CLK_DIVIDER_MASK;
+
+	/* Frequency is going up */
+	if (rate == 2 * cur_rate)
+		target_div = fabric_div / 2;
+	/* Frequency is going down */
+	else
+		target_div = fabric_div;
+
+	if (target_div == 0)
+		target_div = 1;
+
+	reg = readl(cpuclk->pmu_dfs);
+	reg &= ~(PMU_DFS_RATIO_MASK << PMU_DFS_RATIO_SHIFT);
+	reg |= (target_div << PMU_DFS_RATIO_SHIFT);
+	writel(reg, cpuclk->pmu_dfs);
+
+	reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+	reg |= (SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL <<
+		SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT);
+	writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+	return mvebu_pmsu_dfs_request(cpuclk->cpu);
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	if (__clk_is_enabled(hwclk->clk))
+		return clk_cpu_on_set_rate(hwclk, rate, parent_rate);
+	else
+		return clk_cpu_off_set_rate(hwclk, rate, parent_rate);
+}
+
 static const struct clk_ops cpu_ops = {
 	.recalc_rate = clk_cpu_recalc_rate,
 	.round_rate = clk_cpu_round_rate,
@@ -105,6 +168,7 @@ static void __init of_cpu_clk_setup(stru
 {
 	struct cpu_clk *cpuclk;
 	void __iomem *clock_complex_base = of_iomap(node, 0);
+	void __iomem *pmu_dfs_base = of_iomap(node, 1);
 	int ncpus = 0;
 	struct device_node *dn;
 
@@ -114,6 +178,10 @@ static void __init of_cpu_clk_setup(stru
 		return;
 	}
 
+	if (pmu_dfs_base == NULL)
+		pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n",
+			__func__);
+
 	for_each_node_by_type(dn, "cpu")
 		ncpus++;
 
@@ -146,6 +214,8 @@ static void __init of_cpu_clk_setup(stru
 		cpuclk[cpu].clk_name = clk_name;
 		cpuclk[cpu].cpu = cpu;
 		cpuclk[cpu].reg_base = clock_complex_base;
+		if (pmu_dfs_base)
+			cpuclk[cpu].pmu_dfs = pmu_dfs_base + 4 * cpu;
 		cpuclk[cpu].hw.init = &init;
 
 		init.name = cpuclk[cpu].clk_name;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/clk-pll.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-pll.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/clk-pll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-pll.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,7 +166,7 @@ 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)
+clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
 {
 	u32 val;
 	u32 mask;
@@ -175,7 +175,7 @@ clk_pll_set_fsm_mode(struct clk_pll *pll
 	regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
 
 	/* Program bias count and lock count */
-	val = 1 << PLL_BIAS_COUNT_SHIFT;
+	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);
@@ -212,11 +212,20 @@ static void clk_pll_configure(struct clk
 	regmap_update_bits(regmap, pll->config_reg, mask, val);
 }
 
+void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
+		const struct pll_config *config, bool fsm_mode)
+{
+	clk_pll_configure(pll, regmap, config);
+	if (fsm_mode)
+		clk_pll_set_fsm_mode(pll, regmap, 8);
+}
+EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
+
 void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 		const struct pll_config *config, bool fsm_mode)
 {
 	clk_pll_configure(pll, regmap, config);
 	if (fsm_mode)
-		clk_pll_set_fsm_mode(pll, regmap);
+		clk_pll_set_fsm_mode(pll, regmap, 0);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/clk-pll.h linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-pll.h
--- linux-libre-3.16-gnu/drivers/clk/qcom/clk-pll.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-pll.h	2014-09-28 17:29:07.000000000 -0400
@@ -60,6 +60,8 @@ struct pll_config {
 	u32 aux_output_mask;
 };
 
+void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
+		const struct pll_config *config, bool fsm_mode);
 void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 		const struct pll_config *config, bool fsm_mode);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/clk-rcg.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-rcg.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/clk-rcg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-rcg.c	2014-09-28 17:29:07.000000000 -0400
@@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(s
 	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
 }
 
-static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
-			    unsigned long parent_rate)
+static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
-	const struct freq_tbl *f;
+	const struct freq_tbl *f = rcg->freq_tbl;
+
+	*p = clk_get_parent_by_index(hw->clk, f->src);
+	*p_rate = __clk_round_rate(*p, rate);
+
+	return *p_rate;
+}
+
+static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
+{
 	u32 ns, md, ctl;
 	struct mn *mn = &rcg->mn;
 	u32 mask = 0;
 	unsigned int reset_reg;
 
-	f = find_freq(rcg->freq_tbl, rate);
-	if (!f)
-		return -EINVAL;
-
 	if (rcg->mn.reset_in_cc)
 		reset_reg = rcg->clkr.enable_reg;
 	else
@@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_h
 	return 0;
 }
 
+static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	const struct freq_tbl *f;
+
+	f = find_freq(rcg->freq_tbl, rate);
+	if (!f)
+		return -EINVAL;
+
+	return __clk_rcg_set_rate(rcg, f);
+}
+
+static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+
+	return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
+}
+
 static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
 {
 	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
@@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg_ops);
 
+const struct clk_ops clk_rcg_bypass_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_rcg_get_parent,
+	.set_parent = clk_rcg_set_parent,
+	.recalc_rate = clk_rcg_recalc_rate,
+	.determine_rate = clk_rcg_bypass_determine_rate,
+	.set_rate = clk_rcg_bypass_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
+
 const struct clk_ops clk_dyn_rcg_ops = {
 	.enable = clk_enable_regmap,
 	.is_enabled = clk_is_enabled_regmap,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/clk-rcg.h linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-rcg.h
--- linux-libre-3.16-gnu/drivers/clk/qcom/clk-rcg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/clk-rcg.h	2014-09-28 17:29:07.000000000 -0400
@@ -95,6 +95,7 @@ struct clk_rcg {
 };
 
 extern const struct clk_ops clk_rcg_ops;
+extern const struct clk_ops clk_rcg_bypass_ops;
 
 #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/common.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/common.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,30 +27,35 @@ struct qcom_cc {
 	struct clk *clks[];
 };
 
-int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
+struct regmap *
+qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
 {
 	void __iomem *base;
 	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return ERR_CAST(base);
+
+	return devm_regmap_init_mmio(dev, base, desc->config);
+}
+EXPORT_SYMBOL_GPL(qcom_cc_map);
+
+int qcom_cc_really_probe(struct platform_device *pdev,
+			 const struct qcom_cc_desc *desc, struct regmap *regmap)
+{
 	int i, ret;
 	struct device *dev = &pdev->dev;
 	struct clk *clk;
 	struct clk_onecell_data *data;
 	struct clk **clks;
-	struct regmap *regmap;
 	struct qcom_reset_controller *reset;
 	struct qcom_cc *cc;
 	size_t num_clks = desc->num_clks;
 	struct clk_regmap **rclks = desc->clks;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	regmap = devm_regmap_init_mmio(dev, base, desc->config);
-	if (IS_ERR(regmap))
-		return PTR_ERR(regmap);
-
 	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
 			  GFP_KERNEL);
 	if (!cc)
@@ -91,6 +96,18 @@ int qcom_cc_probe(struct platform_device
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
+
+int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
+{
+	struct regmap *regmap;
+
+	regmap = qcom_cc_map(pdev, desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	return qcom_cc_really_probe(pdev, desc, regmap);
+}
 EXPORT_SYMBOL_GPL(qcom_cc_probe);
 
 void qcom_cc_remove(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/common.h linux-libre-3.17-rc7-gnu/drivers/clk/qcom/common.h
--- linux-libre-3.16-gnu/drivers/clk/qcom/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@ struct platform_device;
 struct regmap_config;
 struct clk_regmap;
 struct qcom_reset_map;
+struct regmap;
 
 struct qcom_cc_desc {
 	const struct regmap_config *config;
@@ -26,6 +27,11 @@ struct qcom_cc_desc {
 	size_t num_resets;
 };
 
+extern struct regmap *qcom_cc_map(struct platform_device *pdev,
+				  const struct qcom_cc_desc *desc);
+extern int qcom_cc_really_probe(struct platform_device *pdev,
+				const struct qcom_cc_desc *desc,
+				struct regmap *regmap);
 extern int qcom_cc_probe(struct platform_device *pdev,
 			 const struct qcom_cc_desc *desc);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/gcc-apq8084.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-apq8084.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/gcc-apq8084.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-apq8084.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,3611 @@
+/*
+ * 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/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-apq8084.h>
+#include <dt-bindings/reset/qcom,gcc-apq8084.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO	0
+#define P_GPLL0	1
+#define P_GPLL1	1
+#define P_GPLL4	2
+#define P_PCIE_0_1_PIPE_CLK 1
+#define P_SATA_ASIC0_CLK 1
+#define P_SATA_RX_CLK 1
+#define P_SLEEP_CLK 1
+
+static const u8 gcc_xo_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_GPLL0]	= 1,
+};
+
+static const char *gcc_xo_gpll0[] = {
+	"xo",
+	"gpll0_vote",
+};
+
+static const u8 gcc_xo_gpll0_gpll4_map[] = {
+	[P_XO]		= 0,
+	[P_GPLL0]	= 1,
+	[P_GPLL4]	= 5,
+};
+
+static const char *gcc_xo_gpll0_gpll4[] = {
+	"xo",
+	"gpll0_vote",
+	"gpll4_vote",
+};
+
+static const u8 gcc_xo_sata_asic0_map[] = {
+	[P_XO]			= 0,
+	[P_SATA_ASIC0_CLK]	= 2,
+};
+
+static const char *gcc_xo_sata_asic0[] = {
+	"xo",
+	"sata_asic0_clk",
+};
+
+static const u8 gcc_xo_sata_rx_map[] = {
+	[P_XO]			= 0,
+	[P_SATA_RX_CLK]		= 2,
+};
+
+static const char *gcc_xo_sata_rx[] = {
+	"xo",
+	"sata_rx_clk",
+};
+
+static const u8 gcc_xo_pcie_map[] = {
+	[P_XO]			= 0,
+	[P_PCIE_0_1_PIPE_CLK]	= 2,
+};
+
+static const char *gcc_xo_pcie[] = {
+	"xo",
+	"pcie_pipe",
+};
+
+static const u8 gcc_xo_pcie_sleep_map[] = {
+	[P_XO]			= 0,
+	[P_SLEEP_CLK]		= 6,
+};
+
+static const char *gcc_xo_pcie_sleep[] = {
+	"xo",
+	"sleep_clk_src",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll gpll0 = {
+	.l_reg = 0x0004,
+	.m_reg = 0x0008,
+	.n_reg = 0x000c,
+	.config_reg = 0x0014,
+	.mode_reg = 0x0000,
+	.status_reg = 0x001c,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll0",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap gpll0_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(0),
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll0_vote",
+		.parent_names = (const char *[]){ "gpll0" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_rcg2 config_noc_clk_src = {
+	.cmd_rcgr = 0x0150,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "config_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 periph_noc_clk_src = {
+	.cmd_rcgr = 0x0190,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "periph_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 system_noc_clk_src = {
+	.cmd_rcgr = 0x0120,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "system_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_pll gpll1 = {
+	.l_reg = 0x0044,
+	.m_reg = 0x0048,
+	.n_reg = 0x004c,
+	.config_reg = 0x0054,
+	.mode_reg = 0x0040,
+	.status_reg = 0x005c,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll1",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap gpll1_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(1),
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll1_vote",
+		.parent_names = (const char *[]){ "gpll1" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll gpll4 = {
+	.l_reg = 0x1dc4,
+	.m_reg = 0x1dc8,
+	.n_reg = 0x1dcc,
+	.config_reg = 0x1dd4,
+	.mode_reg = 0x1dc0,
+	.status_reg = 0x1ddc,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll4",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap gpll4_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(4),
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll4_vote",
+		.parent_names = (const char *[]){ "gpll4" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_axi_clk[] = {
+	F(100000000, P_GPLL0, 6, 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 = 0x1d64,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ufs_axi_clk,
+	.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 const struct freq_tbl ftbl_gcc_usb30_master_clk[] = {
+	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_gcc_usb30_master_clk,
+	.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 const struct freq_tbl ftbl_gcc_usb30_sec_master_clk[] = {
+	F(125000000, P_GPLL0, 1, 5, 24),
+	{ }
+};
+
+static struct clk_rcg2 usb30_sec_master_clk_src = {
+	.cmd_rcgr = 0x1bd4,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb30_sec_master_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb30_sec_master_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_usb30_sec_mock_utmi_clk = {
+	.halt_reg = 0x1bd0,
+	.clkr = {
+		.enable_reg = 0x1bd0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sec_mock_utmi_clk",
+			.parent_names = (const char *[]){
+				"usb30_sec_mock_utmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_sec_sleep_clk = {
+	.halt_reg = 0x1bcc,
+	.clkr = {
+		.enable_reg = 0x1bcc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sec_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk[] = {
+	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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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 const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk[] = {
+	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(25000000, P_GPLL0, 12, 1, 2),
+	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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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 const struct freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = {
+	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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.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_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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_gcc_blsp1_2_uart1_6_apps_clk,
+	.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 const struct freq_tbl ftbl_gcc_ce1_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(85710000, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(171430000, P_GPLL0, 3.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ce1_clk_src = {
+	.cmd_rcgr = 0x1050,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ce1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ce1_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ce2_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(85710000, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(171430000, P_GPLL0, 3.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ce2_clk_src = {
+	.cmd_rcgr = 0x1090,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ce2_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ce2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ce3_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(85710000, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(171430000, P_GPLL0, 3.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ce3_clk_src = {
+	.cmd_rcgr = 0x1d10,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ce3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ce3_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_gp_clk[] = {
+	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_gcc_gp_clk,
+	.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 clk_rcg2 gp2_clk_src = {
+	.cmd_rcgr = 0x1944,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.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 clk_rcg2 gp3_clk_src = {
+	.cmd_rcgr = 0x1984,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gp3_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_1_aux_clk[] = {
+	F(1010000, P_XO, 1, 1, 19),
+	{ }
+};
+
+static struct clk_rcg2 pcie_0_aux_clk_src = {
+	.cmd_rcgr = 0x1b2c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_pcie_sleep_map,
+	.freq_tbl = ftbl_gcc_pcie_0_1_aux_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcie_0_aux_clk_src",
+		.parent_names = gcc_xo_pcie_sleep,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 pcie_1_aux_clk_src = {
+	.cmd_rcgr = 0x1bac,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_pcie_sleep_map,
+	.freq_tbl = ftbl_gcc_pcie_0_1_aux_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcie_1_aux_clk_src",
+		.parent_names = gcc_xo_pcie_sleep,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_1_pipe_clk[] = {
+	F(125000000, P_PCIE_0_1_PIPE_CLK, 1, 0, 0),
+	F(250000000, P_PCIE_0_1_PIPE_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pcie_0_pipe_clk_src = {
+	.cmd_rcgr = 0x1b18,
+	.hid_width = 5,
+	.parent_map = gcc_xo_pcie_map,
+	.freq_tbl = ftbl_gcc_pcie_0_1_pipe_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcie_0_pipe_clk_src",
+		.parent_names = gcc_xo_pcie,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 pcie_1_pipe_clk_src = {
+	.cmd_rcgr = 0x1b98,
+	.hid_width = 5,
+	.parent_map = gcc_xo_pcie_map,
+	.freq_tbl = ftbl_gcc_pcie_0_1_pipe_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcie_1_pipe_clk_src",
+		.parent_names = gcc_xo_pcie,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk[] = {
+	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_gcc_pdm2_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pdm2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sata_asic0_clk[] = {
+	F(75000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+	F(150000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+	F(300000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sata_asic0_clk_src = {
+	.cmd_rcgr = 0x1c94,
+	.hid_width = 5,
+	.parent_map = gcc_xo_sata_asic0_map,
+	.freq_tbl = ftbl_gcc_sata_asic0_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sata_asic0_clk_src",
+		.parent_names = gcc_xo_sata_asic0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sata_pmalive_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sata_pmalive_clk_src = {
+	.cmd_rcgr = 0x1c80,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sata_pmalive_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sata_pmalive_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sata_rx_clk[] = {
+	F(75000000, P_SATA_RX_CLK, 1, 0, 0),
+	F(150000000, P_SATA_RX_CLK, 1, 0, 0),
+	F(300000000, P_SATA_RX_CLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sata_rx_clk_src = {
+	.cmd_rcgr = 0x1ca8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_sata_rx_map,
+	.freq_tbl = ftbl_gcc_sata_rx_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sata_rx_clk_src",
+		.parent_names = gcc_xo_sata_rx,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sata_rx_oob_clk[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sata_rx_oob_clk_src = {
+	.cmd_rcgr = 0x1c5c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sata_rx_oob_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sata_rx_oob_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
+	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, 4, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(384000000, P_GPLL4, 2, 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_gcc_sdcc1_4_apps_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+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_gcc_sdcc1_4_apps_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_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_gcc_sdcc1_4_apps_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_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_gcc_sdcc1_4_apps_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "sdcc4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_tsif_ref_clk[] = {
+	F(105000, P_XO, 2, 1, 91),
+	{ }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+	.cmd_rcgr = 0x0d90,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_tsif_ref_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "tsif_ref_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
+	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_gcc_usb30_mock_utmi_clk,
+	.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 const struct freq_tbl ftbl_gcc_usb30_sec_mock_utmi_clk[] = {
+	F(125000000, P_GPLL0, 1, 5, 24),
+	{ }
+};
+
+static struct clk_rcg2 usb30_sec_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x1be8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb30_sec_mock_utmi_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb30_sec_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+	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_gcc_usb_hs_system_clk,
+	.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 const struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+	F(480000000, P_GPLL1, 1, 0, 0),
+	{ }
+};
+
+static u8 usb_hsic_clk_src_map[] = {
+	[P_XO]		= 0,
+	[P_GPLL1]	= 4,
+};
+
+static struct clk_rcg2 usb_hsic_clk_src = {
+	.cmd_rcgr = 0x0440,
+	.hid_width = 5,
+	.parent_map = usb_hsic_clk_src_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_clk_src",
+		.parent_names = (const char *[]){
+			"xo",
+			"gpll1_vote",
+		},
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_ahb_clk_src[] = {
+	F(60000000, P_GPLL1, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_ahb_clk_src = {
+	.cmd_rcgr = 0x046c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = usb_hsic_clk_src_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_ahb_clk_src,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_ahb_clk_src",
+		.parent_names = (const char *[]){
+			"xo",
+			"gpll1_vote",
+		},
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
+	F(9600000, P_XO, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_io_cal_clk_src = {
+	.cmd_rcgr = 0x0458,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_io_cal_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_mock_utmi_clk = {
+	.halt_reg = 0x1f14,
+	.clkr = {
+		.enable_reg = 0x1f14,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_mock_utmi_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_mock_utmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_mock_utmi_clk[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x1f00,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_mock_utmi_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
+	F(75000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_system_clk_src = {
+	.cmd_rcgr = 0x041c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_system_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_bam_dma_ahb_clk = {
+	.halt_reg = 0x0d44,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(12),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_bam_dma_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_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",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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_boot_rom_ahb_clk = {
+	.halt_reg = 0x0e04,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(10),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_boot_rom_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_ahb_clk = {
+	.halt_reg = 0x104c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(3),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce1_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_axi_clk = {
+	.halt_reg = 0x1048,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce1_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_clk = {
+	.halt_reg = 0x1050,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(5),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce1_clk",
+			.parent_names = (const char *[]){
+				"ce1_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_ahb_clk = {
+	.halt_reg = 0x108c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce2_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_axi_clk = {
+	.halt_reg = 0x1088,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(1),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce2_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_clk = {
+	.halt_reg = 0x1090,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce2_clk",
+			.parent_names = (const char *[]){
+				"ce2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce3_ahb_clk = {
+	.halt_reg = 0x1d0c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1d0c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce3_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce3_axi_clk = {
+	.halt_reg = 0x1088,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1d08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce3_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce3_clk = {
+	.halt_reg = 0x1090,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1d04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ce3_clk",
+			.parent_names = (const char *[]){
+				"ce3_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_ocmem_noc_cfg_ahb_clk = {
+	.halt_reg = 0x0248,
+	.clkr = {
+		.enable_reg = 0x0248,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ocmem_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+	.halt_reg = 0x1b10,
+	.clkr = {
+		.enable_reg = 0x1b10,
+		.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_cfg_ahb_clk = {
+	.halt_reg = 0x1b0c,
+	.clkr = {
+		.enable_reg = 0x1b0c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+	.halt_reg = 0x1b08,
+	.clkr = {
+		.enable_reg = 0x1b08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_mstr_axi_clk",
+			.parent_names = (const char *[]){
+				"config_noc_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 = 0x1b14,
+	.clkr = {
+		.enable_reg = 0x1b14,
+		.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_0_slv_axi_clk = {
+	.halt_reg = 0x1b04,
+	.clkr = {
+		.enable_reg = 0x1b04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_0_slv_axi_clk",
+			.parent_names = (const char *[]){
+				"config_noc_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 = 0x1b90,
+	.clkr = {
+		.enable_reg = 0x1b90,
+		.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_cfg_ahb_clk = {
+	.halt_reg = 0x1b8c,
+	.clkr = {
+		.enable_reg = 0x1b8c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+	.halt_reg = 0x1b88,
+	.clkr = {
+		.enable_reg = 0x1b88,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_mstr_axi_clk",
+			.parent_names = (const char *[]){
+				"config_noc_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 = 0x1b94,
+	.clkr = {
+		.enable_reg = 0x1b94,
+		.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_pcie_1_slv_axi_clk = {
+	.halt_reg = 0x1b84,
+	.clkr = {
+		.enable_reg = 0x1b84,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pcie_1_slv_axi_clk",
+			.parent_names = (const char *[]){
+				"config_noc_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_pdm_ahb_clk = {
+	.halt_reg = 0x0cc4,
+	.clkr = {
+		.enable_reg = 0x0cc4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_pdm_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_periph_noc_usb_hsic_ahb_clk = {
+	.halt_reg = 0x01a4,
+	.clkr = {
+		.enable_reg = 0x01a4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_periph_noc_usb_hsic_ahb_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+	.halt_reg = 0x0d04,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(13),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_prng_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_asic0_clk = {
+	.halt_reg = 0x1c54,
+	.clkr = {
+		.enable_reg = 0x1c54,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_asic0_clk",
+			.parent_names = (const char *[]){
+				"sata_asic0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_axi_clk = {
+	.halt_reg = 0x1c44,
+	.clkr = {
+		.enable_reg = 0x1c44,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_axi_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_cfg_ahb_clk = {
+	.halt_reg = 0x1c48,
+	.clkr = {
+		.enable_reg = 0x1c48,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_pmalive_clk = {
+	.halt_reg = 0x1c50,
+	.clkr = {
+		.enable_reg = 0x1c50,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_pmalive_clk",
+			.parent_names = (const char *[]){
+				"sata_pmalive_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_rx_clk = {
+	.halt_reg = 0x1c58,
+	.clkr = {
+		.enable_reg = 0x1c58,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_rx_clk",
+			.parent_names = (const char *[]){
+				"sata_rx_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sata_rx_oob_clk = {
+	.halt_reg = 0x1c4c,
+	.clkr = {
+		.enable_reg = 0x1c4c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sata_rx_oob_clk",
+			.parent_names = (const char *[]){
+				"sata_rx_oob_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+	.halt_reg = 0x04c8,
+	.clkr = {
+		.enable_reg = 0x04c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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_sdcc1_cdccal_ff_clk = {
+	.halt_reg = 0x04e8,
+	.clkr = {
+		.enable_reg = 0x04e8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_cdccal_ff_clk",
+			.parent_names = (const char *[]){
+				"xo"
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = {
+	.halt_reg = 0x04e4,
+	.clkr = {
+		.enable_reg = 0x04e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_cdccal_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src"
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+	.halt_reg = 0x0508,
+	.clkr = {
+		.enable_reg = 0x0508,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc2_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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_ahb_clk = {
+	.halt_reg = 0x0548,
+	.clkr = {
+		.enable_reg = 0x0548,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc3_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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_ahb_clk = {
+	.halt_reg = 0x0588,
+	.clkr = {
+		.enable_reg = 0x0588,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sdcc4_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.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 = 0x013c,
+	.clkr = {
+		.enable_reg = 0x013c,
+		.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 = 0x0108,
+	.clkr = {
+		.enable_reg = 0x0108,
+		.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_sys_noc_usb3_sec_axi_clk = {
+	.halt_reg = 0x0138,
+	.clkr = {
+		.enable_reg = 0x0138,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sys_noc_usb3_sec_axi_clk",
+			.parent_names = (const char *[]){
+				"usb30_sec_master_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ahb_clk = {
+	.halt_reg = 0x0d84,
+	.clkr = {
+		.enable_reg = 0x0d84,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_tsif_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_inactivity_timers_clk = {
+	.halt_reg = 0x0d8c,
+	.clkr = {
+		.enable_reg = 0x0d8c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_tsif_inactivity_timers_clk",
+			.parent_names = (const char *[]){
+				"sleep_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_ahb_clk = {
+	.halt_reg = 0x1d48,
+	.clkr = {
+		.enable_reg = 0x1d48,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+	.halt_reg = 0x1d44,
+	.clkr = {
+		.enable_reg = 0x1d44,
+		.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 = 0x1d50,
+	.clkr = {
+		.enable_reg = 0x1d50,
+		.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_rx_symbol_0_clk = {
+	.halt_reg = 0x1d5c,
+	.clkr = {
+		.enable_reg = 0x1d5c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_rx_symbol_0_clk",
+			.parent_names = (const char *[]){
+				"ufs_rx_symbol_0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+	.halt_reg = 0x1d60,
+	.clkr = {
+		.enable_reg = 0x1d60,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_rx_symbol_1_clk",
+			.parent_names = (const char *[]){
+				"ufs_rx_symbol_1_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 = 0x1d4c,
+	.clkr = {
+		.enable_reg = 0x1d4c,
+		.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_ufs_tx_symbol_0_clk = {
+	.halt_reg = 0x1d54,
+	.clkr = {
+		.enable_reg = 0x1d54,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_tx_symbol_0_clk",
+			.parent_names = (const char *[]){
+				"ufs_tx_symbol_0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_1_clk = {
+	.halt_reg = 0x1d58,
+	.clkr = {
+		.enable_reg = 0x1d58,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_tx_symbol_1_clk",
+			.parent_names = (const char *[]){
+				"ufs_tx_symbol_1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb2a_phy_sleep_clk = {
+	.halt_reg = 0x04ac,
+	.clkr = {
+		.enable_reg = 0x04ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb2a_phy_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb2b_phy_sleep_clk = {
+	.halt_reg = 0x04b4,
+	.clkr = {
+		.enable_reg = 0x04b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb2b_phy_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.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_sec_master_clk = {
+	.halt_reg = 0x1bc8,
+	.clkr = {
+		.enable_reg = 0x1bc8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sec_master_clk",
+			.parent_names = (const char *[]){
+				"usb30_sec_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_usb30_sleep_clk = {
+	.halt_reg = 0x03cc,
+	.clkr = {
+		.enable_reg = 0x03cc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hs_ahb_clk = {
+	.halt_reg = 0x0488,
+	.clkr = {
+		.enable_reg = 0x0488,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hs_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hs_inactivity_timers_clk = {
+	.halt_reg = 0x048c,
+	.clkr = {
+		.enable_reg = 0x048c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hs_inactivity_timers_clk",
+			.parent_names = (const char *[]){
+				"sleep_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_branch gcc_usb_hsic_ahb_clk = {
+	.halt_reg = 0x0408,
+	.clkr = {
+		.enable_reg = 0x0408,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_clk = {
+	.halt_reg = 0x0410,
+	.clkr = {
+		.enable_reg = 0x0410,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_clk = {
+	.halt_reg = 0x0414,
+	.clkr = {
+		.enable_reg = 0x0414,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_io_cal_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_io_cal_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_sleep_clk = {
+	.halt_reg = 0x0418,
+	.clkr = {
+		.enable_reg = 0x0418,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_io_cal_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_system_clk = {
+	.halt_reg = 0x040c,
+	.clkr = {
+		.enable_reg = 0x040c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_system_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_system_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_regmap *gcc_apq8084_clocks[] = {
+	[GPLL0] = &gpll0.clkr,
+	[GPLL0_VOTE] = &gpll0_vote,
+	[GPLL1] = &gpll1.clkr,
+	[GPLL1_VOTE] = &gpll1_vote,
+	[GPLL4] = &gpll4.clkr,
+	[GPLL4_VOTE] = &gpll4_vote,
+	[CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
+	[PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
+	[SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
+	[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+	[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+	[USB30_SEC_MASTER_CLK_SRC] = &usb30_sec_master_clk_src.clkr,
+	[USB_HSIC_AHB_CLK_SRC] = &usb_hsic_ahb_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,
+	[CE1_CLK_SRC] = &ce1_clk_src.clkr,
+	[CE2_CLK_SRC] = &ce2_clk_src.clkr,
+	[CE3_CLK_SRC] = &ce3_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,
+	[SATA_ASIC0_CLK_SRC] = &sata_asic0_clk_src.clkr,
+	[SATA_PMALIVE_CLK_SRC] = &sata_pmalive_clk_src.clkr,
+	[SATA_RX_CLK_SRC] = &sata_rx_clk_src.clkr,
+	[SATA_RX_OOB_CLK_SRC] = &sata_rx_oob_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,
+	[USB30_SEC_MOCK_UTMI_CLK_SRC] = &usb30_sec_mock_utmi_clk_src.clkr,
+	[USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+	[USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr,
+	[USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr,
+	[USB_HSIC_MOCK_UTMI_CLK_SRC] = &usb_hsic_mock_utmi_clk_src.clkr,
+	[USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr,
+	[GCC_BAM_DMA_AHB_CLK] = &gcc_bam_dma_ahb_clk.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_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+	[GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr,
+	[GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
+	[GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
+	[GCC_CE2_AHB_CLK] = &gcc_ce2_ahb_clk.clkr,
+	[GCC_CE2_AXI_CLK] = &gcc_ce2_axi_clk.clkr,
+	[GCC_CE2_CLK] = &gcc_ce2_clk.clkr,
+	[GCC_CE3_AHB_CLK] = &gcc_ce3_ahb_clk.clkr,
+	[GCC_CE3_AXI_CLK] = &gcc_ce3_axi_clk.clkr,
+	[GCC_CE3_CLK] = &gcc_ce3_clk.clkr,
+	[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+	[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+	[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+	[GCC_OCMEM_NOC_CFG_AHB_CLK] = &gcc_ocmem_noc_cfg_ahb_clk.clkr,
+	[GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+	[GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
+	[GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
+	[GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+	[GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
+	[GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+	[GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
+	[GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
+	[GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+	[GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
+	[GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+	[GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+	[GCC_PERIPH_NOC_USB_HSIC_AHB_CLK] = &gcc_periph_noc_usb_hsic_ahb_clk.clkr,
+	[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+	[GCC_SATA_ASIC0_CLK] = &gcc_sata_asic0_clk.clkr,
+	[GCC_SATA_AXI_CLK] = &gcc_sata_axi_clk.clkr,
+	[GCC_SATA_CFG_AHB_CLK] = &gcc_sata_cfg_ahb_clk.clkr,
+	[GCC_SATA_PMALIVE_CLK] = &gcc_sata_pmalive_clk.clkr,
+	[GCC_SATA_RX_CLK] = &gcc_sata_rx_clk.clkr,
+	[GCC_SATA_RX_OOB_CLK] = &gcc_sata_rx_oob_clk.clkr,
+	[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+	[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+	[GCC_SDCC1_CDCCAL_FF_CLK] = &gcc_sdcc1_cdccal_ff_clk.clkr,
+	[GCC_SDCC1_CDCCAL_SLEEP_CLK] = &gcc_sdcc1_cdccal_sleep_clk.clkr,
+	[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+	[GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr,
+	[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+	[GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_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_SYS_NOC_USB3_SEC_AXI_CLK] = &gcc_sys_noc_usb3_sec_axi_clk.clkr,
+	[GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr,
+	[GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr,
+	[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+	[GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+	[GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+	[GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+	[GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+	[GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+	[GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+	[GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+	[GCC_UFS_TX_SYMBOL_1_CLK] = &gcc_ufs_tx_symbol_1_clk.clkr,
+	[GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr,
+	[GCC_USB2B_PHY_SLEEP_CLK] = &gcc_usb2b_phy_sleep_clk.clkr,
+	[GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+	[GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+	[GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+	[GCC_USB30_SEC_MASTER_CLK] = &gcc_usb30_sec_master_clk.clkr,
+	[GCC_USB30_SEC_MOCK_UTMI_CLK] = &gcc_usb30_sec_mock_utmi_clk.clkr,
+	[GCC_USB30_SEC_SLEEP_CLK] = &gcc_usb30_sec_sleep_clk.clkr,
+	[GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr,
+	[GCC_USB_HS_INACTIVITY_TIMERS_CLK] = &gcc_usb_hs_inactivity_timers_clk.clkr,
+	[GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+	[GCC_USB_HSIC_AHB_CLK] = &gcc_usb_hsic_ahb_clk.clkr,
+	[GCC_USB_HSIC_CLK] = &gcc_usb_hsic_clk.clkr,
+	[GCC_USB_HSIC_IO_CAL_CLK] = &gcc_usb_hsic_io_cal_clk.clkr,
+	[GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr,
+	[GCC_USB_HSIC_MOCK_UTMI_CLK] = &gcc_usb_hsic_mock_utmi_clk.clkr,
+	[GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_apq8084_resets[] = {
+	[GCC_SYSTEM_NOC_BCR] = { 0x0100 },
+	[GCC_CONFIG_NOC_BCR] = { 0x0140 },
+	[GCC_PERIPH_NOC_BCR] = { 0x0180 },
+	[GCC_IMEM_BCR] = { 0x0200 },
+	[GCC_MMSS_BCR] = { 0x0240 },
+	[GCC_QDSS_BCR] = { 0x0300 },
+	[GCC_USB_30_BCR] = { 0x03c0 },
+	[GCC_USB3_PHY_BCR] = { 0x03fc },
+	[GCC_USB_HS_HSIC_BCR] = { 0x0400 },
+	[GCC_USB_HS_BCR] = { 0x0480 },
+	[GCC_USB2A_PHY_BCR] = { 0x04a8 },
+	[GCC_USB2B_PHY_BCR] = { 0x04b0 },
+	[GCC_SDCC1_BCR] = { 0x04c0 },
+	[GCC_SDCC2_BCR] = { 0x0500 },
+	[GCC_SDCC3_BCR] = { 0x0540 },
+	[GCC_SDCC4_BCR] = { 0x0580 },
+	[GCC_BLSP1_BCR] = { 0x05c0 },
+	[GCC_BLSP1_QUP1_BCR] = { 0x0640 },
+	[GCC_BLSP1_UART1_BCR] = { 0x0680 },
+	[GCC_BLSP1_QUP2_BCR] = { 0x06c0 },
+	[GCC_BLSP1_UART2_BCR] = { 0x0700 },
+	[GCC_BLSP1_QUP3_BCR] = { 0x0740 },
+	[GCC_BLSP1_UART3_BCR] = { 0x0780 },
+	[GCC_BLSP1_QUP4_BCR] = { 0x07c0 },
+	[GCC_BLSP1_UART4_BCR] = { 0x0800 },
+	[GCC_BLSP1_QUP5_BCR] = { 0x0840 },
+	[GCC_BLSP1_UART5_BCR] = { 0x0880 },
+	[GCC_BLSP1_QUP6_BCR] = { 0x08c0 },
+	[GCC_BLSP1_UART6_BCR] = { 0x0900 },
+	[GCC_BLSP2_BCR] = { 0x0940 },
+	[GCC_BLSP2_QUP1_BCR] = { 0x0980 },
+	[GCC_BLSP2_UART1_BCR] = { 0x09c0 },
+	[GCC_BLSP2_QUP2_BCR] = { 0x0a00 },
+	[GCC_BLSP2_UART2_BCR] = { 0x0a40 },
+	[GCC_BLSP2_QUP3_BCR] = { 0x0a80 },
+	[GCC_BLSP2_UART3_BCR] = { 0x0ac0 },
+	[GCC_BLSP2_QUP4_BCR] = { 0x0b00 },
+	[GCC_BLSP2_UART4_BCR] = { 0x0b40 },
+	[GCC_BLSP2_QUP5_BCR] = { 0x0b80 },
+	[GCC_BLSP2_UART5_BCR] = { 0x0bc0 },
+	[GCC_BLSP2_QUP6_BCR] = { 0x0c00 },
+	[GCC_BLSP2_UART6_BCR] = { 0x0c40 },
+	[GCC_PDM_BCR] = { 0x0cc0 },
+	[GCC_PRNG_BCR] = { 0x0d00 },
+	[GCC_BAM_DMA_BCR] = { 0x0d40 },
+	[GCC_TSIF_BCR] = { 0x0d80 },
+	[GCC_TCSR_BCR] = { 0x0dc0 },
+	[GCC_BOOT_ROM_BCR] = { 0x0e00 },
+	[GCC_MSG_RAM_BCR] = { 0x0e40 },
+	[GCC_TLMM_BCR] = { 0x0e80 },
+	[GCC_MPM_BCR] = { 0x0ec0 },
+	[GCC_MPM_AHB_RESET] = { 0x0ec4, 1 },
+	[GCC_MPM_NON_AHB_RESET] = { 0x0ec4, 2 },
+	[GCC_SEC_CTRL_BCR] = { 0x0f40 },
+	[GCC_SPMI_BCR] = { 0x0fc0 },
+	[GCC_SPDM_BCR] = { 0x1000 },
+	[GCC_CE1_BCR] = { 0x1040 },
+	[GCC_CE2_BCR] = { 0x1080 },
+	[GCC_BIMC_BCR] = { 0x1100 },
+	[GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x1240 },
+	[GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x1248 },
+	[GCC_PNOC_BUS_TIMEOUT0_BCR] = { 0x1280 },
+	[GCC_PNOC_BUS_TIMEOUT1_BCR] = { 0x1288 },
+	[GCC_PNOC_BUS_TIMEOUT2_BCR] = { 0x1290 },
+	[GCC_PNOC_BUS_TIMEOUT3_BCR] = { 0x1298 },
+	[GCC_PNOC_BUS_TIMEOUT4_BCR] = { 0x12a0 },
+	[GCC_CNOC_BUS_TIMEOUT0_BCR] = { 0x12c0 },
+	[GCC_CNOC_BUS_TIMEOUT1_BCR] = { 0x12c8 },
+	[GCC_CNOC_BUS_TIMEOUT2_BCR] = { 0x12d0 },
+	[GCC_CNOC_BUS_TIMEOUT3_BCR] = { 0x12d8 },
+	[GCC_CNOC_BUS_TIMEOUT4_BCR] = { 0x12e0 },
+	[GCC_CNOC_BUS_TIMEOUT5_BCR] = { 0x12e8 },
+	[GCC_CNOC_BUS_TIMEOUT6_BCR] = { 0x12f0 },
+	[GCC_DEHR_BCR] = { 0x1300 },
+	[GCC_RBCPR_BCR] = { 0x1380 },
+	[GCC_MSS_RESTART] = { 0x1680 },
+	[GCC_LPASS_RESTART] = { 0x16c0 },
+	[GCC_WCSS_RESTART] = { 0x1700 },
+	[GCC_VENUS_RESTART] = { 0x1740 },
+	[GCC_COPSS_SMMU_BCR] = { 0x1a40 },
+	[GCC_SPSS_BCR] = { 0x1a80 },
+	[GCC_PCIE_0_BCR] = { 0x1ac0 },
+	[GCC_PCIE_0_PHY_BCR] = { 0x1b00 },
+	[GCC_PCIE_1_BCR] = { 0x1b40 },
+	[GCC_PCIE_1_PHY_BCR] = { 0x1b80 },
+	[GCC_USB_30_SEC_BCR] = { 0x1bc0 },
+	[GCC_USB3_SEC_PHY_BCR] = { 0x1bfc },
+	[GCC_SATA_BCR] = { 0x1c40 },
+	[GCC_CE3_BCR] = { 0x1d00 },
+	[GCC_UFS_BCR] = { 0x1d40 },
+	[GCC_USB30_PHY_COM_BCR] = { 0x1e80 },
+};
+
+static const struct regmap_config gcc_apq8084_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x1fc0,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc gcc_apq8084_desc = {
+	.config = &gcc_apq8084_regmap_config,
+	.clks = gcc_apq8084_clocks,
+	.num_clks = ARRAY_SIZE(gcc_apq8084_clocks),
+	.resets = gcc_apq8084_resets,
+	.num_resets = ARRAY_SIZE(gcc_apq8084_resets),
+};
+
+static const struct of_device_id gcc_apq8084_match_table[] = {
+	{ .compatible = "qcom,gcc-apq8084" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_apq8084_match_table);
+
+static int gcc_apq8084_probe(struct platform_device *pdev)
+{
+	struct clk *clk;
+	struct device *dev = &pdev->dev;
+
+	/* Temporary until RPM clocks supported */
+	clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
+				      CLK_IS_ROOT, 32768);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	return qcom_cc_probe(pdev, &gcc_apq8084_desc);
+}
+
+static int gcc_apq8084_remove(struct platform_device *pdev)
+{
+	qcom_cc_remove(pdev);
+	return 0;
+}
+
+static struct platform_driver gcc_apq8084_driver = {
+	.probe		= gcc_apq8084_probe,
+	.remove		= gcc_apq8084_remove,
+	.driver		= {
+		.name	= "gcc-apq8084",
+		.owner	= THIS_MODULE,
+		.of_match_table = gcc_apq8084_match_table,
+	},
+};
+
+static int __init gcc_apq8084_init(void)
+{
+	return platform_driver_register(&gcc_apq8084_driver);
+}
+core_initcall(gcc_apq8084_init);
+
+static void __exit gcc_apq8084_exit(void)
+{
+	platform_driver_unregister(&gcc_apq8084_driver);
+}
+module_exit(gcc_apq8084_exit);
+
+MODULE_DESCRIPTION("QCOM GCC APQ8084 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-apq8084");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/gcc-ipq806x.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-ipq806x.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/gcc-ipq806x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-ipq806x.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2424 @@
+/*
+ * 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/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
+#include <dt-bindings/reset/qcom,gcc-ipq806x.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+static struct clk_pll pll3 = {
+	.l_reg = 0x3164,
+	.m_reg = 0x3168,
+	.n_reg = 0x316c,
+	.config_reg = 0x3174,
+	.mode_reg = 0x3160,
+	.status_reg = 0x3178,
+	.status_bit = 16,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pll3",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_pll pll8 = {
+	.l_reg = 0x3144,
+	.m_reg = 0x3148,
+	.n_reg = 0x314c,
+	.config_reg = 0x3154,
+	.mode_reg = 0x3140,
+	.status_reg = 0x3158,
+	.status_bit = 16,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pll8",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap pll8_vote = {
+	.enable_reg = 0x34c0,
+	.enable_mask = BIT(8),
+	.hw.init = &(struct clk_init_data){
+		.name = "pll8_vote",
+		.parent_names = (const char *[]){ "pll8" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll pll14 = {
+	.l_reg = 0x31c4,
+	.m_reg = 0x31c8,
+	.n_reg = 0x31cc,
+	.config_reg = 0x31d4,
+	.mode_reg = 0x31c0,
+	.status_reg = 0x31d8,
+	.status_bit = 16,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pll14",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap pll14_vote = {
+	.enable_reg = 0x34c0,
+	.enable_mask = BIT(14),
+	.hw.init = &(struct clk_init_data){
+		.name = "pll14_vote",
+		.parent_names = (const char *[]){ "pll14" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+#define P_PXO	0
+#define P_PLL8	1
+#define P_PLL3	1
+#define P_PLL0	2
+#define P_CXO	2
+
+static const u8 gcc_pxo_pll8_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+};
+
+static const char *gcc_pxo_pll8[] = {
+	"pxo",
+	"pll8_vote",
+};
+
+static const u8 gcc_pxo_pll8_cxo_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+	[P_CXO]		= 5,
+};
+
+static const char *gcc_pxo_pll8_cxo[] = {
+	"pxo",
+	"pll8_vote",
+	"cxo",
+};
+
+static const u8 gcc_pxo_pll3_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL3]	= 1,
+};
+
+static const u8 gcc_pxo_pll3_sata_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL3]	= 6,
+};
+
+static const char *gcc_pxo_pll3[] = {
+	"pxo",
+	"pll3",
+};
+
+static const u8 gcc_pxo_pll8_pll0[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+	[P_PLL0]	= 2,
+};
+
+static const char *gcc_pxo_pll8_pll0_map[] = {
+	"pxo",
+	"pll8_vote",
+	"pll0",
+};
+
+static struct freq_tbl clk_tbl_gsbi_uart[] = {
+	{  1843200, P_PLL8, 2,  6, 625 },
+	{  3686400, P_PLL8, 2, 12, 625 },
+	{  7372800, P_PLL8, 2, 24, 625 },
+	{ 14745600, P_PLL8, 2, 48, 625 },
+	{ 16000000, P_PLL8, 4,  1,   6 },
+	{ 24000000, P_PLL8, 4,  1,   4 },
+	{ 32000000, P_PLL8, 4,  1,   3 },
+	{ 40000000, P_PLL8, 1,  5,  48 },
+	{ 46400000, P_PLL8, 1, 29, 240 },
+	{ 48000000, P_PLL8, 4,  1,   2 },
+	{ 51200000, P_PLL8, 1,  2,  15 },
+	{ 56000000, P_PLL8, 1,  7,  48 },
+	{ 58982400, P_PLL8, 1, 96, 625 },
+	{ 64000000, P_PLL8, 2,  1,   3 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_uart_src = {
+	.ns_reg = 0x29d4,
+	.md_reg = 0x29d0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi1_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_uart_src = {
+	.ns_reg = 0x29f4,
+	.md_reg = 0x29f0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 8,
+	.clkr = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi2_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_uart_src = {
+	.ns_reg = 0x2a34,
+	.md_reg = 0x2a30,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 26,
+	.clkr = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi4_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_uart_src = {
+	.ns_reg = 0x2a54,
+	.md_reg = 0x2a50,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 22,
+	.clkr = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi5_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_uart_src = {
+	.ns_reg = 0x2a74,
+	.md_reg = 0x2a70,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 18,
+	.clkr = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi6_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_uart_src = {
+	.ns_reg = 0x2a94,
+	.md_reg = 0x2a90,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.clkr = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 14,
+	.clkr = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi7_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_gsbi_qup[] = {
+	{  1100000, P_PXO,  1, 2, 49 },
+	{  5400000, P_PXO,  1, 1,  5 },
+	{ 10800000, P_PXO,  1, 2,  5 },
+	{ 15060000, P_PLL8, 1, 2, 51 },
+	{ 24000000, P_PLL8, 4, 1,  4 },
+	{ 25600000, P_PLL8, 1, 1, 15 },
+	{ 27000000, P_PXO,  1, 0,  0 },
+	{ 48000000, P_PLL8, 4, 1,  2 },
+	{ 51200000, P_PLL8, 1, 2, 15 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_qup_src = {
+	.ns_reg = 0x29cc,
+	.md_reg = 0x29c8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 11,
+	.clkr = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_clk",
+			.parent_names = (const char *[]){ "gsbi1_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_qup_src = {
+	.ns_reg = 0x29ec,
+	.md_reg = 0x29e8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 6,
+	.clkr = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_clk",
+			.parent_names = (const char *[]){ "gsbi2_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_qup_src = {
+	.ns_reg = 0x2a2c,
+	.md_reg = 0x2a28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 24,
+	.clkr = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_clk",
+			.parent_names = (const char *[]){ "gsbi4_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_qup_src = {
+	.ns_reg = 0x2a4c,
+	.md_reg = 0x2a48,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 20,
+	.clkr = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_clk",
+			.parent_names = (const char *[]){ "gsbi5_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_qup_src = {
+	.ns_reg = 0x2a6c,
+	.md_reg = 0x2a68,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 16,
+	.clkr = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_clk",
+			.parent_names = (const char *[]){ "gsbi6_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_qup_src = {
+	.ns_reg = 0x2a8c,
+	.md_reg = 0x2a88,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.clkr = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_clk",
+			.parent_names = (const char *[]){ "gsbi7_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_h_clk = {
+	.hwcg_reg = 0x29c0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fcc,
+	.halt_bit = 13,
+	.clkr = {
+		.enable_reg = 0x29c0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_h_clk = {
+	.hwcg_reg = 0x29e0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fcc,
+	.halt_bit = 9,
+	.clkr = {
+		.enable_reg = 0x29e0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_h_clk = {
+	.hwcg_reg = 0x2a20,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 27,
+	.clkr = {
+		.enable_reg = 0x2a20,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_h_clk = {
+	.hwcg_reg = 0x2a40,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 23,
+	.clkr = {
+		.enable_reg = 0x2a40,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi5_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_h_clk = {
+	.hwcg_reg = 0x2a60,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 19,
+	.clkr = {
+		.enable_reg = 0x2a60,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi6_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_h_clk = {
+	.hwcg_reg = 0x2a80,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 15,
+	.clkr = {
+		.enable_reg = 0x2a80,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "gsbi7_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_gp[] = {
+	{ 12500000, P_PXO,  2, 0, 0 },
+	{ 25000000, P_PXO,  1, 0, 0 },
+	{ 64000000, P_PLL8, 2, 1, 3 },
+	{ 76800000, P_PLL8, 1, 1, 5 },
+	{ 96000000, P_PLL8, 4, 0, 0 },
+	{ 128000000, P_PLL8, 3, 0, 0 },
+	{ 192000000, P_PLL8, 2, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg gp0_src = {
+	.ns_reg = 0x2d24,
+	.md_reg = 0x2d00,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.clkr = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp0_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp0_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 7,
+	.clkr = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp0_clk",
+			.parent_names = (const char *[]){ "gp0_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp1_src = {
+	.ns_reg = 0x2d44,
+	.md_reg = 0x2d40,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.clkr = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp1_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp1_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 6,
+	.clkr = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp1_clk",
+			.parent_names = (const char *[]){ "gp1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp2_src = {
+	.ns_reg = 0x2d64,
+	.md_reg = 0x2d60,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.clkr = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp2_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 5,
+	.clkr = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "gp2_clk",
+			.parent_names = (const char *[]){ "gp2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pmem_clk = {
+	.hwcg_reg = 0x25a0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 20,
+	.clkr = {
+		.enable_reg = 0x25a0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pmem_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg prng_src = {
+	.ns_reg = 0x2e80,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.clkr = {
+		.hw.init = &(struct clk_init_data){
+			.name = "prng_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch prng_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 10,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(10),
+		.hw.init = &(struct clk_init_data){
+			.name = "prng_clk",
+			.parent_names = (const char *[]){ "prng_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_sdc[] = {
+	{    200000, P_PXO,   2, 2, 125 },
+	{    400000, P_PLL8,  4, 1, 240 },
+	{  16000000, P_PLL8,  4, 1,   6 },
+	{  17070000, P_PLL8,  1, 2,  45 },
+	{  20210000, P_PLL8,  1, 1,  19 },
+	{  24000000, P_PLL8,  4, 1,   4 },
+	{  48000000, P_PLL8,  4, 1,   2 },
+	{  64000000, P_PLL8,  3, 1,   2 },
+	{  96000000, P_PLL8,  4, 0,   0 },
+	{ 192000000, P_PLL8,  2, 0,   0 },
+	{ }
+};
+
+static struct clk_rcg sdc1_src = {
+	.ns_reg = 0x282c,
+	.md_reg = 0x2828,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.clkr = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc1_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc1_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 6,
+	.clkr = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc1_clk",
+			.parent_names = (const char *[]){ "sdc1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc3_src = {
+	.ns_reg = 0x286c,
+	.md_reg = 0x2868,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.clkr = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc3_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc3_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 4,
+	.clkr = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc3_clk",
+			.parent_names = (const char *[]){ "sdc3_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sdc1_h_clk = {
+	.hwcg_reg = 0x2820,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 11,
+	.clkr = {
+		.enable_reg = 0x2820,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc3_h_clk = {
+	.hwcg_reg = 0x2860,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 9,
+	.clkr = {
+		.enable_reg = 0x2860,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sdc3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_tsif_ref[] = {
+	{ 105000, P_PXO,  1, 1, 256 },
+	{ }
+};
+
+static struct clk_rcg tsif_ref_src = {
+	.ns_reg = 0x2710,
+	.md_reg = 0x270c,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_tsif_ref,
+	.clkr = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "tsif_ref_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch tsif_ref_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 5,
+	.clkr = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "tsif_ref_clk",
+			.parent_names = (const char *[]){ "tsif_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch tsif_h_clk = {
+	.hwcg_reg = 0x2700,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd4,
+	.halt_bit = 7,
+	.clkr = {
+		.enable_reg = 0x2700,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "tsif_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch dma_bam_h_clk = {
+	.hwcg_reg = 0x25c0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x25c0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "dma_bam_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "adm0_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_pbus_clk = {
+	.hwcg_reg = 0x2208,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 11,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(3),
+		.hw.init = &(struct clk_init_data){
+			.name = "adm0_pbus_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb0_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 22,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(8),
+		.hw.init = &(struct clk_init_data){
+			.name = "pmic_arb0_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb1_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 21,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "pmic_arb1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_ssbi2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 23,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(7),
+		.hw.init = &(struct clk_init_data){
+			.name = "pmic_ssbi2_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch rpm_msg_ram_h_clk = {
+	.hwcg_reg = 0x27e0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(6),
+		.hw.init = &(struct clk_init_data){
+			.name = "rpm_msg_ram_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_pcie_ref[] = {
+	{ 100000000, P_PLL3,  12, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg pcie_ref_src = {
+	.ns_reg = 0x3860,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll3_map,
+	},
+	.freq_tbl = clk_tbl_pcie_ref,
+	.clkr = {
+		.enable_reg = 0x3860,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_ref_src",
+			.parent_names = gcc_pxo_pll3,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch pcie_ref_src_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 30,
+	.clkr = {
+		.enable_reg = 0x3860,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_ref_src_clk",
+			.parent_names = (const char *[]){ "pcie_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pcie_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 13,
+	.clkr = {
+		.enable_reg = 0x22c0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_aux_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 31,
+	.clkr = {
+		.enable_reg = 0x22c8,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_aux_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 8,
+	.clkr = {
+		.enable_reg = 0x22cc,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_phy_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 29,
+	.clkr = {
+		.enable_reg = 0x22d0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg pcie1_ref_src = {
+	.ns_reg = 0x3aa0,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll3_map,
+	},
+	.freq_tbl = clk_tbl_pcie_ref,
+	.clkr = {
+		.enable_reg = 0x3aa0,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_ref_src",
+			.parent_names = gcc_pxo_pll3,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch pcie1_ref_src_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 27,
+	.clkr = {
+		.enable_reg = 0x3aa0,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_ref_src_clk",
+			.parent_names = (const char *[]){ "pcie1_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pcie1_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 10,
+	.clkr = {
+		.enable_reg = 0x3a80,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie1_aux_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 28,
+	.clkr = {
+		.enable_reg = 0x3a88,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_aux_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie1_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 9,
+	.clkr = {
+		.enable_reg = 0x3a8c,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie1_phy_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 26,
+	.clkr = {
+		.enable_reg = 0x3a90,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie1_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg pcie2_ref_src = {
+	.ns_reg = 0x3ae0,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll3_map,
+	},
+	.freq_tbl = clk_tbl_pcie_ref,
+	.clkr = {
+		.enable_reg = 0x3ae0,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_ref_src",
+			.parent_names = gcc_pxo_pll3,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch pcie2_ref_src_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 24,
+	.clkr = {
+		.enable_reg = 0x3ae0,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_ref_src_clk",
+			.parent_names = (const char *[]){ "pcie2_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pcie2_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 9,
+	.clkr = {
+		.enable_reg = 0x3ac0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie2_aux_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 25,
+	.clkr = {
+		.enable_reg = 0x3ac8,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_aux_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie2_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 10,
+	.clkr = {
+		.enable_reg = 0x3acc,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie2_phy_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 23,
+	.clkr = {
+		.enable_reg = 0x3ad0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie2_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_sata_ref[] = {
+	{ 100000000, P_PLL3,  12, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg sata_ref_src = {
+	.ns_reg = 0x2c08,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll3_sata_map,
+	},
+	.freq_tbl = clk_tbl_sata_ref,
+	.clkr = {
+		.enable_reg = 0x2c08,
+		.enable_mask = BIT(7),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_ref_src",
+			.parent_names = gcc_pxo_pll3,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch sata_rxoob_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 20,
+	.clkr = {
+		.enable_reg = 0x2c0c,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_rxoob_clk",
+			.parent_names = (const char *[]){ "sata_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sata_pmalive_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 19,
+	.clkr = {
+		.enable_reg = 0x2c10,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_pmalive_clk",
+			.parent_names = (const char *[]){ "sata_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sata_phy_ref_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 18,
+	.clkr = {
+		.enable_reg = 0x2c14,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_phy_ref_clk",
+			.parent_names = (const char *[]){ "pxo" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static struct clk_branch sata_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x2c20,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sata_h_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 21,
+	.clkr = {
+		.enable_reg = 0x2c00,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sfab_sata_s_h_clk = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 14,
+	.clkr = {
+		.enable_reg = 0x2480,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sfab_sata_s_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sata_phy_cfg_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 14,
+	.clkr = {
+		.enable_reg = 0x2c40,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_phy_cfg_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_usb30_master[] = {
+	{ 125000000, P_PLL0,  1, 5, 32 },
+	{ }
+};
+
+static struct clk_rcg usb30_master_clk_src = {
+	.ns_reg = 0x3b2c,
+	.md_reg = 0x3b28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll0,
+	},
+	.freq_tbl = clk_tbl_usb30_master,
+	.clkr = {
+		.enable_reg = 0x3b2c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_master_ref_src",
+			.parent_names = gcc_pxo_pll8_pll0_map,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch usb30_0_branch_clk = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 22,
+	.clkr = {
+		.enable_reg = 0x3b24,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_0_branch_clk",
+			.parent_names = (const char *[]){ "usb30_master_ref_src", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb30_1_branch_clk = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 17,
+	.clkr = {
+		.enable_reg = 0x3b34,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_1_branch_clk",
+			.parent_names = (const char *[]){ "usb30_master_ref_src", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_usb30_utmi[] = {
+	{ 60000000, P_PLL8,  1, 5, 32 },
+	{ }
+};
+
+static struct clk_rcg usb30_utmi_clk = {
+	.ns_reg = 0x3b44,
+	.md_reg = 0x3b40,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll0,
+	},
+	.freq_tbl = clk_tbl_usb30_utmi,
+	.clkr = {
+		.enable_reg = 0x3b44,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_utmi_clk",
+			.parent_names = gcc_pxo_pll8_pll0_map,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch usb30_0_utmi_clk_ctl = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 21,
+	.clkr = {
+		.enable_reg = 0x3b48,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_0_utmi_clk_ctl",
+			.parent_names = (const char *[]){ "usb30_utmi_clk", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb30_1_utmi_clk_ctl = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 15,
+	.clkr = {
+		.enable_reg = 0x3b4c,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb30_1_utmi_clk_ctl",
+			.parent_names = (const char *[]){ "usb30_utmi_clk", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_usb[] = {
+	{ 60000000, P_PLL8,  1, 5, 32 },
+	{ }
+};
+
+static struct clk_rcg usb_hs1_xcvr_clk_src = {
+	.ns_reg = 0x290C,
+	.md_reg = 0x2908,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll0,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.clkr = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_src",
+			.parent_names = gcc_pxo_pll8_pll0_map,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch usb_hs1_xcvr_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 17,
+	.clkr = {
+		.enable_reg = 0x290c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_hs1_xcvr_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_hs1_h_clk = {
+	.hwcg_reg = 0x2900,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 1,
+	.clkr = {
+		.enable_reg = 0x2900,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg usb_fs1_xcvr_clk_src = {
+	.ns_reg = 0x2968,
+	.md_reg = 0x2964,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll0,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.clkr = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_src",
+			.parent_names = gcc_pxo_pll8_pll0_map,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_xcvr_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 17,
+	.clkr = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_fs1_xcvr_src", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_sys_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 18,
+	.clkr = {
+		.enable_reg = 0x296c,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_fs1_sys_clk",
+			.parent_names = (const char *[]){ "usb_fs1_xcvr_src", },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 19,
+	.clkr = {
+		.enable_reg = 0x2960,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_fs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_regmap *gcc_ipq806x_clks[] = {
+	[PLL3] = &pll3.clkr,
+	[PLL8] = &pll8.clkr,
+	[PLL8_VOTE] = &pll8_vote,
+	[PLL14] = &pll14.clkr,
+	[PLL14_VOTE] = &pll14_vote,
+	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+	[GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr,
+	[GSBI4_UART_SRC] = &gsbi4_uart_src.clkr,
+	[GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr,
+	[GSBI5_UART_SRC] = &gsbi5_uart_src.clkr,
+	[GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr,
+	[GSBI6_UART_SRC] = &gsbi6_uart_src.clkr,
+	[GSBI6_UART_CLK] = &gsbi6_uart_clk.clkr,
+	[GSBI7_UART_SRC] = &gsbi7_uart_src.clkr,
+	[GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr,
+	[GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr,
+	[GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr,
+	[GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr,
+	[GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr,
+	[GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr,
+	[GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr,
+	[GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr,
+	[GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr,
+	[GSBI6_QUP_SRC] = &gsbi6_qup_src.clkr,
+	[GSBI6_QUP_CLK] = &gsbi6_qup_clk.clkr,
+	[GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr,
+	[GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr,
+	[GP0_SRC] = &gp0_src.clkr,
+	[GP0_CLK] = &gp0_clk.clkr,
+	[GP1_SRC] = &gp1_src.clkr,
+	[GP1_CLK] = &gp1_clk.clkr,
+	[GP2_SRC] = &gp2_src.clkr,
+	[GP2_CLK] = &gp2_clk.clkr,
+	[PMEM_A_CLK] = &pmem_clk.clkr,
+	[PRNG_SRC] = &prng_src.clkr,
+	[PRNG_CLK] = &prng_clk.clkr,
+	[SDC1_SRC] = &sdc1_src.clkr,
+	[SDC1_CLK] = &sdc1_clk.clkr,
+	[SDC3_SRC] = &sdc3_src.clkr,
+	[SDC3_CLK] = &sdc3_clk.clkr,
+	[TSIF_REF_SRC] = &tsif_ref_src.clkr,
+	[TSIF_REF_CLK] = &tsif_ref_clk.clkr,
+	[DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr,
+	[GSBI1_H_CLK] = &gsbi1_h_clk.clkr,
+	[GSBI2_H_CLK] = &gsbi2_h_clk.clkr,
+	[GSBI4_H_CLK] = &gsbi4_h_clk.clkr,
+	[GSBI5_H_CLK] = &gsbi5_h_clk.clkr,
+	[GSBI6_H_CLK] = &gsbi6_h_clk.clkr,
+	[GSBI7_H_CLK] = &gsbi7_h_clk.clkr,
+	[TSIF_H_CLK] = &tsif_h_clk.clkr,
+	[SDC1_H_CLK] = &sdc1_h_clk.clkr,
+	[SDC3_H_CLK] = &sdc3_h_clk.clkr,
+	[ADM0_CLK] = &adm0_clk.clkr,
+	[ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr,
+	[PCIE_A_CLK] = &pcie_a_clk.clkr,
+	[PCIE_AUX_CLK] = &pcie_aux_clk.clkr,
+	[PCIE_H_CLK] = &pcie_h_clk.clkr,
+	[PCIE_PHY_CLK] = &pcie_phy_clk.clkr,
+	[SFAB_SATA_S_H_CLK] = &sfab_sata_s_h_clk.clkr,
+	[PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr,
+	[PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr,
+	[PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr,
+	[RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr,
+	[SATA_H_CLK] = &sata_h_clk.clkr,
+	[SATA_CLK_SRC] = &sata_ref_src.clkr,
+	[SATA_RXOOB_CLK] = &sata_rxoob_clk.clkr,
+	[SATA_PMALIVE_CLK] = &sata_pmalive_clk.clkr,
+	[SATA_PHY_REF_CLK] = &sata_phy_ref_clk.clkr,
+	[SATA_A_CLK] = &sata_a_clk.clkr,
+	[SATA_PHY_CFG_CLK] = &sata_phy_cfg_clk.clkr,
+	[PCIE_ALT_REF_SRC] = &pcie_ref_src.clkr,
+	[PCIE_ALT_REF_CLK] = &pcie_ref_src_clk.clkr,
+	[PCIE_1_A_CLK] = &pcie1_a_clk.clkr,
+	[PCIE_1_AUX_CLK] = &pcie1_aux_clk.clkr,
+	[PCIE_1_H_CLK] = &pcie1_h_clk.clkr,
+	[PCIE_1_PHY_CLK] = &pcie1_phy_clk.clkr,
+	[PCIE_1_ALT_REF_SRC] = &pcie1_ref_src.clkr,
+	[PCIE_1_ALT_REF_CLK] = &pcie1_ref_src_clk.clkr,
+	[PCIE_2_A_CLK] = &pcie2_a_clk.clkr,
+	[PCIE_2_AUX_CLK] = &pcie2_aux_clk.clkr,
+	[PCIE_2_H_CLK] = &pcie2_h_clk.clkr,
+	[PCIE_2_PHY_CLK] = &pcie2_phy_clk.clkr,
+	[PCIE_2_ALT_REF_SRC] = &pcie2_ref_src.clkr,
+	[PCIE_2_ALT_REF_CLK] = &pcie2_ref_src_clk.clkr,
+	[USB30_MASTER_SRC] = &usb30_master_clk_src.clkr,
+	[USB30_0_MASTER_CLK] = &usb30_0_branch_clk.clkr,
+	[USB30_1_MASTER_CLK] = &usb30_1_branch_clk.clkr,
+	[USB30_UTMI_SRC] = &usb30_utmi_clk.clkr,
+	[USB30_0_UTMI_CLK] = &usb30_0_utmi_clk_ctl.clkr,
+	[USB30_1_UTMI_CLK] = &usb30_1_utmi_clk_ctl.clkr,
+	[USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr,
+	[USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_clk_src.clkr,
+	[USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr,
+	[USB_FS1_H_CLK] = &usb_fs1_h_clk.clkr,
+	[USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr,
+	[USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr,
+	[USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_ipq806x_resets[] = {
+	[QDSS_STM_RESET] = { 0x2060, 6 },
+	[AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+	[AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+	[AFAB_SMPSS_M0_RESET] = { 0x20b8, 0 },
+	[AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 },
+	[AFAB_EBI1_CH1_RESET] = { 0x20c4, 7 },
+	[SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+	[SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+	[SFAB_ADM0_M2_RESET] = { 0x21e8, 7 },
+	[ADM0_C2_RESET] = { 0x220c, 4 },
+	[ADM0_C1_RESET] = { 0x220c, 3 },
+	[ADM0_C0_RESET] = { 0x220c, 2 },
+	[ADM0_PBUS_RESET] = { 0x220c, 1 },
+	[ADM0_RESET] = { 0x220c, 0 },
+	[QDSS_CLKS_SW_RESET] = { 0x2260, 5 },
+	[QDSS_POR_RESET] = { 0x2260, 4 },
+	[QDSS_TSCTR_RESET] = { 0x2260, 3 },
+	[QDSS_HRESET_RESET] = { 0x2260, 2 },
+	[QDSS_AXI_RESET] = { 0x2260, 1 },
+	[QDSS_DBG_RESET] = { 0x2260, 0 },
+	[SFAB_PCIE_M_RESET] = { 0x22d8, 1 },
+	[SFAB_PCIE_S_RESET] = { 0x22d8, 0 },
+	[PCIE_EXT_RESET] = { 0x22dc, 6 },
+	[PCIE_PHY_RESET] = { 0x22dc, 5 },
+	[PCIE_PCI_RESET] = { 0x22dc, 4 },
+	[PCIE_POR_RESET] = { 0x22dc, 3 },
+	[PCIE_HCLK_RESET] = { 0x22dc, 2 },
+	[PCIE_ACLK_RESET] = { 0x22dc, 0 },
+	[SFAB_LPASS_RESET] = { 0x23a0, 7 },
+	[SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+	[AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+	[AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+	[SFAB_SATA_S_RESET] = { 0x2480, 7 },
+	[SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+	[DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+	[DFAB_SWAY0_RESET] = { 0x2540, 7 },
+	[DFAB_SWAY1_RESET] = { 0x2544, 7 },
+	[DFAB_ARB0_RESET] = { 0x2560, 7 },
+	[DFAB_ARB1_RESET] = { 0x2564, 7 },
+	[PPSS_PROC_RESET] = { 0x2594, 1 },
+	[PPSS_RESET] = { 0x2594, 0 },
+	[DMA_BAM_RESET] = { 0x25c0, 7 },
+	[SPS_TIC_H_RESET] = { 0x2600, 7 },
+	[SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+	[SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+	[TSIF_H_RESET] = { 0x2700, 7 },
+	[CE1_H_RESET] = { 0x2720, 7 },
+	[CE1_CORE_RESET] = { 0x2724, 7 },
+	[CE1_SLEEP_RESET] = { 0x2728, 7 },
+	[CE2_H_RESET] = { 0x2740, 7 },
+	[CE2_CORE_RESET] = { 0x2744, 7 },
+	[SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+	[SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+	[RPM_PROC_RESET] = { 0x27c0, 7 },
+	[PMIC_SSBI2_RESET] = { 0x280c, 12 },
+	[SDC1_RESET] = { 0x2830, 0 },
+	[SDC2_RESET] = { 0x2850, 0 },
+	[SDC3_RESET] = { 0x2870, 0 },
+	[SDC4_RESET] = { 0x2890, 0 },
+	[USB_HS1_RESET] = { 0x2910, 0 },
+	[USB_HSIC_RESET] = { 0x2934, 0 },
+	[USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+	[USB_FS1_RESET] = { 0x2974, 0 },
+	[GSBI1_RESET] = { 0x29dc, 0 },
+	[GSBI2_RESET] = { 0x29fc, 0 },
+	[GSBI3_RESET] = { 0x2a1c, 0 },
+	[GSBI4_RESET] = { 0x2a3c, 0 },
+	[GSBI5_RESET] = { 0x2a5c, 0 },
+	[GSBI6_RESET] = { 0x2a7c, 0 },
+	[GSBI7_RESET] = { 0x2a9c, 0 },
+	[SPDM_RESET] = { 0x2b6c, 0 },
+	[SEC_CTRL_RESET] = { 0x2b80, 7 },
+	[TLMM_H_RESET] = { 0x2ba0, 7 },
+	[SFAB_SATA_M_RESET] = { 0x2c18, 0 },
+	[SATA_RESET] = { 0x2c1c, 0 },
+	[TSSC_RESET] = { 0x2ca0, 7 },
+	[PDM_RESET] = { 0x2cc0, 12 },
+	[MPM_H_RESET] = { 0x2da0, 7 },
+	[MPM_RESET] = { 0x2da4, 0 },
+	[SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+	[PRNG_RESET] = { 0x2e80, 12 },
+	[SFAB_CE3_M_RESET] = { 0x36c8, 1 },
+	[SFAB_CE3_S_RESET] = { 0x36c8, 0 },
+	[CE3_SLEEP_RESET] = { 0x36d0, 7 },
+	[PCIE_1_M_RESET] = { 0x3a98, 1 },
+	[PCIE_1_S_RESET] = { 0x3a98, 0 },
+	[PCIE_1_EXT_RESET] = { 0x3a9c, 6 },
+	[PCIE_1_PHY_RESET] = { 0x3a9c, 5 },
+	[PCIE_1_PCI_RESET] = { 0x3a9c, 4 },
+	[PCIE_1_POR_RESET] = { 0x3a9c, 3 },
+	[PCIE_1_HCLK_RESET] = { 0x3a9c, 2 },
+	[PCIE_1_ACLK_RESET] = { 0x3a9c, 0 },
+	[PCIE_2_M_RESET] = { 0x3ad8, 1 },
+	[PCIE_2_S_RESET] = { 0x3ad8, 0 },
+	[PCIE_2_EXT_RESET] = { 0x3adc, 6 },
+	[PCIE_2_PHY_RESET] = { 0x3adc, 5 },
+	[PCIE_2_PCI_RESET] = { 0x3adc, 4 },
+	[PCIE_2_POR_RESET] = { 0x3adc, 3 },
+	[PCIE_2_HCLK_RESET] = { 0x3adc, 2 },
+	[PCIE_2_ACLK_RESET] = { 0x3adc, 0 },
+	[SFAB_USB30_S_RESET] = { 0x3b54, 1 },
+	[SFAB_USB30_M_RESET] = { 0x3b54, 0 },
+	[USB30_0_PORT2_HS_PHY_RESET] = { 0x3b50, 5 },
+	[USB30_0_MASTER_RESET] = { 0x3b50, 4 },
+	[USB30_0_SLEEP_RESET] = { 0x3b50, 3 },
+	[USB30_0_UTMI_PHY_RESET] = { 0x3b50, 2 },
+	[USB30_0_POWERON_RESET] = { 0x3b50, 1 },
+	[USB30_0_PHY_RESET] = { 0x3b50, 0 },
+	[USB30_1_MASTER_RESET] = { 0x3b58, 4 },
+	[USB30_1_SLEEP_RESET] = { 0x3b58, 3 },
+	[USB30_1_UTMI_PHY_RESET] = { 0x3b58, 2 },
+	[USB30_1_POWERON_RESET] = { 0x3b58, 1 },
+	[USB30_1_PHY_RESET] = { 0x3b58, 0 },
+	[NSSFB0_RESET] = { 0x3b60, 6 },
+	[NSSFB1_RESET] = { 0x3b60, 7 },
+};
+
+static const struct regmap_config gcc_ipq806x_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x3e40,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc gcc_ipq806x_desc = {
+	.config = &gcc_ipq806x_regmap_config,
+	.clks = gcc_ipq806x_clks,
+	.num_clks = ARRAY_SIZE(gcc_ipq806x_clks),
+	.resets = gcc_ipq806x_resets,
+	.num_resets = ARRAY_SIZE(gcc_ipq806x_resets),
+};
+
+static const struct of_device_id gcc_ipq806x_match_table[] = {
+	{ .compatible = "qcom,gcc-ipq8064" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table);
+
+static int gcc_ipq806x_probe(struct platform_device *pdev)
+{
+	struct clk *clk;
+	struct device *dev = &pdev->dev;
+
+	/* Temporary until RPM clocks supported */
+	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
+}
+
+static int gcc_ipq806x_remove(struct platform_device *pdev)
+{
+	qcom_cc_remove(pdev);
+	return 0;
+}
+
+static struct platform_driver gcc_ipq806x_driver = {
+	.probe		= gcc_ipq806x_probe,
+	.remove		= gcc_ipq806x_remove,
+	.driver		= {
+		.name	= "gcc-ipq806x",
+		.owner	= THIS_MODULE,
+		.of_match_table = gcc_ipq806x_match_table,
+	},
+};
+
+static int __init gcc_ipq806x_init(void)
+{
+	return platform_driver_register(&gcc_ipq806x_driver);
+}
+core_initcall(gcc_ipq806x_init);
+
+static void __exit gcc_ipq806x_exit(void)
+{
+	platform_driver_unregister(&gcc_ipq806x_driver);
+}
+module_exit(gcc_ipq806x_exit);
+
+MODULE_DESCRIPTION("QCOM GCC IPQ806x Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-ipq806x");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/gcc-msm8960.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-msm8960.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/gcc-msm8960.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/gcc-msm8960.c	2014-09-28 17:29:07.000000000 -0400
@@ -104,6 +104,7 @@ static struct clk_regmap pll14_vote = {
 
 #define P_PXO	0
 #define P_PLL8	1
+#define P_PLL3	2
 #define P_CXO	2
 
 static const u8 gcc_pxo_pll8_map[] = {
@@ -128,6 +129,18 @@ static const char *gcc_pxo_pll8_cxo[] =
 	"cxo",
 };
 
+static const u8 gcc_pxo_pll8_pll3_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+	[P_PLL3]	= 6,
+};
+
+static const char *gcc_pxo_pll8_pll3[] = {
+	"pxo",
+	"pll8_vote",
+	"pll3",
+};
+
 static struct freq_tbl clk_tbl_gsbi_uart[] = {
 	{  1843200, P_PLL8, 2,  6, 625 },
 	{  3686400, P_PLL8, 2, 12, 625 },
@@ -1928,6 +1941,104 @@ static struct clk_branch usb_hs1_xcvr_cl
 	},
 };
 
+static struct clk_rcg usb_hs3_xcvr_src = {
+	.ns_reg = 0x370c,
+	.md_reg = 0x3708,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.clkr = {
+		.enable_reg = 0x370c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs3_xcvr_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch usb_hs3_xcvr_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 30,
+	.clkr = {
+		.enable_reg = 0x370c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs3_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_hs3_xcvr_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg usb_hs4_xcvr_src = {
+	.ns_reg = 0x372c,
+	.md_reg = 0x3728,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.clkr = {
+		.enable_reg = 0x372c,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs4_xcvr_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch usb_hs4_xcvr_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 2,
+	.clkr = {
+		.enable_reg = 0x372c,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs4_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_hs4_xcvr_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
 static struct clk_rcg usb_hsic_xcvr_fs_src = {
 	.ns_reg = 0x2928,
 	.md_reg = 0x2924,
@@ -2456,6 +2567,34 @@ static struct clk_branch usb_hs1_h_clk =
 	},
 };
 
+static struct clk_branch usb_hs3_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 31,
+	.clkr = {
+		.enable_reg = 0x3700,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_hs4_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 7,
+	.clkr = {
+		.enable_reg = 0x3720,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "usb_hs4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
 static struct clk_branch usb_hsic_h_clk = {
 	.halt_reg = 0x2fcc,
 	.halt_bit = 28,
@@ -2582,6 +2721,244 @@ static struct clk_branch adm0_pbus_clk =
 	},
 };
 
+static struct freq_tbl clk_tbl_ce3[] = {
+	{ 48000000, P_PLL8, 8 },
+	{ 100000000, P_PLL3, 12 },
+	{ 120000000, P_PLL3, 10 },
+	{ }
+};
+
+static struct clk_rcg ce3_src = {
+	.ns_reg = 0x36c0,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll3_map,
+	},
+	.freq_tbl = clk_tbl_ce3,
+	.clkr = {
+		.enable_reg = 0x2c08,
+		.enable_mask = BIT(7),
+		.hw.init = &(struct clk_init_data){
+			.name = "ce3_src",
+			.parent_names = gcc_pxo_pll8_pll3,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch ce3_core_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 5,
+	.clkr = {
+		.enable_reg = 0x36c4,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "ce3_core_clk",
+			.parent_names = (const char *[]){ "ce3_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch ce3_h_clk = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 16,
+	.clkr = {
+		.enable_reg = 0x36c4,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "ce3_h_clk",
+			.parent_names = (const char *[]){ "ce3_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_sata_ref[] = {
+	{ 48000000, P_PLL8, 8, 0, 0 },
+	{ 100000000, P_PLL3, 12, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg sata_clk_src = {
+	.ns_reg = 0x2c08,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_pll3_map,
+	},
+	.freq_tbl = clk_tbl_sata_ref,
+	.clkr = {
+		.enable_reg = 0x2c08,
+		.enable_mask = BIT(7),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_clk_src",
+			.parent_names = gcc_pxo_pll8_pll3,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch sata_rxoob_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 26,
+	.clkr = {
+		.enable_reg = 0x2c0c,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_rxoob_clk",
+			.parent_names = (const char *[]){ "sata_clk_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sata_pmalive_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 25,
+	.clkr = {
+		.enable_reg = 0x2c10,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_pmalive_clk",
+			.parent_names = (const char *[]){ "sata_clk_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sata_phy_ref_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 24,
+	.clkr = {
+		.enable_reg = 0x2c14,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_phy_ref_clk",
+			.parent_names = (const char *[]){ "pxo" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static struct clk_branch sata_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x2c20,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sata_h_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 27,
+	.clkr = {
+		.enable_reg = 0x2c00,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sfab_sata_s_h_clk = {
+	.halt_reg = 0x2fc4,
+	.halt_bit = 14,
+	.clkr = {
+		.enable_reg = 0x2480,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sfab_sata_s_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sata_phy_cfg_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 12,
+	.clkr = {
+		.enable_reg = 0x2c40,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "sata_phy_cfg_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_phy_ref_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 29,
+	.clkr = {
+		.enable_reg = 0x22d0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_phy_ref_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 8,
+	.clkr = {
+		.enable_reg = 0x22cc,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pcie_a_clk = {
+	.halt_reg = 0x2fc0,
+	.halt_bit = 13,
+	.clkr = {
+		.enable_reg = 0x22c0,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcie_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
 static struct clk_branch pmic_arb0_h_clk = {
 	.halt_reg = 0x2fd8,
 	.halt_check = BRANCH_HALT_VOTED,
@@ -2869,13 +3246,205 @@ static const struct qcom_reset_map gcc_m
 };
 
 static struct clk_regmap *gcc_apq8064_clks[] = {
+	[PLL3] = &pll3.clkr,
 	[PLL8] = &pll8.clkr,
 	[PLL8_VOTE] = &pll8_vote,
+	[PLL14] = &pll14.clkr,
+	[PLL14_VOTE] = &pll14_vote,
+	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+	[GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr,
+	[GSBI3_UART_SRC] = &gsbi3_uart_src.clkr,
+	[GSBI3_UART_CLK] = &gsbi3_uart_clk.clkr,
+	[GSBI4_UART_SRC] = &gsbi4_uart_src.clkr,
+	[GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr,
+	[GSBI5_UART_SRC] = &gsbi5_uart_src.clkr,
+	[GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr,
+	[GSBI6_UART_SRC] = &gsbi6_uart_src.clkr,
+	[GSBI6_UART_CLK] = &gsbi6_uart_clk.clkr,
 	[GSBI7_UART_SRC] = &gsbi7_uart_src.clkr,
 	[GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr,
+	[GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr,
+	[GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr,
+	[GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr,
+	[GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr,
+	[GSBI3_QUP_SRC] = &gsbi3_qup_src.clkr,
+	[GSBI3_QUP_CLK] = &gsbi3_qup_clk.clkr,
+	[GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr,
+	[GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr,
+	[GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr,
+	[GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr,
+	[GSBI6_QUP_SRC] = &gsbi6_qup_src.clkr,
+	[GSBI6_QUP_CLK] = &gsbi6_qup_clk.clkr,
 	[GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr,
 	[GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr,
+	[GP0_SRC] = &gp0_src.clkr,
+	[GP0_CLK] = &gp0_clk.clkr,
+	[GP1_SRC] = &gp1_src.clkr,
+	[GP1_CLK] = &gp1_clk.clkr,
+	[GP2_SRC] = &gp2_src.clkr,
+	[GP2_CLK] = &gp2_clk.clkr,
+	[PMEM_A_CLK] = &pmem_clk.clkr,
+	[PRNG_SRC] = &prng_src.clkr,
+	[PRNG_CLK] = &prng_clk.clkr,
+	[SDC1_SRC] = &sdc1_src.clkr,
+	[SDC1_CLK] = &sdc1_clk.clkr,
+	[SDC2_SRC] = &sdc2_src.clkr,
+	[SDC2_CLK] = &sdc2_clk.clkr,
+	[SDC3_SRC] = &sdc3_src.clkr,
+	[SDC3_CLK] = &sdc3_clk.clkr,
+	[SDC4_SRC] = &sdc4_src.clkr,
+	[SDC4_CLK] = &sdc4_clk.clkr,
+	[TSIF_REF_SRC] = &tsif_ref_src.clkr,
+	[TSIF_REF_CLK] = &tsif_ref_clk.clkr,
+	[USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_src.clkr,
+	[USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr,
+	[USB_HS3_XCVR_SRC] = &usb_hs3_xcvr_src.clkr,
+	[USB_HS3_XCVR_CLK] = &usb_hs3_xcvr_clk.clkr,
+	[USB_HS4_XCVR_SRC] = &usb_hs4_xcvr_src.clkr,
+	[USB_HS4_XCVR_CLK] = &usb_hs4_xcvr_clk.clkr,
+	[USB_HSIC_XCVR_FS_SRC] = &usb_hsic_xcvr_fs_src.clkr,
+	[USB_HSIC_XCVR_FS_CLK] = &usb_hsic_xcvr_fs_clk.clkr,
+	[USB_HSIC_SYSTEM_CLK] = &usb_hsic_system_clk.clkr,
+	[USB_HSIC_HSIC_CLK] = &usb_hsic_hsic_clk.clkr,
+	[USB_HSIC_HSIO_CAL_CLK] = &usb_hsic_hsio_cal_clk.clkr,
+	[USB_FS1_XCVR_FS_SRC] = &usb_fs1_xcvr_fs_src.clkr,
+	[USB_FS1_XCVR_FS_CLK] = &usb_fs1_xcvr_fs_clk.clkr,
+	[USB_FS1_SYSTEM_CLK] = &usb_fs1_system_clk.clkr,
+	[SATA_H_CLK] = &sata_h_clk.clkr,
+	[SATA_CLK_SRC] = &sata_clk_src.clkr,
+	[SATA_RXOOB_CLK] = &sata_rxoob_clk.clkr,
+	[SATA_PMALIVE_CLK] = &sata_pmalive_clk.clkr,
+	[SATA_PHY_REF_CLK] = &sata_phy_ref_clk.clkr,
+	[SATA_PHY_CFG_CLK] = &sata_phy_cfg_clk.clkr,
+	[SATA_A_CLK] = &sata_a_clk.clkr,
+	[SFAB_SATA_S_H_CLK] = &sfab_sata_s_h_clk.clkr,
+	[CE3_SRC] = &ce3_src.clkr,
+	[CE3_CORE_CLK] = &ce3_core_clk.clkr,
+	[CE3_H_CLK] = &ce3_h_clk.clkr,
+	[DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr,
+	[GSBI1_H_CLK] = &gsbi1_h_clk.clkr,
+	[GSBI2_H_CLK] = &gsbi2_h_clk.clkr,
+	[GSBI3_H_CLK] = &gsbi3_h_clk.clkr,
+	[GSBI4_H_CLK] = &gsbi4_h_clk.clkr,
+	[GSBI5_H_CLK] = &gsbi5_h_clk.clkr,
+	[GSBI6_H_CLK] = &gsbi6_h_clk.clkr,
 	[GSBI7_H_CLK] = &gsbi7_h_clk.clkr,
+	[TSIF_H_CLK] = &tsif_h_clk.clkr,
+	[USB_FS1_H_CLK] = &usb_fs1_h_clk.clkr,
+	[USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr,
+	[USB_HSIC_H_CLK] = &usb_hsic_h_clk.clkr,
+	[USB_HS3_H_CLK] = &usb_hs3_h_clk.clkr,
+	[USB_HS4_H_CLK] = &usb_hs4_h_clk.clkr,
+	[SDC1_H_CLK] = &sdc1_h_clk.clkr,
+	[SDC2_H_CLK] = &sdc2_h_clk.clkr,
+	[SDC3_H_CLK] = &sdc3_h_clk.clkr,
+	[SDC4_H_CLK] = &sdc4_h_clk.clkr,
+	[ADM0_CLK] = &adm0_clk.clkr,
+	[ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr,
+	[PCIE_A_CLK] = &pcie_a_clk.clkr,
+	[PCIE_PHY_REF_CLK] = &pcie_phy_ref_clk.clkr,
+	[PCIE_H_CLK] = &pcie_h_clk.clkr,
+	[PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr,
+	[PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr,
+	[PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr,
+	[RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_apq8064_resets[] = {
+	[QDSS_STM_RESET] = { 0x2060, 6 },
+	[AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+	[AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+	[AFAB_SMPSS_M0_RESET] = { 0x20b8 },
+	[AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 },
+	[AFAB_EBI1_CH1_RESET] = { 0x20c4, 7},
+	[SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+	[SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+	[SFAB_ADM0_M2_RESET] = { 0x21e8, 7 },
+	[ADM0_C2_RESET] = { 0x220c, 4},
+	[ADM0_C1_RESET] = { 0x220c, 3},
+	[ADM0_C0_RESET] = { 0x220c, 2},
+	[ADM0_PBUS_RESET] = { 0x220c, 1 },
+	[ADM0_RESET] = { 0x220c },
+	[QDSS_CLKS_SW_RESET] = { 0x2260, 5 },
+	[QDSS_POR_RESET] = { 0x2260, 4 },
+	[QDSS_TSCTR_RESET] = { 0x2260, 3 },
+	[QDSS_HRESET_RESET] = { 0x2260, 2 },
+	[QDSS_AXI_RESET] = { 0x2260, 1 },
+	[QDSS_DBG_RESET] = { 0x2260 },
+	[SFAB_PCIE_M_RESET] = { 0x22d8, 1 },
+	[SFAB_PCIE_S_RESET] = { 0x22d8 },
+	[PCIE_EXT_PCI_RESET] = { 0x22dc, 6 },
+	[PCIE_PHY_RESET] = { 0x22dc, 5 },
+	[PCIE_PCI_RESET] = { 0x22dc, 4 },
+	[PCIE_POR_RESET] = { 0x22dc, 3 },
+	[PCIE_HCLK_RESET] = { 0x22dc, 2 },
+	[PCIE_ACLK_RESET] = { 0x22dc },
+	[SFAB_USB3_M_RESET] = { 0x2360, 7 },
+	[SFAB_RIVA_M_RESET] = { 0x2380, 7 },
+	[SFAB_LPASS_RESET] = { 0x23a0, 7 },
+	[SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+	[AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+	[AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+	[SFAB_SATA_S_RESET] = { 0x2480, 7 },
+	[SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+	[DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+	[DFAB_SWAY0_RESET] = { 0x2540, 7 },
+	[DFAB_SWAY1_RESET] = { 0x2544, 7 },
+	[DFAB_ARB0_RESET] = { 0x2560, 7 },
+	[DFAB_ARB1_RESET] = { 0x2564, 7 },
+	[PPSS_PROC_RESET] = { 0x2594, 1 },
+	[PPSS_RESET] = { 0x2594},
+	[DMA_BAM_RESET] = { 0x25c0, 7 },
+	[SPS_TIC_H_RESET] = { 0x2600, 7 },
+	[SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+	[SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+	[TSIF_H_RESET] = { 0x2700, 7 },
+	[CE1_H_RESET] = { 0x2720, 7 },
+	[CE1_CORE_RESET] = { 0x2724, 7 },
+	[CE1_SLEEP_RESET] = { 0x2728, 7 },
+	[CE2_H_RESET] = { 0x2740, 7 },
+	[CE2_CORE_RESET] = { 0x2744, 7 },
+	[SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+	[SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+	[RPM_PROC_RESET] = { 0x27c0, 7 },
+	[PMIC_SSBI2_RESET] = { 0x280c, 12 },
+	[SDC1_RESET] = { 0x2830 },
+	[SDC2_RESET] = { 0x2850 },
+	[SDC3_RESET] = { 0x2870 },
+	[SDC4_RESET] = { 0x2890 },
+	[USB_HS1_RESET] = { 0x2910 },
+	[USB_HSIC_RESET] = { 0x2934 },
+	[USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+	[USB_FS1_RESET] = { 0x2974 },
+	[GSBI1_RESET] = { 0x29dc },
+	[GSBI2_RESET] = { 0x29fc },
+	[GSBI3_RESET] = { 0x2a1c },
+	[GSBI4_RESET] = { 0x2a3c },
+	[GSBI5_RESET] = { 0x2a5c },
+	[GSBI6_RESET] = { 0x2a7c },
+	[GSBI7_RESET] = { 0x2a9c },
+	[SPDM_RESET] = { 0x2b6c },
+	[TLMM_H_RESET] = { 0x2ba0, 7 },
+	[SATA_SFAB_M_RESET] = { 0x2c18 },
+	[SATA_RESET] = { 0x2c1c },
+	[GSS_SLP_RESET] = { 0x2c60, 7 },
+	[GSS_RESET] = { 0x2c64 },
+	[TSSC_RESET] = { 0x2ca0, 7 },
+	[PDM_RESET] = { 0x2cc0, 12 },
+	[MPM_H_RESET] = { 0x2da0, 7 },
+	[MPM_RESET] = { 0x2da4 },
+	[SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+	[PRNG_RESET] = { 0x2e80, 12 },
+	[RIVA_RESET] = { 0x35e0 },
+	[CE3_H_RESET] = { 0x36c4, 7 },
+	[SFAB_CE3_M_RESET] = { 0x36c8, 1 },
+	[SFAB_CE3_S_RESET] = { 0x36c8 },
+	[CE3_RESET] = { 0x36cc, 7 },
+	[CE3_SLEEP_RESET] = { 0x36d0, 7 },
+	[USB_HS3_RESET] = { 0x3710 },
+	[USB_HS4_RESET] = { 0x3730 },
 };
 
 static const struct regmap_config gcc_msm8960_regmap_config = {
@@ -2886,6 +3455,14 @@ static const struct regmap_config gcc_ms
 	.fast_io	= true,
 };
 
+static const struct regmap_config gcc_apq8064_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x3880,
+	.fast_io	= true,
+};
+
 static const struct qcom_cc_desc gcc_msm8960_desc = {
 	.config = &gcc_msm8960_regmap_config,
 	.clks = gcc_msm8960_clks,
@@ -2895,11 +3472,11 @@ static const struct qcom_cc_desc gcc_msm
 };
 
 static const struct qcom_cc_desc gcc_apq8064_desc = {
-	.config = &gcc_msm8960_regmap_config,
+	.config = &gcc_apq8064_regmap_config,
 	.clks = gcc_apq8064_clks,
 	.num_clks = ARRAY_SIZE(gcc_apq8064_clks),
-	.resets = gcc_msm8960_resets,
-	.num_resets = ARRAY_SIZE(gcc_msm8960_resets),
+	.resets = gcc_apq8064_resets,
+	.num_resets = ARRAY_SIZE(gcc_apq8064_resets),
 };
 
 static const struct of_device_id gcc_msm8960_match_table[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/Kconfig linux-libre-3.17-rc7-gnu/drivers/clk/qcom/Kconfig
--- linux-libre-3.16-gnu/drivers/clk/qcom/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,31 @@ config COMMON_CLK_QCOM
 	select REGMAP_MMIO
 	select RESET_CONTROLLER
 
+config APQ_GCC_8084
+	tristate "APQ8084 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on apq8084 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, SATA, PCIe, etc.
+
+config APQ_MMCC_8084
+	tristate "APQ8084 Multimedia Clock Controller"
+	select APQ_GCC_8084
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the multimedia clock controller on apq8084 devices.
+	  Say Y if you want to support multimedia devices such as display,
+	  graphics, video encode/decode, camera, etc.
+
+config IPQ_GCC_806X
+	tristate "IPQ806x Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on ipq806x devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, etc.
+
 config MSM_GCC_8660
 	tristate "MSM8660 Global Clock Controller"
 	depends on COMMON_CLK_QCOM
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/qcom/Makefile
--- linux-libre-3.16-gnu/drivers/clk/qcom/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,9 @@ clk-qcom-y += clk-rcg2.o
 clk-qcom-y += clk-branch.o
 clk-qcom-y += reset.o
 
+obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
+obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
+obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
 obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-apq8084.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-apq8084.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-apq8084.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-apq8084.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,3352 @@
+/*
+ * 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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,mmcc-apq8084.h>
+#include <dt-bindings/reset/qcom,mmcc-apq8084.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO		0
+#define P_MMPLL0	1
+#define P_EDPLINK	1
+#define P_MMPLL1	2
+#define P_HDMIPLL	2
+#define P_GPLL0		3
+#define P_EDPVCO	3
+#define P_MMPLL4	4
+#define P_DSI0PLL	4
+#define P_DSI0PLL_BYTE	4
+#define P_MMPLL2	4
+#define P_MMPLL3	4
+#define P_GPLL1		5
+#define P_DSI1PLL	5
+#define P_DSI1PLL_BYTE	5
+#define P_MMSLEEP	6
+
+static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+};
+
+static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+};
+
+static const u8 mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_HDMIPLL]	= 4,
+	[P_GPLL0]	= 5,
+	[P_DSI0PLL]	= 2,
+	[P_DSI1PLL]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"hdmipll",
+	"mmss_gpll0_vote",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+static const u8 mmcc_xo_mmpll0_1_2_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_MMPLL2]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+	"mmpll2",
+};
+
+static const u8 mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_MMPLL3]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+	"mmpll3",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_map[] = {
+	[P_XO]		= 0,
+	[P_EDPLINK]	= 4,
+	[P_HDMIPLL]	= 3,
+	[P_EDPVCO]	= 5,
+	[P_DSI0PLL]	= 1,
+	[P_DSI1PLL]	= 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp[] = {
+	"xo",
+	"edp_link_clk",
+	"hdmipll",
+	"edp_vco_div",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_EDPLINK]	= 4,
+	[P_HDMIPLL]	= 3,
+	[P_GPLL0]	= 5,
+	[P_DSI0PLL]	= 1,
+	[P_DSI1PLL]	= 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+	"xo",
+	"edp_link_clk",
+	"hdmipll",
+	"gpll0_vote",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
+	[P_XO]			= 0,
+	[P_EDPLINK]		= 4,
+	[P_HDMIPLL]		= 3,
+	[P_GPLL0]		= 5,
+	[P_DSI0PLL_BYTE]	= 1,
+	[P_DSI1PLL_BYTE]	= 2,
+};
+
+static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+	"xo",
+	"edp_link_clk",
+	"hdmipll",
+	"gpll0_vote",
+	"dsi0pllbyte",
+	"dsi1pllbyte",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_MMPLL4]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
+	"xo",
+	"mmpll0",
+	"mmpll1",
+	"mmpll4",
+	"gpll0",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_MMPLL4]	= 3,
+	[P_GPLL0]	= 5,
+	[P_GPLL1]	= 4,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
+	"xo",
+	"mmpll0",
+	"mmpll1",
+	"mmpll4",
+	"gpll1",
+	"gpll0",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_MMPLL4]	= 3,
+	[P_GPLL0]	= 5,
+	[P_GPLL1]	= 4,
+	[P_MMSLEEP]	= 6,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
+	"xo",
+	"mmpll0",
+	"mmpll1",
+	"mmpll4",
+	"gpll1",
+	"gpll0",
+	"sleep_clk_src",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll mmpll0 = {
+	.l_reg = 0x0004,
+	.m_reg = 0x0008,
+	.n_reg = 0x000c,
+	.config_reg = 0x0014,
+	.mode_reg = 0x0000,
+	.status_reg = 0x001c,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll0",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap mmpll0_vote = {
+	.enable_reg = 0x0100,
+	.enable_mask = BIT(0),
+	.hw.init = &(struct clk_init_data){
+		.name = "mmpll0_vote",
+		.parent_names = (const char *[]){ "mmpll0" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll mmpll1 = {
+	.l_reg = 0x0044,
+	.m_reg = 0x0048,
+	.n_reg = 0x004c,
+	.config_reg = 0x0050,
+	.mode_reg = 0x0040,
+	.status_reg = 0x005c,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll1",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap mmpll1_vote = {
+	.enable_reg = 0x0100,
+	.enable_mask = BIT(1),
+	.hw.init = &(struct clk_init_data){
+		.name = "mmpll1_vote",
+		.parent_names = (const char *[]){ "mmpll1" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll mmpll2 = {
+	.l_reg = 0x4104,
+	.m_reg = 0x4108,
+	.n_reg = 0x410c,
+	.config_reg = 0x4110,
+	.mode_reg = 0x4100,
+	.status_reg = 0x411c,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll2",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_pll mmpll3 = {
+	.l_reg = 0x0084,
+	.m_reg = 0x0088,
+	.n_reg = 0x008c,
+	.config_reg = 0x0090,
+	.mode_reg = 0x0080,
+	.status_reg = 0x009c,
+	.status_bit = 17,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll3",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_pll mmpll4 = {
+	.l_reg = 0x00a4,
+	.m_reg = 0x00a8,
+	.n_reg = 0x00ac,
+	.config_reg = 0x00b0,
+	.mode_reg = 0x0080,
+	.status_reg = 0x00bc,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmpll4",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_rcg2 mmss_ahb_clk_src = {
+	.cmd_rcgr = 0x5000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmss_ahb_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mmss_axi_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(333430000, P_MMPLL1, 3.5, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	F(466800000, P_MMPLL1, 2.5, 0, 0),
+};
+
+static struct clk_rcg2 mmss_axi_clk_src = {
+	.cmd_rcgr = 0x5040,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mmss_axi_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mmss_axi_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_ocmemnoc_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(109090000, P_GPLL0, 5.5, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+};
+
+static struct clk_rcg2 ocmemnoc_clk_src = {
+	.cmd_rcgr = 0x5090,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_ocmemnoc_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ocmemnoc_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_csi0_3_clk[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+	.cmd_rcgr = 0x3090,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+	.cmd_rcgr = 0x3100,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+	.cmd_rcgr = 0x3160,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi3_clk_src = {
+	.cmd_rcgr = 0x31c0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi3_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_vfe_vfe0_1_clk[] = {
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(80000000, P_GPLL0, 7.5, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(109090000, P_GPLL0, 5.5, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(465000000, P_MMPLL4, 2, 0, 0),
+	F(600000000, P_GPLL0, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+	.cmd_rcgr = 0x3600,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vfe0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+	.cmd_rcgr = 0x3620,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vfe1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_mdp_clk[] = {
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(85710000, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(160000000, P_MMPLL0, 5, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+	.cmd_rcgr = 0x2040,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_dsi_hdmi_gpll0_map,
+	.freq_tbl = ftbl_mdss_mdp_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mdp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+	.cmd_rcgr = 0x4000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_2_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gfx3d_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_2_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_jpeg_jpeg0_2_clk[] = {
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+	.cmd_rcgr = 0x3500,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 jpeg1_clk_src = {
+	.cmd_rcgr = 0x3520,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 jpeg2_clk_src = {
+	.cmd_rcgr = 0x3540,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "jpeg2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl pixel_freq_tbl[] = {
+	{ .src = P_DSI0PLL },
+	{ }
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+	.cmd_rcgr = 0x2000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = pixel_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pclk0_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_pixel_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+	.cmd_rcgr = 0x2020,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = pixel_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pclk1_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_pixel_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl ftbl_venus0_vcodec0_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(465000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+	.cmd_rcgr = 0x1000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_3_gpll0_map,
+	.freq_tbl = ftbl_venus0_vcodec0_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vcodec0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_3_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_avsync_vp_clk[] = {
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vp_clk_src = {
+	.cmd_rcgr = 0x2430,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_avsync_vp_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_cci_cci_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+	.cmd_rcgr = 0x3300,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+	.freq_tbl = ftbl_camss_cci_cci_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "cci_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_gp0_1_clk[] = {
+	F(10000, P_XO, 16, 1, 120),
+	F(24000, P_XO, 16, 1, 50),
+	F(6000000, P_GPLL0, 10, 1, 10),
+	F(12000000, P_GPLL0, 10, 1, 5),
+	F(13000000, P_GPLL0, 4, 13, 150),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	{ }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+	.cmd_rcgr = 0x3420,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "camss_gp0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0_sleep,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+	.cmd_rcgr = 0x3450,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "camss_gp1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0_sleep,
+		.num_parents = 7,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_mclk0_3_clk[] = {
+	F(4800000, P_XO, 4, 0, 0),
+	F(6000000, P_GPLL0, 10, 1, 10),
+	F(8000000, P_GPLL0, 15, 1, 5),
+	F(9600000, P_XO, 2, 0, 0),
+	F(16000000, P_MMPLL0, 10, 1, 5),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	F(32000000, P_MMPLL0, 5, 1, 5),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(64000000, P_MMPLL0, 12.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+	.cmd_rcgr = 0x3360,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+	.cmd_rcgr = 0x3390,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+	.cmd_rcgr = 0x33c0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+	.cmd_rcgr = 0x33f0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "mclk3_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_phy0_2_csi0_2phytimer_clk[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+	.cmd_rcgr = 0x3000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi0phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+	.cmd_rcgr = 0x3030,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi1phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+	.cmd_rcgr = 0x3060,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "csi2phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_vfe_cpp_clk[] = {
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(372000000, P_MMPLL4, 2.5, 0, 0),
+	F(465000000, P_MMPLL4, 2, 0, 0),
+	F(600000000, P_GPLL0, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+	.cmd_rcgr = 0x3640,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_cpp_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "cpp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl byte_freq_tbl[] = {
+	{ .src = P_DSI0PLL_BYTE },
+	{ }
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+	.cmd_rcgr = 0x2120,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+	.freq_tbl = byte_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "byte0_clk_src",
+		.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_byte_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+	.cmd_rcgr = 0x2140,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+	.freq_tbl = byte_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "byte1_clk_src",
+		.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_byte_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_edpaux_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 edpaux_clk_src = {
+	.cmd_rcgr = 0x20e0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_edpaux_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "edpaux_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_edplink_clk[] = {
+	F(135000000, P_EDPLINK, 2, 0, 0),
+	F(270000000, P_EDPLINK, 11, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 edplink_clk_src = {
+	.cmd_rcgr = 0x20c0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_edplink_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "edplink_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl edp_pixel_freq_tbl[] = {
+	{ .src = P_EDPVCO },
+	{ }
+};
+
+static struct clk_rcg2 edppixel_clk_src = {
+	.cmd_rcgr = 0x20a0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_map,
+	.freq_tbl = edp_pixel_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "edppixel_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp,
+		.num_parents = 6,
+		.ops = &clk_edp_pixel_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+	.cmd_rcgr = 0x2160,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "esc0_clk_src",
+		.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+	.cmd_rcgr = 0x2180,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "esc1_clk_src",
+		.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl extpclk_freq_tbl[] = {
+	{ .src = P_HDMIPLL },
+	{ }
+};
+
+static struct clk_rcg2 extpclk_clk_src = {
+	.cmd_rcgr = 0x2060,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = extpclk_freq_tbl,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "extpclk_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_byte_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 hdmi_clk_src = {
+	.cmd_rcgr = 0x2100,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "hdmi_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_vsync_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+	.cmd_rcgr = 0x2080,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vsync_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mmss_rbcpr_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 rbcpr_clk_src = {
+	.cmd_rcgr = 0x4060,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mmss_rbcpr_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "rbcpr_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_oxili_rbbmtimer_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 rbbmtimer_clk_src = {
+	.cmd_rcgr = 0x4090,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_oxili_rbbmtimer_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "rbbmtimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_vpu_maple_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(465000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 maple_clk_src = {
+	.cmd_rcgr = 0x1320,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_vpu_maple_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "maple_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_vpu_vdp_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vdp_clk_src = {
+	.cmd_rcgr = 0x1300,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_vpu_vdp_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vdp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_vpu_bus_clk[] = {
+	F(40000000, P_GPLL0, 15, 0, 0),
+	F(80000000, P_MMPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vpu_bus_clk_src = {
+	.cmd_rcgr = 0x1340,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_vpu_bus_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "vpu_bus_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch mmss_cxo_clk = {
+	.halt_reg = 0x5104,
+	.clkr = {
+		.enable_reg = 0x5104,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_cxo_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_sleepclk_clk = {
+	.halt_reg = 0x5100,
+	.clkr = {
+		.enable_reg = 0x5100,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_sleepclk_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_ahb_clk = {
+	.halt_reg = 0x2414,
+	.clkr = {
+		.enable_reg = 0x2414,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_edppixel_clk = {
+	.halt_reg = 0x2418,
+	.clkr = {
+		.enable_reg = 0x2418,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_edppixel_clk",
+			.parent_names = (const char *[]){
+				"edppixel_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_extpclk_clk = {
+	.halt_reg = 0x2410,
+	.clkr = {
+		.enable_reg = 0x2410,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_extpclk_clk",
+			.parent_names = (const char *[]){
+				"extpclk_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_pclk0_clk = {
+	.halt_reg = 0x241c,
+	.clkr = {
+		.enable_reg = 0x241c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_pclk0_clk",
+			.parent_names = (const char *[]){
+				"pclk0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_pclk1_clk = {
+	.halt_reg = 0x2420,
+	.clkr = {
+		.enable_reg = 0x2420,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_pclk1_clk",
+			.parent_names = (const char *[]){
+				"pclk1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch avsync_vp_clk = {
+	.halt_reg = 0x2404,
+	.clkr = {
+		.enable_reg = 0x2404,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "avsync_vp_clk",
+			.parent_names = (const char *[]){
+				"vp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_ahb_clk = {
+	.halt_reg = 0x348c,
+	.clkr = {
+		.enable_reg = 0x348c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cci_cci_ahb_clk = {
+	.halt_reg = 0x3348,
+	.clkr = {
+		.enable_reg = 0x3348,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cci_cci_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cci_cci_clk = {
+	.halt_reg = 0x3344,
+	.clkr = {
+		.enable_reg = 0x3344,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_cci_cci_clk",
+			.parent_names = (const char *[]){
+				"cci_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_ahb_clk = {
+	.halt_reg = 0x30bc,
+	.clkr = {
+		.enable_reg = 0x30bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_clk = {
+	.halt_reg = 0x30b4,
+	.clkr = {
+		.enable_reg = 0x30b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0phy_clk = {
+	.halt_reg = 0x30c4,
+	.clkr = {
+		.enable_reg = 0x30c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0phy_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0pix_clk = {
+	.halt_reg = 0x30e4,
+	.clkr = {
+		.enable_reg = 0x30e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0pix_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0rdi_clk = {
+	.halt_reg = 0x30d4,
+	.clkr = {
+		.enable_reg = 0x30d4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi0rdi_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_ahb_clk = {
+	.halt_reg = 0x3128,
+	.clkr = {
+		.enable_reg = 0x3128,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_clk = {
+	.halt_reg = 0x3124,
+	.clkr = {
+		.enable_reg = 0x3124,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1phy_clk = {
+	.halt_reg = 0x3134,
+	.clkr = {
+		.enable_reg = 0x3134,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1phy_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1pix_clk = {
+	.halt_reg = 0x3154,
+	.clkr = {
+		.enable_reg = 0x3154,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1pix_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1rdi_clk = {
+	.halt_reg = 0x3144,
+	.clkr = {
+		.enable_reg = 0x3144,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi1rdi_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_ahb_clk = {
+	.halt_reg = 0x3188,
+	.clkr = {
+		.enable_reg = 0x3188,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_clk = {
+	.halt_reg = 0x3184,
+	.clkr = {
+		.enable_reg = 0x3184,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2phy_clk = {
+	.halt_reg = 0x3194,
+	.clkr = {
+		.enable_reg = 0x3194,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2phy_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2pix_clk = {
+	.halt_reg = 0x31b4,
+	.clkr = {
+		.enable_reg = 0x31b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2pix_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2rdi_clk = {
+	.halt_reg = 0x31a4,
+	.clkr = {
+		.enable_reg = 0x31a4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi2rdi_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_ahb_clk = {
+	.halt_reg = 0x31e8,
+	.clkr = {
+		.enable_reg = 0x31e8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_clk = {
+	.halt_reg = 0x31e4,
+	.clkr = {
+		.enable_reg = 0x31e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3phy_clk = {
+	.halt_reg = 0x31f4,
+	.clkr = {
+		.enable_reg = 0x31f4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3phy_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3pix_clk = {
+	.halt_reg = 0x3214,
+	.clkr = {
+		.enable_reg = 0x3214,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3pix_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3rdi_clk = {
+	.halt_reg = 0x3204,
+	.clkr = {
+		.enable_reg = 0x3204,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi3rdi_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe0_clk = {
+	.halt_reg = 0x3704,
+	.clkr = {
+		.enable_reg = 0x3704,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe0_clk",
+			.parent_names = (const char *[]){
+				"vfe0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe1_clk = {
+	.halt_reg = 0x3714,
+	.clkr = {
+		.enable_reg = 0x3714,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe1_clk",
+			.parent_names = (const char *[]){
+				"vfe1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp0_clk = {
+	.halt_reg = 0x3444,
+	.clkr = {
+		.enable_reg = 0x3444,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_gp0_clk",
+			.parent_names = (const char *[]){
+				"camss_gp0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp1_clk = {
+	.halt_reg = 0x3474,
+	.clkr = {
+		.enable_reg = 0x3474,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_gp1_clk",
+			.parent_names = (const char *[]){
+				"camss_gp1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_ispif_ahb_clk = {
+	.halt_reg = 0x3224,
+	.clkr = {
+		.enable_reg = 0x3224,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_ispif_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg0_clk = {
+	.halt_reg = 0x35a8,
+	.clkr = {
+		.enable_reg = 0x35a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg0_clk",
+			.parent_names = (const char *[]){
+				"jpeg0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg1_clk = {
+	.halt_reg = 0x35ac,
+	.clkr = {
+		.enable_reg = 0x35ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg1_clk",
+			.parent_names = (const char *[]){
+				"jpeg1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg2_clk = {
+	.halt_reg = 0x35b0,
+	.clkr = {
+		.enable_reg = 0x35b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg2_clk",
+			.parent_names = (const char *[]){
+				"jpeg2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg_ahb_clk = {
+	.halt_reg = 0x35b4,
+	.clkr = {
+		.enable_reg = 0x35b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg_axi_clk = {
+	.halt_reg = 0x35b8,
+	.clkr = {
+		.enable_reg = 0x35b8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk0_clk = {
+	.halt_reg = 0x3384,
+	.clkr = {
+		.enable_reg = 0x3384,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk0_clk",
+			.parent_names = (const char *[]){
+				"mclk0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk1_clk = {
+	.halt_reg = 0x33b4,
+	.clkr = {
+		.enable_reg = 0x33b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk1_clk",
+			.parent_names = (const char *[]){
+				"mclk1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk2_clk = {
+	.halt_reg = 0x33e4,
+	.clkr = {
+		.enable_reg = 0x33e4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk2_clk",
+			.parent_names = (const char *[]){
+				"mclk2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk3_clk = {
+	.halt_reg = 0x3414,
+	.clkr = {
+		.enable_reg = 0x3414,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_mclk3_clk",
+			.parent_names = (const char *[]){
+				"mclk3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_micro_ahb_clk = {
+	.halt_reg = 0x3494,
+	.clkr = {
+		.enable_reg = 0x3494,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_micro_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy0_csi0phytimer_clk = {
+	.halt_reg = 0x3024,
+	.clkr = {
+		.enable_reg = 0x3024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_phy0_csi0phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi0phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy1_csi1phytimer_clk = {
+	.halt_reg = 0x3054,
+	.clkr = {
+		.enable_reg = 0x3054,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_phy1_csi1phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi1phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy2_csi2phytimer_clk = {
+	.halt_reg = 0x3084,
+	.clkr = {
+		.enable_reg = 0x3084,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_phy2_csi2phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi2phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_top_ahb_clk = {
+	.halt_reg = 0x3484,
+	.clkr = {
+		.enable_reg = 0x3484,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_top_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_cpp_ahb_clk = {
+	.halt_reg = 0x36b4,
+	.clkr = {
+		.enable_reg = 0x36b4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_cpp_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_cpp_clk = {
+	.halt_reg = 0x36b0,
+	.clkr = {
+		.enable_reg = 0x36b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_cpp_clk",
+			.parent_names = (const char *[]){
+				"cpp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe0_clk = {
+	.halt_reg = 0x36a8,
+	.clkr = {
+		.enable_reg = 0x36a8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe0_clk",
+			.parent_names = (const char *[]){
+				"vfe0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe1_clk = {
+	.halt_reg = 0x36ac,
+	.clkr = {
+		.enable_reg = 0x36ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe1_clk",
+			.parent_names = (const char *[]){
+				"vfe1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe_ahb_clk = {
+	.halt_reg = 0x36b8,
+	.clkr = {
+		.enable_reg = 0x36b8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe_axi_clk = {
+	.halt_reg = 0x36bc,
+	.clkr = {
+		.enable_reg = 0x36bc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_ahb_clk = {
+	.halt_reg = 0x2308,
+	.clkr = {
+		.enable_reg = 0x2308,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_axi_clk = {
+	.halt_reg = 0x2310,
+	.clkr = {
+		.enable_reg = 0x2310,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte0_clk = {
+	.halt_reg = 0x233c,
+	.clkr = {
+		.enable_reg = 0x233c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_byte0_clk",
+			.parent_names = (const char *[]){
+				"byte0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte1_clk = {
+	.halt_reg = 0x2340,
+	.clkr = {
+		.enable_reg = 0x2340,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_byte1_clk",
+			.parent_names = (const char *[]){
+				"byte1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edpaux_clk = {
+	.halt_reg = 0x2334,
+	.clkr = {
+		.enable_reg = 0x2334,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_edpaux_clk",
+			.parent_names = (const char *[]){
+				"edpaux_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edplink_clk = {
+	.halt_reg = 0x2330,
+	.clkr = {
+		.enable_reg = 0x2330,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_edplink_clk",
+			.parent_names = (const char *[]){
+				"edplink_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edppixel_clk = {
+	.halt_reg = 0x232c,
+	.clkr = {
+		.enable_reg = 0x232c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_edppixel_clk",
+			.parent_names = (const char *[]){
+				"edppixel_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc0_clk = {
+	.halt_reg = 0x2344,
+	.clkr = {
+		.enable_reg = 0x2344,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_esc0_clk",
+			.parent_names = (const char *[]){
+				"esc0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc1_clk = {
+	.halt_reg = 0x2348,
+	.clkr = {
+		.enable_reg = 0x2348,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_esc1_clk",
+			.parent_names = (const char *[]){
+				"esc1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_extpclk_clk = {
+	.halt_reg = 0x2324,
+	.clkr = {
+		.enable_reg = 0x2324,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_extpclk_clk",
+			.parent_names = (const char *[]){
+				"extpclk_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_ahb_clk = {
+	.halt_reg = 0x230c,
+	.clkr = {
+		.enable_reg = 0x230c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_clk = {
+	.halt_reg = 0x2338,
+	.clkr = {
+		.enable_reg = 0x2338,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_clk",
+			.parent_names = (const char *[]){
+				"hdmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_mdp_clk = {
+	.halt_reg = 0x231c,
+	.clkr = {
+		.enable_reg = 0x231c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_mdp_clk",
+			.parent_names = (const char *[]){
+				"mdp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_mdp_lut_clk = {
+	.halt_reg = 0x2320,
+	.clkr = {
+		.enable_reg = 0x2320,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_mdp_lut_clk",
+			.parent_names = (const char *[]){
+				"mdp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk0_clk = {
+	.halt_reg = 0x2314,
+	.clkr = {
+		.enable_reg = 0x2314,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_pclk0_clk",
+			.parent_names = (const char *[]){
+				"pclk0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk1_clk = {
+	.halt_reg = 0x2318,
+	.clkr = {
+		.enable_reg = 0x2318,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_pclk1_clk",
+			.parent_names = (const char *[]){
+				"pclk1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_vsync_clk = {
+	.halt_reg = 0x2328,
+	.clkr = {
+		.enable_reg = 0x2328,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mdss_vsync_clk",
+			.parent_names = (const char *[]){
+				"vsync_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_rbcpr_ahb_clk = {
+	.halt_reg = 0x4088,
+	.clkr = {
+		.enable_reg = 0x4088,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_rbcpr_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_rbcpr_clk = {
+	.halt_reg = 0x4084,
+	.clkr = {
+		.enable_reg = 0x4084,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_rbcpr_clk",
+			.parent_names = (const char *[]){
+				"rbcpr_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_ahb_clk = {
+	.halt_reg = 0x0230,
+	.clkr = {
+		.enable_reg = 0x0230,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_ahb_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_axi_clk = {
+	.halt_reg = 0x0210,
+	.clkr = {
+		.enable_reg = 0x0210,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_axi_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_csi0_clk = {
+	.halt_reg = 0x023c,
+	.clkr = {
+		.enable_reg = 0x023c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_csi0_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_csi0_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_gfx3d_clk = {
+	.halt_reg = 0x022c,
+	.clkr = {
+		.enable_reg = 0x022c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_gfx3d_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_gfx3d_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_jpeg0_clk = {
+	.halt_reg = 0x0204,
+	.clkr = {
+		.enable_reg = 0x0204,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_jpeg0_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_jpeg0_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_jpeg1_clk = {
+	.halt_reg = 0x0208,
+	.clkr = {
+		.enable_reg = 0x0208,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_jpeg1_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_jpeg1_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_jpeg2_clk = {
+	.halt_reg = 0x0224,
+	.clkr = {
+		.enable_reg = 0x0224,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_jpeg2_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_jpeg2_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_mdp_clk = {
+	.halt_reg = 0x020c,
+	.clkr = {
+		.enable_reg = 0x020c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_mdp_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_mdp_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_pclk0_clk = {
+	.halt_reg = 0x0234,
+	.clkr = {
+		.enable_reg = 0x0234,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_pclk0_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_pclk0_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_pclk1_clk = {
+	.halt_reg = 0x0228,
+	.clkr = {
+		.enable_reg = 0x0228,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_pclk1_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_pclk1_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_vcodec0_clk = {
+	.halt_reg = 0x0214,
+	.clkr = {
+		.enable_reg = 0x0214,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_vcodec0_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_vcodec0_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_vfe0_clk = {
+	.halt_reg = 0x0218,
+	.clkr = {
+		.enable_reg = 0x0218,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_vfe0_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_vfe0_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_vfe1_clk = {
+	.halt_reg = 0x021c,
+	.clkr = {
+		.enable_reg = 0x021c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_vfe1_clk",
+			.parent_names = (const char *[]){
+				"mmss_spdm_vfe1_div_clk",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_rm_axi_clk = {
+	.halt_reg = 0x0304,
+	.clkr = {
+		.enable_reg = 0x0304,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_rm_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_spdm_rm_ocmemnoc_clk = {
+	.halt_reg = 0x0308,
+	.clkr = {
+		.enable_reg = 0x0308,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_spdm_rm_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+
+static struct clk_branch mmss_misc_ahb_clk = {
+	.halt_reg = 0x502c,
+	.clkr = {
+		.enable_reg = 0x502c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_misc_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_ahb_clk = {
+	.halt_reg = 0x5024,
+	.clkr = {
+		.enable_reg = 0x5024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_bto_ahb_clk = {
+	.halt_reg = 0x5028,
+	.clkr = {
+		.enable_reg = 0x5028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_bto_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_axi_clk = {
+	.halt_reg = 0x506c,
+	.clkr = {
+		.enable_reg = 0x506c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_s0_axi_clk = {
+	.halt_reg = 0x5064,
+	.clkr = {
+		.enable_reg = 0x5064,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "mmss_s0_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch ocmemcx_ahb_clk = {
+	.halt_reg = 0x405c,
+	.clkr = {
+		.enable_reg = 0x405c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "ocmemcx_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch ocmemcx_ocmemnoc_clk = {
+	.halt_reg = 0x4058,
+	.clkr = {
+		.enable_reg = 0x4058,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "ocmemcx_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxili_ocmemgx_clk = {
+	.halt_reg = 0x402c,
+	.clkr = {
+		.enable_reg = 0x402c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "oxili_ocmemgx_clk",
+			.parent_names = (const char *[]){
+				"gfx3d_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxili_gfx3d_clk = {
+	.halt_reg = 0x4028,
+	.clkr = {
+		.enable_reg = 0x4028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "oxili_gfx3d_clk",
+			.parent_names = (const char *[]){
+				"gfx3d_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxili_rbbmtimer_clk = {
+	.halt_reg = 0x40b0,
+	.clkr = {
+		.enable_reg = 0x40b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "oxili_rbbmtimer_clk",
+			.parent_names = (const char *[]){
+				"rbbmtimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxilicx_ahb_clk = {
+	.halt_reg = 0x403c,
+	.clkr = {
+		.enable_reg = 0x403c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "oxilicx_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_ahb_clk = {
+	.halt_reg = 0x1030,
+	.clkr = {
+		.enable_reg = 0x1030,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_axi_clk = {
+	.halt_reg = 0x1034,
+	.clkr = {
+		.enable_reg = 0x1034,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_core0_vcodec_clk = {
+	.halt_reg = 0x1048,
+	.clkr = {
+		.enable_reg = 0x1048,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_core0_vcodec_clk",
+			.parent_names = (const char *[]){
+				"vcodec0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_core1_vcodec_clk = {
+	.halt_reg = 0x104c,
+	.clkr = {
+		.enable_reg = 0x104c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_core1_vcodec_clk",
+			.parent_names = (const char *[]){
+				"vcodec0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_ocmemnoc_clk = {
+	.halt_reg = 0x1038,
+	.clkr = {
+		.enable_reg = 0x1038,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_vcodec0_clk = {
+	.halt_reg = 0x1028,
+	.clkr = {
+		.enable_reg = 0x1028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "venus0_vcodec0_clk",
+			.parent_names = (const char *[]){
+				"vcodec0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_ahb_clk = {
+	.halt_reg = 0x1430,
+	.clkr = {
+		.enable_reg = 0x1430,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_axi_clk = {
+	.halt_reg = 0x143c,
+	.clkr = {
+		.enable_reg = 0x143c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_bus_clk = {
+	.halt_reg = 0x1440,
+	.clkr = {
+		.enable_reg = 0x1440,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_bus_clk",
+			.parent_names = (const char *[]){
+				"vpu_bus_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_cxo_clk = {
+	.halt_reg = 0x1434,
+	.clkr = {
+		.enable_reg = 0x1434,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_cxo_clk",
+			.parent_names = (const char *[]){ "xo" },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_maple_clk = {
+	.halt_reg = 0x142c,
+	.clkr = {
+		.enable_reg = 0x142c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_maple_clk",
+			.parent_names = (const char *[]){
+				"maple_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_sleep_clk = {
+	.halt_reg = 0x1438,
+	.clkr = {
+		.enable_reg = 0x1438,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch vpu_vdp_clk = {
+	.halt_reg = 0x1428,
+	.clkr = {
+		.enable_reg = 0x1428,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vpu_vdp_clk",
+			.parent_names = (const char *[]){
+				"vdp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct pll_config mmpll1_config = {
+	.l = 60,
+	.m = 25,
+	.n = 32,
+	.vco_val = 0x0,
+	.vco_mask = 0x3 << 20,
+	.pre_div_val = 0x0,
+	.pre_div_mask = 0x7 << 12,
+	.post_div_val = 0x0,
+	.post_div_mask = 0x3 << 8,
+	.mn_ena_mask = BIT(24),
+	.main_output_mask = BIT(0),
+};
+
+static const struct pll_config mmpll3_config = {
+	.l = 48,
+	.m = 7,
+	.n = 16,
+	.vco_val = 0x0,
+	.vco_mask = 0x3 << 20,
+	.pre_div_val = 0x0,
+	.pre_div_mask = 0x7 << 12,
+	.post_div_val = 0x0,
+	.post_div_mask = 0x3 << 8,
+	.mn_ena_mask = BIT(24),
+	.main_output_mask = BIT(0),
+	.aux_output_mask = BIT(1),
+};
+
+static struct clk_regmap *mmcc_apq8084_clocks[] = {
+	[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
+	[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
+	[MMPLL0] = &mmpll0.clkr,
+	[MMPLL0_VOTE] = &mmpll0_vote,
+	[MMPLL1] = &mmpll1.clkr,
+	[MMPLL1_VOTE] = &mmpll1_vote,
+	[MMPLL2] = &mmpll2.clkr,
+	[MMPLL3] = &mmpll3.clkr,
+	[MMPLL4] = &mmpll4.clkr,
+	[CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+	[CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+	[CSI2_CLK_SRC] = &csi2_clk_src.clkr,
+	[CSI3_CLK_SRC] = &csi3_clk_src.clkr,
+	[VCODEC0_CLK_SRC] = &vcodec0_clk_src.clkr,
+	[VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+	[VFE1_CLK_SRC] = &vfe1_clk_src.clkr,
+	[MDP_CLK_SRC] = &mdp_clk_src.clkr,
+	[PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+	[PCLK1_CLK_SRC] = &pclk1_clk_src.clkr,
+	[OCMEMNOC_CLK_SRC] = &ocmemnoc_clk_src.clkr,
+	[GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+	[JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+	[JPEG1_CLK_SRC] = &jpeg1_clk_src.clkr,
+	[JPEG2_CLK_SRC] = &jpeg2_clk_src.clkr,
+	[EDPPIXEL_CLK_SRC] = &edppixel_clk_src.clkr,
+	[EXTPCLK_CLK_SRC] = &extpclk_clk_src.clkr,
+	[VP_CLK_SRC] = &vp_clk_src.clkr,
+	[CCI_CLK_SRC] = &cci_clk_src.clkr,
+	[CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr,
+	[CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr,
+	[MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+	[MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+	[MCLK2_CLK_SRC] = &mclk2_clk_src.clkr,
+	[MCLK3_CLK_SRC] = &mclk3_clk_src.clkr,
+	[CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+	[CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+	[CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr,
+	[CPP_CLK_SRC] = &cpp_clk_src.clkr,
+	[BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+	[BYTE1_CLK_SRC] = &byte1_clk_src.clkr,
+	[EDPAUX_CLK_SRC] = &edpaux_clk_src.clkr,
+	[EDPLINK_CLK_SRC] = &edplink_clk_src.clkr,
+	[ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+	[ESC1_CLK_SRC] = &esc1_clk_src.clkr,
+	[HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
+	[VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+	[RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+	[RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
+	[MAPLE_CLK_SRC] = &maple_clk_src.clkr,
+	[VDP_CLK_SRC] = &vdp_clk_src.clkr,
+	[VPU_BUS_CLK_SRC] = &vpu_bus_clk_src.clkr,
+	[MMSS_CXO_CLK] = &mmss_cxo_clk.clkr,
+	[MMSS_SLEEPCLK_CLK] = &mmss_sleepclk_clk.clkr,
+	[AVSYNC_AHB_CLK] = &avsync_ahb_clk.clkr,
+	[AVSYNC_EDPPIXEL_CLK] = &avsync_edppixel_clk.clkr,
+	[AVSYNC_EXTPCLK_CLK] = &avsync_extpclk_clk.clkr,
+	[AVSYNC_PCLK0_CLK] = &avsync_pclk0_clk.clkr,
+	[AVSYNC_PCLK1_CLK] = &avsync_pclk1_clk.clkr,
+	[AVSYNC_VP_CLK] = &avsync_vp_clk.clkr,
+	[CAMSS_AHB_CLK] = &camss_ahb_clk.clkr,
+	[CAMSS_CCI_CCI_AHB_CLK] = &camss_cci_cci_ahb_clk.clkr,
+	[CAMSS_CCI_CCI_CLK] = &camss_cci_cci_clk.clkr,
+	[CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.clkr,
+	[CAMSS_CSI0_CLK] = &camss_csi0_clk.clkr,
+	[CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.clkr,
+	[CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.clkr,
+	[CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.clkr,
+	[CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.clkr,
+	[CAMSS_CSI1_CLK] = &camss_csi1_clk.clkr,
+	[CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.clkr,
+	[CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.clkr,
+	[CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.clkr,
+	[CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.clkr,
+	[CAMSS_CSI2_CLK] = &camss_csi2_clk.clkr,
+	[CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.clkr,
+	[CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.clkr,
+	[CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.clkr,
+	[CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.clkr,
+	[CAMSS_CSI3_CLK] = &camss_csi3_clk.clkr,
+	[CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.clkr,
+	[CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.clkr,
+	[CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.clkr,
+	[CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.clkr,
+	[CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.clkr,
+	[CAMSS_GP0_CLK] = &camss_gp0_clk.clkr,
+	[CAMSS_GP1_CLK] = &camss_gp1_clk.clkr,
+	[CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.clkr,
+	[CAMSS_JPEG_JPEG0_CLK] = &camss_jpeg_jpeg0_clk.clkr,
+	[CAMSS_JPEG_JPEG1_CLK] = &camss_jpeg_jpeg1_clk.clkr,
+	[CAMSS_JPEG_JPEG2_CLK] = &camss_jpeg_jpeg2_clk.clkr,
+	[CAMSS_JPEG_JPEG_AHB_CLK] = &camss_jpeg_jpeg_ahb_clk.clkr,
+	[CAMSS_JPEG_JPEG_AXI_CLK] = &camss_jpeg_jpeg_axi_clk.clkr,
+	[CAMSS_MCLK0_CLK] = &camss_mclk0_clk.clkr,
+	[CAMSS_MCLK1_CLK] = &camss_mclk1_clk.clkr,
+	[CAMSS_MCLK2_CLK] = &camss_mclk2_clk.clkr,
+	[CAMSS_MCLK3_CLK] = &camss_mclk3_clk.clkr,
+	[CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.clkr,
+	[CAMSS_PHY0_CSI0PHYTIMER_CLK] = &camss_phy0_csi0phytimer_clk.clkr,
+	[CAMSS_PHY1_CSI1PHYTIMER_CLK] = &camss_phy1_csi1phytimer_clk.clkr,
+	[CAMSS_PHY2_CSI2PHYTIMER_CLK] = &camss_phy2_csi2phytimer_clk.clkr,
+	[CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.clkr,
+	[CAMSS_VFE_CPP_AHB_CLK] = &camss_vfe_cpp_ahb_clk.clkr,
+	[CAMSS_VFE_CPP_CLK] = &camss_vfe_cpp_clk.clkr,
+	[CAMSS_VFE_VFE0_CLK] = &camss_vfe_vfe0_clk.clkr,
+	[CAMSS_VFE_VFE1_CLK] = &camss_vfe_vfe1_clk.clkr,
+	[CAMSS_VFE_VFE_AHB_CLK] = &camss_vfe_vfe_ahb_clk.clkr,
+	[CAMSS_VFE_VFE_AXI_CLK] = &camss_vfe_vfe_axi_clk.clkr,
+	[MDSS_AHB_CLK] = &mdss_ahb_clk.clkr,
+	[MDSS_AXI_CLK] = &mdss_axi_clk.clkr,
+	[MDSS_BYTE0_CLK] = &mdss_byte0_clk.clkr,
+	[MDSS_BYTE1_CLK] = &mdss_byte1_clk.clkr,
+	[MDSS_EDPAUX_CLK] = &mdss_edpaux_clk.clkr,
+	[MDSS_EDPLINK_CLK] = &mdss_edplink_clk.clkr,
+	[MDSS_EDPPIXEL_CLK] = &mdss_edppixel_clk.clkr,
+	[MDSS_ESC0_CLK] = &mdss_esc0_clk.clkr,
+	[MDSS_ESC1_CLK] = &mdss_esc1_clk.clkr,
+	[MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.clkr,
+	[MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.clkr,
+	[MDSS_HDMI_CLK] = &mdss_hdmi_clk.clkr,
+	[MDSS_MDP_CLK] = &mdss_mdp_clk.clkr,
+	[MDSS_MDP_LUT_CLK] = &mdss_mdp_lut_clk.clkr,
+	[MDSS_PCLK0_CLK] = &mdss_pclk0_clk.clkr,
+	[MDSS_PCLK1_CLK] = &mdss_pclk1_clk.clkr,
+	[MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr,
+	[MMSS_RBCPR_AHB_CLK] = &mmss_rbcpr_ahb_clk.clkr,
+	[MMSS_RBCPR_CLK] = &mmss_rbcpr_clk.clkr,
+	[MMSS_SPDM_AHB_CLK] = &mmss_spdm_ahb_clk.clkr,
+	[MMSS_SPDM_AXI_CLK] = &mmss_spdm_axi_clk.clkr,
+	[MMSS_SPDM_CSI0_CLK] = &mmss_spdm_csi0_clk.clkr,
+	[MMSS_SPDM_GFX3D_CLK] = &mmss_spdm_gfx3d_clk.clkr,
+	[MMSS_SPDM_JPEG0_CLK] = &mmss_spdm_jpeg0_clk.clkr,
+	[MMSS_SPDM_JPEG1_CLK] = &mmss_spdm_jpeg1_clk.clkr,
+	[MMSS_SPDM_JPEG2_CLK] = &mmss_spdm_jpeg2_clk.clkr,
+	[MMSS_SPDM_MDP_CLK] = &mmss_spdm_mdp_clk.clkr,
+	[MMSS_SPDM_PCLK0_CLK] = &mmss_spdm_pclk0_clk.clkr,
+	[MMSS_SPDM_PCLK1_CLK] = &mmss_spdm_pclk1_clk.clkr,
+	[MMSS_SPDM_VCODEC0_CLK] = &mmss_spdm_vcodec0_clk.clkr,
+	[MMSS_SPDM_VFE0_CLK] = &mmss_spdm_vfe0_clk.clkr,
+	[MMSS_SPDM_VFE1_CLK] = &mmss_spdm_vfe1_clk.clkr,
+	[MMSS_SPDM_RM_AXI_CLK] = &mmss_spdm_rm_axi_clk.clkr,
+	[MMSS_SPDM_RM_OCMEMNOC_CLK] = &mmss_spdm_rm_ocmemnoc_clk.clkr,
+	[MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr,
+	[MMSS_MMSSNOC_AHB_CLK] = &mmss_mmssnoc_ahb_clk.clkr,
+	[MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr,
+	[MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
+	[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
+	[OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
+	[OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr,
+	[OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr,
+	[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
+	[OXILI_RBBMTIMER_CLK] = &oxili_rbbmtimer_clk.clkr,
+	[OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
+	[VENUS0_AHB_CLK] = &venus0_ahb_clk.clkr,
+	[VENUS0_AXI_CLK] = &venus0_axi_clk.clkr,
+	[VENUS0_CORE0_VCODEC_CLK] = &venus0_core0_vcodec_clk.clkr,
+	[VENUS0_CORE1_VCODEC_CLK] = &venus0_core1_vcodec_clk.clkr,
+	[VENUS0_OCMEMNOC_CLK] = &venus0_ocmemnoc_clk.clkr,
+	[VENUS0_VCODEC0_CLK] = &venus0_vcodec0_clk.clkr,
+	[VPU_AHB_CLK] = &vpu_ahb_clk.clkr,
+	[VPU_AXI_CLK] = &vpu_axi_clk.clkr,
+	[VPU_BUS_CLK] = &vpu_bus_clk.clkr,
+	[VPU_CXO_CLK] = &vpu_cxo_clk.clkr,
+	[VPU_MAPLE_CLK] = &vpu_maple_clk.clkr,
+	[VPU_SLEEP_CLK] = &vpu_sleep_clk.clkr,
+	[VPU_VDP_CLK] = &vpu_vdp_clk.clkr,
+};
+
+static const struct qcom_reset_map mmcc_apq8084_resets[] = {
+	[MMSS_SPDM_RESET] = { 0x0200 },
+	[MMSS_SPDM_RM_RESET] = { 0x0300 },
+	[VENUS0_RESET] = { 0x1020 },
+	[VPU_RESET] = { 0x1400 },
+	[MDSS_RESET] = { 0x2300 },
+	[AVSYNC_RESET] = { 0x2400 },
+	[CAMSS_PHY0_RESET] = { 0x3020 },
+	[CAMSS_PHY1_RESET] = { 0x3050 },
+	[CAMSS_PHY2_RESET] = { 0x3080 },
+	[CAMSS_CSI0_RESET] = { 0x30b0 },
+	[CAMSS_CSI0PHY_RESET] = { 0x30c0 },
+	[CAMSS_CSI0RDI_RESET] = { 0x30d0 },
+	[CAMSS_CSI0PIX_RESET] = { 0x30e0 },
+	[CAMSS_CSI1_RESET] = { 0x3120 },
+	[CAMSS_CSI1PHY_RESET] = { 0x3130 },
+	[CAMSS_CSI1RDI_RESET] = { 0x3140 },
+	[CAMSS_CSI1PIX_RESET] = { 0x3150 },
+	[CAMSS_CSI2_RESET] = { 0x3180 },
+	[CAMSS_CSI2PHY_RESET] = { 0x3190 },
+	[CAMSS_CSI2RDI_RESET] = { 0x31a0 },
+	[CAMSS_CSI2PIX_RESET] = { 0x31b0 },
+	[CAMSS_CSI3_RESET] = { 0x31e0 },
+	[CAMSS_CSI3PHY_RESET] = { 0x31f0 },
+	[CAMSS_CSI3RDI_RESET] = { 0x3200 },
+	[CAMSS_CSI3PIX_RESET] = { 0x3210 },
+	[CAMSS_ISPIF_RESET] = { 0x3220 },
+	[CAMSS_CCI_RESET] = { 0x3340 },
+	[CAMSS_MCLK0_RESET] = { 0x3380 },
+	[CAMSS_MCLK1_RESET] = { 0x33b0 },
+	[CAMSS_MCLK2_RESET] = { 0x33e0 },
+	[CAMSS_MCLK3_RESET] = { 0x3410 },
+	[CAMSS_GP0_RESET] = { 0x3440 },
+	[CAMSS_GP1_RESET] = { 0x3470 },
+	[CAMSS_TOP_RESET] = { 0x3480 },
+	[CAMSS_AHB_RESET] = { 0x3488 },
+	[CAMSS_MICRO_RESET] = { 0x3490 },
+	[CAMSS_JPEG_RESET] = { 0x35a0 },
+	[CAMSS_VFE_RESET] = { 0x36a0 },
+	[CAMSS_CSI_VFE0_RESET] = { 0x3700 },
+	[CAMSS_CSI_VFE1_RESET] = { 0x3710 },
+	[OXILI_RESET] = { 0x4020 },
+	[OXILICX_RESET] = { 0x4030 },
+	[OCMEMCX_RESET] = { 0x4050 },
+	[MMSS_RBCRP_RESET] = { 0x4080 },
+	[MMSSNOCAHB_RESET] = { 0x5020 },
+	[MMSSNOCAXI_RESET] = { 0x5060 },
+};
+
+static const struct regmap_config mmcc_apq8084_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x5104,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc mmcc_apq8084_desc = {
+	.config = &mmcc_apq8084_regmap_config,
+	.clks = mmcc_apq8084_clocks,
+	.num_clks = ARRAY_SIZE(mmcc_apq8084_clocks),
+	.resets = mmcc_apq8084_resets,
+	.num_resets = ARRAY_SIZE(mmcc_apq8084_resets),
+};
+
+static const struct of_device_id mmcc_apq8084_match_table[] = {
+	{ .compatible = "qcom,mmcc-apq8084" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mmcc_apq8084_match_table);
+
+static int mmcc_apq8084_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct regmap *regmap;
+
+	ret = qcom_cc_probe(pdev, &mmcc_apq8084_desc);
+	if (ret)
+		return ret;
+
+	regmap = dev_get_regmap(&pdev->dev, NULL);
+	clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
+	clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
+
+	return 0;
+}
+
+static int mmcc_apq8084_remove(struct platform_device *pdev)
+{
+	qcom_cc_remove(pdev);
+	return 0;
+}
+
+static struct platform_driver mmcc_apq8084_driver = {
+	.probe		= mmcc_apq8084_probe,
+	.remove		= mmcc_apq8084_remove,
+	.driver		= {
+		.name	= "mmcc-apq8084",
+		.owner	= THIS_MODULE,
+		.of_match_table = mmcc_apq8084_match_table,
+	},
+};
+module_platform_driver(mmcc_apq8084_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC APQ8084 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-apq8084");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-msm8960.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-msm8960.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-msm8960.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-msm8960.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,9 @@
 #define P_PLL8	1
 #define P_PLL2	2
 #define P_PLL3	3
+#define P_PLL15	3
+
+#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
 
 static u8 mmcc_pxo_pll8_pll2_map[] = {
 	[P_PXO]		= 0,
@@ -57,10 +60,24 @@ static u8 mmcc_pxo_pll8_pll2_pll3_map[]
 	[P_PLL3]	= 3,
 };
 
-static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+static const char *mmcc_pxo_pll8_pll2_pll15[] = {
 	"pxo",
+	"pll8_vote",
 	"pll2",
+	"pll15",
+};
+
+static u8 mmcc_pxo_pll8_pll2_pll15_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 2,
+	[P_PLL2]	= 1,
+	[P_PLL15]	= 3,
+};
+
+static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+	"pxo",
 	"pll8_vote",
+	"pll2",
 	"pll3",
 };
 
@@ -80,6 +97,36 @@ static struct clk_pll pll2 = {
 	},
 };
 
+static struct clk_pll pll15 = {
+	.l_reg = 0x33c,
+	.m_reg = 0x340,
+	.n_reg = 0x344,
+	.config_reg = 0x348,
+	.mode_reg = 0x338,
+	.status_reg = 0x350,
+	.status_bit = 16,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pll15",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static const struct pll_config pll15_config = {
+	.l = 33,
+	.m = 1,
+	.n = 3,
+	.vco_val = 0x2 << 16,
+	.vco_mask = 0x3 << 16,
+	.pre_div_val = 0x0,
+	.pre_div_mask = BIT(19),
+	.post_div_val = 0x0,
+	.post_div_mask = 0x3 << 20,
+	.mn_ena_mask = BIT(22),
+	.main_output_mask = BIT(23),
+};
+
 static struct freq_tbl clk_tbl_cam[] = {
 	{   6000000, P_PLL8, 4, 1, 16 },
 	{   8000000, P_PLL8, 4, 1, 12 },
@@ -710,18 +757,18 @@ static struct clk_branch csiphy2_timer_c
 };
 
 static struct freq_tbl clk_tbl_gfx2d[] = {
-	{  27000000, P_PXO,  1,  0 },
-	{  48000000, P_PLL8, 1,  8 },
-	{  54857000, P_PLL8, 1,  7 },
-	{  64000000, P_PLL8, 1,  6 },
-	{  76800000, P_PLL8, 1,  5 },
-	{  96000000, P_PLL8, 1,  4 },
-	{ 128000000, P_PLL8, 1,  3 },
-	{ 145455000, P_PLL2, 2, 11 },
-	{ 160000000, P_PLL2, 1,  5 },
-	{ 177778000, P_PLL2, 2,  9 },
-	{ 200000000, P_PLL2, 1,  4 },
-	{ 228571000, P_PLL2, 2,  7 },
+	F_MN( 27000000, P_PXO,  1,  0),
+	F_MN( 48000000, P_PLL8, 1,  8),
+	F_MN( 54857000, P_PLL8, 1,  7),
+	F_MN( 64000000, P_PLL8, 1,  6),
+	F_MN( 76800000, P_PLL8, 1,  5),
+	F_MN( 96000000, P_PLL8, 1,  4),
+	F_MN(128000000, P_PLL8, 1,  3),
+	F_MN(145455000, P_PLL2, 2, 11),
+	F_MN(160000000, P_PLL2, 1,  5),
+	F_MN(177778000, P_PLL2, 2,  9),
+	F_MN(200000000, P_PLL2, 1,  4),
+	F_MN(228571000, P_PLL2, 2,  7),
 	{ }
 };
 
@@ -842,22 +889,43 @@ static struct clk_branch gfx2d1_clk = {
 };
 
 static struct freq_tbl clk_tbl_gfx3d[] = {
-	{  27000000, P_PXO,  1,  0 },
-	{  48000000, P_PLL8, 1,  8 },
-	{  54857000, P_PLL8, 1,  7 },
-	{  64000000, P_PLL8, 1,  6 },
-	{  76800000, P_PLL8, 1,  5 },
-	{  96000000, P_PLL8, 1,  4 },
-	{ 128000000, P_PLL8, 1,  3 },
-	{ 145455000, P_PLL2, 2, 11 },
-	{ 160000000, P_PLL2, 1,  5 },
-	{ 177778000, P_PLL2, 2,  9 },
-	{ 200000000, P_PLL2, 1,  4 },
-	{ 228571000, P_PLL2, 2,  7 },
-	{ 266667000, P_PLL2, 1,  3 },
-	{ 300000000, P_PLL3, 1,  4 },
-	{ 320000000, P_PLL2, 2,  5 },
-	{ 400000000, P_PLL2, 1,  2 },
+	F_MN( 27000000, P_PXO,  1,  0),
+	F_MN( 48000000, P_PLL8, 1,  8),
+	F_MN( 54857000, P_PLL8, 1,  7),
+	F_MN( 64000000, P_PLL8, 1,  6),
+	F_MN( 76800000, P_PLL8, 1,  5),
+	F_MN( 96000000, P_PLL8, 1,  4),
+	F_MN(128000000, P_PLL8, 1,  3),
+	F_MN(145455000, P_PLL2, 2, 11),
+	F_MN(160000000, P_PLL2, 1,  5),
+	F_MN(177778000, P_PLL2, 2,  9),
+	F_MN(200000000, P_PLL2, 1,  4),
+	F_MN(228571000, P_PLL2, 2,  7),
+	F_MN(266667000, P_PLL2, 1,  3),
+	F_MN(300000000, P_PLL3, 1,  4),
+	F_MN(320000000, P_PLL2, 2,  5),
+	F_MN(400000000, P_PLL2, 1,  2),
+	{ }
+};
+
+static struct freq_tbl clk_tbl_gfx3d_8064[] = {
+	F_MN( 27000000, P_PXO,   0,  0),
+	F_MN( 48000000, P_PLL8,  1,  8),
+	F_MN( 54857000, P_PLL8,  1,  7),
+	F_MN( 64000000, P_PLL8,  1,  6),
+	F_MN( 76800000, P_PLL8,  1,  5),
+	F_MN( 96000000, P_PLL8,  1,  4),
+	F_MN(128000000, P_PLL8,  1,  3),
+	F_MN(145455000, P_PLL2,  2, 11),
+	F_MN(160000000, P_PLL2,  1,  5),
+	F_MN(177778000, P_PLL2,  2,  9),
+	F_MN(192000000, P_PLL8,  1,  2),
+	F_MN(200000000, P_PLL2,  1,  4),
+	F_MN(228571000, P_PLL2,  2,  7),
+	F_MN(266667000, P_PLL2,  1,  3),
+	F_MN(320000000, P_PLL2,  2,  5),
+	F_MN(400000000, P_PLL2,  1,  2),
+	F_MN(450000000, P_PLL15, 1,  2),
 	{ }
 };
 
@@ -897,12 +965,19 @@ static struct clk_dyn_rcg gfx3d_src = {
 		.hw.init = &(struct clk_init_data){
 			.name = "gfx3d_src",
 			.parent_names = mmcc_pxo_pll8_pll2_pll3,
-			.num_parents = 3,
+			.num_parents = 4,
 			.ops = &clk_dyn_rcg_ops,
 		},
 	},
 };
 
+static const struct clk_init_data gfx3d_8064_init = {
+	.name = "gfx3d_src",
+	.parent_names = mmcc_pxo_pll8_pll2_pll15,
+	.num_parents = 4,
+	.ops = &clk_dyn_rcg_ops,
+};
+
 static struct clk_branch gfx3d_clk = {
 	.halt_reg = 0x01c8,
 	.halt_bit = 4,
@@ -919,6 +994,91 @@ static struct clk_branch gfx3d_clk = {
 	},
 };
 
+static struct freq_tbl clk_tbl_vcap[] = {
+	F_MN( 27000000, P_PXO,  0,  0),
+	F_MN( 54860000, P_PLL8, 1,  7),
+	F_MN( 64000000, P_PLL8, 1,  6),
+	F_MN( 76800000, P_PLL8, 1,  5),
+	F_MN(128000000, P_PLL8, 1,  3),
+	F_MN(160000000, P_PLL2, 1,  5),
+	F_MN(200000000, P_PLL2, 1,  4),
+	{ }
+};
+
+static struct clk_dyn_rcg vcap_src = {
+	.ns_reg = 0x021c,
+	.md_reg[0] = 0x01ec,
+	.md_reg[1] = 0x0218,
+	.mn[0] = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 23,
+		.mnctr_mode_shift = 9,
+		.n_val_shift = 18,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 22,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 14,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.s[0] = {
+		.src_sel_shift = 3,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 11,
+	.freq_tbl = clk_tbl_vcap,
+	.clkr = {
+		.enable_reg = 0x0178,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "vcap_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch vcap_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 15,
+	.clkr = {
+		.enable_reg = 0x0178,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "vcap_clk",
+			.parent_names = (const char *[]){ "vcap_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch vcap_npl_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 25,
+	.clkr = {
+		.enable_reg = 0x0178,
+		.enable_mask = BIT(13),
+		.hw.init = &(struct clk_init_data){
+			.name = "vcap_npl_clk",
+			.parent_names = (const char *[]){ "vcap_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
 static struct freq_tbl clk_tbl_ijpeg[] = {
 	{  27000000, P_PXO,  1, 0,  0 },
 	{  36570000, P_PLL8, 1, 2, 21 },
@@ -995,7 +1155,7 @@ static struct clk_rcg jpegd_src = {
 	.ns_reg = 0x00ac,
 	.p = {
 		.pre_div_shift = 12,
-		.pre_div_width = 2,
+		.pre_div_width = 4,
 	},
 	.s = {
 		.src_sel_shift = 0,
@@ -1115,7 +1275,7 @@ static struct clk_branch mdp_lut_clk = {
 		.enable_reg = 0x016c,
 		.enable_mask = BIT(0),
 		.hw.init = &(struct clk_init_data){
-			.parent_names = (const char *[]){ "mdp_clk" },
+			.parent_names = (const char *[]){ "mdp_src" },
 			.num_parents = 1,
 			.name = "mdp_lut_clk",
 			.ops = &clk_branch_ops,
@@ -1218,12 +1378,7 @@ static const char *mmcc_pxo_hdmi[] = {
 };
 
 static struct freq_tbl clk_tbl_tv[] = {
-	{  25200000, P_HDMI_PLL, 1, 0, 0 },
-	{  27000000, P_HDMI_PLL, 1, 0, 0 },
-	{  27030000, P_HDMI_PLL, 1, 0, 0 },
-	{  74250000, P_HDMI_PLL, 1, 0, 0 },
-	{ 108000000, P_HDMI_PLL, 1, 0, 0 },
-	{ 148500000, P_HDMI_PLL, 1, 0, 0 },
+	{  .src = P_HDMI_PLL, .pre_div = 1 },
 	{ }
 };
 
@@ -1254,7 +1409,7 @@ static struct clk_rcg tv_src = {
 			.name = "tv_src",
 			.parent_names = mmcc_pxo_hdmi,
 			.num_parents = 2,
-			.ops = &clk_rcg_ops,
+			.ops = &clk_rcg_bypass_ops,
 			.flags = CLK_SET_RATE_PARENT,
 		},
 	},
@@ -1326,6 +1481,38 @@ static struct clk_branch hdmi_tv_clk = {
 	},
 };
 
+static struct clk_branch rgb_tv_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 27,
+	.clkr = {
+		.enable_reg = 0x0124,
+		.enable_mask = BIT(14),
+		.hw.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "rgb_tv_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch npl_tv_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 26,
+	.clkr = {
+		.enable_reg = 0x0124,
+		.enable_mask = BIT(16),
+		.hw.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "npl_tv_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
 static struct clk_branch hdmi_app_clk = {
 	.halt_reg = 0x01cc,
 	.halt_bit = 25,
@@ -1342,15 +1529,15 @@ static struct clk_branch hdmi_app_clk =
 };
 
 static struct freq_tbl clk_tbl_vcodec[] = {
-	{  27000000, P_PXO,  1,  0 },
-	{  32000000, P_PLL8, 1, 12 },
-	{  48000000, P_PLL8, 1,  8 },
-	{  54860000, P_PLL8, 1,  7 },
-	{  96000000, P_PLL8, 1,  4 },
-	{ 133330000, P_PLL2, 1,  6 },
-	{ 200000000, P_PLL2, 1,  4 },
-	{ 228570000, P_PLL2, 2,  7 },
-	{ 266670000, P_PLL2, 1,  3 },
+	F_MN( 27000000, P_PXO,  1,  0),
+	F_MN( 32000000, P_PLL8, 1, 12),
+	F_MN( 48000000, P_PLL8, 1,  8),
+	F_MN( 54860000, P_PLL8, 1,  7),
+	F_MN( 96000000, P_PLL8, 1,  4),
+	F_MN(133330000, P_PLL2, 1,  6),
+	F_MN(200000000, P_PLL2, 1,  4),
+	F_MN(228570000, P_PLL2, 2,  7),
+	F_MN(266670000, P_PLL2, 1,  3),
 	{ }
 };
 
@@ -1701,6 +1888,22 @@ static struct clk_branch rot_axi_clk = {
 	},
 };
 
+static struct clk_branch vcap_axi_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 20,
+	.hwcg_reg = 0x0244,
+	.hwcg_bit = 11,
+	.clkr = {
+		.enable_reg = 0x0244,
+		.enable_mask = BIT(12),
+		.hw.init = &(struct clk_init_data){
+			.name = "vcap_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
 static struct clk_branch vpe_axi_clk = {
 	.hwcg_reg = 0x0020,
 	.hwcg_bit = 27,
@@ -2003,6 +2206,20 @@ static struct clk_branch tv_enc_ahb_clk
 	},
 };
 
+static struct clk_branch vcap_ahb_clk = {
+	.halt_reg = 0x0240,
+	.halt_bit = 23,
+	.clkr = {
+		.enable_reg = 0x0248,
+		.enable_mask = BIT(1),
+		.hw.init = &(struct clk_init_data){
+			.name = "vcap_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
 static struct clk_branch vcodec_ahb_clk = {
 	.hwcg_reg = 0x0038,
 	.hwcg_bit = 26,
@@ -2215,6 +2432,175 @@ static const struct qcom_reset_map mmcc_
 	[CSI_RDI2_RESET] = { 0x0214 },
 };
 
+static struct clk_regmap *mmcc_apq8064_clks[] = {
+	[AMP_AHB_CLK] = &amp_ahb_clk.clkr,
+	[DSI2_S_AHB_CLK] = &dsi2_s_ahb_clk.clkr,
+	[JPEGD_AHB_CLK] = &jpegd_ahb_clk.clkr,
+	[DSI_S_AHB_CLK] = &dsi_s_ahb_clk.clkr,
+	[DSI2_M_AHB_CLK] = &dsi2_m_ahb_clk.clkr,
+	[VPE_AHB_CLK] = &vpe_ahb_clk.clkr,
+	[SMMU_AHB_CLK] = &smmu_ahb_clk.clkr,
+	[HDMI_M_AHB_CLK] = &hdmi_m_ahb_clk.clkr,
+	[VFE_AHB_CLK] = &vfe_ahb_clk.clkr,
+	[ROT_AHB_CLK] = &rot_ahb_clk.clkr,
+	[VCODEC_AHB_CLK] = &vcodec_ahb_clk.clkr,
+	[MDP_AHB_CLK] = &mdp_ahb_clk.clkr,
+	[DSI_M_AHB_CLK] = &dsi_m_ahb_clk.clkr,
+	[CSI_AHB_CLK] = &csi_ahb_clk.clkr,
+	[MMSS_IMEM_AHB_CLK] = &mmss_imem_ahb_clk.clkr,
+	[IJPEG_AHB_CLK] = &ijpeg_ahb_clk.clkr,
+	[HDMI_S_AHB_CLK] = &hdmi_s_ahb_clk.clkr,
+	[GFX3D_AHB_CLK] = &gfx3d_ahb_clk.clkr,
+	[JPEGD_AXI_CLK] = &jpegd_axi_clk.clkr,
+	[GMEM_AXI_CLK] = &gmem_axi_clk.clkr,
+	[MDP_AXI_CLK] = &mdp_axi_clk.clkr,
+	[MMSS_IMEM_AXI_CLK] = &mmss_imem_axi_clk.clkr,
+	[IJPEG_AXI_CLK] = &ijpeg_axi_clk.clkr,
+	[GFX3D_AXI_CLK] = &gfx3d_axi_clk.clkr,
+	[VCODEC_AXI_CLK] = &vcodec_axi_clk.clkr,
+	[VFE_AXI_CLK] = &vfe_axi_clk.clkr,
+	[VPE_AXI_CLK] = &vpe_axi_clk.clkr,
+	[ROT_AXI_CLK] = &rot_axi_clk.clkr,
+	[VCODEC_AXI_A_CLK] = &vcodec_axi_a_clk.clkr,
+	[VCODEC_AXI_B_CLK] = &vcodec_axi_b_clk.clkr,
+	[CSI0_SRC] = &csi0_src.clkr,
+	[CSI0_CLK] = &csi0_clk.clkr,
+	[CSI0_PHY_CLK] = &csi0_phy_clk.clkr,
+	[CSI1_SRC] = &csi1_src.clkr,
+	[CSI1_CLK] = &csi1_clk.clkr,
+	[CSI1_PHY_CLK] = &csi1_phy_clk.clkr,
+	[CSI2_SRC] = &csi2_src.clkr,
+	[CSI2_CLK] = &csi2_clk.clkr,
+	[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+	[CSI_PIX_CLK] = &csi_pix_clk.clkr,
+	[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
+	[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
+	[HDMI_APP_CLK] = &hdmi_app_clk.clkr,
+	[CSI_PIX1_CLK] = &csi_pix1_clk.clkr,
+	[CSI_RDI2_CLK] = &csi_rdi2_clk.clkr,
+	[CSI_RDI1_CLK] = &csi_rdi1_clk.clkr,
+	[GFX3D_SRC] = &gfx3d_src.clkr,
+	[GFX3D_CLK] = &gfx3d_clk.clkr,
+	[IJPEG_SRC] = &ijpeg_src.clkr,
+	[IJPEG_CLK] = &ijpeg_clk.clkr,
+	[JPEGD_SRC] = &jpegd_src.clkr,
+	[JPEGD_CLK] = &jpegd_clk.clkr,
+	[MDP_SRC] = &mdp_src.clkr,
+	[MDP_CLK] = &mdp_clk.clkr,
+	[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+	[ROT_SRC] = &rot_src.clkr,
+	[ROT_CLK] = &rot_clk.clkr,
+	[TV_DAC_CLK] = &tv_dac_clk.clkr,
+	[HDMI_TV_CLK] = &hdmi_tv_clk.clkr,
+	[MDP_TV_CLK] = &mdp_tv_clk.clkr,
+	[TV_SRC] = &tv_src.clkr,
+	[VCODEC_SRC] = &vcodec_src.clkr,
+	[VCODEC_CLK] = &vcodec_clk.clkr,
+	[VFE_SRC] = &vfe_src.clkr,
+	[VFE_CLK] = &vfe_clk.clkr,
+	[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
+	[VPE_SRC] = &vpe_src.clkr,
+	[VPE_CLK] = &vpe_clk.clkr,
+	[CAMCLK0_SRC] = &camclk0_src.clkr,
+	[CAMCLK0_CLK] = &camclk0_clk.clkr,
+	[CAMCLK1_SRC] = &camclk1_src.clkr,
+	[CAMCLK1_CLK] = &camclk1_clk.clkr,
+	[CAMCLK2_SRC] = &camclk2_src.clkr,
+	[CAMCLK2_CLK] = &camclk2_clk.clkr,
+	[CSIPHYTIMER_SRC] = &csiphytimer_src.clkr,
+	[CSIPHY2_TIMER_CLK] = &csiphy2_timer_clk.clkr,
+	[CSIPHY1_TIMER_CLK] = &csiphy1_timer_clk.clkr,
+	[CSIPHY0_TIMER_CLK] = &csiphy0_timer_clk.clkr,
+	[PLL2] = &pll2.clkr,
+	[RGB_TV_CLK] = &rgb_tv_clk.clkr,
+	[NPL_TV_CLK] = &npl_tv_clk.clkr,
+	[VCAP_AHB_CLK] = &vcap_ahb_clk.clkr,
+	[VCAP_AXI_CLK] = &vcap_axi_clk.clkr,
+	[VCAP_SRC] = &vcap_src.clkr,
+	[VCAP_CLK] = &vcap_clk.clkr,
+	[VCAP_NPL_CLK] = &vcap_npl_clk.clkr,
+	[PLL15] = &pll15.clkr,
+};
+
+static const struct qcom_reset_map mmcc_apq8064_resets[] = {
+	[GFX3D_AXI_RESET] = { 0x0208, 17 },
+	[VCAP_AXI_RESET] = { 0x0208, 16 },
+	[VPE_AXI_RESET] = { 0x0208, 15 },
+	[IJPEG_AXI_RESET] = { 0x0208, 14 },
+	[MPD_AXI_RESET] = { 0x0208, 13 },
+	[VFE_AXI_RESET] = { 0x0208, 9 },
+	[SP_AXI_RESET] = { 0x0208, 8 },
+	[VCODEC_AXI_RESET] = { 0x0208, 7 },
+	[ROT_AXI_RESET] = { 0x0208, 6 },
+	[VCODEC_AXI_A_RESET] = { 0x0208, 5 },
+	[VCODEC_AXI_B_RESET] = { 0x0208, 4 },
+	[FAB_S3_AXI_RESET] = { 0x0208, 3 },
+	[FAB_S2_AXI_RESET] = { 0x0208, 2 },
+	[FAB_S1_AXI_RESET] = { 0x0208, 1 },
+	[FAB_S0_AXI_RESET] = { 0x0208 },
+	[SMMU_GFX3D_ABH_RESET] = { 0x020c, 31 },
+	[SMMU_VPE_AHB_RESET] = { 0x020c, 30 },
+	[SMMU_VFE_AHB_RESET] = { 0x020c, 29 },
+	[SMMU_ROT_AHB_RESET] = { 0x020c, 28 },
+	[SMMU_VCODEC_B_AHB_RESET] = { 0x020c, 27 },
+	[SMMU_VCODEC_A_AHB_RESET] = { 0x020c, 26 },
+	[SMMU_MDP1_AHB_RESET] = { 0x020c, 25 },
+	[SMMU_MDP0_AHB_RESET] = { 0x020c, 24 },
+	[SMMU_JPEGD_AHB_RESET] = { 0x020c, 23 },
+	[SMMU_IJPEG_AHB_RESET] = { 0x020c, 22 },
+	[APU_AHB_RESET] = { 0x020c, 18 },
+	[CSI_AHB_RESET] = { 0x020c, 17 },
+	[TV_ENC_AHB_RESET] = { 0x020c, 15 },
+	[VPE_AHB_RESET] = { 0x020c, 14 },
+	[FABRIC_AHB_RESET] = { 0x020c, 13 },
+	[GFX3D_AHB_RESET] = { 0x020c, 10 },
+	[HDMI_AHB_RESET] = { 0x020c, 9 },
+	[MSSS_IMEM_AHB_RESET] = { 0x020c, 8 },
+	[IJPEG_AHB_RESET] = { 0x020c, 7 },
+	[DSI_M_AHB_RESET] = { 0x020c, 6 },
+	[DSI_S_AHB_RESET] = { 0x020c, 5 },
+	[JPEGD_AHB_RESET] = { 0x020c, 4 },
+	[MDP_AHB_RESET] = { 0x020c, 3 },
+	[ROT_AHB_RESET] = { 0x020c, 2 },
+	[VCODEC_AHB_RESET] = { 0x020c, 1 },
+	[VFE_AHB_RESET] = { 0x020c, 0 },
+	[SMMU_VCAP_AHB_RESET] = { 0x0200, 3 },
+	[VCAP_AHB_RESET] = { 0x0200, 2 },
+	[DSI2_M_AHB_RESET] = { 0x0200, 1 },
+	[DSI2_S_AHB_RESET] = { 0x0200, 0 },
+	[CSIPHY2_RESET] = { 0x0210, 31 },
+	[CSI_PIX1_RESET] = { 0x0210, 30 },
+	[CSIPHY0_RESET] = { 0x0210, 29 },
+	[CSIPHY1_RESET] = { 0x0210, 28 },
+	[CSI_RDI_RESET] = { 0x0210, 27 },
+	[CSI_PIX_RESET] = { 0x0210, 26 },
+	[DSI2_RESET] = { 0x0210, 25 },
+	[VFE_CSI_RESET] = { 0x0210, 24 },
+	[MDP_RESET] = { 0x0210, 21 },
+	[AMP_RESET] = { 0x0210, 20 },
+	[JPEGD_RESET] = { 0x0210, 19 },
+	[CSI1_RESET] = { 0x0210, 18 },
+	[VPE_RESET] = { 0x0210, 17 },
+	[MMSS_FABRIC_RESET] = { 0x0210, 16 },
+	[VFE_RESET] = { 0x0210, 15 },
+	[GFX3D_RESET] = { 0x0210, 12 },
+	[HDMI_RESET] = { 0x0210, 11 },
+	[MMSS_IMEM_RESET] = { 0x0210, 10 },
+	[IJPEG_RESET] = { 0x0210, 9 },
+	[CSI0_RESET] = { 0x0210, 8 },
+	[DSI_RESET] = { 0x0210, 7 },
+	[VCODEC_RESET] = { 0x0210, 6 },
+	[MDP_TV_RESET] = { 0x0210, 4 },
+	[MDP_VSYNC_RESET] = { 0x0210, 3 },
+	[ROT_RESET] = { 0x0210, 2 },
+	[TV_HDMI_RESET] = { 0x0210, 1 },
+	[VCAP_NPL_RESET] = { 0x0214, 4 },
+	[VCAP_RESET] = { 0x0214, 3 },
+	[CSI2_RESET] = { 0x0214, 2 },
+	[CSI_RDI1_RESET] = { 0x0214, 1 },
+	[CSI_RDI2_RESET] = { 0x0214 },
+};
+
 static const struct regmap_config mmcc_msm8960_regmap_config = {
 	.reg_bits	= 32,
 	.reg_stride	= 4,
@@ -2223,6 +2609,14 @@ static const struct regmap_config mmcc_m
 	.fast_io	= true,
 };
 
+static const struct regmap_config mmcc_apq8064_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x350,
+	.fast_io	= true,
+};
+
 static const struct qcom_cc_desc mmcc_msm8960_desc = {
 	.config = &mmcc_msm8960_regmap_config,
 	.clks = mmcc_msm8960_clks,
@@ -2231,15 +2625,47 @@ static const struct qcom_cc_desc mmcc_ms
 	.num_resets = ARRAY_SIZE(mmcc_msm8960_resets),
 };
 
+static const struct qcom_cc_desc mmcc_apq8064_desc = {
+	.config = &mmcc_apq8064_regmap_config,
+	.clks = mmcc_apq8064_clks,
+	.num_clks = ARRAY_SIZE(mmcc_apq8064_clks),
+	.resets = mmcc_apq8064_resets,
+	.num_resets = ARRAY_SIZE(mmcc_apq8064_resets),
+};
+
 static const struct of_device_id mmcc_msm8960_match_table[] = {
-	{ .compatible = "qcom,mmcc-msm8960" },
+	{ .compatible = "qcom,mmcc-msm8960", .data = &mmcc_msm8960_desc },
+	{ .compatible = "qcom,mmcc-apq8064", .data = &mmcc_apq8064_desc },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
 
 static int mmcc_msm8960_probe(struct platform_device *pdev)
 {
-	return qcom_cc_probe(pdev, &mmcc_msm8960_desc);
+	const struct of_device_id *match;
+	struct regmap *regmap;
+	bool is_8064;
+	struct device *dev = &pdev->dev;
+
+	match = of_match_device(mmcc_msm8960_match_table, dev);
+	if (!match)
+		return -EINVAL;
+
+	is_8064 = of_device_is_compatible(dev->of_node, "qcom,mmcc-apq8064");
+	if (is_8064) {
+		gfx3d_src.freq_tbl = clk_tbl_gfx3d_8064;
+		gfx3d_src.clkr.hw.init = &gfx3d_8064_init;
+		gfx3d_src.s[0].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
+		gfx3d_src.s[1].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
+	}
+
+	regmap = qcom_cc_map(pdev, match->data);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	clk_pll_configure_sr(&pll15, regmap, &pll15_config, false);
+
+	return qcom_cc_really_probe(pdev, match->data, regmap);
 }
 
 static int mmcc_msm8960_remove(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-msm8974.c linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-msm8974.c
--- linux-libre-3.16-gnu/drivers/clk/qcom/mmcc-msm8974.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/qcom/mmcc-msm8974.c	2014-09-28 17:29:07.000000000 -0400
@@ -2547,18 +2547,16 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_mat
 
 static int mmcc_msm8974_probe(struct platform_device *pdev)
 {
-	int ret;
 	struct regmap *regmap;
 
-	ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc);
-	if (ret)
-		return ret;
+	regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
 
-	regmap = dev_get_regmap(&pdev->dev, NULL);
 	clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
 	clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
 
-	return 0;
+	return qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
 }
 
 static int mmcc_msm8974_remove(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/clk.c linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk.c
--- linux-libre-3.16-gnu/drivers/clk/rockchip/clk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on
+ *
+ * samsung/clk.c
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include "clk.h"
+
+/**
+ * Register a clock branch.
+ * Most clock branches have a form like
+ *
+ * src1 --|--\
+ *        |M |--[GATE]-[DIV]-
+ * src2 --|--/
+ *
+ * sometimes without one of those components.
+ */
+struct clk *rockchip_clk_register_branch(const char *name,
+		const char **parent_names, u8 num_parents, void __iomem *base,
+		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
+		u8 div_shift, u8 div_width, u8 div_flags,
+		struct clk_div_table *div_table, int gate_offset,
+		u8 gate_shift, u8 gate_flags, unsigned long flags,
+		spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_divider *div = NULL;
+	const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
+			     *gate_ops = NULL;
+
+	if (num_parents > 1) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = base + muxdiv_offset;
+		mux->shift = mux_shift;
+		mux->mask = BIT(mux_width) - 1;
+		mux->flags = mux_flags;
+		mux->lock = lock;
+		mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
+							: &clk_mux_ops;
+	}
+
+	if (gate_offset >= 0) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate)
+			return ERR_PTR(-ENOMEM);
+
+		gate->flags = gate_flags;
+		gate->reg = base + gate_offset;
+		gate->bit_idx = gate_shift;
+		gate->lock = lock;
+		gate_ops = &clk_gate_ops;
+	}
+
+	if (div_width > 0) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			return ERR_PTR(-ENOMEM);
+
+		div->flags = div_flags;
+		div->reg = base + muxdiv_offset;
+		div->shift = div_shift;
+		div->width = div_width;
+		div->lock = lock;
+		div->table = div_table;
+		div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
+						? &clk_divider_ro_ops
+						: &clk_divider_ops;
+	}
+
+	clk = clk_register_composite(NULL, name, parent_names, num_parents,
+				     mux ? &mux->hw : NULL, mux_ops,
+				     div ? &div->hw : NULL, div_ops,
+				     gate ? &gate->hw : NULL, gate_ops,
+				     flags);
+
+	return clk;
+}
+
+static DEFINE_SPINLOCK(clk_lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+static struct clk_onecell_data clk_data;
+static struct device_node *cru_node;
+static struct regmap *grf;
+
+void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
+			      unsigned long nr_clks)
+{
+	reg_base = base;
+	cru_node = np;
+	grf = ERR_PTR(-EPROBE_DEFER);
+
+	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
+	if (!clk_table)
+		pr_err("%s: could not allocate clock lookup table\n", __func__);
+
+	clk_data.clks = clk_table;
+	clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+struct regmap *rockchip_clk_get_grf(void)
+{
+	if (IS_ERR(grf))
+		grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf");
+	return grf;
+}
+
+void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+	if (clk_table && id)
+		clk_table[id] = clk;
+}
+
+void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
+				unsigned int nr_pll, int grf_lock_offset)
+{
+	struct clk *clk;
+	int idx;
+
+	for (idx = 0; idx < nr_pll; idx++, list++) {
+		clk = rockchip_clk_register_pll(list->type, list->name,
+				list->parent_names, list->num_parents,
+				reg_base, list->con_offset, grf_lock_offset,
+				list->lock_shift, list->mode_offset,
+				list->mode_shift, list->rate_table, &clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		rockchip_clk_add_lookup(clk, list->id);
+	}
+}
+
+void __init rockchip_clk_register_branches(
+				      struct rockchip_clk_branch *list,
+				      unsigned int nr_clk)
+{
+	struct clk *clk = NULL;
+	unsigned int idx;
+	unsigned long flags;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		flags = list->flags;
+
+		/* catch simple muxes */
+		switch (list->branch_type) {
+		case branch_mux:
+			clk = clk_register_mux(NULL, list->name,
+				list->parent_names, list->num_parents,
+				flags, reg_base + list->muxdiv_offset,
+				list->mux_shift, list->mux_width,
+				list->mux_flags, &clk_lock);
+			break;
+		case branch_divider:
+			if (list->div_table)
+				clk = clk_register_divider_table(NULL,
+					list->name, list->parent_names[0],
+					flags, reg_base + list->muxdiv_offset,
+					list->div_shift, list->div_width,
+					list->div_flags, list->div_table,
+					&clk_lock);
+			else
+				clk = clk_register_divider(NULL, list->name,
+					list->parent_names[0], flags,
+					reg_base + list->muxdiv_offset,
+					list->div_shift, list->div_width,
+					list->div_flags, &clk_lock);
+			break;
+		case branch_fraction_divider:
+			/* unimplemented */
+			continue;
+			break;
+		case branch_gate:
+			flags |= CLK_SET_RATE_PARENT;
+
+			/* keep all gates untouched for now */
+			flags |= CLK_IGNORE_UNUSED;
+
+			clk = clk_register_gate(NULL, list->name,
+				list->parent_names[0], flags,
+				reg_base + list->gate_offset,
+				list->gate_shift, list->gate_flags, &clk_lock);
+			break;
+		case branch_composite:
+			/* keep all gates untouched for now */
+			flags |= CLK_IGNORE_UNUSED;
+
+			clk = rockchip_clk_register_branch(list->name,
+				list->parent_names, list->num_parents,
+				reg_base, list->muxdiv_offset, list->mux_shift,
+				list->mux_width, list->mux_flags,
+				list->div_shift, list->div_width,
+				list->div_flags, list->div_table,
+				list->gate_offset, list->gate_shift,
+				list->gate_flags, flags, &clk_lock);
+			break;
+		}
+
+		/* none of the cases above matched */
+		if (!clk) {
+			pr_err("%s: unknown clock type %d\n",
+			       __func__, list->branch_type);
+			continue;
+		}
+
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s: %ld\n",
+			       __func__, list->name, PTR_ERR(clk));
+			continue;
+		}
+
+		rockchip_clk_add_lookup(clk, list->id);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/clk.h linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk.h
--- linux-libre-3.16-gnu/drivers/clk/rockchip/clk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on
+ *
+ * samsung/clk.h
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef CLK_ROCKCHIP_CLK_H
+#define CLK_ROCKCHIP_CLK_H
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define HIWORD_UPDATE(val, mask, shift) \
+		((val) << (shift) | (mask) << ((shift) + 16))
+
+/* register positions shared by RK2928, RK3066 and RK3188 */
+#define RK2928_PLL_CON(x)		(x * 0x4)
+#define RK2928_MODE_CON		0x40
+#define RK2928_CLKSEL_CON(x)	(x * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x)	(x * 0x4 + 0xd0)
+#define RK2928_GLB_SRST_FST		0x100
+#define RK2928_GLB_SRST_SND		0x104
+#define RK2928_SOFTRST_CON(x)	(x * 0x4 + 0x110)
+#define RK2928_MISC_CON		0x134
+
+#define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3288_MODE_CON			0x50
+#define RK3288_CLKSEL_CON(x)		(x * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x)		(x * 0x4 + 0x160)
+#define RK3288_GLB_SRST_FST		0x1b0
+#define RK3288_GLB_SRST_SND		0x1b4
+#define RK3288_SOFTRST_CON(x)		(x * 0x4 + 0x1b8)
+#define RK3288_MISC_CON			0x1e8
+
+enum rockchip_pll_type {
+	pll_rk3066,
+};
+
+#define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
+{						\
+	.rate	= _rate##U,			\
+	.nr = _nr,				\
+	.nf = _nf,				\
+	.no = _no,				\
+	.bwadj = (_nf >> 1),			\
+}
+
+struct rockchip_pll_rate_table {
+	unsigned long rate;
+	unsigned int nr;
+	unsigned int nf;
+	unsigned int no;
+	unsigned int bwadj;
+};
+
+/**
+ * struct rockchip_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @mode_offset: offset of the register for configuring the PLL-mode.
+ * @mode_shift: offset inside the mode-register for the mode of this pll.
+ * @lock_shift: offset inside the lock register for the lock status.
+ * @type: Type of PLL to be registered.
+ * @rate_table: Table of usable pll rates
+ */
+struct rockchip_pll_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	int			con_offset;
+	int			mode_offset;
+	int			mode_shift;
+	int			lock_shift;
+	enum rockchip_pll_type	type;
+	struct rockchip_pll_rate_table *rate_table;
+};
+
+#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift,	\
+		_lshift, _rtable)					\
+	{								\
+		.id		= _id,					\
+		.type		= _type,				\
+		.name		= _name,				\
+		.parent_names	= _pnames,				\
+		.num_parents	= ARRAY_SIZE(_pnames),			\
+		.flags		= CLK_GET_RATE_NOCACHE | _flags,	\
+		.con_offset	= _con,					\
+		.mode_offset	= _mode,				\
+		.mode_shift	= _mshift,				\
+		.lock_shift	= _lshift,				\
+		.rate_table	= _rtable,				\
+	}
+
+struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+		const char *name, const char **parent_names, u8 num_parents,
+		void __iomem *base, int con_offset, int grf_lock_offset,
+		int lock_shift, int reg_mode, int mode_shift,
+		struct rockchip_pll_rate_table *rate_table,
+		spinlock_t *lock);
+
+#define PNAME(x) static const char *x[] __initconst
+
+enum rockchip_clk_branch_type {
+	branch_composite,
+	branch_mux,
+	branch_divider,
+	branch_fraction_divider,
+	branch_gate,
+};
+
+struct rockchip_clk_branch {
+	unsigned int			id;
+	enum rockchip_clk_branch_type	branch_type;
+	const char			*name;
+	const char			**parent_names;
+	u8				num_parents;
+	unsigned long			flags;
+	int				muxdiv_offset;
+	u8				mux_shift;
+	u8				mux_width;
+	u8				mux_flags;
+	u8				div_shift;
+	u8				div_width;
+	u8				div_flags;
+	struct clk_div_table		*div_table;
+	int				gate_offset;
+	u8				gate_shift;
+	u8				gate_flags;
+};
+
+#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
+		  df, go, gs, gf)				\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
+#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,	\
+			go, gs, gf)				\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
+#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
+			       df, dt, go, gs, gf)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.div_table	= dt,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
+#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf,	\
+			go, gs, gf)				\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
+#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf,	\
+			 ds, dw, df)				\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.gate_offset	= -1,				\
+	}
+
+#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_fraction_divider,	\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= 16,				\
+		.div_width	= 16,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
+#define MUX(_id, cname, pnames, f, o, s, w, mf)			\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_mux,			\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= o,				\
+		.mux_shift	= s,				\
+		.mux_width	= w,				\
+		.mux_flags	= mf,				\
+		.gate_offset	= -1,				\
+	}
+
+#define DIV(_id, cname, pname, f, o, s, w, df)			\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_divider,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= o,				\
+		.div_shift	= s,				\
+		.div_width	= w,				\
+		.div_flags	= df,				\
+		.gate_offset	= -1,				\
+	}
+
+#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_divider,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= o,				\
+		.div_shift	= s,				\
+		.div_width	= w,				\
+		.div_flags	= df,				\
+		.div_table	= dt,				\
+	}
+
+#define GATE(_id, cname, pname, f, o, b, gf)			\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_gate,			\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.gate_offset	= o,				\
+		.gate_shift	= b,				\
+		.gate_flags	= gf,				\
+	}
+
+
+void rockchip_clk_init(struct device_node *np, void __iomem *base,
+		       unsigned long nr_clks);
+struct regmap *rockchip_clk_get_grf(void);
+void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
+void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
+				    unsigned int nr_clk);
+void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
+				unsigned int nr_pll, int grf_lock_offset);
+
+#define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
+
+#ifdef CONFIG_RESET_CONTROLLER
+void rockchip_register_softrst(struct device_node *np,
+			       unsigned int num_regs,
+			       void __iomem *base, u8 flags);
+#else
+static inline void rockchip_register_softrst(struct device_node *np,
+			       unsigned int num_regs,
+			       void __iomem *base, u8 flags)
+{
+}
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/clk-pll.c linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-pll.c
--- linux-libre-3.16-gnu/drivers/clk/rockchip/clk-pll.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-pll.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.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 <asm/div64.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include "clk.h"
+
+#define PLL_MODE_MASK		0x3
+#define PLL_MODE_SLOW		0x0
+#define PLL_MODE_NORM		0x1
+#define PLL_MODE_DEEP		0x2
+
+struct rockchip_clk_pll {
+	struct clk_hw		hw;
+
+	struct clk_mux		pll_mux;
+	const struct clk_ops	*pll_mux_ops;
+
+	struct notifier_block	clk_nb;
+	bool			rate_change_remuxed;
+
+	void __iomem		*reg_base;
+	int			lock_offset;
+	unsigned int		lock_shift;
+	enum rockchip_pll_type	type;
+	const struct rockchip_pll_rate_table *rate_table;
+	unsigned int		rate_count;
+	spinlock_t		*lock;
+};
+
+#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
+#define to_rockchip_clk_pll_nb(nb) \
+			container_of(nb, struct rockchip_clk_pll, clk_nb)
+
+static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
+			    struct rockchip_clk_pll *pll, unsigned long rate)
+{
+	const struct rockchip_pll_rate_table  *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+
+	return NULL;
+}
+
+static long rockchip_pll_round_rate(struct clk_hw *hw,
+			    unsigned long drate, unsigned long *prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
+	int i;
+
+	/* Assumming rate_table is in descending order */
+	for (i = 0; i < pll->rate_count; i++) {
+		if (drate >= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+
+	/* return minimum supported value */
+	return rate_table[i - 1].rate;
+}
+
+/*
+ * Wait for the pll to reach the locked state.
+ * The calling set_rate function is responsible for making sure the
+ * grf regmap is available.
+ */
+static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+	struct regmap *grf = rockchip_clk_get_grf();
+	unsigned int val;
+	int delay = 24000000, ret;
+
+	while (delay > 0) {
+		ret = regmap_read(grf, pll->lock_offset, &val);
+		if (ret) {
+			pr_err("%s: failed to read pll lock status: %d\n",
+			       __func__, ret);
+			return ret;
+		}
+
+		if (val & BIT(pll->lock_shift))
+			return 0;
+		delay--;
+	}
+
+	pr_err("%s: timeout waiting for pll to lock\n", __func__);
+	return -ETIMEDOUT;
+}
+
+/**
+ * Set pll mux when changing the pll rate.
+ * This makes sure to move the pll mux away from the actual pll before
+ * changing its rate and back to the original parent after the change.
+ */
+static int rockchip_pll_notifier_cb(struct notifier_block *nb,
+					unsigned long event, void *data)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb);
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	int cur_parent;
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+		cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+		if (cur_parent == PLL_MODE_NORM) {
+			pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+			pll->rate_change_remuxed = 1;
+		}
+		break;
+	case POST_RATE_CHANGE:
+		if (pll->rate_change_remuxed) {
+			pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+			pll->rate_change_remuxed = 0;
+		}
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+/**
+ * PLL used in RK3066, RK3188 and RK3288
+ */
+
+#define RK3066_PLL_RESET_DELAY(nr)	((nr * 500) / 24 + 1)
+
+#define RK3066_PLLCON(i)		(i * 0x4)
+#define RK3066_PLLCON0_OD_MASK		0xf
+#define RK3066_PLLCON0_OD_SHIFT		0
+#define RK3066_PLLCON0_NR_MASK		0x3f
+#define RK3066_PLLCON0_NR_SHIFT		8
+#define RK3066_PLLCON1_NF_MASK		0x1fff
+#define RK3066_PLLCON1_NF_SHIFT		0
+#define RK3066_PLLCON2_BWADJ_MASK	0xfff
+#define RK3066_PLLCON2_BWADJ_SHIFT	0
+#define RK3066_PLLCON3_RESET		(1 << 5)
+#define RK3066_PLLCON3_PWRDOWN		(1 << 1)
+#define RK3066_PLLCON3_BYPASS		(1 << 0)
+
+static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u64 nf, nr, no, rate64 = prate;
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
+	if (pllcon & RK3066_PLLCON3_BYPASS) {
+		pr_debug("%s: pll %s is bypassed\n", __func__,
+			__clk_get_name(hw->clk));
+		return prate;
+	}
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+	nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+	nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
+	no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
+
+	rate64 *= (nf + 1);
+	do_div(rate64, nr + 1);
+	do_div(rate64, no + 1);
+
+	return (unsigned long)rate64;
+}
+
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
+	struct regmap *grf = rockchip_clk_get_grf();
+	int ret;
+
+	if (IS_ERR(grf)) {
+		pr_debug("%s: grf regmap not available, aborting rate change\n",
+			 __func__);
+		return PTR_ERR(grf);
+	}
+
+	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
+		 __func__, rate->rate, rate->nr, rate->no, rate->nf);
+
+	/* enter reset mode */
+	writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0),
+	       pll->reg_base + RK3066_PLLCON(3));
+
+	/* update pll values */
+	writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK,
+					   RK3066_PLLCON0_NR_SHIFT) |
+	       HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK,
+					   RK3066_PLLCON0_OD_SHIFT),
+	       pll->reg_base + RK3066_PLLCON(0));
+
+	writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
+						   RK3066_PLLCON1_NF_SHIFT),
+		       pll->reg_base + RK3066_PLLCON(1));
+	writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK,
+						  RK3066_PLLCON2_BWADJ_SHIFT),
+		       pll->reg_base + RK3066_PLLCON(2));
+
+	/* leave reset and wait the reset_delay */
+	writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0),
+	       pll->reg_base + RK3066_PLLCON(3));
+	udelay(RK3066_PLL_RESET_DELAY(rate->nr));
+
+	/* wait for the pll to lock */
+	ret = rockchip_pll_wait_lock(pll);
+	if (ret) {
+		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+			__func__, old_rate);
+		rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+	}
+
+	return ret;
+}
+
+static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3066_PLLCON(3));
+
+	return 0;
+}
+
+static void rockchip_rk3066_pll_disable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN,
+			     RK3066_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3066_PLLCON(3));
+}
+
+static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3));
+
+	return !(pllcon & RK3066_PLLCON3_PWRDOWN);
+}
+
+static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
+	.recalc_rate = rockchip_rk3066_pll_recalc_rate,
+	.enable = rockchip_rk3066_pll_enable,
+	.disable = rockchip_rk3066_pll_disable,
+	.is_enabled = rockchip_rk3066_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
+	.recalc_rate = rockchip_rk3066_pll_recalc_rate,
+	.round_rate = rockchip_pll_round_rate,
+	.set_rate = rockchip_rk3066_pll_set_rate,
+	.enable = rockchip_rk3066_pll_enable,
+	.disable = rockchip_rk3066_pll_disable,
+	.is_enabled = rockchip_rk3066_pll_is_enabled,
+};
+
+/*
+ * Common registering of pll clocks
+ */
+
+struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+		const char *name, const char **parent_names, u8 num_parents,
+		void __iomem *base, int con_offset, int grf_lock_offset,
+		int lock_shift, int mode_offset, int mode_shift,
+		struct rockchip_pll_rate_table *rate_table,
+		spinlock_t *lock)
+{
+	const char *pll_parents[3];
+	struct clk_init_data init;
+	struct rockchip_clk_pll *pll;
+	struct clk_mux *pll_mux;
+	struct clk *pll_clk, *mux_clk;
+	char pll_name[20];
+	int ret;
+
+	if (num_parents != 2) {
+		pr_err("%s: needs two parent clocks\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* name the actual pll */
+	snprintf(pll_name, sizeof(pll_name), "pll_%s", name);
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = pll_name;
+
+	/* keep all plls untouched for now */
+	init.flags = CLK_IGNORE_UNUSED;
+
+	init.parent_names = &parent_names[0];
+	init.num_parents = 1;
+
+	if (rate_table) {
+		int len;
+
+		/* find count of rates in rate_table */
+		for (len = 0; rate_table[len].rate != 0; )
+			len++;
+
+		pll->rate_count = len;
+		pll->rate_table = kmemdup(rate_table,
+					pll->rate_count *
+					sizeof(struct rockchip_pll_rate_table),
+					GFP_KERNEL);
+		WARN(!pll->rate_table,
+			"%s: could not allocate rate table for %s\n",
+			__func__, name);
+	}
+
+	switch (pll_type) {
+	case pll_rk3066:
+		if (!pll->rate_table)
+			init.ops = &rockchip_rk3066_pll_clk_norate_ops;
+		else
+			init.ops = &rockchip_rk3066_pll_clk_ops;
+		break;
+	default:
+		pr_warn("%s: Unknown pll type for pll clk %s\n",
+			__func__, name);
+	}
+
+	pll->hw.init = &init;
+	pll->type = pll_type;
+	pll->reg_base = base + con_offset;
+	pll->lock_offset = grf_lock_offset;
+	pll->lock_shift = lock_shift;
+	pll->lock = lock;
+	pll->clk_nb.notifier_call = rockchip_pll_notifier_cb;
+
+	pll_clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(pll_clk)) {
+		pr_err("%s: failed to register pll clock %s : %ld\n",
+			__func__, name, PTR_ERR(pll_clk));
+		mux_clk = pll_clk;
+		goto err_pll;
+	}
+
+	ret = clk_notifier_register(pll_clk, &pll->clk_nb);
+	if (ret) {
+		pr_err("%s: failed to register clock notifier for %s : %d\n",
+				__func__, name, ret);
+		mux_clk = ERR_PTR(ret);
+		goto err_pll_notifier;
+	}
+
+	/* create the mux on top of the real pll */
+	pll->pll_mux_ops = &clk_mux_ops;
+	pll_mux = &pll->pll_mux;
+
+	/* the actual muxing is xin24m, pll-output, xin32k */
+	pll_parents[0] = parent_names[0];
+	pll_parents[1] = pll_name;
+	pll_parents[2] = parent_names[1];
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.ops = pll->pll_mux_ops;
+	init.parent_names = pll_parents;
+	init.num_parents = ARRAY_SIZE(pll_parents);
+
+	pll_mux->reg = base + mode_offset;
+	pll_mux->shift = mode_shift;
+	pll_mux->mask = PLL_MODE_MASK;
+	pll_mux->flags = 0;
+	pll_mux->lock = lock;
+	pll_mux->hw.init = &init;
+
+	if (pll_type == pll_rk3066)
+		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
+
+	mux_clk = clk_register(NULL, &pll_mux->hw);
+	if (IS_ERR(mux_clk))
+		goto err_mux;
+
+	return mux_clk;
+
+err_mux:
+	ret = clk_notifier_unregister(pll_clk, &pll->clk_nb);
+	if (ret) {
+		pr_err("%s: could not unregister clock notifier in error path : %d\n",
+		       __func__, ret);
+		return mux_clk;
+	}
+err_pll_notifier:
+	clk_unregister(pll_clk);
+err_pll:
+	kfree(pll);
+	return mux_clk;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/clk-rk3188.c linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-rk3188.c
--- linux-libre-3.16-gnu/drivers/clk/rockchip/clk-rk3188.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-rk3188.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/rk3188-cru-common.h>
+#include "clk.h"
+
+#define RK3188_GRF_SOC_STATUS	0xac
+
+enum rk3188_plls {
+	apll, cpll, dpll, gpll,
+};
+
+struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+	RK3066_PLL_RATE(2208000000, 1, 92, 1),
+	RK3066_PLL_RATE(2184000000, 1, 91, 1),
+	RK3066_PLL_RATE(2160000000, 1, 90, 1),
+	RK3066_PLL_RATE(2136000000, 1, 89, 1),
+	RK3066_PLL_RATE(2112000000, 1, 88, 1),
+	RK3066_PLL_RATE(2088000000, 1, 87, 1),
+	RK3066_PLL_RATE(2064000000, 1, 86, 1),
+	RK3066_PLL_RATE(2040000000, 1, 85, 1),
+	RK3066_PLL_RATE(2016000000, 1, 84, 1),
+	RK3066_PLL_RATE(1992000000, 1, 83, 1),
+	RK3066_PLL_RATE(1968000000, 1, 82, 1),
+	RK3066_PLL_RATE(1944000000, 1, 81, 1),
+	RK3066_PLL_RATE(1920000000, 1, 80, 1),
+	RK3066_PLL_RATE(1896000000, 1, 79, 1),
+	RK3066_PLL_RATE(1872000000, 1, 78, 1),
+	RK3066_PLL_RATE(1848000000, 1, 77, 1),
+	RK3066_PLL_RATE(1824000000, 1, 76, 1),
+	RK3066_PLL_RATE(1800000000, 1, 75, 1),
+	RK3066_PLL_RATE(1776000000, 1, 74, 1),
+	RK3066_PLL_RATE(1752000000, 1, 73, 1),
+	RK3066_PLL_RATE(1728000000, 1, 72, 1),
+	RK3066_PLL_RATE(1704000000, 1, 71, 1),
+	RK3066_PLL_RATE(1680000000, 1, 70, 1),
+	RK3066_PLL_RATE(1656000000, 1, 69, 1),
+	RK3066_PLL_RATE(1632000000, 1, 68, 1),
+	RK3066_PLL_RATE(1608000000, 1, 67, 1),
+	RK3066_PLL_RATE(1560000000, 1, 65, 1),
+	RK3066_PLL_RATE(1512000000, 1, 63, 1),
+	RK3066_PLL_RATE(1488000000, 1, 62, 1),
+	RK3066_PLL_RATE(1464000000, 1, 61, 1),
+	RK3066_PLL_RATE(1440000000, 1, 60, 1),
+	RK3066_PLL_RATE(1416000000, 1, 59, 1),
+	RK3066_PLL_RATE(1392000000, 1, 58, 1),
+	RK3066_PLL_RATE(1368000000, 1, 57, 1),
+	RK3066_PLL_RATE(1344000000, 1, 56, 1),
+	RK3066_PLL_RATE(1320000000, 1, 55, 1),
+	RK3066_PLL_RATE(1296000000, 1, 54, 1),
+	RK3066_PLL_RATE(1272000000, 1, 53, 1),
+	RK3066_PLL_RATE(1248000000, 1, 52, 1),
+	RK3066_PLL_RATE(1224000000, 1, 51, 1),
+	RK3066_PLL_RATE(1200000000, 1, 50, 1),
+	RK3066_PLL_RATE(1188000000, 2, 99, 1),
+	RK3066_PLL_RATE(1176000000, 1, 49, 1),
+	RK3066_PLL_RATE(1128000000, 1, 47, 1),
+	RK3066_PLL_RATE(1104000000, 1, 46, 1),
+	RK3066_PLL_RATE(1008000000, 1, 84, 2),
+	RK3066_PLL_RATE( 912000000, 1, 76, 2),
+	RK3066_PLL_RATE( 891000000, 8, 594, 2),
+	RK3066_PLL_RATE( 888000000, 1, 74, 2),
+	RK3066_PLL_RATE( 816000000, 1, 68, 2),
+	RK3066_PLL_RATE( 798000000, 2, 133, 2),
+	RK3066_PLL_RATE( 792000000, 1, 66, 2),
+	RK3066_PLL_RATE( 768000000, 1, 64, 2),
+	RK3066_PLL_RATE( 742500000, 8, 495, 2),
+	RK3066_PLL_RATE( 696000000, 1, 58, 2),
+	RK3066_PLL_RATE( 600000000, 1, 50, 2),
+	RK3066_PLL_RATE( 594000000, 2, 198, 4),
+	RK3066_PLL_RATE( 552000000, 1, 46, 2),
+	RK3066_PLL_RATE( 504000000, 1, 84, 4),
+	RK3066_PLL_RATE( 456000000, 1, 76, 4),
+	RK3066_PLL_RATE( 408000000, 1, 68, 4),
+	RK3066_PLL_RATE( 384000000, 2, 128, 4),
+	RK3066_PLL_RATE( 360000000, 1, 60, 4),
+	RK3066_PLL_RATE( 312000000, 1, 52, 4),
+	RK3066_PLL_RATE( 300000000, 1, 50, 4),
+	RK3066_PLL_RATE( 297000000, 2, 198, 8),
+	RK3066_PLL_RATE( 252000000, 1, 84, 8),
+	RK3066_PLL_RATE( 216000000, 1, 72, 8),
+	RK3066_PLL_RATE( 148500000, 2, 99, 8),
+	RK3066_PLL_RATE( 126000000, 1, 84, 16),
+	RK3066_PLL_RATE(  48000000, 1, 64, 32),
+	{ /* sentinel */ },
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
+PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
+PNAME(mux_ddrphy_p)		= { "dpll", "gpll_ddr" };
+PNAME(mux_pll_src_gpll_cpll_p)	= { "gpll", "cpll" };
+PNAME(mux_pll_src_cpll_gpll_p)	= { "cpll", "gpll" };
+PNAME(mux_aclk_cpu_p)		= { "apll", "gpll" };
+PNAME(mux_sclk_cif0_p)		= { "cif0_pre", "xin24m" };
+PNAME(mux_sclk_i2s0_p)		= { "i2s0_pre", "i2s0_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p)		= { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_sclk_uart0_p)		= { "uart0_pre", "uart0_frac", "xin24m" };
+PNAME(mux_sclk_uart1_p)		= { "uart1_pre", "uart1_frac", "xin24m" };
+PNAME(mux_sclk_uart2_p)		= { "uart2_pre", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_uart3_p)		= { "uart3_pre", "uart3_frac", "xin24m" };
+PNAME(mux_sclk_hsadc_p)		= { "hsadc_src", "hsadc_frac", "ext_hsadc" };
+PNAME(mux_mac_p)		= { "gpll", "dpll" };
+PNAME(mux_sclk_macref_p)	= { "mac_src", "ext_rmii" };
+
+static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+		     RK2928_MODE_CON, 0, 6, rk3188_pll_rates),
+	[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
+		     RK2928_MODE_CON, 4, 5, NULL),
+	[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8),
+		     RK2928_MODE_CON, 8, 7, rk3188_pll_rates),
+	[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
+		     RK2928_MODE_CON, 12, 8, rk3188_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)
+
+/* 2 ^ (val + 1) */
+static struct clk_div_table div_core_peri_t[] = {
+	{ .val = 0, .div = 2 },
+	{ .val = 1, .div = 4 },
+	{ .val = 2, .div = 8 },
+	{ .val = 3, .div = 16 },
+	{ /* sentinel */ },
+};
+
+static struct rockchip_clk_branch common_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	GATE(0, "gpll_armclk", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
+
+	/* these two are set by the cpuclk and should not be changed */
+	COMPOSITE_NOMUX_DIVTBL(CORE_PERI, "core_peri", "armclk", 0,
+			RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS),
+
+	COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 9, GFLAGS),
+	GATE(0, "hclk_vepu", "aclk_vepu", 0,
+			RK2928_CLKGATE_CON(3), 10, GFLAGS),
+	COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 11, GFLAGS),
+	GATE(0, "hclk_vdpu", "aclk_vdpu", 0,
+			RK2928_CLKGATE_CON(3), 12, GFLAGS),
+
+	GATE(0, "gpll_ddr", "gpll", 0,
+			RK2928_CLKGATE_CON(1), 7, GFLAGS),
+	COMPOSITE(0, "ddrphy", mux_ddrphy_p, 0,
+			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,
+			RK2928_CLKGATE_CON(0), 3, GFLAGS),
+
+	DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
+			RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+			RK2928_CLKGATE_CON(0), 5, GFLAGS),
+	DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
+			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
+			RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK2928_CLKGATE_CON(4), 9, GFLAGS),
+	GATE(0, "hclk_cpu", "hclk_cpu_pre", 0,
+			RK2928_CLKGATE_CON(0), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 0, GFLAGS),
+	COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 4, GFLAGS),
+
+	GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+			RK2928_CLKGATE_CON(2), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "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,
+			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK2928_CLKGATE_CON(2), 3, GFLAGS),
+
+	MUX(0, "cif_src", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(29), 0, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "cif0_pre", "cif_src", 0,
+			RK2928_CLKSEL_CON(29), 1, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 7, GFLAGS),
+	MUX(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_p, 0,
+			RK2928_CLKSEL_CON(29), 7, 1, MFLAGS),
+
+	GATE(0, "pclkin_cif0", "ext_cif0", 0,
+			RK2928_CLKGATE_CON(3), 3, GFLAGS),
+
+	/*
+	 * the 480m are generated inside the usb block from these clocks,
+	 * but they are also a source for the hsicphy clock.
+	 */
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0,
+			RK2928_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0,
+			RK2928_CLKGATE_CON(1), 6, GFLAGS),
+
+	COMPOSITE(0, "mac_src", mux_mac_p, 0,
+			RK2928_CLKSEL_CON(21), 0, 1, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS),
+	MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(21), 4, 1, MFLAGS),
+	GATE(0, "sclk_mac_lbtest", "sclk_macref",
+			RK2928_CLKGATE_CON(2), 12, 0, GFLAGS),
+
+	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
+			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(2), 6, GFLAGS),
+	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src",
+			RK2928_CLKSEL_CON(23), 0,
+			RK2928_CLKGATE_CON(2), 7, 0, GFLAGS),
+	MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+			RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(2), 8, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+
+	GATE(SCLK_SMC, "sclk_smc", "hclk_peri",
+			RK2928_CLKGATE_CON(2), 4, 0, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0,
+			RK2928_CLKSEL_CON(25), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 9, GFLAGS),
+	COMPOSITE_NOMUX(SCLK_SPI1, "sclk_spi1", "pclk_peri", 0,
+			RK2928_CLKSEL_CON(25), 8, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 10, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SDMMC, "sclk_sdmmc", "hclk_peri", 0,
+			RK2928_CLKSEL_CON(11), 0, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 11, GFLAGS),
+	COMPOSITE_NOMUX(SCLK_SDIO, "sclk_sdio", "hclk_peri", 0,
+			RK2928_CLKSEL_CON(12), 0, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 13, GFLAGS),
+	COMPOSITE_NOMUX(SCLK_EMMC, "sclk_emmc", "hclk_peri", 0,
+			RK2928_CLKSEL_CON(12), 8, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 14, GFLAGS),
+
+	MUX(0, "uart_src", mux_pll_src_gpll_cpll_p, 0,
+			RK2928_CLKSEL_CON(12), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
+			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
+			RK2928_CLKSEL_CON(17), 0,
+			RK2928_CLKGATE_CON(1), 9, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
+			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 10, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
+			RK2928_CLKSEL_CON(18), 0,
+			RK2928_CLKGATE_CON(1), 11, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
+			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 12, GFLAGS),
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
+			RK2928_CLKSEL_CON(19), 0,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
+			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 14, GFLAGS),
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
+			RK2928_CLKSEL_CON(20), 0,
+			RK2928_CLKGATE_CON(1), 15, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
+
+	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
+
+	GATE(SCLK_TIMER0, "timer0", "xin24m", 0, RK2928_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(SCLK_TIMER1, "timer1", "xin24m", 0, RK2928_CLKGATE_CON(1), 1, GFLAGS),
+
+	/* clk_core_pre gates */
+	GATE(0, "core_dbg", "armclk", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS),
+
+	/* aclk_cpu gates */
+	GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 12, GFLAGS),
+	GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 10, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS),
+	GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS),
+	GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS),
+	/* hclk_ahb2apb is part of a clk branch */
+	GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS),
+	GATE(HCLK_LCDC1, "hclk_lcdc1", "aclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS),
+	GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS),
+	GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_axi_matrix", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 0, GFLAGS),
+	GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 6, GFLAGS),
+	GATE(0, "hclk_emem_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 7, GFLAGS),
+	GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
+	GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 5, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_usbotg0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
+	GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 5, GFLAGS),
+	GATE(HCLK_PIDF, "hclk_pidfilter", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 12, GFLAGS),
+
+	/* aclk_lcdc0_pre gates */
+	GATE(0, "aclk_vio0", "aclk_lcdc0_pre", 0, RK2928_CLKGATE_CON(6), 13, GFLAGS),
+	GATE(ACLK_LCDC0, "aclk_lcdc0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(ACLK_IPP, "aclk_ipp", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 8, GFLAGS),
+
+	/* aclk_lcdc1_pre gates */
+	GATE(0, "aclk_vio1", "aclk_lcdc1_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
+	GATE(ACLK_LCDC1, "aclk_lcdc1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 3, GFLAGS),
+	GATE(ACLK_RGA, "aclk_rga", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 11, GFLAGS),
+
+	/* atclk_cpu gates */
+	GATE(0, "atclk", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 3, GFLAGS),
+	GATE(0, "trace", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_PWM01, "pclk_pwm01", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
+	GATE(PCLK_TIMER0, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+	GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS),
+	GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+	GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+	GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
+	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 5, GFLAGS),
+
+	/* aclk_peri */
+	GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 4, GFLAGS),
+	GATE(0, "aclk_cpu_peri", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 2, GFLAGS),
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 3, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(0, "pclk_peri_axi_matrix", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS),
+	GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 13, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS),
+};
+
+PNAME(mux_rk3066_lcdc0_p)	= { "dclk_lcdc0_src", "xin27m" };
+PNAME(mux_rk3066_lcdc1_p)	= { "dclk_lcdc1_src", "xin27m" };
+PNAME(mux_sclk_cif1_p)		= { "cif1_pre", "xin24m" };
+PNAME(mux_sclk_i2s1_p)		= { "i2s1_pre", "i2s1_frac", "xin12m" };
+PNAME(mux_sclk_i2s2_p)		= { "i2s2_pre", "i2s2_frac", "xin12m" };
+
+static struct clk_div_table div_aclk_cpu_t[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 3, .div = 4 },
+	{ .val = 4, .div = 8 },
+	{ /* sentinel */ },
+};
+
+static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
+	COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+			RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 0, 5, DFLAGS),
+	DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
+			RK2928_CLKSEL_CON(1), 0, 3, DFLAGS, div_aclk_cpu_t),
+
+	GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0,
+			RK2928_CLKGATE_CON(9), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0,
+			RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+	COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 1, GFLAGS),
+	MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0,
+			RK2928_CLKSEL_CON(27), 4, 1, MFLAGS),
+	COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+	MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0,
+			RK2928_CLKSEL_CON(28), 4, 1, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0,
+			RK2928_CLKSEL_CON(29), 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 8, GFLAGS),
+	MUX(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_p, 0,
+			RK2928_CLKSEL_CON(29), 15, 1, MFLAGS),
+
+	GATE(0, "pclkin_cif1", "ext_cif1", 0,
+			RK2928_CLKGATE_CON(3), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0,
+			RK2928_CLKGATE_CON(5), 15, GFLAGS),
+
+	GATE(SCLK_TIMER2, "timer2", "xin24m", 0,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+	COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0,
+			RK2928_CLKSEL_CON(34), 0, 16, DFLAGS,
+			RK2928_CLKGATE_CON(2), 15, GFLAGS),
+
+	MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0,
+			RK2928_CLKSEL_CON(2), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+			RK2928_CLKSEL_CON(6), 0,
+			RK2928_CLKGATE_CON(0), 8, GFLAGS),
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
+			RK2928_CLKSEL_CON(7), 0,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 11, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
+			RK2928_CLKSEL_CON(8), 0,
+			RK2928_CLKGATE_CON(0), 12, GFLAGS),
+	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 13, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+
+	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+	GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS),
+	GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
+
+	GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
+
+	GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS),
+
+	GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS),
+	GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS),
+	GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+
+	GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 13, GFLAGS),
+};
+
+static struct clk_div_table div_rk3188_aclk_core_t[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 3, .div = 4 },
+	{ .val = 4, .div = 8 },
+	{ /* sentinel */ },
+};
+
+PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
+				    "gpll", "cpll" };
+
+static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
+	COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+			RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 9, 5, DFLAGS),
+	COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0,
+			RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS),
+
+	/* do not source aclk_cpu_pre from the apll, to keep complexity down */
+	COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT,
+			RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS),
+
+	GATE(CORE_L2C, "core_l2c", "armclk", 0,
+			RK2928_CLKGATE_CON(9), 4, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+	COMPOSITE(DCLK_LCDC0, "dclk_lcdc0", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 1, GFLAGS),
+	COMPOSITE(DCLK_LCDC1, "dclk_lcdc1", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+	COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+			RK2928_CLKSEL_CON(34), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 15, GFLAGS),
+	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0,
+			RK2928_CLKGATE_CON(9), 7, GFLAGS),
+
+	GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 4, GFLAGS),
+	GATE(SCLK_TIMER3, "timer3", "xin24m", 0, RK2928_CLKGATE_CON(1), 2, GFLAGS),
+	GATE(SCLK_TIMER4, "timer4", "xin24m", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS),
+	GATE(SCLK_TIMER5, "timer5", "xin24m", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
+	GATE(SCLK_TIMER6, "timer6", "xin24m", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_hsicphy_480m", mux_hsicphy_p, 0,
+			RK2928_CLKSEL_CON(30), 0, 2, DFLAGS,
+			RK2928_CLKGATE_CON(3), 6, GFLAGS),
+	DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0,
+			RK2928_CLKGATE_CON(11), 8, 6, DFLAGS),
+
+	MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0,
+			RK2928_CLKSEL_CON(2), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+			RK2928_CLKSEL_CON(7), 0,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
+			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(13), 13, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+
+	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
+	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
+
+	GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+	GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+
+	GATE(PCLK_TIMER3, "pclk_timer3", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS),
+
+	GATE(PCLK_UART0, "pclk_uart0", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+
+	GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+};
+
+static void __init rk3188_common_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock usb480m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	rockchip_clk_register_plls(rk3188_pll_clks,
+				   ARRAY_SIZE(rk3188_pll_clks),
+				   RK3188_GRF_SOC_STATUS);
+	rockchip_clk_register_branches(common_clk_branches,
+				  ARRAY_SIZE(common_clk_branches));
+
+	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
+
+static void __init rk3066a_clk_init(struct device_node *np)
+{
+	rk3188_common_clk_init(np);
+	rockchip_clk_register_branches(rk3066a_clk_branches,
+				  ARRAY_SIZE(rk3066a_clk_branches));
+}
+CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
+
+static void __init rk3188a_clk_init(struct device_node *np)
+{
+	rk3188_common_clk_init(np);
+	rockchip_clk_register_branches(rk3188_clk_branches,
+				  ARRAY_SIZE(rk3188_clk_branches));
+}
+CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
+
+static void __init rk3188_clk_init(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rk3188_pll_clks); i++) {
+		struct rockchip_pll_clock *pll = &rk3188_pll_clks[i];
+		struct rockchip_pll_rate_table *rate;
+
+		if (!pll->rate_table)
+			continue;
+
+		rate = pll->rate_table;
+		while (rate->rate > 0) {
+			rate->bwadj = 0;
+			rate++;
+		}
+	}
+
+	rk3188a_clk_init(np);
+}
+CLK_OF_DECLARE(rk3188_cru, "rockchip,rk3188-cru", rk3188_clk_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/clk-rk3288.c linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-rk3288.c
--- linux-libre-3.16-gnu/drivers/clk/rockchip/clk-rk3288.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/clk-rk3288.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include "clk.h"
+
+#define RK3288_GRF_SOC_CON(x)	(0x244 + x * 4)
+#define RK3288_GRF_SOC_STATUS	0x280
+
+enum rk3288_plls {
+	apll, dpll, cpll, gpll, npll,
+};
+
+struct rockchip_pll_rate_table rk3288_pll_rates[] = {
+	RK3066_PLL_RATE(2208000000, 1, 92, 1),
+	RK3066_PLL_RATE(2184000000, 1, 91, 1),
+	RK3066_PLL_RATE(2160000000, 1, 90, 1),
+	RK3066_PLL_RATE(2136000000, 1, 89, 1),
+	RK3066_PLL_RATE(2112000000, 1, 88, 1),
+	RK3066_PLL_RATE(2088000000, 1, 87, 1),
+	RK3066_PLL_RATE(2064000000, 1, 86, 1),
+	RK3066_PLL_RATE(2040000000, 1, 85, 1),
+	RK3066_PLL_RATE(2016000000, 1, 84, 1),
+	RK3066_PLL_RATE(1992000000, 1, 83, 1),
+	RK3066_PLL_RATE(1968000000, 1, 82, 1),
+	RK3066_PLL_RATE(1944000000, 1, 81, 1),
+	RK3066_PLL_RATE(1920000000, 1, 80, 1),
+	RK3066_PLL_RATE(1896000000, 1, 79, 1),
+	RK3066_PLL_RATE(1872000000, 1, 78, 1),
+	RK3066_PLL_RATE(1848000000, 1, 77, 1),
+	RK3066_PLL_RATE(1824000000, 1, 76, 1),
+	RK3066_PLL_RATE(1800000000, 1, 75, 1),
+	RK3066_PLL_RATE(1776000000, 1, 74, 1),
+	RK3066_PLL_RATE(1752000000, 1, 73, 1),
+	RK3066_PLL_RATE(1728000000, 1, 72, 1),
+	RK3066_PLL_RATE(1704000000, 1, 71, 1),
+	RK3066_PLL_RATE(1680000000, 1, 70, 1),
+	RK3066_PLL_RATE(1656000000, 1, 69, 1),
+	RK3066_PLL_RATE(1632000000, 1, 68, 1),
+	RK3066_PLL_RATE(1608000000, 1, 67, 1),
+	RK3066_PLL_RATE(1560000000, 1, 65, 1),
+	RK3066_PLL_RATE(1512000000, 1, 63, 1),
+	RK3066_PLL_RATE(1488000000, 1, 62, 1),
+	RK3066_PLL_RATE(1464000000, 1, 61, 1),
+	RK3066_PLL_RATE(1440000000, 1, 60, 1),
+	RK3066_PLL_RATE(1416000000, 1, 59, 1),
+	RK3066_PLL_RATE(1392000000, 1, 58, 1),
+	RK3066_PLL_RATE(1368000000, 1, 57, 1),
+	RK3066_PLL_RATE(1344000000, 1, 56, 1),
+	RK3066_PLL_RATE(1320000000, 1, 55, 1),
+	RK3066_PLL_RATE(1296000000, 1, 54, 1),
+	RK3066_PLL_RATE(1272000000, 1, 53, 1),
+	RK3066_PLL_RATE(1248000000, 1, 52, 1),
+	RK3066_PLL_RATE(1224000000, 1, 51, 1),
+	RK3066_PLL_RATE(1200000000, 1, 50, 1),
+	RK3066_PLL_RATE(1188000000, 2, 99, 1),
+	RK3066_PLL_RATE(1176000000, 1, 49, 1),
+	RK3066_PLL_RATE(1128000000, 1, 47, 1),
+	RK3066_PLL_RATE(1104000000, 1, 46, 1),
+	RK3066_PLL_RATE(1008000000, 1, 84, 2),
+	RK3066_PLL_RATE( 912000000, 1, 76, 2),
+	RK3066_PLL_RATE( 891000000, 8, 594, 2),
+	RK3066_PLL_RATE( 888000000, 1, 74, 2),
+	RK3066_PLL_RATE( 816000000, 1, 68, 2),
+	RK3066_PLL_RATE( 798000000, 2, 133, 2),
+	RK3066_PLL_RATE( 792000000, 1, 66, 2),
+	RK3066_PLL_RATE( 768000000, 1, 64, 2),
+	RK3066_PLL_RATE( 742500000, 8, 495, 2),
+	RK3066_PLL_RATE( 696000000, 1, 58, 2),
+	RK3066_PLL_RATE( 600000000, 1, 50, 2),
+	RK3066_PLL_RATE( 594000000, 2, 198, 4),
+	RK3066_PLL_RATE( 552000000, 1, 46, 2),
+	RK3066_PLL_RATE( 504000000, 1, 84, 4),
+	RK3066_PLL_RATE( 456000000, 1, 76, 4),
+	RK3066_PLL_RATE( 408000000, 1, 68, 4),
+	RK3066_PLL_RATE( 384000000, 2, 128, 4),
+	RK3066_PLL_RATE( 360000000, 1, 60, 4),
+	RK3066_PLL_RATE( 312000000, 1, 52, 4),
+	RK3066_PLL_RATE( 300000000, 1, 50, 4),
+	RK3066_PLL_RATE( 297000000, 2, 198, 8),
+	RK3066_PLL_RATE( 252000000, 1, 84, 8),
+	RK3066_PLL_RATE( 216000000, 1, 72, 8),
+	RK3066_PLL_RATE( 148500000, 2, 99, 8),
+	RK3066_PLL_RATE( 126000000, 1, 84, 16),
+	RK3066_PLL_RATE(  48000000, 1, 64, 32),
+	{ /* sentinel */ },
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
+PNAME(mux_armclk_p)		= { "apll_core", "gpll_core" };
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_aclk_cpu_src_p)	= { "cpll_aclk_cpu", "gpll_aclk_cpu" };
+
+PNAME(mux_pll_src_cpll_gpll_p)		= { "cpll", "gpll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)	= { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)	= { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_usb480m_p)	= { "cpll", "gpll", "usb480m" };
+
+PNAME(mux_mmc_src_p)	= { "cpll", "gpll", "xin24m", "xin24m" };
+PNAME(mux_i2s_pre_p)	= { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_clkout_p)	= { "i2s_pre", "xin12m" };
+PNAME(mux_spdif_p)	= { "spdif_pre", "spdif_frac", "xin12m" };
+PNAME(mux_spdif_8ch_p)	= { "spdif_8ch_pre", "spdif_8ch_frac", "xin12m" };
+PNAME(mux_uart0_pll_p)	= { "cpll", "gpll", "usbphy_480m_src", "npll" };
+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_uart3_p)	= { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p)	= { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_cif_out_p)	= { "cif_src", "xin24m" };
+PNAME(mux_macref_p)	= { "mac_src", "ext_gmac" };
+PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
+PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
+PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
+
+PNAME(mux_usbphy480m_p)		= { "sclk_otgphy0", "sclk_otgphy1",
+				    "sclk_otgphy2" };
+PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
+PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
+
+static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0),
+		     RK3288_MODE_CON, 0, 6, rk3288_pll_rates),
+	[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4),
+		     RK3288_MODE_CON, 4, 5, NULL),
+	[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8),
+		     RK3288_MODE_CON, 8, 7, rk3288_pll_rates),
+	[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12),
+		     RK3288_MODE_CON, 12, 8, rk3288_pll_rates),
+	[npll] = PLL(pll_rk3066, PLL_NPLL, "npll",  mux_pll_p, 0, RK3288_PLL_CON(16),
+		     RK3288_MODE_CON, 14, 9, NULL),
+};
+
+static struct clk_div_table div_hclk_cpu_t[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 3, .div = 4 },
+	{ /* sentinel */},
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 1
+	 */
+
+	GATE(0, "apll_core", "apll", 0,
+			RK3288_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "gpll_core", "gpll", 0,
+			RK3288_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+			RK3288_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
+
+	COMPOSITE_NOMUX(0, "armcore0", "armclk", 0,
+			RK3288_CLKSEL_CON(36), 0, 3, DFLAGS,
+			RK3288_CLKGATE_CON(12), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "armcore1", "armclk", 0,
+			RK3288_CLKSEL_CON(36), 4, 3, DFLAGS,
+			RK3288_CLKGATE_CON(12), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "armcore2", "armclk", 0,
+			RK3288_CLKSEL_CON(36), 8, 3, DFLAGS,
+			RK3288_CLKGATE_CON(12), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "armcore3", "armclk", 0,
+			RK3288_CLKSEL_CON(36), 12, 3, DFLAGS,
+			RK3288_CLKGATE_CON(12), 3, GFLAGS),
+	COMPOSITE_NOMUX(0, "l2ram", "armclk", 0,
+			RK3288_CLKSEL_CON(37), 0, 3, DFLAGS,
+			RK3288_CLKGATE_CON(12), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0,
+			RK3288_CLKSEL_CON(0), 0, 4, DFLAGS,
+			RK3288_CLKGATE_CON(12), 5, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0,
+			RK3288_CLKSEL_CON(0), 4, 4, DFLAGS,
+			RK3288_CLKGATE_CON(12), 6, GFLAGS),
+	COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
+			RK3288_CLKSEL_CON(37), 4, 5, DFLAGS,
+			RK3288_CLKGATE_CON(12), 7, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0,
+			RK3288_CLKSEL_CON(37), 9, 5, DFLAGS,
+			RK3288_CLKGATE_CON(12), 8, GFLAGS),
+	GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
+			RK3288_CLKGATE_CON(12), 9, GFLAGS),
+	GATE(0, "cs_dbg", "pclk_dbg_pre", 0,
+			RK3288_CLKGATE_CON(12), 10, GFLAGS),
+	GATE(0, "pclk_core_niu", "pclk_dbg_pre", 0,
+			RK3288_CLKGATE_CON(12), 11, GFLAGS),
+
+	GATE(0, "dpll_ddr", "dpll", 0,
+			RK3288_CLKGATE_CON(0), 8, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", 0,
+			RK3288_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, 0,
+			RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2,
+					DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+
+	GATE(0, "gpll_aclk_cpu", "gpll", 0,
+			RK3288_CLKGATE_CON(0), 10, GFLAGS),
+	GATE(0, "cpll_aclk_cpu", "cpll", 0,
+			RK3288_CLKGATE_CON(0), 11, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
+			RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS),
+	DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0,
+			RK3288_CLKSEL_CON(1), 0, 3, DFLAGS),
+	GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+			RK3288_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_cpu", "aclk_cpu_pre", 0,
+			RK3288_CLKSEL_CON(1), 12, 3, DFLAGS,
+			RK3288_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX_DIVTBL(0, "hclk_cpu", "aclk_cpu_pre", 0,
+			RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t,
+			RK3288_CLKGATE_CON(0), 4, GFLAGS),
+	GATE(0, "c2c_host", "aclk_cpu_src", 0,
+			RK3288_CLKGATE_CON(13), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0,
+			RK3288_CLKSEL_CON(26), 6, 2, DFLAGS,
+			RK3288_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", 0,
+			RK3288_CLKGATE_CON(0), 7, GFLAGS),
+
+	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(4), 1, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", 0,
+			RK3288_CLKSEL_CON(8), 0,
+			RK3288_CLKGATE_CON(4), 2, GFLAGS),
+	MUX(0, "i2s_pre", mux_i2s_pre_p, 0,
+			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
+	COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0,
+			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
+			RK3288_CLKGATE_CON(4), 0, GFLAGS),
+	GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", 0,
+			RK3288_CLKGATE_CON(4), 3, GFLAGS),
+
+	MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
+			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(4), 4, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+			RK3288_CLKSEL_CON(9), 0,
+			RK3288_CLKGATE_CON(4), 5, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
+			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 6, GFLAGS),
+	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
+			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(4), 7, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", 0,
+			RK3288_CLKSEL_CON(41), 0,
+			RK3288_CLKGATE_CON(4), 8, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 9, GFLAGS),
+
+	GATE(0, "sclk_acc_efuse", "xin24m", 0,
+			RK3288_CLKGATE_CON(0), 12, GFLAGS),
+
+	GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 2, GFLAGS),
+	GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 3, GFLAGS),
+	GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 4, GFLAGS),
+	GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+			RK3288_CLKGATE_CON(1), 5, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(32), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 9, GFLAGS),
+	COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 0, GFLAGS),
+	DIV(0, "hclk_vio", "aclk_vio0", 0,
+			RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
+	COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 2, GFLAGS),
+
+	COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 5, GFLAGS),
+	COMPOSITE(0, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(3), 4, GFLAGS),
+
+	COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK3288_CLKGATE_CON(3), 1, GFLAGS),
+	COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS,
+			RK3288_CLKGATE_CON(3), 3, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_edp_24m", mux_edp_24m_p, 0,
+			RK3288_CLKSEL_CON(28), 15, 1, MFLAGS,
+			RK3288_CLKGATE_CON(3), 12, GFLAGS),
+	COMPOSITE(0, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3288_CLKGATE_CON(3), 13, GFLAGS),
+
+	COMPOSITE(0, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3288_CLKGATE_CON(3), 14, GFLAGS),
+	COMPOSITE(0, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK3288_CLKGATE_CON(3), 15, GFLAGS),
+
+	GATE(0, "sclk_hdmi_hdcp", "xin24m", 0,
+			RK3288_CLKGATE_CON(5), 12, GFLAGS),
+	GATE(0, "sclk_hdmi_cec", "xin32k", 0,
+			RK3288_CLKGATE_CON(5), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(13), 13, GFLAGS),
+	DIV(0, "hclk_hevc", "aclk_hevc", 0,
+			RK3288_CLKSEL_CON(40), 12, 2, DFLAGS),
+
+	COMPOSITE(0, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(13), 14, GFLAGS),
+	COMPOSITE(0, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(13), 15, GFLAGS),
+
+	COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
+			RK3288_CLKGATE_CON(3), 7, GFLAGS),
+	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+			RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
+
+	DIV(0, "pclk_pd_alive", "gpll", 0,
+			RK3288_CLKSEL_CON(33), 8, 5, DFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", 0,
+			RK3288_CLKSEL_CON(33), 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(5), 8, GFLAGS),
+
+	COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+			RK3288_CLKSEL_CON(34), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(5), 7, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_src", 0,
+			RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3288_CLKGATE_CON(2), 3, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_src", 0,
+			RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3288_CLKGATE_CON(2), 2, GFLAGS),
+	GATE(0, "aclk_peri", "aclk_peri_src", 0,
+			RK3288_CLKGATE_CON(2), 1, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(2), 9, GFLAGS),
+	COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(25), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3288_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(39), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(2), 11, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+			RK3288_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3288_CLKGATE_CON(13), 0, GFLAGS),
+	COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+			RK3288_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3288_CLKGATE_CON(13), 1, GFLAGS),
+	COMPOSITE(SCLK_SDIO1, "sclk_sdio1", mux_mmc_src_p, 0,
+			RK3288_CLKSEL_CON(34), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK3288_CLKGATE_CON(13), 2, GFLAGS),
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK3288_CLKGATE_CON(13), 3, GFLAGS),
+
+	COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0,
+			RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(4), 11, GFLAGS),
+	COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(4), 10, GFLAGS),
+
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0,
+			RK3288_CLKGATE_CON(13), 4, GFLAGS),
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0,
+			RK3288_CLKGATE_CON(13), 5, GFLAGS),
+	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", 0,
+			RK3288_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", 0,
+			RK3288_CLKGATE_CON(13), 7, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+			RK3288_CLKSEL_CON(2), 0, 6, DFLAGS,
+			RK3288_CLKGATE_CON(2), 7, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+			RK3288_CLKSEL_CON(24), 8, 8, DFLAGS,
+			RK3288_CLKGATE_CON(2), 8, GFLAGS),
+
+	GATE(SCLK_PS2C, "sclk_ps2c", "xin24m", 0,
+			RK3288_CLKGATE_CON(5), 13, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(38), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3288_CLKGATE_CON(5), 5, GFLAGS),
+	COMPOSITE(SCLK_NANDC1, "sclk_nandc1", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(38), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(5), 6, GFLAGS),
+
+	COMPOSITE(0, "uart0_src", mux_uart0_pll_p, 0,
+			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(1), 8, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0,
+			RK3288_CLKSEL_CON(17), 0,
+			RK3288_CLKGATE_CON(1), 9, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, 0,
+			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
+	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(1), 10, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", 0,
+			RK3288_CLKSEL_CON(18), 0,
+			RK3288_CLKGATE_CON(1), 11, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, 0,
+			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(1), 12, GFLAGS),
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", 0,
+			RK3288_CLKSEL_CON(19), 0,
+			RK3288_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, 0,
+			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(1), 14, GFLAGS),
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", 0,
+			RK3288_CLKSEL_CON(20), 0,
+			RK3288_CLKGATE_CON(1), 15, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, 0,
+			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
+			RK3288_CLKGATE_CON(2), 12, GFLAGS),
+	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", 0,
+			RK3288_CLKSEL_CON(7), 0,
+			RK3288_CLKGATE_CON(2), 13, GFLAGS),
+	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, 0,
+			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
+
+	COMPOSITE(0, "mac_src", mux_pll_src_npll_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3288_CLKGATE_CON(2), 5, GFLAGS),
+	MUX(0, "macref", mux_macref_p, 0,
+			RK3288_CLKSEL_CON(21), 4, 1, MFLAGS),
+	GATE(0, "sclk_macref_out", "macref", 0,
+			RK3288_CLKGATE_CON(5), 3, GFLAGS),
+	GATE(SCLK_MACREF, "sclk_macref", "macref", 0,
+			RK3288_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(SCLK_MAC_RX, "sclk_mac_rx", "macref", 0,
+			RK3288_CLKGATE_CON(5), 0, GFLAGS),
+	GATE(SCLK_MAC_TX, "sclk_mac_tx", "macref", 0,
+			RK3288_CLKGATE_CON(5), 1, GFLAGS),
+
+	COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
+			RK3288_CLKGATE_CON(2), 6, GFLAGS),
+	MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+			RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+
+	GATE(0, "jtag", "ext_jtag", 0,
+			RK3288_CLKGATE_CON(4), 14, GFLAGS),
+
+	COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0,
+			RK3288_CLKSEL_CON(13), 11, 2, MFLAGS,
+			RK3288_CLKGATE_CON(5), 15, GFLAGS),
+	COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+			RK3288_CLKSEL_CON(29), 0, 2, MFLAGS,
+			RK3288_CLKGATE_CON(3), 6, GFLAGS),
+	GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
+			RK3288_CLKGATE_CON(13), 9, GFLAGS),
+	DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0,
+			RK3288_CLKSEL_CON(11), 8, 6, DFLAGS),
+	MUX(SCLK_HSICPHY12M, "sclk_hsicphy12m", mux_hsicphy12m_p, 0,
+			RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+
+	/* aclk_cpu gates */
+	GATE(0, "sclk_intmem0", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(0, "sclk_intmem1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 6, GFLAGS),
+	GATE(0, "sclk_intmem2", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 7, GFLAGS),
+	GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 12, GFLAGS),
+	GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 13, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 4, GFLAGS),
+	GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 6, GFLAGS),
+	GATE(0, "aclk_ccp", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 8, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK3288_CLKGATE_CON(11), 7, GFLAGS),
+	GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 9, GFLAGS),
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 10, GFLAGS),
+	GATE(HCLK_SPDIF8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 11, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS),
+	GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS),
+	GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
+	GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
+	GATE(0, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
+	GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
+	GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
+	GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
+	GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS),
+
+	/* ddrctrl [DDR Controller PHY clock] gates */
+	GATE(0, "nclk_ddrupctl0", "ddrphy", 0, RK3288_CLKGATE_CON(11), 4, GFLAGS),
+	GATE(0, "nclk_ddrupctl1", "ddrphy", 0, RK3288_CLKGATE_CON(11), 5, GFLAGS),
+
+	/* ddrphy gates */
+	GATE(0, "sclk_ddrphy0", "ddrphy", 0, RK3288_CLKGATE_CON(4), 12, GFLAGS),
+	GATE(0, "sclk_ddrphy1", "ddrphy", 0, RK3288_CLKGATE_CON(4), 13, GFLAGS),
+
+	/* aclk_peri gates */
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 2, GFLAGS),
+	GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS),
+	GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 12, GFLAGS),
+	GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_matrix", "hclk_peri", 0, RK3288_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 4, GFLAGS),
+	GATE(HCLK_USBHOST0, "hclk_host0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(HCLK_USBHOST1, "hclk_host1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 8, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 9, GFLAGS),
+	GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 10, GFLAGS),
+	GATE(0, "hclk_emem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(0, "hclk_mem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 13, GFLAGS),
+	GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 14, GFLAGS),
+	GATE(HCLK_NANDC1, "hclk_nandc1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 15, GFLAGS),
+	GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 8, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 3, GFLAGS),
+	GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(HCLK_SDIO1, "hclk_sdio1", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 5, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(0, "pclk_peri_matrix", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 1, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 4, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 6, GFLAGS),
+	GATE(PCLK_PS2C, "pclk_ps2c", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 7, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 8, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 9, GFLAGS),
+	GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS),
+	GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS),
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS),
+	GATE(PCLK_SIM, "pclk_sim", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 3, GFLAGS),
+	GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 0, GFLAGS),
+	GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3288_CLKGATE_CON(8), 1, GFLAGS),
+
+	GATE(SCLK_LCDC_PWM0, "sclk_lcdc_pwm0", "xin24m", 0, RK3288_CLKGATE_CON(13), 10, GFLAGS),
+	GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
+	GATE(0, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(0, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
+	GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
+
+	/* sclk_gpu gates */
+	GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS),
+
+	/* pclk_pd_alive gates */
+	GATE(PCLK_GPIO8, "pclk_gpio8", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(PCLK_GPIO7, "pclk_gpio7", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 1, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 2, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 3, GFLAGS),
+	GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 4, GFLAGS),
+	GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS),
+	GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS),
+	GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 11, GFLAGS),
+	GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS),
+
+	/* pclk_pd_pmu gates */
+	GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 0, GFLAGS),
+	GATE(0, "pclk_intmem1", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 1, GFLAGS),
+	GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS),
+	GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 3, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS),
+
+	/* hclk_vio gates */
+	GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS),
+	GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS),
+	GATE(0, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS),
+	GATE(0, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS),
+	GATE(0, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS),
+	GATE(0, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS),
+	GATE(0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS),
+	GATE(0, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS),
+	GATE(0, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS),
+	GATE(0, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS),
+	GATE(0, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS),
+	GATE(0, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS),
+	GATE(0, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS),
+
+	/* aclk_vio0 gates */
+	GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS),
+	GATE(0, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(0, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS),
+	GATE(0, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS),
+
+	/* aclk_vio1 gates */
+	GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS),
+	GATE(0, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS),
+	GATE(0, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS),
+
+	/* aclk_rga_pre gates */
+	GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS),
+
+	/*
+	 * Other ungrouped clocks.
+	 */
+
+	GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+	GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+};
+
+static void __init rk3288_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+
+	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock usb480m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	rockchip_clk_register_plls(rk3288_pll_clks,
+				   ARRAY_SIZE(rk3288_pll_clks),
+				   RK3288_GRF_SOC_STATUS);
+	rockchip_clk_register_branches(rk3288_clk_branches,
+				  ARRAY_SIZE(rk3288_clk_branches));
+
+	rockchip_register_softrst(np, 9, reg_base + RK3288_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
+CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/Makefile
--- linux-libre-3.16-gnu/drivers/clk/rockchip/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,3 +3,9 @@
 #
 
 obj-y	+= clk-rockchip.o
+obj-y	+= clk.o
+obj-y	+= clk-pll.o
+obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
+
+obj-y	+= clk-rk3188.o
+obj-y	+= clk-rk3288.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/rockchip/softrst.c linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/softrst.c
--- linux-libre-3.16-gnu/drivers/clk/rockchip/softrst.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/rockchip/softrst.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.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/slab.h>
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_softrst {
+	struct reset_controller_dev	rcdev;
+	void __iomem			*reg_base;
+	int				num_regs;
+	int				num_per_reg;
+	u8				flags;
+	spinlock_t			lock;
+};
+
+static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct rockchip_softrst *softrst = container_of(rcdev,
+						     struct rockchip_softrst,
+						     rcdev);
+	int bank = id / softrst->num_per_reg;
+	int offset = id % softrst->num_per_reg;
+
+	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+		writel(BIT(offset) | (BIT(offset) << 16),
+		       softrst->reg_base + (bank * 4));
+	} else {
+		unsigned long flags;
+		u32 reg;
+
+		spin_lock_irqsave(&softrst->lock, flags);
+
+		reg = readl(softrst->reg_base + (bank * 4));
+		writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
+
+		spin_unlock_irqrestore(&softrst->lock, flags);
+	}
+
+	return 0;
+}
+
+static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct rockchip_softrst *softrst = container_of(rcdev,
+						     struct rockchip_softrst,
+						     rcdev);
+	int bank = id / softrst->num_per_reg;
+	int offset = id % softrst->num_per_reg;
+
+	if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+		writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
+	} else {
+		unsigned long flags;
+		u32 reg;
+
+		spin_lock_irqsave(&softrst->lock, flags);
+
+		reg = readl(softrst->reg_base + (bank * 4));
+		writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
+
+		spin_unlock_irqrestore(&softrst->lock, flags);
+	}
+
+	return 0;
+}
+
+static struct reset_control_ops rockchip_softrst_ops = {
+	.assert		= rockchip_softrst_assert,
+	.deassert	= rockchip_softrst_deassert,
+};
+
+void __init rockchip_register_softrst(struct device_node *np,
+				      unsigned int num_regs,
+				      void __iomem *base, u8 flags)
+{
+	struct rockchip_softrst *softrst;
+	int ret;
+
+	softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
+	if (!softrst)
+		return;
+
+	spin_lock_init(&softrst->lock);
+
+	softrst->reg_base = base;
+	softrst->flags = flags;
+	softrst->num_regs = num_regs;
+	softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
+								      : 32;
+
+	softrst->rcdev.owner = THIS_MODULE;
+	softrst->rcdev.nr_resets =  num_regs * softrst->num_per_reg;
+	softrst->rcdev.ops = &rockchip_softrst_ops;
+	softrst->rcdev.of_node = np;
+	ret = reset_controller_register(&softrst->rcdev);
+	if (ret) {
+		pr_err("%s: could not register reset controller, %d\n",
+		       __func__, ret);
+		kfree(softrst);
+	}
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,6 @@ struct samsung_clk_provider *__init sams
 {
 	struct samsung_clk_provider *ctx;
 	struct clk **clk_table;
-	int ret;
 	int i;
 
 	ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
@@ -72,17 +71,19 @@ struct samsung_clk_provider *__init sams
 	ctx->clk_data.clk_num = nr_clks;
 	spin_lock_init(&ctx->lock);
 
-	if (!np)
-		return ctx;
-
-	ret = of_clk_add_provider(np, of_clk_src_onecell_get,
-			&ctx->clk_data);
-	if (ret)
-		panic("could not register clock provide\n");
-
 	return ctx;
 }
 
+void __init samsung_clk_of_add_provider(struct device_node *np,
+				struct samsung_clk_provider *ctx)
+{
+	if (np) {
+		if (of_clk_add_provider(np, of_clk_src_onecell_get,
+					&ctx->clk_data))
+			panic("could not register clk provider\n");
+	}
+}
+
 /* add a clock instance to the clock lookup table used for dt based lookup */
 void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
 				unsigned int id)
@@ -284,7 +285,7 @@ void __init samsung_clk_register_gate(st
 void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
 			struct samsung_fixed_rate_clock *fixed_rate_clk,
 			unsigned int nr_fixed_rate_clk,
-			struct of_device_id *clk_matches)
+			const struct of_device_id *clk_matches)
 {
 	const struct of_device_id *match;
 	struct device_node *clk_np;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos3250.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos3250.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos3250.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos3250.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,22 @@
 #define SRC_CPU			0x14200
 #define DIV_CPU0		0x14500
 #define DIV_CPU1		0x14504
+#define PWR_CTRL1		0x15020
+#define PWR_CTRL2		0x15024
+
+/* Below definitions are used for PWR_CTRL settings */
+#define PWR_CTRL1_CORE2_DOWN_RATIO(x)		(((x) & 0x7) << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO(x)		(((x) & 0x7) << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN			(1 << 8)
+#define PWR_CTRL1_USE_CORE3_WFE			(1 << 7)
+#define PWR_CTRL1_USE_CORE2_WFE			(1 << 6)
+#define PWR_CTRL1_USE_CORE1_WFE			(1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE			(1 << 4)
+#define PWR_CTRL1_USE_CORE3_WFI			(1 << 3)
+#define PWR_CTRL1_USE_CORE2_WFI			(1 << 2)
+#define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
 
 /* list of PLLs to be registered */
 enum exynos3250_plls {
@@ -168,6 +184,8 @@ static unsigned long exynos3250_cmu_clk_
 	SRC_CPU,
 	DIV_CPU0,
 	DIV_CPU1,
+	PWR_CTRL1,
+	PWR_CTRL2,
 };
 
 static int exynos3250_clk_suspend(void)
@@ -748,6 +766,27 @@ static struct samsung_pll_clock exynos32
 			UPLL_LOCK, UPLL_CON0, NULL),
 };
 
+static void __init exynos3_core_down_clock(void)
+{
+	unsigned int tmp;
+
+	/*
+	 * Enable arm clock down (in idle) and set arm divider
+	 * ratios in WFI/WFE state.
+	 */
+	tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
+		PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
+		PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
+		PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
+	__raw_writel(tmp, reg_base + PWR_CTRL1);
+
+	/*
+	 * Disable the clock up feature on Exynos4x12, in case it was
+	 * enabled by bootloader.
+	 */
+	__raw_writel(0x0, reg_base + PWR_CTRL2);
+}
+
 static void __init exynos3250_cmu_init(struct device_node *np)
 {
 	struct samsung_clk_provider *ctx;
@@ -775,6 +814,10 @@ static void __init exynos3250_cmu_init(s
 	samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
 	samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
 
+	exynos3_core_down_clock();
+
 	exynos3250_clk_sleep_init();
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos4.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos4.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos4.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,10 +25,12 @@
 #define DIV_LEFTBUS		0x4500
 #define GATE_IP_LEFTBUS		0x4800
 #define E4X12_GATE_IP_IMAGE	0x4930
+#define CLKOUT_CMU_LEFTBUS	0x4a00
 #define SRC_RIGHTBUS		0x8200
 #define DIV_RIGHTBUS		0x8500
 #define GATE_IP_RIGHTBUS	0x8800
 #define E4X12_GATE_IP_PERIR	0x8960
+#define CLKOUT_CMU_RIGHTBUS	0x8a00
 #define EPLL_LOCK		0xc010
 #define VPLL_LOCK		0xc020
 #define EPLL_CON0		0xc110
@@ -98,6 +100,7 @@
 #define GATE_IP_PERIL		0xc950
 #define E4210_GATE_IP_PERIR	0xc960
 #define GATE_BLOCK		0xc970
+#define CLKOUT_CMU_TOP		0xca00
 #define E4X12_MPLL_LOCK		0x10008
 #define E4X12_MPLL_CON0		0x10108
 #define SRC_DMC			0x10200
@@ -105,6 +108,7 @@
 #define DIV_DMC0		0x10500
 #define DIV_DMC1		0x10504
 #define GATE_IP_DMC		0x10900
+#define CLKOUT_CMU_DMC		0x10a00
 #define APLL_LOCK		0x14000
 #define E4210_MPLL_LOCK		0x14008
 #define APLL_CON0		0x14100
@@ -114,11 +118,28 @@
 #define DIV_CPU1		0x14504
 #define GATE_SCLK_CPU		0x14800
 #define GATE_IP_CPU		0x14900
+#define CLKOUT_CMU_CPU		0x14a00
+#define PWR_CTRL1		0x15020
+#define E4X12_PWR_CTRL2		0x15024
 #define E4X12_DIV_ISP0		0x18300
 #define E4X12_DIV_ISP1		0x18304
 #define E4X12_GATE_ISP0		0x18800
 #define E4X12_GATE_ISP1		0x18804
 
+/* Below definitions are used for PWR_CTRL settings */
+#define PWR_CTRL1_CORE2_DOWN_RATIO(x)		(((x) & 0x7) << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO(x)		(((x) & 0x7) << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN			(1 << 8)
+#define PWR_CTRL1_USE_CORE3_WFE			(1 << 7)
+#define PWR_CTRL1_USE_CORE2_WFE			(1 << 6)
+#define PWR_CTRL1_USE_CORE1_WFE			(1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE			(1 << 4)
+#define PWR_CTRL1_USE_CORE3_WFI			(1 << 3)
+#define PWR_CTRL1_USE_CORE2_WFI			(1 << 2)
+#define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
+
 /* the exynos4 soc type */
 enum exynos4_soc {
 	EXYNOS4210,
@@ -155,6 +176,7 @@ static unsigned long exynos4210_clk_save
 	E4210_GATE_IP_LCD1,
 	E4210_GATE_IP_PERIR,
 	E4210_MPLL_CON0,
+	PWR_CTRL1,
 };
 
 static unsigned long exynos4x12_clk_save[] __initdata = {
@@ -164,6 +186,8 @@ static unsigned long exynos4x12_clk_save
 	E4X12_DIV_ISP,
 	E4X12_DIV_CAM1,
 	E4X12_MPLL_CON0,
+	PWR_CTRL1,
+	E4X12_PWR_CTRL2,
 };
 
 static unsigned long exynos4_clk_pll_regs[] __initdata = {
@@ -242,6 +266,11 @@ static unsigned long exynos4_clk_regs[]
 	DIV_CPU1,
 	GATE_SCLK_CPU,
 	GATE_IP_CPU,
+	CLKOUT_CMU_LEFTBUS,
+	CLKOUT_CMU_RIGHTBUS,
+	CLKOUT_CMU_TOP,
+	CLKOUT_CMU_DMC,
+	CLKOUT_CMU_CPU,
 };
 
 static const struct samsung_clk_reg_dump src_mask_suspend[] = {
@@ -397,10 +426,32 @@ PNAME(mout_audio2_p4210) = { "cdclk2", "
 				"sclk_epll", "sclk_vpll", };
 PNAME(mout_mixer_p4210)	= { "sclk_dac", "sclk_hdmi", };
 PNAME(mout_dac_p4210)	= { "sclk_vpll", "sclk_hdmiphy", };
+PNAME(mout_pwi_p4210) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+				"sclk_usbphy1", "sclk_hdmiphy", "none",
+				"sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+				"div_gdl", "div_gpl" };
+PNAME(clkout_right_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+				"div_gdr", "div_gpr" };
+PNAME(clkout_top_p4210) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+				"sclk_usbphy0", "sclk_usbphy1", "sclk_hdmiphy",
+				"cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+				"aclk160", "aclk133", "aclk200", "aclk100",
+				"sclk_mfc", "sclk_g3d", "sclk_g2d",
+				"cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+				"s_rxbyteclkhs0_4l" };
+PNAME(clkout_dmc_p4210) = { "div_dmcd", "div_dmcp", "div_acp_pclk", "div_dmc",
+				"div_dphy", "none", "div_pwi" };
+PNAME(clkout_cpu_p4210) = { "fout_apll_div_2", "none", "fout_mpll_div_2",
+				"none", "arm_clk_div_2", "div_corem0",
+				"div_corem1", "div_corem0", "div_atb",
+				"div_periph", "div_pclk_dbg", "div_hpm" };
 
 /* Exynos 4x12-specific parent groups */
 PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", };
 PNAME(mout_core_p4x12)	= { "mout_apll", "mout_mpll_user_c", };
+PNAME(mout_gdl_p4x12)	= { "mout_mpll_user_l", "sclk_apll", };
+PNAME(mout_gdr_p4x12)	= { "mout_mpll_user_r", "sclk_apll", };
 PNAME(sclk_ampll_p4x12)	= { "mout_mpll_user_t", "sclk_apll", };
 PNAME(group1_p4x12)	= { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
 				"none",	"sclk_hdmiphy", "mout_mpll_user_t",
@@ -418,6 +469,32 @@ PNAME(aclk_p4412)	= { "mout_mpll_user_t"
 PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", };
 PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
 PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
+PNAME(mout_pwi_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+				"none", "sclk_hdmiphy", "sclk_mpll",
+				"sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4x12) = { "sclk_mpll_user_l_div_2", "sclk_apll_div_2",
+				"div_gdl", "div_gpl" };
+PNAME(clkout_right_p4x12) = { "sclk_mpll_user_r_div_2", "sclk_apll_div_2",
+				"div_gdr", "div_gpr" };
+PNAME(clkout_top_p4x12) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+				"sclk_usbphy0", "none", "sclk_hdmiphy",
+				"cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+				"aclk160", "aclk133", "aclk200", "aclk100",
+				"sclk_mfc", "sclk_g3d", "aclk400_mcuisp",
+				"cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+				"s_rxbyteclkhs0_4l", "rx_half_byte_clk_csis0",
+				"rx_half_byte_clk_csis1", "div_jpeg",
+				"sclk_pwm_isp", "sclk_spi0_isp",
+				"sclk_spi1_isp", "sclk_uart_isp",
+				"sclk_mipihsi", "sclk_hdmi", "sclk_fimd0",
+				"sclk_pcm0" };
+PNAME(clkout_dmc_p4x12) = { "div_dmcd", "div_dmcp", "aclk_acp", "div_acp_pclk",
+				"div_dmc", "div_dphy", "fout_mpll_div_2",
+				"div_pwi", "none", "div_c2c", "div_c2c_aclk" };
+PNAME(clkout_cpu_p4x12) = { "fout_apll_div_2", "none", "none", "none",
+				"arm_clk_div_2", "div_corem0", "div_corem1",
+				"div_cores", "div_atb", "div_periph",
+				"div_pclk_dbg", "div_hpm" };
 
 /* fixed rate clocks generated outside the soc */
 static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
@@ -436,6 +513,24 @@ static struct samsung_fixed_rate_clock e
 	FRATE(0, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
 };
 
+static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = {
+	FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
+	FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
+	FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
+	FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
+	FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = {
+	FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0),
+	FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0),
+	FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0),
+	FFACTOR(0, "sclk_mpll_user_c_div_2", "mout_mpll_user_c", 1, 2, 0),
+};
+
 /* list of mux clocks supported in all exynos4 soc's */
 static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 	MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
@@ -451,6 +546,9 @@ static struct samsung_mux_clock exynos4_
 	MUX(0, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
 	MUX(CLK_SCLK_EPLL, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1),
 	MUX(0, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
+
+	MUX(0, "mout_dmc_bus", sclk_ampll_p4210, SRC_DMC, 4, 1),
+	MUX(0, "mout_dphy", sclk_ampll_p4210, SRC_DMC, 8, 1),
 };
 
 /* list of mux clocks supported in exynos4210 soc */
@@ -459,6 +557,14 @@ static struct samsung_mux_clock exynos42
 };
 
 static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+	MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1),
+	MUX(0, "mout_clkout_leftbus", clkout_left_p4210,
+			CLKOUT_CMU_LEFTBUS, 0, 5),
+
+	MUX(0, "mout_gdr", sclk_ampll_p4210, SRC_RIGHTBUS, 0, 1),
+	MUX(0, "mout_clkout_rightbus", clkout_right_p4210,
+			CLKOUT_CMU_RIGHTBUS, 0, 5),
+
 	MUX(0, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
 	MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
 	MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
@@ -472,6 +578,7 @@ static struct samsung_mux_clock exynos42
 	MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
 	MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
 	MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
+	MUX(0, "mout_hpm", mout_core_p4210, SRC_CPU, 20, 1),
 	MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
 	MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
 	MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
@@ -503,12 +610,30 @@ static struct samsung_mux_clock exynos42
 	MUX(0, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4),
 	MUX(0, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4),
 	MUX(0, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4),
+	MUX(0, "mout_clkout_top", clkout_top_p4210, CLKOUT_CMU_TOP, 0, 5),
+
+	MUX(0, "mout_pwi", mout_pwi_p4210, SRC_DMC, 16, 4),
+	MUX(0, "mout_clkout_dmc", clkout_dmc_p4210, CLKOUT_CMU_DMC, 0, 5),
+
+	MUX(0, "mout_clkout_cpu", clkout_cpu_p4210, CLKOUT_CMU_CPU, 0, 5),
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
 static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+	MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1),
+	MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1),
+	MUX(0, "mout_clkout_leftbus", clkout_left_p4x12,
+			CLKOUT_CMU_LEFTBUS, 0, 5),
+
+	MUX(0, "mout_mpll_user_r", mout_mpll_p, SRC_RIGHTBUS, 4, 1),
+	MUX(0, "mout_gdr", mout_gdr_p4x12, SRC_RIGHTBUS, 0, 1),
+	MUX(0, "mout_clkout_rightbus", clkout_right_p4x12,
+			CLKOUT_CMU_RIGHTBUS, 0, 5),
+
 	MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p4x12,
 			SRC_CPU, 24, 1),
+	MUX(0, "mout_clkout_cpu", clkout_cpu_p4x12, CLKOUT_CMU_CPU, 0, 5),
+
 	MUX(0, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
 	MUX(0, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
 	MUX(CLK_MOUT_MPLL_USER_T, "mout_mpll_user_t", mout_mpll_user_p4x12,
@@ -531,6 +656,7 @@ static struct samsung_mux_clock exynos4x
 	MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
 	MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
 	MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
+	MUX(0, "mout_hpm", mout_core_p4x12, SRC_CPU, 20, 1),
 	MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
 	MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
 	MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
@@ -565,15 +691,39 @@ static struct samsung_mux_clock exynos4x
 	MUX(0, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4),
 	MUX(0, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4),
 	MUX(0, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4),
+	MUX(0, "mout_clkout_top", clkout_top_p4x12, CLKOUT_CMU_TOP, 0, 5),
+
+	MUX(0, "mout_c2c", sclk_ampll_p4210, SRC_DMC, 0, 1),
+	MUX(0, "mout_pwi", mout_pwi_p4x12, SRC_DMC, 16, 4),
 	MUX(0, "mout_g2d0", sclk_ampll_p4210, SRC_DMC, 20, 1),
 	MUX(0, "mout_g2d1", sclk_evpll_p, SRC_DMC, 24, 1),
 	MUX(0, "mout_g2d", mout_g2d_p, SRC_DMC, 28, 1),
+	MUX(0, "mout_clkout_dmc", clkout_dmc_p4x12, CLKOUT_CMU_DMC, 0, 5),
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
 static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+	DIV(0, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
+	DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
+	DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
+			CLKOUT_CMU_LEFTBUS, 8, 6),
+
+	DIV(0, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3),
+	DIV(0, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3),
+	DIV(0, "div_clkout_rightbus", "mout_clkout_rightbus",
+			CLKOUT_CMU_RIGHTBUS, 8, 6),
+
 	DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
+	DIV(0, "div_corem0", "div_core2", DIV_CPU0, 4, 3),
+	DIV(0, "div_corem1", "div_core2", DIV_CPU0, 8, 3),
+	DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
+	DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
+	DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
 	DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
+	DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
+	DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
+	DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
+
 	DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
 	DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
 	DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
@@ -631,6 +781,16 @@ static struct samsung_div_clock exynos4_
 			CLK_SET_RATE_PARENT, 0),
 	DIV_F(0, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
 			CLK_SET_RATE_PARENT, 0),
+	DIV(0, "div_clkout_top", "mout_clkout_top", CLKOUT_CMU_TOP, 8, 6),
+
+	DIV(0, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3),
+	DIV(0, "div_acp_pclk", "div_acp", DIV_DMC0, 4, 3),
+	DIV(0, "div_dphy", "mout_dphy", DIV_DMC0, 8, 3),
+	DIV(0, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3),
+	DIV(0, "div_dmcd", "div_dmc", DIV_DMC0, 16, 3),
+	DIV(0, "div_dmcp", "div_dmcd", DIV_DMC0, 20, 3),
+	DIV(0, "div_pwi", "mout_pwi", DIV_DMC1, 8, 4),
+	DIV(0, "div_clkout_dmc", "mout_clkout_dmc", CLKOUT_CMU_DMC, 8, 6),
 };
 
 /* list of divider clocks supported in exynos4210 soc */
@@ -671,6 +831,8 @@ static struct samsung_div_clock exynos4x
 	DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
 						8, 3, CLK_GET_RATE_NOCACHE, 0),
 	DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
+	DIV(0, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
+	DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
@@ -680,6 +842,8 @@ static struct samsung_gate_clock exynos4
 	 * the device name and clock alias names specified below for some
 	 * of the clocks can be removed.
 	 */
+	GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0),
+	GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0),
 	GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
 	GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0,
 		0),
@@ -695,11 +859,13 @@ static struct samsung_gate_clock exynos4
 	GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
 	GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0,
 			CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0),
 	GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
 	GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
 	GATE(CLK_NFCON, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
 	GATE(CLK_GPS, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0),
 	GATE(CLK_SMMU_GPS, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0),
+	GATE(CLK_PPMUGPS, "ppmugps", "aclk200", GATE_IP_GPS, 2, 0, 0),
 	GATE(CLK_SLIMBUS, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0),
 	GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4,
 			CLK_SET_RATE_PARENT, 0),
@@ -781,19 +947,24 @@ static struct samsung_gate_clock exynos4
 			0, 0),
 	GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11,
 			0, 0),
+	GATE(CLK_PPMUCAMIF, "ppmucamif", "aclk160", GATE_IP_CAM, 16, 0, 0),
 	GATE(CLK_PIXELASYNCM0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
 	GATE(CLK_PIXELASYNCM1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
 	GATE(CLK_SMMU_TV, "smmu_tv", "aclk160", GATE_IP_TV, 4,
 			0, 0),
+	GATE(CLK_PPMUTV, "ppmutv", "aclk160", GATE_IP_TV, 5, 0, 0),
 	GATE(CLK_MFC, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0),
 	GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1,
 			0, 0),
 	GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2,
 			0, 0),
+	GATE(CLK_PPMUMFC_L, "ppmumfc_l", "aclk100", GATE_IP_MFC, 3, 0, 0),
+	GATE(CLK_PPMUMFC_R, "ppmumfc_r", "aclk100", GATE_IP_MFC, 4, 0, 0),
 	GATE(CLK_FIMD0, "fimd0", "aclk160", GATE_IP_LCD0, 0,
 			0, 0),
 	GATE(CLK_SMMU_FIMD0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4,
 			0, 0),
+	GATE(CLK_PPMULCD0, "ppmulcd0", "aclk160", GATE_IP_LCD0, 5, 0, 0),
 	GATE(CLK_PDMA0, "pdma0", "aclk133", GATE_IP_FSYS, 0,
 			0, 0),
 	GATE(CLK_PDMA1, "pdma1", "aclk133", GATE_IP_FSYS, 1,
@@ -806,6 +977,7 @@ static struct samsung_gate_clock exynos4
 			0, 0),
 	GATE(CLK_SDMMC3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8,
 			0, 0),
+	GATE(CLK_PPMUFILE, "ppmufile", "aclk133", GATE_IP_FSYS, 17, 0, 0),
 	GATE(CLK_UART0, "uart0", "aclk100", GATE_IP_PERIL, 0,
 			0, 0),
 	GATE(CLK_UART1, "uart1", "aclk100", GATE_IP_PERIL, 1,
@@ -852,6 +1024,21 @@ static struct samsung_gate_clock exynos4
 			0, 0),
 	GATE(CLK_AC97, "ac97", "aclk100", GATE_IP_PERIL, 27,
 			0, 0),
+	GATE(CLK_PPMUDMC0, "ppmudmc0", "aclk133", GATE_IP_DMC, 8, 0, 0),
+	GATE(CLK_PPMUDMC1, "ppmudmc1", "aclk133", GATE_IP_DMC, 9, 0, 0),
+	GATE(CLK_PPMUCPU, "ppmucpu", "aclk133", GATE_IP_DMC, 10, 0, 0),
+	GATE(CLK_PPMUACP, "ppmuacp", "aclk133", GATE_IP_DMC, 16, 0, 0),
+
+	GATE(CLK_OUT_LEFTBUS, "clkout_leftbus", "div_clkout_leftbus",
+			CLKOUT_CMU_LEFTBUS, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_OUT_RIGHTBUS, "clkout_rightbus", "div_clkout_rightbus",
+			CLKOUT_CMU_RIGHTBUS, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_OUT_TOP, "clkout_top", "div_clkout_top",
+			CLKOUT_CMU_TOP, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_OUT_DMC, "clkout_dmc", "div_clkout_dmc",
+			CLKOUT_CMU_DMC, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_OUT_CPU, "clkout_cpu", "div_clkout_cpu",
+			CLKOUT_CMU_CPU, 16, CLK_SET_RATE_PARENT, 0),
 };
 
 /* list of gate clocks supported in exynos4210 soc */
@@ -863,6 +1050,9 @@ static struct samsung_gate_clock exynos4
 	GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0),
 	GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0,
 		0),
+	GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4210_GATE_IP_IMAGE, 9, 0,
+		0),
+	GATE(CLK_PPMULCD1, "ppmulcd1", "aclk160", E4210_GATE_IP_LCD1, 5, 0, 0),
 	GATE(CLK_PCIE_PHY, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0),
 	GATE(CLK_SATA_PHY, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0),
 	GATE(CLK_SATA, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0),
@@ -906,6 +1096,8 @@ static struct samsung_gate_clock exynos4
 	GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
 	GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0,
 		0),
+	GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0,
+		0),
 	GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
 	GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
 	GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
@@ -1062,7 +1254,7 @@ static void __init exynos4_clk_register_
 
 }
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
 	{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
 	{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
 	{},
@@ -1164,6 +1356,32 @@ static struct samsung_pll_clock exynos4x
 			VPLL_LOCK, VPLL_CON0, NULL),
 };
 
+static void __init exynos4_core_down_clock(enum exynos4_soc soc)
+{
+	unsigned int tmp;
+
+	/*
+	 * Enable arm clock down (in idle) and set arm divider
+	 * ratios in WFI/WFE state.
+	 */
+	tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
+		PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
+		PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
+		PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
+	/* On Exynos4412 enable it also on core 2 and 3 */
+	if (num_possible_cpus() == 4)
+		tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
+		       PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
+	__raw_writel(tmp, reg_base + PWR_CTRL1);
+
+	/*
+	 * Disable the clock up feature on Exynos4x12, in case it was
+	 * enabled by bootloader.
+	 */
+	if (exynos4_soc == EXYNOS4X12)
+		__raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+}
+
 /* register exynos4 clocks */
 static void __init exynos4_clk_init(struct device_node *np,
 				    enum exynos4_soc soc)
@@ -1224,6 +1442,8 @@ static void __init exynos4_clk_init(stru
 			ARRAY_SIZE(exynos4_div_clks));
 	samsung_clk_register_gate(ctx, exynos4_gate_clks,
 			ARRAY_SIZE(exynos4_gate_clks));
+	samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
+			ARRAY_SIZE(exynos4_fixed_factor_clks));
 
 	if (exynos4_soc == EXYNOS4210) {
 		samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
@@ -1236,6 +1456,9 @@ static void __init exynos4_clk_init(stru
 			ARRAY_SIZE(exynos4210_gate_clks));
 		samsung_clk_register_alias(ctx, exynos4210_aliases,
 			ARRAY_SIZE(exynos4210_aliases));
+		samsung_clk_register_fixed_factor(ctx,
+			exynos4210_fixed_factor_clks,
+			ARRAY_SIZE(exynos4210_fixed_factor_clks));
 	} else {
 		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
 			ARRAY_SIZE(exynos4x12_mux_clks));
@@ -1245,13 +1468,19 @@ static void __init exynos4_clk_init(stru
 			ARRAY_SIZE(exynos4x12_gate_clks));
 		samsung_clk_register_alias(ctx, exynos4x12_aliases,
 			ARRAY_SIZE(exynos4x12_aliases));
+		samsung_clk_register_fixed_factor(ctx,
+			exynos4x12_fixed_factor_clks,
+			ARRAY_SIZE(exynos4x12_fixed_factor_clks));
 	}
 
 	samsung_clk_register_alias(ctx, exynos4_aliases,
 			ARRAY_SIZE(exynos4_aliases));
 
+	exynos4_core_down_clock(soc);
 	exynos4_clk_sleep_init();
 
+	samsung_clk_of_add_provider(np, ctx);
+
 	pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
 		"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
 		exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5250.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5250.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5250.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5250.c	2014-09-28 17:29:07.000000000 -0400
@@ -748,7 +748,7 @@ static struct samsung_pll_clock exynos52
 		VPLL_LOCK, VPLL_CON0, NULL),
 };
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
 	{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
 	{ },
 };
@@ -820,6 +820,8 @@ static void __init exynos5250_clk_init(s
 
 	exynos5250_clk_sleep_init();
 
+	samsung_clk_of_add_provider(np, ctx);
+
 	pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
 			_get_rate("div_arm2"));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5260.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5260.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5260.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5260.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,6 +206,8 @@ void __init exynos5260_cmu_register_one(
 	if (cmu->clk_regs)
 		exynos5260_clk_sleep_init(reg_base, cmu->clk_regs,
 			cmu->nr_clk_regs);
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5410.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5410.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5410.c	2014-09-28 17:29:07.000000000 -0400
@@ -204,6 +204,8 @@ static void __init exynos5410_clk_init(s
 	samsung_clk_register_gate(ctx, exynos5410_gate_clks,
 			ARRAY_SIZE(exynos5410_gate_clks));
 
+	samsung_clk_of_add_provider(np, ctx);
+
 	pr_debug("Exynos5410: clock setup completed.\n");
 }
 CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5420.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5420.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5420.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5420.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #define GATE_BUS_CPU		0x700
 #define GATE_SCLK_CPU		0x800
 #define CLKOUT_CMU_CPU		0xa00
+#define SRC_MASK_CPERI		0x4300
 #define GATE_IP_G2D		0x8800
 #define CPLL_LOCK		0x10020
 #define DPLL_LOCK		0x10030
@@ -70,6 +71,8 @@
 #define SRC_TOP11		0x10284
 #define SRC_TOP12		0x10288
 #define SRC_TOP13		0x1028c /* 5800 specific */
+#define SRC_MASK_TOP0		0x10300
+#define SRC_MASK_TOP1		0x10304
 #define SRC_MASK_TOP2		0x10308
 #define SRC_MASK_TOP7		0x1031c
 #define SRC_MASK_DISP10		0x1032c
@@ -77,6 +80,7 @@
 #define SRC_MASK_FSYS		0x10340
 #define SRC_MASK_PERIC0		0x10350
 #define SRC_MASK_PERIC1		0x10354
+#define SRC_MASK_ISP		0x10370
 #define DIV_TOP0		0x10500
 #define DIV_TOP1		0x10504
 #define DIV_TOP2		0x10508
@@ -98,6 +102,7 @@
 #define DIV2_RATIO0		0x10590
 #define DIV4_RATIO		0x105a0
 #define GATE_BUS_TOP		0x10700
+#define GATE_BUS_DISP1		0x10728
 #define GATE_BUS_GEN		0x1073c
 #define GATE_BUS_FSYS0		0x10740
 #define GATE_BUS_FSYS2		0x10748
@@ -190,6 +195,10 @@ static unsigned long exynos5x_clk_regs[]
 	SRC_MASK_FSYS,
 	SRC_MASK_PERIC0,
 	SRC_MASK_PERIC1,
+	SRC_MASK_TOP0,
+	SRC_MASK_TOP1,
+	SRC_MASK_MAU,
+	SRC_MASK_ISP,
 	SRC_ISP,
 	DIV_TOP0,
 	DIV_TOP1,
@@ -208,6 +217,7 @@ static unsigned long exynos5x_clk_regs[]
 	SCLK_DIV_ISP1,
 	DIV2_RATIO0,
 	DIV4_RATIO,
+	GATE_BUS_DISP1,
 	GATE_BUS_TOP,
 	GATE_BUS_GEN,
 	GATE_BUS_FSYS0,
@@ -249,6 +259,22 @@ static unsigned long exynos5800_clk_regs
 	GATE_IP_CAM,
 };
 
+static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = {
+	{ .offset = SRC_MASK_CPERI,		.value = 0xffffffff, },
+	{ .offset = SRC_MASK_TOP0,		.value = 0x11111111, },
+	{ .offset = SRC_MASK_TOP1,		.value = 0x11101111, },
+	{ .offset = SRC_MASK_TOP2,		.value = 0x11111110, },
+	{ .offset = SRC_MASK_TOP7,		.value = 0x00111100, },
+	{ .offset = SRC_MASK_DISP10,		.value = 0x11111110, },
+	{ .offset = SRC_MASK_MAU,		.value = 0x10000000, },
+	{ .offset = SRC_MASK_FSYS,		.value = 0x11111110, },
+	{ .offset = SRC_MASK_PERIC0,		.value = 0x11111110, },
+	{ .offset = SRC_MASK_PERIC1,		.value = 0x11111100, },
+	{ .offset = SRC_MASK_ISP,		.value = 0x11111000, },
+	{ .offset = GATE_BUS_DISP1,		.value = 0xffffffff, },
+	{ .offset = GATE_IP_PERIC,		.value = 0xffffffff, },
+};
+
 static int exynos5420_clk_suspend(void)
 {
 	samsung_clk_save(reg_base, exynos5x_save,
@@ -258,6 +284,9 @@ static int exynos5420_clk_suspend(void)
 		samsung_clk_save(reg_base, exynos5800_save,
 				ARRAY_SIZE(exynos5800_clk_regs));
 
+	samsung_clk_restore(reg_base, exynos5420_set_clksrc,
+				ARRAY_SIZE(exynos5420_set_clksrc));
+
 	return 0;
 }
 
@@ -1169,6 +1198,28 @@ static struct samsung_gate_clock exynos5
 	GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
 };
 
+static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = {
+	PLL_35XX_RATE(2000000000, 250, 3, 0),
+	PLL_35XX_RATE(1900000000, 475, 6, 0),
+	PLL_35XX_RATE(1800000000, 225, 3, 0),
+	PLL_35XX_RATE(1700000000, 425, 6, 0),
+	PLL_35XX_RATE(1600000000, 200, 3, 0),
+	PLL_35XX_RATE(1500000000, 250, 4, 0),
+	PLL_35XX_RATE(1400000000, 175, 3, 0),
+	PLL_35XX_RATE(1300000000, 325, 6, 0),
+	PLL_35XX_RATE(1200000000, 200, 2, 1),
+	PLL_35XX_RATE(1100000000, 275, 3, 1),
+	PLL_35XX_RATE(1000000000, 250, 3, 1),
+	PLL_35XX_RATE(900000000,  150, 2, 1),
+	PLL_35XX_RATE(800000000,  200, 3, 1),
+	PLL_35XX_RATE(700000000,  175, 3, 1),
+	PLL_35XX_RATE(600000000,  200, 2, 2),
+	PLL_35XX_RATE(500000000,  250, 3, 2),
+	PLL_35XX_RATE(400000000,  200, 3, 2),
+	PLL_35XX_RATE(300000000,  200, 2, 3),
+	PLL_35XX_RATE(200000000,  200, 3, 3),
+};
+
 static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
 	[apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, NULL),
@@ -1194,7 +1245,7 @@ static struct samsung_pll_clock exynos5x
 		KPLL_CON0, NULL),
 };
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
 	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
 	{ },
 };
@@ -1222,6 +1273,12 @@ static void __init exynos5x_clk_init(str
 	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
 			ext_clk_match);
+
+	if (_get_rate("fin_pll") == 24 * MHZ) {
+		exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+		exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+	}
+
 	samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
 					reg_base);
 	samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
@@ -1253,6 +1310,8 @@ static void __init exynos5x_clk_init(str
 	}
 
 	exynos5420_clk_sleep_init();
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 
 static void __init exynos5420_clk_init(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5440.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5440.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos5440.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos5440.c	2014-09-28 17:29:07.000000000 -0400
@@ -84,7 +84,7 @@ static struct samsung_gate_clock exynos5
 	GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
 };
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
 	{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
 	{},
 };
@@ -123,6 +123,8 @@ static void __init exynos5440_clk_init(s
 	samsung_clk_register_gate(ctx, exynos5440_gate_clks,
 			ARRAY_SIZE(exynos5440_gate_clks));
 
+	samsung_clk_of_add_provider(np, ctx);
+
 	pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
 	pr_info("exynos5440 clock initialization complete\n");
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos-clkout.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos-clkout.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-exynos-clkout.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-exynos-clkout.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Tomasz Figa <t.figa@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.
+ *
+ * Clock driver for Exynos clock output
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define EXYNOS_CLKOUT_NR_CLKS		1
+#define EXYNOS_CLKOUT_PARENTS		32
+
+#define EXYNOS_PMU_DEBUG_REG		0xa00
+#define EXYNOS_CLKOUT_DISABLE_SHIFT	0
+#define EXYNOS_CLKOUT_MUX_SHIFT		8
+#define EXYNOS4_CLKOUT_MUX_MASK		0xf
+#define EXYNOS5_CLKOUT_MUX_MASK		0x1f
+
+struct exynos_clkout {
+	struct clk_gate gate;
+	struct clk_mux mux;
+	spinlock_t slock;
+	struct clk_onecell_data data;
+	struct clk *clk_table[EXYNOS_CLKOUT_NR_CLKS];
+	void __iomem *reg;
+	u32 pmu_debug_save;
+};
+
+static struct exynos_clkout *clkout;
+
+static int exynos_clkout_suspend(void)
+{
+	clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
+
+	return 0;
+}
+
+static void exynos_clkout_resume(void)
+{
+	writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
+}
+
+static struct syscore_ops exynos_clkout_syscore_ops = {
+	.suspend = exynos_clkout_suspend,
+	.resume = exynos_clkout_resume,
+};
+
+static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
+{
+	const char *parent_names[EXYNOS_CLKOUT_PARENTS];
+	struct clk *parents[EXYNOS_CLKOUT_PARENTS];
+	int parent_count;
+	int ret;
+	int i;
+
+	clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
+	if (!clkout)
+		return;
+
+	spin_lock_init(&clkout->slock);
+
+	parent_count = 0;
+	for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i) {
+		char name[] = "clkoutXX";
+
+		snprintf(name, sizeof(name), "clkout%d", i);
+		parents[i] = of_clk_get_by_name(node, name);
+		if (IS_ERR(parents[i])) {
+			parent_names[i] = "none";
+			continue;
+		}
+
+		parent_names[i] = __clk_get_name(parents[i]);
+		parent_count = i + 1;
+	}
+
+	if (!parent_count)
+		goto free_clkout;
+
+	clkout->reg = of_iomap(node, 0);
+	if (!clkout->reg)
+		goto clks_put;
+
+	clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
+	clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT;
+	clkout->gate.flags = CLK_GATE_SET_TO_DISABLE;
+	clkout->gate.lock = &clkout->slock;
+
+	clkout->mux.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
+	clkout->mux.mask = mux_mask;
+	clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
+	clkout->mux.lock = &clkout->slock;
+
+	clkout->clk_table[0] = clk_register_composite(NULL, "clkout",
+				parent_names, parent_count, &clkout->mux.hw,
+				&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
+				&clk_gate_ops, CLK_SET_RATE_PARENT
+				| CLK_SET_RATE_NO_REPARENT);
+	if (IS_ERR(clkout->clk_table[0]))
+		goto err_unmap;
+
+	clkout->data.clks = clkout->clk_table;
+	clkout->data.clk_num = EXYNOS_CLKOUT_NR_CLKS;
+	ret = of_clk_add_provider(node, of_clk_src_onecell_get, &clkout->data);
+	if (ret)
+		goto err_clk_unreg;
+
+	register_syscore_ops(&exynos_clkout_syscore_ops);
+
+	return;
+
+err_clk_unreg:
+	clk_unregister(clkout->clk_table[0]);
+err_unmap:
+	iounmap(clkout->reg);
+clks_put:
+	for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i)
+		if (!IS_ERR(parents[i]))
+			clk_put(parents[i]);
+free_clkout:
+	kfree(clkout);
+
+	pr_err("%s: failed to register clkout clock\n", __func__);
+}
+
+static void __init exynos4_clkout_init(struct device_node *node)
+{
+	exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK);
+}
+CLK_OF_DECLARE(exynos4210_clkout, "samsung,exynos4210-pmu",
+		exynos4_clkout_init);
+CLK_OF_DECLARE(exynos4212_clkout, "samsung,exynos4212-pmu",
+		exynos4_clkout_init);
+CLK_OF_DECLARE(exynos4412_clkout, "samsung,exynos4412-pmu",
+		exynos4_clkout_init);
+
+static void __init exynos5_clkout_init(struct device_node *node)
+{
+	exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK);
+}
+CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
+		exynos5_clkout_init);
+CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
+		exynos5_clkout_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk.h linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk.h
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk.h	2014-09-28 17:29:07.000000000 -0400
@@ -327,11 +327,13 @@ struct samsung_pll_clock {
 extern struct samsung_clk_provider *__init samsung_clk_init(
 			struct device_node *np, void __iomem *base,
 			unsigned long nr_clks);
+extern void __init samsung_clk_of_add_provider(struct device_node *np,
+			struct samsung_clk_provider *ctx);
 extern void __init samsung_clk_of_register_fixed_ext(
 			struct samsung_clk_provider *ctx,
 			struct samsung_fixed_rate_clock *fixed_rate_clk,
 			unsigned int nr_fixed_rate_clk,
-			struct of_device_id *clk_matches);
+			const struct of_device_id *clk_matches);
 
 extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
 			struct clk *clk, unsigned int id);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2410.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2410.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2410.c	2014-09-28 17:29:07.000000000 -0400
@@ -466,6 +466,8 @@ void __init s3c2410_common_clk_init(stru
 	}
 
 	s3c2410_clk_sleep_init();
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 
 static void __init s3c2410_clk_init(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2412.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2412.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2412.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2412.c	2014-09-28 17:29:07.000000000 -0400
@@ -265,6 +265,8 @@ void __init s3c2412_common_clk_init(stru
 				   ARRAY_SIZE(s3c2412_aliases));
 
 	s3c2412_clk_sleep_init();
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 
 static void __init s3c2412_clk_init(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2443.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2443.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c2443.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c2443.c	2014-09-28 17:29:07.000000000 -0400
@@ -445,6 +445,8 @@ void __init s3c2443_common_clk_init(stru
 	}
 
 	s3c2443_clk_sleep_init();
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 
 static void __init s3c2416_clk_init(struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c64xx.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c64xx.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s3c64xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s3c64xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -518,6 +518,8 @@ void __init s3c64xx_clk_init(struct devi
 					ARRAY_SIZE(s3c64xx_clock_aliases));
 	s3c64xx_clk_sleep_init();
 
+	samsung_clk_of_add_provider(np, ctx);
+
 	pr_info("%s clocks: apll = %lu, mpll = %lu\n"
 		"\tepll = %lu, arm_clk = %lu\n",
 		is_s3c6400 ? "S3C6400" : "S3C6410",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s5pv210-audss.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s5pv210-audss.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s5pv210-audss.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s5pv210-audss.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
+ *
+ * Based on Exynos Audio Subsystem Clock Controller driver:
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Padmavathi Venna <padma.v@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.
+ *
+ * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
+*/
+
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/s5pv210-audss.h>
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+static struct clk_onecell_data clk_data;
+
+#define ASS_CLK_SRC 0x0
+#define ASS_CLK_DIV 0x4
+#define ASS_CLK_GATE 0x8
+
+#ifdef CONFIG_PM_SLEEP
+static unsigned long reg_save[][2] = {
+	{ASS_CLK_SRC,  0},
+	{ASS_CLK_DIV,  0},
+	{ASS_CLK_GATE, 0},
+};
+
+static int s5pv210_audss_clk_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+		reg_save[i][1] = readl(reg_base + reg_save[i][0]);
+
+	return 0;
+}
+
+static void s5pv210_audss_clk_resume(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+		writel(reg_save[i][1], reg_base + reg_save[i][0]);
+}
+
+static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
+	.suspend	= s5pv210_audss_clk_suspend,
+	.resume		= s5pv210_audss_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+/* register s5pv210_audss clocks */
+static int s5pv210_audss_clk_probe(struct platform_device *pdev)
+{
+	int i, ret = 0;
+	struct resource *res;
+	const char *mout_audss_p[2];
+	const char *mout_i2s_p[3];
+	const char *hclk_p;
+	struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg_base)) {
+		dev_err(&pdev->dev, "failed to map audss registers\n");
+		return PTR_ERR(reg_base);
+	}
+
+	clk_table = devm_kzalloc(&pdev->dev,
+				sizeof(struct clk *) * AUDSS_MAX_CLKS,
+				GFP_KERNEL);
+	if (!clk_table)
+		return -ENOMEM;
+
+	clk_data.clks = clk_table;
+	clk_data.clk_num = AUDSS_MAX_CLKS;
+
+	hclk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(hclk)) {
+		dev_err(&pdev->dev, "failed to get hclk clock\n");
+		return PTR_ERR(hclk);
+	}
+
+	pll_in = devm_clk_get(&pdev->dev, "fout_epll");
+	if (IS_ERR(pll_in)) {
+		dev_err(&pdev->dev, "failed to get fout_epll clock\n");
+		return PTR_ERR(pll_in);
+	}
+
+	sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
+	if (IS_ERR(sclk_audio)) {
+		dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
+		return PTR_ERR(sclk_audio);
+	}
+
+	/* iiscdclk0 is an optional external I2S codec clock */
+	cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
+	pll_ref = devm_clk_get(&pdev->dev, "xxti");
+
+	if (!IS_ERR(pll_ref))
+		mout_audss_p[0] = __clk_get_name(pll_ref);
+	else
+		mout_audss_p[0] = "xxti";
+	mout_audss_p[1] = __clk_get_name(pll_in);
+	clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+				mout_audss_p, ARRAY_SIZE(mout_audss_p),
+				CLK_SET_RATE_NO_REPARENT,
+				reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
+
+	mout_i2s_p[0] = "mout_audss";
+	if (!IS_ERR(cdclk))
+		mout_i2s_p[1] = __clk_get_name(cdclk);
+	else
+		mout_i2s_p[1] = "iiscdclk0";
+	mout_i2s_p[2] = __clk_get_name(sclk_audio);
+	clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
+				mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
+				CLK_SET_RATE_NO_REPARENT,
+				reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
+
+	clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
+				"dout_aud_bus", "mout_audss", 0,
+				reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
+	clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
+				"mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
+				4, 4, 0, &lock);
+
+	clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
+				"dout_i2s_audss", CLK_SET_RATE_PARENT,
+				reg_base + ASS_CLK_GATE, 6, 0, &lock);
+
+	hclk_p = __clk_get_name(hclk);
+
+	clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 5, 0, &lock);
+	clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 4, 0, &lock);
+	clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 3, 0, &lock);
+	clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 2, 0, &lock);
+	clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 1, 0, &lock);
+	clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
+				hclk_p, CLK_IGNORE_UNUSED,
+				reg_base + ASS_CLK_GATE, 0, 0, &lock);
+
+	for (i = 0; i < clk_data.clk_num; i++) {
+		if (IS_ERR(clk_table[i])) {
+			dev_err(&pdev->dev, "failed to register clock %d\n", i);
+			ret = PTR_ERR(clk_table[i]);
+			goto unregister;
+		}
+	}
+
+	ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+					&clk_data);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add clock provider\n");
+		goto unregister;
+	}
+
+#ifdef CONFIG_PM_SLEEP
+	register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
+#endif
+
+	return 0;
+
+unregister:
+	for (i = 0; i < clk_data.clk_num; i++) {
+		if (!IS_ERR(clk_table[i]))
+			clk_unregister(clk_table[i]);
+	}
+
+	return ret;
+}
+
+static int s5pv210_audss_clk_remove(struct platform_device *pdev)
+{
+	int i;
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	for (i = 0; i < clk_data.clk_num; i++) {
+		if (!IS_ERR(clk_table[i]))
+			clk_unregister(clk_table[i]);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id s5pv210_audss_clk_of_match[] = {
+	{ .compatible = "samsung,s5pv210-audss-clock", },
+	{},
+};
+
+static struct platform_driver s5pv210_audss_clk_driver = {
+	.driver	= {
+		.name = "s5pv210-audss-clk",
+		.owner = THIS_MODULE,
+		.of_match_table = s5pv210_audss_clk_of_match,
+	},
+	.probe = s5pv210_audss_clk_probe,
+	.remove = s5pv210_audss_clk_remove,
+};
+
+static int __init s5pv210_audss_clk_init(void)
+{
+	return platform_driver_register(&s5pv210_audss_clk_driver);
+}
+core_initcall(s5pv210_audss_clk_init);
+
+static void __exit s5pv210_audss_clk_exit(void)
+{
+	platform_driver_unregister(&s5pv210_audss_clk_driver);
+}
+module_exit(s5pv210_audss_clk_exit);
+
+MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
+MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:s5pv210-audss-clk");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/clk-s5pv210.c linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s5pv210.c
--- linux-libre-3.16-gnu/drivers/clk/samsung/clk-s5pv210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/clk-s5pv210.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ *
+ * Based on clock drivers for S3C64xx and Exynos4 SoCs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#include <dt-bindings/clock/s5pv210.h>
+
+/* S5PC110/S5PV210 clock controller register offsets */
+#define APLL_LOCK		0x0000
+#define MPLL_LOCK		0x0008
+#define EPLL_LOCK		0x0010
+#define VPLL_LOCK		0x0020
+#define APLL_CON0		0x0100
+#define APLL_CON1		0x0104
+#define MPLL_CON		0x0108
+#define EPLL_CON0		0x0110
+#define EPLL_CON1		0x0114
+#define VPLL_CON		0x0120
+#define CLK_SRC0		0x0200
+#define CLK_SRC1		0x0204
+#define CLK_SRC2		0x0208
+#define CLK_SRC3		0x020c
+#define CLK_SRC4		0x0210
+#define CLK_SRC5		0x0214
+#define CLK_SRC6		0x0218
+#define CLK_SRC_MASK0		0x0280
+#define CLK_SRC_MASK1		0x0284
+#define CLK_DIV0		0x0300
+#define CLK_DIV1		0x0304
+#define CLK_DIV2		0x0308
+#define CLK_DIV3		0x030c
+#define CLK_DIV4		0x0310
+#define CLK_DIV5		0x0314
+#define CLK_DIV6		0x0318
+#define CLK_DIV7		0x031c
+#define CLK_GATE_MAIN0		0x0400
+#define CLK_GATE_MAIN1		0x0404
+#define CLK_GATE_MAIN2		0x0408
+#define CLK_GATE_PERI0		0x0420
+#define CLK_GATE_PERI1		0x0424
+#define CLK_GATE_SCLK0		0x0440
+#define CLK_GATE_SCLK1		0x0444
+#define CLK_GATE_IP0		0x0460
+#define CLK_GATE_IP1		0x0464
+#define CLK_GATE_IP2		0x0468
+#define CLK_GATE_IP3		0x046c
+#define CLK_GATE_IP4		0x0470
+#define CLK_GATE_BLOCK		0x0480
+#define CLK_GATE_IP5		0x0484
+#define CLK_OUT			0x0500
+#define MISC			0xe000
+#define OM_STAT			0xe100
+
+/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
+enum {
+	apll,
+	mpll,
+	epll,
+	vpll,
+};
+
+/* IDs of external clocks (used for legacy boards) */
+enum {
+	xxti,
+	xusbxti,
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s5pv210_clk_dump;
+
+/* List of registers that need to be preserved across suspend/resume. */
+static unsigned long s5pv210_clk_regs[] __initdata = {
+	CLK_SRC0,
+	CLK_SRC1,
+	CLK_SRC2,
+	CLK_SRC3,
+	CLK_SRC4,
+	CLK_SRC5,
+	CLK_SRC6,
+	CLK_SRC_MASK0,
+	CLK_SRC_MASK1,
+	CLK_DIV0,
+	CLK_DIV1,
+	CLK_DIV2,
+	CLK_DIV3,
+	CLK_DIV4,
+	CLK_DIV5,
+	CLK_DIV6,
+	CLK_DIV7,
+	CLK_GATE_MAIN0,
+	CLK_GATE_MAIN1,
+	CLK_GATE_MAIN2,
+	CLK_GATE_PERI0,
+	CLK_GATE_PERI1,
+	CLK_GATE_SCLK0,
+	CLK_GATE_SCLK1,
+	CLK_GATE_IP0,
+	CLK_GATE_IP1,
+	CLK_GATE_IP2,
+	CLK_GATE_IP3,
+	CLK_GATE_IP4,
+	CLK_GATE_IP5,
+	CLK_GATE_BLOCK,
+	APLL_LOCK,
+	MPLL_LOCK,
+	EPLL_LOCK,
+	VPLL_LOCK,
+	APLL_CON0,
+	APLL_CON1,
+	MPLL_CON,
+	EPLL_CON0,
+	EPLL_CON1,
+	VPLL_CON,
+	CLK_OUT,
+};
+
+static int s5pv210_clk_suspend(void)
+{
+	samsung_clk_save(reg_base, s5pv210_clk_dump,
+				ARRAY_SIZE(s5pv210_clk_regs));
+	return 0;
+}
+
+static void s5pv210_clk_resume(void)
+{
+	samsung_clk_restore(reg_base, s5pv210_clk_dump,
+				ARRAY_SIZE(s5pv210_clk_regs));
+}
+
+static struct syscore_ops s5pv210_clk_syscore_ops = {
+	.suspend = s5pv210_clk_suspend,
+	.resume = s5pv210_clk_resume,
+};
+
+static void s5pv210_clk_sleep_init(void)
+{
+	s5pv210_clk_dump =
+		samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
+					   ARRAY_SIZE(s5pv210_clk_regs));
+	if (!s5pv210_clk_dump) {
+		pr_warn("%s: Failed to allocate sleep save data\n", __func__);
+		return;
+	}
+
+	register_syscore_ops(&s5pv210_clk_syscore_ops);
+}
+#else
+static inline void s5pv210_clk_sleep_init(void) { }
+#endif
+
+/* Mux parent lists. */
+static const char *fin_pll_p[] __initconst = {
+	"xxti",
+	"xusbxti"
+};
+
+static const char *mout_apll_p[] __initconst = {
+	"fin_pll",
+	"fout_apll"
+};
+
+static const char *mout_mpll_p[] __initconst = {
+	"fin_pll",
+	"fout_mpll"
+};
+
+static const char *mout_epll_p[] __initconst = {
+	"fin_pll",
+	"fout_epll"
+};
+
+static const char *mout_vpllsrc_p[] __initconst = {
+	"fin_pll",
+	"sclk_hdmi27m"
+};
+
+static const char *mout_vpll_p[] __initconst = {
+	"mout_vpllsrc",
+	"fout_vpll"
+};
+
+static const char *mout_group1_p[] __initconst = {
+	"dout_a2m",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll"
+};
+
+static const char *mout_group2_p[] __initconst = {
+	"xxti",
+	"xusbxti",
+	"sclk_hdmi27m",
+	"sclk_usbphy0",
+	"sclk_usbphy1",
+	"sclk_hdmiphy",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_audio0_p[] __initconst = {
+	"xxti",
+	"pcmcdclk0",
+	"sclk_hdmi27m",
+	"sclk_usbphy0",
+	"sclk_usbphy1",
+	"sclk_hdmiphy",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_audio1_p[] __initconst = {
+	"i2scdclk1",
+	"pcmcdclk1",
+	"sclk_hdmi27m",
+	"sclk_usbphy0",
+	"sclk_usbphy1",
+	"sclk_hdmiphy",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_audio2_p[] __initconst = {
+	"i2scdclk2",
+	"pcmcdclk2",
+	"sclk_hdmi27m",
+	"sclk_usbphy0",
+	"sclk_usbphy1",
+	"sclk_hdmiphy",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_spdif_p[] __initconst = {
+	"dout_audio0",
+	"dout_audio1",
+	"dout_audio3",
+};
+
+static const char *mout_group3_p[] __initconst = {
+	"mout_apll",
+	"mout_mpll"
+};
+
+static const char *mout_group4_p[] __initconst = {
+	"mout_mpll",
+	"dout_a2m"
+};
+
+static const char *mout_flash_p[] __initconst = {
+	"dout_hclkd",
+	"dout_hclkp"
+};
+
+static const char *mout_dac_p[] __initconst = {
+	"mout_vpll",
+	"sclk_hdmiphy"
+};
+
+static const char *mout_hdmi_p[] __initconst = {
+	"sclk_hdmiphy",
+	"dout_tblk"
+};
+
+static const char *mout_mixer_p[] __initconst = {
+	"mout_dac",
+	"mout_hdmi"
+};
+
+static const char *mout_vpll_6442_p[] __initconst = {
+	"fin_pll",
+	"fout_vpll"
+};
+
+static const char *mout_mixer_6442_p[] __initconst = {
+	"mout_vpll",
+	"dout_mixer"
+};
+
+static const char *mout_d0sync_6442_p[] __initconst = {
+	"mout_dsys",
+	"div_apll"
+};
+
+static const char *mout_d1sync_6442_p[] __initconst = {
+	"mout_psys",
+	"div_apll"
+};
+
+static const char *mout_group2_6442_p[] __initconst = {
+	"fin_pll",
+	"none",
+	"none",
+	"sclk_usbphy0",
+	"none",
+	"none",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_audio0_6442_p[] __initconst = {
+	"fin_pll",
+	"pcmcdclk0",
+	"none",
+	"sclk_usbphy0",
+	"none",
+	"none",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+};
+
+static const char *mout_audio1_6442_p[] __initconst = {
+	"i2scdclk1",
+	"pcmcdclk1",
+	"none",
+	"sclk_usbphy0",
+	"none",
+	"none",
+	"mout_mpll",
+	"mout_epll",
+	"mout_vpll",
+	"fin_pll",
+};
+
+static const char *mout_clksel_p[] __initconst = {
+	"fout_apll_clkout",
+	"fout_mpll_clkout",
+	"fout_epll",
+	"fout_vpll",
+	"sclk_usbphy0",
+	"sclk_usbphy1",
+	"sclk_hdmiphy",
+	"rtc",
+	"rtc_tick",
+	"dout_hclkm",
+	"dout_pclkm",
+	"dout_hclkd",
+	"dout_pclkd",
+	"dout_hclkp",
+	"dout_pclkp",
+	"dout_apll_clkout",
+	"dout_hpm",
+	"xxti",
+	"xusbxti",
+	"div_dclk"
+};
+
+static const char *mout_clksel_6442_p[] __initconst = {
+	"fout_apll_clkout",
+	"fout_mpll_clkout",
+	"fout_epll",
+	"fout_vpll",
+	"sclk_usbphy0",
+	"none",
+	"none",
+	"rtc",
+	"rtc_tick",
+	"none",
+	"none",
+	"dout_hclkd",
+	"dout_pclkd",
+	"dout_hclkp",
+	"dout_pclkp",
+	"dout_apll_clkout",
+	"none",
+	"fin_pll",
+	"none",
+	"div_dclk"
+};
+
+static const char *mout_clkout_p[] __initconst = {
+	"dout_clkout",
+	"none",
+	"xxti",
+	"xusbxti"
+};
+
+/* Common fixed factor clocks. */
+static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+	FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
+	FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
+	FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
+};
+
+/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
+static struct samsung_mux_clock early_mux_clks[] __initdata = {
+	MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
+					CLK_MUX_READ_ONLY, 0),
+};
+
+/* Common clock muxes. */
+static struct samsung_mux_clock mux_clks[] __initdata = {
+	MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
+	MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
+	MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
+	MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
+	MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
+	MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
+	MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
+
+	MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
+};
+
+/* S5PV210-specific clock muxes. */
+static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
+
+	MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
+	MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
+	MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
+	MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
+	MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
+	MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
+	MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
+	MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
+
+	MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
+	MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
+	MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
+
+	MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
+	MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
+	MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
+
+	MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
+	MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
+	MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
+	MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
+	MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
+	MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
+	MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
+	MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
+
+	MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
+	MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
+	MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
+
+	MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
+	MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
+	MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
+	MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
+	MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
+	MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
+	MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
+
+	MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
+};
+
+/* S5P6442-specific clock muxes. */
+static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
+
+	MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
+	MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
+	MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
+	MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
+
+	MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
+	MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
+
+	MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
+	MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
+	MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
+
+	MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
+	MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
+	MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
+	MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
+	MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
+	MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
+
+	MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
+	MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
+
+	MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
+	MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
+
+	MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
+};
+
+/* S5PV210-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+	FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+	FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* S5P6442-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
+};
+
+/* Common clock dividers. */
+static struct samsung_div_clock div_clks[] __initdata = {
+	DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
+	DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
+	DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
+	DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
+
+	DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
+	DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
+	DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
+
+	DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
+	DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
+	DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
+
+	DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
+	DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
+	DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
+	DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
+	DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
+	DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
+
+	DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
+	DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
+
+	DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
+	DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
+	DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
+
+	DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
+};
+
+/* S5PV210-specific clock dividers. */
+static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+	DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
+	DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
+	DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
+	DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
+
+	DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
+	DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
+
+	DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
+	DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
+	DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
+
+	DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
+	DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
+
+	DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
+
+	DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
+	DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
+	DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
+	DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
+	DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
+
+	DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
+	DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
+};
+
+/* S5P6442-specific clock dividers. */
+static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+	DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
+	DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
+
+	DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
+};
+
+/* Common clock gates. */
+static struct samsung_gate_clock gate_clks[] __initdata = {
+	GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
+	GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
+	GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
+	GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
+	GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
+	GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
+
+	GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
+	GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
+	GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
+	GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
+	GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
+	GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
+	GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
+
+	GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
+	GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
+	GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
+	GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
+	GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
+
+	GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
+	GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
+	GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
+	GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
+	GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
+	GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
+	GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
+	GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
+	GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
+	GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
+	GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
+	GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
+	GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
+	GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
+	GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
+	GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
+
+	GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
+	GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
+
+	GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
+			CLK_SET_RATE_PARENT, 0),
+
+	GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
+			CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5PV210-specific clock gates. */
+static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+	GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
+	GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
+	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+	GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
+	GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
+	GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
+
+	GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
+	GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
+	GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
+	GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
+	GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
+
+	GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
+	GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
+	GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
+	GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
+	GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
+	GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
+	GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
+	GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
+	GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
+
+	GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
+	GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
+	GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
+	GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
+			CLK_GATE_IP3, 11, 0, 0),
+	GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
+	GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
+	GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
+	GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
+
+	GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
+	GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
+	GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
+	GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
+	GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
+	GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
+
+	GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
+
+	GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
+			CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5P6442-specific clock gates. */
+static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+	GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
+	GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
+	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+	GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
+	GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
+
+	GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
+	GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
+
+	GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
+
+	GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
+			CLK_SET_RATE_PARENT, 0),
+};
+
+/*
+ * Clock aliases for legacy clkdev look-up.
+ * NOTE: Needed only to support legacy board files.
+ */
+static struct samsung_clock_alias s5pv210_aliases[] = {
+	ALIAS(DOUT_APLL, NULL, "armclk"),
+	ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
+	ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
+};
+
+/* S5PV210-specific PLLs. */
+static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+	[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
+						APLL_LOCK, APLL_CON0, NULL),
+	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+						MPLL_LOCK, MPLL_CON, NULL),
+	[epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
+						EPLL_LOCK, EPLL_CON0, NULL),
+	[vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
+						VPLL_LOCK, VPLL_CON, NULL),
+};
+
+/* S5P6442-specific PLLs. */
+static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+	[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
+						APLL_LOCK, APLL_CON0, NULL),
+	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+						MPLL_LOCK, MPLL_CON, NULL),
+	[epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
+						EPLL_LOCK, EPLL_CON0, NULL),
+	[vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
+						VPLL_LOCK, VPLL_CON, NULL),
+};
+
+static void __init __s5pv210_clk_init(struct device_node *np,
+				      unsigned long xxti_f,
+				      unsigned long xusbxti_f,
+				      bool is_s5p6442)
+{
+	struct samsung_clk_provider *ctx;
+
+	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
+
+	samsung_clk_register_mux(ctx, early_mux_clks,
+					ARRAY_SIZE(early_mux_clks));
+
+	if (is_s5p6442) {
+		samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
+			ARRAY_SIZE(s5p6442_frate_clks));
+		samsung_clk_register_pll(ctx, s5p6442_pll_clks,
+			ARRAY_SIZE(s5p6442_pll_clks), reg_base);
+		samsung_clk_register_mux(ctx, s5p6442_mux_clks,
+				ARRAY_SIZE(s5p6442_mux_clks));
+		samsung_clk_register_div(ctx, s5p6442_div_clks,
+				ARRAY_SIZE(s5p6442_div_clks));
+		samsung_clk_register_gate(ctx, s5p6442_gate_clks,
+				ARRAY_SIZE(s5p6442_gate_clks));
+	} else {
+		samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
+			ARRAY_SIZE(s5pv210_frate_clks));
+		samsung_clk_register_pll(ctx, s5pv210_pll_clks,
+			ARRAY_SIZE(s5pv210_pll_clks), reg_base);
+		samsung_clk_register_mux(ctx, s5pv210_mux_clks,
+				ARRAY_SIZE(s5pv210_mux_clks));
+		samsung_clk_register_div(ctx, s5pv210_div_clks,
+				ARRAY_SIZE(s5pv210_div_clks));
+		samsung_clk_register_gate(ctx, s5pv210_gate_clks,
+				ARRAY_SIZE(s5pv210_gate_clks));
+	}
+
+	samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
+	samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
+	samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
+
+	samsung_clk_register_fixed_factor(ctx, ffactor_clks,
+						ARRAY_SIZE(ffactor_clks));
+
+	samsung_clk_register_alias(ctx, s5pv210_aliases,
+						ARRAY_SIZE(s5pv210_aliases));
+
+	s5pv210_clk_sleep_init();
+
+	pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
+		"\tmout_epll = %ld, mout_vpll = %ld\n",
+		is_s5p6442 ? "S5P6442" : "S5PV210",
+		_get_rate("mout_apll"), _get_rate("mout_mpll"),
+		_get_rate("mout_epll"), _get_rate("mout_vpll"));
+}
+
+static void __init s5pv210_clk_dt_init(struct device_node *np)
+{
+	reg_base = of_iomap(np, 0);
+	if (!reg_base)
+		panic("%s: failed to map registers\n", __func__);
+
+	__s5pv210_clk_init(np, 0, 0, false);
+}
+CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
+
+static void __init s5p6442_clk_dt_init(struct device_node *np)
+{
+	reg_base = of_iomap(np, 0);
+	if (!reg_base)
+		panic("%s: failed to map registers\n", __func__);
+
+	__s5pv210_clk_init(np, 0, 0, true);
+}
+CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/samsung/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/samsung/Makefile
--- linux-libre-3.16-gnu/drivers/clk/samsung/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/samsung/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,10 @@ obj-$(CONFIG_SOC_EXYNOS5410)	+= clk-exyn
 obj-$(CONFIG_SOC_EXYNOS5420)	+= clk-exynos5420.o
 obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
 obj-$(CONFIG_ARCH_EXYNOS)	+= clk-exynos-audss.o
+obj-$(CONFIG_ARCH_EXYNOS)	+= clk-exynos-clkout.o
 obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
 obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
 obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
 obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
 obj-$(CONFIG_ARCH_S3C64XX)	+= clk-s3c64xx.o
+obj-$(CONFIG_ARCH_S5PV210)	+= clk-s5pv210.o clk-s5pv210-audss.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/spear/spear1310_clock.c linux-libre-3.17-rc7-gnu/drivers/clk/spear/spear1310_clock.c
--- linux-libre-3.16-gnu/drivers/clk/spear/spear1310_clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/spear/spear1310_clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -742,19 +742,19 @@ void __init spear1310_clk_init(void __io
 	clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.0");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.1");
+	clk_register_clkdev(clk, NULL, "b1800000.pcie");
 	clk_register_clkdev(clk, NULL, "b1800000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.2");
+	clk_register_clkdev(clk, NULL, "b4000000.pcie");
 	clk_register_clkdev(clk, NULL, "b4000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/spear/spear1340_clock.c linux-libre-3.17-rc7-gnu/drivers/clk/spear/spear1340_clock.c
--- linux-libre-3.16-gnu/drivers/clk/spear/spear1340_clock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/spear/spear1340_clock.c	2014-09-28 17:29:07.000000000 -0400
@@ -839,7 +839,7 @@ void __init spear1340_clk_init(void __io
 	clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/st/clk-flexgen.c linux-libre-3.17-rc7-gnu/drivers/clk/st/clk-flexgen.c
--- linux-libre-3.16-gnu/drivers/clk/st/clk-flexgen.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/st/clk-flexgen.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,331 @@
+/*
+ * clk-flexgen.c
+ *
+ * Copyright (C) ST-Microelectronics SA 2013
+ * Author:  Maxime Coquelin <maxime.coquelin@st.com> for ST-Microelectronics.
+ * License terms:  GNU General Public License (GPL), version 2  */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+struct flexgen {
+	struct clk_hw hw;
+
+	/* Crossbar */
+	struct clk_mux mux;
+	/* Pre-divisor's gate */
+	struct clk_gate pgate;
+	/* Pre-divisor */
+	struct clk_divider pdiv;
+	/* Final divisor's gate */
+	struct clk_gate fgate;
+	/* Final divisor */
+	struct clk_divider fdiv;
+};
+
+#define to_flexgen(_hw) container_of(_hw, struct flexgen, hw)
+
+static int flexgen_enable(struct clk_hw *hw)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *pgate_hw = &flexgen->pgate.hw;
+	struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+	pgate_hw->clk = hw->clk;
+	fgate_hw->clk = hw->clk;
+
+	clk_gate_ops.enable(pgate_hw);
+
+	clk_gate_ops.enable(fgate_hw);
+
+	pr_debug("%s: flexgen output enabled\n", __clk_get_name(hw->clk));
+	return 0;
+}
+
+static void flexgen_disable(struct clk_hw *hw)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+	/* disable only the final gate */
+	fgate_hw->clk = hw->clk;
+
+	clk_gate_ops.disable(fgate_hw);
+
+	pr_debug("%s: flexgen output disabled\n", __clk_get_name(hw->clk));
+}
+
+static int flexgen_is_enabled(struct clk_hw *hw)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+	fgate_hw->clk = hw->clk;
+
+	if (!clk_gate_ops.is_enabled(fgate_hw))
+		return 0;
+
+	return 1;
+}
+
+static u8 flexgen_get_parent(struct clk_hw *hw)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *mux_hw = &flexgen->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return clk_mux_ops.get_parent(mux_hw);
+}
+
+static int flexgen_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *mux_hw = &flexgen->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return clk_mux_ops.set_parent(mux_hw, index);
+}
+
+static inline unsigned long
+clk_best_div(unsigned long parent_rate, unsigned long rate)
+{
+	return parent_rate / rate + ((rate > (2*(parent_rate % rate))) ? 0 : 1);
+}
+
+static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	unsigned long div;
+
+	/* Round div according to exact prate and wished rate */
+	div = clk_best_div(*prate, rate);
+
+	if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+		*prate = rate * div;
+		return rate;
+	}
+
+	return *prate / div;
+}
+
+unsigned long flexgen_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
+	struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
+	unsigned long mid_rate;
+
+	pdiv_hw->clk = hw->clk;
+	fdiv_hw->clk = hw->clk;
+
+	mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate);
+
+	return clk_divider_ops.recalc_rate(fdiv_hw, mid_rate);
+}
+
+static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct flexgen *flexgen = to_flexgen(hw);
+	struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
+	struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
+	unsigned long primary_div = 0;
+	int ret = 0;
+
+	pdiv_hw->clk = hw->clk;
+	fdiv_hw->clk = hw->clk;
+
+	primary_div = clk_best_div(parent_rate, rate);
+
+	clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
+	ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * primary_div);
+
+	return ret;
+}
+
+static const struct clk_ops flexgen_ops = {
+	.enable = flexgen_enable,
+	.disable = flexgen_disable,
+	.is_enabled = flexgen_is_enabled,
+	.get_parent = flexgen_get_parent,
+	.set_parent = flexgen_set_parent,
+	.round_rate = flexgen_round_rate,
+	.recalc_rate = flexgen_recalc_rate,
+	.set_rate = flexgen_set_rate,
+};
+
+struct clk *clk_register_flexgen(const char *name,
+				const char **parent_names, u8 num_parents,
+				void __iomem *reg, spinlock_t *lock, u32 idx,
+				unsigned long flexgen_flags) {
+	struct flexgen *fgxbar;
+	struct clk *clk;
+	struct clk_init_data init;
+	u32  xbar_shift;
+	void __iomem *xbar_reg, *fdiv_reg;
+
+	fgxbar = kzalloc(sizeof(struct flexgen), GFP_KERNEL);
+	if (!fgxbar)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &flexgen_ops;
+	init.flags = CLK_IS_BASIC | flexgen_flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	xbar_reg = reg + 0x18 + (idx & ~0x3);
+	xbar_shift = (idx % 4) * 0x8;
+	fdiv_reg = reg + 0x164 + idx * 4;
+
+	/* Crossbar element config */
+	fgxbar->mux.lock = lock;
+	fgxbar->mux.mask = BIT(6) - 1;
+	fgxbar->mux.reg = xbar_reg;
+	fgxbar->mux.shift = xbar_shift;
+	fgxbar->mux.table = NULL;
+
+
+	/* Pre-divider's gate config (in xbar register)*/
+	fgxbar->pgate.lock = lock;
+	fgxbar->pgate.reg = xbar_reg;
+	fgxbar->pgate.bit_idx = xbar_shift + 6;
+
+	/* Pre-divider config */
+	fgxbar->pdiv.lock = lock;
+	fgxbar->pdiv.reg = reg + 0x58 + idx * 4;
+	fgxbar->pdiv.width = 10;
+
+	/* Final divider's gate config */
+	fgxbar->fgate.lock = lock;
+	fgxbar->fgate.reg = fdiv_reg;
+	fgxbar->fgate.bit_idx = 6;
+
+	/* Final divider config */
+	fgxbar->fdiv.lock = lock;
+	fgxbar->fdiv.reg = fdiv_reg;
+	fgxbar->fdiv.width = 6;
+
+	fgxbar->hw.init = &init;
+
+	clk = clk_register(NULL, &fgxbar->hw);
+	if (IS_ERR(clk))
+		kfree(fgxbar);
+	else
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+	return clk;
+}
+
+static const char ** __init flexgen_get_parents(struct device_node *np,
+						       int *num_parents)
+{
+	const char **parents;
+	int nparents, i;
+
+	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	if (WARN_ON(nparents <= 0))
+		return NULL;
+
+	parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
+	if (!parents)
+		return NULL;
+
+	for (i = 0; i < nparents; i++)
+		parents[i] = of_clk_get_parent_name(np, i);
+
+	*num_parents = nparents;
+	return parents;
+}
+
+void __init st_of_flexgen_setup(struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg;
+	struct clk_onecell_data *clk_data;
+	const char **parents;
+	int num_parents, i;
+	spinlock_t *rlock = NULL;
+	unsigned long flex_flags = 0;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return;
+
+	reg = of_iomap(pnode, 0);
+	if (!reg)
+		return;
+
+	parents = flexgen_get_parents(np, &num_parents);
+	if (!parents)
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = of_property_count_strings(np ,
+			"clock-output-names");
+	if (clk_data->clk_num <= 0) {
+		pr_err("%s: Failed to get number of output clocks (%d)",
+				__func__, clk_data->clk_num);
+		goto err;
+	}
+
+	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
+			GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err;
+
+	rlock = kzalloc(sizeof(spinlock_t), GFP_KERNEL);
+	if (!rlock)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name)) {
+			break;
+		}
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = clk_register_flexgen(clk_name, parents, num_parents,
+					   reg, rlock, i, flex_flags);
+
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+
+	return;
+
+err:
+	if (clk_data)
+		kfree(clk_data->clks);
+	kfree(clk_data);
+	kfree(parents);
+	kfree(rlock);
+}
+CLK_OF_DECLARE(flexgen, "st,flexgen", st_of_flexgen_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/st/clkgen-fsyn.c linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-fsyn.c
--- linux-libre-3.16-gnu/drivers/clk/st/clkgen-fsyn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-fsyn.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ struct stm_fs {
 	unsigned long nsdiv;
 };
 
-static struct stm_fs fs216c65_rtbl[] = {
+static const struct stm_fs fs216c65_rtbl[] = {
 	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 312.5 Khz */
 	{ .mdiv = 0x17, .pe = 0x25ed,	.sdiv = 0x1,	.nsdiv = 0 },	/* 27    MHz */
 	{ .mdiv = 0x1a, .pe = 0x7b36,	.sdiv = 0x2,	.nsdiv = 1 },	/* 36.87 MHz */
@@ -49,31 +49,86 @@ static struct stm_fs fs216c65_rtbl[] = {
 	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x1,	.nsdiv = 1 },	/* 108   MHz */
 };
 
-static struct stm_fs fs432c65_rtbl[] = {
-	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 625   Khz */
-	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108   MHz */
-	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   MHz */
+static const struct stm_fs fs432c65_rtbl[] = {
+	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 625     Khz */
+	{ .mdiv = 0x13, .pe = 0x777c,	.sdiv = 0x4,	.nsdiv = 1 },	/* 25.175  MHz */
+	{ .mdiv = 0x19, .pe = 0x4d35,	.sdiv = 0x2,	.nsdiv = 0 },	/* 25.200  MHz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x4,	.nsdiv = 1 },	/* 27.000  MHz */
+	{ .mdiv = 0x17, .pe = 0x28f5,	.sdiv = 0x2,	.nsdiv = 0 },	/* 27.027  MHz */
+	{ .mdiv = 0x16, .pe = 0x3359,	.sdiv = 0x2,	.nsdiv = 0 },	/* 28.320  MHz */
+	{ .mdiv = 0x1f, .pe = 0x2083,	.sdiv = 0x3,	.nsdiv = 1 },	/* 30.240  MHz */
+	{ .mdiv = 0x1e, .pe = 0x430d,	.sdiv = 0x3,	.nsdiv = 1 },	/* 31.500  MHz */
+	{ .mdiv = 0x17, .pe = 0x0,	.sdiv = 0x3,	.nsdiv = 1 },	/* 40.000  MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x1,	.nsdiv = 0 },	/* 49.500  MHz */
+	{ .mdiv = 0x13, .pe = 0x6667,	.sdiv = 0x3,	.nsdiv = 1 },	/* 50.000  MHz */
+	{ .mdiv = 0x10, .pe = 0x1ee6,	.sdiv = 0x3,	.nsdiv = 1 },	/* 57.284  MHz */
+	{ .mdiv = 0x1d, .pe = 0x3b14,	.sdiv = 0x2,	.nsdiv = 1 },	/* 65.000  MHz */
+	{ .mdiv = 0x12, .pe = 0x7c65,	.sdiv = 0x1,	.nsdiv = 0 },	/* 71.000  MHz */
+	{ .mdiv = 0x19, .pe = 0xecd,	.sdiv = 0x2,	.nsdiv = 1 },	/* 74.176  MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x2,	.nsdiv = 1 },	/* 74.250  MHz */
+	{ .mdiv = 0x19, .pe = 0x3334,	.sdiv = 0x2,	.nsdiv = 1 },	/* 75.000  MHz */
+	{ .mdiv = 0x18, .pe = 0x5138,	.sdiv = 0x2,	.nsdiv = 1 },	/* 78.800  MHz */
+	{ .mdiv = 0x1d, .pe = 0x77d,	.sdiv = 0x0,	.nsdiv = 0 },	/* 85.500  MHz */
+	{ .mdiv = 0x1c, .pe = 0x13d5,	.sdiv = 0x0,	.nsdiv = 0 },	/* 88.750  MHz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108.000 MHz */
+	{ .mdiv = 0x17, .pe = 0x28f5,	.sdiv = 0x0,	.nsdiv = 0 },	/* 108.108 MHz */
+	{ .mdiv = 0x10, .pe = 0x6e26,	.sdiv = 0x2,	.nsdiv = 1 },	/* 118.963 MHz */
+	{ .mdiv = 0x15, .pe = 0x3e63,	.sdiv = 0x0,	.nsdiv = 0 },	/* 119.000 MHz */
+	{ .mdiv = 0x1c, .pe = 0x471d,	.sdiv = 0x1,	.nsdiv = 1 },	/* 135.000 MHz */
+	{ .mdiv = 0x19, .pe = 0xecd,	.sdiv = 0x1,	.nsdiv = 1 },	/* 148.352 MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x1,	.nsdiv = 1 },	/* 148.500 MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297     MHz */
 };
 
-static struct stm_fs fs660c32_rtbl[] = {
-	{ .mdiv = 0x01, .pe = 0x2aaa,	.sdiv = 0x8,	.nsdiv = 0 },	/* 600   KHz */
-	{ .mdiv = 0x02, .pe = 0x3d33,	.sdiv = 0x0,	.nsdiv = 0 },	/* 148.5 Mhz */
-	{ .mdiv = 0x13, .pe = 0x5bcc,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   Mhz */
-	{ .mdiv = 0x0e, .pe = 0x1025,	.sdiv = 0x0,	.nsdiv = 1 },	/* 333   Mhz */
-	{ .mdiv = 0x0b, .pe = 0x715f,	.sdiv = 0x0,	.nsdiv = 1 },	/* 350   Mhz */
+static const struct stm_fs fs660c32_rtbl[] = {
+	{ .mdiv = 0x14, .pe = 0x376b,	.sdiv = 0x4,	.nsdiv = 1 },	/* 25.175  MHz */
+	{ .mdiv = 0x14, .pe = 0x30c3,	.sdiv = 0x4,	.nsdiv = 1 },	/* 25.200  MHz */
+	{ .mdiv = 0x10, .pe = 0x71c7,	.sdiv = 0x4,	.nsdiv = 1 },	/* 27.000  MHz */
+	{ .mdiv = 0x00, .pe = 0x47af,	.sdiv = 0x3,	.nsdiv = 0 },	/* 27.027  MHz */
+	{ .mdiv = 0x0e, .pe = 0x4e1a,	.sdiv = 0x4,	.nsdiv = 1 },	/* 28.320  MHz */
+	{ .mdiv = 0x0b, .pe = 0x534d,	.sdiv = 0x4,	.nsdiv = 1 },	/* 30.240  MHz */
+	{ .mdiv = 0x17, .pe = 0x6fbf,	.sdiv = 0x2,	.nsdiv = 0 },	/* 31.500  MHz */
+	{ .mdiv = 0x01, .pe = 0x0,	.sdiv = 0x4,	.nsdiv = 1 },	/* 40.000  MHz */
+	{ .mdiv = 0x15, .pe = 0x2aab,	.sdiv = 0x3,	.nsdiv = 1 },	/* 49.500  MHz */
+	{ .mdiv = 0x14, .pe = 0x6666,	.sdiv = 0x3,	.nsdiv = 1 },	/* 50.000  MHz */
+	{ .mdiv = 0x1d, .pe = 0x395f,	.sdiv = 0x1,	.nsdiv = 0 },	/* 57.284  MHz */
+	{ .mdiv = 0x08, .pe = 0x4ec5,	.sdiv = 0x3,	.nsdiv = 1 },	/* 65.000  MHz */
+	{ .mdiv = 0x05, .pe = 0x1770,	.sdiv = 0x3,	.nsdiv = 1 },	/* 71.000  MHz */
+	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x3,	.nsdiv = 1 },	/* 74.176  MHz */
+	{ .mdiv = 0x0f, .pe = 0x3426,	.sdiv = 0x1,	.nsdiv = 0 },	/* 74.250  MHz */
+	{ .mdiv = 0x0e, .pe = 0x7777,	.sdiv = 0x1,	.nsdiv = 0 },	/* 75.000  MHz */
+	{ .mdiv = 0x01, .pe = 0x4053,	.sdiv = 0x3,	.nsdiv = 1 },	/* 78.800  MHz */
+	{ .mdiv = 0x09, .pe = 0x15b5,	.sdiv = 0x1,	.nsdiv = 0 },	/* 85.500  MHz */
+	{ .mdiv = 0x1b, .pe = 0x3f19,	.sdiv = 0x2,	.nsdiv = 1 },	/* 88.750  MHz */
+	{ .mdiv = 0x10, .pe = 0x71c7,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108.000 MHz */
+	{ .mdiv = 0x00, .pe = 0x47af,	.sdiv = 0x1,	.nsdiv = 0 },	/* 108.108 MHz */
+	{ .mdiv = 0x0c, .pe = 0x3118,	.sdiv = 0x2,	.nsdiv = 1 },	/* 118.963 MHz */
+	{ .mdiv = 0x0c, .pe = 0x2f54,	.sdiv = 0x2,	.nsdiv = 1 },	/* 119.000 MHz */
+	{ .mdiv = 0x07, .pe = 0xe39,	.sdiv = 0x2,	.nsdiv = 1 },	/* 135.000 MHz */
+	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x2,	.nsdiv = 1 },	/* 148.352 MHz */
+	{ .mdiv = 0x0f, .pe = 0x3426,	.sdiv = 0x0,	.nsdiv = 0 },	/* 148.500 MHz */
+	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x1,	.nsdiv = 1 },	/* 296.704 MHz */
+	{ .mdiv = 0x03, .pe = 0x471c,	.sdiv = 0x1,	.nsdiv = 1 },	/* 297.000 MHz */
+	{ .mdiv = 0x00, .pe = 0x295f,	.sdiv = 0x1,	.nsdiv = 1 },	/* 326.700 MHz */
+	{ .mdiv = 0x1f, .pe = 0x3633,	.sdiv = 0x0,	.nsdiv = 1 },	/* 333.000 MHz */
+	{ .mdiv = 0x1c, .pe = 0x0,	.sdiv = 0x0,	.nsdiv = 1 },	/* 352.000 Mhz */
 };
 
 struct clkgen_quadfs_data {
 	bool reset_present;
 	bool bwfilter_present;
 	bool lockstatus_present;
+	bool powerup_polarity;
+	bool standby_polarity;
 	bool nsdiv_present;
+	bool nrst_present;
 	struct clkgen_field ndiv;
 	struct clkgen_field ref_bw;
 	struct clkgen_field nreset;
 	struct clkgen_field npda;
 	struct clkgen_field lock_status;
 
+	struct clkgen_field nrst[QUADFS_MAX_CHAN];
 	struct clkgen_field nsb[QUADFS_MAX_CHAN];
 	struct clkgen_field en[QUADFS_MAX_CHAN];
 	struct clkgen_field mdiv[QUADFS_MAX_CHAN];
@@ -82,9 +137,9 @@ struct clkgen_quadfs_data {
 	struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
 
 	const struct clk_ops *pll_ops;
-	struct stm_fs *rtbl;
+	const struct stm_fs *rtbl;
 	u8 rtbl_cnt;
-	int  (*get_rate)(unsigned long , struct stm_fs *,
+	int  (*get_rate)(unsigned long , const struct stm_fs *,
 			unsigned long *);
 };
 
@@ -94,11 +149,11 @@ static const struct clk_ops st_quadfs_fs
 static const struct clk_ops st_quadfs_fs432c65_ops;
 static const struct clk_ops st_quadfs_fs660c32_ops;
 
-static int clk_fs216c65_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs216c65_get_rate(unsigned long, const struct stm_fs *,
 		unsigned long *);
-static int clk_fs432c65_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs432c65_get_rate(unsigned long, const struct stm_fs *,
 		unsigned long *);
-static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs660c32_dig_get_rate(unsigned long, const struct stm_fs *,
 		unsigned long *);
 /*
  * Values for all of the standalone instances of this clock
@@ -106,7 +161,7 @@ static int clk_fs660c32_dig_get_rate(uns
  * that the individual channel standby control bits (nsb) are in the
  * first register along with the PLL control bits.
  */
-static struct clkgen_quadfs_data st_fs216c65_416 = {
+static const struct clkgen_quadfs_data st_fs216c65_416 = {
 	/* 416 specific */
 	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
 	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
@@ -143,7 +198,7 @@ static struct clkgen_quadfs_data st_fs21
 	.get_rate	= clk_fs216c65_get_rate,
 };
 
-static struct clkgen_quadfs_data st_fs432c65_416 = {
+static const struct clkgen_quadfs_data st_fs432c65_416 = {
 	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
 	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
 		    CLKGEN_FIELD(0x0, 0x1, 11),
@@ -179,7 +234,7 @@ static struct clkgen_quadfs_data st_fs43
 	.get_rate	= clk_fs432c65_get_rate,
 };
 
-static struct clkgen_quadfs_data st_fs660c32_E_416 = {
+static const struct clkgen_quadfs_data st_fs660c32_E_416 = {
 	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
 	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
 		    CLKGEN_FIELD(0x0, 0x1, 11),
@@ -215,7 +270,7 @@ static struct clkgen_quadfs_data st_fs66
 	.get_rate	= clk_fs660c32_dig_get_rate,
 };
 
-static struct clkgen_quadfs_data st_fs660c32_F_416 = {
+static const struct clkgen_quadfs_data st_fs660c32_F_416 = {
 	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
 	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
 		    CLKGEN_FIELD(0x0, 0x1, 11),
@@ -251,6 +306,91 @@ static struct clkgen_quadfs_data st_fs66
 	.get_rate	= clk_fs660c32_dig_get_rate,
 };
 
+static const struct clkgen_quadfs_data st_fs660c32_C_407 = {
+	.nrst_present = true,
+	.nrst	= { CLKGEN_FIELD(0x2f0, 0x1, 0),
+		    CLKGEN_FIELD(0x2f0, 0x1, 1),
+		    CLKGEN_FIELD(0x2f0, 0x1, 2),
+		    CLKGEN_FIELD(0x2f0, 0x1, 3) },
+	.npda	= CLKGEN_FIELD(0x2f0, 0x1, 12),
+	.nsb	= { CLKGEN_FIELD(0x2f0, 0x1, 8),
+		    CLKGEN_FIELD(0x2f0, 0x1, 9),
+		    CLKGEN_FIELD(0x2f0, 0x1, 10),
+		    CLKGEN_FIELD(0x2f0, 0x1, 11) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x304, 0x1, 24),
+		    CLKGEN_FIELD(0x308, 0x1, 24),
+		    CLKGEN_FIELD(0x30c, 0x1, 24),
+		    CLKGEN_FIELD(0x310, 0x1, 24) },
+	.mdiv	= { CLKGEN_FIELD(0x304, 0x1f, 15),
+		    CLKGEN_FIELD(0x308, 0x1f, 15),
+		    CLKGEN_FIELD(0x30c, 0x1f, 15),
+		    CLKGEN_FIELD(0x310, 0x1f, 15) },
+	.en	= { CLKGEN_FIELD(0x2fc, 0x1, 0),
+		    CLKGEN_FIELD(0x2fc, 0x1, 1),
+		    CLKGEN_FIELD(0x2fc, 0x1, 2),
+		    CLKGEN_FIELD(0x2fc, 0x1, 3) },
+	.ndiv	= CLKGEN_FIELD(0x2f4, 0x7, 16),
+	.pe	= { CLKGEN_FIELD(0x304, 0x7fff, 0),
+		    CLKGEN_FIELD(0x308, 0x7fff, 0),
+		    CLKGEN_FIELD(0x30c, 0x7fff, 0),
+		    CLKGEN_FIELD(0x310, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0x304, 0xf, 20),
+		    CLKGEN_FIELD(0x308, 0xf, 20),
+		    CLKGEN_FIELD(0x30c, 0xf, 20),
+		    CLKGEN_FIELD(0x310, 0xf, 20) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
+	.powerup_polarity = 1,
+	.standby_polarity = 1,
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,
+};
+
+static const struct clkgen_quadfs_data st_fs660c32_D_407 = {
+	.nrst_present = true,
+	.nrst	= { CLKGEN_FIELD(0x2a0, 0x1, 0),
+		    CLKGEN_FIELD(0x2a0, 0x1, 1),
+		    CLKGEN_FIELD(0x2a0, 0x1, 2),
+		    CLKGEN_FIELD(0x2a0, 0x1, 3) },
+	.ndiv	= CLKGEN_FIELD(0x2a4, 0x7, 16),
+	.pe	= { CLKGEN_FIELD(0x2b4, 0x7fff, 0),
+		    CLKGEN_FIELD(0x2b8, 0x7fff, 0),
+		    CLKGEN_FIELD(0x2bc, 0x7fff, 0),
+		    CLKGEN_FIELD(0x2c0, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0x2b4, 0xf, 20),
+		    CLKGEN_FIELD(0x2b8, 0xf, 20),
+		    CLKGEN_FIELD(0x2bc, 0xf, 20),
+		    CLKGEN_FIELD(0x2c0, 0xf, 20) },
+	.npda	= CLKGEN_FIELD(0x2a0, 0x1, 12),
+	.nsb	= { CLKGEN_FIELD(0x2a0, 0x1, 8),
+		    CLKGEN_FIELD(0x2a0, 0x1, 9),
+		    CLKGEN_FIELD(0x2a0, 0x1, 10),
+		    CLKGEN_FIELD(0x2a0, 0x1, 11) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x2b4, 0x1, 24),
+		    CLKGEN_FIELD(0x2b8, 0x1, 24),
+		    CLKGEN_FIELD(0x2bc, 0x1, 24),
+		    CLKGEN_FIELD(0x2c0, 0x1, 24) },
+	.mdiv	= { CLKGEN_FIELD(0x2b4, 0x1f, 15),
+		    CLKGEN_FIELD(0x2b8, 0x1f, 15),
+		    CLKGEN_FIELD(0x2bc, 0x1f, 15),
+		    CLKGEN_FIELD(0x2c0, 0x1f, 15) },
+	.en	= { CLKGEN_FIELD(0x2ac, 0x1, 0),
+		    CLKGEN_FIELD(0x2ac, 0x1, 1),
+		    CLKGEN_FIELD(0x2ac, 0x1, 2),
+		    CLKGEN_FIELD(0x2ac, 0x1, 3) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
+	.powerup_polarity = 1,
+	.standby_polarity = 1,
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,};
+
 /**
  * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
  *
@@ -308,7 +448,7 @@ static int quadfs_pll_enable(struct clk_
 	/*
 	 * Power up the PLL
 	 */
-	CLKGEN_WRITE(pll, npda, 1);
+	CLKGEN_WRITE(pll, npda, !pll->data->powerup_polarity);
 
 	if (pll->lock)
 		spin_unlock_irqrestore(pll->lock, flags);
@@ -335,7 +475,7 @@ static void quadfs_pll_disable(struct cl
 	 * Powerdown the PLL and then put block into soft reset if we have
 	 * reset control.
 	 */
-	CLKGEN_WRITE(pll, npda, 0);
+	CLKGEN_WRITE(pll, npda, pll->data->powerup_polarity);
 
 	if (pll->data->reset_present)
 		CLKGEN_WRITE(pll, nreset, 0);
@@ -611,7 +751,10 @@ static int quadfs_fsynth_enable(struct c
 	if (fs->lock)
 		spin_lock_irqsave(fs->lock, flags);
 
-	CLKGEN_WRITE(fs, nsb[fs->chan], 1);
+	CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
+
+	if (fs->data->nrst_present)
+		CLKGEN_WRITE(fs, nrst[fs->chan], 0);
 
 	if (fs->lock)
 		spin_unlock_irqrestore(fs->lock, flags);
@@ -631,7 +774,7 @@ static void quadfs_fsynth_disable(struct
 	if (fs->lock)
 		spin_lock_irqsave(fs->lock, flags);
 
-	CLKGEN_WRITE(fs, nsb[fs->chan], 0);
+	CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
 
 	if (fs->lock)
 		spin_unlock_irqrestore(fs->lock, flags);
@@ -645,12 +788,12 @@ static int quadfs_fsynth_is_enabled(stru
 	pr_debug("%s: %s enable bit = 0x%x\n",
 		 __func__, __clk_get_name(hw->clk), nsb);
 
-	return !!nsb;
+	return fs->data->standby_polarity ? !nsb : !!nsb;
 }
 
 #define P15			(uint64_t)(1 << 15)
 
-static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs216c65_get_rate(unsigned long input, const struct stm_fs *fs,
 		unsigned long *rate)
 {
 	uint64_t res;
@@ -670,7 +813,7 @@ static int clk_fs216c65_get_rate(unsigne
 	return 0;
 }
 
-static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs432c65_get_rate(unsigned long input, const struct stm_fs *fs,
 		unsigned long *rate)
 {
 	uint64_t res;
@@ -693,7 +836,7 @@ static int clk_fs432c65_get_rate(unsigne
 #define P20		(uint64_t)(1 << 20)
 
 static int clk_fs660c32_dig_get_rate(unsigned long input,
-				struct stm_fs *fs, unsigned long *rate)
+				const struct stm_fs *fs, unsigned long *rate)
 {
 	unsigned long s = (1 << fs->sdiv);
 	unsigned long ns;
@@ -749,7 +892,7 @@ static long quadfs_find_best_rate(struct
 {
 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
 	int (*clk_fs_get_rate)(unsigned long ,
-				struct stm_fs *, unsigned long *);
+				const struct stm_fs *, unsigned long *);
 	struct stm_fs prev_params;
 	unsigned long prev_rate, rate = 0;
 	unsigned long diff_rate, prev_diff_rate = ~0;
@@ -793,7 +936,7 @@ static unsigned long quadfs_recalc_rate(
 	unsigned long rate = 0;
 	struct stm_fs params;
 	int (*clk_fs_get_rate)(unsigned long ,
-				struct stm_fs *, unsigned long *);
+				const struct stm_fs *, unsigned long *);
 
 	clk_fs_get_rate = fs->data->get_rate;
 
@@ -917,19 +1060,31 @@ static struct clk * __init st_clk_regist
 static struct of_device_id quadfs_of_match[] = {
 	{
 		.compatible = "st,stih416-quadfs216",
-		.data = (void *)&st_fs216c65_416
+		.data = &st_fs216c65_416
 	},
 	{
 		.compatible = "st,stih416-quadfs432",
-		.data = (void *)&st_fs432c65_416
+		.data = &st_fs432c65_416
 	},
 	{
 		.compatible = "st,stih416-quadfs660-E",
-		.data = (void *)&st_fs660c32_E_416
+		.data = &st_fs660c32_E_416
 	},
 	{
 		.compatible = "st,stih416-quadfs660-F",
-		.data = (void *)&st_fs660c32_F_416
+		.data = &st_fs660c32_F_416
+	},
+	{
+		.compatible = "st,stih407-quadfs660-C",
+		.data = &st_fs660c32_C_407
+	},
+	{
+		.compatible = "st,stih407-quadfs660-D",
+		.data = &st_fs660c32_D_407
+	},
+	{
+		.compatible = "st,stih407-quadfs660-D",
+		.data = (void *)&st_fs660c32_D_407
 	},
 	{}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/st/clkgen-mux.c linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-mux.c
--- linux-libre-3.16-gnu/drivers/clk/st/clkgen-mux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-mux.c	2014-09-28 17:29:07.000000000 -0400
@@ -580,6 +580,11 @@ static struct clkgen_mux_data stih416_a9
 	.shift = 0,
 	.width = 2,
 };
+static struct clkgen_mux_data stih407_a9_mux_data = {
+	.offset = 0x1a4,
+	.shift = 1,
+	.width = 2,
+};
 
 static struct of_device_id mux_of_match[] = {
 	{
@@ -610,6 +615,10 @@ static struct of_device_id mux_of_match[
 		.compatible = "st,stih416-clkgen-a9-mux",
 		.data = &stih416_a9_mux_data,
 	},
+	{
+		.compatible = "st,stih407-clkgen-a9-mux",
+		.data = &stih407_a9_mux_data,
+	},
 	{}
 };
 
@@ -765,7 +774,8 @@ void __init st_of_clkgen_vcc_setup(struc
 		div->reg = reg + VCC_DIV_OFFSET;
 		div->shift = 2 * i;
 		div->width = 2;
-		div->flags = CLK_DIVIDER_POWER_OF_TWO;
+		div->flags = CLK_DIVIDER_POWER_OF_TWO |
+			CLK_DIVIDER_ROUND_CLOSEST;
 
 		mux->reg = reg + VCC_MUX_OFFSET;
 		mux->shift = 2 * i;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/st/clkgen-pll.c linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-pll.c
--- linux-libre-3.16-gnu/drivers/clk/st/clkgen-pll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/st/clkgen-pll.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ static const struct clk_ops st_pll800c65
 static const struct clk_ops stm_pll3200c32_ops;
 static const struct clk_ops st_pll1200c32_ops;
 
-static struct clkgen_pll_data st_pll1600c65_ax = {
+static const struct clkgen_pll_data st_pll1600c65_ax = {
 	.pdn_status	= CLKGEN_FIELD(0x0, 0x1,			19),
 	.locked_status	= CLKGEN_FIELD(0x0, 0x1,			31),
 	.mdiv		= CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK,	0),
@@ -67,7 +67,7 @@ static struct clkgen_pll_data st_pll1600
 	.ops		= &st_pll1600c65_ops
 };
 
-static struct clkgen_pll_data st_pll800c65_ax = {
+static const struct clkgen_pll_data st_pll800c65_ax = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			19),
 	.locked_status	= CLKGEN_FIELD(0x0,	0x1,			31),
 	.mdiv		= CLKGEN_FIELD(0x0,	C65_MDIV_PLL800_MASK,	0),
@@ -76,7 +76,7 @@ static struct clkgen_pll_data st_pll800c
 	.ops		= &st_pll800c65_ops
 };
 
-static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
+static const struct clkgen_pll_data st_pll3200c32_a1x_0 = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			31),
 	.locked_status	= CLKGEN_FIELD(0x4,	0x1,			31),
 	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		0x0),
@@ -93,7 +93,7 @@ static struct clkgen_pll_data st_pll3200
 	.ops		= &stm_pll3200c32_ops,
 };
 
-static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
+static const struct clkgen_pll_data st_pll3200c32_a1x_1 = {
 	.pdn_status	= CLKGEN_FIELD(0xC,	0x1,			31),
 	.locked_status	= CLKGEN_FIELD(0x10,	0x1,			31),
 	.ndiv		= CLKGEN_FIELD(0xC,	C32_NDIV_MASK,		0x0),
@@ -111,7 +111,7 @@ static struct clkgen_pll_data st_pll3200
 };
 
 /* 415 specific */
-static struct clkgen_pll_data st_pll3200c32_a9_415 = {
+static const struct clkgen_pll_data st_pll3200c32_a9_415 = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
 	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
 	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		9),
@@ -122,7 +122,7 @@ static struct clkgen_pll_data st_pll3200
 	.ops		= &stm_pll3200c32_ops,
 };
 
-static struct clkgen_pll_data st_pll3200c32_ddr_415 = {
+static const struct clkgen_pll_data st_pll3200c32_ddr_415 = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
 	.locked_status	= CLKGEN_FIELD(0x100,	0x1,			0),
 	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
@@ -135,7 +135,7 @@ static struct clkgen_pll_data st_pll3200
 	.ops		= &stm_pll3200c32_ops,
 };
 
-static struct clkgen_pll_data st_pll1200c32_gpu_415 = {
+static const struct clkgen_pll_data st_pll1200c32_gpu_415 = {
 	.pdn_status	= CLKGEN_FIELD(0x144,	0x1,			3),
 	.locked_status	= CLKGEN_FIELD(0x168,	0x1,			0),
 	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
@@ -146,7 +146,7 @@ static struct clkgen_pll_data st_pll1200
 };
 
 /* 416 specific */
-static struct clkgen_pll_data st_pll3200c32_a9_416 = {
+static const struct clkgen_pll_data st_pll3200c32_a9_416 = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
 	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
 	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
@@ -157,7 +157,7 @@ static struct clkgen_pll_data st_pll3200
 	.ops		= &stm_pll3200c32_ops,
 };
 
-static struct clkgen_pll_data st_pll3200c32_ddr_416 = {
+static const struct clkgen_pll_data st_pll3200c32_ddr_416 = {
 	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
 	.locked_status	= CLKGEN_FIELD(0x10C,	0x1,			0),
 	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
@@ -170,7 +170,7 @@ static struct clkgen_pll_data st_pll3200
 	.ops		= &stm_pll3200c32_ops,
 };
 
-static struct clkgen_pll_data st_pll1200c32_gpu_416 = {
+static const struct clkgen_pll_data st_pll1200c32_gpu_416 = {
 	.pdn_status	= CLKGEN_FIELD(0x8E4,	0x1,			3),
 	.locked_status	= CLKGEN_FIELD(0x90C,	0x1,			0),
 	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
@@ -180,6 +180,54 @@ static struct clkgen_pll_data st_pll1200
 	.ops		= &st_pll1200c32_ops,
 };
 
+static const struct clkgen_pll_data st_pll3200c32_407_a0 = {
+	/* 407 A0 */
+	.pdn_status	= CLKGEN_FIELD(0x2a0,	0x1,			8),
+	.locked_status	= CLKGEN_FIELD(0x2a0,	0x1,			24),
+	.ndiv		= CLKGEN_FIELD(0x2a4,	C32_NDIV_MASK,		16),
+	.idf		= CLKGEN_FIELD(0x2a4,	C32_IDF_MASK,		0x0),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x2b4, C32_ODF_MASK,		0) },
+	.odf_gate	= { CLKGEN_FIELD(0x2b4,	0x1,			6) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_c0_0 = {
+	/* 407 C0 PLL0 */
+	.pdn_status	= CLKGEN_FIELD(0x2a0,	0x1,			8),
+	.locked_status	= CLKGEN_FIELD(0x2a0,	0x1,			24),
+	.ndiv		= CLKGEN_FIELD(0x2a4,	C32_NDIV_MASK,		16),
+	.idf		= CLKGEN_FIELD(0x2a4,	C32_IDF_MASK,		0x0),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x2b4, C32_ODF_MASK,		0) },
+	.odf_gate	= { CLKGEN_FIELD(0x2b4, 0x1,			6) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_c0_1 = {
+	/* 407 C0 PLL1 */
+	.pdn_status	= CLKGEN_FIELD(0x2c8,	0x1,			8),
+	.locked_status	= CLKGEN_FIELD(0x2c8,	0x1,			24),
+	.ndiv		= CLKGEN_FIELD(0x2cc,	C32_NDIV_MASK,		16),
+	.idf		= CLKGEN_FIELD(0x2cc,	C32_IDF_MASK,		0x0),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x2dc, C32_ODF_MASK,		0) },
+	.odf_gate	= { CLKGEN_FIELD(0x2dc, 0x1,			6) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
+	/* 407 A9 */
+	.pdn_status	= CLKGEN_FIELD(0x1a8,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x87c,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x1b0,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x1a8,	C32_IDF_MASK,		25),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x1b0, C32_ODF_MASK,		8) },
+	.odf_gate	= { CLKGEN_FIELD(0x1ac, 0x1,			28) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
 /**
  * DOC: Clock Generated by PLL, rate set and enabled by bootloader
  *
@@ -450,9 +498,8 @@ static void __init clkgena_c65_pll_setup
 	 * PLL0 HS (high speed) output
 	 */
 	clk_data->clks[0] = clkgen_pll_register(parent_name,
-						&st_pll1600c65_ax,
-						reg + CLKGENAx_PLL0_OFFSET,
-						clk_name);
+			(struct clkgen_pll_data *) &st_pll1600c65_ax,
+			reg + CLKGENAx_PLL0_OFFSET, clk_name);
 
 	if (IS_ERR(clk_data->clks[0]))
 		goto err;
@@ -480,9 +527,8 @@ static void __init clkgena_c65_pll_setup
 	 * PLL1 output
 	 */
 	clk_data->clks[2] = clkgen_pll_register(parent_name,
-						&st_pll800c65_ax,
-						reg + CLKGENAx_PLL1_OFFSET,
-						clk_name);
+			(struct clkgen_pll_data *) &st_pll800c65_ax,
+			reg + CLKGENAx_PLL1_OFFSET, clk_name);
 
 	if (IS_ERR(clk_data->clks[2]))
 		goto err;
@@ -572,6 +618,22 @@ static struct of_device_id c32_pll_of_ma
 		.compatible = "st,stih416-plls-c32-ddr",
 		.data = &st_pll3200c32_ddr_416,
 	},
+	{
+		.compatible = "st,stih407-plls-c32-a0",
+		.data = &st_pll3200c32_407_a0,
+	},
+	{
+		.compatible = "st,stih407-plls-c32-c0_0",
+		.data = &st_pll3200c32_407_c0_0,
+	},
+	{
+		.compatible = "st,stih407-plls-c32-c0_1",
+		.data = &st_pll3200c32_407_c0_1,
+	},
+	{
+		.compatible = "st,stih407-plls-c32-a9",
+		.data = &st_pll3200c32_407_a9,
+	},
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/st/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/st/Makefile
--- linux-libre-3.16-gnu/drivers/clk/st/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/st/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1 +1 @@
-obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o
+obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o clk-flexgen.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-a20-gmac.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-a20-gmac.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-a20-gmac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-a20-gmac.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,7 @@ static void __init sun7i_a20_gmac_clk_se
 	struct clk_gate *gate;
 	const char *clk_name = node->name;
 	const char *parents[SUN7I_A20_GMAC_PARENTS];
-	void *reg;
+	void __iomem *reg;
 
 	if (of_property_read_string(node, "clock-output-names", &clk_name))
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-factors.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-factors.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-factors.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-factors.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_
 		p = FACTOR_GET(config->pshift, config->pwidth, reg);
 
 	/* Calculate the rate */
-	rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+	rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1);
 
 	return rate;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-factors.h linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-factors.h
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-factors.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-factors.h	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@ struct clk_factors_config {
 	u8 mwidth;
 	u8 pshift;
 	u8 pwidth;
+	u8 n_start;
 };
 
 struct clk_factors {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-apb0.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-apb0.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-apb0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-apb0.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,7 @@ static int sun6i_a31_apb0_clk_probe(stru
 	return of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
 
-const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
+static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
 	{ .compatible = "allwinner,sun6i-a31-apb0-clk" },
 	{ /* sentinel */ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-apb0-gates.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-apb0-gates.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-apb0-gates.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,23 +9,53 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/clkdev.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 
 #define SUN6I_APB0_GATES_MAX_SIZE	32
 
+struct gates_data {
+	DECLARE_BITMAP(mask, SUN6I_APB0_GATES_MAX_SIZE);
+};
+
+static const struct gates_data sun6i_a31_apb0_gates __initconst = {
+	.mask = {0x7F},
+};
+
+static const struct gates_data sun8i_a23_apb0_gates __initconst = {
+	.mask = {0x5D},
+};
+
+static const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
+	{ .compatible = "allwinner,sun6i-a31-apb0-gates-clk", .data = &sun6i_a31_apb0_gates },
+	{ .compatible = "allwinner,sun8i-a23-apb0-gates-clk", .data = &sun8i_a23_apb0_gates },
+	{ /* sentinel */ }
+};
+
 static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct clk_onecell_data *clk_data;
+	const struct of_device_id *device;
+	const struct gates_data *data;
 	const char *clk_parent;
 	const char *clk_name;
 	struct resource *r;
 	void __iomem *reg;
-	int gate_id;
 	int ngates;
 	int i;
+	int j = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	device = of_match_device(sun6i_a31_apb0_gates_clk_dt_ids, &pdev->dev);
+	if (!device)
+		return -ENODEV;
+	data = device->data;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	reg = devm_ioremap_resource(&pdev->dev, r);
@@ -36,54 +66,36 @@ static int sun6i_a31_apb0_gates_clk_prob
 	if (!clk_parent)
 		return -EINVAL;
 
-	ngates = of_property_count_strings(np, "clock-output-names");
-	if (ngates < 0)
-		return ngates;
-
-	if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE)
-		return -EINVAL;
-
 	clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
 				GFP_KERNEL);
 	if (!clk_data)
 		return -ENOMEM;
 
-	clk_data->clks = devm_kzalloc(&pdev->dev,
-				      SUN6I_APB0_GATES_MAX_SIZE *
-				      sizeof(struct clk *),
-				      GFP_KERNEL);
+	/* Worst-case size approximation and memory allocation */
+	ngates = find_last_bit(data->mask, SUN6I_APB0_GATES_MAX_SIZE);
+	clk_data->clks = devm_kcalloc(&pdev->dev, (ngates + 1),
+				      sizeof(struct clk *), GFP_KERNEL);
 	if (!clk_data->clks)
 		return -ENOMEM;
 
-	for (i = 0; i < ngates; i++) {
+	for_each_set_bit(i, data->mask, SUN6I_APB0_GATES_MAX_SIZE) {
 		of_property_read_string_index(np, "clock-output-names",
-					      i, &clk_name);
-
-		gate_id = i;
-		of_property_read_u32_index(np, "clock-indices", i, &gate_id);
+					      j, &clk_name);
 
-		WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE);
-		if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE)
-			continue;
+		clk_data->clks[i] = clk_register_gate(&pdev->dev, clk_name,
+						      clk_parent, 0, reg, i,
+						      0, NULL);
+		WARN_ON(IS_ERR(clk_data->clks[i]));
+		clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
 
-		clk_data->clks[gate_id] = clk_register_gate(&pdev->dev,
-							    clk_name,
-							    clk_parent, 0,
-							    reg, gate_id,
-							    0, NULL);
-		WARN_ON(IS_ERR(clk_data->clks[gate_id]));
+		j++;
 	}
 
-	clk_data->clk_num = ngates;
+	clk_data->clk_num = ngates + 1;
 
 	return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
 }
 
-const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
-	{ .compatible = "allwinner,sun6i-a31-apb0-gates-clk" },
-	{ /* sentinel */ }
-};
-
 static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
 	.driver = {
 		.name = "sun6i-a31-apb0-gates-clk",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-ar100.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-ar100.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun6i-ar100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun6i-ar100.c	2014-09-28 17:29:07.000000000 -0400
@@ -160,7 +160,7 @@ static int ar100_set_rate(struct clk_hw
 	return 0;
 }
 
-struct clk_ops ar100_ops = {
+static struct clk_ops ar100_ops = {
 	.recalc_rate = ar100_recalc_rate,
 	.determine_rate = ar100_determine_rate,
 	.set_parent = ar100_set_parent,
@@ -213,7 +213,7 @@ static int sun6i_a31_ar100_clk_probe(str
 	return of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
 
-const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
+static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
 	{ .compatible = "allwinner,sun6i-a31-ar100-clk" },
 	{ /* sentinel */ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun8i-apb0.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun8i-apb0.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sun8i-apb0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sun8i-apb0.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Chen-Yu Tsai
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * Allwinner A23 APB0 clock driver
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Based on clk-sun6i-apb0.c
+ * Allwinner A31 APB0 clock driver
+ *
+ * Copyright (C) 2014 Free Electrons
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const char *clk_name = np->name;
+	const char *clk_parent;
+	struct resource *r;
+	void __iomem *reg;
+	struct clk *clk;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	clk_parent = of_clk_get_parent_name(np, 0);
+	if (!clk_parent)
+		return -EINVAL;
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+
+	/* The A23 APB0 clock is a standard 2 bit wide divider clock */
+	clk = clk_register_divider(&pdev->dev, clk_name, clk_parent, 0, reg,
+				   0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	return of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
+	{ .compatible = "allwinner,sun8i-a23-apb0-clk" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver sun8i_a23_apb0_clk_driver = {
+	.driver = {
+		.name = "sun8i-a23-apb0-clk",
+		.owner = THIS_MODULE,
+		.of_match_table = sun8i_a23_apb0_clk_dt_ids,
+	},
+	.probe = sun8i_a23_apb0_clk_probe,
+};
+module_platform_driver(sun8i_a23_apb0_clk_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_DESCRIPTION("Allwinner A23 APB0 clock Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sunxi.c linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sunxi.c
--- linux-libre-3.16-gnu/drivers/clk/sunxi/clk-sunxi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/clk-sunxi.c	2014-09-28 17:29:07.000000000 -0400
@@ -164,6 +164,54 @@ static void sun6i_a31_get_pll1_factors(u
 }
 
 /**
+ * sun8i_a23_get_pll1_factors() - calculates n, k, m, p factors for PLL1
+ * PLL1 rate is calculated as follows
+ * rate = (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
+ * parent_rate is always 24Mhz
+ */
+
+static void sun8i_a23_get_pll1_factors(u32 *freq, u32 parent_rate,
+				   u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div;
+
+	/* Normalize value to a 6M multiple */
+	div = *freq / 6000000;
+	*freq = 6000000 * div;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	/* m is always zero for pll1 */
+	*m = 0;
+
+	/* k is 1 only on these cases */
+	if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000)
+		*k = 1;
+	else
+		*k = 0;
+
+	/* p will be 2 for divs under 20 and odd divs under 32 */
+	if (div < 20 || (div < 32 && (div & 1)))
+		*p = 2;
+
+	/* p will be 1 for even divs under 32, divs under 40 and odd pairs
+	 * of divs between 40-62 */
+	else if (div < 40 || (div < 64 && (div & 2)))
+		*p = 1;
+
+	/* any other entries have p = 0 */
+	else
+		*p = 0;
+
+	/* calculate a suitable n based on k and p */
+	div <<= *p;
+	div /= (*k + 1);
+	*n = div / 4 - 1;
+}
+
+/**
  * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
  * PLL5 rate is calculated as follows
  * rate = parent_rate * n * (k + 1)
@@ -422,6 +470,18 @@ static struct clk_factors_config sun6i_a
 	.mwidth = 2,
 };
 
+static struct clk_factors_config sun8i_a23_pll1_config = {
+	.nshift = 8,
+	.nwidth = 5,
+	.kshift = 4,
+	.kwidth = 2,
+	.mshift = 0,
+	.mwidth = 2,
+	.pshift = 16,
+	.pwidth = 2,
+	.n_start = 1,
+};
+
 static struct clk_factors_config sun4i_pll5_config = {
 	.nshift = 8,
 	.nwidth = 5,
@@ -471,6 +531,12 @@ static const struct factors_data sun6i_a
 	.getter = sun6i_a31_get_pll1_factors,
 };
 
+static const struct factors_data sun8i_a23_pll1_data __initconst = {
+	.enable = 31,
+	.table = &sun8i_a23_pll1_config,
+	.getter = sun8i_a23_get_pll1_factors,
+};
+
 static const struct factors_data sun7i_a20_pll4_data __initconst = {
 	.enable = 31,
 	.table = &sun4i_pll5_config,
@@ -527,7 +593,7 @@ static struct clk * __init sunxi_factors
 	struct clk_hw *mux_hw = NULL;
 	const char *clk_name = node->name;
 	const char *parents[SUNXI_MAX_PARENTS];
-	void *reg;
+	void __iomem *reg;
 	int i = 0;
 
 	reg = of_iomap(node, 0);
@@ -632,7 +698,7 @@ static void __init sunxi_mux_clk_setup(s
 	struct clk *clk;
 	const char *clk_name = node->name;
 	const char *parents[SUNXI_MAX_PARENTS];
-	void *reg;
+	void __iomem *reg;
 	int i = 0;
 
 	reg = of_iomap(node, 0);
@@ -664,6 +730,7 @@ struct div_data {
 	u8	shift;
 	u8	pow;
 	u8	width;
+	const struct clk_div_table *table;
 };
 
 static const struct div_data sun4i_axi_data __initconst = {
@@ -672,6 +739,23 @@ static const struct div_data sun4i_axi_d
 	.width	= 2,
 };
 
+static const struct clk_div_table sun8i_a23_axi_table[] __initconst = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 3, .div = 4 },
+	{ .val = 4, .div = 4 },
+	{ .val = 5, .div = 4 },
+	{ .val = 6, .div = 4 },
+	{ .val = 7, .div = 4 },
+	{ } /* sentinel */
+};
+
+static const struct div_data sun8i_a23_axi_data __initconst = {
+	.width	= 3,
+	.table	= sun8i_a23_axi_table,
+};
+
 static const struct div_data sun4i_ahb_data __initconst = {
 	.shift	= 4,
 	.pow	= 1,
@@ -696,7 +780,7 @@ static void __init sunxi_divider_clk_set
 	struct clk *clk;
 	const char *clk_name = node->name;
 	const char *clk_parent;
-	void *reg;
+	void __iomem *reg;
 
 	reg = of_iomap(node, 0);
 
@@ -704,10 +788,10 @@ static void __init sunxi_divider_clk_set
 
 	of_property_read_string(node, "clock-output-names", &clk_name);
 
-	clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
-				   reg, data->shift, data->width,
-				   data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
-				   &clk_lock);
+	clk = clk_register_divider_table(NULL, clk_name, clk_parent, 0,
+					 reg, data->shift, data->width,
+					 data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
+					 data->table, &clk_lock);
 	if (clk) {
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
 		clk_register_clkdev(clk, clk_name, NULL);
@@ -804,6 +888,10 @@ static const struct gates_data sun7i_a20
 	.mask = { 0x12f77fff, 0x16ff3f },
 };
 
+static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
+	.mask = {0x25386742, 0x2505111},
+};
+
 static const struct gates_data sun4i_apb0_gates_data __initconst = {
 	.mask = {0x4EF},
 };
@@ -836,6 +924,10 @@ static const struct gates_data sun6i_a31
 	.mask = {0x3031},
 };
 
+static const struct gates_data sun8i_a23_apb1_gates_data __initconst = {
+	.mask = {0x3021},
+};
+
 static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
 	.mask = {0x3F000F},
 };
@@ -844,6 +936,10 @@ static const struct gates_data sun7i_a20
 	.mask = { 0xff80ff },
 };
 
+static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
+	.mask = {0x1F0007},
+};
+
 static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
 	.mask = {0x1C0},
 	.reset_mask = 0x07,
@@ -866,11 +962,10 @@ static void __init sunxi_gates_clk_setup
 	struct gates_reset_data *reset_data;
 	const char *clk_parent;
 	const char *clk_name;
-	void *reg;
+	void __iomem *reg;
 	int qty;
 	int i = 0;
 	int j = 0;
-	int ignore;
 
 	reg = of_iomap(node, 0);
 
@@ -891,14 +986,12 @@ static void __init sunxi_gates_clk_setup
 		of_property_read_string_index(node, "clock-output-names",
 					      j, &clk_name);
 
-		/* No driver claims this clock, but it should remain gated */
-		ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0;
-
 		clk_data->clks[i] = clk_register_gate(NULL, clk_name,
-						      clk_parent, ignore,
+						      clk_parent, 0,
 						      reg + 4 * (i/32), i % 32,
 						      0, &clk_lock);
 		WARN_ON(IS_ERR(clk_data->clks[i]));
+		clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
 
 		j++;
 	}
@@ -991,7 +1084,7 @@ static void __init sunxi_divs_clk_setup(
 	struct clk_gate *gate = NULL;
 	struct clk_fixed_factor *fix_factor;
 	struct clk_divider *divider;
-	void *reg;
+	void __iomem *reg;
 	int i = 0;
 	int flags, clkflags;
 
@@ -1102,6 +1195,7 @@ free_clkdata:
 static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,},
 	{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+	{.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
 	{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
@@ -1113,6 +1207,7 @@ static const struct of_device_id clk_fac
 /* Matches for divider clocks */
 static const struct of_device_id clk_div_match[] __initconst = {
 	{.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,},
+	{.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,},
 	{.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
 	{.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
 	{.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
@@ -1142,6 +1237,7 @@ static const struct of_device_id clk_gat
 	{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
 	{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
+	{.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
 	{.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
 	{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
 	{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
@@ -1151,7 +1247,9 @@ static const struct of_device_id clk_gat
 	{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
 	{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
+	{.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
+	{.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
 	{.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
 	{.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
@@ -1202,6 +1300,7 @@ static void __init sunxi_init_clocks(con
 
 static const char *sun4i_a10_critical_clocks[] __initdata = {
 	"pll5_ddr",
+	"ahb_sdram",
 };
 
 static void __init sun4i_a10_init_clocks(struct device_node *node)
@@ -1214,6 +1313,7 @@ CLK_OF_DECLARE(sun4i_a10_clk_init, "allw
 static const char *sun5i_critical_clocks[] __initdata = {
 	"mbus",
 	"pll5_ddr",
+	"ahb_sdram",
 };
 
 static void __init sun5i_init_clocks(struct device_node *node)
@@ -1236,3 +1336,4 @@ static void __init sun6i_init_clocks(str
 			  ARRAY_SIZE(sun6i_critical_clocks));
 }
 CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/sunxi/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/Makefile
--- linux-libre-3.16-gnu/drivers/clk/sunxi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/sunxi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -6,4 +6,6 @@ obj-y += clk-sunxi.o clk-factors.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
 
-obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o
+obj-$(CONFIG_MFD_SUN6I_PRCM) += \
+	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
+	clk-sun8i-apb0.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,7 +19,8 @@
 #include <linux/of.h>
 #include <linux/clk/tegra.h>
 #include <linux/reset-controller.h>
-#include <linux/tegra-soc.h>
+
+#include <soc/tegra/fuse.h>
 
 #include "clk.h"
 
@@ -277,6 +278,12 @@ void __init tegra_register_devclks(struc
 	for (i = 0; i < num; i++, dev_clks++)
 		clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
 				dev_clks->dev_id);
+
+	for (i = 0; i < clk_num; i++) {
+		if (!IS_ERR_OR_NULL(clks[i]))
+			clk_register_clkdev(clks[i], __clk_get_name(clks[i]),
+				"tegra-clk-debug");
+	}
 }
 
 struct clk ** __init tegra_lookup_dt_id(int clk_id,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-periph-gate.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-periph-gate.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-periph-gate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-periph-gate.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/tegra-soc.h>
+
+#include <soc/tegra/fuse.h>
 
 #include "clk.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-pll.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-pll.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-pll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-pll.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,6 +110,12 @@
 #define XUSBIO_PLL_CFG0_SEQ_ENABLE		BIT(24)
 #define XUSBIO_PLL_CFG0_SEQ_START_STATE		BIT(25)
 
+#define SATA_PLL_CFG0		0x490
+#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL	BIT(0)
+#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET	BIT(2)
+#define SATA_PLL_CFG0_SEQ_ENABLE		BIT(24)
+#define SATA_PLL_CFG0_SEQ_START_STATE		BIT(25)
+
 #define PLLE_MISC_PLLE_PTS	BIT(8)
 #define PLLE_MISC_IDDQ_SW_VALUE	BIT(13)
 #define PLLE_MISC_IDDQ_SW_CTRL	BIT(14)
@@ -1361,6 +1367,19 @@ static int clk_plle_tegra114_enable(stru
 	val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
 	pll_writel(val, XUSBIO_PLL_CFG0, pll);
 
+	/* Enable hw control of SATA pll */
+	val = pll_readl(SATA_PLL_CFG0, pll);
+	val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
+	val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET;
+	val |= SATA_PLL_CFG0_SEQ_START_STATE;
+	pll_writel(val, SATA_PLL_CFG0, pll);
+
+	udelay(1);
+
+	val = pll_readl(SATA_PLL_CFG0, pll);
+	val |= SATA_PLL_CFG0_SEQ_ENABLE;
+	pll_writel(val, SATA_PLL_CFG0, pll);
+
 out:
 	if (pll->lock)
 		spin_unlock_irqrestore(pll->lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra114.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra114.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra114.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra114.c	2014-09-28 17:29:07.000000000 -0400
@@ -151,6 +151,13 @@
 /* Tegra CPU clock and reset control regs */
 #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
 
+#define MUX8(_name, _parents, _offset, \
+			     _clk_num, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+			29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+			_clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
+			NULL)
+
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
 	u32 clk_csite_src;
@@ -777,7 +784,6 @@ static struct tegra_clk tegra114_clks[te
 	[tegra_clk_spdif_in] = { .dt_id = TEGRA114_CLK_SPDIF_IN, .present = true },
 	[tegra_clk_spdif_out] = { .dt_id = TEGRA114_CLK_SPDIF_OUT, .present = true },
 	[tegra_clk_vi_8] = { .dt_id = TEGRA114_CLK_VI, .present = true },
-	[tegra_clk_vi_sensor_8] = { .dt_id = TEGRA114_CLK_VI_SENSOR, .present = true },
 	[tegra_clk_fuse] = { .dt_id = TEGRA114_CLK_FUSE, .present = true },
 	[tegra_clk_fuse_burn] = { .dt_id = TEGRA114_CLK_FUSE_BURN, .present = true },
 	[tegra_clk_clk_32k] = { .dt_id = TEGRA114_CLK_CLK_32K, .present = true },
@@ -923,6 +929,13 @@ static struct tegra_devclk devclks[] __i
 	{ .dev_id = "timer", .dt_id = TEGRA114_CLK_TIMER },
 };
 
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+	"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+static u32 mux_pllm_pllc2_c_c3_pllp_plla_idx[] = {
+	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
 static struct clk **clks;
 
 static unsigned long osc_freq;
@@ -1178,10 +1191,18 @@ static void __init tegra114_pll_init(voi
 	clks[TEGRA114_CLK_PLL_E_OUT0] = clk;
 }
 
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+
+static struct tegra_periph_init_data tegra_periph_clk_list[] = {
+	MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR),
+};
+
 static __init void tegra114_periph_clk_init(void __iomem *clk_base,
 					    void __iomem *pmc_base)
 {
 	struct clk *clk;
+	struct tegra_periph_init_data *data;
+	int i;
 
 	/* xusb_ss_div2 */
 	clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
@@ -1209,6 +1230,14 @@ static __init void tegra114_periph_clk_i
 			       clk_base + CLK_SOURCE_EMC,
 			       29, 3, 0, NULL);
 
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+		data = &tegra_periph_clk_list[i];
+		clk = tegra_clk_register_periph(data->name,
+			data->p.parent_names, data->num_parents,
+			&data->periph, clk_base, data->offset, data->flags);
+		clks[data->clk_id] = clk;
+	}
+
 	tegra_periph_clk_init(clk_base, pmc_base, tegra114_clks,
 				&pll_p_params);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra124.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra124.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra124.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra124.c	2014-09-28 17:29:07.000000000 -0400
@@ -869,7 +869,7 @@ static struct tegra_clk tegra124_clks[te
 	[tegra_clk_spdif_in] = { .dt_id = TEGRA124_CLK_SPDIF_IN, .present = true },
 	[tegra_clk_spdif_out] = { .dt_id = TEGRA124_CLK_SPDIF_OUT, .present = true },
 	[tegra_clk_vi_9] = { .dt_id = TEGRA124_CLK_VI, .present = true },
-	[tegra_clk_vi_sensor] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true },
+	[tegra_clk_vi_sensor_8] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true },
 	[tegra_clk_fuse] = { .dt_id = TEGRA124_CLK_FUSE, .present = true },
 	[tegra_clk_fuse_burn] = { .dt_id = TEGRA124_CLK_FUSE_BURN, .present = true },
 	[tegra_clk_clk_32k] = { .dt_id = TEGRA124_CLK_CLK_32K, .present = true },
@@ -1369,6 +1369,14 @@ static struct tegra_clk_init_table init_
 	{TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0},
 	{TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0},
 	{TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
+	{TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
+	{TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
+	{TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
+	{TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
+	{TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
+	{TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
+	{TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
+	{TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0},
 	/* This MUST be the last entry. */
 	{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra30.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra30.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra30.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,11 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/tegra.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
+
 #include <dt-bindings/clock/tegra30-car.h>
+
 #include "clk.h"
 #include "clk-id.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra-periph.c linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra-periph.c
--- linux-libre-3.16-gnu/drivers/clk/tegra/clk-tegra-periph.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/tegra/clk-tegra-periph.c	2014-09-28 17:29:07.000000000 -0400
@@ -469,7 +469,7 @@ static struct tegra_periph_init_data per
 	MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
 	MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
 	MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
-	MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+	MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
 	MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8),
 	MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8),
 	MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8),
@@ -487,7 +487,7 @@ static struct tegra_periph_init_data per
 	MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
 	MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
 	MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
-	MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
+	MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
 	MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
 	MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy),
 	MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/ti/clk-7xx.c linux-libre-3.17-rc7-gnu/drivers/clk/ti/clk-7xx.c
--- linux-libre-3.16-gnu/drivers/clk/ti/clk-7xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/ti/clk-7xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 
 #define DRA7_DPLL_ABE_DEFFREQ				180633600
 #define DRA7_DPLL_GMAC_DEFFREQ				1000000000
+#define DRA7_DPLL_USB_DEFFREQ				960000000
 
 
 static struct ti_dt_clk dra7xx_clks[] = {
@@ -332,5 +333,15 @@ int __init dra7xx_dt_clk_init(void)
 	if (rc)
 		pr_err("%s: failed to configure GMAC DPLL!\n", __func__);
 
+	dpll_ck = clk_get_sys(NULL, "dpll_usb_ck");
+	rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+	dpll_ck = clk_get_sys(NULL, "dpll_usb_m2_ck");
+	rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ/2);
+	if (rc)
+		pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__);
+
 	return rc;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/ti/clk-dra7-atl.c linux-libre-3.17-rc7-gnu/drivers/clk/ti/clk-dra7-atl.c
--- linux-libre-3.16-gnu/drivers/clk/ti/clk-dra7-atl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/ti/clk-dra7-atl.c	2014-09-28 17:29:07.000000000 -0400
@@ -139,9 +139,13 @@ static long atl_clk_round_rate(struct cl
 static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 			    unsigned long parent_rate)
 {
-	struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+	struct dra7_atl_desc *cdesc;
 	u32 divider;
 
+	if (!hw || !rate)
+		return -EINVAL;
+
+	cdesc = to_atl_desc(hw);
 	divider = ((parent_rate + rate / 2) / rate) - 1;
 	if (divider > DRA7_ATL_DIVIDER_MASK)
 		divider = DRA7_ATL_DIVIDER_MASK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/ti/divider.c linux-libre-3.17-rc7-gnu/drivers/clk/ti/divider.c
--- linux-libre-3.16-gnu/drivers/clk/ti/divider.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/ti/divider.c	2014-09-28 17:29:07.000000000 -0400
@@ -211,11 +211,16 @@ static long ti_clk_divider_round_rate(st
 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 				   unsigned long parent_rate)
 {
-	struct clk_divider *divider = to_clk_divider(hw);
+	struct clk_divider *divider;
 	unsigned int div, value;
 	unsigned long flags = 0;
 	u32 val;
 
+	if (!hw || !rate)
+		return -EINVAL;
+
+	divider = to_clk_divider(hw);
+
 	div = DIV_ROUND_UP(parent_rate, rate);
 	value = _get_val(divider, div);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/versatile/clk-integrator.c linux-libre-3.17-rc7-gnu/drivers/clk/versatile/clk-integrator.c
--- linux-libre-3.16-gnu/drivers/clk/versatile/clk-integrator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/versatile/clk-integrator.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- * Clock driver for the ARM Integrator/AP and Integrator/CP boards
- * Copyright (C) 2012 Linus Walleij
- *
- * This program is free software; you can redistribute it 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-provider.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include "clk-icst.h"
-
-#define INTEGRATOR_HDR_LOCK_OFFSET	0x14
-
-/* Base offset for the core module */
-static void __iomem *cm_base;
-
-static const struct icst_params cp_auxosc_params = {
-	.vco_max	= ICST525_VCO_MAX_5V,
-	.vco_min	= ICST525_VCO_MIN,
-	.vd_min 	= 8,
-	.vd_max 	= 263,
-	.rd_min 	= 3,
-	.rd_max 	= 65,
-	.s2div		= icst525_s2div,
-	.idx2s		= icst525_idx2s,
-};
-
-static const struct clk_icst_desc __initdata cm_auxosc_desc = {
-	.params = &cp_auxosc_params,
-	.vco_offset = 0x1c,
-	.lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
-};
-
-static void __init of_integrator_cm_osc_setup(struct device_node *np)
-{
-	struct clk *clk = ERR_PTR(-EINVAL);
-	const char *clk_name = np->name;
-	const struct clk_icst_desc *desc = &cm_auxosc_desc;
-	const char *parent_name;
-
-	if (!cm_base) {
-		/* Remap the core module base if not done yet */
-		struct device_node *parent;
-
-		parent = of_get_parent(np);
-		if (!np) {
-			pr_err("no parent on core module clock\n");
-			return;
-		}
-		cm_base = of_iomap(parent, 0);
-		if (!cm_base) {
-			pr_err("could not remap core module base\n");
-			return;
-		}
-	}
-
-	parent_name = of_clk_get_parent_name(np, 0);
-	clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base);
-	if (!IS_ERR(clk))
-		of_clk_add_provider(np, of_clk_src_simple_get, clk);
-}
-CLK_OF_DECLARE(integrator_cm_auxosc_clk,
-	"arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/versatile/clk-versatile.c linux-libre-3.17-rc7-gnu/drivers/clk/versatile/clk-versatile.c
--- linux-libre-3.16-gnu/drivers/clk/versatile/clk-versatile.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clk/versatile/clk-versatile.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * Clock driver for the ARM Integrator/AP, Integrator/CP, Versatile AB and
+ * Versatile PB boards.
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute it 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-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk-icst.h"
+
+#define INTEGRATOR_HDR_LOCK_OFFSET	0x14
+
+#define VERSATILE_SYS_OSCCLCD_OFFSET	0x1c
+#define VERSATILE_SYS_LOCK_OFFSET	0x20
+
+/* Base offset for the core module */
+static void __iomem *cm_base;
+
+static const struct icst_params cp_auxosc_params = {
+	.vco_max	= ICST525_VCO_MAX_5V,
+	.vco_min	= ICST525_VCO_MIN,
+	.vd_min 	= 8,
+	.vd_max 	= 263,
+	.rd_min 	= 3,
+	.rd_max 	= 65,
+	.s2div		= icst525_s2div,
+	.idx2s		= icst525_idx2s,
+};
+
+static const struct clk_icst_desc __initdata cm_auxosc_desc = {
+	.params = &cp_auxosc_params,
+	.vco_offset = 0x1c,
+	.lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
+};
+
+static const struct icst_params versatile_auxosc_params = {
+	.vco_max	= ICST307_VCO_MAX,
+	.vco_min	= ICST307_VCO_MIN,
+	.vd_min		= 4 + 8,
+	.vd_max		= 511 + 8,
+	.rd_min		= 1 + 2,
+	.rd_max		= 127 + 2,
+	.s2div		= icst307_s2div,
+	.idx2s		= icst307_idx2s,
+};
+
+static const struct clk_icst_desc versatile_auxosc_desc __initconst = {
+	.params = &versatile_auxosc_params,
+	.vco_offset = VERSATILE_SYS_OSCCLCD_OFFSET,
+	.lock_offset = VERSATILE_SYS_LOCK_OFFSET,
+};
+static void __init cm_osc_setup(struct device_node *np,
+				const struct clk_icst_desc *desc)
+{
+	struct clk *clk = ERR_PTR(-EINVAL);
+	const char *clk_name = np->name;
+	const char *parent_name;
+
+	if (!cm_base) {
+		/* Remap the core module base if not done yet */
+		struct device_node *parent;
+
+		parent = of_get_parent(np);
+		if (!np) {
+			pr_err("no parent on core module clock\n");
+			return;
+		}
+		cm_base = of_iomap(parent, 0);
+		if (!cm_base) {
+			pr_err("could not remap core module base\n");
+			return;
+		}
+	}
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base);
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static void __init of_integrator_cm_osc_setup(struct device_node *np)
+{
+	cm_osc_setup(np, &cm_auxosc_desc);
+}
+CLK_OF_DECLARE(integrator_cm_auxosc_clk,
+	"arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
+
+static void __init of_versatile_cm_osc_setup(struct device_node *np)
+{
+	cm_osc_setup(np, &versatile_auxosc_desc);
+}
+CLK_OF_DECLARE(versatile_cm_auxosc_clk,
+	       "arm,versatile-cm-auxosc", of_versatile_cm_osc_setup);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clk/versatile/Makefile linux-libre-3.17-rc7-gnu/drivers/clk/versatile/Makefile
--- linux-libre-3.16-gnu/drivers/clk/versatile/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clk/versatile/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,5 @@
 # Makefile for Versatile-specific clocks
-obj-$(CONFIG_ICST)		+= clk-icst.o
-obj-$(CONFIG_ARCH_INTEGRATOR)	+= clk-integrator.o
+obj-$(CONFIG_ICST)		+= clk-icst.o clk-versatile.o
 obj-$(CONFIG_INTEGRATOR_IMPD1)	+= clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)	+= clk-realview.o
 obj-$(CONFIG_ARCH_VEXPRESS)	+= clk-vexpress.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/arm_global_timer.c linux-libre-3.17-rc7-gnu/drivers/clocksource/arm_global_timer.c
--- linux-libre-3.16-gnu/drivers/clocksource/arm_global_timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/arm_global_timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -250,7 +250,7 @@ static void __init global_timer_of_regis
 	 * fire when the timer value is greater than or equal to. In previous
 	 * revisions the comparators fired when the timer value was equal to.
 	 */
-	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9
 	    && (read_cpuid_id() & 0xf0000f) < 0x200000) {
 		pr_warn("global-timer: non support for this cpu version.\n");
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/clps711x-timer.c linux-libre-3.17-rc7-gnu/drivers/clocksource/clps711x-timer.c
--- linux-libre-3.16-gnu/drivers/clocksource/clps711x-timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/clps711x-timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ *  Cirrus Logic CLPS711X clocksource driver
+ *
+ *  Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+
+enum {
+	CLPS711X_CLKSRC_CLOCKSOURCE,
+	CLPS711X_CLKSRC_CLOCKEVENT,
+};
+
+static void __iomem *tcd;
+
+static u64 notrace clps711x_sched_clock_read(void)
+{
+	return ~readw(tcd);
+}
+
+static int __init _clps711x_clksrc_init(struct clk *clock, void __iomem *base)
+{
+	unsigned long rate;
+
+	if (!base)
+		return -ENOMEM;
+	if (IS_ERR(clock))
+		return PTR_ERR(clock);
+
+	rate = clk_get_rate(clock);
+
+	tcd = base;
+
+	clocksource_mmio_init(tcd, "clps711x-clocksource", rate, 300, 16,
+			      clocksource_mmio_readw_down);
+
+	sched_clock_register(clps711x_sched_clock_read, 16, rate);
+
+	return 0;
+}
+
+static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void clps711x_clockevent_set_mode(enum clock_event_mode mode,
+					 struct clock_event_device *evt)
+{
+}
+
+static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base,
+					unsigned int irq)
+{
+	struct clock_event_device *clkevt;
+	unsigned long rate;
+
+	if (!irq)
+		return -EINVAL;
+	if (!base)
+		return -ENOMEM;
+	if (IS_ERR(clock))
+		return PTR_ERR(clock);
+
+	clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
+	if (!clkevt)
+		return -ENOMEM;
+
+	rate = clk_get_rate(clock);
+
+	/* Set Timer prescaler */
+	writew(DIV_ROUND_CLOSEST(rate, HZ), base);
+
+	clkevt->name = "clps711x-clockevent";
+	clkevt->rating = 300;
+	clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP;
+	clkevt->set_mode = clps711x_clockevent_set_mode;
+	clkevt->cpumask = cpumask_of(0);
+	clockevents_config_and_register(clkevt, HZ, 0, 0);
+
+	return request_irq(irq, clps711x_timer_interrupt, IRQF_TIMER,
+			   "clps711x-timer", clkevt);
+}
+
+void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base,
+				 unsigned int irq)
+{
+	struct clk *tc1 = clk_get_sys("clps711x-timer.0", NULL);
+	struct clk *tc2 = clk_get_sys("clps711x-timer.1", NULL);
+
+	BUG_ON(_clps711x_clksrc_init(tc1, tc1_base));
+	BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq));
+}
+
+#ifdef CONFIG_CLKSRC_OF
+static void __init clps711x_timer_init(struct device_node *np)
+{
+	unsigned int irq = irq_of_parse_and_map(np, 0);
+	struct clk *clock = of_clk_get(np, 0);
+	void __iomem *base = of_iomap(np, 0);
+
+	switch (of_alias_get_id(np, "timer")) {
+	case CLPS711X_CLKSRC_CLOCKSOURCE:
+		BUG_ON(_clps711x_clksrc_init(clock, base));
+		break;
+	case CLPS711X_CLKSRC_CLOCKEVENT:
+		BUG_ON(_clps711x_clkevt_init(clock, base, irq));
+		break;
+	default:
+		break;
+	}
+}
+CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/exynos_mct.c linux-libre-3.17-rc7-gnu/drivers/clocksource/exynos_mct.c
--- linux-libre-3.16-gnu/drivers/clocksource/exynos_mct.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/exynos_mct.c	2014-09-28 17:29:07.000000000 -0400
@@ -94,7 +94,7 @@ static void exynos4_mct_write(unsigned i
 	u32 mask;
 	u32 i;
 
-	__raw_writel(value, reg_base + offset);
+	writel_relaxed(value, reg_base + offset);
 
 	if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
 		stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
@@ -144,8 +144,8 @@ static void exynos4_mct_write(unsigned i
 
 	/* Wait maximum 1 ms until written values are applied */
 	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-		if (__raw_readl(reg_base + stat_addr) & mask) {
-			__raw_writel(mask, reg_base + stat_addr);
+		if (readl_relaxed(reg_base + stat_addr) & mask) {
+			writel_relaxed(mask, reg_base + stat_addr);
 			return;
 		}
 
@@ -157,28 +157,51 @@ static void exynos4_mct_frc_start(void)
 {
 	u32 reg;
 
-	reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+	reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 	reg |= MCT_G_TCON_START;
 	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 }
 
-static cycle_t notrace _exynos4_frc_read(void)
+/**
+ * exynos4_read_count_64 - Read all 64-bits of the global counter
+ *
+ * This will read all 64-bits of the global counter taking care to make sure
+ * that the upper and lower half match.  Note that reading the MCT can be quite
+ * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half
+ * only) version when possible.
+ *
+ * Returns the number of cycles in the global counter.
+ */
+static u64 exynos4_read_count_64(void)
 {
 	unsigned int lo, hi;
-	u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+	u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
 
 	do {
 		hi = hi2;
-		lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
-		hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+		lo = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
+		hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
 	} while (hi != hi2);
 
 	return ((cycle_t)hi << 32) | lo;
 }
 
+/**
+ * exynos4_read_count_32 - Read the lower 32-bits of the global counter
+ *
+ * This will read just the lower 32-bits of the global counter.  This is marked
+ * as notrace so it can be used by the scheduler clock.
+ *
+ * Returns the number of cycles in the global counter (lower 32 bits).
+ */
+static u32 notrace exynos4_read_count_32(void)
+{
+	return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
+}
+
 static cycle_t exynos4_frc_read(struct clocksource *cs)
 {
-	return _exynos4_frc_read();
+	return exynos4_read_count_32();
 }
 
 static void exynos4_frc_resume(struct clocksource *cs)
@@ -190,21 +213,23 @@ struct clocksource mct_frc = {
 	.name		= "mct-frc",
 	.rating		= 400,
 	.read		= exynos4_frc_read,
-	.mask		= CLOCKSOURCE_MASK(64),
+	.mask		= CLOCKSOURCE_MASK(32),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.resume		= exynos4_frc_resume,
 };
 
 static u64 notrace exynos4_read_sched_clock(void)
 {
-	return _exynos4_frc_read();
+	return exynos4_read_count_32();
 }
 
 static struct delay_timer exynos4_delay_timer;
 
 static cycles_t exynos4_read_current_timer(void)
 {
-	return _exynos4_frc_read();
+	BUILD_BUG_ON_MSG(sizeof(cycles_t) != sizeof(u32),
+			 "cycles_t needs to move to 32-bit for ARM64 usage");
+	return exynos4_read_count_32();
 }
 
 static void __init exynos4_clocksource_init(void)
@@ -218,14 +243,14 @@ static void __init exynos4_clocksource_i
 	if (clocksource_register_hz(&mct_frc, clk_rate))
 		panic("%s: can't register clocksource\n", mct_frc.name);
 
-	sched_clock_register(exynos4_read_sched_clock, 64, clk_rate);
+	sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
 }
 
 static void exynos4_mct_comp0_stop(void)
 {
 	unsigned int tcon;
 
-	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+	tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 
 	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -238,14 +263,14 @@ static void exynos4_mct_comp0_start(enum
 	unsigned int tcon;
 	cycle_t comp_cycle;
 
-	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+	tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 
 	if (mode == CLOCK_EVT_MODE_PERIODIC) {
 		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
 		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
 	}
 
-	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+	comp_cycle = exynos4_read_count_64() + cycles;
 	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
 	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
 
@@ -327,7 +352,7 @@ static void exynos4_mct_tick_stop(struct
 	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
 	unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 
-	tmp = __raw_readl(reg_base + offset);
+	tmp = readl_relaxed(reg_base + offset);
 	if (tmp & mask) {
 		tmp &= ~mask;
 		exynos4_mct_write(tmp, offset);
@@ -349,7 +374,7 @@ static void exynos4_mct_tick_start(unsig
 	/* enable MCT tick interrupt */
 	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 
-	tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
+	tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET);
 	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 	       MCT_L_TCON_INTERVAL_MODE;
 	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -401,7 +426,7 @@ static int exynos4_mct_tick_clear(struct
 		exynos4_mct_tick_stop(mevt);
 
 	/* Clear the MCT tick interrupt */
-	if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+	if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
 		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 		return 1;
 	} else {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/Kconfig linux-libre-3.17-rc7-gnu/drivers/clocksource/Kconfig
--- linux-libre-3.16-gnu/drivers/clocksource/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,5 @@
+menu "Clock Source drivers"
+
 config CLKSRC_OF
 	bool
 
@@ -125,6 +127,7 @@ config CLKSRC_METAG_GENERIC
 
 config CLKSRC_EXYNOS_MCT
 	def_bool y if ARCH_EXYNOS
+	depends on !ARM64
 	help
 	  Support for Multi Core Timer controller on Exynos SoCs.
 
@@ -149,6 +152,11 @@ config VF_PIT_TIMER
 config SYS_SUPPORTS_SH_CMT
         bool
 
+config MTK_TIMER
+	select CLKSRC_OF
+	select CLKSRC_MMIO
+	bool
+
 config SYS_SUPPORTS_SH_MTU2
         bool
 
@@ -173,7 +181,7 @@ config SH_TIMER_MTU2
 	default SYS_SUPPORTS_SH_MTU2
 	help
 	  This enables build of a clockevent driver for the Multi-Function
-	  Timer Pulse Unit 2 (TMU2) hardware available on SoCs from Renesas.
+	  Timer Pulse Unit 2 (MTU2) hardware available on SoCs from Renesas.
 	  This hardware comes with 16 bit-timer registers.
 
 config SH_TIMER_TMU
@@ -187,7 +195,7 @@ config SH_TIMER_TMU
 
 config EM_TIMER_STI
 	bool "Renesas STI timer driver" if COMPILE_TEST
-	depends on GENERIC_CLOCKEVENTS
+	depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
 	default SYS_SUPPORTS_EM_STI
 	help
 	  This enables build of a clocksource and clockevent driver for
@@ -207,3 +215,5 @@ config CLKSRC_VERSATILE
 	  counter available in the "System Registers" block of
 	  ARM Versatile, RealView and Versatile Express reference
 	  platforms.
+
+endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/Makefile linux-libre-3.17-rc7-gnu/drivers/clocksource/Makefile
--- linux-libre-3.16-gnu/drivers/clocksource/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -16,9 +16,11 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clk
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ORION_TIMER)	+= time-orion.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
+obj-$(CONFIG_ARCH_CLPS711X)	+= clps711x-timer.o
 obj-$(CONFIG_ARCH_MARCO)	+= timer-marco.o
 obj-$(CONFIG_ARCH_MOXART)	+= moxart_timer.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
+obj-$(CONFIG_ARCH_PXA)		+= pxa_timer.o
 obj-$(CONFIG_ARCH_PRIMA2)	+= timer-prima2.o
 obj-$(CONFIG_ARCH_U300)		+= timer-u300.o
 obj-$(CONFIG_SUN4I_TIMER)	+= sun4i_timer.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= sams
 obj-$(CONFIG_FSL_FTM_TIMER)	+= fsl_ftm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o
 obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
+obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/mtk_timer.c linux-libre-3.17-rc7-gnu/drivers/clocksource/mtk_timer.c
--- linux-libre-3.16-gnu/drivers/clocksource/mtk_timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/mtk_timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,261 @@
+/*
+ * Mediatek SoCs General-Purpose Timer handling.
+ *
+ * Copyright (C) 2014 Matthias Brugger
+ *
+ * Matthias Brugger <matthias.bgg@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/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#define GPT_IRQ_EN_REG		0x00
+#define GPT_IRQ_ENABLE(val)	BIT((val) - 1)
+#define GPT_IRQ_ACK_REG		0x08
+#define GPT_IRQ_ACK(val)	BIT((val) - 1)
+
+#define TIMER_CTRL_REG(val)	(0x10 * (val))
+#define TIMER_CTRL_OP(val)	(((val) & 0x3) << 4)
+#define TIMER_CTRL_OP_ONESHOT	(0)
+#define TIMER_CTRL_OP_REPEAT	(1)
+#define TIMER_CTRL_OP_FREERUN	(3)
+#define TIMER_CTRL_CLEAR	(2)
+#define TIMER_CTRL_ENABLE	(1)
+#define TIMER_CTRL_DISABLE	(0)
+
+#define TIMER_CLK_REG(val)	(0x04 + (0x10 * (val)))
+#define TIMER_CLK_SRC(val)	(((val) & 0x1) << 4)
+#define TIMER_CLK_SRC_SYS13M	(0)
+#define TIMER_CLK_SRC_RTC32K	(1)
+#define TIMER_CLK_DIV1		(0x0)
+#define TIMER_CLK_DIV2		(0x1)
+
+#define TIMER_CNT_REG(val)	(0x08 + (0x10 * (val)))
+#define TIMER_CMP_REG(val)	(0x0C + (0x10 * (val)))
+
+#define GPT_CLK_EVT	1
+#define GPT_CLK_SRC	2
+
+struct mtk_clock_event_device {
+	void __iomem *gpt_base;
+	u32 ticks_per_jiffy;
+	struct clock_event_device dev;
+};
+
+static inline struct mtk_clock_event_device *to_mtk_clk(
+				struct clock_event_device *c)
+{
+	return container_of(c, struct mtk_clock_event_device, dev);
+}
+
+static void mtk_clkevt_time_stop(struct mtk_clock_event_device *evt, u8 timer)
+{
+	u32 val;
+
+	val = readl(evt->gpt_base + TIMER_CTRL_REG(timer));
+	writel(val & ~TIMER_CTRL_ENABLE, evt->gpt_base +
+			TIMER_CTRL_REG(timer));
+}
+
+static void mtk_clkevt_time_setup(struct mtk_clock_event_device *evt,
+				unsigned long delay, u8 timer)
+{
+	writel(delay, evt->gpt_base + TIMER_CMP_REG(timer));
+}
+
+static void mtk_clkevt_time_start(struct mtk_clock_event_device *evt,
+		bool periodic, u8 timer)
+{
+	u32 val;
+
+	/* Acknowledge interrupt */
+	writel(GPT_IRQ_ACK(timer), evt->gpt_base + GPT_IRQ_ACK_REG);
+
+	val = readl(evt->gpt_base + TIMER_CTRL_REG(timer));
+
+	/* Clear 2 bit timer operation mode field */
+	val &= ~TIMER_CTRL_OP(0x3);
+
+	if (periodic)
+		val |= TIMER_CTRL_OP(TIMER_CTRL_OP_REPEAT);
+	else
+		val |= TIMER_CTRL_OP(TIMER_CTRL_OP_ONESHOT);
+
+	writel(val | TIMER_CTRL_ENABLE | TIMER_CTRL_CLEAR,
+	       evt->gpt_base + TIMER_CTRL_REG(timer));
+}
+
+static void mtk_clkevt_mode(enum clock_event_mode mode,
+				struct clock_event_device *clk)
+{
+	struct mtk_clock_event_device *evt = to_mtk_clk(clk);
+
+	mtk_clkevt_time_stop(evt, GPT_CLK_EVT);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT);
+		mtk_clkevt_time_start(evt, true, GPT_CLK_EVT);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* Timer is enabled in set_next_event */
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		/* No more interrupts will occur as source is disabled */
+		break;
+	}
+}
+
+static int mtk_clkevt_next_event(unsigned long event,
+				   struct clock_event_device *clk)
+{
+	struct mtk_clock_event_device *evt = to_mtk_clk(clk);
+
+	mtk_clkevt_time_stop(evt, GPT_CLK_EVT);
+	mtk_clkevt_time_setup(evt, event, GPT_CLK_EVT);
+	mtk_clkevt_time_start(evt, false, GPT_CLK_EVT);
+
+	return 0;
+}
+
+static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
+{
+	struct mtk_clock_event_device *evt = dev_id;
+
+	/* Acknowledge timer0 irq */
+	writel(GPT_IRQ_ACK(GPT_CLK_EVT), evt->gpt_base + GPT_IRQ_ACK_REG);
+	evt->dev.event_handler(&evt->dev);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_timer_global_reset(struct mtk_clock_event_device *evt)
+{
+	/* Disable all interrupts */
+	writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
+	/* Acknowledge all interrupts */
+	writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
+}
+
+static void
+mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
+{
+	writel(TIMER_CTRL_CLEAR | TIMER_CTRL_DISABLE,
+		evt->gpt_base + TIMER_CTRL_REG(timer));
+
+	writel(TIMER_CLK_SRC(TIMER_CLK_SRC_SYS13M) | TIMER_CLK_DIV1,
+			evt->gpt_base + TIMER_CLK_REG(timer));
+
+	writel(0x0, evt->gpt_base + TIMER_CMP_REG(timer));
+
+	writel(TIMER_CTRL_OP(option) | TIMER_CTRL_ENABLE,
+			evt->gpt_base + TIMER_CTRL_REG(timer));
+}
+
+static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)
+{
+	u32 val;
+
+	val = readl(evt->gpt_base + GPT_IRQ_EN_REG);
+	writel(val | GPT_IRQ_ENABLE(timer),
+			evt->gpt_base + GPT_IRQ_EN_REG);
+}
+
+static void __init mtk_timer_init(struct device_node *node)
+{
+	struct mtk_clock_event_device *evt;
+	struct resource res;
+	unsigned long rate = 0;
+	struct clk *clk;
+
+	evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+	if (!evt) {
+		pr_warn("Can't allocate mtk clock event driver struct");
+		return;
+	}
+
+	evt->dev.name = "mtk_tick";
+	evt->dev.rating = 300;
+	evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	evt->dev.set_mode = mtk_clkevt_mode;
+	evt->dev.set_next_event = mtk_clkevt_next_event;
+	evt->dev.cpumask = cpu_possible_mask;
+
+	evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer");
+	if (IS_ERR(evt->gpt_base)) {
+		pr_warn("Can't get resource\n");
+		return;
+	}
+
+	evt->dev.irq = irq_of_parse_and_map(node, 0);
+	if (evt->dev.irq <= 0) {
+		pr_warn("Can't parse IRQ");
+		goto err_mem;
+	}
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_warn("Can't get timer clock");
+		goto err_irq;
+	}
+
+	if (clk_prepare_enable(clk)) {
+		pr_warn("Can't prepare clock");
+		goto err_clk_put;
+	}
+	rate = clk_get_rate(clk);
+
+	if (request_irq(evt->dev.irq, mtk_timer_interrupt,
+			IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
+		pr_warn("failed to setup irq %d\n", evt->dev.irq);
+		goto err_clk_disable;
+	}
+
+	evt->ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
+
+	mtk_timer_global_reset(evt);
+
+	/* Configure clock source */
+	mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
+	clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
+			node->name, rate, 300, 32, clocksource_mmio_readl_up);
+
+	/* Configure clock event */
+	mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
+	mtk_timer_enable_irq(evt, GPT_CLK_EVT);
+
+	clockevents_config_and_register(&evt->dev, rate, 0x3,
+					0xffffffff);
+	return;
+
+err_clk_disable:
+	clk_disable_unprepare(clk);
+err_clk_put:
+	clk_put(clk);
+err_irq:
+	irq_dispose_mapping(evt->dev.irq);
+err_mem:
+	iounmap(evt->gpt_base);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/pxa_timer.c linux-libre-3.17-rc7-gnu/drivers/clocksource/pxa_timer.c
--- linux-libre-3.16-gnu/drivers/clocksource/pxa_timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/pxa_timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ * arch/arm/mach-pxa/time.c
+ *
+ * PXA clocksource, clockevents, and OST interrupt handlers.
+ * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
+ *
+ * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
+ * by MontaVista Software, Inc.  (Nico, your code rocks!)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <asm/div64.h>
+
+#define OSMR0		0x00	/* OS Timer 0 Match Register */
+#define OSMR1		0x04	/* OS Timer 1 Match Register */
+#define OSMR2		0x08	/* OS Timer 2 Match Register */
+#define OSMR3		0x0C	/* OS Timer 3 Match Register */
+
+#define OSCR		0x10	/* OS Timer Counter Register */
+#define OSSR		0x14	/* OS Timer Status Register */
+#define OWER		0x18	/* OS Timer Watchdog Enable Register */
+#define OIER		0x1C	/* OS Timer Interrupt Enable Register */
+
+#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
+#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
+#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
+#define OSSR_M0		(1 << 0)	/* Match status channel 0 */
+
+#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */
+
+/*
+ * This is PXA's sched_clock implementation. This has a resolution
+ * of at least 308 ns and a maximum value of 208 days.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to sched_clock() which should always be the case in practice.
+ */
+
+#define timer_readl(reg) readl_relaxed(timer_base + (reg))
+#define timer_writel(val, reg) writel_relaxed((val), timer_base + (reg))
+
+static void __iomem *timer_base;
+
+static u64 notrace pxa_read_sched_clock(void)
+{
+	return timer_readl(OSCR);
+}
+
+
+#define MIN_OSCR_DELTA 16
+
+static irqreturn_t
+pxa_ost0_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *c = dev_id;
+
+	/* Disarm the compare/match, signal the event. */
+	timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+	timer_writel(OSSR_M0, OSSR);
+	c->event_handler(c);
+
+	return IRQ_HANDLED;
+}
+
+static int
+pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+	unsigned long next, oscr;
+
+	timer_writel(timer_readl(OIER) | OIER_E0, OIER);
+	next = timer_readl(OSCR) + delta;
+	timer_writel(next, OSMR0);
+	oscr = timer_readl(OSCR);
+
+	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
+}
+
+static void
+pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+		timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+		timer_writel(OSSR_M0, OSSR);
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* initializing, released, or preparing for suspend */
+		timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+		timer_writel(OSSR_M0, OSSR);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	}
+}
+
+#ifdef CONFIG_PM
+static unsigned long osmr[4], oier, oscr;
+
+static void pxa_timer_suspend(struct clock_event_device *cedev)
+{
+	osmr[0] = timer_readl(OSMR0);
+	osmr[1] = timer_readl(OSMR1);
+	osmr[2] = timer_readl(OSMR2);
+	osmr[3] = timer_readl(OSMR3);
+	oier = timer_readl(OIER);
+	oscr = timer_readl(OSCR);
+}
+
+static void pxa_timer_resume(struct clock_event_device *cedev)
+{
+	/*
+	 * Ensure that we have at least MIN_OSCR_DELTA between match
+	 * register 0 and the OSCR, to guarantee that we will receive
+	 * the one-shot timer interrupt.  We adjust OSMR0 in preference
+	 * to OSCR to guarantee that OSCR is monotonically incrementing.
+	 */
+	if (osmr[0] - oscr < MIN_OSCR_DELTA)
+		osmr[0] += MIN_OSCR_DELTA;
+
+	timer_writel(osmr[0], OSMR0);
+	timer_writel(osmr[1], OSMR1);
+	timer_writel(osmr[2], OSMR2);
+	timer_writel(osmr[3], OSMR3);
+	timer_writel(oier, OIER);
+	timer_writel(oscr, OSCR);
+}
+#else
+#define pxa_timer_suspend NULL
+#define pxa_timer_resume NULL
+#endif
+
+static struct clock_event_device ckevt_pxa_osmr0 = {
+	.name		= "osmr0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= pxa_osmr0_set_next_event,
+	.set_mode	= pxa_osmr0_set_mode,
+	.suspend	= pxa_timer_suspend,
+	.resume		= pxa_timer_resume,
+};
+
+static struct irqaction pxa_ost0_irq = {
+	.name		= "ost0",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= pxa_ost0_interrupt,
+	.dev_id		= &ckevt_pxa_osmr0,
+};
+
+static void pxa_timer_common_init(int irq, unsigned long clock_tick_rate)
+{
+	timer_writel(0, OIER);
+	timer_writel(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+	sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
+
+	ckevt_pxa_osmr0.cpumask = cpumask_of(0);
+
+	setup_irq(irq, &pxa_ost0_irq);
+
+	clocksource_mmio_init(timer_base + OSCR, "oscr0", clock_tick_rate, 200,
+			      32, clocksource_mmio_readl_up);
+	clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
+					MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
+
+static void __init pxa_timer_dt_init(struct device_node *np)
+{
+	struct clk *clk;
+	int irq;
+
+	/* timer registers are shared with watchdog timer */
+	timer_base = of_iomap(np, 0);
+	if (!timer_base)
+		panic("%s: unable to map resource\n", np->name);
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		pr_crit("%s: unable to get clk\n", np->name);
+		return;
+	}
+	clk_prepare_enable(clk);
+
+	/* we are only interested in OS-timer0 irq */
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		pr_crit("%s: unable to parse OS-timer0 irq\n", np->name);
+		return;
+	}
+
+	pxa_timer_common_init(irq, clk_get_rate(clk));
+}
+CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
+
+/*
+ * Legacy timer init for non device-tree boards.
+ */
+void __init pxa_timer_nodt_init(int irq, void __iomem *base,
+	unsigned long clock_tick_rate)
+{
+	struct clk *clk;
+
+	timer_base = base;
+	clk = clk_get(NULL, "OSTIMER0");
+	if (clk && !IS_ERR(clk))
+		clk_prepare_enable(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-3.16-gnu/drivers/clocksource/sh_cmt.c linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_cmt.c
--- linux-libre-3.16-gnu/drivers/clocksource/sh_cmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_cmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -114,14 +115,15 @@ struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	const struct sh_cmt_info *info;
-	bool legacy;
 
-	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
 	struct clk *clk;
 
+	raw_spinlock_t lock; /* Protect the shared start/stop register */
+
 	struct sh_cmt_channel *channels;
 	unsigned int num_channels;
+	unsigned int hw_channels;
 
 	bool has_clockevent;
 	bool has_clocksource;
@@ -301,14 +303,12 @@ static unsigned long sh_cmt_get_counter(
 	return v2;
 }
 
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
-
 static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
 {
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
-	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
+	raw_spin_lock_irqsave(&ch->cmt->lock, flags);
 	value = sh_cmt_read_cmstr(ch);
 
 	if (start)
@@ -317,7 +317,7 @@ static void sh_cmt_start_stop_ch(struct
 		value &= ~(1 << ch->timer_bit);
 
 	sh_cmt_write_cmstr(ch, value);
-	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
+	raw_spin_unlock_irqrestore(&ch->cmt->lock, flags);
 }
 
 static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
@@ -792,7 +792,7 @@ static int sh_cmt_register_clockevent(st
 	int irq;
 	int ret;
 
-	irq = platform_get_irq(ch->cmt->pdev, ch->cmt->legacy ? 0 : ch->index);
+	irq = platform_get_irq(ch->cmt->pdev, ch->index);
 	if (irq < 0) {
 		dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n",
 			ch->index);
@@ -863,33 +863,26 @@ static int sh_cmt_setup_channel(struct s
 	 * Compute the address of the channel control register block. For the
 	 * timers with a per-channel start/stop register, compute its address
 	 * as well.
-	 *
-	 * For legacy configuration the address has been mapped explicitly.
 	 */
-	if (cmt->legacy) {
-		ch->ioctrl = cmt->mapbase_ch;
-	} else {
-		switch (cmt->info->model) {
-		case SH_CMT_16BIT:
-			ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
-			break;
-		case SH_CMT_32BIT:
-		case SH_CMT_48BIT:
-			ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
-			break;
-		case SH_CMT_32BIT_FAST:
-			/*
-			 * The 32-bit "fast" timer has a single channel at hwidx
-			 * 5 but is located at offset 0x40 instead of 0x60 for
-			 * some reason.
-			 */
-			ch->ioctrl = cmt->mapbase + 0x40;
-			break;
-		case SH_CMT_48BIT_GEN2:
-			ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
-			ch->ioctrl = ch->iostart + 0x10;
-			break;
-		}
+	switch (cmt->info->model) {
+	case SH_CMT_16BIT:
+		ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
+		break;
+	case SH_CMT_32BIT:
+	case SH_CMT_48BIT:
+		ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
+		break;
+	case SH_CMT_32BIT_FAST:
+		/*
+		 * The 32-bit "fast" timer has a single channel at hwidx 5 but
+		 * is located at offset 0x40 instead of 0x60 for some reason.
+		 */
+		ch->ioctrl = cmt->mapbase + 0x40;
+		break;
+	case SH_CMT_48BIT_GEN2:
+		ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
+		ch->ioctrl = ch->iostart + 0x10;
+		break;
 	}
 
 	if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
@@ -900,12 +893,7 @@ static int sh_cmt_setup_channel(struct s
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
 
-	if (cmt->legacy) {
-		ch->timer_bit = ch->hwidx;
-	} else {
-		ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2
-			      ? 0 : ch->hwidx;
-	}
+	ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx;
 
 	ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
 			      clockevent, clocksource);
@@ -938,75 +926,65 @@ static int sh_cmt_map_memory(struct sh_c
 	return 0;
 }
 
-static int sh_cmt_map_memory_legacy(struct sh_cmt_device *cmt)
-{
-	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
-	struct resource *res, *res2;
-
-	/* map memory, let mapbase_ch point to our channel */
-	res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
-		return -ENXIO;
-	}
-
-	cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res));
-	if (cmt->mapbase_ch == NULL) {
-		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
-		return -ENXIO;
-	}
-
-	/* optional resource for the shared timer start/stop register */
-	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
-
-	/* map second resource for CMSTR */
-	cmt->mapbase = ioremap_nocache(res2 ? res2->start :
-				       res->start - cfg->channel_offset,
-				       res2 ? resource_size(res2) : 2);
-	if (cmt->mapbase == NULL) {
-		dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
-		iounmap(cmt->mapbase_ch);
-		return -ENXIO;
-	}
-
-	/* identify the model based on the resources */
-	if (resource_size(res) == 6)
-		cmt->info = &sh_cmt_info[SH_CMT_16BIT];
-	else if (res2 && (resource_size(res2) == 4))
-		cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
-	else
-		cmt->info = &sh_cmt_info[SH_CMT_32BIT];
+static const struct platform_device_id sh_cmt_id_table[] = {
+	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
+	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
+	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
+	{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
+	{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
 
-	return 0;
-}
+static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
+	{ .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] },
+	{ .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] },
+	{ .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+	{ .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
 
-static void sh_cmt_unmap_memory(struct sh_cmt_device *cmt)
+static int sh_cmt_parse_dt(struct sh_cmt_device *cmt)
 {
-	iounmap(cmt->mapbase);
-	if (cmt->mapbase_ch)
-		iounmap(cmt->mapbase_ch);
+	struct device_node *np = cmt->pdev->dev.of_node;
+
+	return of_property_read_u32(np, "renesas,channels-mask",
+				    &cmt->hw_channels);
 }
 
 static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	const struct platform_device_id *id = pdev->id_entry;
-	unsigned int hw_channels;
+	unsigned int mask;
+	unsigned int i;
 	int ret;
 
 	memset(cmt, 0, sizeof(*cmt));
 	cmt->pdev = pdev;
+	raw_spin_lock_init(&cmt->lock);
 
-	if (!cfg) {
+	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+		const struct of_device_id *id;
+
+		id = of_match_node(sh_cmt_of_table, pdev->dev.of_node);
+		cmt->info = id->data;
+
+		ret = sh_cmt_parse_dt(cmt);
+		if (ret < 0)
+			return ret;
+	} else if (pdev->dev.platform_data) {
+		struct sh_timer_config *cfg = pdev->dev.platform_data;
+		const struct platform_device_id *id = pdev->id_entry;
+
+		cmt->info = (const struct sh_cmt_info *)id->driver_data;
+		cmt->hw_channels = cfg->channels_mask;
+	} else {
 		dev_err(&cmt->pdev->dev, "missing platform data\n");
 		return -ENXIO;
 	}
 
-	cmt->info = (const struct sh_cmt_info *)id->driver_data;
-	cmt->legacy = cmt->info ? false : true;
-
 	/* Get hold of clock. */
-	cmt->clk = clk_get(&cmt->pdev->dev, cmt->legacy ? "cmt_fck" : "fck");
+	cmt->clk = clk_get(&cmt->pdev->dev, "fck");
 	if (IS_ERR(cmt->clk)) {
 		dev_err(&cmt->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(cmt->clk);
@@ -1016,28 +994,13 @@ static int sh_cmt_setup(struct sh_cmt_de
 	if (ret < 0)
 		goto err_clk_put;
 
-	/*
-	 * Map the memory resource(s). We need to support both the legacy
-	 * platform device configuration (with one device per channel) and the
-	 * new version (with multiple channels per device).
-	 */
-	if (cmt->legacy)
-		ret = sh_cmt_map_memory_legacy(cmt);
-	else
-		ret = sh_cmt_map_memory(cmt);
-
+	/* Map the memory resource(s). */
+	ret = sh_cmt_map_memory(cmt);
 	if (ret < 0)
 		goto err_clk_unprepare;
 
 	/* Allocate and setup the channels. */
-	if (cmt->legacy) {
-		cmt->num_channels = 1;
-		hw_channels = 0;
-	} else {
-		cmt->num_channels = hweight8(cfg->channels_mask);
-		hw_channels = cfg->channels_mask;
-	}
-
+	cmt->num_channels = hweight8(cmt->hw_channels);
 	cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
 				GFP_KERNEL);
 	if (cmt->channels == NULL) {
@@ -1045,35 +1008,21 @@ static int sh_cmt_setup(struct sh_cmt_de
 		goto err_unmap;
 	}
 
-	if (cmt->legacy) {
-		ret = sh_cmt_setup_channel(&cmt->channels[0],
-					   cfg->timer_bit, cfg->timer_bit,
-					   cfg->clockevent_rating != 0,
-					   cfg->clocksource_rating != 0, cmt);
+	/*
+	 * Use the first channel as a clock event device and the second channel
+	 * as a clock source. If only one channel is available use it for both.
+	 */
+	for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
+		unsigned int hwidx = ffs(mask) - 1;
+		bool clocksource = i == 1 || cmt->num_channels == 1;
+		bool clockevent = i == 0;
+
+		ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
+					   clockevent, clocksource, cmt);
 		if (ret < 0)
 			goto err_unmap;
-	} else {
-		unsigned int mask = hw_channels;
-		unsigned int i;
-
-		/*
-		 * Use the first channel as a clock event device and the second
-		 * channel as a clock source. If only one channel is available
-		 * use it for both.
-		 */
-		for (i = 0; i < cmt->num_channels; ++i) {
-			unsigned int hwidx = ffs(mask) - 1;
-			bool clocksource = i == 1 || cmt->num_channels == 1;
-			bool clockevent = i == 0;
 
-			ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
-						   clockevent, clocksource,
-						   cmt);
-			if (ret < 0)
-				goto err_unmap;
-
-			mask &= ~(1 << hwidx);
-		}
+		mask &= ~(1 << hwidx);
 	}
 
 	platform_set_drvdata(pdev, cmt);
@@ -1082,7 +1031,7 @@ static int sh_cmt_setup(struct sh_cmt_de
 
 err_unmap:
 	kfree(cmt->channels);
-	sh_cmt_unmap_memory(cmt);
+	iounmap(cmt->mapbase);
 err_clk_unprepare:
 	clk_unprepare(cmt->clk);
 err_clk_put:
@@ -1132,22 +1081,12 @@ static int sh_cmt_remove(struct platform
 	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
-static const struct platform_device_id sh_cmt_id_table[] = {
-	{ "sh_cmt", 0 },
-	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
-	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
-	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
-	{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
-	{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
-	{ }
-};
-MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
-
 static struct platform_driver sh_cmt_device_driver = {
 	.probe		= sh_cmt_probe,
 	.remove		= sh_cmt_remove,
 	.driver		= {
 		.name	= "sh_cmt",
+		.of_match_table = of_match_ptr(sh_cmt_of_table),
 	},
 	.id_table	= sh_cmt_id_table,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/sh_mtu2.c linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_mtu2.c
--- linux-libre-3.16-gnu/drivers/clocksource/sh_mtu2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_mtu2.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -37,7 +38,6 @@ struct sh_mtu2_channel {
 	unsigned int index;
 
 	void __iomem *base;
-	int irq;
 
 	struct clock_event_device ced;
 };
@@ -48,15 +48,14 @@ struct sh_mtu2_device {
 	void __iomem *mapbase;
 	struct clk *clk;
 
+	raw_spinlock_t lock; /* Protect the shared registers */
+
 	struct sh_mtu2_channel *channels;
 	unsigned int num_channels;
 
-	bool legacy;
 	bool has_clockevent;
 };
 
-static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
-
 #define TSTR -1 /* shared register */
 #define TCR  0 /* channel register */
 #define TMDR 1 /* channel register */
@@ -162,12 +161,8 @@ static inline unsigned long sh_mtu2_read
 {
 	unsigned long offs;
 
-	if (reg_nr == TSTR) {
-		if (ch->mtu->legacy)
-			return ioread8(ch->mtu->mapbase);
-		else
-			return ioread8(ch->mtu->mapbase + 0x280);
-	}
+	if (reg_nr == TSTR)
+		return ioread8(ch->mtu->mapbase + 0x280);
 
 	offs = mtu2_reg_offs[reg_nr];
 
@@ -182,12 +177,8 @@ static inline void sh_mtu2_write(struct
 {
 	unsigned long offs;
 
-	if (reg_nr == TSTR) {
-		if (ch->mtu->legacy)
-			return iowrite8(value, ch->mtu->mapbase);
-		else
-			return iowrite8(value, ch->mtu->mapbase + 0x280);
-	}
+	if (reg_nr == TSTR)
+		return iowrite8(value, ch->mtu->mapbase + 0x280);
 
 	offs = mtu2_reg_offs[reg_nr];
 
@@ -202,7 +193,7 @@ static void sh_mtu2_start_stop_ch(struct
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
-	raw_spin_lock_irqsave(&sh_mtu2_lock, flags);
+	raw_spin_lock_irqsave(&ch->mtu->lock, flags);
 	value = sh_mtu2_read(ch, TSTR);
 
 	if (start)
@@ -211,7 +202,7 @@ static void sh_mtu2_start_stop_ch(struct
 		value &= ~(1 << ch->index);
 
 	sh_mtu2_write(ch, TSTR, value);
-	raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags);
+	raw_spin_unlock_irqrestore(&ch->mtu->lock, flags);
 }
 
 static int sh_mtu2_enable(struct sh_mtu2_channel *ch)
@@ -331,7 +322,6 @@ static void sh_mtu2_register_clockevent(
 					const char *name)
 {
 	struct clock_event_device *ced = &ch->ced;
-	int ret;
 
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
@@ -344,24 +334,12 @@ static void sh_mtu2_register_clockevent(
 	dev_info(&ch->mtu->pdev->dev, "ch%u: used for clock events\n",
 		 ch->index);
 	clockevents_register_device(ced);
-
-	ret = request_irq(ch->irq, sh_mtu2_interrupt,
-			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&ch->mtu->pdev->dev), ch);
-	if (ret) {
-		dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n",
-			ch->index, ch->irq);
-		return;
-	}
 }
 
-static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name,
-			    bool clockevent)
+static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name)
 {
-	if (clockevent) {
-		ch->mtu->has_clockevent = true;
-		sh_mtu2_register_clockevent(ch, name);
-	}
+	ch->mtu->has_clockevent = true;
+	sh_mtu2_register_clockevent(ch, name);
 
 	return 0;
 }
@@ -372,40 +350,32 @@ static int sh_mtu2_setup_channel(struct
 	static const unsigned int channel_offsets[] = {
 		0x300, 0x380, 0x000,
 	};
-	bool clockevent;
+	char name[6];
+	int irq;
+	int ret;
 
 	ch->mtu = mtu;
 
-	if (mtu->legacy) {
-		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
-
-		clockevent = cfg->clockevent_rating != 0;
-
-		ch->irq = platform_get_irq(mtu->pdev, 0);
-		ch->base = mtu->mapbase - cfg->channel_offset;
-		ch->index = cfg->timer_bit;
-	} else {
-		char name[6];
-
-		clockevent = true;
-
-		sprintf(name, "tgi%ua", index);
-		ch->irq = platform_get_irq_byname(mtu->pdev, name);
-		ch->base = mtu->mapbase + channel_offsets[index];
-		ch->index = index;
-	}
-
-	if (ch->irq < 0) {
+	sprintf(name, "tgi%ua", index);
+	irq = platform_get_irq_byname(mtu->pdev, name);
+	if (irq < 0) {
 		/* Skip channels with no declared interrupt. */
-		if (!mtu->legacy)
-			return 0;
+		return 0;
+	}
 
-		dev_err(&mtu->pdev->dev, "ch%u: failed to get irq\n",
-			ch->index);
-		return ch->irq;
+	ret = request_irq(irq, sh_mtu2_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&ch->mtu->pdev->dev), ch);
+	if (ret) {
+		dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n",
+			index, irq);
+		return ret;
 	}
 
-	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev), clockevent);
+	ch->base = mtu->mapbase + channel_offsets[index];
+	ch->index = index;
+
+	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev));
 }
 
 static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu)
@@ -422,46 +392,21 @@ static int sh_mtu2_map_memory(struct sh_
 	if (mtu->mapbase == NULL)
 		return -ENXIO;
 
-	/*
-	 * In legacy platform device configuration (with one device per channel)
-	 * the resource points to the channel base address.
-	 */
-	if (mtu->legacy) {
-		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
-		mtu->mapbase += cfg->channel_offset;
-	}
-
 	return 0;
 }
 
-static void sh_mtu2_unmap_memory(struct sh_mtu2_device *mtu)
-{
-	if (mtu->legacy) {
-		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
-		mtu->mapbase -= cfg->channel_offset;
-	}
-
-	iounmap(mtu->mapbase);
-}
-
 static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 			 struct platform_device *pdev)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	const struct platform_device_id *id = pdev->id_entry;
 	unsigned int i;
 	int ret;
 
 	mtu->pdev = pdev;
-	mtu->legacy = id->driver_data;
 
-	if (mtu->legacy && !cfg) {
-		dev_err(&mtu->pdev->dev, "missing platform data\n");
-		return -ENXIO;
-	}
+	raw_spin_lock_init(&mtu->lock);
 
 	/* Get hold of clock. */
-	mtu->clk = clk_get(&mtu->pdev->dev, mtu->legacy ? "mtu2_fck" : "fck");
+	mtu->clk = clk_get(&mtu->pdev->dev, "fck");
 	if (IS_ERR(mtu->clk)) {
 		dev_err(&mtu->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(mtu->clk);
@@ -479,10 +424,7 @@ static int sh_mtu2_setup(struct sh_mtu2_
 	}
 
 	/* Allocate and setup the channels. */
-	if (mtu->legacy)
-		mtu->num_channels = 1;
-	else
-		mtu->num_channels = 3;
+	mtu->num_channels = 3;
 
 	mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels,
 				GFP_KERNEL);
@@ -491,16 +433,10 @@ static int sh_mtu2_setup(struct sh_mtu2_
 		goto err_unmap;
 	}
 
-	if (mtu->legacy) {
-		ret = sh_mtu2_setup_channel(&mtu->channels[0], 0, mtu);
+	for (i = 0; i < mtu->num_channels; ++i) {
+		ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu);
 		if (ret < 0)
 			goto err_unmap;
-	} else {
-		for (i = 0; i < mtu->num_channels; ++i) {
-			ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu);
-			if (ret < 0)
-				goto err_unmap;
-		}
 	}
 
 	platform_set_drvdata(pdev, mtu);
@@ -509,7 +445,7 @@ static int sh_mtu2_setup(struct sh_mtu2_
 
 err_unmap:
 	kfree(mtu->channels);
-	sh_mtu2_unmap_memory(mtu);
+	iounmap(mtu->mapbase);
 err_clk_unprepare:
 	clk_unprepare(mtu->clk);
 err_clk_put:
@@ -560,17 +496,23 @@ static int sh_mtu2_remove(struct platfor
 }
 
 static const struct platform_device_id sh_mtu2_id_table[] = {
-	{ "sh_mtu2", 1 },
 	{ "sh-mtu2", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, sh_mtu2_id_table);
 
+static const struct of_device_id sh_mtu2_of_table[] __maybe_unused = {
+	{ .compatible = "renesas,mtu2" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh_mtu2_of_table);
+
 static struct platform_driver sh_mtu2_device_driver = {
 	.probe		= sh_mtu2_probe,
 	.remove		= sh_mtu2_remove,
 	.driver		= {
 		.name	= "sh_mtu2",
+		.of_match_table = of_match_ptr(sh_mtu2_of_table),
 	},
 	.id_table	= sh_mtu2_id_table,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/sh_tmu.c linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_tmu.c
--- linux-libre-3.16-gnu/drivers/clocksource/sh_tmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/sh_tmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -32,7 +33,6 @@
 #include <linux/spinlock.h>
 
 enum sh_tmu_model {
-	SH_TMU_LEGACY,
 	SH_TMU,
 	SH_TMU_SH3,
 };
@@ -62,6 +62,8 @@ struct sh_tmu_device {
 
 	enum sh_tmu_model model;
 
+	raw_spinlock_t lock; /* Protect the shared start/stop register */
+
 	struct sh_tmu_channel *channels;
 	unsigned int num_channels;
 
@@ -69,8 +71,6 @@ struct sh_tmu_device {
 	bool has_clocksource;
 };
 
-static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
-
 #define TSTR -1 /* shared register */
 #define TCOR  0 /* channel register */
 #define TCNT 1 /* channel register */
@@ -91,8 +91,6 @@ static inline unsigned long sh_tmu_read(
 
 	if (reg_nr == TSTR) {
 		switch (ch->tmu->model) {
-		case SH_TMU_LEGACY:
-			return ioread8(ch->tmu->mapbase);
 		case SH_TMU_SH3:
 			return ioread8(ch->tmu->mapbase + 2);
 		case SH_TMU:
@@ -115,8 +113,6 @@ static inline void sh_tmu_write(struct s
 
 	if (reg_nr == TSTR) {
 		switch (ch->tmu->model) {
-		case SH_TMU_LEGACY:
-			return iowrite8(value, ch->tmu->mapbase);
 		case SH_TMU_SH3:
 			return iowrite8(value, ch->tmu->mapbase + 2);
 		case SH_TMU:
@@ -137,7 +133,7 @@ static void sh_tmu_start_stop_ch(struct
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
-	raw_spin_lock_irqsave(&sh_tmu_lock, flags);
+	raw_spin_lock_irqsave(&ch->tmu->lock, flags);
 	value = sh_tmu_read(ch, TSTR);
 
 	if (start)
@@ -146,7 +142,7 @@ static void sh_tmu_start_stop_ch(struct
 		value &= ~(1 << ch->index);
 
 	sh_tmu_write(ch, TSTR, value);
-	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
+	raw_spin_unlock_irqrestore(&ch->tmu->lock, flags);
 }
 
 static int __sh_tmu_enable(struct sh_tmu_channel *ch)
@@ -476,27 +472,12 @@ static int sh_tmu_channel_setup(struct s
 		return 0;
 
 	ch->tmu = tmu;
+	ch->index = index;
 
-	if (tmu->model == SH_TMU_LEGACY) {
-		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
-
-		/*
-		 * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps
-		 * channel registers blocks at base + 2 + 12 * index, while all
-		 * other variants map them at base + 4 + 12 * index. We can
-		 * compute the index by just dividing by 12, the 2 bytes or 4
-		 * bytes offset being hidden by the integer division.
-		 */
-		ch->index = cfg->channel_offset / 12;
-		ch->base = tmu->mapbase + cfg->channel_offset;
-	} else {
-		ch->index = index;
-
-		if (tmu->model == SH_TMU_SH3)
-			ch->base = tmu->mapbase + 4 + ch->index * 12;
-		else
-			ch->base = tmu->mapbase + 8 + ch->index * 12;
-	}
+	if (tmu->model == SH_TMU_SH3)
+		ch->base = tmu->mapbase + 4 + ch->index * 12;
+	else
+		ch->base = tmu->mapbase + 8 + ch->index * 12;
 
 	ch->irq = platform_get_irq(tmu->pdev, index);
 	if (ch->irq < 0) {
@@ -526,46 +507,53 @@ static int sh_tmu_map_memory(struct sh_t
 	if (tmu->mapbase == NULL)
 		return -ENXIO;
 
-	/*
-	 * In legacy platform device configuration (with one device per channel)
-	 * the resource points to the channel base address.
-	 */
-	if (tmu->model == SH_TMU_LEGACY) {
-		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
-		tmu->mapbase -= cfg->channel_offset;
-	}
-
 	return 0;
 }
 
-static void sh_tmu_unmap_memory(struct sh_tmu_device *tmu)
+static int sh_tmu_parse_dt(struct sh_tmu_device *tmu)
 {
-	if (tmu->model == SH_TMU_LEGACY) {
-		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
-		tmu->mapbase += cfg->channel_offset;
+	struct device_node *np = tmu->pdev->dev.of_node;
+
+	tmu->model = SH_TMU;
+	tmu->num_channels = 3;
+
+	of_property_read_u32(np, "#renesas,channels", &tmu->num_channels);
+
+	if (tmu->num_channels != 2 && tmu->num_channels != 3) {
+		dev_err(&tmu->pdev->dev, "invalid number of channels %u\n",
+			tmu->num_channels);
+		return -EINVAL;
 	}
 
-	iounmap(tmu->mapbase);
+	return 0;
 }
 
 static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	const struct platform_device_id *id = pdev->id_entry;
 	unsigned int i;
 	int ret;
 
-	if (!cfg) {
+	tmu->pdev = pdev;
+
+	raw_spin_lock_init(&tmu->lock);
+
+	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+		ret = sh_tmu_parse_dt(tmu);
+		if (ret < 0)
+			return ret;
+	} else if (pdev->dev.platform_data) {
+		const struct platform_device_id *id = pdev->id_entry;
+		struct sh_timer_config *cfg = pdev->dev.platform_data;
+
+		tmu->model = id->driver_data;
+		tmu->num_channels = hweight8(cfg->channels_mask);
+	} else {
 		dev_err(&tmu->pdev->dev, "missing platform data\n");
 		return -ENXIO;
 	}
 
-	tmu->pdev = pdev;
-	tmu->model = id->driver_data;
-
 	/* Get hold of clock. */
-	tmu->clk = clk_get(&tmu->pdev->dev,
-			   tmu->model == SH_TMU_LEGACY ? "tmu_fck" : "fck");
+	tmu->clk = clk_get(&tmu->pdev->dev, "fck");
 	if (IS_ERR(tmu->clk)) {
 		dev_err(&tmu->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(tmu->clk);
@@ -583,11 +571,6 @@ static int sh_tmu_setup(struct sh_tmu_de
 	}
 
 	/* Allocate and setup the channels. */
-	if (tmu->model == SH_TMU_LEGACY)
-		tmu->num_channels = 1;
-	else
-		tmu->num_channels = hweight8(cfg->channels_mask);
-
 	tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels,
 				GFP_KERNEL);
 	if (tmu->channels == NULL) {
@@ -595,23 +578,15 @@ static int sh_tmu_setup(struct sh_tmu_de
 		goto err_unmap;
 	}
 
-	if (tmu->model == SH_TMU_LEGACY) {
-		ret = sh_tmu_channel_setup(&tmu->channels[0], 0,
-					   cfg->clockevent_rating != 0,
-					   cfg->clocksource_rating != 0, tmu);
+	/*
+	 * Use the first channel as a clock event device and the second channel
+	 * as a clock source.
+	 */
+	for (i = 0; i < tmu->num_channels; ++i) {
+		ret = sh_tmu_channel_setup(&tmu->channels[i], i,
+					   i == 0, i == 1, tmu);
 		if (ret < 0)
 			goto err_unmap;
-	} else {
-		/*
-		 * Use the first channel as a clock event device and the second
-		 * channel as a clock source.
-		 */
-		for (i = 0; i < tmu->num_channels; ++i) {
-			ret = sh_tmu_channel_setup(&tmu->channels[i], i,
-						   i == 0, i == 1, tmu);
-			if (ret < 0)
-				goto err_unmap;
-		}
 	}
 
 	platform_set_drvdata(pdev, tmu);
@@ -620,7 +595,7 @@ static int sh_tmu_setup(struct sh_tmu_de
 
 err_unmap:
 	kfree(tmu->channels);
-	sh_tmu_unmap_memory(tmu);
+	iounmap(tmu->mapbase);
 err_clk_unprepare:
 	clk_unprepare(tmu->clk);
 err_clk_put:
@@ -671,18 +646,24 @@ static int sh_tmu_remove(struct platform
 }
 
 static const struct platform_device_id sh_tmu_id_table[] = {
-	{ "sh_tmu", SH_TMU_LEGACY },
 	{ "sh-tmu", SH_TMU },
 	{ "sh-tmu-sh3", SH_TMU_SH3 },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, sh_tmu_id_table);
 
+static const struct of_device_id sh_tmu_of_table[] __maybe_unused = {
+	{ .compatible = "renesas,tmu" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh_tmu_of_table);
+
 static struct platform_driver sh_tmu_device_driver = {
 	.probe		= sh_tmu_probe,
 	.remove		= sh_tmu_remove,
 	.driver		= {
 		.name	= "sh_tmu",
+		.of_match_table = of_match_ptr(sh_tmu_of_table),
 	},
 	.id_table	= sh_tmu_id_table,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/tegra20_timer.c linux-libre-3.17-rc7-gnu/drivers/clocksource/tegra20_timer.c
--- linux-libre-3.16-gnu/drivers/clocksource/tegra20_timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/tegra20_timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/sched_clock.h>
+#include <linux/delay.h>
 
 #include <asm/mach/time.h>
 #include <asm/smp_twd.h>
@@ -53,6 +54,8 @@ static void __iomem *rtc_base;
 static struct timespec persistent_ts;
 static u64 persistent_ms, last_persistent_ms;
 
+static struct delay_timer tegra_delay_timer;
+
 #define timer_writel(value, reg) \
 	__raw_writel(value, timer_reg_base + (reg))
 #define timer_readl(reg) \
@@ -139,6 +142,11 @@ static void tegra_read_persistent_clock(
 	*ts = *tsp;
 }
 
+static unsigned long tegra_delay_timer_read_counter_long(void)
+{
+	return readl(timer_reg_base + TIMERUS_CNTR_1US);
+}
+
 static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -206,6 +214,11 @@ static void __init tegra20_init_timer(st
 		BUG();
 	}
 
+	tegra_delay_timer.read_current_timer =
+			tegra_delay_timer_read_counter_long;
+	tegra_delay_timer.freq = 1000000;
+	register_current_timer_delay(&tegra_delay_timer);
+
 	ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
 	if (ret) {
 		pr_err("Failed to register timer IRQ: %d\n", ret);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/timer-marco.c linux-libre-3.17-rc7-gnu/drivers/clocksource/timer-marco.c
--- linux-libre-3.16-gnu/drivers/clocksource/timer-marco.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/timer-marco.c	2014-09-28 17:29:07.000000000 -0400
@@ -260,6 +260,9 @@ static void __init sirfsoc_marco_timer_i
 
 	clk = of_clk_get(np, 0);
 	BUG_ON(IS_ERR(clk));
+
+	BUG_ON(clk_prepare_enable(clk));
+
 	rate = clk_get_rate(clk);
 
 	BUG_ON(rate < MARCO_CLOCK_FREQ);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/clocksource/timer-prima2.c linux-libre-3.17-rc7-gnu/drivers/clocksource/timer-prima2.c
--- linux-libre-3.16-gnu/drivers/clocksource/timer-prima2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/clocksource/timer-prima2.c	2014-09-28 17:29:07.000000000 -0400
@@ -200,6 +200,9 @@ static void __init sirfsoc_prima2_timer_
 
 	clk = of_clk_get(np, 0);
 	BUG_ON(IS_ERR(clk));
+
+	BUG_ON(clk_prepare_enable(clk));
+
 	rate = clk_get_rate(clk);
 
 	BUG_ON(rate < PRIMA2_CLOCK_FREQ);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/connector/cn_proc.c linux-libre-3.17-rc7-gnu/drivers/connector/cn_proc.c
--- linux-libre-3.16-gnu/drivers/connector/cn_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/connector/cn_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,7 +69,6 @@ void proc_fork_connector(struct task_str
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
-	struct timespec ts;
 	struct task_struct *parent;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -79,8 +78,7 @@ void proc_fork_connector(struct task_str
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_FORK;
 	rcu_read_lock();
 	parent = rcu_dereference(task->real_parent);
@@ -102,7 +100,6 @@ void proc_exec_connector(struct task_str
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	struct timespec ts;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -112,8 +109,7 @@ void proc_exec_connector(struct task_str
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_EXEC;
 	ev->event_data.exec.process_pid = task->pid;
 	ev->event_data.exec.process_tgid = task->tgid;
@@ -130,7 +126,6 @@ void proc_id_connector(struct task_struc
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
-	struct timespec ts;
 	const struct cred *cred;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -156,8 +151,7 @@ void proc_id_connector(struct task_struc
 	}
 	rcu_read_unlock();
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
@@ -170,7 +164,6 @@ void proc_sid_connector(struct task_stru
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	struct timespec ts;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -180,8 +173,7 @@ void proc_sid_connector(struct task_stru
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_SID;
 	ev->event_data.sid.process_pid = task->pid;
 	ev->event_data.sid.process_tgid = task->tgid;
@@ -197,7 +189,6 @@ void proc_ptrace_connector(struct task_s
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	struct timespec ts;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -207,8 +198,7 @@ void proc_ptrace_connector(struct task_s
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_PTRACE;
 	ev->event_data.ptrace.process_pid  = task->pid;
 	ev->event_data.ptrace.process_tgid = task->tgid;
@@ -232,7 +222,6 @@ void proc_comm_connector(struct task_str
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
-	struct timespec ts;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -242,8 +231,7 @@ void proc_comm_connector(struct task_str
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_COMM;
 	ev->event_data.comm.process_pid  = task->pid;
 	ev->event_data.comm.process_tgid = task->tgid;
@@ -261,7 +249,6 @@ void proc_coredump_connector(struct task
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
-	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -270,8 +257,7 @@ void proc_coredump_connector(struct task
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_COREDUMP;
 	ev->event_data.coredump.process_pid = task->pid;
 	ev->event_data.coredump.process_tgid = task->tgid;
@@ -288,7 +274,6 @@ void proc_exit_connector(struct task_str
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
-	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -297,8 +282,7 @@ void proc_exit_connector(struct task_str
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_EXIT;
 	ev->event_data.exit.process_pid = task->pid;
 	ev->event_data.exit.process_tgid = task->tgid;
@@ -325,7 +309,6 @@ static void cn_proc_ack(int err, int rcv
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
-	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -334,8 +317,7 @@ static void cn_proc_ack(int err, int rcv
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	msg->seq = rcvd_seq;
-	ktime_get_ts(&ts); /* get high res monotonic timestamp */
-	ev->timestamp_ns = timespec_to_ns(&ts);
+	ev->timestamp_ns = ktime_get_ns();
 	ev->cpu = -1;
 	ev->what = PROC_EVENT_NONE;
 	ev->event_data.ack.err = err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/arm_big_little.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/arm_big_little.c
--- linux-libre-3.16-gnu/drivers/cpufreq/arm_big_little.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/arm_big_little.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of_platform.h>
 #include <linux/pm_opp.h>
@@ -593,3 +594,7 @@ void bL_cpufreq_unregister(struct cpufre
 	arm_bL_ops = NULL;
 }
 EXPORT_SYMBOL_GPL(bL_cpufreq_unregister);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/arm_big_little_dt.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/arm_big_little_dt.c
--- linux-libre-3.16-gnu/drivers/cpufreq/arm_big_little_dt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/arm_big_little_dt.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,4 +114,4 @@ module_platform_driver(generic_bL_platdr
 
 MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
 MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct c
 	kfree(policy);
 }
 
-static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
+static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu,
+			     struct device *cpu_dev)
 {
+	int ret;
+
 	if (WARN_ON(cpu == policy->cpu))
-		return;
+		return 0;
+
+	/* Move kobject to the new policy->cpu */
+	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
+	if (ret) {
+		pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
+		return ret;
+	}
 
 	down_write(&policy->rwsem);
 
@@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpu
 
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 			CPUFREQ_UPDATE_POLICY_CPU, policy);
+
+	return 0;
 }
 
 static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
@@ -1153,12 +1165,10 @@ static int __cpufreq_add_dev(struct devi
 	 * the creation of a brand new one. So we need to perform this update
 	 * by invoking update_policy_cpu().
 	 */
-	if (recover_policy && cpu != policy->cpu) {
-		update_policy_cpu(policy, cpu);
-		WARN_ON(kobject_move(&policy->kobj, &dev->kobj));
-	} else {
+	if (recover_policy && cpu != policy->cpu)
+		WARN_ON(update_policy_cpu(policy, cpu, dev));
+	else
 		policy->cpu = cpu;
-	}
 
 	cpumask_copy(policy->cpus, cpumask_of(cpu));
 
@@ -1279,6 +1289,8 @@ err_get_freq:
 		per_cpu(cpufreq_cpu_data, j) = NULL;
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+	up_write(&policy->rwsem);
+
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
 err_set_policy_cpu:
@@ -1309,38 +1321,11 @@ static int cpufreq_add_dev(struct device
 	return __cpufreq_add_dev(dev, sif);
 }
 
-static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
-					   unsigned int old_cpu)
-{
-	struct device *cpu_dev;
-	int ret;
-
-	/* first sibling now owns the new sysfs dir */
-	cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
-
-	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
-	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
-	if (ret) {
-		pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
-
-		down_write(&policy->rwsem);
-		cpumask_set_cpu(old_cpu, policy->cpus);
-		up_write(&policy->rwsem);
-
-		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
-					"cpufreq");
-
-		return -EINVAL;
-	}
-
-	return cpu_dev->id;
-}
-
 static int __cpufreq_remove_dev_prepare(struct device *dev,
 					struct subsys_interface *sif)
 {
 	unsigned int cpu = dev->id, cpus;
-	int new_cpu, ret;
+	int ret;
 	unsigned long flags;
 	struct cpufreq_policy *policy;
 
@@ -1380,14 +1365,23 @@ static int __cpufreq_remove_dev_prepare(
 	if (cpu != policy->cpu) {
 		sysfs_remove_link(&dev->kobj, "cpufreq");
 	} else if (cpus > 1) {
-		new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
-		if (new_cpu >= 0) {
-			update_policy_cpu(policy, new_cpu);
+		/* Nominate new CPU */
+		int new_cpu = cpumask_any_but(policy->cpus, cpu);
+		struct device *cpu_dev = get_cpu_device(new_cpu);
 
-			if (!cpufreq_suspended)
-				pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
-					 __func__, new_cpu, cpu);
+		sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
+		ret = update_policy_cpu(policy, new_cpu, cpu_dev);
+		if (ret) {
+			if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
+					      "cpufreq"))
+				pr_err("%s: Failed to restore kobj link to cpu:%d\n",
+				       __func__, cpu_dev->id);
+			return ret;
 		}
+
+		if (!cpufreq_suspended)
+			pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+				 __func__, new_cpu, cpu);
 	} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
 		cpufreq_driver->stop_cpu(policy);
 	}
@@ -1664,6 +1658,8 @@ void cpufreq_suspend(void)
 	if (!cpufreq_driver)
 		return;
 
+	cpufreq_suspended = true;
+
 	if (!has_target())
 		return;
 
@@ -1678,8 +1674,6 @@ void cpufreq_suspend(void)
 			pr_err("%s: Failed to suspend driver: %p\n", __func__,
 				policy);
 	}
-
-	cpufreq_suspended = true;
 }
 
 /**
@@ -1695,13 +1689,13 @@ void cpufreq_resume(void)
 	if (!cpufreq_driver)
 		return;
 
+	cpufreq_suspended = false;
+
 	if (!has_target())
 		return;
 
 	pr_debug("%s: Resuming Governors\n", __func__);
 
-	cpufreq_suspended = false;
-
 	list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
 		if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
 			pr_err("%s: Failed to resume driver: %p\n", __func__,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/cpufreq-cpu0.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq-cpu0.c
--- linux-libre-3.16-gnu/drivers/cpufreq/cpufreq-cpu0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq-cpu0.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,7 +137,7 @@ static int cpu0_cpufreq_probe(struct pla
 		 * not yet registered, we should try defering probe.
 		 */
 		if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
-			dev_err(cpu_dev, "cpu0 regulator not ready, retry\n");
+			dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
 			ret = -EPROBE_DEFER;
 			goto out_put_node;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-3.16-gnu/drivers/cpufreq/cpufreq_ondemand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq_ondemand.c	2014-09-28 17:29:07.000000000 -0400
@@ -170,21 +170,24 @@ static void od_check_cpu(int cpu, unsign
 		dbs_freq_increase(policy, policy->max);
 	} else {
 		/* Calculate the next frequency proportional to load */
-		unsigned int freq_next;
-		freq_next = load * policy->cpuinfo.max_freq / 100;
+		unsigned int freq_next, min_f, max_f;
+
+		min_f = policy->cpuinfo.min_freq;
+		max_f = policy->cpuinfo.max_freq;
+		freq_next = min_f + load * (max_f - min_f) / 100;
 
 		/* No longer fully busy, reset rate_mult */
 		dbs_info->rate_mult = 1;
 
 		if (!od_tuners->powersave_bias) {
 			__cpufreq_driver_target(policy, freq_next,
-					CPUFREQ_RELATION_L);
+					CPUFREQ_RELATION_C);
 			return;
 		}
 
 		freq_next = od_ops.powersave_bias_target(policy, freq_next,
 					CPUFREQ_RELATION_L);
-		__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
+		__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/cpufreq_opp.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq_opp.c
--- linux-libre-3.16-gnu/drivers/cpufreq/cpufreq_opp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/cpufreq_opp.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct
 		goto out;
 	}
 
-	freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL);
+	freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
 	if (!freq_table) {
 		ret = -ENOMEM;
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/freq_table.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/freq_table.c
--- linux-libre-3.16-gnu/drivers/cpufreq/freq_table.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/freq_table.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,7 +117,7 @@ int cpufreq_frequency_table_target(struc
 		.frequency = 0,
 	};
 	struct cpufreq_frequency_table *pos;
-	unsigned int freq, i = 0;
+	unsigned int freq, diff, i = 0;
 
 	pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
 					target_freq, relation, policy->cpu);
@@ -127,6 +127,7 @@ int cpufreq_frequency_table_target(struc
 		suboptimal.frequency = ~0;
 		break;
 	case CPUFREQ_RELATION_L:
+	case CPUFREQ_RELATION_C:
 		optimal.frequency = ~0;
 		break;
 	}
@@ -168,6 +169,15 @@ int cpufreq_frequency_table_target(struc
 				}
 			}
 			break;
+		case CPUFREQ_RELATION_C:
+			diff = abs(freq - target_freq);
+			if (diff < optimal.frequency ||
+			    (diff == optimal.frequency &&
+			     freq > table[optimal.driver_data].frequency)) {
+				optimal.frequency = diff;
+				optimal.driver_data = i;
+			}
+			break;
 		}
 	}
 	if (optimal.driver_data > i) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/imx6q-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/imx6q-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/imx6q-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/imx6q-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,10 +66,12 @@ static int imx6q_set_target(struct cpufr
 
 	/* scaling up?  scale voltage before frequency */
 	if (new_freq > old_freq) {
-		ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
-		if (ret) {
-			dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
-			return ret;
+		if (!IS_ERR(pu_reg)) {
+			ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
+			if (ret) {
+				dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
+				return ret;
+			}
 		}
 		ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
 		if (ret) {
@@ -121,10 +123,12 @@ static int imx6q_set_target(struct cpufr
 			dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
 			ret = 0;
 		}
-		ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
-		if (ret) {
-			dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
-			ret = 0;
+		if (!IS_ERR(pu_reg)) {
+			ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
+			if (ret) {
+				dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
+				ret = 0;
+			}
 		}
 	}
 
@@ -182,9 +186,9 @@ static int imx6q_cpufreq_probe(struct pl
 	}
 
 	arm_reg = regulator_get(cpu_dev, "arm");
-	pu_reg = regulator_get(cpu_dev, "pu");
+	pu_reg = regulator_get_optional(cpu_dev, "pu");
 	soc_reg = regulator_get(cpu_dev, "soc");
-	if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
+	if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
 		dev_err(cpu_dev, "failed to get regulators\n");
 		ret = -ENOENT;
 		goto put_reg;
@@ -268,9 +272,11 @@ soc_opp_out:
 	ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
 	if (ret > 0)
 		transition_latency += ret * 1000;
-	ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
-	if (ret > 0)
-		transition_latency += ret * 1000;
+	if (!IS_ERR(pu_reg)) {
+		ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
+		if (ret > 0)
+			transition_latency += ret * 1000;
+	}
 
 	/*
 	 * OPP is maintained in order of increasing frequency, and
@@ -327,7 +333,8 @@ static int imx6q_cpufreq_remove(struct p
 	cpufreq_unregister_driver(&imx6q_cpufreq_driver);
 	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 	regulator_put(arm_reg);
-	regulator_put(pu_reg);
+	if (!IS_ERR(pu_reg))
+		regulator_put(pu_reg);
 	regulator_put(soc_reg);
 	clk_put(arm_clk);
 	clk_put(pll1_sys_clk);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/integrator-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/integrator-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/integrator-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/integrator-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,7 +92,7 @@ static int integrator_set_target(struct
 	 * Bind to the specified CPU.  When this call returns,
 	 * we should be running on the right CPU.
 	 */
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* get current setting */
@@ -118,7 +118,7 @@ static int integrator_set_target(struct
 	freqs.new = icst_hz(&cclk_params, vco) / 1000;
 
 	if (freqs.old == freqs.new) {
-		set_cpus_allowed(current, cpus_allowed);
+		set_cpus_allowed_ptr(current, &cpus_allowed);
 		return 0;
 	}
 
@@ -141,7 +141,7 @@ static int integrator_set_target(struct
 	/*
 	 * Restore the CPUs allowed mask.
 	 */
-	set_cpus_allowed(current, cpus_allowed);
+	set_cpus_allowed_ptr(current, &cpus_allowed);
 
 	cpufreq_freq_transition_end(policy, &freqs, 0);
 
@@ -157,7 +157,7 @@ static unsigned int integrator_get(unsig
 
 	cpus_allowed = current->cpus_allowed;
 
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* detect memory etc. */
@@ -173,7 +173,7 @@ static unsigned int integrator_get(unsig
 
 	current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
 
-	set_cpus_allowed(current, cpus_allowed);
+	set_cpus_allowed_ptr(current, &cpus_allowed);
 
 	return current_freq;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/intel_pstate.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/intel_pstate.c
--- linux-libre-3.16-gnu/drivers/cpufreq/intel_pstate.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/intel_pstate.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,6 @@
 #define BYT_TURBO_RATIOS	0x66c
 #define BYT_TURBO_VIDS		0x66d
 
-
 #define FRAC_BITS 8
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
@@ -50,7 +49,7 @@ static inline int32_t mul_fp(int32_t x,
 
 static inline int32_t div_fp(int32_t x, int32_t y)
 {
-	return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
+	return div_s64((int64_t)x << FRAC_BITS, y);
 }
 
 struct sample {
@@ -148,7 +147,7 @@ static struct perf_limits limits = {
 };
 
 static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
-			int deadband, int integral) {
+			     int deadband, int integral) {
 	pid->setpoint = setpoint;
 	pid->deadband  = deadband;
 	pid->integral  = int_tofp(integral);
@@ -167,7 +166,6 @@ static inline void pid_i_gain_set(struct
 
 static inline void pid_d_gain_set(struct _pid *pid, int percent)
 {
-
 	pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
 }
 
@@ -207,16 +205,13 @@ static inline void intel_pstate_busy_pid
 	pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
 	pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
 
-	pid_reset(&cpu->pid,
-		pid_params.setpoint,
-		100,
-		pid_params.deadband,
-		0);
+	pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0);
 }
 
 static inline void intel_pstate_reset_all_pid(void)
 {
 	unsigned int cpu;
+
 	for_each_online_cpu(cpu) {
 		if (all_cpu_data[cpu])
 			intel_pstate_busy_pid_reset(all_cpu_data[cpu]);
@@ -230,13 +225,13 @@ static int pid_param_set(void *data, u64
 	intel_pstate_reset_all_pid();
 	return 0;
 }
+
 static int pid_param_get(void *data, u64 *val)
 {
 	*val = *(u32 *)data;
 	return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get,
-			pid_param_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n");
 
 struct pid_param {
 	char *name;
@@ -253,9 +248,9 @@ static struct pid_param pid_files[] = {
 	{NULL, NULL}
 };
 
-static struct dentry *debugfs_parent;
-static void intel_pstate_debug_expose_params(void)
+static void __init intel_pstate_debug_expose_params(void)
 {
+	struct dentry *debugfs_parent;
 	int i = 0;
 
 	debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
@@ -263,8 +258,8 @@ static void intel_pstate_debug_expose_pa
 		return;
 	while (pid_files[i].name) {
 		debugfs_create_file(pid_files[i].name, 0660,
-				debugfs_parent, pid_files[i].value,
-				&fops_pid_param);
+				    debugfs_parent, pid_files[i].value,
+				    &fops_pid_param);
 		i++;
 	}
 }
@@ -280,10 +275,11 @@ static void intel_pstate_debug_expose_pa
 	}
 
 static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
-				const char *buf, size_t count)
+			      const char *buf, size_t count)
 {
 	unsigned int input;
 	int ret;
+
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
@@ -296,10 +292,11 @@ static ssize_t store_no_turbo(struct kob
 }
 
 static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
-				const char *buf, size_t count)
+				  const char *buf, size_t count)
 {
 	unsigned int input;
 	int ret;
+
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
@@ -307,14 +304,16 @@ static ssize_t store_max_perf_pct(struct
 	limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
 	limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
 	limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
+
 	return count;
 }
 
 static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
-				const char *buf, size_t count)
+				  const char *buf, size_t count)
 {
 	unsigned int input;
 	int ret;
+
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
@@ -342,17 +341,16 @@ static struct attribute *intel_pstate_at
 static struct attribute_group intel_pstate_attr_group = {
 	.attrs = intel_pstate_attributes,
 };
-static struct kobject *intel_pstate_kobject;
 
-static void intel_pstate_sysfs_expose_params(void)
+static void __init intel_pstate_sysfs_expose_params(void)
 {
+	struct kobject *intel_pstate_kobject;
 	int rc;
 
 	intel_pstate_kobject = kobject_create_and_add("intel_pstate",
 						&cpu_subsys.dev_root->kobj);
 	BUG_ON(!intel_pstate_kobject);
-	rc = sysfs_create_group(intel_pstate_kobject,
-				&intel_pstate_attr_group);
+	rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
 	BUG_ON(rc);
 }
 
@@ -360,6 +358,7 @@ static void intel_pstate_sysfs_expose_pa
 static int byt_get_min_pstate(void)
 {
 	u64 value;
+
 	rdmsrl(BYT_RATIOS, value);
 	return (value >> 8) & 0x7F;
 }
@@ -367,6 +366,7 @@ static int byt_get_min_pstate(void)
 static int byt_get_max_pstate(void)
 {
 	u64 value;
+
 	rdmsrl(BYT_RATIOS, value);
 	return (value >> 16) & 0x7F;
 }
@@ -374,6 +374,7 @@ static int byt_get_max_pstate(void)
 static int byt_get_turbo_pstate(void)
 {
 	u64 value;
+
 	rdmsrl(BYT_TURBO_RATIOS, value);
 	return value & 0x7F;
 }
@@ -407,7 +408,6 @@ static void byt_get_vid(struct cpudata *
 {
 	u64 value;
 
-
 	rdmsrl(BYT_VIDS, value);
 	cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
 	cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
@@ -420,10 +420,10 @@ static void byt_get_vid(struct cpudata *
 	cpudata->vid.turbo = value & 0x7f;
 }
 
-
 static int core_get_min_pstate(void)
 {
 	u64 value;
+
 	rdmsrl(MSR_PLATFORM_INFO, value);
 	return (value >> 40) & 0xFF;
 }
@@ -431,6 +431,7 @@ static int core_get_min_pstate(void)
 static int core_get_max_pstate(void)
 {
 	u64 value;
+
 	rdmsrl(MSR_PLATFORM_INFO, value);
 	return (value >> 8) & 0xFF;
 }
@@ -439,9 +440,10 @@ static int core_get_turbo_pstate(void)
 {
 	u64 value;
 	int nont, ret;
+
 	rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
 	nont = core_get_max_pstate();
-	ret = ((value) & 255);
+	ret = (value) & 255;
 	if (ret <= nont)
 		ret = nont;
 	return ret;
@@ -493,12 +495,12 @@ static struct cpu_defaults byt_params =
 	},
 };
 
-
 static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
 {
 	int max_perf = cpu->pstate.turbo_pstate;
 	int max_perf_adj;
 	int min_perf;
+
 	if (limits.no_turbo)
 		max_perf = cpu->pstate.max_pstate;
 
@@ -507,8 +509,7 @@ static void intel_pstate_get_min_max(str
 			cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
 	min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
-	*min = clamp_t(int, min_perf,
-			cpu->pstate.min_pstate, max_perf);
+	*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
 }
 
 static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
@@ -529,21 +530,6 @@ static void intel_pstate_set_pstate(stru
 	pstate_funcs.set(cpu, pstate);
 }
 
-static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
-{
-	int target;
-	target = cpu->pstate.current_pstate + steps;
-
-	intel_pstate_set_pstate(cpu, target);
-}
-
-static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps)
-{
-	int target;
-	target = cpu->pstate.current_pstate - steps;
-	intel_pstate_set_pstate(cpu, target);
-}
-
 static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 {
 	cpu->pstate.min_pstate = pstate_funcs.get_min();
@@ -559,13 +545,9 @@ static inline void intel_pstate_calc_bus
 {
 	struct sample *sample = &cpu->sample;
 	int64_t core_pct;
-	int32_t rem;
 
 	core_pct = int_tofp(sample->aperf) * int_tofp(100);
-	core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
-
-	if ((rem << 1) >= int_tofp(sample->mperf))
-		core_pct += 1;
+	core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
 
 	sample->freq = fp_toint(
 		mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
@@ -576,12 +558,12 @@ static inline void intel_pstate_calc_bus
 static inline void intel_pstate_sample(struct cpudata *cpu)
 {
 	u64 aperf, mperf;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	rdmsrl(MSR_IA32_APERF, aperf);
 	rdmsrl(MSR_IA32_MPERF, mperf);
-
-	aperf = aperf >> FRAC_BITS;
-	mperf = mperf >> FRAC_BITS;
+	local_irq_restore(flags);
 
 	cpu->last_sample_time = cpu->sample.time;
 	cpu->sample.time = ktime_get();
@@ -598,10 +580,9 @@ static inline void intel_pstate_sample(s
 
 static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 {
-	int sample_time, delay;
+	int delay;
 
-	sample_time = pid_params.sample_rate_ms;
-	delay = msecs_to_jiffies(sample_time);
+	delay = msecs_to_jiffies(pid_params.sample_rate_ms);
 	mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
@@ -616,12 +597,12 @@ static inline int32_t intel_pstate_get_s
 	current_pstate = int_tofp(cpu->pstate.current_pstate);
 	core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 
-	sample_time = (pid_params.sample_rate_ms  * USEC_PER_MSEC);
+	sample_time = pid_params.sample_rate_ms  * USEC_PER_MSEC;
 	duration_us = (u32) ktime_us_delta(cpu->sample.time,
-					cpu->last_sample_time);
+					   cpu->last_sample_time);
 	if (duration_us > sample_time * 3) {
 		sample_ratio = div_fp(int_tofp(sample_time),
-				int_tofp(duration_us));
+				      int_tofp(duration_us));
 		core_busy = mul_fp(core_busy, sample_ratio);
 	}
 
@@ -632,20 +613,15 @@ static inline void intel_pstate_adjust_b
 {
 	int32_t busy_scaled;
 	struct _pid *pid;
-	signed int ctl = 0;
-	int steps;
+	signed int ctl;
 
 	pid = &cpu->pid;
 	busy_scaled = intel_pstate_get_scaled_busy(cpu);
 
 	ctl = pid_calc(pid, busy_scaled);
 
-	steps = abs(ctl);
-
-	if (ctl < 0)
-		intel_pstate_pstate_increase(cpu, steps);
-	else
-		intel_pstate_pstate_decrease(cpu, steps);
+	/* Negative values of ctl increase the pstate and vice versa */
+	intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl);
 }
 
 static void intel_pstate_timer_func(unsigned long __data)
@@ -684,6 +660,7 @@ static const struct x86_cpu_id intel_pst
 	ICPU(0x3f, core_params),
 	ICPU(0x45, core_params),
 	ICPU(0x46, core_params),
+	ICPU(0x4c, byt_params),
 	ICPU(0x4f, core_params),
 	ICPU(0x56, core_params),
 	{}
@@ -705,15 +682,14 @@ static int intel_pstate_init_cpu(unsigne
 
 	init_timer_deferrable(&cpu->timer);
 	cpu->timer.function = intel_pstate_timer_func;
-	cpu->timer.data =
-		(unsigned long)cpu;
+	cpu->timer.data = (unsigned long)cpu;
 	cpu->timer.expires = jiffies + HZ/100;
 	intel_pstate_busy_pid_reset(cpu);
 	intel_pstate_sample(cpu);
 
 	add_timer_on(&cpu->timer, cpunum);
 
-	pr_info("Intel pstate controlling: cpu %d\n", cpunum);
+	pr_debug("Intel pstate controlling: cpu %d\n", cpunum);
 
 	return 0;
 }
@@ -732,10 +708,6 @@ static unsigned int intel_pstate_get(uns
 
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
-	struct cpudata *cpu;
-
-	cpu = all_cpu_data[policy->cpu];
-
 	if (!policy->cpuinfo.max_freq)
 		return -ENODEV;
 
@@ -751,7 +723,7 @@ static int intel_pstate_set_policy(struc
 	limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
 	limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
 
-	limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq;
+	limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
 	limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
 	limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
 	limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
@@ -763,8 +735,8 @@ static int intel_pstate_verify_policy(st
 {
 	cpufreq_verify_within_cpu_limits(policy);
 
-	if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
-		(policy->policy != CPUFREQ_POLICY_PERFORMANCE))
+	if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
+	    policy->policy != CPUFREQ_POLICY_PERFORMANCE)
 		return -EINVAL;
 
 	return 0;
@@ -797,7 +769,7 @@ static int intel_pstate_cpu_init(struct
 
 	rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
 	if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
-		cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
+	    cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
 		limits.turbo_disabled = 1;
 		limits.no_turbo = 1;
 	}
@@ -839,8 +811,8 @@ static int intel_pstate_msrs_not_valid(v
 	rdmsrl(MSR_IA32_MPERF, mperf);
 
 	if (!pstate_funcs.get_max() ||
-		!pstate_funcs.get_min() ||
-		!pstate_funcs.get_turbo())
+	    !pstate_funcs.get_min() ||
+	    !pstate_funcs.get_turbo())
 		return -ENODEV;
 
 	rdmsrl(MSR_IA32_APERF, tmp);
@@ -922,14 +894,14 @@ static bool intel_pstate_platform_pwr_mg
 	struct acpi_table_header hdr;
 	struct hw_vendor_info *v_info;
 
-	if (acpi_disabled
-	    || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
+	if (acpi_disabled ||
+	    ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
 		return false;
 
 	for (v_info = vendor_info; v_info->valid; v_info++) {
-		if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
-		    && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
-		    && intel_pstate_no_acpi_pss())
+		if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) &&
+		    !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
+		    intel_pstate_no_acpi_pss())
 			return true;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/loongson2_cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/loongson2_cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/loongson2_cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/loongson2_cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,9 +148,9 @@ static void loongson2_cpu_wait(void)
 	u32 cpu_freq;
 
 	spin_lock_irqsave(&loongson2_wait_lock, flags);
-	cpu_freq = LOONGSON_CHIPCFG0;
-	LOONGSON_CHIPCFG0 &= ~0x7;	/* Put CPU into wait mode */
-	LOONGSON_CHIPCFG0 = cpu_freq;	/* Restore CPU state */
+	cpu_freq = LOONGSON_CHIPCFG(0);
+	LOONGSON_CHIPCFG(0) &= ~0x7;	/* Put CPU into wait mode */
+	LOONGSON_CHIPCFG(0) = cpu_freq;	/* Restore CPU state */
 	spin_unlock_irqrestore(&loongson2_wait_lock, flags);
 	local_irq_enable();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/pmac64-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/pmac64-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/pmac64-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/pmac64-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -499,8 +499,7 @@ static int __init g5_pm72_cpufreq_init(s
 	}
 
 	/* Lookup the i2c hwclock */
-	for (hwclock = NULL;
-	     (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){
+	for_each_node_by_name(hwclock, "i2c-hwclock") {
 		const char *loc = of_get_property(hwclock,
 				"hwctrl-location", NULL);
 		if (loc == NULL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/powernow-k6.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/powernow-k6.c
--- linux-libre-3.16-gnu/drivers/cpufreq/powernow-k6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/powernow-k6.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,6 +55,7 @@ static const struct {
 	unsigned freq;
 	unsigned mult;
 } usual_frequency_table[] = {
+	{ 350000, 35 },	// 100   * 3.5
 	{ 400000, 40 },	// 100   * 4
 	{ 450000, 45 }, // 100   * 4.5
 	{ 475000, 50 }, //  95   * 5
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/powernv-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/powernv-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/powernv-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/powernv-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 
 #include <asm/cputhreads.h>
+#include <asm/firmware.h>
 #include <asm/reg.h>
 #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */
 
@@ -98,7 +99,11 @@ static int init_powernv_pstates(void)
 		return -ENODEV;
 	}
 
-	WARN_ON(len_ids != len_freqs);
+	if (len_ids != len_freqs) {
+		pr_warn("Entries in ibm,pstate-ids and "
+			"ibm,pstate-frequencies-mhz does not match\n");
+	}
+
 	nr_pstates = min(len_ids, len_freqs) / sizeof(u32);
 	if (!nr_pstates) {
 		pr_warn("No PStates found\n");
@@ -131,7 +136,12 @@ static unsigned int pstate_id_to_freq(in
 	int i;
 
 	i = powernv_pstate_info.max - pstate_id;
-	BUG_ON(i >= powernv_pstate_info.nr_pstates || i < 0);
+	if (i >= powernv_pstate_info.nr_pstates || i < 0) {
+		pr_warn("PState id %d outside of PState table, "
+			"reporting nominal id %d instead\n",
+			pstate_id, powernv_pstate_info.nominal);
+		i = powernv_pstate_info.max - powernv_pstate_info.nominal;
+	}
 
 	return powernv_freqs[i].frequency;
 }
@@ -321,6 +331,10 @@ static int __init powernv_cpufreq_init(v
 {
 	int rc = 0;
 
+	/* Don't probe on pseries (guest) platforms */
+	if (!firmware_has_feature(FW_FEATURE_OPALv3))
+		return -ENODEV;
+
 	/* Discover pstates from device tree and init */
 	rc = init_powernv_pstates();
 	if (rc) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/s3c2410-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2410-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/s3c2410-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2410-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,6 @@
 #include <mach/regs-clock.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/cpu-freq-core.h>
 
 /* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
@@ -104,7 +103,6 @@ static struct s3c_cpufreq_info s3c2410_c
 	.calc_iotiming	= s3c2410_iotiming_calc,
 	.set_iotiming	= s3c2410_iotiming_set,
 	.get_iotiming	= s3c2410_iotiming_get,
-	.resume_clocks	= s3c2410_setup_clocks,
 
 	.set_fvco	= s3c2410_set_fvco,
 	.set_refresh	= s3c2410_cpufreq_setrefresh,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/s3c2412-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2412-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/s3c2412-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2412-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,6 @@
 #include <mach/s3c2412.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/cpu-freq-core.h>
 
 /* our clock resources. */
@@ -188,8 +187,6 @@ static struct s3c_cpufreq_info s3c2412_c
 	.set_iotiming	= s3c2412_iotiming_set,
 	.get_iotiming	= s3c2412_iotiming_get,
 
-	.resume_clocks	= s3c2412_setup_clocks,
-
 	.debug_io_show  = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/s3c2440-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2440-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/s3c2440-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c2440-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,6 @@
 
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
-#include <plat/clock.h>
 
 static struct clk *xtal;
 static struct clk *fclk;
@@ -262,8 +261,6 @@ static struct s3c_cpufreq_info s3c2440_c
 	.calc_divs	= s3c2440_cpufreq_calcdivs,
 	.calc_freqtable	= s3c2440_cpufreq_calctable,
 
-	.resume_clocks	= s3c244x_setup_clocks,
-
 	.debug_io_show  = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/s3c24xx-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c24xx-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/s3c24xx-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/s3c24xx-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/cpu-freq-core.h>
 
 #include <mach/regs-clock.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/s5pv210-cpufreq.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/s5pv210-cpufreq.c
--- linux-libre-3.16-gnu/drivers/cpufreq/s5pv210-cpufreq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/s5pv210-cpufreq.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,11 +16,70 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/regulator/consumer.h>
 
-#include <mach/map.h>
-#include <mach/regs-clock.h>
+static void __iomem *clk_base;
+static void __iomem *dmc_base[2];
+
+#define S5P_CLKREG(x)		(clk_base + (x))
+
+#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
+#define S5P_APLL_CON		S5P_CLKREG(0x100)
+#define S5P_CLK_SRC0		S5P_CLKREG(0x200)
+#define S5P_CLK_SRC2		S5P_CLKREG(0x208)
+#define S5P_CLK_DIV0		S5P_CLKREG(0x300)
+#define S5P_CLK_DIV2		S5P_CLKREG(0x308)
+#define S5P_CLK_DIV6		S5P_CLKREG(0x318)
+#define S5P_CLKDIV_STAT0	S5P_CLKREG(0x1000)
+#define S5P_CLKDIV_STAT1	S5P_CLKREG(0x1004)
+#define S5P_CLKMUX_STAT0	S5P_CLKREG(0x1100)
+#define S5P_CLKMUX_STAT1	S5P_CLKREG(0x1104)
+
+#define S5P_ARM_MCS_CON		S5P_CLKREG(0x6100)
+
+/* CLKSRC0 */
+#define S5P_CLKSRC0_MUX200_SHIFT	(16)
+#define S5P_CLKSRC0_MUX200_MASK		(0x1 << S5P_CLKSRC0_MUX200_SHIFT)
+#define S5P_CLKSRC0_MUX166_MASK		(0x1<<20)
+#define S5P_CLKSRC0_MUX133_MASK		(0x1<<24)
+
+/* CLKSRC2 */
+#define S5P_CLKSRC2_G3D_SHIFT           (0)
+#define S5P_CLKSRC2_G3D_MASK            (0x3 << S5P_CLKSRC2_G3D_SHIFT)
+#define S5P_CLKSRC2_MFC_SHIFT           (4)
+#define S5P_CLKSRC2_MFC_MASK            (0x3 << S5P_CLKSRC2_MFC_SHIFT)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT		(0)
+#define S5P_CLKDIV0_APLL_MASK		(0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT		(4)
+#define S5P_CLKDIV0_A2M_MASK		(0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_HCLK200_SHIFT	(8)
+#define S5P_CLKDIV0_HCLK200_MASK	(0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
+#define S5P_CLKDIV0_PCLK100_SHIFT	(12)
+#define S5P_CLKDIV0_PCLK100_MASK	(0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
+#define S5P_CLKDIV0_HCLK166_SHIFT	(16)
+#define S5P_CLKDIV0_HCLK166_MASK	(0xF << S5P_CLKDIV0_HCLK166_SHIFT)
+#define S5P_CLKDIV0_PCLK83_SHIFT	(20)
+#define S5P_CLKDIV0_PCLK83_MASK		(0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
+#define S5P_CLKDIV0_HCLK133_SHIFT	(24)
+#define S5P_CLKDIV0_HCLK133_MASK	(0xF << S5P_CLKDIV0_HCLK133_SHIFT)
+#define S5P_CLKDIV0_PCLK66_SHIFT	(28)
+#define S5P_CLKDIV0_PCLK66_MASK		(0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+
+/* CLKDIV2 */
+#define S5P_CLKDIV2_G3D_SHIFT           (0)
+#define S5P_CLKDIV2_G3D_MASK            (0xF << S5P_CLKDIV2_G3D_SHIFT)
+#define S5P_CLKDIV2_MFC_SHIFT           (4)
+#define S5P_CLKDIV2_MFC_MASK            (0xF << S5P_CLKDIV2_MFC_SHIFT)
+
+/* CLKDIV6 */
+#define S5P_CLKDIV6_ONEDRAM_SHIFT       (28)
+#define S5P_CLKDIV6_ONEDRAM_MASK        (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
 
 static struct clk *dmc0_clk;
 static struct clk *dmc1_clk;
@@ -142,9 +201,9 @@ static void s5pv210_set_refresh(enum s5p
 	void __iomem *reg = NULL;
 
 	if (ch == DMC0) {
-		reg = (S5P_VA_DMC0 + 0x30);
+		reg = (dmc_base[0] + 0x30);
 	} else if (ch == DMC1) {
-		reg = (S5P_VA_DMC1 + 0x30);
+		reg = (dmc_base[1] + 0x30);
 	} else {
 		printk(KERN_ERR "Cannot find DMC port\n");
 		return;
@@ -442,7 +501,7 @@ static int check_mem_type(void __iomem *
 	return val >> 8;
 }
 
-static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
+static int s5pv210_cpu_init(struct cpufreq_policy *policy)
 {
 	unsigned long mem_type;
 	int ret;
@@ -472,7 +531,7 @@ static int __init s5pv210_cpu_init(struc
 	 * check_mem_type : This driver only support LPDDR & LPDDR2.
 	 * other memory type is not supported.
 	 */
-	mem_type = check_mem_type(S5P_VA_DMC0);
+	mem_type = check_mem_type(dmc_base[0]);
 
 	if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
 		printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
@@ -481,10 +540,10 @@ static int __init s5pv210_cpu_init(struc
 	}
 
 	/* Find current refresh counter and frequency each DMC */
-	s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
+	s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000);
 	s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
 
-	s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
+	s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000);
 	s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
 
 	policy->suspend_freq = SLEEP_FREQ;
@@ -527,8 +586,55 @@ static struct notifier_block s5pv210_cpu
 	.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
 };
 
-static int __init s5pv210_cpufreq_init(void)
+static int s5pv210_cpufreq_probe(struct platform_device *pdev)
 {
+	struct device_node *np;
+	int id;
+
+	/*
+	 * HACK: This is a temporary workaround to get access to clock
+	 * and DMC controller registers directly and remove static mappings
+	 * and dependencies on platform headers. It is necessary to enable
+	 * S5PV210 multi-platform support and will be removed together with
+	 * this whole driver as soon as S5PV210 gets migrated to use
+	 * cpufreq-cpu0 driver.
+	 */
+	np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
+	if (!np) {
+		pr_err("%s: failed to find clock controller DT node\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("%s: failed to map clock registers\n", __func__);
+		return -EFAULT;
+	}
+
+	for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {
+		id = of_alias_get_id(np, "dmc");
+		if (id < 0 || id >= ARRAY_SIZE(dmc_base)) {
+			pr_err("%s: failed to get alias of dmc node '%s'\n",
+				__func__, np->name);
+			return id;
+		}
+
+		dmc_base[id] = of_iomap(np, 0);
+		if (!dmc_base[id]) {
+			pr_err("%s: failed to map dmc%d registers\n",
+				__func__, id);
+			return -EFAULT;
+		}
+	}
+
+	for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) {
+		if (!dmc_base[id]) {
+			pr_err("%s: failed to find dmc%d node\n", __func__, id);
+			return -ENODEV;
+		}
+	}
+
 	arm_regulator = regulator_get(NULL, "vddarm");
 	if (IS_ERR(arm_regulator)) {
 		pr_err("failed to get regulator vddarm");
@@ -547,4 +653,11 @@ static int __init s5pv210_cpufreq_init(v
 	return cpufreq_register_driver(&s5pv210_driver);
 }
 
-late_initcall(s5pv210_cpufreq_init);
+static struct platform_driver s5pv210_cpufreq_platdrv = {
+	.driver = {
+		.name	= "s5pv210-cpufreq",
+		.owner	= THIS_MODULE,
+	},
+	.probe = s5pv210_cpufreq_probe,
+};
+module_platform_driver(s5pv210_cpufreq_platdrv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpufreq/speedstep-smi.c linux-libre-3.17-rc7-gnu/drivers/cpufreq/speedstep-smi.c
--- linux-libre-3.16-gnu/drivers/cpufreq/speedstep-smi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpufreq/speedstep-smi.c	2014-09-28 17:29:07.000000000 -0400
@@ -324,8 +324,8 @@ static int __init speedstep_init(void)
 		return -ENODEV;
 	}
 
-	pr_debug("signature:0x%.8ulx, command:0x%.8ulx, "
-		"event:0x%.8ulx, perf_level:0x%.8ulx.\n",
+	pr_debug("signature:0x%.8x, command:0x%.8x, "
+		"event:0x%.8x, perf_level:0x%.8x.\n",
 		ist_info.signature, ist_info.command,
 		ist_info.event, ist_info.perf_level);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-armada-370-xp.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-armada-370-xp.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-armada-370-xp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-armada-370-xp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-/*
- * Marvell Armada 370 and Armada XP SoC cpuidle driver
- *
- * Copyright (C) 2014 Marvell
- *
- * Nadav Haklai <nadavh@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
- */
-
-#include <linux/cpu_pm.h>
-#include <linux/cpuidle.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/suspend.h>
-#include <linux/platform_device.h>
-#include <asm/cpuidle.h>
-
-#define ARMADA_370_XP_MAX_STATES	3
-#define ARMADA_370_XP_FLAG_DEEP_IDLE	0x10000
-
-static int (*armada_370_xp_cpu_suspend)(int);
-
-static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
-{
-	int ret;
-	bool deepidle = false;
-	cpu_pm_enter();
-
-	if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE)
-		deepidle = true;
-
-	ret = armada_370_xp_cpu_suspend(deepidle);
-	if (ret)
-		return ret;
-
-	cpu_pm_exit();
-
-	return index;
-}
-
-static struct cpuidle_driver armada_370_xp_idle_driver = {
-	.name			= "armada_370_xp_idle",
-	.states[0]		= ARM_CPUIDLE_WFI_STATE,
-	.states[1]		= {
-		.enter			= armada_370_xp_enter_idle,
-		.exit_latency		= 10,
-		.power_usage		= 50,
-		.target_residency	= 100,
-		.flags			= CPUIDLE_FLAG_TIME_VALID,
-		.name			= "Idle",
-		.desc			= "CPU power down",
-	},
-	.states[2]		= {
-		.enter			= armada_370_xp_enter_idle,
-		.exit_latency		= 100,
-		.power_usage		= 5,
-		.target_residency	= 1000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID |
-						ARMADA_370_XP_FLAG_DEEP_IDLE,
-		.name			= "Deep idle",
-		.desc			= "CPU and L2 Fabric power down",
-	},
-	.state_count = ARMADA_370_XP_MAX_STATES,
-};
-
-static int armada_370_xp_cpuidle_probe(struct platform_device *pdev)
-{
-
-	armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data);
-	return cpuidle_register(&armada_370_xp_idle_driver, NULL);
-}
-
-static struct platform_driver armada_370_xp_cpuidle_plat_driver = {
-	.driver = {
-		.name = "cpuidle-armada-370-xp",
-		.owner = THIS_MODULE,
-	},
-	.probe = armada_370_xp_cpuidle_probe,
-};
-
-module_platform_driver(armada_370_xp_cpuidle_plat_driver);
-
-MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
-MODULE_DESCRIPTION("Armada 370/XP cpu idle driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-big_little.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-big_little.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-big_little.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-big_little.c	2014-09-28 17:29:07.000000000 -0400
@@ -138,39 +138,42 @@ static int bl_enter_powerdown(struct cpu
 	return idx;
 }
 
-static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
+static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
 {
-	struct cpuinfo_arm *cpu_info;
 	struct cpumask *cpumask;
-	unsigned long cpuid;
 	int cpu;
 
 	cpumask = kzalloc(cpumask_size(), GFP_KERNEL);
 	if (!cpumask)
 		return -ENOMEM;
 
-	for_each_possible_cpu(cpu) {
-		cpu_info = &per_cpu(cpu_data, cpu);
-		cpuid = is_smp() ? cpu_info->cpuid : read_cpuid_id();
-
-		/* read cpu id part number */
-		if ((cpuid & 0xFFF0) == cpu_id)
+	for_each_possible_cpu(cpu)
+		if (smp_cpuid_part(cpu) == part_id)
 			cpumask_set_cpu(cpu, cpumask);
-	}
 
 	drv->cpumask = cpumask;
 
 	return 0;
 }
 
+static const struct of_device_id compatible_machine_match[] = {
+	{ .compatible = "arm,vexpress,v2p-ca15_a7" },
+	{ .compatible = "samsung,exynos5420" },
+	{},
+};
+
 static int __init bl_idle_init(void)
 {
 	int ret;
+	struct device_node *root = of_find_node_by_path("/");
+
+	if (!root)
+		return -ENODEV;
 
 	/*
 	 * Initialize the driver just for a compliant set of machines
 	 */
-	if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7"))
+	if (!of_match_node(compatible_machine_match, root))
 		return -ENODEV;
 	/*
 	 * For now the differentiation between little and big cores
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,11 +119,13 @@ int cpuidle_enter_state(struct cpuidle_d
 	ktime_t time_start, time_end;
 	s64 diff;
 
+	trace_cpu_idle_rcuidle(index, dev->cpu);
 	time_start = ktime_get();
 
 	entered_state = target_state->enter(dev, drv, index);
 
 	time_end = ktime_get();
+	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
 	if (!cpuidle_state_is_coupled(dev, drv, entered_state))
 		local_irq_enable();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-exynos.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-exynos.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-exynos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-exynos.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,25 +20,6 @@
 
 static void (*exynos_enter_aftr)(void);
 
-static int idle_finisher(unsigned long flags)
-{
-	exynos_enter_aftr();
-	cpu_do_idle();
-
-	return 1;
-}
-
-static int exynos_enter_core0_aftr(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
-{
-	cpu_pm_enter();
-	cpu_suspend(0, idle_finisher);
-	cpu_pm_exit();
-
-	return index;
-}
-
 static int exynos_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index)
@@ -51,8 +32,10 @@ static int exynos_enter_lowpower(struct
 
 	if (new_index == 0)
 		return arm_cpuidle_simple_enter(dev, drv, new_index);
-	else
-		return exynos_enter_core0_aftr(dev, drv, new_index);
+
+	exynos_enter_aftr();
+
+	return new_index;
 }
 
 static struct cpuidle_driver exynos_idle_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-mvebu-v7.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-mvebu-v7.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-mvebu-v7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-mvebu-v7.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * Marvell Armada 370, 38x and XP SoC cpuidle driver
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Nadav Haklai <nadavh@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <linux/platform_device.h>
+#include <asm/cpuidle.h>
+
+#define MVEBU_V7_FLAG_DEEP_IDLE	0x10000
+
+static int (*mvebu_v7_cpu_suspend)(int);
+
+static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv,
+				int index)
+{
+	int ret;
+	bool deepidle = false;
+	cpu_pm_enter();
+
+	if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
+		deepidle = true;
+
+	ret = mvebu_v7_cpu_suspend(deepidle);
+	if (ret)
+		return ret;
+
+	cpu_pm_exit();
+
+	return index;
+}
+
+static struct cpuidle_driver armadaxp_idle_driver = {
+	.name			= "armada_xp_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 10,
+		.power_usage		= 50,
+		.target_residency	= 100,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "MV CPU IDLE",
+		.desc			= "CPU power down",
+	},
+	.states[2]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 100,
+		.power_usage		= 5,
+		.target_residency	= 1000,
+		.flags			= CPUIDLE_FLAG_TIME_VALID |
+						MVEBU_V7_FLAG_DEEP_IDLE,
+		.name			= "MV CPU DEEP IDLE",
+		.desc			= "CPU and L2 Fabric power down",
+	},
+	.state_count = 3,
+};
+
+static struct cpuidle_driver armada370_idle_driver = {
+	.name			= "armada_370_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 100,
+		.power_usage		= 5,
+		.target_residency	= 1000,
+		.flags			= (CPUIDLE_FLAG_TIME_VALID |
+					   MVEBU_V7_FLAG_DEEP_IDLE),
+		.name			= "Deep Idle",
+		.desc			= "CPU and L2 Fabric power down",
+	},
+	.state_count = 2,
+};
+
+static struct cpuidle_driver armada38x_idle_driver = {
+	.name			= "armada_38x_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 10,
+		.power_usage		= 5,
+		.target_residency	= 100,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "Idle",
+		.desc			= "CPU and SCU power down",
+	},
+	.state_count = 2,
+};
+
+static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
+{
+	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
+
+	if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
+		return cpuidle_register(&armadaxp_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
+		return cpuidle_register(&armada370_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
+		return cpuidle_register(&armada38x_idle_driver, NULL);
+	else
+		return -EINVAL;
+}
+
+static struct platform_driver armadaxp_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-xp",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armadaxp_cpuidle_plat_driver);
+
+static struct platform_driver armada370_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-370",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada370_cpuidle_plat_driver);
+
+static struct platform_driver armada38x_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-38x",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada38x_cpuidle_plat_driver);
+
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-powernv.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-powernv.c
--- linux-libre-3.16-gnu/drivers/cpuidle/cpuidle-powernv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/cpuidle-powernv.c	2014-09-28 17:29:07.000000000 -0400
@@ -160,10 +160,10 @@ static int powernv_cpuidle_driver_init(v
 static int powernv_add_idle_states(void)
 {
 	struct device_node *power_mgt;
-	struct property *prop;
 	int nr_idle_states = 1; /* Snooze */
 	int dt_idle_states;
-	u32 *flags;
+	const __be32 *idle_state_flags;
+	u32 len_flags, flags;
 	int i;
 
 	/* Currently we have snooze statically defined */
@@ -174,18 +174,18 @@ static int powernv_add_idle_states(void)
 		return nr_idle_states;
 	}
 
-	prop = of_find_property(power_mgt, "ibm,cpu-idle-state-flags", NULL);
-	if (!prop) {
+	idle_state_flags = of_get_property(power_mgt, "ibm,cpu-idle-state-flags", &len_flags);
+	if (!idle_state_flags) {
 		pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n");
 		return nr_idle_states;
 	}
 
-	dt_idle_states = prop->length / sizeof(u32);
-	flags = (u32 *) prop->value;
+	dt_idle_states = len_flags / sizeof(u32);
 
 	for (i = 0; i < dt_idle_states; i++) {
 
-		if (flags[i] & IDLE_USE_INST_NAP) {
+		flags = be32_to_cpu(idle_state_flags[i]);
+		if (flags & IDLE_USE_INST_NAP) {
 			/* Add NAP state */
 			strcpy(powernv_states[nr_idle_states].name, "Nap");
 			strcpy(powernv_states[nr_idle_states].desc, "Nap");
@@ -196,7 +196,7 @@ static int powernv_add_idle_states(void)
 			nr_idle_states++;
 		}
 
-		if (flags[i] & IDLE_USE_INST_SLEEP) {
+		if (flags & IDLE_USE_INST_SLEEP) {
 			/* Add FASTSLEEP state */
 			strcpy(powernv_states[nr_idle_states].name, "FastSleep");
 			strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/driver.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/driver.c
--- linux-libre-3.16-gnu/drivers/cpuidle/driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -182,10 +182,6 @@ static void __cpuidle_driver_init(struct
 static int poll_idle(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
-	ktime_t	t1, t2;
-	s64 diff;
-
-	t1 = ktime_get();
 	local_irq_enable();
 	if (!current_set_polling_and_test()) {
 		while (!need_resched())
@@ -193,13 +189,6 @@ static int poll_idle(struct cpuidle_devi
 	}
 	current_clr_polling();
 
-	t2 = ktime_get();
-	diff = ktime_to_us(ktime_sub(t2, t1));
-	if (diff > INT_MAX)
-		diff = INT_MAX;
-
-	dev->last_residency = (int) diff;
-
 	return index;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/governors/ladder.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/governors/ladder.c
--- linux-libre-3.16-gnu/drivers/cpuidle/governors/ladder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/governors/ladder.c	2014-09-28 17:29:07.000000000 -0400
@@ -144,7 +144,7 @@ static int ladder_enable_device(struct c
 
 	ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-	for (i = 0; i < drv->state_count; i++) {
+	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
 		state = &drv->states[i];
 		lstate = &ldev->states[i];
 
@@ -156,7 +156,7 @@ static int ladder_enable_device(struct c
 
 		if (i < drv->state_count - 1)
 			lstate->threshold.promotion_time = state->exit_latency;
-		if (i > 0)
+		if (i > CPUIDLE_DRIVER_STATE_START)
 			lstate->threshold.demotion_time = state->exit_latency;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/governors/menu.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/governors/menu.c
--- linux-libre-3.16-gnu/drivers/cpuidle/governors/menu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/governors/menu.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,11 +31,11 @@
  * The default values do not overflow.
  */
 #define BUCKETS 12
-#define INTERVALS 8
+#define INTERVAL_SHIFT 3
+#define INTERVALS (1UL << INTERVAL_SHIFT)
 #define RESOLUTION 1024
 #define DECAY 8
 #define MAX_INTERESTING 50000
-#define STDDEV_THRESH 400
 
 
 /*
@@ -134,15 +134,12 @@ struct menu_device {
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
-static int get_loadavg(void)
+static inline int get_loadavg(unsigned long load)
 {
-	unsigned long this = this_cpu_load();
-
-
-	return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10;
+	return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10;
 }
 
-static inline int which_bucket(unsigned int duration)
+static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters)
 {
 	int bucket = 0;
 
@@ -152,7 +149,7 @@ static inline int which_bucket(unsigned
 	 * This allows us to calculate
 	 * E(duration)|iowait
 	 */
-	if (nr_iowait_cpu(smp_processor_id()))
+	if (nr_iowaiters)
 		bucket = BUCKETS/2;
 
 	if (duration < 10)
@@ -175,16 +172,16 @@ static inline int which_bucket(unsigned
  * to be, the higher this multiplier, and thus the higher
  * the barrier to go to an expensive C state.
  */
-static inline int performance_multiplier(void)
+static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load)
 {
 	int mult = 1;
 
 	/* for higher loadavg, we are more reluctant */
 
-	mult += 2 * get_loadavg();
+	mult += 2 * get_loadavg(load);
 
 	/* for IO wait tasks (per cpu!) we add 5x each */
-	mult += 10 * nr_iowait_cpu(smp_processor_id());
+	mult += 10 * nr_iowaiters;
 
 	return mult;
 }
@@ -228,7 +225,10 @@ again:
 				max = value;
 		}
 	}
-	do_div(avg, divisor);
+	if (divisor == INTERVALS)
+		avg >>= INTERVAL_SHIFT;
+	else
+		do_div(avg, divisor);
 
 	/* Then try to determine standard deviation */
 	stddev = 0;
@@ -239,7 +239,11 @@ again:
 			stddev += diff * diff;
 		}
 	}
-	do_div(stddev, divisor);
+	if (divisor == INTERVALS)
+		stddev >>= INTERVAL_SHIFT;
+	else
+		do_div(stddev, divisor);
+
 	/*
 	 * The typical interval is obtained when standard deviation is small
 	 * or standard deviation is small compared to the average interval.
@@ -289,7 +293,7 @@ static int menu_select(struct cpuidle_dr
 	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 	int i;
 	unsigned int interactivity_req;
-	struct timespec t;
+	unsigned long nr_iowaiters, cpu_load;
 
 	if (data->needs_update) {
 		menu_update(drv, dev);
@@ -303,12 +307,10 @@ static int menu_select(struct cpuidle_dr
 		return 0;
 
 	/* determine the expected residency time, round up */
-	t = ktime_to_timespec(tick_nohz_get_sleep_length());
-	data->next_timer_us =
-		t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
-
+	data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length());
 
-	data->bucket = which_bucket(data->next_timer_us);
+	get_iowait_load(&nr_iowaiters, &cpu_load);
+	data->bucket = which_bucket(data->next_timer_us, nr_iowaiters);
 
 	/*
 	 * Force the result of multiplication to be 64 bits even if both
@@ -326,7 +328,7 @@ static int menu_select(struct cpuidle_dr
 	 * duration / latency ratio. Adjust the latency limit if
 	 * necessary.
 	 */
-	interactivity_req = data->predicted_us / performance_multiplier();
+	interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
 	if (latency_req > interactivity_req)
 		latency_req = interactivity_req;
 
@@ -399,7 +401,7 @@ static void menu_update(struct cpuidle_d
 	 *
 	 * Any measured amount of time will include the exit latency.
 	 * Since we are interested in when the wakeup begun, not when it
-	 * was completed, we must substract the exit latency. However, if
+	 * was completed, we must subtract the exit latency. However, if
 	 * the measured amount of time is less than the exit latency,
 	 * assume the state was never reached and the exit latency is 0.
 	 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/Kconfig linux-libre-3.17-rc7-gnu/drivers/cpuidle/Kconfig
--- linux-libre-3.16-gnu/drivers/cpuidle/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -15,12 +15,7 @@ config CPU_IDLE
 if CPU_IDLE
 
 config CPU_IDLE_MULTIPLE_DRIVERS
-        bool "Support multiple cpuidle drivers"
-        default n
-        help
-         Allows the cpuidle framework to use different drivers for each CPU.
-         This is useful if you have a system with different CPU latencies and
-         states. If unsure say N.
+        bool
 
 config CPU_IDLE_GOV_LADDER
 	bool "Ladder governor (for periodic timer tick)"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/Kconfig.arm linux-libre-3.17-rc7-gnu/drivers/cpuidle/Kconfig.arm
--- linux-libre-3.16-gnu/drivers/cpuidle/Kconfig.arm	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/Kconfig.arm	2014-09-28 17:29:07.000000000 -0400
@@ -1,15 +1,10 @@
 #
 # ARM CPU Idle drivers
 #
-config ARM_ARMADA_370_XP_CPUIDLE
-	bool "CPU Idle Driver for Armada 370/XP family processors"
-	depends on ARCH_MVEBU
-	help
-	  Select this to enable cpuidle on Armada 370/XP processors.
-
 config ARM_BIG_LITTLE_CPUIDLE
 	bool "Support for ARM big.LITTLE processors"
-	depends on ARCH_VEXPRESS_TC2_PM
+	depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
+	depends on MCPM
 	select ARM_CPU_SUSPEND
 	select CPU_IDLE_MULTIPLE_DRIVERS
 	help
@@ -61,3 +56,9 @@ config ARM_EXYNOS_CPUIDLE
 	depends on ARCH_EXYNOS
 	help
 	  Select this to enable cpuidle for Exynos processors
+
+config ARM_MVEBU_V7_CPUIDLE
+	bool "CPU Idle Driver for mvebu v7 family processors"
+	depends on ARCH_MVEBU
+	help
+	  Select this to enable cpuidle on Armada 370, 38x and XP processors.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/Makefile linux-libre-3.17-rc7-gnu/drivers/cpuidle/Makefile
--- linux-libre-3.16-gnu/drivers/cpuidle/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
 
 ##################################################################################
 # ARM SoC drivers
-obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o
+obj-$(CONFIG_ARM_MVEBU_V7_CPUIDLE) += cpuidle-mvebu-v7.o
 obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE)	+= cpuidle-big_little.o
 obj-$(CONFIG_ARM_CLPS711X_CPUIDLE)	+= cpuidle-clps711x.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/cpuidle/sysfs.c linux-libre-3.17-rc7-gnu/drivers/cpuidle/sysfs.c
--- linux-libre-3.16-gnu/drivers/cpuidle/sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/cpuidle/sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -445,7 +445,7 @@ static void cpuidle_remove_state_sysfs(s
 
 #define define_one_driver_ro(_name, show)                       \
 	static struct cpuidle_driver_attr attr_driver_##_name = \
-		__ATTR(_name, 0644, show, NULL)
+		__ATTR(_name, 0444, show, NULL)
 
 struct cpuidle_driver_kobj {
 	struct cpuidle_driver *drv;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/amcc/crypto4xx_core.c linux-libre-3.17-rc7-gnu/drivers/crypto/amcc/crypto4xx_core.c
--- linux-libre-3.16-gnu/drivers/crypto/amcc/crypto4xx_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/amcc/crypto4xx_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1292,7 +1292,7 @@ static struct platform_driver crypto4xx_
 		.of_match_table = crypto4xx_match,
 	},
 	.probe		= crypto4xx_probe,
-	.remove		= crypto4xx_remove,
+	.remove		= __exit_p(crypto4xx_remove),
 };
 
 module_platform_driver(crypto4xx_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/atmel-sha.c linux-libre-3.17-rc7-gnu/drivers/crypto/atmel-sha.c
--- linux-libre-3.16-gnu/drivers/crypto/atmel-sha.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/atmel-sha.c	2014-09-28 17:29:07.000000000 -0400
@@ -1353,7 +1353,6 @@ static struct crypto_platform_data *atme
 					GFP_KERNEL);
 	if (!pdata->dma_slave) {
 		dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-		devm_kfree(&pdev->dev, pdata);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1375,7 +1374,8 @@ static int atmel_sha_probe(struct platfo
 	unsigned long sha_phys_size;
 	int err;
 
-	sha_dd = kzalloc(sizeof(struct atmel_sha_dev), GFP_KERNEL);
+	sha_dd = devm_kzalloc(&pdev->dev, sizeof(struct atmel_sha_dev),
+				GFP_KERNEL);
 	if (sha_dd == NULL) {
 		dev_err(dev, "unable to alloc data struct.\n");
 		err = -ENOMEM;
@@ -1490,8 +1490,6 @@ clk_err:
 	free_irq(sha_dd->irq, sha_dd);
 res_err:
 	tasklet_kill(&sha_dd->done_task);
-	kfree(sha_dd);
-	sha_dd = NULL;
 sha_dd_err:
 	dev_err(dev, "initialization failed.\n");
 
@@ -1523,9 +1521,6 @@ static int atmel_sha_remove(struct platf
 	if (sha_dd->irq >= 0)
 		free_irq(sha_dd->irq, sha_dd);
 
-	kfree(sha_dd);
-	sha_dd = NULL;
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/atmel-tdes.c linux-libre-3.17-rc7-gnu/drivers/crypto/atmel-tdes.c
--- linux-libre-3.16-gnu/drivers/crypto/atmel-tdes.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/atmel-tdes.c	2014-09-28 17:29:07.000000000 -0400
@@ -1337,7 +1337,6 @@ static struct crypto_platform_data *atme
 					GFP_KERNEL);
 	if (!pdata->dma_slave) {
 		dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-		devm_kfree(&pdev->dev, pdata);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1359,7 +1358,7 @@ static int atmel_tdes_probe(struct platf
 	unsigned long tdes_phys_size;
 	int err;
 
-	tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL);
+	tdes_dd = devm_kmalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL);
 	if (tdes_dd == NULL) {
 		dev_err(dev, "unable to alloc data struct.\n");
 		err = -ENOMEM;
@@ -1483,8 +1482,6 @@ tdes_irq_err:
 res_err:
 	tasklet_kill(&tdes_dd->done_task);
 	tasklet_kill(&tdes_dd->queue_task);
-	kfree(tdes_dd);
-	tdes_dd = NULL;
 tdes_dd_err:
 	dev_err(dev, "initialization failed.\n");
 
@@ -1519,9 +1516,6 @@ static int atmel_tdes_remove(struct plat
 	if (tdes_dd->irq >= 0)
 		free_irq(tdes_dd->irq, tdes_dd);
 
-	kfree(tdes_dd);
-	tdes_dd = NULL;
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/caamalg.c linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamalg.c
--- linux-libre-3.16-gnu/drivers/crypto/caam/caamalg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamalg.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,6 +97,13 @@ static inline void append_dec_op1(u32 *d
 {
 	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);
@@ -786,7 +793,7 @@ static int ablkcipher_setkey(struct cryp
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+	if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
@@ -1313,8 +1320,13 @@ static struct aead_edesc *aead_edesc_all
 					 DMA_FROM_DEVICE, dst_chained);
 	}
 
-	/* Check if data are contiguous */
 	iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, iv_dma)) {
+		dev_err(jrdev, "unable to map IV\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Check if data are contiguous */
 	if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
 	    iv_dma || src_nents || iv_dma + ivsize !=
 	    sg_dma_address(req->src)) {
@@ -1345,8 +1357,6 @@ static struct aead_edesc *aead_edesc_all
 	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
 			 desc_bytes;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
 	*all_contig_ptr = all_contig;
 
 	sec4_sg_index = 0;
@@ -1369,6 +1379,12 @@ static struct aead_edesc *aead_edesc_all
 		sg_to_sec4_sg_last(req->dst, dst_nents,
 				   edesc->sec4_sg + sec4_sg_index, 0);
 	}
+	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+		return ERR_PTR(-ENOMEM);
+	}
 
 	return edesc;
 }
@@ -1494,8 +1510,13 @@ static struct aead_edesc *aead_giv_edesc
 					 DMA_FROM_DEVICE, dst_chained);
 	}
 
-	/* Check if data are contiguous */
 	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");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Check if data are contiguous */
 	if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
 	    iv_dma || src_nents || iv_dma + ivsize != sg_dma_address(req->src))
 		contig &= ~GIV_SRC_CONTIG;
@@ -1534,8 +1555,6 @@ static struct aead_edesc *aead_giv_edesc
 	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
 			 desc_bytes;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
 	*contig_ptr = contig;
 
 	sec4_sg_index = 0;
@@ -1559,6 +1578,12 @@ static struct aead_edesc *aead_giv_edesc
 		sg_to_sec4_sg_last(req->dst, dst_nents,
 				   edesc->sec4_sg + sec4_sg_index, 0);
 	}
+	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+		return ERR_PTR(-ENOMEM);
+	}
 
 	return edesc;
 }
@@ -1650,11 +1675,16 @@ static struct ablkcipher_edesc *ablkciph
 					 DMA_FROM_DEVICE, dst_chained);
 	}
 
+	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");
+		return ERR_PTR(-ENOMEM);
+	}
+
 	/*
 	 * Check if iv can be contiguous with source and destination.
 	 * If so, include it. If not, create scatterlist.
 	 */
-	iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
 	if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
 		iv_contig = true;
 	else
@@ -1693,6 +1723,11 @@ static struct ablkcipher_edesc *ablkciph
 
 	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
 					    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");
+		return ERR_PTR(-ENOMEM);
+	}
+
 	edesc->iv_dma = iv_dma;
 
 #ifdef DEBUG
@@ -2441,8 +2476,37 @@ static struct caam_crypto_alg *caam_alg_
 
 static int __init caam_algapi_init(void)
 {
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	void *priv;
 	int i = 0, err = 0;
 
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev) {
+		of_node_put(dev_node);
+		return -ENODEV;
+	}
+
+	ctrldev = &pdev->dev;
+	priv = dev_get_drvdata(ctrldev);
+	of_node_put(dev_node);
+
+	/*
+	 * If priv is NULL, it's probably because the caam driver wasn't
+	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+	 */
+	if (!priv)
+		return -ENODEV;
+
+
 	INIT_LIST_HEAD(&alg_list);
 
 	/* register crypto algorithms the device supports */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/caamhash.c linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamhash.c
--- linux-libre-3.16-gnu/drivers/crypto/caam/caamhash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamhash.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,13 +137,20 @@ struct caam_hash_state {
 /* Common job descriptor seq in/out ptr routines */
 
 /* Map state->caam_ctx, and append seq_out_ptr command that points to it */
-static inline void map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
-				       struct caam_hash_state *state,
-				       int ctx_len)
+static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
+				      struct caam_hash_state *state,
+				      int ctx_len)
 {
 	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
 					ctx_len, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, state->ctx_dma)) {
+		dev_err(jrdev, "unable to map ctx\n");
+		return -ENOMEM;
+	}
+
 	append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
+
+	return 0;
 }
 
 /* Map req->result, and append seq_out_ptr command that points to it */
@@ -201,14 +208,19 @@ try_buf_map_to_sec4_sg(struct device *jr
 }
 
 /* Map state->caam_ctx, and add it to link table */
-static inline void ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
-				      struct caam_hash_state *state,
-				      int ctx_len,
-				      struct sec4_sg_entry *sec4_sg,
-				      u32 flag)
+static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
+				     struct caam_hash_state *state, int ctx_len,
+				     struct sec4_sg_entry *sec4_sg, u32 flag)
 {
 	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
+	if (dma_mapping_error(jrdev, state->ctx_dma)) {
+		dev_err(jrdev, "unable to map ctx\n");
+		return -ENOMEM;
+	}
+
 	dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
+
+	return 0;
 }
 
 /* Common shared descriptor commands */
@@ -487,11 +499,11 @@ static int hash_digest_key(struct caam_h
 			       digestsize, 1);
 #endif
 	}
-	*keylen = digestsize;
-
 	dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
 	dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
 
+	*keylen = digestsize;
+
 	kfree(desc);
 
 	return ret;
@@ -706,7 +718,7 @@ static void ahash_done_ctx_src(struct de
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
-	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+	ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_TO_DEVICE);
 	kfree(edesc);
 
 #ifdef DEBUG
@@ -741,7 +753,7 @@ static void ahash_done_ctx_dst(struct de
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
-	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
+	ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE);
 	kfree(edesc);
 
 #ifdef DEBUG
@@ -808,12 +820,11 @@ static int ahash_update_ctx(struct ahash
 		edesc->sec4_sg_bytes = sec4_sg_bytes;
 		edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 				 DESC_JOB_IO_LEN;
-		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-						     sec4_sg_bytes,
-						     DMA_TO_DEVICE);
 
-		ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
-				   edesc->sec4_sg, DMA_BIDIRECTIONAL);
+		ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+					 edesc->sec4_sg, DMA_BIDIRECTIONAL);
+		if (ret)
+			return ret;
 
 		state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
 							edesc->sec4_sg + 1,
@@ -839,6 +850,14 @@ static int ahash_update_ctx(struct ahash
 		init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
 				     HDR_REVERSE);
 
+		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+						     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");
+			return -ENOMEM;
+		}
+
 		append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
 				       to_hash, LDST_SGF);
 
@@ -911,23 +930,34 @@ static int ahash_final_ctx(struct ahash_
 	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 			 DESC_JOB_IO_LEN;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
 	edesc->src_nents = 0;
 
-	ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
-			   DMA_TO_DEVICE);
+	ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+				 edesc->sec4_sg, DMA_TO_DEVICE);
+	if (ret)
+		return ret;
 
 	state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
 						buf, state->buf_dma, buflen,
 						last_buflen);
 	(edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN;
 
+	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+		return -ENOMEM;
+	}
+
 	append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
 			  LDST_SGF);
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
+	if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -989,11 +1019,11 @@ static int ahash_finup_ctx(struct ahash_
 	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 			 DESC_JOB_IO_LEN;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
 
-	ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
-			   DMA_TO_DEVICE);
+	ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+				 edesc->sec4_sg, DMA_TO_DEVICE);
+	if (ret)
+		return ret;
 
 	state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
 						buf, state->buf_dma, buflen,
@@ -1002,11 +1032,22 @@ static int ahash_finup_ctx(struct ahash_
 	src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg +
 			   sec4_sg_src_index, chained);
 
+	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+		return -ENOMEM;
+	}
+
 	append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
 			       buflen + req->nbytes, LDST_SGF);
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
+	if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1056,8 +1097,7 @@ static int ahash_digest(struct ahash_req
 	}
 	edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 			  DESC_JOB_IO_LEN;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
+	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->src_nents = src_nents;
 	edesc->chained = chained;
 
@@ -1067,6 +1107,12 @@ static int ahash_digest(struct ahash_req
 
 	if (src_nents) {
 		sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
+		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+			return -ENOMEM;
+		}
 		src_dma = edesc->sec4_sg_dma;
 		options = LDST_SGF;
 	} else {
@@ -1077,6 +1123,10 @@ static int ahash_digest(struct ahash_req
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
+	if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1125,11 +1175,19 @@ static int ahash_final_no_ctx(struct aha
 	init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
 
 	state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, state->buf_dma)) {
+		dev_err(jrdev, "unable to map src\n");
+		return -ENOMEM;
+	}
 
 	append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
+	if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 	edesc->src_nents = 0;
 
 #ifdef DEBUG
@@ -1197,9 +1255,7 @@ static int ahash_update_no_ctx(struct ah
 		edesc->sec4_sg_bytes = sec4_sg_bytes;
 		edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 				 DESC_JOB_IO_LEN;
-		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-						    sec4_sg_bytes,
-						    DMA_TO_DEVICE);
+		edesc->dst_dma = 0;
 
 		state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg,
 						    buf, *buflen);
@@ -1216,9 +1272,19 @@ static int ahash_update_no_ctx(struct ah
 		init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
 				     HDR_REVERSE);
 
+		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+						    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");
+			return -ENOMEM;
+		}
+
 		append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
 
-		map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+		if (ret)
+			return ret;
 
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1297,8 +1363,6 @@ static int ahash_finup_no_ctx(struct aha
 	edesc->sec4_sg_bytes = sec4_sg_bytes;
 	edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 			 DESC_JOB_IO_LEN;
-	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-					    sec4_sg_bytes, DMA_TO_DEVICE);
 
 	state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, buf,
 						state->buf_dma, buflen,
@@ -1307,11 +1371,22 @@ static int ahash_finup_no_ctx(struct aha
 	src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1,
 			   chained);
 
+	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+					    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");
+		return -ENOMEM;
+	}
+
 	append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen +
 			       req->nbytes, LDST_SGF);
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
+	if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1380,13 +1455,19 @@ static int ahash_update_first(struct aha
 		edesc->sec4_sg_bytes = sec4_sg_bytes;
 		edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
 				 DESC_JOB_IO_LEN;
-		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-						    sec4_sg_bytes,
-						    DMA_TO_DEVICE);
+		edesc->dst_dma = 0;
 
 		if (src_nents) {
 			sg_to_sec4_sg_last(req->src, src_nents,
 					   edesc->sec4_sg, 0);
+			edesc->sec4_sg_dma = dma_map_single(jrdev,
+							    edesc->sec4_sg,
+							    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");
+				return -ENOMEM;
+			}
 			src_dma = edesc->sec4_sg_dma;
 			options = LDST_SGF;
 		} else {
@@ -1404,7 +1485,9 @@ static int ahash_update_first(struct aha
 
 		append_seq_in_ptr(desc, src_dma, to_hash, options);
 
-		map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+		ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+		if (ret)
+			return ret;
 
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1453,6 +1536,7 @@ static int ahash_init(struct ahash_reque
 	state->final = ahash_final_no_ctx;
 
 	state->current_buf = 0;
+	state->buf_dma = 0;
 
 	return 0;
 }
@@ -1787,8 +1871,36 @@ caam_hash_alloc(struct caam_hash_templat
 
 static int __init caam_algapi_hash_init(void)
 {
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	void *priv;
 	int i = 0, err = 0;
 
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev) {
+		of_node_put(dev_node);
+		return -ENODEV;
+	}
+
+	ctrldev = &pdev->dev;
+	priv = dev_get_drvdata(ctrldev);
+	of_node_put(dev_node);
+
+	/*
+	 * If priv is NULL, it's probably because the caam driver wasn't
+	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+	 */
+	if (!priv)
+		return -ENODEV;
+
 	INIT_LIST_HEAD(&hash_list);
 
 	/* register crypto algorithms the device supports */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/caamrng.c linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamrng.c
--- linux-libre-3.16-gnu/drivers/crypto/caam/caamrng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/caamrng.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,7 +185,7 @@ static int caam_read(struct hwrng *rng,
 				      max - copied_idx, false);
 }
 
-static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx)
+static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
 {
 	struct device *jrdev = ctx->jrdev;
 	u32 *desc = ctx->sh_desc;
@@ -203,13 +203,18 @@ static inline void rng_create_sh_desc(st
 
 	ctx->sh_desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
 					  DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
 		       desc, desc_bytes(desc), 1);
 #endif
+	return 0;
 }
 
-static inline void rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
+static inline int rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
 {
 	struct device *jrdev = ctx->jrdev;
 	struct buf_data *bd = &ctx->bufs[buf_id];
@@ -220,12 +225,17 @@ static inline void rng_create_job_desc(s
 			     HDR_REVERSE);
 
 	bd->addr = dma_map_single(jrdev, bd->buf, RN_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, bd->addr)) {
+		dev_err(jrdev, "unable to map dst\n");
+		return -ENOMEM;
+	}
 
 	append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0);
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
 		       desc, desc_bytes(desc), 1);
 #endif
+	return 0;
 }
 
 static void caam_cleanup(struct hwrng *rng)
@@ -242,24 +252,44 @@ static void caam_cleanup(struct hwrng *r
 	rng_unmap_ctx(rng_ctx);
 }
 
-static void caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
+static int caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
 {
 	struct buf_data *bd = &ctx->bufs[buf_id];
+	int err;
+
+	err = rng_create_job_desc(ctx, buf_id);
+	if (err)
+		return err;
 
-	rng_create_job_desc(ctx, buf_id);
 	atomic_set(&bd->empty, BUF_EMPTY);
 	submit_job(ctx, buf_id == ctx->current_buf);
 	wait_for_completion(&bd->filled);
+
+	return 0;
 }
 
-static void caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev)
+static int caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev)
 {
+	int err;
+
 	ctx->jrdev = jrdev;
-	rng_create_sh_desc(ctx);
+
+	err = rng_create_sh_desc(ctx);
+	if (err)
+		return err;
+
 	ctx->current_buf = 0;
 	ctx->cur_buf_idx = 0;
-	caam_init_buf(ctx, 0);
-	caam_init_buf(ctx, 1);
+
+	err = caam_init_buf(ctx, 0);
+	if (err)
+		return err;
+
+	err = caam_init_buf(ctx, 1);
+	if (err)
+		return err;
+
+	return 0;
 }
 
 static struct hwrng caam_rng = {
@@ -278,6 +308,35 @@ static void __exit caam_rng_exit(void)
 static int __init caam_rng_init(void)
 {
 	struct device *dev;
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	void *priv;
+	int err;
+
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev) {
+		of_node_put(dev_node);
+		return -ENODEV;
+	}
+
+	ctrldev = &pdev->dev;
+	priv = dev_get_drvdata(ctrldev);
+	of_node_put(dev_node);
+
+	/*
+	 * If priv is NULL, it's probably because the caam driver wasn't
+	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+	 */
+	if (!priv)
+		return -ENODEV;
 
 	dev = caam_jr_alloc();
 	if (IS_ERR(dev)) {
@@ -287,7 +346,9 @@ static int __init caam_rng_init(void)
 	rng_ctx = kmalloc(sizeof(struct caam_rng_ctx), GFP_DMA);
 	if (!rng_ctx)
 		return -ENOMEM;
-	caam_init_rng(rng_ctx, dev);
+	err = caam_init_rng(rng_ctx, dev);
+	if (err)
+		return err;
 
 	dev_info(dev, "registering rng-caam\n");
 	return hwrng_register(&caam_rng);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/ctrl.c linux-libre-3.17-rc7-gnu/drivers/crypto/caam/ctrl.c
--- linux-libre-3.16-gnu/drivers/crypto/caam/ctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/ctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
  * Copyright 2008-2012 Freescale Semiconductor, Inc.
  */
 
+#include <linux/device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
@@ -87,6 +88,17 @@ static inline int run_descriptor_deco0(s
 
 	/* Set the bit to request direct access to DECO0 */
 	topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+
+	if (ctrlpriv->virt_en == 1) {
+		setbits32(&topregs->ctrl.deco_rsr, DECORSR_JR0);
+
+		while (!(rd_reg32(&topregs->ctrl.deco_rsr) & DECORSR_VALID) &&
+		       --timeout)
+			cpu_relax();
+
+		timeout = 100000;
+	}
+
 	setbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
 
 	while (!(rd_reg32(&topregs->ctrl.deco_rq) & DECORR_DEN0) &&
@@ -129,6 +141,9 @@ static inline int run_descriptor_deco0(s
 	*status = rd_reg32(&topregs->deco.op_status_hi) &
 		  DECO_OP_STATUS_HI_ERR_MASK;
 
+	if (ctrlpriv->virt_en == 1)
+		clrbits32(&topregs->ctrl.deco_rsr, DECORSR_JR0);
+
 	/* Mark the DECO as free */
 	clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
 
@@ -295,9 +310,6 @@ static int caam_remove(struct platform_d
 	/* Unmap controller region */
 	iounmap(&topregs->ctrl);
 
-	kfree(ctrlpriv->jrpdev);
-	kfree(ctrlpriv);
-
 	return ret;
 }
 
@@ -380,9 +392,11 @@ static int caam_probe(struct platform_de
 #ifdef CONFIG_DEBUG_FS
 	struct caam_perfmon *perfmon;
 #endif
-	u64 cha_vid;
+	u32 scfgr, comp_params;
+	u32 cha_vid_ls;
 
-	ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL);
+	ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(struct caam_drv_private),
+				GFP_KERNEL);
 	if (!ctrlpriv)
 		return -ENOMEM;
 
@@ -413,13 +427,40 @@ static int caam_probe(struct platform_de
 	setbits32(&topregs->ctrl.mcr, MCFGR_WDENABLE |
 		  (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
 
+	/*
+	 *  Read the Compile Time paramters and SCFGR to determine
+	 * if Virtualization is enabled for this platform
+	 */
+	comp_params = rd_reg32(&topregs->ctrl.perfmon.comp_parms_ms);
+	scfgr = rd_reg32(&topregs->ctrl.scfgr);
+
+	ctrlpriv->virt_en = 0;
+	if (comp_params & CTPR_MS_VIRT_EN_INCL) {
+		/* VIRT_EN_INCL = 1 & VIRT_EN_POR = 1 or
+		 * VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SCFGR_VIRT_EN = 1
+		 */
+		if ((comp_params & CTPR_MS_VIRT_EN_POR) ||
+		    (!(comp_params & CTPR_MS_VIRT_EN_POR) &&
+		       (scfgr & SCFGR_VIRT_EN)))
+				ctrlpriv->virt_en = 1;
+	} else {
+		/* VIRT_EN_INCL = 0 && VIRT_EN_POR_VALUE = 1 */
+		if (comp_params & CTPR_MS_VIRT_EN_POR)
+				ctrlpriv->virt_en = 1;
+	}
+
+	if (ctrlpriv->virt_en == 1)
+		setbits32(&topregs->ctrl.jrstart, JRSTART_JR0_START |
+			  JRSTART_JR1_START | JRSTART_JR2_START |
+			  JRSTART_JR3_START);
+
 	if (sizeof(dma_addr_t) == sizeof(u64))
 		if (of_device_is_compatible(nprop, "fsl,sec-v5.0"))
-			dma_set_mask(dev, DMA_BIT_MASK(40));
+			dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
 		else
-			dma_set_mask(dev, DMA_BIT_MASK(36));
+			dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
 	else
-		dma_set_mask(dev, DMA_BIT_MASK(32));
+		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
 
 	/*
 	 * Detect and enable JobRs
@@ -432,8 +473,9 @@ static int caam_probe(struct platform_de
 		    of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
 			rspec++;
 
-	ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
-								GFP_KERNEL);
+	ctrlpriv->jrpdev = devm_kzalloc(&pdev->dev,
+					sizeof(struct platform_device *) * rspec,
+					GFP_KERNEL);
 	if (ctrlpriv->jrpdev == NULL) {
 		iounmap(&topregs->ctrl);
 		return -ENOMEM;
@@ -456,8 +498,9 @@ static int caam_probe(struct platform_de
 		}
 
 	/* Check to see if QI present. If so, enable */
-	ctrlpriv->qi_present = !!(rd_reg64(&topregs->ctrl.perfmon.comp_parms) &
-				  CTPR_QI_MASK);
+	ctrlpriv->qi_present =
+			!!(rd_reg32(&topregs->ctrl.perfmon.comp_parms_ms) &
+			   CTPR_MS_QI_MASK);
 	if (ctrlpriv->qi_present) {
 		ctrlpriv->qi = (struct caam_queue_if __force *)&topregs->qi;
 		/* This is all that's required to physically enable QI */
@@ -471,13 +514,13 @@ static int caam_probe(struct platform_de
 		return -ENOMEM;
 	}
 
-	cha_vid = rd_reg64(&topregs->ctrl.perfmon.cha_id);
+	cha_vid_ls = rd_reg32(&topregs->ctrl.perfmon.cha_id_ls);
 
 	/*
 	 * If SEC has RNG version >= 4 and RNG state handle has not been
 	 * already instantiated, do RNG instantiation
 	 */
-	if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
+	if ((cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 4) {
 		ctrlpriv->rng4_sh_init =
 			rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
 		/*
@@ -531,7 +574,8 @@ static int caam_probe(struct platform_de
 
 	/* NOTE: RTIC detection ought to go here, around Si time */
 
-	caam_id = rd_reg64(&topregs->ctrl.perfmon.caam_id);
+	caam_id = (u64)rd_reg32(&topregs->ctrl.perfmon.caam_id_ms) << 32 |
+		  (u64)rd_reg32(&topregs->ctrl.perfmon.caam_id_ls);
 
 	/* Report "alive" for developer to see */
 	dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
@@ -547,7 +591,7 @@ static int caam_probe(struct platform_de
 	 */
 	perfmon = (struct caam_perfmon __force *)&ctrl->perfmon;
 
-	ctrlpriv->dfs_root = debugfs_create_dir("caam", NULL);
+	ctrlpriv->dfs_root = debugfs_create_dir(dev_name(dev), NULL);
 	ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root);
 
 	/* Controller-level - performance monitor counters */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/desc.h linux-libre-3.17-rc7-gnu/drivers/crypto/caam/desc.h
--- linux-libre-3.16-gnu/drivers/crypto/caam/desc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/desc.h	2014-09-28 17:29:07.000000000 -0400
@@ -321,7 +321,6 @@ struct sec4_sg_entry {
 /* Continue - Not the last FIFO store to come */
 #define FIFOST_CONT_SHIFT	23
 #define FIFOST_CONT_MASK	(1 << FIFOST_CONT_SHIFT)
-#define FIFOST_CONT_MASK	(1 << FIFOST_CONT_SHIFT)
 
 /*
  * Extended Length - use 32-bit extended length that
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/intern.h linux-libre-3.17-rc7-gnu/drivers/crypto/caam/intern.h
--- linux-libre-3.16-gnu/drivers/crypto/caam/intern.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/intern.h	2014-09-28 17:29:07.000000000 -0400
@@ -82,6 +82,7 @@ struct caam_drv_private {
 	u8 total_jobrs;		/* Total Job Rings in device */
 	u8 qi_present;		/* Nonzero if QI present in device */
 	int secvio_irq;		/* Security violation interrupt number */
+	int virt_en;		/* Virtualization enabled in CAAM */
 
 #define	RNG4_MAX_HANDLES 2
 	/* RNG4 block */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/jr.c linux-libre-3.17-rc7-gnu/drivers/crypto/caam/jr.c
--- linux-libre-3.16-gnu/drivers/crypto/caam/jr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/jr.c	2014-09-28 17:29:07.000000000 -0400
@@ -476,11 +476,11 @@ static int caam_jr_probe(struct platform
 
 	if (sizeof(dma_addr_t) == sizeof(u64))
 		if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring"))
-			dma_set_mask(jrdev, DMA_BIT_MASK(40));
+			dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(40));
 		else
-			dma_set_mask(jrdev, DMA_BIT_MASK(36));
+			dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(36));
 	else
-		dma_set_mask(jrdev, DMA_BIT_MASK(32));
+		dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(32));
 
 	/* Identify the interrupt */
 	jrpriv->irq = irq_of_parse_and_map(nprop, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/caam/regs.h linux-libre-3.17-rc7-gnu/drivers/crypto/caam/regs.h
--- linux-libre-3.16-gnu/drivers/crypto/caam/regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/caam/regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -84,6 +84,7 @@
 #endif
 
 #ifndef CONFIG_64BIT
+#ifdef __BIG_ENDIAN
 static inline void wr_reg64(u64 __iomem *reg, u64 data)
 {
 	wr_reg32((u32 __iomem *)reg, (data & 0xffffffff00000000ull) >> 32);
@@ -95,6 +96,21 @@ static inline u64 rd_reg64(u64 __iomem *
 	return (((u64)rd_reg32((u32 __iomem *)reg)) << 32) |
 		((u64)rd_reg32((u32 __iomem *)reg + 1));
 }
+#else
+#ifdef __LITTLE_ENDIAN
+static inline void wr_reg64(u64 __iomem *reg, u64 data)
+{
+	wr_reg32((u32 __iomem *)reg + 1, (data & 0xffffffff00000000ull) >> 32);
+	wr_reg32((u32 __iomem *)reg, data & 0x00000000ffffffffull);
+}
+
+static inline u64 rd_reg64(u64 __iomem *reg)
+{
+	return (((u64)rd_reg32((u32 __iomem *)reg + 1)) << 32) |
+		((u64)rd_reg32((u32 __iomem *)reg));
+}
+#endif
+#endif
 #endif
 
 /*
@@ -114,45 +130,45 @@ struct jr_outentry {
  */
 
 /* Number of DECOs */
-#define CHA_NUM_DECONUM_SHIFT	56
-#define CHA_NUM_DECONUM_MASK	(0xfull << CHA_NUM_DECONUM_SHIFT)
+#define CHA_NUM_MS_DECONUM_SHIFT	24
+#define CHA_NUM_MS_DECONUM_MASK	(0xfull << CHA_NUM_MS_DECONUM_SHIFT)
 
 /* CHA Version IDs */
-#define CHA_ID_AES_SHIFT	0
-#define CHA_ID_AES_MASK		(0xfull << CHA_ID_AES_SHIFT)
+#define CHA_ID_LS_AES_SHIFT	0
+#define CHA_ID_LS_AES_MASK		(0xfull << CHA_ID_LS_AES_SHIFT)
 
-#define CHA_ID_DES_SHIFT	4
-#define CHA_ID_DES_MASK		(0xfull << CHA_ID_DES_SHIFT)
+#define CHA_ID_LS_DES_SHIFT	4
+#define CHA_ID_LS_DES_MASK		(0xfull << CHA_ID_LS_DES_SHIFT)
 
-#define CHA_ID_ARC4_SHIFT	8
-#define CHA_ID_ARC4_MASK	(0xfull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_LS_ARC4_SHIFT	8
+#define CHA_ID_LS_ARC4_MASK	(0xfull << CHA_ID_LS_ARC4_SHIFT)
 
-#define CHA_ID_MD_SHIFT		12
-#define CHA_ID_MD_MASK		(0xfull << CHA_ID_MD_SHIFT)
+#define CHA_ID_LS_MD_SHIFT	12
+#define CHA_ID_LS_MD_MASK	(0xfull << CHA_ID_LS_MD_SHIFT)
 
-#define CHA_ID_RNG_SHIFT	16
-#define CHA_ID_RNG_MASK		(0xfull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_LS_RNG_SHIFT	16
+#define CHA_ID_LS_RNG_MASK	(0xfull << CHA_ID_LS_RNG_SHIFT)
 
-#define CHA_ID_SNW8_SHIFT	20
-#define CHA_ID_SNW8_MASK	(0xfull << CHA_ID_SNW8_SHIFT)
+#define CHA_ID_LS_SNW8_SHIFT	20
+#define CHA_ID_LS_SNW8_MASK	(0xfull << CHA_ID_LS_SNW8_SHIFT)
 
-#define CHA_ID_KAS_SHIFT	24
-#define CHA_ID_KAS_MASK		(0xfull << CHA_ID_KAS_SHIFT)
+#define CHA_ID_LS_KAS_SHIFT	24
+#define CHA_ID_LS_KAS_MASK	(0xfull << CHA_ID_LS_KAS_SHIFT)
 
-#define CHA_ID_PK_SHIFT		28
-#define CHA_ID_PK_MASK		(0xfull << CHA_ID_PK_SHIFT)
+#define CHA_ID_LS_PK_SHIFT	28
+#define CHA_ID_LS_PK_MASK	(0xfull << CHA_ID_LS_PK_SHIFT)
 
-#define CHA_ID_CRC_SHIFT	32
-#define CHA_ID_CRC_MASK		(0xfull << CHA_ID_CRC_SHIFT)
+#define CHA_ID_MS_CRC_SHIFT	0
+#define CHA_ID_MS_CRC_MASK	(0xfull << CHA_ID_MS_CRC_SHIFT)
 
-#define CHA_ID_SNW9_SHIFT	36
-#define CHA_ID_SNW9_MASK	(0xfull << CHA_ID_SNW9_SHIFT)
+#define CHA_ID_MS_SNW9_SHIFT	4
+#define CHA_ID_MS_SNW9_MASK	(0xfull << CHA_ID_MS_SNW9_SHIFT)
 
-#define CHA_ID_DECO_SHIFT	56
-#define CHA_ID_DECO_MASK	(0xfull << CHA_ID_DECO_SHIFT)
+#define CHA_ID_MS_DECO_SHIFT	24
+#define CHA_ID_MS_DECO_MASK	(0xfull << CHA_ID_MS_DECO_SHIFT)
 
-#define CHA_ID_JR_SHIFT		60
-#define CHA_ID_JR_MASK		(0xfull << CHA_ID_JR_SHIFT)
+#define CHA_ID_MS_JR_SHIFT	28
+#define CHA_ID_MS_JR_MASK	(0xfull << CHA_ID_MS_JR_SHIFT)
 
 struct sec_vid {
 	u16 ip_id;
@@ -172,10 +188,14 @@ struct caam_perfmon {
 	u64 rsvd[13];
 
 	/* CAAM Hardware Instantiation Parameters		fa0-fbf */
-	u64 cha_rev;		/* CRNR - CHA Revision Number		*/
-#define CTPR_QI_SHIFT		57
-#define CTPR_QI_MASK		(0x1ull << CTPR_QI_SHIFT)
-	u64 comp_parms;	/* CTPR - Compile Parameters Register	*/
+	u32 cha_rev_ms;		/* CRNR - CHA Rev No. Most significant half*/
+	u32 cha_rev_ls;		/* CRNR - CHA Rev No. Least significant half*/
+#define CTPR_MS_QI_SHIFT	25
+#define CTPR_MS_QI_MASK		(0x1ull << CTPR_MS_QI_SHIFT)
+#define CTPR_MS_VIRT_EN_INCL	0x00000001
+#define CTPR_MS_VIRT_EN_POR	0x00000002
+	u32 comp_parms_ms;	/* CTPR - Compile Parameters Register	*/
+	u32 comp_parms_ls;	/* CTPR - Compile Parameters Register	*/
 	u64 rsvd1[2];
 
 	/* CAAM Global Status					fc0-fdf */
@@ -189,9 +209,12 @@ struct caam_perfmon {
 	/* Component Instantiation Parameters			fe0-fff */
 	u32 rtic_id;		/* RVID - RTIC Version ID	*/
 	u32 ccb_id;		/* CCBVID - CCB Version ID	*/
-	u64 cha_id;		/* CHAVID - CHA Version ID	*/
-	u64 cha_num;		/* CHANUM - CHA Number		*/
-	u64 caam_id;		/* CAAMVID - CAAM Version ID	*/
+	u32 cha_id_ms;		/* CHAVID - CHA Version ID Most Significant*/
+	u32 cha_id_ls;		/* CHAVID - CHA Version ID Least Significant*/
+	u32 cha_num_ms;		/* CHANUM - CHA Number Most Significant	*/
+	u32 cha_num_ls;		/* CHANUM - CHA Number Least Significant*/
+	u32 caam_id_ms;		/* CAAMVID - CAAM Version ID MS	*/
+	u32 caam_id_ls;		/* CAAMVID - CAAM Version ID LS	*/
 };
 
 /* LIODN programming for DMA configuration */
@@ -304,9 +327,12 @@ struct caam_ctrl {
 	/* Bus Access Configuration Section			010-11f */
 	/* Read/Writable                                                */
 	struct masterid jr_mid[4];	/* JRxLIODNR - JobR LIODN setup */
-	u32 rsvd3[12];
+	u32 rsvd3[11];
+	u32 jrstart;			/* JRSTART - Job Ring Start Register */
 	struct masterid rtic_mid[4];	/* RTICxLIODNR - RTIC LIODN setup */
-	u32 rsvd4[7];
+	u32 rsvd4[5];
+	u32 deco_rsr;			/* DECORSR - Deco Request Source */
+	u32 rsvd11;
 	u32 deco_rq;			/* DECORR - DECO Request */
 	struct partid deco_mid[5];	/* DECOxLIODNR - 1 per DECO */
 	u32 rsvd5[22];
@@ -347,7 +373,10 @@ struct caam_ctrl {
 #define MCFGR_DMA_RESET		0x10000000
 #define MCFGR_LONG_PTR		0x00010000 /* Use >32-bit desc addressing */
 #define SCFGR_RDBENABLE		0x00000400
+#define SCFGR_VIRT_EN		0x00008000
 #define DECORR_RQD0ENABLE	0x00000001 /* Enable DECO0 for direct access */
+#define DECORSR_JR0		0x00000001 /* JR to supply TZ, SDID, ICID */
+#define DECORSR_VALID		0x80000000
 #define DECORR_DEN0		0x00010000 /* DECO0 available for access*/
 
 /* AXI read cache control */
@@ -365,6 +394,12 @@ struct caam_ctrl {
 #define MCFGR_AXIPRI		0x00000008 /* Assert AXI priority sideband */
 #define MCFGR_BURST_64		0x00000001 /* Max burst size */
 
+/* JRSTART register offsets */
+#define JRSTART_JR0_START       0x00000001 /* Start Job ring 0 */
+#define JRSTART_JR1_START       0x00000002 /* Start Job ring 1 */
+#define JRSTART_JR2_START       0x00000004 /* Start Job ring 2 */
+#define JRSTART_JR3_START       0x00000008 /* Start Job ring 3 */
+
 /*
  * caam_job_ring - direct job ring setup
  * 1-4 possible per instantiation, base + 1000/2000/3000/4000
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-crypto-main.c linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-crypto-main.c
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-crypto-main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-crypto-main.c	2014-09-28 17:29:07.000000000 -0400
@@ -367,6 +367,10 @@ static int ccp_crypto_init(void)
 {
 	int ret;
 
+	ret = ccp_present();
+	if (ret)
+		return ret;
+
 	spin_lock_init(&req_queue_lock);
 	INIT_LIST_HEAD(&req_queue.cmds);
 	req_queue.backlog = &req_queue.cmds;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-dev.c linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-dev.c
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,9 @@
 #include <linux/delay.h>
 #include <linux/hw_random.h>
 #include <linux/cpu.h>
+#ifdef CONFIG_X86
 #include <asm/cpu_device_id.h>
+#endif
 #include <linux/ccp.h>
 
 #include "ccp-dev.h"
@@ -53,6 +55,20 @@ static inline void ccp_del_device(struct
 }
 
 /**
+ * ccp_present - check if a CCP device is present
+ *
+ * Returns zero if a CCP device is present, -ENODEV otherwise.
+ */
+int ccp_present(void)
+{
+	if (ccp_get_device())
+		return 0;
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ccp_present);
+
+/**
  * ccp_enqueue_cmd - queue an operation for processing by the CCP
  *
  * @cmd: ccp_cmd struct to be processed
@@ -360,6 +376,12 @@ int ccp_init(struct ccp_device *ccp)
 		/* Build queue interrupt mask (two interrupts per queue) */
 		qim |= cmd_q->int_ok | cmd_q->int_err;
 
+#ifdef CONFIG_ARM64
+		/* For arm64 set the recommended queue cache settings */
+		iowrite32(ccp->axcache, ccp->io_regs + CMD_Q_CACHE_BASE +
+			  (CMD_Q_CACHE_INC * i));
+#endif
+
 		dev_dbg(dev, "queue #%u available\n", i);
 	}
 	if (ccp->cmd_q_count == 0) {
@@ -558,12 +580,15 @@ bool ccp_queues_suspended(struct ccp_dev
 }
 #endif
 
+#ifdef CONFIG_X86
 static const struct x86_cpu_id ccp_support[] = {
 	{ X86_VENDOR_AMD, 22, },
 };
+#endif
 
 static int __init ccp_mod_init(void)
 {
+#ifdef CONFIG_X86
 	struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
 	int ret;
 
@@ -589,12 +614,30 @@ static int __init ccp_mod_init(void)
 
 		break;
 	}
+#endif
+
+#ifdef CONFIG_ARM64
+	int ret;
+
+	ret = ccp_platform_init();
+	if (ret)
+		return ret;
+
+	/* Don't leave the driver loaded if init failed */
+	if (!ccp_get_device()) {
+		ccp_platform_exit();
+		return -ENODEV;
+	}
+
+	return 0;
+#endif
 
 	return -ENODEV;
 }
 
 static void __exit ccp_mod_exit(void)
 {
+#ifdef CONFIG_X86
 	struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
 
 	switch (cpuinfo->x86) {
@@ -602,6 +645,11 @@ static void __exit ccp_mod_exit(void)
 		ccp_pci_exit();
 		break;
 	}
+#endif
+
+#ifdef CONFIG_ARM64
+	ccp_platform_exit();
+#endif
 }
 
 module_init(ccp_mod_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-dev.h linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-dev.h
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-dev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-dev.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,6 @@
 #include <linux/hw_random.h>
 
 
-#define IO_OFFSET			0x20000
-
 #define MAX_DMAPOOL_NAME_LEN		32
 
 #define MAX_HW_QUEUES			5
@@ -32,6 +30,9 @@
 
 #define TRNG_RETRIES			10
 
+#define CACHE_NONE			0x00
+#define CACHE_WB_NO_ALLOC		0xb7
+
 
 /****** Register Mappings ******/
 #define Q_MASK_REG			0x000
@@ -50,7 +51,7 @@
 #define CMD_Q_INT_STATUS_BASE		0x214
 #define CMD_Q_STATUS_INCR		0x20
 
-#define CMD_Q_CACHE			0x228
+#define CMD_Q_CACHE_BASE		0x228
 #define CMD_Q_CACHE_INC			0x20
 
 #define CMD_Q_ERROR(__qs)		((__qs) & 0x0000003f);
@@ -194,6 +195,7 @@ struct ccp_device {
 	void *dev_specific;
 	int (*get_irq)(struct ccp_device *ccp);
 	void (*free_irq)(struct ccp_device *ccp);
+	unsigned int irq;
 
 	/*
 	 * I/O area used for device communication. The register mapping
@@ -254,12 +256,18 @@ struct ccp_device {
 	/* Suspend support */
 	unsigned int suspending;
 	wait_queue_head_t suspend_queue;
+
+	/* DMA caching attribute support */
+	unsigned int axcache;
 };
 
 
 int ccp_pci_init(void);
 void ccp_pci_exit(void);
 
+int ccp_platform_init(void);
+void ccp_platform_exit(void);
+
 struct ccp_device *ccp_alloc_struct(struct device *dev);
 int ccp_init(struct ccp_device *ccp);
 void ccp_destroy(struct ccp_device *ccp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-ops.c linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-ops.c
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-ops.c	2014-09-28 17:29:07.000000000 -0400
@@ -1606,7 +1606,7 @@ static int ccp_run_rsa_cmd(struct ccp_cm
 		goto e_ksb;
 
 	ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len, CCP_KSB_BYTES,
-				true);
+				false);
 	ret = ccp_copy_to_ksb(cmd_q, &exp, op.jobid, op.ksb_key,
 			      CCP_PASSTHRU_BYTESWAP_NOOP);
 	if (ret) {
@@ -1623,10 +1623,10 @@ static int ccp_run_rsa_cmd(struct ccp_cm
 		goto e_exp;
 
 	ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len, CCP_KSB_BYTES,
-				true);
+				false);
 	src.address += o_len;	/* Adjust the address for the copy operation */
 	ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len, CCP_KSB_BYTES,
-				true);
+				false);
 	src.address -= o_len;	/* Reset the address to original value */
 
 	/* Prepare the output area for the operation */
@@ -1841,20 +1841,20 @@ static int ccp_run_ecc_mm_cmd(struct ccp
 
 	/* Copy the ECC modulus */
 	ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
-				CCP_ECC_OPERAND_SIZE, true);
+				CCP_ECC_OPERAND_SIZE, false);
 	src.address += CCP_ECC_OPERAND_SIZE;
 
 	/* Copy the first operand */
 	ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1,
 				ecc->u.mm.operand_1_len,
-				CCP_ECC_OPERAND_SIZE, true);
+				CCP_ECC_OPERAND_SIZE, false);
 	src.address += CCP_ECC_OPERAND_SIZE;
 
 	if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) {
 		/* Copy the second operand */
 		ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2,
 					ecc->u.mm.operand_2_len,
-					CCP_ECC_OPERAND_SIZE, true);
+					CCP_ECC_OPERAND_SIZE, false);
 		src.address += CCP_ECC_OPERAND_SIZE;
 	}
 
@@ -1960,17 +1960,17 @@ static int ccp_run_ecc_pm_cmd(struct ccp
 
 	/* Copy the ECC modulus */
 	ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
-				CCP_ECC_OPERAND_SIZE, true);
+				CCP_ECC_OPERAND_SIZE, false);
 	src.address += CCP_ECC_OPERAND_SIZE;
 
 	/* Copy the first point X and Y coordinate */
 	ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x,
 				ecc->u.pm.point_1.x_len,
-				CCP_ECC_OPERAND_SIZE, true);
+				CCP_ECC_OPERAND_SIZE, false);
 	src.address += CCP_ECC_OPERAND_SIZE;
 	ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y,
 				ecc->u.pm.point_1.y_len,
-				CCP_ECC_OPERAND_SIZE, true);
+				CCP_ECC_OPERAND_SIZE, false);
 	src.address += CCP_ECC_OPERAND_SIZE;
 
 	/* Set the first point Z coordianate to 1 */
@@ -1981,11 +1981,11 @@ static int ccp_run_ecc_pm_cmd(struct ccp
 		/* Copy the second point X and Y coordinate */
 		ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x,
 					ecc->u.pm.point_2.x_len,
-					CCP_ECC_OPERAND_SIZE, true);
+					CCP_ECC_OPERAND_SIZE, false);
 		src.address += CCP_ECC_OPERAND_SIZE;
 		ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y,
 					ecc->u.pm.point_2.y_len,
-					CCP_ECC_OPERAND_SIZE, true);
+					CCP_ECC_OPERAND_SIZE, false);
 		src.address += CCP_ECC_OPERAND_SIZE;
 
 		/* Set the second point Z coordianate to 1 */
@@ -1995,14 +1995,14 @@ static int ccp_run_ecc_pm_cmd(struct ccp
 		/* Copy the Domain "a" parameter */
 		ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a,
 					ecc->u.pm.domain_a_len,
-					CCP_ECC_OPERAND_SIZE, true);
+					CCP_ECC_OPERAND_SIZE, false);
 		src.address += CCP_ECC_OPERAND_SIZE;
 
 		if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) {
 			/* Copy the scalar value */
 			ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar,
 						ecc->u.pm.scalar_len,
-						CCP_ECC_OPERAND_SIZE, true);
+						CCP_ECC_OPERAND_SIZE, false);
 			src.address += CCP_ECC_OPERAND_SIZE;
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-pci.c linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-pci.c
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,8 +12,10 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/device.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
+#include <linux/dma-mapping.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -24,6 +26,8 @@
 #include "ccp-dev.h"
 
 #define IO_BAR				2
+#define IO_OFFSET			0x20000
+
 #define MSIX_VECTORS			2
 
 struct ccp_msix {
@@ -89,7 +93,8 @@ static int ccp_get_msi_irq(struct ccp_de
 	if (ret)
 		return ret;
 
-	ret = request_irq(pdev->irq, ccp_irq_handler, 0, "ccp", dev);
+	ccp->irq = pdev->irq;
+	ret = request_irq(ccp->irq, ccp_irq_handler, 0, "ccp", dev);
 	if (ret) {
 		dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
 		goto e_msi;
@@ -136,7 +141,7 @@ static void ccp_free_irqs(struct ccp_dev
 				 dev);
 		pci_disable_msix(pdev);
 	} else {
-		free_irq(pdev->irq, dev);
+		free_irq(ccp->irq, dev);
 		pci_disable_msi(pdev);
 	}
 }
@@ -147,21 +152,12 @@ static int ccp_find_mmio_area(struct ccp
 	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
 	resource_size_t io_len;
 	unsigned long io_flags;
-	int bar;
 
 	io_flags = pci_resource_flags(pdev, IO_BAR);
 	io_len = pci_resource_len(pdev, IO_BAR);
 	if ((io_flags & IORESOURCE_MEM) && (io_len >= (IO_OFFSET + 0x800)))
 		return IO_BAR;
 
-	for (bar = 0; bar < PCI_STD_RESOURCE_END; bar++) {
-		io_flags = pci_resource_flags(pdev, bar);
-		io_len = pci_resource_len(pdev, bar);
-		if ((io_flags & IORESOURCE_MEM) &&
-		    (io_len >= (IO_OFFSET + 0x800)))
-			return bar;
-	}
-
 	return -EIO;
 }
 
@@ -214,20 +210,13 @@ static int ccp_pci_probe(struct pci_dev
 	}
 	ccp->io_regs = ccp->io_map + IO_OFFSET;
 
-	ret = dma_set_mask(dev, DMA_BIT_MASK(48));
-	if (ret == 0) {
-		ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(48));
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+	if (ret) {
+		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
 		if (ret) {
-			dev_err(dev,
-				"pci_set_consistent_dma_mask failed (%d)\n",
+			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
 				ret);
-			goto e_bar0;
-		}
-	} else {
-		ret = dma_set_mask(dev, DMA_BIT_MASK(32));
-		if (ret) {
-			dev_err(dev, "pci_set_dma_mask failed (%d)\n", ret);
-			goto e_bar0;
+			goto e_iomap;
 		}
 	}
 
@@ -235,13 +224,13 @@ static int ccp_pci_probe(struct pci_dev
 
 	ret = ccp_init(ccp);
 	if (ret)
-		goto e_bar0;
+		goto e_iomap;
 
 	dev_notice(dev, "enabled\n");
 
 	return 0;
 
-e_bar0:
+e_iomap:
 	pci_iounmap(pdev, ccp->io_map);
 
 e_device:
@@ -331,7 +320,7 @@ static int ccp_pci_resume(struct pci_dev
 }
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(ccp_pci_table) = {
+static const struct pci_device_id ccp_pci_table[] = {
 	{ PCI_VDEVICE(AMD, 0x1537), },
 	/* Last entry must be zero */
 	{ 0, }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-platform.c linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-platform.c
--- linux-libre-3.16-gnu/drivers/crypto/ccp/ccp-platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/ccp-platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,230 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ccp.h>
+#include <linux/of.h>
+
+#include "ccp-dev.h"
+
+
+static int ccp_get_irq(struct ccp_device *ccp)
+{
+	struct device *dev = ccp->dev;
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	int ret;
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+
+	ccp->irq = ret;
+	ret = request_irq(ccp->irq, ccp_irq_handler, 0, "ccp", dev);
+	if (ret) {
+		dev_notice(dev, "unable to allocate IRQ (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ccp_get_irqs(struct ccp_device *ccp)
+{
+	struct device *dev = ccp->dev;
+	int ret;
+
+	ret = ccp_get_irq(ccp);
+	if (!ret)
+		return 0;
+
+	/* Couldn't get an interrupt */
+	dev_notice(dev, "could not enable interrupts (%d)\n", ret);
+
+	return ret;
+}
+
+static void ccp_free_irqs(struct ccp_device *ccp)
+{
+	struct device *dev = ccp->dev;
+
+	free_irq(ccp->irq, dev);
+}
+
+static struct resource *ccp_find_mmio_area(struct ccp_device *ccp)
+{
+	struct device *dev = ccp->dev;
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	struct resource *ior;
+
+	ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (ior && (resource_size(ior) >= 0x800))
+		return ior;
+
+	return NULL;
+}
+
+static int ccp_platform_probe(struct platform_device *pdev)
+{
+	struct ccp_device *ccp;
+	struct device *dev = &pdev->dev;
+	struct resource *ior;
+	int ret;
+
+	ret = -ENOMEM;
+	ccp = ccp_alloc_struct(dev);
+	if (!ccp)
+		goto e_err;
+
+	ccp->dev_specific = NULL;
+	ccp->get_irq = ccp_get_irqs;
+	ccp->free_irq = ccp_free_irqs;
+
+	ior = ccp_find_mmio_area(ccp);
+	ccp->io_map = devm_ioremap_resource(dev, ior);
+	if (IS_ERR(ccp->io_map)) {
+		ret = PTR_ERR(ccp->io_map);
+		goto e_free;
+	}
+	ccp->io_regs = ccp->io_map;
+
+	if (!dev->dma_mask)
+		dev->dma_mask = &dev->coherent_dma_mask;
+	*(dev->dma_mask) = DMA_BIT_MASK(48);
+	dev->coherent_dma_mask = DMA_BIT_MASK(48);
+
+	if (of_property_read_bool(dev->of_node, "dma-coherent"))
+		ccp->axcache = CACHE_WB_NO_ALLOC;
+	else
+		ccp->axcache = CACHE_NONE;
+
+	dev_set_drvdata(dev, ccp);
+
+	ret = ccp_init(ccp);
+	if (ret)
+		goto e_free;
+
+	dev_notice(dev, "enabled\n");
+
+	return 0;
+
+e_free:
+	kfree(ccp);
+
+e_err:
+	dev_notice(dev, "initialization failed\n");
+	return ret;
+}
+
+static int ccp_platform_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ccp_device *ccp = dev_get_drvdata(dev);
+
+	ccp_destroy(ccp);
+
+	kfree(ccp);
+
+	dev_notice(dev, "disabled\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ccp_platform_suspend(struct platform_device *pdev,
+				pm_message_t state)
+{
+	struct device *dev = &pdev->dev;
+	struct ccp_device *ccp = dev_get_drvdata(dev);
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+	ccp->suspending = 1;
+
+	/* Wake all the queue kthreads to prepare for suspend */
+	for (i = 0; i < ccp->cmd_q_count; i++)
+		wake_up_process(ccp->cmd_q[i].kthread);
+
+	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+	/* Wait for all queue kthreads to say they're done */
+	while (!ccp_queues_suspended(ccp))
+		wait_event_interruptible(ccp->suspend_queue,
+					 ccp_queues_suspended(ccp));
+
+	return 0;
+}
+
+static int ccp_platform_resume(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ccp_device *ccp = dev_get_drvdata(dev);
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+	ccp->suspending = 0;
+
+	/* Wake up all the kthreads */
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		ccp->cmd_q[i].suspended = 0;
+		wake_up_process(ccp->cmd_q[i].kthread);
+	}
+
+	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+	return 0;
+}
+#endif
+
+static const struct of_device_id ccp_platform_ids[] = {
+	{ .compatible = "amd,ccp-seattle-v1a" },
+	{ },
+};
+
+static struct platform_driver ccp_platform_driver = {
+	.driver = {
+		.name = "AMD Cryptographic Coprocessor",
+		.owner = THIS_MODULE,
+		.of_match_table = ccp_platform_ids,
+	},
+	.probe = ccp_platform_probe,
+	.remove = ccp_platform_remove,
+#ifdef CONFIG_PM
+	.suspend = ccp_platform_suspend,
+	.resume = ccp_platform_resume,
+#endif
+};
+
+int ccp_platform_init(void)
+{
+	return platform_driver_register(&ccp_platform_driver);
+}
+
+void ccp_platform_exit(void)
+{
+	platform_driver_unregister(&ccp_platform_driver);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ccp/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/ccp/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ccp/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,11 @@
 obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
 ccp-objs := ccp-dev.o ccp-ops.o
+ifdef CONFIG_X86
 ccp-objs += ccp-pci.o
+endif
+ifdef CONFIG_ARM64
+ccp-objs += ccp-platform.o
+endif
 
 obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
 ccp-crypto-objs := ccp-crypto-main.o \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/hifn_795x.c linux-libre-3.17-rc7-gnu/drivers/crypto/hifn_795x.c
--- linux-libre-3.16-gnu/drivers/crypto/hifn_795x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/hifn_795x.c	2014-09-28 17:29:07.000000000 -0400
@@ -2617,14 +2617,13 @@ static int hifn_probe(struct pci_dev *pd
 		}
 	}
 
-	dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma),
-			&dev->desc_dma);
+	dev->desc_virt = pci_zalloc_consistent(pdev, sizeof(struct hifn_dma),
+					       &dev->desc_dma);
 	if (!dev->desc_virt) {
 		dprintk("Failed to allocate descriptor rings.\n");
 		err = -ENOMEM;
 		goto err_out_unmap_bars;
 	}
-	memset(dev->desc_virt, 0, sizeof(struct hifn_dma));
 
 	dev->pdev = pdev;
 	dev->irq = pdev->irq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/Kconfig linux-libre-3.17-rc7-gnu/drivers/crypto/Kconfig
--- linux-libre-3.16-gnu/drivers/crypto/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -391,7 +391,7 @@ config CRYPTO_DEV_ATMEL_SHA
 
 config CRYPTO_DEV_CCP
 	bool "Support for AMD Cryptographic Coprocessor"
-	depends on X86 && PCI
+	depends on (X86 && PCI) || ARM64
 	default n
 	help
 	  The AMD Cryptographic Coprocessor provides hardware support
@@ -418,4 +418,22 @@ config CRYPTO_DEV_MXS_DCP
 	  To compile this driver as a module, choose M here: the module
 	  will be called mxs-dcp.
 
+source "drivers/crypto/qat/Kconfig"
+
+config CRYPTO_DEV_QCE
+	tristate "Qualcomm crypto engine accelerator"
+	depends on (ARCH_QCOM || COMPILE_TEST) && HAS_DMA && HAS_IOMEM
+	select CRYPTO_AES
+	select CRYPTO_DES
+	select CRYPTO_ECB
+	select CRYPTO_CBC
+	select CRYPTO_XTS
+	select CRYPTO_CTR
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  This driver supports Qualcomm crypto engine accelerator
+	  hardware. To compile this driver as a module, choose M here. The
+	  module will be called qcrypto.
+
 endif # CRYPTO_HW
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -23,3 +23,5 @@ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.
 obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
 obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
 obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
+obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/nx/nx-842.c linux-libre-3.17-rc7-gnu/drivers/crypto/nx/nx-842.c
--- linux-libre-3.16-gnu/drivers/crypto/nx/nx-842.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/nx/nx-842.c	2014-09-28 17:29:07.000000000 -0400
@@ -936,28 +936,14 @@ static int nx842_OF_upd(struct property
 		goto error_out;
 	}
 
-	/* Set ptr to new property if provided */
-	if (new_prop) {
-		/* Single property */
-		if (!strncmp(new_prop->name, "status", new_prop->length)) {
-			status = new_prop;
-
-		} else if (!strncmp(new_prop->name, "ibm,max-sg-len",
-					new_prop->length)) {
-			maxsglen = new_prop;
-
-		} else if (!strncmp(new_prop->name, "ibm,max-sync-cop",
-					new_prop->length)) {
-			maxsyncop = new_prop;
-
-		} else {
-			/*
-			 * Skip the update, the property being updated
-			 * has no impact.
-			 */
-			goto out;
-		}
-	}
+	/*
+	 * If this is a property update, there are only certain properties that
+	 * we care about. Bail if it isn't in the below list
+	 */
+	if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) ||
+		         strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) ||
+		         strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length)))
+		goto out;
 
 	/* Perform property updates */
 	ret = nx842_OF_upd_status(new_devdata, status);
@@ -1247,7 +1233,7 @@ static struct vio_device_id nx842_driver
 static struct vio_driver nx842_driver = {
 	.name = MODULE_NAME,
 	.probe = nx842_probe,
-	.remove = nx842_remove,
+	.remove = __exit_p(nx842_remove),
 	.get_desired_dma = nx842_get_desired_dma,
 	.id_table = nx842_driver_ids,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/Kconfig linux-libre-3.17-rc7-gnu/drivers/crypto/qat/Kconfig
--- linux-libre-3.16-gnu/drivers/crypto/qat/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,23 @@
+config CRYPTO_DEV_QAT
+	tristate
+	select CRYPTO_AEAD
+	select CRYPTO_AUTHENC
+	select CRYPTO_ALGAPI
+	select CRYPTO_AES
+	select CRYPTO_CBC
+	select CRYPTO_SHA1
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	select FW_LOADER
+
+config CRYPTO_DEV_QAT_DH895xCC
+	tristate "Support for Intel(R) DH895xCC"
+	depends on X86 && PCI
+	default n
+	select CRYPTO_DEV_QAT
+	help
+	  Support for Intel(R) DH895xcc with Intel(R) QuickAssist Technology
+	  for accelerating crypto and compression workloads.
+
+	  To compile this as a module, choose M here: the module
+	  will be called qat_dh895xcc.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/qat/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/qat/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_QAT) += qat_common/
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,205 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_ACCEL_DEVICES_H_
+#define ADF_ACCEL_DEVICES_H_
+#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/io.h>
+#include "adf_cfg_common.h"
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define ADF_DH895XCC_DEVICE_NAME "dh895xcc"
+#define ADF_DH895XCC_PCI_DEVICE_ID 0x435
+#define ADF_DH895XCC_PMISC_BAR 1
+#define ADF_DH895XCC_ETR_BAR 2
+#define ADF_PCI_MAX_BARS 3
+#define ADF_DEVICE_NAME_LENGTH 32
+#define ADF_ETR_MAX_RINGS_PER_BANK 16
+#define ADF_MAX_MSIX_VECTOR_NAME 16
+#define ADF_DEVICE_NAME_PREFIX "qat_"
+
+enum adf_accel_capabilities {
+	ADF_ACCEL_CAPABILITIES_NULL = 0,
+	ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = 1,
+	ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = 2,
+	ADF_ACCEL_CAPABILITIES_CIPHER = 4,
+	ADF_ACCEL_CAPABILITIES_AUTHENTICATION = 8,
+	ADF_ACCEL_CAPABILITIES_COMPRESSION = 32,
+	ADF_ACCEL_CAPABILITIES_LZS_COMPRESSION = 64,
+	ADF_ACCEL_CAPABILITIES_RANDOM_NUMBER = 128
+};
+
+struct adf_bar {
+	resource_size_t base_addr;
+	void __iomem *virt_addr;
+	resource_size_t size;
+} __packed;
+
+struct adf_accel_msix {
+	struct msix_entry *entries;
+	char **names;
+} __packed;
+
+struct adf_accel_pci {
+	struct pci_dev *pci_dev;
+	struct adf_accel_msix msix_entries;
+	struct adf_bar pci_bars[ADF_PCI_MAX_BARS];
+	uint8_t revid;
+	uint8_t sku;
+} __packed;
+
+enum dev_state {
+	DEV_DOWN = 0,
+	DEV_UP
+};
+
+enum dev_sku_info {
+	DEV_SKU_1 = 0,
+	DEV_SKU_2,
+	DEV_SKU_3,
+	DEV_SKU_4,
+	DEV_SKU_UNKNOWN,
+};
+
+static inline const char *get_sku_info(enum dev_sku_info info)
+{
+	switch (info) {
+	case DEV_SKU_1:
+		return "SKU1";
+	case DEV_SKU_2:
+		return "SKU2";
+	case DEV_SKU_3:
+		return "SKU3";
+	case DEV_SKU_4:
+		return "SKU4";
+	case DEV_SKU_UNKNOWN:
+	default:
+		break;
+	}
+	return "Unknown SKU";
+}
+
+struct adf_hw_device_class {
+	const char *name;
+	const enum adf_device_type type;
+	uint32_t instances;
+} __packed;
+
+struct adf_cfg_device_data;
+struct adf_accel_dev;
+struct adf_etr_data;
+struct adf_etr_ring_data;
+
+struct adf_hw_device_data {
+	struct adf_hw_device_class *dev_class;
+	uint32_t (*get_accel_mask)(uint32_t fuse);
+	uint32_t (*get_ae_mask)(uint32_t fuse);
+	uint32_t (*get_misc_bar_id)(struct adf_hw_device_data *self);
+	uint32_t (*get_etr_bar_id)(struct adf_hw_device_data *self);
+	uint32_t (*get_num_aes)(struct adf_hw_device_data *self);
+	uint32_t (*get_num_accels)(struct adf_hw_device_data *self);
+	enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self);
+	void (*hw_arb_ring_enable)(struct adf_etr_ring_data *ring);
+	void (*hw_arb_ring_disable)(struct adf_etr_ring_data *ring);
+	int (*alloc_irq)(struct adf_accel_dev *accel_dev);
+	void (*free_irq)(struct adf_accel_dev *accel_dev);
+	void (*enable_error_correction)(struct adf_accel_dev *accel_dev);
+	const char *fw_name;
+	uint32_t pci_dev_id;
+	uint32_t fuses;
+	uint32_t accel_capabilities_mask;
+	uint16_t accel_mask;
+	uint16_t ae_mask;
+	uint16_t tx_rings_mask;
+	uint8_t tx_rx_gap;
+	uint8_t instance_id;
+	uint8_t num_banks;
+	uint8_t num_accel;
+	uint8_t num_logical_accel;
+	uint8_t num_engines;
+} __packed;
+
+/* CSR write macro */
+#define ADF_CSR_WR(csr_base, csr_offset, val) \
+	__raw_writel(val, csr_base + csr_offset)
+
+/* CSR read macro */
+#define ADF_CSR_RD(csr_base, csr_offset) __raw_readl(csr_base + csr_offset)
+
+#define GET_DEV(accel_dev) ((accel_dev)->accel_pci_dev.pci_dev->dev)
+#define GET_BARS(accel_dev) ((accel_dev)->accel_pci_dev.pci_bars)
+#define GET_HW_DATA(accel_dev) (accel_dev->hw_device)
+#define GET_MAX_BANKS(accel_dev) (GET_HW_DATA(accel_dev)->num_banks)
+#define GET_MAX_ACCELENGINES(accel_dev) (GET_HW_DATA(accel_dev)->num_engines)
+#define accel_to_pci_dev(accel_ptr) accel_ptr->accel_pci_dev.pci_dev
+
+struct adf_admin_comms;
+struct icp_qat_fw_loader_handle;
+struct adf_fw_loader_data {
+	struct icp_qat_fw_loader_handle *fw_loader;
+	const struct firmware *uof_fw;
+};
+
+struct adf_accel_dev {
+	struct adf_etr_data *transport;
+	struct adf_hw_device_data *hw_device;
+	struct adf_cfg_device_data *cfg;
+	struct adf_fw_loader_data *fw_loader;
+	struct adf_admin_comms *admin;
+	struct list_head crypto_list;
+	unsigned long status;
+	atomic_t ref_count;
+	struct dentry *debugfs_dir;
+	struct list_head list;
+	struct module *owner;
+	uint8_t accel_id;
+	uint8_t numa_node;
+	struct adf_accel_pci accel_pci_dev;
+} __packed;
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_accel_engine.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_accel_engine.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_accel_engine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_accel_engine.c	2014-09-28 21:26:12.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include "adf_cfg.h"
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_uclo.h"
+
+int adf_ae_fw_load(struct adf_accel_dev *accel_dev)
+{
+	struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+	void *uof_addr;
+	uint32_t uof_size;
+
+	if (reject_firmware(&loader_data->uof_fw, hw_device->fw_name,
+			     &accel_dev->accel_pci_dev.pci_dev->dev)) {
+		pr_err("QAT: Failed to load firmware %s\n", hw_device->fw_name);
+		return -EFAULT;
+	}
+
+	uof_size = loader_data->uof_fw->size;
+	uof_addr = (void *)loader_data->uof_fw->data;
+	if (qat_uclo_map_uof_obj(loader_data->fw_loader, uof_addr, uof_size)) {
+		pr_err("QAT: Failed to map UOF\n");
+		goto out_err;
+	}
+	if (qat_uclo_wr_all_uimage(loader_data->fw_loader)) {
+		pr_err("QAT: Failed to map UOF\n");
+		goto out_err;
+	}
+	return 0;
+
+out_err:
+	release_firmware(loader_data->uof_fw);
+	return -EFAULT;
+}
+
+int adf_ae_fw_release(struct adf_accel_dev *accel_dev)
+{
+	struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+
+	release_firmware(loader_data->uof_fw);
+	qat_uclo_del_uof_obj(loader_data->fw_loader);
+	qat_hal_deinit(loader_data->fw_loader);
+	loader_data->fw_loader = NULL;
+	return 0;
+}
+
+int adf_ae_start(struct adf_accel_dev *accel_dev)
+{
+	struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
+
+	for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
+		if (hw_data->ae_mask & (1 << ae)) {
+			qat_hal_start(loader_data->fw_loader, ae, 0xFF);
+			ae_ctr++;
+		}
+	}
+	pr_info("QAT: qat_dev%d started %d acceleration engines\n",
+		accel_dev->accel_id, ae_ctr);
+	return 0;
+}
+
+int adf_ae_stop(struct adf_accel_dev *accel_dev)
+{
+	struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
+
+	for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
+		if (hw_data->ae_mask & (1 << ae)) {
+			qat_hal_stop(loader_data->fw_loader, ae, 0xFF);
+			ae_ctr++;
+		}
+	}
+	pr_info("QAT: qat_dev%d stopped %d acceleration engines\n",
+		accel_dev->accel_id, ae_ctr);
+	return 0;
+}
+
+static int adf_ae_reset(struct adf_accel_dev *accel_dev, int ae)
+{
+	struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+
+	qat_hal_reset(loader_data->fw_loader);
+	if (qat_hal_clr_reset(loader_data->fw_loader))
+		return -EFAULT;
+
+	return 0;
+}
+
+int adf_ae_init(struct adf_accel_dev *accel_dev)
+{
+	struct adf_fw_loader_data *loader_data;
+
+	loader_data = kzalloc(sizeof(*loader_data), GFP_KERNEL);
+	if (!loader_data)
+		return -ENOMEM;
+
+	accel_dev->fw_loader = loader_data;
+	if (qat_hal_init(accel_dev)) {
+		pr_err("QAT: Failed to init the AEs\n");
+		kfree(loader_data);
+		return -EFAULT;
+	}
+	if (adf_ae_reset(accel_dev, 0)) {
+		pr_err("QAT: Failed to reset the AEs\n");
+		qat_hal_deinit(loader_data->fw_loader);
+		kfree(loader_data);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+int adf_ae_shutdown(struct adf_accel_dev *accel_dev)
+{
+	kfree(accel_dev->fw_loader);
+	accel_dev->fw_loader = NULL;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_aer.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_aer.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_aer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_aer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,259 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+
+static struct workqueue_struct *device_reset_wq;
+
+static pci_ers_result_t adf_error_detected(struct pci_dev *pdev,
+					   pci_channel_state_t state)
+{
+	struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+	pr_info("QAT: Acceleration driver hardware error detected.\n");
+	if (!accel_dev) {
+		pr_err("QAT: Can't find acceleration device\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	if (state == pci_channel_io_perm_failure) {
+		pr_err("QAT: Can't recover from device error\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/* reset dev data */
+struct adf_reset_dev_data {
+	int mode;
+	struct adf_accel_dev *accel_dev;
+	struct completion compl;
+	struct work_struct reset_work;
+};
+
+#define PPDSTAT_OFFSET 0x7E
+static void adf_dev_restore(struct adf_accel_dev *accel_dev)
+{
+	struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+	struct pci_dev *parent = pdev->bus->self;
+	uint16_t ppdstat = 0, bridge_ctl = 0;
+	int pending = 0;
+
+	pr_info("QAT: Reseting device qat_dev%d\n", accel_dev->accel_id);
+	pci_read_config_word(pdev, PPDSTAT_OFFSET, &ppdstat);
+	pending = ppdstat & PCI_EXP_DEVSTA_TRPND;
+	if (pending) {
+		int ctr = 0;
+
+		do {
+			msleep(100);
+			pci_read_config_word(pdev, PPDSTAT_OFFSET, &ppdstat);
+			pending = ppdstat & PCI_EXP_DEVSTA_TRPND;
+		} while (pending && ctr++ < 10);
+	}
+
+	if (pending)
+		pr_info("QAT: Transaction still in progress. Proceeding\n");
+
+	pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &bridge_ctl);
+	bridge_ctl |= PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
+	msleep(100);
+	bridge_ctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
+	msleep(100);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
+}
+
+static void adf_device_reset_worker(struct work_struct *work)
+{
+	struct adf_reset_dev_data *reset_data =
+		  container_of(work, struct adf_reset_dev_data, reset_work);
+	struct adf_accel_dev *accel_dev = reset_data->accel_dev;
+
+	adf_dev_restarting_notify(accel_dev);
+	adf_dev_stop(accel_dev);
+	adf_dev_restore(accel_dev);
+	if (adf_dev_start(accel_dev)) {
+		/* The device hanged and we can't restart it so stop here */
+		dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
+		kfree(reset_data);
+		WARN(1, "QAT: device restart failed. Device is unusable\n");
+		return;
+	}
+	adf_dev_restarted_notify(accel_dev);
+	clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+
+	/* The dev is back alive. Notify the caller if in sync mode */
+	if (reset_data->mode == ADF_DEV_RESET_SYNC)
+		complete(&reset_data->compl);
+	else
+		kfree(reset_data);
+}
+
+static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
+				      enum adf_dev_reset_mode mode)
+{
+	struct adf_reset_dev_data *reset_data;
+
+	if (adf_dev_started(accel_dev) &&
+	    !test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
+		return 0;
+
+	set_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+	reset_data = kzalloc(sizeof(*reset_data), GFP_ATOMIC);
+	if (!reset_data)
+		return -ENOMEM;
+	reset_data->accel_dev = accel_dev;
+	init_completion(&reset_data->compl);
+	reset_data->mode = mode;
+	INIT_WORK(&reset_data->reset_work, adf_device_reset_worker);
+	queue_work(device_reset_wq, &reset_data->reset_work);
+
+	/* If in sync mode wait for the result */
+	if (mode == ADF_DEV_RESET_SYNC) {
+		int ret = 0;
+		/* Maximum device reset time is 10 seconds */
+		unsigned long wait_jiffies = msecs_to_jiffies(10000);
+		unsigned long timeout = wait_for_completion_timeout(
+				   &reset_data->compl, wait_jiffies);
+		if (!timeout) {
+			pr_err("QAT: Reset device timeout expired\n");
+			ret = -EFAULT;
+		}
+		kfree(reset_data);
+		return ret;
+	}
+	return 0;
+}
+
+static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev)
+{
+	struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+	if (!accel_dev) {
+		pr_err("QAT: Can't find acceleration device\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_cleanup_aer_uncorrect_error_status(pdev);
+	if (adf_dev_aer_schedule_reset(accel_dev, ADF_DEV_RESET_SYNC))
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void adf_resume(struct pci_dev *pdev)
+{
+	pr_info("QAT: Acceleration driver reset completed\n");
+	pr_info("QAT: Device is up and runnig\n");
+}
+
+static struct pci_error_handlers adf_err_handler = {
+	.error_detected = adf_error_detected,
+	.slot_reset = adf_slot_reset,
+	.resume = adf_resume,
+};
+
+/**
+ * adf_enable_aer() - Enable Advance Error Reporting for acceleration device
+ * @accel_dev:  Pointer to acceleration device.
+ * @adf:        PCI device driver owning the given acceleration device.
+ *
+ * Function enables PCI Advance Error Reporting for the
+ * QAT acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf)
+{
+	struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+	adf->err_handler = &adf_err_handler;
+	pci_enable_pcie_error_reporting(pdev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_enable_aer);
+
+/**
+ * adf_disable_aer() - Enable Advance Error Reporting for acceleration device
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function disables PCI Advance Error Reporting for the
+ * QAT acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_disable_aer(struct adf_accel_dev *accel_dev)
+{
+	struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+	pci_disable_pcie_error_reporting(pdev);
+}
+EXPORT_SYMBOL_GPL(adf_disable_aer);
+
+int adf_init_aer(void)
+{
+	device_reset_wq = create_workqueue("qat_device_reset_wq");
+	return (device_reset_wq == NULL) ? -EFAULT : 0;
+}
+
+void adf_exit_aer(void)
+{
+	if (device_reset_wq)
+		destroy_workqueue(device_reset_wq);
+	device_reset_wq = NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,361 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg.h"
+
+static DEFINE_MUTEX(qat_cfg_read_lock);
+
+static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
+{
+	struct adf_cfg_device_data *dev_cfg = sfile->private;
+
+	mutex_lock(&qat_cfg_read_lock);
+	return seq_list_start(&dev_cfg->sec_list, *pos);
+}
+
+static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
+{
+	struct list_head *list;
+	struct adf_cfg_section *sec =
+				list_entry(v, struct adf_cfg_section, list);
+
+	seq_printf(sfile, "[%s]\n", sec->name);
+	list_for_each(list, &sec->param_head) {
+		struct adf_cfg_key_val *ptr =
+			list_entry(list, struct adf_cfg_key_val, list);
+		seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
+	}
+	return 0;
+}
+
+static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+	struct adf_cfg_device_data *dev_cfg = sfile->private;
+
+	return seq_list_next(v, &dev_cfg->sec_list, pos);
+}
+
+static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
+{
+	mutex_unlock(&qat_cfg_read_lock);
+}
+
+static const struct seq_operations qat_dev_cfg_sops = {
+	.start = qat_dev_cfg_start,
+	.next = qat_dev_cfg_next,
+	.stop = qat_dev_cfg_stop,
+	.show = qat_dev_cfg_show
+};
+
+static int qat_dev_cfg_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &qat_dev_cfg_sops);
+
+	if (!ret) {
+		struct seq_file *seq_f = file->private_data;
+
+		seq_f->private = inode->i_private;
+	}
+	return ret;
+}
+
+static const struct file_operations qat_dev_cfg_fops = {
+	.open = qat_dev_cfg_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release
+};
+
+/**
+ * adf_cfg_dev_add() - Create an acceleration device configuration table.
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function creates a configuration table for the given acceleration device.
+ * The table stores device specific config values.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
+{
+	struct adf_cfg_device_data *dev_cfg_data;
+
+	dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
+	if (!dev_cfg_data)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&dev_cfg_data->sec_list);
+	init_rwsem(&dev_cfg_data->lock);
+	accel_dev->cfg = dev_cfg_data;
+
+	/* accel_dev->debugfs_dir should always be non-NULL here */
+	dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
+						  accel_dev->debugfs_dir,
+						  dev_cfg_data,
+						  &qat_dev_cfg_fops);
+	if (!dev_cfg_data->debug) {
+		pr_err("QAT: Failed to create qat cfg debugfs entry.\n");
+		kfree(dev_cfg_data);
+		accel_dev->cfg = NULL;
+		return -EFAULT;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
+
+static void adf_cfg_section_del_all(struct list_head *head);
+
+void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
+{
+	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+	down_write(&dev_cfg_data->lock);
+	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
+	up_write(&dev_cfg_data->lock);
+}
+
+/**
+ * adf_cfg_dev_remove() - Clears acceleration device configuration table.
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function removes configuration table from the given acceleration device
+ * and frees all allocated memory.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
+{
+	struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+	down_write(&dev_cfg_data->lock);
+	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
+	up_write(&dev_cfg_data->lock);
+	debugfs_remove(dev_cfg_data->debug);
+	kfree(dev_cfg_data);
+	accel_dev->cfg = NULL;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
+
+static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
+			       struct adf_cfg_section *sec)
+{
+	list_add_tail(&new->list, &sec->param_head);
+}
+
+static void adf_cfg_keyval_del_all(struct list_head *head)
+{
+	struct list_head *list_ptr, *tmp;
+
+	list_for_each_prev_safe(list_ptr, tmp, head) {
+		struct adf_cfg_key_val *ptr =
+			list_entry(list_ptr, struct adf_cfg_key_val, list);
+		list_del(list_ptr);
+		kfree(ptr);
+	}
+}
+
+static void adf_cfg_section_del_all(struct list_head *head)
+{
+	struct adf_cfg_section *ptr;
+	struct list_head *list, *tmp;
+
+	list_for_each_prev_safe(list, tmp, head) {
+		ptr = list_entry(list, struct adf_cfg_section, list);
+		adf_cfg_keyval_del_all(&ptr->param_head);
+		list_del(list);
+		kfree(ptr);
+	}
+}
+
+static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
+						      const char *key)
+{
+	struct list_head *list;
+
+	list_for_each(list, &s->param_head) {
+		struct adf_cfg_key_val *ptr =
+			list_entry(list, struct adf_cfg_key_val, list);
+		if (!strcmp(ptr->key, key))
+			return ptr;
+	}
+	return NULL;
+}
+
+static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
+						const char *sec_name)
+{
+	struct adf_cfg_device_data *cfg = accel_dev->cfg;
+	struct list_head *list;
+
+	list_for_each(list, &cfg->sec_list) {
+		struct adf_cfg_section *ptr =
+			list_entry(list, struct adf_cfg_section, list);
+		if (!strcmp(ptr->name, sec_name))
+			return ptr;
+	}
+	return NULL;
+}
+
+static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
+			       const char *sec_name,
+			       const char *key_name,
+			       char *val)
+{
+	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
+	struct adf_cfg_key_val *keyval = NULL;
+
+	if (sec)
+		keyval = adf_cfg_key_value_find(sec, key_name);
+	if (keyval) {
+		memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
+		return 0;
+	}
+	return -1;
+}
+
+/**
+ * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
+ * @accel_dev:  Pointer to acceleration device.
+ * @section_name: Name of the section where the param will be added
+ * @key: The key string
+ * @val: Value pain for the given @key
+ * @type: Type - string, int or address
+ *
+ * Function adds configuration key - value entry in the appropriate section
+ * in the given acceleration device
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
+				const char *section_name,
+				const char *key, const void *val,
+				enum adf_cfg_val_type type)
+{
+	struct adf_cfg_device_data *cfg = accel_dev->cfg;
+	struct adf_cfg_key_val *key_val;
+	struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
+							   section_name);
+	if (!section)
+		return -EFAULT;
+
+	key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
+	if (!key_val)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&key_val->list);
+	strlcpy(key_val->key, key, sizeof(key_val->key));
+
+	if (type == ADF_DEC) {
+		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
+			 "%ld", (*((long *)val)));
+	} else if (type == ADF_STR) {
+		strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
+	} else if (type == ADF_HEX) {
+		snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
+			 "0x%lx", (unsigned long)val);
+	} else {
+		pr_err("QAT: Unknown type given.\n");
+		kfree(key_val);
+		return -1;
+	}
+	key_val->type = type;
+	down_write(&cfg->lock);
+	adf_cfg_keyval_add(key_val, section);
+	up_write(&cfg->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
+
+/**
+ * adf_cfg_section_add() - Add config section entry to config table.
+ * @accel_dev:  Pointer to acceleration device.
+ * @name: Name of the section
+ *
+ * Function adds configuration section where key - value entries
+ * will be stored.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
+{
+	struct adf_cfg_device_data *cfg = accel_dev->cfg;
+	struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
+
+	if (sec)
+		return 0;
+
+	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
+	if (!sec)
+		return -ENOMEM;
+
+	strlcpy(sec->name, name, sizeof(sec->name));
+	INIT_LIST_HEAD(&sec->param_head);
+	down_write(&cfg->lock);
+	list_add_tail(&sec->list, &cfg->sec_list);
+	up_write(&cfg->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_section_add);
+
+int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
+			    const char *section, const char *name,
+			    char *value)
+{
+	struct adf_cfg_device_data *cfg = accel_dev->cfg;
+	int ret;
+
+	down_read(&cfg->lock);
+	ret = adf_cfg_key_val_get(accel_dev, section, name, value);
+	up_read(&cfg->lock);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_common.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_common.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_common.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_CFG_COMMON_H_
+#define ADF_CFG_COMMON_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define ADF_CFG_MAX_STR_LEN 64
+#define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_BASE_DEC 10
+#define ADF_CFG_BASE_HEX 16
+#define ADF_CFG_ALL_DEVICES 0xFE
+#define ADF_CFG_NO_DEVICE 0xFF
+#define ADF_CFG_AFFINITY_WHATEVER 0xFF
+#define MAX_DEVICE_NAME_SIZE 32
+#define ADF_MAX_DEVICES 32
+
+enum adf_cfg_val_type {
+	ADF_DEC,
+	ADF_HEX,
+	ADF_STR
+};
+
+enum adf_device_type {
+	DEV_UNKNOWN = 0,
+	DEV_DH895XCC,
+};
+
+struct adf_dev_status_info {
+	enum adf_device_type type;
+	uint8_t accel_id;
+	uint8_t instance_id;
+	uint8_t num_ae;
+	uint8_t num_accel;
+	uint8_t num_logical_accel;
+	uint8_t banks_per_accel;
+	uint8_t state;
+	uint8_t bus;
+	uint8_t dev;
+	uint8_t fun;
+	char name[MAX_DEVICE_NAME_SIZE];
+};
+
+#define ADF_CTL_IOC_MAGIC 'a'
+#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \
+		struct adf_user_cfg_ctl_data)
+#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \
+		struct adf_user_cfg_ctl_data)
+#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \
+		struct adf_user_cfg_ctl_data)
+#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, uint32_t)
+#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, int32_t)
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_CFG_H_
+#define ADF_CFG_H_
+
+#include <linux/list.h>
+#include <linux/rwsem.h>
+#include <linux/debugfs.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg_common.h"
+#include "adf_cfg_strings.h"
+
+struct adf_cfg_key_val {
+	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+	enum adf_cfg_val_type type;
+	struct list_head list;
+};
+
+struct adf_cfg_section {
+	char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
+	struct list_head list;
+	struct list_head param_head;
+};
+
+struct adf_cfg_device_data {
+	struct list_head sec_list;
+	struct dentry *debug;
+	struct rw_semaphore lock;
+};
+
+int adf_cfg_dev_add(struct adf_accel_dev *accel_dev);
+void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev);
+int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name);
+void adf_cfg_del_all(struct adf_accel_dev *accel_dev);
+int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
+				const char *section_name,
+				const char *key, const void *val,
+				enum adf_cfg_val_type type);
+int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
+			    const char *section, const char *name, char *value);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_CFG_STRINGS_H_
+#define ADF_CFG_STRINGS_H_
+
+#define ADF_GENERAL_SEC "GENERAL"
+#define ADF_KERNEL_SEC "KERNEL"
+#define ADF_ACCEL_SEC "Accelerator"
+#define ADF_NUM_CY "NumberCyInstances"
+#define ADF_NUM_DC "NumberDcInstances"
+#define ADF_RING_SYM_SIZE "NumConcurrentSymRequests"
+#define ADF_RING_ASYM_SIZE "NumConcurrentAsymRequests"
+#define ADF_RING_DC_SIZE "NumConcurrentRequests"
+#define ADF_RING_ASYM_TX "RingAsymTx"
+#define ADF_RING_SYM_TX "RingSymTx"
+#define ADF_RING_RND_TX "RingNrbgTx"
+#define ADF_RING_ASYM_RX "RingAsymRx"
+#define ADF_RING_SYM_RX "RinSymRx"
+#define ADF_RING_RND_RX "RingNrbgRx"
+#define ADF_RING_DC_TX "RingTx"
+#define ADF_RING_DC_RX "RingRx"
+#define ADF_ETRMGR_BANK "Bank"
+#define ADF_RING_BANK_NUM "BankNumber"
+#define ADF_CY "Cy"
+#define ADF_DC "Dc"
+#define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled"
+#define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \
+	ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCING_ENABLED
+#define ADF_ETRMGR_COALESCE_TIMER "InterruptCoalescingTimerNs"
+#define ADF_ETRMGR_COALESCE_TIMER_FORMAT \
+	ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCE_TIMER
+#define ADF_ETRMGR_COALESCING_MSG_ENABLED "InterruptCoalescingNumResponses"
+#define ADF_ETRMGR_COALESCING_MSG_ENABLED_FORMAT \
+	ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCING_MSG_ENABLED
+#define ADF_ETRMGR_CORE_AFFINITY "CoreAffinity"
+#define ADF_ETRMGR_CORE_AFFINITY_FORMAT \
+	ADF_ETRMGR_BANK"%d"ADF_ETRMGR_CORE_AFFINITY
+#define ADF_ACCEL_STR "Accelerator%d"
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_user.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_user.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_cfg_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_cfg_user.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_CFG_USER_H_
+#define ADF_CFG_USER_H_
+
+#include "adf_cfg_common.h"
+#include "adf_cfg_strings.h"
+
+struct adf_user_cfg_key_val {
+	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+	union {
+		char *user_val_ptr;
+		uint64_t padding1;
+	};
+	union {
+		struct adf_user_cfg_key_val *prev;
+		uint64_t padding2;
+	};
+	union {
+		struct adf_user_cfg_key_val *next;
+		uint64_t padding3;
+	};
+	enum adf_cfg_val_type type;
+};
+
+struct adf_user_cfg_section {
+	char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
+	union {
+		struct adf_user_cfg_key_val *params;
+		uint64_t padding1;
+	};
+	union {
+		struct adf_user_cfg_section *prev;
+		uint64_t padding2;
+	};
+	union {
+		struct adf_user_cfg_section *next;
+		uint64_t padding3;
+	};
+};
+
+struct adf_user_cfg_ctl_data {
+	union {
+		struct adf_user_cfg_section *config_section;
+		uint64_t padding;
+	};
+	uint8_t device_id;
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,192 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_DRV_H
+#define ADF_DRV_H
+
+#include <linux/list.h>
+#include <linux/pci.h>
+#include "adf_accel_devices.h"
+#include "icp_qat_fw_loader_handle.h"
+#include "icp_qat_hal.h"
+
+#define ADF_STATUS_RESTARTING 0
+#define ADF_STATUS_STARTING 1
+#define ADF_STATUS_CONFIGURED 2
+#define ADF_STATUS_STARTED 3
+#define ADF_STATUS_AE_INITIALISED 4
+#define ADF_STATUS_AE_UCODE_LOADED 5
+#define ADF_STATUS_AE_STARTED 6
+#define ADF_STATUS_ORPHAN_TH_RUNNING 7
+#define ADF_STATUS_IRQ_ALLOCATED 8
+
+enum adf_dev_reset_mode {
+	ADF_DEV_RESET_ASYNC = 0,
+	ADF_DEV_RESET_SYNC
+};
+
+enum adf_event {
+	ADF_EVENT_INIT = 0,
+	ADF_EVENT_START,
+	ADF_EVENT_STOP,
+	ADF_EVENT_SHUTDOWN,
+	ADF_EVENT_RESTARTING,
+	ADF_EVENT_RESTARTED,
+};
+
+struct service_hndl {
+	int (*event_hld)(struct adf_accel_dev *accel_dev,
+			 enum adf_event event);
+	unsigned long init_status;
+	unsigned long start_status;
+	char *name;
+	struct list_head list;
+	int admin;
+};
+
+int adf_service_register(struct service_hndl *service);
+int adf_service_unregister(struct service_hndl *service);
+
+int adf_dev_init(struct adf_accel_dev *accel_dev);
+int adf_dev_start(struct adf_accel_dev *accel_dev);
+int adf_dev_stop(struct adf_accel_dev *accel_dev);
+int adf_dev_shutdown(struct adf_accel_dev *accel_dev);
+
+int adf_ctl_dev_register(void);
+void adf_ctl_dev_unregister(void);
+int adf_processes_dev_register(void);
+void adf_processes_dev_unregister(void);
+
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev);
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev);
+struct list_head *adf_devmgr_get_head(void);
+struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id);
+struct adf_accel_dev *adf_devmgr_get_first(void);
+struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev);
+int adf_devmgr_verify_id(uint32_t id);
+void adf_devmgr_get_num_dev(uint32_t *num);
+int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev);
+int adf_dev_started(struct adf_accel_dev *accel_dev);
+int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev);
+int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev);
+int adf_ae_init(struct adf_accel_dev *accel_dev);
+int adf_ae_shutdown(struct adf_accel_dev *accel_dev);
+int adf_ae_fw_load(struct adf_accel_dev *accel_dev);
+int adf_ae_fw_release(struct adf_accel_dev *accel_dev);
+int adf_ae_start(struct adf_accel_dev *accel_dev);
+int adf_ae_stop(struct adf_accel_dev *accel_dev);
+
+int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf);
+void adf_disable_aer(struct adf_accel_dev *accel_dev);
+int adf_init_aer(void);
+void adf_exit_aer(void);
+
+int adf_dev_get(struct adf_accel_dev *accel_dev);
+void adf_dev_put(struct adf_accel_dev *accel_dev);
+int adf_dev_in_use(struct adf_accel_dev *accel_dev);
+int adf_init_etr_data(struct adf_accel_dev *accel_dev);
+void adf_cleanup_etr_data(struct adf_accel_dev *accel_dev);
+int qat_crypto_register(void);
+int qat_crypto_unregister(void);
+struct qat_crypto_instance *qat_crypto_get_instance_node(int node);
+void qat_crypto_put_instance(struct qat_crypto_instance *inst);
+void qat_alg_callback(void *resp);
+int qat_algs_init(void);
+void qat_algs_exit(void);
+int qat_algs_register(void);
+int qat_algs_unregister(void);
+
+int qat_hal_init(struct adf_accel_dev *accel_dev);
+void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle);
+void qat_hal_start(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+		   unsigned int ctx_mask);
+void qat_hal_stop(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+		  unsigned int ctx_mask);
+void qat_hal_reset(struct icp_qat_fw_loader_handle *handle);
+int qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle);
+void qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle,
+			  unsigned char ae, unsigned int ctx_mask);
+int qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle,
+			   unsigned char ae, enum icp_qat_uof_regtype lm_type,
+			   unsigned char mode);
+int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle,
+			    unsigned char ae, unsigned char mode);
+int qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle,
+			   unsigned char ae, unsigned char mode);
+void qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle,
+		    unsigned char ae, unsigned int ctx_mask, unsigned int upc);
+void qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle,
+		       unsigned char ae, unsigned int uaddr,
+		       unsigned int words_num, uint64_t *uword);
+void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+		     unsigned int uword_addr, unsigned int words_num,
+		     unsigned int *data);
+int qat_hal_get_ins_num(void);
+int qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle,
+			unsigned char ae,
+			struct icp_qat_uof_batch_init *lm_init_header);
+int qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle,
+		     unsigned char ae, unsigned char ctx_mask,
+		     enum icp_qat_uof_regtype reg_type,
+		     unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+			 unsigned char ae, unsigned char ctx_mask,
+			 enum icp_qat_uof_regtype reg_type,
+			 unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+			 unsigned char ae, unsigned char ctx_mask,
+			 enum icp_qat_uof_regtype reg_type,
+			 unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle,
+		    unsigned char ae, unsigned char ctx_mask,
+		    unsigned short reg_num, unsigned int regdata);
+int qat_hal_wr_lm(struct icp_qat_fw_loader_handle *handle,
+		  unsigned char ae, unsigned short lm_addr, unsigned int value);
+int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle);
+void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle);
+int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
+			 void *addr_ptr, int mem_size);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,490 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_cfg.h"
+#include "adf_cfg_common.h"
+#include "adf_cfg_user.h"
+
+#define DEVICE_NAME "qat_adf_ctl"
+
+static DEFINE_MUTEX(adf_ctl_lock);
+static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+
+static const struct file_operations adf_ctl_ops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = adf_ctl_ioctl,
+	.compat_ioctl = adf_ctl_ioctl,
+};
+
+struct adf_ctl_drv_info {
+	unsigned int major;
+	struct cdev drv_cdev;
+	struct class *drv_class;
+};
+
+static struct adf_ctl_drv_info adt_ctl_drv;
+
+static void adf_chr_drv_destroy(void)
+{
+	device_destroy(adt_ctl_drv.drv_class, MKDEV(adt_ctl_drv.major, 0));
+	cdev_del(&adt_ctl_drv.drv_cdev);
+	class_destroy(adt_ctl_drv.drv_class);
+	unregister_chrdev_region(MKDEV(adt_ctl_drv.major, 0), 1);
+}
+
+static int adf_chr_drv_create(void)
+{
+	dev_t dev_id;
+	struct device *drv_device;
+
+	if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
+		pr_err("QAT: unable to allocate chrdev region\n");
+		return -EFAULT;
+	}
+
+	adt_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(adt_ctl_drv.drv_class)) {
+		pr_err("QAT: class_create failed for adf_ctl\n");
+		goto err_chrdev_unreg;
+	}
+	adt_ctl_drv.major = MAJOR(dev_id);
+	cdev_init(&adt_ctl_drv.drv_cdev, &adf_ctl_ops);
+	if (cdev_add(&adt_ctl_drv.drv_cdev, dev_id, 1)) {
+		pr_err("QAT: cdev add failed\n");
+		goto err_class_destr;
+	}
+
+	drv_device = device_create(adt_ctl_drv.drv_class, NULL,
+				   MKDEV(adt_ctl_drv.major, 0),
+				   NULL, DEVICE_NAME);
+	if (!drv_device) {
+		pr_err("QAT: failed to create device\n");
+		goto err_cdev_del;
+	}
+	return 0;
+err_cdev_del:
+	cdev_del(&adt_ctl_drv.drv_cdev);
+err_class_destr:
+	class_destroy(adt_ctl_drv.drv_class);
+err_chrdev_unreg:
+	unregister_chrdev_region(dev_id, 1);
+	return -EFAULT;
+}
+
+static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
+				   unsigned long arg)
+{
+	struct adf_user_cfg_ctl_data *cfg_data;
+
+	cfg_data = kzalloc(sizeof(*cfg_data), GFP_KERNEL);
+	if (!cfg_data)
+		return -ENOMEM;
+
+	/* Initialize device id to NO DEVICE as 0 is a valid device id */
+	cfg_data->device_id = ADF_CFG_NO_DEVICE;
+
+	if (copy_from_user(cfg_data, (void __user *)arg, sizeof(*cfg_data))) {
+		pr_err("QAT: failed to copy from user cfg_data.\n");
+		kfree(cfg_data);
+		return -EIO;
+	}
+
+	*ctl_data = cfg_data;
+	return 0;
+}
+
+static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
+				  const char *section,
+				  const struct adf_user_cfg_key_val *key_val)
+{
+	if (key_val->type == ADF_HEX) {
+		long *ptr = (long *)key_val->val;
+		long val = *ptr;
+
+		if (adf_cfg_add_key_value_param(accel_dev, section,
+						key_val->key, (void *)val,
+						key_val->type)) {
+			pr_err("QAT: failed to add keyvalue.\n");
+			return -EFAULT;
+		}
+	} else {
+		if (adf_cfg_add_key_value_param(accel_dev, section,
+						key_val->key, key_val->val,
+						key_val->type)) {
+			pr_err("QAT: failed to add keyvalue.\n");
+			return -EFAULT;
+		}
+	}
+	return 0;
+}
+
+static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
+				   struct adf_user_cfg_ctl_data *ctl_data)
+{
+	struct adf_user_cfg_key_val key_val;
+	struct adf_user_cfg_key_val *params_head;
+	struct adf_user_cfg_section section, *section_head;
+
+	section_head = ctl_data->config_section;
+
+	while (section_head) {
+		if (copy_from_user(&section, (void __user *)section_head,
+				   sizeof(*section_head))) {
+			pr_err("QAT: failed to copy section info\n");
+			goto out_err;
+		}
+
+		if (adf_cfg_section_add(accel_dev, section.name)) {
+			pr_err("QAT: failed to add section.\n");
+			goto out_err;
+		}
+
+		params_head = section_head->params;
+
+		while (params_head) {
+			if (copy_from_user(&key_val, (void __user *)params_head,
+					   sizeof(key_val))) {
+				pr_err("QAT: Failed to copy keyvalue.\n");
+				goto out_err;
+			}
+			if (adf_add_key_value_data(accel_dev, section.name,
+						   &key_val)) {
+				goto out_err;
+			}
+			params_head = key_val.next;
+		}
+		section_head = section.next;
+	}
+	return 0;
+out_err:
+	adf_cfg_del_all(accel_dev);
+	return -EFAULT;
+}
+
+static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
+				    unsigned long arg)
+{
+	int ret;
+	struct adf_user_cfg_ctl_data *ctl_data;
+	struct adf_accel_dev *accel_dev;
+
+	ret = adf_ctl_alloc_resources(&ctl_data, arg);
+	if (ret)
+		return ret;
+
+	accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+	if (!accel_dev) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (adf_dev_started(accel_dev)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (adf_copy_key_value_data(accel_dev, ctl_data)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+out:
+	kfree(ctl_data);
+	return ret;
+}
+
+static int adf_ctl_is_device_in_use(int id)
+{
+	struct list_head *itr, *head = adf_devmgr_get_head();
+
+	list_for_each(itr, head) {
+		struct adf_accel_dev *dev =
+				list_entry(itr, struct adf_accel_dev, list);
+
+		if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+			if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
+				pr_info("QAT: device qat_dev%d is busy\n",
+					dev->accel_id);
+				return -EBUSY;
+			}
+		}
+	}
+	return 0;
+}
+
+static int adf_ctl_stop_devices(uint32_t id)
+{
+	struct list_head *itr, *head = adf_devmgr_get_head();
+	int ret = 0;
+
+	list_for_each(itr, head) {
+		struct adf_accel_dev *accel_dev =
+				list_entry(itr, struct adf_accel_dev, list);
+		if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+			if (!adf_dev_started(accel_dev))
+				continue;
+
+			if (adf_dev_stop(accel_dev)) {
+				pr_err("QAT: Failed to stop qat_dev%d\n", id);
+				ret = -EFAULT;
+			}
+		}
+	}
+	return ret;
+}
+
+static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
+				  unsigned long arg)
+{
+	int ret;
+	struct adf_user_cfg_ctl_data *ctl_data;
+
+	ret = adf_ctl_alloc_resources(&ctl_data, arg);
+	if (ret)
+		return ret;
+
+	if (adf_devmgr_verify_id(ctl_data->device_id)) {
+		pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = adf_ctl_is_device_in_use(ctl_data->device_id);
+	if (ret)
+		goto out;
+
+	if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
+		pr_info("QAT: Stopping all acceleration devices.\n");
+	else
+		pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
+			ctl_data->device_id);
+
+	ret = adf_ctl_stop_devices(ctl_data->device_id);
+	if (ret)
+		pr_err("QAT: failed to stop device.\n");
+out:
+	kfree(ctl_data);
+	return ret;
+}
+
+static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
+				   unsigned long arg)
+{
+	int ret;
+	struct adf_user_cfg_ctl_data *ctl_data;
+	struct adf_accel_dev *accel_dev;
+
+	ret = adf_ctl_alloc_resources(&ctl_data, arg);
+	if (ret)
+		return ret;
+
+	accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+	if (!accel_dev) {
+		pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!adf_dev_started(accel_dev)) {
+		pr_info("QAT: Starting acceleration device qat_dev%d.\n",
+			ctl_data->device_id);
+		ret = adf_dev_start(accel_dev);
+	} else {
+		pr_info("QAT: Acceleration device qat_dev%d already started.\n",
+			ctl_data->device_id);
+	}
+	if (ret) {
+		pr_err("QAT: Failed to start qat_dev%d\n", ctl_data->device_id);
+		adf_dev_stop(accel_dev);
+	}
+out:
+	kfree(ctl_data);
+	return ret;
+}
+
+static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
+					 unsigned long arg)
+{
+	uint32_t num_devices = 0;
+
+	adf_devmgr_get_num_dev(&num_devices);
+	if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
+				    unsigned long arg)
+{
+	struct adf_hw_device_data *hw_data;
+	struct adf_dev_status_info dev_info;
+	struct adf_accel_dev *accel_dev;
+
+	if (copy_from_user(&dev_info, (void __user *)arg,
+			   sizeof(struct adf_dev_status_info))) {
+		pr_err("QAT: failed to copy from user.\n");
+		return -EFAULT;
+	}
+
+	accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
+	if (!accel_dev) {
+		pr_err("QAT: Device %d not found\n", dev_info.accel_id);
+		return -ENODEV;
+	}
+	hw_data = accel_dev->hw_device;
+	dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
+	dev_info.num_ae = hw_data->get_num_aes(hw_data);
+	dev_info.num_accel = hw_data->get_num_accels(hw_data);
+	dev_info.num_logical_accel = hw_data->num_logical_accel;
+	dev_info.banks_per_accel = hw_data->num_banks
+					/ hw_data->num_logical_accel;
+	strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
+	dev_info.instance_id = hw_data->instance_id;
+	dev_info.type = hw_data->dev_class->type;
+	dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
+	dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
+	dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
+
+	if (copy_to_user((void __user *)arg, &dev_info,
+			 sizeof(struct adf_dev_status_info))) {
+		pr_err("QAT: failed to copy status.\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&adf_ctl_lock))
+		return -EFAULT;
+
+	switch (cmd) {
+	case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
+		ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
+		break;
+
+	case IOCTL_STOP_ACCEL_DEV:
+		ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
+		break;
+
+	case IOCTL_START_ACCEL_DEV:
+		ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
+		break;
+
+	case IOCTL_GET_NUM_DEVICES:
+		ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
+		break;
+
+	case IOCTL_STATUS_ACCEL_DEV:
+		ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
+		break;
+	default:
+		pr_err("QAT: Invalid ioclt\n");
+		ret = -EFAULT;
+		break;
+	}
+	mutex_unlock(&adf_ctl_lock);
+	return ret;
+}
+
+static int __init adf_register_ctl_device_driver(void)
+{
+	mutex_init(&adf_ctl_lock);
+
+	if (qat_algs_init())
+		goto err_algs_init;
+
+	if (adf_chr_drv_create())
+		goto err_chr_dev;
+
+	if (adf_init_aer())
+		goto err_aer;
+
+	if (qat_crypto_register())
+		goto err_crypto_register;
+
+	return 0;
+
+err_crypto_register:
+	adf_exit_aer();
+err_aer:
+	adf_chr_drv_destroy();
+err_chr_dev:
+	qat_algs_exit();
+err_algs_init:
+	mutex_destroy(&adf_ctl_lock);
+	return -EFAULT;
+}
+
+static void __exit adf_unregister_ctl_device_driver(void)
+{
+	adf_chr_drv_destroy();
+	adf_exit_aer();
+	qat_crypto_unregister();
+	qat_algs_exit();
+	mutex_destroy(&adf_ctl_lock);
+}
+
+module_init(adf_register_ctl_device_driver);
+module_exit(adf_unregister_ctl_device_driver);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
+MODULE_ALIAS("intel_qat");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_dev_mgr.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_dev_mgr.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_dev_mgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_dev_mgr.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,215 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static LIST_HEAD(accel_table);
+static DEFINE_MUTEX(table_lock);
+static uint32_t num_devices;
+
+/**
+ * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function adds acceleration device to the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev)
+{
+	struct list_head *itr;
+
+	if (num_devices == ADF_MAX_DEVICES) {
+		pr_err("QAT: Only support up to %d devices\n", ADF_MAX_DEVICES);
+		return -EFAULT;
+	}
+
+	mutex_lock(&table_lock);
+	list_for_each(itr, &accel_table) {
+		struct adf_accel_dev *ptr =
+				list_entry(itr, struct adf_accel_dev, list);
+
+		if (ptr == accel_dev) {
+			mutex_unlock(&table_lock);
+			return -EEXIST;
+		}
+	}
+	atomic_set(&accel_dev->ref_count, 0);
+	list_add_tail(&accel_dev->list, &accel_table);
+	accel_dev->accel_id = num_devices++;
+	mutex_unlock(&table_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_add_dev);
+
+struct list_head *adf_devmgr_get_head(void)
+{
+	return &accel_table;
+}
+
+/**
+ * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework.
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function removes acceleration device from the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev)
+{
+	mutex_lock(&table_lock);
+	list_del(&accel_dev->list);
+	num_devices--;
+	mutex_unlock(&table_lock);
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev);
+
+struct adf_accel_dev *adf_devmgr_get_first(void)
+{
+	struct adf_accel_dev *dev = NULL;
+
+	if (!list_empty(&accel_table))
+		dev = list_first_entry(&accel_table, struct adf_accel_dev,
+				       list);
+	return dev;
+}
+
+/**
+ * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev.
+ * @accel_dev:  Pointer to pci device.
+ *
+ * Function returns acceleration device associated with the given pci device.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: pinter to accel_dev or NULL if not found.
+ */
+struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev)
+{
+	struct list_head *itr;
+
+	list_for_each(itr, &accel_table) {
+		struct adf_accel_dev *ptr =
+				list_entry(itr, struct adf_accel_dev, list);
+
+		if (ptr->accel_pci_dev.pci_dev == pci_dev) {
+			mutex_unlock(&table_lock);
+			return ptr;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev);
+
+struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id)
+{
+	struct list_head *itr;
+
+	list_for_each(itr, &accel_table) {
+		struct adf_accel_dev *ptr =
+				list_entry(itr, struct adf_accel_dev, list);
+
+		if (ptr->accel_id == id) {
+			mutex_unlock(&table_lock);
+			return ptr;
+		}
+	}
+	return NULL;
+}
+
+int adf_devmgr_verify_id(uint32_t id)
+{
+	if (id == ADF_CFG_ALL_DEVICES)
+		return 0;
+
+	if (adf_devmgr_get_dev_by_id(id))
+		return 0;
+
+	return -ENODEV;
+}
+
+void adf_devmgr_get_num_dev(uint32_t *num)
+{
+	struct list_head *itr;
+
+	*num = 0;
+	list_for_each(itr, &accel_table) {
+		(*num)++;
+	}
+}
+
+int adf_dev_in_use(struct adf_accel_dev *accel_dev)
+{
+	return atomic_read(&accel_dev->ref_count) != 0;
+}
+
+int adf_dev_get(struct adf_accel_dev *accel_dev)
+{
+	if (atomic_add_return(1, &accel_dev->ref_count) == 1)
+		if (!try_module_get(accel_dev->owner))
+			return -EFAULT;
+	return 0;
+}
+
+void adf_dev_put(struct adf_accel_dev *accel_dev)
+{
+	if (atomic_sub_return(1, &accel_dev->ref_count) == 0)
+		module_put(accel_dev->owner);
+}
+
+int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev)
+{
+	return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+}
+
+int adf_dev_started(struct adf_accel_dev *accel_dev)
+{
+	return test_bit(ADF_STATUS_STARTED, &accel_dev->status);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_init.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_init.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,388 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static LIST_HEAD(service_table);
+static DEFINE_MUTEX(service_lock);
+
+static void adf_service_add(struct service_hndl *service)
+{
+	mutex_lock(&service_lock);
+	list_add(&service->list, &service_table);
+	mutex_unlock(&service_lock);
+}
+
+/**
+ * adf_service_register() - Register acceleration service in the accel framework
+ * @service:    Pointer to the service
+ *
+ * Function adds the acceleration service to the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_service_register(struct service_hndl *service)
+{
+	service->init_status = 0;
+	service->start_status = 0;
+	adf_service_add(service);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_service_register);
+
+static void adf_service_remove(struct service_hndl *service)
+{
+	mutex_lock(&service_lock);
+	list_del(&service->list);
+	mutex_unlock(&service_lock);
+}
+
+/**
+ * adf_service_unregister() - Unregister acceleration service from the framework
+ * @service:    Pointer to the service
+ *
+ * Function remove the acceleration service from the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_service_unregister(struct service_hndl *service)
+{
+	if (service->init_status || service->start_status) {
+		pr_err("QAT: Could not remove active service\n");
+		return -EFAULT;
+	}
+	adf_service_remove(service);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_service_unregister);
+
+/**
+ * adf_dev_start() - Start acceleration service for the given accel device
+ * @accel_dev:    Pointer to acceleration device.
+ *
+ * Function notifies all the registered services that the acceleration device
+ * is ready to be used.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_dev_start(struct adf_accel_dev *accel_dev)
+{
+	struct service_hndl *service;
+	struct list_head *list_itr;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+
+	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
+		pr_info("QAT: Device not configured\n");
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_STARTING, &accel_dev->status);
+
+	if (adf_ae_init(accel_dev)) {
+		pr_err("QAT: Failed to initialise Acceleration Engine\n");
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
+
+	if (adf_ae_fw_load(accel_dev)) {
+		pr_err("QAT: Failed to load acceleration FW\n");
+		adf_ae_fw_release(accel_dev);
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
+
+	if (hw_data->alloc_irq(accel_dev)) {
+		pr_err("QAT: Failed to allocate interrupts\n");
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
+
+	/*
+	 * Subservice initialisation is divided into two stages: init and start.
+	 * This is to facilitate any ordering dependencies between services
+	 * prior to starting any of the accelerators.
+	 */
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
+			pr_err("QAT: Failed to initialise service %s\n",
+			       service->name);
+			return -EFAULT;
+		}
+		set_bit(accel_dev->accel_id, &service->init_status);
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
+			pr_err("QAT: Failed to initialise service %s\n",
+			       service->name);
+			return -EFAULT;
+		}
+		set_bit(accel_dev->accel_id, &service->init_status);
+	}
+
+	hw_data->enable_error_correction(accel_dev);
+
+	if (adf_ae_start(accel_dev)) {
+		pr_err("QAT: AE Start Failed\n");
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
+
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
+			pr_err("QAT: Failed to start service %s\n",
+			       service->name);
+			return -EFAULT;
+		}
+		set_bit(accel_dev->accel_id, &service->start_status);
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
+			pr_err("QAT: Failed to start service %s\n",
+			       service->name);
+			return -EFAULT;
+		}
+		set_bit(accel_dev->accel_id, &service->start_status);
+	}
+
+	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
+	set_bit(ADF_STATUS_STARTED, &accel_dev->status);
+
+	if (qat_algs_register()) {
+		pr_err("QAT: Failed to register crypto algs\n");
+		set_bit(ADF_STATUS_STARTING, &accel_dev->status);
+		clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
+		return -EFAULT;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_dev_start);
+
+/**
+ * adf_dev_stop() - Stop acceleration service for the given accel device
+ * @accel_dev:    Pointer to acceleration device.
+ *
+ * Function notifies all the registered services that the acceleration device
+ * is shuting down.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_dev_stop(struct adf_accel_dev *accel_dev)
+{
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	struct service_hndl *service;
+	struct list_head *list_itr;
+	int ret, wait = 0;
+
+	if (!adf_dev_started(accel_dev) &&
+	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
+		return 0;
+	}
+	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
+	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
+
+	if (qat_algs_unregister())
+		pr_err("QAT: Failed to unregister crypto algs\n");
+
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (!test_bit(accel_dev->accel_id, &service->start_status))
+			continue;
+		ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
+		if (!ret) {
+			clear_bit(accel_dev->accel_id, &service->start_status);
+		} else if (ret == -EAGAIN) {
+			wait = 1;
+			clear_bit(accel_dev->accel_id, &service->start_status);
+		}
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (!test_bit(accel_dev->accel_id, &service->start_status))
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_STOP))
+			pr_err("QAT: Failed to shutdown service %s\n",
+			       service->name);
+		else
+			clear_bit(accel_dev->accel_id, &service->start_status);
+	}
+
+	if (wait)
+		msleep(100);
+
+	if (adf_dev_started(accel_dev)) {
+		if (adf_ae_stop(accel_dev))
+			pr_err("QAT: failed to stop AE\n");
+		else
+			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
+	}
+
+	if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
+		if (adf_ae_fw_release(accel_dev))
+			pr_err("QAT: Failed to release the ucode\n");
+		else
+			clear_bit(ADF_STATUS_AE_UCODE_LOADED,
+				  &accel_dev->status);
+	}
+
+	if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
+		if (adf_ae_shutdown(accel_dev))
+			pr_err("QAT: Failed to shutdown Accel Engine\n");
+		else
+			clear_bit(ADF_STATUS_AE_INITIALISED,
+				  &accel_dev->status);
+	}
+
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (!test_bit(accel_dev->accel_id, &service->init_status))
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
+			pr_err("QAT: Failed to shutdown service %s\n",
+			       service->name);
+		else
+			clear_bit(accel_dev->accel_id, &service->init_status);
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (!test_bit(accel_dev->accel_id, &service->init_status))
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
+			pr_err("QAT: Failed to shutdown service %s\n",
+			       service->name);
+		else
+			clear_bit(accel_dev->accel_id, &service->init_status);
+	}
+
+	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
+		hw_data->free_irq(accel_dev);
+		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
+	}
+
+	/* Delete configuration only if not restarting */
+	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
+		adf_cfg_del_all(accel_dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_dev_stop);
+
+int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
+{
+	struct service_hndl *service;
+	struct list_head *list_itr;
+
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
+			pr_err("QAT: Failed to restart service %s.\n",
+			       service->name);
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
+			pr_err("QAT: Failed to restart service %s.\n",
+			       service->name);
+	}
+	return 0;
+}
+
+int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
+{
+	struct service_hndl *service;
+	struct list_head *list_itr;
+
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
+			pr_err("QAT: Failed to restart service %s.\n",
+			       service->name);
+	}
+	list_for_each(list_itr, &service_table) {
+		service = list_entry(list_itr, struct service_hndl, list);
+		if (!service->admin)
+			continue;
+		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
+			pr_err("QAT: Failed to restart service %s.\n",
+			       service->name);
+	}
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_access_macros.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_access_macros.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_access_macros.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_access_macros.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,160 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_TRANSPORT_ACCESS_MACROS_H
+#define ADF_TRANSPORT_ACCESS_MACROS_H
+
+#include "adf_accel_devices.h"
+#define ADF_BANK_INT_SRC_SEL_MASK_0 0x4444444CUL
+#define ADF_BANK_INT_SRC_SEL_MASK_X 0x44444444UL
+#define ADF_RING_CSR_RING_CONFIG 0x000
+#define ADF_RING_CSR_RING_LBASE 0x040
+#define ADF_RING_CSR_RING_UBASE 0x080
+#define ADF_RING_CSR_RING_HEAD 0x0C0
+#define ADF_RING_CSR_RING_TAIL 0x100
+#define ADF_RING_CSR_E_STAT 0x14C
+#define ADF_RING_CSR_INT_SRCSEL 0x174
+#define ADF_RING_CSR_INT_SRCSEL_2 0x178
+#define ADF_RING_CSR_INT_COL_EN 0x17C
+#define ADF_RING_CSR_INT_COL_CTL 0x180
+#define ADF_RING_CSR_INT_FLAG_AND_COL 0x184
+#define ADF_RING_CSR_INT_COL_CTL_ENABLE	0x80000000
+#define ADF_RING_BUNDLE_SIZE 0x1000
+#define ADF_RING_CONFIG_NEAR_FULL_WM 0x0A
+#define ADF_RING_CONFIG_NEAR_EMPTY_WM 0x05
+#define ADF_COALESCING_MIN_TIME 0x1FF
+#define ADF_COALESCING_MAX_TIME 0xFFFFF
+#define ADF_COALESCING_DEF_TIME 0x27FF
+#define ADF_RING_NEAR_WATERMARK_512 0x08
+#define ADF_RING_NEAR_WATERMARK_0 0x00
+#define ADF_RING_EMPTY_SIG 0x7F7F7F7F
+
+/* Valid internal ring size values */
+#define ADF_RING_SIZE_128 0x01
+#define ADF_RING_SIZE_256 0x02
+#define ADF_RING_SIZE_512 0x03
+#define ADF_RING_SIZE_4K 0x06
+#define ADF_RING_SIZE_16K 0x08
+#define ADF_RING_SIZE_4M 0x10
+#define ADF_MIN_RING_SIZE ADF_RING_SIZE_128
+#define ADF_MAX_RING_SIZE ADF_RING_SIZE_4M
+#define ADF_DEFAULT_RING_SIZE ADF_RING_SIZE_16K
+
+/* Valid internal msg size values internal */
+#define ADF_MSG_SIZE_32 0x01
+#define ADF_MSG_SIZE_64 0x02
+#define ADF_MSG_SIZE_128 0x04
+#define ADF_MIN_MSG_SIZE ADF_MSG_SIZE_32
+#define ADF_MAX_MSG_SIZE ADF_MSG_SIZE_128
+
+/* Size to bytes conversion macros for ring and msg values */
+#define ADF_MSG_SIZE_TO_BYTES(SIZE) (SIZE << 5)
+#define ADF_BYTES_TO_MSG_SIZE(SIZE) (SIZE >> 5)
+#define ADF_SIZE_TO_RING_SIZE_IN_BYTES(SIZE) ((1 << (SIZE - 1)) << 7)
+#define ADF_RING_SIZE_IN_BYTES_TO_SIZE(SIZE) ((1 << (SIZE - 1)) >> 7)
+
+/* Minimum ring bufer size for memory allocation */
+#define ADF_RING_SIZE_BYTES_MIN(SIZE) ((SIZE < ADF_RING_SIZE_4K) ? \
+				ADF_RING_SIZE_4K : SIZE)
+#define ADF_RING_SIZE_MODULO(SIZE) (SIZE + 0x6)
+#define ADF_MAX_INFLIGHTS(RING_SIZE, MSG_SIZE) \
+	((((1 << (RING_SIZE - 1)) << 4) >> MSG_SIZE) - 1)
+#define BUILD_RING_CONFIG(size)	\
+	((ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_FULL_WM) \
+	| (ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_EMPTY_WM) \
+	| size)
+#define BUILD_RESP_RING_CONFIG(size, watermark_nf, watermark_ne) \
+	((watermark_nf << ADF_RING_CONFIG_NEAR_FULL_WM)	\
+	| (watermark_ne << ADF_RING_CONFIG_NEAR_EMPTY_WM) \
+	| size)
+#define BUILD_RING_BASE_ADDR(addr, size) \
+	((addr >> 6) & (0xFFFFFFFFFFFFFFFFULL << size))
+#define READ_CSR_RING_HEAD(csr_base_addr, bank, ring) \
+	ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_RING_HEAD + (ring << 2))
+#define READ_CSR_RING_TAIL(csr_base_addr, bank, ring) \
+	ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_RING_TAIL + (ring << 2))
+#define READ_CSR_E_STAT(csr_base_addr, bank) \
+	ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_E_STAT)
+#define WRITE_CSR_RING_CONFIG(csr_base_addr, bank, ring, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+		ADF_RING_CSR_RING_CONFIG + (ring << 2), value)
+#define WRITE_CSR_RING_BASE(csr_base_addr, bank, ring, value) \
+do { \
+	uint32_t l_base = 0, u_base = 0; \
+	l_base = (uint32_t)(value & 0xFFFFFFFF); \
+	u_base = (uint32_t)((value & 0xFFFFFFFF00000000ULL) >> 32); \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+		ADF_RING_CSR_RING_LBASE + (ring << 2), l_base);	\
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+		ADF_RING_CSR_RING_UBASE + (ring << 2), u_base);	\
+} while (0)
+#define WRITE_CSR_RING_HEAD(csr_base_addr, bank, ring, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+		ADF_RING_CSR_RING_HEAD + (ring << 2), value)
+#define WRITE_CSR_RING_TAIL(csr_base_addr, bank, ring, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+		ADF_RING_CSR_RING_TAIL + (ring << 2), value)
+#define WRITE_CSR_INT_SRCSEL(csr_base_addr, bank) \
+do { \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+	ADF_RING_CSR_INT_SRCSEL, ADF_BANK_INT_SRC_SEL_MASK_0);	\
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+	ADF_RING_CSR_INT_SRCSEL_2, ADF_BANK_INT_SRC_SEL_MASK_X); \
+} while (0)
+#define WRITE_CSR_INT_COL_EN(csr_base_addr, bank, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_INT_COL_EN, value)
+#define WRITE_CSR_INT_COL_CTL(csr_base_addr, bank, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_INT_COL_CTL, \
+			ADF_RING_CSR_INT_COL_CTL_ENABLE | value)
+#define WRITE_CSR_INT_FLAG_AND_COL(csr_base_addr, bank, value) \
+	ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+			ADF_RING_CSR_INT_FLAG_AND_COL, value)
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,567 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_transport_internal.h"
+#include "adf_transport_access_macros.h"
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static inline uint32_t adf_modulo(uint32_t data, uint32_t shift)
+{
+	uint32_t div = data >> shift;
+	uint32_t mult = div << shift;
+
+	return data - mult;
+}
+
+static inline int adf_check_ring_alignment(uint64_t addr, uint64_t size)
+{
+	if (((size - 1) & addr) != 0)
+		return -EFAULT;
+	return 0;
+}
+
+static int adf_verify_ring_size(uint32_t msg_size, uint32_t msg_num)
+{
+	int i = ADF_MIN_RING_SIZE;
+
+	for (; i <= ADF_MAX_RING_SIZE; i++)
+		if ((msg_size * msg_num) == ADF_SIZE_TO_RING_SIZE_IN_BYTES(i))
+			return i;
+
+	return ADF_DEFAULT_RING_SIZE;
+}
+
+static int adf_reserve_ring(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+	spin_lock(&bank->lock);
+	if (bank->ring_mask & (1 << ring)) {
+		spin_unlock(&bank->lock);
+		return -EFAULT;
+	}
+	bank->ring_mask |= (1 << ring);
+	spin_unlock(&bank->lock);
+	return 0;
+}
+
+static void adf_unreserve_ring(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+	spin_lock(&bank->lock);
+	bank->ring_mask &= ~(1 << ring);
+	spin_unlock(&bank->lock);
+}
+
+static void adf_enable_ring_irq(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+	spin_lock_bh(&bank->lock);
+	bank->irq_mask |= (1 << ring);
+	spin_unlock_bh(&bank->lock);
+	WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask);
+	WRITE_CSR_INT_COL_CTL(bank->csr_addr, bank->bank_number,
+			      bank->irq_coalesc_timer);
+}
+
+static void adf_disable_ring_irq(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+	spin_lock_bh(&bank->lock);
+	bank->irq_mask &= ~(1 << ring);
+	spin_unlock_bh(&bank->lock);
+	WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask);
+}
+
+int adf_send_message(struct adf_etr_ring_data *ring, uint32_t *msg)
+{
+	if (atomic_add_return(1, ring->inflights) >
+	    ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) {
+		atomic_dec(ring->inflights);
+		return -EAGAIN;
+	}
+	spin_lock_bh(&ring->lock);
+	memcpy(ring->base_addr + ring->tail, msg,
+	       ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
+
+	ring->tail = adf_modulo(ring->tail +
+				ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
+				ADF_RING_SIZE_MODULO(ring->ring_size));
+	WRITE_CSR_RING_TAIL(ring->bank->csr_addr, ring->bank->bank_number,
+			    ring->ring_number, ring->tail);
+	spin_unlock_bh(&ring->lock);
+	return 0;
+}
+
+static int adf_handle_response(struct adf_etr_ring_data *ring)
+{
+	uint32_t msg_counter = 0;
+	uint32_t *msg = (uint32_t *)(ring->base_addr + ring->head);
+
+	while (*msg != ADF_RING_EMPTY_SIG) {
+		ring->callback((uint32_t *)msg);
+		*msg = ADF_RING_EMPTY_SIG;
+		ring->head = adf_modulo(ring->head +
+					ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
+					ADF_RING_SIZE_MODULO(ring->ring_size));
+		msg_counter++;
+		msg = (uint32_t *)(ring->base_addr + ring->head);
+	}
+	if (msg_counter > 0) {
+		WRITE_CSR_RING_HEAD(ring->bank->csr_addr,
+				    ring->bank->bank_number,
+				    ring->ring_number, ring->head);
+		atomic_sub(msg_counter, ring->inflights);
+	}
+	return 0;
+}
+
+static void adf_configure_tx_ring(struct adf_etr_ring_data *ring)
+{
+	uint32_t ring_config = BUILD_RING_CONFIG(ring->ring_size);
+
+	WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, ring->bank->bank_number,
+			      ring->ring_number, ring_config);
+}
+
+static void adf_configure_rx_ring(struct adf_etr_ring_data *ring)
+{
+	uint32_t ring_config =
+			BUILD_RESP_RING_CONFIG(ring->ring_size,
+					       ADF_RING_NEAR_WATERMARK_512,
+					       ADF_RING_NEAR_WATERMARK_0);
+
+	WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, ring->bank->bank_number,
+			      ring->ring_number, ring_config);
+}
+
+static int adf_init_ring(struct adf_etr_ring_data *ring)
+{
+	struct adf_etr_bank_data *bank = ring->bank;
+	struct adf_accel_dev *accel_dev = bank->accel_dev;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint64_t ring_base;
+	uint32_t ring_size_bytes =
+			ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size);
+
+	ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes);
+	ring->base_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
+					     ring_size_bytes, &ring->dma_addr,
+					     GFP_KERNEL);
+	if (!ring->base_addr)
+		return -ENOMEM;
+
+	memset(ring->base_addr, 0x7F, ring_size_bytes);
+	/* The base_addr has to be aligned to the size of the buffer */
+	if (adf_check_ring_alignment(ring->dma_addr, ring_size_bytes)) {
+		pr_err("QAT: Ring address not aligned\n");
+		dma_free_coherent(&GET_DEV(accel_dev), ring_size_bytes,
+				  ring->base_addr, ring->dma_addr);
+		return -EFAULT;
+	}
+
+	if (hw_data->tx_rings_mask & (1 << ring->ring_number))
+		adf_configure_tx_ring(ring);
+
+	else
+		adf_configure_rx_ring(ring);
+
+	ring_base = BUILD_RING_BASE_ADDR(ring->dma_addr, ring->ring_size);
+	WRITE_CSR_RING_BASE(ring->bank->csr_addr, ring->bank->bank_number,
+			    ring->ring_number, ring_base);
+	spin_lock_init(&ring->lock);
+	return 0;
+}
+
+static void adf_cleanup_ring(struct adf_etr_ring_data *ring)
+{
+	uint32_t ring_size_bytes =
+			ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size);
+	ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes);
+
+	if (ring->base_addr) {
+		memset(ring->base_addr, 0x7F, ring_size_bytes);
+		dma_free_coherent(&GET_DEV(ring->bank->accel_dev),
+				  ring_size_bytes, ring->base_addr,
+				  ring->dma_addr);
+	}
+}
+
+int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+		    uint32_t bank_num, uint32_t num_msgs,
+		    uint32_t msg_size, const char *ring_name,
+		    adf_callback_fn callback, int poll_mode,
+		    struct adf_etr_ring_data **ring_ptr)
+{
+	struct adf_etr_data *transport_data = accel_dev->transport;
+	struct adf_etr_bank_data *bank;
+	struct adf_etr_ring_data *ring;
+	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+	uint32_t ring_num;
+	int ret;
+
+	if (bank_num >= GET_MAX_BANKS(accel_dev)) {
+		pr_err("QAT: Invalid bank number\n");
+		return -EFAULT;
+	}
+	if (msg_size > ADF_MSG_SIZE_TO_BYTES(ADF_MAX_MSG_SIZE)) {
+		pr_err("QAT: Invalid msg size\n");
+		return -EFAULT;
+	}
+	if (ADF_MAX_INFLIGHTS(adf_verify_ring_size(msg_size, num_msgs),
+			      ADF_BYTES_TO_MSG_SIZE(msg_size)) < 2) {
+		pr_err("QAT: Invalid ring size for given msg size\n");
+		return -EFAULT;
+	}
+	if (adf_cfg_get_param_value(accel_dev, section, ring_name, val)) {
+		pr_err("QAT: Section %s, no such entry : %s\n",
+		       section, ring_name);
+		return -EFAULT;
+	}
+	if (kstrtouint(val, 10, &ring_num)) {
+		pr_err("QAT: Can't get ring number\n");
+		return -EFAULT;
+	}
+
+	bank = &transport_data->banks[bank_num];
+	if (adf_reserve_ring(bank, ring_num)) {
+		pr_err("QAT: Ring %d, %s already exists.\n",
+		       ring_num, ring_name);
+		return -EFAULT;
+	}
+	ring = &bank->rings[ring_num];
+	ring->ring_number = ring_num;
+	ring->bank = bank;
+	ring->callback = callback;
+	ring->msg_size = ADF_BYTES_TO_MSG_SIZE(msg_size);
+	ring->ring_size = adf_verify_ring_size(msg_size, num_msgs);
+	ring->head = 0;
+	ring->tail = 0;
+	atomic_set(ring->inflights, 0);
+	ret = adf_init_ring(ring);
+	if (ret)
+		goto err;
+
+	/* Enable HW arbitration for the given ring */
+	accel_dev->hw_device->hw_arb_ring_enable(ring);
+
+	if (adf_ring_debugfs_add(ring, ring_name)) {
+		pr_err("QAT: Couldn't add ring debugfs entry\n");
+		ret = -EFAULT;
+		goto err;
+	}
+
+	/* Enable interrupts if needed */
+	if (callback && (!poll_mode))
+		adf_enable_ring_irq(bank, ring->ring_number);
+	*ring_ptr = ring;
+	return 0;
+err:
+	adf_cleanup_ring(ring);
+	adf_unreserve_ring(bank, ring_num);
+	accel_dev->hw_device->hw_arb_ring_disable(ring);
+	return ret;
+}
+
+void adf_remove_ring(struct adf_etr_ring_data *ring)
+{
+	struct adf_etr_bank_data *bank = ring->bank;
+	struct adf_accel_dev *accel_dev = bank->accel_dev;
+
+	/* Disable interrupts for the given ring */
+	adf_disable_ring_irq(bank, ring->ring_number);
+
+	/* Clear PCI config space */
+	WRITE_CSR_RING_CONFIG(bank->csr_addr, bank->bank_number,
+			      ring->ring_number, 0);
+	WRITE_CSR_RING_BASE(bank->csr_addr, bank->bank_number,
+			    ring->ring_number, 0);
+	adf_ring_debugfs_rm(ring);
+	adf_unreserve_ring(bank, ring->ring_number);
+	/* Disable HW arbitration for the given ring */
+	accel_dev->hw_device->hw_arb_ring_disable(ring);
+	adf_cleanup_ring(ring);
+}
+
+static void adf_ring_response_handler(struct adf_etr_bank_data *bank)
+{
+	uint32_t empty_rings, i;
+
+	empty_rings = READ_CSR_E_STAT(bank->csr_addr, bank->bank_number);
+	empty_rings = ~empty_rings & bank->irq_mask;
+
+	for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; ++i) {
+		if (empty_rings & (1 << i))
+			adf_handle_response(&bank->rings[i]);
+	}
+}
+
+/**
+ * adf_response_handler() - Bottom half handler response handler
+ * @bank_addr:  Address of a ring bank for with the BH was scheduled.
+ *
+ * Function is the bottom half handler for the response from acceleration
+ * device. There is one handler for every ring bank. Function checks all
+ * communication rings in the bank.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_response_handler(unsigned long bank_addr)
+{
+	struct adf_etr_bank_data *bank = (void *)bank_addr;
+
+	/* Handle all the responses nad reenable IRQs */
+	adf_ring_response_handler(bank);
+	WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number,
+				   bank->irq_mask);
+}
+EXPORT_SYMBOL_GPL(adf_response_handler);
+
+static inline int adf_get_cfg_int(struct adf_accel_dev *accel_dev,
+				  const char *section, const char *format,
+				  uint32_t key, uint32_t *value)
+{
+	char key_buf[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	char val_buf[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+
+	snprintf(key_buf, ADF_CFG_MAX_KEY_LEN_IN_BYTES, format, key);
+
+	if (adf_cfg_get_param_value(accel_dev, section, key_buf, val_buf))
+		return -EFAULT;
+
+	if (kstrtouint(val_buf, 10, value))
+		return -EFAULT;
+	return 0;
+}
+
+static void adf_enable_coalesc(struct adf_etr_bank_data *bank,
+			       const char *section, uint32_t bank_num_in_accel)
+{
+	if (adf_get_cfg_int(bank->accel_dev, section,
+			    ADF_ETRMGR_COALESCE_TIMER_FORMAT,
+			    bank_num_in_accel, &bank->irq_coalesc_timer))
+		bank->irq_coalesc_timer = ADF_COALESCING_DEF_TIME;
+
+	if (ADF_COALESCING_MAX_TIME < bank->irq_coalesc_timer ||
+	    ADF_COALESCING_MIN_TIME > bank->irq_coalesc_timer)
+		bank->irq_coalesc_timer = ADF_COALESCING_DEF_TIME;
+}
+
+static int adf_init_bank(struct adf_accel_dev *accel_dev,
+			 struct adf_etr_bank_data *bank,
+			 uint32_t bank_num, void __iomem *csr_addr)
+{
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	struct adf_etr_ring_data *ring;
+	struct adf_etr_ring_data *tx_ring;
+	uint32_t i, coalesc_enabled;
+
+	memset(bank, 0, sizeof(*bank));
+	bank->bank_number = bank_num;
+	bank->csr_addr = csr_addr;
+	bank->accel_dev = accel_dev;
+	spin_lock_init(&bank->lock);
+
+	/* Enable IRQ coalescing always. This will allow to use
+	 * the optimised flag and coalesc register.
+	 * If it is disabled in the config file just use min time value */
+	if (adf_get_cfg_int(accel_dev, "Accelerator0",
+			    ADF_ETRMGR_COALESCING_ENABLED_FORMAT,
+			    bank_num, &coalesc_enabled) && coalesc_enabled)
+		adf_enable_coalesc(bank, "Accelerator0", bank_num);
+	else
+		bank->irq_coalesc_timer = ADF_COALESCING_MIN_TIME;
+
+	for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+		WRITE_CSR_RING_CONFIG(csr_addr, bank_num, i, 0);
+		WRITE_CSR_RING_BASE(csr_addr, bank_num, i, 0);
+		ring = &bank->rings[i];
+		if (hw_data->tx_rings_mask & (1 << i)) {
+			ring->inflights = kzalloc_node(sizeof(atomic_t),
+						       GFP_KERNEL,
+						       accel_dev->numa_node);
+			if (!ring->inflights)
+				goto err;
+		} else {
+			if (i < hw_data->tx_rx_gap) {
+				pr_err("QAT: Invalid tx rings mask config\n");
+				goto err;
+			}
+			tx_ring = &bank->rings[i - hw_data->tx_rx_gap];
+			ring->inflights = tx_ring->inflights;
+		}
+	}
+	if (adf_bank_debugfs_add(bank)) {
+		pr_err("QAT: Failed to add bank debugfs entry\n");
+		goto err;
+	}
+
+	WRITE_CSR_INT_SRCSEL(csr_addr, bank_num);
+	return 0;
+err:
+	for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+		ring = &bank->rings[i];
+		if (hw_data->tx_rings_mask & (1 << i) && ring->inflights)
+			kfree(ring->inflights);
+	}
+	return -ENOMEM;
+}
+
+/**
+ * adf_init_etr_data() - Initialize transport rings for acceleration device
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function is the initializes the communications channels (rings) to the
+ * acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_init_etr_data(struct adf_accel_dev *accel_dev)
+{
+	struct adf_etr_data *etr_data;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	void __iomem *csr_addr;
+	uint32_t size;
+	uint32_t num_banks = 0;
+	int i, ret;
+
+	etr_data = kzalloc_node(sizeof(*etr_data), GFP_KERNEL,
+				accel_dev->numa_node);
+	if (!etr_data)
+		return -ENOMEM;
+
+	num_banks = GET_MAX_BANKS(accel_dev);
+	size = num_banks * sizeof(struct adf_etr_bank_data);
+	etr_data->banks = kzalloc_node(size, GFP_KERNEL, accel_dev->numa_node);
+	if (!etr_data->banks) {
+		ret = -ENOMEM;
+		goto err_bank;
+	}
+
+	accel_dev->transport = etr_data;
+	i = hw_data->get_etr_bar_id(hw_data);
+	csr_addr = accel_dev->accel_pci_dev.pci_bars[i].virt_addr;
+
+	/* accel_dev->debugfs_dir should always be non-NULL here */
+	etr_data->debug = debugfs_create_dir("transport",
+					     accel_dev->debugfs_dir);
+	if (!etr_data->debug) {
+		pr_err("QAT: Unable to create transport debugfs entry\n");
+		ret = -ENOENT;
+		goto err_bank_debug;
+	}
+
+	for (i = 0; i < num_banks; i++) {
+		ret = adf_init_bank(accel_dev, &etr_data->banks[i], i,
+				    csr_addr);
+		if (ret)
+			goto err_bank_all;
+	}
+
+	return 0;
+
+err_bank_all:
+	debugfs_remove(etr_data->debug);
+err_bank_debug:
+	kfree(etr_data->banks);
+err_bank:
+	kfree(etr_data);
+	accel_dev->transport = NULL;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adf_init_etr_data);
+
+static void cleanup_bank(struct adf_etr_bank_data *bank)
+{
+	uint32_t i;
+
+	for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+		struct adf_accel_dev *accel_dev = bank->accel_dev;
+		struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+		struct adf_etr_ring_data *ring = &bank->rings[i];
+
+		if (bank->ring_mask & (1 << i))
+			adf_cleanup_ring(ring);
+
+		if (hw_data->tx_rings_mask & (1 << i))
+			kfree(ring->inflights);
+	}
+	adf_bank_debugfs_rm(bank);
+	memset(bank, 0, sizeof(*bank));
+}
+
+static void adf_cleanup_etr_handles(struct adf_accel_dev *accel_dev)
+{
+	struct adf_etr_data *etr_data = accel_dev->transport;
+	uint32_t i, num_banks = GET_MAX_BANKS(accel_dev);
+
+	for (i = 0; i < num_banks; i++)
+		cleanup_bank(&etr_data->banks[i]);
+}
+
+/**
+ * adf_cleanup_etr_data() - Clear transport rings for acceleration device
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function is the clears the communications channels (rings) of the
+ * acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_cleanup_etr_data(struct adf_accel_dev *accel_dev)
+{
+	struct adf_etr_data *etr_data = accel_dev->transport;
+
+	if (etr_data) {
+		adf_cleanup_etr_handles(accel_dev);
+		debugfs_remove(etr_data->debug);
+		kfree(etr_data->banks);
+		kfree(etr_data);
+		accel_dev->transport = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(adf_cleanup_etr_data);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_debug.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_debug.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,304 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include "adf_accel_devices.h"
+#include "adf_transport_internal.h"
+#include "adf_transport_access_macros.h"
+
+static DEFINE_MUTEX(ring_read_lock);
+static DEFINE_MUTEX(bank_read_lock);
+
+static void *adf_ring_start(struct seq_file *sfile, loff_t *pos)
+{
+	struct adf_etr_ring_data *ring = sfile->private;
+
+	mutex_lock(&ring_read_lock);
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
+		     ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
+		return NULL;
+
+	return ring->base_addr +
+		(ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
+}
+
+static void *adf_ring_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+	struct adf_etr_ring_data *ring = sfile->private;
+
+	if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
+		     ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
+		return NULL;
+
+	return ring->base_addr +
+		(ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
+}
+
+static int adf_ring_show(struct seq_file *sfile, void *v)
+{
+	struct adf_etr_ring_data *ring = sfile->private;
+	struct adf_etr_bank_data *bank = ring->bank;
+	uint32_t *msg = v;
+	void __iomem *csr = ring->bank->csr_addr;
+	int i, x;
+
+	if (v == SEQ_START_TOKEN) {
+		int head, tail, empty;
+
+		head = READ_CSR_RING_HEAD(csr, bank->bank_number,
+					  ring->ring_number);
+		tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
+					  ring->ring_number);
+		empty = READ_CSR_E_STAT(csr, bank->bank_number);
+
+		seq_puts(sfile, "------- Ring configuration -------\n");
+		seq_printf(sfile, "ring num %d, bank num %d\n",
+			   ring->ring_number, ring->bank->bank_number);
+		seq_printf(sfile, "head %x, tail %x, empty: %d\n",
+			   head, tail, (empty & 1 << ring->ring_number)
+			   >> ring->ring_number);
+		seq_printf(sfile, "ring size %d, msg size %d\n",
+			   ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size),
+			   ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
+		seq_puts(sfile, "----------- Ring data ------------\n");
+		return 0;
+	}
+	seq_printf(sfile, "%p:", msg);
+	x = 0;
+	i = 0;
+	for (; i < (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2); i++) {
+		seq_printf(sfile, " %08X", *(msg + i));
+		if ((ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2) != i + 1 &&
+		    (++x == 8)) {
+			seq_printf(sfile, "\n%p:", msg + i + 1);
+			x = 0;
+		}
+	}
+	seq_puts(sfile, "\n");
+	return 0;
+}
+
+static void adf_ring_stop(struct seq_file *sfile, void *v)
+{
+	mutex_unlock(&ring_read_lock);
+}
+
+static const struct seq_operations adf_ring_sops = {
+	.start = adf_ring_start,
+	.next = adf_ring_next,
+	.stop = adf_ring_stop,
+	.show = adf_ring_show
+};
+
+static int adf_ring_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &adf_ring_sops);
+
+	if (!ret) {
+		struct seq_file *seq_f = file->private_data;
+
+		seq_f->private = inode->i_private;
+	}
+	return ret;
+}
+
+static const struct file_operations adf_ring_debug_fops = {
+	.open = adf_ring_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release
+};
+
+int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
+{
+	struct adf_etr_ring_debug_entry *ring_debug;
+	char entry_name[8];
+
+	ring_debug = kzalloc(sizeof(*ring_debug), GFP_KERNEL);
+	if (!ring_debug)
+		return -ENOMEM;
+
+	strlcpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name));
+	snprintf(entry_name, sizeof(entry_name), "ring_%02d",
+		 ring->ring_number);
+
+	ring_debug->debug = debugfs_create_file(entry_name, S_IRUSR,
+						ring->bank->bank_debug_dir,
+						ring, &adf_ring_debug_fops);
+	if (!ring_debug->debug) {
+		pr_err("QAT: Failed to create ring debug entry.\n");
+		kfree(ring_debug);
+		return -EFAULT;
+	}
+	ring->ring_debug = ring_debug;
+	return 0;
+}
+
+void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring)
+{
+	if (ring->ring_debug) {
+		debugfs_remove(ring->ring_debug->debug);
+		kfree(ring->ring_debug);
+		ring->ring_debug = NULL;
+	}
+}
+
+static void *adf_bank_start(struct seq_file *sfile, loff_t *pos)
+{
+	mutex_lock(&bank_read_lock);
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	if (*pos >= ADF_ETR_MAX_RINGS_PER_BANK)
+		return NULL;
+
+	return pos;
+}
+
+static void *adf_bank_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+	if (++(*pos) >= ADF_ETR_MAX_RINGS_PER_BANK)
+		return NULL;
+
+	return pos;
+}
+
+static int adf_bank_show(struct seq_file *sfile, void *v)
+{
+	struct adf_etr_bank_data *bank = sfile->private;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(sfile, "------- Bank %d configuration -------\n",
+			   bank->bank_number);
+	} else {
+		int ring_id = *((int *)v) - 1;
+		struct adf_etr_ring_data *ring = &bank->rings[ring_id];
+		void __iomem *csr = bank->csr_addr;
+		int head, tail, empty;
+
+		if (!(bank->ring_mask & 1 << ring_id))
+			return 0;
+
+		head = READ_CSR_RING_HEAD(csr, bank->bank_number,
+					  ring->ring_number);
+		tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
+					  ring->ring_number);
+		empty = READ_CSR_E_STAT(csr, bank->bank_number);
+
+		seq_printf(sfile,
+			   "ring num %02d, head %04x, tail %04x, empty: %d\n",
+			   ring->ring_number, head, tail,
+			   (empty & 1 << ring->ring_number) >>
+			   ring->ring_number);
+	}
+	return 0;
+}
+
+static void adf_bank_stop(struct seq_file *sfile, void *v)
+{
+	mutex_unlock(&bank_read_lock);
+}
+
+static const struct seq_operations adf_bank_sops = {
+	.start = adf_bank_start,
+	.next = adf_bank_next,
+	.stop = adf_bank_stop,
+	.show = adf_bank_show
+};
+
+static int adf_bank_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &adf_bank_sops);
+
+	if (!ret) {
+		struct seq_file *seq_f = file->private_data;
+
+		seq_f->private = inode->i_private;
+	}
+	return ret;
+}
+
+static const struct file_operations adf_bank_debug_fops = {
+	.open = adf_bank_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release
+};
+
+int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
+{
+	struct adf_accel_dev *accel_dev = bank->accel_dev;
+	struct dentry *parent = accel_dev->transport->debug;
+	char name[8];
+
+	snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
+	bank->bank_debug_dir = debugfs_create_dir(name, parent);
+	if (!bank->bank_debug_dir) {
+		pr_err("QAT: Failed to create bank debug dir.\n");
+		return -EFAULT;
+	}
+
+	bank->bank_debug_cfg = debugfs_create_file("config", S_IRUSR,
+						   bank->bank_debug_dir, bank,
+						   &adf_bank_debug_fops);
+	if (!bank->bank_debug_cfg) {
+		pr_err("QAT: Failed to create bank debug entry.\n");
+		debugfs_remove(bank->bank_debug_dir);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank)
+{
+	debugfs_remove(bank->bank_debug_cfg);
+	debugfs_remove(bank->bank_debug_dir);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_TRANSPORT_H
+#define ADF_TRANSPORT_H
+
+#include "adf_accel_devices.h"
+
+struct adf_etr_ring_data;
+
+typedef void (*adf_callback_fn)(void *resp_msg);
+
+int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+		    uint32_t bank_num, uint32_t num_mgs, uint32_t msg_size,
+		    const char *ring_name, adf_callback_fn callback,
+		    int poll_mode, struct adf_etr_ring_data **ring_ptr);
+
+int adf_send_message(struct adf_etr_ring_data *ring, uint32_t *msg);
+void adf_remove_ring(struct adf_etr_ring_data *ring);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_internal.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_internal.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/adf_transport_internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/adf_transport_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,118 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_TRANSPORT_INTRN_H
+#define ADF_TRANSPORT_INTRN_H
+
+#include <linux/interrupt.h>
+#include <linux/atomic.h>
+#include <linux/spinlock_types.h>
+#include "adf_transport.h"
+
+struct adf_etr_ring_debug_entry {
+	char ring_name[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	struct dentry *debug;
+};
+
+struct adf_etr_ring_data {
+	void *base_addr;
+	atomic_t *inflights;
+	spinlock_t lock;	/* protects ring data struct */
+	adf_callback_fn callback;
+	struct adf_etr_bank_data *bank;
+	dma_addr_t dma_addr;
+	uint16_t head;
+	uint16_t tail;
+	uint8_t ring_number;
+	uint8_t ring_size;
+	uint8_t msg_size;
+	uint8_t reserved;
+	struct adf_etr_ring_debug_entry *ring_debug;
+} __packed;
+
+struct adf_etr_bank_data {
+	struct adf_etr_ring_data rings[ADF_ETR_MAX_RINGS_PER_BANK];
+	struct tasklet_struct resp_hanlder;
+	void __iomem *csr_addr;
+	struct adf_accel_dev *accel_dev;
+	uint32_t irq_coalesc_timer;
+	uint16_t ring_mask;
+	uint16_t irq_mask;
+	spinlock_t lock;	/* protects bank data struct */
+	struct dentry *bank_debug_dir;
+	struct dentry *bank_debug_cfg;
+	uint32_t bank_number;
+} __packed;
+
+struct adf_etr_data {
+	struct adf_etr_bank_data *banks;
+	struct dentry *debug;
+};
+
+void adf_response_handler(unsigned long bank_addr);
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+int adf_bank_debugfs_add(struct adf_etr_bank_data *bank);
+void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank);
+int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name);
+void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring);
+#else
+static inline int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
+{
+	return 0;
+}
+
+#define adf_bank_debugfs_rm(bank) do {} while (0)
+
+static inline int adf_ring_debugfs_add(struct adf_etr_ring_data *ring,
+				       const char *name)
+{
+	return 0;
+}
+
+#define adf_ring_debugfs_rm(ring) do {} while (0)
+#endif
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,316 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef _ICP_QAT_FW_H_
+#define _ICP_QAT_FW_H_
+#include <linux/types.h>
+#include "icp_qat_hw.h"
+
+#define QAT_FIELD_SET(flags, val, bitpos, mask) \
+{ (flags) = (((flags) & (~((mask) << (bitpos)))) | \
+		(((val) & (mask)) << (bitpos))) ; }
+
+#define QAT_FIELD_GET(flags, bitpos, mask) \
+	(((flags) >> (bitpos)) & (mask))
+
+#define ICP_QAT_FW_REQ_DEFAULT_SZ 128
+#define ICP_QAT_FW_RESP_DEFAULT_SZ 32
+#define ICP_QAT_FW_COMN_ONE_BYTE_SHIFT 8
+#define ICP_QAT_FW_COMN_SINGLE_BYTE_MASK 0xFF
+#define ICP_QAT_FW_NUM_LONGWORDS_1 1
+#define ICP_QAT_FW_NUM_LONGWORDS_2 2
+#define ICP_QAT_FW_NUM_LONGWORDS_3 3
+#define ICP_QAT_FW_NUM_LONGWORDS_4 4
+#define ICP_QAT_FW_NUM_LONGWORDS_5 5
+#define ICP_QAT_FW_NUM_LONGWORDS_6 6
+#define ICP_QAT_FW_NUM_LONGWORDS_7 7
+#define ICP_QAT_FW_NUM_LONGWORDS_10 10
+#define ICP_QAT_FW_NUM_LONGWORDS_13 13
+#define ICP_QAT_FW_NULL_REQ_SERV_ID 1
+
+enum icp_qat_fw_comn_resp_serv_id {
+	ICP_QAT_FW_COMN_RESP_SERV_NULL,
+	ICP_QAT_FW_COMN_RESP_SERV_CPM_FW,
+	ICP_QAT_FW_COMN_RESP_SERV_DELIMITER
+};
+
+enum icp_qat_fw_comn_request_id {
+	ICP_QAT_FW_COMN_REQ_NULL = 0,
+	ICP_QAT_FW_COMN_REQ_CPM_FW_PKE = 3,
+	ICP_QAT_FW_COMN_REQ_CPM_FW_LA = 4,
+	ICP_QAT_FW_COMN_REQ_CPM_FW_DMA = 7,
+	ICP_QAT_FW_COMN_REQ_CPM_FW_COMP = 9,
+	ICP_QAT_FW_COMN_REQ_DELIMITER
+};
+
+struct icp_qat_fw_comn_req_hdr_cd_pars {
+	union {
+		struct {
+			uint64_t content_desc_addr;
+			uint16_t content_desc_resrvd1;
+			uint8_t content_desc_params_sz;
+			uint8_t content_desc_hdr_resrvd2;
+			uint32_t content_desc_resrvd3;
+		} s;
+		struct {
+			uint32_t serv_specif_fields[4];
+		} s1;
+	} u;
+};
+
+struct icp_qat_fw_comn_req_mid {
+	uint64_t opaque_data;
+	uint64_t src_data_addr;
+	uint64_t dest_data_addr;
+	uint32_t src_length;
+	uint32_t dst_length;
+};
+
+struct icp_qat_fw_comn_req_cd_ctrl {
+	uint32_t content_desc_ctrl_lw[ICP_QAT_FW_NUM_LONGWORDS_5];
+};
+
+struct icp_qat_fw_comn_req_hdr {
+	uint8_t resrvd1;
+	uint8_t service_cmd_id;
+	uint8_t service_type;
+	uint8_t hdr_flags;
+	uint16_t serv_specif_flags;
+	uint16_t comn_req_flags;
+};
+
+struct icp_qat_fw_comn_req_rqpars {
+	uint32_t serv_specif_rqpars_lw[ICP_QAT_FW_NUM_LONGWORDS_13];
+};
+
+struct icp_qat_fw_comn_req {
+	struct icp_qat_fw_comn_req_hdr comn_hdr;
+	struct icp_qat_fw_comn_req_hdr_cd_pars cd_pars;
+	struct icp_qat_fw_comn_req_mid comn_mid;
+	struct icp_qat_fw_comn_req_rqpars serv_specif_rqpars;
+	struct icp_qat_fw_comn_req_cd_ctrl cd_ctrl;
+};
+
+struct icp_qat_fw_comn_error {
+	uint8_t xlat_err_code;
+	uint8_t cmp_err_code;
+};
+
+struct icp_qat_fw_comn_resp_hdr {
+	uint8_t resrvd1;
+	uint8_t service_id;
+	uint8_t response_type;
+	uint8_t hdr_flags;
+	struct icp_qat_fw_comn_error comn_error;
+	uint8_t comn_status;
+	uint8_t cmd_id;
+};
+
+struct icp_qat_fw_comn_resp {
+	struct icp_qat_fw_comn_resp_hdr comn_hdr;
+	uint64_t opaque_data;
+	uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4];
+};
+
+#define ICP_QAT_FW_COMN_REQ_FLAG_SET 1
+#define ICP_QAT_FW_COMN_REQ_FLAG_CLR 0
+#define ICP_QAT_FW_COMN_VALID_FLAG_BITPOS 7
+#define ICP_QAT_FW_COMN_VALID_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK 0x7F
+
+#define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \
+	icp_qat_fw_comn_req_hdr_t.service_type
+
+#define ICP_QAT_FW_COMN_OV_SRV_TYPE_SET(icp_qat_fw_comn_req_hdr_t, val) \
+	icp_qat_fw_comn_req_hdr_t.service_type = val
+
+#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_GET(icp_qat_fw_comn_req_hdr_t) \
+	icp_qat_fw_comn_req_hdr_t.service_cmd_id
+
+#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_SET(icp_qat_fw_comn_req_hdr_t, val) \
+	icp_qat_fw_comn_req_hdr_t.service_cmd_id = val
+
+#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_GET(hdr_t) \
+	ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_t.hdr_flags)
+
+#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_SET(hdr_t, val) \
+	ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val)
+
+#define ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_flags) \
+	QAT_FIELD_GET(hdr_flags, \
+	ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \
+	ICP_QAT_FW_COMN_VALID_FLAG_MASK)
+
+#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_GET(hdr_flags) \
+	(hdr_flags & ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK)
+
+#define ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) \
+	QAT_FIELD_SET((hdr_t.hdr_flags), (val), \
+	ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \
+	ICP_QAT_FW_COMN_VALID_FLAG_MASK)
+
+#define ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(valid) \
+	(((valid) & ICP_QAT_FW_COMN_VALID_FLAG_MASK) << \
+	 ICP_QAT_FW_COMN_VALID_FLAG_BITPOS)
+
+#define QAT_COMN_PTR_TYPE_BITPOS 0
+#define QAT_COMN_PTR_TYPE_MASK 0x1
+#define QAT_COMN_CD_FLD_TYPE_BITPOS 1
+#define QAT_COMN_CD_FLD_TYPE_MASK 0x1
+#define QAT_COMN_PTR_TYPE_FLAT 0x0
+#define QAT_COMN_PTR_TYPE_SGL 0x1
+#define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0
+#define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1
+
+#define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \
+	((((cdt) & QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) \
+	 | (((ptr) & QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS))
+
+#define ICP_QAT_FW_COMN_PTR_TYPE_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_CD_FLD_TYPE_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_COMN_CD_FLD_TYPE_BITPOS, \
+			QAT_COMN_CD_FLD_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_PTR_TYPE_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_COMN_PTR_TYPE_BITPOS, \
+			QAT_COMN_PTR_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_COMN_CD_FLD_TYPE_BITPOS, \
+			QAT_COMN_CD_FLD_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4
+#define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0
+#define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0
+#define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F
+
+#define ICP_QAT_FW_COMN_NEXT_ID_GET(cd_ctrl_hdr_t) \
+	((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) \
+	>> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+	{ ((cd_ctrl_hdr_t)->next_curr_id) = ((((cd_ctrl_hdr_t)->next_curr_id) \
+	& ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+	((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+	 & ICP_QAT_FW_COMN_NEXT_ID_MASK)); }
+
+#define ICP_QAT_FW_COMN_CURR_ID_GET(cd_ctrl_hdr_t) \
+	(((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+	{ ((cd_ctrl_hdr_t)->next_curr_id) = ((((cd_ctrl_hdr_t)->next_curr_id) \
+	& ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+	((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)); }
+
+#define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7
+#define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1
+#define QAT_COMN_RESP_CMP_STATUS_BITPOS 5
+#define QAT_COMN_RESP_CMP_STATUS_MASK 0x1
+#define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4
+#define QAT_COMN_RESP_XLAT_STATUS_MASK 0x1
+#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS 3
+#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK 0x1
+
+#define ICP_QAT_FW_COMN_RESP_STATUS_BUILD(crypto, comp, xlat, eolb) \
+	((((crypto) & QAT_COMN_RESP_CRYPTO_STATUS_MASK) << \
+	QAT_COMN_RESP_CRYPTO_STATUS_BITPOS) | \
+	(((comp) & QAT_COMN_RESP_CMP_STATUS_MASK) << \
+	QAT_COMN_RESP_CMP_STATUS_BITPOS) | \
+	(((xlat) & QAT_COMN_RESP_XLAT_STATUS_MASK) << \
+	QAT_COMN_RESP_XLAT_STATUS_BITPOS) | \
+	(((eolb) & QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) << \
+	QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS))
+
+#define ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(status) \
+	QAT_FIELD_GET(status, QAT_COMN_RESP_CRYPTO_STATUS_BITPOS, \
+	QAT_COMN_RESP_CRYPTO_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(status) \
+	QAT_FIELD_GET(status, QAT_COMN_RESP_CMP_STATUS_BITPOS, \
+	QAT_COMN_RESP_CMP_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(status) \
+	QAT_FIELD_GET(status, QAT_COMN_RESP_XLAT_STATUS_BITPOS, \
+	QAT_COMN_RESP_XLAT_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(status) \
+	QAT_FIELD_GET(status, QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS, \
+	QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK)
+
+#define ICP_QAT_FW_COMN_STATUS_FLAG_OK 0
+#define ICP_QAT_FW_COMN_STATUS_FLAG_ERROR 1
+#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_CLR 0
+#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET 1
+#define ERR_CODE_NO_ERROR 0
+#define ERR_CODE_INVALID_BLOCK_TYPE -1
+#define ERR_CODE_NO_MATCH_ONES_COMP -2
+#define ERR_CODE_TOO_MANY_LEN_OR_DIS -3
+#define ERR_CODE_INCOMPLETE_LEN -4
+#define ERR_CODE_RPT_LEN_NO_FIRST_LEN -5
+#define ERR_CODE_RPT_GT_SPEC_LEN -6
+#define ERR_CODE_INV_LIT_LEN_CODE_LEN -7
+#define ERR_CODE_INV_DIS_CODE_LEN -8
+#define ERR_CODE_INV_LIT_LEN_DIS_IN_BLK -9
+#define ERR_CODE_DIS_TOO_FAR_BACK -10
+#define ERR_CODE_OVERFLOW_ERROR -11
+#define ERR_CODE_SOFT_ERROR -12
+#define ERR_CODE_FATAL_ERROR -13
+#define ERR_CODE_SSM_ERROR -14
+#define ERR_CODE_ENDPOINT_ERROR -15
+
+enum icp_qat_fw_slice {
+	ICP_QAT_FW_SLICE_NULL = 0,
+	ICP_QAT_FW_SLICE_CIPHER = 1,
+	ICP_QAT_FW_SLICE_AUTH = 2,
+	ICP_QAT_FW_SLICE_DRAM_RD = 3,
+	ICP_QAT_FW_SLICE_DRAM_WR = 4,
+	ICP_QAT_FW_SLICE_COMP = 5,
+	ICP_QAT_FW_SLICE_XLAT = 6,
+	ICP_QAT_FW_SLICE_DELIMITER
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef _ICP_QAT_FW_INIT_ADMIN_H_
+#define _ICP_QAT_FW_INIT_ADMIN_H_
+
+#include "icp_qat_fw.h"
+
+enum icp_qat_fw_init_admin_cmd_id {
+	ICP_QAT_FW_INIT_ME = 0,
+	ICP_QAT_FW_TRNG_ENABLE = 1,
+	ICP_QAT_FW_TRNG_DISABLE = 2,
+	ICP_QAT_FW_CONSTANTS_CFG = 3,
+	ICP_QAT_FW_STATUS_GET = 4,
+	ICP_QAT_FW_COUNTERS_GET = 5,
+	ICP_QAT_FW_LOOPBACK = 6,
+	ICP_QAT_FW_HEARTBEAT_SYNC = 7,
+	ICP_QAT_FW_HEARTBEAT_GET = 8
+};
+
+enum icp_qat_fw_init_admin_resp_status {
+	ICP_QAT_FW_INIT_RESP_STATUS_SUCCESS = 0,
+	ICP_QAT_FW_INIT_RESP_STATUS_FAIL
+};
+
+struct icp_qat_fw_init_admin_req {
+	uint16_t init_cfg_sz;
+	uint8_t resrvd1;
+	uint8_t init_admin_cmd_id;
+	uint32_t resrvd2;
+	uint64_t opaque_data;
+	uint64_t init_cfg_ptr;
+	uint64_t resrvd3;
+};
+
+struct icp_qat_fw_init_admin_resp_hdr {
+	uint8_t flags;
+	uint8_t resrvd1;
+	uint8_t status;
+	uint8_t init_admin_cmd_id;
+};
+
+struct icp_qat_fw_init_admin_resp_pars {
+	union {
+		uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_4];
+		struct {
+			uint32_t version_patch_num;
+			uint8_t context_id;
+			uint8_t ae_id;
+			uint16_t resrvd1;
+			uint64_t resrvd2;
+		} s1;
+		struct {
+			uint64_t req_rec_count;
+			uint64_t resp_sent_count;
+		} s2;
+	} u;
+};
+
+struct icp_qat_fw_init_admin_resp {
+	struct icp_qat_fw_init_admin_resp_hdr init_resp_hdr;
+	union {
+		uint32_t resrvd2;
+		struct {
+			uint16_t version_minor_num;
+			uint16_t version_major_num;
+		} s;
+	} u;
+	uint64_t opaque_data;
+	struct icp_qat_fw_init_admin_resp_pars init_resp_pars;
+};
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_OK 0
+#define ICP_QAT_FW_COMN_HEARTBEAT_BLOCKED 1
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS 0
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_STATUS_RESRVD_FLD_MASK 0xFE
+#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_GET(hdr_t) \
+	ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(hdr_t.flags)
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_SET(hdr_t, val) \
+	ICP_QAT_FW_COMN_HEARTBEAT_FLAG_SET(hdr_t, val)
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(flags) \
+	QAT_FIELD_GET(flags, \
+		 ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS, \
+		 ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK)
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_la.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_la.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_la.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_la.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,404 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef _ICP_QAT_FW_LA_H_
+#define _ICP_QAT_FW_LA_H_
+#include "icp_qat_fw.h"
+
+enum icp_qat_fw_la_cmd_id {
+	ICP_QAT_FW_LA_CMD_CIPHER = 0,
+	ICP_QAT_FW_LA_CMD_AUTH = 1,
+	ICP_QAT_FW_LA_CMD_CIPHER_HASH = 2,
+	ICP_QAT_FW_LA_CMD_HASH_CIPHER = 3,
+	ICP_QAT_FW_LA_CMD_TRNG_GET_RANDOM = 4,
+	ICP_QAT_FW_LA_CMD_TRNG_TEST = 5,
+	ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE = 6,
+	ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE = 7,
+	ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE = 8,
+	ICP_QAT_FW_LA_CMD_MGF1 = 9,
+	ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP = 10,
+	ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP = 11,
+	ICP_QAT_FW_LA_CMD_DELIMITER = 12
+};
+
+#define ICP_QAT_FW_LA_ICV_VER_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK
+#define ICP_QAT_FW_LA_ICV_VER_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR
+#define ICP_QAT_FW_LA_TRNG_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK
+#define ICP_QAT_FW_LA_TRNG_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR
+
+struct icp_qat_fw_la_bulk_req {
+	struct icp_qat_fw_comn_req_hdr comn_hdr;
+	struct icp_qat_fw_comn_req_hdr_cd_pars cd_pars;
+	struct icp_qat_fw_comn_req_mid comn_mid;
+	struct icp_qat_fw_comn_req_rqpars serv_specif_rqpars;
+	struct icp_qat_fw_comn_req_cd_ctrl cd_ctrl;
+};
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS 1
+#define ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS 0
+#define QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS 12
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO 1
+#define QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK 0x1
+#define QAT_LA_GCM_IV_LEN_FLAG_BITPOS 11
+#define QAT_LA_GCM_IV_LEN_FLAG_MASK 0x1
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER 1
+#define ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER 0
+#define QAT_LA_DIGEST_IN_BUFFER_BITPOS	10
+#define QAT_LA_DIGEST_IN_BUFFER_MASK 0x1
+#define ICP_QAT_FW_LA_SNOW_3G_PROTO 4
+#define ICP_QAT_FW_LA_GCM_PROTO	2
+#define ICP_QAT_FW_LA_CCM_PROTO	1
+#define ICP_QAT_FW_LA_NO_PROTO 0
+#define QAT_LA_PROTO_BITPOS 7
+#define QAT_LA_PROTO_MASK 0x7
+#define ICP_QAT_FW_LA_CMP_AUTH_RES 1
+#define ICP_QAT_FW_LA_NO_CMP_AUTH_RES 0
+#define QAT_LA_CMP_AUTH_RES_BITPOS 6
+#define QAT_LA_CMP_AUTH_RES_MASK 0x1
+#define ICP_QAT_FW_LA_RET_AUTH_RES 1
+#define ICP_QAT_FW_LA_NO_RET_AUTH_RES 0
+#define QAT_LA_RET_AUTH_RES_BITPOS 5
+#define QAT_LA_RET_AUTH_RES_MASK 0x1
+#define ICP_QAT_FW_LA_UPDATE_STATE 1
+#define ICP_QAT_FW_LA_NO_UPDATE_STATE 0
+#define QAT_LA_UPDATE_STATE_BITPOS 4
+#define QAT_LA_UPDATE_STATE_MASK 0x1
+#define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP 0
+#define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_SHRAM_CP 1
+#define QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS 3
+#define QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK 0x1
+#define ICP_QAT_FW_CIPH_IV_64BIT_PTR 0
+#define ICP_QAT_FW_CIPH_IV_16BYTE_DATA 1
+#define QAT_LA_CIPH_IV_FLD_BITPOS 2
+#define QAT_LA_CIPH_IV_FLD_MASK   0x1
+#define ICP_QAT_FW_LA_PARTIAL_NONE 0
+#define ICP_QAT_FW_LA_PARTIAL_START 1
+#define ICP_QAT_FW_LA_PARTIAL_MID 3
+#define ICP_QAT_FW_LA_PARTIAL_END 2
+#define QAT_LA_PARTIAL_BITPOS 0
+#define QAT_LA_PARTIAL_MASK 0x3
+#define ICP_QAT_FW_LA_FLAGS_BUILD(zuc_proto, gcm_iv_len, auth_rslt, proto, \
+	cmp_auth, ret_auth, update_state, \
+	ciph_iv, ciphcfg, partial) \
+	(((zuc_proto & QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK) << \
+	QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS) | \
+	((gcm_iv_len & QAT_LA_GCM_IV_LEN_FLAG_MASK) << \
+	QAT_LA_GCM_IV_LEN_FLAG_BITPOS) | \
+	((auth_rslt & QAT_LA_DIGEST_IN_BUFFER_MASK) << \
+	QAT_LA_DIGEST_IN_BUFFER_BITPOS) | \
+	((proto & QAT_LA_PROTO_MASK) << \
+	QAT_LA_PROTO_BITPOS)	| \
+	((cmp_auth & QAT_LA_CMP_AUTH_RES_MASK) << \
+	QAT_LA_CMP_AUTH_RES_BITPOS) | \
+	((ret_auth & QAT_LA_RET_AUTH_RES_MASK) << \
+	QAT_LA_RET_AUTH_RES_BITPOS) | \
+	((update_state & QAT_LA_UPDATE_STATE_MASK) << \
+	QAT_LA_UPDATE_STATE_BITPOS) | \
+	((ciph_iv & QAT_LA_CIPH_IV_FLD_MASK) << \
+	QAT_LA_CIPH_IV_FLD_BITPOS) | \
+	((ciphcfg & QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK) << \
+	QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS) | \
+	((partial & QAT_LA_PARTIAL_MASK) << \
+	QAT_LA_PARTIAL_BITPOS))
+
+#define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_CIPH_IV_FLD_BITPOS, \
+	QAT_LA_CIPH_IV_FLD_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \
+	QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK)
+
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \
+	QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_GCM_IV_LEN_FLAG_BITPOS, \
+	QAT_LA_GCM_IV_LEN_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_PROTO_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_PROTO_BITPOS, QAT_LA_PROTO_MASK)
+
+#define ICP_QAT_FW_LA_CMP_AUTH_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_CMP_AUTH_RES_BITPOS, \
+	QAT_LA_CMP_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_RET_AUTH_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_RET_AUTH_RES_BITPOS, \
+	QAT_LA_RET_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_DIGEST_IN_BUFFER_BITPOS, \
+	QAT_LA_DIGEST_IN_BUFFER_MASK)
+
+#define ICP_QAT_FW_LA_UPDATE_STATE_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_UPDATE_STATE_BITPOS, \
+	QAT_LA_UPDATE_STATE_MASK)
+
+#define ICP_QAT_FW_LA_PARTIAL_GET(flags) \
+	QAT_FIELD_GET(flags, QAT_LA_PARTIAL_BITPOS, \
+	QAT_LA_PARTIAL_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_CIPH_IV_FLD_BITPOS, \
+	QAT_LA_CIPH_IV_FLD_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \
+	QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK)
+
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \
+	QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_GCM_IV_LEN_FLAG_BITPOS, \
+	QAT_LA_GCM_IV_LEN_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_PROTO_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_PROTO_BITPOS, \
+	QAT_LA_PROTO_MASK)
+
+#define ICP_QAT_FW_LA_CMP_AUTH_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_CMP_AUTH_RES_BITPOS, \
+	QAT_LA_CMP_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_RET_AUTH_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_RET_AUTH_RES_BITPOS, \
+	QAT_LA_RET_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_DIGEST_IN_BUFFER_BITPOS, \
+	QAT_LA_DIGEST_IN_BUFFER_MASK)
+
+#define ICP_QAT_FW_LA_UPDATE_STATE_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_UPDATE_STATE_BITPOS, \
+	QAT_LA_UPDATE_STATE_MASK)
+
+#define ICP_QAT_FW_LA_PARTIAL_SET(flags, val) \
+	QAT_FIELD_SET(flags, val, QAT_LA_PARTIAL_BITPOS, \
+	QAT_LA_PARTIAL_MASK)
+
+struct icp_qat_fw_cipher_req_hdr_cd_pars {
+	union {
+		struct {
+			uint64_t content_desc_addr;
+			uint16_t content_desc_resrvd1;
+			uint8_t content_desc_params_sz;
+			uint8_t content_desc_hdr_resrvd2;
+			uint32_t content_desc_resrvd3;
+		} s;
+		struct {
+			uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+		} s1;
+	} u;
+};
+
+struct icp_qat_fw_cipher_auth_req_hdr_cd_pars {
+	union {
+		struct {
+			uint64_t content_desc_addr;
+			uint16_t content_desc_resrvd1;
+			uint8_t content_desc_params_sz;
+			uint8_t content_desc_hdr_resrvd2;
+			uint32_t content_desc_resrvd3;
+		} s;
+		struct {
+			uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+		} sl;
+	} u;
+};
+
+struct icp_qat_fw_cipher_cd_ctrl_hdr {
+	uint8_t cipher_state_sz;
+	uint8_t cipher_key_sz;
+	uint8_t cipher_cfg_offset;
+	uint8_t next_curr_id;
+	uint8_t cipher_padding_sz;
+	uint8_t resrvd1;
+	uint16_t resrvd2;
+	uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_3];
+};
+
+struct icp_qat_fw_auth_cd_ctrl_hdr {
+	uint32_t resrvd1;
+	uint8_t resrvd2;
+	uint8_t hash_flags;
+	uint8_t hash_cfg_offset;
+	uint8_t next_curr_id;
+	uint8_t resrvd3;
+	uint8_t outer_prefix_sz;
+	uint8_t final_sz;
+	uint8_t inner_res_sz;
+	uint8_t resrvd4;
+	uint8_t inner_state1_sz;
+	uint8_t inner_state2_offset;
+	uint8_t inner_state2_sz;
+	uint8_t outer_config_offset;
+	uint8_t outer_state1_sz;
+	uint8_t outer_res_sz;
+	uint8_t outer_prefix_offset;
+};
+
+struct icp_qat_fw_cipher_auth_cd_ctrl_hdr {
+	uint8_t cipher_state_sz;
+	uint8_t cipher_key_sz;
+	uint8_t cipher_cfg_offset;
+	uint8_t next_curr_id_cipher;
+	uint8_t cipher_padding_sz;
+	uint8_t hash_flags;
+	uint8_t hash_cfg_offset;
+	uint8_t next_curr_id_auth;
+	uint8_t resrvd1;
+	uint8_t outer_prefix_sz;
+	uint8_t final_sz;
+	uint8_t inner_res_sz;
+	uint8_t resrvd2;
+	uint8_t inner_state1_sz;
+	uint8_t inner_state2_offset;
+	uint8_t inner_state2_sz;
+	uint8_t outer_config_offset;
+	uint8_t outer_state1_sz;
+	uint8_t outer_res_sz;
+	uint8_t outer_prefix_offset;
+};
+
+#define ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED 1
+#define ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED 0
+#define ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX	240
+#define ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET \
+	(sizeof(struct icp_qat_fw_la_cipher_req_params_t))
+#define ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET (0)
+
+struct icp_qat_fw_la_cipher_req_params {
+	uint32_t cipher_offset;
+	uint32_t cipher_length;
+	union {
+		uint32_t cipher_IV_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+		struct {
+			uint64_t cipher_IV_ptr;
+			uint64_t resrvd1;
+		} s;
+	} u;
+};
+
+struct icp_qat_fw_la_auth_req_params {
+	uint32_t auth_off;
+	uint32_t auth_len;
+	union {
+		uint64_t auth_partial_st_prefix;
+		uint64_t aad_adr;
+	} u1;
+	uint64_t auth_res_addr;
+	union {
+		uint8_t inner_prefix_sz;
+		uint8_t aad_sz;
+	} u2;
+	uint8_t resrvd1;
+	uint8_t hash_state_sz;
+	uint8_t auth_res_sz;
+} __packed;
+
+struct icp_qat_fw_la_auth_req_params_resrvd_flds {
+	uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_6];
+	union {
+		uint8_t inner_prefix_sz;
+		uint8_t aad_sz;
+	} u2;
+	uint8_t resrvd1;
+	uint16_t resrvd2;
+};
+
+struct icp_qat_fw_la_resp {
+	struct icp_qat_fw_comn_resp_hdr comn_resp;
+	uint64_t opaque_data;
+	uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4];
+};
+
+#define ICP_QAT_FW_CIPHER_NEXT_ID_GET(cd_ctrl_hdr_t) \
+	((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \
+	  ICP_QAT_FW_COMN_NEXT_ID_MASK) >> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_CIPHER_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_cipher = \
+	((((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+	& ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+	((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+	& ICP_QAT_FW_COMN_NEXT_ID_MASK)) }
+
+#define ICP_QAT_FW_CIPHER_CURR_ID_GET(cd_ctrl_hdr_t) \
+	(((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+	& ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_CIPHER_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_cipher = \
+	((((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+	& ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+	((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)) }
+
+#define ICP_QAT_FW_AUTH_NEXT_ID_GET(cd_ctrl_hdr_t) \
+	((((cd_ctrl_hdr_t)->next_curr_id_auth) & ICP_QAT_FW_COMN_NEXT_ID_MASK) \
+	>> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_AUTH_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_auth = \
+	((((cd_ctrl_hdr_t)->next_curr_id_auth) \
+	& ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+	((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+	& ICP_QAT_FW_COMN_NEXT_ID_MASK)) }
+
+#define ICP_QAT_FW_AUTH_CURR_ID_GET(cd_ctrl_hdr_t) \
+	(((cd_ctrl_hdr_t)->next_curr_id_auth) \
+	& ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_AUTH_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_auth = \
+	((((cd_ctrl_hdr_t)->next_curr_id_auth) \
+	& ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+	((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)) }
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef __ICP_QAT_FW_LOADER_HANDLE_H__
+#define __ICP_QAT_FW_LOADER_HANDLE_H__
+#include "icp_qat_uclo.h"
+
+struct icp_qat_fw_loader_ae_data {
+	unsigned int state;
+	unsigned int ustore_size;
+	unsigned int free_addr;
+	unsigned int free_size;
+	unsigned int live_ctx_mask;
+};
+
+struct icp_qat_fw_loader_hal_handle {
+	struct icp_qat_fw_loader_ae_data aes[ICP_QAT_UCLO_MAX_AE];
+	unsigned int ae_mask;
+	unsigned int slice_mask;
+	unsigned int revision_id;
+	unsigned int ae_max_num;
+	unsigned int upc_mask;
+	unsigned int max_ustore;
+};
+
+struct icp_qat_fw_loader_handle {
+	struct icp_qat_fw_loader_hal_handle *hal_handle;
+	void *obj_handle;
+	void __iomem *hal_sram_addr_v;
+	void __iomem *hal_cap_g_ctl_csr_addr_v;
+	void __iomem *hal_cap_ae_xfer_csr_addr_v;
+	void __iomem *hal_cap_ae_local_csr_addr_v;
+	void __iomem *hal_ep_csr_addr_v;
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_hal.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_hal.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_hal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_hal.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef __ICP_QAT_HAL_H
+#define __ICP_QAT_HAL_H
+#include "icp_qat_fw_loader_handle.h"
+
+enum hal_global_csr {
+	MISC_CONTROL = 0x04,
+	ICP_RESET = 0x0c,
+	ICP_GLOBAL_CLK_ENABLE = 0x50
+};
+
+enum hal_ae_csr {
+	USTORE_ADDRESS = 0x000,
+	USTORE_DATA_LOWER = 0x004,
+	USTORE_DATA_UPPER = 0x008,
+	ALU_OUT = 0x010,
+	CTX_ARB_CNTL = 0x014,
+	CTX_ENABLES = 0x018,
+	CC_ENABLE = 0x01c,
+	CSR_CTX_POINTER = 0x020,
+	CTX_STS_INDIRECT = 0x040,
+	ACTIVE_CTX_STATUS = 0x044,
+	CTX_SIG_EVENTS_INDIRECT = 0x048,
+	CTX_SIG_EVENTS_ACTIVE = 0x04c,
+	CTX_WAKEUP_EVENTS_INDIRECT = 0x050,
+	LM_ADDR_0_INDIRECT = 0x060,
+	LM_ADDR_1_INDIRECT = 0x068,
+	INDIRECT_LM_ADDR_0_BYTE_INDEX = 0x0e0,
+	INDIRECT_LM_ADDR_1_BYTE_INDEX = 0x0e8,
+	FUTURE_COUNT_SIGNAL_INDIRECT = 0x078,
+	TIMESTAMP_LOW = 0x0c0,
+	TIMESTAMP_HIGH = 0x0c4,
+	PROFILE_COUNT = 0x144,
+	SIGNATURE_ENABLE = 0x150,
+	AE_MISC_CONTROL = 0x160,
+	LOCAL_CSR_STATUS = 0x180,
+};
+
+#define UA_ECS                      (0x1 << 31)
+#define ACS_ABO_BITPOS              31
+#define ACS_ACNO                    0x7
+#define CE_ENABLE_BITPOS            0x8
+#define CE_LMADDR_0_GLOBAL_BITPOS   16
+#define CE_LMADDR_1_GLOBAL_BITPOS   17
+#define CE_NN_MODE_BITPOS           20
+#define CE_REG_PAR_ERR_BITPOS       25
+#define CE_BREAKPOINT_BITPOS        27
+#define CE_CNTL_STORE_PARITY_ERROR_BITPOS 29
+#define CE_INUSE_CONTEXTS_BITPOS    31
+#define CE_NN_MODE                  (0x1 << CE_NN_MODE_BITPOS)
+#define CE_INUSE_CONTEXTS           (0x1 << CE_INUSE_CONTEXTS_BITPOS)
+#define XCWE_VOLUNTARY              (0x1)
+#define LCS_STATUS          (0x1)
+#define MMC_SHARE_CS_BITPOS         2
+#define GLOBAL_CSR                0xA00
+
+#define SET_CAP_CSR(handle, csr, val) \
+	ADF_CSR_WR(handle->hal_cap_g_ctl_csr_addr_v, csr, val)
+#define GET_CAP_CSR(handle, csr) \
+	ADF_CSR_RD(handle->hal_cap_g_ctl_csr_addr_v, csr)
+#define SET_GLB_CSR(handle, csr, val) SET_CAP_CSR(handle, csr + GLOBAL_CSR, val)
+#define GET_GLB_CSR(handle, csr) GET_CAP_CSR(handle, GLOBAL_CSR + csr)
+#define AE_CSR(handle, ae) \
+	(handle->hal_cap_ae_local_csr_addr_v + \
+	((ae & handle->hal_handle->ae_mask) << 12))
+#define AE_CSR_ADDR(handle, ae, csr) (AE_CSR(handle, ae) + (0x3ff & csr))
+#define SET_AE_CSR(handle, ae, csr, val) \
+	ADF_CSR_WR(AE_CSR_ADDR(handle, ae, csr), 0, val)
+#define GET_AE_CSR(handle, ae, csr) ADF_CSR_RD(AE_CSR_ADDR(handle, ae, csr), 0)
+#define AE_XFER(handle, ae) \
+	(handle->hal_cap_ae_xfer_csr_addr_v + \
+	((ae & handle->hal_handle->ae_mask) << 12))
+#define AE_XFER_ADDR(handle, ae, reg) (AE_XFER(handle, ae) + \
+	((reg & 0xff) << 2))
+#define SET_AE_XFER(handle, ae, reg, val) \
+	ADF_CSR_WR(AE_XFER_ADDR(handle, ae, reg), 0, val)
+#define SRAM_WRITE(handle, addr, val) \
+	ADF_CSR_WR(handle->hal_sram_addr_v, addr, val)
+#define SRAM_READ(handle, addr) ADF_CSR_RD(handle->hal_sram_addr_v, addr)
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_hw.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_hw.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,305 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef _ICP_QAT_HW_H_
+#define _ICP_QAT_HW_H_
+
+enum icp_qat_hw_ae_id {
+	ICP_QAT_HW_AE_0 = 0,
+	ICP_QAT_HW_AE_1 = 1,
+	ICP_QAT_HW_AE_2 = 2,
+	ICP_QAT_HW_AE_3 = 3,
+	ICP_QAT_HW_AE_4 = 4,
+	ICP_QAT_HW_AE_5 = 5,
+	ICP_QAT_HW_AE_6 = 6,
+	ICP_QAT_HW_AE_7 = 7,
+	ICP_QAT_HW_AE_8 = 8,
+	ICP_QAT_HW_AE_9 = 9,
+	ICP_QAT_HW_AE_10 = 10,
+	ICP_QAT_HW_AE_11 = 11,
+	ICP_QAT_HW_AE_DELIMITER = 12
+};
+
+enum icp_qat_hw_qat_id {
+	ICP_QAT_HW_QAT_0 = 0,
+	ICP_QAT_HW_QAT_1 = 1,
+	ICP_QAT_HW_QAT_2 = 2,
+	ICP_QAT_HW_QAT_3 = 3,
+	ICP_QAT_HW_QAT_4 = 4,
+	ICP_QAT_HW_QAT_5 = 5,
+	ICP_QAT_HW_QAT_DELIMITER = 6
+};
+
+enum icp_qat_hw_auth_algo {
+	ICP_QAT_HW_AUTH_ALGO_NULL = 0,
+	ICP_QAT_HW_AUTH_ALGO_SHA1 = 1,
+	ICP_QAT_HW_AUTH_ALGO_MD5 = 2,
+	ICP_QAT_HW_AUTH_ALGO_SHA224 = 3,
+	ICP_QAT_HW_AUTH_ALGO_SHA256 = 4,
+	ICP_QAT_HW_AUTH_ALGO_SHA384 = 5,
+	ICP_QAT_HW_AUTH_ALGO_SHA512 = 6,
+	ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC = 7,
+	ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC = 8,
+	ICP_QAT_HW_AUTH_ALGO_AES_F9 = 9,
+	ICP_QAT_HW_AUTH_ALGO_GALOIS_128 = 10,
+	ICP_QAT_HW_AUTH_ALGO_GALOIS_64 = 11,
+	ICP_QAT_HW_AUTH_ALGO_KASUMI_F9 = 12,
+	ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 = 13,
+	ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 = 14,
+	ICP_QAT_HW_AUTH_RESERVED_1 = 15,
+	ICP_QAT_HW_AUTH_RESERVED_2 = 16,
+	ICP_QAT_HW_AUTH_ALGO_SHA3_256 = 17,
+	ICP_QAT_HW_AUTH_RESERVED_3 = 18,
+	ICP_QAT_HW_AUTH_ALGO_SHA3_512 = 19,
+	ICP_QAT_HW_AUTH_ALGO_DELIMITER = 20
+};
+
+enum icp_qat_hw_auth_mode {
+	ICP_QAT_HW_AUTH_MODE0 = 0,
+	ICP_QAT_HW_AUTH_MODE1 = 1,
+	ICP_QAT_HW_AUTH_MODE2 = 2,
+	ICP_QAT_HW_AUTH_MODE_DELIMITER = 3
+};
+
+struct icp_qat_hw_auth_config {
+	uint32_t config;
+	uint32_t reserved;
+};
+
+#define QAT_AUTH_MODE_BITPOS 4
+#define QAT_AUTH_MODE_MASK 0xF
+#define QAT_AUTH_ALGO_BITPOS 0
+#define QAT_AUTH_ALGO_MASK 0xF
+#define QAT_AUTH_CMP_BITPOS 8
+#define QAT_AUTH_CMP_MASK 0x7F
+#define QAT_AUTH_SHA3_PADDING_BITPOS 16
+#define QAT_AUTH_SHA3_PADDING_MASK 0x1
+#define QAT_AUTH_ALGO_SHA3_BITPOS 22
+#define QAT_AUTH_ALGO_SHA3_MASK 0x3
+#define ICP_QAT_HW_AUTH_CONFIG_BUILD(mode, algo, cmp_len) \
+	(((mode & QAT_AUTH_MODE_MASK) << QAT_AUTH_MODE_BITPOS) | \
+	((algo & QAT_AUTH_ALGO_MASK) << QAT_AUTH_ALGO_BITPOS) | \
+	(((algo >> 4) & QAT_AUTH_ALGO_SHA3_MASK) << \
+	 QAT_AUTH_ALGO_SHA3_BITPOS) | \
+	 (((((algo == ICP_QAT_HW_AUTH_ALGO_SHA3_256) || \
+	(algo == ICP_QAT_HW_AUTH_ALGO_SHA3_512)) ? 1 : 0) \
+	& QAT_AUTH_SHA3_PADDING_MASK) << QAT_AUTH_SHA3_PADDING_BITPOS) | \
+	((cmp_len & QAT_AUTH_CMP_MASK) << QAT_AUTH_CMP_BITPOS))
+
+struct icp_qat_hw_auth_counter {
+	__be32 counter;
+	uint32_t reserved;
+};
+
+#define QAT_AUTH_COUNT_MASK 0xFFFFFFFF
+#define QAT_AUTH_COUNT_BITPOS 0
+#define ICP_QAT_HW_AUTH_COUNT_BUILD(val) \
+	(((val) & QAT_AUTH_COUNT_MASK) << QAT_AUTH_COUNT_BITPOS)
+
+struct icp_qat_hw_auth_setup {
+	struct icp_qat_hw_auth_config auth_config;
+	struct icp_qat_hw_auth_counter auth_counter;
+};
+
+#define QAT_HW_DEFAULT_ALIGNMENT 8
+#define QAT_HW_ROUND_UP(val, n) (((val) + ((n)-1)) & (~(n-1)))
+#define ICP_QAT_HW_NULL_STATE1_SZ 32
+#define ICP_QAT_HW_MD5_STATE1_SZ 16
+#define ICP_QAT_HW_SHA1_STATE1_SZ 20
+#define ICP_QAT_HW_SHA224_STATE1_SZ 32
+#define ICP_QAT_HW_SHA256_STATE1_SZ 32
+#define ICP_QAT_HW_SHA3_256_STATE1_SZ 32
+#define ICP_QAT_HW_SHA384_STATE1_SZ 64
+#define ICP_QAT_HW_SHA512_STATE1_SZ 64
+#define ICP_QAT_HW_SHA3_512_STATE1_SZ 64
+#define ICP_QAT_HW_SHA3_224_STATE1_SZ 28
+#define ICP_QAT_HW_SHA3_384_STATE1_SZ 48
+#define ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ 16
+#define ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ 16
+#define ICP_QAT_HW_AES_F9_STATE1_SZ 32
+#define ICP_QAT_HW_KASUMI_F9_STATE1_SZ 16
+#define ICP_QAT_HW_GALOIS_128_STATE1_SZ 16
+#define ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ 8
+#define ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ 8
+#define ICP_QAT_HW_NULL_STATE2_SZ 32
+#define ICP_QAT_HW_MD5_STATE2_SZ 16
+#define ICP_QAT_HW_SHA1_STATE2_SZ 20
+#define ICP_QAT_HW_SHA224_STATE2_SZ 32
+#define ICP_QAT_HW_SHA256_STATE2_SZ 32
+#define ICP_QAT_HW_SHA3_256_STATE2_SZ 0
+#define ICP_QAT_HW_SHA384_STATE2_SZ 64
+#define ICP_QAT_HW_SHA512_STATE2_SZ 64
+#define ICP_QAT_HW_SHA3_512_STATE2_SZ 0
+#define ICP_QAT_HW_SHA3_224_STATE2_SZ 0
+#define ICP_QAT_HW_SHA3_384_STATE2_SZ 0
+#define ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ 16
+#define ICP_QAT_HW_AES_CBC_MAC_KEY_SZ 16
+#define ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ 16
+#define ICP_QAT_HW_F9_IK_SZ 16
+#define ICP_QAT_HW_F9_FK_SZ 16
+#define ICP_QAT_HW_KASUMI_F9_STATE2_SZ (ICP_QAT_HW_F9_IK_SZ + \
+	ICP_QAT_HW_F9_FK_SZ)
+#define ICP_QAT_HW_AES_F9_STATE2_SZ ICP_QAT_HW_KASUMI_F9_STATE2_SZ
+#define ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ 24
+#define ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ 32
+#define ICP_QAT_HW_GALOIS_H_SZ 16
+#define ICP_QAT_HW_GALOIS_LEN_A_SZ 8
+#define ICP_QAT_HW_GALOIS_E_CTR0_SZ 16
+
+struct icp_qat_hw_auth_sha512 {
+	struct icp_qat_hw_auth_setup inner_setup;
+	uint8_t state1[ICP_QAT_HW_SHA512_STATE1_SZ];
+	struct icp_qat_hw_auth_setup outer_setup;
+	uint8_t state2[ICP_QAT_HW_SHA512_STATE2_SZ];
+};
+
+struct icp_qat_hw_auth_algo_blk {
+	struct icp_qat_hw_auth_sha512 sha;
+};
+
+#define ICP_QAT_HW_GALOIS_LEN_A_BITPOS 0
+#define ICP_QAT_HW_GALOIS_LEN_A_MASK 0xFFFFFFFF
+
+enum icp_qat_hw_cipher_algo {
+	ICP_QAT_HW_CIPHER_ALGO_NULL = 0,
+	ICP_QAT_HW_CIPHER_ALGO_DES = 1,
+	ICP_QAT_HW_CIPHER_ALGO_3DES = 2,
+	ICP_QAT_HW_CIPHER_ALGO_AES128 = 3,
+	ICP_QAT_HW_CIPHER_ALGO_AES192 = 4,
+	ICP_QAT_HW_CIPHER_ALGO_AES256 = 5,
+	ICP_QAT_HW_CIPHER_ALGO_ARC4 = 6,
+	ICP_QAT_HW_CIPHER_ALGO_KASUMI = 7,
+	ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 = 8,
+	ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3 = 9,
+	ICP_QAT_HW_CIPHER_DELIMITER = 10
+};
+
+enum icp_qat_hw_cipher_mode {
+	ICP_QAT_HW_CIPHER_ECB_MODE = 0,
+	ICP_QAT_HW_CIPHER_CBC_MODE = 1,
+	ICP_QAT_HW_CIPHER_CTR_MODE = 2,
+	ICP_QAT_HW_CIPHER_F8_MODE = 3,
+	ICP_QAT_HW_CIPHER_XTS_MODE = 6,
+	ICP_QAT_HW_CIPHER_MODE_DELIMITER = 7
+};
+
+struct icp_qat_hw_cipher_config {
+	uint32_t val;
+	uint32_t reserved;
+};
+
+enum icp_qat_hw_cipher_dir {
+	ICP_QAT_HW_CIPHER_ENCRYPT = 0,
+	ICP_QAT_HW_CIPHER_DECRYPT = 1,
+};
+
+enum icp_qat_hw_cipher_convert {
+	ICP_QAT_HW_CIPHER_NO_CONVERT = 0,
+	ICP_QAT_HW_CIPHER_KEY_CONVERT = 1,
+};
+
+#define QAT_CIPHER_MODE_BITPOS 4
+#define QAT_CIPHER_MODE_MASK 0xF
+#define QAT_CIPHER_ALGO_BITPOS 0
+#define QAT_CIPHER_ALGO_MASK 0xF
+#define QAT_CIPHER_CONVERT_BITPOS 9
+#define QAT_CIPHER_CONVERT_MASK 0x1
+#define QAT_CIPHER_DIR_BITPOS 8
+#define QAT_CIPHER_DIR_MASK 0x1
+#define QAT_CIPHER_MODE_F8_KEY_SZ_MULT 2
+#define QAT_CIPHER_MODE_XTS_KEY_SZ_MULT 2
+#define ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, algo, convert, dir) \
+	(((mode & QAT_CIPHER_MODE_MASK) << QAT_CIPHER_MODE_BITPOS) | \
+	((algo & QAT_CIPHER_ALGO_MASK) << QAT_CIPHER_ALGO_BITPOS) | \
+	((convert & QAT_CIPHER_CONVERT_MASK) << QAT_CIPHER_CONVERT_BITPOS) | \
+	((dir & QAT_CIPHER_DIR_MASK) << QAT_CIPHER_DIR_BITPOS))
+#define ICP_QAT_HW_DES_BLK_SZ 8
+#define ICP_QAT_HW_3DES_BLK_SZ 8
+#define ICP_QAT_HW_NULL_BLK_SZ 8
+#define ICP_QAT_HW_AES_BLK_SZ 16
+#define ICP_QAT_HW_KASUMI_BLK_SZ 8
+#define ICP_QAT_HW_SNOW_3G_BLK_SZ 8
+#define ICP_QAT_HW_ZUC_3G_BLK_SZ 8
+#define ICP_QAT_HW_NULL_KEY_SZ 256
+#define ICP_QAT_HW_DES_KEY_SZ 8
+#define ICP_QAT_HW_3DES_KEY_SZ 24
+#define ICP_QAT_HW_AES_128_KEY_SZ 16
+#define ICP_QAT_HW_AES_192_KEY_SZ 24
+#define ICP_QAT_HW_AES_256_KEY_SZ 32
+#define ICP_QAT_HW_AES_128_F8_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+	QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_192_F8_KEY_SZ (ICP_QAT_HW_AES_192_KEY_SZ * \
+	QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_F8_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+	QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_128_XTS_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+	QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_XTS_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+	QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_KASUMI_KEY_SZ 16
+#define ICP_QAT_HW_KASUMI_F8_KEY_SZ (ICP_QAT_HW_KASUMI_KEY_SZ * \
+	QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_128_XTS_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+	QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_XTS_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+	QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_ARC4_KEY_SZ 256
+#define ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ 16
+#define ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ 16
+#define ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ 16
+#define ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ 16
+#define ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR 2
+#define INIT_SHRAM_CONSTANTS_TABLE_SZ 1024
+
+struct icp_qat_hw_cipher_aes256_f8 {
+	struct icp_qat_hw_cipher_config cipher_config;
+	uint8_t key[ICP_QAT_HW_AES_256_F8_KEY_SZ];
+};
+
+struct icp_qat_hw_cipher_algo_blk {
+	struct icp_qat_hw_cipher_aes256_f8 aes;
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_uclo.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_uclo.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/icp_qat_uclo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/icp_qat_uclo.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,377 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef __ICP_QAT_UCLO_H__
+#define __ICP_QAT_UCLO_H__
+
+#define ICP_QAT_AC_C_CPU_TYPE     0x00400000
+#define ICP_QAT_UCLO_MAX_AE       12
+#define ICP_QAT_UCLO_MAX_CTX      8
+#define ICP_QAT_UCLO_MAX_UIMAGE   (ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX)
+#define ICP_QAT_UCLO_MAX_USTORE   0x4000
+#define ICP_QAT_UCLO_MAX_XFER_REG 128
+#define ICP_QAT_UCLO_MAX_GPR_REG  128
+#define ICP_QAT_UCLO_MAX_NN_REG   128
+#define ICP_QAT_UCLO_MAX_LMEM_REG 1024
+#define ICP_QAT_UCLO_AE_ALL_CTX   0xff
+#define ICP_QAT_UOF_OBJID_LEN     8
+#define ICP_QAT_UOF_FID 0xc6c2
+#define ICP_QAT_UOF_MAJVER 0x4
+#define ICP_QAT_UOF_MINVER 0x11
+#define ICP_QAT_UOF_NN_MODE_NOTCARE   0xff
+#define ICP_QAT_UOF_OBJS        "UOF_OBJS"
+#define ICP_QAT_UOF_STRT        "UOF_STRT"
+#define ICP_QAT_UOF_GTID        "UOF_GTID"
+#define ICP_QAT_UOF_IMAG        "UOF_IMAG"
+#define ICP_QAT_UOF_IMEM        "UOF_IMEM"
+#define ICP_QAT_UOF_MSEG        "UOF_MSEG"
+#define ICP_QAT_UOF_LOCAL_SCOPE     1
+#define ICP_QAT_UOF_INIT_EXPR               0
+#define ICP_QAT_UOF_INIT_REG                1
+#define ICP_QAT_UOF_INIT_REG_CTX            2
+#define ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP   3
+
+#define ICP_QAT_CTX_MODE(ae_mode) ((ae_mode) & 0xf)
+#define ICP_QAT_NN_MODE(ae_mode) (((ae_mode) >> 0x4) & 0xf)
+#define ICP_QAT_SHARED_USTORE_MODE(ae_mode) (((ae_mode) >> 0xb) & 0x1)
+#define RELOADABLE_CTX_SHARED_MODE(ae_mode) (((ae_mode) >> 0xc) & 0x1)
+
+#define ICP_QAT_LOC_MEM0_MODE(ae_mode) (((ae_mode) >> 0x8) & 0x1)
+#define ICP_QAT_LOC_MEM1_MODE(ae_mode) (((ae_mode) >> 0x9) & 0x1)
+
+enum icp_qat_uof_mem_region {
+	ICP_QAT_UOF_SRAM_REGION = 0x0,
+	ICP_QAT_UOF_LMEM_REGION = 0x3,
+	ICP_QAT_UOF_UMEM_REGION = 0x5
+};
+
+enum icp_qat_uof_regtype {
+	ICP_NO_DEST,
+	ICP_GPA_REL,
+	ICP_GPA_ABS,
+	ICP_GPB_REL,
+	ICP_GPB_ABS,
+	ICP_SR_REL,
+	ICP_SR_RD_REL,
+	ICP_SR_WR_REL,
+	ICP_SR_ABS,
+	ICP_SR_RD_ABS,
+	ICP_SR_WR_ABS,
+	ICP_DR_REL,
+	ICP_DR_RD_REL,
+	ICP_DR_WR_REL,
+	ICP_DR_ABS,
+	ICP_DR_RD_ABS,
+	ICP_DR_WR_ABS,
+	ICP_LMEM,
+	ICP_LMEM0,
+	ICP_LMEM1,
+	ICP_NEIGH_REL,
+};
+
+struct icp_qat_uclo_page {
+	struct icp_qat_uclo_encap_page *encap_page;
+	struct icp_qat_uclo_region *region;
+	unsigned int flags;
+};
+
+struct icp_qat_uclo_region {
+	struct icp_qat_uclo_page *loaded;
+	struct icp_qat_uclo_page *page;
+};
+
+struct icp_qat_uclo_aeslice {
+	struct icp_qat_uclo_region *region;
+	struct icp_qat_uclo_page *page;
+	struct icp_qat_uclo_page *cur_page[ICP_QAT_UCLO_MAX_CTX];
+	struct icp_qat_uclo_encapme *encap_image;
+	unsigned int ctx_mask_assigned;
+	unsigned int new_uaddr[ICP_QAT_UCLO_MAX_CTX];
+};
+
+struct icp_qat_uclo_aedata {
+	unsigned int slice_num;
+	unsigned int eff_ustore_size;
+	struct icp_qat_uclo_aeslice ae_slices[ICP_QAT_UCLO_MAX_CTX];
+};
+
+struct icp_qat_uof_encap_obj {
+	char *beg_uof;
+	struct icp_qat_uof_objhdr *obj_hdr;
+	struct icp_qat_uof_chunkhdr *chunk_hdr;
+	struct icp_qat_uof_varmem_seg *var_mem_seg;
+};
+
+struct icp_qat_uclo_encap_uwblock {
+	unsigned int start_addr;
+	unsigned int words_num;
+	uint64_t micro_words;
+};
+
+struct icp_qat_uclo_encap_page {
+	unsigned int def_page;
+	unsigned int page_region;
+	unsigned int beg_addr_v;
+	unsigned int beg_addr_p;
+	unsigned int micro_words_num;
+	unsigned int uwblock_num;
+	struct icp_qat_uclo_encap_uwblock *uwblock;
+};
+
+struct icp_qat_uclo_encapme {
+	struct icp_qat_uof_image *img_ptr;
+	struct icp_qat_uclo_encap_page *page;
+	unsigned int ae_reg_num;
+	struct icp_qat_uof_ae_reg *ae_reg;
+	unsigned int init_regsym_num;
+	struct icp_qat_uof_init_regsym *init_regsym;
+	unsigned int sbreak_num;
+	struct icp_qat_uof_sbreak *sbreak;
+	unsigned int uwords_num;
+};
+
+struct icp_qat_uclo_init_mem_table {
+	unsigned int entry_num;
+	struct icp_qat_uof_initmem *init_mem;
+};
+
+struct icp_qat_uclo_objhdr {
+	char *file_buff;
+	unsigned int checksum;
+	unsigned int size;
+};
+
+struct icp_qat_uof_strtable {
+	unsigned int table_len;
+	unsigned int reserved;
+	uint64_t strings;
+};
+
+struct icp_qat_uclo_objhandle {
+	unsigned int prod_type;
+	unsigned int prod_rev;
+	struct icp_qat_uclo_objhdr *obj_hdr;
+	struct icp_qat_uof_encap_obj encap_uof_obj;
+	struct icp_qat_uof_strtable str_table;
+	struct icp_qat_uclo_encapme ae_uimage[ICP_QAT_UCLO_MAX_UIMAGE];
+	struct icp_qat_uclo_aedata ae_data[ICP_QAT_UCLO_MAX_AE];
+	struct icp_qat_uclo_init_mem_table init_mem_tab;
+	struct icp_qat_uof_batch_init *lm_init_tab[ICP_QAT_UCLO_MAX_AE];
+	struct icp_qat_uof_batch_init *umem_init_tab[ICP_QAT_UCLO_MAX_AE];
+	int uimage_num;
+	int uword_in_bytes;
+	int global_inited;
+	unsigned int ae_num;
+	unsigned int ustore_phy_size;
+	void *obj_buf;
+	uint64_t *uword_buf;
+};
+
+struct icp_qat_uof_uword_block {
+	unsigned int start_addr;
+	unsigned int words_num;
+	unsigned int uword_offset;
+	unsigned int reserved;
+};
+
+struct icp_qat_uof_filehdr {
+	unsigned short file_id;
+	unsigned short reserved1;
+	char min_ver;
+	char maj_ver;
+	unsigned short reserved2;
+	unsigned short max_chunks;
+	unsigned short num_chunks;
+};
+
+struct icp_qat_uof_filechunkhdr {
+	char chunk_id[ICP_QAT_UOF_OBJID_LEN];
+	unsigned int checksum;
+	unsigned int offset;
+	unsigned int size;
+};
+
+struct icp_qat_uof_objhdr {
+	unsigned int cpu_type;
+	unsigned short min_cpu_ver;
+	unsigned short max_cpu_ver;
+	short max_chunks;
+	short num_chunks;
+	unsigned int reserved1;
+	unsigned int reserved2;
+};
+
+struct icp_qat_uof_chunkhdr {
+	char chunk_id[ICP_QAT_UOF_OBJID_LEN];
+	unsigned int offset;
+	unsigned int size;
+};
+
+struct icp_qat_uof_memvar_attr {
+	unsigned int offset_in_byte;
+	unsigned int value;
+};
+
+struct icp_qat_uof_initmem {
+	unsigned int sym_name;
+	char region;
+	char scope;
+	unsigned short reserved1;
+	unsigned int addr;
+	unsigned int num_in_bytes;
+	unsigned int val_attr_num;
+};
+
+struct icp_qat_uof_init_regsym {
+	unsigned int sym_name;
+	char init_type;
+	char value_type;
+	char reg_type;
+	unsigned char ctx;
+	unsigned int reg_addr;
+	unsigned int value;
+};
+
+struct icp_qat_uof_varmem_seg {
+	unsigned int sram_base;
+	unsigned int sram_size;
+	unsigned int sram_alignment;
+	unsigned int sdram_base;
+	unsigned int sdram_size;
+	unsigned int sdram_alignment;
+	unsigned int sdram1_base;
+	unsigned int sdram1_size;
+	unsigned int sdram1_alignment;
+	unsigned int scratch_base;
+	unsigned int scratch_size;
+	unsigned int scratch_alignment;
+};
+
+struct icp_qat_uof_gtid {
+	char tool_id[ICP_QAT_UOF_OBJID_LEN];
+	int tool_ver;
+	unsigned int reserved1;
+	unsigned int reserved2;
+};
+
+struct icp_qat_uof_sbreak {
+	unsigned int page_num;
+	unsigned int virt_uaddr;
+	unsigned char sbreak_type;
+	unsigned char reg_type;
+	unsigned short reserved1;
+	unsigned int addr_offset;
+	unsigned int reg_addr;
+};
+
+struct icp_qat_uof_code_page {
+	unsigned int page_region;
+	unsigned int page_num;
+	unsigned char def_page;
+	unsigned char reserved2;
+	unsigned short reserved1;
+	unsigned int beg_addr_v;
+	unsigned int beg_addr_p;
+	unsigned int neigh_reg_tab_offset;
+	unsigned int uc_var_tab_offset;
+	unsigned int imp_var_tab_offset;
+	unsigned int imp_expr_tab_offset;
+	unsigned int code_area_offset;
+};
+
+struct icp_qat_uof_image {
+	unsigned int img_name;
+	unsigned int ae_assigned;
+	unsigned int ctx_assigned;
+	unsigned int cpu_type;
+	unsigned int entry_address;
+	unsigned int fill_pattern[2];
+	unsigned int reloadable_size;
+	unsigned char sensitivity;
+	unsigned char reserved;
+	unsigned short ae_mode;
+	unsigned short max_ver;
+	unsigned short min_ver;
+	unsigned short image_attrib;
+	unsigned short reserved2;
+	unsigned short page_region_num;
+	unsigned short numpages;
+	unsigned int reg_tab_offset;
+	unsigned int init_reg_sym_tab;
+	unsigned int sbreak_tab;
+	unsigned int app_metadata;
+};
+
+struct icp_qat_uof_objtable {
+	unsigned int entry_num;
+};
+
+struct icp_qat_uof_ae_reg {
+	unsigned int name;
+	unsigned int vis_name;
+	unsigned short type;
+	unsigned short addr;
+	unsigned short access_mode;
+	unsigned char visible;
+	unsigned char reserved1;
+	unsigned short ref_count;
+	unsigned short reserved2;
+	unsigned int xo_id;
+};
+
+struct icp_qat_uof_code_area {
+	unsigned int micro_words_num;
+	unsigned int uword_block_tab;
+};
+
+struct icp_qat_uof_batch_init {
+	unsigned int ae;
+	unsigned int addr;
+	unsigned int *value;
+	unsigned int size;
+	struct icp_qat_uof_batch_init *next;
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
+intel_qat-objs := adf_cfg.o \
+	adf_ctl_drv.o \
+	adf_dev_mgr.o \
+	adf_init.o \
+	adf_accel_engine.o \
+	adf_aer.o \
+	adf_transport.o \
+	qat_crypto.o \
+	qat_algs.o \
+	qat_uclo.o \
+	qat_hal.o
+
+intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_algs.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_algs.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_algs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_algs.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1038 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/crypto.h>
+#include <crypto/aead.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/hash.h>
+#include <crypto/algapi.h>
+#include <crypto/authenc.h>
+#include <crypto/rng.h>
+#include <linux/dma-mapping.h>
+#include "adf_accel_devices.h"
+#include "adf_transport.h"
+#include "adf_common_drv.h"
+#include "qat_crypto.h"
+#include "icp_qat_hw.h"
+#include "icp_qat_fw.h"
+#include "icp_qat_fw_la.h"
+
+#define QAT_AES_HW_CONFIG_ENC(alg) \
+	ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+			ICP_QAT_HW_CIPHER_NO_CONVERT, \
+			ICP_QAT_HW_CIPHER_ENCRYPT)
+
+#define QAT_AES_HW_CONFIG_DEC(alg) \
+	ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+			ICP_QAT_HW_CIPHER_KEY_CONVERT, \
+			ICP_QAT_HW_CIPHER_DECRYPT)
+
+static atomic_t active_dev;
+
+struct qat_alg_buf {
+	uint32_t len;
+	uint32_t resrvd;
+	uint64_t addr;
+} __packed;
+
+struct qat_alg_buf_list {
+	uint64_t resrvd;
+	uint32_t num_bufs;
+	uint32_t num_mapped_bufs;
+	struct qat_alg_buf bufers[];
+} __packed __aligned(64);
+
+/* Common content descriptor */
+struct qat_alg_cd {
+	union {
+		struct qat_enc { /* Encrypt content desc */
+			struct icp_qat_hw_cipher_algo_blk cipher;
+			struct icp_qat_hw_auth_algo_blk hash;
+		} qat_enc_cd;
+		struct qat_dec { /* Decrytp content desc */
+			struct icp_qat_hw_auth_algo_blk hash;
+			struct icp_qat_hw_cipher_algo_blk cipher;
+		} qat_dec_cd;
+	};
+} __aligned(64);
+
+#define MAX_AUTH_STATE_SIZE sizeof(struct icp_qat_hw_auth_algo_blk)
+
+struct qat_auth_state {
+	uint8_t data[MAX_AUTH_STATE_SIZE];
+} __aligned(64);
+
+struct qat_alg_session_ctx {
+	struct qat_alg_cd *enc_cd;
+	dma_addr_t enc_cd_paddr;
+	struct qat_alg_cd *dec_cd;
+	dma_addr_t dec_cd_paddr;
+	struct qat_auth_state *auth_hw_state_enc;
+	dma_addr_t auth_state_enc_paddr;
+	struct qat_auth_state *auth_hw_state_dec;
+	dma_addr_t auth_state_dec_paddr;
+	struct icp_qat_fw_la_bulk_req enc_fw_req_tmpl;
+	struct icp_qat_fw_la_bulk_req dec_fw_req_tmpl;
+	struct qat_crypto_instance *inst;
+	struct crypto_tfm *tfm;
+	struct crypto_shash *hash_tfm;
+	enum icp_qat_hw_auth_algo qat_hash_alg;
+	uint8_t salt[AES_BLOCK_SIZE];
+	spinlock_t lock;	/* protects qat_alg_session_ctx struct */
+};
+
+static int get_current_node(void)
+{
+	return cpu_data(current_thread_info()->cpu).phys_proc_id;
+}
+
+static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg)
+{
+	switch (qat_hash_alg) {
+	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		return ICP_QAT_HW_SHA1_STATE1_SZ;
+	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		return ICP_QAT_HW_SHA256_STATE1_SZ;
+	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		return ICP_QAT_HW_SHA512_STATE1_SZ;
+	default:
+		return -EFAULT;
+	};
+	return -EFAULT;
+}
+
+static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash,
+				  struct qat_alg_session_ctx *ctx,
+				  const uint8_t *auth_key,
+				  unsigned int auth_keylen, uint8_t *auth_state)
+{
+	struct {
+		struct shash_desc shash;
+		char ctx[crypto_shash_descsize(ctx->hash_tfm)];
+	} desc;
+	struct sha1_state sha1;
+	struct sha256_state sha256;
+	struct sha512_state sha512;
+	int block_size = crypto_shash_blocksize(ctx->hash_tfm);
+	int digest_size = crypto_shash_digestsize(ctx->hash_tfm);
+	uint8_t *ipad = auth_state;
+	uint8_t *opad = ipad + block_size;
+	__be32 *hash_state_out;
+	__be64 *hash512_state_out;
+	int i, offset;
+
+	desc.shash.tfm = ctx->hash_tfm;
+	desc.shash.flags = 0x0;
+
+	if (auth_keylen > block_size) {
+		char buff[SHA512_BLOCK_SIZE];
+		int ret = crypto_shash_digest(&desc.shash, auth_key,
+					      auth_keylen, buff);
+		if (ret)
+			return ret;
+
+		memcpy(ipad, buff, digest_size);
+		memcpy(opad, buff, digest_size);
+		memset(ipad + digest_size, 0, block_size - digest_size);
+		memset(opad + digest_size, 0, block_size - digest_size);
+	} else {
+		memcpy(ipad, auth_key, auth_keylen);
+		memcpy(opad, auth_key, auth_keylen);
+		memset(ipad + auth_keylen, 0, block_size - auth_keylen);
+		memset(opad + auth_keylen, 0, block_size - auth_keylen);
+	}
+
+	for (i = 0; i < block_size; i++) {
+		char *ipad_ptr = ipad + i;
+		char *opad_ptr = opad + i;
+		*ipad_ptr ^= 0x36;
+		*opad_ptr ^= 0x5C;
+	}
+
+	if (crypto_shash_init(&desc.shash))
+		return -EFAULT;
+
+	if (crypto_shash_update(&desc.shash, ipad, block_size))
+		return -EFAULT;
+
+	hash_state_out = (__be32 *)hash->sha.state1;
+	hash512_state_out = (__be64 *)hash_state_out;
+
+	switch (ctx->qat_hash_alg) {
+	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		if (crypto_shash_export(&desc.shash, &sha1))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+			*hash_state_out = cpu_to_be32(*(sha1.state + i));
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		if (crypto_shash_export(&desc.shash, &sha256))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+			*hash_state_out = cpu_to_be32(*(sha256.state + i));
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		if (crypto_shash_export(&desc.shash, &sha512))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 3; i++, hash512_state_out++)
+			*hash512_state_out = cpu_to_be64(*(sha512.state + i));
+		break;
+	default:
+		return -EFAULT;
+	}
+
+	if (crypto_shash_init(&desc.shash))
+		return -EFAULT;
+
+	if (crypto_shash_update(&desc.shash, opad, block_size))
+		return -EFAULT;
+
+	offset = round_up(qat_get_inter_state_size(ctx->qat_hash_alg), 8);
+	hash_state_out = (__be32 *)(hash->sha.state1 + offset);
+	hash512_state_out = (__be64 *)hash_state_out;
+
+	switch (ctx->qat_hash_alg) {
+	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		if (crypto_shash_export(&desc.shash, &sha1))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+			*hash_state_out = cpu_to_be32(*(sha1.state + i));
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		if (crypto_shash_export(&desc.shash, &sha256))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+			*hash_state_out = cpu_to_be32(*(sha256.state + i));
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		if (crypto_shash_export(&desc.shash, &sha512))
+			return -EFAULT;
+		for (i = 0; i < digest_size >> 3; i++, hash512_state_out++)
+			*hash512_state_out = cpu_to_be64(*(sha512.state + i));
+		break;
+	default:
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header)
+{
+	header->hdr_flags =
+		ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
+	header->service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_LA;
+	header->comn_req_flags =
+		ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_CD_FLD_TYPE_64BIT_ADR,
+					    QAT_COMN_PTR_TYPE_SGL);
+	ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags,
+					   ICP_QAT_FW_LA_DIGEST_IN_BUFFER);
+	ICP_QAT_FW_LA_PARTIAL_SET(header->serv_specif_flags,
+				  ICP_QAT_FW_LA_PARTIAL_NONE);
+	ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags,
+					   ICP_QAT_FW_CIPH_IV_16BYTE_DATA);
+	ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
+				ICP_QAT_FW_LA_NO_PROTO);
+	ICP_QAT_FW_LA_UPDATE_STATE_SET(header->serv_specif_flags,
+				       ICP_QAT_FW_LA_NO_UPDATE_STATE);
+}
+
+static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx,
+				    int alg, struct crypto_authenc_keys *keys)
+{
+	struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
+	unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+	struct qat_enc *enc_ctx = &ctx->enc_cd->qat_enc_cd;
+	struct icp_qat_hw_cipher_algo_blk *cipher = &enc_ctx->cipher;
+	struct icp_qat_hw_auth_algo_blk *hash =
+		(struct icp_qat_hw_auth_algo_blk *)((char *)enc_ctx +
+		sizeof(struct icp_qat_hw_auth_setup) + keys->enckeylen);
+	struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->enc_fw_req_tmpl;
+	struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars;
+	struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr;
+	void *ptr = &req_tmpl->cd_ctrl;
+	struct icp_qat_fw_cipher_cd_ctrl_hdr *cipher_cd_ctrl = ptr;
+	struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr;
+	struct icp_qat_fw_la_auth_req_params *auth_param =
+		(struct icp_qat_fw_la_auth_req_params *)
+		((char *)&req_tmpl->serv_specif_rqpars +
+		 sizeof(struct icp_qat_fw_la_cipher_req_params));
+
+	/* CD setup */
+	cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg);
+	memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
+	hash->sha.inner_setup.auth_config.config =
+		ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
+					     ctx->qat_hash_alg, digestsize);
+	hash->sha.inner_setup.auth_counter.counter =
+		cpu_to_be32(crypto_shash_blocksize(ctx->hash_tfm));
+
+	if (qat_alg_do_precomputes(hash, ctx, keys->authkey, keys->authkeylen,
+				   (uint8_t *)ctx->auth_hw_state_enc))
+		return -EFAULT;
+
+	/* Request setup */
+	qat_alg_init_common_hdr(header);
+	header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER_HASH;
+	ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags,
+				   ICP_QAT_FW_LA_RET_AUTH_RES);
+	ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags,
+				   ICP_QAT_FW_LA_NO_CMP_AUTH_RES);
+	cd_pars->u.s.content_desc_addr = ctx->enc_cd_paddr;
+	cd_pars->u.s.content_desc_params_sz = sizeof(struct qat_alg_cd) >> 3;
+
+	/* Cipher CD config setup */
+	cipher_cd_ctrl->cipher_key_sz = keys->enckeylen >> 3;
+	cipher_cd_ctrl->cipher_state_sz = AES_BLOCK_SIZE >> 3;
+	cipher_cd_ctrl->cipher_cfg_offset = 0;
+	ICP_QAT_FW_COMN_CURR_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+	ICP_QAT_FW_COMN_NEXT_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+	/* Auth CD config setup */
+	hash_cd_ctrl->hash_cfg_offset = ((char *)hash - (char *)cipher) >> 3;
+	hash_cd_ctrl->hash_flags = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED;
+	hash_cd_ctrl->inner_res_sz = digestsize;
+	hash_cd_ctrl->final_sz = digestsize;
+
+	switch (ctx->qat_hash_alg) {
+	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		hash_cd_ctrl->inner_state1_sz =
+			round_up(ICP_QAT_HW_SHA1_STATE1_SZ, 8);
+		hash_cd_ctrl->inner_state2_sz =
+			round_up(ICP_QAT_HW_SHA1_STATE2_SZ, 8);
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA256_STATE1_SZ;
+		hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA256_STATE2_SZ;
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA512_STATE1_SZ;
+		hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA512_STATE2_SZ;
+		break;
+	default:
+		break;
+	}
+	hash_cd_ctrl->inner_state2_offset = hash_cd_ctrl->hash_cfg_offset +
+			((sizeof(struct icp_qat_hw_auth_setup) +
+			 round_up(hash_cd_ctrl->inner_state1_sz, 8)) >> 3);
+	auth_param->u1.auth_partial_st_prefix = ctx->auth_state_enc_paddr +
+			sizeof(struct icp_qat_hw_auth_counter) +
+			round_up(hash_cd_ctrl->inner_state1_sz, 8);
+	ICP_QAT_FW_COMN_CURR_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+	ICP_QAT_FW_COMN_NEXT_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_DRAM_WR);
+	return 0;
+}
+
+static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx,
+				    int alg, struct crypto_authenc_keys *keys)
+{
+	struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
+	unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+	struct qat_dec *dec_ctx = &ctx->dec_cd->qat_dec_cd;
+	struct icp_qat_hw_auth_algo_blk *hash = &dec_ctx->hash;
+	struct icp_qat_hw_cipher_algo_blk *cipher =
+		(struct icp_qat_hw_cipher_algo_blk *)((char *)dec_ctx +
+		sizeof(struct icp_qat_hw_auth_setup) +
+		roundup(crypto_shash_digestsize(ctx->hash_tfm), 8) * 2);
+	struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->dec_fw_req_tmpl;
+	struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars;
+	struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr;
+	void *ptr = &req_tmpl->cd_ctrl;
+	struct icp_qat_fw_cipher_cd_ctrl_hdr *cipher_cd_ctrl = ptr;
+	struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr;
+	struct icp_qat_fw_la_auth_req_params *auth_param =
+		(struct icp_qat_fw_la_auth_req_params *)
+		((char *)&req_tmpl->serv_specif_rqpars +
+		sizeof(struct icp_qat_fw_la_cipher_req_params));
+
+	/* CD setup */
+	cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_DEC(alg);
+	memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
+	hash->sha.inner_setup.auth_config.config =
+		ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
+					     ctx->qat_hash_alg,
+					     digestsize);
+	hash->sha.inner_setup.auth_counter.counter =
+		cpu_to_be32(crypto_shash_blocksize(ctx->hash_tfm));
+
+	if (qat_alg_do_precomputes(hash, ctx, keys->authkey, keys->authkeylen,
+				   (uint8_t *)ctx->auth_hw_state_dec))
+		return -EFAULT;
+
+	/* Request setup */
+	qat_alg_init_common_hdr(header);
+	header->service_cmd_id = ICP_QAT_FW_LA_CMD_HASH_CIPHER;
+	ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags,
+				   ICP_QAT_FW_LA_NO_RET_AUTH_RES);
+	ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags,
+				   ICP_QAT_FW_LA_CMP_AUTH_RES);
+	cd_pars->u.s.content_desc_addr = ctx->dec_cd_paddr;
+	cd_pars->u.s.content_desc_params_sz = sizeof(struct qat_alg_cd) >> 3;
+
+	/* Cipher CD config setup */
+	cipher_cd_ctrl->cipher_key_sz = keys->enckeylen >> 3;
+	cipher_cd_ctrl->cipher_state_sz = AES_BLOCK_SIZE >> 3;
+	cipher_cd_ctrl->cipher_cfg_offset =
+		(sizeof(struct icp_qat_hw_auth_setup) +
+		 roundup(crypto_shash_digestsize(ctx->hash_tfm), 8) * 2) >> 3;
+	ICP_QAT_FW_COMN_CURR_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+	ICP_QAT_FW_COMN_NEXT_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_DRAM_WR);
+
+	/* Auth CD config setup */
+	hash_cd_ctrl->hash_cfg_offset = 0;
+	hash_cd_ctrl->hash_flags = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED;
+	hash_cd_ctrl->inner_res_sz = digestsize;
+	hash_cd_ctrl->final_sz = digestsize;
+
+	switch (ctx->qat_hash_alg) {
+	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		hash_cd_ctrl->inner_state1_sz =
+			round_up(ICP_QAT_HW_SHA1_STATE1_SZ, 8);
+		hash_cd_ctrl->inner_state2_sz =
+			round_up(ICP_QAT_HW_SHA1_STATE2_SZ, 8);
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA256_STATE1_SZ;
+		hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA256_STATE2_SZ;
+		break;
+	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA512_STATE1_SZ;
+		hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA512_STATE2_SZ;
+		break;
+	default:
+		break;
+	}
+
+	hash_cd_ctrl->inner_state2_offset = hash_cd_ctrl->hash_cfg_offset +
+			((sizeof(struct icp_qat_hw_auth_setup) +
+			 round_up(hash_cd_ctrl->inner_state1_sz, 8)) >> 3);
+	auth_param->u1.auth_partial_st_prefix = ctx->auth_state_enc_paddr +
+			sizeof(struct icp_qat_hw_auth_counter) +
+			round_up(hash_cd_ctrl->inner_state1_sz, 8);
+	auth_param->auth_res_sz = digestsize;
+	ICP_QAT_FW_COMN_CURR_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+	ICP_QAT_FW_COMN_NEXT_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+	return 0;
+}
+
+static int qat_alg_init_sessions(struct qat_alg_session_ctx *ctx,
+				 const uint8_t *key, unsigned int keylen)
+{
+	struct crypto_authenc_keys keys;
+	int alg;
+
+	if (crypto_rng_get_bytes(crypto_default_rng, ctx->salt, AES_BLOCK_SIZE))
+		return -EFAULT;
+
+	if (crypto_authenc_extractkeys(&keys, key, keylen))
+		goto bad_key;
+
+	switch (keys.enckeylen) {
+	case AES_KEYSIZE_128:
+		alg = ICP_QAT_HW_CIPHER_ALGO_AES128;
+		break;
+	case AES_KEYSIZE_192:
+		alg = ICP_QAT_HW_CIPHER_ALGO_AES192;
+		break;
+	case AES_KEYSIZE_256:
+		alg = ICP_QAT_HW_CIPHER_ALGO_AES256;
+		break;
+	default:
+		goto bad_key;
+		break;
+	}
+
+	if (qat_alg_init_enc_session(ctx, alg, &keys))
+		goto error;
+
+	if (qat_alg_init_dec_session(ctx, alg, &keys))
+		goto error;
+
+	return 0;
+bad_key:
+	crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	return -EINVAL;
+error:
+	return -EFAULT;
+}
+
+static int qat_alg_setkey(struct crypto_aead *tfm, const uint8_t *key,
+			  unsigned int keylen)
+{
+	struct qat_alg_session_ctx *ctx = crypto_aead_ctx(tfm);
+	struct device *dev;
+
+	spin_lock(&ctx->lock);
+	if (ctx->enc_cd) {
+		/* rekeying */
+		dev = &GET_DEV(ctx->inst->accel_dev);
+		memset(ctx->enc_cd, 0, sizeof(struct qat_alg_cd));
+		memset(ctx->dec_cd, 0, sizeof(struct qat_alg_cd));
+		memset(ctx->auth_hw_state_enc, 0,
+		       sizeof(struct qat_auth_state));
+		memset(ctx->auth_hw_state_dec, 0,
+		       sizeof(struct qat_auth_state));
+		memset(&ctx->enc_fw_req_tmpl, 0,
+		       sizeof(struct icp_qat_fw_la_bulk_req));
+		memset(&ctx->dec_fw_req_tmpl, 0,
+		       sizeof(struct icp_qat_fw_la_bulk_req));
+	} else {
+		/* new key */
+		int node = get_current_node();
+		struct qat_crypto_instance *inst =
+				qat_crypto_get_instance_node(node);
+		if (!inst) {
+			spin_unlock(&ctx->lock);
+			return -EINVAL;
+		}
+
+		dev = &GET_DEV(inst->accel_dev);
+		ctx->inst = inst;
+		ctx->enc_cd = dma_zalloc_coherent(dev,
+						  sizeof(struct qat_alg_cd),
+						  &ctx->enc_cd_paddr,
+						  GFP_ATOMIC);
+		if (!ctx->enc_cd) {
+			spin_unlock(&ctx->lock);
+			return -ENOMEM;
+		}
+		ctx->dec_cd = dma_zalloc_coherent(dev,
+						  sizeof(struct qat_alg_cd),
+						  &ctx->dec_cd_paddr,
+						  GFP_ATOMIC);
+		if (!ctx->dec_cd) {
+			spin_unlock(&ctx->lock);
+			goto out_free_enc;
+		}
+		ctx->auth_hw_state_enc =
+			dma_zalloc_coherent(dev, sizeof(struct qat_auth_state),
+					    &ctx->auth_state_enc_paddr,
+					    GFP_ATOMIC);
+		if (!ctx->auth_hw_state_enc) {
+			spin_unlock(&ctx->lock);
+			goto out_free_dec;
+		}
+		ctx->auth_hw_state_dec =
+			dma_zalloc_coherent(dev, sizeof(struct qat_auth_state),
+					    &ctx->auth_state_dec_paddr,
+					    GFP_ATOMIC);
+		if (!ctx->auth_hw_state_dec) {
+			spin_unlock(&ctx->lock);
+			goto out_free_auth_enc;
+		}
+	}
+	spin_unlock(&ctx->lock);
+	if (qat_alg_init_sessions(ctx, key, keylen))
+		goto out_free_all;
+
+	return 0;
+
+out_free_all:
+	dma_free_coherent(dev, sizeof(struct qat_auth_state),
+			  ctx->auth_hw_state_dec, ctx->auth_state_dec_paddr);
+	ctx->auth_hw_state_dec = NULL;
+out_free_auth_enc:
+	dma_free_coherent(dev, sizeof(struct qat_auth_state),
+			  ctx->auth_hw_state_enc, ctx->auth_state_enc_paddr);
+	ctx->auth_hw_state_enc = NULL;
+out_free_dec:
+	dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+			  ctx->dec_cd, ctx->dec_cd_paddr);
+	ctx->dec_cd = NULL;
+out_free_enc:
+	dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+			  ctx->enc_cd, ctx->enc_cd_paddr);
+	ctx->enc_cd = NULL;
+	return -ENOMEM;
+}
+
+static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
+			      struct qat_crypto_request *qat_req)
+{
+	struct device *dev = &GET_DEV(inst->accel_dev);
+	struct qat_alg_buf_list *bl = qat_req->buf.bl;
+	struct qat_alg_buf_list *blout = qat_req->buf.blout;
+	dma_addr_t blp = qat_req->buf.blp;
+	dma_addr_t blpout = qat_req->buf.bloutp;
+	size_t sz = qat_req->buf.sz;
+	int i, bufs = bl->num_bufs;
+
+	for (i = 0; i < bl->num_bufs; i++)
+		dma_unmap_single(dev, bl->bufers[i].addr,
+				 bl->bufers[i].len, DMA_BIDIRECTIONAL);
+
+	dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE);
+	kfree(bl);
+	if (blp != blpout) {
+		/* If out of place operation dma unmap only data */
+		int bufless = bufs - blout->num_mapped_bufs;
+
+		for (i = bufless; i < bufs; i++) {
+			dma_unmap_single(dev, blout->bufers[i].addr,
+					 blout->bufers[i].len,
+					 DMA_BIDIRECTIONAL);
+		}
+		dma_unmap_single(dev, blpout, sz, DMA_TO_DEVICE);
+		kfree(blout);
+	}
+}
+
+static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+			       struct scatterlist *assoc,
+			       struct scatterlist *sgl,
+			       struct scatterlist *sglout, uint8_t *iv,
+			       uint8_t ivlen,
+			       struct qat_crypto_request *qat_req)
+{
+	struct device *dev = &GET_DEV(inst->accel_dev);
+	int i, bufs = 0, n = sg_nents(sgl), assoc_n = sg_nents(assoc);
+	struct qat_alg_buf_list *bufl;
+	struct qat_alg_buf_list *buflout = NULL;
+	dma_addr_t blp;
+	dma_addr_t bloutp = 0;
+	struct scatterlist *sg;
+	size_t sz = sizeof(struct qat_alg_buf_list) +
+			((1 + n + assoc_n) * sizeof(struct qat_alg_buf));
+
+	if (unlikely(!n))
+		return -EINVAL;
+
+	bufl = kmalloc_node(sz, GFP_ATOMIC, inst->accel_dev->numa_node);
+	if (unlikely(!bufl))
+		return -ENOMEM;
+
+	blp = dma_map_single(dev, bufl, sz, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, blp)))
+		goto err;
+
+	for_each_sg(assoc, sg, assoc_n, i) {
+		bufl->bufers[bufs].addr = dma_map_single(dev,
+							 sg_virt(sg),
+							 sg->length,
+							 DMA_BIDIRECTIONAL);
+		bufl->bufers[bufs].len = sg->length;
+		if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
+			goto err;
+		bufs++;
+	}
+	bufl->bufers[bufs].addr = dma_map_single(dev, iv, ivlen,
+						 DMA_BIDIRECTIONAL);
+	bufl->bufers[bufs].len = ivlen;
+	if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
+		goto err;
+	bufs++;
+
+	for_each_sg(sgl, sg, n, i) {
+		int y = i + bufs;
+
+		bufl->bufers[y].addr = dma_map_single(dev, sg_virt(sg),
+						      sg->length,
+						      DMA_BIDIRECTIONAL);
+		bufl->bufers[y].len = sg->length;
+		if (unlikely(dma_mapping_error(dev, bufl->bufers[y].addr)))
+			goto err;
+	}
+	bufl->num_bufs = n + bufs;
+	qat_req->buf.bl = bufl;
+	qat_req->buf.blp = blp;
+	qat_req->buf.sz = sz;
+	/* Handle out of place operation */
+	if (sgl != sglout) {
+		struct qat_alg_buf *bufers;
+
+		buflout = kmalloc_node(sz, GFP_ATOMIC,
+				       inst->accel_dev->numa_node);
+		if (unlikely(!buflout))
+			goto err;
+		bloutp = dma_map_single(dev, buflout, sz, DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(dev, bloutp)))
+			goto err;
+		bufers = buflout->bufers;
+		/* For out of place operation dma map only data and
+		 * reuse assoc mapping and iv */
+		for (i = 0; i < bufs; i++) {
+			bufers[i].len = bufl->bufers[i].len;
+			bufers[i].addr = bufl->bufers[i].addr;
+		}
+		for_each_sg(sglout, sg, n, i) {
+			int y = i + bufs;
+
+			bufers[y].addr = dma_map_single(dev, sg_virt(sg),
+							sg->length,
+							DMA_BIDIRECTIONAL);
+			buflout->bufers[y].len = sg->length;
+			if (unlikely(dma_mapping_error(dev, bufers[y].addr)))
+				goto err;
+		}
+		buflout->num_bufs = n + bufs;
+		buflout->num_mapped_bufs = n;
+		qat_req->buf.blout = buflout;
+		qat_req->buf.bloutp = bloutp;
+	} else {
+		/* Otherwise set the src and dst to the same address */
+		qat_req->buf.bloutp = qat_req->buf.blp;
+	}
+	return 0;
+err:
+	dev_err(dev, "Failed to map buf for dma\n");
+	for_each_sg(sgl, sg, n + bufs, i) {
+		if (!dma_mapping_error(dev, bufl->bufers[i].addr)) {
+			dma_unmap_single(dev, bufl->bufers[i].addr,
+					 bufl->bufers[i].len,
+					 DMA_BIDIRECTIONAL);
+		}
+	}
+	if (!dma_mapping_error(dev, blp))
+		dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE);
+	kfree(bufl);
+	if (sgl != sglout && buflout) {
+		for_each_sg(sglout, sg, n, i) {
+			int y = i + bufs;
+
+			if (!dma_mapping_error(dev, buflout->bufers[y].addr))
+				dma_unmap_single(dev, buflout->bufers[y].addr,
+						 buflout->bufers[y].len,
+						 DMA_BIDIRECTIONAL);
+		}
+		if (!dma_mapping_error(dev, bloutp))
+			dma_unmap_single(dev, bloutp, sz, DMA_TO_DEVICE);
+		kfree(buflout);
+	}
+	return -ENOMEM;
+}
+
+void qat_alg_callback(void *resp)
+{
+	struct icp_qat_fw_la_resp *qat_resp = resp;
+	struct qat_crypto_request *qat_req =
+				(void *)(__force long)qat_resp->opaque_data;
+	struct qat_alg_session_ctx *ctx = qat_req->ctx;
+	struct qat_crypto_instance *inst = ctx->inst;
+	struct aead_request *areq = qat_req->areq;
+	uint8_t stat_filed = qat_resp->comn_resp.comn_status;
+	int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed);
+
+	qat_alg_free_bufl(inst, qat_req);
+	if (unlikely(qat_res != ICP_QAT_FW_COMN_STATUS_FLAG_OK))
+		res = -EBADMSG;
+	areq->base.complete(&areq->base, res);
+}
+
+static int qat_alg_dec(struct aead_request *areq)
+{
+	struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+	struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct qat_crypto_request *qat_req = aead_request_ctx(areq);
+	struct icp_qat_fw_la_cipher_req_params *cipher_param;
+	struct icp_qat_fw_la_auth_req_params *auth_param;
+	struct icp_qat_fw_la_bulk_req *msg;
+	int digst_size = crypto_aead_crt(aead_tfm)->authsize;
+	int ret, ctr = 0;
+
+	ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->src, areq->dst,
+				  areq->iv, AES_BLOCK_SIZE, qat_req);
+	if (unlikely(ret))
+		return ret;
+
+	msg = &qat_req->req;
+	*msg = ctx->dec_fw_req_tmpl;
+	qat_req->ctx = ctx;
+	qat_req->areq = areq;
+	qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req;
+	qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp;
+	qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
+	cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
+	cipher_param->cipher_length = areq->cryptlen - digst_size;
+	cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
+	memcpy(cipher_param->u.cipher_IV_array, areq->iv, AES_BLOCK_SIZE);
+	auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
+	auth_param->auth_off = 0;
+	auth_param->auth_len = areq->assoclen +
+				cipher_param->cipher_length + AES_BLOCK_SIZE;
+	do {
+		ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
+	} while (ret == -EAGAIN && ctr++ < 10);
+
+	if (ret == -EAGAIN) {
+		qat_alg_free_bufl(ctx->inst, qat_req);
+		return -EBUSY;
+	}
+	return -EINPROGRESS;
+}
+
+static int qat_alg_enc_internal(struct aead_request *areq, uint8_t *iv,
+				int enc_iv)
+{
+	struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+	struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct qat_crypto_request *qat_req = aead_request_ctx(areq);
+	struct icp_qat_fw_la_cipher_req_params *cipher_param;
+	struct icp_qat_fw_la_auth_req_params *auth_param;
+	struct icp_qat_fw_la_bulk_req *msg;
+	int ret, ctr = 0;
+
+	ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->src, areq->dst,
+				  iv, AES_BLOCK_SIZE, qat_req);
+	if (unlikely(ret))
+		return ret;
+
+	msg = &qat_req->req;
+	*msg = ctx->enc_fw_req_tmpl;
+	qat_req->ctx = ctx;
+	qat_req->areq = areq;
+	qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req;
+	qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp;
+	qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
+	cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
+	auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
+
+	if (enc_iv) {
+		cipher_param->cipher_length = areq->cryptlen + AES_BLOCK_SIZE;
+		cipher_param->cipher_offset = areq->assoclen;
+	} else {
+		memcpy(cipher_param->u.cipher_IV_array, iv, AES_BLOCK_SIZE);
+		cipher_param->cipher_length = areq->cryptlen;
+		cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
+	}
+	auth_param->auth_off = 0;
+	auth_param->auth_len = areq->assoclen + areq->cryptlen + AES_BLOCK_SIZE;
+
+	do {
+		ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
+	} while (ret == -EAGAIN && ctr++ < 10);
+
+	if (ret == -EAGAIN) {
+		qat_alg_free_bufl(ctx->inst, qat_req);
+		return -EBUSY;
+	}
+	return -EINPROGRESS;
+}
+
+static int qat_alg_enc(struct aead_request *areq)
+{
+	return qat_alg_enc_internal(areq, areq->iv, 0);
+}
+
+static int qat_alg_genivenc(struct aead_givcrypt_request *req)
+{
+	struct crypto_aead *aead_tfm = crypto_aead_reqtfm(&req->areq);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+	struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+	__be64 seq;
+
+	memcpy(req->giv, ctx->salt, AES_BLOCK_SIZE);
+	seq = cpu_to_be64(req->seq);
+	memcpy(req->giv + AES_BLOCK_SIZE - sizeof(uint64_t),
+	       &seq, sizeof(uint64_t));
+	return qat_alg_enc_internal(&req->areq, req->giv, 1);
+}
+
+static int qat_alg_init(struct crypto_tfm *tfm,
+			enum icp_qat_hw_auth_algo hash, const char *hash_name)
+{
+	struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	memset(ctx, '\0', sizeof(*ctx));
+	ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
+	if (IS_ERR(ctx->hash_tfm))
+		return -EFAULT;
+	spin_lock_init(&ctx->lock);
+	ctx->qat_hash_alg = hash;
+	tfm->crt_aead.reqsize = sizeof(struct aead_request) +
+				sizeof(struct qat_crypto_request);
+	ctx->tfm = tfm;
+	return 0;
+}
+
+static int qat_alg_sha1_init(struct crypto_tfm *tfm)
+{
+	return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA1, "sha1");
+}
+
+static int qat_alg_sha256_init(struct crypto_tfm *tfm)
+{
+	return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA256, "sha256");
+}
+
+static int qat_alg_sha512_init(struct crypto_tfm *tfm)
+{
+	return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA512, "sha512");
+}
+
+static void qat_alg_exit(struct crypto_tfm *tfm)
+{
+	struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct qat_crypto_instance *inst = ctx->inst;
+	struct device *dev;
+
+	if (!IS_ERR(ctx->hash_tfm))
+		crypto_free_shash(ctx->hash_tfm);
+
+	if (!inst)
+		return;
+
+	dev = &GET_DEV(inst->accel_dev);
+	if (ctx->enc_cd)
+		dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+				  ctx->enc_cd, ctx->enc_cd_paddr);
+	if (ctx->dec_cd)
+		dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+				  ctx->dec_cd, ctx->dec_cd_paddr);
+	if (ctx->auth_hw_state_enc)
+		dma_free_coherent(dev, sizeof(struct qat_auth_state),
+				  ctx->auth_hw_state_enc,
+				  ctx->auth_state_enc_paddr);
+
+	if (ctx->auth_hw_state_dec)
+		dma_free_coherent(dev, sizeof(struct qat_auth_state),
+				  ctx->auth_hw_state_dec,
+				  ctx->auth_state_dec_paddr);
+
+	qat_crypto_put_instance(inst);
+}
+
+static struct crypto_alg qat_algs[] = { {
+	.cra_name = "authenc(hmac(sha1),cbc(aes))",
+	.cra_driver_name = "qat_aes_cbc_hmac_sha1",
+	.cra_priority = 4001,
+	.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	.cra_blocksize = AES_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+	.cra_alignmask = 0,
+	.cra_type = &crypto_aead_type,
+	.cra_module = THIS_MODULE,
+	.cra_init = qat_alg_sha1_init,
+	.cra_exit = qat_alg_exit,
+	.cra_u = {
+		.aead = {
+			.setkey = qat_alg_setkey,
+			.decrypt = qat_alg_dec,
+			.encrypt = qat_alg_enc,
+			.givencrypt = qat_alg_genivenc,
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA1_DIGEST_SIZE,
+		},
+	},
+}, {
+	.cra_name = "authenc(hmac(sha256),cbc(aes))",
+	.cra_driver_name = "qat_aes_cbc_hmac_sha256",
+	.cra_priority = 4001,
+	.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	.cra_blocksize = AES_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+	.cra_alignmask = 0,
+	.cra_type = &crypto_aead_type,
+	.cra_module = THIS_MODULE,
+	.cra_init = qat_alg_sha256_init,
+	.cra_exit = qat_alg_exit,
+	.cra_u = {
+		.aead = {
+			.setkey = qat_alg_setkey,
+			.decrypt = qat_alg_dec,
+			.encrypt = qat_alg_enc,
+			.givencrypt = qat_alg_genivenc,
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA256_DIGEST_SIZE,
+		},
+	},
+}, {
+	.cra_name = "authenc(hmac(sha512),cbc(aes))",
+	.cra_driver_name = "qat_aes_cbc_hmac_sha512",
+	.cra_priority = 4001,
+	.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	.cra_blocksize = AES_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+	.cra_alignmask = 0,
+	.cra_type = &crypto_aead_type,
+	.cra_module = THIS_MODULE,
+	.cra_init = qat_alg_sha512_init,
+	.cra_exit = qat_alg_exit,
+	.cra_u = {
+		.aead = {
+			.setkey = qat_alg_setkey,
+			.decrypt = qat_alg_dec,
+			.encrypt = qat_alg_enc,
+			.givencrypt = qat_alg_genivenc,
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA512_DIGEST_SIZE,
+		},
+	},
+} };
+
+int qat_algs_register(void)
+{
+	if (atomic_add_return(1, &active_dev) == 1) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(qat_algs); i++)
+			qat_algs[i].cra_flags =	CRYPTO_ALG_TYPE_AEAD |
+						CRYPTO_ALG_ASYNC;
+		return crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
+	}
+	return 0;
+}
+
+int qat_algs_unregister(void)
+{
+	if (atomic_sub_return(1, &active_dev) == 0)
+		return crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+	return 0;
+}
+
+int qat_algs_init(void)
+{
+	atomic_set(&active_dev, 0);
+	crypto_get_default_rng();
+	return 0;
+}
+
+void qat_algs_exit(void)
+{
+	crypto_put_default_rng();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_crypto.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_crypto.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_crypto.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_crypto.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_transport.h"
+#include "adf_cfg.h"
+#include "adf_cfg_strings.h"
+#include "qat_crypto.h"
+#include "icp_qat_fw.h"
+
+#define SEC ADF_KERNEL_SEC
+
+static struct service_hndl qat_crypto;
+
+void qat_crypto_put_instance(struct qat_crypto_instance *inst)
+{
+	if (atomic_sub_return(1, &inst->refctr) == 0)
+		adf_dev_put(inst->accel_dev);
+}
+
+static int qat_crypto_free_instances(struct adf_accel_dev *accel_dev)
+{
+	struct qat_crypto_instance *inst;
+	struct list_head *list_ptr, *tmp;
+	int i;
+
+	list_for_each_safe(list_ptr, tmp, &accel_dev->crypto_list) {
+		inst = list_entry(list_ptr, struct qat_crypto_instance, list);
+
+		for (i = 0; i < atomic_read(&inst->refctr); i++)
+			qat_crypto_put_instance(inst);
+
+		if (inst->sym_tx)
+			adf_remove_ring(inst->sym_tx);
+
+		if (inst->sym_rx)
+			adf_remove_ring(inst->sym_rx);
+
+		if (inst->pke_tx)
+			adf_remove_ring(inst->pke_tx);
+
+		if (inst->pke_rx)
+			adf_remove_ring(inst->pke_rx);
+
+		if (inst->rnd_tx)
+			adf_remove_ring(inst->rnd_tx);
+
+		if (inst->rnd_rx)
+			adf_remove_ring(inst->rnd_rx);
+
+		list_del(list_ptr);
+		kfree(inst);
+	}
+	return 0;
+}
+
+struct qat_crypto_instance *qat_crypto_get_instance_node(int node)
+{
+	struct adf_accel_dev *accel_dev = NULL;
+	struct qat_crypto_instance *inst_best = NULL;
+	struct list_head *itr;
+	unsigned long best = ~0;
+
+	list_for_each(itr, adf_devmgr_get_head()) {
+		accel_dev = list_entry(itr, struct adf_accel_dev, list);
+		if (accel_dev->numa_node == node && adf_dev_started(accel_dev))
+			break;
+		accel_dev = NULL;
+	}
+	if (!accel_dev) {
+		pr_err("QAT: Could not find device on give node\n");
+		accel_dev = adf_devmgr_get_first();
+	}
+	if (!accel_dev || !adf_dev_started(accel_dev))
+		return NULL;
+
+	list_for_each(itr, &accel_dev->crypto_list) {
+		struct qat_crypto_instance *inst;
+		unsigned long cur;
+
+		inst = list_entry(itr, struct qat_crypto_instance, list);
+		cur = atomic_read(&inst->refctr);
+		if (best > cur) {
+			inst_best = inst;
+			best = cur;
+		}
+	}
+	if (inst_best) {
+		if (atomic_add_return(1, &inst_best->refctr) == 1) {
+			if (adf_dev_get(accel_dev)) {
+				atomic_dec(&inst_best->refctr);
+				pr_err("QAT: Could increment dev refctr\n");
+				return NULL;
+			}
+		}
+	}
+	return inst_best;
+}
+
+static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
+{
+	int i;
+	unsigned long bank;
+	unsigned long num_inst, num_msg_sym, num_msg_asym;
+	int msg_size;
+	struct qat_crypto_instance *inst;
+	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+
+	INIT_LIST_HEAD(&accel_dev->crypto_list);
+	strlcpy(key, ADF_NUM_CY, sizeof(key));
+
+	if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+		return -EFAULT;
+
+	if (kstrtoul(val, 0, &num_inst))
+		return -EFAULT;
+
+	for (i = 0; i < num_inst; i++) {
+		inst = kzalloc_node(sizeof(*inst), GFP_KERNEL,
+				    accel_dev->numa_node);
+		if (!inst)
+			goto err;
+
+		list_add_tail(&inst->list, &accel_dev->crypto_list);
+		inst->id = i;
+		atomic_set(&inst->refctr, 0);
+		inst->accel_dev = accel_dev;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i);
+		if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+			goto err;
+
+		if (kstrtoul(val, 10, &bank))
+			goto err;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_SIZE, i);
+		if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+			goto err;
+
+		if (kstrtoul(val, 10, &num_msg_sym))
+			goto err;
+		num_msg_sym = num_msg_sym >> 1;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, i);
+		if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+			goto err;
+
+		if (kstrtoul(val, 10, &num_msg_asym))
+			goto err;
+		num_msg_asym = num_msg_asym >> 1;
+
+		msg_size = ICP_QAT_FW_REQ_DEFAULT_SZ;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_TX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_sym,
+				    msg_size, key, NULL, 0, &inst->sym_tx))
+			goto err;
+
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+				    msg_size, key, NULL, 0, &inst->rnd_tx))
+			goto err;
+
+		msg_size = msg_size >> 1;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+				    msg_size, key, NULL, 0, &inst->pke_tx))
+			goto err;
+
+		msg_size = ICP_QAT_FW_RESP_DEFAULT_SZ;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_RX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_sym,
+				    msg_size, key, qat_alg_callback, 0,
+				    &inst->sym_rx))
+			goto err;
+
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+				    msg_size, key, qat_alg_callback, 0,
+				    &inst->rnd_rx))
+			goto err;
+
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
+		if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+				    msg_size, key, qat_alg_callback, 0,
+				    &inst->pke_rx))
+			goto err;
+	}
+	return 0;
+err:
+	qat_crypto_free_instances(accel_dev);
+	return -ENOMEM;
+}
+
+static int qat_crypto_init(struct adf_accel_dev *accel_dev)
+{
+	if (qat_crypto_create_instances(accel_dev))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int qat_crypto_shutdown(struct adf_accel_dev *accel_dev)
+{
+	return qat_crypto_free_instances(accel_dev);
+}
+
+static int qat_crypto_event_handler(struct adf_accel_dev *accel_dev,
+				    enum adf_event event)
+{
+	int ret;
+
+	switch (event) {
+	case ADF_EVENT_INIT:
+		ret = qat_crypto_init(accel_dev);
+		break;
+	case ADF_EVENT_SHUTDOWN:
+		ret = qat_crypto_shutdown(accel_dev);
+		break;
+	case ADF_EVENT_RESTARTING:
+	case ADF_EVENT_RESTARTED:
+	case ADF_EVENT_START:
+	case ADF_EVENT_STOP:
+	default:
+		ret = 0;
+	}
+	return ret;
+}
+
+int qat_crypto_register(void)
+{
+	memset(&qat_crypto, 0, sizeof(qat_crypto));
+	qat_crypto.event_hld = qat_crypto_event_handler;
+	qat_crypto.name = "qat_crypto";
+	return adf_service_register(&qat_crypto);
+}
+
+int qat_crypto_unregister(void)
+{
+	return adf_service_unregister(&qat_crypto);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_crypto.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_crypto.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_crypto.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_crypto.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef _QAT_CRYPTO_INSTANCE_H_
+#define _QAT_CRYPTO_INSTANCE_H_
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "adf_accel_devices.h"
+#include "icp_qat_fw_la.h"
+
+struct qat_crypto_instance {
+	struct adf_etr_ring_data *sym_tx;
+	struct adf_etr_ring_data *sym_rx;
+	struct adf_etr_ring_data *pke_tx;
+	struct adf_etr_ring_data *pke_rx;
+	struct adf_etr_ring_data *rnd_tx;
+	struct adf_etr_ring_data *rnd_rx;
+	struct adf_accel_dev *accel_dev;
+	struct list_head list;
+	unsigned long state;
+	int id;
+	atomic_t refctr;
+};
+
+struct qat_crypto_request_buffs {
+	struct qat_alg_buf_list *bl;
+	dma_addr_t blp;
+	struct qat_alg_buf_list *blout;
+	dma_addr_t bloutp;
+	size_t sz;
+};
+
+struct qat_crypto_request {
+	struct icp_qat_fw_la_bulk_req req;
+	struct qat_alg_session_ctx *ctx;
+	struct aead_request *areq;
+	struct qat_crypto_request_buffs buf;
+};
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_hal.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_hal.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_hal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_hal.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1393 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/slab.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_hal.h"
+#include "icp_qat_uclo.h"
+
+#define BAD_REGADDR               0xffff
+#define MAX_RETRY_TIMES           10000
+#define INIT_CTX_ARB_VALUE        0x0
+#define INIT_CTX_ENABLE_VALUE     0x0
+#define INIT_PC_VALUE             0x0
+#define INIT_WAKEUP_EVENTS_VALUE  0x1
+#define INIT_SIG_EVENTS_VALUE     0x1
+#define INIT_CCENABLE_VALUE       0x2000
+#define RST_CSR_QAT_LSB           20
+#define RST_CSR_AE_LSB		  0
+#define MC_TIMESTAMP_ENABLE       (0x1 << 7)
+
+#define IGNORE_W1C_MASK ((~(1 << CE_BREAKPOINT_BITPOS)) & \
+	(~(1 << CE_CNTL_STORE_PARITY_ERROR_BITPOS)) & \
+	(~(1 << CE_REG_PAR_ERR_BITPOS)))
+#define INSERT_IMMED_GPRA_CONST(inst, const_val) \
+	(inst = ((inst & 0xFFFF00C03FFull) | \
+		((((const_val) << 12) & 0x0FF00000ull) | \
+		(((const_val) << 10) & 0x0003FC00ull))))
+#define INSERT_IMMED_GPRB_CONST(inst, const_val) \
+	(inst = ((inst & 0xFFFF00FFF00ull) | \
+		((((const_val) << 12) & 0x0FF00000ull) | \
+		(((const_val) <<  0) & 0x000000FFull))))
+
+#define AE(handle, ae) handle->hal_handle->aes[ae]
+
+static const uint64_t inst_4b[] = {
+	0x0F0400C0000ull, 0x0F4400C0000ull, 0x0F040000300ull, 0x0F440000300ull,
+	0x0FC066C0000ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+	0x0A021000000ull
+};
+
+static const uint64_t inst[] = {
+	0x0F0000C0000ull, 0x0F000000380ull, 0x0D805000011ull, 0x0FC082C0300ull,
+	0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+	0x0A0643C0000ull, 0x0BAC0000301ull, 0x0D802000101ull, 0x0F0000C0001ull,
+	0x0FC066C0001ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+	0x0F000400300ull, 0x0A0610C0000ull, 0x0BAC0000301ull, 0x0D804400101ull,
+	0x0A0580C0000ull, 0x0A0581C0000ull, 0x0A0582C0000ull, 0x0A0583C0000ull,
+	0x0A0584C0000ull, 0x0A0585C0000ull, 0x0A0586C0000ull, 0x0A0587C0000ull,
+	0x0A0588C0000ull, 0x0A0589C0000ull, 0x0A058AC0000ull, 0x0A058BC0000ull,
+	0x0A058CC0000ull, 0x0A058DC0000ull, 0x0A058EC0000ull, 0x0A058FC0000ull,
+	0x0A05C0C0000ull, 0x0A05C1C0000ull, 0x0A05C2C0000ull, 0x0A05C3C0000ull,
+	0x0A05C4C0000ull, 0x0A05C5C0000ull, 0x0A05C6C0000ull, 0x0A05C7C0000ull,
+	0x0A05C8C0000ull, 0x0A05C9C0000ull, 0x0A05CAC0000ull, 0x0A05CBC0000ull,
+	0x0A05CCC0000ull, 0x0A05CDC0000ull, 0x0A05CEC0000ull, 0x0A05CFC0000ull,
+	0x0A0400C0000ull, 0x0B0400C0000ull, 0x0A0401C0000ull, 0x0B0401C0000ull,
+	0x0A0402C0000ull, 0x0B0402C0000ull, 0x0A0403C0000ull, 0x0B0403C0000ull,
+	0x0A0404C0000ull, 0x0B0404C0000ull, 0x0A0405C0000ull, 0x0B0405C0000ull,
+	0x0A0406C0000ull, 0x0B0406C0000ull, 0x0A0407C0000ull, 0x0B0407C0000ull,
+	0x0A0408C0000ull, 0x0B0408C0000ull, 0x0A0409C0000ull, 0x0B0409C0000ull,
+	0x0A040AC0000ull, 0x0B040AC0000ull, 0x0A040BC0000ull, 0x0B040BC0000ull,
+	0x0A040CC0000ull, 0x0B040CC0000ull, 0x0A040DC0000ull, 0x0B040DC0000ull,
+	0x0A040EC0000ull, 0x0B040EC0000ull, 0x0A040FC0000ull, 0x0B040FC0000ull,
+	0x0D81581C010ull, 0x0E000010000ull, 0x0E000010000ull,
+};
+
+void qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle,
+			  unsigned char ae, unsigned int ctx_mask)
+{
+	AE(handle, ae).live_ctx_mask = ctx_mask;
+}
+
+#define CSR_RETRY_TIMES 500
+static int qat_hal_rd_ae_csr(struct icp_qat_fw_loader_handle *handle,
+			     unsigned char ae, unsigned int csr,
+			     unsigned int *value)
+{
+	unsigned int iterations = CSR_RETRY_TIMES;
+
+	do {
+		*value = GET_AE_CSR(handle, ae, csr);
+		if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS))
+			return 0;
+	} while (iterations--);
+
+	pr_err("QAT: Read CSR timeout\n");
+	return -EFAULT;
+}
+
+static int qat_hal_wr_ae_csr(struct icp_qat_fw_loader_handle *handle,
+			     unsigned char ae, unsigned int csr,
+			     unsigned int value)
+{
+	unsigned int iterations = CSR_RETRY_TIMES;
+
+	do {
+		SET_AE_CSR(handle, ae, csr, value);
+		if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS))
+			return 0;
+	} while (iterations--);
+
+	pr_err("QAT: Write CSR Timeout\n");
+	return -EFAULT;
+}
+
+static void qat_hal_get_wakeup_event(struct icp_qat_fw_loader_handle *handle,
+				     unsigned char ae, unsigned char ctx,
+				     unsigned int *events)
+{
+	unsigned int cur_ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+	qat_hal_rd_ae_csr(handle, ae, CTX_WAKEUP_EVENTS_INDIRECT, events);
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static int qat_hal_wait_cycles(struct icp_qat_fw_loader_handle *handle,
+			       unsigned char ae, unsigned int cycles,
+			       int chk_inactive)
+{
+	unsigned int base_cnt = 0, cur_cnt = 0;
+	unsigned int csr = (1 << ACS_ABO_BITPOS);
+	int times = MAX_RETRY_TIMES;
+	int elapsed_cycles = 0;
+
+	qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &base_cnt);
+	base_cnt &= 0xffff;
+	while ((int)cycles > elapsed_cycles && times--) {
+		if (chk_inactive)
+			qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &csr);
+
+		qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &cur_cnt);
+		cur_cnt &= 0xffff;
+		elapsed_cycles = cur_cnt - base_cnt;
+
+		if (elapsed_cycles < 0)
+			elapsed_cycles += 0x10000;
+
+		/* ensure at least 8 time cycles elapsed in wait_cycles */
+		if (elapsed_cycles >= 8 && !(csr & (1 << ACS_ABO_BITPOS)))
+			return 0;
+	}
+	if (!times) {
+		pr_err("QAT: wait_num_cycles time out\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+#define CLR_BIT(wrd, bit) (wrd & ~(1 << bit))
+#define SET_BIT(wrd, bit) (wrd | 1 << bit)
+
+int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle,
+			    unsigned char ae, unsigned char mode)
+{
+	unsigned int csr, new_csr;
+
+	if ((mode != 4) && (mode != 8)) {
+		pr_err("QAT: bad ctx mode=%d\n", mode);
+		return -EINVAL;
+	}
+
+	/* Sets the accelaration engine context mode to either four or eight */
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+	csr = IGNORE_W1C_MASK & csr;
+	new_csr = (mode == 4) ?
+		SET_BIT(csr, CE_INUSE_CONTEXTS_BITPOS) :
+		CLR_BIT(csr, CE_INUSE_CONTEXTS_BITPOS);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+	return 0;
+}
+
+int qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle,
+			   unsigned char ae, unsigned char mode)
+{
+	unsigned int csr, new_csr;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+	csr &= IGNORE_W1C_MASK;
+
+	new_csr = (mode) ?
+		SET_BIT(csr, CE_NN_MODE_BITPOS) :
+		CLR_BIT(csr, CE_NN_MODE_BITPOS);
+
+	if (new_csr != csr)
+		qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+
+	return 0;
+}
+
+int qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle,
+			   unsigned char ae, enum icp_qat_uof_regtype lm_type,
+			   unsigned char mode)
+{
+	unsigned int csr, new_csr;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+	csr &= IGNORE_W1C_MASK;
+	switch (lm_type) {
+	case ICP_LMEM0:
+		new_csr = (mode) ?
+			SET_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS) :
+			CLR_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS);
+		break;
+	case ICP_LMEM1:
+		new_csr = (mode) ?
+			SET_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS) :
+			CLR_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS);
+		break;
+	default:
+		pr_err("QAT: lmType = 0x%x\n", lm_type);
+		return -EINVAL;
+	}
+
+	if (new_csr != csr)
+		qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+	return 0;
+}
+
+static unsigned short qat_hal_get_reg_addr(unsigned int type,
+					   unsigned short reg_num)
+{
+	unsigned short reg_addr;
+
+	switch (type) {
+	case ICP_GPA_ABS:
+	case ICP_GPB_ABS:
+		reg_addr = 0x80 | (reg_num & 0x7f);
+		break;
+	case ICP_GPA_REL:
+	case ICP_GPB_REL:
+		reg_addr = reg_num & 0x1f;
+		break;
+	case ICP_SR_RD_REL:
+	case ICP_SR_WR_REL:
+	case ICP_SR_REL:
+		reg_addr = 0x180 | (reg_num & 0x1f);
+		break;
+	case ICP_SR_ABS:
+		reg_addr = 0x140 | ((reg_num & 0x3) << 1);
+		break;
+	case ICP_DR_RD_REL:
+	case ICP_DR_WR_REL:
+	case ICP_DR_REL:
+		reg_addr = 0x1c0 | (reg_num & 0x1f);
+		break;
+	case ICP_DR_ABS:
+		reg_addr = 0x100 | ((reg_num & 0x3) << 1);
+		break;
+	case ICP_NEIGH_REL:
+		reg_addr = 0x280 | (reg_num & 0x1f);
+		break;
+	case ICP_LMEM0:
+		reg_addr = 0x200;
+		break;
+	case ICP_LMEM1:
+		reg_addr = 0x220;
+		break;
+	case ICP_NO_DEST:
+		reg_addr = 0x300 | (reg_num & 0xff);
+		break;
+	default:
+		reg_addr = BAD_REGADDR;
+		break;
+	}
+	return reg_addr;
+}
+
+void qat_hal_reset(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned int ae_reset_csr;
+
+	ae_reset_csr = GET_GLB_CSR(handle, ICP_RESET);
+	ae_reset_csr |= handle->hal_handle->ae_mask << RST_CSR_AE_LSB;
+	ae_reset_csr |= handle->hal_handle->slice_mask << RST_CSR_QAT_LSB;
+	SET_GLB_CSR(handle, ICP_RESET, ae_reset_csr);
+}
+
+static void qat_hal_wr_indr_csr(struct icp_qat_fw_loader_handle *handle,
+				unsigned char ae, unsigned int ctx_mask,
+				unsigned int ae_csr, unsigned int csr_val)
+{
+	unsigned int ctx, cur_ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+
+	for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+		if (!(ctx_mask & (1 << ctx)))
+			continue;
+		qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+		qat_hal_wr_ae_csr(handle, ae, ae_csr, csr_val);
+	}
+
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_rd_indr_csr(struct icp_qat_fw_loader_handle *handle,
+				unsigned char ae, unsigned char ctx,
+				unsigned int ae_csr, unsigned int *csr_val)
+{
+	unsigned int cur_ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+	qat_hal_rd_ae_csr(handle, ae, ae_csr, csr_val);
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_put_sig_event(struct icp_qat_fw_loader_handle *handle,
+				  unsigned char ae, unsigned int ctx_mask,
+				  unsigned int events)
+{
+	unsigned int ctx, cur_ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+	for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+		if (!(ctx_mask & (1 << ctx)))
+			continue;
+		qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+		qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_INDIRECT, events);
+	}
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_put_wakeup_event(struct icp_qat_fw_loader_handle *handle,
+				     unsigned char ae, unsigned int ctx_mask,
+				     unsigned int events)
+{
+	unsigned int ctx, cur_ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+	for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+		if (!(ctx_mask & (1 << ctx)))
+			continue;
+		qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+		qat_hal_wr_ae_csr(handle, ae, CTX_WAKEUP_EVENTS_INDIRECT,
+				  events);
+	}
+	qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static int qat_hal_check_ae_alive(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned int base_cnt, cur_cnt;
+	unsigned char ae;
+	unsigned int times = MAX_RETRY_TIMES;
+
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!(handle->hal_handle->ae_mask & (1 << ae)))
+			continue;
+
+		qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT,
+				  (unsigned int *)&base_cnt);
+		base_cnt &= 0xffff;
+
+		do {
+			qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT,
+					  (unsigned int *)&cur_cnt);
+			cur_cnt &= 0xffff;
+		} while (times-- && (cur_cnt == base_cnt));
+
+		if (!times) {
+			pr_err("QAT: AE%d is inactive!!\n", ae);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static void qat_hal_reset_timestamp(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned int misc_ctl;
+	unsigned char ae;
+
+	/* stop the timestamp timers */
+	misc_ctl = GET_GLB_CSR(handle, MISC_CONTROL);
+	if (misc_ctl & MC_TIMESTAMP_ENABLE)
+		SET_GLB_CSR(handle, MISC_CONTROL, misc_ctl &
+			    (~MC_TIMESTAMP_ENABLE));
+
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!(handle->hal_handle->ae_mask & (1 << ae)))
+			continue;
+		qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_LOW, 0);
+		qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_HIGH, 0);
+	}
+	/* start timestamp timers */
+	SET_GLB_CSR(handle, MISC_CONTROL, misc_ctl | MC_TIMESTAMP_ENABLE);
+}
+
+#define ESRAM_AUTO_TINIT (1<<2)
+#define ESRAM_AUTO_TINIT_DONE (1<<3)
+#define ESRAM_AUTO_INIT_USED_CYCLES (1640)
+#define ESRAM_AUTO_INIT_CSR_OFFSET 0xC1C
+static int qat_hal_init_esram(struct icp_qat_fw_loader_handle *handle)
+{
+	void __iomem *csr_addr = handle->hal_ep_csr_addr_v +
+				 ESRAM_AUTO_INIT_CSR_OFFSET;
+	unsigned int csr_val, times = 30;
+
+	csr_val = ADF_CSR_RD(csr_addr, 0);
+	if ((csr_val & ESRAM_AUTO_TINIT) && (csr_val & ESRAM_AUTO_TINIT_DONE))
+		return 0;
+
+	csr_val = ADF_CSR_RD(csr_addr, 0);
+	csr_val |= ESRAM_AUTO_TINIT;
+	ADF_CSR_WR(csr_addr, 0, csr_val);
+
+	do {
+		qat_hal_wait_cycles(handle, 0, ESRAM_AUTO_INIT_USED_CYCLES, 0);
+		csr_val = ADF_CSR_RD(csr_addr, 0);
+	} while (!(csr_val & ESRAM_AUTO_TINIT_DONE) && times--);
+	if ((!times)) {
+		pr_err("QAT: Fail to init eSram!\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+#define SHRAM_INIT_CYCLES 2060
+int qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned int ae_reset_csr;
+	unsigned char ae;
+	unsigned int clk_csr;
+	unsigned int times = 100;
+	unsigned int csr;
+
+	/* write to the reset csr */
+	ae_reset_csr = GET_GLB_CSR(handle, ICP_RESET);
+	ae_reset_csr &= ~(handle->hal_handle->ae_mask << RST_CSR_AE_LSB);
+	ae_reset_csr &= ~(handle->hal_handle->slice_mask << RST_CSR_QAT_LSB);
+	do {
+		SET_GLB_CSR(handle, ICP_RESET, ae_reset_csr);
+		if (!(times--))
+			goto out_err;
+		csr = GET_GLB_CSR(handle, ICP_RESET);
+	} while ((handle->hal_handle->ae_mask |
+		 (handle->hal_handle->slice_mask << RST_CSR_QAT_LSB)) & csr);
+	/* enable clock */
+	clk_csr = GET_GLB_CSR(handle, ICP_GLOBAL_CLK_ENABLE);
+	clk_csr |= handle->hal_handle->ae_mask << 0;
+	clk_csr |= handle->hal_handle->slice_mask << 20;
+	SET_GLB_CSR(handle, ICP_GLOBAL_CLK_ENABLE, clk_csr);
+	if (qat_hal_check_ae_alive(handle))
+		goto out_err;
+
+	/* Set undefined power-up/reset states to reasonable default values */
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!(handle->hal_handle->ae_mask & (1 << ae)))
+			continue;
+		qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES,
+				  INIT_CTX_ENABLE_VALUE);
+		qat_hal_wr_indr_csr(handle, ae, ICP_QAT_UCLO_AE_ALL_CTX,
+				    CTX_STS_INDIRECT,
+				    handle->hal_handle->upc_mask &
+				    INIT_PC_VALUE);
+		qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE);
+		qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE);
+		qat_hal_put_wakeup_event(handle, ae,
+					 ICP_QAT_UCLO_AE_ALL_CTX,
+					 INIT_WAKEUP_EVENTS_VALUE);
+		qat_hal_put_sig_event(handle, ae,
+				      ICP_QAT_UCLO_AE_ALL_CTX,
+				      INIT_SIG_EVENTS_VALUE);
+	}
+	if (qat_hal_init_esram(handle))
+		goto out_err;
+	if (qat_hal_wait_cycles(handle, 0, SHRAM_INIT_CYCLES, 0))
+		goto out_err;
+	qat_hal_reset_timestamp(handle);
+
+	return 0;
+out_err:
+	pr_err("QAT: failed to get device out of reset\n");
+	return -EFAULT;
+}
+
+static void qat_hal_disable_ctx(struct icp_qat_fw_loader_handle *handle,
+				unsigned char ae, unsigned int ctx_mask)
+{
+	unsigned int ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx);
+	ctx &= IGNORE_W1C_MASK &
+		(~((ctx_mask & ICP_QAT_UCLO_AE_ALL_CTX) << CE_ENABLE_BITPOS));
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
+}
+
+static uint64_t qat_hal_parity_64bit(uint64_t word)
+{
+	word ^= word >> 1;
+	word ^= word >> 2;
+	word ^= word >> 4;
+	word ^= word >> 8;
+	word ^= word >> 16;
+	word ^= word >> 32;
+	return word & 1;
+}
+
+static uint64_t qat_hal_set_uword_ecc(uint64_t uword)
+{
+	uint64_t bit0_mask = 0xff800007fffULL, bit1_mask = 0x1f801ff801fULL,
+		bit2_mask = 0xe387e0781e1ULL, bit3_mask = 0x7cb8e388e22ULL,
+		bit4_mask = 0xaf5b2c93244ULL, bit5_mask = 0xf56d5525488ULL,
+		bit6_mask = 0xdaf69a46910ULL;
+
+	/* clear the ecc bits */
+	uword &= ~(0x7fULL << 0x2C);
+	uword |= qat_hal_parity_64bit(bit0_mask & uword) << 0x2C;
+	uword |= qat_hal_parity_64bit(bit1_mask & uword) << 0x2D;
+	uword |= qat_hal_parity_64bit(bit2_mask & uword) << 0x2E;
+	uword |= qat_hal_parity_64bit(bit3_mask & uword) << 0x2F;
+	uword |= qat_hal_parity_64bit(bit4_mask & uword) << 0x30;
+	uword |= qat_hal_parity_64bit(bit5_mask & uword) << 0x31;
+	uword |= qat_hal_parity_64bit(bit6_mask & uword) << 0x32;
+	return uword;
+}
+
+void qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle,
+		       unsigned char ae, unsigned int uaddr,
+		       unsigned int words_num, uint64_t *uword)
+{
+	unsigned int ustore_addr;
+	unsigned int i;
+
+	qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+	uaddr |= UA_ECS;
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+	for (i = 0; i < words_num; i++) {
+		unsigned int uwrd_lo, uwrd_hi;
+		uint64_t tmp;
+
+		tmp = qat_hal_set_uword_ecc(uword[i]);
+		uwrd_lo = (unsigned int)(tmp & 0xffffffff);
+		uwrd_hi = (unsigned int)(tmp >> 0x20);
+		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+	}
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+static void qat_hal_enable_ctx(struct icp_qat_fw_loader_handle *handle,
+			       unsigned char ae, unsigned int ctx_mask)
+{
+	unsigned int ctx;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx);
+	ctx &= IGNORE_W1C_MASK;
+	ctx_mask &= (ctx & CE_INUSE_CONTEXTS) ? 0x55 : 0xFF;
+	ctx |= (ctx_mask << CE_ENABLE_BITPOS);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
+}
+
+static int qat_hal_clear_gpr(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned char ae;
+	unsigned int ctx_mask = ICP_QAT_UCLO_AE_ALL_CTX;
+	int times = MAX_RETRY_TIMES;
+	unsigned int csr_val = 0;
+	unsigned short reg;
+	unsigned int savctx = 0;
+	int ret = 0;
+
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!(handle->hal_handle->ae_mask & (1 << ae)))
+			continue;
+		for (reg = 0; reg < ICP_QAT_UCLO_MAX_GPR_REG; reg++) {
+			qat_hal_init_rd_xfer(handle, ae, 0, ICP_SR_RD_ABS,
+					     reg, 0);
+			qat_hal_init_rd_xfer(handle, ae, 0, ICP_DR_RD_ABS,
+					     reg, 0);
+		}
+		qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val);
+		csr_val &= ~(1 << MMC_SHARE_CS_BITPOS);
+		qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, csr_val);
+		qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr_val);
+		csr_val &= IGNORE_W1C_MASK;
+		csr_val |= CE_NN_MODE;
+		qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, csr_val);
+		qat_hal_wr_uwords(handle, ae, 0, ARRAY_SIZE(inst),
+				  (uint64_t *)inst);
+		qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+				    handle->hal_handle->upc_mask &
+				    INIT_PC_VALUE);
+		qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+		qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, 0);
+		qat_hal_put_wakeup_event(handle, ae, ctx_mask, XCWE_VOLUNTARY);
+		qat_hal_wr_indr_csr(handle, ae, ctx_mask,
+				    CTX_SIG_EVENTS_INDIRECT, 0);
+		qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0);
+		qat_hal_enable_ctx(handle, ae, ctx_mask);
+	}
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!(handle->hal_handle->ae_mask & (1 << ae)))
+			continue;
+		/* wait for AE to finish */
+		do {
+			ret = qat_hal_wait_cycles(handle, ae, 20, 1);
+		} while (ret && times--);
+
+		if (!times) {
+			pr_err("QAT: clear GPR of AE %d failed", ae);
+			return -EINVAL;
+		}
+		qat_hal_disable_ctx(handle, ae, ctx_mask);
+		qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+				  savctx & ACS_ACNO);
+		qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES,
+				  INIT_CTX_ENABLE_VALUE);
+		qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+				    handle->hal_handle->upc_mask &
+				    INIT_PC_VALUE);
+		qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE);
+		qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE);
+		qat_hal_put_wakeup_event(handle, ae, ctx_mask,
+					 INIT_WAKEUP_EVENTS_VALUE);
+		qat_hal_put_sig_event(handle, ae, ctx_mask,
+				      INIT_SIG_EVENTS_VALUE);
+	}
+	return 0;
+}
+
+#define ICP_DH895XCC_AE_OFFSET      0x20000
+#define ICP_DH895XCC_CAP_OFFSET     (ICP_DH895XCC_AE_OFFSET + 0x10000)
+#define LOCAL_TO_XFER_REG_OFFSET    0x800
+#define ICP_DH895XCC_EP_OFFSET      0x3a000
+#define ICP_DH895XCC_PMISC_BAR 1
+int qat_hal_init(struct adf_accel_dev *accel_dev)
+{
+	unsigned char ae;
+	unsigned int max_en_ae_id = 0;
+	struct icp_qat_fw_loader_handle *handle;
+	struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	struct adf_bar *bar = &pci_info->pci_bars[ADF_DH895XCC_PMISC_BAR];
+
+	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
+
+	handle->hal_cap_g_ctl_csr_addr_v = bar->virt_addr +
+						ICP_DH895XCC_CAP_OFFSET;
+	handle->hal_cap_ae_xfer_csr_addr_v = bar->virt_addr +
+						ICP_DH895XCC_AE_OFFSET;
+	handle->hal_ep_csr_addr_v = bar->virt_addr + ICP_DH895XCC_EP_OFFSET;
+	handle->hal_cap_ae_local_csr_addr_v =
+		handle->hal_cap_ae_xfer_csr_addr_v + LOCAL_TO_XFER_REG_OFFSET;
+
+	handle->hal_handle = kzalloc(sizeof(*handle->hal_handle), GFP_KERNEL);
+	if (!handle->hal_handle)
+		goto out_hal_handle;
+	handle->hal_handle->revision_id = accel_dev->accel_pci_dev.revid;
+	handle->hal_handle->ae_mask = hw_data->ae_mask;
+	handle->hal_handle->slice_mask = hw_data->accel_mask;
+	/* create AE objects */
+	handle->hal_handle->upc_mask = 0x1ffff;
+	handle->hal_handle->max_ustore = 0x4000;
+	for (ae = 0; ae < ICP_QAT_UCLO_MAX_AE; ae++) {
+		if (!(hw_data->ae_mask & (1 << ae)))
+			continue;
+		handle->hal_handle->aes[ae].free_addr = 0;
+		handle->hal_handle->aes[ae].free_size =
+		    handle->hal_handle->max_ustore;
+		handle->hal_handle->aes[ae].ustore_size =
+		    handle->hal_handle->max_ustore;
+		handle->hal_handle->aes[ae].live_ctx_mask =
+						ICP_QAT_UCLO_AE_ALL_CTX;
+		max_en_ae_id = ae;
+	}
+	handle->hal_handle->ae_max_num = max_en_ae_id + 1;
+	/* take all AEs out of reset */
+	if (qat_hal_clr_reset(handle)) {
+		pr_err("QAT: qat_hal_clr_reset error\n");
+		goto out_err;
+	}
+	if (qat_hal_clear_gpr(handle))
+		goto out_err;
+	/* Set SIGNATURE_ENABLE[0] to 0x1 in order to enable ALU_OUT csr */
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		unsigned int csr_val = 0;
+
+		if (!(hw_data->ae_mask & (1 << ae)))
+			continue;
+		qat_hal_rd_ae_csr(handle, ae, SIGNATURE_ENABLE, &csr_val);
+		csr_val |= 0x1;
+		qat_hal_wr_ae_csr(handle, ae, SIGNATURE_ENABLE, csr_val);
+	}
+	accel_dev->fw_loader->fw_loader = handle;
+	return 0;
+
+out_err:
+	kfree(handle->hal_handle);
+out_hal_handle:
+	kfree(handle);
+	return -EFAULT;
+}
+
+void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle)
+{
+	if (!handle)
+		return;
+	kfree(handle->hal_handle);
+	kfree(handle);
+}
+
+void qat_hal_start(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+		   unsigned int ctx_mask)
+{
+	qat_hal_put_wakeup_event(handle, ae, (~ctx_mask) &
+				 ICP_QAT_UCLO_AE_ALL_CTX, 0x10000);
+	qat_hal_enable_ctx(handle, ae, ctx_mask);
+}
+
+void qat_hal_stop(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+		  unsigned int ctx_mask)
+{
+	qat_hal_disable_ctx(handle, ae, ctx_mask);
+}
+
+void qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle,
+		    unsigned char ae, unsigned int ctx_mask, unsigned int upc)
+{
+	qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+			    handle->hal_handle->upc_mask & upc);
+}
+
+static void qat_hal_get_uwords(struct icp_qat_fw_loader_handle *handle,
+			       unsigned char ae, unsigned int uaddr,
+			       unsigned int words_num, uint64_t *uword)
+{
+	unsigned int i, uwrd_lo, uwrd_hi;
+	unsigned int ustore_addr, misc_control;
+
+	qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &misc_control);
+	qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL,
+			  misc_control & 0xfffffffb);
+	qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+	uaddr |= UA_ECS;
+	for (i = 0; i < words_num; i++) {
+		qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+		uaddr++;
+		qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_LOWER, &uwrd_lo);
+		qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_UPPER, &uwrd_hi);
+		uword[i] = uwrd_hi;
+		uword[i] = (uword[i] << 0x20) | uwrd_lo;
+	}
+	qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, misc_control);
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle,
+		     unsigned char ae, unsigned int uaddr,
+		     unsigned int words_num, unsigned int *data)
+{
+	unsigned int i, ustore_addr;
+
+	qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+	uaddr |= UA_ECS;
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+	for (i = 0; i < words_num; i++) {
+		unsigned int uwrd_lo, uwrd_hi, tmp;
+
+		uwrd_lo = ((data[i] & 0xfff0000) << 4) | (0x3 << 18) |
+			  ((data[i] & 0xff00) << 2) |
+			  (0x3 << 8) | (data[i] & 0xff);
+		uwrd_hi = (0xf << 4) | ((data[i] & 0xf0000000) >> 28);
+		uwrd_hi |= (hweight32(data[i] & 0xffff) & 0x1) << 8;
+		tmp = ((data[i] >> 0x10) & 0xffff);
+		uwrd_hi |= (hweight32(tmp) & 0x1) << 9;
+		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+		qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+	}
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+#define MAX_EXEC_INST 100
+static int qat_hal_exec_micro_inst(struct icp_qat_fw_loader_handle *handle,
+				   unsigned char ae, unsigned char ctx,
+				   uint64_t *micro_inst, unsigned int inst_num,
+				   int code_off, unsigned int max_cycle,
+				   unsigned int *endpc)
+{
+	uint64_t savuwords[MAX_EXEC_INST];
+	unsigned int ind_lm_addr0, ind_lm_addr1;
+	unsigned int ind_lm_addr_byte0, ind_lm_addr_byte1;
+	unsigned int ind_cnt_sig;
+	unsigned int ind_sig, act_sig;
+	unsigned int csr_val = 0, newcsr_val;
+	unsigned int savctx;
+	unsigned int savcc, wakeup_events, savpc;
+	unsigned int ctxarb_ctl, ctx_enables;
+
+	if ((inst_num > handle->hal_handle->max_ustore) || !micro_inst) {
+		pr_err("QAT: invalid instruction num %d\n", inst_num);
+		return -EINVAL;
+	}
+	/* save current context */
+	qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_0_INDIRECT, &ind_lm_addr0);
+	qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_1_INDIRECT, &ind_lm_addr1);
+	qat_hal_rd_indr_csr(handle, ae, ctx, INDIRECT_LM_ADDR_0_BYTE_INDEX,
+			    &ind_lm_addr_byte0);
+	qat_hal_rd_indr_csr(handle, ae, ctx, INDIRECT_LM_ADDR_1_BYTE_INDEX,
+			    &ind_lm_addr_byte1);
+	if (inst_num <= MAX_EXEC_INST)
+		qat_hal_get_uwords(handle, ae, 0, inst_num, savuwords);
+	qat_hal_get_wakeup_event(handle, ae, ctx, &wakeup_events);
+	qat_hal_rd_indr_csr(handle, ae, ctx, CTX_STS_INDIRECT, &savpc);
+	savpc = (savpc & handle->hal_handle->upc_mask) >> 0;
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	ctx_enables &= IGNORE_W1C_MASK;
+	qat_hal_rd_ae_csr(handle, ae, CC_ENABLE, &savcc);
+	qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+	qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_ctl);
+	qat_hal_rd_indr_csr(handle, ae, ctx, FUTURE_COUNT_SIGNAL_INDIRECT,
+			    &ind_cnt_sig);
+	qat_hal_rd_indr_csr(handle, ae, ctx, CTX_SIG_EVENTS_INDIRECT, &ind_sig);
+	qat_hal_rd_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, &act_sig);
+	/* execute micro codes */
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+	qat_hal_wr_uwords(handle, ae, 0, inst_num, micro_inst);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_STS_INDIRECT, 0);
+	qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, ctx & ACS_ACNO);
+	if (code_off)
+		qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc & 0xffffdfff);
+	qat_hal_put_wakeup_event(handle, ae, (1 << ctx), XCWE_VOLUNTARY);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_SIG_EVENTS_INDIRECT, 0);
+	qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0);
+	qat_hal_enable_ctx(handle, ae, (1 << ctx));
+	/* wait for micro codes to finish */
+	if (qat_hal_wait_cycles(handle, ae, max_cycle, 1) != 0)
+		return -EFAULT;
+	if (endpc) {
+		unsigned int ctx_status;
+
+		qat_hal_rd_indr_csr(handle, ae, ctx, CTX_STS_INDIRECT,
+				    &ctx_status);
+		*endpc = ctx_status & handle->hal_handle->upc_mask;
+	}
+	/* retore to saved context */
+	qat_hal_disable_ctx(handle, ae, (1 << ctx));
+	if (inst_num <= MAX_EXEC_INST)
+		qat_hal_wr_uwords(handle, ae, 0, inst_num, savuwords);
+	qat_hal_put_wakeup_event(handle, ae, (1 << ctx), wakeup_events);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_STS_INDIRECT,
+			    handle->hal_handle->upc_mask & savpc);
+	qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val);
+	newcsr_val = CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS);
+	qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val);
+	qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc);
+	qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, savctx & ACS_ACNO);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_ctl);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    LM_ADDR_0_INDIRECT, ind_lm_addr0);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    LM_ADDR_1_INDIRECT, ind_lm_addr1);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    INDIRECT_LM_ADDR_0_BYTE_INDEX, ind_lm_addr_byte0);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    INDIRECT_LM_ADDR_1_BYTE_INDEX, ind_lm_addr_byte1);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    FUTURE_COUNT_SIGNAL_INDIRECT, ind_cnt_sig);
+	qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+			    CTX_SIG_EVENTS_INDIRECT, ind_sig);
+	qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, act_sig);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+
+	return 0;
+}
+
+static int qat_hal_rd_rel_reg(struct icp_qat_fw_loader_handle *handle,
+			      unsigned char ae, unsigned char ctx,
+			      enum icp_qat_uof_regtype reg_type,
+			      unsigned short reg_num, unsigned int *data)
+{
+	unsigned int savctx, uaddr, uwrd_lo, uwrd_hi;
+	unsigned int ctxarb_cntl, ustore_addr, ctx_enables;
+	unsigned short reg_addr;
+	int status = 0;
+	uint64_t insts, savuword;
+
+	reg_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+	if (reg_addr == BAD_REGADDR) {
+		pr_err("QAT: bad regaddr=0x%x\n", reg_addr);
+		return -EINVAL;
+	}
+	switch (reg_type) {
+	case ICP_GPA_REL:
+		insts = 0xA070000000ull | (reg_addr & 0x3ff);
+		break;
+	default:
+		insts = (uint64_t)0xA030000000ull | ((reg_addr & 0x3ff) << 10);
+		break;
+	}
+	qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+	qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_cntl);
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	ctx_enables &= IGNORE_W1C_MASK;
+	if (ctx != (savctx & ACS_ACNO))
+		qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+				  ctx & ACS_ACNO);
+	qat_hal_get_uwords(handle, ae, 0, 1, &savuword);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+	qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+	uaddr = UA_ECS;
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+	insts = qat_hal_set_uword_ecc(insts);
+	uwrd_lo = (unsigned int)(insts & 0xffffffff);
+	uwrd_hi = (unsigned int)(insts >> 0x20);
+	qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+	qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+	/* delay for at least 8 cycles */
+	qat_hal_wait_cycles(handle, ae, 0x8, 0);
+	/*
+	 * read ALU output
+	 * the instruction should have been executed
+	 * prior to clearing the ECS in putUwords
+	 */
+	qat_hal_rd_ae_csr(handle, ae, ALU_OUT, data);
+	qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+	qat_hal_wr_uwords(handle, ae, 0, 1, &savuword);
+	if (ctx != (savctx & ACS_ACNO))
+		qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+				  savctx & ACS_ACNO);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_cntl);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+
+	return status;
+}
+
+static int qat_hal_wr_rel_reg(struct icp_qat_fw_loader_handle *handle,
+			      unsigned char ae, unsigned char ctx,
+			      enum icp_qat_uof_regtype reg_type,
+			      unsigned short reg_num, unsigned int data)
+{
+	unsigned short src_hiaddr, src_lowaddr, dest_addr, data16hi, data16lo;
+	uint64_t insts[] = {
+		0x0F440000000ull,
+		0x0F040000000ull,
+		0x0F0000C0300ull,
+		0x0E000010000ull
+	};
+	const int num_inst = ARRAY_SIZE(insts), code_off = 1;
+	const int imm_w1 = 0, imm_w0 = 1;
+
+	dest_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+	if (dest_addr == BAD_REGADDR) {
+		pr_err("QAT: bad destAddr=0x%x\n", dest_addr);
+		return -EINVAL;
+	}
+
+	data16lo = 0xffff & data;
+	data16hi = 0xffff & (data >> 0x10);
+	src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST, (unsigned short)
+					  (0xff & data16hi));
+	src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST, (unsigned short)
+					   (0xff & data16lo));
+	switch (reg_type) {
+	case ICP_GPA_REL:
+		insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) |
+		    ((src_hiaddr & 0x3ff) << 10) | (dest_addr & 0x3ff);
+		insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) |
+		    ((src_lowaddr & 0x3ff) << 10) | (dest_addr & 0x3ff);
+		break;
+	default:
+		insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) |
+		    ((dest_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff);
+
+		insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) |
+		    ((dest_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff);
+		break;
+	}
+
+	return qat_hal_exec_micro_inst(handle, ae, ctx, insts, num_inst,
+				       code_off, num_inst * 0x5, NULL);
+}
+
+int qat_hal_get_ins_num(void)
+{
+	return ARRAY_SIZE(inst_4b);
+}
+
+static int qat_hal_concat_micro_code(uint64_t *micro_inst,
+				     unsigned int inst_num, unsigned int size,
+				     unsigned int addr, unsigned int *value)
+{
+	int i, val_indx;
+	unsigned int cur_value;
+	const uint64_t *inst_arr;
+	int fixup_offset;
+	int usize = 0;
+	int orig_num;
+
+	orig_num = inst_num;
+	val_indx = 0;
+	cur_value = value[val_indx++];
+	inst_arr = inst_4b;
+	usize = ARRAY_SIZE(inst_4b);
+	fixup_offset = inst_num;
+	for (i = 0; i < usize; i++)
+		micro_inst[inst_num++] = inst_arr[i];
+	INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], (addr));
+	fixup_offset++;
+	INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], 0);
+	fixup_offset++;
+	INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0));
+	fixup_offset++;
+	INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0x10));
+
+	return inst_num - orig_num;
+}
+
+static int qat_hal_exec_micro_init_lm(struct icp_qat_fw_loader_handle *handle,
+				      unsigned char ae, unsigned char ctx,
+				      int *pfirst_exec, uint64_t *micro_inst,
+				      unsigned int inst_num)
+{
+	int stat = 0;
+	unsigned int gpra0 = 0, gpra1 = 0, gpra2 = 0;
+	unsigned int gprb0 = 0, gprb1 = 0;
+
+	if (*pfirst_exec) {
+		qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, &gpra0);
+		qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, &gpra1);
+		qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, &gpra2);
+		qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, &gprb0);
+		qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, &gprb1);
+		*pfirst_exec = 0;
+	}
+	stat = qat_hal_exec_micro_inst(handle, ae, ctx, micro_inst, inst_num, 1,
+				       inst_num * 0x5, NULL);
+	if (stat != 0)
+		return -EFAULT;
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, gpra0);
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, gpra1);
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, gpra2);
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, gprb0);
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, gprb1);
+
+	return 0;
+}
+
+int qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle,
+			unsigned char ae,
+			struct icp_qat_uof_batch_init *lm_init_header)
+{
+	struct icp_qat_uof_batch_init *plm_init;
+	uint64_t *micro_inst_arry;
+	int micro_inst_num;
+	int alloc_inst_size;
+	int first_exec = 1;
+	int stat = 0;
+
+	plm_init = lm_init_header->next;
+	alloc_inst_size = lm_init_header->size;
+	if ((unsigned int)alloc_inst_size > handle->hal_handle->max_ustore)
+		alloc_inst_size = handle->hal_handle->max_ustore;
+	micro_inst_arry = kmalloc_array(alloc_inst_size, sizeof(uint64_t),
+					GFP_KERNEL);
+	if (!micro_inst_arry)
+		return -ENOMEM;
+	micro_inst_num = 0;
+	while (plm_init) {
+		unsigned int addr, *value, size;
+
+		ae = plm_init->ae;
+		addr = plm_init->addr;
+		value = plm_init->value;
+		size = plm_init->size;
+		micro_inst_num += qat_hal_concat_micro_code(micro_inst_arry,
+							    micro_inst_num,
+							    size, addr, value);
+		plm_init = plm_init->next;
+	}
+	/* exec micro codes */
+	if (micro_inst_arry && (micro_inst_num > 0)) {
+		micro_inst_arry[micro_inst_num++] = 0x0E000010000ull;
+		stat = qat_hal_exec_micro_init_lm(handle, ae, 0, &first_exec,
+						  micro_inst_arry,
+						  micro_inst_num);
+	}
+	kfree(micro_inst_arry);
+	return stat;
+}
+
+static int qat_hal_put_rel_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+				   unsigned char ae, unsigned char ctx,
+				   enum icp_qat_uof_regtype reg_type,
+				   unsigned short reg_num, unsigned int val)
+{
+	int status = 0;
+	unsigned int reg_addr;
+	unsigned int ctx_enables;
+	unsigned short mask;
+	unsigned short dr_offset = 0x10;
+
+	status = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	if (CE_INUSE_CONTEXTS & ctx_enables) {
+		if (ctx & 0x1) {
+			pr_err("QAT: bad 4-ctx mode,ctx=0x%x\n", ctx);
+			return -EINVAL;
+		}
+		mask = 0x1f;
+		dr_offset = 0x20;
+	} else {
+		mask = 0x0f;
+	}
+	if (reg_num & ~mask)
+		return -EINVAL;
+	reg_addr = reg_num + (ctx << 0x5);
+	switch (reg_type) {
+	case ICP_SR_RD_REL:
+	case ICP_SR_REL:
+		SET_AE_XFER(handle, ae, reg_addr, val);
+		break;
+	case ICP_DR_RD_REL:
+	case ICP_DR_REL:
+		SET_AE_XFER(handle, ae, (reg_addr + dr_offset), val);
+		break;
+	default:
+		status = -EINVAL;
+		break;
+	}
+	return status;
+}
+
+static int qat_hal_put_rel_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+				   unsigned char ae, unsigned char ctx,
+				   enum icp_qat_uof_regtype reg_type,
+				   unsigned short reg_num, unsigned int data)
+{
+	unsigned int gprval, ctx_enables;
+	unsigned short src_hiaddr, src_lowaddr, gpr_addr, xfr_addr, data16hi,
+	    data16low;
+	unsigned short reg_mask;
+	int status = 0;
+	uint64_t micro_inst[] = {
+		0x0F440000000ull,
+		0x0F040000000ull,
+		0x0A000000000ull,
+		0x0F0000C0300ull,
+		0x0E000010000ull
+	};
+	const int num_inst = ARRAY_SIZE(micro_inst), code_off = 1;
+	const unsigned short gprnum = 0, dly = num_inst * 0x5;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	if (CE_INUSE_CONTEXTS & ctx_enables) {
+		if (ctx & 0x1) {
+			pr_err("QAT: 4-ctx mode,ctx=0x%x\n", ctx);
+			return -EINVAL;
+		}
+		reg_mask = (unsigned short)~0x1f;
+	} else {
+		reg_mask = (unsigned short)~0xf;
+	}
+	if (reg_num & reg_mask)
+		return -EINVAL;
+	xfr_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+	if (xfr_addr == BAD_REGADDR) {
+		pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr);
+		return -EINVAL;
+	}
+	qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
+	gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum);
+	data16low = 0xffff & data;
+	data16hi = 0xffff & (data >> 0x10);
+	src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST,
+					  (unsigned short)(0xff & data16hi));
+	src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST,
+					   (unsigned short)(0xff & data16low));
+	micro_inst[0] = micro_inst[0x0] | ((data16hi >> 8) << 20) |
+	    ((gpr_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff);
+	micro_inst[1] = micro_inst[0x1] | ((data16low >> 8) << 20) |
+	    ((gpr_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff);
+	micro_inst[0x2] = micro_inst[0x2] |
+	    ((xfr_addr & 0x3ff) << 20) | ((gpr_addr & 0x3ff) << 10);
+	status = qat_hal_exec_micro_inst(handle, ae, ctx, micro_inst, num_inst,
+					 code_off, dly, NULL);
+	qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, gprval);
+	return status;
+}
+
+static int qat_hal_put_rel_nn(struct icp_qat_fw_loader_handle *handle,
+			      unsigned char ae, unsigned char ctx,
+			      unsigned short nn, unsigned int val)
+{
+	unsigned int ctx_enables;
+	int stat = 0;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	ctx_enables &= IGNORE_W1C_MASK;
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables | CE_NN_MODE);
+
+	stat = qat_hal_put_rel_wr_xfer(handle, ae, ctx, ICP_NEIGH_REL, nn, val);
+	qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+	return stat;
+}
+
+static int qat_hal_convert_abs_to_rel(struct icp_qat_fw_loader_handle
+				      *handle, unsigned char ae,
+				      unsigned short absreg_num,
+				      unsigned short *relreg,
+				      unsigned char *ctx)
+{
+	unsigned int ctx_enables;
+
+	qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+	if (ctx_enables & CE_INUSE_CONTEXTS) {
+		/* 4-ctx mode */
+		*relreg = absreg_num & 0x1F;
+		*ctx = (absreg_num >> 0x4) & 0x6;
+	} else {
+		/* 8-ctx mode */
+		*relreg = absreg_num & 0x0F;
+		*ctx = (absreg_num >> 0x4) & 0x7;
+	}
+	return 0;
+}
+
+int qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle,
+		     unsigned char ae, unsigned char ctx_mask,
+		     enum icp_qat_uof_regtype reg_type,
+		     unsigned short reg_num, unsigned int regdata)
+{
+	int stat = 0;
+	unsigned short reg;
+	unsigned char ctx = 0;
+	enum icp_qat_uof_regtype type;
+
+	if (reg_num >= ICP_QAT_UCLO_MAX_GPR_REG)
+		return -EINVAL;
+
+	do {
+		if (ctx_mask == 0) {
+			qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+						   &ctx);
+			type = reg_type - 1;
+		} else {
+			reg = reg_num;
+			type = reg_type;
+			if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+				continue;
+		}
+		stat = qat_hal_wr_rel_reg(handle, ae, ctx, type, reg, regdata);
+		if (stat) {
+			pr_err("QAT: write gpr fail\n");
+			return -EINVAL;
+		}
+	} while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+	return 0;
+}
+
+int qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+			 unsigned char ae, unsigned char ctx_mask,
+			 enum icp_qat_uof_regtype reg_type,
+			 unsigned short reg_num, unsigned int regdata)
+{
+	int stat = 0;
+	unsigned short reg;
+	unsigned char ctx = 0;
+	enum icp_qat_uof_regtype type;
+
+	if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG)
+		return -EINVAL;
+
+	do {
+		if (ctx_mask == 0) {
+			qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+						   &ctx);
+			type = reg_type - 3;
+		} else {
+			reg = reg_num;
+			type = reg_type;
+			if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+				continue;
+		}
+		stat = qat_hal_put_rel_wr_xfer(handle, ae, ctx, type, reg,
+					       regdata);
+		if (stat) {
+			pr_err("QAT: write wr xfer fail\n");
+			return -EINVAL;
+		}
+	} while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+	return 0;
+}
+
+int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+			 unsigned char ae, unsigned char ctx_mask,
+			 enum icp_qat_uof_regtype reg_type,
+			 unsigned short reg_num, unsigned int regdata)
+{
+	int stat = 0;
+	unsigned short reg;
+	unsigned char ctx = 0;
+	enum icp_qat_uof_regtype type;
+
+	if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG)
+		return -EINVAL;
+
+	do {
+		if (ctx_mask == 0) {
+			qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+						   &ctx);
+			type = reg_type - 3;
+		} else {
+			reg = reg_num;
+			type = reg_type;
+			if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+				continue;
+		}
+		stat = qat_hal_put_rel_rd_xfer(handle, ae, ctx, type, reg,
+					       regdata);
+		if (stat) {
+			pr_err("QAT: write rd xfer fail\n");
+			return -EINVAL;
+		}
+	} while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+	return 0;
+}
+
+int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle,
+		    unsigned char ae, unsigned char ctx_mask,
+		    unsigned short reg_num, unsigned int regdata)
+{
+	int stat = 0;
+	unsigned char ctx;
+
+	if (ctx_mask == 0)
+		return -EINVAL;
+
+	for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+		if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+			continue;
+		stat = qat_hal_put_rel_nn(handle, ae, ctx, reg_num, regdata);
+		if (stat) {
+			pr_err("QAT: write neigh error\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_uclo.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_uclo.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_common/qat_uclo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_common/qat_uclo.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1181 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_uclo.h"
+#include "icp_qat_hal.h"
+#include "icp_qat_fw_loader_handle.h"
+
+#define UWORD_CPYBUF_SIZE 1024
+#define INVLD_UWORD 0xffffffffffull
+#define PID_MINOR_REV 0xf
+#define PID_MAJOR_REV (0xf << 4)
+
+static int qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle,
+				 unsigned int ae, unsigned int image_num)
+{
+	struct icp_qat_uclo_aedata *ae_data;
+	struct icp_qat_uclo_encapme *encap_image;
+	struct icp_qat_uclo_page *page = NULL;
+	struct icp_qat_uclo_aeslice *ae_slice = NULL;
+
+	ae_data = &obj_handle->ae_data[ae];
+	encap_image = &obj_handle->ae_uimage[image_num];
+	ae_slice = &ae_data->ae_slices[ae_data->slice_num];
+	ae_slice->encap_image = encap_image;
+
+	if (encap_image->img_ptr) {
+		ae_slice->ctx_mask_assigned =
+					encap_image->img_ptr->ctx_assigned;
+		ae_data->eff_ustore_size = obj_handle->ustore_phy_size;
+	} else {
+		ae_slice->ctx_mask_assigned = 0;
+	}
+	ae_slice->region = kzalloc(sizeof(*ae_slice->region), GFP_KERNEL);
+	if (!ae_slice->region)
+		return -ENOMEM;
+	ae_slice->page = kzalloc(sizeof(*ae_slice->page), GFP_KERNEL);
+	if (!ae_slice->page)
+		goto out_err;
+	page = ae_slice->page;
+	page->encap_page = encap_image->page;
+	ae_slice->page->region = ae_slice->region;
+	ae_data->slice_num++;
+	return 0;
+out_err:
+	kfree(ae_slice->region);
+	ae_slice->region = NULL;
+	return -ENOMEM;
+}
+
+static int qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data)
+{
+	unsigned int i;
+
+	if (!ae_data) {
+		pr_err("QAT: bad argument, ae_data is NULL\n ");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ae_data->slice_num; i++) {
+		kfree(ae_data->ae_slices[i].region);
+		ae_data->ae_slices[i].region = NULL;
+		kfree(ae_data->ae_slices[i].page);
+		ae_data->ae_slices[i].page = NULL;
+	}
+	return 0;
+}
+
+static char *qat_uclo_get_string(struct icp_qat_uof_strtable *str_table,
+				 unsigned int str_offset)
+{
+	if ((!str_table->table_len) || (str_offset > str_table->table_len))
+		return NULL;
+	return (char *)(((unsigned long)(str_table->strings)) + str_offset);
+}
+
+static int qat_uclo_check_format(struct icp_qat_uof_filehdr *hdr)
+{
+	int maj = hdr->maj_ver & 0xff;
+	int min = hdr->min_ver & 0xff;
+
+	if (hdr->file_id != ICP_QAT_UOF_FID) {
+		pr_err("QAT: Invalid header 0x%x\n", hdr->file_id);
+		return -EINVAL;
+	}
+	if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) {
+		pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n",
+		       maj, min);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle,
+				      unsigned int addr, unsigned int *val,
+				      unsigned int num_in_bytes)
+{
+	unsigned int outval;
+	unsigned char *ptr = (unsigned char *)val;
+
+	while (num_in_bytes) {
+		memcpy(&outval, ptr, 4);
+		SRAM_WRITE(handle, addr, outval);
+		num_in_bytes -= 4;
+		ptr += 4;
+		addr += 4;
+	}
+}
+
+static void qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle,
+				      unsigned char ae, unsigned int addr,
+				      unsigned int *val,
+				      unsigned int num_in_bytes)
+{
+	unsigned int outval;
+	unsigned char *ptr = (unsigned char *)val;
+
+	addr >>= 0x2; /* convert to uword address */
+
+	while (num_in_bytes) {
+		memcpy(&outval, ptr, 4);
+		qat_hal_wr_umem(handle, ae, addr++, 1, &outval);
+		num_in_bytes -= 4;
+		ptr += 4;
+	}
+}
+
+static void qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle,
+				   unsigned char ae,
+				   struct icp_qat_uof_batch_init
+				   *umem_init_header)
+{
+	struct icp_qat_uof_batch_init *umem_init;
+
+	if (!umem_init_header)
+		return;
+	umem_init = umem_init_header->next;
+	while (umem_init) {
+		unsigned int addr, *value, size;
+
+		ae = umem_init->ae;
+		addr = umem_init->addr;
+		value = umem_init->value;
+		size = umem_init->size;
+		qat_uclo_wr_umem_by_words(handle, ae, addr, value, size);
+		umem_init = umem_init->next;
+	}
+}
+
+static void
+qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,
+				 struct icp_qat_uof_batch_init **base)
+{
+	struct icp_qat_uof_batch_init *umem_init;
+
+	umem_init = *base;
+	while (umem_init) {
+		struct icp_qat_uof_batch_init *pre;
+
+		pre = umem_init;
+		umem_init = umem_init->next;
+		kfree(pre);
+	}
+	*base = NULL;
+}
+
+static int qat_uclo_parse_num(char *str, unsigned int *num)
+{
+	char buf[16] = {0};
+	unsigned long ae = 0;
+	int i;
+
+	strncpy(buf, str, 15);
+	for (i = 0; i < 16; i++) {
+		if (!isdigit(buf[i])) {
+			buf[i] = '\0';
+			break;
+		}
+	}
+	if ((kstrtoul(buf, 10, &ae)))
+		return -EFAULT;
+
+	*num = (unsigned int)ae;
+	return 0;
+}
+
+static int qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle,
+				     struct icp_qat_uof_initmem *init_mem,
+				     unsigned int size_range, unsigned int *ae)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	char *str;
+
+	if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) {
+		pr_err("QAT: initmem is out of range");
+		return -EINVAL;
+	}
+	if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) {
+		pr_err("QAT: Memory scope for init_mem error\n");
+		return -EINVAL;
+	}
+	str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name);
+	if (!str) {
+		pr_err("QAT: AE name assigned in UOF init table is NULL\n");
+		return -EINVAL;
+	}
+	if (qat_uclo_parse_num(str, ae)) {
+		pr_err("QAT: Parse num for AE number failed\n");
+		return -EINVAL;
+	}
+	if (*ae >= ICP_QAT_UCLO_MAX_AE) {
+		pr_err("QAT: ae %d out of range\n", *ae);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle
+					   *handle, struct icp_qat_uof_initmem
+					   *init_mem, unsigned int ae,
+					   struct icp_qat_uof_batch_init
+					   **init_tab_base)
+{
+	struct icp_qat_uof_batch_init *init_header, *tail;
+	struct icp_qat_uof_batch_init *mem_init, *tail_old;
+	struct icp_qat_uof_memvar_attr *mem_val_attr;
+	unsigned int i, flag = 0;
+
+	mem_val_attr =
+		(struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
+		sizeof(struct icp_qat_uof_initmem));
+
+	init_header = *init_tab_base;
+	if (!init_header) {
+		init_header = kzalloc(sizeof(*init_header), GFP_KERNEL);
+		if (!init_header)
+			return -ENOMEM;
+		init_header->size = 1;
+		*init_tab_base = init_header;
+		flag = 1;
+	}
+	tail_old = init_header;
+	while (tail_old->next)
+		tail_old = tail_old->next;
+	tail = tail_old;
+	for (i = 0; i < init_mem->val_attr_num; i++) {
+		mem_init = kzalloc(sizeof(*mem_init), GFP_KERNEL);
+		if (!mem_init)
+			goto out_err;
+		mem_init->ae = ae;
+		mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte;
+		mem_init->value = &mem_val_attr->value;
+		mem_init->size = 4;
+		mem_init->next = NULL;
+		tail->next = mem_init;
+		tail = mem_init;
+		init_header->size += qat_hal_get_ins_num();
+		mem_val_attr++;
+	}
+	return 0;
+out_err:
+	while (tail_old) {
+		mem_init = tail_old->next;
+		kfree(tail_old);
+		tail_old = mem_init;
+	}
+	if (flag)
+		kfree(*init_tab_base);
+	return -ENOMEM;
+}
+
+static int qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle,
+				  struct icp_qat_uof_initmem *init_mem)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int ae;
+
+	if (qat_uclo_fetch_initmem_ae(handle, init_mem,
+				      ICP_QAT_UCLO_MAX_LMEM_REG, &ae))
+		return -EINVAL;
+	if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
+					    &obj_handle->lm_init_tab[ae]))
+		return -EINVAL;
+	return 0;
+}
+
+static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
+				  struct icp_qat_uof_initmem *init_mem)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int ae, ustore_size, uaddr, i;
+
+	ustore_size = obj_handle->ustore_phy_size;
+	if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae))
+		return -EINVAL;
+	if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
+					    &obj_handle->umem_init_tab[ae]))
+		return -EINVAL;
+	/* set the highest ustore address referenced */
+	uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2;
+	for (i = 0; i < obj_handle->ae_data[ae].slice_num; i++) {
+		if (obj_handle->ae_data[ae].ae_slices[i].
+		    encap_image->uwords_num < uaddr)
+			obj_handle->ae_data[ae].ae_slices[i].
+			encap_image->uwords_num = uaddr;
+	}
+	return 0;
+}
+
+#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
+static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
+				   struct icp_qat_uof_initmem *init_mem)
+{
+	unsigned int i;
+	struct icp_qat_uof_memvar_attr *mem_val_attr;
+
+	mem_val_attr =
+		(struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
+		sizeof(struct icp_qat_uof_initmem));
+
+	switch (init_mem->region) {
+	case ICP_QAT_UOF_SRAM_REGION:
+		if ((init_mem->addr + init_mem->num_in_bytes) >
+		    ICP_DH895XCC_PESRAM_BAR_SIZE) {
+			pr_err("QAT: initmem on SRAM is out of range");
+			return -EINVAL;
+		}
+		for (i = 0; i < init_mem->val_attr_num; i++) {
+			qat_uclo_wr_sram_by_words(handle,
+						  init_mem->addr +
+						  mem_val_attr->offset_in_byte,
+						  &mem_val_attr->value, 4);
+			mem_val_attr++;
+		}
+		break;
+	case ICP_QAT_UOF_LMEM_REGION:
+		if (qat_uclo_init_lmem_seg(handle, init_mem))
+			return -EINVAL;
+		break;
+	case ICP_QAT_UOF_UMEM_REGION:
+		if (qat_uclo_init_umem_seg(handle, init_mem))
+			return -EINVAL;
+		break;
+	default:
+		pr_err("QAT: initmem region error. region type=0x%x\n",
+		       init_mem->region);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle,
+				struct icp_qat_uclo_encapme *image)
+{
+	unsigned int i;
+	struct icp_qat_uclo_encap_page *page;
+	struct icp_qat_uof_image *uof_image;
+	unsigned char ae;
+	unsigned int ustore_size;
+	unsigned int patt_pos;
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	uint64_t *fill_data;
+
+	uof_image = image->img_ptr;
+	fill_data = kcalloc(ICP_QAT_UCLO_MAX_USTORE, sizeof(uint64_t),
+			    GFP_KERNEL);
+	if (!fill_data)
+		return -ENOMEM;
+	for (i = 0; i < ICP_QAT_UCLO_MAX_USTORE; i++)
+		memcpy(&fill_data[i], &uof_image->fill_pattern,
+		       sizeof(uint64_t));
+	page = image->page;
+
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!test_bit(ae, (unsigned long *)&uof_image->ae_assigned))
+			continue;
+		ustore_size = obj_handle->ae_data[ae].eff_ustore_size;
+		patt_pos = page->beg_addr_p + page->micro_words_num;
+
+		qat_hal_wr_uwords(handle, (unsigned char)ae, 0,
+				  page->beg_addr_p, &fill_data[0]);
+		qat_hal_wr_uwords(handle, (unsigned char)ae, patt_pos,
+				  ustore_size - patt_pos + 1,
+				  &fill_data[page->beg_addr_p]);
+	}
+	kfree(fill_data);
+	return 0;
+}
+
+static int qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle)
+{
+	int i, ae;
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem;
+
+	for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) {
+		if (initmem->num_in_bytes) {
+			if (qat_uclo_init_ae_memory(handle, initmem))
+				return -EINVAL;
+		}
+		initmem = (struct icp_qat_uof_initmem *)((unsigned long)(
+			(unsigned long)initmem +
+			sizeof(struct icp_qat_uof_initmem)) +
+			(sizeof(struct icp_qat_uof_memvar_attr) *
+			initmem->val_attr_num));
+	}
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (qat_hal_batch_wr_lm(handle, ae,
+					obj_handle->lm_init_tab[ae])) {
+			pr_err("QAT: fail to batch init lmem for AE %d\n", ae);
+			return -EINVAL;
+		}
+		qat_uclo_cleanup_batch_init_list(handle,
+						 &obj_handle->lm_init_tab[ae]);
+		qat_uclo_batch_wr_umem(handle, ae,
+				       obj_handle->umem_init_tab[ae]);
+		qat_uclo_cleanup_batch_init_list(handle,
+						 &obj_handle->
+						 umem_init_tab[ae]);
+	}
+	return 0;
+}
+
+static void *qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr,
+				 char *chunk_id, void *cur)
+{
+	int i;
+	struct icp_qat_uof_chunkhdr *chunk_hdr =
+	    (struct icp_qat_uof_chunkhdr *)
+	    ((unsigned long)obj_hdr + sizeof(struct icp_qat_uof_objhdr));
+
+	for (i = 0; i < obj_hdr->num_chunks; i++) {
+		if ((cur < (void *)&chunk_hdr[i]) &&
+		    !strncmp(chunk_hdr[i].chunk_id, chunk_id,
+			     ICP_QAT_UOF_OBJID_LEN)) {
+			return &chunk_hdr[i];
+		}
+	}
+	return NULL;
+}
+
+static unsigned int qat_uclo_calc_checksum(unsigned int reg, int ch)
+{
+	int i;
+	unsigned int topbit = 1 << 0xF;
+	unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch);
+
+	reg ^= inbyte << 0x8;
+	for (i = 0; i < 0x8; i++) {
+		if (reg & topbit)
+			reg = (reg << 1) ^ 0x1021;
+		else
+			reg <<= 1;
+	}
+	return reg & 0xFFFF;
+}
+
+static unsigned int qat_uclo_calc_str_checksum(char *ptr, int num)
+{
+	unsigned int chksum = 0;
+
+	if (ptr)
+		while (num--)
+			chksum = qat_uclo_calc_checksum(chksum, *ptr++);
+	return chksum;
+}
+
+static struct icp_qat_uclo_objhdr *
+qat_uclo_map_chunk(char *buf, struct icp_qat_uof_filehdr *file_hdr,
+		   char *chunk_id)
+{
+	struct icp_qat_uof_filechunkhdr *file_chunk;
+	struct icp_qat_uclo_objhdr *obj_hdr;
+	char *chunk;
+	int i;
+
+	file_chunk = (struct icp_qat_uof_filechunkhdr *)
+		(buf + sizeof(struct icp_qat_uof_filehdr));
+	for (i = 0; i < file_hdr->num_chunks; i++) {
+		if (!strncmp(file_chunk->chunk_id, chunk_id,
+			     ICP_QAT_UOF_OBJID_LEN)) {
+			chunk = buf + file_chunk->offset;
+			if (file_chunk->checksum != qat_uclo_calc_str_checksum(
+				chunk, file_chunk->size))
+				break;
+			obj_hdr = kzalloc(sizeof(*obj_hdr), GFP_KERNEL);
+			if (!obj_hdr)
+				break;
+			obj_hdr->file_buff = chunk;
+			obj_hdr->checksum = file_chunk->checksum;
+			obj_hdr->size = file_chunk->size;
+			return obj_hdr;
+		}
+		file_chunk++;
+	}
+	return NULL;
+}
+
+static unsigned int
+qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj,
+			    struct icp_qat_uof_image *image)
+{
+	struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab;
+	struct icp_qat_uof_objtable *neigh_reg_tab;
+	struct icp_qat_uof_code_page *code_page;
+
+	code_page = (struct icp_qat_uof_code_page *)
+			((char *)image + sizeof(struct icp_qat_uof_image));
+	uc_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
+		     code_page->uc_var_tab_offset);
+	imp_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
+		      code_page->imp_var_tab_offset);
+	imp_expr_tab = (struct icp_qat_uof_objtable *)
+		       (encap_uof_obj->beg_uof +
+		       code_page->imp_expr_tab_offset);
+	if (uc_var_tab->entry_num || imp_var_tab->entry_num ||
+	    imp_expr_tab->entry_num) {
+		pr_err("QAT: UOF can't contain imported variable to be parsed");
+		return -EINVAL;
+	}
+	neigh_reg_tab = (struct icp_qat_uof_objtable *)
+			(encap_uof_obj->beg_uof +
+			code_page->neigh_reg_tab_offset);
+	if (neigh_reg_tab->entry_num) {
+		pr_err("QAT: UOF can't contain shared control store feature");
+		return -EINVAL;
+	}
+	if (image->numpages > 1) {
+		pr_err("QAT: UOF can't contain multiple pages");
+		return -EINVAL;
+	}
+	if (ICP_QAT_SHARED_USTORE_MODE(image->ae_mode)) {
+		pr_err("QAT: UOF can't use shared control store feature");
+		return -EFAULT;
+	}
+	if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) {
+		pr_err("QAT: UOF can't use reloadable feature");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void qat_uclo_map_image_page(struct icp_qat_uof_encap_obj
+				     *encap_uof_obj,
+				     struct icp_qat_uof_image *img,
+				     struct icp_qat_uclo_encap_page *page)
+{
+	struct icp_qat_uof_code_page *code_page;
+	struct icp_qat_uof_code_area *code_area;
+	struct icp_qat_uof_objtable *uword_block_tab;
+	struct icp_qat_uof_uword_block *uwblock;
+	int i;
+
+	code_page = (struct icp_qat_uof_code_page *)
+			((char *)img + sizeof(struct icp_qat_uof_image));
+	page->def_page = code_page->def_page;
+	page->page_region = code_page->page_region;
+	page->beg_addr_v = code_page->beg_addr_v;
+	page->beg_addr_p = code_page->beg_addr_p;
+	code_area = (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof +
+						code_page->code_area_offset);
+	page->micro_words_num = code_area->micro_words_num;
+	uword_block_tab = (struct icp_qat_uof_objtable *)
+			  (encap_uof_obj->beg_uof +
+			  code_area->uword_block_tab);
+	page->uwblock_num = uword_block_tab->entry_num;
+	uwblock = (struct icp_qat_uof_uword_block *)((char *)uword_block_tab +
+			sizeof(struct icp_qat_uof_objtable));
+	page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock;
+	for (i = 0; i < uword_block_tab->entry_num; i++)
+		page->uwblock[i].micro_words =
+		(unsigned long)encap_uof_obj->beg_uof + uwblock[i].uword_offset;
+}
+
+static int qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle,
+			       struct icp_qat_uclo_encapme *ae_uimage,
+			       int max_image)
+{
+	int i, j;
+	struct icp_qat_uof_chunkhdr *chunk_hdr = NULL;
+	struct icp_qat_uof_image *image;
+	struct icp_qat_uof_objtable *ae_regtab;
+	struct icp_qat_uof_objtable *init_reg_sym_tab;
+	struct icp_qat_uof_objtable *sbreak_tab;
+	struct icp_qat_uof_encap_obj *encap_uof_obj =
+					&obj_handle->encap_uof_obj;
+
+	for (j = 0; j < max_image; j++) {
+		chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
+						ICP_QAT_UOF_IMAG, chunk_hdr);
+		if (!chunk_hdr)
+			break;
+		image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof +
+						     chunk_hdr->offset);
+		ae_regtab = (struct icp_qat_uof_objtable *)
+			   (image->reg_tab_offset +
+			   obj_handle->obj_hdr->file_buff);
+		ae_uimage[j].ae_reg_num = ae_regtab->entry_num;
+		ae_uimage[j].ae_reg = (struct icp_qat_uof_ae_reg *)
+			(((char *)ae_regtab) +
+			sizeof(struct icp_qat_uof_objtable));
+		init_reg_sym_tab = (struct icp_qat_uof_objtable *)
+				   (image->init_reg_sym_tab +
+				   obj_handle->obj_hdr->file_buff);
+		ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num;
+		ae_uimage[j].init_regsym = (struct icp_qat_uof_init_regsym *)
+			(((char *)init_reg_sym_tab) +
+			sizeof(struct icp_qat_uof_objtable));
+		sbreak_tab = (struct icp_qat_uof_objtable *)
+			(image->sbreak_tab + obj_handle->obj_hdr->file_buff);
+		ae_uimage[j].sbreak_num = sbreak_tab->entry_num;
+		ae_uimage[j].sbreak = (struct icp_qat_uof_sbreak *)
+				      (((char *)sbreak_tab) +
+				      sizeof(struct icp_qat_uof_objtable));
+		ae_uimage[j].img_ptr = image;
+		if (qat_uclo_check_image_compat(encap_uof_obj, image))
+			goto out_err;
+		ae_uimage[j].page =
+			kzalloc(sizeof(struct icp_qat_uclo_encap_page),
+				GFP_KERNEL);
+		if (!ae_uimage[j].page)
+			goto out_err;
+		qat_uclo_map_image_page(encap_uof_obj, image,
+					ae_uimage[j].page);
+	}
+	return j;
+out_err:
+	for (i = 0; i < j; i++)
+		kfree(ae_uimage[i].page);
+	return 0;
+}
+
+static int qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae)
+{
+	int i, ae;
+	int mflag = 0;
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+
+	for (ae = 0; ae <= max_ae; ae++) {
+		if (!test_bit(ae,
+			      (unsigned long *)&handle->hal_handle->ae_mask))
+			continue;
+		for (i = 0; i < obj_handle->uimage_num; i++) {
+			if (!test_bit(ae, (unsigned long *)
+			&obj_handle->ae_uimage[i].img_ptr->ae_assigned))
+				continue;
+			mflag = 1;
+			if (qat_uclo_init_ae_data(obj_handle, ae, i))
+				return -EINVAL;
+		}
+	}
+	if (!mflag) {
+		pr_err("QAT: uimage uses AE not set");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct icp_qat_uof_strtable *
+qat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr,
+		       char *tab_name, struct icp_qat_uof_strtable *str_table)
+{
+	struct icp_qat_uof_chunkhdr *chunk_hdr;
+
+	chunk_hdr = qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)
+					obj_hdr->file_buff, tab_name, NULL);
+	if (chunk_hdr) {
+		int hdr_size;
+
+		memcpy(&str_table->table_len, obj_hdr->file_buff +
+		       chunk_hdr->offset, sizeof(str_table->table_len));
+		hdr_size = (char *)&str_table->strings - (char *)str_table;
+		str_table->strings = (unsigned long)obj_hdr->file_buff +
+					chunk_hdr->offset + hdr_size;
+		return str_table;
+	}
+	return NULL;
+}
+
+static void
+qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj,
+			   struct icp_qat_uclo_init_mem_table *init_mem_tab)
+{
+	struct icp_qat_uof_chunkhdr *chunk_hdr;
+
+	chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
+					ICP_QAT_UOF_IMEM, NULL);
+	if (chunk_hdr) {
+		memmove(&init_mem_tab->entry_num, encap_uof_obj->beg_uof +
+			chunk_hdr->offset, sizeof(unsigned int));
+		init_mem_tab->init_mem = (struct icp_qat_uof_initmem *)
+		(encap_uof_obj->beg_uof + chunk_hdr->offset +
+		sizeof(unsigned int));
+	}
+}
+
+static int qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle)
+{
+	unsigned int maj_ver, prod_type = obj_handle->prod_type;
+
+	if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->cpu_type)) {
+		pr_err("QAT: UOF type 0x%x not match with cur platform 0x%x\n",
+		       obj_handle->encap_uof_obj.obj_hdr->cpu_type, prod_type);
+		return -EINVAL;
+	}
+	maj_ver = obj_handle->prod_rev & 0xff;
+	if ((obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver) ||
+	    (obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver)) {
+		pr_err("QAT: UOF majVer 0x%x out of range\n", maj_ver);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle,
+			     unsigned char ae, unsigned char ctx_mask,
+			     enum icp_qat_uof_regtype reg_type,
+			     unsigned short reg_addr, unsigned int value)
+{
+	switch (reg_type) {
+	case ICP_GPA_ABS:
+	case ICP_GPB_ABS:
+		ctx_mask = 0;
+	case ICP_GPA_REL:
+	case ICP_GPB_REL:
+		return qat_hal_init_gpr(handle, ae, ctx_mask, reg_type,
+					reg_addr, value);
+	case ICP_SR_ABS:
+	case ICP_DR_ABS:
+	case ICP_SR_RD_ABS:
+	case ICP_DR_RD_ABS:
+		ctx_mask = 0;
+	case ICP_SR_REL:
+	case ICP_DR_REL:
+	case ICP_SR_RD_REL:
+	case ICP_DR_RD_REL:
+		return qat_hal_init_rd_xfer(handle, ae, ctx_mask, reg_type,
+					    reg_addr, value);
+	case ICP_SR_WR_ABS:
+	case ICP_DR_WR_ABS:
+		ctx_mask = 0;
+	case ICP_SR_WR_REL:
+	case ICP_DR_WR_REL:
+		return qat_hal_init_wr_xfer(handle, ae, ctx_mask, reg_type,
+					    reg_addr, value);
+	case ICP_NEIGH_REL:
+		return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value);
+	default:
+		pr_err("QAT: UOF uses not supported reg type 0x%x\n", reg_type);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle,
+				 unsigned int ae,
+				 struct icp_qat_uclo_encapme *encap_ae)
+{
+	unsigned int i;
+	unsigned char ctx_mask;
+	struct icp_qat_uof_init_regsym *init_regsym;
+
+	if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) ==
+	    ICP_QAT_UCLO_MAX_CTX)
+		ctx_mask = 0xff;
+	else
+		ctx_mask = 0x55;
+
+	for (i = 0; i < encap_ae->init_regsym_num; i++) {
+		unsigned int exp_res;
+
+		init_regsym = &encap_ae->init_regsym[i];
+		exp_res = init_regsym->value;
+		switch (init_regsym->init_type) {
+		case ICP_QAT_UOF_INIT_REG:
+			qat_uclo_init_reg(handle, ae, ctx_mask,
+					  (enum icp_qat_uof_regtype)
+					  init_regsym->reg_type,
+					  (unsigned short)init_regsym->reg_addr,
+					  exp_res);
+			break;
+		case ICP_QAT_UOF_INIT_REG_CTX:
+			/* check if ctx is appropriate for the ctxMode */
+			if (!((1 << init_regsym->ctx) & ctx_mask)) {
+				pr_err("QAT: invalid ctx num = 0x%x\n",
+				       init_regsym->ctx);
+				return -EINVAL;
+			}
+			qat_uclo_init_reg(handle, ae,
+					  (unsigned char)
+					  (1 << init_regsym->ctx),
+					  (enum icp_qat_uof_regtype)
+					  init_regsym->reg_type,
+					  (unsigned short)init_regsym->reg_addr,
+					  exp_res);
+			break;
+		case ICP_QAT_UOF_INIT_EXPR:
+			pr_err("QAT: INIT_EXPR feature not supported\n");
+			return -EINVAL;
+		case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP:
+			pr_err("QAT: INIT_EXPR_ENDIAN_SWAP feature not supported\n");
+			return -EINVAL;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static int qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int s, ae;
+
+	if (obj_handle->global_inited)
+		return 0;
+	if (obj_handle->init_mem_tab.entry_num) {
+		if (qat_uclo_init_memory(handle)) {
+			pr_err("QAT: initialize memory failed\n");
+			return -EINVAL;
+		}
+	}
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
+			if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
+				continue;
+			if (qat_uclo_init_reg_sym(handle, ae,
+						  obj_handle->ae_data[ae].
+						  ae_slices[s].encap_image))
+				return -EINVAL;
+		}
+	}
+	obj_handle->global_inited = 1;
+	return 0;
+}
+
+static int qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle)
+{
+	unsigned char ae, nn_mode, s;
+	struct icp_qat_uof_image *uof_image;
+	struct icp_qat_uclo_aedata *ae_data;
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!test_bit(ae,
+			      (unsigned long *)&handle->hal_handle->ae_mask))
+			continue;
+		ae_data = &obj_handle->ae_data[ae];
+		for (s = 0; s < min_t(unsigned int, ae_data->slice_num,
+				      ICP_QAT_UCLO_MAX_CTX); s++) {
+			if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
+				continue;
+			uof_image = ae_data->ae_slices[s].encap_image->img_ptr;
+			if (qat_hal_set_ae_ctx_mode(handle, ae,
+						    (char)ICP_QAT_CTX_MODE
+						    (uof_image->ae_mode))) {
+				pr_err("QAT: qat_hal_set_ae_ctx_mode error\n");
+				return -EFAULT;
+			}
+			nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode);
+			if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) {
+				pr_err("QAT: qat_hal_set_ae_nn_mode error\n");
+				return -EFAULT;
+			}
+			if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0,
+						   (char)ICP_QAT_LOC_MEM0_MODE
+						   (uof_image->ae_mode))) {
+				pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n");
+				return -EFAULT;
+			}
+			if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1,
+						   (char)ICP_QAT_LOC_MEM1_MODE
+						   (uof_image->ae_mode))) {
+				pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n");
+				return -EFAULT;
+			}
+		}
+	}
+	return 0;
+}
+
+static void qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	struct icp_qat_uclo_encapme *image;
+	int a;
+
+	for (a = 0; a < obj_handle->uimage_num; a++) {
+		image = &obj_handle->ae_uimage[a];
+		image->uwords_num = image->page->beg_addr_p +
+					image->page->micro_words_num;
+	}
+}
+
+static int qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int ae;
+
+	obj_handle->uword_buf = kcalloc(UWORD_CPYBUF_SIZE, sizeof(uint64_t),
+					GFP_KERNEL);
+	if (!obj_handle->uword_buf)
+		return -ENOMEM;
+	obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff;
+	obj_handle->encap_uof_obj.obj_hdr = (struct icp_qat_uof_objhdr *)
+					     obj_handle->obj_hdr->file_buff;
+	obj_handle->uword_in_bytes = 6;
+	obj_handle->prod_type = ICP_QAT_AC_C_CPU_TYPE;
+	obj_handle->prod_rev = PID_MAJOR_REV |
+			(PID_MINOR_REV & handle->hal_handle->revision_id);
+	if (qat_uclo_check_uof_compat(obj_handle)) {
+		pr_err("QAT: UOF incompatible\n");
+		return -EINVAL;
+	}
+	obj_handle->ustore_phy_size = ICP_QAT_UCLO_MAX_USTORE;
+	if (!obj_handle->obj_hdr->file_buff ||
+	    !qat_uclo_map_str_table(obj_handle->obj_hdr, ICP_QAT_UOF_STRT,
+				    &obj_handle->str_table)) {
+		pr_err("QAT: UOF doesn't have effective images\n");
+		goto out_err;
+	}
+	obj_handle->uimage_num =
+		qat_uclo_map_uimage(obj_handle, obj_handle->ae_uimage,
+				    ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX);
+	if (!obj_handle->uimage_num)
+		goto out_err;
+	if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) {
+		pr_err("QAT: Bad object\n");
+		goto out_check_uof_aemask_err;
+	}
+	qat_uclo_init_uword_num(handle);
+	qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj,
+				   &obj_handle->init_mem_tab);
+	if (qat_uclo_set_ae_mode(handle))
+		goto out_check_uof_aemask_err;
+	return 0;
+out_check_uof_aemask_err:
+	for (ae = 0; ae < obj_handle->uimage_num; ae++)
+		kfree(obj_handle->ae_uimage[ae].page);
+out_err:
+	kfree(obj_handle->uword_buf);
+	return -EFAULT;
+}
+
+int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
+			 void *addr_ptr, int mem_size)
+{
+	struct icp_qat_uof_filehdr *filehdr;
+	struct icp_qat_uclo_objhandle *objhdl;
+
+	BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE >=
+		     (sizeof(handle->hal_handle->ae_mask) * 8));
+
+	if (!handle || !addr_ptr || mem_size < 24)
+		return -EINVAL;
+	objhdl = kzalloc(sizeof(*objhdl), GFP_KERNEL);
+	if (!objhdl)
+		return -ENOMEM;
+	objhdl->obj_buf = kmemdup(addr_ptr, mem_size, GFP_KERNEL);
+	if (!objhdl->obj_buf)
+		goto out_objbuf_err;
+	filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf;
+	if (qat_uclo_check_format(filehdr))
+		goto out_objhdr_err;
+	objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf, filehdr,
+					     ICP_QAT_UOF_OBJS);
+	if (!objhdl->obj_hdr) {
+		pr_err("QAT: object file chunk is null\n");
+		goto out_objhdr_err;
+	}
+	handle->obj_handle = objhdl;
+	if (qat_uclo_parse_uof_obj(handle))
+		goto out_overlay_obj_err;
+	return 0;
+
+out_overlay_obj_err:
+	handle->obj_handle = NULL;
+	kfree(objhdl->obj_hdr);
+out_objhdr_err:
+	kfree(objhdl->obj_buf);
+out_objbuf_err:
+	kfree(objhdl);
+	return -ENOMEM;
+}
+
+void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int a;
+
+	if (!obj_handle)
+		return;
+
+	kfree(obj_handle->uword_buf);
+	for (a = 0; a < obj_handle->uimage_num; a++)
+		kfree(obj_handle->ae_uimage[a].page);
+
+	for (a = 0; a < handle->hal_handle->ae_max_num; a++)
+		qat_uclo_free_ae_data(&obj_handle->ae_data[a]);
+
+	kfree(obj_handle->obj_hdr);
+	kfree(obj_handle->obj_buf);
+	kfree(obj_handle);
+	handle->obj_handle = NULL;
+}
+
+static void qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle,
+				 struct icp_qat_uclo_encap_page *encap_page,
+				 uint64_t *uword, unsigned int addr_p,
+				 unsigned int raddr, uint64_t fill)
+{
+	uint64_t uwrd = 0;
+	unsigned int i;
+
+	if (!encap_page) {
+		*uword = fill;
+		return;
+	}
+	for (i = 0; i < encap_page->uwblock_num; i++) {
+		if (raddr >= encap_page->uwblock[i].start_addr &&
+		    raddr <= encap_page->uwblock[i].start_addr +
+		    encap_page->uwblock[i].words_num - 1) {
+			raddr -= encap_page->uwblock[i].start_addr;
+			raddr *= obj_handle->uword_in_bytes;
+			memcpy(&uwrd, (void *)(((unsigned long)
+			       encap_page->uwblock[i].micro_words) + raddr),
+			       obj_handle->uword_in_bytes);
+			uwrd = uwrd & 0xbffffffffffull;
+		}
+	}
+	*uword = uwrd;
+	if (*uword == INVLD_UWORD)
+		*uword = fill;
+}
+
+static void qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle,
+					struct icp_qat_uclo_encap_page
+					*encap_page, unsigned int ae)
+{
+	unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen;
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	uint64_t fill_pat;
+
+	/* load the page starting at appropriate ustore address */
+	/* get fill-pattern from an image -- they are all the same */
+	memcpy(&fill_pat, obj_handle->ae_uimage[0].img_ptr->fill_pattern,
+	       sizeof(uint64_t));
+	uw_physical_addr = encap_page->beg_addr_p;
+	uw_relative_addr = 0;
+	words_num = encap_page->micro_words_num;
+	while (words_num) {
+		if (words_num < UWORD_CPYBUF_SIZE)
+			cpylen = words_num;
+		else
+			cpylen = UWORD_CPYBUF_SIZE;
+
+		/* load the buffer */
+		for (i = 0; i < cpylen; i++)
+			qat_uclo_fill_uwords(obj_handle, encap_page,
+					     &obj_handle->uword_buf[i],
+					     uw_physical_addr + i,
+					     uw_relative_addr + i, fill_pat);
+
+		/* copy the buffer to ustore */
+		qat_hal_wr_uwords(handle, (unsigned char)ae,
+				  uw_physical_addr, cpylen,
+				  obj_handle->uword_buf);
+
+		uw_physical_addr += cpylen;
+		uw_relative_addr += cpylen;
+		words_num -= cpylen;
+	}
+}
+
+static void qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle,
+				    struct icp_qat_uof_image *image)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int ctx_mask, s;
+	struct icp_qat_uclo_page *page;
+	unsigned char ae;
+	int ctx;
+
+	if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX)
+		ctx_mask = 0xff;
+	else
+		ctx_mask = 0x55;
+	/* load the default page and set assigned CTX PC
+	 * to the entrypoint address */
+	for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+		if (!test_bit(ae, (unsigned long *)&image->ae_assigned))
+			continue;
+		/* find the slice to which this image is assigned */
+		for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
+			if (image->ctx_assigned & obj_handle->ae_data[ae].
+			    ae_slices[s].ctx_mask_assigned)
+				break;
+		}
+		if (s >= obj_handle->ae_data[ae].slice_num)
+			continue;
+		page = obj_handle->ae_data[ae].ae_slices[s].page;
+		if (!page->encap_page->def_page)
+			continue;
+		qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae);
+
+		page = obj_handle->ae_data[ae].ae_slices[s].page;
+		for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++)
+			obj_handle->ae_data[ae].ae_slices[s].cur_page[ctx] =
+					(ctx_mask & (1 << ctx)) ? page : NULL;
+		qat_hal_set_live_ctx(handle, (unsigned char)ae,
+				     image->ctx_assigned);
+		qat_hal_set_pc(handle, (unsigned char)ae, image->ctx_assigned,
+			       image->entry_address);
+	}
+}
+
+int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle)
+{
+	struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+	unsigned int i;
+
+	if (qat_uclo_init_globals(handle))
+		return -EINVAL;
+	for (i = 0; i < obj_handle->uimage_num; i++) {
+		if (!obj_handle->ae_uimage[i].img_ptr)
+			return -EINVAL;
+		if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i]))
+			return -EINVAL;
+		qat_uclo_wr_uimage_page(handle,
+					obj_handle->ae_uimage[i].img_ptr);
+	}
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_admin.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_admin.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_admin.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_admin.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,144 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <adf_accel_devices.h>
+#include "adf_drv.h"
+#include "adf_dh895xcc_hw_data.h"
+
+#define ADF_ADMINMSG_LEN 32
+
+struct adf_admin_comms {
+	dma_addr_t phy_addr;
+	void *virt_addr;
+	void __iomem *mailbox_addr;
+	struct mutex lock;	/* protects adf_admin_comms struct */
+};
+
+int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
+			   uint32_t ae, void *in, void *out)
+{
+	struct adf_admin_comms *admin = accel_dev->admin;
+	int offset = ae * ADF_ADMINMSG_LEN * 2;
+	void __iomem *mailbox = admin->mailbox_addr;
+	int mb_offset = ae * ADF_DH895XCC_MAILBOX_STRIDE;
+	int times, received;
+
+	mutex_lock(&admin->lock);
+
+	if (ADF_CSR_RD(mailbox, mb_offset) == 1) {
+		mutex_unlock(&admin->lock);
+		return -EAGAIN;
+	}
+
+	memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
+	ADF_CSR_WR(mailbox, mb_offset, 1);
+	received = 0;
+	for (times = 0; times < 50; times++) {
+		msleep(20);
+		if (ADF_CSR_RD(mailbox, mb_offset) == 0) {
+			received = 1;
+			break;
+		}
+	}
+	if (received)
+		memcpy(out, admin->virt_addr + offset +
+		       ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
+	else
+		pr_err("QAT: Failed to send admin msg to accelerator\n");
+
+	mutex_unlock(&admin->lock);
+	return received ? 0 : -EFAULT;
+}
+
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
+{
+	struct adf_admin_comms *admin;
+	struct adf_bar *pmisc = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
+	void __iomem *csr = pmisc->virt_addr;
+	void __iomem *mailbox = csr + ADF_DH895XCC_MAILBOX_BASE_OFFSET;
+	uint64_t reg_val;
+
+	admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
+			     accel_dev->numa_node);
+	if (!admin)
+		return -ENOMEM;
+	admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+					       &admin->phy_addr, GFP_KERNEL);
+	if (!admin->virt_addr) {
+		dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
+		kfree(admin);
+		return -ENOMEM;
+	}
+	reg_val = (uint64_t)admin->phy_addr;
+	ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGUR_OFFSET, reg_val >> 32);
+	ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGLR_OFFSET, reg_val);
+	mutex_init(&admin->lock);
+	admin->mailbox_addr = mailbox;
+	accel_dev->admin = admin;
+	return 0;
+}
+
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
+{
+	struct adf_admin_comms *admin = accel_dev->admin;
+
+	if (!admin)
+		return;
+
+	if (admin->virt_addr)
+		dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+				  admin->virt_addr, admin->phy_addr);
+
+	mutex_destroy(&admin->lock);
+	kfree(admin);
+	accel_dev->admin = NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,214 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <adf_accel_devices.h>
+#include "adf_dh895xcc_hw_data.h"
+#include "adf_drv.h"
+
+/* Worker thread to service arbiter mappings based on dev SKUs */
+static const uint32_t thrd_to_arb_map_sku4[] = {
+	0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
+	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+static const uint32_t thrd_to_arb_map_sku6[] = {
+	0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
+	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
+	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222
+};
+
+static struct adf_hw_device_class dh895xcc_class = {
+	.name = ADF_DH895XCC_DEVICE_NAME,
+	.type = DEV_DH895XCC,
+	.instances = 0
+};
+
+static uint32_t get_accel_mask(uint32_t fuse)
+{
+	return (~fuse) >> ADF_DH895XCC_ACCELERATORS_REG_OFFSET &
+			  ADF_DH895XCC_ACCELERATORS_MASK;
+}
+
+static uint32_t get_ae_mask(uint32_t fuse)
+{
+	return (~fuse) & ADF_DH895XCC_ACCELENGINES_MASK;
+}
+
+static uint32_t get_num_accels(struct adf_hw_device_data *self)
+{
+	uint32_t i, ctr = 0;
+
+	if (!self || !self->accel_mask)
+		return 0;
+
+	for (i = 0; i < ADF_DH895XCC_MAX_ACCELERATORS; i++) {
+		if (self->accel_mask & (1 << i))
+			ctr++;
+	}
+	return ctr;
+}
+
+static uint32_t get_num_aes(struct adf_hw_device_data *self)
+{
+	uint32_t i, ctr = 0;
+
+	if (!self || !self->ae_mask)
+		return 0;
+
+	for (i = 0; i < ADF_DH895XCC_MAX_ACCELENGINES; i++) {
+		if (self->ae_mask & (1 << i))
+			ctr++;
+	}
+	return ctr;
+}
+
+static uint32_t get_misc_bar_id(struct adf_hw_device_data *self)
+{
+	return ADF_DH895XCC_PMISC_BAR;
+}
+
+static uint32_t get_etr_bar_id(struct adf_hw_device_data *self)
+{
+	return ADF_DH895XCC_ETR_BAR;
+}
+
+static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
+{
+	int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK)
+	    >> ADF_DH895XCC_FUSECTL_SKU_SHIFT;
+
+	switch (sku) {
+	case ADF_DH895XCC_FUSECTL_SKU_1:
+		return DEV_SKU_1;
+	case ADF_DH895XCC_FUSECTL_SKU_2:
+		return DEV_SKU_2;
+	case ADF_DH895XCC_FUSECTL_SKU_3:
+		return DEV_SKU_3;
+	case ADF_DH895XCC_FUSECTL_SKU_4:
+		return DEV_SKU_4;
+	default:
+		return DEV_SKU_UNKNOWN;
+	}
+	return DEV_SKU_UNKNOWN;
+}
+
+void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
+			     uint32_t const **arb_map_config)
+{
+	switch (accel_dev->accel_pci_dev.sku) {
+	case DEV_SKU_1:
+		*arb_map_config = thrd_to_arb_map_sku4;
+		break;
+
+	case DEV_SKU_2:
+	case DEV_SKU_4:
+		*arb_map_config = thrd_to_arb_map_sku6;
+		break;
+	default:
+		pr_err("QAT: The configuration doesn't match any SKU");
+		*arb_map_config = NULL;
+	}
+}
+
+static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
+{
+	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+	struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
+	void __iomem *csr = misc_bar->virt_addr;
+	unsigned int val, i;
+
+	/* Enable Accel Engine error detection & correction */
+	for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
+		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_CTX_ENABLES(i));
+		val |= ADF_DH895XCC_ENABLE_AE_ECC_ERR;
+		ADF_CSR_WR(csr, ADF_DH895XCC_AE_CTX_ENABLES(i), val);
+		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_MISC_CONTROL(i));
+		val |= ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR;
+		ADF_CSR_WR(csr, ADF_DH895XCC_AE_MISC_CONTROL(i), val);
+	}
+
+	/* Enable shared memory error detection & correction */
+	for (i = 0; i < hw_device->get_num_accels(hw_device); i++) {
+		val = ADF_CSR_RD(csr, ADF_DH895XCC_UERRSSMSH(i));
+		val |= ADF_DH895XCC_ERRSSMSH_EN;
+		ADF_CSR_WR(csr, ADF_DH895XCC_UERRSSMSH(i), val);
+		val = ADF_CSR_RD(csr, ADF_DH895XCC_CERRSSMSH(i));
+		val |= ADF_DH895XCC_ERRSSMSH_EN;
+		ADF_CSR_WR(csr, ADF_DH895XCC_CERRSSMSH(i), val);
+	}
+}
+
+void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
+{
+	hw_data->dev_class = &dh895xcc_class;
+	hw_data->instance_id = dh895xcc_class.instances++;
+	hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS;
+	hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS;
+	hw_data->pci_dev_id = ADF_DH895XCC_PCI_DEVICE_ID;
+	hw_data->num_logical_accel = 1;
+	hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES;
+	hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET;
+	hw_data->tx_rings_mask = ADF_DH895XCC_TX_RINGS_MASK;
+	hw_data->alloc_irq = adf_isr_resource_alloc;
+	hw_data->free_irq = adf_isr_resource_free;
+	hw_data->enable_error_correction = adf_enable_error_correction;
+	hw_data->hw_arb_ring_enable = adf_update_ring_arb_enable;
+	hw_data->hw_arb_ring_disable = adf_update_ring_arb_enable;
+	hw_data->get_accel_mask = get_accel_mask;
+	hw_data->get_ae_mask = get_ae_mask;
+	hw_data->get_num_accels = get_num_accels;
+	hw_data->get_num_aes = get_num_aes;
+	hw_data->get_etr_bar_id = get_etr_bar_id;
+	hw_data->get_misc_bar_id = get_misc_bar_id;
+	hw_data->get_sku = get_sku;
+	hw_data->fw_name = ADF_DH895XCC_FW;
+}
+
+void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
+{
+	hw_data->dev_class->instances--;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h	2014-09-28 21:26:09.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_DH895x_HW_DATA_H_
+#define ADF_DH895x_HW_DATA_H_
+
+/* PCIe configuration space */
+#define ADF_DH895XCC_RX_RINGS_OFFSET 8
+#define ADF_DH895XCC_TX_RINGS_MASK 0xFF
+#define ADF_DH895XCC_FUSECTL_OFFSET 0x40
+#define ADF_DH895XCC_FUSECTL_SKU_MASK 0x300000
+#define ADF_DH895XCC_FUSECTL_SKU_SHIFT 20
+#define ADF_DH895XCC_FUSECTL_SKU_1 0x0
+#define ADF_DH895XCC_FUSECTL_SKU_2 0x1
+#define ADF_DH895XCC_FUSECTL_SKU_3 0x2
+#define ADF_DH895XCC_FUSECTL_SKU_4 0x3
+#define ADF_DH895XCC_MAX_ACCELERATORS 6
+#define ADF_DH895XCC_MAX_ACCELENGINES 12
+#define ADF_DH895XCC_ACCELERATORS_REG_OFFSET 13
+#define ADF_DH895XCC_ACCELERATORS_MASK 0x3F
+#define ADF_DH895XCC_ACCELENGINES_MASK 0xFFF
+#define ADF_DH895XCC_LEGFUSE_OFFSET 0x4C
+#define ADF_DH895XCC_ETR_MAX_BANKS 32
+#define ADF_DH895XCC_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28)
+#define ADF_DH895XCC_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30)
+#define ADF_DH895XCC_SMIA0_MASK 0xFFFFFFFF
+#define ADF_DH895XCC_SMIA1_MASK 0x1
+/* Error detection and correction */
+#define ADF_DH895XCC_AE_CTX_ENABLES(i) (i * 0x1000 + 0x20818)
+#define ADF_DH895XCC_AE_MISC_CONTROL(i) (i * 0x1000 + 0x20960)
+#define ADF_DH895XCC_ENABLE_AE_ECC_ERR (1 << 28)
+#define ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR (1 << 24 | 1 << 12)
+#define ADF_DH895XCC_UERRSSMSH(i) (i * 0x4000 + 0x18)
+#define ADF_DH895XCC_CERRSSMSH(i) (i * 0x4000 + 0x10)
+#define ADF_DH895XCC_ERRSSMSH_EN (1 << 3)
+
+/* Admin Messages Registers */
+#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574)
+#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578)
+#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970
+#define ADF_DH895XCC_MAILBOX_STRIDE 0x1000
+#define ADF_DH895XCC_FW "/*(DEBLOBBED)*/"
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c	2014-09-28 21:26:11.000000000 -0400
@@ -0,0 +1,449 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_transport_access_macros.h>
+#include "adf_dh895xcc_hw_data.h"
+#include "adf_drv.h"
+
+static const char adf_driver_name[] = ADF_DH895XCC_DEVICE_NAME;
+
+#define ADF_SYSTEM_DEVICE(device_id) \
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+
+static const struct pci_device_id adf_pci_tbl[] = {
+	ADF_SYSTEM_DEVICE(ADF_DH895XCC_PCI_DEVICE_ID),
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
+
+static int adf_probe(struct pci_dev *dev, const struct pci_device_id *ent);
+static void adf_remove(struct pci_dev *dev);
+
+static struct pci_driver adf_driver = {
+	.id_table = adf_pci_tbl,
+	.name = adf_driver_name,
+	.probe = adf_probe,
+	.remove = adf_remove
+};
+
+static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
+{
+	struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
+	int i;
+
+	adf_exit_admin_comms(accel_dev);
+	adf_exit_arb(accel_dev);
+	adf_cleanup_etr_data(accel_dev);
+
+	for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
+		struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+
+		if (bar->virt_addr)
+			pci_iounmap(accel_pci_dev->pci_dev, bar->virt_addr);
+	}
+
+	if (accel_dev->hw_device) {
+		switch (accel_dev->hw_device->pci_dev_id) {
+		case ADF_DH895XCC_PCI_DEVICE_ID:
+			adf_clean_hw_data_dh895xcc(accel_dev->hw_device);
+			break;
+		default:
+			break;
+		}
+		kfree(accel_dev->hw_device);
+	}
+	adf_cfg_dev_remove(accel_dev);
+	debugfs_remove(accel_dev->debugfs_dir);
+	adf_devmgr_rm_dev(accel_dev);
+	pci_release_regions(accel_pci_dev->pci_dev);
+	pci_disable_device(accel_pci_dev->pci_dev);
+	kfree(accel_dev);
+}
+
+static uint8_t adf_get_dev_node_id(struct pci_dev *pdev)
+{
+	unsigned int bus_per_cpu = 0;
+	struct cpuinfo_x86 *c = &cpu_data(num_online_cpus() - 1);
+
+	if (!c->phys_proc_id)
+		return 0;
+
+	bus_per_cpu = 256 / (c->phys_proc_id + 1);
+
+	if (bus_per_cpu != 0)
+		return pdev->bus->number / bus_per_cpu;
+	return 0;
+}
+
+static int qat_dev_start(struct adf_accel_dev *accel_dev)
+{
+	int cpus = num_online_cpus();
+	int banks = GET_MAX_BANKS(accel_dev);
+	int instances = min(cpus, banks);
+	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+	int i;
+	unsigned long val;
+
+	if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
+		goto err;
+	if (adf_cfg_section_add(accel_dev, "Accelerator0"))
+		goto err;
+	for (i = 0; i < instances; i++) {
+		val = i;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY,
+			 i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, i);
+		val = 128;
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 512;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_SIZE, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 0;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 2;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_TX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 4;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 8;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 10;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_RX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = 12;
+		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
+		if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+						key, (void *)&val, ADF_DEC))
+			goto err;
+
+		val = ADF_COALESCING_DEF_TIME;
+		snprintf(key, sizeof(key), ADF_ETRMGR_COALESCE_TIMER_FORMAT, i);
+		if (adf_cfg_add_key_value_param(accel_dev, "Accelerator0",
+						key, (void *)&val, ADF_DEC))
+			goto err;
+	}
+
+	val = i;
+	if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+					ADF_NUM_CY, (void *)&val, ADF_DEC))
+		goto err;
+
+	set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+	return adf_dev_start(accel_dev);
+err:
+	dev_err(&GET_DEV(accel_dev), "Failed to start QAT accel dev\n");
+	return -EINVAL;
+}
+
+static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct adf_accel_dev *accel_dev;
+	struct adf_accel_pci *accel_pci_dev;
+	struct adf_hw_device_data *hw_data;
+	void __iomem *pmisc_bar_addr = NULL;
+	char name[ADF_DEVICE_NAME_LENGTH];
+	unsigned int i, bar_nr;
+	uint8_t node;
+	int ret;
+
+	switch (ent->device) {
+	case ADF_DH895XCC_PCI_DEVICE_ID:
+		break;
+	default:
+		dev_err(&pdev->dev, "Invalid device 0x%x.\n", ent->device);
+		return -ENODEV;
+	}
+
+	node = adf_get_dev_node_id(pdev);
+	accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL, node);
+	if (!accel_dev)
+		return -ENOMEM;
+
+	accel_dev->numa_node = node;
+	INIT_LIST_HEAD(&accel_dev->crypto_list);
+
+	/* Add accel device to accel table.
+	 * This should be called before adf_cleanup_accel is called */
+	if (adf_devmgr_add_dev(accel_dev)) {
+		dev_err(&pdev->dev, "Failed to add new accelerator device.\n");
+		kfree(accel_dev);
+		return -EFAULT;
+	}
+
+	accel_dev->owner = THIS_MODULE;
+	/* Allocate and configure device configuration structure */
+	hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL, node);
+	if (!hw_data) {
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	accel_dev->hw_device = hw_data;
+	switch (ent->device) {
+	case ADF_DH895XCC_PCI_DEVICE_ID:
+		adf_init_hw_data_dh895xcc(accel_dev->hw_device);
+		break;
+	default:
+		return -ENODEV;
+	}
+	accel_pci_dev = &accel_dev->accel_pci_dev;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &accel_pci_dev->revid);
+	pci_read_config_dword(pdev, ADF_DH895XCC_FUSECTL_OFFSET,
+			      &hw_data->fuses);
+
+	/* Get Accelerators and Accelerators Engines masks */
+	hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses);
+	hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses);
+	accel_pci_dev->sku = hw_data->get_sku(hw_data);
+	accel_pci_dev->pci_dev = pdev;
+	/* If the device has no acceleration engines then ignore it. */
+	if (!hw_data->accel_mask || !hw_data->ae_mask ||
+	    ((~hw_data->ae_mask) & 0x01)) {
+		dev_err(&pdev->dev, "No acceleration units found");
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	/* Create dev top level debugfs entry */
+	snprintf(name, sizeof(name), "%s%s_dev%d", ADF_DEVICE_NAME_PREFIX,
+		 hw_data->dev_class->name, hw_data->instance_id);
+	accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
+	if (!accel_dev->debugfs_dir) {
+		dev_err(&pdev->dev, "Could not create debugfs dir\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	/* Create device configuration table */
+	ret = adf_cfg_dev_add(accel_dev);
+	if (ret)
+		goto out_err;
+
+	/* enable PCI device */
+	if (pci_enable_device(pdev)) {
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	/* set dma identifier */
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
+			dev_err(&pdev->dev, "No usable DMA configuration\n");
+			ret = -EFAULT;
+			goto out_err;
+		} else {
+			pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		}
+
+	} else {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	}
+
+	if (pci_request_regions(pdev, adf_driver_name)) {
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	/* Read accelerator capabilities mask */
+	pci_read_config_dword(pdev, ADF_DH895XCC_LEGFUSE_OFFSET,
+			      &hw_data->accel_capabilities_mask);
+
+	/* Find and map all the device's BARS */
+	for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
+		struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+
+		bar_nr = i * 2;
+		bar->base_addr = pci_resource_start(pdev, bar_nr);
+		if (!bar->base_addr)
+			break;
+		bar->size = pci_resource_len(pdev, bar_nr);
+		bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0);
+		if (!bar->virt_addr) {
+			dev_err(&pdev->dev, "Failed to map BAR %d\n", i);
+			ret = -EFAULT;
+			goto out_err;
+		}
+		if (i == ADF_DH895XCC_PMISC_BAR)
+			pmisc_bar_addr = bar->virt_addr;
+	}
+	pci_set_master(pdev);
+
+	if (adf_enable_aer(accel_dev, &adf_driver)) {
+		dev_err(&pdev->dev, "Failed to enable aer\n");
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	if (adf_init_etr_data(accel_dev)) {
+		dev_err(&pdev->dev, "Failed initialize etr\n");
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	if (adf_init_admin_comms(accel_dev)) {
+		dev_err(&pdev->dev, "Failed initialize admin comms\n");
+		ret = -EFAULT;
+		goto out_err;
+	}
+
+	if (adf_init_arb(accel_dev)) {
+		dev_err(&pdev->dev, "Failed initialize hw arbiter\n");
+		ret = -EFAULT;
+		goto out_err;
+	}
+	if (pci_save_state(pdev)) {
+		dev_err(&pdev->dev, "Failed to save pci state\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	/* Enable bundle and misc interrupts */
+	ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCC_SMIAPF0_MASK_OFFSET,
+		   ADF_DH895XCC_SMIA0_MASK);
+	ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCC_SMIAPF1_MASK_OFFSET,
+		   ADF_DH895XCC_SMIA1_MASK);
+
+	ret = qat_dev_start(accel_dev);
+	if (ret) {
+		adf_dev_stop(accel_dev);
+		goto out_err;
+	}
+
+	return 0;
+out_err:
+	adf_cleanup_accel(accel_dev);
+	return ret;
+}
+
+static void __exit adf_remove(struct pci_dev *pdev)
+{
+	struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+	if (!accel_dev) {
+		pr_err("QAT: Driver removal failed\n");
+		return;
+	}
+	if (adf_dev_stop(accel_dev))
+		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
+	adf_disable_aer(accel_dev);
+	adf_cleanup_accel(accel_dev);
+}
+
+static int __init adfdrv_init(void)
+{
+	request_module("intel_qat");
+	if (qat_admin_register())
+		return -EFAULT;
+
+	if (pci_register_driver(&adf_driver)) {
+		pr_err("QAT: Driver initialization failed\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void __exit adfdrv_release(void)
+{
+	pci_unregister_driver(&adf_driver);
+	qat_admin_unregister();
+}
+
+module_init(adfdrv_init);
+module_exit(adfdrv_release);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+/*(DEBLOBBED)*/
+MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.h linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.h
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#ifndef ADF_DH895x_DRV_H_
+#define ADF_DH895x_DRV_H_
+#include <adf_accel_devices.h>
+#include <adf_transport.h>
+
+void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
+void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
+int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev);
+void adf_isr_resource_free(struct adf_accel_dev *accel_dev);
+void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring);
+void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
+			     uint32_t const **arb_map_config);
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
+int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
+			   uint32_t ae, void *in, void *out);
+int qat_admin_register(void);
+int qat_admin_unregister(void);
+int adf_init_arb(struct adf_accel_dev *accel_dev);
+void adf_exit_arb(struct adf_accel_dev *accel_dev);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,159 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <adf_accel_devices.h>
+#include <adf_transport_internal.h>
+#include "adf_drv.h"
+
+#define ADF_ARB_NUM 4
+#define ADF_ARB_REQ_RING_NUM 8
+#define ADF_ARB_REG_SIZE 0x4
+#define ADF_ARB_WTR_SIZE 0x20
+#define ADF_ARB_OFFSET 0x30000
+#define ADF_ARB_REG_SLOT 0x1000
+#define ADF_ARB_WTR_OFFSET 0x010
+#define ADF_ARB_RO_EN_OFFSET 0x090
+#define ADF_ARB_WQCFG_OFFSET 0x100
+#define ADF_ARB_WRK_2_SER_MAP_OFFSET 0x180
+#define ADF_ARB_WRK_2_SER_MAP 10
+#define ADF_ARB_RINGSRVARBEN_OFFSET 0x19C
+
+#define WRITE_CSR_ARB_RINGSRVARBEN(csr_addr, index, value) \
+	ADF_CSR_WR(csr_addr, ADF_ARB_RINGSRVARBEN_OFFSET + \
+	(ADF_ARB_REG_SLOT * index), value)
+
+#define WRITE_CSR_ARB_RESPORDERING(csr_addr, index, value) \
+	ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+	ADF_ARB_RO_EN_OFFSET) + (ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WEIGHT(csr_addr, arb, index, value) \
+	ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+	ADF_ARB_WTR_OFFSET) + (ADF_ARB_WTR_SIZE * arb) + \
+	(ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_SARCONFIG(csr_addr, index, value) \
+	ADF_CSR_WR(csr_addr, ADF_ARB_OFFSET + \
+	(ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WRK_2_SER_MAP(csr_addr, index, value) \
+	ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+	ADF_ARB_WRK_2_SER_MAP_OFFSET) + \
+	(ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WQCFG(csr_addr, index, value) \
+	ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+	ADF_ARB_WQCFG_OFFSET) + (ADF_ARB_REG_SIZE * index), value)
+
+int adf_init_arb(struct adf_accel_dev *accel_dev)
+{
+	void __iomem *csr = accel_dev->transport->banks[0].csr_addr;
+	uint32_t arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1;
+	uint32_t arb, i;
+	const uint32_t *thd_2_arb_cfg;
+
+	/* Service arb configured for 32 bytes responses and
+	 * ring flow control check enabled. */
+	for (arb = 0; arb < ADF_ARB_NUM; arb++)
+		WRITE_CSR_ARB_SARCONFIG(csr, arb, arb_cfg);
+
+	/* Setup service weighting */
+	for (arb = 0; arb < ADF_ARB_NUM; arb++)
+		for (i = 0; i < ADF_ARB_REQ_RING_NUM; i++)
+			WRITE_CSR_ARB_WEIGHT(csr, arb, i, 0xFFFFFFFF);
+
+	/* Setup ring response ordering */
+	for (i = 0; i < ADF_ARB_REQ_RING_NUM; i++)
+		WRITE_CSR_ARB_RESPORDERING(csr, i, 0xFFFFFFFF);
+
+	/* Setup worker queue registers */
+	for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+		WRITE_CSR_ARB_WQCFG(csr, i, i);
+
+	/* Map worker threads to service arbiters */
+	adf_get_arbiter_mapping(accel_dev, &thd_2_arb_cfg);
+
+	if (!thd_2_arb_cfg)
+		return -EFAULT;
+
+	for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+		WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, *(thd_2_arb_cfg + i));
+
+	return 0;
+}
+
+void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring)
+{
+	WRITE_CSR_ARB_RINGSRVARBEN(ring->bank->csr_addr,
+				   ring->bank->bank_number,
+				   ring->bank->ring_mask & 0xFF);
+}
+
+void adf_exit_arb(struct adf_accel_dev *accel_dev)
+{
+	void __iomem *csr;
+	unsigned int i;
+
+	if (!accel_dev->transport)
+		return;
+
+	csr = accel_dev->transport->banks[0].csr_addr;
+
+	/* Reset arbiter configuration */
+	for (i = 0; i < ADF_ARB_NUM; i++)
+		WRITE_CSR_ARB_SARCONFIG(csr, i, 0);
+
+	/* Shutdown work queue */
+	for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+		WRITE_CSR_ARB_WQCFG(csr, i, 0);
+
+	/* Unmap worker threads to service arbiters */
+	for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+		WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, 0);
+
+	/* Disable arbitration on all rings */
+	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++)
+		WRITE_CSR_ARB_RINGSRVARBEN(csr, i, 0);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_isr.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_isr.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/adf_isr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_isr.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,266 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_cfg_strings.h>
+#include <adf_cfg_common.h>
+#include <adf_transport_access_macros.h>
+#include <adf_transport_internal.h>
+#include "adf_drv.h"
+
+static int adf_enable_msix(struct adf_accel_dev *accel_dev)
+{
+	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint32_t msix_num_entries = hw_data->num_banks + 1;
+	int i;
+
+	for (i = 0; i < msix_num_entries; i++)
+		pci_dev_info->msix_entries.entries[i].entry = i;
+
+	if (pci_enable_msix(pci_dev_info->pci_dev,
+			    pci_dev_info->msix_entries.entries,
+			    msix_num_entries)) {
+		pr_err("QAT: Failed to enable MSIX IRQ\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void adf_disable_msix(struct adf_accel_pci *pci_dev_info)
+{
+	pci_disable_msix(pci_dev_info->pci_dev);
+}
+
+static irqreturn_t adf_msix_isr_bundle(int irq, void *bank_ptr)
+{
+	struct adf_etr_bank_data *bank = bank_ptr;
+
+	WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number, 0);
+	tasklet_hi_schedule(&bank->resp_hanlder);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
+{
+	struct adf_accel_dev *accel_dev = dev_ptr;
+
+	pr_info("QAT: qat_dev%d spurious AE interrupt\n", accel_dev->accel_id);
+	return IRQ_HANDLED;
+}
+
+static int adf_request_irqs(struct adf_accel_dev *accel_dev)
+{
+	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
+	struct adf_etr_data *etr_data = accel_dev->transport;
+	int ret, i;
+	char *name;
+
+	/* Request msix irq for all banks */
+	for (i = 0; i < hw_data->num_banks; i++) {
+		struct adf_etr_bank_data *bank = &etr_data->banks[i];
+		unsigned int cpu, cpus = num_online_cpus();
+
+		name = *(pci_dev_info->msix_entries.names + i);
+		snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
+			 "qat%d-bundle%d", accel_dev->accel_id, i);
+		ret = request_irq(msixe[i].vector,
+				  adf_msix_isr_bundle, 0, name, bank);
+		if (ret) {
+			pr_err("QAT: failed to enable irq %d for %s\n",
+			       msixe[i].vector, name);
+			return ret;
+		}
+
+		cpu = ((accel_dev->accel_id * hw_data->num_banks) + i) % cpus;
+		irq_set_affinity_hint(msixe[i].vector, get_cpu_mask(cpu));
+	}
+
+	/* Request msix irq for AE */
+	name = *(pci_dev_info->msix_entries.names + i);
+	snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
+		 "qat%d-ae-cluster", accel_dev->accel_id);
+	ret = request_irq(msixe[i].vector, adf_msix_isr_ae, 0, name, accel_dev);
+	if (ret) {
+		pr_err("QAT: failed to enable irq %d, for %s\n",
+		       msixe[i].vector, name);
+		return ret;
+	}
+	return ret;
+}
+
+static void adf_free_irqs(struct adf_accel_dev *accel_dev)
+{
+	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
+	struct adf_etr_data *etr_data = accel_dev->transport;
+	int i;
+
+	for (i = 0; i < hw_data->num_banks; i++) {
+		irq_set_affinity_hint(msixe[i].vector, NULL);
+		free_irq(msixe[i].vector, &etr_data->banks[i]);
+	}
+	irq_set_affinity_hint(msixe[i].vector, NULL);
+	free_irq(msixe[i].vector, accel_dev);
+}
+
+static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
+{
+	int i;
+	char **names;
+	struct msix_entry *entries;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint32_t msix_num_entries = hw_data->num_banks + 1;
+
+	entries = kzalloc_node(msix_num_entries * sizeof(*entries),
+			       GFP_KERNEL, accel_dev->numa_node);
+	if (!entries)
+		return -ENOMEM;
+
+	names = kcalloc(msix_num_entries, sizeof(char *), GFP_KERNEL);
+	if (!names) {
+		kfree(entries);
+		return -ENOMEM;
+	}
+	for (i = 0; i < msix_num_entries; i++) {
+		*(names + i) = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
+		if (!(*(names + i)))
+			goto err;
+	}
+	accel_dev->accel_pci_dev.msix_entries.entries = entries;
+	accel_dev->accel_pci_dev.msix_entries.names = names;
+	return 0;
+err:
+	for (i = 0; i < msix_num_entries; i++) {
+		if (*(names + i))
+			kfree(*(names + i));
+	}
+	kfree(entries);
+	kfree(names);
+	return -ENOMEM;
+}
+
+static void adf_isr_free_msix_entry_table(struct adf_accel_dev *accel_dev)
+{
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	uint32_t msix_num_entries = hw_data->num_banks + 1;
+	char **names = accel_dev->accel_pci_dev.msix_entries.names;
+	int i;
+
+	kfree(accel_dev->accel_pci_dev.msix_entries.entries);
+	for (i = 0; i < msix_num_entries; i++) {
+		if (*(names + i))
+			kfree(*(names + i));
+	}
+	kfree(names);
+}
+
+static int adf_setup_bh(struct adf_accel_dev *accel_dev)
+{
+	struct adf_etr_data *priv_data = accel_dev->transport;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	int i;
+
+	for (i = 0; i < hw_data->num_banks; i++)
+		tasklet_init(&priv_data->banks[i].resp_hanlder,
+			     adf_response_handler,
+			     (unsigned long)&priv_data->banks[i]);
+	return 0;
+}
+
+static void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
+{
+	struct adf_etr_data *priv_data = accel_dev->transport;
+	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	int i;
+
+	for (i = 0; i < hw_data->num_banks; i++) {
+		tasklet_disable(&priv_data->banks[i].resp_hanlder);
+		tasklet_kill(&priv_data->banks[i].resp_hanlder);
+	}
+}
+
+void adf_isr_resource_free(struct adf_accel_dev *accel_dev)
+{
+	adf_free_irqs(accel_dev);
+	adf_cleanup_bh(accel_dev);
+	adf_disable_msix(&accel_dev->accel_pci_dev);
+	adf_isr_free_msix_entry_table(accel_dev);
+}
+
+int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
+{
+	int ret;
+
+	ret = adf_isr_alloc_msix_entry_table(accel_dev);
+	if (ret)
+		return ret;
+	if (adf_enable_msix(accel_dev))
+		goto err_out;
+
+	if (adf_setup_bh(accel_dev))
+		goto err_out;
+
+	if (adf_request_irqs(accel_dev))
+		goto err_out;
+
+	return 0;
+err_out:
+	adf_isr_resource_free(accel_dev);
+	return -EFAULT;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,8 @@
+ccflags-y := -I$(src)/../qat_common
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc.o
+qat_dh895xcc-objs := adf_drv.o \
+		adf_isr.o \
+		adf_dh895xcc_hw_data.o \
+		adf_hw_arbiter.o \
+		qat_admin.o \
+		adf_admin.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/qat_admin.c linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/qat_admin.c
--- linux-libre-3.16-gnu/drivers/crypto/qat/qat_dh895xcc/qat_admin.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qat/qat_dh895xcc/qat_admin.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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.
+*/
+#include <icp_qat_fw_init_admin.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include "adf_drv.h"
+
+static struct service_hndl qat_admin;
+
+static int qat_send_admin_cmd(struct adf_accel_dev *accel_dev, int cmd)
+{
+	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+	struct icp_qat_fw_init_admin_req req;
+	struct icp_qat_fw_init_admin_resp resp;
+	int i;
+
+	memset(&req, 0, sizeof(struct icp_qat_fw_init_admin_req));
+	req.init_admin_cmd_id = cmd;
+	for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
+		memset(&resp, 0, sizeof(struct icp_qat_fw_init_admin_resp));
+		if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
+		    resp.init_resp_hdr.status)
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int qat_admin_start(struct adf_accel_dev *accel_dev)
+{
+	return qat_send_admin_cmd(accel_dev, ICP_QAT_FW_INIT_ME);
+}
+
+static int qat_admin_event_handler(struct adf_accel_dev *accel_dev,
+				   enum adf_event event)
+{
+	int ret;
+
+	switch (event) {
+	case ADF_EVENT_START:
+		ret = qat_admin_start(accel_dev);
+		break;
+	case ADF_EVENT_STOP:
+	case ADF_EVENT_INIT:
+	case ADF_EVENT_SHUTDOWN:
+	default:
+		ret = 0;
+	}
+	return ret;
+}
+
+int qat_admin_register(void)
+{
+	memset(&qat_admin, 0, sizeof(struct service_hndl));
+	qat_admin.event_hld = qat_admin_event_handler;
+	qat_admin.name = "qat_admin";
+	qat_admin.admin = 1;
+	return adf_service_register(&qat_admin);
+}
+
+int qat_admin_unregister(void)
+{
+	return adf_service_unregister(&qat_admin);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/ablkcipher.c linux-libre-3.17-rc7-gnu/drivers/crypto/qce/ablkcipher.c
--- linux-libre-3.16-gnu/drivers/crypto/qce/ablkcipher.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/ablkcipher.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2010-2014, 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/device.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+#include "cipher.h"
+
+static LIST_HEAD(ablkcipher_algs);
+
+static void qce_ablkcipher_done(void *data)
+{
+	struct crypto_async_request *async_req = data;
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	enum dma_data_direction dir_src, dir_dst;
+	u32 status;
+	int error;
+	bool diff_dst;
+
+	diff_dst = (req->src != req->dst) ? true : false;
+	dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
+	dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
+
+	error = qce_dma_terminate_all(&qce->dma);
+	if (error)
+		dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n",
+			error);
+
+	if (diff_dst)
+		qce_unmapsg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src,
+			    rctx->dst_chained);
+	qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+		    rctx->dst_chained);
+
+	sg_free_table(&rctx->dst_tbl);
+
+	error = qce_check_status(qce, &status);
+	if (error < 0)
+		dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status);
+
+	qce->async_req_done(tmpl->qce, error);
+}
+
+static int
+qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	enum dma_data_direction dir_src, dir_dst;
+	struct scatterlist *sg;
+	bool diff_dst;
+	gfp_t gfp;
+	int ret;
+
+	rctx->iv = req->info;
+	rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+	rctx->cryptlen = req->nbytes;
+
+	diff_dst = (req->src != req->dst) ? true : false;
+	dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
+	dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
+
+	rctx->src_nents = qce_countsg(req->src, req->nbytes,
+				      &rctx->src_chained);
+	if (diff_dst) {
+		rctx->dst_nents = qce_countsg(req->dst, req->nbytes,
+					      &rctx->dst_chained);
+	} else {
+		rctx->dst_nents = rctx->src_nents;
+		rctx->dst_chained = rctx->src_chained;
+	}
+
+	rctx->dst_nents += 1;
+
+	gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+						GFP_KERNEL : GFP_ATOMIC;
+
+	ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
+	if (ret)
+		return ret;
+
+	sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
+
+	sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
+	if (IS_ERR(sg)) {
+		ret = PTR_ERR(sg);
+		goto error_free;
+	}
+
+	sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
+	if (IS_ERR(sg)) {
+		ret = PTR_ERR(sg);
+		goto error_free;
+	}
+
+	sg_mark_end(sg);
+	rctx->dst_sg = rctx->dst_tbl.sgl;
+
+	ret = qce_mapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+			rctx->dst_chained);
+	if (ret < 0)
+		goto error_free;
+
+	if (diff_dst) {
+		ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, dir_src,
+				rctx->src_chained);
+		if (ret < 0)
+			goto error_unmap_dst;
+		rctx->src_sg = req->src;
+	} else {
+		rctx->src_sg = rctx->dst_sg;
+	}
+
+	ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
+			       rctx->dst_sg, rctx->dst_nents,
+			       qce_ablkcipher_done, async_req);
+	if (ret)
+		goto error_unmap_src;
+
+	qce_dma_issue_pending(&qce->dma);
+
+	ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0);
+	if (ret)
+		goto error_terminate;
+
+	return 0;
+
+error_terminate:
+	qce_dma_terminate_all(&qce->dma);
+error_unmap_src:
+	if (diff_dst)
+		qce_unmapsg(qce->dev, req->src, rctx->src_nents, dir_src,
+			    rctx->src_chained);
+error_unmap_dst:
+	qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+		    rctx->dst_chained);
+error_free:
+	sg_free_table(&rctx->dst_tbl);
+	return ret;
+}
+
+static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
+				 unsigned int keylen)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk);
+	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	unsigned long flags = to_cipher_tmpl(tfm)->alg_flags;
+	int ret;
+
+	if (!key || !keylen)
+		return -EINVAL;
+
+	if (IS_AES(flags)) {
+		switch (keylen) {
+		case AES_KEYSIZE_128:
+		case AES_KEYSIZE_256:
+			break;
+		default:
+			goto fallback;
+		}
+	} else if (IS_DES(flags)) {
+		u32 tmp[DES_EXPKEY_WORDS];
+
+		ret = des_ekey(tmp, key);
+		if (!ret && crypto_ablkcipher_get_flags(ablk) &
+		    CRYPTO_TFM_REQ_WEAK_KEY)
+			goto weakkey;
+	}
+
+	ctx->enc_keylen = keylen;
+	memcpy(ctx->enc_key, key, keylen);
+	return 0;
+fallback:
+	ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen);
+	if (!ret)
+		ctx->enc_keylen = keylen;
+	return ret;
+weakkey:
+	crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY);
+	return -EINVAL;
+}
+
+static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt)
+{
+	struct crypto_tfm *tfm =
+			crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
+	int ret;
+
+	rctx->flags = tmpl->alg_flags;
+	rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
+
+	if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
+	    ctx->enc_keylen != AES_KEYSIZE_256) {
+		ablkcipher_request_set_tfm(req, ctx->fallback);
+		ret = encrypt ? crypto_ablkcipher_encrypt(req) :
+				crypto_ablkcipher_decrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+		return ret;
+	}
+
+	return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+	return qce_ablkcipher_crypt(req, 1);
+}
+
+static int qce_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+	return qce_ablkcipher_crypt(req, 0);
+}
+
+static int qce_ablkcipher_init(struct crypto_tfm *tfm)
+{
+	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	memset(ctx, 0, sizeof(*ctx));
+	tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx);
+
+	ctx->fallback = crypto_alloc_ablkcipher(crypto_tfm_alg_name(tfm),
+						CRYPTO_ALG_TYPE_ABLKCIPHER,
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(ctx->fallback))
+		return PTR_ERR(ctx->fallback);
+
+	return 0;
+}
+
+static void qce_ablkcipher_exit(struct crypto_tfm *tfm)
+{
+	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_ablkcipher(ctx->fallback);
+}
+
+struct qce_ablkcipher_def {
+	unsigned long flags;
+	const char *name;
+	const char *drv_name;
+	unsigned int blocksize;
+	unsigned int ivsize;
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+};
+
+static const struct qce_ablkcipher_def ablkcipher_def[] = {
+	{
+		.flags		= QCE_ALG_AES | QCE_MODE_ECB,
+		.name		= "ecb(aes)",
+		.drv_name	= "ecb-aes-qce",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_AES | QCE_MODE_CBC,
+		.name		= "cbc(aes)",
+		.drv_name	= "cbc-aes-qce",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_AES | QCE_MODE_CTR,
+		.name		= "ctr(aes)",
+		.drv_name	= "ctr-aes-qce",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_AES | QCE_MODE_XTS,
+		.name		= "xts(aes)",
+		.drv_name	= "xts-aes-qce",
+		.blocksize	= AES_BLOCK_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_DES | QCE_MODE_ECB,
+		.name		= "ecb(des)",
+		.drv_name	= "ecb-des-qce",
+		.blocksize	= DES_BLOCK_SIZE,
+		.ivsize		= 0,
+		.min_keysize	= DES_KEY_SIZE,
+		.max_keysize	= DES_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_DES | QCE_MODE_CBC,
+		.name		= "cbc(des)",
+		.drv_name	= "cbc-des-qce",
+		.blocksize	= DES_BLOCK_SIZE,
+		.ivsize		= DES_BLOCK_SIZE,
+		.min_keysize	= DES_KEY_SIZE,
+		.max_keysize	= DES_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_3DES | QCE_MODE_ECB,
+		.name		= "ecb(des3_ede)",
+		.drv_name	= "ecb-3des-qce",
+		.blocksize	= DES3_EDE_BLOCK_SIZE,
+		.ivsize		= 0,
+		.min_keysize	= DES3_EDE_KEY_SIZE,
+		.max_keysize	= DES3_EDE_KEY_SIZE,
+	},
+	{
+		.flags		= QCE_ALG_3DES | QCE_MODE_CBC,
+		.name		= "cbc(des3_ede)",
+		.drv_name	= "cbc-3des-qce",
+		.blocksize	= DES3_EDE_BLOCK_SIZE,
+		.ivsize		= DES3_EDE_BLOCK_SIZE,
+		.min_keysize	= DES3_EDE_KEY_SIZE,
+		.max_keysize	= DES3_EDE_KEY_SIZE,
+	},
+};
+
+static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def,
+				       struct qce_device *qce)
+{
+	struct qce_alg_template *tmpl;
+	struct crypto_alg *alg;
+	int ret;
+
+	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+	if (!tmpl)
+		return -ENOMEM;
+
+	alg = &tmpl->alg.crypto;
+
+	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->drv_name);
+
+	alg->cra_blocksize = def->blocksize;
+	alg->cra_ablkcipher.ivsize = def->ivsize;
+	alg->cra_ablkcipher.min_keysize = def->min_keysize;
+	alg->cra_ablkcipher.max_keysize = def->max_keysize;
+	alg->cra_ablkcipher.setkey = qce_ablkcipher_setkey;
+	alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt;
+	alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt;
+
+	alg->cra_priority = 300;
+	alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
+			 CRYPTO_ALG_NEED_FALLBACK;
+	alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
+	alg->cra_alignmask = 0;
+	alg->cra_type = &crypto_ablkcipher_type;
+	alg->cra_module = THIS_MODULE;
+	alg->cra_init = qce_ablkcipher_init;
+	alg->cra_exit = qce_ablkcipher_exit;
+	INIT_LIST_HEAD(&alg->cra_list);
+
+	INIT_LIST_HEAD(&tmpl->entry);
+	tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER;
+	tmpl->alg_flags = def->flags;
+	tmpl->qce = qce;
+
+	ret = crypto_register_alg(alg);
+	if (ret) {
+		kfree(tmpl);
+		dev_err(qce->dev, "%s registration failed\n", alg->cra_name);
+		return ret;
+	}
+
+	list_add_tail(&tmpl->entry, &ablkcipher_algs);
+	dev_dbg(qce->dev, "%s is registered\n", alg->cra_name);
+	return 0;
+}
+
+static void qce_ablkcipher_unregister(struct qce_device *qce)
+{
+	struct qce_alg_template *tmpl, *n;
+
+	list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) {
+		crypto_unregister_alg(&tmpl->alg.crypto);
+		list_del(&tmpl->entry);
+		kfree(tmpl);
+	}
+}
+
+static int qce_ablkcipher_register(struct qce_device *qce)
+{
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) {
+		ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+err:
+	qce_ablkcipher_unregister(qce);
+	return ret;
+}
+
+const struct qce_algo_ops ablkcipher_ops = {
+	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+	.register_algs = qce_ablkcipher_register,
+	.unregister_algs = qce_ablkcipher_unregister,
+	.async_req_handle = qce_ablkcipher_async_req_handle,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/cipher.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/cipher.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/cipher.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/cipher.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010-2014, 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 _CIPHER_H_
+#define _CIPHER_H_
+
+#include "common.h"
+#include "core.h"
+
+#define QCE_MAX_KEY_SIZE	64
+
+struct qce_cipher_ctx {
+	u8 enc_key[QCE_MAX_KEY_SIZE];
+	unsigned int enc_keylen;
+	struct crypto_ablkcipher *fallback;
+};
+
+/**
+ * struct qce_cipher_reqctx - holds private cipher objects per request
+ * @flags: operation flags
+ * @iv: pointer to the IV
+ * @ivsize: IV size
+ * @src_nents: source entries
+ * @dst_nents: destination entries
+ * @src_chained: is source chained
+ * @dst_chained: is destination chained
+ * @result_sg: scatterlist used for result buffer
+ * @dst_tbl: destination sg table
+ * @dst_sg: destination sg pointer table beginning
+ * @src_tbl: source sg table
+ * @src_sg: source sg pointer table beginning;
+ * @cryptlen: crypto length
+ */
+struct qce_cipher_reqctx {
+	unsigned long flags;
+	u8 *iv;
+	unsigned int ivsize;
+	int src_nents;
+	int dst_nents;
+	bool src_chained;
+	bool dst_chained;
+	struct scatterlist result_sg;
+	struct sg_table dst_tbl;
+	struct scatterlist *dst_sg;
+	struct sg_table src_tbl;
+	struct scatterlist *src_sg;
+	unsigned int cryptlen;
+};
+
+static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *alg = tfm->__crt_alg;
+	return container_of(alg, struct qce_alg_template, alg.crypto);
+}
+
+extern const struct qce_algo_ops ablkcipher_ops;
+
+#endif /* _CIPHER_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/common.c linux-libre-3.17-rc7-gnu/drivers/crypto/qce/common.c
--- linux-libre-3.16-gnu/drivers/crypto/qce/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2012-2014, 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/err.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/sha.h>
+
+#include "cipher.h"
+#include "common.h"
+#include "core.h"
+#include "regs-v5.h"
+#include "sha.h"
+
+#define QCE_SECTOR_SIZE		512
+
+static inline u32 qce_read(struct qce_device *qce, u32 offset)
+{
+	return readl(qce->base + offset);
+}
+
+static inline void qce_write(struct qce_device *qce, u32 offset, u32 val)
+{
+	writel(val, qce->base + offset);
+}
+
+static inline void qce_write_array(struct qce_device *qce, u32 offset,
+				   const u32 *val, unsigned int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		qce_write(qce, offset + i * sizeof(u32), val[i]);
+}
+
+static inline void
+qce_clear_array(struct qce_device *qce, u32 offset, unsigned int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		qce_write(qce, offset + i * sizeof(u32), 0);
+}
+
+static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
+{
+	u32 cfg = 0;
+
+	if (IS_AES(flags)) {
+		if (aes_key_size == AES_KEYSIZE_128)
+			cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
+		else if (aes_key_size == AES_KEYSIZE_256)
+			cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
+	}
+
+	if (IS_AES(flags))
+		cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
+	else if (IS_DES(flags) || IS_3DES(flags))
+		cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
+
+	if (IS_DES(flags))
+		cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
+
+	if (IS_3DES(flags))
+		cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
+
+	switch (flags & QCE_MODE_MASK) {
+	case QCE_MODE_ECB:
+		cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
+		break;
+	case QCE_MODE_CBC:
+		cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
+		break;
+	case QCE_MODE_CTR:
+		cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
+		break;
+	case QCE_MODE_XTS:
+		cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
+		break;
+	case QCE_MODE_CCM:
+		cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
+		cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
+		break;
+	default:
+		return ~0;
+	}
+
+	return cfg;
+}
+
+static u32 qce_auth_cfg(unsigned long flags, u32 key_size)
+{
+	u32 cfg = 0;
+
+	if (IS_AES(flags) && (IS_CCM(flags) || IS_CMAC(flags)))
+		cfg |= AUTH_ALG_AES << AUTH_ALG_SHIFT;
+	else
+		cfg |= AUTH_ALG_SHA << AUTH_ALG_SHIFT;
+
+	if (IS_CCM(flags) || IS_CMAC(flags)) {
+		if (key_size == AES_KEYSIZE_128)
+			cfg |= AUTH_KEY_SZ_AES128 << AUTH_KEY_SIZE_SHIFT;
+		else if (key_size == AES_KEYSIZE_256)
+			cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT;
+	}
+
+	if (IS_SHA1(flags) || IS_SHA1_HMAC(flags))
+		cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT;
+	else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags))
+		cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT;
+	else if (IS_CMAC(flags))
+		cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT;
+
+	if (IS_SHA1(flags) || IS_SHA256(flags))
+		cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT;
+	else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags) ||
+		 IS_CBC(flags) || IS_CTR(flags))
+		cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT;
+	else if (IS_AES(flags) && IS_CCM(flags))
+		cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT;
+	else if (IS_AES(flags) && IS_CMAC(flags))
+		cfg |= AUTH_MODE_CMAC << AUTH_MODE_SHIFT;
+
+	if (IS_SHA(flags) || IS_SHA_HMAC(flags))
+		cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT;
+
+	if (IS_CCM(flags))
+		cfg |= QCE_MAX_NONCE_WORDS << AUTH_NONCE_NUM_WORDS_SHIFT;
+
+	if (IS_CBC(flags) || IS_CTR(flags) || IS_CCM(flags) ||
+	    IS_CMAC(flags))
+		cfg |= BIT(AUTH_LAST_SHIFT) | BIT(AUTH_FIRST_SHIFT);
+
+	return cfg;
+}
+
+static u32 qce_config_reg(struct qce_device *qce, int little)
+{
+	u32 beats = (qce->burst_size >> 3) - 1;
+	u32 pipe_pair = qce->pipe_pair_id;
+	u32 config;
+
+	config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
+	config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
+		  BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
+	config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
+	config &= ~HIGH_SPD_EN_N_SHIFT;
+
+	if (little)
+		config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
+
+	return config;
+}
+
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
+{
+	__be32 *d = dst;
+	const u8 *s = src;
+	unsigned int n;
+
+	n = len / sizeof(u32);
+	for (; n > 0; n--) {
+		*d = cpu_to_be32p((const __u32 *) s);
+		s += sizeof(__u32);
+		d++;
+	}
+}
+
+static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
+{
+	u8 swap[QCE_AES_IV_LENGTH];
+	u32 i, j;
+
+	if (ivsize > QCE_AES_IV_LENGTH)
+		return;
+
+	memset(swap, 0, QCE_AES_IV_LENGTH);
+
+	for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
+	     i < QCE_AES_IV_LENGTH; i++, j--)
+		swap[i] = src[j];
+
+	qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
+}
+
+static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
+		       unsigned int enckeylen, unsigned int cryptlen)
+{
+	u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
+	unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
+	unsigned int xtsdusize;
+
+	qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
+			       enckeylen / 2);
+	qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
+
+	/* xts du size 512B */
+	xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
+	qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
+}
+
+static void qce_setup_config(struct qce_device *qce)
+{
+	u32 config;
+
+	/* get big endianness */
+	config = qce_config_reg(qce, 0);
+
+	/* clear status */
+	qce_write(qce, REG_STATUS, 0);
+	qce_write(qce, REG_CONFIG, config);
+}
+
+static inline void qce_crypto_go(struct qce_device *qce)
+{
+	qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
+}
+
+static int qce_setup_regs_ahash(struct crypto_async_request *async_req,
+				u32 totallen, u32 offset)
+{
+	struct ahash_request *req = ahash_request_cast(async_req);
+	struct crypto_ahash *ahash = __crypto_ahash_cast(async_req->tfm);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	unsigned int digestsize = crypto_ahash_digestsize(ahash);
+	unsigned int blocksize = crypto_tfm_alg_blocksize(async_req->tfm);
+	__be32 auth[SHA256_DIGEST_SIZE / sizeof(__be32)] = {0};
+	__be32 mackey[QCE_SHA_HMAC_KEY_SIZE / sizeof(__be32)] = {0};
+	u32 auth_cfg = 0, config;
+	unsigned int iv_words;
+
+	/* if not the last, the size has to be on the block boundary */
+	if (!rctx->last_blk && req->nbytes % blocksize)
+		return -EINVAL;
+
+	qce_setup_config(qce);
+
+	if (IS_CMAC(rctx->flags)) {
+		qce_write(qce, REG_AUTH_SEG_CFG, 0);
+		qce_write(qce, REG_ENCR_SEG_CFG, 0);
+		qce_write(qce, REG_ENCR_SEG_SIZE, 0);
+		qce_clear_array(qce, REG_AUTH_IV0, 16);
+		qce_clear_array(qce, REG_AUTH_KEY0, 16);
+		qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
+
+		auth_cfg = qce_auth_cfg(rctx->flags, rctx->authklen);
+	}
+
+	if (IS_SHA_HMAC(rctx->flags) || IS_CMAC(rctx->flags)) {
+		u32 authkey_words = rctx->authklen / sizeof(u32);
+
+		qce_cpu_to_be32p_array(mackey, rctx->authkey, rctx->authklen);
+		qce_write_array(qce, REG_AUTH_KEY0, (u32 *)mackey,
+				authkey_words);
+	}
+
+	if (IS_CMAC(rctx->flags))
+		goto go_proc;
+
+	if (rctx->first_blk)
+		memcpy(auth, rctx->digest, digestsize);
+	else
+		qce_cpu_to_be32p_array(auth, rctx->digest, digestsize);
+
+	iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8;
+	qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words);
+
+	if (rctx->first_blk)
+		qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
+	else
+		qce_write_array(qce, REG_AUTH_BYTECNT0,
+				(u32 *)rctx->byte_count, 2);
+
+	auth_cfg = qce_auth_cfg(rctx->flags, 0);
+
+	if (rctx->last_blk)
+		auth_cfg |= BIT(AUTH_LAST_SHIFT);
+	else
+		auth_cfg &= ~BIT(AUTH_LAST_SHIFT);
+
+	if (rctx->first_blk)
+		auth_cfg |= BIT(AUTH_FIRST_SHIFT);
+	else
+		auth_cfg &= ~BIT(AUTH_FIRST_SHIFT);
+
+go_proc:
+	qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
+	qce_write(qce, REG_AUTH_SEG_SIZE, req->nbytes);
+	qce_write(qce, REG_AUTH_SEG_START, 0);
+	qce_write(qce, REG_ENCR_SEG_CFG, 0);
+	qce_write(qce, REG_SEG_SIZE, req->nbytes);
+
+	/* get little endianness */
+	config = qce_config_reg(qce, 1);
+	qce_write(qce, REG_CONFIG, config);
+
+	qce_crypto_go(qce);
+
+	return 0;
+}
+
+static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req,
+				     u32 totallen, u32 offset)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+	struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
+	struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	__be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0};
+	__be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0};
+	unsigned int enckey_words, enciv_words;
+	unsigned int keylen;
+	u32 encr_cfg = 0, auth_cfg = 0, config;
+	unsigned int ivsize = rctx->ivsize;
+	unsigned long flags = rctx->flags;
+
+	qce_setup_config(qce);
+
+	if (IS_XTS(flags))
+		keylen = ctx->enc_keylen / 2;
+	else
+		keylen = ctx->enc_keylen;
+
+	qce_cpu_to_be32p_array(enckey, ctx->enc_key, keylen);
+	enckey_words = keylen / sizeof(u32);
+
+	qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
+
+	encr_cfg = qce_encr_cfg(flags, keylen);
+
+	if (IS_DES(flags)) {
+		enciv_words = 2;
+		enckey_words = 2;
+	} else if (IS_3DES(flags)) {
+		enciv_words = 2;
+		enckey_words = 6;
+	} else if (IS_AES(flags)) {
+		if (IS_XTS(flags))
+			qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen,
+				   rctx->cryptlen);
+		enciv_words = 4;
+	} else {
+		return -EINVAL;
+	}
+
+	qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words);
+
+	if (!IS_ECB(flags)) {
+		if (IS_XTS(flags))
+			qce_xts_swapiv(enciv, rctx->iv, ivsize);
+		else
+			qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize);
+
+		qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words);
+	}
+
+	if (IS_ENCRYPT(flags))
+		encr_cfg |= BIT(ENCODE_SHIFT);
+
+	qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg);
+	qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen);
+	qce_write(qce, REG_ENCR_SEG_START, offset & 0xffff);
+
+	if (IS_CTR(flags)) {
+		qce_write(qce, REG_CNTR_MASK, ~0);
+		qce_write(qce, REG_CNTR_MASK0, ~0);
+		qce_write(qce, REG_CNTR_MASK1, ~0);
+		qce_write(qce, REG_CNTR_MASK2, ~0);
+	}
+
+	qce_write(qce, REG_SEG_SIZE, totallen);
+
+	/* get little endianness */
+	config = qce_config_reg(qce, 1);
+	qce_write(qce, REG_CONFIG, config);
+
+	qce_crypto_go(qce);
+
+	return 0;
+}
+
+int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
+	      u32 offset)
+{
+	switch (type) {
+	case CRYPTO_ALG_TYPE_ABLKCIPHER:
+		return qce_setup_regs_ablkcipher(async_req, totallen, offset);
+	case CRYPTO_ALG_TYPE_AHASH:
+		return qce_setup_regs_ahash(async_req, totallen, offset);
+	default:
+		return -EINVAL;
+	}
+}
+
+#define STATUS_ERRORS	\
+		(BIT(SW_ERR_SHIFT) | BIT(AXI_ERR_SHIFT) | BIT(HSD_ERR_SHIFT))
+
+int qce_check_status(struct qce_device *qce, u32 *status)
+{
+	int ret = 0;
+
+	*status = qce_read(qce, REG_STATUS);
+
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read from device. In case, we need to
+	 * use result_status from result dump the result_status needs to be byte
+	 * swapped, since we set the device to little endian.
+	 */
+	if (*status & STATUS_ERRORS || !(*status & BIT(OPERATION_DONE_SHIFT)))
+		ret = -ENXIO;
+
+	return ret;
+}
+
+void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step)
+{
+	u32 val;
+
+	val = qce_read(qce, REG_VERSION);
+	*major = (val & CORE_MAJOR_REV_MASK) >> CORE_MAJOR_REV_SHIFT;
+	*minor = (val & CORE_MINOR_REV_MASK) >> CORE_MINOR_REV_SHIFT;
+	*step = (val & CORE_STEP_REV_MASK) >> CORE_STEP_REV_SHIFT;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/common.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/common.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010-2014, 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 _COMMON_H_
+#define _COMMON_H_
+
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/aes.h>
+#include <crypto/hash.h>
+
+/* key size in bytes */
+#define QCE_SHA_HMAC_KEY_SIZE		64
+#define QCE_MAX_CIPHER_KEY_SIZE		AES_KEYSIZE_256
+
+/* IV length in bytes */
+#define QCE_AES_IV_LENGTH		AES_BLOCK_SIZE
+/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
+#define QCE_MAX_IV_SIZE			AES_BLOCK_SIZE
+
+/* maximum nonce bytes  */
+#define QCE_MAX_NONCE			16
+#define QCE_MAX_NONCE_WORDS		(QCE_MAX_NONCE / sizeof(u32))
+
+/* burst size alignment requirement */
+#define QCE_MAX_ALIGN_SIZE		64
+
+/* cipher algorithms */
+#define QCE_ALG_DES			BIT(0)
+#define QCE_ALG_3DES			BIT(1)
+#define QCE_ALG_AES			BIT(2)
+
+/* hash and hmac algorithms */
+#define QCE_HASH_SHA1			BIT(3)
+#define QCE_HASH_SHA256			BIT(4)
+#define QCE_HASH_SHA1_HMAC		BIT(5)
+#define QCE_HASH_SHA256_HMAC		BIT(6)
+#define QCE_HASH_AES_CMAC		BIT(7)
+
+/* cipher modes */
+#define QCE_MODE_CBC			BIT(8)
+#define QCE_MODE_ECB			BIT(9)
+#define QCE_MODE_CTR			BIT(10)
+#define QCE_MODE_XTS			BIT(11)
+#define QCE_MODE_CCM			BIT(12)
+#define QCE_MODE_MASK			GENMASK(12, 8)
+
+/* cipher encryption/decryption operations */
+#define QCE_ENCRYPT			BIT(13)
+#define QCE_DECRYPT			BIT(14)
+
+#define IS_DES(flags)			(flags & QCE_ALG_DES)
+#define IS_3DES(flags)			(flags & QCE_ALG_3DES)
+#define IS_AES(flags)			(flags & QCE_ALG_AES)
+
+#define IS_SHA1(flags)			(flags & QCE_HASH_SHA1)
+#define IS_SHA256(flags)		(flags & QCE_HASH_SHA256)
+#define IS_SHA1_HMAC(flags)		(flags & QCE_HASH_SHA1_HMAC)
+#define IS_SHA256_HMAC(flags)		(flags & QCE_HASH_SHA256_HMAC)
+#define IS_CMAC(flags)			(flags & QCE_HASH_AES_CMAC)
+#define IS_SHA(flags)			(IS_SHA1(flags) || IS_SHA256(flags))
+#define IS_SHA_HMAC(flags)		\
+		(IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags))
+
+#define IS_CBC(mode)			(mode & QCE_MODE_CBC)
+#define IS_ECB(mode)			(mode & QCE_MODE_ECB)
+#define IS_CTR(mode)			(mode & QCE_MODE_CTR)
+#define IS_XTS(mode)			(mode & QCE_MODE_XTS)
+#define IS_CCM(mode)			(mode & QCE_MODE_CCM)
+
+#define IS_ENCRYPT(dir)			(dir & QCE_ENCRYPT)
+#define IS_DECRYPT(dir)			(dir & QCE_DECRYPT)
+
+struct qce_alg_template {
+	struct list_head entry;
+	u32 crypto_alg_type;
+	unsigned long alg_flags;
+	const u32 *std_iv;
+	union {
+		struct crypto_alg crypto;
+		struct ahash_alg ahash;
+	} alg;
+	struct qce_device *qce;
+};
+
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len);
+int qce_check_status(struct qce_device *qce, u32 *status);
+void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step);
+int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
+	      u32 offset);
+
+#endif /* _COMMON_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/core.c linux-libre-3.17-rc7-gnu/drivers/crypto/qce/core.c
--- linux-libre-3.16-gnu/drivers/crypto/qce/core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2010-2014, 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/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+
+#include "core.h"
+#include "cipher.h"
+#include "sha.h"
+
+#define QCE_MAJOR_VERSION5	0x05
+#define QCE_QUEUE_LENGTH	1
+
+static const struct qce_algo_ops *qce_ops[] = {
+	&ablkcipher_ops,
+	&ahash_ops,
+};
+
+static void qce_unregister_algs(struct qce_device *qce)
+{
+	const struct qce_algo_ops *ops;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+		ops = qce_ops[i];
+		ops->unregister_algs(qce);
+	}
+}
+
+static int qce_register_algs(struct qce_device *qce)
+{
+	const struct qce_algo_ops *ops;
+	int i, ret = -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+		ops = qce_ops[i];
+		ret = ops->register_algs(qce);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int qce_handle_request(struct crypto_async_request *async_req)
+{
+	int ret = -EINVAL, i;
+	const struct qce_algo_ops *ops;
+	u32 type = crypto_tfm_alg_type(async_req->tfm);
+
+	for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+		ops = qce_ops[i];
+		if (type != ops->type)
+			continue;
+		ret = ops->async_req_handle(async_req);
+		break;
+	}
+
+	return ret;
+}
+
+static int qce_handle_queue(struct qce_device *qce,
+			    struct crypto_async_request *req)
+{
+	struct crypto_async_request *async_req, *backlog;
+	unsigned long flags;
+	int ret = 0, err;
+
+	spin_lock_irqsave(&qce->lock, flags);
+
+	if (req)
+		ret = crypto_enqueue_request(&qce->queue, req);
+
+	/* busy, do not dequeue request */
+	if (qce->req) {
+		spin_unlock_irqrestore(&qce->lock, flags);
+		return ret;
+	}
+
+	backlog = crypto_get_backlog(&qce->queue);
+	async_req = crypto_dequeue_request(&qce->queue);
+	if (async_req)
+		qce->req = async_req;
+
+	spin_unlock_irqrestore(&qce->lock, flags);
+
+	if (!async_req)
+		return ret;
+
+	if (backlog) {
+		spin_lock_bh(&qce->lock);
+		backlog->complete(backlog, -EINPROGRESS);
+		spin_unlock_bh(&qce->lock);
+	}
+
+	err = qce_handle_request(async_req);
+	if (err) {
+		qce->result = err;
+		tasklet_schedule(&qce->done_tasklet);
+	}
+
+	return ret;
+}
+
+static void qce_tasklet_req_done(unsigned long data)
+{
+	struct qce_device *qce = (struct qce_device *)data;
+	struct crypto_async_request *req;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qce->lock, flags);
+	req = qce->req;
+	qce->req = NULL;
+	spin_unlock_irqrestore(&qce->lock, flags);
+
+	if (req)
+		req->complete(req, qce->result);
+
+	qce_handle_queue(qce, NULL);
+}
+
+static int qce_async_request_enqueue(struct qce_device *qce,
+				     struct crypto_async_request *req)
+{
+	return qce_handle_queue(qce, req);
+}
+
+static void qce_async_request_done(struct qce_device *qce, int ret)
+{
+	qce->result = ret;
+	tasklet_schedule(&qce->done_tasklet);
+}
+
+static int qce_check_version(struct qce_device *qce)
+{
+	u32 major, minor, step;
+
+	qce_get_version(qce, &major, &minor, &step);
+
+	/*
+	 * the driver does not support v5 with minor 0 because it has special
+	 * alignment requirements.
+	 */
+	if (major != QCE_MAJOR_VERSION5 || minor == 0)
+		return -ENODEV;
+
+	qce->burst_size = QCE_BAM_BURST_SIZE;
+	qce->pipe_pair_id = 1;
+
+	dev_dbg(qce->dev, "Crypto device found, version %d.%d.%d\n",
+		major, minor, step);
+
+	return 0;
+}
+
+static int qce_crypto_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct qce_device *qce;
+	struct resource *res;
+	int ret;
+
+	qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL);
+	if (!qce)
+		return -ENOMEM;
+
+	qce->dev = dev;
+	platform_set_drvdata(pdev, qce);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	qce->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(qce->base))
+		return PTR_ERR(qce->base);
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	if (ret < 0)
+		return ret;
+
+	qce->core = devm_clk_get(qce->dev, "core");
+	if (IS_ERR(qce->core))
+		return PTR_ERR(qce->core);
+
+	qce->iface = devm_clk_get(qce->dev, "iface");
+	if (IS_ERR(qce->iface))
+		return PTR_ERR(qce->iface);
+
+	qce->bus = devm_clk_get(qce->dev, "bus");
+	if (IS_ERR(qce->bus))
+		return PTR_ERR(qce->bus);
+
+	ret = clk_prepare_enable(qce->core);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(qce->iface);
+	if (ret)
+		goto err_clks_core;
+
+	ret = clk_prepare_enable(qce->bus);
+	if (ret)
+		goto err_clks_iface;
+
+	ret = qce_dma_request(qce->dev, &qce->dma);
+	if (ret)
+		goto err_clks;
+
+	ret = qce_check_version(qce);
+	if (ret)
+		goto err_clks;
+
+	spin_lock_init(&qce->lock);
+	tasklet_init(&qce->done_tasklet, qce_tasklet_req_done,
+		     (unsigned long)qce);
+	crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
+
+	qce->async_req_enqueue = qce_async_request_enqueue;
+	qce->async_req_done = qce_async_request_done;
+
+	ret = qce_register_algs(qce);
+	if (ret)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	qce_dma_release(&qce->dma);
+err_clks:
+	clk_disable_unprepare(qce->bus);
+err_clks_iface:
+	clk_disable_unprepare(qce->iface);
+err_clks_core:
+	clk_disable_unprepare(qce->core);
+	return ret;
+}
+
+static int qce_crypto_remove(struct platform_device *pdev)
+{
+	struct qce_device *qce = platform_get_drvdata(pdev);
+
+	tasklet_kill(&qce->done_tasklet);
+	qce_unregister_algs(qce);
+	qce_dma_release(&qce->dma);
+	clk_disable_unprepare(qce->bus);
+	clk_disable_unprepare(qce->iface);
+	clk_disable_unprepare(qce->core);
+	return 0;
+}
+
+static const struct of_device_id qce_crypto_of_match[] = {
+	{ .compatible = "qcom,crypto-v5.1", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
+
+static struct platform_driver qce_crypto_driver = {
+	.probe = qce_crypto_probe,
+	.remove = qce_crypto_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = KBUILD_MODNAME,
+		.of_match_table = qce_crypto_of_match,
+	},
+};
+module_platform_driver(qce_crypto_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm crypto engine driver");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_AUTHOR("The Linux Foundation");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/core.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/core.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/core.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010-2014, 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 _CORE_H_
+#define _CORE_H_
+
+#include "dma.h"
+
+/**
+ * struct qce_device - crypto engine device structure
+ * @queue: crypto request queue
+ * @lock: the lock protects queue and req
+ * @done_tasklet: done tasklet object
+ * @req: current active request
+ * @result: result of current transform
+ * @base: virtual IO base
+ * @dev: pointer to device structure
+ * @core: core device clock
+ * @iface: interface clock
+ * @bus: bus clock
+ * @dma: pointer to dma data
+ * @burst_size: the crypto burst size
+ * @pipe_pair_id: which pipe pair id the device using
+ * @async_req_enqueue: invoked by every algorithm to enqueue a request
+ * @async_req_done: invoked by every algorithm to finish its request
+ */
+struct qce_device {
+	struct crypto_queue queue;
+	spinlock_t lock;
+	struct tasklet_struct done_tasklet;
+	struct crypto_async_request *req;
+	int result;
+	void __iomem *base;
+	struct device *dev;
+	struct clk *core, *iface, *bus;
+	struct qce_dma_data dma;
+	int burst_size;
+	unsigned int pipe_pair_id;
+	int (*async_req_enqueue)(struct qce_device *qce,
+				 struct crypto_async_request *req);
+	void (*async_req_done)(struct qce_device *qce, int ret);
+};
+
+/**
+ * struct qce_algo_ops - algorithm operations per crypto type
+ * @type: should be CRYPTO_ALG_TYPE_XXX
+ * @register_algs: invoked by core to register the algorithms
+ * @unregister_algs: invoked by core to unregister the algorithms
+ * @async_req_handle: invoked by core to handle enqueued request
+ */
+struct qce_algo_ops {
+	u32 type;
+	int (*register_algs)(struct qce_device *qce);
+	void (*unregister_algs)(struct qce_device *qce);
+	int (*async_req_handle)(struct crypto_async_request *async_req);
+};
+
+#endif /* _CORE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/dma.c linux-libre-3.17-rc7-gnu/drivers/crypto/qce/dma.c
--- linux-libre-3.16-gnu/drivers/crypto/qce/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012-2014, 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/dmaengine.h>
+#include <crypto/scatterwalk.h>
+
+#include "dma.h"
+
+int qce_dma_request(struct device *dev, struct qce_dma_data *dma)
+{
+	int ret;
+
+	dma->txchan = dma_request_slave_channel_reason(dev, "tx");
+	if (IS_ERR(dma->txchan))
+		return PTR_ERR(dma->txchan);
+
+	dma->rxchan = dma_request_slave_channel_reason(dev, "rx");
+	if (IS_ERR(dma->rxchan)) {
+		ret = PTR_ERR(dma->rxchan);
+		goto error_rx;
+	}
+
+	dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ,
+				  GFP_KERNEL);
+	if (!dma->result_buf) {
+		ret = -ENOMEM;
+		goto error_nomem;
+	}
+
+	dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ;
+
+	return 0;
+error_nomem:
+	dma_release_channel(dma->rxchan);
+error_rx:
+	dma_release_channel(dma->txchan);
+	return ret;
+}
+
+void qce_dma_release(struct qce_dma_data *dma)
+{
+	dma_release_channel(dma->txchan);
+	dma_release_channel(dma->rxchan);
+	kfree(dma->result_buf);
+}
+
+int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
+	      enum dma_data_direction dir, bool chained)
+{
+	int err;
+
+	if (chained) {
+		while (sg) {
+			err = dma_map_sg(dev, sg, 1, dir);
+			if (!err)
+				return -EFAULT;
+			sg = scatterwalk_sg_next(sg);
+		}
+	} else {
+		err = dma_map_sg(dev, sg, nents, dir);
+		if (!err)
+			return -EFAULT;
+	}
+
+	return nents;
+}
+
+void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
+		 enum dma_data_direction dir, bool chained)
+{
+	if (chained)
+		while (sg) {
+			dma_unmap_sg(dev, sg, 1, dir);
+			sg = scatterwalk_sg_next(sg);
+		}
+	else
+		dma_unmap_sg(dev, sg, nents, dir);
+}
+
+int qce_countsg(struct scatterlist *sglist, int nbytes, bool *chained)
+{
+	struct scatterlist *sg = sglist;
+	int nents = 0;
+
+	if (chained)
+		*chained = false;
+
+	while (nbytes > 0 && sg) {
+		nents++;
+		nbytes -= sg->length;
+		if (!sg_is_last(sg) && (sg + 1)->length == 0 && chained)
+			*chained = true;
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
+struct scatterlist *
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl)
+{
+	struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
+
+	while (sg) {
+		if (!sg_page(sg))
+			break;
+		sg = sg_next(sg);
+	}
+
+	if (!sg)
+		return ERR_PTR(-EINVAL);
+
+	while (new_sgl && sg) {
+		sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
+			    new_sgl->offset);
+		sg_last = sg;
+		sg = sg_next(sg);
+		new_sgl = sg_next(new_sgl);
+	}
+
+	return sg_last;
+}
+
+static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg,
+			   int nents, unsigned long flags,
+			   enum dma_transfer_direction dir,
+			   dma_async_tx_callback cb, void *cb_param)
+{
+	struct dma_async_tx_descriptor *desc;
+	dma_cookie_t cookie;
+
+	if (!sg || !nents)
+		return -EINVAL;
+
+	desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags);
+	if (!desc)
+		return -EINVAL;
+
+	desc->callback = cb;
+	desc->callback_param = cb_param;
+	cookie = dmaengine_submit(desc);
+
+	return dma_submit_error(cookie);
+}
+
+int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg,
+		     int rx_nents, struct scatterlist *tx_sg, int tx_nents,
+		     dma_async_tx_callback cb, void *cb_param)
+{
+	struct dma_chan *rxchan = dma->rxchan;
+	struct dma_chan *txchan = dma->txchan;
+	unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+	int ret;
+
+	ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV,
+			     NULL, NULL);
+	if (ret)
+		return ret;
+
+	return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM,
+			       cb, cb_param);
+}
+
+void qce_dma_issue_pending(struct qce_dma_data *dma)
+{
+	dma_async_issue_pending(dma->rxchan);
+	dma_async_issue_pending(dma->txchan);
+}
+
+int qce_dma_terminate_all(struct qce_dma_data *dma)
+{
+	int ret;
+
+	ret = dmaengine_terminate_all(dma->rxchan);
+	return ret ?: dmaengine_terminate_all(dma->txchan);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/dma.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/dma.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/dma.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011-2014, 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 _DMA_H_
+#define _DMA_H_
+
+/* maximum data transfer block size between BAM and CE */
+#define QCE_BAM_BURST_SIZE		64
+
+#define QCE_AUTHIV_REGS_CNT		16
+#define QCE_AUTH_BYTECOUNT_REGS_CNT	4
+#define QCE_CNTRIV_REGS_CNT		4
+
+struct qce_result_dump {
+	u32 auth_iv[QCE_AUTHIV_REGS_CNT];
+	u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT];
+	u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT];
+	u32 status;
+	u32 status2;
+};
+
+#define QCE_IGNORE_BUF_SZ	(2 * QCE_BAM_BURST_SIZE)
+#define QCE_RESULT_BUF_SZ	\
+		ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE)
+
+struct qce_dma_data {
+	struct dma_chan *txchan;
+	struct dma_chan *rxchan;
+	struct qce_result_dump *result_buf;
+	void *ignore_buf;
+};
+
+int qce_dma_request(struct device *dev, struct qce_dma_data *dma);
+void qce_dma_release(struct qce_dma_data *dma);
+int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in,
+		     int in_ents, struct scatterlist *sg_out, int out_ents,
+		     dma_async_tx_callback cb, void *cb_param);
+void qce_dma_issue_pending(struct qce_dma_data *dma);
+int qce_dma_terminate_all(struct qce_dma_data *dma);
+int qce_countsg(struct scatterlist *sg_list, int nbytes, bool *chained);
+void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
+		 enum dma_data_direction dir, bool chained);
+int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
+	      enum dma_data_direction dir, bool chained);
+struct scatterlist *
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add);
+
+#endif /* _DMA_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/Makefile linux-libre-3.17-rc7-gnu/drivers/crypto/qce/Makefile
--- linux-libre-3.16-gnu/drivers/crypto/qce/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
+qcrypto-objs := core.o \
+		common.o \
+		dma.o \
+		sha.o \
+		ablkcipher.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/regs-v5.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/regs-v5.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/regs-v5.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/regs-v5.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2012-2014, 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 _REGS_V5_H_
+#define _REGS_V5_H_
+
+#include <linux/bitops.h>
+
+#define REG_VERSION			0x000
+#define REG_STATUS			0x100
+#define REG_STATUS2			0x104
+#define REG_ENGINES_AVAIL		0x108
+#define REG_FIFO_SIZES			0x10c
+#define REG_SEG_SIZE			0x110
+#define REG_GOPROC			0x120
+#define REG_ENCR_SEG_CFG		0x200
+#define REG_ENCR_SEG_SIZE		0x204
+#define REG_ENCR_SEG_START		0x208
+#define REG_CNTR0_IV0			0x20c
+#define REG_CNTR1_IV1			0x210
+#define REG_CNTR2_IV2			0x214
+#define REG_CNTR3_IV3			0x218
+#define REG_CNTR_MASK			0x21C
+#define REG_ENCR_CCM_INT_CNTR0		0x220
+#define REG_ENCR_CCM_INT_CNTR1		0x224
+#define REG_ENCR_CCM_INT_CNTR2		0x228
+#define REG_ENCR_CCM_INT_CNTR3		0x22c
+#define REG_ENCR_XTS_DU_SIZE		0x230
+#define REG_CNTR_MASK2			0x234
+#define REG_CNTR_MASK1			0x238
+#define REG_CNTR_MASK0			0x23c
+#define REG_AUTH_SEG_CFG		0x300
+#define REG_AUTH_SEG_SIZE		0x304
+#define REG_AUTH_SEG_START		0x308
+#define REG_AUTH_IV0			0x310
+#define REG_AUTH_IV1			0x314
+#define REG_AUTH_IV2			0x318
+#define REG_AUTH_IV3			0x31c
+#define REG_AUTH_IV4			0x320
+#define REG_AUTH_IV5			0x324
+#define REG_AUTH_IV6			0x328
+#define REG_AUTH_IV7			0x32c
+#define REG_AUTH_IV8			0x330
+#define REG_AUTH_IV9			0x334
+#define REG_AUTH_IV10			0x338
+#define REG_AUTH_IV11			0x33c
+#define REG_AUTH_IV12			0x340
+#define REG_AUTH_IV13			0x344
+#define REG_AUTH_IV14			0x348
+#define REG_AUTH_IV15			0x34c
+#define REG_AUTH_INFO_NONCE0		0x350
+#define REG_AUTH_INFO_NONCE1		0x354
+#define REG_AUTH_INFO_NONCE2		0x358
+#define REG_AUTH_INFO_NONCE3		0x35c
+#define REG_AUTH_BYTECNT0		0x390
+#define REG_AUTH_BYTECNT1		0x394
+#define REG_AUTH_BYTECNT2		0x398
+#define REG_AUTH_BYTECNT3		0x39c
+#define REG_AUTH_EXP_MAC0		0x3a0
+#define REG_AUTH_EXP_MAC1		0x3a4
+#define REG_AUTH_EXP_MAC2		0x3a8
+#define REG_AUTH_EXP_MAC3		0x3ac
+#define REG_AUTH_EXP_MAC4		0x3b0
+#define REG_AUTH_EXP_MAC5		0x3b4
+#define REG_AUTH_EXP_MAC6		0x3b8
+#define REG_AUTH_EXP_MAC7		0x3bc
+#define REG_CONFIG			0x400
+#define REG_GOPROC_QC_KEY		0x1000
+#define REG_GOPROC_OEM_KEY		0x2000
+#define REG_ENCR_KEY0			0x3000
+#define REG_ENCR_KEY1			0x3004
+#define REG_ENCR_KEY2			0x3008
+#define REG_ENCR_KEY3			0x300c
+#define REG_ENCR_KEY4			0x3010
+#define REG_ENCR_KEY5			0x3014
+#define REG_ENCR_KEY6			0x3018
+#define REG_ENCR_KEY7			0x301c
+#define REG_ENCR_XTS_KEY0		0x3020
+#define REG_ENCR_XTS_KEY1		0x3024
+#define REG_ENCR_XTS_KEY2		0x3028
+#define REG_ENCR_XTS_KEY3		0x302c
+#define REG_ENCR_XTS_KEY4		0x3030
+#define REG_ENCR_XTS_KEY5		0x3034
+#define REG_ENCR_XTS_KEY6		0x3038
+#define REG_ENCR_XTS_KEY7		0x303c
+#define REG_AUTH_KEY0			0x3040
+#define REG_AUTH_KEY1			0x3044
+#define REG_AUTH_KEY2			0x3048
+#define REG_AUTH_KEY3			0x304c
+#define REG_AUTH_KEY4			0x3050
+#define REG_AUTH_KEY5			0x3054
+#define REG_AUTH_KEY6			0x3058
+#define REG_AUTH_KEY7			0x305c
+#define REG_AUTH_KEY8			0x3060
+#define REG_AUTH_KEY9			0x3064
+#define REG_AUTH_KEY10			0x3068
+#define REG_AUTH_KEY11			0x306c
+#define REG_AUTH_KEY12			0x3070
+#define REG_AUTH_KEY13			0x3074
+#define REG_AUTH_KEY14			0x3078
+#define REG_AUTH_KEY15			0x307c
+
+/* Register bits - REG_VERSION */
+#define CORE_STEP_REV_SHIFT		0
+#define CORE_STEP_REV_MASK		GENMASK(15, 0)
+#define CORE_MINOR_REV_SHIFT		16
+#define CORE_MINOR_REV_MASK		GENMASK(23, 16)
+#define CORE_MAJOR_REV_SHIFT		24
+#define CORE_MAJOR_REV_MASK		GENMASK(31, 24)
+
+/* Register bits - REG_STATUS */
+#define MAC_FAILED_SHIFT		31
+#define DOUT_SIZE_AVAIL_SHIFT		26
+#define DOUT_SIZE_AVAIL_MASK		GENMASK(30, 26)
+#define DIN_SIZE_AVAIL_SHIFT		21
+#define DIN_SIZE_AVAIL_MASK		GENMASK(25, 21)
+#define HSD_ERR_SHIFT			20
+#define ACCESS_VIOL_SHIFT		19
+#define PIPE_ACTIVE_ERR_SHIFT		18
+#define CFG_CHNG_ERR_SHIFT		17
+#define DOUT_ERR_SHIFT			16
+#define DIN_ERR_SHIFT			15
+#define AXI_ERR_SHIFT			14
+#define CRYPTO_STATE_SHIFT		10
+#define CRYPTO_STATE_MASK		GENMASK(13, 10)
+#define ENCR_BUSY_SHIFT			9
+#define AUTH_BUSY_SHIFT			8
+#define DOUT_INTR_SHIFT			7
+#define DIN_INTR_SHIFT			6
+#define OP_DONE_INTR_SHIFT		5
+#define ERR_INTR_SHIFT			4
+#define DOUT_RDY_SHIFT			3
+#define DIN_RDY_SHIFT			2
+#define OPERATION_DONE_SHIFT		1
+#define SW_ERR_SHIFT			0
+
+/* Register bits - REG_STATUS2 */
+#define AXI_EXTRA_SHIFT			1
+#define LOCKED_SHIFT			2
+
+/* Register bits - REG_CONFIG */
+#define REQ_SIZE_SHIFT			17
+#define REQ_SIZE_MASK			GENMASK(20, 17)
+#define REQ_SIZE_ENUM_1_BEAT		0
+#define REQ_SIZE_ENUM_2_BEAT		1
+#define REQ_SIZE_ENUM_3_BEAT		2
+#define REQ_SIZE_ENUM_4_BEAT		3
+#define REQ_SIZE_ENUM_5_BEAT		4
+#define REQ_SIZE_ENUM_6_BEAT		5
+#define REQ_SIZE_ENUM_7_BEAT		6
+#define REQ_SIZE_ENUM_8_BEAT		7
+#define REQ_SIZE_ENUM_9_BEAT		8
+#define REQ_SIZE_ENUM_10_BEAT		9
+#define REQ_SIZE_ENUM_11_BEAT		10
+#define REQ_SIZE_ENUM_12_BEAT		11
+#define REQ_SIZE_ENUM_13_BEAT		12
+#define REQ_SIZE_ENUM_14_BEAT		13
+#define REQ_SIZE_ENUM_15_BEAT		14
+#define REQ_SIZE_ENUM_16_BEAT		15
+
+#define MAX_QUEUED_REQ_SHIFT		14
+#define MAX_QUEUED_REQ_MASK		GENMASK(24, 16)
+#define ENUM_1_QUEUED_REQS		0
+#define ENUM_2_QUEUED_REQS		1
+#define ENUM_3_QUEUED_REQS		2
+
+#define IRQ_ENABLES_SHIFT		10
+#define IRQ_ENABLES_MASK		GENMASK(13, 10)
+
+#define LITTLE_ENDIAN_MODE_SHIFT	9
+#define PIPE_SET_SELECT_SHIFT		5
+#define PIPE_SET_SELECT_MASK		GENMASK(8, 5)
+
+#define HIGH_SPD_EN_N_SHIFT		4
+#define MASK_DOUT_INTR_SHIFT		3
+#define MASK_DIN_INTR_SHIFT		2
+#define MASK_OP_DONE_INTR_SHIFT		1
+#define MASK_ERR_INTR_SHIFT		0
+
+/* Register bits - REG_AUTH_SEG_CFG */
+#define COMP_EXP_MAC_SHIFT		24
+#define COMP_EXP_MAC_DISABLED		0
+#define COMP_EXP_MAC_ENABLED		1
+
+#define F9_DIRECTION_SHIFT		23
+#define F9_DIRECTION_UPLINK		0
+#define F9_DIRECTION_DOWNLINK		1
+
+#define AUTH_NONCE_NUM_WORDS_SHIFT	20
+#define AUTH_NONCE_NUM_WORDS_MASK	GENMASK(22, 20)
+
+#define USE_PIPE_KEY_AUTH_SHIFT		19
+#define USE_HW_KEY_AUTH_SHIFT		18
+#define AUTH_FIRST_SHIFT		17
+#define AUTH_LAST_SHIFT			16
+
+#define AUTH_POS_SHIFT			14
+#define AUTH_POS_MASK			GENMASK(15, 14)
+#define AUTH_POS_BEFORE			0
+#define AUTH_POS_AFTER			1
+
+#define AUTH_SIZE_SHIFT			9
+#define AUTH_SIZE_MASK			GENMASK(13, 9)
+#define AUTH_SIZE_SHA1			0
+#define AUTH_SIZE_SHA256		1
+#define AUTH_SIZE_ENUM_1_BYTES		0
+#define AUTH_SIZE_ENUM_2_BYTES		1
+#define AUTH_SIZE_ENUM_3_BYTES		2
+#define AUTH_SIZE_ENUM_4_BYTES		3
+#define AUTH_SIZE_ENUM_5_BYTES		4
+#define AUTH_SIZE_ENUM_6_BYTES		5
+#define AUTH_SIZE_ENUM_7_BYTES		6
+#define AUTH_SIZE_ENUM_8_BYTES		7
+#define AUTH_SIZE_ENUM_9_BYTES		8
+#define AUTH_SIZE_ENUM_10_BYTES		9
+#define AUTH_SIZE_ENUM_11_BYTES		10
+#define AUTH_SIZE_ENUM_12_BYTES		11
+#define AUTH_SIZE_ENUM_13_BYTES		12
+#define AUTH_SIZE_ENUM_14_BYTES		13
+#define AUTH_SIZE_ENUM_15_BYTES		14
+#define AUTH_SIZE_ENUM_16_BYTES		15
+
+#define AUTH_MODE_SHIFT			6
+#define AUTH_MODE_MASK			GENMASK(8, 6)
+#define AUTH_MODE_HASH			0
+#define AUTH_MODE_HMAC			1
+#define AUTH_MODE_CCM			0
+#define AUTH_MODE_CMAC			1
+
+#define AUTH_KEY_SIZE_SHIFT		3
+#define AUTH_KEY_SIZE_MASK		GENMASK(5, 3)
+#define AUTH_KEY_SZ_AES128		0
+#define AUTH_KEY_SZ_AES256		2
+
+#define AUTH_ALG_SHIFT			0
+#define AUTH_ALG_MASK			GENMASK(2, 0)
+#define AUTH_ALG_NONE			0
+#define AUTH_ALG_SHA			1
+#define AUTH_ALG_AES			2
+#define AUTH_ALG_KASUMI			3
+#define AUTH_ALG_SNOW3G			4
+#define AUTH_ALG_ZUC			5
+
+/* Register bits - REG_ENCR_XTS_DU_SIZE */
+#define ENCR_XTS_DU_SIZE_SHIFT		0
+#define ENCR_XTS_DU_SIZE_MASK		GENMASK(19, 0)
+
+/* Register bits - REG_ENCR_SEG_CFG */
+#define F8_KEYSTREAM_ENABLE_SHIFT	17
+#define F8_KEYSTREAM_DISABLED		0
+#define F8_KEYSTREAM_ENABLED		1
+
+#define F8_DIRECTION_SHIFT		16
+#define F8_DIRECTION_UPLINK		0
+#define F8_DIRECTION_DOWNLINK		1
+
+#define USE_PIPE_KEY_ENCR_SHIFT		15
+#define USE_PIPE_KEY_ENCR_ENABLED	1
+#define USE_KEY_REGISTERS		0
+
+#define USE_HW_KEY_ENCR_SHIFT		14
+#define USE_KEY_REG			0
+#define USE_HW_KEY			1
+
+#define LAST_CCM_SHIFT			13
+#define LAST_CCM_XFR			1
+#define INTERM_CCM_XFR			0
+
+#define CNTR_ALG_SHIFT			11
+#define CNTR_ALG_MASK			GENMASK(12, 11)
+#define CNTR_ALG_NIST			0
+
+#define ENCODE_SHIFT			10
+
+#define ENCR_MODE_SHIFT			6
+#define ENCR_MODE_MASK			GENMASK(9, 6)
+#define ENCR_MODE_ECB			0
+#define ENCR_MODE_CBC			1
+#define ENCR_MODE_CTR			2
+#define ENCR_MODE_XTS			3
+#define ENCR_MODE_CCM			4
+
+#define ENCR_KEY_SZ_SHIFT		3
+#define ENCR_KEY_SZ_MASK		GENMASK(5, 3)
+#define ENCR_KEY_SZ_DES			0
+#define ENCR_KEY_SZ_3DES		1
+#define ENCR_KEY_SZ_AES128		0
+#define ENCR_KEY_SZ_AES256		2
+
+#define ENCR_ALG_SHIFT			0
+#define ENCR_ALG_MASK			GENMASK(2, 0)
+#define ENCR_ALG_NONE			0
+#define ENCR_ALG_DES			1
+#define ENCR_ALG_AES			2
+#define ENCR_ALG_KASUMI			4
+#define ENCR_ALG_SNOW_3G		5
+#define ENCR_ALG_ZUC			6
+
+/* Register bits - REG_GOPROC */
+#define GO_SHIFT			0
+#define CLR_CNTXT_SHIFT			1
+#define RESULTS_DUMP_SHIFT		2
+
+/* Register bits - REG_ENGINES_AVAIL */
+#define ENCR_AES_SEL_SHIFT		0
+#define DES_SEL_SHIFT			1
+#define ENCR_SNOW3G_SEL_SHIFT		2
+#define ENCR_KASUMI_SEL_SHIFT		3
+#define SHA_SEL_SHIFT			4
+#define SHA512_SEL_SHIFT		5
+#define AUTH_AES_SEL_SHIFT		6
+#define AUTH_SNOW3G_SEL_SHIFT		7
+#define AUTH_KASUMI_SEL_SHIFT		8
+#define BAM_PIPE_SETS_SHIFT		9
+#define BAM_PIPE_SETS_MASK		GENMASK(12, 9)
+#define AXI_WR_BEATS_SHIFT		13
+#define AXI_WR_BEATS_MASK		GENMASK(18, 13)
+#define AXI_RD_BEATS_SHIFT		19
+#define AXI_RD_BEATS_MASK		GENMASK(24, 19)
+#define ENCR_ZUC_SEL_SHIFT		26
+#define AUTH_ZUC_SEL_SHIFT		27
+#define ZUC_ENABLE_SHIFT		28
+
+#endif /* _REGS_V5_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/sha.c linux-libre-3.17-rc7-gnu/drivers/crypto/qce/sha.c
--- linux-libre-3.16-gnu/drivers/crypto/qce/sha.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/sha.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2010-2014, 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/device.h>
+#include <linux/interrupt.h>
+#include <crypto/internal/hash.h>
+
+#include "common.h"
+#include "core.h"
+#include "sha.h"
+
+/* crypto hw padding constant for first operation */
+#define SHA_PADDING		64
+#define SHA_PADDING_MASK	(SHA_PADDING - 1)
+
+static LIST_HEAD(ahash_algs);
+
+static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = {
+	SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0
+};
+
+static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = {
+	SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
+	SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7
+};
+
+static void qce_ahash_done(void *data)
+{
+	struct crypto_async_request *async_req = data;
+	struct ahash_request *req = ahash_request_cast(async_req);
+	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	struct qce_result_dump *result = qce->dma.result_buf;
+	unsigned int digestsize = crypto_ahash_digestsize(ahash);
+	int error;
+	u32 status;
+
+	error = qce_dma_terminate_all(&qce->dma);
+	if (error)
+		dev_dbg(qce->dev, "ahash dma termination error (%d)\n", error);
+
+	qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+		    rctx->src_chained);
+	qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+
+	memcpy(rctx->digest, result->auth_iv, digestsize);
+	if (req->result)
+		memcpy(req->result, result->auth_iv, digestsize);
+
+	rctx->byte_count[0] = cpu_to_be32(result->auth_byte_count[0]);
+	rctx->byte_count[1] = cpu_to_be32(result->auth_byte_count[1]);
+
+	error = qce_check_status(qce, &status);
+	if (error < 0)
+		dev_dbg(qce->dev, "ahash operation error (%x)\n", status);
+
+	req->src = rctx->src_orig;
+	req->nbytes = rctx->nbytes_orig;
+	rctx->last_blk = false;
+	rctx->first_blk = false;
+
+	qce->async_req_done(tmpl->qce, error);
+}
+
+static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
+{
+	struct ahash_request *req = ahash_request_cast(async_req);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_sha_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+	struct qce_device *qce = tmpl->qce;
+	unsigned long flags = rctx->flags;
+	int ret;
+
+	if (IS_SHA_HMAC(flags)) {
+		rctx->authkey = ctx->authkey;
+		rctx->authklen = QCE_SHA_HMAC_KEY_SIZE;
+	} else if (IS_CMAC(flags)) {
+		rctx->authkey = ctx->authkey;
+		rctx->authklen = AES_KEYSIZE_128;
+	}
+
+	rctx->src_nents = qce_countsg(req->src, req->nbytes,
+				      &rctx->src_chained);
+	ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+			rctx->src_chained);
+	if (ret < 0)
+		return ret;
+
+	sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
+
+	ret = qce_mapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+	if (ret < 0)
+		goto error_unmap_src;
+
+	ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents,
+			       &rctx->result_sg, 1, qce_ahash_done, async_req);
+	if (ret)
+		goto error_unmap_dst;
+
+	qce_dma_issue_pending(&qce->dma);
+
+	ret = qce_start(async_req, tmpl->crypto_alg_type, 0, 0);
+	if (ret)
+		goto error_terminate;
+
+	return 0;
+
+error_terminate:
+	qce_dma_terminate_all(&qce->dma);
+error_unmap_dst:
+	qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+error_unmap_src:
+	qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+		    rctx->src_chained);
+	return ret;
+}
+
+static int qce_ahash_init(struct ahash_request *req)
+{
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+	const u32 *std_iv = tmpl->std_iv;
+
+	memset(rctx, 0, sizeof(*rctx));
+	rctx->first_blk = true;
+	rctx->last_blk = false;
+	rctx->flags = tmpl->alg_flags;
+	memcpy(rctx->digest, std_iv, sizeof(rctx->digest));
+
+	return 0;
+}
+
+static int qce_ahash_export(struct ahash_request *req, void *out)
+{
+	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	unsigned long flags = rctx->flags;
+	unsigned int digestsize = crypto_ahash_digestsize(ahash);
+	unsigned int blocksize =
+			crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
+
+	if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
+		struct sha1_state *out_state = out;
+
+		out_state->count = rctx->count;
+		qce_cpu_to_be32p_array((__be32 *)out_state->state,
+				       rctx->digest, digestsize);
+		memcpy(out_state->buffer, rctx->buf, blocksize);
+	} else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
+		struct sha256_state *out_state = out;
+
+		out_state->count = rctx->count;
+		qce_cpu_to_be32p_array((__be32 *)out_state->state,
+				       rctx->digest, digestsize);
+		memcpy(out_state->buf, rctx->buf, blocksize);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int qce_import_common(struct ahash_request *req, u64 in_count,
+			     const u32 *state, const u8 *buffer, bool hmac)
+{
+	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	unsigned int digestsize = crypto_ahash_digestsize(ahash);
+	unsigned int blocksize;
+	u64 count = in_count;
+
+	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
+	rctx->count = in_count;
+	memcpy(rctx->buf, buffer, blocksize);
+
+	if (in_count <= blocksize) {
+		rctx->first_blk = 1;
+	} else {
+		rctx->first_blk = 0;
+		/*
+		 * For HMAC, there is a hardware padding done when first block
+		 * is set. Therefore the byte_count must be incremened by 64
+		 * after the first block operation.
+		 */
+		if (hmac)
+			count += SHA_PADDING;
+	}
+
+	rctx->byte_count[0] = (__force __be32)(count & ~SHA_PADDING_MASK);
+	rctx->byte_count[1] = (__force __be32)(count >> 32);
+	qce_cpu_to_be32p_array((__be32 *)rctx->digest, (const u8 *)state,
+			       digestsize);
+	rctx->buflen = (unsigned int)(in_count & (blocksize - 1));
+
+	return 0;
+}
+
+static int qce_ahash_import(struct ahash_request *req, const void *in)
+{
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	unsigned long flags = rctx->flags;
+	bool hmac = IS_SHA_HMAC(flags);
+	int ret = -EINVAL;
+
+	if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
+		const struct sha1_state *state = in;
+
+		ret = qce_import_common(req, state->count, state->state,
+					state->buffer, hmac);
+	} else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
+		const struct sha256_state *state = in;
+
+		ret = qce_import_common(req, state->count, state->state,
+					state->buf, hmac);
+	}
+
+	return ret;
+}
+
+static int qce_ahash_update(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+	struct qce_device *qce = tmpl->qce;
+	struct scatterlist *sg_last, *sg;
+	unsigned int total, len;
+	unsigned int hash_later;
+	unsigned int nbytes;
+	unsigned int blocksize;
+
+	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+	rctx->count += req->nbytes;
+
+	/* check for buffer from previous updates and append it */
+	total = req->nbytes + rctx->buflen;
+
+	if (total <= blocksize) {
+		scatterwalk_map_and_copy(rctx->buf + rctx->buflen, req->src,
+					 0, req->nbytes, 0);
+		rctx->buflen += req->nbytes;
+		return 0;
+	}
+
+	/* save the original req structure fields */
+	rctx->src_orig = req->src;
+	rctx->nbytes_orig = req->nbytes;
+
+	/*
+	 * if we have data from previous update copy them on buffer. The old
+	 * data will be combined with current request bytes.
+	 */
+	if (rctx->buflen)
+		memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
+
+	/* calculate how many bytes will be hashed later */
+	hash_later = total % blocksize;
+	if (hash_later) {
+		unsigned int src_offset = req->nbytes - hash_later;
+		scatterwalk_map_and_copy(rctx->buf, req->src, src_offset,
+					 hash_later, 0);
+	}
+
+	/* here nbytes is multiple of blocksize */
+	nbytes = total - hash_later;
+
+	len = rctx->buflen;
+	sg = sg_last = req->src;
+
+	while (len < nbytes && sg) {
+		if (len + sg_dma_len(sg) > nbytes)
+			break;
+		len += sg_dma_len(sg);
+		sg_last = sg;
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	if (!sg_last)
+		return -EINVAL;
+
+	sg_mark_end(sg_last);
+
+	if (rctx->buflen) {
+		sg_init_table(rctx->sg, 2);
+		sg_set_buf(rctx->sg, rctx->tmpbuf, rctx->buflen);
+		scatterwalk_sg_chain(rctx->sg, 2, req->src);
+		req->src = rctx->sg;
+	}
+
+	req->nbytes = nbytes;
+	rctx->buflen = hash_later;
+
+	return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ahash_final(struct ahash_request *req)
+{
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+	struct qce_device *qce = tmpl->qce;
+
+	if (!rctx->buflen)
+		return 0;
+
+	rctx->last_blk = true;
+
+	rctx->src_orig = req->src;
+	rctx->nbytes_orig = req->nbytes;
+
+	memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
+	sg_init_one(rctx->sg, rctx->tmpbuf, rctx->buflen);
+
+	req->src = rctx->sg;
+	req->nbytes = rctx->buflen;
+
+	return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ahash_digest(struct ahash_request *req)
+{
+	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+	struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+	struct qce_device *qce = tmpl->qce;
+	int ret;
+
+	ret = qce_ahash_init(req);
+	if (ret)
+		return ret;
+
+	rctx->src_orig = req->src;
+	rctx->nbytes_orig = req->nbytes;
+	rctx->first_blk = true;
+	rctx->last_blk = true;
+
+	return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+struct qce_ahash_result {
+	struct completion completion;
+	int error;
+};
+
+static void qce_digest_complete(struct crypto_async_request *req, int error)
+{
+	struct qce_ahash_result *result = req->data;
+
+	if (error == -EINPROGRESS)
+		return;
+
+	result->error = error;
+	complete(&result->completion);
+}
+
+static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
+				 unsigned int keylen)
+{
+	unsigned int digestsize = crypto_ahash_digestsize(tfm);
+	struct qce_sha_ctx *ctx = crypto_tfm_ctx(&tfm->base);
+	struct qce_ahash_result result;
+	struct ahash_request *req;
+	struct scatterlist sg;
+	unsigned int blocksize;
+	struct crypto_ahash *ahash_tfm;
+	u8 *buf;
+	int ret;
+	const char *alg_name;
+
+	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+	memset(ctx->authkey, 0, sizeof(ctx->authkey));
+
+	if (keylen <= blocksize) {
+		memcpy(ctx->authkey, key, keylen);
+		return 0;
+	}
+
+	if (digestsize == SHA1_DIGEST_SIZE)
+		alg_name = "sha1-qce";
+	else if (digestsize == SHA256_DIGEST_SIZE)
+		alg_name = "sha256-qce";
+	else
+		return -EINVAL;
+
+	ahash_tfm = crypto_alloc_ahash(alg_name, CRYPTO_ALG_TYPE_AHASH,
+				       CRYPTO_ALG_TYPE_AHASH_MASK);
+	if (IS_ERR(ahash_tfm))
+		return PTR_ERR(ahash_tfm);
+
+	req = ahash_request_alloc(ahash_tfm, GFP_KERNEL);
+	if (!req) {
+		ret = -ENOMEM;
+		goto err_free_ahash;
+	}
+
+	init_completion(&result.completion);
+	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				   qce_digest_complete, &result);
+	crypto_ahash_clear_flags(ahash_tfm, ~0);
+
+	buf = kzalloc(keylen + QCE_MAX_ALIGN_SIZE, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err_free_req;
+	}
+
+	memcpy(buf, key, keylen);
+	sg_init_one(&sg, buf, keylen);
+	ahash_request_set_crypt(req, &sg, ctx->authkey, keylen);
+
+	ret = crypto_ahash_digest(req);
+	if (ret == -EINPROGRESS || ret == -EBUSY) {
+		ret = wait_for_completion_interruptible(&result.completion);
+		if (!ret)
+			ret = result.error;
+	}
+
+	if (ret)
+		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+	kfree(buf);
+err_free_req:
+	ahash_request_free(req);
+err_free_ahash:
+	crypto_free_ahash(ahash_tfm);
+	return ret;
+}
+
+static int qce_ahash_cra_init(struct crypto_tfm *tfm)
+{
+	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+	struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_ahash_set_reqsize(ahash, sizeof(struct qce_sha_reqctx));
+	memset(ctx, 0, sizeof(*ctx));
+	return 0;
+}
+
+struct qce_ahash_def {
+	unsigned long flags;
+	const char *name;
+	const char *drv_name;
+	unsigned int digestsize;
+	unsigned int blocksize;
+	unsigned int statesize;
+	const u32 *std_iv;
+};
+
+static const struct qce_ahash_def ahash_def[] = {
+	{
+		.flags		= QCE_HASH_SHA1,
+		.name		= "sha1",
+		.drv_name	= "sha1-qce",
+		.digestsize	= SHA1_DIGEST_SIZE,
+		.blocksize	= SHA1_BLOCK_SIZE,
+		.statesize	= sizeof(struct sha1_state),
+		.std_iv		= std_iv_sha1,
+	},
+	{
+		.flags		= QCE_HASH_SHA256,
+		.name		= "sha256",
+		.drv_name	= "sha256-qce",
+		.digestsize	= SHA256_DIGEST_SIZE,
+		.blocksize	= SHA256_BLOCK_SIZE,
+		.statesize	= sizeof(struct sha256_state),
+		.std_iv		= std_iv_sha256,
+	},
+	{
+		.flags		= QCE_HASH_SHA1_HMAC,
+		.name		= "hmac(sha1)",
+		.drv_name	= "hmac-sha1-qce",
+		.digestsize	= SHA1_DIGEST_SIZE,
+		.blocksize	= SHA1_BLOCK_SIZE,
+		.statesize	= sizeof(struct sha1_state),
+		.std_iv		= std_iv_sha1,
+	},
+	{
+		.flags		= QCE_HASH_SHA256_HMAC,
+		.name		= "hmac(sha256)",
+		.drv_name	= "hmac-sha256-qce",
+		.digestsize	= SHA256_DIGEST_SIZE,
+		.blocksize	= SHA256_BLOCK_SIZE,
+		.statesize	= sizeof(struct sha256_state),
+		.std_iv		= std_iv_sha256,
+	},
+};
+
+static int qce_ahash_register_one(const struct qce_ahash_def *def,
+				  struct qce_device *qce)
+{
+	struct qce_alg_template *tmpl;
+	struct ahash_alg *alg;
+	struct crypto_alg *base;
+	int ret;
+
+	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+	if (!tmpl)
+		return -ENOMEM;
+
+	tmpl->std_iv = def->std_iv;
+
+	alg = &tmpl->alg.ahash;
+	alg->init = qce_ahash_init;
+	alg->update = qce_ahash_update;
+	alg->final = qce_ahash_final;
+	alg->digest = qce_ahash_digest;
+	alg->export = qce_ahash_export;
+	alg->import = qce_ahash_import;
+	if (IS_SHA_HMAC(def->flags))
+		alg->setkey = qce_ahash_hmac_setkey;
+	alg->halg.digestsize = def->digestsize;
+	alg->halg.statesize = def->statesize;
+
+	base = &alg->halg.base;
+	base->cra_blocksize = def->blocksize;
+	base->cra_priority = 300;
+	base->cra_flags = CRYPTO_ALG_ASYNC;
+	base->cra_ctxsize = sizeof(struct qce_sha_ctx);
+	base->cra_alignmask = 0;
+	base->cra_module = THIS_MODULE;
+	base->cra_init = qce_ahash_cra_init;
+	INIT_LIST_HEAD(&base->cra_list);
+
+	snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->drv_name);
+
+	INIT_LIST_HEAD(&tmpl->entry);
+	tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_AHASH;
+	tmpl->alg_flags = def->flags;
+	tmpl->qce = qce;
+
+	ret = crypto_register_ahash(alg);
+	if (ret) {
+		kfree(tmpl);
+		dev_err(qce->dev, "%s registration failed\n", base->cra_name);
+		return ret;
+	}
+
+	list_add_tail(&tmpl->entry, &ahash_algs);
+	dev_dbg(qce->dev, "%s is registered\n", base->cra_name);
+	return 0;
+}
+
+static void qce_ahash_unregister(struct qce_device *qce)
+{
+	struct qce_alg_template *tmpl, *n;
+
+	list_for_each_entry_safe(tmpl, n, &ahash_algs, entry) {
+		crypto_unregister_ahash(&tmpl->alg.ahash);
+		list_del(&tmpl->entry);
+		kfree(tmpl);
+	}
+}
+
+static int qce_ahash_register(struct qce_device *qce)
+{
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(ahash_def); i++) {
+		ret = qce_ahash_register_one(&ahash_def[i], qce);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+err:
+	qce_ahash_unregister(qce);
+	return ret;
+}
+
+const struct qce_algo_ops ahash_ops = {
+	.type = CRYPTO_ALG_TYPE_AHASH,
+	.register_algs = qce_ahash_register,
+	.unregister_algs = qce_ahash_unregister,
+	.async_req_handle = qce_ahash_async_req_handle,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/qce/sha.h linux-libre-3.17-rc7-gnu/drivers/crypto/qce/sha.h
--- linux-libre-3.16-gnu/drivers/crypto/qce/sha.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/qce/sha.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010-2014, 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 _SHA_H_
+#define _SHA_H_
+
+#include <crypto/scatterwalk.h>
+#include <crypto/sha.h>
+
+#include "common.h"
+#include "core.h"
+
+#define QCE_SHA_MAX_BLOCKSIZE		SHA256_BLOCK_SIZE
+#define QCE_SHA_MAX_DIGESTSIZE		SHA256_DIGEST_SIZE
+
+struct qce_sha_ctx {
+	u8 authkey[QCE_SHA_MAX_BLOCKSIZE];
+};
+
+/**
+ * struct qce_sha_reqctx - holds private ahash objects per request
+ * @buf: used during update, import and export
+ * @tmpbuf: buffer for internal use
+ * @digest: calculated digest buffer
+ * @buflen: length of the buffer
+ * @flags: operation flags
+ * @src_orig: original request sg list
+ * @nbytes_orig: original request number of bytes
+ * @src_chained: is source scatterlist chained
+ * @src_nents: source number of entries
+ * @byte_count: byte count
+ * @count: save count in states during update, import and export
+ * @first_blk: is it the first block
+ * @last_blk: is it the last block
+ * @sg: used to chain sg lists
+ * @authkey: pointer to auth key in sha ctx
+ * @authklen: auth key length
+ * @result_sg: scatterlist used for result buffer
+ */
+struct qce_sha_reqctx {
+	u8 buf[QCE_SHA_MAX_BLOCKSIZE];
+	u8 tmpbuf[QCE_SHA_MAX_BLOCKSIZE];
+	u8 digest[QCE_SHA_MAX_DIGESTSIZE];
+	unsigned int buflen;
+	unsigned long flags;
+	struct scatterlist *src_orig;
+	unsigned int nbytes_orig;
+	bool src_chained;
+	int src_nents;
+	__be32 byte_count[2];
+	u64 count;
+	bool first_blk;
+	bool last_blk;
+	struct scatterlist sg[2];
+	u8 *authkey;
+	unsigned int authklen;
+	struct scatterlist result_sg;
+};
+
+static inline struct qce_alg_template *to_ahash_tmpl(struct crypto_tfm *tfm)
+{
+	struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+	struct ahash_alg *alg = container_of(crypto_hash_alg_common(ahash),
+					     struct ahash_alg, halg);
+
+	return container_of(alg, struct qce_alg_template, alg.ahash);
+}
+
+extern const struct qce_algo_ops ahash_ops;
+
+#endif /* _SHA_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/crypto/ux500/cryp/cryp_core.c linux-libre-3.17-rc7-gnu/drivers/crypto/ux500/cryp/cryp_core.c
--- linux-libre-3.16-gnu/drivers/crypto/ux500/cryp/cryp_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/crypto/ux500/cryp/cryp_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,7 +190,7 @@ static void add_session_id(struct cryp_c
 static irqreturn_t cryp_interrupt_handler(int irq, void *param)
 {
 	struct cryp_ctx *ctx;
-	int i;
+	int count;
 	struct cryp_device_data *device_data;
 
 	if (param == NULL) {
@@ -215,12 +215,11 @@ static irqreturn_t cryp_interrupt_handle
 	if (cryp_pending_irq_src(device_data,
 				 CRYP_IRQ_SRC_OUTPUT_FIFO)) {
 		if (ctx->outlen / ctx->blocksize > 0) {
-			for (i = 0; i < ctx->blocksize / 4; i++) {
-				*(ctx->outdata) = readl_relaxed(
-						&device_data->base->dout);
-				ctx->outdata += 4;
-				ctx->outlen -= 4;
-			}
+			count = ctx->blocksize / 4;
+
+			readsl(&device_data->base->dout, ctx->outdata, count);
+			ctx->outdata += count;
+			ctx->outlen -= count;
 
 			if (ctx->outlen == 0) {
 				cryp_disable_irq_src(device_data,
@@ -230,12 +229,12 @@ static irqreturn_t cryp_interrupt_handle
 	} else if (cryp_pending_irq_src(device_data,
 					CRYP_IRQ_SRC_INPUT_FIFO)) {
 		if (ctx->datalen / ctx->blocksize > 0) {
-			for (i = 0 ; i < ctx->blocksize / 4; i++) {
-				writel_relaxed(ctx->indata,
-						&device_data->base->din);
-				ctx->indata += 4;
-				ctx->datalen -= 4;
-			}
+			count = ctx->blocksize / 4;
+
+			writesl(&device_data->base->din, ctx->indata, count);
+
+			ctx->indata += count;
+			ctx->datalen -= count;
 
 			if (ctx->datalen == 0)
 				cryp_disable_irq_src(device_data,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/devfreq/Kconfig linux-libre-3.17-rc7-gnu/drivers/devfreq/Kconfig
--- linux-libre-3.16-gnu/drivers/devfreq/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/devfreq/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,6 @@ comment "DEVFREQ Drivers"
 config ARM_EXYNOS4_BUS_DEVFREQ
 	bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver"
 	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
-	select ARCH_HAS_OPP
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
 	select PM_OPP
 	help
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/amba-pl08x.c linux-libre-3.17-rc7-gnu/drivers/dma/amba-pl08x.c
--- linux-libre-3.16-gnu/drivers/dma/amba-pl08x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/amba-pl08x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1040,7 +1040,7 @@ static int pl08x_fill_llis_for_desc(stru
 
 		if (early_bytes) {
 			dev_vdbg(&pl08x->adev->dev,
-				"%s byte width LLIs (remain 0x%08x)\n",
+				"%s byte width LLIs (remain 0x%08zx)\n",
 				__func__, bd.remainder);
 			prep_byte_width_lli(pl08x, &bd, &cctl, early_bytes,
 				num_llis++, &total_bytes);
@@ -1653,7 +1653,7 @@ static struct dma_async_tx_descriptor *p
 static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
@@ -1662,7 +1662,7 @@ static struct dma_async_tx_descriptor *p
 	dma_addr_t slave_addr;
 
 	dev_dbg(&pl08x->adev->dev,
-		"%s prepare cyclic transaction of %d/%d bytes %s %s\n",
+		"%s prepare cyclic transaction of %zd/%zd bytes %s %s\n",
 		__func__, period_len, buf_len,
 		direction == DMA_MEM_TO_DEV ? "to" : "from",
 		plchan->name);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/at_hdmac.c linux-libre-3.17-rc7-gnu/drivers/dma/at_hdmac.c
--- linux-libre-3.16-gnu/drivers/dma/at_hdmac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/at_hdmac.c	2014-09-28 17:29:07.000000000 -0400
@@ -294,14 +294,16 @@ static int atc_get_bytes_left(struct dma
 			ret = -EINVAL;
 			goto out;
 		}
-		atchan->remain_desc -= (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
-						<< (desc_first->tx_width);
-		if (atchan->remain_desc < 0) {
+
+		count = (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
+			<< desc_first->tx_width;
+		if (atchan->remain_desc < count) {
 			ret = -EINVAL;
 			goto out;
-		} else {
-			ret = atchan->remain_desc;
 		}
+
+		atchan->remain_desc -= count;
+		ret = atchan->remain_desc;
 	} else {
 		/*
 		 * Get residual bytes when current
@@ -893,12 +895,11 @@ atc_dma_cyclic_fill_desc(struct dma_chan
  * @period_len: number of bytes for each period
  * @direction: transfer direction, to or from device
  * @flags: tx descriptor status flags
- * @context: transfer context (ignored)
  */
 static struct dma_async_tx_descriptor *
 atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	struct at_dma_slave	*atslave = chan->private;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/bcm2835-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/bcm2835-dma.c
--- linux-libre-3.16-gnu/drivers/dma/bcm2835-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/bcm2835-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -335,7 +335,7 @@ static void bcm2835_dma_issue_pending(st
 static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags, void *context)
+	unsigned long flags)
 {
 	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
 	enum dma_slave_buswidth dev_width;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/dma-jz4740.c linux-libre-3.17-rc7-gnu/drivers/dma/dma-jz4740.c
--- linux-libre-3.16-gnu/drivers/dma/dma-jz4740.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/dma-jz4740.c	2014-09-28 17:29:07.000000000 -0400
@@ -362,8 +362,9 @@ static void jz4740_dma_chan_irq(struct j
 			vchan_cyclic_callback(&chan->desc->vdesc);
 		} else {
 			if (chan->next_sg == chan->desc->num_sgs) {
-				chan->desc = NULL;
+				list_del(&chan->desc->vdesc.node);
 				vchan_cookie_complete(&chan->desc->vdesc);
+				chan->desc = NULL;
 			}
 		}
 	}
@@ -433,7 +434,7 @@ static struct dma_async_tx_descriptor *j
 static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic(
 	struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags, void *context)
+	unsigned long flags)
 {
 	struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
 	struct jz4740_dma_desc *desc;
@@ -614,4 +615,4 @@ module_platform_driver(jz4740_dma_driver
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("JZ4740 DMA driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/dw/core.c linux-libre-3.17-rc7-gnu/drivers/dma/dw/core.c
--- linux-libre-3.16-gnu/drivers/dma/dw/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/dw/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -279,6 +279,19 @@ static void dwc_dostart(struct dw_dma_ch
 	channel_set_bit(dw, CH_EN, dwc->mask);
 }
 
+static void dwc_dostart_first_queued(struct dw_dma_chan *dwc)
+{
+	struct dw_desc *desc;
+
+	if (list_empty(&dwc->queue))
+		return;
+
+	list_move(dwc->queue.next, &dwc->active_list);
+	desc = dwc_first_active(dwc);
+	dev_vdbg(chan2dev(&dwc->chan), "%s: started %u\n", __func__, desc->txd.cookie);
+	dwc_dostart(dwc, desc);
+}
+
 /*----------------------------------------------------------------------*/
 
 static void
@@ -335,10 +348,7 @@ static void dwc_complete_all(struct dw_d
 	 * the completed ones.
 	 */
 	list_splice_init(&dwc->active_list, &list);
-	if (!list_empty(&dwc->queue)) {
-		list_move(dwc->queue.next, &dwc->active_list);
-		dwc_dostart(dwc, dwc_first_active(dwc));
-	}
+	dwc_dostart_first_queued(dwc);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -467,10 +477,7 @@ static void dwc_scan_descriptors(struct
 	/* Try to continue after resetting the channel... */
 	dwc_chan_disable(dw, dwc);
 
-	if (!list_empty(&dwc->queue)) {
-		list_move(dwc->queue.next, &dwc->active_list);
-		dwc_dostart(dwc, dwc_first_active(dwc));
-	}
+	dwc_dostart_first_queued(dwc);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
@@ -677,17 +684,9 @@ static dma_cookie_t dwc_tx_submit(struct
 	 * possible, perhaps even appending to those already submitted
 	 * for DMA. But this is hard to do in a race-free manner.
 	 */
-	if (list_empty(&dwc->active_list)) {
-		dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__,
-				desc->txd.cookie);
-		list_add_tail(&desc->desc_node, &dwc->active_list);
-		dwc_dostart(dwc, dwc_first_active(dwc));
-	} else {
-		dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__,
-				desc->txd.cookie);
 
-		list_add_tail(&desc->desc_node, &dwc->queue);
-	}
+	dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie);
+	list_add_tail(&desc->desc_node, &dwc->queue);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1092,9 +1091,12 @@ dwc_tx_status(struct dma_chan *chan,
 static void dwc_issue_pending(struct dma_chan *chan)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	unsigned long		flags;
 
-	if (!list_empty(&dwc->queue))
-		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+	spin_lock_irqsave(&dwc->lock, flags);
+	if (list_empty(&dwc->active_list))
+		dwc_dostart_first_queued(dwc);
+	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
 static int dwc_alloc_chan_resources(struct dma_chan *chan)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/edma.c linux-libre-3.17-rc7-gnu/drivers/dma/edma.c
--- linux-libre-3.16-gnu/drivers/dma/edma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/edma.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/of.h>
 
 #include <linux/platform_data/edma.h>
 
@@ -256,8 +257,13 @@ static int edma_terminate_all(struct edm
 	 * echan->edesc is NULL and exit.)
 	 */
 	if (echan->edesc) {
+		int cyclic = echan->edesc->cyclic;
 		echan->edesc = NULL;
 		edma_stop(echan->ch_num);
+		/* Move the cyclic channel back to default queue */
+		if (cyclic)
+			edma_assign_channel_eventq(echan->ch_num,
+						   EVENTQ_DEFAULT);
 	}
 
 	vchan_get_all_descriptors(&echan->vchan, &head);
@@ -592,7 +598,7 @@ struct dma_async_tx_descriptor *edma_pre
 static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long tx_flags, void *context)
+	unsigned long tx_flags)
 {
 	struct edma_chan *echan = to_edma_chan(chan);
 	struct device *dev = chan->device->dev;
@@ -718,12 +724,15 @@ static struct dma_async_tx_descriptor *e
 		edesc->absync = ret;
 
 		/*
-		 * Enable interrupts for every period because callback
-		 * has to be called for every period.
+		 * Enable period interrupt only if it is requested
 		 */
-		edesc->pset[i].param.opt |= TCINTEN;
+		if (tx_flags & DMA_PREP_INTERRUPT)
+			edesc->pset[i].param.opt |= TCINTEN;
 	}
 
+	/* Place the cyclic channel to highest priority queue */
+	edma_assign_channel_eventq(echan->ch_num, EVENTQ_0);
+
 	return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
 }
 
@@ -982,6 +991,7 @@ static void __init edma_chan_init(struct
 
 #define EDMA_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 int edma_dma_device_slave_caps(struct dma_chan *dchan,
@@ -992,7 +1002,7 @@ static int edma_dma_device_slave_caps(st
 	caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
 	caps->cmd_pause = true;
 	caps->cmd_terminate = true;
-	caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+	caps->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
 
 	return 0;
 }
@@ -1039,7 +1049,7 @@ static int edma_probe(struct platform_de
 	ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
 	if (ecc->dummy_slot < 0) {
 		dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
-		return -EIO;
+		return ecc->dummy_slot;
 	}
 
 	dma_cap_zero(ecc->dma_slave.cap_mask);
@@ -1124,7 +1134,7 @@ static int edma_init(void)
 		}
 	}
 
-	if (EDMA_CTLRS == 2) {
+	if (!of_have_populated_dt() && EDMA_CTLRS == 2) {
 		pdev1 = platform_device_register_full(&edma_dev_info1);
 		if (IS_ERR(pdev1)) {
 			platform_driver_unregister(&edma_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/ep93xx_dma.c linux-libre-3.17-rc7-gnu/drivers/dma/ep93xx_dma.c
--- linux-libre-3.16-gnu/drivers/dma/ep93xx_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/ep93xx_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -1092,7 +1092,6 @@ fail:
  * @period_len: length of a single period
  * @dir: direction of the operation
  * @flags: tx descriptor status flags
- * @context: operation context (ignored)
  *
  * Prepares a descriptor for cyclic DMA operation. This means that once the
  * descriptor is submitted, we will be submitting in a @period_len sized
@@ -1105,8 +1104,7 @@ fail:
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
 			   size_t buf_len, size_t period_len,
-			   enum dma_transfer_direction dir, unsigned long flags,
-			   void *context)
+			   enum dma_transfer_direction dir, unsigned long flags)
 {
 	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
 	struct ep93xx_dma_desc *desc, *first;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/fsldma.c linux-libre-3.17-rc7-gnu/drivers/dma/fsldma.c
--- linux-libre-3.16-gnu/drivers/dma/fsldma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/fsldma.c	2014-09-28 17:29:07.000000000 -0400
@@ -396,10 +396,17 @@ static dma_cookie_t fsl_dma_tx_submit(st
 	struct fsldma_chan *chan = to_fsl_chan(tx->chan);
 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
 	struct fsl_desc_sw *child;
-	unsigned long flags;
 	dma_cookie_t cookie = -EINVAL;
 
-	spin_lock_irqsave(&chan->desc_lock, flags);
+	spin_lock_bh(&chan->desc_lock);
+
+#ifdef CONFIG_PM
+	if (unlikely(chan->pm_state != RUNNING)) {
+		chan_dbg(chan, "cannot submit due to suspend\n");
+		spin_unlock_bh(&chan->desc_lock);
+		return -1;
+	}
+#endif
 
 	/*
 	 * assign cookies to all of the software descriptors
@@ -412,7 +419,7 @@ static dma_cookie_t fsl_dma_tx_submit(st
 	/* put this transaction onto the tail of the pending queue */
 	append_ld_queue(chan, desc);
 
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+	spin_unlock_bh(&chan->desc_lock);
 
 	return cookie;
 }
@@ -459,6 +466,88 @@ static struct fsl_desc_sw *fsl_dma_alloc
 }
 
 /**
+ * fsldma_clean_completed_descriptor - free all descriptors which
+ * has been completed and acked
+ * @chan: Freescale DMA channel
+ *
+ * This function is used on all completed and acked descriptors.
+ * All descriptors should only be freed in this function.
+ */
+static void fsldma_clean_completed_descriptor(struct fsldma_chan *chan)
+{
+	struct fsl_desc_sw *desc, *_desc;
+
+	/* Run the callback for each descriptor, in order */
+	list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node)
+		if (async_tx_test_ack(&desc->async_tx))
+			fsl_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * fsldma_run_tx_complete_actions - cleanup a single link descriptor
+ * @chan: Freescale DMA channel
+ * @desc: descriptor to cleanup and free
+ * @cookie: Freescale DMA transaction identifier
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies.
+ */
+static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
+		struct fsl_desc_sw *desc, dma_cookie_t cookie)
+{
+	struct dma_async_tx_descriptor *txd = &desc->async_tx;
+	dma_cookie_t ret = cookie;
+
+	BUG_ON(txd->cookie < 0);
+
+	if (txd->cookie > 0) {
+		ret = txd->cookie;
+
+		/* Run the link descriptor callback function */
+		if (txd->callback) {
+			chan_dbg(chan, "LD %p callback\n", desc);
+			txd->callback(txd->callback_param);
+		}
+	}
+
+	/* Run any dependencies */
+	dma_run_dependencies(txd);
+
+	return ret;
+}
+
+/**
+ * fsldma_clean_running_descriptor - move the completed descriptor from
+ * ld_running to ld_completed
+ * @chan: Freescale DMA channel
+ * @desc: the descriptor which is completed
+ *
+ * Free the descriptor directly if acked by async_tx api, or move it to
+ * queue ld_completed.
+ */
+static void fsldma_clean_running_descriptor(struct fsldma_chan *chan,
+		struct fsl_desc_sw *desc)
+{
+	/* Remove from the list of transactions */
+	list_del(&desc->node);
+
+	/*
+	 * the client is allowed to attach dependent operations
+	 * until 'ack' is set
+	 */
+	if (!async_tx_test_ack(&desc->async_tx)) {
+		/*
+		 * Move this descriptor to the list of descriptors which is
+		 * completed, but still awaiting the 'ack' bit to be set.
+		 */
+		list_add_tail(&desc->node, &chan->ld_completed);
+		return;
+	}
+
+	dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
+/**
  * fsl_chan_xfer_ld_queue - transfer any pending transactions
  * @chan : Freescale DMA channel
  *
@@ -526,31 +615,58 @@ static void fsl_chan_xfer_ld_queue(struc
 }
 
 /**
- * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
+ * fsldma_cleanup_descriptors - cleanup link descriptors which are completed
+ * and move them to ld_completed to free until flag 'ack' is set
  * @chan: Freescale DMA channel
- * @desc: descriptor to cleanup and free
  *
- * This function is used on a descriptor which has been executed by the DMA
- * controller. It will run any callbacks, submit any dependencies, and then
- * free the descriptor.
+ * This function is used on descriptors which have been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, then
+ * free these descriptors if flag 'ack' is set.
  */
-static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
-				      struct fsl_desc_sw *desc)
+static void fsldma_cleanup_descriptors(struct fsldma_chan *chan)
 {
-	struct dma_async_tx_descriptor *txd = &desc->async_tx;
+	struct fsl_desc_sw *desc, *_desc;
+	dma_cookie_t cookie = 0;
+	dma_addr_t curr_phys = get_cdar(chan);
+	int seen_current = 0;
 
-	/* Run the link descriptor callback function */
-	if (txd->callback) {
-		chan_dbg(chan, "LD %p callback\n", desc);
-		txd->callback(txd->callback_param);
+	fsldma_clean_completed_descriptor(chan);
+
+	/* Run the callback for each descriptor, in order */
+	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+		/*
+		 * do not advance past the current descriptor loaded into the
+		 * hardware channel, subsequent descriptors are either in
+		 * process or have not been submitted
+		 */
+		if (seen_current)
+			break;
+
+		/*
+		 * stop the search if we reach the current descriptor and the
+		 * channel is busy
+		 */
+		if (desc->async_tx.phys == curr_phys) {
+			seen_current = 1;
+			if (!dma_is_idle(chan))
+				break;
+		}
+
+		cookie = fsldma_run_tx_complete_actions(chan, desc, cookie);
+
+		fsldma_clean_running_descriptor(chan, desc);
 	}
 
-	/* Run any dependencies */
-	dma_run_dependencies(txd);
+	/*
+	 * Start any pending transactions automatically
+	 *
+	 * In the ideal case, we keep the DMA controller busy while we go
+	 * ahead and free the descriptors below.
+	 */
+	fsl_chan_xfer_ld_queue(chan);
 
-	dma_descriptor_unmap(txd);
-	chan_dbg(chan, "LD %p free\n", desc);
-	dma_pool_free(chan->desc_pool, desc, txd->phys);
+	if (cookie > 0)
+		chan->common.completed_cookie = cookie;
 }
 
 /**
@@ -617,13 +733,14 @@ static void fsldma_free_desc_list_revers
 static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
-	unsigned long flags;
 
 	chan_dbg(chan, "free all channel resources\n");
-	spin_lock_irqsave(&chan->desc_lock, flags);
+	spin_lock_bh(&chan->desc_lock);
+	fsldma_cleanup_descriptors(chan);
 	fsldma_free_desc_list(chan, &chan->ld_pending);
 	fsldma_free_desc_list(chan, &chan->ld_running);
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+	fsldma_free_desc_list(chan, &chan->ld_completed);
+	spin_unlock_bh(&chan->desc_lock);
 
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
@@ -842,7 +959,6 @@ static int fsl_dma_device_control(struct
 {
 	struct dma_slave_config *config;
 	struct fsldma_chan *chan;
-	unsigned long flags;
 	int size;
 
 	if (!dchan)
@@ -852,7 +968,7 @@ static int fsl_dma_device_control(struct
 
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
-		spin_lock_irqsave(&chan->desc_lock, flags);
+		spin_lock_bh(&chan->desc_lock);
 
 		/* Halt the DMA engine */
 		dma_halt(chan);
@@ -860,9 +976,10 @@ static int fsl_dma_device_control(struct
 		/* Remove and free all of the descriptors in the LD queue */
 		fsldma_free_desc_list(chan, &chan->ld_pending);
 		fsldma_free_desc_list(chan, &chan->ld_running);
+		fsldma_free_desc_list(chan, &chan->ld_completed);
 		chan->idle = true;
 
-		spin_unlock_irqrestore(&chan->desc_lock, flags);
+		spin_unlock_bh(&chan->desc_lock);
 		return 0;
 
 	case DMA_SLAVE_CONFIG:
@@ -904,11 +1021,10 @@ static int fsl_dma_device_control(struct
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chan->desc_lock, flags);
+	spin_lock_bh(&chan->desc_lock);
 	fsl_chan_xfer_ld_queue(chan);
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+	spin_unlock_bh(&chan->desc_lock);
 }
 
 /**
@@ -919,6 +1035,17 @@ static enum dma_status fsl_tx_status(str
 					dma_cookie_t cookie,
 					struct dma_tx_state *txstate)
 {
+	struct fsldma_chan *chan = to_fsl_chan(dchan);
+	enum dma_status ret;
+
+	ret = dma_cookie_status(dchan, cookie, txstate);
+	if (ret == DMA_COMPLETE)
+		return ret;
+
+	spin_lock_bh(&chan->desc_lock);
+	fsldma_cleanup_descriptors(chan);
+	spin_unlock_bh(&chan->desc_lock);
+
 	return dma_cookie_status(dchan, cookie, txstate);
 }
 
@@ -996,52 +1123,18 @@ static irqreturn_t fsldma_chan_irq(int i
 static void dma_do_tasklet(unsigned long data)
 {
 	struct fsldma_chan *chan = (struct fsldma_chan *)data;
-	struct fsl_desc_sw *desc, *_desc;
-	LIST_HEAD(ld_cleanup);
-	unsigned long flags;
 
 	chan_dbg(chan, "tasklet entry\n");
 
-	spin_lock_irqsave(&chan->desc_lock, flags);
-
-	/* update the cookie if we have some descriptors to cleanup */
-	if (!list_empty(&chan->ld_running)) {
-		dma_cookie_t cookie;
-
-		desc = to_fsl_desc(chan->ld_running.prev);
-		cookie = desc->async_tx.cookie;
-		dma_cookie_complete(&desc->async_tx);
-
-		chan_dbg(chan, "completed_cookie=%d\n", cookie);
-	}
-
-	/*
-	 * move the descriptors to a temporary list so we can drop the lock
-	 * during the entire cleanup operation
-	 */
-	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+	spin_lock_bh(&chan->desc_lock);
 
 	/* the hardware is now idle and ready for more */
 	chan->idle = true;
 
-	/*
-	 * Start any pending transactions automatically
-	 *
-	 * In the ideal case, we keep the DMA controller busy while we go
-	 * ahead and free the descriptors below.
-	 */
-	fsl_chan_xfer_ld_queue(chan);
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
-
-	/* Run the callback for each descriptor, in order */
-	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
-
-		/* Remove from the list of transactions */
-		list_del(&desc->node);
+	/* Run all cleanup for descriptors which have been completed */
+	fsldma_cleanup_descriptors(chan);
 
-		/* Run all cleanup for this descriptor */
-		fsldma_cleanup_descriptor(chan, desc);
-	}
+	spin_unlock_bh(&chan->desc_lock);
 
 	chan_dbg(chan, "tasklet exit\n");
 }
@@ -1225,7 +1318,11 @@ static int fsl_dma_chan_probe(struct fsl
 	spin_lock_init(&chan->desc_lock);
 	INIT_LIST_HEAD(&chan->ld_pending);
 	INIT_LIST_HEAD(&chan->ld_running);
+	INIT_LIST_HEAD(&chan->ld_completed);
 	chan->idle = true;
+#ifdef CONFIG_PM
+	chan->pm_state = RUNNING;
+#endif
 
 	chan->common.device = &fdev->common;
 	dma_cookie_init(&chan->common);
@@ -1365,6 +1462,69 @@ static int fsldma_of_remove(struct platf
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int fsldma_suspend_late(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fsldma_device *fdev = platform_get_drvdata(pdev);
+	struct fsldma_chan *chan;
+	int i;
+
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
+
+		spin_lock_bh(&chan->desc_lock);
+		if (unlikely(!chan->idle))
+			goto out;
+		chan->regs_save.mr = get_mr(chan);
+		chan->pm_state = SUSPENDED;
+		spin_unlock_bh(&chan->desc_lock);
+	}
+	return 0;
+
+out:
+	for (; i >= 0; i--) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
+		chan->pm_state = RUNNING;
+		spin_unlock_bh(&chan->desc_lock);
+	}
+	return -EBUSY;
+}
+
+static int fsldma_resume_early(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fsldma_device *fdev = platform_get_drvdata(pdev);
+	struct fsldma_chan *chan;
+	u32 mode;
+	int i;
+
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
+
+		spin_lock_bh(&chan->desc_lock);
+		mode = chan->regs_save.mr
+			& ~FSL_DMA_MR_CS & ~FSL_DMA_MR_CC & ~FSL_DMA_MR_CA;
+		set_mr(chan, mode);
+		chan->pm_state = RUNNING;
+		spin_unlock_bh(&chan->desc_lock);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops fsldma_pm_ops = {
+	.suspend_late	= fsldma_suspend_late,
+	.resume_early	= fsldma_resume_early,
+};
+#endif
+
 static const struct of_device_id fsldma_of_ids[] = {
 	{ .compatible = "fsl,elo3-dma", },
 	{ .compatible = "fsl,eloplus-dma", },
@@ -1377,6 +1537,9 @@ static struct platform_driver fsldma_of_
 		.name = "fsl-elo-dma",
 		.owner = THIS_MODULE,
 		.of_match_table = fsldma_of_ids,
+#ifdef CONFIG_PM
+		.pm = &fsldma_pm_ops,
+#endif
 	},
 	.probe = fsldma_of_probe,
 	.remove = fsldma_of_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/fsldma.h linux-libre-3.17-rc7-gnu/drivers/dma/fsldma.h
--- linux-libre-3.16-gnu/drivers/dma/fsldma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/fsldma.h	2014-09-28 17:29:07.000000000 -0400
@@ -134,12 +134,36 @@ struct fsldma_device {
 #define FSL_DMA_CHAN_PAUSE_EXT	0x00001000
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
+#ifdef CONFIG_PM
+struct fsldma_chan_regs_save {
+	u32 mr;
+};
+
+enum fsldma_pm_state {
+	RUNNING = 0,
+	SUSPENDED,
+};
+#endif
+
 struct fsldma_chan {
 	char name[8];			/* Channel name */
 	struct fsldma_chan_regs __iomem *regs;
 	spinlock_t desc_lock;		/* Descriptor operation lock */
-	struct list_head ld_pending;	/* Link descriptors queue */
-	struct list_head ld_running;	/* Link descriptors queue */
+	/*
+	 * Descriptors which are queued to run, but have not yet been
+	 * submitted to the hardware for execution
+	 */
+	struct list_head ld_pending;
+	/*
+	 * Descriptors which are currently being executed by the hardware
+	 */
+	struct list_head ld_running;
+	/*
+	 * Descriptors which have finished execution by the hardware. These
+	 * descriptors have already had their cleanup actions run. They are
+	 * waiting for the ACK bit to be set by the async_tx API.
+	 */
+	struct list_head ld_completed;	/* Link descriptors queue */
 	struct dma_chan common;		/* DMA common channel */
 	struct dma_pool *desc_pool;	/* Descriptors pool */
 	struct device *dev;		/* Channel device */
@@ -148,6 +172,10 @@ struct fsldma_chan {
 	struct tasklet_struct tasklet;
 	u32 feature;
 	bool idle;			/* DMA controller is idle */
+#ifdef CONFIG_PM
+	struct fsldma_chan_regs_save regs_save;
+	enum fsldma_pm_state pm_state;
+#endif
 
 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/fsl-edma.c linux-libre-3.17-rc7-gnu/drivers/dma/fsl-edma.c
--- linux-libre-3.16-gnu/drivers/dma/fsl-edma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/fsl-edma.c	2014-09-28 17:29:07.000000000 -0400
@@ -248,11 +248,12 @@ static void fsl_edma_chan_mux(struct fsl
 			unsigned int slot, bool enable)
 {
 	u32 ch = fsl_chan->vchan.chan.chan_id;
-	void __iomem *muxaddr = fsl_chan->edma->muxbase[ch / DMAMUX_NR];
+	void __iomem *muxaddr;
 	unsigned chans_per_mux, ch_off;
 
 	chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
 	ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
+	muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
 
 	if (enable)
 		edma_writeb(fsl_chan->edma,
@@ -516,7 +517,7 @@ err:
 static struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
 	struct fsl_edma_desc *fsl_desc;
@@ -724,6 +725,7 @@ static struct dma_chan *fsl_edma_xlate(s
 {
 	struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
 	struct dma_chan *chan, *_chan;
+	unsigned long chans_per_mux = fsl_edma->n_chans / DMAMUX_NR;
 
 	if (dma_spec->args_count != 2)
 		return NULL;
@@ -732,7 +734,7 @@ static struct dma_chan *fsl_edma_xlate(s
 	list_for_each_entry_safe(chan, _chan, &fsl_edma->dma_dev.channels, device_node) {
 		if (chan->client_count)
 			continue;
-		if ((chan->chan_id / DMAMUX_NR) == dma_spec->args[0]) {
+		if ((chan->chan_id / chans_per_mux) == dma_spec->args[0]) {
 			chan = dma_get_slave_channel(chan);
 			if (chan) {
 				chan->device->privatecnt++;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/imx-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/imx-dma.c
--- linux-libre-3.16-gnu/drivers/dma/imx-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/imx-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -866,7 +866,7 @@ static struct dma_async_tx_descriptor *i
 static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
 	struct imxdma_engine *imxdma = imxdmac->imxdma;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/imx-sdma.c linux-libre-3.17-rc7-gnu/drivers/dma/imx-sdma.c
--- linux-libre-3.16-gnu/drivers/dma/imx-sdma.c	2014-08-07 04:46:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/imx-sdma.c	2014-09-28 21:27:21.000000000 -0400
@@ -271,6 +271,7 @@ struct sdma_channel {
 	unsigned int			chn_count;
 	unsigned int			chn_real_count;
 	struct tasklet_struct		tasklet;
+	struct imx_dma_data		data;
 };
 
 #define IMX_DMA_SG_LOOP		BIT(0)
@@ -749,6 +750,11 @@ static void sdma_get_pc(struct sdma_chan
 		emi_2_per = sdma->script_addrs->asrc_2_mcu_addr;
 		per_2_per = sdma->script_addrs->per_2_per_addr;
 		break;
+	case IMX_DMATYPE_ASRC_SP:
+		per_2_emi = sdma->script_addrs->shp_2_mcu_addr;
+		emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
+		per_2_per = sdma->script_addrs->per_2_per_addr;
+		break;
 	case IMX_DMATYPE_MSHC:
 		per_2_emi = sdma->script_addrs->mshc_2_mcu_addr;
 		emi_2_per = sdma->script_addrs->mcu_2_mshc_addr;
@@ -911,14 +917,13 @@ static int sdma_request_channel(struct s
 	int channel = sdmac->channel;
 	int ret = -EBUSY;
 
-	sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL);
+	sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+					GFP_KERNEL);
 	if (!sdmac->bd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	memset(sdmac->bd, 0, PAGE_SIZE);
-
 	sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
 	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
 
@@ -1120,7 +1125,7 @@ err_out:
 static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
@@ -1414,12 +1419,14 @@ err_dma_alloc:
 
 static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
 {
+	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct imx_dma_data *data = fn_param;
 
 	if (!imx_dma_is_general_purpose(chan))
 		return false;
 
-	chan->private = data;
+	sdmac->data = *data;
+	chan->private = &sdmac->data;
 
 	return true;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/ipu/ipu_idmac.c linux-libre-3.17-rc7-gnu/drivers/dma/ipu/ipu_idmac.c
--- linux-libre-3.16-gnu/drivers/dma/ipu/ipu_idmac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/ipu/ipu_idmac.c	2014-09-28 17:29:07.000000000 -0400
@@ -1532,11 +1532,17 @@ static int idmac_alloc_chan_resources(st
 #ifdef DEBUG
 	if (chan->chan_id == IDMAC_IC_7) {
 		ic_sof = ipu_irq_map(69);
-		if (ic_sof > 0)
-			request_irq(ic_sof, ic_sof_irq, 0, "IC SOF", ichan);
+		if (ic_sof > 0) {
+			ret = request_irq(ic_sof, ic_sof_irq, 0, "IC SOF", ichan);
+			if (ret)
+				dev_err(&chan->dev->device, "request irq failed for IC SOF");
+		}
 		ic_eof = ipu_irq_map(70);
-		if (ic_eof > 0)
-			request_irq(ic_eof, ic_eof_irq, 0, "IC EOF", ichan);
+		if (ic_eof > 0) {
+			ret = request_irq(ic_eof, ic_eof_irq, 0, "IC EOF", ichan);
+			if (ret)
+				dev_err(&chan->dev->device, "request irq failed for IC EOF");
+		}
 	}
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/Kconfig linux-libre-3.17-rc7-gnu/drivers/dma/Kconfig
--- linux-libre-3.16-gnu/drivers/dma/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,24 @@ if DMADEVICES
 
 comment "DMA Devices"
 
+config INTEL_MIC_X100_DMA
+	tristate "Intel MIC X100 DMA Driver"
+	depends on 64BIT && X86 && INTEL_MIC_BUS
+	select DMA_ENGINE
+	help
+	  This enables DMA support for the Intel Many Integrated Core
+	  (MIC) family of PCIe form factor coprocessor X100 devices that
+	  run a 64 bit Linux OS. This driver will be used by both MIC
+	  host and card drivers.
+
+	  If you are building host kernel with a MIC device or a card
+	  kernel for a MIC device, then say M (recommended) or Y, else
+	  say N. If unsure say N.
+
+	  More information about the Intel MIC family as well as the Linux
+	  OS and tools for MIC to use with this driver are available from
+	  <http://software.intel.com/en-us/mic-developer>.
+
 config INTEL_MID_DMAC
 	tristate "Intel MID DMA support for Peripheral DMA controllers"
 	depends on PCI && X86
@@ -375,6 +393,22 @@ config XILINX_VDMA
 	  channels, Memory Mapped to Stream (MM2S) and Stream to
 	  Memory Mapped (S2MM) for the data transfers.
 
+config DMA_SUN6I
+	tristate "Allwinner A31 SoCs DMA support"
+	depends on MACH_SUN6I || COMPILE_TEST
+	depends on RESET_CONTROLLER
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Support for the DMA engine for Allwinner A31 SoCs.
+
+config NBPFAXI_DMA
+	tristate "Renesas Type-AXI NBPF DMA support"
+	select DMA_ENGINE
+	depends on ARM || COMPILE_TEST
+	help
+	  Support for "Type-AXI" NBPF DMA IPs from Renesas
+
 config DMA_ENGINE
 	bool
 
@@ -388,6 +422,7 @@ config DMA_ACPI
 config DMA_OF
 	def_bool y
 	depends on OF
+	select DMA_ENGINE
 
 comment "DMA Clients"
 	depends on DMA_ENGINE
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/Makefile linux-libre-3.17-rc7-gnu/drivers/dma/Makefile
--- linux-libre-3.16-gnu/drivers/dma/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
-ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
-ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
+subdir-ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
+subdir-ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o
@@ -47,3 +47,6 @@ obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
 obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
 obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
 obj-y += xilinx/
+obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
+obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o
+obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mic_x100_dma.c linux-libre-3.17-rc7-gnu/drivers/dma/mic_x100_dma.c
--- linux-libre-3.16-gnu/drivers/dma/mic_x100_dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mic_x100_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,774 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC X100 DMA Driver.
+ *
+ * Adapted from IOAT dma driver.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+
+#include "mic_x100_dma.h"
+
+#define MIC_DMA_MAX_XFER_SIZE_CARD  (1 * 1024 * 1024 -\
+				       MIC_DMA_ALIGN_BYTES)
+#define MIC_DMA_MAX_XFER_SIZE_HOST  (1 * 1024 * 1024 >> 1)
+#define MIC_DMA_DESC_TYPE_SHIFT	60
+#define MIC_DMA_MEMCPY_LEN_SHIFT 46
+#define MIC_DMA_STAT_INTR_SHIFT 59
+
+/* high-water mark for pushing dma descriptors */
+static int mic_dma_pending_level = 4;
+
+/* Status descriptor is used to write a 64 bit value to a memory location */
+enum mic_dma_desc_format_type {
+	MIC_DMA_MEMCPY = 1,
+	MIC_DMA_STATUS,
+};
+
+static inline u32 mic_dma_hw_ring_inc(u32 val)
+{
+	return (val + 1) % MIC_DMA_DESC_RX_SIZE;
+}
+
+static inline u32 mic_dma_hw_ring_dec(u32 val)
+{
+	return val ? val - 1 : MIC_DMA_DESC_RX_SIZE - 1;
+}
+
+static inline void mic_dma_hw_ring_inc_head(struct mic_dma_chan *ch)
+{
+	ch->head = mic_dma_hw_ring_inc(ch->head);
+}
+
+/* Prepare a memcpy desc */
+static inline void mic_dma_memcpy_desc(struct mic_dma_desc *desc,
+	dma_addr_t src_phys, dma_addr_t dst_phys, u64 size)
+{
+	u64 qw0, qw1;
+
+	qw0 = src_phys;
+	qw0 |= (size >> MIC_DMA_ALIGN_SHIFT) << MIC_DMA_MEMCPY_LEN_SHIFT;
+	qw1 = MIC_DMA_MEMCPY;
+	qw1 <<= MIC_DMA_DESC_TYPE_SHIFT;
+	qw1 |= dst_phys;
+	desc->qw0 = qw0;
+	desc->qw1 = qw1;
+}
+
+/* Prepare a status desc. with @data to be written at @dst_phys */
+static inline void mic_dma_prep_status_desc(struct mic_dma_desc *desc, u64 data,
+	dma_addr_t dst_phys, bool generate_intr)
+{
+	u64 qw0, qw1;
+
+	qw0 = data;
+	qw1 = (u64) MIC_DMA_STATUS << MIC_DMA_DESC_TYPE_SHIFT | dst_phys;
+	if (generate_intr)
+		qw1 |= (1ULL << MIC_DMA_STAT_INTR_SHIFT);
+	desc->qw0 = qw0;
+	desc->qw1 = qw1;
+}
+
+static void mic_dma_cleanup(struct mic_dma_chan *ch)
+{
+	struct dma_async_tx_descriptor *tx;
+	u32 tail;
+	u32 last_tail;
+
+	spin_lock(&ch->cleanup_lock);
+	tail = mic_dma_read_cmp_cnt(ch);
+	/*
+	 * This is the barrier pair for smp_wmb() in fn.
+	 * mic_dma_tx_submit_unlock. It's required so that we read the
+	 * updated cookie value from tx->cookie.
+	 */
+	smp_rmb();
+	for (last_tail = ch->last_tail; tail != last_tail;) {
+		tx = &ch->tx_array[last_tail];
+		if (tx->cookie) {
+			dma_cookie_complete(tx);
+			if (tx->callback) {
+				tx->callback(tx->callback_param);
+				tx->callback = NULL;
+			}
+		}
+		last_tail = mic_dma_hw_ring_inc(last_tail);
+	}
+	/* finish all completion callbacks before incrementing tail */
+	smp_mb();
+	ch->last_tail = last_tail;
+	spin_unlock(&ch->cleanup_lock);
+}
+
+static u32 mic_dma_ring_count(u32 head, u32 tail)
+{
+	u32 count;
+
+	if (head >= tail)
+		count = (tail - 0) + (MIC_DMA_DESC_RX_SIZE - head);
+	else
+		count = tail - head;
+	return count - 1;
+}
+
+/* Returns the num. of free descriptors on success, -ENOMEM on failure */
+static int mic_dma_avail_desc_ring_space(struct mic_dma_chan *ch, int required)
+{
+	struct device *dev = mic_dma_ch_to_device(ch);
+	u32 count;
+
+	count = mic_dma_ring_count(ch->head, ch->last_tail);
+	if (count < required) {
+		mic_dma_cleanup(ch);
+		count = mic_dma_ring_count(ch->head, ch->last_tail);
+	}
+
+	if (count < required) {
+		dev_dbg(dev, "Not enough desc space");
+		dev_dbg(dev, "%s %d required=%u, avail=%u\n",
+			__func__, __LINE__, required, count);
+		return -ENOMEM;
+	} else {
+		return count;
+	}
+}
+
+/* Program memcpy descriptors into the descriptor ring and update s/w head ptr*/
+static int mic_dma_prog_memcpy_desc(struct mic_dma_chan *ch, dma_addr_t src,
+				    dma_addr_t dst, size_t len)
+{
+	size_t current_transfer_len;
+	size_t max_xfer_size = to_mic_dma_dev(ch)->max_xfer_size;
+	/* 3 is added to make sure we have enough space for status desc */
+	int num_desc = len / max_xfer_size + 3;
+	int ret;
+
+	if (len % max_xfer_size)
+		num_desc++;
+
+	ret = mic_dma_avail_desc_ring_space(ch, num_desc);
+	if (ret < 0)
+		return ret;
+	do {
+		current_transfer_len = min(len, max_xfer_size);
+		mic_dma_memcpy_desc(&ch->desc_ring[ch->head],
+				    src, dst, current_transfer_len);
+		mic_dma_hw_ring_inc_head(ch);
+		len -= current_transfer_len;
+		dst = dst + current_transfer_len;
+		src = src + current_transfer_len;
+	} while (len > 0);
+	return 0;
+}
+
+/* It's a h/w quirk and h/w needs 2 status descriptors for every status desc */
+static void mic_dma_prog_intr(struct mic_dma_chan *ch)
+{
+	mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+				 ch->status_dest_micpa, false);
+	mic_dma_hw_ring_inc_head(ch);
+	mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+				 ch->status_dest_micpa, true);
+	mic_dma_hw_ring_inc_head(ch);
+}
+
+/* Wrapper function to program memcpy descriptors/status descriptors */
+static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags, dma_addr_t src,
+			  dma_addr_t dst, size_t len)
+{
+	if (-ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len))
+		return -ENOMEM;
+	/* Above mic_dma_prog_memcpy_desc() makes sure we have enough space */
+	if (flags & DMA_PREP_FENCE) {
+		mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+					 ch->status_dest_micpa, false);
+		mic_dma_hw_ring_inc_head(ch);
+	}
+
+	if (flags & DMA_PREP_INTERRUPT)
+		mic_dma_prog_intr(ch);
+
+	return 0;
+}
+
+static inline void mic_dma_issue_pending(struct dma_chan *ch)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+
+	spin_lock(&mic_ch->issue_lock);
+	/*
+	 * Write to head triggers h/w to act on the descriptors.
+	 * On MIC, writing the same head value twice causes
+	 * a h/w error. On second write, h/w assumes we filled
+	 * the entire ring & overwrote some of the descriptors.
+	 */
+	if (mic_ch->issued == mic_ch->submitted)
+		goto out;
+	mic_ch->issued = mic_ch->submitted;
+	/*
+	 * make descriptor updates visible before advancing head,
+	 * this is purposefully not smp_wmb() since we are also
+	 * publishing the descriptor updates to a dma device
+	 */
+	wmb();
+	mic_dma_write_reg(mic_ch, MIC_DMA_REG_DHPR, mic_ch->issued);
+out:
+	spin_unlock(&mic_ch->issue_lock);
+}
+
+static inline void mic_dma_update_pending(struct mic_dma_chan *ch)
+{
+	if (mic_dma_ring_count(ch->issued, ch->submitted)
+			> mic_dma_pending_level)
+		mic_dma_issue_pending(&ch->api_ch);
+}
+
+static dma_cookie_t mic_dma_tx_submit_unlock(struct dma_async_tx_descriptor *tx)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(tx->chan);
+	dma_cookie_t cookie;
+
+	dma_cookie_assign(tx);
+	cookie = tx->cookie;
+	/*
+	 * We need an smp write barrier here because another CPU might see
+	 * an update to submitted and update h/w head even before we
+	 * assigned a cookie to this tx.
+	 */
+	smp_wmb();
+	mic_ch->submitted = mic_ch->head;
+	spin_unlock(&mic_ch->prep_lock);
+	mic_dma_update_pending(mic_ch);
+	return cookie;
+}
+
+static inline struct dma_async_tx_descriptor *
+allocate_tx(struct mic_dma_chan *ch)
+{
+	u32 idx = mic_dma_hw_ring_dec(ch->head);
+	struct dma_async_tx_descriptor *tx = &ch->tx_array[idx];
+
+	dma_async_tx_descriptor_init(tx, &ch->api_ch);
+	tx->tx_submit = mic_dma_tx_submit_unlock;
+	return tx;
+}
+
+/*
+ * Prepare a memcpy descriptor to be added to the ring.
+ * Note that the temporary descriptor adds an extra overhead of copying the
+ * descriptor to ring. So, we copy directly to the descriptor ring
+ */
+static struct dma_async_tx_descriptor *
+mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest,
+			 dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+	struct device *dev = mic_dma_ch_to_device(mic_ch);
+	int result;
+
+	if (!len && !flags)
+		return NULL;
+
+	spin_lock(&mic_ch->prep_lock);
+	result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len);
+	if (result >= 0)
+		return allocate_tx(mic_ch);
+	dev_err(dev, "Error enqueueing dma, error=%d\n", result);
+	spin_unlock(&mic_ch->prep_lock);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mic_dma_prep_interrupt_lock(struct dma_chan *ch, unsigned long flags)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+	int ret;
+
+	spin_lock(&mic_ch->prep_lock);
+	ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
+	if (!ret)
+		return allocate_tx(mic_ch);
+	spin_unlock(&mic_ch->prep_lock);
+	return NULL;
+}
+
+/* Return the status of the transaction */
+static enum dma_status
+mic_dma_tx_status(struct dma_chan *ch, dma_cookie_t cookie,
+		  struct dma_tx_state *txstate)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+
+	if (DMA_COMPLETE != dma_cookie_status(ch, cookie, txstate))
+		mic_dma_cleanup(mic_ch);
+
+	return dma_cookie_status(ch, cookie, txstate);
+}
+
+static irqreturn_t mic_dma_thread_fn(int irq, void *data)
+{
+	mic_dma_cleanup((struct mic_dma_chan *)data);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mic_dma_intr_handler(int irq, void *data)
+{
+	struct mic_dma_chan *ch = ((struct mic_dma_chan *)data);
+
+	mic_dma_ack_interrupt(ch);
+	return IRQ_WAKE_THREAD;
+}
+
+static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch)
+{
+	u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
+	struct device *dev = &to_mbus_device(ch)->dev;
+
+	desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
+	ch->desc_ring = kzalloc(desc_ring_size, GFP_KERNEL);
+
+	if (!ch->desc_ring)
+		return -ENOMEM;
+
+	ch->desc_ring_micpa = dma_map_single(dev, ch->desc_ring,
+					     desc_ring_size, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(dev, ch->desc_ring_micpa))
+		goto map_error;
+
+	ch->tx_array = vzalloc(MIC_DMA_DESC_RX_SIZE * sizeof(*ch->tx_array));
+	if (!ch->tx_array)
+		goto tx_error;
+	return 0;
+tx_error:
+	dma_unmap_single(dev, ch->desc_ring_micpa, desc_ring_size,
+			 DMA_BIDIRECTIONAL);
+map_error:
+	kfree(ch->desc_ring);
+	return -ENOMEM;
+}
+
+static void mic_dma_free_desc_ring(struct mic_dma_chan *ch)
+{
+	u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
+
+	vfree(ch->tx_array);
+	desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
+	dma_unmap_single(&to_mbus_device(ch)->dev, ch->desc_ring_micpa,
+			 desc_ring_size, DMA_BIDIRECTIONAL);
+	kfree(ch->desc_ring);
+	ch->desc_ring = NULL;
+}
+
+static void mic_dma_free_status_dest(struct mic_dma_chan *ch)
+{
+	dma_unmap_single(&to_mbus_device(ch)->dev, ch->status_dest_micpa,
+			 L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
+	kfree(ch->status_dest);
+}
+
+static int mic_dma_alloc_status_dest(struct mic_dma_chan *ch)
+{
+	struct device *dev = &to_mbus_device(ch)->dev;
+
+	ch->status_dest = kzalloc(L1_CACHE_BYTES, GFP_KERNEL);
+	if (!ch->status_dest)
+		return -ENOMEM;
+	ch->status_dest_micpa = dma_map_single(dev, ch->status_dest,
+					L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(dev, ch->status_dest_micpa)) {
+		kfree(ch->status_dest);
+		ch->status_dest = NULL;
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int mic_dma_check_chan(struct mic_dma_chan *ch)
+{
+	if (mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR) ||
+	    mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) & MIC_DMA_CHAN_QUIESCE) {
+		mic_dma_disable_chan(ch);
+		mic_dma_chan_mask_intr(ch);
+		dev_err(mic_dma_ch_to_device(ch),
+			"%s %d error setting up mic dma chan %d\n",
+			__func__, __LINE__, ch->ch_num);
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static int mic_dma_chan_setup(struct mic_dma_chan *ch)
+{
+	if (MIC_DMA_CHAN_MIC == ch->owner)
+		mic_dma_chan_set_owner(ch);
+	mic_dma_disable_chan(ch);
+	mic_dma_chan_mask_intr(ch);
+	mic_dma_write_reg(ch, MIC_DMA_REG_DCHERRMSK, 0);
+	mic_dma_chan_set_desc_ring(ch);
+	ch->last_tail = mic_dma_read_reg(ch, MIC_DMA_REG_DTPR);
+	ch->head = ch->last_tail;
+	ch->issued = 0;
+	mic_dma_chan_unmask_intr(ch);
+	mic_dma_enable_chan(ch);
+	return mic_dma_check_chan(ch);
+}
+
+static void mic_dma_chan_destroy(struct mic_dma_chan *ch)
+{
+	mic_dma_disable_chan(ch);
+	mic_dma_chan_mask_intr(ch);
+}
+
+static void mic_dma_unregister_dma_device(struct mic_dma_device *mic_dma_dev)
+{
+	dma_async_device_unregister(&mic_dma_dev->dma_dev);
+}
+
+static int mic_dma_setup_irq(struct mic_dma_chan *ch)
+{
+	ch->cookie =
+		to_mbus_hw_ops(ch)->request_threaded_irq(to_mbus_device(ch),
+			mic_dma_intr_handler, mic_dma_thread_fn,
+			"mic dma_channel", ch, ch->ch_num);
+	if (IS_ERR(ch->cookie))
+		return IS_ERR(ch->cookie);
+	return 0;
+}
+
+static inline void mic_dma_free_irq(struct mic_dma_chan *ch)
+{
+	to_mbus_hw_ops(ch)->free_irq(to_mbus_device(ch), ch->cookie, ch);
+}
+
+static int mic_dma_chan_init(struct mic_dma_chan *ch)
+{
+	int ret = mic_dma_alloc_desc_ring(ch);
+
+	if (ret)
+		goto ring_error;
+	ret = mic_dma_alloc_status_dest(ch);
+	if (ret)
+		goto status_error;
+	ret = mic_dma_chan_setup(ch);
+	if (ret)
+		goto chan_error;
+	return ret;
+chan_error:
+	mic_dma_free_status_dest(ch);
+status_error:
+	mic_dma_free_desc_ring(ch);
+ring_error:
+	return ret;
+}
+
+static int mic_dma_drain_chan(struct mic_dma_chan *ch)
+{
+	struct dma_async_tx_descriptor *tx;
+	int err = 0;
+	dma_cookie_t cookie;
+
+	tx = mic_dma_prep_memcpy_lock(&ch->api_ch, 0, 0, 0, DMA_PREP_FENCE);
+	if (!tx) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	cookie = tx->tx_submit(tx);
+	if (dma_submit_error(cookie))
+		err = -ENOMEM;
+	else
+		err = dma_sync_wait(&ch->api_ch, cookie);
+	if (err) {
+		dev_err(mic_dma_ch_to_device(ch), "%s %d TO chan 0x%x\n",
+			__func__, __LINE__, ch->ch_num);
+		err = -EIO;
+	}
+error:
+	mic_dma_cleanup(ch);
+	return err;
+}
+
+static inline void mic_dma_chan_uninit(struct mic_dma_chan *ch)
+{
+	mic_dma_chan_destroy(ch);
+	mic_dma_cleanup(ch);
+	mic_dma_free_status_dest(ch);
+	mic_dma_free_desc_ring(ch);
+}
+
+static int mic_dma_init(struct mic_dma_device *mic_dma_dev,
+			enum mic_dma_chan_owner owner)
+{
+	int i, first_chan = mic_dma_dev->start_ch;
+	struct mic_dma_chan *ch;
+	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);
+		spin_lock_init(&ch->prep_lock);
+		spin_lock_init(&ch->issue_lock);
+		ret = mic_dma_setup_irq(ch);
+		if (ret)
+			goto error;
+	}
+	return 0;
+error:
+	for (i = i - 1; i >= first_chan; i--)
+		mic_dma_free_irq(ch);
+	return ret;
+}
+
+static void mic_dma_uninit(struct mic_dma_device *mic_dma_dev)
+{
+	int i, first_chan = mic_dma_dev->start_ch;
+	struct mic_dma_chan *ch;
+
+	for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+		ch = &mic_dma_dev->mic_ch[i];
+		mic_dma_free_irq(ch);
+	}
+}
+
+static int mic_dma_alloc_chan_resources(struct dma_chan *ch)
+{
+	int ret = mic_dma_chan_init(to_mic_dma_chan(ch));
+	if (ret)
+		return ret;
+	return MIC_DMA_DESC_RX_SIZE;
+}
+
+static void mic_dma_free_chan_resources(struct dma_chan *ch)
+{
+	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+	mic_dma_drain_chan(mic_ch);
+	mic_dma_chan_uninit(mic_ch);
+}
+
+/* Set the fn. handlers and register the dma device with dma api */
+static int mic_dma_register_dma_device(struct mic_dma_device *mic_dma_dev,
+				       enum mic_dma_chan_owner owner)
+{
+	int i, first_chan = mic_dma_dev->start_ch;
+
+	dma_cap_zero(mic_dma_dev->dma_dev.cap_mask);
+	/*
+	 * This dma engine is not capable of host memory to host memory
+	 * transfers
+	 */
+	dma_cap_set(DMA_MEMCPY, mic_dma_dev->dma_dev.cap_mask);
+
+	if (MIC_DMA_CHAN_HOST == owner)
+		dma_cap_set(DMA_PRIVATE, mic_dma_dev->dma_dev.cap_mask);
+	mic_dma_dev->dma_dev.device_alloc_chan_resources =
+		mic_dma_alloc_chan_resources;
+	mic_dma_dev->dma_dev.device_free_chan_resources =
+		mic_dma_free_chan_resources;
+	mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status;
+	mic_dma_dev->dma_dev.device_prep_dma_memcpy = mic_dma_prep_memcpy_lock;
+	mic_dma_dev->dma_dev.device_prep_dma_interrupt =
+		mic_dma_prep_interrupt_lock;
+	mic_dma_dev->dma_dev.device_issue_pending = mic_dma_issue_pending;
+	mic_dma_dev->dma_dev.copy_align = MIC_DMA_ALIGN_SHIFT;
+	INIT_LIST_HEAD(&mic_dma_dev->dma_dev.channels);
+	for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+		mic_dma_dev->mic_ch[i].api_ch.device = &mic_dma_dev->dma_dev;
+		dma_cookie_init(&mic_dma_dev->mic_ch[i].api_ch);
+		list_add_tail(&mic_dma_dev->mic_ch[i].api_ch.device_node,
+			      &mic_dma_dev->dma_dev.channels);
+	}
+	return dma_async_device_register(&mic_dma_dev->dma_dev);
+}
+
+/*
+ * Initializes dma channels and registers the dma device with the
+ * dma engine api.
+ */
+static struct mic_dma_device *mic_dma_dev_reg(struct mbus_device *mbdev,
+					      enum mic_dma_chan_owner owner)
+{
+	struct mic_dma_device *mic_dma_dev;
+	int ret;
+	struct device *dev = &mbdev->dev;
+
+	mic_dma_dev = kzalloc(sizeof(*mic_dma_dev), GFP_KERNEL);
+	if (!mic_dma_dev) {
+		ret = -ENOMEM;
+		goto alloc_error;
+	}
+	mic_dma_dev->mbdev = mbdev;
+	mic_dma_dev->dma_dev.dev = dev;
+	mic_dma_dev->mmio = mbdev->mmio_va;
+	if (MIC_DMA_CHAN_HOST == owner) {
+		mic_dma_dev->start_ch = 0;
+		mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_HOST;
+	} else {
+		mic_dma_dev->start_ch = 4;
+		mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_CARD;
+	}
+	ret = mic_dma_init(mic_dma_dev, owner);
+	if (ret)
+		goto init_error;
+	ret = mic_dma_register_dma_device(mic_dma_dev, owner);
+	if (ret)
+		goto reg_error;
+	return mic_dma_dev;
+reg_error:
+	mic_dma_uninit(mic_dma_dev);
+init_error:
+	kfree(mic_dma_dev);
+	mic_dma_dev = NULL;
+alloc_error:
+	dev_err(dev, "Error at %s %d ret=%d\n", __func__, __LINE__, ret);
+	return mic_dma_dev;
+}
+
+static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev)
+{
+	mic_dma_unregister_dma_device(mic_dma_dev);
+	mic_dma_uninit(mic_dma_dev);
+	kfree(mic_dma_dev);
+}
+
+/* DEBUGFS CODE */
+static int mic_dma_reg_seq_show(struct seq_file *s, void *pos)
+{
+	struct mic_dma_device *mic_dma_dev = s->private;
+	int i, chan_num, first_chan = mic_dma_dev->start_ch;
+	struct mic_dma_chan *ch;
+
+	seq_printf(s, "SBOX_DCR: %#x\n",
+		   mic_dma_mmio_read(&mic_dma_dev->mic_ch[first_chan],
+				     MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR));
+	seq_puts(s, "DMA Channel Registers\n");
+	seq_printf(s, "%-10s| %-10s %-10s %-10s %-10s %-10s",
+		   "Channel", "DCAR", "DTPR", "DHPR", "DRAR_HI", "DRAR_LO");
+	seq_printf(s, " %-11s %-14s %-10s\n", "DCHERR", "DCHERRMSK", "DSTAT");
+	for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+		ch = &mic_dma_dev->mic_ch[i];
+		chan_num = ch->ch_num;
+		seq_printf(s, "%-10i| %-#10x %-#10x %-#10x %-#10x",
+			   chan_num,
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DCAR),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DTPR),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DHPR),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_HI));
+		seq_printf(s, " %-#10x %-#10x %-#14x %-#10x\n",
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_LO),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DCHERRMSK),
+			   mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT));
+	}
+	return 0;
+}
+
+static int mic_dma_reg_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_dma_reg_seq_show, inode->i_private);
+}
+
+static int mic_dma_reg_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations mic_dma_reg_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_dma_reg_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_dma_reg_debug_release
+};
+
+/* Debugfs parent dir */
+static struct dentry *mic_dma_dbg;
+
+static int mic_dma_driver_probe(struct mbus_device *mbdev)
+{
+	struct mic_dma_device *mic_dma_dev;
+	enum mic_dma_chan_owner owner;
+
+	if (MBUS_DEV_DMA_MIC == mbdev->id.device)
+		owner = MIC_DMA_CHAN_MIC;
+	else
+		owner = MIC_DMA_CHAN_HOST;
+
+	mic_dma_dev = mic_dma_dev_reg(mbdev, owner);
+	dev_set_drvdata(&mbdev->dev, mic_dma_dev);
+
+	if (mic_dma_dbg) {
+		mic_dma_dev->dbg_dir = debugfs_create_dir(dev_name(&mbdev->dev),
+							  mic_dma_dbg);
+		if (mic_dma_dev->dbg_dir)
+			debugfs_create_file("mic_dma_reg", 0444,
+					    mic_dma_dev->dbg_dir, mic_dma_dev,
+					    &mic_dma_reg_ops);
+	}
+	return 0;
+}
+
+static void mic_dma_driver_remove(struct mbus_device *mbdev)
+{
+	struct mic_dma_device *mic_dma_dev;
+
+	mic_dma_dev = dev_get_drvdata(&mbdev->dev);
+	debugfs_remove_recursive(mic_dma_dev->dbg_dir);
+	mic_dma_dev_unreg(mic_dma_dev);
+}
+
+static struct mbus_device_id id_table[] = {
+	{MBUS_DEV_DMA_MIC, MBUS_DEV_ANY_ID},
+	{MBUS_DEV_DMA_HOST, MBUS_DEV_ANY_ID},
+	{0},
+};
+
+static struct mbus_driver mic_dma_driver = {
+	.driver.name =	KBUILD_MODNAME,
+	.driver.owner =	THIS_MODULE,
+	.id_table = id_table,
+	.probe = mic_dma_driver_probe,
+	.remove = mic_dma_driver_remove,
+};
+
+static int __init mic_x100_dma_init(void)
+{
+	int rc = mbus_register_driver(&mic_dma_driver);
+	if (rc)
+		return rc;
+	mic_dma_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	return 0;
+}
+
+static void __exit mic_x100_dma_exit(void)
+{
+	debugfs_remove_recursive(mic_dma_dbg);
+	mbus_unregister_driver(&mic_dma_driver);
+}
+
+module_init(mic_x100_dma_init);
+module_exit(mic_x100_dma_exit);
+
+MODULE_DEVICE_TABLE(mbus, id_table);
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 DMA Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mic_x100_dma.h linux-libre-3.17-rc7-gnu/drivers/dma/mic_x100_dma.h
--- linux-libre-3.16-gnu/drivers/dma/mic_x100_dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mic_x100_dma.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,286 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC X100 DMA Driver.
+ *
+ * Adapted from IOAT dma driver.
+ */
+#ifndef _MIC_X100_DMA_H_
+#define _MIC_X100_DMA_H_
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/mic_bus.h>
+
+#include "dmaengine.h"
+
+/*
+ * MIC has a total of 8 dma channels.
+ * Four channels are assigned for host SW use & the remaining for MIC SW.
+ * MIC DMA transfer size & addresses need to be 64 byte aligned.
+ */
+#define MIC_DMA_MAX_NUM_CHAN	8
+#define MIC_DMA_NUM_CHAN	4
+#define MIC_DMA_ALIGN_SHIFT	6
+#define MIC_DMA_ALIGN_BYTES	(1 << MIC_DMA_ALIGN_SHIFT)
+#define MIC_DMA_DESC_RX_SIZE	(128 * 1024 - 4)
+
+/*
+ * Register descriptions
+ * All the registers are 32 bit registers.
+ * DCR is a global register and all others are per-channel.
+ * DCR - bits 0, 2, 4, 6, 8, 10, 12, 14 - enable bits for channels 0 to 7
+ *	 bits 1, 3, 5, 7, 9, 11, 13, 15 - owner bits for channels 0 to 7
+ * DCAR - bit 24 & 25 interrupt masks for mic owned & host owned channels
+ * DHPR - head of the descriptor ring updated by s/w
+ * DTPR - tail of the descriptor ring updated by h/w
+ * DRAR_LO - lower 32 bits of descriptor ring's mic address
+ * DRAR_HI - 3:0 - remaining 4 bits of descriptor ring's mic address
+ *	     20:4 descriptor ring size
+ *	     25:21 mic smpt entry number
+ * DSTAT - 16:0 h/w completion count; 31:28 dma engine status
+ * DCHERR - this register is non-zero on error
+ * DCHERRMSK - interrupt mask register
+ */
+#define MIC_DMA_HW_CMP_CNT_MASK		0x1ffff
+#define MIC_DMA_CHAN_QUIESCE		0x20000000
+#define MIC_DMA_SBOX_BASE		0x00010000
+#define MIC_DMA_SBOX_DCR		0x0000A280
+#define MIC_DMA_SBOX_CH_BASE		0x0001A000
+#define MIC_DMA_SBOX_CHAN_OFF		0x40
+#define MIC_DMA_SBOX_DCAR_IM0		(0x1 << 24)
+#define MIC_DMA_SBOX_DCAR_IM1		(0x1 << 25)
+#define MIC_DMA_SBOX_DRARHI_SYS_MASK	(0x1 << 26)
+#define MIC_DMA_REG_DCAR		0
+#define MIC_DMA_REG_DHPR		4
+#define MIC_DMA_REG_DTPR		8
+#define MIC_DMA_REG_DRAR_LO		20
+#define MIC_DMA_REG_DRAR_HI		24
+#define MIC_DMA_REG_DSTAT		32
+#define MIC_DMA_REG_DCHERR		44
+#define MIC_DMA_REG_DCHERRMSK		48
+
+/* HW dma desc */
+struct mic_dma_desc {
+	u64 qw0;
+	u64 qw1;
+};
+
+enum mic_dma_chan_owner {
+	MIC_DMA_CHAN_MIC = 0,
+	MIC_DMA_CHAN_HOST
+};
+
+/*
+ * mic_dma_chan - channel specific information
+ * @ch_num: channel number
+ * @owner: owner of this channel
+ * @last_tail: cached value of descriptor ring tail
+ * @head: index of next descriptor in desc_ring
+ * @issued: hardware notification point
+ * @submitted: index that will be used to submit descriptors to h/w
+ * @api_ch: dma engine api channel
+ * @desc_ring: dma descriptor ring
+ * @desc_ring_micpa: mic physical address of desc_ring
+ * @status_dest: destination for status (fence) descriptor
+ * @status_dest_micpa: mic address for status_dest,
+ *		       DMA controller uses this address
+ * @tx_array: array of async_tx
+ * @cleanup_lock: lock held when processing completed tx
+ * @prep_lock: lock held in prep_memcpy & released in tx_submit
+ * @issue_lock: lock used to synchronize writes to head
+ * @cookie: mic_irq cookie used with mic irq request
+ */
+struct mic_dma_chan {
+	int ch_num;
+	enum mic_dma_chan_owner owner;
+	u32 last_tail;
+	u32 head;
+	u32 issued;
+	u32 submitted;
+	struct dma_chan api_ch;
+	struct mic_dma_desc *desc_ring;
+	dma_addr_t desc_ring_micpa;
+	u64 *status_dest;
+	dma_addr_t status_dest_micpa;
+	struct dma_async_tx_descriptor *tx_array;
+	spinlock_t cleanup_lock;
+	spinlock_t prep_lock;
+	spinlock_t issue_lock;
+	struct mic_irq *cookie;
+};
+
+/*
+ * struct mic_dma_device - per mic device
+ * @mic_ch: dma channels
+ * @dma_dev: underlying dma device
+ * @mbdev: mic bus dma device
+ * @mmio: virtual address of the mmio space
+ * @dbg_dir: debugfs directory
+ * @start_ch: first channel number that can be used
+ * @max_xfer_size: maximum transfer size per dma descriptor
+ */
+struct mic_dma_device {
+	struct mic_dma_chan mic_ch[MIC_DMA_MAX_NUM_CHAN];
+	struct dma_device dma_dev;
+	struct mbus_device *mbdev;
+	void __iomem *mmio;
+	struct dentry *dbg_dir;
+	int start_ch;
+	size_t max_xfer_size;
+};
+
+static inline struct mic_dma_chan *to_mic_dma_chan(struct dma_chan *ch)
+{
+	return container_of(ch, struct mic_dma_chan, api_ch);
+}
+
+static inline struct mic_dma_device *to_mic_dma_dev(struct mic_dma_chan *ch)
+{
+	return
+	container_of((const typeof(((struct mic_dma_device *)0)->mic_ch)*)
+		     (ch - ch->ch_num), struct mic_dma_device, mic_ch);
+}
+
+static inline struct mbus_device *to_mbus_device(struct mic_dma_chan *ch)
+{
+	return to_mic_dma_dev(ch)->mbdev;
+}
+
+static inline struct mbus_hw_ops *to_mbus_hw_ops(struct mic_dma_chan *ch)
+{
+	return to_mbus_device(ch)->hw_ops;
+}
+
+static inline struct device *mic_dma_ch_to_device(struct mic_dma_chan *ch)
+{
+	return to_mic_dma_dev(ch)->dma_dev.dev;
+}
+
+static inline void __iomem *mic_dma_chan_to_mmio(struct mic_dma_chan *ch)
+{
+	return to_mic_dma_dev(ch)->mmio;
+}
+
+static inline u32 mic_dma_read_reg(struct mic_dma_chan *ch, u32 reg)
+{
+	return ioread32(mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
+			ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
+}
+
+static inline void mic_dma_write_reg(struct mic_dma_chan *ch, u32 reg, u32 val)
+{
+	iowrite32(val, mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
+		  ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
+}
+
+static inline u32 mic_dma_mmio_read(struct mic_dma_chan *ch, u32 offset)
+{
+	return ioread32(mic_dma_chan_to_mmio(ch) + offset);
+}
+
+static inline void mic_dma_mmio_write(struct mic_dma_chan *ch, u32 val,
+				      u32 offset)
+{
+	iowrite32(val, mic_dma_chan_to_mmio(ch) + offset);
+}
+
+static inline u32 mic_dma_read_cmp_cnt(struct mic_dma_chan *ch)
+{
+	return mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) &
+	       MIC_DMA_HW_CMP_CNT_MASK;
+}
+
+static inline void mic_dma_chan_set_owner(struct mic_dma_chan *ch)
+{
+	u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+	u32 chan_num = ch->ch_num;
+
+	dcr = (dcr & ~(0x1 << (chan_num * 2))) | (ch->owner << (chan_num * 2));
+	mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static inline void mic_dma_enable_chan(struct mic_dma_chan *ch)
+{
+	u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+
+	dcr |= 2 << (ch->ch_num << 1);
+	mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static inline void mic_dma_disable_chan(struct mic_dma_chan *ch)
+{
+	u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+
+	dcr &= ~(2 << (ch->ch_num << 1));
+	mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static void mic_dma_chan_set_desc_ring(struct mic_dma_chan *ch)
+{
+	u32 drar_hi;
+	dma_addr_t desc_ring_micpa = ch->desc_ring_micpa;
+
+	drar_hi = (MIC_DMA_DESC_RX_SIZE & 0x1ffff) << 4;
+	if (MIC_DMA_CHAN_MIC == ch->owner) {
+		drar_hi |= (desc_ring_micpa >> 32) & 0xf;
+	} else {
+		drar_hi |= MIC_DMA_SBOX_DRARHI_SYS_MASK;
+		drar_hi |= ((desc_ring_micpa >> 34)
+			    & 0x1f) << 21;
+		drar_hi |= (desc_ring_micpa >> 32) & 0x3;
+	}
+	mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_LO, (u32) desc_ring_micpa);
+	mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_HI, drar_hi);
+}
+
+static inline void mic_dma_chan_mask_intr(struct mic_dma_chan *ch)
+{
+	u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
+
+	if (MIC_DMA_CHAN_MIC == ch->owner)
+		dcar |= MIC_DMA_SBOX_DCAR_IM0;
+	else
+		dcar |= MIC_DMA_SBOX_DCAR_IM1;
+	mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
+}
+
+static inline void mic_dma_chan_unmask_intr(struct mic_dma_chan *ch)
+{
+	u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
+
+	if (MIC_DMA_CHAN_MIC == ch->owner)
+		dcar &= ~MIC_DMA_SBOX_DCAR_IM0;
+	else
+		dcar &= ~MIC_DMA_SBOX_DCAR_IM1;
+	mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
+}
+
+static void mic_dma_ack_interrupt(struct mic_dma_chan *ch)
+{
+	if (MIC_DMA_CHAN_MIC == ch->owner) {
+		/* HW errata */
+		mic_dma_chan_mask_intr(ch);
+		mic_dma_chan_unmask_intr(ch);
+	}
+	to_mbus_hw_ops(ch)->ack_interrupt(to_mbus_device(ch), ch->ch_num);
+}
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mmp_pdma.c linux-libre-3.17-rc7-gnu/drivers/dma/mmp_pdma.c
--- linux-libre-3.16-gnu/drivers/dma/mmp_pdma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mmp_pdma.c	2014-09-28 17:29:07.000000000 -0400
@@ -601,7 +601,7 @@ static struct dma_async_tx_descriptor *
 mmp_pdma_prep_dma_cyclic(struct dma_chan *dchan,
 			 dma_addr_t buf_addr, size_t len, size_t period_len,
 			 enum dma_transfer_direction direction,
-			 unsigned long flags, void *context)
+			 unsigned long flags)
 {
 	struct mmp_pdma_chan *chan;
 	struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mmp_tdma.c linux-libre-3.17-rc7-gnu/drivers/dma/mmp_tdma.c
--- linux-libre-3.16-gnu/drivers/dma/mmp_tdma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mmp_tdma.c	2014-09-28 17:29:07.000000000 -0400
@@ -389,7 +389,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_des
 static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
 	struct mmp_tdma_desc *desc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mpc512x_dma.c linux-libre-3.17-rc7-gnu/drivers/dma/mpc512x_dma.c
--- linux-libre-3.16-gnu/drivers/dma/mpc512x_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mpc512x_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,6 +53,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/of_dma.h>
 #include <linux/of_platform.h>
 
 #include <linux/random.h>
@@ -1036,7 +1037,15 @@ static int mpc_dma_probe(struct platform
 	if (retval)
 		goto err_free2;
 
-	return retval;
+	/* Register with OF helpers for DMA lookups (nonfatal) */
+	if (dev->of_node) {
+		retval = of_dma_controller_register(dev->of_node,
+						of_dma_xlate_by_chan_id, mdma);
+		if (retval)
+			dev_warn(dev, "Could not register for OF lookup\n");
+	}
+
+	return 0;
 
 err_free2:
 	if (mdma->is_mpc8308)
@@ -1057,6 +1066,8 @@ static int mpc_dma_remove(struct platfor
 	struct device *dev = &op->dev;
 	struct mpc_dma *mdma = dev_get_drvdata(dev);
 
+	if (dev->of_node)
+		of_dma_controller_free(dev->of_node);
 	dma_async_device_unregister(&mdma->dma);
 	if (mdma->is_mpc8308) {
 		free_irq(mdma->irq2, mdma);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/mxs-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/mxs-dma.c
--- linux-libre-3.16-gnu/drivers/dma/mxs-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/mxs-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -413,16 +413,14 @@ static int mxs_dma_alloc_chan_resources(
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
 	int ret;
 
-	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
-				CCW_BLOCK_SIZE, &mxs_chan->ccw_phys,
-				GFP_KERNEL);
+	mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev,
+					    CCW_BLOCK_SIZE,
+					    &mxs_chan->ccw_phys, GFP_KERNEL);
 	if (!mxs_chan->ccw) {
 		ret = -ENOMEM;
 		goto err_alloc;
 	}
 
-	memset(mxs_chan->ccw, 0, CCW_BLOCK_SIZE);
-
 	if (mxs_chan->chan_irq != NO_IRQ) {
 		ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
 					0, "mxs-dma", mxs_dma);
@@ -591,7 +589,7 @@ err_out:
 static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/nbpfaxi.c linux-libre-3.17-rc7-gnu/drivers/dma/nbpfaxi.c
--- linux-libre-3.16-gnu/drivers/dma/nbpfaxi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma/nbpfaxi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1517 @@
+/*
+ * Copyright (C) 2013-2014 Renesas Electronics Europe Ltd.
+ * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * 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.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/dma/nbpfaxi.h>
+
+#include "dmaengine.h"
+
+#define NBPF_REG_CHAN_OFFSET	0
+#define NBPF_REG_CHAN_SIZE	0x40
+
+/* Channel Current Transaction Byte register */
+#define NBPF_CHAN_CUR_TR_BYTE	0x20
+
+/* Channel Status register */
+#define NBPF_CHAN_STAT	0x24
+#define NBPF_CHAN_STAT_EN	1
+#define NBPF_CHAN_STAT_TACT	4
+#define NBPF_CHAN_STAT_ERR	0x10
+#define NBPF_CHAN_STAT_END	0x20
+#define NBPF_CHAN_STAT_TC	0x40
+#define NBPF_CHAN_STAT_DER	0x400
+
+/* Channel Control register */
+#define NBPF_CHAN_CTRL	0x28
+#define NBPF_CHAN_CTRL_SETEN	1
+#define NBPF_CHAN_CTRL_CLREN	2
+#define NBPF_CHAN_CTRL_STG	4
+#define NBPF_CHAN_CTRL_SWRST	8
+#define NBPF_CHAN_CTRL_CLRRQ	0x10
+#define NBPF_CHAN_CTRL_CLREND	0x20
+#define NBPF_CHAN_CTRL_CLRTC	0x40
+#define NBPF_CHAN_CTRL_SETSUS	0x100
+#define NBPF_CHAN_CTRL_CLRSUS	0x200
+
+/* Channel Configuration register */
+#define NBPF_CHAN_CFG	0x2c
+#define NBPF_CHAN_CFG_SEL	7		/* terminal SELect: 0..7 */
+#define NBPF_CHAN_CFG_REQD	8		/* REQuest Direction: DMAREQ is 0: input, 1: output */
+#define NBPF_CHAN_CFG_LOEN	0x10		/* LOw ENable: low DMA request line is: 0: inactive, 1: active */
+#define NBPF_CHAN_CFG_HIEN	0x20		/* HIgh ENable: high DMA request line is: 0: inactive, 1: active */
+#define NBPF_CHAN_CFG_LVL	0x40		/* LeVeL: DMA request line is sensed as 0: edge, 1: level */
+#define NBPF_CHAN_CFG_AM	0x700		/* ACK Mode: 0: Pulse mode, 1: Level mode, b'1x: Bus Cycle */
+#define NBPF_CHAN_CFG_SDS	0xf000		/* Source Data Size: 0: 8 bits,... , 7: 1024 bits */
+#define NBPF_CHAN_CFG_DDS	0xf0000		/* Destination Data Size: as above */
+#define NBPF_CHAN_CFG_SAD	0x100000	/* Source ADdress counting: 0: increment, 1: fixed */
+#define NBPF_CHAN_CFG_DAD	0x200000	/* Destination ADdress counting: 0: increment, 1: fixed */
+#define NBPF_CHAN_CFG_TM	0x400000	/* Transfer Mode: 0: single, 1: block TM */
+#define NBPF_CHAN_CFG_DEM	0x1000000	/* DMAEND interrupt Mask */
+#define NBPF_CHAN_CFG_TCM	0x2000000	/* DMATCO interrupt Mask */
+#define NBPF_CHAN_CFG_SBE	0x8000000	/* Sweep Buffer Enable */
+#define NBPF_CHAN_CFG_RSEL	0x10000000	/* RM: Register Set sELect */
+#define NBPF_CHAN_CFG_RSW	0x20000000	/* RM: Register Select sWitch */
+#define NBPF_CHAN_CFG_REN	0x40000000	/* RM: Register Set Enable */
+#define NBPF_CHAN_CFG_DMS	0x80000000	/* 0: register mode (RM), 1: link mode (LM) */
+
+#define NBPF_CHAN_NXLA	0x38
+#define NBPF_CHAN_CRLA	0x3c
+
+/* Link Header field */
+#define NBPF_HEADER_LV	1
+#define NBPF_HEADER_LE	2
+#define NBPF_HEADER_WBD	4
+#define NBPF_HEADER_DIM	8
+
+#define NBPF_CTRL	0x300
+#define NBPF_CTRL_PR	1		/* 0: fixed priority, 1: round robin */
+#define NBPF_CTRL_LVINT	2		/* DMAEND and DMAERR signalling: 0: pulse, 1: level */
+
+#define NBPF_DSTAT_ER	0x314
+#define NBPF_DSTAT_END	0x318
+
+#define NBPF_DMA_BUSWIDTHS \
+	(BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
+	 BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+	 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+	 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
+	 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES))
+
+struct nbpf_config {
+	int num_channels;
+	int buffer_size;
+};
+
+/*
+ * We've got 3 types of objects, used to describe DMA transfers:
+ * 1. high-level descriptor, containing a struct dma_async_tx_descriptor object
+ *	in it, used to communicate with the user
+ * 2. hardware DMA link descriptors, that we pass to DMAC for DMA transfer
+ *	queuing, these must be DMAable, using either the streaming DMA API or
+ *	allocated from coherent memory - one per SG segment
+ * 3. one per SG segment descriptors, used to manage HW link descriptors from
+ *	(2). They do not have to be DMAable. They can either be (a) allocated
+ *	together with link descriptors as mixed (DMA / CPU) objects, or (b)
+ *	separately. Even if allocated separately it would be best to link them
+ *	to link descriptors once during channel resource allocation and always
+ *	use them as a single object.
+ * Therefore for both cases (a) and (b) at run-time objects (2) and (3) shall be
+ * treated as a single SG segment descriptor.
+ */
+
+struct nbpf_link_reg {
+	u32	header;
+	u32	src_addr;
+	u32	dst_addr;
+	u32	transaction_size;
+	u32	config;
+	u32	interval;
+	u32	extension;
+	u32	next;
+} __packed;
+
+struct nbpf_device;
+struct nbpf_channel;
+struct nbpf_desc;
+
+struct nbpf_link_desc {
+	struct nbpf_link_reg *hwdesc;
+	dma_addr_t hwdesc_dma_addr;
+	struct nbpf_desc *desc;
+	struct list_head node;
+};
+
+/**
+ * struct nbpf_desc - DMA transfer descriptor
+ * @async_tx:	dmaengine object
+ * @user_wait:	waiting for a user ack
+ * @length:	total transfer length
+ * @sg:		list of hardware descriptors, represented by struct nbpf_link_desc
+ * @node:	member in channel descriptor lists
+ */
+struct nbpf_desc {
+	struct dma_async_tx_descriptor async_tx;
+	bool user_wait;
+	size_t length;
+	struct nbpf_channel *chan;
+	struct list_head sg;
+	struct list_head node;
+};
+
+/* Take a wild guess: allocate 4 segments per descriptor */
+#define NBPF_SEGMENTS_PER_DESC 4
+#define NBPF_DESCS_PER_PAGE ((PAGE_SIZE - sizeof(struct list_head)) /	\
+	(sizeof(struct nbpf_desc) +					\
+	 NBPF_SEGMENTS_PER_DESC *					\
+	 (sizeof(struct nbpf_link_desc) + sizeof(struct nbpf_link_reg))))
+#define NBPF_SEGMENTS_PER_PAGE (NBPF_SEGMENTS_PER_DESC * NBPF_DESCS_PER_PAGE)
+
+struct nbpf_desc_page {
+	struct list_head node;
+	struct nbpf_desc desc[NBPF_DESCS_PER_PAGE];
+	struct nbpf_link_desc ldesc[NBPF_SEGMENTS_PER_PAGE];
+	struct nbpf_link_reg hwdesc[NBPF_SEGMENTS_PER_PAGE];
+};
+
+/**
+ * struct nbpf_channel - one DMAC channel
+ * @dma_chan:	standard dmaengine channel object
+ * @base:	register address base
+ * @nbpf:	DMAC
+ * @name:	IRQ name
+ * @irq:	IRQ number
+ * @slave_addr:	address for slave DMA
+ * @slave_width:slave data size in bytes
+ * @slave_burst:maximum slave burst size in bytes
+ * @terminal:	DMA terminal, assigned to this channel
+ * @dmarq_cfg:	DMA request line configuration - high / low, edge / level for NBPF_CHAN_CFG
+ * @flags:	configuration flags from DT
+ * @lock:	protect descriptor lists
+ * @free_links:	list of free link descriptors
+ * @free:	list of free descriptors
+ * @queued:	list of queued descriptors
+ * @active:	list of descriptors, scheduled for processing
+ * @done:	list of completed descriptors, waiting post-processing
+ * @desc_page:	list of additionally allocated descriptor pages - if any
+ */
+struct nbpf_channel {
+	struct dma_chan dma_chan;
+	struct tasklet_struct tasklet;
+	void __iomem *base;
+	struct nbpf_device *nbpf;
+	char name[16];
+	int irq;
+	dma_addr_t slave_src_addr;
+	size_t slave_src_width;
+	size_t slave_src_burst;
+	dma_addr_t slave_dst_addr;
+	size_t slave_dst_width;
+	size_t slave_dst_burst;
+	unsigned int terminal;
+	u32 dmarq_cfg;
+	unsigned long flags;
+	spinlock_t lock;
+	struct list_head free_links;
+	struct list_head free;
+	struct list_head queued;
+	struct list_head active;
+	struct list_head done;
+	struct list_head desc_page;
+	struct nbpf_desc *running;
+	bool paused;
+};
+
+struct nbpf_device {
+	struct dma_device dma_dev;
+	void __iomem *base;
+	struct clk *clk;
+	const struct nbpf_config *config;
+	struct nbpf_channel chan[];
+};
+
+enum nbpf_model {
+	NBPF1B4,
+	NBPF1B8,
+	NBPF1B16,
+	NBPF4B4,
+	NBPF4B8,
+	NBPF4B16,
+	NBPF8B4,
+	NBPF8B8,
+	NBPF8B16,
+};
+
+static struct nbpf_config nbpf_cfg[] = {
+	[NBPF1B4] = {
+		.num_channels = 1,
+		.buffer_size = 4,
+	},
+	[NBPF1B8] = {
+		.num_channels = 1,
+		.buffer_size = 8,
+	},
+	[NBPF1B16] = {
+		.num_channels = 1,
+		.buffer_size = 16,
+	},
+	[NBPF4B4] = {
+		.num_channels = 4,
+		.buffer_size = 4,
+	},
+	[NBPF4B8] = {
+		.num_channels = 4,
+		.buffer_size = 8,
+	},
+	[NBPF4B16] = {
+		.num_channels = 4,
+		.buffer_size = 16,
+	},
+	[NBPF8B4] = {
+		.num_channels = 8,
+		.buffer_size = 4,
+	},
+	[NBPF8B8] = {
+		.num_channels = 8,
+		.buffer_size = 8,
+	},
+	[NBPF8B16] = {
+		.num_channels = 8,
+		.buffer_size = 16,
+	},
+};
+
+#define nbpf_to_chan(d) container_of(d, struct nbpf_channel, dma_chan)
+
+/*
+ * dmaengine drivers seem to have a lot in common and instead of sharing more
+ * code, they reimplement those common algorithms independently. In this driver
+ * we try to separate the hardware-specific part from the (largely) generic
+ * part. This improves code readability and makes it possible in the future to
+ * reuse the generic code in form of a helper library. That generic code should
+ * be suitable for various DMA controllers, using transfer descriptors in RAM
+ * and pushing one SG list at a time to the DMA controller.
+ */
+
+/*		Hardware-specific part		*/
+
+static inline u32 nbpf_chan_read(struct nbpf_channel *chan,
+				 unsigned int offset)
+{
+	u32 data = ioread32(chan->base + offset);
+	dev_dbg(chan->dma_chan.device->dev, "%s(0x%p + 0x%x) = 0x%x\n",
+		__func__, chan->base, offset, data);
+	return data;
+}
+
+static inline void nbpf_chan_write(struct nbpf_channel *chan,
+				   unsigned int offset, u32 data)
+{
+	iowrite32(data, chan->base + offset);
+	dev_dbg(chan->dma_chan.device->dev, "%s(0x%p + 0x%x) = 0x%x\n",
+		__func__, chan->base, offset, data);
+}
+
+static inline u32 nbpf_read(struct nbpf_device *nbpf,
+			    unsigned int offset)
+{
+	u32 data = ioread32(nbpf->base + offset);
+	dev_dbg(nbpf->dma_dev.dev, "%s(0x%p + 0x%x) = 0x%x\n",
+		__func__, nbpf->base, offset, data);
+	return data;
+}
+
+static inline void nbpf_write(struct nbpf_device *nbpf,
+			      unsigned int offset, u32 data)
+{
+	iowrite32(data, nbpf->base + offset);
+	dev_dbg(nbpf->dma_dev.dev, "%s(0x%p + 0x%x) = 0x%x\n",
+		__func__, nbpf->base, offset, data);
+}
+
+static void nbpf_chan_halt(struct nbpf_channel *chan)
+{
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREN);
+}
+
+static bool nbpf_status_get(struct nbpf_channel *chan)
+{
+	u32 status = nbpf_read(chan->nbpf, NBPF_DSTAT_END);
+
+	return status & BIT(chan - chan->nbpf->chan);
+}
+
+static void nbpf_status_ack(struct nbpf_channel *chan)
+{
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREND);
+}
+
+static u32 nbpf_error_get(struct nbpf_device *nbpf)
+{
+	return nbpf_read(nbpf, NBPF_DSTAT_ER);
+}
+
+static struct nbpf_channel *nbpf_error_get_channel(struct nbpf_device *nbpf, u32 error)
+{
+	return nbpf->chan + __ffs(error);
+}
+
+static void nbpf_error_clear(struct nbpf_channel *chan)
+{
+	u32 status;
+	int i;
+
+	/* Stop the channel, make sure DMA has been aborted */
+	nbpf_chan_halt(chan);
+
+	for (i = 1000; i; i--) {
+		status = nbpf_chan_read(chan, NBPF_CHAN_STAT);
+		if (!(status & NBPF_CHAN_STAT_TACT))
+			break;
+		cpu_relax();
+	}
+
+	if (!i)
+		dev_err(chan->dma_chan.device->dev,
+			"%s(): abort timeout, channel status 0x%x\n", __func__, status);
+
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SWRST);
+}
+
+static int nbpf_start(struct nbpf_desc *desc)
+{
+	struct nbpf_channel *chan = desc->chan;
+	struct nbpf_link_desc *ldesc = list_first_entry(&desc->sg, struct nbpf_link_desc, node);
+
+	nbpf_chan_write(chan, NBPF_CHAN_NXLA, (u32)ldesc->hwdesc_dma_addr);
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SETEN | NBPF_CHAN_CTRL_CLRSUS);
+	chan->paused = false;
+
+	/* Software trigger MEMCPY - only MEMCPY uses the block mode */
+	if (ldesc->hwdesc->config & NBPF_CHAN_CFG_TM)
+		nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_STG);
+
+	dev_dbg(chan->nbpf->dma_dev.dev, "%s(): next 0x%x, cur 0x%x\n", __func__,
+		nbpf_chan_read(chan, NBPF_CHAN_NXLA), nbpf_chan_read(chan, NBPF_CHAN_CRLA));
+
+	return 0;
+}
+
+static void nbpf_chan_prepare(struct nbpf_channel *chan)
+{
+	chan->dmarq_cfg = (chan->flags & NBPF_SLAVE_RQ_HIGH ? NBPF_CHAN_CFG_HIEN : 0) |
+		(chan->flags & NBPF_SLAVE_RQ_LOW ? NBPF_CHAN_CFG_LOEN : 0) |
+		(chan->flags & NBPF_SLAVE_RQ_LEVEL ?
+		 NBPF_CHAN_CFG_LVL | (NBPF_CHAN_CFG_AM & 0x200) : 0) |
+		chan->terminal;
+}
+
+static void nbpf_chan_prepare_default(struct nbpf_channel *chan)
+{
+	/* Don't output DMAACK */
+	chan->dmarq_cfg = NBPF_CHAN_CFG_AM & 0x400;
+	chan->terminal = 0;
+	chan->flags = 0;
+}
+
+static void nbpf_chan_configure(struct nbpf_channel *chan)
+{
+	/*
+	 * We assume, that only the link mode and DMA request line configuration
+	 * have to be set in the configuration register manually. Dynamic
+	 * per-transfer configuration will be loaded from transfer descriptors.
+	 */
+	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)
+{
+	/* Maximum supported bursts depend on the buffer size */
+	return min_t(int, __ffs(size), ilog2(nbpf->config->buffer_size * 8));
+}
+
+static size_t nbpf_xfer_size(struct nbpf_device *nbpf,
+			     enum dma_slave_buswidth width, u32 burst)
+{
+	size_t size;
+
+	if (!burst)
+		burst = 1;
+
+	switch (width) {
+	case DMA_SLAVE_BUSWIDTH_8_BYTES:
+		size = 8 * burst;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		size = 4 * burst;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		size = 2 * burst;
+		break;
+
+	default:
+		pr_warn("%s(): invalid bus width %u\n", __func__, width);
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		size = burst;
+	}
+
+	return nbpf_xfer_ds(nbpf, size);
+}
+
+/*
+ * We need a way to recognise slaves, whose data is sent "raw" over the bus,
+ * i.e. it isn't known in advance how many bytes will be received. Therefore
+ * the slave driver has to provide a "large enough" buffer and either read the
+ * buffer, when it is full, or detect, that some data has arrived, then wait for
+ * a timeout, if no more data arrives - receive what's already there. We want to
+ * handle such slaves in a special way to allow an optimised mode for other
+ * users, for whom the amount of data is known in advance. So far there's no way
+ * to recognise such slaves. We use a data-width check to distinguish between
+ * the SD host and the PL011 UART.
+ */
+
+static int nbpf_prep_one(struct nbpf_link_desc *ldesc,
+			 enum dma_transfer_direction direction,
+			 dma_addr_t src, dma_addr_t dst, size_t size, bool last)
+{
+	struct nbpf_link_reg *hwdesc = ldesc->hwdesc;
+	struct nbpf_desc *desc = ldesc->desc;
+	struct nbpf_channel *chan = desc->chan;
+	struct device *dev = chan->dma_chan.device->dev;
+	size_t mem_xfer, slave_xfer;
+	bool can_burst;
+
+	hwdesc->header = NBPF_HEADER_WBD | NBPF_HEADER_LV |
+		(last ? NBPF_HEADER_LE : 0);
+
+	hwdesc->src_addr = src;
+	hwdesc->dst_addr = dst;
+	hwdesc->transaction_size = size;
+
+	/*
+	 * set config: SAD, DAD, DDS, SDS, etc.
+	 * Note on transfer sizes: the DMAC can perform unaligned DMA transfers,
+	 * but it is important to have transaction size a multiple of both
+	 * receiver and transmitter transfer sizes. It is also possible to use
+	 * different RAM and device transfer sizes, and it does work well with
+	 * some devices, e.g. with V08R07S01E SD host controllers, which can use
+	 * 128 byte transfers. But this doesn't work with other devices,
+	 * especially when the transaction size is unknown. This is the case,
+	 * e.g. with serial drivers like amba-pl011.c. For reception it sets up
+	 * the transaction size of 4K and if fewer bytes are received, it
+	 * pauses DMA and reads out data received via DMA as well as those left
+	 * in the Rx FIFO. For this to work with the RAM side using burst
+	 * transfers we enable the SBE bit and terminate the transfer in our
+	 * DMA_PAUSE handler.
+	 */
+	mem_xfer = nbpf_xfer_ds(chan->nbpf, size);
+
+	switch (direction) {
+	case DMA_DEV_TO_MEM:
+		can_burst = chan->slave_src_width >= 3;
+		slave_xfer = min(mem_xfer, can_burst ?
+				 chan->slave_src_burst : chan->slave_src_width);
+		/*
+		 * Is the slave narrower than 64 bits, i.e. isn't using the full
+		 * bus width and cannot use bursts?
+		 */
+		if (mem_xfer > chan->slave_src_burst && !can_burst)
+			mem_xfer = chan->slave_src_burst;
+		/* Device-to-RAM DMA is unreliable without REQD set */
+		hwdesc->config = NBPF_CHAN_CFG_SAD | (NBPF_CHAN_CFG_DDS & (mem_xfer << 16)) |
+			(NBPF_CHAN_CFG_SDS & (slave_xfer << 12)) | NBPF_CHAN_CFG_REQD |
+			NBPF_CHAN_CFG_SBE;
+		break;
+
+	case DMA_MEM_TO_DEV:
+		slave_xfer = min(mem_xfer, chan->slave_dst_width >= 3 ?
+				 chan->slave_dst_burst : chan->slave_dst_width);
+		hwdesc->config = NBPF_CHAN_CFG_DAD | (NBPF_CHAN_CFG_SDS & (mem_xfer << 12)) |
+			(NBPF_CHAN_CFG_DDS & (slave_xfer << 16)) | NBPF_CHAN_CFG_REQD;
+		break;
+
+	case DMA_MEM_TO_MEM:
+		hwdesc->config = NBPF_CHAN_CFG_TCM | NBPF_CHAN_CFG_TM |
+			(NBPF_CHAN_CFG_SDS & (mem_xfer << 12)) |
+			(NBPF_CHAN_CFG_DDS & (mem_xfer << 16));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	hwdesc->config |= chan->dmarq_cfg | (last ? 0 : NBPF_CHAN_CFG_DEM) |
+		NBPF_CHAN_CFG_DMS;
+
+	dev_dbg(dev, "%s(): desc @ %pad: hdr 0x%x, cfg 0x%x, %zu @ %pad -> %pad\n",
+		__func__, &ldesc->hwdesc_dma_addr, hwdesc->header,
+		hwdesc->config, size, &src, &dst);
+
+	dma_sync_single_for_device(dev, ldesc->hwdesc_dma_addr, sizeof(*hwdesc),
+				   DMA_TO_DEVICE);
+
+	return 0;
+}
+
+static size_t nbpf_bytes_left(struct nbpf_channel *chan)
+{
+	return nbpf_chan_read(chan, NBPF_CHAN_CUR_TR_BYTE);
+}
+
+static void nbpf_configure(struct nbpf_device *nbpf)
+{
+	nbpf_write(nbpf, NBPF_CTRL, NBPF_CTRL_LVINT);
+}
+
+static void nbpf_pause(struct nbpf_channel *chan)
+{
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SETSUS);
+	/* See comment in nbpf_prep_one() */
+	nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREN);
+}
+
+/*		Generic part			*/
+
+/* DMA ENGINE functions */
+static void nbpf_issue_pending(struct dma_chan *dchan)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	unsigned long flags;
+
+	dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (list_empty(&chan->queued))
+		goto unlock;
+
+	list_splice_tail_init(&chan->queued, &chan->active);
+
+	if (!chan->running) {
+		struct nbpf_desc *desc = list_first_entry(&chan->active,
+						struct nbpf_desc, node);
+		if (!nbpf_start(desc))
+			chan->running = desc;
+	}
+
+unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static enum dma_status nbpf_tx_status(struct dma_chan *dchan,
+		dma_cookie_t cookie, struct dma_tx_state *state)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	enum dma_status status = dma_cookie_status(dchan, cookie, state);
+
+	if (state) {
+		dma_cookie_t running;
+		unsigned long flags;
+
+		spin_lock_irqsave(&chan->lock, flags);
+		running = chan->running ? chan->running->async_tx.cookie : -EINVAL;
+
+		if (cookie == running) {
+			state->residue = nbpf_bytes_left(chan);
+			dev_dbg(dchan->device->dev, "%s(): residue %u\n", __func__,
+				state->residue);
+		} else if (status == DMA_IN_PROGRESS) {
+			struct nbpf_desc *desc;
+			bool found = false;
+
+			list_for_each_entry(desc, &chan->active, node)
+				if (desc->async_tx.cookie == cookie) {
+					found = true;
+					break;
+				}
+
+			if (!found)
+				list_for_each_entry(desc, &chan->queued, node)
+					if (desc->async_tx.cookie == cookie) {
+						found = true;
+						break;
+
+					}
+
+			state->residue = found ? desc->length : 0;
+		}
+
+		spin_unlock_irqrestore(&chan->lock, flags);
+	}
+
+	if (chan->paused)
+		status = DMA_PAUSED;
+
+	return status;
+}
+
+static dma_cookie_t nbpf_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct nbpf_desc *desc = container_of(tx, struct nbpf_desc, async_tx);
+	struct nbpf_channel *chan = desc->chan;
+	unsigned long flags;
+	dma_cookie_t cookie;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	cookie = dma_cookie_assign(tx);
+	list_add_tail(&desc->node, &chan->queued);
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	dev_dbg(chan->dma_chan.device->dev, "Entry %s(%d)\n", __func__, cookie);
+
+	return cookie;
+}
+
+static int nbpf_desc_page_alloc(struct nbpf_channel *chan)
+{
+	struct dma_chan *dchan = &chan->dma_chan;
+	struct nbpf_desc_page *dpage = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	struct nbpf_link_desc *ldesc;
+	struct nbpf_link_reg *hwdesc;
+	struct nbpf_desc *desc;
+	LIST_HEAD(head);
+	LIST_HEAD(lhead);
+	int i;
+	struct device *dev = dchan->device->dev;
+
+	if (!dpage)
+		return -ENOMEM;
+
+	dev_dbg(dev, "%s(): alloc %lu descriptors, %lu segments, total alloc %zu\n",
+		__func__, NBPF_DESCS_PER_PAGE, NBPF_SEGMENTS_PER_PAGE, sizeof(*dpage));
+
+	for (i = 0, ldesc = dpage->ldesc, hwdesc = dpage->hwdesc;
+	     i < ARRAY_SIZE(dpage->ldesc);
+	     i++, ldesc++, hwdesc++) {
+		ldesc->hwdesc = hwdesc;
+		list_add_tail(&ldesc->node, &lhead);
+		ldesc->hwdesc_dma_addr = dma_map_single(dchan->device->dev,
+					hwdesc, sizeof(*hwdesc), DMA_TO_DEVICE);
+
+		dev_dbg(dev, "%s(): mapped 0x%p to %pad\n", __func__,
+			hwdesc, &ldesc->hwdesc_dma_addr);
+	}
+
+	for (i = 0, desc = dpage->desc;
+	     i < ARRAY_SIZE(dpage->desc);
+	     i++, desc++) {
+		dma_async_tx_descriptor_init(&desc->async_tx, dchan);
+		desc->async_tx.tx_submit = nbpf_tx_submit;
+		desc->chan = chan;
+		INIT_LIST_HEAD(&desc->sg);
+		list_add_tail(&desc->node, &head);
+	}
+
+	/*
+	 * This function cannot be called from interrupt context, so, no need to
+	 * save flags
+	 */
+	spin_lock_irq(&chan->lock);
+	list_splice_tail(&lhead, &chan->free_links);
+	list_splice_tail(&head, &chan->free);
+	list_add(&dpage->node, &chan->desc_page);
+	spin_unlock_irq(&chan->lock);
+
+	return ARRAY_SIZE(dpage->desc);
+}
+
+static void nbpf_desc_put(struct nbpf_desc *desc)
+{
+	struct nbpf_channel *chan = desc->chan;
+	struct nbpf_link_desc *ldesc, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	list_for_each_entry_safe(ldesc, tmp, &desc->sg, node)
+		list_move(&ldesc->node, &chan->free_links);
+
+	list_add(&desc->node, &chan->free);
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static void nbpf_scan_acked(struct nbpf_channel *chan)
+{
+	struct nbpf_desc *desc, *tmp;
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&chan->lock, flags);
+	list_for_each_entry_safe(desc, tmp, &chan->done, node)
+		if (async_tx_test_ack(&desc->async_tx) && desc->user_wait) {
+			list_move(&desc->node, &head);
+			desc->user_wait = false;
+		}
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, tmp, &head, node) {
+		list_del(&desc->node);
+		nbpf_desc_put(desc);
+	}
+}
+
+/*
+ * We have to allocate descriptors with the channel lock dropped. This means,
+ * before we re-acquire the lock buffers can be taken already, so we have to
+ * re-check after re-acquiring the lock and possibly retry, if buffers are gone
+ * again.
+ */
+static struct nbpf_desc *nbpf_desc_get(struct nbpf_channel *chan, size_t len)
+{
+	struct nbpf_desc *desc = NULL;
+	struct nbpf_link_desc *ldesc, *prev = NULL;
+
+	nbpf_scan_acked(chan);
+
+	spin_lock_irq(&chan->lock);
+
+	do {
+		int i = 0, ret;
+
+		if (list_empty(&chan->free)) {
+			/* No more free descriptors */
+			spin_unlock_irq(&chan->lock);
+			ret = nbpf_desc_page_alloc(chan);
+			if (ret < 0)
+				return NULL;
+			spin_lock_irq(&chan->lock);
+			continue;
+		}
+		desc = list_first_entry(&chan->free, struct nbpf_desc, node);
+		list_del(&desc->node);
+
+		do {
+			if (list_empty(&chan->free_links)) {
+				/* No more free link descriptors */
+				spin_unlock_irq(&chan->lock);
+				ret = nbpf_desc_page_alloc(chan);
+				if (ret < 0) {
+					nbpf_desc_put(desc);
+					return NULL;
+				}
+				spin_lock_irq(&chan->lock);
+				continue;
+			}
+
+			ldesc = list_first_entry(&chan->free_links,
+						 struct nbpf_link_desc, node);
+			ldesc->desc = desc;
+			if (prev)
+				prev->hwdesc->next = (u32)ldesc->hwdesc_dma_addr;
+
+			prev = ldesc;
+			list_move_tail(&ldesc->node, &desc->sg);
+
+			i++;
+		} while (i < len);
+	} while (!desc);
+
+	prev->hwdesc->next = 0;
+
+	spin_unlock_irq(&chan->lock);
+
+	return desc;
+}
+
+static void nbpf_chan_idle(struct nbpf_channel *chan)
+{
+	struct nbpf_desc *desc, *tmp;
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	list_splice_init(&chan->done, &head);
+	list_splice_init(&chan->active, &head);
+	list_splice_init(&chan->queued, &head);
+
+	chan->running = NULL;
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, tmp, &head, node) {
+		dev_dbg(chan->nbpf->dma_dev.dev, "%s(): force-free desc %p cookie %d\n",
+			__func__, desc, desc->async_tx.cookie);
+		list_del(&desc->node);
+		nbpf_desc_put(desc);
+	}
+}
+
+static int nbpf_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
+			unsigned long arg)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	struct dma_slave_config *config;
+
+	dev_dbg(dchan->device->dev, "Entry %s(%d)\n", __func__, cmd);
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		dev_dbg(dchan->device->dev, "Terminating\n");
+		nbpf_chan_halt(chan);
+		nbpf_chan_idle(chan);
+		break;
+
+	case DMA_SLAVE_CONFIG:
+		if (!arg)
+			return -EINVAL;
+		config = (struct dma_slave_config *)arg;
+
+		/*
+		 * We could check config->slave_id to match chan->terminal here,
+		 * but with DT they would be coming from the same source, so
+		 * such a check would be superflous
+		 */
+
+		chan->slave_dst_addr = config->dst_addr;
+		chan->slave_dst_width = nbpf_xfer_size(chan->nbpf,
+						       config->dst_addr_width, 1);
+		chan->slave_dst_burst = nbpf_xfer_size(chan->nbpf,
+						       config->dst_addr_width,
+						       config->dst_maxburst);
+		chan->slave_src_addr = config->src_addr;
+		chan->slave_src_width = nbpf_xfer_size(chan->nbpf,
+						       config->src_addr_width, 1);
+		chan->slave_src_burst = nbpf_xfer_size(chan->nbpf,
+						       config->src_addr_width,
+						       config->src_maxburst);
+		break;
+
+	case DMA_PAUSE:
+		chan->paused = true;
+		nbpf_pause(chan);
+		break;
+
+	default:
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_sg(struct nbpf_channel *chan,
+		struct scatterlist *src_sg, struct scatterlist *dst_sg,
+		size_t len, enum dma_transfer_direction direction,
+		unsigned long flags)
+{
+	struct nbpf_link_desc *ldesc;
+	struct scatterlist *mem_sg;
+	struct nbpf_desc *desc;
+	bool inc_src, inc_dst;
+	size_t data_len = 0;
+	int i = 0;
+
+	switch (direction) {
+	case DMA_DEV_TO_MEM:
+		mem_sg = dst_sg;
+		inc_src = false;
+		inc_dst = true;
+		break;
+
+	case DMA_MEM_TO_DEV:
+		mem_sg = src_sg;
+		inc_src = true;
+		inc_dst = false;
+		break;
+
+	default:
+	case DMA_MEM_TO_MEM:
+		mem_sg = src_sg;
+		inc_src = true;
+		inc_dst = true;
+	}
+
+	desc = nbpf_desc_get(chan, len);
+	if (!desc)
+		return NULL;
+
+	desc->async_tx.flags = flags;
+	desc->async_tx.cookie = -EBUSY;
+	desc->user_wait = false;
+
+	/*
+	 * This is a private descriptor list, and we own the descriptor. No need
+	 * to lock.
+	 */
+	list_for_each_entry(ldesc, &desc->sg, node) {
+		int ret = nbpf_prep_one(ldesc, direction,
+					sg_dma_address(src_sg),
+					sg_dma_address(dst_sg),
+					sg_dma_len(mem_sg),
+					i == len - 1);
+		if (ret < 0) {
+			nbpf_desc_put(desc);
+			return NULL;
+		}
+		data_len += sg_dma_len(mem_sg);
+		if (inc_src)
+			src_sg = sg_next(src_sg);
+		if (inc_dst)
+			dst_sg = sg_next(dst_sg);
+		mem_sg = direction == DMA_DEV_TO_MEM ? dst_sg : src_sg;
+		i++;
+	}
+
+	desc->length = data_len;
+
+	/* The user has to return the descriptor to us ASAP via .tx_submit() */
+	return &desc->async_tx;
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_memcpy(
+	struct dma_chan *dchan, dma_addr_t dst, dma_addr_t src,
+	size_t len, unsigned long flags)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	struct scatterlist dst_sg;
+	struct scatterlist src_sg;
+
+	sg_init_table(&dst_sg, 1);
+	sg_init_table(&src_sg, 1);
+
+	sg_dma_address(&dst_sg) = dst;
+	sg_dma_address(&src_sg) = src;
+
+	sg_dma_len(&dst_sg) = len;
+	sg_dma_len(&src_sg) = len;
+
+	dev_dbg(dchan->device->dev, "%s(): %zu @ %pad -> %pad\n",
+		__func__, len, &src, &dst);
+
+	return nbpf_prep_sg(chan, &src_sg, &dst_sg, 1,
+			    DMA_MEM_TO_MEM, flags);
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_memcpy_sg(
+	struct dma_chan *dchan,
+	struct scatterlist *dst_sg, unsigned int dst_nents,
+	struct scatterlist *src_sg, unsigned int src_nents,
+	unsigned long flags)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+
+	if (dst_nents != src_nents)
+		return NULL;
+
+	return nbpf_prep_sg(chan, src_sg, dst_sg, src_nents,
+			    DMA_MEM_TO_MEM, flags);
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_slave_sg(
+	struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+	enum dma_transfer_direction direction, unsigned long flags, void *context)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	struct scatterlist slave_sg;
+
+	dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+	sg_init_table(&slave_sg, 1);
+
+	switch (direction) {
+	case DMA_MEM_TO_DEV:
+		sg_dma_address(&slave_sg) = chan->slave_dst_addr;
+		return nbpf_prep_sg(chan, sgl, &slave_sg, sg_len,
+				    direction, flags);
+
+	case DMA_DEV_TO_MEM:
+		sg_dma_address(&slave_sg) = chan->slave_src_addr;
+		return nbpf_prep_sg(chan, &slave_sg, sgl, sg_len,
+				    direction, flags);
+
+	default:
+		return NULL;
+	}
+}
+
+static int nbpf_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	int ret;
+
+	INIT_LIST_HEAD(&chan->free);
+	INIT_LIST_HEAD(&chan->free_links);
+	INIT_LIST_HEAD(&chan->queued);
+	INIT_LIST_HEAD(&chan->active);
+	INIT_LIST_HEAD(&chan->done);
+
+	ret = nbpf_desc_page_alloc(chan);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(dchan->device->dev, "Entry %s(): terminal %u\n", __func__,
+		chan->terminal);
+
+	nbpf_chan_configure(chan);
+
+	return ret;
+}
+
+static void nbpf_free_chan_resources(struct dma_chan *dchan)
+{
+	struct nbpf_channel *chan = nbpf_to_chan(dchan);
+	struct nbpf_desc_page *dpage, *tmp;
+
+	dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+	nbpf_chan_halt(chan);
+	nbpf_chan_idle(chan);
+	/* Clean up for if a channel is re-used for MEMCPY after slave DMA */
+	nbpf_chan_prepare_default(chan);
+
+	list_for_each_entry_safe(dpage, tmp, &chan->desc_page, node) {
+		struct nbpf_link_desc *ldesc;
+		int i;
+		list_del(&dpage->node);
+		for (i = 0, ldesc = dpage->ldesc;
+		     i < ARRAY_SIZE(dpage->ldesc);
+		     i++, ldesc++)
+			dma_unmap_single(dchan->device->dev, ldesc->hwdesc_dma_addr,
+					 sizeof(*ldesc->hwdesc), DMA_TO_DEVICE);
+		free_page((unsigned long)dpage);
+	}
+}
+
+static int nbpf_slave_caps(struct dma_chan *dchan,
+			   struct dma_slave_caps *caps)
+{
+	caps->src_addr_widths = NBPF_DMA_BUSWIDTHS;
+	caps->dstn_addr_widths = NBPF_DMA_BUSWIDTHS;
+	caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	caps->cmd_pause = false;
+	caps->cmd_terminate = true;
+
+	return 0;
+}
+
+static struct dma_chan *nbpf_of_xlate(struct of_phandle_args *dma_spec,
+				      struct of_dma *ofdma)
+{
+	struct nbpf_device *nbpf = ofdma->of_dma_data;
+	struct dma_chan *dchan;
+	struct nbpf_channel *chan;
+
+	if (dma_spec->args_count != 2)
+		return NULL;
+
+	dchan = dma_get_any_slave_channel(&nbpf->dma_dev);
+	if (!dchan)
+		return NULL;
+
+	dev_dbg(dchan->device->dev, "Entry %s(%s)\n", __func__,
+		dma_spec->np->name);
+
+	chan = nbpf_to_chan(dchan);
+
+	chan->terminal = dma_spec->args[0];
+	chan->flags = dma_spec->args[1];
+
+	nbpf_chan_prepare(chan);
+	nbpf_chan_configure(chan);
+
+	return dchan;
+}
+
+static void nbpf_chan_tasklet(unsigned long data)
+{
+	struct nbpf_channel *chan = (struct nbpf_channel *)data;
+	struct nbpf_desc *desc, *tmp;
+	dma_async_tx_callback callback;
+	void *param;
+
+	while (!list_empty(&chan->done)) {
+		bool found = false, must_put, recycling = false;
+
+		spin_lock_irq(&chan->lock);
+
+		list_for_each_entry_safe(desc, tmp, &chan->done, node) {
+			if (!desc->user_wait) {
+				/* Newly completed descriptor, have to process */
+				found = true;
+				break;
+			} else if (async_tx_test_ack(&desc->async_tx)) {
+				/*
+				 * This descriptor was waiting for a user ACK,
+				 * it can be recycled now.
+				 */
+				list_del(&desc->node);
+				spin_unlock_irq(&chan->lock);
+				nbpf_desc_put(desc);
+				recycling = true;
+				break;
+			}
+		}
+
+		if (recycling)
+			continue;
+
+		if (!found) {
+			/* This can happen if TERMINATE_ALL has been called */
+			spin_unlock_irq(&chan->lock);
+			break;
+		}
+
+		dma_cookie_complete(&desc->async_tx);
+
+		/*
+		 * With released lock we cannot dereference desc, maybe it's
+		 * still on the "done" list
+		 */
+		if (async_tx_test_ack(&desc->async_tx)) {
+			list_del(&desc->node);
+			must_put = true;
+		} else {
+			desc->user_wait = true;
+			must_put = false;
+		}
+
+		callback = desc->async_tx.callback;
+		param = desc->async_tx.callback_param;
+
+		/* ack and callback completed descriptor */
+		spin_unlock_irq(&chan->lock);
+
+		if (callback)
+			callback(param);
+
+		if (must_put)
+			nbpf_desc_put(desc);
+	}
+}
+
+static irqreturn_t nbpf_chan_irq(int irq, void *dev)
+{
+	struct nbpf_channel *chan = dev;
+	bool done = nbpf_status_get(chan);
+	struct nbpf_desc *desc;
+	irqreturn_t ret;
+	bool bh = false;
+
+	if (!done)
+		return IRQ_NONE;
+
+	nbpf_status_ack(chan);
+
+	dev_dbg(&chan->dma_chan.dev->device, "%s()\n", __func__);
+
+	spin_lock(&chan->lock);
+	desc = chan->running;
+	if (WARN_ON(!desc)) {
+		ret = IRQ_NONE;
+		goto unlock;
+	} else {
+		ret = IRQ_HANDLED;
+		bh = true;
+	}
+
+	list_move_tail(&desc->node, &chan->done);
+	chan->running = NULL;
+
+	if (!list_empty(&chan->active)) {
+		desc = list_first_entry(&chan->active,
+					struct nbpf_desc, node);
+		if (!nbpf_start(desc))
+			chan->running = desc;
+	}
+
+unlock:
+	spin_unlock(&chan->lock);
+
+	if (bh)
+		tasklet_schedule(&chan->tasklet);
+
+	return ret;
+}
+
+static irqreturn_t nbpf_err_irq(int irq, void *dev)
+{
+	struct nbpf_device *nbpf = dev;
+	u32 error = nbpf_error_get(nbpf);
+
+	dev_warn(nbpf->dma_dev.dev, "DMA error IRQ %u\n", irq);
+
+	if (!error)
+		return IRQ_NONE;
+
+	do {
+		struct nbpf_channel *chan = nbpf_error_get_channel(nbpf, error);
+		/* On error: abort all queued transfers, no callback */
+		nbpf_error_clear(chan);
+		nbpf_chan_idle(chan);
+		error = nbpf_error_get(nbpf);
+	} while (error);
+
+	return IRQ_HANDLED;
+}
+
+static int nbpf_chan_probe(struct nbpf_device *nbpf, int n)
+{
+	struct dma_device *dma_dev = &nbpf->dma_dev;
+	struct nbpf_channel *chan = nbpf->chan + n;
+	int ret;
+
+	chan->nbpf = nbpf;
+	chan->base = nbpf->base + NBPF_REG_CHAN_OFFSET + NBPF_REG_CHAN_SIZE * n;
+	INIT_LIST_HEAD(&chan->desc_page);
+	spin_lock_init(&chan->lock);
+	chan->dma_chan.device = dma_dev;
+	dma_cookie_init(&chan->dma_chan);
+	nbpf_chan_prepare_default(chan);
+
+	dev_dbg(dma_dev->dev, "%s(): channel %d: -> %p\n", __func__, n, chan->base);
+
+	snprintf(chan->name, sizeof(chan->name), "nbpf %d", n);
+
+	tasklet_init(&chan->tasklet, nbpf_chan_tasklet, (unsigned long)chan);
+	ret = devm_request_irq(dma_dev->dev, chan->irq,
+			nbpf_chan_irq, IRQF_SHARED,
+			chan->name, chan);
+	if (ret < 0)
+		return ret;
+
+	/* Add the channel to DMA device channel list */
+	list_add_tail(&chan->dma_chan.device_node,
+		      &dma_dev->channels);
+
+	return 0;
+}
+
+static const struct of_device_id nbpf_match[] = {
+	{.compatible = "renesas,nbpfaxi64dmac1b4",	.data = &nbpf_cfg[NBPF1B4]},
+	{.compatible = "renesas,nbpfaxi64dmac1b8",	.data = &nbpf_cfg[NBPF1B8]},
+	{.compatible = "renesas,nbpfaxi64dmac1b16",	.data = &nbpf_cfg[NBPF1B16]},
+	{.compatible = "renesas,nbpfaxi64dmac4b4",	.data = &nbpf_cfg[NBPF4B4]},
+	{.compatible = "renesas,nbpfaxi64dmac4b8",	.data = &nbpf_cfg[NBPF4B8]},
+	{.compatible = "renesas,nbpfaxi64dmac4b16",	.data = &nbpf_cfg[NBPF4B16]},
+	{.compatible = "renesas,nbpfaxi64dmac8b4",	.data = &nbpf_cfg[NBPF8B4]},
+	{.compatible = "renesas,nbpfaxi64dmac8b8",	.data = &nbpf_cfg[NBPF8B8]},
+	{.compatible = "renesas,nbpfaxi64dmac8b16",	.data = &nbpf_cfg[NBPF8B16]},
+	{}
+};
+MODULE_DEVICE_TABLE(of, nbpf_match);
+
+static int nbpf_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *of_id = of_match_device(nbpf_match, dev);
+	struct device_node *np = dev->of_node;
+	struct nbpf_device *nbpf;
+	struct dma_device *dma_dev;
+	struct resource *iomem, *irq_res;
+	const struct nbpf_config *cfg;
+	int num_channels;
+	int ret, irq, eirq, i;
+	int irqbuf[9] /* maximum 8 channels + error IRQ */;
+	unsigned int irqs = 0;
+
+	BUILD_BUG_ON(sizeof(struct nbpf_desc_page) > PAGE_SIZE);
+
+	/* DT only */
+	if (!np || !of_id || !of_id->data)
+		return -ENODEV;
+
+	cfg = of_id->data;
+	num_channels = cfg->num_channels;
+
+	nbpf = devm_kzalloc(dev, sizeof(*nbpf) + num_channels *
+			    sizeof(nbpf->chan[0]), GFP_KERNEL);
+	if (!nbpf) {
+		dev_err(dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+	dma_dev = &nbpf->dma_dev;
+	dma_dev->dev = dev;
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	nbpf->base = devm_ioremap_resource(dev, iomem);
+	if (IS_ERR(nbpf->base))
+		return PTR_ERR(nbpf->base);
+
+	nbpf->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(nbpf->clk))
+		return PTR_ERR(nbpf->clk);
+
+	nbpf->config = cfg;
+
+	for (i = 0; irqs < ARRAY_SIZE(irqbuf); i++) {
+		irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		if (!irq_res)
+			break;
+
+		for (irq = irq_res->start; irq <= irq_res->end;
+		     irq++, irqs++)
+			irqbuf[irqs] = irq;
+	}
+
+	/*
+	 * 3 IRQ resource schemes are supported:
+	 * 1. 1 shared IRQ for error and all channels
+	 * 2. 2 IRQs: one for error and one shared for all channels
+	 * 3. 1 IRQ for error and an own IRQ for each channel
+	 */
+	if (irqs != 1 && irqs != 2 && irqs != num_channels + 1)
+		return -ENXIO;
+
+	if (irqs == 1) {
+		eirq = irqbuf[0];
+
+		for (i = 0; i <= num_channels; i++)
+			nbpf->chan[i].irq = irqbuf[0];
+	} else {
+		eirq = platform_get_irq_byname(pdev, "error");
+		if (eirq < 0)
+			return eirq;
+
+		if (irqs == num_channels + 1) {
+			struct nbpf_channel *chan;
+
+			for (i = 0, chan = nbpf->chan; i <= num_channels;
+			     i++, chan++) {
+				/* Skip the error IRQ */
+				if (irqbuf[i] == eirq)
+					i++;
+				chan->irq = irqbuf[i];
+			}
+
+			if (chan != nbpf->chan + num_channels)
+				return -EINVAL;
+		} else {
+			/* 2 IRQs and more than one channel */
+			if (irqbuf[0] == eirq)
+				irq = irqbuf[1];
+			else
+				irq = irqbuf[0];
+
+			for (i = 0; i <= num_channels; i++)
+				nbpf->chan[i].irq = irq;
+		}
+	}
+
+	ret = devm_request_irq(dev, eirq, nbpf_err_irq,
+			       IRQF_SHARED, "dma error", nbpf);
+	if (ret < 0)
+		return ret;
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+
+	/* Create DMA Channel */
+	for (i = 0; i < num_channels; i++) {
+		ret = nbpf_chan_probe(nbpf, i);
+		if (ret < 0)
+			return ret;
+	}
+
+	dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+	dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
+	dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+	dma_cap_set(DMA_SG, dma_dev->cap_mask);
+
+	/* Common and MEMCPY operations */
+	dma_dev->device_alloc_chan_resources
+		= nbpf_alloc_chan_resources;
+	dma_dev->device_free_chan_resources = nbpf_free_chan_resources;
+	dma_dev->device_prep_dma_sg = nbpf_prep_memcpy_sg;
+	dma_dev->device_prep_dma_memcpy = nbpf_prep_memcpy;
+	dma_dev->device_tx_status = nbpf_tx_status;
+	dma_dev->device_issue_pending = nbpf_issue_pending;
+	dma_dev->device_slave_caps = nbpf_slave_caps;
+
+	/*
+	 * If we drop support for unaligned MEMCPY buffer addresses and / or
+	 * lengths by setting
+	 * dma_dev->copy_align = 4;
+	 * then we can set transfer length to 4 bytes in nbpf_prep_one() for
+	 * DMA_MEM_TO_MEM
+	 */
+
+	/* Compulsory for DMA_SLAVE fields */
+	dma_dev->device_prep_slave_sg = nbpf_prep_slave_sg;
+	dma_dev->device_control = nbpf_control;
+
+	platform_set_drvdata(pdev, nbpf);
+
+	ret = clk_prepare_enable(nbpf->clk);
+	if (ret < 0)
+		return ret;
+
+	nbpf_configure(nbpf);
+
+	ret = dma_async_device_register(dma_dev);
+	if (ret < 0)
+		goto e_clk_off;
+
+	ret = of_dma_controller_register(np, nbpf_of_xlate, nbpf);
+	if (ret < 0)
+		goto e_dma_dev_unreg;
+
+	return 0;
+
+e_dma_dev_unreg:
+	dma_async_device_unregister(dma_dev);
+e_clk_off:
+	clk_disable_unprepare(nbpf->clk);
+
+	return ret;
+}
+
+static int nbpf_remove(struct platform_device *pdev)
+{
+	struct nbpf_device *nbpf = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&nbpf->dma_dev);
+	clk_disable_unprepare(nbpf->clk);
+
+	return 0;
+}
+
+static struct platform_device_id nbpf_ids[] = {
+	{"nbpfaxi64dmac1b4",	(kernel_ulong_t)&nbpf_cfg[NBPF1B4]},
+	{"nbpfaxi64dmac1b8",	(kernel_ulong_t)&nbpf_cfg[NBPF1B8]},
+	{"nbpfaxi64dmac1b16",	(kernel_ulong_t)&nbpf_cfg[NBPF1B16]},
+	{"nbpfaxi64dmac4b4",	(kernel_ulong_t)&nbpf_cfg[NBPF4B4]},
+	{"nbpfaxi64dmac4b8",	(kernel_ulong_t)&nbpf_cfg[NBPF4B8]},
+	{"nbpfaxi64dmac4b16",	(kernel_ulong_t)&nbpf_cfg[NBPF4B16]},
+	{"nbpfaxi64dmac8b4",	(kernel_ulong_t)&nbpf_cfg[NBPF8B4]},
+	{"nbpfaxi64dmac8b8",	(kernel_ulong_t)&nbpf_cfg[NBPF8B8]},
+	{"nbpfaxi64dmac8b16",	(kernel_ulong_t)&nbpf_cfg[NBPF8B16]},
+	{},
+};
+MODULE_DEVICE_TABLE(platform, nbpf_ids);
+
+#ifdef CONFIG_PM_RUNTIME
+static int nbpf_runtime_suspend(struct device *dev)
+{
+	struct nbpf_device *nbpf = platform_get_drvdata(to_platform_device(dev));
+	clk_disable_unprepare(nbpf->clk);
+	return 0;
+}
+
+static int nbpf_runtime_resume(struct device *dev)
+{
+	struct nbpf_device *nbpf = platform_get_drvdata(to_platform_device(dev));
+	return clk_prepare_enable(nbpf->clk);
+}
+#endif
+
+static const struct dev_pm_ops nbpf_pm_ops = {
+	SET_RUNTIME_PM_OPS(nbpf_runtime_suspend, nbpf_runtime_resume, NULL)
+};
+
+static struct platform_driver nbpf_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "dma-nbpf",
+		.of_match_table = nbpf_match,
+		.pm = &nbpf_pm_ops,
+	},
+	.id_table = nbpf_ids,
+	.probe = nbpf_probe,
+	.remove = nbpf_remove,
+};
+
+module_platform_driver(nbpf_driver);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("dmaengine driver for NBPFAXI64* DMACs");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/of-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/of-dma.c
--- linux-libre-3.16-gnu/drivers/dma/of-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/of-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(str
 			&dma_spec->args[0]);
 }
 EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+
+/**
+ * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
+ * @dma_spec:	pointer to DMA specifier as found in the device tree
+ * @of_dma:	pointer to DMA controller data
+ *
+ * This function can be used as the of xlate callback for DMA driver which wants
+ * to match the channel based on the channel id. When using this xlate function
+ * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
+ * The data parameter of of_dma_controller_register must be a pointer to the
+ * dma_device struct the function should match upon.
+ *
+ * Returns pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dma_device *dev = ofdma->of_dma_data;
+	struct dma_chan *chan, *candidate = NULL;
+
+	if (!dev || dma_spec->args_count != 1)
+		return NULL;
+
+	list_for_each_entry(chan, &dev->channels, device_node)
+		if (chan->chan_id == dma_spec->args[0]) {
+			candidate = chan;
+			break;
+		}
+
+	if (!candidate)
+		return NULL;
+
+	return dma_get_slave_channel(candidate);
+}
+EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/omap-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/omap-dma.c
--- linux-libre-3.16-gnu/drivers/dma/omap-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/omap-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -853,8 +853,7 @@ static struct dma_async_tx_descriptor *o
 
 static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-	size_t period_len, enum dma_transfer_direction dir, unsigned long flags,
-	void *context)
+	size_t period_len, enum dma_transfer_direction dir, unsigned long flags)
 {
 	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
@@ -1018,6 +1017,11 @@ static int omap_dma_resume(struct omap_c
 		return -EINVAL;
 
 	if (c->paused) {
+		mb();
+
+		/* Restore channel link register */
+		omap_dma_chan_write(c, CLNK_CTRL, c->desc->clnk_ctrl);
+
 		omap_dma_start(c, c->desc);
 		c->paused = false;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/pl330.c linux-libre-3.17-rc7-gnu/drivers/dma/pl330.c
--- linux-libre-3.16-gnu/drivers/dma/pl330.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/pl330.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,26 +33,15 @@
 #define PL330_MAX_IRQS		32
 #define PL330_MAX_PERI		32
 
-enum pl330_srccachectrl {
-	SCCTRL0,	/* Noncacheable and nonbufferable */
-	SCCTRL1,	/* Bufferable only */
-	SCCTRL2,	/* Cacheable, but do not allocate */
-	SCCTRL3,	/* Cacheable and bufferable, but do not allocate */
-	SINVALID1,
-	SINVALID2,
-	SCCTRL6,	/* Cacheable write-through, allocate on reads only */
-	SCCTRL7,	/* Cacheable write-back, allocate on reads only */
-};
-
-enum pl330_dstcachectrl {
-	DCCTRL0,	/* Noncacheable and nonbufferable */
-	DCCTRL1,	/* Bufferable only */
-	DCCTRL2,	/* Cacheable, but do not allocate */
-	DCCTRL3,	/* Cacheable and bufferable, but do not allocate */
-	DINVALID1,	/* AWCACHE = 0x1000 */
-	DINVALID2,
-	DCCTRL6,	/* Cacheable write-through, allocate on writes only */
-	DCCTRL7,	/* Cacheable write-back, allocate on writes only */
+enum pl330_cachectrl {
+	CCTRL0,		/* Noncacheable and nonbufferable */
+	CCTRL1,		/* Bufferable only */
+	CCTRL2,		/* Cacheable, but do not allocate */
+	CCTRL3,		/* Cacheable and bufferable, but do not allocate */
+	INVALID1,	/* AWCACHE = 0x1000 */
+	INVALID2,
+	CCTRL6,		/* Cacheable write-through, allocate on writes only */
+	CCTRL7,		/* Cacheable write-back, allocate on writes only */
 };
 
 enum pl330_byteswap {
@@ -63,13 +52,6 @@ enum pl330_byteswap {
 	SWAP_16,
 };
 
-enum pl330_reqtype {
-	MEMTOMEM,
-	MEMTODEV,
-	DEVTOMEM,
-	DEVTODEV,
-};
-
 /* Register and Bit field Definitions */
 #define DS			0x0
 #define DS_ST_STOP		0x0
@@ -263,9 +245,6 @@ enum pl330_reqtype {
  */
 #define MCODE_BUFF_PER_REQ	256
 
-/* If the _pl330_req is available to the client */
-#define IS_FREE(req)	(*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
-
 /* Use this _only_ to wait on transient states */
 #define UNTIL(t, s)	while (!(_state(t) & (s))) cpu_relax();
 
@@ -300,27 +279,6 @@ struct pl330_config {
 	u32		irq_ns;
 };
 
-/* Handle to the DMAC provided to the PL330 core */
-struct pl330_info {
-	/* Owning device */
-	struct device *dev;
-	/* Size of MicroCode buffers for each channel. */
-	unsigned mcbufsz;
-	/* ioremap'ed address of PL330 registers. */
-	void __iomem	*base;
-	/* Client can freely use it. */
-	void	*client_data;
-	/* PL330 core data, Client must not touch it. */
-	void	*pl330_data;
-	/* Populated by the PL330 core driver during pl330_add */
-	struct pl330_config	pcfg;
-	/*
-	 * If the DMAC has some reset mechanism, then the
-	 * client may want to provide pointer to the method.
-	 */
-	void (*dmac_reset)(struct pl330_info *pi);
-};
-
 /**
  * Request Configuration.
  * The PL330 core does not modify this and uses the last
@@ -344,8 +302,8 @@ struct pl330_reqcfg {
 	unsigned brst_len:5;
 	unsigned brst_size:3; /* in power of 2 */
 
-	enum pl330_dstcachectrl dcctl;
-	enum pl330_srccachectrl scctl;
+	enum pl330_cachectrl dcctl;
+	enum pl330_cachectrl scctl;
 	enum pl330_byteswap swap;
 	struct pl330_config *pcfg;
 };
@@ -359,11 +317,6 @@ struct pl330_xfer {
 	u32 dst_addr;
 	/* Size to xfer */
 	u32 bytes;
-	/*
-	 * Pointer to next xfer in the list.
-	 * The last xfer in the req must point to NULL.
-	 */
-	struct pl330_xfer *next;
 };
 
 /* The xfer callbacks are made with one of these arguments. */
@@ -376,67 +329,6 @@ enum pl330_op_err {
 	PL330_ERR_FAIL,
 };
 
-/* A request defining Scatter-Gather List ending with NULL xfer. */
-struct pl330_req {
-	enum pl330_reqtype rqtype;
-	/* Index of peripheral for the xfer. */
-	unsigned peri:5;
-	/* Unique token for this xfer, set by the client. */
-	void *token;
-	/* Callback to be called after xfer. */
-	void (*xfer_cb)(void *token, enum pl330_op_err err);
-	/* If NULL, req will be done at last set parameters. */
-	struct pl330_reqcfg *cfg;
-	/* Pointer to first xfer in the request. */
-	struct pl330_xfer *x;
-	/* Hook to attach to DMAC's list of reqs with due callback */
-	struct list_head rqd;
-};
-
-/*
- * To know the status of the channel and DMAC, the client
- * provides a pointer to this structure. The PL330 core
- * fills it with current information.
- */
-struct pl330_chanstatus {
-	/*
-	 * If the DMAC engine halted due to some error,
-	 * the client should remove-add DMAC.
-	 */
-	bool dmac_halted;
-	/*
-	 * If channel is halted due to some error,
-	 * the client should ABORT/FLUSH and START the channel.
-	 */
-	bool faulting;
-	/* Location of last load */
-	u32 src_addr;
-	/* Location of last store */
-	u32 dst_addr;
-	/*
-	 * Pointer to the currently active req, NULL if channel is
-	 * inactive, even though the requests may be present.
-	 */
-	struct pl330_req *top_req;
-	/* Pointer to req waiting second in the queue if any. */
-	struct pl330_req *wait_req;
-};
-
-enum pl330_chan_op {
-	/* Start the channel */
-	PL330_OP_START,
-	/* Abort the active xfer */
-	PL330_OP_ABORT,
-	/* Stop xfer and flush queue */
-	PL330_OP_FLUSH,
-};
-
-struct _xfer_spec {
-	u32 ccr;
-	struct pl330_req *r;
-	struct pl330_xfer *x;
-};
-
 enum dmamov_dst {
 	SAR = 0,
 	CCR,
@@ -454,12 +346,12 @@ enum pl330_cond {
 	ALWAYS,
 };
 
+struct dma_pl330_desc;
+
 struct _pl330_req {
 	u32 mc_bus;
 	void *mc_cpu;
-	/* Number of bytes taken to setup MC for the req */
-	u32 mc_len;
-	struct pl330_req *r;
+	struct dma_pl330_desc *desc;
 };
 
 /* ToBeDone for tasklet */
@@ -491,30 +383,6 @@ enum pl330_dmac_state {
 	DYING,
 };
 
-/* A DMAC */
-struct pl330_dmac {
-	spinlock_t		lock;
-	/* Holds list of reqs with due callbacks */
-	struct list_head	req_done;
-	/* Pointer to platform specific stuff */
-	struct pl330_info	*pinfo;
-	/* Maximum possible events/irqs */
-	int			events[32];
-	/* BUS address of MicroCode buffer */
-	dma_addr_t		mcode_bus;
-	/* CPU address of MicroCode buffer */
-	void			*mcode_cpu;
-	/* List of all Channel threads */
-	struct pl330_thread	*channels;
-	/* Pointer to the MANAGER thread */
-	struct pl330_thread	*manager;
-	/* To handle bad news in interrupt */
-	struct tasklet_struct	tasks;
-	struct _pl330_tbd	dmac_tbd;
-	/* State of DMAC operation */
-	enum pl330_dmac_state	state;
-};
-
 enum desc_status {
 	/* In the DMAC pool */
 	FREE,
@@ -555,15 +423,16 @@ struct dma_pl330_chan {
 	 * As the parent, this DMAC also provides descriptors
 	 * to the channel.
 	 */
-	struct dma_pl330_dmac *dmac;
+	struct pl330_dmac *dmac;
 
 	/* To protect channel manipulation */
 	spinlock_t lock;
 
-	/* Token of a hardware channel thread of PL330 DMAC
-	 * NULL if the channel is available to be acquired.
+	/*
+	 * Hardware channel thread of PL330 DMAC. NULL if the channel is
+	 * available.
 	 */
-	void *pl330_chid;
+	struct pl330_thread *thread;
 
 	/* For D-to-M and M-to-D channels */
 	int burst_sz; /* the peripheral fifo width */
@@ -574,9 +443,7 @@ struct dma_pl330_chan {
 	bool cyclic;
 };
 
-struct dma_pl330_dmac {
-	struct pl330_info pif;
-
+struct pl330_dmac {
 	/* DMA-Engine Device */
 	struct dma_device ddma;
 
@@ -588,6 +455,32 @@ struct dma_pl330_dmac {
 	/* To protect desc_pool manipulation */
 	spinlock_t pool_lock;
 
+	/* Size of MicroCode buffers for each channel. */
+	unsigned mcbufsz;
+	/* ioremap'ed address of PL330 registers. */
+	void __iomem	*base;
+	/* Populated by the PL330 core driver during pl330_add */
+	struct pl330_config	pcfg;
+
+	spinlock_t		lock;
+	/* Maximum possible events/irqs */
+	int			events[32];
+	/* BUS address of MicroCode buffer */
+	dma_addr_t		mcode_bus;
+	/* CPU address of MicroCode buffer */
+	void			*mcode_cpu;
+	/* List of all Channel threads */
+	struct pl330_thread	*channels;
+	/* Pointer to the MANAGER thread */
+	struct pl330_thread	*manager;
+	/* To handle bad news in interrupt */
+	struct tasklet_struct	tasks;
+	struct _pl330_tbd	dmac_tbd;
+	/* State of DMAC operation */
+	enum pl330_dmac_state	state;
+	/* Holds list of reqs with due callbacks */
+	struct list_head        req_done;
+
 	/* Peripheral channels connected to this DMAC */
 	unsigned int num_peripherals;
 	struct dma_pl330_chan *peripherals; /* keep at end */
@@ -604,49 +497,43 @@ struct dma_pl330_desc {
 	struct pl330_xfer px;
 
 	struct pl330_reqcfg rqcfg;
-	struct pl330_req req;
 
 	enum desc_status status;
 
 	/* The channel which currently holds this desc */
 	struct dma_pl330_chan *pchan;
+
+	enum dma_transfer_direction rqtype;
+	/* Index of peripheral for the xfer. */
+	unsigned peri:5;
+	/* Hook to attach to DMAC's list of reqs with due callback */
+	struct list_head rqd;
 };
 
-static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
-{
-	if (r && r->xfer_cb)
-		r->xfer_cb(r->token, err);
-}
+struct _xfer_spec {
+	u32 ccr;
+	struct dma_pl330_desc *desc;
+};
 
 static inline bool _queue_empty(struct pl330_thread *thrd)
 {
-	return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
-		? true : false;
+	return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
 }
 
 static inline bool _queue_full(struct pl330_thread *thrd)
 {
-	return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
-		? false : true;
+	return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
 }
 
 static inline bool is_manager(struct pl330_thread *thrd)
 {
-	struct pl330_dmac *pl330 = thrd->dmac;
-
-	/* MANAGER is indexed at the end */
-	if (thrd->id == pl330->pinfo->pcfg.num_chan)
-		return true;
-	else
-		return false;
+	return thrd->dmac->manager == thrd;
 }
 
 /* If manager of the thread is in Non-Secure mode */
 static inline bool _manager_ns(struct pl330_thread *thrd)
 {
-	struct pl330_dmac *pl330 = thrd->dmac;
-
-	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
+	return (thrd->dmac->pcfg.mode & DMAC_MODE_NS) ? true : false;
 }
 
 static inline u32 get_revision(u32 periph_id)
@@ -1004,7 +891,7 @@ static inline u32 _emit_GO(unsigned dry_
 /* Returns Time-Out */
 static bool _until_dmac_idle(struct pl330_thread *thrd)
 {
-	void __iomem *regs = thrd->dmac->pinfo->base;
+	void __iomem *regs = thrd->dmac->base;
 	unsigned long loops = msecs_to_loops(5);
 
 	do {
@@ -1024,7 +911,7 @@ static bool _until_dmac_idle(struct pl33
 static inline void _execute_DBGINSN(struct pl330_thread *thrd,
 		u8 insn[], bool as_manager)
 {
-	void __iomem *regs = thrd->dmac->pinfo->base;
+	void __iomem *regs = thrd->dmac->base;
 	u32 val;
 
 	val = (insn[0] << 16) | (insn[1] << 24);
@@ -1039,7 +926,7 @@ static inline void _execute_DBGINSN(stru
 
 	/* If timed out due to halted state-machine */
 	if (_until_dmac_idle(thrd)) {
-		dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
+		dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n");
 		return;
 	}
 
@@ -1047,25 +934,9 @@ static inline void _execute_DBGINSN(stru
 	writel(0, regs + DBGCMD);
 }
 
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-static void mark_free(struct pl330_thread *thrd, int idx)
-{
-	struct _pl330_req *req = &thrd->req[idx];
-
-	_emit_END(0, req->mc_cpu);
-	req->mc_len = 0;
-
-	thrd->req_running = -1;
-}
-
 static inline u32 _state(struct pl330_thread *thrd)
 {
-	void __iomem *regs = thrd->dmac->pinfo->base;
+	void __iomem *regs = thrd->dmac->base;
 	u32 val;
 
 	if (is_manager(thrd))
@@ -1123,7 +994,7 @@ static inline u32 _state(struct pl330_th
 
 static void _stop(struct pl330_thread *thrd)
 {
-	void __iomem *regs = thrd->dmac->pinfo->base;
+	void __iomem *regs = thrd->dmac->base;
 	u8 insn[6] = {0, 0, 0, 0, 0, 0};
 
 	if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
@@ -1146,9 +1017,9 @@ static void _stop(struct pl330_thread *t
 /* Start doing req 'idx' of thread 'thrd' */
 static bool _trigger(struct pl330_thread *thrd)
 {
-	void __iomem *regs = thrd->dmac->pinfo->base;
+	void __iomem *regs = thrd->dmac->base;
 	struct _pl330_req *req;
-	struct pl330_req *r;
+	struct dma_pl330_desc *desc;
 	struct _arg_GO go;
 	unsigned ns;
 	u8 insn[6] = {0, 0, 0, 0, 0, 0};
@@ -1159,32 +1030,27 @@ static bool _trigger(struct pl330_thread
 		return true;
 
 	idx = 1 - thrd->lstenq;
-	if (!IS_FREE(&thrd->req[idx]))
+	if (thrd->req[idx].desc != NULL) {
 		req = &thrd->req[idx];
-	else {
+	} else {
 		idx = thrd->lstenq;
-		if (!IS_FREE(&thrd->req[idx]))
+		if (thrd->req[idx].desc != NULL)
 			req = &thrd->req[idx];
 		else
 			req = NULL;
 	}
 
 	/* Return if no request */
-	if (!req || !req->r)
+	if (!req)
 		return true;
 
-	r = req->r;
+	desc = req->desc;
 
-	if (r->cfg)
-		ns = r->cfg->nonsecure ? 1 : 0;
-	else if (readl(regs + CS(thrd->id)) & CS_CNS)
-		ns = 1;
-	else
-		ns = 0;
+	ns = desc->rqcfg.nonsecure ? 1 : 0;
 
 	/* See 'Abort Sources' point-4 at Page 2-25 */
 	if (_manager_ns(thrd) && !ns)
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
+		dev_info(thrd->dmac->ddma.dev, "%s:%d Recipe for ABORT!\n",
 			__func__, __LINE__);
 
 	go.chan = thrd->id;
@@ -1240,7 +1106,7 @@ static inline int _ldst_memtomem(unsigne
 		const struct _xfer_spec *pxs, int cyc)
 {
 	int off = 0;
-	struct pl330_config *pcfg = pxs->r->cfg->pcfg;
+	struct pl330_config *pcfg = pxs->desc->rqcfg.pcfg;
 
 	/* check lock-up free version */
 	if (get_revision(pcfg->periph_id) >= PERIPH_REV_R1P0) {
@@ -1266,10 +1132,10 @@ static inline int _ldst_devtomem(unsigne
 	int off = 0;
 
 	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+		off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
 		off += _emit_ST(dry_run, &buf[off], ALWAYS);
-		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
 	}
 
 	return off;
@@ -1281,10 +1147,10 @@ static inline int _ldst_memtodev(unsigne
 	int off = 0;
 
 	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
 		off += _emit_LD(dry_run, &buf[off], ALWAYS);
-		off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+		off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
 	}
 
 	return off;
@@ -1295,14 +1161,14 @@ static int _bursts(unsigned dry_run, u8
 {
 	int off = 0;
 
-	switch (pxs->r->rqtype) {
-	case MEMTODEV:
+	switch (pxs->desc->rqtype) {
+	case DMA_MEM_TO_DEV:
 		off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
 		break;
-	case DEVTOMEM:
+	case DMA_DEV_TO_MEM:
 		off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
 		break;
-	case MEMTOMEM:
+	case DMA_MEM_TO_MEM:
 		off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
 		break;
 	default:
@@ -1395,7 +1261,7 @@ static inline int _loop(unsigned dry_run
 static inline int _setup_loops(unsigned dry_run, u8 buf[],
 		const struct _xfer_spec *pxs)
 {
-	struct pl330_xfer *x = pxs->x;
+	struct pl330_xfer *x = &pxs->desc->px;
 	u32 ccr = pxs->ccr;
 	unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
 	int off = 0;
@@ -1412,7 +1278,7 @@ static inline int _setup_loops(unsigned
 static inline int _setup_xfer(unsigned dry_run, u8 buf[],
 		const struct _xfer_spec *pxs)
 {
-	struct pl330_xfer *x = pxs->x;
+	struct pl330_xfer *x = &pxs->desc->px;
 	int off = 0;
 
 	/* DMAMOV SAR, x->src_addr */
@@ -1443,17 +1309,12 @@ static int _setup_req(unsigned dry_run,
 	/* DMAMOV CCR, ccr */
 	off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
 
-	x = pxs->r->x;
-	do {
-		/* Error if xfer length is not aligned at burst size */
-		if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
-			return -EINVAL;
-
-		pxs->x = x;
-		off += _setup_xfer(dry_run, &buf[off], pxs);
+	x = &pxs->desc->px;
+	/* Error if xfer length is not aligned at burst size */
+	if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
+		return -EINVAL;
 
-		x = x->next;
-	} while (x);
+	off += _setup_xfer(dry_run, &buf[off], pxs);
 
 	/* DMASEV peripheral/event */
 	off += _emit_SEV(dry_run, &buf[off], thrd->ev);
@@ -1495,31 +1356,15 @@ static inline u32 _prepare_ccr(const str
 	return ccr;
 }
 
-static inline bool _is_valid(u32 ccr)
-{
-	enum pl330_dstcachectrl dcctl;
-	enum pl330_srccachectrl scctl;
-
-	dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
-	scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
-
-	if (dcctl == DINVALID1 || dcctl == DINVALID2
-			|| scctl == SINVALID1 || scctl == SINVALID2)
-		return false;
-	else
-		return true;
-}
-
 /*
  * Submit a list of xfers after which the client wants notification.
  * Client is not notified after each xfer unit, just once after all
  * xfer units are done or some error occurs.
  */
-static int pl330_submit_req(void *ch_id, struct pl330_req *r)
+static int pl330_submit_req(struct pl330_thread *thrd,
+	struct dma_pl330_desc *desc)
 {
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	struct pl330_info *pi;
+	struct pl330_dmac *pl330 = thrd->dmac;
 	struct _xfer_spec xs;
 	unsigned long flags;
 	void __iomem *regs;
@@ -1528,25 +1373,24 @@ static int pl330_submit_req(void *ch_id,
 	int ret = 0;
 
 	/* No Req or Unacquired Channel or DMAC */
-	if (!r || !thrd || thrd->free)
+	if (!desc || !thrd || thrd->free)
 		return -EINVAL;
 
-	pl330 = thrd->dmac;
-	pi = pl330->pinfo;
-	regs = pi->base;
+	regs = thrd->dmac->base;
 
 	if (pl330->state == DYING
 		|| pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
+		dev_info(thrd->dmac->ddma.dev, "%s:%d\n",
 			__func__, __LINE__);
 		return -EAGAIN;
 	}
 
 	/* If request for non-existing peripheral */
-	if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
-		dev_info(thrd->dmac->pinfo->dev,
+	if (desc->rqtype != DMA_MEM_TO_MEM &&
+	    desc->peri >= pl330->pcfg.num_peri) {
+		dev_info(thrd->dmac->ddma.dev,
 				"%s:%d Invalid peripheral(%u)!\n",
-				__func__, __LINE__, r->peri);
+				__func__, __LINE__, desc->peri);
 		return -EINVAL;
 	}
 
@@ -1557,41 +1401,26 @@ static int pl330_submit_req(void *ch_id,
 		goto xfer_exit;
 	}
 
+	/* Prefer Secure Channel */
+	if (!_manager_ns(thrd))
+		desc->rqcfg.nonsecure = 0;
+	else
+		desc->rqcfg.nonsecure = 1;
 
-	/* Use last settings, if not provided */
-	if (r->cfg) {
-		/* Prefer Secure Channel */
-		if (!_manager_ns(thrd))
-			r->cfg->nonsecure = 0;
-		else
-			r->cfg->nonsecure = 1;
-
-		ccr = _prepare_ccr(r->cfg);
-	} else {
-		ccr = readl(regs + CC(thrd->id));
-	}
-
-	/* If this req doesn't have valid xfer settings */
-	if (!_is_valid(ccr)) {
-		ret = -EINVAL;
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
-			__func__, __LINE__, ccr);
-		goto xfer_exit;
-	}
+	ccr = _prepare_ccr(&desc->rqcfg);
 
-	idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
+	idx = thrd->req[0].desc == NULL ? 0 : 1;
 
 	xs.ccr = ccr;
-	xs.r = r;
+	xs.desc = desc;
 
 	/* First dry run to check if req is acceptable */
 	ret = _setup_req(1, thrd, idx, &xs);
 	if (ret < 0)
 		goto xfer_exit;
 
-	if (ret > pi->mcbufsz / 2) {
-		dev_info(thrd->dmac->pinfo->dev,
-			"%s:%d Trying increasing mcbufsz\n",
+	if (ret > pl330->mcbufsz / 2) {
+		dev_info(pl330->ddma.dev, "%s:%d Trying increasing mcbufsz\n",
 				__func__, __LINE__);
 		ret = -ENOMEM;
 		goto xfer_exit;
@@ -1599,8 +1428,8 @@ static int pl330_submit_req(void *ch_id,
 
 	/* Hook the request */
 	thrd->lstenq = idx;
-	thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
-	thrd->req[idx].r = r;
+	thrd->req[idx].desc = desc;
+	_setup_req(0, thrd, idx, &xs);
 
 	ret = 0;
 
@@ -1610,10 +1439,32 @@ xfer_exit:
 	return ret;
 }
 
+static void dma_pl330_rqcb(struct dma_pl330_desc *desc, enum pl330_op_err err)
+{
+	struct dma_pl330_chan *pch;
+	unsigned long flags;
+
+	if (!desc)
+		return;
+
+	pch = desc->pchan;
+
+	/* If desc aborted */
+	if (!pch)
+		return;
+
+	spin_lock_irqsave(&pch->lock, flags);
+
+	desc->status = DONE;
+
+	spin_unlock_irqrestore(&pch->lock, flags);
+
+	tasklet_schedule(&pch->task);
+}
+
 static void pl330_dotask(unsigned long data)
 {
 	struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
-	struct pl330_info *pi = pl330->pinfo;
 	unsigned long flags;
 	int i;
 
@@ -1631,16 +1482,16 @@ static void pl330_dotask(unsigned long d
 	if (pl330->dmac_tbd.reset_mngr) {
 		_stop(pl330->manager);
 		/* Reset all channels */
-		pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
+		pl330->dmac_tbd.reset_chan = (1 << pl330->pcfg.num_chan) - 1;
 		/* Clear the reset flag */
 		pl330->dmac_tbd.reset_mngr = false;
 	}
 
-	for (i = 0; i < pi->pcfg.num_chan; i++) {
+	for (i = 0; i < pl330->pcfg.num_chan; i++) {
 
 		if (pl330->dmac_tbd.reset_chan & (1 << i)) {
 			struct pl330_thread *thrd = &pl330->channels[i];
-			void __iomem *regs = pi->base;
+			void __iomem *regs = pl330->base;
 			enum pl330_op_err err;
 
 			_stop(thrd);
@@ -1651,16 +1502,13 @@ static void pl330_dotask(unsigned long d
 				err = PL330_ERR_ABORT;
 
 			spin_unlock_irqrestore(&pl330->lock, flags);
-
-			_callback(thrd->req[1 - thrd->lstenq].r, err);
-			_callback(thrd->req[thrd->lstenq].r, err);
-
+			dma_pl330_rqcb(thrd->req[1 - thrd->lstenq].desc, err);
+			dma_pl330_rqcb(thrd->req[thrd->lstenq].desc, err);
 			spin_lock_irqsave(&pl330->lock, flags);
 
-			thrd->req[0].r = NULL;
-			thrd->req[1].r = NULL;
-			mark_free(thrd, 0);
-			mark_free(thrd, 1);
+			thrd->req[0].desc = NULL;
+			thrd->req[1].desc = NULL;
+			thrd->req_running = -1;
 
 			/* Clear the reset flag */
 			pl330->dmac_tbd.reset_chan &= ~(1 << i);
@@ -1673,20 +1521,15 @@ static void pl330_dotask(unsigned long d
 }
 
 /* Returns 1 if state was updated, 0 otherwise */
-static int pl330_update(const struct pl330_info *pi)
+static int pl330_update(struct pl330_dmac *pl330)
 {
-	struct pl330_req *rqdone, *tmp;
-	struct pl330_dmac *pl330;
+	struct dma_pl330_desc *descdone, *tmp;
 	unsigned long flags;
 	void __iomem *regs;
 	u32 val;
 	int id, ev, ret = 0;
 
-	if (!pi || !pi->pl330_data)
-		return 0;
-
-	regs = pi->base;
-	pl330 = pi->pl330_data;
+	regs = pl330->base;
 
 	spin_lock_irqsave(&pl330->lock, flags);
 
@@ -1696,13 +1539,13 @@ static int pl330_update(const struct pl3
 	else
 		pl330->dmac_tbd.reset_mngr = false;
 
-	val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
+	val = readl(regs + FSC) & ((1 << pl330->pcfg.num_chan) - 1);
 	pl330->dmac_tbd.reset_chan |= val;
 	if (val) {
 		int i = 0;
-		while (i < pi->pcfg.num_chan) {
+		while (i < pl330->pcfg.num_chan) {
 			if (val & (1 << i)) {
-				dev_info(pi->dev,
+				dev_info(pl330->ddma.dev,
 					"Reset Channel-%d\t CS-%x FTC-%x\n",
 						i, readl(regs + CS(i)),
 						readl(regs + FTC(i)));
@@ -1714,15 +1557,16 @@ static int pl330_update(const struct pl3
 
 	/* Check which event happened i.e, thread notified */
 	val = readl(regs + ES);
-	if (pi->pcfg.num_events < 32
-			&& val & ~((1 << pi->pcfg.num_events) - 1)) {
+	if (pl330->pcfg.num_events < 32
+			&& val & ~((1 << pl330->pcfg.num_events) - 1)) {
 		pl330->dmac_tbd.reset_dmac = true;
-		dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
+		dev_err(pl330->ddma.dev, "%s:%d Unexpected!\n", __func__,
+			__LINE__);
 		ret = 1;
 		goto updt_exit;
 	}
 
-	for (ev = 0; ev < pi->pcfg.num_events; ev++) {
+	for (ev = 0; ev < pl330->pcfg.num_events; ev++) {
 		if (val & (1 << ev)) { /* Event occurred */
 			struct pl330_thread *thrd;
 			u32 inten = readl(regs + INTEN);
@@ -1743,25 +1587,22 @@ static int pl330_update(const struct pl3
 				continue;
 
 			/* Detach the req */
-			rqdone = thrd->req[active].r;
-			thrd->req[active].r = NULL;
-
-			mark_free(thrd, active);
+			descdone = thrd->req[active].desc;
+			thrd->req[active].desc = NULL;
 
 			/* Get going again ASAP */
 			_start(thrd);
 
 			/* For now, just make a list of callbacks to be done */
-			list_add_tail(&rqdone->rqd, &pl330->req_done);
+			list_add_tail(&descdone->rqd, &pl330->req_done);
 		}
 	}
 
 	/* Now that we are in no hurry, do the callbacks */
-	list_for_each_entry_safe(rqdone, tmp, &pl330->req_done, rqd) {
-		list_del(&rqdone->rqd);
-
+	list_for_each_entry_safe(descdone, tmp, &pl330->req_done, rqd) {
+		list_del(&descdone->rqd);
 		spin_unlock_irqrestore(&pl330->lock, flags);
-		_callback(rqdone, PL330_ERR_NONE);
+		dma_pl330_rqcb(descdone, PL330_ERR_NONE);
 		spin_lock_irqsave(&pl330->lock, flags);
 	}
 
@@ -1778,65 +1619,13 @@ updt_exit:
 	return ret;
 }
 
-static int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
-{
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	unsigned long flags;
-	int ret = 0, active;
-
-	if (!thrd || thrd->free || thrd->dmac->state == DYING)
-		return -EINVAL;
-
-	pl330 = thrd->dmac;
-	active = thrd->req_running;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	switch (op) {
-	case PL330_OP_FLUSH:
-		/* Make sure the channel is stopped */
-		_stop(thrd);
-
-		thrd->req[0].r = NULL;
-		thrd->req[1].r = NULL;
-		mark_free(thrd, 0);
-		mark_free(thrd, 1);
-		break;
-
-	case PL330_OP_ABORT:
-		/* Make sure the channel is stopped */
-		_stop(thrd);
-
-		/* ABORT is only for the active req */
-		if (active == -1)
-			break;
-
-		thrd->req[active].r = NULL;
-		mark_free(thrd, active);
-
-		/* Start the next */
-	case PL330_OP_START:
-		if ((active == -1) && !_start(thrd))
-			ret = -EIO;
-		break;
-
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&pl330->lock, flags);
-	return ret;
-}
-
 /* Reserve an event */
 static inline int _alloc_event(struct pl330_thread *thrd)
 {
 	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
 	int ev;
 
-	for (ev = 0; ev < pi->pcfg.num_events; ev++)
+	for (ev = 0; ev < pl330->pcfg.num_events; ev++)
 		if (pl330->events[ev] == -1) {
 			pl330->events[ev] = thrd->id;
 			return ev;
@@ -1845,45 +1634,38 @@ static inline int _alloc_event(struct pl
 	return -1;
 }
 
-static bool _chan_ns(const struct pl330_info *pi, int i)
+static bool _chan_ns(const struct pl330_dmac *pl330, int i)
 {
-	return pi->pcfg.irq_ns & (1 << i);
+	return pl330->pcfg.irq_ns & (1 << i);
 }
 
 /* Upon success, returns IdentityToken for the
  * allocated channel, NULL otherwise.
  */
-static void *pl330_request_channel(const struct pl330_info *pi)
+static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
 {
 	struct pl330_thread *thrd = NULL;
-	struct pl330_dmac *pl330;
 	unsigned long flags;
 	int chans, i;
 
-	if (!pi || !pi->pl330_data)
-		return NULL;
-
-	pl330 = pi->pl330_data;
-
 	if (pl330->state == DYING)
 		return NULL;
 
-	chans = pi->pcfg.num_chan;
+	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) ||
-					_chan_ns(pi, i))) {
+					_chan_ns(pl330, i))) {
 			thrd->ev = _alloc_event(thrd);
 			if (thrd->ev >= 0) {
 				thrd->free = false;
 				thrd->lstenq = 1;
-				thrd->req[0].r = NULL;
-				mark_free(thrd, 0);
-				thrd->req[1].r = NULL;
-				mark_free(thrd, 1);
+				thrd->req[0].desc = NULL;
+				thrd->req[1].desc = NULL;
+				thrd->req_running = -1;
 				break;
 			}
 		}
@@ -1899,17 +1681,15 @@ static void *pl330_request_channel(const
 static inline void _free_event(struct pl330_thread *thrd, int ev)
 {
 	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
 
 	/* If the event is valid and was held by the thread */
-	if (ev >= 0 && ev < pi->pcfg.num_events
+	if (ev >= 0 && ev < pl330->pcfg.num_events
 			&& pl330->events[ev] == thrd->id)
 		pl330->events[ev] = -1;
 }
 
-static void pl330_release_channel(void *ch_id)
+static void pl330_release_channel(struct pl330_thread *thrd)
 {
-	struct pl330_thread *thrd = ch_id;
 	struct pl330_dmac *pl330;
 	unsigned long flags;
 
@@ -1918,8 +1698,8 @@ static void pl330_release_channel(void *
 
 	_stop(thrd);
 
-	_callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
-	_callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
+	dma_pl330_rqcb(thrd->req[1 - thrd->lstenq].desc, PL330_ERR_ABORT);
+	dma_pl330_rqcb(thrd->req[thrd->lstenq].desc, PL330_ERR_ABORT);
 
 	pl330 = thrd->dmac;
 
@@ -1932,72 +1712,70 @@ static void pl330_release_channel(void *
 /* Initialize the structure for PL330 configuration, that can be used
  * by the client driver the make best use of the DMAC
  */
-static void read_dmac_config(struct pl330_info *pi)
+static void read_dmac_config(struct pl330_dmac *pl330)
 {
-	void __iomem *regs = pi->base;
+	void __iomem *regs = pl330->base;
 	u32 val;
 
 	val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
 	val &= CRD_DATA_WIDTH_MASK;
-	pi->pcfg.data_bus_width = 8 * (1 << val);
+	pl330->pcfg.data_bus_width = 8 * (1 << val);
 
 	val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
 	val &= CRD_DATA_BUFF_MASK;
-	pi->pcfg.data_buf_dep = val + 1;
+	pl330->pcfg.data_buf_dep = val + 1;
 
 	val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
 	val &= CR0_NUM_CHANS_MASK;
 	val += 1;
-	pi->pcfg.num_chan = val;
+	pl330->pcfg.num_chan = val;
 
 	val = readl(regs + CR0);
 	if (val & CR0_PERIPH_REQ_SET) {
 		val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
 		val += 1;
-		pi->pcfg.num_peri = val;
-		pi->pcfg.peri_ns = readl(regs + CR4);
+		pl330->pcfg.num_peri = val;
+		pl330->pcfg.peri_ns = readl(regs + CR4);
 	} else {
-		pi->pcfg.num_peri = 0;
+		pl330->pcfg.num_peri = 0;
 	}
 
 	val = readl(regs + CR0);
 	if (val & CR0_BOOT_MAN_NS)
-		pi->pcfg.mode |= DMAC_MODE_NS;
+		pl330->pcfg.mode |= DMAC_MODE_NS;
 	else
-		pi->pcfg.mode &= ~DMAC_MODE_NS;
+		pl330->pcfg.mode &= ~DMAC_MODE_NS;
 
 	val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
 	val &= CR0_NUM_EVENTS_MASK;
 	val += 1;
-	pi->pcfg.num_events = val;
+	pl330->pcfg.num_events = val;
 
-	pi->pcfg.irq_ns = readl(regs + CR3);
+	pl330->pcfg.irq_ns = readl(regs + CR3);
 }
 
 static inline void _reset_thread(struct pl330_thread *thrd)
 {
 	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
 
 	thrd->req[0].mc_cpu = pl330->mcode_cpu
-				+ (thrd->id * pi->mcbufsz);
+				+ (thrd->id * pl330->mcbufsz);
 	thrd->req[0].mc_bus = pl330->mcode_bus
-				+ (thrd->id * pi->mcbufsz);
-	thrd->req[0].r = NULL;
-	mark_free(thrd, 0);
+				+ (thrd->id * pl330->mcbufsz);
+	thrd->req[0].desc = NULL;
 
 	thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
-				+ pi->mcbufsz / 2;
+				+ pl330->mcbufsz / 2;
 	thrd->req[1].mc_bus = thrd->req[0].mc_bus
-				+ pi->mcbufsz / 2;
-	thrd->req[1].r = NULL;
-	mark_free(thrd, 1);
+				+ pl330->mcbufsz / 2;
+	thrd->req[1].desc = NULL;
+
+	thrd->req_running = -1;
 }
 
 static int dmac_alloc_threads(struct pl330_dmac *pl330)
 {
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
+	int chans = pl330->pcfg.num_chan;
 	struct pl330_thread *thrd;
 	int i;
 
@@ -2028,29 +1806,28 @@ static int dmac_alloc_threads(struct pl3
 
 static int dmac_alloc_resources(struct pl330_dmac *pl330)
 {
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
+	int chans = pl330->pcfg.num_chan;
 	int ret;
 
 	/*
 	 * Alloc MicroCode buffer for 'chans' Channel threads.
 	 * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
 	 */
-	pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
-				chans * pi->mcbufsz,
+	pl330->mcode_cpu = dma_alloc_coherent(pl330->ddma.dev,
+				chans * pl330->mcbufsz,
 				&pl330->mcode_bus, GFP_KERNEL);
 	if (!pl330->mcode_cpu) {
-		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+		dev_err(pl330->ddma.dev, "%s:%d Can't allocate memory!\n",
 			__func__, __LINE__);
 		return -ENOMEM;
 	}
 
 	ret = dmac_alloc_threads(pl330);
 	if (ret) {
-		dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
+		dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n",
 			__func__, __LINE__);
-		dma_free_coherent(pi->dev,
-				chans * pi->mcbufsz,
+		dma_free_coherent(pl330->ddma.dev,
+				chans * pl330->mcbufsz,
 				pl330->mcode_cpu, pl330->mcode_bus);
 		return ret;
 	}
@@ -2058,71 +1835,45 @@ static int dmac_alloc_resources(struct p
 	return 0;
 }
 
-static int pl330_add(struct pl330_info *pi)
+static int pl330_add(struct pl330_dmac *pl330)
 {
-	struct pl330_dmac *pl330;
 	void __iomem *regs;
 	int i, ret;
 
-	if (!pi || !pi->dev)
-		return -EINVAL;
-
-	/* If already added */
-	if (pi->pl330_data)
-		return -EINVAL;
-
-	/*
-	 * If the SoC can perform reset on the DMAC, then do it
-	 * before reading its configuration.
-	 */
-	if (pi->dmac_reset)
-		pi->dmac_reset(pi);
-
-	regs = pi->base;
+	regs = pl330->base;
 
 	/* Check if we can handle this DMAC */
-	if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
-		dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id);
+	if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
+		dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n",
+			pl330->pcfg.periph_id);
 		return -EINVAL;
 	}
 
 	/* Read the configuration of the DMAC */
-	read_dmac_config(pi);
+	read_dmac_config(pl330);
 
-	if (pi->pcfg.num_events == 0) {
-		dev_err(pi->dev, "%s:%d Can't work without events!\n",
+	if (pl330->pcfg.num_events == 0) {
+		dev_err(pl330->ddma.dev, "%s:%d Can't work without events!\n",
 			__func__, __LINE__);
 		return -EINVAL;
 	}
 
-	pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
-	if (!pl330) {
-		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
-			__func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	/* Assign the info structure and private data */
-	pl330->pinfo = pi;
-	pi->pl330_data = pl330;
-
 	spin_lock_init(&pl330->lock);
 
 	INIT_LIST_HEAD(&pl330->req_done);
 
 	/* Use default MC buffer size if not provided */
-	if (!pi->mcbufsz)
-		pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
+	if (!pl330->mcbufsz)
+		pl330->mcbufsz = MCODE_BUFF_PER_REQ * 2;
 
 	/* Mark all events as free */
-	for (i = 0; i < pi->pcfg.num_events; i++)
+	for (i = 0; i < pl330->pcfg.num_events; i++)
 		pl330->events[i] = -1;
 
 	/* Allocate resources needed by the DMAC */
 	ret = dmac_alloc_resources(pl330);
 	if (ret) {
-		dev_err(pi->dev, "Unable to create channels for DMAC\n");
-		kfree(pl330);
+		dev_err(pl330->ddma.dev, "Unable to create channels for DMAC\n");
 		return ret;
 	}
 
@@ -2135,15 +1886,13 @@ static int pl330_add(struct pl330_info *
 
 static int dmac_free_threads(struct pl330_dmac *pl330)
 {
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
 	struct pl330_thread *thrd;
 	int i;
 
 	/* Release Channel threads */
-	for (i = 0; i < chans; i++) {
+	for (i = 0; i < pl330->pcfg.num_chan; i++) {
 		thrd = &pl330->channels[i];
-		pl330_release_channel((void *)thrd);
+		pl330_release_channel(thrd);
 	}
 
 	/* Free memory */
@@ -2152,35 +1901,18 @@ static int dmac_free_threads(struct pl33
 	return 0;
 }
 
-static void dmac_free_resources(struct pl330_dmac *pl330)
-{
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
-
-	dmac_free_threads(pl330);
-
-	dma_free_coherent(pi->dev, chans * pi->mcbufsz,
-				pl330->mcode_cpu, pl330->mcode_bus);
-}
-
-static void pl330_del(struct pl330_info *pi)
+static void pl330_del(struct pl330_dmac *pl330)
 {
-	struct pl330_dmac *pl330;
-
-	if (!pi || !pi->pl330_data)
-		return;
-
-	pl330 = pi->pl330_data;
-
 	pl330->state = UNINIT;
 
 	tasklet_kill(&pl330->tasks);
 
 	/* Free DMAC resources */
-	dmac_free_resources(pl330);
+	dmac_free_threads(pl330);
 
-	kfree(pl330);
-	pi->pl330_data = NULL;
+	dma_free_coherent(pl330->ddma.dev,
+		pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu,
+		pl330->mcode_bus);
 }
 
 /* forward declaration */
@@ -2212,8 +1944,7 @@ static inline void fill_queue(struct dma
 		if (desc->status == BUSY)
 			continue;
 
-		ret = pl330_submit_req(pch->pl330_chid,
-						&desc->req);
+		ret = pl330_submit_req(pch->thread, desc);
 		if (!ret) {
 			desc->status = BUSY;
 		} else if (ret == -EAGAIN) {
@@ -2222,7 +1953,7 @@ static inline void fill_queue(struct dma
 		} else {
 			/* Unacceptable request */
 			desc->status = DONE;
-			dev_err(pch->dmac->pif.dev, "%s:%d Bad Desc(%d)\n",
+			dev_err(pch->dmac->ddma.dev, "%s:%d Bad Desc(%d)\n",
 					__func__, __LINE__, desc->txd.cookie);
 			tasklet_schedule(&pch->task);
 		}
@@ -2249,7 +1980,9 @@ static void pl330_tasklet(unsigned long
 	fill_queue(pch);
 
 	/* Make sure the PL330 Channel thread is active */
-	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
+	spin_lock(&pch->thread->dmac->lock);
+	_start(pch->thread);
+	spin_unlock(&pch->thread->dmac->lock);
 
 	while (!list_empty(&pch->completed_list)) {
 		dma_async_tx_callback callback;
@@ -2280,25 +2013,6 @@ static void pl330_tasklet(unsigned long
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
-static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
-{
-	struct dma_pl330_desc *desc = token;
-	struct dma_pl330_chan *pch = desc->pchan;
-	unsigned long flags;
-
-	/* If desc aborted */
-	if (!pch)
-		return;
-
-	spin_lock_irqsave(&pch->lock, flags);
-
-	desc->status = DONE;
-
-	spin_unlock_irqrestore(&pch->lock, flags);
-
-	tasklet_schedule(&pch->task);
-}
-
 bool pl330_filter(struct dma_chan *chan, void *param)
 {
 	u8 *peri_id;
@@ -2315,23 +2029,26 @@ static struct dma_chan *of_dma_pl330_xla
 						struct of_dma *ofdma)
 {
 	int count = dma_spec->args_count;
-	struct dma_pl330_dmac *pdmac = ofdma->of_dma_data;
+	struct pl330_dmac *pl330 = ofdma->of_dma_data;
 	unsigned int chan_id;
 
+	if (!pl330)
+		return NULL;
+
 	if (count != 1)
 		return NULL;
 
 	chan_id = dma_spec->args[0];
-	if (chan_id >= pdmac->num_peripherals)
+	if (chan_id >= pl330->num_peripherals)
 		return NULL;
 
-	return dma_get_slave_channel(&pdmac->peripherals[chan_id].chan);
+	return dma_get_slave_channel(&pl330->peripherals[chan_id].chan);
 }
 
 static int pl330_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct pl330_dmac *pl330 = pch->dmac;
 	unsigned long flags;
 
 	spin_lock_irqsave(&pch->lock, flags);
@@ -2339,8 +2056,8 @@ static int pl330_alloc_chan_resources(st
 	dma_cookie_init(chan);
 	pch->cyclic = false;
 
-	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
-	if (!pch->pl330_chid) {
+	pch->thread = pl330_request_channel(pl330);
+	if (!pch->thread) {
 		spin_unlock_irqrestore(&pch->lock, flags);
 		return -ENOMEM;
 	}
@@ -2357,7 +2074,7 @@ static int pl330_control(struct dma_chan
 	struct dma_pl330_chan *pch = to_pchan(chan);
 	struct dma_pl330_desc *desc;
 	unsigned long flags;
-	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct pl330_dmac *pl330 = pch->dmac;
 	struct dma_slave_config *slave_config;
 	LIST_HEAD(list);
 
@@ -2365,8 +2082,13 @@ static int pl330_control(struct dma_chan
 	case DMA_TERMINATE_ALL:
 		spin_lock_irqsave(&pch->lock, flags);
 
-		/* FLUSH the PL330 Channel thread */
-		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+		spin_lock(&pl330->lock);
+		_stop(pch->thread);
+		spin_unlock(&pl330->lock);
+
+		pch->thread->req[0].desc = NULL;
+		pch->thread->req[1].desc = NULL;
+		pch->thread->req_running = -1;
 
 		/* Mark all desc done */
 		list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2384,9 +2106,9 @@ static int pl330_control(struct dma_chan
 			dma_cookie_complete(&desc->txd);
 		}
 
-		list_splice_tail_init(&pch->submitted_list, &pdmac->desc_pool);
-		list_splice_tail_init(&pch->work_list, &pdmac->desc_pool);
-		list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool);
+		list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool);
+		list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
+		list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
 		spin_unlock_irqrestore(&pch->lock, flags);
 		break;
 	case DMA_SLAVE_CONFIG:
@@ -2409,7 +2131,7 @@ static int pl330_control(struct dma_chan
 		}
 		break;
 	default:
-		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+		dev_err(pch->dmac->ddma.dev, "Not supported command.\n");
 		return -ENXIO;
 	}
 
@@ -2425,8 +2147,8 @@ static void pl330_free_chan_resources(st
 
 	spin_lock_irqsave(&pch->lock, flags);
 
-	pl330_release_channel(pch->pl330_chid);
-	pch->pl330_chid = NULL;
+	pl330_release_channel(pch->thread);
+	pch->thread = NULL;
 
 	if (pch->cyclic)
 		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
@@ -2489,57 +2211,46 @@ static dma_cookie_t pl330_tx_submit(stru
 
 static inline void _init_desc(struct dma_pl330_desc *desc)
 {
-	desc->req.x = &desc->px;
-	desc->req.token = desc;
 	desc->rqcfg.swap = SWAP_NO;
-	desc->rqcfg.scctl = SCCTRL0;
-	desc->rqcfg.dcctl = DCCTRL0;
-	desc->req.cfg = &desc->rqcfg;
-	desc->req.xfer_cb = dma_pl330_rqcb;
+	desc->rqcfg.scctl = CCTRL0;
+	desc->rqcfg.dcctl = CCTRL0;
 	desc->txd.tx_submit = pl330_tx_submit;
 
 	INIT_LIST_HEAD(&desc->node);
 }
 
 /* Returns the number of descriptors added to the DMAC pool */
-static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
+static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
 {
 	struct dma_pl330_desc *desc;
 	unsigned long flags;
 	int i;
 
-	if (!pdmac)
-		return 0;
-
 	desc = kcalloc(count, sizeof(*desc), flg);
 	if (!desc)
 		return 0;
 
-	spin_lock_irqsave(&pdmac->pool_lock, flags);
+	spin_lock_irqsave(&pl330->pool_lock, flags);
 
 	for (i = 0; i < count; i++) {
 		_init_desc(&desc[i]);
-		list_add_tail(&desc[i].node, &pdmac->desc_pool);
+		list_add_tail(&desc[i].node, &pl330->desc_pool);
 	}
 
-	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+	spin_unlock_irqrestore(&pl330->pool_lock, flags);
 
 	return count;
 }
 
-static struct dma_pl330_desc *
-pluck_desc(struct dma_pl330_dmac *pdmac)
+static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
 {
 	struct dma_pl330_desc *desc = NULL;
 	unsigned long flags;
 
-	if (!pdmac)
-		return NULL;
-
-	spin_lock_irqsave(&pdmac->pool_lock, flags);
+	spin_lock_irqsave(&pl330->pool_lock, flags);
 
-	if (!list_empty(&pdmac->desc_pool)) {
-		desc = list_entry(pdmac->desc_pool.next,
+	if (!list_empty(&pl330->desc_pool)) {
+		desc = list_entry(pl330->desc_pool.next,
 				struct dma_pl330_desc, node);
 
 		list_del_init(&desc->node);
@@ -2548,29 +2259,29 @@ pluck_desc(struct dma_pl330_dmac *pdmac)
 		desc->txd.callback = NULL;
 	}
 
-	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+	spin_unlock_irqrestore(&pl330->pool_lock, flags);
 
 	return desc;
 }
 
 static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 {
-	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct pl330_dmac *pl330 = pch->dmac;
 	u8 *peri_id = pch->chan.private;
 	struct dma_pl330_desc *desc;
 
 	/* Pluck one desc from the pool of DMAC */
-	desc = pluck_desc(pdmac);
+	desc = pluck_desc(pl330);
 
 	/* If the DMAC pool is empty, alloc new */
 	if (!desc) {
-		if (!add_desc(pdmac, GFP_ATOMIC, 1))
+		if (!add_desc(pl330, GFP_ATOMIC, 1))
 			return NULL;
 
 		/* Try again */
-		desc = pluck_desc(pdmac);
+		desc = pluck_desc(pl330);
 		if (!desc) {
-			dev_err(pch->dmac->pif.dev,
+			dev_err(pch->dmac->ddma.dev,
 				"%s:%d ALERT!\n", __func__, __LINE__);
 			return NULL;
 		}
@@ -2581,8 +2292,8 @@ static struct dma_pl330_desc *pl330_get_
 	desc->txd.cookie = 0;
 	async_tx_ack(&desc->txd);
 
-	desc->req.peri = peri_id ? pch->chan.chan_id : 0;
-	desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;
+	desc->peri = peri_id ? pch->chan.chan_id : 0;
+	desc->rqcfg.pcfg = &pch->dmac->pcfg;
 
 	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -2592,7 +2303,6 @@ static struct dma_pl330_desc *pl330_get_
 static inline void fill_px(struct pl330_xfer *px,
 		dma_addr_t dst, dma_addr_t src, size_t len)
 {
-	px->next = NULL;
 	px->bytes = len;
 	px->dst_addr = dst;
 	px->src_addr = src;
@@ -2605,7 +2315,7 @@ __pl330_prep_dma_memcpy(struct dma_pl330
 	struct dma_pl330_desc *desc = pl330_get_desc(pch);
 
 	if (!desc) {
-		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+		dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
 			__func__, __LINE__);
 		return NULL;
 	}
@@ -2629,11 +2339,11 @@ __pl330_prep_dma_memcpy(struct dma_pl330
 static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 {
 	struct dma_pl330_chan *pch = desc->pchan;
-	struct pl330_info *pi = &pch->dmac->pif;
+	struct pl330_dmac *pl330 = pch->dmac;
 	int burst_len;
 
-	burst_len = pi->pcfg.data_bus_width / 8;
-	burst_len *= pi->pcfg.data_buf_dep;
+	burst_len = pl330->pcfg.data_bus_width / 8;
+	burst_len *= pl330->pcfg.data_buf_dep;
 	burst_len >>= desc->rqcfg.brst_size;
 
 	/* src/dst_burst_len can't be more than 16 */
@@ -2652,11 +2362,11 @@ static inline int get_burst_len(struct d
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
 		size_t period_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+		unsigned long flags)
 {
 	struct dma_pl330_desc *desc = NULL, *first = NULL;
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct pl330_dmac *pl330 = pch->dmac;
 	unsigned int i;
 	dma_addr_t dst;
 	dma_addr_t src;
@@ -2665,7 +2375,7 @@ static struct dma_async_tx_descriptor *p
 		return NULL;
 
 	if (!is_slave_direction(direction)) {
-		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+		dev_err(pch->dmac->ddma.dev, "%s:%d Invalid dma direction\n",
 		__func__, __LINE__);
 		return NULL;
 	}
@@ -2673,23 +2383,23 @@ static struct dma_async_tx_descriptor *p
 	for (i = 0; i < len / period_len; i++) {
 		desc = pl330_get_desc(pch);
 		if (!desc) {
-			dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+			dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
 				__func__, __LINE__);
 
 			if (!first)
 				return NULL;
 
-			spin_lock_irqsave(&pdmac->pool_lock, flags);
+			spin_lock_irqsave(&pl330->pool_lock, flags);
 
 			while (!list_empty(&first->node)) {
 				desc = list_entry(first->node.next,
 						struct dma_pl330_desc, node);
-				list_move_tail(&desc->node, &pdmac->desc_pool);
+				list_move_tail(&desc->node, &pl330->desc_pool);
 			}
 
-			list_move_tail(&first->node, &pdmac->desc_pool);
+			list_move_tail(&first->node, &pl330->desc_pool);
 
-			spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+			spin_unlock_irqrestore(&pl330->pool_lock, flags);
 
 			return NULL;
 		}
@@ -2698,14 +2408,12 @@ static struct dma_async_tx_descriptor *p
 		case DMA_MEM_TO_DEV:
 			desc->rqcfg.src_inc = 1;
 			desc->rqcfg.dst_inc = 0;
-			desc->req.rqtype = MEMTODEV;
 			src = dma_addr;
 			dst = pch->fifo_addr;
 			break;
 		case DMA_DEV_TO_MEM:
 			desc->rqcfg.src_inc = 0;
 			desc->rqcfg.dst_inc = 1;
-			desc->req.rqtype = DEVTOMEM;
 			src = pch->fifo_addr;
 			dst = dma_addr;
 			break;
@@ -2713,6 +2421,7 @@ static struct dma_async_tx_descriptor *p
 			break;
 		}
 
+		desc->rqtype = direction;
 		desc->rqcfg.brst_size = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
 		fill_px(&desc->px, dst, src, period_len);
@@ -2740,24 +2449,22 @@ pl330_prep_dma_memcpy(struct dma_chan *c
 {
 	struct dma_pl330_desc *desc;
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct pl330_info *pi;
+	struct pl330_dmac *pl330 = pch->dmac;
 	int burst;
 
 	if (unlikely(!pch || !len))
 		return NULL;
 
-	pi = &pch->dmac->pif;
-
 	desc = __pl330_prep_dma_memcpy(pch, dst, src, len);
 	if (!desc)
 		return NULL;
 
 	desc->rqcfg.src_inc = 1;
 	desc->rqcfg.dst_inc = 1;
-	desc->req.rqtype = MEMTOMEM;
+	desc->rqtype = DMA_MEM_TO_MEM;
 
 	/* Select max possible burst size */
-	burst = pi->pcfg.data_bus_width / 8;
+	burst = pl330->pcfg.data_bus_width / 8;
 
 	while (burst > 1) {
 		if (!(len % burst))
@@ -2776,7 +2483,7 @@ pl330_prep_dma_memcpy(struct dma_chan *c
 	return &desc->txd;
 }
 
-static void __pl330_giveback_desc(struct dma_pl330_dmac *pdmac,
+static void __pl330_giveback_desc(struct pl330_dmac *pl330,
 				  struct dma_pl330_desc *first)
 {
 	unsigned long flags;
@@ -2785,17 +2492,17 @@ static void __pl330_giveback_desc(struct
 	if (!first)
 		return;
 
-	spin_lock_irqsave(&pdmac->pool_lock, flags);
+	spin_lock_irqsave(&pl330->pool_lock, flags);
 
 	while (!list_empty(&first->node)) {
 		desc = list_entry(first->node.next,
 				struct dma_pl330_desc, node);
-		list_move_tail(&desc->node, &pdmac->desc_pool);
+		list_move_tail(&desc->node, &pl330->desc_pool);
 	}
 
-	list_move_tail(&first->node, &pdmac->desc_pool);
+	list_move_tail(&first->node, &pl330->desc_pool);
 
-	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+	spin_unlock_irqrestore(&pl330->pool_lock, flags);
 }
 
 static struct dma_async_tx_descriptor *
@@ -2820,12 +2527,12 @@ pl330_prep_slave_sg(struct dma_chan *cha
 
 		desc = pl330_get_desc(pch);
 		if (!desc) {
-			struct dma_pl330_dmac *pdmac = pch->dmac;
+			struct pl330_dmac *pl330 = pch->dmac;
 
-			dev_err(pch->dmac->pif.dev,
+			dev_err(pch->dmac->ddma.dev,
 				"%s:%d Unable to fetch desc\n",
 				__func__, __LINE__);
-			__pl330_giveback_desc(pdmac, first);
+			__pl330_giveback_desc(pl330, first);
 
 			return NULL;
 		}
@@ -2838,19 +2545,18 @@ pl330_prep_slave_sg(struct dma_chan *cha
 		if (direction == DMA_MEM_TO_DEV) {
 			desc->rqcfg.src_inc = 1;
 			desc->rqcfg.dst_inc = 0;
-			desc->req.rqtype = MEMTODEV;
 			fill_px(&desc->px,
 				addr, sg_dma_address(sg), sg_dma_len(sg));
 		} else {
 			desc->rqcfg.src_inc = 0;
 			desc->rqcfg.dst_inc = 1;
-			desc->req.rqtype = DEVTOMEM;
 			fill_px(&desc->px,
 				sg_dma_address(sg), addr, sg_dma_len(sg));
 		}
 
 		desc->rqcfg.brst_size = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
+		desc->rqtype = direction;
 	}
 
 	/* Return the last desc in the chain */
@@ -2890,9 +2596,9 @@ static int
 pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct dma_pl330_platdata *pdat;
-	struct dma_pl330_dmac *pdmac;
+	struct pl330_config *pcfg;
+	struct pl330_dmac *pl330;
 	struct dma_pl330_chan *pch, *_p;
-	struct pl330_info *pi;
 	struct dma_device *pd;
 	struct resource *res;
 	int i, ret, irq;
@@ -2905,30 +2611,27 @@ pl330_probe(struct amba_device *adev, co
 		return ret;
 
 	/* Allocate a new DMAC and its Channels */
-	pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL);
-	if (!pdmac) {
+	pl330 = devm_kzalloc(&adev->dev, sizeof(*pl330), GFP_KERNEL);
+	if (!pl330) {
 		dev_err(&adev->dev, "unable to allocate mem\n");
 		return -ENOMEM;
 	}
 
-	pi = &pdmac->pif;
-	pi->dev = &adev->dev;
-	pi->pl330_data = NULL;
-	pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
+	pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
 
 	res = &adev->res;
-	pi->base = devm_ioremap_resource(&adev->dev, res);
-	if (IS_ERR(pi->base))
-		return PTR_ERR(pi->base);
+	pl330->base = devm_ioremap_resource(&adev->dev, res);
+	if (IS_ERR(pl330->base))
+		return PTR_ERR(pl330->base);
 
-	amba_set_drvdata(adev, pdmac);
+	amba_set_drvdata(adev, pl330);
 
 	for (i = 0; i < AMBA_NR_IRQS; i++) {
 		irq = adev->irq[i];
 		if (irq) {
 			ret = devm_request_irq(&adev->dev, irq,
 					       pl330_irq_handler, 0,
-					       dev_name(&adev->dev), pi);
+					       dev_name(&adev->dev), pl330);
 			if (ret)
 				return ret;
 		} else {
@@ -2936,38 +2639,40 @@ pl330_probe(struct amba_device *adev, co
 		}
 	}
 
-	pi->pcfg.periph_id = adev->periphid;
-	ret = pl330_add(pi);
+	pcfg = &pl330->pcfg;
+
+	pcfg->periph_id = adev->periphid;
+	ret = pl330_add(pl330);
 	if (ret)
 		return ret;
 
-	INIT_LIST_HEAD(&pdmac->desc_pool);
-	spin_lock_init(&pdmac->pool_lock);
+	INIT_LIST_HEAD(&pl330->desc_pool);
+	spin_lock_init(&pl330->pool_lock);
 
 	/* Create a descriptor pool of default size */
-	if (!add_desc(pdmac, GFP_KERNEL, NR_DEFAULT_DESC))
+	if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
 		dev_warn(&adev->dev, "unable to allocate desc\n");
 
-	pd = &pdmac->ddma;
+	pd = &pl330->ddma;
 	INIT_LIST_HEAD(&pd->channels);
 
 	/* Initialize channel parameters */
 	if (pdat)
-		num_chan = max_t(int, pdat->nr_valid_peri, pi->pcfg.num_chan);
+		num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan);
 	else
-		num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
+		num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
 
-	pdmac->num_peripherals = num_chan;
+	pl330->num_peripherals = num_chan;
 
-	pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
-	if (!pdmac->peripherals) {
+	pl330->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
+	if (!pl330->peripherals) {
 		ret = -ENOMEM;
-		dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
+		dev_err(&adev->dev, "unable to allocate pl330->peripherals\n");
 		goto probe_err2;
 	}
 
 	for (i = 0; i < num_chan; i++) {
-		pch = &pdmac->peripherals[i];
+		pch = &pl330->peripherals[i];
 		if (!adev->dev.of_node)
 			pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
 		else
@@ -2977,9 +2682,9 @@ pl330_probe(struct amba_device *adev, co
 		INIT_LIST_HEAD(&pch->work_list);
 		INIT_LIST_HEAD(&pch->completed_list);
 		spin_lock_init(&pch->lock);
-		pch->pl330_chid = NULL;
+		pch->thread = NULL;
 		pch->chan.device = pd;
-		pch->dmac = pdmac;
+		pch->dmac = pl330;
 
 		/* Add the channel to the DMAC list */
 		list_add_tail(&pch->chan.device_node, &pd->channels);
@@ -2990,7 +2695,7 @@ pl330_probe(struct amba_device *adev, co
 		pd->cap_mask = pdat->cap_mask;
 	} else {
 		dma_cap_set(DMA_MEMCPY, pd->cap_mask);
-		if (pi->pcfg.num_peri) {
+		if (pcfg->num_peri) {
 			dma_cap_set(DMA_SLAVE, pd->cap_mask);
 			dma_cap_set(DMA_CYCLIC, pd->cap_mask);
 			dma_cap_set(DMA_PRIVATE, pd->cap_mask);
@@ -3015,14 +2720,14 @@ pl330_probe(struct amba_device *adev, co
 
 	if (adev->dev.of_node) {
 		ret = of_dma_controller_register(adev->dev.of_node,
-					 of_dma_pl330_xlate, pdmac);
+					 of_dma_pl330_xlate, pl330);
 		if (ret) {
 			dev_err(&adev->dev,
 			"unable to register DMA to the generic DT DMA helpers\n");
 		}
 	}
 
-	adev->dev.dma_parms = &pdmac->dma_parms;
+	adev->dev.dma_parms = &pl330->dma_parms;
 
 	/*
 	 * This is the limit for transfers with a buswidth of 1, larger
@@ -3037,14 +2742,13 @@ pl330_probe(struct amba_device *adev, co
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
 		"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-		pi->pcfg.data_buf_dep,
-		pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
-		pi->pcfg.num_peri, pi->pcfg.num_events);
+		pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
+		pcfg->num_peri, pcfg->num_events);
 
 	return 0;
 probe_err3:
 	/* Idle the DMAC */
-	list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+	list_for_each_entry_safe(pch, _p, &pl330->ddma.channels,
 			chan.device_node) {
 
 		/* Remove the channel */
@@ -3055,27 +2759,23 @@ probe_err3:
 		pl330_free_chan_resources(&pch->chan);
 	}
 probe_err2:
-	pl330_del(pi);
+	pl330_del(pl330);
 
 	return ret;
 }
 
 static int pl330_remove(struct amba_device *adev)
 {
-	struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
+	struct pl330_dmac *pl330 = amba_get_drvdata(adev);
 	struct dma_pl330_chan *pch, *_p;
-	struct pl330_info *pi;
-
-	if (!pdmac)
-		return 0;
 
 	if (adev->dev.of_node)
 		of_dma_controller_free(adev->dev.of_node);
 
-	dma_async_device_unregister(&pdmac->ddma);
+	dma_async_device_unregister(&pl330->ddma);
 
 	/* Idle the DMAC */
-	list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+	list_for_each_entry_safe(pch, _p, &pl330->ddma.channels,
 			chan.device_node) {
 
 		/* Remove the channel */
@@ -3086,9 +2786,7 @@ static int pl330_remove(struct amba_devi
 		pl330_free_chan_resources(&pch->chan);
 	}
 
-	pi = &pdmac->pif;
-
-	pl330_del(pi);
+	pl330_del(pl330);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/qcom_bam_dma.c linux-libre-3.17-rc7-gnu/drivers/dma/qcom_bam_dma.c
--- linux-libre-3.16-gnu/drivers/dma/qcom_bam_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/qcom_bam_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,12 +61,17 @@ struct bam_desc_hw {
 #define DESC_FLAG_INT BIT(15)
 #define DESC_FLAG_EOT BIT(14)
 #define DESC_FLAG_EOB BIT(13)
+#define DESC_FLAG_NWD BIT(12)
 
 struct bam_async_desc {
 	struct virt_dma_desc vd;
 
 	u32 num_desc;
 	u32 xfer_len;
+
+	/* transaction flags, EOT|EOB|NWD */
+	u16 flags;
+
 	struct bam_desc_hw *curr_desc;
 
 	enum dma_transfer_direction dir;
@@ -490,6 +495,14 @@ static struct dma_async_tx_descriptor *b
 	if (!async_desc)
 		goto err_out;
 
+	if (flags & DMA_PREP_FENCE)
+		async_desc->flags |= DESC_FLAG_NWD;
+
+	if (flags & DMA_PREP_INTERRUPT)
+		async_desc->flags |= DESC_FLAG_EOT;
+	else
+		async_desc->flags |= DESC_FLAG_INT;
+
 	async_desc->num_desc = num_alloc;
 	async_desc->curr_desc = async_desc->desc;
 	async_desc->dir = direction;
@@ -793,8 +806,11 @@ static void bam_start_dma(struct bam_cha
 	else
 		async_desc->xfer_len = async_desc->num_desc;
 
-	/* set INT on last descriptor */
-	desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT;
+	/* set any special flags on the last descriptor */
+	if (async_desc->num_desc == async_desc->xfer_len)
+		desc[async_desc->xfer_len - 1].flags = async_desc->flags;
+	else
+		desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT;
 
 	if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) {
 		u32 partial = MAX_DESCRIPTORS - bchan->tail;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/s3c24xx-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/s3c24xx-dma.c
--- linux-libre-3.16-gnu/drivers/dma/s3c24xx-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/s3c24xx-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -889,8 +889,7 @@ static struct dma_async_tx_descriptor *s
 
 static struct dma_async_tx_descriptor *s3c24xx_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period,
-	enum dma_transfer_direction direction, unsigned long flags,
-	void *context)
+	enum dma_transfer_direction direction, unsigned long flags)
 {
 	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
 	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sa11x0-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/sa11x0-dma.c
--- linux-libre-3.16-gnu/drivers/dma/sa11x0-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sa11x0-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -612,7 +612,7 @@ static struct dma_async_tx_descriptor *s
 
 static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period,
-	enum dma_transfer_direction dir, unsigned long flags, void *context)
+	enum dma_transfer_direction dir, unsigned long flags)
 {
 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
 	struct sa11x0_dma_desc *txd;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/Kconfig linux-libre-3.17-rc7-gnu/drivers/dma/sh/Kconfig
--- linux-libre-3.16-gnu/drivers/dma/sh/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -2,21 +2,39 @@
 # DMA engine configuration for sh
 #
 
+#
+# DMA Engine Helpers
+#
+
 config SH_DMAE_BASE
 	bool "Renesas SuperH DMA Engine support"
-	depends on (SUPERH && SH_DMA) || ARCH_SHMOBILE || COMPILE_TEST
+	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+	depends on !SUPERH || SH_DMA
 	depends on !SH_DMA_API
 	default y
 	select DMA_ENGINE
 	help
 	  Enable support for the Renesas SuperH DMA controllers.
 
+#
+# DMA Controllers
+#
+
 config SH_DMAE
 	tristate "Renesas SuperH DMAC support"
 	depends on SH_DMAE_BASE
 	help
 	  Enable support for the Renesas SuperH DMA controllers.
 
+if SH_DMAE
+
+config SH_DMAE_R8A73A4
+	def_bool y
+	depends on ARCH_R8A73A4
+	depends on OF
+
+endif
+
 config SUDMAC
 	tristate "Renesas SUDMAC support"
 	depends on SH_DMAE_BASE
@@ -34,7 +52,3 @@ config RCAR_AUDMAC_PP
 	depends on SH_DMAE_BASE
 	help
 	  Enable support for the Renesas R-Car Audio DMAC Peripheral Peripheral controllers.
-
-config SHDMA_R8A73A4
-	def_bool y
-	depends on ARCH_R8A73A4 && SH_DMAE != n
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/Makefile linux-libre-3.17-rc7-gnu/drivers/dma/sh/Makefile
--- linux-libre-3.16-gnu/drivers/dma/sh/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,10 +1,18 @@
+#
+# DMA Engine Helpers
+#
+
 obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o
-obj-$(CONFIG_SH_DMAE) += shdma.o
+
+#
+# DMA Controllers
+#
+
 shdma-y := shdmac.o
-ifeq ($(CONFIG_OF),y)
-shdma-$(CONFIG_SHDMA_R8A73A4) += shdma-r8a73a4.o
-endif
+shdma-$(CONFIG_SH_DMAE_R8A73A4) += shdma-r8a73a4.o
 shdma-objs := $(shdma-y)
+obj-$(CONFIG_SH_DMAE) += shdma.o
+
 obj-$(CONFIG_SUDMAC) += sudmac.o
 obj-$(CONFIG_RCAR_HPB_DMAE) += rcar-hpbdma.o
 obj-$(CONFIG_RCAR_AUDMAC_PP) += rcar-audmapp.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/rcar-audmapp.c linux-libre-3.17-rc7-gnu/drivers/dma/sh/rcar-audmapp.c
--- linux-libre-3.16-gnu/drivers/dma/sh/rcar-audmapp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/rcar-audmapp.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
+#include <linux/of_dma.h>
 #include <linux/platform_data/dma-rcar-audmapp.h>
 #include <linux/platform_device.h>
 #include <linux/shdma-base.h>
@@ -45,8 +46,9 @@
 
 struct audmapp_chan {
 	struct shdma_chan shdma_chan;
-	struct audmapp_slave_config *config;
 	void __iomem *base;
+	dma_addr_t slave_addr;
+	u32 chcr;
 };
 
 struct audmapp_device {
@@ -56,7 +58,16 @@ struct audmapp_device {
 	void __iomem *chan_reg;
 };
 
+struct audmapp_desc {
+	struct shdma_desc shdma_desc;
+	dma_addr_t src;
+	dma_addr_t dst;
+};
+
+#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
+
 #define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan)
+#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc)
 #define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device,	\
 				  struct audmapp_device, shdma_dev.dma_dev)
 
@@ -90,70 +101,82 @@ static void audmapp_halt(struct shdma_ch
 }
 
 static void audmapp_start_xfer(struct shdma_chan *schan,
-			       struct shdma_desc *sdecs)
+			       struct shdma_desc *sdesc)
 {
 	struct audmapp_chan *auchan = to_chan(schan);
 	struct audmapp_device *audev = to_dev(auchan);
-	struct audmapp_slave_config *cfg = auchan->config;
+	struct audmapp_desc *desc = to_desc(sdesc);
 	struct device *dev = audev->dev;
-	u32 chcr = cfg->chcr | PDMACHCR_DE;
+	u32 chcr = auchan->chcr | PDMACHCR_DE;
 
-	dev_dbg(dev, "src/dst/chcr = %pad/%pad/%x\n",
-		&cfg->src, &cfg->dst, cfg->chcr);
+	dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n",
+		&desc->src, &desc->dst, chcr);
 
-	audmapp_write(auchan, cfg->src,	PDMASAR);
-	audmapp_write(auchan, cfg->dst,	PDMADAR);
+	audmapp_write(auchan, desc->src,	PDMASAR);
+	audmapp_write(auchan, desc->dst,	PDMADAR);
 	audmapp_write(auchan, chcr,	PDMACHCR);
 }
 
-static struct audmapp_slave_config *
-audmapp_find_slave(struct audmapp_chan *auchan, int slave_id)
+static void audmapp_get_config(struct audmapp_chan *auchan, int slave_id,
+			      u32 *chcr, dma_addr_t *dst)
 {
 	struct audmapp_device *audev = to_dev(auchan);
 	struct audmapp_pdata *pdata = audev->pdata;
 	struct audmapp_slave_config *cfg;
 	int i;
 
+	*chcr	= 0;
+	*dst	= 0;
+
+	if (!pdata) { /* DT */
+		*chcr = ((u32)slave_id) << 16;
+		auchan->shdma_chan.slave_id = (slave_id) >> 8;
+		return;
+	}
+
+	/* non-DT */
+
 	if (slave_id >= AUDMAPP_SLAVE_NUMBER)
-		return NULL;
+		return;
 
 	for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
-		if (cfg->slave_id == slave_id)
-			return cfg;
-
-	return NULL;
+		if (cfg->slave_id == slave_id) {
+			*chcr	= cfg->chcr;
+			*dst	= cfg->dst;
+			break;
+		}
 }
 
 static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
 			     dma_addr_t slave_addr, bool try)
 {
 	struct audmapp_chan *auchan = to_chan(schan);
-	struct audmapp_slave_config *cfg =
-		audmapp_find_slave(auchan, slave_id);
+	u32 chcr;
+	dma_addr_t dst;
+
+	audmapp_get_config(auchan, slave_id, &chcr, &dst);
 
-	if (!cfg)
-		return -ENODEV;
 	if (try)
 		return 0;
 
-	auchan->config	= cfg;
+	auchan->chcr		= chcr;
+	auchan->slave_addr	= slave_addr ? : dst;
 
 	return 0;
 }
 
 static int audmapp_desc_setup(struct shdma_chan *schan,
-			      struct shdma_desc *sdecs,
+			      struct shdma_desc *sdesc,
 			      dma_addr_t src, dma_addr_t dst, size_t *len)
 {
-	struct audmapp_chan *auchan = to_chan(schan);
-	struct audmapp_slave_config *cfg = auchan->config;
-
-	if (!cfg)
-		return -ENODEV;
+	struct audmapp_desc *desc = to_desc(sdesc);
 
 	if (*len > (size_t)AUDMAPP_LEN_MAX)
 		*len = (size_t)AUDMAPP_LEN_MAX;
 
+	desc->src = src;
+	desc->dst = dst;
+
 	return 0;
 }
 
@@ -164,7 +187,9 @@ static void audmapp_setup_xfer(struct sh
 
 static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan)
 {
-	return 0; /* always fixed address */
+	struct audmapp_chan *auchan = to_chan(schan);
+
+	return auchan->slave_addr;
 }
 
 static bool audmapp_channel_busy(struct shdma_chan *schan)
@@ -183,7 +208,7 @@ static bool audmapp_desc_completed(struc
 
 static struct shdma_desc *audmapp_embedded_desc(void *buf, int i)
 {
-	return &((struct shdma_desc *)buf)[i];
+	return &((struct audmapp_desc *)buf)[i].shdma_desc;
 }
 
 static const struct shdma_ops audmapp_shdma_ops = {
@@ -234,16 +259,39 @@ static void audmapp_chan_remove(struct a
 	dma_dev->chancnt = 0;
 }
 
+static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	u32 chcr = dma_spec->args[0];
+
+	if (dma_spec->args_count != 1)
+		return NULL;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	chan = dma_request_channel(mask, shdma_chan_filter, NULL);
+	if (chan)
+		to_shdma_chan(chan)->hw_req = chcr;
+
+	return chan;
+}
+
 static int audmapp_probe(struct platform_device *pdev)
 {
 	struct audmapp_pdata *pdata = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
 	struct audmapp_device *audev;
 	struct shdma_dev *sdev;
 	struct dma_device *dma_dev;
 	struct resource *res;
 	int err, i;
 
-	if (!pdata)
+	if (np)
+		of_dma_controller_register(np, audmapp_of_xlate, pdev);
+	else if (!pdata)
 		return -ENODEV;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -260,7 +308,7 @@ static int audmapp_probe(struct platform
 
 	sdev		= &audev->shdma_dev;
 	sdev->ops	= &audmapp_shdma_ops;
-	sdev->desc_size	= sizeof(struct shdma_desc);
+	sdev->desc_size	= sizeof(struct audmapp_desc);
 
 	dma_dev			= &sdev->dma_dev;
 	dma_dev->copy_align	= LOG2_DEFAULT_XFER_SIZE;
@@ -305,12 +353,18 @@ static int audmapp_remove(struct platfor
 	return 0;
 }
 
+static const struct of_device_id audmapp_of_match[] = {
+	{ .compatible = "renesas,rcar-audmapp", },
+	{},
+};
+
 static struct platform_driver audmapp_driver = {
 	.probe		= audmapp_probe,
 	.remove		= audmapp_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "rcar-audmapp-engine",
+		.of_match_table = audmapp_of_match,
 	},
 };
 module_platform_driver(audmapp_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/shdma-arm.h linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma-arm.h
--- linux-libre-3.16-gnu/drivers/dma/sh/shdma-arm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma-arm.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@ enum {
 	((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
 	 (((i) & TS_HI_BIT)  << TS_HI_SHIFT))
 
-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz)))
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/shdma-base.c linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma-base.c
--- linux-libre-3.16-gnu/drivers/dma/sh/shdma-base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma-base.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,45 +206,6 @@ static int shdma_setup_slave(struct shdm
 	return 0;
 }
 
-/*
- * This is the standard shdma filter function to be used as a replacement to the
- * "old" method, using the .private pointer. If for some reason you allocate a
- * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
- * parameter. If this filter is used, the slave driver, after calling
- * dma_request_channel(), will also have to call dmaengine_slave_config() with
- * .slave_id, .direction, and either .src_addr or .dst_addr set.
- * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
- * capability! If this becomes a requirement, hardware glue drivers, using this
- * services would have to provide their own filters, which first would check
- * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
- * this, and only then, in case of a match, call this common filter.
- * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
- * In that case the MID-RID value is used for slave channel filtering and is
- * passed to this function in the "arg" parameter.
- */
-bool shdma_chan_filter(struct dma_chan *chan, void *arg)
-{
-	struct shdma_chan *schan = to_shdma_chan(chan);
-	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-	const struct shdma_ops *ops = sdev->ops;
-	int match = (long)arg;
-	int ret;
-
-	if (match < 0)
-		/* No slave requested - arbitrary channel */
-		return true;
-
-	if (!schan->dev->of_node && match >= slave_num)
-		return false;
-
-	ret = ops->set_slave(schan, match, 0, true);
-	if (ret < 0)
-		return false;
-
-	return true;
-}
-EXPORT_SYMBOL(shdma_chan_filter);
-
 static int shdma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct shdma_chan *schan = to_shdma_chan(chan);
@@ -295,6 +256,51 @@ esetslave:
 	return ret;
 }
 
+/*
+ * This is the standard shdma filter function to be used as a replacement to the
+ * "old" method, using the .private pointer. If for some reason you allocate a
+ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
+ * parameter. If this filter is used, the slave driver, after calling
+ * dma_request_channel(), will also have to call dmaengine_slave_config() with
+ * .slave_id, .direction, and either .src_addr or .dst_addr set.
+ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
+ * capability! If this becomes a requirement, hardware glue drivers, using this
+ * services would have to provide their own filters, which first would check
+ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
+ * this, and only then, in case of a match, call this common filter.
+ * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
+ * In that case the MID-RID value is used for slave channel filtering and is
+ * passed to this function in the "arg" parameter.
+ */
+bool shdma_chan_filter(struct dma_chan *chan, void *arg)
+{
+	struct shdma_chan *schan;
+	struct shdma_dev *sdev;
+	int match = (long)arg;
+	int ret;
+
+	/* Only support channels handled by this driver. */
+	if (chan->device->device_alloc_chan_resources !=
+	    shdma_alloc_chan_resources)
+		return false;
+
+	if (match < 0)
+		/* No slave requested - arbitrary channel */
+		return true;
+
+	schan = to_shdma_chan(chan);
+	if (!schan->dev->of_node && match >= slave_num)
+		return false;
+
+	sdev = to_shdma_dev(schan->dma_chan.device);
+	ret = sdev->ops->set_slave(schan, match, 0, true);
+	if (ret < 0)
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(shdma_chan_filter);
+
 static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all)
 {
 	struct shdma_desc *desc, *_desc;
@@ -662,15 +668,16 @@ static struct dma_async_tx_descriptor *s
 static struct dma_async_tx_descriptor *shdma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags, void *context)
+	unsigned long flags)
 {
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+	struct dma_async_tx_descriptor *desc;
 	const struct shdma_ops *ops = sdev->ops;
 	unsigned int sg_len = buf_len / period_len;
 	int slave_id = schan->slave_id;
 	dma_addr_t slave_addr;
-	struct scatterlist sgl[SHDMA_MAX_SG_LEN];
+	struct scatterlist *sgl;
 	int i;
 
 	if (!chan)
@@ -694,7 +701,16 @@ static struct dma_async_tx_descriptor *s
 
 	slave_addr = ops->slave_addr(schan);
 
+	/*
+	 * Allocate the sg list dynamically as it would consumer too much stack
+	 * space.
+	 */
+	sgl = kcalloc(sg_len, sizeof(*sgl), GFP_KERNEL);
+	if (!sgl)
+		return NULL;
+
 	sg_init_table(sgl, sg_len);
+
 	for (i = 0; i < sg_len; i++) {
 		dma_addr_t src = buf_addr + (period_len * i);
 
@@ -704,8 +720,11 @@ static struct dma_async_tx_descriptor *s
 		sg_dma_len(&sgl[i]) = period_len;
 	}
 
-	return shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
+	desc = shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
 			     direction, flags, true);
+
+	kfree(sgl);
+	return desc;
 }
 
 static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/shdmac.c linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdmac.c
--- linux-libre-3.16-gnu/drivers/dma/sh/shdmac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdmac.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,12 +38,12 @@
 #include "../dmaengine.h"
 #include "shdma.h"
 
-/* DMA register */
-#define SAR	0x00
-#define DAR	0x04
-#define TCR	0x08
-#define CHCR	0x0C
-#define DMAOR	0x40
+/* DMA registers */
+#define SAR	0x00	/* Source Address Register */
+#define DAR	0x04	/* Destination Address Register */
+#define TCR	0x08	/* Transfer Count Register */
+#define CHCR	0x0C	/* Channel Control Register */
+#define DMAOR	0x40	/* DMA Operation Register */
 
 #define TEND	0x18 /* USB-DMAC */
 
@@ -239,9 +239,8 @@ static void dmae_init(struct sh_dmae_cha
 {
 	/*
 	 * Default configuration for dual address memory-memory transfer.
-	 * 0x400 represents auto-request.
 	 */
-	u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
+	u32 chcr = DM_INC | SM_INC | RS_AUTO | log2size_to_chcr(sh_chan,
 						   LOG2_DEFAULT_XFER_SIZE);
 	sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
 	chcr_write(sh_chan, chcr);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sh/shdma.h linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma.h
--- linux-libre-3.16-gnu/drivers/dma/sh/shdma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sh/shdma.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@ struct sh_dmae_desc {
 #define to_sh_dev(chan) container_of(chan->shdma_chan.dma_chan.device,\
 				     struct sh_dmae_device, shdma_dev.dma_dev)
 
-#ifdef CONFIG_SHDMA_R8A73A4
+#ifdef CONFIG_SH_DMAE_R8A73A4
 extern const struct sh_dmae_pdata r8a73a4_dma_pdata;
 #define r8a73a4_shdma_devid (&r8a73a4_dma_pdata)
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sirf-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/sirf-dma.c
--- linux-libre-3.16-gnu/drivers/dma/sirf-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sirf-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -580,7 +580,7 @@ err_dir:
 static struct dma_async_tx_descriptor *
 sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
 	size_t buf_len, size_t period_len,
-	enum dma_transfer_direction direction, unsigned long flags, void *context)
+	enum dma_transfer_direction direction, unsigned long flags)
 {
 	struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
 	struct sirfsoc_dma_desc *sdesc = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/ste_dma40.c linux-libre-3.17-rc7-gnu/drivers/dma/ste_dma40.c
--- linux-libre-3.16-gnu/drivers/dma/ste_dma40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/ste_dma40.c	2014-09-28 17:29:07.000000000 -0400
@@ -2531,8 +2531,7 @@ d40_prep_slave_sg(struct dma_chan *chan,
 static struct dma_async_tx_descriptor *
 dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
 		     size_t buf_len, size_t period_len,
-		     enum dma_transfer_direction direction, unsigned long flags,
-		     void *context)
+		     enum dma_transfer_direction direction, unsigned long flags)
 {
 	unsigned int periods = buf_len / period_len;
 	struct dma_async_tx_descriptor *txd;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/sun6i-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/sun6i-dma.c
--- linux-libre-3.16-gnu/drivers/dma/sun6i-dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma/sun6i-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (C) 2013-2014 Allwinner Tech Co., Ltd
+ * Author: Sugar <shuge@allwinnertech.com>
+ *
+ * Copyright (C) 2014 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "virt-dma.h"
+
+/*
+ * There's 16 physical channels that can work in parallel.
+ *
+ * However we have 30 different endpoints for our requests.
+ *
+ * Since the channels are able to handle only an unidirectional
+ * transfer, we need to allocate more virtual channels so that
+ * everyone can grab one channel.
+ *
+ * Some devices can't work in both direction (mostly because it
+ * wouldn't make sense), so we have a bit fewer virtual channels than
+ * 2 channels per endpoints.
+ */
+
+#define NR_MAX_CHANNELS		16
+#define NR_MAX_REQUESTS		30
+#define NR_MAX_VCHANS		53
+
+/*
+ * Common registers
+ */
+#define DMA_IRQ_EN(x)		((x) * 0x04)
+#define DMA_IRQ_HALF			BIT(0)
+#define DMA_IRQ_PKG			BIT(1)
+#define DMA_IRQ_QUEUE			BIT(2)
+
+#define DMA_IRQ_CHAN_NR			8
+#define DMA_IRQ_CHAN_WIDTH		4
+
+
+#define DMA_IRQ_STAT(x)		((x) * 0x04 + 0x10)
+
+#define DMA_STAT		0x30
+
+/*
+ * Channels specific registers
+ */
+#define DMA_CHAN_ENABLE		0x00
+#define DMA_CHAN_ENABLE_START		BIT(0)
+#define DMA_CHAN_ENABLE_STOP		0
+
+#define DMA_CHAN_PAUSE		0x04
+#define DMA_CHAN_PAUSE_PAUSE		BIT(1)
+#define DMA_CHAN_PAUSE_RESUME		0
+
+#define DMA_CHAN_LLI_ADDR	0x08
+
+#define DMA_CHAN_CUR_CFG	0x0c
+#define DMA_CHAN_CFG_SRC_DRQ(x)		((x) & 0x1f)
+#define DMA_CHAN_CFG_SRC_IO_MODE	BIT(5)
+#define DMA_CHAN_CFG_SRC_LINEAR_MODE	(0 << 5)
+#define DMA_CHAN_CFG_SRC_BURST(x)	(((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
+
+#define DMA_CHAN_CFG_DST_DRQ(x)		(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
+#define DMA_CHAN_CFG_DST_IO_MODE	(DMA_CHAN_CFG_SRC_IO_MODE << 16)
+#define DMA_CHAN_CFG_DST_LINEAR_MODE	(DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
+#define DMA_CHAN_CFG_DST_BURST(x)	(DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
+
+#define DMA_CHAN_CUR_SRC	0x10
+
+#define DMA_CHAN_CUR_DST	0x14
+
+#define DMA_CHAN_CUR_CNT	0x18
+
+#define DMA_CHAN_CUR_PARA	0x1c
+
+
+/*
+ * Various hardware related defines
+ */
+#define LLI_LAST_ITEM	0xfffff800
+#define NORMAL_WAIT	8
+#define DRQ_SDRAM	1
+
+/*
+ * Hardware representation of the LLI
+ *
+ * The hardware will be fed the physical address of this structure,
+ * and read its content in order to start the transfer.
+ */
+struct sun6i_dma_lli {
+	u32			cfg;
+	u32			src;
+	u32			dst;
+	u32			len;
+	u32			para;
+	u32			p_lli_next;
+
+	/*
+	 * This field is not used by the DMA controller, but will be
+	 * used by the CPU to go through the list (mostly for dumping
+	 * or freeing it).
+	 */
+	struct sun6i_dma_lli	*v_lli_next;
+};
+
+
+struct sun6i_desc {
+	struct virt_dma_desc	vd;
+	dma_addr_t		p_lli;
+	struct sun6i_dma_lli	*v_lli;
+};
+
+struct sun6i_pchan {
+	u32			idx;
+	void __iomem		*base;
+	struct sun6i_vchan	*vchan;
+	struct sun6i_desc	*desc;
+	struct sun6i_desc	*done;
+};
+
+struct sun6i_vchan {
+	struct virt_dma_chan	vc;
+	struct list_head	node;
+	struct dma_slave_config	cfg;
+	struct sun6i_pchan	*phy;
+	u8			port;
+};
+
+struct sun6i_dma_dev {
+	struct dma_device	slave;
+	void __iomem		*base;
+	struct clk		*clk;
+	int			irq;
+	spinlock_t		lock;
+	struct reset_control	*rstc;
+	struct tasklet_struct	task;
+	atomic_t		tasklet_shutdown;
+	struct list_head	pending;
+	struct dma_pool		*pool;
+	struct sun6i_pchan	*pchans;
+	struct sun6i_vchan	*vchans;
+};
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+	return &chan->dev->device;
+}
+
+static inline struct sun6i_dma_dev *to_sun6i_dma_dev(struct dma_device *d)
+{
+	return container_of(d, struct sun6i_dma_dev, slave);
+}
+
+static inline struct sun6i_vchan *to_sun6i_vchan(struct dma_chan *chan)
+{
+	return container_of(chan, struct sun6i_vchan, vc.chan);
+}
+
+static inline struct sun6i_desc *
+to_sun6i_desc(struct dma_async_tx_descriptor *tx)
+{
+	return container_of(tx, struct sun6i_desc, vd.tx);
+}
+
+static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev)
+{
+	dev_dbg(sdev->slave.dev, "Common register:\n"
+		"\tmask0(%04x): 0x%08x\n"
+		"\tmask1(%04x): 0x%08x\n"
+		"\tpend0(%04x): 0x%08x\n"
+		"\tpend1(%04x): 0x%08x\n"
+		"\tstats(%04x): 0x%08x\n",
+		DMA_IRQ_EN(0), readl(sdev->base + DMA_IRQ_EN(0)),
+		DMA_IRQ_EN(1), readl(sdev->base + DMA_IRQ_EN(1)),
+		DMA_IRQ_STAT(0), readl(sdev->base + DMA_IRQ_STAT(0)),
+		DMA_IRQ_STAT(1), readl(sdev->base + DMA_IRQ_STAT(1)),
+		DMA_STAT, readl(sdev->base + DMA_STAT));
+}
+
+static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev,
+					    struct sun6i_pchan *pchan)
+{
+	phys_addr_t reg = virt_to_phys(pchan->base);
+
+	dev_dbg(sdev->slave.dev, "Chan %d reg: %pa\n"
+		"\t___en(%04x): \t0x%08x\n"
+		"\tpause(%04x): \t0x%08x\n"
+		"\tstart(%04x): \t0x%08x\n"
+		"\t__cfg(%04x): \t0x%08x\n"
+		"\t__src(%04x): \t0x%08x\n"
+		"\t__dst(%04x): \t0x%08x\n"
+		"\tcount(%04x): \t0x%08x\n"
+		"\t_para(%04x): \t0x%08x\n\n",
+		pchan->idx, &reg,
+		DMA_CHAN_ENABLE,
+		readl(pchan->base + DMA_CHAN_ENABLE),
+		DMA_CHAN_PAUSE,
+		readl(pchan->base + DMA_CHAN_PAUSE),
+		DMA_CHAN_LLI_ADDR,
+		readl(pchan->base + DMA_CHAN_LLI_ADDR),
+		DMA_CHAN_CUR_CFG,
+		readl(pchan->base + DMA_CHAN_CUR_CFG),
+		DMA_CHAN_CUR_SRC,
+		readl(pchan->base + DMA_CHAN_CUR_SRC),
+		DMA_CHAN_CUR_DST,
+		readl(pchan->base + DMA_CHAN_CUR_DST),
+		DMA_CHAN_CUR_CNT,
+		readl(pchan->base + DMA_CHAN_CUR_CNT),
+		DMA_CHAN_CUR_PARA,
+		readl(pchan->base + DMA_CHAN_CUR_PARA));
+}
+
+static inline int convert_burst(u32 maxburst, u8 *burst)
+{
+	switch (maxburst) {
+	case 1:
+		*burst = 0;
+		break;
+	case 8:
+		*burst = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline int convert_buswidth(enum dma_slave_buswidth addr_width, u8 *width)
+{
+	if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
+	    (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
+		return -EINVAL;
+
+	*width = addr_width >> 1;
+	return 0;
+}
+
+static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev,
+			       struct sun6i_dma_lli *next,
+			       dma_addr_t next_phy,
+			       struct sun6i_desc *txd)
+{
+	if ((!prev && !txd) || !next)
+		return NULL;
+
+	if (!prev) {
+		txd->p_lli = next_phy;
+		txd->v_lli = next;
+	} else {
+		prev->p_lli_next = next_phy;
+		prev->v_lli_next = next;
+	}
+
+	next->p_lli_next = LLI_LAST_ITEM;
+	next->v_lli_next = NULL;
+
+	return next;
+}
+
+static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli,
+				    dma_addr_t src,
+				    dma_addr_t dst, u32 len,
+				    struct dma_slave_config *config)
+{
+	u8 src_width, dst_width, src_burst, dst_burst;
+	int ret;
+
+	if (!config)
+		return -EINVAL;
+
+	ret = convert_burst(config->src_maxburst, &src_burst);
+	if (ret)
+		return ret;
+
+	ret = convert_burst(config->dst_maxburst, &dst_burst);
+	if (ret)
+		return ret;
+
+	ret = convert_buswidth(config->src_addr_width, &src_width);
+	if (ret)
+		return ret;
+
+	ret = convert_buswidth(config->dst_addr_width, &dst_width);
+	if (ret)
+		return ret;
+
+	lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
+		DMA_CHAN_CFG_SRC_WIDTH(src_width) |
+		DMA_CHAN_CFG_DST_BURST(dst_burst) |
+		DMA_CHAN_CFG_DST_WIDTH(dst_width);
+
+	lli->src = src;
+	lli->dst = dst;
+	lli->len = len;
+	lli->para = NORMAL_WAIT;
+
+	return 0;
+}
+
+static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan,
+				      struct sun6i_dma_lli *lli)
+{
+	phys_addr_t p_lli = virt_to_phys(lli);
+
+	dev_dbg(chan2dev(&vchan->vc.chan),
+		"\n\tdesc:   p - %pa v - 0x%p\n"
+		"\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n"
+		"\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n",
+		&p_lli, lli,
+		lli->cfg, lli->src, lli->dst,
+		lli->len, lli->para, lli->p_lli_next);
+}
+
+static void sun6i_dma_free_desc(struct virt_dma_desc *vd)
+{
+	struct sun6i_desc *txd = to_sun6i_desc(&vd->tx);
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vd->tx.chan->device);
+	struct sun6i_dma_lli *v_lli, *v_next;
+	dma_addr_t p_lli, p_next;
+
+	if (unlikely(!txd))
+		return;
+
+	p_lli = txd->p_lli;
+	v_lli = txd->v_lli;
+
+	while (v_lli) {
+		v_next = v_lli->v_lli_next;
+		p_next = v_lli->p_lli_next;
+
+		dma_pool_free(sdev->pool, v_lli, p_lli);
+
+		v_lli = v_next;
+		p_lli = p_next;
+	}
+
+	kfree(txd);
+}
+
+static int sun6i_dma_terminate_all(struct sun6i_vchan *vchan)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
+	struct sun6i_pchan *pchan = vchan->phy;
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock(&sdev->lock);
+	list_del_init(&vchan->node);
+	spin_unlock(&sdev->lock);
+
+	spin_lock_irqsave(&vchan->vc.lock, flags);
+
+	vchan_get_all_descriptors(&vchan->vc, &head);
+
+	if (pchan) {
+		writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE);
+		writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE);
+
+		vchan->phy = NULL;
+		pchan->vchan = NULL;
+		pchan->desc = NULL;
+		pchan->done = NULL;
+	}
+
+	spin_unlock_irqrestore(&vchan->vc.lock, flags);
+
+	vchan_dma_desc_free_list(&vchan->vc, &head);
+
+	return 0;
+}
+
+static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
+	struct virt_dma_desc *desc = vchan_next_desc(&vchan->vc);
+	struct sun6i_pchan *pchan = vchan->phy;
+	u32 irq_val, irq_reg, irq_offset;
+
+	if (!pchan)
+		return -EAGAIN;
+
+	if (!desc) {
+		pchan->desc = NULL;
+		pchan->done = NULL;
+		return -EAGAIN;
+	}
+
+	list_del(&desc->node);
+
+	pchan->desc = to_sun6i_desc(&desc->tx);
+	pchan->done = NULL;
+
+	sun6i_dma_dump_lli(vchan, pchan->desc->v_lli);
+
+	irq_reg = pchan->idx / DMA_IRQ_CHAN_NR;
+	irq_offset = pchan->idx % DMA_IRQ_CHAN_NR;
+
+	irq_val = readl(sdev->base + DMA_IRQ_EN(irq_offset));
+	irq_val |= DMA_IRQ_QUEUE << (irq_offset * DMA_IRQ_CHAN_WIDTH);
+	writel(irq_val, sdev->base + DMA_IRQ_EN(irq_offset));
+
+	writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR);
+	writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE);
+
+	sun6i_dma_dump_com_regs(sdev);
+	sun6i_dma_dump_chan_regs(sdev, pchan);
+
+	return 0;
+}
+
+static void sun6i_dma_tasklet(unsigned long data)
+{
+	struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
+	struct sun6i_vchan *vchan;
+	struct sun6i_pchan *pchan;
+	unsigned int pchan_alloc = 0;
+	unsigned int pchan_idx;
+
+	list_for_each_entry(vchan, &sdev->slave.channels, vc.chan.device_node) {
+		spin_lock_irq(&vchan->vc.lock);
+
+		pchan = vchan->phy;
+
+		if (pchan && pchan->done) {
+			if (sun6i_dma_start_desc(vchan)) {
+				/*
+				 * No current txd associated with this channel
+				 */
+				dev_dbg(sdev->slave.dev, "pchan %u: free\n",
+					pchan->idx);
+
+				/* Mark this channel free */
+				vchan->phy = NULL;
+				pchan->vchan = NULL;
+			}
+		}
+		spin_unlock_irq(&vchan->vc.lock);
+	}
+
+	spin_lock_irq(&sdev->lock);
+	for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+		pchan = &sdev->pchans[pchan_idx];
+
+		if (pchan->vchan || list_empty(&sdev->pending))
+			continue;
+
+		vchan = list_first_entry(&sdev->pending,
+					 struct sun6i_vchan, node);
+
+		/* Remove from pending channels */
+		list_del_init(&vchan->node);
+		pchan_alloc |= BIT(pchan_idx);
+
+		/* Mark this channel allocated */
+		pchan->vchan = vchan;
+		vchan->phy = pchan;
+		dev_dbg(sdev->slave.dev, "pchan %u: alloc vchan %p\n",
+			pchan->idx, &vchan->vc);
+	}
+	spin_unlock_irq(&sdev->lock);
+
+	for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+		if (!(pchan_alloc & BIT(pchan_idx)))
+			continue;
+
+		pchan = sdev->pchans + pchan_idx;
+		vchan = pchan->vchan;
+		if (vchan) {
+			spin_lock_irq(&vchan->vc.lock);
+			sun6i_dma_start_desc(vchan);
+			spin_unlock_irq(&vchan->vc.lock);
+		}
+	}
+}
+
+static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
+{
+	struct sun6i_dma_dev *sdev = dev_id;
+	struct sun6i_vchan *vchan;
+	struct sun6i_pchan *pchan;
+	int i, j, ret = IRQ_NONE;
+	u32 status;
+
+	for (i = 0; i < 2; i++) {
+		status = readl(sdev->base + DMA_IRQ_STAT(i));
+		if (!status)
+			continue;
+
+		dev_dbg(sdev->slave.dev, "DMA irq status %s: 0x%x\n",
+			i ? "high" : "low", status);
+
+		writel(status, sdev->base + DMA_IRQ_STAT(i));
+
+		for (j = 0; (j < 8) && status; j++) {
+			if (status & DMA_IRQ_QUEUE) {
+				pchan = sdev->pchans + j;
+				vchan = pchan->vchan;
+
+				if (vchan) {
+					spin_lock(&vchan->vc.lock);
+					vchan_cookie_complete(&pchan->desc->vd);
+					pchan->done = pchan->desc;
+					spin_unlock(&vchan->vc.lock);
+				}
+			}
+
+			status = status >> 4;
+		}
+
+		if (!atomic_read(&sdev->tasklet_shutdown))
+			tasklet_schedule(&sdev->task);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	struct dma_slave_config *sconfig = &vchan->cfg;
+	struct sun6i_dma_lli *v_lli;
+	struct sun6i_desc *txd;
+	dma_addr_t p_lli;
+	int ret;
+
+	dev_dbg(chan2dev(chan),
+		"%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n",
+		__func__, vchan->vc.chan.chan_id, &dest, &src, len, flags);
+
+	if (!len)
+		return NULL;
+
+	txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+	if (!txd)
+		return NULL;
+
+	v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
+	if (!v_lli) {
+		dev_err(sdev->slave.dev, "Failed to alloc lli memory\n");
+		goto err_txd_free;
+	}
+
+	ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig);
+	if (ret)
+		goto err_dma_free;
+
+	v_lli->cfg |= DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
+		DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
+		DMA_CHAN_CFG_DST_LINEAR_MODE |
+		DMA_CHAN_CFG_SRC_LINEAR_MODE;
+
+	sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
+
+	sun6i_dma_dump_lli(vchan, v_lli);
+
+	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
+
+err_dma_free:
+	dma_pool_free(sdev->pool, v_lli, p_lli);
+err_txd_free:
+	kfree(txd);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction dir,
+		unsigned long flags, void *context)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	struct dma_slave_config *sconfig = &vchan->cfg;
+	struct sun6i_dma_lli *v_lli, *prev = NULL;
+	struct sun6i_desc *txd;
+	struct scatterlist *sg;
+	dma_addr_t p_lli;
+	int i, ret;
+
+	if (!sgl)
+		return NULL;
+
+	if (!is_slave_direction(dir)) {
+		dev_err(chan2dev(chan), "Invalid DMA direction\n");
+		return NULL;
+	}
+
+	txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+	if (!txd)
+		return NULL;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
+		if (!v_lli)
+			goto err_lli_free;
+
+		if (dir == DMA_MEM_TO_DEV) {
+			ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg),
+						sconfig->dst_addr, sg_dma_len(sg),
+						sconfig);
+			if (ret)
+				goto err_cur_lli_free;
+
+			v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE |
+				DMA_CHAN_CFG_SRC_LINEAR_MODE |
+				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
+				DMA_CHAN_CFG_DST_DRQ(vchan->port);
+
+			dev_dbg(chan2dev(chan),
+				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
+				__func__, vchan->vc.chan.chan_id,
+				&sconfig->dst_addr, &sg_dma_address(sg),
+				sg_dma_len(sg), flags);
+
+		} else {
+			ret = sun6i_dma_cfg_lli(v_lli, sconfig->src_addr,
+						sg_dma_address(sg), sg_dma_len(sg),
+						sconfig);
+			if (ret)
+				goto err_cur_lli_free;
+
+			v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE |
+				DMA_CHAN_CFG_SRC_IO_MODE |
+				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
+				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+
+			dev_dbg(chan2dev(chan),
+				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
+				__func__, vchan->vc.chan.chan_id,
+				&sg_dma_address(sg), &sconfig->src_addr,
+				sg_dma_len(sg), flags);
+		}
+
+		prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
+	}
+
+	dev_dbg(chan2dev(chan), "First: %pad\n", &txd->p_lli);
+	for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+		sun6i_dma_dump_lli(vchan, prev);
+
+	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
+
+err_cur_lli_free:
+	dma_pool_free(sdev->pool, v_lli, p_lli);
+err_lli_free:
+	for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+		dma_pool_free(sdev->pool, prev, virt_to_phys(prev));
+	kfree(txd);
+	return NULL;
+}
+
+static int sun6i_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+		       unsigned long arg)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	struct sun6i_pchan *pchan = vchan->phy;
+	unsigned long flags;
+	int ret = 0;
+
+	switch (cmd) {
+	case DMA_RESUME:
+		dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
+
+		spin_lock_irqsave(&vchan->vc.lock, flags);
+
+		if (pchan) {
+			writel(DMA_CHAN_PAUSE_RESUME,
+			       pchan->base + DMA_CHAN_PAUSE);
+		} else if (!list_empty(&vchan->vc.desc_issued)) {
+			spin_lock(&sdev->lock);
+			list_add_tail(&vchan->node, &sdev->pending);
+			spin_unlock(&sdev->lock);
+		}
+
+		spin_unlock_irqrestore(&vchan->vc.lock, flags);
+		break;
+
+	case DMA_PAUSE:
+		dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc);
+
+		if (pchan) {
+			writel(DMA_CHAN_PAUSE_PAUSE,
+			       pchan->base + DMA_CHAN_PAUSE);
+		} else {
+			spin_lock(&sdev->lock);
+			list_del_init(&vchan->node);
+			spin_unlock(&sdev->lock);
+		}
+		break;
+
+	case DMA_TERMINATE_ALL:
+		ret = sun6i_dma_terminate_all(vchan);
+		break;
+	case DMA_SLAVE_CONFIG:
+		memcpy(&vchan->cfg, (void *)arg, sizeof(struct dma_slave_config));
+		break;
+	default:
+		ret = -ENXIO;
+		break;
+	}
+	return ret;
+}
+
+static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan,
+					   dma_cookie_t cookie,
+					   struct dma_tx_state *state)
+{
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	struct sun6i_pchan *pchan = vchan->phy;
+	struct sun6i_dma_lli *lli;
+	struct virt_dma_desc *vd;
+	struct sun6i_desc *txd;
+	enum dma_status ret;
+	unsigned long flags;
+	size_t bytes = 0;
+
+	ret = dma_cookie_status(chan, cookie, state);
+	if (ret == DMA_COMPLETE)
+		return ret;
+
+	spin_lock_irqsave(&vchan->vc.lock, flags);
+
+	vd = vchan_find_desc(&vchan->vc, cookie);
+	txd = to_sun6i_desc(&vd->tx);
+
+	if (vd) {
+		for (lli = txd->v_lli; lli != NULL; lli = lli->v_lli_next)
+			bytes += lli->len;
+	} else if (!pchan || !pchan->desc) {
+		bytes = 0;
+	} else {
+		bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
+	}
+
+	spin_unlock_irqrestore(&vchan->vc.lock, flags);
+
+	dma_set_residue(state, bytes);
+
+	return ret;
+}
+
+static void sun6i_dma_issue_pending(struct dma_chan *chan)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vchan->vc.lock, flags);
+
+	if (vchan_issue_pending(&vchan->vc)) {
+		spin_lock(&sdev->lock);
+
+		if (!vchan->phy && list_empty(&vchan->node)) {
+			list_add_tail(&vchan->node, &sdev->pending);
+			tasklet_schedule(&sdev->task);
+			dev_dbg(chan2dev(chan), "vchan %p: issued\n",
+				&vchan->vc);
+		}
+
+		spin_unlock(&sdev->lock);
+	} else {
+		dev_dbg(chan2dev(chan), "vchan %p: nothing to issue\n",
+			&vchan->vc);
+	}
+
+	spin_unlock_irqrestore(&vchan->vc.lock, flags);
+}
+
+static int sun6i_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	return 0;
+}
+
+static void sun6i_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdev->lock, flags);
+	list_del_init(&vchan->node);
+	spin_unlock_irqrestore(&sdev->lock, flags);
+
+	vchan_free_chan_resources(&vchan->vc);
+}
+
+static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
+					   struct of_dma *ofdma)
+{
+	struct sun6i_dma_dev *sdev = ofdma->of_dma_data;
+	struct sun6i_vchan *vchan;
+	struct dma_chan *chan;
+	u8 port = dma_spec->args[0];
+
+	if (port > NR_MAX_REQUESTS)
+		return NULL;
+
+	chan = dma_get_any_slave_channel(&sdev->slave);
+	if (!chan)
+		return NULL;
+
+	vchan = to_sun6i_vchan(chan);
+	vchan->port = port;
+
+	return chan;
+}
+
+static inline void sun6i_kill_tasklet(struct sun6i_dma_dev *sdev)
+{
+	/* Disable all interrupts from DMA */
+	writel(0, sdev->base + DMA_IRQ_EN(0));
+	writel(0, sdev->base + DMA_IRQ_EN(1));
+
+	/* Prevent spurious interrupts from scheduling the tasklet */
+	atomic_inc(&sdev->tasklet_shutdown);
+
+	/* Make sure we won't have any further interrupts */
+	devm_free_irq(sdev->slave.dev, sdev->irq, sdev);
+
+	/* Actually prevent the tasklet from being scheduled */
+	tasklet_kill(&sdev->task);
+}
+
+static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
+{
+	int i;
+
+	for (i = 0; i < NR_MAX_VCHANS; i++) {
+		struct sun6i_vchan *vchan = &sdev->vchans[i];
+
+		list_del(&vchan->vc.chan.device_node);
+		tasklet_kill(&vchan->vc.task);
+	}
+}
+
+static int sun6i_dma_probe(struct platform_device *pdev)
+{
+	struct sun6i_dma_dev *sdc;
+	struct resource *res;
+	struct clk *mux, *pll6;
+	int ret, i;
+
+	sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
+	if (!sdc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sdc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sdc->base))
+		return PTR_ERR(sdc->base);
+
+	sdc->irq = platform_get_irq(pdev, 0);
+	if (sdc->irq < 0) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		return sdc->irq;
+	}
+
+	sdc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(sdc->clk)) {
+		dev_err(&pdev->dev, "No clock specified\n");
+		return PTR_ERR(sdc->clk);
+	}
+
+	mux = clk_get(NULL, "ahb1_mux");
+	if (IS_ERR(mux)) {
+		dev_err(&pdev->dev, "Couldn't get AHB1 Mux\n");
+		return PTR_ERR(mux);
+	}
+
+	pll6 = clk_get(NULL, "pll6");
+	if (IS_ERR(pll6)) {
+		dev_err(&pdev->dev, "Couldn't get PLL6\n");
+		clk_put(mux);
+		return PTR_ERR(pll6);
+	}
+
+	ret = clk_set_parent(mux, pll6);
+	clk_put(pll6);
+	clk_put(mux);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't reparent AHB1 on PLL6\n");
+		return ret;
+	}
+
+	sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(sdc->rstc)) {
+		dev_err(&pdev->dev, "No reset controller specified\n");
+		return PTR_ERR(sdc->rstc);
+	}
+
+	sdc->pool = dmam_pool_create(dev_name(&pdev->dev), &pdev->dev,
+				     sizeof(struct sun6i_dma_lli), 4, 0);
+	if (!sdc->pool) {
+		dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, sdc);
+	INIT_LIST_HEAD(&sdc->pending);
+	spin_lock_init(&sdc->lock);
+
+	dma_cap_set(DMA_PRIVATE, sdc->slave.cap_mask);
+	dma_cap_set(DMA_MEMCPY, sdc->slave.cap_mask);
+	dma_cap_set(DMA_SLAVE, sdc->slave.cap_mask);
+
+	INIT_LIST_HEAD(&sdc->slave.channels);
+	sdc->slave.device_alloc_chan_resources	= sun6i_dma_alloc_chan_resources;
+	sdc->slave.device_free_chan_resources	= sun6i_dma_free_chan_resources;
+	sdc->slave.device_tx_status		= sun6i_dma_tx_status;
+	sdc->slave.device_issue_pending		= sun6i_dma_issue_pending;
+	sdc->slave.device_prep_slave_sg		= sun6i_dma_prep_slave_sg;
+	sdc->slave.device_prep_dma_memcpy	= sun6i_dma_prep_dma_memcpy;
+	sdc->slave.device_control		= sun6i_dma_control;
+	sdc->slave.chancnt			= NR_MAX_VCHANS;
+
+	sdc->slave.dev = &pdev->dev;
+
+	sdc->pchans = devm_kcalloc(&pdev->dev, NR_MAX_CHANNELS,
+				   sizeof(struct sun6i_pchan), GFP_KERNEL);
+	if (!sdc->pchans)
+		return -ENOMEM;
+
+	sdc->vchans = devm_kcalloc(&pdev->dev, NR_MAX_VCHANS,
+				   sizeof(struct sun6i_vchan), GFP_KERNEL);
+	if (!sdc->vchans)
+		return -ENOMEM;
+
+	tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
+
+	for (i = 0; i < NR_MAX_CHANNELS; i++) {
+		struct sun6i_pchan *pchan = &sdc->pchans[i];
+
+		pchan->idx = i;
+		pchan->base = sdc->base + 0x100 + i * 0x40;
+	}
+
+	for (i = 0; i < NR_MAX_VCHANS; i++) {
+		struct sun6i_vchan *vchan = &sdc->vchans[i];
+
+		INIT_LIST_HEAD(&vchan->node);
+		vchan->vc.desc_free = sun6i_dma_free_desc;
+		vchan_init(&vchan->vc, &sdc->slave);
+	}
+
+	ret = reset_control_deassert(sdc->rstc);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't deassert the device from reset\n");
+		goto err_chan_free;
+	}
+
+	ret = clk_prepare_enable(sdc->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable the clock\n");
+		goto err_reset_assert;
+	}
+
+	ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
+			       dev_name(&pdev->dev), sdc);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot request IRQ\n");
+		goto err_clk_disable;
+	}
+
+	ret = dma_async_device_register(&sdc->slave);
+	if (ret) {
+		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
+		goto err_irq_disable;
+	}
+
+	ret = of_dma_controller_register(pdev->dev.of_node, sun6i_dma_of_xlate,
+					 sdc);
+	if (ret) {
+		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
+		goto err_dma_unregister;
+	}
+
+	return 0;
+
+err_dma_unregister:
+	dma_async_device_unregister(&sdc->slave);
+err_irq_disable:
+	sun6i_kill_tasklet(sdc);
+err_clk_disable:
+	clk_disable_unprepare(sdc->clk);
+err_reset_assert:
+	reset_control_assert(sdc->rstc);
+err_chan_free:
+	sun6i_dma_free(sdc);
+	return ret;
+}
+
+static int sun6i_dma_remove(struct platform_device *pdev)
+{
+	struct sun6i_dma_dev *sdc = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&sdc->slave);
+
+	sun6i_kill_tasklet(sdc);
+
+	clk_disable_unprepare(sdc->clk);
+	reset_control_assert(sdc->rstc);
+
+	sun6i_dma_free(sdc);
+
+	return 0;
+}
+
+static struct of_device_id sun6i_dma_match[] = {
+	{ .compatible = "allwinner,sun6i-a31-dma" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver sun6i_dma_driver = {
+	.probe		= sun6i_dma_probe,
+	.remove		= sun6i_dma_remove,
+	.driver = {
+		.name		= "sun6i-dma",
+		.of_match_table	= sun6i_dma_match,
+	},
+};
+module_platform_driver(sun6i_dma_driver);
+
+MODULE_DESCRIPTION("Allwinner A31 DMA Controller Driver");
+MODULE_AUTHOR("Sugar <shuge@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/tegra20-apb-dma.c linux-libre-3.17-rc7-gnu/drivers/dma/tegra20-apb-dma.c
--- linux-libre-3.16-gnu/drivers/dma/tegra20-apb-dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/tegra20-apb-dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -1055,7 +1055,7 @@ static struct dma_async_tx_descriptor *t
 static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
 	struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags, void *context)
+	unsigned long flags)
 {
 	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
 	struct tegra_dma_desc *dma_desc = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma/TODO linux-libre-3.17-rc7-gnu/drivers/dma/TODO
--- linux-libre-3.16-gnu/drivers/dma/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/dma/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,6 @@ TODO for slave dma
 	- imx-dma
 	- imx-sdma
 	- mxs-dma.c
-	- dw_dmac
 	- intel_mid_dma
 4. Check other subsystems for dma drivers and merge/move to dmaengine
 5. Remove dma_slave_config's dma direction.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma-buf/dma-buf.c linux-libre-3.17-rc7-gnu/drivers/dma-buf/dma-buf.c
--- linux-libre-3.16-gnu/drivers/dma-buf/dma-buf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma-buf/dma-buf.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,907 @@
+/*
+ * Framework for buffer objects that can be shared across devices/subsystems.
+ *
+ * Copyright(C) 2011 Linaro Limited. All rights reserved.
+ * Author: Sumit Semwal <sumit.semwal@ti.com>
+ *
+ * Many thanks to linaro-mm-sig list, and specially
+ * Arnd Bergmann <arnd@arndb.de>, Rob Clark <rob@ti.com> and
+ * Daniel Vetter <daniel@ffwll.ch> for their support in creation and
+ * refining of this idea.
+ *
+ * This program is free software; you can 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/fs.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+#include <linux/fence.h>
+#include <linux/anon_inodes.h>
+#include <linux/export.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+#include <linux/reservation.h>
+
+static inline int is_dma_buf_file(struct file *);
+
+struct dma_buf_list {
+	struct list_head head;
+	struct mutex lock;
+};
+
+static struct dma_buf_list db_list;
+
+static int dma_buf_release(struct inode *inode, struct file *file)
+{
+	struct dma_buf *dmabuf;
+
+	if (!is_dma_buf_file(file))
+		return -EINVAL;
+
+	dmabuf = file->private_data;
+
+	BUG_ON(dmabuf->vmapping_counter);
+
+	/*
+	 * Any fences that a dma-buf poll can wait on should be signaled
+	 * before releasing dma-buf. This is the responsibility of each
+	 * driver that uses the reservation objects.
+	 *
+	 * If you hit this BUG() it means someone dropped their ref to the
+	 * dma-buf while still having pending operation to the buffer.
+	 */
+	BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
+
+	dmabuf->ops->release(dmabuf);
+
+	mutex_lock(&db_list.lock);
+	list_del(&dmabuf->list_node);
+	mutex_unlock(&db_list.lock);
+
+	if (dmabuf->resv == (struct reservation_object *)&dmabuf[1])
+		reservation_object_fini(dmabuf->resv);
+
+	kfree(dmabuf);
+	return 0;
+}
+
+static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
+{
+	struct dma_buf *dmabuf;
+
+	if (!is_dma_buf_file(file))
+		return -EINVAL;
+
+	dmabuf = file->private_data;
+
+	/* check for overflowing the buffer's size */
+	if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+	    dmabuf->size >> PAGE_SHIFT)
+		return -EINVAL;
+
+	return dmabuf->ops->mmap(dmabuf, vma);
+}
+
+static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
+{
+	struct dma_buf *dmabuf;
+	loff_t base;
+
+	if (!is_dma_buf_file(file))
+		return -EBADF;
+
+	dmabuf = file->private_data;
+
+	/* only support discovering the end of the buffer,
+	   but also allow SEEK_SET to maintain the idiomatic
+	   SEEK_END(0), SEEK_CUR(0) pattern */
+	if (whence == SEEK_END)
+		base = dmabuf->size;
+	else if (whence == SEEK_SET)
+		base = 0;
+	else
+		return -EINVAL;
+
+	if (offset != 0)
+		return -EINVAL;
+
+	return base + offset;
+}
+
+static void dma_buf_poll_cb(struct fence *fence, struct fence_cb *cb)
+{
+	struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dcb->poll->lock, flags);
+	wake_up_locked_poll(dcb->poll, dcb->active);
+	dcb->active = 0;
+	spin_unlock_irqrestore(&dcb->poll->lock, flags);
+}
+
+static unsigned int dma_buf_poll(struct file *file, poll_table *poll)
+{
+	struct dma_buf *dmabuf;
+	struct reservation_object *resv;
+	struct reservation_object_list *fobj;
+	struct fence *fence_excl;
+	unsigned long events;
+	unsigned shared_count, seq;
+
+	dmabuf = file->private_data;
+	if (!dmabuf || !dmabuf->resv)
+		return POLLERR;
+
+	resv = dmabuf->resv;
+
+	poll_wait(file, &dmabuf->poll, poll);
+
+	events = poll_requested_events(poll) & (POLLIN | POLLOUT);
+	if (!events)
+		return 0;
+
+retry:
+	seq = read_seqcount_begin(&resv->seq);
+	rcu_read_lock();
+
+	fobj = rcu_dereference(resv->fence);
+	if (fobj)
+		shared_count = fobj->shared_count;
+	else
+		shared_count = 0;
+	fence_excl = rcu_dereference(resv->fence_excl);
+	if (read_seqcount_retry(&resv->seq, seq)) {
+		rcu_read_unlock();
+		goto retry;
+	}
+
+	if (fence_excl && (!(events & POLLOUT) || shared_count == 0)) {
+		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
+		unsigned long pevents = POLLIN;
+
+		if (shared_count == 0)
+			pevents |= POLLOUT;
+
+		spin_lock_irq(&dmabuf->poll.lock);
+		if (dcb->active) {
+			dcb->active |= pevents;
+			events &= ~pevents;
+		} else
+			dcb->active = pevents;
+		spin_unlock_irq(&dmabuf->poll.lock);
+
+		if (events & pevents) {
+			if (!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)) {
+				events &= ~pevents;
+				fence_put(fence_excl);
+			} else {
+				/*
+				 * No callback queued, wake up any additional
+				 * waiters.
+				 */
+				fence_put(fence_excl);
+				dma_buf_poll_cb(NULL, &dcb->cb);
+			}
+		}
+	}
+
+	if ((events & POLLOUT) && shared_count > 0) {
+		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared;
+		int i;
+
+		/* Only queue a new callback if no event has fired yet */
+		spin_lock_irq(&dmabuf->poll.lock);
+		if (dcb->active)
+			events &= ~POLLOUT;
+		else
+			dcb->active = POLLOUT;
+		spin_unlock_irq(&dmabuf->poll.lock);
+
+		if (!(events & POLLOUT))
+			goto out;
+
+		for (i = 0; i < shared_count; ++i) {
+			struct fence *fence = rcu_dereference(fobj->shared[i]);
+
+			if (!fence_get_rcu(fence)) {
+				/*
+				 * fence refcount dropped to zero, this means
+				 * that fobj has been freed
+				 *
+				 * call dma_buf_poll_cb and force a recheck!
+				 */
+				events &= ~POLLOUT;
+				dma_buf_poll_cb(NULL, &dcb->cb);
+				break;
+			}
+			if (!fence_add_callback(fence, &dcb->cb,
+						dma_buf_poll_cb)) {
+				fence_put(fence);
+				events &= ~POLLOUT;
+				break;
+			}
+			fence_put(fence);
+		}
+
+		/* No callback queued, wake up any additional waiters. */
+		if (i == shared_count)
+			dma_buf_poll_cb(NULL, &dcb->cb);
+	}
+
+out:
+	rcu_read_unlock();
+	return events;
+}
+
+static const struct file_operations dma_buf_fops = {
+	.release	= dma_buf_release,
+	.mmap		= dma_buf_mmap_internal,
+	.llseek		= dma_buf_llseek,
+	.poll		= dma_buf_poll,
+};
+
+/*
+ * is_dma_buf_file - Check if struct file* is associated with dma_buf
+ */
+static inline int is_dma_buf_file(struct file *file)
+{
+	return file->f_op == &dma_buf_fops;
+}
+
+/**
+ * dma_buf_export_named - Creates a new dma_buf, and associates an anon file
+ * with this buffer, so it can be exported.
+ * Also connect the allocator specific data and ops to the buffer.
+ * Additionally, provide a name string for exporter; useful in debugging.
+ *
+ * @priv:	[in]	Attach private data of allocator to this buffer
+ * @ops:	[in]	Attach allocator-defined dma buf ops to the new buffer.
+ * @size:	[in]	Size of the buffer
+ * @flags:	[in]	mode flags for the file.
+ * @exp_name:	[in]	name of the exporting module - useful for debugging.
+ * @resv:	[in]	reservation-object, NULL to allocate default one.
+ *
+ * Returns, on success, a newly created dma_buf object, which wraps the
+ * supplied private data and operations for dma_buf_ops. On either missing
+ * ops, or error in allocating struct dma_buf, will return negative error.
+ *
+ */
+struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
+				size_t size, int flags, const char *exp_name,
+				struct reservation_object *resv)
+{
+	struct dma_buf *dmabuf;
+	struct file *file;
+	size_t alloc_size = sizeof(struct dma_buf);
+	if (!resv)
+		alloc_size += sizeof(struct reservation_object);
+	else
+		/* prevent &dma_buf[1] == dma_buf->resv */
+		alloc_size += 1;
+
+	if (WARN_ON(!priv || !ops
+			  || !ops->map_dma_buf
+			  || !ops->unmap_dma_buf
+			  || !ops->release
+			  || !ops->kmap_atomic
+			  || !ops->kmap
+			  || !ops->mmap)) {
+		return ERR_PTR(-EINVAL);
+	}
+
+	dmabuf = kzalloc(alloc_size, GFP_KERNEL);
+	if (dmabuf == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	dmabuf->priv = priv;
+	dmabuf->ops = ops;
+	dmabuf->size = size;
+	dmabuf->exp_name = exp_name;
+	init_waitqueue_head(&dmabuf->poll);
+	dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
+	dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
+
+	if (!resv) {
+		resv = (struct reservation_object *)&dmabuf[1];
+		reservation_object_init(resv);
+	}
+	dmabuf->resv = resv;
+
+	file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
+	if (IS_ERR(file)) {
+		kfree(dmabuf);
+		return ERR_CAST(file);
+	}
+
+	file->f_mode |= FMODE_LSEEK;
+	dmabuf->file = file;
+
+	mutex_init(&dmabuf->lock);
+	INIT_LIST_HEAD(&dmabuf->attachments);
+
+	mutex_lock(&db_list.lock);
+	list_add(&dmabuf->list_node, &db_list.head);
+	mutex_unlock(&db_list.lock);
+
+	return dmabuf;
+}
+EXPORT_SYMBOL_GPL(dma_buf_export_named);
+
+
+/**
+ * dma_buf_fd - returns a file descriptor for the given dma_buf
+ * @dmabuf:	[in]	pointer to dma_buf for which fd is required.
+ * @flags:      [in]    flags to give to fd
+ *
+ * On success, returns an associated 'fd'. Else, returns error.
+ */
+int dma_buf_fd(struct dma_buf *dmabuf, int flags)
+{
+	int fd;
+
+	if (!dmabuf || !dmabuf->file)
+		return -EINVAL;
+
+	fd = get_unused_fd_flags(flags);
+	if (fd < 0)
+		return fd;
+
+	fd_install(fd, dmabuf->file);
+
+	return fd;
+}
+EXPORT_SYMBOL_GPL(dma_buf_fd);
+
+/**
+ * dma_buf_get - returns the dma_buf structure related to an fd
+ * @fd:	[in]	fd associated with the dma_buf to be returned
+ *
+ * On success, returns the dma_buf structure associated with an fd; uses
+ * file's refcounting done by fget to increase refcount. returns ERR_PTR
+ * otherwise.
+ */
+struct dma_buf *dma_buf_get(int fd)
+{
+	struct file *file;
+
+	file = fget(fd);
+
+	if (!file)
+		return ERR_PTR(-EBADF);
+
+	if (!is_dma_buf_file(file)) {
+		fput(file);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return file->private_data;
+}
+EXPORT_SYMBOL_GPL(dma_buf_get);
+
+/**
+ * dma_buf_put - decreases refcount of the buffer
+ * @dmabuf:	[in]	buffer to reduce refcount of
+ *
+ * Uses file's refcounting done implicitly by fput()
+ */
+void dma_buf_put(struct dma_buf *dmabuf)
+{
+	if (WARN_ON(!dmabuf || !dmabuf->file))
+		return;
+
+	fput(dmabuf->file);
+}
+EXPORT_SYMBOL_GPL(dma_buf_put);
+
+/**
+ * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
+ * calls attach() of dma_buf_ops to allow device-specific attach functionality
+ * @dmabuf:	[in]	buffer to attach device to.
+ * @dev:	[in]	device to be attached.
+ *
+ * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
+ * error.
+ */
+struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
+					  struct device *dev)
+{
+	struct dma_buf_attachment *attach;
+	int ret;
+
+	if (WARN_ON(!dmabuf || !dev))
+		return ERR_PTR(-EINVAL);
+
+	attach = kzalloc(sizeof(struct dma_buf_attachment), GFP_KERNEL);
+	if (attach == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	attach->dev = dev;
+	attach->dmabuf = dmabuf;
+
+	mutex_lock(&dmabuf->lock);
+
+	if (dmabuf->ops->attach) {
+		ret = dmabuf->ops->attach(dmabuf, dev, attach);
+		if (ret)
+			goto err_attach;
+	}
+	list_add(&attach->node, &dmabuf->attachments);
+
+	mutex_unlock(&dmabuf->lock);
+	return attach;
+
+err_attach:
+	kfree(attach);
+	mutex_unlock(&dmabuf->lock);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dma_buf_attach);
+
+/**
+ * dma_buf_detach - Remove the given attachment from dmabuf's attachments list;
+ * optionally calls detach() of dma_buf_ops for device-specific detach
+ * @dmabuf:	[in]	buffer to detach from.
+ * @attach:	[in]	attachment to be detached; is free'd after this call.
+ *
+ */
+void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
+{
+	if (WARN_ON(!dmabuf || !attach))
+		return;
+
+	mutex_lock(&dmabuf->lock);
+	list_del(&attach->node);
+	if (dmabuf->ops->detach)
+		dmabuf->ops->detach(dmabuf, attach);
+
+	mutex_unlock(&dmabuf->lock);
+	kfree(attach);
+}
+EXPORT_SYMBOL_GPL(dma_buf_detach);
+
+/**
+ * dma_buf_map_attachment - Returns the scatterlist table of the attachment;
+ * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
+ * dma_buf_ops.
+ * @attach:	[in]	attachment whose scatterlist is to be returned
+ * @direction:	[in]	direction of DMA transfer
+ *
+ * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
+ * on error.
+ */
+struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
+					enum dma_data_direction direction)
+{
+	struct sg_table *sg_table = ERR_PTR(-EINVAL);
+
+	might_sleep();
+
+	if (WARN_ON(!attach || !attach->dmabuf))
+		return ERR_PTR(-EINVAL);
+
+	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
+	if (!sg_table)
+		sg_table = ERR_PTR(-ENOMEM);
+
+	return sg_table;
+}
+EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
+
+/**
+ * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
+ * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
+ * dma_buf_ops.
+ * @attach:	[in]	attachment to unmap buffer from
+ * @sg_table:	[in]	scatterlist info of the buffer to unmap
+ * @direction:  [in]    direction of DMA transfer
+ *
+ */
+void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
+				struct sg_table *sg_table,
+				enum dma_data_direction direction)
+{
+	might_sleep();
+
+	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
+		return;
+
+	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,
+						direction);
+}
+EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+
+
+/**
+ * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the
+ * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific
+ * preparations. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dmabuf:	[in]	buffer to prepare cpu access for.
+ * @start:	[in]	start of range for cpu access.
+ * @len:	[in]	length of range for cpu access.
+ * @direction:	[in]	length of range for cpu access.
+ *
+ * Can return negative error values, returns 0 on success.
+ */
+int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+			     enum dma_data_direction direction)
+{
+	int ret = 0;
+
+	if (WARN_ON(!dmabuf))
+		return -EINVAL;
+
+	if (dmabuf->ops->begin_cpu_access)
+		ret = dmabuf->ops->begin_cpu_access(dmabuf, start, len, direction);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
+
+/**
+ * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the
+ * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific
+ * actions. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dmabuf:	[in]	buffer to complete cpu access for.
+ * @start:	[in]	start of range for cpu access.
+ * @len:	[in]	length of range for cpu access.
+ * @direction:	[in]	length of range for cpu access.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+			    enum dma_data_direction direction)
+{
+	WARN_ON(!dmabuf);
+
+	if (dmabuf->ops->end_cpu_access)
+		dmabuf->ops->end_cpu_access(dmabuf, start, len, direction);
+}
+EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
+
+/**
+ * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
+ * space. The same restrictions as for kmap_atomic and friends apply.
+ * @dmabuf:	[in]	buffer to map page from.
+ * @page_num:	[in]	page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
+{
+	WARN_ON(!dmabuf);
+
+	return dmabuf->ops->kmap_atomic(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
+
+/**
+ * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
+ * @dmabuf:	[in]	buffer to unmap page from.
+ * @page_num:	[in]	page in PAGE_SIZE units to unmap.
+ * @vaddr:	[in]	kernel space pointer obtained from dma_buf_kmap_atomic.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
+			   void *vaddr)
+{
+	WARN_ON(!dmabuf);
+
+	if (dmabuf->ops->kunmap_atomic)
+		dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
+
+/**
+ * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
+ * same restrictions as for kmap and friends apply.
+ * @dmabuf:	[in]	buffer to map page from.
+ * @page_num:	[in]	page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
+{
+	WARN_ON(!dmabuf);
+
+	return dmabuf->ops->kmap(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap);
+
+/**
+ * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
+ * @dmabuf:	[in]	buffer to unmap page from.
+ * @page_num:	[in]	page in PAGE_SIZE units to unmap.
+ * @vaddr:	[in]	kernel space pointer obtained from dma_buf_kmap.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
+		    void *vaddr)
+{
+	WARN_ON(!dmabuf);
+
+	if (dmabuf->ops->kunmap)
+		dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap);
+
+
+/**
+ * dma_buf_mmap - Setup up a userspace mmap with the given vma
+ * @dmabuf:	[in]	buffer that should back the vma
+ * @vma:	[in]	vma for the mmap
+ * @pgoff:	[in]	offset in pages where this mmap should start within the
+ * 			dma-buf buffer.
+ *
+ * This function adjusts the passed in vma so that it points at the file of the
+ * dma_buf operation. It also adjusts the starting pgoff and does bounds
+ * checking on the size of the vma. Then it calls the exporters mmap function to
+ * set up the mapping.
+ *
+ * Can return negative error values, returns 0 on success.
+ */
+int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
+		 unsigned long pgoff)
+{
+	struct file *oldfile;
+	int ret;
+
+	if (WARN_ON(!dmabuf || !vma))
+		return -EINVAL;
+
+	/* check for offset overflow */
+	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)
+		return -EOVERFLOW;
+
+	/* check for overflowing the buffer's size */
+	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+	    dmabuf->size >> PAGE_SHIFT)
+		return -EINVAL;
+
+	/* readjust the vma */
+	get_file(dmabuf->file);
+	oldfile = vma->vm_file;
+	vma->vm_file = dmabuf->file;
+	vma->vm_pgoff = pgoff;
+
+	ret = dmabuf->ops->mmap(dmabuf, vma);
+	if (ret) {
+		/* restore old parameters on failure */
+		vma->vm_file = oldfile;
+		fput(dmabuf->file);
+	} else {
+		if (oldfile)
+			fput(oldfile);
+	}
+	return ret;
+
+}
+EXPORT_SYMBOL_GPL(dma_buf_mmap);
+
+/**
+ * dma_buf_vmap - Create virtual mapping for the buffer object into kernel
+ * address space. Same restrictions as for vmap and friends apply.
+ * @dmabuf:	[in]	buffer to vmap
+ *
+ * This call may fail due to lack of virtual mapping address space.
+ * These calls are optional in drivers. The intended use for them
+ * is for mapping objects linear in kernel space for high use objects.
+ * Please attempt to use kmap/kunmap before thinking about these interfaces.
+ *
+ * Returns NULL on error.
+ */
+void *dma_buf_vmap(struct dma_buf *dmabuf)
+{
+	void *ptr;
+
+	if (WARN_ON(!dmabuf))
+		return NULL;
+
+	if (!dmabuf->ops->vmap)
+		return NULL;
+
+	mutex_lock(&dmabuf->lock);
+	if (dmabuf->vmapping_counter) {
+		dmabuf->vmapping_counter++;
+		BUG_ON(!dmabuf->vmap_ptr);
+		ptr = dmabuf->vmap_ptr;
+		goto out_unlock;
+	}
+
+	BUG_ON(dmabuf->vmap_ptr);
+
+	ptr = dmabuf->ops->vmap(dmabuf);
+	if (WARN_ON_ONCE(IS_ERR(ptr)))
+		ptr = NULL;
+	if (!ptr)
+		goto out_unlock;
+
+	dmabuf->vmap_ptr = ptr;
+	dmabuf->vmapping_counter = 1;
+
+out_unlock:
+	mutex_unlock(&dmabuf->lock);
+	return ptr;
+}
+EXPORT_SYMBOL_GPL(dma_buf_vmap);
+
+/**
+ * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
+ * @dmabuf:	[in]	buffer to vunmap
+ * @vaddr:	[in]	vmap to vunmap
+ */
+void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+	if (WARN_ON(!dmabuf))
+		return;
+
+	BUG_ON(!dmabuf->vmap_ptr);
+	BUG_ON(dmabuf->vmapping_counter == 0);
+	BUG_ON(dmabuf->vmap_ptr != vaddr);
+
+	mutex_lock(&dmabuf->lock);
+	if (--dmabuf->vmapping_counter == 0) {
+		if (dmabuf->ops->vunmap)
+			dmabuf->ops->vunmap(dmabuf, vaddr);
+		dmabuf->vmap_ptr = NULL;
+	}
+	mutex_unlock(&dmabuf->lock);
+}
+EXPORT_SYMBOL_GPL(dma_buf_vunmap);
+
+#ifdef CONFIG_DEBUG_FS
+static int dma_buf_describe(struct seq_file *s)
+{
+	int ret;
+	struct dma_buf *buf_obj;
+	struct dma_buf_attachment *attach_obj;
+	int count = 0, attach_count;
+	size_t size = 0;
+
+	ret = mutex_lock_interruptible(&db_list.lock);
+
+	if (ret)
+		return ret;
+
+	seq_puts(s, "\nDma-buf Objects:\n");
+	seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
+
+	list_for_each_entry(buf_obj, &db_list.head, list_node) {
+		ret = mutex_lock_interruptible(&buf_obj->lock);
+
+		if (ret) {
+			seq_puts(s,
+				 "\tERROR locking buffer object: skipping\n");
+			continue;
+		}
+
+		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n",
+				buf_obj->size,
+				buf_obj->file->f_flags, buf_obj->file->f_mode,
+				(long)(buf_obj->file->f_count.counter),
+				buf_obj->exp_name);
+
+		seq_puts(s, "\tAttached Devices:\n");
+		attach_count = 0;
+
+		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
+			seq_puts(s, "\t");
+
+			seq_printf(s, "%s\n", dev_name(attach_obj->dev));
+			attach_count++;
+		}
+
+		seq_printf(s, "Total %d devices attached\n\n",
+				attach_count);
+
+		count++;
+		size += buf_obj->size;
+		mutex_unlock(&buf_obj->lock);
+	}
+
+	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
+
+	mutex_unlock(&db_list.lock);
+	return 0;
+}
+
+static int dma_buf_show(struct seq_file *s, void *unused)
+{
+	void (*func)(struct seq_file *) = s->private;
+	func(s);
+	return 0;
+}
+
+static int dma_buf_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dma_buf_show, inode->i_private);
+}
+
+static const struct file_operations dma_buf_debug_fops = {
+	.open           = dma_buf_debug_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static struct dentry *dma_buf_debugfs_dir;
+
+static int dma_buf_init_debugfs(void)
+{
+	int err = 0;
+	dma_buf_debugfs_dir = debugfs_create_dir("dma_buf", NULL);
+	if (IS_ERR(dma_buf_debugfs_dir)) {
+		err = PTR_ERR(dma_buf_debugfs_dir);
+		dma_buf_debugfs_dir = NULL;
+		return err;
+	}
+
+	err = dma_buf_debugfs_create_file("bufinfo", dma_buf_describe);
+
+	if (err)
+		pr_debug("dma_buf: debugfs: failed to create node bufinfo\n");
+
+	return err;
+}
+
+static void dma_buf_uninit_debugfs(void)
+{
+	if (dma_buf_debugfs_dir)
+		debugfs_remove_recursive(dma_buf_debugfs_dir);
+}
+
+int dma_buf_debugfs_create_file(const char *name,
+				int (*write)(struct seq_file *))
+{
+	struct dentry *d;
+
+	d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir,
+			write, &dma_buf_debug_fops);
+
+	return PTR_ERR_OR_ZERO(d);
+}
+#else
+static inline int dma_buf_init_debugfs(void)
+{
+	return 0;
+}
+static inline void dma_buf_uninit_debugfs(void)
+{
+}
+#endif
+
+static int __init dma_buf_init(void)
+{
+	mutex_init(&db_list.lock);
+	INIT_LIST_HEAD(&db_list.head);
+	dma_buf_init_debugfs();
+	return 0;
+}
+subsys_initcall(dma_buf_init);
+
+static void __exit dma_buf_deinit(void)
+{
+	dma_buf_uninit_debugfs();
+}
+__exitcall(dma_buf_deinit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma-buf/fence.c linux-libre-3.17-rc7-gnu/drivers/dma-buf/fence.c
--- linux-libre-3.16-gnu/drivers/dma-buf/fence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma-buf/fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,431 @@
+/*
+ * 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 atomic_t fence_context_counter = ATOMIC_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.
+ */
+unsigned fence_context_alloc(unsigned num)
+{
+	BUG_ON(!num);
+	return atomic_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;
+
+	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 succesfully 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);
+
+/**
+ * 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, unsigned 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-3.16-gnu/drivers/dma-buf/Makefile linux-libre-3.17-rc7-gnu/drivers/dma-buf/Makefile
--- linux-libre-3.16-gnu/drivers/dma-buf/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma-buf/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/dma-buf/reservation.c linux-libre-3.17-rc7-gnu/drivers/dma-buf/reservation.c
--- linux-libre-3.16-gnu/drivers/dma-buf/reservation.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma-buf/reservation.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012-2014 Canonical Ltd (Maarten Lankhorst)
+ *
+ * Based on bo.c which bears the following copyright notice,
+ * but is dual licensed:
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <linux/reservation.h>
+#include <linux/export.h>
+
+DEFINE_WW_CLASS(reservation_ww_class);
+EXPORT_SYMBOL(reservation_ww_class);
+
+struct lock_class_key reservation_seqcount_class;
+EXPORT_SYMBOL(reservation_seqcount_class);
+
+const char reservation_seqcount_string[] = "reservation_seqcount";
+EXPORT_SYMBOL(reservation_seqcount_string);
+/*
+ * Reserve space to add a shared fence to a reservation_object,
+ * must be called with obj->lock held.
+ */
+int reservation_object_reserve_shared(struct reservation_object *obj)
+{
+	struct reservation_object_list *fobj, *old;
+	u32 max;
+
+	old = reservation_object_get_list(obj);
+
+	if (old && old->shared_max) {
+		if (old->shared_count < old->shared_max) {
+			/* perform an in-place update */
+			kfree(obj->staged);
+			obj->staged = NULL;
+			return 0;
+		} else
+			max = old->shared_max * 2;
+	} else
+		max = 4;
+
+	/*
+	 * resize obj->staged or allocate if it doesn't exist,
+	 * noop if already correct size
+	 */
+	fobj = krealloc(obj->staged, offsetof(typeof(*fobj), shared[max]),
+			GFP_KERNEL);
+	if (!fobj)
+		return -ENOMEM;
+
+	obj->staged = fobj;
+	fobj->shared_max = max;
+	return 0;
+}
+EXPORT_SYMBOL(reservation_object_reserve_shared);
+
+static void
+reservation_object_add_shared_inplace(struct reservation_object *obj,
+				      struct reservation_object_list *fobj,
+				      struct fence *fence)
+{
+	u32 i;
+
+	fence_get(fence);
+
+	preempt_disable();
+	write_seqcount_begin(&obj->seq);
+
+	for (i = 0; i < fobj->shared_count; ++i) {
+		struct fence *old_fence;
+
+		old_fence = rcu_dereference_protected(fobj->shared[i],
+						reservation_object_held(obj));
+
+		if (old_fence->context == fence->context) {
+			/* memory barrier is added by write_seqcount_begin */
+			RCU_INIT_POINTER(fobj->shared[i], fence);
+			write_seqcount_end(&obj->seq);
+			preempt_enable();
+
+			fence_put(old_fence);
+			return;
+		}
+	}
+
+	/*
+	 * memory barrier is added by write_seqcount_begin,
+	 * fobj->shared_count is protected by this lock too
+	 */
+	RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+	fobj->shared_count++;
+
+	write_seqcount_end(&obj->seq);
+	preempt_enable();
+}
+
+static void
+reservation_object_add_shared_replace(struct reservation_object *obj,
+				      struct reservation_object_list *old,
+				      struct reservation_object_list *fobj,
+				      struct fence *fence)
+{
+	unsigned i;
+	struct fence *old_fence = NULL;
+
+	fence_get(fence);
+
+	if (!old) {
+		RCU_INIT_POINTER(fobj->shared[0], fence);
+		fobj->shared_count = 1;
+		goto done;
+	}
+
+	/*
+	 * no need to bump fence refcounts, rcu_read access
+	 * requires the use of kref_get_unless_zero, and the
+	 * references from the old struct are carried over to
+	 * the new.
+	 */
+	fobj->shared_count = old->shared_count;
+
+	for (i = 0; i < old->shared_count; ++i) {
+		struct fence *check;
+
+		check = rcu_dereference_protected(old->shared[i],
+						reservation_object_held(obj));
+
+		if (!old_fence && check->context == fence->context) {
+			old_fence = check;
+			RCU_INIT_POINTER(fobj->shared[i], fence);
+		} else
+			RCU_INIT_POINTER(fobj->shared[i], check);
+	}
+	if (!old_fence) {
+		RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+		fobj->shared_count++;
+	}
+
+done:
+	preempt_disable();
+	write_seqcount_begin(&obj->seq);
+	/*
+	 * RCU_INIT_POINTER can be used here,
+	 * seqcount provides the necessary barriers
+	 */
+	RCU_INIT_POINTER(obj->fence, fobj);
+	write_seqcount_end(&obj->seq);
+	preempt_enable();
+
+	if (old)
+		kfree_rcu(old, rcu);
+
+	if (old_fence)
+		fence_put(old_fence);
+}
+
+/*
+ * Add a fence to a shared slot, obj->lock must be held, and
+ * reservation_object_reserve_shared_fence has been called.
+ */
+void reservation_object_add_shared_fence(struct reservation_object *obj,
+					 struct fence *fence)
+{
+	struct reservation_object_list *old, *fobj = obj->staged;
+
+	old = reservation_object_get_list(obj);
+	obj->staged = NULL;
+
+	if (!fobj) {
+		BUG_ON(old->shared_count >= old->shared_max);
+		reservation_object_add_shared_inplace(obj, old, fence);
+	} else
+		reservation_object_add_shared_replace(obj, old, fobj, fence);
+}
+EXPORT_SYMBOL(reservation_object_add_shared_fence);
+
+void reservation_object_add_excl_fence(struct reservation_object *obj,
+				       struct fence *fence)
+{
+	struct fence *old_fence = reservation_object_get_excl(obj);
+	struct reservation_object_list *old;
+	u32 i = 0;
+
+	old = reservation_object_get_list(obj);
+	if (old)
+		i = old->shared_count;
+
+	if (fence)
+		fence_get(fence);
+
+	preempt_disable();
+	write_seqcount_begin(&obj->seq);
+	/* write_seqcount_begin provides the necessary memory barrier */
+	RCU_INIT_POINTER(obj->fence_excl, fence);
+	if (old)
+		old->shared_count = 0;
+	write_seqcount_end(&obj->seq);
+	preempt_enable();
+
+	/* inplace update, no shared fences */
+	while (i--)
+		fence_put(rcu_dereference_protected(old->shared[i],
+						reservation_object_held(obj)));
+
+	if (old_fence)
+		fence_put(old_fence);
+}
+EXPORT_SYMBOL(reservation_object_add_excl_fence);
+
+int reservation_object_get_fences_rcu(struct reservation_object *obj,
+				      struct fence **pfence_excl,
+				      unsigned *pshared_count,
+				      struct fence ***pshared)
+{
+	unsigned shared_count = 0;
+	unsigned retry = 1;
+	struct fence **shared = NULL, *fence_excl = NULL;
+	int ret = 0;
+
+	while (retry) {
+		struct reservation_object_list *fobj;
+		unsigned seq;
+
+		seq = read_seqcount_begin(&obj->seq);
+
+		rcu_read_lock();
+
+		fobj = rcu_dereference(obj->fence);
+		if (fobj) {
+			struct fence **nshared;
+			size_t sz = sizeof(*shared) * fobj->shared_max;
+
+			nshared = krealloc(shared, sz,
+					   GFP_NOWAIT | __GFP_NOWARN);
+			if (!nshared) {
+				rcu_read_unlock();
+				nshared = krealloc(shared, sz, GFP_KERNEL);
+				if (nshared) {
+					shared = nshared;
+					continue;
+				}
+
+				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;
+			}
+		} else
+			retry = 1;
+
+unlock:
+		rcu_read_unlock();
+	}
+	*pshared_count = shared_count;
+	if (shared_count)
+		*pshared = shared;
+	else {
+		*pshared = NULL;
+		kfree(shared);
+	}
+	*pfence_excl = fence_excl;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
+
+long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
+					 bool wait_all, bool intr,
+					 unsigned long timeout)
+{
+	struct fence *fence;
+	unsigned seq, shared_count, i = 0;
+	long ret = timeout;
+
+retry:
+	fence = NULL;
+	shared_count = 0;
+	seq = read_seqcount_begin(&obj->seq);
+	rcu_read_lock();
+
+	if (wait_all) {
+		struct reservation_object_list *fobj = rcu_dereference(obj->fence);
+
+		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]);
+
+			if (test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags))
+				continue;
+
+			if (!fence_get_rcu(lfence))
+				goto unlock_retry;
+
+			if (fence_is_signaled(lfence)) {
+				fence_put(lfence);
+				continue;
+			}
+
+			fence = lfence;
+			break;
+		}
+	}
+
+	if (!shared_count) {
+		struct fence *fence_excl = rcu_dereference(obj->fence_excl);
+
+		if (read_seqcount_retry(&obj->seq, seq))
+			goto unlock_retry;
+
+		if (fence_excl &&
+		    !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) {
+			if (!fence_get_rcu(fence_excl))
+				goto unlock_retry;
+
+			if (fence_is_signaled(fence_excl))
+				fence_put(fence_excl);
+			else
+				fence = fence_excl;
+		}
+	}
+
+	rcu_read_unlock();
+	if (fence) {
+		ret = fence_wait_timeout(fence, intr, ret);
+		fence_put(fence);
+		if (ret > 0 && wait_all && (i + 1 < shared_count))
+			goto retry;
+	}
+	return ret;
+
+unlock_retry:
+	rcu_read_unlock();
+	goto retry;
+}
+EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu);
+
+
+static inline int
+reservation_object_test_signaled_single(struct fence *passed_fence)
+{
+	struct fence *fence, *lfence = passed_fence;
+	int ret = 1;
+
+	if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
+		int ret;
+
+		fence = fence_get_rcu(lfence);
+		if (!fence)
+			return -1;
+
+		ret = !!fence_is_signaled(fence);
+		fence_put(fence);
+	}
+	return ret;
+}
+
+bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
+					  bool test_all)
+{
+	unsigned seq, shared_count;
+	int ret = true;
+
+retry:
+	shared_count = 0;
+	seq = read_seqcount_begin(&obj->seq);
+	rcu_read_lock();
+
+	if (test_all) {
+		unsigned i;
+
+		struct reservation_object_list *fobj = rcu_dereference(obj->fence);
+
+		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]);
+
+			ret = reservation_object_test_signaled_single(fence);
+			if (ret < 0)
+				goto unlock_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 (!shared_count) {
+		struct fence *fence_excl = rcu_dereference(obj->fence_excl);
+
+		if (read_seqcount_retry(&obj->seq, seq))
+			goto unlock_retry;
+
+		if (fence_excl) {
+			ret = reservation_object_test_signaled_single(fence_excl);
+			if (ret < 0)
+				goto unlock_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-3.16-gnu/drivers/dma-buf/seqno-fence.c linux-libre-3.17-rc7-gnu/drivers/dma-buf/seqno-fence.c
--- linux-libre-3.16-gnu/drivers/dma-buf/seqno-fence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/dma-buf/seqno-fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * seqno-fence, using a dma-buf to synchronize fencing
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Copyright (C) 2012-2014 Canonical Ltd
+ * 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/seqno-fence.h>
+
+static const char *seqno_fence_get_driver_name(struct 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)
+{
+	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)
+{
+	struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+	return seqno_fence->ops->enable_signaling(fence);
+}
+
+static bool seqno_signaled(struct 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)
+{
+	struct seqno_fence *f = to_seqno_fence(fence);
+
+	dma_buf_put(f->sync_buf);
+	if (f->ops->release)
+		f->ops->release(fence);
+	else
+		fence_free(&f->base);
+}
+
+static signed long seqno_wait(struct 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 = {
+	.get_driver_name = seqno_fence_get_driver_name,
+	.get_timeline_name = seqno_fence_get_timeline_name,
+	.enable_signaling = seqno_enable_signaling,
+	.signaled = seqno_signaled,
+	.wait = seqno_wait,
+	.release = seqno_release,
+};
+EXPORT_SYMBOL(seqno_fence_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/cell_edac.c linux-libre-3.17-rc7-gnu/drivers/edac/cell_edac.c
--- linux-libre-3.16-gnu/drivers/edac/cell_edac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/cell_edac.c	2014-09-28 17:29:07.000000000 -0400
@@ -134,8 +134,7 @@ static void cell_edac_init_csrows(struct
 	int				j;
 	u32				nr_pages;
 
-	for (np = NULL;
-	     (np = of_find_node_by_name(np, "memory")) != NULL;) {
+	for_each_node_by_name(np, "memory") {
 		struct resource r;
 
 		/* We "know" that the Cell firmware only creates one entry
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/edac_mc.c linux-libre-3.17-rc7-gnu/drivers/edac/edac_mc.c
--- linux-libre-3.16-gnu/drivers/edac/edac_mc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/edac_mc.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,9 +33,6 @@
 #include <asm/edac.h>
 #include "edac_core.h"
 #include "edac_module.h"
-
-#define CREATE_TRACE_POINTS
-#define TRACE_INCLUDE_PATH ../../include/ras
 #include <ras/ras_event.h>
 
 /* lock to memory controller's control array */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-3.17-rc7-gnu/drivers/edac/edac_mc_sysfs.c
--- linux-libre-3.16-gnu/drivers/edac/edac_mc_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/edac_mc_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,7 +108,9 @@ static const char * const mem_types[] =
 	[MEM_RDDR2] = "Registered-DDR2",
 	[MEM_XDR] = "XDR",
 	[MEM_DDR3] = "Unbuffered-DDR3",
-	[MEM_RDDR3] = "Registered-DDR3"
+	[MEM_RDDR3] = "Registered-DDR3",
+	[MEM_DDR4] = "Unbuffered-DDR4",
+	[MEM_RDDR4] = "Registered-DDR4"
 };
 
 static const char * const dev_types[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/edac_module.c linux-libre-3.17-rc7-gnu/drivers/edac/edac_module.c
--- linux-libre-3.16-gnu/drivers/edac/edac_module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/edac_module.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@ static int edac_set_debug_level(const ch
 	if (ret)
 		return ret;
 
-	if (val < 0 || val > 4)
+	if (val > 4)
 		return -EINVAL;
 
 	return param_set_int(buf, kp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/ie31200_edac.c linux-libre-3.17-rc7-gnu/drivers/edac/ie31200_edac.c
--- linux-libre-3.16-gnu/drivers/edac/ie31200_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/edac/ie31200_edac.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,536 @@
+/*
+ * Intel E3-1200
+ * Copyright (C) 2014 Jason Baron <jbaron@akamai.com>
+ *
+ * Support for the E3-1200 processor family. Heavily based on previous
+ * Intel EDAC drivers.
+ *
+ * Since the DRAM controller is on the cpu chip, we can use its PCI device
+ * id to identify these processors.
+ *
+ * PCI DRAM controller device ids (Taken from The PCI ID Repository - http://pci-ids.ucw.cz/)
+ *
+ * 0108: Xeon E3-1200 Processor Family DRAM Controller
+ * 010c: Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller
+ * 0150: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
+ * 0158: Xeon E3-1200 v2/Ivy Bridge DRAM Controller
+ * 015c: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
+ * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
+ * 0c08: Xeon E3-1200 v3 Processor DRAM Controller
+ *
+ * Based on Intel specification:
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
+ * http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
+ *
+ * According to the above datasheet (p.16):
+ * "
+ * 6. Software must not access B0/D0/F0 32-bit memory-mapped registers with
+ * requests that cross a DW boundary.
+ * "
+ *
+ * Thus, we make use of the explicit: lo_hi_readq(), which breaks the readq into
+ * 2 readl() calls. This restriction may be lifted in subsequent chip releases,
+ * but lo_hi_readq() ensures that we are safe across all e3-1200 processors.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/edac.h>
+
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include "edac_core.h"
+
+#define IE31200_REVISION "1.0"
+#define EDAC_MOD_STR "ie31200_edac"
+
+#define ie31200_printk(level, fmt, arg...) \
+	edac_printk(level, "ie31200", fmt, ##arg)
+
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_1 0x0108
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_2 0x010c
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_3 0x0150
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_4 0x0158
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_5 0x015c
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08
+
+#define IE31200_DIMMS			4
+#define IE31200_RANKS			8
+#define IE31200_RANKS_PER_CHANNEL	4
+#define IE31200_DIMMS_PER_CHANNEL	2
+#define IE31200_CHANNELS		2
+
+/* Intel IE31200 register addresses - device 0 function 0 - DRAM Controller */
+#define IE31200_MCHBAR_LOW		0x48
+#define IE31200_MCHBAR_HIGH		0x4c
+#define IE31200_MCHBAR_MASK		GENMASK_ULL(38, 15)
+#define IE31200_MMR_WINDOW_SIZE		BIT(15)
+
+/*
+ * Error Status Register (16b)
+ *
+ * 15    reserved
+ * 14    Isochronous TBWRR Run Behind FIFO Full
+ *       (ITCV)
+ * 13    Isochronous TBWRR Run Behind FIFO Put
+ *       (ITSTV)
+ * 12    reserved
+ * 11    MCH Thermal Sensor Event
+ *       for SMI/SCI/SERR (GTSE)
+ * 10    reserved
+ *  9    LOCK to non-DRAM Memory Flag (LCKF)
+ *  8    reserved
+ *  7    DRAM Throttle Flag (DTF)
+ *  6:2  reserved
+ *  1    Multi-bit DRAM ECC Error Flag (DMERR)
+ *  0    Single-bit DRAM ECC Error Flag (DSERR)
+ */
+#define IE31200_ERRSTS			0xc8
+#define IE31200_ERRSTS_UE		BIT(1)
+#define IE31200_ERRSTS_CE		BIT(0)
+#define IE31200_ERRSTS_BITS		(IE31200_ERRSTS_UE | IE31200_ERRSTS_CE)
+
+/*
+ * Channel 0 ECC Error Log (64b)
+ *
+ * 63:48 Error Column Address (ERRCOL)
+ * 47:32 Error Row Address (ERRROW)
+ * 31:29 Error Bank Address (ERRBANK)
+ * 28:27 Error Rank Address (ERRRANK)
+ * 26:24 reserved
+ * 23:16 Error Syndrome (ERRSYND)
+ * 15: 2 reserved
+ *    1  Multiple Bit Error Status (MERRSTS)
+ *    0  Correctable Error Status (CERRSTS)
+ */
+#define IE31200_C0ECCERRLOG			0x40c8
+#define IE31200_C1ECCERRLOG			0x44c8
+#define IE31200_ECCERRLOG_CE			BIT(0)
+#define IE31200_ECCERRLOG_UE			BIT(1)
+#define IE31200_ECCERRLOG_RANK_BITS		GENMASK_ULL(28, 27)
+#define IE31200_ECCERRLOG_RANK_SHIFT		27
+#define IE31200_ECCERRLOG_SYNDROME_BITS		GENMASK_ULL(23, 16)
+#define IE31200_ECCERRLOG_SYNDROME_SHIFT	16
+
+#define IE31200_ECCERRLOG_SYNDROME(log)		   \
+	((log & IE31200_ECCERRLOG_SYNDROME_BITS) >> \
+	 IE31200_ECCERRLOG_SYNDROME_SHIFT)
+
+#define IE31200_CAPID0			0xe4
+#define IE31200_CAPID0_PDCD		BIT(4)
+#define IE31200_CAPID0_DDPCD		BIT(6)
+#define IE31200_CAPID0_ECC		BIT(1)
+
+#define IE31200_MAD_DIMM_0_OFFSET	0x5004
+#define IE31200_MAD_DIMM_SIZE		GENMASK_ULL(7, 0)
+#define IE31200_MAD_DIMM_A_RANK		BIT(17)
+#define IE31200_MAD_DIMM_A_WIDTH	BIT(19)
+
+#define IE31200_PAGES(n)		(n << (28 - PAGE_SHIFT))
+
+static int nr_channels;
+
+struct ie31200_priv {
+	void __iomem *window;
+};
+
+enum ie31200_chips {
+	IE31200 = 0,
+};
+
+struct ie31200_dev_info {
+	const char *ctl_name;
+};
+
+struct ie31200_error_info {
+	u16 errsts;
+	u16 errsts2;
+	u64 eccerrlog[IE31200_CHANNELS];
+};
+
+static const struct ie31200_dev_info ie31200_devs[] = {
+	[IE31200] = {
+		.ctl_name = "IE31200"
+	},
+};
+
+struct dimm_data {
+	u8 size; /* in 256MB multiples */
+	u8 dual_rank : 1,
+	   x16_width : 1; /* 0 means x8 width */
+};
+
+static int how_many_channels(struct pci_dev *pdev)
+{
+	int n_channels;
+	unsigned char capid0_2b; /* 2nd byte of CAPID0 */
+
+	pci_read_config_byte(pdev, IE31200_CAPID0 + 1, &capid0_2b);
+
+	/* check PDCD: Dual Channel Disable */
+	if (capid0_2b & IE31200_CAPID0_PDCD) {
+		edac_dbg(0, "In single channel mode\n");
+		n_channels = 1;
+	} else {
+		edac_dbg(0, "In dual channel mode\n");
+		n_channels = 2;
+	}
+
+	/* check DDPCD - check if both channels are filled */
+	if (capid0_2b & IE31200_CAPID0_DDPCD)
+		edac_dbg(0, "2 DIMMS per channel disabled\n");
+	else
+		edac_dbg(0, "2 DIMMS per channel enabled\n");
+
+	return n_channels;
+}
+
+static bool ecc_capable(struct pci_dev *pdev)
+{
+	unsigned char capid0_4b; /* 4th byte of CAPID0 */
+
+	pci_read_config_byte(pdev, IE31200_CAPID0 + 3, &capid0_4b);
+	if (capid0_4b & IE31200_CAPID0_ECC)
+		return false;
+	return true;
+}
+
+static int eccerrlog_row(int channel, u64 log)
+{
+	int rank = ((log & IE31200_ECCERRLOG_RANK_BITS) >>
+		IE31200_ECCERRLOG_RANK_SHIFT);
+	return rank | (channel * IE31200_RANKS_PER_CHANNEL);
+}
+
+static void ie31200_clear_error_info(struct mem_ctl_info *mci)
+{
+	/*
+	 * Clear any error bits.
+	 * (Yes, we really clear bits by writing 1 to them.)
+	 */
+	pci_write_bits16(to_pci_dev(mci->pdev), IE31200_ERRSTS,
+			 IE31200_ERRSTS_BITS, IE31200_ERRSTS_BITS);
+}
+
+static void ie31200_get_and_clear_error_info(struct mem_ctl_info *mci,
+					     struct ie31200_error_info *info)
+{
+	struct pci_dev *pdev;
+	struct ie31200_priv *priv = mci->pvt_info;
+	void __iomem *window = priv->window;
+
+	pdev = to_pci_dev(mci->pdev);
+
+	/*
+	 * This is a mess because there is no atomic way to read all the
+	 * registers at once and the registers can transition from CE being
+	 * overwritten by UE.
+	 */
+	pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts);
+	if (!(info->errsts & IE31200_ERRSTS_BITS))
+		return;
+
+	info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+	if (nr_channels == 2)
+		info->eccerrlog[1] = lo_hi_readq(window + IE31200_C1ECCERRLOG);
+
+	pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts2);
+
+	/*
+	 * If the error is the same for both reads then the first set
+	 * of reads is valid.  If there is a change then there is a CE
+	 * with no info and the second set of reads is valid and
+	 * should be UE info.
+	 */
+	if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) {
+		info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+		if (nr_channels == 2)
+			info->eccerrlog[1] =
+				lo_hi_readq(window + IE31200_C1ECCERRLOG);
+	}
+
+	ie31200_clear_error_info(mci);
+}
+
+static void ie31200_process_error_info(struct mem_ctl_info *mci,
+				       struct ie31200_error_info *info)
+{
+	int channel;
+	u64 log;
+
+	if (!(info->errsts & IE31200_ERRSTS_BITS))
+		return;
+
+	if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) {
+		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
+				     -1, -1, -1, "UE overwrote CE", "");
+		info->errsts = info->errsts2;
+	}
+
+	for (channel = 0; channel < nr_channels; channel++) {
+		log = info->eccerrlog[channel];
+		if (log & IE31200_ECCERRLOG_UE) {
+			edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
+					     0, 0, 0,
+					     eccerrlog_row(channel, log),
+					     channel, -1,
+					     "ie31200 UE", "");
+		} else if (log & IE31200_ECCERRLOG_CE) {
+			edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
+					     0, 0,
+					     IE31200_ECCERRLOG_SYNDROME(log),
+					     eccerrlog_row(channel, log),
+					     channel, -1,
+					     "ie31200 CE", "");
+		}
+	}
+}
+
+static void ie31200_check(struct mem_ctl_info *mci)
+{
+	struct ie31200_error_info info;
+
+	edac_dbg(1, "MC%d\n", mci->mc_idx);
+	ie31200_get_and_clear_error_info(mci, &info);
+	ie31200_process_error_info(mci, &info);
+}
+
+static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev)
+{
+	union {
+		u64 mchbar;
+		struct {
+			u32 mchbar_low;
+			u32 mchbar_high;
+		};
+	} u;
+	void __iomem *window;
+
+	pci_read_config_dword(pdev, IE31200_MCHBAR_LOW, &u.mchbar_low);
+	pci_read_config_dword(pdev, IE31200_MCHBAR_HIGH, &u.mchbar_high);
+	u.mchbar &= IE31200_MCHBAR_MASK;
+
+	if (u.mchbar != (resource_size_t)u.mchbar) {
+		ie31200_printk(KERN_ERR, "mmio space beyond accessible range (0x%llx)\n",
+			       (unsigned long long)u.mchbar);
+		return NULL;
+	}
+
+	window = ioremap_nocache(u.mchbar, IE31200_MMR_WINDOW_SIZE);
+	if (!window)
+		ie31200_printk(KERN_ERR, "Cannot map mmio space at 0x%llx\n",
+			       (unsigned long long)u.mchbar);
+
+	return window;
+}
+
+static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
+{
+	int i, j, ret;
+	struct mem_ctl_info *mci = NULL;
+	struct edac_mc_layer layers[2];
+	struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
+	void __iomem *window;
+	struct ie31200_priv *priv;
+	u32 addr_decode;
+
+	edac_dbg(0, "MC:\n");
+
+	if (!ecc_capable(pdev)) {
+		ie31200_printk(KERN_INFO, "No ECC support\n");
+		return -ENODEV;
+	}
+
+	nr_channels = how_many_channels(pdev);
+	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
+	layers[0].size = IE31200_DIMMS;
+	layers[0].is_virt_csrow = true;
+	layers[1].type = EDAC_MC_LAYER_CHANNEL;
+	layers[1].size = nr_channels;
+	layers[1].is_virt_csrow = false;
+	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
+			    sizeof(struct ie31200_priv));
+	if (!mci)
+		return -ENOMEM;
+
+	window = ie31200_map_mchbar(pdev);
+	if (!window) {
+		ret = -ENODEV;
+		goto fail_free;
+	}
+
+	edac_dbg(3, "MC: init mci\n");
+	mci->pdev = &pdev->dev;
+	mci->mtype_cap = MEM_FLAG_DDR3;
+	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+	mci->edac_cap = EDAC_FLAG_SECDED;
+	mci->mod_name = EDAC_MOD_STR;
+	mci->mod_ver = IE31200_REVISION;
+	mci->ctl_name = ie31200_devs[dev_idx].ctl_name;
+	mci->dev_name = pci_name(pdev);
+	mci->edac_check = ie31200_check;
+	mci->ctl_page_to_phys = NULL;
+	priv = mci->pvt_info;
+	priv->window = window;
+
+	/* populate DIMM info */
+	for (i = 0; i < IE31200_CHANNELS; i++) {
+		addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET +
+					(i * 4));
+		edac_dbg(0, "addr_decode: 0x%x\n", addr_decode);
+		for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) {
+			dimm_info[i][j].size = (addr_decode >> (j * 8)) &
+						IE31200_MAD_DIMM_SIZE;
+			dimm_info[i][j].dual_rank = (addr_decode &
+				(IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0;
+			dimm_info[i][j].x16_width = (addr_decode &
+				(IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0;
+			edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
+				 dimm_info[i][j].size,
+				 dimm_info[i][j].dual_rank,
+				 dimm_info[i][j].x16_width);
+		}
+	}
+
+	/*
+	 * The dram rank boundary (DRB) reg values are boundary addresses
+	 * for each DRAM rank with a granularity of 64MB.  DRB regs are
+	 * cumulative; the last one will contain the total memory
+	 * contained in all ranks.
+	 */
+	for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) {
+		for (j = 0; j < IE31200_CHANNELS; j++) {
+			struct dimm_info *dimm;
+			unsigned long nr_pages;
+
+			nr_pages = IE31200_PAGES(dimm_info[j][i].size);
+			if (nr_pages == 0)
+				continue;
+
+			if (dimm_info[j][i].dual_rank) {
+				nr_pages = nr_pages / 2;
+				dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
+						     mci->n_layers, (i * 2) + 1,
+						     j, 0);
+				dimm->nr_pages = nr_pages;
+				edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
+				dimm->grain = 8; /* just a guess */
+				dimm->mtype = MEM_DDR3;
+				dimm->dtype = DEV_UNKNOWN;
+				dimm->edac_mode = EDAC_UNKNOWN;
+			}
+			dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
+					     mci->n_layers, i * 2, j, 0);
+			dimm->nr_pages = nr_pages;
+			edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
+			dimm->grain = 8; /* same guess */
+			dimm->mtype = MEM_DDR3;
+			dimm->dtype = DEV_UNKNOWN;
+			dimm->edac_mode = EDAC_UNKNOWN;
+		}
+	}
+
+	ie31200_clear_error_info(mci);
+
+	if (edac_mc_add_mc(mci)) {
+		edac_dbg(3, "MC: failed edac_mc_add_mc()\n");
+		ret = -ENODEV;
+		goto fail_unmap;
+	}
+
+	/* get this far and it's successful */
+	edac_dbg(3, "MC: success\n");
+	return 0;
+
+fail_unmap:
+	iounmap(window);
+
+fail_free:
+	edac_mc_free(mci);
+
+	return ret;
+}
+
+static int ie31200_init_one(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
+{
+	edac_dbg(0, "MC:\n");
+
+	if (pci_enable_device(pdev) < 0)
+		return -EIO;
+
+	return ie31200_probe1(pdev, ent->driver_data);
+}
+
+static void ie31200_remove_one(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct ie31200_priv *priv;
+
+	edac_dbg(0, "\n");
+	mci = edac_mc_del_mc(&pdev->dev);
+	if (!mci)
+		return;
+	priv = mci->pvt_info;
+	iounmap(priv->window);
+	edac_mc_free(mci);
+}
+
+static const struct pci_device_id ie31200_pci_tbl[] = {
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_4), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_5), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_6), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
+		0,
+	}            /* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, ie31200_pci_tbl);
+
+static struct pci_driver ie31200_driver = {
+	.name = EDAC_MOD_STR,
+	.probe = ie31200_init_one,
+	.remove = ie31200_remove_one,
+	.id_table = ie31200_pci_tbl,
+};
+
+static int __init ie31200_init(void)
+{
+	edac_dbg(3, "MC:\n");
+	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
+	opstate_init();
+
+	return pci_register_driver(&ie31200_driver);
+}
+
+static void __exit ie31200_exit(void)
+{
+	edac_dbg(3, "MC:\n");
+	pci_unregister_driver(&ie31200_driver);
+}
+
+module_init(ie31200_init);
+module_exit(ie31200_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
+MODULE_DESCRIPTION("MC support for Intel Processor E31200 memory hub controllers");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/Kconfig linux-libre-3.17-rc7-gnu/drivers/edac/Kconfig
--- linux-libre-3.16-gnu/drivers/edac/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -72,6 +72,7 @@ config EDAC_MCE_INJ
 
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+	select RAS
 	help
 	  Some systems are able to detect and correct errors in main
 	  memory.  EDAC can report statistics on memory error
@@ -186,6 +187,13 @@ config EDAC_I3200
 	  Support for error detection and correction on the Intel
 	  3200 and 3210 server chipsets.
 
+config EDAC_IE31200
+	tristate "Intel e312xx"
+	depends on EDAC_MM_EDAC && PCI && X86
+	help
+	  Support for error detection and correction on the Intel
+	  E3-1200 based DRAM controllers.
+
 config EDAC_X38
 	tristate "Intel X38"
 	depends on EDAC_MM_EDAC && PCI && X86
@@ -245,12 +253,12 @@ config EDAC_I7300
 	  Clarksboro MCH (Intel 7300 chipset).
 
 config EDAC_SBRIDGE
-	tristate "Intel Sandy-Bridge Integrated MC"
+	tristate "Intel Sandy-Bridge/Ivy-Bridge/Haswell Integrated MC"
 	depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
 	depends on PCI_MMCONFIG
 	help
 	  Support for error detection and correction the Intel
-	  Sandy Bridge Integrated Memory Controller.
+	  Sandy Bridge, Ivy Bridge and Haswell Integrated Memory Controllers.
 
 config EDAC_MPC85XX
 	tristate "Freescale MPC83xx / MPC85xx"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/Makefile linux-libre-3.17-rc7-gnu/drivers/edac/Makefile
--- linux-libre-3.16-gnu/drivers/edac/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,7 @@ obj-$(CONFIG_EDAC_I82875P)		+= i82875p_e
 obj-$(CONFIG_EDAC_I82975X)		+= i82975x_edac.o
 obj-$(CONFIG_EDAC_I3000)		+= i3000_edac.o
 obj-$(CONFIG_EDAC_I3200)		+= i3200_edac.o
+obj-$(CONFIG_EDAC_IE31200)		+= ie31200_edac.o
 obj-$(CONFIG_EDAC_X38)			+= x38_edac.o
 obj-$(CONFIG_EDAC_I82860)		+= i82860_edac.o
 obj-$(CONFIG_EDAC_R82600)		+= r82600_edac.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/mce_amd.c linux-libre-3.17-rc7-gnu/drivers/edac/mce_amd.c
--- linux-libre-3.16-gnu/drivers/edac/mce_amd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/mce_amd.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,8 @@ static const char * const f15h_mc1_mce_d
 	"uop queue",
 	"insn buffer",
 	"predecode buffer",
-	"fetch address FIFO"
+	"fetch address FIFO",
+	"dispatch uop queue"
 };
 
 static const char * const f15h_mc2_mce_desc[] = {
@@ -267,6 +268,12 @@ static bool f15h_mc0_mce(u16 ec, u8 xec)
 			pr_cont("System Read Data Error.\n");
 		else
 			pr_cont(" Internal error condition type %d.\n", xec);
+	} else if (INT_ERROR(ec)) {
+		if (xec <= 0x1f)
+			pr_cont("Hardware Assert.\n");
+		else
+			ret = false;
+
 	} else
 		ret = false;
 
@@ -373,7 +380,7 @@ static bool f15h_mc1_mce(u16 ec, u8 xec)
 		pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
 		break;
 
-	case 0x11 ... 0x14:
+	case 0x11 ... 0x15:
 		pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
 		break;
 
@@ -397,10 +404,20 @@ static void decode_mc1_mce(struct mce *m
 		bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
 
 		pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
+	} else if (INT_ERROR(ec)) {
+		if (xec <= 0x3f)
+			pr_cont("Hardware Assert.\n");
+		else
+			goto wrong_mc1_mce;
 	} else if (fam_ops->mc1_mce(ec, xec))
 		;
 	else
-		pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
+		goto wrong_mc1_mce;
+
+	return;
+
+wrong_mc1_mce:
+	pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
 }
 
 static bool k8_mc2_mce(u16 ec, u8 xec)
@@ -468,6 +485,11 @@ static bool f15h_mc2_mce(u16 ec, u8 xec)
 		default:
 			ret = false;
 		}
+	} else if (INT_ERROR(ec)) {
+		if (xec <= 0x3f)
+			pr_cont("Hardware Assert.\n");
+		else
+			ret = false;
 	}
 
 	return ret;
@@ -615,6 +637,7 @@ static void decode_mc4_mce(struct mce *m
 static void decode_mc5_mce(struct mce *m)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
+	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
 	if (c->x86 == 0xf || c->x86 == 0x11)
@@ -622,6 +645,14 @@ static void decode_mc5_mce(struct mce *m
 
 	pr_emerg(HW_ERR "MC5 Error: ");
 
+	if (INT_ERROR(ec)) {
+		if (xec <= 0x1f) {
+			pr_cont("Hardware Assert.\n");
+			return;
+		} else
+			goto wrong_mc5_mce;
+	}
+
 	if (xec == 0x0 || xec == 0xc)
 		pr_cont("%s.\n", mc5_mce_desc[xec]);
 	else if (xec <= 0xd)
@@ -642,6 +673,10 @@ static void decode_mc6_mce(struct mce *m
 	pr_emerg(HW_ERR "MC6 Error: ");
 
 	switch (xec) {
+	case 0x0:
+		pr_cont("Hardware Assertion");
+		break;
+
 	case 0x1:
 		pr_cont("Free List");
 		break;
@@ -857,7 +892,8 @@ static int __init mce_amd_init(void)
 		break;
 
 	case 0x15:
-		xec_mask = 0x1f;
+		xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f;
+
 		fam_ops->mc0_mce = f15h_mc0_mce;
 		fam_ops->mc1_mce = f15h_mc1_mce;
 		fam_ops->mc2_mce = f15h_mc2_mce;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/sb_edac.c linux-libre-3.17-rc7-gnu/drivers/edac/sb_edac.c
--- linux-libre-3.16-gnu/drivers/edac/sb_edac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/sb_edac.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,7 @@ static const u32 ibridge_dram_rule[] = {
 #define DRAM_ATTR(reg)		GET_BITFIELD(reg, 2,  3)
 #define INTERLEAVE_MODE(reg)	GET_BITFIELD(reg, 1,  1)
 #define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
+#define A7MODE(reg)		GET_BITFIELD(reg, 26, 26)
 
 static char *get_dram_attr(u32 reg)
 {
@@ -164,6 +165,8 @@ static inline int sad_pkg(const struct i
 
 #define TOLM		0x80
 #define	TOHM		0x84
+#define HASWELL_TOHM_0	0xd4
+#define HASWELL_TOHM_1	0xd8
 
 #define GET_TOLM(reg)		((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ffffff)
 #define GET_TOHM(reg)		((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
@@ -176,8 +179,6 @@ static inline int sad_pkg(const struct i
 
 #define SAD_CONTROL	0xf4
 
-#define NODE_ID(reg)		GET_BITFIELD(reg, 0, 2)
-
 /* Device 14 function 0 */
 
 static const u32 tad_dram_rule[] = {
@@ -235,7 +236,6 @@ static const u32 rir_way_limit[] = {
 
 #define IS_RIR_VALID(reg)	GET_BITFIELD(reg, 31, 31)
 #define RIR_WAY(reg)		GET_BITFIELD(reg, 28, 29)
-#define RIR_LIMIT(reg)		((GET_BITFIELD(reg,  1, 10) << 29)| 0x1fffffff)
 
 #define MAX_RIR_WAY	8
 
@@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = {
 
 #define IB_RANK_CFG_A		0x0320
 
-#define IS_RDIMM_ENABLED(reg)		GET_BITFIELD(reg, 11, 11)
-
 /*
  * sbridge structs
  */
@@ -291,6 +289,7 @@ static const u32 correrrthrsld[] = {
 enum type {
 	SANDY_BRIDGE,
 	IVY_BRIDGE,
+	HASWELL,
 };
 
 struct sbridge_pvt;
@@ -300,11 +299,15 @@ struct sbridge_info {
 	u32		rankcfgr;
 	u64		(*get_tolm)(struct sbridge_pvt *pvt);
 	u64		(*get_tohm)(struct sbridge_pvt *pvt);
+	u64		(*rir_limit)(u32 reg);
 	const u32	*dram_rule;
 	const u32	*interleave_list;
 	const struct interleave_pkg *interleave_pkg;
 	u8		max_sad;
 	u8		max_interleave;
+	u8		(*get_node_id)(struct sbridge_pvt *pvt);
+	enum mem_type	(*get_memory_type)(struct sbridge_pvt *pvt);
+	struct pci_dev	*pci_vtd;
 };
 
 struct sbridge_channel {
@@ -313,9 +316,7 @@ struct sbridge_channel {
 };
 
 struct pci_id_descr {
-	int			dev;
-	int			func;
-	int 			dev_id;
+	int			dev_id;
 	int			optional;
 };
 
@@ -338,6 +339,7 @@ struct sbridge_pvt {
 	struct pci_dev		*pci_sad0, *pci_sad1;
 	struct pci_dev		*pci_ha0, *pci_ha1;
 	struct pci_dev		*pci_br0, *pci_br1;
+	struct pci_dev		*pci_ha1_ta;
 	struct pci_dev		*pci_tad[NUM_CHANNELS];
 
 	struct sbridge_dev	*sbridge_dev;
@@ -362,31 +364,29 @@ struct sbridge_pvt {
 	u64			tolm, tohm;
 };
 
-#define PCI_DESCR(device, function, device_id, opt)	\
-	.dev = (device),				\
-	.func = (function),				\
-	.dev_id = (device_id),				\
+#define PCI_DESCR(device_id, opt)	\
+	.dev_id = (device_id),		\
 	.optional = opt
 
 static const struct pci_id_descr pci_dev_descr_sbridge[] = {
 		/* Processor Home Agent */
-	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)	},
 
 		/* Memory controller */
-	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)	},
-	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)	},
-	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)	},
-	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)	},
-	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)	},
-	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)	},
-	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)	},
 
 		/* System Address Decoder */
-	{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)		},
-	{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)	},
 
 		/* Broadcast Registers */
-	{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
 };
 
 #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -423,34 +423,34 @@ static const struct pci_id_table pci_dev
 
 static const struct pci_id_descr pci_dev_descr_ibridge[] = {
 		/* Processor Home Agent */
-	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)		},
 
 		/* Memory controller */
-	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)	},
-	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)	},
-	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)	},
-	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)	},
-	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)	},
-	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)	},
 
 		/* System Address Decoder */
-	{ PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)			},
 
 		/* Broadcast Registers */
-	{ PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)		},
-	{ PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)			},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)			},
 
 		/* Optional, mode 2HA */
-	{ PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)		},
 #if 0
-	{ PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)	},
-	{ PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)	},
 #endif
-	{ PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)	},
-	{ PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)	},
 
-	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
-	{ PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1)	},
 };
 
 static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
@@ -458,12 +458,80 @@ static const struct pci_id_table pci_dev
 	{0,}			/* 0 terminated list. */
 };
 
+/* Haswell support */
+/* EN processor:
+ *	- 1 IMC
+ *	- 3 DDR3 channels, 2 DPC per channel
+ * EP processor:
+ *	- 1 or 2 IMC
+ *	- 4 DDR4 channels, 3 DPC per channel
+ * EP 4S processor:
+ *	- 2 IMC
+ *	- 4 DDR4 channels, 3 DPC per channel
+ * EX processor:
+ *	- 2 IMC
+ *	- each IMC interfaces with a SMI 2 channel
+ *	- each SMI channel interfaces with a scalable memory buffer
+ *	- each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
+ */
+#define HASWELL_DDRCRCLKCONTROLS 0xa10
+#define HASWELL_HASYSDEFEATURE2 0x84
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0	0x2fa0
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1	0x2f60
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA	0x2fa8
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA	0x2f68
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd
+static const struct pci_id_descr pci_dev_descr_haswell[] = {
+	/* first item must be the HA */
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0)		},
+
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0)	},
+
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1)		},
+
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1)	},
+
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1)		},
+
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1)		},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1)	},
+	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1)	},
+};
+
+static const struct pci_id_table pci_dev_descr_haswell_table[] = {
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell),
+	{0,}			/* 0 terminated list. */
+};
+
 /*
  *	pci_device_id	table for which devices we are looking for
  */
 static const struct pci_device_id sbridge_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
 	{0,}			/* 0 terminated list. */
 };
 
@@ -472,13 +540,17 @@ static const struct pci_device_id sbridg
 			Ancillary status routines
  ****************************************************************************/
 
-static inline int numrank(u32 mtr)
+static inline int numrank(enum type type, u32 mtr)
 {
 	int ranks = (1 << RANK_CNT_BITS(mtr));
+	int max = 4;
 
-	if (ranks > 4) {
-		edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n",
-			 ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+	if (type == HASWELL)
+		max = 8;
+
+	if (ranks > max) {
+		edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)\n",
+			 ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr);
 		return -EINVAL;
 	}
 
@@ -588,10 +660,107 @@ static u64 ibridge_get_tohm(struct sbrid
 	return GET_TOHM(reg);
 }
 
+static u64 rir_limit(u32 reg)
+{
+	return ((u64)GET_BITFIELD(reg,  1, 10) << 29) | 0x1fffffff;
+}
+
+static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
+{
+	u32 reg;
+	enum mem_type mtype;
+
+	if (pvt->pci_ddrio) {
+		pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
+				      &reg);
+		if (GET_BITFIELD(reg, 11, 11))
+			/* FIXME: Can also be LRDIMM */
+			mtype = MEM_RDDR3;
+		else
+			mtype = MEM_DDR3;
+	} else
+		mtype = MEM_UNKNOWN;
+
+	return mtype;
+}
+
+static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt)
+{
+	u32 reg;
+	bool registered = false;
+	enum mem_type mtype = MEM_UNKNOWN;
+
+	if (!pvt->pci_ddrio)
+		goto out;
+
+	pci_read_config_dword(pvt->pci_ddrio,
+			      HASWELL_DDRCRCLKCONTROLS, &reg);
+	/* Is_Rdimm */
+	if (GET_BITFIELD(reg, 16, 16))
+		registered = true;
+
+	pci_read_config_dword(pvt->pci_ta, MCMTR, &reg);
+	if (GET_BITFIELD(reg, 14, 14)) {
+		if (registered)
+			mtype = MEM_RDDR4;
+		else
+			mtype = MEM_DDR4;
+	} else {
+		if (registered)
+			mtype = MEM_RDDR3;
+		else
+			mtype = MEM_DDR3;
+	}
+
+out:
+	return mtype;
+}
+
+static u8 get_node_id(struct sbridge_pvt *pvt)
+{
+	u32 reg;
+	pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
+	return GET_BITFIELD(reg, 0, 2);
+}
+
+static u8 haswell_get_node_id(struct sbridge_pvt *pvt)
+{
+	u32 reg;
+
+	pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, &reg);
+	return GET_BITFIELD(reg, 0, 3);
+}
+
+static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
+{
+	u32 reg;
+
+	pci_read_config_dword(pvt->info.pci_vtd, TOLM, &reg);
+	return (GET_BITFIELD(reg, 26, 31) << 26) | 0x1ffffff;
+}
+
+static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
+{
+	u64 rc;
+	u32 reg;
+
+	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, &reg);
+	rc = GET_BITFIELD(reg, 26, 31);
+	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg);
+	rc = ((reg << 6) | rc) << 26;
+
+	return rc | 0x1ffffff;
+}
+
+static u64 haswell_rir_limit(u32 reg)
+{
+	return (((u64)GET_BITFIELD(reg,  1, 11) + 1) << 29) - 1;
+}
+
 static inline u8 sad_pkg_socket(u8 pkg)
 {
 	/* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
-	return (pkg >> 3) | (pkg & 0x3);
+	return ((pkg >> 3) << 2) | (pkg & 0x3);
 }
 
 static inline u8 sad_pkg_ha(u8 pkg)
@@ -602,44 +771,43 @@ static inline u8 sad_pkg_ha(u8 pkg)
 /****************************************************************************
 			Memory check routines
  ****************************************************************************/
-static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
-					  unsigned func)
+static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
 {
-	struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
-	int i;
-
-	if (!sbridge_dev)
-		return NULL;
-
-	for (i = 0; i < sbridge_dev->n_devs; i++) {
-		if (!sbridge_dev->pdev[i])
-			continue;
+	struct pci_dev *pdev = NULL;
 
-		if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
-		    PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
-			edac_dbg(1, "Associated %02x.%02x.%d with %p\n",
-				 bus, slot, func, sbridge_dev->pdev[i]);
-			return sbridge_dev->pdev[i];
-		}
-	}
+	do {
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
+		if (pdev && pdev->bus->number == bus)
+			break;
+	} while (pdev);
 
-	return NULL;
+	return pdev;
 }
 
 /**
  * check_if_ecc_is_active() - Checks if ECC is active
- * bus:		Device bus
+ * @bus:	Device bus
+ * @type:	Memory controller type
+ * returns: 0 in case ECC is active, -ENODEV if it can't be determined or
+ *	    disabled
  */
-static int check_if_ecc_is_active(const u8 bus)
+static int check_if_ecc_is_active(const u8 bus, enum type type)
 {
 	struct pci_dev *pdev = NULL;
-	u32 mcmtr;
+	u32 mcmtr, id;
 
-	pdev = get_pdev_slot_func(bus, 15, 0);
+	if (type == IVY_BRIDGE)
+		id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
+	else if (type == HASWELL)
+		id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
+	else
+		id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
+
+	pdev = get_pdev_same_bus(bus, id);
 	if (!pdev) {
 		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
-					"%2x.%02d.%d!!!\n",
-					bus, 15, 0);
+					"%04x:%04x! on bus %02d\n",
+					PCI_VENDOR_ID_INTEL, id, bus);
 		return -ENODEV;
 	}
 
@@ -661,11 +829,14 @@ static int get_dimm_config(struct mem_ct
 	enum edac_type mode;
 	enum mem_type mtype;
 
-	pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
+	if (pvt->info.type == HASWELL)
+		pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
+	else
+		pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
+
 	pvt->sbridge_dev->source_id = SOURCE_ID(reg);
 
-	pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
-	pvt->sbridge_dev->node_id = NODE_ID(reg);
+	pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
 	edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
 		 pvt->sbridge_dev->mc,
 		 pvt->sbridge_dev->node_id,
@@ -698,24 +869,18 @@ static int get_dimm_config(struct mem_ct
 		pvt->is_close_pg = false;
 	}
 
-	if (pvt->pci_ddrio) {
-		pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
-				      &reg);
-		if (IS_RDIMM_ENABLED(reg)) {
-			/* FIXME: Can also be LRDIMM */
-			edac_dbg(0, "Memory is registered\n");
-			mtype = MEM_RDDR3;
-		} else {
-			edac_dbg(0, "Memory is unregistered\n");
-			mtype = MEM_DDR3;
-		}
-	} else {
+	mtype = pvt->info.get_memory_type(pvt);
+	if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
+		edac_dbg(0, "Memory is registered\n");
+	else if (mtype == MEM_UNKNOWN)
 		edac_dbg(0, "Cannot determine memory type\n");
-		mtype = MEM_UNKNOWN;
-	}
+	else
+		edac_dbg(0, "Memory is unregistered\n");
 
-	/* On all supported DDR3 DIMM types, there are 8 banks available */
-	banks = 8;
+	if (mtype == MEM_DDR4 || MEM_RDDR4)
+		banks = 16;
+	else
+		banks = 8;
 
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		u32 mtr;
@@ -729,11 +894,10 @@ static int get_dimm_config(struct mem_ct
 			if (IS_DIMM_PRESENT(mtr)) {
 				pvt->channel[i].dimms++;
 
-				ranks = numrank(mtr);
+				ranks = numrank(pvt->info.type, mtr);
 				rows = numrow(mtr);
 				cols = numcol(mtr);
 
-				/* DDR3 has 8 I/O banks */
 				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
 				npages = MiB_TO_PAGES(size);
 
@@ -744,7 +908,17 @@ static int get_dimm_config(struct mem_ct
 
 				dimm->nr_pages = npages;
 				dimm->grain = 32;
-				dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+				switch (banks) {
+				case 16:
+					dimm->dtype = DEV_X16;
+					break;
+				case 8:
+					dimm->dtype = DEV_X8;
+					break;
+				case 4:
+					dimm->dtype = DEV_X4;
+					break;
+				}
 				dimm->mtype = mtype;
 				dimm->edac_mode = mode;
 				snprintf(dimm->label, sizeof(dimm->label),
@@ -887,7 +1061,7 @@ static void get_memory_layout(const stru
 			if (!IS_RIR_VALID(reg))
 				continue;
 
-			tmp_mb = RIR_LIMIT(reg) >> 20;
+			tmp_mb = pvt->info.rir_limit(reg) >> 20;
 			rir_way = 1 << RIR_WAY(reg);
 			mb = div_u64_rem(tmp_mb, 1000, &kb);
 			edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
@@ -936,11 +1110,11 @@ static int get_memory_error_data(struct
 	struct mem_ctl_info	*new_mci;
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	struct pci_dev		*pci_ha;
-	int 			n_rir, n_sads, n_tads, sad_way, sck_xch;
+	int			n_rir, n_sads, n_tads, sad_way, sck_xch;
 	int			sad_interl, idx, base_ch;
-	int			interleave_mode;
+	int			interleave_mode, shiftup = 0;
 	unsigned		sad_interleave[pvt->info.max_interleave];
-	u32			reg;
+	u32			reg, dram_rule;
 	u8			ch_way, sck_way, pkg, sad_ha = 0;
 	u32			tad_offset;
 	u32			rir_way;
@@ -987,8 +1161,9 @@ static int get_memory_error_data(struct
 		sprintf(msg, "Can't discover the memory socket");
 		return -EINVAL;
 	}
-	*area_type = get_dram_attr(reg);
-	interleave_mode = INTERLEAVE_MODE(reg);
+	dram_rule = reg;
+	*area_type = get_dram_attr(dram_rule);
+	interleave_mode = INTERLEAVE_MODE(dram_rule);
 
 	pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
 			      &reg);
@@ -1033,6 +1208,36 @@ static int get_memory_error_data(struct
 		*socket = sad_interleave[idx];
 		edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
 			 idx, sad_way, *socket);
+	} else if (pvt->info.type == HASWELL) {
+		int bits, a7mode = A7MODE(dram_rule);
+
+		if (a7mode) {
+			/* A7 mode swaps P9 with P6 */
+			bits = GET_BITFIELD(addr, 7, 8) << 1;
+			bits |= GET_BITFIELD(addr, 9, 9);
+		} else
+			bits = GET_BITFIELD(addr, 7, 9);
+
+		if (interleave_mode) {
+			/* interleave mode will XOR {8,7,6} with {18,17,16} */
+			idx = GET_BITFIELD(addr, 16, 18);
+			idx ^= bits;
+		} else
+			idx = bits;
+
+		pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
+		*socket = sad_pkg_socket(pkg);
+		sad_ha = sad_pkg_ha(pkg);
+
+		if (a7mode) {
+			/* MCChanShiftUpEnable */
+			pci_read_config_dword(pvt->pci_ha0,
+					      HASWELL_HASYSDEFEATURE2, &reg);
+			shiftup = GET_BITFIELD(reg, 22, 22);
+		}
+
+		edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i\n",
+			 idx, *socket, sad_ha, shiftup);
 	} else {
 		/* Ivy Bridge's SAD mode doesn't support XOR interleave mode */
 		idx = (addr >> 6) & 7;
@@ -1090,7 +1295,7 @@ static int get_memory_error_data(struct
 	if (ch_way == 3)
 		idx = addr >> 6;
 	else
-		idx = addr >> (6 + sck_way);
+		idx = (addr >> (6 + sck_way + shiftup)) & 0x3;
 	idx = idx % ch_way;
 
 	/*
@@ -1181,7 +1386,7 @@ static int get_memory_error_data(struct
 		if (!IS_RIR_VALID(reg))
 			continue;
 
-		limit = RIR_LIMIT(reg);
+		limit = pvt->info.rir_limit(reg);
 		mb = div_u64_rem(limit >> 20, 1000, &kb);
 		edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
 			 n_rir,
@@ -1197,6 +1402,7 @@ static int get_memory_error_data(struct
 		return -EINVAL;
 	}
 	rir_way = RIR_WAY(reg);
+
 	if (pvt->is_close_pg)
 		idx = (ch_addr >> 6);
 	else
@@ -1259,13 +1465,11 @@ static int sbridge_get_onedevice(struct
 {
 	struct sbridge_dev *sbridge_dev;
 	const struct pci_id_descr *dev_descr = &table->descr[devno];
-
 	struct pci_dev *pdev = NULL;
 	u8 bus = 0;
 
 	sbridge_printk(KERN_DEBUG,
-		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
-		dev_descr->dev, dev_descr->func,
+		"Seeking for: PCI ID %04x:%04x\n",
 		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1280,12 +1484,12 @@ static int sbridge_get_onedevice(struct
 		if (dev_descr->optional)
 			return 0;
 
+		/* if the HA wasn't found */
 		if (devno == 0)
 			return -ENODEV;
 
 		sbridge_printk(KERN_INFO,
-			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
-			dev_descr->dev, dev_descr->func,
+			"Device not found: %04x:%04x\n",
 			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
 		/* End of list, leave */
@@ -1305,9 +1509,7 @@ static int sbridge_get_onedevice(struct
 
 	if (sbridge_dev->pdev[devno]) {
 		sbridge_printk(KERN_ERR,
-			"Duplicated device for "
-			"dev %02x:%d.%d PCI ID %04x:%04x\n",
-			bus, dev_descr->dev, dev_descr->func,
+			"Duplicated device for %04x:%04x\n",
 			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 		pci_dev_put(pdev);
 		return -ENODEV;
@@ -1315,30 +1517,15 @@ static int sbridge_get_onedevice(struct
 
 	sbridge_dev->pdev[devno] = pdev;
 
-	/* Sanity check */
-	if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
-			PCI_FUNC(pdev->devfn) != dev_descr->func)) {
-		sbridge_printk(KERN_ERR,
-			"Device PCI ID %04x:%04x "
-			"has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
-			PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
-			bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-			bus, dev_descr->dev, dev_descr->func);
-		return -ENODEV;
-	}
-
 	/* Be sure that the device is enabled */
 	if (unlikely(pci_enable_device(pdev) < 0)) {
 		sbridge_printk(KERN_ERR,
-			"Couldn't enable "
-			"dev %02x:%d.%d PCI ID %04x:%04x\n",
-			bus, dev_descr->dev, dev_descr->func,
+			"Couldn't enable %04x:%04x\n",
 			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 		return -ENODEV;
 	}
 
-	edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
-		 bus, dev_descr->dev, dev_descr->func,
+	edac_dbg(0, "Detected %04x:%04x\n",
 		 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
 	/*
@@ -1355,10 +1542,9 @@ static int sbridge_get_onedevice(struct
 
 /*
  * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
- *			     device/functions we want to reference for this driver.
- *			     Need to 'get' device 16 func 1 and func 2.
+ *			     devices we want to reference for this driver.
  * @num_mc: pointer to the memory controllers count, to be incremented in case
- * 	    of success.
+ *	    of success.
  * @table: model specific table
  *
  * returns 0 in case of success or error code
@@ -1396,79 +1582,51 @@ static int sbridge_mci_bind_devs(struct
 {
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	struct pci_dev *pdev;
-	int i, func, slot;
+	int i;
 
 	for (i = 0; i < sbridge_dev->n_devs; i++) {
 		pdev = sbridge_dev->pdev[i];
 		if (!pdev)
 			continue;
-		slot = PCI_SLOT(pdev->devfn);
-		func = PCI_FUNC(pdev->devfn);
-		switch (slot) {
-		case 12:
-			switch (func) {
-			case 6:
-				pvt->pci_sad0 = pdev;
-				break;
-			case 7:
-				pvt->pci_sad1 = pdev;
-				break;
-			default:
-				goto error;
-			}
+
+		switch (pdev->device) {
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
+			pvt->pci_sad0 = pdev;
 			break;
-		case 13:
-			switch (func) {
-			case 6:
-				pvt->pci_br0 = pdev;
-				break;
-			default:
-				goto error;
-			}
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
+			pvt->pci_sad1 = pdev;
 			break;
-		case 14:
-			switch (func) {
-			case 0:
-				pvt->pci_ha0 = pdev;
-				break;
-			default:
-				goto error;
-			}
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
+			pvt->pci_br0 = pdev;
 			break;
-		case 15:
-			switch (func) {
-			case 0:
-				pvt->pci_ta = pdev;
-				break;
-			case 1:
-				pvt->pci_ras = pdev;
-				break;
-			case 2:
-			case 3:
-			case 4:
-			case 5:
-				pvt->pci_tad[func - 2] = pdev;
-				break;
-			default:
-				goto error;
-			}
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
+			pvt->pci_ha0 = pdev;
 			break;
-		case 17:
-			switch (func) {
-			case 0:
-				pvt->pci_ddrio = pdev;
-				break;
-			default:
-				goto error;
-			}
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
+			pvt->pci_ta = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS:
+			pvt->pci_ras = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0:
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1:
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
+		{
+			int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
+			pvt->pci_tad[id] = pdev;
+		}
+			break;
+		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
+			pvt->pci_ddrio = pdev;
 			break;
 		default:
 			goto error;
 		}
 
-		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
+		edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n",
+			 pdev->vendor, pdev->device,
 			 sbridge_dev->bus,
-			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
 			 pdev);
 	}
 
@@ -1488,9 +1646,8 @@ enodev:
 	return -ENODEV;
 
 error:
-	sbridge_printk(KERN_ERR, "Device %d, function %d "
-		      "is out of the expected range\n",
-		      slot, func);
+	sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n",
+		       PCI_VENDOR_ID_INTEL, pdev->device);
 	return -EINVAL;
 }
 
@@ -1499,7 +1656,7 @@ static int ibridge_mci_bind_devs(struct
 {
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	struct pci_dev *pdev, *tmp;
-	int i, func, slot;
+	int i;
 	bool mode_2ha = false;
 
 	tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1513,79 +1670,60 @@ static int ibridge_mci_bind_devs(struct
 		pdev = sbridge_dev->pdev[i];
 		if (!pdev)
 			continue;
-		slot = PCI_SLOT(pdev->devfn);
-		func = PCI_FUNC(pdev->devfn);
 
-		switch (slot) {
-		case 14:
-			if (func == 0) {
-				pvt->pci_ha0 = pdev;
-				break;
-			}
-			goto error;
-		case 15:
-			switch (func) {
-			case 0:
-				pvt->pci_ta = pdev;
-				break;
-			case 1:
-				pvt->pci_ras = pdev;
-				break;
-			case 4:
-			case 5:
-				/* if we have 2 HAs active, channels 2 and 3
-				 * are in other device */
-				if (mode_2ha)
-					break;
-				/* fall through */
-			case 2:
-			case 3:
-				pvt->pci_tad[func - 2] = pdev;
+		switch (pdev->device) {
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
+			pvt->pci_ha0 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
+			pvt->pci_ta = pdev;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
+			pvt->pci_ras = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
+			/* if we have 2 HAs active, channels 2 and 3
+			 * are in other device */
+			if (mode_2ha)
 				break;
-			default:
-				goto error;
-			}
+			/* fall through */
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
+		{
+			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
+			pvt->pci_tad[id] = pdev;
+		}
 			break;
-		case 17:
-			if (func == 4) {
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0:
+			pvt->pci_ddrio = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0:
+			if (!mode_2ha)
 				pvt->pci_ddrio = pdev;
-				break;
-			} else if (func == 0) {
-				if (!mode_2ha)
-					pvt->pci_ddrio = pdev;
-				break;
-			}
-			goto error;
-		case 22:
-			switch (func) {
-			case 0:
-				pvt->pci_sad0 = pdev;
-				break;
-			case 1:
-				pvt->pci_br0 = pdev;
-				break;
-			case 2:
-				pvt->pci_br1 = pdev;
-				break;
-			default:
-				goto error;
-			}
 			break;
-		case 28:
-			if (func == 0) {
-				pvt->pci_ha1 = pdev;
-				break;
-			}
-			goto error;
-		case 29:
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD:
+			pvt->pci_sad0 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0:
+			pvt->pci_br0 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
+			pvt->pci_br1 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
+			pvt->pci_ha1 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
+		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
+		{
+			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2;
+
 			/* we shouldn't have this device if we have just one
 			 * HA present */
 			WARN_ON(!mode_2ha);
-			if (func == 2 || func == 3) {
-				pvt->pci_tad[func] = pdev;
-				break;
-			}
-			goto error;
+			pvt->pci_tad[id] = pdev;
+		}
+			break;
 		default:
 			goto error;
 		}
@@ -1614,11 +1752,111 @@ enodev:
 
 error:
 	sbridge_printk(KERN_ERR,
-		       "Device %d, function %d is out of the expected range\n",
-		       slot, func);
+		       "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL,
+			pdev->device);
 	return -EINVAL;
 }
 
+static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
+				 struct sbridge_dev *sbridge_dev)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev, *tmp;
+	int i;
+	bool mode_2ha = false;
+
+	tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
+			     PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, NULL);
+	if (tmp) {
+		mode_2ha = true;
+		pci_dev_put(tmp);
+	}
+
+	/* there's only one device per system; not tied to any bus */
+	if (pvt->info.pci_vtd == NULL)
+		/* result will be checked later */
+		pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
+						   PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC,
+						   NULL);
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+
+		switch (pdev->device) {
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0:
+			pvt->pci_sad0 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1:
+			pvt->pci_sad1 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
+			pvt->pci_ha0 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
+			pvt->pci_ta = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL:
+			pvt->pci_ras = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
+			pvt->pci_tad[0] = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
+			pvt->pci_tad[1] = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
+			if (!mode_2ha)
+				pvt->pci_tad[2] = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
+			if (!mode_2ha)
+				pvt->pci_tad[3] = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
+			pvt->pci_ddrio = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
+			pvt->pci_ha1 = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
+			pvt->pci_ha1_ta = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0:
+			if (mode_2ha)
+				pvt->pci_tad[2] = pdev;
+			break;
+		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1:
+			if (mode_2ha)
+				pvt->pci_tad[3] = pdev;
+			break;
+		default:
+			break;
+		}
+
+		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
+			 sbridge_dev->bus,
+			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			 pdev);
+	}
+
+	/* Check if everything were registered */
+	if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
+	    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
+		goto enodev;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->pci_tad[i])
+			goto enodev;
+	}
+	return 0;
+
+enodev:
+	sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+	return -ENODEV;
+}
+
 /****************************************************************************
 			Error check routines
  ****************************************************************************/
@@ -1736,6 +1974,9 @@ static void sbridge_mce_output_error(str
 	 * EDAC core should be handling the channel mask, in order to point
 	 * to the group of dimm's where the error may be happening.
 	 */
+	if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg)
+		channel = first_channel;
+
 	snprintf(msg, sizeof(msg),
 		 "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d",
 		 overflow ? " OVERFLOW" : "",
@@ -1865,10 +2106,6 @@ static int sbridge_mce_check_error(struc
 			  "%u APIC %x\n", mce->cpuvendor, mce->cpuid,
 			  mce->time, mce->socketid, mce->apicid);
 
-	/* Only handle if it is the right mc controller */
-	if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
-		return NOTIFY_DONE;
-
 	smp_rmb();
 	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
 		smp_wmb();
@@ -1932,7 +2169,7 @@ static int sbridge_register_mci(struct s
 	int rc;
 
 	/* Check the number of active and not disabled channels */
-	rc = check_if_ecc_is_active(sbridge_dev->bus);
+	rc = check_if_ecc_is_active(sbridge_dev->bus, type);
 	if (unlikely(rc < 0))
 		return rc;
 
@@ -1971,11 +2208,15 @@ static int sbridge_register_mci(struct s
 	mci->edac_check = sbridge_check_error;
 
 	pvt->info.type = type;
-	if (type == IVY_BRIDGE) {
+	switch (type) {
+	case IVY_BRIDGE:
 		pvt->info.rankcfgr = IB_RANK_CFG_A;
 		pvt->info.get_tolm = ibridge_get_tolm;
 		pvt->info.get_tohm = ibridge_get_tohm;
 		pvt->info.dram_rule = ibridge_dram_rule;
+		pvt->info.get_memory_type = get_memory_type;
+		pvt->info.get_node_id = get_node_id;
+		pvt->info.rir_limit = rir_limit;
 		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
 		pvt->info.interleave_list = ibridge_interleave_list;
 		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -1986,11 +2227,15 @@ static int sbridge_register_mci(struct s
 		rc = ibridge_mci_bind_devs(mci, sbridge_dev);
 		if (unlikely(rc < 0))
 			goto fail0;
-	} else {
+		break;
+	case SANDY_BRIDGE:
 		pvt->info.rankcfgr = SB_RANK_CFG_A;
 		pvt->info.get_tolm = sbridge_get_tolm;
 		pvt->info.get_tohm = sbridge_get_tohm;
 		pvt->info.dram_rule = sbridge_dram_rule;
+		pvt->info.get_memory_type = get_memory_type;
+		pvt->info.get_node_id = get_node_id;
+		pvt->info.rir_limit = rir_limit;
 		pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
 		pvt->info.interleave_list = sbridge_interleave_list;
 		pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
@@ -2001,8 +2246,27 @@ static int sbridge_register_mci(struct s
 		rc = sbridge_mci_bind_devs(mci, sbridge_dev);
 		if (unlikely(rc < 0))
 			goto fail0;
-	}
+		break;
+	case HASWELL:
+		/* rankcfgr isn't used */
+		pvt->info.get_tolm = haswell_get_tolm;
+		pvt->info.get_tohm = haswell_get_tohm;
+		pvt->info.dram_rule = ibridge_dram_rule;
+		pvt->info.get_memory_type = haswell_get_memory_type;
+		pvt->info.get_node_id = haswell_get_node_id;
+		pvt->info.rir_limit = haswell_rir_limit;
+		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
+		pvt->info.interleave_list = ibridge_interleave_list;
+		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
+		pvt->info.interleave_pkg = ibridge_interleave_pkg;
+		mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
 
+		/* Store pci devices at mci for faster access */
+		rc = haswell_mci_bind_devs(mci, sbridge_dev);
+		if (unlikely(rc < 0))
+			goto fail0;
+		break;
+	}
 
 	/* Get dimm basic config and the memory layout */
 	get_dimm_config(mci);
@@ -2037,10 +2301,10 @@ fail0:
 
 static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	int rc;
+	int rc = -ENODEV;
 	u8 mc, num_mc = 0;
 	struct sbridge_dev *sbridge_dev;
-	enum type type;
+	enum type type = SANDY_BRIDGE;
 
 	/* get the pci devices we want to reserve for our use */
 	mutex_lock(&sbridge_edac_lock);
@@ -2054,12 +2318,19 @@ static int sbridge_probe(struct pci_dev
 	}
 	probed++;
 
-	if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) {
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
 		rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table);
 		type = IVY_BRIDGE;
-	} else {
+		break;
+	case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
 		rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table);
 		type = SANDY_BRIDGE;
+		break;
+	case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
+		rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
+		type = HASWELL;
+		break;
 	}
 	if (unlikely(rc < 0))
 		goto fail0;
@@ -2068,6 +2339,7 @@ static int sbridge_probe(struct pci_dev
 	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
 		edac_dbg(0, "Registering MC#%d (%d of %d)\n",
 			 mc, mc + 1, num_mc);
+
 		sbridge_dev->mc = mc++;
 		rc = sbridge_register_mci(sbridge_dev, type);
 		if (unlikely(rc < 0))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/edac/x38_edac.c linux-libre-3.17-rc7-gnu/drivers/edac/x38_edac.c
--- linux-libre-3.16-gnu/drivers/edac/x38_edac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/edac/x38_edac.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,8 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
+
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
 #include "edac_core.h"
 
 #define X38_REVISION		"1.1"
@@ -161,11 +163,6 @@ static void x38_clear_error_info(struct
 			 X38_ERRSTS_BITS);
 }
 
-static u64 x38_readq(const void __iomem *addr)
-{
-	return readl(addr) | (((u64)readl(addr + 4)) << 32);
-}
-
 static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
 				 struct x38_error_info *info)
 {
@@ -183,9 +180,9 @@ static void x38_get_and_clear_error_info
 	if (!(info->errsts & X38_ERRSTS_BITS))
 		return;
 
-	info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG);
+	info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
 	if (x38_channel_num == 2)
-		info->eccerrlog[1] = x38_readq(window + X38_C1ECCERRLOG);
+		info->eccerrlog[1] = lo_hi_readq(window + X38_C1ECCERRLOG);
 
 	pci_read_config_word(pdev, X38_ERRSTS, &info->errsts2);
 
@@ -196,10 +193,10 @@ static void x38_get_and_clear_error_info
 	 * should be UE info.
 	 */
 	if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) {
-		info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG);
+		info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
 		if (x38_channel_num == 2)
 			info->eccerrlog[1] =
-				x38_readq(window + X38_C1ECCERRLOG);
+				lo_hi_readq(window + X38_C1ECCERRLOG);
 	}
 
 	x38_clear_error_info(mci);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-adc-jack.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-adc-jack.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-adc-jack.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-adc-jack.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,7 +112,6 @@ static int adc_jack_probe(struct platfor
 		dev_err(&pdev->dev, "failed to allocate extcon device\n");
 		return -ENOMEM;
 	}
-	data->edev->dev.parent = &pdev->dev;
 	data->edev->name = pdata->name;
 
 	/* Check the length of array and set num_cables */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-arizona.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-arizona.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-arizona.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-arizona.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,11 @@
 #define ARIZONA_ACCDET_MODE_HPL 1
 #define ARIZONA_ACCDET_MODE_HPR 2
 
+#define ARIZONA_MICD_CLAMP_MODE_JDL      0x4
+#define ARIZONA_MICD_CLAMP_MODE_JDH      0x5
+#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
+#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
+
 #define ARIZONA_HPDET_MAX 10000
 
 #define HPDET_DEBOUNCE 500
@@ -324,14 +329,17 @@ static void arizona_stop_mic(struct ariz
 }
 
 static struct {
+	unsigned int threshold;
 	unsigned int factor_a;
 	unsigned int factor_b;
 } arizona_hpdet_b_ranges[] = {
-	{  5528,   362464 },
-	{ 11084,  6186851 },
-	{ 11065, 65460395 },
+	{ 100,  5528,   362464 },
+	{ 169, 11084,  6186851 },
+	{ 169, 11065, 65460395 },
 };
 
+#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
+
 static struct {
 	int min;
 	int max;
@@ -386,7 +394,8 @@ static int arizona_hpdet_read(struct ari
 			   >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
 
 		if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
-		    (val < 100 || val >= 0x3fb)) {
+		    (val < arizona_hpdet_b_ranges[range].threshold ||
+		     val >= ARIZONA_HPDET_B_RANGE_MAX)) {
 			range++;
 			dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
 				range);
@@ -399,7 +408,8 @@ static int arizona_hpdet_read(struct ari
 		}
 
 		/* If we go out of range report top of range */
-		if (val < 100 || val >= 0x3fb) {
+		if (val < arizona_hpdet_b_ranges[range].threshold ||
+		    val >= ARIZONA_HPDET_B_RANGE_MAX) {
 			dev_dbg(arizona->dev, "Measurement out of range\n");
 			return ARIZONA_HPDET_MAX;
 		}
@@ -664,9 +674,8 @@ err:
 			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 
 	/* Just report headphone */
-	ret = extcon_update_state(info->edev,
-				  1 << ARIZONA_CABLE_HEADPHONE,
-				  1 << ARIZONA_CABLE_HEADPHONE);
+	ret = extcon_set_cable_state_(info->edev,
+				      ARIZONA_CABLE_HEADPHONE, true);
 	if (ret != 0)
 		dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
 
@@ -723,9 +732,8 @@ err:
 			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 
 	/* Just report headphone */
-	ret = extcon_update_state(info->edev,
-				  1 << ARIZONA_CABLE_HEADPHONE,
-				  1 << ARIZONA_CABLE_HEADPHONE);
+	ret = extcon_set_cable_state_(info->edev,
+				      ARIZONA_CABLE_HEADPHONE, true);
 	if (ret != 0)
 		dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
 
@@ -812,16 +820,15 @@ static void arizona_micd_detect(struct w
 	if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
 		arizona_identify_headphone(info);
 
-		ret = extcon_update_state(info->edev,
-					  1 << ARIZONA_CABLE_MICROPHONE,
-					  1 << ARIZONA_CABLE_MICROPHONE);
+		ret = extcon_set_cable_state_(info->edev,
+					      ARIZONA_CABLE_MICROPHONE, true);
 
 		if (ret != 0)
 			dev_err(arizona->dev, "Headset report failed: %d\n",
 				ret);
 
 		/* Don't need to regulate for button detection */
-		ret = regulator_allow_bypass(info->micvdd, false);
+		ret = regulator_allow_bypass(info->micvdd, true);
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
 				ret);
@@ -962,10 +969,16 @@ static irqreturn_t arizona_jackdet(int i
 
 	if (arizona->pdata.jd_gpio5) {
 		mask = ARIZONA_MICD_CLAMP_STS;
-		present = 0;
+		if (arizona->pdata.jd_invert)
+			present = ARIZONA_MICD_CLAMP_STS;
+		else
+			present = 0;
 	} else {
 		mask = ARIZONA_JD1_STS;
-		present = ARIZONA_JD1_STS;
+		if (arizona->pdata.jd_invert)
+			present = 0;
+		else
+			present = ARIZONA_JD1_STS;
 	}
 
 	ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
@@ -1096,6 +1109,7 @@ static int arizona_extcon_probe(struct p
 	struct arizona_pdata *pdata = &arizona->pdata;
 	struct arizona_extcon_info *info;
 	unsigned int val;
+	unsigned int clamp_mode;
 	int jack_irq_fall, jack_irq_rise;
 	int ret, mode, i, j;
 
@@ -1103,12 +1117,10 @@ static int arizona_extcon_probe(struct p
 		return -EPROBE_DEFER;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "Failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
 
-	info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
+	info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
 	if (IS_ERR(info->micvdd)) {
 		ret = PTR_ERR(info->micvdd);
 		dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
@@ -1156,7 +1168,6 @@ static int arizona_extcon_probe(struct p
 		return -ENOMEM;
 	}
 	info->edev->name = "Headset Jack";
-	info->edev->dev.parent = arizona->dev;
 
 	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 	if (ret < 0) {
@@ -1174,7 +1185,6 @@ static int arizona_extcon_probe(struct p
 
 	info->input->name = "Headset";
 	info->input->phys = "arizona/extcon";
-	info->input->dev.parent = &pdev->dev;
 
 	if (pdata->num_micd_configs) {
 		info->micd_modes = pdata->micd_configs;
@@ -1305,16 +1315,22 @@ static int arizona_extcon_probe(struct p
 			regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
 				     val);
 
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_MICD_CLAMP_CONTROL,
-					   ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
+			if (arizona->pdata.jd_invert)
+				clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
+			else
+				clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
 		} else {
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_MICD_CLAMP_CONTROL,
-					   ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
+			if (arizona->pdata.jd_invert)
+				clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
+			else
+				clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
 		}
 
 		regmap_update_bits(arizona->regmap,
+				   ARIZONA_MICD_CLAMP_CONTROL,
+				   ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
+
+		regmap_update_bits(arizona->regmap,
 				   ARIZONA_JACK_DETECT_DEBOUNCE,
 				   ARIZONA_MICD_CLAMP_DB,
 				   ARIZONA_MICD_CLAMP_DB);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-class.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-class.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-class.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-class.c	2014-09-28 17:29:07.000000000 -0400
@@ -645,6 +645,8 @@ struct extcon_dev *devm_extcon_dev_alloc
 		return edev;
 	}
 
+	edev->dev.parent = dev;
+
 	*ptr = edev;
 	devres_add(dev, ptr);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-gpio.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-gpio.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,7 +105,6 @@ static int gpio_extcon_probe(struct plat
 		return -ENOMEM;
 	}
 	extcon_data->edev->name = pdata->name;
-	extcon_data->edev->dev.parent = &pdev->dev;
 
 	extcon_data->gpio = pdata->gpio;
 	extcon_data->gpio_active_low = pdata->gpio_active_low;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-max14577.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max14577.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-max14577.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max14577.c	2014-09-28 17:29:07.000000000 -0400
@@ -692,10 +692,9 @@ static int max14577_muic_probe(struct pl
 	u8 id;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
+
 	info->dev = &pdev->dev;
 	info->max14577 = max14577;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-max77693.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max77693.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-max77693.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max77693.c	2014-09-28 17:29:07.000000000 -0400
@@ -255,10 +255,10 @@ static int max77693_muic_set_debounce_ti
 	case ADC_DEBOUNCE_TIME_10MS:
 	case ADC_DEBOUNCE_TIME_25MS:
 	case ADC_DEBOUNCE_TIME_38_62MS:
-		ret = max77693_update_reg(info->max77693->regmap_muic,
+		ret = regmap_update_bits(info->max77693->regmap_muic,
 					  MAX77693_MUIC_REG_CTRL3,
-					  time << CONTROL3_ADCDBSET_SHIFT,
-					  CONTROL3_ADCDBSET_MASK);
+					  CONTROL3_ADCDBSET_MASK,
+					  time << CONTROL3_ADCDBSET_SHIFT);
 		if (ret) {
 			dev_err(info->dev, "failed to set ADC debounce time\n");
 			return ret;
@@ -286,15 +286,15 @@ static int max77693_muic_set_path(struct
 		u8 val, bool attached)
 {
 	int ret = 0;
-	u8 ctrl1, ctrl2 = 0;
+	unsigned int ctrl1, ctrl2 = 0;
 
 	if (attached)
 		ctrl1 = val;
 	else
 		ctrl1 = CONTROL1_SW_OPEN;
 
-	ret = max77693_update_reg(info->max77693->regmap_muic,
-			MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK);
+	ret = regmap_update_bits(info->max77693->regmap_muic,
+			MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);
 	if (ret < 0) {
 		dev_err(info->dev, "failed to update MUIC register\n");
 		return ret;
@@ -305,9 +305,9 @@ static int max77693_muic_set_path(struct
 	else
 		ctrl2 |= CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */
 
-	ret = max77693_update_reg(info->max77693->regmap_muic,
-			MAX77693_MUIC_REG_CTRL2, ctrl2,
-			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
+	ret = regmap_update_bits(info->max77693->regmap_muic,
+			MAX77693_MUIC_REG_CTRL2,
+			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
 	if (ret < 0) {
 		dev_err(info->dev, "failed to update MUIC register\n");
 		return ret;
@@ -969,8 +969,8 @@ static void max77693_muic_irq_work(struc
 		if (info->irq == muic_irqs[i].virq)
 			irq_type = muic_irqs[i].irq;
 
-	ret = max77693_bulk_read(info->max77693->regmap_muic,
-			MAX77693_MUIC_REG_STATUS1, 2, info->status);
+	ret = regmap_bulk_read(info->max77693->regmap_muic,
+			MAX77693_MUIC_REG_STATUS1, info->status, 2);
 	if (ret) {
 		dev_err(info->dev, "failed to read MUIC register\n");
 		mutex_unlock(&info->mutex);
@@ -1042,8 +1042,8 @@ static int max77693_muic_detect_accessor
 	mutex_lock(&info->mutex);
 
 	/* Read STATUSx register to detect accessory */
-	ret = max77693_bulk_read(info->max77693->regmap_muic,
-			MAX77693_MUIC_REG_STATUS1, 2, info->status);
+	ret = regmap_bulk_read(info->max77693->regmap_muic,
+			MAX77693_MUIC_REG_STATUS1, info->status, 2);
 	if (ret) {
 		dev_err(info->dev, "failed to read MUIC register\n");
 		mutex_unlock(&info->mutex);
@@ -1095,14 +1095,13 @@ static int max77693_muic_probe(struct pl
 	int delay_jiffies;
 	int ret;
 	int i;
-	u8 id;
+	unsigned int id;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
 				   GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
+
 	info->dev = &pdev->dev;
 	info->max77693 = max77693;
 	if (info->max77693->regmap_muic) {
@@ -1154,7 +1153,8 @@ static int max77693_muic_probe(struct pl
 		struct max77693_muic_irq *muic_irq = &muic_irqs[i];
 		unsigned int virq = 0;
 
-		virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
+		virq = regmap_irq_get_virq(max77693->irq_data_muic,
+					muic_irq->irq);
 		if (!virq) {
 			ret = -EINVAL;
 			goto err_irq;
@@ -1183,7 +1183,6 @@ static int max77693_muic_probe(struct pl
 		goto err_irq;
 	}
 	info->edev->name = DEV_NAME;
-	info->edev->dev.parent = &pdev->dev;
 
 	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 	if (ret) {
@@ -1204,7 +1203,7 @@ static int max77693_muic_probe(struct pl
 		enum max77693_irq_source irq_src
 				= MAX77693_IRQ_GROUP_NR;
 
-		max77693_write_reg(info->max77693->regmap_muic,
+		regmap_write(info->max77693->regmap_muic,
 				init_data[i].addr,
 				init_data[i].data);
 
@@ -1262,7 +1261,7 @@ static int max77693_muic_probe(struct pl
 	 max77693_muic_set_path(info, info->path_uart, true);
 
 	/* Check revision number of MUIC device*/
-	ret = max77693_read_reg(info->max77693->regmap_muic,
+	ret = regmap_read(info->max77693->regmap_muic,
 			MAX77693_MUIC_REG_ID, &id);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to read revision number\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-max8997.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max8997.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-max8997.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-max8997.c	2014-09-28 17:29:07.000000000 -0400
@@ -661,10 +661,8 @@ static int max8997_muic_probe(struct pla
 
 	info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
 			    GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
 
 	info->dev = &pdev->dev;
 	info->muic = max8997->muic;
@@ -706,7 +704,6 @@ static int max8997_muic_probe(struct pla
 		goto err_irq;
 	}
 	info->edev->name = DEV_NAME;
-	info->edev->dev.parent = &pdev->dev;
 
 	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 	if (ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-palmas.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-palmas.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-palmas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-palmas.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,7 +194,6 @@ static int palmas_usb_probe(struct platf
 		return -ENOMEM;
 	}
 	palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
-	palmas_usb->edev->dev.parent = palmas_usb->dev;
 	palmas_usb->edev->mutually_exclusive = mutually_exclusive;
 
 	status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
@@ -278,7 +277,7 @@ static int palmas_usb_resume(struct devi
 
 static SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume);
 
-static struct of_device_id of_palmas_match_tbl[] = {
+static const struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas-usb", },
 	{ .compatible = "ti,palmas-usb-vid", },
 	{ .compatible = "ti,twl6035-usb", },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/extcon-sm5502.c linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-sm5502.c
--- linux-libre-3.16-gnu/drivers/extcon/extcon-sm5502.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/extcon-sm5502.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,724 @@
+/*
+ * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ * Author: 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/extcon.h>
+#include <linux/extcon/sm5502.h>
+
+#define	DELAY_MS_DEFAULT		17000	/* unit: millisecond */
+
+struct muic_irq {
+	unsigned int irq;
+	const char *name;
+	unsigned int virq;
+};
+
+struct reg_data {
+	u8 reg;
+	unsigned int val;
+	bool invert;
+};
+
+struct sm5502_muic_info {
+	struct device *dev;
+	struct extcon_dev *edev;
+
+	struct i2c_client *i2c;
+	struct regmap *regmap;
+
+	struct regmap_irq_chip_data *irq_data;
+	struct muic_irq *muic_irqs;
+	unsigned int num_muic_irqs;
+	int irq;
+	bool irq_attach;
+	bool irq_detach;
+	struct work_struct irq_work;
+
+	struct reg_data *reg_data;
+	unsigned int num_reg_data;
+
+	struct mutex mutex;
+
+	/*
+	 * Use delayed workqueue to detect cable state and then
+	 * notify cable state to notifiee/platform through uevent.
+	 * After completing the booting of platform, the extcon provider
+	 * driver should notify cable state to upper layer.
+	 */
+	struct delayed_work wq_detcable;
+};
+
+/* Default value of SM5502 register to bring up MUIC device. */
+static struct reg_data sm5502_reg_data[] = {
+	{
+		.reg = SM5502_REG_CONTROL,
+		.val = SM5502_REG_CONTROL_MASK_INT_MASK,
+		.invert = false,
+	}, {
+		.reg = SM5502_REG_INTMASK1,
+		.val = SM5502_REG_INTM1_KP_MASK
+			| SM5502_REG_INTM1_LKP_MASK
+			| SM5502_REG_INTM1_LKR_MASK,
+		.invert = true,
+	}, {
+		.reg = SM5502_REG_INTMASK2,
+		.val = SM5502_REG_INTM2_VBUS_DET_MASK
+			| SM5502_REG_INTM2_REV_ACCE_MASK
+			| SM5502_REG_INTM2_ADC_CHG_MASK
+			| SM5502_REG_INTM2_STUCK_KEY_MASK
+			| SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
+			| SM5502_REG_INTM2_MHL_MASK,
+		.invert = true,
+	},
+	{ }
+};
+
+/* List of detectable cables */
+enum {
+	EXTCON_CABLE_USB = 0,
+	EXTCON_CABLE_USB_HOST,
+	EXTCON_CABLE_TA,
+
+	EXTCON_CABLE_END,
+};
+
+static const char *sm5502_extcon_cable[] = {
+	[EXTCON_CABLE_USB]	= "USB",
+	[EXTCON_CABLE_USB_HOST]	= "USB-Host",
+	[EXTCON_CABLE_TA]	= "TA",
+	NULL,
+};
+
+/* Define supported accessory type */
+enum sm5502_muic_acc_type {
+	SM5502_MUIC_ADC_GROUND = 0x0,
+	SM5502_MUIC_ADC_SEND_END_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S4_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S5_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S6_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S7_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S8_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S9_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S10_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S11_BUTTON,
+	SM5502_MUIC_ADC_REMOTE_S12_BUTTON,
+	SM5502_MUIC_ADC_RESERVED_ACC_1,
+	SM5502_MUIC_ADC_RESERVED_ACC_2,
+	SM5502_MUIC_ADC_RESERVED_ACC_3,
+	SM5502_MUIC_ADC_RESERVED_ACC_4,
+	SM5502_MUIC_ADC_RESERVED_ACC_5,
+	SM5502_MUIC_ADC_AUDIO_TYPE2,
+	SM5502_MUIC_ADC_PHONE_POWERED_DEV,
+	SM5502_MUIC_ADC_TTY_CONVERTER,
+	SM5502_MUIC_ADC_UART_CABLE,
+	SM5502_MUIC_ADC_TYPE1_CHARGER,
+	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB,
+	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB,
+	SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE,
+	SM5502_MUIC_ADC_TYPE2_CHARGER,
+	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART,
+	SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART,
+	SM5502_MUIC_ADC_AUDIO_TYPE1,
+	SM5502_MUIC_ADC_OPEN = 0x1f,
+
+	/* The below accessories have same ADC value (0x1f or 0x1e).
+	   So, Device type1 is used to separate specific accessory. */
+							/* |---------|--ADC| */
+							/* |    [7:5]|[4:0]| */
+	SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e,	/* |      001|11110| */
+	SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e,	/* |      010|11110| */
+							/* |Dev Type1|--ADC| */
+	SM5502_MUIC_ADC_OPEN_USB = 0x5f,		/* |      010|11111| */
+	SM5502_MUIC_ADC_OPEN_TA = 0xdf,			/* |      110|11111| */
+	SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff,		/* |      111|11111| */
+};
+
+/* List of supported interrupt for SM5502 */
+static struct muic_irq sm5502_muic_irqs[] = {
+	{ SM5502_IRQ_INT1_ATTACH,	"muic-attach" },
+	{ SM5502_IRQ_INT1_DETACH,	"muic-detach" },
+	{ SM5502_IRQ_INT1_KP,		"muic-kp" },
+	{ SM5502_IRQ_INT1_LKP,		"muic-lkp" },
+	{ SM5502_IRQ_INT1_LKR,		"muic-lkr" },
+	{ SM5502_IRQ_INT1_OVP_EVENT,	"muic-ovp-event" },
+	{ SM5502_IRQ_INT1_OCP_EVENT,	"muic-ocp-event" },
+	{ SM5502_IRQ_INT1_OVP_OCP_DIS,	"muic-ovp-ocp-dis" },
+	{ SM5502_IRQ_INT2_VBUS_DET,	"muic-vbus-det" },
+	{ SM5502_IRQ_INT2_REV_ACCE,	"muic-rev-acce" },
+	{ SM5502_IRQ_INT2_ADC_CHG,	"muic-adc-chg" },
+	{ SM5502_IRQ_INT2_STUCK_KEY,	"muic-stuck-key" },
+	{ SM5502_IRQ_INT2_STUCK_KEY_RCV, "muic-stuck-key-rcv" },
+	{ SM5502_IRQ_INT2_MHL,		"muic-mhl" },
+};
+
+/* Define interrupt list of SM5502 to register regmap_irq */
+static const struct regmap_irq sm5502_irqs[] = {
+	/* INT1 interrupts */
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_ATTACH_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_DETACH_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_KP_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKP_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKR_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_EVENT_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OCP_EVENT_MASK, },
+	{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_OCP_DIS_MASK, },
+
+	/* INT2 interrupts */
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_VBUS_DET_MASK,},
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_REV_ACCE_MASK, },
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_ADC_CHG_MASK, },
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_MASK, },
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK, },
+	{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_MHL_MASK, },
+};
+
+static const struct regmap_irq_chip sm5502_muic_irq_chip = {
+	.name			= "sm5502",
+	.status_base		= SM5502_REG_INT1,
+	.mask_base		= SM5502_REG_INTMASK1,
+	.mask_invert		= false,
+	.num_regs		= 2,
+	.irqs			= sm5502_irqs,
+	.num_irqs		= ARRAY_SIZE(sm5502_irqs),
+};
+
+/* Define regmap configuration of SM5502 for I2C communication  */
+static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SM5502_REG_INTMASK1:
+	case SM5502_REG_INTMASK2:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static const struct regmap_config sm5502_muic_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.volatile_reg	= sm5502_muic_volatile_reg,
+	.max_register	= SM5502_REG_END,
+};
+
+/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
+static int sm5502_muic_set_path(struct sm5502_muic_info *info,
+				unsigned int con_sw, unsigned int vbus_sw,
+				bool attached)
+{
+	int ret;
+
+	if (!attached) {
+		con_sw	= DM_DP_SWITCH_OPEN;
+		vbus_sw	= VBUSIN_SWITCH_OPEN;
+	}
+
+	switch (con_sw) {
+	case DM_DP_SWITCH_OPEN:
+	case DM_DP_SWITCH_USB:
+	case DM_DP_SWITCH_AUDIO:
+	case DM_DP_SWITCH_UART:
+		ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
+					 SM5502_REG_MANUAL_SW1_DP_MASK |
+					 SM5502_REG_MANUAL_SW1_DM_MASK,
+					 con_sw);
+		if (ret < 0) {
+			dev_err(info->dev,
+				"cannot update DM_CON/DP_CON switch\n");
+			return ret;
+		}
+		break;
+	default:
+		dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
+				con_sw);
+		return -EINVAL;
+	};
+
+	switch (vbus_sw) {
+	case VBUSIN_SWITCH_OPEN:
+	case VBUSIN_SWITCH_VBUSOUT:
+	case VBUSIN_SWITCH_MIC:
+	case VBUSIN_SWITCH_VBUSOUT_WITH_USB:
+		ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
+					 SM5502_REG_MANUAL_SW1_VBUSIN_MASK,
+					 vbus_sw);
+		if (ret < 0) {
+			dev_err(info->dev,
+				"cannot update VBUSIN switch\n");
+			return ret;
+		}
+		break;
+	default:
+		dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+/* Return cable type of attached or detached accessories */
+static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
+{
+	unsigned int cable_type = -1, adc, dev_type1;
+	int ret;
+
+	/* Read ADC value according to external cable or button */
+	ret = regmap_read(info->regmap, SM5502_REG_ADC, &adc);
+	if (ret) {
+		dev_err(info->dev, "failed to read ADC register\n");
+		return ret;
+	}
+
+	/*
+	 * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
+	 * connected with to MUIC device.
+	 */
+	cable_type &= SM5502_REG_ADC_MASK;
+	if (cable_type == SM5502_MUIC_ADC_GROUND)
+		return SM5502_MUIC_ADC_GROUND;
+
+	switch (cable_type) {
+	case SM5502_MUIC_ADC_GROUND:
+	case SM5502_MUIC_ADC_SEND_END_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S1_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S2_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S3_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S4_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S5_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S6_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S7_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S8_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S9_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S10_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S11_BUTTON:
+	case SM5502_MUIC_ADC_REMOTE_S12_BUTTON:
+	case SM5502_MUIC_ADC_RESERVED_ACC_1:
+	case SM5502_MUIC_ADC_RESERVED_ACC_2:
+	case SM5502_MUIC_ADC_RESERVED_ACC_3:
+	case SM5502_MUIC_ADC_RESERVED_ACC_4:
+	case SM5502_MUIC_ADC_RESERVED_ACC_5:
+	case SM5502_MUIC_ADC_AUDIO_TYPE2:
+	case SM5502_MUIC_ADC_PHONE_POWERED_DEV:
+	case SM5502_MUIC_ADC_TTY_CONVERTER:
+	case SM5502_MUIC_ADC_UART_CABLE:
+	case SM5502_MUIC_ADC_TYPE1_CHARGER:
+	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
+	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
+	case SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE:
+	case SM5502_MUIC_ADC_TYPE2_CHARGER:
+	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
+	case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
+		break;
+	case SM5502_MUIC_ADC_AUDIO_TYPE1:
+		/*
+		 * Check whether cable type is
+		 * SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE
+		 * or SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END
+		 * by using Button event.
+		 */
+		break;
+	case SM5502_MUIC_ADC_OPEN:
+		ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1,
+				  &dev_type1);
+		if (ret) {
+			dev_err(info->dev, "failed to read DEV_TYPE1 reg\n");
+			return ret;
+		}
+
+		switch (dev_type1) {
+		case SM5502_REG_DEV_TYPE1_USB_SDP_MASK:
+			cable_type = SM5502_MUIC_ADC_OPEN_USB;
+			break;
+		case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK:
+			cable_type = SM5502_MUIC_ADC_OPEN_TA;
+			break;
+		case SM5502_REG_DEV_TYPE1_USB_OTG_MASK:
+			cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG;
+			break;
+		default:
+			dev_dbg(info->dev,
+				"cannot identify the cable type: adc(0x%x) "
+				"dev_type1(0x%x)\n", adc, dev_type1);
+			return -EINVAL;
+		};
+		break;
+	default:
+		dev_err(info->dev,
+			"failed to identify the cable type: adc(0x%x)\n", adc);
+		return -EINVAL;
+	};
+
+	return cable_type;
+}
+
+static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
+				     bool attached)
+{
+	static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
+	const char **cable_names = info->edev->supported_cable;
+	unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
+	unsigned int con_sw = DM_DP_SWITCH_OPEN;
+	unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
+	unsigned int idx = 0;
+	int ret;
+
+	if (!cable_names)
+		return 0;
+
+	/* Get the type of attached or detached cable */
+	if (attached)
+		cable_type = sm5502_muic_get_cable_type(info);
+	else if (!attached)
+		cable_type = prev_cable_type;
+	prev_cable_type = cable_type;
+
+	switch (cable_type) {
+	case SM5502_MUIC_ADC_OPEN_USB:
+		idx	= EXTCON_CABLE_USB;
+		con_sw	= DM_DP_SWITCH_USB;
+		vbus_sw	= VBUSIN_SWITCH_VBUSOUT_WITH_USB;
+		break;
+	case SM5502_MUIC_ADC_OPEN_TA:
+		idx	= EXTCON_CABLE_TA;
+		con_sw	= DM_DP_SWITCH_OPEN;
+		vbus_sw	= VBUSIN_SWITCH_VBUSOUT;
+		break;
+	case SM5502_MUIC_ADC_OPEN_USB_OTG:
+		idx	= EXTCON_CABLE_USB_HOST;
+		con_sw	= DM_DP_SWITCH_USB;
+		vbus_sw	= VBUSIN_SWITCH_OPEN;
+		break;
+	default:
+		dev_dbg(info->dev,
+			"cannot handle this cable_type (0x%x)\n", cable_type);
+		return 0;
+	};
+
+	/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
+	ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
+	if (ret < 0)
+		return ret;
+
+	/* Change the state of external accessory */
+	extcon_set_cable_state(info->edev, cable_names[idx], attached);
+
+	return 0;
+}
+
+static void sm5502_muic_irq_work(struct work_struct *work)
+{
+	struct sm5502_muic_info *info = container_of(work,
+			struct sm5502_muic_info, irq_work);
+	int ret = 0;
+
+	if (!info->edev)
+		return;
+
+	mutex_lock(&info->mutex);
+
+	/* Detect attached or detached cables */
+	if (info->irq_attach) {
+		ret = sm5502_muic_cable_handler(info, true);
+		info->irq_attach = false;
+	}
+	if (info->irq_detach) {
+		ret = sm5502_muic_cable_handler(info, false);
+		info->irq_detach = false;
+	}
+
+	if (ret < 0)
+		dev_err(info->dev, "failed to handle MUIC interrupt\n");
+
+	mutex_unlock(&info->mutex);
+
+	return;
+}
+
+/*
+ * Sets irq_attach or irq_detach in sm5502_muic_info and returns 0.
+ * Returns -ESRCH if irq_type does not match registered IRQ for this dev type.
+ */
+static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type)
+{
+	switch (irq_type) {
+	case SM5502_IRQ_INT1_ATTACH:
+		info->irq_attach = true;
+		break;
+	case SM5502_IRQ_INT1_DETACH:
+		info->irq_detach = true;
+		break;
+	case SM5502_IRQ_INT1_KP:
+	case SM5502_IRQ_INT1_LKP:
+	case SM5502_IRQ_INT1_LKR:
+	case SM5502_IRQ_INT1_OVP_EVENT:
+	case SM5502_IRQ_INT1_OCP_EVENT:
+	case SM5502_IRQ_INT1_OVP_OCP_DIS:
+	case SM5502_IRQ_INT2_VBUS_DET:
+	case SM5502_IRQ_INT2_REV_ACCE:
+	case SM5502_IRQ_INT2_ADC_CHG:
+	case SM5502_IRQ_INT2_STUCK_KEY:
+	case SM5502_IRQ_INT2_STUCK_KEY_RCV:
+	case SM5502_IRQ_INT2_MHL:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static irqreturn_t sm5502_muic_irq_handler(int irq, void *data)
+{
+	struct sm5502_muic_info *info = data;
+	int i, irq_type = -1, ret;
+
+	for (i = 0; i < info->num_muic_irqs; i++)
+		if (irq == info->muic_irqs[i].virq)
+			irq_type = info->muic_irqs[i].irq;
+
+	ret = sm5502_parse_irq(info, irq_type);
+	if (ret < 0) {
+		dev_warn(info->dev, "cannot handle is interrupt:%d\n",
+				    irq_type);
+		return IRQ_HANDLED;
+	}
+	schedule_work(&info->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static void sm5502_muic_detect_cable_wq(struct work_struct *work)
+{
+	struct sm5502_muic_info *info = container_of(to_delayed_work(work),
+				struct sm5502_muic_info, wq_detcable);
+	int ret;
+
+	/* Notify the state of connector cable or not  */
+	ret = sm5502_muic_cable_handler(info, true);
+	if (ret < 0)
+		dev_warn(info->dev, "failed to detect cable state\n");
+}
+
+static void sm5502_init_dev_type(struct sm5502_muic_info *info)
+{
+	unsigned int reg_data, vendor_id, version_id;
+	int i, ret;
+
+	/* To test I2C, Print version_id and vendor_id of SM5502 */
+	ret = regmap_read(info->regmap, SM5502_REG_DEVICE_ID, &reg_data);
+	if (ret) {
+		dev_err(info->dev,
+			"failed to read DEVICE_ID register: %d\n", ret);
+		return;
+	}
+
+	vendor_id = ((reg_data & SM5502_REG_DEVICE_ID_VENDOR_MASK) >>
+				SM5502_REG_DEVICE_ID_VENDOR_SHIFT);
+	version_id = ((reg_data & SM5502_REG_DEVICE_ID_VERSION_MASK) >>
+				SM5502_REG_DEVICE_ID_VERSION_SHIFT);
+
+	dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
+			    version_id, vendor_id);
+
+	/* Initiazle the register of SM5502 device to bring-up */
+	for (i = 0; i < info->num_reg_data; i++) {
+		unsigned int val = 0;
+
+		if (!info->reg_data[i].invert)
+			val |= ~info->reg_data[i].val;
+		else
+			val = info->reg_data[i].val;
+		regmap_write(info->regmap, info->reg_data[i].reg, val);
+	}
+}
+
+static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
+				 const struct i2c_device_id *id)
+{
+	struct device_node *np = i2c->dev.of_node;
+	struct sm5502_muic_info *info;
+	int i, ret, irq_flags;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	i2c_set_clientdata(i2c, info);
+
+	info->dev = &i2c->dev;
+	info->i2c = i2c;
+	info->irq = i2c->irq;
+	info->muic_irqs = sm5502_muic_irqs;
+	info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs);
+	info->reg_data = sm5502_reg_data;
+	info->num_reg_data = ARRAY_SIZE(sm5502_reg_data);
+
+	mutex_init(&info->mutex);
+
+	INIT_WORK(&info->irq_work, sm5502_muic_irq_work);
+
+	info->regmap = devm_regmap_init_i2c(i2c, &sm5502_muic_regmap_config);
+	if (IS_ERR(info->regmap)) {
+		ret = PTR_ERR(info->regmap);
+		dev_err(info->dev, "failed to allocate register map: %d\n",
+				   ret);
+		return ret;
+	}
+
+	/* Support irq domain for SM5502 MUIC device */
+	irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
+	ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0,
+				  &sm5502_muic_irq_chip, &info->irq_data);
+	if (ret != 0) {
+		dev_err(info->dev, "failed to request IRQ %d: %d\n",
+				    info->irq, ret);
+		return ret;
+	}
+
+	for (i = 0; i < info->num_muic_irqs; i++) {
+		struct muic_irq *muic_irq = &info->muic_irqs[i];
+		unsigned int virq = 0;
+
+		virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
+		if (virq <= 0)
+			return -EINVAL;
+		muic_irq->virq = virq;
+
+		ret = devm_request_threaded_irq(info->dev, virq, NULL,
+						sm5502_muic_irq_handler,
+						IRQF_NO_SUSPEND,
+						muic_irq->name, info);
+		if (ret) {
+			dev_err(info->dev, "failed: irq request (IRQ: %d,"
+				" error :%d)\n", muic_irq->irq, ret);
+			return ret;
+		}
+	}
+
+	/* Allocate extcon device */
+	info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
+	if (IS_ERR(info->edev)) {
+		dev_err(info->dev, "failed to allocate memory for extcon\n");
+		return -ENOMEM;
+	}
+	info->edev->name = np->name;
+
+	/* Register extcon device */
+	ret = devm_extcon_dev_register(info->dev, info->edev);
+	if (ret) {
+		dev_err(info->dev, "failed to register extcon device\n");
+		return ret;
+	}
+
+	/*
+	 * Detect accessory after completing the initialization of platform
+	 *
+	 * - Use delayed workqueue to detect cable state and then
+	 * notify cable state to notifiee/platform through uevent.
+	 * After completing the booting of platform, the extcon provider
+	 * driver should notify cable state to upper layer.
+	 */
+	INIT_DELAYED_WORK(&info->wq_detcable, sm5502_muic_detect_cable_wq);
+	queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+			msecs_to_jiffies(DELAY_MS_DEFAULT));
+
+	/* Initialize SM5502 device and print vendor id and version id */
+	sm5502_init_dev_type(info);
+
+	return 0;
+}
+
+static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
+{
+	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+	regmap_del_irq_chip(info->irq, info->irq_data);
+
+	return 0;
+}
+
+static struct of_device_id sm5502_dt_match[] = {
+	{ .compatible = "siliconmitus,sm5502-muic" },
+	{ },
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int sm5502_muic_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+	enable_irq_wake(info->irq);
+
+	return 0;
+}
+
+static int sm5502_muic_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+	disable_irq_wake(info->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops,
+			 sm5502_muic_suspend, sm5502_muic_resume);
+
+static const struct i2c_device_id sm5502_i2c_id[] = {
+	{ "sm5502", TYPE_SM5502 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
+
+static struct i2c_driver sm5502_muic_i2c_driver = {
+	.driver		= {
+		.name	= "sm5502",
+		.owner	= THIS_MODULE,
+		.pm	= &sm5502_muic_pm_ops,
+		.of_match_table = sm5502_dt_match,
+	},
+	.probe	= sm5022_muic_i2c_probe,
+	.remove	= sm5502_muic_i2c_remove,
+	.id_table = sm5502_i2c_id,
+};
+
+static int __init sm5502_muic_i2c_init(void)
+{
+	return i2c_add_driver(&sm5502_muic_i2c_driver);
+}
+subsys_initcall(sm5502_muic_i2c_init);
+
+MODULE_DESCRIPTION("Silicon Mitus SM5502 Extcon driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/Kconfig linux-libre-3.17-rc7-gnu/drivers/extcon/Kconfig
--- linux-libre-3.16-gnu/drivers/extcon/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,20 @@ if EXTCON
 
 comment "Extcon Device Drivers"
 
+config EXTCON_ADC_JACK
+	tristate "ADC Jack extcon support"
+	depends on IIO
+	help
+	  Say Y here to enable extcon device driver based on ADC values.
+
+config EXTCON_ARIZONA
+	tristate "Wolfson Arizona EXTCON support"
+	depends on MFD_ARIZONA && INPUT && SND_SOC
+	help
+	  Say Y here to enable support for external accessory detection
+	  with Wolfson Arizona devices. These are audio CODECs with
+	  advanced audio accessory detection support.
+
 config EXTCON_GPIO
 	tristate "GPIO extcon support"
 	depends on GPIOLIB
@@ -21,12 +35,6 @@ config EXTCON_GPIO
 	  Say Y here to enable GPIO based extcon support. Note that GPIO
 	  extcon supports single state per extcon instance.
 
-config EXTCON_ADC_JACK
-	tristate "ADC Jack extcon support"
-	depends on IIO
-	help
-	  Say Y here to enable extcon device driver based on ADC values.
-
 config EXTCON_MAX14577
 	tristate "MAX14577/77836 EXTCON Support"
 	depends on MFD_MAX14577
@@ -55,14 +63,6 @@ config EXTCON_MAX8997
 	  Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
 	  detector and switch.
 
-config EXTCON_ARIZONA
-	tristate "Wolfson Arizona EXTCON support"
-	depends on MFD_ARIZONA && INPUT && SND_SOC
-	help
-	  Say Y here to enable support for external accessory detection
-	  with Wolfson Arizona devices. These are audio CODECs with
-	  advanced audio accessory detection support.
-
 config EXTCON_PALMAS
 	tristate "Palmas USB EXTCON support"
 	depends on MFD_PALMAS
@@ -70,4 +70,14 @@ config EXTCON_PALMAS
 	  Say Y here to enable support for USB peripheral and USB host
 	  detection by palmas usb.
 
+config EXTCON_SM5502
+	tristate "SM5502 EXTCON support"
+	select IRQ_DOMAIN
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  If you say yes here you get support for the MUIC device of
+	  Silicon Mitus SM5502. The SM5502 is a USB port accessory
+	  detector and switch.
+
 endif # MULTISTATE_SWITCH
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/extcon/Makefile linux-libre-3.17-rc7-gnu/drivers/extcon/Makefile
--- linux-libre-3.16-gnu/drivers/extcon/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/extcon/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,13 @@
-#
+
 # Makefile for external connector class (extcon) devices
 #
 
 obj-$(CONFIG_EXTCON)		+= extcon-class.o
-obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
 obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
+obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
+obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
 obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
 obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
 obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
-obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
 obj-$(CONFIG_EXTCON_PALMAS)	+= extcon-palmas.o
+obj-$(CONFIG_EXTCON_SM5502)	+= extcon-sm5502.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firewire/core-cdev.c linux-libre-3.17-rc7-gnu/drivers/firewire/core-cdev.c
--- linux-libre-3.16-gnu/drivers/firewire/core-cdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firewire/core-cdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -1214,9 +1214,9 @@ static int ioctl_get_cycle_timer2(struct
 	cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
 
 	switch (a->clk_id) {
-	case CLOCK_REALTIME:      getnstimeofday(&ts);                   break;
-	case CLOCK_MONOTONIC:     do_posix_clock_monotonic_gettime(&ts); break;
-	case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts);                  break;
+	case CLOCK_REALTIME:      getnstimeofday(&ts);	break;
+	case CLOCK_MONOTONIC:     ktime_get_ts(&ts);	break;
+	case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts);	break;
 	default:
 		ret = -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firewire/net.c linux-libre-3.17-rc7-gnu/drivers/firewire/net.c
--- linux-libre-3.16-gnu/drivers/firewire/net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firewire/net.c	2014-09-28 17:29:07.000000000 -0400
@@ -1460,7 +1460,8 @@ static int fwnet_probe(struct fw_unit *u
 		goto have_dev;
 	}
 
-	net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev);
+	net = alloc_netdev(sizeof(*dev), "firewire%d", NET_NAME_UNKNOWN,
+			   fwnet_init_dev);
 	if (net == NULL) {
 		mutex_unlock(&fwnet_device_mutex);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/arm-stub.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/arm-stub.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/arm-stub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/arm-stub.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,278 +0,0 @@
-/*
- * EFI stub implementation that is shared by arm and arm64 architectures.
- * This should be #included by the EFI stub implementation files.
- *
- * Copyright (C) 2013,2014 Linaro Limited
- *     Roy Franz <roy.franz@linaro.org
- * Copyright (C) 2013 Red Hat, Inc.
- *     Mark Salter <msalter@redhat.com>
- *
- * This file is part of the Linux kernel, and is made available under the
- * terms of the GNU General Public License version 2.
- *
- */
-
-static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
-{
-	static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
-	static efi_char16_t const var_name[] __initconst = {
-		'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
-
-	efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
-	unsigned long size = sizeof(u8);
-	efi_status_t status;
-	u8 val;
-
-	status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid,
-			  NULL, &size, &val);
-
-	switch (status) {
-	case EFI_SUCCESS:
-		return val;
-	case EFI_NOT_FOUND:
-		return 0;
-	default:
-		return 1;
-	}
-}
-
-static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
-				    void *__image, void **__fh)
-{
-	efi_file_io_interface_t *io;
-	efi_loaded_image_t *image = __image;
-	efi_file_handle_t *fh;
-	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
-	efi_status_t status;
-	void *handle = (void *)(unsigned long)image->device_handle;
-
-	status = sys_table_arg->boottime->handle_protocol(handle,
-				 &fs_proto, (void **)&io);
-	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
-		return status;
-	}
-
-	status = io->open_volume(io, &fh);
-	if (status != EFI_SUCCESS)
-		efi_printk(sys_table_arg, "Failed to open volume\n");
-
-	*__fh = fh;
-	return status;
-}
-static efi_status_t efi_file_close(void *handle)
-{
-	efi_file_handle_t *fh = handle;
-
-	return fh->close(handle);
-}
-
-static efi_status_t
-efi_file_read(void *handle, unsigned long *size, void *addr)
-{
-	efi_file_handle_t *fh = handle;
-
-	return fh->read(handle, size, addr);
-}
-
-
-static efi_status_t
-efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
-	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
-{
-	efi_file_handle_t *h, *fh = __fh;
-	efi_file_info_t *info;
-	efi_status_t status;
-	efi_guid_t info_guid = EFI_FILE_INFO_ID;
-	unsigned long info_sz;
-
-	status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0);
-	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to open file: ");
-		efi_char16_printk(sys_table_arg, filename_16);
-		efi_printk(sys_table_arg, "\n");
-		return status;
-	}
-
-	*handle = h;
-
-	info_sz = 0;
-	status = h->get_info(h, &info_guid, &info_sz, NULL);
-	if (status != EFI_BUFFER_TOO_SMALL) {
-		efi_printk(sys_table_arg, "Failed to get file info size\n");
-		return status;
-	}
-
-grow:
-	status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA,
-				 info_sz, (void **)&info);
-	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
-		return status;
-	}
-
-	status = h->get_info(h, &info_guid, &info_sz,
-						   info);
-	if (status == EFI_BUFFER_TOO_SMALL) {
-		sys_table_arg->boottime->free_pool(info);
-		goto grow;
-	}
-
-	*file_sz = info->file_size;
-	sys_table_arg->boottime->free_pool(info);
-
-	if (status != EFI_SUCCESS)
-		efi_printk(sys_table_arg, "Failed to get initrd info\n");
-
-	return status;
-}
-
-
-
-static void efi_char16_printk(efi_system_table_t *sys_table_arg,
-			      efi_char16_t *str)
-{
-	struct efi_simple_text_output_protocol *out;
-
-	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
-	out->output_string(out, str);
-}
-
-
-/*
- * This function handles the architcture specific differences between arm and
- * arm64 regarding where the kernel image must be loaded and any memory that
- * must be reserved. On failure it is required to free all
- * all allocations it has made.
- */
-static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
-					unsigned long *image_addr,
-					unsigned long *image_size,
-					unsigned long *reserve_addr,
-					unsigned long *reserve_size,
-					unsigned long dram_base,
-					efi_loaded_image_t *image);
-/*
- * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
- * that is described in the PE/COFF header.  Most of the code is the same
- * for both archictectures, with the arch-specific code provided in the
- * handle_kernel_image() function.
- */
-unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
-			       unsigned long *image_addr)
-{
-	efi_loaded_image_t *image;
-	efi_status_t status;
-	unsigned long image_size = 0;
-	unsigned long dram_base;
-	/* addr/point and size pairs for memory management*/
-	unsigned long initrd_addr;
-	u64 initrd_size = 0;
-	unsigned long fdt_addr = 0;  /* Original DTB */
-	u64 fdt_size = 0;  /* We don't get size from configuration table */
-	char *cmdline_ptr = NULL;
-	int cmdline_size = 0;
-	unsigned long new_fdt_addr;
-	efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
-	unsigned long reserve_addr = 0;
-	unsigned long reserve_size = 0;
-
-	/* Check if we were booted by the EFI firmware */
-	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
-		goto fail;
-
-	pr_efi(sys_table, "Booting Linux Kernel...\n");
-
-	/*
-	 * Get a handle to the loaded image protocol.  This is used to get
-	 * information about the running image, such as size and the command
-	 * line.
-	 */
-	status = sys_table->boottime->handle_protocol(handle,
-					&loaded_image_proto, (void *)&image);
-	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
-		goto fail;
-	}
-
-	dram_base = get_dram_base(sys_table);
-	if (dram_base == EFI_ERROR) {
-		pr_efi_err(sys_table, "Failed to find DRAM base\n");
-		goto fail;
-	}
-	status = handle_kernel_image(sys_table, image_addr, &image_size,
-				     &reserve_addr,
-				     &reserve_size,
-				     dram_base, image);
-	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to relocate kernel\n");
-		goto fail;
-	}
-
-	/*
-	 * Get the command line from EFI, using the LOADED_IMAGE
-	 * protocol. We are going to copy the command line into the
-	 * device tree, so this can be allocated anywhere.
-	 */
-	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
-	if (!cmdline_ptr) {
-		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
-		goto fail_free_image;
-	}
-
-	/*
-	 * Unauthenticated device tree data is a security hazard, so
-	 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
-	 */
-	if (efi_secureboot_enabled(sys_table)) {
-		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
-	} else {
-		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
-					      "dtb=",
-					      ~0UL, (unsigned long *)&fdt_addr,
-					      (unsigned long *)&fdt_size);
-
-		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table, "Failed to load device tree!\n");
-			goto fail_free_cmdline;
-		}
-	}
-	if (!fdt_addr)
-		/* Look for a device tree configuration table entry. */
-		fdt_addr = (uintptr_t)get_fdt(sys_table);
-
-	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
-				      "initrd=", dram_base + SZ_512M,
-				      (unsigned long *)&initrd_addr,
-				      (unsigned long *)&initrd_size);
-	if (status != EFI_SUCCESS)
-		pr_efi_err(sys_table, "Failed initrd from command line!\n");
-
-	new_fdt_addr = fdt_addr;
-	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
-				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
-				initrd_addr, initrd_size, cmdline_ptr,
-				fdt_addr, fdt_size);
-
-	/*
-	 * If all went well, we need to return the FDT address to the
-	 * calling function so it can be passed to kernel as part of
-	 * the kernel boot protocol.
-	 */
-	if (status == EFI_SUCCESS)
-		return new_fdt_addr;
-
-	pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
-
-	efi_free(sys_table, initrd_size, initrd_addr);
-	efi_free(sys_table, fdt_size, fdt_addr);
-
-fail_free_cmdline:
-	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
-
-fail_free_image:
-	efi_free(sys_table, image_size, *image_addr);
-	efi_free(sys_table, reserve_size, reserve_addr);
-fail:
-	return EFI_ERROR;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/cper.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/cper.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/cper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/cper.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,9 @@
 #include <linux/aer.h>
 
 #define INDENT_SP	" "
+
+static char rcd_decode_str[CPER_REC_LEN];
+
 /*
  * CPER record ID need to be unique even after reboot, because record
  * ID is used as index for ERST storage, while CPER records from
@@ -50,18 +53,19 @@ u64 cper_next_record_id(void)
 }
 EXPORT_SYMBOL_GPL(cper_next_record_id);
 
-static const char *cper_severity_strs[] = {
+static const char * const severity_strs[] = {
 	"recoverable",
 	"fatal",
 	"corrected",
 	"info",
 };
 
-static const char *cper_severity_str(unsigned int severity)
+const char *cper_severity_str(unsigned int severity)
 {
-	return severity < ARRAY_SIZE(cper_severity_strs) ?
-		cper_severity_strs[severity] : "unknown";
+	return severity < ARRAY_SIZE(severity_strs) ?
+		severity_strs[severity] : "unknown";
 }
+EXPORT_SYMBOL_GPL(cper_severity_str);
 
 /*
  * cper_print_bits - print strings for set bits
@@ -100,32 +104,32 @@ void cper_print_bits(const char *pfx, un
 		printk("%s\n", buf);
 }
 
-static const char * const cper_proc_type_strs[] = {
+static const char * const proc_type_strs[] = {
 	"IA32/X64",
 	"IA64",
 };
 
-static const char * const cper_proc_isa_strs[] = {
+static const char * const proc_isa_strs[] = {
 	"IA32",
 	"IA64",
 	"X64",
 };
 
-static const char * const cper_proc_error_type_strs[] = {
+static const char * const proc_error_type_strs[] = {
 	"cache error",
 	"TLB error",
 	"bus error",
 	"micro-architectural error",
 };
 
-static const char * const cper_proc_op_strs[] = {
+static const char * const proc_op_strs[] = {
 	"unknown or generic",
 	"data read",
 	"data write",
 	"instruction execution",
 };
 
-static const char * const cper_proc_flag_strs[] = {
+static const char * const proc_flag_strs[] = {
 	"restartable",
 	"precise IP",
 	"overflow",
@@ -137,26 +141,26 @@ static void cper_print_proc_generic(cons
 {
 	if (proc->validation_bits & CPER_PROC_VALID_TYPE)
 		printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
-		       proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ?
-		       cper_proc_type_strs[proc->proc_type] : "unknown");
+		       proc->proc_type < ARRAY_SIZE(proc_type_strs) ?
+		       proc_type_strs[proc->proc_type] : "unknown");
 	if (proc->validation_bits & CPER_PROC_VALID_ISA)
 		printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
-		       proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ?
-		       cper_proc_isa_strs[proc->proc_isa] : "unknown");
+		       proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ?
+		       proc_isa_strs[proc->proc_isa] : "unknown");
 	if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
 		printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
 		cper_print_bits(pfx, proc->proc_error_type,
-				cper_proc_error_type_strs,
-				ARRAY_SIZE(cper_proc_error_type_strs));
+				proc_error_type_strs,
+				ARRAY_SIZE(proc_error_type_strs));
 	}
 	if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
 		printk("%s""operation: %d, %s\n", pfx, proc->operation,
-		       proc->operation < ARRAY_SIZE(cper_proc_op_strs) ?
-		       cper_proc_op_strs[proc->operation] : "unknown");
+		       proc->operation < ARRAY_SIZE(proc_op_strs) ?
+		       proc_op_strs[proc->operation] : "unknown");
 	if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
 		printk("%s""flags: 0x%02x\n", pfx, proc->flags);
-		cper_print_bits(pfx, proc->flags, cper_proc_flag_strs,
-				ARRAY_SIZE(cper_proc_flag_strs));
+		cper_print_bits(pfx, proc->flags, proc_flag_strs,
+				ARRAY_SIZE(proc_flag_strs));
 	}
 	if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
 		printk("%s""level: %d\n", pfx, proc->level);
@@ -177,7 +181,7 @@ static void cper_print_proc_generic(cons
 		printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
 }
 
-static const char *cper_mem_err_type_strs[] = {
+static const char * const mem_err_type_strs[] = {
 	"unknown",
 	"no error",
 	"single-bit ECC",
@@ -196,58 +200,136 @@ static const char *cper_mem_err_type_str
 	"physical memory map-out event",
 };
 
-static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+const char *cper_mem_err_type_str(unsigned int etype)
 {
-	if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
-		printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
-	if (mem->validation_bits & CPER_MEM_VALID_PA)
-		printk("%s""physical_address: 0x%016llx\n",
-		       pfx, mem->physical_addr);
-	if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
-		printk("%s""physical_address_mask: 0x%016llx\n",
-		       pfx, mem->physical_addr_mask);
+	return etype < ARRAY_SIZE(mem_err_type_strs) ?
+		mem_err_type_strs[etype] : "unknown";
+}
+EXPORT_SYMBOL_GPL(cper_mem_err_type_str);
+
+static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
+{
+	u32 len, n;
+
+	if (!msg)
+		return 0;
+
+	n = 0;
+	len = CPER_REC_LEN - 1;
 	if (mem->validation_bits & CPER_MEM_VALID_NODE)
-		pr_debug("node: %d\n", mem->node);
+		n += scnprintf(msg + n, len - n, "node: %d ", mem->node);
 	if (mem->validation_bits & CPER_MEM_VALID_CARD)
-		pr_debug("card: %d\n", mem->card);
+		n += scnprintf(msg + n, len - n, "card: %d ", mem->card);
 	if (mem->validation_bits & CPER_MEM_VALID_MODULE)
-		pr_debug("module: %d\n", mem->module);
+		n += scnprintf(msg + n, len - n, "module: %d ", mem->module);
 	if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
-		pr_debug("rank: %d\n", mem->rank);
+		n += scnprintf(msg + n, len - n, "rank: %d ", mem->rank);
 	if (mem->validation_bits & CPER_MEM_VALID_BANK)
-		pr_debug("bank: %d\n", mem->bank);
+		n += scnprintf(msg + n, len - n, "bank: %d ", mem->bank);
 	if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
-		pr_debug("device: %d\n", mem->device);
+		n += scnprintf(msg + n, len - n, "device: %d ", mem->device);
 	if (mem->validation_bits & CPER_MEM_VALID_ROW)
-		pr_debug("row: %d\n", mem->row);
+		n += scnprintf(msg + n, len - n, "row: %d ", mem->row);
 	if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
-		pr_debug("column: %d\n", mem->column);
+		n += scnprintf(msg + n, len - n, "column: %d ", mem->column);
 	if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
-		pr_debug("bit_position: %d\n", mem->bit_pos);
+		n += scnprintf(msg + n, len - n, "bit_position: %d ",
+			       mem->bit_pos);
 	if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
-		pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id);
+		n += scnprintf(msg + n, len - n, "requestor_id: 0x%016llx ",
+			       mem->requestor_id);
 	if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
-		pr_debug("responder_id: 0x%016llx\n", mem->responder_id);
+		n += scnprintf(msg + n, len - n, "responder_id: 0x%016llx ",
+			       mem->responder_id);
 	if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
-		pr_debug("target_id: 0x%016llx\n", mem->target_id);
+		scnprintf(msg + n, len - n, "target_id: 0x%016llx ",
+			  mem->target_id);
+
+	msg[n] = '\0';
+	return n;
+}
+
+static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
+{
+	u32 len, n;
+	const char *bank = NULL, *device = NULL;
+
+	if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
+		return 0;
+
+	n = 0;
+	len = CPER_REC_LEN - 1;
+	dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
+	if (bank && device)
+		n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
+	else
+		n = snprintf(msg, len,
+			     "DIMM location: not present. DMI handle: 0x%.4x ",
+			     mem->mem_dev_handle);
+
+	msg[n] = '\0';
+	return n;
+}
+
+void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
+		       struct cper_mem_err_compact *cmem)
+{
+	cmem->validation_bits = mem->validation_bits;
+	cmem->node = mem->node;
+	cmem->card = mem->card;
+	cmem->module = mem->module;
+	cmem->bank = mem->bank;
+	cmem->device = mem->device;
+	cmem->row = mem->row;
+	cmem->column = mem->column;
+	cmem->bit_pos = mem->bit_pos;
+	cmem->requestor_id = mem->requestor_id;
+	cmem->responder_id = mem->responder_id;
+	cmem->target_id = mem->target_id;
+	cmem->rank = mem->rank;
+	cmem->mem_array_handle = mem->mem_array_handle;
+	cmem->mem_dev_handle = mem->mem_dev_handle;
+}
+
+const char *cper_mem_err_unpack(struct trace_seq *p,
+				struct cper_mem_err_compact *cmem)
+{
+	const char *ret = p->buffer + p->len;
+
+	if (cper_mem_err_location(cmem, rcd_decode_str))
+		trace_seq_printf(p, "%s", rcd_decode_str);
+	if (cper_dimm_err_location(cmem, rcd_decode_str))
+		trace_seq_printf(p, "%s", rcd_decode_str);
+	trace_seq_putc(p, '\0');
+
+	return ret;
+}
+
+static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+{
+	struct cper_mem_err_compact cmem;
+
+	if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
+		printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
+	if (mem->validation_bits & CPER_MEM_VALID_PA)
+		printk("%s""physical_address: 0x%016llx\n",
+		       pfx, mem->physical_addr);
+	if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
+		printk("%s""physical_address_mask: 0x%016llx\n",
+		       pfx, mem->physical_addr_mask);
+	cper_mem_err_pack(mem, &cmem);
+	if (cper_mem_err_location(&cmem, rcd_decode_str))
+		printk("%s%s\n", pfx, rcd_decode_str);
 	if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
 		u8 etype = mem->error_type;
 		printk("%s""error_type: %d, %s\n", pfx, etype,
-		       etype < ARRAY_SIZE(cper_mem_err_type_strs) ?
-		       cper_mem_err_type_strs[etype] : "unknown");
-	}
-	if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
-		const char *bank = NULL, *device = NULL;
-		dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
-		if (bank != NULL && device != NULL)
-			printk("%s""DIMM location: %s %s", pfx, bank, device);
-		else
-			printk("%s""DIMM DMI handle: 0x%.4x",
-			       pfx, mem->mem_dev_handle);
+		       cper_mem_err_type_str(etype));
 	}
+	if (cper_dimm_err_location(&cmem, rcd_decode_str))
+		printk("%s%s\n", pfx, rcd_decode_str);
 }
 
-static const char *cper_pcie_port_type_strs[] = {
+static const char * const pcie_port_type_strs[] = {
 	"PCIe end point",
 	"legacy PCI end point",
 	"unknown",
@@ -262,12 +344,12 @@ static const char *cper_pcie_port_type_s
 };
 
 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
-			    const struct acpi_generic_data *gdata)
+			    const struct acpi_hest_generic_data *gdata)
 {
 	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
 		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
-		       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
-		       cper_pcie_port_type_strs[pcie->port_type] : "unknown");
+		       pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ?
+		       pcie_port_type_strs[pcie->port_type] : "unknown");
 	if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
 		printk("%s""version: %d.%d\n", pfx,
 		       pcie->version.major, pcie->version.minor);
@@ -298,7 +380,7 @@ static void cper_print_pcie(const char *
 }
 
 static void cper_estatus_print_section(
-	const char *pfx, const struct acpi_generic_data *gdata, int sec_no)
+	const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
 {
 	uuid_le *sec_type = (uuid_le *)gdata->section_type;
 	__u16 severity;
@@ -344,9 +426,9 @@ err_section_too_small:
 }
 
 void cper_estatus_print(const char *pfx,
-			const struct acpi_generic_status *estatus)
+			const struct acpi_hest_generic_status *estatus)
 {
-	struct acpi_generic_data *gdata;
+	struct acpi_hest_generic_data *gdata;
 	unsigned int data_len, gedata_len;
 	int sec_no = 0;
 	char newpfx[64];
@@ -359,7 +441,7 @@ void cper_estatus_print(const char *pfx,
 		       "and requires no further action");
 	printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
 	data_len = estatus->data_length;
-	gdata = (struct acpi_generic_data *)(estatus + 1);
+	gdata = (struct acpi_hest_generic_data *)(estatus + 1);
 	snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
 	while (data_len >= sizeof(*gdata)) {
 		gedata_len = gdata->error_data_length;
@@ -371,10 +453,10 @@ void cper_estatus_print(const char *pfx,
 }
 EXPORT_SYMBOL_GPL(cper_estatus_print);
 
-int cper_estatus_check_header(const struct acpi_generic_status *estatus)
+int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus)
 {
 	if (estatus->data_length &&
-	    estatus->data_length < sizeof(struct acpi_generic_data))
+	    estatus->data_length < sizeof(struct acpi_hest_generic_data))
 		return -EINVAL;
 	if (estatus->raw_data_length &&
 	    estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
@@ -384,9 +466,9 @@ int cper_estatus_check_header(const stru
 }
 EXPORT_SYMBOL_GPL(cper_estatus_check_header);
 
-int cper_estatus_check(const struct acpi_generic_status *estatus)
+int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
 {
-	struct acpi_generic_data *gdata;
+	struct acpi_hest_generic_data *gdata;
 	unsigned int data_len, gedata_len;
 	int rc;
 
@@ -394,7 +476,7 @@ int cper_estatus_check(const struct acpi
 	if (rc)
 		return rc;
 	data_len = estatus->data_length;
-	gdata = (struct acpi_generic_data *)(estatus + 1);
+	gdata = (struct acpi_hest_generic_data *)(estatus + 1);
 	while (data_len >= sizeof(*gdata)) {
 		gedata_len = gdata->error_data_length;
 		if (gedata_len > data_len - sizeof(*gdata))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/efi.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efi.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/efi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 struct efi __read_mostly efi = {
 	.mps        = EFI_INVALID_TABLE_ADDR,
@@ -104,16 +105,19 @@ static struct attribute *efi_subsys_attr
 static umode_t efi_attr_is_visible(struct kobject *kobj,
 				   struct attribute *attr, int n)
 {
-	umode_t mode = attr->mode;
-
-	if (attr == &efi_attr_fw_vendor.attr)
-		return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
-	else if (attr == &efi_attr_runtime.attr)
-		return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
-	else if (attr == &efi_attr_config_table.attr)
-		return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
+	if (attr == &efi_attr_fw_vendor.attr) {
+		if (efi_enabled(EFI_PARAVIRT) ||
+				efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
+			return 0;
+	} else if (attr == &efi_attr_runtime.attr) {
+		if (efi.runtime == EFI_INVALID_TABLE_ADDR)
+			return 0;
+	} else if (attr == &efi_attr_config_table.attr) {
+		if (efi.config_table == EFI_INVALID_TABLE_ADDR)
+			return 0;
+	}
 
-	return mode;
+	return attr->mode;
 }
 
 static struct attribute_group efi_subsys_attr_group = {
@@ -298,7 +302,7 @@ int __init efi_config_init(efi_config_ta
 			if (table64 >> 32) {
 				pr_cont("\n");
 				pr_err("Table located above 4GB, disabling EFI.\n");
-				early_iounmap(config_tables,
+				early_memunmap(config_tables,
 					       efi.systab->nr_tables * sz);
 				return -EINVAL;
 			}
@@ -314,13 +318,27 @@ int __init efi_config_init(efi_config_ta
 		tablep += sz;
 	}
 	pr_cont("\n");
-	early_iounmap(config_tables, efi.systab->nr_tables * sz);
+	early_memunmap(config_tables, efi.systab->nr_tables * sz);
 
 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
 	return 0;
 }
 
+#ifdef CONFIG_EFI_VARS_MODULE
+static int __init efi_load_efivars(void)
+{
+	struct platform_device *pdev;
+
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
+		return 0;
+
+	pdev = platform_device_register_simple("efivars", 0, NULL, 0);
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+}
+device_initcall(efi_load_efivars);
+#endif
+
 #ifdef CONFIG_EFI_PARAMS_FROM_FDT
 
 #define UEFI_PARAM(name, prop, field)			   \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/efi-stub-helper.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efi-stub-helper.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/efi-stub-helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efi-stub-helper.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,634 +0,0 @@
-/*
- * Helper functions used by the EFI stub on multiple
- * architectures. This should be #included by the EFI stub
- * implementation files.
- *
- * Copyright 2011 Intel Corporation; author Matt Fleming
- *
- * This file is part of the Linux kernel, and is made available
- * under the terms of the GNU General Public License version 2.
- *
- */
-#define EFI_READ_CHUNK_SIZE	(1024 * 1024)
-
-/* error code which can't be mistaken for valid address */
-#define EFI_ERROR	(~0UL)
-
-
-struct file_info {
-	efi_file_handle_t *handle;
-	u64 size;
-};
-
-static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
-{
-	char *s8;
-
-	for (s8 = str; *s8; s8++) {
-		efi_char16_t ch[2] = { 0 };
-
-		ch[0] = *s8;
-		if (*s8 == '\n') {
-			efi_char16_t nl[2] = { '\r', 0 };
-			efi_char16_printk(sys_table_arg, nl);
-		}
-
-		efi_char16_printk(sys_table_arg, ch);
-	}
-}
-
-#define pr_efi(sys_table, msg)     efi_printk(sys_table, "EFI stub: "msg)
-#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
-
-
-static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
-				       efi_memory_desc_t **map,
-				       unsigned long *map_size,
-				       unsigned long *desc_size,
-				       u32 *desc_ver,
-				       unsigned long *key_ptr)
-{
-	efi_memory_desc_t *m = NULL;
-	efi_status_t status;
-	unsigned long key;
-	u32 desc_version;
-
-	*map_size = sizeof(*m) * 32;
-again:
-	/*
-	 * Add an additional efi_memory_desc_t because we're doing an
-	 * allocation which may be in a new descriptor region.
-	 */
-	*map_size += sizeof(*m);
-	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-				*map_size, (void **)&m);
-	if (status != EFI_SUCCESS)
-		goto fail;
-
-	*desc_size = 0;
-	key = 0;
-	status = efi_call_early(get_memory_map, map_size, m,
-				&key, desc_size, &desc_version);
-	if (status == EFI_BUFFER_TOO_SMALL) {
-		efi_call_early(free_pool, m);
-		goto again;
-	}
-
-	if (status != EFI_SUCCESS)
-		efi_call_early(free_pool, m);
-
-	if (key_ptr && status == EFI_SUCCESS)
-		*key_ptr = key;
-	if (desc_ver && status == EFI_SUCCESS)
-		*desc_ver = desc_version;
-
-fail:
-	*map = m;
-	return status;
-}
-
-
-static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg)
-{
-	efi_status_t status;
-	unsigned long map_size;
-	unsigned long membase  = EFI_ERROR;
-	struct efi_memory_map map;
-	efi_memory_desc_t *md;
-
-	status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map,
-				    &map_size, &map.desc_size, NULL, NULL);
-	if (status != EFI_SUCCESS)
-		return membase;
-
-	map.map_end = map.map + map_size;
-
-	for_each_efi_memory_desc(&map, md)
-		if (md->attribute & EFI_MEMORY_WB)
-			if (membase > md->phys_addr)
-				membase = md->phys_addr;
-
-	efi_call_early(free_pool, map.map);
-
-	return membase;
-}
-
-/*
- * Allocate at the highest possible address that is not above 'max'.
- */
-static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
-			       unsigned long size, unsigned long align,
-			       unsigned long *addr, unsigned long max)
-{
-	unsigned long map_size, desc_size;
-	efi_memory_desc_t *map;
-	efi_status_t status;
-	unsigned long nr_pages;
-	u64 max_addr = 0;
-	int i;
-
-	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
-				    NULL, NULL);
-	if (status != EFI_SUCCESS)
-		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.
-	 */
-	if (align < EFI_PAGE_SIZE)
-		align = EFI_PAGE_SIZE;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-again:
-	for (i = 0; i < map_size / desc_size; i++) {
-		efi_memory_desc_t *desc;
-		unsigned long m = (unsigned long)map;
-		u64 start, end;
-
-		desc = (efi_memory_desc_t *)(m + (i * desc_size));
-		if (desc->type != EFI_CONVENTIONAL_MEMORY)
-			continue;
-
-		if (desc->num_pages < nr_pages)
-			continue;
-
-		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
-
-		if ((start + size) > end || (start + size) > max)
-			continue;
-
-		if (end - size > max)
-			end = max;
-
-		if (round_down(end - size, align) < start)
-			continue;
-
-		start = round_down(end - size, align);
-
-		/*
-		 * Don't allocate at 0x0. It will confuse code that
-		 * checks pointers against NULL.
-		 */
-		if (start == 0x0)
-			continue;
-
-		if (start > max_addr)
-			max_addr = start;
-	}
-
-	if (!max_addr)
-		status = EFI_NOT_FOUND;
-	else {
-		status = efi_call_early(allocate_pages,
-					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-					nr_pages, &max_addr);
-		if (status != EFI_SUCCESS) {
-			max = max_addr;
-			max_addr = 0;
-			goto again;
-		}
-
-		*addr = max_addr;
-	}
-
-	efi_call_early(free_pool, map);
-fail:
-	return status;
-}
-
-/*
- * Allocate at the lowest possible address.
- */
-static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
-			      unsigned long size, unsigned long align,
-			      unsigned long *addr)
-{
-	unsigned long map_size, desc_size;
-	efi_memory_desc_t *map;
-	efi_status_t status;
-	unsigned long nr_pages;
-	int i;
-
-	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
-				    NULL, NULL);
-	if (status != EFI_SUCCESS)
-		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.
-	 */
-	if (align < EFI_PAGE_SIZE)
-		align = EFI_PAGE_SIZE;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	for (i = 0; i < map_size / desc_size; i++) {
-		efi_memory_desc_t *desc;
-		unsigned long m = (unsigned long)map;
-		u64 start, end;
-
-		desc = (efi_memory_desc_t *)(m + (i * desc_size));
-
-		if (desc->type != EFI_CONVENTIONAL_MEMORY)
-			continue;
-
-		if (desc->num_pages < nr_pages)
-			continue;
-
-		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
-
-		/*
-		 * Don't allocate at 0x0. It will confuse code that
-		 * checks pointers against NULL. Skip the first 8
-		 * bytes so we start at a nice even number.
-		 */
-		if (start == 0x0)
-			start += 8;
-
-		start = round_up(start, align);
-		if ((start + size) > end)
-			continue;
-
-		status = efi_call_early(allocate_pages,
-					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-					nr_pages, &start);
-		if (status == EFI_SUCCESS) {
-			*addr = start;
-			break;
-		}
-	}
-
-	if (i == map_size / desc_size)
-		status = EFI_NOT_FOUND;
-
-	efi_call_early(free_pool, map);
-fail:
-	return status;
-}
-
-static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
-		     unsigned long addr)
-{
-	unsigned long nr_pages;
-
-	if (!size)
-		return;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	efi_call_early(free_pages, addr, nr_pages);
-}
-
-
-/*
- * Check the cmdline for a LILO-style file= arguments.
- *
- * We only support loading a file from the same filesystem as
- * the kernel image.
- */
-static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
-					 efi_loaded_image_t *image,
-					 char *cmd_line, char *option_string,
-					 unsigned long max_addr,
-					 unsigned long *load_addr,
-					 unsigned long *load_size)
-{
-	struct file_info *files;
-	unsigned long file_addr;
-	u64 file_size_total;
-	efi_file_handle_t *fh = NULL;
-	efi_status_t status;
-	int nr_files;
-	char *str;
-	int i, j, k;
-
-	file_addr = 0;
-	file_size_total = 0;
-
-	str = cmd_line;
-
-	j = 0;			/* See close_handles */
-
-	if (!load_addr || !load_size)
-		return EFI_INVALID_PARAMETER;
-
-	*load_addr = 0;
-	*load_size = 0;
-
-	if (!str || !*str)
-		return EFI_SUCCESS;
-
-	for (nr_files = 0; *str; nr_files++) {
-		str = strstr(str, option_string);
-		if (!str)
-			break;
-
-		str += strlen(option_string);
-
-		/* Skip any leading slashes */
-		while (*str == '/' || *str == '\\')
-			str++;
-
-		while (*str && *str != ' ' && *str != '\n')
-			str++;
-	}
-
-	if (!nr_files)
-		return EFI_SUCCESS;
-
-	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-				nr_files * sizeof(*files), (void **)&files);
-	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg, "Failed to alloc mem for file handle list\n");
-		goto fail;
-	}
-
-	str = cmd_line;
-	for (i = 0; i < nr_files; i++) {
-		struct file_info *file;
-		efi_char16_t filename_16[256];
-		efi_char16_t *p;
-
-		str = strstr(str, option_string);
-		if (!str)
-			break;
-
-		str += strlen(option_string);
-
-		file = &files[i];
-		p = filename_16;
-
-		/* Skip any leading slashes */
-		while (*str == '/' || *str == '\\')
-			str++;
-
-		while (*str && *str != ' ' && *str != '\n') {
-			if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
-				break;
-
-			if (*str == '/') {
-				*p++ = '\\';
-				str++;
-			} else {
-				*p++ = *str++;
-			}
-		}
-
-		*p = '\0';
-
-		/* Only open the volume once. */
-		if (!i) {
-			status = efi_open_volume(sys_table_arg, image,
-						 (void **)&fh);
-			if (status != EFI_SUCCESS)
-				goto free_files;
-		}
-
-		status = efi_file_size(sys_table_arg, fh, filename_16,
-				       (void **)&file->handle, &file->size);
-		if (status != EFI_SUCCESS)
-			goto close_handles;
-
-		file_size_total += file->size;
-	}
-
-	if (file_size_total) {
-		unsigned long addr;
-
-		/*
-		 * Multiple files need to be at consecutive addresses in memory,
-		 * so allocate enough memory for all the files.  This is used
-		 * for loading multiple files.
-		 */
-		status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
-				    &file_addr, max_addr);
-		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table_arg, "Failed to alloc highmem for files\n");
-			goto close_handles;
-		}
-
-		/* We've run out of free low memory. */
-		if (file_addr > max_addr) {
-			pr_efi_err(sys_table_arg, "We've run out of free low memory\n");
-			status = EFI_INVALID_PARAMETER;
-			goto free_file_total;
-		}
-
-		addr = file_addr;
-		for (j = 0; j < nr_files; j++) {
-			unsigned long size;
-
-			size = files[j].size;
-			while (size) {
-				unsigned long chunksize;
-				if (size > EFI_READ_CHUNK_SIZE)
-					chunksize = EFI_READ_CHUNK_SIZE;
-				else
-					chunksize = size;
-
-				status = efi_file_read(files[j].handle,
-						       &chunksize,
-						       (void *)addr);
-				if (status != EFI_SUCCESS) {
-					pr_efi_err(sys_table_arg, "Failed to read file\n");
-					goto free_file_total;
-				}
-				addr += chunksize;
-				size -= chunksize;
-			}
-
-			efi_file_close(files[j].handle);
-		}
-
-	}
-
-	efi_call_early(free_pool, files);
-
-	*load_addr = file_addr;
-	*load_size = file_size_total;
-
-	return status;
-
-free_file_total:
-	efi_free(sys_table_arg, file_size_total, file_addr);
-
-close_handles:
-	for (k = j; k < i; k++)
-		efi_file_close(files[k].handle);
-free_files:
-	efi_call_early(free_pool, files);
-fail:
-	*load_addr = 0;
-	*load_size = 0;
-
-	return status;
-}
-/*
- * Relocate a kernel image, either compressed or uncompressed.
- * In the ARM64 case, all kernel images are currently
- * uncompressed, and as such when we relocate it we need to
- * allocate additional space for the BSS segment. Any low
- * memory that this function should avoid needs to be
- * unavailable in the EFI memory map, as if the preferred
- * address is not available the lowest available address will
- * be used.
- */
-static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
-					unsigned long *image_addr,
-					unsigned long image_size,
-					unsigned long alloc_size,
-					unsigned long preferred_addr,
-					unsigned long alignment)
-{
-	unsigned long cur_image_addr;
-	unsigned long new_addr = 0;
-	efi_status_t status;
-	unsigned long nr_pages;
-	efi_physical_addr_t efi_addr = preferred_addr;
-
-	if (!image_addr || !image_size || !alloc_size)
-		return EFI_INVALID_PARAMETER;
-	if (alloc_size < image_size)
-		return EFI_INVALID_PARAMETER;
-
-	cur_image_addr = *image_addr;
-
-	/*
-	 * The EFI firmware loader could have placed the kernel image
-	 * anywhere in memory, but the kernel has restrictions on the
-	 * max physical address it can run at.  Some architectures
-	 * also have a prefered address, so first try to relocate
-	 * to the preferred address.  If that fails, allocate as low
-	 * as possible while respecting the required alignment.
-	 */
-	nr_pages = round_up(alloc_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	status = efi_call_early(allocate_pages,
-				EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-				nr_pages, &efi_addr);
-	new_addr = efi_addr;
-	/*
-	 * If preferred address allocation failed allocate as low as
-	 * possible.
-	 */
-	if (status != EFI_SUCCESS) {
-		status = efi_low_alloc(sys_table_arg, alloc_size, alignment,
-				       &new_addr);
-	}
-	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg, "Failed to allocate usable memory for kernel.\n");
-		return status;
-	}
-
-	/*
-	 * We know source/dest won't overlap since both memory ranges
-	 * have been allocated by UEFI, so we can safely use memcpy.
-	 */
-	memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
-
-	/* Return the new address of the relocated image. */
-	*image_addr = new_addr;
-
-	return status;
-}
-
-/*
- * Get the number of UTF-8 bytes corresponding to an UTF-16 character.
- * This overestimates for surrogates, but that is okay.
- */
-static int efi_utf8_bytes(u16 c)
-{
-	return 1 + (c >= 0x80) + (c >= 0x800);
-}
-
-/*
- * Convert an UTF-16 string, not necessarily null terminated, to UTF-8.
- */
-static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
-{
-	unsigned int c;
-
-	while (n--) {
-		c = *src++;
-		if (n && c >= 0xd800 && c <= 0xdbff &&
-		    *src >= 0xdc00 && *src <= 0xdfff) {
-			c = 0x10000 + ((c & 0x3ff) << 10) + (*src & 0x3ff);
-			src++;
-			n--;
-		}
-		if (c >= 0xd800 && c <= 0xdfff)
-			c = 0xfffd; /* Unmatched surrogate */
-		if (c < 0x80) {
-			*dst++ = c;
-			continue;
-		}
-		if (c < 0x800) {
-			*dst++ = 0xc0 + (c >> 6);
-			goto t1;
-		}
-		if (c < 0x10000) {
-			*dst++ = 0xe0 + (c >> 12);
-			goto t2;
-		}
-		*dst++ = 0xf0 + (c >> 18);
-		*dst++ = 0x80 + ((c >> 12) & 0x3f);
-	t2:
-		*dst++ = 0x80 + ((c >> 6) & 0x3f);
-	t1:
-		*dst++ = 0x80 + (c & 0x3f);
-	}
-
-	return dst;
-}
-
-/*
- * Convert the unicode UEFI command line to ASCII to pass to kernel.
- * Size of memory allocated return in *cmd_line_len.
- * Returns NULL on error.
- */
-static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
-				 efi_loaded_image_t *image,
-				 int *cmd_line_len)
-{
-	const u16 *s2;
-	u8 *s1 = NULL;
-	unsigned long cmdline_addr = 0;
-	int load_options_chars = image->load_options_size / 2; /* UTF-16 */
-	const u16 *options = image->load_options;
-	int options_bytes = 0;  /* UTF-8 bytes */
-	int options_chars = 0;  /* UTF-16 chars */
-	efi_status_t status;
-	u16 zero = 0;
-
-	if (options) {
-		s2 = options;
-		while (*s2 && *s2 != '\n'
-		       && options_chars < load_options_chars) {
-			options_bytes += efi_utf8_bytes(*s2++);
-			options_chars++;
-		}
-	}
-
-	if (!options_chars) {
-		/* No command line options, so return empty string*/
-		options = &zero;
-	}
-
-	options_bytes++;	/* NUL termination */
-
-	status = efi_low_alloc(sys_table_arg, options_bytes, 0, &cmdline_addr);
-	if (status != EFI_SUCCESS)
-		return NULL;
-
-	s1 = (u8 *)cmdline_addr;
-	s2 = (const u16 *)options;
-
-	s1 = efi_utf16_to_utf8(s1, s2, options_chars);
-	*s1 = '\0';
-
-	*cmd_line_len = options_bytes;
-	return (char *)cmdline_addr;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/efivars.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efivars.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/efivars.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/efivars.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@
 MODULE_DESCRIPTION("sysfs interface to EFI Variables");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(EFIVARS_VERSION);
+MODULE_ALIAS("platform:efivars");
 
 LIST_HEAD(efivar_sysfs_list);
 EXPORT_SYMBOL_GPL(efivar_sysfs_list);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/fdt.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/fdt.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/fdt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/fdt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,275 +0,0 @@
-/*
- * FDT related Helper functions used by the EFI stub on multiple
- * architectures. This should be #included by the EFI stub
- * implementation files.
- *
- * Copyright 2013 Linaro Limited; author Roy Franz
- *
- * This file is part of the Linux kernel, and is made available
- * under the terms of the GNU General Public License version 2.
- *
- */
-
-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,
-			       efi_memory_desc_t *memory_map,
-			       unsigned long map_size, unsigned long desc_size,
-			       u32 desc_ver)
-{
-	int node, prev;
-	int status;
-	u32 fdt_val32;
-	u64 fdt_val64;
-
-	/* Do some checks on provided FDT, if it exists*/
-	if (orig_fdt) {
-		if (fdt_check_header(orig_fdt)) {
-			pr_efi_err(sys_table, "Device Tree header not valid!\n");
-			return EFI_LOAD_ERROR;
-		}
-		/*
-		 * We don't get the size of the FDT if we get if from a
-		 * configuration table.
-		 */
-		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
-			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
-			return EFI_LOAD_ERROR;
-		}
-	}
-
-	if (orig_fdt)
-		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
-	else
-		status = fdt_create_empty_tree(fdt, new_fdt_size);
-
-	if (status != 0)
-		goto fdt_set_fail;
-
-	/*
-	 * Delete any memory nodes present. We must delete nodes which
-	 * early_init_dt_scan_memory may try to use.
-	 */
-	prev = 0;
-	for (;;) {
-		const char *type;
-		int len;
-
-		node = fdt_next_node(fdt, prev, NULL);
-		if (node < 0)
-			break;
-
-		type = fdt_getprop(fdt, node, "device_type", &len);
-		if (type && strncmp(type, "memory", len) == 0) {
-			fdt_del_node(fdt, node);
-			continue;
-		}
-
-		prev = node;
-	}
-
-	node = fdt_subnode_offset(fdt, 0, "chosen");
-	if (node < 0) {
-		node = fdt_add_subnode(fdt, 0, "chosen");
-		if (node < 0) {
-			status = node; /* node is error code when negative */
-			goto fdt_set_fail;
-		}
-	}
-
-	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
-		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
-				     strlen(cmdline_ptr) + 1);
-		if (status)
-			goto fdt_set_fail;
-	}
-
-	/* Set initrd address/end in device tree, if present */
-	if (initrd_size != 0) {
-		u64 initrd_image_end;
-		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
-
-		status = fdt_setprop(fdt, node, "linux,initrd-start",
-				     &initrd_image_start, sizeof(u64));
-		if (status)
-			goto fdt_set_fail;
-		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
-		status = fdt_setprop(fdt, node, "linux,initrd-end",
-				     &initrd_image_end, sizeof(u64));
-		if (status)
-			goto fdt_set_fail;
-	}
-
-	/* Add FDT entries for EFI runtime services in chosen node. */
-	node = fdt_subnode_offset(fdt, 0, "chosen");
-	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
-	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
-			     &fdt_val64, sizeof(fdt_val64));
-	if (status)
-		goto fdt_set_fail;
-
-	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
-	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);
-	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)
-		goto fdt_set_fail;
-
-	/*
-	 * Add kernel version banner so stub/kernel match can be
-	 * verified.
-	 */
-	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
-			     linux_banner);
-	if (status)
-		goto fdt_set_fail;
-
-	return EFI_SUCCESS;
-
-fdt_set_fail:
-	if (status == -FDT_ERR_NOSPACE)
-		return EFI_BUFFER_TOO_SMALL;
-
-	return EFI_LOAD_ERROR;
-}
-
-#ifndef EFI_FDT_ALIGN
-#define EFI_FDT_ALIGN EFI_PAGE_SIZE
-#endif
-
-/*
- * Allocate memory for a new FDT, then add EFI, commandline, and
- * initrd related fields to the FDT.  This routine increases the
- * FDT allocation size until the allocated memory is large
- * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
- * which are fixed at 4K bytes, so in most cases the first
- * allocation should succeed.
- * EFI boot services are exited at the end of this function.
- * There must be no allocations between the get_memory_map()
- * call and the exit_boot_services() call, so the exiting of
- * boot services is very tightly tied to the creation of the FDT
- * with the final memory map in it.
- */
-
-efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
-					    void *handle,
-					    unsigned long *new_fdt_addr,
-					    unsigned long max_addr,
-					    u64 initrd_addr, u64 initrd_size,
-					    char *cmdline_ptr,
-					    unsigned long fdt_addr,
-					    unsigned long fdt_size)
-{
-	unsigned long map_size, desc_size;
-	u32 desc_ver;
-	unsigned long mmap_key;
-	efi_memory_desc_t *memory_map;
-	unsigned long new_fdt_size;
-	efi_status_t status;
-
-	/*
-	 * Estimate size of new FDT, and allocate memory for it. We
-	 * will allocate a bigger buffer if this ends up being too
-	 * small, so a rough guess is OK here.
-	 */
-	new_fdt_size = fdt_size + EFI_PAGE_SIZE;
-	while (1) {
-		status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
-					new_fdt_addr, max_addr);
-		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
-			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, &memory_map, &map_size,
-					    &desc_size, &desc_ver, &mmap_key);
-		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);
-
-		/* Succeeding the first time is the expected case. */
-		if (status == EFI_SUCCESS)
-			break;
-
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			/*
-			 * 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.
-			 */
-			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 constuct new device tree.\n");
-			goto fail_free_mmap;
-		}
-	}
-
-	/* Now we are ready to exit_boot_services.*/
-	status = sys_table->boottime->exit_boot_services(handle, mmap_key);
-
-
-	if (status == EFI_SUCCESS)
-		return status;
-
-	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);
-
-fail:
-	return EFI_LOAD_ERROR;
-}
-
-static void *get_fdt(efi_system_table_t *sys_table)
-{
-	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
-	efi_config_table_t *tables;
-	void *fdt;
-	int i;
-
-	tables = (efi_config_table_t *) sys_table->tables;
-	fdt = NULL;
-
-	for (i = 0; i < sys_table->nr_tables; i++)
-		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
-			fdt = (void *) tables[i].table;
-			break;
-	 }
-
-	return fdt;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/Kconfig linux-libre-3.17-rc7-gnu/drivers/firmware/efi/Kconfig
--- linux-libre-3.16-gnu/drivers/firmware/efi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -54,6 +54,12 @@ config EFI_PARAMS_FROM_FDT
 	  the EFI runtime support gets system table address, memory
           map address, and other parameters from the device tree.
 
+config EFI_RUNTIME_WRAPPERS
+	bool
+
+config EFI_ARMSTUB
+	bool
+
 endmenu
 
 config UEFI_CPER
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/libstub/arm-stub.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/arm-stub.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/libstub/arm-stub.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/arm-stub.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+ * EFI stub implementation that is shared by arm and arm64 architectures.
+ * This should be #included by the EFI stub implementation files.
+ *
+ * Copyright (C) 2013,2014 Linaro Limited
+ *     Roy Franz <roy.franz@linaro.org
+ * Copyright (C) 2013 Red Hat, Inc.
+ *     Mark Salter <msalter@redhat.com>
+ *
+ * This file is part of the Linux kernel, and is made available under the
+ * terms of the GNU General Public License version 2.
+ *
+ */
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
+{
+	static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
+	static efi_char16_t const var_name[] __initconst = {
+		'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
+
+	efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
+	unsigned long size = sizeof(u8);
+	efi_status_t status;
+	u8 val;
+
+	status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid,
+			  NULL, &size, &val);
+
+	switch (status) {
+	case EFI_SUCCESS:
+		return val;
+	case EFI_NOT_FOUND:
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
+			     void *__image, void **__fh)
+{
+	efi_file_io_interface_t *io;
+	efi_loaded_image_t *image = __image;
+	efi_file_handle_t *fh;
+	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+	efi_status_t status;
+	void *handle = (void *)(unsigned long)image->device_handle;
+
+	status = sys_table_arg->boottime->handle_protocol(handle,
+				 &fs_proto, (void **)&io);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+		return status;
+	}
+
+	status = io->open_volume(io, &fh);
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to open volume\n");
+
+	*__fh = fh;
+	return status;
+}
+
+efi_status_t efi_file_close(void *handle)
+{
+	efi_file_handle_t *fh = handle;
+
+	return fh->close(handle);
+}
+
+efi_status_t
+efi_file_read(void *handle, unsigned long *size, void *addr)
+{
+	efi_file_handle_t *fh = handle;
+
+	return fh->read(handle, size, addr);
+}
+
+
+efi_status_t
+efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
+	      efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+	efi_file_handle_t *h, *fh = __fh;
+	efi_file_info_t *info;
+	efi_status_t status;
+	efi_guid_t info_guid = EFI_FILE_INFO_ID;
+	unsigned long info_sz;
+
+	status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to open file: ");
+		efi_char16_printk(sys_table_arg, filename_16);
+		efi_printk(sys_table_arg, "\n");
+		return status;
+	}
+
+	*handle = h;
+
+	info_sz = 0;
+	status = h->get_info(h, &info_guid, &info_sz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		efi_printk(sys_table_arg, "Failed to get file info size\n");
+		return status;
+	}
+
+grow:
+	status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA,
+				 info_sz, (void **)&info);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+		return status;
+	}
+
+	status = h->get_info(h, &info_guid, &info_sz,
+						   info);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		sys_table_arg->boottime->free_pool(info);
+		goto grow;
+	}
+
+	*file_sz = info->file_size;
+	sys_table_arg->boottime->free_pool(info);
+
+	if (status != EFI_SUCCESS)
+		efi_printk(sys_table_arg, "Failed to get initrd info\n");
+
+	return status;
+}
+
+
+
+void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str)
+{
+	struct efi_simple_text_output_protocol *out;
+
+	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
+	out->output_string(out, str);
+}
+
+
+/*
+ * This function handles the architcture specific differences between arm and
+ * arm64 regarding where the kernel image must be loaded and any memory that
+ * must be reserved. On failure it is required to free all
+ * all allocations it has made.
+ */
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+				 unsigned long *image_addr,
+				 unsigned long *image_size,
+				 unsigned long *reserve_addr,
+				 unsigned long *reserve_size,
+				 unsigned long dram_base,
+				 efi_loaded_image_t *image);
+/*
+ * EFI entry point for the arm/arm64 EFI stubs.  This is the entrypoint
+ * that is described in the PE/COFF header.  Most of the code is the same
+ * for both archictectures, with the arch-specific code provided in the
+ * handle_kernel_image() function.
+ */
+unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
+			       unsigned long *image_addr)
+{
+	efi_loaded_image_t *image;
+	efi_status_t status;
+	unsigned long image_size = 0;
+	unsigned long dram_base;
+	/* addr/point and size pairs for memory management*/
+	unsigned long initrd_addr;
+	u64 initrd_size = 0;
+	unsigned long fdt_addr = 0;  /* Original DTB */
+	u64 fdt_size = 0;  /* We don't get size from configuration table */
+	char *cmdline_ptr = NULL;
+	int cmdline_size = 0;
+	unsigned long new_fdt_addr;
+	efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+	unsigned long reserve_addr = 0;
+	unsigned long reserve_size = 0;
+
+	/* Check if we were booted by the EFI firmware */
+	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+		goto fail;
+
+	pr_efi(sys_table, "Booting Linux Kernel...\n");
+
+	/*
+	 * Get a handle to the loaded image protocol.  This is used to get
+	 * information about the running image, such as size and the command
+	 * line.
+	 */
+	status = sys_table->boottime->handle_protocol(handle,
+					&loaded_image_proto, (void *)&image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
+		goto fail;
+	}
+
+	dram_base = get_dram_base(sys_table);
+	if (dram_base == EFI_ERROR) {
+		pr_efi_err(sys_table, "Failed to find DRAM base\n");
+		goto fail;
+	}
+	status = handle_kernel_image(sys_table, image_addr, &image_size,
+				     &reserve_addr,
+				     &reserve_size,
+				     dram_base, image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel\n");
+		goto fail;
+	}
+
+	/*
+	 * Get the command line from EFI, using the LOADED_IMAGE
+	 * protocol. We are going to copy the command line into the
+	 * device tree, so this can be allocated anywhere.
+	 */
+	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
+	if (!cmdline_ptr) {
+		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
+		goto fail_free_image;
+	}
+
+	/*
+	 * Unauthenticated device tree data is a security hazard, so
+	 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
+	 */
+	if (efi_secureboot_enabled(sys_table)) {
+		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
+	} else {
+		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+					      "dtb=",
+					      ~0UL, (unsigned long *)&fdt_addr,
+					      (unsigned long *)&fdt_size);
+
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Failed to load device tree!\n");
+			goto fail_free_cmdline;
+		}
+	}
+	if (!fdt_addr)
+		/* Look for a device tree configuration table entry. */
+		fdt_addr = (uintptr_t)get_fdt(sys_table);
+
+	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+				      "initrd=", dram_base + SZ_512M,
+				      (unsigned long *)&initrd_addr,
+				      (unsigned long *)&initrd_size);
+	if (status != EFI_SUCCESS)
+		pr_efi_err(sys_table, "Failed initrd from command line!\n");
+
+	new_fdt_addr = fdt_addr;
+	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
+				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
+				initrd_addr, initrd_size, cmdline_ptr,
+				fdt_addr, fdt_size);
+
+	/*
+	 * If all went well, we need to return the FDT address to the
+	 * calling function so it can be passed to kernel as part of
+	 * the kernel boot protocol.
+	 */
+	if (status == EFI_SUCCESS)
+		return new_fdt_addr;
+
+	pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
+
+	efi_free(sys_table, initrd_size, initrd_addr);
+	efi_free(sys_table, fdt_size, fdt_addr);
+
+fail_free_cmdline:
+	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
+
+fail_free_image:
+	efi_free(sys_table, image_size, *image_addr);
+	efi_free(sys_table, reserve_size, reserve_addr);
+fail:
+	return EFI_ERROR;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/libstub/efistub.h linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/efistub.h
--- linux-libre-3.16-gnu/drivers/firmware/efi/libstub/efistub.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/efistub.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+
+#ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+
+/* error code which can't be mistaken for valid address */
+#define EFI_ERROR	(~0UL)
+
+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,
+			     void **__fh);
+
+efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
+			   efi_char16_t *filename_16, void **handle,
+			   u64 *file_sz);
+
+efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr);
+
+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,
+					    unsigned long max_addr,
+					    u64 initrd_addr, u64 initrd_size,
+					    char *cmdline_ptr,
+					    unsigned long fdt_addr,
+					    unsigned long fdt_size);
+
+void *get_fdt(efi_system_table_t *sys_table);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,632 @@
+/*
+ * Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2011 Intel Corporation; author Matt Fleming
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+#define EFI_READ_CHUNK_SIZE	(1024 * 1024)
+
+struct file_info {
+	efi_file_handle_t *handle;
+	u64 size;
+};
+
+void efi_printk(efi_system_table_t *sys_table_arg, char *str)
+{
+	char *s8;
+
+	for (s8 = str; *s8; s8++) {
+		efi_char16_t ch[2] = { 0 };
+
+		ch[0] = *s8;
+		if (*s8 == '\n') {
+			efi_char16_t nl[2] = { '\r', 0 };
+			efi_char16_printk(sys_table_arg, nl);
+		}
+
+		efi_char16_printk(sys_table_arg, ch);
+	}
+}
+
+efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
+				efi_memory_desc_t **map,
+				unsigned long *map_size,
+				unsigned long *desc_size,
+				u32 *desc_ver,
+				unsigned long *key_ptr)
+{
+	efi_memory_desc_t *m = NULL;
+	efi_status_t status;
+	unsigned long key;
+	u32 desc_version;
+
+	*map_size = sizeof(*m) * 32;
+again:
+	/*
+	 * Add an additional efi_memory_desc_t because we're doing an
+	 * allocation which may be in a new descriptor region.
+	 */
+	*map_size += sizeof(*m);
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+				*map_size, (void **)&m);
+	if (status != EFI_SUCCESS)
+		goto fail;
+
+	*desc_size = 0;
+	key = 0;
+	status = efi_call_early(get_memory_map, map_size, m,
+				&key, desc_size, &desc_version);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		efi_call_early(free_pool, m);
+		goto again;
+	}
+
+	if (status != EFI_SUCCESS)
+		efi_call_early(free_pool, m);
+
+	if (key_ptr && status == EFI_SUCCESS)
+		*key_ptr = key;
+	if (desc_ver && status == EFI_SUCCESS)
+		*desc_ver = desc_version;
+
+fail:
+	*map = m;
+	return status;
+}
+
+
+unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg)
+{
+	efi_status_t status;
+	unsigned long map_size;
+	unsigned long membase  = EFI_ERROR;
+	struct efi_memory_map map;
+	efi_memory_desc_t *md;
+
+	status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map,
+				    &map_size, &map.desc_size, NULL, NULL);
+	if (status != EFI_SUCCESS)
+		return membase;
+
+	map.map_end = map.map + map_size;
+
+	for_each_efi_memory_desc(&map, md)
+		if (md->attribute & EFI_MEMORY_WB)
+			if (membase > md->phys_addr)
+				membase = md->phys_addr;
+
+	efi_call_early(free_pool, map.map);
+
+	return membase;
+}
+
+/*
+ * Allocate at the highest possible address that is not above 'max'.
+ */
+efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
+			    unsigned long size, unsigned long align,
+			    unsigned long *addr, unsigned long max)
+{
+	unsigned long map_size, desc_size;
+	efi_memory_desc_t *map;
+	efi_status_t status;
+	unsigned long nr_pages;
+	u64 max_addr = 0;
+	int i;
+
+	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
+				    NULL, NULL);
+	if (status != EFI_SUCCESS)
+		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.
+	 */
+	if (align < EFI_PAGE_SIZE)
+		align = EFI_PAGE_SIZE;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+again:
+	for (i = 0; i < map_size / desc_size; i++) {
+		efi_memory_desc_t *desc;
+		unsigned long m = (unsigned long)map;
+		u64 start, end;
+
+		desc = (efi_memory_desc_t *)(m + (i * desc_size));
+		if (desc->type != EFI_CONVENTIONAL_MEMORY)
+			continue;
+
+		if (desc->num_pages < nr_pages)
+			continue;
+
+		start = desc->phys_addr;
+		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+
+		if ((start + size) > end || (start + size) > max)
+			continue;
+
+		if (end - size > max)
+			end = max;
+
+		if (round_down(end - size, align) < start)
+			continue;
+
+		start = round_down(end - size, align);
+
+		/*
+		 * Don't allocate at 0x0. It will confuse code that
+		 * checks pointers against NULL.
+		 */
+		if (start == 0x0)
+			continue;
+
+		if (start > max_addr)
+			max_addr = start;
+	}
+
+	if (!max_addr)
+		status = EFI_NOT_FOUND;
+	else {
+		status = efi_call_early(allocate_pages,
+					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+					nr_pages, &max_addr);
+		if (status != EFI_SUCCESS) {
+			max = max_addr;
+			max_addr = 0;
+			goto again;
+		}
+
+		*addr = max_addr;
+	}
+
+	efi_call_early(free_pool, map);
+fail:
+	return status;
+}
+
+/*
+ * Allocate at the lowest possible address.
+ */
+efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
+			   unsigned long size, unsigned long align,
+			   unsigned long *addr)
+{
+	unsigned long map_size, desc_size;
+	efi_memory_desc_t *map;
+	efi_status_t status;
+	unsigned long nr_pages;
+	int i;
+
+	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
+				    NULL, NULL);
+	if (status != EFI_SUCCESS)
+		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.
+	 */
+	if (align < EFI_PAGE_SIZE)
+		align = EFI_PAGE_SIZE;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	for (i = 0; i < map_size / desc_size; i++) {
+		efi_memory_desc_t *desc;
+		unsigned long m = (unsigned long)map;
+		u64 start, end;
+
+		desc = (efi_memory_desc_t *)(m + (i * desc_size));
+
+		if (desc->type != EFI_CONVENTIONAL_MEMORY)
+			continue;
+
+		if (desc->num_pages < nr_pages)
+			continue;
+
+		start = desc->phys_addr;
+		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+
+		/*
+		 * Don't allocate at 0x0. It will confuse code that
+		 * checks pointers against NULL. Skip the first 8
+		 * bytes so we start at a nice even number.
+		 */
+		if (start == 0x0)
+			start += 8;
+
+		start = round_up(start, align);
+		if ((start + size) > end)
+			continue;
+
+		status = efi_call_early(allocate_pages,
+					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+					nr_pages, &start);
+		if (status == EFI_SUCCESS) {
+			*addr = start;
+			break;
+		}
+	}
+
+	if (i == map_size / desc_size)
+		status = EFI_NOT_FOUND;
+
+	efi_call_early(free_pool, map);
+fail:
+	return status;
+}
+
+void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
+	      unsigned long addr)
+{
+	unsigned long nr_pages;
+
+	if (!size)
+		return;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	efi_call_early(free_pages, addr, nr_pages);
+}
+
+
+/*
+ * Check the cmdline for a LILO-style file= arguments.
+ *
+ * We only support loading a file from the same filesystem as
+ * the kernel image.
+ */
+efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
+				  efi_loaded_image_t *image,
+				  char *cmd_line, char *option_string,
+				  unsigned long max_addr,
+				  unsigned long *load_addr,
+				  unsigned long *load_size)
+{
+	struct file_info *files;
+	unsigned long file_addr;
+	u64 file_size_total;
+	efi_file_handle_t *fh = NULL;
+	efi_status_t status;
+	int nr_files;
+	char *str;
+	int i, j, k;
+
+	file_addr = 0;
+	file_size_total = 0;
+
+	str = cmd_line;
+
+	j = 0;			/* See close_handles */
+
+	if (!load_addr || !load_size)
+		return EFI_INVALID_PARAMETER;
+
+	*load_addr = 0;
+	*load_size = 0;
+
+	if (!str || !*str)
+		return EFI_SUCCESS;
+
+	for (nr_files = 0; *str; nr_files++) {
+		str = strstr(str, option_string);
+		if (!str)
+			break;
+
+		str += strlen(option_string);
+
+		/* Skip any leading slashes */
+		while (*str == '/' || *str == '\\')
+			str++;
+
+		while (*str && *str != ' ' && *str != '\n')
+			str++;
+	}
+
+	if (!nr_files)
+		return EFI_SUCCESS;
+
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+				nr_files * sizeof(*files), (void **)&files);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table_arg, "Failed to alloc mem for file handle list\n");
+		goto fail;
+	}
+
+	str = cmd_line;
+	for (i = 0; i < nr_files; i++) {
+		struct file_info *file;
+		efi_char16_t filename_16[256];
+		efi_char16_t *p;
+
+		str = strstr(str, option_string);
+		if (!str)
+			break;
+
+		str += strlen(option_string);
+
+		file = &files[i];
+		p = filename_16;
+
+		/* Skip any leading slashes */
+		while (*str == '/' || *str == '\\')
+			str++;
+
+		while (*str && *str != ' ' && *str != '\n') {
+			if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
+				break;
+
+			if (*str == '/') {
+				*p++ = '\\';
+				str++;
+			} else {
+				*p++ = *str++;
+			}
+		}
+
+		*p = '\0';
+
+		/* Only open the volume once. */
+		if (!i) {
+			status = efi_open_volume(sys_table_arg, image,
+						 (void **)&fh);
+			if (status != EFI_SUCCESS)
+				goto free_files;
+		}
+
+		status = efi_file_size(sys_table_arg, fh, filename_16,
+				       (void **)&file->handle, &file->size);
+		if (status != EFI_SUCCESS)
+			goto close_handles;
+
+		file_size_total += file->size;
+	}
+
+	if (file_size_total) {
+		unsigned long addr;
+
+		/*
+		 * Multiple files need to be at consecutive addresses in memory,
+		 * so allocate enough memory for all the files.  This is used
+		 * for loading multiple files.
+		 */
+		status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
+				    &file_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table_arg, "Failed to alloc highmem for files\n");
+			goto close_handles;
+		}
+
+		/* We've run out of free low memory. */
+		if (file_addr > max_addr) {
+			pr_efi_err(sys_table_arg, "We've run out of free low memory\n");
+			status = EFI_INVALID_PARAMETER;
+			goto free_file_total;
+		}
+
+		addr = file_addr;
+		for (j = 0; j < nr_files; j++) {
+			unsigned long size;
+
+			size = files[j].size;
+			while (size) {
+				unsigned long chunksize;
+				if (size > EFI_READ_CHUNK_SIZE)
+					chunksize = EFI_READ_CHUNK_SIZE;
+				else
+					chunksize = size;
+
+				status = efi_file_read(files[j].handle,
+						       &chunksize,
+						       (void *)addr);
+				if (status != EFI_SUCCESS) {
+					pr_efi_err(sys_table_arg, "Failed to read file\n");
+					goto free_file_total;
+				}
+				addr += chunksize;
+				size -= chunksize;
+			}
+
+			efi_file_close(files[j].handle);
+		}
+
+	}
+
+	efi_call_early(free_pool, files);
+
+	*load_addr = file_addr;
+	*load_size = file_size_total;
+
+	return status;
+
+free_file_total:
+	efi_free(sys_table_arg, file_size_total, file_addr);
+
+close_handles:
+	for (k = j; k < i; k++)
+		efi_file_close(files[k].handle);
+free_files:
+	efi_call_early(free_pool, files);
+fail:
+	*load_addr = 0;
+	*load_size = 0;
+
+	return status;
+}
+/*
+ * Relocate a kernel image, either compressed or uncompressed.
+ * In the ARM64 case, all kernel images are currently
+ * uncompressed, and as such when we relocate it we need to
+ * allocate additional space for the BSS segment. Any low
+ * memory that this function should avoid needs to be
+ * unavailable in the EFI memory map, as if the preferred
+ * address is not available the lowest available address will
+ * be used.
+ */
+efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
+				 unsigned long *image_addr,
+				 unsigned long image_size,
+				 unsigned long alloc_size,
+				 unsigned long preferred_addr,
+				 unsigned long alignment)
+{
+	unsigned long cur_image_addr;
+	unsigned long new_addr = 0;
+	efi_status_t status;
+	unsigned long nr_pages;
+	efi_physical_addr_t efi_addr = preferred_addr;
+
+	if (!image_addr || !image_size || !alloc_size)
+		return EFI_INVALID_PARAMETER;
+	if (alloc_size < image_size)
+		return EFI_INVALID_PARAMETER;
+
+	cur_image_addr = *image_addr;
+
+	/*
+	 * The EFI firmware loader could have placed the kernel image
+	 * anywhere in memory, but the kernel has restrictions on the
+	 * max physical address it can run at.  Some architectures
+	 * also have a prefered address, so first try to relocate
+	 * to the preferred address.  If that fails, allocate as low
+	 * as possible while respecting the required alignment.
+	 */
+	nr_pages = round_up(alloc_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	status = efi_call_early(allocate_pages,
+				EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+				nr_pages, &efi_addr);
+	new_addr = efi_addr;
+	/*
+	 * If preferred address allocation failed allocate as low as
+	 * possible.
+	 */
+	if (status != EFI_SUCCESS) {
+		status = efi_low_alloc(sys_table_arg, alloc_size, alignment,
+				       &new_addr);
+	}
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table_arg, "Failed to allocate usable memory for kernel.\n");
+		return status;
+	}
+
+	/*
+	 * We know source/dest won't overlap since both memory ranges
+	 * have been allocated by UEFI, so we can safely use memcpy.
+	 */
+	memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
+
+	/* Return the new address of the relocated image. */
+	*image_addr = new_addr;
+
+	return status;
+}
+
+/*
+ * Get the number of UTF-8 bytes corresponding to an UTF-16 character.
+ * This overestimates for surrogates, but that is okay.
+ */
+static int efi_utf8_bytes(u16 c)
+{
+	return 1 + (c >= 0x80) + (c >= 0x800);
+}
+
+/*
+ * Convert an UTF-16 string, not necessarily null terminated, to UTF-8.
+ */
+static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
+{
+	unsigned int c;
+
+	while (n--) {
+		c = *src++;
+		if (n && c >= 0xd800 && c <= 0xdbff &&
+		    *src >= 0xdc00 && *src <= 0xdfff) {
+			c = 0x10000 + ((c & 0x3ff) << 10) + (*src & 0x3ff);
+			src++;
+			n--;
+		}
+		if (c >= 0xd800 && c <= 0xdfff)
+			c = 0xfffd; /* Unmatched surrogate */
+		if (c < 0x80) {
+			*dst++ = c;
+			continue;
+		}
+		if (c < 0x800) {
+			*dst++ = 0xc0 + (c >> 6);
+			goto t1;
+		}
+		if (c < 0x10000) {
+			*dst++ = 0xe0 + (c >> 12);
+			goto t2;
+		}
+		*dst++ = 0xf0 + (c >> 18);
+		*dst++ = 0x80 + ((c >> 12) & 0x3f);
+	t2:
+		*dst++ = 0x80 + ((c >> 6) & 0x3f);
+	t1:
+		*dst++ = 0x80 + (c & 0x3f);
+	}
+
+	return dst;
+}
+
+/*
+ * Convert the unicode UEFI command line to ASCII to pass to kernel.
+ * Size of memory allocated return in *cmd_line_len.
+ * Returns NULL on error.
+ */
+char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
+			  efi_loaded_image_t *image,
+			  int *cmd_line_len)
+{
+	const u16 *s2;
+	u8 *s1 = NULL;
+	unsigned long cmdline_addr = 0;
+	int load_options_chars = image->load_options_size / 2; /* UTF-16 */
+	const u16 *options = image->load_options;
+	int options_bytes = 0;  /* UTF-8 bytes */
+	int options_chars = 0;  /* UTF-16 chars */
+	efi_status_t status;
+	u16 zero = 0;
+
+	if (options) {
+		s2 = options;
+		while (*s2 && *s2 != '\n'
+		       && options_chars < load_options_chars) {
+			options_bytes += efi_utf8_bytes(*s2++);
+			options_chars++;
+		}
+	}
+
+	if (!options_chars) {
+		/* No command line options, so return empty string*/
+		options = &zero;
+	}
+
+	options_bytes++;	/* NUL termination */
+
+	status = efi_low_alloc(sys_table_arg, options_bytes, 0, &cmdline_addr);
+	if (status != EFI_SUCCESS)
+		return NULL;
+
+	s1 = (u8 *)cmdline_addr;
+	s2 = (const u16 *)options;
+
+	s1 = efi_utf16_to_utf8(s1, s2, options_chars);
+	*s1 = '\0';
+
+	*cmd_line_len = options_bytes;
+	return (char *)cmdline_addr;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/libstub/fdt.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/fdt.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/libstub/fdt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/fdt.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,287 @@
+/*
+ * FDT related Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2013 Linaro Limited; author Roy Franz
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+#include <asm/efi.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)
+{
+	int node, prev, num_rsv;
+	int status;
+	u32 fdt_val32;
+	u64 fdt_val64;
+
+	/* Do some checks on provided FDT, if it exists*/
+	if (orig_fdt) {
+		if (fdt_check_header(orig_fdt)) {
+			pr_efi_err(sys_table, "Device Tree header not valid!\n");
+			return EFI_LOAD_ERROR;
+		}
+		/*
+		 * We don't get the size of the FDT if we get if from a
+		 * configuration table.
+		 */
+		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
+			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
+			return EFI_LOAD_ERROR;
+		}
+	}
+
+	if (orig_fdt)
+		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
+	else
+		status = fdt_create_empty_tree(fdt, new_fdt_size);
+
+	if (status != 0)
+		goto fdt_set_fail;
+
+	/*
+	 * Delete any memory nodes present. We must delete nodes which
+	 * early_init_dt_scan_memory may try to use.
+	 */
+	prev = 0;
+	for (;;) {
+		const char *type;
+		int len;
+
+		node = fdt_next_node(fdt, prev, NULL);
+		if (node < 0)
+			break;
+
+		type = fdt_getprop(fdt, node, "device_type", &len);
+		if (type && strncmp(type, "memory", len) == 0) {
+			fdt_del_node(fdt, node);
+			continue;
+		}
+
+		prev = node;
+	}
+
+	/*
+	 * Delete all memory reserve map entries. When booting via UEFI,
+	 * kernel will use the UEFI memory map to find reserved regions.
+	 */
+	num_rsv = fdt_num_mem_rsv(fdt);
+	while (num_rsv-- > 0)
+		fdt_del_mem_rsv(fdt, num_rsv);
+
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	if (node < 0) {
+		node = fdt_add_subnode(fdt, 0, "chosen");
+		if (node < 0) {
+			status = node; /* node is error code when negative */
+			goto fdt_set_fail;
+		}
+	}
+
+	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
+				     strlen(cmdline_ptr) + 1);
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Set initrd address/end in device tree, if present */
+	if (initrd_size != 0) {
+		u64 initrd_image_end;
+		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
+
+		status = fdt_setprop(fdt, node, "linux,initrd-start",
+				     &initrd_image_start, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
+		status = fdt_setprop(fdt, node, "linux,initrd-end",
+				     &initrd_image_end, sizeof(u64));
+		if (status)
+			goto fdt_set_fail;
+	}
+
+	/* Add FDT entries for EFI runtime services in chosen node. */
+	node = fdt_subnode_offset(fdt, 0, "chosen");
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+			     &fdt_val64, sizeof(fdt_val64));
+	if (status)
+		goto fdt_set_fail;
+
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+	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);
+	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)
+		goto fdt_set_fail;
+
+	/*
+	 * Add kernel version banner so stub/kernel match can be
+	 * verified.
+	 */
+	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
+			     linux_banner);
+	if (status)
+		goto fdt_set_fail;
+
+	return EFI_SUCCESS;
+
+fdt_set_fail:
+	if (status == -FDT_ERR_NOSPACE)
+		return EFI_BUFFER_TOO_SMALL;
+
+	return EFI_LOAD_ERROR;
+}
+
+#ifndef EFI_FDT_ALIGN
+#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+#endif
+
+/*
+ * Allocate memory for a new FDT, then add EFI, commandline, and
+ * initrd related fields to the FDT.  This routine increases the
+ * FDT allocation size until the allocated memory is large
+ * enough.  EFI allocations are in EFI_PAGE_SIZE granules,
+ * which are fixed at 4K bytes, so in most cases the first
+ * allocation should succeed.
+ * EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map()
+ * call and the exit_boot_services() call, so the exiting of
+ * boot services is very tightly tied to the creation of the FDT
+ * with the final memory map in it.
+ */
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+					    void *handle,
+					    unsigned long *new_fdt_addr,
+					    unsigned long max_addr,
+					    u64 initrd_addr, u64 initrd_size,
+					    char *cmdline_ptr,
+					    unsigned long fdt_addr,
+					    unsigned long fdt_size)
+{
+	unsigned long map_size, desc_size;
+	u32 desc_ver;
+	unsigned long mmap_key;
+	efi_memory_desc_t *memory_map;
+	unsigned long new_fdt_size;
+	efi_status_t status;
+
+	/*
+	 * Estimate size of new FDT, and allocate memory for it. We
+	 * will allocate a bigger buffer if this ends up being too
+	 * small, so a rough guess is OK here.
+	 */
+	new_fdt_size = fdt_size + EFI_PAGE_SIZE;
+	while (1) {
+		status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
+					new_fdt_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+			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, &memory_map, &map_size,
+					    &desc_size, &desc_ver, &mmap_key);
+		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);
+
+		/* Succeeding the first time is the expected case. */
+		if (status == EFI_SUCCESS)
+			break;
+
+		if (status == EFI_BUFFER_TOO_SMALL) {
+			/*
+			 * 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.
+			 */
+			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 constuct new device tree.\n");
+			goto fail_free_mmap;
+		}
+	}
+
+	/* Now we are ready to exit_boot_services.*/
+	status = sys_table->boottime->exit_boot_services(handle, mmap_key);
+
+
+	if (status == EFI_SUCCESS)
+		return status;
+
+	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);
+
+fail:
+	return EFI_LOAD_ERROR;
+}
+
+void *get_fdt(efi_system_table_t *sys_table)
+{
+	efi_guid_t fdt_guid = DEVICE_TREE_GUID;
+	efi_config_table_t *tables;
+	void *fdt;
+	int i;
+
+	tables = (efi_config_table_t *) sys_table->tables;
+	fdt = NULL;
+
+	for (i = 0; i < sys_table->nr_tables; i++)
+		if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
+			fdt = (void *) tables[i].table;
+			break;
+	 }
+
+	return fdt;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/libstub/Makefile linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/Makefile
--- linux-libre-3.16-gnu/drivers/firmware/efi/libstub/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/libstub/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,26 @@
+#
+# The stub may be linked into the kernel proper or into a separate boot binary,
+# but in either case, it executes before the kernel does (with MMU disabled) so
+# things like ftrace and stack-protector are likely to cause trouble if left
+# enabled, even if doing so doesn't break the build.
+#
+cflags-$(CONFIG_X86_32)		:= -march=i386
+cflags-$(CONFIG_X86_64)		:= -mcmodel=small
+cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+				   -fPIC -fno-strict-aliasing -mno-red-zone \
+				   -mno-mmx -mno-sse -DDISABLE_BRANCH_PROFILING
+
+cflags-$(CONFIG_ARM64)		:= $(subst -pg,,$(KBUILD_CFLAGS))
+cflags-$(CONFIG_ARM)		:= $(subst -pg,,$(KBUILD_CFLAGS)) \
+				   -fno-builtin -fpic -mno-single-pic-base
+
+KBUILD_CFLAGS			:= $(cflags-y) \
+				   $(call cc-option,-ffreestanding) \
+				   $(call cc-option,-fno-stack-protector)
+
+GCOV_PROFILE			:= n
+
+lib-y				:= efi-stub-helper.o
+lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o
+
+CFLAGS_fdt.o			+= -I$(srctree)/scripts/dtc/libfdt/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/Makefile linux-libre-3.17-rc7-gnu/drivers/firmware/efi/Makefile
--- linux-libre-3.16-gnu/drivers/firmware/efi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,10 @@
 #
 # Makefile for linux kernel
 #
-obj-$(CONFIG_EFI)			+= efi.o vars.o
+obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o
 obj-$(CONFIG_EFI_VARS)			+= efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)		+= efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)			+= cper.o
 obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
+obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
+obj-$(CONFIG_EFI_ARM_STUB)		+= libstub/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/reboot.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/reboot.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/reboot.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/reboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 Intel Corporation; author Matt Fleming
+ * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com>
+ */
+#include <linux/efi.h>
+#include <linux/reboot.h>
+
+int efi_reboot_quirk_mode = -1;
+
+void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
+{
+	int efi_mode;
+
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
+		return;
+
+	switch (reboot_mode) {
+	case REBOOT_WARM:
+	case REBOOT_SOFT:
+		efi_mode = EFI_RESET_WARM;
+		break;
+	default:
+		efi_mode = EFI_RESET_COLD;
+		break;
+	}
+
+	/*
+	 * If a quirk forced an EFI reset mode, always use that.
+	 */
+	if (efi_reboot_quirk_mode != -1)
+		efi_mode = efi_reboot_quirk_mode;
+
+	efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);
+}
+
+bool __weak efi_poweroff_required(void)
+{
+	return false;
+}
+
+static void efi_power_off(void)
+{
+	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
+}
+
+static int __init efi_shutdown_init(void)
+{
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
+		return -ENODEV;
+
+	if (efi_poweroff_required())
+		pm_power_off = efi_power_off;
+
+	return 0;
+}
+late_initcall(efi_shutdown_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/runtime-map.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/runtime-map.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/runtime-map.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/runtime-map.c	2014-09-28 17:29:07.000000000 -0400
@@ -138,6 +138,27 @@ add_sysfs_runtime_map_entry(struct kobje
 	return entry;
 }
 
+int efi_get_runtime_map_size(void)
+{
+	return nr_efi_runtime_map * efi_memdesc_size;
+}
+
+int efi_get_runtime_map_desc_size(void)
+{
+	return efi_memdesc_size;
+}
+
+int efi_runtime_map_copy(void *buf, size_t bufsz)
+{
+	size_t sz = efi_get_runtime_map_size();
+
+	if (sz > bufsz)
+		sz = bufsz;
+
+	memcpy(buf, efi_runtime_map, sz);
+	return 0;
+}
+
 void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size)
 {
 	efi_runtime_map = map;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/runtime-wrappers.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/runtime-wrappers.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/runtime-wrappers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/runtime-wrappers.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * runtime-wrappers.c - Runtime Services function call wrappers
+ *
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * Split off from arch/x86/platform/efi/efi.c
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ * Copyright (C) 2005-2008 Intel Co.
+ * Copyright (C) 2013 SuSE Labs
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/efi.h>
+#include <linux/spinlock.h>             /* spinlock_t */
+#include <asm/efi.h>
+
+/*
+ * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
+ * the EFI specification requires that callers of the time related runtime
+ * functions serialize with other CMOS accesses in the kernel, as the EFI time
+ * functions may choose to also use the legacy CMOS RTC.
+ */
+__weak DEFINE_SPINLOCK(rtc_lock);
+
+static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt(get_time, tm, tc);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
+}
+
+static efi_status_t virt_efi_set_time(efi_time_t *tm)
+{
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt(set_time, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
+}
+
+static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
+					     efi_bool_t *pending,
+					     efi_time_t *tm)
+{
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
+}
+
+static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+{
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt(set_wakeup_time, enabled, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
+}
+
+static efi_status_t virt_efi_get_variable(efi_char16_t *name,
+					  efi_guid_t *vendor,
+					  u32 *attr,
+					  unsigned long *data_size,
+					  void *data)
+{
+	return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
+					       efi_char16_t *name,
+					       efi_guid_t *vendor)
+{
+	return efi_call_virt(get_next_variable, name_size, name, vendor);
+}
+
+static efi_status_t virt_efi_set_variable(efi_char16_t *name,
+					  efi_guid_t *vendor,
+					  u32 attr,
+					  unsigned long data_size,
+					  void *data)
+{
+	return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_query_variable_info(u32 attr,
+						 u64 *storage_space,
+						 u64 *remaining_space,
+						 u64 *max_variable_size)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt(query_variable_info, attr, storage_space,
+			     remaining_space, max_variable_size);
+}
+
+static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
+{
+	return efi_call_virt(get_next_high_mono_count, count);
+}
+
+static void virt_efi_reset_system(int reset_type,
+				  efi_status_t status,
+				  unsigned long data_size,
+				  efi_char16_t *data)
+{
+	__efi_call_virt(reset_system, reset_type, status, data_size, data);
+}
+
+static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
+					    unsigned long count,
+					    unsigned long sg_list)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt(update_capsule, capsules, count, sg_list);
+}
+
+static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+						unsigned long count,
+						u64 *max_size,
+						int *reset_type)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt(query_capsule_caps, capsules, count, max_size,
+			     reset_type);
+}
+
+void efi_native_runtime_setup(void)
+{
+	efi.get_time = virt_efi_get_time;
+	efi.set_time = virt_efi_set_time;
+	efi.get_wakeup_time = virt_efi_get_wakeup_time;
+	efi.set_wakeup_time = virt_efi_set_wakeup_time;
+	efi.get_variable = virt_efi_get_variable;
+	efi.get_next_variable = virt_efi_get_next_variable;
+	efi.set_variable = virt_efi_set_variable;
+	efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+	efi.reset_system = virt_efi_reset_system;
+	efi.query_variable_info = virt_efi_query_variable_info;
+	efi.update_capsule = virt_efi_update_capsule;
+	efi.query_capsule_caps = virt_efi_query_capsule_caps;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/efi/vars.c linux-libre-3.17-rc7-gnu/drivers/firmware/efi/vars.c
--- linux-libre-3.16-gnu/drivers/firmware/efi/vars.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/efi/vars.c	2014-09-28 17:29:07.000000000 -0400
@@ -481,7 +481,7 @@ EXPORT_SYMBOL_GPL(efivar_entry_remove);
  */
 static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
 {
-	WARN_ON(!spin_is_locked(&__efivars->lock));
+	lockdep_assert_held(&__efivars->lock);
 
 	list_del(&entry->list);
 	spin_unlock_irq(&__efivars->lock);
@@ -507,7 +507,7 @@ int __efivar_entry_delete(struct efivar_
 	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	WARN_ON(!spin_is_locked(&__efivars->lock));
+	lockdep_assert_held(&__efivars->lock);
 
 	status = ops->set_variable(entry->var.VariableName,
 				   &entry->var.VendorGuid,
@@ -667,7 +667,7 @@ struct efivar_entry *efivar_entry_find(e
 	int strsize1, strsize2;
 	bool found = false;
 
-	WARN_ON(!spin_is_locked(&__efivars->lock));
+	lockdep_assert_held(&__efivars->lock);
 
 	list_for_each_entry_safe(entry, n, head, list) {
 		strsize1 = ucs2_strsize(name, 1024);
@@ -739,7 +739,7 @@ int __efivar_entry_get(struct efivar_ent
 	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	WARN_ON(!spin_is_locked(&__efivars->lock));
+	lockdep_assert_held(&__efivars->lock);
 
 	status = ops->get_variable(entry->var.VariableName,
 				   &entry->var.VendorGuid,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/firmware/memmap.c linux-libre-3.17-rc7-gnu/drivers/firmware/memmap.c
--- linux-libre-3.16-gnu/drivers/firmware/memmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/firmware/memmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -286,7 +286,11 @@ int __meminit firmware_map_add_hotplug(u
 {
 	struct firmware_map_entry *entry;
 
-	entry = firmware_map_find_entry_bootmem(start, end, type);
+	entry = firmware_map_find_entry(start, end - 1, type);
+	if (entry)
+		return 0;
+
+	entry = firmware_map_find_entry_bootmem(start, end - 1, type);
 	if (!entry) {
 		entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
 		if (!entry)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/devres.c linux-libre-3.17-rc7-gnu/drivers/gpio/devres.c
--- linux-libre-3.16-gnu/drivers/gpio/devres.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/devres.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,57 +39,63 @@ static int devm_gpiod_match(struct devic
  * devm_gpiod_get - Resource-managed gpiod_get()
  * @dev:	GPIO consumer
  * @con_id:	function within the GPIO consumer
+ * @flags:	optional GPIO initialization flags
  *
  * Managed gpiod_get(). GPIO descriptors returned from this function are
  * automatically disposed on driver detach. See gpiod_get() for detailed
  * information about behavior and return values.
  */
-struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
-					      const char *con_id)
+struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
+					      const char *con_id,
+					      enum gpiod_flags flags)
 {
-	return devm_gpiod_get_index(dev, con_id, 0);
+	return devm_gpiod_get_index(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL(devm_gpiod_get);
+EXPORT_SYMBOL(__devm_gpiod_get);
 
 /**
  * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
  * @dev: GPIO consumer
  * @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
  *
  * Managed gpiod_get_optional(). GPIO descriptors returned from this function
  * are automatically disposed on driver detach. See gpiod_get_optional() for
  * detailed information about behavior and return values.
  */
-struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
-						       const char *con_id)
+struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
+						       const char *con_id,
+						       enum gpiod_flags flags)
 {
-	return devm_gpiod_get_index_optional(dev, con_id, 0);
+	return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL(devm_gpiod_get_optional);
+EXPORT_SYMBOL(__devm_gpiod_get_optional);
 
 /**
  * devm_gpiod_get_index - Resource-managed gpiod_get_index()
  * @dev:	GPIO consumer
  * @con_id:	function within the GPIO consumer
  * @idx:	index of the GPIO to obtain in the consumer
+ * @flags:	optional GPIO initialization flags
  *
  * Managed gpiod_get_index(). GPIO descriptors returned from this function are
  * automatically disposed on driver detach. See gpiod_get_index() for detailed
  * information about behavior and return values.
  */
-struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
 						    const char *con_id,
-						    unsigned int idx)
+						    unsigned int idx,
+						    enum gpiod_flags flags)
 {
 	struct gpio_desc **dr;
 	struct gpio_desc *desc;
 
-	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpiod_desc *),
+	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
 			  GFP_KERNEL);
 	if (!dr)
 		return ERR_PTR(-ENOMEM);
 
-	desc = gpiod_get_index(dev, con_id, idx);
+	desc = gpiod_get_index(dev, con_id, idx, flags);
 	if (IS_ERR(desc)) {
 		devres_free(dr);
 		return desc;
@@ -100,26 +106,28 @@ struct gpio_desc *__must_check devm_gpio
 
 	return desc;
 }
-EXPORT_SYMBOL(devm_gpiod_get_index);
+EXPORT_SYMBOL(__devm_gpiod_get_index);
 
 /**
  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
  * @dev: GPIO consumer
  * @con_id: function within the GPIO consumer
  * @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
  *
  * Managed gpiod_get_index_optional(). GPIO descriptors returned from this
  * function are automatically disposed on driver detach. See
  * gpiod_get_index_optional() for detailed information about behavior and
  * return values.
  */
-struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev,
 							     const char *con_id,
-							     unsigned int index)
+							     unsigned int index,
+							 enum gpiod_flags flags)
 {
 	struct gpio_desc *desc;
 
-	desc = devm_gpiod_get_index(dev, con_id, index);
+	desc = devm_gpiod_get_index(dev, con_id, index, flags);
 	if (IS_ERR(desc)) {
 		if (PTR_ERR(desc) == -ENOENT)
 			return NULL;
@@ -127,7 +135,7 @@ struct gpio_desc *__must_check devm_gpio
 
 	return desc;
 }
-EXPORT_SYMBOL(devm_gpiod_get_index_optional);
+EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
 
 /**
  * devm_gpiod_put - Resource-managed gpiod_put()
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-74x164.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-74x164.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-74x164.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-74x164.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,13 +167,11 @@ exit_destroy:
 static int gen_74x164_remove(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip = spi_get_drvdata(spi);
-	int ret;
 
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (!ret)
-		mutex_destroy(&chip->lock);
+	gpiochip_remove(&chip->gpio_chip);
+	mutex_destroy(&chip->lock);
 
-	return ret;
+	return 0;
 }
 
 static const struct of_device_id gen_74x164_dt_ids[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-adnp.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adnp.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-adnp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adnp.c	2014-09-28 17:29:07.000000000 -0400
@@ -585,15 +585,8 @@ static int adnp_i2c_remove(struct i2c_cl
 {
 	struct adnp *adnp = i2c_get_clientdata(client);
 	struct device_node *np = client->dev.of_node;
-	int err;
-
-	err = gpiochip_remove(&adnp->gpio);
-	if (err < 0) {
-		dev_err(&client->dev, "%s failed: %d\n", "gpiochip_remove()",
-			err);
-		return err;
-	}
 
+	gpiochip_remove(&adnp->gpio);
 	if (of_find_property(np, "interrupt-controller", NULL))
 		adnp_irq_teardown(adnp);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-adp5520.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adp5520.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-adp5520.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adp5520.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,15 +167,9 @@ err:
 static int adp5520_gpio_remove(struct platform_device *pdev)
 {
 	struct adp5520_gpio *dev;
-	int ret;
 
 	dev = platform_get_drvdata(pdev);
-	ret = gpiochip_remove(&dev->gpio_chip);
-	if (ret) {
-		dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
+	gpiochip_remove(&dev->gpio_chip);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-adp5588.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adp5588.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-adp5588.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-adp5588.c	2014-09-28 17:29:07.000000000 -0400
@@ -470,11 +470,7 @@ static int adp5588_gpio_remove(struct i2
 	if (dev->irq_base)
 		free_irq(dev->client->irq, dev);
 
-	ret = gpiochip_remove(&dev->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
-		return ret;
-	}
+	gpiochip_remove(&dev->gpio_chip);
 
 	kfree(dev);
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-amd8111.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-amd8111.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-amd8111.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-amd8111.c	2014-09-28 17:29:07.000000000 -0400
@@ -232,8 +232,7 @@ out:
 
 static void __exit amd_gpio_exit(void)
 {
-	int err = gpiochip_remove(&gp.chip);
-	WARN_ON(err);
+	gpiochip_remove(&gp.chip);
 	ioport_unmap(gp.pm);
 	release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-arizona.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-arizona.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-arizona.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-arizona.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,7 +149,8 @@ static int arizona_gpio_remove(struct pl
 {
 	struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&arizona_gpio->gpio_chip);
+	gpiochip_remove(&arizona_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver arizona_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-bt8xx.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-bt8xx.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-bt8xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-bt8xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -241,9 +241,6 @@ static void bt8xxgpio_remove(struct pci_
 	bgwrite(~0x0, BT848_INT_STAT);
 	bgwrite(0x0, BT848_GPIO_OUT_EN);
 
-	iounmap(bg->mmio);
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
 	pci_disable_device(pdev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-crystalcove.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-crystalcove.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-crystalcove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-crystalcove.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,380 @@
+/*
+ * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver
+ *
+ * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/seq_file.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+
+#define CRYSTALCOVE_GPIO_NUM	16
+
+#define UPDATE_IRQ_TYPE		BIT(0)
+#define UPDATE_IRQ_MASK		BIT(1)
+
+#define GPIO0IRQ		0x0b
+#define GPIO1IRQ		0x0c
+#define MGPIO0IRQS0		0x19
+#define MGPIO1IRQS0		0x1a
+#define MGPIO0IRQSX		0x1b
+#define MGPIO1IRQSX		0x1c
+#define GPIO0P0CTLO		0x2b
+#define GPIO0P0CTLI		0x33
+#define GPIO1P0CTLO		0x3b
+#define GPIO1P0CTLI		0x43
+
+#define CTLI_INTCNT_DIS		(0)
+#define CTLI_INTCNT_NE		(1 << 1)
+#define CTLI_INTCNT_PE		(2 << 1)
+#define CTLI_INTCNT_BE		(3 << 1)
+
+#define CTLO_DIR_IN		(0)
+#define CTLO_DIR_OUT		(1 << 5)
+
+#define CTLO_DRV_CMOS		(0)
+#define CTLO_DRV_OD		(1 << 4)
+
+#define CTLO_DRV_REN		(1 << 3)
+
+#define CTLO_RVAL_2KDW		(0)
+#define CTLO_RVAL_2KUP		(1 << 1)
+#define CTLO_RVAL_50KDW		(2 << 1)
+#define CTLO_RVAL_50KUP		(3 << 1)
+
+#define CTLO_INPUT_SET	(CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP)
+#define CTLO_OUTPUT_SET	(CTLO_DIR_OUT | CTLO_INPUT_SET)
+
+enum ctrl_register {
+	CTRL_IN,
+	CTRL_OUT,
+};
+
+/**
+ * struct crystalcove_gpio - Crystal Cove GPIO controller
+ * @buslock: for bus lock/sync and unlock.
+ * @chip: the abstract gpio_chip structure.
+ * @regmap: the regmap from the parent device.
+ * @update: pending IRQ setting update, to be written to the chip upon unlock.
+ * @intcnt_value: the Interrupt Detect value to be written.
+ * @set_irq_mask: true if the IRQ mask needs to be set, false to clear.
+ */
+struct crystalcove_gpio {
+	struct mutex buslock; /* irq_bus_lock */
+	struct gpio_chip chip;
+	struct regmap *regmap;
+	int update;
+	int intcnt_value;
+	bool set_irq_mask;
+};
+
+static inline struct crystalcove_gpio *to_cg(struct gpio_chip *gc)
+{
+	return container_of(gc, struct crystalcove_gpio, chip);
+}
+
+static inline int to_reg(int gpio, enum ctrl_register reg_type)
+{
+	int reg;
+
+	if (reg_type == CTRL_IN) {
+		if (gpio < 8)
+			reg = GPIO0P0CTLI;
+		else
+			reg = GPIO1P0CTLI;
+	} else {
+		if (gpio < 8)
+			reg = GPIO0P0CTLO;
+		else
+			reg = GPIO1P0CTLO;
+	}
+
+	return reg + gpio % 8;
+}
+
+static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg,
+					int gpio)
+{
+	u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0;
+	int mask = BIT(gpio % 8);
+
+	if (cg->set_irq_mask)
+		regmap_update_bits(cg->regmap, mirqs0, mask, mask);
+	else
+		regmap_update_bits(cg->regmap, mirqs0, mask, 0);
+}
+
+static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
+{
+	int reg = to_reg(gpio, CTRL_IN);
+
+	regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value);
+}
+
+static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
+{
+	struct crystalcove_gpio *cg = to_cg(chip);
+
+	return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+			    CTLO_INPUT_SET);
+}
+
+static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
+				    int value)
+{
+	struct crystalcove_gpio *cg = to_cg(chip);
+
+	return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+			    CTLO_OUTPUT_SET | value);
+}
+
+static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+	struct crystalcove_gpio *cg = to_cg(chip);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+	if (ret)
+		return ret;
+
+	return val & 0x1;
+}
+
+static void crystalcove_gpio_set(struct gpio_chip *chip,
+				 unsigned gpio, int value)
+{
+	struct crystalcove_gpio *cg = to_cg(chip);
+
+	if (value)
+		regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+	else
+		regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+}
+
+static int crystalcove_irq_type(struct irq_data *data, unsigned type)
+{
+	struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+	switch (type) {
+	case IRQ_TYPE_NONE:
+		cg->intcnt_value = CTLI_INTCNT_DIS;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		cg->intcnt_value = CTLI_INTCNT_BE;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		cg->intcnt_value = CTLI_INTCNT_PE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		cg->intcnt_value = CTLI_INTCNT_NE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cg->update |= UPDATE_IRQ_TYPE;
+
+	return 0;
+}
+
+static void crystalcove_bus_lock(struct irq_data *data)
+{
+	struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+	mutex_lock(&cg->buslock);
+}
+
+static void crystalcove_bus_sync_unlock(struct irq_data *data)
+{
+	struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+	int gpio = data->hwirq;
+
+	if (cg->update & UPDATE_IRQ_TYPE)
+		crystalcove_update_irq_ctrl(cg, gpio);
+	if (cg->update & UPDATE_IRQ_MASK)
+		crystalcove_update_irq_mask(cg, gpio);
+	cg->update = 0;
+
+	mutex_unlock(&cg->buslock);
+}
+
+static void crystalcove_irq_unmask(struct irq_data *data)
+{
+	struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+	cg->set_irq_mask = false;
+	cg->update |= UPDATE_IRQ_MASK;
+}
+
+static void crystalcove_irq_mask(struct irq_data *data)
+{
+	struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+	cg->set_irq_mask = true;
+	cg->update |= UPDATE_IRQ_MASK;
+}
+
+static struct irq_chip crystalcove_irqchip = {
+	.name			= "Crystal Cove",
+	.irq_mask		= crystalcove_irq_mask,
+	.irq_unmask		= crystalcove_irq_unmask,
+	.irq_set_type		= crystalcove_irq_type,
+	.irq_bus_lock		= crystalcove_bus_lock,
+	.irq_bus_sync_unlock	= crystalcove_bus_sync_unlock,
+};
+
+static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
+{
+	struct crystalcove_gpio *cg = data;
+	unsigned int p0, p1;
+	int pending;
+	int gpio;
+	unsigned int virq;
+
+	if (regmap_read(cg->regmap, GPIO0IRQ, &p0) ||
+	    regmap_read(cg->regmap, GPIO1IRQ, &p1))
+		return IRQ_NONE;
+
+	regmap_write(cg->regmap, GPIO0IRQ, p0);
+	regmap_write(cg->regmap, GPIO1IRQ, p1);
+
+	pending = p0 | p1 << 8;
+
+	for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+		if (pending & BIT(gpio)) {
+			virq = irq_find_mapping(cg->chip.irqdomain, gpio);
+			generic_handle_irq(virq);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void crystalcove_gpio_dbg_show(struct seq_file *s,
+				      struct gpio_chip *chip)
+{
+	struct crystalcove_gpio *cg = to_cg(chip);
+	int gpio, offset;
+	unsigned int ctlo, ctli, mirqs0, mirqsx, irq;
+
+	for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+		regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
+		regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli);
+		regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0,
+			    &mirqs0);
+		regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQSX : MGPIO1IRQSX,
+			    &mirqsx);
+		regmap_read(cg->regmap, gpio < 8 ? GPIO0IRQ : GPIO1IRQ,
+			    &irq);
+
+		offset = gpio % 8;
+		seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s %s\n",
+			   gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ",
+			   ctli & 0x1 ? "hi" : "lo",
+			   ctli & CTLI_INTCNT_NE ? "fall" : "    ",
+			   ctli & CTLI_INTCNT_PE ? "rise" : "    ",
+			   ctlo,
+			   mirqs0 & BIT(offset) ? "s0 mask  " : "s0 unmask",
+			   mirqsx & BIT(offset) ? "sx mask  " : "sx unmask",
+			   irq & BIT(offset) ? "pending" : "       ");
+	}
+}
+
+static int crystalcove_gpio_probe(struct platform_device *pdev)
+{
+	int irq = platform_get_irq(pdev, 0);
+	struct crystalcove_gpio *cg;
+	int retval;
+	struct device *dev = pdev->dev.parent;
+	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+	if (irq < 0)
+		return irq;
+
+	cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, cg);
+
+	mutex_init(&cg->buslock);
+	cg->chip.label = KBUILD_MODNAME;
+	cg->chip.direction_input = crystalcove_gpio_dir_in;
+	cg->chip.direction_output = crystalcove_gpio_dir_out;
+	cg->chip.get = crystalcove_gpio_get;
+	cg->chip.set = crystalcove_gpio_set;
+	cg->chip.base = -1;
+	cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM;
+	cg->chip.can_sleep = true;
+	cg->chip.dev = dev;
+	cg->chip.dbg_show = crystalcove_gpio_dbg_show;
+	cg->regmap = pmic->regmap;
+
+	retval = gpiochip_add(&cg->chip);
+	if (retval) {
+		dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
+		return retval;
+	}
+
+	gpiochip_irqchip_add(&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);
+
+	if (retval) {
+		dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
+		goto out_remove_gpio;
+	}
+
+	return 0;
+
+out_remove_gpio:
+	WARN_ON(gpiochip_remove(&cg->chip));
+	return retval;
+}
+
+static int crystalcove_gpio_remove(struct platform_device *pdev)
+{
+	struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+	int err;
+
+	err = gpiochip_remove(&cg->chip);
+
+	if (irq >= 0)
+		free_irq(irq, cg);
+
+	return err;
+}
+
+static struct platform_driver crystalcove_gpio_driver = {
+	.probe = crystalcove_gpio_probe,
+	.remove = crystalcove_gpio_remove,
+	.driver = {
+		.name = "crystal_cove_gpio",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(crystalcove_gpio_driver);
+
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_DESCRIPTION("Intel Crystal Cove GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-cs5535.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-cs5535.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-cs5535.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-cs5535.c	2014-09-28 17:29:07.000000000 -0400
@@ -358,14 +358,8 @@ done:
 static int cs5535_gpio_remove(struct platform_device *pdev)
 {
 	struct resource *r;
-	int err;
 
-	err = gpiochip_remove(&cs5535_gpio_chip.chip);
-	if (err) {
-		/* uhh? */
-		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-		return err;
-	}
+	gpiochip_remove(&cs5535_gpio_chip.chip);
 
 	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	release_region(r->start, resource_size(r));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-da9052.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-da9052.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-da9052.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-da9052.c	2014-09-28 17:29:07.000000000 -0400
@@ -237,7 +237,8 @@ static int da9052_gpio_remove(struct pla
 {
 	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&gpio->gp);
+	gpiochip_remove(&gpio->gp);
+	return 0;
 }
 
 static struct platform_driver da9052_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-da9055.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-da9055.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-da9055.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-da9055.c	2014-09-28 17:29:07.000000000 -0400
@@ -174,7 +174,8 @@ static int da9055_gpio_remove(struct pla
 {
 	struct da9055_gpio *gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&gpio->gp);
+	gpiochip_remove(&gpio->gp);
+	return 0;
 }
 
 static struct platform_driver da9055_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-dwapb.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-dwapb.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-dwapb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-dwapb.c	2014-09-28 17:29:07.000000000 -0400
@@ -359,7 +359,7 @@ static void dwapb_gpio_unregister(struct
 
 	for (m = 0; m < gpio->nr_ports; ++m)
 		if (gpio->ports[m].is_registered)
-			WARN_ON(gpiochip_remove(&gpio->ports[m].bgc.gc));
+			gpiochip_remove(&gpio->ports[m].bgc.gc);
 }
 
 static int dwapb_gpio_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-em.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-em.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-em.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-em.c	2014-09-28 17:29:07.000000000 -0400
@@ -409,11 +409,8 @@ err0:
 static int em_gio_remove(struct platform_device *pdev)
 {
 	struct em_gio_priv *p = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = gpiochip_remove(&p->gpio_chip);
-	if (ret)
-		return ret;
+	gpiochip_remove(&p->gpio_chip);
 
 	irq_domain_remove(p->irq_domain);
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-f7188x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-f7188x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-f7188x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-f7188x.c	2014-09-28 17:29:07.000000000 -0400
@@ -317,13 +317,7 @@ static int f7188x_gpio_probe(struct plat
 err_gpiochip:
 	for (i = i - 1; i >= 0; i--) {
 		struct f7188x_gpio_bank *bank = &data->bank[i];
-		int tmp;
-
-		tmp = gpiochip_remove(&bank->chip);
-		if (tmp < 0)
-			dev_err(&pdev->dev,
-				"Failed to remove gpiochip %d: %d\n",
-				i, tmp);
+		gpiochip_remove(&bank->chip);
 	}
 
 	return err;
@@ -331,20 +325,12 @@ err_gpiochip:
 
 static int f7188x_gpio_remove(struct platform_device *pdev)
 {
-	int err;
 	int i;
 	struct f7188x_gpio_data *data = platform_get_drvdata(pdev);
 
 	for (i = 0; i < data->nr_bank; i++) {
 		struct f7188x_gpio_bank *bank = &data->bank[i];
-
-		err = gpiochip_remove(&bank->chip);
-		if (err) {
-			dev_err(&pdev->dev,
-				"Failed to remove GPIO gpiochip %d: %d\n",
-				i, err);
-			return err;
-		}
+		gpiochip_remove(&bank->chip);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-generic.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-generic.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -398,7 +398,8 @@ static int bgpio_request(struct gpio_chi
 
 int bgpio_remove(struct bgpio_chip *bgc)
 {
-	return gpiochip_remove(&bgc->gc);
+	gpiochip_remove(&bgc->gc);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(bgpio_remove);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-grgpio.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-grgpio.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-grgpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-grgpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -468,9 +468,7 @@ static int grgpio_remove(struct platform
 		}
 	}
 
-	ret = gpiochip_remove(&priv->bgc.gc);
-	if (ret)
-		goto out;
+	gpiochip_remove(&priv->bgc.gc);
 
 	if (priv->domain)
 		irq_domain_remove(priv->domain);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-ich.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ich.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-ich.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ich.c	2014-09-28 17:29:07.000000000 -0400
@@ -514,14 +514,7 @@ add_err:
 
 static int ichx_gpio_remove(struct platform_device *pdev)
 {
-	int err;
-
-	err = gpiochip_remove(&ichx_priv.chip);
-	if (err) {
-		dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-		return err;
-	}
+	gpiochip_remove(&ichx_priv.chip);
 
 	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
 	if (ichx_priv.pm_base)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-intel-mid.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-intel-mid.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-intel-mid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-intel-mid.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,12 +28,10 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
-#include <linux/irqdomain.h>
 
 #define INTEL_MID_IRQ_TYPE_EDGE		(1 << 0)
 #define INTEL_MID_IRQ_TYPE_LEVEL	(1 << 1)
@@ -78,10 +76,12 @@ struct intel_mid_gpio {
 	void __iomem			*reg_base;
 	spinlock_t			lock;
 	struct pci_dev			*pdev;
-	struct irq_domain		*domain;
 };
 
-#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip)
+static inline struct intel_mid_gpio *to_intel_gpio_priv(struct gpio_chip *gc)
+{
+	return container_of(gc, struct intel_mid_gpio, chip);
+}
 
 static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
 			      enum GPIO_REG reg_type)
@@ -182,15 +182,10 @@ static int intel_gpio_direction_output(s
 	return 0;
 }
 
-static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
-	return irq_create_mapping(priv->domain, offset);
-}
-
 static int intel_mid_irq_type(struct irq_data *d, unsigned type)
 {
-	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
 	u32 gpio = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 value;
@@ -231,33 +226,11 @@ static void intel_mid_irq_mask(struct ir
 {
 }
 
-static int intel_mid_irq_reqres(struct irq_data *d)
-{
-	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
-
-	if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) {
-		dev_err(priv->chip.dev,
-			"unable to lock HW IRQ %lu for IRQ\n",
-			irqd_to_hwirq(d));
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void intel_mid_irq_relres(struct irq_data *d)
-{
-	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
-
-	gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d));
-}
-
 static struct irq_chip intel_mid_irqchip = {
 	.name		= "INTEL_MID-GPIO",
 	.irq_mask	= intel_mid_irq_mask,
 	.irq_unmask	= intel_mid_irq_unmask,
 	.irq_set_type	= intel_mid_irq_type,
-	.irq_request_resources = intel_mid_irq_reqres,
-	.irq_release_resources = intel_mid_irq_relres,
 };
 
 static const struct intel_mid_gpio_ddata gpio_lincroft = {
@@ -330,8 +303,9 @@ MODULE_DEVICE_TABLE(pci, intel_gpio_ids)
 
 static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
 	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data);
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	u32 base, gpio, mask;
 	unsigned long pending;
@@ -345,7 +319,7 @@ static void intel_mid_irq_handler(unsign
 			mask = BIT(gpio);
 			/* Clear before handling so we can't lose an edge */
 			writel(mask, gedr);
-			generic_handle_irq(irq_find_mapping(priv->domain,
+			generic_handle_irq(irq_find_mapping(gc->irqdomain,
 							    base + gpio));
 		}
 	}
@@ -371,23 +345,6 @@ static void intel_mid_irq_init_hw(struct
 	}
 }
 
-static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-			    irq_hw_number_t hwirq)
-{
-	struct intel_mid_gpio *priv = d->host_data;
-
-	irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq);
-	irq_set_chip_data(irq, priv);
-	irq_set_irq_type(irq, IRQ_TYPE_NONE);
-
-	return 0;
-}
-
-static const struct irq_domain_ops intel_gpio_irq_ops = {
-	.map = intel_gpio_irq_map,
-	.xlate = irq_domain_xlate_twocell,
-};
-
 static int intel_gpio_runtime_idle(struct device *dev)
 {
 	int err = pm_schedule_suspend(dev, 500);
@@ -441,7 +398,6 @@ static int intel_gpio_probe(struct pci_d
 	priv->chip.direction_output = intel_gpio_direction_output;
 	priv->chip.get = intel_gpio_get;
 	priv->chip.set = intel_gpio_set;
-	priv->chip.to_irq = intel_gpio_to_irq;
 	priv->chip.base = gpio_base;
 	priv->chip.ngpio = ddata->ngpio;
 	priv->chip.can_sleep = false;
@@ -449,11 +405,6 @@ static int intel_gpio_probe(struct pci_d
 
 	spin_lock_init(&priv->lock);
 
-	priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
-					irq_base, &intel_gpio_irq_ops, priv);
-	if (!priv->domain)
-		return -ENOMEM;
-
 	pci_set_drvdata(pdev, priv);
 	retval = gpiochip_add(&priv->chip);
 	if (retval) {
@@ -461,10 +412,23 @@ static int intel_gpio_probe(struct pci_d
 		return retval;
 	}
 
+	retval = gpiochip_irqchip_add(&priv->chip,
+				      &intel_mid_irqchip,
+				      irq_base,
+				      handle_simple_irq,
+				      IRQ_TYPE_NONE);
+	if (retval) {
+		dev_err(&pdev->dev,
+			"could not connect irqchip to gpiochip\n");
+		return retval;
+	}
+
 	intel_mid_irq_init_hw(priv);
 
-	irq_set_handler_data(pdev->irq, priv);
-	irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);
+	gpiochip_set_chained_irqchip(&priv->chip,
+				     &intel_mid_irqchip,
+				     pdev->irq,
+				     intel_mid_irq_handler);
 
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_allow(&pdev->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-it8761e.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-it8761e.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-it8761e.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-it8761e.c	2014-09-28 17:29:07.000000000 -0400
@@ -217,11 +217,7 @@ gpiochip_add_err:
 static void __exit it8761e_gpio_exit(void)
 {
 	if (gpio_ba) {
-		int ret = gpiochip_remove(&it8761e_gpio_chip);
-
-		WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
-				__func__, ret);
-
+		gpiochip_remove(&it8761e_gpio_chip);
 		release_region(gpio_ba, GPIO_IOSIZE);
 		gpio_ba = 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-janz-ttl.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-janz-ttl.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-janz-ttl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-janz-ttl.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,14 +194,8 @@ static int ttl_probe(struct platform_dev
 static int ttl_remove(struct platform_device *pdev)
 {
 	struct ttl_module *mod = platform_get_drvdata(pdev);
-	struct device *dev = &pdev->dev;
-	int ret;
 
-	ret = gpiochip_remove(&mod->gpio);
-	if (ret) {
-		dev_err(dev, "unable to remove GPIO chip\n");
-		return ret;
-	}
+	gpiochip_remove(&mod->gpio);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-kempld.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-kempld.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-kempld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-kempld.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,7 +199,8 @@ static int kempld_gpio_remove(struct pla
 {
 	struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&gpio->chip);
+	gpiochip_remove(&gpio->chip);
+	return 0;
 }
 
 static struct platform_driver kempld_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib-acpi.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-acpi.c
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib-acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -157,7 +157,7 @@ static acpi_status acpi_gpiochip_request
 
 	gpiod_direction_input(desc);
 
-	ret = gpiod_lock_as_irq(desc);
+	ret = gpio_lock_as_irq(chip, pin);
 	if (ret) {
 		dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
 		goto fail_free_desc;
@@ -212,7 +212,7 @@ static acpi_status acpi_gpiochip_request
 fail_free_event:
 	kfree(event);
 fail_unlock_irq:
-	gpiod_unlock_as_irq(desc);
+	gpio_unlock_as_irq(chip, pin);
 fail_free_desc:
 	gpiochip_free_own_desc(desc);
 
@@ -221,7 +221,7 @@ fail_free_desc:
 
 /**
  * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
- * @acpi_gpio:      ACPI GPIO chip
+ * @chip:      GPIO chip
  *
  * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
  * handled by ACPI event methods which need to be called from the GPIO
@@ -229,11 +229,21 @@ fail_free_desc:
  * gpio pins have acpi event methods and assigns interrupt handlers that calls
  * the acpi event methods for those pins.
  */
-static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
 {
-	struct gpio_chip *chip = acpi_gpio->chip;
+	struct acpi_gpio_chip *acpi_gpio;
+	acpi_handle handle;
+	acpi_status status;
 
-	if (!chip->to_irq)
+	if (!chip->dev || !chip->to_irq)
+		return;
+
+	handle = ACPI_HANDLE(chip->dev);
+	if (!handle)
+		return;
+
+	status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+	if (ACPI_FAILURE(status))
 		return;
 
 	INIT_LIST_HEAD(&acpi_gpio->events);
@@ -243,17 +253,27 @@ static void acpi_gpiochip_request_interr
 
 /**
  * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
- * @acpi_gpio:      ACPI GPIO chip
+ * @chip:      GPIO chip
  *
  * Free interrupts associated with GPIO ACPI event method for the given
  * GPIO chip.
  */
-static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
 {
+	struct acpi_gpio_chip *acpi_gpio;
 	struct acpi_gpio_event *event, *ep;
-	struct gpio_chip *chip = acpi_gpio->chip;
+	acpi_handle handle;
+	acpi_status status;
 
-	if (!chip->to_irq)
+	if (!chip->dev || !chip->to_irq)
+		return;
+
+	handle = ACPI_HANDLE(chip->dev);
+	if (!handle)
+		return;
+
+	status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+	if (ACPI_FAILURE(status))
 		return;
 
 	list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@@ -263,7 +283,7 @@ static void acpi_gpiochip_free_interrupt
 		desc = gpiochip_get_desc(chip, event->pin);
 		if (WARN_ON(IS_ERR(desc)))
 			continue;
-		gpiod_unlock_as_irq(desc);
+		gpio_unlock_as_irq(chip, event->pin);
 		gpiochip_free_own_desc(desc);
 		list_del(&event->node);
 		kfree(event);
@@ -357,8 +377,10 @@ acpi_gpio_adr_space_handler(u32 function
 	struct gpio_chip *chip = achip->chip;
 	struct acpi_resource_gpio *agpio;
 	struct acpi_resource *ares;
+	int pin_index = (int)address;
 	acpi_status status;
 	bool pull_up;
+	int length;
 	int i;
 
 	status = acpi_buffer_to_resource(achip->conn_info.connection,
@@ -380,7 +402,8 @@ acpi_gpio_adr_space_handler(u32 function
 		return AE_BAD_PARAMETER;
 	}
 
-	for (i = 0; i < agpio->pin_table_length; i++) {
+	length = min(agpio->pin_table_length, (u16)(pin_index + bits));
+	for (i = pin_index; i < length; ++i) {
 		unsigned pin = agpio->pin_table[i];
 		struct acpi_gpio_connection *conn;
 		struct gpio_desc *desc;
@@ -525,7 +548,6 @@ void acpi_gpiochip_add(struct gpio_chip
 		return;
 	}
 
-	acpi_gpiochip_request_interrupts(acpi_gpio);
 	acpi_gpiochip_request_regions(acpi_gpio);
 }
 
@@ -549,7 +571,6 @@ void acpi_gpiochip_remove(struct gpio_ch
 	}
 
 	acpi_gpiochip_free_regions(acpi_gpio);
-	acpi_gpiochip_free_interrupts(acpi_gpio);
 
 	acpi_detach_data(handle, acpi_gpio_chip_dh);
 	kfree(acpi_gpio);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib.c
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 
 #include "gpiolib.h"
 
@@ -44,111 +45,19 @@
  * While any GPIO is requested, its gpio_chip is not removable;
  * each GPIO's "requested" flag serves as a lock and refcount.
  */
-static DEFINE_SPINLOCK(gpio_lock);
-
-struct gpio_desc {
-	struct gpio_chip	*chip;
-	unsigned long		flags;
-/* flag symbols are bit numbers */
-#define FLAG_REQUESTED	0
-#define FLAG_IS_OUT	1
-#define FLAG_EXPORT	2	/* protected by sysfs_lock */
-#define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */
-#define FLAG_TRIG_FALL	4	/* trigger on falling edge */
-#define FLAG_TRIG_RISE	5	/* trigger on rising edge */
-#define FLAG_ACTIVE_LOW	6	/* value has active low */
-#define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */
-#define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
-#define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
-
-#define ID_SHIFT	16	/* add new flags before this one */
-
-#define GPIO_FLAGS_MASK		((1 << ID_SHIFT) - 1)
-#define GPIO_TRIGGER_MASK	(BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
+DEFINE_SPINLOCK(gpio_lock);
 
-#ifdef CONFIG_DEBUG_FS
-	const char		*label;
-#endif
-};
 static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
 
 #define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
 
 static DEFINE_MUTEX(gpio_lookup_lock);
 static LIST_HEAD(gpio_lookup_list);
-static LIST_HEAD(gpio_chips);
-
-#ifdef CONFIG_GPIO_SYSFS
-static DEFINE_IDR(dirent_idr);
-#endif
-
-static int gpiod_request(struct gpio_desc *desc, const char *label);
-static void gpiod_free(struct gpio_desc *desc);
-
-/* With descriptor prefix */
-
-#ifdef CONFIG_DEBUG_FS
-#define gpiod_emerg(desc, fmt, ...)					       \
-	pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
-                 ##__VA_ARGS__)
-#define gpiod_crit(desc, fmt, ...)					       \
-	pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
-                 ##__VA_ARGS__)
-#define gpiod_err(desc, fmt, ...)					       \
-	pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",  \
-                 ##__VA_ARGS__)
-#define gpiod_warn(desc, fmt, ...)					       \
-	pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
-                 ##__VA_ARGS__)
-#define gpiod_info(desc, fmt, ...)					       \
-	pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
-                ##__VA_ARGS__)
-#define gpiod_dbg(desc, fmt, ...)					       \
-	pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
-                 ##__VA_ARGS__)
-#else
-#define gpiod_emerg(desc, fmt, ...)					\
-	pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_crit(desc, fmt, ...)					\
-	pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_err(desc, fmt, ...)					\
-	pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_warn(desc, fmt, ...)					\
-	pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_info(desc, fmt, ...)					\
-	pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_dbg(desc, fmt, ...)					\
-	pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#endif
-
-/* With chip prefix */
-
-#define chip_emerg(chip, fmt, ...)					\
-	pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_crit(chip, fmt, ...)					\
-	pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_err(chip, fmt, ...)					\
-	pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_warn(chip, fmt, ...)					\
-	pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_info(chip, fmt, ...)					\
-	pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_dbg(chip, fmt, ...)					\
-	pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+LIST_HEAD(gpio_chips);
 
 static inline void desc_set_label(struct gpio_desc *d, const char *label)
 {
-#ifdef CONFIG_DEBUG_FS
 	d->label = label;
-#endif
-}
-
-/*
- * Return the GPIO number of the passed descriptor relative to its chip
- */
-static int gpio_chip_hwgpio(const struct gpio_desc *desc)
-{
-	return desc - &desc->chip->desc[0];
 }
 
 /**
@@ -174,7 +83,6 @@ struct gpio_desc *gpiochip_get_desc(stru
 
 	return &chip->desc[hwnum];
 }
-EXPORT_SYMBOL_GPL(gpiochip_get_desc);
 
 /**
  * Convert a GPIO descriptor to the integer namespace.
@@ -188,39 +96,6 @@ int desc_to_gpio(const struct gpio_desc
 EXPORT_SYMBOL_GPL(desc_to_gpio);
 
 
-/* Warn when drivers omit gpio_request() calls -- legal but ill-advised
- * when setting direction, and otherwise illegal.  Until board setup code
- * and drivers use explicit requests everywhere (which won't happen when
- * those calls have no teeth) we can't avoid autorequesting.  This nag
- * message should motivate switching to explicit requests... so should
- * the weaker cleanup after faults, compared to gpio_request().
- *
- * NOTE: the autorequest mechanism is going away; at this point it's
- * only "legal" in the sense that (old) code using it won't break yet,
- * but instead only triggers a WARN() stack dump.
- */
-static int gpio_ensure_requested(struct gpio_desc *desc)
-{
-	const struct gpio_chip *chip = desc->chip;
-	const int gpio = desc_to_gpio(desc);
-
-	if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0,
-			"autorequest GPIO-%d\n", gpio)) {
-		if (!try_module_get(chip->owner)) {
-			gpiod_err(desc, "%s: module can't be gotten\n",
-					__func__);
-			clear_bit(FLAG_REQUESTED, &desc->flags);
-			/* lose */
-			return -EIO;
-		}
-		desc_set_label(desc, "[auto]");
-		/* caller must chip->request() w/o spinlock */
-		if (chip->request)
-			return 1;
-	}
-	return 0;
-}
-
 /**
  * gpiod_to_chip - Return the GPIO chip to which a GPIO descriptor belongs
  * @desc:	descriptor to return the chip of
@@ -291,836 +166,6 @@ int gpiod_get_direction(const struct gpi
 }
 EXPORT_SYMBOL_GPL(gpiod_get_direction);
 
-#ifdef CONFIG_GPIO_SYSFS
-
-/* lock protects against unexport_gpio() being called while
- * sysfs files are active.
- */
-static DEFINE_MUTEX(sysfs_lock);
-
-/*
- * /sys/class/gpio/gpioN... only for GPIOs that are exported
- *   /direction
- *      * MAY BE OMITTED if kernel won't allow direction changes
- *      * is read/write as "in" or "out"
- *      * may also be written as "high" or "low", initializing
- *        output value as specified ("out" implies "low")
- *   /value
- *      * always readable, subject to hardware behavior
- *      * may be writable, as zero/nonzero
- *   /edge
- *      * configures behavior of poll(2) on /value
- *      * available only if pin can generate IRQs on input
- *      * is read/write as "none", "falling", "rising", or "both"
- *   /active_low
- *      * configures polarity of /value
- *      * is read/write as zero/nonzero
- *      * also affects existing and subsequent "falling" and "rising"
- *        /edge configuration
- */
-
-static ssize_t gpio_direction_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	const struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
-		status = -EIO;
-	} else {
-		gpiod_get_direction(desc);
-		status = sprintf(buf, "%s\n",
-			test_bit(FLAG_IS_OUT, &desc->flags)
-				? "out" : "in");
-	}
-
-	mutex_unlock(&sysfs_lock);
-	return status;
-}
-
-static ssize_t gpio_direction_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else if (sysfs_streq(buf, "high"))
-		status = gpiod_direction_output_raw(desc, 1);
-	else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
-		status = gpiod_direction_output_raw(desc, 0);
-	else if (sysfs_streq(buf, "in"))
-		status = gpiod_direction_input(desc);
-	else
-		status = -EINVAL;
-
-	mutex_unlock(&sysfs_lock);
-	return status ? : size;
-}
-
-static /* const */ DEVICE_ATTR(direction, 0644,
-		gpio_direction_show, gpio_direction_store);
-
-static ssize_t gpio_value_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else
-		status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
-
-	mutex_unlock(&sysfs_lock);
-	return status;
-}
-
-static ssize_t gpio_value_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else if (!test_bit(FLAG_IS_OUT, &desc->flags))
-		status = -EPERM;
-	else {
-		long		value;
-
-		status = kstrtol(buf, 0, &value);
-		if (status == 0) {
-			gpiod_set_value_cansleep(desc, value);
-			status = size;
-		}
-	}
-
-	mutex_unlock(&sysfs_lock);
-	return status;
-}
-
-static const DEVICE_ATTR(value, 0644,
-		gpio_value_show, gpio_value_store);
-
-static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
-{
-	struct kernfs_node	*value_sd = priv;
-
-	sysfs_notify_dirent(value_sd);
-	return IRQ_HANDLED;
-}
-
-static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
-		unsigned long gpio_flags)
-{
-	struct kernfs_node	*value_sd;
-	unsigned long		irq_flags;
-	int			ret, irq, id;
-
-	if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
-		return 0;
-
-	irq = gpiod_to_irq(desc);
-	if (irq < 0)
-		return -EIO;
-
-	id = desc->flags >> ID_SHIFT;
-	value_sd = idr_find(&dirent_idr, id);
-	if (value_sd)
-		free_irq(irq, value_sd);
-
-	desc->flags &= ~GPIO_TRIGGER_MASK;
-
-	if (!gpio_flags) {
-		gpiod_unlock_as_irq(desc);
-		ret = 0;
-		goto free_id;
-	}
-
-	irq_flags = IRQF_SHARED;
-	if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
-		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
-			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
-	if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
-		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
-			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
-
-	if (!value_sd) {
-		value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
-		if (!value_sd) {
-			ret = -ENODEV;
-			goto err_out;
-		}
-
-		ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
-		if (ret < 0)
-			goto free_sd;
-		id = ret;
-
-		desc->flags &= GPIO_FLAGS_MASK;
-		desc->flags |= (unsigned long)id << ID_SHIFT;
-
-		if (desc->flags >> ID_SHIFT != id) {
-			ret = -ERANGE;
-			goto free_id;
-		}
-	}
-
-	ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
-				"gpiolib", value_sd);
-	if (ret < 0)
-		goto free_id;
-
-	ret = gpiod_lock_as_irq(desc);
-	if (ret < 0) {
-		gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
-		goto free_id;
-	}
-
-	desc->flags |= gpio_flags;
-	return 0;
-
-free_id:
-	idr_remove(&dirent_idr, id);
-	desc->flags &= GPIO_FLAGS_MASK;
-free_sd:
-	if (value_sd)
-		sysfs_put(value_sd);
-err_out:
-	return ret;
-}
-
-static const struct {
-	const char *name;
-	unsigned long flags;
-} trigger_types[] = {
-	{ "none",    0 },
-	{ "falling", BIT(FLAG_TRIG_FALL) },
-	{ "rising",  BIT(FLAG_TRIG_RISE) },
-	{ "both",    BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
-};
-
-static ssize_t gpio_edge_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	const struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else {
-		int i;
-
-		status = 0;
-		for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
-			if ((desc->flags & GPIO_TRIGGER_MASK)
-					== trigger_types[i].flags) {
-				status = sprintf(buf, "%s\n",
-						 trigger_types[i].name);
-				break;
-			}
-	}
-
-	mutex_unlock(&sysfs_lock);
-	return status;
-}
-
-static ssize_t gpio_edge_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-	int			i;
-
-	for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
-		if (sysfs_streq(trigger_types[i].name, buf))
-			goto found;
-	return -EINVAL;
-
-found:
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else {
-		status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
-		if (!status)
-			status = size;
-	}
-
-	mutex_unlock(&sysfs_lock);
-
-	return status;
-}
-
-static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
-
-static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
-				int value)
-{
-	int			status = 0;
-
-	if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
-		return 0;
-
-	if (value)
-		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-	else
-		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
-	/* reconfigure poll(2) support if enabled on one edge only */
-	if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
-				!!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
-		unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
-
-		gpio_setup_irq(desc, dev, 0);
-		status = gpio_setup_irq(desc, dev, trigger_flags);
-	}
-
-	return status;
-}
-
-static ssize_t gpio_active_low_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	const struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		status = -EIO;
-	else
-		status = sprintf(buf, "%d\n",
-				!!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
-
-	mutex_unlock(&sysfs_lock);
-
-	return status;
-}
-
-static ssize_t gpio_active_low_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct gpio_desc	*desc = dev_get_drvdata(dev);
-	ssize_t			status;
-
-	mutex_lock(&sysfs_lock);
-
-	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
-		status = -EIO;
-	} else {
-		long		value;
-
-		status = kstrtol(buf, 0, &value);
-		if (status == 0)
-			status = sysfs_set_active_low(desc, dev, value != 0);
-	}
-
-	mutex_unlock(&sysfs_lock);
-
-	return status ? : size;
-}
-
-static const DEVICE_ATTR(active_low, 0644,
-		gpio_active_low_show, gpio_active_low_store);
-
-static const struct attribute *gpio_attrs[] = {
-	&dev_attr_value.attr,
-	&dev_attr_active_low.attr,
-	NULL,
-};
-
-static const struct attribute_group gpio_attr_group = {
-	.attrs = (struct attribute **) gpio_attrs,
-};
-
-/*
- * /sys/class/gpio/gpiochipN/
- *   /base ... matching gpio_chip.base (N)
- *   /label ... matching gpio_chip.label
- *   /ngpio ... matching gpio_chip.ngpio
- */
-
-static ssize_t chip_base_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	const struct gpio_chip	*chip = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%d\n", chip->base);
-}
-static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
-
-static ssize_t chip_label_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	const struct gpio_chip	*chip = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%s\n", chip->label ? : "");
-}
-static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
-
-static ssize_t chip_ngpio_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	const struct gpio_chip	*chip = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%u\n", chip->ngpio);
-}
-static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
-
-static const struct attribute *gpiochip_attrs[] = {
-	&dev_attr_base.attr,
-	&dev_attr_label.attr,
-	&dev_attr_ngpio.attr,
-	NULL,
-};
-
-static const struct attribute_group gpiochip_attr_group = {
-	.attrs = (struct attribute **) gpiochip_attrs,
-};
-
-/*
- * /sys/class/gpio/export ... write-only
- *	integer N ... number of GPIO to export (full access)
- * /sys/class/gpio/unexport ... write-only
- *	integer N ... number of GPIO to unexport
- */
-static ssize_t export_store(struct class *class,
-				struct class_attribute *attr,
-				const char *buf, size_t len)
-{
-	long			gpio;
-	struct gpio_desc	*desc;
-	int			status;
-
-	status = kstrtol(buf, 0, &gpio);
-	if (status < 0)
-		goto done;
-
-	desc = gpio_to_desc(gpio);
-	/* reject invalid GPIOs */
-	if (!desc) {
-		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
-		return -EINVAL;
-	}
-
-	/* No extra locking here; FLAG_SYSFS just signifies that the
-	 * request and export were done by on behalf of userspace, so
-	 * they may be undone on its behalf too.
-	 */
-
-	status = gpiod_request(desc, "sysfs");
-	if (status < 0) {
-		if (status == -EPROBE_DEFER)
-			status = -ENODEV;
-		goto done;
-	}
-	status = gpiod_export(desc, true);
-	if (status < 0)
-		gpiod_free(desc);
-	else
-		set_bit(FLAG_SYSFS, &desc->flags);
-
-done:
-	if (status)
-		pr_debug("%s: status %d\n", __func__, status);
-	return status ? : len;
-}
-
-static ssize_t unexport_store(struct class *class,
-				struct class_attribute *attr,
-				const char *buf, size_t len)
-{
-	long			gpio;
-	struct gpio_desc	*desc;
-	int			status;
-
-	status = kstrtol(buf, 0, &gpio);
-	if (status < 0)
-		goto done;
-
-	desc = gpio_to_desc(gpio);
-	/* reject bogus commands (gpio_unexport ignores them) */
-	if (!desc) {
-		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
-		return -EINVAL;
-	}
-
-	status = -EINVAL;
-
-	/* No extra locking here; FLAG_SYSFS just signifies that the
-	 * request and export were done by on behalf of userspace, so
-	 * they may be undone on its behalf too.
-	 */
-	if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
-		status = 0;
-		gpiod_free(desc);
-	}
-done:
-	if (status)
-		pr_debug("%s: status %d\n", __func__, status);
-	return status ? : len;
-}
-
-static struct class_attribute gpio_class_attrs[] = {
-	__ATTR(export, 0200, NULL, export_store),
-	__ATTR(unexport, 0200, NULL, unexport_store),
-	__ATTR_NULL,
-};
-
-static struct class gpio_class = {
-	.name =		"gpio",
-	.owner =	THIS_MODULE,
-
-	.class_attrs =	gpio_class_attrs,
-};
-
-
-/**
- * gpiod_export - export a GPIO through sysfs
- * @gpio: gpio to make available, already requested
- * @direction_may_change: true if userspace may change gpio direction
- * Context: arch_initcall or later
- *
- * When drivers want to make a GPIO accessible to userspace after they
- * have requested it -- perhaps while debugging, or as part of their
- * public interface -- they may use this routine.  If the GPIO can
- * change direction (some can't) and the caller allows it, userspace
- * will see "direction" sysfs attribute which may be used to change
- * the gpio's direction.  A "value" attribute will always be provided.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
-{
-	unsigned long		flags;
-	int			status;
-	const char		*ioname = NULL;
-	struct device		*dev;
-	int			offset;
-
-	/* can't export until sysfs is available ... */
-	if (!gpio_class.p) {
-		pr_debug("%s: called too early!\n", __func__);
-		return -ENOENT;
-	}
-
-	if (!desc) {
-		pr_debug("%s: invalid gpio descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&sysfs_lock);
-
-	spin_lock_irqsave(&gpio_lock, flags);
-	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
-	     test_bit(FLAG_EXPORT, &desc->flags)) {
-		spin_unlock_irqrestore(&gpio_lock, flags);
-		gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
-				__func__,
-				test_bit(FLAG_REQUESTED, &desc->flags),
-				test_bit(FLAG_EXPORT, &desc->flags));
-		status = -EPERM;
-		goto fail_unlock;
-	}
-
-	if (!desc->chip->direction_input || !desc->chip->direction_output)
-		direction_may_change = false;
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	offset = gpio_chip_hwgpio(desc);
-	if (desc->chip->names && desc->chip->names[offset])
-		ioname = desc->chip->names[offset];
-
-	dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
-			    desc, ioname ? ioname : "gpio%u",
-			    desc_to_gpio(desc));
-	if (IS_ERR(dev)) {
-		status = PTR_ERR(dev);
-		goto fail_unlock;
-	}
-
-	status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
-	if (status)
-		goto fail_unregister_device;
-
-	if (direction_may_change) {
-		status = device_create_file(dev, &dev_attr_direction);
-		if (status)
-			goto fail_unregister_device;
-	}
-
-	if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||
-				       !test_bit(FLAG_IS_OUT, &desc->flags))) {
-		status = device_create_file(dev, &dev_attr_edge);
-		if (status)
-			goto fail_unregister_device;
-	}
-
-	set_bit(FLAG_EXPORT, &desc->flags);
-	mutex_unlock(&sysfs_lock);
-	return 0;
-
-fail_unregister_device:
-	device_unregister(dev);
-fail_unlock:
-	mutex_unlock(&sysfs_lock);
-	gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-	return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_export);
-
-static int match_export(struct device *dev, const void *data)
-{
-	return dev_get_drvdata(dev) == data;
-}
-
-/**
- * gpiod_export_link - create a sysfs link to an exported GPIO node
- * @dev: device under which to create symlink
- * @name: name of the symlink
- * @gpio: gpio to create symlink to, already exported
- *
- * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
- * node. Caller is responsible for unlinking.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_export_link(struct device *dev, const char *name,
-		      struct gpio_desc *desc)
-{
-	int			status = -EINVAL;
-
-	if (!desc) {
-		pr_warn("%s: invalid GPIO\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&sysfs_lock);
-
-	if (test_bit(FLAG_EXPORT, &desc->flags)) {
-		struct device *tdev;
-
-		tdev = class_find_device(&gpio_class, NULL, desc, match_export);
-		if (tdev != NULL) {
-			status = sysfs_create_link(&dev->kobj, &tdev->kobj,
-						name);
-		} else {
-			status = -ENODEV;
-		}
-	}
-
-	mutex_unlock(&sysfs_lock);
-
-	if (status)
-		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
-	return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_export_link);
-
-/**
- * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
- * @gpio: gpio to change
- * @value: non-zero to use active low, i.e. inverted values
- *
- * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
- * The GPIO does not have to be exported yet.  If poll(2) support has
- * been enabled for either rising or falling edge, it will be
- * reconfigured to follow the new polarity.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
-{
-	struct device		*dev = NULL;
-	int			status = -EINVAL;
-
-	if (!desc) {
-		pr_warn("%s: invalid GPIO\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&sysfs_lock);
-
-	if (test_bit(FLAG_EXPORT, &desc->flags)) {
-		dev = class_find_device(&gpio_class, NULL, desc, match_export);
-		if (dev == NULL) {
-			status = -ENODEV;
-			goto unlock;
-		}
-	}
-
-	status = sysfs_set_active_low(desc, dev, value);
-
-unlock:
-	mutex_unlock(&sysfs_lock);
-
-	if (status)
-		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
-	return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
-
-/**
- * gpiod_unexport - reverse effect of gpio_export()
- * @gpio: gpio to make unavailable
- *
- * This is implicit on gpio_free().
- */
-void gpiod_unexport(struct gpio_desc *desc)
-{
-	int			status = 0;
-	struct device		*dev = NULL;
-
-	if (!desc) {
-		pr_warn("%s: invalid GPIO\n", __func__);
-		return;
-	}
-
-	mutex_lock(&sysfs_lock);
-
-	if (test_bit(FLAG_EXPORT, &desc->flags)) {
-
-		dev = class_find_device(&gpio_class, NULL, desc, match_export);
-		if (dev) {
-			gpio_setup_irq(desc, dev, 0);
-			clear_bit(FLAG_EXPORT, &desc->flags);
-		} else
-			status = -ENODEV;
-	}
-
-	mutex_unlock(&sysfs_lock);
-
-	if (dev) {
-		device_unregister(dev);
-		put_device(dev);
-	}
-
-	if (status)
-		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-}
-EXPORT_SYMBOL_GPL(gpiod_unexport);
-
-static int gpiochip_export(struct gpio_chip *chip)
-{
-	int		status;
-	struct device	*dev;
-
-	/* Many systems register gpio chips for SOC support very early,
-	 * before driver model support is available.  In those cases we
-	 * export this later, in gpiolib_sysfs_init() ... here we just
-	 * verify that _some_ field of gpio_class got initialized.
-	 */
-	if (!gpio_class.p)
-		return 0;
-
-	/* use chip->base for the ID; it's already known to be unique */
-	mutex_lock(&sysfs_lock);
-	dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
-				"gpiochip%d", chip->base);
-	if (!IS_ERR(dev)) {
-		status = sysfs_create_group(&dev->kobj,
-				&gpiochip_attr_group);
-	} else
-		status = PTR_ERR(dev);
-	chip->exported = (status == 0);
-	mutex_unlock(&sysfs_lock);
-
-	if (status) {
-		unsigned long	flags;
-		unsigned	gpio;
-
-		spin_lock_irqsave(&gpio_lock, flags);
-		gpio = 0;
-		while (gpio < chip->ngpio)
-			chip->desc[gpio++].chip = NULL;
-		spin_unlock_irqrestore(&gpio_lock, flags);
-
-		chip_dbg(chip, "%s: status %d\n", __func__, status);
-	}
-
-	return status;
-}
-
-static void gpiochip_unexport(struct gpio_chip *chip)
-{
-	int			status;
-	struct device		*dev;
-
-	mutex_lock(&sysfs_lock);
-	dev = class_find_device(&gpio_class, NULL, chip, match_export);
-	if (dev) {
-		put_device(dev);
-		device_unregister(dev);
-		chip->exported = false;
-		status = 0;
-	} else
-		status = -ENODEV;
-	mutex_unlock(&sysfs_lock);
-
-	if (status)
-		chip_dbg(chip, "%s: status %d\n", __func__, status);
-}
-
-static int __init gpiolib_sysfs_init(void)
-{
-	int		status;
-	unsigned long	flags;
-	struct gpio_chip *chip;
-
-	status = class_register(&gpio_class);
-	if (status < 0)
-		return status;
-
-	/* Scan and register the gpio_chips which registered very
-	 * early (e.g. before the class_register above was called).
-	 *
-	 * We run before arch_initcall() so chip->dev nodes can have
-	 * registered, and so arch_initcall() can always gpio_export().
-	 */
-	spin_lock_irqsave(&gpio_lock, flags);
-	list_for_each_entry(chip, &gpio_chips, list) {
-		if (!chip || chip->exported)
-			continue;
-
-		spin_unlock_irqrestore(&gpio_lock, flags);
-		status = gpiochip_export(chip);
-		spin_lock_irqsave(&gpio_lock, flags);
-	}
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-
-	return status;
-}
-postcore_initcall(gpiolib_sysfs_init);
-
-#else
-static inline int gpiochip_export(struct gpio_chip *chip)
-{
-	return 0;
-}
-
-static inline void gpiochip_unexport(struct gpio_chip *chip)
-{
-}
-
-#endif /* CONFIG_GPIO_SYSFS */
-
 /*
  * Add a new chip to the global chips list, keeping the list of chips sorted
  * by base order.
@@ -1368,12 +413,12 @@ void gpiochip_set_chained_irqchip(struct
 		return;
 	}
 
-	irq_set_chained_handler(parent_irq, parent_handler);
 	/*
 	 * The parent irqchip is already using the chip_data for this
 	 * irqchip, so our callbacks simply use the handler_data.
 	 */
 	irq_set_handler_data(parent_irq, gpiochip);
+	irq_set_chained_handler(parent_irq, parent_handler);
 }
 EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
 
@@ -1474,6 +519,8 @@ static void gpiochip_irqchip_remove(stru
 {
 	unsigned int offset;
 
+	acpi_gpiochip_free_interrupts(gpiochip);
+
 	/* Remove all IRQ mappings and delete the domain */
 	if (gpiochip->irqdomain) {
 		for (offset = 0; offset < gpiochip->ngpio; offset++)
@@ -1567,6 +614,8 @@ int gpiochip_irqchip_add(struct gpio_chi
 			gpiochip->irq_base = irq_base;
 	}
 
+	acpi_gpiochip_request_interrupts(gpiochip);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpiochip_irqchip_add);
@@ -1740,7 +789,7 @@ done:
 	return status;
 }
 
-static int gpiod_request(struct gpio_desc *desc, const char *label)
+int gpiod_request(struct gpio_desc *desc, const char *label)
 {
 	int status = -EPROBE_DEFER;
 	struct gpio_chip *chip;
@@ -1767,12 +816,6 @@ done:
 	return status;
 }
 
-int gpio_request(unsigned gpio, const char *label)
-{
-	return gpiod_request(gpio_to_desc(gpio), label);
-}
-EXPORT_SYMBOL_GPL(gpio_request);
-
 static bool __gpiod_free(struct gpio_desc *desc)
 {
 	bool			ret = false;
@@ -1805,7 +848,7 @@ static bool __gpiod_free(struct gpio_des
 	return ret;
 }
 
-static void gpiod_free(struct gpio_desc *desc)
+void gpiod_free(struct gpio_desc *desc)
 {
 	if (desc && __gpiod_free(desc))
 		module_put(desc->chip->owner);
@@ -1813,101 +856,14 @@ static void gpiod_free(struct gpio_desc
 		WARN_ON(extra_checks);
 }
 
-void gpio_free(unsigned gpio)
-{
-	gpiod_free(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_free);
-
-/**
- * gpio_request_one - request a single GPIO with initial configuration
- * @gpio:	the GPIO number
- * @flags:	GPIO configuration as specified by GPIOF_*
- * @label:	a literal description string of this GPIO
- */
-int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
-{
-	struct gpio_desc *desc;
-	int err;
-
-	desc = gpio_to_desc(gpio);
-
-	err = gpiod_request(desc, label);
-	if (err)
-		return err;
-
-	if (flags & GPIOF_OPEN_DRAIN)
-		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-
-	if (flags & GPIOF_OPEN_SOURCE)
-		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-
-	if (flags & GPIOF_DIR_IN)
-		err = gpiod_direction_input(desc);
-	else
-		err = gpiod_direction_output_raw(desc,
-				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
-
-	if (err)
-		goto free_gpio;
-
-	if (flags & GPIOF_EXPORT) {
-		err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
-		if (err)
-			goto free_gpio;
-	}
-
-	return 0;
-
- free_gpio:
-	gpiod_free(desc);
-	return err;
-}
-EXPORT_SYMBOL_GPL(gpio_request_one);
-
-/**
- * gpio_request_array - request multiple GPIOs in a single call
- * @array:	array of the 'struct gpio'
- * @num:	how many GPIOs in the array
- */
-int gpio_request_array(const struct gpio *array, size_t num)
-{
-	int i, err;
-
-	for (i = 0; i < num; i++, array++) {
-		err = gpio_request_one(array->gpio, array->flags, array->label);
-		if (err)
-			goto err_free;
-	}
-	return 0;
-
-err_free:
-	while (i--)
-		gpio_free((--array)->gpio);
-	return err;
-}
-EXPORT_SYMBOL_GPL(gpio_request_array);
-
-/**
- * gpio_free_array - release multiple GPIOs in a single call
- * @array:	array of the 'struct gpio'
- * @num:	how many GPIOs in the array
- */
-void gpio_free_array(const struct gpio *array, size_t num)
-{
-	while (num--)
-		gpio_free((array++)->gpio);
-}
-EXPORT_SYMBOL_GPL(gpio_free_array);
-
 /**
  * gpiochip_is_requested - return string iff signal was requested
  * @chip: controller managing the signal
  * @offset: of signal within controller's 0..(ngpio - 1) range
  *
  * Returns NULL if the GPIO is not currently requested, else a string.
- * If debugfs support is enabled, the string returned is the label passed
- * to gpio_request(); otherwise it is a meaningless constant.
+ * The string returned is the label passed to gpio_request(); if none has been
+ * passed it is a meaningless, non-NULL constant.
  *
  * This function is for use by GPIO controller drivers.  The label can
  * help with diagnostics, and knowing that the signal is used as a GPIO
@@ -1924,11 +880,7 @@ const char *gpiochip_is_requested(struct
 
 	if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
 		return NULL;
-#ifdef CONFIG_DEBUG_FS
 	return desc->label;
-#else
-	return "?";
-#endif
 }
 EXPORT_SYMBOL_GPL(gpiochip_is_requested);
 
@@ -1950,6 +902,7 @@ int gpiochip_request_own_desc(struct gpi
 
 	return __gpiod_request(desc, label);
 }
+EXPORT_SYMBOL_GPL(gpiochip_request_own_desc);
 
 /**
  * gpiochip_free_own_desc - Free GPIO requested by the chip driver
@@ -1963,6 +916,7 @@ void gpiochip_free_own_desc(struct gpio_
 	if (desc)
 		__gpiod_free(desc);
 }
+EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);
 
 /* Drivers MUST set GPIO direction before making get/set calls.  In
  * some cases this is done in early boot, before IRQs are enabled.
@@ -1984,10 +938,8 @@ void gpiochip_free_own_desc(struct gpio_
  */
 int gpiod_direction_input(struct gpio_desc *desc)
 {
-	unsigned long		flags;
 	struct gpio_chip	*chip;
 	int			status = -EINVAL;
-	int			offset;
 
 	if (!desc || !desc->chip) {
 		pr_warn("%s: invalid GPIO\n", __func__);
@@ -2002,52 +954,20 @@ int gpiod_direction_input(struct gpio_de
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	status = gpio_ensure_requested(desc);
-	if (status < 0)
-		goto fail;
-
-	/* now we know the gpio is valid and chip won't vanish */
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	might_sleep_if(chip->can_sleep);
-
-	offset = gpio_chip_hwgpio(desc);
-	if (status) {
-		status = chip->request(chip, offset);
-		if (status < 0) {
-			gpiod_dbg(desc, "%s: chip request fail, %d\n",
-					__func__, status);
-			/* and it's not available to anyone else ...
-			 * gpio_request() is the fully clean solution.
-			 */
-			goto lose;
-		}
-	}
-
-	status = chip->direction_input(chip, offset);
+	status = chip->direction_input(chip, gpio_chip_hwgpio(desc));
 	if (status == 0)
 		clear_bit(FLAG_IS_OUT, &desc->flags);
 
 	trace_gpio_direction(desc_to_gpio(desc), 1, status);
-lose:
-	return status;
-fail:
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	if (status)
-		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
 	return status;
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
 static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
-	unsigned long		flags;
 	struct gpio_chip	*chip;
 	int			status = -EINVAL;
-	int offset;
 
 	/* GPIOs used for IRQs shall not be set as output */
 	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
@@ -2073,42 +993,11 @@ static int _gpiod_direction_output_raw(s
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	status = gpio_ensure_requested(desc);
-	if (status < 0)
-		goto fail;
-
-	/* now we know the gpio is valid and chip won't vanish */
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	might_sleep_if(chip->can_sleep);
-
-	offset = gpio_chip_hwgpio(desc);
-	if (status) {
-		status = chip->request(chip, offset);
-		if (status < 0) {
-			gpiod_dbg(desc, "%s: chip request fail, %d\n",
-					__func__, status);
-			/* and it's not available to anyone else ...
-			 * gpio_request() is the fully clean solution.
-			 */
-			goto lose;
-		}
-	}
-
-	status = chip->direction_output(chip, offset, value);
+	status = chip->direction_output(chip, gpio_chip_hwgpio(desc), value);
 	if (status == 0)
 		set_bit(FLAG_IS_OUT, &desc->flags);
 	trace_gpio_value(desc_to_gpio(desc), 0, value);
 	trace_gpio_direction(desc_to_gpio(desc), 0, status);
-lose:
-	return status;
-fail:
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	if (status)
-		gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
 	return status;
 }
 
@@ -2167,10 +1056,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output
  */
 int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
 {
-	unsigned long		flags;
 	struct gpio_chip	*chip;
-	int			status = -EINVAL;
-	int			offset;
 
 	if (!desc || !desc->chip) {
 		pr_warn("%s: invalid GPIO\n", __func__);
@@ -2185,27 +1071,7 @@ int gpiod_set_debounce(struct gpio_desc
 		return -ENOTSUPP;
 	}
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	status = gpio_ensure_requested(desc);
-	if (status < 0)
-		goto fail;
-
-	/* now we know the gpio is valid and chip won't vanish */
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	might_sleep_if(chip->can_sleep);
-
-	offset = gpio_chip_hwgpio(desc);
-	return chip->set_debounce(chip, offset, debounce);
-
-fail:
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	if (status)
-		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
-	return status;
+	return chip->set_debounce(chip, gpio_chip_hwgpio(desc), debounce);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_debounce);
 
@@ -2448,54 +1314,44 @@ int gpiod_to_irq(const struct gpio_desc
 EXPORT_SYMBOL_GPL(gpiod_to_irq);
 
 /**
- * gpiod_lock_as_irq() - lock a GPIO to be used as IRQ
- * @gpio: the GPIO line to lock as used for IRQ
+ * gpio_lock_as_irq() - lock a GPIO to be used as IRQ
+ * @chip: the chip the GPIO to lock belongs to
+ * @offset: the offset of the GPIO to lock as IRQ
  *
  * This is used directly by GPIO drivers that want to lock down
  * a certain GPIO line to be used for IRQs.
  */
-int gpiod_lock_as_irq(struct gpio_desc *desc)
+int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	if (!desc)
+	if (offset >= chip->ngpio)
 		return -EINVAL;
 
-	if (test_bit(FLAG_IS_OUT, &desc->flags)) {
-		gpiod_err(desc,
+	if (test_bit(FLAG_IS_OUT, &chip->desc[offset].flags)) {
+		chip_err(chip,
 			  "%s: tried to flag a GPIO set as output for IRQ\n",
 			  __func__);
 		return -EIO;
 	}
 
-	set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+	set_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
-
-int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	return gpiod_lock_as_irq(gpiochip_get_desc(chip, offset));
-}
 EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
 
 /**
- * gpiod_unlock_as_irq() - unlock a GPIO used as IRQ
- * @gpio: the GPIO line to unlock from IRQ usage
+ * gpio_unlock_as_irq() - unlock a GPIO used as IRQ
+ * @chip: the chip the GPIO to lock belongs to
+ * @offset: the offset of the GPIO to lock as IRQ
  *
  * This is used directly by GPIO drivers that want to indicate
  * that a certain GPIO is no longer used exclusively for IRQ.
  */
-void gpiod_unlock_as_irq(struct gpio_desc *desc)
+void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	if (!desc)
+	if (offset >= chip->ngpio)
 		return;
 
-	clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
-}
-EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
-
-void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	return gpiod_unlock_as_irq(gpiochip_get_desc(chip, offset));
+	clear_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
 }
 EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
 
@@ -2726,38 +1582,43 @@ static struct gpio_desc *gpiod_find(stru
  * gpiod_get - obtain a GPIO for a given GPIO function
  * @dev:	GPIO consumer, can be NULL for system-global GPIOs
  * @con_id:	function within the GPIO consumer
+ * @flags:	optional GPIO initialization flags
  *
  * Return the GPIO descriptor corresponding to the function con_id of device
  * dev, -ENOENT if no GPIO has been assigned to the requested function, or
  * another IS_ERR() code if an error occured while trying to acquire the GPIO.
  */
-struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
+struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id,
+					 enum gpiod_flags flags)
 {
-	return gpiod_get_index(dev, con_id, 0);
+	return gpiod_get_index(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL_GPL(gpiod_get);
+EXPORT_SYMBOL_GPL(__gpiod_get);
 
 /**
  * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
  * @dev: GPIO consumer, can be NULL for system-global GPIOs
  * @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
  *
  * This is equivalent to gpiod_get(), except that when no GPIO was assigned to
  * the requested function it will return NULL. This is convenient for drivers
  * that need to handle optional GPIOs.
  */
-struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
-						  const char *con_id)
+struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
+						  const char *con_id,
+						  enum gpiod_flags flags)
 {
-	return gpiod_get_index_optional(dev, con_id, 0);
+	return gpiod_get_index_optional(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL_GPL(gpiod_get_optional);
+EXPORT_SYMBOL_GPL(__gpiod_get_optional);
 
 /**
  * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
  * @dev:	GPIO consumer, can be NULL for system-global GPIOs
  * @con_id:	function within the GPIO consumer
  * @idx:	index of the GPIO to obtain in the consumer
+ * @flags:	optional GPIO initialization flags
  *
  * This variant of gpiod_get() allows to access GPIOs other than the first
  * defined one for functions that define several GPIOs.
@@ -2766,23 +1627,24 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
  * requested function and/or index, or another IS_ERR() code if an error
  * occured while trying to acquire the GPIO.
  */
-struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
 					       const char *con_id,
-					       unsigned int idx)
+					       unsigned int idx,
+					       enum gpiod_flags flags)
 {
 	struct gpio_desc *desc = NULL;
 	int status;
-	enum gpio_lookup_flags flags = 0;
+	enum gpio_lookup_flags lookupflags = 0;
 
 	dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
 
 	/* Using device tree? */
 	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
 		dev_dbg(dev, "using device tree for GPIO lookup\n");
-		desc = of_find_gpio(dev, con_id, idx, &flags);
+		desc = of_find_gpio(dev, con_id, idx, &lookupflags);
 	} else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
 		dev_dbg(dev, "using ACPI for GPIO lookup\n");
-		desc = acpi_find_gpio(dev, con_id, idx, &flags);
+		desc = acpi_find_gpio(dev, con_id, idx, &lookupflags);
 	}
 
 	/*
@@ -2791,7 +1653,7 @@ struct gpio_desc *__must_check gpiod_get
 	 */
 	if (!desc || desc == ERR_PTR(-ENOENT)) {
 		dev_dbg(dev, "using lookup tables for GPIO lookup");
-		desc = gpiod_find(dev, con_id, idx, &flags);
+		desc = gpiod_find(dev, con_id, idx, &lookupflags);
 	}
 
 	if (IS_ERR(desc)) {
@@ -2804,16 +1666,33 @@ struct gpio_desc *__must_check gpiod_get
 	if (status < 0)
 		return ERR_PTR(status);
 
-	if (flags & GPIO_ACTIVE_LOW)
+	if (lookupflags & GPIO_ACTIVE_LOW)
 		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-	if (flags & GPIO_OPEN_DRAIN)
+	if (lookupflags & GPIO_OPEN_DRAIN)
 		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-	if (flags & GPIO_OPEN_SOURCE)
+	if (lookupflags & GPIO_OPEN_SOURCE)
 		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 
+	/* No particular flag request, return here... */
+	if (!(flags & GPIOD_FLAGS_BIT_DIR_SET))
+		return desc;
+
+	/* Process flags */
+	if (flags & GPIOD_FLAGS_BIT_DIR_OUT)
+		status = gpiod_direction_output(desc,
+					      flags & GPIOD_FLAGS_BIT_DIR_VAL);
+	else
+		status = gpiod_direction_input(desc);
+
+	if (status < 0) {
+		dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
+		gpiod_put(desc);
+		return ERR_PTR(status);
+	}
+
 	return desc;
 }
-EXPORT_SYMBOL_GPL(gpiod_get_index);
+EXPORT_SYMBOL_GPL(__gpiod_get_index);
 
 /**
  * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
@@ -2821,18 +1700,20 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
  * @dev: GPIO consumer, can be NULL for system-global GPIOs
  * @con_id: function within the GPIO consumer
  * @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
  *
  * This is equivalent to gpiod_get_index(), except that when no GPIO with the
  * specified index was assigned to the requested function it will return NULL.
  * This is convenient for drivers that need to handle optional GPIOs.
  */
-struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
 							const char *con_id,
-							unsigned int index)
+							unsigned int index,
+							enum gpiod_flags flags)
 {
 	struct gpio_desc *desc;
 
-	desc = gpiod_get_index(dev, con_id, index);
+	desc = gpiod_get_index(dev, con_id, index, flags);
 	if (IS_ERR(desc)) {
 		if (PTR_ERR(desc) == -ENOENT)
 			return NULL;
@@ -2840,7 +1721,7 @@ struct gpio_desc *__must_check gpiod_get
 
 	return desc;
 }
-EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
+EXPORT_SYMBOL_GPL(__gpiod_get_index_optional);
 
 /**
  * gpiod_put - dispose of a GPIO descriptor
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib.h linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib.h
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib.h	2014-09-28 17:29:07.000000000 -0400
@@ -31,12 +31,21 @@ struct acpi_gpio_info {
 void acpi_gpiochip_add(struct gpio_chip *chip);
 void acpi_gpiochip_remove(struct gpio_chip *chip);
 
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
+
 struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 					  struct acpi_gpio_info *info);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
 static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
 
+static inline void
+acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
+
+static inline void
+acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
+
 static inline struct gpio_desc *
 acpi_get_gpiod_by_index(struct device *dev, int index,
 			struct acpi_gpio_info *info)
@@ -45,10 +54,100 @@ acpi_get_gpiod_by_index(struct device *d
 }
 #endif
 
-int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
-void gpiochip_free_own_desc(struct gpio_desc *desc);
-
 struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 		   const char *list_name, int index, enum of_gpio_flags *flags);
 
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
+
+extern struct spinlock gpio_lock;
+extern struct list_head gpio_chips;
+
+struct gpio_desc {
+	struct gpio_chip	*chip;
+	unsigned long		flags;
+/* flag symbols are bit numbers */
+#define FLAG_REQUESTED	0
+#define FLAG_IS_OUT	1
+#define FLAG_EXPORT	2	/* protected by sysfs_lock */
+#define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */
+#define FLAG_TRIG_FALL	4	/* trigger on falling edge */
+#define FLAG_TRIG_RISE	5	/* trigger on rising edge */
+#define FLAG_ACTIVE_LOW	6	/* value has active low */
+#define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */
+#define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
+#define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
+
+#define ID_SHIFT	16	/* add new flags before this one */
+
+#define GPIO_FLAGS_MASK		((1 << ID_SHIFT) - 1)
+#define GPIO_TRIGGER_MASK	(BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
+
+	const char		*label;
+};
+
+int gpiod_request(struct gpio_desc *desc, const char *label);
+void gpiod_free(struct gpio_desc *desc);
+
+/*
+ * Return the GPIO number of the passed descriptor relative to its chip
+ */
+static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
+{
+	return desc - &desc->chip->desc[0];
+}
+
+/* With descriptor prefix */
+
+#define gpiod_emerg(desc, fmt, ...)					       \
+	pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
+		 ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...)					       \
+	pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+		 ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...)					       \
+	pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",  \
+		 ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...)					       \
+	pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+		 ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...)					       \
+	pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+		 ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...)					       \
+	pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
+		 ##__VA_ARGS__)
+
+/* With chip prefix */
+
+#define chip_emerg(chip, fmt, ...)					\
+	pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_crit(chip, fmt, ...)					\
+	pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_err(chip, fmt, ...)					\
+	pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_warn(chip, fmt, ...)					\
+	pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_info(chip, fmt, ...)					\
+	pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_dbg(chip, fmt, ...)					\
+	pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+
+#ifdef CONFIG_GPIO_SYSFS
+
+int gpiochip_export(struct gpio_chip *chip);
+void gpiochip_unexport(struct gpio_chip *chip);
+
+#else
+
+static inline int gpiochip_export(struct gpio_chip *chip)
+{
+	return 0;
+}
+
+static inline void gpiochip_unexport(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_GPIO_SYSFS */
+
 #endif /* GPIOLIB_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib-legacy.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-legacy.c
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib-legacy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-legacy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,102 @@
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+#include <linux/gpio.h>
+
+#include "gpiolib.h"
+
+void gpio_free(unsigned gpio)
+{
+	gpiod_free(gpio_to_desc(gpio));
+}
+EXPORT_SYMBOL_GPL(gpio_free);
+
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio:	the GPIO number
+ * @flags:	GPIO configuration as specified by GPIOF_*
+ * @label:	a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+	struct gpio_desc *desc;
+	int err;
+
+	desc = gpio_to_desc(gpio);
+
+	err = gpiod_request(desc, label);
+	if (err)
+		return err;
+
+	if (flags & GPIOF_OPEN_DRAIN)
+		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+
+	if (flags & GPIOF_OPEN_SOURCE)
+		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
+	if (flags & GPIOF_ACTIVE_LOW)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	if (flags & GPIOF_DIR_IN)
+		err = gpiod_direction_input(desc);
+	else
+		err = gpiod_direction_output_raw(desc,
+				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+	if (err)
+		goto free_gpio;
+
+	if (flags & GPIOF_EXPORT) {
+		err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
+		if (err)
+			goto free_gpio;
+	}
+
+	return 0;
+
+ free_gpio:
+	gpiod_free(desc);
+	return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+int gpio_request(unsigned gpio, const char *label)
+{
+	return gpiod_request(gpio_to_desc(gpio), label);
+}
+EXPORT_SYMBOL_GPL(gpio_request);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array:	array of the 'struct gpio'
+ * @num:	how many GPIOs in the array
+ */
+int gpio_request_array(const struct gpio *array, size_t num)
+{
+	int i, err;
+
+	for (i = 0; i < num; i++, array++) {
+		err = gpio_request_one(array->gpio, array->flags, array->label);
+		if (err)
+			goto err_free;
+	}
+	return 0;
+
+err_free:
+	while (i--)
+		gpio_free((--array)->gpio);
+	return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array:	array of the 'struct gpio'
+ * @num:	how many GPIOs in the array
+ */
+void gpio_free_array(const struct gpio *array, size_t num)
+{
+	while (num--)
+		gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib-of.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-of.c
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib-of.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-of.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
-struct gpio_desc;
+#include "gpiolib.h"
 
 /* Private data structure for of_gpiochip_find_and_xlate */
 struct gg_data {
@@ -82,19 +82,19 @@ struct gpio_desc *of_get_named_gpiod_fla
 	ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
 					 &gg_data.gpiospec);
 	if (ret) {
-		pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
-			__func__, np->full_name, index);
+		pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n",
+			__func__, propname, np->full_name, index);
 		return ERR_PTR(ret);
 	}
 
 	gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
 
 	of_node_put(gg_data.gpiospec.np);
-	pr_debug("%s exited with status %d\n", __func__,
+	pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n",
+		 __func__, propname, np->full_name, index,
 		 PTR_ERR_OR_ZERO(gg_data.out_gpio));
 	return gg_data.out_gpio;
 }
-EXPORT_SYMBOL(of_get_named_gpiod_flags);
 
 int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
 			    int index, enum of_gpio_flags *flags)
@@ -307,7 +307,5 @@ void of_gpiochip_add(struct gpio_chip *c
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
 	gpiochip_remove_pin_ranges(chip);
-
-	if (chip->of_node)
-		of_node_put(chip->of_node);
+	of_node_put(chip->of_node);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpiolib-sysfs.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-sysfs.c
--- linux-libre-3.16-gnu/drivers/gpio/gpiolib-sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpiolib-sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,827 @@
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+
+#include "gpiolib.h"
+
+static DEFINE_IDR(dirent_idr);
+
+
+/* lock protects against unexport_gpio() being called while
+ * sysfs files are active.
+ */
+static DEFINE_MUTEX(sysfs_lock);
+
+/*
+ * /sys/class/gpio/gpioN... only for GPIOs that are exported
+ *   /direction
+ *      * MAY BE OMITTED if kernel won't allow direction changes
+ *      * is read/write as "in" or "out"
+ *      * may also be written as "high" or "low", initializing
+ *        output value as specified ("out" implies "low")
+ *   /value
+ *      * always readable, subject to hardware behavior
+ *      * may be writable, as zero/nonzero
+ *   /edge
+ *      * configures behavior of poll(2) on /value
+ *      * available only if pin can generate IRQs on input
+ *      * is read/write as "none", "falling", "rising", or "both"
+ *   /active_low
+ *      * configures polarity of /value
+ *      * is read/write as zero/nonzero
+ *      * also affects existing and subsequent "falling" and "rising"
+ *        /edge configuration
+ */
+
+static ssize_t gpio_direction_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+		status = -EIO;
+	} else {
+		gpiod_get_direction(desc);
+		status = sprintf(buf, "%s\n",
+			test_bit(FLAG_IS_OUT, &desc->flags)
+				? "out" : "in");
+	}
+
+	mutex_unlock(&sysfs_lock);
+	return status;
+}
+
+static ssize_t gpio_direction_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else if (sysfs_streq(buf, "high"))
+		status = gpiod_direction_output_raw(desc, 1);
+	else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
+		status = gpiod_direction_output_raw(desc, 0);
+	else if (sysfs_streq(buf, "in"))
+		status = gpiod_direction_input(desc);
+	else
+		status = -EINVAL;
+
+	mutex_unlock(&sysfs_lock);
+	return status ? : size;
+}
+
+static /* const */ DEVICE_ATTR(direction, 0644,
+		gpio_direction_show, gpio_direction_store);
+
+static ssize_t gpio_value_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
+
+	mutex_unlock(&sysfs_lock);
+	return status;
+}
+
+static ssize_t gpio_value_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else if (!test_bit(FLAG_IS_OUT, &desc->flags))
+		status = -EPERM;
+	else {
+		long		value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0) {
+			gpiod_set_value_cansleep(desc, value);
+			status = size;
+		}
+	}
+
+	mutex_unlock(&sysfs_lock);
+	return status;
+}
+
+static const DEVICE_ATTR(value, 0644,
+		gpio_value_show, gpio_value_store);
+
+static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
+{
+	struct kernfs_node	*value_sd = priv;
+
+	sysfs_notify_dirent(value_sd);
+	return IRQ_HANDLED;
+}
+
+static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
+		unsigned long gpio_flags)
+{
+	struct kernfs_node	*value_sd;
+	unsigned long		irq_flags;
+	int			ret, irq, id;
+
+	if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
+		return 0;
+
+	irq = gpiod_to_irq(desc);
+	if (irq < 0)
+		return -EIO;
+
+	id = desc->flags >> ID_SHIFT;
+	value_sd = idr_find(&dirent_idr, id);
+	if (value_sd)
+		free_irq(irq, value_sd);
+
+	desc->flags &= ~GPIO_TRIGGER_MASK;
+
+	if (!gpio_flags) {
+		gpio_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+		ret = 0;
+		goto free_id;
+	}
+
+	irq_flags = IRQF_SHARED;
+	if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
+		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
+	if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
+		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+
+	if (!value_sd) {
+		value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
+		if (!value_sd) {
+			ret = -ENODEV;
+			goto err_out;
+		}
+
+		ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
+		if (ret < 0)
+			goto free_sd;
+		id = ret;
+
+		desc->flags &= GPIO_FLAGS_MASK;
+		desc->flags |= (unsigned long)id << ID_SHIFT;
+
+		if (desc->flags >> ID_SHIFT != id) {
+			ret = -ERANGE;
+			goto free_id;
+		}
+	}
+
+	ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
+				"gpiolib", value_sd);
+	if (ret < 0)
+		goto free_id;
+
+	ret = gpio_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+	if (ret < 0) {
+		gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
+		goto free_id;
+	}
+
+	desc->flags |= gpio_flags;
+	return 0;
+
+free_id:
+	idr_remove(&dirent_idr, id);
+	desc->flags &= GPIO_FLAGS_MASK;
+free_sd:
+	if (value_sd)
+		sysfs_put(value_sd);
+err_out:
+	return ret;
+}
+
+static const struct {
+	const char *name;
+	unsigned long flags;
+} trigger_types[] = {
+	{ "none",    0 },
+	{ "falling", BIT(FLAG_TRIG_FALL) },
+	{ "rising",  BIT(FLAG_TRIG_RISE) },
+	{ "both",    BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
+};
+
+static ssize_t gpio_edge_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else {
+		int i;
+
+		status = 0;
+		for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
+			if ((desc->flags & GPIO_TRIGGER_MASK)
+					== trigger_types[i].flags) {
+				status = sprintf(buf, "%s\n",
+						 trigger_types[i].name);
+				break;
+			}
+	}
+
+	mutex_unlock(&sysfs_lock);
+	return status;
+}
+
+static ssize_t gpio_edge_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+	int			i;
+
+	for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
+		if (sysfs_streq(trigger_types[i].name, buf))
+			goto found;
+	return -EINVAL;
+
+found:
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else {
+		status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
+		if (!status)
+			status = size;
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
+
+static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
+				int value)
+{
+	int			status = 0;
+
+	if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
+		return 0;
+
+	if (value)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+	else
+		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	/* reconfigure poll(2) support if enabled on one edge only */
+	if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
+				!!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
+		unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
+
+		gpio_setup_irq(desc, dev, 0);
+		status = gpio_setup_irq(desc, dev, trigger_flags);
+	}
+
+	return status;
+}
+
+static ssize_t gpio_active_low_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n",
+				!!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t gpio_active_low_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+		status = -EIO;
+	} else {
+		long		value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0)
+			status = sysfs_set_active_low(desc, dev, value != 0);
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status ? : size;
+}
+
+static const DEVICE_ATTR(active_low, 0644,
+		gpio_active_low_show, gpio_active_low_store);
+
+static const struct attribute *gpio_attrs[] = {
+	&dev_attr_value.attr,
+	&dev_attr_active_low.attr,
+	NULL,
+};
+
+static const struct attribute_group gpio_attr_group = {
+	.attrs = (struct attribute **) gpio_attrs,
+};
+
+/*
+ * /sys/class/gpio/gpiochipN/
+ *   /base ... matching gpio_chip.base (N)
+ *   /label ... matching gpio_chip.label
+ *   /ngpio ... matching gpio_chip.ngpio
+ */
+
+static ssize_t chip_base_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	const struct gpio_chip	*chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", chip->base);
+}
+static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
+
+static ssize_t chip_label_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	const struct gpio_chip	*chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", chip->label ? : "");
+}
+static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
+
+static ssize_t chip_ngpio_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	const struct gpio_chip	*chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", chip->ngpio);
+}
+static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
+
+static const struct attribute *gpiochip_attrs[] = {
+	&dev_attr_base.attr,
+	&dev_attr_label.attr,
+	&dev_attr_ngpio.attr,
+	NULL,
+};
+
+static const struct attribute_group gpiochip_attr_group = {
+	.attrs = (struct attribute **) gpiochip_attrs,
+};
+
+/*
+ * /sys/class/gpio/export ... write-only
+ *	integer N ... number of GPIO to export (full access)
+ * /sys/class/gpio/unexport ... write-only
+ *	integer N ... number of GPIO to unexport
+ */
+static ssize_t export_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
+{
+	long			gpio;
+	struct gpio_desc	*desc;
+	int			status;
+
+	status = kstrtol(buf, 0, &gpio);
+	if (status < 0)
+		goto done;
+
+	desc = gpio_to_desc(gpio);
+	/* reject invalid GPIOs */
+	if (!desc) {
+		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+		return -EINVAL;
+	}
+
+	/* No extra locking here; FLAG_SYSFS just signifies that the
+	 * request and export were done by on behalf of userspace, so
+	 * they may be undone on its behalf too.
+	 */
+
+	status = gpiod_request(desc, "sysfs");
+	if (status < 0) {
+		if (status == -EPROBE_DEFER)
+			status = -ENODEV;
+		goto done;
+	}
+	status = gpiod_export(desc, true);
+	if (status < 0)
+		gpiod_free(desc);
+	else
+		set_bit(FLAG_SYSFS, &desc->flags);
+
+done:
+	if (status)
+		pr_debug("%s: status %d\n", __func__, status);
+	return status ? : len;
+}
+
+static ssize_t unexport_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
+{
+	long			gpio;
+	struct gpio_desc	*desc;
+	int			status;
+
+	status = kstrtol(buf, 0, &gpio);
+	if (status < 0)
+		goto done;
+
+	desc = gpio_to_desc(gpio);
+	/* reject bogus commands (gpio_unexport ignores them) */
+	if (!desc) {
+		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+		return -EINVAL;
+	}
+
+	status = -EINVAL;
+
+	/* No extra locking here; FLAG_SYSFS just signifies that the
+	 * request and export were done by on behalf of userspace, so
+	 * they may be undone on its behalf too.
+	 */
+	if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
+		status = 0;
+		gpiod_free(desc);
+	}
+done:
+	if (status)
+		pr_debug("%s: status %d\n", __func__, status);
+	return status ? : len;
+}
+
+static struct class_attribute gpio_class_attrs[] = {
+	__ATTR(export, 0200, NULL, export_store),
+	__ATTR(unexport, 0200, NULL, unexport_store),
+	__ATTR_NULL,
+};
+
+static struct class gpio_class = {
+	.name =		"gpio",
+	.owner =	THIS_MODULE,
+
+	.class_attrs =	gpio_class_attrs,
+};
+
+
+/**
+ * gpiod_export - export a GPIO through sysfs
+ * @gpio: gpio to make available, already requested
+ * @direction_may_change: true if userspace may change gpio direction
+ * Context: arch_initcall or later
+ *
+ * When drivers want to make a GPIO accessible to userspace after they
+ * have requested it -- perhaps while debugging, or as part of their
+ * public interface -- they may use this routine.  If the GPIO can
+ * change direction (some can't) and the caller allows it, userspace
+ * will see "direction" sysfs attribute which may be used to change
+ * the gpio's direction.  A "value" attribute will always be provided.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+{
+	unsigned long		flags;
+	int			status;
+	const char		*ioname = NULL;
+	struct device		*dev;
+	int			offset;
+
+	/* can't export until sysfs is available ... */
+	if (!gpio_class.p) {
+		pr_debug("%s: called too early!\n", __func__);
+		return -ENOENT;
+	}
+
+	if (!desc) {
+		pr_debug("%s: invalid gpio descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&sysfs_lock);
+
+	spin_lock_irqsave(&gpio_lock, flags);
+	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+	     test_bit(FLAG_EXPORT, &desc->flags)) {
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
+				__func__,
+				test_bit(FLAG_REQUESTED, &desc->flags),
+				test_bit(FLAG_EXPORT, &desc->flags));
+		status = -EPERM;
+		goto fail_unlock;
+	}
+
+	if (!desc->chip->direction_input || !desc->chip->direction_output)
+		direction_may_change = false;
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	offset = gpio_chip_hwgpio(desc);
+	if (desc->chip->names && desc->chip->names[offset])
+		ioname = desc->chip->names[offset];
+
+	dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+			    desc, ioname ? ioname : "gpio%u",
+			    desc_to_gpio(desc));
+	if (IS_ERR(dev)) {
+		status = PTR_ERR(dev);
+		goto fail_unlock;
+	}
+
+	status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
+	if (status)
+		goto fail_unregister_device;
+
+	if (direction_may_change) {
+		status = device_create_file(dev, &dev_attr_direction);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||
+				       !test_bit(FLAG_IS_OUT, &desc->flags))) {
+		status = device_create_file(dev, &dev_attr_edge);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	set_bit(FLAG_EXPORT, &desc->flags);
+	mutex_unlock(&sysfs_lock);
+	return 0;
+
+fail_unregister_device:
+	device_unregister(dev);
+fail_unlock:
+	mutex_unlock(&sysfs_lock);
+	gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+	return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_export);
+
+static int match_export(struct device *dev, const void *data)
+{
+	return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * gpiod_export_link - create a sysfs link to an exported GPIO node
+ * @dev: device under which to create symlink
+ * @name: name of the symlink
+ * @gpio: gpio to create symlink to, already exported
+ *
+ * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
+ * node. Caller is responsible for unlinking.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_export_link(struct device *dev, const char *name,
+		      struct gpio_desc *desc)
+{
+	int			status = -EINVAL;
+
+	if (!desc) {
+		pr_warn("%s: invalid GPIO\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&sysfs_lock);
+
+	if (test_bit(FLAG_EXPORT, &desc->flags)) {
+		struct device *tdev;
+
+		tdev = class_find_device(&gpio_class, NULL, desc, match_export);
+		if (tdev != NULL) {
+			status = sysfs_create_link(&dev->kobj, &tdev->kobj,
+						name);
+		} else {
+			status = -ENODEV;
+		}
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	if (status)
+		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_export_link);
+
+/**
+ * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
+ * @gpio: gpio to change
+ * @value: non-zero to use active low, i.e. inverted values
+ *
+ * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
+ * The GPIO does not have to be exported yet.  If poll(2) support has
+ * been enabled for either rising or falling edge, it will be
+ * reconfigured to follow the new polarity.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
+{
+	struct device		*dev = NULL;
+	int			status = -EINVAL;
+
+	if (!desc) {
+		pr_warn("%s: invalid GPIO\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&sysfs_lock);
+
+	if (test_bit(FLAG_EXPORT, &desc->flags)) {
+		dev = class_find_device(&gpio_class, NULL, desc, match_export);
+		if (dev == NULL) {
+			status = -ENODEV;
+			goto unlock;
+		}
+	}
+
+	status = sysfs_set_active_low(desc, dev, value);
+
+unlock:
+	mutex_unlock(&sysfs_lock);
+
+	if (status)
+		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
+
+/**
+ * gpiod_unexport - reverse effect of gpio_export()
+ * @gpio: gpio to make unavailable
+ *
+ * This is implicit on gpio_free().
+ */
+void gpiod_unexport(struct gpio_desc *desc)
+{
+	int			status = 0;
+	struct device		*dev = NULL;
+
+	if (!desc) {
+		pr_warn("%s: invalid GPIO\n", __func__);
+		return;
+	}
+
+	mutex_lock(&sysfs_lock);
+
+	if (test_bit(FLAG_EXPORT, &desc->flags)) {
+
+		dev = class_find_device(&gpio_class, NULL, desc, match_export);
+		if (dev) {
+			gpio_setup_irq(desc, dev, 0);
+			clear_bit(FLAG_EXPORT, &desc->flags);
+		} else
+			status = -ENODEV;
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	if (dev) {
+		device_unregister(dev);
+		put_device(dev);
+	}
+
+	if (status)
+		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+}
+EXPORT_SYMBOL_GPL(gpiod_unexport);
+
+int gpiochip_export(struct gpio_chip *chip)
+{
+	int		status;
+	struct device	*dev;
+
+	/* Many systems register gpio chips for SOC support very early,
+	 * before driver model support is available.  In those cases we
+	 * export this later, in gpiolib_sysfs_init() ... here we just
+	 * verify that _some_ field of gpio_class got initialized.
+	 */
+	if (!gpio_class.p)
+		return 0;
+
+	/* use chip->base for the ID; it's already known to be unique */
+	mutex_lock(&sysfs_lock);
+	dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
+				"gpiochip%d", chip->base);
+	if (!IS_ERR(dev)) {
+		status = sysfs_create_group(&dev->kobj,
+				&gpiochip_attr_group);
+	} else
+		status = PTR_ERR(dev);
+	chip->exported = (status == 0);
+	mutex_unlock(&sysfs_lock);
+
+	if (status)
+		chip_dbg(chip, "%s: status %d\n", __func__, status);
+
+	return status;
+}
+
+void gpiochip_unexport(struct gpio_chip *chip)
+{
+	int			status;
+	struct device		*dev;
+
+	mutex_lock(&sysfs_lock);
+	dev = class_find_device(&gpio_class, NULL, chip, match_export);
+	if (dev) {
+		put_device(dev);
+		device_unregister(dev);
+		chip->exported = false;
+		status = 0;
+	} else
+		status = -ENODEV;
+	mutex_unlock(&sysfs_lock);
+
+	if (status)
+		chip_dbg(chip, "%s: status %d\n", __func__, status);
+}
+
+static int __init gpiolib_sysfs_init(void)
+{
+	int		status;
+	unsigned long	flags;
+	struct gpio_chip *chip;
+
+	status = class_register(&gpio_class);
+	if (status < 0)
+		return status;
+
+	/* Scan and register the gpio_chips which registered very
+	 * early (e.g. before the class_register above was called).
+	 *
+	 * We run before arch_initcall() so chip->dev nodes can have
+	 * registered, and so arch_initcall() can always gpio_export().
+	 */
+	spin_lock_irqsave(&gpio_lock, flags);
+	list_for_each_entry(chip, &gpio_chips, list) {
+		if (chip->exported)
+			continue;
+
+		/*
+		 * TODO we yield gpio_lock here because gpiochip_export()
+		 * acquires a mutex. This is unsafe and needs to be fixed.
+		 *
+		 * Also it would be nice to use gpiochip_find() here so we
+		 * can keep gpio_chips local to gpiolib.c, but the yield of
+		 * gpio_lock prevents us from doing this.
+		 */
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		status = gpiochip_export(chip);
+		spin_lock_irqsave(&gpio_lock, flags);
+	}
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+
+	return status;
+}
+postcore_initcall(gpiolib_sysfs_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-lp3943.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lp3943.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-lp3943.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lp3943.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,7 +216,8 @@ static int lp3943_gpio_remove(struct pla
 {
 	struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&lp3943_gpio->chip);
+	gpiochip_remove(&lp3943_gpio->chip);
+	return 0;
 }
 
 static const struct of_device_id lp3943_gpio_of_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-lpc32xx.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lpc32xx.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-lpc32xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lpc32xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -560,7 +560,7 @@ static int lpc32xx_gpio_probe(struct pla
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id lpc32xx_gpio_of_match[] = {
+static const struct of_device_id lpc32xx_gpio_of_match[] = {
 	{ .compatible = "nxp,lpc3220-gpio", },
 	{ },
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-lynxpoint.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lynxpoint.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-lynxpoint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-lynxpoint.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,9 +25,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/irqdomain.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
@@ -62,7 +60,6 @@
 
 struct lp_gpio {
 	struct gpio_chip	chip;
-	struct irq_domain	*domain;
 	struct platform_device	*pdev;
 	spinlock_t		lock;
 	unsigned long		reg_base;
@@ -151,7 +148,8 @@ static void lp_gpio_free(struct gpio_chi
 
 static int lp_irq_type(struct irq_data *d, unsigned type)
 {
-	struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
 	u32 hwirq = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 value;
@@ -236,16 +234,11 @@ static int lp_gpio_direction_output(stru
 	return 0;
 }
 
-static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
-	return irq_create_mapping(lg->domain, offset);
-}
-
 static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	u32 base, pin, mask;
 	unsigned long reg, ena, pending;
@@ -262,7 +255,7 @@ static void lp_gpio_irq_handler(unsigned
 			mask = BIT(pin);
 			/* Clear before handling so we don't lose an edge */
 			outl(mask, reg);
-			irq = irq_find_mapping(lg->domain, base + pin);
+			irq = irq_find_mapping(lg->chip.irqdomain, base + pin);
 			generic_handle_irq(irq);
 		}
 	}
@@ -279,7 +272,8 @@ static void lp_irq_mask(struct irq_data
 
 static void lp_irq_enable(struct irq_data *d)
 {
-	struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
 	u32 hwirq = irqd_to_hwirq(d);
 	unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
 	unsigned long flags;
@@ -291,7 +285,8 @@ static void lp_irq_enable(struct irq_dat
 
 static void lp_irq_disable(struct irq_data *d)
 {
-	struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
 	u32 hwirq = irqd_to_hwirq(d);
 	unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
 	unsigned long flags;
@@ -301,26 +296,6 @@ static void lp_irq_disable(struct irq_da
 	spin_unlock_irqrestore(&lg->lock, flags);
 }
 
-static int lp_irq_reqres(struct irq_data *d)
-{
-	struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
-
-	if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) {
-		dev_err(lg->chip.dev,
-			"unable to lock HW IRQ %lu for IRQ\n",
-			irqd_to_hwirq(d));
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void lp_irq_relres(struct irq_data *d)
-{
-	struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
-
-	gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d));
-}
-
 static struct irq_chip lp_irqchip = {
 	.name = "LP-GPIO",
 	.irq_mask = lp_irq_mask,
@@ -328,8 +303,6 @@ static struct irq_chip lp_irqchip = {
 	.irq_enable = lp_irq_enable,
 	.irq_disable = lp_irq_disable,
 	.irq_set_type = lp_irq_type,
-	.irq_request_resources = lp_irq_reqres,
-	.irq_release_resources = lp_irq_relres,
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -348,22 +321,6 @@ static void lp_gpio_irq_init_hw(struct l
 	}
 }
 
-static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-			    irq_hw_number_t hwirq)
-{
-	struct lp_gpio *lg = d->host_data;
-
-	irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq);
-	irq_set_chip_data(irq, lg);
-	irq_set_irq_type(irq, IRQ_TYPE_NONE);
-
-	return 0;
-}
-
-static const struct irq_domain_ops lp_gpio_irq_ops = {
-	.map = lp_gpio_irq_map,
-};
-
 static int lp_gpio_probe(struct platform_device *pdev)
 {
 	struct lp_gpio *lg;
@@ -371,7 +328,6 @@ static int lp_gpio_probe(struct platform
 	struct resource *io_rc, *irq_rc;
 	struct device *dev = &pdev->dev;
 	unsigned long reg_len;
-	unsigned hwirq;
 	int ret = -ENODEV;
 
 	lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
@@ -414,27 +370,28 @@ static int lp_gpio_probe(struct platform
 	gc->can_sleep = false;
 	gc->dev = dev;
 
+	ret = gpiochip_add(gc);
+	if (ret) {
+		dev_err(dev, "failed adding lp-gpio chip\n");
+		return ret;
+	}
+
 	/* set up interrupts  */
 	if (irq_rc && irq_rc->start) {
-		hwirq = irq_rc->start;
-		gc->to_irq = lp_gpio_to_irq;
-
-		lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO,
-						   &lp_gpio_irq_ops, lg);
-		if (!lg->domain)
-			return -ENXIO;
-
 		lp_gpio_irq_init_hw(lg);
+		ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0,
+					   handle_simple_irq, IRQ_TYPE_NONE);
+		if (ret) {
+			dev_err(dev, "failed to add irqchip\n");
+			gpiochip_remove(gc);
+			return ret;
+		}
 
-		irq_set_handler_data(hwirq, lg);
-		irq_set_chained_handler(hwirq, lp_gpio_irq_handler);
+		gpiochip_set_chained_irqchip(gc, &lp_irqchip,
+					     (unsigned)irq_rc->start,
+					     lp_gpio_irq_handler);
 	}
 
-	ret = gpiochip_add(gc);
-	if (ret) {
-		dev_err(dev, "failed adding lp-gpio chip\n");
-		return ret;
-	}
 	pm_runtime_enable(dev);
 
 	return 0;
@@ -450,9 +407,27 @@ static int lp_gpio_runtime_resume(struct
 	return 0;
 }
 
+static int lp_gpio_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct lp_gpio *lg = platform_get_drvdata(pdev);
+	unsigned long reg;
+	int i;
+
+	/* on some hardware suspend clears input sensing, re-enable it here */
+	for (i = 0; i < lg->chip.ngpio; i++) {
+		if (gpiochip_is_requested(&lg->chip, i) != NULL) {
+			reg = lp_gpio_reg(&lg->chip, i, LP_CONFIG2);
+			outl(inl(reg) & ~GPINDIS_BIT, reg);
+		}
+	}
+	return 0;
+}
+
 static const struct dev_pm_ops lp_gpio_pm_ops = {
 	.runtime_suspend = lp_gpio_runtime_suspend,
 	.runtime_resume = lp_gpio_runtime_resume,
+	.resume = lp_gpio_resume,
 };
 
 static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
@@ -465,11 +440,8 @@ MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio
 static int lp_gpio_remove(struct platform_device *pdev)
 {
 	struct lp_gpio *lg = platform_get_drvdata(pdev);
-	int err;
 	pm_runtime_disable(&pdev->dev);
-	err = gpiochip_remove(&lg->chip);
-	if (err)
-		dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
+	gpiochip_remove(&lg->chip);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-max730x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-max730x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-max730x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-max730x.c	2014-09-28 17:29:07.000000000 -0400
@@ -228,21 +228,16 @@ EXPORT_SYMBOL_GPL(__max730x_probe);
 int __max730x_remove(struct device *dev)
 {
 	struct max7301 *ts = dev_get_drvdata(dev);
-	int ret;
 
 	if (ts == NULL)
 		return -ENODEV;
 
 	/* Power down the chip and disable IRQ output */
 	ts->write(dev, 0x04, 0x00);
-
-	ret = gpiochip_remove(&ts->chip);
-	if (!ret)
-		mutex_destroy(&ts->lock);
-	else
-		dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
-
-	return ret;
+	gpiochip_remove(&ts->chip);
+	mutex_destroy(&ts->lock);
+	kfree(ts);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(__max730x_remove);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-max732x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-max732x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-max732x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-max732x.c	2014-09-28 17:29:07.000000000 -0400
@@ -676,12 +676,7 @@ static int max732x_remove(struct i2c_cli
 		}
 	}
 
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
+	gpiochip_remove(&chip->gpio_chip);
 
 	max732x_irq_teardown(chip);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-mc33880.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mc33880.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-mc33880.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mc33880.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,20 +149,15 @@ exit_destroy:
 static int mc33880_remove(struct spi_device *spi)
 {
 	struct mc33880 *mc;
-	int ret;
 
 	mc = spi_get_drvdata(spi);
 	if (mc == NULL)
 		return -ENODEV;
 
-	ret = gpiochip_remove(&mc->chip);
-	if (!ret)
-		mutex_destroy(&mc->lock);
-	else
-		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-			ret);
+	gpiochip_remove(&mc->chip);
+	mutex_destroy(&mc->lock);
 
-	return ret;
+	return 0;
 }
 
 static struct spi_driver mc33880_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-mc9s08dz60.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mc9s08dz60.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-mc9s08dz60.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mc9s08dz60.c	2014-09-28 17:29:07.000000000 -0400
@@ -118,7 +118,8 @@ static int mc9s08dz60_remove(struct i2c_
 
 	mc9s = i2c_get_clientdata(client);
 
-	return gpiochip_remove(&mc9s->chip);
+	gpiochip_remove(&mc9s->chip);
+	return 0;
 }
 
 static const struct i2c_device_id mc9s08dz60_id[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-mcp23s08.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mcp23s08.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-mcp23s08.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mcp23s08.c	2014-09-28 17:29:07.000000000 -0400
@@ -812,16 +812,14 @@ fail:
 static int mcp230xx_remove(struct i2c_client *client)
 {
 	struct mcp23s08 *mcp = i2c_get_clientdata(client);
-	int status;
 
 	if (client->irq && mcp->irq_controller)
 		mcp23s08_irq_teardown(mcp);
 
-	status = gpiochip_remove(&mcp->chip);
-	if (status == 0)
-		kfree(mcp);
+	gpiochip_remove(&mcp->chip);
+	kfree(mcp);
 
-	return status;
+	return 0;
 }
 
 static const struct i2c_device_id mcp230xx_id[] = {
@@ -960,13 +958,10 @@ static int mcp23s08_probe(struct spi_dev
 
 fail:
 	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-		int tmp;
 
 		if (!data->mcp[addr])
 			continue;
-		tmp = gpiochip_remove(&data->mcp[addr]->chip);
-		if (tmp < 0)
-			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+		gpiochip_remove(&data->mcp[addr]->chip);
 	}
 	kfree(data);
 	return status;
@@ -976,23 +971,16 @@ static int mcp23s08_remove(struct spi_de
 {
 	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
 	unsigned			addr;
-	int				status = 0;
 
 	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-		int tmp;
 
 		if (!data->mcp[addr])
 			continue;
 
-		tmp = gpiochip_remove(&data->mcp[addr]->chip);
-		if (tmp < 0) {
-			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
-			status = tmp;
-		}
+		gpiochip_remove(&data->mcp[addr]->chip);
 	}
-	if (status == 0)
-		kfree(data);
-	return status;
+	kfree(data);
+	return 0;
 }
 
 static const struct spi_device_id mcp23s08_ids[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-ml-ioh.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ml-ioh.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-ml-ioh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ml-ioh.c	2014-09-28 17:29:07.000000000 -0400
@@ -497,8 +497,7 @@ err_irq_alloc_descs:
 err_gpiochip_add:
 	while (--i >= 0) {
 		chip--;
-		if (gpiochip_remove(&chip->gpio))
-			dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
+		gpiochip_remove(&chip->gpio);
 	}
 	kfree(chip_save);
 
@@ -519,7 +518,6 @@ err_pci_enable:
 
 static void ioh_gpio_remove(struct pci_dev *pdev)
 {
-	int err;
 	int i;
 	struct ioh_gpio *chip = pci_get_drvdata(pdev);
 	void *chip_save;
@@ -530,9 +528,7 @@ static void ioh_gpio_remove(struct pci_d
 
 	for (i = 0; i < 8; i++, chip++) {
 		irq_free_descs(chip->irq_base, num_ports[i]);
-		err = gpiochip_remove(&chip->gpio);
-		if (err)
-			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+		gpiochip_remove(&chip->gpio);
 	}
 
 	chip = chip_save;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-msm-v2.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-msm-v2.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-msm-v2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-msm-v2.c	2014-09-28 17:29:07.000000000 -0400
@@ -438,10 +438,7 @@ MODULE_DEVICE_TABLE(of, msm_gpio_of_matc
 
 static int msm_gpio_remove(struct platform_device *dev)
 {
-	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
-	if (ret < 0)
-		return ret;
+	gpiochip_remove(&msm_gpio.gpio_chip);
 
 	irq_set_handler(msm_gpio.summary_irq, NULL);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-mxc.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mxc.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-mxc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-mxc.c	2014-09-28 17:29:07.000000000 -0400
@@ -485,7 +485,7 @@ static int mxc_gpio_probe(struct platfor
 out_irqdesc_free:
 	irq_free_descs(irq_base, 32);
 out_gpiochip_remove:
-	WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
+	gpiochip_remove(&port->bgc.gc);
 out_bgpio_remove:
 	bgpio_remove(&port->bgc);
 out_bgio:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-octeon.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-octeon.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-octeon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-octeon.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,7 +129,8 @@ out:
 static int octeon_gpio_remove(struct platform_device *pdev)
 {
 	struct gpio_chip *chip = pdev->dev.platform_data;
-	return gpiochip_remove(chip);
+	gpiochip_remove(chip);
+	return 0;
 }
 
 static struct of_device_id octeon_gpio_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-omap.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-omap.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-omap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-omap.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/gpio.h>
 #include <linux/bitops.h>
 #include <linux/platform_data/gpio-omap.h>
@@ -89,18 +88,19 @@ struct gpio_bank {
 #define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
 #define LINE_USED(line, offset) (line & (BIT(offset)))
 
-static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
+static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
 {
 	return bank->chip.base + gpio_irq;
 }
 
-static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
+static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 	return container_of(chip, struct gpio_bank, chip);
 }
 
-static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
+static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
+				    int is_input)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -117,7 +117,8 @@ static void _set_gpio_direction(struct g
 
 
 /* set data out value using dedicate set/clear register */
-static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
+static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, int gpio,
+				      int enable)
 {
 	void __iomem *reg = bank->base;
 	u32 l = GPIO_BIT(bank, gpio);
@@ -134,7 +135,8 @@ static void _set_gpio_dataout_reg(struct
 }
 
 /* set data out value using mask register */
-static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
+static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, int gpio,
+				       int enable)
 {
 	void __iomem *reg = bank->base + bank->regs->dataout;
 	u32 gpio_bit = GPIO_BIT(bank, gpio);
@@ -149,21 +151,21 @@ static void _set_gpio_dataout_mask(struc
 	bank->context.dataout = l;
 }
 
-static int _get_gpio_datain(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_datain(struct gpio_bank *bank, int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->datain;
 
 	return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
-static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
 {
 	void __iomem *reg = bank->base + bank->regs->dataout;
 
 	return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
-static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
 {
 	int l = readl_relaxed(base + reg);
 
@@ -175,7 +177,7 @@ static inline void _gpio_rmw(void __iome
 	writel_relaxed(l, base + reg);
 }
 
-static inline void _gpio_dbck_enable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
 {
 	if (bank->dbck_enable_mask && !bank->dbck_enabled) {
 		clk_prepare_enable(bank->dbck);
@@ -186,7 +188,7 @@ static inline void _gpio_dbck_enable(str
 	}
 }
 
-static inline void _gpio_dbck_disable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
 {
 	if (bank->dbck_enable_mask && bank->dbck_enabled) {
 		/*
@@ -202,7 +204,7 @@ static inline void _gpio_dbck_disable(st
 }
 
 /**
- * _set_gpio_debounce - low level gpio debounce time
+ * omap2_set_gpio_debounce - low level gpio debounce time
  * @bank: the gpio bank we're acting upon
  * @gpio: the gpio number on this @gpio
  * @debounce: debounce time to use
@@ -210,8 +212,8 @@ static inline void _gpio_dbck_disable(st
  * OMAP's debounce time is in 31us steps so we need
  * to convert and round up to the closest unit.
  */
-static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
-		unsigned debounce)
+static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
+				    unsigned debounce)
 {
 	void __iomem		*reg;
 	u32			val;
@@ -252,7 +254,7 @@ static void _set_gpio_debounce(struct gp
 	 * used within _gpio_dbck_enable() is still not initialized at
 	 * that point. Therefore we have to enable dbck here.
 	 */
-	_gpio_dbck_enable(bank);
+	omap_gpio_dbck_enable(bank);
 	if (bank->dbck_enable_mask) {
 		bank->context.debounce = debounce;
 		bank->context.debounce_en = val;
@@ -260,7 +262,7 @@ static void _set_gpio_debounce(struct gp
 }
 
 /**
- * _clear_gpio_debounce - clear debounce settings for a gpio
+ * omap_clear_gpio_debounce - clear debounce settings for a gpio
  * @bank: the gpio bank we're acting upon
  * @gpio: the gpio number on this @gpio
  *
@@ -269,7 +271,7 @@ static void _set_gpio_debounce(struct gp
  * time too. The debounce clock will also be disabled when calling this function
  * if this is the only gpio in the bank using debounce.
  */
-static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
 {
 	u32 gpio_bit = GPIO_BIT(bank, gpio);
 
@@ -293,20 +295,20 @@ static void _clear_gpio_debounce(struct
 	}
 }
 
-static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
+static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
 						unsigned trigger)
 {
 	void __iomem *base = bank->base;
 	u32 gpio_bit = BIT(gpio);
 
-	_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
-		  trigger & IRQ_TYPE_LEVEL_LOW);
-	_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
-		  trigger & IRQ_TYPE_LEVEL_HIGH);
-	_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
-		  trigger & IRQ_TYPE_EDGE_RISING);
-	_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
-		  trigger & IRQ_TYPE_EDGE_FALLING);
+	omap_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
+		      trigger & IRQ_TYPE_LEVEL_LOW);
+	omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
+		      trigger & IRQ_TYPE_LEVEL_HIGH);
+	omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
+		      trigger & IRQ_TYPE_EDGE_RISING);
+	omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
+		      trigger & IRQ_TYPE_EDGE_FALLING);
 
 	bank->context.leveldetect0 =
 			readl_relaxed(bank->base + bank->regs->leveldetect0);
@@ -318,7 +320,7 @@ static inline void set_gpio_trigger(stru
 			readl_relaxed(bank->base + bank->regs->fallingdetect);
 
 	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
-		_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
+		omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
 		bank->context.wake_en =
 			readl_relaxed(bank->base + bank->regs->wkup_en);
 	}
@@ -354,7 +356,7 @@ exit:
  * This only applies to chips that can't do both rising and falling edge
  * detection at once.  For all other chips, this function is a noop.
  */
-static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 {
 	void __iomem *reg = bank->base;
 	u32 l = 0;
@@ -373,18 +375,18 @@ static void _toggle_gpio_edge_triggering
 	writel_relaxed(l, reg);
 }
 #else
-static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
+static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
 #endif
 
-static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
-							unsigned trigger)
+static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
+				    unsigned trigger)
 {
 	void __iomem *reg = bank->base;
 	void __iomem *base = bank->base;
 	u32 l = 0;
 
 	if (bank->regs->leveldetect0 && bank->regs->wkup_en) {
-		set_gpio_trigger(bank, gpio, trigger);
+		omap_set_gpio_trigger(bank, gpio, trigger);
 	} else if (bank->regs->irqctrl) {
 		reg += bank->regs->irqctrl;
 
@@ -414,7 +416,7 @@ static int _set_gpio_triggering(struct g
 			l |= BIT(gpio << 1);
 
 		/* Enable wake-up during idle for dynamic tick */
-		_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
+		omap_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
 		bank->context.wake_en =
 			readl_relaxed(bank->base + bank->regs->wkup_en);
 		writel_relaxed(l, reg);
@@ -422,7 +424,7 @@ static int _set_gpio_triggering(struct g
 	return 0;
 }
 
-static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
 {
 	if (bank->regs->pinctrl) {
 		void __iomem *reg = bank->base + bank->regs->pinctrl;
@@ -443,7 +445,7 @@ static void _enable_gpio_module(struct g
 	}
 }
 
-static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
 {
 	void __iomem *base = bank->base;
 
@@ -451,7 +453,7 @@ static void _disable_gpio_module(struct
 	    !LINE_USED(bank->mod_usage, offset) &&
 	    !LINE_USED(bank->irq_usage, offset)) {
 		/* Disable wake-up during idle for dynamic tick */
-		_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
+		omap_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
 		bank->context.wake_en =
 			readl_relaxed(bank->base + bank->regs->wkup_en);
 	}
@@ -468,16 +470,16 @@ static void _disable_gpio_module(struct
 	}
 }
 
-static int gpio_is_input(struct gpio_bank *bank, int mask)
+static int omap_gpio_is_input(struct gpio_bank *bank, int mask)
 {
 	void __iomem *reg = bank->base + bank->regs->direction;
 
 	return readl_relaxed(reg) & mask;
 }
 
-static int gpio_irq_type(struct irq_data *d, unsigned type)
+static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
 	unsigned gpio = 0;
 	int retval;
 	unsigned long flags;
@@ -492,7 +494,7 @@ static int gpio_irq_type(struct irq_data
 #endif
 
 	if (!gpio)
-		gpio = irq_to_gpio(bank, d->hwirq);
+		gpio = omap_irq_to_gpio(bank, d->hwirq);
 
 	if (type & ~IRQ_TYPE_SENSE_MASK)
 		return -EINVAL;
@@ -503,11 +505,11 @@ static int gpio_irq_type(struct irq_data
 
 	spin_lock_irqsave(&bank->lock, flags);
 	offset = GPIO_INDEX(bank, gpio);
-	retval = _set_gpio_triggering(bank, offset, type);
+	retval = omap_set_gpio_triggering(bank, offset, type);
 	if (!LINE_USED(bank->mod_usage, offset)) {
-		_enable_gpio_module(bank, offset);
-		_set_gpio_direction(bank, offset, 1);
-	} else if (!gpio_is_input(bank, BIT(offset))) {
+		omap_enable_gpio_module(bank, offset);
+		omap_set_gpio_direction(bank, offset, 1);
+	} else if (!omap_gpio_is_input(bank, BIT(offset))) {
 		spin_unlock_irqrestore(&bank->lock, flags);
 		return -EINVAL;
 	}
@@ -523,7 +525,7 @@ static int gpio_irq_type(struct irq_data
 	return retval;
 }
 
-static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 
@@ -540,12 +542,12 @@ static void _clear_gpio_irqbank(struct g
 	readl_relaxed(reg);
 }
 
-static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
+static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
 {
-	_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+	omap_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
-static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
+static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -559,7 +561,7 @@ static u32 _get_gpio_irqbank_mask(struct
 	return l;
 }
 
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -581,7 +583,7 @@ static void _enable_gpio_irqbank(struct
 	writel_relaxed(l, reg);
 }
 
-static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
@@ -603,12 +605,13 @@ static void _disable_gpio_irqbank(struct
 	writel_relaxed(l, reg);
 }
 
-static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
+static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, int gpio,
+					   int enable)
 {
 	if (enable)
-		_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+		omap_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 	else
-		_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+		omap_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
@@ -619,7 +622,7 @@ static inline void _set_gpio_irqenable(s
  * enabled. When system is suspended, only selected GPIO interrupts need
  * to have wake-up enabled.
  */
-static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
+static int omap_set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
 	u32 gpio_bit = GPIO_BIT(bank, gpio);
 	unsigned long flags;
@@ -642,22 +645,22 @@ static int _set_gpio_wakeup(struct gpio_
 	return 0;
 }
 
-static void _reset_gpio(struct gpio_bank *bank, int gpio)
+static void omap_reset_gpio(struct gpio_bank *bank, int gpio)
 {
-	_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
-	_set_gpio_irqenable(bank, gpio, 0);
-	_clear_gpio_irqstatus(bank, gpio);
-	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
-	_clear_gpio_debounce(bank, gpio);
+	omap_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
+	omap_set_gpio_irqenable(bank, gpio, 0);
+	omap_clear_gpio_irqstatus(bank, gpio);
+	omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+	omap_clear_gpio_debounce(bank, gpio);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
-static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
+static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
-	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
 
-	return _set_gpio_wakeup(bank, gpio, enable);
+	return omap_set_gpio_wakeup(bank, gpio, enable);
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -678,8 +681,8 @@ static int omap_gpio_request(struct gpio
 	 * not already been requested.
 	 */
 	if (!LINE_USED(bank->irq_usage, offset)) {
-		_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-		_enable_gpio_module(bank, offset);
+		omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+		omap_enable_gpio_module(bank, offset);
 	}
 	bank->mod_usage |= BIT(offset);
 	spin_unlock_irqrestore(&bank->lock, flags);
@@ -694,8 +697,8 @@ static void omap_gpio_free(struct gpio_c
 
 	spin_lock_irqsave(&bank->lock, flags);
 	bank->mod_usage &= ~(BIT(offset));
-	_disable_gpio_module(bank, offset);
-	_reset_gpio(bank, bank->chip.base + offset);
+	omap_disable_gpio_module(bank, offset);
+	omap_reset_gpio(bank, bank->chip.base + offset);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	/*
@@ -715,7 +718,7 @@ static void omap_gpio_free(struct gpio_c
  * line's interrupt handler has been run, we may miss some nested
  * interrupts.
  */
-static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	void __iomem *isr_reg = NULL;
 	u32 isr;
@@ -738,7 +741,7 @@ static void gpio_irq_handler(unsigned in
 		u32 isr_saved, level_mask = 0;
 		u32 enabled;
 
-		enabled = _get_gpio_irqbank_mask(bank);
+		enabled = omap_get_gpio_irqbank_mask(bank);
 		isr_saved = isr = readl_relaxed(isr_reg) & enabled;
 
 		if (bank->level_mask)
@@ -747,9 +750,9 @@ static void gpio_irq_handler(unsigned in
 		/* clear edge sensitive interrupts before handler(s) are
 		called so that we don't miss any interrupt occurred while
 		executing them */
-		_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
-		_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
-		_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
+		omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
+		omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+		omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
 
 		/* if there is only edge sensitive GPIO pin interrupts
 		configured, we could unmask GPIO bank interrupt immediately */
@@ -773,7 +776,7 @@ static void gpio_irq_handler(unsigned in
 			 * This will be indicated in the bank toggle_mask.
 			 */
 			if (bank->toggle_mask & (BIT(bit)))
-				_toggle_gpio_edge_triggering(bank, bit);
+				omap_toggle_gpio_edge_triggering(bank, bit);
 
 			generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
 							    bit));
@@ -789,18 +792,18 @@ exit:
 	pm_runtime_put(bank->dev);
 }
 
-static void gpio_irq_shutdown(struct irq_data *d)
+static void omap_gpio_irq_shutdown(struct irq_data *d)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
-	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 	unsigned offset = GPIO_INDEX(bank, gpio);
 
 	spin_lock_irqsave(&bank->lock, flags);
 	gpio_unlock_as_irq(&bank->chip, offset);
 	bank->irq_usage &= ~(BIT(offset));
-	_disable_gpio_module(bank, offset);
-	_reset_gpio(bank, gpio);
+	omap_disable_gpio_module(bank, offset);
+	omap_reset_gpio(bank, gpio);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	/*
@@ -811,57 +814,57 @@ static void gpio_irq_shutdown(struct irq
 		pm_runtime_put(bank->dev);
 }
 
-static void gpio_ack_irq(struct irq_data *d)
+static void omap_gpio_ack_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
-	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
 
-	_clear_gpio_irqstatus(bank, gpio);
+	omap_clear_gpio_irqstatus(bank, gpio);
 }
 
-static void gpio_mask_irq(struct irq_data *d)
+static void omap_gpio_mask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
-	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
-	_set_gpio_irqenable(bank, gpio, 0);
-	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+	omap_set_gpio_irqenable(bank, gpio, 0);
+	omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
-static void gpio_unmask_irq(struct irq_data *d)
+static void omap_gpio_unmask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = _irq_data_get_bank(d);
-	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+	struct gpio_bank *bank = omap_irq_data_get_bank(d);
+	unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
 	unsigned int irq_mask = GPIO_BIT(bank, gpio);
 	u32 trigger = irqd_get_trigger_type(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
 	if (trigger)
-		_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
+		omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
 
 	/* For level-triggered GPIOs, the clearing must be done after
 	 * the HW source is cleared, thus after the handler has run */
 	if (bank->level_mask & irq_mask) {
-		_set_gpio_irqenable(bank, gpio, 0);
-		_clear_gpio_irqstatus(bank, gpio);
+		omap_set_gpio_irqenable(bank, gpio, 0);
+		omap_clear_gpio_irqstatus(bank, gpio);
 	}
 
-	_set_gpio_irqenable(bank, gpio, 1);
+	omap_set_gpio_irqenable(bank, gpio, 1);
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 static struct irq_chip gpio_irq_chip = {
 	.name		= "GPIO",
-	.irq_shutdown	= gpio_irq_shutdown,
-	.irq_ack	= gpio_ack_irq,
-	.irq_mask	= gpio_mask_irq,
-	.irq_unmask	= gpio_unmask_irq,
-	.irq_set_type	= gpio_irq_type,
-	.irq_set_wake	= gpio_wake_enable,
+	.irq_shutdown	= omap_gpio_irq_shutdown,
+	.irq_ack	= omap_gpio_ack_irq,
+	.irq_mask	= omap_gpio_mask_irq,
+	.irq_unmask	= omap_gpio_unmask_irq,
+	.irq_set_type	= omap_gpio_irq_type,
+	.irq_set_wake	= omap_gpio_wake_enable,
 };
 
 /*---------------------------------------------------------------------*/
@@ -918,7 +921,7 @@ static struct platform_device omap_mpuio
 	/* could list the /proc/iomem resources */
 };
 
-static inline void mpuio_init(struct gpio_bank *bank)
+static inline void omap_mpuio_init(struct gpio_bank *bank)
 {
 	platform_set_drvdata(&omap_mpuio_device, bank);
 
@@ -928,7 +931,7 @@ static inline void mpuio_init(struct gpi
 
 /*---------------------------------------------------------------------*/
 
-static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -943,19 +946,19 @@ static int gpio_get_direction(struct gpi
 	return dir;
 }
 
-static int gpio_input(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
 
 	bank = container_of(chip, struct gpio_bank, chip);
 	spin_lock_irqsave(&bank->lock, flags);
-	_set_gpio_direction(bank, offset, 1);
+	omap_set_gpio_direction(bank, offset, 1);
 	spin_unlock_irqrestore(&bank->lock, flags);
 	return 0;
 }
 
-static int gpio_get(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct gpio_bank *bank;
 	u32 mask;
@@ -963,13 +966,13 @@ static int gpio_get(struct gpio_chip *ch
 	bank = container_of(chip, struct gpio_bank, chip);
 	mask = (BIT(offset));
 
-	if (gpio_is_input(bank, mask))
-		return _get_gpio_datain(bank, offset);
+	if (omap_gpio_is_input(bank, mask))
+		return omap_get_gpio_datain(bank, offset);
 	else
-		return _get_gpio_dataout(bank, offset);
+		return omap_get_gpio_dataout(bank, offset);
 }
 
-static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -977,13 +980,13 @@ static int gpio_output(struct gpio_chip
 	bank = container_of(chip, struct gpio_bank, chip);
 	spin_lock_irqsave(&bank->lock, flags);
 	bank->set_dataout(bank, offset, value);
-	_set_gpio_direction(bank, offset, 0);
+	omap_set_gpio_direction(bank, offset, 0);
 	spin_unlock_irqrestore(&bank->lock, flags);
 	return 0;
 }
 
-static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
-		unsigned debounce)
+static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
+			      unsigned debounce)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -991,13 +994,13 @@ static int gpio_debounce(struct gpio_chi
 	bank = container_of(chip, struct gpio_bank, chip);
 
 	spin_lock_irqsave(&bank->lock, flags);
-	_set_gpio_debounce(bank, offset, debounce);
+	omap2_set_gpio_debounce(bank, offset, debounce);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	return 0;
 }
 
-static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
@@ -1025,11 +1028,6 @@ static void __init omap_gpio_show_rev(st
 	called = true;
 }
 
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
 static void omap_gpio_mod_init(struct gpio_bank *bank)
 {
 	void __iomem *base = bank->base;
@@ -1043,8 +1041,10 @@ static void omap_gpio_mod_init(struct gp
 		return;
 	}
 
-	_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv);
-	_gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv);
+	omap_gpio_rmw(base, bank->regs->irqenable, l,
+		      bank->regs->irqenable_inv);
+	omap_gpio_rmw(base, bank->regs->irqstatus, l,
+		      !bank->regs->irqenable_inv);
 	if (bank->regs->debounce_en)
 		writel_relaxed(0, base + bank->regs->debounce_en);
 
@@ -1078,10 +1078,10 @@ omap_mpuio_alloc_gc(struct gpio_bank *ba
 	/* NOTE: No ack required, reading IRQ status clears it. */
 	ct->chip.irq_mask = irq_gc_mask_set_bit;
 	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-	ct->chip.irq_set_type = gpio_irq_type;
+	ct->chip.irq_set_type = omap_gpio_irq_type;
 
 	if (bank->regs->wkup_en)
-		ct->chip.irq_set_wake = gpio_wake_enable;
+		ct->chip.irq_set_wake = omap_gpio_wake_enable;
 
 	ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
 	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@@ -1101,12 +1101,12 @@ static int omap_gpio_chip_init(struct gp
 	 */
 	bank->chip.request = omap_gpio_request;
 	bank->chip.free = omap_gpio_free;
-	bank->chip.get_direction = gpio_get_direction;
-	bank->chip.direction_input = gpio_input;
-	bank->chip.get = gpio_get;
-	bank->chip.direction_output = gpio_output;
-	bank->chip.set_debounce = gpio_debounce;
-	bank->chip.set = gpio_set;
+	bank->chip.get_direction = omap_gpio_get_direction;
+	bank->chip.direction_input = omap_gpio_input;
+	bank->chip.get = omap_gpio_get;
+	bank->chip.direction_output = omap_gpio_output;
+	bank->chip.set_debounce = omap_gpio_debounce;
+	bank->chip.set = omap_gpio_set;
 	if (bank->is_mpuio) {
 		bank->chip.label = "mpuio";
 		if (bank->regs->wkup_en)
@@ -1138,7 +1138,7 @@ static int omap_gpio_chip_init(struct gp
 #endif
 
 	ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
-				   irq_base, gpio_irq_handler,
+				   irq_base, omap_gpio_irq_handler,
 				   IRQ_TYPE_NONE);
 
 	if (ret) {
@@ -1148,11 +1148,10 @@ static int omap_gpio_chip_init(struct gp
 	}
 
 	gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
-				     bank->irq, gpio_irq_handler);
+				     bank->irq, omap_gpio_irq_handler);
 
 	for (j = 0; j < bank->width; j++) {
 		int irq = irq_find_mapping(bank->chip.irqdomain, j);
-		irq_set_lockdep_class(irq, &gpio_lock_class);
 		if (bank->is_mpuio) {
 			omap_mpuio_alloc_gc(bank, irq, bank->width);
 			irq_set_chip_and_handler(irq, NULL, NULL);
@@ -1217,9 +1216,9 @@ static int omap_gpio_probe(struct platfo
 	}
 
 	if (bank->regs->set_dataout && bank->regs->clr_dataout)
-		bank->set_dataout = _set_gpio_dataout_reg;
+		bank->set_dataout = omap_set_gpio_dataout_reg;
 	else
-		bank->set_dataout = _set_gpio_dataout_mask;
+		bank->set_dataout = omap_set_gpio_dataout_mask;
 
 	spin_lock_init(&bank->lock);
 
@@ -1238,7 +1237,7 @@ static int omap_gpio_probe(struct platfo
 	pm_runtime_get_sync(bank->dev);
 
 	if (bank->is_mpuio)
-		mpuio_init(bank);
+		omap_mpuio_init(bank);
 
 	omap_gpio_mod_init(bank);
 
@@ -1320,7 +1319,7 @@ update_gpio_context_count:
 		bank->context_loss_count =
 				bank->get_context_loss_count(bank->dev);
 
-	_gpio_dbck_disable(bank);
+	omap_gpio_dbck_disable(bank);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	return 0;
@@ -1351,7 +1350,7 @@ static int omap_gpio_runtime_resume(stru
 				bank->get_context_loss_count(bank->dev);
 	}
 
-	_gpio_dbck_enable(bank);
+	omap_gpio_dbck_enable(bank);
 
 	/*
 	 * In ->runtime_suspend(), level-triggered, wakeup-enabled
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-palmas.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-palmas.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-palmas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-palmas.c	2014-09-28 17:29:07.000000000 -0400
@@ -210,7 +210,8 @@ static int palmas_gpio_remove(struct pla
 {
 	struct palmas_gpio *palmas_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&palmas_gpio->gpio_chip);
+	gpiochip_remove(&palmas_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver palmas_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-pca953x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pca953x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-pca953x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pca953x.c	2014-09-28 17:29:07.000000000 -0400
@@ -765,12 +765,7 @@ static int pca953x_remove(struct i2c_cli
 		}
 	}
 
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
+	gpiochip_remove(&chip->gpio_chip);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-pcf857x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pcf857x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-pcf857x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pcf857x.c	2014-09-28 17:29:07.000000000 -0400
@@ -444,9 +444,7 @@ static int pcf857x_remove(struct i2c_cli
 	if (client->irq)
 		pcf857x_irq_domain_cleanup(gpio);
 
-	status = gpiochip_remove(&gpio->chip);
-	if (status)
-		dev_err(&client->dev, "%s --> %d\n", "remove", status);
+	gpiochip_remove(&gpio->chip);
 	return status;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-pch.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pch.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-pch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pch.c	2014-09-28 17:29:07.000000000 -0400
@@ -426,9 +426,7 @@ end:
 
 err_request_irq:
 	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
-
-	if (gpiochip_remove(&chip->gpio))
-		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+	gpiochip_remove(&chip->gpio);
 
 err_gpiochip_add:
 	pci_iounmap(pdev, chip->base);
@@ -447,7 +445,6 @@ err_pci_enable:
 
 static void pch_gpio_remove(struct pci_dev *pdev)
 {
-	int err;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
 
 	if (chip->irq_base != -1) {
@@ -456,10 +453,7 @@ static void pch_gpio_remove(struct pci_d
 		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
 	}
 
-	err = gpiochip_remove(&chip->gpio);
-	if (err)
-		dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-
+	gpiochip_remove(&chip->gpio);
 	pci_iounmap(pdev, chip->base);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-pxa.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pxa.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-pxa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-pxa.c	2014-09-28 17:29:07.000000000 -0400
@@ -498,7 +498,7 @@ static int pxa_gpio_nums(struct platform
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id pxa_gpio_dt_ids[] = {
+static const struct of_device_id pxa_gpio_dt_ids[] = {
 	{ .compatible = "intel,pxa25x-gpio",	.data = &pxa25x_id, },
 	{ .compatible = "intel,pxa26x-gpio",	.data = &pxa26x_id, },
 	{ .compatible = "intel,pxa27x-gpio",	.data = &pxa27x_id, },
@@ -649,6 +649,11 @@ static int pxa_gpio_probe(struct platfor
 						 handle_edge_irq);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
+	} else {
+		if (irq0 > 0)
+			irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
+		if (irq1 > 0)
+			irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
 	}
 
 	irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-rc5t583.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rc5t583.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-rc5t583.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rc5t583.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,7 +148,8 @@ static int rc5t583_gpio_remove(struct pl
 {
 	struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&rc5t583_gpio->gpio_chip);
+	gpiochip_remove(&rc5t583_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver rc5t583_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-rcar.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rcar.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-rcar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rcar.c	2014-09-28 17:29:07.000000000 -0400
@@ -240,9 +240,9 @@ static int gpio_rcar_get(struct gpio_chi
 	/* testing on r8a7790 shows that INDT does not show correct pin state
 	 * when configured as output, so use OUTDT in case of output pins */
 	if (gpio_rcar_read(gpio_to_priv(chip), INOUTSEL) & bit)
-		return (int)(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
+		return !!(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
 	else
-		return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
+		return !!(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
 }
 
 static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -472,11 +472,8 @@ err0:
 static int gpio_rcar_remove(struct platform_device *pdev)
 {
 	struct gpio_rcar_priv *p = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = gpiochip_remove(&p->gpio_chip);
-	if (ret)
-		return ret;
+	gpiochip_remove(&p->gpio_chip);
 
 	irq_domain_remove(p->irq_domain);
 	pm_runtime_put(&pdev->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-rdc321x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rdc321x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-rdc321x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-rdc321x.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,14 +199,11 @@ static int rdc321x_gpio_probe(struct pla
 
 static int rdc321x_gpio_remove(struct platform_device *pdev)
 {
-	int ret;
 	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
 
-	ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
-	if (ret)
-		dev_err(&pdev->dev, "failed to unregister chip\n");
+	gpiochip_remove(&rdc321x_gpio_dev->chip);
 
-	return ret;
+	return 0;
 }
 
 static struct platform_driver rdc321x_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-samsung.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-samsung.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-samsung.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-samsung.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,7 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
 #include <mach/gpio-samsung.h>
-#endif
 
 #include <plat/cpu.h>
 #include <plat/gpio-core.h>
@@ -358,47 +355,6 @@ static unsigned s3c24xx_gpio_getcfg_aban
 }
 #endif
 
-#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
-static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
-				     unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift;
-	u32 con;
-
-	switch (off) {
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		shift = (off & 7) * 4;
-		reg -= 4;
-		break;
-	case 6:
-		shift = ((off + 1) & 7) * 4;
-		reg -= 4;
-		break;
-	default:
-		shift = ((off + 1) & 7) * 4;
-		break;
-	}
-
-	if (samsung_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0xf << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-#endif
-
 static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
 					   int nr_chips)
 {
@@ -426,16 +382,6 @@ static struct samsung_gpio_cfg s3c24xx_g
 };
 #endif
 
-#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
-static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
-	.cfg_eint	= 0x3,
-	.set_config	= s5p64x0_gpio_setcfg_rbank,
-	.get_config	= samsung_gpio_getcfg_4bit,
-	.set_pull	= samsung_gpio_setpull_updown,
-	.get_pull	= samsung_gpio_getpull_updown,
-};
-#endif
-
 static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
 	[0] = {
 		.cfg_eint	= 0x0,
@@ -708,91 +654,6 @@ static int s3c24xx_gpiolib_banka_output(
 }
 #endif
 
-/* The next set of routines are for the case of s5p64x0 bank r */
-
-static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
-				       unsigned int offset)
-{
-	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long flags;
-
-	switch (offset) {
-	case 6:
-		offset += 1;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		regcon -= 4;
-		break;
-	default:
-		offset -= 7;
-		break;
-	}
-
-	samsung_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	samsung_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
-static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
-					unsigned int offset, int value)
-{
-	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long dat;
-	unsigned long flags;
-	unsigned con_offset  = offset;
-
-	switch (con_offset) {
-	case 6:
-		con_offset += 1;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		regcon -= 4;
-		break;
-	default:
-		con_offset -= 7;
-		break;
-	}
-
-	samsung_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(con_offset));
-	con |= 0x1 << con_4bit_shift(con_offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(con, regcon);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	samsung_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
 static void samsung_gpiolib_set(struct gpio_chip *chip,
 				unsigned offset, int value)
 {
@@ -999,20 +860,6 @@ static void __init samsung_gpiolib_add_4
 	}
 }
 
-static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
-					     int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
-		chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
-
-		if (!chip->pm)
-			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
-
-		samsung_gpiolib_add(chip);
-	}
-}
-
 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
 {
 	struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
@@ -1319,773 +1166,9 @@ static struct samsung_gpio_chip s3c64xx_
 #endif
 };
 
-/*
- * S5P6440 GPIO bank summary:
- *
- * Bank	GPIOs	Style	SlpCon	ExtInt Group
- * A	6	4Bit	Yes	1
- * B	7	4Bit	Yes	1
- * C	8	4Bit	Yes	2
- * F	2	2Bit	Yes	4 [1]
- * G	7	4Bit	Yes	5
- * H	10	4Bit[2]	Yes	6
- * I	16	2Bit	Yes	None
- * J	12	2Bit	Yes	None
- * N	16	2Bit	No	IRQ_EINT
- * P	8	2Bit	Yes	8
- * R	15	4Bit[2]	Yes	8
- */
-
-static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5P6440
-	{
-		.chip	= {
-			.base	= S5P6440_GPA(0),
-			.ngpio	= S5P6440_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.chip	= {
-			.base	= S5P6440_GPB(0),
-			.ngpio	= S5P6440_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5P6440_GPC(0),
-			.ngpio	= S5P6440_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S5P64X0_GPG_BASE,
-		.chip	= {
-			.base	= S5P6440_GPG(0),
-			.ngpio	= S5P6440_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
-#ifdef CONFIG_CPU_S5P6440
-	{
-		.base	= S5P64X0_GPH_BASE + 0x4,
-		.chip	= {
-			.base	= S5P6440_GPH(0),
-			.ngpio	= S5P6440_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
-#ifdef CONFIG_CPU_S5P6440
-	{
-		.base	= S5P64X0_GPR_BASE + 0x4,
-		.config	= &s5p64x0_gpio_cfg_rbank,
-		.chip	= {
-			.base	= S5P6440_GPR(0),
-			.ngpio	= S5P6440_GPIO_R_NR,
-			.label	= "GPR",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
-#ifdef CONFIG_CPU_S5P6440
-	{
-		.base	= S5P64X0_GPF_BASE,
-		.config	= &samsung_gpio_cfgs[6],
-		.chip	= {
-			.base	= S5P6440_GPF(0),
-			.ngpio	= S5P6440_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S5P64X0_GPI_BASE,
-		.config	= &samsung_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6440_GPI(0),
-			.ngpio	= S5P6440_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S5P64X0_GPJ_BASE,
-		.config	= &samsung_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6440_GPJ(0),
-			.ngpio	= S5P6440_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S5P64X0_GPN_BASE,
-		.config	= &samsung_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6440_GPN(0),
-			.ngpio	= S5P6440_GPIO_N_NR,
-			.label	= "GPN",
-		},
-	}, {
-		.base	= S5P64X0_GPP_BASE,
-		.config	= &samsung_gpio_cfgs[6],
-		.chip	= {
-			.base	= S5P6440_GPP(0),
-			.ngpio	= S5P6440_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	},
-#endif
-};
-
-/*
- * S5P6450 GPIO bank summary:
- *
- * Bank	GPIOs	Style	SlpCon	ExtInt Group
- * A	6	4Bit	Yes	1
- * B	7	4Bit	Yes	1
- * C	8	4Bit	Yes	2
- * D	8	4Bit	Yes	None
- * F	2	2Bit	Yes	None
- * G	14	4Bit[2]	Yes	5
- * H	10	4Bit[2]	Yes	6
- * I	16	2Bit	Yes	None
- * J	12	2Bit	Yes	None
- * K	5	4Bit	Yes	None
- * N	16	2Bit	No	IRQ_EINT
- * P	11	2Bit	Yes	8
- * Q	14	2Bit	Yes	None
- * R	15	4Bit[2]	Yes	None
- * S	8	2Bit	Yes	None
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5P6450
-	{
-		.chip	= {
-			.base	= S5P6450_GPA(0),
-			.ngpio	= S5P6450_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.chip	= {
-			.base	= S5P6450_GPB(0),
-			.ngpio	= S5P6450_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5P6450_GPC(0),
-			.ngpio	= S5P6450_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.chip	= {
-			.base	= S5P6450_GPD(0),
-			.ngpio	= S5P6450_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.base	= S5P6450_GPK_BASE,
-		.chip	= {
-			.base	= S5P6450_GPK(0),
-			.ngpio	= S5P6450_GPIO_K_NR,
-			.label	= "GPK",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
-#ifdef CONFIG_CPU_S5P6450
-	{
-		.base	= S5P64X0_GPG_BASE + 0x4,
-		.chip	= {
-			.base	= S5P6450_GPG(0),
-			.ngpio	= S5P6450_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	}, {
-		.base	= S5P64X0_GPH_BASE + 0x4,
-		.chip	= {
-			.base	= S5P6450_GPH(0),
-			.ngpio	= S5P6450_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
-#ifdef CONFIG_CPU_S5P6450
-	{
-		.base	= S5P64X0_GPR_BASE + 0x4,
-		.config	= &s5p64x0_gpio_cfg_rbank,
-		.chip	= {
-			.base	= S5P6450_GPR(0),
-			.ngpio	= S5P6450_GPIO_R_NR,
-			.label	= "GPR",
-		},
-	},
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
-#ifdef CONFIG_CPU_S5P6450
-	{
-		.base	= S5P64X0_GPF_BASE,
-		.config	= &samsung_gpio_cfgs[6],
-		.chip	= {
-			.base	= S5P6450_GPF(0),
-			.ngpio	= S5P6450_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S5P64X0_GPI_BASE,
-		.config	= &samsung_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6450_GPI(0),
-			.ngpio	= S5P6450_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S5P64X0_GPJ_BASE,
-		.config	= &samsung_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6450_GPJ(0),
-			.ngpio	= S5P6450_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S5P64X0_GPN_BASE,
-		.config	= &samsung_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6450_GPN(0),
-			.ngpio	= S5P6450_GPIO_N_NR,
-			.label	= "GPN",
-		},
-	}, {
-		.base	= S5P64X0_GPP_BASE,
-		.config	= &samsung_gpio_cfgs[6],
-		.chip	= {
-			.base	= S5P6450_GPP(0),
-			.ngpio	= S5P6450_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	}, {
-		.base	= S5P6450_GPQ_BASE,
-		.config	= &samsung_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6450_GPQ(0),
-			.ngpio	= S5P6450_GPIO_Q_NR,
-			.label	= "GPQ",
-		},
-	}, {
-		.base	= S5P6450_GPS_BASE,
-		.config	= &samsung_gpio_cfgs[6],
-		.chip	= {
-			.base	= S5P6450_GPS(0),
-			.ngpio	= S5P6450_GPIO_S_NR,
-			.label	= "GPS",
-		},
-	},
-#endif
-};
-
-/*
- * S5PC100 GPIO bank summary:
- *
- * Bank	GPIOs	Style	INT Type
- * A0	8	4Bit	GPIO_INT0
- * A1	5	4Bit	GPIO_INT1
- * B	8	4Bit	GPIO_INT2
- * C	5	4Bit	GPIO_INT3
- * D	7	4Bit	GPIO_INT4
- * E0	8	4Bit	GPIO_INT5
- * E1	6	4Bit	GPIO_INT6
- * F0	8	4Bit	GPIO_INT7
- * F1	8	4Bit	GPIO_INT8
- * F2	8	4Bit	GPIO_INT9
- * F3	4	4Bit	GPIO_INT10
- * G0	8	4Bit	GPIO_INT11
- * G1	3	4Bit	GPIO_INT12
- * G2	7	4Bit	GPIO_INT13
- * G3	7	4Bit	GPIO_INT14
- * H0	8	4Bit	WKUP_INT
- * H1	8	4Bit	WKUP_INT
- * H2	8	4Bit	WKUP_INT
- * H3	8	4Bit	WKUP_INT
- * I	8	4Bit	GPIO_INT15
- * J0	8	4Bit	GPIO_INT16
- * J1	5	4Bit	GPIO_INT17
- * J2	8	4Bit	GPIO_INT18
- * J3	8	4Bit	GPIO_INT19
- * J4	4	4Bit	GPIO_INT20
- * K0	8	4Bit	None
- * K1	6	4Bit	None
- * K2	8	4Bit	None
- * K3	8	4Bit	None
- * L0	8	4Bit	None
- * L1	8	4Bit	None
- * L2	8	4Bit	None
- * L3	8	4Bit	None
- */
-
-static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5PC100
-	{
-		.chip	= {
-			.base	= S5PC100_GPA0(0),
-			.ngpio	= S5PC100_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPA1(0),
-			.ngpio	= S5PC100_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPB(0),
-			.ngpio	= S5PC100_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPC(0),
-			.ngpio	= S5PC100_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPD(0),
-			.ngpio	= S5PC100_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE0(0),
-			.ngpio	= S5PC100_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE1(0),
-			.ngpio	= S5PC100_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF0(0),
-			.ngpio	= S5PC100_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF1(0),
-			.ngpio	= S5PC100_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF2(0),
-			.ngpio	= S5PC100_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF3(0),
-			.ngpio	= S5PC100_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG0(0),
-			.ngpio	= S5PC100_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG1(0),
-			.ngpio	= S5PC100_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG2(0),
-			.ngpio	= S5PC100_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG3(0),
-			.ngpio	= S5PC100_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPI(0),
-			.ngpio	= S5PC100_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ0(0),
-			.ngpio	= S5PC100_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ1(0),
-			.ngpio	= S5PC100_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ2(0),
-			.ngpio	= S5PC100_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ3(0),
-			.ngpio	= S5PC100_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ4(0),
-			.ngpio	= S5PC100_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPK0(0),
-			.ngpio	= S5PC100_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPK1(0),
-			.ngpio	= S5PC100_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPK2(0),
-			.ngpio	= S5PC100_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPK3(0),
-			.ngpio	= S5PC100_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPL0(0),
-			.ngpio	= S5PC100_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPL1(0),
-			.ngpio	= S5PC100_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPL2(0),
-			.ngpio	= S5PC100_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPL3(0),
-			.ngpio	= S5PC100_GPIO_L3_NR,
-			.label	= "GPL3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPL4(0),
-			.ngpio	= S5PC100_GPIO_L4_NR,
-			.label	= "GPL4",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PC100_GPH0(0),
-			.ngpio	= S5PC100_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PC100_GPH1(0),
-			.ngpio	= S5PC100_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PC100_GPH2(0),
-			.ngpio	= S5PC100_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PC100_GPH3(0),
-			.ngpio	= S5PC100_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-#endif
-};
-
-/*
- * Followings are the gpio banks in S5PV210/S5PC110
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure samsung_gpio_cfgs[3] in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of samsung_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-
-static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5PV210
-	{
-		.chip	= {
-			.base	= S5PV210_GPA0(0),
-			.ngpio	= S5PV210_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPA1(0),
-			.ngpio	= S5PV210_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPB(0),
-			.ngpio	= S5PV210_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC0(0),
-			.ngpio	= S5PV210_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC1(0),
-			.ngpio	= S5PV210_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD0(0),
-			.ngpio	= S5PV210_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD1(0),
-			.ngpio	= S5PV210_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE0(0),
-			.ngpio	= S5PV210_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE1(0),
-			.ngpio	= S5PV210_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF0(0),
-			.ngpio	= S5PV210_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF1(0),
-			.ngpio	= S5PV210_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF2(0),
-			.ngpio	= S5PV210_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF3(0),
-			.ngpio	= S5PV210_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG0(0),
-			.ngpio	= S5PV210_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG1(0),
-			.ngpio	= S5PV210_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG2(0),
-			.ngpio	= S5PV210_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG3(0),
-			.ngpio	= S5PV210_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPI(0),
-			.ngpio	= S5PV210_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ0(0),
-			.ngpio	= S5PV210_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ1(0),
-			.ngpio	= S5PV210_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ2(0),
-			.ngpio	= S5PV210_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ3(0),
-			.ngpio	= S5PV210_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ4(0),
-			.ngpio	= S5PV210_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_MP01(0),
-			.ngpio	= S5PV210_GPIO_MP01_NR,
-			.label	= "MP01",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_MP02(0),
-			.ngpio	= S5PV210_GPIO_MP02_NR,
-			.label	= "MP02",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_MP03(0),
-			.ngpio	= S5PV210_GPIO_MP03_NR,
-			.label	= "MP03",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_MP04(0),
-			.ngpio	= S5PV210_GPIO_MP04_NR,
-			.label	= "MP04",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_MP05(0),
-			.ngpio	= S5PV210_GPIO_MP05_NR,
-			.label	= "MP05",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PV210_GPH0(0),
-			.ngpio	= S5PV210_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PV210_GPH1(0),
-			.ngpio	= S5PV210_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PV210_GPH2(0),
-			.ngpio	= S5PV210_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PV210_GPH3(0),
-			.ngpio	= S5PV210_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-#endif
-};
-
 /* TODO: cleanup soc_is_* */
 static __init int samsung_gpiolib_init(void)
 {
-	struct samsung_gpio_chip *chip;
-	int i, nr_chips;
-	int group = 0;
-
 	/*
 	 * Currently there are two drivers that can provide GPIO support for
 	 * Samsung SoCs. For device tree enabled platforms, the new
@@ -2109,54 +1192,6 @@ static __init int samsung_gpiolib_init(v
 				S3C64XX_VA_GPIO);
 		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
 				ARRAY_SIZE(s3c64xx_gpios_4bit2));
-	} else if (soc_is_s5p6440()) {
-		samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
-				ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
-		samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
-				ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
-		samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
-				ARRAY_SIZE(s5p6440_gpios_4bit2));
-		s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
-				ARRAY_SIZE(s5p6440_gpios_rbank));
-	} else if (soc_is_s5p6450()) {
-		samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
-				ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
-		samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
-				ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
-		samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
-				ARRAY_SIZE(s5p6450_gpios_4bit2));
-		s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
-				ARRAY_SIZE(s5p6450_gpios_rbank));
-	} else if (soc_is_s5pc100()) {
-		group = 0;
-		chip = s5pc100_gpios_4bit;
-		nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
-
-		for (i = 0; i < nr_chips; i++, chip++) {
-			if (!chip->config) {
-				chip->config = &samsung_gpio_cfgs[3];
-				chip->group = group++;
-			}
-		}
-		samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
-#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
-		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-#endif
-	} else if (soc_is_s5pv210()) {
-		group = 0;
-		chip = s5pv210_gpios_4bit;
-		nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
-
-		for (i = 0; i < nr_chips; i++, chip++) {
-			if (!chip->config) {
-				chip->config = &samsung_gpio_cfgs[3];
-				chip->group = group++;
-			}
-		}
-		samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
-#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
-		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-#endif
 	} else {
 		WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
 		return -ENODEV;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-sch311x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sch311x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-sch311x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sch311x.c	2014-09-28 17:29:07.000000000 -0400
@@ -291,14 +291,12 @@ static int sch311x_gpio_remove(struct pl
 {
 	struct sch311x_pdev_data *pdata = pdev->dev.platform_data;
 	struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
-	int err, i;
+	int i;
 
 	release_region(pdata->runtime_reg + GP1, 6);
 
 	for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
-		err = gpiochip_remove(&priv->blocks[i].chip);
-		if (err)
-			return err;
+		gpiochip_remove(&priv->blocks[i].chip);
 		dev_info(&pdev->dev,
 			 "SMSC SCH311x GPIO block %d unregistered.\n", i);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-sch.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sch.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-sch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sch.c	2014-09-28 17:29:07.000000000 -0400
@@ -290,8 +290,7 @@ static int sch_gpio_probe(struct platfor
 	return 0;
 
 err_sch_gpio_resume:
-	if (gpiochip_remove(&sch_gpio_core))
-		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+	gpiochip_remove(&sch_gpio_core);
 
 err_sch_gpio_core:
 	release_region(res->start, resource_size(res));
@@ -304,23 +303,14 @@ static int sch_gpio_remove(struct platfo
 {
 	struct resource *res;
 	if (gpio_ba) {
-		int err;
 
-		err  = gpiochip_remove(&sch_gpio_core);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-		err = gpiochip_remove(&sch_gpio_resume);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
+		gpiochip_remove(&sch_gpio_core);
+		gpiochip_remove(&sch_gpio_resume);
 
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 
 		release_region(res->start, resource_size(res));
 		gpio_ba = 0;
-
-		return err;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-sodaville.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sodaville.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-sodaville.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sodaville.c	2014-09-28 17:29:07.000000000 -0400
@@ -265,9 +265,7 @@ static void sdv_gpio_remove(struct pci_d
 	free_irq(pdev->irq, sd);
 	irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
 
-	if (gpiochip_remove(&sd->bgpio.gc))
-		dev_err(&pdev->dev, "gpiochip_remove() failed.\n");
-
+	gpiochip_remove(&sd->bgpio.gc);
 	pci_release_region(pdev, GPIO_BAR);
 	iounmap(sd->gpio_pub_base);
 	pci_disable_device(pdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-stmpe.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-stmpe.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-stmpe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-stmpe.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,8 +10,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/mfd/stmpe.h>
@@ -31,9 +29,7 @@ struct stmpe_gpio {
 	struct stmpe *stmpe;
 	struct device *dev;
 	struct mutex irq_lock;
-	struct irq_domain *domain;
 	unsigned norequest_mask;
-
 	/* Caches of interrupt control registers for bus_lock */
 	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
 	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -101,13 +97,6 @@ static int stmpe_gpio_direction_input(st
 	return stmpe_set_bits(stmpe, reg, mask, 0);
 }
 
-static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-
-	return irq_create_mapping(stmpe_gpio->domain, offset);
-}
-
 static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
 	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
@@ -126,14 +115,14 @@ static struct gpio_chip template_chip =
 	.get			= stmpe_gpio_get,
 	.direction_output	= stmpe_gpio_direction_output,
 	.set			= stmpe_gpio_set,
-	.to_irq			= stmpe_gpio_to_irq,
 	.request		= stmpe_gpio_request,
 	.can_sleep		= true,
 };
 
 static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -160,14 +149,16 @@ static int stmpe_gpio_irq_set_type(struc
 
 static void stmpe_gpio_irq_lock(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
 
 	mutex_lock(&stmpe_gpio->irq_lock);
 }
 
 static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
 	struct stmpe *stmpe = stmpe_gpio->stmpe;
 	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
 	static const u8 regmap[] = {
@@ -200,7 +191,8 @@ static void stmpe_gpio_irq_sync_unlock(s
 
 static void stmpe_gpio_irq_mask(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -210,7 +202,8 @@ static void stmpe_gpio_irq_mask(struct i
 
 static void stmpe_gpio_irq_unmask(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -253,7 +246,7 @@ static irqreturn_t stmpe_gpio_irq(int ir
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = bank * 8 + bit;
-			int child_irq = irq_find_mapping(stmpe_gpio->domain,
+			int child_irq = irq_find_mapping(stmpe_gpio->chip.irqdomain,
 							 line);
 
 			handle_nested_irq(child_irq);
@@ -271,56 +264,6 @@ static irqreturn_t stmpe_gpio_irq(int ir
 	return IRQ_HANDLED;
 }
 
-static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-			      irq_hw_number_t hwirq)
-{
-	struct stmpe_gpio *stmpe_gpio = d->host_data;
-
-	if (!stmpe_gpio)
-		return -EINVAL;
-
-	irq_set_chip_data(irq, stmpe_gpio);
-	irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
-				 handle_simple_irq);
-	irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-
-	return 0;
-}
-
-static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, 0);
-#endif
-	irq_set_chip_and_handler(irq, NULL, NULL);
-	irq_set_chip_data(irq, NULL);
-}
-
-static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
-	.unmap = stmpe_gpio_irq_unmap,
-	.map = stmpe_gpio_irq_map,
-	.xlate = irq_domain_xlate_twocell,
-};
-
-static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
-		struct device_node *np)
-{
-	stmpe_gpio->domain = irq_domain_add_simple(np,
-				stmpe_gpio->chip.ngpio, 0,
-				&stmpe_gpio_irq_simple_ops, stmpe_gpio);
-	if (!stmpe_gpio->domain) {
-		dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
-		return -ENOSYS;
-	}
-
-	return 0;
-}
-
 static int stmpe_gpio_probe(struct platform_device *pdev)
 {
 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
@@ -358,30 +301,37 @@ static int stmpe_gpio_probe(struct platf
 
 	if (irq < 0)
 		dev_info(&pdev->dev,
-			"device configured in no-irq mode; "
+			"device configured in no-irq mode: "
 			"irqs are not available\n");
 
 	ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
 	if (ret)
 		goto out_free;
 
-	if (irq >= 0) {
-		ret = stmpe_gpio_irq_init(stmpe_gpio, np);
-		if (ret)
-			goto out_disable;
-
-		ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq,
-				IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
+	if (irq > 0) {
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+				stmpe_gpio_irq, IRQF_ONESHOT,
+				"stmpe-gpio", stmpe_gpio);
 		if (ret) {
 			dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
 			goto out_disable;
 		}
+		ret =  gpiochip_irqchip_add(&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");
+			return ret;
+		}
 	}
 
 	ret = gpiochip_add(&stmpe_gpio->chip);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		goto out_freeirq;
+		goto out_disable;
 	}
 
 	if (pdata && pdata->setup)
@@ -391,9 +341,6 @@ static int stmpe_gpio_probe(struct platf
 
 	return 0;
 
-out_freeirq:
-	if (irq >= 0)
-		free_irq(irq, stmpe_gpio);
 out_disable:
 	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 out_free:
@@ -406,24 +353,14 @@ static int stmpe_gpio_remove(struct plat
 	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
 	struct stmpe *stmpe = stmpe_gpio->stmpe;
 	struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
-	int irq = platform_get_irq(pdev, 0);
-	int ret;
 
 	if (pdata && pdata->remove)
 		pdata->remove(stmpe, stmpe_gpio->chip.base);
 
-	ret = gpiochip_remove(&stmpe_gpio->chip);
-	if (ret < 0) {
-		dev_err(stmpe_gpio->dev,
-			"unable to remove gpiochip: %d\n", ret);
-		return ret;
-	}
+	gpiochip_remove(&stmpe_gpio->chip);
 
 	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 
-	if (irq >= 0)
-		free_irq(irq, stmpe_gpio);
-
 	kfree(stmpe_gpio);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-sx150x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sx150x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-sx150x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-sx150x.c	2014-09-28 17:29:07.000000000 -0400
@@ -615,19 +615,16 @@ static int sx150x_probe(struct i2c_clien
 
 	return 0;
 probe_fail_post_gpiochip_add:
-	WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
+	gpiochip_remove(&chip->gpio_chip);
 	return rc;
 }
 
 static int sx150x_remove(struct i2c_client *client)
 {
 	struct sx150x_chip *chip;
-	int rc;
 
 	chip = i2c_get_clientdata(client);
-	rc = gpiochip_remove(&chip->gpio_chip);
-	if (rc < 0)
-		return rc;
+	gpiochip_remove(&chip->gpio_chip);
 
 	if (chip->irq_summary >= 0)
 		sx150x_remove_irq_chip(chip);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-syscon.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-syscon.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-syscon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-syscon.c	2014-09-28 17:29:07.000000000 -0400
@@ -172,7 +172,8 @@ static int syscon_gpio_remove(struct pla
 {
 	struct syscon_gpio_priv *priv = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&priv->chip);
+	gpiochip_remove(&priv->chip);
+	return 0;
 }
 
 static struct platform_driver syscon_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-tb10x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tb10x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-tb10x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tb10x.c	2014-09-28 17:29:07.000000000 -0400
@@ -291,7 +291,6 @@ fail_ioremap:
 static int __exit tb10x_gpio_remove(struct platform_device *pdev)
 {
 	struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
-	int ret;
 
 	if (tb10x_gpio->gc.to_irq) {
 		irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0],
@@ -300,9 +299,7 @@ static int __exit tb10x_gpio_remove(stru
 		irq_domain_remove(tb10x_gpio->domain);
 		free_irq(tb10x_gpio->irq, tb10x_gpio);
 	}
-	ret = gpiochip_remove(&tb10x_gpio->gc);
-	if (ret)
-		return ret;
+	gpiochip_remove(&tb10x_gpio->gc);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-tc3589x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tc3589x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-tc3589x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tc3589x.c	2014-09-28 17:29:07.000000000 -0400
@@ -313,17 +313,11 @@ static int tc3589x_gpio_remove(struct pl
 	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
 	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
-	int ret;
 
 	if (pdata && pdata->remove)
 		pdata->remove(tc3589x, tc3589x_gpio->chip.base);
 
-	ret = gpiochip_remove(&tc3589x_gpio->chip);
-	if (ret < 0) {
-		dev_err(tc3589x_gpio->dev,
-			"unable to remove gpiochip: %d\n", ret);
-		return ret;
-	}
+	gpiochip_remove(&tc3589x_gpio->chip);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-timberdale.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-timberdale.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-timberdale.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-timberdale.c	2014-09-28 17:29:07.000000000 -0400
@@ -307,7 +307,6 @@ static int timbgpio_probe(struct platfor
 
 static int timbgpio_remove(struct platform_device *pdev)
 {
-	int err;
 	struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct timbgpio *tgpio = platform_get_drvdata(pdev);
 	int irq = platform_get_irq(pdev, 0);
@@ -323,9 +322,7 @@ static int timbgpio_remove(struct platfo
 		irq_set_handler_data(irq, NULL);
 	}
 
-	err = gpiochip_remove(&tgpio->gpio);
-	if (err)
-		printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
+	gpiochip_remove(&tgpio->gpio);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-tps6586x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps6586x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-tps6586x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps6586x.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,7 +137,8 @@ static int tps6586x_gpio_remove(struct p
 {
 	struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&tps6586x_gpio->gpio_chip);
+	gpiochip_remove(&tps6586x_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver tps6586x_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-tps65910.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps65910.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-tps65910.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps65910.c	2014-09-28 17:29:07.000000000 -0400
@@ -190,7 +190,8 @@ static int tps65910_gpio_remove(struct p
 {
 	struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&tps65910_gpio->gpio_chip);
+	gpiochip_remove(&tps65910_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver tps65910_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-tps65912.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps65912.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-tps65912.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-tps65912.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,7 +117,8 @@ static int tps65912_gpio_remove(struct p
 {
 	struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&tps65912_gpio->gpio_chip);
+	gpiochip_remove(&tps65912_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver tps65912_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-ts5500.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ts5500.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-ts5500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ts5500.c	2014-09-28 17:29:07.000000000 -0400
@@ -427,8 +427,7 @@ static int ts5500_dio_probe(struct platf
 
 	return 0;
 cleanup:
-	if (gpiochip_remove(&priv->gpio_chip))
-		dev_err(dev, "failed to remove gpio chip\n");
+	gpiochip_remove(&priv->gpio_chip);
 	return ret;
 }
 
@@ -437,7 +436,8 @@ static int ts5500_dio_remove(struct plat
 	struct ts5500_priv *priv = platform_get_drvdata(pdev);
 
 	ts5500_disable_irq(priv);
-	return gpiochip_remove(&priv->gpio_chip);
+	gpiochip_remove(&priv->gpio_chip);
+	return 0;
 }
 
 static struct platform_device_id ts5500_dio_ids[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-twl4030.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-twl4030.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-twl4030.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-twl4030.c	2014-09-28 17:29:07.000000000 -0400
@@ -554,7 +554,7 @@ no_irqs:
 
 	platform_set_drvdata(pdev, priv);
 
-	if (pdata && pdata->setup) {
+	if (pdata->setup) {
 		int status;
 
 		status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
@@ -583,9 +583,7 @@ static int gpio_twl4030_remove(struct pl
 		}
 	}
 
-	status = gpiochip_remove(&priv->gpio_chip);
-	if (status < 0)
-		return status;
+	gpiochip_remove(&priv->gpio_chip);
 
 	if (is_module())
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-twl6040.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-twl6040.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-twl6040.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-twl6040.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,7 +111,8 @@ static int gpo_twl6040_probe(struct plat
 
 static int gpo_twl6040_remove(struct platform_device *pdev)
 {
-	return gpiochip_remove(&twl6040gpo_chip);
+	gpiochip_remove(&twl6040gpo_chip);
+	return 0;
 }
 
 /* Note:  this hardware lives inside an I2C-based multi-function device. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-ucb1400.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ucb1400.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-ucb1400.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-ucb1400.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ static int ucb1400_gpio_probe(struct pla
 	if (err)
 		goto err;
 
-	if (ucb && ucb->gpio_setup)
+	if (ucb->gpio_setup)
 		err = ucb->gpio_setup(&dev->dev, ucb->gc.ngpio);
 
 err:
@@ -89,7 +89,7 @@ static int ucb1400_gpio_remove(struct pl
 			return err;
 	}
 
-	err = gpiochip_remove(&ucb->gc);
+	gpiochip_remove(&ucb->gc);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-viperboard.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-viperboard.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-viperboard.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-viperboard.c	2014-09-28 17:29:07.000000000 -0400
@@ -446,8 +446,7 @@ static int vprbrd_gpio_probe(struct plat
 	return ret;
 
 err_gpiob:
-	if (gpiochip_remove(&vb_gpio->gpioa))
-		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+	gpiochip_remove(&vb_gpio->gpioa);
 
 err_gpioa:
 	return ret;
@@ -456,13 +455,10 @@ err_gpioa:
 static int vprbrd_gpio_remove(struct platform_device *pdev)
 {
 	struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = gpiochip_remove(&vb_gpio->gpiob);
-	if (ret == 0)
-		ret = gpiochip_remove(&vb_gpio->gpioa);
+	gpiochip_remove(&vb_gpio->gpiob);
 
-	return ret;
+	return 0;
 }
 
 static struct platform_driver vprbrd_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-vr41xx.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-vr41xx.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-vr41xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-vr41xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -515,7 +515,7 @@ static int giu_probe(struct platform_dev
 	struct resource *res;
 	unsigned int trigger, i, pin;
 	struct irq_chip *chip;
-	int irq, retval;
+	int irq, ret;
 
 	switch (pdev->id) {
 	case GPIO_50PINS_PULLUPDOWN:
@@ -544,7 +544,11 @@ static int giu_probe(struct platform_dev
 
 	vr41xx_gpio_chip.dev = &pdev->dev;
 
-	retval = gpiochip_add(&vr41xx_gpio_chip);
+	ret = gpiochip_add(&vr41xx_gpio_chip);
+	if (!ret) {
+		iounmap(giu_base);
+		return -ENODEV;
+	}
 
 	giu_write(GIUINTENL, 0);
 	giu_write(GIUINTENH, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-vx855.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-vx855.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-vx855.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-vx855.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,8 +288,7 @@ static int vx855gpio_remove(struct platf
 	struct vx855_gpio *vg = platform_get_drvdata(pdev);
 	struct resource *res;
 
-	if (gpiochip_remove(&vg->gpio))
-		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+	gpiochip_remove(&vg->gpio);
 
 	if (vg->gpi_reserved) {
 		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-wm831x.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm831x.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-wm831x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm831x.c	2014-09-28 17:29:07.000000000 -0400
@@ -279,7 +279,8 @@ static int wm831x_gpio_remove(struct pla
 {
 	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
 
-	return  gpiochip_remove(&wm831x_gpio->gpio_chip);
+	gpiochip_remove(&wm831x_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver wm831x_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-wm8350.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm8350.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-wm8350.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm8350.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,8 @@ static int wm8350_gpio_remove(struct pla
 {
 	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&wm8350_gpio->gpio_chip);
+	gpiochip_remove(&wm8350_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver wm8350_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-wm8994.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm8994.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-wm8994.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-wm8994.c	2014-09-28 17:29:07.000000000 -0400
@@ -285,7 +285,8 @@ static int wm8994_gpio_remove(struct pla
 {
 	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
 
-	return gpiochip_remove(&wm8994_gpio->gpio_chip);
+	gpiochip_remove(&wm8994_gpio->gpio_chip);
+	return 0;
 }
 
 static struct platform_driver wm8994_gpio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/gpio-zynq.c linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-zynq.c
--- linux-libre-3.16-gnu/drivers/gpio/gpio-zynq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/gpio-zynq.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,712 @@
+/*
+ * Xilinx Zynq GPIO device driver
+ *
+ * Copyright (C) 2009 - 2014 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define DRIVER_NAME "zynq-gpio"
+
+/* Maximum banks */
+#define ZYNQ_GPIO_MAX_BANK	4
+
+#define ZYNQ_GPIO_BANK0_NGPIO	32
+#define ZYNQ_GPIO_BANK1_NGPIO	22
+#define ZYNQ_GPIO_BANK2_NGPIO	32
+#define ZYNQ_GPIO_BANK3_NGPIO	32
+
+#define ZYNQ_GPIO_NR_GPIOS	(ZYNQ_GPIO_BANK0_NGPIO + \
+				 ZYNQ_GPIO_BANK1_NGPIO + \
+				 ZYNQ_GPIO_BANK2_NGPIO + \
+				 ZYNQ_GPIO_BANK3_NGPIO)
+
+#define ZYNQ_GPIO_BANK0_PIN_MIN	0
+#define ZYNQ_GPIO_BANK0_PIN_MAX	(ZYNQ_GPIO_BANK0_PIN_MIN + \
+					ZYNQ_GPIO_BANK0_NGPIO - 1)
+#define ZYNQ_GPIO_BANK1_PIN_MIN	(ZYNQ_GPIO_BANK0_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK1_PIN_MAX	(ZYNQ_GPIO_BANK1_PIN_MIN + \
+					ZYNQ_GPIO_BANK1_NGPIO - 1)
+#define ZYNQ_GPIO_BANK2_PIN_MIN	(ZYNQ_GPIO_BANK1_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK2_PIN_MAX	(ZYNQ_GPIO_BANK2_PIN_MIN + \
+					ZYNQ_GPIO_BANK2_NGPIO - 1)
+#define ZYNQ_GPIO_BANK3_PIN_MIN	(ZYNQ_GPIO_BANK2_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK3_PIN_MAX	(ZYNQ_GPIO_BANK3_PIN_MIN + \
+					ZYNQ_GPIO_BANK3_NGPIO - 1)
+
+
+/* Register offsets for the GPIO device */
+/* LSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK)	(0x000 + (8 * BANK))
+/* MSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK)	(0x004 + (8 * BANK))
+/* Data Register-RW */
+#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK)	(0x060 + (4 * BANK))
+/* Direction mode reg-RW */
+#define ZYNQ_GPIO_DIRM_OFFSET(BANK)	(0x204 + (0x40 * BANK))
+/* Output enable reg-RW */
+#define ZYNQ_GPIO_OUTEN_OFFSET(BANK)	(0x208 + (0x40 * BANK))
+/* Interrupt mask reg-RO */
+#define ZYNQ_GPIO_INTMASK_OFFSET(BANK)	(0x20C + (0x40 * BANK))
+/* Interrupt enable reg-WO */
+#define ZYNQ_GPIO_INTEN_OFFSET(BANK)	(0x210 + (0x40 * BANK))
+/* Interrupt disable reg-WO */
+#define ZYNQ_GPIO_INTDIS_OFFSET(BANK)	(0x214 + (0x40 * BANK))
+/* Interrupt status reg-RO */
+#define ZYNQ_GPIO_INTSTS_OFFSET(BANK)	(0x218 + (0x40 * BANK))
+/* Interrupt type reg-RW */
+#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK)	(0x21C + (0x40 * BANK))
+/* Interrupt polarity reg-RW */
+#define ZYNQ_GPIO_INTPOL_OFFSET(BANK)	(0x220 + (0x40 * BANK))
+/* Interrupt on any, reg-RW */
+#define ZYNQ_GPIO_INTANY_OFFSET(BANK)	(0x224 + (0x40 * BANK))
+
+/* Disable all interrupts mask */
+#define ZYNQ_GPIO_IXR_DISABLE_ALL	0xFFFFFFFF
+
+/* Mid pin number of a bank */
+#define ZYNQ_GPIO_MID_PIN_NUM 16
+
+/* GPIO upper 16 bit mask */
+#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
+
+/**
+ * struct zynq_gpio - gpio device private data structure
+ * @chip:	instance of the gpio_chip
+ * @base_addr:	base address of the GPIO device
+ * @clk:	clock resource for this controller
+ */
+struct zynq_gpio {
+	struct gpio_chip chip;
+	void __iomem *base_addr;
+	struct clk *clk;
+};
+
+static struct irq_chip zynq_gpio_level_irqchip;
+static struct irq_chip zynq_gpio_edge_irqchip;
+
+/**
+ * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
+ * for a given pin in the GPIO device
+ * @pin_num:	gpio pin number within the device
+ * @bank_num:	an output parameter used to return the bank number of the gpio
+ *		pin
+ * @bank_pin_num: an output parameter used to return pin number within a bank
+ *		  for the given gpio pin
+ *
+ * Returns the bank number and pin offset within the bank.
+ */
+static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
+					  unsigned int *bank_num,
+					  unsigned int *bank_pin_num)
+{
+	switch (pin_num) {
+	case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
+		*bank_num = 0;
+		*bank_pin_num = pin_num;
+		break;
+	case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
+		*bank_num = 1;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
+		break;
+	case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
+		*bank_num = 2;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
+		break;
+	case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
+		*bank_num = 3;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
+		break;
+	default:
+		WARN(true, "invalid GPIO pin number: %u", pin_num);
+		*bank_num = 0;
+		*bank_pin_num = 0;
+		break;
+	}
+}
+
+/**
+ * zynq_gpio_get_value - Get the state of the specified pin of GPIO device
+ * @chip:	gpio_chip instance to be worked on
+ * @pin:	gpio pin number within the device
+ *
+ * This function reads the state of the specified pin of the GPIO device.
+ *
+ * Return: 0 if the pin is low, 1 if pin is high.
+ */
+static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
+{
+	u32 data;
+	unsigned int bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+	data = readl_relaxed(gpio->base_addr +
+			     ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
+
+	return (data >> bank_pin_num) & 1;
+}
+
+/**
+ * zynq_gpio_set_value - Modify the state of the pin with specified value
+ * @chip:	gpio_chip instance to be worked on
+ * @pin:	gpio pin number within the device
+ * @state:	value used to modify the state of the specified pin
+ *
+ * This function calculates the register offset (i.e to lower 16 bits or
+ * upper 16 bits) based on the given pin number and sets the state of a
+ * gpio pin to the specified value. The state is either 0 or non-zero.
+ */
+static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
+				int state)
+{
+	unsigned int reg_offset, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+	if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
+		/* only 16 data bits in bit maskable reg */
+		bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
+		reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
+	} else {
+		reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
+	}
+
+	/*
+	 * get the 32 bit value to be written to the mask/data register where
+	 * the upper 16 bits is the mask and lower 16 bits is the data
+	 */
+	state = !!state;
+	state = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
+		((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
+
+	writel_relaxed(state, gpio->base_addr + reg_offset);
+}
+
+/**
+ * zynq_gpio_dir_in - Set the direction of the specified GPIO pin as input
+ * @chip:	gpio_chip instance to be worked on
+ * @pin:	gpio pin number within the device
+ *
+ * This function uses the read-modify-write sequence to set the direction of
+ * the gpio pin as input.
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
+{
+	u32 reg;
+	unsigned int bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+	/* bank 0 pins 7 and 8 are special and cannot be used as inputs */
+	if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
+		return -EINVAL;
+
+	/* clear the bit in direction mode reg to set the pin as input */
+	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	reg &= ~BIT(bank_pin_num);
+	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+	return 0;
+}
+
+/**
+ * zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output
+ * @chip:	gpio_chip instance to be worked on
+ * @pin:	gpio pin number within the device
+ * @state:	value to be written to specified pin
+ *
+ * This function sets the direction of specified GPIO pin as output, configures
+ * the Output Enable register for the pin and uses zynq_gpio_set to set
+ * the state of the pin to the value specified.
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
+			     int state)
+{
+	u32 reg;
+	unsigned int bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+	/* set the GPIO pin as output */
+	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	reg |= BIT(bank_pin_num);
+	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+	/* configure the output enable reg for the pin */
+	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+	reg |= BIT(bank_pin_num);
+	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+
+	/* set the state of the pin */
+	zynq_gpio_set_value(chip, pin, state);
+	return 0;
+}
+
+/**
+ * zynq_gpio_irq_mask - Disable the interrupts for a gpio pin
+ * @irq_data:	per irq and chip data passed down to chip functions
+ *
+ * This function calculates gpio pin number from irq number and sets the
+ * bit in the Interrupt Disable register of the corresponding bank to disable
+ * interrupts for that pin.
+ */
+static void zynq_gpio_irq_mask(struct irq_data *irq_data)
+{
+	unsigned int device_pin_num, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+	device_pin_num = irq_data->hwirq;
+	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+	writel_relaxed(BIT(bank_pin_num),
+		       gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_unmask - Enable the interrupts for a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin for the interrupt
+ *		to enable
+ *
+ * This function calculates the gpio pin number from irq number and sets the
+ * bit in the Interrupt Enable register of the corresponding bank to enable
+ * interrupts for that pin.
+ */
+static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
+{
+	unsigned int device_pin_num, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+	device_pin_num = irq_data->hwirq;
+	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+	writel_relaxed(BIT(bank_pin_num),
+		       gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin for the interrupt
+ *		to ack
+ *
+ * This function calculates gpio pin number from irq number and sets the bit
+ * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
+ */
+static void zynq_gpio_irq_ack(struct irq_data *irq_data)
+{
+	unsigned int device_pin_num, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+	device_pin_num = irq_data->hwirq;
+	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+	writel_relaxed(BIT(bank_pin_num),
+		       gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin for the interrupt
+ *		to enable
+ *
+ * Clears the INTSTS bit and unmasks the given interrrupt.
+ */
+static void zynq_gpio_irq_enable(struct irq_data *irq_data)
+{
+	/*
+	 * The Zynq GPIO controller does not disable interrupt detection when
+	 * the interrupt is masked and only disables the propagation of the
+	 * interrupt. This means when the controller detects an interrupt
+	 * condition while the interrupt is logically disabled it will propagate
+	 * that interrupt event once the interrupt is enabled. This will cause
+	 * the interrupt consumer to see spurious interrupts to prevent this
+	 * first make sure that the interrupt is not asserted and then enable
+	 * it.
+	 */
+	zynq_gpio_irq_ack(irq_data);
+	zynq_gpio_irq_unmask(irq_data);
+}
+
+/**
+ * zynq_gpio_set_irq_type - Set the irq type for a gpio pin
+ * @irq_data:	irq data containing irq number of gpio pin
+ * @type:	interrupt type that is to be set for the gpio pin
+ *
+ * This function gets the gpio pin number and its bank from the gpio pin number
+ * and configures the INT_TYPE, INT_POLARITY and INT_ANY registers.
+ *
+ * Return: 0, negative error otherwise.
+ * TYPE-EDGE_RISING,  INT_TYPE - 1, INT_POLARITY - 1,  INT_ANY - 0;
+ * TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0,  INT_ANY - 0;
+ * TYPE-EDGE_BOTH,    INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1;
+ * TYPE-LEVEL_HIGH,   INT_TYPE - 0, INT_POLARITY - 1,  INT_ANY - NA;
+ * TYPE-LEVEL_LOW,    INT_TYPE - 0, INT_POLARITY - 0,  INT_ANY - NA
+ */
+static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
+{
+	u32 int_type, int_pol, int_any;
+	unsigned int device_pin_num, bank_num, bank_pin_num;
+	struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+	device_pin_num = irq_data->hwirq;
+	zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+
+	int_type = readl_relaxed(gpio->base_addr +
+				 ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+	int_pol = readl_relaxed(gpio->base_addr +
+				ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+	int_any = readl_relaxed(gpio->base_addr +
+				ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+
+	/*
+	 * based on the type requested, configure the INT_TYPE, INT_POLARITY
+	 * and INT_ANY registers
+	 */
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		int_type |= BIT(bank_pin_num);
+		int_pol |= BIT(bank_pin_num);
+		int_any &= ~BIT(bank_pin_num);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		int_type |= BIT(bank_pin_num);
+		int_pol &= ~BIT(bank_pin_num);
+		int_any &= ~BIT(bank_pin_num);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		int_type |= BIT(bank_pin_num);
+		int_any |= BIT(bank_pin_num);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		int_type &= ~BIT(bank_pin_num);
+		int_pol |= BIT(bank_pin_num);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		int_type &= ~BIT(bank_pin_num);
+		int_pol &= ~BIT(bank_pin_num);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel_relaxed(int_type,
+		       gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+	writel_relaxed(int_pol,
+		       gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+	writel_relaxed(int_any,
+		       gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+
+	if (type & IRQ_TYPE_LEVEL_MASK) {
+		__irq_set_chip_handler_name_locked(irq_data->irq,
+			&zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL);
+	} else {
+		__irq_set_chip_handler_name_locked(irq_data->irq,
+			&zynq_gpio_edge_irqchip, handle_level_irq, NULL);
+	}
+
+	return 0;
+}
+
+static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
+{
+	if (on)
+		zynq_gpio_irq_unmask(data);
+	else
+		zynq_gpio_irq_mask(data);
+
+	return 0;
+}
+
+/* irq chip descriptor */
+static struct irq_chip zynq_gpio_level_irqchip = {
+	.name		= DRIVER_NAME,
+	.irq_enable	= zynq_gpio_irq_enable,
+	.irq_eoi	= zynq_gpio_irq_ack,
+	.irq_mask	= zynq_gpio_irq_mask,
+	.irq_unmask	= zynq_gpio_irq_unmask,
+	.irq_set_type	= zynq_gpio_set_irq_type,
+	.irq_set_wake	= zynq_gpio_set_wake,
+	.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
+};
+
+static struct irq_chip zynq_gpio_edge_irqchip = {
+	.name		= DRIVER_NAME,
+	.irq_enable	= zynq_gpio_irq_enable,
+	.irq_ack	= zynq_gpio_irq_ack,
+	.irq_mask	= zynq_gpio_irq_mask,
+	.irq_unmask	= zynq_gpio_irq_unmask,
+	.irq_set_type	= zynq_gpio_set_irq_type,
+	.irq_set_wake	= zynq_gpio_set_wake,
+};
+
+/**
+ * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
+ * @irq:	irq number of the gpio bank where interrupt has occurred
+ * @desc:	irq descriptor instance of the 'irq'
+ *
+ * This function reads the Interrupt Status Register of each bank to get the
+ * gpio pin number which has triggered an interrupt. It then acks the triggered
+ * interrupt and calls the pin specific handler set by the higher layer
+ * application for that pin.
+ * Note: A bug is reported if no handler is set for the gpio pin.
+ */
+static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
+{
+	u32 int_sts, int_enb;
+	unsigned int bank_num;
+	struct zynq_gpio *gpio = irq_get_handler_data(irq);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(irqchip, desc);
+
+	for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++) {
+		int_sts = readl_relaxed(gpio->base_addr +
+					ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+		int_enb = readl_relaxed(gpio->base_addr +
+					ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
+		int_sts &= ~int_enb;
+		if (int_sts) {
+			int offset;
+			unsigned long pending = int_sts;
+
+			for_each_set_bit(offset, &pending, 32) {
+				unsigned int gpio_irq =
+					irq_find_mapping(gpio->chip.irqdomain,
+							offset);
+				generic_handle_irq(gpio_irq);
+			}
+		}
+	}
+
+	chained_irq_exit(irqchip, desc);
+}
+
+static int __maybe_unused zynq_gpio_suspend(struct device *dev)
+{
+	if (!device_may_wakeup(dev))
+		return pm_runtime_force_suspend(dev);
+
+	return 0;
+}
+
+static int __maybe_unused zynq_gpio_resume(struct device *dev)
+{
+	if (!device_may_wakeup(dev))
+		return pm_runtime_force_resume(dev);
+
+	return 0;
+}
+
+static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(gpio->clk);
+
+	return 0;
+}
+
+static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+	return clk_prepare_enable(gpio->clk);
+}
+
+static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(chip->dev);
+
+	/*
+	 * If the device is already active pm_runtime_get() will return 1 on
+	 * success, but gpio_request still needs to return 0.
+	 */
+	return ret < 0 ? ret : 0;
+}
+
+static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pm_runtime_put(chip->dev);
+}
+
+static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume)
+	SET_PM_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
+			zynq_gpio_runtime_resume, NULL)
+};
+
+/**
+ * zynq_gpio_probe - Initialization method for a zynq_gpio device
+ * @pdev:	platform device instance
+ *
+ * This function allocates memory resources for the gpio device and registers
+ * all the banks of the device. It will also set up interrupts for the gpio
+ * pins.
+ * Note: Interrupts are disabled for all the banks during initialization.
+ *
+ * Return: 0 on success, negative error otherwise.
+ */
+static int zynq_gpio_probe(struct platform_device *pdev)
+{
+	int ret, bank_num, irq;
+	struct zynq_gpio *gpio;
+	struct gpio_chip *chip;
+	struct resource *res;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, gpio);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gpio->base_addr))
+		return PTR_ERR(gpio->base_addr);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "invalid IRQ\n");
+		return irq;
+	}
+
+	/* configure the gpio chip */
+	chip = &gpio->chip;
+	chip->label = "zynq_gpio";
+	chip->owner = THIS_MODULE;
+	chip->dev = &pdev->dev;
+	chip->get = zynq_gpio_get_value;
+	chip->set = zynq_gpio_set_value;
+	chip->request = zynq_gpio_request;
+	chip->free = zynq_gpio_free;
+	chip->direction_input = zynq_gpio_dir_in;
+	chip->direction_output = zynq_gpio_dir_out;
+	chip->base = -1;
+	chip->ngpio = ZYNQ_GPIO_NR_GPIOS;
+
+	/* Enable GPIO clock */
+	gpio->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(gpio->clk)) {
+		dev_err(&pdev->dev, "input clock not found.\n");
+		return PTR_ERR(gpio->clk);
+	}
+	ret = clk_prepare_enable(gpio->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return ret;
+	}
+
+	/* report a bug if gpio chip registration fails */
+	ret = gpiochip_add(chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add gpio chip\n");
+		goto err_disable_clk;
+	}
+
+	/* disable interrupts for all banks */
+	for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++)
+		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
+			       ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+
+	ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0,
+				   handle_level_irq, IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add irq chip\n");
+		goto err_rm_gpiochip;
+	}
+
+	gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, irq,
+				     zynq_gpio_irqhandler);
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	device_set_wakeup_capable(&pdev->dev, 1);
+
+	return 0;
+
+err_rm_gpiochip:
+	if (gpiochip_remove(chip))
+		dev_err(&pdev->dev, "Failed to remove gpio chip\n");
+err_disable_clk:
+	clk_disable_unprepare(gpio->clk);
+
+	return ret;
+}
+
+/**
+ * zynq_gpio_remove - Driver removal function
+ * @pdev:	platform device instance
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_remove(struct platform_device *pdev)
+{
+	int ret;
+	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+	pm_runtime_get_sync(&pdev->dev);
+
+	ret = gpiochip_remove(&gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to remove gpio chip\n");
+		return ret;
+	}
+	clk_disable_unprepare(gpio->clk);
+	device_set_wakeup_capable(&pdev->dev, 0);
+	return 0;
+}
+
+static struct of_device_id zynq_gpio_of_match[] = {
+	{ .compatible = "xlnx,zynq-gpio-1.0", },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
+
+static struct platform_driver zynq_gpio_driver = {
+	.driver	= {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = &zynq_gpio_dev_pm_ops,
+		.of_match_table = zynq_gpio_of_match,
+	},
+	.probe = zynq_gpio_probe,
+	.remove = zynq_gpio_remove,
+};
+
+/**
+ * zynq_gpio_init - Initial driver registration call
+ *
+ * Return: value from platform_driver_register
+ */
+static int __init zynq_gpio_init(void)
+{
+	return platform_driver_register(&zynq_gpio_driver);
+}
+postcore_initcall(zynq_gpio_init);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Zynq GPIO driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpio/Kconfig
--- linux-libre-3.16-gnu/drivers/gpio/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -340,6 +340,13 @@ config GPIO_XILINX
 	help
 	  Say yes here to support the Xilinx FPGA GPIO device
 
+config GPIO_ZYNQ
+	tristate "Xilinx Zynq GPIO support"
+	depends on ARCH_ZYNQ
+	select GPIOLIB_IRQCHIP
+	help
+	  Say yes here to support Xilinx Zynq GPIO controller.
+
 config GPIO_XTENSA
 	bool "Xtensa GPIO32 support"
 	depends on XTENSA
@@ -423,7 +430,7 @@ config GPIO_GE_FPGA
 config GPIO_LYNXPOINT
 	tristate "Intel Lynxpoint GPIO support"
 	depends on ACPI && X86
-	select IRQ_DOMAIN
+	select GPIOLIB_IRQCHIP
 	help
 	  driver for GPIO functionality on Intel Lynxpoint PCH chipset
 	  Requires ACPI device enumeration code to set up a platform device.
@@ -450,6 +457,19 @@ config GPIO_ARIZONA
 	help
 	  Support for GPIOs on Wolfson Arizona class devices.
 
+config GPIO_CRYSTAL_COVE
+	tristate "GPIO support for Crystal Cove PMIC"
+	depends on INTEL_SOC_PMIC
+	select GPIOLIB_IRQCHIP
+	help
+	  Support for GPIO pins on Crystal Cove PMIC.
+
+	  Say Yes if you have a Intel SoC based tablet with Crystal Cove PMIC
+	  inside.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called gpio-crystalcove.
+
 config GPIO_LP3943
 	tristate "TI/National Semiconductor LP3943 GPIO expander"
 	depends on MFD_LP3943
@@ -573,6 +593,7 @@ config GPIO_SX150X
 config GPIO_STMPE
 	bool "STMPE GPIOs"
 	depends on MFD_STMPE
+	select GPIOLIB_IRQCHIP
 	help
 	  This enables support for the GPIOs found on the STMPE I/O
 	  Expanders.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpio/Makefile linux-libre-3.17-rc7-gnu/drivers/gpio/Makefile
--- linux-libre-3.16-gnu/drivers/gpio/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpio/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,9 @@ ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 
 obj-$(CONFIG_GPIO_DEVRES)	+= devres.o
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o
+obj-$(CONFIG_GPIOLIB)		+= gpiolib-legacy.o
 obj-$(CONFIG_OF_GPIO)		+= gpiolib-of.o
+obj-$(CONFIG_GPIO_SYSFS)	+= gpiolib-sysfs.o
 obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi.o
 
 # Device drivers. Generally keep list sorted alphabetically
@@ -20,6 +22,7 @@ obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
+obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
 obj-$(CONFIG_GPIO_DA9055)	+= gpio-da9055.o
 obj-$(CONFIG_GPIO_DAVINCI)	+= gpio-davinci.o
@@ -101,3 +104,4 @@ obj-$(CONFIG_GPIO_WM8994)	+= gpio-wm8994
 obj-$(CONFIG_GPIO_XILINX)	+= gpio-xilinx.o
 obj-$(CONFIG_GPIO_XTENSA)	+= gpio-xtensa.o
 obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o
+obj-$(CONFIG_GPIO_ZYNQ)		+= gpio-zynq.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_510.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_510.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_510.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_510.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,20 +15,19 @@
 #include "armada_drm.h"
 #include "armada_hw.h"
 
-static int armada510_init(struct armada_private *priv, struct device *dev)
+static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
 {
-	priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1");
+	struct clk *clk;
 
-	if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
-		priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+	clk = devm_clk_get(dev, "ext_ref_clk1");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
 
-	return PTR_RET(priv->extclk[0]);
-}
+	dcrtc->extclk[0] = clk;
 
-static int armada510_crtc_init(struct armada_crtc *dcrtc)
-{
 	/* Lower the watermark so to eliminate jitter at higher bandwidths */
 	armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+
 	return 0;
 }
 
@@ -45,8 +44,7 @@ static int armada510_crtc_init(struct ar
 static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
 	const struct drm_display_mode *mode, uint32_t *sclk)
 {
-	struct armada_private *priv = dcrtc->crtc.dev->dev_private;
-	struct clk *clk = priv->extclk[0];
+	struct clk *clk = dcrtc->extclk[0];
 	int ret;
 
 	if (dcrtc->num == 1)
@@ -81,7 +79,6 @@ static int armada510_crtc_compute_clock(
 const struct armada_variant armada510_ops = {
 	.has_spu_adv_reg = true,
 	.spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
-	.init = armada510_init,
-	.crtc_init = armada510_crtc_init,
-	.crtc_compute_clock = armada510_crtc_compute_clock,
+	.init = armada510_crtc_init,
+	.compute_clock = armada510_crtc_compute_clock,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,9 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include "armada_crtc.h"
@@ -332,24 +335,23 @@ static void armada_drm_crtc_commit(struc
 static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 	const struct drm_display_mode *mode, struct drm_display_mode *adj)
 {
-	struct armada_private *priv = crtc->dev->dev_private;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	int ret;
 
 	/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
-	if (!priv->variant->has_spu_adv_reg &&
+	if (!dcrtc->variant->has_spu_adv_reg &&
 	    adj->flags & DRM_MODE_FLAG_INTERLACE)
 		return false;
 
 	/* Check whether the display mode is possible */
-	ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL);
+	ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
 	if (ret)
 		return false;
 
 	return true;
 }
 
-void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
+static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 {
 	struct armada_vbl_event *e, *n;
 	void __iomem *base = dcrtc->base;
@@ -410,6 +412,27 @@ void armada_drm_crtc_irq(struct armada_c
 	}
 }
 
+static irqreturn_t armada_drm_irq(int irq, void *arg)
+{
+	struct armada_crtc *dcrtc = arg;
+	u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
+
+	/*
+	 * This is rediculous - rather than writing bits to clear, we
+	 * have to set the actual status register value.  This is racy.
+	 */
+	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+
+	/* Mask out those interrupts we haven't enabled */
+	v = stat & dcrtc->irq_ena;
+
+	if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
+		armada_drm_crtc_irq(dcrtc, stat);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
 /* These are locked by dev->vbl_lock */
 void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
 {
@@ -470,7 +493,6 @@ static int armada_drm_crtc_mode_set(stru
 	struct drm_display_mode *mode, struct drm_display_mode *adj,
 	int x, int y, struct drm_framebuffer *old_fb)
 {
-	struct armada_private *priv = crtc->dev->dev_private;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct armada_regs regs[17];
 	uint32_t lm, rm, tm, bm, val, sclk;
@@ -515,7 +537,7 @@ static int armada_drm_crtc_mode_set(stru
 	}
 
 	/* Now compute the divider for real */
-	priv->variant->crtc_compute_clock(dcrtc, adj, &sclk);
+	dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
 
 	/* Ensure graphic fifo is enabled */
 	armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
@@ -537,7 +559,7 @@ static int armada_drm_crtc_mode_set(stru
 	dcrtc->v[1].spu_v_porch = tm << 16 | bm;
 	val = adj->crtc_hsync_start;
 	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
-		priv->variant->spu_adv_reg;
+		dcrtc->variant->spu_adv_reg;
 
 	if (interlaced) {
 		/* Odd interlaced frame */
@@ -546,7 +568,7 @@ static int armada_drm_crtc_mode_set(stru
 		dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
 		val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
 		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
-			priv->variant->spu_adv_reg;
+			dcrtc->variant->spu_adv_reg;
 	} else {
 		dcrtc->v[0] = dcrtc->v[1];
 	}
@@ -561,7 +583,7 @@ static int armada_drm_crtc_mode_set(stru
 	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
 			   LCD_SPUT_V_H_TOTAL);
 
-	if (priv->variant->has_spu_adv_reg) {
+	if (dcrtc->variant->has_spu_adv_reg) {
 		armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
 				     ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
 				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
@@ -805,12 +827,11 @@ static int armada_drm_crtc_cursor_set(st
 {
 	struct drm_device *dev = crtc->dev;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
-	struct armada_private *priv = crtc->dev->dev_private;
 	struct armada_gem_object *obj = NULL;
 	int ret;
 
 	/* If no cursor support, replicate drm's return value */
-	if (!priv->variant->has_spu_adv_reg)
+	if (!dcrtc->variant->has_spu_adv_reg)
 		return -ENXIO;
 
 	if (handle && w > 0 && h > 0) {
@@ -858,11 +879,10 @@ static int armada_drm_crtc_cursor_move(s
 {
 	struct drm_device *dev = crtc->dev;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
-	struct armada_private *priv = crtc->dev->dev_private;
 	int ret;
 
 	/* If no cursor support, replicate drm's return value */
-	if (!priv->variant->has_spu_adv_reg)
+	if (!dcrtc->variant->has_spu_adv_reg)
 		return -EFAULT;
 
 	mutex_lock(&dev->struct_mutex);
@@ -888,6 +908,10 @@ static void armada_drm_crtc_destroy(stru
 	if (!IS_ERR(dcrtc->clk))
 		clk_disable_unprepare(dcrtc->clk);
 
+	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
+
+	of_node_put(dcrtc->crtc.port);
+
 	kfree(dcrtc);
 }
 
@@ -1027,23 +1051,22 @@ static int armada_drm_crtc_create_proper
 	return 0;
 }
 
-int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
-	struct resource *res)
+int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
+	struct resource *res, int irq, const struct armada_variant *variant,
+	struct device_node *port)
 {
-	struct armada_private *priv = dev->dev_private;
+	struct armada_private *priv = drm->dev_private;
 	struct armada_crtc *dcrtc;
 	void __iomem *base;
 	int ret;
 
-	ret = armada_drm_crtc_create_properties(dev);
+	ret = armada_drm_crtc_create_properties(drm);
 	if (ret)
 		return ret;
 
-	base = devm_request_and_ioremap(dev->dev, res);
-	if (!base) {
-		DRM_ERROR("failed to ioremap register\n");
-		return -ENOMEM;
-	}
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);
 	if (!dcrtc) {
@@ -1051,8 +1074,12 @@ int armada_drm_crtc_create(struct drm_de
 		return -ENOMEM;
 	}
 
+	if (dev != drm->dev)
+		dev_set_drvdata(dev, dcrtc);
+
+	dcrtc->variant = variant;
 	dcrtc->base = base;
-	dcrtc->num = num;
+	dcrtc->num = drm->mode_config.num_crtc;
 	dcrtc->clk = ERR_PTR(-EINVAL);
 	dcrtc->csc_yuv_mode = CSC_AUTO;
 	dcrtc->csc_rgb_mode = CSC_AUTO;
@@ -1074,9 +1101,18 @@ int armada_drm_crtc_create(struct drm_de
 		       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);
 
-	if (priv->variant->crtc_init) {
-		ret = priv->variant->crtc_init(dcrtc);
+	ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
+			       dcrtc);
+	if (ret < 0) {
+		kfree(dcrtc);
+		return ret;
+	}
+
+	if (dcrtc->variant->init) {
+		ret = dcrtc->variant->init(dcrtc, dev);
 		if (ret) {
 			kfree(dcrtc);
 			return ret;
@@ -1088,7 +1124,8 @@ int armada_drm_crtc_create(struct drm_de
 
 	priv->dcrtc[dcrtc->num] = dcrtc;
 
-	drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
+	dcrtc->crtc.port = port;
+	drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs);
 	drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
 
 	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
@@ -1096,5 +1133,107 @@ int armada_drm_crtc_create(struct drm_de
 	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
 				   dcrtc->csc_rgb_mode);
 
-	return armada_overlay_plane_create(dev, 1 << dcrtc->num);
+	return armada_overlay_plane_create(drm, 1 << dcrtc->num);
 }
+
+static int
+armada_lcd_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 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int irq = platform_get_irq(pdev, 0);
+	const struct armada_variant *variant;
+	struct device_node *port = NULL;
+
+	if (irq < 0)
+		return irq;
+
+	if (!dev->of_node) {
+		const struct platform_device_id *id;
+
+		id = platform_get_device_id(pdev);
+		if (!id)
+			return -ENXIO;
+
+		variant = (const struct armada_variant *)id->driver_data;
+	} else {
+		const struct of_device_id *match;
+		struct device_node *np, *parent = dev->of_node;
+
+		match = of_match_device(dev->driver->of_match_table, dev);
+		if (!match)
+			return -ENXIO;
+
+		np = of_get_child_by_name(parent, "ports");
+		if (np)
+			parent = np;
+		port = of_get_child_by_name(parent, "port");
+		of_node_put(np);
+		if (!port) {
+			dev_err(dev, "no port node found in %s\n",
+				parent->full_name);
+			return -ENXIO;
+		}
+
+		variant = match->data;
+	}
+
+	return armada_drm_crtc_create(drm, dev, res, irq, variant, port);
+}
+
+static void
+armada_lcd_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct armada_crtc *dcrtc = dev_get_drvdata(dev);
+
+	armada_drm_crtc_destroy(&dcrtc->crtc);
+}
+
+static const struct component_ops armada_lcd_ops = {
+	.bind = armada_lcd_bind,
+	.unbind = armada_lcd_unbind,
+};
+
+static int armada_lcd_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &armada_lcd_ops);
+}
+
+static int armada_lcd_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &armada_lcd_ops);
+	return 0;
+}
+
+static struct of_device_id armada_lcd_of_match[] = {
+	{
+		.compatible	= "marvell,dove-lcd",
+		.data		= &armada510_ops,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
+
+static const struct platform_device_id armada_lcd_platform_ids[] = {
+	{
+		.name		= "armada-lcd",
+		.driver_data	= (unsigned long)&armada510_ops,
+	}, {
+		.name		= "armada-510-lcd",
+		.driver_data	= (unsigned long)&armada510_ops,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
+
+struct platform_driver armada_lcd_platform_driver = {
+	.probe	= armada_lcd_probe,
+	.remove	= armada_lcd_remove,
+	.driver = {
+		.name	= "armada-lcd",
+		.owner	=  THIS_MODULE,
+		.of_match_table = armada_lcd_of_match,
+	},
+	.id_table = armada_lcd_platform_ids,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_crtc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_crtc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_crtc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_crtc.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,12 +32,15 @@ struct armada_regs {
 	armada_reg_queue_mod(_r, _i, 0, 0, ~0)
 
 struct armada_frame_work;
+struct armada_variant;
 
 struct armada_crtc {
 	struct drm_crtc		crtc;
+	const struct armada_variant *variant;
 	unsigned		num;
 	void __iomem		*base;
 	struct clk		*clk;
+	struct clk		*extclk[2];
 	struct {
 		uint32_t	spu_v_h_total;
 		uint32_t	spu_v_porch;
@@ -72,12 +75,16 @@ struct armada_crtc {
 };
 #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
 
-int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *);
+struct device_node;
+int armada_drm_crtc_create(struct drm_device *, struct device *,
+	struct resource *, int, const struct armada_variant *,
+	struct device_node *);
 void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
 void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
-void armada_drm_crtc_irq(struct armada_crtc *, u32);
 void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
 void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
 void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
 
+extern struct platform_driver armada_lcd_platform_driver;
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_drm.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_drm.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_drm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_drm.h	2014-09-28 17:29:07.000000000 -0400
@@ -59,26 +59,23 @@ void armada_drm_vbl_event_remove_unlocke
 struct armada_private;
 
 struct armada_variant {
-	bool	has_spu_adv_reg;
+	bool has_spu_adv_reg;
 	uint32_t spu_adv_reg;
-	int (*init)(struct armada_private *, struct device *);
-	int (*crtc_init)(struct armada_crtc *);
-	int (*crtc_compute_clock)(struct armada_crtc *,
-				  const struct drm_display_mode *,
-				  uint32_t *);
+	int (*init)(struct armada_crtc *, struct device *);
+	int (*compute_clock)(struct armada_crtc *,
+			     const struct drm_display_mode *,
+			     uint32_t *);
 };
 
 /* Variant ops */
 extern const struct armada_variant armada510_ops;
 
 struct armada_private {
-	const struct armada_variant *variant;
 	struct work_struct	fb_unref_work;
 	DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
 	struct drm_fb_helper	*fbdev;
 	struct armada_crtc	*dcrtc[2];
 	struct drm_mm		linear;
-	struct clk		*extclk[2];
 	struct drm_property	*csc_yuv_prop;
 	struct drm_property	*csc_rgb_prop;
 	struct drm_property	*colorkey_prop;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,7 +6,9 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <linux/module.h>
+#include <linux/of_graph.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include "armada_crtc.h"
@@ -52,6 +54,11 @@ static const struct armada_drm_slave_con
 };
 #endif
 
+static bool is_componentized(struct device *dev)
+{
+	return dev->of_node || dev->platform_data;
+}
+
 static void armada_drm_unref_work(struct work_struct *work)
 {
 	struct armada_private *priv =
@@ -85,6 +92,7 @@ void armada_drm_queue_unref_work(struct
 static int armada_drm_load(struct drm_device *dev, unsigned long flags)
 {
 	const struct platform_device_id *id;
+	const struct armada_variant *variant;
 	struct armada_private *priv;
 	struct resource *res[ARRAY_SIZE(priv->dcrtc)];
 	struct resource *mem = NULL;
@@ -107,7 +115,7 @@ static int armada_drm_load(struct drm_de
 			return -EINVAL;
 	}
 
-	if (!res[0] || !mem)
+	if (!mem)
 		return -ENXIO;
 
 	if (!devm_request_mem_region(dev->dev, mem->start,
@@ -128,11 +136,7 @@ static int armada_drm_load(struct drm_de
 	if (!id)
 		return -ENXIO;
 
-	priv->variant = (struct armada_variant *)id->driver_data;
-
-	ret = priv->variant->init(priv, dev->dev);
-	if (ret)
-		return ret;
+	variant = (const struct armada_variant *)id->driver_data;
 
 	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
 	INIT_KFIFO(priv->fb_unref);
@@ -155,40 +159,50 @@ static int armada_drm_load(struct drm_de
 
 	/* Create all LCD controllers */
 	for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+		int irq;
+
 		if (!res[n])
 			break;
 
-		ret = armada_drm_crtc_create(dev, n, res[n]);
+		irq = platform_get_irq(dev->platformdev, n);
+		if (irq < 0)
+			goto err_kms;
+
+		ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
+					     variant, NULL);
 		if (ret)
 			goto err_kms;
 	}
 
+	if (is_componentized(dev->dev)) {
+		ret = component_bind_all(dev->dev, dev);
+		if (ret)
+			goto err_kms;
+	} else {
 #ifdef CONFIG_DRM_ARMADA_TDA1998X
-	ret = armada_drm_connector_slave_create(dev, &tda19988_config);
-	if (ret)
-		goto err_kms;
+		ret = armada_drm_connector_slave_create(dev, &tda19988_config);
+		if (ret)
+			goto err_kms;
 #endif
+	}
 
-	ret = drm_vblank_init(dev, n);
-	if (ret)
-		goto err_kms;
-
-	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 	if (ret)
-		goto err_kms;
+		goto err_comp;
 
 	dev->vblank_disable_allowed = 1;
 
 	ret = armada_fbdev_init(dev);
 	if (ret)
-		goto err_irq;
+		goto err_comp;
 
 	drm_kms_helper_poll_init(dev);
 
 	return 0;
 
- err_irq:
-	drm_irq_uninstall(dev);
+ err_comp:
+	if (is_componentized(dev->dev))
+		component_unbind_all(dev->dev, dev);
  err_kms:
 	drm_mode_config_cleanup(dev);
 	drm_mm_takedown(&priv->linear);
@@ -203,7 +217,10 @@ static int armada_drm_unload(struct drm_
 
 	drm_kms_helper_poll_fini(dev);
 	armada_fbdev_fini(dev);
-	drm_irq_uninstall(dev);
+
+	if (is_componentized(dev->dev))
+		component_unbind_all(dev->dev, dev);
+
 	drm_mode_config_cleanup(dev);
 	drm_mm_takedown(&priv->linear);
 	flush_work(&priv->fb_unref_work);
@@ -259,52 +276,6 @@ static void armada_drm_disable_vblank(st
 	armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
 }
 
-static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
-{
-	struct drm_device *dev = arg;
-	struct armada_private *priv = dev->dev_private;
-	struct armada_crtc *dcrtc = priv->dcrtc[0];
-	uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
-	irqreturn_t handled = IRQ_NONE;
-
-	/*
-	 * This is rediculous - rather than writing bits to clear, we
-	 * have to set the actual status register value.  This is racy.
-	 */
-	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
-
-	/* Mask out those interrupts we haven't enabled */
-	v = stat & dcrtc->irq_ena;
-
-	if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
-		armada_drm_crtc_irq(dcrtc, stat);
-		handled = IRQ_HANDLED;
-	}
-
-	return handled;
-}
-
-static int armada_drm_irq_postinstall(struct drm_device *dev)
-{
-	struct armada_private *priv = dev->dev_private;
-	struct armada_crtc *dcrtc = priv->dcrtc[0];
-
-	spin_lock_irq(&dev->vbl_lock);
-	writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
-	writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
-	spin_unlock_irq(&dev->vbl_lock);
-
-	return 0;
-}
-
-static void armada_drm_irq_uninstall(struct drm_device *dev)
-{
-	struct armada_private *priv = dev->dev_private;
-	struct armada_crtc *dcrtc = priv->dcrtc[0];
-
-	writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
-}
-
 static struct drm_ioctl_desc armada_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
 		DRM_UNLOCKED),
@@ -340,9 +311,6 @@ static struct drm_driver armada_drm_driv
 	.get_vblank_counter	= drm_vblank_count,
 	.enable_vblank		= armada_drm_enable_vblank,
 	.disable_vblank		= armada_drm_disable_vblank,
-	.irq_handler		= armada_drm_irq_handler,
-	.irq_postinstall	= armada_drm_irq_postinstall,
-	.irq_uninstall		= armada_drm_irq_uninstall,
 #ifdef CONFIG_DEBUG_FS
 	.debugfs_init		= armada_drm_debugfs_init,
 	.debugfs_cleanup	= armada_drm_debugfs_cleanup,
@@ -362,19 +330,140 @@ static struct drm_driver armada_drm_driv
 	.desc			= "Armada SoC DRM",
 	.date			= "20120730",
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
-				  DRIVER_HAVE_IRQ | DRIVER_PRIME,
+				  DRIVER_PRIME,
 	.ioctls			= armada_ioctls,
 	.fops			= &armada_drm_fops,
 };
 
+static int armada_drm_bind(struct device *dev)
+{
+	return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
+}
+
+static void armada_drm_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int compare_dev_name(struct device *dev, void *data)
+{
+	const char *name = data;
+	return !strcmp(dev_name(dev), name);
+}
+
+static void armada_add_endpoints(struct device *dev,
+	struct component_match **match, struct device_node *port)
+{
+	struct device_node *ep, *remote;
+
+	for_each_child_of_node(port, ep) {
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote || !of_device_is_available(remote)) {
+			of_node_put(remote);
+			continue;
+		} else if (!of_device_is_available(remote->parent)) {
+			dev_warn(dev, "parent device of %s is not available\n",
+				 remote->full_name);
+			of_node_put(remote);
+			continue;
+		}
+
+		component_match_add(dev, match, compare_of, remote);
+		of_node_put(remote);
+	}
+}
+
+static int armada_drm_find_components(struct device *dev,
+	struct component_match **match)
+{
+	struct device_node *port;
+	int i;
+
+	if (dev->of_node) {
+		struct device_node *np = dev->of_node;
+
+		for (i = 0; ; i++) {
+			port = of_parse_phandle(np, "ports", i);
+			if (!port)
+				break;
+
+			component_match_add(dev, match, compare_of, port);
+			of_node_put(port);
+		}
+
+		if (i == 0) {
+			dev_err(dev, "missing 'ports' property\n");
+			return -ENODEV;
+		}
+
+		for (i = 0; ; i++) {
+			port = of_parse_phandle(np, "ports", i);
+			if (!port)
+				break;
+
+			armada_add_endpoints(dev, match, port);
+			of_node_put(port);
+		}
+	} else if (dev->platform_data) {
+		char **devices = dev->platform_data;
+		struct device *d;
+
+		for (i = 0; devices[i]; i++)
+			component_match_add(dev, match, compare_dev_name,
+					    devices[i]);
+
+		if (i == 0) {
+			dev_err(dev, "missing 'ports' property\n");
+			return -ENODEV;
+		}
+
+		for (i = 0; devices[i]; i++) {
+			d = bus_find_device_by_name(&platform_bus_type, NULL,
+					devices[i]);
+			if (d && d->of_node) {
+				for_each_child_of_node(d->of_node, port)
+					armada_add_endpoints(dev, match, port);
+			}
+			put_device(d);
+		}
+	}
+
+	return 0;
+}
+
+static const struct component_master_ops armada_master_ops = {
+	.bind = armada_drm_bind,
+	.unbind = armada_drm_unbind,
+};
+
 static int armada_drm_probe(struct platform_device *pdev)
 {
-	return drm_platform_init(&armada_drm_driver, pdev);
+	if (is_componentized(&pdev->dev)) {
+		struct component_match *match = NULL;
+		int ret;
+
+		ret = armada_drm_find_components(&pdev->dev, &match);
+		if (ret < 0)
+			return ret;
+
+		return component_master_add_with_match(&pdev->dev,
+				&armada_master_ops, match);
+	} else {
+		return drm_platform_init(&armada_drm_driver, pdev);
+	}
 }
 
 static int armada_drm_remove(struct platform_device *pdev)
 {
-	drm_put_dev(platform_get_drvdata(pdev));
+	if (is_componentized(&pdev->dev))
+		component_master_del(&pdev->dev, &armada_master_ops);
+	else
+		drm_put_dev(platform_get_drvdata(pdev));
 	return 0;
 }
 
@@ -402,14 +491,24 @@ static struct platform_driver armada_drm
 
 static int __init armada_drm_init(void)
 {
+	int ret;
+
 	armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls);
-	return platform_driver_register(&armada_drm_platform_driver);
+
+	ret = platform_driver_register(&armada_lcd_platform_driver);
+	if (ret)
+		return ret;
+	ret = platform_driver_register(&armada_drm_platform_driver);
+	if (ret)
+		platform_driver_unregister(&armada_lcd_platform_driver);
+	return ret;
 }
 module_init(armada_drm_init);
 
 static void __exit armada_drm_exit(void)
 {
 	platform_driver_unregister(&armada_drm_platform_driver);
+	platform_driver_unregister(&armada_lcd_platform_driver);
 }
 module_exit(armada_drm_exit);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,7 +131,7 @@ static int armada_fb_probe(struct drm_fb
 	return ret;
 }
 
-static struct drm_fb_helper_funcs armada_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
 	.gamma_set	= armada_drm_crtc_gamma_set,
 	.gamma_get	= armada_drm_crtc_gamma_get,
 	.fb_probe	= armada_fb_probe,
@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device
 
 	priv->fbdev = fbh;
 
-	fbh->funcs = &armada_fb_helper_funcs;
+	drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(dev, fbh, 1, 1);
 	if (ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -539,7 +539,7 @@ armada_gem_prime_export(struct drm_devic
 	int flags)
 {
 	return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
-			      O_RDWR);
+			      O_RDWR, NULL);
 }
 
 struct drm_gem_object *
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_output.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_output.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/armada/armada_output.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/armada/armada_output.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@ static void armada_drm_connector_destroy
 {
 	struct armada_connector *dconn = drm_to_armada_conn(conn);
 
-	drm_sysfs_connector_remove(conn);
+	drm_connector_unregister(conn);
 	drm_connector_cleanup(conn);
 	kfree(dconn);
 }
@@ -141,7 +141,7 @@ int armada_output_create(struct drm_devi
 	if (ret)
 		goto err_conn;
 
-	ret = drm_sysfs_connector_add(&dconn->conn);
+	ret = drm_connector_register(&dconn->conn);
 	if (ret)
 		goto err_sysfs;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ static struct drm_driver driver;
 	.subdevice = PCI_ANY_ID,		\
 	.driver_data = (unsigned long) info }
 
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
 	AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL),
 	AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL),
 	/*	AST_VGA_DEVICE(PCI_CHIP_AST1180, NULL), - don't bind to 1180 for now */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -362,7 +362,7 @@ static inline int ast_bo_reserve(struct
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -287,7 +287,7 @@ static void ast_fb_gamma_get(struct drm_
 	*blue = ast_crtc->lut_b[regno] << 8;
 }
 
-static struct drm_fb_helper_funcs ast_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
 	.gamma_set = ast_fb_gamma_set,
 	.gamma_get = ast_fb_gamma_get,
 	.fb_probe = astfb_create,
@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *de
 		return -ENOMEM;
 
 	ast->fbdev = afbdev;
-	afbdev->helper.funcs = &ast_fb_helper_funcs;
 	spin_lock_init(&afbdev->dirty_lock);
+
+	drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
+
 	ret = drm_fb_helper_init(dev, &afbdev->helper,
 				 1, 1);
 	if (ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_main.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_main.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,7 @@ static int ast_detect_chip(struct drm_de
 {
 	struct ast_private *ast = dev->dev_private;
 	uint32_t data, jreg;
+	ast_open_key(ast);
 
 	if (dev->pdev->device == PCI_CHIP_AST1180) {
 		ast->chip = AST1100;
@@ -104,7 +105,7 @@ static int ast_detect_chip(struct drm_de
 			}
 			ast->vga2_clone = false;
 		} else {
-			ast->chip = 2000;
+			ast->chip = AST2000;
 			DRM_INFO("AST 2000 detected\n");
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_mode.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_mode.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_mode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_mode.c	2014-09-28 17:29:07.000000000 -0400
@@ -667,17 +667,9 @@ static void ast_encoder_destroy(struct d
 static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
 	/* pick the encoder ids */
-	if (enc_id) {
-		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
@@ -829,7 +821,7 @@ static void ast_connector_destroy(struct
 {
 	struct ast_connector *ast_connector = to_ast_connector(connector);
 	ast_i2c_destroy(ast_connector->i2c);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -871,7 +863,7 @@ static int ast_connector_init(struct drm
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_tables.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_tables.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/ast/ast_tables.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ast/ast_tables.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,7 @@ static struct ast_vbios_dclk_info dclk_t
 	{0x25, 0x65, 0x80},					/* 16: VCLK88.75    */
 	{0x77, 0x58, 0x80},					/* 17: VCLK119      */
 	{0x32, 0x67, 0x80},				    /* 18: VCLK85_5     */
+	{0x6a, 0x6d, 0x80},					/* 19: VCLK97_75	*/
 };
 
 static struct ast_vbios_stdtable vbios_stdtable[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,6 +97,7 @@ static struct drm_driver bochs_driver =
 /* ---------------------------------------------------------------------- */
 /* pm interface                                                           */
 
+#ifdef CONFIG_PM_SLEEP
 static int bochs_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -131,6 +132,7 @@ static int bochs_pm_resume(struct device
 	drm_kms_helper_poll_enable(drm_dev);
 	return 0;
 }
+#endif
 
 static const struct dev_pm_ops bochs_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
@@ -175,7 +177,7 @@ static void bochs_pci_remove(struct pci_
 	drm_put_dev(dev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = {
+static const struct pci_device_id bochs_pci_tbl[] = {
 	{
 		.vendor      = 0x1234,
 		.device      = 0x1111,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,7 @@ static int bochsfb_create(struct drm_fb_
 
 	bo = gem_to_bochs_bo(gobj);
 
-	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+	ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -179,7 +179,7 @@ void bochs_fb_gamma_get(struct drm_crtc
 	*blue  = regno;
 }
 
-static struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
 	.gamma_set = bochs_fb_gamma_set,
 	.gamma_get = bochs_fb_gamma_get,
 	.fb_probe = bochsfb_create,
@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device
 {
 	int ret;
 
-	bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
+	drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
+			      &bochs_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
 				 1, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@ static int bochs_crtc_mode_set_base(stru
 	if (old_fb) {
 		bochs_fb = to_bochs_framebuffer(old_fb);
 		bo = gem_to_bochs_bo(bochs_fb->obj);
-		ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+		ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
 		if (ret) {
 			DRM_ERROR("failed to reserve old_fb bo\n");
 		} else {
@@ -67,7 +67,7 @@ static int bochs_crtc_mode_set_base(stru
 
 	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
 	bo = gem_to_bochs_bo(bochs_fb->obj);
-	ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+	ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -216,18 +216,9 @@ static struct drm_encoder *
 bochs_connector_best_encoder(struct drm_connector *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
 	/* pick the encoder ids */
-	if (enc_id) {
-		obj = drm_mode_object_find(connector->dev, enc_id,
-					   DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
@@ -259,6 +250,7 @@ static void bochs_connector_init(struct
 			   DRM_MODE_CONNECTOR_VIRTUAL);
 	drm_connector_helper_add(connector,
 				 &bochs_connector_connector_helper_funcs);
+	drm_connector_register(connector);
 }
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_mm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_mm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2014-09-28 17:29:07.000000000 -0400
@@ -387,7 +387,7 @@ int bochs_gem_create(struct drm_device *
 
 	*obj = NULL;
 
-	size = ALIGN(size, PAGE_SIZE);
+	size = PAGE_ALIGN(size);
 	if (size == 0)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/bridge/ptn3460.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bridge/ptn3460.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/bridge/ptn3460.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/bridge/ptn3460.c	2014-09-28 17:29:07.000000000 -0400
@@ -328,7 +328,7 @@ int ptn3460_init(struct drm_device *dev,
 	}
 	drm_connector_helper_add(&ptn_bridge->connector,
 			&ptn3460_connector_helper_funcs);
-	drm_sysfs_connector_add(&ptn_bridge->connector);
+	drm_connector_register(&ptn_bridge->connector);
 	drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,7 @@ module_param_named(modeset, cirrus_modes
 static struct drm_driver driver;
 
 /* only bind to the cirrus chip in qemu */
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
 	{ PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
 	  0, 0 },
 	{0,}
@@ -76,6 +76,7 @@ static void cirrus_pci_remove(struct pci
 	drm_put_dev(dev);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int cirrus_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -110,6 +111,7 @@ static int cirrus_pm_resume(struct devic
 	drm_kms_helper_poll_enable(drm_dev);
 	return 0;
 }
+#endif
 
 static const struct file_operations cirrus_driver_fops = {
 	.owner = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -241,7 +241,7 @@ static inline int cirrus_bo_reserve(stru
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,7 +288,7 @@ static int cirrus_fbdev_destroy(struct d
 	return 0;
 }
 
-static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
 	.gamma_set = cirrus_crtc_fb_gamma_set,
 	.gamma_get = cirrus_crtc_fb_gamma_get,
 	.fb_probe = cirrusfb_create,
@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_devi
 		return -ENOMEM;
 
 	cdev->mode_info.gfbdev = gfbdev;
-	gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
 	spin_lock_init(&gfbdev->dirty_lock);
 
+	drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
+			      &cirrus_fb_helper_funcs);
+
 	ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
 				 cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
 	if (ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c	2014-09-28 17:29:07.000000000 -0400
@@ -509,19 +509,9 @@ static struct drm_encoder *cirrus_connec
 						  *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
 	/* pick the encoder ids */
-	if (enc_id) {
-		obj =
-		    drm_mode_object_find(connector->dev, enc_id,
-					 DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
@@ -565,6 +555,7 @@ static struct drm_connector *cirrus_vga_
 
 	drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
 
+	drm_connector_register(connector);
 	return connector;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_buffer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_buffer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_buffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_buffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,11 +80,7 @@ int drm_buffer_alloc(struct drm_buffer *
 
 error_out:
 
-	/* Only last element can be null pointer so check for it first. */
-	if ((*buf)->data[idx])
-		kfree((*buf)->data[idx]);
-
-	for (--idx; idx >= 0; --idx)
+	for (; idx >= 0; --idx)
 		kfree((*buf)->data[idx]);
 
 	kfree(*buf);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_bufs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_bufs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_bufs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_bufs.c	2014-09-28 17:29:07.000000000 -0400
@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev,
 				struct drm_buf_desc __user *to =
 				    &request->list[count];
 				struct drm_buf_entry *from = &dma->bufs[i];
-				struct drm_freelist *list = &dma->bufs[i].freelist;
 				if (copy_to_user(&to->count,
 						 &from->buf_count,
 						 sizeof(from->buf_count)) ||
@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev,
 						 &from->buf_size,
 						 sizeof(from->buf_size)) ||
 				    copy_to_user(&to->low_mark,
-						 &list->low_mark,
-						 sizeof(list->low_mark)) ||
+						 &from->low_mark,
+						 sizeof(from->low_mark)) ||
 				    copy_to_user(&to->high_mark,
-						 &list->high_mark,
-						 sizeof(list->high_mark)))
+						 &from->high_mark,
+						 sizeof(from->high_mark)))
 					return -EFAULT;
 
 				DRM_DEBUG("%d %d %d %d %d\n",
 					  i,
 					  dma->bufs[i].buf_count,
 					  dma->bufs[i].buf_size,
-					  dma->bufs[i].freelist.low_mark,
-					  dma->bufs[i].freelist.high_mark);
+					  dma->bufs[i].low_mark,
+					  dma->bufs[i].high_mark);
 				++count;
 			}
 		}
@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev,
 	if (request->high_mark < 0 || request->high_mark > entry->buf_count)
 		return -EINVAL;
 
-	entry->freelist.low_mark = request->low_mark;
-	entry->freelist.high_mark = request->high_mark;
+	entry->low_mark = request->low_mark;
+	entry->high_mark = request->high_mark;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_context.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_context.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_context.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_context.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,18 +1,13 @@
-/**
- * \file drm_context.c
- * IOCTLs for generic contexts
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
 /*
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ * Legacy: Generic DRM Contexts
  *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -33,14 +28,14 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/*
- * ChangeLog:
- *  2001-11-16	Torsten Duwe <duwe@caldera.de>
- *		added context constructor/destructor hooks,
- *		needed by SiS driver's memory management.
- */
-
 #include <drm/drmP.h>
+#include "drm_legacy.h"
+
+struct drm_ctx_list {
+	struct list_head head;
+	drm_context_t handle;
+	struct drm_file *tag;
+};
 
 /******************************************************************/
 /** \name Context bitmap support */
@@ -56,7 +51,7 @@
  * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
  * lock.
  */
-void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
+void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
 {
 	mutex_lock(&dev->struct_mutex);
 	idr_remove(&dev->ctx_idr, ctx_handle);
@@ -72,7 +67,7 @@ void drm_ctxbitmap_free(struct drm_devic
  * Allocate a new idr from drm_device::ctx_idr while holding the
  * drm_device::struct_mutex lock.
  */
-static int drm_ctxbitmap_next(struct drm_device * dev)
+static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
 {
 	int ret;
 
@@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm
  *
  * Initialise the drm_device::ctx_idr
  */
-int drm_ctxbitmap_init(struct drm_device * dev)
+int drm_legacy_ctxbitmap_init(struct drm_device * dev)
 {
 	idr_init(&dev->ctx_idr);
 	return 0;
@@ -104,13 +99,43 @@ int drm_ctxbitmap_init(struct drm_device
  * Free all idr members using drm_ctx_sarea_free helper function
  * while holding the drm_device::struct_mutex lock.
  */
-void drm_ctxbitmap_cleanup(struct drm_device * dev)
+void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
 {
 	mutex_lock(&dev->struct_mutex);
 	idr_destroy(&dev->ctx_idr);
 	mutex_unlock(&dev->struct_mutex);
 }
 
+/**
+ * drm_ctxbitmap_flush() - Flush all contexts owned by a file
+ * @dev: DRM device to operate on
+ * @file: Open file to flush contexts for
+ *
+ * This iterates over all contexts on @dev and drops them if they're owned by
+ * @file. Note that after this call returns, new contexts might be added if
+ * the file is still alive.
+ */
+void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_ctx_list *pos, *tmp;
+
+	mutex_lock(&dev->ctxlist_mutex);
+
+	list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
+		if (pos->tag == file &&
+		    pos->handle != DRM_KERNEL_CONTEXT) {
+			if (dev->driver->context_dtor)
+				dev->driver->context_dtor(dev, pos->handle);
+
+			drm_legacy_ctxbitmap_free(dev, pos->handle);
+			list_del(&pos->head);
+			kfree(pos);
+		}
+	}
+
+	mutex_unlock(&dev->ctxlist_mutex);
+}
+
 /*@}*/
 
 /******************************************************************/
@@ -129,8 +154,8 @@ void drm_ctxbitmap_cleanup(struct drm_de
  * Gets the map from drm_device::ctx_idr with the handle specified and
  * returns its handle.
  */
-int drm_getsareactx(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
+int drm_legacy_getsareactx(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
 {
 	struct drm_ctx_priv_map *request = data;
 	struct drm_local_map *map;
@@ -173,8 +198,8 @@ int drm_getsareactx(struct drm_device *d
  * Searches the mapping specified in \p arg and update the entry in
  * drm_device::ctx_idr with it.
  */
-int drm_setsareactx(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
+int drm_legacy_setsareactx(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
 {
 	struct drm_ctx_priv_map *request = data;
 	struct drm_local_map *map = NULL;
@@ -273,8 +298,8 @@ static int drm_context_switch_complete(s
  * \param arg user argument pointing to a drm_ctx_res structure.
  * \return zero on success or a negative number on failure.
  */
-int drm_resctx(struct drm_device *dev, void *data,
-	       struct drm_file *file_priv)
+int drm_legacy_resctx(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
 {
 	struct drm_ctx_res *res = data;
 	struct drm_ctx ctx;
@@ -304,16 +329,16 @@ int drm_resctx(struct drm_device *dev, v
  *
  * Get a new handle for the context and copy to userspace.
  */
-int drm_addctx(struct drm_device *dev, void *data,
-	       struct drm_file *file_priv)
+int drm_legacy_addctx(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
 {
 	struct drm_ctx_list *ctx_entry;
 	struct drm_ctx *ctx = data;
 
-	ctx->handle = drm_ctxbitmap_next(dev);
+	ctx->handle = drm_legacy_ctxbitmap_next(dev);
 	if (ctx->handle == DRM_KERNEL_CONTEXT) {
 		/* Skip kernel's context and get a new one. */
-		ctx->handle = drm_ctxbitmap_next(dev);
+		ctx->handle = drm_legacy_ctxbitmap_next(dev);
 	}
 	DRM_DEBUG("%d\n", ctx->handle);
 	if (ctx->handle == -1) {
@@ -348,7 +373,8 @@ int drm_addctx(struct drm_device *dev, v
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  */
-int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_legacy_getctx(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
 {
 	struct drm_ctx *ctx = data;
 
@@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, v
  *
  * Calls context_switch().
  */
-int drm_switchctx(struct drm_device *dev, void *data,
-		  struct drm_file *file_priv)
+int drm_legacy_switchctx(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
 {
 	struct drm_ctx *ctx = data;
 
@@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev
  *
  * Calls context_switch_complete().
  */
-int drm_newctx(struct drm_device *dev, void *data,
-	       struct drm_file *file_priv)
+int drm_legacy_newctx(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
 {
 	struct drm_ctx *ctx = data;
 
@@ -411,8 +437,8 @@ int drm_newctx(struct drm_device *dev, v
  *
  * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
  */
-int drm_rmctx(struct drm_device *dev, void *data,
-	      struct drm_file *file_priv)
+int drm_legacy_rmctx(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
 {
 	struct drm_ctx *ctx = data;
 
@@ -420,7 +446,7 @@ int drm_rmctx(struct drm_device *dev, vo
 	if (ctx->handle != DRM_KERNEL_CONTEXT) {
 		if (dev->driver->context_dtor)
 			dev->driver->context_dtor(dev, ctx->handle);
-		drm_ctxbitmap_free(dev, ctx->handle);
+		drm_legacy_ctxbitmap_free(dev, ctx->handle);
 	}
 
 	mutex_lock(&dev->ctxlist_mutex);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,6 +41,10 @@
 
 #include "drm_crtc_internal.h"
 
+static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
+							struct drm_mode_fb_cmd2 *r,
+							struct drm_file *file_priv);
+
 /**
  * drm_modeset_lock_all - take all modeset locks
  * @dev: drm device
@@ -178,6 +182,12 @@ static const struct drm_prop_enum_list d
 	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
 };
 
+static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
+	{ DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
+	{ DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
+	{ DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
+};
+
 /*
  * Non-global properties, but "required" for certain connectors.
  */
@@ -357,6 +367,32 @@ const char *drm_get_format_name(uint32_t
 }
 EXPORT_SYMBOL(drm_get_format_name);
 
+/*
+ * Internal function to assign a slot in the object idr and optionally
+ * register the object into the idr.
+ */
+static int drm_mode_object_get_reg(struct drm_device *dev,
+				   struct drm_mode_object *obj,
+				   uint32_t obj_type,
+				   bool register_obj)
+{
+	int ret;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
+	if (ret >= 0) {
+		/*
+		 * Set up the object linking under the protection of the idr
+		 * lock so that other users can't see inconsistent state.
+		 */
+		obj->id = ret;
+		obj->type = obj_type;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return ret < 0 ? ret : 0;
+}
+
 /**
  * drm_mode_object_get - allocate a new modeset identifier
  * @dev: DRM device
@@ -375,21 +411,15 @@ EXPORT_SYMBOL(drm_get_format_name);
 int drm_mode_object_get(struct drm_device *dev,
 			struct drm_mode_object *obj, uint32_t obj_type)
 {
-	int ret;
+	return drm_mode_object_get_reg(dev, obj, obj_type, true);
+}
 
+static void drm_mode_object_register(struct drm_device *dev,
+				     struct drm_mode_object *obj)
+{
 	mutex_lock(&dev->mode_config.idr_mutex);
-	ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL);
-	if (ret >= 0) {
-		/*
-		 * Set up the object linking under the protection of the idr
-		 * lock so that other users can't see inconsistent state.
-		 */
-		obj->id = ret;
-		obj->type = obj_type;
-	}
+	idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
 	mutex_unlock(&dev->mode_config.idr_mutex);
-
-	return ret < 0 ? ret : 0;
 }
 
 /**
@@ -416,8 +446,12 @@ static struct drm_mode_object *_object_f
 
 	mutex_lock(&dev->mode_config.idr_mutex);
 	obj = idr_find(&dev->mode_config.crtc_idr, id);
-	if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
-	    (obj->id != id))
+	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+		obj = NULL;
+	if (obj && obj->id != id)
+		obj = NULL;
+	/* don't leak out unref'd fb's */
+	if (obj && (obj->type == DRM_MODE_OBJECT_FB))
 		obj = NULL;
 	mutex_unlock(&dev->mode_config.idr_mutex);
 
@@ -444,9 +478,6 @@ struct drm_mode_object *drm_mode_object_
 	 * function.*/
 	WARN_ON(type == DRM_MODE_OBJECT_FB);
 	obj = _object_find(dev, id, type);
-	/* don't leak out unref'd fb's */
-	if (obj && (obj->type == DRM_MODE_OBJECT_FB))
-		obj = NULL;
 	return obj;
 }
 EXPORT_SYMBOL(drm_mode_object_find);
@@ -723,7 +754,7 @@ DEFINE_WW_CLASS(crtc_ww_class);
  */
 int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
 			      struct drm_plane *primary,
-			      void *cursor,
+			      struct drm_plane *cursor,
 			      const struct drm_crtc_funcs *funcs)
 {
 	struct drm_mode_config *config = &dev->mode_config;
@@ -748,8 +779,11 @@ int drm_crtc_init_with_planes(struct drm
 	config->num_crtc++;
 
 	crtc->primary = primary;
+	crtc->cursor = cursor;
 	if (primary)
 		primary->possible_crtcs = 1 << drm_crtc_index(crtc);
+	if (cursor)
+		cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
 
  out:
 	drm_modeset_unlock_all(dev);
@@ -842,7 +876,7 @@ int drm_connector_init(struct drm_device
 
 	drm_modeset_lock_all(dev);
 
-	ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
+	ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false);
 	if (ret)
 		goto out_unlock;
 
@@ -881,6 +915,8 @@ int drm_connector_init(struct drm_device
 	drm_object_attach_property(&connector->base,
 				      dev->mode_config.dpms_property, 0);
 
+	connector->debugfs_entry = NULL;
+
 out_put:
 	if (ret)
 		drm_mode_object_put(dev, &connector->base);
@@ -921,6 +957,49 @@ void drm_connector_cleanup(struct drm_co
 EXPORT_SYMBOL(drm_connector_cleanup);
 
 /**
+ * drm_connector_register - register a connector
+ * @connector: the connector to register
+ *
+ * Register userspace interfaces for a connector
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_register(struct drm_connector *connector)
+{
+	int ret;
+
+	drm_mode_object_register(connector->dev, &connector->base);
+
+	ret = drm_sysfs_connector_add(connector);
+	if (ret)
+		return ret;
+
+	ret = drm_debugfs_connector_add(connector);
+	if (ret) {
+		drm_sysfs_connector_remove(connector);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_connector_register);
+
+/**
+ * drm_connector_unregister - unregister a connector
+ * @connector: the connector to unregister
+ *
+ * Unregister userspace interfaces for a connector
+ */
+void drm_connector_unregister(struct drm_connector *connector)
+{
+	drm_sysfs_connector_remove(connector);
+	drm_debugfs_connector_remove(connector);
+}
+EXPORT_SYMBOL(drm_connector_unregister);
+
+
+/**
  * drm_connector_unplug_all - unregister connector userspace interfaces
  * @dev: drm device
  *
@@ -934,7 +1013,7 @@ void drm_connector_unplug_all(struct drm
 
 	/* taking the mode config mutex ends up in a clash with sysfs */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		drm_sysfs_connector_remove(connector);
+		drm_connector_unregister(connector);
 
 }
 EXPORT_SYMBOL(drm_connector_unplug_all);
@@ -1214,6 +1293,7 @@ static int drm_mode_create_standard_conn
 {
 	struct drm_property *edid;
 	struct drm_property *dpms;
+	struct drm_property *dev_path;
 
 	/*
 	 * Standard properties (apply to all connectors)
@@ -1228,6 +1308,12 @@ static int drm_mode_create_standard_conn
 				   ARRAY_SIZE(drm_dpms_enum_list));
 	dev->mode_config.dpms_property = dpms;
 
+	dev_path = drm_property_create(dev,
+				       DRM_MODE_PROP_BLOB |
+				       DRM_MODE_PROP_IMMUTABLE,
+				       "PATH", 0);
+	dev->mode_config.path_property = dev_path;
+
 	return 0;
 }
 
@@ -1384,6 +1470,33 @@ int drm_mode_create_scaling_mode_propert
 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
 
 /**
+ * drm_mode_create_aspect_ratio_property - create aspect ratio property
+ * @dev: DRM device
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * connectors.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
+{
+	if (dev->mode_config.aspect_ratio_property)
+		return 0;
+
+	dev->mode_config.aspect_ratio_property =
+		drm_property_create_enum(dev, 0, "aspect ratio",
+				drm_aspect_ratio_enum_list,
+				ARRAY_SIZE(drm_aspect_ratio_enum_list));
+
+	if (dev->mode_config.aspect_ratio_property == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
+
+/**
  * drm_mode_create_dirty_property - create dirty property
  * @dev: DRM device
  *
@@ -1470,6 +1583,15 @@ int drm_mode_group_init_legacy_group(str
 }
 EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
 
+void drm_reinit_primary_mode_group(struct drm_device *dev)
+{
+	drm_modeset_lock_all(dev);
+	drm_mode_group_destroy(&dev->primary->mode_group);
+	drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
+	drm_modeset_unlock_all(dev);
+}
+EXPORT_SYMBOL(drm_reinit_primary_mode_group);
+
 /**
  * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
  * @out: drm_mode_modeinfo struct to return to the user
@@ -2118,45 +2240,32 @@ out:
 	return ret;
 }
 
-/**
- * drm_mode_setplane - configure a plane's configuration
- * @dev: DRM device
- * @data: ioctl data*
- * @file_priv: DRM file info
+/*
+ * setplane_internal - setplane handler for internal callers
  *
- * Set plane configuration, including placement, fb, scaling, and other factors.
- * Or pass a NULL fb to disable.
+ * Note that we assume an extra reference has already been taken on fb.  If the
+ * update fails, this reference will be dropped before return; if it succeeds,
+ * the previous framebuffer (if any) will be unreferenced instead.
  *
- * Returns:
- * Zero on success, errno on failure.
+ * src_{x,y,w,h} are provided in 16.16 fixed point format
  */
-int drm_mode_setplane(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
+static int setplane_internal(struct drm_plane *plane,
+			     struct drm_crtc *crtc,
+			     struct drm_framebuffer *fb,
+			     int32_t crtc_x, int32_t crtc_y,
+			     uint32_t crtc_w, uint32_t crtc_h,
+			     /* src_{x,y,w,h} values are 16.16 fixed point */
+			     uint32_t src_x, uint32_t src_y,
+			     uint32_t src_w, uint32_t src_h)
 {
-	struct drm_mode_set_plane *plane_req = data;
-	struct drm_plane *plane;
-	struct drm_crtc *crtc;
-	struct drm_framebuffer *fb = NULL, *old_fb = NULL;
+	struct drm_device *dev = plane->dev;
+	struct drm_framebuffer *old_fb = NULL;
 	int ret = 0;
 	unsigned int fb_width, fb_height;
 	int i;
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	/*
-	 * First, find the plane, crtc, and fb objects.  If not available,
-	 * we don't bother to call the driver.
-	 */
-	plane = drm_plane_find(dev, plane_req->plane_id);
-	if (!plane) {
-		DRM_DEBUG_KMS("Unknown plane ID %d\n",
-			      plane_req->plane_id);
-		return -ENOENT;
-	}
-
 	/* No fb means shut it down */
-	if (!plane_req->fb_id) {
+	if (!fb) {
 		drm_modeset_lock_all(dev);
 		old_fb = plane->fb;
 		ret = plane->funcs->disable_plane(plane);
@@ -2170,14 +2279,6 @@ int drm_mode_setplane(struct drm_device
 		goto out;
 	}
 
-	crtc = drm_crtc_find(dev, plane_req->crtc_id);
-	if (!crtc) {
-		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
-			      plane_req->crtc_id);
-		ret = -ENOENT;
-		goto out;
-	}
-
 	/* Check whether this plane is usable on this CRTC */
 	if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
 		DRM_DEBUG_KMS("Invalid crtc for plane\n");
@@ -2185,14 +2286,6 @@ int drm_mode_setplane(struct drm_device
 		goto out;
 	}
 
-	fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
-	if (!fb) {
-		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
-			      plane_req->fb_id);
-		ret = -ENOENT;
-		goto out;
-	}
-
 	/* Check whether this plane supports the fb pixel format. */
 	for (i = 0; i < plane->format_count; i++)
 		if (fb->pixel_format == plane->format_types[i])
@@ -2208,43 +2301,25 @@ int drm_mode_setplane(struct drm_device
 	fb_height = fb->height << 16;
 
 	/* Make sure source coordinates are inside the fb. */
-	if (plane_req->src_w > fb_width ||
-	    plane_req->src_x > fb_width - plane_req->src_w ||
-	    plane_req->src_h > fb_height ||
-	    plane_req->src_y > fb_height - plane_req->src_h) {
+	if (src_w > fb_width ||
+	    src_x > fb_width - src_w ||
+	    src_h > fb_height ||
+	    src_y > fb_height - src_h) {
 		DRM_DEBUG_KMS("Invalid source coordinates "
 			      "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
-			      plane_req->src_w >> 16,
-			      ((plane_req->src_w & 0xffff) * 15625) >> 10,
-			      plane_req->src_h >> 16,
-			      ((plane_req->src_h & 0xffff) * 15625) >> 10,
-			      plane_req->src_x >> 16,
-			      ((plane_req->src_x & 0xffff) * 15625) >> 10,
-			      plane_req->src_y >> 16,
-			      ((plane_req->src_y & 0xffff) * 15625) >> 10);
+			      src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
+			      src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
+			      src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
+			      src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
 		ret = -ENOSPC;
 		goto out;
 	}
 
-	/* Give drivers some help against integer overflows */
-	if (plane_req->crtc_w > INT_MAX ||
-	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
-	    plane_req->crtc_h > INT_MAX ||
-	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
-		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
-			      plane_req->crtc_w, plane_req->crtc_h,
-			      plane_req->crtc_x, plane_req->crtc_y);
-		ret = -ERANGE;
-		goto out;
-	}
-
 	drm_modeset_lock_all(dev);
 	old_fb = plane->fb;
 	ret = plane->funcs->update_plane(plane, crtc, fb,
-					 plane_req->crtc_x, plane_req->crtc_y,
-					 plane_req->crtc_w, plane_req->crtc_h,
-					 plane_req->src_x, plane_req->src_y,
-					 plane_req->src_w, plane_req->src_h);
+					 crtc_x, crtc_y, crtc_w, crtc_h,
+					 src_x, src_y, src_w, src_h);
 	if (!ret) {
 		plane->crtc = crtc;
 		plane->fb = fb;
@@ -2261,6 +2336,85 @@ out:
 		drm_framebuffer_unreference(old_fb);
 
 	return ret;
+
+}
+
+/**
+ * drm_mode_setplane - configure a plane's configuration
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_priv: DRM file info
+ *
+ * Set plane configuration, including placement, fb, scaling, and other factors.
+ * Or pass a NULL fb to disable (planes may be disabled without providing a
+ * valid crtc).
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_setplane(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_mode_set_plane *plane_req = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc = NULL;
+	struct drm_framebuffer *fb = NULL;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	/* Give drivers some help against integer overflows */
+	if (plane_req->crtc_w > INT_MAX ||
+	    plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
+	    plane_req->crtc_h > INT_MAX ||
+	    plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
+		DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
+			      plane_req->crtc_w, plane_req->crtc_h,
+			      plane_req->crtc_x, plane_req->crtc_y);
+		return -ERANGE;
+	}
+
+	/*
+	 * First, find the plane, crtc, and fb objects.  If not available,
+	 * we don't bother to call the driver.
+	 */
+	obj = drm_mode_object_find(dev, plane_req->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown plane ID %d\n",
+			      plane_req->plane_id);
+		return -ENOENT;
+	}
+	plane = obj_to_plane(obj);
+
+	if (plane_req->fb_id) {
+		fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
+		if (!fb) {
+			DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+				      plane_req->fb_id);
+			return -ENOENT;
+		}
+
+		obj = drm_mode_object_find(dev, plane_req->crtc_id,
+					   DRM_MODE_OBJECT_CRTC);
+		if (!obj) {
+			DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+				      plane_req->crtc_id);
+			return -ENOENT;
+		}
+		crtc = obj_to_crtc(obj);
+	}
+
+	/*
+	 * setplane_internal will take care of deref'ing either the old or new
+	 * framebuffer depending on success.
+	 */
+	return setplane_internal(plane, crtc, fb,
+				 plane_req->crtc_x, plane_req->crtc_y,
+				 plane_req->crtc_w, plane_req->crtc_h,
+				 plane_req->src_x, plane_req->src_y,
+				 plane_req->src_w, plane_req->src_h);
 }
 
 /**
@@ -2509,6 +2663,102 @@ out:
 	return ret;
 }
 
+/**
+ * drm_mode_cursor_universal - translate legacy cursor ioctl call into a
+ *     universal plane handler call
+ * @crtc: crtc to update cursor for
+ * @req: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Legacy cursor ioctl's work directly with driver buffer handles.  To
+ * translate legacy ioctl calls into universal plane handler calls, we need to
+ * wrap the native buffer handle in a drm_framebuffer.
+ *
+ * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB
+ * buffer with a pitch of 4*width; the universal plane interface should be used
+ * directly in cases where the hardware can support other buffer settings and
+ * userspace wants to make use of these capabilities.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+static int drm_mode_cursor_universal(struct drm_crtc *crtc,
+				     struct drm_mode_cursor2 *req,
+				     struct drm_file *file_priv)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_framebuffer *fb = NULL;
+	struct drm_mode_fb_cmd2 fbreq = {
+		.width = req->width,
+		.height = req->height,
+		.pixel_format = DRM_FORMAT_ARGB8888,
+		.pitches = { req->width * 4 },
+		.handles = { req->handle },
+	};
+	int32_t crtc_x, crtc_y;
+	uint32_t crtc_w = 0, crtc_h = 0;
+	uint32_t src_w = 0, src_h = 0;
+	int ret = 0;
+
+	BUG_ON(!crtc->cursor);
+
+	/*
+	 * Obtain fb we'll be using (either new or existing) and take an extra
+	 * reference to it if fb != null.  setplane will take care of dropping
+	 * the reference if the plane update fails.
+	 */
+	if (req->flags & DRM_MODE_CURSOR_BO) {
+		if (req->handle) {
+			fb = add_framebuffer_internal(dev, &fbreq, file_priv);
+			if (IS_ERR(fb)) {
+				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
+				return PTR_ERR(fb);
+			}
+
+			drm_framebuffer_reference(fb);
+		} else {
+			fb = NULL;
+		}
+	} else {
+		mutex_lock(&dev->mode_config.mutex);
+		fb = crtc->cursor->fb;
+		if (fb)
+			drm_framebuffer_reference(fb);
+		mutex_unlock(&dev->mode_config.mutex);
+	}
+
+	if (req->flags & DRM_MODE_CURSOR_MOVE) {
+		crtc_x = req->x;
+		crtc_y = req->y;
+	} else {
+		crtc_x = crtc->cursor_x;
+		crtc_y = crtc->cursor_y;
+	}
+
+	if (fb) {
+		crtc_w = fb->width;
+		crtc_h = fb->height;
+		src_w = fb->width << 16;
+		src_h = fb->height << 16;
+	}
+
+	/*
+	 * setplane_internal will take care of deref'ing either the old or new
+	 * framebuffer depending on success.
+	 */
+	ret = setplane_internal(crtc->cursor, crtc, fb,
+				crtc_x, crtc_y, crtc_w, crtc_h,
+				0, 0, src_w, src_h);
+
+	/* Update successful; save new cursor position, if necessary */
+	if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
+		crtc->cursor_x = req->x;
+		crtc->cursor_y = req->y;
+	}
+
+	return ret;
+}
+
 static int drm_mode_cursor_common(struct drm_device *dev,
 				  struct drm_mode_cursor2 *req,
 				  struct drm_file *file_priv)
@@ -2528,6 +2778,13 @@ static int drm_mode_cursor_common(struct
 		return -ENOENT;
 	}
 
+	/*
+	 * If this crtc has a universal cursor plane, call that plane's update
+	 * handler rather than using legacy cursor handlers.
+	 */
+	if (crtc->cursor)
+		return drm_mode_cursor_universal(crtc, req, file_priv);
+
 	drm_modeset_lock(&crtc->mutex, NULL);
 	if (req->flags & DRM_MODE_CURSOR_BO) {
 		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
@@ -2827,56 +3084,38 @@ static int framebuffer_check(const struc
 	return 0;
 }
 
-/**
- * drm_mode_addfb2 - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request with format. This is
- * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
- * and uses fourcc codes as pixel format specifiers.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, errno on failure.
- */
-int drm_mode_addfb2(struct drm_device *dev,
-		    void *data, struct drm_file *file_priv)
+static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
+							struct drm_mode_fb_cmd2 *r,
+							struct drm_file *file_priv)
 {
-	struct drm_mode_fb_cmd2 *r = data;
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_framebuffer *fb;
 	int ret;
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
 	if (r->flags & ~DRM_MODE_FB_INTERLACED) {
 		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
 		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
 			  r->width, config->min_width, config->max_width);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 	if ((config->min_height > r->height) || (r->height > config->max_height)) {
 		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
 			  r->height, config->min_height, config->max_height);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	ret = framebuffer_check(r);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
 
 	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
 	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("could not create framebuffer\n");
-		return PTR_ERR(fb);
+		return fb;
 	}
 
 	mutex_lock(&file_priv->fbs_lock);
@@ -2885,8 +3124,37 @@ int drm_mode_addfb2(struct drm_device *d
 	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
 	mutex_unlock(&file_priv->fbs_lock);
 
+	return fb;
+}
 
-	return ret;
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request with format. This is
+ * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
+ * and uses fourcc codes as pixel format specifiers.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv)
+{
+	struct drm_framebuffer *fb;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = add_framebuffer_internal(dev, data, file_priv);
+	if (IS_ERR(fb))
+		return PTR_ERR(fb);
+
+	return 0;
 }
 
 /**
@@ -3176,7 +3444,7 @@ fail:
 EXPORT_SYMBOL(drm_property_create);
 
 /**
- * drm_property_create - create a new enumeration property type
+ * drm_property_create_enum - create a new enumeration property type
  * @dev: drm device
  * @flags: flags specifying the property type
  * @name: name of the property
@@ -3222,7 +3490,7 @@ struct drm_property *drm_property_create
 EXPORT_SYMBOL(drm_property_create_enum);
 
 /**
- * drm_property_create - create a new bitmask property type
+ * drm_property_create_bitmask - create a new bitmask property type
  * @dev: drm device
  * @flags: flags specifying the property type
  * @name: name of the property
@@ -3242,19 +3510,28 @@ EXPORT_SYMBOL(drm_property_create_enum);
 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
 					 int flags, const char *name,
 					 const struct drm_prop_enum_list *props,
-					 int num_values)
+					 int num_props,
+					 uint64_t supported_bits)
 {
 	struct drm_property *property;
-	int i, ret;
+	int i, ret, index = 0;
+	int num_values = hweight64(supported_bits);
 
 	flags |= DRM_MODE_PROP_BITMASK;
 
 	property = drm_property_create(dev, flags, name, num_values);
 	if (!property)
 		return NULL;
+	for (i = 0; i < num_props; i++) {
+		if (!(supported_bits & (1ULL << props[i].type)))
+			continue;
 
-	for (i = 0; i < num_values; i++) {
-		ret = drm_property_add_enum(property, i,
+		if (WARN_ON(index >= num_values)) {
+			drm_property_destroy(dev, property);
+			return NULL;
+		}
+
+		ret = drm_property_add_enum(property, index++,
 				      props[i].type,
 				      props[i].name);
 		if (ret) {
@@ -3284,7 +3561,7 @@ static struct drm_property *property_cre
 }
 
 /**
- * drm_property_create - create a new ranged property type
+ * drm_property_create_range - create a new ranged property type
  * @dev: drm device
  * @flags: flags specifying the property type
  * @name: name of the property
@@ -3703,6 +3980,25 @@ done:
 	return ret;
 }
 
+int drm_mode_connector_set_path_property(struct drm_connector *connector,
+					 char *path)
+{
+	struct drm_device *dev = connector->dev;
+	int ret, size;
+	size = strlen(path) + 1;
+
+	connector->path_blob_ptr = drm_property_create_blob(connector->dev,
+							    size, path);
+	if (!connector->path_blob_ptr)
+		return -EINVAL;
+
+	ret = drm_object_property_set_value(&connector->base,
+					    dev->mode_config.path_property,
+					    connector->path_blob_ptr->base.id);
+	return ret;
+}
+EXPORT_SYMBOL(drm_mode_connector_set_path_property);
+
 /**
  * drm_mode_connector_update_edid_property - update the edid property of a connector
  * @connector: drm connector
@@ -3720,6 +4016,10 @@ int drm_mode_connector_update_edid_prope
 	struct drm_device *dev = connector->dev;
 	int ret, size;
 
+	/* ignore requests to set edid when overridden */
+	if (connector->override_edid)
+		return 0;
+
 	if (connector->edid_blob_ptr)
 		drm_property_destroy_blob(dev, connector->edid_blob_ptr);
 
@@ -4396,8 +4696,9 @@ int drm_mode_create_dumb_ioctl(struct dr
 		return -EINVAL;
 
 	/* overflow checks for 32bit size calculations */
+	/* NOTE: DIV_ROUND_UP() can overflow */
 	cpp = DIV_ROUND_UP(args->bpp, 8);
-	if (cpp > 0xffffffffU / args->width)
+	if (!cpp || cpp > 0xffffffffU / args->width)
 		return -EINVAL;
 	stride = cpp * args->width;
 	if (args->height > 0xffffffffU / stride)
@@ -4680,6 +4981,36 @@ int drm_format_vert_chroma_subsampling(u
 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
 
 /**
+ * drm_rotation_simplify() - Try to simplify the rotation
+ * @rotation: Rotation to be simplified
+ * @supported_rotations: Supported rotations
+ *
+ * Attempt to simplify the rotation to a form that is supported.
+ * Eg. if the hardware supports everything except DRM_REFLECT_X
+ * one could call this function like this:
+ *
+ * drm_rotation_simplify(rotation, BIT(DRM_ROTATE_0) |
+ *                       BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) |
+ *                       BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_Y));
+ *
+ * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
+ * transforms the hardware supports, this function may not
+ * be able to produce a supported transform, so the caller should
+ * check the result afterwards.
+ */
+unsigned int drm_rotation_simplify(unsigned int rotation,
+				   unsigned int supported_rotations)
+{
+	if (rotation & ~supported_rotations) {
+		rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y);
+		rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4);
+	}
+
+	return rotation;
+}
+EXPORT_SYMBOL(drm_rotation_simplify);
+
+/**
  * drm_mode_config_init - initialize DRM mode_configuration structure
  * @dev: DRM device
  *
@@ -4797,3 +5128,21 @@ void drm_mode_config_cleanup(struct drm_
 	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
+
+struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
+						       unsigned int supported_rotations)
+{
+	static const struct drm_prop_enum_list props[] = {
+		{ DRM_ROTATE_0,   "rotate-0" },
+		{ DRM_ROTATE_90,  "rotate-90" },
+		{ DRM_ROTATE_180, "rotate-180" },
+		{ DRM_ROTATE_270, "rotate-270" },
+		{ DRM_REFLECT_X,  "reflect-x" },
+		{ DRM_REFLECT_Y,  "reflect-y" },
+	};
+
+	return drm_property_create_bitmask(dev, 0, "rotation",
+					   props, ARRAY_SIZE(props),
+					   supported_rotations);
+}
+EXPORT_SYMBOL(drm_mode_create_rotation_property);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_crtc_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_crtc_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_crtc_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -818,6 +818,7 @@ void drm_helper_mode_fill_fb_struct(stru
 	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
 				    &fb->bits_per_pixel);
 	fb->pixel_format = mode_cmd->pixel_format;
+	fb->flags = mode_cmd->flags;
 }
 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_debugfs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_debugfs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <drm/drmP.h>
+#include <drm/drm_edid.h>
 
 #if defined(CONFIG_DEBUG_FS)
 
@@ -237,5 +238,186 @@ int drm_debugfs_cleanup(struct drm_minor
 	return 0;
 }
 
+static int connector_show(struct seq_file *m, void *data)
+{
+	struct drm_connector *connector = m->private;
+	const char *status;
+
+	switch (connector->force) {
+	case DRM_FORCE_ON:
+		status = "on\n";
+		break;
+
+	case DRM_FORCE_ON_DIGITAL:
+		status = "digital\n";
+		break;
+
+	case DRM_FORCE_OFF:
+		status = "off\n";
+		break;
+
+	case DRM_FORCE_UNSPECIFIED:
+		status = "unspecified\n";
+		break;
+
+	default:
+		return 0;
+	}
+
+	seq_puts(m, status);
+
+	return 0;
+}
+
+static int connector_open(struct inode *inode, struct file *file)
+{
+	struct drm_connector *dev = inode->i_private;
+
+	return single_open(file, connector_show, dev);
+}
+
+static ssize_t connector_write(struct file *file, const char __user *ubuf,
+			       size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_connector *connector = m->private;
+	char buf[12];
+
+	if (len > sizeof(buf) - 1)
+		return -EINVAL;
+
+	if (copy_from_user(buf, ubuf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	if (!strcmp(buf, "on"))
+		connector->force = DRM_FORCE_ON;
+	else if (!strcmp(buf, "digital"))
+		connector->force = DRM_FORCE_ON_DIGITAL;
+	else if (!strcmp(buf, "off"))
+		connector->force = DRM_FORCE_OFF;
+	else if (!strcmp(buf, "unspecified"))
+		connector->force = DRM_FORCE_UNSPECIFIED;
+	else
+		return -EINVAL;
+
+	return len;
+}
+
+static int edid_show(struct seq_file *m, void *data)
+{
+	struct drm_connector *connector = m->private;
+	struct drm_property_blob *edid = connector->edid_blob_ptr;
+
+	if (connector->override_edid && edid)
+		seq_write(m, edid->data, edid->length);
+
+	return 0;
+}
+
+static int edid_open(struct inode *inode, struct file *file)
+{
+	struct drm_connector *dev = inode->i_private;
+
+	return single_open(file, edid_show, dev);
+}
+
+static ssize_t edid_write(struct file *file, const char __user *ubuf,
+			  size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_connector *connector = m->private;
+	char *buf;
+	struct edid *edid;
+	int ret;
+
+	buf = memdup_user(ubuf, len);
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
+
+	edid = (struct edid *) buf;
+
+	if (len == 5 && !strncmp(buf, "reset", 5)) {
+		connector->override_edid = false;
+		ret = drm_mode_connector_update_edid_property(connector, NULL);
+	} else if (len < EDID_LENGTH ||
+		   EDID_LENGTH * (1 + edid->extensions) > len)
+		ret = -EINVAL;
+	else {
+		connector->override_edid = false;
+		ret = drm_mode_connector_update_edid_property(connector, edid);
+		if (!ret)
+			connector->override_edid = true;
+	}
+
+	kfree(buf);
+
+	return (ret) ? ret : len;
+}
+
+static const struct file_operations drm_edid_fops = {
+	.owner = THIS_MODULE,
+	.open = edid_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = edid_write
+};
+
+
+static const struct file_operations drm_connector_fops = {
+	.owner = THIS_MODULE,
+	.open = connector_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = connector_write
+};
+
+int drm_debugfs_connector_add(struct drm_connector *connector)
+{
+	struct drm_minor *minor = connector->dev->primary;
+	struct dentry *root, *ent;
+
+	if (!minor->debugfs_root)
+		return -1;
+
+	root = debugfs_create_dir(connector->name, minor->debugfs_root);
+	if (!root)
+		return -ENOMEM;
+
+	connector->debugfs_entry = root;
+
+	/* force */
+	ent = debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
+				  &drm_connector_fops);
+	if (!ent)
+		goto error;
+
+	/* edid */
+	ent = debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root,
+				  connector, &drm_edid_fops);
+	if (!ent)
+		goto error;
+
+	return 0;
+
+error:
+	debugfs_remove_recursive(connector->debugfs_entry);
+	connector->debugfs_entry = NULL;
+	return -ENOMEM;
+}
+
+void drm_debugfs_connector_remove(struct drm_connector *connector)
+{
+	if (!connector->debugfs_entry)
+		return;
+
+	debugfs_remove_recursive(connector->debugfs_entry);
+
+	connector->debugfs_entry = NULL;
+}
+
 #endif /* CONFIG_DEBUG_FS */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_dp_mst_topology.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2715 @@
+/*
+ * Copyright Â© 2014 Red Hat
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/i2c.h>
+#include <drm/drm_dp_mst_helper.h>
+#include <drm/drmP.h>
+
+#include <drm/drm_fixed.h>
+
+/**
+ * DOC: dp mst helper
+ *
+ * These functions contain parts of the DisplayPort 1.2a MultiStream Transport
+ * protocol. The helpers contain a topology manager and bandwidth manager.
+ * The helpers encapsulate the sending and received of sideband msgs.
+ */
+static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
+				  char *buf);
+static int test_calc_pbn_mode(void);
+
+static void drm_dp_put_port(struct drm_dp_mst_port *port);
+
+static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
+				     int id,
+				     struct drm_dp_payload *payload);
+
+static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+				  struct drm_dp_mst_port *port,
+				  int offset, int size, u8 *bytes);
+
+static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+				    struct drm_dp_mst_branch *mstb);
+static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
+					   struct drm_dp_mst_branch *mstb,
+					   struct drm_dp_mst_port *port);
+static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
+				 u8 *guid);
+
+static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
+static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
+static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
+/* sideband msg handling */
+static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t num_nibbles)
+{
+	u8 bitmask = 0x80;
+	u8 bitshift = 7;
+	u8 array_index = 0;
+	int number_of_bits = num_nibbles * 4;
+	u8 remainder = 0;
+
+	while (number_of_bits != 0) {
+		number_of_bits--;
+		remainder <<= 1;
+		remainder |= (data[array_index] & bitmask) >> bitshift;
+		bitmask >>= 1;
+		bitshift--;
+		if (bitmask == 0) {
+			bitmask = 0x80;
+			bitshift = 7;
+			array_index++;
+		}
+		if ((remainder & 0x10) == 0x10)
+			remainder ^= 0x13;
+	}
+
+	number_of_bits = 4;
+	while (number_of_bits != 0) {
+		number_of_bits--;
+		remainder <<= 1;
+		if ((remainder & 0x10) != 0)
+			remainder ^= 0x13;
+	}
+
+	return remainder;
+}
+
+static u8 drm_dp_msg_data_crc4(const uint8_t *data, u8 number_of_bytes)
+{
+	u8 bitmask = 0x80;
+	u8 bitshift = 7;
+	u8 array_index = 0;
+	int number_of_bits = number_of_bytes * 8;
+	u16 remainder = 0;
+
+	while (number_of_bits != 0) {
+		number_of_bits--;
+		remainder <<= 1;
+		remainder |= (data[array_index] & bitmask) >> bitshift;
+		bitmask >>= 1;
+		bitshift--;
+		if (bitmask == 0) {
+			bitmask = 0x80;
+			bitshift = 7;
+			array_index++;
+		}
+		if ((remainder & 0x100) == 0x100)
+			remainder ^= 0xd5;
+	}
+
+	number_of_bits = 8;
+	while (number_of_bits != 0) {
+		number_of_bits--;
+		remainder <<= 1;
+		if ((remainder & 0x100) != 0)
+			remainder ^= 0xd5;
+	}
+
+	return remainder & 0xff;
+}
+static inline u8 drm_dp_calc_sb_hdr_size(struct drm_dp_sideband_msg_hdr *hdr)
+{
+	u8 size = 3;
+	size += (hdr->lct / 2);
+	return size;
+}
+
+static void drm_dp_encode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
+					   u8 *buf, int *len)
+{
+	int idx = 0;
+	int i;
+	u8 crc4;
+	buf[idx++] = ((hdr->lct & 0xf) << 4) | (hdr->lcr & 0xf);
+	for (i = 0; i < (hdr->lct / 2); i++)
+		buf[idx++] = hdr->rad[i];
+	buf[idx++] = (hdr->broadcast << 7) | (hdr->path_msg << 6) |
+		(hdr->msg_len & 0x3f);
+	buf[idx++] = (hdr->somt << 7) | (hdr->eomt << 6) | (hdr->seqno << 4);
+
+	crc4 = drm_dp_msg_header_crc4(buf, (idx * 2) - 1);
+	buf[idx - 1] |= (crc4 & 0xf);
+
+	*len = idx;
+}
+
+static bool drm_dp_decode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
+					   u8 *buf, int buflen, u8 *hdrlen)
+{
+	u8 crc4;
+	u8 len;
+	int i;
+	u8 idx;
+	if (buf[0] == 0)
+		return false;
+	len = 3;
+	len += ((buf[0] & 0xf0) >> 4) / 2;
+	if (len > buflen)
+		return false;
+	crc4 = drm_dp_msg_header_crc4(buf, (len * 2) - 1);
+
+	if ((crc4 & 0xf) != (buf[len - 1] & 0xf)) {
+		DRM_DEBUG_KMS("crc4 mismatch 0x%x 0x%x\n", crc4, buf[len - 1]);
+		return false;
+	}
+
+	hdr->lct = (buf[0] & 0xf0) >> 4;
+	hdr->lcr = (buf[0] & 0xf);
+	idx = 1;
+	for (i = 0; i < (hdr->lct / 2); i++)
+		hdr->rad[i] = buf[idx++];
+	hdr->broadcast = (buf[idx] >> 7) & 0x1;
+	hdr->path_msg = (buf[idx] >> 6) & 0x1;
+	hdr->msg_len = buf[idx] & 0x3f;
+	idx++;
+	hdr->somt = (buf[idx] >> 7) & 0x1;
+	hdr->eomt = (buf[idx] >> 6) & 0x1;
+	hdr->seqno = (buf[idx] >> 4) & 0x1;
+	idx++;
+	*hdrlen = idx;
+	return true;
+}
+
+static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req,
+				       struct drm_dp_sideband_msg_tx *raw)
+{
+	int idx = 0;
+	int i;
+	u8 *buf = raw->msg;
+	buf[idx++] = req->req_type & 0x7f;
+
+	switch (req->req_type) {
+	case DP_ENUM_PATH_RESOURCES:
+		buf[idx] = (req->u.port_num.port_number & 0xf) << 4;
+		idx++;
+		break;
+	case DP_ALLOCATE_PAYLOAD:
+		buf[idx] = (req->u.allocate_payload.port_number & 0xf) << 4 |
+			(req->u.allocate_payload.number_sdp_streams & 0xf);
+		idx++;
+		buf[idx] = (req->u.allocate_payload.vcpi & 0x7f);
+		idx++;
+		buf[idx] = (req->u.allocate_payload.pbn >> 8);
+		idx++;
+		buf[idx] = (req->u.allocate_payload.pbn & 0xff);
+		idx++;
+		for (i = 0; i < req->u.allocate_payload.number_sdp_streams / 2; i++) {
+			buf[idx] = ((req->u.allocate_payload.sdp_stream_sink[i * 2] & 0xf) << 4) |
+				(req->u.allocate_payload.sdp_stream_sink[i * 2 + 1] & 0xf);
+			idx++;
+		}
+		if (req->u.allocate_payload.number_sdp_streams & 1) {
+			i = req->u.allocate_payload.number_sdp_streams - 1;
+			buf[idx] = (req->u.allocate_payload.sdp_stream_sink[i] & 0xf) << 4;
+			idx++;
+		}
+		break;
+	case DP_QUERY_PAYLOAD:
+		buf[idx] = (req->u.query_payload.port_number & 0xf) << 4;
+		idx++;
+		buf[idx] = (req->u.query_payload.vcpi & 0x7f);
+		idx++;
+		break;
+	case DP_REMOTE_DPCD_READ:
+		buf[idx] = (req->u.dpcd_read.port_number & 0xf) << 4;
+		buf[idx] |= ((req->u.dpcd_read.dpcd_address & 0xf0000) >> 16) & 0xf;
+		idx++;
+		buf[idx] = (req->u.dpcd_read.dpcd_address & 0xff00) >> 8;
+		idx++;
+		buf[idx] = (req->u.dpcd_read.dpcd_address & 0xff);
+		idx++;
+		buf[idx] = (req->u.dpcd_read.num_bytes);
+		idx++;
+		break;
+
+	case DP_REMOTE_DPCD_WRITE:
+		buf[idx] = (req->u.dpcd_write.port_number & 0xf) << 4;
+		buf[idx] |= ((req->u.dpcd_write.dpcd_address & 0xf0000) >> 16) & 0xf;
+		idx++;
+		buf[idx] = (req->u.dpcd_write.dpcd_address & 0xff00) >> 8;
+		idx++;
+		buf[idx] = (req->u.dpcd_write.dpcd_address & 0xff);
+		idx++;
+		buf[idx] = (req->u.dpcd_write.num_bytes);
+		idx++;
+		memcpy(&buf[idx], req->u.dpcd_write.bytes, req->u.dpcd_write.num_bytes);
+		idx += req->u.dpcd_write.num_bytes;
+		break;
+	case DP_REMOTE_I2C_READ:
+		buf[idx] = (req->u.i2c_read.port_number & 0xf) << 4;
+		buf[idx] |= (req->u.i2c_read.num_transactions & 0x3);
+		idx++;
+		for (i = 0; i < (req->u.i2c_read.num_transactions & 0x3); i++) {
+			buf[idx] = req->u.i2c_read.transactions[i].i2c_dev_id & 0x7f;
+			idx++;
+			buf[idx] = req->u.i2c_read.transactions[i].num_bytes;
+			idx++;
+			memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes);
+			idx += req->u.i2c_read.transactions[i].num_bytes;
+
+			buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5;
+			buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf);
+			idx++;
+		}
+		buf[idx] = (req->u.i2c_read.read_i2c_device_id) & 0x7f;
+		idx++;
+		buf[idx] = (req->u.i2c_read.num_bytes_read);
+		idx++;
+		break;
+
+	case DP_REMOTE_I2C_WRITE:
+		buf[idx] = (req->u.i2c_write.port_number & 0xf) << 4;
+		idx++;
+		buf[idx] = (req->u.i2c_write.write_i2c_device_id) & 0x7f;
+		idx++;
+		buf[idx] = (req->u.i2c_write.num_bytes);
+		idx++;
+		memcpy(&buf[idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes);
+		idx += req->u.i2c_write.num_bytes;
+		break;
+	}
+	raw->cur_len = idx;
+}
+
+static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len)
+{
+	u8 crc4;
+	crc4 = drm_dp_msg_data_crc4(msg, len);
+	msg[len] = crc4;
+}
+
+static void drm_dp_encode_sideband_reply(struct drm_dp_sideband_msg_reply_body *rep,
+					 struct drm_dp_sideband_msg_tx *raw)
+{
+	int idx = 0;
+	u8 *buf = raw->msg;
+
+	buf[idx++] = (rep->reply_type & 0x1) << 7 | (rep->req_type & 0x7f);
+
+	raw->cur_len = idx;
+}
+
+/* this adds a chunk of msg to the builder to get the final msg */
+static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
+				      u8 *replybuf, u8 replybuflen, bool hdr)
+{
+	int ret;
+	u8 crc4;
+
+	if (hdr) {
+		u8 hdrlen;
+		struct drm_dp_sideband_msg_hdr recv_hdr;
+		ret = drm_dp_decode_sideband_msg_hdr(&recv_hdr, replybuf, replybuflen, &hdrlen);
+		if (ret == false) {
+			print_hex_dump(KERN_DEBUG, "failed hdr", DUMP_PREFIX_NONE, 16, 1, replybuf, replybuflen, false);
+			return false;
+		}
+
+		/* get length contained in this portion */
+		msg->curchunk_len = recv_hdr.msg_len;
+		msg->curchunk_hdrlen = hdrlen;
+
+		/* we have already gotten an somt - don't bother parsing */
+		if (recv_hdr.somt && msg->have_somt)
+			return false;
+
+		if (recv_hdr.somt) {
+			memcpy(&msg->initial_hdr, &recv_hdr, sizeof(struct drm_dp_sideband_msg_hdr));
+			msg->have_somt = true;
+		}
+		if (recv_hdr.eomt)
+			msg->have_eomt = true;
+
+		/* copy the bytes for the remainder of this header chunk */
+		msg->curchunk_idx = min(msg->curchunk_len, (u8)(replybuflen - hdrlen));
+		memcpy(&msg->chunk[0], replybuf + hdrlen, msg->curchunk_idx);
+	} else {
+		memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen);
+		msg->curchunk_idx += replybuflen;
+	}
+
+	if (msg->curchunk_idx >= msg->curchunk_len) {
+		/* do CRC */
+		crc4 = drm_dp_msg_data_crc4(msg->chunk, msg->curchunk_len - 1);
+		/* copy chunk into bigger msg */
+		memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
+		msg->curlen += msg->curchunk_len - 1;
+	}
+	return true;
+}
+
+static bool drm_dp_sideband_parse_link_address(struct drm_dp_sideband_msg_rx *raw,
+					       struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	int i;
+	memcpy(repmsg->u.link_addr.guid, &raw->msg[idx], 16);
+	idx += 16;
+	repmsg->u.link_addr.nports = raw->msg[idx] & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	for (i = 0; i < repmsg->u.link_addr.nports; i++) {
+		if (raw->msg[idx] & 0x80)
+			repmsg->u.link_addr.ports[i].input_port = 1;
+
+		repmsg->u.link_addr.ports[i].peer_device_type = (raw->msg[idx] >> 4) & 0x7;
+		repmsg->u.link_addr.ports[i].port_number = (raw->msg[idx] & 0xf);
+
+		idx++;
+		if (idx > raw->curlen)
+			goto fail_len;
+		repmsg->u.link_addr.ports[i].mcs = (raw->msg[idx] >> 7) & 0x1;
+		repmsg->u.link_addr.ports[i].ddps = (raw->msg[idx] >> 6) & 0x1;
+		if (repmsg->u.link_addr.ports[i].input_port == 0)
+			repmsg->u.link_addr.ports[i].legacy_device_plug_status = (raw->msg[idx] >> 5) & 0x1;
+		idx++;
+		if (idx > raw->curlen)
+			goto fail_len;
+		if (repmsg->u.link_addr.ports[i].input_port == 0) {
+			repmsg->u.link_addr.ports[i].dpcd_revision = (raw->msg[idx]);
+			idx++;
+			if (idx > raw->curlen)
+				goto fail_len;
+			memcpy(repmsg->u.link_addr.ports[i].peer_guid, &raw->msg[idx], 16);
+			idx += 16;
+			if (idx > raw->curlen)
+				goto fail_len;
+			repmsg->u.link_addr.ports[i].num_sdp_streams = (raw->msg[idx] >> 4) & 0xf;
+			repmsg->u.link_addr.ports[i].num_sdp_stream_sinks = (raw->msg[idx] & 0xf);
+			idx++;
+
+		}
+		if (idx > raw->curlen)
+			goto fail_len;
+	}
+
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("link address reply parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_remote_dpcd_read(struct drm_dp_sideband_msg_rx *raw,
+						   struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	repmsg->u.remote_dpcd_read_ack.port_number = raw->msg[idx] & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx];
+	if (idx > raw->curlen)
+		goto fail_len;
+
+	memcpy(repmsg->u.remote_dpcd_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_dpcd_read_ack.num_bytes);
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("link address reply parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_remote_dpcd_write(struct drm_dp_sideband_msg_rx *raw,
+						      struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	repmsg->u.remote_dpcd_write_ack.port_number = raw->msg[idx] & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_remote_i2c_read_ack(struct drm_dp_sideband_msg_rx *raw,
+						      struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+
+	repmsg->u.remote_i2c_read_ack.port_number = (raw->msg[idx] & 0xf);
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.remote_i2c_read_ack.num_bytes = raw->msg[idx];
+	idx++;
+	/* TODO check */
+	memcpy(repmsg->u.remote_i2c_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_i2c_read_ack.num_bytes);
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("remote i2c reply parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband_msg_rx *raw,
+							  struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.path_resources.full_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+	idx += 2;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.path_resources.avail_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+	idx += 2;
+	if (idx > raw->curlen)
+		goto fail_len;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("enum resource parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_allocate_payload_ack(struct drm_dp_sideband_msg_rx *raw,
+							  struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	repmsg->u.allocate_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.allocate_payload.vcpi = raw->msg[idx];
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.allocate_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+	idx += 2;
+	if (idx > raw->curlen)
+		goto fail_len;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("allocate payload parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_rx *raw,
+						    struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+	int idx = 1;
+	repmsg->u.query_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+	repmsg->u.query_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
+	idx += 2;
+	if (idx > raw->curlen)
+		goto fail_len;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("query payload parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw,
+					struct drm_dp_sideband_msg_reply_body *msg)
+{
+	memset(msg, 0, sizeof(*msg));
+	msg->reply_type = (raw->msg[0] & 0x80) >> 7;
+	msg->req_type = (raw->msg[0] & 0x7f);
+
+	if (msg->reply_type) {
+		memcpy(msg->u.nak.guid, &raw->msg[1], 16);
+		msg->u.nak.reason = raw->msg[17];
+		msg->u.nak.nak_data = raw->msg[18];
+		return false;
+	}
+
+	switch (msg->req_type) {
+	case DP_LINK_ADDRESS:
+		return drm_dp_sideband_parse_link_address(raw, msg);
+	case DP_QUERY_PAYLOAD:
+		return drm_dp_sideband_parse_query_payload_ack(raw, msg);
+	case DP_REMOTE_DPCD_READ:
+		return drm_dp_sideband_parse_remote_dpcd_read(raw, msg);
+	case DP_REMOTE_DPCD_WRITE:
+		return drm_dp_sideband_parse_remote_dpcd_write(raw, msg);
+	case DP_REMOTE_I2C_READ:
+		return drm_dp_sideband_parse_remote_i2c_read_ack(raw, msg);
+	case DP_ENUM_PATH_RESOURCES:
+		return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg);
+	case DP_ALLOCATE_PAYLOAD:
+		return drm_dp_sideband_parse_allocate_payload_ack(raw, msg);
+	default:
+		DRM_ERROR("Got unknown reply 0x%02x\n", msg->req_type);
+		return false;
+	}
+}
+
+static bool drm_dp_sideband_parse_connection_status_notify(struct drm_dp_sideband_msg_rx *raw,
+							   struct drm_dp_sideband_msg_req_body *msg)
+{
+	int idx = 1;
+
+	msg->u.conn_stat.port_number = (raw->msg[idx] & 0xf0) >> 4;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+
+	memcpy(msg->u.conn_stat.guid, &raw->msg[idx], 16);
+	idx += 16;
+	if (idx > raw->curlen)
+		goto fail_len;
+
+	msg->u.conn_stat.legacy_device_plug_status = (raw->msg[idx] >> 6) & 0x1;
+	msg->u.conn_stat.displayport_device_plug_status = (raw->msg[idx] >> 5) & 0x1;
+	msg->u.conn_stat.message_capability_status = (raw->msg[idx] >> 4) & 0x1;
+	msg->u.conn_stat.input_port = (raw->msg[idx] >> 3) & 0x1;
+	msg->u.conn_stat.peer_device_type = (raw->msg[idx] & 0x7);
+	idx++;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("connection status reply parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_resource_status_notify(struct drm_dp_sideband_msg_rx *raw,
+							   struct drm_dp_sideband_msg_req_body *msg)
+{
+	int idx = 1;
+
+	msg->u.resource_stat.port_number = (raw->msg[idx] & 0xf0) >> 4;
+	idx++;
+	if (idx > raw->curlen)
+		goto fail_len;
+
+	memcpy(msg->u.resource_stat.guid, &raw->msg[idx], 16);
+	idx += 16;
+	if (idx > raw->curlen)
+		goto fail_len;
+
+	msg->u.resource_stat.available_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
+	idx++;
+	return true;
+fail_len:
+	DRM_DEBUG_KMS("resource status reply parse length fail %d %d\n", idx, raw->curlen);
+	return false;
+}
+
+static bool drm_dp_sideband_parse_req(struct drm_dp_sideband_msg_rx *raw,
+				      struct drm_dp_sideband_msg_req_body *msg)
+{
+	memset(msg, 0, sizeof(*msg));
+	msg->req_type = (raw->msg[0] & 0x7f);
+
+	switch (msg->req_type) {
+	case DP_CONNECTION_STATUS_NOTIFY:
+		return drm_dp_sideband_parse_connection_status_notify(raw, msg);
+	case DP_RESOURCE_STATUS_NOTIFY:
+		return drm_dp_sideband_parse_resource_status_notify(raw, msg);
+	default:
+		DRM_ERROR("Got unknown request 0x%02x\n", msg->req_type);
+		return false;
+	}
+}
+
+static int build_dpcd_write(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes, u8 *bytes)
+{
+	struct drm_dp_sideband_msg_req_body req;
+
+	req.req_type = DP_REMOTE_DPCD_WRITE;
+	req.u.dpcd_write.port_number = port_num;
+	req.u.dpcd_write.dpcd_address = offset;
+	req.u.dpcd_write.num_bytes = num_bytes;
+	req.u.dpcd_write.bytes = bytes;
+	drm_dp_encode_sideband_req(&req, msg);
+
+	return 0;
+}
+
+static int build_link_address(struct drm_dp_sideband_msg_tx *msg)
+{
+	struct drm_dp_sideband_msg_req_body req;
+
+	req.req_type = DP_LINK_ADDRESS;
+	drm_dp_encode_sideband_req(&req, msg);
+	return 0;
+}
+
+static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int port_num)
+{
+	struct drm_dp_sideband_msg_req_body req;
+
+	req.req_type = DP_ENUM_PATH_RESOURCES;
+	req.u.port_num.port_number = port_num;
+	drm_dp_encode_sideband_req(&req, msg);
+	msg->path_msg = true;
+	return 0;
+}
+
+static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
+				  u8 vcpi, uint16_t pbn)
+{
+	struct drm_dp_sideband_msg_req_body req;
+	memset(&req, 0, sizeof(req));
+	req.req_type = DP_ALLOCATE_PAYLOAD;
+	req.u.allocate_payload.port_number = port_num;
+	req.u.allocate_payload.vcpi = vcpi;
+	req.u.allocate_payload.pbn = pbn;
+	drm_dp_encode_sideband_req(&req, msg);
+	msg->path_msg = true;
+	return 0;
+}
+
+static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
+					struct drm_dp_vcpi *vcpi)
+{
+	int ret;
+
+	mutex_lock(&mgr->payload_lock);
+	ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
+	if (ret > mgr->max_payloads) {
+		ret = -EINVAL;
+		DRM_DEBUG_KMS("out of payload ids %d\n", ret);
+		goto out_unlock;
+	}
+
+	set_bit(ret, &mgr->payload_mask);
+	vcpi->vcpi = ret;
+	mgr->proposed_vcpis[ret - 1] = vcpi;
+out_unlock:
+	mutex_unlock(&mgr->payload_lock);
+	return ret;
+}
+
+static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
+				      int id)
+{
+	if (id == 0)
+		return;
+
+	mutex_lock(&mgr->payload_lock);
+	DRM_DEBUG_KMS("putting payload %d\n", id);
+	clear_bit(id, &mgr->payload_mask);
+	mgr->proposed_vcpis[id - 1] = NULL;
+	mutex_unlock(&mgr->payload_lock);
+}
+
+static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
+			      struct drm_dp_sideband_msg_tx *txmsg)
+{
+	bool ret;
+	mutex_lock(&mgr->qlock);
+	ret = (txmsg->state == DRM_DP_SIDEBAND_TX_RX ||
+	       txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT);
+	mutex_unlock(&mgr->qlock);
+	return ret;
+}
+
+static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
+				    struct drm_dp_sideband_msg_tx *txmsg)
+{
+	struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
+	int ret;
+
+	ret = wait_event_timeout(mgr->tx_waitq,
+				 check_txmsg_state(mgr, txmsg),
+				 (4 * HZ));
+	mutex_lock(&mstb->mgr->qlock);
+	if (ret > 0) {
+		if (txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT) {
+			ret = -EIO;
+			goto out;
+		}
+	} else {
+		DRM_DEBUG_KMS("timedout msg send %p %d %d\n", txmsg, txmsg->state, txmsg->seqno);
+
+		/* dump some state */
+		ret = -EIO;
+
+		/* remove from q */
+		if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED ||
+		    txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND) {
+			list_del(&txmsg->next);
+		}
+
+		if (txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
+		    txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
+			mstb->tx_slots[txmsg->seqno] = NULL;
+		}
+	}
+out:
+	mutex_unlock(&mgr->qlock);
+
+	return ret;
+}
+
+static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
+{
+	struct drm_dp_mst_branch *mstb;
+
+	mstb = kzalloc(sizeof(*mstb), GFP_KERNEL);
+	if (!mstb)
+		return NULL;
+
+	mstb->lct = lct;
+	if (lct > 1)
+		memcpy(mstb->rad, rad, lct / 2);
+	INIT_LIST_HEAD(&mstb->ports);
+	kref_init(&mstb->kref);
+	return mstb;
+}
+
+static void drm_dp_destroy_mst_branch_device(struct kref *kref)
+{
+	struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+	struct drm_dp_mst_port *port, *tmp;
+	bool wake_tx = false;
+
+	cancel_work_sync(&mstb->mgr->work);
+
+	/*
+	 * destroy all ports - don't need lock
+	 * as there are no more references to the mst branch
+	 * device at this point.
+	 */
+	list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
+		list_del(&port->next);
+		drm_dp_put_port(port);
+	}
+
+	/* drop any tx slots msg */
+	mutex_lock(&mstb->mgr->qlock);
+	if (mstb->tx_slots[0]) {
+		mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+		mstb->tx_slots[0] = NULL;
+		wake_tx = true;
+	}
+	if (mstb->tx_slots[1]) {
+		mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+		mstb->tx_slots[1] = NULL;
+		wake_tx = true;
+	}
+	mutex_unlock(&mstb->mgr->qlock);
+
+	if (wake_tx)
+		wake_up(&mstb->mgr->tx_waitq);
+	kfree(mstb);
+}
+
+static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
+{
+	kref_put(&mstb->kref, drm_dp_destroy_mst_branch_device);
+}
+
+
+static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
+{
+	switch (old_pdt) {
+	case DP_PEER_DEVICE_DP_LEGACY_CONV:
+	case DP_PEER_DEVICE_SST_SINK:
+		/* remove i2c over sideband */
+		drm_dp_mst_unregister_i2c_bus(&port->aux);
+		break;
+	case DP_PEER_DEVICE_MST_BRANCHING:
+		drm_dp_put_mst_branch_device(port->mstb);
+		port->mstb = NULL;
+		break;
+	}
+}
+
+static void drm_dp_destroy_port(struct kref *kref)
+{
+	struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
+	struct drm_dp_mst_topology_mgr *mgr = port->mgr;
+	if (!port->input) {
+		port->vcpi.num_slots = 0;
+		if (port->connector)
+			(*port->mgr->cbs->destroy_connector)(mgr, port->connector);
+		drm_dp_port_teardown_pdt(port, port->pdt);
+
+		if (!port->input && port->vcpi.vcpi > 0)
+			drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+	}
+	kfree(port);
+
+	(*mgr->cbs->hotplug)(mgr);
+}
+
+static void drm_dp_put_port(struct drm_dp_mst_port *port)
+{
+	kref_put(&port->kref, drm_dp_destroy_port);
+}
+
+static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_branch *to_find)
+{
+	struct drm_dp_mst_port *port;
+	struct drm_dp_mst_branch *rmstb;
+	if (to_find == mstb) {
+		kref_get(&mstb->kref);
+		return mstb;
+	}
+	list_for_each_entry(port, &mstb->ports, next) {
+		if (port->mstb) {
+			rmstb = drm_dp_mst_get_validated_mstb_ref_locked(port->mstb, to_find);
+			if (rmstb)
+				return rmstb;
+		}
+	}
+	return NULL;
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_validated_mstb_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb)
+{
+	struct drm_dp_mst_branch *rmstb = NULL;
+	mutex_lock(&mgr->lock);
+	if (mgr->mst_primary)
+		rmstb = drm_dp_mst_get_validated_mstb_ref_locked(mgr->mst_primary, mstb);
+	mutex_unlock(&mgr->lock);
+	return rmstb;
+}
+
+static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_port *to_find)
+{
+	struct drm_dp_mst_port *port, *mport;
+
+	list_for_each_entry(port, &mstb->ports, next) {
+		if (port == to_find) {
+			kref_get(&port->kref);
+			return port;
+		}
+		if (port->mstb) {
+			mport = drm_dp_mst_get_port_ref_locked(port->mstb, to_find);
+			if (mport)
+				return mport;
+		}
+	}
+	return NULL;
+}
+
+static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	struct drm_dp_mst_port *rport = NULL;
+	mutex_lock(&mgr->lock);
+	if (mgr->mst_primary)
+		rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, port);
+	mutex_unlock(&mgr->lock);
+	return rport;
+}
+
+static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u8 port_num)
+{
+	struct drm_dp_mst_port *port;
+
+	list_for_each_entry(port, &mstb->ports, next) {
+		if (port->port_num == port_num) {
+			kref_get(&port->kref);
+			return port;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * calculate a new RAD for this MST branch device
+ * if parent has an LCT of 2 then it has 1 nibble of RAD,
+ * if parent has an LCT of 3 then it has 2 nibbles of RAD,
+ */
+static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
+				 u8 *rad)
+{
+	int lct = port->parent->lct;
+	int shift = 4;
+	int idx = lct / 2;
+	if (lct > 1) {
+		memcpy(rad, port->parent->rad, idx);
+		shift = (lct % 2) ? 4 : 0;
+	} else
+		rad[0] = 0;
+
+	rad[idx] |= port->port_num << shift;
+	return lct + 1;
+}
+
+/*
+ * return sends link address for new mstb
+ */
+static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
+{
+	int ret;
+	u8 rad[6], lct;
+	bool send_link = false;
+	switch (port->pdt) {
+	case DP_PEER_DEVICE_DP_LEGACY_CONV:
+	case DP_PEER_DEVICE_SST_SINK:
+		/* add i2c over sideband */
+		ret = drm_dp_mst_register_i2c_bus(&port->aux);
+		break;
+	case DP_PEER_DEVICE_MST_BRANCHING:
+		lct = drm_dp_calculate_rad(port, rad);
+
+		port->mstb = drm_dp_add_mst_branch_device(lct, rad);
+		port->mstb->mgr = port->mgr;
+		port->mstb->port_parent = port;
+
+		send_link = true;
+		break;
+	}
+	return send_link;
+}
+
+static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
+				   struct drm_dp_mst_port *port)
+{
+	int ret;
+	if (port->dpcd_rev >= 0x12) {
+		port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid);
+		if (!port->guid_valid) {
+			ret = drm_dp_send_dpcd_write(mstb->mgr,
+						     port,
+						     DP_GUID,
+						     16, port->guid);
+			port->guid_valid = true;
+		}
+	}
+}
+
+static void build_mst_prop_path(struct drm_dp_mst_port *port,
+				struct drm_dp_mst_branch *mstb,
+				char *proppath)
+{
+	int i;
+	char temp[8];
+	snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id);
+	for (i = 0; i < (mstb->lct - 1); i++) {
+		int shift = (i % 2) ? 0 : 4;
+		int port_num = mstb->rad[i / 2] >> shift;
+		snprintf(temp, 8, "-%d", port_num);
+		strncat(proppath, temp, 255);
+	}
+	snprintf(temp, 8, "-%d", port->port_num);
+	strncat(proppath, temp, 255);
+}
+
+static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
+			    struct device *dev,
+			    struct drm_dp_link_addr_reply_port *port_msg)
+{
+	struct drm_dp_mst_port *port;
+	bool ret;
+	bool created = false;
+	int old_pdt = 0;
+	int old_ddps = 0;
+	port = drm_dp_get_port(mstb, port_msg->port_number);
+	if (!port) {
+		port = kzalloc(sizeof(*port), GFP_KERNEL);
+		if (!port)
+			return;
+		kref_init(&port->kref);
+		port->parent = mstb;
+		port->port_num = port_msg->port_number;
+		port->mgr = mstb->mgr;
+		port->aux.name = "DPMST";
+		port->aux.dev = dev;
+		created = true;
+	} else {
+		old_pdt = port->pdt;
+		old_ddps = port->ddps;
+	}
+
+	port->pdt = port_msg->peer_device_type;
+	port->input = port_msg->input_port;
+	port->mcs = port_msg->mcs;
+	port->ddps = port_msg->ddps;
+	port->ldps = port_msg->legacy_device_plug_status;
+	port->dpcd_rev = port_msg->dpcd_revision;
+	port->num_sdp_streams = port_msg->num_sdp_streams;
+	port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
+	memcpy(port->guid, port_msg->peer_guid, 16);
+
+	/* manage mstb port lists with mgr lock - take a reference
+	   for this list */
+	if (created) {
+		mutex_lock(&mstb->mgr->lock);
+		kref_get(&port->kref);
+		list_add(&port->next, &mstb->ports);
+		mutex_unlock(&mstb->mgr->lock);
+	}
+
+	if (old_ddps != port->ddps) {
+		if (port->ddps) {
+			drm_dp_check_port_guid(mstb, port);
+			if (!port->input)
+				drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
+		} else {
+			port->guid_valid = false;
+			port->available_pbn = 0;
+			}
+	}
+
+	if (old_pdt != port->pdt && !port->input) {
+		drm_dp_port_teardown_pdt(port, old_pdt);
+
+		ret = drm_dp_port_setup_pdt(port);
+		if (ret == true) {
+			drm_dp_send_link_address(mstb->mgr, port->mstb);
+			port->mstb->link_address_sent = true;
+		}
+	}
+
+	if (created && !port->input) {
+		char proppath[255];
+		build_mst_prop_path(port, mstb, proppath);
+		port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+	}
+
+	/* put reference to this port */
+	drm_dp_put_port(port);
+}
+
+static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
+			       struct drm_dp_connection_status_notify *conn_stat)
+{
+	struct drm_dp_mst_port *port;
+	int old_pdt;
+	int old_ddps;
+	bool dowork = false;
+	port = drm_dp_get_port(mstb, conn_stat->port_number);
+	if (!port)
+		return;
+
+	old_ddps = port->ddps;
+	old_pdt = port->pdt;
+	port->pdt = conn_stat->peer_device_type;
+	port->mcs = conn_stat->message_capability_status;
+	port->ldps = conn_stat->legacy_device_plug_status;
+	port->ddps = conn_stat->displayport_device_plug_status;
+
+	if (old_ddps != port->ddps) {
+		if (port->ddps) {
+			drm_dp_check_port_guid(mstb, port);
+			dowork = true;
+		} else {
+			port->guid_valid = false;
+			port->available_pbn = 0;
+		}
+	}
+	if (old_pdt != port->pdt && !port->input) {
+		drm_dp_port_teardown_pdt(port, old_pdt);
+
+		if (drm_dp_port_setup_pdt(port))
+			dowork = true;
+	}
+
+	drm_dp_put_port(port);
+	if (dowork)
+		queue_work(system_long_wq, &mstb->mgr->work);
+
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_topology_mgr *mgr,
+							       u8 lct, u8 *rad)
+{
+	struct drm_dp_mst_branch *mstb;
+	struct drm_dp_mst_port *port;
+	int i;
+	/* find the port by iterating down */
+	mstb = mgr->mst_primary;
+
+	for (i = 0; i < lct - 1; i++) {
+		int shift = (i % 2) ? 0 : 4;
+		int port_num = rad[i / 2] >> shift;
+
+		list_for_each_entry(port, &mstb->ports, next) {
+			if (port->port_num == port_num) {
+				if (!port->mstb) {
+					DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
+					return NULL;
+				}
+
+				mstb = port->mstb;
+				break;
+			}
+		}
+	}
+	kref_get(&mstb->kref);
+	return mstb;
+}
+
+static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+					       struct drm_dp_mst_branch *mstb)
+{
+	struct drm_dp_mst_port *port;
+
+	if (!mstb->link_address_sent) {
+		drm_dp_send_link_address(mgr, mstb);
+		mstb->link_address_sent = true;
+	}
+	list_for_each_entry(port, &mstb->ports, next) {
+		if (port->input)
+			continue;
+
+		if (!port->ddps)
+			continue;
+
+		if (!port->available_pbn)
+			drm_dp_send_enum_path_resources(mgr, mstb, port);
+
+		if (port->mstb)
+			drm_dp_check_and_send_link_address(mgr, port->mstb);
+	}
+}
+
+static void drm_dp_mst_link_probe_work(struct work_struct *work)
+{
+	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
+
+	drm_dp_check_and_send_link_address(mgr, mgr->mst_primary);
+
+}
+
+static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
+				 u8 *guid)
+{
+	static u8 zero_guid[16];
+
+	if (!memcmp(guid, zero_guid, 16)) {
+		u64 salt = get_jiffies_64();
+		memcpy(&guid[0], &salt, sizeof(u64));
+		memcpy(&guid[8], &salt, sizeof(u64));
+		return false;
+	}
+	return true;
+}
+
+#if 0
+static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
+{
+	struct drm_dp_sideband_msg_req_body req;
+
+	req.req_type = DP_REMOTE_DPCD_READ;
+	req.u.dpcd_read.port_number = port_num;
+	req.u.dpcd_read.dpcd_address = offset;
+	req.u.dpcd_read.num_bytes = num_bytes;
+	drm_dp_encode_sideband_req(&req, msg);
+
+	return 0;
+}
+#endif
+
+static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
+				    bool up, u8 *msg, int len)
+{
+	int ret;
+	int regbase = up ? DP_SIDEBAND_MSG_UP_REP_BASE : DP_SIDEBAND_MSG_DOWN_REQ_BASE;
+	int tosend, total, offset;
+	int retries = 0;
+
+retry:
+	total = len;
+	offset = 0;
+	do {
+		tosend = min3(mgr->max_dpcd_transaction_bytes, 16, total);
+
+		ret = drm_dp_dpcd_write(mgr->aux, regbase + offset,
+					&msg[offset],
+					tosend);
+		if (ret != tosend) {
+			if (ret == -EIO && retries < 5) {
+				retries++;
+				goto retry;
+			}
+			DRM_DEBUG_KMS("failed to dpcd write %d %d\n", tosend, ret);
+			WARN(1, "fail\n");
+
+			return -EIO;
+		}
+		offset += tosend;
+		total -= tosend;
+	} while (total > 0);
+	return 0;
+}
+
+static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
+				  struct drm_dp_sideband_msg_tx *txmsg)
+{
+	struct drm_dp_mst_branch *mstb = txmsg->dst;
+
+	/* both msg slots are full */
+	if (txmsg->seqno == -1) {
+		if (mstb->tx_slots[0] && mstb->tx_slots[1]) {
+			DRM_DEBUG_KMS("%s: failed to find slot\n", __func__);
+			return -EAGAIN;
+		}
+		if (mstb->tx_slots[0] == NULL && mstb->tx_slots[1] == NULL) {
+			txmsg->seqno = mstb->last_seqno;
+			mstb->last_seqno ^= 1;
+		} else if (mstb->tx_slots[0] == NULL)
+			txmsg->seqno = 0;
+		else
+			txmsg->seqno = 1;
+		mstb->tx_slots[txmsg->seqno] = txmsg;
+	}
+	hdr->broadcast = 0;
+	hdr->path_msg = txmsg->path_msg;
+	hdr->lct = mstb->lct;
+	hdr->lcr = mstb->lct - 1;
+	if (mstb->lct > 1)
+		memcpy(hdr->rad, mstb->rad, mstb->lct / 2);
+	hdr->seqno = txmsg->seqno;
+	return 0;
+}
+/*
+ * process a single block of the next message in the sideband queue
+ */
+static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
+				   struct drm_dp_sideband_msg_tx *txmsg,
+				   bool up)
+{
+	u8 chunk[48];
+	struct drm_dp_sideband_msg_hdr hdr;
+	int len, space, idx, tosend;
+	int ret;
+
+	memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr));
+
+	if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) {
+		txmsg->seqno = -1;
+		txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND;
+	}
+
+	/* make hdr from dst mst - for replies use seqno
+	   otherwise assign one */
+	ret = set_hdr_from_dst_qlock(&hdr, txmsg);
+	if (ret < 0)
+		return ret;
+
+	/* amount left to send in this message */
+	len = txmsg->cur_len - txmsg->cur_offset;
+
+	/* 48 - sideband msg size - 1 byte for data CRC, x header bytes */
+	space = 48 - 1 - drm_dp_calc_sb_hdr_size(&hdr);
+
+	tosend = min(len, space);
+	if (len == txmsg->cur_len)
+		hdr.somt = 1;
+	if (space >= len)
+		hdr.eomt = 1;
+
+
+	hdr.msg_len = tosend + 1;
+	drm_dp_encode_sideband_msg_hdr(&hdr, chunk, &idx);
+	memcpy(&chunk[idx], &txmsg->msg[txmsg->cur_offset], tosend);
+	/* add crc at end */
+	drm_dp_crc_sideband_chunk_req(&chunk[idx], tosend);
+	idx += tosend + 1;
+
+	ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
+	if (ret) {
+		DRM_DEBUG_KMS("sideband msg failed to send\n");
+		return ret;
+	}
+
+	txmsg->cur_offset += tosend;
+	if (txmsg->cur_offset == txmsg->cur_len) {
+		txmsg->state = DRM_DP_SIDEBAND_TX_SENT;
+		return 1;
+	}
+	return 0;
+}
+
+/* must be called holding qlock */
+static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_dp_sideband_msg_tx *txmsg;
+	int ret;
+
+	/* construct a chunk from the first msg in the tx_msg queue */
+	if (list_empty(&mgr->tx_msg_downq)) {
+		mgr->tx_down_in_progress = false;
+		return;
+	}
+	mgr->tx_down_in_progress = true;
+
+	txmsg = list_first_entry(&mgr->tx_msg_downq, struct drm_dp_sideband_msg_tx, next);
+	ret = process_single_tx_qlock(mgr, txmsg, false);
+	if (ret == 1) {
+		/* txmsg is sent it should be in the slots now */
+		list_del(&txmsg->next);
+	} else if (ret) {
+		DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+		list_del(&txmsg->next);
+		if (txmsg->seqno != -1)
+			txmsg->dst->tx_slots[txmsg->seqno] = NULL;
+		txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+		wake_up(&mgr->tx_waitq);
+	}
+	if (list_empty(&mgr->tx_msg_downq)) {
+		mgr->tx_down_in_progress = false;
+		return;
+	}
+}
+
+/* called holding qlock */
+static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_dp_sideband_msg_tx *txmsg;
+	int ret;
+
+	/* construct a chunk from the first msg in the tx_msg queue */
+	if (list_empty(&mgr->tx_msg_upq)) {
+		mgr->tx_up_in_progress = false;
+		return;
+	}
+
+	txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
+	ret = process_single_tx_qlock(mgr, txmsg, true);
+	if (ret == 1) {
+		/* up txmsgs aren't put in slots - so free after we send it */
+		list_del(&txmsg->next);
+		kfree(txmsg);
+	} else if (ret)
+		DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+	mgr->tx_up_in_progress = true;
+}
+
+static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
+				 struct drm_dp_sideband_msg_tx *txmsg)
+{
+	mutex_lock(&mgr->qlock);
+	list_add_tail(&txmsg->next, &mgr->tx_msg_downq);
+	if (!mgr->tx_down_in_progress)
+		process_single_down_tx_qlock(mgr);
+	mutex_unlock(&mgr->qlock);
+}
+
+static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+				    struct drm_dp_mst_branch *mstb)
+{
+	int len;
+	struct drm_dp_sideband_msg_tx *txmsg;
+	int ret;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg)
+		return -ENOMEM;
+
+	txmsg->dst = mstb;
+	len = build_link_address(txmsg);
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+	if (ret > 0) {
+		int i;
+
+		if (txmsg->reply.reply_type == 1)
+			DRM_DEBUG_KMS("link address nak received\n");
+		else {
+			DRM_DEBUG_KMS("link address reply: %d\n", txmsg->reply.u.link_addr.nports);
+			for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+				DRM_DEBUG_KMS("port %d: input %d, pdt: %d, pn: %d, dpcd_rev: %02x, mcs: %d, ddps: %d, ldps %d, sdp %d/%d\n", i,
+				       txmsg->reply.u.link_addr.ports[i].input_port,
+				       txmsg->reply.u.link_addr.ports[i].peer_device_type,
+				       txmsg->reply.u.link_addr.ports[i].port_number,
+				       txmsg->reply.u.link_addr.ports[i].dpcd_revision,
+				       txmsg->reply.u.link_addr.ports[i].mcs,
+				       txmsg->reply.u.link_addr.ports[i].ddps,
+				       txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status,
+				       txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
+				       txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
+			}
+			for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+				drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
+			}
+			(*mgr->cbs->hotplug)(mgr);
+		}
+	} else
+		DRM_DEBUG_KMS("link address failed %d\n", ret);
+
+	kfree(txmsg);
+	return 0;
+}
+
+static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
+					   struct drm_dp_mst_branch *mstb,
+					   struct drm_dp_mst_port *port)
+{
+	int len;
+	struct drm_dp_sideband_msg_tx *txmsg;
+	int ret;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg)
+		return -ENOMEM;
+
+	txmsg->dst = mstb;
+	len = build_enum_path_resources(txmsg, port->port_num);
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+	if (ret > 0) {
+		if (txmsg->reply.reply_type == 1)
+			DRM_DEBUG_KMS("enum path resources nak received\n");
+		else {
+			if (port->port_num != txmsg->reply.u.path_resources.port_number)
+				DRM_ERROR("got incorrect port in response\n");
+			DRM_DEBUG_KMS("enum path resources %d: %d %d\n", txmsg->reply.u.path_resources.port_number, txmsg->reply.u.path_resources.full_payload_bw_number,
+			       txmsg->reply.u.path_resources.avail_payload_bw_number);
+			port->available_pbn = txmsg->reply.u.path_resources.avail_payload_bw_number;
+		}
+	}
+
+	kfree(txmsg);
+	return 0;
+}
+
+static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
+				   struct drm_dp_mst_port *port,
+				   int id,
+				   int pbn)
+{
+	struct drm_dp_sideband_msg_tx *txmsg;
+	struct drm_dp_mst_branch *mstb;
+	int len, ret;
+
+	mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+	if (!mstb)
+		return -EINVAL;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg) {
+		ret = -ENOMEM;
+		goto fail_put;
+	}
+
+	txmsg->dst = mstb;
+	len = build_allocate_payload(txmsg, port->port_num,
+				     id,
+				     pbn);
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+	if (ret > 0) {
+		if (txmsg->reply.reply_type == 1) {
+			ret = -EINVAL;
+		} else
+			ret = 0;
+	}
+	kfree(txmsg);
+fail_put:
+	drm_dp_put_mst_branch_device(mstb);
+	return ret;
+}
+
+static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
+				       int id,
+				       struct drm_dp_payload *payload)
+{
+	int ret;
+
+	ret = drm_dp_dpcd_write_payload(mgr, id, payload);
+	if (ret < 0) {
+		payload->payload_state = 0;
+		return ret;
+	}
+	payload->payload_state = DP_PAYLOAD_LOCAL;
+	return 0;
+}
+
+static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
+				       struct drm_dp_mst_port *port,
+				       int id,
+				       struct drm_dp_payload *payload)
+{
+	int ret;
+	ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
+	if (ret < 0)
+		return ret;
+	payload->payload_state = DP_PAYLOAD_REMOTE;
+	return ret;
+}
+
+static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
+					struct drm_dp_mst_port *port,
+					int id,
+					struct drm_dp_payload *payload)
+{
+	DRM_DEBUG_KMS("\n");
+	/* its okay for these to fail */
+	if (port) {
+		drm_dp_payload_send_msg(mgr, port, id, 0);
+	}
+
+	drm_dp_dpcd_write_payload(mgr, id, payload);
+	payload->payload_state = 0;
+	return 0;
+}
+
+static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
+					int id,
+					struct drm_dp_payload *payload)
+{
+	payload->payload_state = 0;
+	return 0;
+}
+
+/**
+ * drm_dp_update_payload_part1() - Execute payload update part 1
+ * @mgr: manager to use.
+ *
+ * This iterates over all proposed virtual channels, and tries to
+ * allocate space in the link for them. For 0->slots transitions,
+ * this step just writes the VCPI to the MST device. For slots->0
+ * transitions, this writes the updated VCPIs and removes the
+ * remote VC payloads.
+ *
+ * after calling this the driver should generate ACT and payload
+ * packets.
+ */
+int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
+{
+	int i;
+	int cur_slots = 1;
+	struct drm_dp_payload req_payload;
+	struct drm_dp_mst_port *port;
+
+	mutex_lock(&mgr->payload_lock);
+	for (i = 0; i < mgr->max_payloads; i++) {
+		/* solve the current payloads - compare to the hw ones
+		   - update the hw view */
+		req_payload.start_slot = cur_slots;
+		if (mgr->proposed_vcpis[i]) {
+			port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+			req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots;
+		} else {
+			port = NULL;
+			req_payload.num_slots = 0;
+		}
+		/* work out what is required to happen with this payload */
+		if (mgr->payloads[i].start_slot != req_payload.start_slot ||
+		    mgr->payloads[i].num_slots != req_payload.num_slots) {
+
+			/* need to push an update for this payload */
+			if (req_payload.num_slots) {
+				drm_dp_create_payload_step1(mgr, i + 1, &req_payload);
+				mgr->payloads[i].num_slots = req_payload.num_slots;
+			} else if (mgr->payloads[i].num_slots) {
+				mgr->payloads[i].num_slots = 0;
+				drm_dp_destroy_payload_step1(mgr, port, i + 1, &mgr->payloads[i]);
+				req_payload.payload_state = mgr->payloads[i].payload_state;
+			} else
+				req_payload.payload_state = 0;
+
+			mgr->payloads[i].start_slot = req_payload.start_slot;
+			mgr->payloads[i].payload_state = req_payload.payload_state;
+		}
+		cur_slots += req_payload.num_slots;
+	}
+	mutex_unlock(&mgr->payload_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_update_payload_part1);
+
+/**
+ * drm_dp_update_payload_part2() - Execute payload update part 2
+ * @mgr: manager to use.
+ *
+ * This iterates over all proposed virtual channels, and tries to
+ * allocate space in the link for them. For 0->slots transitions,
+ * this step writes the remote VC payload commands. For slots->0
+ * this just resets some internal state.
+ */
+int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_dp_mst_port *port;
+	int i;
+	int ret = 0;
+	mutex_lock(&mgr->payload_lock);
+	for (i = 0; i < mgr->max_payloads; i++) {
+
+		if (!mgr->proposed_vcpis[i])
+			continue;
+
+		port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+
+		DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state);
+		if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
+			ret = drm_dp_create_payload_step2(mgr, port, i + 1, &mgr->payloads[i]);
+		} else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
+			ret = drm_dp_destroy_payload_step2(mgr, i + 1, &mgr->payloads[i]);
+		}
+		if (ret) {
+			mutex_unlock(&mgr->payload_lock);
+			return ret;
+		}
+	}
+	mutex_unlock(&mgr->payload_lock);
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_update_payload_part2);
+
+#if 0 /* unused as of yet */
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+				 struct drm_dp_mst_port *port,
+				 int offset, int size)
+{
+	int len;
+	struct drm_dp_sideband_msg_tx *txmsg;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg)
+		return -ENOMEM;
+
+	len = build_dpcd_read(txmsg, port->port_num, 0, 8);
+	txmsg->dst = port->parent;
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	return 0;
+}
+#endif
+
+static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+				  struct drm_dp_mst_port *port,
+				  int offset, int size, u8 *bytes)
+{
+	int len;
+	int ret;
+	struct drm_dp_sideband_msg_tx *txmsg;
+	struct drm_dp_mst_branch *mstb;
+
+	mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+	if (!mstb)
+		return -EINVAL;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg) {
+		ret = -ENOMEM;
+		goto fail_put;
+	}
+
+	len = build_dpcd_write(txmsg, port->port_num, offset, size, bytes);
+	txmsg->dst = mstb;
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+	if (ret > 0) {
+		if (txmsg->reply.reply_type == 1) {
+			ret = -EINVAL;
+		} else
+			ret = 0;
+	}
+	kfree(txmsg);
+fail_put:
+	drm_dp_put_mst_branch_device(mstb);
+	return ret;
+}
+
+static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type)
+{
+	struct drm_dp_sideband_msg_reply_body reply;
+
+	reply.reply_type = 1;
+	reply.req_type = req_type;
+	drm_dp_encode_sideband_reply(&reply, msg);
+	return 0;
+}
+
+static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
+				    struct drm_dp_mst_branch *mstb,
+				    int req_type, int seqno, bool broadcast)
+{
+	struct drm_dp_sideband_msg_tx *txmsg;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg)
+		return -ENOMEM;
+
+	txmsg->dst = mstb;
+	txmsg->seqno = seqno;
+	drm_dp_encode_up_ack_reply(txmsg, req_type);
+
+	mutex_lock(&mgr->qlock);
+	list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
+	if (!mgr->tx_up_in_progress) {
+		process_single_up_tx_qlock(mgr);
+	}
+	mutex_unlock(&mgr->qlock);
+	return 0;
+}
+
+static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
+{
+	switch (dp_link_bw) {
+	case DP_LINK_BW_1_62:
+		return 3 * dp_link_count;
+	case DP_LINK_BW_2_7:
+		return 5 * dp_link_count;
+	case DP_LINK_BW_5_4:
+		return 10 * dp_link_count;
+	}
+	return 0;
+}
+
+/**
+ * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager
+ * @mgr: manager to set state for
+ * @mst_state: true to enable MST on this connector - false to disable.
+ *
+ * This is called by the driver when it detects an MST capable device plugged
+ * into a DP MST capable port, or when a DP MST capable device is unplugged.
+ */
+int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state)
+{
+	int ret = 0;
+	struct drm_dp_mst_branch *mstb = NULL;
+
+	mutex_lock(&mgr->lock);
+	if (mst_state == mgr->mst_state)
+		goto out_unlock;
+
+	mgr->mst_state = mst_state;
+	/* set the device into MST mode */
+	if (mst_state) {
+		WARN_ON(mgr->mst_primary);
+
+		/* get dpcd info */
+		ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
+		if (ret != DP_RECEIVER_CAP_SIZE) {
+			DRM_DEBUG_KMS("failed to read DPCD\n");
+			goto out_unlock;
+		}
+
+		mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr->dpcd[1], mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK);
+		mgr->total_pbn = 2560;
+		mgr->total_slots = DIV_ROUND_UP(mgr->total_pbn, mgr->pbn_div);
+		mgr->avail_slots = mgr->total_slots;
+
+		/* add initial branch device at LCT 1 */
+		mstb = drm_dp_add_mst_branch_device(1, NULL);
+		if (mstb == NULL) {
+			ret = -ENOMEM;
+			goto out_unlock;
+		}
+		mstb->mgr = mgr;
+
+		/* give this the main reference */
+		mgr->mst_primary = mstb;
+		kref_get(&mgr->mst_primary->kref);
+
+		{
+			struct drm_dp_payload reset_pay;
+			reset_pay.start_slot = 0;
+			reset_pay.num_slots = 0x3f;
+			drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+		}
+
+		ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+					 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+		if (ret < 0) {
+			goto out_unlock;
+		}
+
+
+		/* sort out guid */
+		ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16);
+		if (ret != 16) {
+			DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret);
+			goto out_unlock;
+		}
+
+		mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid);
+		if (!mgr->guid_valid) {
+			ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16);
+			mgr->guid_valid = true;
+		}
+
+		queue_work(system_long_wq, &mgr->work);
+
+		ret = 0;
+	} else {
+		/* disable MST on the device */
+		mstb = mgr->mst_primary;
+		mgr->mst_primary = NULL;
+		/* this can fail if the device is gone */
+		drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
+		ret = 0;
+		memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload));
+		mgr->payload_mask = 0;
+		set_bit(0, &mgr->payload_mask);
+	}
+
+out_unlock:
+	mutex_unlock(&mgr->lock);
+	if (mstb)
+		drm_dp_put_mst_branch_device(mstb);
+	return ret;
+
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_set_mst);
+
+/**
+ * drm_dp_mst_topology_mgr_suspend() - suspend the MST manager
+ * @mgr: manager to suspend
+ *
+ * This function tells the MST device that we can't handle UP messages
+ * anymore. This should stop it from sending any since we are suspended.
+ */
+void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr)
+{
+	mutex_lock(&mgr->lock);
+	drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+			   DP_MST_EN | DP_UPSTREAM_IS_SRC);
+	mutex_unlock(&mgr->lock);
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
+
+/**
+ * drm_dp_mst_topology_mgr_resume() - resume the MST manager
+ * @mgr: manager to resume
+ *
+ * This will fetch DPCD and see if the device is still there,
+ * if it is, it will rewrite the MSTM control bits, and return.
+ *
+ * if the device fails this returns -1, and the driver should do
+ * a full MST reprobe, in case we were undocked.
+ */
+int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)
+{
+	int ret = 0;
+
+	mutex_lock(&mgr->lock);
+
+	if (mgr->mst_primary) {
+		int sret;
+		sret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
+		if (sret != DP_RECEIVER_CAP_SIZE) {
+			DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n");
+			ret = -1;
+			goto out_unlock;
+		}
+
+		ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+					 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("mst write failed - undocked during suspend?\n");
+			ret = -1;
+			goto out_unlock;
+		}
+		ret = 0;
+	} else
+		ret = -1;
+
+out_unlock:
+	mutex_unlock(&mgr->lock);
+	return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
+
+static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
+{
+	int len;
+	u8 replyblock[32];
+	int replylen, origlen, curreply;
+	int ret;
+	struct drm_dp_sideband_msg_rx *msg;
+	int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE;
+	msg = up ? &mgr->up_req_recv : &mgr->down_rep_recv;
+
+	len = min(mgr->max_dpcd_transaction_bytes, 16);
+	ret = drm_dp_dpcd_read(mgr->aux, basereg,
+			       replyblock, len);
+	if (ret != len) {
+		DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
+		return;
+	}
+	ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
+	if (!ret) {
+		DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
+		return;
+	}
+	replylen = msg->curchunk_len + msg->curchunk_hdrlen;
+
+	origlen = replylen;
+	replylen -= len;
+	curreply = len;
+	while (replylen > 0) {
+		len = min3(replylen, mgr->max_dpcd_transaction_bytes, 16);
+		ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
+				    replyblock, len);
+		if (ret != len) {
+			DRM_DEBUG_KMS("failed to read a chunk\n");
+		}
+		ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
+		if (ret == false)
+			DRM_DEBUG_KMS("failed to build sideband msg\n");
+		curreply += len;
+		replylen -= len;
+	}
+}
+
+static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
+{
+	int ret = 0;
+
+	drm_dp_get_one_sb_msg(mgr, false);
+
+	if (mgr->down_rep_recv.have_eomt) {
+		struct drm_dp_sideband_msg_tx *txmsg;
+		struct drm_dp_mst_branch *mstb;
+		int slot = -1;
+		mstb = drm_dp_get_mst_branch_device(mgr,
+						    mgr->down_rep_recv.initial_hdr.lct,
+						    mgr->down_rep_recv.initial_hdr.rad);
+
+		if (!mstb) {
+			DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->down_rep_recv.initial_hdr.lct);
+			memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+			return 0;
+		}
+
+		/* find the message */
+		slot = mgr->down_rep_recv.initial_hdr.seqno;
+		mutex_lock(&mgr->qlock);
+		txmsg = mstb->tx_slots[slot];
+		/* remove from slots */
+		mutex_unlock(&mgr->qlock);
+
+		if (!txmsg) {
+			DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
+			       mstb,
+			       mgr->down_rep_recv.initial_hdr.seqno,
+			       mgr->down_rep_recv.initial_hdr.lct,
+				      mgr->down_rep_recv.initial_hdr.rad[0],
+				      mgr->down_rep_recv.msg[0]);
+			drm_dp_put_mst_branch_device(mstb);
+			memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+			return 0;
+		}
+
+		drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply);
+		if (txmsg->reply.reply_type == 1) {
+			DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, reason 0x%02x, nak data 0x%02x\n", txmsg->reply.req_type, txmsg->reply.u.nak.reason, txmsg->reply.u.nak.nak_data);
+		}
+
+		memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+		drm_dp_put_mst_branch_device(mstb);
+
+		mutex_lock(&mgr->qlock);
+		txmsg->state = DRM_DP_SIDEBAND_TX_RX;
+		mstb->tx_slots[slot] = NULL;
+		mutex_unlock(&mgr->qlock);
+
+		wake_up(&mgr->tx_waitq);
+	}
+	return ret;
+}
+
+static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
+{
+	int ret = 0;
+	drm_dp_get_one_sb_msg(mgr, true);
+
+	if (mgr->up_req_recv.have_eomt) {
+		struct drm_dp_sideband_msg_req_body msg;
+		struct drm_dp_mst_branch *mstb;
+		bool seqno;
+		mstb = drm_dp_get_mst_branch_device(mgr,
+						    mgr->up_req_recv.initial_hdr.lct,
+						    mgr->up_req_recv.initial_hdr.rad);
+		if (!mstb) {
+			DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+			memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+			return 0;
+		}
+
+		seqno = mgr->up_req_recv.initial_hdr.seqno;
+		drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
+
+		if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
+			drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+			drm_dp_update_port(mstb, &msg.u.conn_stat);
+			DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+			(*mgr->cbs->hotplug)(mgr);
+
+		} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
+			drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+			DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
+		}
+
+		drm_dp_put_mst_branch_device(mstb);
+		memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+	}
+	return ret;
+}
+
+/**
+ * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
+ * @mgr: manager to notify irq for.
+ * @esi: 4 bytes from SINK_COUNT_ESI
+ *
+ * This should be called from the driver when it detects a short IRQ,
+ * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
+ * topology manager will process the sideband messages received as a result
+ * of this.
+ */
+int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled)
+{
+	int ret = 0;
+	int sc;
+	*handled = false;
+	sc = esi[0] & 0x3f;
+
+	if (sc != mgr->sink_count) {
+		mgr->sink_count = sc;
+		*handled = true;
+	}
+
+	if (esi[1] & DP_DOWN_REP_MSG_RDY) {
+		ret = drm_dp_mst_handle_down_rep(mgr);
+		*handled = true;
+	}
+
+	if (esi[1] & DP_UP_REQ_MSG_RDY) {
+		ret |= drm_dp_mst_handle_up_req(mgr);
+		*handled = true;
+	}
+
+	drm_dp_mst_kick_tx(mgr);
+	return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
+
+/**
+ * drm_dp_mst_detect_port() - get connection status for an MST port
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port
+ *
+ * This returns the current connection state for a port. It validates the
+ * port pointer still exists so the caller doesn't require a reference
+ */
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	enum drm_connector_status status = connector_status_disconnected;
+
+	/* we need to search for the port in the mgr in case its gone */
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return connector_status_disconnected;
+
+	if (!port->ddps)
+		goto out;
+
+	switch (port->pdt) {
+	case DP_PEER_DEVICE_NONE:
+	case DP_PEER_DEVICE_MST_BRANCHING:
+		break;
+
+	case DP_PEER_DEVICE_SST_SINK:
+		status = connector_status_connected;
+		break;
+	case DP_PEER_DEVICE_DP_LEGACY_CONV:
+		if (port->ldps)
+			status = connector_status_connected;
+		break;
+	}
+out:
+	drm_dp_put_port(port);
+	return status;
+}
+EXPORT_SYMBOL(drm_dp_mst_detect_port);
+
+/**
+ * drm_dp_mst_get_edid() - get EDID for an MST port
+ * @connector: toplevel connector to get EDID for
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This returns an EDID for the port connected to a connector,
+ * It validates the pointer still exists so the caller doesn't require a
+ * reference.
+ */
+struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	struct edid *edid = NULL;
+
+	/* we need to search for the port in the mgr in case its gone */
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return NULL;
+
+	edid = drm_get_edid(connector, &port->aux.ddc);
+	drm_dp_put_port(port);
+	return edid;
+}
+EXPORT_SYMBOL(drm_dp_mst_get_edid);
+
+/**
+ * drm_dp_find_vcpi_slots() - find slots for this PBN value
+ * @mgr: manager to use
+ * @pbn: payload bandwidth to convert into slots.
+ */
+int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
+			   int pbn)
+{
+	int num_slots;
+
+	num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
+
+	if (num_slots > mgr->avail_slots)
+		return -ENOSPC;
+	return num_slots;
+}
+EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
+
+static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
+			    struct drm_dp_vcpi *vcpi, int pbn)
+{
+	int num_slots;
+	int ret;
+
+	num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
+
+	if (num_slots > mgr->avail_slots)
+		return -ENOSPC;
+
+	vcpi->pbn = pbn;
+	vcpi->aligned_pbn = num_slots * mgr->pbn_div;
+	vcpi->num_slots = num_slots;
+
+	ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+/**
+ * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
+ * @mgr: manager for this port
+ * @port: port to allocate a virtual channel for.
+ * @pbn: payload bandwidth number to request
+ * @slots: returned number of slots for this PBN.
+ */
+bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots)
+{
+	int ret;
+
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return false;
+
+	if (port->vcpi.vcpi > 0) {
+		DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
+		if (pbn == port->vcpi.pbn) {
+			*slots = port->vcpi.num_slots;
+			return true;
+		}
+	}
+
+	ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn);
+	if (ret) {
+		DRM_DEBUG_KMS("failed to init vcpi %d %d %d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), mgr->avail_slots, ret);
+		goto out;
+	}
+	DRM_DEBUG_KMS("initing vcpi for %d %d\n", pbn, port->vcpi.num_slots);
+	*slots = port->vcpi.num_slots;
+
+	drm_dp_put_port(port);
+	return true;
+out:
+	return false;
+}
+EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
+
+/**
+ * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This just resets the number of slots for the ports VCPI for later programming.
+ */
+void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return;
+	port->vcpi.num_slots = 0;
+	drm_dp_put_port(port);
+}
+EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
+
+/**
+ * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI
+ * @mgr: manager for this port
+ * @port: unverified port to deallocate vcpi for
+ */
+void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return;
+
+	drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+	port->vcpi.num_slots = 0;
+	port->vcpi.pbn = 0;
+	port->vcpi.aligned_pbn = 0;
+	port->vcpi.vcpi = 0;
+	drm_dp_put_port(port);
+}
+EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
+
+static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
+				     int id, struct drm_dp_payload *payload)
+{
+	u8 payload_alloc[3], status;
+	int ret;
+	int retries = 0;
+
+	drm_dp_dpcd_writeb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS,
+			   DP_PAYLOAD_TABLE_UPDATED);
+
+	payload_alloc[0] = id;
+	payload_alloc[1] = payload->start_slot;
+	payload_alloc[2] = payload->num_slots;
+
+	ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3);
+	if (ret != 3) {
+		DRM_DEBUG_KMS("failed to write payload allocation %d\n", ret);
+		goto fail;
+	}
+
+retry:
+	ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
+		goto fail;
+	}
+
+	if (!(status & DP_PAYLOAD_TABLE_UPDATED)) {
+		retries++;
+		if (retries < 20) {
+			usleep_range(10000, 20000);
+			goto retry;
+		}
+		DRM_DEBUG_KMS("status not set after read payload table status %d\n", status);
+		ret = -EINVAL;
+		goto fail;
+	}
+	ret = 0;
+fail:
+	return ret;
+}
+
+
+/**
+ * drm_dp_check_act_status() - Check ACT handled status.
+ * @mgr: manager to use
+ *
+ * Check the payload status bits in the DPCD for ACT handled completion.
+ */
+int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr)
+{
+	u8 status;
+	int ret;
+	int count = 0;
+
+	do {
+		ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
+
+		if (ret < 0) {
+			DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
+			goto fail;
+		}
+
+		if (status & DP_PAYLOAD_ACT_HANDLED)
+			break;
+		count++;
+		udelay(100);
+
+	} while (count < 30);
+
+	if (!(status & DP_PAYLOAD_ACT_HANDLED)) {
+		DRM_DEBUG_KMS("failed to get ACT bit %d after %d retries\n", status, count);
+		ret = -EINVAL;
+		goto fail;
+	}
+	return 0;
+fail:
+	return ret;
+}
+EXPORT_SYMBOL(drm_dp_check_act_status);
+
+/**
+ * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
+ * @clock: dot clock for the mode
+ * @bpp: bpp for the mode.
+ *
+ * This uses the formula in the spec to calculate the PBN value for a mode.
+ */
+int drm_dp_calc_pbn_mode(int clock, int bpp)
+{
+	fixed20_12 pix_bw;
+	fixed20_12 fbpp;
+	fixed20_12 result;
+	fixed20_12 margin, tmp;
+	u32 res;
+
+	pix_bw.full = dfixed_const(clock);
+	fbpp.full = dfixed_const(bpp);
+	tmp.full = dfixed_const(8);
+	fbpp.full = dfixed_div(fbpp, tmp);
+
+	result.full = dfixed_mul(pix_bw, fbpp);
+	margin.full = dfixed_const(54);
+	tmp.full = dfixed_const(64);
+	margin.full = dfixed_div(margin, tmp);
+	result.full = dfixed_div(result, margin);
+
+	margin.full = dfixed_const(1006);
+	tmp.full = dfixed_const(1000);
+	margin.full = dfixed_div(margin, tmp);
+	result.full = dfixed_mul(result, margin);
+
+	result.full = dfixed_div(result, tmp);
+	result.full = dfixed_ceil(result);
+	res = dfixed_trunc(result);
+	return res;
+}
+EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
+
+static int test_calc_pbn_mode(void)
+{
+	int ret;
+	ret = drm_dp_calc_pbn_mode(154000, 30);
+	if (ret != 689)
+		return -EINVAL;
+	ret = drm_dp_calc_pbn_mode(234000, 30);
+	if (ret != 1047)
+		return -EINVAL;
+	return 0;
+}
+
+/* we want to kick the TX after we've ack the up/down IRQs. */
+static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
+{
+	queue_work(system_long_wq, &mgr->tx_work);
+}
+
+static void drm_dp_mst_dump_mstb(struct seq_file *m,
+				 struct drm_dp_mst_branch *mstb)
+{
+	struct drm_dp_mst_port *port;
+	int tabs = mstb->lct;
+	char prefix[10];
+	int i;
+
+	for (i = 0; i < tabs; i++)
+		prefix[i] = '\t';
+	prefix[i] = '\0';
+
+	seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
+	list_for_each_entry(port, &mstb->ports, next) {
+		seq_printf(m, "%sport: %d: ddps: %d ldps: %d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port, port->connector);
+		if (port->mstb)
+			drm_dp_mst_dump_mstb(m, port->mstb);
+	}
+}
+
+static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
+				  char *buf)
+{
+	int ret;
+	int i;
+	for (i = 0; i < 4; i++) {
+		ret = drm_dp_dpcd_read(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS + (i * 16), &buf[i * 16], 16);
+		if (ret != 16)
+			break;
+	}
+	if (i == 4)
+		return true;
+	return false;
+}
+
+/**
+ * drm_dp_mst_dump_topology(): dump topology to seq file.
+ * @m: seq_file to dump output to
+ * @mgr: manager to dump current topology for.
+ *
+ * helper to dump MST topology to a seq file for debugfs.
+ */
+void drm_dp_mst_dump_topology(struct seq_file *m,
+			      struct drm_dp_mst_topology_mgr *mgr)
+{
+	int i;
+	struct drm_dp_mst_port *port;
+	mutex_lock(&mgr->lock);
+	if (mgr->mst_primary)
+		drm_dp_mst_dump_mstb(m, mgr->mst_primary);
+
+	/* dump VCPIs */
+	mutex_unlock(&mgr->lock);
+
+	mutex_lock(&mgr->payload_lock);
+	seq_printf(m, "vcpi: %lx\n", mgr->payload_mask);
+
+	for (i = 0; i < mgr->max_payloads; i++) {
+		if (mgr->proposed_vcpis[i]) {
+			port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+			seq_printf(m, "vcpi %d: %d %d %d\n", i, port->port_num, port->vcpi.vcpi, port->vcpi.num_slots);
+		} else
+			seq_printf(m, "vcpi %d:unsed\n", i);
+	}
+	for (i = 0; i < mgr->max_payloads; i++) {
+		seq_printf(m, "payload %d: %d, %d, %d\n",
+			   i,
+			   mgr->payloads[i].payload_state,
+			   mgr->payloads[i].start_slot,
+			   mgr->payloads[i].num_slots);
+
+
+	}
+	mutex_unlock(&mgr->payload_lock);
+
+	mutex_lock(&mgr->lock);
+	if (mgr->mst_primary) {
+		u8 buf[64];
+		bool bret;
+		int ret;
+		ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
+		seq_printf(m, "dpcd: ");
+		for (i = 0; i < DP_RECEIVER_CAP_SIZE; i++)
+			seq_printf(m, "%02x ", buf[i]);
+		seq_printf(m, "\n");
+		ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
+		seq_printf(m, "faux/mst: ");
+		for (i = 0; i < 2; i++)
+			seq_printf(m, "%02x ", buf[i]);
+		seq_printf(m, "\n");
+		ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
+		seq_printf(m, "mst ctrl: ");
+		for (i = 0; i < 1; i++)
+			seq_printf(m, "%02x ", buf[i]);
+		seq_printf(m, "\n");
+
+		bret = dump_dp_payload_table(mgr, buf);
+		if (bret == true) {
+			seq_printf(m, "payload table: ");
+			for (i = 0; i < 63; i++)
+				seq_printf(m, "%02x ", buf[i]);
+			seq_printf(m, "\n");
+		}
+
+	}
+
+	mutex_unlock(&mgr->lock);
+
+}
+EXPORT_SYMBOL(drm_dp_mst_dump_topology);
+
+static void drm_dp_tx_work(struct work_struct *work)
+{
+	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
+
+	mutex_lock(&mgr->qlock);
+	if (mgr->tx_down_in_progress)
+		process_single_down_tx_qlock(mgr);
+	mutex_unlock(&mgr->qlock);
+}
+
+/**
+ * drm_dp_mst_topology_mgr_init - initialise a topology manager
+ * @mgr: manager struct to initialise
+ * @dev: device providing this structure - for i2c addition.
+ * @aux: DP helper aux channel to talk to this device
+ * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
+ * @max_payloads: maximum number of payloads this GPU can source
+ * @conn_base_id: the connector object ID the MST device is connected to.
+ *
+ * Return 0 for success, or negative error code on failure
+ */
+int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
+				 struct device *dev, struct drm_dp_aux *aux,
+				 int max_dpcd_transaction_bytes,
+				 int max_payloads, int conn_base_id)
+{
+	mutex_init(&mgr->lock);
+	mutex_init(&mgr->qlock);
+	mutex_init(&mgr->payload_lock);
+	INIT_LIST_HEAD(&mgr->tx_msg_upq);
+	INIT_LIST_HEAD(&mgr->tx_msg_downq);
+	INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
+	INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
+	init_waitqueue_head(&mgr->tx_waitq);
+	mgr->dev = dev;
+	mgr->aux = aux;
+	mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
+	mgr->max_payloads = max_payloads;
+	mgr->conn_base_id = conn_base_id;
+	mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL);
+	if (!mgr->payloads)
+		return -ENOMEM;
+	mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL);
+	if (!mgr->proposed_vcpis)
+		return -ENOMEM;
+	set_bit(0, &mgr->payload_mask);
+	test_calc_pbn_mode();
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
+
+/**
+ * drm_dp_mst_topology_mgr_destroy() - destroy topology manager.
+ * @mgr: manager to destroy
+ */
+void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
+{
+	mutex_lock(&mgr->payload_lock);
+	kfree(mgr->payloads);
+	mgr->payloads = NULL;
+	kfree(mgr->proposed_vcpis);
+	mgr->proposed_vcpis = NULL;
+	mutex_unlock(&mgr->payload_lock);
+	mgr->dev = NULL;
+	mgr->aux = NULL;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
+
+/* I2C device */
+static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+			       int num)
+{
+	struct drm_dp_aux *aux = adapter->algo_data;
+	struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux);
+	struct drm_dp_mst_branch *mstb;
+	struct drm_dp_mst_topology_mgr *mgr = port->mgr;
+	unsigned int i;
+	bool reading = false;
+	struct drm_dp_sideband_msg_req_body msg;
+	struct drm_dp_sideband_msg_tx *txmsg = NULL;
+	int ret;
+
+	mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+	if (!mstb)
+		return -EREMOTEIO;
+
+	/* construct i2c msg */
+	/* see if last msg is a read */
+	if (msgs[num - 1].flags & I2C_M_RD)
+		reading = true;
+
+	if (!reading) {
+		DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	msg.req_type = DP_REMOTE_I2C_READ;
+	msg.u.i2c_read.num_transactions = num - 1;
+	msg.u.i2c_read.port_number = port->port_num;
+	for (i = 0; i < num - 1; i++) {
+		msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr;
+		msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len;
+		msg.u.i2c_read.transactions[i].bytes = msgs[i].buf;
+	}
+	msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr;
+	msg.u.i2c_read.num_bytes_read = msgs[num - 1].len;
+
+	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+	if (!txmsg) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	txmsg->dst = mstb;
+	drm_dp_encode_sideband_req(&msg, txmsg);
+
+	drm_dp_queue_down_tx(mgr, txmsg);
+
+	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+	if (ret > 0) {
+
+		if (txmsg->reply.reply_type == 1) { /* got a NAK back */
+			ret = -EREMOTEIO;
+			goto out;
+		}
+		if (txmsg->reply.u.remote_i2c_read_ack.num_bytes != msgs[num - 1].len) {
+			ret = -EIO;
+			goto out;
+		}
+		memcpy(msgs[num - 1].buf, txmsg->reply.u.remote_i2c_read_ack.bytes, msgs[num - 1].len);
+		ret = num;
+	}
+out:
+	kfree(txmsg);
+	drm_dp_put_mst_branch_device(mstb);
+	return ret;
+}
+
+static u32 drm_dp_mst_i2c_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	       I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm drm_dp_mst_i2c_algo = {
+	.functionality = drm_dp_mst_i2c_functionality,
+	.master_xfer = drm_dp_mst_i2c_xfer,
+};
+
+/**
+ * drm_dp_mst_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
+ * @aux: DisplayPort AUX channel
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux)
+{
+	aux->ddc.algo = &drm_dp_mst_i2c_algo;
+	aux->ddc.algo_data = aux;
+	aux->ddc.retries = 3;
+
+	aux->ddc.class = I2C_CLASS_DDC;
+	aux->ddc.owner = THIS_MODULE;
+	aux->ddc.dev.parent = aux->dev;
+	aux->ddc.dev.of_node = aux->dev->of_node;
+
+	strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
+		sizeof(aux->ddc.name));
+
+	return i2c_add_adapter(&aux->ddc);
+}
+
+/**
+ * drm_dp_mst_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
+ * @aux: DisplayPort AUX channel
+ */
+static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux)
+{
+	i2c_del_adapter(&aux->ddc);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,31 +1,11 @@
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME		"mga"
- * #define DRIVER_DESC		"Matrox G200/G400"
- * #define DRIVER_DATE		"20001127"
- *
- * #define drm_x		mga_##x
- * \endcode
- */
-
 /*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
  *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
+ * Author Rickard E. (Rik) Faith <faith@valinux.com>
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -40,432 +20,906 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  */
 
 #include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mount.h>
 #include <linux/slab.h>
-#include <linux/export.h>
 #include <drm/drmP.h>
 #include <drm/drm_core.h>
+#include "drm_legacy.h"
 
+unsigned int drm_debug = 0;	/* 1 to enable debug output */
+EXPORT_SYMBOL(drm_debug);
 
-static int drm_version(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv);
+unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
 
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
 
-/** Ioctl table */
-static const struct drm_ioctl_desc drm_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
+/*
+ * Default to use monotonic timestamps for wait-for-vblank and page-flip
+ * complete events.
+ */
+unsigned int drm_timestamp_monotonic = 1;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
+MODULE_LICENSE("GPL and additional rights");
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
 
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+module_param_named(debug, drm_debug, int, 0600);
+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
+static DEFINE_SPINLOCK(drm_minor_lock);
+static struct idr drm_minors_idr;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
+struct class *drm_class;
+static struct dentry *drm_debugfs_root;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
+int drm_err(const char *func, const char *format, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	va_start(args, format);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+	vaf.fmt = format;
+	vaf.va = &args;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+	r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
+	va_end(args);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	return r;
+}
+EXPORT_SYMBOL(drm_err);
 
-#if __OS_HAS_AGP
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#endif
+void drm_ut_debug_printk(const char *function_name, const char *format, ...)
+{
+	struct va_format vaf;
+	va_list args;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	va_start(args, format);
+	vaf.fmt = format;
+	vaf.va = &args;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
+	printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+	va_end(args);
+}
+EXPORT_SYMBOL(drm_ut_debug_printk);
 
-	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+struct drm_master *drm_master_create(struct drm_minor *minor)
+{
+	struct drm_master *master;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	master = kzalloc(sizeof(*master), GFP_KERNEL);
+	if (!master)
+		return NULL;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	kref_init(&master->refcount);
+	spin_lock_init(&master->lock.spinlock);
+	init_waitqueue_head(&master->lock.lock_queue);
+	if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
+		kfree(master);
+		return NULL;
+	}
+	INIT_LIST_HEAD(&master->magicfree);
+	master->minor = minor;
 
-	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	return master;
+}
 
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-};
+struct drm_master *drm_master_get(struct drm_master *master)
+{
+	kref_get(&master->refcount);
+	return master;
+}
+EXPORT_SYMBOL(drm_master_get);
 
-#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
+static void drm_master_destroy(struct kref *kref)
+{
+	struct drm_master *master = container_of(kref, struct drm_master, refcount);
+	struct drm_magic_entry *pt, *next;
+	struct drm_device *dev = master->minor->dev;
+	struct drm_map_list *r_list, *list_temp;
 
-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
-	.owner = THIS_MODULE,
-	.open = drm_stub_open,
-	.llseek = noop_llseek,
-};
+	mutex_lock(&dev->struct_mutex);
+	if (dev->driver->master_destroy)
+		dev->driver->master_destroy(dev, master);
 
-static int __init drm_core_init(void)
+	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+		if (r_list->master == master) {
+			drm_rmmap_locked(dev, r_list->map);
+			r_list = NULL;
+		}
+	}
+
+	if (master->unique) {
+		kfree(master->unique);
+		master->unique = NULL;
+		master->unique_len = 0;
+	}
+
+	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
+		list_del(&pt->head);
+		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
+		kfree(pt);
+	}
+
+	drm_ht_remove(&master->magiclist);
+
+	mutex_unlock(&dev->struct_mutex);
+	kfree(master);
+}
+
+void drm_master_put(struct drm_master **master)
 {
-	int ret = -ENOMEM;
+	kref_put(&(*master)->refcount, drm_master_destroy);
+	*master = NULL;
+}
+EXPORT_SYMBOL(drm_master_put);
 
-	drm_global_init();
-	drm_connector_ida_init();
-	idr_init(&drm_minors_idr);
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	int ret = 0;
 
-	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-		goto err_p1;
+	mutex_lock(&dev->master_mutex);
+	if (file_priv->is_master)
+		goto out_unlock;
 
-	drm_class = drm_sysfs_create(THIS_MODULE, "drm");
-	if (IS_ERR(drm_class)) {
-		printk(KERN_ERR "DRM: Error creating drm class.\n");
-		ret = PTR_ERR(drm_class);
-		goto err_p2;
+	if (file_priv->minor->master) {
+		ret = -EINVAL;
+		goto out_unlock;
 	}
 
-	drm_debugfs_root = debugfs_create_dir("dri", NULL);
-	if (!drm_debugfs_root) {
-		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
-		ret = -1;
-		goto err_p3;
+	if (!file_priv->master) {
+		ret = -EINVAL;
+		goto out_unlock;
 	}
 
-	DRM_INFO("Initialized %s %d.%d.%d %s\n",
-		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-	return 0;
-err_p3:
-	drm_sysfs_destroy();
-err_p2:
-	unregister_chrdev(DRM_MAJOR, "drm");
+	file_priv->minor->master = drm_master_get(file_priv->master);
+	file_priv->is_master = 1;
+	if (dev->driver->master_set) {
+		ret = dev->driver->master_set(dev, file_priv, false);
+		if (unlikely(ret != 0)) {
+			file_priv->is_master = 0;
+			drm_master_put(&file_priv->minor->master);
+		}
+	}
 
-	idr_destroy(&drm_minors_idr);
-err_p1:
+out_unlock:
+	mutex_unlock(&dev->master_mutex);
 	return ret;
 }
 
-static void __exit drm_core_exit(void)
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
 {
-	debugfs_remove(drm_debugfs_root);
-	drm_sysfs_destroy();
+	int ret = -EINVAL;
 
-	unregister_chrdev(DRM_MAJOR, "drm");
+	mutex_lock(&dev->master_mutex);
+	if (!file_priv->is_master)
+		goto out_unlock;
 
-	drm_connector_ida_destroy();
-	idr_destroy(&drm_minors_idr);
-}
+	if (!file_priv->minor->master)
+		goto out_unlock;
 
-module_init(drm_core_init);
-module_exit(drm_core_exit);
+	ret = 0;
+	if (dev->driver->master_drop)
+		dev->driver->master_drop(dev, file_priv, false);
+	drm_master_put(&file_priv->minor->master);
+	file_priv->is_master = 0;
 
-/**
- * Copy and IOCTL return string to user space
+out_unlock:
+	mutex_unlock(&dev->master_mutex);
+	return ret;
+}
+
+/*
+ * DRM Minors
+ * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
+ * of them is represented by a drm_minor object. Depending on the capabilities
+ * of the device-driver, different interfaces are registered.
+ *
+ * Minors can be accessed via dev->$minor_name. This pointer is either
+ * NULL or a valid drm_minor pointer and stays valid as long as the device is
+ * valid. This means, DRM minors have the same life-time as the underlying
+ * device. However, this doesn't mean that the minor is active. Minors are
+ * registered and unregistered dynamically according to device-state.
  */
-static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
+
+static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
+					     unsigned int type)
 {
-	int len;
+	switch (type) {
+	case DRM_MINOR_LEGACY:
+		return &dev->primary;
+	case DRM_MINOR_RENDER:
+		return &dev->render;
+	case DRM_MINOR_CONTROL:
+		return &dev->control;
+	default:
+		return NULL;
+	}
+}
 
-	/* don't overflow userbuf */
-	len = strlen(value);
-	if (len > *buf_len)
-		len = *buf_len;
+static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
+{
+	struct drm_minor *minor;
+	unsigned long flags;
+	int r;
 
-	/* let userspace know exact length of driver value (which could be
-	 * larger than the userspace-supplied buffer) */
-	*buf_len = strlen(value);
+	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
+	if (!minor)
+		return -ENOMEM;
 
-	/* finally, try filling in the userbuf */
-	if (len && buf)
-		if (copy_to_user(buf, value, len))
-			return -EFAULT;
+	minor->type = type;
+	minor->dev = dev;
+
+	idr_preload(GFP_KERNEL);
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	r = idr_alloc(&drm_minors_idr,
+		      NULL,
+		      64 * type,
+		      64 * (type + 1),
+		      GFP_NOWAIT);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+	idr_preload_end();
+
+	if (r < 0)
+		goto err_free;
+
+	minor->index = r;
+
+	minor->kdev = drm_sysfs_minor_alloc(minor);
+	if (IS_ERR(minor->kdev)) {
+		r = PTR_ERR(minor->kdev);
+		goto err_index;
+	}
+
+	*drm_minor_get_slot(dev, type) = minor;
 	return 0;
+
+err_index:
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_remove(&drm_minors_idr, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+err_free:
+	kfree(minor);
+	return r;
+}
+
+static void drm_minor_free(struct drm_device *dev, unsigned int type)
+{
+	struct drm_minor **slot, *minor;
+	unsigned long flags;
+
+	slot = drm_minor_get_slot(dev, type);
+	minor = *slot;
+	if (!minor)
+		return;
+
+	drm_mode_group_destroy(&minor->mode_group);
+	put_device(minor->kdev);
+
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_remove(&drm_minors_idr, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+	kfree(minor);
+	*slot = NULL;
+}
+
+static int drm_minor_register(struct drm_device *dev, unsigned int type)
+{
+	struct drm_minor *minor;
+	unsigned long flags;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	minor = *drm_minor_get_slot(dev, type);
+	if (!minor)
+		return 0;
+
+	ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
+	if (ret) {
+		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
+		return ret;
+	}
+
+	ret = device_add(minor->kdev);
+	if (ret)
+		goto err_debugfs;
+
+	/* replace NULL with @minor so lookups will succeed from now on */
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_replace(&drm_minors_idr, minor, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+	DRM_DEBUG("new minor registered %d\n", minor->index);
+	return 0;
+
+err_debugfs:
+	drm_debugfs_cleanup(minor);
+	return ret;
+}
+
+static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
+{
+	struct drm_minor *minor;
+	unsigned long flags;
+
+	minor = *drm_minor_get_slot(dev, type);
+	if (!minor || !device_is_registered(minor->kdev))
+		return;
+
+	/* replace @minor with NULL so lookups will fail from now on */
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	idr_replace(&drm_minors_idr, NULL, minor->index);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+	device_del(minor->kdev);
+	dev_set_drvdata(minor->kdev, NULL); /* safety belt */
+	drm_debugfs_cleanup(minor);
 }
 
 /**
- * Get version information
+ * drm_minor_acquire - Acquire a DRM minor
+ * @minor_id: Minor ID of the DRM-minor
  *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_version structure.
- * \return zero on success or negative number on failure.
+ * 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().
  *
- * Fills in the version information in \p arg.
+ * 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.
  */
-static int drm_version(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
+struct drm_minor *drm_minor_acquire(unsigned int minor_id)
 {
-	struct drm_version *version = data;
-	int err;
+	struct drm_minor *minor;
+	unsigned long flags;
 
-	version->version_major = dev->driver->major;
-	version->version_minor = dev->driver->minor;
-	version->version_patchlevel = dev->driver->patchlevel;
-	err = drm_copy_field(version->name, &version->name_len,
-			dev->driver->name);
-	if (!err)
-		err = drm_copy_field(version->date, &version->date_len,
-				dev->driver->date);
-	if (!err)
-		err = drm_copy_field(version->desc, &version->desc_len,
-				dev->driver->desc);
+	spin_lock_irqsave(&drm_minor_lock, flags);
+	minor = idr_find(&drm_minors_idr, minor_id);
+	if (minor)
+		drm_dev_ref(minor->dev);
+	spin_unlock_irqrestore(&drm_minor_lock, flags);
 
-	return err;
+	if (!minor) {
+		return ERR_PTR(-ENODEV);
+	} else if (drm_device_is_unplugged(minor->dev)) {
+		drm_dev_unref(minor->dev);
+		return ERR_PTR(-ENODEV);
+	}
+
+	return minor;
 }
 
 /**
- * drm_ioctl_permit - Check ioctl permissions against caller
+ * drm_minor_release - Release DRM minor
+ * @minor: Pointer to DRM minor object
  *
- * @flags: ioctl permission flags.
- * @file_priv: Pointer to struct drm_file identifying the caller.
+ * Release a minor that was previously acquired via drm_minor_acquire().
+ */
+void drm_minor_release(struct drm_minor *minor)
+{
+	drm_dev_unref(minor->dev);
+}
+
+/**
+ * drm_put_dev - Unregister and release a DRM device
+ * @dev: DRM device
  *
- * Checks whether the caller is allowed to run an ioctl with the
- * indicated permissions. If so, returns zero. Otherwise returns an
- * error code suitable for ioctl return.
+ * Called at module unload time or when a PCI device is unplugged.
+ *
+ * Use of this function is discouraged. It will eventually go away completely.
+ * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
+ *
+ * Cleans up all DRM device, calling drm_lastclose().
  */
-static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+void drm_put_dev(struct drm_device *dev)
 {
-	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
-	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
-		return -EACCES;
+	DRM_DEBUG("\n");
 
-	/* AUTH is only for authenticated or render client */
-	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
-		     !file_priv->authenticated))
-		return -EACCES;
+	if (!dev) {
+		DRM_ERROR("cleanup called no dev\n");
+		return;
+	}
 
-	/* MASTER is only for master or control clients */
-	if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
-		     !drm_is_control_client(file_priv)))
-		return -EACCES;
+	drm_dev_unregister(dev);
+	drm_dev_unref(dev);
+}
+EXPORT_SYMBOL(drm_put_dev);
 
-	/* Control clients must be explicitly allowed */
-	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
-		     drm_is_control_client(file_priv)))
-		return -EACCES;
+void drm_unplug_dev(struct drm_device *dev)
+{
+	/* for a USB device */
+	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+	drm_minor_unregister(dev, DRM_MINOR_RENDER);
+	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
 
-	/* Render clients must be explicitly allowed */
-	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
-		     drm_is_render_client(file_priv)))
-		return -EACCES;
+	mutex_lock(&drm_global_mutex);
 
-	return 0;
+	drm_device_set_unplugged(dev);
+
+	if (dev->open_count == 0) {
+		drm_put_dev(dev);
+	}
+	mutex_unlock(&drm_global_mutex);
 }
+EXPORT_SYMBOL(drm_unplug_dev);
 
-/**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+/*
+ * DRM internal mount
+ * We want to be able to allocate our own "struct address_space" to control
+ * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow
+ * stand-alone address_space objects, so we need an underlying inode. As there
+ * is no way to allocate an independent inode easily, we need a fake internal
+ * VFS mount-point.
  *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
+ * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free()
+ * frees it again. You are allowed to use iget() and iput() to get references to
+ * the inode. But each drm_fs_inode_new() call must be paired with exactly one
+ * drm_fs_inode_free() call (which does not have to be the last iput()).
+ * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it
+ * between multiple inode-users. You could, technically, call
+ * iget() + drm_fs_inode_free() directly after alloc and sometime later do an
+ * iput(), but this way you'd end up with a new vfsmount for each inode.
  */
-long drm_ioctl(struct file *filp,
-	      unsigned int cmd, unsigned long arg)
+
+static int drm_fs_cnt;
+static struct vfsmount *drm_fs_mnt;
+
+static const struct dentry_operations drm_fs_dops = {
+	.d_dname	= simple_dname,
+};
+
+static const struct super_operations drm_fs_sops = {
+	.statfs		= simple_statfs,
+};
+
+static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
+				   const char *dev_name, void *data)
 {
-	struct drm_file *file_priv = filp->private_data;
-	struct drm_device *dev;
-	const struct drm_ioctl_desc *ioctl = NULL;
-	drm_ioctl_t *func;
-	unsigned int nr = DRM_IOCTL_NR(cmd);
-	int retcode = -EINVAL;
-	char stack_kdata[128];
-	char *kdata = NULL;
-	unsigned int usize, asize;
+	return mount_pseudo(fs_type,
+			    "drm:",
+			    &drm_fs_sops,
+			    &drm_fs_dops,
+			    0x010203ff);
+}
 
-	dev = file_priv->minor->dev;
+static struct file_system_type drm_fs_type = {
+	.name		= "drm",
+	.owner		= THIS_MODULE,
+	.mount		= drm_fs_mount,
+	.kill_sb	= kill_anon_super,
+};
 
-	if (drm_device_is_unplugged(dev))
-		return -ENODEV;
+static struct inode *drm_fs_inode_new(void)
+{
+	struct inode *inode;
+	int r;
 
-	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
-	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
-		goto err_i1;
-	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
-	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
-		u32 drv_size;
-		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
-		drv_size = _IOC_SIZE(ioctl->cmd_drv);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
-		cmd = ioctl->cmd_drv;
+	r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
+	if (r < 0) {
+		DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
+		return ERR_PTR(r);
 	}
-	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
-		u32 drv_size;
 
-		ioctl = &drm_ioctls[nr];
+	inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
+	if (IS_ERR(inode))
+		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
 
-		drv_size = _IOC_SIZE(ioctl->cmd);
-		usize = asize = _IOC_SIZE(cmd);
-		if (drv_size > asize)
-			asize = drv_size;
+	return inode;
+}
 
-		cmd = ioctl->cmd;
-	} else
-		goto err_i1;
+static void drm_fs_inode_free(struct inode *inode)
+{
+	if (inode) {
+		iput(inode);
+		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
+	}
+}
 
-	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
-		  task_pid_nr(current),
-		  (long)old_encode_dev(file_priv->minor->kdev->devt),
-		  file_priv->authenticated, ioctl->name);
+/**
+ * drm_dev_alloc - Allocate new DRM device
+ * @driver: DRM driver to allocate device for
+ * @parent: Parent device object
+ *
+ * Allocate and initialize a new DRM device. No device registration is done.
+ * Call drm_dev_register() to advertice the device to user space and register it
+ * with other core subsystems.
+ *
+ * The initial ref-count of the object is 1. Use drm_dev_ref() and
+ * drm_dev_unref() to take and drop further ref-counts.
+ *
+ * RETURNS:
+ * Pointer to new DRM device, or NULL if out of memory.
+ */
+struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+				 struct device *parent)
+{
+	struct drm_device *dev;
+	int ret;
 
-	/* Do not trust userspace, use our own definition */
-	func = ioctl->func;
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
 
-	if (unlikely(!func)) {
-		DRM_DEBUG("no function\n");
-		retcode = -EINVAL;
-		goto err_i1;
+	kref_init(&dev->ref);
+	dev->dev = parent;
+	dev->driver = driver;
+
+	INIT_LIST_HEAD(&dev->filelist);
+	INIT_LIST_HEAD(&dev->ctxlist);
+	INIT_LIST_HEAD(&dev->vmalist);
+	INIT_LIST_HEAD(&dev->maplist);
+	INIT_LIST_HEAD(&dev->vblank_event_list);
+
+	spin_lock_init(&dev->buf_lock);
+	spin_lock_init(&dev->event_lock);
+	mutex_init(&dev->struct_mutex);
+	mutex_init(&dev->ctxlist_mutex);
+	mutex_init(&dev->master_mutex);
+
+	dev->anon_inode = drm_fs_inode_new();
+	if (IS_ERR(dev->anon_inode)) {
+		ret = PTR_ERR(dev->anon_inode);
+		DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
+		goto err_free;
 	}
 
-	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
-	if (unlikely(retcode))
-		goto err_i1;
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
+		if (ret)
+			goto err_minors;
+	}
 
-	if (cmd & (IOC_IN | IOC_OUT)) {
-		if (asize <= sizeof(stack_kdata)) {
-			kdata = stack_kdata;
-		} else {
-			kdata = kmalloc(asize, GFP_KERNEL);
-			if (!kdata) {
-				retcode = -ENOMEM;
-				goto err_i1;
-			}
-		}
-		if (asize > usize)
-			memset(kdata + usize, 0, asize - usize);
+	if (drm_core_check_feature(dev, DRIVER_RENDER)) {
+		ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
+		if (ret)
+			goto err_minors;
 	}
 
-	if (cmd & IOC_IN) {
-		if (copy_from_user(kdata, (void __user *)arg,
-				   usize) != 0) {
-			retcode = -EFAULT;
-			goto err_i1;
+	ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
+	if (ret)
+		goto err_minors;
+
+	if (drm_ht_create(&dev->map_hash, 12))
+		goto err_minors;
+
+	ret = drm_legacy_ctxbitmap_init(dev);
+	if (ret) {
+		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+		goto err_ht;
+	}
+
+	if (driver->driver_features & DRIVER_GEM) {
+		ret = drm_gem_init(dev);
+		if (ret) {
+			DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
+			goto err_ctxbitmap;
 		}
-	} else if (cmd & IOC_OUT) {
-		memset(kdata, 0, usize);
 	}
 
-	if (ioctl->flags & DRM_UNLOCKED)
-		retcode = func(dev, kdata, file_priv);
-	else {
-		mutex_lock(&drm_global_mutex);
-		retcode = func(dev, kdata, file_priv);
-		mutex_unlock(&drm_global_mutex);
+	return dev;
+
+err_ctxbitmap:
+	drm_legacy_ctxbitmap_cleanup(dev);
+err_ht:
+	drm_ht_remove(&dev->map_hash);
+err_minors:
+	drm_minor_free(dev, DRM_MINOR_LEGACY);
+	drm_minor_free(dev, DRM_MINOR_RENDER);
+	drm_minor_free(dev, DRM_MINOR_CONTROL);
+	drm_fs_inode_free(dev->anon_inode);
+err_free:
+	mutex_destroy(&dev->master_mutex);
+	kfree(dev);
+	return NULL;
+}
+EXPORT_SYMBOL(drm_dev_alloc);
+
+static void drm_dev_release(struct kref *ref)
+{
+	struct drm_device *dev = container_of(ref, struct drm_device, ref);
+
+	if (dev->driver->driver_features & DRIVER_GEM)
+		drm_gem_destroy(dev);
+
+	drm_legacy_ctxbitmap_cleanup(dev);
+	drm_ht_remove(&dev->map_hash);
+	drm_fs_inode_free(dev->anon_inode);
+
+	drm_minor_free(dev, DRM_MINOR_LEGACY);
+	drm_minor_free(dev, DRM_MINOR_RENDER);
+	drm_minor_free(dev, DRM_MINOR_CONTROL);
+
+	mutex_destroy(&dev->master_mutex);
+	kfree(dev->unique);
+	kfree(dev);
+}
+
+/**
+ * drm_dev_ref - Take reference of a DRM device
+ * @dev: device to take reference of or NULL
+ *
+ * This increases the ref-count of @dev by one. You *must* already own a
+ * reference when calling this. Use drm_dev_unref() to drop this reference
+ * again.
+ *
+ * This function never fails. However, this function does not provide *any*
+ * guarantee whether the device is alive or running. It only provides a
+ * reference to the object and the memory associated with it.
+ */
+void drm_dev_ref(struct drm_device *dev)
+{
+	if (dev)
+		kref_get(&dev->ref);
+}
+EXPORT_SYMBOL(drm_dev_ref);
+
+/**
+ * drm_dev_unref - Drop reference of a DRM device
+ * @dev: device to drop reference of or NULL
+ *
+ * This decreases the ref-count of @dev by one. The device is destroyed if the
+ * ref-count drops to zero.
+ */
+void drm_dev_unref(struct drm_device *dev)
+{
+	if (dev)
+		kref_put(&dev->ref, drm_dev_release);
+}
+EXPORT_SYMBOL(drm_dev_unref);
+
+/**
+ * drm_dev_register - Register DRM device
+ * @dev: Device to register
+ * @flags: Flags passed to the driver's .load() function
+ *
+ * Register the DRM device @dev with the system, advertise device to user-space
+ * and start normal device operation. @dev must be allocated via drm_dev_alloc()
+ * previously.
+ *
+ * Never call this twice on any device!
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int drm_dev_register(struct drm_device *dev, unsigned long flags)
+{
+	int ret;
+
+	mutex_lock(&drm_global_mutex);
+
+	ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
+	if (ret)
+		goto err_minors;
+
+	ret = drm_minor_register(dev, DRM_MINOR_RENDER);
+	if (ret)
+		goto err_minors;
+
+	ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
+	if (ret)
+		goto err_minors;
+
+	if (dev->driver->load) {
+		ret = dev->driver->load(dev, flags);
+		if (ret)
+			goto err_minors;
 	}
 
-	if (cmd & IOC_OUT) {
-		if (copy_to_user((void __user *)arg, kdata,
-				 usize) != 0)
-			retcode = -EFAULT;
+	/* setup grouping for legacy outputs */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = drm_mode_group_init_legacy_group(dev,
+				&dev->primary->mode_group);
+		if (ret)
+			goto err_unload;
 	}
 
-      err_i1:
-	if (!ioctl)
-		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
-			  task_pid_nr(current),
-			  (long)old_encode_dev(file_priv->minor->kdev->devt),
-			  file_priv->authenticated, cmd, nr);
+	ret = 0;
+	goto out_unlock;
 
-	if (kdata != stack_kdata)
-		kfree(kdata);
-	if (retcode)
-		DRM_DEBUG("ret = %d\n", retcode);
-	return retcode;
+err_unload:
+	if (dev->driver->unload)
+		dev->driver->unload(dev);
+err_minors:
+	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+	drm_minor_unregister(dev, DRM_MINOR_RENDER);
+	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
+out_unlock:
+	mutex_unlock(&drm_global_mutex);
+	return ret;
 }
-EXPORT_SYMBOL(drm_ioctl);
+EXPORT_SYMBOL(drm_dev_register);
 
 /**
- * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ * drm_dev_unregister - Unregister DRM device
+ * @dev: Device to unregister
  *
- * @nr: Ioctl number.
- * @flags: Where to return the ioctl permission flags
+ * Unregister the DRM device from the system. This does the reverse of
+ * drm_dev_register() but does not deallocate the device. The caller must call
+ * drm_dev_unref() to drop their final reference.
  */
-bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+void drm_dev_unregister(struct drm_device *dev)
 {
-	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
-	    (nr < DRM_COMMAND_BASE)) {
-		*flags = drm_ioctls[nr].flags;
-		return true;
+	struct drm_map_list *r_list, *list_temp;
+
+	drm_lastclose(dev);
+
+	if (dev->driver->unload)
+		dev->driver->unload(dev);
+
+	if (dev->agp)
+		drm_pci_agp_destroy(dev);
+
+	drm_vblank_cleanup(dev);
+
+	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+		drm_rmmap(dev, r_list->map);
+
+	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+	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
+ * @fmt: format string for unique name
+ *
+ * Sets the unique name of a DRM device using the specified format string and
+ * a variable list of arguments. 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 *fmt, ...)
+{
+	va_list ap;
+
+	kfree(dev->unique);
+
+	va_start(ap, fmt);
+	dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
+	va_end(ap);
+
+	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
+ * available to drivers. Once setup, drivers can probe their respective
+ * devices.
+ * Currently, core management includes:
+ *  - The "DRM-Global" key/value database
+ *  - Global ID management for connectors
+ *  - DRM major number allocation
+ *  - DRM minor management
+ *  - DRM sysfs class
+ *  - DRM debugfs root
+ *
+ * Furthermore, the DRM core provides dynamic char-dev lookups. For each
+ * interface registered on a DRM device, you can request minor numbers from DRM
+ * core. DRM core takes care of major-number management and char-dev
+ * registration. A stub ->open() callback forwards any open() requests to the
+ * registered minor.
+ */
+
+static int drm_stub_open(struct inode *inode, struct file *filp)
+{
+	const struct file_operations *new_fops;
+	struct drm_minor *minor;
+	int err;
+
+	DRM_DEBUG("\n");
+
+	mutex_lock(&drm_global_mutex);
+	minor = drm_minor_acquire(iminor(inode));
+	if (IS_ERR(minor)) {
+		err = PTR_ERR(minor);
+		goto out_unlock;
 	}
 
-	return false;
+	new_fops = fops_get(minor->dev->driver->fops);
+	if (!new_fops) {
+		err = -ENODEV;
+		goto out_release;
+	}
+
+	replace_fops(filp, new_fops);
+	if (filp->f_op->open)
+		err = filp->f_op->open(inode, filp);
+	else
+		err = 0;
+
+out_release:
+	drm_minor_release(minor);
+out_unlock:
+	mutex_unlock(&drm_global_mutex);
+	return err;
 }
-EXPORT_SYMBOL(drm_ioctl_flags);
+
+static const struct file_operations drm_stub_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_stub_open,
+	.llseek = noop_llseek,
+};
+
+static int __init drm_core_init(void)
+{
+	int ret = -ENOMEM;
+
+	drm_global_init();
+	drm_connector_ida_init();
+	idr_init(&drm_minors_idr);
+
+	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+		goto err_p1;
+
+	drm_class = drm_sysfs_create(THIS_MODULE, "drm");
+	if (IS_ERR(drm_class)) {
+		printk(KERN_ERR "DRM: Error creating drm class.\n");
+		ret = PTR_ERR(drm_class);
+		goto err_p2;
+	}
+
+	drm_debugfs_root = debugfs_create_dir("dri", NULL);
+	if (!drm_debugfs_root) {
+		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
+		ret = -1;
+		goto err_p3;
+	}
+
+	DRM_INFO("Initialized %s %d.%d.%d %s\n",
+		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+	return 0;
+err_p3:
+	drm_sysfs_destroy();
+err_p2:
+	unregister_chrdev(DRM_MAJOR, "drm");
+
+	idr_destroy(&drm_minors_idr);
+err_p1:
+	return ret;
+}
+
+static void __exit drm_core_exit(void)
+{
+	debugfs_remove(drm_debugfs_root);
+	drm_sysfs_destroy();
+
+	unregister_chrdev(DRM_MAJOR, "drm");
+
+	drm_connector_ida_destroy();
+	idr_destroy(&drm_minors_idr);
+}
+
+module_init(drm_core_init);
+module_exit(drm_core_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_edid.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_edid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_edid.c	2014-09-28 17:29:07.000000000 -0400
@@ -3305,6 +3305,7 @@ struct drm_connector *drm_select_eld(str
 	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));
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 		if (connector->encoder == encoder && connector->eld[0])
@@ -3775,8 +3776,14 @@ drm_hdmi_avi_infoframe_from_display_mode
 
 	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 
-	/* Populate picture aspect ratio from CEA mode list */
-	if (frame->video_code > 0)
+	/*
+	 * Populate picture aspect ratio from either
+	 * user input (if specified) or from the CEA mode list.
+	 */
+	if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_4_3 ||
+		mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_16_9)
+		frame->picture_aspect = mode->picture_aspect_ratio;
+	else if (frame->video_code > 0)
 		frame->picture_aspect = drm_get_cea_aspect_ratio(
 						frame->video_code);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_fb_cma_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fb_cma_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -327,7 +327,7 @@ err_drm_gem_cma_free_object:
 	return ret;
 }
 
-static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
 	.fb_probe = drm_fbdev_cma_create,
 };
 
@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init
 		return ERR_PTR(-ENOMEM);
 	}
 
-	fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
 	helper = &fbdev_cma->fb_helper;
 
+	drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
+
 	ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
 	if (ret < 0) {
 		dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_fb_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fb_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list);
  * helper functions used by many drivers to implement the kernel mode setting
  * interfaces.
  *
- * Initialization is done as a three-step process with drm_fb_helper_init(),
- * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config().
- * Drivers with fancier requirements than the default behaviour can override the
- * second step with their own code.  Teardown is done with drm_fb_helper_fini().
+ * Initialization is done as a four-step process with drm_fb_helper_prepare(),
+ * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
+ * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
+ * default behaviour can override the third step with their own code.
+ * Teardown is done with drm_fb_helper_fini().
  *
  * At runtime drivers should restore the fbdev console by calling
  * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
@@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list);
  *
  * All other functions exported by the fb helper library can be used to
  * implement the fbdev driver interface by the driver.
+ *
+ * It is possible, though perhaps somewhat tricky, to implement race-free
+ * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
+ * helper must be called first to initialize the minimum required to make
+ * hotplug detection work. Drivers also need to make sure to properly set up
+ * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
+ * it is safe to enable interrupts and start processing hotplug events. At the
+ * same time, drivers should initialize all modeset objects such as CRTCs,
+ * encoders and connectors. To finish up the fbdev helper initialization, the
+ * drm_fb_helper_init() function is called. To probe for all attached displays
+ * and set up an initial configuration using the detected hardware, drivers
+ * should call drm_fb_helper_single_add_all_connectors() followed by
+ * drm_fb_helper_initial_config().
  */
 
 /**
@@ -105,6 +119,58 @@ fail:
 }
 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
 
+int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector)
+{
+	struct drm_fb_helper_connector **temp;
+	struct drm_fb_helper_connector *fb_helper_connector;
+
+	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
+	if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
+		temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
+		if (!temp)
+			return -ENOMEM;
+
+		fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1;
+		fb_helper->connector_info = temp;
+	}
+
+
+	fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
+	if (!fb_helper_connector)
+		return -ENOMEM;
+
+	fb_helper_connector->connector = connector;
+	fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
+	return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
+
+int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
+				       struct drm_connector *connector)
+{
+	struct drm_fb_helper_connector *fb_helper_connector;
+	int i, j;
+
+	WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
+
+	for (i = 0; i < fb_helper->connector_count; i++) {
+		if (fb_helper->connector_info[i]->connector == connector)
+			break;
+	}
+
+	if (i == fb_helper->connector_count)
+		return -EINVAL;
+	fb_helper_connector = fb_helper->connector_info[i];
+
+	for (j = i + 1; j < fb_helper->connector_count; j++) {
+		fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
+	}
+	fb_helper->connector_count--;
+	kfree(fb_helper_connector);
+	return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
+
 static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
 {
 	struct drm_fb_helper_connector *fb_helper_conn;
@@ -199,9 +265,6 @@ int drm_fb_helper_debug_enter(struct fb_
 	struct drm_crtc_helper_funcs *funcs;
 	int i;
 
-	if (list_empty(&kernel_fb_helper_list))
-		return false;
-
 	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
 		for (i = 0; i < helper->crtc_count; i++) {
 			struct drm_mode_set *mode_set =
@@ -531,6 +594,24 @@ static void drm_fb_helper_crtc_free(stru
 }
 
 /**
+ * drm_fb_helper_prepare - setup a drm_fb_helper structure
+ * @dev: DRM device
+ * @helper: driver-allocated fbdev helper structure to set up
+ * @funcs: pointer to structure of functions associate with this helper
+ *
+ * Sets up the bare minimum to make the framebuffer helper usable. This is
+ * useful to implement race-free initialization of the polling helpers.
+ */
+void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
+			   const struct drm_fb_helper_funcs *funcs)
+{
+	INIT_LIST_HEAD(&helper->kernel_fb_list);
+	helper->funcs = funcs;
+	helper->dev = dev;
+}
+EXPORT_SYMBOL(drm_fb_helper_prepare);
+
+/**
  * drm_fb_helper_init - initialize a drm_fb_helper structure
  * @dev: drm device
  * @fb_helper: driver-allocated fbdev helper structure to initialize
@@ -542,8 +623,7 @@ static void drm_fb_helper_crtc_free(stru
  * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
  * to allow driver writes more control over the exact init sequence.
  *
- * Drivers must set fb_helper->funcs before calling
- * drm_fb_helper_initial_config().
+ * Drivers must call drm_fb_helper_prepare() before calling this function.
  *
  * RETURNS:
  * Zero if everything went ok, nonzero otherwise.
@@ -558,10 +638,6 @@ int drm_fb_helper_init(struct drm_device
 	if (!max_conn_count)
 		return -EINVAL;
 
-	fb_helper->dev = dev;
-
-	INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
-
 	fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
 	if (!fb_helper->crtc_info)
 		return -ENOMEM;
@@ -572,6 +648,7 @@ int drm_fb_helper_init(struct drm_device
 		kfree(fb_helper->crtc_info);
 		return -ENOMEM;
 	}
+	fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
 	fb_helper->connector_count = 0;
 
 	for (i = 0; i < crtc_count; i++) {
@@ -1056,7 +1133,6 @@ void drm_fb_helper_fill_fix(struct fb_in
 	info->fix.ypanstep = 1; /* doing it in hw */
 	info->fix.ywrapstep = 0;
 	info->fix.accel = FB_ACCEL_NONE;
-	info->fix.type_aux = 0;
 
 	info->fix.line_length = pitch;
 	return;
@@ -1613,8 +1689,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_conf
  * either the output polling work or a work item launched from the driver's
  * hotplug interrupt).
  *
- * Note that the driver must ensure that this is only called _after_ the fb has
- * been fully set up, i.e. after the call to drm_fb_helper_initial_config.
+ * Note that drivers may call this even before calling
+ * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
+ * for a race-free fbcon setup and will make sure that the fbdev emulation will
+ * not miss any hotplug events.
  *
  * RETURNS:
  * 0 on success and a non-zero error code otherwise.
@@ -1624,11 +1702,8 @@ int drm_fb_helper_hotplug_event(struct d
 	struct drm_device *dev = fb_helper->dev;
 	u32 max_width, max_height;
 
-	if (!fb_helper->fb)
-		return 0;
-
 	mutex_lock(&fb_helper->dev->mode_config.mutex);
-	if (!drm_fb_helper_is_bound(fb_helper)) {
+	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
 		fb_helper->delayed_hotplug = true;
 		mutex_unlock(&fb_helper->dev->mode_config.mutex);
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_fops.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fops.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_fops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_fops.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include "drm_legacy.h"
 
 /* from BKL pushdown */
 DEFINE_MUTEX(drm_global_mutex);
@@ -112,55 +113,12 @@ err_undo:
 EXPORT_SYMBOL(drm_open);
 
 /**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
-	struct drm_device *dev;
-	struct drm_minor *minor;
-	int err = -ENODEV;
-	const struct file_operations *new_fops;
-
-	DRM_DEBUG("\n");
-
-	mutex_lock(&drm_global_mutex);
-	minor = drm_minor_acquire(iminor(inode));
-	if (IS_ERR(minor))
-		goto out_unlock;
-
-	dev = minor->dev;
-	new_fops = fops_get(dev->driver->fops);
-	if (!new_fops)
-		goto out_release;
-
-	replace_fops(filp, new_fops);
-	if (filp->f_op->open)
-		err = filp->f_op->open(inode, filp);
-
-out_release:
-	drm_minor_release(minor);
-out_unlock:
-	mutex_unlock(&drm_global_mutex);
-	return err;
-}
-
-/**
  * Check whether DRI will run on this CPU.
  *
  * \return non-zero if the DRI will run on this CPU, or zero otherwise.
  */
 static int drm_cpu_valid(void)
 {
-#if defined(__i386__)
-	if (boot_cpu_data.x86 == 3)
-		return 0;	/* No cmpxchg on a 386 */
-#endif
 #if defined(__sparc__) && !defined(__sparc_v9__)
 	return 0;		/* No cmpxchg before v9 sparc. */
 #endif
@@ -203,8 +161,7 @@ static int drm_open_helper(struct file *
 	priv->minor = minor;
 
 	/* for compatibility root is always authenticated */
-	priv->always_authenticated = capable(CAP_SYS_ADMIN);
-	priv->authenticated = priv->always_authenticated;
+	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count = 0;
 
 	INIT_LIST_HEAD(&priv->lhead);
@@ -429,6 +386,10 @@ int drm_release(struct inode *inode, str
 
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
+	mutex_lock(&dev->struct_mutex);
+	list_del(&file_priv->lhead);
+	mutex_unlock(&dev->struct_mutex);
+
 	if (dev->driver->preclose)
 		dev->driver->preclose(dev, file_priv);
 
@@ -461,44 +422,18 @@ int drm_release(struct inode *inode, str
 	if (dev->driver->driver_features & DRIVER_GEM)
 		drm_gem_release(dev, file_priv);
 
-	mutex_lock(&dev->ctxlist_mutex);
-	if (!list_empty(&dev->ctxlist)) {
-		struct drm_ctx_list *pos, *n;
-
-		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-			if (pos->tag == file_priv &&
-			    pos->handle != DRM_KERNEL_CONTEXT) {
-				if (dev->driver->context_dtor)
-					dev->driver->context_dtor(dev,
-								  pos->handle);
-
-				drm_ctxbitmap_free(dev, pos->handle);
-
-				list_del(&pos->head);
-				kfree(pos);
-			}
-		}
-	}
-	mutex_unlock(&dev->ctxlist_mutex);
+	drm_legacy_ctxbitmap_flush(dev, file_priv);
 
 	mutex_lock(&dev->master_mutex);
 
 	if (file_priv->is_master) {
 		struct drm_master *master = file_priv->master;
-		struct drm_file *temp;
-
-		mutex_lock(&dev->struct_mutex);
-		list_for_each_entry(temp, &dev->filelist, lhead) {
-			if ((temp->master == file_priv->master) &&
-			    (temp != file_priv))
-				temp->authenticated = temp->always_authenticated;
-		}
 
 		/**
 		 * Since the master is disappearing, so is the
 		 * possibility to lock.
 		 */
-
+		mutex_lock(&dev->struct_mutex);
 		if (master->lock.hw_lock) {
 			if (dev->sigdata.lock == master->lock.hw_lock)
 				dev->sigdata.lock = NULL;
@@ -522,10 +457,6 @@ int drm_release(struct inode *inode, str
 	file_priv->is_master = 0;
 	mutex_unlock(&dev->master_mutex);
 
-	mutex_lock(&dev->struct_mutex);
-	list_del(&file_priv->lhead);
-	mutex_unlock(&dev->struct_mutex);
-
 	if (dev->driver->postclose)
 		dev->driver->postclose(dev, file_priv);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -441,18 +441,31 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset
  * drm_gem_get_pages - helper to allocate backing pages for a GEM object
  * from shmem
  * @obj: obj in question
- * @gfpmask: gfp mask of requested pages
+ *
+ * This reads the page-array of the shmem-backing storage of the given gem
+ * object. An array of pages is returned. If a page is not allocated or
+ * swapped-out, this will allocate/swap-in the required pages. Note that the
+ * whole object is covered by the page-array and pinned in memory.
+ *
+ * Use drm_gem_put_pages() to release the array and unpin all pages.
+ *
+ * This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()).
+ * If you require other GFP-masks, you have to do those allocations yourself.
+ *
+ * Note that you are not allowed to change gfp-zones during runtime. That is,
+ * shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as
+ * set during initialization. If you have special zone constraints, set them
+ * after drm_gem_init_object() via mapping_set_gfp_mask(). shmem-core takes care
+ * to keep pages in the required zone during swap-in.
  */
-struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
+struct page **drm_gem_get_pages(struct drm_gem_object *obj)
 {
-	struct inode *inode;
 	struct address_space *mapping;
 	struct page *p, **pages;
 	int i, npages;
 
 	/* This is the shared memory object that backs the GEM resource */
-	inode = file_inode(obj->filp);
-	mapping = inode->i_mapping;
+	mapping = file_inode(obj->filp)->i_mapping;
 
 	/* We already BUG_ON() for non-page-aligned sizes in
 	 * drm_gem_object_init(), so we should never hit this unless
@@ -466,10 +479,8 @@ struct page **drm_gem_get_pages(struct d
 	if (pages == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	gfpmask |= mapping_gfp_mask(mapping);
-
 	for (i = 0; i < npages; i++) {
-		p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
+		p = shmem_read_mapping_page(mapping, i);
 		if (IS_ERR(p))
 			goto fail;
 		pages[i] = p;
@@ -479,7 +490,7 @@ struct page **drm_gem_get_pages(struct d
 		 * __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping)
 		 * so shmem can relocate pages during swapin if required.
 		 */
-		BUG_ON((gfpmask & __GFP_DMA32) &&
+		BUG_ON((mapping_gfp_mask(mapping) & __GFP_DMA32) &&
 				(page_to_pfn(p) >= 0x00100000UL));
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_gem_cma_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_gem_cma_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_gem_cma_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_gem_cma_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -327,7 +327,7 @@ drm_gem_cma_prime_import_sg_table(struct
 	/* Create a CMA GEM buffer. */
 	cma_obj = __drm_gem_cma_create(dev, size);
 	if (IS_ERR(cma_obj))
-		return ERR_PTR(PTR_ERR(cma_obj));
+		return ERR_CAST(cma_obj);
 
 	cma_obj->paddr = sg_dma_address(sgt->sgl);
 	cma_obj->sgt = sgt;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_hashtab.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_hashtab.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_hashtab.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_hashtab.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,7 @@ int drm_ht_insert_item(struct drm_open_h
 		parent = &entry->head;
 	}
 	if (parent) {
-		hlist_add_after_rcu(parent, &item->head);
+		hlist_add_behind_rcu(&item->head, parent);
 	} else {
 		hlist_add_head_rcu(&item->head, h_list);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_info.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_info.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_info.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_info.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, vo
 				   i,
 				   dma->bufs[i].buf_size,
 				   dma->bufs[i].buf_count,
-				   atomic_read(&dma->bufs[i].freelist.count),
+				   0,
 				   dma->bufs[i].seg_count,
 				   seg_pages,
 				   seg_pages * PAGE_SIZE / 1024);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_ioctl.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_ioctl.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,11 +1,3 @@
-/**
- * \file drm_ioctl.c
- * IOCTL processing for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
 /*
  * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
  *
@@ -13,6 +5,9 @@
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
+ * Author Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author Gareth Hughes <gareth@valinux.com>
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -35,6 +30,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_core.h>
+#include "drm_legacy.h"
 
 #include <linux/pci.h>
 #include <linux/export.h>
@@ -42,6 +38,124 @@
 #include <asm/mtrr.h>
 #endif
 
+static int drm_version(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+
+#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
+	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+
+/** Ioctl table */
+static const struct drm_ioctl_desc drm_ioctls[] = {
+	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+#if __OS_HAS_AGP
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
+
+	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+};
+
+#define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
+
 /**
  * Get the bus id.
  *
@@ -342,8 +456,6 @@ drm_setclientcap(struct drm_device *dev,
 		file_priv->stereo_allowed = req->value;
 		break;
 	case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
-		if (!drm_universal_planes)
-			return -EINVAL;
 		if (req->value > 1)
 			return -EINVAL;
 		file_priv->universal_planes = req->value;
@@ -417,3 +529,243 @@ int drm_noop(struct drm_device *dev, voi
 	return 0;
 }
 EXPORT_SYMBOL(drm_noop);
+
+/**
+ * Copy and IOCTL return string to user space
+ */
+static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
+{
+	int len;
+
+	/* don't overflow userbuf */
+	len = strlen(value);
+	if (len > *buf_len)
+		len = *buf_len;
+
+	/* let userspace know exact length of driver value (which could be
+	 * larger than the userspace-supplied buffer) */
+	*buf_len = strlen(value);
+
+	/* finally, try filling in the userbuf */
+	if (len && buf)
+		if (copy_to_user(buf, value, len))
+			return -EFAULT;
+	return 0;
+}
+
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
+static int drm_version(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct drm_version *version = data;
+	int err;
+
+	version->version_major = dev->driver->major;
+	version->version_minor = dev->driver->minor;
+	version->version_patchlevel = dev->driver->patchlevel;
+	err = drm_copy_field(version->name, &version->name_len,
+			dev->driver->name);
+	if (!err)
+		err = drm_copy_field(version->date, &version->date_len,
+				dev->driver->date);
+	if (!err)
+		err = drm_copy_field(version->desc, &version->desc_len,
+				dev->driver->desc);
+
+	return err;
+}
+
+/**
+ * drm_ioctl_permit - Check ioctl permissions against caller
+ *
+ * @flags: ioctl permission flags.
+ * @file_priv: Pointer to struct drm_file identifying the caller.
+ *
+ * Checks whether the caller is allowed to run an ioctl with the
+ * indicated permissions. If so, returns zero. Otherwise returns an
+ * error code suitable for ioctl return.
+ */
+static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+{
+	/* ROOT_ONLY is only for CAP_SYS_ADMIN */
+	if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
+		return -EACCES;
+
+	/* AUTH is only for authenticated or render client */
+	if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
+		     !file_priv->authenticated))
+		return -EACCES;
+
+	/* MASTER is only for master or control clients */
+	if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
+		     !drm_is_control_client(file_priv)))
+		return -EACCES;
+
+	/* Control clients must be explicitly allowed */
+	if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
+		     drm_is_control_client(file_priv)))
+		return -EACCES;
+
+	/* Render clients must be explicitly allowed */
+	if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
+		     drm_is_render_client(file_priv)))
+		return -EACCES;
+
+	return 0;
+}
+
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
+ */
+long drm_ioctl(struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev;
+	const struct drm_ioctl_desc *ioctl = NULL;
+	drm_ioctl_t *func;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	int retcode = -EINVAL;
+	char stack_kdata[128];
+	char *kdata = NULL;
+	unsigned int usize, asize;
+
+	dev = file_priv->minor->dev;
+
+	if (drm_device_is_unplugged(dev))
+		return -ENODEV;
+
+	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+		goto err_i1;
+	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+	    (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+		u32 drv_size;
+		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+		drv_size = _IOC_SIZE(ioctl->cmd_drv);
+		usize = asize = _IOC_SIZE(cmd);
+		if (drv_size > asize)
+			asize = drv_size;
+		cmd = ioctl->cmd_drv;
+	}
+	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+		u32 drv_size;
+
+		ioctl = &drm_ioctls[nr];
+
+		drv_size = _IOC_SIZE(ioctl->cmd);
+		usize = asize = _IOC_SIZE(cmd);
+		if (drv_size > asize)
+			asize = drv_size;
+
+		cmd = ioctl->cmd;
+	} else
+		goto err_i1;
+
+	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
+		  task_pid_nr(current),
+		  (long)old_encode_dev(file_priv->minor->kdev->devt),
+		  file_priv->authenticated, ioctl->name);
+
+	/* Do not trust userspace, use our own definition */
+	func = ioctl->func;
+
+	if (unlikely(!func)) {
+		DRM_DEBUG("no function\n");
+		retcode = -EINVAL;
+		goto err_i1;
+	}
+
+	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
+	if (unlikely(retcode))
+		goto err_i1;
+
+	if (cmd & (IOC_IN | IOC_OUT)) {
+		if (asize <= sizeof(stack_kdata)) {
+			kdata = stack_kdata;
+		} else {
+			kdata = kmalloc(asize, GFP_KERNEL);
+			if (!kdata) {
+				retcode = -ENOMEM;
+				goto err_i1;
+			}
+		}
+		if (asize > usize)
+			memset(kdata + usize, 0, asize - usize);
+	}
+
+	if (cmd & IOC_IN) {
+		if (copy_from_user(kdata, (void __user *)arg,
+				   usize) != 0) {
+			retcode = -EFAULT;
+			goto err_i1;
+		}
+	} else if (cmd & IOC_OUT) {
+		memset(kdata, 0, usize);
+	}
+
+	if (ioctl->flags & DRM_UNLOCKED)
+		retcode = func(dev, kdata, file_priv);
+	else {
+		mutex_lock(&drm_global_mutex);
+		retcode = func(dev, kdata, file_priv);
+		mutex_unlock(&drm_global_mutex);
+	}
+
+	if (cmd & IOC_OUT) {
+		if (copy_to_user((void __user *)arg, kdata,
+				 usize) != 0)
+			retcode = -EFAULT;
+	}
+
+      err_i1:
+	if (!ioctl)
+		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
+			  task_pid_nr(current),
+			  (long)old_encode_dev(file_priv->minor->kdev->devt),
+			  file_priv->authenticated, cmd, nr);
+
+	if (kdata != stack_kdata)
+		kfree(kdata);
+	if (retcode)
+		DRM_DEBUG("ret = %d\n", retcode);
+	return retcode;
+}
+EXPORT_SYMBOL(drm_ioctl);
+
+/**
+ * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ *
+ * @nr: Ioctl number.
+ * @flags: Where to return the ioctl permission flags
+ */
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+{
+	if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
+	    (nr < DRM_COMMAND_BASE)) {
+		*flags = drm_ioctls[nr].flags;
+		return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(drm_ioctl_flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_irq.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -542,8 +542,8 @@ int drm_calc_vbltimestamp_from_scanoutpo
 					  const struct drm_crtc *refcrtc,
 					  const struct drm_display_mode *mode)
 {
-	ktime_t stime, etime, mono_time_offset;
 	struct timeval tv_etime;
+	ktime_t stime, etime;
 	int vbl_status;
 	int vpos, hpos, i;
 	int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
@@ -588,13 +588,6 @@ int drm_calc_vbltimestamp_from_scanoutpo
 		vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
 							       &hpos, &stime, &etime);
 
-		/*
-		 * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if
-		 * CLOCK_REALTIME is requested.
-		 */
-		if (!drm_timestamp_monotonic)
-			mono_time_offset = ktime_get_monotonic_offset();
-
 		/* Return as no-op if scanout query unsupported or failed. */
 		if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
 			DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
@@ -633,7 +626,7 @@ int drm_calc_vbltimestamp_from_scanoutpo
 	delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
 
 	if (!drm_timestamp_monotonic)
-		etime = ktime_sub(etime, mono_time_offset);
+		etime = ktime_mono_to_real(etime);
 
 	/* save this only for debugging purposes */
 	tv_etime = ktime_to_timeval(etime);
@@ -664,10 +657,7 @@ static struct timeval get_drm_timestamp(
 {
 	ktime_t now;
 
-	now = ktime_get();
-	if (!drm_timestamp_monotonic)
-		now = ktime_sub(now, ktime_get_monotonic_offset());
-
+	now = drm_timestamp_monotonic ? ktime_get() : ktime_get_real();
 	return ktime_to_timeval(now);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_legacy.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_legacy.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_legacy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_legacy.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,51 @@
+#ifndef __DRM_LEGACY_H__
+#define __DRM_LEGACY_H__
+
+/*
+ * Copyright (c) 2014 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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.
+ */
+
+struct drm_device;
+struct drm_file;
+
+/*
+ * Generic DRM Contexts
+ */
+
+#define DRM_KERNEL_CONTEXT		0
+#define DRM_RESERVED_CONTEXTS		1
+
+int drm_legacy_ctxbitmap_init(struct drm_device *dev);
+void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev);
+void drm_legacy_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
+
+int drm_legacy_resctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_addctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_getctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_switchctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_newctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_rmctx(struct drm_device *d, void *v, struct drm_file *f);
+
+int drm_legacy_setsareactx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_getsareactx(struct drm_device *d, void *v, struct drm_file *f);
+
+#endif /* __DRM_LEGACY_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_lock.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_lock.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include <linux/export.h>
 #include <drm/drmP.h>
+#include "drm_legacy.h"
 
 static int drm_notifier(void *priv);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_mipi_dsi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_mipi_dsi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_mipi_dsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_mipi_dsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -201,16 +201,15 @@ EXPORT_SYMBOL(mipi_dsi_detach);
 /**
  * mipi_dsi_dcs_write - send DCS write command
  * @dsi: DSI device
- * @channel: virtual channel
  * @data: pointer to the command followed by parameters
  * @len: length of @data
  */
-int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel,
-		       const void *data, size_t len)
+ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
+			    size_t len)
 {
 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
 	struct mipi_dsi_msg msg = {
-		.channel = channel,
+		.channel = dsi->channel,
 		.tx_buf = data,
 		.tx_len = len
 	};
@@ -239,19 +238,18 @@ EXPORT_SYMBOL(mipi_dsi_dcs_write);
 /**
  * mipi_dsi_dcs_read - send DCS read request command
  * @dsi: DSI device
- * @channel: virtual channel
  * @cmd: DCS read command
  * @data: pointer to read buffer
  * @len: length of @data
  *
  * Function returns number of read bytes or error code.
  */
-ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel,
-			  u8 cmd, void *data, size_t len)
+ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
+			  size_t len)
 {
 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
 	struct mipi_dsi_msg msg = {
-		.channel = channel,
+		.channel = dsi->channel,
 		.type = MIPI_DSI_DCS_READ,
 		.tx_buf = &cmd,
 		.tx_len = 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_of.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_of.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_of.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_of.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,67 @@
+#include <linux/export.h>
+#include <linux/list.h>
+#include <linux/of_graph.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_of.h>
+
+/**
+ * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
+ * @dev: DRM device
+ * @port: port OF node
+ *
+ * Given a port OF node, return the possible mask of the corresponding
+ * CRTC within a device's list of CRTCs.  Returns zero if not found.
+ */
+static uint32_t drm_crtc_port_mask(struct drm_device *dev,
+				   struct device_node *port)
+{
+	unsigned int index = 0;
+	struct drm_crtc *tmp;
+
+	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+		if (tmp->port == port)
+			return 1 << index;
+
+		index++;
+	}
+
+	return 0;
+}
+
+/**
+ * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
+ * @dev: DRM device
+ * @port: encoder port to scan for endpoints
+ *
+ * Scan all endpoints attached to a port, locate their attached CRTCs,
+ * and generate the DRM mask of CRTCs which may be attached to this
+ * encoder.
+ *
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ */
+uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
+				    struct device_node *port)
+{
+	struct device_node *remote_port, *ep = NULL;
+	uint32_t possible_crtcs = 0;
+
+	do {
+		ep = of_graph_get_next_endpoint(port, ep);
+		if (!ep)
+			break;
+
+		remote_port = of_graph_get_remote_port(ep);
+		if (!remote_port) {
+			of_node_put(ep);
+			return 0;
+		}
+
+		possible_crtcs |= drm_crtc_port_mask(dev, remote_port);
+
+		of_node_put(remote_port);
+	} while (1);
+
+	return possible_crtcs;
+}
+EXPORT_SYMBOL(drm_of_find_possible_crtcs);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_plane_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_plane_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_plane_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_plane_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -335,9 +335,10 @@ struct drm_plane *drm_primary_helper_cre
 	}
 
 	/* possible_crtc's will be filled in later by crtc_init */
-	ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs,
-			     formats, num_formats,
-			     DRM_PLANE_TYPE_PRIMARY);
+	ret = drm_universal_plane_init(dev, primary, 0,
+				       &drm_primary_helper_funcs,
+				       formats, num_formats,
+				       DRM_PLANE_TYPE_PRIMARY);
 	if (ret) {
 		kfree(primary);
 		primary = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_prime.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_prime.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_prime.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_prime.c	2014-09-28 17:29:07.000000000 -0400
@@ -336,7 +336,13 @@ static const struct dma_buf_ops drm_gem_
 struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
 				     struct drm_gem_object *obj, int flags)
 {
-	return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags);
+	struct reservation_object *robj = NULL;
+
+	if (dev->driver->gem_prime_res_obj)
+		robj = dev->driver->gem_prime_res_obj(obj);
+
+	return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size,
+			      flags, robj);
 }
 EXPORT_SYMBOL(drm_gem_prime_export);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_probe_helper.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_probe_helper.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_probe_helper.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_probe_helper.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,7 +130,14 @@ static int drm_helper_probe_single_conne
 	count = drm_load_edid_firmware(connector);
 	if (count == 0)
 #endif
-		count = (*connector_funcs->get_modes)(connector);
+	{
+		if (connector->override_edid) {
+			struct edid *edid = (struct edid *) connector->edid_blob_ptr->data;
+
+			count = drm_add_edid_modes(connector, edid);
+		} else
+			count = (*connector_funcs->get_modes)(connector);
+	}
 
 	if (count == 0 && connector->status == connector_status_connected)
 		count = drm_add_modes_noedid(connector, 1024, 768);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_rect.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_rect.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_rect.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_rect.c	2014-09-28 17:29:07.000000000 -0400
@@ -293,3 +293,143 @@ void drm_rect_debug_print(const struct d
 		DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
 }
 EXPORT_SYMBOL(drm_rect_debug_print);
+
+/**
+ * drm_rect_rotate - Rotate the rectangle
+ * @r: rectangle to be rotated
+ * @width: Width of the coordinate space
+ * @height: Height of the coordinate space
+ * @rotation: Transformation to be applied
+ *
+ * Apply @rotation to the coordinates of rectangle @r.
+ *
+ * @width and @height combined with @rotation define
+ * the location of the new origin.
+ *
+ * @width correcsponds to the horizontal and @height
+ * to the vertical axis of the untransformed coordinate
+ * space.
+ */
+void drm_rect_rotate(struct drm_rect *r,
+		     int width, int height,
+		     unsigned int rotation)
+{
+	struct drm_rect tmp;
+
+	if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) {
+		tmp = *r;
+
+		if (rotation & BIT(DRM_REFLECT_X)) {
+			r->x1 = width - tmp.x2;
+			r->x2 = width - tmp.x1;
+		}
+
+		if (rotation & BIT(DRM_REFLECT_Y)) {
+			r->y1 = height - tmp.y2;
+			r->y2 = height - tmp.y1;
+		}
+	}
+
+	switch (rotation & 0xf) {
+	case BIT(DRM_ROTATE_0):
+		break;
+	case BIT(DRM_ROTATE_90):
+		tmp = *r;
+		r->x1 = tmp.y1;
+		r->x2 = tmp.y2;
+		r->y1 = width - tmp.x2;
+		r->y2 = width - tmp.x1;
+		break;
+	case BIT(DRM_ROTATE_180):
+		tmp = *r;
+		r->x1 = width - tmp.x2;
+		r->x2 = width - tmp.x1;
+		r->y1 = height - tmp.y2;
+		r->y2 = height - tmp.y1;
+		break;
+	case BIT(DRM_ROTATE_270):
+		tmp = *r;
+		r->x1 = height - tmp.y2;
+		r->x2 = height - tmp.y1;
+		r->y1 = tmp.x1;
+		r->y2 = tmp.x2;
+		break;
+	default:
+		break;
+	}
+}
+EXPORT_SYMBOL(drm_rect_rotate);
+
+/**
+ * drm_rect_rotate_inv - Inverse rotate the rectangle
+ * @r: rectangle to be rotated
+ * @width: Width of the coordinate space
+ * @height: Height of the coordinate space
+ * @rotation: Transformation whose inverse is to be applied
+ *
+ * Apply the inverse of @rotation to the coordinates
+ * of rectangle @r.
+ *
+ * @width and @height combined with @rotation define
+ * the location of the new origin.
+ *
+ * @width correcsponds to the horizontal and @height
+ * to the vertical axis of the original untransformed
+ * coordinate space, so that you never have to flip
+ * them when doing a rotatation and its inverse.
+ * That is, if you do:
+ *
+ * drm_rotate(&r, width, height, rotation);
+ * drm_rotate_inv(&r, width, height, rotation);
+ *
+ * you will always get back the original rectangle.
+ */
+void drm_rect_rotate_inv(struct drm_rect *r,
+			 int width, int height,
+			 unsigned int rotation)
+{
+	struct drm_rect tmp;
+
+	switch (rotation & 0xf) {
+	case BIT(DRM_ROTATE_0):
+		break;
+	case BIT(DRM_ROTATE_90):
+		tmp = *r;
+		r->x1 = width - tmp.y2;
+		r->x2 = width - tmp.y1;
+		r->y1 = tmp.x1;
+		r->y2 = tmp.x2;
+		break;
+	case BIT(DRM_ROTATE_180):
+		tmp = *r;
+		r->x1 = width - tmp.x2;
+		r->x2 = width - tmp.x1;
+		r->y1 = height - tmp.y2;
+		r->y2 = height - tmp.y1;
+		break;
+	case BIT(DRM_ROTATE_270):
+		tmp = *r;
+		r->x1 = tmp.y1;
+		r->x2 = tmp.y2;
+		r->y1 = height - tmp.x2;
+		r->y2 = height - tmp.x1;
+		break;
+	default:
+		break;
+	}
+
+	if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) {
+		tmp = *r;
+
+		if (rotation & BIT(DRM_REFLECT_X)) {
+			r->x1 = width - tmp.x2;
+			r->x2 = width - tmp.x1;
+		}
+
+		if (rotation & BIT(DRM_REFLECT_Y)) {
+			r->y1 = height - tmp.y2;
+			r->y2 = height - tmp.y1;
+		}
+	}
+}
+EXPORT_SYMBOL(drm_rect_rotate_inv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_stub.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_stub.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_stub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_stub.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,805 +0,0 @@
-/*
- * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
- *
- * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Author Rickard E. (Rik) Faith <faith@valinux.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <drm/drmP.h>
-#include <drm/drm_core.h>
-
-unsigned int drm_debug = 0;	/* 1 to enable debug output */
-EXPORT_SYMBOL(drm_debug);
-
-unsigned int drm_rnodes = 0;	/* 1 to enable experimental render nodes API */
-EXPORT_SYMBOL(drm_rnodes);
-
-/* 1 to allow user space to request universal planes (experimental) */
-unsigned int drm_universal_planes = 0;
-EXPORT_SYMBOL(drm_universal_planes);
-
-unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
-EXPORT_SYMBOL(drm_vblank_offdelay);
-
-unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
-EXPORT_SYMBOL(drm_timestamp_precision);
-
-/*
- * Default to use monotonic timestamps for wait-for-vblank and page-flip
- * complete events.
- */
-unsigned int drm_timestamp_monotonic = 1;
-
-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
-MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output");
-MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API");
-MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
-MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
-MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
-
-module_param_named(debug, drm_debug, int, 0600);
-module_param_named(rnodes, drm_rnodes, int, 0600);
-module_param_named(universal_planes, drm_universal_planes, int, 0600);
-module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
-module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
-module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
-
-static DEFINE_SPINLOCK(drm_minor_lock);
-struct idr drm_minors_idr;
-
-struct class *drm_class;
-struct dentry *drm_debugfs_root;
-
-int drm_err(const char *func, const char *format, ...)
-{
-	struct va_format vaf;
-	va_list args;
-	int r;
-
-	va_start(args, format);
-
-	vaf.fmt = format;
-	vaf.va = &args;
-
-	r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
-
-	va_end(args);
-
-	return r;
-}
-EXPORT_SYMBOL(drm_err);
-
-void drm_ut_debug_printk(const char *function_name, const char *format, ...)
-{
-	struct va_format vaf;
-	va_list args;
-
-	va_start(args, format);
-	vaf.fmt = format;
-	vaf.va = &args;
-
-	printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
-
-	va_end(args);
-}
-EXPORT_SYMBOL(drm_ut_debug_printk);
-
-struct drm_master *drm_master_create(struct drm_minor *minor)
-{
-	struct drm_master *master;
-
-	master = kzalloc(sizeof(*master), GFP_KERNEL);
-	if (!master)
-		return NULL;
-
-	kref_init(&master->refcount);
-	spin_lock_init(&master->lock.spinlock);
-	init_waitqueue_head(&master->lock.lock_queue);
-	if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
-		kfree(master);
-		return NULL;
-	}
-	INIT_LIST_HEAD(&master->magicfree);
-	master->minor = minor;
-
-	return master;
-}
-
-struct drm_master *drm_master_get(struct drm_master *master)
-{
-	kref_get(&master->refcount);
-	return master;
-}
-EXPORT_SYMBOL(drm_master_get);
-
-static void drm_master_destroy(struct kref *kref)
-{
-	struct drm_master *master = container_of(kref, struct drm_master, refcount);
-	struct drm_magic_entry *pt, *next;
-	struct drm_device *dev = master->minor->dev;
-	struct drm_map_list *r_list, *list_temp;
-
-	mutex_lock(&dev->struct_mutex);
-	if (dev->driver->master_destroy)
-		dev->driver->master_destroy(dev, master);
-
-	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
-		if (r_list->master == master) {
-			drm_rmmap_locked(dev, r_list->map);
-			r_list = NULL;
-		}
-	}
-
-	if (master->unique) {
-		kfree(master->unique);
-		master->unique = NULL;
-		master->unique_len = 0;
-	}
-
-	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
-		list_del(&pt->head);
-		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
-		kfree(pt);
-	}
-
-	drm_ht_remove(&master->magiclist);
-
-	mutex_unlock(&dev->struct_mutex);
-	kfree(master);
-}
-
-void drm_master_put(struct drm_master **master)
-{
-	kref_put(&(*master)->refcount, drm_master_destroy);
-	*master = NULL;
-}
-EXPORT_SYMBOL(drm_master_put);
-
-int drm_setmaster_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	int ret = 0;
-
-	mutex_lock(&dev->master_mutex);
-	if (file_priv->is_master)
-		goto out_unlock;
-
-	if (file_priv->minor->master) {
-		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	if (!file_priv->master) {
-		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	file_priv->minor->master = drm_master_get(file_priv->master);
-	file_priv->is_master = 1;
-	if (dev->driver->master_set) {
-		ret = dev->driver->master_set(dev, file_priv, false);
-		if (unlikely(ret != 0)) {
-			file_priv->is_master = 0;
-			drm_master_put(&file_priv->minor->master);
-		}
-	}
-
-out_unlock:
-	mutex_unlock(&dev->master_mutex);
-	return ret;
-}
-
-int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	int ret = -EINVAL;
-
-	mutex_lock(&dev->master_mutex);
-	if (!file_priv->is_master)
-		goto out_unlock;
-
-	if (!file_priv->minor->master)
-		goto out_unlock;
-
-	ret = 0;
-	if (dev->driver->master_drop)
-		dev->driver->master_drop(dev, file_priv, false);
-	drm_master_put(&file_priv->minor->master);
-	file_priv->is_master = 0;
-
-out_unlock:
-	mutex_unlock(&dev->master_mutex);
-	return ret;
-}
-
-/*
- * DRM Minors
- * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
- * of them is represented by a drm_minor object. Depending on the capabilities
- * of the device-driver, different interfaces are registered.
- *
- * Minors can be accessed via dev->$minor_name. This pointer is either
- * NULL or a valid drm_minor pointer and stays valid as long as the device is
- * valid. This means, DRM minors have the same life-time as the underlying
- * device. However, this doesn't mean that the minor is active. Minors are
- * registered and unregistered dynamically according to device-state.
- */
-
-static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
-					     unsigned int type)
-{
-	switch (type) {
-	case DRM_MINOR_LEGACY:
-		return &dev->primary;
-	case DRM_MINOR_RENDER:
-		return &dev->render;
-	case DRM_MINOR_CONTROL:
-		return &dev->control;
-	default:
-		return NULL;
-	}
-}
-
-static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
-{
-	struct drm_minor *minor;
-
-	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
-	if (!minor)
-		return -ENOMEM;
-
-	minor->type = type;
-	minor->dev = dev;
-
-	*drm_minor_get_slot(dev, type) = minor;
-	return 0;
-}
-
-static void drm_minor_free(struct drm_device *dev, unsigned int type)
-{
-	struct drm_minor **slot;
-
-	slot = drm_minor_get_slot(dev, type);
-	if (*slot) {
-		drm_mode_group_destroy(&(*slot)->mode_group);
-		kfree(*slot);
-		*slot = NULL;
-	}
-}
-
-static int drm_minor_register(struct drm_device *dev, unsigned int type)
-{
-	struct drm_minor *new_minor;
-	unsigned long flags;
-	int ret;
-	int minor_id;
-
-	DRM_DEBUG("\n");
-
-	new_minor = *drm_minor_get_slot(dev, type);
-	if (!new_minor)
-		return 0;
-
-	idr_preload(GFP_KERNEL);
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	minor_id = idr_alloc(&drm_minors_idr,
-			     NULL,
-			     64 * type,
-			     64 * (type + 1),
-			     GFP_NOWAIT);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	idr_preload_end();
-
-	if (minor_id < 0)
-		return minor_id;
-
-	new_minor->index = minor_id;
-
-	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
-	if (ret) {
-		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
-		goto err_id;
-	}
-
-	ret = drm_sysfs_device_add(new_minor);
-	if (ret) {
-		DRM_ERROR("DRM: Error sysfs_device_add.\n");
-		goto err_debugfs;
-	}
-
-	/* replace NULL with @minor so lookups will succeed from now on */
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_replace(&drm_minors_idr, new_minor, new_minor->index);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-
-	DRM_DEBUG("new minor assigned %d\n", minor_id);
-	return 0;
-
-err_debugfs:
-	drm_debugfs_cleanup(new_minor);
-err_id:
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_remove(&drm_minors_idr, minor_id);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	new_minor->index = 0;
-	return ret;
-}
-
-static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
-{
-	struct drm_minor *minor;
-	unsigned long flags;
-
-	minor = *drm_minor_get_slot(dev, type);
-	if (!minor || !minor->kdev)
-		return;
-
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	idr_remove(&drm_minors_idr, minor->index);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-	minor->index = 0;
-
-	drm_debugfs_cleanup(minor);
-	drm_sysfs_device_remove(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().
- *
- * 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)
-{
-	struct drm_minor *minor;
-	unsigned long flags;
-
-	spin_lock_irqsave(&drm_minor_lock, flags);
-	minor = idr_find(&drm_minors_idr, minor_id);
-	if (minor)
-		drm_dev_ref(minor->dev);
-	spin_unlock_irqrestore(&drm_minor_lock, flags);
-
-	if (!minor) {
-		return ERR_PTR(-ENODEV);
-	} else if (drm_device_is_unplugged(minor->dev)) {
-		drm_dev_unref(minor->dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	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);
-}
-
-/**
- * drm_put_dev - Unregister and release a DRM device
- * @dev: DRM device
- *
- * Called at module unload time or when a PCI device is unplugged.
- *
- * Use of this function is discouraged. It will eventually go away completely.
- * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
- *
- * Cleans up all DRM device, calling drm_lastclose().
- */
-void drm_put_dev(struct drm_device *dev)
-{
-	DRM_DEBUG("\n");
-
-	if (!dev) {
-		DRM_ERROR("cleanup called no dev\n");
-		return;
-	}
-
-	drm_dev_unregister(dev);
-	drm_dev_unref(dev);
-}
-EXPORT_SYMBOL(drm_put_dev);
-
-void drm_unplug_dev(struct drm_device *dev)
-{
-	/* for a USB device */
-	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
-	drm_minor_unregister(dev, DRM_MINOR_RENDER);
-	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
-
-	mutex_lock(&drm_global_mutex);
-
-	drm_device_set_unplugged(dev);
-
-	if (dev->open_count == 0) {
-		drm_put_dev(dev);
-	}
-	mutex_unlock(&drm_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
-/*
- * DRM internal mount
- * We want to be able to allocate our own "struct address_space" to control
- * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow
- * stand-alone address_space objects, so we need an underlying inode. As there
- * is no way to allocate an independent inode easily, we need a fake internal
- * VFS mount-point.
- *
- * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free()
- * frees it again. You are allowed to use iget() and iput() to get references to
- * the inode. But each drm_fs_inode_new() call must be paired with exactly one
- * drm_fs_inode_free() call (which does not have to be the last iput()).
- * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it
- * between multiple inode-users. You could, technically, call
- * iget() + drm_fs_inode_free() directly after alloc and sometime later do an
- * iput(), but this way you'd end up with a new vfsmount for each inode.
- */
-
-static int drm_fs_cnt;
-static struct vfsmount *drm_fs_mnt;
-
-static const struct dentry_operations drm_fs_dops = {
-	.d_dname	= simple_dname,
-};
-
-static const struct super_operations drm_fs_sops = {
-	.statfs		= simple_statfs,
-};
-
-static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
-				   const char *dev_name, void *data)
-{
-	return mount_pseudo(fs_type,
-			    "drm:",
-			    &drm_fs_sops,
-			    &drm_fs_dops,
-			    0x010203ff);
-}
-
-static struct file_system_type drm_fs_type = {
-	.name		= "drm",
-	.owner		= THIS_MODULE,
-	.mount		= drm_fs_mount,
-	.kill_sb	= kill_anon_super,
-};
-
-static struct inode *drm_fs_inode_new(void)
-{
-	struct inode *inode;
-	int r;
-
-	r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
-	if (r < 0) {
-		DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
-		return ERR_PTR(r);
-	}
-
-	inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
-	if (IS_ERR(inode))
-		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
-
-	return inode;
-}
-
-static void drm_fs_inode_free(struct inode *inode)
-{
-	if (inode) {
-		iput(inode);
-		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
-	}
-}
-
-/**
- * drm_dev_alloc - Allocate new DRM device
- * @driver: DRM driver to allocate device for
- * @parent: Parent device object
- *
- * Allocate and initialize a new DRM device. No device registration is done.
- * Call drm_dev_register() to advertice the device to user space and register it
- * with other core subsystems.
- *
- * The initial ref-count of the object is 1. Use drm_dev_ref() and
- * drm_dev_unref() to take and drop further ref-counts.
- *
- * RETURNS:
- * Pointer to new DRM device, or NULL if out of memory.
- */
-struct drm_device *drm_dev_alloc(struct drm_driver *driver,
-				 struct device *parent)
-{
-	struct drm_device *dev;
-	int ret;
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	kref_init(&dev->ref);
-	dev->dev = parent;
-	dev->driver = driver;
-
-	INIT_LIST_HEAD(&dev->filelist);
-	INIT_LIST_HEAD(&dev->ctxlist);
-	INIT_LIST_HEAD(&dev->vmalist);
-	INIT_LIST_HEAD(&dev->maplist);
-	INIT_LIST_HEAD(&dev->vblank_event_list);
-
-	spin_lock_init(&dev->buf_lock);
-	spin_lock_init(&dev->event_lock);
-	mutex_init(&dev->struct_mutex);
-	mutex_init(&dev->ctxlist_mutex);
-	mutex_init(&dev->master_mutex);
-
-	dev->anon_inode = drm_fs_inode_new();
-	if (IS_ERR(dev->anon_inode)) {
-		ret = PTR_ERR(dev->anon_inode);
-		DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
-		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) && drm_rnodes) {
-		ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
-		if (ret)
-			goto err_minors;
-	}
-
-	ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
-	if (ret)
-		goto err_minors;
-
-	if (drm_ht_create(&dev->map_hash, 12))
-		goto err_minors;
-
-	ret = drm_ctxbitmap_init(dev);
-	if (ret) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		goto err_ht;
-	}
-
-	if (driver->driver_features & DRIVER_GEM) {
-		ret = drm_gem_init(dev);
-		if (ret) {
-			DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
-			goto err_ctxbitmap;
-		}
-	}
-
-	return dev;
-
-err_ctxbitmap:
-	drm_ctxbitmap_cleanup(dev);
-err_ht:
-	drm_ht_remove(&dev->map_hash);
-err_minors:
-	drm_minor_free(dev, DRM_MINOR_LEGACY);
-	drm_minor_free(dev, DRM_MINOR_RENDER);
-	drm_minor_free(dev, DRM_MINOR_CONTROL);
-	drm_fs_inode_free(dev->anon_inode);
-err_free:
-	mutex_destroy(&dev->master_mutex);
-	kfree(dev);
-	return NULL;
-}
-EXPORT_SYMBOL(drm_dev_alloc);
-
-static void drm_dev_release(struct kref *ref)
-{
-	struct drm_device *dev = container_of(ref, struct drm_device, ref);
-
-	if (dev->driver->driver_features & DRIVER_GEM)
-		drm_gem_destroy(dev);
-
-	drm_ctxbitmap_cleanup(dev);
-	drm_ht_remove(&dev->map_hash);
-	drm_fs_inode_free(dev->anon_inode);
-
-	drm_minor_free(dev, DRM_MINOR_LEGACY);
-	drm_minor_free(dev, DRM_MINOR_RENDER);
-	drm_minor_free(dev, DRM_MINOR_CONTROL);
-
-	mutex_destroy(&dev->master_mutex);
-	kfree(dev->unique);
-	kfree(dev);
-}
-
-/**
- * drm_dev_ref - Take reference of a DRM device
- * @dev: device to take reference of or NULL
- *
- * This increases the ref-count of @dev by one. You *must* already own a
- * reference when calling this. Use drm_dev_unref() to drop this reference
- * again.
- *
- * This function never fails. However, this function does not provide *any*
- * guarantee whether the device is alive or running. It only provides a
- * reference to the object and the memory associated with it.
- */
-void drm_dev_ref(struct drm_device *dev)
-{
-	if (dev)
-		kref_get(&dev->ref);
-}
-EXPORT_SYMBOL(drm_dev_ref);
-
-/**
- * drm_dev_unref - Drop reference of a DRM device
- * @dev: device to drop reference of or NULL
- *
- * This decreases the ref-count of @dev by one. The device is destroyed if the
- * ref-count drops to zero.
- */
-void drm_dev_unref(struct drm_device *dev)
-{
-	if (dev)
-		kref_put(&dev->ref, drm_dev_release);
-}
-EXPORT_SYMBOL(drm_dev_unref);
-
-/**
- * drm_dev_register - Register DRM device
- * @dev: Device to register
- * @flags: Flags passed to the driver's .load() function
- *
- * Register the DRM device @dev with the system, advertise device to user-space
- * and start normal device operation. @dev must be allocated via drm_dev_alloc()
- * previously.
- *
- * Never call this twice on any device!
- *
- * RETURNS:
- * 0 on success, negative error code on failure.
- */
-int drm_dev_register(struct drm_device *dev, unsigned long flags)
-{
-	int ret;
-
-	mutex_lock(&drm_global_mutex);
-
-	ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
-	if (ret)
-		goto err_minors;
-
-	ret = drm_minor_register(dev, DRM_MINOR_RENDER);
-	if (ret)
-		goto err_minors;
-
-	ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
-	if (ret)
-		goto err_minors;
-
-	if (dev->driver->load) {
-		ret = dev->driver->load(dev, flags);
-		if (ret)
-			goto err_minors;
-	}
-
-	/* setup grouping for legacy outputs */
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = drm_mode_group_init_legacy_group(dev,
-				&dev->primary->mode_group);
-		if (ret)
-			goto err_unload;
-	}
-
-	ret = 0;
-	goto out_unlock;
-
-err_unload:
-	if (dev->driver->unload)
-		dev->driver->unload(dev);
-err_minors:
-	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
-	drm_minor_unregister(dev, DRM_MINOR_RENDER);
-	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
-out_unlock:
-	mutex_unlock(&drm_global_mutex);
-	return ret;
-}
-EXPORT_SYMBOL(drm_dev_register);
-
-/**
- * drm_dev_unregister - Unregister DRM device
- * @dev: Device to unregister
- *
- * Unregister the DRM device from the system. This does the reverse of
- * drm_dev_register() but does not deallocate the device. The caller must call
- * drm_dev_unref() to drop their final reference.
- */
-void drm_dev_unregister(struct drm_device *dev)
-{
-	struct drm_map_list *r_list, *list_temp;
-
-	drm_lastclose(dev);
-
-	if (dev->driver->unload)
-		dev->driver->unload(dev);
-
-	if (dev->agp)
-		drm_pci_agp_destroy(dev);
-
-	drm_vblank_cleanup(dev);
-
-	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
-		drm_rmmap(dev, r_list->map);
-
-	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
-	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
- * @fmt: format string for unique name
- *
- * Sets the unique name of a DRM device using the specified format string and
- * a variable list of arguments. 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 *fmt, ...)
-{
-	va_list ap;
-
-	kfree(dev->unique);
-
-	va_start(ap, fmt);
-	dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
-	va_end(ap);
-
-	return dev->unique ? 0 : -ENOMEM;
-}
-EXPORT_SYMBOL(drm_dev_set_unique);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/drm_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/drm_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -438,7 +438,6 @@ err_out_files:
 out:
 	return ret;
 }
-EXPORT_SYMBOL(drm_sysfs_connector_add);
 
 /**
  * drm_sysfs_connector_remove - remove an connector device from sysfs
@@ -468,7 +467,6 @@ void drm_sysfs_connector_remove(struct d
 	device_unregister(connector->kdev);
 	connector->kdev = NULL;
 }
-EXPORT_SYMBOL(drm_sysfs_connector_remove);
 
 /**
  * drm_sysfs_hotplug_event - generate a DRM uevent
@@ -495,71 +493,55 @@ static void drm_sysfs_release(struct dev
 }
 
 /**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
+ * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
+ * @minor: minor to allocate sysfs device for
  *
- * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
+ * This allocates a new sysfs device for @minor and returns it. The device is
+ * not registered nor linked. The caller has to use device_add() and
+ * device_del() to register and unregister it.
+ *
+ * Note that dev_get_drvdata() on the new device will return the minor.
+ * However, the device does not hold a ref-count to the minor nor to the
+ * underlying drm_device. This is unproblematic as long as you access the
+ * private data only in sysfs callbacks. device_del() disables those
+ * synchronously, so they cannot be called after you cleanup a minor.
  */
-int drm_sysfs_device_add(struct drm_minor *minor)
+struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
 {
-	char *minor_str;
+	const char *minor_str;
+	struct device *kdev;
 	int r;
 
 	if (minor->type == DRM_MINOR_CONTROL)
 		minor_str = "controlD%d";
-        else if (minor->type == DRM_MINOR_RENDER)
-                minor_str = "renderD%d";
-        else
-                minor_str = "card%d";
-
-	minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
-	if (!minor->kdev) {
-		r = -ENOMEM;
-		goto error;
-	}
+	else if (minor->type == DRM_MINOR_RENDER)
+		minor_str = "renderD%d";
+	else
+		minor_str = "card%d";
 
-	device_initialize(minor->kdev);
-	minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
-	minor->kdev->class = drm_class;
-	minor->kdev->type = &drm_sysfs_device_minor;
-	minor->kdev->parent = minor->dev->dev;
-	minor->kdev->release = drm_sysfs_release;
-	dev_set_drvdata(minor->kdev, minor);
+	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+	if (!kdev)
+		return ERR_PTR(-ENOMEM);
 
-	r = dev_set_name(minor->kdev, minor_str, minor->index);
-	if (r < 0)
-		goto error;
+	device_initialize(kdev);
+	kdev->devt = MKDEV(DRM_MAJOR, minor->index);
+	kdev->class = drm_class;
+	kdev->type = &drm_sysfs_device_minor;
+	kdev->parent = minor->dev->dev;
+	kdev->release = drm_sysfs_release;
+	dev_set_drvdata(kdev, minor);
 
-	r = device_add(minor->kdev);
+	r = dev_set_name(kdev, minor_str, minor->index);
 	if (r < 0)
-		goto error;
-
-	return 0;
+		goto err_free;
 
-error:
-	DRM_ERROR("device create failed %d\n", r);
-	put_device(minor->kdev);
-	return r;
-}
+	return kdev;
 
-/**
- * drm_sysfs_device_remove - remove DRM device
- * @dev: DRM device to remove
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to drm_sysfs_device_add()
- */
-void drm_sysfs_device_remove(struct drm_minor *minor)
-{
-	if (minor->kdev)
-		device_unregister(minor->kdev);
-	minor->kdev = NULL;
+err_free:
+	put_device(kdev);
+	return ERR_PTR(r);
 }
 
-
 /**
  * drm_class_device_register - Register a struct device in the drm class.
  *
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
@@ -28,6 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
 #include <drm/bridge/ptn3460.h>
 
 #include "exynos_drm_drv.h"
@@ -41,7 +41,7 @@ struct bridge_init {
 	struct device_node *node;
 };
 
-static int exynos_dp_init_dp(struct exynos_dp_device *dp)
+static void exynos_dp_init_dp(struct exynos_dp_device *dp)
 {
 	exynos_dp_reset(dp);
 
@@ -58,8 +58,6 @@ static int exynos_dp_init_dp(struct exyn
 
 	exynos_dp_init_hpd(dp);
 	exynos_dp_init_aux(dp);
-
-	return 0;
 }
 
 static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
@@ -875,10 +873,24 @@ static irqreturn_t exynos_dp_irq_handler
 static void exynos_dp_hotplug(struct work_struct *work)
 {
 	struct exynos_dp_device *dp;
-	int ret;
 
 	dp = container_of(work, struct exynos_dp_device, hotplug_work);
 
+	if (dp->drm_dev)
+		drm_helper_hpd_irq_event(dp->drm_dev);
+}
+
+static void exynos_dp_commit(struct exynos_drm_display *display)
+{
+	struct exynos_dp_device *dp = display->ctx;
+	int ret;
+
+	/* Keep the panel disabled while we configure video */
+	if (dp->panel) {
+		if (drm_panel_disable(dp->panel))
+			DRM_ERROR("failed to disable the panel\n");
+	}
+
 	ret = exynos_dp_detect_hpd(dp);
 	if (ret) {
 		/* Cable has been disconnected, we're done */
@@ -909,6 +921,12 @@ static void exynos_dp_hotplug(struct wor
 	ret = exynos_dp_config_video(dp);
 	if (ret)
 		dev_err(dp->dev, "unable to config video\n");
+
+	/* Safe to enable the panel now */
+	if (dp->panel) {
+		if (drm_panel_enable(dp->panel))
+			DRM_ERROR("failed to enable the panel\n");
+	}
 }
 
 static enum drm_connector_status exynos_dp_detect(
@@ -933,15 +951,18 @@ static int exynos_dp_get_modes(struct dr
 	struct exynos_dp_device *dp = ctx_from_connector(connector);
 	struct drm_display_mode *mode;
 
+	if (dp->panel)
+		return drm_panel_get_modes(dp->panel);
+
 	mode = drm_mode_create(connector->dev);
 	if (!mode) {
 		DRM_ERROR("failed to create a new display mode.\n");
 		return 0;
 	}
 
-	drm_display_mode_from_videomode(&dp->panel.vm, mode);
-	mode->width_mm = dp->panel.width_mm;
-	mode->height_mm = dp->panel.height_mm;
+	drm_display_mode_from_videomode(&dp->priv.vm, mode);
+	mode->width_mm = dp->priv.width_mm;
+	mode->height_mm = dp->priv.height_mm;
 	connector->display_info.width_mm = mode->width_mm;
 	connector->display_info.height_mm = mode->height_mm;
 
@@ -1018,10 +1039,13 @@ static int exynos_dp_create_connector(st
 	}
 
 	drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
-	return 0;
+	if (dp->panel)
+		ret = drm_panel_attach(dp->panel, &dp->connector);
+
+	return ret;
 }
 
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
@@ -1050,26 +1074,50 @@ static void exynos_dp_phy_exit(struct ex
 	}
 }
 
-static void exynos_dp_poweron(struct exynos_dp_device *dp)
+static void exynos_dp_poweron(struct exynos_drm_display *display)
 {
+	struct exynos_dp_device *dp = display->ctx;
+
 	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
 		return;
 
+	if (dp->panel) {
+		if (drm_panel_prepare(dp->panel)) {
+			DRM_ERROR("failed to setup the panel\n");
+			return;
+		}
+	}
+
 	clk_prepare_enable(dp->clock);
 	exynos_dp_phy_init(dp);
 	exynos_dp_init_dp(dp);
 	enable_irq(dp->irq);
+	exynos_dp_commit(display);
 }
 
-static void exynos_dp_poweroff(struct exynos_dp_device *dp)
+static void exynos_dp_poweroff(struct exynos_drm_display *display)
 {
+	struct exynos_dp_device *dp = display->ctx;
+
 	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
 		return;
 
+	if (dp->panel) {
+		if (drm_panel_disable(dp->panel)) {
+			DRM_ERROR("failed to disable the panel\n");
+			return;
+		}
+	}
+
 	disable_irq(dp->irq);
 	flush_work(&dp->hotplug_work);
 	exynos_dp_phy_exit(dp);
 	clk_disable_unprepare(dp->clock);
+
+	if (dp->panel) {
+		if (drm_panel_unprepare(dp->panel))
+			DRM_ERROR("failed to turnoff the panel\n");
+	}
 }
 
 static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
@@ -1078,12 +1126,12 @@ static void exynos_dp_dpms(struct exynos
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		exynos_dp_poweron(dp);
+		exynos_dp_poweron(display);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		exynos_dp_poweroff(dp);
+		exynos_dp_poweroff(display);
 		break;
 	default:
 		break;
@@ -1094,6 +1142,7 @@ static void exynos_dp_dpms(struct exynos
 static struct exynos_drm_display_ops exynos_dp_display_ops = {
 	.create_connector = exynos_dp_create_connector,
 	.dpms = exynos_dp_dpms,
+	.commit = exynos_dp_commit,
 };
 
 static struct exynos_drm_display exynos_dp_display = {
@@ -1201,7 +1250,7 @@ static int exynos_dp_dt_parse_panel(stru
 {
 	int ret;
 
-	ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm,
+	ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm,
 			OF_USE_NATIVE_MODE);
 	if (ret) {
 		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
@@ -1215,16 +1264,10 @@ static int exynos_dp_bind(struct device
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm_dev = data;
 	struct resource *res;
-	struct exynos_dp_device *dp;
+	struct exynos_dp_device *dp = exynos_dp_display.ctx;
 	unsigned int irq_flags;
-
 	int ret = 0;
 
-	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
-				GFP_KERNEL);
-	if (!dp)
-		return -ENOMEM;
-
 	dp->dev = &pdev->dev;
 	dp->dpms_mode = DRM_MODE_DPMS_OFF;
 
@@ -1236,9 +1279,11 @@ static int exynos_dp_bind(struct device
 	if (ret)
 		return ret;
 
-	ret = exynos_dp_dt_parse_panel(dp);
-	if (ret)
-		return ret;
+	if (!dp->panel) {
+		ret = exynos_dp_dt_parse_panel(dp);
+		if (ret)
+			return ret;
+	}
 
 	dp->clock = devm_clk_get(&pdev->dev, "dp");
 	if (IS_ERR(dp->clock)) {
@@ -1298,7 +1343,6 @@ static int exynos_dp_bind(struct device
 	disable_irq(dp->irq);
 
 	dp->drm_dev = drm_dev;
-	exynos_dp_display.ctx = dp;
 
 	platform_set_drvdata(pdev, &exynos_dp_display);
 
@@ -1325,6 +1369,9 @@ static const struct component_ops exynos
 
 static int exynos_dp_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct device_node *panel_node;
+	struct exynos_dp_device *dp;
 	int ret;
 
 	ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
@@ -1332,6 +1379,21 @@ static int exynos_dp_probe(struct platfo
 	if (ret)
 		return ret;
 
+	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+				GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	panel_node = of_parse_phandle(dev->of_node, "panel", 0);
+	if (panel_node) {
+		dp->panel = of_drm_find_panel(panel_node);
+		of_node_put(panel_node);
+		if (!dp->panel)
+			return -EPROBE_DEFER;
+	}
+
+	exynos_dp_display.ctx = dp;
+
 	ret = component_add(&pdev->dev, &exynos_dp_ops);
 	if (ret)
 		exynos_drm_component_del(&pdev->dev,
@@ -1376,6 +1438,7 @@ static const struct of_device_id exynos_
 	{ .compatible = "samsung,exynos5-dp" },
 	{},
 };
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
 
 struct platform_driver dp_driver = {
 	.probe		= exynos_dp_probe,
@@ -1390,4 +1453,4 @@ struct platform_driver dp_driver = {
 
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
 MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h	2014-09-28 17:29:07.000000000 -0400
@@ -149,6 +149,7 @@ struct exynos_dp_device {
 	struct drm_device	*drm_dev;
 	struct drm_connector	connector;
 	struct drm_encoder	*encoder;
+	struct drm_panel	*panel;
 	struct clk		*clock;
 	unsigned int		irq;
 	void __iomem		*reg_base;
@@ -162,7 +163,7 @@ struct exynos_dp_device {
 	int			dpms_mode;
 	int			hpd_gpio;
 
-	struct exynos_drm_panel_info panel;
+	struct exynos_drm_panel_info priv;
 };
 
 /* exynos_dp_reg.c */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,20 +117,7 @@ static struct drm_encoder *exynos_drm_be
 	struct drm_device *dev = connector->dev;
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
-	obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
-				   DRM_MODE_OBJECT_ENCODER);
-	if (!obj) {
-		DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
-				exynos_connector->encoder_id);
-		return NULL;
-	}
-
-	encoder = obj_to_encoder(obj);
-
-	return encoder;
+	return drm_encoder_find(dev, exynos_connector->encoder_id);
 }
 
 static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
@@ -185,7 +172,7 @@ static void exynos_drm_connector_destroy
 	struct exynos_drm_connector *exynos_connector =
 		to_exynos_connector(connector);
 
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(exynos_connector);
 }
@@ -230,7 +217,7 @@ struct drm_connector *exynos_drm_connect
 	drm_connector_init(dev, connector, &exynos_connector_funcs, type);
 	drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
 
-	err = drm_sysfs_connector_add(connector);
+	err = drm_connector_register(connector);
 	if (err)
 		goto err_connector;
 
@@ -250,7 +237,7 @@ struct drm_connector *exynos_drm_connect
 	return connector;
 
 err_sysfs:
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 err_connector:
 	drm_connector_cleanup(connector);
 	kfree(exynos_connector);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,8 +69,10 @@ static void exynos_drm_crtc_dpms(struct
 
 	if (mode > DRM_MODE_DPMS_ON) {
 		/* wait for the completion of page flip. */
-		wait_event(exynos_crtc->pending_flip_queue,
-				atomic_read(&exynos_crtc->pending_flip) == 0);
+		if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
+				!atomic_read(&exynos_crtc->pending_flip),
+				HZ/20))
+			atomic_set(&exynos_crtc->pending_flip, 0);
 		drm_vblank_off(crtc->dev, exynos_crtc->pipe);
 	}
 
@@ -259,6 +261,7 @@ static int exynos_drm_crtc_page_flip(str
 			spin_lock_irq(&dev->event_lock);
 			drm_vblank_put(dev, exynos_crtc->pipe);
 			list_del(&event->base.link);
+			atomic_set(&exynos_crtc->pending_flip, 0);
 			spin_unlock_irq(&dev->event_lock);
 
 			goto out;
@@ -508,3 +511,11 @@ int exynos_drm_crtc_get_pipe_from_type(s
 
 	return -EPERM;
 }
+
+void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
+{
+	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+	if (manager->ops->te_handler)
+		manager->ops->te_handler(manager);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struc
 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
 					unsigned int out_type);
 
+/*
+ * This function calls the crtc device(manager)'s te_handler() callback
+ * to trigger to transfer video image at the tearing effect synchronization
+ * signal.
+ */
+void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -187,7 +187,7 @@ struct dma_buf *exynos_dmabuf_prime_expo
 	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
 
 	return dma_buf_export(obj, &exynos_dmabuf_ops,
-				exynos_gem_obj->base.size, flags);
+				exynos_gem_obj->base.size, flags, NULL);
 }
 
 struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@ exynos_dpi_detect(struct drm_connector *
 
 static void exynos_dpi_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 
@@ -117,7 +117,7 @@ static int exynos_dpi_create_connector(s
 	}
 
 	drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return 0;
@@ -125,14 +125,18 @@ static int exynos_dpi_create_connector(s
 
 static void exynos_dpi_poweron(struct exynos_dpi *ctx)
 {
-	if (ctx->panel)
+	if (ctx->panel) {
+		drm_panel_prepare(ctx->panel);
 		drm_panel_enable(ctx->panel);
+	}
 }
 
 static void exynos_dpi_poweroff(struct exynos_dpi *ctx)
 {
-	if (ctx->panel)
+	if (ctx->panel) {
 		drm_panel_disable(ctx->panel);
+		drm_panel_unprepare(ctx->panel);
+	}
 }
 
 static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,8 +39,6 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
-#define VBLANK_OFF_DELAY	50000
-
 static struct platform_device *exynos_drm_pdev;
 
 static DEFINE_MUTEX(drm_component_lock);
@@ -103,8 +101,6 @@ static int exynos_drm_load(struct drm_de
 	/* setup possible_clones. */
 	exynos_drm_encoder_setup(dev);
 
-	drm_vblank_offdelay = VBLANK_OFF_DELAY;
-
 	platform_set_drvdata(dev->platformdev, dev);
 
 	/* Try to bind all sub drivers. */
@@ -362,7 +358,7 @@ static int exynos_drm_sys_suspend(struct
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 	pm_message_t message;
 
-	if (pm_runtime_suspended(dev))
+	if (pm_runtime_suspended(dev) || !drm_dev)
 		return 0;
 
 	message.event = PM_EVENT_SUSPEND;
@@ -373,7 +369,7 @@ static int exynos_drm_sys_resume(struct
 {
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
-	if (pm_runtime_suspended(dev))
+	if (pm_runtime_suspended(dev) || !drm_dev)
 		return 0;
 
 	return exynos_drm_resume(drm_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,6 @@ struct drm_device;
 struct exynos_drm_overlay;
 struct drm_connector;
 
-extern unsigned int drm_vblank_offdelay;
-
 /* This enumerates device type. */
 enum exynos_drm_device_type {
 	EXYNOS_DEVICE_TYPE_NONE,
@@ -188,6 +186,8 @@ struct exynos_drm_display {
  * @win_commit: apply hardware specific overlay data to registers.
  * @win_enable: enable hardware specific overlay.
  * @win_disable: disable hardware specific overlay.
+ * @te_handler: trigger to transfer video image at the tearing effect
+ *	synchronization signal if there is a page flip request.
  */
 struct exynos_drm_manager;
 struct exynos_drm_manager_ops {
@@ -206,6 +206,7 @@ struct exynos_drm_manager_ops {
 	void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
 	void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
 	void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
+	void (*te_handler)(struct exynos_drm_manager *mgr);
 };
 
 /*
@@ -236,14 +237,9 @@ struct exynos_drm_g2d_private {
 	struct list_head	userptr_list;
 };
 
-struct exynos_drm_ipp_private {
-	struct device	*dev;
-	struct list_head	event_list;
-};
-
 struct drm_exynos_file_private {
 	struct exynos_drm_g2d_private	*g2d_priv;
-	struct exynos_drm_ipp_private	*ipp_priv;
+	struct device			*ipp_dev;
 	struct file			*anon_filp;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,10 @@
 #include <drm/drm_panel.h>
 
 #include <linux/clk.h>
+#include <linux/gpio/consumer.h>
 #include <linux/irq.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/phy/phy.h>
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
@@ -24,6 +27,7 @@
 #include <video/mipi_display.h>
 #include <video/videomode.h>
 
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_drv.h"
 
 /* returns true iff both arguments logically differs */
@@ -54,9 +58,12 @@
 
 /* FIFO memory AC characteristic register */
 #define DSIM_PLLCTRL_REG	0x4c	/* PLL control register */
-#define DSIM_PLLTMR_REG		0x50	/* PLL timer register */
 #define DSIM_PHYACCHR_REG	0x54	/* D-PHY AC characteristic register */
 #define DSIM_PHYACCHR1_REG	0x58	/* D-PHY AC characteristic register1 */
+#define DSIM_PHYCTRL_REG	0x5c
+#define DSIM_PHYTIMING_REG	0x64
+#define DSIM_PHYTIMING1_REG	0x68
+#define DSIM_PHYTIMING2_REG	0x6c
 
 /* DSIM_STATUS */
 #define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
@@ -200,6 +207,24 @@
 #define DSIM_PLL_M(x)			((x) << 4)
 #define DSIM_PLL_S(x)			((x) << 1)
 
+/* DSIM_PHYCTRL */
+#define DSIM_PHYCTRL_ULPS_EXIT(x)	(((x) & 0x1ff) << 0)
+
+/* DSIM_PHYTIMING */
+#define DSIM_PHYTIMING_LPX(x)		((x) << 8)
+#define DSIM_PHYTIMING_HS_EXIT(x)	((x) << 0)
+
+/* DSIM_PHYTIMING1 */
+#define DSIM_PHYTIMING1_CLK_PREPARE(x)	((x) << 24)
+#define DSIM_PHYTIMING1_CLK_ZERO(x)	((x) << 16)
+#define DSIM_PHYTIMING1_CLK_POST(x)	((x) << 8)
+#define DSIM_PHYTIMING1_CLK_TRAIL(x)	((x) << 0)
+
+/* DSIM_PHYTIMING2 */
+#define DSIM_PHYTIMING2_HS_PREPARE(x)	((x) << 16)
+#define DSIM_PHYTIMING2_HS_ZERO(x)	((x) << 8)
+#define DSIM_PHYTIMING2_HS_TRAIL(x)	((x) << 0)
+
 #define DSI_MAX_BUS_WIDTH		4
 #define DSI_NUM_VIRTUAL_CHANNELS	4
 #define DSI_TX_FIFO_SIZE		2048
@@ -233,6 +258,12 @@ struct exynos_dsi_transfer {
 #define DSIM_STATE_INITIALIZED		BIT(1)
 #define DSIM_STATE_CMD_LPM		BIT(2)
 
+struct exynos_dsi_driver_data {
+	unsigned int plltmr_reg;
+
+	unsigned int has_freqband:1;
+};
+
 struct exynos_dsi {
 	struct mipi_dsi_host dsi_host;
 	struct drm_connector connector;
@@ -247,6 +278,7 @@ struct exynos_dsi {
 	struct clk *bus_clk;
 	struct regulator_bulk_data supplies[2];
 	int irq;
+	int te_gpio;
 
 	u32 pll_clk_rate;
 	u32 burst_clk_rate;
@@ -262,11 +294,39 @@ struct exynos_dsi {
 
 	spinlock_t transfer_lock; /* protects transfer_list */
 	struct list_head transfer_list;
+
+	struct exynos_dsi_driver_data *driver_data;
 };
 
 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
 #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
 
+static struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
+	.plltmr_reg = 0x50,
+	.has_freqband = 1,
+};
+
+static struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
+	.plltmr_reg = 0x58,
+};
+
+static struct of_device_id exynos_dsi_of_match[] = {
+	{ .compatible = "samsung,exynos4210-mipi-dsi",
+	  .data = &exynos4_dsi_driver_data },
+	{ .compatible = "samsung,exynos5410-mipi-dsi",
+	  .data = &exynos5_dsi_driver_data },
+	{ }
+};
+
+static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
+						struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(exynos_dsi_of_match, &pdev->dev);
+
+	return (struct exynos_dsi_driver_data *)of_id->data;
+}
+
 static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
 {
 	if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
@@ -340,14 +400,9 @@ static unsigned long exynos_dsi_pll_find
 static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
 					unsigned long freq)
 {
-	static const unsigned long freq_bands[] = {
-		100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
-		270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
-		510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
-		770 * MHZ, 870 * MHZ, 950 * MHZ,
-	};
+	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	unsigned long fin, fout;
-	int timeout, band;
+	int timeout;
 	u8 p, s;
 	u16 m;
 	u32 reg;
@@ -368,18 +423,30 @@ static unsigned long exynos_dsi_set_pll(
 			"failed to find PLL PMS for requested frequency\n");
 		return -EFAULT;
 	}
+	dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
 
-	for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
-		if (fout < freq_bands[band])
-			break;
+	writel(500, dsi->reg_base + driver_data->plltmr_reg);
 
-	dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d), band %d\n", fout,
-		p, m, s, band);
+	reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
 
-	writel(500, dsi->reg_base + DSIM_PLLTMR_REG);
+	if (driver_data->has_freqband) {
+		static const unsigned long freq_bands[] = {
+			100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
+			270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
+			510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
+			770 * MHZ, 870 * MHZ, 950 * MHZ,
+		};
+		int band;
+
+		for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
+			if (fout < freq_bands[band])
+				break;
+
+		dev_dbg(dsi->dev, "band %d\n", band);
+
+		reg |= DSIM_FREQ_BAND(band);
+	}
 
-	reg = DSIM_FREQ_BAND(band) | DSIM_PLL_EN
-			| DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
 	writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
 
 	timeout = 1000;
@@ -433,6 +500,59 @@ static int exynos_dsi_enable_clock(struc
 	return 0;
 }
 
+static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
+{
+	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	u32 reg;
+
+	if (driver_data->has_freqband)
+		return;
+
+	/* B D-PHY: D-PHY Master & Slave Analog Block control */
+	reg = DSIM_PHYCTRL_ULPS_EXIT(0x0af);
+	writel(reg, dsi->reg_base + DSIM_PHYCTRL_REG);
+
+	/*
+	 * T LPX: Transmitted length of any Low-Power state period
+	 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
+	 *	burst
+	 */
+	reg = DSIM_PHYTIMING_LPX(0x06) | DSIM_PHYTIMING_HS_EXIT(0x0b);
+	writel(reg, dsi->reg_base + DSIM_PHYTIMING_REG);
+
+	/*
+	 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Clock.
+	 * T CLK_POST: Time that the transmitter continues to send HS clock
+	 *	after the last associated Data Lane has transitioned to LP Mode
+	 *	Interval is defined as the period from the end of T HS-TRAIL to
+	 *	the beginning of T CLK-TRAIL
+	 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
+	 *	the last payload clock bit of a HS transmission burst
+	 */
+	reg = DSIM_PHYTIMING1_CLK_PREPARE(0x07) |
+			DSIM_PHYTIMING1_CLK_ZERO(0x27) |
+			DSIM_PHYTIMING1_CLK_POST(0x0d) |
+			DSIM_PHYTIMING1_CLK_TRAIL(0x08);
+	writel(reg, dsi->reg_base + DSIM_PHYTIMING1_REG);
+
+	/*
+	 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Sync sequence.
+	 * T HS-TRAIL: Time that the transmitter drives the flipped differential
+	 *	state after last payload data bit of a HS transmission burst
+	 */
+	reg = DSIM_PHYTIMING2_HS_PREPARE(0x09) | DSIM_PHYTIMING2_HS_ZERO(0x0d) |
+			DSIM_PHYTIMING2_HS_TRAIL(0x0b);
+	writel(reg, dsi->reg_base + DSIM_PHYTIMING2_REG);
+}
+
 static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
 {
 	u32 reg;
@@ -468,13 +588,20 @@ static int exynos_dsi_init_link(struct e
 	/* DSI configuration */
 	reg = 0;
 
+	/*
+	 * The first bit of mode_flags specifies display configuration.
+	 * If this bit is set[= MIPI_DSI_MODE_VIDEO], dsi will support video
+	 * mode, otherwise it will support command mode.
+	 */
 	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
 		reg |= DSIM_VIDEO_MODE;
 
+		/*
+		 * The user manual describes that following bits are ignored in
+		 * command mode.
+		 */
 		if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
 			reg |= DSIM_MFLUSH_VS;
-		if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
-			reg |= DSIM_EOT_DISABLE;
 		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
 			reg |= DSIM_SYNC_INFORM;
 		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -491,6 +618,9 @@ static int exynos_dsi_init_link(struct e
 			reg |= DSIM_HSA_MODE;
 	}
 
+	if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+		reg |= DSIM_EOT_DISABLE;
+
 	switch (dsi->format) {
 	case MIPI_DSI_FMT_RGB888:
 		reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
@@ -944,17 +1074,90 @@ static irqreturn_t exynos_dsi_irq(int ir
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
+{
+	struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
+	struct drm_encoder *encoder = dsi->encoder;
+
+	if (dsi->state & DSIM_STATE_ENABLED)
+		exynos_drm_crtc_te_handler(encoder->crtc);
+
+	return IRQ_HANDLED;
+}
+
+static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
+{
+	enable_irq(dsi->irq);
+
+	if (gpio_is_valid(dsi->te_gpio))
+		enable_irq(gpio_to_irq(dsi->te_gpio));
+}
+
+static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
+{
+	if (gpio_is_valid(dsi->te_gpio))
+		disable_irq(gpio_to_irq(dsi->te_gpio));
+
+	disable_irq(dsi->irq);
+}
+
 static int exynos_dsi_init(struct exynos_dsi *dsi)
 {
-	exynos_dsi_enable_clock(dsi);
 	exynos_dsi_reset(dsi);
-	enable_irq(dsi->irq);
+	exynos_dsi_enable_irq(dsi);
+	exynos_dsi_enable_clock(dsi);
 	exynos_dsi_wait_for_reset(dsi);
+	exynos_dsi_set_phy_ctrl(dsi);
 	exynos_dsi_init_link(dsi);
 
 	return 0;
 }
 
+static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi)
+{
+	int ret;
+
+	dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0);
+	if (!gpio_is_valid(dsi->te_gpio)) {
+		dev_err(dsi->dev, "no te-gpios specified\n");
+		ret = dsi->te_gpio;
+		goto out;
+	}
+
+	ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
+	if (ret) {
+		dev_err(dsi->dev, "gpio request failed with %d\n", ret);
+		goto out;
+	}
+
+	/*
+	 * This TE GPIO IRQ should not be set to IRQ_NOAUTOEN, because panel
+	 * calls drm_panel_init() first then calls mipi_dsi_attach() in probe().
+	 * It means that te_gpio is invalid when exynos_dsi_enable_irq() is
+	 * called by drm_panel_init() before panel is attached.
+	 */
+	ret = request_threaded_irq(gpio_to_irq(dsi->te_gpio),
+					exynos_dsi_te_irq_handler, NULL,
+					IRQF_TRIGGER_RISING, "TE", dsi);
+	if (ret) {
+		dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
+		gpio_free(dsi->te_gpio);
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
+{
+	if (gpio_is_valid(dsi->te_gpio)) {
+		free_irq(gpio_to_irq(dsi->te_gpio), dsi);
+		gpio_free(dsi->te_gpio);
+		dsi->te_gpio = -ENOENT;
+	}
+}
+
 static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 				  struct mipi_dsi_device *device)
 {
@@ -968,6 +1171,19 @@ static int exynos_dsi_host_attach(struct
 	if (dsi->connector.dev)
 		drm_helper_hpd_irq_event(dsi->connector.dev);
 
+	/*
+	 * This is a temporary solution and should be made by more generic way.
+	 *
+	 * If attached panel device is for command mode one, dsi should register
+	 * TE interrupt handler.
+	 */
+	if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) {
+		int ret = exynos_dsi_register_te_irq(dsi);
+
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -976,6 +1192,8 @@ static int exynos_dsi_host_detach(struct
 {
 	struct exynos_dsi *dsi = host_to_dsi(host);
 
+	exynos_dsi_unregister_te_irq(dsi);
+
 	dsi->panel_node = NULL;
 
 	if (dsi->connector.dev)
@@ -1089,7 +1307,7 @@ static void exynos_dsi_poweroff(struct e
 
 		exynos_dsi_disable_clock(dsi);
 
-		disable_irq(dsi->irq);
+		exynos_dsi_disable_irq(dsi);
 	}
 
 	dsi->state &= ~DSIM_STATE_CMD_LPM;
@@ -1115,7 +1333,7 @@ static int exynos_dsi_enable(struct exyn
 	if (ret < 0)
 		return ret;
 
-	ret = drm_panel_enable(dsi->panel);
+	ret = drm_panel_prepare(dsi->panel);
 	if (ret < 0) {
 		exynos_dsi_poweroff(dsi);
 		return ret;
@@ -1124,6 +1342,14 @@ static int exynos_dsi_enable(struct exyn
 	exynos_dsi_set_display_mode(dsi);
 	exynos_dsi_set_display_enable(dsi, true);
 
+	ret = drm_panel_enable(dsi->panel);
+	if (ret < 0) {
+		exynos_dsi_set_display_enable(dsi, false);
+		drm_panel_unprepare(dsi->panel);
+		exynos_dsi_poweroff(dsi);
+		return ret;
+	}
+
 	dsi->state |= DSIM_STATE_ENABLED;
 
 	return 0;
@@ -1134,8 +1360,9 @@ static void exynos_dsi_disable(struct ex
 	if (!(dsi->state & DSIM_STATE_ENABLED))
 		return;
 
-	exynos_dsi_set_display_enable(dsi, false);
 	drm_panel_disable(dsi->panel);
+	exynos_dsi_set_display_enable(dsi, false);
+	drm_panel_unprepare(dsi->panel);
 	exynos_dsi_poweroff(dsi);
 
 	dsi->state &= ~DSIM_STATE_ENABLED;
@@ -1246,7 +1473,7 @@ static int exynos_dsi_create_connector(s
 	}
 
 	drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return 0;
@@ -1278,6 +1505,7 @@ static struct exynos_drm_display exynos_
 	.type = EXYNOS_DISPLAY_TYPE_LCD,
 	.ops = &exynos_dsi_display_ops,
 };
+MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
 
 /* of_* functions will be removed after merge of of_graph patches */
 static struct device_node *
@@ -1435,6 +1663,9 @@ static int exynos_dsi_probe(struct platf
 		goto err_del_component;
 	}
 
+	/* To be checked as invalid one */
+	dsi->te_gpio = -ENOENT;
+
 	init_completion(&dsi->completed);
 	spin_lock_init(&dsi->transfer_lock);
 	INIT_LIST_HEAD(&dsi->transfer_list);
@@ -1443,6 +1674,7 @@ static int exynos_dsi_probe(struct platf
 	dsi->dsi_host.dev = &pdev->dev;
 
 	dsi->dev = &pdev->dev;
+	dsi->driver_data = exynos_dsi_get_driver_data(pdev);
 
 	ret = exynos_dsi_parse_dt(dsi);
 	if (ret)
@@ -1525,11 +1757,6 @@ static int exynos_dsi_remove(struct plat
 	return 0;
 }
 
-static struct of_device_id exynos_dsi_of_match[] = {
-	{ .compatible = "samsung,exynos4210-mipi-dsi" },
-	{ }
-};
-
 struct platform_driver dsi_driver = {
 	.probe = exynos_dsi_probe,
 	.remove = exynos_dsi_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -225,7 +225,7 @@ out:
 	return ret;
 }
 
-static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
 	.fb_probe =	exynos_drm_fbdev_create,
 };
 
@@ -266,7 +266,8 @@ int exynos_drm_fbdev_init(struct drm_dev
 		return -ENOMEM;
 
 	private->fb_helper = helper = &fbdev->drm_fb_helper;
-	helper->funcs = &exynos_drm_fb_helper_funcs;
+
+	drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs);
 
 	num_crtc = dev->mode_config.num_crtc;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1887,6 +1887,7 @@ static const struct of_device_id fimc_of
 	{ .compatible = "samsung,exynos4212-fimc" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, fimc_of_match);
 
 struct platform_driver fimc_driver = {
 	.probe		= fimc_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,8 @@
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/component.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <video/of_display_timing.h>
 #include <video/of_videomode.h>
@@ -61,6 +63,24 @@
 /* color key value register for hardware window 1 ~ 4. */
 #define WKEYCON1_BASE(x)		((WKEYCON1 + 0x140) + ((x - 1) * 8))
 
+/* I80 / RGB trigger control register */
+#define TRIGCON				0x1A4
+#define TRGMODE_I80_RGB_ENABLE_I80	(1 << 0)
+#define SWTRGCMD_I80_RGB_ENABLE		(1 << 1)
+
+/* display mode change control register except exynos4 */
+#define VIDOUT_CON			0x000
+#define VIDOUT_CON_F_I80_LDI0		(0x2 << 8)
+
+/* I80 interface control for main LDI register */
+#define I80IFCONFAx(x)			(0x1B0 + (x) * 4)
+#define I80IFCONFBx(x)			(0x1B8 + (x) * 4)
+#define LCD_CS_SETUP(x)			((x) << 16)
+#define LCD_WR_SETUP(x)			((x) << 12)
+#define LCD_WR_ACTIVE(x)		((x) << 8)
+#define LCD_WR_HOLD(x)			((x) << 4)
+#define I80IFEN_ENABLE			(1 << 0)
+
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR	5
 
@@ -68,10 +88,14 @@
 
 struct fimd_driver_data {
 	unsigned int timing_base;
+	unsigned int lcdblk_offset;
+	unsigned int lcdblk_vt_shift;
+	unsigned int lcdblk_bypass_shift;
 
 	unsigned int has_shadowcon:1;
 	unsigned int has_clksel:1;
 	unsigned int has_limited_fmt:1;
+	unsigned int has_vidoutcon:1;
 };
 
 static struct fimd_driver_data s3c64xx_fimd_driver_data = {
@@ -82,12 +106,19 @@ static struct fimd_driver_data s3c64xx_f
 
 static struct fimd_driver_data exynos4_fimd_driver_data = {
 	.timing_base = 0x0,
+	.lcdblk_offset = 0x210,
+	.lcdblk_vt_shift = 10,
+	.lcdblk_bypass_shift = 1,
 	.has_shadowcon = 1,
 };
 
 static struct fimd_driver_data exynos5_fimd_driver_data = {
 	.timing_base = 0x20000,
+	.lcdblk_offset = 0x214,
+	.lcdblk_vt_shift = 24,
+	.lcdblk_bypass_shift = 15,
 	.has_shadowcon = 1,
+	.has_vidoutcon = 1,
 };
 
 struct fimd_win_data {
@@ -112,15 +143,22 @@ struct fimd_context {
 	struct clk			*bus_clk;
 	struct clk			*lcd_clk;
 	void __iomem			*regs;
+	struct regmap			*sysreg;
 	struct drm_display_mode		mode;
 	struct fimd_win_data		win_data[WINDOWS_NR];
 	unsigned int			default_win;
 	unsigned long			irq_flags;
+	u32				vidcon0;
 	u32				vidcon1;
+	u32				vidout_con;
+	u32				i80ifcon;
+	bool				i80_if;
 	bool				suspended;
 	int				pipe;
 	wait_queue_head_t		wait_vsync_queue;
 	atomic_t			wait_vsync_event;
+	atomic_t			win_updated;
+	atomic_t			triggering;
 
 	struct exynos_drm_panel_info panel;
 	struct fimd_driver_data *driver_data;
@@ -136,6 +174,7 @@ static const struct of_device_id fimd_dr
 	  .data = &exynos5_fimd_driver_data },
 	{},
 };
+MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
 
 static inline struct fimd_driver_data *drm_fimd_get_driver_data(
 	struct platform_device *pdev)
@@ -243,6 +282,14 @@ static u32 fimd_calc_clkdiv(struct fimd_
 	unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
 	u32 clkdiv;
 
+	if (ctx->i80_if) {
+		/*
+		 * The frame done interrupt should be occurred prior to the
+		 * next TE signal.
+		 */
+		ideal_clk *= 2;
+	}
+
 	/* Find the clock divider value that gets us closest to ideal_clk */
 	clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
 
@@ -271,11 +318,10 @@ static void fimd_commit(struct exynos_dr
 {
 	struct fimd_context *ctx = mgr->ctx;
 	struct drm_display_mode *mode = &ctx->mode;
-	struct fimd_driver_data *driver_data;
-	u32 val, clkdiv, vidcon1;
-	int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
+	struct fimd_driver_data *driver_data = ctx->driver_data;
+	void *timing_base = ctx->regs + driver_data->timing_base;
+	u32 val, clkdiv;
 
-	driver_data = ctx->driver_data;
 	if (ctx->suspended)
 		return;
 
@@ -283,33 +329,65 @@ static void fimd_commit(struct exynos_dr
 	if (mode->htotal == 0 || mode->vtotal == 0)
 		return;
 
-	/* setup polarity values */
-	vidcon1 = ctx->vidcon1;
-	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-		vidcon1 |= VIDCON1_INV_VSYNC;
-	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-		vidcon1 |= VIDCON1_INV_HSYNC;
-	writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+	if (ctx->i80_if) {
+		val = ctx->i80ifcon | I80IFEN_ENABLE;
+		writel(val, timing_base + I80IFCONFAx(0));
 
-	/* setup vertical timing values. */
-	vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
-	vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
-	vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+		/* disable auto frame rate */
+		writel(0, timing_base + I80IFCONFBx(0));
 
-	val = VIDTCON0_VBPD(vbpd - 1) |
-		VIDTCON0_VFPD(vfpd - 1) |
-		VIDTCON0_VSPW(vsync_len - 1);
-	writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
+		/* set video type selection to I80 interface */
+		if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+					driver_data->lcdblk_offset,
+					0x3 << driver_data->lcdblk_vt_shift,
+					0x1 << driver_data->lcdblk_vt_shift)) {
+			DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
+			return;
+		}
+	} else {
+		int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
+		u32 vidcon1;
 
-	/* setup horizontal timing values.  */
-	hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
-	hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
-	hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+		/* setup polarity values */
+		vidcon1 = ctx->vidcon1;
+		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+			vidcon1 |= VIDCON1_INV_VSYNC;
+		if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+			vidcon1 |= VIDCON1_INV_HSYNC;
+		writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
 
-	val = VIDTCON1_HBPD(hbpd - 1) |
-		VIDTCON1_HFPD(hfpd - 1) |
-		VIDTCON1_HSPW(hsync_len - 1);
-	writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+		/* setup vertical timing values. */
+		vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+		vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
+		vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
+		val = VIDTCON0_VBPD(vbpd - 1) |
+			VIDTCON0_VFPD(vfpd - 1) |
+			VIDTCON0_VSPW(vsync_len - 1);
+		writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
+
+		/* setup horizontal timing values.  */
+		hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+		hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
+		hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+
+		val = VIDTCON1_HBPD(hbpd - 1) |
+			VIDTCON1_HFPD(hfpd - 1) |
+			VIDTCON1_HSPW(hsync_len - 1);
+		writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+	}
+
+	if (driver_data->has_vidoutcon)
+		writel(ctx->vidout_con, timing_base + VIDOUT_CON);
+
+	/* set bypass selection */
+	if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+				driver_data->lcdblk_offset,
+				0x1 << driver_data->lcdblk_bypass_shift,
+				0x1 << driver_data->lcdblk_bypass_shift)) {
+		DRM_ERROR("Failed to update sysreg for bypass setting.\n");
+		return;
+	}
 
 	/* setup horizontal and vertical display size. */
 	val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
@@ -322,7 +400,8 @@ static void fimd_commit(struct exynos_dr
 	 * fields of register with prefix '_F' would be updated
 	 * at vsync(same as dma start)
 	 */
-	val = VIDCON0_ENVID | VIDCON0_ENVID_F;
+	val = ctx->vidcon0;
+	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
 
 	if (ctx->driver_data->has_clksel)
 		val |= VIDCON0_CLKSEL_LCD;
@@ -660,6 +739,9 @@ static void fimd_win_commit(struct exyno
 	}
 
 	win_data->enabled = true;
+
+	if (ctx->i80_if)
+		atomic_set(&ctx->win_updated, 1);
 }
 
 static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
@@ -838,6 +920,58 @@ static void fimd_dpms(struct exynos_drm_
 	}
 }
 
+static void fimd_trigger(struct device *dev)
+{
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_driver_data *driver_data = ctx->driver_data;
+	void *timing_base = ctx->regs + driver_data->timing_base;
+	u32 reg;
+
+	atomic_set(&ctx->triggering, 1);
+
+	reg = readl(ctx->regs + VIDINTCON0);
+	reg |= (VIDINTCON0_INT_ENABLE | VIDINTCON0_INT_I80IFDONE |
+						VIDINTCON0_INT_SYSMAINCON);
+	writel(reg, ctx->regs + VIDINTCON0);
+
+	reg = readl(timing_base + TRIGCON);
+	reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
+	writel(reg, timing_base + TRIGCON);
+}
+
+static void fimd_te_handler(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+
+	/* Checks the crtc is detached already from encoder */
+	if (ctx->pipe < 0 || !ctx->drm_dev)
+		return;
+
+	 /*
+	 * Skips to trigger if in triggering state, because multiple triggering
+	 * requests can cause panel reset.
+	 */
+	if (atomic_read(&ctx->triggering))
+		return;
+
+	/*
+	 * If there is a page flip request, triggers and handles the page flip
+	 * event so that current fb can be updated into panel GRAM.
+	 */
+	if (atomic_add_unless(&ctx->win_updated, -1, 0))
+		fimd_trigger(ctx->dev);
+
+	/* Wakes up vsync event queue */
+	if (atomic_read(&ctx->wait_vsync_event)) {
+		atomic_set(&ctx->wait_vsync_event, 0);
+		wake_up(&ctx->wait_vsync_queue);
+
+		if (!atomic_read(&ctx->triggering))
+			drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+	}
+}
+
 static struct exynos_drm_manager_ops fimd_manager_ops = {
 	.dpms = fimd_dpms,
 	.mode_fixup = fimd_mode_fixup,
@@ -849,6 +983,7 @@ static struct exynos_drm_manager_ops fim
 	.win_mode_set = fimd_win_mode_set,
 	.win_commit = fimd_win_commit,
 	.win_disable = fimd_win_disable,
+	.te_handler = fimd_te_handler,
 };
 
 static struct exynos_drm_manager fimd_manager = {
@@ -859,26 +994,40 @@ static struct exynos_drm_manager fimd_ma
 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 {
 	struct fimd_context *ctx = (struct fimd_context *)dev_id;
-	u32 val;
+	u32 val, clear_bit;
 
 	val = readl(ctx->regs + VIDINTCON1);
 
-	if (val & VIDINTCON1_INT_FRAME)
-		/* VSYNC interrupt */
-		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+	clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
+	if (val & clear_bit)
+		writel(clear_bit, ctx->regs + VIDINTCON1);
 
 	/* check the crtc is detached already from encoder */
 	if (ctx->pipe < 0 || !ctx->drm_dev)
 		goto out;
 
-	drm_handle_vblank(ctx->drm_dev, ctx->pipe);
-	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+	if (ctx->i80_if) {
+		/* unset I80 frame done interrupt */
+		val = readl(ctx->regs + VIDINTCON0);
+		val &= ~(VIDINTCON0_INT_I80IFDONE | VIDINTCON0_INT_SYSMAINCON);
+		writel(val, ctx->regs + VIDINTCON0);
 
-	/* set wait vsync event to zero and wake up queue. */
-	if (atomic_read(&ctx->wait_vsync_event)) {
-		atomic_set(&ctx->wait_vsync_event, 0);
-		wake_up(&ctx->wait_vsync_queue);
+		/* exit triggering mode */
+		atomic_set(&ctx->triggering, 0);
+
+		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+	} else {
+		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+
+		/* set wait vsync event to zero and wake up queue. */
+		if (atomic_read(&ctx->wait_vsync_event)) {
+			atomic_set(&ctx->wait_vsync_event, 0);
+			wake_up(&ctx->wait_vsync_queue);
+		}
 	}
+
 out:
 	return IRQ_HANDLED;
 }
@@ -923,6 +1072,7 @@ static int fimd_probe(struct platform_de
 {
 	struct device *dev = &pdev->dev;
 	struct fimd_context *ctx;
+	struct device_node *i80_if_timings;
 	struct resource *res;
 	int ret = -EINVAL;
 
@@ -944,12 +1094,51 @@ static int fimd_probe(struct platform_de
 
 	ctx->dev = dev;
 	ctx->suspended = true;
+	ctx->driver_data = drm_fimd_get_driver_data(pdev);
 
 	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
 		ctx->vidcon1 |= VIDCON1_INV_VDEN;
 	if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
 		ctx->vidcon1 |= VIDCON1_INV_VCLK;
 
+	i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
+	if (i80_if_timings) {
+		u32 val;
+
+		ctx->i80_if = true;
+
+		if (ctx->driver_data->has_vidoutcon)
+			ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
+		else
+			ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
+		/*
+		 * The user manual describes that this "DSI_EN" bit is required
+		 * to enable I80 24-bit data interface.
+		 */
+		ctx->vidcon0 |= VIDCON0_DSI_EN;
+
+		if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
+			val = 0;
+		ctx->i80ifcon = LCD_CS_SETUP(val);
+		if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
+			val = 0;
+		ctx->i80ifcon |= LCD_WR_SETUP(val);
+		if (of_property_read_u32(i80_if_timings, "wr-active", &val))
+			val = 1;
+		ctx->i80ifcon |= LCD_WR_ACTIVE(val);
+		if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
+			val = 0;
+		ctx->i80ifcon |= LCD_WR_HOLD(val);
+	}
+	of_node_put(i80_if_timings);
+
+	ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+							"samsung,sysreg");
+	if (IS_ERR(ctx->sysreg)) {
+		dev_warn(dev, "failed to get system register.\n");
+		ctx->sysreg = NULL;
+	}
+
 	ctx->bus_clk = devm_clk_get(dev, "fimd");
 	if (IS_ERR(ctx->bus_clk)) {
 		dev_err(dev, "failed to get bus clock\n");
@@ -972,7 +1161,8 @@ static int fimd_probe(struct platform_de
 		goto err_del_component;
 	}
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync");
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+					   ctx->i80_if ? "lcd_sys" : "vsync");
 	if (!res) {
 		dev_err(dev, "irq request failed.\n");
 		ret = -ENXIO;
@@ -986,7 +1176,6 @@ static int fimd_probe(struct platform_de
 		goto err_del_component;
 	}
 
-	ctx->driver_data = drm_fimd_get_driver_data(pdev);
 	init_waitqueue_head(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c	2014-09-28 17:29:07.000000000 -0400
@@ -1042,8 +1042,23 @@ err:
 int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
 			     struct drm_file *file)
 {
+	struct drm_exynos_file_private *file_priv = file->driver_priv;
+	struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
+	struct device *dev;
+	struct g2d_data *g2d;
 	struct drm_exynos_g2d_get_ver *ver = data;
 
+	if (!g2d_priv)
+		return -ENODEV;
+
+	dev = g2d_priv->dev;
+	if (!dev)
+		return -ENODEV;
+
+	g2d = dev_get_drvdata(dev);
+	if (!g2d)
+		return -EFAULT;
+
 	ver->major = G2D_HW_MAJOR_VER;
 	ver->minor = G2D_HW_MINOR_VER;
 
@@ -1056,7 +1071,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
 	struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
-	struct device *dev = g2d_priv->dev;
+	struct device *dev;
 	struct g2d_data *g2d;
 	struct drm_exynos_g2d_set_cmdlist *req = data;
 	struct drm_exynos_g2d_cmd *cmd;
@@ -1067,6 +1082,10 @@ int exynos_g2d_set_cmdlist_ioctl(struct
 	int size;
 	int ret;
 
+	if (!g2d_priv)
+		return -ENODEV;
+
+	dev = g2d_priv->dev;
 	if (!dev)
 		return -ENODEV;
 
@@ -1223,13 +1242,17 @@ int exynos_g2d_exec_ioctl(struct drm_dev
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
 	struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
-	struct device *dev = g2d_priv->dev;
+	struct device *dev;
 	struct g2d_data *g2d;
 	struct drm_exynos_g2d_exec *req = data;
 	struct g2d_runqueue_node *runqueue_node;
 	struct list_head *run_cmdlist;
 	struct list_head *event_list;
 
+	if (!g2d_priv)
+		return -ENODEV;
+
+	dev = g2d_priv->dev;
 	if (!dev)
 		return -ENODEV;
 
@@ -1544,8 +1567,10 @@ static const struct dev_pm_ops g2d_pm_op
 
 static const struct of_device_id exynos_g2d_match[] = {
 	{ .compatible = "samsung,exynos5250-g2d" },
+	{ .compatible = "samsung,exynos4212-g2d" },
 	{},
 };
+MODULE_DEVICE_TABLE(of, exynos_g2d_match);
 
 struct platform_driver g2d_driver = {
 	.probe		= g2d_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -301,7 +301,6 @@ void exynos_drm_gem_put_dma_addr(struct
 					unsigned int gem_handle,
 					struct drm_file *filp)
 {
-	struct exynos_drm_gem_obj *exynos_gem_obj;
 	struct drm_gem_object *obj;
 
 	obj = drm_gem_object_lookup(dev, filp, gem_handle);
@@ -310,8 +309,6 @@ void exynos_drm_gem_put_dma_addr(struct
 		return;
 	}
 
-	exynos_gem_obj = to_exynos_gem_obj(obj);
-
 	drm_gem_object_unreference_unlocked(obj);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,9 +129,6 @@ void exynos_platform_device_ipp_unregist
 
 int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
 {
-	if (!ippdrv)
-		return -EINVAL;
-
 	mutex_lock(&exynos_drm_ippdrv_lock);
 	list_add_tail(&ippdrv->drv_list, &exynos_drm_ippdrv_list);
 	mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -141,9 +138,6 @@ int exynos_drm_ippdrv_register(struct ex
 
 int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
 {
-	if (!ippdrv)
-		return -EINVAL;
-
 	mutex_lock(&exynos_drm_ippdrv_lock);
 	list_del(&ippdrv->drv_list);
 	mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -151,20 +145,15 @@ int exynos_drm_ippdrv_unregister(struct
 	return 0;
 }
 
-static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
-		u32 *idp)
+static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj)
 {
 	int ret;
 
-	/* do the allocation under our mutexlock */
 	mutex_lock(lock);
 	ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
 	mutex_unlock(lock);
-	if (ret < 0)
-		return ret;
 
-	*idp = ret;
-	return 0;
+	return ret;
 }
 
 static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id)
@@ -178,35 +167,25 @@ static void *ipp_find_obj(struct idr *id
 {
 	void *obj;
 
-	DRM_DEBUG_KMS("id[%d]\n", id);
-
 	mutex_lock(lock);
-
-	/* find object using handle */
 	obj = idr_find(id_idr, id);
-	if (!obj) {
-		DRM_ERROR("failed to find object.\n");
-		mutex_unlock(lock);
-		return ERR_PTR(-ENODEV);
-	}
-
 	mutex_unlock(lock);
 
 	return obj;
 }
 
-static inline bool ipp_check_dedicated(struct exynos_drm_ippdrv *ippdrv,
-		enum drm_exynos_ipp_cmd	cmd)
+static int ipp_check_driver(struct exynos_drm_ippdrv *ippdrv,
+			    struct drm_exynos_ipp_property *property)
 {
-	/*
-	 * check dedicated flag and WB, OUTPUT operation with
-	 * power on state.
-	 */
-	if (ippdrv->dedicated || (!ipp_is_m2m_cmd(cmd) &&
-	    !pm_runtime_suspended(ippdrv->dev)))
-		return true;
+	if (ippdrv->dedicated || (!ipp_is_m2m_cmd(property->cmd) &&
+				  !pm_runtime_suspended(ippdrv->dev)))
+		return -EBUSY;
 
-	return false;
+	if (ippdrv->check_property &&
+	    ippdrv->check_property(ippdrv->dev, property))
+		return -EINVAL;
+
+	return 0;
 }
 
 static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
@@ -214,62 +193,30 @@ static struct exynos_drm_ippdrv *ipp_fin
 {
 	struct exynos_drm_ippdrv *ippdrv;
 	u32 ipp_id = property->ipp_id;
-
-	DRM_DEBUG_KMS("ipp_id[%d]\n", ipp_id);
+	int ret;
 
 	if (ipp_id) {
-		/* find ipp driver using idr */
-		ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
-			ipp_id);
-		if (IS_ERR(ippdrv)) {
-			DRM_ERROR("not found ipp%d driver.\n", ipp_id);
-			return ippdrv;
-		}
-
-		/*
-		 * WB, OUTPUT opertion not supported multi-operation.
-		 * so, make dedicated state at set property ioctl.
-		 * when ipp driver finished operations, clear dedicated flags.
-		 */
-		if (ipp_check_dedicated(ippdrv, property->cmd)) {
-			DRM_ERROR("already used choose device.\n");
-			return ERR_PTR(-EBUSY);
+		ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, ipp_id);
+		if (!ippdrv) {
+			DRM_DEBUG("ipp%d driver not found\n", ipp_id);
+			return ERR_PTR(-ENODEV);
 		}
 
-		/*
-		 * This is necessary to find correct device in ipp drivers.
-		 * ipp drivers have different abilities,
-		 * so need to check property.
-		 */
-		if (ippdrv->check_property &&
-		    ippdrv->check_property(ippdrv->dev, property)) {
-			DRM_ERROR("not support property.\n");
-			return ERR_PTR(-EINVAL);
+		ret = ipp_check_driver(ippdrv, property);
+		if (ret < 0) {
+			DRM_DEBUG("ipp%d driver check error %d\n", ipp_id, ret);
+			return ERR_PTR(ret);
 		}
 
 		return ippdrv;
 	} else {
-		/*
-		 * This case is search all ipp driver for finding.
-		 * user application don't set ipp_id in this case,
-		 * so ipp subsystem search correct driver in driver list.
-		 */
 		list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
-			if (ipp_check_dedicated(ippdrv, property->cmd)) {
-				DRM_DEBUG_KMS("used device.\n");
-				continue;
-			}
-
-			if (ippdrv->check_property &&
-			    ippdrv->check_property(ippdrv->dev, property)) {
-				DRM_DEBUG_KMS("not support property.\n");
-				continue;
-			}
-
-			return ippdrv;
+			ret = ipp_check_driver(ippdrv, property);
+			if (ret == 0)
+				return ippdrv;
 		}
 
-		DRM_ERROR("not support ipp driver operations.\n");
+		DRM_DEBUG("cannot find driver suitable for given property.\n");
 	}
 
 	return ERR_PTR(-ENODEV);
@@ -308,8 +255,7 @@ int exynos_drm_ipp_get_property(struct d
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
-	struct device *dev = priv->dev;
+	struct device *dev = file_priv->ipp_dev;
 	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_prop_list *prop_list = data;
 	struct exynos_drm_ippdrv *ippdrv;
@@ -346,10 +292,10 @@ int exynos_drm_ipp_get_property(struct d
 		 */
 		ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
 						prop_list->ipp_id);
-		if (IS_ERR(ippdrv)) {
+		if (!ippdrv) {
 			DRM_ERROR("not found ipp%d driver.\n",
 					prop_list->ipp_id);
-			return PTR_ERR(ippdrv);
+			return -ENODEV;
 		}
 
 		*prop_list = ippdrv->prop_list;
@@ -432,7 +378,7 @@ static struct drm_exynos_ipp_event_work
 	if (!event_work)
 		return ERR_PTR(-ENOMEM);
 
-	INIT_WORK((struct work_struct *)event_work, ipp_sched_event);
+	INIT_WORK(&event_work->work, ipp_sched_event);
 
 	return event_work;
 }
@@ -441,8 +387,7 @@ int exynos_drm_ipp_set_property(struct d
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
-	struct device *dev = priv->dev;
+	struct device *dev = file_priv->ipp_dev;
 	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_property *property = data;
 	struct exynos_drm_ippdrv *ippdrv;
@@ -489,19 +434,18 @@ int exynos_drm_ipp_set_property(struct d
 	if (!c_node)
 		return -ENOMEM;
 
-	/* create property id */
-	ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node,
-		&property->prop_id);
-	if (ret) {
+	ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node);
+	if (ret < 0) {
 		DRM_ERROR("failed to create id.\n");
 		goto err_clear;
 	}
+	property->prop_id = ret;
 
 	DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
 		property->prop_id, property->cmd, (int)ippdrv);
 
 	/* stored property information and ippdrv in private data */
-	c_node->priv = priv;
+	c_node->dev = dev;
 	c_node->property = *property;
 	c_node->state = IPP_STATE_IDLE;
 
@@ -534,7 +478,6 @@ int exynos_drm_ipp_set_property(struct d
 		INIT_LIST_HEAD(&c_node->mem_list[i]);
 
 	INIT_LIST_HEAD(&c_node->event_list);
-	list_splice_init(&priv->event_list, &c_node->event_list);
 	mutex_lock(&ippdrv->cmd_lock);
 	list_add_tail(&c_node->list, &ippdrv->cmd_list);
 	mutex_unlock(&ippdrv->cmd_lock);
@@ -577,42 +520,18 @@ static void ipp_clean_cmd_node(struct ip
 	kfree(c_node);
 }
 
-static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
+static bool ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
 {
-	struct drm_exynos_ipp_property *property = &c_node->property;
-	struct drm_exynos_ipp_mem_node *m_node;
-	struct list_head *head;
-	int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, };
-
-	for_each_ipp_ops(i) {
-		/* source/destination memory list */
-		head = &c_node->mem_list[i];
-
-		/* find memory node entry */
-		list_for_each_entry(m_node, head, list) {
-			DRM_DEBUG_KMS("%s,count[%d]m_node[0x%x]\n",
-				i ? "dst" : "src", count[i], (int)m_node);
-			count[i]++;
-		}
+	switch (c_node->property.cmd) {
+	case IPP_CMD_WB:
+		return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
+	case IPP_CMD_OUTPUT:
+		return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]);
+	case IPP_CMD_M2M:
+	default:
+		return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]) &&
+		       !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
 	}
-
-	DRM_DEBUG_KMS("min[%d]max[%d]\n",
-		min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
-		max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
-
-	/*
-	 * M2M operations should be need paired memory address.
-	 * so, need to check minimum count about src, dst.
-	 * other case not use paired memory, so use maximum count
-	 */
-	if (ipp_is_m2m_cmd(property->cmd))
-		ret = min(count[EXYNOS_DRM_OPS_SRC],
-			count[EXYNOS_DRM_OPS_DST]);
-	else
-		ret = max(count[EXYNOS_DRM_OPS_SRC],
-			count[EXYNOS_DRM_OPS_DST]);
-
-	return ret;
 }
 
 static struct drm_exynos_ipp_mem_node
@@ -683,16 +602,14 @@ static struct drm_exynos_ipp_mem_node
 		struct drm_exynos_ipp_queue_buf *qbuf)
 {
 	struct drm_exynos_ipp_mem_node *m_node;
-	struct drm_exynos_ipp_buf_info buf_info;
-	void *addr;
+	struct drm_exynos_ipp_buf_info *buf_info;
 	int i;
 
 	m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
 	if (!m_node)
 		return ERR_PTR(-ENOMEM);
 
-	/* clear base address for error handling */
-	memset(&buf_info, 0x0, sizeof(buf_info));
+	buf_info = &m_node->buf_info;
 
 	/* operations, buffer id */
 	m_node->ops_id = qbuf->ops_id;
@@ -707,6 +624,8 @@ static struct drm_exynos_ipp_mem_node
 
 		/* get dma address by handle */
 		if (qbuf->handle[i]) {
+			dma_addr_t *addr;
+
 			addr = exynos_drm_gem_get_dma_addr(drm_dev,
 					qbuf->handle[i], file);
 			if (IS_ERR(addr)) {
@@ -714,15 +633,14 @@ static struct drm_exynos_ipp_mem_node
 				goto err_clear;
 			}
 
-			buf_info.handles[i] = qbuf->handle[i];
-			buf_info.base[i] = *(dma_addr_t *) addr;
-			DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%x]\n",
-				i, buf_info.base[i], (int)buf_info.handles[i]);
+			buf_info->handles[i] = qbuf->handle[i];
+			buf_info->base[i] = *addr;
+			DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i,
+				      buf_info->base[i], buf_info->handles[i]);
 		}
 	}
 
 	m_node->filp = file;
-	m_node->buf_info = buf_info;
 	mutex_lock(&c_node->mem_lock);
 	list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
 	mutex_unlock(&c_node->mem_lock);
@@ -930,8 +848,7 @@ int exynos_drm_ipp_queue_buf(struct drm_
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
-	struct device *dev = priv->dev;
+	struct device *dev = file_priv->ipp_dev;
 	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_queue_buf *qbuf = data;
 	struct drm_exynos_ipp_cmd_node *c_node;
@@ -955,9 +872,9 @@ int exynos_drm_ipp_queue_buf(struct drm_
 	/* find command node */
 	c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
 		qbuf->prop_id);
-	if (IS_ERR(c_node)) {
+	if (!c_node) {
 		DRM_ERROR("failed to get command node.\n");
-		return PTR_ERR(c_node);
+		return -ENODEV;
 	}
 
 	/* buffer control */
@@ -1062,9 +979,8 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_d
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
 	struct exynos_drm_ippdrv *ippdrv = NULL;
-	struct device *dev = priv->dev;
+	struct device *dev = file_priv->ipp_dev;
 	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data;
 	struct drm_exynos_ipp_cmd_work *cmd_work;
@@ -1091,9 +1007,9 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_d
 
 	c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
 		cmd_ctrl->prop_id);
-	if (IS_ERR(c_node)) {
+	if (!c_node) {
 		DRM_ERROR("invalid command node list.\n");
-		return PTR_ERR(c_node);
+		return -ENODEV;
 	}
 
 	if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl,
@@ -1198,7 +1114,6 @@ static int ipp_set_property(struct exyno
 	/* reset h/w block */
 	if (ippdrv->reset &&
 	    ippdrv->reset(ippdrv->dev)) {
-		DRM_ERROR("failed to reset.\n");
 		return -EINVAL;
 	}
 
@@ -1216,30 +1131,24 @@ static int ipp_set_property(struct exyno
 		/* set format */
 		if (ops->set_fmt) {
 			ret = ops->set_fmt(ippdrv->dev, config->fmt);
-			if (ret) {
-				DRM_ERROR("not support format.\n");
+			if (ret)
 				return ret;
-			}
 		}
 
 		/* set transform for rotation, flip */
 		if (ops->set_transf) {
 			ret = ops->set_transf(ippdrv->dev, config->degree,
 				config->flip, &swap);
-			if (ret) {
-				DRM_ERROR("not support tranf.\n");
-				return -EINVAL;
-			}
+			if (ret)
+				return ret;
 		}
 
 		/* set size */
 		if (ops->set_size) {
 			ret = ops->set_size(ippdrv->dev, swap, &config->pos,
 				&config->sz);
-			if (ret) {
-				DRM_ERROR("not support size.\n");
+			if (ret)
 				return ret;
-			}
 		}
 	}
 
@@ -1283,11 +1192,6 @@ static int ipp_start_property(struct exy
 
 			m_node = list_first_entry(head,
 				struct drm_exynos_ipp_mem_node, list);
-			if (!m_node) {
-				DRM_ERROR("failed to get node.\n");
-				ret = -EFAULT;
-				goto err_unlock;
-			}
 
 			DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
 
@@ -1545,11 +1449,6 @@ static int ipp_send_event(struct exynos_
 
 			m_node = list_first_entry(head,
 				struct drm_exynos_ipp_mem_node, list);
-			if (!m_node) {
-				DRM_ERROR("empty memory node.\n");
-				ret = -ENOMEM;
-				goto err_mem_unlock;
-			}
 
 			tbuf_id[i] = m_node->buf_id;
 			DRM_DEBUG_KMS("%s buf_id[%d]\n",
@@ -1586,11 +1485,6 @@ static int ipp_send_event(struct exynos_
 
 		m_node = list_first_entry(head,
 			struct drm_exynos_ipp_mem_node, list);
-		if (!m_node) {
-			DRM_ERROR("empty memory node.\n");
-			ret = -ENOMEM;
-			goto err_mem_unlock;
-		}
 
 		tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id;
 
@@ -1704,21 +1598,17 @@ static int ipp_subdrv_probe(struct drm_d
 
 	/* get ipp driver entry */
 	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
-		u32 ipp_id;
-
 		ippdrv->drm_dev = drm_dev;
 
-		ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv,
-				    &ipp_id);
-		if (ret || ipp_id == 0) {
+		ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv);
+		if (ret < 0) {
 			DRM_ERROR("failed to create id.\n");
 			goto err;
 		}
+		ippdrv->prop_list.ipp_id = ret;
 
 		DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
-			count++, (int)ippdrv, ipp_id);
-
-		ippdrv->prop_list.ipp_id = ipp_id;
+			count++, (int)ippdrv, ret);
 
 		/* store parent device for node */
 		ippdrv->parent_dev = dev;
@@ -1776,17 +1666,10 @@ static int ipp_subdrv_open(struct drm_de
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	priv->dev = dev;
-	file_priv->ipp_priv = priv;
-
-	INIT_LIST_HEAD(&priv->event_list);
+	file_priv->ipp_dev = dev;
 
-	DRM_DEBUG_KMS("done priv[0x%x]\n", (int)priv);
+	DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev);
 
 	return 0;
 }
@@ -1795,13 +1678,12 @@ static void ipp_subdrv_close(struct drm_
 		struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
-	struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
 	struct exynos_drm_ippdrv *ippdrv = NULL;
 	struct ipp_context *ctx = get_ipp_context(dev);
 	struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
 	int count = 0;
 
-	DRM_DEBUG_KMS("for priv[0x%x]\n", (int)priv);
+	DRM_DEBUG_KMS("for priv[0x%x]\n", (int)file_priv->ipp_dev);
 
 	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
 		mutex_lock(&ippdrv->cmd_lock);
@@ -1810,7 +1692,7 @@ static void ipp_subdrv_close(struct drm_
 			DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
 				count++, (int)ippdrv);
 
-			if (c_node->priv == priv) {
+			if (c_node->dev == file_priv->ipp_dev) {
 				/*
 				 * userland goto unnormal state. process killed.
 				 * and close the file.
@@ -1832,7 +1714,6 @@ static void ipp_subdrv_close(struct drm_
 		mutex_unlock(&ippdrv->cmd_lock);
 	}
 
-	kfree(priv);
 	return;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_ipp.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work {
 /*
  * A structure of command node.
  *
- * @priv: IPP private information.
+ * @dev: IPP device.
  * @list: list head to command queue information.
  * @event_list: list head of event.
  * @mem_list: list head to source,destination memory queue information.
@@ -64,7 +64,7 @@ struct drm_exynos_ipp_cmd_work {
  * @state: state of command node.
  */
 struct drm_exynos_ipp_cmd_node {
-	struct exynos_drm_ipp_private *priv;
+	struct device		*dev;
 	struct list_head	list;
 	struct list_head	event_list;
 	struct list_head	mem_list[EXYNOS_DRM_OPS_MAX];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c	2014-09-28 17:29:07.000000000 -0400
@@ -691,6 +691,7 @@ static const struct of_device_id exynos_
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, exynos_rotator_match);
 
 static int rotator_probe(struct platform_device *pdev)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_vidi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_vidi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_drm_vidi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_drm_vidi.c	2014-09-28 17:29:07.000000000 -0400
@@ -562,7 +562,7 @@ static int vidi_create_connector(struct
 	}
 
 	drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -84,6 +84,7 @@ struct hdmi_resources {
 	struct clk			*sclk_hdmiphy;
 	struct clk			*mout_hdmi;
 	struct regulator_bulk_data	*regul_bulk;
+	struct regulator		*reg_hdmi_en;
 	int				regul_count;
 };
 
@@ -592,6 +593,13 @@ static struct hdmi_driver_data exynos421
 	.is_apb_phy	= 0,
 };
 
+static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
+	.type		= HDMI_TYPE13,
+	.phy_confs	= hdmiphy_v13_configs,
+	.phy_conf_count	= ARRAY_SIZE(hdmiphy_v13_configs),
+	.is_apb_phy	= 0,
+};
+
 static struct hdmi_driver_data exynos5_hdmi_driver_data = {
 	.type		= HDMI_TYPE14,
 	.phy_confs	= hdmiphy_v13_configs,
@@ -1129,7 +1137,7 @@ static int hdmi_create_connector(struct
 	}
 
 	drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return 0;
@@ -1241,14 +1249,13 @@ static void hdmi_reg_acr(struct hdmi_con
 
 static void hdmi_audio_init(struct hdmi_context *hdata)
 {
-	u32 sample_rate, bits_per_sample, frame_size_code;
+	u32 sample_rate, bits_per_sample;
 	u32 data_num, bit_ch, sample_frq;
 	u32 val;
 	u8 acr[7];
 
 	sample_rate = 44100;
 	bits_per_sample = 16;
-	frame_size_code = 0;
 
 	switch (bits_per_sample) {
 	case 20:
@@ -2168,7 +2175,6 @@ static int hdmi_resources_init(struct hd
 	struct device *dev = hdata->dev;
 	struct hdmi_resources *res = &hdata->res;
 	static char *supply[] = {
-		"hdmi-en",
 		"vdd",
 		"vdd_osc",
 		"vdd_pll",
@@ -2228,6 +2234,20 @@ static int hdmi_resources_init(struct hd
 	}
 	res->regul_count = ARRAY_SIZE(supply);
 
+	res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
+	if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
+		DRM_ERROR("failed to get hdmi-en regulator\n");
+		return PTR_ERR(res->reg_hdmi_en);
+	}
+	if (!IS_ERR(res->reg_hdmi_en)) {
+		ret = regulator_enable(res->reg_hdmi_en);
+		if (ret) {
+			DRM_ERROR("failed to enable hdmi-en regulator\n");
+			return ret;
+		}
+	} else
+		res->reg_hdmi_en = NULL;
+
 	return ret;
 fail:
 	DRM_ERROR("HDMI resource init - failed\n");
@@ -2263,6 +2283,9 @@ static struct of_device_id hdmi_match_ty
 		.compatible = "samsung,exynos5-hdmi",
 		.data = &exynos5_hdmi_driver_data,
 	}, {
+		.compatible = "samsung,exynos4210-hdmi",
+		.data = &exynos4210_hdmi_driver_data,
+	}, {
 		.compatible = "samsung,exynos4212-hdmi",
 		.data = &exynos4212_hdmi_driver_data,
 	}, {
@@ -2272,6 +2295,7 @@ static struct of_device_id hdmi_match_ty
 		/* end node */
 	}
 };
+MODULE_DEVICE_TABLE (of, hdmi_match_types);
 
 static int hdmi_bind(struct device *dev, struct device *master, void *data)
 {
@@ -2494,7 +2518,11 @@ static int hdmi_remove(struct platform_d
 
 	cancel_delayed_work_sync(&hdata->hotplug_work);
 
-	put_device(&hdata->hdmiphy_port->dev);
+	if (hdata->res.reg_hdmi_en)
+		regulator_disable(hdata->res.reg_hdmi_en);
+
+	if (hdata->hdmiphy_port)
+		put_device(&hdata->hdmiphy_port->dev);
 	put_device(&hdata->ddc_adpt->dev);
 
 	pm_runtime_disable(&pdev->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_mixer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_mixer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/exynos_mixer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/exynos_mixer.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ struct mixer_resources {
 	struct clk		*vp;
 	struct clk		*sclk_mixer;
 	struct clk		*sclk_hdmi;
-	struct clk		*sclk_dac;
+	struct clk		*mout_mixer;
 };
 
 enum mixer_version_id {
@@ -93,6 +93,7 @@ struct mixer_context {
 	bool			interlace;
 	bool			powered;
 	bool			vp_enabled;
+	bool			has_sclk;
 	u32			int_en;
 
 	struct mutex		mixer_mutex;
@@ -106,6 +107,7 @@ struct mixer_context {
 struct mixer_drv_data {
 	enum mixer_version_id	version;
 	bool					is_vp_enabled;
+	bool					has_sclk;
 };
 
 static const u8 filter_y_horiz_tap8[] = {
@@ -363,6 +365,11 @@ static void mixer_cfg_layer(struct mixer
 			vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 			mixer_reg_writemask(res, MXR_CFG, val,
 				MXR_CFG_VP_ENABLE);
+
+			/* control blending of graphic layer 0 */
+			mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
+					MXR_GRP_CFG_BLEND_PRE_MUL |
+					MXR_GRP_CFG_PIXEL_BLEND_EN);
 		}
 		break;
 	}
@@ -809,19 +816,23 @@ static int vp_resources_init(struct mixe
 		dev_err(dev, "failed to get clock 'vp'\n");
 		return -ENODEV;
 	}
-	mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
-	if (IS_ERR(mixer_res->sclk_mixer)) {
-		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
-		return -ENODEV;
-	}
-	mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
-	if (IS_ERR(mixer_res->sclk_dac)) {
-		dev_err(dev, "failed to get clock 'sclk_dac'\n");
-		return -ENODEV;
-	}
 
-	if (mixer_res->sclk_hdmi)
-		clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
+	if (mixer_ctx->has_sclk) {
+		mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
+		if (IS_ERR(mixer_res->sclk_mixer)) {
+			dev_err(dev, "failed to get clock 'sclk_mixer'\n");
+			return -ENODEV;
+		}
+		mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
+		if (IS_ERR(mixer_res->mout_mixer)) {
+			dev_err(dev, "failed to get clock 'mout_mixer'\n");
+			return -ENODEV;
+		}
+
+		if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
+			clk_set_parent(mixer_res->mout_mixer,
+				       mixer_res->sclk_hdmi);
+	}
 
 	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 	if (res == NULL) {
@@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_
 	clk_prepare_enable(res->mixer);
 	if (ctx->vp_enabled) {
 		clk_prepare_enable(res->vp);
-		clk_prepare_enable(res->sclk_mixer);
+		if (ctx->has_sclk)
+			clk_prepare_enable(res->sclk_mixer);
 	}
 
 	mutex_lock(&ctx->mixer_mutex);
@@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos
 	clk_disable_unprepare(res->mixer);
 	if (ctx->vp_enabled) {
 		clk_disable_unprepare(res->vp);
-		clk_disable_unprepare(res->sclk_mixer);
+		if (ctx->has_sclk)
+			clk_disable_unprepare(res->sclk_mixer);
 	}
 
 	pm_runtime_put_sync(ctx->dev);
@@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_
 	.is_vp_enabled = 0,
 };
 
+static struct mixer_drv_data exynos4212_mxr_drv_data = {
+	.version = MXR_VER_0_0_0_16,
+	.is_vp_enabled = 1,
+};
+
 static struct mixer_drv_data exynos4210_mxr_drv_data = {
 	.version = MXR_VER_0_0_0_16,
 	.is_vp_enabled = 1,
+	.has_sclk = 1,
 };
 
 static struct platform_device_id mixer_driver_types[] = {
@@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_d
 
 static struct of_device_id mixer_match_types[] = {
 	{
+		.compatible = "samsung,exynos4210-mixer",
+		.data	= &exynos4210_mxr_drv_data,
+	}, {
+		.compatible = "samsung,exynos4212-mixer",
+		.data	= &exynos4212_mxr_drv_data,
+	}, {
 		.compatible = "samsung,exynos5-mixer",
 		.data	= &exynos5250_mxr_drv_data,
 	}, {
@@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_t
 		/* end node */
 	}
 };
+MODULE_DEVICE_TABLE(of, mixer_match_types);
 
 static int mixer_bind(struct device *dev, struct device *manager, void *data)
 {
@@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev
 	ctx->pdev = pdev;
 	ctx->dev = dev;
 	ctx->vp_enabled = drv->is_vp_enabled;
+	ctx->has_sclk = drv->has_sclk;
 	ctx->mxr_ver = drv->version;
 	init_waitqueue_head(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/exynos/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/exynos/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/exynos/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD
 	bool "Exynos DRM FIMD"
 	depends on DRM_EXYNOS && !FB_S3C
 	select FB_MODE_HELPERS
+	select MFD_SYSCON
 	help
 	  Choose this option if you want to use Exynos FIMD for DRM.
 
@@ -52,6 +53,7 @@ config DRM_EXYNOS_DP
 	bool "EXYNOS DRM DP driver support"
 	depends on DRM_EXYNOS_FIMD && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
 	default DRM_EXYNOS
+	select DRM_PANEL
 	help
 	  This enables support for DP device.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_crt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_crt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_crt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_crt.c	2014-09-28 17:29:07.000000000 -0400
@@ -192,7 +192,7 @@ static void cdv_intel_crt_destroy(struct
 	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
 
 	psb_intel_i2c_destroy(gma_encoder->ddc_bus);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -304,7 +304,7 @@ void cdv_intel_crt_init(struct drm_devic
 	drm_connector_helper_add(connector,
 					&cdv_intel_crt_connector_helper_funcs);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	return;
 failed_ddc:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_dp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_dp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_dp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_dp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1713,7 +1713,7 @@ cdv_intel_dp_destroy(struct drm_connecto
 		}
 	}
 	i2c_del_adapter(&intel_dp->adapter);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -1847,7 +1847,7 @@ cdv_intel_dp_init(struct drm_device *dev
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	/* Set up the DDC bus. */
 	switch (output_reg) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -248,7 +248,7 @@ static void cdv_hdmi_destroy(struct drm_
 
 	if (gma_encoder->i2c_bus)
 		psb_intel_i2c_destroy(gma_encoder->i2c_bus);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -356,7 +356,7 @@ void cdv_hdmi_init(struct drm_device *de
 
 	hdmi_priv->hdmi_i2c_adapter = &(gma_encoder->i2c_bus->adapter);
 	hdmi_priv->dev = dev;
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return;
 
 failed_ddc:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c	2014-09-28 17:29:07.000000000 -0400
@@ -446,7 +446,7 @@ static void cdv_intel_lvds_destroy(struc
 
 	if (gma_encoder->i2c_bus)
 		psb_intel_i2c_destroy(gma_encoder->i2c_bus);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -774,7 +774,7 @@ void cdv_intel_lvds_init(struct drm_devi
 
 out:
 	mutex_unlock(&dev->mode_config.mutex);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return;
 
 failed_find:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/framebuffer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/framebuffer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/framebuffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/framebuffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -561,7 +561,7 @@ static int psbfb_probe(struct drm_fb_hel
 	return psbfb_create(psb_fbdev, sizes);
 }
 
-static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
 	.gamma_set = psbfb_gamma_set,
 	.gamma_get = psbfb_gamma_get,
 	.fb_probe = psbfb_probe,
@@ -600,7 +600,8 @@ int psb_fbdev_init(struct drm_device *de
 	}
 
 	dev_priv->fbdev = fbdev;
-	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+	drm_fb_helper_prepare(dev, &fbdev->psb_fb_helper, &psb_fb_helper_funcs);
 
 	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
 							INTELFB_CONN_LIMIT);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/gtt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/gtt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/gtt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/gtt.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,7 +206,7 @@ static int psb_gtt_attach_pages(struct g
 
 	WARN_ON(gt->pages);
 
-	pages = drm_gem_get_pages(&gt->gem, 0);
+	pages = drm_gem_get_pages(&gt->gem);
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/mdfld_dsi_output.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_output.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/mdfld_dsi_output.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_output.c	2014-09-28 17:29:07.000000000 -0400
@@ -318,7 +318,7 @@ static void mdfld_dsi_connector_destroy(
 
 	if (!dsi_connector)
 		return;
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	sender = dsi_connector->pkg_sender;
 	mdfld_dsi_pkg_sender_destroy(sender);
@@ -597,7 +597,7 @@ void mdfld_dsi_output_init(struct drm_de
 	dsi_config->encoder = encoder;
 	encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
 		INTEL_OUTPUT_MIPI2;
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return;
 
 	/*TODO: add code to destroy outputs on error*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/mid_bios.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/mid_bios.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/mid_bios.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/mid_bios.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,6 @@ static void mid_get_fuse_settings(struct
 #define FB_REG06 0xD0810600
 #define FB_MIPI_DISABLE  (1 << 11)
 #define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
 #define FB_SKU_MASK  0x7000
 #define FB_SKU_SHIFT 12
 #define FB_SKU_100 0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/oaktrail_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/oaktrail_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/oaktrail_hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/oaktrail_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -665,7 +665,7 @@ void oaktrail_hdmi_init(struct drm_devic
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	dev_info(dev->dev, "HDMI initialised.\n");
 
 	return;
@@ -674,7 +674,7 @@ failed_connector:
 	kfree(gma_encoder);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
+static const struct pci_device_id hdmi_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
 	{ 0 }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/oaktrail_lvds.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/oaktrail_lvds.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/oaktrail_lvds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/oaktrail_lvds.c	2014-09-28 17:29:07.000000000 -0400
@@ -404,7 +404,7 @@ void oaktrail_lvds_init(struct drm_devic
 out:
 	mutex_unlock(&dev->mode_config.mutex);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return;
 
 failed_find:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ static int psb_pci_probe(struct pci_dev
  * PowerVR SGX545    - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700,
  *                                  N2800
  */
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
 	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
 	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
 #if defined(CONFIG_DRM_GMA600)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c	2014-09-28 17:29:07.000000000 -0400
@@ -563,7 +563,7 @@ void psb_intel_lvds_destroy(struct drm_c
 
 	if (lvds_priv->ddc_bus)
 		psb_intel_i2c_destroy(lvds_priv->ddc_bus);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -829,7 +829,7 @@ void psb_intel_lvds_init(struct drm_devi
 	 */
 out:
 	mutex_unlock(&dev->mode_config.mutex);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return;
 
 failed_find:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_intel_sdvo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_intel_sdvo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/gma500/psb_intel_sdvo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/gma500/psb_intel_sdvo.c	2014-09-28 17:29:07.000000000 -0400
@@ -1682,7 +1682,7 @@ static void psb_intel_sdvo_destroy(struc
 				     psb_intel_sdvo_connector->tv_format);
 
 	psb_intel_sdvo_destroy_enhance_property(connector);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -2071,7 +2071,7 @@ psb_intel_sdvo_connector_init(struct psb
 	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
 
 	gma_connector_attach_encoder(&connector->base, &encoder->base);
-	drm_sysfs_connector_add(&connector->base.base);
+	drm_connector_register(&connector->base.base);
 }
 
 static void
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i2c/tda998x_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i2c/tda998x_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i2c/tda998x_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i2c/tda998x_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-
+#include <linux/component.h>
 #include <linux/hdmi.h>
 #include <linux/module.h>
 #include <linux/irq.h>
@@ -730,12 +729,9 @@ tda998x_configure_audio(struct tda998x_p
 
 /* DRM encoder functions */
 
-static void
-tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
+static void tda998x_encoder_set_config(struct tda998x_priv *priv,
+				       const struct tda998x_encoder_params *p)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-	struct tda998x_encoder_params *p = params;
-
 	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) |
@@ -752,11 +748,8 @@ tda998x_encoder_set_config(struct drm_en
 	priv->params = *p;
 }
 
-static void
-tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+static void tda998x_encoder_dpms(struct tda998x_priv *priv, int mode)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
 	/* we only care about on or off: */
 	if (mode != DRM_MODE_DPMS_ON)
 		mode = DRM_MODE_DPMS_OFF;
@@ -806,9 +799,8 @@ tda998x_encoder_mode_fixup(struct drm_en
 	return true;
 }
 
-static int
-tda998x_encoder_mode_valid(struct drm_encoder *encoder,
-			  struct drm_display_mode *mode)
+static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
+				      struct drm_display_mode *mode)
 {
 	if (mode->clock > 150000)
 		return MODE_CLOCK_HIGH;
@@ -820,11 +812,10 @@ tda998x_encoder_mode_valid(struct drm_en
 }
 
 static void
-tda998x_encoder_mode_set(struct drm_encoder *encoder,
-			struct drm_display_mode *mode,
-			struct drm_display_mode *adjusted_mode)
+tda998x_encoder_mode_set(struct tda998x_priv *priv,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	uint16_t ref_pix, ref_line, n_pix, n_line;
 	uint16_t hs_pix_s, hs_pix_e;
 	uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
@@ -1012,20 +1003,16 @@ tda998x_encoder_mode_set(struct drm_enco
 }
 
 static enum drm_connector_status
-tda998x_encoder_detect(struct drm_encoder *encoder,
-		      struct drm_connector *connector)
+tda998x_encoder_detect(struct tda998x_priv *priv)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV);
 
 	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
 			connector_status_disconnected;
 }
 
-static int
-read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+static int read_edid_block(struct tda998x_priv *priv, uint8_t *buf, int blk)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	uint8_t offset, segptr;
 	int ret, i;
 
@@ -1079,10 +1066,8 @@ read_edid_block(struct drm_encoder *enco
 	return 0;
 }
 
-static uint8_t *
-do_get_edid(struct drm_encoder *encoder)
+static uint8_t *do_get_edid(struct tda998x_priv *priv)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
 	int j, valid_extensions = 0;
 	uint8_t *block, *new;
 	bool print_bad_edid = drm_debug & DRM_UT_KMS;
@@ -1094,7 +1079,7 @@ do_get_edid(struct drm_encoder *encoder)
 		reg_clear(priv, REG_TX4, TX4_PD_RAM);
 
 	/* base block fetch */
-	if (read_edid_block(encoder, block, 0))
+	if (read_edid_block(priv, block, 0))
 		goto fail;
 
 	if (!drm_edid_block_valid(block, 0, print_bad_edid))
@@ -1111,7 +1096,7 @@ do_get_edid(struct drm_encoder *encoder)
 
 	for (j = 1; j <= block[0x7e]; j++) {
 		uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
-		if (read_edid_block(encoder, ext_block, j))
+		if (read_edid_block(priv, ext_block, j))
 			goto fail;
 
 		if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
@@ -1144,11 +1129,10 @@ fail:
 }
 
 static int
-tda998x_encoder_get_modes(struct drm_encoder *encoder,
-			 struct drm_connector *connector)
+tda998x_encoder_get_modes(struct tda998x_priv *priv,
+			  struct drm_connector *connector)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-	struct edid *edid = (struct edid *)do_get_edid(encoder);
+	struct edid *edid = (struct edid *)do_get_edid(priv);
 	int n = 0;
 
 	if (edid) {
@@ -1161,18 +1145,14 @@ tda998x_encoder_get_modes(struct drm_enc
 	return n;
 }
 
-static int
-tda998x_encoder_create_resources(struct drm_encoder *encoder,
-				struct drm_connector *connector)
+static void tda998x_encoder_set_polling(struct tda998x_priv *priv,
+					struct drm_connector *connector)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
 	if (priv->hdmi->irq)
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	else
 		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
 			DRM_CONNECTOR_POLL_DISCONNECT;
-	return 0;
 }
 
 static int
@@ -1185,66 +1165,97 @@ tda998x_encoder_set_property(struct drm_
 	return 0;
 }
 
-static void
-tda998x_encoder_destroy(struct drm_encoder *encoder)
+static void tda998x_destroy(struct tda998x_priv *priv)
 {
-	struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
 	/* disable all IRQs and free the IRQ handler */
 	cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
 	reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
 	if (priv->hdmi->irq)
 		free_irq(priv->hdmi->irq, priv);
 
-	if (priv->cec)
-		i2c_unregister_device(priv->cec);
+	i2c_unregister_device(priv->cec);
+}
+
+/* Slave encoder support */
+
+static void
+tda998x_encoder_slave_set_config(struct drm_encoder *encoder, void *params)
+{
+	tda998x_encoder_set_config(to_tda998x_priv(encoder), params);
+}
+
+static void tda998x_encoder_slave_destroy(struct drm_encoder *encoder)
+{
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+
+	tda998x_destroy(priv);
 	drm_i2c_encoder_destroy(encoder);
 	kfree(priv);
 }
 
-static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
-	.set_config = tda998x_encoder_set_config,
-	.destroy = tda998x_encoder_destroy,
-	.dpms = tda998x_encoder_dpms,
-	.save = tda998x_encoder_save,
-	.restore = tda998x_encoder_restore,
-	.mode_fixup = tda998x_encoder_mode_fixup,
-	.mode_valid = tda998x_encoder_mode_valid,
-	.mode_set = tda998x_encoder_mode_set,
-	.detect = tda998x_encoder_detect,
-	.get_modes = tda998x_encoder_get_modes,
-	.create_resources = tda998x_encoder_create_resources,
-	.set_property = tda998x_encoder_set_property,
-};
+static void tda998x_encoder_slave_dpms(struct drm_encoder *encoder, int mode)
+{
+	tda998x_encoder_dpms(to_tda998x_priv(encoder), mode);
+}
 
-/* I2C driver functions */
+static int tda998x_encoder_slave_mode_valid(struct drm_encoder *encoder,
+					    struct drm_display_mode *mode)
+{
+	return tda998x_encoder_mode_valid(to_tda998x_priv(encoder), mode);
+}
 
-static int
-tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static void
+tda998x_encoder_slave_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
 {
-	return 0;
+	tda998x_encoder_mode_set(to_tda998x_priv(encoder), mode, adjusted_mode);
+}
+
+static enum drm_connector_status
+tda998x_encoder_slave_detect(struct drm_encoder *encoder,
+			     struct drm_connector *connector)
+{
+	return tda998x_encoder_detect(to_tda998x_priv(encoder));
+}
+
+static int tda998x_encoder_slave_get_modes(struct drm_encoder *encoder,
+					   struct drm_connector *connector)
+{
+	return tda998x_encoder_get_modes(to_tda998x_priv(encoder), connector);
 }
 
 static int
-tda998x_remove(struct i2c_client *client)
+tda998x_encoder_slave_create_resources(struct drm_encoder *encoder,
+				       struct drm_connector *connector)
 {
+	tda998x_encoder_set_polling(to_tda998x_priv(encoder), connector);
 	return 0;
 }
 
-static int
-tda998x_encoder_init(struct i2c_client *client,
-		    struct drm_device *dev,
-		    struct drm_encoder_slave *encoder_slave)
+static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = {
+	.set_config = tda998x_encoder_slave_set_config,
+	.destroy = tda998x_encoder_slave_destroy,
+	.dpms = tda998x_encoder_slave_dpms,
+	.save = tda998x_encoder_save,
+	.restore = tda998x_encoder_restore,
+	.mode_fixup = tda998x_encoder_mode_fixup,
+	.mode_valid = tda998x_encoder_slave_mode_valid,
+	.mode_set = tda998x_encoder_slave_mode_set,
+	.detect = tda998x_encoder_slave_detect,
+	.get_modes = tda998x_encoder_slave_get_modes,
+	.create_resources = tda998x_encoder_slave_create_resources,
+	.set_property = tda998x_encoder_set_property,
+};
+
+/* I2C driver functions */
+
+static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 {
-	struct tda998x_priv *priv;
 	struct device_node *np = client->dev.of_node;
 	u32 video;
 	int rev_lo, rev_hi, ret;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
 	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);
@@ -1252,17 +1263,11 @@ tda998x_encoder_init(struct i2c_client *
 	priv->current_page = 0xff;
 	priv->hdmi = client;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
-	if (!priv->cec) {
-		kfree(priv);
+	if (!priv->cec)
 		return -ENODEV;
-	}
 
-	priv->encoder = &encoder_slave->base;
 	priv->dpms = DRM_MODE_DPMS_OFF;
 
-	encoder_slave->slave_priv = priv;
-	encoder_slave->slave_funcs = &tda998x_encoder_funcs;
-
 	/* wake up the device: */
 	cec_write(priv, REG_CEC_ENAMODS,
 			CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
@@ -1365,12 +1370,231 @@ fail:
 	 */
 	if (priv->cec)
 		i2c_unregister_device(priv->cec);
-	kfree(priv);
-	encoder_slave->slave_priv = NULL;
-	encoder_slave->slave_funcs = NULL;
 	return -ENXIO;
 }
 
+static int tda998x_encoder_init(struct i2c_client *client,
+				struct drm_device *dev,
+				struct drm_encoder_slave *encoder_slave)
+{
+	struct tda998x_priv *priv;
+	int ret;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->encoder = &encoder_slave->base;
+
+	ret = tda998x_create(client, priv);
+	if (ret) {
+		kfree(priv);
+		return ret;
+	}
+
+	encoder_slave->slave_priv = priv;
+	encoder_slave->slave_funcs = &tda998x_encoder_slave_funcs;
+
+	return 0;
+}
+
+struct tda998x_priv2 {
+	struct tda998x_priv base;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+};
+
+#define conn_to_tda998x_priv2(x) \
+	container_of(x, struct tda998x_priv2, connector);
+
+#define enc_to_tda998x_priv2(x) \
+	container_of(x, struct tda998x_priv2, encoder);
+
+static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+	tda998x_encoder_dpms(&priv->base, mode);
+}
+
+static void tda998x_encoder_prepare(struct drm_encoder *encoder)
+{
+	tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void tda998x_encoder_commit(struct drm_encoder *encoder)
+{
+	tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void tda998x_encoder2_mode_set(struct drm_encoder *encoder,
+				      struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
+{
+	struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+	tda998x_encoder_mode_set(&priv->base, mode, adjusted_mode);
+}
+
+static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = {
+	.dpms = tda998x_encoder2_dpms,
+	.save = tda998x_encoder_save,
+	.restore = tda998x_encoder_restore,
+	.mode_fixup = tda998x_encoder_mode_fixup,
+	.prepare = tda998x_encoder_prepare,
+	.commit = tda998x_encoder_commit,
+	.mode_set = tda998x_encoder2_mode_set,
+};
+
+static void tda998x_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+	tda998x_destroy(&priv->base);
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs tda998x_encoder_funcs = {
+	.destroy = tda998x_encoder_destroy,
+};
+
+static int tda998x_connector_get_modes(struct drm_connector *connector)
+{
+	struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+	return tda998x_encoder_get_modes(&priv->base, connector);
+}
+
+static int tda998x_connector_mode_valid(struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+	return tda998x_encoder_mode_valid(&priv->base, mode);
+}
+
+static struct drm_encoder *
+tda998x_connector_best_encoder(struct drm_connector *connector)
+{
+	struct tda998x_priv2 *priv = conn_to_tda998x_priv2(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 enum drm_connector_status
+tda998x_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+	return tda998x_encoder_detect(&priv->base);
+}
+
+static void tda998x_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs tda998x_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = tda998x_connector_detect,
+	.destroy = tda998x_connector_destroy,
+};
+
+static int tda998x_bind(struct device *dev, struct device *master, void *data)
+{
+	struct tda998x_encoder_params *params = dev->platform_data;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct drm_device *drm = data;
+	struct tda998x_priv2 *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+
+	priv->base.encoder = &priv->encoder;
+	priv->connector.interlace_allowed = 1;
+	priv->encoder.possible_crtcs = 1 << 0;
+
+	ret = tda998x_create(client, &priv->base);
+	if (ret)
+		return ret;
+
+	if (!dev->of_node && params)
+		tda998x_encoder_set_config(&priv->base, params);
+
+	tda998x_encoder_set_polling(&priv->base, &priv->connector);
+
+	drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
+	ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS);
+	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);
+	if (ret)
+		goto err_connector;
+
+	ret = drm_connector_register(&priv->connector);
+	if (ret)
+		goto err_sysfs;
+
+	priv->connector.encoder = &priv->encoder;
+	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:
+	tda998x_destroy(&priv->base);
+	return ret;
+}
+
+static void tda998x_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct tda998x_priv2 *priv = dev_get_drvdata(dev);
+
+	drm_connector_cleanup(&priv->connector);
+	drm_encoder_cleanup(&priv->encoder);
+	tda998x_destroy(&priv->base);
+}
+
+static const struct component_ops tda998x_ops = {
+	.bind = tda998x_bind,
+	.unbind = tda998x_unbind,
+};
+
+static int
+tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	return component_add(&client->dev, &tda998x_ops);
+}
+
+static int tda998x_remove(struct i2c_client *client)
+{
+	component_del(&client->dev, &tda998x_ops);
+	return 0;
+}
+
 #ifdef CONFIG_OF
 static const struct of_device_id tda998x_dt_ids[] = {
 	{ .compatible = "nxp,tda998x", },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i810/i810_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i810/i810_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i810/i810_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i810/i810_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -393,15 +393,14 @@ static int i810_dma_initialize(struct dr
 
 	/* Program Hardware Status Page */
 	dev_priv->hw_status_page =
-	    pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-				 &dev_priv->dma_status_page);
+		pci_zalloc_consistent(dev->pdev, PAGE_SIZE,
+				      &dev_priv->dma_status_page);
 	if (!dev_priv->hw_status_page) {
 		dev->dev_private = (void *)dev_priv;
 		i810_dma_cleanup(dev);
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
 	I810_WRITE(0x02080, dev_priv->dma_status_page);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2014-09-28 17:29:07.000000000 -0400
@@ -426,6 +426,9 @@ static const u32 gen7_render_regs[] = {
 	GEN7_SO_WRITE_OFFSET(1),
 	GEN7_SO_WRITE_OFFSET(2),
 	GEN7_SO_WRITE_OFFSET(3),
+	GEN7_L3SQCREG1,
+	GEN7_L3CNTLREG2,
+	GEN7_L3CNTLREG3,
 };
 
 static const u32 gen7_blt_regs[] = {
@@ -706,11 +709,13 @@ int i915_cmd_parser_init_ring(struct int
 	BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count));
 	BUG_ON(!validate_regs_sorted(ring));
 
-	ret = init_hash_table(ring, cmd_tables, cmd_table_count);
-	if (ret) {
-		DRM_ERROR("CMD: cmd_parser_init failed!\n");
-		fini_hash_table(ring);
-		return ret;
+	if (hash_empty(ring->cmd_hash)) {
+		ret = init_hash_table(ring, cmd_tables, cmd_table_count);
+		if (ret) {
+			DRM_ERROR("CMD: cmd_parser_init failed!\n");
+			fini_hash_table(ring);
+			return ret;
+		}
 	}
 
 	ring->needs_cmd_parser = true;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -170,11 +170,13 @@ describe_obj(struct seq_file *m, struct
 	}
 	if (obj->ring != NULL)
 		seq_printf(m, " (%s)", obj->ring->name);
+	if (obj->frontbuffer_bits)
+		seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
 }
 
 static void describe_ctx(struct seq_file *m, struct intel_context *ctx)
 {
-	seq_putc(m, ctx->is_initialized ? 'I' : 'i');
+	seq_putc(m, ctx->legacy_hw_ctx.initialized ? 'I' : 'i');
 	seq_putc(m, ctx->remap_slice ? 'R' : 'r');
 	seq_putc(m, ' ');
 }
@@ -515,6 +517,11 @@ static int i915_gem_pageflip_info(struct
 	struct drm_device *dev = node->minor->dev;
 	unsigned long flags;
 	struct intel_crtc *crtc;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	for_each_intel_crtc(dev, crtc) {
 		const char pipe = pipe_name(crtc->pipe);
@@ -556,6 +563,8 @@ static int i915_gem_pageflip_info(struct
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -985,29 +994,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_
 			i915_next_seqno_get, i915_next_seqno_set,
 			"0x%llx\n");
 
-static int i915_rstdby_delays(struct seq_file *m, void *unused)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u16 crstanddelay;
-	int ret;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-	intel_runtime_pm_get(dev_priv);
-
-	crstanddelay = I915_READ16(CRSTANDVID);
-
-	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
-
-	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
-
-	return 0;
-}
-
 static int i915_frequency_info(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = m->private;
@@ -1029,7 +1015,8 @@ static int i915_frequency_info(struct se
 			   MEMSTAT_VID_SHIFT);
 		seq_printf(m, "Current P-state: %d\n",
 			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
-	} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
+	} else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
+		   IS_BROADWELL(dev)) {
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1048,7 +1035,7 @@ static int i915_frequency_info(struct se
 
 		reqf = I915_READ(GEN6_RPNSWREQ);
 		reqf &= ~GEN6_TURBO_DISABLE;
-		if (IS_HASWELL(dev))
+		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 			reqf >>= 24;
 		else
 			reqf >>= 25;
@@ -1065,7 +1052,7 @@ static int i915_frequency_info(struct se
 		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
 		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
 		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
-		if (IS_HASWELL(dev))
+		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 			cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
 		else
 			cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
@@ -1121,20 +1108,21 @@ static int i915_frequency_info(struct se
 		seq_printf(m, "Max overclocked frequency: %dMHz\n",
 			   dev_priv->rps.max_freq * GT_FREQUENCY_MULTIPLIER);
 	} else if (IS_VALLEYVIEW(dev)) {
-		u32 freq_sts, val;
+		u32 freq_sts;
 
 		mutex_lock(&dev_priv->rps.hw_lock);
 		freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
 		seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
 
-		val = valleyview_rps_max_freq(dev_priv);
 		seq_printf(m, "max GPU freq: %d MHz\n",
-			   vlv_gpu_freq(dev_priv, val));
+			   vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq));
 
-		val = valleyview_rps_min_freq(dev_priv);
 		seq_printf(m, "min GPU freq: %d MHz\n",
-			   vlv_gpu_freq(dev_priv, val));
+			   vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq));
+
+		seq_printf(m, "efficient (RPe) frequency: %d MHz\n",
+			   vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
 
 		seq_printf(m, "current GPU freq: %d MHz\n",
 			   vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
@@ -1148,61 +1136,6 @@ out:
 	return ret;
 }
 
-static int i915_delayfreq_table(struct seq_file *m, void *unused)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 delayfreq;
-	int ret, i;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-	intel_runtime_pm_get(dev_priv);
-
-	for (i = 0; i < 16; i++) {
-		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
-		seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
-			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
-	}
-
-	intel_runtime_pm_put(dev_priv);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
-static inline int MAP_TO_MV(int map)
-{
-	return 1250 - (map * 25);
-}
-
-static int i915_inttoext_table(struct seq_file *m, void *unused)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 inttoext;
-	int ret, i;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-	intel_runtime_pm_get(dev_priv);
-
-	for (i = 1; i <= 32; i++) {
-		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
-		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
-	}
-
-	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
 static int ironlake_drpc_info(struct seq_file *m)
 {
 	struct drm_info_node *node = m->private;
@@ -1513,10 +1446,17 @@ static int i915_ips_status(struct seq_fi
 
 	intel_runtime_pm_get(dev_priv);
 
-	if (IS_BROADWELL(dev) || I915_READ(IPS_CTL) & IPS_ENABLE)
-		seq_puts(m, "enabled\n");
-	else
-		seq_puts(m, "disabled\n");
+	seq_printf(m, "Enabled by kernel parameter: %s\n",
+		   yesno(i915.enable_ips));
+
+	if (INTEL_INFO(dev)->gen >= 8) {
+		seq_puts(m, "Currently: unknown\n");
+	} else {
+		if (I915_READ(IPS_CTL) & IPS_ENABLE)
+			seq_puts(m, "Currently: enabled\n");
+		else
+			seq_puts(m, "Currently: disabled\n");
+	}
 
 	intel_runtime_pm_put(dev_priv);
 
@@ -1620,26 +1560,6 @@ out:
 	return ret;
 }
 
-static int i915_gfxec(struct seq_file *m, void *unused)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-	intel_runtime_pm_get(dev_priv);
-
-	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
-	intel_runtime_pm_put(dev_priv);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
 static int i915_opregion(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = m->private;
@@ -1677,9 +1597,6 @@ static int i915_gem_framebuffer_info(str
 
 #ifdef CONFIG_DRM_I915_FBDEV
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret = mutex_lock_interruptible(&dev->mode_config.mutex);
-	if (ret)
-		return ret;
 
 	ifbdev = dev_priv->fbdev;
 	fb = to_intel_framebuffer(ifbdev->helper.fb);
@@ -1692,7 +1609,6 @@ static int i915_gem_framebuffer_info(str
 		   atomic_read(&fb->base.refcount.refcount));
 	describe_obj(m, fb->obj);
 	seq_putc(m, '\n');
-	mutex_unlock(&dev->mode_config.mutex);
 #endif
 
 	mutex_lock(&dev->mode_config.fb_lock);
@@ -1723,7 +1639,7 @@ static int i915_context_status(struct se
 	struct intel_context *ctx;
 	int ret, i;
 
-	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
@@ -1740,7 +1656,7 @@ static int i915_context_status(struct se
 	}
 
 	list_for_each_entry(ctx, &dev_priv->context_list, link) {
-		if (ctx->obj == NULL)
+		if (ctx->legacy_hw_ctx.rcs_state == NULL)
 			continue;
 
 		seq_puts(m, "HW context ");
@@ -1749,11 +1665,11 @@ static int i915_context_status(struct se
 			if (ring->default_context == ctx)
 				seq_printf(m, "(default context %s) ", ring->name);
 
-		describe_obj(m, ctx->obj);
+		describe_obj(m, ctx->legacy_hw_ctx.rcs_state);
 		seq_putc(m, '\n');
 	}
 
-	mutex_unlock(&dev->mode_config.mutex);
+	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -1863,7 +1779,7 @@ static int per_file_ctx(int id, void *pt
 	if (i915_gem_context_is_default(ctx))
 		seq_puts(m, "  default context:\n");
 	else
-		seq_printf(m, "  context %d:\n", ctx->id);
+		seq_printf(m, "  context %d:\n", ctx->user_handle);
 	ppgtt->debug_dump(ppgtt, m);
 
 	return 0;
@@ -1976,17 +1892,25 @@ static int i915_edp_psr_status(struct se
 
 	intel_runtime_pm_get(dev_priv);
 
+	mutex_lock(&dev_priv->psr.lock);
 	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
 	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
+	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
+	seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active));
+	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
+		   dev_priv->psr.busy_frontbuffer_bits);
+	seq_printf(m, "Re-enable work scheduled: %s\n",
+		   yesno(work_busy(&dev_priv->psr.work.work)));
 
 	enabled = HAS_PSR(dev) &&
 		I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
-	seq_printf(m, "Enabled: %s\n", yesno(enabled));
+	seq_printf(m, "HW Enabled & Active bit: %s\n", yesno(enabled));
 
 	if (HAS_PSR(dev))
 		psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
 			EDP_PSR_PERF_CNT_MASK;
 	seq_printf(m, "Performance_Counter: %u\n", psrperf);
+	mutex_unlock(&dev_priv->psr.lock);
 
 	intel_runtime_pm_put(dev_priv);
 	return 0;
@@ -2072,7 +1996,7 @@ static int i915_pc8_status(struct seq_fi
 
 	seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy));
 	seq_printf(m, "IRQs disabled: %s\n",
-		   yesno(dev_priv->pm.irqs_disabled));
+		   yesno(!intel_irqs_enabled(dev_priv)));
 
 	return 0;
 }
@@ -2126,6 +2050,8 @@ static const char *power_domain_str(enum
 		return "VGA";
 	case POWER_DOMAIN_AUDIO:
 		return "AUDIO";
+	case POWER_DOMAIN_PLLS:
+		return "PLLS";
 	case POWER_DOMAIN_INIT:
 		return "INIT";
 	default:
@@ -2223,9 +2149,12 @@ static void intel_crtc_info(struct seq_f
 	struct drm_crtc *crtc = &intel_crtc->base;
 	struct intel_encoder *intel_encoder;
 
-	seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
-		   crtc->primary->fb->base.id, crtc->x, crtc->y,
-		   crtc->primary->fb->width, crtc->primary->fb->height);
+	if (crtc->primary->fb)
+		seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
+			   crtc->primary->fb->base.id, crtc->x, crtc->y,
+			   crtc->primary->fb->width, crtc->primary->fb->height);
+	else
+		seq_puts(m, "\tprimary plane disabled\n");
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 		intel_encoder_info(m, intel_crtc, intel_encoder);
 }
@@ -2287,13 +2216,15 @@ static void intel_connector_info(struct
 		seq_printf(m, "\tCEA rev: %d\n",
 			   connector->display_info.cea_rev);
 	}
-	if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-	    intel_encoder->type == INTEL_OUTPUT_EDP)
-		intel_dp_info(m, intel_connector);
-	else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
-		intel_hdmi_info(m, intel_connector);
-	else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
-		intel_lvds_info(m, intel_connector);
+	if (intel_encoder) {
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_encoder->type == INTEL_OUTPUT_EDP)
+			intel_dp_info(m, intel_connector);
+		else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+			intel_hdmi_info(m, intel_connector);
+		else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
+			intel_lvds_info(m, intel_connector);
+	}
 
 	seq_printf(m, "\tmodes:\n");
 	list_for_each_entry(mode, &connector->modes, head)
@@ -2347,17 +2278,17 @@ static int i915_display_info(struct seq_
 		bool active;
 		int x, y;
 
-		seq_printf(m, "CRTC %d: pipe: %c, active: %s\n",
+		seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n",
 			   crtc->base.base.id, pipe_name(crtc->pipe),
-			   yesno(crtc->active));
+			   yesno(crtc->active), crtc->config.pipe_src_w, crtc->config.pipe_src_h);
 		if (crtc->active) {
 			intel_crtc_info(m, crtc);
 
 			active = cursor_position(dev, crtc->pipe, &x, &y);
-			seq_printf(m, "\tcursor visible? %s, position (%d, %d), addr 0x%08x, active? %s\n",
+			seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x, active? %s\n",
 				   yesno(crtc->cursor_base),
-				   x, y, crtc->cursor_addr,
-				   yesno(active));
+				   x, y, crtc->cursor_width, crtc->cursor_height,
+				   crtc->cursor_addr, yesno(active));
 		}
 
 		seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
@@ -2377,12 +2308,132 @@ static int i915_display_info(struct seq_
 	return 0;
 }
 
+static int i915_semaphore_status(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 drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_engine_cs *ring;
+	int num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	int i, j, ret;
+
+	if (!i915_semaphore_is_enabled(dev)) {
+		seq_puts(m, "Semaphores are disabled\n");
+		return 0;
+	}
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+	intel_runtime_pm_get(dev_priv);
+
+	if (IS_BROADWELL(dev)) {
+		struct page *page;
+		uint64_t *seqno;
+
+		page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
+
+		seqno = (uint64_t *)kmap_atomic(page);
+		for_each_ring(ring, dev_priv, i) {
+			uint64_t offset;
+
+			seq_printf(m, "%s\n", ring->name);
+
+			seq_puts(m, "  Last signal:");
+			for (j = 0; j < num_rings; j++) {
+				offset = i * I915_NUM_RINGS + j;
+				seq_printf(m, "0x%08llx (0x%02llx) ",
+					   seqno[offset], offset * 8);
+			}
+			seq_putc(m, '\n');
+
+			seq_puts(m, "  Last wait:  ");
+			for (j = 0; j < num_rings; j++) {
+				offset = i + (j * I915_NUM_RINGS);
+				seq_printf(m, "0x%08llx (0x%02llx) ",
+					   seqno[offset], offset * 8);
+			}
+			seq_putc(m, '\n');
+
+		}
+		kunmap_atomic(seqno);
+	} else {
+		seq_puts(m, "  Last signal:");
+		for_each_ring(ring, dev_priv, i)
+			for (j = 0; j < num_rings; j++)
+				seq_printf(m, "0x%08x\n",
+					   I915_READ(ring->semaphore.mbox.signal[j]));
+		seq_putc(m, '\n');
+	}
+
+	seq_puts(m, "\nSync seqno:\n");
+	for_each_ring(ring, dev_priv, i) {
+		for (j = 0; j < num_rings; j++) {
+			seq_printf(m, "  0x%08x ", ring->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;
+}
+
+static int i915_shared_dplls_info(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 drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+
+		seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id);
+		seq_printf(m, " refcount: %i, active: %i, on: %s\n", pll->refcount,
+			   pll->active, yesno(pll->on));
+		seq_printf(m, " tracked hardware state:\n");
+		seq_printf(m, " dpll:    0x%08x\n", pll->hw_state.dpll);
+		seq_printf(m, " dpll_md: 0x%08x\n", pll->hw_state.dpll_md);
+		seq_printf(m, " fp0:     0x%08x\n", pll->hw_state.fp0);
+		seq_printf(m, " fp1:     0x%08x\n", pll->hw_state.fp1);
+		seq_printf(m, " wrpll:   0x%08x\n", pll->hw_state.wrpll);
+	}
+	drm_modeset_unlock_all(dev);
+
+	return 0;
+}
+
 struct pipe_crc_info {
 	const char *name;
 	struct drm_device *dev;
 	enum pipe pipe;
 };
 
+static int i915_dp_mst_info(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 drm_encoder *encoder;
+	struct intel_encoder *intel_encoder;
+	struct intel_digital_port *intel_dig_port;
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		intel_encoder = to_intel_encoder(encoder);
+		if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT)
+			continue;
+		intel_dig_port = enc_to_dig_port(encoder);
+		if (!intel_dig_port->dp.can_mst)
+			continue;
+
+		drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr);
+	}
+	drm_modeset_unlock_all(dev);
+	return 0;
+}
+
 static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
 {
 	struct pipe_crc_info *info = inode->i_private;
@@ -2849,7 +2900,60 @@ static int ilk_pipe_crc_ctl_reg(enum int
 	return 0;
 }
 
-static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
+static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+
+	drm_modeset_lock_all(dev);
+	/*
+	 * If we use the eDP transcoder we need to make sure that we don't
+	 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
+	 * relevant on hsw with pipe A when using the always-on power well
+	 * routing.
+	 */
+	if (crtc->config.cpu_transcoder == TRANSCODER_EDP &&
+	    !crtc->config.pch_pfit.enabled) {
+		crtc->config.pch_pfit.force_thru = true;
+
+		intel_display_power_get(dev_priv,
+					POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
+
+		dev_priv->display.crtc_disable(&crtc->base);
+		dev_priv->display.crtc_enable(&crtc->base);
+	}
+	drm_modeset_unlock_all(dev);
+}
+
+static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+
+	drm_modeset_lock_all(dev);
+	/*
+	 * If we use the eDP transcoder we need to make sure that we don't
+	 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
+	 * relevant on hsw with pipe A when using the always-on power well
+	 * routing.
+	 */
+	if (crtc->config.pch_pfit.force_thru) {
+		crtc->config.pch_pfit.force_thru = false;
+
+		dev_priv->display.crtc_disable(&crtc->base);
+		dev_priv->display.crtc_enable(&crtc->base);
+
+		intel_display_power_put(dev_priv,
+					POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
+	}
+	drm_modeset_unlock_all(dev);
+}
+
+static int ivb_pipe_crc_ctl_reg(struct drm_device *dev,
+				enum pipe pipe,
+				enum intel_pipe_crc_source *source,
 				uint32_t *val)
 {
 	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
@@ -2863,6 +2967,9 @@ static int ivb_pipe_crc_ctl_reg(enum int
 		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
 		break;
 	case INTEL_PIPE_CRC_SOURCE_PF:
+		if (IS_HASWELL(dev) && pipe == PIPE_A)
+			hsw_trans_edp_pipe_A_crc_wa(dev);
+
 		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
 		break;
 	case INTEL_PIPE_CRC_SOURCE_NONE:
@@ -2895,11 +3002,11 @@ static int pipe_crc_set_source(struct dr
 	else if (INTEL_INFO(dev)->gen < 5)
 		ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 	else if (IS_VALLEYVIEW(dev))
-		ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val);
+		ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 	else if (IS_GEN5(dev) || IS_GEN6(dev))
 		ret = ilk_pipe_crc_ctl_reg(&source, &val);
 	else
-		ret = ivb_pipe_crc_ctl_reg(&source, &val);
+		ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 
 	if (ret != 0)
 		return ret;
@@ -2929,11 +3036,16 @@ 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]);
 
 		DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
 				 pipe_name(pipe));
 
-		intel_wait_for_vblank(dev, pipe);
+		drm_modeset_lock(&crtc->base.mutex, NULL);
+		if (crtc->active)
+			intel_wait_for_vblank(dev, pipe);
+		drm_modeset_unlock(&crtc->base.mutex);
 
 		spin_lock_irq(&pipe_crc->lock);
 		entries = pipe_crc->entries;
@@ -2946,6 +3058,8 @@ static int pipe_crc_set_source(struct dr
 			g4x_undo_pipe_scramble_reset(dev, pipe);
 		else if (IS_VALLEYVIEW(dev))
 			vlv_undo_pipe_scramble_reset(dev, pipe);
+		else if (IS_HASWELL(dev) && pipe == PIPE_A)
+			hsw_undo_trans_edp_pipe_A_crc_wa(dev);
 	}
 
 	return 0;
@@ -3177,7 +3291,7 @@ static int pri_wm_latency_open(struct in
 {
 	struct drm_device *dev = inode->i_private;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (HAS_GMCH_DISPLAY(dev))
 		return -ENODEV;
 
 	return single_open(file, pri_wm_latency_show, dev);
@@ -3187,7 +3301,7 @@ static int spr_wm_latency_open(struct in
 {
 	struct drm_device *dev = inode->i_private;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (HAS_GMCH_DISPLAY(dev))
 		return -ENODEV;
 
 	return single_open(file, spr_wm_latency_show, dev);
@@ -3197,7 +3311,7 @@ static int cur_wm_latency_open(struct in
 {
 	struct drm_device *dev = inode->i_private;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (HAS_GMCH_DISPLAY(dev))
 		return -ENODEV;
 
 	return single_open(file, cur_wm_latency_show, dev);
@@ -3506,7 +3620,7 @@ i915_max_freq_get(void *data, u64 *val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+	if (INTEL_INFO(dev)->gen < 6)
 		return -ENODEV;
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3532,7 +3646,7 @@ i915_max_freq_set(void *data, u64 val)
 	u32 rp_state_cap, hw_max, hw_min;
 	int ret;
 
-	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+	if (INTEL_INFO(dev)->gen < 6)
 		return -ENODEV;
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3549,8 +3663,8 @@ i915_max_freq_set(void *data, u64 val)
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
+		hw_max = dev_priv->rps.max_freq;
+		hw_min = dev_priv->rps.min_freq;
 	} else {
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
@@ -3587,7 +3701,7 @@ i915_min_freq_get(void *data, u64 *val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+	if (INTEL_INFO(dev)->gen < 6)
 		return -ENODEV;
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3613,7 +3727,7 @@ i915_min_freq_set(void *data, u64 val)
 	u32 rp_state_cap, hw_max, hw_min;
 	int ret;
 
-	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+	if (INTEL_INFO(dev)->gen < 6)
 		return -ENODEV;
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3630,8 +3744,8 @@ i915_min_freq_set(void *data, u64 val)
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
+		hw_max = dev_priv->rps.max_freq;
+		hw_min = dev_priv->rps.min_freq;
 	} else {
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
@@ -3799,14 +3913,10 @@ static const struct drm_info_list i915_d
 	{"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_rstdby_delays", i915_rstdby_delays, 0},
 	{"i915_frequency_info", i915_frequency_info, 0},
-	{"i915_delayfreq_table", i915_delayfreq_table, 0},
-	{"i915_inttoext_table", i915_inttoext_table, 0},
 	{"i915_drpc_info", i915_drpc_info, 0},
 	{"i915_emon_status", i915_emon_status, 0},
 	{"i915_ring_freq_table", i915_ring_freq_table, 0},
-	{"i915_gfxec", i915_gfxec, 0},
 	{"i915_fbc_status", i915_fbc_status, 0},
 	{"i915_ips_status", i915_ips_status, 0},
 	{"i915_sr_status", i915_sr_status, 0},
@@ -3823,6 +3933,9 @@ static const struct drm_info_list i915_d
 	{"i915_pc8_status", i915_pc8_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
 	{"i915_display_info", i915_display_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},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -138,7 +138,7 @@ static void i915_free_hws(struct drm_dev
 	I915_WRITE(HWS_PGA, 0x1ffff000);
 }
 
-void i915_kernel_lost_context(struct drm_device * dev)
+void i915_kernel_lost_context(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
@@ -166,7 +166,7 @@ void i915_kernel_lost_context(struct drm
 		master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
-static int i915_dma_cleanup(struct drm_device * dev)
+static int i915_dma_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
@@ -190,7 +190,7 @@ static int i915_dma_cleanup(struct drm_d
 	return 0;
 }
 
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
+static int i915_initialize(struct drm_device *dev, drm_i915_init_t *init)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -235,7 +235,7 @@ static int i915_initialize(struct drm_de
 	return 0;
 }
 
-static int i915_dma_resume(struct drm_device * dev)
+static int i915_dma_resume(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *ring = LP_RING(dev_priv);
@@ -359,7 +359,7 @@ static int validate_cmd(int cmd)
 	return 0;
 }
 
-static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
+static int i915_emit_cmds(struct drm_device *dev, int *buffer, int dwords)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i, ret;
@@ -369,6 +369,7 @@ static int i915_emit_cmds(struct drm_dev
 
 	for (i = 0; i < dwords;) {
 		int sz = validate_cmd(buffer[i]);
+
 		if (sz == 0 || i + sz > dwords)
 			return -EINVAL;
 		i += sz;
@@ -453,7 +454,7 @@ static void i915_emit_breadcrumb(struct
 	}
 }
 
-static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+static int i915_dispatch_cmdbuffer(struct drm_device *dev,
 				   drm_i915_cmdbuffer_t *cmd,
 				   struct drm_clip_rect *cliprects,
 				   void *cmdbuf)
@@ -487,8 +488,8 @@ static int i915_dispatch_cmdbuffer(struc
 	return 0;
 }
 
-static int i915_dispatch_batchbuffer(struct drm_device * dev,
-				     drm_i915_batchbuffer_t * batch,
+static int i915_dispatch_batchbuffer(struct drm_device *dev,
+				     drm_i915_batchbuffer_t *batch,
 				     struct drm_clip_rect *cliprects)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -549,7 +550,7 @@ static int i915_dispatch_batchbuffer(str
 	return 0;
 }
 
-static int i915_dispatch_flip(struct drm_device * dev)
+static int i915_dispatch_flip(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv =
@@ -755,7 +756,7 @@ fail_batch_free:
 	return ret;
 }
 
-static int i915_emit_irq(struct drm_device * dev)
+static int i915_emit_irq(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -781,7 +782,7 @@ static int i915_emit_irq(struct drm_devi
 	return dev_priv->dri1.counter;
 }
 
-static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device *dev, int irq_nr)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -1266,6 +1267,7 @@ static void i915_switcheroo_set_state(st
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+
 	if (state == VGA_SWITCHEROO_ON) {
 		pr_info("switched on\n");
 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -1334,6 +1336,13 @@ static int i915_load_modeset_init(struct
 
 	intel_power_domains_init_hw(dev_priv);
 
+	/*
+	 * We enable some interrupt sources in our postinstall hooks, so mark
+	 * interrupts as enabled _before_ actually enabling them to avoid
+	 * special cases in our ordering checks.
+	 */
+	dev_priv->pm._irqs_disabled = false;
+
 	ret = drm_irq_install(dev, dev->pdev->irq);
 	if (ret)
 		goto cleanup_gem_stolen;
@@ -1375,9 +1384,6 @@ static int i915_load_modeset_init(struct
 	 */
 	intel_fbdev_initial_config(dev);
 
-	/* Only enable hotplug handling once the fbdev is fully set up. */
-	dev_priv->enable_hotplug_processing = true;
-
 	drm_kms_helper_poll_init(dev);
 
 	return 0;
@@ -1425,15 +1431,16 @@ void i915_master_destroy(struct drm_devi
 }
 
 #if IS_ENABLED(CONFIG_FB)
-static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
+static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
 	struct apertures_struct *ap;
 	struct pci_dev *pdev = dev_priv->dev->pdev;
 	bool primary;
+	int ret;
 
 	ap = alloc_apertures(1);
 	if (!ap)
-		return;
+		return -ENOMEM;
 
 	ap->ranges[0].base = dev_priv->gtt.mappable_base;
 	ap->ranges[0].size = dev_priv->gtt.mappable_end;
@@ -1441,13 +1448,16 @@ static void i915_kick_out_firmware_fb(st
 	primary =
 		pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
 
-	remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
+	ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
 
 	kfree(ap);
+
+	return ret;
 }
 #else
-static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
+static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
+	return 0;
 }
 #endif
 
@@ -1492,10 +1502,11 @@ static void i915_dump_device_info(struct
 #define SEP_EMPTY
 #define PRINT_FLAG(name) info->name ? #name "," : ""
 #define SEP_COMMA ,
-	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
+	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
 			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
 			 info->gen,
 			 dev_priv->dev->pdev->device,
+			 dev_priv->dev->pdev->revision,
 			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
 #undef PRINT_S
 #undef SEP_EMPTY
@@ -1594,7 +1605,7 @@ int i915_driver_load(struct drm_device *
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	dev->dev_private = (void *)dev_priv;
+	dev->dev_private = dev_priv;
 	dev_priv->dev = dev;
 
 	/* copy initial configuration to dev_priv->info */
@@ -1606,6 +1617,7 @@ int i915_driver_load(struct drm_device *
 	spin_lock_init(&dev_priv->backlight_lock);
 	spin_lock_init(&dev_priv->uncore.lock);
 	spin_lock_init(&dev_priv->mm.object_stat_lock);
+	spin_lock_init(&dev_priv->mmio_flip_lock);
 	mutex_init(&dev_priv->dpio_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
 
@@ -1664,7 +1676,11 @@ int i915_driver_load(struct drm_device *
 			goto out_gtt;
 		}
 
-		i915_kick_out_firmware_fb(dev_priv);
+		ret = i915_kick_out_firmware_fb(dev_priv);
+		if (ret) {
+			DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
+			goto out_gtt;
+		}
 	}
 
 	pci_set_master(dev->pdev);
@@ -1717,6 +1733,13 @@ int i915_driver_load(struct drm_device *
 		goto out_mtrrfree;
 	}
 
+	dev_priv->dp_wq = alloc_ordered_workqueue("i915-dp", 0);
+	if (dev_priv->dp_wq == NULL) {
+		DRM_ERROR("Failed to create our dp workqueue.\n");
+		ret = -ENOMEM;
+		goto out_freewq;
+	}
+
 	intel_irq_init(dev);
 	intel_uncore_sanitize(dev);
 
@@ -1792,6 +1815,8 @@ out_gem_unload:
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
 	pm_qos_remove_request(&dev_priv->pm_qos);
+	destroy_workqueue(dev_priv->dp_wq);
+out_freewq:
 	destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
 	arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1892,6 +1917,7 @@ int i915_driver_unload(struct drm_device
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
 
+	destroy_workqueue(dev_priv->dp_wq);
 	destroy_workqueue(dev_priv->wq);
 	pm_qos_remove_request(&dev_priv->pm_qos);
 
@@ -1933,7 +1959,7 @@ int i915_driver_open(struct drm_device *
  * and DMA structures, since the kernel won't be using them, and clea
  * up any GEM state.
  */
-void i915_driver_lastclose(struct drm_device * dev)
+void i915_driver_lastclose(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -1954,11 +1980,11 @@ void i915_driver_lastclose(struct drm_de
 	i915_dma_cleanup(dev);
 }
 
-void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
 {
 	mutex_lock(&dev->struct_mutex);
-	i915_gem_context_close(dev, file_priv);
-	i915_gem_release(dev, file_priv);
+	i915_gem_context_close(dev, file);
+	i915_gem_release(dev, file);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -2031,7 +2057,7 @@ int i915_max_ioctl = ARRAY_SIZE(i915_ioc
  * manage the gtt, we need to claim that all intel devices are agp.  For
  * otherwise the drm core refuses to initialize the agp support code.
  */
-int i915_driver_device_is_agp(struct drm_device * dev)
+int i915_driver_device_is_agp(struct drm_device *dev)
 {
 	return 1;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/acpi.h>
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
@@ -46,8 +47,6 @@ static struct drm_driver driver;
 			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
 	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
 			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
-	.dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET }, \
-	.dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET }, \
 	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
 
 #define GEN_CHV_PIPEOFFSETS \
@@ -55,10 +54,6 @@ static struct drm_driver driver;
 			  CHV_PIPE_C_OFFSET }, \
 	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
 			   CHV_TRANSCODER_C_OFFSET, }, \
-	.dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET, \
-			  CHV_DPLL_C_OFFSET }, \
-	.dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET, \
-			     CHV_DPLL_C_MD_OFFSET }, \
 	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
 			     CHV_PALETTE_C_OFFSET }
 
@@ -308,6 +303,7 @@ static const struct intel_device_info in
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	.has_fpga_dbg = 1,
 	.has_fbc = 1,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
@@ -319,6 +315,7 @@ static const struct intel_device_info in
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	.has_fpga_dbg = 1,
 	.has_fbc = 1,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
@@ -330,6 +327,7 @@ static const struct intel_device_info in
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	.has_fpga_dbg = 1,
 	.has_fbc = 1,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
@@ -341,6 +339,7 @@ static const struct intel_device_info in
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 	.has_llc = 1,
 	.has_ddi = 1,
+	.has_fpga_dbg = 1,
 	.has_fbc = 1,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
@@ -495,12 +494,41 @@ bool i915_semaphore_is_enabled(struct dr
 	return true;
 }
 
+void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
+{
+	spin_lock_irq(&dev_priv->irq_lock);
+
+	dev_priv->long_hpd_port_mask = 0;
+	dev_priv->short_hpd_port_mask = 0;
+	dev_priv->hpd_event_bits = 0;
+
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	cancel_work_sync(&dev_priv->dig_port_work);
+	cancel_work_sync(&dev_priv->hotplug_work);
+	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
+}
+
+static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_encoder *encoder;
+
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+		if (intel_encoder->suspend)
+			intel_encoder->suspend(intel_encoder);
+	}
+	drm_modeset_unlock_all(dev);
+}
+
 static int i915_drm_freeze(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
-
-	intel_runtime_pm_get(dev_priv);
+	pci_power_t opregion_target_state;
 
 	/* ignore lid events during suspend */
 	mutex_lock(&dev_priv->modeset_restore_lock);
@@ -526,21 +554,26 @@ static int i915_drm_freeze(struct drm_de
 			return error;
 		}
 
-		drm_irq_uninstall(dev);
-		dev_priv->enable_hotplug_processing = false;
-
-		intel_disable_gt_powersave(dev);
-
 		/*
 		 * Disable CRTCs directly since we want to preserve sw state
-		 * for _thaw.
+		 * for _thaw. Also, power gate the CRTC power wells.
 		 */
 		drm_modeset_lock_all(dev);
-		for_each_crtc(dev, crtc) {
-			dev_priv->display.crtc_disable(crtc);
-		}
+		for_each_crtc(dev, crtc)
+			intel_crtc_control(crtc, false);
 		drm_modeset_unlock_all(dev);
 
+		intel_dp_mst_suspend(dev);
+
+		flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+		intel_runtime_pm_disable_interrupts(dev);
+		intel_hpd_cancel_work(dev_priv);
+
+		intel_suspend_encoders(dev_priv);
+
+		intel_suspend_gt_powersave(dev);
+
 		intel_modeset_suspend_hw(dev);
 	}
 
@@ -548,8 +581,15 @@ static int i915_drm_freeze(struct drm_de
 
 	i915_save_state(dev);
 
+	opregion_target_state = PCI_D3cold;
+#if IS_ENABLED(CONFIG_ACPI_SLEEP)
+	if (acpi_target_system_state() < ACPI_STATE_S3)
+		opregion_target_state = PCI_D1;
+#endif
+	intel_opregion_notify_adapter(dev, opregion_target_state);
+
+	intel_uncore_forcewake_reset(dev, false);
 	intel_opregion_fini(dev);
-	intel_uncore_fini(dev);
 
 	console_lock();
 	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
@@ -557,6 +597,8 @@ static int i915_drm_freeze(struct drm_de
 
 	dev_priv->suspend_count++;
 
+	intel_display_set_init_power(dev_priv, false);
+
 	return 0;
 }
 
@@ -606,7 +648,10 @@ static int i915_drm_thaw_early(struct dr
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	intel_uncore_early_sanitize(dev);
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		hsw_disable_pc8(dev_priv);
+
+	intel_uncore_early_sanitize(dev, true);
 	intel_uncore_sanitize(dev);
 	intel_power_domains_init_hw(dev_priv);
 
@@ -639,11 +684,19 @@ static int __i915_drm_thaw(struct drm_de
 		}
 		mutex_unlock(&dev->struct_mutex);
 
-		/* We need working interrupts for modeset enabling ... */
-		drm_irq_install(dev, dev->pdev->irq);
+		intel_runtime_pm_restore_interrupts(dev);
 
 		intel_modeset_init_hw(dev);
 
+		{
+			unsigned long irqflags;
+			spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+			if (dev_priv->display.hpd_irq_setup)
+				dev_priv->display.hpd_irq_setup(dev);
+			spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+		}
+
+		intel_dp_mst_resume(dev);
 		drm_modeset_lock_all(dev);
 		intel_modeset_setup_hw_state(dev, true);
 		drm_modeset_unlock_all(dev);
@@ -655,7 +708,6 @@ static int __i915_drm_thaw(struct drm_de
 		 * notifications.
 		 * */
 		intel_hpd_init(dev);
-		dev_priv->enable_hotplug_processing = true;
 		/* Config may have changed between suspend and resume */
 		drm_helper_hpd_irq_event(dev);
 	}
@@ -678,7 +730,8 @@ static int __i915_drm_thaw(struct drm_de
 	dev_priv->modeset_restore = MODESET_DONE;
 	mutex_unlock(&dev_priv->modeset_restore_lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_opregion_notify_adapter(dev, PCI_D0);
+
 	return 0;
 }
 
@@ -887,6 +940,7 @@ static int i915_pm_suspend_late(struct d
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct drm_i915_private *dev_priv = drm_dev->dev_private;
 
 	/*
 	 * We have a suspedn ordering issue with the snd-hda driver also
@@ -900,6 +954,9 @@ static int i915_pm_suspend_late(struct d
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
+	if (IS_HASWELL(drm_dev) || IS_BROADWELL(drm_dev))
+		hsw_enable_pc8(dev_priv);
+
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20080730"
+#define DRIVER_DATE		"20140725"
 
 enum pipe {
 	INVALID_PIPE = -1,
@@ -129,6 +129,7 @@ enum intel_display_power_domain {
 	POWER_DOMAIN_PORT_OTHER,
 	POWER_DOMAIN_VGA,
 	POWER_DOMAIN_AUDIO,
+	POWER_DOMAIN_PLLS,
 	POWER_DOMAIN_INIT,
 
 	POWER_DOMAIN_NUM,
@@ -178,14 +179,21 @@ enum hpd_pin {
 	list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
 		if ((intel_connector)->base.encoder == (__encoder))
 
+#define for_each_power_domain(domain, mask)				\
+	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
+		if ((1 << (domain)) & (mask))
+
 struct drm_i915_private;
+struct i915_mm_struct;
 struct i915_mmu_object;
 
 enum intel_dpll_id {
 	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
 	/* real shared dpll ids must be >= 0 */
-	DPLL_ID_PCH_PLL_A,
-	DPLL_ID_PCH_PLL_B,
+	DPLL_ID_PCH_PLL_A = 0,
+	DPLL_ID_PCH_PLL_B = 1,
+	DPLL_ID_WRPLL1 = 0,
+	DPLL_ID_WRPLL2 = 1,
 };
 #define I915_NUM_PLLS 2
 
@@ -194,6 +202,7 @@ struct intel_dpll_hw_state {
 	uint32_t dpll_md;
 	uint32_t fp0;
 	uint32_t fp1;
+	uint32_t wrpll;
 };
 
 struct intel_shared_dpll {
@@ -204,6 +213,8 @@ struct intel_shared_dpll {
 	/* should match the index in the dev_priv->shared_dplls array */
 	enum intel_dpll_id id;
 	struct intel_dpll_hw_state hw_state;
+	/* The mode_set hook is optional and should be used together with the
+	 * intel_prepare_shared_dpll function. */
 	void (*mode_set)(struct drm_i915_private *dev_priv,
 			 struct intel_shared_dpll *pll);
 	void (*enable)(struct drm_i915_private *dev_priv,
@@ -228,12 +239,6 @@ void intel_link_compute_m_n(int bpp, int
 			    int pixel_clock, int link_clock,
 			    struct intel_link_m_n *m_n);
 
-struct intel_ddi_plls {
-	int spll_refcount;
-	int wrpll1_refcount;
-	int wrpll2_refcount;
-};
-
 /* Interface history:
  *
  * 1.1: Original.
@@ -310,6 +315,7 @@ struct drm_i915_error_state {
 	u32 eir;
 	u32 pgtbl_er;
 	u32 ier;
+	u32 gtier[4];
 	u32 ccid;
 	u32 derrmr;
 	u32 forcewake;
@@ -324,6 +330,7 @@ struct drm_i915_error_state {
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
+	struct drm_i915_error_object *semaphore_obj;
 
 	struct drm_i915_error_ring {
 		bool valid;
@@ -435,8 +442,8 @@ struct drm_i915_display_funcs {
 	void (*update_wm)(struct drm_crtc *crtc);
 	void (*update_sprite_wm)(struct drm_plane *plane,
 				 struct drm_crtc *crtc,
-				 uint32_t sprite_width, int pixel_size,
-				 bool enable, bool scaled);
+				 uint32_t sprite_width, uint32_t sprite_height,
+				 int pixel_size, bool enable, bool scaled);
 	void (*modeset_global_resources)(struct drm_device *dev);
 	/* Returns the active state of the crtc, and if the crtc is active,
 	 * fills out the pipe-config with the hw state. */
@@ -552,8 +559,6 @@ struct intel_device_info {
 	/* Register offsets for the various display pipes and transcoders */
 	int pipe_offsets[I915_MAX_TRANSCODERS];
 	int trans_offsets[I915_MAX_TRANSCODERS];
-	int dpll_offsets[I915_MAX_PIPES];
-	int dpll_md_offsets[I915_MAX_PIPES];
 	int palette_offsets[I915_MAX_PIPES];
 	int cursor_offsets[I915_MAX_PIPES];
 };
@@ -586,28 +591,48 @@ struct i915_ctx_hang_stats {
 };
 
 /* This must match up with the value previously used for execbuf2.rsvd1. */
-#define DEFAULT_CONTEXT_ID 0
+#define DEFAULT_CONTEXT_HANDLE 0
+/**
+ * struct intel_context - as the name implies, represents a context.
+ * @ref: reference count.
+ * @user_handle: userspace tracking identity for this context.
+ * @remap_slice: l3 row remapping information.
+ * @file_priv: filp associated with this context (NULL for global default
+ *	       context).
+ * @hang_stats: information about the role of this context in possible GPU
+ *		hangs.
+ * @vm: virtual memory space used by this context.
+ * @legacy_hw_ctx: render context backing object and whether it is correctly
+ *                initialized (legacy ring submission mechanism only).
+ * @link: link in the global list of contexts.
+ *
+ * Contexts are memory images used by the hardware to store copies of their
+ * internal state.
+ */
 struct intel_context {
 	struct kref ref;
-	int id;
-	bool is_initialized;
+	int user_handle;
 	uint8_t remap_slice;
 	struct drm_i915_file_private *file_priv;
-	struct intel_engine_cs *last_ring;
-	struct drm_i915_gem_object *obj;
 	struct i915_ctx_hang_stats hang_stats;
 	struct i915_address_space *vm;
 
+	struct {
+		struct drm_i915_gem_object *rcs_state;
+		bool initialized;
+	} legacy_hw_ctx;
+
 	struct list_head link;
 };
 
 struct i915_fbc {
 	unsigned long size;
+	unsigned threshold;
 	unsigned int fb_id;
 	enum plane plane;
 	int y;
 
-	struct drm_mm_node *compressed_fb;
+	struct drm_mm_node compressed_fb;
 	struct drm_mm_node *compressed_llb;
 
 	struct intel_fbc_work {
@@ -635,9 +660,15 @@ struct i915_drrs {
 	struct intel_connector *connector;
 };
 
+struct intel_dp;
 struct i915_psr {
+	struct mutex lock;
 	bool sink_support;
 	bool source_ok;
+	struct intel_dp *enabled;
+	bool active;
+	struct delayed_work work;
+	unsigned busy_frontbuffer_bits;
 };
 
 enum intel_pch {
@@ -880,6 +911,12 @@ struct vlv_s0ix_state {
 	u32 clock_gate_dis2;
 };
 
+struct intel_rps_ei {
+	u32 cz_clock;
+	u32 render_c0;
+	u32 media_c0;
+};
+
 struct intel_gen6_power_mgmt {
 	/* work and pm_iir are protected by dev_priv->irq_lock */
 	struct work_struct work;
@@ -903,6 +940,9 @@ struct intel_gen6_power_mgmt {
 	u8 efficient_freq;	/* AKA RPe. Pre-determined balanced frequency */
 	u8 rp1_freq;		/* "less than" RP0 power/freqency */
 	u8 rp0_freq;		/* Non-overclocked max frequency. */
+	u32 cz_freq;
+
+	u32 ei_interrupt_count;
 
 	int last_adj;
 	enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
@@ -910,6 +950,9 @@ struct intel_gen6_power_mgmt {
 	bool enabled;
 	struct delayed_work delayed_resume_work;
 
+	/* manual wa residency calculations */
+	struct intel_rps_ei up_ei, down_ei;
+
 	/*
 	 * Protects RPS/RC6 register access and PCU communication.
 	 * Must be taken after struct_mutex if nested.
@@ -931,7 +974,7 @@ struct intel_ilk_power_mgmt {
 	unsigned long last_time1;
 	unsigned long chipset_power;
 	u64 last_count2;
-	struct timespec last_time2;
+	u64 last_time2;
 	unsigned long gfx_power;
 	u8 corr;
 
@@ -1230,6 +1273,7 @@ struct intel_vbt_data {
 		u16 pwm_freq_hz;
 		bool present;
 		bool active_low_pwm;
+		u8 min_brightness;	/* min_brightness/255 of max */
 	} backlight;
 
 	/* MIPI DSI */
@@ -1299,7 +1343,7 @@ struct ilk_wm_values {
  */
 struct i915_runtime_pm {
 	bool suspended;
-	bool irqs_disabled;
+	bool _irqs_disabled;
 };
 
 enum intel_pipe_crc_source {
@@ -1332,6 +1376,17 @@ struct intel_pipe_crc {
 	wait_queue_head_t wq;
 };
 
+struct i915_frontbuffer_tracking {
+	struct mutex lock;
+
+	/*
+	 * Tracking bits for delayed frontbuffer flushing du to gpu activity or
+	 * scheduled flips.
+	 */
+	unsigned busy_bits;
+	unsigned flip_bits;
+};
+
 struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
@@ -1363,6 +1418,7 @@ struct drm_i915_private {
 
 	struct pci_dev *bridge_dev;
 	struct intel_engine_cs ring[I915_NUM_RINGS];
+	struct drm_i915_gem_object *semaphore_obj;
 	uint32_t last_seqno, next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
@@ -1371,6 +1427,9 @@ struct drm_i915_private {
 	/* protects the irq masks */
 	spinlock_t irq_lock;
 
+	/* protects the mmio flip data */
+	spinlock_t mmio_flip_lock;
+
 	bool display_irqs_enabled;
 
 	/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
@@ -1390,7 +1449,6 @@ struct drm_i915_private {
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
 	struct work_struct hotplug_work;
-	bool enable_hotplug_processing;
 	struct {
 		unsigned long hpd_last_jiffies;
 		int hpd_cnt;
@@ -1401,7 +1459,7 @@ struct drm_i915_private {
 		} hpd_mark;
 	} hpd_stats[HPD_NUM_PINS];
 	u32 hpd_event_bits;
-	struct timer_list hotplug_reenable_timer;
+	struct delayed_work hotplug_reenable_work;
 
 	struct i915_fbc fbc;
 	struct i915_drrs drrs;
@@ -1449,9 +1507,8 @@ struct drm_i915_private {
 	struct i915_gtt gtt; /* VM representing the global address space */
 
 	struct i915_gem_mm mm;
-#if defined(CONFIG_MMU_NOTIFIER)
-	DECLARE_HASHTABLE(mmu_notifiers, 7);
-#endif
+	DECLARE_HASHTABLE(mm_structs, 7);
+	struct mutex mm_lock;
 
 	/* Kernel Modesetting */
 
@@ -1467,7 +1524,6 @@ struct drm_i915_private {
 
 	int num_shared_dpll;
 	struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
-	struct intel_ddi_plls ddi_plls;
 	int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
 	/* Reclocking support */
@@ -1475,6 +1531,9 @@ struct drm_i915_private {
 	bool lvds_downclock_avail;
 	/* indicates the reduced downclock for LVDS*/
 	int lvds_downclock;
+
+	struct i915_frontbuffer_tracking fb_tracking;
+
 	u16 orig_clock;
 
 	bool mchbar_need_disable;
@@ -1541,6 +1600,20 @@ struct drm_i915_private {
 
 	struct i915_runtime_pm pm;
 
+	struct intel_digital_port *hpd_irq_port[I915_MAX_PORTS];
+	u32 long_hpd_port_mask;
+	u32 short_hpd_port_mask;
+	struct work_struct dig_port_work;
+
+	/*
+	 * if we get a HPD irq from DP and a HPD irq from non-DP
+	 * the non-DP HPD could block the workqueue on a mode config
+	 * mutex getting, that userspace may have taken. However
+	 * userspace is waiting on the DP workqueue to run which is
+	 * blocked behind the non-DP one.
+	 */
+	struct workqueue_struct *dp_wq;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
@@ -1592,6 +1665,28 @@ struct drm_i915_gem_object_ops {
 	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-vise. This
+ * doesn't mean that the hw necessarily already scans it out, but that any
+ * rendering (by the cpu or gpu) will land in the frontbuffer eventually.
+ *
+ * We have one bit per pipe and per scanout plane type.
+ */
+#define INTEL_FRONTBUFFER_BITS_PER_PIPE 4
+#define INTEL_FRONTBUFFER_BITS \
+	(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES)
+#define INTEL_FRONTBUFFER_PRIMARY(pipe) \
+	(1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
+#define INTEL_FRONTBUFFER_CURSOR(pipe) \
+	(1 << (1 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_SPRITE(pipe) \
+	(1 << (2 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_OVERLAY(pipe) \
+	(1 << (3 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
+	(0xf << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
+
 struct drm_i915_gem_object {
 	struct drm_gem_object base;
 
@@ -1662,6 +1757,12 @@ struct drm_i915_gem_object {
 	unsigned int pin_display: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;
+
+	/*
 	 * Is the GPU currently using a fence to access this buffer,
 	 */
 	unsigned int pending_fenced_gpu_access:1;
@@ -1673,6 +1774,8 @@ struct drm_i915_gem_object {
 	unsigned int has_global_gtt_mapping:1;
 	unsigned int has_dma_mapping:1;
 
+	unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;
+
 	struct sg_table *pages;
 	int pages_pin_count;
 
@@ -1711,14 +1814,18 @@ struct drm_i915_gem_object {
 			unsigned workers :4;
 #define I915_GEM_USERPTR_MAX_WORKERS 15
 
-			struct mm_struct *mm;
-			struct i915_mmu_object *mn;
+			struct i915_mm_struct *mm;
+			struct i915_mmu_object *mmu_object;
 			struct work_struct *work;
 		} userptr;
 	};
 };
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
+void i915_gem_track_fb(struct drm_i915_gem_object *old,
+		       struct drm_i915_gem_object *new,
+		       unsigned frontbuffer_bits);
+
 /**
  * Request queue structure.
  *
@@ -1940,10 +2047,8 @@ struct drm_i915_cmd_table {
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
 #define HAS_HW_CONTEXTS(dev)	(INTEL_INFO(dev)->gen >= 6)
-#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >= 6 && \
-				 (!IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
-#define HAS_PPGTT(dev)		(INTEL_INFO(dev)->gen >= 7 \
-				 && !IS_GEN8(dev))
+#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >= 6)
+#define HAS_PPGTT(dev)		(INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))
 #define USES_PPGTT(dev)		intel_enable_ppgtt(dev, false)
 #define USES_FULL_PPGTT(dev)	intel_enable_ppgtt(dev, true)
 
@@ -1998,6 +2103,8 @@ struct drm_i915_cmd_table {
 #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
 #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
 
+#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
+
 /* DPF == dynamic parity feature */
 #define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
 #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
@@ -2040,6 +2147,8 @@ struct i915_params {
 	bool reset;
 	bool disable_display;
 	bool disable_vtd_wa;
+	int use_mmio_flip;
+	bool mmio_debug;
 };
 extern struct i915_params i915 __read_mostly;
 
@@ -2048,12 +2157,12 @@ void i915_update_dri1_breadcrumb(struct
 extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
-extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
 extern void i915_driver_lastclose(struct drm_device * dev);
 extern void i915_driver_preclose(struct drm_device *dev,
-				 struct drm_file *file_priv);
+				 struct drm_file *file);
 extern void i915_driver_postclose(struct drm_device *dev,
-				  struct drm_file *file_priv);
+				  struct drm_file *file);
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 #ifdef CONFIG_COMPAT
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
@@ -2069,6 +2178,7 @@ extern unsigned long i915_mch_val(struct
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
+void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
 
 extern void intel_console_resume(struct work_struct *work);
 
@@ -2084,10 +2194,12 @@ extern void intel_irq_init(struct drm_de
 extern void intel_hpd_init(struct drm_device *dev);
 
 extern void intel_uncore_sanitize(struct drm_device *dev);
-extern void intel_uncore_early_sanitize(struct drm_device *dev);
+extern void intel_uncore_early_sanitize(struct drm_device *dev,
+					bool restore_forcewake);
 extern void intel_uncore_init(struct drm_device *dev);
 extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
+extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore);
 
 void
 i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
@@ -2235,6 +2347,8 @@ bool i915_gem_retire_requests(struct drm
 void i915_gem_retire_requests_ring(struct intel_engine_cs *ring);
 int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
 				      bool interruptible);
+int __must_check i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno);
+
 static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
 {
 	return unlikely(atomic_read(&error->reset_counter)
@@ -2404,7 +2518,7 @@ static inline void i915_gem_context_unre
 
 static inline bool i915_gem_context_is_default(const struct intel_context *c)
 {
-	return c->id == DEFAULT_CONTEXT_ID;
+	return c->user_handle == DEFAULT_CONTEXT_HANDLE;
 }
 
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -2435,7 +2549,7 @@ static inline void i915_gem_chipset_flus
 
 /* i915_gem_stolen.c */
 int i915_gem_init_stolen(struct drm_device *dev);
-int i915_gem_stolen_setup_compression(struct drm_device *dev, int size);
+int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp);
 void i915_gem_stolen_cleanup_compression(struct drm_device *dev);
 void i915_gem_cleanup_stolen(struct drm_device *dev);
 struct drm_i915_gem_object *
@@ -2445,7 +2559,6 @@ i915_gem_object_create_stolen_for_preall
 					       u32 stolen_offset,
 					       u32 gtt_offset,
 					       u32 size);
-void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
 
 /* i915_gem_tiling.c */
 static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
@@ -2593,8 +2706,8 @@ extern bool ironlake_set_drps(struct drm
 extern void intel_init_pch_refclk(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
 extern void valleyview_set_rps(struct drm_device *dev, u8 val);
-extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv);
-extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv);
+extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
+				  bool enable);
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 extern int intel_enable_rc6(const struct drm_device *dev);
@@ -2605,6 +2718,8 @@ int i915_reg_read_ioctl(struct drm_devic
 int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file);
 
+void intel_notify_mmio_flip(struct intel_engine_cs *ring);
+
 /* overlay */
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
 extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
@@ -2700,10 +2815,10 @@ int vlv_freq_opcode(struct drm_i915_priv
 
 static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
 {
-	if (HAS_PCH_SPLIT(dev))
-		return CPU_VGACNTRL;
-	else if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev))
 		return VLV_VGACNTRL;
+	else if (INTEL_INFO(dev)->gen >= 5)
+		return CPU_VGACNTRL;
 	else
 		return VGACNTRL;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -1095,7 +1095,7 @@ i915_gem_check_wedge(struct i915_gpu_err
  * Compare seqno against outstanding lazy request. Emit a request if they are
  * equal.
  */
-static int
+int
 i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno)
 {
 	int ret;
@@ -1149,26 +1149,26 @@ static bool can_wait_boost(struct drm_i9
 static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
 			unsigned reset_counter,
 			bool interruptible,
-			struct timespec *timeout,
+			s64 *timeout,
 			struct drm_i915_file_private *file_priv)
 {
 	struct drm_device *dev = ring->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const bool irq_test_in_progress =
 		ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
-	struct timespec before, now;
 	DEFINE_WAIT(wait);
 	unsigned long timeout_expire;
+	s64 before, now;
 	int ret;
 
-	WARN(dev_priv->pm.irqs_disabled, "IRQs disabled\n");
+	WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
 
 	if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
 		return 0;
 
-	timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
+	timeout_expire = timeout ? jiffies + nsecs_to_jiffies((u64)*timeout) : 0;
 
-	if (INTEL_INFO(dev)->gen >= 6 && can_wait_boost(file_priv)) {
+	if (INTEL_INFO(dev)->gen >= 6 && ring->id == RCS && can_wait_boost(file_priv)) {
 		gen6_rps_boost(dev_priv);
 		if (file_priv)
 			mod_delayed_work(dev_priv->wq,
@@ -1181,7 +1181,7 @@ static int __wait_seqno(struct intel_eng
 
 	/* Record current time in case interrupted by signal, or wedged */
 	trace_i915_gem_request_wait_begin(ring, seqno);
-	getrawmonotonic(&before);
+	before = ktime_get_raw_ns();
 	for (;;) {
 		struct timer_list timer;
 
@@ -1230,7 +1230,7 @@ static int __wait_seqno(struct intel_eng
 			destroy_timer_on_stack(&timer);
 		}
 	}
-	getrawmonotonic(&now);
+	now = ktime_get_raw_ns();
 	trace_i915_gem_request_wait_end(ring, seqno);
 
 	if (!irq_test_in_progress)
@@ -1239,10 +1239,9 @@ static int __wait_seqno(struct intel_eng
 	finish_wait(&ring->irq_queue, &wait);
 
 	if (timeout) {
-		struct timespec sleep_time = timespec_sub(now, before);
-		*timeout = timespec_sub(*timeout, sleep_time);
-		if (!timespec_valid(timeout)) /* i.e. negative time remains */
-			set_normalized_timespec(timeout, 0, 0);
+		s64 tres = *timeout - (now - before);
+
+		*timeout = tres < 0 ? 0 : tres;
 	}
 
 	return ret;
@@ -1561,14 +1560,29 @@ int i915_gem_fault(struct vm_area_struct
 	if (ret)
 		goto unpin;
 
-	obj->fault_mappable = true;
-
+	/* Finally, remap it using the new GTT offset */
 	pfn = dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj);
 	pfn >>= PAGE_SHIFT;
-	pfn += page_offset;
 
-	/* Finally, remap it using the new GTT offset */
-	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+	if (!obj->fault_mappable) {
+		unsigned long size = min_t(unsigned long,
+					   vma->vm_end - vma->vm_start,
+					   obj->base.size);
+		int i;
+
+		for (i = 0; i < size >> PAGE_SHIFT; i++) {
+			ret = vm_insert_pfn(vma,
+					    (unsigned long)vma->vm_start + i * PAGE_SIZE,
+					    pfn + i);
+			if (ret)
+				break;
+		}
+
+		obj->fault_mappable = true;
+	} else
+		ret = vm_insert_pfn(vma,
+				    (unsigned long)vmf->virtual_address,
+				    pfn + page_offset);
 unpin:
 	i915_gem_object_ggtt_unpin(obj);
 unlock:
@@ -1576,10 +1590,13 @@ unlock:
 out:
 	switch (ret) {
 	case -EIO:
-		/* If this -EIO is due to a gpu hang, give the reset code a
-		 * chance to clean up the mess. Otherwise return the proper
-		 * SIGBUS. */
-		if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+		/*
+		 * We eat errors when the gpu is terminally wedged to avoid
+		 * userspace unduly crashing (gl has no provisions for mmaps to
+		 * fail). But any other -EIO isn't ours (e.g. swap in failure)
+		 * and so needs to be reported.
+		 */
+		if (!i915_terminally_wedged(&dev_priv->gpu_error)) {
 			ret = VM_FAULT_SIGBUS;
 			break;
 		}
@@ -2052,16 +2069,10 @@ 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.
 			 */
-			gfp &= ~(__GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD);
-			gfp |= __GFP_IO | __GFP_WAIT;
-
 			i915_gem_shrink_all(dev_priv);
-			page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+			page = shmem_read_mapping_page(mapping, i);
 			if (IS_ERR(page))
 				goto err_pages;
-
-			gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
-			gfp &= ~(__GFP_IO | __GFP_WAIT);
 		}
 #ifdef CONFIG_SWIOTLB
 		if (swiotlb_nr_tbl()) {
@@ -2210,6 +2221,8 @@ i915_gem_object_move_to_inactive(struct
 			list_move_tail(&vma->mm_list, &vm->inactive_list);
 	}
 
+	intel_fb_obj_flush(obj, true);
+
 	list_del_init(&obj->ring_list);
 	obj->ring = NULL;
 
@@ -2319,7 +2332,7 @@ int __i915_add_request(struct intel_engi
 	u32 request_ring_position, request_start;
 	int ret;
 
-	request_start = intel_ring_get_tail(ring);
+	request_start = intel_ring_get_tail(ring->buffer);
 	/*
 	 * Emit any outstanding flushes - execbuf can fail to emit the flush
 	 * after having emitted the batchbuffer command. Hence we need to fix
@@ -2340,7 +2353,7 @@ int __i915_add_request(struct intel_engi
 	 * GPU processing the request, we never over-estimate the
 	 * position of the head.
 	 */
-	request_ring_position = intel_ring_get_tail(ring);
+	request_ring_position = intel_ring_get_tail(ring->buffer);
 
 	ret = ring->add_request(ring);
 	if (ret)
@@ -2746,16 +2759,10 @@ i915_gem_wait_ioctl(struct drm_device *d
 	struct drm_i915_gem_wait *args = data;
 	struct drm_i915_gem_object *obj;
 	struct intel_engine_cs *ring = NULL;
-	struct timespec timeout_stack, *timeout = NULL;
 	unsigned reset_counter;
 	u32 seqno = 0;
 	int ret = 0;
 
-	if (args->timeout_ns >= 0) {
-		timeout_stack = ns_to_timespec(args->timeout_ns);
-		timeout = &timeout_stack;
-	}
-
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
@@ -2780,9 +2787,9 @@ i915_gem_wait_ioctl(struct drm_device *d
 		 goto out;
 
 	/* Do this after OLR check to make sure we make forward progress polling
-	 * on this IOCTL with a 0 timeout (like busy ioctl)
+	 * on this IOCTL with a timeout <=0 (like busy ioctl)
 	 */
-	if (!args->timeout_ns) {
+	if (args->timeout_ns <= 0) {
 		ret = -ETIME;
 		goto out;
 	}
@@ -2791,10 +2798,8 @@ i915_gem_wait_ioctl(struct drm_device *d
 	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 	mutex_unlock(&dev->struct_mutex);
 
-	ret = __wait_seqno(ring, seqno, reset_counter, true, timeout, file->driver_priv);
-	if (timeout)
-		args->timeout_ns = timespec_to_ns(timeout);
-	return ret;
+	return __wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns,
+			    file->driver_priv);
 
 out:
 	drm_gem_object_unreference(&obj->base);
@@ -2831,6 +2836,8 @@ i915_gem_object_sync(struct drm_i915_gem
 	idx = intel_ring_sync_index(from, to);
 
 	seqno = obj->last_read_seqno;
+	/* Optimization: Avoid semaphore sync when we are sure we already
+	 * waited for an object with higher seqno */
 	if (seqno <= from->semaphore.sync_seqno[idx])
 		return 0;
 
@@ -2914,8 +2921,6 @@ int i915_vma_unbind(struct i915_vma *vma
 
 	vma->unbind_vma(vma);
 
-	i915_gem_gtt_finish_object(obj);
-
 	list_del_init(&vma->mm_list);
 	/* Avoid an unnecessary call to unbind on rebind. */
 	if (i915_is_ggtt(vma->vm))
@@ -2926,8 +2931,10 @@ int i915_vma_unbind(struct i915_vma *vma
 
 	/* Since the unbound list is global, only move to that list if
 	 * no more VMAs exist. */
-	if (list_empty(&obj->vma_list))
+	if (list_empty(&obj->vma_list)) {
+		i915_gem_gtt_finish_object(obj);
 		list_move_tail(&obj->global_list, &dev_priv->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
@@ -3539,6 +3546,8 @@ i915_gem_object_flush_gtt_write_domain(s
 	old_write_domain = obj->base.write_domain;
 	obj->base.write_domain = 0;
 
+	intel_fb_obj_flush(obj, false);
+
 	trace_i915_gem_object_change_domain(obj,
 					    obj->base.read_domains,
 					    old_write_domain);
@@ -3560,6 +3569,8 @@ i915_gem_object_flush_cpu_write_domain(s
 	old_write_domain = obj->base.write_domain;
 	obj->base.write_domain = 0;
 
+	intel_fb_obj_flush(obj, false);
+
 	trace_i915_gem_object_change_domain(obj,
 					    obj->base.read_domains,
 					    old_write_domain);
@@ -3613,6 +3624,9 @@ i915_gem_object_set_to_gtt_domain(struct
 		obj->dirty = 1;
 	}
 
+	if (write)
+		intel_fb_obj_invalidate(obj, NULL);
+
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
 					    old_write_domain);
@@ -3949,6 +3963,9 @@ i915_gem_object_set_to_cpu_domain(struct
 		obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
 
+	if (write)
+		intel_fb_obj_invalidate(obj, NULL);
+
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
 					    old_write_domain);
@@ -4437,13 +4454,14 @@ void i915_gem_free_object(struct drm_gem
 	if (obj->stolen)
 		i915_gem_object_unpin_pages(obj);
 
+	WARN_ON(obj->frontbuffer_bits);
+
 	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);
 	i915_gem_object_free_mmap_offset(obj);
-	i915_gem_object_release_stolen(obj);
 
 	BUG_ON(obj->pages);
 
@@ -4530,7 +4548,7 @@ i915_gem_suspend(struct drm_device *dev)
 
 	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
 	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
-	cancel_delayed_work_sync(&dev_priv->mm.idle_work);
+	flush_delayed_work(&dev_priv->mm.idle_work);
 
 	return 0;
 
@@ -4921,6 +4939,8 @@ i915_gem_load(struct drm_device *dev)
 
 	dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
 	register_oom_notifier(&dev_priv->mm.oom_notifier);
+
+	mutex_init(&dev_priv->fb_tracking.lock);
 }
 
 void i915_gem_release(struct drm_device *dev, struct drm_file *file)
@@ -4982,6 +5002,23 @@ int i915_gem_open(struct drm_device *dev
 	return ret;
 }
 
+void i915_gem_track_fb(struct drm_i915_gem_object *old,
+		       struct drm_i915_gem_object *new,
+		       unsigned frontbuffer_bits)
+{
+	if (old) {
+		WARN_ON(!mutex_is_locked(&old->base.dev->struct_mutex));
+		WARN_ON(!(old->frontbuffer_bits & frontbuffer_bits));
+		old->frontbuffer_bits &= ~frontbuffer_bits;
+	}
+
+	if (new) {
+		WARN_ON(!mutex_is_locked(&new->base.dev->struct_mutex));
+		WARN_ON(new->frontbuffer_bits & frontbuffer_bits);
+		new->frontbuffer_bits |= frontbuffer_bits;
+	}
+}
+
 static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
 {
 	if (!mutex_is_locked(mutex))
@@ -5064,12 +5101,13 @@ unsigned long i915_gem_obj_offset(struct
 	    vm == &dev_priv->mm.aliasing_ppgtt->base)
 		vm = &dev_priv->gtt.base;
 
-	BUG_ON(list_empty(&o->vma_list));
 	list_for_each_entry(vma, &o->vma_list, vma_link) {
 		if (vma->vm == vm)
 			return vma->node.start;
 
 	}
+	WARN(1, "%s vma for this object not found.\n",
+	     i915_is_ggtt(vm) ? "global" : "ppgtt");
 	return -1;
 }
 
@@ -5150,8 +5188,11 @@ i915_gem_shrinker_oom(struct notifier_bl
 	bool was_interruptible;
 	bool unlock;
 
-	while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout)
+	while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout) {
 		schedule_timeout_killable(1);
+		if (fatal_signal_pending(current))
+			return NOTIFY_DONE;
+	}
 	if (timeout == 0) {
 		pr_err("Unable to purge GPU memory due lock contention.\n");
 		return NOTIFY_DONE;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_context.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_context.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2014-09-28 17:29:07.000000000 -0400
@@ -182,22 +182,50 @@ void i915_gem_context_free(struct kref *
 						   typeof(*ctx), ref);
 	struct i915_hw_ppgtt *ppgtt = NULL;
 
-	if (ctx->obj) {
+	if (ctx->legacy_hw_ctx.rcs_state) {
 		/* We refcount even the aliasing PPGTT to keep the code symmetric */
-		if (USES_PPGTT(ctx->obj->base.dev))
+		if (USES_PPGTT(ctx->legacy_hw_ctx.rcs_state->base.dev))
 			ppgtt = ctx_to_ppgtt(ctx);
-
-		/* XXX: Free up the object before tearing down the address space, in
-		 * case we're bound in the PPGTT */
-		drm_gem_object_unreference(&ctx->obj->base);
 	}
 
 	if (ppgtt)
 		kref_put(&ppgtt->ref, ppgtt_release);
+	if (ctx->legacy_hw_ctx.rcs_state)
+		drm_gem_object_unreference(&ctx->legacy_hw_ctx.rcs_state->base);
 	list_del(&ctx->link);
 	kfree(ctx);
 }
 
+static struct drm_i915_gem_object *
+i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
+{
+	struct drm_i915_gem_object *obj;
+	int ret;
+
+	obj = i915_gem_alloc_object(dev, size);
+	if (obj == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * Try to make the context utilize L3 as well as LLC.
+	 *
+	 * On VLV we don't have L3 controls in the PTEs so we
+	 * shouldn't touch the cache level, especially as that
+	 * would make the object snooped which might have a
+	 * negative performance impact.
+	 */
+	if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
+		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
+		/* Failure shouldn't ever happen this early */
+		if (WARN_ON(ret)) {
+			drm_gem_object_unreference(&obj->base);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return obj;
+}
+
 static struct i915_hw_ppgtt *
 create_vm_for_ctx(struct drm_device *dev, struct intel_context *ctx)
 {
@@ -234,40 +262,26 @@ __create_hw_context(struct drm_device *d
 	list_add_tail(&ctx->link, &dev_priv->context_list);
 
 	if (dev_priv->hw_context_size) {
-		ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
-		if (ctx->obj == NULL) {
-			ret = -ENOMEM;
+		struct drm_i915_gem_object *obj =
+				i915_gem_alloc_context_obj(dev, dev_priv->hw_context_size);
+		if (IS_ERR(obj)) {
+			ret = PTR_ERR(obj);
 			goto err_out;
 		}
-
-		/*
-		 * Try to make the context utilize L3 as well as LLC.
-		 *
-		 * On VLV we don't have L3 controls in the PTEs so we
-		 * shouldn't touch the cache level, especially as that
-		 * would make the object snooped which might have a
-		 * negative performance impact.
-		 */
-		if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
-			ret = i915_gem_object_set_cache_level(ctx->obj,
-							      I915_CACHE_L3_LLC);
-			/* Failure shouldn't ever happen this early */
-			if (WARN_ON(ret))
-				goto err_out;
-		}
+		ctx->legacy_hw_ctx.rcs_state = obj;
 	}
 
 	/* Default context will never have a file_priv */
 	if (file_priv != NULL) {
 		ret = idr_alloc(&file_priv->context_idr, ctx,
-				DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
+				DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL);
 		if (ret < 0)
 			goto err_out;
 	} else
-		ret = DEFAULT_CONTEXT_ID;
+		ret = DEFAULT_CONTEXT_HANDLE;
 
 	ctx->file_priv = file_priv;
-	ctx->id = ret;
+	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. */
@@ -301,7 +315,7 @@ i915_gem_create_context(struct drm_devic
 	if (IS_ERR(ctx))
 		return ctx;
 
-	if (is_global_default_ctx && ctx->obj) {
+	if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state) {
 		/* We may need to do things with the shrinker which
 		 * require us to immediately switch back to the default
 		 * context. This can cause a problem as pinning the
@@ -309,7 +323,7 @@ i915_gem_create_context(struct drm_devic
 		 * be available. To avoid this we always pin the default
 		 * context.
 		 */
-		ret = i915_gem_obj_ggtt_pin(ctx->obj,
+		ret = i915_gem_obj_ggtt_pin(ctx->legacy_hw_ctx.rcs_state,
 					    get_context_alignment(dev), 0);
 		if (ret) {
 			DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
@@ -349,8 +363,8 @@ i915_gem_create_context(struct drm_devic
 	return ctx;
 
 err_unpin:
-	if (is_global_default_ctx && ctx->obj)
-		i915_gem_object_ggtt_unpin(ctx->obj);
+	if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state)
+		i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
 err_destroy:
 	i915_gem_context_unreference(ctx);
 	return ERR_PTR(ret);
@@ -366,23 +380,27 @@ void i915_gem_context_reset(struct drm_d
 	for (i = 0; i < I915_NUM_RINGS; i++) {
 		struct intel_engine_cs *ring = &dev_priv->ring[i];
 		struct intel_context *dctx = ring->default_context;
+		struct intel_context *lctx = ring->last_context;
 
 		/* Do a fake switch to the default context */
-		if (ring->last_context == dctx)
+		if (lctx == dctx)
 			continue;
 
-		if (!ring->last_context)
+		if (!lctx)
 			continue;
 
-		if (dctx->obj && i == RCS) {
-			WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
+		if (dctx->legacy_hw_ctx.rcs_state && i == RCS) {
+			WARN_ON(i915_gem_obj_ggtt_pin(dctx->legacy_hw_ctx.rcs_state,
 						      get_context_alignment(dev), 0));
 			/* Fake a finish/inactive */
-			dctx->obj->base.write_domain = 0;
-			dctx->obj->active = 0;
+			dctx->legacy_hw_ctx.rcs_state->base.write_domain = 0;
+			dctx->legacy_hw_ctx.rcs_state->active = 0;
 		}
 
-		i915_gem_context_unreference(ring->last_context);
+		if (lctx->legacy_hw_ctx.rcs_state && i == RCS)
+			i915_gem_object_ggtt_unpin(lctx->legacy_hw_ctx.rcs_state);
+
+		i915_gem_context_unreference(lctx);
 		i915_gem_context_reference(dctx);
 		ring->last_context = dctx;
 	}
@@ -429,7 +447,7 @@ void i915_gem_context_fini(struct drm_de
 	struct intel_context *dctx = dev_priv->ring[RCS].default_context;
 	int i;
 
-	if (dctx->obj) {
+	if (dctx->legacy_hw_ctx.rcs_state) {
 		/* The only known way to stop the gpu from accessing the hw context is
 		 * to reset it. Do this as the very last operation to avoid confusing
 		 * other code, leading to spurious errors. */
@@ -444,13 +462,13 @@ void i915_gem_context_fini(struct drm_de
 		WARN_ON(!dev_priv->ring[RCS].last_context);
 		if (dev_priv->ring[RCS].last_context == dctx) {
 			/* Fake switch to NULL context */
-			WARN_ON(dctx->obj->active);
-			i915_gem_object_ggtt_unpin(dctx->obj);
+			WARN_ON(dctx->legacy_hw_ctx.rcs_state->active);
+			i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
 			i915_gem_context_unreference(dctx);
 			dev_priv->ring[RCS].last_context = NULL;
 		}
 
-		i915_gem_object_ggtt_unpin(dctx->obj);
+		i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
 	}
 
 	for (i = 0; i < I915_NUM_RINGS; i++) {
@@ -570,7 +588,7 @@ mi_set_context(struct intel_engine_cs *r
 
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_emit(ring, MI_SET_CONTEXT);
-	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->obj) |
+	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) |
 			MI_MM_SPACE_GTT |
 			MI_SAVE_EXT_STATE_EN |
 			MI_RESTORE_EXT_STATE_EN |
@@ -602,16 +620,16 @@ static int do_switch(struct intel_engine
 	int ret, i;
 
 	if (from != NULL && ring == &dev_priv->ring[RCS]) {
-		BUG_ON(from->obj == NULL);
-		BUG_ON(!i915_gem_obj_is_pinned(from->obj));
+		BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
+		BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
 	}
 
-	if (from == to && from->last_ring == ring && !to->remap_slice)
+	if (from == to && !to->remap_slice)
 		return 0;
 
 	/* Trying to pin first makes error handling easier. */
 	if (ring == &dev_priv->ring[RCS]) {
-		ret = i915_gem_obj_ggtt_pin(to->obj,
+		ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
 					    get_context_alignment(ring->dev), 0);
 		if (ret)
 			return ret;
@@ -644,17 +662,17 @@ static int do_switch(struct intel_engine
 	 *
 	 * XXX: We need a real interface to do this instead of trickery.
 	 */
-	ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
+	ret = i915_gem_object_set_to_gtt_domain(to->legacy_hw_ctx.rcs_state, false);
 	if (ret)
 		goto unpin_out;
 
-	if (!to->obj->has_global_gtt_mapping) {
-		struct i915_vma *vma = i915_gem_obj_to_vma(to->obj,
+	if (!to->legacy_hw_ctx.rcs_state->has_global_gtt_mapping) {
+		struct i915_vma *vma = i915_gem_obj_to_vma(to->legacy_hw_ctx.rcs_state,
 							   &dev_priv->gtt.base);
-		vma->bind_vma(vma, to->obj->cache_level, GLOBAL_BIND);
+		vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, GLOBAL_BIND);
 	}
 
-	if (!to->is_initialized || i915_gem_context_is_default(to))
+	if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
 	ret = mi_set_context(ring, to, hw_flags);
@@ -680,8 +698,8 @@ static int do_switch(struct intel_engine
 	 * MI_SET_CONTEXT instead of when the next seqno has completed.
 	 */
 	if (from != NULL) {
-		from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
-		i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring);
+		from->legacy_hw_ctx.rcs_state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+		i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), ring);
 		/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
 		 * whole damn pipeline, we don't need to explicitly mark the
 		 * object dirty. The only exception is that the context must be
@@ -689,21 +707,20 @@ static int do_switch(struct intel_engine
 		 * able to defer doing this until we know the object would be
 		 * swapped, but there is no way to do that yet.
 		 */
-		from->obj->dirty = 1;
-		BUG_ON(from->obj->ring != ring);
+		from->legacy_hw_ctx.rcs_state->dirty = 1;
+		BUG_ON(from->legacy_hw_ctx.rcs_state->ring != ring);
 
 		/* obj is kept alive until the next request by its active ref */
-		i915_gem_object_ggtt_unpin(from->obj);
+		i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
 		i915_gem_context_unreference(from);
 	}
 
-	uninitialized = !to->is_initialized && from == NULL;
-	to->is_initialized = true;
+	uninitialized = !to->legacy_hw_ctx.initialized && from == NULL;
+	to->legacy_hw_ctx.initialized = true;
 
 done:
 	i915_gem_context_reference(to);
 	ring->last_context = to;
-	to->last_ring = ring;
 
 	if (uninitialized) {
 		ret = i915_gem_render_state_init(ring);
@@ -715,7 +732,7 @@ done:
 
 unpin_out:
 	if (ring->id == RCS)
-		i915_gem_object_ggtt_unpin(to->obj);
+		i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
 	return ret;
 }
 
@@ -736,7 +753,7 @@ int i915_switch_context(struct intel_eng
 
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-	if (to->obj == NULL) { /* We have the fake context */
+	if (to->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
 		if (to != ring->last_context) {
 			i915_gem_context_reference(to);
 			if (ring->last_context)
@@ -774,7 +791,7 @@ int i915_gem_context_create_ioctl(struct
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	args->ctx_id = ctx->id;
+	args->ctx_id = ctx->user_handle;
 	DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id);
 
 	return 0;
@@ -788,7 +805,7 @@ int i915_gem_context_destroy_ioctl(struc
 	struct intel_context *ctx;
 	int ret;
 
-	if (args->ctx_id == DEFAULT_CONTEXT_ID)
+	if (args->ctx_id == DEFAULT_CONTEXT_HANDLE)
 		return -ENOENT;
 
 	ret = i915_mutex_lock_interruptible(dev);
@@ -801,7 +818,7 @@ int i915_gem_context_destroy_ioctl(struc
 		return PTR_ERR(ctx);
 	}
 
-	idr_remove(&ctx->file_priv->context_idr, ctx->id);
+	idr_remove(&ctx->file_priv->context_idr, ctx->user_handle);
 	i915_gem_context_unreference(ctx);
 	mutex_unlock(&dev->struct_mutex);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -237,7 +237,8 @@ struct dma_buf *i915_gem_prime_export(st
 			return ERR_PTR(ret);
 	}
 
-	return dma_buf_export(gem_obj, &i915_dmabuf_ops, gem_obj->size, flags);
+	return dma_buf_export(gem_obj, &i915_dmabuf_ops, gem_obj->size, flags,
+			      NULL);
 }
 
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -938,7 +938,7 @@ i915_gem_validate_context(struct drm_dev
 	struct intel_context *ctx = NULL;
 	struct i915_ctx_hang_stats *hs;
 
-	if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_ID)
+	if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
 		return ERR_PTR(-EINVAL);
 
 	ctx = i915_gem_context_get(file->driver_priv, ctx_id);
@@ -975,10 +975,8 @@ i915_gem_execbuffer_move_to_active(struc
 		if (obj->base.write_domain) {
 			obj->dirty = 1;
 			obj->last_write_seqno = intel_ring_get_seqno(ring);
-			/* check for potential scanout */
-			if (i915_gem_obj_ggtt_bound(obj) &&
-			    i915_gem_obj_to_ggtt(obj)->pin_count)
-				intel_mark_fb_busy(obj, ring);
+
+			intel_fb_obj_invalidate(obj, ring);
 
 			/* update for the implicit flush after a batch */
 			obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
@@ -1028,6 +1026,163 @@ i915_reset_gen7_sol_offsets(struct drm_d
 	return 0;
 }
 
+static int
+legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
+			     struct intel_engine_cs *ring,
+			     struct intel_context *ctx,
+			     struct drm_i915_gem_execbuffer2 *args,
+			     struct list_head *vmas,
+			     struct drm_i915_gem_object *batch_obj,
+			     u64 exec_start, u32 flags)
+{
+	struct drm_clip_rect *cliprects = NULL;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u64 exec_len;
+	int instp_mode;
+	u32 instp_mask;
+	int i, ret = 0;
+
+	if (args->num_cliprects != 0) {
+		if (ring != &dev_priv->ring[RCS]) {
+			DRM_DEBUG("clip rectangles are only valid with the render ring\n");
+			return -EINVAL;
+		}
+
+		if (INTEL_INFO(dev)->gen >= 5) {
+			DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
+			return -EINVAL;
+		}
+
+		if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+			DRM_DEBUG("execbuf with %u cliprects\n",
+				  args->num_cliprects);
+			return -EINVAL;
+		}
+
+		cliprects = kcalloc(args->num_cliprects,
+				    sizeof(*cliprects),
+				    GFP_KERNEL);
+		if (cliprects == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		if (copy_from_user(cliprects,
+				   to_user_ptr(args->cliprects_ptr),
+				   sizeof(*cliprects)*args->num_cliprects)) {
+			ret = -EFAULT;
+			goto error;
+		}
+	} else {
+		if (args->DR4 == 0xffffffff) {
+			DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
+			args->DR4 = 0;
+		}
+
+		if (args->DR1 || args->DR4 || args->cliprects_ptr) {
+			DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
+			return -EINVAL;
+		}
+	}
+
+	ret = i915_gem_execbuffer_move_to_gpu(ring, vmas);
+	if (ret)
+		goto error;
+
+	ret = i915_switch_context(ring, ctx);
+	if (ret)
+		goto error;
+
+	instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+	instp_mask = I915_EXEC_CONSTANTS_MASK;
+	switch (instp_mode) {
+	case I915_EXEC_CONSTANTS_REL_GENERAL:
+	case I915_EXEC_CONSTANTS_ABSOLUTE:
+	case I915_EXEC_CONSTANTS_REL_SURFACE:
+		if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+			DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
+			ret = -EINVAL;
+			goto error;
+		}
+
+		if (instp_mode != dev_priv->relative_constants_mode) {
+			if (INTEL_INFO(dev)->gen < 4) {
+				DRM_DEBUG("no rel constants on pre-gen4\n");
+				ret = -EINVAL;
+				goto error;
+			}
+
+			if (INTEL_INFO(dev)->gen > 5 &&
+			    instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
+				DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
+				ret = -EINVAL;
+				goto error;
+			}
+
+			/* The HW changed the meaning on this bit on gen6 */
+			if (INTEL_INFO(dev)->gen >= 6)
+				instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
+		}
+		break;
+	default:
+		DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (ring == &dev_priv->ring[RCS] &&
+			instp_mode != dev_priv->relative_constants_mode) {
+		ret = intel_ring_begin(ring, 4);
+		if (ret)
+			goto error;
+
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit(ring, INSTPM);
+		intel_ring_emit(ring, instp_mask << 16 | instp_mode);
+		intel_ring_advance(ring);
+
+		dev_priv->relative_constants_mode = instp_mode;
+	}
+
+	if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
+		ret = i915_reset_gen7_sol_offsets(dev, ring);
+		if (ret)
+			goto error;
+	}
+
+	exec_len = args->batch_len;
+	if (cliprects) {
+		for (i = 0; i < args->num_cliprects; i++) {
+			ret = i915_emit_box(dev, &cliprects[i],
+					    args->DR1, args->DR4);
+			if (ret)
+				goto error;
+
+			ret = ring->dispatch_execbuffer(ring,
+							exec_start, exec_len,
+							flags);
+			if (ret)
+				goto error;
+		}
+	} else {
+		ret = ring->dispatch_execbuffer(ring,
+						exec_start, exec_len,
+						flags);
+		if (ret)
+			return ret;
+	}
+
+	trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
+
+	i915_gem_execbuffer_move_to_active(vmas, ring);
+	i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
+
+error:
+	kfree(cliprects);
+	return ret;
+}
+
 /**
  * Find one BSD ring to dispatch the corresponding BSD command.
  * The Ring ID is returned.
@@ -1087,14 +1242,13 @@ i915_gem_do_execbuffer(struct drm_device
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct eb_vmas *eb;
 	struct drm_i915_gem_object *batch_obj;
-	struct drm_clip_rect *cliprects = NULL;
 	struct intel_engine_cs *ring;
 	struct intel_context *ctx;
 	struct i915_address_space *vm;
 	const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
-	u64 exec_start = args->batch_start_offset, exec_len;
-	u32 mask, flags;
-	int ret, mode, i;
+	u64 exec_start = args->batch_start_offset;
+	u32 flags;
+	int ret;
 	bool need_relocs;
 
 	if (!i915_gem_check_execbuffer(args))
@@ -1138,87 +1292,11 @@ i915_gem_do_execbuffer(struct drm_device
 		return -EINVAL;
 	}
 
-	mode = args->flags & I915_EXEC_CONSTANTS_MASK;
-	mask = I915_EXEC_CONSTANTS_MASK;
-	switch (mode) {
-	case I915_EXEC_CONSTANTS_REL_GENERAL:
-	case I915_EXEC_CONSTANTS_ABSOLUTE:
-	case I915_EXEC_CONSTANTS_REL_SURFACE:
-		if (mode != 0 && ring != &dev_priv->ring[RCS]) {
-			DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
-			return -EINVAL;
-		}
-
-		if (mode != dev_priv->relative_constants_mode) {
-			if (INTEL_INFO(dev)->gen < 4) {
-				DRM_DEBUG("no rel constants on pre-gen4\n");
-				return -EINVAL;
-			}
-
-			if (INTEL_INFO(dev)->gen > 5 &&
-			    mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
-				DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
-				return -EINVAL;
-			}
-
-			/* The HW changed the meaning on this bit on gen6 */
-			if (INTEL_INFO(dev)->gen >= 6)
-				mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
-		}
-		break;
-	default:
-		DRM_DEBUG("execbuf with unknown constants: %d\n", mode);
-		return -EINVAL;
-	}
-
 	if (args->buffer_count < 1) {
 		DRM_DEBUG("execbuf with %d buffers\n", args->buffer_count);
 		return -EINVAL;
 	}
 
-	if (args->num_cliprects != 0) {
-		if (ring != &dev_priv->ring[RCS]) {
-			DRM_DEBUG("clip rectangles are only valid with the render ring\n");
-			return -EINVAL;
-		}
-
-		if (INTEL_INFO(dev)->gen >= 5) {
-			DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
-			return -EINVAL;
-		}
-
-		if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
-			DRM_DEBUG("execbuf with %u cliprects\n",
-				  args->num_cliprects);
-			return -EINVAL;
-		}
-
-		cliprects = kcalloc(args->num_cliprects,
-				    sizeof(*cliprects),
-				    GFP_KERNEL);
-		if (cliprects == NULL) {
-			ret = -ENOMEM;
-			goto pre_mutex_err;
-		}
-
-		if (copy_from_user(cliprects,
-				   to_user_ptr(args->cliprects_ptr),
-				   sizeof(*cliprects)*args->num_cliprects)) {
-			ret = -EFAULT;
-			goto pre_mutex_err;
-		}
-	} else {
-		if (args->DR4 == 0xffffffff) {
-			DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
-			args->DR4 = 0;
-		}
-
-		if (args->DR1 || args->DR4 || args->cliprects_ptr) {
-			DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
-			return -EINVAL;
-		}
-	}
-
 	intel_runtime_pm_get(dev_priv);
 
 	ret = i915_mutex_lock_interruptible(dev);
@@ -1322,63 +1400,11 @@ i915_gem_do_execbuffer(struct drm_device
 	else
 		exec_start += i915_gem_obj_offset(batch_obj, vm);
 
-	ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas);
-	if (ret)
-		goto err;
-
-	ret = i915_switch_context(ring, ctx);
+	ret = legacy_ringbuffer_submission(dev, file, ring, ctx,
+			args, &eb->vmas, batch_obj, exec_start, flags);
 	if (ret)
 		goto err;
 
-	if (ring == &dev_priv->ring[RCS] &&
-	    mode != dev_priv->relative_constants_mode) {
-		ret = intel_ring_begin(ring, 4);
-		if (ret)
-				goto err;
-
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-		intel_ring_emit(ring, INSTPM);
-		intel_ring_emit(ring, mask << 16 | mode);
-		intel_ring_advance(ring);
-
-		dev_priv->relative_constants_mode = mode;
-	}
-
-	if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
-		ret = i915_reset_gen7_sol_offsets(dev, ring);
-		if (ret)
-			goto err;
-	}
-
-
-	exec_len = args->batch_len;
-	if (cliprects) {
-		for (i = 0; i < args->num_cliprects; i++) {
-			ret = i915_emit_box(dev, &cliprects[i],
-					    args->DR1, args->DR4);
-			if (ret)
-				goto err;
-
-			ret = ring->dispatch_execbuffer(ring,
-							exec_start, exec_len,
-							flags);
-			if (ret)
-				goto err;
-		}
-	} else {
-		ret = ring->dispatch_execbuffer(ring,
-						exec_start, exec_len,
-						flags);
-		if (ret)
-			goto err;
-	}
-
-	trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
-
-	i915_gem_execbuffer_move_to_active(&eb->vmas, ring);
-	i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
-
 err:
 	/* the request owns the ref now */
 	i915_gem_context_unreference(ctx);
@@ -1387,8 +1413,6 @@ err:
 	mutex_unlock(&dev->struct_mutex);
 
 pre_mutex_err:
-	kfree(cliprects);
-
 	/* intel_gpu_busy should also get a ref, so it will free when the device
 	 * is really idle. */
 	intel_runtime_pm_put(dev_priv);
@@ -1525,7 +1549,7 @@ i915_gem_execbuffer2(struct drm_device *
 	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
-		struct drm_i915_gem_exec_object2 *user_exec_list =
+		struct drm_i915_gem_exec_object2 __user *user_exec_list =
 				   to_user_ptr(args->buffers_ptr);
 		int i;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,13 @@ static int sanitize_enable_ppgtt(struct
 	}
 #endif
 
+	/* Early VLV doesn't have this */
+	if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+	    dev->pdev->revision < 0xb) {
+		DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
+		return 0;
+	}
+
 	return HAS_ALIASING_PPGTT(dev) ? 1 : 0;
 }
 
@@ -110,7 +117,7 @@ static inline gen8_ppgtt_pde_t gen8_pde_
 
 static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level,
-				     bool valid)
+				     bool valid, u32 unused)
 {
 	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -132,7 +139,7 @@ static gen6_gtt_pte_t snb_pte_encode(dma
 
 static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level,
-				     bool valid)
+				     bool valid, u32 unused)
 {
 	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -156,7 +163,7 @@ static gen6_gtt_pte_t ivb_pte_encode(dma
 
 static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level,
-				     bool valid)
+				     bool valid, u32 flags)
 {
 	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -164,7 +171,8 @@ static gen6_gtt_pte_t byt_pte_encode(dma
 	/* Mark the page as writeable.  Other platforms don't have a
 	 * setting for read-only/writable, so this matches that behavior.
 	 */
-	pte |= BYT_PTE_WRITEABLE;
+	if (!(flags & PTE_READ_ONLY))
+		pte |= BYT_PTE_WRITEABLE;
 
 	if (level != I915_CACHE_NONE)
 		pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
@@ -174,7 +182,7 @@ static gen6_gtt_pte_t byt_pte_encode(dma
 
 static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level,
-				     bool valid)
+				     bool valid, u32 unused)
 {
 	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
@@ -187,7 +195,7 @@ static gen6_gtt_pte_t hsw_pte_encode(dma
 
 static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
 				      enum i915_cache_level level,
-				      bool valid)
+				      bool valid, u32 unused)
 {
 	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
@@ -301,7 +309,7 @@ static void gen8_ppgtt_clear_range(struc
 static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
 				      struct sg_table *pages,
 				      uint64_t start,
-				      enum i915_cache_level cache_level)
+				      enum i915_cache_level cache_level, u32 unused)
 {
 	struct i915_hw_ppgtt *ppgtt =
 		container_of(vm, struct i915_hw_ppgtt, base);
@@ -639,7 +647,7 @@ static void gen6_dump_ppgtt(struct i915_
 	uint32_t pd_entry;
 	int pte, pde;
 
-	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
 
 	pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm +
 		ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
@@ -941,7 +949,7 @@ static void gen6_ppgtt_clear_range(struc
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
-	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -964,7 +972,7 @@ static void gen6_ppgtt_clear_range(struc
 static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 				      struct sg_table *pages,
 				      uint64_t start,
-				      enum i915_cache_level cache_level)
+				      enum i915_cache_level cache_level, u32 flags)
 {
 	struct i915_hw_ppgtt *ppgtt =
 		container_of(vm, struct i915_hw_ppgtt, base);
@@ -981,7 +989,8 @@ static void gen6_ppgtt_insert_entries(st
 
 		pt_vaddr[act_pte] =
 			vm->pte_encode(sg_page_iter_dma_address(&sg_iter),
-				       cache_level, true);
+				       cache_level, true, flags);
+
 		if (++act_pte == I915_PPGTT_PT_ENTRIES) {
 			kunmap_atomic(pt_vaddr);
 			pt_vaddr = NULL;
@@ -1218,8 +1227,12 @@ ppgtt_bind_vma(struct i915_vma *vma,
 	       enum i915_cache_level cache_level,
 	       u32 flags)
 {
+	/* Currently applicable only to VLV */
+	if (vma->obj->gt_ro)
+		flags |= PTE_READ_ONLY;
+
 	vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start,
-				cache_level);
+				cache_level, flags);
 }
 
 static void ppgtt_unbind_vma(struct i915_vma *vma)
@@ -1394,7 +1407,7 @@ static inline void gen8_set_pte(void __i
 static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     uint64_t start,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level, u32 unused)
 {
 	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	unsigned first_entry = start >> PAGE_SHIFT;
@@ -1402,7 +1415,7 @@ static void gen8_ggtt_insert_entries(str
 		(gen8_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
 	int i = 0;
 	struct sg_page_iter sg_iter;
-	dma_addr_t addr = 0;
+	dma_addr_t addr = 0; /* shut up gcc */
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_dma_address(sg_iter.sg) +
@@ -1440,7 +1453,7 @@ static void gen8_ggtt_insert_entries(str
 static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     uint64_t start,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level, u32 flags)
 {
 	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	unsigned first_entry = start >> PAGE_SHIFT;
@@ -1448,11 +1461,11 @@ static void gen6_ggtt_insert_entries(str
 		(gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
 	int i = 0;
 	struct sg_page_iter sg_iter;
-	dma_addr_t addr;
+	dma_addr_t addr = 0;
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_page_iter_dma_address(&sg_iter);
-		iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
+		iowrite32(vm->pte_encode(addr, level, true, flags), &gtt_entries[i]);
 		i++;
 	}
 
@@ -1462,9 +1475,10 @@ static void gen6_ggtt_insert_entries(str
 	 * of NUMA access patterns. Therefore, even with the way we assume
 	 * hardware should work, we must keep this posting read for paranoia.
 	 */
-	if (i != 0)
-		WARN_ON(readl(&gtt_entries[i-1]) !=
-			vm->pte_encode(addr, level, true));
+	if (i != 0) {
+		unsigned long gtt = readl(&gtt_entries[i-1]);
+		WARN_ON(gtt != vm->pte_encode(addr, level, true, flags));
+	}
 
 	/* This next bit makes the above posting read even more important. We
 	 * want to flush the TLBs only after we're certain all the PTE updates
@@ -1518,7 +1532,7 @@ static void gen6_ggtt_clear_range(struct
 		 first_entry, num_entries, max_entries))
 		num_entries = max_entries;
 
-	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch, 0);
 
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
@@ -1567,6 +1581,10 @@ static void ggtt_bind_vma(struct i915_vm
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj = vma->obj;
 
+	/* Currently applicable only to VLV */
+	if (obj->gt_ro)
+		flags |= PTE_READ_ONLY;
+
 	/* If there is no aliasing PPGTT, or the caller needs a global mapping,
 	 * or we have a global mapping already but the cacheability flags have
 	 * changed, set the global PTEs.
@@ -1583,7 +1601,7 @@ static void ggtt_bind_vma(struct i915_vm
 		    (cache_level != obj->cache_level)) {
 			vma->vm->insert_entries(vma->vm, obj->pages,
 						vma->node.start,
-						cache_level);
+						cache_level, flags);
 			obj->has_global_gtt_mapping = 1;
 		}
 	}
@@ -1595,7 +1613,7 @@ static void ggtt_bind_vma(struct i915_vm
 		appgtt->base.insert_entries(&appgtt->base,
 					    vma->obj->pages,
 					    vma->node.start,
-					    cache_level);
+					    cache_level, flags);
 		vma->obj->has_aliasing_ppgtt_mapping = 1;
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2014-09-28 17:29:07.000000000 -0400
@@ -154,6 +154,7 @@ struct i915_vma {
 	void (*unbind_vma)(struct i915_vma *vma);
 	/* Map an object into an address space with the given cache flags. */
 #define GLOBAL_BIND (1<<0)
+#define PTE_READ_ONLY (1<<1)
 	void (*bind_vma)(struct i915_vma *vma,
 			 enum i915_cache_level cache_level,
 			 u32 flags);
@@ -197,7 +198,7 @@ struct i915_address_space {
 	/* FIXME: Need a more generic return type */
 	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
 				     enum i915_cache_level level,
-				     bool valid); /* Create a valid PTE */
+				     bool valid, u32 flags); /* Create a valid PTE */
 	void (*clear_range)(struct i915_address_space *vm,
 			    uint64_t start,
 			    uint64_t length,
@@ -205,7 +206,7 @@ struct i915_address_space {
 	void (*insert_entries)(struct i915_address_space *vm,
 			       struct sg_table *st,
 			       uint64_t start,
-			       enum i915_cache_level cache_level);
+			       enum i915_cache_level cache_level, u32 flags);
 	void (*cleanup)(struct i915_address_space *vm);
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,64 +28,13 @@
 #include "i915_drv.h"
 #include "intel_renderstate.h"
 
-struct i915_render_state {
+struct render_state {
+	const struct intel_renderstate_rodata *rodata;
 	struct drm_i915_gem_object *obj;
-	unsigned long ggtt_offset;
-	u32 *batch;
-	u32 size;
-	u32 len;
+	u64 ggtt_offset;
+	int gen;
 };
 
-static struct i915_render_state *render_state_alloc(struct drm_device *dev)
-{
-	struct i915_render_state *so;
-	struct page *page;
-	int ret;
-
-	so = kzalloc(sizeof(*so), GFP_KERNEL);
-	if (!so)
-		return ERR_PTR(-ENOMEM);
-
-	so->obj = i915_gem_alloc_object(dev, 4096);
-	if (so->obj == NULL) {
-		ret = -ENOMEM;
-		goto free;
-	}
-	so->size = 4096;
-
-	ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
-	if (ret)
-		goto free_gem;
-
-	BUG_ON(so->obj->pages->nents != 1);
-	page = sg_page(so->obj->pages->sgl);
-
-	so->batch = kmap(page);
-	if (!so->batch) {
-		ret = -ENOMEM;
-		goto unpin;
-	}
-
-	so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
-
-	return so;
-unpin:
-	i915_gem_object_ggtt_unpin(so->obj);
-free_gem:
-	drm_gem_object_unreference(&so->obj->base);
-free:
-	kfree(so);
-	return ERR_PTR(ret);
-}
-
-static void render_state_free(struct i915_render_state *so)
-{
-	kunmap(kmap_to_page(so->batch));
-	i915_gem_object_ggtt_unpin(so->obj);
-	drm_gem_object_unreference(&so->obj->base);
-	kfree(so);
-}
-
 static const struct intel_renderstate_rodata *
 render_state_get_rodata(struct drm_device *dev, const int gen)
 {
@@ -101,98 +50,120 @@ render_state_get_rodata(struct drm_devic
 	return NULL;
 }
 
-static int render_state_setup(const int gen,
-			      const struct intel_renderstate_rodata *rodata,
-			      struct i915_render_state *so)
+static int render_state_init(struct render_state *so, struct drm_device *dev)
 {
-	const u64 goffset = i915_gem_obj_ggtt_offset(so->obj);
-	u32 reloc_index = 0;
-	u32 * const d = so->batch;
-	unsigned int i = 0;
 	int ret;
 
-	if (!rodata || rodata->batch_items * 4 > so->size)
+	so->gen = INTEL_INFO(dev)->gen;
+	so->rodata = render_state_get_rodata(dev, so->gen);
+	if (so->rodata == NULL)
+		return 0;
+
+	if (so->rodata->batch_items * 4 > 4096)
 		return -EINVAL;
 
+	so->obj = i915_gem_alloc_object(dev, 4096);
+	if (so->obj == NULL)
+		return -ENOMEM;
+
+	ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
+	if (ret)
+		goto free_gem;
+
+	so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
+	return 0;
+
+free_gem:
+	drm_gem_object_unreference(&so->obj->base);
+	return ret;
+}
+
+static int render_state_setup(struct render_state *so)
+{
+	const struct intel_renderstate_rodata *rodata = so->rodata;
+	unsigned int i = 0, reloc_index = 0;
+	struct page *page;
+	u32 *d;
+	int ret;
+
 	ret = i915_gem_object_set_to_cpu_domain(so->obj, true);
 	if (ret)
 		return ret;
 
+	page = sg_page(so->obj->pages->sgl);
+	d = kmap(page);
+
 	while (i < rodata->batch_items) {
 		u32 s = rodata->batch[i];
 
-		if (reloc_index < rodata->reloc_items &&
-		    i * 4  == rodata->reloc[reloc_index]) {
-
-			s += goffset & 0xffffffff;
-
-			/* We keep batch offsets max 32bit */
-			if (gen >= 8) {
+		if (i * 4  == rodata->reloc[reloc_index]) {
+			u64 r = s + so->ggtt_offset;
+			s = lower_32_bits(r);
+			if (so->gen >= 8) {
 				if (i + 1 >= rodata->batch_items ||
 				    rodata->batch[i + 1] != 0)
 					return -EINVAL;
 
-				d[i] = s;
-				i++;
-				s = (goffset & 0xffffffff00000000ull) >> 32;
+				d[i++] = s;
+				s = upper_32_bits(r);
 			}
 
 			reloc_index++;
 		}
 
-		d[i] = s;
-		i++;
+		d[i++] = s;
 	}
+	kunmap(page);
 
 	ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
 	if (ret)
 		return ret;
 
-	if (rodata->reloc_items != reloc_index) {
-		DRM_ERROR("not all relocs resolved, %d out of %d\n",
-			  reloc_index, rodata->reloc_items);
+	if (rodata->reloc[reloc_index] != -1) {
+		DRM_ERROR("only %d relocs resolved\n", reloc_index);
 		return -EINVAL;
 	}
 
-	so->len = rodata->batch_items * 4;
-
 	return 0;
 }
 
+static void render_state_fini(struct render_state *so)
+{
+	i915_gem_object_ggtt_unpin(so->obj);
+	drm_gem_object_unreference(&so->obj->base);
+}
+
 int i915_gem_render_state_init(struct intel_engine_cs *ring)
 {
-	const int gen = INTEL_INFO(ring->dev)->gen;
-	struct i915_render_state *so;
-	const struct intel_renderstate_rodata *rodata;
+	struct render_state so;
 	int ret;
 
 	if (WARN_ON(ring->id != RCS))
 		return -ENOENT;
 
-	rodata = render_state_get_rodata(ring->dev, gen);
-	if (rodata == NULL)
-		return 0;
+	ret = render_state_init(&so, ring->dev);
+	if (ret)
+		return ret;
 
-	so = render_state_alloc(ring->dev);
-	if (IS_ERR(so))
-		return PTR_ERR(so);
+	if (so.rodata == NULL)
+		return 0;
 
-	ret = render_state_setup(gen, rodata, so);
+	ret = render_state_setup(&so);
 	if (ret)
 		goto out;
 
 	ret = ring->dispatch_execbuffer(ring,
-					i915_gem_obj_ggtt_offset(so->obj),
-					so->len,
+					so.ggtt_offset,
+					so.rodata->batch_items * 4,
 					I915_DISPATCH_SECURE);
 	if (ret)
 		goto out;
 
-	i915_vma_move_to_active(i915_gem_obj_to_ggtt(so->obj), ring);
+	i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
 
-	ret = __i915_add_request(ring, NULL, so->obj, NULL);
+	ret = __i915_add_request(ring, NULL, so.obj, NULL);
 	/* __i915_add_request moves object to inactive if it fails */
 out:
-	render_state_free(so);
+	render_state_fini(&so);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2014-09-28 17:29:07.000000000 -0400
@@ -147,30 +147,68 @@ static unsigned long i915_stolen_to_phys
 	return base;
 }
 
-static int i915_setup_compression(struct drm_device *dev, int size)
+static int find_compression_threshold(struct drm_device *dev,
+				      struct drm_mm_node *node,
+				      int size,
+				      int fb_cpp)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
+	int compression_threshold = 1;
 	int ret;
 
-	compressed_fb = kzalloc(sizeof(*compressed_fb), GFP_KERNEL);
-	if (!compressed_fb)
-		goto err_llb;
+	/* HACK: This code depends on what we will do in *_enable_fbc. If that
+	 * code changes, this code needs to change as well.
+	 *
+	 * The enable_fbc code will attempt to use one of our 2 compression
+	 * thresholds, therefore, in that case, we only have 1 resort.
+	 */
 
-	/* Try to over-allocate to reduce reallocations and fragmentation */
-	ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
+	/* Try to over-allocate to reduce reallocations and fragmentation. */
+	ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
 				 size <<= 1, 4096, DRM_MM_SEARCH_DEFAULT);
-	if (ret)
-		ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
-					 size >>= 1, 4096,
-					 DRM_MM_SEARCH_DEFAULT);
-	if (ret)
+	if (ret == 0)
+		return compression_threshold;
+
+again:
+	/* HW's ability to limit the CFB is 1:4 */
+	if (compression_threshold > 4 ||
+	    (fb_cpp == 2 && compression_threshold == 2))
+		return 0;
+
+	ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
+				 size >>= 1, 4096,
+				 DRM_MM_SEARCH_DEFAULT);
+	if (ret && INTEL_INFO(dev)->gen <= 4) {
+		return 0;
+	} else if (ret) {
+		compression_threshold <<= 1;
+		goto again;
+	} else {
+		return compression_threshold;
+	}
+}
+
+static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_mm_node *uninitialized_var(compressed_llb);
+	int ret;
+
+	ret = find_compression_threshold(dev, &dev_priv->fbc.compressed_fb,
+					 size, fb_cpp);
+	if (!ret)
 		goto err_llb;
+	else if (ret > 1) {
+		DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
+
+	}
+
+	dev_priv->fbc.threshold = ret;
 
 	if (HAS_PCH_SPLIT(dev))
-		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
+		I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
 	else if (IS_GM45(dev)) {
-		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
+		I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
 	} else {
 		compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
 		if (!compressed_llb)
@@ -184,13 +222,12 @@ static int i915_setup_compression(struct
 		dev_priv->fbc.compressed_llb = compressed_llb;
 
 		I915_WRITE(FBC_CFB_BASE,
-			   dev_priv->mm.stolen_base + compressed_fb->start);
+			   dev_priv->mm.stolen_base + dev_priv->fbc.compressed_fb.start);
 		I915_WRITE(FBC_LL_BASE,
 			   dev_priv->mm.stolen_base + compressed_llb->start);
 	}
 
-	dev_priv->fbc.compressed_fb = compressed_fb;
-	dev_priv->fbc.size = size;
+	dev_priv->fbc.size = size / dev_priv->fbc.threshold;
 
 	DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
 		      size);
@@ -199,14 +236,13 @@ static int i915_setup_compression(struct
 
 err_fb:
 	kfree(compressed_llb);
-	drm_mm_remove_node(compressed_fb);
+	drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
 err_llb:
-	kfree(compressed_fb);
 	pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
 	return -ENOSPC;
 }
 
-int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
+int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -219,7 +255,7 @@ int i915_gem_stolen_setup_compression(st
 	/* Release any current block */
 	i915_gem_stolen_cleanup_compression(dev);
 
-	return i915_setup_compression(dev, size);
+	return i915_setup_compression(dev, size, fb_cpp);
 }
 
 void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
@@ -229,10 +265,7 @@ void i915_gem_stolen_cleanup_compression
 	if (dev_priv->fbc.size == 0)
 		return;
 
-	if (dev_priv->fbc.compressed_fb) {
-		drm_mm_remove_node(dev_priv->fbc.compressed_fb);
-		kfree(dev_priv->fbc.compressed_fb);
-	}
+	drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
 
 	if (dev_priv->fbc.compressed_llb) {
 		drm_mm_remove_node(dev_priv->fbc.compressed_llb);
@@ -336,9 +369,20 @@ static void i915_gem_object_put_pages_st
 	kfree(obj->pages);
 }
 
+
+static void
+i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
+{
+	if (obj->stolen) {
+		drm_mm_remove_node(obj->stolen);
+		kfree(obj->stolen);
+		obj->stolen = NULL;
+	}
+}
 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,
+	.release = i915_gem_object_release_stolen,
 };
 
 static struct drm_i915_gem_object *
@@ -496,13 +540,3 @@ err_out:
 	drm_gem_object_unreference(&obj->base);
 	return NULL;
 }
-
-void
-i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
-{
-	if (obj->stolen) {
-		drm_mm_remove_node(obj->stolen);
-		kfree(obj->stolen);
-		obj->stolen = NULL;
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,15 @@
 #include <linux/mempolicy.h>
 #include <linux/swap.h>
 
+struct i915_mm_struct {
+	struct mm_struct *mm;
+	struct drm_device *dev;
+	struct i915_mmu_notifier *mn;
+	struct hlist_node node;
+	struct kref kref;
+	struct work_struct work;
+};
+
 #if defined(CONFIG_MMU_NOTIFIER)
 #include <linux/interval_tree.h>
 
@@ -40,19 +49,83 @@ struct i915_mmu_notifier {
 	struct hlist_node node;
 	struct mmu_notifier mn;
 	struct rb_root objects;
-	struct drm_device *dev;
-	struct mm_struct *mm;
-	struct work_struct work;
-	unsigned long count;
+	struct list_head linear;
 	unsigned long serial;
+	bool has_linear;
 };
 
 struct i915_mmu_object {
-	struct i915_mmu_notifier *mmu;
+	struct i915_mmu_notifier *mn;
 	struct interval_tree_node it;
+	struct list_head link;
 	struct drm_i915_gem_object *obj;
+	bool is_linear;
 };
 
+static unsigned long cancel_userptr(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	unsigned long end;
+
+	mutex_lock(&dev->struct_mutex);
+	/* Cancel any active worker and force us to re-evaluate gup */
+	obj->userptr.work = NULL;
+
+	if (obj->pages != NULL) {
+		struct drm_i915_private *dev_priv = to_i915(dev);
+		struct i915_vma *vma, *tmp;
+		bool was_interruptible;
+
+		was_interruptible = dev_priv->mm.interruptible;
+		dev_priv->mm.interruptible = false;
+
+		list_for_each_entry_safe(vma, tmp, &obj->vma_list, vma_link) {
+			int ret = i915_vma_unbind(vma);
+			WARN_ON(ret && ret != -EIO);
+		}
+		WARN_ON(i915_gem_object_put_pages(obj));
+
+		dev_priv->mm.interruptible = was_interruptible;
+	}
+
+	end = obj->userptr.ptr + obj->base.size;
+
+	drm_gem_object_unreference(&obj->base);
+	mutex_unlock(&dev->struct_mutex);
+
+	return end;
+}
+
+static void *invalidate_range__linear(struct i915_mmu_notifier *mn,
+				      struct mm_struct *mm,
+				      unsigned long start,
+				      unsigned long end)
+{
+	struct i915_mmu_object *mo;
+	unsigned long serial;
+
+restart:
+	serial = mn->serial;
+	list_for_each_entry(mo, &mn->linear, link) {
+		struct drm_i915_gem_object *obj;
+
+		if (mo->it.last < start || mo->it.start > end)
+			continue;
+
+		obj = mo->obj;
+		drm_gem_object_reference(&obj->base);
+		spin_unlock(&mn->lock);
+
+		cancel_userptr(obj);
+
+		spin_lock(&mn->lock);
+		if (serial != mn->serial)
+			goto restart;
+	}
+
+	return NULL;
+}
+
 static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
 						       struct mm_struct *mm,
 						       unsigned long start,
@@ -60,16 +133,18 @@ static void i915_gem_userptr_mn_invalida
 {
 	struct i915_mmu_notifier *mn = container_of(_mn, struct i915_mmu_notifier, mn);
 	struct interval_tree_node *it = NULL;
+	unsigned long next = start;
 	unsigned long serial = 0;
 
 	end--; /* interval ranges are inclusive, but invalidate range is exclusive */
-	while (start < end) {
-		struct drm_i915_gem_object *obj;
+	while (next < end) {
+		struct drm_i915_gem_object *obj = NULL;
 
-		obj = NULL;
 		spin_lock(&mn->lock);
-		if (serial == mn->serial)
-			it = interval_tree_iter_next(it, start, end);
+		if (mn->has_linear)
+			it = invalidate_range__linear(mn, mm, start, end);
+		else if (serial == mn->serial)
+			it = interval_tree_iter_next(it, next, end);
 		else
 			it = interval_tree_iter_first(&mn->objects, start, end);
 		if (it != NULL) {
@@ -81,31 +156,7 @@ static void i915_gem_userptr_mn_invalida
 		if (obj == NULL)
 			return;
 
-		mutex_lock(&mn->dev->struct_mutex);
-		/* Cancel any active worker and force us to re-evaluate gup */
-		obj->userptr.work = NULL;
-
-		if (obj->pages != NULL) {
-			struct drm_i915_private *dev_priv = to_i915(mn->dev);
-			struct i915_vma *vma, *tmp;
-			bool was_interruptible;
-
-			was_interruptible = dev_priv->mm.interruptible;
-			dev_priv->mm.interruptible = false;
-
-			list_for_each_entry_safe(vma, tmp, &obj->vma_list, vma_link) {
-				int ret = i915_vma_unbind(vma);
-				WARN_ON(ret && ret != -EIO);
-			}
-			WARN_ON(i915_gem_object_put_pages(obj));
-
-			dev_priv->mm.interruptible = was_interruptible;
-		}
-
-		start = obj->userptr.ptr + obj->base.size;
-
-		drm_gem_object_unreference(&obj->base);
-		mutex_unlock(&mn->dev->struct_mutex);
+		next = cancel_userptr(obj);
 	}
 }
 
@@ -114,113 +165,47 @@ static const struct mmu_notifier_ops i91
 };
 
 static struct i915_mmu_notifier *
-__i915_mmu_notifier_lookup(struct drm_device *dev, struct mm_struct *mm)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_mmu_notifier *mmu;
-
-	/* Protected by dev->struct_mutex */
-	hash_for_each_possible(dev_priv->mmu_notifiers, mmu, node, (unsigned long)mm)
-		if (mmu->mm == mm)
-			return mmu;
-
-	return NULL;
-}
-
-static struct i915_mmu_notifier *
-i915_mmu_notifier_get(struct drm_device *dev, struct mm_struct *mm)
+i915_mmu_notifier_create(struct mm_struct *mm)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_mmu_notifier *mmu;
+	struct i915_mmu_notifier *mn;
 	int ret;
 
-	lockdep_assert_held(&dev->struct_mutex);
-
-	mmu = __i915_mmu_notifier_lookup(dev, mm);
-	if (mmu)
-		return mmu;
-
-	mmu = kmalloc(sizeof(*mmu), GFP_KERNEL);
-	if (mmu == NULL)
+	mn = kmalloc(sizeof(*mn), GFP_KERNEL);
+	if (mn == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	spin_lock_init(&mmu->lock);
-	mmu->dev = dev;
-	mmu->mn.ops = &i915_gem_userptr_notifier;
-	mmu->mm = mm;
-	mmu->objects = RB_ROOT;
-	mmu->count = 0;
-	mmu->serial = 0;
+	spin_lock_init(&mn->lock);
+	mn->mn.ops = &i915_gem_userptr_notifier;
+	mn->objects = RB_ROOT;
+	mn->serial = 1;
+	INIT_LIST_HEAD(&mn->linear);
+	mn->has_linear = false;
 
-	/* Protected by mmap_sem (write-lock) */
-	ret = __mmu_notifier_register(&mmu->mn, mm);
+	 /* Protected by mmap_sem (write-lock) */
+	ret = __mmu_notifier_register(&mn->mn, mm);
 	if (ret) {
-		kfree(mmu);
+		kfree(mn);
 		return ERR_PTR(ret);
 	}
 
-	/* Protected by dev->struct_mutex */
-	hash_add(dev_priv->mmu_notifiers, &mmu->node, (unsigned long)mm);
-	return mmu;
-}
-
-static void
-__i915_mmu_notifier_destroy_worker(struct work_struct *work)
-{
-	struct i915_mmu_notifier *mmu = container_of(work, typeof(*mmu), work);
-	mmu_notifier_unregister(&mmu->mn, mmu->mm);
-	kfree(mmu);
-}
-
-static void
-__i915_mmu_notifier_destroy(struct i915_mmu_notifier *mmu)
-{
-	lockdep_assert_held(&mmu->dev->struct_mutex);
-
-	/* Protected by dev->struct_mutex */
-	hash_del(&mmu->node);
-
-	/* Our lock ordering is: mmap_sem, mmu_notifier_scru, struct_mutex.
-	 * We enter the function holding struct_mutex, therefore we need
-	 * to drop our mutex prior to calling mmu_notifier_unregister in
-	 * order to prevent lock inversion (and system-wide deadlock)
-	 * between the mmap_sem and struct-mutex. Hence we defer the
-	 * unregistration to a workqueue where we hold no locks.
-	 */
-	INIT_WORK(&mmu->work, __i915_mmu_notifier_destroy_worker);
-	schedule_work(&mmu->work);
-}
-
-static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mmu)
-{
-	if (++mmu->serial == 0)
-		mmu->serial = 1;
+	return mn;
 }
 
-static void
-i915_mmu_notifier_del(struct i915_mmu_notifier *mmu,
-		      struct i915_mmu_object *mn)
+static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mn)
 {
-	lockdep_assert_held(&mmu->dev->struct_mutex);
-
-	spin_lock(&mmu->lock);
-	interval_tree_remove(&mn->it, &mmu->objects);
-	__i915_mmu_notifier_update_serial(mmu);
-	spin_unlock(&mmu->lock);
-
-	/* Protected against _add() by dev->struct_mutex */
-	if (--mmu->count == 0)
-		__i915_mmu_notifier_destroy(mmu);
+	if (++mn->serial == 0)
+		mn->serial = 1;
 }
 
 static int
-i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
-		      struct i915_mmu_object *mn)
+i915_mmu_notifier_add(struct drm_device *dev,
+		      struct i915_mmu_notifier *mn,
+		      struct i915_mmu_object *mo)
 {
 	struct interval_tree_node *it;
 	int ret;
 
-	ret = i915_mutex_lock_interruptible(mmu->dev);
+	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
 
@@ -228,12 +213,11 @@ i915_mmu_notifier_add(struct i915_mmu_no
 	 * remove the objects from the interval tree) before we do
 	 * the check for overlapping objects.
 	 */
-	i915_gem_retire_requests(mmu->dev);
+	i915_gem_retire_requests(dev);
 
-	/* Disallow overlapping userptr objects */
-	spin_lock(&mmu->lock);
-	it = interval_tree_iter_first(&mmu->objects,
-				      mn->it.start, mn->it.last);
+	spin_lock(&mn->lock);
+	it = interval_tree_iter_first(&mn->objects,
+				      mo->it.start, mo->it.last);
 	if (it) {
 		struct drm_i915_gem_object *obj;
 
@@ -243,85 +227,129 @@ i915_mmu_notifier_add(struct i915_mmu_no
 		 * to flush their object references upon which the object will
 		 * be removed from the interval-tree, or the the range is
 		 * still in use by another client and the overlap is invalid.
+		 *
+		 * If we do have an overlap, we cannot use the interval tree
+		 * for fast range invalidation.
 		 */
 
 		obj = container_of(it, struct i915_mmu_object, it)->obj;
-		ret = obj->userptr.workers ? -EAGAIN : -EINVAL;
-	} else {
-		interval_tree_insert(&mn->it, &mmu->objects);
-		__i915_mmu_notifier_update_serial(mmu);
-		ret = 0;
+		if (!obj->userptr.workers)
+			mn->has_linear = mo->is_linear = true;
+		else
+			ret = -EAGAIN;
+	} else
+		interval_tree_insert(&mo->it, &mn->objects);
+
+	if (ret == 0) {
+		list_add(&mo->link, &mn->linear);
+		__i915_mmu_notifier_update_serial(mn);
 	}
-	spin_unlock(&mmu->lock);
-	mutex_unlock(&mmu->dev->struct_mutex);
+	spin_unlock(&mn->lock);
+	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
 }
 
+static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mn)
+{
+	struct i915_mmu_object *mo;
+
+	list_for_each_entry(mo, &mn->linear, link)
+		if (mo->is_linear)
+			return true;
+
+	return false;
+}
+
+static void
+i915_mmu_notifier_del(struct i915_mmu_notifier *mn,
+		      struct i915_mmu_object *mo)
+{
+	spin_lock(&mn->lock);
+	list_del(&mo->link);
+	if (mo->is_linear)
+		mn->has_linear = i915_mmu_notifier_has_linear(mn);
+	else
+		interval_tree_remove(&mo->it, &mn->objects);
+	__i915_mmu_notifier_update_serial(mn);
+	spin_unlock(&mn->lock);
+}
+
 static void
 i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj)
 {
-	struct i915_mmu_object *mn;
+	struct i915_mmu_object *mo;
 
-	mn = obj->userptr.mn;
-	if (mn == NULL)
+	mo = obj->userptr.mmu_object;
+	if (mo == NULL)
 		return;
 
-	i915_mmu_notifier_del(mn->mmu, mn);
-	obj->userptr.mn = NULL;
+	i915_mmu_notifier_del(mo->mn, mo);
+	kfree(mo);
+
+	obj->userptr.mmu_object = NULL;
+}
+
+static struct i915_mmu_notifier *
+i915_mmu_notifier_find(struct i915_mm_struct *mm)
+{
+	if (mm->mn == NULL) {
+		down_write(&mm->mm->mmap_sem);
+		mutex_lock(&to_i915(mm->dev)->mm_lock);
+		if (mm->mn == NULL)
+			mm->mn = i915_mmu_notifier_create(mm->mm);
+		mutex_unlock(&to_i915(mm->dev)->mm_lock);
+		up_write(&mm->mm->mmap_sem);
+	}
+	return mm->mn;
 }
 
 static int
 i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj,
 				    unsigned flags)
 {
-	struct i915_mmu_notifier *mmu;
-	struct i915_mmu_object *mn;
+	struct i915_mmu_notifier *mn;
+	struct i915_mmu_object *mo;
 	int ret;
 
 	if (flags & I915_USERPTR_UNSYNCHRONIZED)
 		return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
 
-	down_write(&obj->userptr.mm->mmap_sem);
-	ret = i915_mutex_lock_interruptible(obj->base.dev);
-	if (ret == 0) {
-		mmu = i915_mmu_notifier_get(obj->base.dev, obj->userptr.mm);
-		if (!IS_ERR(mmu))
-			mmu->count++; /* preemptive add to act as a refcount */
-		else
-			ret = PTR_ERR(mmu);
-		mutex_unlock(&obj->base.dev->struct_mutex);
-	}
-	up_write(&obj->userptr.mm->mmap_sem);
-	if (ret)
-		return ret;
+	if (WARN_ON(obj->userptr.mm == NULL))
+		return -EINVAL;
 
-	mn = kzalloc(sizeof(*mn), GFP_KERNEL);
-	if (mn == NULL) {
-		ret = -ENOMEM;
-		goto destroy_mmu;
-	}
+	mn = i915_mmu_notifier_find(obj->userptr.mm);
+	if (IS_ERR(mn))
+		return PTR_ERR(mn);
 
-	mn->mmu = mmu;
-	mn->it.start = obj->userptr.ptr;
-	mn->it.last = mn->it.start + obj->base.size - 1;
-	mn->obj = obj;
+	mo = kzalloc(sizeof(*mo), GFP_KERNEL);
+	if (mo == NULL)
+		return -ENOMEM;
 
-	ret = i915_mmu_notifier_add(mmu, mn);
-	if (ret)
-		goto free_mn;
+	mo->mn = mn;
+	mo->it.start = obj->userptr.ptr;
+	mo->it.last = mo->it.start + obj->base.size - 1;
+	mo->obj = obj;
 
-	obj->userptr.mn = mn;
+	ret = i915_mmu_notifier_add(obj->base.dev, mn, mo);
+	if (ret) {
+		kfree(mo);
+		return ret;
+	}
+
+	obj->userptr.mmu_object = mo;
 	return 0;
+}
 
-free_mn:
+static void
+i915_mmu_notifier_free(struct i915_mmu_notifier *mn,
+		       struct mm_struct *mm)
+{
+	if (mn == NULL)
+		return;
+
+	mmu_notifier_unregister(&mn->mn, mm);
 	kfree(mn);
-destroy_mmu:
-	mutex_lock(&obj->base.dev->struct_mutex);
-	if (--mmu->count == 0)
-		__i915_mmu_notifier_destroy(mmu);
-	mutex_unlock(&obj->base.dev->struct_mutex);
-	return ret;
 }
 
 #else
@@ -343,15 +371,114 @@ i915_gem_userptr_init__mmu_notifier(stru
 
 	return 0;
 }
+
+static void
+i915_mmu_notifier_free(struct i915_mmu_notifier *mn,
+		       struct mm_struct *mm)
+{
+}
+
 #endif
 
+static struct i915_mm_struct *
+__i915_mm_struct_find(struct drm_i915_private *dev_priv, struct mm_struct *real)
+{
+	struct i915_mm_struct *mm;
+
+	/* Protected by dev_priv->mm_lock */
+	hash_for_each_possible(dev_priv->mm_structs, mm, node, (unsigned long)real)
+		if (mm->mm == real)
+			return mm;
+
+	return NULL;
+}
+
+static int
+i915_gem_userptr_init__mm_struct(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct i915_mm_struct *mm;
+	int ret = 0;
+
+	/* During release of the GEM object we hold the struct_mutex. This
+	 * precludes us from calling mmput() at that time as that may be
+	 * the last reference and so call exit_mmap(). exit_mmap() will
+	 * attempt to reap the vma, and if we were holding a GTT mmap
+	 * would then call drm_gem_vm_close() and attempt to reacquire
+	 * the struct mutex. So in order to avoid that recursion, we have
+	 * to defer releasing the mm reference until after we drop the
+	 * struct_mutex, i.e. we need to schedule a worker to do the clean
+	 * up.
+	 */
+	mutex_lock(&dev_priv->mm_lock);
+	mm = __i915_mm_struct_find(dev_priv, current->mm);
+	if (mm == NULL) {
+		mm = kmalloc(sizeof(*mm), GFP_KERNEL);
+		if (mm == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		kref_init(&mm->kref);
+		mm->dev = obj->base.dev;
+
+		mm->mm = current->mm;
+		atomic_inc(&current->mm->mm_count);
+
+		mm->mn = NULL;
+
+		/* Protected by dev_priv->mm_lock */
+		hash_add(dev_priv->mm_structs,
+			 &mm->node, (unsigned long)mm->mm);
+	} else
+		kref_get(&mm->kref);
+
+	obj->userptr.mm = mm;
+out:
+	mutex_unlock(&dev_priv->mm_lock);
+	return ret;
+}
+
+static void
+__i915_mm_struct_free__worker(struct work_struct *work)
+{
+	struct i915_mm_struct *mm = container_of(work, typeof(*mm), work);
+	i915_mmu_notifier_free(mm->mn, mm->mm);
+	mmdrop(mm->mm);
+	kfree(mm);
+}
+
+static void
+__i915_mm_struct_free(struct kref *kref)
+{
+	struct i915_mm_struct *mm = container_of(kref, typeof(*mm), kref);
+
+	/* Protected by dev_priv->mm_lock */
+	hash_del(&mm->node);
+	mutex_unlock(&to_i915(mm->dev)->mm_lock);
+
+	INIT_WORK(&mm->work, __i915_mm_struct_free__worker);
+	schedule_work(&mm->work);
+}
+
+static void
+i915_gem_userptr_release__mm_struct(struct drm_i915_gem_object *obj)
+{
+	if (obj->userptr.mm == NULL)
+		return;
+
+	kref_put_mutex(&obj->userptr.mm->kref,
+		       __i915_mm_struct_free,
+		       &to_i915(obj->base.dev)->mm_lock);
+	obj->userptr.mm = NULL;
+}
+
 struct get_pages_work {
 	struct work_struct work;
 	struct drm_i915_gem_object *obj;
 	struct task_struct *task;
 };
 
-
 #if IS_ENABLED(CONFIG_SWIOTLB)
 #define swiotlb_active() swiotlb_nr_tbl()
 #else
@@ -409,7 +536,7 @@ __i915_gem_userptr_get_pages_worker(stru
 	if (pvec == NULL)
 		pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
 	if (pvec != NULL) {
-		struct mm_struct *mm = obj->userptr.mm;
+		struct mm_struct *mm = obj->userptr.mm->mm;
 
 		down_read(&mm->mmap_sem);
 		while (pinned < num_pages) {
@@ -475,7 +602,7 @@ i915_gem_userptr_get_pages(struct drm_i9
 
 	pvec = NULL;
 	pinned = 0;
-	if (obj->userptr.mm == current->mm) {
+	if (obj->userptr.mm->mm == current->mm) {
 		pvec = kmalloc(num_pages*sizeof(struct page *),
 			       GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
 		if (pvec == NULL) {
@@ -581,17 +708,13 @@ static void
 i915_gem_userptr_release(struct drm_i915_gem_object *obj)
 {
 	i915_gem_userptr_release__mmu_notifier(obj);
-
-	if (obj->userptr.mm) {
-		mmput(obj->userptr.mm);
-		obj->userptr.mm = NULL;
-	}
+	i915_gem_userptr_release__mm_struct(obj);
 }
 
 static int
 i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
 {
-	if (obj->userptr.mn)
+	if (obj->userptr.mmu_object)
 		return 0;
 
 	return i915_gem_userptr_init__mmu_notifier(obj, 0);
@@ -611,12 +734,11 @@ static const struct drm_i915_gem_object_
  * We impose several restrictions upon the memory being mapped
  * into the GPU.
  * 1. It must be page aligned (both start/end addresses, i.e ptr and size).
- * 2. It cannot overlap any other userptr object in the same address space.
- * 3. It must be normal system memory, not a pointer into another map of IO
+ * 2. It must be normal system memory, not a pointer into another map of IO
  *    space (e.g. it must not be a GTT mmapping of another object).
- * 4. We only allow a bo as large as we could in theory map into the GTT,
+ * 3. We only allow a bo as large as we could in theory map into the GTT,
  *    that is we limit the size to the total size of the GTT.
- * 5. The bo is marked as being snoopable. The backing pages are left
+ * 4. The bo is marked as being snoopable. The backing pages are left
  *    accessible directly by the CPU, but reads and writes by the GPU may
  *    incur the cost of a snoop (unless you have an LLC architecture).
  *
@@ -667,7 +789,6 @@ i915_gem_userptr_ioctl(struct drm_device
 		return -ENODEV;
 	}
 
-	/* Allocate the new object */
 	obj = i915_gem_object_alloc(dev);
 	if (obj == NULL)
 		return -ENOMEM;
@@ -685,8 +806,8 @@ i915_gem_userptr_ioctl(struct drm_device
 	 * at binding. This means that we need to hook into the mmu_notifier
 	 * in order to detect if the mmu is destroyed.
 	 */
-	ret = -ENOMEM;
-	if ((obj->userptr.mm = get_task_mm(current)))
+	ret = i915_gem_userptr_init__mm_struct(obj);
+	if (ret == 0)
 		ret = i915_gem_userptr_init__mmu_notifier(obj, args->flags);
 	if (ret == 0)
 		ret = drm_gem_handle_create(file, &obj->base, &handle);
@@ -703,9 +824,8 @@ i915_gem_userptr_ioctl(struct drm_device
 int
 i915_gem_init_userptr(struct drm_device *dev)
 {
-#if defined(CONFIG_MMU_NOTIFIER)
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	hash_init(dev_priv->mmu_notifiers);
-#endif
+	mutex_init(&dev_priv->mm_lock);
+	hash_init(dev_priv->mm_structs);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gpu_error.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gpu_error.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2014-09-28 17:29:07.000000000 -0400
@@ -229,6 +229,8 @@ static const char *hangcheck_action_to_s
 		return "wait";
 	case HANGCHECK_ACTIVE:
 		return "active";
+	case HANGCHECK_ACTIVE_LOOP:
+		return "active (loop)";
 	case HANGCHECK_KICK:
 		return "kick";
 	case HANGCHECK_HUNG:
@@ -327,6 +329,7 @@ int i915_error_state_to_str(struct drm_i
 	struct drm_device *dev = error_priv->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error = error_priv->error;
+	struct drm_i915_error_object *obj;
 	int i, j, offset, elt;
 	int max_hangcheck_score;
 
@@ -358,6 +361,12 @@ int i915_error_state_to_str(struct drm_i
 	err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
 	err_printf(m, "EIR: 0x%08x\n", error->eir);
 	err_printf(m, "IER: 0x%08x\n", error->ier);
+	if (INTEL_INFO(dev)->gen >= 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))
+		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);
 	err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
@@ -395,8 +404,6 @@ int i915_error_state_to_str(struct drm_i
 				    error->pinned_bo_count[0]);
 
 	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
-		struct drm_i915_error_object *obj;
-
 		obj = error->ring[i].batchbuffer;
 		if (obj) {
 			err_puts(m, dev_priv->ring[i].name);
@@ -459,6 +466,18 @@ int i915_error_state_to_str(struct drm_i
 		}
 	}
 
+	if ((obj = error->semaphore_obj)) {
+		err_printf(m, "Semaphore page = 0x%08x\n", 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]);
+		}
+	}
+
 	if (error->overlay)
 		intel_overlay_print_error_state(m, error->overlay);
 
@@ -529,6 +548,7 @@ static void i915_error_state_free(struct
 		kfree(error->ring[i].requests);
 	}
 
+	i915_error_object_free(error->semaphore_obj);
 	kfree(error->active_bo);
 	kfree(error->overlay);
 	kfree(error->display);
@@ -746,7 +766,60 @@ static void i915_gem_record_fences(struc
 	}
 }
 
+
+static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
+					struct drm_i915_error_state *error,
+					struct intel_engine_cs *ring,
+					struct drm_i915_error_ring *ering)
+{
+	struct intel_engine_cs *to;
+	int i;
+
+	if (!i915_semaphore_is_enabled(dev_priv->dev))
+		return;
+
+	if (!error->semaphore_obj)
+		error->semaphore_obj =
+			i915_error_object_create(dev_priv,
+						 dev_priv->semaphore_obj,
+						 &dev_priv->gtt.base);
+
+	for_each_ring(to, dev_priv, i) {
+		int idx;
+		u16 signal_offset;
+		u32 *tmp;
+
+		if (ring == to)
+			continue;
+
+		signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
+				/ 4;
+		tmp = error->semaphore_obj->pages[0];
+		idx = intel_ring_sync_index(ring, to);
+
+		ering->semaphore_mboxes[idx] = tmp[signal_offset];
+		ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx];
+	}
+}
+
+static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
+					struct intel_engine_cs *ring,
+					struct drm_i915_error_ring *ering)
+{
+	ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
+	ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
+	ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
+	ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
+
+	if (HAS_VEBOX(dev_priv->dev)) {
+		ering->semaphore_mboxes[2] =
+			I915_READ(RING_SYNC_2(ring->mmio_base));
+		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+	}
+}
+
 static void i915_record_ring_state(struct drm_device *dev,
+				   struct drm_i915_error_state *error,
 				   struct intel_engine_cs *ring,
 				   struct drm_i915_error_ring *ering)
 {
@@ -755,18 +828,10 @@ static void i915_record_ring_state(struc
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
 		ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
-		ering->semaphore_mboxes[0]
-			= I915_READ(RING_SYNC_0(ring->mmio_base));
-		ering->semaphore_mboxes[1]
-			= I915_READ(RING_SYNC_1(ring->mmio_base));
-		ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
-		ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
-	}
-
-	if (HAS_VEBOX(dev)) {
-		ering->semaphore_mboxes[2] =
-			I915_READ(RING_SYNC_2(ring->mmio_base));
-		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+		if (INTEL_INFO(dev)->gen >= 8)
+			gen8_record_semaphore_state(dev_priv, error, ring, ering);
+		else
+			gen6_record_semaphore_state(dev_priv, ring, ering);
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -871,6 +936,9 @@ static void i915_gem_record_active_conte
 		return;
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		if (!i915_gem_obj_ggtt_bound(obj))
+			continue;
+
 		if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
 			ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
 			break;
@@ -895,7 +963,7 @@ static void i915_gem_record_rings(struct
 
 		error->ring[i].valid = true;
 
-		i915_record_ring_state(dev, ring, &error->ring[i]);
+		i915_record_ring_state(dev, error, ring, &error->ring[i]);
 
 		request = i915_gem_find_active_request(ring);
 		if (request) {
@@ -1032,6 +1100,7 @@ static void i915_capture_reg_state(struc
 				   struct drm_i915_error_state *error)
 {
 	struct drm_device *dev = dev_priv->dev;
+	int i;
 
 	/* General organization
 	 * 1. Registers specific to a single generation
@@ -1043,7 +1112,8 @@ static void i915_capture_reg_state(struc
 
 	/* 1: Registers specific to a single generation */
 	if (IS_VALLEYVIEW(dev)) {
-		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+		error->gtier[0] = I915_READ(GTIER);
+		error->ier = I915_READ(VLV_IER);
 		error->forcewake = I915_READ(FORCEWAKE_VLV);
 	}
 
@@ -1076,16 +1146,18 @@ static void i915_capture_reg_state(struc
 	if (HAS_HW_CONTEXTS(dev))
 		error->ccid = I915_READ(CCID);
 
-	if (HAS_PCH_SPLIT(dev))
-		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
-	else {
-		if (IS_GEN2(dev))
-			error->ier = I915_READ16(IER);
-		else
-			error->ier = I915_READ(IER);
+	if (INTEL_INFO(dev)->gen >= 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)) {
+		error->ier = I915_READ(DEIER);
+		error->gtier[0] = I915_READ(GTIER);
+	} else if (IS_GEN2(dev)) {
+		error->ier = I915_READ16(IER);
+	} else if (!IS_VALLEYVIEW(dev)) {
+		error->ier = I915_READ(IER);
 	}
-
-	/* 4: Everything else */
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,7 +136,7 @@ ironlake_enable_display_irq(struct drm_i
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
 	if ((dev_priv->irq_mask & mask) != 0) {
@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (!intel_irqs_enabled(dev_priv))
 		return;
 
 	if ((dev_priv->irq_mask & mask) != mask) {
@@ -173,7 +173,7 @@ static void ilk_update_gt_irq(struct drm
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
 	dev_priv->gt_irq_mask &= ~interrupt_mask;
@@ -182,12 +182,12 @@ static void ilk_update_gt_irq(struct drm
 	POSTING_READ(GTIMR);
 }
 
-void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
 	ilk_update_gt_irq(dev_priv, mask, mask);
 }
 
-void ilk_disable_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)
 {
 	ilk_update_gt_irq(dev_priv, mask, 0);
 }
@@ -206,7 +206,7 @@ static void snb_update_pm_irq(struct drm
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
 	new_val = dev_priv->pm_irq_mask;
@@ -220,12 +220,12 @@ static void snb_update_pm_irq(struct drm
 	}
 }
 
-void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
 	snb_update_pm_irq(dev_priv, mask, mask);
 }
 
-void snb_disable_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)
 {
 	snb_update_pm_irq(dev_priv, mask, 0);
 }
@@ -264,7 +264,7 @@ static void bdw_update_pm_irq(struct drm
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
 	new_val = dev_priv->pm_irq_mask;
@@ -278,12 +278,12 @@ static void bdw_update_pm_irq(struct drm
 	}
 }
 
-void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
 	bdw_update_pm_irq(dev_priv, mask, mask);
 }
 
-void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
 	bdw_update_pm_irq(dev_priv, mask, 0);
 }
@@ -420,7 +420,7 @@ static void ibx_display_interrupt_update
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON(dev_priv->pm.irqs_disabled))
+	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
 	I915_WRITE(SDEIMR, sdeimr);
@@ -1090,6 +1090,53 @@ static bool intel_hpd_irq_event(struct d
 	return true;
 }
 
+static void i915_digport_work_func(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private, dig_port_work);
+	unsigned long irqflags;
+	u32 long_port_mask, short_port_mask;
+	struct intel_digital_port *intel_dig_port;
+	int i, ret;
+	u32 old_bits = 0;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	long_port_mask = dev_priv->long_hpd_port_mask;
+	dev_priv->long_hpd_port_mask = 0;
+	short_port_mask = dev_priv->short_hpd_port_mask;
+	dev_priv->short_hpd_port_mask = 0;
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+	for (i = 0; i < I915_MAX_PORTS; i++) {
+		bool valid = false;
+		bool long_hpd = false;
+		intel_dig_port = dev_priv->hpd_irq_port[i];
+		if (!intel_dig_port || !intel_dig_port->hpd_pulse)
+			continue;
+
+		if (long_port_mask & (1 << i))  {
+			valid = true;
+			long_hpd = true;
+		} else if (short_port_mask & (1 << i))
+			valid = true;
+
+		if (valid) {
+			ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);
+			if (ret == true) {
+				/* if we get true fallback to old school hpd */
+				old_bits |= (1 << intel_dig_port->base.hpd_pin);
+			}
+		}
+	}
+
+	if (old_bits) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		dev_priv->hpd_event_bits |= old_bits;
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+		schedule_work(&dev_priv->hotplug_work);
+	}
+}
+
 /*
  * Handle hotplug events outside the interrupt handler proper.
  */
@@ -1109,10 +1156,6 @@ static void i915_hotplug_work_func(struc
 	bool changed = false;
 	u32 hpd_event_bits;
 
-	/* HPD irq before everything is fully set up. */
-	if (!dev_priv->enable_hotplug_processing)
-		return;
-
 	mutex_lock(&mode_config->mutex);
 	DRM_DEBUG_KMS("running encoder hotplug functions\n");
 
@@ -1122,6 +1165,8 @@ static void i915_hotplug_work_func(struc
 	dev_priv->hpd_event_bits = 0;
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		intel_connector = to_intel_connector(connector);
+		if (!intel_connector->encoder)
+			continue;
 		intel_encoder = intel_connector->encoder;
 		if (intel_encoder->hpd_pin > HPD_NONE &&
 		    dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
@@ -1144,14 +1189,16 @@ static void i915_hotplug_work_func(struc
 	  * some connectors */
 	if (hpd_disabled) {
 		drm_kms_helper_poll_enable(dev);
-		mod_timer(&dev_priv->hotplug_reenable_timer,
-			  jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
+		mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work,
+				 msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
 	}
 
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		intel_connector = to_intel_connector(connector);
+		if (!intel_connector->encoder)
+			continue;
 		intel_encoder = intel_connector->encoder;
 		if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
 			if (intel_encoder->hot_plug)
@@ -1166,11 +1213,6 @@ static void i915_hotplug_work_func(struc
 		drm_kms_helper_hotplug_event(dev);
 }
 
-static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv)
-{
-	del_timer_sync(&dev_priv->hotplug_reenable_timer);
-}
-
 static void ironlake_rps_change_irq_handler(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1218,10 +1260,138 @@ static void notify_ring(struct drm_devic
 
 	trace_i915_gem_request_complete(ring);
 
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		intel_notify_mmio_flip(ring);
+
 	wake_up_all(&ring->irq_queue);
 	i915_queue_hangcheck(dev);
 }
 
+static u32 vlv_c0_residency(struct drm_i915_private *dev_priv,
+			    struct intel_rps_ei *rps_ei)
+{
+	u32 cz_ts, cz_freq_khz;
+	u32 render_count, media_count;
+	u32 elapsed_render, elapsed_media, elapsed_time;
+	u32 residency = 0;
+
+	cz_ts = vlv_punit_read(dev_priv, PUNIT_REG_CZ_TIMESTAMP);
+	cz_freq_khz = DIV_ROUND_CLOSEST(dev_priv->mem_freq * 1000, 4);
+
+	render_count = I915_READ(VLV_RENDER_C0_COUNT_REG);
+	media_count = I915_READ(VLV_MEDIA_C0_COUNT_REG);
+
+	if (rps_ei->cz_clock == 0) {
+		rps_ei->cz_clock = cz_ts;
+		rps_ei->render_c0 = render_count;
+		rps_ei->media_c0 = media_count;
+
+		return dev_priv->rps.cur_freq;
+	}
+
+	elapsed_time = cz_ts - rps_ei->cz_clock;
+	rps_ei->cz_clock = cz_ts;
+
+	elapsed_render = render_count - rps_ei->render_c0;
+	rps_ei->render_c0 = render_count;
+
+	elapsed_media = media_count - rps_ei->media_c0;
+	rps_ei->media_c0 = media_count;
+
+	/* Convert all the counters into common unit of milli sec */
+	elapsed_time /= VLV_CZ_CLOCK_TO_MILLI_SEC;
+	elapsed_render /=  cz_freq_khz;
+	elapsed_media /= cz_freq_khz;
+
+	/*
+	 * Calculate overall C0 residency percentage
+	 * only if elapsed time is non zero
+	 */
+	if (elapsed_time) {
+		residency =
+			((max(elapsed_render, elapsed_media) * 100)
+				/ elapsed_time);
+	}
+
+	return residency;
+}
+
+/**
+ * vlv_calc_delay_from_C0_counters - Increase/Decrease freq based on GPU
+ * busy-ness calculated from C0 counters of render & media power wells
+ * @dev_priv: DRM device private
+ *
+ */
+static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv)
+{
+	u32 residency_C0_up = 0, residency_C0_down = 0;
+	u8 new_delay, adj;
+
+	dev_priv->rps.ei_interrupt_count++;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+
+	if (dev_priv->rps.up_ei.cz_clock == 0) {
+		vlv_c0_residency(dev_priv, &dev_priv->rps.up_ei);
+		vlv_c0_residency(dev_priv, &dev_priv->rps.down_ei);
+		return dev_priv->rps.cur_freq;
+	}
+
+
+	/*
+	 * To down throttle, C0 residency should be less than down threshold
+	 * for continous EI intervals. So calculate down EI counters
+	 * once in VLV_INT_COUNT_FOR_DOWN_EI
+	 */
+	if (dev_priv->rps.ei_interrupt_count == VLV_INT_COUNT_FOR_DOWN_EI) {
+
+		dev_priv->rps.ei_interrupt_count = 0;
+
+		residency_C0_down = vlv_c0_residency(dev_priv,
+						     &dev_priv->rps.down_ei);
+	} else {
+		residency_C0_up = vlv_c0_residency(dev_priv,
+						   &dev_priv->rps.up_ei);
+	}
+
+	new_delay = dev_priv->rps.cur_freq;
+
+	adj = dev_priv->rps.last_adj;
+	/* C0 residency is greater than UP threshold. Increase Frequency */
+	if (residency_C0_up >= VLV_RP_UP_EI_THRESHOLD) {
+		if (adj > 0)
+			adj *= 2;
+		else
+			adj = 1;
+
+		if (dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit)
+			new_delay = dev_priv->rps.cur_freq + adj;
+
+		/*
+		 * For better performance, jump directly
+		 * to RPe if we're below it.
+		 */
+		if (new_delay < dev_priv->rps.efficient_freq)
+			new_delay = dev_priv->rps.efficient_freq;
+
+	} else if (!dev_priv->rps.ei_interrupt_count &&
+			(residency_C0_down < VLV_RP_DOWN_EI_THRESHOLD)) {
+		if (adj < 0)
+			adj *= 2;
+		else
+			adj = -1;
+		/*
+		 * This means, C0 residency is less than down threshold over
+		 * a period of VLV_INT_COUNT_FOR_DOWN_EI. So, reduce the freq
+		 */
+		if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit)
+			new_delay = dev_priv->rps.cur_freq + adj;
+	}
+
+	return new_delay;
+}
+
 static void gen6_pm_rps_work(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
@@ -1232,11 +1402,11 @@ static void gen6_pm_rps_work(struct work
 	spin_lock_irq(&dev_priv->irq_lock);
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
-	if (IS_BROADWELL(dev_priv->dev))
-		bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	if (INTEL_INFO(dev_priv->dev)->gen >= 8)
+		gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
 	else {
 		/* Make sure not to corrupt PMIMR state used by ringbuffer */
-		snb_enable_pm_irq(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);
 
@@ -1252,8 +1422,10 @@ static void gen6_pm_rps_work(struct work
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
 		if (adj > 0)
 			adj *= 2;
-		else
-			adj = 1;
+		else {
+			/* CHV needs even encode values */
+			adj = IS_CHERRYVIEW(dev_priv->dev) ? 2 : 1;
+		}
 		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
@@ -1268,11 +1440,15 @@ static void gen6_pm_rps_work(struct work
 		else
 			new_delay = dev_priv->rps.min_freq_softlimit;
 		adj = 0;
+	} else if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
+		new_delay = vlv_calc_delay_from_C0_counters(dev_priv);
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
 		if (adj < 0)
 			adj *= 2;
-		else
-			adj = -1;
+		else {
+			/* CHV needs even encode values */
+			adj = IS_CHERRYVIEW(dev_priv->dev) ? -2 : -1;
+		}
 		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
 		new_delay = dev_priv->rps.cur_freq;
@@ -1372,7 +1548,7 @@ static void ivybridge_parity_work(struct
 out:
 	WARN_ON(dev_priv->l3_parity.which_slice);
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
+	gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
 	mutex_unlock(&dev_priv->dev->struct_mutex);
@@ -1386,7 +1562,7 @@ static void ivybridge_parity_error_irq_h
 		return;
 
 	spin_lock(&dev_priv->irq_lock);
-	ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
+	gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
 	spin_unlock(&dev_priv->irq_lock);
 
 	iir &= GT_PARITY_ERROR(dev);
@@ -1441,7 +1617,7 @@ static void gen8_rps_irq_handler(struct
 
 	spin_lock(&dev_priv->irq_lock);
 	dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
-	bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+	gen8_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
 	spin_unlock(&dev_priv->irq_lock);
 
 	queue_work(dev_priv->wq, &dev_priv->rps.work);
@@ -1458,6 +1634,7 @@ static irqreturn_t gen8_gt_irq_handler(s
 	if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
 		tmp = I915_READ(GEN8_GT_IIR(0));
 		if (tmp) {
+			I915_WRITE(GEN8_GT_IIR(0), tmp);
 			ret = IRQ_HANDLED;
 			rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
 			bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
@@ -1465,7 +1642,6 @@ static irqreturn_t gen8_gt_irq_handler(s
 				notify_ring(dev, &dev_priv->ring[RCS]);
 			if (bcs & GT_RENDER_USER_INTERRUPT)
 				notify_ring(dev, &dev_priv->ring[BCS]);
-			I915_WRITE(GEN8_GT_IIR(0), tmp);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT0)!\n");
 	}
@@ -1473,6 +1649,7 @@ static irqreturn_t gen8_gt_irq_handler(s
 	if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
 		tmp = I915_READ(GEN8_GT_IIR(1));
 		if (tmp) {
+			I915_WRITE(GEN8_GT_IIR(1), tmp);
 			ret = IRQ_HANDLED;
 			vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
 			if (vcs & GT_RENDER_USER_INTERRUPT)
@@ -1480,7 +1657,6 @@ static irqreturn_t gen8_gt_irq_handler(s
 			vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
 			if (vcs & GT_RENDER_USER_INTERRUPT)
 				notify_ring(dev, &dev_priv->ring[VCS2]);
-			I915_WRITE(GEN8_GT_IIR(1), tmp);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT1)!\n");
 	}
@@ -1488,10 +1664,10 @@ static irqreturn_t gen8_gt_irq_handler(s
 	if (master_ctl & GEN8_GT_PM_IRQ) {
 		tmp = I915_READ(GEN8_GT_IIR(2));
 		if (tmp & dev_priv->pm_rps_events) {
-			ret = IRQ_HANDLED;
-			gen8_rps_irq_handler(dev_priv, tmp);
 			I915_WRITE(GEN8_GT_IIR(2),
 				   tmp & dev_priv->pm_rps_events);
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
 		} else
 			DRM_ERROR("The master control interrupt lied (PM)!\n");
 	}
@@ -1499,11 +1675,11 @@ static irqreturn_t gen8_gt_irq_handler(s
 	if (master_ctl & GEN8_GT_VECS_IRQ) {
 		tmp = I915_READ(GEN8_GT_IIR(3));
 		if (tmp) {
+			I915_WRITE(GEN8_GT_IIR(3), tmp);
 			ret = IRQ_HANDLED;
 			vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
 			if (vcs & GT_RENDER_USER_INTERRUPT)
 				notify_ring(dev, &dev_priv->ring[VECS]);
-			I915_WRITE(GEN8_GT_IIR(3), tmp);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT3)!\n");
 	}
@@ -1514,23 +1690,104 @@ static irqreturn_t gen8_gt_irq_handler(s
 #define HPD_STORM_DETECT_PERIOD 1000
 #define HPD_STORM_THRESHOLD 5
 
+static int ilk_port_to_hotplug_shift(enum port port)
+{
+	switch (port) {
+	case PORT_A:
+	case PORT_E:
+	default:
+		return -1;
+	case PORT_B:
+		return 0;
+	case PORT_C:
+		return 8;
+	case PORT_D:
+		return 16;
+	}
+}
+
+static int g4x_port_to_hotplug_shift(enum port port)
+{
+	switch (port) {
+	case PORT_A:
+	case PORT_E:
+	default:
+		return -1;
+	case PORT_B:
+		return 17;
+	case PORT_C:
+		return 19;
+	case PORT_D:
+		return 21;
+	}
+}
+
+static inline enum port get_port_from_pin(enum hpd_pin pin)
+{
+	switch (pin) {
+	case HPD_PORT_B:
+		return PORT_B;
+	case HPD_PORT_C:
+		return PORT_C;
+	case HPD_PORT_D:
+		return PORT_D;
+	default:
+		return PORT_A; /* no hpd */
+	}
+}
+
 static inline void intel_hpd_irq_handler(struct drm_device *dev,
 					 u32 hotplug_trigger,
+					 u32 dig_hotplug_reg,
 					 const u32 *hpd)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
+	enum port port;
 	bool storm_detected = false;
+	bool queue_dig = false, queue_hp = false;
+	u32 dig_shift;
+	u32 dig_port_mask = 0;
 
 	if (!hotplug_trigger)
 		return;
 
-	DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-			  hotplug_trigger);
+	DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x\n",
+			 hotplug_trigger, dig_hotplug_reg);
 
 	spin_lock(&dev_priv->irq_lock);
 	for (i = 1; i < HPD_NUM_PINS; i++) {
+		if (!(hpd[i] & hotplug_trigger))
+			continue;
+
+		port = get_port_from_pin(i);
+		if (port && dev_priv->hpd_irq_port[port]) {
+			bool long_hpd;
+
+			if (IS_G4X(dev)) {
+				dig_shift = g4x_port_to_hotplug_shift(port);
+				long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
+			} else {
+				dig_shift = ilk_port_to_hotplug_shift(port);
+				long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
+			}
+
+			DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port, long_hpd);
+			/* for long HPD pulses we want to have the digital queue happen,
+			   but we still want HPD storm detection to function. */
+			if (long_hpd) {
+				dev_priv->long_hpd_port_mask |= (1 << port);
+				dig_port_mask |= hpd[i];
+			} else {
+				/* for short HPD just trigger the digital queue */
+				dev_priv->short_hpd_port_mask |= (1 << port);
+				hotplug_trigger &= ~hpd[i];
+			}
+			queue_dig = true;
+		}
+	}
 
+	for (i = 1; i < HPD_NUM_PINS; i++) {
 		if (hpd[i] & hotplug_trigger &&
 		    dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {
 			/*
@@ -1550,7 +1807,11 @@ static inline void intel_hpd_irq_handler
 		    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
 			continue;
 
-		dev_priv->hpd_event_bits |= (1 << i);
+		if (!(dig_port_mask & hpd[i])) {
+			dev_priv->hpd_event_bits |= (1 << i);
+			queue_hp = true;
+		}
+
 		if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
 				   dev_priv->hpd_stats[i].hpd_last_jiffies
 				   + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
@@ -1579,7 +1840,10 @@ static inline void intel_hpd_irq_handler
 	 * queue for otherwise the flush_work in the pageflip code will
 	 * deadlock.
 	 */
-	schedule_work(&dev_priv->hotplug_work);
+	if (queue_dig)
+		queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
+	if (queue_hp)
+		schedule_work(&dev_priv->hotplug_work);
 }
 
 static void gmbus_irq_handler(struct drm_device *dev)
@@ -1700,7 +1964,7 @@ static void gen6_rps_irq_handler(struct
 	if (pm_iir & dev_priv->pm_rps_events) {
 		spin_lock(&dev_priv->irq_lock);
 		dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
-		snb_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+		gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
 		spin_unlock(&dev_priv->irq_lock);
 
 		queue_work(dev_priv->wq, &dev_priv->rps.work);
@@ -1809,26 +2073,28 @@ static void i9xx_hpd_irq_handler(struct
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
 
-	if (IS_G4X(dev)) {
-		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
+	if (hotplug_status) {
+		I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+		/*
+		 * Make sure hotplug status is cleared before we clear IIR, or else we
+		 * may miss hotplug events.
+		 */
+		POSTING_READ(PORT_HOTPLUG_STAT);
 
-		intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_g4x);
-	} else {
-		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+		if (IS_G4X(dev)) {
+			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
 
-		intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
-	}
+			intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_g4x);
+		} else {
+			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
 
-	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
-	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
-		dp_aux_irq_handler(dev);
+			intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_i915);
+		}
 
-	I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-	/*
-	 * Make sure hotplug status is cleared before we clear IIR, or else we
-	 * may miss hotplug events.
-	 */
-	POSTING_READ(PORT_HOTPLUG_STAT);
+		if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
+		    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+			dp_aux_irq_handler(dev);
+	}
 }
 
 static irqreturn_t valleyview_irq_handler(int irq, void *arg)
@@ -1839,29 +2105,36 @@ static irqreturn_t valleyview_irq_handle
 	irqreturn_t ret = IRQ_NONE;
 
 	while (true) {
-		iir = I915_READ(VLV_IIR);
+		/* Find, clear, then process each source of interrupt */
+
 		gt_iir = I915_READ(GTIIR);
+		if (gt_iir)
+			I915_WRITE(GTIIR, gt_iir);
+
 		pm_iir = I915_READ(GEN6_PMIIR);
+		if (pm_iir)
+			I915_WRITE(GEN6_PMIIR, pm_iir);
+
+		iir = I915_READ(VLV_IIR);
+		if (iir) {
+			/* Consume port before clearing IIR or we'll miss events */
+			if (iir & I915_DISPLAY_PORT_INTERRUPT)
+				i9xx_hpd_irq_handler(dev);
+			I915_WRITE(VLV_IIR, iir);
+		}
 
 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
 			goto out;
 
 		ret = IRQ_HANDLED;
 
-		snb_gt_irq_handler(dev, dev_priv, gt_iir);
-
-		valleyview_pipestat_irq_handler(dev, iir);
-
-		/* Consume port.  Then clear IIR or we'll miss events */
-		if (iir & I915_DISPLAY_PORT_INTERRUPT)
-			i9xx_hpd_irq_handler(dev);
-
+		if (gt_iir)
+			snb_gt_irq_handler(dev, dev_priv, gt_iir);
 		if (pm_iir)
 			gen6_rps_irq_handler(dev_priv, pm_iir);
-
-		I915_WRITE(GTIIR, gt_iir);
-		I915_WRITE(GEN6_PMIIR, pm_iir);
-		I915_WRITE(VLV_IIR, iir);
+		/* Call regardless, as some status bits might not be
+		 * signalled in iir */
+		valleyview_pipestat_irq_handler(dev, iir);
 	}
 
 out:
@@ -1882,21 +2155,27 @@ static irqreturn_t cherryview_irq_handle
 		if (master_ctl == 0 && iir == 0)
 			break;
 
+		ret = IRQ_HANDLED;
+
 		I915_WRITE(GEN8_MASTER_IRQ, 0);
 
-		gen8_gt_irq_handler(dev, dev_priv, master_ctl);
+		/* Find, clear, then process each source of interrupt */
 
-		valleyview_pipestat_irq_handler(dev, iir);
+		if (iir) {
+			/* Consume port before clearing IIR or we'll miss events */
+			if (iir & I915_DISPLAY_PORT_INTERRUPT)
+				i9xx_hpd_irq_handler(dev);
+			I915_WRITE(VLV_IIR, iir);
+		}
 
-		/* Consume port.  Then clear IIR or we'll miss events */
-		i9xx_hpd_irq_handler(dev);
+		gen8_gt_irq_handler(dev, dev_priv, master_ctl);
 
-		I915_WRITE(VLV_IIR, iir);
+		/* Call regardless, as some status bits might not be
+		 * signalled in iir */
+		valleyview_pipestat_irq_handler(dev, iir);
 
 		I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
 		POSTING_READ(GEN8_MASTER_IRQ);
-
-		ret = IRQ_HANDLED;
 	}
 
 	return ret;
@@ -1907,8 +2186,12 @@ static void ibx_irq_handler(struct drm_d
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
+	u32 dig_hotplug_reg;
 
-	intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
+	dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+	I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+	intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_ibx);
 
 	if (pch_iir & SDE_AUDIO_POWER_MASK) {
 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -2014,8 +2297,12 @@ static void cpt_irq_handler(struct drm_d
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
+	u32 dig_hotplug_reg;
 
-	intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
+	dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+	I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+	intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_cpt);
 
 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
@@ -2132,6 +2419,14 @@ static void ivb_display_irq_handler(stru
 	}
 }
 
+/*
+ * To handle irqs with the minimum potential races with fresh interrupts, we:
+ * 1 - Disable Master Interrupt Control.
+ * 2 - Find the source(s) of the interrupt.
+ * 3 - Clear the Interrupt Identity bits (IIR).
+ * 4 - Process the interrupt(s) that had bits set in the IIRs.
+ * 5 - Re-enable Master Interrupt Control.
+ */
 static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = arg;
@@ -2159,32 +2454,34 @@ static irqreturn_t ironlake_irq_handler(
 		POSTING_READ(SDEIER);
 	}
 
+	/* Find, clear, then process each source of interrupt */
+
 	gt_iir = I915_READ(GTIIR);
 	if (gt_iir) {
+		I915_WRITE(GTIIR, gt_iir);
+		ret = IRQ_HANDLED;
 		if (INTEL_INFO(dev)->gen >= 6)
 			snb_gt_irq_handler(dev, dev_priv, gt_iir);
 		else
 			ilk_gt_irq_handler(dev, dev_priv, gt_iir);
-		I915_WRITE(GTIIR, gt_iir);
-		ret = IRQ_HANDLED;
 	}
 
 	de_iir = I915_READ(DEIIR);
 	if (de_iir) {
+		I915_WRITE(DEIIR, de_iir);
+		ret = IRQ_HANDLED;
 		if (INTEL_INFO(dev)->gen >= 7)
 			ivb_display_irq_handler(dev, de_iir);
 		else
 			ilk_display_irq_handler(dev, de_iir);
-		I915_WRITE(DEIIR, de_iir);
-		ret = IRQ_HANDLED;
 	}
 
 	if (INTEL_INFO(dev)->gen >= 6) {
 		u32 pm_iir = I915_READ(GEN6_PMIIR);
 		if (pm_iir) {
-			gen6_rps_irq_handler(dev_priv, pm_iir);
 			I915_WRITE(GEN6_PMIIR, pm_iir);
 			ret = IRQ_HANDLED;
+			gen6_rps_irq_handler(dev_priv, pm_iir);
 		}
 	}
 
@@ -2215,36 +2512,36 @@ static irqreturn_t gen8_irq_handler(int
 	I915_WRITE(GEN8_MASTER_IRQ, 0);
 	POSTING_READ(GEN8_MASTER_IRQ);
 
+	/* Find, clear, then process each source of interrupt */
+
 	ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl);
 
 	if (master_ctl & GEN8_DE_MISC_IRQ) {
 		tmp = I915_READ(GEN8_DE_MISC_IIR);
-		if (tmp & GEN8_DE_MISC_GSE)
-			intel_opregion_asle_intr(dev);
-		else if (tmp)
-			DRM_ERROR("Unexpected DE Misc interrupt\n");
-		else
-			DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
-
 		if (tmp) {
 			I915_WRITE(GEN8_DE_MISC_IIR, tmp);
 			ret = IRQ_HANDLED;
+			if (tmp & GEN8_DE_MISC_GSE)
+				intel_opregion_asle_intr(dev);
+			else
+				DRM_ERROR("Unexpected DE Misc interrupt\n");
 		}
+		else
+			DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
 	}
 
 	if (master_ctl & GEN8_DE_PORT_IRQ) {
 		tmp = I915_READ(GEN8_DE_PORT_IIR);
-		if (tmp & GEN8_AUX_CHANNEL_A)
-			dp_aux_irq_handler(dev);
-		else if (tmp)
-			DRM_ERROR("Unexpected DE Port interrupt\n");
-		else
-			DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
-
 		if (tmp) {
 			I915_WRITE(GEN8_DE_PORT_IIR, tmp);
 			ret = IRQ_HANDLED;
+			if (tmp & GEN8_AUX_CHANNEL_A)
+				dp_aux_irq_handler(dev);
+			else
+				DRM_ERROR("Unexpected DE Port interrupt\n");
 		}
+		else
+			DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
 	}
 
 	for_each_pipe(pipe) {
@@ -2254,33 +2551,32 @@ static irqreturn_t gen8_irq_handler(int
 			continue;
 
 		pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
-		if (pipe_iir & GEN8_PIPE_VBLANK)
-			intel_pipe_handle_vblank(dev, pipe);
-
-		if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
-			intel_prepare_page_flip(dev, pipe);
-			intel_finish_page_flip_plane(dev, pipe);
-		}
+		if (pipe_iir) {
+			ret = IRQ_HANDLED;
+			I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+			if (pipe_iir & GEN8_PIPE_VBLANK)
+				intel_pipe_handle_vblank(dev, pipe);
 
-		if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
-			hsw_pipe_crc_irq_handler(dev, pipe);
+			if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
+				intel_prepare_page_flip(dev, pipe);
+				intel_finish_page_flip_plane(dev, pipe);
+			}
 
-		if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
-			if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
-								  false))
-				DRM_ERROR("Pipe %c FIFO underrun\n",
-					  pipe_name(pipe));
-		}
+			if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
+				hsw_pipe_crc_irq_handler(dev, pipe);
 
-		if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
-			DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
-				  pipe_name(pipe),
-				  pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
-		}
+			if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
+				if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
+									  false))
+					DRM_ERROR("Pipe %c FIFO underrun\n",
+						  pipe_name(pipe));
+			}
 
-		if (pipe_iir) {
-			ret = IRQ_HANDLED;
-			I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+			if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
+				DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
+					  pipe_name(pipe),
+					  pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
+			}
 		} else
 			DRM_ERROR("The master control interrupt lied (DE PIPE)!\n");
 	}
@@ -2292,13 +2588,13 @@ static irqreturn_t gen8_irq_handler(int
 		 * on older pch-split platforms. But this needs testing.
 		 */
 		u32 pch_iir = I915_READ(SDEIIR);
-
-		cpt_irq_handler(dev, pch_iir);
-
 		if (pch_iir) {
 			I915_WRITE(SDEIIR, pch_iir);
 			ret = IRQ_HANDLED;
-		}
+			cpt_irq_handler(dev, pch_iir);
+		} else
+			DRM_ERROR("The master control interrupt lied (SDE)!\n");
+
 	}
 
 	I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -2753,12 +3049,7 @@ static bool
 ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 {
 	if (INTEL_INFO(dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return false;
+		return (ipehr >> 23) == 0x1c;
 	} else {
 		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
 		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
@@ -2767,19 +3058,20 @@ ipehr_is_semaphore_wait(struct drm_devic
 }
 
 static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr)
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr, u64 offset)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct intel_engine_cs *signaller;
 	int i;
 
 	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return NULL;
+		for_each_ring(signaller, dev_priv, i) {
+			if (ring == signaller)
+				continue;
+
+			if (offset == signaller->semaphore.signal_ggtt[ring->id])
+				return signaller;
+		}
 	} else {
 		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
@@ -2792,8 +3084,8 @@ semaphore_wait_to_signaller_ring(struct
 		}
 	}
 
-	DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x\n",
-		  ring->id, ipehr);
+	DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n",
+		  ring->id, ipehr, offset);
 
 	return NULL;
 }
@@ -2803,7 +3095,8 @@ semaphore_waits_for(struct intel_engine_
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	u32 cmd, ipehr, head;
-	int i;
+	u64 offset = 0;
+	int i, backwards;
 
 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
 	if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
@@ -2812,13 +3105,15 @@ semaphore_waits_for(struct intel_engine_
 	/*
 	 * 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
-	 * dwords. Note that we don't care about ACTHD here since that might
+	 * 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(ring) & HEAD_ADDR;
+	backwards = (INTEL_INFO(ring->dev)->gen >= 8) ? 5 : 4;
 
-	for (i = 4; i; --i) {
+	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
@@ -2838,7 +3133,12 @@ semaphore_waits_for(struct intel_engine_
 		return NULL;
 
 	*seqno = ioread32(ring->buffer->virtual_start + head + 4) + 1;
-	return semaphore_wait_to_signaller_ring(ring, ipehr);
+	if (INTEL_INFO(ring->dev)->gen >= 8) {
+		offset = ioread32(ring->buffer->virtual_start + head + 12);
+		offset <<= 32;
+		offset = ioread32(ring->buffer->virtual_start + head + 8);
+	}
+	return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
 }
 
 static int semaphore_passed(struct intel_engine_cs *ring)
@@ -2884,8 +3184,14 @@ ring_stuck(struct intel_engine_cs *ring,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 tmp;
 
-	if (ring->hangcheck.acthd != acthd)
-		return HANGCHECK_ACTIVE;
+	if (acthd != ring->hangcheck.acthd) {
+		if (acthd > ring->hangcheck.max_acthd) {
+			ring->hangcheck.max_acthd = acthd;
+			return HANGCHECK_ACTIVE;
+		}
+
+		return HANGCHECK_ACTIVE_LOOP;
+	}
 
 	if (IS_GEN2(dev))
 		return HANGCHECK_HUNG;
@@ -2996,8 +3302,9 @@ static void i915_hangcheck_elapsed(unsig
 				switch (ring->hangcheck.action) {
 				case HANGCHECK_IDLE:
 				case HANGCHECK_WAIT:
-					break;
 				case HANGCHECK_ACTIVE:
+					break;
+				case HANGCHECK_ACTIVE_LOOP:
 					ring->hangcheck.score += BUSY;
 					break;
 				case HANGCHECK_KICK:
@@ -3017,6 +3324,8 @@ static void i915_hangcheck_elapsed(unsig
 			 */
 			if (ring->hangcheck.score > 0)
 				ring->hangcheck.score--;
+
+			ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
 		}
 
 		ring->hangcheck.seqno = seqno;
@@ -3159,7 +3468,9 @@ static void gen8_irq_reset(struct drm_de
 	gen8_gt_irq_reset(dev_priv);
 
 	for_each_pipe(pipe)
-		GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
+		if (intel_display_power_enabled(dev_priv,
+						POWER_DOMAIN_PIPE(pipe)))
+			GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
 
 	GEN5_IRQ_RESET(GEN8_DE_PORT_);
 	GEN5_IRQ_RESET(GEN8_DE_MISC_);
@@ -3168,6 +3479,18 @@ static void gen8_irq_reset(struct drm_de
 	ibx_irq_reset(dev);
 }
 
+void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_B, dev_priv->de_irq_mask[PIPE_B],
+			  ~dev_priv->de_irq_mask[PIPE_B]);
+	GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_C, dev_priv->de_irq_mask[PIPE_C],
+			  ~dev_priv->de_irq_mask[PIPE_C]);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
 static void cherryview_irq_preinstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3492,8 +3815,11 @@ static void gen8_de_irq_postinstall(stru
 	dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
 
 	for_each_pipe(pipe)
-		GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe],
-				  de_pipe_enables);
+		if (intel_display_power_enabled(dev_priv,
+				POWER_DOMAIN_PIPE(pipe)))
+			GEN8_IRQ_INIT_NDX(DE_PIPE, pipe,
+					  dev_priv->de_irq_mask[pipe],
+					  de_pipe_enables);
 
 	GEN5_IRQ_INIT(GEN8_DE_PORT_, ~GEN8_AUX_CHANNEL_A, GEN8_AUX_CHANNEL_A);
 }
@@ -3561,8 +3887,6 @@ static void gen8_irq_uninstall(struct dr
 	if (!dev_priv)
 		return;
 
-	intel_hpd_irq_uninstall(dev_priv);
-
 	gen8_irq_reset(dev);
 }
 
@@ -3577,8 +3901,6 @@ static void valleyview_irq_uninstall(str
 
 	I915_WRITE(VLV_MASTER_IER, 0);
 
-	intel_hpd_irq_uninstall(dev_priv);
-
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0xffff);
 
@@ -3657,8 +3979,6 @@ static void ironlake_irq_uninstall(struc
 	if (!dev_priv)
 		return;
 
-	intel_hpd_irq_uninstall(dev_priv);
-
 	ironlake_irq_reset(dev);
 }
 
@@ -4029,8 +4349,6 @@ static void i915_irq_uninstall(struct dr
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
 
-	intel_hpd_irq_uninstall(dev_priv);
-
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -4267,8 +4585,6 @@ static void i965_irq_uninstall(struct dr
 	if (!dev_priv)
 		return;
 
-	intel_hpd_irq_uninstall(dev_priv);
-
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
@@ -4284,14 +4600,18 @@ static void i965_irq_uninstall(struct dr
 	I915_WRITE(IIR, I915_READ(IIR));
 }
 
-static void intel_hpd_irq_reenable(unsigned long data)
+static void intel_hpd_irq_reenable(struct work_struct *work)
 {
-	struct drm_i915_private *dev_priv = (struct drm_i915_private *)data;
+	struct drm_i915_private *dev_priv =
+		container_of(work, typeof(*dev_priv),
+			     hotplug_reenable_work.work);
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	unsigned long irqflags;
 	int i;
 
+	intel_runtime_pm_get(dev_priv);
+
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
 		struct drm_connector *connector;
@@ -4317,6 +4637,8 @@ static void intel_hpd_irq_reenable(unsig
 	if (dev_priv->display.hpd_irq_setup)
 		dev_priv->display.hpd_irq_setup(dev);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 void intel_irq_init(struct drm_device *dev)
@@ -4324,21 +4646,29 @@ void intel_irq_init(struct drm_device *d
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+	INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);
 	INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);
 	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
 	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
 
 	/* Let's track the enabled rps events */
-	dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
+	if (IS_VALLEYVIEW(dev))
+		/* WaGsvRC0ResidenncyMethod:VLV */
+		dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
+	else
+		dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
 	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
 		    i915_hangcheck_elapsed,
 		    (unsigned long) dev);
-	setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable,
-		    (unsigned long) dev_priv);
+	INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work,
+			  intel_hpd_irq_reenable);
 
 	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 
+	/* Haven't installed the IRQ handler yet */
+	dev_priv->pm._irqs_disabled = true;
+
 	if (IS_GEN2(dev)) {
 		dev->max_vblank_count = 0;
 		dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
@@ -4426,7 +4756,9 @@ void intel_hpd_init(struct drm_device *d
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		struct intel_connector *intel_connector = to_intel_connector(connector);
 		connector->polled = intel_connector->polled;
-		if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+		if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+			connector->polled = DRM_CONNECTOR_POLL_HPD;
+		if (intel_connector->mst_port)
 			connector->polled = DRM_CONNECTOR_POLL_HPD;
 	}
 
@@ -4444,7 +4776,7 @@ void intel_runtime_pm_disable_interrupts
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	dev->driver->irq_uninstall(dev);
-	dev_priv->pm.irqs_disabled = true;
+	dev_priv->pm._irqs_disabled = true;
 }
 
 /* Restore interrupts so we can recover from runtime PM. */
@@ -4452,7 +4784,7 @@ void intel_runtime_pm_restore_interrupts
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->pm.irqs_disabled = false;
+	dev_priv->pm._irqs_disabled = false;
 	dev->driver->irq_preinstall(dev);
 	dev->driver->irq_postinstall(dev);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_params.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_params.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_params.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_params.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,8 @@ struct i915_params i915 __read_mostly =
 	.disable_display = 0,
 	.enable_cmd_parser = 1,
 	.disable_vtd_wa = 0,
+	.use_mmio_flip = 0,
+	.mmio_debug = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -156,3 +158,12 @@ MODULE_PARM_DESC(disable_vtd_wa, "Disabl
 module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
 MODULE_PARM_DESC(enable_cmd_parser,
 		 "Enable command parsing (1=enabled [default], 0=disabled)");
+
+module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600);
+MODULE_PARM_DESC(use_mmio_flip,
+		 "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");
+
+module_param_named(mmio_debug, i915.mmio_debug, bool, 0600);
+MODULE_PARM_DESC(mmio_debug,
+	"Enable the MMIO debug code (default: false). This may negatively "
+	"affect performance.");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -29,8 +29,8 @@
 #define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
 
 #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
-#define _PIPE3(pipe, a, b, c) (pipe < 2 ? _PIPE(pipe, a, b) : c)
-#define _PORT3(port, a, b, c) (port < 2 ? _PORT(port, a, b) : c)
+#define _PIPE3(pipe, a, b, c) ((pipe) == PIPE_A ? (a) : \
+			       (pipe) == PIPE_B ? (b) : (c))
 
 #define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a))
 #define _MASKED_BIT_DISABLE(a) ((a) << 16)
@@ -240,7 +240,7 @@
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
-#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6+ */
+#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6, gen7 */
 #define   MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
 #define   MI_SEMAPHORE_UPDATE	    (1<<21)
 #define   MI_SEMAPHORE_COMPARE	    (1<<20)
@@ -266,6 +266,11 @@
 #define   MI_RESTORE_EXT_STATE_EN	(1<<2)
 #define   MI_FORCE_RESTORE		(1<<1)
 #define   MI_RESTORE_INHIBIT		(1<<0)
+#define MI_SEMAPHORE_SIGNAL	MI_INSTR(0x1b, 0) /* GEN8+ */
+#define   MI_SEMAPHORE_TARGET(engine)	((engine)<<15)
+#define MI_SEMAPHORE_WAIT	MI_INSTR(0x1c, 2) /* GEN8+ */
+#define   MI_SEMAPHORE_POLL		(1<<15)
+#define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
@@ -329,16 +334,20 @@
 #define GFX_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
 #define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
 #define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
-#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
+
+#define COLOR_BLT_CMD			(2<<29 | 0x40<<22 | (5-2))
+#define SRC_COPY_BLT_CMD		((2<<29)|(0x43<<22)|4)
 #define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
 #define XY_MONO_SRC_COPY_IMM_BLT	((2<<29)|(0x71<<22)|5)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
+#define   BLT_WRITE_A			(2<<20)
+#define   BLT_WRITE_RGB			(1<<20)
+#define   BLT_WRITE_RGBA		(BLT_WRITE_RGB | BLT_WRITE_A)
 #define   BLT_DEPTH_8			(0<<24)
 #define   BLT_DEPTH_16_565		(1<<24)
 #define   BLT_DEPTH_16_1555		(2<<24)
 #define   BLT_DEPTH_32			(3<<24)
-#define   BLT_ROP_GXCOPY		(0xcc<<16)
+#define   BLT_ROP_SRC_COPY		(0xcc<<16)
+#define   BLT_ROP_COLOR_COPY		(0xf0<<16)
 #define XY_SRC_COPY_BLT_SRC_TILED	(1<<15) /* 965+ only */
 #define XY_SRC_COPY_BLT_DST_TILED	(1<<11) /* 965+ only */
 #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
@@ -360,6 +369,7 @@
 #define   PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE		(1<<10) /* GM45+ only */
 #define   PIPE_CONTROL_INDIRECT_STATE_DISABLE		(1<<9)
 #define   PIPE_CONTROL_NOTIFY				(1<<8)
+#define   PIPE_CONTROL_FLUSH_ENABLE			(1<<7) /* gen7+ */
 #define   PIPE_CONTROL_VF_CACHE_INVALIDATE		(1<<4)
 #define   PIPE_CONTROL_CONST_CACHE_INVALIDATE		(1<<3)
 #define   PIPE_CONTROL_STATE_CACHE_INVALIDATE		(1<<2)
@@ -525,10 +535,21 @@ enum punit_power_well {
 #define PUNIT_REG_GPU_FREQ_STS			0xd8
 #define   GENFREQSTATUS				(1<<0)
 #define PUNIT_REG_MEDIA_TURBO_FREQ_REQ		0xdc
+#define PUNIT_REG_CZ_TIMESTAMP			0xce
 
 #define PUNIT_FUSE_BUS2				0xf6 /* bits 47:40 */
 #define PUNIT_FUSE_BUS1				0xf5 /* bits 55:48 */
 
+#define PUNIT_GPU_STATUS_REG			0xdb
+#define PUNIT_GPU_STATUS_MAX_FREQ_SHIFT	16
+#define PUNIT_GPU_STATUS_MAX_FREQ_MASK		0xff
+#define PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT	8
+#define PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK	0xff
+
+#define PUNIT_GPU_DUTYCYCLE_REG		0xdf
+#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT	8
+#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK	0xff
+
 #define IOSF_NC_FB_GFX_FREQ_FUSE		0x1c
 #define   FB_GFX_MAX_FREQ_FUSE_SHIFT		3
 #define   FB_GFX_MAX_FREQ_FUSE_MASK		0x000007f8
@@ -540,6 +561,11 @@ enum punit_power_well {
 #define   FB_FMAX_VMIN_FREQ_LO_SHIFT		27
 #define   FB_FMAX_VMIN_FREQ_LO_MASK		0xf8000000
 
+#define VLV_CZ_CLOCK_TO_MILLI_SEC		100000
+#define VLV_RP_UP_EI_THRESHOLD			90
+#define VLV_RP_DOWN_EI_THRESHOLD		70
+#define VLV_INT_COUNT_FOR_DOWN_EI		5
+
 /* vlv2 north clock has */
 #define CCK_FUSE_REG				0x8
 #define  CCK_FUSE_HPLL_FREQ_MASK		0x3
@@ -574,6 +600,11 @@ enum punit_power_well {
 #define  DSI_PLL_M1_DIV_SHIFT			0
 #define  DSI_PLL_M1_DIV_MASK			(0x1ff << 0)
 #define CCK_DISPLAY_CLOCK_CONTROL		0x6b
+#define  DISPLAY_TRUNK_FORCE_ON			(1 << 17)
+#define  DISPLAY_TRUNK_FORCE_OFF		(1 << 16)
+#define  DISPLAY_FREQUENCY_STATUS		(0x1f << 8)
+#define  DISPLAY_FREQUENCY_STATUS_SHIFT		8
+#define  DISPLAY_FREQUENCY_VALUES		(0x1f << 0)
 
 /**
  * DOC: DPIO
@@ -761,6 +792,8 @@ enum punit_power_well {
 
 #define _VLV_PCS_DW8_CH0		0x8220
 #define _VLV_PCS_DW8_CH1		0x8420
+#define   CHV_PCS_USEDCLKCHANNEL_OVRRIDE	(1 << 20)
+#define   CHV_PCS_USEDCLKCHANNEL		(1 << 21)
 #define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1)
 
 #define _VLV_PCS01_DW8_CH0		0x0220
@@ -869,6 +902,16 @@ enum punit_power_well {
 #define   DPIO_CHV_PROP_COEFF_SHIFT	0
 #define CHV_PLL_DW6(ch) _PIPE(ch, _CHV_PLL_DW6_CH0, _CHV_PLL_DW6_CH1)
 
+#define _CHV_CMN_DW5_CH0               0x8114
+#define   CHV_BUFRIGHTENA1_DISABLE	(0 << 20)
+#define   CHV_BUFRIGHTENA1_NORMAL	(1 << 20)
+#define   CHV_BUFRIGHTENA1_FORCE	(3 << 20)
+#define   CHV_BUFRIGHTENA1_MASK		(3 << 20)
+#define   CHV_BUFLEFTENA1_DISABLE	(0 << 22)
+#define   CHV_BUFLEFTENA1_NORMAL	(1 << 22)
+#define   CHV_BUFLEFTENA1_FORCE		(3 << 22)
+#define   CHV_BUFLEFTENA1_MASK		(3 << 22)
+
 #define _CHV_CMN_DW13_CH0		0x8134
 #define _CHV_CMN_DW0_CH1		0x8080
 #define   DPIO_CHV_S1_DIV_SHIFT		21
@@ -883,8 +926,21 @@ enum punit_power_well {
 #define _CHV_CMN_DW1_CH1		0x8084
 #define   DPIO_AFC_RECAL		(1 << 14)
 #define   DPIO_DCLKP_EN			(1 << 13)
+#define   CHV_BUFLEFTENA2_DISABLE	(0 << 17) /* CL2 DW1 only */
+#define   CHV_BUFLEFTENA2_NORMAL	(1 << 17) /* CL2 DW1 only */
+#define   CHV_BUFLEFTENA2_FORCE		(3 << 17) /* CL2 DW1 only */
+#define   CHV_BUFLEFTENA2_MASK		(3 << 17) /* CL2 DW1 only */
+#define   CHV_BUFRIGHTENA2_DISABLE	(0 << 19) /* CL2 DW1 only */
+#define   CHV_BUFRIGHTENA2_NORMAL	(1 << 19) /* CL2 DW1 only */
+#define   CHV_BUFRIGHTENA2_FORCE	(3 << 19) /* CL2 DW1 only */
+#define   CHV_BUFRIGHTENA2_MASK		(3 << 19) /* CL2 DW1 only */
 #define CHV_CMN_DW14(ch) _PIPE(ch, _CHV_CMN_DW14_CH0, _CHV_CMN_DW1_CH1)
 
+#define _CHV_CMN_DW19_CH0		0x814c
+#define _CHV_CMN_DW6_CH1		0x8098
+#define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
+#define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1)
+
 #define CHV_CMN_DW30			0x8178
 #define   DPIO_LRC_BYPASS		(1 << 3)
 
@@ -933,6 +989,7 @@ enum punit_power_well {
 #define   SANDYBRIDGE_FENCE_PITCH_SHIFT	32
 #define   GEN7_FENCE_MAX_PITCH_VAL	0x0800
 
+
 /* control register for cpu gtt access */
 #define TILECTL				0x101000
 #define   TILECTL_SWZCTL			(1 << 0)
@@ -1170,6 +1227,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
@@ -1570,11 +1629,10 @@ enum punit_power_well {
 /*
  * Clock control & power management
  */
-#define DPLL_A_OFFSET 0x6014
-#define DPLL_B_OFFSET 0x6018
-#define CHV_DPLL_C_OFFSET 0x6030
-#define DPLL(pipe) (dev_priv->info.dpll_offsets[pipe] + \
-		    dev_priv->info.display_mmio_offset)
+#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
+#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
+#define _CHV_DPLL_C (dev_priv->info.display_mmio_offset + 0x6030)
+#define DPLL(pipe) _PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C)
 
 #define VGA0	0x6000
 #define VGA1	0x6004
@@ -1662,11 +1720,10 @@ enum punit_power_well {
 #define   SDVO_MULTIPLIER_SHIFT_HIRES		4
 #define   SDVO_MULTIPLIER_SHIFT_VGA		0
 
-#define DPLL_A_MD_OFFSET 0x601c /* 965+ only */
-#define DPLL_B_MD_OFFSET 0x6020 /* 965+ only */
-#define CHV_DPLL_C_MD_OFFSET 0x603c
-#define DPLL_MD(pipe) (dev_priv->info.dpll_md_offsets[pipe] + \
-		       dev_priv->info.display_mmio_offset)
+#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
+#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
+#define _CHV_DPLL_C_MD (dev_priv->info.display_mmio_offset + 0x603c)
+#define DPLL_MD(pipe) _PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD)
 
 /*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
@@ -2231,7 +2288,7 @@ enum punit_power_well {
 /* Same as Haswell, but 72064 bytes now. */
 #define GEN8_CXT_TOTAL_SIZE		(18 * PAGE_SIZE)
 
-
+#define CHV_CLK_CTL1			0x101100
 #define VLV_CLK_CTL2			0x101104
 #define   CLK_CTL2_CZCOUNT_30NS_SHIFT	28
 
@@ -2376,6 +2433,7 @@ enum punit_power_well {
 #define EDP_PSR_BASE(dev)                       (IS_HASWELL(dev) ? 0x64800 : 0x6f800)
 #define EDP_PSR_CTL(dev)			(EDP_PSR_BASE(dev) + 0)
 #define   EDP_PSR_ENABLE			(1<<31)
+#define   BDW_PSR_SINGLE_FRAME			(1<<30)
 #define   EDP_PSR_LINK_DISABLE			(0<<27)
 #define   EDP_PSR_LINK_STANDBY			(1<<27)
 #define   EDP_PSR_MIN_LINK_ENTRY_TIME_MASK	(3<<25)
@@ -2533,8 +2591,14 @@ enum punit_power_well {
 #define   PORTC_HOTPLUG_LIVE_STATUS_VLV		(1 << 28)
 #define   PORTB_HOTPLUG_LIVE_STATUS_VLV		(1 << 29)
 #define   PORTD_HOTPLUG_INT_STATUS		(3 << 21)
+#define   PORTD_HOTPLUG_INT_LONG_PULSE		(2 << 21)
+#define   PORTD_HOTPLUG_INT_SHORT_PULSE		(1 << 21)
 #define   PORTC_HOTPLUG_INT_STATUS		(3 << 19)
+#define   PORTC_HOTPLUG_INT_LONG_PULSE		(2 << 19)
+#define   PORTC_HOTPLUG_INT_SHORT_PULSE		(1 << 19)
 #define   PORTB_HOTPLUG_INT_STATUS		(3 << 17)
+#define   PORTB_HOTPLUG_INT_LONG_PULSE		(2 << 17)
+#define   PORTB_HOTPLUG_INT_SHORT_PLUSE		(1 << 17)
 /* CRT/TV common between gen3+ */
 #define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
 #define   TV_HOTPLUG_INT_STATUS			(1 << 10)
@@ -2588,7 +2652,7 @@ enum punit_power_well {
 
 #define PORT_DFT_I9XX				0x61150
 #define   DC_BALANCE_RESET			(1 << 25)
-#define PORT_DFT2_G4X				0x61154
+#define PORT_DFT2_G4X		(dev_priv->info.display_mmio_offset + 0x61154)
 #define   DC_BALANCE_RESET_VLV			(1 << 31)
 #define   PIPE_SCRAMBLE_RESET_MASK		(0x3 << 0)
 #define   PIPE_B_SCRAMBLE_RESET			(1 << 1)
@@ -3803,47 +3867,47 @@ enum punit_power_well {
 
 /* drain latency register values*/
 #define DRAIN_LATENCY_PRECISION_32	32
-#define DRAIN_LATENCY_PRECISION_16	16
+#define DRAIN_LATENCY_PRECISION_64	64
 #define VLV_DDL1			(VLV_DISPLAY_BASE + 0x70050)
-#define DDL_CURSORA_PRECISION_32	(1<<31)
-#define DDL_CURSORA_PRECISION_16	(0<<31)
+#define DDL_CURSORA_PRECISION_64	(1<<31)
+#define DDL_CURSORA_PRECISION_32	(0<<31)
 #define DDL_CURSORA_SHIFT		24
-#define DDL_SPRITEB_PRECISION_32	(1<<23)
-#define DDL_SPRITEB_PRECISION_16	(0<<23)
+#define DDL_SPRITEB_PRECISION_64	(1<<23)
+#define DDL_SPRITEB_PRECISION_32	(0<<23)
 #define DDL_SPRITEB_SHIFT		16
-#define DDL_SPRITEA_PRECISION_32	(1<<15)
-#define DDL_SPRITEA_PRECISION_16	(0<<15)
+#define DDL_SPRITEA_PRECISION_64	(1<<15)
+#define DDL_SPRITEA_PRECISION_32	(0<<15)
 #define DDL_SPRITEA_SHIFT		8
-#define DDL_PLANEA_PRECISION_32		(1<<7)
-#define DDL_PLANEA_PRECISION_16		(0<<7)
+#define DDL_PLANEA_PRECISION_64		(1<<7)
+#define DDL_PLANEA_PRECISION_32		(0<<7)
 #define DDL_PLANEA_SHIFT		0
 
 #define VLV_DDL2			(VLV_DISPLAY_BASE + 0x70054)
-#define DDL_CURSORB_PRECISION_32	(1<<31)
-#define DDL_CURSORB_PRECISION_16	(0<<31)
+#define DDL_CURSORB_PRECISION_64	(1<<31)
+#define DDL_CURSORB_PRECISION_32	(0<<31)
 #define DDL_CURSORB_SHIFT		24
-#define DDL_SPRITED_PRECISION_32	(1<<23)
-#define DDL_SPRITED_PRECISION_16	(0<<23)
+#define DDL_SPRITED_PRECISION_64	(1<<23)
+#define DDL_SPRITED_PRECISION_32	(0<<23)
 #define DDL_SPRITED_SHIFT		16
-#define DDL_SPRITEC_PRECISION_32	(1<<15)
-#define DDL_SPRITEC_PRECISION_16	(0<<15)
+#define DDL_SPRITEC_PRECISION_64	(1<<15)
+#define DDL_SPRITEC_PRECISION_32	(0<<15)
 #define DDL_SPRITEC_SHIFT		8
-#define DDL_PLANEB_PRECISION_32		(1<<7)
-#define DDL_PLANEB_PRECISION_16		(0<<7)
+#define DDL_PLANEB_PRECISION_64		(1<<7)
+#define DDL_PLANEB_PRECISION_32		(0<<7)
 #define DDL_PLANEB_SHIFT		0
 
 #define VLV_DDL3			(VLV_DISPLAY_BASE + 0x70058)
-#define DDL_CURSORC_PRECISION_32	(1<<31)
-#define DDL_CURSORC_PRECISION_16	(0<<31)
+#define DDL_CURSORC_PRECISION_64	(1<<31)
+#define DDL_CURSORC_PRECISION_32	(0<<31)
 #define DDL_CURSORC_SHIFT		24
-#define DDL_SPRITEF_PRECISION_32	(1<<23)
-#define DDL_SPRITEF_PRECISION_16	(0<<23)
+#define DDL_SPRITEF_PRECISION_64	(1<<23)
+#define DDL_SPRITEF_PRECISION_32	(0<<23)
 #define DDL_SPRITEF_SHIFT		16
-#define DDL_SPRITEE_PRECISION_32	(1<<15)
-#define DDL_SPRITEE_PRECISION_16	(0<<15)
+#define DDL_SPRITEE_PRECISION_64	(1<<15)
+#define DDL_SPRITEE_PRECISION_32	(0<<15)
 #define DDL_SPRITEE_SHIFT		8
-#define DDL_PLANEC_PRECISION_32		(1<<7)
-#define DDL_PLANEC_PRECISION_16		(0<<7)
+#define DDL_PLANEC_PRECISION_64		(1<<7)
+#define DDL_PLANEC_PRECISION_32		(0<<7)
 #define DDL_PLANEC_SHIFT		0
 
 /* FIFO watermark sizes etc */
@@ -4630,6 +4694,8 @@ enum punit_power_well {
 #define GEN7_L3CNTLREG1				0xB01C
 #define  GEN7_WA_FOR_GEN7_L3_CONTROL			0x3C47FF8C
 #define  GEN7_L3AGDIS				(1<<19)
+#define GEN7_L3CNTLREG2				0xB020
+#define GEN7_L3CNTLREG3				0xB024
 
 #define GEN7_L3_CHICKEN_MODE_REGISTER		0xB030
 #define  GEN7_WA_L3_CHICKEN_MODE				0x20000000
@@ -4876,8 +4942,7 @@ enum punit_power_well {
 #define _PCH_TRANSA_LINK_M2	0xe0048
 #define _PCH_TRANSA_LINK_N2	0xe004c
 
-/* Per-transcoder DIP controls */
-
+/* Per-transcoder DIP controls (PCH) */
 #define _VIDEO_DIP_CTL_A         0xe0200
 #define _VIDEO_DIP_DATA_A        0xe0208
 #define _VIDEO_DIP_GCP_A         0xe0210
@@ -4890,6 +4955,7 @@ enum punit_power_well {
 #define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
 #define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
 
+/* Per-transcoder DIP controls (VLV) */
 #define VLV_VIDEO_DIP_CTL_A		(VLV_DISPLAY_BASE + 0x60200)
 #define VLV_VIDEO_DIP_DATA_A		(VLV_DISPLAY_BASE + 0x60208)
 #define VLV_VIDEO_DIP_GDCP_PAYLOAD_A	(VLV_DISPLAY_BASE + 0x60210)
@@ -4898,12 +4964,19 @@ enum punit_power_well {
 #define VLV_VIDEO_DIP_DATA_B		(VLV_DISPLAY_BASE + 0x61174)
 #define VLV_VIDEO_DIP_GDCP_PAYLOAD_B	(VLV_DISPLAY_BASE + 0x61178)
 
+#define CHV_VIDEO_DIP_CTL_C		(VLV_DISPLAY_BASE + 0x611f0)
+#define CHV_VIDEO_DIP_DATA_C		(VLV_DISPLAY_BASE + 0x611f4)
+#define CHV_VIDEO_DIP_GDCP_PAYLOAD_C	(VLV_DISPLAY_BASE + 0x611f8)
+
 #define VLV_TVIDEO_DIP_CTL(pipe) \
-	 _PIPE(pipe, VLV_VIDEO_DIP_CTL_A, VLV_VIDEO_DIP_CTL_B)
+	_PIPE3((pipe), VLV_VIDEO_DIP_CTL_A, \
+	       VLV_VIDEO_DIP_CTL_B, CHV_VIDEO_DIP_CTL_C)
 #define VLV_TVIDEO_DIP_DATA(pipe) \
-	 _PIPE(pipe, VLV_VIDEO_DIP_DATA_A, VLV_VIDEO_DIP_DATA_B)
+	_PIPE3((pipe), VLV_VIDEO_DIP_DATA_A, \
+	       VLV_VIDEO_DIP_DATA_B, CHV_VIDEO_DIP_DATA_C)
 #define VLV_TVIDEO_DIP_GCP(pipe) \
-	_PIPE(pipe, VLV_VIDEO_DIP_GDCP_PAYLOAD_A, VLV_VIDEO_DIP_GDCP_PAYLOAD_B)
+	_PIPE3((pipe), VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \
+		VLV_VIDEO_DIP_GDCP_PAYLOAD_B, CHV_VIDEO_DIP_GDCP_PAYLOAD_C)
 
 /* Haswell DIP controls */
 #define HSW_VIDEO_DIP_CTL_A		0x60200
@@ -5334,6 +5407,7 @@ enum punit_power_well {
 #define   VLV_GTLC_ALLOWWAKEERR			(1 << 1)
 #define   VLV_GTLC_PW_MEDIA_STATUS_MASK		(1 << 5)
 #define   VLV_GTLC_PW_RENDER_STATUS_MASK	(1 << 7)
+#define VLV_GTLC_SURVIVABILITY_REG              0x130098
 #define  FORCEWAKE_MT				0xa188 /* multi-threaded */
 #define   FORCEWAKE_KERNEL			0x1
 #define   FORCEWAKE_USER			0x2
@@ -5471,6 +5545,12 @@ enum punit_power_well {
 						 GEN6_PM_RP_DOWN_THRESHOLD | \
 						 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define CHV_CZ_CLOCK_FREQ_MODE_200			200
+#define CHV_CZ_CLOCK_FREQ_MODE_267			267
+#define CHV_CZ_CLOCK_FREQ_MODE_320			320
+#define CHV_CZ_CLOCK_FREQ_MODE_333			333
+#define CHV_CZ_CLOCK_FREQ_MODE_400			400
+
 #define GEN7_GT_SCRATCH_BASE			0x4F100
 #define GEN7_GT_SCRATCH_REG_NUM			8
 
@@ -5481,6 +5561,8 @@ enum punit_power_well {
 #define GEN6_GT_GFX_RC6_LOCKED			0x138104
 #define VLV_COUNTER_CONTROL			0x138104
 #define   VLV_COUNT_RANGE_HIGH			(1<<15)
+#define   VLV_MEDIA_RC0_COUNT_EN		(1<<5)
+#define   VLV_RENDER_RC0_COUNT_EN		(1<<4)
 #define   VLV_MEDIA_RC6_COUNT_EN		(1<<1)
 #define   VLV_RENDER_RC6_COUNT_EN		(1<<0)
 #define GEN6_GT_GFX_RC6				0x138108
@@ -5489,6 +5571,8 @@ enum punit_power_well {
 
 #define GEN6_GT_GFX_RC6p			0x13810C
 #define GEN6_GT_GFX_RC6pp			0x138110
+#define VLV_RENDER_C0_COUNT_REG		0x138118
+#define VLV_MEDIA_C0_COUNT_REG			0x13811C
 
 #define GEN6_PCODE_MAILBOX			0x138124
 #define   GEN6_PCODE_READY			(1<<31)
@@ -5723,6 +5807,7 @@ enum punit_power_well {
 #define  TRANS_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
 #define  TRANS_DDI_PORT_MASK		(7<<28)
+#define  TRANS_DDI_PORT_SHIFT		28
 #define  TRANS_DDI_SELECT_PORT(x)	((x)<<28)
 #define  TRANS_DDI_PORT_NONE		(0<<28)
 #define  TRANS_DDI_MODE_SELECT_MASK	(7<<24)
@@ -5743,6 +5828,7 @@ enum punit_power_well {
 #define  TRANS_DDI_EDP_INPUT_A_ONOFF	(4<<12)
 #define  TRANS_DDI_EDP_INPUT_B_ONOFF	(5<<12)
 #define  TRANS_DDI_EDP_INPUT_C_ONOFF	(6<<12)
+#define  TRANS_DDI_DP_VC_PAYLOAD_ALLOC	(1<<8)
 #define  TRANS_DDI_BFI_ENABLE		(1<<4)
 
 /* DisplayPort Transport Control */
@@ -5752,6 +5838,7 @@ enum punit_power_well {
 #define  DP_TP_CTL_ENABLE			(1<<31)
 #define  DP_TP_CTL_MODE_SST			(0<<27)
 #define  DP_TP_CTL_MODE_MST			(1<<27)
+#define  DP_TP_CTL_FORCE_ACT			(1<<25)
 #define  DP_TP_CTL_ENHANCED_FRAME_ENABLE	(1<<18)
 #define  DP_TP_CTL_FDI_AUTOTRAIN		(1<<15)
 #define  DP_TP_CTL_LINK_TRAIN_MASK		(7<<8)
@@ -5766,15 +5853,19 @@ enum punit_power_well {
 #define DP_TP_STATUS_A			0x64044
 #define DP_TP_STATUS_B			0x64144
 #define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
-#define  DP_TP_STATUS_IDLE_DONE		(1<<25)
-#define  DP_TP_STATUS_AUTOTRAIN_DONE	(1<<12)
+#define  DP_TP_STATUS_IDLE_DONE			(1<<25)
+#define  DP_TP_STATUS_ACT_SENT			(1<<24)
+#define  DP_TP_STATUS_MODE_STATUS_MST		(1<<23)
+#define  DP_TP_STATUS_AUTOTRAIN_DONE		(1<<12)
+#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC2	(3 << 8)
+#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC1	(3 << 4)
+#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC0	(3 << 0)
 
 /* DDI Buffer Control */
 #define DDI_BUF_CTL_A				0x64000
 #define DDI_BUF_CTL_B				0x64100
 #define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B)
 #define  DDI_BUF_CTL_ENABLE			(1<<31)
-/* Haswell */
 #define  DDI_BUF_EMP_400MV_0DB_HSW		(0<<24)   /* Sel0 */
 #define  DDI_BUF_EMP_400MV_3_5DB_HSW		(1<<24)   /* Sel1 */
 #define  DDI_BUF_EMP_400MV_6DB_HSW		(2<<24)   /* Sel2 */
@@ -5784,16 +5875,6 @@ enum punit_power_well {
 #define  DDI_BUF_EMP_600MV_6DB_HSW		(6<<24)   /* Sel6 */
 #define  DDI_BUF_EMP_800MV_0DB_HSW		(7<<24)   /* Sel7 */
 #define  DDI_BUF_EMP_800MV_3_5DB_HSW		(8<<24)   /* Sel8 */
-/* Broadwell */
-#define  DDI_BUF_EMP_400MV_0DB_BDW		(0<<24)   /* Sel0 */
-#define  DDI_BUF_EMP_400MV_3_5DB_BDW		(1<<24)   /* Sel1 */
-#define  DDI_BUF_EMP_400MV_6DB_BDW		(2<<24)   /* Sel2 */
-#define  DDI_BUF_EMP_600MV_0DB_BDW		(3<<24)   /* Sel3 */
-#define  DDI_BUF_EMP_600MV_3_5DB_BDW		(4<<24)   /* Sel4 */
-#define  DDI_BUF_EMP_600MV_6DB_BDW		(5<<24)   /* Sel5 */
-#define  DDI_BUF_EMP_800MV_0DB_BDW		(6<<24)   /* Sel6 */
-#define  DDI_BUF_EMP_800MV_3_5DB_BDW		(7<<24)   /* Sel7 */
-#define  DDI_BUF_EMP_1200MV_0DB_BDW		(8<<24)   /* Sel8 */
 #define  DDI_BUF_EMP_MASK			(0xf<<24)
 #define  DDI_BUF_PORT_REVERSAL			(1<<16)
 #define  DDI_BUF_IS_IDLE			(1<<7)
@@ -5861,10 +5942,12 @@ enum punit_power_well {
 /* WRPLL */
 #define WRPLL_CTL1			0x46040
 #define WRPLL_CTL2			0x46060
+#define WRPLL_CTL(pll)			(pll == 0 ? WRPLL_CTL1 : WRPLL_CTL2)
 #define  WRPLL_PLL_ENABLE		(1<<31)
-#define  WRPLL_PLL_SELECT_SSC		(0x01<<28)
-#define  WRPLL_PLL_SELECT_NON_SSC	(0x02<<28)
-#define  WRPLL_PLL_SELECT_LCPLL_2700	(0x03<<28)
+#define  WRPLL_PLL_SSC			(1<<28)
+#define  WRPLL_PLL_NON_SSC		(2<<28)
+#define  WRPLL_PLL_LCPLL		(3<<28)
+#define  WRPLL_PLL_REF_MASK		(3<<28)
 /* WRPLL divider programming */
 #define  WRPLL_DIVIDER_REFERENCE(x)	((x)<<0)
 #define  WRPLL_DIVIDER_REF_MASK		(0xff)
@@ -5883,6 +5966,7 @@ enum punit_power_well {
 #define  PORT_CLK_SEL_LCPLL_1350	(1<<29)
 #define  PORT_CLK_SEL_LCPLL_810		(2<<29)
 #define  PORT_CLK_SEL_SPLL		(3<<29)
+#define  PORT_CLK_SEL_WRPLL(pll)	(((pll)+4)<<29)
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
 #define  PORT_CLK_SEL_NONE		(7<<29)
@@ -5924,7 +6008,10 @@ enum punit_power_well {
 #define  LCPLL_CD_SOURCE_FCLK		(1<<21)
 #define  LCPLL_CD_SOURCE_FCLK_DONE	(1<<19)
 
-#define D_COMP				(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+/* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
+ * since on HSW we can't write to it using I915_WRITE. */
+#define D_COMP_HSW			(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+#define D_COMP_BDW			0x138144
 #define  D_COMP_RCOMP_IN_PROGRESS	(1<<9)
 #define  D_COMP_COMP_FORCE		(1<<8)
 #define  D_COMP_COMP_DISABLE		(1<<0)
@@ -6005,7 +6092,8 @@ enum punit_power_well {
 
 #define _MIPIA_PORT_CTRL			(VLV_DISPLAY_BASE + 0x61190)
 #define _MIPIB_PORT_CTRL			(VLV_DISPLAY_BASE + 0x61700)
-#define MIPI_PORT_CTRL(pipe)		_PIPE(pipe, _MIPIA_PORT_CTRL, _MIPIB_PORT_CTRL)
+#define MIPI_PORT_CTRL(tc)		_TRANSCODER(tc, _MIPIA_PORT_CTRL, \
+						_MIPIB_PORT_CTRL)
 #define  DPI_ENABLE					(1 << 31) /* A + B */
 #define  MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT		27
 #define  MIPIA_MIPI4DPHY_DELAY_COUNT_MASK		(0xf << 27)
@@ -6047,18 +6135,20 @@ enum punit_power_well {
 
 #define _MIPIA_TEARING_CTRL			(VLV_DISPLAY_BASE + 0x61194)
 #define _MIPIB_TEARING_CTRL			(VLV_DISPLAY_BASE + 0x61704)
-#define MIPI_TEARING_CTRL(pipe)		_PIPE(pipe, _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL)
+#define MIPI_TEARING_CTRL(tc)			_TRANSCODER(tc, \
+				_MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL)
 #define  TEARING_EFFECT_DELAY_SHIFT			0
 #define  TEARING_EFFECT_DELAY_MASK			(0xffff << 0)
 
 /* XXX: all bits reserved */
-#define _MIPIA_AUTOPWG				(VLV_DISPLAY_BASE + 0x611a0)
+#define _MIPIA_AUTOPWG			(VLV_DISPLAY_BASE + 0x611a0)
 
 /* MIPI DSI Controller and D-PHY registers */
 
-#define _MIPIA_DEVICE_READY			(VLV_DISPLAY_BASE + 0xb000)
-#define _MIPIB_DEVICE_READY			(VLV_DISPLAY_BASE + 0xb800)
-#define MIPI_DEVICE_READY(pipe)		_PIPE(pipe, _MIPIA_DEVICE_READY, _MIPIB_DEVICE_READY)
+#define _MIPIA_DEVICE_READY		(dev_priv->mipi_mmio_base + 0xb000)
+#define _MIPIB_DEVICE_READY		(dev_priv->mipi_mmio_base + 0xb800)
+#define MIPI_DEVICE_READY(tc)		_TRANSCODER(tc, _MIPIA_DEVICE_READY, \
+						_MIPIB_DEVICE_READY)
 #define  BUS_POSSESSION					(1 << 3) /* set to give bus to receiver */
 #define  ULPS_STATE_MASK				(3 << 1)
 #define  ULPS_STATE_ENTER				(2 << 1)
@@ -6066,12 +6156,14 @@ enum punit_power_well {
 #define  ULPS_STATE_NORMAL_OPERATION			(0 << 1)
 #define  DEVICE_READY					(1 << 0)
 
-#define _MIPIA_INTR_STAT			(VLV_DISPLAY_BASE + 0xb004)
-#define _MIPIB_INTR_STAT			(VLV_DISPLAY_BASE + 0xb804)
-#define MIPI_INTR_STAT(pipe)		_PIPE(pipe, _MIPIA_INTR_STAT, _MIPIB_INTR_STAT)
-#define _MIPIA_INTR_EN				(VLV_DISPLAY_BASE + 0xb008)
-#define _MIPIB_INTR_EN				(VLV_DISPLAY_BASE + 0xb808)
-#define MIPI_INTR_EN(pipe)		_PIPE(pipe, _MIPIA_INTR_EN, _MIPIB_INTR_EN)
+#define _MIPIA_INTR_STAT		(dev_priv->mipi_mmio_base + 0xb004)
+#define _MIPIB_INTR_STAT		(dev_priv->mipi_mmio_base + 0xb804)
+#define MIPI_INTR_STAT(tc)		_TRANSCODER(tc, _MIPIA_INTR_STAT, \
+					_MIPIB_INTR_STAT)
+#define _MIPIA_INTR_EN			(dev_priv->mipi_mmio_base + 0xb008)
+#define _MIPIB_INTR_EN			(dev_priv->mipi_mmio_base + 0xb808)
+#define MIPI_INTR_EN(tc)		_TRANSCODER(tc, _MIPIA_INTR_EN, \
+					_MIPIB_INTR_EN)
 #define  TEARING_EFFECT					(1 << 31)
 #define  SPL_PKT_SENT_INTERRUPT				(1 << 30)
 #define  GEN_READ_DATA_AVAIL				(1 << 29)
@@ -6105,9 +6197,10 @@ enum punit_power_well {
 #define  RXSOT_SYNC_ERROR				(1 << 1)
 #define  RXSOT_ERROR					(1 << 0)
 
-#define _MIPIA_DSI_FUNC_PRG			(VLV_DISPLAY_BASE + 0xb00c)
-#define _MIPIB_DSI_FUNC_PRG			(VLV_DISPLAY_BASE + 0xb80c)
-#define MIPI_DSI_FUNC_PRG(pipe)		_PIPE(pipe, _MIPIA_DSI_FUNC_PRG, _MIPIB_DSI_FUNC_PRG)
+#define _MIPIA_DSI_FUNC_PRG		(dev_priv->mipi_mmio_base + 0xb00c)
+#define _MIPIB_DSI_FUNC_PRG		(dev_priv->mipi_mmio_base + 0xb80c)
+#define MIPI_DSI_FUNC_PRG(tc)		_TRANSCODER(tc, _MIPIA_DSI_FUNC_PRG, \
+						_MIPIB_DSI_FUNC_PRG)
 #define  CMD_MODE_DATA_WIDTH_MASK			(7 << 13)
 #define  CMD_MODE_NOT_SUPPORTED				(0 << 13)
 #define  CMD_MODE_DATA_WIDTH_16_BIT			(1 << 13)
@@ -6128,78 +6221,94 @@ enum punit_power_well {
 #define  DATA_LANES_PRG_REG_SHIFT			0
 #define  DATA_LANES_PRG_REG_MASK			(7 << 0)
 
-#define _MIPIA_HS_TX_TIMEOUT			(VLV_DISPLAY_BASE + 0xb010)
-#define _MIPIB_HS_TX_TIMEOUT			(VLV_DISPLAY_BASE + 0xb810)
-#define MIPI_HS_TX_TIMEOUT(pipe)	_PIPE(pipe, _MIPIA_HS_TX_TIMEOUT, _MIPIB_HS_TX_TIMEOUT)
+#define _MIPIA_HS_TX_TIMEOUT		(dev_priv->mipi_mmio_base + 0xb010)
+#define _MIPIB_HS_TX_TIMEOUT		(dev_priv->mipi_mmio_base + 0xb810)
+#define MIPI_HS_TX_TIMEOUT(tc)	_TRANSCODER(tc, _MIPIA_HS_TX_TIMEOUT, \
+					_MIPIB_HS_TX_TIMEOUT)
 #define  HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK		0xffffff
 
-#define _MIPIA_LP_RX_TIMEOUT			(VLV_DISPLAY_BASE + 0xb014)
-#define _MIPIB_LP_RX_TIMEOUT			(VLV_DISPLAY_BASE + 0xb814)
-#define MIPI_LP_RX_TIMEOUT(pipe)	_PIPE(pipe, _MIPIA_LP_RX_TIMEOUT, _MIPIB_LP_RX_TIMEOUT)
+#define _MIPIA_LP_RX_TIMEOUT		(dev_priv->mipi_mmio_base + 0xb014)
+#define _MIPIB_LP_RX_TIMEOUT		(dev_priv->mipi_mmio_base + 0xb814)
+#define MIPI_LP_RX_TIMEOUT(tc)	_TRANSCODER(tc, _MIPIA_LP_RX_TIMEOUT, \
+					_MIPIB_LP_RX_TIMEOUT)
 #define  LOW_POWER_RX_TIMEOUT_COUNTER_MASK		0xffffff
 
-#define _MIPIA_TURN_AROUND_TIMEOUT		(VLV_DISPLAY_BASE + 0xb018)
-#define _MIPIB_TURN_AROUND_TIMEOUT		(VLV_DISPLAY_BASE + 0xb818)
-#define MIPI_TURN_AROUND_TIMEOUT(pipe)	_PIPE(pipe, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT)
+#define _MIPIA_TURN_AROUND_TIMEOUT	(dev_priv->mipi_mmio_base + 0xb018)
+#define _MIPIB_TURN_AROUND_TIMEOUT	(dev_priv->mipi_mmio_base + 0xb818)
+#define MIPI_TURN_AROUND_TIMEOUT(tc)	_TRANSCODER(tc, \
+			_MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT)
 #define  TURN_AROUND_TIMEOUT_MASK			0x3f
 
-#define _MIPIA_DEVICE_RESET_TIMER		(VLV_DISPLAY_BASE + 0xb01c)
-#define _MIPIB_DEVICE_RESET_TIMER		(VLV_DISPLAY_BASE + 0xb81c)
-#define MIPI_DEVICE_RESET_TIMER(pipe)	_PIPE(pipe, _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER)
+#define _MIPIA_DEVICE_RESET_TIMER	(dev_priv->mipi_mmio_base + 0xb01c)
+#define _MIPIB_DEVICE_RESET_TIMER	(dev_priv->mipi_mmio_base + 0xb81c)
+#define MIPI_DEVICE_RESET_TIMER(tc)	_TRANSCODER(tc, \
+			_MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER)
 #define  DEVICE_RESET_TIMER_MASK			0xffff
 
-#define _MIPIA_DPI_RESOLUTION			(VLV_DISPLAY_BASE + 0xb020)
-#define _MIPIB_DPI_RESOLUTION			(VLV_DISPLAY_BASE + 0xb820)
-#define MIPI_DPI_RESOLUTION(pipe)	_PIPE(pipe, _MIPIA_DPI_RESOLUTION, _MIPIB_DPI_RESOLUTION)
+#define _MIPIA_DPI_RESOLUTION		(dev_priv->mipi_mmio_base + 0xb020)
+#define _MIPIB_DPI_RESOLUTION		(dev_priv->mipi_mmio_base + 0xb820)
+#define MIPI_DPI_RESOLUTION(tc)	_TRANSCODER(tc, _MIPIA_DPI_RESOLUTION, \
+					_MIPIB_DPI_RESOLUTION)
 #define  VERTICAL_ADDRESS_SHIFT				16
 #define  VERTICAL_ADDRESS_MASK				(0xffff << 16)
 #define  HORIZONTAL_ADDRESS_SHIFT			0
 #define  HORIZONTAL_ADDRESS_MASK			0xffff
 
-#define _MIPIA_DBI_FIFO_THROTTLE		(VLV_DISPLAY_BASE + 0xb024)
-#define _MIPIB_DBI_FIFO_THROTTLE		(VLV_DISPLAY_BASE + 0xb824)
-#define MIPI_DBI_FIFO_THROTTLE(pipe)	_PIPE(pipe, _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE)
+#define _MIPIA_DBI_FIFO_THROTTLE	(dev_priv->mipi_mmio_base + 0xb024)
+#define _MIPIB_DBI_FIFO_THROTTLE	(dev_priv->mipi_mmio_base + 0xb824)
+#define MIPI_DBI_FIFO_THROTTLE(tc)	_TRANSCODER(tc, \
+			_MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE)
 #define  DBI_FIFO_EMPTY_HALF				(0 << 0)
 #define  DBI_FIFO_EMPTY_QUARTER				(1 << 0)
 #define  DBI_FIFO_EMPTY_7_LOCATIONS			(2 << 0)
 
 /* regs below are bits 15:0 */
-#define _MIPIA_HSYNC_PADDING_COUNT		(VLV_DISPLAY_BASE + 0xb028)
-#define _MIPIB_HSYNC_PADDING_COUNT		(VLV_DISPLAY_BASE + 0xb828)
-#define MIPI_HSYNC_PADDING_COUNT(pipe)	_PIPE(pipe, _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT)
+#define _MIPIA_HSYNC_PADDING_COUNT	(dev_priv->mipi_mmio_base + 0xb028)
+#define _MIPIB_HSYNC_PADDING_COUNT	(dev_priv->mipi_mmio_base + 0xb828)
+#define MIPI_HSYNC_PADDING_COUNT(tc)	_TRANSCODER(tc, \
+			_MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT)
 
-#define _MIPIA_HBP_COUNT			(VLV_DISPLAY_BASE + 0xb02c)
-#define _MIPIB_HBP_COUNT			(VLV_DISPLAY_BASE + 0xb82c)
-#define MIPI_HBP_COUNT(pipe)		_PIPE(pipe, _MIPIA_HBP_COUNT, _MIPIB_HBP_COUNT)
+#define _MIPIA_HBP_COUNT		(dev_priv->mipi_mmio_base + 0xb02c)
+#define _MIPIB_HBP_COUNT		(dev_priv->mipi_mmio_base + 0xb82c)
+#define MIPI_HBP_COUNT(tc)		_TRANSCODER(tc, _MIPIA_HBP_COUNT, \
+					_MIPIB_HBP_COUNT)
 
-#define _MIPIA_HFP_COUNT			(VLV_DISPLAY_BASE + 0xb030)
-#define _MIPIB_HFP_COUNT			(VLV_DISPLAY_BASE + 0xb830)
-#define MIPI_HFP_COUNT(pipe)		_PIPE(pipe, _MIPIA_HFP_COUNT, _MIPIB_HFP_COUNT)
+#define _MIPIA_HFP_COUNT		(dev_priv->mipi_mmio_base + 0xb030)
+#define _MIPIB_HFP_COUNT		(dev_priv->mipi_mmio_base + 0xb830)
+#define MIPI_HFP_COUNT(tc)		_TRANSCODER(tc, _MIPIA_HFP_COUNT, \
+					_MIPIB_HFP_COUNT)
 
-#define _MIPIA_HACTIVE_AREA_COUNT		(VLV_DISPLAY_BASE + 0xb034)
-#define _MIPIB_HACTIVE_AREA_COUNT		(VLV_DISPLAY_BASE + 0xb834)
-#define MIPI_HACTIVE_AREA_COUNT(pipe)	_PIPE(pipe, _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT)
+#define _MIPIA_HACTIVE_AREA_COUNT	(dev_priv->mipi_mmio_base + 0xb034)
+#define _MIPIB_HACTIVE_AREA_COUNT	(dev_priv->mipi_mmio_base + 0xb834)
+#define MIPI_HACTIVE_AREA_COUNT(tc)	_TRANSCODER(tc, \
+			_MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT)
 
-#define _MIPIA_VSYNC_PADDING_COUNT		(VLV_DISPLAY_BASE + 0xb038)
-#define _MIPIB_VSYNC_PADDING_COUNT		(VLV_DISPLAY_BASE + 0xb838)
-#define MIPI_VSYNC_PADDING_COUNT(pipe)	_PIPE(pipe, _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT)
+#define _MIPIA_VSYNC_PADDING_COUNT	(dev_priv->mipi_mmio_base + 0xb038)
+#define _MIPIB_VSYNC_PADDING_COUNT	(dev_priv->mipi_mmio_base + 0xb838)
+#define MIPI_VSYNC_PADDING_COUNT(tc)	_TRANSCODER(tc, \
+			_MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT)
 
-#define _MIPIA_VBP_COUNT			(VLV_DISPLAY_BASE + 0xb03c)
-#define _MIPIB_VBP_COUNT			(VLV_DISPLAY_BASE + 0xb83c)
-#define MIPI_VBP_COUNT(pipe)		_PIPE(pipe, _MIPIA_VBP_COUNT, _MIPIB_VBP_COUNT)
+#define _MIPIA_VBP_COUNT		(dev_priv->mipi_mmio_base + 0xb03c)
+#define _MIPIB_VBP_COUNT		(dev_priv->mipi_mmio_base + 0xb83c)
+#define MIPI_VBP_COUNT(tc)		_TRANSCODER(tc, _MIPIA_VBP_COUNT, \
+					_MIPIB_VBP_COUNT)
 
-#define _MIPIA_VFP_COUNT			(VLV_DISPLAY_BASE + 0xb040)
-#define _MIPIB_VFP_COUNT			(VLV_DISPLAY_BASE + 0xb840)
-#define MIPI_VFP_COUNT(pipe)		_PIPE(pipe, _MIPIA_VFP_COUNT, _MIPIB_VFP_COUNT)
+#define _MIPIA_VFP_COUNT		(dev_priv->mipi_mmio_base + 0xb040)
+#define _MIPIB_VFP_COUNT		(dev_priv->mipi_mmio_base + 0xb840)
+#define MIPI_VFP_COUNT(tc)		_TRANSCODER(tc, _MIPIA_VFP_COUNT, \
+					_MIPIB_VFP_COUNT)
+
+#define _MIPIA_HIGH_LOW_SWITCH_COUNT	(dev_priv->mipi_mmio_base + 0xb044)
+#define _MIPIB_HIGH_LOW_SWITCH_COUNT	(dev_priv->mipi_mmio_base + 0xb844)
+#define MIPI_HIGH_LOW_SWITCH_COUNT(tc)	_TRANSCODER(tc,	\
+		_MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT)
 
-#define _MIPIA_HIGH_LOW_SWITCH_COUNT		(VLV_DISPLAY_BASE + 0xb044)
-#define _MIPIB_HIGH_LOW_SWITCH_COUNT		(VLV_DISPLAY_BASE + 0xb844)
-#define MIPI_HIGH_LOW_SWITCH_COUNT(pipe)	_PIPE(pipe, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT)
 /* regs above are bits 15:0 */
 
-#define _MIPIA_DPI_CONTROL			(VLV_DISPLAY_BASE + 0xb048)
-#define _MIPIB_DPI_CONTROL			(VLV_DISPLAY_BASE + 0xb848)
-#define MIPI_DPI_CONTROL(pipe)		_PIPE(pipe, _MIPIA_DPI_CONTROL, _MIPIB_DPI_CONTROL)
+#define _MIPIA_DPI_CONTROL		(dev_priv->mipi_mmio_base + 0xb048)
+#define _MIPIB_DPI_CONTROL		(dev_priv->mipi_mmio_base + 0xb848)
+#define MIPI_DPI_CONTROL(tc)		_TRANSCODER(tc, _MIPIA_DPI_CONTROL, \
+					_MIPIB_DPI_CONTROL)
 #define  DPI_LP_MODE					(1 << 6)
 #define  BACKLIGHT_OFF					(1 << 5)
 #define  BACKLIGHT_ON					(1 << 4)
@@ -6208,27 +6317,31 @@ enum punit_power_well {
 #define  TURN_ON					(1 << 1)
 #define  SHUTDOWN					(1 << 0)
 
-#define _MIPIA_DPI_DATA				(VLV_DISPLAY_BASE + 0xb04c)
-#define _MIPIB_DPI_DATA				(VLV_DISPLAY_BASE + 0xb84c)
-#define MIPI_DPI_DATA(pipe)		_PIPE(pipe, _MIPIA_DPI_DATA, _MIPIB_DPI_DATA)
+#define _MIPIA_DPI_DATA			(dev_priv->mipi_mmio_base + 0xb04c)
+#define _MIPIB_DPI_DATA			(dev_priv->mipi_mmio_base + 0xb84c)
+#define MIPI_DPI_DATA(tc)		_TRANSCODER(tc, _MIPIA_DPI_DATA, \
+					_MIPIB_DPI_DATA)
 #define  COMMAND_BYTE_SHIFT				0
 #define  COMMAND_BYTE_MASK				(0x3f << 0)
 
-#define _MIPIA_INIT_COUNT			(VLV_DISPLAY_BASE + 0xb050)
-#define _MIPIB_INIT_COUNT			(VLV_DISPLAY_BASE + 0xb850)
-#define MIPI_INIT_COUNT(pipe)		_PIPE(pipe, _MIPIA_INIT_COUNT, _MIPIB_INIT_COUNT)
+#define _MIPIA_INIT_COUNT		(dev_priv->mipi_mmio_base + 0xb050)
+#define _MIPIB_INIT_COUNT		(dev_priv->mipi_mmio_base + 0xb850)
+#define MIPI_INIT_COUNT(tc)		_TRANSCODER(tc, _MIPIA_INIT_COUNT, \
+					_MIPIB_INIT_COUNT)
 #define  MASTER_INIT_TIMER_SHIFT			0
 #define  MASTER_INIT_TIMER_MASK				(0xffff << 0)
 
-#define _MIPIA_MAX_RETURN_PKT_SIZE		(VLV_DISPLAY_BASE + 0xb054)
-#define _MIPIB_MAX_RETURN_PKT_SIZE		(VLV_DISPLAY_BASE + 0xb854)
-#define MIPI_MAX_RETURN_PKT_SIZE(pipe)	_PIPE(pipe, _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE)
+#define _MIPIA_MAX_RETURN_PKT_SIZE	(dev_priv->mipi_mmio_base + 0xb054)
+#define _MIPIB_MAX_RETURN_PKT_SIZE	(dev_priv->mipi_mmio_base + 0xb854)
+#define MIPI_MAX_RETURN_PKT_SIZE(tc)	_TRANSCODER(tc, \
+			_MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE)
 #define  MAX_RETURN_PKT_SIZE_SHIFT			0
 #define  MAX_RETURN_PKT_SIZE_MASK			(0x3ff << 0)
 
-#define _MIPIA_VIDEO_MODE_FORMAT		(VLV_DISPLAY_BASE + 0xb058)
-#define _MIPIB_VIDEO_MODE_FORMAT		(VLV_DISPLAY_BASE + 0xb858)
-#define MIPI_VIDEO_MODE_FORMAT(pipe)	_PIPE(pipe, _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT)
+#define _MIPIA_VIDEO_MODE_FORMAT	(dev_priv->mipi_mmio_base + 0xb058)
+#define _MIPIB_VIDEO_MODE_FORMAT	(dev_priv->mipi_mmio_base + 0xb858)
+#define MIPI_VIDEO_MODE_FORMAT(tc)	_TRANSCODER(tc, \
+			_MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT)
 #define  RANDOM_DPI_DISPLAY_RESOLUTION			(1 << 4)
 #define  DISABLE_VIDEO_BTA				(1 << 3)
 #define  IP_TG_CONFIG					(1 << 2)
@@ -6236,9 +6349,10 @@ enum punit_power_well {
 #define  VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS		(2 << 0)
 #define  VIDEO_MODE_BURST				(3 << 0)
 
-#define _MIPIA_EOT_DISABLE			(VLV_DISPLAY_BASE + 0xb05c)
-#define _MIPIB_EOT_DISABLE			(VLV_DISPLAY_BASE + 0xb85c)
-#define MIPI_EOT_DISABLE(pipe)		_PIPE(pipe, _MIPIA_EOT_DISABLE, _MIPIB_EOT_DISABLE)
+#define _MIPIA_EOT_DISABLE		(dev_priv->mipi_mmio_base + 0xb05c)
+#define _MIPIB_EOT_DISABLE		(dev_priv->mipi_mmio_base + 0xb85c)
+#define MIPI_EOT_DISABLE(tc)		_TRANSCODER(tc, _MIPIA_EOT_DISABLE, \
+					_MIPIB_EOT_DISABLE)
 #define  LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE		(1 << 7)
 #define  HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE		(1 << 6)
 #define  LOW_CONTENTION_RECOVERY_DISABLE		(1 << 5)
@@ -6248,28 +6362,33 @@ enum punit_power_well {
 #define  CLOCKSTOP					(1 << 1)
 #define  EOT_DISABLE					(1 << 0)
 
-#define _MIPIA_LP_BYTECLK			(VLV_DISPLAY_BASE + 0xb060)
-#define _MIPIB_LP_BYTECLK			(VLV_DISPLAY_BASE + 0xb860)
-#define MIPI_LP_BYTECLK(pipe)		_PIPE(pipe, _MIPIA_LP_BYTECLK, _MIPIB_LP_BYTECLK)
+#define _MIPIA_LP_BYTECLK		(dev_priv->mipi_mmio_base + 0xb060)
+#define _MIPIB_LP_BYTECLK		(dev_priv->mipi_mmio_base + 0xb860)
+#define MIPI_LP_BYTECLK(tc)		_TRANSCODER(tc, _MIPIA_LP_BYTECLK, \
+					_MIPIB_LP_BYTECLK)
 #define  LP_BYTECLK_SHIFT				0
 #define  LP_BYTECLK_MASK				(0xffff << 0)
 
 /* bits 31:0 */
-#define _MIPIA_LP_GEN_DATA			(VLV_DISPLAY_BASE + 0xb064)
-#define _MIPIB_LP_GEN_DATA			(VLV_DISPLAY_BASE + 0xb864)
-#define MIPI_LP_GEN_DATA(pipe)		_PIPE(pipe, _MIPIA_LP_GEN_DATA, _MIPIB_LP_GEN_DATA)
+#define _MIPIA_LP_GEN_DATA		(dev_priv->mipi_mmio_base + 0xb064)
+#define _MIPIB_LP_GEN_DATA		(dev_priv->mipi_mmio_base + 0xb864)
+#define MIPI_LP_GEN_DATA(tc)		_TRANSCODER(tc, _MIPIA_LP_GEN_DATA, \
+					_MIPIB_LP_GEN_DATA)
 
 /* bits 31:0 */
-#define _MIPIA_HS_GEN_DATA			(VLV_DISPLAY_BASE + 0xb068)
-#define _MIPIB_HS_GEN_DATA			(VLV_DISPLAY_BASE + 0xb868)
-#define MIPI_HS_GEN_DATA(pipe)		_PIPE(pipe, _MIPIA_HS_GEN_DATA, _MIPIB_HS_GEN_DATA)
+#define _MIPIA_HS_GEN_DATA		(dev_priv->mipi_mmio_base + 0xb068)
+#define _MIPIB_HS_GEN_DATA		(dev_priv->mipi_mmio_base + 0xb868)
+#define MIPI_HS_GEN_DATA(tc)		_TRANSCODER(tc, _MIPIA_HS_GEN_DATA, \
+					_MIPIB_HS_GEN_DATA)
 
-#define _MIPIA_LP_GEN_CTRL			(VLV_DISPLAY_BASE + 0xb06c)
-#define _MIPIB_LP_GEN_CTRL			(VLV_DISPLAY_BASE + 0xb86c)
-#define MIPI_LP_GEN_CTRL(pipe)		_PIPE(pipe, _MIPIA_LP_GEN_CTRL, _MIPIB_LP_GEN_CTRL)
-#define _MIPIA_HS_GEN_CTRL			(VLV_DISPLAY_BASE + 0xb070)
-#define _MIPIB_HS_GEN_CTRL			(VLV_DISPLAY_BASE + 0xb870)
-#define MIPI_HS_GEN_CTRL(pipe)		_PIPE(pipe, _MIPIA_HS_GEN_CTRL, _MIPIB_HS_GEN_CTRL)
+#define _MIPIA_LP_GEN_CTRL		(dev_priv->mipi_mmio_base + 0xb06c)
+#define _MIPIB_LP_GEN_CTRL		(dev_priv->mipi_mmio_base + 0xb86c)
+#define MIPI_LP_GEN_CTRL(tc)		_TRANSCODER(tc, _MIPIA_LP_GEN_CTRL, \
+					_MIPIB_LP_GEN_CTRL)
+#define _MIPIA_HS_GEN_CTRL		(dev_priv->mipi_mmio_base + 0xb070)
+#define _MIPIB_HS_GEN_CTRL		(dev_priv->mipi_mmio_base + 0xb870)
+#define MIPI_HS_GEN_CTRL(tc)		_TRANSCODER(tc, _MIPIA_HS_GEN_CTRL, \
+					_MIPIB_HS_GEN_CTRL)
 #define  LONG_PACKET_WORD_COUNT_SHIFT			8
 #define  LONG_PACKET_WORD_COUNT_MASK			(0xffff << 8)
 #define  SHORT_PACKET_PARAM_SHIFT			8
@@ -6280,9 +6399,10 @@ enum punit_power_well {
 #define  DATA_TYPE_MASK					(3f << 0)
 /* data type values, see include/video/mipi_display.h */
 
-#define _MIPIA_GEN_FIFO_STAT			(VLV_DISPLAY_BASE + 0xb074)
-#define _MIPIB_GEN_FIFO_STAT			(VLV_DISPLAY_BASE + 0xb874)
-#define MIPI_GEN_FIFO_STAT(pipe)	_PIPE(pipe, _MIPIA_GEN_FIFO_STAT, _MIPIB_GEN_FIFO_STAT)
+#define _MIPIA_GEN_FIFO_STAT		(dev_priv->mipi_mmio_base + 0xb074)
+#define _MIPIB_GEN_FIFO_STAT		(dev_priv->mipi_mmio_base + 0xb874)
+#define MIPI_GEN_FIFO_STAT(tc)	_TRANSCODER(tc, _MIPIA_GEN_FIFO_STAT, \
+					_MIPIB_GEN_FIFO_STAT)
 #define  DPI_FIFO_EMPTY					(1 << 28)
 #define  DBI_FIFO_EMPTY					(1 << 27)
 #define  LP_CTRL_FIFO_EMPTY				(1 << 26)
@@ -6298,16 +6418,18 @@ enum punit_power_well {
 #define  HS_DATA_FIFO_HALF_EMPTY			(1 << 1)
 #define  HS_DATA_FIFO_FULL				(1 << 0)
 
-#define _MIPIA_HS_LS_DBI_ENABLE			(VLV_DISPLAY_BASE + 0xb078)
-#define _MIPIB_HS_LS_DBI_ENABLE			(VLV_DISPLAY_BASE + 0xb878)
-#define MIPI_HS_LP_DBI_ENABLE(pipe)	_PIPE(pipe, _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE)
+#define _MIPIA_HS_LS_DBI_ENABLE		(dev_priv->mipi_mmio_base + 0xb078)
+#define _MIPIB_HS_LS_DBI_ENABLE		(dev_priv->mipi_mmio_base + 0xb878)
+#define MIPI_HS_LP_DBI_ENABLE(tc)	_TRANSCODER(tc, \
+			_MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE)
 #define  DBI_HS_LP_MODE_MASK				(1 << 0)
 #define  DBI_LP_MODE					(1 << 0)
 #define  DBI_HS_MODE					(0 << 0)
 
-#define _MIPIA_DPHY_PARAM			(VLV_DISPLAY_BASE + 0xb080)
-#define _MIPIB_DPHY_PARAM			(VLV_DISPLAY_BASE + 0xb880)
-#define MIPI_DPHY_PARAM(pipe)		_PIPE(pipe, _MIPIA_DPHY_PARAM, _MIPIB_DPHY_PARAM)
+#define _MIPIA_DPHY_PARAM		(dev_priv->mipi_mmio_base + 0xb080)
+#define _MIPIB_DPHY_PARAM		(dev_priv->mipi_mmio_base + 0xb880)
+#define MIPI_DPHY_PARAM(tc)		_TRANSCODER(tc, _MIPIA_DPHY_PARAM, \
+					_MIPIB_DPHY_PARAM)
 #define  EXIT_ZERO_COUNT_SHIFT				24
 #define  EXIT_ZERO_COUNT_MASK				(0x3f << 24)
 #define  TRAIL_COUNT_SHIFT				16
@@ -6318,34 +6440,41 @@ enum punit_power_well {
 #define  PREPARE_COUNT_MASK				(0x3f << 0)
 
 /* bits 31:0 */
-#define _MIPIA_DBI_BW_CTRL			(VLV_DISPLAY_BASE + 0xb084)
-#define _MIPIB_DBI_BW_CTRL			(VLV_DISPLAY_BASE + 0xb884)
-#define MIPI_DBI_BW_CTRL(pipe)		_PIPE(pipe, _MIPIA_DBI_BW_CTRL, _MIPIB_DBI_BW_CTRL)
+#define _MIPIA_DBI_BW_CTRL		(dev_priv->mipi_mmio_base + 0xb084)
+#define _MIPIB_DBI_BW_CTRL		(dev_priv->mipi_mmio_base + 0xb884)
+#define MIPI_DBI_BW_CTRL(tc)		_TRANSCODER(tc, _MIPIA_DBI_BW_CTRL, \
+					_MIPIB_DBI_BW_CTRL)
 
-#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT		(VLV_DISPLAY_BASE + 0xb088)
-#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT		(VLV_DISPLAY_BASE + 0xb888)
-#define MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe)	_PIPE(pipe, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT)
+#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT		(dev_priv->mipi_mmio_base \
+							+ 0xb088)
+#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT		(dev_priv->mipi_mmio_base \
+							+ 0xb888)
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT(tc)	_TRANSCODER(tc, \
+	_MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT)
 #define  LP_HS_SSW_CNT_SHIFT				16
 #define  LP_HS_SSW_CNT_MASK				(0xffff << 16)
 #define  HS_LP_PWR_SW_CNT_SHIFT				0
 #define  HS_LP_PWR_SW_CNT_MASK				(0xffff << 0)
 
-#define _MIPIA_STOP_STATE_STALL			(VLV_DISPLAY_BASE + 0xb08c)
-#define _MIPIB_STOP_STATE_STALL			(VLV_DISPLAY_BASE + 0xb88c)
-#define MIPI_STOP_STATE_STALL(pipe)	_PIPE(pipe, _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL)
+#define _MIPIA_STOP_STATE_STALL		(dev_priv->mipi_mmio_base + 0xb08c)
+#define _MIPIB_STOP_STATE_STALL		(dev_priv->mipi_mmio_base + 0xb88c)
+#define MIPI_STOP_STATE_STALL(tc)	_TRANSCODER(tc, \
+			_MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL)
 #define  STOP_STATE_STALL_COUNTER_SHIFT			0
 #define  STOP_STATE_STALL_COUNTER_MASK			(0xff << 0)
 
-#define _MIPIA_INTR_STAT_REG_1			(VLV_DISPLAY_BASE + 0xb090)
-#define _MIPIB_INTR_STAT_REG_1			(VLV_DISPLAY_BASE + 0xb890)
-#define MIPI_INTR_STAT_REG_1(pipe)	_PIPE(pipe, _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1)
-#define _MIPIA_INTR_EN_REG_1			(VLV_DISPLAY_BASE + 0xb094)
-#define _MIPIB_INTR_EN_REG_1			(VLV_DISPLAY_BASE + 0xb894)
-#define MIPI_INTR_EN_REG_1(pipe)	_PIPE(pipe, _MIPIA_INTR_EN_REG_1, _MIPIB_INTR_EN_REG_1)
+#define _MIPIA_INTR_STAT_REG_1		(dev_priv->mipi_mmio_base + 0xb090)
+#define _MIPIB_INTR_STAT_REG_1		(dev_priv->mipi_mmio_base + 0xb890)
+#define MIPI_INTR_STAT_REG_1(tc)	_TRANSCODER(tc, \
+				_MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1)
+#define _MIPIA_INTR_EN_REG_1		(dev_priv->mipi_mmio_base + 0xb094)
+#define _MIPIB_INTR_EN_REG_1		(dev_priv->mipi_mmio_base + 0xb894)
+#define MIPI_INTR_EN_REG_1(tc)	_TRANSCODER(tc, _MIPIA_INTR_EN_REG_1, \
+					_MIPIB_INTR_EN_REG_1)
 #define  RX_CONTENTION_DETECTED				(1 << 0)
 
 /* XXX: only pipe A ?!? */
-#define MIPIA_DBI_TYPEC_CTRL			(VLV_DISPLAY_BASE + 0xb100)
+#define MIPIA_DBI_TYPEC_CTRL		(dev_priv->mipi_mmio_base + 0xb100)
 #define  DBI_TYPEC_ENABLE				(1 << 31)
 #define  DBI_TYPEC_WIP					(1 << 30)
 #define  DBI_TYPEC_OPTION_SHIFT				28
@@ -6359,9 +6488,10 @@ enum punit_power_well {
 
 /* MIPI adapter registers */
 
-#define _MIPIA_CTRL				(VLV_DISPLAY_BASE + 0xb104)
-#define _MIPIB_CTRL				(VLV_DISPLAY_BASE + 0xb904)
-#define MIPI_CTRL(pipe)			_PIPE(pipe, _MIPIA_CTRL, _MIPIB_CTRL)
+#define _MIPIA_CTRL			(dev_priv->mipi_mmio_base + 0xb104)
+#define _MIPIB_CTRL			(dev_priv->mipi_mmio_base + 0xb904)
+#define MIPI_CTRL(tc)			_TRANSCODER(tc, _MIPIA_CTRL, \
+					_MIPIB_CTRL)
 #define  ESCAPE_CLOCK_DIVIDER_SHIFT			5 /* A only */
 #define  ESCAPE_CLOCK_DIVIDER_MASK			(3 << 5)
 #define  ESCAPE_CLOCK_DIVIDER_1				(0 << 5)
@@ -6373,50 +6503,52 @@ enum punit_power_well {
 #define  READ_REQUEST_PRIORITY_HIGH			(3 << 3)
 #define  RGB_FLIP_TO_BGR				(1 << 2)
 
-#define _MIPIA_DATA_ADDRESS			(VLV_DISPLAY_BASE + 0xb108)
-#define _MIPIB_DATA_ADDRESS			(VLV_DISPLAY_BASE + 0xb908)
-#define MIPI_DATA_ADDRESS(pipe)		_PIPE(pipe, _MIPIA_DATA_ADDRESS, _MIPIB_DATA_ADDRESS)
+#define _MIPIA_DATA_ADDRESS		(dev_priv->mipi_mmio_base + 0xb108)
+#define _MIPIB_DATA_ADDRESS		(dev_priv->mipi_mmio_base + 0xb908)
+#define MIPI_DATA_ADDRESS(tc)		_TRANSCODER(tc, _MIPIA_DATA_ADDRESS, \
+					_MIPIB_DATA_ADDRESS)
 #define  DATA_MEM_ADDRESS_SHIFT				5
 #define  DATA_MEM_ADDRESS_MASK				(0x7ffffff << 5)
 #define  DATA_VALID					(1 << 0)
 
-#define _MIPIA_DATA_LENGTH			(VLV_DISPLAY_BASE + 0xb10c)
-#define _MIPIB_DATA_LENGTH			(VLV_DISPLAY_BASE + 0xb90c)
-#define MIPI_DATA_LENGTH(pipe)		_PIPE(pipe, _MIPIA_DATA_LENGTH, _MIPIB_DATA_LENGTH)
+#define _MIPIA_DATA_LENGTH		(dev_priv->mipi_mmio_base + 0xb10c)
+#define _MIPIB_DATA_LENGTH		(dev_priv->mipi_mmio_base + 0xb90c)
+#define MIPI_DATA_LENGTH(tc)		_TRANSCODER(tc, _MIPIA_DATA_LENGTH, \
+					_MIPIB_DATA_LENGTH)
 #define  DATA_LENGTH_SHIFT				0
 #define  DATA_LENGTH_MASK				(0xfffff << 0)
 
-#define _MIPIA_COMMAND_ADDRESS			(VLV_DISPLAY_BASE + 0xb110)
-#define _MIPIB_COMMAND_ADDRESS			(VLV_DISPLAY_BASE + 0xb910)
-#define MIPI_COMMAND_ADDRESS(pipe)	_PIPE(pipe, _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS)
+#define _MIPIA_COMMAND_ADDRESS		(dev_priv->mipi_mmio_base + 0xb110)
+#define _MIPIB_COMMAND_ADDRESS		(dev_priv->mipi_mmio_base + 0xb910)
+#define MIPI_COMMAND_ADDRESS(tc)	_TRANSCODER(tc, \
+				_MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS)
 #define  COMMAND_MEM_ADDRESS_SHIFT			5
 #define  COMMAND_MEM_ADDRESS_MASK			(0x7ffffff << 5)
 #define  AUTO_PWG_ENABLE				(1 << 2)
 #define  MEMORY_WRITE_DATA_FROM_PIPE_RENDERING		(1 << 1)
 #define  COMMAND_VALID					(1 << 0)
 
-#define _MIPIA_COMMAND_LENGTH			(VLV_DISPLAY_BASE + 0xb114)
-#define _MIPIB_COMMAND_LENGTH			(VLV_DISPLAY_BASE + 0xb914)
-#define MIPI_COMMAND_LENGTH(pipe)	_PIPE(pipe, _MIPIA_COMMAND_LENGTH, _MIPIB_COMMAND_LENGTH)
+#define _MIPIA_COMMAND_LENGTH		(dev_priv->mipi_mmio_base + 0xb114)
+#define _MIPIB_COMMAND_LENGTH		(dev_priv->mipi_mmio_base + 0xb914)
+#define MIPI_COMMAND_LENGTH(tc)	_TRANSCODER(tc, _MIPIA_COMMAND_LENGTH, \
+					_MIPIB_COMMAND_LENGTH)
 #define  COMMAND_LENGTH_SHIFT(n)			(8 * (n)) /* n: 0...3 */
 #define  COMMAND_LENGTH_MASK(n)				(0xff << (8 * (n)))
 
-#define _MIPIA_READ_DATA_RETURN0		(VLV_DISPLAY_BASE + 0xb118)
-#define _MIPIB_READ_DATA_RETURN0		(VLV_DISPLAY_BASE + 0xb918)
-#define MIPI_READ_DATA_RETURN(pipe, n) \
-	(_PIPE(pipe, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */
+#define _MIPIA_READ_DATA_RETURN0	(dev_priv->mipi_mmio_base + 0xb118)
+#define _MIPIB_READ_DATA_RETURN0	(dev_priv->mipi_mmio_base + 0xb918)
+#define MIPI_READ_DATA_RETURN(tc, n) \
+	(_TRANSCODER(tc, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) \
+					+ 4 * (n)) /* n: 0...7 */
 
-#define _MIPIA_READ_DATA_VALID			(VLV_DISPLAY_BASE + 0xb138)
-#define _MIPIB_READ_DATA_VALID			(VLV_DISPLAY_BASE + 0xb938)
-#define MIPI_READ_DATA_VALID(pipe)	_PIPE(pipe, _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
+#define _MIPIA_READ_DATA_VALID		(dev_priv->mipi_mmio_base + 0xb138)
+#define _MIPIB_READ_DATA_VALID		(dev_priv->mipi_mmio_base + 0xb938)
+#define MIPI_READ_DATA_VALID(tc)	_TRANSCODER(tc, \
+				_MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
 #define  READ_DATA_VALID(n)				(1 << (n))
 
 /* For UMS only (deprecated): */
 #define _PALETTE_A (dev_priv->info.display_mmio_offset + 0xa000)
 #define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800)
-#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
-#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
-#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
-#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
 
 #endif /* _I915_REG_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_sysfs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_sysfs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,22 +47,45 @@ static u32 calc_residency(struct drm_dev
 
 	intel_runtime_pm_get(dev_priv);
 
-	/* On VLV, residency time is in CZ units rather than 1.28us */
+	/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
 	if (IS_VALLEYVIEW(dev)) {
-		u32 clkctl2;
+		u32 reg, czcount_30ns;
 
-		clkctl2 = I915_READ(VLV_CLK_CTL2) >>
-			CLK_CTL2_CZCOUNT_30NS_SHIFT;
-		if (!clkctl2) {
-			WARN(!clkctl2, "bogus CZ count value");
+		if (IS_CHERRYVIEW(dev))
+			reg = CHV_CLK_CTL1;
+		else
+			reg = VLV_CLK_CTL2;
+
+		czcount_30ns = I915_READ(reg) >> CLK_CTL2_CZCOUNT_30NS_SHIFT;
+
+		if (!czcount_30ns) {
+			WARN(!czcount_30ns, "bogus CZ count value");
 			ret = 0;
 			goto out;
 		}
-		units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
+
+		units = 0;
+		div = 1000000ULL;
+
+		if (IS_CHERRYVIEW(dev)) {
+			/* Special case for 320Mhz */
+			if (czcount_30ns == 1) {
+				div = 10000000ULL;
+				units = 3125ULL;
+			} else {
+				/* chv counts are one less */
+				czcount_30ns += 1;
+			}
+		}
+
+		if (units == 0)
+			units = DIV_ROUND_UP_ULL(30ULL * bias,
+						 (u64)czcount_30ns);
+
 		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
 			units <<= 8;
 
-		div = 1000000ULL * bias;
+		div = div * bias;
 	}
 
 	raw_time = I915_READ(reg) * units;
@@ -461,11 +484,20 @@ static ssize_t gt_rp_mhz_show(struct dev
 	mutex_unlock(&dev->struct_mutex);
 
 	if (attr == &dev_attr_gt_RP0_freq_mhz) {
-		val = ((rp_state_cap & 0x0000ff) >> 0) * GT_FREQUENCY_MULTIPLIER;
+		if (IS_VALLEYVIEW(dev))
+			val = vlv_gpu_freq(dev_priv, dev_priv->rps.rp0_freq);
+		else
+			val = ((rp_state_cap & 0x0000ff) >> 0) * GT_FREQUENCY_MULTIPLIER;
 	} else if (attr == &dev_attr_gt_RP1_freq_mhz) {
-		val = ((rp_state_cap & 0x00ff00) >> 8) * GT_FREQUENCY_MULTIPLIER;
+		if (IS_VALLEYVIEW(dev))
+			val = vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq);
+		else
+			val = ((rp_state_cap & 0x00ff00) >> 8) * GT_FREQUENCY_MULTIPLIER;
 	} else if (attr == &dev_attr_gt_RPn_freq_mhz) {
-		val = ((rp_state_cap & 0xff0000) >> 16) * GT_FREQUENCY_MULTIPLIER;
+		if (IS_VALLEYVIEW(dev))
+			val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq);
+		else
+			val = ((rp_state_cap & 0xff0000) >> 16) * GT_FREQUENCY_MULTIPLIER;
 	} else {
 		BUG();
 	}
@@ -486,6 +518,9 @@ static const struct attribute *vlv_attrs
 	&dev_attr_gt_cur_freq_mhz.attr,
 	&dev_attr_gt_max_freq_mhz.attr,
 	&dev_attr_gt_min_freq_mhz.attr,
+	&dev_attr_gt_RP0_freq_mhz.attr,
+	&dev_attr_gt_RP1_freq_mhz.attr,
+	&dev_attr_gt_RPn_freq_mhz.attr,
 	&dev_attr_vlv_rpe_freq_mhz.attr,
 	NULL,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_bios.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_bios.c	2014-09-28 17:29:07.000000000 -0400
@@ -336,11 +336,12 @@ parse_lfp_backlight(struct drm_i915_priv
 
 	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
 	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+	dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
 	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
 		      "active %s, min brightness %u, level %u\n",
 		      dev_priv->vbt.backlight.pwm_freq_hz,
 		      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
-		      entry->min_brightness,
+		      dev_priv->vbt.backlight.min_brightness,
 		      backlight_data->level[panel_type]);
 }
 
@@ -877,7 +878,7 @@ err:
 
 	/* error during parsing so set all pointers to null
 	 * because of partial parsing */
-	memset(dev_priv->vbt.dsi.sequence, 0, MIPI_SEQ_MAX);
+	memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence));
 }
 
 static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
@@ -1122,7 +1123,7 @@ init_vbt_defaults(struct drm_i915_privat
 	}
 }
 
-static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
 {
 	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
 		      "VBIOS ROM for %s\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_crt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_crt.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,6 +137,18 @@ static void hsw_crt_get_config(struct in
 	pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
 }
 
+static void hsw_crt_pre_enable(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
+	I915_WRITE(SPLL_CTL,
+		   SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
+	POSTING_READ(SPLL_CTL);
+	udelay(20);
+}
+
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -194,6 +206,20 @@ static void intel_disable_crt(struct int
 	intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
+
+static void hsw_crt_post_disable(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t val;
+
+	DRM_DEBUG_KMS("Disabling SPLL\n");
+	val = I915_READ(SPLL_CTL);
+	WARN_ON(!(val & SPLL_PLL_ENABLE));
+	I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+	POSTING_READ(SPLL_CTL);
+}
+
 static void intel_enable_crt(struct intel_encoder *encoder)
 {
 	struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -289,8 +315,10 @@ static bool intel_crt_compute_config(str
 		pipe_config->pipe_bpp = 24;
 
 	/* FDI must always be 2.7 GHz */
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev)) {
+		pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
 		pipe_config->port_clock = 135000 * 2;
+	}
 
 	return true;
 }
@@ -632,8 +660,6 @@ intel_crt_detect(struct drm_connector *c
 	struct intel_load_detect_pipe tmp;
 	struct drm_modeset_acquire_ctx ctx;
 
-	intel_runtime_pm_get(dev_priv);
-
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
 		      connector->base.id, connector->name,
 		      force);
@@ -673,20 +699,23 @@ intel_crt_detect(struct drm_connector *c
 		goto out;
 	}
 
+	drm_modeset_acquire_init(&ctx, 0);
+
 	/* for pre-945g platforms use load detect */
 	if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
 		if (intel_crt_detect_ddc(connector))
 			status = connector_status_connected;
 		else
 			status = intel_crt_load_detect(crt);
-		intel_release_load_detect_pipe(connector, &tmp, &ctx);
+		intel_release_load_detect_pipe(connector, &tmp);
 	} else
 		status = connector_status_unknown;
 
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
 out:
 	intel_display_power_put(dev_priv, power_domain);
-	intel_runtime_pm_put(dev_priv);
-
 	return status;
 }
 
@@ -775,7 +804,7 @@ static const struct drm_encoder_funcs in
 	.destroy = intel_encoder_destroy,
 };
 
-static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
+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;
@@ -860,6 +889,8 @@ void intel_crt_init(struct drm_device *d
 	if (HAS_DDI(dev)) {
 		crt->base.get_config = hsw_crt_get_config;
 		crt->base.get_hw_state = intel_ddi_get_hw_state;
+		crt->base.pre_enable = hsw_crt_pre_enable;
+		crt->base.post_disable = hsw_crt_post_disable;
 	} else {
 		crt->base.get_config = intel_crt_get_config;
 		crt->base.get_hw_state = intel_crt_get_hw_state;
@@ -869,7 +900,7 @@ void intel_crt_init(struct drm_device *d
 
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	if (!I915_HAS_HOTPLUG(dev))
 		intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ddi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ddi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ddi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ddi.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,12 +76,12 @@ static const u32 bdw_ddi_translations_ed
 	0x00FFFFFF, 0x00000012,		/* eDP parameters */
 	0x00EBAFFF, 0x00020011,
 	0x00C71FFF, 0x0006000F,
+	0x00AAAFFF, 0x000E000A,
 	0x00FFFFFF, 0x00020011,
 	0x00DB6FFF, 0x0005000F,
 	0x00BEEFFF, 0x000A000C,
 	0x00FFFFFF, 0x0005000F,
 	0x00DB6FFF, 0x000A000C,
-	0x00FFFFFF, 0x000A000C,
 	0x00FFFFFF, 0x00140006		/* HDMI parameters 800mV 0dB*/
 };
 
@@ -89,12 +89,12 @@ static const u32 bdw_ddi_translations_dp
 	0x00FFFFFF, 0x0007000E,		/* DP parameters */
 	0x00D75FFF, 0x000E000A,
 	0x00BEFFFF, 0x00140006,
+	0x80B2CFFF, 0x001B0002,
 	0x00FFFFFF, 0x000E000A,
 	0x00D75FFF, 0x00180004,
 	0x80CB2FFF, 0x001B0002,
 	0x00F7DFFF, 0x00180004,
 	0x80D75FFF, 0x001B0002,
-	0x80FFFFFF, 0x001B0002,
 	0x00FFFFFF, 0x00140006		/* HDMI parameters 800mV 0dB*/
 };
 
@@ -116,7 +116,10 @@ enum port intel_ddi_get_encoder_port(str
 	struct drm_encoder *encoder = &intel_encoder->base;
 	int type = intel_encoder->type;
 
-	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
+	if (type == INTEL_OUTPUT_DP_MST) {
+		struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary;
+		return intel_dig_port->port;
+	} else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
 	    type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
 		struct intel_digital_port *intel_dig_port =
 			enc_to_dig_port(encoder);
@@ -277,7 +280,8 @@ void hsw_fdi_link_train(struct drm_crtc
 	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
 
 	/* Configure Port Clock Select */
-	I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel);
+	I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config.ddi_pll_sel);
+	WARN_ON(intel_crtc->config.ddi_pll_sel != PORT_CLK_SEL_SPLL);
 
 	/* Start the training iterating through available voltages and emphasis,
 	 * testing each value twice. */
@@ -364,6 +368,18 @@ void hsw_fdi_link_train(struct drm_crtc
 	DRM_ERROR("FDI link training failed!\n");
 }
 
+void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct intel_digital_port *intel_dig_port =
+		enc_to_dig_port(&encoder->base);
+
+	intel_dp->DP = intel_dig_port->saved_port_bits |
+		DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
+	intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
+
+}
+
 static struct intel_encoder *
 intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
 {
@@ -385,53 +401,6 @@ intel_ddi_get_crtc_encoder(struct drm_cr
 	return ret;
 }
 
-void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
-	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	uint32_t val;
-
-	switch (intel_crtc->ddi_pll_sel) {
-	case PORT_CLK_SEL_SPLL:
-		plls->spll_refcount--;
-		if (plls->spll_refcount == 0) {
-			DRM_DEBUG_KMS("Disabling SPLL\n");
-			val = I915_READ(SPLL_CTL);
-			WARN_ON(!(val & SPLL_PLL_ENABLE));
-			I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
-			POSTING_READ(SPLL_CTL);
-		}
-		break;
-	case PORT_CLK_SEL_WRPLL1:
-		plls->wrpll1_refcount--;
-		if (plls->wrpll1_refcount == 0) {
-			DRM_DEBUG_KMS("Disabling WRPLL 1\n");
-			val = I915_READ(WRPLL_CTL1);
-			WARN_ON(!(val & WRPLL_PLL_ENABLE));
-			I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE);
-			POSTING_READ(WRPLL_CTL1);
-		}
-		break;
-	case PORT_CLK_SEL_WRPLL2:
-		plls->wrpll2_refcount--;
-		if (plls->wrpll2_refcount == 0) {
-			DRM_DEBUG_KMS("Disabling WRPLL 2\n");
-			val = I915_READ(WRPLL_CTL2);
-			WARN_ON(!(val & WRPLL_PLL_ENABLE));
-			I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE);
-			POSTING_READ(WRPLL_CTL2);
-		}
-		break;
-	}
-
-	WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n");
-	WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n");
-	WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n");
-
-	intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
-}
-
 #define LC_FREQ 2700
 #define LC_FREQ_2K (LC_FREQ * 2000)
 
@@ -592,9 +561,9 @@ static int intel_ddi_calc_wrpll_link(str
 	u32 wrpll;
 
 	wrpll = I915_READ(reg);
-	switch (wrpll & SPLL_PLL_REF_MASK) {
-	case SPLL_PLL_SSC:
-	case SPLL_PLL_NON_SSC:
+	switch (wrpll & WRPLL_PLL_REF_MASK) {
+	case WRPLL_PLL_SSC:
+	case WRPLL_PLL_NON_SSC:
 		/*
 		 * We could calculate spread here, but our checking
 		 * code only cares about 5% accuracy, and spread is a max of
@@ -602,7 +571,7 @@ static int intel_ddi_calc_wrpll_link(str
 		 */
 		refclk = 135;
 		break;
-	case SPLL_PLL_LCPLL:
+	case WRPLL_PLL_LCPLL:
 		refclk = LC_FREQ;
 		break;
 	default:
@@ -618,15 +587,14 @@ static int intel_ddi_calc_wrpll_link(str
 	return (refclk * n * 100) / (p * r);
 }
 
-static void intel_ddi_clock_get(struct intel_encoder *encoder,
-				struct intel_crtc_config *pipe_config)
+void intel_ddi_clock_get(struct intel_encoder *encoder,
+			 struct intel_crtc_config *pipe_config)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	enum port port = intel_ddi_get_encoder_port(encoder);
 	int link_clock = 0;
 	u32 val, pll;
 
-	val = I915_READ(PORT_CLK_SEL(port));
+	val = pipe_config->ddi_pll_sel;
 	switch (val & PORT_CLK_SEL_MASK) {
 	case PORT_CLK_SEL_LCPLL_810:
 		link_clock = 81000;
@@ -750,173 +718,37 @@ bool intel_ddi_pll_select(struct intel_c
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
-	struct drm_encoder *encoder = &intel_encoder->base;
-	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
-	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
 	int type = intel_encoder->type;
-	enum pipe pipe = intel_crtc->pipe;
 	int clock = intel_crtc->config.port_clock;
 
-	intel_ddi_put_crtc_pll(crtc);
-
-	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-		switch (intel_dp->link_bw) {
-		case DP_LINK_BW_1_62:
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
-			break;
-		case DP_LINK_BW_2_7:
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
-			break;
-		case DP_LINK_BW_5_4:
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
-			break;
-		default:
-			DRM_ERROR("Link bandwidth %d unsupported\n",
-				  intel_dp->link_bw);
-			return false;
-		}
+	intel_put_shared_dpll(intel_crtc);
 
-	} else if (type == INTEL_OUTPUT_HDMI) {
-		uint32_t reg, val;
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_shared_dpll *pll;
+		uint32_t val;
 		unsigned p, n2, r2;
 
 		intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
 
-		val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+		val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
 		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
 		      WRPLL_DIVIDER_POST(p);
 
-		if (val == I915_READ(WRPLL_CTL1)) {
-			DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n",
-				      pipe_name(pipe));
-			reg = WRPLL_CTL1;
-		} else if (val == I915_READ(WRPLL_CTL2)) {
-			DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n",
-				      pipe_name(pipe));
-			reg = WRPLL_CTL2;
-		} else if (plls->wrpll1_refcount == 0) {
-			DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
-				      pipe_name(pipe));
-			reg = WRPLL_CTL1;
-		} else if (plls->wrpll2_refcount == 0) {
-			DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
-				      pipe_name(pipe));
-			reg = WRPLL_CTL2;
-		} else {
-			DRM_ERROR("No WRPLLs available!\n");
-			return false;
-		}
-
-		DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
-			      clock, p, n2, r2);
-
-		if (reg == WRPLL_CTL1) {
-			plls->wrpll1_refcount++;
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
-		} else {
-			plls->wrpll2_refcount++;
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
-		}
+		intel_crtc->config.dpll_hw_state.wrpll = val;
 
-	} else if (type == INTEL_OUTPUT_ANALOG) {
-		if (plls->spll_refcount == 0) {
-			DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
-				      pipe_name(pipe));
-			plls->spll_refcount++;
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
-		} else {
-			DRM_ERROR("SPLL already in use\n");
+		pll = intel_get_shared_dpll(intel_crtc);
+		if (pll == NULL) {
+			DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+					 pipe_name(intel_crtc->pipe));
 			return false;
 		}
 
-	} else {
-		WARN(1, "Invalid DDI encoder type %d\n", type);
-		return false;
+		intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
 	}
 
 	return true;
 }
 
-/*
- * To be called after intel_ddi_pll_select(). That one selects the PLL to be
- * used, this one actually enables the PLL.
- */
-void intel_ddi_pll_enable(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
-	int clock = crtc->config.port_clock;
-	uint32_t reg, cur_val, new_val;
-	int refcount;
-	const char *pll_name;
-	uint32_t enable_bit = (1 << 31);
-	unsigned int p, n2, r2;
-
-	BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
-	BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
-
-	switch (crtc->ddi_pll_sel) {
-	case PORT_CLK_SEL_LCPLL_2700:
-	case PORT_CLK_SEL_LCPLL_1350:
-	case PORT_CLK_SEL_LCPLL_810:
-		/*
-		 * LCPLL should always be enabled at this point of the mode set
-		 * sequence, so nothing to do.
-		 */
-		return;
-
-	case PORT_CLK_SEL_SPLL:
-		pll_name = "SPLL";
-		reg = SPLL_CTL;
-		refcount = plls->spll_refcount;
-		new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
-			  SPLL_PLL_SSC;
-		break;
-
-	case PORT_CLK_SEL_WRPLL1:
-	case PORT_CLK_SEL_WRPLL2:
-		if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
-			pll_name = "WRPLL1";
-			reg = WRPLL_CTL1;
-			refcount = plls->wrpll1_refcount;
-		} else {
-			pll_name = "WRPLL2";
-			reg = WRPLL_CTL2;
-			refcount = plls->wrpll2_refcount;
-		}
-
-		intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-		new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
-			  WRPLL_DIVIDER_REFERENCE(r2) |
-			  WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
-
-		break;
-
-	case PORT_CLK_SEL_NONE:
-		WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
-		return;
-	default:
-		WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
-		return;
-	}
-
-	cur_val = I915_READ(reg);
-
-	WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
-	if (refcount == 1) {
-		WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
-		I915_WRITE(reg, new_val);
-		POSTING_READ(reg);
-		udelay(20);
-	} else {
-		WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
-	}
-}
-
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -926,8 +758,7 @@ void intel_ddi_set_pipe_settings(struct
 	int type = intel_encoder->type;
 	uint32_t temp;
 
-	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
-
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) {
 		temp = TRANS_MSA_SYNC_CLK;
 		switch (intel_crtc->config.pipe_bpp) {
 		case 18:
@@ -949,6 +780,21 @@ void intel_ddi_set_pipe_settings(struct
 	}
 }
 
+void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+	uint32_t temp;
+	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+	if (state == true)
+		temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+	else
+		temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+	I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
+}
+
 void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -995,7 +841,9 @@ 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) && intel_crtc->config.pch_pfit.enabled)
+			if (IS_HASWELL(dev) &&
+			    (intel_crtc->config.pch_pfit.enabled ||
+			     intel_crtc->config.pch_pfit.force_thru))
 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
 			else
 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
@@ -1026,7 +874,19 @@ void intel_ddi_enable_transcoder_func(st
 		   type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+		if (intel_dp->is_mst) {
+			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
+		} else
+			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+
+		temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
+	} else if (type == INTEL_OUTPUT_DP_MST) {
+		struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
+
+		if (intel_dp->is_mst) {
+			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
+		} else
+			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
 
 		temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
 	} else {
@@ -1043,7 +903,7 @@ void intel_ddi_disable_transcoder_func(s
 	uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
 	uint32_t val = I915_READ(reg);
 
-	val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK);
+	val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
 	val |= TRANS_DDI_PORT_NONE;
 	I915_WRITE(reg, val);
 }
@@ -1082,8 +942,11 @@ bool intel_ddi_connector_get_hw_state(st
 	case TRANS_DDI_MODE_SELECT_DP_SST:
 		if (type == DRM_MODE_CONNECTOR_eDP)
 			return true;
-	case TRANS_DDI_MODE_SELECT_DP_MST:
 		return (type == DRM_MODE_CONNECTOR_DisplayPort);
+	case TRANS_DDI_MODE_SELECT_DP_MST:
+		/* if the transcoder is in MST state then
+		 * connector isn't connected */
+		return false;
 
 	case TRANS_DDI_MODE_SELECT_FDI:
 		return (type == DRM_MODE_CONNECTOR_VGA);
@@ -1135,6 +998,9 @@ bool intel_ddi_get_hw_state(struct intel
 
 			if ((tmp & TRANS_DDI_PORT_MASK)
 			    == TRANS_DDI_SELECT_PORT(port)) {
+				if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST)
+					return false;
+
 				*pipe = i;
 				return true;
 			}
@@ -1146,76 +1012,6 @@ bool intel_ddi_get_hw_state(struct intel
 	return false;
 }
 
-static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
-				       enum pipe pipe)
-{
-	uint32_t temp, ret;
-	enum port port = I915_MAX_PORTS;
-	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-								      pipe);
-	int i;
-
-	if (cpu_transcoder == TRANSCODER_EDP) {
-		port = PORT_A;
-	} else {
-		temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
-		temp &= TRANS_DDI_PORT_MASK;
-
-		for (i = PORT_B; i <= PORT_E; i++)
-			if (temp == TRANS_DDI_SELECT_PORT(i))
-				port = i;
-	}
-
-	if (port == I915_MAX_PORTS) {
-		WARN(1, "Pipe %c enabled on an unknown port\n",
-		     pipe_name(pipe));
-		ret = PORT_CLK_SEL_NONE;
-	} else {
-		ret = I915_READ(PORT_CLK_SEL(port));
-		DRM_DEBUG_KMS("Pipe %c connected to port %c using clock "
-			      "0x%08x\n", pipe_name(pipe), port_name(port),
-			      ret);
-	}
-
-	return ret;
-}
-
-void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum pipe pipe;
-	struct intel_crtc *intel_crtc;
-
-	dev_priv->ddi_plls.spll_refcount = 0;
-	dev_priv->ddi_plls.wrpll1_refcount = 0;
-	dev_priv->ddi_plls.wrpll2_refcount = 0;
-
-	for_each_pipe(pipe) {
-		intel_crtc =
-			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-
-		if (!intel_crtc->active) {
-			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
-			continue;
-		}
-
-		intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
-								 pipe);
-
-		switch (intel_crtc->ddi_pll_sel) {
-		case PORT_CLK_SEL_SPLL:
-			dev_priv->ddi_plls.spll_refcount++;
-			break;
-		case PORT_CLK_SEL_WRPLL1:
-			dev_priv->ddi_plls.wrpll1_refcount++;
-			break;
-		case PORT_CLK_SEL_WRPLL2:
-			dev_priv->ddi_plls.wrpll2_refcount++;
-			break;
-		}
-	}
-}
-
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
@@ -1261,17 +1057,13 @@ static void intel_ddi_pre_enable(struct
 		intel_edp_panel_on(intel_dp);
 	}
 
-	WARN_ON(crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
-	I915_WRITE(PORT_CLK_SEL(port), crtc->ddi_pll_sel);
+	WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE);
+	I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel);
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		struct intel_digital_port *intel_dig_port =
-			enc_to_dig_port(encoder);
 
-		intel_dp->DP = intel_dig_port->saved_port_bits |
-			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
-		intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
+		intel_ddi_init_dp_buf_reg(intel_encoder);
 
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 		intel_dp_start_link_train(intel_dp);
@@ -1418,10 +1210,60 @@ int intel_ddi_get_cdclk_freq(struct drm_
 	}
 }
 
+static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
+			       struct intel_shared_dpll *pll)
+{
+	I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll);
+	POSTING_READ(WRPLL_CTL(pll->id));
+	udelay(20);
+}
+
+static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
+				struct intel_shared_dpll *pll)
+{
+	uint32_t val;
+
+	val = I915_READ(WRPLL_CTL(pll->id));
+	I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
+	POSTING_READ(WRPLL_CTL(pll->id));
+}
+
+static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+				     struct intel_shared_dpll *pll,
+				     struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+
+	if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(WRPLL_CTL(pll->id));
+	hw_state->wrpll = val;
+
+	return val & WRPLL_PLL_ENABLE;
+}
+
+static const char * const hsw_ddi_pll_names[] = {
+	"WRPLL 1",
+	"WRPLL 2",
+};
+
 void intel_ddi_pll_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t val = I915_READ(LCPLL_CTL);
+	int i;
+
+	dev_priv->num_shared_dpll = 2;
+
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		dev_priv->shared_dplls[i].id = i;
+		dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
+		dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
+		dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
+		dev_priv->shared_dplls[i].get_hw_state =
+			hsw_ddi_pll_get_hw_state;
+	}
 
 	/* The LCPLL register should be turned on by the BIOS. For now let's
 	 * just check its state and print errors in case something is wrong.
@@ -1465,10 +1307,15 @@ void intel_ddi_prepare_link_retrain(stru
 			intel_wait_ddi_buf_idle(dev_priv, port);
 	}
 
-	val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
+	val = DP_TP_CTL_ENABLE |
 	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
-	if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
-		val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+	if (intel_dp->is_mst)
+		val |= DP_TP_CTL_MODE_MST;
+	else {
+		val |= DP_TP_CTL_MODE_SST;
+		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+			val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+	}
 	I915_WRITE(DP_TP_CTL(port), val);
 	POSTING_READ(DP_TP_CTL(port));
 
@@ -1507,11 +1354,16 @@ void intel_ddi_fdi_disable(struct drm_cr
 
 static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-	int type = intel_encoder->type;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+	int type = intel_dig_port->base.type;
 
-	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP)
-		intel_dp_check_link_status(intel_dp);
+	if (type != INTEL_OUTPUT_DISPLAYPORT &&
+	    type != INTEL_OUTPUT_EDP &&
+	    type != INTEL_OUTPUT_UNKNOWN) {
+		return;
+	}
+
+	intel_dp_hot_plug(intel_encoder);
 }
 
 void intel_ddi_get_config(struct intel_encoder *encoder,
@@ -1663,15 +1515,13 @@ void intel_ddi_init(struct drm_device *d
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct drm_encoder *encoder;
-	struct intel_connector *hdmi_connector = NULL;
-	struct intel_connector *dp_connector = NULL;
 	bool init_hdmi, init_dp;
 
 	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 (!init_dp && !init_hdmi) {
-		DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n",
+		DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n",
 			      port_name(port));
 		init_hdmi = true;
 		init_dp = true;
@@ -1701,20 +1551,28 @@ void intel_ddi_init(struct drm_device *d
 					   DDI_A_4_LANES);
 
 	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
-	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	intel_encoder->cloneable = 0;
 	intel_encoder->hot_plug = intel_ddi_hot_plug;
 
-	if (init_dp)
-		dp_connector = intel_ddi_init_dp_connector(intel_dig_port);
+	if (init_dp) {
+		if (!intel_ddi_init_dp_connector(intel_dig_port))
+			goto err;
+
+		intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
+		dev_priv->hpd_irq_port[port] = intel_dig_port;
+	}
 
 	/* In theory we don't need the encoder->type check, but leave it just in
 	 * case we have some really bad VBTs... */
-	if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi)
-		hdmi_connector = intel_ddi_init_hdmi_connector(intel_dig_port);
-
-	if (!dp_connector && !hdmi_connector) {
-		drm_encoder_cleanup(encoder);
-		kfree(intel_dig_port);
+	if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
+		if (!intel_ddi_init_hdmi_connector(intel_dig_port))
+			goto err;
 	}
+
+	return;
+
+err:
+	drm_encoder_cleanup(encoder);
+	kfree(intel_dig_port);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,12 +39,45 @@
 #include "i915_trace.h"
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_rect.h>
 #include <linux/dma_remapping.h>
 
+/* Primary plane formats supported by all gen */
+#define COMMON_PRIMARY_FORMATS \
+	DRM_FORMAT_C8, \
+	DRM_FORMAT_RGB565, \
+	DRM_FORMAT_XRGB8888, \
+	DRM_FORMAT_ARGB8888
+
+/* Primary plane formats for gen <= 3 */
+static const uint32_t intel_primary_formats_gen2[] = {
+	COMMON_PRIMARY_FORMATS,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_ARGB1555,
+};
+
+/* Primary plane formats for gen >= 4 */
+static const uint32_t intel_primary_formats_gen4[] = {
+	COMMON_PRIMARY_FORMATS, \
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ABGR2101010,
+};
+
+/* Cursor formats */
+static const uint32_t intel_cursor_formats[] = {
+	DRM_FORMAT_ARGB8888,
+};
+
 #define DIV_ROUND_CLOSEST_ULL(ll, d)	\
-	({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
+({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
 
-static void intel_increase_pllclock(struct drm_crtc *crtc);
+static void intel_increase_pllclock(struct drm_device *dev,
+				    enum pipe pipe);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
@@ -68,6 +101,14 @@ static void haswell_set_pipeconf(struct
 static void intel_set_pipe_csc(struct drm_crtc *crtc);
 static void vlv_prepare_pll(struct intel_crtc *crtc);
 
+static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
+{
+	if (!connector->mst_port)
+		return connector->encoder;
+	else
+		return &connector->mst_port->mst_encoders[pipe]->base;
+}
+
 typedef struct {
 	int	min, max;
 } intel_range_t;
@@ -1061,11 +1102,6 @@ void assert_shared_dpll(struct drm_i915_
 	bool cur_state;
 	struct intel_dpll_hw_state hw_state;
 
-	if (HAS_PCH_LPT(dev_priv->dev)) {
-		DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
-		return;
-	}
-
 	if (WARN (!pll,
 		  "asserting DPLL %s with no DPLL\n", state_string(state)))
 		return;
@@ -1481,9 +1517,6 @@ static void intel_reset_dpio(struct drm_
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!IS_VALLEYVIEW(dev))
-		return;
-
 	if (IS_CHERRYVIEW(dev)) {
 		enum dpio_phy phy;
 		u32 val;
@@ -1505,26 +1538,6 @@ static void intel_reset_dpio(struct drm_
 			I915_WRITE(DISPLAY_PHY_CONTROL,
 				PHY_COM_LANE_RESET_DEASSERT(phy, val));
 		}
-
-	} else {
-		/*
-		 * If DPIO has already been reset, e.g. by BIOS, just skip all
-		 * this.
-		 */
-		if (I915_READ(DPIO_CTL) & DPIO_CMNRST)
-			return;
-
-		/*
-		 * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
-		 * Need to assert and de-assert PHY SB reset by gating the
-		 * common lane power, then un-gating it.
-		 * Simply ungating isn't enough to reset the PHY enough to get
-		 * ports and lanes running.
-		 */
-		__vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
-				     false);
-		__vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
-				     true);
 	}
 }
 
@@ -1712,6 +1725,17 @@ static void chv_disable_pll(struct drm_i
 	val &= ~DPIO_DCLKP_EN;
 	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
 
+	/* disable left/right clock distribution */
+	if (pipe != PIPE_B) {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+	} else {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+	}
+
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1749,6 +1773,9 @@ static void intel_prepare_shared_dpll(st
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
+	if (WARN_ON(pll == NULL))
+		return;
+
 	WARN_ON(!pll->refcount);
 	if (pll->active == 0) {
 		DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
@@ -1790,12 +1817,14 @@ static void intel_enable_shared_dpll(str
 	}
 	WARN_ON(pll->on);
 
+	intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
+
 	DRM_DEBUG_KMS("enabling %s\n", pll->name);
 	pll->enable(dev_priv, pll);
 	pll->on = true;
 }
 
-static void intel_disable_shared_dpll(struct intel_crtc *crtc)
+void intel_disable_shared_dpll(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1826,6 +1855,8 @@ static void intel_disable_shared_dpll(st
 	DRM_DEBUG_KMS("disabling %s\n", pll->name);
 	pll->disable(dev_priv, pll);
 	pll->on = false;
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
 }
 
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
@@ -2172,6 +2203,8 @@ intel_pin_and_fence_fb_obj(struct drm_de
 	u32 alignment;
 	int ret;
 
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
 	switch (obj->tiling_mode) {
 	case I915_TILING_NONE:
 		if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
@@ -2200,6 +2233,15 @@ intel_pin_and_fence_fb_obj(struct drm_de
 	if (need_vtd_wa(dev) && alignment < 256 * 1024)
 		alignment = 256 * 1024;
 
+	/*
+	 * Global gtt pte registers are special registers which actually forward
+	 * writes to a chunk of system memory. Which means that there is no risk
+	 * that the register values disappear as soon as we call
+	 * intel_runtime_pm_put(), so it is correct to wrap only the
+	 * pin/unpin/fence and not more.
+	 */
+	intel_runtime_pm_get(dev_priv);
+
 	dev_priv->mm.interruptible = false;
 	ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
 	if (ret)
@@ -2217,17 +2259,21 @@ intel_pin_and_fence_fb_obj(struct drm_de
 	i915_gem_object_pin_fence(obj);
 
 	dev_priv->mm.interruptible = true;
+	intel_runtime_pm_put(dev_priv);
 	return 0;
 
 err_unpin:
 	i915_gem_object_unpin_from_display_plane(obj);
 err_interruptible:
 	dev_priv->mm.interruptible = true;
+	intel_runtime_pm_put(dev_priv);
 	return ret;
 }
 
 void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
 {
+	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
+
 	i915_gem_object_unpin_fence(obj);
 	i915_gem_object_unpin_from_display_plane(obj);
 }
@@ -2314,6 +2360,7 @@ static bool intel_alloc_plane_obj(struct
 		goto out_unref_obj;
 	}
 
+	obj->frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(crtc->pipe);
 	mutex_unlock(&dev->struct_mutex);
 
 	DRM_DEBUG_KMS("plane fb obj %p\n", obj);
@@ -2331,7 +2378,7 @@ static void intel_find_plane_obj(struct
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_crtc *c;
 	struct intel_crtc *i;
-	struct intel_framebuffer *fb;
+	struct drm_i915_gem_object *obj;
 
 	if (!intel_crtc->base.primary->fb)
 		return;
@@ -2352,13 +2399,17 @@ static void intel_find_plane_obj(struct
 		if (c == &intel_crtc->base)
 			continue;
 
-		if (!i->active || !c->primary->fb)
+		if (!i->active)
 			continue;
 
-		fb = to_intel_framebuffer(c->primary->fb);
-		if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
+		obj = intel_fb_obj(c->primary->fb);
+		if (obj == NULL)
+			continue;
+
+		if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
 			drm_framebuffer_reference(c->primary->fb);
 			intel_crtc->base.primary->fb = c->primary->fb;
+			obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 			break;
 		}
 	}
@@ -2371,16 +2422,12 @@ static void i9xx_update_primary_plane(st
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int plane = intel_crtc->plane;
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg;
 
-	intel_fb = to_intel_framebuffer(fb);
-	obj = intel_fb->obj;
-
 	reg = DSPCNTR(plane);
 	dspcntr = I915_READ(reg);
 	/* Mask out pixel format bits in case we change it */
@@ -2461,16 +2508,12 @@ static void ironlake_update_primary_plan
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int plane = intel_crtc->plane;
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg;
 
-	intel_fb = to_intel_framebuffer(fb);
-	obj = intel_fb->obj;
-
 	reg = DSPCNTR(plane);
 	dspcntr = I915_READ(reg);
 	/* Mask out pixel format bits in case we change it */
@@ -2546,7 +2589,7 @@ intel_pipe_set_base_atomic(struct drm_cr
 
 	if (dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
-	intel_increase_pllclock(crtc);
+	intel_increase_pllclock(dev, to_intel_crtc(crtc)->pipe);
 
 	dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
@@ -2601,7 +2644,7 @@ void intel_display_handle_reset(struct d
 static int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
-	struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
 	bool was_interruptible = dev_priv->mm.interruptible;
 	int ret;
@@ -2647,7 +2690,10 @@ intel_pipe_set_base(struct drm_crtc *crt
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_framebuffer *old_fb;
+	enum pipe pipe = intel_crtc->pipe;
+	struct drm_framebuffer *old_fb = crtc->primary->fb;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
 	int ret;
 
 	if (intel_crtc_has_pending_flip(crtc)) {
@@ -2669,9 +2715,10 @@ intel_pipe_set_base(struct drm_crtc *crt
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	ret = intel_pin_and_fence_fb_obj(dev,
-					 to_intel_framebuffer(fb)->obj,
-					 NULL);
+	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+	if (ret == 0)
+		i915_gem_track_fb(old_obj, obj,
+				  INTEL_FRONTBUFFER_PRIMARY(pipe));
 	mutex_unlock(&dev->struct_mutex);
 	if (ret != 0) {
 		DRM_ERROR("pin & fence failed\n");
@@ -2711,7 +2758,9 @@ intel_pipe_set_base(struct drm_crtc *crt
 
 	dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
-	old_fb = crtc->primary->fb;
+	if (intel_crtc->active)
+		intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
+
 	crtc->primary->fb = fb;
 	crtc->x = x;
 	crtc->y = y;
@@ -2720,13 +2769,12 @@ intel_pipe_set_base(struct drm_crtc *crt
 		if (intel_crtc->active && old_fb != fb)
 			intel_wait_for_vblank(dev, intel_crtc->pipe);
 		mutex_lock(&dev->struct_mutex);
-		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
+		intel_unpin_fb_obj(old_obj);
 		mutex_unlock(&dev->struct_mutex);
 	}
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
-	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -3587,7 +3635,7 @@ static void lpt_pch_enable(struct drm_cr
 	lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
 }
 
-static void intel_put_shared_dpll(struct intel_crtc *crtc)
+void intel_put_shared_dpll(struct intel_crtc *crtc)
 {
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
@@ -3607,7 +3655,7 @@ static void intel_put_shared_dpll(struct
 	crtc->config.shared_dpll = DPLL_ID_PRIVATE;
 }
 
-static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
@@ -3818,7 +3866,7 @@ static void intel_crtc_load_lut(struct d
 	}
 
 	/* use legacy palette for Ironlake */
-	if (HAS_PCH_SPLIT(dev))
+	if (!HAS_GMCH_DISPLAY(dev))
 		palreg = LGC_PALETTE(pipe);
 
 	/* Workaround : Do not read or write the pipe palette/gamma data while
@@ -3860,30 +3908,6 @@ static void intel_crtc_dpms_overlay(stru
 	 */
 }
 
-/**
- * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
- * cursor plane briefly if not already running after enabling the display
- * plane.
- * This workaround avoids occasional blank screens when self refresh is
- * enabled.
- */
-static void
-g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
-	u32 cntl = I915_READ(CURCNTR(pipe));
-
-	if ((cntl & CURSOR_MODE) == 0) {
-		u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
-
-		I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
-		I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
-		intel_wait_for_vblank(dev_priv->dev, pipe);
-		I915_WRITE(CURCNTR(pipe), cntl);
-		I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
-		I915_WRITE(FW_BLC_SELF, fw_bcl_self);
-	}
-}
-
 static void intel_crtc_enable_planes(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3892,11 +3916,10 @@ static void intel_crtc_enable_planes(str
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	drm_vblank_on(dev, pipe);
+
 	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
-	/* The fixup needs to happen before cursor is enabled */
-	if (IS_G4X(dev))
-		g4x_fixup_plane(dev_priv, pipe);
 	intel_crtc_update_cursor(crtc, true);
 	intel_crtc_dpms_overlay(intel_crtc, true);
 
@@ -3904,8 +3927,14 @@ static void intel_crtc_enable_planes(str
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
-	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
+
+	/*
+	 * FIXME: Once we grow proper nuclear flip support out of this we need
+	 * to compute the mask of flip planes precisely. For the time being
+	 * consider this a flip from a NULL plane.
+	 */
+	intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
 }
 
 static void intel_crtc_disable_planes(struct drm_crtc *crtc)
@@ -3917,7 +3946,6 @@ static void intel_crtc_disable_planes(st
 	int plane = intel_crtc->plane;
 
 	intel_crtc_wait_for_pending_flips(crtc);
-	drm_crtc_vblank_off(crtc);
 
 	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
@@ -3928,6 +3956,15 @@ static void intel_crtc_disable_planes(st
 	intel_crtc_update_cursor(crtc, false);
 	intel_disable_planes(crtc);
 	intel_disable_primary_hw_plane(dev_priv, plane, pipe);
+
+	/*
+	 * FIXME: Once we grow proper nuclear flip support out of this we need
+	 * to compute the mask of flip planes precisely. For the time being
+	 * consider this a flip to a NULL plane.
+	 */
+	intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
+
+	drm_vblank_off(dev, pipe);
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@ -4006,8 +4043,6 @@ static void ironlake_crtc_enable(struct
 		cpt_verify_modeset(dev, intel_crtc->pipe);
 
 	intel_crtc_enable_planes(crtc);
-
-	drm_crtc_vblank_on(crtc);
 }
 
 /* IPS only exists on ULT machines and is tied to pipe A. */
@@ -4059,6 +4094,9 @@ static void haswell_crtc_enable(struct d
 	if (intel_crtc->active)
 		return;
 
+	if (intel_crtc_to_shared_dpll(intel_crtc))
+		intel_enable_shared_dpll(intel_crtc);
+
 	if (intel_crtc->config.has_dp_encoder)
 		intel_dp_set_m_n(intel_crtc);
 
@@ -4083,16 +4121,15 @@ static void haswell_crtc_enable(struct d
 	intel_crtc->active = true;
 
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
-	if (intel_crtc->config.has_pch_encoder)
-		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
-
-	if (intel_crtc->config.has_pch_encoder)
-		dev_priv->display.fdi_link_train(crtc);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	if (intel_crtc->config.has_pch_encoder) {
+		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
+		dev_priv->display.fdi_link_train(crtc);
+	}
+
 	intel_ddi_enable_pipe_clock(intel_crtc);
 
 	ironlake_pfit_enable(intel_crtc);
@@ -4112,6 +4149,9 @@ static void haswell_crtc_enable(struct d
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
+	if (intel_crtc->config.dp_encoder_is_mst)
+		intel_ddi_set_vc_payload_alloc(crtc, true);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		encoder->enable(encoder);
 		intel_opregion_notify_encoder(encoder, true);
@@ -4121,8 +4161,6 @@ static void haswell_crtc_enable(struct d
 	 * to change the workaround. */
 	haswell_mode_set_planes_workaround(intel_crtc);
 	intel_crtc_enable_planes(crtc);
-
-	drm_crtc_vblank_on(crtc);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -4161,7 +4199,6 @@ static void ironlake_crtc_disable(struct
 		intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
 
 	intel_disable_pipe(dev_priv, pipe);
-
 	ironlake_pfit_disable(intel_crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4200,7 +4237,6 @@ static void ironlake_crtc_disable(struct
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
-	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4227,29 +4263,34 @@ static void haswell_crtc_disable(struct
 		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
 	intel_disable_pipe(dev_priv, pipe);
 
+	if (intel_crtc->config.dp_encoder_is_mst)
+		intel_ddi_set_vc_payload_alloc(crtc, false);
+
 	intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
 	ironlake_pfit_disable(intel_crtc);
 
 	intel_ddi_disable_pipe_clock(intel_crtc);
 
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		if (encoder->post_disable)
-			encoder->post_disable(encoder);
-
 	if (intel_crtc->config.has_pch_encoder) {
 		lpt_disable_pch_transcoder(dev_priv);
 		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
 		intel_ddi_fdi_disable(crtc);
 	}
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->post_disable)
+			encoder->post_disable(encoder);
+
 	intel_crtc->active = false;
 	intel_update_watermarks(crtc);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
-	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
+
+	if (intel_crtc_to_shared_dpll(intel_crtc))
+		intel_disable_shared_dpll(intel_crtc);
 }
 
 static void ironlake_crtc_off(struct drm_crtc *crtc)
@@ -4258,10 +4299,6 @@ static void ironlake_crtc_off(struct drm
 	intel_put_shared_dpll(intel_crtc);
 }
 
-static void haswell_crtc_off(struct drm_crtc *crtc)
-{
-	intel_ddi_put_crtc_pll(crtc);
-}
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
 {
@@ -4287,6 +4324,23 @@ static void i9xx_pfit_enable(struct inte
 	I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+static enum intel_display_power_domain port_to_power_domain(enum port port)
+{
+	switch (port) {
+	case PORT_A:
+		return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+	case PORT_B:
+		return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+	case PORT_C:
+		return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+	case PORT_D:
+		return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+	default:
+		WARN_ON_ONCE(1);
+		return POWER_DOMAIN_PORT_OTHER;
+	}
+}
+
 #define for_each_power_domain(domain, mask)				\
 	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
 		if ((1 << (domain)) & (mask))
@@ -4305,19 +4359,10 @@ intel_display_port_power_domain(struct i
 	case INTEL_OUTPUT_HDMI:
 	case INTEL_OUTPUT_EDP:
 		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
-		switch (intel_dig_port->port) {
-		case PORT_A:
-			return POWER_DOMAIN_PORT_DDI_A_4_LANES;
-		case PORT_B:
-			return POWER_DOMAIN_PORT_DDI_B_4_LANES;
-		case PORT_C:
-			return POWER_DOMAIN_PORT_DDI_C_4_LANES;
-		case PORT_D:
-			return POWER_DOMAIN_PORT_DDI_D_4_LANES;
-		default:
-			WARN_ON_ONCE(1);
-			return POWER_DOMAIN_PORT_OTHER;
-		}
+		return port_to_power_domain(intel_dig_port->port);
+	case INTEL_OUTPUT_DP_MST:
+		intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
+		return port_to_power_domain(intel_dig_port->port);
 	case INTEL_OUTPUT_ANALOG:
 		return POWER_DOMAIN_PORT_CRT;
 	case INTEL_OUTPUT_DSI:
@@ -4333,7 +4378,6 @@ static unsigned long get_crtc_power_doma
 	struct intel_encoder *intel_encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum pipe pipe = intel_crtc->pipe;
-	bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
 	unsigned long mask;
 	enum transcoder transcoder;
 
@@ -4341,7 +4385,8 @@ static unsigned long get_crtc_power_doma
 
 	mask = BIT(POWER_DOMAIN_PIPE(pipe));
 	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
-	if (pfit_enabled)
+	if (intel_crtc->config.pch_pfit.enabled ||
+	    intel_crtc->config.pch_pfit.force_thru)
 		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
@@ -4398,7 +4443,8 @@ static void modeset_update_crtc_power_do
 	intel_display_set_init_power(dev_priv, false);
 }
 
-int valleyview_get_vco(struct drm_i915_private *dev_priv)
+/* returns HPLL frequency in kHz */
+static int valleyview_get_vco(struct drm_i915_private *dev_priv)
 {
 	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
 
@@ -4408,7 +4454,23 @@ int valleyview_get_vco(struct drm_i915_p
 		CCK_FUSE_HPLL_FREQ_MASK;
 	mutex_unlock(&dev_priv->dpio_lock);
 
-	return vco_freq[hpll_freq];
+	return vco_freq[hpll_freq] * 1000;
+}
+
+static void vlv_update_cdclk(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz",
+			 dev_priv->vlv_cdclk_freq);
+
+	/*
+	 * Program the gmbus_freq based on the cdclk frequency.
+	 * BSpec erroneously claims we should aim for 4MHz, but
+	 * in fact 1MHz is the correct frequency.
+	 */
+	I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq);
 }
 
 /* Adjust CDclk dividers to allow high res or save power if possible */
@@ -4417,12 +4479,11 @@ static void valleyview_set_cdclk(struct
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 val, cmd;
 
-	WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq);
-	dev_priv->vlv_cdclk_freq = cdclk;
+	WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq);
 
-	if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
+	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
 		cmd = 2;
-	else if (cdclk == 266)
+	else if (cdclk == 266667)
 		cmd = 1;
 	else
 		cmd = 0;
@@ -4439,18 +4500,23 @@ static void valleyview_set_cdclk(struct
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	if (cdclk == 400) {
+	if (cdclk == 400000) {
 		u32 divider, vco;
 
 		vco = valleyview_get_vco(dev_priv);
-		divider = ((vco << 1) / cdclk) - 1;
+		divider = DIV_ROUND_CLOSEST(vco << 1, cdclk) - 1;
 
 		mutex_lock(&dev_priv->dpio_lock);
 		/* adjust cdclk divider */
 		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
-		val &= ~0xf;
+		val &= ~DISPLAY_FREQUENCY_VALUES;
 		val |= divider;
 		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+
+		if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
+			      DISPLAY_FREQUENCY_STATUS) == (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
+			     50))
+			DRM_ERROR("timed out waiting for CDclk change\n");
 		mutex_unlock(&dev_priv->dpio_lock);
 	}
 
@@ -4463,54 +4529,43 @@ static void valleyview_set_cdclk(struct
 	 * For high bandwidth configs, we set a higher latency in the bunit
 	 * so that the core display fetch happens in time to avoid underruns.
 	 */
-	if (cdclk == 400)
+	if (cdclk == 400000)
 		val |= 4500 / 250; /* 4.5 usec */
 	else
 		val |= 3000 / 250; /* 3.0 usec */
 	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
 	mutex_unlock(&dev_priv->dpio_lock);
 
-	/* Since we changed the CDclk, we need to update the GMBUSFREQ too */
-	intel_i2c_reset(dev);
-}
-
-int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
-{
-	int cur_cdclk, vco;
-	int divider;
-
-	vco = valleyview_get_vco(dev_priv);
-
-	mutex_lock(&dev_priv->dpio_lock);
-	divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
-	mutex_unlock(&dev_priv->dpio_lock);
-
-	divider &= 0xf;
-
-	cur_cdclk = (vco << 1) / (divider + 1);
-
-	return cur_cdclk;
+	vlv_update_cdclk(dev);
 }
 
 static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
 				 int max_pixclk)
 {
+	int vco = valleyview_get_vco(dev_priv);
+	int freq_320 = (vco <<  1) % 320000 != 0 ? 333333 : 320000;
+
 	/*
 	 * Really only a few cases to deal with, as only 4 CDclks are supported:
 	 *   200MHz
 	 *   267MHz
-	 *   320MHz
+	 *   320/333MHz (depends on HPLL freq)
 	 *   400MHz
 	 * So we check to see whether we're above 90% of the lower bin and
 	 * adjust if needed.
+	 *
+	 * We seem to get an unstable or solid color picture at 200MHz.
+	 * Not sure what's wrong. For now use 200MHz only when all pipes
+	 * are off.
 	 */
-	if (max_pixclk > 288000) {
-		return 400;
-	} else if (max_pixclk > 240000) {
-		return 320;
-	} else
-		return 266;
-	/* Looks like the 200MHz CDclk freq doesn't work on some configs */
+	if (max_pixclk > freq_320*9/10)
+		return 400000;
+	else if (max_pixclk > 266667*9/10)
+		return freq_320;
+	else if (max_pixclk > 0)
+		return 266667;
+	else
+		return 200000;
 }
 
 /* compute the max pixel clock for new configuration */
@@ -4633,8 +4688,6 @@ static void valleyview_crtc_enable(struc
 
 	intel_crtc_enable_planes(crtc);
 
-	drm_crtc_vblank_on(crtc);
-
 	/* Underruns don't raise interrupts, so check manually. */
 	i9xx_check_fifo_underruns(dev);
 }
@@ -4727,8 +4780,6 @@ static void i9xx_crtc_enable(struct drm_
 	if (IS_GEN2(dev))
 		intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 
-	drm_crtc_vblank_on(crtc);
-
 	/* Underruns don't raise interrupts, so check manually. */
 	i9xx_check_fifo_underruns(dev);
 }
@@ -4768,6 +4819,16 @@ static void i9xx_crtc_disable(struct drm
 	if (IS_GEN2(dev))
 		intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
 
+	/*
+	 * Vblank time updates from the shadow to live plane control register
+	 * are blocked if the memory self-refresh mode is active at that
+	 * moment. So to make sure the plane gets truly disabled, disable
+	 * first the self-refresh mode. The self-refresh enable bit in turn
+	 * will be checked/applied by the HW only at the next frame start
+	 * event which is after the vblank start event, so we need to have a
+	 * wait-for-vblank between disabling the plane and the pipe.
+	 */
+	intel_set_memory_cxsr(dev_priv, false);
 	intel_crtc_disable_planes(crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4776,9 +4837,10 @@ static void i9xx_crtc_disable(struct drm
 	/*
 	 * 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.
+	 * We also need to wait on all gmch platforms because of the
+	 * self-refresh mode constraint explained above.
 	 */
-	if (IS_GEN2(dev))
-		intel_wait_for_vblank(dev, pipe);
+	intel_wait_for_vblank(dev, pipe);
 
 	intel_disable_pipe(dev_priv, pipe);
 
@@ -4805,7 +4867,6 @@ static void i9xx_crtc_disable(struct drm
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
-	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4843,23 +4904,49 @@ static void intel_crtc_update_sarea(stru
 	}
 }
 
+/* Master function to enable/disable CRTC and corresponding power wells */
+void intel_crtc_control(struct drm_crtc *crtc, bool enable)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum intel_display_power_domain domain;
+	unsigned long domains;
+
+	if (enable) {
+		if (!intel_crtc->active) {
+			domains = get_crtc_power_domains(crtc);
+			for_each_power_domain(domain, domains)
+				intel_display_power_get(dev_priv, domain);
+			intel_crtc->enabled_power_domains = domains;
+
+			dev_priv->display.crtc_enable(crtc);
+		}
+	} else {
+		if (intel_crtc->active) {
+			dev_priv->display.crtc_disable(crtc);
+
+			domains = intel_crtc->enabled_power_domains;
+			for_each_power_domain(domain, domains)
+				intel_display_power_put(dev_priv, domain);
+			intel_crtc->enabled_power_domains = 0;
+		}
+	}
+}
+
 /**
  * Sets the power management mode of the pipe and plane.
  */
 void intel_crtc_update_dpms(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *intel_encoder;
 	bool enable = false;
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 		enable |= intel_encoder->connectors_active;
 
-	if (enable)
-		dev_priv->display.crtc_enable(crtc);
-	else
-		dev_priv->display.crtc_disable(crtc);
+	intel_crtc_control(crtc, enable);
 
 	intel_crtc_update_sarea(crtc, enable);
 }
@@ -4869,6 +4956,8 @@ static void intel_crtc_disable(struct dr
 	struct drm_device *dev = crtc->dev;
 	struct drm_connector *connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb);
+	enum pipe pipe = to_intel_crtc(crtc)->pipe;
 
 	/* crtc should still be enabled when we disable it. */
 	WARN_ON(!crtc->enabled);
@@ -4877,13 +4966,11 @@ static void intel_crtc_disable(struct dr
 	intel_crtc_update_sarea(crtc, false);
 	dev_priv->display.off(crtc);
 
-	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
-	assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
-	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
-
 	if (crtc->primary->fb) {
 		mutex_lock(&dev->struct_mutex);
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
+		intel_unpin_fb_obj(old_obj);
+		i915_gem_track_fb(old_obj, NULL,
+				  INTEL_FRONTBUFFER_PRIMARY(pipe));
 		mutex_unlock(&dev->struct_mutex);
 		crtc->primary->fb = NULL;
 	}
@@ -4939,24 +5026,31 @@ static void intel_connector_check_state(
 			      connector->base.base.id,
 			      connector->base.name);
 
+		/* there is no real hw state for MST connectors */
+		if (connector->mst_port)
+			return;
+
 		WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
 		     "wrong connector dpms state\n");
 		WARN(connector->base.encoder != &encoder->base,
 		     "active connector not linked to encoder\n");
-		WARN(!encoder->connectors_active,
-		     "encoder->connectors_active not set\n");
 
-		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
-		WARN(!encoder_enabled, "encoder not enabled\n");
-		if (WARN_ON(!encoder->base.crtc))
-			return;
+		if (encoder) {
+			WARN(!encoder->connectors_active,
+			     "encoder->connectors_active not set\n");
 
-		crtc = encoder->base.crtc;
+			encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+			WARN(!encoder_enabled, "encoder not enabled\n");
+			if (WARN_ON(!encoder->base.crtc))
+				return;
 
-		WARN(!crtc->enabled, "crtc not enabled\n");
-		WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
-		WARN(pipe != to_intel_crtc(crtc)->pipe,
-		     "encoder active on the wrong pipe\n");
+			crtc = encoder->base.crtc;
+
+			WARN(!crtc->enabled, "crtc not enabled\n");
+			WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
+			WARN(pipe != to_intel_crtc(crtc)->pipe,
+			     "encoder active on the wrong pipe\n");
+		}
 	}
 }
 
@@ -5161,9 +5255,11 @@ static int intel_crtc_compute_config(str
 	if (HAS_IPS(dev))
 		hsw_compute_ips_config(crtc, pipe_config);
 
-	/* XXX: PCH clock sharing is done in ->mode_set, so make sure the old
-	 * clock survives for now. */
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+	/*
+	 * XXX: PCH/WRPLL clock sharing is done in ->mode_set, so make sure the
+	 * old clock survives for now.
+	 */
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev) || HAS_DDI(dev))
 		pipe_config->shared_dpll = crtc->config.shared_dpll;
 
 	if (pipe_config->has_pch_encoder)
@@ -5174,7 +5270,22 @@ static int intel_crtc_compute_config(str
 
 static int valleyview_get_display_clock_speed(struct drm_device *dev)
 {
-	return 400000; /* FIXME */
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int vco = valleyview_get_vco(dev_priv);
+	u32 val;
+	int divider;
+
+	mutex_lock(&dev_priv->dpio_lock);
+	val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	divider = val & DISPLAY_FREQUENCY_VALUES;
+
+	WARN((val & DISPLAY_FREQUENCY_STATUS) !=
+	     (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
+	     "cdclk change in progress\n");
+
+	return DIV_ROUND_CLOSEST(vco << 1, divider + 1);
 }
 
 static int i945_get_display_clock_speed(struct drm_device *dev)
@@ -6060,6 +6171,10 @@ static void vlv_crtc_clock_get(struct in
 	u32 mdiv;
 	int refclk = 100000;
 
+	/* In case of MIPI DPLL will not even be used */
+	if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
+		return;
+
 	mutex_lock(&dev_priv->dpio_lock);
 	mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
 	mutex_unlock(&dev_priv->dpio_lock);
@@ -6125,8 +6240,8 @@ static void i9xx_get_plane_config(struct
 	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
 					    plane_config->tiled);
 
-	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
-				   aligned_height, PAGE_SIZE);
+	plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
+					aligned_height);
 
 	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
 		      pipe, plane, crtc->base.primary->fb->width,
@@ -7145,8 +7260,8 @@ static void ironlake_get_plane_config(st
 	aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
 					    plane_config->tiled);
 
-	plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
-				   aligned_height, PAGE_SIZE);
+	plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
+					aligned_height);
 
 	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
 		      pipe, plane, crtc->base.primary->fb->width,
@@ -7163,6 +7278,10 @@ static bool ironlake_get_pipe_config(str
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
+	if (!intel_display_power_enabled(dev_priv,
+					 POWER_DOMAIN_PIPE(crtc->pipe)))
+		return false;
+
 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
@@ -7237,7 +7356,6 @@ static bool ironlake_get_pipe_config(str
 static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
 	struct intel_crtc *crtc;
 
 	for_each_intel_crtc(dev, crtc)
@@ -7245,14 +7363,15 @@ static void assert_can_disable_lcpll(str
 		     pipe_name(crtc->pipe));
 
 	WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
-	WARN(plls->spll_refcount, "SPLL enabled\n");
-	WARN(plls->wrpll1_refcount, "WRPLL1 enabled\n");
-	WARN(plls->wrpll2_refcount, "WRPLL2 enabled\n");
+	WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
+	WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
+	WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
 	WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
 	WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
 	     "CPU PWM1 enabled\n");
-	WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
-	     "CPU PWM2 enabled\n");
+	if (IS_HASWELL(dev))
+		WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
+		     "CPU PWM2 enabled\n");
 	WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
 	     "PCH PWM1 enabled\n");
 	WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
@@ -7265,7 +7384,17 @@ static void assert_can_disable_lcpll(str
 	 * gen-specific and since we only disable LCPLL after we fully disable
 	 * the interrupts, the check below should be enough.
 	 */
-	WARN(!dev_priv->pm.irqs_disabled, "IRQs enabled\n");
+	WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
+}
+
+static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (IS_HASWELL(dev))
+		return I915_READ(D_COMP_HSW);
+	else
+		return I915_READ(D_COMP_BDW);
 }
 
 static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
@@ -7276,12 +7405,12 @@ static void hsw_write_dcomp(struct drm_i
 		mutex_lock(&dev_priv->rps.hw_lock);
 		if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
 					    val))
-			DRM_ERROR("Failed to disable D_COMP\n");
+			DRM_ERROR("Failed to write to D_COMP\n");
 		mutex_unlock(&dev_priv->rps.hw_lock);
 	} else {
-		I915_WRITE(D_COMP, val);
+		I915_WRITE(D_COMP_BDW, val);
+		POSTING_READ(D_COMP_BDW);
 	}
-	POSTING_READ(D_COMP);
 }
 
 /*
@@ -7319,12 +7448,13 @@ static void hsw_disable_lcpll(struct drm
 	if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1))
 		DRM_ERROR("LCPLL still locked\n");
 
-	val = I915_READ(D_COMP);
+	val = hsw_read_dcomp(dev_priv);
 	val |= D_COMP_COMP_DISABLE;
 	hsw_write_dcomp(dev_priv, val);
 	ndelay(100);
 
-	if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1))
+	if (wait_for((hsw_read_dcomp(dev_priv) & D_COMP_RCOMP_IN_PROGRESS) == 0,
+		     1))
 		DRM_ERROR("D_COMP RCOMP still in progress\n");
 
 	if (allow_power_down) {
@@ -7373,7 +7503,7 @@ static void hsw_restore_lcpll(struct drm
 		POSTING_READ(LCPLL_CTL);
 	}
 
-	val = I915_READ(D_COMP);
+	val = hsw_read_dcomp(dev_priv);
 	val |= D_COMP_COMP_FORCE;
 	val &= ~D_COMP_COMP_DISABLE;
 	hsw_write_dcomp(dev_priv, val);
@@ -7479,13 +7609,59 @@ static int haswell_crtc_mode_set(struct
 
 	if (!intel_ddi_pll_select(intel_crtc))
 		return -EINVAL;
-	intel_ddi_pll_enable(intel_crtc);
 
 	intel_crtc->lowfreq_avail = false;
 
 	return 0;
 }
 
+static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
+				       struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_shared_dpll *pll;
+	enum port port;
+	uint32_t tmp;
+
+	tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
+
+	port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
+
+	pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
+
+	switch (pipe_config->ddi_pll_sel) {
+	case PORT_CLK_SEL_WRPLL1:
+		pipe_config->shared_dpll = DPLL_ID_WRPLL1;
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		pipe_config->shared_dpll = DPLL_ID_WRPLL2;
+		break;
+	}
+
+	if (pipe_config->shared_dpll >= 0) {
+		pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
+
+		WARN_ON(!pll->get_hw_state(dev_priv, pll,
+					   &pipe_config->dpll_hw_state));
+	}
+
+	/*
+	 * Haswell has only FDI/PCH transcoder A. It is which is connected to
+	 * DDI E. So just check whether this pipe is wired to DDI E and whether
+	 * the PCH transcoder is on.
+	 */
+	if ((port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
+		pipe_config->has_pch_encoder = true;
+
+		tmp = I915_READ(FDI_RX_CTL(PIPE_A));
+		pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
+					  FDI_DP_PORT_WIDTH_SHIFT) + 1;
+
+		ironlake_get_fdi_m_n_config(crtc, pipe_config);
+	}
+}
+
 static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 				    struct intel_crtc_config *pipe_config)
 {
@@ -7531,22 +7707,7 @@ static bool haswell_get_pipe_config(stru
 	if (!(tmp & PIPECONF_ENABLE))
 		return false;
 
-	/*
-	 * Haswell has only FDI/PCH transcoder A. It is which is connected to
-	 * DDI E. So just check whether this pipe is wired to DDI E and whether
-	 * the PCH transcoder is on.
-	 */
-	tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
-	if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
-	    I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
-		pipe_config->has_pch_encoder = true;
-
-		tmp = I915_READ(FDI_RX_CTL(PIPE_A));
-		pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
-					  FDI_DP_PORT_WIDTH_SHIFT) + 1;
-
-		ironlake_get_fdi_m_n_config(crtc, pipe_config);
-	}
+	haswell_get_ddi_port_state(crtc, pipe_config);
 
 	intel_get_pipe_timings(crtc, pipe_config);
 
@@ -7991,8 +8152,8 @@ static void intel_crtc_update_cursor(str
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	int x = intel_crtc->cursor_x;
-	int y = intel_crtc->cursor_y;
+	int x = crtc->cursor_x;
+	int y = crtc->cursor_y;
 	u32 base = 0, pos = 0;
 
 	if (on)
@@ -8036,21 +8197,27 @@ static void intel_crtc_update_cursor(str
 	intel_crtc->cursor_base = base;
 }
 
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
-				 struct drm_file *file,
-				 uint32_t handle,
-				 uint32_t width, uint32_t height)
+/*
+ * intel_crtc_cursor_set_obj - Set cursor to specified GEM object
+ *
+ * Note that the object's reference will be consumed if the update fails.  If
+ * the update succeeds, the reference of the old object (if any) will be
+ * consumed.
+ */
+static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
+				     struct drm_i915_gem_object *obj,
+				     uint32_t width, uint32_t height)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_i915_gem_object *obj;
+	enum pipe pipe = intel_crtc->pipe;
 	unsigned old_width;
 	uint32_t addr;
 	int ret;
 
 	/* if we want to turn off the cursor ignore width and height */
-	if (!handle) {
+	if (!obj) {
 		DRM_DEBUG_KMS("cursor off\n");
 		addr = 0;
 		obj = NULL;
@@ -8066,12 +8233,8 @@ static int intel_crtc_cursor_set(struct
 		return -EINVAL;
 	}
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
-	if (&obj->base == NULL)
-		return -ENOENT;
-
 	if (obj->base.size < width * height * 4) {
-		DRM_DEBUG_KMS("buffer is to small\n");
+		DRM_DEBUG_KMS("buffer is too small\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -8087,6 +8250,15 @@ static int intel_crtc_cursor_set(struct
 			goto fail_locked;
 		}
 
+		/*
+		 * Global gtt pte registers are special registers which actually
+		 * forward writes to a chunk of system memory. Which means that
+		 * there is no risk that the register values disappear as soon
+		 * as we call intel_runtime_pm_put(), so it is correct to wrap
+		 * only the pin/unpin/fence and not more.
+		 */
+		intel_runtime_pm_get(dev_priv);
+
 		/* Note that the w/a also requires 2 PTE of padding following
 		 * the bo. We currently fill all unused PTE with the shadow
 		 * page and so we should always have valid PTE following the
@@ -8099,16 +8271,20 @@ static int intel_crtc_cursor_set(struct
 		ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
 		if (ret) {
 			DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
+			intel_runtime_pm_put(dev_priv);
 			goto fail_locked;
 		}
 
 		ret = i915_gem_object_put_fence(obj);
 		if (ret) {
 			DRM_DEBUG_KMS("failed to release fence for cursor");
+			intel_runtime_pm_put(dev_priv);
 			goto fail_unpin;
 		}
 
 		addr = i915_gem_obj_ggtt_offset(obj);
+
+		intel_runtime_pm_put(dev_priv);
 	} else {
 		int align = IS_I830(dev) ? 16 * 1024 : 256;
 		ret = i915_gem_object_attach_phys(obj, align);
@@ -8126,9 +8302,10 @@ static int intel_crtc_cursor_set(struct
 	if (intel_crtc->cursor_bo) {
 		if (!INTEL_INFO(dev)->cursor_needs_physical)
 			i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo);
-		drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
 	}
 
+	i915_gem_track_fb(intel_crtc->cursor_bo, obj,
+			  INTEL_FRONTBUFFER_CURSOR(pipe));
 	mutex_unlock(&dev->struct_mutex);
 
 	old_width = intel_crtc->cursor_width;
@@ -8144,6 +8321,8 @@ static int intel_crtc_cursor_set(struct
 		intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 	}
 
+	intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe));
+
 	return 0;
 fail_unpin:
 	i915_gem_object_unpin_from_display_plane(obj);
@@ -8154,19 +8333,6 @@ fail:
 	return ret;
 }
 
-static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX);
-	intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX);
-
-	if (intel_crtc->active)
-		intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
-
-	return 0;
-}
-
 static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
 				 u16 *blue, uint32_t start, uint32_t size)
 {
@@ -8242,7 +8408,7 @@ static u32
 intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
 {
 	u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
-	return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
+	return PAGE_ALIGN(pitch * mode->vdisplay);
 }
 
 static struct drm_framebuffer *
@@ -8319,8 +8485,6 @@ bool intel_get_load_detect_pipe(struct d
 		      connector->base.id, connector->name,
 		      encoder->base.id, encoder->name);
 
-	drm_modeset_acquire_init(ctx, 0);
-
 retry:
 	ret = drm_modeset_lock(&config->connection_mutex, ctx);
 	if (ret)
@@ -8359,10 +8523,14 @@ retry:
 		i++;
 		if (!(encoder->possible_crtcs & (1 << i)))
 			continue;
-		if (!possible_crtc->enabled) {
-			crtc = possible_crtc;
-			break;
-		}
+		if (possible_crtc->enabled)
+			continue;
+		/* This can occur when applying the pipe A quirk on resume. */
+		if (to_intel_crtc(possible_crtc)->new_enabled)
+			continue;
+
+		crtc = possible_crtc;
+		break;
 	}
 
 	/*
@@ -8431,15 +8599,11 @@ fail_unlock:
 		goto retry;
 	}
 
-	drm_modeset_drop_locks(ctx);
-	drm_modeset_acquire_fini(ctx);
-
 	return false;
 }
 
 void intel_release_load_detect_pipe(struct drm_connector *connector,
-				    struct intel_load_detect_pipe *old,
-				    struct drm_modeset_acquire_ctx *ctx)
+				    struct intel_load_detect_pipe *old)
 {
 	struct intel_encoder *intel_encoder =
 		intel_attached_encoder(connector);
@@ -8463,17 +8627,12 @@ void intel_release_load_detect_pipe(stru
 			drm_framebuffer_unreference(old->release_fb);
 		}
 
-		goto unlock;
 		return;
 	}
 
 	/* Switch crtc and encoder back off if necessary */
 	if (old->dpms_mode != DRM_MODE_DPMS_ON)
 		connector->funcs->dpms(connector, old->dpms_mode);
-
-unlock:
-	drm_modeset_drop_locks(ctx);
-	drm_modeset_acquire_fini(ctx);
 }
 
 static int i9xx_pll_refclk(struct drm_device *dev,
@@ -8667,16 +8826,14 @@ struct drm_display_mode *intel_crtc_mode
 	return mode;
 }
 
-static void intel_increase_pllclock(struct drm_crtc *crtc)
+static void intel_increase_pllclock(struct drm_device *dev,
+				    enum pipe pipe)
 {
-	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
 	int dpll_reg = DPLL(pipe);
 	int dpll;
 
-	if (HAS_PCH_SPLIT(dev))
+	if (!HAS_GMCH_DISPLAY(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -8704,7 +8861,7 @@ static void intel_decrease_pllclock(stru
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	if (HAS_PCH_SPLIT(dev))
+	if (!HAS_GMCH_DISPLAY(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -8773,28 +8930,179 @@ out:
 	intel_runtime_pm_put(dev_priv);
 }
 
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
-			struct intel_engine_cs *ring)
+
+/**
+ * intel_mark_fb_busy - mark given planes as busy
+ * @dev: DRM device
+ * @frontbuffer_bits: bits for the affected planes
+ * @ring: optional ring for asynchronous commands
+ *
+ * This function gets called every time the screen contents change. It can be
+ * used to keep e.g. the update rate at the nominal refresh rate with DRRS.
+ */
+static void intel_mark_fb_busy(struct drm_device *dev,
+			       unsigned frontbuffer_bits,
+			       struct intel_engine_cs *ring)
 {
-	struct drm_device *dev = obj->base.dev;
-	struct drm_crtc *crtc;
+	enum pipe pipe;
 
 	if (!i915.powersave)
 		return;
 
-	for_each_crtc(dev, crtc) {
-		if (!crtc->primary->fb)
-			continue;
-
-		if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
+	for_each_pipe(pipe) {
+		if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)))
 			continue;
 
-		intel_increase_pllclock(crtc);
+		intel_increase_pllclock(dev, pipe);
 		if (ring && intel_fbc_enabled(dev))
 			ring->fbc_dirty = true;
 	}
 }
 
+/**
+ * intel_fb_obj_invalidate - invalidate frontbuffer object
+ * @obj: GEM object to invalidate
+ * @ring: set for asynchronous rendering
+ *
+ * This function gets called every time rendering on the given object starts and
+ * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must
+ * be invalidated. If @ring is non-NULL any subsequent invalidation will be delayed
+ * until the rendering completes or a flip on this frontbuffer plane is
+ * scheduled.
+ */
+void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+			     struct intel_engine_cs *ring)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (!obj->frontbuffer_bits)
+		return;
+
+	if (ring) {
+		mutex_lock(&dev_priv->fb_tracking.lock);
+		dev_priv->fb_tracking.busy_bits
+			|= obj->frontbuffer_bits;
+		dev_priv->fb_tracking.flip_bits
+			&= ~obj->frontbuffer_bits;
+		mutex_unlock(&dev_priv->fb_tracking.lock);
+	}
+
+	intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
+
+	intel_edp_psr_invalidate(dev, obj->frontbuffer_bits);
+}
+
+/**
+ * intel_frontbuffer_flush - flush frontbuffer
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called every time rendering on the given planes has
+ * completed and frontbuffer caching can be started again. Flushes will get
+ * delayed if they're blocked by some oustanding asynchronous rendering.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flush(struct drm_device *dev,
+			     unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* Delay flushing when rings are still busy.*/
+	mutex_lock(&dev_priv->fb_tracking.lock);
+	frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits;
+	mutex_unlock(&dev_priv->fb_tracking.lock);
+
+	intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
+
+	intel_edp_psr_flush(dev, frontbuffer_bits);
+}
+
+/**
+ * intel_fb_obj_flush - flush frontbuffer object
+ * @obj: GEM object to flush
+ * @retire: set when retiring asynchronous rendering
+ *
+ * This function gets called every time rendering on the given object has
+ * completed and frontbuffer caching can be started again. If @retire is true
+ * then any delayed flushes will be unblocked.
+ */
+void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
+			bool retire)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned frontbuffer_bits;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (!obj->frontbuffer_bits)
+		return;
+
+	frontbuffer_bits = obj->frontbuffer_bits;
+
+	if (retire) {
+		mutex_lock(&dev_priv->fb_tracking.lock);
+		/* Filter out new bits since rendering started. */
+		frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
+
+		dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
+		mutex_unlock(&dev_priv->fb_tracking.lock);
+	}
+
+	intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
+/**
+ * intel_frontbuffer_flip_prepare - prepare asnychronous frontbuffer flip
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after scheduling a flip on @obj. The actual
+ * frontbuffer flushing will be delayed until completion is signalled with
+ * intel_frontbuffer_flip_complete. If an invalidate happens in between this
+ * flush will be cancelled.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flip_prepare(struct drm_device *dev,
+				    unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->fb_tracking.lock);
+	dev_priv->fb_tracking.flip_bits
+		|= frontbuffer_bits;
+	mutex_unlock(&dev_priv->fb_tracking.lock);
+}
+
+/**
+ * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flush
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after the flip has been latched and will complete
+ * on the next vblank. It will execute the fush if it hasn't been cancalled yet.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flip_complete(struct drm_device *dev,
+				     unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->fb_tracking.lock);
+	/* Mask any cancelled flips. */
+	frontbuffer_bits &= dev_priv->fb_tracking.flip_bits;
+	dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
+	mutex_unlock(&dev_priv->fb_tracking.lock);
+
+	intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
 static void intel_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -8812,8 +9120,6 @@ static void intel_crtc_destroy(struct dr
 		kfree(work);
 	}
 
-	intel_crtc_cursor_set(crtc, NULL, 0, 0, 0);
-
 	drm_crtc_cleanup(crtc);
 
 	kfree(intel_crtc);
@@ -8824,6 +9130,7 @@ static void intel_unpin_work_fn(struct w
 	struct intel_unpin_work *work =
 		container_of(__work, struct intel_unpin_work, work);
 	struct drm_device *dev = work->crtc->dev;
+	enum pipe pipe = to_intel_crtc(work->crtc)->pipe;
 
 	mutex_lock(&dev->struct_mutex);
 	intel_unpin_fb_obj(work->old_fb_obj);
@@ -8833,6 +9140,8 @@ static void intel_unpin_work_fn(struct w
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
 
+	intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
+
 	BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
 	atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
 
@@ -9202,6 +9511,150 @@ static int intel_gen7_queue_flip(struct
 	return 0;
 }
 
+static bool use_mmio_flip(struct intel_engine_cs *ring,
+			  struct drm_i915_gem_object *obj)
+{
+	/*
+	 * This is not being used for older platforms, because
+	 * non-availability of flip done interrupt forces us to use
+	 * CS flips. Older platforms derive flip done using some clever
+	 * tricks involving the flip_pending status bits and vblank irqs.
+	 * So using MMIO flips there would disrupt this mechanism.
+	 */
+
+	if (ring == NULL)
+		return true;
+
+	if (INTEL_INFO(ring->dev)->gen < 5)
+		return false;
+
+	if (i915.use_mmio_flip < 0)
+		return false;
+	else if (i915.use_mmio_flip > 0)
+		return true;
+	else
+		return ring != obj->ring;
+}
+
+static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_framebuffer *intel_fb =
+		to_intel_framebuffer(intel_crtc->base.primary->fb);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
+	u32 dspcntr;
+	u32 reg;
+
+	intel_mark_page_flip_active(intel_crtc);
+
+	reg = DSPCNTR(intel_crtc->plane);
+	dspcntr = I915_READ(reg);
+
+	if (INTEL_INFO(dev)->gen >= 4) {
+		if (obj->tiling_mode != I915_TILING_NONE)
+			dspcntr |= DISPPLANE_TILED;
+		else
+			dspcntr &= ~DISPPLANE_TILED;
+	}
+	I915_WRITE(reg, dspcntr);
+
+	I915_WRITE(DSPSURF(intel_crtc->plane),
+		   intel_crtc->unpin_work->gtt_offset);
+	POSTING_READ(DSPSURF(intel_crtc->plane));
+}
+
+static int intel_postpone_flip(struct drm_i915_gem_object *obj)
+{
+	struct intel_engine_cs *ring;
+	int ret;
+
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	if (!obj->last_write_seqno)
+		return 0;
+
+	ring = obj->ring;
+
+	if (i915_seqno_passed(ring->get_seqno(ring, true),
+			      obj->last_write_seqno))
+		return 0;
+
+	ret = i915_gem_check_olr(ring, obj->last_write_seqno);
+	if (ret)
+		return ret;
+
+	if (WARN_ON(!ring->irq_get(ring)))
+		return 0;
+
+	return 1;
+}
+
+void intel_notify_mmio_flip(struct intel_engine_cs *ring)
+{
+	struct drm_i915_private *dev_priv = to_i915(ring->dev);
+	struct intel_crtc *intel_crtc;
+	unsigned long irq_flags;
+	u32 seqno;
+
+	seqno = ring->get_seqno(ring, false);
+
+	spin_lock_irqsave(&dev_priv->mmio_flip_lock, irq_flags);
+	for_each_intel_crtc(ring->dev, intel_crtc) {
+		struct intel_mmio_flip *mmio_flip;
+
+		mmio_flip = &intel_crtc->mmio_flip;
+		if (mmio_flip->seqno == 0)
+			continue;
+
+		if (ring->id != mmio_flip->ring_id)
+			continue;
+
+		if (i915_seqno_passed(seqno, mmio_flip->seqno)) {
+			intel_do_mmio_flip(intel_crtc);
+			mmio_flip->seqno = 0;
+			ring->irq_put(ring);
+		}
+	}
+	spin_unlock_irqrestore(&dev_priv->mmio_flip_lock, irq_flags);
+}
+
+static int intel_queue_mmio_flip(struct drm_device *dev,
+				 struct drm_crtc *crtc,
+				 struct drm_framebuffer *fb,
+				 struct drm_i915_gem_object *obj,
+				 struct intel_engine_cs *ring,
+				 uint32_t flags)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	unsigned long irq_flags;
+	int ret;
+
+	if (WARN_ON(intel_crtc->mmio_flip.seqno))
+		return -EBUSY;
+
+	ret = intel_postpone_flip(obj);
+	if (ret < 0)
+		return ret;
+	if (ret == 0) {
+		intel_do_mmio_flip(intel_crtc);
+		return 0;
+	}
+
+	spin_lock_irqsave(&dev_priv->mmio_flip_lock, irq_flags);
+	intel_crtc->mmio_flip.seqno = obj->last_write_seqno;
+	intel_crtc->mmio_flip.ring_id = obj->ring->id;
+	spin_unlock_irqrestore(&dev_priv->mmio_flip_lock, irq_flags);
+
+	/*
+	 * Double check to catch cases where irq fired before
+	 * mmio flip data was ready
+	 */
+	intel_notify_mmio_flip(obj->ring);
+	return 0;
+}
+
 static int intel_default_queue_flip(struct drm_device *dev,
 				    struct drm_crtc *crtc,
 				    struct drm_framebuffer *fb,
@@ -9220,13 +9673,22 @@ static int intel_crtc_page_flip(struct d
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *old_fb = crtc->primary->fb;
-	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
 	struct intel_unpin_work *work;
 	struct intel_engine_cs *ring;
 	unsigned long flags;
 	int ret;
 
+	/*
+	 * drm_mode_page_flip_ioctl() should already catch this, but double
+	 * check to be safe.  In the future we may enable pageflipping from
+	 * a disabled primary plane.
+	 */
+	if (WARN_ON(intel_fb_obj(old_fb) == NULL))
+		return -EBUSY;
+
 	/* Can't change pixel format via MI display flips. */
 	if (fb->pixel_format != crtc->primary->fb->pixel_format)
 		return -EINVAL;
@@ -9249,7 +9711,7 @@ static int intel_crtc_page_flip(struct d
 
 	work->event = event;
 	work->crtc = crtc;
-	work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
+	work->old_fb_obj = intel_fb_obj(old_fb);
 	INIT_WORK(&work->work, intel_unpin_work_fn);
 
 	ret = drm_crtc_vblank_get(crtc);
@@ -9290,10 +9752,15 @@ static int intel_crtc_page_flip(struct d
 	intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
-		work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(intel_crtc->pipe)) + 1;
+		work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(pipe)) + 1;
 
 	if (IS_VALLEYVIEW(dev)) {
 		ring = &dev_priv->ring[BCS];
+		if (obj->tiling_mode != work->old_fb_obj->tiling_mode)
+			/* vlv: DISPLAY_FLIP fails to change tiling */
+			ring = NULL;
+	} else if (IS_IVYBRIDGE(dev)) {
+		ring = &dev_priv->ring[BCS];
 	} else if (INTEL_INFO(dev)->gen >= 7) {
 		ring = obj->ring;
 		if (ring == NULL || ring->id != RCS)
@@ -9309,12 +9776,20 @@ static int intel_crtc_page_flip(struct d
 	work->gtt_offset =
 		i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
 
-	ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, page_flip_flags);
+	if (use_mmio_flip(ring, obj))
+		ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
+					    page_flip_flags);
+	else
+		ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
+				page_flip_flags);
 	if (ret)
 		goto cleanup_unpin;
 
+	i915_gem_track_fb(work->old_fb_obj, obj,
+			  INTEL_FRONTBUFFER_PRIMARY(pipe));
+
 	intel_disable_fbc(dev);
-	intel_mark_fb_busy(obj, NULL);
+	intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
 	mutex_unlock(&dev->struct_mutex);
 
 	trace_i915_flip_request(intel_crtc->plane, obj);
@@ -9344,7 +9819,7 @@ out_hang:
 		intel_crtc_wait_for_pending_flips(crtc);
 		ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb);
 		if (ret == 0 && event)
-			drm_send_vblank_event(dev, intel_crtc->pipe, event);
+			drm_send_vblank_event(dev, pipe, event);
 	}
 	return ret;
 }
@@ -10017,11 +10492,14 @@ intel_pipe_config_compare(struct drm_dev
 
 	PIPE_CONF_CHECK_I(double_wide);
 
+	PIPE_CONF_CHECK_X(ddi_pll_sel);
+
 	PIPE_CONF_CHECK_I(shared_dpll);
 	PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
 	PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
+	PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
 
 	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
 		PIPE_CONF_CHECK_I(pipe_bpp);
@@ -10083,6 +10561,14 @@ check_encoder_state(struct drm_device *d
 			if (connector->base.dpms != DRM_MODE_DPMS_OFF)
 				active = true;
 		}
+		/*
+		 * for MST connectors if we unplug the connector is gone
+		 * away but the encoder is still connected to a crtc
+		 * until a modeset happens in response to the hotplug.
+		 */
+		if (!enabled && encoder->base.encoder_type == DRM_MODE_ENCODER_DPMST)
+			continue;
+
 		WARN(!!encoder->base.crtc != enabled,
 		     "encoder's enabled state mismatch "
 		     "(expected %i, found %i)\n",
@@ -10378,20 +10864,23 @@ static int __intel_set_mode(struct drm_c
 	 * on the DPLL.
 	 */
 	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
-		struct drm_framebuffer *old_fb;
+		struct drm_framebuffer *old_fb = crtc->primary->fb;
+		struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
+		struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 
 		mutex_lock(&dev->struct_mutex);
 		ret = intel_pin_and_fence_fb_obj(dev,
-						 to_intel_framebuffer(fb)->obj,
+						 obj,
 						 NULL);
 		if (ret != 0) {
 			DRM_ERROR("pin & fence failed\n");
 			mutex_unlock(&dev->struct_mutex);
 			goto done;
 		}
-		old_fb = crtc->primary->fb;
 		if (old_fb)
-			intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
+			intel_unpin_fb_obj(old_obj);
+		i915_gem_track_fb(old_obj, obj,
+				  INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
 		mutex_unlock(&dev->struct_mutex);
 
 		crtc->primary->fb = fb;
@@ -10563,12 +11052,17 @@ intel_set_config_compute_mode_changes(st
 	if (is_crtc_connector_off(set)) {
 		config->mode_changed = true;
 	} else if (set->crtc->primary->fb != set->fb) {
-		/* If we have no fb then treat it as a full mode set */
+		/*
+		 * If we have no fb, we can only flip as long as the crtc is
+		 * active, otherwise we need a full mode set.  The crtc may
+		 * be active if we've only disabled the primary plane, or
+		 * in fastboot situations.
+		 */
 		if (set->crtc->primary->fb == NULL) {
 			struct intel_crtc *intel_crtc =
 				to_intel_crtc(set->crtc);
 
-			if (intel_crtc->active && i915.fastboot) {
+			if (intel_crtc->active) {
 				DRM_DEBUG_KMS("crtc has no fb, will flip\n");
 				config->fb_changed = true;
 			} else {
@@ -10620,7 +11114,7 @@ intel_modeset_stage_output_state(struct
 		 * for them. */
 		for (ro = 0; ro < set->num_connectors; ro++) {
 			if (set->connectors[ro] == &connector->base) {
-				connector->new_encoder = connector->encoder;
+				connector->new_encoder = intel_find_encoder(connector, to_intel_crtc(set->crtc)->pipe);
 				break;
 			}
 		}
@@ -10666,7 +11160,7 @@ intel_modeset_stage_output_state(struct
 					 new_crtc)) {
 			return -EINVAL;
 		}
-		connector->encoder->new_crtc = to_intel_crtc(new_crtc);
+		connector->new_encoder->new_crtc = to_intel_crtc(new_crtc);
 
 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
 			connector->base.base.id,
@@ -10700,7 +11194,12 @@ intel_modeset_stage_output_state(struct
 		}
 	}
 	/* Now we've also updated encoder->new_crtc for all encoders. */
-
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->new_encoder)
+			if (connector->new_encoder != connector->encoder)
+				connector->encoder = connector->new_encoder;
+	}
 	for_each_intel_crtc(dev, crtc) {
 		crtc->new_enabled = false;
 
@@ -10806,10 +11305,24 @@ static int intel_crtc_set_config(struct
 		ret = intel_set_mode(set->crtc, set->mode,
 				     set->x, set->y, set->fb);
 	} else if (config->fb_changed) {
+		struct drm_i915_private *dev_priv = dev->dev_private;
+		struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
+
 		intel_crtc_wait_for_pending_flips(set->crtc);
 
 		ret = intel_pipe_set_base(set->crtc,
 					  set->x, set->y, set->fb);
+
+		/*
+		 * We need to make sure the primary plane is re-enabled if it
+		 * has previously been turned off.
+		 */
+		if (!intel_crtc->primary_enabled && ret == 0) {
+			WARN_ON(!intel_crtc->active);
+			intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
+						      intel_crtc->pipe);
+		}
+
 		/*
 		 * In the fastboot case this may be our only check of the
 		 * state after boot.  It would be better to only do it on
@@ -10850,26 +11363,21 @@ out_config:
 }
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.cursor_set = intel_crtc_cursor_set,
-	.cursor_move = intel_crtc_cursor_move,
 	.gamma_set = intel_crtc_gamma_set,
 	.set_config = intel_crtc_set_config,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
 };
 
-static void intel_cpu_pll_init(struct drm_device *dev)
-{
-	if (HAS_DDI(dev))
-		intel_ddi_pll_init(dev);
-}
-
 static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 				      struct intel_shared_dpll *pll,
 				      struct intel_dpll_hw_state *hw_state)
 {
 	uint32_t val;
 
+	if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
 	val = I915_READ(PCH_DPLL(pll->id));
 	hw_state->dpll = val;
 	hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
@@ -10951,7 +11459,9 @@ static void intel_shared_dpll_init(struc
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+	if (HAS_DDI(dev))
+		intel_ddi_pll_init(dev);
+	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		ibx_pch_dpll_init(dev);
 	else
 		dev_priv->num_shared_dpll = 0;
@@ -10959,17 +11469,328 @@ static void intel_shared_dpll_init(struc
 	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
 }
 
+static int
+intel_primary_plane_disable(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct intel_crtc *intel_crtc;
+
+	if (!plane->fb)
+		return 0;
+
+	BUG_ON(!plane->crtc);
+
+	intel_crtc = to_intel_crtc(plane->crtc);
+
+	/*
+	 * Even though we checked plane->fb above, it's still possible that
+	 * the primary plane has been implicitly disabled because the crtc
+	 * coordinates given weren't visible, or because we detected
+	 * that it was 100% covered by a sprite plane.  Or, the CRTC may be
+	 * off and we've set a fb, but haven't actually turned on the CRTC yet.
+	 * In either case, we need to unpin the FB and let the fb pointer get
+	 * updated, but otherwise we don't need to touch the hardware.
+	 */
+	if (!intel_crtc->primary_enabled)
+		goto disable_unpin;
+
+	intel_crtc_wait_for_pending_flips(plane->crtc);
+	intel_disable_primary_hw_plane(dev_priv, intel_plane->plane,
+				       intel_plane->pipe);
+disable_unpin:
+	mutex_lock(&dev->struct_mutex);
+	i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
+			  INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+	intel_unpin_fb_obj(intel_fb_obj(plane->fb));
+	mutex_unlock(&dev->struct_mutex);
+	plane->fb = NULL;
+
+	return 0;
+}
+
+static int
+intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
+			     struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+			     unsigned int crtc_w, unsigned int crtc_h,
+			     uint32_t src_x, uint32_t src_y,
+			     uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
+	struct drm_rect dest = {
+		/* integer pixels */
+		.x1 = crtc_x,
+		.y1 = crtc_y,
+		.x2 = crtc_x + crtc_w,
+		.y2 = crtc_y + crtc_h,
+	};
+	struct drm_rect src = {
+		/* 16.16 fixed point */
+		.x1 = src_x,
+		.y1 = src_y,
+		.x2 = src_x + src_w,
+		.y2 = src_y + src_h,
+	};
+	const struct drm_rect clip = {
+		/* integer pixels */
+		.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
+		.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
+	};
+	bool visible;
+	int ret;
+
+	ret = drm_plane_helper_check_update(plane, crtc, fb,
+					    &src, &dest, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    false, true, &visible);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * If the CRTC isn't enabled, we're just pinning the framebuffer,
+	 * updating the fb pointer, and returning without touching the
+	 * hardware.  This allows us to later do a drmModeSetCrtc with fb=-1 to
+	 * turn on the display with all planes setup as desired.
+	 */
+	if (!crtc->enabled) {
+		mutex_lock(&dev->struct_mutex);
+
+		/*
+		 * If we already called setplane while the crtc was disabled,
+		 * we may have an fb pinned; unpin it.
+		 */
+		if (plane->fb)
+			intel_unpin_fb_obj(old_obj);
+
+		i915_gem_track_fb(old_obj, obj,
+				  INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+
+		/* Pin and return without programming hardware */
+		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		mutex_unlock(&dev->struct_mutex);
+
+		return ret;
+	}
+
+	intel_crtc_wait_for_pending_flips(crtc);
+
+	/*
+	 * If clipping results in a non-visible primary plane, we'll disable
+	 * the primary plane.  Note that this is a bit different than what
+	 * happens if userspace explicitly disables the plane by passing fb=0
+	 * because plane->fb still gets set and pinned.
+	 */
+	if (!visible) {
+		mutex_lock(&dev->struct_mutex);
+
+		/*
+		 * Try to pin the new fb first so that we can bail out if we
+		 * fail.
+		 */
+		if (plane->fb != fb) {
+			ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+			if (ret) {
+				mutex_unlock(&dev->struct_mutex);
+				return ret;
+			}
+		}
+
+		i915_gem_track_fb(old_obj, obj,
+				  INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+
+		if (intel_crtc->primary_enabled)
+			intel_disable_primary_hw_plane(dev_priv,
+						       intel_plane->plane,
+						       intel_plane->pipe);
+
+
+		if (plane->fb != fb)
+			if (plane->fb)
+				intel_unpin_fb_obj(old_obj);
+
+		mutex_unlock(&dev->struct_mutex);
+
+		return 0;
+	}
+
+	ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb);
+	if (ret)
+		return ret;
+
+	if (!intel_crtc->primary_enabled)
+		intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
+					      intel_crtc->pipe);
+
+	return 0;
+}
+
+/* Common destruction function for both primary and cursor planes */
+static void intel_plane_destroy(struct drm_plane *plane)
+{
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	drm_plane_cleanup(plane);
+	kfree(intel_plane);
+}
+
+static const struct drm_plane_funcs intel_primary_plane_funcs = {
+	.update_plane = intel_primary_plane_setplane,
+	.disable_plane = intel_primary_plane_disable,
+	.destroy = intel_plane_destroy,
+};
+
+static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
+						    int pipe)
+{
+	struct intel_plane *primary;
+	const uint32_t *intel_primary_formats;
+	int num_formats;
+
+	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+	if (primary == NULL)
+		return NULL;
+
+	primary->can_scale = false;
+	primary->max_downscale = 1;
+	primary->pipe = pipe;
+	primary->plane = pipe;
+	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
+		primary->plane = !pipe;
+
+	if (INTEL_INFO(dev)->gen <= 3) {
+		intel_primary_formats = intel_primary_formats_gen2;
+		num_formats = ARRAY_SIZE(intel_primary_formats_gen2);
+	} else {
+		intel_primary_formats = intel_primary_formats_gen4;
+		num_formats = ARRAY_SIZE(intel_primary_formats_gen4);
+	}
+
+	drm_universal_plane_init(dev, &primary->base, 0,
+				 &intel_primary_plane_funcs,
+				 intel_primary_formats, num_formats,
+				 DRM_PLANE_TYPE_PRIMARY);
+	return &primary->base;
+}
+
+static int
+intel_cursor_plane_disable(struct drm_plane *plane)
+{
+	if (!plane->fb)
+		return 0;
+
+	BUG_ON(!plane->crtc);
+
+	return intel_crtc_cursor_set_obj(plane->crtc, NULL, 0, 0);
+}
+
+static int
+intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+			  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+			  unsigned int crtc_w, unsigned int crtc_h,
+			  uint32_t src_x, uint32_t src_y,
+			  uint32_t src_w, uint32_t src_h)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_rect dest = {
+		/* integer pixels */
+		.x1 = crtc_x,
+		.y1 = crtc_y,
+		.x2 = crtc_x + crtc_w,
+		.y2 = crtc_y + crtc_h,
+	};
+	struct drm_rect src = {
+		/* 16.16 fixed point */
+		.x1 = src_x,
+		.y1 = src_y,
+		.x2 = src_x + src_w,
+		.y2 = src_y + src_h,
+	};
+	const struct drm_rect clip = {
+		/* integer pixels */
+		.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
+		.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
+	};
+	bool visible;
+	int ret;
+
+	ret = drm_plane_helper_check_update(plane, crtc, fb,
+					    &src, &dest, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    true, true, &visible);
+	if (ret)
+		return ret;
+
+	crtc->cursor_x = crtc_x;
+	crtc->cursor_y = crtc_y;
+	if (fb != crtc->cursor->fb) {
+		return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h);
+	} else {
+		intel_crtc_update_cursor(crtc, visible);
+		return 0;
+	}
+}
+static const struct drm_plane_funcs intel_cursor_plane_funcs = {
+	.update_plane = intel_cursor_plane_update,
+	.disable_plane = intel_cursor_plane_disable,
+	.destroy = intel_plane_destroy,
+};
+
+static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
+						   int pipe)
+{
+	struct intel_plane *cursor;
+
+	cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
+	if (cursor == NULL)
+		return NULL;
+
+	cursor->can_scale = false;
+	cursor->max_downscale = 1;
+	cursor->pipe = pipe;
+	cursor->plane = pipe;
+
+	drm_universal_plane_init(dev, &cursor->base, 0,
+				 &intel_cursor_plane_funcs,
+				 intel_cursor_formats,
+				 ARRAY_SIZE(intel_cursor_formats),
+				 DRM_PLANE_TYPE_CURSOR);
+	return &cursor->base;
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
-	int i;
+	struct drm_plane *primary = NULL;
+	struct drm_plane *cursor = NULL;
+	int i, ret;
 
 	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
 	if (intel_crtc == NULL)
 		return;
 
-	drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
+	primary = intel_primary_plane_create(dev, pipe);
+	if (!primary)
+		goto fail;
+
+	cursor = intel_cursor_plane_create(dev, pipe);
+	if (!cursor)
+		goto fail;
+
+	ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
+					cursor, &intel_crtc_funcs);
+	if (ret)
+		goto fail;
 
 	drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
 	for (i = 0; i < 256; i++) {
@@ -10980,7 +11801,7 @@ static void intel_crtc_init(struct drm_d
 
 	/*
 	 * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
-	 * is hooked to plane B. Hence we want plane A feeding pipe B.
+	 * is hooked to pipe B. Hence we want plane A feeding pipe B.
 	 */
 	intel_crtc->pipe = pipe;
 	intel_crtc->plane = pipe;
@@ -11002,6 +11823,14 @@ static void intel_crtc_init(struct drm_d
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
 	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
+	return;
+
+fail:
+	if (primary)
+		drm_plane_cleanup(primary);
+	if (cursor)
+		drm_plane_cleanup(cursor);
+	kfree(intel_crtc);
 }
 
 enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
@@ -11021,21 +11850,20 @@ int intel_get_pipe_from_crtc_id(struct d
 				struct drm_file *file)
 {
 	struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
-	struct drm_mode_object *drmmode_obj;
+	struct drm_crtc *drmmode_crtc;
 	struct intel_crtc *crtc;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -ENODEV;
 
-	drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
-			DRM_MODE_OBJECT_CRTC);
+	drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id);
 
-	if (!drmmode_obj) {
+	if (!drmmode_crtc) {
 		DRM_ERROR("no such CRTC id\n");
 		return -ENOENT;
 	}
 
-	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+	crtc = to_intel_crtc(drmmode_crtc);
 	pipe_from_crtc_id->pipe = crtc->pipe;
 
 	return 0;
@@ -11236,6 +12064,8 @@ static void intel_setup_outputs(struct d
 	if (SUPPORTS_TV(dev))
 		intel_tv_init(dev);
 
+	intel_edp_psr_init(dev);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->base.possible_crtcs = encoder->crtc_mask;
 		encoder->base.possible_clones =
@@ -11249,11 +12079,14 @@ static void intel_setup_outputs(struct d
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
+	struct drm_device *dev = fb->dev;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
 	drm_framebuffer_cleanup(fb);
+	mutex_lock(&dev->struct_mutex);
 	WARN_ON(!intel_fb->obj->framebuffer_references--);
-	drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
+	drm_gem_object_unreference(&intel_fb->obj->base);
+	mutex_unlock(&dev->struct_mutex);
 	kfree(intel_fb);
 }
 
@@ -11438,7 +12271,7 @@ static void intel_init_display(struct dr
 		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
 		dev_priv->display.crtc_enable = haswell_crtc_enable;
 		dev_priv->display.crtc_disable = haswell_crtc_disable;
-		dev_priv->display.off = haswell_crtc_off;
+		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_primary_plane =
 			ironlake_update_primary_plane;
 	} else if (HAS_PCH_SPLIT(dev)) {
@@ -11671,6 +12504,9 @@ static struct intel_quirk intel_quirks[]
 	/* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
 	{ 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
 
+	/* Acer C720 Chromebook (Core i3 4005U) */
+	{ 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
+
 	/* Toshiba CB35 Chromebook (Celeron 2955U) */
 	{ 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
@@ -11722,6 +12558,9 @@ void intel_modeset_init_hw(struct drm_de
 {
 	intel_prepare_ddi(dev);
 
+	if (IS_VALLEYVIEW(dev))
+		vlv_update_cdclk(dev);
+
 	intel_init_clock_gating(dev);
 
 	intel_reset_dpio(dev);
@@ -11798,7 +12637,6 @@ void intel_modeset_init(struct drm_devic
 	intel_init_dpio(dev);
 	intel_reset_dpio(dev);
 
-	intel_cpu_pll_init(dev);
 	intel_shared_dpll_init(dev);
 
 	/* Just disable it once at startup */
@@ -11840,7 +12678,7 @@ static void intel_enable_pipe_a(struct d
 	struct intel_connector *connector;
 	struct drm_connector *crt = NULL;
 	struct intel_load_detect_pipe load_detect_temp;
-	struct drm_modeset_acquire_ctx ctx;
+	struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
 
 	/* We can't just switch on the pipe A, we need to set things up with a
 	 * proper mode and output configuration. As a gross hack, enable pipe A
@@ -11857,10 +12695,8 @@ static void intel_enable_pipe_a(struct d
 	if (!crt)
 		return;
 
-	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
-		intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
-
-
+	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
+		intel_release_load_detect_pipe(crt, &load_detect_temp);
 }
 
 static bool
@@ -12024,6 +12860,8 @@ static void intel_sanitize_encoder(struc
 				      encoder->base.base.id,
 				      encoder->base.name);
 			encoder->disable(encoder);
+			if (encoder->post_disable)
+				encoder->post_disable(encoder);
 		}
 		encoder->base.crtc = NULL;
 		encoder->connectors_active = false;
@@ -12108,10 +12946,6 @@ static void intel_modeset_readout_hw_sta
 			      crtc->active ? "enabled" : "disabled");
 	}
 
-	/* FIXME: Smash this into the new shared dpll infrastructure. */
-	if (HAS_DDI(dev))
-		intel_ddi_setup_hw_pll_state(dev);
-
 	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
@@ -12125,6 +12959,9 @@ static void intel_modeset_readout_hw_sta
 
 		DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
 			      pll->name, pll->refcount, pll->on);
+
+		if (pll->refcount)
+			intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
@@ -12242,7 +13079,7 @@ void intel_modeset_setup_hw_state(struct
 void intel_modeset_gem_init(struct drm_device *dev)
 {
 	struct drm_crtc *c;
-	struct intel_framebuffer *fb;
+	struct drm_i915_gem_object *obj;
 
 	mutex_lock(&dev->struct_mutex);
 	intel_init_gt_powersave(dev);
@@ -12259,11 +13096,11 @@ void intel_modeset_gem_init(struct drm_d
 	 */
 	mutex_lock(&dev->struct_mutex);
 	for_each_crtc(dev, c) {
-		if (!c->primary->fb)
+		obj = intel_fb_obj(c->primary->fb);
+		if (obj == NULL)
 			continue;
 
-		fb = to_intel_framebuffer(c->primary->fb);
-		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
+		if (intel_pin_and_fence_fb_obj(dev, obj, NULL)) {
 			DRM_ERROR("failed to pin boot fb on pipe %d\n",
 				  to_intel_crtc(c)->pipe);
 			drm_framebuffer_unreference(c->primary->fb);
@@ -12278,13 +13115,12 @@ void intel_connector_unregister(struct i
 	struct drm_connector *connector = &intel_connector->base;
 
 	intel_panel_destroy_backlight(connector);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
 	struct drm_connector *connector;
 
 	/*
@@ -12293,7 +13129,9 @@ void intel_modeset_cleanup(struct drm_de
 	 * experience fancy races otherwise.
 	 */
 	drm_irq_uninstall(dev);
-	cancel_work_sync(&dev_priv->hotplug_work);
+	intel_hpd_cancel_work(dev_priv);
+	dev_priv->pm._irqs_disabled = true;
+
 	/*
 	 * Due to the hpd irq storm handling the hotplug work can re-arm the
 	 * poll handlers. Hence disable polling after hpd handling is shut down.
@@ -12304,14 +13142,6 @@ void intel_modeset_cleanup(struct drm_de
 
 	intel_unregister_dsm_handler();
 
-	for_each_crtc(dev, crtc) {
-		/* Skip inactive CRTCs */
-		if (!crtc->primary->fb)
-			continue;
-
-		intel_increase_pllclock(crtc);
-	}
-
 	intel_disable_fbc(dev);
 
 	intel_disable_gt_powersave(dev);
@@ -12479,7 +13309,7 @@ intel_display_capture_error_state(struct
 
 		error->pipe[i].source = I915_READ(PIPESRC(i));
 
-		if (!HAS_PCH_SPLIT(dev))
+		if (HAS_GMCH_DISPLAY(dev))
 			error->pipe[i].stat = I915_READ(PIPESTAT(i));
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dp.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,7 @@ static void intel_dp_link_down(struct in
 static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 
-static int
+int
 intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
 	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
@@ -773,12 +773,29 @@ intel_dp_connector_unregister(struct int
 {
 	struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
 
-	sysfs_remove_link(&intel_connector->base.kdev->kobj,
-			  intel_dp->aux.ddc.dev.kobj.name);
+	if (!intel_connector->mst_port)
+		sysfs_remove_link(&intel_connector->base.kdev->kobj,
+				  intel_dp->aux.ddc.dev.kobj.name);
 	intel_connector_unregister(intel_connector);
 }
 
 static void
+hsw_dp_set_ddi_pll_sel(struct intel_crtc_config *pipe_config, int link_bw)
+{
+	switch (link_bw) {
+	case DP_LINK_BW_1_62:
+		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
+		break;
+	case DP_LINK_BW_2_7:
+		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
+		break;
+	case DP_LINK_BW_5_4:
+		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
+		break;
+	}
+}
+
+static void
 intel_dp_set_clock(struct intel_encoder *encoder,
 		   struct intel_crtc_config *pipe_config, int link_bw)
 {
@@ -789,8 +806,6 @@ intel_dp_set_clock(struct intel_encoder
 	if (IS_G4X(dev)) {
 		divisor = gen4_dpll;
 		count = ARRAY_SIZE(gen4_dpll);
-	} else if (IS_HASWELL(dev)) {
-		/* Haswell has special-purpose DP DDI clocks. */
 	} else if (HAS_PCH_SPLIT(dev)) {
 		divisor = pch_dpll;
 		count = ARRAY_SIZE(pch_dpll);
@@ -961,7 +976,10 @@ found:
 				&pipe_config->dp_m2_n2);
 	}
 
-	intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
+	if (HAS_DDI(dev))
+		hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
+	else
+		intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
 
 	return true;
 }
@@ -1267,6 +1285,19 @@ static void edp_panel_vdd_work(struct wo
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 }
 
+static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
+{
+	unsigned long delay;
+
+	/*
+	 * Queue the timer to fire a long time from now (relative to the power
+	 * down delay) to keep the panel power up across a sequence of
+	 * operations.
+	 */
+	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
+	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
+}
+
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	if (!is_edp(intel_dp))
@@ -1276,17 +1307,10 @@ static void edp_panel_vdd_off(struct int
 
 	intel_dp->want_panel_vdd = false;
 
-	if (sync) {
+	if (sync)
 		edp_panel_vdd_off_sync(intel_dp);
-	} else {
-		/*
-		 * Queue the timer to fire a long
-		 * time from now (relative to the power down delay)
-		 * to keep the panel power up across a sequence of operations
-		 */
-		schedule_delayed_work(&intel_dp->panel_vdd_work,
-				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
-	}
+	else
+		edp_panel_vdd_schedule_off(intel_dp);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1349,8 +1373,6 @@ void intel_edp_panel_off(struct intel_dp
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	edp_wait_backlight_off(intel_dp);
-
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1386,6 +1408,9 @@ void intel_edp_backlight_on(struct intel
 		return;
 
 	DRM_DEBUG_KMS("\n");
+
+	intel_panel_enable_backlight(intel_dp->attached_connector);
+
 	/*
 	 * If we enable the backlight right away following a panel power
 	 * on, we may see slight flicker as the panel syncs with the eDP
@@ -1400,8 +1425,6 @@ void intel_edp_backlight_on(struct intel
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-
-	intel_panel_enable_backlight(intel_dp->attached_connector);
 }
 
 void intel_edp_backlight_off(struct intel_dp *intel_dp)
@@ -1414,8 +1437,6 @@ void intel_edp_backlight_off(struct inte
 	if (!is_edp(intel_dp))
 		return;
 
-	intel_panel_disable_backlight(intel_dp->attached_connector);
-
 	DRM_DEBUG_KMS("\n");
 	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
@@ -1425,6 +1446,10 @@ void intel_edp_backlight_off(struct inte
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 	intel_dp->last_backlight_off = jiffies;
+
+	edp_wait_backlight_off(intel_dp);
+
+	intel_panel_disable_backlight(intel_dp->attached_connector);
 }
 
 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
@@ -1606,6 +1631,10 @@ static void intel_dp_get_config(struct i
 
 	pipe_config->adjusted_mode.flags |= flags;
 
+	if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
+	    tmp & DP_COLOR_RANGE_16_235)
+		pipe_config->limited_color_range = true;
+
 	pipe_config->has_dp_encoder = true;
 
 	intel_dp_get_m_n(crtc, pipe_config);
@@ -1646,11 +1675,9 @@ static void intel_dp_get_config(struct i
 	}
 }
 
-static bool is_edp_psr(struct drm_device *dev)
+static bool is_edp_psr(struct intel_dp *intel_dp)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	return dev_priv->psr.sink_support;
+	return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED;
 }
 
 static bool intel_edp_is_psr_enabled(struct drm_device *dev)
@@ -1698,9 +1725,6 @@ static void intel_edp_psr_setup(struct i
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct edp_vsc_psr psr_vsc;
 
-	if (intel_dp->psr_setup_done)
-		return;
-
 	/* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
 	memset(&psr_vsc, 0, sizeof(psr_vsc));
 	psr_vsc.sdp_header.HB0 = 0;
@@ -1712,22 +1736,25 @@ static void intel_edp_psr_setup(struct i
 	/* Avoid continuous PSR exit by masking memup and hpd */
 	I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
 		   EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
-
-	intel_dp->psr_setup_done = true;
 }
 
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(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 = dev->dev_private;
 	uint32_t aux_clock_divider;
 	int precharge = 0x3;
 	int msg_size = 5;       /* Header(4) + Message(1) */
+	bool only_standby = false;
 
 	aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
 
+	if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
+		only_standby = true;
+
 	/* Enable PSR in sink */
-	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
+	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby)
 		drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
 				   DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
 	else
@@ -1746,18 +1773,24 @@ static void intel_edp_psr_enable_sink(st
 
 static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(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 = dev->dev_private;
 	uint32_t max_sleep_time = 0x1f;
 	uint32_t idle_frames = 1;
 	uint32_t val = 0x0;
 	const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
+	bool only_standby = false;
 
-	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
+	if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
+		only_standby = true;
+
+	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) {
 		val |= EDP_PSR_LINK_STANDBY;
 		val |= EDP_PSR_TP2_TP3_TIME_0us;
 		val |= EDP_PSR_TP1_TIME_0us;
 		val |= EDP_PSR_SKIP_AUX_EXIT;
+		val |= IS_BROADWELL(dev) ? BDW_PSR_SINGLE_FRAME : 0;
 	} else
 		val |= EDP_PSR_LINK_DISABLE;
 
@@ -1775,18 +1808,14 @@ static bool intel_edp_psr_match_conditio
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = dig_port->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->primary->fb)->obj;
-	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 
-	dev_priv->psr.source_ok = false;
+	lockdep_assert_held(&dev_priv->psr.lock);
+	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
 
-	if (!HAS_PSR(dev)) {
-		DRM_DEBUG_KMS("PSR not supported on this platform\n");
-		return false;
-	}
+	dev_priv->psr.source_ok = false;
 
-	if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
-	    (dig_port->port != PORT_A)) {
+	if (IS_HASWELL(dev) && dig_port->port != PORT_A) {
 		DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
 		return false;
 	}
@@ -1796,29 +1825,9 @@ static bool intel_edp_psr_match_conditio
 		return false;
 	}
 
-	crtc = dig_port->base.base.crtc;
-	if (crtc == NULL) {
-		DRM_DEBUG_KMS("crtc not active for PSR\n");
-		return false;
-	}
-
-	intel_crtc = to_intel_crtc(crtc);
-	if (!intel_crtc_active(crtc)) {
-		DRM_DEBUG_KMS("crtc not active for PSR\n");
-		return false;
-	}
-
-	obj = to_intel_framebuffer(crtc->primary->fb)->obj;
-	if (obj->tiling_mode != I915_TILING_X ||
-	    obj->fence_reg == I915_FENCE_REG_NONE) {
-		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
-		return false;
-	}
-
-	if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
-		DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
-		return false;
-	}
+	/* Below limitations aren't valid for Broadwell */
+	if (IS_BROADWELL(dev))
+		goto out;
 
 	if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
 	    S3D_ENABLE) {
@@ -1831,35 +1840,60 @@ static bool intel_edp_psr_match_conditio
 		return false;
 	}
 
+ out:
 	dev_priv->psr.source_ok = true;
 	return true;
 }
 
 static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-
-	if (!intel_edp_psr_match_conditions(intel_dp) ||
-	    intel_edp_is_psr_enabled(dev))
-		return;
+	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 = dev->dev_private;
 
-	/* Setup PSR once */
-	intel_edp_psr_setup(intel_dp);
+	WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+	WARN_ON(dev_priv->psr.active);
+	lockdep_assert_held(&dev_priv->psr.lock);
 
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
 	/* Enable PSR on the host */
 	intel_edp_psr_enable_source(intel_dp);
+
+	dev_priv->psr.active = true;
 }
 
 void intel_edp_psr_enable(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (intel_edp_psr_match_conditions(intel_dp) &&
-	    !intel_edp_is_psr_enabled(dev))
-		intel_edp_psr_do_enable(intel_dp);
+	if (!HAS_PSR(dev)) {
+		DRM_DEBUG_KMS("PSR not supported on this platform\n");
+		return;
+	}
+
+	if (!is_edp_psr(intel_dp)) {
+		DRM_DEBUG_KMS("PSR not supported by this panel\n");
+		return;
+	}
+
+	mutex_lock(&dev_priv->psr.lock);
+	if (dev_priv->psr.enabled) {
+		DRM_DEBUG_KMS("PSR already in use\n");
+		mutex_unlock(&dev_priv->psr.lock);
+		return;
+	}
+
+	dev_priv->psr.busy_frontbuffer_bits = 0;
+
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
+	if (intel_edp_psr_match_conditions(intel_dp))
+		dev_priv->psr.enabled = intel_dp;
+	mutex_unlock(&dev_priv->psr.lock);
 }
 
 void intel_edp_psr_disable(struct intel_dp *intel_dp)
@@ -1867,36 +1901,136 @@ void intel_edp_psr_disable(struct intel_
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!intel_edp_is_psr_enabled(dev))
+	mutex_lock(&dev_priv->psr.lock);
+	if (!dev_priv->psr.enabled) {
+		mutex_unlock(&dev_priv->psr.lock);
 		return;
+	}
 
-	I915_WRITE(EDP_PSR_CTL(dev),
-		   I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
+	if (dev_priv->psr.active) {
+		I915_WRITE(EDP_PSR_CTL(dev),
+			   I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
 
-	/* Wait till PSR is idle */
-	if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
-		       EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
-		DRM_ERROR("Timed out waiting for PSR Idle State\n");
+		/* Wait till PSR is idle */
+		if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
+			       EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+			DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+		dev_priv->psr.active = false;
+	} else {
+		WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+	}
+
+	dev_priv->psr.enabled = NULL;
+	mutex_unlock(&dev_priv->psr.lock);
+
+	cancel_delayed_work_sync(&dev_priv->psr.work);
 }
 
-void intel_edp_psr_update(struct drm_device *dev)
+static void intel_edp_psr_work(struct work_struct *work)
 {
-	struct intel_encoder *encoder;
-	struct intel_dp *intel_dp = NULL;
+	struct drm_i915_private *dev_priv =
+		container_of(work, typeof(*dev_priv), psr.work.work);
+	struct intel_dp *intel_dp = dev_priv->psr.enabled;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
-		if (encoder->type == INTEL_OUTPUT_EDP) {
-			intel_dp = enc_to_intel_dp(&encoder->base);
+	mutex_lock(&dev_priv->psr.lock);
+	intel_dp = dev_priv->psr.enabled;
 
-			if (!is_edp_psr(dev))
-				return;
+	if (!intel_dp)
+		goto unlock;
 
-			if (!intel_edp_psr_match_conditions(intel_dp))
-				intel_edp_psr_disable(intel_dp);
-			else
-				if (!intel_edp_is_psr_enabled(dev))
-					intel_edp_psr_do_enable(intel_dp);
-		}
+	/*
+	 * The delayed work can race with an invalidate hence we need to
+	 * recheck. Since psr_flush first clears this and then reschedules we
+	 * won't ever miss a flush when bailing out here.
+	 */
+	if (dev_priv->psr.busy_frontbuffer_bits)
+		goto unlock;
+
+	intel_edp_psr_do_enable(intel_dp);
+unlock:
+	mutex_unlock(&dev_priv->psr.lock);
+}
+
+static void intel_edp_psr_do_exit(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->psr.active) {
+		u32 val = I915_READ(EDP_PSR_CTL(dev));
+
+		WARN_ON(!(val & EDP_PSR_ENABLE));
+
+		I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE);
+
+		dev_priv->psr.active = false;
+	}
+
+}
+
+void intel_edp_psr_invalidate(struct drm_device *dev,
+			      unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	enum pipe pipe;
+
+	mutex_lock(&dev_priv->psr.lock);
+	if (!dev_priv->psr.enabled) {
+		mutex_unlock(&dev_priv->psr.lock);
+		return;
+	}
+
+	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	pipe = to_intel_crtc(crtc)->pipe;
+
+	intel_edp_psr_do_exit(dev);
+
+	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
+
+	dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits;
+	mutex_unlock(&dev_priv->psr.lock);
+}
+
+void intel_edp_psr_flush(struct drm_device *dev,
+			 unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	enum pipe pipe;
+
+	mutex_lock(&dev_priv->psr.lock);
+	if (!dev_priv->psr.enabled) {
+		mutex_unlock(&dev_priv->psr.lock);
+		return;
+	}
+
+	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	pipe = to_intel_crtc(crtc)->pipe;
+	dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits;
+
+	/*
+	 * On Haswell sprite plane updates don't result in a psr invalidating
+	 * signal in the hardware. Which means we need to manually fake this in
+	 * software for all flushes, not just when we've seen a preceding
+	 * invalidation through frontbuffer rendering.
+	 */
+	if (IS_HASWELL(dev) &&
+	    (frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe)))
+		intel_edp_psr_do_exit(dev);
+
+	if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
+		schedule_delayed_work(&dev_priv->psr.work,
+				      msecs_to_jiffies(100));
+	mutex_unlock(&dev_priv->psr.lock);
+}
+
+void intel_edp_psr_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_edp_psr_work);
+	mutex_init(&dev_priv->psr.lock);
 }
 
 static void intel_disable_dp(struct intel_encoder *encoder)
@@ -2152,6 +2286,70 @@ static void chv_pre_enable_dp(struct int
 	vlv_wait_port_ready(dev_priv, dport);
 }
 
+static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(encoder->base.crtc);
+	enum dpio_channel ch = vlv_dport_to_channel(dport);
+	enum pipe pipe = intel_crtc->pipe;
+	u32 val;
+
+	mutex_lock(&dev_priv->dpio_lock);
+
+	/* program left/right clock distribution */
+	if (pipe != PIPE_B) {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+		if (ch == DPIO_CH0)
+			val |= CHV_BUFLEFTENA1_FORCE;
+		if (ch == DPIO_CH1)
+			val |= CHV_BUFRIGHTENA1_FORCE;
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+	} else {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+		if (ch == DPIO_CH0)
+			val |= CHV_BUFLEFTENA2_FORCE;
+		if (ch == DPIO_CH1)
+			val |= CHV_BUFRIGHTENA2_FORCE;
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+	}
+
+	/* program clock channel usage */
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch));
+	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+	if (pipe != PIPE_B)
+		val &= ~CHV_PCS_USEDCLKCHANNEL;
+	else
+		val |= CHV_PCS_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+	if (pipe != PIPE_B)
+		val &= ~CHV_PCS_USEDCLKCHANNEL;
+	else
+		val |= CHV_PCS_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+
+	/*
+	 * This a a bit weird since generally CL
+	 * matches the pipe, but here we need to
+	 * pick the CL based on the port.
+	 */
+	val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch));
+	if (pipe != PIPE_B)
+		val &= ~CHV_CMN_USEDCLKCHANNEL;
+	else
+		val |= CHV_CMN_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
+
+	mutex_unlock(&dev_priv->dpio_lock);
+}
+
 /*
  * Native read with retry for link status and receiver capability reads for
  * cases where the sink may still be asleep.
@@ -2189,18 +2387,14 @@ intel_dp_get_link_status(struct intel_dp
 				       DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
 }
 
-/*
- * These are source-specific values; current Intel hardware supports
- * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
- */
-
+/* These are source-specific values. */
 static uint8_t
 intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
-	if (IS_VALLEYVIEW(dev) || IS_BROADWELL(dev))
+	if (IS_VALLEYVIEW(dev))
 		return DP_TRAIN_VOLTAGE_SWING_1200;
 	else if (IS_GEN7(dev) && port == PORT_A)
 		return DP_TRAIN_VOLTAGE_SWING_800;
@@ -2216,18 +2410,7 @@ intel_dp_pre_emphasis_max(struct intel_d
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
-	if (IS_BROADWELL(dev)) {
-		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-		case DP_TRAIN_VOLTAGE_SWING_400:
-		case DP_TRAIN_VOLTAGE_SWING_600:
-			return DP_TRAIN_PRE_EMPHASIS_6;
-		case DP_TRAIN_VOLTAGE_SWING_800:
-			return DP_TRAIN_PRE_EMPHASIS_3_5;
-		case DP_TRAIN_VOLTAGE_SWING_1200:
-		default:
-			return DP_TRAIN_PRE_EMPHASIS_0;
-		}
-	} else if (IS_HASWELL(dev)) {
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_400:
 			return DP_TRAIN_PRE_EMPHASIS_9_5;
@@ -2699,41 +2882,6 @@ intel_hsw_signal_levels(uint8_t train_se
 	}
 }
 
-static uint32_t
-intel_bdw_signal_levels(uint8_t train_set)
-{
-	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
-					 DP_TRAIN_PRE_EMPHASIS_MASK);
-	switch (signal_levels) {
-	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
-		return DDI_BUF_EMP_400MV_0DB_BDW;	/* Sel0 */
-	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
-		return DDI_BUF_EMP_400MV_3_5DB_BDW;	/* Sel1 */
-	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
-		return DDI_BUF_EMP_400MV_6DB_BDW;	/* Sel2 */
-
-	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
-		return DDI_BUF_EMP_600MV_0DB_BDW;	/* Sel3 */
-	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
-		return DDI_BUF_EMP_600MV_3_5DB_BDW;	/* Sel4 */
-	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
-		return DDI_BUF_EMP_600MV_6DB_BDW;	/* Sel5 */
-
-	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
-		return DDI_BUF_EMP_800MV_0DB_BDW;	/* Sel6 */
-	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
-		return DDI_BUF_EMP_800MV_3_5DB_BDW;	/* Sel7 */
-
-	case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0:
-		return DDI_BUF_EMP_1200MV_0DB_BDW;	/* Sel8 */
-
-	default:
-		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
-			      "0x%x\n", signal_levels);
-		return DDI_BUF_EMP_400MV_0DB_BDW;	/* Sel0 */
-	}
-}
-
 /* Properly updates "DP" with the correct signal levels. */
 static void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
@@ -2744,10 +2892,7 @@ intel_dp_set_signal_levels(struct intel_
 	uint32_t signal_levels, mask;
 	uint8_t train_set = intel_dp->train_set[0];
 
-	if (IS_BROADWELL(dev)) {
-		signal_levels = intel_bdw_signal_levels(train_set);
-		mask = DDI_BUF_EMP_MASK;
-	} else if (IS_HASWELL(dev)) {
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		signal_levels = intel_hsw_signal_levels(train_set);
 		mask = DDI_BUF_EMP_MASK;
 	} else if (IS_CHERRYVIEW(dev)) {
@@ -3246,6 +3391,33 @@ intel_dp_probe_oui(struct intel_dp *inte
 	edp_panel_vdd_off(intel_dp, false);
 }
 
+static bool
+intel_dp_probe_mst(struct intel_dp *intel_dp)
+{
+	u8 buf[1];
+
+	if (!intel_dp->can_mst)
+		return false;
+
+	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
+		return false;
+
+	_edp_panel_vdd_on(intel_dp);
+	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
+		if (buf[0] & DP_MST_CAP) {
+			DRM_DEBUG_KMS("Sink is MST capable\n");
+			intel_dp->is_mst = true;
+		} else {
+			DRM_DEBUG_KMS("Sink is not MST capable\n");
+			intel_dp->is_mst = false;
+		}
+	}
+	edp_panel_vdd_off(intel_dp, false);
+
+	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+	return intel_dp->is_mst;
+}
+
 int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -3283,6 +3455,20 @@ intel_dp_get_sink_irq(struct intel_dp *i
 				       sink_irq_vector, 1) == 1;
 }
 
+static bool
+intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+{
+	int ret;
+
+	ret = intel_dp_dpcd_read_wake(&intel_dp->aux,
+					     DP_SINK_COUNT_ESI,
+					     sink_irq_vector, 14);
+	if (ret != 14)
+		return false;
+
+	return true;
+}
+
 static void
 intel_dp_handle_test_request(struct intel_dp *intel_dp)
 {
@@ -3290,6 +3476,63 @@ intel_dp_handle_test_request(struct inte
 	drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK);
 }
 
+static int
+intel_dp_check_mst_status(struct intel_dp *intel_dp)
+{
+	bool bret;
+
+	if (intel_dp->is_mst) {
+		u8 esi[16] = { 0 };
+		int ret = 0;
+		int retry;
+		bool handled;
+		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
+go_again:
+		if (bret == true) {
+
+			/* check link status - esi[10] = 0x200c */
+			if (intel_dp->active_mst_links && !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
+				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
+				intel_dp_start_link_train(intel_dp);
+				intel_dp_complete_link_train(intel_dp);
+				intel_dp_stop_link_train(intel_dp);
+			}
+
+			DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
+
+			if (handled) {
+				for (retry = 0; retry < 3; retry++) {
+					int wret;
+					wret = drm_dp_dpcd_write(&intel_dp->aux,
+								 DP_SINK_COUNT_ESI+1,
+								 &esi[1], 3);
+					if (wret == 3) {
+						break;
+					}
+				}
+
+				bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
+				if (bret == true) {
+					DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+					goto go_again;
+				}
+			} else
+				ret = 0;
+
+			return ret;
+		} else {
+			struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+			DRM_DEBUG_KMS("failed to get ESI - device may have failed\n");
+			intel_dp->is_mst = false;
+			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+			/* send a hotplug event */
+			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev);
+		}
+	}
+	return -EINVAL;
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -3298,21 +3541,25 @@ intel_dp_handle_test_request(struct inte
  *  3. Use Link Training from 2.5.3.3 and 3.5.1.3
  *  4. Check link status on receipt of hot-plug interrupt
  */
-
 void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 	u8 sink_irq_vector;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	/* FIXME: This access isn't protected by any locks. */
+	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
 	if (!intel_encoder->connectors_active)
 		return;
 
 	if (WARN_ON(!intel_encoder->base.crtc))
 		return;
 
+	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
+		return;
+
 	/* Try to read receiver status if the link appears to be up */
 	if (!intel_dp_get_link_status(intel_dp, link_status)) {
 		return;
@@ -3418,24 +3665,12 @@ ironlake_dp_detect(struct intel_dp *inte
 	return intel_dp_detect_dpcd(intel_dp);
 }
 
-static enum drm_connector_status
-g4x_dp_detect(struct intel_dp *intel_dp)
+static int g4x_digital_port_connected(struct drm_device *dev,
+				       struct intel_digital_port *intel_dig_port)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	uint32_t bit;
 
-	/* Can't disconnect eDP, but you can close the lid... */
-	if (is_edp(intel_dp)) {
-		enum drm_connector_status status;
-
-		status = intel_panel_detect(dev);
-		if (status == connector_status_unknown)
-			status = connector_status_connected;
-		return status;
-	}
-
 	if (IS_VALLEYVIEW(dev)) {
 		switch (intel_dig_port->port) {
 		case PORT_B:
@@ -3448,7 +3683,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 			bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
 			break;
 		default:
-			return connector_status_unknown;
+			return -EINVAL;
 		}
 	} else {
 		switch (intel_dig_port->port) {
@@ -3462,11 +3697,36 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 			bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
 			break;
 		default:
-			return connector_status_unknown;
+			return -EINVAL;
 		}
 	}
 
 	if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
+		return 0;
+	return 1;
+}
+
+static enum drm_connector_status
+g4x_dp_detect(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	int ret;
+
+	/* Can't disconnect eDP, but you can close the lid... */
+	if (is_edp(intel_dp)) {
+		enum drm_connector_status status;
+
+		status = intel_panel_detect(dev);
+		if (status == connector_status_unknown)
+			status = connector_status_connected;
+		return status;
+	}
+
+	ret = g4x_digital_port_connected(dev, intel_dig_port);
+	if (ret == -EINVAL)
+		return connector_status_unknown;
+	else if (ret == 0)
 		return connector_status_disconnected;
 
 	return intel_dp_detect_dpcd(intel_dp);
@@ -3518,8 +3778,7 @@ intel_dp_detect(struct drm_connector *co
 	enum drm_connector_status status;
 	enum intel_display_power_domain power_domain;
 	struct edid *edid = NULL;
-
-	intel_runtime_pm_get(dev_priv);
+	bool ret;
 
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_get(dev_priv, power_domain);
@@ -3527,6 +3786,14 @@ intel_dp_detect(struct drm_connector *co
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
+	if (intel_dp->is_mst) {
+		/* MST devices are disconnected from a monitor POV */
+		if (intel_encoder->type != INTEL_OUTPUT_EDP)
+			intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+		status = connector_status_disconnected;
+		goto out;
+	}
+
 	intel_dp->has_audio = false;
 
 	if (HAS_PCH_SPLIT(dev))
@@ -3539,6 +3806,16 @@ intel_dp_detect(struct drm_connector *co
 
 	intel_dp_probe_oui(intel_dp);
 
+	ret = intel_dp_probe_mst(intel_dp);
+	if (ret) {
+		/* if we are in MST mode then this connector
+		   won't appear connected or have anything with EDID on it */
+		if (intel_encoder->type != INTEL_OUTPUT_EDP)
+			intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+		status = connector_status_disconnected;
+		goto out;
+	}
+
 	if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
 		intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
 	} else {
@@ -3555,9 +3832,6 @@ intel_dp_detect(struct drm_connector *co
 
 out:
 	intel_display_power_put(dev_priv, power_domain);
-
-	intel_runtime_pm_put(dev_priv);
-
 	return status;
 }
 
@@ -3734,6 +4008,7 @@ void intel_dp_encoder_destroy(struct drm
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	drm_dp_aux_unregister(&intel_dp->aux);
+	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
@@ -3748,6 +4023,21 @@ void intel_dp_encoder_destroy(struct drm
 	kfree(intel_dig_port);
 }
 
+static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	if (!is_edp(intel_dp))
+		return;
+
+	edp_panel_vdd_off_sync(intel_dp);
+}
+
+static void intel_dp_encoder_reset(struct drm_encoder *encoder)
+{
+	intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
+}
+
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_dp_detect,
@@ -3763,15 +4053,83 @@ static const struct drm_connector_helper
 };
 
 static const struct drm_encoder_funcs intel_dp_enc_funcs = {
+	.reset = intel_dp_encoder_reset,
 	.destroy = intel_dp_encoder_destroy,
 };
 
-static void
+void
 intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	return;
+}
 
-	intel_dp_check_link_status(intel_dp);
+bool
+intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
+{
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+	bool ret = true;
+
+	if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
+		intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
+
+	DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
+		      long_hpd ? "long" : "short");
+
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
+	if (long_hpd) {
+
+		if (HAS_PCH_SPLIT(dev)) {
+			if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
+				goto mst_fail;
+		} else {
+			if (g4x_digital_port_connected(dev, intel_dig_port) != 1)
+				goto mst_fail;
+		}
+
+		if (!intel_dp_get_dpcd(intel_dp)) {
+			goto mst_fail;
+		}
+
+		intel_dp_probe_oui(intel_dp);
+
+		if (!intel_dp_probe_mst(intel_dp))
+			goto mst_fail;
+
+	} else {
+		if (intel_dp->is_mst) {
+			if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
+				goto mst_fail;
+		}
+
+		if (!intel_dp->is_mst) {
+			/*
+			 * we'll check the link status via the normal hot plug path later -
+			 * but for short hpds we should check it now
+			 */
+			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+			intel_dp_check_link_status(intel_dp);
+			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+		}
+	}
+	ret = false;
+	goto put_power;
+mst_fail:
+	/* if we were in MST mode, and device is not there get out of MST mode */
+	if (intel_dp->is_mst) {
+		DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+		intel_dp->is_mst = false;
+		drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+	}
+put_power:
+	intel_display_power_put(dev_priv, power_domain);
+
+	return ret;
 }
 
 /* Return which DP Port should be selected for Transcoder DP control */
@@ -3822,7 +4180,7 @@ bool intel_dp_is_edp(struct drm_device *
 	return false;
 }
 
-static void
+void
 intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -4035,6 +4393,11 @@ void intel_dp_set_drrs_state(struct drm_
 		return;
 	}
 
+	/*
+	 * FIXME: This needs proper synchronization with psr state. But really
+	 * hard to tell without seeing the user of this function of this code.
+	 * Check locking and ordering once that lands.
+	 */
 	if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
 		DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
 		return;
@@ -4138,6 +4501,32 @@ intel_dp_drrs_init(struct intel_digital_
 	return downclock_mode;
 }
 
+void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp *intel_dp;
+	enum intel_display_power_domain power_domain;
+
+	if (intel_encoder->type != INTEL_OUTPUT_EDP)
+		return;
+
+	intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	if (!edp_have_panel_vdd(intel_dp))
+		return;
+	/*
+	 * The VDD bit needs a power domain reference, so if the bit is
+	 * already enabled when we boot or resume, grab this reference and
+	 * schedule a vdd off, so we don't hold on to the reference
+	 * indefinitely.
+	 */
+	DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n");
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
+	edp_panel_vdd_schedule_off(intel_dp);
+}
+
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 				     struct intel_connector *intel_connector,
 				     struct edp_power_seq *power_seq)
@@ -4158,13 +4547,7 @@ static bool intel_edp_init_connector(str
 	if (!is_edp(intel_dp))
 		return true;
 
-	/* The VDD bit needs a power domain reference, so if the bit is already
-	 * enabled when we boot, grab this reference. */
-	if (edp_have_panel_vdd(intel_dp)) {
-		enum intel_display_power_domain power_domain;
-		power_domain = intel_display_port_power_domain(intel_encoder);
-		intel_display_power_get(dev_priv, power_domain);
-	}
+	intel_edp_panel_vdd_sanitize(intel_encoder);
 
 	/* Cache DPCD and EDID for edp. */
 	intel_edp_panel_vdd_on(intel_dp);
@@ -4288,7 +4671,7 @@ intel_dp_init_connector(struct intel_dig
 			  edp_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	if (HAS_DDI(dev))
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
@@ -4321,7 +4704,12 @@ intel_dp_init_connector(struct intel_dig
 
 	intel_dp_aux_init(intel_dp, intel_connector);
 
-	intel_dp->psr_setup_done = false;
+	/* init MST on ports that can support it */
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		if (port == PORT_B || port == PORT_C || port == PORT_D) {
+			intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id);
+		}
+	}
 
 	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
 		drm_dp_aux_unregister(&intel_dp->aux);
@@ -4331,7 +4719,7 @@ intel_dp_init_connector(struct intel_dig
 			edp_panel_vdd_off_sync(intel_dp);
 			drm_modeset_unlock(&dev->mode_config.connection_mutex);
 		}
-		drm_sysfs_connector_remove(connector);
+		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
 		return false;
 	}
@@ -4353,6 +4741,7 @@ intel_dp_init_connector(struct intel_dig
 void
 intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct drm_encoder *encoder;
@@ -4378,7 +4767,9 @@ intel_dp_init(struct drm_device *dev, in
 	intel_encoder->disable = intel_disable_dp;
 	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)) {
+		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;
@@ -4408,9 +4799,55 @@ intel_dp_init(struct drm_device *dev, in
 	intel_encoder->cloneable = 0;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
+	intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
+	dev_priv->hpd_irq_port[port] = intel_dig_port;
+
 	if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
 		drm_encoder_cleanup(encoder);
 		kfree(intel_dig_port);
 		kfree(intel_connector);
 	}
 }
+
+void intel_dp_mst_suspend(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* disable MST */
+	for (i = 0; i < I915_MAX_PORTS; i++) {
+		struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+		if (!intel_dig_port)
+			continue;
+
+		if (intel_dig_port->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+			if (!intel_dig_port->dp.can_mst)
+				continue;
+			if (intel_dig_port->dp.is_mst)
+				drm_dp_mst_topology_mgr_suspend(&intel_dig_port->dp.mst_mgr);
+		}
+	}
+}
+
+void intel_dp_mst_resume(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	for (i = 0; i < I915_MAX_PORTS; i++) {
+		struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+		if (!intel_dig_port)
+			continue;
+		if (intel_dig_port->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+			int ret;
+
+			if (!intel_dig_port->dp.can_mst)
+				continue;
+
+			ret = drm_dp_mst_topology_mgr_resume(&intel_dig_port->dp.mst_mgr);
+			if (ret != 0) {
+				intel_dp_check_mst_status(&intel_dig_port->dp);
+			}
+		}
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dp_mst.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dp_mst.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,548 @@
+/*
+ * Copyright Â© 2008 Intel Corporation
+ *             2014 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 (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 "i915_drv.h"
+#include "intel_drv.h"
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+
+static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
+					struct intel_crtc_config *pipe_config)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = encoder->base.dev;
+	int bpp;
+	int lane_count, slots;
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	struct intel_connector *found = NULL, *intel_connector;
+	int mst_pbn;
+
+	pipe_config->dp_encoder_is_mst = true;
+	pipe_config->has_pch_encoder = false;
+	pipe_config->has_dp_encoder = true;
+	bpp = 24;
+	/*
+	 * for MST we always configure max link bw - the spec doesn't
+	 * seem to suggest we should do otherwise.
+	 */
+	lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+	intel_dp->link_bw = intel_dp_max_link_bw(intel_dp);
+	intel_dp->lane_count = lane_count;
+
+	pipe_config->pipe_bpp = 24;
+	pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+
+	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) {
+		if (intel_connector->new_encoder == encoder) {
+			found = intel_connector;
+			break;
+		}
+	}
+
+	if (!found) {
+		DRM_ERROR("can't find connector\n");
+		return false;
+	}
+
+	mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
+
+	pipe_config->pbn = mst_pbn;
+	slots = drm_dp_find_vcpi_slots(&intel_dp->mst_mgr, mst_pbn);
+
+	intel_link_compute_m_n(bpp, lane_count,
+			       adjusted_mode->crtc_clock,
+			       pipe_config->port_clock,
+			       &pipe_config->dp_m_n);
+
+	pipe_config->dp_m_n.tu = slots;
+	return true;
+
+}
+
+static void intel_mst_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	int ret;
+
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->port);
+
+	ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
+	if (ret) {
+		DRM_ERROR("failed to update payload %d\n", ret);
+	}
+}
+
+static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+	/* this can fail */
+	drm_dp_check_act_status(&intel_dp->mst_mgr);
+	/* and this can also fail */
+	drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->port);
+
+	intel_dp->active_mst_links--;
+	intel_mst->port = NULL;
+	if (intel_dp->active_mst_links == 0) {
+		intel_dig_port->base.post_disable(&intel_dig_port->base);
+		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
+	}
+}
+
+static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_dig_port->port;
+	int ret;
+	uint32_t temp;
+	struct intel_connector *found = NULL, *intel_connector;
+	int slots;
+	struct drm_crtc *crtc = encoder->base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) {
+		if (intel_connector->new_encoder == encoder) {
+			found = intel_connector;
+			break;
+		}
+	}
+
+	if (!found) {
+		DRM_ERROR("can't find connector\n");
+		return;
+	}
+
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+	intel_mst->port = found->port;
+
+	if (intel_dp->active_mst_links == 0) {
+		enum port port = intel_ddi_get_encoder_port(encoder);
+
+		I915_WRITE(PORT_CLK_SEL(port), intel_crtc->config.ddi_pll_sel);
+
+		intel_ddi_init_dp_buf_reg(&intel_dig_port->base);
+
+		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+
+
+		intel_dp_start_link_train(intel_dp);
+		intel_dp_complete_link_train(intel_dp);
+		intel_dp_stop_link_train(intel_dp);
+	}
+
+	ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
+				       intel_mst->port, intel_crtc->config.pbn, &slots);
+	if (ret == false) {
+		DRM_ERROR("failed to allocate vcpi\n");
+		return;
+	}
+
+
+	intel_dp->active_mst_links++;
+	temp = I915_READ(DP_TP_STATUS(port));
+	I915_WRITE(DP_TP_STATUS(port), temp);
+
+	ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
+}
+
+static void intel_mst_enable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_dig_port->port;
+	int ret;
+
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+	if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_ACT_SENT),
+		     1))
+		DRM_ERROR("Timed out waiting for ACT sent\n");
+
+	ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
+
+	ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+}
+
+static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
+				      enum pipe *pipe)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	*pipe = intel_mst->pipe;
+	if (intel_mst->port)
+		return true;
+	return false;
+}
+
+static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
+					struct intel_crtc_config *pipe_config)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
+	u32 temp, flags = 0;
+
+	pipe_config->has_dp_encoder = true;
+
+	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+	if (temp & TRANS_DDI_PHSYNC)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (temp & TRANS_DDI_PVSYNC)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	switch (temp & TRANS_DDI_BPC_MASK) {
+	case TRANS_DDI_BPC_6:
+		pipe_config->pipe_bpp = 18;
+		break;
+	case TRANS_DDI_BPC_8:
+		pipe_config->pipe_bpp = 24;
+		break;
+	case TRANS_DDI_BPC_10:
+		pipe_config->pipe_bpp = 30;
+		break;
+	case TRANS_DDI_BPC_12:
+		pipe_config->pipe_bpp = 36;
+		break;
+	default:
+		break;
+	}
+	pipe_config->adjusted_mode.flags |= flags;
+	intel_dp_get_m_n(crtc, pipe_config);
+
+	intel_ddi_clock_get(&intel_dig_port->base, pipe_config);
+}
+
+static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_dp *intel_dp = intel_connector->mst_port;
+	struct edid *edid;
+	int ret;
+
+	edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
+	if (!edid)
+		return 0;
+
+	ret = intel_connector_update_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
+}
+
+static enum drm_connector_status
+intel_mst_port_dp_detect(struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_dp *intel_dp = intel_connector->mst_port;
+
+	return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
+}
+
+static enum drm_connector_status
+intel_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status;
+	status = intel_mst_port_dp_detect(connector);
+	return status;
+}
+
+static int
+intel_dp_mst_set_property(struct drm_connector *connector,
+			  struct drm_property *property,
+			  uint64_t val)
+{
+	return 0;
+}
+
+static void
+intel_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+
+	if (!IS_ERR_OR_NULL(intel_connector->edid))
+		kfree(intel_connector->edid);
+
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
+	.dpms = intel_connector_dpms,
+	.detect = intel_dp_mst_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = intel_dp_mst_set_property,
+	.destroy = intel_dp_mst_connector_destroy,
+};
+
+static int intel_dp_mst_get_modes(struct drm_connector *connector)
+{
+	return intel_dp_mst_get_ddc_modes(connector);
+}
+
+static enum drm_mode_status
+intel_dp_mst_mode_valid(struct drm_connector *connector,
+			struct drm_display_mode *mode)
+{
+	/* TODO - validate mode against available PBN for link */
+	if (mode->clock < 10000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		return MODE_H_ILLEGAL;
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_dp *intel_dp = intel_connector->mst_port;
+	return &intel_dp->mst_encoders[0]->base.base;
+}
+
+static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
+	.get_modes = intel_dp_mst_get_modes,
+	.mode_valid = intel_dp_mst_mode_valid,
+	.best_encoder = intel_mst_best_encoder,
+};
+
+static void intel_dp_mst_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
+
+	drm_encoder_cleanup(encoder);
+	kfree(intel_mst);
+}
+
+static const struct drm_encoder_funcs intel_dp_mst_enc_funcs = {
+	.destroy = intel_dp_mst_encoder_destroy,
+};
+
+static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
+{
+	if (connector->encoder) {
+		enum pipe pipe;
+		if (!connector->encoder->get_hw_state(connector->encoder, &pipe))
+			return false;
+		return true;
+	}
+	return false;
+}
+
+static void intel_connector_add_to_fbdev(struct intel_connector *connector)
+{
+#ifdef CONFIG_DRM_I915_FBDEV
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
+#endif
+}
+
+static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
+{
+#ifdef CONFIG_DRM_I915_FBDEV
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
+#endif
+}
+
+static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, char *pathprop)
+{
+	struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct intel_connector *intel_connector;
+	struct drm_connector *connector;
+	int i;
+
+	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	if (!intel_connector)
+		return NULL;
+
+	connector = &intel_connector->base;
+	drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort);
+	drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
+
+	intel_connector->unregister = intel_connector_unregister;
+	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
+	intel_connector->mst_port = intel_dp;
+	intel_connector->port = port;
+
+	for (i = PIPE_A; i <= PIPE_C; i++) {
+		drm_mode_connector_attach_encoder(&intel_connector->base,
+						  &intel_dp->mst_encoders[i]->base.base);
+	}
+	intel_dp_add_properties(intel_dp, connector);
+
+	drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+	drm_mode_connector_set_path_property(connector, pathprop);
+	drm_reinit_primary_mode_group(dev);
+	mutex_lock(&dev->mode_config.mutex);
+	intel_connector_add_to_fbdev(intel_connector);
+	mutex_unlock(&dev->mode_config.mutex);
+	drm_connector_register(&intel_connector->base);
+	return connector;
+}
+
+static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+					   struct drm_connector *connector)
+{
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_device *dev = connector->dev;
+	/* need to nuke the connector */
+	mutex_lock(&dev->mode_config.mutex);
+	intel_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	intel_connector->unregister(intel_connector);
+
+	mutex_lock(&dev->mode_config.mutex);
+	intel_connector_remove_from_fbdev(intel_connector);
+	drm_connector_cleanup(connector);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	drm_reinit_primary_mode_group(dev);
+
+	kfree(intel_connector);
+	DRM_DEBUG_KMS("\n");
+}
+
+static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+static struct drm_dp_mst_topology_cbs mst_cbs = {
+	.add_connector = intel_dp_add_mst_connector,
+	.destroy_connector = intel_dp_destroy_mst_connector,
+	.hotplug = intel_dp_mst_hotplug,
+};
+
+static struct intel_dp_mst_encoder *
+intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum pipe pipe)
+{
+	struct intel_dp_mst_encoder *intel_mst;
+	struct intel_encoder *intel_encoder;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+
+	intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL);
+
+	if (!intel_mst)
+		return NULL;
+
+	intel_mst->pipe = pipe;
+	intel_encoder = &intel_mst->base;
+	intel_mst->primary = intel_dig_port;
+
+	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
+			 DRM_MODE_ENCODER_DPMST);
+
+	intel_encoder->type = INTEL_OUTPUT_DP_MST;
+	intel_encoder->crtc_mask = 0x7;
+	intel_encoder->cloneable = 0;
+
+	intel_encoder->compute_config = intel_dp_mst_compute_config;
+	intel_encoder->disable = intel_mst_disable_dp;
+	intel_encoder->post_disable = intel_mst_post_disable_dp;
+	intel_encoder->pre_enable = intel_mst_pre_enable_dp;
+	intel_encoder->enable = intel_mst_enable_dp;
+	intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state;
+	intel_encoder->get_config = intel_dp_mst_enc_get_config;
+
+	return intel_mst;
+
+}
+
+static bool
+intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port)
+{
+	int i;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+	for (i = PIPE_A; i <= PIPE_C; i++)
+		intel_dp->mst_encoders[i] = intel_dp_create_fake_mst_encoder(intel_dig_port, i);
+	return true;
+}
+
+int
+intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id)
+{
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	int ret;
+
+	intel_dp->can_mst = true;
+	intel_dp->mst_mgr.cbs = &mst_cbs;
+
+	/* create encoders */
+	intel_dp_create_fake_mst_encoders(intel_dig_port);
+	ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev->dev, &intel_dp->aux, 16, 3, conn_base_id);
+	if (ret) {
+		intel_dp->can_mst = false;
+		return ret;
+	}
+	return 0;
+}
+
+void
+intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port)
+{
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+	if (!intel_dp->can_mst)
+		return;
+
+	drm_dp_mst_topology_mgr_destroy(&intel_dp->mst_mgr);
+	/* encoders will get killed by normal cleanup */
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_dp_helper.h>
+#include <drm/drm_dp_mst_helper.h>
 
 /**
  * _wait_for - magic (register) wait macro
@@ -100,6 +100,7 @@
 #define INTEL_OUTPUT_EDP 8
 #define INTEL_OUTPUT_DSI 9
 #define INTEL_OUTPUT_UNKNOWN 10
+#define INTEL_OUTPUT_DP_MST 11
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -152,6 +153,12 @@ struct intel_encoder {
 	 * be set correctly before calling this function. */
 	void (*get_config)(struct intel_encoder *,
 			   struct intel_crtc_config *pipe_config);
+	/*
+	 * Called during system suspend after all pending requests for the
+	 * encoder are flushed (for example for DP AUX transactions) and
+	 * device interrupts are disabled.
+	 */
+	void (*suspend)(struct intel_encoder *);
 	int crtc_mask;
 	enum hpd_pin hpd_pin;
 };
@@ -165,6 +172,7 @@ struct intel_panel {
 	struct {
 		bool present;
 		u32 level;
+		u32 min;
 		u32 max;
 		bool enabled;
 		bool combination_mode;	/* gen 2/4 only */
@@ -207,6 +215,10 @@ struct intel_connector {
 	/* since POLL and HPD connectors may use the same HPD line keep the native
 	   state of connector->polled in case hotplug storm detection changes it */
 	u8 polled;
+
+	void *port; /* store this opaque as its illegal to dereference it */
+
+	struct intel_dp *mst_port;
 };
 
 typedef struct dpll {
@@ -307,6 +319,9 @@ struct intel_crtc_config {
 	/* Selected dpll when shared or DPLL_ID_PRIVATE. */
 	enum intel_dpll_id shared_dpll;
 
+	/* PORT_CLK_SEL for DDI ports. */
+	uint32_t ddi_pll_sel;
+
 	/* Actual register state of the dpll, for shared dpll cross-checking. */
 	struct intel_dpll_hw_state dpll_hw_state;
 
@@ -338,6 +353,7 @@ struct intel_crtc_config {
 		u32 pos;
 		u32 size;
 		bool enabled;
+		bool force_thru;
 	} pch_pfit;
 
 	/* FDI configuration, only valid if has_pch_encoder is set. */
@@ -347,6 +363,9 @@ struct intel_crtc_config {
 	bool ips_enabled;
 
 	bool double_wide;
+
+	bool dp_encoder_is_mst;
+	int pbn;
 };
 
 struct intel_pipe_wm {
@@ -358,6 +377,11 @@ struct intel_pipe_wm {
 	bool sprites_scaled;
 };
 
+struct intel_mmio_flip {
+	u32 seqno;
+	u32 ring_id;
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -384,7 +408,6 @@ struct intel_crtc {
 
 	struct drm_i915_gem_object *cursor_bo;
 	uint32_t cursor_addr;
-	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
 	uint32_t cursor_cntl;
 	uint32_t cursor_base;
@@ -394,8 +417,6 @@ struct intel_crtc {
 	struct intel_crtc_config *new_config;
 	bool new_enabled;
 
-	uint32_t ddi_pll_sel;
-
 	/* reset counter value when the last flip was submitted */
 	unsigned int reset_counter;
 
@@ -412,10 +433,12 @@ struct intel_crtc {
 	wait_queue_head_t vbl_wait;
 
 	int scanline_offset;
+	struct intel_mmio_flip mmio_flip;
 };
 
 struct intel_plane_wm_parameters {
 	uint32_t horiz_pixels;
+	uint32_t vert_pixels;
 	uint8_t bytes_per_pixel;
 	bool enabled;
 	bool scaled;
@@ -428,7 +451,6 @@ struct intel_plane {
 	struct drm_i915_gem_object *obj;
 	bool can_scale;
 	int max_downscale;
-	u32 lut_r[1024], lut_g[1024], lut_b[1024];
 	int crtc_x, crtc_y;
 	unsigned int crtc_w, crtc_h;
 	uint32_t src_x, src_y;
@@ -481,6 +503,7 @@ struct cxsr_latency {
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
+#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
 
 struct intel_hdmi {
 	u32 hdmi_reg;
@@ -491,6 +514,7 @@ struct intel_hdmi {
 	bool has_audio;
 	enum hdmi_force_audio force_audio;
 	bool rgb_quant_range_selectable;
+	enum hdmi_picture_aspect aspect_ratio;
 	void (*write_infoframe)(struct drm_encoder *encoder,
 				enum hdmi_infoframe_type type,
 				const void *frame, ssize_t len);
@@ -499,6 +523,7 @@ struct intel_hdmi {
 			       struct drm_display_mode *adjusted_mode);
 };
 
+struct intel_dp_mst_encoder;
 #define DP_MAX_DOWNSTREAM_PORTS		0x10
 
 /**
@@ -537,12 +562,20 @@ struct intel_dp {
 	unsigned long last_power_cycle;
 	unsigned long last_power_on;
 	unsigned long last_backlight_off;
-	bool psr_setup_done;
+
 	struct notifier_block edp_notifier;
 
 	bool use_tps3;
+	bool can_mst; /* this port supports mst */
+	bool is_mst;
+	int active_mst_links;
+	/* connector directly attached - won't be use for modeset in mst world */
 	struct intel_connector *attached_connector;
 
+	/* mst connector list */
+	struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES];
+	struct drm_dp_mst_topology_mgr mst_mgr;
+
 	uint32_t (*get_aux_clock_divider)(struct intel_dp *dp, int index);
 	/*
 	 * This function returns the value we have to program the AUX_CTL
@@ -566,6 +599,14 @@ struct intel_digital_port {
 	u32 saved_port_bits;
 	struct intel_dp dp;
 	struct intel_hdmi hdmi;
+	bool (*hpd_pulse)(struct intel_digital_port *, bool);
+};
+
+struct intel_dp_mst_encoder {
+	struct intel_encoder base;
+	enum pipe pipe;
+	struct intel_digital_port *primary;
+	void *port; /* store this opaque as its illegal to dereference it */
 };
 
 static inline int
@@ -652,6 +693,12 @@ enc_to_dig_port(struct drm_encoder *enco
 	return container_of(encoder, struct intel_digital_port, base.base);
 }
 
+static inline struct intel_dp_mst_encoder *
+enc_to_mst(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct intel_dp_mst_encoder, base.base);
+}
+
 static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 {
 	return &enc_to_dig_port(encoder)->dp;
@@ -676,17 +723,26 @@ bool intel_set_cpu_fifo_underrun_reporti
 bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 					   enum transcoder pch_transcoder,
 					   bool enable);
-void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+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_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 gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void intel_runtime_pm_disable_interrupts(struct drm_device *dev);
 void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
+static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
+{
+	/*
+	 * We only use drm_irq_uninstall() at unload and VT switch, so
+	 * this is the only thing we need to check.
+	 */
+	return !dev_priv->pm._irqs_disabled;
+}
+
 int intel_get_crtc_scanline(struct intel_crtc *crtc);
 void i9xx_check_fifo_underruns(struct drm_device *dev);
-
+void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);
 
 /* intel_crt.c */
 void intel_crt_init(struct drm_device *dev);
@@ -705,10 +761,7 @@ void intel_ddi_disable_transcoder_func(s
 				       enum transcoder cpu_transcoder);
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
-void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
 bool intel_ddi_pll_select(struct intel_crtc *crtc);
-void intel_ddi_pll_enable(struct intel_crtc *crtc);
-void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
 bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
@@ -716,17 +769,46 @@ void intel_ddi_fdi_disable(struct drm_cr
 void intel_ddi_get_config(struct intel_encoder *encoder,
 			  struct intel_crtc_config *pipe_config);
 
+void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder);
+void intel_ddi_clock_get(struct intel_encoder *encoder,
+			 struct intel_crtc_config *pipe_config);
+void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state);
 
 /* intel_display.c */
 const char *intel_output_name(int output);
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
-int valleyview_cur_cdclk(struct drm_i915_private *dev_priv);
 void intel_mark_busy(struct drm_device *dev);
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
-			struct intel_engine_cs *ring);
+void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+			     struct intel_engine_cs *ring);
+void intel_frontbuffer_flip_prepare(struct drm_device *dev,
+				    unsigned frontbuffer_bits);
+void intel_frontbuffer_flip_complete(struct drm_device *dev,
+				     unsigned frontbuffer_bits);
+void intel_frontbuffer_flush(struct drm_device *dev,
+			     unsigned frontbuffer_bits);
+/**
+ * intel_frontbuffer_flip - prepare frontbuffer flip
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after scheduling a flip on @obj. This is for
+ * synchronous plane updates which will happen on the next vblank and which will
+ * not get delayed by pending gpu rendering.
+ *
+ * Can be called without any locks held.
+ */
+static inline
+void intel_frontbuffer_flip(struct drm_device *dev,
+			    unsigned frontbuffer_bits)
+{
+	intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
+void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
 void intel_mark_idle(struct drm_device *dev);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
+void intel_crtc_control(struct drm_crtc *crtc, bool enable);
 void intel_crtc_update_dpms(struct drm_crtc *crtc);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 void intel_connector_dpms(struct drm_connector *, int mode);
@@ -754,8 +836,7 @@ bool intel_get_load_detect_pipe(struct d
 				struct intel_load_detect_pipe *old,
 				struct drm_modeset_acquire_ctx *ctx);
 void intel_release_load_detect_pipe(struct drm_connector *connector,
-				    struct intel_load_detect_pipe *old,
-				    struct drm_modeset_acquire_ctx *ctx);
+				    struct intel_load_detect_pipe *old);
 int intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			       struct drm_i915_gem_object *obj,
 			       struct intel_engine_cs *pipelined);
@@ -767,12 +848,18 @@ __intel_framebuffer_create(struct drm_de
 void intel_prepare_page_flip(struct drm_device *dev, int plane);
 void intel_finish_page_flip(struct drm_device *dev, int pipe);
 void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
+
+/* shared dpll functions */
 struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
 void assert_shared_dpll(struct drm_i915_private *dev_priv,
 			struct intel_shared_dpll *pll,
 			bool state);
 #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
 #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc);
+void intel_put_shared_dpll(struct intel_crtc *crtc);
+
+/* modesetting asserts */
 void assert_pll(struct drm_i915_private *dev_priv,
 		enum pipe pipe, bool state);
 #define assert_pll_enabled(d, p) assert_pll(d, p, true)
@@ -805,7 +892,6 @@ void hsw_disable_ips(struct intel_crtc *
 void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
 enum intel_display_power_domain
 intel_display_port_power_domain(struct intel_encoder *intel_encoder);
-int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_config *pipe_config);
 int intel_format_to_fourcc(int format);
@@ -826,18 +912,34 @@ int intel_dp_sink_crc(struct intel_dp *i
 bool intel_dp_compute_config(struct intel_encoder *encoder,
 			     struct intel_crtc_config *pipe_config);
 bool intel_dp_is_edp(struct drm_device *dev, enum port port);
+bool intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
+			bool long_hpd);
 void intel_edp_backlight_on(struct intel_dp *intel_dp);
 void intel_edp_backlight_off(struct intel_dp *intel_dp);
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
+void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder);
 void intel_edp_panel_on(struct intel_dp *intel_dp);
 void intel_edp_panel_off(struct intel_dp *intel_dp);
 void intel_edp_psr_enable(struct intel_dp *intel_dp);
 void intel_edp_psr_disable(struct intel_dp *intel_dp);
-void intel_edp_psr_update(struct drm_device *dev);
 void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
+void intel_edp_psr_invalidate(struct drm_device *dev,
+			      unsigned frontbuffer_bits);
+void intel_edp_psr_flush(struct drm_device *dev,
+			 unsigned frontbuffer_bits);
+void intel_edp_psr_init(struct drm_device *dev);
 
+int intel_dp_handle_hpd_irq(struct intel_digital_port *digport, bool long_hpd);
+void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector);
+void intel_dp_mst_suspend(struct drm_device *dev);
+void intel_dp_mst_resume(struct drm_device *dev);
+int intel_dp_max_link_bw(struct intel_dp *intel_dp);
+void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
+/* intel_dp_mst.c */
+int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
+void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
 /* intel_dsi.c */
-bool intel_dsi_init(struct drm_device *dev);
+void intel_dsi_init(struct drm_device *dev);
 
 
 /* intel_dvo.c */
@@ -920,8 +1022,8 @@ void intel_pch_panel_fitting(struct inte
 void intel_gmch_panel_fitting(struct intel_crtc *crtc,
 			      struct intel_crtc_config *pipe_config,
 			      int fitting_mode);
-void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
-			       u32 max);
+void intel_panel_set_backlight_acpi(struct intel_connector *connector,
+				    u32 level, u32 max);
 int intel_panel_setup_backlight(struct drm_connector *connector);
 void intel_panel_enable_backlight(struct intel_connector *connector);
 void intel_panel_disable_backlight(struct intel_connector *connector);
@@ -940,7 +1042,9 @@ int ilk_wm_max_level(const struct drm_de
 void intel_update_watermarks(struct drm_crtc *crtc);
 void intel_update_sprite_watermarks(struct drm_plane *plane,
 				    struct drm_crtc *crtc,
-				    uint32_t sprite_width, int pixel_size,
+				    uint32_t sprite_width,
+				    uint32_t sprite_height,
+				    int pixel_size,
 				    bool enabled, bool scaled);
 void intel_init_pm(struct drm_device *dev);
 void intel_pm_setup(struct drm_device *dev);
@@ -963,6 +1067,7 @@ void intel_init_gt_powersave(struct drm_
 void intel_cleanup_gt_powersave(struct drm_device *dev);
 void intel_enable_gt_powersave(struct drm_device *dev);
 void intel_disable_gt_powersave(struct drm_device *dev);
+void intel_suspend_gt_powersave(struct drm_device *dev);
 void intel_reset_gt_powersave(struct drm_device *dev);
 void ironlake_teardown_rc6(struct drm_device *dev);
 void gen6_update_ring_freq(struct drm_device *dev);
@@ -976,8 +1081,7 @@ void intel_runtime_pm_put(struct drm_i91
 void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
-void __vlv_set_power_well(struct drm_i915_private *dev_priv,
-			  enum punit_power_well power_well_id, bool enable);
+
 
 /* intel_sdvo.c */
 bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,6 +92,9 @@ static bool intel_dsi_compute_config(str
 	if (fixed_mode)
 		intel_fixed_panel_mode(fixed_mode, adjusted_mode);
 
+	/* DSI uses short packets for sync events, so clear mode flags for DSI */
+	adjusted_mode->flags = 0;
+
 	if (intel_dsi->dev.dev_ops->mode_fixup)
 		return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev,
 							  mode, adjusted_mode);
@@ -152,6 +155,8 @@ static void intel_dsi_enable(struct inte
 		if (intel_dsi->dev.dev_ops->enable)
 			intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
 
+		wait_for_dsi_fifo_empty(intel_dsi);
+
 		/* assert ip_tg_enable signal */
 		temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
 		temp = temp | intel_dsi->port_bits;
@@ -177,6 +182,10 @@ static void intel_dsi_pre_enable(struct
 	tmp |= DPLL_REFA_CLK_ENABLE_VLV;
 	I915_WRITE(DPLL(pipe), tmp);
 
+	/* update the hw state for DPLL */
+	intel_crtc->config.dpll_hw_state.dpll = DPLL_INTEGRATED_CLOCK_VLV |
+						DPLL_REFA_CLK_ENABLE_VLV;
+
 	tmp = I915_READ(DSPCLK_GATE_D);
 	tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
 	I915_WRITE(DSPCLK_GATE_D, tmp);
@@ -192,6 +201,8 @@ static void intel_dsi_pre_enable(struct
 	if (intel_dsi->dev.dev_ops->send_otp_cmds)
 		intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
 
+	wait_for_dsi_fifo_empty(intel_dsi);
+
 	/* Enable port in pre-enable phase itself because as per hw team
 	 * recommendation, port should be enabled befor plane & pipe */
 	intel_dsi_enable(encoder);
@@ -232,6 +243,8 @@ static void intel_dsi_disable(struct int
 	DRM_DEBUG_KMS("\n");
 
 	if (is_vid_mode(intel_dsi)) {
+		wait_for_dsi_fifo_empty(intel_dsi);
+
 		/* de-assert ip_tg_enable signal */
 		temp = I915_READ(MIPI_PORT_CTRL(pipe));
 		I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE);
@@ -261,6 +274,8 @@ static void intel_dsi_disable(struct int
 	 * some next enable sequence send turn on packet error is observed */
 	if (intel_dsi->dev.dev_ops->disable)
 		intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
+
+	wait_for_dsi_fifo_empty(intel_dsi);
 }
 
 static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
@@ -351,9 +366,21 @@ static bool intel_dsi_get_hw_state(struc
 static void intel_dsi_get_config(struct intel_encoder *encoder,
 				 struct intel_crtc_config *pipe_config)
 {
+	u32 pclk;
 	DRM_DEBUG_KMS("\n");
 
-	/* XXX: read flags, set to adjusted_mode */
+	/*
+	 * DPLL_MD is not used in case of DSI, reading will get some default value
+	 * set dpll_md = 0
+	 */
+	pipe_config->dpll_hw_state.dpll_md = 0;
+
+	pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
+	if (!pclk)
+		return;
+
+	pipe_config->adjusted_mode.crtc_clock = pclk;
+	pipe_config->port_clock = pclk;
 }
 
 static enum drm_mode_status
@@ -658,7 +685,7 @@ static const struct drm_connector_funcs
 	.fill_modes = drm_helper_probe_single_connector_modes,
 };
 
-bool intel_dsi_init(struct drm_device *dev)
+void intel_dsi_init(struct drm_device *dev)
 {
 	struct intel_dsi *intel_dsi;
 	struct intel_encoder *intel_encoder;
@@ -674,29 +701,29 @@ bool intel_dsi_init(struct drm_device *d
 
 	/* There is no detection method for MIPI so rely on VBT */
 	if (!dev_priv->vbt.has_mipi)
-		return false;
+		return;
+
+	if (IS_VALLEYVIEW(dev)) {
+		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
+	} else {
+		DRM_ERROR("Unsupported Mipi device to reg base");
+		return;
+	}
 
 	intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
 	if (!intel_dsi)
-		return false;
+		return;
 
 	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
 		kfree(intel_dsi);
-		return false;
+		return;
 	}
 
 	intel_encoder = &intel_dsi->base;
 	encoder = &intel_encoder->base;
 	intel_dsi->attached_connector = intel_connector;
 
-	if (IS_VALLEYVIEW(dev)) {
-		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
-	} else {
-		DRM_ERROR("Unsupported Mipi device to reg base");
-		return false;
-	}
-
 	connector = &intel_connector->base;
 
 	drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI);
@@ -743,7 +770,7 @@ bool intel_dsi_init(struct drm_device *d
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev);
 	if (!fixed_mode) {
@@ -754,12 +781,10 @@ bool intel_dsi_init(struct drm_device *d
 	fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 
-	return true;
+	return;
 
 err:
 	drm_encoder_cleanup(&intel_encoder->base);
 	kfree(intel_dsi);
 	kfree(intel_connector);
-
-	return false;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -419,3 +419,19 @@ int dpi_send_cmd(struct intel_dsi *intel
 
 	return 0;
 }
+
+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi)
+{
+	struct drm_encoder *encoder = &intel_dsi->base.base;
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	u32 mask;
+
+	mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
+					LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
+
+	if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 100))
+		DRM_ERROR("DPI FIFOs are not empty\n");
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,7 @@ int dsi_vc_generic_read(struct intel_dsi
 			u8 *reqdata, int reqlen, u8 *buf, int buflen);
 
 int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs);
+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi);
 
 /* XXX: questionable write helpers */
 static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi.h	2014-09-28 17:29:07.000000000 -0400
@@ -132,6 +132,7 @@ static inline struct intel_dsi *enc_to_i
 
 extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
 extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
+extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp);
 
 extern struct intel_dsi_dev_ops vbt_generic_dsi_display_ops;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,7 +143,7 @@ static u8 *mipi_exec_send_packet(struct
 	case MIPI_DSI_DCS_LONG_WRITE:
 		dsi_vc_dcs_write(intel_dsi, vc, data, len);
 		break;
-	};
+	}
 
 	data += len;
 
@@ -294,7 +294,8 @@ static bool generic_init(struct intel_ds
 	intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
 	intel_dsi->init_count = mipi_config->master_init_timer;
 	intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
-	intel_dsi->video_frmt_cfg_bits = mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
+	intel_dsi->video_frmt_cfg_bits =
+		mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
 
 	switch (intel_dsi->escape_clk_div) {
 	case 0:
@@ -351,7 +352,8 @@ static bool generic_init(struct intel_ds
 	 *
 	 * prepare count
 	 */
-	ths_prepare_ns = max(mipi_config->ths_prepare, mipi_config->tclk_prepare);
+	ths_prepare_ns = max(mipi_config->ths_prepare,
+			     mipi_config->tclk_prepare);
 	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * 2);
 
 	/* exit zero count */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2014-09-28 17:29:07.000000000 -0400
@@ -298,3 +298,84 @@ void vlv_disable_dsi_pll(struct intel_en
 
 	mutex_unlock(&dev_priv->dpio_lock);
 }
+
+static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
+{
+	int bpp;
+
+	switch (pixel_format) {
+	default:
+	case VID_MODE_FORMAT_RGB888:
+	case VID_MODE_FORMAT_RGB666_LOOSE:
+		bpp = 24;
+		break;
+	case VID_MODE_FORMAT_RGB666:
+		bpp = 18;
+		break;
+	case VID_MODE_FORMAT_RGB565:
+		bpp = 16;
+		break;
+	}
+
+	WARN(bpp != pipe_bpp,
+		"bpp match assertion failure (expected %d, current %d)\n",
+		bpp, pipe_bpp);
+}
+
+u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	u32 dsi_clock, pclk;
+	u32 pll_ctl, pll_div;
+	u32 m = 0, p = 0;
+	int refclk = 25000;
+	int i;
+
+	DRM_DEBUG_KMS("\n");
+
+	mutex_lock(&dev_priv->dpio_lock);
+	pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
+	pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER);
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	/* mask out other bits and extract the P1 divisor */
+	pll_ctl &= DSI_PLL_P1_POST_DIV_MASK;
+	pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);
+
+	/* mask out the other bits and extract the M1 divisor */
+	pll_div &= DSI_PLL_M1_DIV_MASK;
+	pll_div = pll_div >> DSI_PLL_M1_DIV_SHIFT;
+
+	while (pll_ctl) {
+		pll_ctl = pll_ctl >> 1;
+		p++;
+	}
+	p--;
+
+	if (!p) {
+		DRM_ERROR("wrong P1 divisor\n");
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(lfsr_converts); i++) {
+		if (lfsr_converts[i] == pll_div)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(lfsr_converts)) {
+		DRM_ERROR("wrong m_seed programmed\n");
+		return 0;
+	}
+
+	m = i + 62;
+
+	dsi_clock = (m * refclk) / p;
+
+	/* pixel_format and pipe_bpp should agree */
+	assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
+
+	pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp);
+
+	return pclk;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dvo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dvo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_dvo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_dvo.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,7 +112,15 @@ static struct intel_dvo *intel_attached_
 
 static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
 {
+	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_dvo->dev.dvo_reg);
+
+	if (!(tmp & DVO_ENABLE))
+		return false;
 
 	return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
 }
@@ -558,7 +566,7 @@ void intel_dvo_init(struct drm_device *d
 			intel_dvo->panel_wants_dither = true;
 		}
 
-		drm_sysfs_connector_add(connector);
+		drm_connector_register(connector);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,10 +43,36 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+static int intel_fbdev_set_par(struct fb_info *info)
+{
+	struct drm_fb_helper *fb_helper = info->par;
+	struct intel_fbdev *ifbdev =
+		container_of(fb_helper, struct intel_fbdev, helper);
+	int ret;
+
+	ret = drm_fb_helper_set_par(info);
+
+	if (ret == 0) {
+		/*
+		 * FIXME: fbdev presumes that all callbacks also work from
+		 * atomic contexts and relies on that for emergency oops
+		 * printing. KMS totally doesn't do that and the locking here is
+		 * by far not the only place this goes wrong.  Ignore this for
+		 * now until we solve this for real.
+		 */
+		mutex_lock(&fb_helper->dev->struct_mutex);
+		ret = i915_gem_object_set_to_gtt_domain(ifbdev->fb->obj,
+							true);
+		mutex_unlock(&fb_helper->dev->struct_mutex);
+	}
+
+	return ret;
+}
+
 static struct fb_ops intelfb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
+	.fb_set_par = intel_fbdev_set_par,
 	.fb_fillrect = cfb_fillrect,
 	.fb_copyarea = cfb_copyarea,
 	.fb_imageblit = cfb_imageblit,
@@ -81,7 +107,7 @@ static int intelfb_alloc(struct drm_fb_h
 							  sizes->surface_depth);
 
 	size = mode_cmd.pitches[0] * mode_cmd.height;
-	size = ALIGN(size, PAGE_SIZE);
+	size = PAGE_ALIGN(size);
 	obj = i915_gem_object_create_stolen(dev, size);
 	if (obj == NULL)
 		obj = i915_gem_alloc_object(dev, size);
@@ -417,7 +443,7 @@ static bool intel_fb_initial_config(stru
 		}
 		crtcs[i] = new_crtc;
 
-		DRM_DEBUG_KMS("connector %s on pipe %d [CRTC:%d]: %dx%d%s\n",
+		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
 			      connector->name,
 			      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
 			      encoder->crtc->base.id,
@@ -452,7 +478,7 @@ out:
 	return true;
 }
 
-static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
 	.initial_config = intel_fb_initial_config,
 	.gamma_set = intel_crtc_fb_gamma_set,
 	.gamma_get = intel_crtc_fb_gamma_get,
@@ -623,7 +649,8 @@ int intel_fbdev_init(struct drm_device *
 	if (ifbdev == NULL)
 		return -ENOMEM;
 
-	ifbdev->helper.funcs = &intel_fb_helper_funcs;
+	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
+
 	if (!intel_fbdev_init_bios(dev, ifbdev))
 		ifbdev->preferred_bpp = 32;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -367,6 +367,9 @@ static void intel_hdmi_set_avi_infoframe
 	union hdmi_infoframe frame;
 	int ret;
 
+	/* Set user selected PAR to incoming mode's member */
+	adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
+
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
 						       adjusted_mode);
 	if (ret < 0) {
@@ -709,7 +712,8 @@ static void intel_hdmi_get_config(struct
 				  struct intel_crtc_config *pipe_config)
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 tmp, flags = 0;
 	int dotclock;
 
@@ -728,9 +732,13 @@ static void intel_hdmi_get_config(struct
 	if (tmp & HDMI_MODE_SELECT_HDMI)
 		pipe_config->has_hdmi_sink = true;
 
-	if (tmp & HDMI_MODE_SELECT_HDMI)
+	if (tmp & SDVO_AUDIO_ENABLE)
 		pipe_config->has_audio = true;
 
+	if (!HAS_PCH_SPLIT(dev) &&
+	    tmp & HDMI_COLOR_RANGE_16_235)
+		pipe_config->limited_color_range = true;
+
 	pipe_config->adjusted_mode.flags |= flags;
 
 	if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc)
@@ -879,7 +887,7 @@ static bool hdmi_12bpc_possible(struct i
 	struct intel_encoder *encoder;
 	int count = 0, count_hdmi = 0;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (HAS_GMCH_DISPLAY(dev))
 		return false;
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
@@ -1124,6 +1132,23 @@ intel_hdmi_set_property(struct drm_conne
 		goto done;
 	}
 
+	if (property == connector->dev->mode_config.aspect_ratio_property) {
+		switch (val) {
+		case DRM_MODE_PICTURE_ASPECT_NONE:
+			intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
+			break;
+		case DRM_MODE_PICTURE_ASPECT_4_3:
+			intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
+			break;
+		case DRM_MODE_PICTURE_ASPECT_16_9:
+			intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
+			break;
+		default:
+			return -EINVAL;
+		}
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -1229,6 +1254,70 @@ static void vlv_hdmi_pre_pll_enable(stru
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
+static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(encoder->base.crtc);
+	enum dpio_channel ch = vlv_dport_to_channel(dport);
+	enum pipe pipe = intel_crtc->pipe;
+	u32 val;
+
+	mutex_lock(&dev_priv->dpio_lock);
+
+	/* program left/right clock distribution */
+	if (pipe != PIPE_B) {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+		if (ch == DPIO_CH0)
+			val |= CHV_BUFLEFTENA1_FORCE;
+		if (ch == DPIO_CH1)
+			val |= CHV_BUFRIGHTENA1_FORCE;
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+	} else {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+		if (ch == DPIO_CH0)
+			val |= CHV_BUFLEFTENA2_FORCE;
+		if (ch == DPIO_CH1)
+			val |= CHV_BUFRIGHTENA2_FORCE;
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+	}
+
+	/* program clock channel usage */
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch));
+	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+	if (pipe != PIPE_B)
+		val &= ~CHV_PCS_USEDCLKCHANNEL;
+	else
+		val |= CHV_PCS_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+	if (pipe != PIPE_B)
+		val &= ~CHV_PCS_USEDCLKCHANNEL;
+	else
+		val |= CHV_PCS_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+
+	/*
+	 * This a a bit weird since generally CL
+	 * matches the pipe, but here we need to
+	 * pick the CL based on the port.
+	 */
+	val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch));
+	if (pipe != PIPE_B)
+		val &= ~CHV_CMN_USEDCLKCHANNEL;
+	else
+		val |= CHV_CMN_USEDCLKCHANNEL;
+	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
+
+	mutex_unlock(&dev_priv->dpio_lock);
+}
+
 static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1416,11 +1505,22 @@ static const struct drm_encoder_funcs in
 };
 
 static void
+intel_attach_aspect_ratio_property(struct drm_connector *connector)
+{
+	if (!drm_mode_create_aspect_ratio_property(connector->dev))
+		drm_object_attach_property(&connector->base,
+			connector->dev->mode_config.aspect_ratio_property,
+			DRM_MODE_PICTURE_ASPECT_NONE);
+}
+
+static void
 intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
 {
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
 	intel_hdmi->color_range_auto = true;
+	intel_attach_aspect_ratio_property(connector);
+	intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
 }
 
 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
@@ -1467,7 +1567,7 @@ void intel_hdmi_init_connector(struct in
 	if (IS_VALLEYVIEW(dev)) {
 		intel_hdmi->write_infoframe = vlv_write_infoframe;
 		intel_hdmi->set_infoframes = vlv_set_infoframes;
-	} else if (!HAS_PCH_SPLIT(dev)) {
+	} else if (IS_G4X(dev)) {
 		intel_hdmi->write_infoframe = g4x_write_infoframe;
 		intel_hdmi->set_infoframes = g4x_set_infoframes;
 	} else if (HAS_DDI(dev)) {
@@ -1490,7 +1590,7 @@ void intel_hdmi_init_connector(struct in
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
 	 * 0xd.  Failure to do so will result in spurious interrupts being
@@ -1528,6 +1628,7 @@ 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)) {
+		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;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,11 +34,6 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
-enum disp_clk {
-	CDCLK,
-	CZCLK
-};
-
 struct gmbus_port {
 	const char *name;
 	int reg;
@@ -63,60 +58,11 @@ to_intel_gmbus(struct i2c_adapter *i2c)
 	return container_of(i2c, struct intel_gmbus, adapter);
 }
 
-static int get_disp_clk_div(struct drm_i915_private *dev_priv,
-			    enum disp_clk clk)
-{
-	u32 reg_val;
-	int clk_ratio;
-
-	reg_val = I915_READ(CZCLK_CDCLK_FREQ_RATIO);
-
-	if (clk == CDCLK)
-		clk_ratio =
-			((reg_val & CDCLK_FREQ_MASK) >> CDCLK_FREQ_SHIFT) + 1;
-	else
-		clk_ratio = (reg_val & CZCLK_FREQ_MASK) + 1;
-
-	return clk_ratio;
-}
-
-static void gmbus_set_freq(struct drm_i915_private *dev_priv)
-{
-	int vco, gmbus_freq = 0, cdclk_div;
-
-	BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
-
-	vco = valleyview_get_vco(dev_priv);
-
-	/* Get the CDCLK divide ratio */
-	cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
-
-	/*
-	 * Program the gmbus_freq based on the cdclk frequency.
-	 * BSpec erroneously claims we should aim for 4MHz, but
-	 * in fact 1MHz is the correct frequency.
-	 */
-	if (cdclk_div)
-		gmbus_freq = (vco << 1) / cdclk_div;
-
-	if (WARN_ON(gmbus_freq == 0))
-		return;
-
-	I915_WRITE(GMBUSFREQ_VLV, gmbus_freq);
-}
-
 void
 intel_i2c_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/*
-	 * In BIOS-less system, program the correct gmbus frequency
-	 * before reading edid.
-	 */
-	if (IS_VALLEYVIEW(dev))
-		gmbus_set_freq(dev_priv);
-
 	I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
 	I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_lvds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_lvds.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,7 @@ struct intel_lvds_encoder {
 
 	bool is_dual_link;
 	u32 reg;
+	u32 a3_power;
 
 	struct intel_lvds_connector *attached_connector;
 };
@@ -71,8 +72,13 @@ static bool intel_lvds_get_hw_state(stru
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+	enum intel_display_power_domain power_domain;
 	u32 tmp;
 
+	power_domain = intel_display_port_power_domain(encoder);
+	if (!intel_display_power_enabled(dev_priv, power_domain))
+		return false;
+
 	tmp = I915_READ(lvds_encoder->reg);
 
 	if (!(tmp & LVDS_PORT_EN))
@@ -172,8 +178,11 @@ static void intel_pre_enable_lvds(struct
 
 	/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
 	 * appropriately here, but we need to look more thoroughly into how
-	 * panels behave in the two modes.
+	 * panels behave in the two modes. For now, let's just maintain the
+	 * value we got from the BIOS.
 	 */
+	 temp &= ~LVDS_A3_POWER_MASK;
+	 temp |= lvds_encoder->a3_power;
 
 	/* Set the dithering flag on LVDS as needed, note that there is no
 	 * special lvds dither control bit on pch-split platforms, dithering is
@@ -271,7 +280,6 @@ static bool intel_lvds_compute_config(st
 				      struct intel_crtc_config *pipe_config)
 {
 	struct drm_device *dev = intel_encoder->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_lvds_encoder *lvds_encoder =
 		to_lvds_encoder(&intel_encoder->base);
 	struct intel_connector *intel_connector =
@@ -286,8 +294,7 @@ static bool intel_lvds_compute_config(st
 		return false;
 	}
 
-	if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) ==
-	    LVDS_A3_POWER_UP)
+	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
 		lvds_bpp = 8*3;
 	else
 		lvds_bpp = 6*3;
@@ -531,7 +538,7 @@ static const struct drm_encoder_funcs in
 	.destroy = intel_encoder_destroy,
 };
 
-static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
+static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
 {
 	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
 	return 1;
@@ -1088,6 +1095,9 @@ out:
 	DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
 		      lvds_encoder->is_dual_link ? "dual" : "single");
 
+	lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
+				 LVDS_A3_POWER_MASK;
+
 	/*
 	 * Unlock registers and just
 	 * leave them unlocked
@@ -1104,7 +1114,7 @@ out:
 		DRM_DEBUG_KMS("lid notifier registration failed\n");
 		lvds_connector->lid_notifier.notifier_call = NULL;
 	}
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
 	intel_panel_setup_backlight(connector);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_opregion.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_opregion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_opregion.c	2014-09-28 17:29:07.000000000 -0400
@@ -352,6 +352,7 @@ int intel_opregion_notify_encoder(struct
 	case INTEL_OUTPUT_UNKNOWN:
 	case INTEL_OUTPUT_DISPLAYPORT:
 	case INTEL_OUTPUT_HDMI:
+	case INTEL_OUTPUT_DP_MST:
 		type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
 		break;
 	case INTEL_OUTPUT_EDP:
@@ -427,7 +428,7 @@ static u32 asle_set_backlight(struct drm
 	 */
 	DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
 	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
-		intel_panel_set_backlight(intel_connector, bclp, 255);
+		intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
 	iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
 
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_overlay.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_overlay.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_overlay.c	2014-09-28 17:29:07.000000000 -0400
@@ -415,6 +415,10 @@ static int intel_overlay_release_old_vid
 	}
 
 	intel_overlay_release_old_vid_tail(overlay);
+
+
+	i915_gem_track_fb(overlay->old_vid_bo, NULL,
+			  INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
 	return 0;
 }
 
@@ -686,6 +690,7 @@ static int intel_overlay_do_put_image(st
 	bool scale_changed = false;
 	struct drm_device *dev = overlay->dev;
 	u32 swidth, swidthsw, sheight, ostride;
+	enum pipe pipe = overlay->crtc->pipe;
 
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 	BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
@@ -713,7 +718,7 @@ static int intel_overlay_do_put_image(st
 		oconfig = OCONF_CC_OUT_8BIT;
 		if (IS_GEN4(overlay->dev))
 			oconfig |= OCONF_CSC_MODE_BT709;
-		oconfig |= overlay->crtc->pipe == 0 ?
+		oconfig |= pipe == 0 ?
 			OCONF_PIPE_A : OCONF_PIPE_B;
 		iowrite32(oconfig, &regs->OCONFIG);
 		intel_overlay_unmap_regs(overlay, regs);
@@ -776,9 +781,15 @@ static int intel_overlay_do_put_image(st
 	if (ret)
 		goto out_unpin;
 
+	i915_gem_track_fb(overlay->vid_bo, new_bo,
+			  INTEL_FRONTBUFFER_OVERLAY(pipe));
+
 	overlay->old_vid_bo = overlay->vid_bo;
 	overlay->vid_bo = new_bo;
 
+	intel_frontbuffer_flip(dev,
+			       INTEL_FRONTBUFFER_OVERLAY(pipe));
+
 	return 0;
 
 out_unpin:
@@ -1028,7 +1039,7 @@ int intel_overlay_put_image(struct drm_d
 	struct drm_intel_overlay_put_image *put_image_rec = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
-	struct drm_mode_object *drmmode_obj;
+	struct drm_crtc *drmmode_crtc;
 	struct intel_crtc *crtc;
 	struct drm_i915_gem_object *new_bo;
 	struct put_image_params *params;
@@ -1057,13 +1068,12 @@ int intel_overlay_put_image(struct drm_d
 	if (!params)
 		return -ENOMEM;
 
-	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
-					   DRM_MODE_OBJECT_CRTC);
-	if (!drmmode_obj) {
+	drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
+	if (!drmmode_crtc) {
 		ret = -ENOENT;
 		goto out_free;
 	}
-	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+	crtc = to_intel_crtc(drmmode_crtc);
 
 	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
 						   put_image_rec->bo_handle));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_panel.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_panel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_panel.c	2014-09-28 17:29:07.000000000 -0400
@@ -398,6 +398,69 @@ intel_panel_detect(struct drm_device *de
 	}
 }
 
+/**
+ * scale - scale values from one range to another
+ *
+ * @source_val: value in range [@source_min..@source_max]
+ *
+ * Return @source_val in range [@source_min..@source_max] scaled to range
+ * [@target_min..@target_max].
+ */
+static uint32_t scale(uint32_t source_val,
+		      uint32_t source_min, uint32_t source_max,
+		      uint32_t target_min, uint32_t target_max)
+{
+	uint64_t target_val;
+
+	WARN_ON(source_min > source_max);
+	WARN_ON(target_min > target_max);
+
+	/* defensive */
+	source_val = clamp(source_val, source_min, source_max);
+
+	/* avoid overflows */
+	target_val = (uint64_t)(source_val - source_min) *
+		(target_max - target_min);
+	do_div(target_val, source_max - source_min);
+	target_val += target_min;
+
+	return target_val;
+}
+
+/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
+static inline u32 scale_user_to_hw(struct intel_connector *connector,
+				   u32 user_level, u32 user_max)
+{
+	struct intel_panel *panel = &connector->panel;
+
+	return scale(user_level, 0, user_max,
+		     panel->backlight.min, panel->backlight.max);
+}
+
+/* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
+ * to [hw_min..hw_max]. */
+static inline u32 clamp_user_to_hw(struct intel_connector *connector,
+				   u32 user_level, u32 user_max)
+{
+	struct intel_panel *panel = &connector->panel;
+	u32 hw_level;
+
+	hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
+	hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
+
+	return hw_level;
+}
+
+/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
+static inline u32 scale_hw_to_user(struct intel_connector *connector,
+				   u32 hw_level, u32 user_max)
+{
+	struct intel_panel *panel = &connector->panel;
+
+	return scale(hw_level, panel->backlight.min, panel->backlight.max,
+		     0, user_max);
+}
+
 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 					  u32 val)
 {
@@ -557,17 +620,16 @@ intel_panel_actually_set_backlight(struc
 	dev_priv->display.set_backlight(connector, level);
 }
 
-/* set backlight brightness to level in range [0..max] */
-void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
-			       u32 max)
+/* set backlight brightness to level in range [0..max], scaling wrt hw min */
+static void intel_panel_set_backlight(struct intel_connector *connector,
+				      u32 user_level, u32 user_max)
 {
 	struct drm_device *dev = connector->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
-	u32 freq;
+	u32 hw_level;
 	unsigned long flags;
-	u64 n;
 
 	if (!panel->backlight.present || pipe == INVALID_PIPE)
 		return;
@@ -576,18 +638,46 @@ void intel_panel_set_backlight(struct in
 
 	WARN_ON(panel->backlight.max == 0);
 
-	/* scale to hardware max, but be careful to not overflow */
-	freq = panel->backlight.max;
-	n = (u64)level * freq;
-	do_div(n, max);
-	level = n;
+	hw_level = scale_user_to_hw(connector, user_level, user_max);
+	panel->backlight.level = hw_level;
+
+	if (panel->backlight.enabled)
+		intel_panel_actually_set_backlight(connector, hw_level);
+
+	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
+
+/* set backlight brightness to level in range [0..max], assuming hw min is
+ * respected.
+ */
+void intel_panel_set_backlight_acpi(struct intel_connector *connector,
+				    u32 user_level, u32 user_max)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_panel *panel = &connector->panel;
+	enum pipe pipe = intel_get_pipe_from_connector(connector);
+	u32 hw_level;
+	unsigned long flags;
+
+	if (!panel->backlight.present || pipe == INVALID_PIPE)
+		return;
+
+	spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+
+	WARN_ON(panel->backlight.max == 0);
+
+	hw_level = clamp_user_to_hw(connector, user_level, user_max);
+	panel->backlight.level = hw_level;
 
-	panel->backlight.level = level;
 	if (panel->backlight.device)
-		panel->backlight.device->props.brightness = level;
+		panel->backlight.device->props.brightness =
+			scale_hw_to_user(connector,
+					 panel->backlight.level,
+					 panel->backlight.device->props.max_brightness);
 
 	if (panel->backlight.enabled)
-		intel_panel_actually_set_backlight(connector, level);
+		intel_panel_actually_set_backlight(connector, hw_level);
 
 	spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
@@ -711,7 +801,7 @@ static void pch_enable_backlight(struct
 
 	cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
 	if (cpu_ctl2 & BLM_PWM_ENABLE) {
-		WARN(1, "cpu backlight already enabled\n");
+		DRM_DEBUG_KMS("cpu backlight already enabled\n");
 		cpu_ctl2 &= ~BLM_PWM_ENABLE;
 		I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
 	}
@@ -755,7 +845,7 @@ static void i9xx_enable_backlight(struct
 
 	ctl = I915_READ(BLC_PWM_CTL);
 	if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
-		WARN(1, "backlight already enabled\n");
+		DRM_DEBUG_KMS("backlight already enabled\n");
 		I915_WRITE(BLC_PWM_CTL, 0);
 	}
 
@@ -786,7 +876,7 @@ static void i965_enable_backlight(struct
 
 	ctl2 = I915_READ(BLC_PWM_CTL2);
 	if (ctl2 & BLM_PWM_ENABLE) {
-		WARN(1, "backlight already enabled\n");
+		DRM_DEBUG_KMS("backlight already enabled\n");
 		ctl2 &= ~BLM_PWM_ENABLE;
 		I915_WRITE(BLC_PWM_CTL2, ctl2);
 	}
@@ -820,7 +910,7 @@ static void vlv_enable_backlight(struct
 
 	ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
 	if (ctl2 & BLM_PWM_ENABLE) {
-		WARN(1, "backlight already enabled\n");
+		DRM_DEBUG_KMS("backlight already enabled\n");
 		ctl2 &= ~BLM_PWM_ENABLE;
 		I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
 	}
@@ -860,7 +950,9 @@ void intel_panel_enable_backlight(struct
 		panel->backlight.level = panel->backlight.max;
 		if (panel->backlight.device)
 			panel->backlight.device->props.brightness =
-				panel->backlight.level;
+				scale_hw_to_user(connector,
+						 panel->backlight.level,
+						 panel->backlight.device->props.max_brightness);
 	}
 
 	dev_priv->display.enable_backlight(connector);
@@ -889,11 +981,15 @@ static int intel_backlight_device_get_br
 	struct intel_connector *connector = bl_get_data(bd);
 	struct drm_device *dev = connector->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 hw_level;
 	int ret;
 
 	intel_runtime_pm_get(dev_priv);
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	ret = intel_panel_get_backlight(connector);
+
+	hw_level = intel_panel_get_backlight(connector);
+	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
+
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 	intel_runtime_pm_put(dev_priv);
 
@@ -913,12 +1009,19 @@ static int intel_backlight_device_regist
 	if (WARN_ON(panel->backlight.device))
 		return -ENODEV;
 
-	BUG_ON(panel->backlight.max == 0);
+	WARN_ON(panel->backlight.max == 0);
 
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_RAW;
-	props.brightness = panel->backlight.level;
+
+	/*
+	 * Note: Everything should work even if the backlight device max
+	 * presented to the userspace is arbitrarily chosen.
+	 */
 	props.max_brightness = panel->backlight.max;
+	props.brightness = scale_hw_to_user(connector,
+					    panel->backlight.level,
+					    props.max_brightness);
 
 	/*
 	 * Note: using the same name independent of the connector prevents
@@ -964,6 +1067,19 @@ static void intel_backlight_device_unreg
  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
  * appropriately when it's 0. Use VBT and/or sane defaults.
  */
+static u32 get_backlight_min_vbt(struct intel_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_panel *panel = &connector->panel;
+
+	WARN_ON(panel->backlight.max == 0);
+
+	/* vbt value is a coefficient in range [0..255] */
+	return scale(dev_priv->vbt.backlight.min_brightness, 0, 255,
+		     0, panel->backlight.max);
+}
+
 static int bdw_setup_backlight(struct intel_connector *connector)
 {
 	struct drm_device *dev = connector->base.dev;
@@ -979,6 +1095,8 @@ static int bdw_setup_backlight(struct in
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min_vbt(connector);
+
 	val = bdw_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1003,6 +1121,8 @@ static int pch_setup_backlight(struct in
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min_vbt(connector);
+
 	val = pch_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1035,6 +1155,8 @@ static int i9xx_setup_backlight(struct i
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min_vbt(connector);
+
 	val = i9xx_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1062,6 +1184,8 @@ static int i965_setup_backlight(struct i
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min_vbt(connector);
+
 	val = i9xx_get_backlight(connector);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
@@ -1099,6 +1223,8 @@ static int vlv_setup_backlight(struct in
 	if (!panel->backlight.max)
 		return -ENODEV;
 
+	panel->backlight.min = get_backlight_min_vbt(connector);
+
 	val = _vlv_get_backlight(dev, PIPE_A);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_pm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,8 +93,7 @@ static void i8xx_enable_fbc(struct drm_c
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->primary->fb;
-	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int cfb_pitch;
 	int i;
@@ -150,8 +149,7 @@ static void g4x_enable_fbc(struct drm_cr
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->primary->fb;
-	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 dpfc_ctl;
 
@@ -222,16 +220,26 @@ static void ironlake_enable_fbc(struct d
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->primary->fb;
-	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 dpfc_ctl;
 
 	dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane);
 	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+		dev_priv->fbc.threshold++;
+
+	switch (dev_priv->fbc.threshold) {
+	case 4:
+	case 3:
+		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
+		break;
+	case 2:
 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
-	else
+		break;
+	case 1:
 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+		break;
+	}
 	dpfc_ctl |= DPFC_CTL_FENCE_EN;
 	if (IS_GEN5(dev))
 		dpfc_ctl |= obj->fence_reg;
@@ -278,16 +286,27 @@ static void gen7_enable_fbc(struct drm_c
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->primary->fb;
-	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 dpfc_ctl;
 
 	dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane);
 	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+		dev_priv->fbc.threshold++;
+
+	switch (dev_priv->fbc.threshold) {
+	case 4:
+	case 3:
+		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
+		break;
+	case 2:
 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
-	else
+		break;
+	case 1:
 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+		break;
+	}
+
 	dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
 
 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
@@ -462,7 +481,6 @@ void intel_update_fbc(struct drm_device
 	struct drm_crtc *crtc = NULL, *tmp_crtc;
 	struct intel_crtc *intel_crtc;
 	struct drm_framebuffer *fb;
-	struct intel_framebuffer *intel_fb;
 	struct drm_i915_gem_object *obj;
 	const struct drm_display_mode *adjusted_mode;
 	unsigned int max_width, max_height;
@@ -507,8 +525,7 @@ void intel_update_fbc(struct drm_device
 
 	intel_crtc = to_intel_crtc(crtc);
 	fb = crtc->primary->fb;
-	intel_fb = to_intel_framebuffer(fb);
-	obj = intel_fb->obj;
+	obj = intel_fb_obj(fb);
 	adjusted_mode = &intel_crtc->config.adjusted_mode;
 
 	if (i915.enable_fbc < 0) {
@@ -529,7 +546,10 @@ void intel_update_fbc(struct drm_device
 		goto out_disable;
 	}
 
-	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_INFO(dev)->gen >= 8 || IS_HASWELL(dev)) {
+		max_width = 4096;
+		max_height = 4096;
+	} else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
 		max_width = 4096;
 		max_height = 2048;
 	} else {
@@ -563,7 +583,8 @@ void intel_update_fbc(struct drm_device
 	if (in_dbg_master())
 		goto out_disable;
 
-	if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) {
+	if (i915_gem_stolen_setup_compression(dev, obj->base.size,
+					      drm_format_plane_cpp(fb->pixel_format, 0))) {
 		if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL))
 			DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
 		goto out_disable;
@@ -789,12 +810,33 @@ static const struct cxsr_latency *intel_
 	return NULL;
 }
 
-static void pineview_disable_cxsr(struct drm_device *dev)
+void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_device *dev = dev_priv->dev;
+	u32 val;
 
-	/* deactivate cxsr */
-	I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN);
+	if (IS_VALLEYVIEW(dev)) {
+		I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
+	} else if (IS_G4X(dev) || IS_CRESTLINE(dev)) {
+		I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0);
+	} else if (IS_PINEVIEW(dev)) {
+		val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN;
+		val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0;
+		I915_WRITE(DSPFW3, val);
+	} else if (IS_I945G(dev) || IS_I945GM(dev)) {
+		val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
+			       _MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
+		I915_WRITE(FW_BLC_SELF, val);
+	} else if (IS_I915GM(dev)) {
+		val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) :
+			       _MASKED_BIT_DISABLE(INSTPM_SELF_EN);
+		I915_WRITE(INSTPM, val);
+	} else {
+		return;
+	}
+
+	DRM_DEBUG_KMS("memory self-refresh is %s\n",
+		      enable ? "enabled" : "disabled");
 }
 
 /*
@@ -864,95 +906,95 @@ static int i845_get_fifo_size(struct drm
 
 /* Pineview has different values for various configs */
 static const struct intel_watermark_params pineview_display_wm = {
-	PINEVIEW_DISPLAY_FIFO,
-	PINEVIEW_MAX_WM,
-	PINEVIEW_DFT_WM,
-	PINEVIEW_GUARD_WM,
-	PINEVIEW_FIFO_LINE_SIZE
+	.fifo_size = PINEVIEW_DISPLAY_FIFO,
+	.max_wm = PINEVIEW_MAX_WM,
+	.default_wm = PINEVIEW_DFT_WM,
+	.guard_size = PINEVIEW_GUARD_WM,
+	.cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params pineview_display_hplloff_wm = {
-	PINEVIEW_DISPLAY_FIFO,
-	PINEVIEW_MAX_WM,
-	PINEVIEW_DFT_HPLLOFF_WM,
-	PINEVIEW_GUARD_WM,
-	PINEVIEW_FIFO_LINE_SIZE
+	.fifo_size = PINEVIEW_DISPLAY_FIFO,
+	.max_wm = PINEVIEW_MAX_WM,
+	.default_wm = PINEVIEW_DFT_HPLLOFF_WM,
+	.guard_size = PINEVIEW_GUARD_WM,
+	.cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params pineview_cursor_wm = {
-	PINEVIEW_CURSOR_FIFO,
-	PINEVIEW_CURSOR_MAX_WM,
-	PINEVIEW_CURSOR_DFT_WM,
-	PINEVIEW_CURSOR_GUARD_WM,
-	PINEVIEW_FIFO_LINE_SIZE,
+	.fifo_size = PINEVIEW_CURSOR_FIFO,
+	.max_wm = PINEVIEW_CURSOR_MAX_WM,
+	.default_wm = PINEVIEW_CURSOR_DFT_WM,
+	.guard_size = PINEVIEW_CURSOR_GUARD_WM,
+	.cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
-	PINEVIEW_CURSOR_FIFO,
-	PINEVIEW_CURSOR_MAX_WM,
-	PINEVIEW_CURSOR_DFT_WM,
-	PINEVIEW_CURSOR_GUARD_WM,
-	PINEVIEW_FIFO_LINE_SIZE
+	.fifo_size = PINEVIEW_CURSOR_FIFO,
+	.max_wm = PINEVIEW_CURSOR_MAX_WM,
+	.default_wm = PINEVIEW_CURSOR_DFT_WM,
+	.guard_size = PINEVIEW_CURSOR_GUARD_WM,
+	.cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params g4x_wm_info = {
-	G4X_FIFO_SIZE,
-	G4X_MAX_WM,
-	G4X_MAX_WM,
-	2,
-	G4X_FIFO_LINE_SIZE,
+	.fifo_size = G4X_FIFO_SIZE,
+	.max_wm = G4X_MAX_WM,
+	.default_wm = G4X_MAX_WM,
+	.guard_size = 2,
+	.cacheline_size = G4X_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params g4x_cursor_wm_info = {
-	I965_CURSOR_FIFO,
-	I965_CURSOR_MAX_WM,
-	I965_CURSOR_DFT_WM,
-	2,
-	G4X_FIFO_LINE_SIZE,
+	.fifo_size = I965_CURSOR_FIFO,
+	.max_wm = I965_CURSOR_MAX_WM,
+	.default_wm = I965_CURSOR_DFT_WM,
+	.guard_size = 2,
+	.cacheline_size = G4X_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params valleyview_wm_info = {
-	VALLEYVIEW_FIFO_SIZE,
-	VALLEYVIEW_MAX_WM,
-	VALLEYVIEW_MAX_WM,
-	2,
-	G4X_FIFO_LINE_SIZE,
+	.fifo_size = VALLEYVIEW_FIFO_SIZE,
+	.max_wm = VALLEYVIEW_MAX_WM,
+	.default_wm = VALLEYVIEW_MAX_WM,
+	.guard_size = 2,
+	.cacheline_size = G4X_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params valleyview_cursor_wm_info = {
-	I965_CURSOR_FIFO,
-	VALLEYVIEW_CURSOR_MAX_WM,
-	I965_CURSOR_DFT_WM,
-	2,
-	G4X_FIFO_LINE_SIZE,
+	.fifo_size = I965_CURSOR_FIFO,
+	.max_wm = VALLEYVIEW_CURSOR_MAX_WM,
+	.default_wm = I965_CURSOR_DFT_WM,
+	.guard_size = 2,
+	.cacheline_size = G4X_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params i965_cursor_wm_info = {
-	I965_CURSOR_FIFO,
-	I965_CURSOR_MAX_WM,
-	I965_CURSOR_DFT_WM,
-	2,
-	I915_FIFO_LINE_SIZE,
+	.fifo_size = I965_CURSOR_FIFO,
+	.max_wm = I965_CURSOR_MAX_WM,
+	.default_wm = I965_CURSOR_DFT_WM,
+	.guard_size = 2,
+	.cacheline_size = I915_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params i945_wm_info = {
-	I945_FIFO_SIZE,
-	I915_MAX_WM,
-	1,
-	2,
-	I915_FIFO_LINE_SIZE
+	.fifo_size = I945_FIFO_SIZE,
+	.max_wm = I915_MAX_WM,
+	.default_wm = 1,
+	.guard_size = 2,
+	.cacheline_size = I915_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params i915_wm_info = {
-	I915_FIFO_SIZE,
-	I915_MAX_WM,
-	1,
-	2,
-	I915_FIFO_LINE_SIZE
+	.fifo_size = I915_FIFO_SIZE,
+	.max_wm = I915_MAX_WM,
+	.default_wm = 1,
+	.guard_size = 2,
+	.cacheline_size = I915_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params i830_wm_info = {
-	I855GM_FIFO_SIZE,
-	I915_MAX_WM,
-	1,
-	2,
-	I830_FIFO_LINE_SIZE
+	.fifo_size = I855GM_FIFO_SIZE,
+	.max_wm = I915_MAX_WM,
+	.default_wm = 1,
+	.guard_size = 2,
+	.cacheline_size = I830_FIFO_LINE_SIZE,
 };
 static const struct intel_watermark_params i845_wm_info = {
-	I830_FIFO_SIZE,
-	I915_MAX_WM,
-	1,
-	2,
-	I830_FIFO_LINE_SIZE
+	.fifo_size = I830_FIFO_SIZE,
+	.max_wm = I915_MAX_WM,
+	.default_wm = 1,
+	.guard_size = 2,
+	.cacheline_size = I830_FIFO_LINE_SIZE,
 };
 
 /**
@@ -1033,7 +1075,7 @@ static void pineview_update_wm(struct dr
 					 dev_priv->fsb_freq, dev_priv->mem_freq);
 	if (!latency) {
 		DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
-		pineview_disable_cxsr(dev);
+		intel_set_memory_cxsr(dev_priv, false);
 		return;
 	}
 
@@ -1084,13 +1126,9 @@ static void pineview_update_wm(struct dr
 		I915_WRITE(DSPFW3, reg);
 		DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
 
-		/* activate cxsr */
-		I915_WRITE(DSPFW3,
-			   I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN);
-		DRM_DEBUG_KMS("Self-refresh is enabled\n");
+		intel_set_memory_cxsr(dev_priv, true);
 	} else {
-		pineview_disable_cxsr(dev);
-		DRM_DEBUG_KMS("Self-refresh is disabled\n");
+		intel_set_memory_cxsr(dev_priv, false);
 	}
 }
 
@@ -1249,15 +1287,14 @@ static bool vlv_compute_drain_latency(st
 	pixel_size = crtc->primary->fb->bits_per_pixel / 8;	/* BPP */
 
 	entries = (clock / 1000) * pixel_size;
-	*plane_prec_mult = (entries > 256) ?
-		DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
-	*plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) *
-						     pixel_size);
+	*plane_prec_mult = (entries > 128) ?
+		DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
+	*plane_dl = (64 * (*plane_prec_mult) * 4) / entries;
 
 	entries = (clock / 1000) * 4;	/* BPP is always 4 for cursor */
-	*cursor_prec_mult = (entries > 256) ?
-		DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
-	*cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4);
+	*cursor_prec_mult = (entries > 128) ?
+		DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
+	*cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries;
 
 	return true;
 }
@@ -1282,9 +1319,9 @@ static void vlv_update_drain_latency(str
 	if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl,
 				      &cursor_prec_mult, &cursora_dl)) {
 		cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
-			DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16;
+			DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64;
 		planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
-			DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16;
+			DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64;
 
 		I915_WRITE(VLV_DDL1, cursora_prec |
 				(cursora_dl << DDL_CURSORA_SHIFT) |
@@ -1295,9 +1332,9 @@ static void vlv_update_drain_latency(str
 	if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl,
 				      &cursor_prec_mult, &cursorb_dl)) {
 		cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
-			DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16;
+			DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64;
 		planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
-			DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16;
+			DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64;
 
 		I915_WRITE(VLV_DDL2, cursorb_prec |
 				(cursorb_dl << DDL_CURSORB_SHIFT) |
@@ -1316,6 +1353,7 @@ static void valleyview_update_wm(struct
 	int plane_sr, cursor_sr;
 	int ignore_plane_sr, ignore_cursor_sr;
 	unsigned int enabled = 0;
+	bool cxsr_enabled;
 
 	vlv_update_drain_latency(dev);
 
@@ -1342,10 +1380,10 @@ static void valleyview_update_wm(struct
 			     &valleyview_wm_info,
 			     &valleyview_cursor_wm_info,
 			     &ignore_plane_sr, &cursor_sr)) {
-		I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN);
+		cxsr_enabled = true;
 	} else {
-		I915_WRITE(FW_BLC_SELF_VLV,
-			   I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN);
+		cxsr_enabled = false;
+		intel_set_memory_cxsr(dev_priv, false);
 		plane_sr = cursor_sr = 0;
 	}
 
@@ -1365,6 +1403,9 @@ static void valleyview_update_wm(struct
 	I915_WRITE(DSPFW3,
 		   (I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) |
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+	if (cxsr_enabled)
+		intel_set_memory_cxsr(dev_priv, true);
 }
 
 static void g4x_update_wm(struct drm_crtc *crtc)
@@ -1375,6 +1416,7 @@ static void g4x_update_wm(struct drm_crt
 	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,
 			    &g4x_wm_info, latency_ns,
@@ -1394,10 +1436,10 @@ static void g4x_update_wm(struct drm_crt
 			     &g4x_wm_info,
 			     &g4x_cursor_wm_info,
 			     &plane_sr, &cursor_sr)) {
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+		cxsr_enabled = true;
 	} else {
-		I915_WRITE(FW_BLC_SELF,
-			   I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
+		cxsr_enabled = false;
+		intel_set_memory_cxsr(dev_priv, false);
 		plane_sr = cursor_sr = 0;
 	}
 
@@ -1418,6 +1460,9 @@ static void g4x_update_wm(struct drm_crt
 	I915_WRITE(DSPFW3,
 		   (I915_READ(DSPFW3) & ~(DSPFW_HPLL_SR_EN | DSPFW_CURSOR_SR_MASK)) |
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+	if (cxsr_enabled)
+		intel_set_memory_cxsr(dev_priv, true);
 }
 
 static void i965_update_wm(struct drm_crtc *unused_crtc)
@@ -1427,6 +1472,7 @@ static void i965_update_wm(struct drm_cr
 	struct drm_crtc *crtc;
 	int srwm = 1;
 	int cursor_sr = 16;
+	bool cxsr_enabled;
 
 	/* Calc sr entries for one plane configs */
 	crtc = single_enabled_crtc(dev);
@@ -1468,13 +1514,11 @@ static void i965_update_wm(struct drm_cr
 		DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
 			      "cursor %d\n", srwm, cursor_sr);
 
-		if (IS_CRESTLINE(dev))
-			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+		cxsr_enabled = true;
 	} else {
+		cxsr_enabled = false;
 		/* Turn off self refresh if both pipes are enabled */
-		if (IS_CRESTLINE(dev))
-			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-				   & ~FW_BLC_SELF_EN);
+		intel_set_memory_cxsr(dev_priv, false);
 	}
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -1486,6 +1530,9 @@ static void i965_update_wm(struct drm_cr
 	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
 	/* update cursor SR watermark */
 	I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+	if (cxsr_enabled)
+		intel_set_memory_cxsr(dev_priv, true);
 }
 
 static void i9xx_update_wm(struct drm_crtc *unused_crtc)
@@ -1545,12 +1592,12 @@ 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) {
-		struct intel_framebuffer *fb;
+		struct drm_i915_gem_object *obj;
 
-		fb = to_intel_framebuffer(enabled->primary->fb);
+		obj = intel_fb_obj(enabled->primary->fb);
 
 		/* self-refresh seems busted with untiled */
-		if (fb->obj->tiling_mode == I915_TILING_NONE)
+		if (obj->tiling_mode == I915_TILING_NONE)
 			enabled = NULL;
 	}
 
@@ -1560,10 +1607,7 @@ static void i9xx_update_wm(struct drm_cr
 	cwm = 2;
 
 	/* Play safe and disable self-refresh before adjusting watermarks. */
-	if (IS_I945G(dev) || IS_I945GM(dev))
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
-	else if (IS_I915GM(dev))
-		I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_SELF_EN));
+	intel_set_memory_cxsr(dev_priv, false);
 
 	/* Calc sr entries for one plane configs */
 	if (HAS_FW_BLC(dev) && enabled) {
@@ -1609,17 +1653,8 @@ static void i9xx_update_wm(struct drm_cr
 	I915_WRITE(FW_BLC, fwater_lo);
 	I915_WRITE(FW_BLC2, fwater_hi);
 
-	if (HAS_FW_BLC(dev)) {
-		if (enabled) {
-			if (IS_I945G(dev) || IS_I945GM(dev))
-				I915_WRITE(FW_BLC_SELF,
-					   FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
-			else if (IS_I915GM(dev))
-				I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_SELF_EN));
-			DRM_DEBUG_KMS("memory self refresh enabled\n");
-		} else
-			DRM_DEBUG_KMS("memory self refresh disabled\n");
-	}
+	if (enabled)
+		intel_set_memory_cxsr(dev_priv, true);
 }
 
 static void i845_update_wm(struct drm_crtc *unused_crtc)
@@ -2707,10 +2742,11 @@ static void ilk_update_wm(struct drm_crt
 	ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_sprite_wm(struct drm_plane *plane,
-				     struct drm_crtc *crtc,
-				     uint32_t sprite_width, int pixel_size,
-				     bool enabled, bool scaled)
+static void
+ilk_update_sprite_wm(struct drm_plane *plane,
+		     struct drm_crtc *crtc,
+		     uint32_t sprite_width, uint32_t sprite_height,
+		     int pixel_size, bool enabled, bool scaled)
 {
 	struct drm_device *dev = plane->dev;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -2718,6 +2754,7 @@ static void ilk_update_sprite_wm(struct
 	intel_plane->wm.enabled = enabled;
 	intel_plane->wm.scaled = scaled;
 	intel_plane->wm.horiz_pixels = sprite_width;
+	intel_plane->wm.vert_pixels = sprite_width;
 	intel_plane->wm.bytes_per_pixel = pixel_size;
 
 	/*
@@ -2852,13 +2889,16 @@ void intel_update_watermarks(struct drm_
 
 void intel_update_sprite_watermarks(struct drm_plane *plane,
 				    struct drm_crtc *crtc,
-				    uint32_t sprite_width, int pixel_size,
+				    uint32_t sprite_width,
+				    uint32_t sprite_height,
+				    int pixel_size,
 				    bool enabled, bool scaled)
 {
 	struct drm_i915_private *dev_priv = plane->dev->dev_private;
 
 	if (dev_priv->display.update_sprite_wm)
-		dev_priv->display.update_sprite_wm(plane, crtc, sprite_width,
+		dev_priv->display.update_sprite_wm(plane, crtc,
+						   sprite_width, sprite_height,
 						   pixel_size, enabled, scaled);
 }
 
@@ -2993,7 +3033,7 @@ static void ironlake_enable_drps(struct
 		I915_READ(0x112e0);
 	dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies);
 	dev_priv->ips.last_count2 = I915_READ(0x112f4);
-	getrawmonotonic(&dev_priv->ips.last_time2);
+	dev_priv->ips.last_time2 = ktime_get_raw_ns();
 
 	spin_unlock_irq(&mchdev_lock);
 }
@@ -3147,6 +3187,9 @@ static u32 gen6_rps_pm_mask(struct drm_i
 	if (val < dev_priv->rps.max_freq_softlimit)
 		mask |= GEN6_PM_RP_UP_THRESHOLD;
 
+	mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED);
+	mask &= dev_priv->pm_rps_events;
+
 	/* IVB and SNB hard hangs on looping batchbuffer
 	 * if GEN6_PM_UP_EI_EXPIRED is masked.
 	 */
@@ -3250,7 +3293,9 @@ void gen6_rps_idle(struct drm_i915_priva
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
+		else if (IS_VALLEYVIEW(dev))
 			vlv_set_rps_idle(dev_priv);
 		else
 			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
@@ -3348,6 +3393,15 @@ static void gen6_disable_rps(struct drm_
 		gen6_disable_rps_interrupts(dev);
 }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+
+	gen8_disable_rps_interrupts(dev);
+}
+
 static void valleyview_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3365,10 +3419,10 @@ static void intel_print_rc6_info(struct
 		else
 			mode = 0;
 	}
-	DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
-		 (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
-		 (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
-		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+	DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
+		      (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
+		      (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
+		      (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
 static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
@@ -3392,8 +3446,8 @@ static int sanitize_rc6_option(const str
 			mask = INTEL_RC6_ENABLE;
 
 		if ((enable_rc6 & mask) != enable_rc6)
-			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
-				 enable_rc6 & mask, enable_rc6, mask);
+			DRM_DEBUG_KMS("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
+				      enable_rc6 & mask, enable_rc6, mask);
 
 		return enable_rc6 & mask;
 	}
@@ -3419,7 +3473,7 @@ static void gen8_enable_rps_interrupts(s
 
 	spin_lock_irq(&dev_priv->irq_lock);
 	WARN_ON(dev_priv->rps.pm_iir);
-	bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
 	I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
@@ -3430,7 +3484,7 @@ static void gen6_enable_rps_interrupts(s
 
 	spin_lock_irq(&dev_priv->irq_lock);
 	WARN_ON(dev_priv->rps.pm_iir);
-	snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
 	I915_WRITE(GEN6_PMIIR, dev_priv->pm_rps_events);
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
@@ -3483,15 +3537,23 @@ static void gen8_enable_rps(struct drm_d
 	for_each_ring(ring, dev_priv, unused)
 		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 	I915_WRITE(GEN6_RC_SLEEP, 0);
-	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+	if (IS_BROADWELL(dev))
+		I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
+	else
+		I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
 
 	/* 3: Enable RC6 */
 	if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
 		rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
 	intel_print_rc6_info(dev, rc6_mask);
-	I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
-				    GEN6_RC_CTL_EI_MODE(1) |
-				    rc6_mask);
+	if (IS_BROADWELL(dev))
+		I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+				GEN7_RC_CTL_TO_MODE |
+				rc6_mask);
+	else
+		I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+				GEN6_RC_CTL_EI_MODE(1) |
+				rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
 	I915_WRITE(GEN6_RPNSWREQ,
@@ -3727,7 +3789,57 @@ void gen6_update_ring_freq(struct drm_de
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
-int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
+static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv)
+{
+	u32 val, rp0;
+
+	val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
+	rp0 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+
+	return rp0;
+}
+
+static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv)
+{
+	u32 val, rpe;
+
+	val = vlv_punit_read(dev_priv, PUNIT_GPU_DUTYCYCLE_REG);
+	rpe = (val >> PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT) & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK;
+
+	return rpe;
+}
+
+static int cherryview_rps_guar_freq(struct drm_i915_private *dev_priv)
+{
+	u32 val, rp1;
+
+	val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+	rp1 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+
+	return rp1;
+}
+
+static int cherryview_rps_min_freq(struct drm_i915_private *dev_priv)
+{
+	u32 val, rpn;
+
+	val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
+	rpn = (val >> PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT) & PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK;
+	return rpn;
+}
+
+static int valleyview_rps_guar_freq(struct drm_i915_private *dev_priv)
+{
+	u32 val, rp1;
+
+	val = vlv_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE);
+
+	rp1 = (val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK) >> FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT;
+
+	return rp1;
+}
+
+static int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
 {
 	u32 val, rp0;
 
@@ -3752,7 +3864,7 @@ static int valleyview_rps_rpe_freq(struc
 	return rpe;
 }
 
-int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
+static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
 {
 	return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
 }
@@ -3766,6 +3878,35 @@ static void valleyview_check_pctx(struct
 			     dev_priv->vlv_pctx->stolen->start);
 }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr, paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
+		paddr = (dev_priv->mm.stolen_base +
+			 (gtt->stolen_size - pctx_size));
+
+		pctx_paddr = (paddr & (~4095));
+		I915_WRITE(VLV_PCBR, pctx_paddr);
+	}
+}
+
 static void valleyview_setup_pctx(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3840,6 +3981,11 @@ static void valleyview_init_gt_powersave
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
 			 dev_priv->rps.efficient_freq);
 
+	dev_priv->rps.rp1_freq = valleyview_rps_guar_freq(dev_priv);
+	DRM_DEBUG_DRIVER("RP1(Guar Freq) GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq),
+			 dev_priv->rps.rp1_freq);
+
 	dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
@@ -3855,11 +4001,142 @@ static void valleyview_init_gt_powersave
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	cherryview_setup_pctx(dev);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+
+	dev_priv->rps.max_freq = cherryview_rps_max_freq(dev_priv);
+	dev_priv->rps.rp0_freq = dev_priv->rps.max_freq;
+	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq),
+			 dev_priv->rps.max_freq);
+
+	dev_priv->rps.efficient_freq = cherryview_rps_rpe_freq(dev_priv);
+	DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+			 dev_priv->rps.efficient_freq);
+
+	dev_priv->rps.rp1_freq = cherryview_rps_guar_freq(dev_priv);
+	DRM_DEBUG_DRIVER("RP1(Guar) GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq),
+			 dev_priv->rps.rp1_freq);
+
+	dev_priv->rps.min_freq = cherryview_rps_min_freq(dev_priv);
+	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
+			 dev_priv->rps.min_freq);
+
+	/* Preserve min/max settings in case of re-init */
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
+
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
+
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
 static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 {
 	valleyview_cleanup_pctx(dev);
 }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_engine_cs *ring;
+	u32 gtfifodbg, val, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
+	/* 2a: Program RC6 thresholds.*/
+	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_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	I915_WRITE(GEN6_RC_SLEEP, 0);
+
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* For now we assume BIOS is allocating and populating the PCBR  */
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1);
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	/* 4 Program defaults and thresholds for RPS*/
+	I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
+	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
+	I915_WRITE(GEN6_RP_UP_EI, 66000);
+	I915_WRITE(GEN6_RP_DOWN_EI, 350000);
+
+	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+
+	/* WaDisablePwrmtrEvent:chv (pre-production hw) */
+	I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff);
+	I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00);
+
+	/* 5: Enable RPS */
+	I915_WRITE(GEN6_RP_CONTROL,
+		   GEN6_RP_MEDIA_HW_NORMAL_MODE |
+		   GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */
+		   GEN6_RP_ENABLE |
+		   GEN6_RP_UP_BUSY_AVG |
+		   GEN6_RP_DOWN_IDLE_AVG);
+
+	val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+
+	DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
+	DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
+
+	dev_priv->rps.cur_freq = (val >> 8) & 0xff;
+	DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq);
+
+	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+			 dev_priv->rps.efficient_freq);
+
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
+
+	gen8_enable_rps_interrupts(dev);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
 static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3886,6 +4163,7 @@ static void valleyview_enable_rps(struct
 	I915_WRITE(GEN6_RP_DOWN_EI, 350000);
 
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 0xf4240);
 
 	I915_WRITE(GEN6_RP_CONTROL,
 		   GEN6_RP_MEDIA_TURBO |
@@ -3906,9 +4184,11 @@ static void valleyview_enable_rps(struct
 
 	/* allows RC6 residency counter to work */
 	I915_WRITE(VLV_COUNTER_CONTROL,
-		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+		   _MASKED_BIT_ENABLE(VLV_MEDIA_RC0_COUNT_EN |
+				      VLV_RENDER_RC0_COUNT_EN |
 				      VLV_MEDIA_RC6_COUNT_EN |
 				      VLV_RENDER_RC6_COUNT_EN));
+
 	if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
 		rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
 
@@ -4314,18 +4594,16 @@ static u16 pvid_to_extvid(struct drm_i91
 
 static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
-	struct timespec now, diff1;
-	u64 diff;
-	unsigned long diffms;
+	u64 now, diff, diffms;
 	u32 count;
 
 	assert_spin_locked(&mchdev_lock);
 
-	getrawmonotonic(&now);
-	diff1 = timespec_sub(now, dev_priv->ips.last_time2);
+	now = ktime_get_raw_ns();
+	diffms = now - dev_priv->ips.last_time2;
+	do_div(diffms, NSEC_PER_MSEC);
 
 	/* Don't divide by 0 */
-	diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
 	if (!diffms)
 		return;
 
@@ -4668,33 +4946,60 @@ void intel_init_gt_powersave(struct drm_
 {
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_init_gt_powersave(dev);
 }
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_cleanup_gt_powersave(dev);
 }
 
+/**
+ * intel_suspend_gt_powersave - suspend PM work and helper threads
+ * @dev: drm device
+ *
+ * We don't want to disable RC6 or other features here, we just want
+ * to make sure any work we've queued has finished and won't bother
+ * us while we're suspended.
+ */
+void intel_suspend_gt_powersave(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* Interrupts should be disabled already to avoid re-arming. */
+	WARN_ON(intel_irqs_enabled(dev_priv));
+
+	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+	cancel_work_sync(&dev_priv->rps.work);
+
+	/* Force GPU to min freq during suspend */
+	gen6_rps_idle(dev_priv);
+}
+
 void intel_disable_gt_powersave(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* Interrupts should be disabled already to avoid re-arming. */
-	WARN_ON(dev->irq_enabled);
+	WARN_ON(intel_irqs_enabled(dev_priv));
 
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
-		if (cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work))
-			intel_runtime_pm_put(dev_priv);
+	} else if (INTEL_INFO(dev)->gen >= 6) {
+		intel_suspend_gt_powersave(dev);
 
-		cancel_work_sync(&dev_priv->rps.work);
 		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
 			valleyview_disable_rps(dev);
 		else
 			gen6_disable_rps(dev);
@@ -4712,7 +5017,9 @@ static void intel_gen6_powersave_work(st
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
@@ -4737,7 +5044,7 @@ void intel_enable_gt_powersave(struct dr
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
@@ -4920,11 +5227,9 @@ static void gen6_check_mch_setup(struct
 	uint32_t tmp;
 
 	tmp = I915_READ(MCH_SSKPD);
-	if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) {
-		DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp);
-		DRM_INFO("This can cause pipe underruns and display issues.\n");
-		DRM_INFO("Please upgrade your BIOS to fix this.\n");
-	}
+	if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL)
+		DRM_DEBUG_KMS("Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n",
+			      tmp);
 }
 
 static void gen6_init_clock_gating(struct drm_device *dev)
@@ -5110,7 +5415,7 @@ static void gen8_init_clock_gating(struc
 	I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE));
 
 	I915_WRITE(_3D_CHICKEN3,
-		   _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2));
+		   _MASKED_BIT_ENABLE(_3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)));
 
 	I915_WRITE(COMMON_SLICE_CHICKEN2,
 		   _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE));
@@ -5345,10 +5650,6 @@ static void valleyview_init_clock_gating
 	}
 	DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
-	dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv);
-	DRM_DEBUG_DRIVER("Current CD clock rate: %d MHz",
-			 dev_priv->vlv_cdclk_freq);
-
 	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
 	/* WaDisableEarlyCull:vlv */
@@ -5423,6 +5724,35 @@ static void valleyview_init_clock_gating
 static void cherryview_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 val;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	val = vlv_punit_read(dev_priv, CCK_FUSE_REG);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+	switch ((val >> 2) & 0x7) {
+	case 0:
+	case 1:
+			dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_200;
+			dev_priv->mem_freq = 1600;
+			break;
+	case 2:
+			dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_267;
+			dev_priv->mem_freq = 1600;
+			break;
+	case 3:
+			dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_333;
+			dev_priv->mem_freq = 2000;
+			break;
+	case 4:
+			dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_320;
+			dev_priv->mem_freq = 1600;
+			break;
+	case 5:
+			dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_400;
+			dev_priv->mem_freq = 1600;
+			break;
+	}
+	DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
 	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5663,7 +5993,6 @@ bool intel_display_power_enabled(struct
 static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	unsigned long irqflags;
 
 	/*
 	 * After we re-enable the power well, if we touch VGA register 0x3d5
@@ -5679,21 +6008,8 @@ static void hsw_power_well_post_enable(s
 	outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
 	vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
 
-	if (IS_BROADWELL(dev)) {
-		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
-			   dev_priv->de_irq_mask[PIPE_B]);
-		I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
-			   ~dev_priv->de_irq_mask[PIPE_B] |
-			   GEN8_PIPE_VBLANK);
-		I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
-			   dev_priv->de_irq_mask[PIPE_C]);
-		I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
-			   ~dev_priv->de_irq_mask[PIPE_C] |
-			   GEN8_PIPE_VBLANK);
-		POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-	}
+	if (IS_BROADWELL(dev))
+		gen8_irq_power_well_post_enable(dev_priv);
 }
 
 static void hsw_set_power_well(struct drm_i915_private *dev_priv,
@@ -5764,34 +6080,13 @@ static bool i9xx_always_on_power_well_en
 	return true;
 }
 
-void __vlv_set_power_well(struct drm_i915_private *dev_priv,
-			  enum punit_power_well power_well_id, bool enable)
+static void vlv_set_power_well(struct drm_i915_private *dev_priv,
+			       struct i915_power_well *power_well, bool enable)
 {
-	struct drm_device *dev = dev_priv->dev;
+	enum punit_power_well power_well_id = power_well->data;
 	u32 mask;
 	u32 state;
 	u32 ctrl;
-	enum pipe pipe;
-
-	if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
-		if (enable) {
-			/*
-			 * Enable the CRI clock source so we can get at the
-			 * display and the reference clock for VGA
-			 * hotplug / manual detection.
-			 */
-			I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
-				   DPLL_REFA_CLK_ENABLE_VLV |
-				   DPLL_INTEGRATED_CRI_CLK_VLV);
-			udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
-		} else {
-			for_each_pipe(pipe)
-				assert_pll_disabled(dev_priv, pipe);
-			/* Assert common reset */
-			I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) &
-				   ~DPIO_CMNRST);
-		}
-	}
 
 	mask = PUNIT_PWRGT_MASK(power_well_id);
 	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
@@ -5819,28 +6114,6 @@ void __vlv_set_power_well(struct drm_i91
 
 out:
 	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	/*
-	 * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
-	 *  6.	De-assert cmn_reset/side_reset. Same as VLV X0.
-	 *   a.	GUnit 0x2110 bit[0] set to 1 (def 0)
-	 *   b.	The other bits such as sfr settings / modesel may all
-	 *	be set to 0.
-	 *
-	 * This should only be done on init and resume from S3 with
-	 * both PLLs disabled, or we risk losing DPIO and PLL
-	 * synchronization.
-	 */
-	if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC && enable)
-		I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
-}
-
-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;
-
-	__vlv_set_power_well(dev_priv, power_well_id, enable);
 }
 
 static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
@@ -5932,6 +6205,53 @@ static void vlv_display_power_well_disab
 	vlv_set_power_well(dev_priv, power_well, false);
 }
 
+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);
+
+	/*
+	 * Enable the CRI clock source so we can get at the
+	 * display and the reference clock for VGA
+	 * hotplug / manual detection.
+	 */
+	I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+		   DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
+	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
+
+	vlv_set_power_well(dev_priv, power_well, true);
+
+	/*
+	 * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
+	 *  6.	De-assert cmn_reset/side_reset. Same as VLV X0.
+	 *   a.	GUnit 0x2110 bit[0] set to 1 (def 0)
+	 *   b.	The other bits such as sfr settings / modesel may all
+	 *	be set to 0.
+	 *
+	 * This should only be done on init and resume from S3 with
+	 * both PLLs disabled, or we risk losing DPIO and PLL
+	 * synchronization.
+	 */
+	I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
+}
+
+static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
+					    struct i915_power_well *power_well)
+{
+	struct drm_device *dev = dev_priv->dev;
+	enum pipe pipe;
+
+	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+
+	for_each_pipe(pipe)
+		assert_pll_disabled(dev_priv, pipe);
+
+	/* Assert common reset */
+	I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST);
+
+	vlv_set_power_well(dev_priv, power_well, false);
+}
+
 static void check_power_well_state(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
@@ -6081,6 +6401,7 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
 	BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |		\
 	BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |		\
 	BIT(POWER_DOMAIN_PORT_CRT) |			\
+	BIT(POWER_DOMAIN_PLLS) |			\
 	BIT(POWER_DOMAIN_INIT))
 #define HSW_DISPLAY_POWER_DOMAINS (				\
 	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
@@ -6180,6 +6501,13 @@ static const struct i915_power_well_ops
 	.is_enabled = vlv_power_well_enabled,
 };
 
+static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = {
+	.sync_hw = vlv_power_well_sync_hw,
+	.enable = vlv_dpio_cmn_power_well_enable,
+	.disable = vlv_dpio_cmn_power_well_disable,
+	.is_enabled = vlv_power_well_enabled,
+};
+
 static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
 	.sync_hw = vlv_power_well_sync_hw,
 	.enable = vlv_power_well_enable,
@@ -6240,10 +6568,25 @@ static struct i915_power_well vlv_power_
 		.name = "dpio-common",
 		.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
 		.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
-		.ops = &vlv_dpio_power_well_ops,
+		.ops = &vlv_dpio_cmn_power_well_ops,
 	},
 };
 
+static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
+						 enum punit_power_well power_well_id)
+{
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *power_well;
+	int i;
+
+	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+		if (power_well->data == power_well_id)
+			return power_well;
+	}
+
+	return NULL;
+}
+
 #define set_power_wells(power_domains, __power_wells) ({		\
 	(power_domains)->power_wells = (__power_wells);			\
 	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\
@@ -6294,11 +6637,50 @@ static void intel_power_domains_resume(s
 	mutex_unlock(&power_domains->lock);
 }
 
+static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
+{
+	struct i915_power_well *cmn =
+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
+	struct i915_power_well *disp2d =
+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
+
+	/* nothing to do if common lane is already off */
+	if (!cmn->ops->is_enabled(dev_priv, cmn))
+		return;
+
+	/* If the display might be already active skip this */
+	if (disp2d->ops->is_enabled(dev_priv, disp2d) &&
+	    I915_READ(DPIO_CTL) & DPIO_CMNRST)
+		return;
+
+	DRM_DEBUG_KMS("toggling display PHY side reset\n");
+
+	/* cmnlane needs DPLL registers */
+	disp2d->ops->enable(dev_priv, disp2d);
+
+	/*
+	 * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
+	 * Need to assert and de-assert PHY SB reset by gating the
+	 * common lane power, then un-gating it.
+	 * Simply ungating isn't enough to reset the PHY enough to get
+	 * ports and lanes running.
+	 */
+	cmn->ops->disable(dev_priv, cmn);
+}
+
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
 	power_domains->initializing = true;
+
+	if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+		mutex_lock(&power_domains->lock);
+		vlv_cmnlane_wa(dev_priv);
+		mutex_unlock(&power_domains->lock);
+	}
+
 	/* For now, we need the power well to be always enabled. */
 	intel_display_set_init_power(dev_priv, true);
 	intel_power_domains_resume(dev_priv);
@@ -6471,7 +6853,7 @@ void intel_init_pm(struct drm_device *de
 				 (dev_priv->is_ddr3 == 1) ? "3" : "2",
 				 dev_priv->fsb_freq, dev_priv->mem_freq);
 			/* Disable CxSR and never update its watermark again */
-			pineview_disable_cxsr(dev);
+			intel_set_memory_cxsr(dev_priv, false);
 			dev_priv->display.update_wm = NULL;
 		} else
 			dev_priv->display.update_wm = pineview_update_wm;
@@ -6554,7 +6936,7 @@ int sandybridge_pcode_write(struct drm_i
 	return 0;
 }
 
-int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
 	int div;
 
@@ -6576,7 +6958,7 @@ int vlv_gpu_freq(struct drm_i915_private
 	return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div);
 }
 
-int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
 	int mul;
 
@@ -6598,6 +6980,80 @@ int vlv_freq_opcode(struct drm_i915_priv
 	return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6;
 }
 
+static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+{
+	int div, freq;
+
+	switch (dev_priv->rps.cz_freq) {
+	case 200:
+		div = 5;
+		break;
+	case 267:
+		div = 6;
+		break;
+	case 320:
+	case 333:
+	case 400:
+		div = 8;
+		break;
+	default:
+		return -1;
+	}
+
+	freq = (DIV_ROUND_CLOSEST((dev_priv->rps.cz_freq * val), 2 * div) / 2);
+
+	return freq;
+}
+
+static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+{
+	int mul, opcode;
+
+	switch (dev_priv->rps.cz_freq) {
+	case 200:
+		mul = 5;
+		break;
+	case 267:
+		mul = 6;
+		break;
+	case 320:
+	case 333:
+	case 400:
+		mul = 8;
+		break;
+	default:
+		return -1;
+	}
+
+	opcode = (DIV_ROUND_CLOSEST((val * 2 * mul), dev_priv->rps.cz_freq) * 2);
+
+	return opcode;
+}
+
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+{
+	int ret = -1;
+
+	if (IS_CHERRYVIEW(dev_priv->dev))
+		ret = chv_gpu_freq(dev_priv, val);
+	else if (IS_VALLEYVIEW(dev_priv->dev))
+		ret = byt_gpu_freq(dev_priv, val);
+
+	return ret;
+}
+
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+{
+	int ret = -1;
+
+	if (IS_CHERRYVIEW(dev_priv->dev))
+		ret = chv_freq_opcode(dev_priv, val);
+	else if (IS_VALLEYVIEW(dev_priv->dev))
+		ret = byt_freq_opcode(dev_priv, val);
+
+	return ret;
+}
+
 void intel_pm_setup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6608,5 +7064,5 @@ void intel_pm_setup(struct drm_device *d
 			  intel_gen6_powersave_work);
 
 	dev_priv->pm.suspended = false;
-	dev_priv->pm.irqs_disabled = false;
+	dev_priv->pm._irqs_disabled = false;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen6.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen6.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen6.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@ static const u32 gen6_null_state_relocs[
 	0x0000002c,
 	0x000001e0,
 	0x000001e4,
+	-1,
 };
 
 static const u32 gen6_null_state_batch[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen7.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen7.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen7.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ static const u32 gen7_null_state_relocs[
 	0x00000010,
 	0x00000018,
 	0x000001ec,
+	-1,
 };
 
 static const u32 gen7_null_state_batch[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen8.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen8.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate_gen8.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate_gen8.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@ static const u32 gen8_null_state_relocs[
 	0x00000050,
 	0x00000060,
 	0x000003ec,
+	-1,
 };
 
 static const u32 gen8_null_state_batch[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_renderstate.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_renderstate.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,6 @@
 
 struct intel_renderstate_rodata {
 	const u32 *reloc;
-	const u32 reloc_items;
 	const u32 *batch;
 	const u32 batch_items;
 };
@@ -40,7 +39,6 @@ extern const struct intel_renderstate_ro
 #define RO_RENDERSTATE(_g)						\
 	const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
 		.reloc = gen ## _g ## _null_state_relocs,		\
-		.reloc_items = sizeof(gen ## _g ## _null_state_relocs)/4, \
 		.batch = gen ## _g ## _null_state_batch,		\
 		.batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,9 +48,8 @@ static inline int __ring_space(int head,
 	return space;
 }
 
-static inline int ring_space(struct intel_engine_cs *ring)
+static inline int ring_space(struct intel_ringbuffer *ringbuf)
 {
-	struct intel_ringbuffer *ringbuf = ring->buffer;
 	return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size);
 }
 
@@ -381,6 +380,27 @@ gen7_render_ring_flush(struct intel_engi
 }
 
 static int
+gen8_emit_pipe_control(struct intel_engine_cs *ring,
+		       u32 flags, u32 scratch_addr)
+{
+	int ret;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
+	intel_ring_emit(ring, flags);
+	intel_ring_emit(ring, scratch_addr);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int
 gen8_render_ring_flush(struct intel_engine_cs *ring,
 		       u32 invalidate_domains, u32 flush_domains)
 {
@@ -403,22 +423,17 @@ gen8_render_ring_flush(struct intel_engi
 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
 		flags |= PIPE_CONTROL_QW_WRITE;
 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
-	}
-
-	ret = intel_ring_begin(ring, 6);
-	if (ret)
-		return ret;
-
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-	intel_ring_emit(ring, flags);
-	intel_ring_emit(ring, scratch_addr);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_advance(ring);
 
-	return 0;
+		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
+		ret = gen8_emit_pipe_control(ring,
+					     PIPE_CONTROL_CS_STALL |
+					     PIPE_CONTROL_STALL_AT_SCOREBOARD,
+					     0);
+		if (ret)
+			return ret;
+	}
 
+	return gen8_emit_pipe_control(ring, flags, scratch_addr);
 }
 
 static void ring_write_tail(struct intel_engine_cs *ring,
@@ -517,6 +532,9 @@ static int init_ring_common(struct intel
 	else
 		ring_setup_phys_status_page(ring);
 
+	/* Enforce ordering by reading HEAD register back */
+	I915_READ_HEAD(ring);
+
 	/* Initialize the ring. This must happen _after_ we've cleared the ring
 	 * registers with the above sequence (the readback of the HEAD registers
 	 * also enforces ordering), otherwise the hw might lose the new ring
@@ -545,7 +563,7 @@ static int init_ring_common(struct intel
 	else {
 		ringbuf->head = I915_READ_HEAD(ring);
 		ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
-		ringbuf->space = ring_space(ring);
+		ringbuf->space = ring_space(ringbuf);
 		ringbuf->last_retired_head = -1;
 	}
 
@@ -604,6 +622,8 @@ static int init_render_ring(struct intel
 	struct drm_device *dev = ring->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret = init_ring_common(ring);
+	if (ret)
+		return ret;
 
 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
 	if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7)
@@ -658,6 +678,13 @@ static int init_render_ring(struct intel
 static void render_ring_cleanup(struct intel_engine_cs *ring)
 {
 	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->semaphore_obj) {
+		i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
+		drm_gem_object_unreference(&dev_priv->semaphore_obj->base);
+		dev_priv->semaphore_obj = NULL;
+	}
 
 	if (ring->scratch.obj == NULL)
 		return;
@@ -671,29 +698,96 @@ static void render_ring_cleanup(struct i
 	ring->scratch.obj = NULL;
 }
 
+static int gen8_rcs_signal(struct intel_engine_cs *signaller,
+			   unsigned int num_dwords)
+{
+#define MBOX_UPDATE_DWORDS 8
+	struct drm_device *dev = signaller->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_engine_cs *waiter;
+	int i, ret, num_rings;
+
+	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
+#undef MBOX_UPDATE_DWORDS
+
+	ret = intel_ring_begin(signaller, num_dwords);
+	if (ret)
+		return ret;
+
+	for_each_ring(waiter, dev_priv, i) {
+		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
+			continue;
+
+		intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6));
+		intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB |
+					   PIPE_CONTROL_QW_WRITE |
+					   PIPE_CONTROL_FLUSH_ENABLE);
+		intel_ring_emit(signaller, lower_32_bits(gtt_offset));
+		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
+		intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
+		intel_ring_emit(signaller, 0);
+		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
+					   MI_SEMAPHORE_TARGET(waiter->id));
+		intel_ring_emit(signaller, 0);
+	}
+
+	return 0;
+}
+
+static int gen8_xcs_signal(struct intel_engine_cs *signaller,
+			   unsigned int num_dwords)
+{
+#define MBOX_UPDATE_DWORDS 6
+	struct drm_device *dev = signaller->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_engine_cs *waiter;
+	int i, ret, num_rings;
+
+	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
+#undef MBOX_UPDATE_DWORDS
+
+	ret = intel_ring_begin(signaller, num_dwords);
+	if (ret)
+		return ret;
+
+	for_each_ring(waiter, dev_priv, i) {
+		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
+			continue;
+
+		intel_ring_emit(signaller, (MI_FLUSH_DW + 1) |
+					   MI_FLUSH_DW_OP_STOREDW);
+		intel_ring_emit(signaller, lower_32_bits(gtt_offset) |
+					   MI_FLUSH_DW_USE_GTT);
+		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
+		intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
+		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
+					   MI_SEMAPHORE_TARGET(waiter->id));
+		intel_ring_emit(signaller, 0);
+	}
+
+	return 0;
+}
+
 static int gen6_signal(struct intel_engine_cs *signaller,
 		       unsigned int num_dwords)
 {
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *useless;
-	int i, ret;
+	int i, ret, num_rings;
 
-	/* NB: In order to be able to do semaphore MBOX updates for varying
-	 * number of rings, it's easiest if we round up each individual update
-	 * to a multiple of 2 (since ring updates must always be a multiple of
-	 * 2) even though the actual update only requires 3 dwords.
-	 */
-#define MBOX_UPDATE_DWORDS 4
-	if (i915_semaphore_is_enabled(dev))
-		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
-	else
-		return intel_ring_begin(signaller, num_dwords);
+#define MBOX_UPDATE_DWORDS 3
+	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
+#undef MBOX_UPDATE_DWORDS
 
 	ret = intel_ring_begin(signaller, num_dwords);
 	if (ret)
 		return ret;
-#undef MBOX_UPDATE_DWORDS
 
 	for_each_ring(useless, dev_priv, i) {
 		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
@@ -701,15 +795,13 @@ static int gen6_signal(struct intel_engi
 			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
 			intel_ring_emit(signaller, mbox_reg);
 			intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
-			intel_ring_emit(signaller, MI_NOOP);
-		} else {
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
 		}
 	}
 
+	/* If num_dwords was rounded, make sure the tail pointer is correct */
+	if (num_rings % 2 == 0)
+		intel_ring_emit(signaller, MI_NOOP);
+
 	return 0;
 }
 
@@ -727,7 +819,11 @@ gen6_add_request(struct intel_engine_cs
 {
 	int ret;
 
-	ret = ring->semaphore.signal(ring, 4);
+	if (ring->semaphore.signal)
+		ret = ring->semaphore.signal(ring, 4);
+	else
+		ret = intel_ring_begin(ring, 4);
+
 	if (ret)
 		return ret;
 
@@ -754,6 +850,32 @@ static inline bool i915_gem_has_seqno_wr
  * @signaller - ring which has, or will signal
  * @seqno - seqno which the waiter will block on
  */
+
+static int
+gen8_ring_sync(struct intel_engine_cs *waiter,
+	       struct intel_engine_cs *signaller,
+	       u32 seqno)
+{
+	struct drm_i915_private *dev_priv = waiter->dev->dev_private;
+	int ret;
+
+	ret = intel_ring_begin(waiter, 4);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
+				MI_SEMAPHORE_GLOBAL_GTT |
+				MI_SEMAPHORE_POLL |
+				MI_SEMAPHORE_SAD_GTE_SDD);
+	intel_ring_emit(waiter, seqno);
+	intel_ring_emit(waiter,
+			lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+	intel_ring_emit(waiter,
+			upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+	intel_ring_advance(waiter);
+	return 0;
+}
+
 static int
 gen6_ring_sync(struct intel_engine_cs *waiter,
 	       struct intel_engine_cs *signaller,
@@ -901,7 +1023,7 @@ gen5_ring_get_irq(struct intel_engine_cs
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (ring->irq_refcount++ == 0)
-		ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
 	return true;
@@ -916,7 +1038,7 @@ gen5_ring_put_irq(struct intel_engine_cs
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (--ring->irq_refcount == 0)
-		ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
@@ -1109,7 +1231,7 @@ gen6_ring_get_irq(struct intel_engine_cs
 					 GT_PARITY_ERROR(dev)));
 		else
 			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-		ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1129,7 +1251,7 @@ gen6_ring_put_irq(struct intel_engine_cs
 			I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
 		else
 			I915_WRITE_IMR(ring, ~0);
-		ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1147,7 +1269,7 @@ hsw_vebox_get_irq(struct intel_engine_cs
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (ring->irq_refcount++ == 0) {
 		I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-		snb_enable_pm_irq(dev_priv, ring->irq_enable_mask);
+		gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1167,7 +1289,7 @@ hsw_vebox_put_irq(struct intel_engine_cs
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (--ring->irq_refcount == 0) {
 		I915_WRITE_IMR(ring, ~0);
-		snb_disable_pm_irq(dev_priv, ring->irq_enable_mask);
+		gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1241,54 +1363,66 @@ i965_dispatch_execbuffer(struct intel_en
 
 /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
 #define I830_BATCH_LIMIT (256*1024)
+#define I830_TLB_ENTRIES (2)
+#define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
 static int
 i830_dispatch_execbuffer(struct intel_engine_cs *ring,
 				u64 offset, u32 len,
 				unsigned flags)
 {
+	u32 cs_offset = ring->scratch.gtt_offset;
 	int ret;
 
-	if (flags & I915_DISPATCH_PINNED) {
-		ret = intel_ring_begin(ring, 4);
-		if (ret)
-			return ret;
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
 
-		intel_ring_emit(ring, MI_BATCH_BUFFER);
-		intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
-		intel_ring_emit(ring, offset + len - 8);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_advance(ring);
-	} else {
-		u32 cs_offset = ring->scratch.gtt_offset;
+	/* Evict the invalid PTE TLBs */
+	intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
+	intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
+	intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
+	intel_ring_emit(ring, cs_offset);
+	intel_ring_emit(ring, 0xdeadbeef);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
 
+	if ((flags & I915_DISPATCH_PINNED) == 0) {
 		if (len > I830_BATCH_LIMIT)
 			return -ENOSPC;
 
-		ret = intel_ring_begin(ring, 9+3);
+		ret = intel_ring_begin(ring, 6 + 2);
 		if (ret)
 			return ret;
-		/* Blit the batch (which has now all relocs applied) to the stable batch
-		 * scratch bo area (so that the CS never stumbles over its tlb
-		 * invalidation bug) ... */
-		intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD |
-				XY_SRC_COPY_BLT_WRITE_ALPHA |
-				XY_SRC_COPY_BLT_WRITE_RGB);
-		intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096);
-		intel_ring_emit(ring, 0);
-		intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024);
+
+		/* Blit the batch (which has now all relocs applied) to the
+		 * stable batch scratch bo area (so that the CS never
+		 * stumbles over its tlb invalidation bug) ...
+		 */
+		intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
+		intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
+		intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
 		intel_ring_emit(ring, cs_offset);
-		intel_ring_emit(ring, 0);
 		intel_ring_emit(ring, 4096);
 		intel_ring_emit(ring, offset);
+
 		intel_ring_emit(ring, MI_FLUSH);
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_advance(ring);
 
 		/* ... and execute it. */
-		intel_ring_emit(ring, MI_BATCH_BUFFER);
-		intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
-		intel_ring_emit(ring, cs_offset + len - 8);
-		intel_ring_advance(ring);
+		offset = cs_offset;
 	}
 
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, MI_BATCH_BUFFER);
+	intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
+	intel_ring_emit(ring, offset + len - 8);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
 	return 0;
 }
 
@@ -1329,6 +1463,7 @@ static int init_status_page(struct intel
 	struct drm_i915_gem_object *obj;
 
 	if ((obj = ring->status_page.obj) == NULL) {
+		unsigned flags;
 		int ret;
 
 		obj = i915_gem_alloc_object(ring->dev, 4096);
@@ -1341,7 +1476,20 @@ static int init_status_page(struct intel
 		if (ret)
 			goto err_unref;
 
-		ret = i915_gem_obj_ggtt_pin(obj, 4096, 0);
+		flags = 0;
+		if (!HAS_LLC(ring->dev))
+			/* On g33, we cannot place HWS above 256MiB, so
+			 * restrict its pinning to the low mappable arena.
+			 * Though this restriction is not documented for
+			 * gen4, gen5, or byt, they also behave similarly
+			 * and hang if the HWS is placed at the top of the
+			 * GTT. To generalise, it appears that all !llc
+			 * platforms have issues with us placing the HWS
+			 * above the mappable region (even though we never
+			 * actualy map it).
+			 */
+			flags |= PIN_MAPPABLE;
+		ret = i915_gem_obj_ggtt_pin(obj, 4096, flags);
 		if (ret) {
 err_unref:
 			drm_gem_object_unreference(&obj->base);
@@ -1378,15 +1526,25 @@ static int init_phys_status_page(struct
 	return 0;
 }
 
-static int allocate_ring_buffer(struct intel_engine_cs *ring)
+static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
+{
+	if (!ringbuf->obj)
+		return;
+
+	iounmap(ringbuf->virtual_start);
+	i915_gem_object_ggtt_unpin(ringbuf->obj);
+	drm_gem_object_unreference(&ringbuf->obj->base);
+	ringbuf->obj = NULL;
+}
+
+static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+				      struct intel_ringbuffer *ringbuf)
 {
-	struct drm_device *dev = ring->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_ringbuffer *ringbuf = ring->buffer;
 	struct drm_i915_gem_object *obj;
 	int ret;
 
-	if (intel_ring_initialized(ring))
+	if (ringbuf->obj)
 		return 0;
 
 	obj = NULL;
@@ -1397,6 +1555,9 @@ static int allocate_ring_buffer(struct i
 	if (obj == NULL)
 		return -ENOMEM;
 
+	/* mark ring buffers as read-only from GPU side by default */
+	obj->gt_ro = 1;
+
 	ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
 	if (ret)
 		goto err_unref;
@@ -1455,7 +1616,7 @@ static int intel_init_ring_buffer(struct
 			goto error;
 	}
 
-	ret = allocate_ring_buffer(ring);
+	ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
 	if (ret) {
 		DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret);
 		goto error;
@@ -1496,11 +1657,7 @@ void intel_cleanup_ring_buffer(struct in
 	intel_stop_ring_buffer(ring);
 	WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
 
-	iounmap(ringbuf->virtual_start);
-
-	i915_gem_object_ggtt_unpin(ringbuf->obj);
-	drm_gem_object_unreference(&ringbuf->obj->base);
-	ringbuf->obj = NULL;
+	intel_destroy_ringbuffer_obj(ringbuf);
 	ring->preallocated_lazy_request = NULL;
 	ring->outstanding_lazy_seqno = 0;
 
@@ -1526,7 +1683,7 @@ static int intel_ring_wait_request(struc
 		ringbuf->head = ringbuf->last_retired_head;
 		ringbuf->last_retired_head = -1;
 
-		ringbuf->space = ring_space(ring);
+		ringbuf->space = ring_space(ringbuf);
 		if (ringbuf->space >= n)
 			return 0;
 	}
@@ -1549,7 +1706,7 @@ static int intel_ring_wait_request(struc
 	ringbuf->head = ringbuf->last_retired_head;
 	ringbuf->last_retired_head = -1;
 
-	ringbuf->space = ring_space(ring);
+	ringbuf->space = ring_space(ringbuf);
 	return 0;
 }
 
@@ -1578,7 +1735,7 @@ static int ring_wait_for_space(struct in
 	trace_i915_ring_wait_begin(ring);
 	do {
 		ringbuf->head = I915_READ_HEAD(ring);
-		ringbuf->space = ring_space(ring);
+		ringbuf->space = ring_space(ringbuf);
 		if (ringbuf->space >= n) {
 			ret = 0;
 			break;
@@ -1630,7 +1787,7 @@ static int intel_wrap_ring_buffer(struct
 		iowrite32(MI_NOOP, virt++);
 
 	ringbuf->tail = 0;
-	ringbuf->space = ring_space(ring);
+	ringbuf->space = ring_space(ringbuf);
 
 	return 0;
 }
@@ -1746,14 +1903,15 @@ int intel_ring_cacheline_align(struct in
 
 void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	BUG_ON(ring->outstanding_lazy_seqno);
 
-	if (INTEL_INFO(ring->dev)->gen >= 6) {
+	if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
 		I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
 		I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
-		if (HAS_VEBOX(ring->dev))
+		if (HAS_VEBOX(dev))
 			I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
 	}
 
@@ -1941,45 +2099,74 @@ int intel_init_render_ring_buffer(struct
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct drm_i915_gem_object *obj;
+	int ret;
 
 	ring->name = "render ring";
 	ring->id = RCS;
 	ring->mmio_base = RENDER_RING_BASE;
 
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (INTEL_INFO(dev)->gen >= 8) {
+		if (i915_semaphore_is_enabled(dev)) {
+			obj = i915_gem_alloc_object(dev, 4096);
+			if (obj == NULL) {
+				DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
+				i915.semaphores = 0;
+			} else {
+				i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+				ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK);
+				if (ret != 0) {
+					drm_gem_object_unreference(&obj->base);
+					DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
+					i915.semaphores = 0;
+				} else
+					dev_priv->semaphore_obj = obj;
+			}
+		}
+		ring->add_request = gen6_add_request;
+		ring->flush = gen8_render_ring_flush;
+		ring->irq_get = gen8_ring_get_irq;
+		ring->irq_put = gen8_ring_put_irq;
+		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+		ring->get_seqno = gen6_ring_get_seqno;
+		ring->set_seqno = ring_set_seqno;
+		if (i915_semaphore_is_enabled(dev)) {
+			WARN_ON(!dev_priv->semaphore_obj);
+			ring->semaphore.sync_to = gen8_ring_sync;
+			ring->semaphore.signal = gen8_rcs_signal;
+			GEN8_RING_SEMAPHORE_INIT;
+		}
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		ring->add_request = gen6_add_request;
 		ring->flush = gen7_render_ring_flush;
 		if (INTEL_INFO(dev)->gen == 6)
 			ring->flush = gen6_render_ring_flush;
-		if (INTEL_INFO(dev)->gen >= 8) {
-			ring->flush = gen8_render_ring_flush;
-			ring->irq_get = gen8_ring_get_irq;
-			ring->irq_put = gen8_ring_put_irq;
-		} else {
-			ring->irq_get = gen6_ring_get_irq;
-			ring->irq_put = gen6_ring_put_irq;
-		}
+		ring->irq_get = gen6_ring_get_irq;
+		ring->irq_put = gen6_ring_put_irq;
 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between RCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and RCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between RCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between VCS2 and RCS later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else if (IS_GEN5(dev)) {
 		ring->add_request = pc_render_add_request;
 		ring->flush = gen4_render_ring_flush;
@@ -2007,6 +2194,7 @@ int intel_init_render_ring_buffer(struct
 		ring->irq_enable_mask = I915_USER_INTERRUPT;
 	}
 	ring->write_tail = ring_write_tail;
+
 	if (IS_HASWELL(dev))
 		ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
 	else if (IS_GEN8(dev))
@@ -2024,10 +2212,7 @@ int intel_init_render_ring_buffer(struct
 
 	/* Workaround batchbuffer to combat CS tlb bug. */
 	if (HAS_BROKEN_CS_TLB(dev)) {
-		struct drm_i915_gem_object *obj;
-		int ret;
-
-		obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT);
+		obj = i915_gem_alloc_object(dev, I830_WA_SIZE);
 		if (obj == NULL) {
 			DRM_ERROR("Failed to allocate batch bo\n");
 			return -ENOMEM;
@@ -2157,31 +2342,32 @@ int intel_init_bsd_ring_buffer(struct dr
 			ring->irq_put = gen8_ring_put_irq;
 			ring->dispatch_execbuffer =
 				gen8_ring_dispatch_execbuffer;
+			if (i915_semaphore_is_enabled(dev)) {
+				ring->semaphore.sync_to = gen8_ring_sync;
+				ring->semaphore.signal = gen8_xcs_signal;
+				GEN8_RING_SEMAPHORE_INIT;
+			}
 		} else {
 			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
 			ring->irq_get = gen6_ring_get_irq;
 			ring->irq_put = gen6_ring_put_irq;
 			ring->dispatch_execbuffer =
 				gen6_ring_dispatch_execbuffer;
+			if (i915_semaphore_is_enabled(dev)) {
+				ring->semaphore.sync_to = gen6_ring_sync;
+				ring->semaphore.signal = gen6_signal;
+				ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+				ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+				ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+				ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+				ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+				ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+				ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			}
 		}
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between VCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and VCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 	} else {
 		ring->mmio_base = BSD_RING_BASE;
 		ring->flush = bsd_ring_flush;
@@ -2218,7 +2404,7 @@ int intel_init_bsd2_ring_buffer(struct d
 		return -EINVAL;
 	}
 
-	ring->name = "bds2_ring";
+	ring->name = "bsd2 ring";
 	ring->id = VCS2;
 
 	ring->write_tail = ring_write_tail;
@@ -2233,25 +2419,11 @@ int intel_init_bsd2_ring_buffer(struct d
 	ring->irq_put = gen8_ring_put_irq;
 	ring->dispatch_execbuffer =
 			gen8_ring_dispatch_execbuffer;
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	/*
-	 * The current semaphore is only applied on the pre-gen8. And there
-	 * is no bsd2 ring on the pre-gen8. So now the semaphore_register
-	 * between VCS2 and other ring is initialized as invalid.
-	 * Gen8 will initialize the sema between VCS2 and other ring later.
-	 */
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
-
+	if (i915_semaphore_is_enabled(dev)) {
+		ring->semaphore.sync_to = gen8_ring_sync;
+		ring->semaphore.signal = gen8_xcs_signal;
+		GEN8_RING_SEMAPHORE_INIT;
+	}
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
@@ -2277,30 +2449,38 @@ int intel_init_blt_ring_buffer(struct dr
 		ring->irq_get = gen8_ring_get_irq;
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen8_ring_sync;
+			ring->semaphore.signal = gen8_xcs_signal;
+			GEN8_RING_SEMAPHORE_INIT;
+		}
 	} else {
 		ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
 		ring->irq_get = gen6_ring_get_irq;
 		ring->irq_put = gen6_ring_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.sync_to = gen6_ring_sync;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between BCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between BCS and VCS2 later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	/*
-	 * The current semaphore is only applied on pre-gen8 platform. And
-	 * there is no VCS2 ring on the pre-gen8 platform. So the semaphore
-	 * between BCS and VCS2 is initialized as INVALID.
-	 * Gen8 will initialize the sema between BCS and VCS2 later.
-	 */
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
@@ -2327,24 +2507,31 @@ int intel_init_vebox_ring_buffer(struct
 		ring->irq_get = gen8_ring_get_irq;
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen8_ring_sync;
+			ring->semaphore.signal = gen8_xcs_signal;
+			GEN8_RING_SEMAPHORE_INIT;
+		}
 	} else {
 		ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
 		ring->irq_get = hsw_vebox_get_irq;
 		ring->irq_put = hsw_vebox_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,10 +40,37 @@ struct  intel_hw_status_page {
 #define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base))
 #define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val)
 
+/* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
+ * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
+ */
+#define i915_semaphore_seqno_size sizeof(uint64_t)
+#define GEN8_SIGNAL_OFFSET(__ring, to)			     \
+	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+	((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) +	\
+	(i915_semaphore_seqno_size * (to)))
+
+#define GEN8_WAIT_OFFSET(__ring, from)			     \
+	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+	((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
+	(i915_semaphore_seqno_size * (__ring)->id))
+
+#define GEN8_RING_SEMAPHORE_INIT do { \
+	if (!dev_priv->semaphore_obj) { \
+		break; \
+	} \
+	ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \
+	ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \
+	ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \
+	ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \
+	ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \
+	ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \
+	} while(0)
+
 enum intel_ring_hangcheck_action {
 	HANGCHECK_IDLE = 0,
 	HANGCHECK_WAIT,
 	HANGCHECK_ACTIVE,
+	HANGCHECK_ACTIVE_LOOP,
 	HANGCHECK_KICK,
 	HANGCHECK_HUNG,
 };
@@ -52,6 +79,7 @@ enum intel_ring_hangcheck_action {
 
 struct intel_ring_hangcheck {
 	u64 acthd;
+	u64 max_acthd;
 	u32 seqno;
 	int score;
 	enum intel_ring_hangcheck_action action;
@@ -127,15 +155,55 @@ struct  intel_engine_cs {
 #define I915_DISPATCH_PINNED 0x2
 	void		(*cleanup)(struct intel_engine_cs *ring);
 
+	/* GEN8 signal/wait table - never trust comments!
+	 *	  signal to	signal to    signal to   signal to      signal to
+	 *	    RCS		   VCS          BCS        VECS		 VCS2
+	 *      --------------------------------------------------------------------
+	 *  RCS | NOP (0x00) | VCS (0x08) | BCS (0x10) | VECS (0x18) | VCS2 (0x20) |
+	 *	|-------------------------------------------------------------------
+	 *  VCS | RCS (0x28) | NOP (0x30) | BCS (0x38) | VECS (0x40) | VCS2 (0x48) |
+	 *	|-------------------------------------------------------------------
+	 *  BCS | RCS (0x50) | VCS (0x58) | NOP (0x60) | VECS (0x68) | VCS2 (0x70) |
+	 *	|-------------------------------------------------------------------
+	 * VECS | RCS (0x78) | VCS (0x80) | BCS (0x88) |  NOP (0x90) | VCS2 (0x98) |
+	 *	|-------------------------------------------------------------------
+	 * VCS2 | RCS (0xa0) | VCS (0xa8) | BCS (0xb0) | VECS (0xb8) | NOP  (0xc0) |
+	 *	|-------------------------------------------------------------------
+	 *
+	 * Generalization:
+	 *  f(x, y) := (x->id * NUM_RINGS * seqno_size) + (seqno_size * y->id)
+	 *  ie. transpose of g(x, y)
+	 *
+	 *	 sync from	sync from    sync from    sync from	sync from
+	 *	    RCS		   VCS          BCS        VECS		 VCS2
+	 *      --------------------------------------------------------------------
+	 *  RCS | NOP (0x00) | VCS (0x28) | BCS (0x50) | VECS (0x78) | VCS2 (0xa0) |
+	 *	|-------------------------------------------------------------------
+	 *  VCS | RCS (0x08) | NOP (0x30) | BCS (0x58) | VECS (0x80) | VCS2 (0xa8) |
+	 *	|-------------------------------------------------------------------
+	 *  BCS | RCS (0x10) | VCS (0x38) | NOP (0x60) | VECS (0x88) | VCS2 (0xb0) |
+	 *	|-------------------------------------------------------------------
+	 * VECS | RCS (0x18) | VCS (0x40) | BCS (0x68) |  NOP (0x90) | VCS2 (0xb8) |
+	 *	|-------------------------------------------------------------------
+	 * VCS2 | RCS (0x20) | VCS (0x48) | BCS (0x70) | VECS (0x98) |  NOP (0xc0) |
+	 *	|-------------------------------------------------------------------
+	 *
+	 * Generalization:
+	 *  g(x, y) := (y->id * NUM_RINGS * seqno_size) + (seqno_size * x->id)
+	 *  ie. transpose of f(x, y)
+	 */
 	struct {
 		u32	sync_seqno[I915_NUM_RINGS-1];
 
-		struct {
-			/* our mbox written by others */
-			u32		wait[I915_NUM_RINGS];
-			/* mboxes this ring signals to */
-			u32		signal[I915_NUM_RINGS];
-		} mbox;
+		union {
+			struct {
+				/* our mbox written by others */
+				u32		wait[I915_NUM_RINGS];
+				/* mboxes this ring signals to */
+				u32		signal[I915_NUM_RINGS];
+			} mbox;
+			u64		signal_ggtt[I915_NUM_RINGS];
+		};
 
 		/* AKA wait() */
 		int	(*sync_to)(struct intel_engine_cs *ring,
@@ -238,9 +306,11 @@ intel_ring_sync_index(struct intel_engin
 	int idx;
 
 	/*
-	 * cs -> 0 = vcs, 1 = bcs
-	 * vcs -> 0 = bcs, 1 = cs,
-	 * bcs -> 0 = cs, 1 = vcs.
+	 * 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 - ring) - 1;
@@ -318,9 +388,9 @@ int intel_init_vebox_ring_buffer(struct
 u64 intel_ring_get_active_head(struct intel_engine_cs *ring);
 void intel_ring_setup_status_page(struct intel_engine_cs *ring);
 
-static inline u32 intel_ring_get_tail(struct intel_engine_cs *ring)
+static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf)
 {
-	return ring->buffer->tail;
+	return ringbuf->tail;
 }
 
 static inline u32 intel_ring_get_seqno(struct intel_engine_cs *ring)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2014-09-28 17:29:07.000000000 -0400
@@ -2433,7 +2433,7 @@ intel_sdvo_connector_init(struct intel_s
 	connector->base.unregister = intel_sdvo_connector_unregister;
 
 	intel_connector_attach_encoder(&connector->base, &encoder->base);
-	ret = drm_sysfs_connector_add(drm_connector);
+	ret = drm_connector_register(drm_connector);
 	if (ret < 0)
 		goto err1;
 
@@ -2446,7 +2446,7 @@ intel_sdvo_connector_init(struct intel_s
 	return 0;
 
 err2:
-	drm_sysfs_connector_remove(drm_connector);
+	drm_connector_unregister(drm_connector);
 err1:
 	drm_connector_cleanup(drm_connector);
 
@@ -2559,7 +2559,7 @@ intel_sdvo_tv_init(struct intel_sdvo *in
 	return true;
 
 err:
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	intel_sdvo_destroy(connector);
 	return false;
 }
@@ -2638,7 +2638,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *
 	return true;
 
 err:
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	intel_sdvo_destroy(connector);
 	return false;
 }
@@ -2711,7 +2711,7 @@ static void intel_sdvo_output_cleanup(st
 	list_for_each_entry_safe(connector, tmp,
 				 &dev->mode_config.connector_list, head) {
 		if (intel_attached_encoder(connector) == &intel_sdvo->base) {
-			drm_sysfs_connector_remove(connector);
+			drm_connector_unregister(connector);
 			intel_sdvo_destroy(connector);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_sprite.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_sprite.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_sprite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_sprite.c	2014-09-28 17:29:07.000000000 -0400
@@ -218,7 +218,8 @@ vlv_update_plane(struct drm_plane *dplan
 
 	sprctl |= SP_ENABLE;
 
-	intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
+				       pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -283,7 +284,7 @@ vlv_disable_plane(struct drm_plane *dpla
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
 
-	intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
+	intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
 }
 
 static int
@@ -406,7 +407,8 @@ ivb_update_plane(struct drm_plane *plane
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
-	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
+				       true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -486,7 +488,7 @@ ivb_disable_plane(struct drm_plane *plan
 	 */
 	intel_wait_for_vblank(dev, pipe);
 
-	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
 }
 
 static int
@@ -606,7 +608,8 @@ ilk_update_plane(struct drm_plane *plane
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 	dvscntr |= DVS_ENABLE;
 
-	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
+				       pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -681,7 +684,7 @@ ilk_disable_plane(struct drm_plane *plan
 	 */
 	intel_wait_for_vblank(dev, pipe);
 
-	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
 }
 
 static void
@@ -819,6 +822,7 @@ intel_update_plane(struct drm_plane *pla
 	struct drm_device *dev = plane->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane = to_intel_plane(plane);
+	enum pipe pipe = intel_crtc->pipe;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct drm_i915_gem_object *old_obj = intel_plane->obj;
@@ -1006,6 +1010,8 @@ intel_update_plane(struct drm_plane *pla
 	 */
 	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
 
+	i915_gem_track_fb(old_obj, obj,
+			  INTEL_FRONTBUFFER_SPRITE(pipe));
 	mutex_unlock(&dev->struct_mutex);
 
 	if (ret)
@@ -1039,6 +1045,8 @@ intel_update_plane(struct drm_plane *pla
 		else
 			intel_plane->disable_plane(plane, crtc);
 
+		intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
+
 		if (!primary_was_enabled && primary_enabled)
 			intel_post_enable_primary(crtc);
 	}
@@ -1068,6 +1076,7 @@ intel_disable_plane(struct drm_plane *pl
 	struct drm_device *dev = plane->dev;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	struct intel_crtc *intel_crtc;
+	enum pipe pipe;
 
 	if (!plane->fb)
 		return 0;
@@ -1076,6 +1085,7 @@ intel_disable_plane(struct drm_plane *pl
 		return -EINVAL;
 
 	intel_crtc = to_intel_crtc(plane->crtc);
+	pipe = intel_crtc->pipe;
 
 	if (intel_crtc->active) {
 		bool primary_was_enabled = intel_crtc->primary_enabled;
@@ -1094,6 +1104,8 @@ intel_disable_plane(struct drm_plane *pl
 
 		mutex_lock(&dev->struct_mutex);
 		intel_unpin_fb_obj(intel_plane->obj);
+		i915_gem_track_fb(intel_plane->obj, NULL,
+				  INTEL_FRONTBUFFER_SPRITE(pipe));
 		mutex_unlock(&dev->struct_mutex);
 
 		intel_plane->obj = NULL;
@@ -1114,7 +1126,6 @@ int intel_sprite_set_colorkey(struct drm
 			      struct drm_file *file_priv)
 {
 	struct drm_intel_sprite_colorkey *set = data;
-	struct drm_mode_object *obj;
 	struct drm_plane *plane;
 	struct intel_plane *intel_plane;
 	int ret = 0;
@@ -1128,13 +1139,12 @@ int intel_sprite_set_colorkey(struct drm
 
 	drm_modeset_lock_all(dev);
 
-	obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
-	if (!obj) {
+	plane = drm_plane_find(dev, set->plane_id);
+	if (!plane) {
 		ret = -ENOENT;
 		goto out_unlock;
 	}
 
-	plane = obj_to_plane(obj);
 	intel_plane = to_intel_plane(plane);
 	ret = intel_plane->update_colorkey(plane, set);
 
@@ -1147,7 +1157,6 @@ int intel_sprite_get_colorkey(struct drm
 			      struct drm_file *file_priv)
 {
 	struct drm_intel_sprite_colorkey *get = data;
-	struct drm_mode_object *obj;
 	struct drm_plane *plane;
 	struct intel_plane *intel_plane;
 	int ret = 0;
@@ -1157,13 +1166,12 @@ int intel_sprite_get_colorkey(struct drm
 
 	drm_modeset_lock_all(dev);
 
-	obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
-	if (!obj) {
+	plane = drm_plane_find(dev, get->plane_id);
+	if (!plane) {
 		ret = -ENOENT;
 		goto out_unlock;
 	}
 
-	plane = obj_to_plane(obj);
 	intel_plane = to_intel_plane(plane);
 	intel_plane->get_colorkey(plane, get);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_tv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_tv.c	2014-09-28 17:29:07.000000000 -0400
@@ -854,6 +854,10 @@ intel_enable_tv(struct intel_encoder *en
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	/* Prevents vblank waits from timing out in intel_tv_detect_type() */
+	intel_wait_for_vblank(encoder->base.dev,
+			      to_intel_crtc(encoder->base.crtc)->pipe);
+
 	I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 }
 
@@ -1311,6 +1315,7 @@ intel_tv_detect(struct drm_connector *co
 {
 	struct drm_display_mode mode;
 	struct intel_tv *intel_tv = intel_attached_tv(connector);
+	enum drm_connector_status status;
 	int type;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
@@ -1323,16 +1328,24 @@ intel_tv_detect(struct drm_connector *co
 		struct intel_load_detect_pipe tmp;
 		struct drm_modeset_acquire_ctx ctx;
 
+		drm_modeset_acquire_init(&ctx, 0);
+
 		if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
 			type = intel_tv_detect_type(intel_tv, connector);
-			intel_release_load_detect_pipe(connector, &tmp, &ctx);
+			intel_release_load_detect_pipe(connector, &tmp);
+			status = type < 0 ?
+				connector_status_disconnected :
+				connector_status_connected;
 		} else
-			return connector_status_unknown;
+			status = connector_status_unknown;
+
+		drm_modeset_drop_locks(&ctx);
+		drm_modeset_acquire_fini(&ctx);
 	} else
 		return connector->status;
 
-	if (type < 0)
-		return connector_status_disconnected;
+	if (status != connector_status_connected)
+		return status;
 
 	intel_tv->type = type;
 	intel_tv_find_better_format(connector);
@@ -1680,5 +1693,5 @@ intel_tv_init(struct drm_device *dev)
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.tv_bottom_margin_property,
 				   intel_tv->margin[TV_MARGIN_BOTTOM]);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_uncore.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_uncore.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/intel_uncore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/intel_uncore.c	2014-09-28 17:29:07.000000000 -0400
@@ -231,8 +231,8 @@ static void __vlv_force_wake_get(struct
 	}
 
 	/* WaRsForcewakeWaitTC0:vlv */
-	__gen6_gt_wait_for_thread_c0(dev_priv);
-
+	if (!IS_CHERRYVIEW(dev_priv->dev))
+		__gen6_gt_wait_for_thread_c0(dev_priv);
 }
 
 static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
@@ -250,9 +250,10 @@ static void __vlv_force_wake_put(struct
 		__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
 				_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
 
-	/* The below doubles as a POSTING_READ */
-	gen6_gt_check_fifodbg(dev_priv);
-
+	/* something from same cacheline, but !FORCEWAKE_VLV */
+	__raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
+	if (!IS_CHERRYVIEW(dev_priv->dev))
+		gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
@@ -315,7 +316,7 @@ static void gen6_force_wake_timer(unsign
 	intel_runtime_pm_put(dev_priv);
 }
 
-static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
+void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
@@ -357,16 +358,12 @@ static void intel_uncore_forcewake_reset
 			dev_priv->uncore.fifo_count =
 				__raw_i915_read32(dev_priv, GTFIFOCTL) &
 				GT_FIFO_FREE_ENTRIES_MASK;
-	} else {
-		dev_priv->uncore.forcewake_count = 0;
-		dev_priv->uncore.fw_rendercount = 0;
-		dev_priv->uncore.fw_mediacount = 0;
 	}
 
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-void intel_uncore_early_sanitize(struct drm_device *dev)
+void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -389,7 +386,7 @@ void intel_uncore_early_sanitize(struct
 		__raw_i915_write32(dev_priv, GTFIFODBG,
 				   __raw_i915_read32(dev_priv, GTFIFODBG));
 
-	intel_uncore_forcewake_reset(dev, false);
+	intel_uncore_forcewake_reset(dev, restore_forcewake);
 }
 
 void intel_uncore_sanitize(struct drm_device *dev)
@@ -469,16 +466,43 @@ void assert_force_wake_inactive(struct d
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	 ((reg) < 0x40000 && (reg) != FORCEWAKE)
 
+#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
+
 #define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
-	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
-	((reg) >= 0x5000 && (reg) < 0x8000) ||\
-	((reg) >= 0xB000 && (reg) < 0x12000) ||\
-	((reg) >= 0x2E000 && (reg) < 0x30000))
+	(REG_RANGE((reg), 0x2000, 0x4000) || \
+	 REG_RANGE((reg), 0x5000, 0x8000) || \
+	 REG_RANGE((reg), 0xB000, 0x12000) || \
+	 REG_RANGE((reg), 0x2E000, 0x30000))
 
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
-	(((reg) >= 0x12000 && (reg) < 0x14000) ||\
-	((reg) >= 0x22000 && (reg) < 0x24000) ||\
-	((reg) >= 0x30000 && (reg) < 0x40000))
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
+	(REG_RANGE((reg), 0x12000, 0x14000) || \
+	 REG_RANGE((reg), 0x22000, 0x24000) || \
+	 REG_RANGE((reg), 0x30000, 0x40000))
+
+#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
+	(REG_RANGE((reg), 0x2000, 0x4000) || \
+	 REG_RANGE((reg), 0x5000, 0x8000) || \
+	 REG_RANGE((reg), 0x8300, 0x8500) || \
+	 REG_RANGE((reg), 0xB000, 0xC000) || \
+	 REG_RANGE((reg), 0xE000, 0xE800))
+
+#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, 0x40000))
+
+#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), 0xC000, 0xC800) || \
+	 REG_RANGE((reg), 0xF000, 0x10000) || \
+	 REG_RANGE((reg), 0x14000, 0x14400) || \
+	 REG_RANGE((reg), 0x22000, 0x24000))
 
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
@@ -490,20 +514,30 @@ ilk_dummy_write(struct drm_i915_private
 }
 
 static void
-hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
+hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,
+			bool before)
 {
+	const char *op = read ? "reading" : "writing to";
+	const char *when = before ? "before" : "after";
+
+	if (!i915.mmio_debug)
+		return;
+
 	if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
-		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
-			  reg);
+		WARN(1, "Unclaimed register detected %s %s register 0x%x\n",
+		     when, op, reg);
 		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 	}
 }
 
 static void
-hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
+hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)
 {
+	if (i915.mmio_debug)
+		return;
+
 	if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
-		DRM_ERROR("Unclaimed write to %x\n", reg);
+		DRM_ERROR("Unclaimed register detected. Please use the i915.mmio_debug=1 to debug this problem.");
 		__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 	}
 }
@@ -540,6 +574,7 @@ gen5_read##x(struct drm_i915_private *de
 static u##x \
 gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
 	REG_READ_HEADER(x); \
+	hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
 	if (dev_priv->uncore.forcewake_count == 0 && \
 	    NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		dev_priv->uncore.funcs.force_wake_get(dev_priv, \
@@ -550,6 +585,7 @@ gen6_read##x(struct drm_i915_private *de
 	} else { \
 		val = __raw_i915_read##x(dev_priv, reg); \
 	} \
+	hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
 	REG_READ_FOOTER; \
 }
 
@@ -573,7 +609,35 @@ vlv_read##x(struct drm_i915_private *dev
 	REG_READ_FOOTER; \
 }
 
+#define __chv_read(x) \
+static u##x \
+chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+	unsigned fwengine = 0; \
+	REG_READ_HEADER(x); \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_rendercount == 0) \
+			fwengine = FORCEWAKE_RENDER; \
+	} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_mediacount == 0) \
+			fwengine = FORCEWAKE_MEDIA; \
+	} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_rendercount == 0) \
+			fwengine |= FORCEWAKE_RENDER; \
+		if (dev_priv->uncore.fw_mediacount == 0) \
+			fwengine |= FORCEWAKE_MEDIA; \
+	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
+	val = __raw_i915_read##x(dev_priv, reg); \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
+	REG_READ_FOOTER; \
+}
 
+__chv_read(8)
+__chv_read(16)
+__chv_read(32)
+__chv_read(64)
 __vlv_read(8)
 __vlv_read(16)
 __vlv_read(32)
@@ -591,6 +655,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __chv_read
 #undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
@@ -647,12 +712,13 @@ hsw_write##x(struct drm_i915_private *de
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
-	hsw_unclaimed_reg_clear(dev_priv, reg); \
+	hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
 	} \
-	hsw_unclaimed_reg_check(dev_priv, reg); \
+	hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
+	hsw_unclaimed_reg_detect(dev_priv); \
 	REG_WRITE_FOOTER; \
 }
 
@@ -681,6 +747,7 @@ static bool is_gen8_shadowed(struct drm_
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
 	REG_WRITE_HEADER; \
+	hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
 	if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) { \
 		if (dev_priv->uncore.forcewake_count == 0) \
 			dev_priv->uncore.funcs.force_wake_get(dev_priv,	\
@@ -692,9 +759,43 @@ gen8_write##x(struct drm_i915_private *d
 	} else { \
 		__raw_i915_write##x(dev_priv, reg, val); \
 	} \
+	hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
+	hsw_unclaimed_reg_detect(dev_priv); \
 	REG_WRITE_FOOTER; \
 }
 
+#define __chv_write(x) \
+static void \
+chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+	unsigned fwengine = 0; \
+	bool shadowed = is_gen8_shadowed(dev_priv, reg); \
+	REG_WRITE_HEADER; \
+	if (!shadowed) { \
+		if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_rendercount == 0) \
+				fwengine = FORCEWAKE_RENDER; \
+		} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_mediacount == 0) \
+				fwengine = FORCEWAKE_MEDIA; \
+		} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_rendercount == 0) \
+				fwengine |= FORCEWAKE_RENDER; \
+			if (dev_priv->uncore.fw_mediacount == 0) \
+				fwengine |= FORCEWAKE_MEDIA; \
+		} \
+	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
+	__raw_i915_write##x(dev_priv, reg, val); \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
+	REG_WRITE_FOOTER; \
+}
+
+__chv_write(8)
+__chv_write(16)
+__chv_write(32)
+__chv_write(64)
 __gen8_write(8)
 __gen8_write(16)
 __gen8_write(32)
@@ -716,6 +817,7 @@ __gen4_write(16)
 __gen4_write(32)
 __gen4_write(64)
 
+#undef __chv_write
 #undef __gen8_write
 #undef __hsw_write
 #undef __gen6_write
@@ -731,7 +833,7 @@ void intel_uncore_init(struct drm_device
 	setup_timer(&dev_priv->uncore.force_wake_timer,
 		    gen6_force_wake_timer, (unsigned long)dev_priv);
 
-	intel_uncore_early_sanitize(dev);
+	intel_uncore_early_sanitize(dev, false);
 
 	if (IS_VALLEYVIEW(dev)) {
 		dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
@@ -779,14 +881,26 @@ void intel_uncore_init(struct drm_device
 
 	switch (INTEL_INFO(dev)->gen) {
 	default:
-		dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
-		dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
-		dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
-		dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
-		dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-		dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-		dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-		dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		if (IS_CHERRYVIEW(dev)) {
+			dev_priv->uncore.funcs.mmio_writeb  = chv_write8;
+			dev_priv->uncore.funcs.mmio_writew  = chv_write16;
+			dev_priv->uncore.funcs.mmio_writel  = chv_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = chv_write64;
+			dev_priv->uncore.funcs.mmio_readb  = chv_read8;
+			dev_priv->uncore.funcs.mmio_readw  = chv_read16;
+			dev_priv->uncore.funcs.mmio_readl  = chv_read32;
+			dev_priv->uncore.funcs.mmio_readq  = chv_read64;
+
+		} else {
+			dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
+			dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
+			dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
+			dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+			dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+			dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+			dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		}
 		break;
 	case 7:
 	case 6:
@@ -912,7 +1026,7 @@ int i915_get_reset_stats_ioctl(struct dr
 	if (args->flags || args->pad)
 		return -EINVAL;
 
-	if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN))
+	if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1053,18 +1167,16 @@ static int gen6_do_reset(struct drm_devi
 
 int intel_gpu_reset(struct drm_device *dev)
 {
-	switch (INTEL_INFO(dev)->gen) {
-	case 8:
-	case 7:
-	case 6: return gen6_do_reset(dev);
-	case 5: return ironlake_do_reset(dev);
-	case 4:
-		if (IS_G4X(dev))
-			return g4x_do_reset(dev);
-		else
-			return i965_do_reset(dev);
-	default: return -ENODEV;
-	}
+	if (INTEL_INFO(dev)->gen >= 6)
+		return gen6_do_reset(dev);
+	else if (IS_GEN5(dev))
+		return ironlake_do_reset(dev);
+	else if (IS_G4X(dev))
+		return g4x_do_reset(dev);
+	else if (IS_GEN4(dev))
+		return i965_do_reset(dev);
+	else
+		return -ENODEV;
 }
 
 void intel_uncore_check_errors(struct drm_device *dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -69,15 +69,3 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
 	  option changes the default for that module option.
 
 	  If in doubt, say "N".
-
-config DRM_I915_UMS
-	bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
-	depends on DRM_I915 && BROKEN
-	default n
-	help
-	  Choose this option if you still need userspace modesetting.
-
-	  Userspace modesetting is deprecated for quite some time now, so
-	  enable this only if you have ancient versions of the DDX drivers.
-
-	  If in doubt, say "N".
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/i915/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/i915/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/i915/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,7 @@ i915-y += dvo_ch7017.o \
 	  intel_crt.o \
 	  intel_ddi.o \
 	  intel_dp.o \
+	  intel_dp_mst.o \
 	  intel_dsi_cmd.o \
 	  intel_dsi.o \
 	  intel_dsi_pll.o \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -114,6 +114,7 @@ config DRM_RADEON
 	select POWER_SUPPLY
 	select HWMON
 	select BACKLIGHT_CLASS_DEVICE
+	select INTERVAL_TREE
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to
@@ -201,3 +202,5 @@ source "drivers/gpu/drm/msm/Kconfig"
 source "drivers/gpu/drm/tegra/Kconfig"
 
 source "drivers/gpu/drm/panel/Kconfig"
+
+source "drivers/gpu/drm/sti/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -6,8 +6,8 @@ ccflags-y := -Iinclude/drm
 
 drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_context.o drm_dma.o \
-		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
-		drm_lock.o drm_memory.o drm_stub.o drm_vm.o \
+		drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+		drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
 		drm_agpsupport.o drm_scatter.o drm_pci.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
@@ -20,11 +20,12 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 drm-$(CONFIG_PCI) += ati_pcigart.o
 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
+drm-$(CONFIG_OF) += drm_of.o
 
 drm-usb-y   := drm_usb.o
 
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
-		drm_plane_helper.o
+		drm_plane_helper.o drm_dp_mst_topology.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_BOCHS) += bochs/
 obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
+obj-$(CONFIG_DRM_STI) += sti/
 obj-y			+= i2c/
 obj-y			+= panel/
 obj-y			+= bridge/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@ module_param_named(modeset, mgag200_mode
 
 static struct drm_driver driver;
 
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
 	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
 	{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
 	{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -280,7 +280,7 @@ static inline int mgag200_bo_reserve(str
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -272,7 +272,7 @@ static int mga_fbdev_destroy(struct drm_
 	return 0;
 }
 
-static struct drm_fb_helper_funcs mga_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs mga_fb_helper_funcs = {
 	.gamma_set = mga_crtc_fb_gamma_set,
 	.gamma_get = mga_crtc_fb_gamma_get,
 	.fb_probe = mgag200fb_create,
@@ -293,9 +293,10 @@ int mgag200_fbdev_init(struct mga_device
 		return -ENOMEM;
 
 	mdev->mfbdev = mfbdev;
-	mfbdev->helper.funcs = &mga_fb_helper_funcs;
 	spin_lock_init(&mfbdev->dirty_lock);
 
+	drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
+
 	ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
 				 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2014-09-28 17:29:07.000000000 -0400
@@ -1562,19 +1562,9 @@ static struct drm_encoder *mga_connector
 						  *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
 	/* pick the encoder ids */
-	if (enc_id) {
-		obj =
-		    drm_mode_object_find(connector->dev, enc_id,
-					 DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
@@ -1621,7 +1611,7 @@ static struct drm_connector *mga_vga_ini
 
 	drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	mga_connector->i2c = mgag200_i2c_create(dev);
 	if (!mga_connector->i2c)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/e
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  26602 bytes, from 2014-06-25 12:57:16)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -203,6 +203,15 @@ enum a2xx_rb_copy_sample_select {
 	SAMPLE_0123 = 6,
 };
 
+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,
+};
+
 enum adreno_mmu_clnt_beh {
 	BEH_NEVR = 0,
 	BEH_TRAN_RNG = 1,
@@ -890,6 +899,39 @@ static inline uint32_t A2XX_SQ_CONTEXT_M
 #define REG_A2XX_VGT_EVENT_INITIATOR				0x000021f9
 
 #define REG_A2XX_VGT_DRAW_INITIATOR				0x000021fc
+#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK			0x0000003f
+#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT		0
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
+{
+	return ((val) << A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK		0x000000c0
+#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT		6
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+	return ((val) << A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK			0x00000600
+#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT			9
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+	return ((val) << A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK		0x00000800
+#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT		11
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
+{
+	return ((val) << A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_NOT_EOP				0x00001000
+#define A2XX_VGT_DRAW_INITIATOR_SMALL_INDEX			0x00002000
+#define A2XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE	0x00004000
+#define A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK		0xffff0000
+#define A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT		16
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_NUM_INDICES(uint32_t val)
+{
+	return ((val) << A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT) & A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK;
+}
 
 #define REG_A2XX_VGT_IMMED_DATA					0x000021fd
 
@@ -963,7 +1005,7 @@ static inline uint32_t A2XX_RB_BLEND_CON
 }
 #define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK		0x000000e0
 #define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT		5
-static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(enum adreno_rb_blend_opcode val)
+static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(enum a2xx_rb_blend_opcode val)
 {
 	return ((val) << A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK;
 }
@@ -981,7 +1023,7 @@ static inline uint32_t A2XX_RB_BLEND_CON
 }
 #define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK		0x00e00000
 #define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT		21
-static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(enum adreno_rb_blend_opcode val)
+static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(enum a2xx_rb_blend_opcode val)
 {
 	return ((val) << A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -392,13 +392,10 @@ static const unsigned int a3xx_registers
 #ifdef CONFIG_DEBUG_FS
 static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
 {
-	struct drm_device *dev = gpu->dev;
 	int i;
 
 	adreno_show(gpu, m);
 
-	mutex_lock(&dev->struct_mutex);
-
 	gpu->funcs->pm_resume(gpu);
 
 	seq_printf(m, "status:   %08x\n",
@@ -418,8 +415,6 @@ static void a3xx_show(struct msm_gpu *gp
 	}
 
 	gpu->funcs->pm_suspend(gpu);
-
-	mutex_unlock(&dev->struct_mutex);
 }
 #endif
 
@@ -685,6 +680,8 @@ static int a3xx_remove(struct platform_d
 }
 
 static const struct of_device_id dt_match[] = {
+	{ .compatible = "qcom,adreno-3xx" },
+	/* for backwards compat w/ downstream kgsl DT files: */
 	{ .compatible = "qcom,kgsl-3d0" },
 	{}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,11 @@
 #define __A3XX_GPU_H__
 
 #include "adreno_gpu.h"
+
+/* arrg, somehow fb.h is getting pulled in: */
+#undef ROP_COPY
+#undef ROP_XOR
+
 #include "a3xx.xml.h"
 
 struct a3xx_gpu {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/e
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  26602 bytes, from 2014-06-25 12:57:16)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -41,31 +41,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 */
 
 
-enum a3xx_render_mode {
-	RB_RENDERING_PASS = 0,
-	RB_TILING_PASS = 1,
-	RB_RESOLVE_PASS = 2,
-};
-
 enum a3xx_tile_mode {
 	LINEAR = 0,
 	TILE_32X32 = 2,
 };
 
-enum a3xx_threadmode {
-	MULTI = 0,
-	SINGLE = 1,
-};
-
-enum a3xx_instrbuffermode {
-	BUFFER = 1,
-};
-
-enum a3xx_threadsize {
-	TWO_QUADS = 0,
-	FOUR_QUADS = 1,
-};
-
 enum a3xx_state_block_id {
 	HLSQ_BLOCK_ID_TP_TEX = 2,
 	HLSQ_BLOCK_ID_TP_MIPMAP = 3,
@@ -169,6 +149,8 @@ enum a3xx_color_fmt {
 	RB_R8G8B8A8_UNORM = 8,
 	RB_Z16_UNORM = 12,
 	RB_A8_UNORM = 20,
+	RB_R16G16B16A16_FLOAT = 27,
+	RB_R32G32B32A32_FLOAT = 51,
 };
 
 enum a3xx_color_swap {
@@ -178,12 +160,6 @@ enum a3xx_color_swap {
 	XYZW = 3,
 };
 
-enum a3xx_msaa_samples {
-	MSAA_ONE = 0,
-	MSAA_TWO = 1,
-	MSAA_FOUR = 2,
-};
-
 enum a3xx_sp_perfcounter_select {
 	SP_FS_CFLOW_INSTRUCTIONS = 12,
 	SP_FS_FULL_ALU_INSTRUCTIONS = 14,
@@ -191,21 +167,45 @@ enum a3xx_sp_perfcounter_select {
 	SP_ALU_ACTIVE_CYCLES = 29,
 };
 
-enum adreno_rb_copy_control_mode {
-	RB_COPY_RESOLVE = 1,
-	RB_COPY_DEPTH_STENCIL = 5,
+enum a3xx_rop_code {
+	ROP_CLEAR = 0,
+	ROP_NOR = 1,
+	ROP_AND_INVERTED = 2,
+	ROP_COPY_INVERTED = 3,
+	ROP_AND_REVERSE = 4,
+	ROP_INVERT = 5,
+	ROP_XOR = 6,
+	ROP_NAND = 7,
+	ROP_AND = 8,
+	ROP_EQUIV = 9,
+	ROP_NOOP = 10,
+	ROP_OR_INVERTED = 11,
+	ROP_COPY = 12,
+	ROP_OR_REVERSE = 13,
+	ROP_OR = 14,
+	ROP_SET = 15,
+};
+
+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_tex_filter {
 	A3XX_TEX_NEAREST = 0,
 	A3XX_TEX_LINEAR = 1,
+	A3XX_TEX_ANISO = 2,
 };
 
 enum a3xx_tex_clamp {
 	A3XX_TEX_REPEAT = 0,
 	A3XX_TEX_CLAMP_TO_EDGE = 1,
 	A3XX_TEX_MIRROR_REPEAT = 2,
-	A3XX_TEX_CLAMP_NONE = 3,
+	A3XX_TEX_CLAMP_TO_BORDER = 3,
+	A3XX_TEX_MIRROR_CLAMP = 4,
 };
 
 enum a3xx_tex_swiz {
@@ -316,6 +316,7 @@ enum a3xx_tex_type {
 #define REG_A3XX_RBBM_INT_0_STATUS				0x00000064
 
 #define REG_A3XX_RBBM_PERFCTR_CTL				0x00000080
+#define A3XX_RBBM_PERFCTR_CTL_ENABLE				0x00000001
 
 #define REG_A3XX_RBBM_PERFCTR_LOAD_CMD0				0x00000081
 
@@ -549,6 +550,10 @@ static inline uint32_t REG_A3XX_CP_PROTE
 
 #define REG_A3XX_CP_AHB_FAULT					0x0000054d
 
+#define REG_A3XX_SP_GLOBAL_MEM_SIZE				0x00000e22
+
+#define REG_A3XX_SP_GLOBAL_MEM_ADDR				0x00000e23
+
 #define REG_A3XX_GRAS_CL_CLIP_CNTL				0x00002040
 #define A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER			0x00001000
 #define A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE			0x00010000
@@ -556,6 +561,9 @@ static inline uint32_t REG_A3XX_CP_PROTE
 #define A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE		0x00080000
 #define A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE			0x00100000
 #define A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE		0x00200000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZCOORD				0x00800000
+#define A3XX_GRAS_CL_CLIP_CNTL_WCOORD				0x01000000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE			0x02000000
 
 #define REG_A3XX_GRAS_CL_GB_CLIP_ADJ				0x00002044
 #define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK			0x000003ff
@@ -620,8 +628,26 @@ static inline uint32_t A3XX_GRAS_CL_VPOR
 }
 
 #define REG_A3XX_GRAS_SU_POINT_MINMAX				0x00002068
+#define A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK			0x0000ffff
+#define A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT			0
+static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MIN(float val)
+{
+	return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
+}
+#define A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK			0xffff0000
+#define A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT			16
+static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MAX(float val)
+{
+	return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
+}
 
 #define REG_A3XX_GRAS_SU_POINT_SIZE				0x00002069
+#define A3XX_GRAS_SU_POINT_SIZE__MASK				0xffffffff
+#define A3XX_GRAS_SU_POINT_SIZE__SHIFT				0
+static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
+{
+	return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_SIZE__SHIFT) & A3XX_GRAS_SU_POINT_SIZE__MASK;
+}
 
 #define REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE			0x0000206c
 #define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK		0x00ffffff
@@ -743,6 +769,7 @@ static inline uint32_t A3XX_RB_MODE_CONT
 #define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE		0x00010000
 
 #define REG_A3XX_RB_RENDER_CONTROL				0x000020c1
+#define A3XX_RB_RENDER_CONTROL_FACENESS				0x00000008
 #define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK			0x00000ff0
 #define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT			4
 static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
@@ -751,6 +778,10 @@ static inline uint32_t A3XX_RB_RENDER_CO
 }
 #define A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE		0x00001000
 #define A3XX_RB_RENDER_CONTROL_ENABLE_GMEM			0x00002000
+#define A3XX_RB_RENDER_CONTROL_XCOORD				0x00004000
+#define A3XX_RB_RENDER_CONTROL_YCOORD				0x00008000
+#define A3XX_RB_RENDER_CONTROL_ZCOORD				0x00010000
+#define A3XX_RB_RENDER_CONTROL_WCOORD				0x00020000
 #define A3XX_RB_RENDER_CONTROL_ALPHA_TEST			0x00400000
 #define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK		0x07000000
 #define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT		24
@@ -796,7 +827,7 @@ static inline uint32_t REG_A3XX_RB_MRT_C
 #define A3XX_RB_MRT_CONTROL_BLEND2				0x00000020
 #define A3XX_RB_MRT_CONTROL_ROP_CODE__MASK			0x00000f00
 #define A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT			8
-static inline uint32_t A3XX_RB_MRT_CONTROL_ROP_CODE(uint32_t val)
+static inline uint32_t A3XX_RB_MRT_CONTROL_ROP_CODE(enum a3xx_rop_code val)
 {
 	return ((val) << A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT) & A3XX_RB_MRT_CONTROL_ROP_CODE__MASK;
 }
@@ -856,7 +887,7 @@ static inline uint32_t A3XX_RB_MRT_BLEND
 }
 #define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK	0x000000e0
 #define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT	5
-static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum adreno_rb_blend_opcode val)
+static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
 {
 	return ((val) << A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
 }
@@ -874,7 +905,7 @@ static inline uint32_t A3XX_RB_MRT_BLEND
 }
 #define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK	0x00e00000
 #define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT	21
-static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum adreno_rb_blend_opcode val)
+static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
 {
 	return ((val) << A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
 }
@@ -957,17 +988,24 @@ static inline uint32_t A3XX_RB_COPY_CONT
 {
 	return ((val) << A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT) & A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK;
 }
+#define A3XX_RB_COPY_CONTROL_DEPTHCLEAR				0x00000008
 #define A3XX_RB_COPY_CONTROL_MODE__MASK				0x00000070
 #define A3XX_RB_COPY_CONTROL_MODE__SHIFT			4
 static inline uint32_t A3XX_RB_COPY_CONTROL_MODE(enum adreno_rb_copy_control_mode val)
 {
 	return ((val) << A3XX_RB_COPY_CONTROL_MODE__SHIFT) & A3XX_RB_COPY_CONTROL_MODE__MASK;
 }
-#define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK			0xfffffc00
-#define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT			10
+#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_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)
 {
-	return ((val >> 10) << A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
+	return ((val >> 14) << A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
 }
 
 #define REG_A3XX_RB_COPY_DEST_BASE				0x000020ed
@@ -1005,6 +1043,12 @@ static inline uint32_t A3XX_RB_COPY_DEST
 {
 	return ((val) << A3XX_RB_COPY_DEST_INFO_SWAP__SHIFT) & A3XX_RB_COPY_DEST_INFO_SWAP__MASK;
 }
+#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK		0x00000c00
+#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT		10
+static inline uint32_t A3XX_RB_COPY_DEST_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
+{
+	return ((val) << A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT) & A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK;
+}
 #define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK		0x0003c000
 #define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT		14
 static inline uint32_t A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(uint32_t val)
@@ -1019,6 +1063,7 @@ static inline uint32_t A3XX_RB_COPY_DEST
 }
 
 #define REG_A3XX_RB_DEPTH_CONTROL				0x00002100
+#define A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z			0x00000001
 #define A3XX_RB_DEPTH_CONTROL_Z_ENABLE				0x00000002
 #define A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE			0x00000004
 #define A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE			0x00000008
@@ -1044,7 +1089,7 @@ static inline uint32_t A3XX_RB_DEPTH_INF
 #define A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT			11
 static inline uint32_t A3XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
 {
-	return ((val >> 10) << A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
+	return ((val >> 12) << A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
 }
 
 #define REG_A3XX_RB_DEPTH_PITCH					0x00002103
@@ -1172,6 +1217,8 @@ static inline uint32_t A3XX_RB_WINDOW_OF
 }
 
 #define REG_A3XX_RB_SAMPLE_COUNT_CONTROL			0x00002110
+#define A3XX_RB_SAMPLE_COUNT_CONTROL_RESET			0x00000001
+#define A3XX_RB_SAMPLE_COUNT_CONTROL_COPY			0x00000002
 
 #define REG_A3XX_RB_SAMPLE_COUNT_ADDR				0x00002111
 
@@ -1179,7 +1226,23 @@ static inline uint32_t A3XX_RB_WINDOW_OF
 
 #define REG_A3XX_RB_Z_CLAMP_MAX					0x00002115
 
+#define REG_A3XX_VGT_BIN_BASE					0x000021e1
+
+#define REG_A3XX_VGT_BIN_SIZE					0x000021e2
+
 #define REG_A3XX_PC_VSTREAM_CONTROL				0x000021e4
+#define A3XX_PC_VSTREAM_CONTROL_SIZE__MASK			0x003f0000
+#define A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT			16
+static inline uint32_t A3XX_PC_VSTREAM_CONTROL_SIZE(uint32_t val)
+{
+	return ((val) << A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT) & A3XX_PC_VSTREAM_CONTROL_SIZE__MASK;
+}
+#define A3XX_PC_VSTREAM_CONTROL_N__MASK				0x07c00000
+#define A3XX_PC_VSTREAM_CONTROL_N__SHIFT			22
+static inline uint32_t A3XX_PC_VSTREAM_CONTROL_N(uint32_t val)
+{
+	return ((val) << A3XX_PC_VSTREAM_CONTROL_N__SHIFT) & A3XX_PC_VSTREAM_CONTROL_N__MASK;
+}
 
 #define REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL			0x000021ea
 
@@ -1203,6 +1266,7 @@ static inline uint32_t A3XX_PC_PRIM_VTX_
 	return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;
 }
 #define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST		0x02000000
+#define A3XX_PC_PRIM_VTX_CNTL_PSIZE				0x04000000
 
 #define REG_A3XX_PC_RESTART_INDEX				0x000021ed
 
@@ -1232,6 +1296,7 @@ static inline uint32_t A3XX_HLSQ_CONTROL
 }
 #define A3XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE		0x00000100
 #define A3XX_HLSQ_CONTROL_1_REG_RESERVED1			0x00000200
+#define A3XX_HLSQ_CONTROL_1_REG_ZWCOORD				0x02000000
 
 #define REG_A3XX_HLSQ_CONTROL_2_REG				0x00002202
 #define A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK	0xfc000000
@@ -1242,6 +1307,12 @@ static inline uint32_t A3XX_HLSQ_CONTROL
 }
 
 #define REG_A3XX_HLSQ_CONTROL_3_REG				0x00002203
+#define A3XX_HLSQ_CONTROL_3_REG_REGID__MASK			0x000000ff
+#define A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT			0
+static inline uint32_t A3XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
+{
+	return ((val) << A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A3XX_HLSQ_CONTROL_3_REG_REGID__MASK;
+}
 
 #define REG_A3XX_HLSQ_VS_CONTROL_REG				0x00002204
 #define A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK		0x00000fff
@@ -1312,10 +1383,36 @@ static inline uint32_t A3XX_HLSQ_CONST_F
 }
 
 #define REG_A3XX_HLSQ_CL_NDRANGE_0_REG				0x0000220a
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK		0x00000003
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT		0
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM(uint32_t val)
+{
+	return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK		0x00000ffc
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT		2
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0(uint32_t val)
+{
+	return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK		0x003ff000
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT		12
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1(uint32_t val)
+{
+	return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK		0xffc00000
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT		22
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2(uint32_t val)
+{
+	return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK;
+}
 
-#define REG_A3XX_HLSQ_CL_NDRANGE_1_REG				0x0000220b
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK(uint32_t i0) { return 0x0000220b + 0x2*i0; }
 
-#define REG_A3XX_HLSQ_CL_NDRANGE_2_REG				0x0000220c
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_SIZE(uint32_t i0) { return 0x0000220b + 0x2*i0; }
+
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_OFFSET(uint32_t i0) { return 0x0000220c + 0x2*i0; }
 
 #define REG_A3XX_HLSQ_CL_CONTROL_0_REG				0x00002211
 
@@ -1323,7 +1420,9 @@ static inline uint32_t A3XX_HLSQ_CONST_F
 
 #define REG_A3XX_HLSQ_CL_KERNEL_CONST_REG			0x00002214
 
-#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG			0x00002215
+static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP(uint32_t i0) { return 0x00002215 + 0x1*i0; }
+
+static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP_RATIO(uint32_t i0) { return 0x00002215 + 0x1*i0; }
 
 #define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG			0x00002216
 
@@ -1438,6 +1537,12 @@ static inline uint32_t A3XX_VFD_DECODE_I
 {
 	return ((val) << A3XX_VFD_DECODE_INSTR_REGID__SHIFT) & A3XX_VFD_DECODE_INSTR_REGID__MASK;
 }
+#define A3XX_VFD_DECODE_INSTR_SWAP__MASK			0x00c00000
+#define A3XX_VFD_DECODE_INSTR_SWAP__SHIFT			22
+static inline uint32_t A3XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A3XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A3XX_VFD_DECODE_INSTR_SWAP__MASK;
+}
 #define A3XX_VFD_DECODE_INSTR_SHIFTCNT__MASK			0x1f000000
 #define A3XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT			24
 static inline uint32_t A3XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
@@ -1462,12 +1567,13 @@ static inline uint32_t A3XX_VFD_VS_THREA
 }
 
 #define REG_A3XX_VPC_ATTR					0x00002280
-#define A3XX_VPC_ATTR_TOTALATTR__MASK				0x00000fff
+#define A3XX_VPC_ATTR_TOTALATTR__MASK				0x000001ff
 #define A3XX_VPC_ATTR_TOTALATTR__SHIFT				0
 static inline uint32_t A3XX_VPC_ATTR_TOTALATTR(uint32_t val)
 {
 	return ((val) << A3XX_VPC_ATTR_TOTALATTR__SHIFT) & A3XX_VPC_ATTR_TOTALATTR__MASK;
 }
+#define A3XX_VPC_ATTR_PSIZE					0x00000200
 #define A3XX_VPC_ATTR_THRDASSIGN__MASK				0x0ffff000
 #define A3XX_VPC_ATTR_THRDASSIGN__SHIFT				12
 static inline uint32_t A3XX_VPC_ATTR_THRDASSIGN(uint32_t val)
@@ -1522,11 +1628,11 @@ static inline uint32_t A3XX_SP_SP_CTRL_R
 {
 	return ((val) << A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK;
 }
-#define A3XX_SP_SP_CTRL_REG_LOMODE__MASK			0x00c00000
-#define A3XX_SP_SP_CTRL_REG_LOMODE__SHIFT			22
-static inline uint32_t A3XX_SP_SP_CTRL_REG_LOMODE(uint32_t val)
+#define A3XX_SP_SP_CTRL_REG_L0MODE__MASK			0x00c00000
+#define A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT			22
+static inline uint32_t A3XX_SP_SP_CTRL_REG_L0MODE(uint32_t val)
 {
-	return ((val) << A3XX_SP_SP_CTRL_REG_LOMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_LOMODE__MASK;
+	return ((val) << A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT) & A3XX_SP_SP_CTRL_REG_L0MODE__MASK;
 }
 
 #define REG_A3XX_SP_VS_CTRL_REG0				0x000022c4
@@ -1569,6 +1675,7 @@ static inline uint32_t A3XX_SP_VS_CTRL_R
 }
 #define A3XX_SP_VS_CTRL_REG0_SUPERTHREADMODE			0x00200000
 #define A3XX_SP_VS_CTRL_REG0_PIXLODENABLE			0x00400000
+#define A3XX_SP_VS_CTRL_REG0_COMPUTEMODE			0x00800000
 #define A3XX_SP_VS_CTRL_REG0_LENGTH__MASK			0xff000000
 #define A3XX_SP_VS_CTRL_REG0_LENGTH__SHIFT			24
 static inline uint32_t A3XX_SP_VS_CTRL_REG0_LENGTH(uint32_t val)
@@ -1742,6 +1849,7 @@ static inline uint32_t A3XX_SP_FS_CTRL_R
 }
 #define A3XX_SP_FS_CTRL_REG0_SUPERTHREADMODE			0x00200000
 #define A3XX_SP_FS_CTRL_REG0_PIXLODENABLE			0x00400000
+#define A3XX_SP_FS_CTRL_REG0_COMPUTEMODE			0x00800000
 #define A3XX_SP_FS_CTRL_REG0_LENGTH__MASK			0xff000000
 #define A3XX_SP_FS_CTRL_REG0_LENGTH__SHIFT			24
 static inline uint32_t A3XX_SP_FS_CTRL_REG0_LENGTH(uint32_t val)
@@ -1802,6 +1910,13 @@ static inline uint32_t A3XX_SP_FS_OBJ_OF
 #define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1			0x000022e9
 
 #define REG_A3XX_SP_FS_OUTPUT_REG				0x000022ec
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE			0x00000080
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK			0x0000ff00
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT		8
+static inline uint32_t A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
+{
+	return ((val) << A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
+}
 
 static inline uint32_t REG_A3XX_SP_FS_MRT(uint32_t i0) { return 0x000022f0 + 0x1*i0; }
 
@@ -1914,6 +2029,42 @@ static inline uint32_t A3XX_TPL1_TP_FS_T
 
 #define REG_A3XX_VBIF_OUT_AXI_AOOO				0x0000305f
 
+#define REG_A3XX_VBIF_PERF_CNT_EN				0x00003070
+#define A3XX_VBIF_PERF_CNT_EN_CNT0				0x00000001
+#define A3XX_VBIF_PERF_CNT_EN_CNT1				0x00000002
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT0				0x00000004
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT1				0x00000008
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT2				0x00000010
+
+#define REG_A3XX_VBIF_PERF_CNT_CLR				0x00003071
+#define A3XX_VBIF_PERF_CNT_CLR_CNT0				0x00000001
+#define A3XX_VBIF_PERF_CNT_CLR_CNT1				0x00000002
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT0				0x00000004
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT1				0x00000008
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT2				0x00000010
+
+#define REG_A3XX_VBIF_PERF_CNT_SEL				0x00003072
+
+#define REG_A3XX_VBIF_PERF_CNT0_LO				0x00003073
+
+#define REG_A3XX_VBIF_PERF_CNT0_HI				0x00003074
+
+#define REG_A3XX_VBIF_PERF_CNT1_LO				0x00003075
+
+#define REG_A3XX_VBIF_PERF_CNT1_HI				0x00003076
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT0_LO				0x00003077
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT0_HI				0x00003078
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT1_LO				0x00003079
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT1_HI				0x0000307a
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT2_LO				0x0000307b
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT2_HI				0x0000307c
+
 #define REG_A3XX_VSC_BIN_SIZE					0x00000c01
 #define A3XX_VSC_BIN_SIZE_WIDTH__MASK				0x0000001f
 #define A3XX_VSC_BIN_SIZE_WIDTH__SHIFT				0
@@ -2080,6 +2231,8 @@ static inline uint32_t A3XX_UCHE_CACHE_I
 }
 #define A3XX_UCHE_CACHE_INVALIDATE1_REG_ENTIRE_CACHE		0x80000000
 
+#define REG_A3XX_UNKNOWN_0EA6					0x00000ea6
+
 #define REG_A3XX_SP_PERFCOUNTER0_SELECT				0x00000ec4
 
 #define REG_A3XX_SP_PERFCOUNTER1_SELECT				0x00000ec5
@@ -2117,6 +2270,39 @@ static inline uint32_t A3XX_UCHE_CACHE_I
 #define REG_A3XX_VGT_EVENT_INITIATOR				0x000021f9
 
 #define REG_A3XX_VGT_DRAW_INITIATOR				0x000021fc
+#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK			0x0000003f
+#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT		0
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
+{
+	return ((val) << A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK		0x000000c0
+#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT		6
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+	return ((val) << A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK			0x00000600
+#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT			9
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+	return ((val) << A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK		0x00000800
+#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT		11
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
+{
+	return ((val) << A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_NOT_EOP				0x00001000
+#define A3XX_VGT_DRAW_INITIATOR_SMALL_INDEX			0x00002000
+#define A3XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE	0x00004000
+#define A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK		0xffff0000
+#define A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT		16
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_NUM_INDICES(uint32_t val)
+{
+	return ((val) << A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT) & A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK;
+}
 
 #define REG_A3XX_VGT_IMMED_DATA					0x000021fd
 
@@ -2152,6 +2338,12 @@ static inline uint32_t A3XX_TEX_SAMP_0_W
 {
 	return ((val) << A3XX_TEX_SAMP_0_WRAP_R__SHIFT) & A3XX_TEX_SAMP_0_WRAP_R__MASK;
 }
+#define A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK			0x00700000
+#define A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT			20
+static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val)
+{
+	return ((val) << A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT) & A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK;
+}
 #define A3XX_TEX_SAMP_0_UNNORM_COORDS				0x80000000
 
 #define REG_A3XX_TEX_SAMP_1					0x00000001
@@ -2170,6 +2362,7 @@ static inline uint32_t A3XX_TEX_SAMP_1_M
 
 #define REG_A3XX_TEX_CONST_0					0x00000000
 #define A3XX_TEX_CONST_0_TILED					0x00000001
+#define A3XX_TEX_CONST_0_SRGB					0x00000004
 #define A3XX_TEX_CONST_0_SWIZ_X__MASK				0x00000070
 #define A3XX_TEX_CONST_0_SWIZ_X__SHIFT				4
 static inline uint32_t A3XX_TEX_CONST_0_SWIZ_X(enum a3xx_tex_swiz val)
@@ -2206,6 +2399,7 @@ static inline uint32_t A3XX_TEX_CONST_0_
 {
 	return ((val) << A3XX_TEX_CONST_0_FMT__SHIFT) & A3XX_TEX_CONST_0_FMT__MASK;
 }
+#define A3XX_TEX_CONST_0_NOCONVERT				0x20000000
 #define A3XX_TEX_CONST_0_TYPE__MASK				0xc0000000
 #define A3XX_TEX_CONST_0_TYPE__SHIFT				30
 static inline uint32_t A3XX_TEX_CONST_0_TYPE(enum a3xx_tex_type val)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/e
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  26602 bytes, from 2014-06-25 12:57:16)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -87,15 +87,6 @@ enum adreno_rb_blend_factor {
 	FACTOR_SRC_ALPHA_SATURATE = 16,
 };
 
-enum adreno_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,
-};
-
 enum adreno_rb_surface_endian {
 	ENDIAN_NONE = 0,
 	ENDIAN_8IN16 = 1,
@@ -116,6 +107,39 @@ enum adreno_rb_depth_format {
 	DEPTHX_24_8 = 1,
 };
 
+enum adreno_rb_copy_control_mode {
+	RB_COPY_RESOLVE = 1,
+	RB_COPY_CLEAR = 2,
+	RB_COPY_DEPTH_STENCIL = 5,
+};
+
+enum a3xx_render_mode {
+	RB_RENDERING_PASS = 0,
+	RB_TILING_PASS = 1,
+	RB_RESOLVE_PASS = 2,
+	RB_COMPUTE_PASS = 3,
+};
+
+enum a3xx_msaa_samples {
+	MSAA_ONE = 0,
+	MSAA_TWO = 1,
+	MSAA_FOUR = 2,
+};
+
+enum a3xx_threadmode {
+	MULTI = 0,
+	SINGLE = 1,
+};
+
+enum a3xx_instrbuffermode {
+	BUFFER = 1,
+};
+
+enum a3xx_threadsize {
+	TWO_QUADS = 0,
+	FOUR_QUADS = 1,
+};
+
 #define REG_AXXX_CP_RB_BASE					0x000001c0
 
 #define REG_AXXX_CP_RB_CNTL					0x000001c1
@@ -264,6 +288,8 @@ static inline uint32_t AXXX_SCRATCH_UMSK
 #define REG_AXXX_CP_INT_ACK					0x000001f4
 
 #define REG_AXXX_CP_ME_CNTL					0x000001f6
+#define AXXX_CP_ME_CNTL_BUSY					0x20000000
+#define AXXX_CP_ME_CNTL_HALT					0x10000000
 
 #define REG_AXXX_CP_ME_STATUS					0x000001f7
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2014-08-07 04:45:59.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2014-09-28 21:26:40.000000000 -0400
@@ -88,9 +88,17 @@ int adreno_get_param(struct msm_gpu *gpu
 int adreno_hw_init(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	int ret;
 
 	DBG("%s", gpu->name);
 
+	ret = msm_gem_get_iova(gpu->rb->bo, gpu->id, &gpu->rb_iova);
+	if (ret) {
+		gpu->rb_iova = 0;
+		dev_err(gpu->dev->dev, "could not map ringbuffer: %d\n", ret);
+		return ret;
+	}
+
 	/* Setup REG_CP_RB_CNTL: */
 	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
 			/* size is log2(quad-words): */
@@ -359,8 +367,10 @@ int adreno_gpu_init(struct drm_device *d
 			return ret;
 	}
 
+	mutex_lock(&drm->struct_mutex);
 	gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs),
 			MSM_BO_UNCACHED);
+	mutex_unlock(&drm->struct_mutex);
 	if (IS_ERR(gpu->memptrs_bo)) {
 		ret = PTR_ERR(gpu->memptrs_bo);
 		gpu->memptrs_bo = NULL;
@@ -368,13 +378,13 @@ int adreno_gpu_init(struct drm_device *d
 		return ret;
 	}
 
-	gpu->memptrs = msm_gem_vaddr_locked(gpu->memptrs_bo);
+	gpu->memptrs = msm_gem_vaddr(gpu->memptrs_bo);
 	if (!gpu->memptrs) {
 		dev_err(drm->dev, "could not vmap memptrs\n");
 		return -ENOMEM;
 	}
 
-	ret = msm_gem_get_iova_locked(gpu->memptrs_bo, gpu->base.id,
+	ret = msm_gem_get_iova(gpu->memptrs_bo, gpu->base.id,
 			&gpu->memptrs_iova);
 	if (ret) {
 		dev_err(drm->dev, "could not map memptrs: %d\n", ret);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/e
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  26602 bytes, from 2014-06-25 12:57:16)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -105,6 +105,7 @@ enum pc_di_index_size {
 
 enum pc_di_vis_cull_mode {
 	IGNORE_VISIBILITY = 0,
+	USE_VISIBILITY = 1,
 };
 
 enum adreno_pm4_packet_type {
@@ -163,6 +164,11 @@ enum adreno_pm4_type3_packets {
 	CP_SET_BIN = 76,
 	CP_TEST_TWO_MEMS = 113,
 	CP_WAIT_FOR_ME = 19,
+	CP_SET_DRAW_STATE = 67,
+	CP_DRAW_INDX_OFFSET = 56,
+	CP_DRAW_INDIRECT = 40,
+	CP_DRAW_INDX_INDIRECT = 41,
+	CP_DRAW_AUTO = 36,
 	IN_IB_PREFETCH_END = 23,
 	IN_SUBBLK_PREFETCH = 31,
 	IN_INSTR_PREFETCH = 32,
@@ -232,6 +238,211 @@ 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_DRAW_INDX_0					0x00000000
+#define CP_DRAW_INDX_0_VIZ_QUERY__MASK				0xffffffff
+#define CP_DRAW_INDX_0_VIZ_QUERY__SHIFT				0
+static inline uint32_t CP_DRAW_INDX_0_VIZ_QUERY(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_0_VIZ_QUERY__MASK;
+}
+
+#define REG_CP_DRAW_INDX_1					0x00000001
+#define CP_DRAW_INDX_1_PRIM_TYPE__MASK				0x0000003f
+#define CP_DRAW_INDX_1_PRIM_TYPE__SHIFT				0
+static inline uint32_t CP_DRAW_INDX_1_PRIM_TYPE(enum pc_di_primtype val)
+{
+	return ((val) << CP_DRAW_INDX_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_1_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_1_SOURCE_SELECT__MASK			0x000000c0
+#define CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT			6
+static inline uint32_t CP_DRAW_INDX_1_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+	return ((val) << CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_1_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_1_VIS_CULL__MASK				0x00000600
+#define CP_DRAW_INDX_1_VIS_CULL__SHIFT				9
+static inline uint32_t CP_DRAW_INDX_1_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+	return ((val) << CP_DRAW_INDX_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_1_VIS_CULL__MASK;
+}
+#define CP_DRAW_INDX_1_INDEX_SIZE__MASK				0x00000800
+#define CP_DRAW_INDX_1_INDEX_SIZE__SHIFT			11
+static inline uint32_t CP_DRAW_INDX_1_INDEX_SIZE(enum pc_di_index_size val)
+{
+	return ((val) << CP_DRAW_INDX_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_1_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_1_NOT_EOP					0x00001000
+#define CP_DRAW_INDX_1_SMALL_INDEX				0x00002000
+#define CP_DRAW_INDX_1_PRE_DRAW_INITIATOR_ENABLE		0x00004000
+#define CP_DRAW_INDX_1_NUM_INDICES__MASK			0xffff0000
+#define CP_DRAW_INDX_1_NUM_INDICES__SHIFT			16
+static inline uint32_t CP_DRAW_INDX_1_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_1_NUM_INDICES__SHIFT) & CP_DRAW_INDX_1_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2					0x00000002
+#define CP_DRAW_INDX_2_NUM_INDICES__MASK			0xffffffff
+#define CP_DRAW_INDX_2_NUM_INDICES__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_2_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2					0x00000002
+#define CP_DRAW_INDX_2_INDX_BASE__MASK				0xffffffff
+#define CP_DRAW_INDX_2_INDX_BASE__SHIFT				0
+static inline uint32_t CP_DRAW_INDX_2_INDX_BASE(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_INDX_BASE__SHIFT) & CP_DRAW_INDX_2_INDX_BASE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2					0x00000002
+#define CP_DRAW_INDX_2_INDX_SIZE__MASK				0xffffffff
+#define CP_DRAW_INDX_2_INDX_SIZE__SHIFT				0
+static inline uint32_t CP_DRAW_INDX_2_INDX_SIZE(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_INDX_SIZE__SHIFT) & CP_DRAW_INDX_2_INDX_SIZE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_0					0x00000000
+#define CP_DRAW_INDX_2_0_VIZ_QUERY__MASK			0xffffffff
+#define CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_2_0_VIZ_QUERY(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_2_0_VIZ_QUERY__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_1					0x00000001
+#define CP_DRAW_INDX_2_1_PRIM_TYPE__MASK			0x0000003f
+#define CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_2_1_PRIM_TYPE(enum pc_di_primtype val)
+{
+	return ((val) << CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_2_1_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK			0x000000c0
+#define CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT			6
+static inline uint32_t CP_DRAW_INDX_2_1_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+	return ((val) << CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_2_1_VIS_CULL__MASK				0x00000600
+#define CP_DRAW_INDX_2_1_VIS_CULL__SHIFT			9
+static inline uint32_t CP_DRAW_INDX_2_1_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+	return ((val) << CP_DRAW_INDX_2_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_2_1_VIS_CULL__MASK;
+}
+#define CP_DRAW_INDX_2_1_INDEX_SIZE__MASK			0x00000800
+#define CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT			11
+static inline uint32_t CP_DRAW_INDX_2_1_INDEX_SIZE(enum pc_di_index_size val)
+{
+	return ((val) << CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_2_1_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_2_1_NOT_EOP				0x00001000
+#define CP_DRAW_INDX_2_1_SMALL_INDEX				0x00002000
+#define CP_DRAW_INDX_2_1_PRE_DRAW_INITIATOR_ENABLE		0x00004000
+#define CP_DRAW_INDX_2_1_NUM_INDICES__MASK			0xffff0000
+#define CP_DRAW_INDX_2_1_NUM_INDICES__SHIFT			16
+static inline uint32_t CP_DRAW_INDX_2_1_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_1_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_1_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_2					0x00000002
+#define CP_DRAW_INDX_2_2_NUM_INDICES__MASK			0xffffffff
+#define CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_2_2_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_0				0x00000000
+#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK			0x0000003f
+#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_PRIM_TYPE(enum pc_di_primtype val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK		0x000000c0
+#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT		6
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK			0x00000700
+#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			0x00000800
+#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT			11
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum pc_di_index_size val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_NOT_EOP				0x00001000
+#define CP_DRAW_INDX_OFFSET_0_SMALL_INDEX			0x00002000
+#define CP_DRAW_INDX_OFFSET_0_PRE_DRAW_INITIATOR_ENABLE		0x00004000
+#define CP_DRAW_INDX_OFFSET_0_NUM_INDICES__MASK			0xffff0000
+#define CP_DRAW_INDX_OFFSET_0_NUM_INDICES__SHIFT		16
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_NUM_INDICES__SHIFT) & CP_DRAW_INDX_OFFSET_0_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_1				0x00000001
+
+#define REG_CP_DRAW_INDX_OFFSET_2				0x00000002
+#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK			0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT		0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_NUM_INDICES(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_2				0x00000002
+#define CP_DRAW_INDX_OFFSET_2_INDX_BASE__MASK			0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_INDX_BASE__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_INDX_BASE(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_2_INDX_BASE__SHIFT) & CP_DRAW_INDX_OFFSET_2_INDX_BASE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_2				0x00000002
+#define CP_DRAW_INDX_OFFSET_2_INDX_SIZE__MASK			0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_INDX_SIZE__SHIFT			0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_INDX_SIZE(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_2_INDX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_2_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)
+{
+	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)
+{
+	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)
+{
+	return ((val) << CP_SET_DRAW_STATE_1_ADDR__SHIFT) & CP_SET_DRAW_STATE_1_ADDR__MASK;
+}
+
 #define REG_CP_SET_BIN_0					0x00000000
 
 #define REG_CP_SET_BIN_1					0x00000001
@@ -262,5 +473,21 @@ static inline uint32_t CP_SET_BIN_2_Y2(u
 	return ((val) << CP_SET_BIN_2_Y2__SHIFT) & CP_SET_BIN_2_Y2__MASK;
 }
 
+#define REG_CP_SET_BIN_DATA_0					0x00000000
+#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK			0xffffffff
+#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT			0
+static inline uint32_t CP_SET_BIN_DATA_0_BIN_DATA_ADDR(uint32_t val)
+{
+	return ((val) << CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT) & CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK;
+}
+
+#define REG_CP_SET_BIN_DATA_1					0x00000001
+#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK		0xffffffff
+#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT		0
+static inline uint32_t CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS(uint32_t val)
+{
+	return ((val) << CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT) & CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK;
+}
+
 
 #endif /* ADRENO_PM4_XML */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,7 +123,8 @@ struct hdmi *hdmi_init(struct drm_device
 	for (i = 0; i < config->hpd_reg_cnt; i++) {
 		struct regulator *reg;
 
-		reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]);
+		reg = devm_regulator_get_exclusive(&pdev->dev,
+				config->hpd_reg_names[i]);
 		if (IS_ERR(reg)) {
 			ret = PTR_ERR(reg);
 			dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
@@ -138,7 +139,8 @@ struct hdmi *hdmi_init(struct drm_device
 	for (i = 0; i < config->pwr_reg_cnt; i++) {
 		struct regulator *reg;
 
-		reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]);
+		reg = devm_regulator_get_exclusive(&pdev->dev,
+				config->pwr_reg_names[i]);
 		if (IS_ERR(reg)) {
 			ret = PTR_ERR(reg);
 			dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
@@ -256,47 +258,68 @@ static void set_hdmi_pdev(struct drm_dev
 	priv->hdmi_pdev = pdev;
 }
 
-static int hdmi_bind(struct device *dev, struct device *master, void *data)
-{
-	static struct hdmi_platform_config config = {};
 #ifdef CONFIG_OF
-	struct device_node *of_node = dev->of_node;
-
-	int get_gpio(const char *name)
-	{
-		int gpio = of_get_named_gpio(of_node, name, 0);
+static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
+{
+	int gpio = of_get_named_gpio(of_node, name, 0);
+	if (gpio < 0) {
+		char name2[32];
+		snprintf(name2, sizeof(name2), "%s-gpio", name);
+		gpio = of_get_named_gpio(of_node, name2, 0);
 		if (gpio < 0) {
 			dev_err(dev, "failed to get gpio: %s (%d)\n",
 					name, gpio);
 			gpio = -1;
 		}
-		return gpio;
 	}
+	return gpio;
+}
+#endif
 
-	/* TODO actually use DT.. */
-	static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
-	static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
-	static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
-	static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
-	static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+static int hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+	static struct hdmi_platform_config config = {};
+#ifdef CONFIG_OF
+	struct device_node *of_node = dev->of_node;
+
+	if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) {
+		static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
+		static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
+		static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
+		static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
+		static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+		config.phy_init      = hdmi_phy_8x74_init;
+		config.hpd_reg_names = hpd_reg_names;
+		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+		config.pwr_reg_names = pwr_reg_names;
+		config.pwr_reg_cnt   = ARRAY_SIZE(pwr_reg_names);
+		config.hpd_clk_names = hpd_clk_names;
+		config.hpd_freq      = hpd_clk_freq;
+		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
+		config.pwr_clk_names = pwr_clk_names;
+		config.pwr_clk_cnt   = ARRAY_SIZE(pwr_clk_names);
+		config.shared_irq    = true;
+	} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
+		static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
+		static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
+		config.phy_init      = hdmi_phy_8960_init;
+		config.hpd_reg_names = hpd_reg_names;
+		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+		config.hpd_clk_names = hpd_clk_names;
+		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
+	} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8660")) {
+		config.phy_init      = hdmi_phy_8x60_init;
+	} else {
+		dev_err(dev, "unknown phy: %s\n", of_node->name);
+	}
 
-	config.phy_init      = hdmi_phy_8x74_init;
 	config.mmio_name     = "core_physical";
-	config.hpd_reg_names = hpd_reg_names;
-	config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
-	config.pwr_reg_names = pwr_reg_names;
-	config.pwr_reg_cnt   = ARRAY_SIZE(pwr_reg_names);
-	config.hpd_clk_names = hpd_clk_names;
-	config.hpd_freq      = hpd_clk_freq;
-	config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
-	config.pwr_clk_names = pwr_clk_names;
-	config.pwr_clk_cnt   = ARRAY_SIZE(pwr_clk_names);
-	config.ddc_clk_gpio  = get_gpio("qcom,hdmi-tx-ddc-clk");
-	config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
-	config.hpd_gpio      = get_gpio("qcom,hdmi-tx-hpd");
-	config.mux_en_gpio   = get_gpio("qcom,hdmi-tx-mux-en");
-	config.mux_sel_gpio  = get_gpio("qcom,hdmi-tx-mux-sel");
-	config.shared_irq    = true;
+	config.ddc_clk_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk");
+	config.ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data");
+	config.hpd_gpio      = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd");
+	config.mux_en_gpio   = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en");
+	config.mux_sel_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel");
+	config.mux_lpm_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm");
 
 #else
 	static const char *hpd_clk_names[] = {
@@ -373,7 +396,9 @@ static int hdmi_dev_remove(struct platfo
 }
 
 static const struct of_device_id dt_match[] = {
-	{ .compatible = "qcom,hdmi-tx" },
+	{ .compatible = "qcom,hdmi-tx-8074" },
+	{ .compatible = "qcom,hdmi-tx-8960" },
+	{ .compatible = "qcom,hdmi-tx-8660" },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,7 +63,7 @@ static int gpio_config(struct hdmi *hdmi
 			ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
 			if (ret) {
 				dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
-					"HDMI_MUX_SEL", config->mux_en_gpio, ret);
+					"HDMI_MUX_EN", config->mux_en_gpio, ret);
 				goto error4;
 			}
 			gpio_set_value_cansleep(config->mux_en_gpio, 1);
@@ -78,6 +78,19 @@ static int gpio_config(struct hdmi *hdmi
 			}
 			gpio_set_value_cansleep(config->mux_sel_gpio, 0);
 		}
+
+		if (config->mux_lpm_gpio != -1) {
+			ret = gpio_request(config->mux_lpm_gpio,
+					"HDMI_MUX_LPM");
+			if (ret) {
+				dev_err(dev->dev,
+					"'%s'(%d) gpio_request failed: %d\n",
+					"HDMI_MUX_LPM",
+					config->mux_lpm_gpio, ret);
+				goto error6;
+			}
+			gpio_set_value_cansleep(config->mux_lpm_gpio, 1);
+		}
 		DBG("gpio on");
 	} else {
 		gpio_free(config->ddc_clk_gpio);
@@ -93,11 +106,19 @@ static int gpio_config(struct hdmi *hdmi
 			gpio_set_value_cansleep(config->mux_sel_gpio, 1);
 			gpio_free(config->mux_sel_gpio);
 		}
+
+		if (config->mux_lpm_gpio != -1) {
+			gpio_set_value_cansleep(config->mux_lpm_gpio, 0);
+			gpio_free(config->mux_lpm_gpio);
+		}
 		DBG("gpio off");
 	}
 
 	return 0;
 
+error6:
+	if (config->mux_sel_gpio != -1)
+		gpio_free(config->mux_sel_gpio);
 error5:
 	if (config->mux_en_gpio != -1)
 		gpio_free(config->mux_en_gpio);
@@ -306,7 +327,7 @@ static void hdmi_connector_destroy(struc
 
 	hdp_disable(hdmi_connector);
 
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 
 	hdmi_unreference(hdmi_connector->hdmi);
@@ -416,7 +437,7 @@ struct drm_connector *hdmi_connector_ini
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	ret = hpd_enable(hdmi_connector);
 	if (ret) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h	2014-09-28 17:29:07.000000000 -0400
@@ -96,6 +96,7 @@ struct hdmi_platform_config {
 
 	/* gpio's: */
 	int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
+	int mux_lpm_gpio;
 
 	/* older devices had their own irq, mdp5+ it is shared w/ mdp: */
 	bool shared_irq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,14 +15,377 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#endif
+
 #include "hdmi.h"
 
 struct hdmi_phy_8960 {
 	struct hdmi_phy base;
 	struct hdmi *hdmi;
+#ifdef CONFIG_COMMON_CLK
+	struct clk_hw pll_hw;
+	struct clk *pll;
+	unsigned long pixclk;
+#endif
 };
 #define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
 
+#ifdef CONFIG_COMMON_CLK
+#define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
+
+/*
+ * HDMI PLL:
+ *
+ * To get the parent clock setup properly, we need to plug in hdmi pll
+ * configuration into common-clock-framework.
+ */
+
+struct pll_rate {
+	unsigned long rate;
+	struct {
+		uint32_t val;
+		uint32_t reg;
+	} conf[32];
+};
+
+/* NOTE: keep sorted highest freq to lowest: */
+static const struct pll_rate freqtbl[] = {
+	/* 1080p60/1080p50 case */
+	{ 148500000, {
+		{ 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
+		{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+		{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
+		{ 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
+		{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
+		{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
+		{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
+		{ 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
+		{ 0, 0 } }
+	},
+	{ 108000000, {
+		{ 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0, 0 } }
+	},
+	/* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
+	{ 74250000, {
+		{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
+		{ 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0, 0 } }
+	},
+	{ 65000000, {
+		{ 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0, 0 } }
+	},
+	/* 480p60/480i60 */
+	{ 27030000, {
+		{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
+		{ 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+		{ 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
+		{ 0, 0 } }
+	},
+	/* 576p50/576i50 */
+	{ 27000000, {
+		{ 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
+		{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+		{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
+		{ 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
+		{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
+		{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
+		{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
+		{ 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
+		{ 0, 0 } }
+	},
+	/* 640x480p60 */
+	{ 25200000, {
+		{ 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG    },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+		{ 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+		{ 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG  },
+		{ 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+		{ 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B       },
+		{ 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0      },
+		{ 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2      },
+		{ 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4      },
+		{ 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1      },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2      },
+		{ 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3      },
+		{ 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0  },
+		{ 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1  },
+		{ 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2  },
+		{ 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0   },
+		{ 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1   },
+		{ 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3   },
+		{ 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5   },
+		{ 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6   },
+		{ 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7   },
+		{ 0, 0 } }
+	},
+};
+
+static int hdmi_pll_enable(struct clk_hw *hw)
+{
+	struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+	struct hdmi *hdmi = phy_8960->hdmi;
+	int timeout_count, pll_lock_retry = 10;
+	unsigned int val;
+
+	DBG("");
+
+	/* Assert PLL S/W reset */
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
+
+	/* Wait for a short time before de-asserting
+	 * to allow the hardware to complete its job.
+	 * This much of delay should be fine for hardware
+	 * to assert and de-assert.
+	 */
+	udelay(10);
+
+	/* De-assert PLL S/W reset */
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
+
+	val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+	val |= HDMI_8960_PHY_REG12_SW_RESET;
+	/* Assert PHY S/W reset */
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+	val &= ~HDMI_8960_PHY_REG12_SW_RESET;
+	/* Wait for a short time before de-asserting
+	   to allow the hardware to complete its job.
+	   This much of delay should be fine for hardware
+	   to assert and de-assert. */
+	udelay(10);
+	/* De-assert PHY S/W reset */
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2,  0x3f);
+
+	val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+	val |= HDMI_8960_PHY_REG12_PWRDN_B;
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+	/* Wait 10 us for enabling global power for PHY */
+	mb();
+	udelay(10);
+
+	val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
+	val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
+	val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x80);
+
+	timeout_count = 1000;
+	while (--pll_lock_retry > 0) {
+
+		/* are we there yet? */
+		val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_STATUS0);
+		if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
+			break;
+
+		udelay(1);
+
+		if (--timeout_count > 0)
+			continue;
+
+		/*
+		 * PLL has still not locked.
+		 * Do a software reset and try again
+		 * Assert PLL S/W reset first
+		 */
+		hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
+		udelay(10);
+		hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
+
+		/*
+		 * Wait for a short duration for the PLL calibration
+		 * before checking if the PLL gets locked
+		 */
+		udelay(350);
+
+		timeout_count = 1000;
+	}
+
+	return 0;
+}
+
+static void hdmi_pll_disable(struct clk_hw *hw)
+{
+	struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+	struct hdmi *hdmi = phy_8960->hdmi;
+	unsigned int val;
+
+	DBG("");
+
+	val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+	val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+
+	val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
+	val |= HDMI_8960_PHY_REG12_SW_RESET;
+	val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
+	/* Make sure HDMI PHY/PLL are powered down */
+	mb();
+}
+
+static const struct pll_rate *find_rate(unsigned long rate)
+{
+	int i;
+	for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
+		if (rate > freqtbl[i].rate)
+			return &freqtbl[i-1];
+	return &freqtbl[i-1];
+}
+
+static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+	return phy_8960->pixclk;
+}
+
+static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	const struct pll_rate *pll_rate = find_rate(rate);
+	return pll_rate->rate;
+}
+
+static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+	struct hdmi *hdmi = phy_8960->hdmi;
+	const struct pll_rate *pll_rate = find_rate(rate);
+	int i;
+
+	DBG("rate=%lu", rate);
+
+	for (i = 0; pll_rate->conf[i].reg; i++)
+		hdmi_write(hdmi, pll_rate->conf[i].reg, pll_rate->conf[i].val);
+
+	phy_8960->pixclk = rate;
+
+	return 0;
+}
+
+
+static const struct clk_ops hdmi_pll_ops = {
+	.enable = hdmi_pll_enable,
+	.disable = hdmi_pll_disable,
+	.recalc_rate = hdmi_pll_recalc_rate,
+	.round_rate = hdmi_pll_round_rate,
+	.set_rate = hdmi_pll_set_rate,
+};
+
+static const char *hdmi_pll_parents[] = {
+	"pxo",
+};
+
+static struct clk_init_data pll_init = {
+	.name = "hdmi_pll",
+	.ops = &hdmi_pll_ops,
+	.parent_names = hdmi_pll_parents,
+	.num_parents = ARRAY_SIZE(hdmi_pll_parents),
+};
+#endif
+
+/*
+ * HDMI Phy:
+ */
+
 static void hdmi_phy_8960_destroy(struct hdmi_phy *phy)
 {
 	struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
@@ -86,6 +449,9 @@ static void hdmi_phy_8960_powerup(struct
 	struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
 	struct hdmi *hdmi = phy_8960->hdmi;
 
+	DBG("pixclock: %lu", pixclock);
+
+	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x00);
 	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b);
 	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2);
 	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00);
@@ -104,6 +470,8 @@ static void hdmi_phy_8960_powerdown(stru
 	struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
 	struct hdmi *hdmi = phy_8960->hdmi;
 
+	DBG("");
+
 	hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f);
 }
 
@@ -119,6 +487,14 @@ struct hdmi_phy *hdmi_phy_8960_init(stru
 	struct hdmi_phy_8960 *phy_8960;
 	struct hdmi_phy *phy = NULL;
 	int ret;
+#ifdef CONFIG_COMMON_CLK
+	int i;
+
+	/* sanity check: */
+	for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
+		if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate))
+			return ERR_PTR(-EINVAL);
+#endif
 
 	phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
 	if (!phy_8960) {
@@ -132,6 +508,16 @@ struct hdmi_phy *hdmi_phy_8960_init(stru
 
 	phy_8960->hdmi = hdmi;
 
+#ifdef CONFIG_COMMON_CLK
+	phy_8960->pll_hw.init = &pll_init;
+	phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw);
+	if (IS_ERR(phy_8960->pll)) {
+		ret = PTR_ERR(phy_8960->pll);
+		phy_8960->pll = NULL;
+		goto fail;
+	}
+#endif
+
 	return phy;
 
 fail:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,14 +12,14 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -148,9 +148,9 @@ static inline uint32_t REG_HDMI_GENERIC0
 
 static inline uint32_t REG_HDMI_GENERIC1(uint32_t i0) { return 0x000000a8 + 0x4*i0; }
 
-static inline uint32_t REG_HDMI_ACR(uint32_t i0) { return 0x000000c4 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
 
-static inline uint32_t REG_HDMI_ACR_0(uint32_t i0) { return 0x000000c4 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR_0(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
 #define HDMI_ACR_0_CTS__MASK					0xfffff000
 #define HDMI_ACR_0_CTS__SHIFT					12
 static inline uint32_t HDMI_ACR_0_CTS(uint32_t val)
@@ -158,7 +158,7 @@ static inline uint32_t HDMI_ACR_0_CTS(ui
 	return ((val) << HDMI_ACR_0_CTS__SHIFT) & HDMI_ACR_0_CTS__MASK;
 }
 
-static inline uint32_t REG_HDMI_ACR_1(uint32_t i0) { return 0x000000c8 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR_1(enum hdmi_acr_cts i0) { return 0x000000c8 + 0x8*i0; }
 #define HDMI_ACR_1_N__MASK					0xffffffff
 #define HDMI_ACR_1_N__SHIFT					0
 static inline uint32_t HDMI_ACR_1_N(uint32_t val)
@@ -552,6 +552,103 @@ static inline uint32_t HDMI_8x60_PHY_REG
 #define REG_HDMI_8960_PHY_REG11					0x0000042c
 
 #define REG_HDMI_8960_PHY_REG12					0x00000430
+#define HDMI_8960_PHY_REG12_SW_RESET				0x00000020
+#define HDMI_8960_PHY_REG12_PWRDN_B				0x00000080
+
+#define REG_HDMI_8960_PHY_REG_BIST_CFG				0x00000434
+
+#define REG_HDMI_8960_PHY_DEBUG_BUS_SEL				0x00000438
+
+#define REG_HDMI_8960_PHY_REG_MISC0				0x0000043c
+
+#define REG_HDMI_8960_PHY_REG13					0x00000440
+
+#define REG_HDMI_8960_PHY_REG14					0x00000444
+
+#define REG_HDMI_8960_PHY_REG15					0x00000448
+
+#define REG_HDMI_8960_PHY_PLL_REFCLK_CFG			0x00000500
+
+#define REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG			0x00000504
+
+#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0			0x00000508
+
+#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1			0x0000050c
+
+#define REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG			0x00000510
+
+#define REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG			0x00000514
+
+#define REG_HDMI_8960_PHY_PLL_PWRDN_B				0x00000518
+#define HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL			0x00000002
+#define HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B			0x00000008
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG0				0x0000051c
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG1				0x00000520
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG2				0x00000524
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG3				0x00000528
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG4				0x0000052c
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG0				0x00000530
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG1				0x00000534
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG2				0x00000538
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG3				0x0000053c
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0			0x00000540
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1			0x00000544
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2			0x00000548
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0			0x0000054c
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1			0x00000550
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2			0x00000554
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3			0x00000558
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4			0x0000055c
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5			0x00000560
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6			0x00000564
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7			0x00000568
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_SEL				0x0000056c
+
+#define REG_HDMI_8960_PHY_PLL_MISC0				0x00000570
+
+#define REG_HDMI_8960_PHY_PLL_MISC1				0x00000574
+
+#define REG_HDMI_8960_PHY_PLL_MISC2				0x00000578
+
+#define REG_HDMI_8960_PHY_PLL_MISC3				0x0000057c
+
+#define REG_HDMI_8960_PHY_PLL_MISC4				0x00000580
+
+#define REG_HDMI_8960_PHY_PLL_MISC5				0x00000584
+
+#define REG_HDMI_8960_PHY_PLL_MISC6				0x00000588
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS0			0x0000058c
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS1			0x00000590
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS2			0x00000594
+
+#define REG_HDMI_8960_PHY_PLL_STATUS0				0x00000598
+#define HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK			0x00000001
+
+#define REG_HDMI_8960_PHY_PLL_STATUS1				0x0000059c
 
 #define REG_HDMI_8x74_ANA_CFG0					0x00000000
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,6 @@
 config DRM_MSM
 	tristate "MSM DRM"
 	depends on DRM
-	depends on MSM_IOMMU
 	depends on ARCH_QCOM || (ARM && COMPILE_TEST)
 	select DRM_KMS_HELPER
 	select SHMEM
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -397,6 +397,7 @@ static void mdp4_crtc_prepare(struct drm
 	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
 	DBG("%s", mdp4_crtc->name);
 	/* make sure we hold a ref to mdp clks while setting up mode: */
+	drm_crtc_vblank_get(crtc);
 	mdp4_enable(get_kms(crtc));
 	mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
@@ -407,6 +408,7 @@ static void mdp4_crtc_commit(struct drm_
 	crtc_flush(crtc);
 	/* drop the ref to mdp clk's that we got in prepare: */
 	mdp4_disable(get_kms(crtc));
+	drm_crtc_vblank_put(crtc);
 }
 
 static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -147,7 +147,7 @@ static void mdp4_destroy(struct msm_kms
 	if (mdp4_kms->blank_cursor_iova)
 		msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
 	if (mdp4_kms->blank_cursor_bo)
-		drm_gem_object_unreference(mdp4_kms->blank_cursor_bo);
+		drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo);
 	kfree(mdp4_kms);
 }
 
@@ -176,6 +176,8 @@ int mdp4_disable(struct mdp4_kms *mdp4_k
 	if (mdp4_kms->pclk)
 		clk_disable_unprepare(mdp4_kms->pclk);
 	clk_disable_unprepare(mdp4_kms->lut_clk);
+	if (mdp4_kms->axi_clk)
+		clk_disable_unprepare(mdp4_kms->axi_clk);
 
 	return 0;
 }
@@ -188,6 +190,8 @@ int mdp4_enable(struct mdp4_kms *mdp4_km
 	if (mdp4_kms->pclk)
 		clk_prepare_enable(mdp4_kms->pclk);
 	clk_prepare_enable(mdp4_kms->lut_clk);
+	if (mdp4_kms->axi_clk)
+		clk_prepare_enable(mdp4_kms->axi_clk);
 
 	return 0;
 }
@@ -294,15 +298,17 @@ struct msm_kms *mdp4_kms_init(struct drm
 		goto fail;
 	}
 
-	mdp4_kms->dsi_pll_vdda = devm_regulator_get(&pdev->dev, "dsi_pll_vdda");
+	mdp4_kms->dsi_pll_vdda =
+			devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda");
 	if (IS_ERR(mdp4_kms->dsi_pll_vdda))
 		mdp4_kms->dsi_pll_vdda = NULL;
 
-	mdp4_kms->dsi_pll_vddio = devm_regulator_get(&pdev->dev, "dsi_pll_vddio");
+	mdp4_kms->dsi_pll_vddio =
+			devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio");
 	if (IS_ERR(mdp4_kms->dsi_pll_vddio))
 		mdp4_kms->dsi_pll_vddio = NULL;
 
-	mdp4_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
+	mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd");
 	if (IS_ERR(mdp4_kms->vdd))
 		mdp4_kms->vdd = NULL;
 
@@ -333,6 +339,13 @@ struct msm_kms *mdp4_kms_init(struct drm
 		goto fail;
 	}
 
+	mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "mdp_axi_clk");
+	if (IS_ERR(mdp4_kms->axi_clk)) {
+		dev_err(dev->dev, "failed to get axi_clk\n");
+		ret = PTR_ERR(mdp4_kms->axi_clk);
+		goto fail;
+	}
+
 	clk_set_rate(mdp4_kms->clk, config->max_clk);
 	clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
 
@@ -348,7 +361,7 @@ struct msm_kms *mdp4_kms_init(struct drm
 	mdelay(16);
 
 	if (config->iommu) {
-		mmu = msm_iommu_new(dev, config->iommu);
+		mmu = msm_iommu_new(&pdev->dev, config->iommu);
 		if (IS_ERR(mmu)) {
 			ret = PTR_ERR(mmu);
 			goto fail;
@@ -406,6 +419,8 @@ static struct mdp4_platform_config *mdp4
 	static struct mdp4_platform_config config = {};
 #ifdef CONFIG_OF
 	/* TODO */
+	config.max_clk = 266667000;
+	config.iommu = iommu_domain_alloc(&platform_bus_type);
 #else
 	if (cpu_is_apq8064())
 		config.max_clk = 266667000;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,7 @@ struct mdp4_kms {
 	struct clk *clk;
 	struct clk *pclk;
 	struct clk *lut_clk;
+	struct clk *axi_clk;
 
 	struct mdp_irq error_handler;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,14 +26,98 @@ static const char *iommu_ports[] = {
 
 static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev);
 
-static int mdp5_hw_init(struct msm_kms *kms)
+const struct mdp5_config *mdp5_cfg;
+
+static const struct mdp5_config msm8x74_config = {
+	.name = "msm8x74",
+	.ctl = {
+		.count = 5,
+		.base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
+	},
+	.pipe_vig = {
+		.count = 3,
+		.base = { 0x01200, 0x01600, 0x01a00 },
+	},
+	.pipe_rgb = {
+		.count = 3,
+		.base = { 0x01e00, 0x02200, 0x02600 },
+	},
+	.pipe_dma = {
+		.count = 2,
+		.base = { 0x02a00, 0x02e00 },
+	},
+	.lm = {
+		.count = 5,
+		.base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 },
+	},
+	.dspp = {
+		.count = 3,
+		.base = { 0x04600, 0x04a00, 0x04e00 },
+	},
+	.ad = {
+		.count = 2,
+		.base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */
+	},
+	.intf = {
+		.count = 4,
+		.base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
+	},
+};
+
+static const struct mdp5_config apq8084_config = {
+	.name = "apq8084",
+	.ctl = {
+		.count = 5,
+		.base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
+	},
+	.pipe_vig = {
+		.count = 4,
+		.base = { 0x01200, 0x01600, 0x01a00, 0x01e00 },
+	},
+	.pipe_rgb = {
+		.count = 4,
+		.base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
+	},
+	.pipe_dma = {
+		.count = 2,
+		.base = { 0x03200, 0x03600 },
+	},
+	.lm = {
+		.count = 6,
+		.base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 },
+	},
+	.dspp = {
+		.count = 4,
+		.base = { 0x05200, 0x05600, 0x05a00, 0x05e00 },
+
+	},
+	.ad = {
+		.count = 3,
+		.base = { 0x13500, 0x13700, 0x13900 },
+	},
+	.intf = {
+		.count = 5,
+		.base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
+	},
+};
+
+struct mdp5_config_entry {
+	int revision;
+	const struct mdp5_config *config;
+};
+
+static const struct mdp5_config_entry mdp5_configs[] = {
+	{ .revision = 0, .config = &msm8x74_config },
+	{ .revision = 2, .config = &msm8x74_config },
+	{ .revision = 3, .config = &apq8084_config },
+};
+
+static int mdp5_select_hw_cfg(struct msm_kms *kms)
 {
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
 	struct drm_device *dev = mdp5_kms->dev;
 	uint32_t version, major, minor;
-	int ret = 0;
-
-	pm_runtime_get_sync(dev->dev);
+	int i, ret = 0;
 
 	mdp5_enable(mdp5_kms);
 	version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION);
@@ -44,8 +128,8 @@ static int mdp5_hw_init(struct msm_kms *
 
 	DBG("found MDP5 version v%d.%d", major, minor);
 
-	if ((major != 1) || ((minor != 0) && (minor != 2))) {
-		dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
+	if (major != 1) {
+		dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
 				major, minor);
 		ret = -ENXIO;
 		goto out;
@@ -53,6 +137,35 @@ static int mdp5_hw_init(struct msm_kms *
 
 	mdp5_kms->rev = minor;
 
+	/* only after mdp5_cfg global pointer's init can we access the hw */
+	for (i = 0; i < ARRAY_SIZE(mdp5_configs); i++) {
+		if (mdp5_configs[i].revision != minor)
+			continue;
+		mdp5_kms->hw_cfg = mdp5_cfg = mdp5_configs[i].config;
+		break;
+	}
+	if (unlikely(!mdp5_kms->hw_cfg)) {
+		dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
+				major, minor);
+		ret = -ENXIO;
+		goto out;
+	}
+
+	DBG("MDP5: %s config selected", mdp5_kms->hw_cfg->name);
+
+	return 0;
+out:
+	return ret;
+}
+
+static int mdp5_hw_init(struct msm_kms *kms)
+{
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+	struct drm_device *dev = mdp5_kms->dev;
+	int i;
+
+	pm_runtime_get_sync(dev->dev);
+
 	/* Magic unknown register writes:
 	 *
 	 *    W VBIF:0x004 00000001      (mdss_mdp.c:839)
@@ -78,15 +191,13 @@ static int mdp5_hw_init(struct msm_kms *
 	 */
 
 	mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0);
-	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(0), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(1), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(2), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(3), 0);
 
-out:
+	for (i = 0; i < mdp5_kms->hw_cfg->ctl.count; i++)
+		mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(i), 0);
+
 	pm_runtime_put_sync(dev->dev);
 
-	return ret;
+	return 0;
 }
 
 static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
@@ -161,7 +272,7 @@ int mdp5_enable(struct mdp5_kms *mdp5_km
 static int modeset_init(struct mdp5_kms *mdp5_kms)
 {
 	static const enum mdp5_pipe crtcs[] = {
-			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2,
+			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
 	};
 	struct drm_device *dev = mdp5_kms->dev;
 	struct msm_drm_private *priv = dev->dev_private;
@@ -169,7 +280,7 @@ static int modeset_init(struct mdp5_kms
 	int i, ret;
 
 	/* construct CRTCs: */
-	for (i = 0; i < ARRAY_SIZE(crtcs); i++) {
+	for (i = 0; i < mdp5_kms->hw_cfg->pipe_rgb.count; i++) {
 		struct drm_plane *plane;
 		struct drm_crtc *crtc;
 
@@ -246,7 +357,7 @@ struct msm_kms *mdp5_kms_init(struct drm
 	struct mdp5_kms *mdp5_kms;
 	struct msm_kms *kms = NULL;
 	struct msm_mmu *mmu;
-	int ret;
+	int i, ret;
 
 	mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL);
 	if (!mdp5_kms) {
@@ -307,20 +418,22 @@ struct msm_kms *mdp5_kms_init(struct drm
 
 	ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk);
 
+	ret = mdp5_select_hw_cfg(kms);
+	if (ret)
+		goto fail;
+
 	/* make sure things are off before attaching iommu (bootloader could
 	 * have left things on, in which case we'll start getting faults if
 	 * we don't disable):
 	 */
 	mdp5_enable(mdp5_kms);
-	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(0), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(1), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(2), 0);
-	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(3), 0);
+	for (i = 0; i < mdp5_kms->hw_cfg->intf.count; i++)
+		mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);
 	mdp5_disable(mdp5_kms);
 	mdelay(16);
 
 	if (config->iommu) {
-		mmu = msm_iommu_new(dev, config->iommu);
+		mmu = msm_iommu_new(&pdev->dev, config->iommu);
 		if (IS_ERR(mmu)) {
 			ret = PTR_ERR(mmu);
 			dev_err(dev->dev, "failed to init iommu: %d\n", ret);
@@ -368,5 +481,11 @@ static struct mdp5_platform_config *mdp5
 #ifdef CONFIG_OF
 	/* TODO */
 #endif
+	config.iommu = iommu_domain_alloc(&platform_bus_type);
+	/* TODO hard-coded in downstream mdss, but should it be? */
+	config.max_clk = 200000000;
+	/* TODO get from DT: */
+	config.smp_blk_cnt = 22;
+
 	return &config;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,24 @@
 #include "msm_drv.h"
 #include "msm_kms.h"
 #include "mdp/mdp_kms.h"
+/* dynamic offsets used by mdp5.xml.h (initialized in mdp5_kms.c) */
+#define MDP5_MAX_BASES		8
+struct mdp5_sub_block {
+	int	count;
+	uint32_t base[MDP5_MAX_BASES];
+};
+struct mdp5_config {
+	char  *name;
+	struct mdp5_sub_block ctl;
+	struct mdp5_sub_block pipe_vig;
+	struct mdp5_sub_block pipe_rgb;
+	struct mdp5_sub_block pipe_dma;
+	struct mdp5_sub_block lm;
+	struct mdp5_sub_block dspp;
+	struct mdp5_sub_block ad;
+	struct mdp5_sub_block intf;
+};
+extern const struct mdp5_config *mdp5_cfg;
 #include "mdp5.xml.h"
 #include "mdp5_smp.h"
 
@@ -30,6 +48,7 @@ struct mdp5_kms {
 	struct drm_device *dev;
 
 	int rev;
+	const struct mdp5_config *hw_cfg;
 
 	/* mapper-id used to request GEM buffer mapped for scanout: */
 	int id;
@@ -82,6 +101,7 @@ static inline const char *pipe2name(enum
 		NAME(VIG0), NAME(VIG1), NAME(VIG2),
 		NAME(RGB0), NAME(RGB1), NAME(RGB2),
 		NAME(DMA0), NAME(DMA1),
+		NAME(VIG3), NAME(RGB3),
 #undef NAME
 	};
 	return names[pipe];
@@ -98,6 +118,8 @@ static inline uint32_t pipe2flush(enum m
 	case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2;
 	case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0;
 	case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
+	case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
+	case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
 	default:        return 0;
 	}
 }
@@ -108,6 +130,7 @@ static inline int pipe2nclients(enum mdp
 	case SSPP_RGB0:
 	case SSPP_RGB1:
 	case SSPP_RGB2:
+	case SSPP_RGB3:
 		return 1;
 	default:
 		return 3;
@@ -126,6 +149,8 @@ static inline enum mdp5_client_id pipe2c
 	case SSPP_RGB2: return CID_RGB2;
 	case SSPP_DMA0: return CID_DMA0_Y + plane;
 	case SSPP_DMA1: return CID_DMA1_Y + plane;
+	case SSPP_VIG3: return CID_VIG3_Y + plane;
+	case SSPP_RGB3: return CID_RGB3;
 	default:        return CID_UNUSED;
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,14 +12,14 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -68,6 +68,8 @@ enum mdp5_pipe {
 	SSPP_RGB2 = 5,
 	SSPP_DMA0 = 6,
 	SSPP_DMA1 = 7,
+	SSPP_VIG3 = 8,
+	SSPP_RGB3 = 9,
 };
 
 enum mdp5_ctl_mode {
@@ -126,7 +128,11 @@ enum mdp5_client_id {
 	CID_RGB0 = 16,
 	CID_RGB1 = 17,
 	CID_RGB2 = 18,
-	CID_MAX = 19,
+	CID_VIG3_Y = 19,
+	CID_VIG3_CR = 20,
+	CID_VIG3_CB = 21,
+	CID_RGB3 = 22,
+	CID_MAX = 23,
 };
 
 enum mdp5_igc_type {
@@ -299,11 +305,34 @@ static inline uint32_t MDP5_IGC_LUT_REG_
 #define MDP5_IGC_LUT_REG_DISABLE_PIPE_1				0x20000000
 #define MDP5_IGC_LUT_REG_DISABLE_PIPE_2				0x40000000
 
-static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000600 + 0x100*i0; }
+static inline uint32_t __offset_CTL(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return (mdp5_cfg->ctl.base[0]);
+		case 1: return (mdp5_cfg->ctl.base[1]);
+		case 2: return (mdp5_cfg->ctl.base[2]);
+		case 3: return (mdp5_cfg->ctl.base[3]);
+		case 4: return (mdp5_cfg->ctl.base[4]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000000 + __offset_CTL(i0); }
 
-static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+static inline uint32_t __offset_LAYER(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return 0x00000000;
+		case 1: return 0x00000004;
+		case 2: return 0x00000008;
+		case 3: return 0x0000000c;
+		case 4: return 0x00000010;
+		case 5: return 0x00000024;
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_CTL(i0) + __offset_LAYER(i1); }
 
-static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_CTL(i0) + __offset_LAYER(i1); }
 #define MDP5_CTL_LAYER_REG_VIG0__MASK				0x00000007
 #define MDP5_CTL_LAYER_REG_VIG0__SHIFT				0
 static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val)
@@ -354,8 +383,20 @@ static inline uint32_t MDP5_CTL_LAYER_RE
 }
 #define MDP5_CTL_LAYER_REG_BORDER_COLOR				0x01000000
 #define MDP5_CTL_LAYER_REG_CURSOR_OUT				0x02000000
+#define MDP5_CTL_LAYER_REG_VIG3__MASK				0x1c000000
+#define MDP5_CTL_LAYER_REG_VIG3__SHIFT				26
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(enum mdp_mixer_stage_id val)
+{
+	return ((val) << MDP5_CTL_LAYER_REG_VIG3__SHIFT) & MDP5_CTL_LAYER_REG_VIG3__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB3__MASK				0xe0000000
+#define MDP5_CTL_LAYER_REG_RGB3__SHIFT				29
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(enum mdp_mixer_stage_id val)
+{
+	return ((val) << MDP5_CTL_LAYER_REG_RGB3__SHIFT) & MDP5_CTL_LAYER_REG_RGB3__MASK;
+}
 
-static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000614 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000014 + __offset_CTL(i0); }
 #define MDP5_CTL_OP_MODE__MASK					0x0000000f
 #define MDP5_CTL_OP_MODE__SHIFT					0
 static inline uint32_t MDP5_CTL_OP_MODE(enum mdp5_ctl_mode val)
@@ -377,7 +418,7 @@ static inline uint32_t MDP5_CTL_OP_PACK_
 	return ((val) << MDP5_CTL_OP_PACK_3D__SHIFT) & MDP5_CTL_OP_PACK_3D__MASK;
 }
 
-static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000618 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000018 + __offset_CTL(i0); }
 #define MDP5_CTL_FLUSH_VIG0					0x00000001
 #define MDP5_CTL_FLUSH_VIG1					0x00000002
 #define MDP5_CTL_FLUSH_VIG2					0x00000004
@@ -387,26 +428,48 @@ static inline uint32_t REG_MDP5_CTL_FLUS
 #define MDP5_CTL_FLUSH_LM0					0x00000040
 #define MDP5_CTL_FLUSH_LM1					0x00000080
 #define MDP5_CTL_FLUSH_LM2					0x00000100
+#define MDP5_CTL_FLUSH_LM3					0x00000200
+#define MDP5_CTL_FLUSH_LM4					0x00000400
 #define MDP5_CTL_FLUSH_DMA0					0x00000800
 #define MDP5_CTL_FLUSH_DMA1					0x00001000
 #define MDP5_CTL_FLUSH_DSPP0					0x00002000
 #define MDP5_CTL_FLUSH_DSPP1					0x00004000
 #define MDP5_CTL_FLUSH_DSPP2					0x00008000
 #define MDP5_CTL_FLUSH_CTL					0x00020000
+#define MDP5_CTL_FLUSH_VIG3					0x00040000
+#define MDP5_CTL_FLUSH_RGB3					0x00080000
+#define MDP5_CTL_FLUSH_LM5					0x00100000
+#define MDP5_CTL_FLUSH_DSPP3					0x00200000
 
-static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000061c + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000001c + __offset_CTL(i0); }
 
-static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000620 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000020 + __offset_CTL(i0); }
 
-static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)
+{
+	switch (idx) {
+		case SSPP_VIG0: return (mdp5_cfg->pipe_vig.base[0]);
+		case SSPP_VIG1: return (mdp5_cfg->pipe_vig.base[1]);
+		case SSPP_VIG2: return (mdp5_cfg->pipe_vig.base[2]);
+		case SSPP_RGB0: return (mdp5_cfg->pipe_rgb.base[0]);
+		case SSPP_RGB1: return (mdp5_cfg->pipe_rgb.base[1]);
+		case SSPP_RGB2: return (mdp5_cfg->pipe_rgb.base[2]);
+		case SSPP_DMA0: return (mdp5_cfg->pipe_dma.base[0]);
+		case SSPP_DMA1: return (mdp5_cfg->pipe_dma.base[1]);
+		case SSPP_VIG3: return (mdp5_cfg->pipe_vig.base[3]);
+		case SSPP_RGB3: return (mdp5_cfg->pipe_rgb.base[3]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000014c4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000002c4 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000014f0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000002f0 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00001500 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00000300 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK				0xffff0000
 #define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT			16
 static inline uint32_t MDP5_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
@@ -420,7 +483,7 @@ static inline uint32_t MDP5_PIPE_SRC_SIZ
 	return ((val) << MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_SIZE_WIDTH__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00001204 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00000004 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK			0xffff0000
 #define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT			16
 static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(uint32_t val)
@@ -434,7 +497,7 @@ static inline uint32_t MDP5_PIPE_SRC_IMG
 	return ((val) << MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00001208 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00000008 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_XY_Y__MASK				0xffff0000
 #define MDP5_PIPE_SRC_XY_Y__SHIFT				16
 static inline uint32_t MDP5_PIPE_SRC_XY_Y(uint32_t val)
@@ -448,7 +511,7 @@ static inline uint32_t MDP5_PIPE_SRC_XY_
 	return ((val) << MDP5_PIPE_SRC_XY_X__SHIFT) & MDP5_PIPE_SRC_XY_X__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000120c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000000c + __offset_PIPE(i0); }
 #define MDP5_PIPE_OUT_SIZE_HEIGHT__MASK				0xffff0000
 #define MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT			16
 static inline uint32_t MDP5_PIPE_OUT_SIZE_HEIGHT(uint32_t val)
@@ -462,7 +525,7 @@ static inline uint32_t MDP5_PIPE_OUT_SIZ
 	return ((val) << MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT) & MDP5_PIPE_OUT_SIZE_WIDTH__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00001210 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00000010 + __offset_PIPE(i0); }
 #define MDP5_PIPE_OUT_XY_Y__MASK				0xffff0000
 #define MDP5_PIPE_OUT_XY_Y__SHIFT				16
 static inline uint32_t MDP5_PIPE_OUT_XY_Y(uint32_t val)
@@ -476,15 +539,15 @@ static inline uint32_t MDP5_PIPE_OUT_XY_
 	return ((val) << MDP5_PIPE_OUT_XY_X__SHIFT) & MDP5_PIPE_OUT_XY_X__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00001214 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00000014 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00001218 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00000018 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000121c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000001c + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00001220 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00000020 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00001224 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00000024 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_STRIDE_A_P0__MASK				0x0000ffff
 #define MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT			0
 static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P0(uint32_t val)
@@ -498,7 +561,7 @@ static inline uint32_t MDP5_PIPE_SRC_STR
 	return ((val) << MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P1__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00001228 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00000028 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_STRIDE_B_P2__MASK				0x0000ffff
 #define MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT			0
 static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P2(uint32_t val)
@@ -512,9 +575,9 @@ static inline uint32_t MDP5_PIPE_SRC_STR
 	return ((val) << MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P3__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000122c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000002c + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00001230 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00000030 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_FORMAT_G_BPC__MASK			0x00000003
 #define MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT			0
 static inline uint32_t MDP5_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
@@ -568,7 +631,7 @@ static inline uint32_t MDP5_PIPE_SRC_FOR
 	return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00001234 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00000034 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_UNPACK_ELEM0__MASK			0x000000ff
 #define MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT			0
 static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
@@ -594,7 +657,7 @@ static inline uint32_t MDP5_PIPE_SRC_UNP
 	return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM3__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00001238 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00000038 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SRC_OP_MODE_BWC_EN				0x00000001
 #define MDP5_PIPE_SRC_OP_MODE_BWC__MASK				0x00000006
 #define MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT			1
@@ -610,29 +673,29 @@ static inline uint32_t MDP5_PIPE_SRC_OP_
 #define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE			0x00400000
 #define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD			0x00800000
 
-static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000123c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000003c + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00001248 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00000048 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000124c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000004c + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00001250 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00000050 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00001254 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00000054 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00001258 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00000058 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00001270 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00000070 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000012a4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000000a4 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000012a8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000000a8 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000012ac + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000000ac + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000012b0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000000b0 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000012b4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000000b4 + __offset_PIPE(i0); }
 #define MDP5_PIPE_DECIMATION_VERT__MASK				0x000000ff
 #define MDP5_PIPE_DECIMATION_VERT__SHIFT			0
 static inline uint32_t MDP5_PIPE_DECIMATION_VERT(uint32_t val)
@@ -646,7 +709,7 @@ static inline uint32_t MDP5_PIPE_DECIMAT
 	return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00001404 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00000204 + __offset_PIPE(i0); }
 #define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN			0x00000001
 #define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN			0x00000002
 #define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK		0x00000300
@@ -686,23 +749,34 @@ static inline uint32_t MDP5_PIPE_SCALE_C
 	return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK;
 }
 
-static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00001410 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00000210 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00001414 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00000214 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00001420 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00000220 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00001424 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00000224 + __offset_PIPE(i0); }
 
-static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+static inline uint32_t __offset_LM(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return (mdp5_cfg->lm.base[0]);
+		case 1: return (mdp5_cfg->lm.base[1]);
+		case 2: return (mdp5_cfg->lm.base[2]);
+		case 3: return (mdp5_cfg->lm.base[3]);
+		case 4: return (mdp5_cfg->lm.base[4]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00000000 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00000000 + __offset_LM(i0); }
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA			0x00000002
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA			0x00000004
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA			0x00000008
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA			0x00000010
 
-static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00003204 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00000004 + __offset_LM(i0); }
 #define MDP5_LM_OUT_SIZE_HEIGHT__MASK				0xffff0000
 #define MDP5_LM_OUT_SIZE_HEIGHT__SHIFT				16
 static inline uint32_t MDP5_LM_OUT_SIZE_HEIGHT(uint32_t val)
@@ -716,13 +790,13 @@ static inline uint32_t MDP5_LM_OUT_SIZE_
 	return ((val) << MDP5_LM_OUT_SIZE_WIDTH__SHIFT) & MDP5_LM_OUT_SIZE_WIDTH__MASK;
 }
 
-static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00003208 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00000008 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00003210 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00000010 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00000020 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00000020 + __offset_LM(i0) + 0x30*i1; }
 #define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK			0x00000003
 #define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT			0
 static inline uint32_t MDP5_LM_BLEND_OP_MODE_FG_ALPHA(enum mdp_alpha_type val)
@@ -744,57 +818,67 @@ static inline uint32_t MDP5_LM_BLEND_OP_
 #define MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA			0x00001000
 #define MDP5_LM_BLEND_OP_MODE_BG_TRANSP_EN			0x00002000
 
-static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003224 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000024 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003228 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000028 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000322c + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000002c + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003230 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000030 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003234 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000034 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003238 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000038 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000323c + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000003c + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003240 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000040 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003244 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000044 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003248 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000048 + __offset_LM(i0) + 0x30*i1; }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000032e0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000000e0 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000032e4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000000e4 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000032e8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000000e8 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000032dc + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000000dc + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000032ec + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000000ec + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000032f0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000000f0 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000032f4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000000f4 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000032f8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000000f8 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000032fc + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000000fc + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00003300 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00000100 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00003304 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00000104 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00003308 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00000108 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000330c + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000010c + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00003310 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00000110 + __offset_LM(i0); }
 
-static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+static inline uint32_t __offset_DSPP(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return (mdp5_cfg->dspp.base[0]);
+		case 1: return (mdp5_cfg->dspp.base[1]);
+		case 2: return (mdp5_cfg->dspp.base[2]);
+		case 3: return (mdp5_cfg->dspp.base[3]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00000000 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00000000 + __offset_DSPP(i0); }
 #define MDP5_DSPP_OP_MODE_IGC_LUT_EN				0x00000001
 #define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK			0x0000000e
 #define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT			1
@@ -811,29 +895,40 @@ static inline uint32_t MDP5_DSPP_OP_MODE
 #define MDP5_DSPP_OP_MODE_GAMUT_EN				0x00800000
 #define MDP5_DSPP_OP_MODE_GAMUT_ORDER				0x01000000
 
-static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00004630 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00000030 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00004750 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00000150 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00004810 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00000210 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00004830 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00000230 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00004834 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00000234 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00004838 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00000238 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000048dc + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000002dc + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000048b0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000002b0 + __offset_DSPP(i0); }
 
-static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+static inline uint32_t __offset_INTF(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return (mdp5_cfg->intf.base[0]);
+		case 1: return (mdp5_cfg->intf.base[1]);
+		case 2: return (mdp5_cfg->intf.base[2]);
+		case 3: return (mdp5_cfg->intf.base[3]);
+		case 4: return (mdp5_cfg->intf.base[4]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00000000 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00000000 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00012504 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00000004 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00012508 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00000008 + __offset_INTF(i0); }
 #define MDP5_INTF_HSYNC_CTL_PULSEW__MASK			0x0000ffff
 #define MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT			0
 static inline uint32_t MDP5_INTF_HSYNC_CTL_PULSEW(uint32_t val)
@@ -847,23 +942,23 @@ static inline uint32_t MDP5_INTF_HSYNC_C
 	return ((val) << MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT) & MDP5_INTF_HSYNC_CTL_PERIOD__MASK;
 }
 
-static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0001250c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0000000c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00012510 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00000010 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00012514 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00000014 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00012518 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00000018 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0001251c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0000001c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00012520 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00000020 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00012524 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00000024 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00012528 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00000028 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0001252c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0000002c + __offset_INTF(i0); }
 #define MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK			0x7fffffff
 #define MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT			0
 static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F0_VAL(uint32_t val)
@@ -872,7 +967,7 @@ static inline uint32_t MDP5_INTF_ACTIVE_
 }
 #define MDP5_INTF_ACTIVE_VSTART_F0_ACTIVE_V_ENABLE		0x80000000
 
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00012530 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00000030 + __offset_INTF(i0); }
 #define MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK			0x7fffffff
 #define MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT			0
 static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F1_VAL(uint32_t val)
@@ -880,11 +975,11 @@ static inline uint32_t MDP5_INTF_ACTIVE_
 	return ((val) << MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK;
 }
 
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00012534 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00000034 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00012538 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00000038 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0001253c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0000003c + __offset_INTF(i0); }
 #define MDP5_INTF_DISPLAY_HCTL_START__MASK			0x0000ffff
 #define MDP5_INTF_DISPLAY_HCTL_START__SHIFT			0
 static inline uint32_t MDP5_INTF_DISPLAY_HCTL_START(uint32_t val)
@@ -898,7 +993,7 @@ static inline uint32_t MDP5_INTF_DISPLAY
 	return ((val) << MDP5_INTF_DISPLAY_HCTL_END__SHIFT) & MDP5_INTF_DISPLAY_HCTL_END__MASK;
 }
 
-static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00012540 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00000040 + __offset_INTF(i0); }
 #define MDP5_INTF_ACTIVE_HCTL_START__MASK			0x00007fff
 #define MDP5_INTF_ACTIVE_HCTL_START__SHIFT			0
 static inline uint32_t MDP5_INTF_ACTIVE_HCTL_START(uint32_t val)
@@ -913,124 +1008,132 @@ static inline uint32_t MDP5_INTF_ACTIVE_
 }
 #define MDP5_INTF_ACTIVE_HCTL_ACTIVE_H_ENABLE			0x80000000
 
-static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00012544 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00000044 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00012548 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00000048 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0001254c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0000004c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00012550 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00000050 + __offset_INTF(i0); }
 #define MDP5_INTF_POLARITY_CTL_HSYNC_LOW			0x00000001
 #define MDP5_INTF_POLARITY_CTL_VSYNC_LOW			0x00000002
 #define MDP5_INTF_POLARITY_CTL_DATA_EN_LOW			0x00000004
 
-static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00012554 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00000054 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00012558 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00000058 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0001255c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0000005c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00012584 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00000084 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00012590 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00000090 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000125a8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000000a8 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000125ac + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000000ac + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000125b0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000000b0 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000125f0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000000f0 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000125f4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000000f4 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000125f8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000000f8 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00012600 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00000100 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00012604 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00000104 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00012608 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00000108 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0001260c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0000010c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00012610 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00000110 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00012614 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00000114 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00012618 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00000118 + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0001261c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0000011c + __offset_INTF(i0); }
 
-static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+static inline uint32_t __offset_AD(uint32_t idx)
+{
+	switch (idx) {
+		case 0: return (mdp5_cfg->ad.base[0]);
+		case 1: return (mdp5_cfg->ad.base[1]);
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00000000 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00000000 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00013104 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00000004 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00013108 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00000008 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0001310c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0000000c + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00013110 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00000010 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00013114 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00000014 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00013118 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00000018 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0001311c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0000001c + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00013120 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00000020 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00013124 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00000024 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00013128 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00000028 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0001312c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0000002c + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00013130 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00000030 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00013134 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00000034 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00013138 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00000038 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0001317c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0000007c + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000131c8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000000c8 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000131cc + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000000cc + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000131d0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000000d0 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000131d4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000000d4 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000131d8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000000d8 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000131dc + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000000dc + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000131e0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000000e0 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000131e8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000000e8 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000131ec + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000000ec + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000131f0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000000f0 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000131f4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000000f4 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000131f8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000000f8 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00013200 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00000100 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00013244 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00000144 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00013248 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00000148 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0001324c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0000014c + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00013254 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00000154 + __offset_AD(i0); }
 
-static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00013258 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00000158 + __offset_AD(i0); }
 
 
 #endif /* MDP5_XML */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ module_param(reglog, bool, 0600);
 #define reglog 0
 #endif
 
-static char *vram;
+static char *vram = "16m";
 MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
 module_param(vram, charp, 0);
 
@@ -181,7 +181,6 @@ static int msm_load(struct drm_device *d
 	struct msm_kms *kms;
 	int ret;
 
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		dev_err(dev->dev, "failed to allocate private data\n");
@@ -314,13 +313,15 @@ fail:
 
 static void load_gpu(struct drm_device *dev)
 {
+	static DEFINE_MUTEX(init_lock);
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gpu *gpu;
 
+	mutex_lock(&init_lock);
+
 	if (priv->gpu)
-		return;
+		goto out;
 
-	mutex_lock(&dev->struct_mutex);
 	gpu = a3xx_gpu_init(dev);
 	if (IS_ERR(gpu)) {
 		dev_warn(dev->dev, "failed to load a3xx gpu\n");
@@ -330,7 +331,9 @@ static void load_gpu(struct drm_device *
 
 	if (gpu) {
 		int ret;
+		mutex_lock(&dev->struct_mutex);
 		gpu->funcs->pm_resume(gpu);
+		mutex_unlock(&dev->struct_mutex);
 		ret = gpu->funcs->hw_init(gpu);
 		if (ret) {
 			dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
@@ -340,12 +343,12 @@ static void load_gpu(struct drm_device *
 			/* give inactive pm a chance to kick in: */
 			msm_gpu_retire(gpu);
 		}
-
 	}
 
 	priv->gpu = gpu;
 
-	mutex_unlock(&dev->struct_mutex);
+out:
+	mutex_unlock(&init_lock);
 }
 
 static int msm_open(struct drm_device *dev, struct drm_file *file)
@@ -906,25 +909,22 @@ static int compare_of(struct device *dev
 	return dev->of_node == data;
 }
 
-static int msm_drm_add_components(struct device *master, struct master *m)
+static int add_components(struct device *dev, struct component_match **matchptr,
+		const char *name)
 {
-	struct device_node *np = master->of_node;
+	struct device_node *np = dev->of_node;
 	unsigned i;
-	int ret;
 
 	for (i = 0; ; i++) {
 		struct device_node *node;
 
-		node = of_parse_phandle(np, "connectors", i);
+		node = of_parse_phandle(np, name, i);
 		if (!node)
 			break;
 
-		ret = component_master_add_child(m, compare_of, node);
-		of_node_put(node);
-
-		if (ret)
-			return ret;
+		component_match_add(dev, matchptr, compare_of, node);
 	}
+
 	return 0;
 }
 #else
@@ -932,9 +932,34 @@ static int compare_dev(struct device *de
 {
 	return dev == data;
 }
+#endif
 
-static int msm_drm_add_components(struct device *master, struct master *m)
+static int msm_drm_bind(struct device *dev)
+{
+	return drm_platform_init(&msm_driver, to_platform_device(dev));
+}
+
+static void msm_drm_unbind(struct device *dev)
+{
+	drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+}
+
+static const struct component_master_ops msm_drm_ops = {
+	.bind = msm_drm_bind,
+	.unbind = msm_drm_unbind,
+};
+
+/*
+ * Platform driver:
+ */
+
+static int msm_pdev_probe(struct platform_device *pdev)
 {
+	struct component_match *match = NULL;
+#ifdef CONFIG_OF
+	add_components(&pdev->dev, &match, "connectors");
+	add_components(&pdev->dev, &match, "gpus");
+#else
 	/* For non-DT case, it kinda sucks.  We don't actually have a way
 	 * to know whether or not we are waiting for certain devices (or if
 	 * they are simply not present).  But for non-DT we only need to
@@ -949,50 +974,20 @@ static int msm_drm_add_components(struct
 
 	for (i = 0; i < ARRAY_SIZE(devnames); i++) {
 		struct device *dev;
-		int ret;
 
 		dev = bus_find_device_by_name(&platform_bus_type,
 				NULL, devnames[i]);
 		if (!dev) {
-			dev_info(master, "still waiting for %s\n", devnames[i]);
+			dev_info(&pdev->dev, "still waiting for %s\n", devnames[i]);
 			return -EPROBE_DEFER;
 		}
 
-		ret = component_master_add_child(m, compare_dev, dev);
-		if (ret) {
-			DBG("could not add child: %d", ret);
-			return ret;
-		}
+		component_match_add(&pdev->dev, &match, compare_dev, dev);
 	}
-
-	return 0;
-}
 #endif
 
-static int msm_drm_bind(struct device *dev)
-{
-	return drm_platform_init(&msm_driver, to_platform_device(dev));
-}
-
-static void msm_drm_unbind(struct device *dev)
-{
-	drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
-}
-
-static const struct component_master_ops msm_drm_ops = {
-		.add_components = msm_drm_add_components,
-		.bind = msm_drm_bind,
-		.unbind = msm_drm_unbind,
-};
-
-/*
- * Platform driver:
- */
-
-static int msm_pdev_probe(struct platform_device *pdev)
-{
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-	return component_master_add(&pdev->dev, &msm_drm_ops);
+	return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
 }
 
 static int msm_pdev_remove(struct platform_device *pdev)
@@ -1008,7 +1003,8 @@ static const struct platform_device_id m
 };
 
 static const struct of_device_id dt_match[] = {
-	{ .compatible = "qcom,mdss_mdp" },
+	{ .compatible = "qcom,mdp" },      /* mdp4 */
+	{ .compatible = "qcom,mdss_mdp" }, /* mdp5 */
 	{}
 };
 MODULE_DEVICE_TABLE(of, dt_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,11 @@
 
 #include "drm_crtc.h"
 #include "drm_fb_helper.h"
+#include "msm_gem.h"
+
+extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
+					struct vm_area_struct *vma);
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
 
 /*
  * fbdev funcs, to implement legacy fbdev interface on top of drm driver
@@ -43,6 +48,7 @@ static struct fb_ops msm_fb_ops = {
 	.fb_fillrect = sys_fillrect,
 	.fb_copyarea = sys_copyarea,
 	.fb_imageblit = sys_imageblit,
+	.fb_mmap = msm_fbdev_mmap,
 
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par,
@@ -51,6 +57,31 @@ static struct fb_ops msm_fb_ops = {
 	.fb_setcmap = drm_fb_helper_setcmap,
 };
 
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+	struct msm_fbdev *fbdev = to_msm_fbdev(helper);
+	struct drm_gem_object *drm_obj = fbdev->bo;
+	struct drm_device *dev = helper->dev;
+	int ret = 0;
+
+	if (drm_device_is_unplugged(dev))
+		return -ENODEV;
+
+	mutex_lock(&dev->struct_mutex);
+
+	ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	if (ret) {
+		pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
+		return ret;
+	}
+
+	return msm_gem_mmap_obj(drm_obj, vma);
+}
+
 static int msm_fbdev_create(struct drm_fb_helper *helper,
 		struct drm_fb_helper_surface_size *sizes)
 {
@@ -104,8 +135,16 @@ static int msm_fbdev_create(struct drm_f
 
 	mutex_lock(&dev->struct_mutex);
 
-	/* TODO implement our own fb_mmap so we don't need this: */
-	msm_gem_get_iova_locked(fbdev->bo, 0, &paddr);
+	/*
+	 * NOTE: if we can be guaranteed to be able to map buffer
+	 * in panic (ie. lock-safe, etc) we could avoid pinning the
+	 * buffer now:
+	 */
+	ret = msm_gem_get_iova_locked(fbdev->bo, 0, &paddr);
+	if (ret) {
+		dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
+		goto fail_unlock;
+	}
 
 	fbi = framebuffer_alloc(0, dev->dev);
 	if (!fbi) {
@@ -177,7 +216,7 @@ static void msm_crtc_fb_gamma_get(struct
 	DBG("fbdev: get gamma");
 }
 
-static struct drm_fb_helper_funcs msm_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs msm_fb_helper_funcs = {
 	.gamma_set = msm_crtc_fb_gamma_set,
 	.gamma_get = msm_crtc_fb_gamma_get,
 	.fb_probe = msm_fbdev_create,
@@ -189,7 +228,7 @@ struct drm_fb_helper *msm_fbdev_init(str
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_fbdev *fbdev = NULL;
 	struct drm_fb_helper *helper;
-	int ret = 0;
+	int ret;
 
 	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
 	if (!fbdev)
@@ -197,7 +236,7 @@ struct drm_fb_helper *msm_fbdev_init(str
 
 	helper = &fbdev->base;
 
-	helper->funcs = &msm_fb_helper_funcs;
+	drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(dev, helper,
 			priv->num_crtcs, priv->num_connectors);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ static struct page **get_pages(struct dr
 		int npages = obj->size >> PAGE_SHIFT;
 
 		if (iommu_present(&platform_bus_type))
-			p = drm_gem_get_pages(obj, 0);
+			p = drm_gem_get_pages(obj);
 		else
 			p = get_pages_vram(obj, npages);
 
@@ -278,24 +278,23 @@ int msm_gem_get_iova_locked(struct drm_g
 		uint32_t *iova)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
-	struct drm_device *dev = obj->dev;
 	int ret = 0;
 
 	if (!msm_obj->domain[id].iova) {
 		struct msm_drm_private *priv = obj->dev->dev_private;
-		struct msm_mmu *mmu = priv->mmus[id];
 		struct page **pages = get_pages(obj);
 
-		if (!mmu) {
-			dev_err(dev->dev, "null MMU pointer\n");
-			return -EINVAL;
-		}
-
 		if (IS_ERR(pages))
 			return PTR_ERR(pages);
 
 		if (iommu_present(&platform_bus_type)) {
-			uint32_t offset = (uint32_t)mmap_offset(obj);
+			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;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_gpu.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_gpu.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_gpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_gpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -606,14 +606,17 @@ int msm_gpu_init(struct drm_device *drm,
 	iommu = iommu_domain_alloc(&platform_bus_type);
 	if (iommu) {
 		dev_info(drm->dev, "%s: using IOMMU\n", name);
-		gpu->mmu = msm_iommu_new(drm, iommu);
+		gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
 	} else {
 		dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
 	}
 	gpu->id = msm_register_mmu(drm, gpu->mmu);
 
+
 	/* Create ringbuffer: */
+	mutex_lock(&drm->struct_mutex);
 	gpu->rb = msm_ringbuffer_new(gpu, ringsz);
+	mutex_unlock(&drm->struct_mutex);
 	if (IS_ERR(gpu->rb)) {
 		ret = PTR_ERR(gpu->rb);
 		gpu->rb = NULL;
@@ -621,13 +624,6 @@ int msm_gpu_init(struct drm_device *drm,
 		goto fail;
 	}
 
-	ret = msm_gem_get_iova_locked(gpu->rb->bo, gpu->id, &gpu->rb_iova);
-	if (ret) {
-		gpu->rb_iova = 0;
-		dev_err(drm->dev, "could not map ringbuffer: %d\n", ret);
-		goto fail;
-	}
-
 	bs_init(gpu);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_iommu.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_iommu.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,45 +27,20 @@ struct msm_iommu {
 static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
 		unsigned long iova, int flags, void *arg)
 {
-	DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
-	return -ENOSYS;
+	pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
+	return 0;
 }
 
 static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
 {
-	struct drm_device *dev = mmu->dev;
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
-	int i, ret;
-
-	for (i = 0; i < cnt; i++) {
-		struct device *msm_iommu_get_ctx(const char *ctx_name);
-		struct device *ctx = msm_iommu_get_ctx(names[i]);
-		if (IS_ERR_OR_NULL(ctx)) {
-			dev_warn(dev->dev, "couldn't get %s context", names[i]);
-			continue;
-		}
-		ret = iommu_attach_device(iommu->domain, ctx);
-		if (ret) {
-			dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
-			return ret;
-		}
-	}
-
-	return 0;
+	return iommu_attach_device(iommu->domain, mmu->dev);
 }
 
 static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
-	int i;
-
-	for (i = 0; i < cnt; i++) {
-		struct device *msm_iommu_get_ctx(const char *ctx_name);
-		struct device *ctx = msm_iommu_get_ctx(names[i]);
-		if (IS_ERR_OR_NULL(ctx))
-			continue;
-		iommu_detach_device(iommu->domain, ctx);
-	}
+	iommu_detach_device(iommu->domain, mmu->dev);
 }
 
 static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
@@ -149,7 +124,7 @@ static const struct msm_mmu_funcs funcs
 		.destroy = msm_iommu_destroy,
 };
 
-struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain)
+struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
 {
 	struct msm_iommu *iommu;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_mmu.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_mmu.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/msm/msm_mmu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/msm/msm_mmu.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,17 +32,17 @@ struct msm_mmu_funcs {
 
 struct msm_mmu {
 	const struct msm_mmu_funcs *funcs;
-	struct drm_device *dev;
+	struct device *dev;
 };
 
-static inline void msm_mmu_init(struct msm_mmu *mmu, struct drm_device *dev,
+static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
 		const struct msm_mmu_funcs *funcs)
 {
 	mmu->dev = dev;
 	mmu->funcs = funcs;
 }
 
-struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain);
-struct msm_mmu *msm_gpummu_new(struct drm_device *dev, struct msm_gpu *gpu);
+struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
+struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
 
 #endif /* __MSM_MMU_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/client.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/client.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/client.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/client.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,13 +26,167 @@
 #include <core/client.h>
 #include <core/handle.h>
 #include <core/option.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+
+#include <nvif/unpack.h>
+#include <nvif/event.h>
 
 #include <engine/device.h>
 
+struct nvkm_client_notify {
+	struct nouveau_client *client;
+	struct nvkm_notify n;
+	u8 version;
+	u8 size;
+	union {
+		struct nvif_notify_rep_v0 v0;
+	} rep;
+};
+
+static int
+nvkm_client_notify(struct nvkm_notify *n)
+{
+	struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
+	struct nouveau_client *client = notify->client;
+	return client->ntfy(&notify->rep, notify->size, n->data, n->size);
+}
+
+int
+nvkm_client_notify_put(struct nouveau_client *client, int index)
+{
+	if (index < ARRAY_SIZE(client->notify)) {
+		if (client->notify[index]) {
+			nvkm_notify_put(&client->notify[index]->n);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int
+nvkm_client_notify_get(struct nouveau_client *client, int index)
+{
+	if (index < ARRAY_SIZE(client->notify)) {
+		if (client->notify[index]) {
+			nvkm_notify_get(&client->notify[index]->n);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int
+nvkm_client_notify_del(struct nouveau_client *client, int index)
+{
+	if (index < ARRAY_SIZE(client->notify)) {
+		if (client->notify[index]) {
+			nvkm_notify_fini(&client->notify[index]->n);
+			kfree(client->notify[index]);
+			client->notify[index] = NULL;
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int
+nvkm_client_notify_new(struct nouveau_client *client,
+		       struct nvkm_event *event, void *data, u32 size)
+{
+	struct nvkm_client_notify *notify;
+	union {
+		struct nvif_notify_req_v0 v0;
+	} *req = data;
+	u8  index, reply;
+	int ret;
+
+	for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
+		if (!client->notify[index])
+			break;
+	}
+
+	if (index == ARRAY_SIZE(client->notify))
+		return -ENOSPC;
+
+	notify = kzalloc(sizeof(*notify), GFP_KERNEL);
+	if (!notify)
+		return -ENOMEM;
+
+	nv_ioctl(client, "notify new size %d\n", size);
+	if (nvif_unpack(req->v0, 0, 0, true)) {
+		nv_ioctl(client, "notify new vers %d reply %d route %02x "
+				 "token %llx\n", req->v0.version,
+			 req->v0.reply, req->v0.route, req->v0.token);
+		notify->version = req->v0.version;
+		notify->size = sizeof(notify->rep.v0);
+		notify->rep.v0.version = req->v0.version;
+		notify->rep.v0.route = req->v0.route;
+		notify->rep.v0.token = req->v0.token;
+		reply = req->v0.reply;
+	}
+
+	if (ret == 0) {
+		ret = nvkm_notify_init(event, nvkm_client_notify, false,
+				       data, size, reply, &notify->n);
+		if (ret == 0) {
+			client->notify[index] = notify;
+			notify->client = client;
+			return index;
+		}
+	}
+
+	kfree(notify);
+	return ret;
+}
+
+static int
+nouveau_client_devlist(struct nouveau_object *object, void *data, u32 size)
+{
+	union {
+		struct nv_client_devlist_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "client devlist size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "client devlist vers %d count %d\n",
+			 args->v0.version, args->v0.count);
+		if (size == sizeof(args->v0.device[0]) * args->v0.count) {
+			ret = nouveau_device_list(args->v0.device,
+						  args->v0.count);
+			if (ret >= 0) {
+				args->v0.count = ret;
+				ret = 0;
+			}
+		} else {
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nouveau_client_mthd(struct nouveau_object *object, u32 mthd,
+		    void *data, u32 size)
+{
+	switch (mthd) {
+	case NV_CLIENT_DEVLIST:
+		return nouveau_client_devlist(object, data, size);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
 static void
 nouveau_client_dtor(struct nouveau_object *object)
 {
 	struct nouveau_client *client = (void *)object;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(client->notify); i++)
+		nvkm_client_notify_del(client, i);
 	nouveau_object_ref(NULL, &client->device);
 	nouveau_handle_destroy(client->root);
 	nouveau_namedb_destroy(&client->base);
@@ -42,6 +196,7 @@ static struct nouveau_oclass
 nouveau_client_oclass = {
 	.ofuncs = &(struct nouveau_ofuncs) {
 		.dtor = nouveau_client_dtor,
+		.mthd = nouveau_client_mthd,
 	},
 };
 
@@ -93,9 +248,12 @@ int
 nouveau_client_fini(struct nouveau_client *client, bool suspend)
 {
 	const char *name[2] = { "fini", "suspend" };
-	int ret;
-
+	int ret, i;
 	nv_debug(client, "%s running\n", name[suspend]);
+	nv_debug(client, "%s notify\n", name[suspend]);
+	for (i = 0; i < ARRAY_SIZE(client->notify); i++)
+		nvkm_client_notify_put(client, i);
+	nv_debug(client, "%s object\n", name[suspend]);
 	ret = nouveau_handle_fini(client->root, suspend);
 	nv_debug(client, "%s completed with %d\n", name[suspend], ret);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/event.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/event.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/event.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Red Hat Inc.
+ * Copyright 2013-2014 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"),
@@ -24,173 +24,77 @@
 #include <core/event.h>
 
 void
-nouveau_event_put(struct nouveau_eventh *handler)
+nvkm_event_put(struct nvkm_event *event, u32 types, int index)
 {
-	struct nouveau_event *event = handler->event;
-	unsigned long flags;
-	u32 m, t;
-
-	if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags))
-		return;
-
-	spin_lock_irqsave(&event->refs_lock, flags);
-	for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
-		if (!--event->refs[handler->index * event->types_nr + t]) {
-			if (event->disable)
-				event->disable(event, 1 << t, handler->index);
+	BUG_ON(!spin_is_locked(&event->refs_lock));
+	while (types) {
+		int type = __ffs(types); types &= ~(1 << type);
+		if (--event->refs[index * event->types_nr + type] == 0) {
+			if (event->func->fini)
+				event->func->fini(event, 1 << type, index);
 		}
-
 	}
-	spin_unlock_irqrestore(&event->refs_lock, flags);
 }
 
 void
-nouveau_event_get(struct nouveau_eventh *handler)
+nvkm_event_get(struct nvkm_event *event, u32 types, int index)
 {
-	struct nouveau_event *event = handler->event;
-	unsigned long flags;
-	u32 m, t;
-
-	if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags))
-		return;
-
-	spin_lock_irqsave(&event->refs_lock, flags);
-	for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
-		if (!event->refs[handler->index * event->types_nr + t]++) {
-			if (event->enable)
-				event->enable(event, 1 << t, handler->index);
+	BUG_ON(!spin_is_locked(&event->refs_lock));
+	while (types) {
+		int type = __ffs(types); types &= ~(1 << type);
+		if (++event->refs[index * event->types_nr + type] == 1) {
+			if (event->func->init)
+				event->func->init(event, 1 << type, index);
 		}
-
-	}
-	spin_unlock_irqrestore(&event->refs_lock, flags);
-}
-
-static void
-nouveau_event_fini(struct nouveau_eventh *handler)
-{
-	struct nouveau_event *event = handler->event;
-	unsigned long flags;
-	nouveau_event_put(handler);
-	spin_lock_irqsave(&event->list_lock, flags);
-	list_del(&handler->head);
-	spin_unlock_irqrestore(&event->list_lock, flags);
-}
-
-static int
-nouveau_event_init(struct nouveau_event *event, u32 types, int index,
-		   int (*func)(void *, u32, int), void *priv,
-		   struct nouveau_eventh *handler)
-{
-	unsigned long flags;
-
-	if (types & ~((1 << event->types_nr) - 1))
-		return -EINVAL;
-	if (index >= event->index_nr)
-		return -EINVAL;
-
-	handler->event = event;
-	handler->flags = 0;
-	handler->types = types;
-	handler->index = index;
-	handler->func = func;
-	handler->priv = priv;
-
-	spin_lock_irqsave(&event->list_lock, flags);
-	list_add_tail(&handler->head, &event->list[index]);
-	spin_unlock_irqrestore(&event->list_lock, flags);
-	return 0;
-}
-
-int
-nouveau_event_new(struct nouveau_event *event, u32 types, int index,
-		  int (*func)(void *, u32, int), void *priv,
-		  struct nouveau_eventh **phandler)
-{
-	struct nouveau_eventh *handler;
-	int ret = -ENOMEM;
-
-	if (event->check) {
-		ret = event->check(event, types, index);
-		if (ret)
-			return ret;
-	}
-
-	handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
-	if (handler) {
-		ret = nouveau_event_init(event, types, index, func, priv, handler);
-		if (ret)
-			kfree(handler);
-	}
-
-	return ret;
-}
-
-void
-nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
-{
-	BUG_ON(handler != NULL);
-	if (*ref) {
-		nouveau_event_fini(*ref);
-		kfree(*ref);
 	}
-	*ref = handler;
 }
 
 void
-nouveau_event_trigger(struct nouveau_event *event, u32 types, int index)
+nvkm_event_send(struct nvkm_event *event, u32 types, int index,
+		void *data, u32 size)
 {
-	struct nouveau_eventh *handler;
+	struct nvkm_notify *notify;
 	unsigned long flags;
 
-	if (WARN_ON(index >= event->index_nr))
+	if (!event->refs || WARN_ON(index >= event->index_nr))
 		return;
 
 	spin_lock_irqsave(&event->list_lock, flags);
-	list_for_each_entry(handler, &event->list[index], head) {
-		if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags))
-			continue;
-		if (!(handler->types & types))
-			continue;
-		if (handler->func(handler->priv, handler->types & types, index)
-				!= NVKM_EVENT_DROP)
-			continue;
-		nouveau_event_put(handler);
+	list_for_each_entry(notify, &event->list, head) {
+		if (notify->index == index && (notify->types & types)) {
+			if (event->func->send) {
+				event->func->send(data, size, notify);
+				continue;
+			}
+			nvkm_notify_send(notify, data, size);
+		}
 	}
 	spin_unlock_irqrestore(&event->list_lock, flags);
 }
 
 void
-nouveau_event_destroy(struct nouveau_event **pevent)
+nvkm_event_fini(struct nvkm_event *event)
 {
-	struct nouveau_event *event = *pevent;
-	if (event) {
-		kfree(event);
-		*pevent = NULL;
+	if (event->refs) {
+		kfree(event->refs);
+		event->refs = NULL;
 	}
 }
 
 int
-nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent)
+nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
+		struct nvkm_event *event)
 {
-	struct nouveau_event *event;
-	int i;
-
-	event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) *
-				  sizeof(event->refs[0]), GFP_KERNEL);
-	if (!event)
-		return -ENOMEM;
-
-	event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL);
-	if (!event->list) {
-		kfree(event);
+	event->refs = kzalloc(sizeof(*event->refs) * index_nr * types_nr,
+			      GFP_KERNEL);
+	if (!event->refs)
 		return -ENOMEM;
-	}
 
-	spin_lock_init(&event->list_lock);
-	spin_lock_init(&event->refs_lock);
-	for (i = 0; i < index_nr; i++)
-		INIT_LIST_HEAD(&event->list[i]);
+	event->func = func;
 	event->types_nr = types_nr;
 	event->index_nr = index_nr;
+	spin_lock_init(&event->refs_lock);
+	spin_lock_init(&event->list_lock);
+	INIT_LIST_HEAD(&event->list);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/handle.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/handle.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/handle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/handle.c	2014-09-28 17:29:07.000000000 -0400
@@ -146,9 +146,7 @@ nouveau_handle_create(struct nouveau_obj
 	}
 
 	hprintk(handle, TRACE, "created\n");
-
 	*phandle = handle;
-
 	return 0;
 }
 
@@ -224,3 +222,116 @@ nouveau_handle_put(struct nouveau_handle
 	if (handle)
 		nouveau_namedb_put(handle);
 }
+
+int
+nouveau_handle_new(struct nouveau_object *client, u32 _parent, u32 _handle,
+		   u16 _oclass, void *data, u32 size,
+		   struct nouveau_object **pobject)
+{
+	struct nouveau_object *parent = NULL;
+	struct nouveau_object *engctx = NULL;
+	struct nouveau_object *object = NULL;
+	struct nouveau_object *engine;
+	struct nouveau_oclass *oclass;
+	struct nouveau_handle *handle;
+	int ret;
+
+	/* lookup parent object and ensure it *is* a parent */
+	parent = nouveau_handle_ref(client, _parent);
+	if (!parent) {
+		nv_error(client, "parent 0x%08x not found\n", _parent);
+		return -ENOENT;
+	}
+
+	if (!nv_iclass(parent, NV_PARENT_CLASS)) {
+		nv_error(parent, "cannot have children\n");
+		ret = -EINVAL;
+		goto fail_class;
+	}
+
+	/* check that parent supports the requested subclass */
+	ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
+	if (ret) {
+		nv_debug(parent, "illegal class 0x%04x\n", _oclass);
+		goto fail_class;
+	}
+
+	/* make sure engine init has been completed *before* any objects
+	 * it controls are created - the constructors may depend on
+	 * state calculated at init (ie. default context construction)
+	 */
+	if (engine) {
+		ret = nouveau_object_inc(engine);
+		if (ret)
+			goto fail_class;
+	}
+
+	/* if engine requires it, create a context object to insert
+	 * between the parent and its children (eg. PGRAPH context)
+	 */
+	if (engine && nv_engine(engine)->cclass) {
+		ret = nouveau_object_ctor(parent, engine,
+					  nv_engine(engine)->cclass,
+					  data, size, &engctx);
+		if (ret)
+			goto fail_engctx;
+	} else {
+		nouveau_object_ref(parent, &engctx);
+	}
+
+	/* finally, create new object and bind it to its handle */
+	ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
+	*pobject = object;
+	if (ret)
+		goto fail_ctor;
+
+	ret = nouveau_object_inc(object);
+	if (ret)
+		goto fail_init;
+
+	ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
+	if (ret)
+		goto fail_handle;
+
+	ret = nouveau_handle_init(handle);
+	if (ret)
+		nouveau_handle_destroy(handle);
+
+fail_handle:
+	nouveau_object_dec(object, false);
+fail_init:
+	nouveau_object_ref(NULL, &object);
+fail_ctor:
+	nouveau_object_ref(NULL, &engctx);
+fail_engctx:
+	if (engine)
+		nouveau_object_dec(engine, false);
+fail_class:
+	nouveau_object_ref(NULL, &parent);
+	return ret;
+}
+
+int
+nouveau_handle_del(struct nouveau_object *client, u32 _parent, u32 _handle)
+{
+	struct nouveau_object *parent = NULL;
+	struct nouveau_object *namedb = NULL;
+	struct nouveau_handle *handle = NULL;
+
+	parent = nouveau_handle_ref(client, _parent);
+	if (!parent)
+		return -ENOENT;
+
+	namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
+	if (namedb) {
+		handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
+		if (handle) {
+			nouveau_namedb_put(handle);
+			nouveau_handle_fini(handle, false);
+			nouveau_handle_destroy(handle);
+		}
+	}
+
+	nouveau_object_ref(NULL, &parent);
+	return handle ? 0 : -EINVAL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/ioctl.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/ioctl.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/ioctl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2014 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 <core/object.h>
+#include <core/parent.h>
+#include <core/handle.h>
+#include <core/namedb.h>
+#include <core/client.h>
+#include <core/device.h>
+#include <core/ioctl.h>
+#include <core/event.h>
+
+#include <nvif/unpack.h>
+#include <nvif/ioctl.h>
+
+static int
+nvkm_ioctl_nop(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_nop none;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "nop size %d\n", size);
+	if (nvif_unvers(args->none)) {
+		nv_ioctl(object, "nop\n");
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_sclass(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_sclass_v0 v0;
+	} *args = data;
+	int ret;
+
+	if (!nv_iclass(object, NV_PARENT_CLASS)) {
+		nv_debug(object, "cannot have children (sclass)\n");
+		return -ENODEV;
+	}
+
+	nv_ioctl(object, "sclass size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "sclass vers %d count %d\n",
+			 args->v0.version, args->v0.count);
+		if (size == args->v0.count * sizeof(args->v0.oclass[0])) {
+			ret = nouveau_parent_lclass(object, args->v0.oclass,
+							    args->v0.count);
+			if (ret >= 0) {
+				args->v0.count = ret;
+				ret = 0;
+			}
+		} else {
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_new(struct nouveau_handle *parent, void *data, u32 size)
+{
+	union {
+		struct nvif_ioctl_new_v0 v0;
+	} *args = data;
+	struct nouveau_client *client = nouveau_client(parent->object);
+	struct nouveau_object *engctx = NULL;
+	struct nouveau_object *object = NULL;
+	struct nouveau_object *engine;
+	struct nouveau_oclass *oclass;
+	struct nouveau_handle *handle;
+	u32 _handle, _oclass;
+	int ret;
+
+	nv_ioctl(client, "new size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		_handle = args->v0.handle;
+		_oclass = args->v0.oclass;
+	} else
+		return ret;
+
+	nv_ioctl(client, "new vers %d handle %08x class %08x "
+			 "route %02x token %llx\n",
+		args->v0.version, _handle, _oclass,
+		args->v0.route, args->v0.token);
+
+	if (!nv_iclass(parent->object, NV_PARENT_CLASS)) {
+		nv_debug(parent->object, "cannot have children (ctor)\n");
+		ret = -ENODEV;
+		goto fail_class;
+	}
+
+	/* check that parent supports the requested subclass */
+	ret = nouveau_parent_sclass(parent->object, _oclass, &engine, &oclass);
+	if (ret) {
+		nv_debug(parent->object, "illegal class 0x%04x\n", _oclass);
+		goto fail_class;
+	}
+
+	/* make sure engine init has been completed *before* any objects
+	 * it controls are created - the constructors may depend on
+	 * state calculated at init (ie. default context construction)
+	 */
+	if (engine) {
+		ret = nouveau_object_inc(engine);
+		if (ret)
+			goto fail_class;
+	}
+
+	/* if engine requires it, create a context object to insert
+	 * between the parent and its children (eg. PGRAPH context)
+	 */
+	if (engine && nv_engine(engine)->cclass) {
+		ret = nouveau_object_ctor(parent->object, engine,
+					  nv_engine(engine)->cclass,
+					  data, size, &engctx);
+		if (ret)
+			goto fail_engctx;
+	} else {
+		nouveau_object_ref(parent->object, &engctx);
+	}
+
+	/* finally, create new object and bind it to its handle */
+	ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
+	client->data = object;
+	if (ret)
+		goto fail_ctor;
+
+	ret = nouveau_object_inc(object);
+	if (ret)
+		goto fail_init;
+
+	ret = nouveau_handle_create(parent->object, parent->name,
+				    _handle, object, &handle);
+	if (ret)
+		goto fail_handle;
+
+	ret = nouveau_handle_init(handle);
+	handle->route = args->v0.route;
+	handle->token = args->v0.token;
+	if (ret)
+		nouveau_handle_destroy(handle);
+
+fail_handle:
+	nouveau_object_dec(object, false);
+fail_init:
+	nouveau_object_ref(NULL, &object);
+fail_ctor:
+	nouveau_object_ref(NULL, &engctx);
+fail_engctx:
+	if (engine)
+		nouveau_object_dec(engine, false);
+fail_class:
+	return ret;
+}
+
+static int
+nvkm_ioctl_del(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_del none;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "delete size %d\n", size);
+	if (nvif_unvers(args->none)) {
+		nv_ioctl(object, "delete\n");
+		nouveau_handle_fini(handle, false);
+		nouveau_handle_destroy(handle);
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_mthd(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+	union {
+		struct nvif_ioctl_mthd_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "mthd size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "mthd vers %d mthd %02x\n",
+			 args->v0.version, args->v0.method);
+		if (ret = -ENODEV, ofuncs->mthd)
+			ret = ofuncs->mthd(object, args->v0.method, data, size);
+	}
+
+	return ret;
+}
+
+
+static int
+nvkm_ioctl_rd(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+	union {
+		struct nvif_ioctl_rd_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "rd size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "rd vers %d size %d addr %016llx\n",
+			args->v0.version, args->v0.size, args->v0.addr);
+		switch (args->v0.size) {
+		case 1:
+			if (ret = -ENODEV, ofuncs->rd08) {
+				args->v0.data = nv_ro08(object, args->v0.addr);
+				ret = 0;
+			}
+			break;
+		case 2:
+			if (ret = -ENODEV, ofuncs->rd16) {
+				args->v0.data = nv_ro16(object, args->v0.addr);
+				ret = 0;
+			}
+			break;
+		case 4:
+			if (ret = -ENODEV, ofuncs->rd32) {
+				args->v0.data = nv_ro32(object, args->v0.addr);
+				ret = 0;
+			}
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_wr(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+	union {
+		struct nvif_ioctl_wr_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "wr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "wr vers %d size %d addr %016llx data %08x\n",
+			 args->v0.version, args->v0.size, args->v0.addr,
+			 args->v0.data);
+		switch (args->v0.size) {
+		case 1:
+			if (ret = -ENODEV, ofuncs->wr08) {
+				nv_wo08(object, args->v0.addr, args->v0.data);
+				ret = 0;
+			}
+			break;
+		case 2:
+			if (ret = -ENODEV, ofuncs->wr16) {
+				nv_wo16(object, args->v0.addr, args->v0.data);
+				ret = 0;
+			}
+			break;
+		case 4:
+			if (ret = -ENODEV, ofuncs->wr32) {
+				nv_wo32(object, args->v0.addr, args->v0.data);
+				ret = 0;
+			}
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_map(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+	union {
+		struct nvif_ioctl_map_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "map size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "map vers %d\n", args->v0.version);
+		if (ret = -ENODEV, ofuncs->map) {
+			ret = ofuncs->map(object, &args->v0.handle,
+						  &args->v0.length);
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_unmap(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_unmap none;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "unmap size %d\n", size);
+	if (nvif_unvers(args->none)) {
+		nv_ioctl(object, "unmap\n");
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_new(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_client *client = nouveau_client(handle->object);
+	struct nouveau_object *object = handle->object;
+	struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+	union {
+		struct nvif_ioctl_ntfy_new_v0 v0;
+	} *args = data;
+	struct nvkm_event *event;
+	int ret;
+
+	nv_ioctl(object, "ntfy new size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "ntfy new vers %d event %02x\n",
+			 args->v0.version, args->v0.event);
+		if (ret = -ENODEV, ofuncs->ntfy)
+			ret = ofuncs->ntfy(object, args->v0.event, &event);
+		if (ret == 0) {
+			ret = nvkm_client_notify_new(client, event, data, size);
+			if (ret >= 0) {
+				args->v0.index = ret;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_del(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_client *client = nouveau_client(handle->object);
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_ntfy_del_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "ntfy del size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "ntfy del vers %d index %d\n",
+			 args->v0.version, args->v0.index);
+		ret = nvkm_client_notify_del(client, args->v0.index);
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_get(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_client *client = nouveau_client(handle->object);
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_ntfy_get_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "ntfy get size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "ntfy get vers %d index %d\n",
+			 args->v0.version, args->v0.index);
+		ret = nvkm_client_notify_get(client, args->v0.index);
+	}
+
+	return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_put(struct nouveau_handle *handle, void *data, u32 size)
+{
+	struct nouveau_client *client = nouveau_client(handle->object);
+	struct nouveau_object *object = handle->object;
+	union {
+		struct nvif_ioctl_ntfy_put_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "ntfy put size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "ntfy put vers %d index %d\n",
+			 args->v0.version, args->v0.index);
+		ret = nvkm_client_notify_put(client, args->v0.index);
+	}
+
+	return ret;
+}
+
+static struct {
+	int version;
+	int (*func)(struct nouveau_handle *, void *, u32);
+}
+nvkm_ioctl_v0[] = {
+	{ 0x00, nvkm_ioctl_nop },
+	{ 0x00, nvkm_ioctl_sclass },
+	{ 0x00, nvkm_ioctl_new },
+	{ 0x00, nvkm_ioctl_del },
+	{ 0x00, nvkm_ioctl_mthd },
+	{ 0x00, nvkm_ioctl_rd },
+	{ 0x00, nvkm_ioctl_wr },
+	{ 0x00, nvkm_ioctl_map },
+	{ 0x00, nvkm_ioctl_unmap },
+	{ 0x00, nvkm_ioctl_ntfy_new },
+	{ 0x00, nvkm_ioctl_ntfy_del },
+	{ 0x00, nvkm_ioctl_ntfy_get },
+	{ 0x00, nvkm_ioctl_ntfy_put },
+};
+
+static int
+nvkm_ioctl_path(struct nouveau_handle *parent, u32 type, u32 nr,
+		  u32 *path, void *data, u32 size,
+		  u8 owner, u8 *route, u64 *token)
+{
+	struct nouveau_handle *handle = parent;
+	struct nouveau_namedb *namedb;
+	struct nouveau_object *object;
+	int ret;
+
+	while ((object = parent->object), nr--) {
+		nv_ioctl(object, "path 0x%08x\n", path[nr]);
+		if (!nv_iclass(object, NV_PARENT_CLASS)) {
+			nv_debug(object, "cannot have children (path)\n");
+			return -EINVAL;
+		}
+
+		if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) ||
+		    !(handle = nouveau_namedb_get(namedb, path[nr]))) {
+			nv_debug(object, "handle 0x%08x not found\n", path[nr]);
+			return -ENOENT;
+		}
+		nouveau_namedb_put(handle);
+		parent = handle;
+	}
+
+	if (owner != NVIF_IOCTL_V0_OWNER_ANY &&
+	    owner != handle->route) {
+		nv_ioctl(object, "object route != owner\n");
+		return -EACCES;
+	}
+	*route = handle->route;
+	*token = handle->token;
+
+	if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {
+		if (nvkm_ioctl_v0[type].version == 0) {
+			ret = nvkm_ioctl_v0[type].func(handle, data, size);
+		}
+	}
+
+	return ret;
+}
+
+int
+nvkm_ioctl(struct nouveau_client *client, bool supervisor,
+	   void *data, u32 size, void **hack)
+{
+	union {
+		struct nvif_ioctl_v0 v0;
+	} *args = data;
+	int ret;
+
+	client->super = supervisor;
+	nv_ioctl(client, "size %d\n", size);
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(client, "vers %d type %02x path %d owner %02x\n",
+			 args->v0.version, args->v0.type, args->v0.path_nr,
+			 args->v0.owner);
+		ret = nvkm_ioctl_path(client->root, args->v0.type,
+				      args->v0.path_nr, args->v0.path,
+				      data, size, args->v0.owner,
+				     &args->v0.route, &args->v0.token);
+	}
+
+	nv_ioctl(client, "return %d\n", ret);
+	if (hack) {
+		*hack = client->data;
+		client->data = NULL;
+	}
+	client->super = false;
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/notify.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/notify.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/notify.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/notify.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 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 <core/client.h>
+#include <core/event.h>
+#include <core/notify.h>
+
+#include <nvif/unpack.h>
+#include <nvif/event.h>
+
+static inline void
+nvkm_notify_put_locked(struct nvkm_notify *notify)
+{
+	if (notify->block++ == 0)
+		nvkm_event_put(notify->event, notify->types, notify->index);
+}
+
+void
+nvkm_notify_put(struct nvkm_notify *notify)
+{
+	struct nvkm_event *event = notify->event;
+	unsigned long flags;
+	if (likely(event) &&
+	    test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+		spin_lock_irqsave(&event->refs_lock, flags);
+		nvkm_notify_put_locked(notify);
+		spin_unlock_irqrestore(&event->refs_lock, flags);
+		if (test_bit(NVKM_NOTIFY_WORK, &notify->flags))
+			flush_work(&notify->work);
+	}
+}
+
+static inline void
+nvkm_notify_get_locked(struct nvkm_notify *notify)
+{
+	if (--notify->block == 0)
+		nvkm_event_get(notify->event, notify->types, notify->index);
+}
+
+void
+nvkm_notify_get(struct nvkm_notify *notify)
+{
+	struct nvkm_event *event = notify->event;
+	unsigned long flags;
+	if (likely(event) &&
+	    !test_and_set_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+		spin_lock_irqsave(&event->refs_lock, flags);
+		nvkm_notify_get_locked(notify);
+		spin_unlock_irqrestore(&event->refs_lock, flags);
+	}
+}
+
+static inline void
+nvkm_notify_func(struct nvkm_notify *notify)
+{
+	struct nvkm_event *event = notify->event;
+	int ret = notify->func(notify);
+	unsigned long flags;
+	if ((ret == NVKM_NOTIFY_KEEP) ||
+	    !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+		spin_lock_irqsave(&event->refs_lock, flags);
+		nvkm_notify_get_locked(notify);
+		spin_unlock_irqrestore(&event->refs_lock, flags);
+	}
+}
+
+static void
+nvkm_notify_work(struct work_struct *work)
+{
+	struct nvkm_notify *notify = container_of(work, typeof(*notify), work);
+	nvkm_notify_func(notify);
+}
+
+void
+nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size)
+{
+	struct nvkm_event *event = notify->event;
+	unsigned long flags;
+
+	BUG_ON(!spin_is_locked(&event->list_lock));
+	BUG_ON(size != notify->size);
+
+	spin_lock_irqsave(&event->refs_lock, flags);
+	if (notify->block) {
+		spin_unlock_irqrestore(&event->refs_lock, flags);
+		return;
+	}
+	nvkm_notify_put_locked(notify);
+	spin_unlock_irqrestore(&event->refs_lock, flags);
+
+	if (test_bit(NVKM_NOTIFY_WORK, &notify->flags)) {
+		memcpy((void *)notify->data, data, size);
+		schedule_work(&notify->work);
+	} else {
+		notify->data = data;
+		nvkm_notify_func(notify);
+		notify->data = NULL;
+	}
+}
+
+void
+nvkm_notify_fini(struct nvkm_notify *notify)
+{
+	unsigned long flags;
+	if (notify->event) {
+		nvkm_notify_put(notify);
+		spin_lock_irqsave(&notify->event->list_lock, flags);
+		list_del(&notify->head);
+		spin_unlock_irqrestore(&notify->event->list_lock, flags);
+		kfree((void *)notify->data);
+		notify->event = NULL;
+	}
+}
+
+int
+nvkm_notify_init(struct nvkm_event *event, int (*func)(struct nvkm_notify *),
+		 bool work, void *data, u32 size, u32 reply,
+		 struct nvkm_notify *notify)
+{
+	unsigned long flags;
+	int ret = -ENODEV;
+	if ((notify->event = event), event->refs) {
+		ret = event->func->ctor(data, size, notify);
+		if (ret == 0 && (ret = -EINVAL, notify->size == reply)) {
+			notify->flags = 0;
+			notify->block = 1;
+			notify->func = func;
+			notify->data = NULL;
+			if (ret = 0, work) {
+				INIT_WORK(&notify->work, nvkm_notify_work);
+				set_bit(NVKM_NOTIFY_WORK, &notify->flags);
+				notify->data = kmalloc(reply, GFP_KERNEL);
+				if (!notify->data)
+					ret = -ENOMEM;
+			}
+		}
+		if (ret == 0) {
+			spin_lock_irqsave(&event->list_lock, flags);
+			list_add_tail(&notify->head, &event->list);
+			spin_unlock_irqrestore(&event->list_lock, flags);
+		}
+	}
+	if (ret)
+		notify->event = NULL;
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/object.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/object.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/object.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,9 +23,6 @@
  */
 
 #include <core/object.h>
-#include <core/parent.h>
-#include <core/namedb.h>
-#include <core/handle.h>
 #include <core/engine.h>
 
 #ifdef NOUVEAU_OBJECT_MAGIC
@@ -61,21 +58,15 @@ nouveau_object_create_(struct nouveau_ob
 	return 0;
 }
 
-static int
+int
 _nouveau_object_ctor(struct nouveau_object *parent,
 		     struct nouveau_object *engine,
 		     struct nouveau_oclass *oclass, void *data, u32 size,
 		     struct nouveau_object **pobject)
 {
-	struct nouveau_object *object;
-	int ret;
-
-	ret = nouveau_object_create(parent, engine, oclass, 0, &object);
-	*pobject = nv_object(object);
-	if (ret)
-		return ret;
-
-	return 0;
+	if (size != 0)
+		return -ENOSYS;
+	return nouveau_object_create(parent, engine, oclass, 0, pobject);
 }
 
 void
@@ -91,42 +82,24 @@ nouveau_object_destroy(struct nouveau_ob
 	kfree(object);
 }
 
-static void
-_nouveau_object_dtor(struct nouveau_object *object)
-{
-	nouveau_object_destroy(object);
-}
-
 int
 nouveau_object_init(struct nouveau_object *object)
 {
 	return 0;
 }
 
-static int
-_nouveau_object_init(struct nouveau_object *object)
-{
-	return nouveau_object_init(object);
-}
-
 int
 nouveau_object_fini(struct nouveau_object *object, bool suspend)
 {
 	return 0;
 }
 
-static int
-_nouveau_object_fini(struct nouveau_object *object, bool suspend)
-{
-	return nouveau_object_fini(object, suspend);
-}
-
 struct nouveau_ofuncs
 nouveau_object_ofuncs = {
 	.ctor = _nouveau_object_ctor,
-	.dtor = _nouveau_object_dtor,
-	.init = _nouveau_object_init,
-	.fini = _nouveau_object_fini,
+	.dtor = nouveau_object_destroy,
+	.init = nouveau_object_init,
+	.fini = nouveau_object_fini,
 };
 
 int
@@ -189,119 +162,6 @@ nouveau_object_ref(struct nouveau_object
 }
 
 int
-nouveau_object_new(struct nouveau_object *client, u32 _parent, u32 _handle,
-		   u16 _oclass, void *data, u32 size,
-		   struct nouveau_object **pobject)
-{
-	struct nouveau_object *parent = NULL;
-	struct nouveau_object *engctx = NULL;
-	struct nouveau_object *object = NULL;
-	struct nouveau_object *engine;
-	struct nouveau_oclass *oclass;
-	struct nouveau_handle *handle;
-	int ret;
-
-	/* lookup parent object and ensure it *is* a parent */
-	parent = nouveau_handle_ref(client, _parent);
-	if (!parent) {
-		nv_error(client, "parent 0x%08x not found\n", _parent);
-		return -ENOENT;
-	}
-
-	if (!nv_iclass(parent, NV_PARENT_CLASS)) {
-		nv_error(parent, "cannot have children\n");
-		ret = -EINVAL;
-		goto fail_class;
-	}
-
-	/* check that parent supports the requested subclass */
-	ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
-	if (ret) {
-		nv_debug(parent, "illegal class 0x%04x\n", _oclass);
-		goto fail_class;
-	}
-
-	/* make sure engine init has been completed *before* any objects
-	 * it controls are created - the constructors may depend on
-	 * state calculated at init (ie. default context construction)
-	 */
-	if (engine) {
-		ret = nouveau_object_inc(engine);
-		if (ret)
-			goto fail_class;
-	}
-
-	/* if engine requires it, create a context object to insert
-	 * between the parent and its children (eg. PGRAPH context)
-	 */
-	if (engine && nv_engine(engine)->cclass) {
-		ret = nouveau_object_ctor(parent, engine,
-					  nv_engine(engine)->cclass,
-					  data, size, &engctx);
-		if (ret)
-			goto fail_engctx;
-	} else {
-		nouveau_object_ref(parent, &engctx);
-	}
-
-	/* finally, create new object and bind it to its handle */
-	ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
-	*pobject = object;
-	if (ret)
-		goto fail_ctor;
-
-	ret = nouveau_object_inc(object);
-	if (ret)
-		goto fail_init;
-
-	ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
-	if (ret)
-		goto fail_handle;
-
-	ret = nouveau_handle_init(handle);
-	if (ret)
-		nouveau_handle_destroy(handle);
-
-fail_handle:
-	nouveau_object_dec(object, false);
-fail_init:
-	nouveau_object_ref(NULL, &object);
-fail_ctor:
-	nouveau_object_ref(NULL, &engctx);
-fail_engctx:
-	if (engine)
-		nouveau_object_dec(engine, false);
-fail_class:
-	nouveau_object_ref(NULL, &parent);
-	return ret;
-}
-
-int
-nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
-{
-	struct nouveau_object *parent = NULL;
-	struct nouveau_object *namedb = NULL;
-	struct nouveau_handle *handle = NULL;
-
-	parent = nouveau_handle_ref(client, _parent);
-	if (!parent)
-		return -ENOENT;
-
-	namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
-	if (namedb) {
-		handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
-		if (handle) {
-			nouveau_namedb_put(handle);
-			nouveau_handle_fini(handle, false);
-			nouveau_handle_destroy(handle);
-		}
-	}
-
-	nouveau_object_ref(NULL, &parent);
-	return handle ? 0 : -EINVAL;
-}
-
-int
 nouveau_object_inc(struct nouveau_object *object)
 {
 	int ref = atomic_add_return(1, &object->usecount);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/parent.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/parent.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/core/parent.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/core/parent.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,6 +75,39 @@ nouveau_parent_sclass(struct nouveau_obj
 }
 
 int
+nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
+{
+	struct nouveau_sclass *sclass;
+	struct nouveau_engine *engine;
+	struct nouveau_oclass *oclass;
+	int nr = -1, i;
+	u64 mask;
+
+	sclass = nv_parent(parent)->sclass;
+	while (sclass) {
+		if (++nr < size)
+			lclass[nr] = sclass->oclass->handle & 0xffff;
+		sclass = sclass->sclass;
+	}
+
+	mask = nv_parent(parent)->engine;
+	while (i = __ffs64(mask), mask) {
+		engine = nouveau_engine(parent, i);
+		if (engine && (oclass = engine->sclass)) {
+			while (oclass->ofuncs) {
+				if (++nr < size)
+					lclass[nr] = oclass->handle & 0xffff;
+				oclass++;
+			}
+		}
+
+		mask &= ~(1ULL << i);
+	}
+
+	return nr + 1;
+}
+
+int
 nouveau_parent_create_(struct nouveau_object *parent,
 		       struct nouveau_object *engine,
 		       struct nouveau_oclass *oclass, u32 pclass,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,6 @@
 #include <subdev/vm.h>
 
 #include <core/client.h>
-#include <core/class.h>
 #include <core/enum.h>
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,9 +26,7 @@
 #include <engine/fifo.h>
 #include <engine/copy.h>
 
-#include <core/class.h>
 #include <core/enum.h>
-#include <core/class.h>
 #include <core/enum.h>
 
 #include "fuc/nvc0.fuc.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 
 #include <core/os.h>
 #include <core/enum.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <engine/copy.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,6 @@
 #include <core/client.h>
 #include <core/os.h>
 #include <core/enum.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/gpuobj.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,6 @@
 #include <core/client.h>
 #include <core/os.h>
 #include <core/enum.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <subdev/timer.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 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 "acpi.h"
+
+#ifdef CONFIG_ACPI
+static int
+nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct nouveau_device *device =
+		container_of(nb, typeof(*device), acpi.nb);
+	struct acpi_bus_event *info = data;
+
+	if (!strcmp(info->device_class, "ac_adapter"))
+		nvkm_event_send(&device->event, 1, 0, NULL, 0);
+
+	return NOTIFY_DONE;
+}
+#endif
+
+int
+nvkm_acpi_fini(struct nouveau_device *device, bool suspend)
+{
+#ifdef CONFIG_ACPI
+	unregister_acpi_notifier(&device->acpi.nb);
+#endif
+	return 0;
+}
+
+int
+nvkm_acpi_init(struct nouveau_device *device)
+{
+#ifdef CONFIG_ACPI
+	device->acpi.nb.notifier_call = nvkm_acpi_ntfy;
+	register_acpi_notifier(&device->acpi.nb);
+#endif
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/acpi.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef __NVKM_DEVICE_ACPI_H__
+#define __NVKM_DEVICE_ACPI_H__
+
+#include <engine/device.h>
+
+int nvkm_acpi_init(struct nouveau_device *);
+int nvkm_acpi_fini(struct nouveau_device *, bool);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,10 +26,14 @@
 #include <core/device.h>
 #include <core/client.h>
 #include <core/option.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
-#include <core/class.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
 
 #include "priv.h"
+#include "acpi.h"
 
 static DEFINE_MUTEX(nv_devices_mutex);
 static LIST_HEAD(nv_devices);
@@ -49,74 +53,258 @@ nouveau_device_find(u64 name)
 	return match;
 }
 
+int
+nouveau_device_list(u64 *name, int size)
+{
+	struct nouveau_device *device;
+	int nr = 0;
+	mutex_lock(&nv_devices_mutex);
+	list_for_each_entry(device, &nv_devices, head) {
+		if (nr++ < size)
+			name[nr - 1] = device->handle;
+	}
+	mutex_unlock(&nv_devices_mutex);
+	return nr;
+}
+
 /******************************************************************************
  * nouveau_devobj (0x0080): class implementation
  *****************************************************************************/
+
 struct nouveau_devobj {
 	struct nouveau_parent base;
 	struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
 };
 
+static int
+nouveau_devobj_info(struct nouveau_object *object, void *data, u32 size)
+{
+	struct nouveau_device *device = nv_device(object);
+	struct nouveau_fb *pfb = nouveau_fb(device);
+	struct nouveau_instmem *imem = nouveau_instmem(device);
+	union {
+		struct nv_device_info_v0 v0;
+	} *args = data;
+	int ret;
+
+	nv_ioctl(object, "device info size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "device info vers %d\n", args->v0.version);
+	} else
+		return ret;
+
+	switch (device->chipset) {
+	case 0x01a:
+	case 0x01f:
+	case 0x04c:
+	case 0x04e:
+	case 0x063:
+	case 0x067:
+	case 0x068:
+	case 0x0aa:
+	case 0x0ac:
+	case 0x0af:
+		args->v0.platform = NV_DEVICE_INFO_V0_IGP;
+		break;
+	default:
+		if (device->pdev) {
+			if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP))
+				args->v0.platform = NV_DEVICE_INFO_V0_AGP;
+			else
+			if (pci_is_pcie(device->pdev))
+				args->v0.platform = NV_DEVICE_INFO_V0_PCIE;
+			else
+				args->v0.platform = NV_DEVICE_INFO_V0_PCI;
+		} else {
+			args->v0.platform = NV_DEVICE_INFO_V0_SOC;
+		}
+		break;
+	}
+
+	switch (device->card_type) {
+	case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break;
+	case NV_10:
+	case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break;
+	case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break;
+	case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break;
+	case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break;
+	case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break;
+	case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break;
+	case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break;
+	case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
+	default:
+		args->v0.family = 0;
+		break;
+	}
+
+	args->v0.chipset  = device->chipset;
+	args->v0.revision = device->chipset >= 0x10 ? nv_rd32(device, 0) : 0x00;
+	if (pfb)  args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
+	else      args->v0.ram_size = args->v0.ram_user = 0;
+	if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved;
+	return 0;
+}
+
+static int
+nouveau_devobj_mthd(struct nouveau_object *object, u32 mthd,
+		    void *data, u32 size)
+{
+	switch (mthd) {
+	case NV_DEVICE_V0_INFO:
+		return nouveau_devobj_info(object, data, size);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static u8
+nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
+{
+	return nv_rd08(object->engine, addr);
+}
+
+static u16
+nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
+{
+	return nv_rd16(object->engine, addr);
+}
+
+static u32
+nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
+{
+	return nv_rd32(object->engine, addr);
+}
+
+static void
+nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
+{
+	nv_wr08(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
+{
+	nv_wr16(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+	nv_wr32(object->engine, addr, data);
+}
+
+static int
+nouveau_devobj_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+	struct nouveau_device *device = nv_device(object);
+	*addr = nv_device_resource_start(device, 0);
+	*size = nv_device_resource_len(device, 0);
+	return 0;
+}
+
 static const u64 disable_map[] = {
-	[NVDEV_SUBDEV_VBIOS]	= NV_DEVICE_DISABLE_VBIOS,
-	[NVDEV_SUBDEV_DEVINIT]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_GPIO]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_I2C]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_CLOCK]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_MXM]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_MC]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_BUS]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_TIMER]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_FB]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_LTCG]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_IBUS]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_INSTMEM]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_VM]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_BAR]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_VOLT]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_THERM]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_SUBDEV_PWR]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_ENGINE_DMAOBJ]	= NV_DEVICE_DISABLE_CORE,
-	[NVDEV_ENGINE_PERFMON]  = NV_DEVICE_DISABLE_CORE,
-	[NVDEV_ENGINE_FIFO]	= NV_DEVICE_DISABLE_FIFO,
-	[NVDEV_ENGINE_SW]	= NV_DEVICE_DISABLE_FIFO,
-	[NVDEV_ENGINE_GR]	= NV_DEVICE_DISABLE_GRAPH,
-	[NVDEV_ENGINE_MPEG]	= NV_DEVICE_DISABLE_MPEG,
-	[NVDEV_ENGINE_ME]	= NV_DEVICE_DISABLE_ME,
-	[NVDEV_ENGINE_VP]	= NV_DEVICE_DISABLE_VP,
-	[NVDEV_ENGINE_CRYPT]	= NV_DEVICE_DISABLE_CRYPT,
-	[NVDEV_ENGINE_BSP]	= NV_DEVICE_DISABLE_BSP,
-	[NVDEV_ENGINE_PPP]	= NV_DEVICE_DISABLE_PPP,
-	[NVDEV_ENGINE_COPY0]	= NV_DEVICE_DISABLE_COPY0,
-	[NVDEV_ENGINE_COPY1]	= NV_DEVICE_DISABLE_COPY1,
-	[NVDEV_ENGINE_VIC]	= NV_DEVICE_DISABLE_VIC,
-	[NVDEV_ENGINE_VENC]	= NV_DEVICE_DISABLE_VENC,
-	[NVDEV_ENGINE_DISP]	= NV_DEVICE_DISABLE_DISP,
+	[NVDEV_SUBDEV_VBIOS]	= NV_DEVICE_V0_DISABLE_VBIOS,
+	[NVDEV_SUBDEV_DEVINIT]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_GPIO]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_I2C]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_CLOCK]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_MXM]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_MC]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_BUS]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_TIMER]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_FB]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_LTC]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_IBUS]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_INSTMEM]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_VM]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_BAR]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_VOLT]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_THERM]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_SUBDEV_PWR]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_ENGINE_DMAOBJ]	= NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_ENGINE_PERFMON]  = NV_DEVICE_V0_DISABLE_CORE,
+	[NVDEV_ENGINE_FIFO]	= NV_DEVICE_V0_DISABLE_FIFO,
+	[NVDEV_ENGINE_SW]	= NV_DEVICE_V0_DISABLE_FIFO,
+	[NVDEV_ENGINE_GR]	= NV_DEVICE_V0_DISABLE_GRAPH,
+	[NVDEV_ENGINE_MPEG]	= NV_DEVICE_V0_DISABLE_MPEG,
+	[NVDEV_ENGINE_ME]	= NV_DEVICE_V0_DISABLE_ME,
+	[NVDEV_ENGINE_VP]	= NV_DEVICE_V0_DISABLE_VP,
+	[NVDEV_ENGINE_CRYPT]	= NV_DEVICE_V0_DISABLE_CRYPT,
+	[NVDEV_ENGINE_BSP]	= NV_DEVICE_V0_DISABLE_BSP,
+	[NVDEV_ENGINE_PPP]	= NV_DEVICE_V0_DISABLE_PPP,
+	[NVDEV_ENGINE_COPY0]	= NV_DEVICE_V0_DISABLE_COPY0,
+	[NVDEV_ENGINE_COPY1]	= NV_DEVICE_V0_DISABLE_COPY1,
+	[NVDEV_ENGINE_VIC]	= NV_DEVICE_V0_DISABLE_VIC,
+	[NVDEV_ENGINE_VENC]	= NV_DEVICE_V0_DISABLE_VENC,
+	[NVDEV_ENGINE_DISP]	= NV_DEVICE_V0_DISABLE_DISP,
 	[NVDEV_SUBDEV_NR]	= 0,
 };
 
+static void
+nouveau_devobj_dtor(struct nouveau_object *object)
+{
+	struct nouveau_devobj *devobj = (void *)object;
+	int i;
+
+	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
+		nouveau_object_ref(NULL, &devobj->subdev[i]);
+
+	nouveau_parent_destroy(&devobj->base);
+}
+
+static struct nouveau_oclass
+nouveau_devobj_oclass_super = {
+	.handle = NV_DEVICE,
+	.ofuncs = &(struct nouveau_ofuncs) {
+		.dtor = nouveau_devobj_dtor,
+		.init = _nouveau_parent_init,
+		.fini = _nouveau_parent_fini,
+		.mthd = nouveau_devobj_mthd,
+		.map  = nouveau_devobj_map,
+		.rd08 = nouveau_devobj_rd08,
+		.rd16 = nouveau_devobj_rd16,
+		.rd32 = nouveau_devobj_rd32,
+		.wr08 = nouveau_devobj_wr08,
+		.wr16 = nouveau_devobj_wr16,
+		.wr32 = nouveau_devobj_wr32,
+	}
+};
+
 static int
 nouveau_devobj_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv_device_v0 v0;
+	} *args = data;
 	struct nouveau_client *client = nv_client(parent);
 	struct nouveau_device *device;
 	struct nouveau_devobj *devobj;
-	struct nv_device_class *args = data;
 	u32 boot0, strap;
 	u64 disable, mmio_base, mmio_size;
 	void __iomem *map;
 	int ret, i, c;
 
-	if (size < sizeof(struct nv_device_class))
-		return -EINVAL;
+	nv_ioctl(parent, "create device size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create device v%d device %016llx "
+				 "disable %016llx debug0 %016llx\n",
+			 args->v0.version, args->v0.device,
+			 args->v0.disable, args->v0.debug0);
+	} else
+		return ret;
+
+	/* give priviledged clients register access */
+	if (client->super)
+		oclass = &nouveau_devobj_oclass_super;
 
 	/* find the device subdev that matches what the client requested */
 	device = nv_device(client->device);
-	if (args->device != ~0) {
-		device = nouveau_device_find(args->device);
+	if (args->v0.device != ~0) {
+		device = nouveau_device_find(args->v0.device);
 		if (!device)
 			return -ENODEV;
 	}
@@ -135,14 +323,14 @@ nouveau_devobj_ctor(struct nouveau_objec
 	mmio_size = nv_device_resource_len(device, 0);
 
 	/* translate api disable mask into internal mapping */
-	disable = args->debug0;
+	disable = args->v0.debug0;
 	for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
-		if (args->disable & disable_map[i])
+		if (args->v0.disable & disable_map[i])
 			disable |= (1ULL << i);
 	}
 
 	/* identify the chipset, and determine classes of subdev/engines */
-	if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
+	if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY) &&
 	    !device->card_type) {
 		map = ioremap(mmio_base, 0x102000);
 		if (map == NULL)
@@ -180,8 +368,8 @@ nouveau_devobj_ctor(struct nouveau_objec
 			case 0x080:
 			case 0x090:
 			case 0x0a0: device->card_type = NV_50; break;
-			case 0x0c0: device->card_type = NV_C0; break;
-			case 0x0d0: device->card_type = NV_D0; break;
+			case 0x0c0:
+			case 0x0d0: device->card_type = NV_C0; break;
 			case 0x0e0:
 			case 0x0f0:
 			case 0x100: device->card_type = NV_E0; break;
@@ -206,8 +394,7 @@ nouveau_devobj_ctor(struct nouveau_objec
 		case NV_30: ret = nv30_identify(device); break;
 		case NV_40: ret = nv40_identify(device); break;
 		case NV_50: ret = nv50_identify(device); break;
-		case NV_C0:
-		case NV_D0: ret = nvc0_identify(device); break;
+		case NV_C0: ret = nvc0_identify(device); break;
 		case NV_E0: ret = nve0_identify(device); break;
 		case GM100: ret = gm100_identify(device); break;
 		default:
@@ -242,7 +429,7 @@ nouveau_devobj_ctor(struct nouveau_objec
 		nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
 	}
 
-	if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
+	if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_MMIO) &&
 	    !nv_subdev(device)->mmio) {
 		nv_subdev(device)->mmio  = ioremap(mmio_base, mmio_size);
 		if (!nv_subdev(device)->mmio) {
@@ -298,71 +485,19 @@ nouveau_devobj_ctor(struct nouveau_objec
 	return 0;
 }
 
-static void
-nouveau_devobj_dtor(struct nouveau_object *object)
-{
-	struct nouveau_devobj *devobj = (void *)object;
-	int i;
-
-	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
-		nouveau_object_ref(NULL, &devobj->subdev[i]);
-
-	nouveau_parent_destroy(&devobj->base);
-}
-
-static u8
-nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
-{
-	return nv_rd08(object->engine, addr);
-}
-
-static u16
-nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
-{
-	return nv_rd16(object->engine, addr);
-}
-
-static u32
-nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
-{
-	return nv_rd32(object->engine, addr);
-}
-
-static void
-nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
-{
-	nv_wr08(object->engine, addr, data);
-}
-
-static void
-nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
-{
-	nv_wr16(object->engine, addr, data);
-}
-
-static void
-nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-	nv_wr32(object->engine, addr, data);
-}
-
 static struct nouveau_ofuncs
 nouveau_devobj_ofuncs = {
 	.ctor = nouveau_devobj_ctor,
 	.dtor = nouveau_devobj_dtor,
 	.init = _nouveau_parent_init,
 	.fini = _nouveau_parent_fini,
-	.rd08 = nouveau_devobj_rd08,
-	.rd16 = nouveau_devobj_rd16,
-	.rd32 = nouveau_devobj_rd32,
-	.wr08 = nouveau_devobj_wr08,
-	.wr16 = nouveau_devobj_wr16,
-	.wr32 = nouveau_devobj_wr32,
+	.mthd = nouveau_devobj_mthd,
 };
 
 /******************************************************************************
  * nouveau_device: engine functions
  *****************************************************************************/
+
 static struct nouveau_oclass
 nouveau_device_sclass[] = {
 	{ 0x0080, &nouveau_devobj_ofuncs },
@@ -370,6 +505,23 @@ nouveau_device_sclass[] = {
 };
 
 static int
+nouveau_device_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	if (!WARN_ON(size != 0)) {
+		notify->size  = 0;
+		notify->types = 1;
+		notify->index = 0;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static const struct nvkm_event_func
+nouveau_device_event_func = {
+	.ctor = nouveau_device_event_ctor,
+};
+
+static int
 nouveau_device_fini(struct nouveau_object *object, bool suspend)
 {
 	struct nouveau_device *device = (void *)object;
@@ -386,7 +538,7 @@ nouveau_device_fini(struct nouveau_objec
 		}
 	}
 
-	ret = 0;
+	ret = nvkm_acpi_fini(device, suspend);
 fail:
 	for (; ret && i < NVDEV_SUBDEV_NR; i++) {
 		if ((subdev = device->subdev[i])) {
@@ -407,7 +559,11 @@ nouveau_device_init(struct nouveau_objec
 {
 	struct nouveau_device *device = (void *)object;
 	struct nouveau_object *subdev;
-	int ret, i;
+	int ret, i = 0;
+
+	ret = nvkm_acpi_init(device);
+	if (ret)
+		goto fail;
 
 	for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
 		if ((subdev = device->subdev[i])) {
@@ -430,6 +586,8 @@ fail:
 		}
 	}
 
+	if (ret)
+		nvkm_acpi_fini(device, false);
 	return ret;
 }
 
@@ -438,6 +596,8 @@ nouveau_device_dtor(struct nouveau_objec
 {
 	struct nouveau_device *device = (void *)object;
 
+	nvkm_event_fini(&device->event);
+
 	mutex_lock(&nv_devices_mutex);
 	list_del(&device->head);
 	mutex_unlock(&nv_devices_mutex);
@@ -478,31 +638,6 @@ nv_device_resource_len(struct nouveau_de
 	}
 }
 
-dma_addr_t
-nv_device_map_page(struct nouveau_device *device, struct page *page)
-{
-	dma_addr_t ret;
-
-	if (nv_device_is_pci(device)) {
-		ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
-				   PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(device->pdev, ret))
-			ret = 0;
-	} else {
-		ret = page_to_phys(page);
-	}
-
-	return ret;
-}
-
-void
-nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
-{
-	if (nv_device_is_pci(device))
-		pci_unmap_page(device->pdev, addr, PAGE_SIZE,
-			       PCI_DMA_BIDIRECTIONAL);
-}
-
 int
 nv_device_get_irq(struct nouveau_device *device, bool stall)
 {
@@ -560,6 +695,9 @@ nouveau_device_create_(void *dev, enum n
 	nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
 	nv_engine(device)->sclass = nouveau_device_sclass;
 	list_add(&device->head, &nv_devices);
+
+	ret = nvkm_event_init(&nouveau_device_event_func, 1, 1,
+			      &device->event);
 done:
 	mutex_unlock(&nv_devices_mutex);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,55 +22,82 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
+#include <core/client.h>
 #include <core/object.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
 
 #include <subdev/clock.h>
 
 #include "priv.h"
 
 static int
-nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
-				void *data, u32 size)
+nouveau_control_mthd_pstate_info(struct nouveau_object *object,
+				 void *data, u32 size)
 {
+	union {
+		struct nvif_control_pstate_info_v0 v0;
+	} *args = data;
 	struct nouveau_clock *clk = nouveau_clock(object);
-	struct nv_control_pstate_info *args = data;
+	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(object, "control pstate info size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "control pstate info vers %d\n",
+			 args->v0.version);
+	} else
+		return ret;
 
 	if (clk) {
-		args->count  = clk->state_nr;
-		args->ustate = clk->ustate;
-		args->pstate = clk->pstate;
+		args->v0.count = clk->state_nr;
+		args->v0.ustate_ac = clk->ustate_ac;
+		args->v0.ustate_dc = clk->ustate_dc;
+		args->v0.pwrsrc = clk->pwrsrc;
+		args->v0.pstate = clk->pstate;
 	} else {
-		args->count  = 0;
-		args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
-		args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN;
+		args->v0.count = 0;
+		args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
+		args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
+		args->v0.pwrsrc = -ENOSYS;
+		args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
 	}
 
 	return 0;
 }
 
 static int
-nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
-				void *data, u32 size)
+nouveau_control_mthd_pstate_attr(struct nouveau_object *object,
+				 void *data, u32 size)
 {
+	union {
+		struct nvif_control_pstate_attr_v0 v0;
+	} *args = data;
 	struct nouveau_clock *clk = nouveau_clock(object);
-	struct nv_control_pstate_attr *args = data;
 	struct nouveau_clocks *domain;
 	struct nouveau_pstate *pstate;
 	struct nouveau_cstate *cstate;
 	int i = 0, j = -1;
 	u32 lo, hi;
+	int ret;
 
-	if ((size < sizeof(*args)) || !clk ||
-	    (args->state >= 0 && args->state >= clk->state_nr))
-		return -EINVAL;
+	nv_ioctl(object, "control pstate attr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "control pstate attr vers %d state %d "
+				 "index %d\n",
+			 args->v0.version, args->v0.state, args->v0.index);
+		if (!clk)
+			return -ENODEV;
+		if (args->v0.state < NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT)
+			return -EINVAL;
+		if (args->v0.state >= clk->state_nr)
+			return -EINVAL;
+	} else
+		return ret;
 	domain = clk->domains;
 
 	while (domain->name != nv_clk_src_max) {
-		if (domain->mname && ++j == args->index)
+		if (domain->mname && ++j == args->v0.index)
 			break;
 		domain++;
 	}
@@ -78,9 +105,9 @@ nouveau_control_mthd_pstate_attr(struct
 	if (domain->name == nv_clk_src_max)
 		return -EINVAL;
 
-	if (args->state != NV_CONTROL_PSTATE_ATTR_STATE_CURRENT) {
+	if (args->v0.state != NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT) {
 		list_for_each_entry(pstate, &clk->states, head) {
-			if (i++ == args->state)
+			if (i++ == args->v0.state)
 				break;
 		}
 
@@ -91,21 +118,21 @@ nouveau_control_mthd_pstate_attr(struct
 			hi = max(hi, cstate->domain[domain->name]);
 		}
 
-		args->state = pstate->pstate;
+		args->v0.state = pstate->pstate;
 	} else {
 		lo = max(clk->read(clk, domain->name), 0);
 		hi = lo;
 	}
 
-	snprintf(args->name, sizeof(args->name), "%s", domain->mname);
-	snprintf(args->unit, sizeof(args->unit), "MHz");
-	args->min = lo / domain->mdiv;
-	args->max = hi / domain->mdiv;
+	snprintf(args->v0.name, sizeof(args->v0.name), "%s", domain->mname);
+	snprintf(args->v0.unit, sizeof(args->v0.unit), "MHz");
+	args->v0.min = lo / domain->mdiv;
+	args->v0.max = hi / domain->mdiv;
 
-	args->index = 0;
+	args->v0.index = 0;
 	while ((++domain)->name != nv_clk_src_max) {
 		if (domain->mname) {
-			args->index = ++j;
+			args->v0.index = ++j;
 			break;
 		}
 	}
@@ -114,31 +141,65 @@ nouveau_control_mthd_pstate_attr(struct
 }
 
 static int
-nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd,
-				void *data, u32 size)
+nouveau_control_mthd_pstate_user(struct nouveau_object *object,
+				 void *data, u32 size)
 {
+	union {
+		struct nvif_control_pstate_user_v0 v0;
+	} *args = data;
 	struct nouveau_clock *clk = nouveau_clock(object);
-	struct nv_control_pstate_user *args = data;
+	int ret;
 
-	if (size < sizeof(*args) || !clk)
-		return -EINVAL;
+	nv_ioctl(object, "control pstate user size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "control pstate user vers %d ustate %d "
+				 "pwrsrc %d\n", args->v0.version,
+			 args->v0.ustate, args->v0.pwrsrc);
+		if (!clk)
+			return -ENODEV;
+	} else
+		return ret;
 
-	return nouveau_clock_ustate(clk, args->state);
+	if (args->v0.pwrsrc >= 0) {
+		ret |= nouveau_clock_ustate(clk, args->v0.ustate, args->v0.pwrsrc);
+	} else {
+		ret |= nouveau_clock_ustate(clk, args->v0.ustate, 0);
+		ret |= nouveau_clock_ustate(clk, args->v0.ustate, 1);
+	}
+
+	return ret;
 }
 
+static int
+nouveau_control_mthd(struct nouveau_object *object, u32 mthd,
+		     void *data, u32 size)
+{
+	switch (mthd) {
+	case NVIF_CONTROL_PSTATE_INFO:
+		return nouveau_control_mthd_pstate_info(object, data, size);
+	case NVIF_CONTROL_PSTATE_ATTR:
+		return nouveau_control_mthd_pstate_attr(object, data, size);
+	case NVIF_CONTROL_PSTATE_USER:
+		return nouveau_control_mthd_pstate_user(object, data, size);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static struct nouveau_ofuncs
+nouveau_control_ofuncs = {
+	.ctor = _nouveau_object_ctor,
+	.dtor = nouveau_object_destroy,
+	.init = nouveau_object_init,
+	.fini = nouveau_object_fini,
+	.mthd = nouveau_control_mthd,
+};
+
 struct nouveau_oclass
 nouveau_control_oclass[] = {
-	{ .handle = NV_CONTROL_CLASS,
-	  .ofuncs = &nouveau_object_ofuncs,
-	  .omthds = (struct nouveau_omthds[]) {
-		  { NV_CONTROL_PSTATE_INFO,
-		    NV_CONTROL_PSTATE_INFO, nouveau_control_mthd_pstate_info },
-		  { NV_CONTROL_PSTATE_ATTR,
-		    NV_CONTROL_PSTATE_ATTR, nouveau_control_mthd_pstate_attr },
-		  { NV_CONTROL_PSTATE_USER,
-		    NV_CONTROL_PSTATE_USER, nouveau_control_mthd_pstate_user },
-		  {},
-	  },
+	{ .handle = NVIF_IOCTL_NEW_V0_CONTROL,
+	  .ofuncs = &nouveau_control_ofuncs
 	},
 	{}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/gm100.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/gm100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/gm100.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
 #include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
 #include <subdev/ibus.h>
 #include <subdev/instmem.h>
 #include <subdev/vm.h>
@@ -68,20 +68,20 @@ gm100_identify(struct nouveau_device *de
 #endif
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm107_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gm107_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gm107_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 #if 0
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nv108_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 #endif
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  gm107_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@ nv04_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass;
@@ -74,7 +74,7 @@ nv04_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv10.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv10.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
 		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;
 		break;
@@ -75,7 +75,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -94,7 +94,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -113,7 +113,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -132,7 +132,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -151,7 +151,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -170,7 +170,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -189,7 +189,7 @@ nv10_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv20.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv20.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ nv20_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv20_graph_oclass;
@@ -78,7 +78,7 @@ nv20_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass;
@@ -97,7 +97,7 @@ nv20_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass;
@@ -116,7 +116,7 @@ nv20_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv2a_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv30.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv30.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ nv30_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass;
@@ -78,7 +78,7 @@ nv30_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass;
@@ -97,7 +97,7 @@ nv30_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass;
@@ -117,7 +117,7 @@ nv30_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass;
@@ -137,7 +137,7 @@ nv30_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv34_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv40.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv40.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -88,7 +88,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -111,7 +111,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -134,7 +134,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -157,7 +157,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -180,7 +180,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -203,7 +203,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -226,7 +226,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -249,7 +249,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -272,7 +272,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -295,7 +295,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -341,7 +341,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -364,7 +364,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -387,7 +387,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
@@ -410,7 +410,7 @@ nv40_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv50_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -99,7 +99,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -127,7 +127,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -155,7 +155,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -183,7 +183,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -211,7 +211,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -239,7 +239,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -267,7 +267,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -295,7 +295,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -323,7 +323,7 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -350,9 +350,9 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nva3_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -380,9 +380,9 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nva3_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -409,9 +409,9 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nva3_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
@@ -438,9 +438,9 @@ nv50_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nva3_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nv50_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
 #include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
 #include <subdev/ibus.h>
 #include <subdev/instmem.h>
 #include <subdev/vm.h>
@@ -70,14 +70,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc0_graph_oclass;
@@ -102,14 +102,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
@@ -134,14 +134,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
@@ -165,14 +165,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
@@ -197,14 +197,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;
@@ -229,14 +229,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc1_graph_oclass;
@@ -260,14 +260,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvc0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvc0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvc8_graph_oclass;
@@ -292,14 +292,14 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvd0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvd9_graph_oclass;
@@ -323,12 +323,12 @@ nvc0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gf100_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvd7_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nve0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/device/nve0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/device/nve0.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
 #include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
 #include <subdev/ibus.h>
 #include <subdev/instmem.h>
 #include <subdev/vm.h>
@@ -70,14 +70,14 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  gk104_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
@@ -103,14 +103,14 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvd0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
@@ -136,14 +136,14 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  gk104_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass;
@@ -158,15 +158,17 @@ nve0_identify(struct nouveau_device *dev
 		break;
 	case 0xea:
 		device->cname = "GK20A";
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &gk20a_clock_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  gk20a_fb_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &gk20a_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
-		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_SUBDEV_BAR    ] = &gk20a_bar_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk20a_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  gk20a_graph_oclass;
@@ -186,14 +188,14 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvd0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
@@ -219,17 +221,17 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nvd0_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-		device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
+		device->oclass[NVDEV_ENGINE_GR     ] =  gk110b_graph_oclass;
 		device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass;
 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
 		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
@@ -248,18 +250,18 @@ nve0_identify(struct nouveau_device *dev
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
+		device->oclass[NVDEV_SUBDEV_PWR    ] =  nv108_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
-		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,23 +22,93 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/os.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/event.h>
+
 #include "priv.h"
 #include "outp.h"
 #include "conn.h"
 
+int
+nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	struct nouveau_disp *disp =
+		container_of(notify->event, typeof(*disp), vblank);
+	union {
+		struct nvif_notify_head_req_v0 v0;
+	} *req = data;
+	int ret;
+
+	if (nvif_unpack(req->v0, 0, 0, false)) {
+		notify->size = sizeof(struct nvif_notify_head_rep_v0);
+		if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
+			notify->types = 1;
+			notify->index = req->v0.head;
+			return 0;
+		}
+	}
+
+	return ret;
+}
+
+void
+nouveau_disp_vblank(struct nouveau_disp *disp, int head)
+{
+	struct nvif_notify_head_rep_v0 rep = {};
+	nvkm_event_send(&disp->vblank, 1, head, &rep, sizeof(rep));
+}
+
 static int
-nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index)
+nouveau_disp_hpd_ctor(void *data, u32 size, struct nvkm_notify *notify)
 {
-	struct nouveau_disp *disp = event->priv;
+	struct nouveau_disp *disp =
+		container_of(notify->event, typeof(*disp), hpd);
+	union {
+		struct nvif_notify_conn_req_v0 v0;
+	} *req = data;
 	struct nvkm_output *outp;
-	list_for_each_entry(outp, &disp->outp, head) {
-		if (outp->conn->index == index) {
-			if (outp->conn->hpd.event)
-				return 0;
-			break;
+	int ret;
+
+	if (nvif_unpack(req->v0, 0, 0, false)) {
+		notify->size = sizeof(struct nvif_notify_conn_rep_v0);
+		list_for_each_entry(outp, &disp->outp, head) {
+			if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
+				if (ret = -ENODEV, outp->conn->hpd.event) {
+					notify->types = req->v0.mask;
+					notify->index = req->v0.conn;
+					ret = 0;
+				}
+				break;
+			}
 		}
 	}
-	return -ENOSYS;
+
+	return ret;
+}
+
+static const struct nvkm_event_func
+nouveau_disp_hpd_func = {
+	.ctor = nouveau_disp_hpd_ctor
+};
+
+int
+nouveau_disp_ntfy(struct nouveau_object *object, u32 type,
+		  struct nvkm_event **event)
+{
+	struct nouveau_disp *disp = (void *)object->engine;
+	switch (type) {
+	case NV04_DISP_NTFY_VBLANK:
+		*event = &disp->vblank;
+		return 0;
+	case NV04_DISP_NTFY_CONN:
+		*event = &disp->hpd;
+		return 0;
+	default:
+		break;
+	}
+	return -EINVAL;
 }
 
 int
@@ -97,7 +167,8 @@ _nouveau_disp_dtor(struct nouveau_object
 	struct nouveau_disp *disp = (void *)object;
 	struct nvkm_output *outp, *outt;
 
-	nouveau_event_destroy(&disp->vblank);
+	nvkm_event_fini(&disp->vblank);
+	nvkm_event_fini(&disp->hpd);
 
 	if (disp->outp.next) {
 		list_for_each_entry_safe(outp, outt, &disp->outp, head) {
@@ -157,14 +228,11 @@ nouveau_disp_create_(struct nouveau_obje
 		hpd = max(hpd, (u8)(dcbE.connector + 1));
 	}
 
-	ret = nouveau_event_create(3, hpd, &disp->hpd);
+	ret = nvkm_event_init(&nouveau_disp_hpd_func, 3, hpd, &disp->hpd);
 	if (ret)
 		return ret;
 
-	disp->hpd->priv = disp;
-	disp->hpd->check = nouveau_disp_hpd_check;
-
-	ret = nouveau_event_create(1, heads, &disp->vblank);
+	ret = nvkm_event_init(impl->vblank, 1, heads, &disp->vblank);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,39 +22,41 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/os.h>
+#include <nvif/event.h>
+
 #include <subdev/gpio.h>
 
 #include "conn.h"
 #include "outp.h"
 
-static void
-nvkm_connector_hpd_work(struct work_struct *w)
+static int
+nvkm_connector_hpd(struct nvkm_notify *notify)
 {
-	struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work);
+	struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
 	struct nouveau_disp *disp = nouveau_disp(conn);
 	struct nouveau_gpio *gpio = nouveau_gpio(conn);
-	u32 send = NVKM_HPD_UNPLUG;
-	if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index))
-		send = NVKM_HPD_PLUG;
-	nouveau_event_trigger(disp->hpd, send, conn->index);
-	nouveau_event_get(conn->hpd.event);
-}
+	const struct nvkm_gpio_ntfy_rep *line = notify->data;
+	struct nvif_notify_conn_rep_v0 rep;
+	int index = conn->index;
 
-static int
-nvkm_connector_hpd(void *data, u32 type, int index)
-{
-	struct nvkm_connector *conn = data;
-	DBG("HPD: %d\n", type);
-	schedule_work(&conn->hpd.work);
-	return NVKM_EVENT_DROP;
+	DBG("HPD: %d\n", line->mask);
+
+	if (!gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
+		rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
+	else
+		rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
+	rep.version = 0;
+
+	nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
+	return NVKM_NOTIFY_KEEP;
 }
 
 int
 _nvkm_connector_fini(struct nouveau_object *object, bool suspend)
 {
 	struct nvkm_connector *conn = (void *)object;
-	if (conn->hpd.event)
-		nouveau_event_put(conn->hpd.event);
+	nvkm_notify_put(&conn->hpd);
 	return nouveau_object_fini(&conn->base, suspend);
 }
 
@@ -63,10 +65,8 @@ _nvkm_connector_init(struct nouveau_obje
 {
 	struct nvkm_connector *conn = (void *)object;
 	int ret = nouveau_object_init(&conn->base);
-	if (ret == 0) {
-		if (conn->hpd.event)
-			nouveau_event_get(conn->hpd.event);
-	}
+	if (ret == 0)
+		nvkm_notify_get(&conn->hpd);
 	return ret;
 }
 
@@ -74,7 +74,7 @@ void
 _nvkm_connector_dtor(struct nouveau_object *object)
 {
 	struct nvkm_connector *conn = (void *)object;
-	nouveau_event_ref(NULL, &conn->hpd.event);
+	nvkm_notify_fini(&conn->hpd);
 	nouveau_object_destroy(&conn->base);
 }
 
@@ -116,19 +116,24 @@ nvkm_connector_create_(struct nouveau_ob
 	if ((info->hpd = ffs(info->hpd))) {
 		if (--info->hpd >= ARRAY_SIZE(hpd)) {
 			ERR("hpd %02x unknown\n", info->hpd);
-			goto done;
+			return 0;
 		}
 		info->hpd = hpd[info->hpd];
 
 		ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
 		if (ret) {
 			ERR("func %02x lookup failed, %d\n", info->hpd, ret);
-			goto done;
+			return 0;
 		}
 
-		ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED,
-					func.line, nvkm_connector_hpd,
-					conn, &conn->hpd.event);
+		ret = nvkm_notify_init(&gpio->event, nvkm_connector_hpd, true,
+				       &(struct nvkm_gpio_ntfy_req) {
+					.mask = NVKM_GPIO_TOGGLED,
+					.line = func.line,
+				       },
+				       sizeof(struct nvkm_gpio_ntfy_req),
+				       sizeof(struct nvkm_gpio_ntfy_rep),
+				       &conn->hpd);
 		if (ret) {
 			ERR("func %02x failed, %d\n", info->hpd, ret);
 		} else {
@@ -136,8 +141,6 @@ nvkm_connector_create_(struct nouveau_ob
 		}
 	}
 
-done:
-	INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/conn.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,10 +10,7 @@ struct nvkm_connector {
 	struct nvbios_connE info;
 	int index;
 
-	struct {
-		struct nouveau_eventh *event;
-		struct work_struct work;
-	} hpd;
+	struct nvkm_notify hpd;
 };
 
 #define nvkm_connector_create(p,e,c,b,i,d)                                     \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -32,13 +33,28 @@
 #include "nv50.h"
 
 int
-nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
+nv50_dac_power(NV50_DISP_MTHD_V1)
 {
-	const u32 stat = (data & NV50_DISP_DAC_PWR_HSYNC) |
-		         (data & NV50_DISP_DAC_PWR_VSYNC) |
-		         (data & NV50_DISP_DAC_PWR_DATA) |
-		         (data & NV50_DISP_DAC_PWR_STATE);
-	const u32 doff = (or * 0x800);
+	const u32 doff = outp->or * 0x800;
+	union {
+		struct nv50_disp_dac_pwr_v0 v0;
+	} *args = data;
+	u32 stat;
+	int ret;
+
+	nv_ioctl(object, "disp dac pwr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp dac pwr vers %d state %d data %d "
+				 "vsync %d hsync %d\n",
+			 args->v0.version, args->v0.state, args->v0.data,
+			 args->v0.vsync, args->v0.hsync);
+		stat  = 0x00000040 * !args->v0.state;
+		stat |= 0x00000010 * !args->v0.data;
+		stat |= 0x00000004 * !args->v0.vsync;
+		stat |= 0x00000001 * !args->v0.hsync;
+	} else
+		return ret;
+
 	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
 	nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat);
 	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@@ -46,9 +62,24 @@ nv50_dac_power(struct nv50_disp_priv *pr
 }
 
 int
-nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
+nv50_dac_sense(NV50_DISP_MTHD_V1)
 {
-	const u32 doff = (or * 0x800);
+	union {
+		struct nv50_disp_dac_load_v0 v0;
+	} *args = data;
+	const u32 doff = outp->or * 0x800;
+	u32 loadval;
+	int ret;
+
+	nv_ioctl(object, "disp dac load size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp dac load vers %d data %08x\n",
+			 args->v0.version, args->v0.data);
+		if (args->v0.data & 0xfff00000)
+			return -EINVAL;
+		loadval = args->v0.data;
+	} else
+		return ret;
 
 	nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
 	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@@ -61,38 +92,10 @@ nv50_dac_sense(struct nv50_disp_priv *pr
 	nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
 	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
 
-	nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval);
+	nv_debug(priv, "DAC%d sense: 0x%08x\n", outp->or, loadval);
 	if (!(loadval & 0x80000000))
 		return -ETIMEDOUT;
 
-	return (loadval & 0x38000000) >> 27;
-}
-
-int
-nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
-{
-	struct nv50_disp_priv *priv = (void *)object->engine;
-	const u8 or = (mthd & NV50_DISP_DAC_MTHD_OR);
-	u32 *data = args;
-	int ret;
-
-	if (size < sizeof(u32))
-		return -EINVAL;
-
-	switch (mthd & ~0x3f) {
-	case NV50_DISP_DAC_PWR:
-		ret = priv->dac.power(priv, or, data[0]);
-		break;
-	case NV50_DISP_DAC_LOAD:
-		ret = priv->dac.sense(priv, or, data[0]);
-		if (ret >= 0) {
-			data[0] = ret;
-			ret = 0;
-		}
-		break;
-	default:
-		BUG_ON(1);
-	}
-
-	return ret;
+	args->v0.load = (loadval & 0x38000000) >> 27;
+	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dport.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/dport.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@
 
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "dport.h"
 #include "outpdp.h"
@@ -335,7 +335,7 @@ nouveau_dp_train(struct work_struct *w)
 	int ret;
 
 	/* bring capabilities within encoder limits */
-	if (nv_mclass(disp) < NVD0_DISP_CLASS)
+	if (nv_mclass(disp) < GF110_DISP)
 		outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
 	if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
 		outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
@@ -354,7 +354,7 @@ nouveau_dp_train(struct work_struct *w)
 	cfg--;
 
 	/* disable link interrupt handling during link training */
-	nouveau_event_put(outp->irq);
+	nvkm_notify_put(&outp->irq);
 
 	/* enable down-spreading and execute pre-train script from vbios */
 	dp_link_train_init(dp, outp->dpcd[3] & 0x01);
@@ -395,5 +395,5 @@ nouveau_dp_train(struct work_struct *w)
 	DBG("training complete\n");
 	atomic_set(&outp->lt.done, 1);
 	wake_up(&outp->lt.wait);
-	nouveau_event_get(outp->irq);
+	nvkm_notify_get(&outp->irq);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -35,17 +35,17 @@
 
 static struct nouveau_oclass
 gm107_disp_sclass[] = {
-	{ GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
-	{ GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
-	{ GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
-	{ GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
-	{ GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+	{ GM107_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+	{ GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+	{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+	{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+	{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
 	{}
 };
 
 static struct nouveau_oclass
 gm107_disp_base_oclass[] = {
-	{ GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+	{ GM107_DISP, &nvd0_disp_base_ofuncs },
 	{}
 };
 
@@ -93,9 +93,11 @@ gm107_disp_oclass = &(struct nv50_disp_i
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nvd0_disp_vblank_func,
 	.base.outp =  nvd0_disp_outp_sclass,
 	.mthd.core = &nve0_disp_mast_mthd_chan,
 	.mthd.base = &nvd0_disp_sync_mthd_chan,
 	.mthd.ovly = &nve0_disp_ovly_mthd_chan,
 	.mthd.prev = -0x020000,
+	.head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,25 +22,37 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
 int
-nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+nva3_hda_eld(NV50_DISP_MTHD_V1)
 {
-	const u32 soff = (or * 0x800);
-	int i;
+	union {
+		struct nv50_disp_sor_hda_eld_v0 v0;
+	} *args = data;
+	const u32 soff = outp->or * 0x800;
+	int ret, i;
 
-	if (data && data[0]) {
+	nv_ioctl(object, "disp sor hda eld size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
+		if (size > 0x60)
+			return -E2BIG;
+	} else
+		return ret;
+
+	if (size && args->v0.data[0]) {
 		for (i = 0; i < size; i++)
-			nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
+			nv_wr32(priv, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
 		for (; i < 0x60; i++)
 			nv_wr32(priv, 0x61c440 + soff, (i << 8));
 		nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
 	} else
-	if (data) {
+	if (size) {
 		nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000001);
 	} else {
 		nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -33,19 +34,30 @@
 #include "nv50.h"
 
 int
-nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+nvd0_hda_eld(NV50_DISP_MTHD_V1)
 {
-	const u32 soff = (or * 0x030);
-	int i;
+	union {
+		struct nv50_disp_sor_hda_eld_v0 v0;
+	} *args = data;
+	const u32 soff = outp->or * 0x030;
+	int ret, i;
 
-	if (data && data[0]) {
+	nv_ioctl(object, "disp sor hda eld size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
+		if (size > 0x60)
+			return -E2BIG;
+	} else
+		return ret;
+
+	if (size && args->v0.data[0]) {
 		for (i = 0; i < size; i++)
-			nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
+			nv_wr32(priv, 0x10ec00 + soff, (i << 8) | args->v0.data[i]);
 		for (; i < 0x60; i++)
 			nv_wr32(priv, 0x10ec00 + soff, (i << 8));
 		nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
 	} else
-	if (data) {
+	if (size) {
 		nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000001);
 	} else {
 		nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,17 +22,38 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
 int
-nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nv84_hdmi_ctrl(NV50_DISP_MTHD_V1)
 {
 	const u32 hoff = (head * 0x800);
+	union {
+		struct nv50_disp_sor_hdmi_pwr_v0 v0;
+	} *args = data;
+	u32 ctrl;
+	int ret;
 
-	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+				 "max_ac_packet %d rekey %d\n",
+			 args->v0.version, args->v0.state,
+			 args->v0.max_ac_packet, args->v0.rekey);
+		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+			return -EINVAL;
+		ctrl  = 0x40000000 * !!args->v0.state;
+		ctrl |= args->v0.max_ac_packet << 16;
+		ctrl |= args->v0.rekey;
+		ctrl |= 0x1f000000; /* ??? */
+	} else
+		return ret;
+
+	if (!(ctrl & 0x40000000)) {
 		nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000);
 		nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000);
 		nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *pr
 	nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
 
 	/* HDMI_CTRL */
-	nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
+	nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,17 +22,38 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
 int
-nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nva3_hdmi_ctrl(NV50_DISP_MTHD_V1)
 {
-	const u32 soff = (or * 0x800);
+	const u32 soff = outp->or * 0x800;
+	union {
+		struct nv50_disp_sor_hdmi_pwr_v0 v0;
+	} *args = data;
+	u32 ctrl;
+	int ret;
 
-	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+				 "max_ac_packet %d rekey %d\n",
+			 args->v0.version, args->v0.state,
+			 args->v0.max_ac_packet, args->v0.rekey);
+		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+			return -EINVAL;
+		ctrl  = 0x40000000 * !!args->v0.state;
+		ctrl |= args->v0.max_ac_packet << 16;
+		ctrl |= args->v0.rekey;
+		ctrl |= 0x1f000000; /* ??? */
+	} else
+		return ret;
+
+	if (!(ctrl & 0x40000000)) {
 		nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000);
 		nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000);
 		nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *pr
 	nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
 
 	/* HDMI_CTRL */
-	nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
+	nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,17 +22,37 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
 int
-nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1)
 {
 	const u32 hoff = (head * 0x800);
+	union {
+		struct nv50_disp_sor_hdmi_pwr_v0 v0;
+	} *args = data;
+	u32 ctrl;
+	int ret;
 
-	if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+	nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+				 "max_ac_packet %d rekey %d\n",
+			 args->v0.version, args->v0.state,
+			 args->v0.max_ac_packet, args->v0.rekey);
+		if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+			return -EINVAL;
+		ctrl  = 0x40000000 * !!args->v0.state;
+		ctrl |= args->v0.max_ac_packet << 16;
+		ctrl |= args->v0.rekey;
+	} else
+		return ret;
+
+	if (!(ctrl & 0x40000000)) {
 		nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000);
 		nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000);
 		nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000);
@@ -54,7 +74,7 @@ nvd0_hdmi_ctrl(struct nv50_disp_priv *pr
 	nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001);
 
 	/* HDMI_CTRL */
-	nv_mask(priv, 0x616798 + hoff, 0x401f007f, data);
+	nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl);
 
 	/* NFI, audio doesn't work without it though.. */
 	nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,60 +24,100 @@
 
 #include "priv.h"
 
+#include <core/client.h>
 #include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 struct nv04_disp_priv {
 	struct nouveau_disp base;
 };
 
 static int
-nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
-		     void *data, u32 size)
+nv04_disp_scanoutpos(struct nouveau_object *object, struct nv04_disp_priv *priv,
+		     void *data, u32 size, int head)
 {
-	struct nv04_disp_priv *priv = (void *)object->engine;
-	struct nv04_display_scanoutpos *args = data;
-	const int head = (mthd & NV04_DISP_MTHD_HEAD);
+	const u32 hoff = head * 0x2000;
+	union {
+		struct nv04_disp_scanoutpos_v0 v0;
+	} *args = data;
 	u32 line;
+	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(object, "disp scanoutpos size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+		args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff;
+		args->v0.vtotal  = nv_rd32(priv, 0x680804 + hoff) & 0xffff;
+		args->v0.vblanke = args->v0.vtotal - 1;
 
-	args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
-	args->vtotal  = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
-	args->vblanke = args->vtotal - 1;
+		args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff;
+		args->v0.htotal  = nv_rd32(priv, 0x680824 + hoff) & 0xffff;
+		args->v0.hblanke = args->v0.htotal - 1;
 
-	args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
-	args->htotal  = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
-	args->hblanke = args->htotal - 1;
+		/*
+		 * If output is vga instead of digital then vtotal/htotal is
+		 * invalid so we have to give up and trigger the timestamping
+		 * fallback in the drm core.
+		 */
+		if (!args->v0.vtotal || !args->v0.htotal)
+			return -ENOTSUPP;
 
-	/*
-	 * If output is vga instead of digital then vtotal/htotal is invalid
-	 * so we have to give up and trigger the timestamping fallback in the
-	 * drm core.
-	 */
-	if (!args->vtotal || !args->htotal)
-		return -ENOTSUPP;
+		args->v0.time[0] = ktime_to_ns(ktime_get());
+		line = nv_rd32(priv, 0x600868 + hoff);
+		args->v0.time[1] = ktime_to_ns(ktime_get());
+		args->v0.hline = (line & 0xffff0000) >> 16;
+		args->v0.vline = (line & 0x0000ffff);
+	} else
+		return ret;
 
-	args->time[0] = ktime_to_ns(ktime_get());
-	line = nv_rd32(priv, 0x600868 + (head * 0x2000));
-	args->time[1] = ktime_to_ns(ktime_get());
-	args->hline = (line & 0xffff0000) >> 16;
-	args->vline = (line & 0x0000ffff);
 	return 0;
 }
 
-#define HEAD_MTHD(n) (n), (n) + 0x01
+static int
+nv04_disp_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+	union {
+		struct nv04_disp_mthd_v0 v0;
+	} *args = data;
+	struct nv04_disp_priv *priv = (void *)object->engine;
+	int head, ret;
 
-static struct nouveau_omthds
-nv04_disp_omthds[] = {
-	{ HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
-	{}
+	nv_ioctl(object, "disp mthd size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+			 args->v0.version, args->v0.method, args->v0.head);
+		mthd = args->v0.method;
+		head = args->v0.head;
+	} else
+		return ret;
+
+	if (head < 0 || head >= 2)
+		return -ENXIO;
+
+	switch (mthd) {
+	case NV04_DISP_SCANOUTPOS:
+		return nv04_disp_scanoutpos(object, priv, data, size, head);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static struct nouveau_ofuncs
+nv04_disp_ofuncs = {
+	.ctor = _nouveau_object_ctor,
+	.dtor = nouveau_object_destroy,
+	.init = nouveau_object_init,
+	.fini = nouveau_object_fini,
+	.mthd = nv04_disp_mthd,
+	.ntfy = nouveau_disp_ntfy,
 };
 
 static struct nouveau_oclass
 nv04_disp_sclass[] = {
-	{ NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
+	{ NV04_DISP, &nv04_disp_ofuncs },
 	{},
 };
 
@@ -86,17 +126,26 @@ nv04_disp_sclass[] = {
  ******************************************************************************/
 
 static void
-nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)
+nv04_disp_vblank_init(struct nvkm_event *event, int type, int head)
 {
-	nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000001);
 }
 
 static void
-nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)
+nv04_disp_vblank_fini(struct nvkm_event *event, int type, int head)
 {
-	nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000000);
 }
 
+static const struct nvkm_event_func
+nv04_disp_vblank_func = {
+	.ctor = nouveau_disp_vblank_ctor,
+	.init = nv04_disp_vblank_init,
+	.fini = nv04_disp_vblank_fini,
+};
+
 static void
 nv04_disp_intr(struct nouveau_subdev *subdev)
 {
@@ -106,12 +155,12 @@ nv04_disp_intr(struct nouveau_subdev *su
 	u32 pvideo;
 
 	if (crtc0 & 0x00000001) {
-		nouveau_event_trigger(priv->base.vblank, 1, 0);
+		nouveau_disp_vblank(&priv->base, 0);
 		nv_wr32(priv, 0x600100, 0x00000001);
 	}
 
 	if (crtc1 & 0x00000001) {
-		nouveau_event_trigger(priv->base.vblank, 1, 1);
+		nouveau_disp_vblank(&priv->base, 1);
 		nv_wr32(priv, 0x602100, 0x00000001);
 	}
 
@@ -140,9 +189,6 @@ nv04_disp_ctor(struct nouveau_object *pa
 
 	nv_engine(priv)->sclass = nv04_disp_sclass;
 	nv_subdev(priv)->intr = nv04_disp_intr;
-	priv->base.vblank->priv = priv;
-	priv->base.vblank->enable = nv04_disp_vblank_enable;
-	priv->base.vblank->disable = nv04_disp_vblank_disable;
 	return 0;
 }
 
@@ -155,4 +201,5 @@ nv04_disp_oclass = &(struct nouveau_disp
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.vblank = &nv04_disp_vblank_func,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,10 +23,12 @@
  */
 
 #include <core/object.h>
+#include <core/client.h>
 #include <core/parent.h>
 #include <core/handle.h>
-#include <core/class.h>
 #include <core/enum.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -43,14 +45,16 @@
  * EVO channel base class
  ******************************************************************************/
 
-int
+static int
 nv50_disp_chan_create_(struct nouveau_object *parent,
 		       struct nouveau_object *engine,
-		       struct nouveau_oclass *oclass, int chid,
+		       struct nouveau_oclass *oclass, int head,
 		       int length, void **pobject)
 {
+	const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
 	struct nv50_disp_base *base = (void *)parent;
 	struct nv50_disp_chan *chan;
+	int chid = impl->chid + head;
 	int ret;
 
 	if (base->chan & (1 << chid))
@@ -63,12 +67,14 @@ nv50_disp_chan_create_(struct nouveau_ob
 	chan = *pobject;
 	if (ret)
 		return ret;
-
 	chan->chid = chid;
+
+	nv_parent(chan)->object_attach = impl->attach;
+	nv_parent(chan)->object_detach = impl->detach;
 	return 0;
 }
 
-void
+static void
 nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
 {
 	struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
@@ -76,6 +82,16 @@ nv50_disp_chan_destroy(struct nv50_disp_
 	nouveau_namedb_destroy(&chan->base);
 }
 
+int
+nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+	struct nv50_disp_chan *chan = (void *)object;
+	*addr = nv_device_resource_start(nv_device(object), 0) +
+		0x640000 + (chan->chid * 0x1000);
+	*size = 0x001000;
+	return 0;
+}
+
 u32
 nv50_disp_chan_rd32(struct nouveau_object *object, u64 addr)
 {
@@ -115,16 +131,16 @@ nv50_disp_dmac_object_detach(struct nouv
 	nouveau_ramht_remove(base->ramht, cookie);
 }
 
-int
+static int
 nv50_disp_dmac_create_(struct nouveau_object *parent,
 		       struct nouveau_object *engine,
-		       struct nouveau_oclass *oclass, u32 pushbuf, int chid,
+		       struct nouveau_oclass *oclass, u32 pushbuf, int head,
 		       int length, void **pobject)
 {
 	struct nv50_disp_dmac *dmac;
 	int ret;
 
-	ret = nv50_disp_chan_create_(parent, engine, oclass, chid,
+	ret = nv50_disp_chan_create_(parent, engine, oclass, head,
 				     length, pobject);
 	dmac = *pobject;
 	if (ret)
@@ -397,27 +413,32 @@ nv50_disp_mast_mthd_chan = {
 	}
 };
 
-static int
+int
 nv50_disp_mast_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
-	struct nv50_display_mast_class *args = data;
+	union {
+		struct nv50_disp_core_channel_dma_v0 v0;
+	} *args = data;
 	struct nv50_disp_dmac *mast;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create disp core channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create disp core channel dma vers %d "
+				 "pushbuf %08x\n",
+			 args->v0.version, args->v0.pushbuf);
+	} else
+		return ret;
 
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
+	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
 				     0, sizeof(*mast), (void **)&mast);
 	*pobject = nv_object(mast);
 	if (ret)
 		return ret;
 
-	nv_parent(mast)->object_attach = nv50_disp_dmac_object_attach;
-	nv_parent(mast)->object_detach = nv50_disp_dmac_object_detach;
 	return 0;
 }
 
@@ -479,14 +500,18 @@ nv50_disp_mast_fini(struct nouveau_objec
 	return nv50_disp_chan_fini(&mast->base, suspend);
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nv50_disp_mast_ofuncs = {
-	.ctor = nv50_disp_mast_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nv50_disp_mast_init,
-	.fini = nv50_disp_mast_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_mast_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nv50_disp_mast_init,
+	.base.fini = nv50_disp_mast_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 0,
+	.attach = nv50_disp_dmac_object_attach,
+	.detach = nv50_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -543,39 +568,51 @@ nv50_disp_sync_mthd_chan = {
 	}
 };
 
-static int
+int
 nv50_disp_sync_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
-	struct nv50_display_sync_class *args = data;
+	union {
+		struct nv50_disp_base_channel_dma_v0 v0;
+	} *args = data;
+	struct nv50_disp_priv *priv = (void *)engine;
 	struct nv50_disp_dmac *dmac;
 	int ret;
 
-	if (size < sizeof(*args) || args->head > 1)
-		return -EINVAL;
+	nv_ioctl(parent, "create disp base channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create disp base channel dma vers %d "
+				 "pushbuf %08x head %d\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.head);
+		if (args->v0.head > priv->head.nr)
+			return -EINVAL;
+	} else
+		return ret;
 
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
-				     1 + args->head, sizeof(*dmac),
+	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
+				     args->v0.head, sizeof(*dmac),
 				     (void **)&dmac);
 	*pobject = nv_object(dmac);
 	if (ret)
 		return ret;
 
-	nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
-	nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
 	return 0;
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nv50_disp_sync_ofuncs = {
-	.ctor = nv50_disp_sync_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nv50_disp_dmac_init,
-	.fini = nv50_disp_dmac_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_sync_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nv50_disp_dmac_init,
+	.base.fini = nv50_disp_dmac_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 1,
+	.attach = nv50_disp_dmac_object_attach,
+	.detach = nv50_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -620,39 +657,51 @@ nv50_disp_ovly_mthd_chan = {
 	}
 };
 
-static int
+int
 nv50_disp_ovly_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
-	struct nv50_display_ovly_class *args = data;
+	union {
+		struct nv50_disp_overlay_channel_dma_v0 v0;
+	} *args = data;
+	struct nv50_disp_priv *priv = (void *)engine;
 	struct nv50_disp_dmac *dmac;
 	int ret;
 
-	if (size < sizeof(*args) || args->head > 1)
-		return -EINVAL;
+	nv_ioctl(parent, "create disp overlay channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create disp overlay channel dma vers %d "
+				 "pushbuf %08x head %d\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.head);
+		if (args->v0.head > priv->head.nr)
+			return -EINVAL;
+	} else
+		return ret;
 
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
-				     3 + args->head, sizeof(*dmac),
+	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
+				     args->v0.head, sizeof(*dmac),
 				     (void **)&dmac);
 	*pobject = nv_object(dmac);
 	if (ret)
 		return ret;
 
-	nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
-	nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
 	return 0;
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nv50_disp_ovly_ofuncs = {
-	.ctor = nv50_disp_ovly_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nv50_disp_dmac_init,
-	.fini = nv50_disp_dmac_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_ovly_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nv50_disp_dmac_init,
+	.base.fini = nv50_disp_dmac_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 3,
+	.attach = nv50_disp_dmac_object_attach,
+	.detach = nv50_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -662,14 +711,14 @@ nv50_disp_ovly_ofuncs = {
 static int
 nv50_disp_pioc_create_(struct nouveau_object *parent,
 		       struct nouveau_object *engine,
-		       struct nouveau_oclass *oclass, int chid,
+		       struct nouveau_oclass *oclass, int head,
 		       int length, void **pobject)
 {
-	return nv50_disp_chan_create_(parent, engine, oclass, chid,
+	return nv50_disp_chan_create_(parent, engine, oclass, head,
 				      length, pobject);
 }
 
-static void
+void
 nv50_disp_pioc_dtor(struct nouveau_object *object)
 {
 	struct nv50_disp_pioc *pioc = (void *)object;
@@ -727,20 +776,29 @@ nv50_disp_pioc_fini(struct nouveau_objec
  * EVO immediate overlay channel objects
  ******************************************************************************/
 
-static int
+int
 nv50_disp_oimm_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
-	struct nv50_display_oimm_class *args = data;
+	union {
+		struct nv50_disp_overlay_v0 v0;
+	} *args = data;
+	struct nv50_disp_priv *priv = (void *)engine;
 	struct nv50_disp_pioc *pioc;
 	int ret;
 
-	if (size < sizeof(*args) || args->head > 1)
-		return -EINVAL;
+	nv_ioctl(parent, "create disp overlay size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create disp overlay vers %d head %d\n",
+			 args->v0.version, args->v0.head);
+		if (args->v0.head > priv->head.nr)
+			return -EINVAL;
+	} else
+		return ret;
 
-	ret = nv50_disp_pioc_create_(parent, engine, oclass, 5 + args->head,
+	ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
 				     sizeof(*pioc), (void **)&pioc);
 	*pobject = nv_object(pioc);
 	if (ret)
@@ -749,34 +807,45 @@ nv50_disp_oimm_ctor(struct nouveau_objec
 	return 0;
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nv50_disp_oimm_ofuncs = {
-	.ctor = nv50_disp_oimm_ctor,
-	.dtor = nv50_disp_pioc_dtor,
-	.init = nv50_disp_pioc_init,
-	.fini = nv50_disp_pioc_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_oimm_ctor,
+	.base.dtor = nv50_disp_pioc_dtor,
+	.base.init = nv50_disp_pioc_init,
+	.base.fini = nv50_disp_pioc_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 5,
 };
 
 /*******************************************************************************
  * EVO cursor channel objects
  ******************************************************************************/
 
-static int
+int
 nv50_disp_curs_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
-	struct nv50_display_curs_class *args = data;
+	union {
+		struct nv50_disp_cursor_v0 v0;
+	} *args = data;
+	struct nv50_disp_priv *priv = (void *)engine;
 	struct nv50_disp_pioc *pioc;
 	int ret;
 
-	if (size < sizeof(*args) || args->head > 1)
-		return -EINVAL;
+	nv_ioctl(parent, "create disp cursor size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create disp cursor vers %d head %d\n",
+			 args->v0.version, args->v0.head);
+		if (args->v0.head > priv->head.nr)
+			return -EINVAL;
+	} else
+		return ret;
 
-	ret = nv50_disp_pioc_create_(parent, engine, oclass, 7 + args->head,
+	ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
 				     sizeof(*pioc), (void **)&pioc);
 	*pobject = nv_object(pioc);
 	if (ret)
@@ -785,14 +854,16 @@ nv50_disp_curs_ctor(struct nouveau_objec
 	return 0;
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nv50_disp_curs_ofuncs = {
-	.ctor = nv50_disp_curs_ctor,
-	.dtor = nv50_disp_pioc_dtor,
-	.init = nv50_disp_pioc_init,
-	.fini = nv50_disp_pioc_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_curs_ctor,
+	.base.dtor = nv50_disp_pioc_dtor,
+	.base.init = nv50_disp_pioc_init,
+	.base.fini = nv50_disp_pioc_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 7,
 };
 
 /*******************************************************************************
@@ -800,47 +871,162 @@ nv50_disp_curs_ofuncs = {
  ******************************************************************************/
 
 int
-nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
-			  void *data, u32 size)
+nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
 {
-	struct nv50_disp_priv *priv = (void *)object->engine;
-	struct nv04_display_scanoutpos *args = data;
-	const int head = (mthd & NV50_DISP_MTHD_HEAD);
-	u32 blanke, blanks, total;
-
-	if (size < sizeof(*args) || head >= priv->head.nr)
-		return -EINVAL;
-	blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
-	blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
-	total  = nv_rd32(priv, 0x610afc + (head * 0x540));
+	const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+	const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+	const u32 total  = nv_rd32(priv, 0x610afc + (head * 0x540));
+	union {
+		struct nv04_disp_scanoutpos_v0 v0;
+	} *args = data;
+	int ret;
 
-	args->vblanke = (blanke & 0xffff0000) >> 16;
-	args->hblanke = (blanke & 0x0000ffff);
-	args->vblanks = (blanks & 0xffff0000) >> 16;
-	args->hblanks = (blanks & 0x0000ffff);
-	args->vtotal  = ( total & 0xffff0000) >> 16;
-	args->htotal  = ( total & 0x0000ffff);
+	nv_ioctl(object, "disp scanoutpos size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+		args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+		args->v0.hblanke = (blanke & 0x0000ffff);
+		args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+		args->v0.hblanks = (blanks & 0x0000ffff);
+		args->v0.vtotal  = ( total & 0xffff0000) >> 16;
+		args->v0.htotal  = ( total & 0x0000ffff);
+		args->v0.time[0] = ktime_to_ns(ktime_get());
+		args->v0.vline = /* vline read locks hline */
+			nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+		args->v0.time[1] = ktime_to_ns(ktime_get());
+		args->v0.hline =
+			nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+	} else
+		return ret;
 
-	args->time[0] = ktime_to_ns(ktime_get());
-	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
-	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
-	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
 	return 0;
 }
 
-static void
-nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
+int
+nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
+		    void *data, u32 size)
 {
-	nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
-}
+	const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
+	union {
+		struct nv50_disp_mthd_v0 v0;
+		struct nv50_disp_mthd_v1 v1;
+	} *args = data;
+	struct nv50_disp_priv *priv = (void *)object->engine;
+	struct nvkm_output *outp = NULL;
+	struct nvkm_output *temp;
+	u16 type, mask = 0;
+	int head, ret;
 
-static void
-nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
-{
-	nv_mask(event->priv, 0x61002c, (4 << head), 0);
+	if (mthd != NV50_DISP_MTHD)
+		return -EINVAL;
+
+	nv_ioctl(object, "disp mthd size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+			 args->v0.version, args->v0.method, args->v0.head);
+		mthd = args->v0.method;
+		head = args->v0.head;
+	} else
+	if (nvif_unpack(args->v1, 1, 1, true)) {
+		nv_ioctl(object, "disp mthd vers %d mthd %02x "
+				 "type %04x mask %04x\n",
+			 args->v1.version, args->v1.method,
+			 args->v1.hasht, args->v1.hashm);
+		mthd = args->v1.method;
+		type = args->v1.hasht;
+		mask = args->v1.hashm;
+		head = ffs((mask >> 8) & 0x0f) - 1;
+	} else
+		return ret;
+
+	if (head < 0 || head >= priv->head.nr)
+		return -ENXIO;
+
+	if (mask) {
+		list_for_each_entry(temp, &priv->base.outp, head) {
+			if ((temp->info.hasht         == type) &&
+			    (temp->info.hashm & mask) == mask) {
+				outp = temp;
+				break;
+			}
+		}
+		if (outp == NULL)
+			return -ENXIO;
+	}
+
+	switch (mthd) {
+	case NV50_DISP_SCANOUTPOS:
+		return impl->head.scanoutpos(object, priv, data, size, head);
+	default:
+		break;
+	}
+
+	switch (mthd * !!outp) {
+	case NV50_DISP_MTHD_V1_DAC_PWR:
+		return priv->dac.power(object, priv, data, size, head, outp);
+	case NV50_DISP_MTHD_V1_DAC_LOAD:
+		return priv->dac.sense(object, priv, data, size, head, outp);
+	case NV50_DISP_MTHD_V1_SOR_PWR:
+		return priv->sor.power(object, priv, data, size, head, outp);
+	case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
+		if (!priv->sor.hda_eld)
+			return -ENODEV;
+		return priv->sor.hda_eld(object, priv, data, size, head, outp);
+	case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
+		if (!priv->sor.hdmi)
+			return -ENODEV;
+		return priv->sor.hdmi(object, priv, data, size, head, outp);
+	case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
+		union {
+			struct nv50_disp_sor_lvds_script_v0 v0;
+		} *args = data;
+		nv_ioctl(object, "disp sor lvds script size %d\n", size);
+		if (nvif_unpack(args->v0, 0, 0, false)) {
+			nv_ioctl(object, "disp sor lvds script "
+					 "vers %d name %04x\n",
+				 args->v0.version, args->v0.script);
+			priv->sor.lvdsconf = args->v0.script;
+			return 0;
+		} else
+			return ret;
+	}
+		break;
+	case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
+		struct nvkm_output_dp *outpdp = (void *)outp;
+		union {
+			struct nv50_disp_sor_dp_pwr_v0 v0;
+		} *args = data;
+		nv_ioctl(object, "disp sor dp pwr size %d\n", size);
+		if (nvif_unpack(args->v0, 0, 0, false)) {
+			nv_ioctl(object, "disp sor dp pwr vers %d state %d\n",
+				 args->v0.version, args->v0.state);
+			if (args->v0.state == 0) {
+				nvkm_notify_put(&outpdp->irq);
+				((struct nvkm_output_dp_impl *)nv_oclass(outp))
+					->lnk_pwr(outpdp, 0);
+				atomic_set(&outpdp->lt.done, 0);
+				return 0;
+			} else
+			if (args->v0.state != 0) {
+				nvkm_output_dp_train(&outpdp->base, 0, true);
+				return 0;
+			}
+		} else
+			return ret;
+	}
+		break;
+	case NV50_DISP_MTHD_V1_PIOR_PWR:
+		if (!priv->pior.power)
+			return -ENODEV;
+		return priv->pior.power(object, priv, data, size, head, outp);
+	default:
+		break;
+	}
+
+	return -EINVAL;
 }
 
-static int
+int
 nv50_disp_base_ctor(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
 		    struct nouveau_oclass *oclass, void *data, u32 size,
@@ -856,14 +1042,11 @@ nv50_disp_base_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
-	priv->base.vblank->priv = priv;
-	priv->base.vblank->enable = nv50_disp_base_vblank_enable;
-	priv->base.vblank->disable = nv50_disp_base_vblank_disable;
 	return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
 				&base->ramht);
 }
 
-static void
+void
 nv50_disp_base_dtor(struct nouveau_object *object)
 {
 	struct nv50_disp_base *base = (void *)object;
@@ -958,34 +1141,23 @@ nv50_disp_base_ofuncs = {
 	.dtor = nv50_disp_base_dtor,
 	.init = nv50_disp_base_init,
 	.fini = nv50_disp_base_fini,
-};
-
-static struct nouveau_omthds
-nv50_disp_base_omthds[] = {
-	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
-	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
-	{},
+	.mthd = nv50_disp_base_mthd,
+	.ntfy = nouveau_disp_ntfy,
 };
 
 static struct nouveau_oclass
 nv50_disp_base_oclass[] = {
-	{ NV50_DISP_CLASS, &nv50_disp_base_ofuncs, nv50_disp_base_omthds },
+	{ NV50_DISP, &nv50_disp_base_ofuncs },
 	{}
 };
 
 static struct nouveau_oclass
 nv50_disp_sclass[] = {
-	{ NV50_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
-	{ NV50_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
-	{ NV50_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
-	{ NV50_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
-	{ NV50_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+	{ NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+	{ NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+	{ NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+	{ NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+	{ NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
 	{}
 };
 
@@ -1005,7 +1177,7 @@ nv50_disp_data_ctor(struct nouveau_objec
 	int ret = -EBUSY;
 
 	/* no context needed for channel objects... */
-	if (nv_mclass(parent) != NV_DEVICE_CLASS) {
+	if (nv_mclass(parent) != NV_DEVICE) {
 		atomic_inc(&parent->refcount);
 		*pobject = parent;
 		return 1;
@@ -1040,6 +1212,27 @@ nv50_disp_cclass = {
  * Display engine implementation
  ******************************************************************************/
 
+static void
+nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
+{
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_mask(disp, 0x61002c, (4 << head), 0);
+}
+
+static void
+nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
+{
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_mask(disp, 0x61002c, (4 << head), (4 << head));
+}
+
+const struct nvkm_event_func
+nv50_disp_vblank_func = {
+	.ctor = nouveau_disp_vblank_ctor,
+	.init = nv50_disp_vblank_init,
+	.fini = nv50_disp_vblank_fini,
+};
+
 static const struct nouveau_enum
 nv50_disp_intr_error_type[] = {
 	{ 3, "ILLEGAL_MTHD" },
@@ -1381,7 +1574,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_di
 	int TU, VTUi, VTUf, VTUa;
 	u64 link_data_rate, link_ratio, unk;
 	u32 best_diff = 64 * symbol;
-	u32 link_nr, link_bw, bits, r;
+	u32 link_nr, link_bw, bits;
 
 	/* calculate packed data rate for each lane */
 	if      (dpctrl > 0x00030000) link_nr = 4;
@@ -1401,7 +1594,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_di
 
 	/* calculate ratio of packed data rate to link symbol rate */
 	link_ratio = link_data_rate * symbol;
-	r = do_div(link_ratio, link_bw);
+	do_div(link_ratio, link_bw);
 
 	for (TU = 64; TU >= 32; TU--) {
 		/* calculate average number of valid symbols in each TU */
@@ -1462,8 +1655,8 @@ nv50_disp_intr_unk20_2_dp(struct nv50_di
 	/* XXX close to vbios numbers, but not right */
 	unk  = (symbol - link_ratio) * bestTU;
 	unk *= link_ratio;
-	r = do_div(unk, symbol);
-	r = do_div(unk, symbol);
+	do_div(unk, symbol);
+	do_div(unk, symbol);
 	unk += 6;
 
 	nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2);
@@ -1654,13 +1847,13 @@ nv50_disp_intr(struct nouveau_subdev *su
 	}
 
 	if (intr1 & 0x00000004) {
-		nouveau_event_trigger(priv->base.vblank, 1, 0);
+		nouveau_disp_vblank(&priv->base, 0);
 		nv_wr32(priv, 0x610024, 0x00000004);
 		intr1 &= ~0x00000004;
 	}
 
 	if (intr1 & 0x00000008) {
-		nouveau_event_trigger(priv->base.vblank, 1, 1);
+		nouveau_disp_vblank(&priv->base, 1);
 		nv_wr32(priv, 0x610024, 0x00000008);
 		intr1 &= ~0x00000008;
 	}
@@ -1718,9 +1911,11 @@ nv50_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nv50_disp_vblank_func,
 	.base.outp =  nv50_disp_outp_sclass,
 	.mthd.core = &nv50_disp_mast_mthd_chan,
 	.mthd.base = &nv50_disp_sync_mthd_chan,
 	.mthd.ovly = &nv50_disp_ovly_mthd_chan,
 	.mthd.prev = 0x000004,
+	.head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,15 +14,10 @@
 #include "outp.h"
 #include "outpdp.h"
 
-struct nv50_disp_impl {
-	struct nouveau_disp_impl base;
-	struct {
-		const struct nv50_disp_mthd_chan *core;
-		const struct nv50_disp_mthd_chan *base;
-		const struct nv50_disp_mthd_chan *ovly;
-		int prev;
-	} mthd;
-};
+#define NV50_DISP_MTHD_ struct nouveau_object *object,                         \
+	struct nv50_disp_priv *priv, void *data, u32 size
+#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
+#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp
 
 struct nv50_disp_priv {
 	struct nouveau_disp base;
@@ -36,44 +31,52 @@ struct nv50_disp_priv {
 	} head;
 	struct {
 		int nr;
-		int (*power)(struct nv50_disp_priv *, int dac, u32 data);
-		int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
+		int (*power)(NV50_DISP_MTHD_V1);
+		int (*sense)(NV50_DISP_MTHD_V1);
 	} dac;
 	struct {
 		int nr;
-		int (*power)(struct nv50_disp_priv *, int sor, u32 data);
-		int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
-		int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
+		int (*power)(NV50_DISP_MTHD_V1);
+		int (*hda_eld)(NV50_DISP_MTHD_V1);
+		int (*hdmi)(NV50_DISP_MTHD_V1);
 		u32 lvdsconf;
 	} sor;
 	struct {
 		int nr;
-		int (*power)(struct nv50_disp_priv *, int ext, u32 data);
+		int (*power)(NV50_DISP_MTHD_V1);
 		u8 type[3];
 	} pior;
 };
 
-#define HEAD_MTHD(n) (n), (n) + 0x03
-
-int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+struct nv50_disp_impl {
+	struct nouveau_disp_impl base;
+	struct {
+		const struct nv50_disp_mthd_chan *core;
+		const struct nv50_disp_mthd_chan *base;
+		const struct nv50_disp_mthd_chan *ovly;
+		int prev;
+	} mthd;
+	struct {
+		int (*scanoutpos)(NV50_DISP_MTHD_V0);
+	} head;
+};
 
-#define DAC_MTHD(n) (n), (n) + 0x03
+int nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
+int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
 
-int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_dac_power(struct nv50_disp_priv *, int, u32);
-int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
+int nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
 
-#define SOR_MTHD(n) (n), (n) + 0x3f
+int nv50_dac_power(NV50_DISP_MTHD_V1);
+int nv50_dac_sense(NV50_DISP_MTHD_V1);
 
-int nva3_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
-int nvd0_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
+int nva3_hda_eld(NV50_DISP_MTHD_V1);
+int nvd0_hda_eld(NV50_DISP_MTHD_V1);
 
-int nv84_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
-int nva3_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
-int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
+int nv84_hdmi_ctrl(NV50_DISP_MTHD_V1);
+int nva3_hdmi_ctrl(NV50_DISP_MTHD_V1);
+int nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1);
 
-int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_sor_power(struct nv50_disp_priv *, int, u32);
+int nv50_sor_power(NV50_DISP_MTHD_V1);
 
 int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16,
 		           u32, struct dcb_output *);
@@ -93,10 +96,7 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_
 int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
 		       struct dcb_output *);
 
-#define PIOR_MTHD(n) (n), (n) + 0x03
-
-int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_pior_power(struct nv50_disp_priv *, int, u32);
+int nv50_pior_power(NV50_DISP_MTHD_V1);
 
 struct nv50_disp_base {
 	struct nouveau_parent base;
@@ -104,14 +104,19 @@ struct nv50_disp_base {
 	u32 chan;
 };
 
+struct nv50_disp_chan_impl {
+	struct nouveau_ofuncs base;
+	int chid;
+	int  (*attach)(struct nouveau_object *, struct nouveau_object *, u32);
+	void (*detach)(struct nouveau_object *, int);
+};
+
 struct nv50_disp_chan {
 	struct nouveau_namedb base;
 	int chid;
 };
 
-int  nv50_disp_chan_create_(struct nouveau_object *, struct nouveau_object *,
-			    struct nouveau_oclass *, int, int, void **);
-void nv50_disp_chan_destroy(struct nv50_disp_chan *);
+int  nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *);
 u32  nv50_disp_chan_rd32(struct nouveau_object *, u64);
 void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
 
@@ -120,20 +125,20 @@ void nv50_disp_chan_wr32(struct nouveau_
 #define nv50_disp_chan_fini(a,b)                                               \
 	nouveau_namedb_fini(&(a)->base, (b))
 
-int  nv50_disp_dmac_create_(struct nouveau_object *, struct nouveau_object *,
-			    struct nouveau_oclass *, u32, int, int, void **);
-void nv50_disp_dmac_dtor(struct nouveau_object *);
-
 struct nv50_disp_dmac {
 	struct nv50_disp_chan base;
 	struct nouveau_dmaobj *pushdma;
 	u32 push;
 };
 
+void nv50_disp_dmac_dtor(struct nouveau_object *);
+
 struct nv50_disp_pioc {
 	struct nv50_disp_chan base;
 };
 
+void nv50_disp_pioc_dtor(struct nouveau_object *);
+
 struct nv50_disp_mthd_list {
 	u32 mthd;
 	u32 addr;
@@ -154,47 +159,67 @@ struct nv50_disp_mthd_chan {
 	} data[];
 };
 
-extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_mast_ofuncs;
+int nv50_disp_mast_ctor(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void *, u32,
+			struct nouveau_object **);
 extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
 extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
 extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
-extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_sync_ofuncs;
+int nv50_disp_sync_ctor(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void *, u32,
+			struct nouveau_object **);
 extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
-extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs;
+int nv50_disp_ovly_ctor(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void *, u32,
+			struct nouveau_object **);
 extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
-extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
-extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs;
+int nv50_disp_oimm_ctor(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void *, u32,
+			struct nouveau_object **);
+extern struct nv50_disp_chan_impl nv50_disp_curs_ofuncs;
+int nv50_disp_curs_ctor(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void *, u32,
+			struct nouveau_object **);
 extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
+int  nv50_disp_base_ctor(struct nouveau_object *, struct nouveau_object *,
+			 struct nouveau_oclass *, void *, u32,
+			 struct nouveau_object **);
+void nv50_disp_base_dtor(struct nouveau_object *);
+extern struct nouveau_omthds nv50_disp_base_omthds[];
 extern struct nouveau_oclass nv50_disp_cclass;
 void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
 			 const struct nv50_disp_mthd_chan *);
 void nv50_disp_intr_supervisor(struct work_struct *);
 void nv50_disp_intr(struct nouveau_subdev *);
+extern const struct nvkm_event_func nv50_disp_vblank_func;
 
 extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
 extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
 extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
 extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
 extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
-extern struct nouveau_omthds nv84_disp_base_omthds[];
 
 extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
 
-extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_mast_ofuncs;
 extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
 extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
 extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
 extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
-extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
-extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_sync_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_ovly_ofuncs;
 extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
-extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
-extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
-extern struct nouveau_omthds nvd0_disp_base_omthds[];
+extern struct nv50_disp_chan_impl nvd0_disp_oimm_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_curs_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
 extern struct nouveau_oclass nvd0_disp_cclass;
 void nvd0_disp_intr_supervisor(struct work_struct *);
 void nvd0_disp_intr(struct nouveau_subdev *);
+extern const struct nvkm_event_func nvd0_disp_vblank_func;
 
 extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
 extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -204,31 +204,17 @@ nv84_disp_ovly_mthd_chan = {
 
 static struct nouveau_oclass
 nv84_disp_sclass[] = {
-	{ NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
-	{ NV84_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
-	{ NV84_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
-	{ NV84_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
-	{ NV84_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+	{ G82_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+	{ G82_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+	{ G82_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+	{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+	{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
 	{}
 };
 
-struct nouveau_omthds
-nv84_disp_base_omthds[] = {
-	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
-	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
-	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
-	{},
-};
-
 static struct nouveau_oclass
 nv84_disp_base_oclass[] = {
-	{ NV84_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+	{ G82_DISP, &nv50_disp_base_ofuncs },
 	{}
 };
 
@@ -276,9 +262,11 @@ nv84_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nv50_disp_vblank_func,
 	.base.outp =  nv50_disp_outp_sclass,
 	.mthd.core = &nv84_disp_mast_mthd_chan,
 	.mthd.base = &nv84_disp_sync_mthd_chan,
 	.mthd.ovly = &nv84_disp_ovly_mthd_chan,
 	.mthd.prev = 0x000004,
+	.head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -63,32 +63,17 @@ nv94_disp_mast_mthd_chan = {
 
 static struct nouveau_oclass
 nv94_disp_sclass[] = {
-	{ NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
-	{ NV94_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
-	{ NV94_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
-	{ NV94_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
-	{ NV94_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+	{ GT206_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+	{ GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+	{ GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+	{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+	{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
 	{}
 };
 
-static struct nouveau_omthds
-nv94_disp_base_omthds[] = {
-	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
-	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
-	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
-	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
-	{},
-};
-
 static struct nouveau_oclass
 nv94_disp_base_oclass[] = {
-	{ NV94_DISP_CLASS, &nv50_disp_base_ofuncs, nv94_disp_base_omthds },
+	{ GT206_DISP, &nv50_disp_base_ofuncs },
 	{}
 };
 
@@ -143,9 +128,11 @@ nv94_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nv50_disp_vblank_func,
 	.base.outp =  nv94_disp_outp_sclass,
 	.mthd.core = &nv94_disp_mast_mthd_chan,
 	.mthd.base = &nv84_disp_sync_mthd_chan,
 	.mthd.ovly = &nv84_disp_ovly_mthd_chan,
 	.mthd.prev = 0x000004,
+	.head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -80,17 +80,17 @@ nva0_disp_ovly_mthd_chan = {
 
 static struct nouveau_oclass
 nva0_disp_sclass[] = {
-	{ NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
-	{ NVA0_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
-	{ NVA0_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
-	{ NVA0_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
-	{ NVA0_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+	{ GT200_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+	{ GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+	{ GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+	{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+	{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
 	{}
 };
 
 static struct nouveau_oclass
 nva0_disp_base_oclass[] = {
-	{ NVA0_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+	{ GT200_DISP, &nv50_disp_base_ofuncs },
 	{}
 };
 
@@ -138,9 +138,11 @@ nva0_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nv50_disp_vblank_func,
 	.base.outp =  nv50_disp_outp_sclass,
 	.mthd.core = &nv84_disp_mast_mthd_chan,
 	.mthd.base = &nv84_disp_sync_mthd_chan,
 	.mthd.ovly = &nva0_disp_ovly_mthd_chan,
 	.mthd.prev = 0x000004,
+	.head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -35,33 +35,17 @@
 
 static struct nouveau_oclass
 nva3_disp_sclass[] = {
-	{ NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
-	{ NVA3_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
-	{ NVA3_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
-	{ NVA3_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
-	{ NVA3_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+	{ GT214_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+	{ GT214_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+	{ GT214_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+	{ GT214_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+	{ GT214_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
 	{}
 };
 
-static struct nouveau_omthds
-nva3_disp_base_omthds[] = {
-	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
-	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },
-	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
-	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
-	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
-	{},
-};
-
 static struct nouveau_oclass
 nva3_disp_base_oclass[] = {
-	{ NVA3_DISP_CLASS, &nv50_disp_base_ofuncs, nva3_disp_base_omthds },
+	{ GT214_DISP, &nv50_disp_base_ofuncs },
 	{}
 };
 
@@ -110,9 +94,11 @@ nva3_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nv50_disp_vblank_func,
 	.base.outp =  nv94_disp_outp_sclass,
 	.mthd.core = &nv94_disp_mast_mthd_chan,
 	.mthd.base = &nv84_disp_sync_mthd_chan,
 	.mthd.ovly = &nv84_disp_ovly_mthd_chan,
 	.mthd.prev = 0x000004,
+	.head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,9 +23,11 @@
  */
 
 #include <core/object.h>
+#include <core/client.h>
 #include <core/parent.h>
 #include <core/handle.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <engine/disp.h>
 
@@ -265,30 +267,6 @@ nvd0_disp_mast_mthd_chan = {
 };
 
 static int
-nvd0_disp_mast_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
-{
-	struct nv50_display_mast_class *args = data;
-	struct nv50_disp_dmac *mast;
-	int ret;
-
-	if (size < sizeof(*args))
-		return -EINVAL;
-
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
-				     0, sizeof(*mast), (void **)&mast);
-	*pobject = nv_object(mast);
-	if (ret)
-		return ret;
-
-	nv_parent(mast)->object_attach = nvd0_disp_dmac_object_attach;
-	nv_parent(mast)->object_detach = nvd0_disp_dmac_object_detach;
-	return 0;
-}
-
-static int
 nvd0_disp_mast_init(struct nouveau_object *object)
 {
 	struct nv50_disp_priv *priv = (void *)object->engine;
@@ -342,14 +320,18 @@ nvd0_disp_mast_fini(struct nouveau_objec
 	return nv50_disp_chan_fini(&mast->base, suspend);
 }
 
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nvd0_disp_mast_ofuncs = {
-	.ctor = nvd0_disp_mast_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nvd0_disp_mast_init,
-	.fini = nvd0_disp_mast_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_mast_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nvd0_disp_mast_init,
+	.base.fini = nvd0_disp_mast_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 0,
+	.attach = nvd0_disp_dmac_object_attach,
+	.detach = nvd0_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -431,40 +413,18 @@ nvd0_disp_sync_mthd_chan = {
 	}
 };
 
-static int
-nvd0_disp_sync_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
-{
-	struct nv50_display_sync_class *args = data;
-	struct nv50_disp_priv *priv = (void *)engine;
-	struct nv50_disp_dmac *dmac;
-	int ret;
-
-	if (size < sizeof(*args) || args->head >= priv->head.nr)
-		return -EINVAL;
-
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
-				     1 + args->head, sizeof(*dmac),
-				     (void **)&dmac);
-	*pobject = nv_object(dmac);
-	if (ret)
-		return ret;
-
-	nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
-	nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
-	return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nvd0_disp_sync_ofuncs = {
-	.ctor = nvd0_disp_sync_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nvd0_disp_dmac_init,
-	.fini = nvd0_disp_dmac_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_sync_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nvd0_disp_dmac_init,
+	.base.fini = nvd0_disp_dmac_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 1,
+	.attach = nvd0_disp_dmac_object_attach,
+	.detach = nvd0_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -533,40 +493,18 @@ nvd0_disp_ovly_mthd_chan = {
 	}
 };
 
-static int
-nvd0_disp_ovly_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
-{
-	struct nv50_display_ovly_class *args = data;
-	struct nv50_disp_priv *priv = (void *)engine;
-	struct nv50_disp_dmac *dmac;
-	int ret;
-
-	if (size < sizeof(*args) || args->head >= priv->head.nr)
-		return -EINVAL;
-
-	ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
-				     5 + args->head, sizeof(*dmac),
-				     (void **)&dmac);
-	*pobject = nv_object(dmac);
-	if (ret)
-		return ret;
-
-	nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
-	nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
-	return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nvd0_disp_ovly_ofuncs = {
-	.ctor = nvd0_disp_ovly_ctor,
-	.dtor = nv50_disp_dmac_dtor,
-	.init = nvd0_disp_dmac_init,
-	.fini = nvd0_disp_dmac_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_ovly_ctor,
+	.base.dtor = nv50_disp_dmac_dtor,
+	.base.init = nvd0_disp_dmac_init,
+	.base.fini = nvd0_disp_dmac_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 5,
+	.attach = nvd0_disp_dmac_object_attach,
+	.detach = nvd0_disp_dmac_object_detach,
 };
 
 /*******************************************************************************
@@ -574,23 +512,6 @@ nvd0_disp_ovly_ofuncs = {
  ******************************************************************************/
 
 static int
-nvd0_disp_pioc_create_(struct nouveau_object *parent,
-		       struct nouveau_object *engine,
-		       struct nouveau_oclass *oclass, int chid,
-		       int length, void **pobject)
-{
-	return nv50_disp_chan_create_(parent, engine, oclass, chid,
-				      length, pobject);
-}
-
-static void
-nvd0_disp_pioc_dtor(struct nouveau_object *object)
-{
-	struct nv50_disp_pioc *pioc = (void *)object;
-	nv50_disp_chan_destroy(&pioc->base);
-}
-
-static int
 nvd0_disp_pioc_init(struct nouveau_object *object)
 {
 	struct nv50_disp_priv *priv = (void *)object->engine;
@@ -643,152 +564,68 @@ nvd0_disp_pioc_fini(struct nouveau_objec
  * EVO immediate overlay channel objects
  ******************************************************************************/
 
-static int
-nvd0_disp_oimm_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
-{
-	struct nv50_display_oimm_class *args = data;
-	struct nv50_disp_priv *priv = (void *)engine;
-	struct nv50_disp_pioc *pioc;
-	int ret;
-
-	if (size < sizeof(*args) || args->head >= priv->head.nr)
-		return -EINVAL;
-
-	ret = nvd0_disp_pioc_create_(parent, engine, oclass, 9 + args->head,
-				     sizeof(*pioc), (void **)&pioc);
-	*pobject = nv_object(pioc);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nvd0_disp_oimm_ofuncs = {
-	.ctor = nvd0_disp_oimm_ctor,
-	.dtor = nvd0_disp_pioc_dtor,
-	.init = nvd0_disp_pioc_init,
-	.fini = nvd0_disp_pioc_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_oimm_ctor,
+	.base.dtor = nv50_disp_pioc_dtor,
+	.base.init = nvd0_disp_pioc_init,
+	.base.fini = nvd0_disp_pioc_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 9,
 };
 
 /*******************************************************************************
  * EVO cursor channel objects
  ******************************************************************************/
 
-static int
-nvd0_disp_curs_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
-{
-	struct nv50_display_curs_class *args = data;
-	struct nv50_disp_priv *priv = (void *)engine;
-	struct nv50_disp_pioc *pioc;
-	int ret;
-
-	if (size < sizeof(*args) || args->head >= priv->head.nr)
-		return -EINVAL;
-
-	ret = nvd0_disp_pioc_create_(parent, engine, oclass, 13 + args->head,
-				     sizeof(*pioc), (void **)&pioc);
-	*pobject = nv_object(pioc);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
 nvd0_disp_curs_ofuncs = {
-	.ctor = nvd0_disp_curs_ctor,
-	.dtor = nvd0_disp_pioc_dtor,
-	.init = nvd0_disp_pioc_init,
-	.fini = nvd0_disp_pioc_fini,
-	.rd32 = nv50_disp_chan_rd32,
-	.wr32 = nv50_disp_chan_wr32,
+	.base.ctor = nv50_disp_curs_ctor,
+	.base.dtor = nv50_disp_pioc_dtor,
+	.base.init = nvd0_disp_pioc_init,
+	.base.fini = nvd0_disp_pioc_fini,
+	.base.map  = nv50_disp_chan_map,
+	.base.rd32 = nv50_disp_chan_rd32,
+	.base.wr32 = nv50_disp_chan_wr32,
+	.chid = 13,
 };
 
 /*******************************************************************************
  * Base display object
  ******************************************************************************/
 
-static int
-nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
-			  void *data, u32 size)
-{
-	struct nv50_disp_priv *priv = (void *)object->engine;
-	struct nv04_display_scanoutpos *args = data;
-	const int head = (mthd & NV50_DISP_MTHD_HEAD);
-	u32 blanke, blanks, total;
-
-	if (size < sizeof(*args) || head >= priv->head.nr)
-		return -EINVAL;
-
-	total  = nv_rd32(priv, 0x640414 + (head * 0x300));
-	blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
-	blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
-
-	args->vblanke = (blanke & 0xffff0000) >> 16;
-	args->hblanke = (blanke & 0x0000ffff);
-	args->vblanks = (blanks & 0xffff0000) >> 16;
-	args->hblanks = (blanks & 0x0000ffff);
-	args->vtotal  = ( total & 0xffff0000) >> 16;
-	args->htotal  = ( total & 0x0000ffff);
-
-	args->time[0] = ktime_to_ns(ktime_get());
-	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
-	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
-	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
-	return 0;
-}
-
-static void
-nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
-{
-	nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
-}
-
-static void
-nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
-{
-	nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
-}
-
-static int
-nvd0_disp_base_ctor(struct nouveau_object *parent,
-		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
+int
+nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
 {
-	struct nv50_disp_priv *priv = (void *)engine;
-	struct nv50_disp_base *base;
+	const u32 total  = nv_rd32(priv, 0x640414 + (head * 0x300));
+	const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+	const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+	union {
+		struct nv04_disp_scanoutpos_v0 v0;
+	} *args = data;
 	int ret;
 
-	ret = nouveau_parent_create(parent, engine, oclass, 0,
-				    priv->sclass, 0, &base);
-	*pobject = nv_object(base);
-	if (ret)
+	nv_ioctl(object, "disp scanoutpos size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+		args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+		args->v0.hblanke = (blanke & 0x0000ffff);
+		args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+		args->v0.hblanks = (blanks & 0x0000ffff);
+		args->v0.vtotal  = ( total & 0xffff0000) >> 16;
+		args->v0.htotal  = ( total & 0x0000ffff);
+		args->v0.time[0] = ktime_to_ns(ktime_get());
+		args->v0.vline = /* vline read locks hline */
+			nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+		args->v0.time[1] = ktime_to_ns(ktime_get());
+		args->v0.hline =
+			nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+	} else
 		return ret;
 
-	priv->base.vblank->priv = priv;
-	priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
-	priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
-
-	return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
-				&base->ramht);
-}
-
-static void
-nvd0_disp_base_dtor(struct nouveau_object *object)
-{
-	struct nv50_disp_base *base = (void *)object;
-	nouveau_ramht_ref(NULL, &base->ramht);
-	nouveau_parent_destroy(&base->base);
+	return 0;
 }
 
 static int
@@ -874,41 +711,27 @@ nvd0_disp_base_fini(struct nouveau_objec
 
 struct nouveau_ofuncs
 nvd0_disp_base_ofuncs = {
-	.ctor = nvd0_disp_base_ctor,
-	.dtor = nvd0_disp_base_dtor,
+	.ctor = nv50_disp_base_ctor,
+	.dtor = nv50_disp_base_dtor,
 	.init = nvd0_disp_base_init,
 	.fini = nvd0_disp_base_fini,
-};
-
-struct nouveau_omthds
-nvd0_disp_base_omthds[] = {
-	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nvd0_disp_base_scanoutpos },
-	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
-	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },
-	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
-	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
-	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
-	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
-	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
-	{},
+	.mthd = nv50_disp_base_mthd,
+	.ntfy = nouveau_disp_ntfy,
 };
 
 static struct nouveau_oclass
 nvd0_disp_base_oclass[] = {
-	{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+	{ GF110_DISP, &nvd0_disp_base_ofuncs },
 	{}
 };
 
 static struct nouveau_oclass
 nvd0_disp_sclass[] = {
-	{ NVD0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
-	{ NVD0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
-	{ NVD0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
-	{ NVD0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
-	{ NVD0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+	{ GF110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+	{ GF110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+	{ GF110_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+	{ GF110_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+	{ GF110_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
 	{}
 };
 
@@ -916,6 +739,27 @@ nvd0_disp_sclass[] = {
  * Display engine implementation
  ******************************************************************************/
 
+static void
+nvd0_disp_vblank_init(struct nvkm_event *event, int type, int head)
+{
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
+}
+
+static void
+nvd0_disp_vblank_fini(struct nvkm_event *event, int type, int head)
+{
+	struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+	nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
+}
+
+const struct nvkm_event_func
+nvd0_disp_vblank_func = {
+	.ctor = nouveau_disp_vblank_ctor,
+	.init = nvd0_disp_vblank_init,
+	.fini = nvd0_disp_vblank_fini,
+};
+
 static struct nvkm_output *
 exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
 	    u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@@ -1343,7 +1187,7 @@ nvd0_disp_intr(struct nouveau_subdev *su
 		if (mask & intr) {
 			u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
 			if (stat & 0x00000001)
-				nouveau_event_trigger(priv->base.vblank, 1, i);
+				nouveau_disp_vblank(&priv->base, i);
 			nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
 			nv_rd32(priv, 0x6100c0 + (i * 0x800));
 		}
@@ -1396,9 +1240,11 @@ nvd0_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nvd0_disp_vblank_func,
 	.base.outp =  nvd0_disp_outp_sclass,
 	.mthd.core = &nvd0_disp_mast_mthd_chan,
 	.mthd.base = &nvd0_disp_sync_mthd_chan,
 	.mthd.ovly = &nvd0_disp_ovly_mthd_chan,
 	.mthd.prev = -0x020000,
+	.head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -200,17 +200,17 @@ nve0_disp_ovly_mthd_chan = {
 
 static struct nouveau_oclass
 nve0_disp_sclass[] = {
-	{ NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
-	{ NVE0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
-	{ NVE0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
-	{ NVE0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
-	{ NVE0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+	{ GK104_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+	{ GK104_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+	{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+	{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+	{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
 	{}
 };
 
 static struct nouveau_oclass
 nve0_disp_base_oclass[] = {
-	{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+	{ GK104_DISP, &nvd0_disp_base_ofuncs },
 	{}
 };
 
@@ -258,9 +258,11 @@ nve0_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nvd0_disp_vblank_func,
 	.base.outp =  nvd0_disp_outp_sclass,
 	.mthd.core = &nve0_disp_mast_mthd_chan,
 	.mthd.base = &nvd0_disp_sync_mthd_chan,
 	.mthd.ovly = &nve0_disp_ovly_mthd_chan,
 	.mthd.prev = -0x020000,
+	.head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #include <engine/software.h>
 #include <engine/disp.h>
 
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include "nv50.h"
 
@@ -35,17 +35,17 @@
 
 static struct nouveau_oclass
 nvf0_disp_sclass[] = {
-	{ NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
-	{ NVF0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
-	{ NVF0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
-	{ NVF0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
-	{ NVF0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+	{ GK110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+	{ GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+	{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+	{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+	{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
 	{}
 };
 
 static struct nouveau_oclass
 nvf0_disp_base_oclass[] = {
-	{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+	{ GK110_DISP, &nvd0_disp_base_ofuncs },
 	{}
 };
 
@@ -93,9 +93,11 @@ nvf0_disp_oclass = &(struct nv50_disp_im
 		.init = _nouveau_disp_init,
 		.fini = _nouveau_disp_fini,
 	},
+	.base.vblank = &nvd0_disp_vblank_func,
 	.base.outp =  nvd0_disp_outp_sclass,
 	.mthd.core = &nve0_disp_mast_mthd_chan,
 	.mthd.base = &nvd0_disp_sync_mthd_chan,
 	.mthd.ovly = &nve0_disp_ovly_mthd_chan,
 	.mthd.prev = -0x020000,
+	.head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,6 +78,7 @@ nvkm_output_create_(struct nouveau_objec
 
 	outp->info = *dcbE;
 	outp->index = index;
+	outp->or = ffs(outp->info.or) - 1;
 
 	DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n",
 	    dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ?
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,9 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/os.h>
+#include <nvif/event.h>
+
 #include <subdev/i2c.h>
 
 #include "outpdp.h"
@@ -86,7 +89,7 @@ done:
 		atomic_set(&outp->lt.done, 0);
 		schedule_work(&outp->lt.work);
 	} else {
-		nouveau_event_get(outp->irq);
+		nvkm_notify_get(&outp->irq);
 	}
 
 	if (wait) {
@@ -133,46 +136,59 @@ nvkm_output_dp_detect(struct nvkm_output
 	}
 }
 
-static void
-nvkm_output_dp_service_work(struct work_struct *work)
+static int
+nvkm_output_dp_hpd(struct nvkm_notify *notify)
 {
-	struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work);
-	struct nouveau_disp *disp = nouveau_disp(outp);
-	int type = atomic_xchg(&outp->pending, 0);
-	u32 send = 0;
+	struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
+	struct nvkm_output_dp *outp;
+	struct nouveau_disp *disp = nouveau_disp(conn);
+	const struct nvkm_i2c_ntfy_rep *line = notify->data;
+	struct nvif_notify_conn_rep_v0 rep = {};
 
-	if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) {
-		nvkm_output_dp_detect(outp);
-		if (type & NVKM_I2C_UNPLUG)
-			send |= NVKM_HPD_UNPLUG;
-		if (type & NVKM_I2C_PLUG)
-			send |= NVKM_HPD_PLUG;
-		nouveau_event_get(outp->base.conn->hpd.event);
-	}
+	list_for_each_entry(outp, &disp->outp, base.head) {
+		if (outp->base.conn == conn &&
+		    outp->info.type == DCB_OUTPUT_DP) {
+			DBG("HPD: %d\n", line->mask);
+			nvkm_output_dp_detect(outp);
 
-	if (type & NVKM_I2C_IRQ) {
-		nvkm_output_dp_train(&outp->base, 0, true);
-		send |= NVKM_HPD_IRQ;
+			if (line->mask & NVKM_I2C_UNPLUG)
+				rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG;
+			if (line->mask & NVKM_I2C_PLUG)
+				rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG;
+
+			nvkm_event_send(&disp->hpd, rep.mask, conn->index,
+					&rep, sizeof(rep));
+			return NVKM_NOTIFY_KEEP;
+		}
 	}
 
-	nouveau_event_trigger(disp->hpd, send, outp->base.info.connector);
+	WARN_ON(1);
+	return NVKM_NOTIFY_DROP;
 }
 
 static int
-nvkm_output_dp_service(void *data, u32 type, int index)
+nvkm_output_dp_irq(struct nvkm_notify *notify)
 {
-	struct nvkm_output_dp *outp = data;
-	DBG("HPD: %d\n", type);
-	atomic_or(type, &outp->pending);
-	schedule_work(&outp->work);
-	return NVKM_EVENT_DROP;
+	struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), irq);
+	struct nouveau_disp *disp = nouveau_disp(outp);
+	const struct nvkm_i2c_ntfy_rep *line = notify->data;
+	struct nvif_notify_conn_rep_v0 rep = {
+		.mask = NVIF_NOTIFY_CONN_V0_IRQ,
+	};
+	int index = outp->base.info.connector;
+
+	DBG("IRQ: %d\n", line->mask);
+	nvkm_output_dp_train(&outp->base, 0, true);
+
+	nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
+	return NVKM_NOTIFY_DROP;
 }
 
 int
 _nvkm_output_dp_fini(struct nouveau_object *object, bool suspend)
 {
 	struct nvkm_output_dp *outp = (void *)object;
-	nouveau_event_put(outp->irq);
+	nvkm_notify_put(&outp->irq);
 	nvkm_output_dp_enable(outp, false);
 	return nvkm_output_fini(&outp->base, suspend);
 }
@@ -189,7 +205,7 @@ void
 _nvkm_output_dp_dtor(struct nouveau_object *object)
 {
 	struct nvkm_output_dp *outp = (void *)object;
-	nouveau_event_ref(NULL, &outp->irq);
+	nvkm_notify_fini(&outp->irq);
 	nvkm_output_destroy(&outp->base);
 }
 
@@ -213,7 +229,7 @@ nvkm_output_dp_create_(struct nouveau_ob
 	if (ret)
 		return ret;
 
-	nouveau_event_ref(NULL, &outp->base.conn->hpd.event);
+	nvkm_notify_fini(&outp->base.conn->hpd);
 
 	/* access to the aux channel is not optional... */
 	if (!outp->base.edid) {
@@ -238,20 +254,28 @@ nvkm_output_dp_create_(struct nouveau_ob
 	atomic_set(&outp->lt.done, 0);
 
 	/* link maintenance */
-	ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_IRQ, outp->base.edid->index,
-				nvkm_output_dp_service, outp, &outp->irq);
+	ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_irq, true,
+			       &(struct nvkm_i2c_ntfy_req) {
+				.mask = NVKM_I2C_IRQ,
+				.port = outp->base.edid->index,
+			       },
+			       sizeof(struct nvkm_i2c_ntfy_req),
+			       sizeof(struct nvkm_i2c_ntfy_rep),
+			       &outp->irq);
 	if (ret) {
 		ERR("error monitoring aux irq event: %d\n", ret);
 		return ret;
 	}
 
-	INIT_WORK(&outp->work, nvkm_output_dp_service_work);
-
 	/* hotplug detect, replaces gpio-based mechanism with aux events */
-	ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
-				outp->base.edid->index,
-				nvkm_output_dp_service, outp,
-			       &outp->base.conn->hpd.event);
+	ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_hpd, true,
+			       &(struct nvkm_i2c_ntfy_req) {
+				.mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
+				.port = outp->base.edid->index,
+			       },
+			       sizeof(struct nvkm_i2c_ntfy_req),
+			       sizeof(struct nvkm_i2c_ntfy_rep),
+			       &outp->base.conn->hpd);
 	if (ret) {
 		ERR("error monitoring aux hpd events: %d\n", ret);
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,10 +12,7 @@ struct nvkm_output_dp {
 	struct nvbios_dpout info;
 	u8 version;
 
-	struct nouveau_eventh *irq;
-	struct nouveau_eventh *hpd;
-	struct work_struct work;
-	atomic_t pending;
+	struct nvkm_notify irq;
 	bool present;
 	u8 dpcd[16];
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/outp.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@ struct nvkm_output {
 
 	struct dcb_output info;
 	int index;
+	int or;
 
 	struct nouveau_i2c_port *port;
 	struct nouveau_i2c_port *edid;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -143,38 +144,29 @@ nv50_pior_dp_impl = {
  *****************************************************************************/
 
 int
-nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data)
-{
-	const u32 stat = data & NV50_DISP_PIOR_PWR_STATE;
-	const u32 soff = (or * 0x800);
-	nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
-	nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat);
-	nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
-	return 0;
-}
-
-int
-nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
+nv50_pior_power(NV50_DISP_MTHD_V1)
 {
-	struct nv50_disp_priv *priv = (void *)object->engine;
-	const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12;
-	const u8 or   = (mthd & NV50_DISP_PIOR_MTHD_OR);
-	u32 *data = args;
+	const u32 soff = outp->or * 0x800;
+	union {
+		struct nv50_disp_pior_pwr_v0 v0;
+	} *args = data;
+	u32 ctrl, type;
 	int ret;
 
-	if (size < sizeof(u32))
-		return -EINVAL;
-
-	mthd &= ~NV50_DISP_PIOR_MTHD_TYPE;
-	mthd &= ~NV50_DISP_PIOR_MTHD_OR;
-	switch (mthd) {
-	case NV50_DISP_PIOR_PWR:
-		ret = priv->pior.power(priv, or, data[0]);
-		priv->pior.type[or] = type;
-		break;
-	default:
-		return -EINVAL;
-	}
+	nv_ioctl(object, "disp pior pwr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
+			 args->v0.version, args->v0.state, args->v0.type);
+		if (args->v0.type > 0x0f)
+			return -EINVAL;
+		ctrl = !!args->v0.state;
+		type = args->v0.type;
+	} else
+		return ret;
 
-	return ret;
+	nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
+	nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
+	nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
+	priv->pior.type[outp->or] = type;
+	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ struct nouveau_disp_impl {
 	struct nouveau_oclass base;
 	struct nouveau_oclass **outp;
 	struct nouveau_oclass **conn;
+	const struct nvkm_event_func *vblank;
 };
 
 #define nouveau_disp_create(p,e,c,h,i,x,d)                                     \
@@ -39,4 +40,8 @@ int  _nouveau_disp_fini(struct nouveau_o
 extern struct nouveau_oclass *nvkm_output_oclass;
 extern struct nouveau_oclass *nvkm_connector_oclass;
 
+int  nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *);
+void nouveau_disp_vblank(struct nouveau_disp *, int head);
+int  nouveau_disp_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
@@ -32,77 +33,26 @@
 #include "nv50.h"
 
 int
-nv50_sor_power(struct nv50_disp_priv *priv, int or, u32 data)
+nv50_sor_power(NV50_DISP_MTHD_V1)
 {
-	const u32 stat = data & NV50_DISP_SOR_PWR_STATE;
-	const u32 soff = (or * 0x800);
+	union {
+		struct nv50_disp_sor_pwr_v0 v0;
+	} *args = data;
+	const u32 soff = outp->or * 0x800;
+	u32 stat;
+	int ret;
+
+	nv_ioctl(object, "disp sor pwr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "disp sor pwr vers %d state %d\n",
+			 args->v0.version, args->v0.state);
+		stat = !!args->v0.state;
+	} else
+		return ret;
+
 	nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
 	nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat);
 	nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
 	nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000);
 	return 0;
 }
-
-int
-nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
-{
-	struct nv50_disp_priv *priv = (void *)object->engine;
-	const u8  type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
-	const u8  head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
-	const u8  link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
-	const u8    or = (mthd & NV50_DISP_SOR_MTHD_OR);
-	const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
-	struct nvkm_output *outp = NULL, *temp;
-	u32 data;
-	int ret = -EINVAL;
-
-	if (size < sizeof(u32))
-		return -EINVAL;
-	data = *(u32 *)args;
-
-	list_for_each_entry(temp, &priv->base.outp, head) {
-		if ((temp->info.hasht & 0xff) == type &&
-		    (temp->info.hashm & mask) == mask) {
-			outp = temp;
-			break;
-		}
-	}
-
-	switch (mthd & ~0x3f) {
-	case NV50_DISP_SOR_PWR:
-		ret = priv->sor.power(priv, or, data);
-		break;
-	case NVA3_DISP_SOR_HDA_ELD:
-		ret = priv->sor.hda_eld(priv, or, args, size);
-		break;
-	case NV84_DISP_SOR_HDMI_PWR:
-		ret = priv->sor.hdmi(priv, head, or, data);
-		break;
-	case NV50_DISP_SOR_LVDS_SCRIPT:
-		priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
-		ret = 0;
-		break;
-	case NV94_DISP_SOR_DP_PWR:
-		if (outp) {
-			struct nvkm_output_dp *outpdp = (void *)outp;
-			switch (data) {
-			case NV94_DISP_SOR_DP_PWR_STATE_OFF:
-				nouveau_event_put(outpdp->irq);
-				((struct nvkm_output_dp_impl *)nv_oclass(outp))
-					->lnk_pwr(outpdp, 0);
-				atomic_set(&outpdp->lt.done, 0);
-				break;
-			case NV94_DISP_SOR_DP_PWR_STATE_ON:
-				nvkm_output_dp_train(&outpdp->base, 0, true);
-				break;
-			default:
-				return -EINVAL;
-			}
-		}
-		break;
-	default:
-		BUG_ON(1);
-	}
-
-	return ret;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,98 +23,143 @@
  */
 
 #include <core/object.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/fb.h>
-#include <engine/dmaobj.h>
+#include <subdev/instmem.h>
+
+#include "priv.h"
 
 static int
-nouveau_dmaobj_ctor(struct nouveau_object *parent,
+nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
+		 struct nouveau_gpuobj **pgpuobj)
+{
+	const struct nvkm_dmaeng_impl *impl = (void *)
+		nv_oclass(nv_object(dmaobj)->engine);
+	int ret = 0;
+
+	if (nv_object(dmaobj) == parent) { /* ctor bind */
+		if (nv_mclass(parent->parent) == NV_DEVICE) {
+			/* delayed, or no, binding */
+			return 0;
+		}
+		ret = impl->bind(dmaobj, parent, pgpuobj);
+		if (ret == 0)
+			nouveau_object_ref(NULL, &parent);
+		return ret;
+	}
+
+	return impl->bind(dmaobj, parent, pgpuobj);
+}
+
+int
+nvkm_dmaobj_create_(struct nouveau_object *parent,
 		    struct nouveau_object *engine,
-		    struct nouveau_oclass *oclass, void *data, u32 size,
-		    struct nouveau_object **pobject)
+		    struct nouveau_oclass *oclass, void **pdata, u32 *psize,
+		    int length, void **pobject)
 {
-	struct nouveau_dmaeng *dmaeng = (void *)engine;
+	union {
+		struct nv_dma_v0 v0;
+	} *args = *pdata;
+	struct nouveau_instmem *instmem = nouveau_instmem(parent);
+	struct nouveau_client *client = nouveau_client(parent);
+	struct nouveau_device *device = nv_device(parent);
+	struct nouveau_fb *pfb = nouveau_fb(parent);
 	struct nouveau_dmaobj *dmaobj;
-	struct nouveau_gpuobj *gpuobj;
-	struct nv_dma_class *args = data;
+	void *data = *pdata;
+	u32 size = *psize;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
-
-	ret = nouveau_object_create(parent, engine, oclass, 0, &dmaobj);
-	*pobject = nv_object(dmaobj);
+	ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
+	dmaobj = *pobject;
 	if (ret)
 		return ret;
 
-	switch (args->flags & NV_DMA_TARGET_MASK) {
-	case NV_DMA_TARGET_VM:
+	nv_ioctl(parent, "create dma size %d\n", *psize);
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		nv_ioctl(parent, "create dma vers %d target %d access %d "
+				 "start %016llx limit %016llx\n",
+			 args->v0.version, args->v0.target, args->v0.access,
+			 args->v0.start, args->v0.limit);
+		dmaobj->target = args->v0.target;
+		dmaobj->access = args->v0.access;
+		dmaobj->start  = args->v0.start;
+		dmaobj->limit  = args->v0.limit;
+	} else
+		return ret;
+
+	*pdata = data;
+	*psize = size;
+
+	if (dmaobj->start > dmaobj->limit)
+		return -EINVAL;
+
+	switch (dmaobj->target) {
+	case NV_DMA_V0_TARGET_VM:
 		dmaobj->target = NV_MEM_TARGET_VM;
 		break;
-	case NV_DMA_TARGET_VRAM:
+	case NV_DMA_V0_TARGET_VRAM:
+		if (!client->super) {
+			if (dmaobj->limit >= pfb->ram->size - instmem->reserved)
+				return -EACCES;
+			if (device->card_type >= NV_50)
+				return -EACCES;
+		}
 		dmaobj->target = NV_MEM_TARGET_VRAM;
 		break;
-	case NV_DMA_TARGET_PCI:
+	case NV_DMA_V0_TARGET_PCI:
+		if (!client->super)
+			return -EACCES;
 		dmaobj->target = NV_MEM_TARGET_PCI;
 		break;
-	case NV_DMA_TARGET_PCI_US:
-	case NV_DMA_TARGET_AGP:
+	case NV_DMA_V0_TARGET_PCI_US:
+	case NV_DMA_V0_TARGET_AGP:
+		if (!client->super)
+			return -EACCES;
 		dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	switch (args->flags & NV_DMA_ACCESS_MASK) {
-	case NV_DMA_ACCESS_VM:
+	switch (dmaobj->access) {
+	case NV_DMA_V0_ACCESS_VM:
 		dmaobj->access = NV_MEM_ACCESS_VM;
 		break;
-	case NV_DMA_ACCESS_RD:
+	case NV_DMA_V0_ACCESS_RD:
 		dmaobj->access = NV_MEM_ACCESS_RO;
 		break;
-	case NV_DMA_ACCESS_WR:
+	case NV_DMA_V0_ACCESS_WR:
 		dmaobj->access = NV_MEM_ACCESS_WO;
 		break;
-	case NV_DMA_ACCESS_RDWR:
+	case NV_DMA_V0_ACCESS_RDWR:
 		dmaobj->access = NV_MEM_ACCESS_RW;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	dmaobj->start = args->start;
-	dmaobj->limit = args->limit;
-	dmaobj->conf0 = args->conf0;
-
-	switch (nv_mclass(parent)) {
-	case NV_DEVICE_CLASS:
-		/* delayed, or no, binding */
-		break;
-	default:
-		ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
-		if (ret == 0) {
-			nouveau_object_ref(NULL, pobject);
-			*pobject = nv_object(gpuobj);
-		}
-		break;
-	}
-
 	return ret;
 }
 
-static struct nouveau_ofuncs
-nouveau_dmaobj_ofuncs = {
-	.ctor = nouveau_dmaobj_ctor,
-	.dtor = nouveau_object_destroy,
-	.init = nouveau_object_init,
-	.fini = nouveau_object_fini,
-};
+int
+_nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+		  struct nouveau_oclass *oclass, void *data, u32 size,
+		  struct nouveau_object **pobject)
+{
+	const struct nvkm_dmaeng_impl *impl = (void *)oclass;
+	struct nouveau_dmaeng *dmaeng;
+	int ret;
 
-struct nouveau_oclass
-nouveau_dmaobj_sclass[] = {
-	{ NV_DMA_FROM_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-	{ NV_DMA_TO_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-	{ NV_DMA_IN_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
-	{}
-};
+	ret = nouveau_engine_create(parent, engine, oclass, true, "DMAOBJ",
+				    "dmaobj", &dmaeng);
+	*pobject = nv_object(dmaeng);
+	if (ret)
+		return ret;
+
+	nv_engine(dmaeng)->sclass = impl->sclass;
+	dmaeng->bind = nvkm_dmaobj_bind;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,121 +23,143 @@
  */
 
 #include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/class.h>
 
 #include <subdev/fb.h>
 #include <subdev/vm/nv04.h>
 
-#include <engine/dmaobj.h>
+#include "priv.h"
 
-struct nv04_dmaeng_priv {
-	struct nouveau_dmaeng base;
+struct nv04_dmaobj_priv {
+	struct nouveau_dmaobj base;
+	bool clone;
+	u32 flags0;
+	u32 flags2;
 };
 
 static int
-nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_object *parent,
-		 struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_gpuobj **pgpuobj)
 {
-	struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng);
+	struct nv04_dmaobj_priv *priv = (void *)dmaobj;
 	struct nouveau_gpuobj *gpuobj;
-	u32 flags0 = nv_mclass(dmaobj);
-	u32 flags2 = 0x00000000;
-	u64 offset = dmaobj->start & 0xfffff000;
-	u64 adjust = dmaobj->start & 0x00000fff;
-	u32 length = dmaobj->limit - dmaobj->start;
+	u64 offset = priv->base.start & 0xfffff000;
+	u64 adjust = priv->base.start & 0x00000fff;
+	u32 length = priv->base.limit - priv->base.start;
 	int ret;
 
 	if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
 		switch (nv_mclass(parent->parent)) {
-		case NV03_CHANNEL_DMA_CLASS:
-		case NV10_CHANNEL_DMA_CLASS:
-		case NV17_CHANNEL_DMA_CLASS:
-		case NV40_CHANNEL_DMA_CLASS:
+		case NV03_CHANNEL_DMA:
+		case NV10_CHANNEL_DMA:
+		case NV17_CHANNEL_DMA:
+		case NV40_CHANNEL_DMA:
 			break;
 		default:
 			return -EINVAL;
 		}
 	}
 
-	if (dmaobj->target == NV_MEM_TARGET_VM) {
-		if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) {
-			struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
-			if (!dmaobj->start)
-				return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
-			offset  = nv_ro32(pgt, 8 + (offset >> 10));
-			offset &= 0xfffff000;
-		}
+	if (priv->clone) {
+		struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaobj);
+		struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
+		if (!dmaobj->start)
+			return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
+		offset  = nv_ro32(pgt, 8 + (offset >> 10));
+		offset &= 0xfffff000;
+	}
 
-		dmaobj->target = NV_MEM_TARGET_PCI;
-		dmaobj->access = NV_MEM_ACCESS_RW;
+	ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
+	*pgpuobj = gpuobj;
+	if (ret == 0) {
+		nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
+		nv_wo32(*pgpuobj, 0x04, length);
+		nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset);
+		nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset);
 	}
 
-	switch (dmaobj->target) {
+	return ret;
+}
+
+static int
+nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+		 struct nouveau_oclass *oclass, void *data, u32 size,
+		 struct nouveau_object **pobject)
+{
+	struct nouveau_dmaeng *dmaeng = (void *)engine;
+	struct nv04_vmmgr_priv *vmm = nv04_vmmgr(engine);
+	struct nv04_dmaobj_priv *priv;
+	int ret;
+
+	ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+	*pobject = nv_object(priv);
+	if (ret || (ret = -ENOSYS, size))
+		return ret;
+
+	if (priv->base.target == NV_MEM_TARGET_VM) {
+		if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass)
+			priv->clone = true;
+		priv->base.target = NV_MEM_TARGET_PCI;
+		priv->base.access = NV_MEM_ACCESS_RW;
+	}
+
+	priv->flags0 = nv_mclass(priv);
+	switch (priv->base.target) {
 	case NV_MEM_TARGET_VRAM:
-		flags0 |= 0x00003000;
+		priv->flags0 |= 0x00003000;
 		break;
 	case NV_MEM_TARGET_PCI:
-		flags0 |= 0x00023000;
+		priv->flags0 |= 0x00023000;
 		break;
 	case NV_MEM_TARGET_PCI_NOSNOOP:
-		flags0 |= 0x00033000;
+		priv->flags0 |= 0x00033000;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	switch (dmaobj->access) {
+	switch (priv->base.access) {
 	case NV_MEM_ACCESS_RO:
-		flags0 |= 0x00004000;
+		priv->flags0 |= 0x00004000;
 		break;
 	case NV_MEM_ACCESS_WO:
-		flags0 |= 0x00008000;
+		priv->flags0 |= 0x00008000;
 	case NV_MEM_ACCESS_RW:
-		flags2 |= 0x00000002;
+		priv->flags2 |= 0x00000002;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
-	*pgpuobj = gpuobj;
-	if (ret == 0) {
-		nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
-		nv_wo32(*pgpuobj, 0x04, length);
-		nv_wo32(*pgpuobj, 0x08, flags2 | offset);
-		nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
-	}
-
-	return ret;
+	return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
-static int
-nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		 struct nouveau_oclass *oclass, void *data, u32 size,
-		 struct nouveau_object **pobject)
-{
-	struct nv04_dmaeng_priv *priv;
-	int ret;
-
-	ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
+static struct nouveau_ofuncs
+nv04_dmaobj_ofuncs = {
+	.ctor =  nv04_dmaobj_ctor,
+	.dtor = _nvkm_dmaobj_dtor,
+	.init = _nvkm_dmaobj_init,
+	.fini = _nvkm_dmaobj_fini,
+};
 
-	nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
-	priv->base.bind = nv04_dmaobj_bind;
-	return 0;
-}
+static struct nouveau_oclass
+nv04_dmaeng_sclass[] = {
+	{ NV_DMA_FROM_MEMORY, &nv04_dmaobj_ofuncs },
+	{ NV_DMA_TO_MEMORY, &nv04_dmaobj_ofuncs },
+	{ NV_DMA_IN_MEMORY, &nv04_dmaobj_ofuncs },
+	{}
+};
 
-struct nouveau_oclass
-nv04_dmaeng_oclass = {
-	.handle = NV_ENGINE(DMAOBJ, 0x04),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv04_dmaeng_ctor,
-		.dtor = _nouveau_dmaeng_dtor,
-		.init = _nouveau_dmaeng_init,
-		.fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+	.base.handle = NV_ENGINE(DMAOBJ, 0x04),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nvkm_dmaeng_ctor,
+		.dtor = _nvkm_dmaeng_dtor,
+		.init = _nvkm_dmaeng_init,
+		.fini = _nvkm_dmaeng_fini,
 	},
-};
+	.sclass = nv04_dmaeng_sclass,
+	.bind = nv04_dmaobj_bind,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,140 +22,176 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/client.h>
 #include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/fb.h>
-#include <engine/dmaobj.h>
 
-struct nv50_dmaeng_priv {
-	struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nv50_dmaobj_priv {
+	struct nouveau_dmaobj base;
+	u32 flags0;
+	u32 flags5;
 };
 
 static int
-nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_object *parent,
-		 struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_gpuobj **pgpuobj)
 {
-	u32 flags0 = nv_mclass(dmaobj);
-	u32 flags5 = 0x00000000;
+	struct nv50_dmaobj_priv *priv = (void *)dmaobj;
 	int ret;
 
 	if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
 		switch (nv_mclass(parent->parent)) {
-		case NV50_CHANNEL_DMA_CLASS:
-		case NV84_CHANNEL_DMA_CLASS:
-		case NV50_CHANNEL_IND_CLASS:
-		case NV84_CHANNEL_IND_CLASS:
-		case NV50_DISP_MAST_CLASS:
-		case NV84_DISP_MAST_CLASS:
-		case NV94_DISP_MAST_CLASS:
-		case NVA0_DISP_MAST_CLASS:
-		case NVA3_DISP_MAST_CLASS:
-		case NV50_DISP_SYNC_CLASS:
-		case NV84_DISP_SYNC_CLASS:
-		case NV94_DISP_SYNC_CLASS:
-		case NVA0_DISP_SYNC_CLASS:
-		case NVA3_DISP_SYNC_CLASS:
-		case NV50_DISP_OVLY_CLASS:
-		case NV84_DISP_OVLY_CLASS:
-		case NV94_DISP_OVLY_CLASS:
-		case NVA0_DISP_OVLY_CLASS:
-		case NVA3_DISP_OVLY_CLASS:
+		case NV40_CHANNEL_DMA:
+		case NV50_CHANNEL_GPFIFO:
+		case G82_CHANNEL_GPFIFO:
+		case NV50_DISP_CORE_CHANNEL_DMA:
+		case G82_DISP_CORE_CHANNEL_DMA:
+		case GT206_DISP_CORE_CHANNEL_DMA:
+		case GT200_DISP_CORE_CHANNEL_DMA:
+		case GT214_DISP_CORE_CHANNEL_DMA:
+		case NV50_DISP_BASE_CHANNEL_DMA:
+		case G82_DISP_BASE_CHANNEL_DMA:
+		case GT200_DISP_BASE_CHANNEL_DMA:
+		case GT214_DISP_BASE_CHANNEL_DMA:
+		case NV50_DISP_OVERLAY_CHANNEL_DMA:
+		case G82_DISP_OVERLAY_CHANNEL_DMA:
+		case GT200_DISP_OVERLAY_CHANNEL_DMA:
+		case GT214_DISP_OVERLAY_CHANNEL_DMA:
 			break;
 		default:
 			return -EINVAL;
 		}
 	}
 
-	if (!(dmaobj->conf0 & NV50_DMA_CONF0_ENABLE)) {
-		if (dmaobj->target == NV_MEM_TARGET_VM) {
-			dmaobj->conf0  = NV50_DMA_CONF0_PRIV_VM;
-			dmaobj->conf0 |= NV50_DMA_CONF0_PART_VM;
-			dmaobj->conf0 |= NV50_DMA_CONF0_COMP_VM;
-			dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_VM;
+	ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+	if (ret == 0) {
+		nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+		nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+		nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+		nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+					upper_32_bits(priv->base.start));
+		nv_wo32(*pgpuobj, 0x10, 0x00000000);
+		nv_wo32(*pgpuobj, 0x14, priv->flags5);
+	}
+
+	return ret;
+}
+
+static int
+nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+		 struct nouveau_oclass *oclass, void *data, u32 size,
+		 struct nouveau_object **pobject)
+{
+	struct nouveau_dmaeng *dmaeng = (void *)engine;
+	union {
+		struct nv50_dma_v0 v0;
+	} *args;
+	struct nv50_dmaobj_priv *priv;
+	u32 user, part, comp, kind;
+	int ret;
+
+	ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+	args = data;
+
+	nv_ioctl(parent, "create nv50 dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create nv50 dma vers %d priv %d part %d "
+				 "comp %d kind %02x\n", args->v0.version,
+			 args->v0.priv, args->v0.part, args->v0.comp,
+			 args->v0.kind);
+		user = args->v0.priv;
+		part = args->v0.part;
+		comp = args->v0.comp;
+		kind = args->v0.kind;
+	} else
+	if (size == 0) {
+		if (priv->base.target != NV_MEM_TARGET_VM) {
+			user = NV50_DMA_V0_PRIV_US;
+			part = NV50_DMA_V0_PART_256;
+			comp = NV50_DMA_V0_COMP_NONE;
+			kind = NV50_DMA_V0_KIND_PITCH;
 		} else {
-			dmaobj->conf0  = NV50_DMA_CONF0_PRIV_US;
-			dmaobj->conf0 |= NV50_DMA_CONF0_PART_256;
-			dmaobj->conf0 |= NV50_DMA_CONF0_COMP_NONE;
-			dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
+			user = NV50_DMA_V0_PRIV_VM;
+			part = NV50_DMA_V0_PART_VM;
+			comp = NV50_DMA_V0_COMP_VM;
+			kind = NV50_DMA_V0_KIND_VM;
 		}
-	}
+	} else
+		return ret;
 
-	flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_COMP) << 22;
-	flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_TYPE) << 22;
-	flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_PRIV);
-	flags5 |= (dmaobj->conf0 & NV50_DMA_CONF0_PART);
+	if (user > 2 || part > 2 || comp > 3 || kind > 0x7f)
+		return -EINVAL;
+	priv->flags0 = (comp << 29) | (kind << 22) | (user << 20);
+	priv->flags5 = (part << 16);
 
-	switch (dmaobj->target) {
+	switch (priv->base.target) {
 	case NV_MEM_TARGET_VM:
-		flags0 |= 0x00000000;
+		priv->flags0 |= 0x00000000;
 		break;
 	case NV_MEM_TARGET_VRAM:
-		flags0 |= 0x00010000;
+		priv->flags0 |= 0x00010000;
 		break;
 	case NV_MEM_TARGET_PCI:
-		flags0 |= 0x00020000;
+		priv->flags0 |= 0x00020000;
 		break;
 	case NV_MEM_TARGET_PCI_NOSNOOP:
-		flags0 |= 0x00030000;
+		priv->flags0 |= 0x00030000;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	switch (dmaobj->access) {
+	switch (priv->base.access) {
 	case NV_MEM_ACCESS_VM:
 		break;
 	case NV_MEM_ACCESS_RO:
-		flags0 |= 0x00040000;
+		priv->flags0 |= 0x00040000;
 		break;
 	case NV_MEM_ACCESS_WO:
 	case NV_MEM_ACCESS_RW:
-		flags0 |= 0x00080000;
+		priv->flags0 |= 0x00080000;
 		break;
+	default:
+		return -EINVAL;
 	}
 
-	ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
-	if (ret == 0) {
-		nv_wo32(*pgpuobj, 0x00, flags0);
-		nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
-		nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
-		nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
-					upper_32_bits(dmaobj->start));
-		nv_wo32(*pgpuobj, 0x10, 0x00000000);
-		nv_wo32(*pgpuobj, 0x14, flags5);
-	}
-
-	return ret;
+	return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
-static int
-nv50_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		 struct nouveau_oclass *oclass, void *data, u32 size,
-		 struct nouveau_object **pobject)
-{
-	struct nv50_dmaeng_priv *priv;
-	int ret;
-
-	ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
+static struct nouveau_ofuncs
+nv50_dmaobj_ofuncs = {
+	.ctor =  nv50_dmaobj_ctor,
+	.dtor = _nvkm_dmaobj_dtor,
+	.init = _nvkm_dmaobj_init,
+	.fini = _nvkm_dmaobj_fini,
+};
 
-	nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
-	priv->base.bind = nv50_dmaobj_bind;
-	return 0;
-}
+static struct nouveau_oclass
+nv50_dmaeng_sclass[] = {
+	{ NV_DMA_FROM_MEMORY, &nv50_dmaobj_ofuncs },
+	{ NV_DMA_TO_MEMORY, &nv50_dmaobj_ofuncs },
+	{ NV_DMA_IN_MEMORY, &nv50_dmaobj_ofuncs },
+	{}
+};
 
-struct nouveau_oclass
-nv50_dmaeng_oclass = {
-	.handle = NV_ENGINE(DMAOBJ, 0x50),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv50_dmaeng_ctor,
-		.dtor = _nouveau_dmaeng_dtor,
-		.init = _nouveau_dmaeng_init,
-		.fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+	.base.handle = NV_ENGINE(DMAOBJ, 0x50),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nvkm_dmaeng_ctor,
+		.dtor = _nvkm_dmaeng_dtor,
+		.init = _nvkm_dmaeng_init,
+		.fini = _nvkm_dmaeng_fini,
 	},
-};
+	.sclass = nv50_dmaeng_sclass,
+	.bind = nv50_dmaobj_bind,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,32 +22,35 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/client.h>
 #include <core/device.h>
 #include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/fb.h>
-#include <engine/dmaobj.h>
 
-struct nvc0_dmaeng_priv {
-	struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nvc0_dmaobj_priv {
+	struct nouveau_dmaobj base;
+	u32 flags0;
+	u32 flags5;
 };
 
 static int
-nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvc0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_object *parent,
-		 struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_gpuobj **pgpuobj)
 {
-	u32 flags0 = nv_mclass(dmaobj);
-	u32 flags5 = 0x00000000;
+	struct nvc0_dmaobj_priv *priv = (void *)dmaobj;
 	int ret;
 
 	if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
 		switch (nv_mclass(parent->parent)) {
-		case NVA3_DISP_MAST_CLASS:
-		case NVA3_DISP_SYNC_CLASS:
-		case NVA3_DISP_OVLY_CLASS:
+		case GT214_DISP_CORE_CHANNEL_DMA:
+		case GT214_DISP_BASE_CHANNEL_DMA:
+		case GT214_DISP_OVERLAY_CHANNEL_DMA:
 			break;
 		default:
 			return -EINVAL;
@@ -55,89 +58,122 @@ nvc0_dmaobj_bind(struct nouveau_dmaeng *
 	} else
 		return 0;
 
-	if (!(dmaobj->conf0 & NVC0_DMA_CONF0_ENABLE)) {
-		if (dmaobj->target == NV_MEM_TARGET_VM) {
-			dmaobj->conf0  = NVC0_DMA_CONF0_PRIV_VM;
-			dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
+	ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+	if (ret == 0) {
+		nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+		nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+		nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+		nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+					upper_32_bits(priv->base.start));
+		nv_wo32(*pgpuobj, 0x10, 0x00000000);
+		nv_wo32(*pgpuobj, 0x14, priv->flags5);
+	}
+
+	return ret;
+}
+
+static int
+nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+		 struct nouveau_oclass *oclass, void *data, u32 size,
+		 struct nouveau_object **pobject)
+{
+	struct nouveau_dmaeng *dmaeng = (void *)engine;
+	union {
+		struct gf100_dma_v0 v0;
+	} *args;
+	struct nvc0_dmaobj_priv *priv;
+	u32 kind, user, unkn;
+	int ret;
+
+	ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+	args = data;
+
+	nv_ioctl(parent, "create gf100 dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create gf100 dma vers %d priv %d kind %02x\n",
+			 args->v0.version, args->v0.priv, args->v0.kind);
+		kind = args->v0.kind;
+		user = args->v0.priv;
+		unkn = 0;
+	} else
+	if (size == 0) {
+		if (priv->base.target != NV_MEM_TARGET_VM) {
+			kind = GF100_DMA_V0_KIND_PITCH;
+			user = GF100_DMA_V0_PRIV_US;
+			unkn = 2;
 		} else {
-			dmaobj->conf0  = NVC0_DMA_CONF0_PRIV_US;
-			dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
-			dmaobj->conf0 |= 0x00020000;
+			kind = GF100_DMA_V0_KIND_VM;
+			user = GF100_DMA_V0_PRIV_VM;
+			unkn = 0;
 		}
-	}
+	} else
+		return ret;
 
-	flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
-	flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_PRIV);
-	flags5 |= (dmaobj->conf0 & NVC0_DMA_CONF0_UNKN);
+	if (user > 2)
+		return -EINVAL;
+	priv->flags0 |= (kind << 22) | (user << 20);
+	priv->flags5 |= (unkn << 16);
 
-	switch (dmaobj->target) {
+	switch (priv->base.target) {
 	case NV_MEM_TARGET_VM:
-		flags0 |= 0x00000000;
+		priv->flags0 |= 0x00000000;
 		break;
 	case NV_MEM_TARGET_VRAM:
-		flags0 |= 0x00010000;
+		priv->flags0 |= 0x00010000;
 		break;
 	case NV_MEM_TARGET_PCI:
-		flags0 |= 0x00020000;
+		priv->flags0 |= 0x00020000;
 		break;
 	case NV_MEM_TARGET_PCI_NOSNOOP:
-		flags0 |= 0x00030000;
+		priv->flags0 |= 0x00030000;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	switch (dmaobj->access) {
+	switch (priv->base.access) {
 	case NV_MEM_ACCESS_VM:
 		break;
 	case NV_MEM_ACCESS_RO:
-		flags0 |= 0x00040000;
+		priv->flags0 |= 0x00040000;
 		break;
 	case NV_MEM_ACCESS_WO:
 	case NV_MEM_ACCESS_RW:
-		flags0 |= 0x00080000;
+		priv->flags0 |= 0x00080000;
 		break;
 	}
 
-	ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
-	if (ret == 0) {
-		nv_wo32(*pgpuobj, 0x00, flags0);
-		nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
-		nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
-		nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
-					upper_32_bits(dmaobj->start));
-		nv_wo32(*pgpuobj, 0x10, 0x00000000);
-		nv_wo32(*pgpuobj, 0x14, flags5);
-	}
-
-	return ret;
+	return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
-static int
-nvc0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		 struct nouveau_oclass *oclass, void *data, u32 size,
-		 struct nouveau_object **pobject)
-{
-	struct nvc0_dmaeng_priv *priv;
-	int ret;
-
-	ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
+static struct nouveau_ofuncs
+nvc0_dmaobj_ofuncs = {
+	.ctor =  nvc0_dmaobj_ctor,
+	.dtor = _nvkm_dmaobj_dtor,
+	.init = _nvkm_dmaobj_init,
+	.fini = _nvkm_dmaobj_fini,
+};
 
-	nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
-	priv->base.bind = nvc0_dmaobj_bind;
-	return 0;
-}
+static struct nouveau_oclass
+nvc0_dmaeng_sclass[] = {
+	{ NV_DMA_FROM_MEMORY, &nvc0_dmaobj_ofuncs },
+	{ NV_DMA_TO_MEMORY, &nvc0_dmaobj_ofuncs },
+	{ NV_DMA_IN_MEMORY, &nvc0_dmaobj_ofuncs },
+	{}
+};
 
-struct nouveau_oclass
-nvc0_dmaeng_oclass = {
-	.handle = NV_ENGINE(DMAOBJ, 0xc0),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nvc0_dmaeng_ctor,
-		.dtor = _nouveau_dmaeng_dtor,
-		.init = _nouveau_dmaeng_init,
-		.fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+	.base.handle = NV_ENGINE(DMAOBJ, 0xc0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nvkm_dmaeng_ctor,
+		.dtor = _nvkm_dmaeng_dtor,
+		.init = _nvkm_dmaeng_init,
+		.fini = _nvkm_dmaeng_fini,
 	},
-};
+	.sclass = nvc0_dmaeng_sclass,
+	.bind = nvc0_dmaobj_bind,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,40 +22,40 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/client.h>
 #include <core/device.h>
 #include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/fb.h>
-#include <engine/dmaobj.h>
 
-struct nvd0_dmaeng_priv {
-	struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nvd0_dmaobj_priv {
+	struct nouveau_dmaobj base;
+	u32 flags0;
 };
 
 static int
-nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvd0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_object *parent,
-		 struct nouveau_dmaobj *dmaobj,
 		 struct nouveau_gpuobj **pgpuobj)
 {
-	u32 flags0 = 0x00000000;
+	struct nvd0_dmaobj_priv *priv = (void *)dmaobj;
 	int ret;
 
 	if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
 		switch (nv_mclass(parent->parent)) {
-		case NVD0_DISP_MAST_CLASS:
-		case NVD0_DISP_SYNC_CLASS:
-		case NVD0_DISP_OVLY_CLASS:
-		case NVE0_DISP_MAST_CLASS:
-		case NVE0_DISP_SYNC_CLASS:
-		case NVE0_DISP_OVLY_CLASS:
-		case NVF0_DISP_MAST_CLASS:
-		case NVF0_DISP_SYNC_CLASS:
-		case NVF0_DISP_OVLY_CLASS:
-		case GM107_DISP_MAST_CLASS:
-		case GM107_DISP_SYNC_CLASS:
-		case GM107_DISP_OVLY_CLASS:
+		case GF110_DISP_CORE_CHANNEL_DMA:
+		case GK104_DISP_CORE_CHANNEL_DMA:
+		case GK110_DISP_CORE_CHANNEL_DMA:
+		case GM107_DISP_CORE_CHANNEL_DMA:
+		case GF110_DISP_BASE_CHANNEL_DMA:
+		case GK104_DISP_BASE_CHANNEL_DMA:
+		case GK110_DISP_BASE_CHANNEL_DMA:
+		case GF110_DISP_OVERLAY_CONTROL_DMA:
+		case GK104_DISP_OVERLAY_CONTROL_DMA:
 			break;
 		default:
 			return -EINVAL;
@@ -63,33 +63,11 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *
 	} else
 		return 0;
 
-	if (!(dmaobj->conf0 & NVD0_DMA_CONF0_ENABLE)) {
-		if (dmaobj->target == NV_MEM_TARGET_VM) {
-			dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
-			dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
-		} else {
-			dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
-			dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
-		}
-	}
-
-	flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
-	flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
-
-	switch (dmaobj->target) {
-	case NV_MEM_TARGET_VRAM:
-		flags0 |= 0x00000009;
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
-
 	ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
 	if (ret == 0) {
-		nv_wo32(*pgpuobj, 0x00, flags0);
-		nv_wo32(*pgpuobj, 0x04, dmaobj->start >> 8);
-		nv_wo32(*pgpuobj, 0x08, dmaobj->limit >> 8);
+		nv_wo32(*pgpuobj, 0x00, priv->flags0);
+		nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8);
+		nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8);
 		nv_wo32(*pgpuobj, 0x0c, 0x00000000);
 		nv_wo32(*pgpuobj, 0x10, 0x00000000);
 		nv_wo32(*pgpuobj, 0x14, 0x00000000);
@@ -99,30 +77,91 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *
 }
 
 static int
-nvd0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+nvd0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		 struct nouveau_oclass *oclass, void *data, u32 size,
 		 struct nouveau_object **pobject)
 {
-	struct nvd0_dmaeng_priv *priv;
+	struct nouveau_dmaeng *dmaeng = (void *)engine;
+	union {
+		struct gf110_dma_v0 v0;
+	} *args;
+	struct nvd0_dmaobj_priv *priv;
+	u32 kind, page;
 	int ret;
 
-	ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
+	ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
+	args = data;
 
-	nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
-	priv->base.bind = nvd0_dmaobj_bind;
-	return 0;
+	nv_ioctl(parent, "create gf110 dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create gf100 dma vers %d page %d kind %02x\n",
+			 args->v0.version, args->v0.page, args->v0.kind);
+		kind = args->v0.kind;
+		page = args->v0.page;
+	} else
+	if (size == 0) {
+		if (priv->base.target != NV_MEM_TARGET_VM) {
+			kind = GF110_DMA_V0_KIND_PITCH;
+			page = GF110_DMA_V0_PAGE_SP;
+		} else {
+			kind = GF110_DMA_V0_KIND_VM;
+			page = GF110_DMA_V0_PAGE_LP;
+		}
+	} else
+		return ret;
+
+	if (page > 1)
+		return -EINVAL;
+	priv->flags0 = (kind << 20) | (page << 6);
+
+	switch (priv->base.target) {
+	case NV_MEM_TARGET_VRAM:
+		priv->flags0 |= 0x00000009;
+		break;
+	case NV_MEM_TARGET_VM:
+	case NV_MEM_TARGET_PCI:
+	case NV_MEM_TARGET_PCI_NOSNOOP:
+		/* XXX: don't currently know how to construct a real one
+		 *      of these.  we only use them to represent pushbufs
+		 *      on these chipsets, and the classes that use them
+		 *      deal with the target themselves.
+		 */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
 }
 
-struct nouveau_oclass
-nvd0_dmaeng_oclass = {
-	.handle = NV_ENGINE(DMAOBJ, 0xd0),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nvd0_dmaeng_ctor,
-		.dtor = _nouveau_dmaeng_dtor,
-		.init = _nouveau_dmaeng_init,
-		.fini = _nouveau_dmaeng_fini,
-	},
+static struct nouveau_ofuncs
+nvd0_dmaobj_ofuncs = {
+	.ctor =  nvd0_dmaobj_ctor,
+	.dtor = _nvkm_dmaobj_dtor,
+	.init = _nvkm_dmaobj_init,
+	.fini = _nvkm_dmaobj_fini,
 };
+
+static struct nouveau_oclass
+nvd0_dmaeng_sclass[] = {
+	{ NV_DMA_FROM_MEMORY, &nvd0_dmaobj_ofuncs },
+	{ NV_DMA_TO_MEMORY, &nvd0_dmaobj_ofuncs },
+	{ NV_DMA_IN_MEMORY, &nvd0_dmaobj_ofuncs },
+	{}
+};
+
+struct nouveau_oclass *
+nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+	.base.handle = NV_ENGINE(DMAOBJ, 0xd0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nvkm_dmaeng_ctor,
+		.dtor = _nvkm_dmaeng_dtor,
+		.init = _nvkm_dmaeng_init,
+		.fini = _nvkm_dmaeng_fini,
+	},
+	.sclass = nvd0_dmaeng_sclass,
+	.bind = nvd0_dmaobj_bind,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+#ifndef __NVKM_DMAOBJ_PRIV_H__
+#define __NVKM_DMAOBJ_PRIV_H__
+
+#include <engine/dmaobj.h>
+
+#define nvkm_dmaobj_create(p,e,c,pa,sa,d)                                      \
+	nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d)
+
+int nvkm_dmaobj_create_(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, void **, u32 *,
+			int, void **);
+#define _nvkm_dmaobj_dtor nouveau_object_destroy
+#define _nvkm_dmaobj_init nouveau_object_init
+#define _nvkm_dmaobj_fini nouveau_object_fini
+
+int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
+		      struct nouveau_oclass *, void *, u32,
+		      struct nouveau_object **);
+#define _nvkm_dmaeng_dtor _nouveau_engine_dtor
+#define _nvkm_dmaeng_init _nouveau_engine_init
+#define _nvkm_dmaeng_fini _nouveau_engine_fini
+
+struct nvkm_dmaeng_impl {
+	struct nouveau_oclass base;
+	struct nouveau_oclass *sclass;
+	int (*bind)(struct nouveau_dmaobj *, struct nouveau_object *,
+		    struct nouveau_gpuobj **);
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,11 +26,30 @@
 #include <core/object.h>
 #include <core/handle.h>
 #include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/event.h>
 
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+static int
+nouveau_fifo_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	if (size == 0) {
+		notify->size  = 0;
+		notify->types = 1;
+		notify->index = 0;
+		return 0;
+	}
+	return -ENOSYS;
+}
+
+static const struct nvkm_event_func
+nouveau_fifo_event_func = {
+	.ctor = nouveau_fifo_event_ctor,
+};
+
 int
 nouveau_fifo_channel_create_(struct nouveau_object *parent,
 			     struct nouveau_object *engine,
@@ -59,14 +78,14 @@ nouveau_fifo_channel_create_(struct nouv
 
 	dmaeng = (void *)chan->pushdma->base.engine;
 	switch (chan->pushdma->base.oclass->handle) {
-	case NV_DMA_FROM_MEMORY_CLASS:
-	case NV_DMA_IN_MEMORY_CLASS:
+	case NV_DMA_FROM_MEMORY:
+	case NV_DMA_IN_MEMORY:
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu);
+	ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu);
 	if (ret)
 		return ret;
 
@@ -85,15 +104,10 @@ nouveau_fifo_channel_create_(struct nouv
 		return -ENOSPC;
 	}
 
-	/* map fifo control registers */
-	chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
-			     (chan->chid * size), size);
-	if (!chan->user)
-		return -EFAULT;
-
-	nouveau_event_trigger(priv->cevent, 1, 0);
-
+	chan->addr = nv_device_resource_start(device, bar) +
+		     addr + size * chan->chid;
 	chan->size = size;
+	nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
 	return 0;
 }
 
@@ -103,7 +117,8 @@ nouveau_fifo_channel_destroy(struct nouv
 	struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
 	unsigned long flags;
 
-	iounmap(chan->user);
+	if (chan->user)
+		iounmap(chan->user);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->channel[chan->chid] = NULL;
@@ -121,10 +136,24 @@ _nouveau_fifo_channel_dtor(struct nouvea
 	nouveau_fifo_channel_destroy(chan);
 }
 
+int
+_nouveau_fifo_channel_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+	struct nouveau_fifo_chan *chan = (void *)object;
+	*addr = chan->addr;
+	*size = chan->size;
+	return 0;
+}
+
 u32
 _nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr)
 {
 	struct nouveau_fifo_chan *chan = (void *)object;
+	if (unlikely(!chan->user)) {
+		chan->user = ioremap(chan->addr, chan->size);
+		if (WARN_ON_ONCE(chan->user == NULL))
+			return 0;
+	}
 	return ioread32_native(chan->user + addr);
 }
 
@@ -132,9 +161,57 @@ void
 _nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data)
 {
 	struct nouveau_fifo_chan *chan = (void *)object;
+	if (unlikely(!chan->user)) {
+		chan->user = ioremap(chan->addr, chan->size);
+		if (WARN_ON_ONCE(chan->user == NULL))
+			return;
+	}
 	iowrite32_native(data, chan->user + addr);
 }
 
+int
+nouveau_fifo_uevent_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	union {
+		struct nvif_notify_uevent_req none;
+	} *req = data;
+	int ret;
+
+	if (nvif_unvers(req->none)) {
+		notify->size  = sizeof(struct nvif_notify_uevent_rep);
+		notify->types = 1;
+		notify->index = 0;
+	}
+
+	return ret;
+}
+
+void
+nouveau_fifo_uevent(struct nouveau_fifo *fifo)
+{
+	struct nvif_notify_uevent_rep rep = {
+	};
+	nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
+}
+
+int
+_nouveau_fifo_channel_ntfy(struct nouveau_object *object, u32 type,
+			   struct nvkm_event **event)
+{
+	struct nouveau_fifo *fifo = (void *)object->engine;
+	switch (type) {
+	case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
+		if (nv_mclass(object) >= G82_CHANNEL_DMA) {
+			*event = &fifo->uevent;
+			return 0;
+		}
+		break;
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
 static int
 nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object)
 {
@@ -168,8 +245,8 @@ void
 nouveau_fifo_destroy(struct nouveau_fifo *priv)
 {
 	kfree(priv->channel);
-	nouveau_event_destroy(&priv->uevent);
-	nouveau_event_destroy(&priv->cevent);
+	nvkm_event_fini(&priv->uevent);
+	nvkm_event_fini(&priv->cevent);
 	nouveau_engine_destroy(&priv->base);
 }
 
@@ -194,11 +271,7 @@ nouveau_fifo_create_(struct nouveau_obje
 	if (!priv->channel)
 		return -ENOMEM;
 
-	ret = nouveau_event_create(1, 1, &priv->cevent);
-	if (ret)
-		return ret;
-
-	ret = nouveau_event_create(1, 1, &priv->uevent);
+	ret = nvkm_event_init(&nouveau_fifo_event_func, 1, 1, &priv->cevent);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/engctx.h>
 #include <core/namedb.h>
 #include <core/handle.h>
@@ -117,16 +118,23 @@ nv04_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nv04_fifo_priv *priv = (void *)engine;
 	struct nv04_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-					  0x10000, args->pushbuf,
+					  0x10000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR), &chan);
@@ -134,13 +142,15 @@ nv04_fifo_chan_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->object_attach = nv04_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv04_fifo_object_detach;
 	nv_parent(chan)->context_attach = nv04_fifo_context_attach;
 	chan->ramfc = chan->base.chid * 32;
 
-	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
-	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x10,
 			     NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -242,13 +252,15 @@ nv04_fifo_ofuncs = {
 	.dtor = nv04_fifo_chan_dtor,
 	.init = nv04_fifo_chan_init,
 	.fini = nv04_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv04_fifo_sclass[] = {
-	{ NV03_CHANNEL_DMA_CLASS, &nv04_fifo_ofuncs },
+	{ NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
 	{}
 };
 
@@ -539,7 +551,7 @@ nv04_fifo_intr(struct nouveau_subdev *su
 			}
 
 			if (status & 0x40000000) {
-				nouveau_event_trigger(priv->base.uevent, 1, 0);
+				nouveau_fifo_uevent(&priv->base);
 				nv_wr32(priv, 0x002100, 0x40000000);
 				status &= ~0x40000000;
 			}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/engctx.h>
 #include <core/ramht.h>
 
@@ -59,16 +60,23 @@ nv10_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nv04_fifo_priv *priv = (void *)engine;
 	struct nv04_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-					  0x10000, args->pushbuf,
+					  0x10000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR), &chan);
@@ -76,13 +84,15 @@ nv10_fifo_chan_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->object_attach = nv04_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv04_fifo_object_detach;
 	nv_parent(chan)->context_attach = nv04_fifo_context_attach;
 	chan->ramfc = chan->base.chid * 32;
 
-	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
-	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x14,
 			     NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -100,13 +110,15 @@ nv10_fifo_ofuncs = {
 	.dtor = nv04_fifo_chan_dtor,
 	.init = nv04_fifo_chan_init,
 	.fini = nv04_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv10_fifo_sclass[] = {
-	{ NV10_CHANNEL_DMA_CLASS, &nv10_fifo_ofuncs },
+	{ NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/engctx.h>
 #include <core/ramht.h>
 
@@ -64,16 +65,23 @@ nv17_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nv04_fifo_priv *priv = (void *)engine;
 	struct nv04_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-					  0x10000, args->pushbuf,
+					  0x10000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -83,13 +91,15 @@ nv17_fifo_chan_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->object_attach = nv04_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv04_fifo_object_detach;
 	nv_parent(chan)->context_attach = nv04_fifo_context_attach;
 	chan->ramfc = chan->base.chid * 64;
 
-	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
-	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x14,
 			     NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -107,13 +117,15 @@ nv17_fifo_ofuncs = {
 	.dtor = nv04_fifo_chan_dtor,
 	.init = nv04_fifo_chan_init,
 	.fini = nv04_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv17_fifo_sclass[] = {
-	{ NV17_CHANNEL_DMA_CLASS, &nv17_fifo_ofuncs },
+	{ NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,9 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/engctx.h>
 #include <core/ramht.h>
 
@@ -182,16 +183,23 @@ nv40_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nv04_fifo_priv *priv = (void *)engine;
 	struct nv04_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-					  0x1000, args->pushbuf,
+					  0x1000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -200,14 +208,16 @@ nv40_fifo_chan_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->context_attach = nv40_fifo_context_attach;
 	nv_parent(chan)->context_detach = nv40_fifo_context_detach;
 	nv_parent(chan)->object_attach = nv40_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv04_fifo_object_detach;
 	chan->ramfc = chan->base.chid * 128;
 
-	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
-	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+	nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
 	nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 |
 			     NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -226,13 +236,15 @@ nv40_fifo_ofuncs = {
 	.dtor = nv04_fifo_chan_dtor,
 	.init = nv04_fifo_chan_init,
 	.fini = nv04_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv40_fifo_sclass[] = {
-	{ NV40_CHANNEL_DMA_CLASS, &nv40_fifo_ofuncs },
+	{ NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,8 @@
 #include <core/client.h>
 #include <core/engctx.h>
 #include <core/ramht.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
@@ -194,17 +195,24 @@ nv50_fifo_chan_ctor_dma(struct nouveau_o
 			struct nouveau_oclass *oclass, void *data, u32 size,
 			struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nv50_fifo_base *base = (void *)parent;
 	struct nv50_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-					  0x2000, args->pushbuf,
+					  0x2000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -213,6 +221,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_o
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->context_attach = nv50_fifo_context_attach;
 	nv_parent(chan)->context_detach = nv50_fifo_context_detach;
 	nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@@ -223,10 +233,10 @@ nv50_fifo_chan_ctor_dma(struct nouveau_o
 	if (ret)
 		return ret;
 
-	nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
+	nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
 	nv_wo32(base->ramfc, 0x3c, 0x003f6078);
 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
 	nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@@ -247,18 +257,26 @@ nv50_fifo_chan_ctor_ind(struct nouveau_o
 			struct nouveau_oclass *oclass, void *data, u32 size,
 			struct nouveau_object **pobject)
 {
-	struct nv50_channel_ind_class *args = data;
+	union {
+		struct nv50_channel_gpfifo_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nv50_fifo_base *base = (void *)parent;
 	struct nv50_fifo_chan *chan;
 	u64 ioffset, ilength;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+				 "ioffset %016llx ilength %08x\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+			 args->v0.ilength);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-					  0x2000, args->pushbuf,
+					  0x2000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -267,6 +285,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_o
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->context_attach = nv50_fifo_context_attach;
 	nv_parent(chan)->context_detach = nv50_fifo_context_detach;
 	nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@@ -277,8 +297,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_o
 	if (ret)
 		return ret;
 
-	ioffset = args->ioffset;
-	ilength = order_base_2(args->ilength / 8);
+	ioffset = args->v0.ioffset;
+	ilength = order_base_2(args->v0.ilength / 8);
 
 	nv_wo32(base->ramfc, 0x3c, 0x403f6078);
 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
@@ -343,8 +363,10 @@ nv50_fifo_ofuncs_dma = {
 	.dtor = nv50_fifo_chan_dtor,
 	.init = nv50_fifo_chan_init,
 	.fini = nv50_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_ofuncs
@@ -353,14 +375,16 @@ nv50_fifo_ofuncs_ind = {
 	.dtor = nv50_fifo_chan_dtor,
 	.init = nv50_fifo_chan_init,
 	.fini = nv50_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv50_fifo_sclass[] = {
-	{ NV50_CHANNEL_DMA_CLASS, &nv50_fifo_ofuncs_dma },
-	{ NV50_CHANNEL_IND_CLASS, &nv50_fifo_ofuncs_ind },
+	{ NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
+	{ NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,8 @@
 #include <core/engctx.h>
 #include <core/ramht.h>
 #include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
@@ -160,17 +161,24 @@ nv84_fifo_chan_ctor_dma(struct nouveau_o
 			struct nouveau_oclass *oclass, void *data, u32 size,
 			struct nouveau_object **pobject)
 {
+	union {
+		struct nv03_channel_dma_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nv50_fifo_base *base = (void *)parent;
 	struct nv50_fifo_chan *chan;
-	struct nv03_channel_dma_class *args = data;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel dma size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+				 "offset %016llx\n", args->v0.version,
+			 args->v0.pushbuf, args->v0.offset);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-					  0x2000, args->pushbuf,
+					  0x2000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -186,6 +194,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_o
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
 			       &chan->ramht);
 	if (ret)
@@ -196,10 +206,10 @@ nv84_fifo_chan_ctor_dma(struct nouveau_o
 	nv_parent(chan)->object_attach = nv84_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv50_fifo_object_detach;
 
-	nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
-	nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
+	nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
+	nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
 	nv_wo32(base->ramfc, 0x3c, 0x003f6078);
 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
 	nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@@ -222,18 +232,26 @@ nv84_fifo_chan_ctor_ind(struct nouveau_o
 			struct nouveau_oclass *oclass, void *data, u32 size,
 			struct nouveau_object **pobject)
 {
+	union {
+		struct nv50_channel_gpfifo_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nv50_fifo_base *base = (void *)parent;
 	struct nv50_fifo_chan *chan;
-	struct nv50_channel_ind_class *args = data;
 	u64 ioffset, ilength;
 	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+				 "ioffset %016llx ilength %08x\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+			 args->v0.ilength);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-					  0x2000, args->pushbuf,
+					  0x2000, args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_DMAOBJ) |
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
@@ -249,6 +267,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_o
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
 			       &chan->ramht);
 	if (ret)
@@ -259,8 +279,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_o
 	nv_parent(chan)->object_attach = nv84_fifo_object_attach;
 	nv_parent(chan)->object_detach = nv50_fifo_object_detach;
 
-	ioffset = args->ioffset;
-	ilength = order_base_2(args->ilength / 8);
+	ioffset = args->v0.ioffset;
+	ilength = order_base_2(args->v0.ilength / 8);
 
 	nv_wo32(base->ramfc, 0x3c, 0x403f6078);
 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
@@ -304,8 +324,10 @@ nv84_fifo_ofuncs_dma = {
 	.dtor = nv50_fifo_chan_dtor,
 	.init = nv84_fifo_chan_init,
 	.fini = nv50_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_ofuncs
@@ -314,14 +336,16 @@ nv84_fifo_ofuncs_ind = {
 	.dtor = nv50_fifo_chan_dtor,
 	.init = nv84_fifo_chan_init,
 	.fini = nv50_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nv84_fifo_sclass[] = {
-	{ NV84_CHANNEL_DMA_CLASS, &nv84_fifo_ofuncs_dma },
-	{ NV84_CHANNEL_IND_CLASS, &nv84_fifo_ofuncs_ind },
+	{ G82_CHANNEL_DMA, &nv84_fifo_ofuncs_dma },
+	{ G82_CHANNEL_GPFIFO, &nv84_fifo_ofuncs_ind },
 	{}
 };
 
@@ -389,19 +413,26 @@ nv84_fifo_cclass = {
  ******************************************************************************/
 
 static void
-nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nv84_fifo_uevent_init(struct nvkm_event *event, int type, int index)
 {
-	struct nv84_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x40000000, 0x40000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x40000000, 0x40000000);
 }
 
 static void
-nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nv84_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
 {
-	struct nv84_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x40000000, 0x00000000);
 }
 
+static const struct nvkm_event_func
+nv84_fifo_uevent_func = {
+	.ctor = nouveau_fifo_uevent_ctor,
+	.init = nv84_fifo_uevent_init,
+	.fini = nv84_fifo_uevent_fini,
+};
+
 static int
 nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	       struct nouveau_oclass *oclass, void *data, u32 size,
@@ -425,9 +456,9 @@ nv84_fifo_ctor(struct nouveau_object *pa
 	if (ret)
 		return ret;
 
-	priv->base.uevent->enable = nv84_fifo_uevent_enable;
-	priv->base.uevent->disable = nv84_fifo_uevent_disable;
-	priv->base.uevent->priv = priv;
+	ret = nvkm_event_init(&nv84_fifo_uevent_func, 1, 1, &priv->base.uevent);
+	if (ret)
+		return ret;
 
 	nv_subdev(priv)->unit = 0x00000100;
 	nv_subdev(priv)->intr = nv04_fifo_intr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,8 @@
 #include <core/gpuobj.h>
 #include <core/engctx.h>
 #include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/enum.h>
 
 #include <subdev/timer.h>
@@ -187,20 +188,28 @@ nvc0_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct nv50_channel_gpfifo_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nvc0_fifo_priv *priv = (void *)engine;
 	struct nvc0_fifo_base *base = (void *)parent;
 	struct nvc0_fifo_chan *chan;
-	struct nv50_channel_ind_class *args = data;
 	u64 usermem, ioffset, ilength;
 	int ret, i;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+				 "ioffset %016llx ilength %08x\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+			 args->v0.ilength);
+	} else
+		return ret;
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
 					  priv->user.bar.offset, 0x1000,
-					  args->pushbuf,
+					  args->v0.pushbuf,
 					  (1ULL << NVDEV_ENGINE_SW) |
 					  (1ULL << NVDEV_ENGINE_GR) |
 					  (1ULL << NVDEV_ENGINE_COPY0) |
@@ -212,12 +221,14 @@ nvc0_fifo_chan_ctor(struct nouveau_objec
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->context_attach = nvc0_fifo_context_attach;
 	nv_parent(chan)->context_detach = nvc0_fifo_context_detach;
 
 	usermem = chan->base.chid * 0x1000;
-	ioffset = args->ioffset;
-	ilength = order_base_2(args->ilength / 8);
+	ioffset = args->v0.ioffset;
+	ilength = order_base_2(args->v0.ilength / 8);
 
 	for (i = 0; i < 0x1000; i += 4)
 		nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@@ -291,13 +302,15 @@ nvc0_fifo_ofuncs = {
 	.dtor = _nouveau_fifo_channel_dtor,
 	.init = nvc0_fifo_chan_init,
 	.fini = nvc0_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nvc0_fifo_sclass[] = {
-	{ NVC0_CHANNEL_IND_CLASS, &nvc0_fifo_ofuncs },
+	{ FERMI_CHANNEL_GPFIFO, &nvc0_fifo_ofuncs },
 	{}
 };
 
@@ -654,7 +667,7 @@ nvc0_fifo_intr_fault(struct nvc0_fifo_pr
 	object = engctx;
 	while (object) {
 		switch (nv_mclass(object)) {
-		case NVC0_CHANNEL_IND_CLASS:
+		case FERMI_CHANNEL_GPFIFO:
 			nvc0_fifo_recover(priv, engine, (void *)object);
 			break;
 		}
@@ -730,7 +743,7 @@ nvc0_fifo_intr_engine_unit(struct nvc0_f
 	for (unkn = 0; unkn < 8; unkn++) {
 		u32 ints = (intr >> (unkn * 0x04)) & inte;
 		if (ints & 0x1) {
-			nouveau_event_trigger(priv->base.uevent, 1, 0);
+			nouveau_fifo_uevent(&priv->base);
 			ints &= ~1;
 		}
 		if (ints) {
@@ -827,19 +840,26 @@ nvc0_fifo_intr(struct nouveau_subdev *su
 }
 
 static void
-nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nvc0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
 {
-	struct nvc0_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
 }
 
 static void
-nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nvc0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
 {
-	struct nvc0_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
 }
 
+static const struct nvkm_event_func
+nvc0_fifo_uevent_func = {
+	.ctor = nouveau_fifo_uevent_ctor,
+	.init = nvc0_fifo_uevent_init,
+	.fini = nvc0_fifo_uevent_fini,
+};
+
 static int
 nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	       struct nouveau_oclass *oclass, void *data, u32 size,
@@ -877,9 +897,9 @@ nvc0_fifo_ctor(struct nouveau_object *pa
 	if (ret)
 		return ret;
 
-	priv->base.uevent->enable = nvc0_fifo_uevent_enable;
-	priv->base.uevent->disable = nvc0_fifo_uevent_disable;
-	priv->base.uevent->priv = priv;
+	ret = nvkm_event_init(&nvc0_fifo_uevent_func, 1, 1, &priv->base.uevent);
+	if (ret)
+		return ret;
 
 	nv_subdev(priv)->unit = 0x00000100;
 	nv_subdev(priv)->intr = nvc0_fifo_intr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,8 @@
 #include <core/gpuobj.h>
 #include <core/engctx.h>
 #include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 #include <core/enum.h>
 
 #include <subdev/timer.h>
@@ -216,46 +217,56 @@ nve0_fifo_chan_ctor(struct nouveau_objec
 		    struct nouveau_oclass *oclass, void *data, u32 size,
 		    struct nouveau_object **pobject)
 {
+	union {
+		struct kepler_channel_gpfifo_a_v0 v0;
+	} *args = data;
 	struct nouveau_bar *bar = nouveau_bar(parent);
 	struct nve0_fifo_priv *priv = (void *)engine;
 	struct nve0_fifo_base *base = (void *)parent;
 	struct nve0_fifo_chan *chan;
-	struct nve0_channel_ind_class *args = data;
 	u64 usermem, ioffset, ilength;
 	int ret, i;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+				 "ioffset %016llx ilength %08x engine %08x\n",
+			 args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+			 args->v0.ilength, args->v0.engine);
+	} else
+		return ret;
 
 	for (i = 0; i < FIFO_ENGINE_NR; i++) {
-		if (args->engine & (1 << i)) {
+		if (args->v0.engine & (1 << i)) {
 			if (nouveau_engine(parent, fifo_engine[i].subdev)) {
-				args->engine = (1 << i);
+				args->v0.engine = (1 << i);
 				break;
 			}
 		}
 	}
 
 	if (i == FIFO_ENGINE_NR) {
-		nv_error(priv, "unsupported engines 0x%08x\n", args->engine);
+		nv_error(priv, "unsupported engines 0x%08x\n", args->v0.engine);
 		return -ENODEV;
 	}
 
 	ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
 					  priv->user.bar.offset, 0x200,
-					  args->pushbuf,
+					  args->v0.pushbuf,
 					  fifo_engine[i].mask, &chan);
 	*pobject = nv_object(chan);
 	if (ret)
 		return ret;
 
+	args->v0.chid = chan->base.chid;
+
 	nv_parent(chan)->context_attach = nve0_fifo_context_attach;
 	nv_parent(chan)->context_detach = nve0_fifo_context_detach;
 	chan->engine = i;
 
 	usermem = chan->base.chid * 0x200;
-	ioffset = args->ioffset;
-	ilength = order_base_2(args->ilength / 8);
+	ioffset = args->v0.ioffset;
+	ilength = order_base_2(args->v0.ilength / 8);
 
 	for (i = 0; i < 0x200; i += 4)
 		nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@@ -325,13 +336,15 @@ nve0_fifo_ofuncs = {
 	.dtor = _nouveau_fifo_channel_dtor,
 	.init = nve0_fifo_chan_init,
 	.fini = nve0_fifo_chan_fini,
+	.map  = _nouveau_fifo_channel_map,
 	.rd32 = _nouveau_fifo_channel_rd32,
 	.wr32 = _nouveau_fifo_channel_wr32,
+	.ntfy = _nouveau_fifo_channel_ntfy
 };
 
 static struct nouveau_oclass
 nve0_fifo_sclass[] = {
-	{ NVE0_CHANNEL_IND_CLASS, &nve0_fifo_ofuncs },
+	{ KEPLER_CHANNEL_GPFIFO_A, &nve0_fifo_ofuncs },
 	{}
 };
 
@@ -769,7 +782,7 @@ nve0_fifo_intr_fault(struct nve0_fifo_pr
 	object = engctx;
 	while (object) {
 		switch (nv_mclass(object)) {
-		case NVE0_CHANNEL_IND_CLASS:
+		case KEPLER_CHANNEL_GPFIFO_A:
 			nve0_fifo_recover(priv, engine, (void *)object);
 			break;
 		}
@@ -859,7 +872,7 @@ nve0_fifo_intr_runlist(struct nve0_fifo_
 static void
 nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
 {
-	nouveau_event_trigger(priv->base.uevent, 1, 0);
+	nouveau_fifo_uevent(&priv->base);
 }
 
 static void
@@ -952,19 +965,26 @@ nve0_fifo_intr(struct nouveau_subdev *su
 }
 
 static void
-nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nve0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
 {
-	struct nve0_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
 }
 
 static void
-nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nve0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
 {
-	struct nve0_fifo_priv *priv = event->priv;
-	nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+	struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+	nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
 }
 
+static const struct nvkm_event_func
+nve0_fifo_uevent_func = {
+	.ctor = nouveau_fifo_uevent_ctor,
+	.init = nve0_fifo_uevent_init,
+	.fini = nve0_fifo_uevent_fini,
+};
+
 int
 nve0_fifo_fini(struct nouveau_object *object, bool suspend)
 {
@@ -1067,9 +1087,9 @@ nve0_fifo_ctor(struct nouveau_object *pa
 	if (ret)
 		return ret;
 
-	priv->base.uevent->enable = nve0_fifo_uevent_enable;
-	priv->base.uevent->disable = nve0_fifo_uevent_disable;
-	priv->base.uevent->priv = priv;
+	ret = nvkm_event_init(&nve0_fifo_uevent_func, 1, 1, &priv->base.uevent);
+	if (ret)
+		return ret;
 
 	nv_subdev(priv)->unit = 0x00000100;
 	nv_subdev(priv)->intr = nve0_fifo_intr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 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 "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gk110b_grctx_init_sm_0[] = {
+	{ 0x419e04,   1, 0x04, 0x00000000 },
+	{ 0x419e08,   1, 0x04, 0x0000001d },
+	{ 0x419e0c,   1, 0x04, 0x00000000 },
+	{ 0x419e10,   1, 0x04, 0x00001c02 },
+	{ 0x419e44,   1, 0x04, 0x0013eff2 },
+	{ 0x419e48,   1, 0x04, 0x00000000 },
+	{ 0x419e4c,   1, 0x04, 0x0000007f },
+	{ 0x419e50,   2, 0x04, 0x00000000 },
+	{ 0x419e58,   1, 0x04, 0x00000001 },
+	{ 0x419e5c,   3, 0x04, 0x00000000 },
+	{ 0x419e68,   1, 0x04, 0x00000002 },
+	{ 0x419e6c,  12, 0x04, 0x00000000 },
+	{ 0x419eac,   1, 0x04, 0x00001f8f },
+	{ 0x419eb0,   1, 0x04, 0x0db00d2f },
+	{ 0x419eb8,   1, 0x04, 0x00000000 },
+	{ 0x419ec8,   1, 0x04, 0x0001304f },
+	{ 0x419f30,   4, 0x04, 0x00000000 },
+	{ 0x419f40,   1, 0x04, 0x00000018 },
+	{ 0x419f44,   3, 0x04, 0x00000000 },
+	{ 0x419f58,   1, 0x04, 0x00000000 },
+	{ 0x419f70,   1, 0x04, 0x00006300 },
+	{ 0x419f78,   1, 0x04, 0x000000eb },
+	{ 0x419f7c,   1, 0x04, 0x00000404 },
+	{}
+};
+
+static const struct nvc0_graph_pack
+gk110b_grctx_pack_tpc[] = {
+	{ nvd7_grctx_init_pe_0 },
+	{ nvf0_grctx_init_tex_0 },
+	{ nvf0_grctx_init_mpc_0 },
+	{ nvf0_grctx_init_l1c_0 },
+	{ gk110b_grctx_init_sm_0 },
+	{}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
+struct nouveau_oclass *
+gk110b_grctx_oclass = &(struct nvc0_grctx_oclass) {
+	.base.handle = NV_ENGCTX(GR, 0xf1),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nvc0_graph_context_ctor,
+		.dtor = nvc0_graph_context_dtor,
+		.init = _nouveau_graph_context_init,
+		.fini = _nouveau_graph_context_fini,
+		.rd32 = _nouveau_graph_context_rd32,
+		.wr32 = _nouveau_graph_context_wr32,
+	},
+	.main  = nve4_grctx_generate_main,
+	.unkn  = nve4_grctx_generate_unkn,
+	.hub   = nvf0_grctx_pack_hub,
+	.gpc   = nvf0_grctx_pack_gpc,
+	.zcull = nvc0_grctx_pack_zcull,
+	.tpc   = gk110b_grctx_pack_tpc,
+	.ppc   = nvf0_grctx_pack_ppc,
+	.icmd  = nvf0_grctx_pack_icmd,
+	.mthd  = nvf0_grctx_pack_mthd,
+	.bundle = nve4_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x600,
+	.pagepool = nve4_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,6 @@ gk20a_grctx_oclass = &(struct nvc0_grctx
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nve4_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nve4_grctx_pack_hub,
 	.gpc   = nve4_grctx_pack_gpc,
@@ -50,4 +49,15 @@ gk20a_grctx_oclass = &(struct nvc0_grctx
 	.ppc   = nve4_grctx_pack_ppc,
 	.icmd  = nve4_grctx_pack_icmd,
 	.mthd  = gk20a_grctx_pack_mthd,
+	.bundle = nve4_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.bundle_min_gpm_fifo_depth = 0x62,
+	.bundle_token_limit = 0x100,
+	.pagepool = nve4_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x240,
+	.attrib_nr = 0x240,
+	.alpha_nr_max = 0x648 + (0x648 / 2),
+	.alpha_nr = 0x648,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c	2014-09-28 17:29:07.000000000 -0400
@@ -859,45 +859,74 @@ gm107_grctx_pack_ppc[] = {
  ******************************************************************************/
 
 static void
-gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+gm107_grctx_generate_bundle(struct nvc0_grctx *info)
 {
-	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW);
-
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x4064cc, 0x80000000,  0, 0);
-	mmio_list(0x418e30, 0x80000000,  0, 0);
-
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000030,  0, 0);
-	mmio_list(0x418e24, 0x00000000,  8, 0);
-	mmio_list(0x418e28, 0x80000030,  0, 0);
-
-	mmio_list(0x4064c8, 0x018002c0,  0, 0);
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
+				    impl->bundle_size / 0x20);
+	const u32 token_limit = impl->bundle_token_limit;
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+	mmio_refn(info, 0x408004, 0x00000000, s, b);
+	mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+	mmio_refn(info, 0x418e24, 0x00000000, s, b);
+	mmio_refn(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s), 0, b);
+	mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+}
 
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-	mmio_list(0x419c2c, 0x10000000, 12, 2);
+static void
+gm107_grctx_generate_pagepool(struct nvc0_grctx *info)
+{
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+	mmio_refn(info, 0x40800c, 0x00000000, s, b);
+	mmio_wr32(info, 0x408010, 0x80000000);
+	mmio_refn(info, 0x419004, 0x00000000, s, b);
+	mmio_wr32(info, 0x419008, 0x00000000);
+	mmio_wr32(info, 0x4064cc, 0x80000000);
+	mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */
+}
 
-	mmio_list(0x405830, 0x0aa01000,  0, 0);
-	mmio_list(0x4064c4, 0x0400ffff,  0, 0);
+static void
+gm107_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = (void *)nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32 attrib = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+	int gpc, ppc, n = 0;
 
-	/*XXX*/
-	mmio_list(0x5030c0, 0x00001540,  0, 0);
-	mmio_list(0x5030f4, 0x00000000,  0, 0);
-	mmio_list(0x5030e4, 0x00002000,  0, 0);
-	mmio_list(0x5030f8, 0x00003fc0,  0, 0);
-	mmio_list(0x418ea0, 0x07151540,  0, 0);
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_refn(info, 0x419c2c, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (attrib << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
 
-	mmio_list(0x5032c0, 0x00001540,  0, 0);
-	mmio_list(0x5032f4, 0x00001fe0,  0, 0);
-	mmio_list(0x5032e4, 0x00002000,  0, 0);
-	mmio_list(0x5032f8, 0x00006fc0,  0, 0);
-	mmio_list(0x418ea4, 0x07151540,  0, 0);
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++, n++) {
+			const u32 as =  alpha * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 bs = attrib * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 u = 0x418ea0 + (n * 0x04);
+			const u32 o = PPC_UNIT(gpc, ppc, 0);
+			mmio_wr32(info, o + 0xc0, bs);
+			mmio_wr32(info, o + 0xf4, bo);
+			bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, o + 0xe4, as);
+			mmio_wr32(info, o + 0xf8, ao);
+			ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs);
+		}
+	}
 }
 
 static void
@@ -934,7 +963,9 @@ gm107_grctx_generate_main(struct nvc0_gr
 
 	nv_wr32(priv, 0x404154, 0x00000000);
 
-	oclass->mods(priv, info);
+	oclass->bundle(info);
+	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->unkn(priv);
 
 	gm107_grctx_generate_tpcid(priv);
@@ -979,7 +1010,6 @@ gm107_grctx_oclass = &(struct nvc0_grctx
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = gm107_grctx_generate_main,
-	.mods  = gm107_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = gm107_grctx_pack_hub,
 	.gpc   = gm107_grctx_pack_gpc,
@@ -988,4 +1018,15 @@ gm107_grctx_oclass = &(struct nvc0_grctx
 	.ppc   = gm107_grctx_pack_ppc,
 	.icmd  = gm107_grctx_pack_icmd,
 	.mthd  = gm107_grctx_pack_mthd,
+	.bundle = gm107_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x2c0,
+	.pagepool = gm107_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = gm107_grctx_generate_attrib,
+	.attrib_nr_max = 0xff0,
+	.attrib_nr = 0xaa0,
+	.alpha_nr_max = 0x1800,
+	.alpha_nr = 0x1000,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c	2014-09-28 17:29:07.000000000 -0400
@@ -531,50 +531,6 @@ nv108_grctx_pack_ppc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
-static void
-nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
-{
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x4064cc, 0x80000000,  0, 0);
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000030,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000030,  0, 0);
-	mmio_list(0x4064c8, 0x00c20200,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
-	}
-
-	mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
-	mmio_list(0x17e920, 0x00090d08, 0, 0);
-}
-
 struct nouveau_oclass *
 nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
 	.base.handle = NV_ENGCTX(GR, 0x08),
@@ -587,7 +543,6 @@ nv108_grctx_oclass = &(struct nvc0_grctx
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nv108_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nv108_grctx_pack_hub,
 	.gpc   = nv108_grctx_pack_gpc,
@@ -596,4 +551,15 @@ nv108_grctx_oclass = &(struct nvc0_grctx
 	.ppc   = nv108_grctx_pack_ppc,
 	.icmd  = nv108_grctx_pack_icmd,
 	.mthd  = nvf0_grctx_pack_mthd,
+	.bundle = nve4_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0xc2,
+	.bundle_token_limit = 0x200,
+	.pagepool = nve4_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -982,34 +982,93 @@ nvc0_grctx_pack_tpc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
+int
+nvc0_grctx_mmio_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access)
+{
+	if (info->data) {
+		info->buffer[info->buffer_nr] = round_up(info->addr, align);
+		info->addr = info->buffer[info->buffer_nr] + size;
+		info->data->size = size;
+		info->data->align = align;
+		info->data->access = access;
+		info->data++;
+		return info->buffer_nr++;
+	}
+	return -1;
+}
+
 void
-nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc0_grctx_mmio_item(struct nvc0_grctx *info, u32 addr, u32 data,
+		     int shift, int buffer)
 {
-	int gpc, tpc;
-	u32 offset;
+	if (info->data) {
+		if (shift >= 0) {
+			info->mmio->addr = addr;
+			info->mmio->data = data;
+			info->mmio->shift = shift;
+			info->mmio->buffer = buffer;
+			if (buffer >= 0)
+				data |= info->buffer[buffer] >> shift;
+			info->mmio++;
+		} else
+			return;
+	} else {
+		if (buffer >= 0)
+			return;
+	}
 
-	mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+	nv_wr32(info->priv, addr, data);
+}
 
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000018,  0, 0);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000018,  0, 0);
+void
+nvc0_grctx_generate_bundle(struct nvc0_grctx *info)
+{
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+	mmio_refn(info, 0x408004, 0x00000000, s, b);
+	mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+	mmio_refn(info, 0x418808, 0x00000000, s, b);
+	mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+}
 
-	mmio_list(0x405830, 0x02180000, 0, 0);
+void
+nvc0_grctx_generate_pagepool(struct nvc0_grctx *info)
+{
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+	mmio_refn(info, 0x40800c, 0x00000000, s, b);
+	mmio_wr32(info, 0x408010, 0x80000000);
+	mmio_refn(info, 0x419004, 0x00000000, s, b);
+	mmio_wr32(info, 0x419008, 0x00000000);
+}
 
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+void
+nvc0_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32 attrib = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	int gpc, tpc;
+	u32 bo = 0;
+
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (attrib << 16));
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
 		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
-			mmio_list(addr, 0x02180000 | offset, 0, 0);
-			offset += 0x0324;
+			const u32 o = TPC_UNIT(gpc, tpc, 0x0520);
+			mmio_skip(info, o, (attrib << 16) | ++bo);
+			mmio_wr32(info, o, (attrib << 16) | --bo);
+			bo += impl->attrib_nr_max;
 		}
 	}
 }
@@ -1170,7 +1229,7 @@ nvc0_grctx_generate_main(struct nvc0_gra
 {
 	struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
 
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
 
 	nvc0_graph_mmio(priv, oclass->hub);
 	nvc0_graph_mmio(priv, oclass->gpc);
@@ -1180,7 +1239,9 @@ nvc0_grctx_generate_main(struct nvc0_gra
 
 	nv_wr32(priv, 0x404154, 0x00000000);
 
-	oclass->mods(priv, info);
+	oclass->bundle(info);
+	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->unkn(priv);
 
 	nvc0_grctx_generate_tpcid(priv);
@@ -1192,7 +1253,7 @@ nvc0_grctx_generate_main(struct nvc0_gra
 	nvc0_graph_icmd(priv, oclass->icmd);
 	nv_wr32(priv, 0x404154, 0x00000400);
 	nvc0_graph_mthd(priv, oclass->mthd);
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
 }
 
 int
@@ -1308,7 +1369,6 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvc0_grctx_generate_main,
-	.mods  = nvc0_grctx_generate_mods,
 	.unkn  = nvc0_grctx_generate_unkn,
 	.hub   = nvc0_grctx_pack_hub,
 	.gpc   = nvc0_grctx_pack_gpc,
@@ -1316,4 +1376,11 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_
 	.tpc   = nvc0_grctx_pack_tpc,
 	.icmd  = nvc0_grctx_pack_icmd,
 	.mthd  = nvc0_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,12 +12,19 @@ struct nvc0_grctx {
 	u64 addr;
 };
 
+int  nvc0_grctx_mmio_data(struct nvc0_grctx *, u32 size, u32 align, u32 access);
+void nvc0_grctx_mmio_item(struct nvc0_grctx *, u32 addr, u32 data, int s, int);
+
+#define mmio_vram(a,b,c,d) nvc0_grctx_mmio_data((a), (b), (c), (d))
+#define mmio_refn(a,b,c,d,e) nvc0_grctx_mmio_item((a), (b), (c), (d), (e))
+#define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1)
+#define mmio_wr32(a,b,c) mmio_refn((a), (b), (c),  0, -1)
+
 struct nvc0_grctx_oclass {
 	struct nouveau_oclass base;
 	/* main context generation function */
 	void  (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
 	/* context-specific modify-on-first-load list generation function */
-	void  (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
 	void  (*unkn)(struct nvc0_graph_priv *);
 	/* mmio context data */
 	const struct nvc0_graph_pack *hub;
@@ -28,30 +35,34 @@ struct nvc0_grctx_oclass {
 	/* indirect context data, generated with icmds/mthds */
 	const struct nvc0_graph_pack *icmd;
 	const struct nvc0_graph_pack *mthd;
+	/* bundle circular buffer */
+	void (*bundle)(struct nvc0_grctx *);
+	u32 bundle_size;
+	u32 bundle_min_gpm_fifo_depth;
+	u32 bundle_token_limit;
+	/* pagepool */
+	void (*pagepool)(struct nvc0_grctx *);
+	u32 pagepool_size;
+	/* attribute(/alpha) circular buffer */
+	void (*attrib)(struct nvc0_grctx *);
+	u32 attrib_nr_max;
+	u32 attrib_nr;
+	u32 alpha_nr_max;
+	u32 alpha_nr;
 };
 
-#define mmio_data(s,a,p) do {                                                  \
-	info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
-	info->addr = info->buffer[info->buffer_nr++] + (s);                    \
-	info->data->size = (s);                                                \
-	info->data->align = (a);                                               \
-	info->data->access = (p);                                              \
-	info->data++;                                                          \
-} while(0)
-
-#define mmio_list(r,d,s,b) do {                                                \
-	info->mmio->addr = (r);                                                \
-	info->mmio->data = (d);                                                \
-	info->mmio->shift = (s);                                               \
-	info->mmio->buffer = (b);                                              \
-	info->mmio++;                                                          \
-	nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0));      \
-} while(0)
+static inline const struct nvc0_grctx_oclass *
+nvc0_grctx_impl(struct nvc0_graph_priv *priv)
+{
+	return (void *)nv_engine(priv)->cclass;
+}
 
 extern struct nouveau_oclass *nvc0_grctx_oclass;
 int  nvc0_grctx_generate(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc0_grctx_generate_bundle(struct nvc0_grctx *);
+void nvc0_grctx_generate_pagepool(struct nvc0_grctx *);
+void nvc0_grctx_generate_attrib(struct nvc0_grctx *);
 void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
@@ -60,22 +71,27 @@ void nvc0_grctx_generate_r418bb8(struct
 void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
 
 extern struct nouveau_oclass *nvc1_grctx_oclass;
-void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc1_grctx_generate_attrib(struct nvc0_grctx *);
 void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
 
 extern struct nouveau_oclass *nvc4_grctx_oclass;
 extern struct nouveau_oclass *nvc8_grctx_oclass;
+
 extern struct nouveau_oclass *nvd7_grctx_oclass;
+void nvd7_grctx_generate_attrib(struct nvc0_grctx *);
+
 extern struct nouveau_oclass *nvd9_grctx_oclass;
 
 extern struct nouveau_oclass *nve4_grctx_oclass;
 extern struct nouveau_oclass *gk20a_grctx_oclass;
 void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nve4_grctx_generate_bundle(struct nvc0_grctx *);
+void nve4_grctx_generate_pagepool(struct nvc0_grctx *);
 void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
 void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
 
 extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nouveau_oclass *gk110b_grctx_oclass;
 extern struct nouveau_oclass *nv108_grctx_oclass;
 extern struct nouveau_oclass *gm107_grctx_oclass;
 
@@ -160,16 +176,23 @@ extern const struct nvc0_graph_pack nve4
 extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[];
 extern const struct nvc0_graph_init nve4_grctx_init_a097_0[];
 
+extern const struct nvc0_graph_pack nvf0_grctx_pack_icmd[];
+
 extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
 
+extern const struct nvc0_graph_pack nvf0_grctx_pack_hub[];
 extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
 extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[];
 
+extern const struct nvc0_graph_pack nvf0_grctx_pack_gpc[];
 extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[];
 
+extern const struct nvc0_graph_init nvf0_grctx_init_tex_0[];
 extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[];
 extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[];
 
+extern const struct nvc0_graph_pack nvf0_grctx_pack_ppc[];
+
 extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[];
 
 extern const struct nvc0_graph_init nv108_grctx_init_prop_0[];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c	2014-09-28 17:29:07.000000000 -0400
@@ -727,38 +727,38 @@ nvc1_grctx_pack_tpc[] = {
  ******************************************************************************/
 
 void
-nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc1_grctx_generate_attrib(struct nvc0_grctx *info)
 {
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32   beta = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int timeslice_mode = 1;
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
 	int gpc, tpc;
-	u32 offset;
-
-	mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000018,  0, 0);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000018,  0, 0);
 
-	mmio_list(0x405830, 0x02180218, 0, 0);
-	mmio_list(0x4064c4, 0x0086ffff, 0, 0);
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
 
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
-			mmio_list(addr, 0x12180000 | offset, 0, 0);
-			offset += 0x0324;
-		}
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
 		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0544);
-			mmio_list(addr, 0x02180000 | offset, 0, 0);
-			offset += 0x0324;
+			const u32 a = alpha;
+			const u32 b =  beta;
+			const u32 t = timeslice_mode;
+			const u32 o = TPC_UNIT(gpc, tpc, 0x500);
+			mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo);
+			mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo);
+			bo += impl->attrib_nr_max;
+			mmio_wr32(info, o + 0x44, (a << 16) | ao);
+			ao += impl->alpha_nr_max;
 		}
 	}
 }
@@ -786,7 +786,6 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvc0_grctx_generate_main,
-	.mods  = nvc1_grctx_generate_mods,
 	.unkn  = nvc1_grctx_generate_unkn,
 	.hub   = nvc1_grctx_pack_hub,
 	.gpc   = nvc1_grctx_pack_gpc,
@@ -794,4 +793,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_
 	.tpc   = nvc1_grctx_pack_tpc,
 	.icmd  = nvc1_grctx_pack_icmd,
 	.mthd  = nvc1_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvc1_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x324,
+	.alpha_nr = 0x218,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,7 +92,6 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvc0_grctx_generate_main,
-	.mods  = nvc0_grctx_generate_mods,
 	.unkn  = nvc0_grctx_generate_unkn,
 	.hub   = nvc0_grctx_pack_hub,
 	.gpc   = nvc0_grctx_pack_gpc,
@@ -100,4 +99,11 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_
 	.tpc   = nvc4_grctx_pack_tpc,
 	.icmd  = nvc0_grctx_pack_icmd,
 	.mthd  = nvc0_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c	2014-09-28 17:29:07.000000000 -0400
@@ -343,7 +343,6 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvc0_grctx_generate_main,
-	.mods  = nvc0_grctx_generate_mods,
 	.unkn  = nvc0_grctx_generate_unkn,
 	.hub   = nvc0_grctx_pack_hub,
 	.gpc   = nvc8_grctx_pack_gpc,
@@ -351,4 +350,11 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_
 	.tpc   = nvc0_grctx_pack_tpc,
 	.icmd  = nvc8_grctx_pack_icmd,
 	.mthd  = nvc8_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,44 +177,41 @@ nvd7_grctx_pack_ppc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
-static void
-nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+void
+nvd7_grctx_generate_attrib(struct nvc0_grctx *info)
 {
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000018,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000018,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180324,  0, 0);
-	mmio_list(0x4064c4, 0x00c9ffff,  0, 0);
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32   beta = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int timeslice_mode = 1;
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+	int gpc, ppc;
 
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0324 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
 
 	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
+		for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) {
+			const u32 a = alpha * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 b =  beta * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 t = timeslice_mode;
+			const u32 o = PPC_UNIT(gpc, ppc, 0);
+			mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo);
+			mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo);
+			bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, o + 0xe4, (a << 16) | ao);
+			ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+		}
 	}
-	mmio_list(0x17e91c, 0x03060609, 0, 0); /* different from kepler */
 }
 
 void
@@ -223,7 +220,7 @@ nvd7_grctx_generate_main(struct nvc0_gra
 	struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
 	int i;
 
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
 
 	nvc0_graph_mmio(priv, oclass->hub);
 	nvc0_graph_mmio(priv, oclass->gpc);
@@ -233,7 +230,9 @@ nvd7_grctx_generate_main(struct nvc0_gra
 
 	nv_wr32(priv, 0x404154, 0x00000000);
 
-	oclass->mods(priv, info);
+	oclass->bundle(info);
+	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->unkn(priv);
 
 	nvc0_grctx_generate_tpcid(priv);
@@ -248,7 +247,7 @@ nvd7_grctx_generate_main(struct nvc0_gra
 	nvc0_graph_icmd(priv, oclass->icmd);
 	nv_wr32(priv, 0x404154, 0x00000400);
 	nvc0_graph_mthd(priv, oclass->mthd);
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
 }
 
 struct nouveau_oclass *
@@ -263,7 +262,6 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvd7_grctx_generate_main,
-	.mods  = nvd7_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nvd7_grctx_pack_hub,
 	.gpc   = nvd7_grctx_pack_gpc,
@@ -272,4 +270,13 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_
 	.ppc   = nvd7_grctx_pack_ppc,
 	.icmd  = nvd9_grctx_pack_icmd,
 	.mthd  = nvd9_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x324,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c	2014-09-28 17:29:07.000000000 -0400
@@ -511,7 +511,6 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nvc0_grctx_generate_main,
-	.mods  = nvc1_grctx_generate_mods,
 	.unkn  = nvc1_grctx_generate_unkn,
 	.hub   = nvd9_grctx_pack_hub,
 	.gpc   = nvd9_grctx_pack_gpc,
@@ -519,4 +518,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_
 	.tpc   = nvd9_grctx_pack_tpc,
 	.icmd  = nvd9_grctx_pack_icmd,
 	.mthd  = nvd9_grctx_pack_mthd,
+	.bundle = nvc0_grctx_generate_bundle,
+	.bundle_size = 0x1800,
+	.pagepool = nvc0_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvc1_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x324,
+	.alpha_nr = 0x218,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c	2014-09-28 17:29:07.000000000 -0400
@@ -839,47 +839,34 @@ nve4_grctx_pack_ppc[] = {
  ******************************************************************************/
 
 void
-nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nve4_grctx_generate_bundle(struct nvc0_grctx *info)
 {
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x4064cc, 0x80000000,  0, 0);
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000030,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000030,  0, 0);
-	mmio_list(0x4064c8, 0x01800600,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
-	}
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
+				    impl->bundle_size / 0x20);
+	const u32 token_limit = impl->bundle_token_limit;
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+	mmio_refn(info, 0x408004, 0x00000000, s, b);
+	mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+	mmio_refn(info, 0x418808, 0x00000000, s, b);
+	mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+	mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+}
 
-	mmio_list(0x17e91c, 0x06060609, 0, 0);
-	mmio_list(0x17e920, 0x00090a05, 0, 0);
+void
+nve4_grctx_generate_pagepool(struct nvc0_grctx *info)
+{
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+	const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+	const int s = 8;
+	const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+	mmio_refn(info, 0x40800c, 0x00000000, s, b);
+	mmio_wr32(info, 0x408010, 0x80000000);
+	mmio_refn(info, 0x419004, 0x00000000, s, b);
+	mmio_wr32(info, 0x419008, 0x00000000);
+	mmio_wr32(info, 0x4064cc, 0x80000000);
 }
 
 void
@@ -957,7 +944,7 @@ nve4_grctx_generate_main(struct nvc0_gra
 	struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
 	int i;
 
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
 
 	nvc0_graph_mmio(priv, oclass->hub);
 	nvc0_graph_mmio(priv, oclass->gpc);
@@ -967,7 +954,9 @@ nve4_grctx_generate_main(struct nvc0_gra
 
 	nv_wr32(priv, 0x404154, 0x00000000);
 
-	oclass->mods(priv, info);
+	oclass->bundle(info);
+	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->unkn(priv);
 
 	nvc0_grctx_generate_tpcid(priv);
@@ -991,7 +980,7 @@ nve4_grctx_generate_main(struct nvc0_gra
 	nvc0_graph_icmd(priv, oclass->icmd);
 	nv_wr32(priv, 0x404154, 0x00000400);
 	nvc0_graph_mthd(priv, oclass->mthd);
-	nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
 
 	nv_mask(priv, 0x418800, 0x00200000, 0x00200000);
 	nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);
@@ -1009,7 +998,6 @@ nve4_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nve4_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nve4_grctx_pack_hub,
 	.gpc   = nve4_grctx_pack_gpc,
@@ -1018,4 +1006,15 @@ nve4_grctx_oclass = &(struct nvc0_grctx_
 	.ppc   = nve4_grctx_pack_ppc,
 	.icmd  = nve4_grctx_pack_icmd,
 	.mthd  = nve4_grctx_pack_mthd,
+	.bundle = nve4_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x600,
+	.pagepool = nve4_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c	2014-09-28 17:29:07.000000000 -0400
@@ -279,7 +279,7 @@ nvf0_grctx_init_icmd_0[] = {
 	{}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nvf0_grctx_pack_icmd[] = {
 	{ nvf0_grctx_init_icmd_0 },
 	{}
@@ -668,7 +668,7 @@ nvf0_grctx_init_be_0[] = {
 	{}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nvf0_grctx_pack_hub[] = {
 	{ nvc0_grctx_init_main_0 },
 	{ nvf0_grctx_init_fe_0 },
@@ -704,7 +704,7 @@ nvf0_grctx_init_gpc_unk_2[] = {
 	{}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nvf0_grctx_pack_gpc[] = {
 	{ nvc0_grctx_init_gpc_unk_0 },
 	{ nvd9_grctx_init_prop_0 },
@@ -718,7 +718,7 @@ nvf0_grctx_pack_gpc[] = {
 	{}
 };
 
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
 nvf0_grctx_init_tex_0[] = {
 	{ 0x419a00,   1, 0x04, 0x000000f0 },
 	{ 0x419a04,   1, 0x04, 0x00000001 },
@@ -797,7 +797,7 @@ nvf0_grctx_init_cbm_0[] = {
 	{}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nvf0_grctx_pack_ppc[] = {
 	{ nve4_grctx_init_pes_0 },
 	{ nvf0_grctx_init_cbm_0 },
@@ -809,58 +809,6 @@ nvf0_grctx_pack_ppc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
-static void
-nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
-{
-	u32 magic[GPC_MAX][4];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x40800c, 0x00000000,  8, 1);
-	mmio_list(0x408010, 0x80000000,  0, 0);
-	mmio_list(0x419004, 0x00000000,  8, 1);
-	mmio_list(0x419008, 0x00000000,  0, 0);
-	mmio_list(0x4064cc, 0x80000000,  0, 0);
-	mmio_list(0x408004, 0x00000000,  8, 0);
-	mmio_list(0x408008, 0x80000030,  0, 0);
-	mmio_list(0x418808, 0x00000000,  8, 0);
-	mmio_list(0x41880c, 0x80000030,  0, 0);
-	mmio_list(0x4064c8, 0x01800600,  0, 0);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * (priv->tpc_nr[gpc] - 1);
-		u16 magic1 = 0x0648 * (priv->tpc_nr[gpc] - 1);
-		u16 magic2 = 0x0218;
-		u16 magic3 = 0x0648;
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * (priv->tpc_nr[gpc] - 1);
-		magic[gpc][2]  = 0x10000000 | (magic2 << 16) | offset;
-		magic[gpc][3]  = 0x00000000 | (magic3 << 16);
-		offset += 0x0324;
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * (priv->tpc_nr[gpc] - 1);
-		mmio_list(GPC_UNIT(gpc, 0x32c0), magic[gpc][2], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x32e4), magic[gpc][3] | offset, 0, 0);
-		offset += 0x07ff;
-	}
-
-	mmio_list(0x17e91c, 0x06060609, 0, 0);
-	mmio_list(0x17e920, 0x00090a05, 0, 0);
-}
-
 struct nouveau_oclass *
 nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
 	.base.handle = NV_ENGCTX(GR, 0xf0),
@@ -873,7 +821,6 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nvf0_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nvf0_grctx_pack_hub,
 	.gpc   = nvf0_grctx_pack_gpc,
@@ -882,4 +829,15 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_
 	.ppc   = nvf0_grctx_pack_ppc,
 	.icmd  = nvf0_grctx_pack_icmd,
 	.mthd  = nvf0_grctx_pack_mthd,
+	.bundle = nve4_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x7c0,
+	.pagepool = nve4_grctx_generate_pagepool,
+	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 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 "nvc0.h"
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gk110b_graph_init_l1c_0[] = {
+	{ 0x419c98,   1, 0x04, 0x00000000 },
+	{ 0x419ca8,   1, 0x04, 0x00000000 },
+	{ 0x419cb0,   1, 0x04, 0x09000000 },
+	{ 0x419cb4,   1, 0x04, 0x00000000 },
+	{ 0x419cb8,   1, 0x04, 0x00b08bea },
+	{ 0x419c84,   1, 0x04, 0x00010384 },
+	{ 0x419cbc,   1, 0x04, 0x281b3646 },
+	{ 0x419cc0,   2, 0x04, 0x00000000 },
+	{ 0x419c80,   1, 0x04, 0x00020230 },
+	{ 0x419ccc,   2, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct nvc0_graph_init
+gk110b_graph_init_sm_0[] = {
+	{ 0x419e00,   1, 0x04, 0x00000080 },
+	{ 0x419ea0,   1, 0x04, 0x00000000 },
+	{ 0x419ee4,   1, 0x04, 0x00000000 },
+	{ 0x419ea4,   1, 0x04, 0x00000100 },
+	{ 0x419ea8,   1, 0x04, 0x00000000 },
+	{ 0x419eb4,   1, 0x04, 0x00000000 },
+	{ 0x419ebc,   2, 0x04, 0x00000000 },
+	{ 0x419edc,   1, 0x04, 0x00000000 },
+	{ 0x419f00,   1, 0x04, 0x00000000 },
+	{ 0x419ed0,   1, 0x04, 0x00002616 },
+	{ 0x419f74,   1, 0x04, 0x00015555 },
+	{ 0x419f80,   4, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct nvc0_graph_pack
+gk110b_graph_pack_mmio[] = {
+	{ nve4_graph_init_main_0 },
+	{ nvf0_graph_init_fe_0 },
+	{ nvc0_graph_init_pri_0 },
+	{ nvc0_graph_init_rstr2d_0 },
+	{ nvd9_graph_init_pd_0 },
+	{ nvf0_graph_init_ds_0 },
+	{ nvc0_graph_init_scc_0 },
+	{ nvf0_graph_init_sked_0 },
+	{ nvf0_graph_init_cwd_0 },
+	{ nvd9_graph_init_prop_0 },
+	{ nvc1_graph_init_gpc_unk_0 },
+	{ nvc0_graph_init_setup_0 },
+	{ nvc0_graph_init_crstr_0 },
+	{ nvc1_graph_init_setup_1 },
+	{ nvc0_graph_init_zcull_0 },
+	{ nvd9_graph_init_gpm_0 },
+	{ nvf0_graph_init_gpc_unk_1 },
+	{ nvc0_graph_init_gcc_0 },
+	{ nve4_graph_init_tpccs_0 },
+	{ nvf0_graph_init_tex_0 },
+	{ nve4_graph_init_pe_0 },
+	{ gk110b_graph_init_l1c_0 },
+	{ nvc0_graph_init_mpc_0 },
+	{ gk110b_graph_init_sm_0 },
+	{ nvd7_graph_init_pes_0 },
+	{ nvd7_graph_init_wwdx_0 },
+	{ nvd7_graph_init_cbm_0 },
+	{ nve4_graph_init_be_0 },
+	{ nvc0_graph_init_fe_1 },
+	{}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+struct nouveau_oclass *
+gk110b_graph_oclass = &(struct nvc0_graph_oclass) {
+	.base.handle = NV_ENGINE(GR, 0xf1),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nvc0_graph_ctor,
+		.dtor = nvc0_graph_dtor,
+		.init = nve4_graph_init,
+		.fini = nvf0_graph_fini,
+	},
+	.cclass = &gk110b_grctx_oclass,
+	.sclass =  nvf0_graph_sclass,
+	.mmio = gk110b_graph_pack_mmio,
+	.fecs.ucode = &nvf0_graph_fecs_ucode,
+	.gpccs.ucode = &nvf0_graph_gpccs_ucode,
+	.ppc_nr = 2,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,8 +27,8 @@ static struct nouveau_oclass
 gk20a_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0xa040, &nouveau_object_ofuncs },
-	{ 0xa297, &nouveau_object_ofuncs },
-	{ 0xa0c0, &nouveau_object_ofuncs },
+	{ KEPLER_C, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ KEPLER_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
@@ -39,9 +39,10 @@ gk20a_graph_oclass = &(struct nvc0_graph
 		.ctor = nvc0_graph_ctor,
 		.dtor = nvc0_graph_dtor,
 		.init = nve4_graph_init,
-		.fini = nve4_graph_fini,
+		.fini = _nouveau_graph_fini,
 	},
 	.cclass = &gk20a_grctx_oclass,
 	.sclass = gk20a_graph_sclass,
 	.mmio = nve4_graph_pack_mmio,
+	.ppc_nr = 1,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,8 @@ static struct nouveau_oclass
 gm107_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0xa140, &nouveau_object_ofuncs },
-	{ 0xb097, &nouveau_object_ofuncs },
-	{ 0xb0c0, &nouveau_object_ofuncs },
+	{ MAXWELL_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ MAXWELL_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
@@ -425,6 +425,9 @@ gm107_graph_init(struct nouveau_object *
 	nv_wr32(priv, 0x400134, 0xffffffff);
 
 	nv_wr32(priv, 0x400054, 0x2c350f63);
+
+	nvc0_graph_zbc_init(priv);
+
 	return nvc0_graph_init_ctxctl(priv);
 }
 
@@ -462,4 +465,5 @@ gm107_graph_oclass = &(struct nvc0_graph
 	.mmio = gm107_graph_pack_mmio,
 	.fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL,
 	.gpccs.ucode = &gm107_graph_gpccs_ucode,
+	.ppc_nr = 2,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 
 #include <core/client.h>
 #include <core/os.h>
-#include <core/class.h>
 #include <core/handle.h>
 #include <core/namedb.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@ static struct nouveau_oclass
 nv108_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0xa140, &nouveau_object_ofuncs },
-	{ 0xa197, &nouveau_object_ofuncs },
+	{ KEPLER_B, &nvc0_fermi_ofuncs },
 	{ 0xa1c0, &nouveau_object_ofuncs },
 	{}
 };
@@ -220,4 +220,5 @@ nv108_graph_oclass = &(struct nvc0_graph
 	.mmio = nv108_graph_pack_mmio,
 	.fecs.ucode = &nv108_graph_fecs_ucode,
 	.gpccs.ucode = &nv108_graph_gpccs_ucode,
+	.ppc_nr = 1,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 
 #include <core/client.h>
 #include <core/os.h>
-#include <core/class.h>
 #include <core/handle.h>
 
 #include <subdev/fb.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,5 @@
 #include <core/client.h>
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/handle.h>
 #include <core/enum.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/enum.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/enum.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/enum.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/enum.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/enum.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 
 #include <core/client.h>
 #include <core/os.h>
-#include <core/class.h>
 #include <core/handle.h>
 #include <core/engctx.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/client.h>
 #include <core/handle.h>
 #include <core/engctx.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c	2014-08-07 04:45:50.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c	2014-09-28 21:26:30.000000000 -0400
@@ -26,15 +26,232 @@
 #include "ctxnvc0.h"
 
 /*******************************************************************************
+ * Zero Bandwidth Clear
+ ******************************************************************************/
+
+static void
+nvc0_graph_zbc_clear_color(struct nvc0_graph_priv *priv, int zbc)
+{
+	if (priv->zbc_color[zbc].format) {
+		nv_wr32(priv, 0x405804, priv->zbc_color[zbc].ds[0]);
+		nv_wr32(priv, 0x405808, priv->zbc_color[zbc].ds[1]);
+		nv_wr32(priv, 0x40580c, priv->zbc_color[zbc].ds[2]);
+		nv_wr32(priv, 0x405810, priv->zbc_color[zbc].ds[3]);
+	}
+	nv_wr32(priv, 0x405814, priv->zbc_color[zbc].format);
+	nv_wr32(priv, 0x405820, zbc);
+	nv_wr32(priv, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
+}
+
+static int
+nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format,
+			 const u32 ds[4], const u32 l2[4])
+{
+	struct nouveau_ltc *ltc = nouveau_ltc(priv);
+	int zbc = -ENOSPC, i;
+
+	for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+		if (priv->zbc_color[i].format) {
+			if (priv->zbc_color[i].format != format)
+				continue;
+			if (memcmp(priv->zbc_color[i].ds, ds, sizeof(
+				   priv->zbc_color[i].ds)))
+				continue;
+			if (memcmp(priv->zbc_color[i].l2, l2, sizeof(
+				   priv->zbc_color[i].l2))) {
+				WARN_ON(1);
+				return -EINVAL;
+			}
+			return i;
+		} else {
+			zbc = (zbc < 0) ? i : zbc;
+		}
+	}
+
+	if (zbc < 0)
+		return zbc;
+
+	memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds));
+	memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2));
+	priv->zbc_color[zbc].format = format;
+	ltc->zbc_color_get(ltc, zbc, l2);
+	nvc0_graph_zbc_clear_color(priv, zbc);
+	return zbc;
+}
+
+static void
+nvc0_graph_zbc_clear_depth(struct nvc0_graph_priv *priv, int zbc)
+{
+	if (priv->zbc_depth[zbc].format)
+		nv_wr32(priv, 0x405818, priv->zbc_depth[zbc].ds);
+	nv_wr32(priv, 0x40581c, priv->zbc_depth[zbc].format);
+	nv_wr32(priv, 0x405820, zbc);
+	nv_wr32(priv, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
+}
+
+static int
+nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format,
+			 const u32 ds, const u32 l2)
+{
+	struct nouveau_ltc *ltc = nouveau_ltc(priv);
+	int zbc = -ENOSPC, i;
+
+	for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+		if (priv->zbc_depth[i].format) {
+			if (priv->zbc_depth[i].format != format)
+				continue;
+			if (priv->zbc_depth[i].ds != ds)
+				continue;
+			if (priv->zbc_depth[i].l2 != l2) {
+				WARN_ON(1);
+				return -EINVAL;
+			}
+			return i;
+		} else {
+			zbc = (zbc < 0) ? i : zbc;
+		}
+	}
+
+	if (zbc < 0)
+		return zbc;
+
+	priv->zbc_depth[zbc].format = format;
+	priv->zbc_depth[zbc].ds = ds;
+	priv->zbc_depth[zbc].l2 = l2;
+	ltc->zbc_depth_get(ltc, zbc, l2);
+	nvc0_graph_zbc_clear_depth(priv, zbc);
+	return zbc;
+}
+
+/*******************************************************************************
  * Graphics object classes
  ******************************************************************************/
 
+static int
+nvc0_fermi_mthd_zbc_color(struct nouveau_object *object, void *data, u32 size)
+{
+	struct nvc0_graph_priv *priv = (void *)object->engine;
+	union {
+		struct fermi_a_zbc_color_v0 v0;
+	} *args = data;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		switch (args->v0.format) {
+		case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
+		case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
+		case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
+		case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
+		case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
+		case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
+		case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
+		case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
+		case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
+		case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
+		case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
+			ret = nvc0_graph_zbc_color_get(priv, args->v0.format,
+							     args->v0.ds,
+							     args->v0.l2);
+			if (ret >= 0) {
+				args->v0.index = ret;
+				return 0;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvc0_fermi_mthd_zbc_depth(struct nouveau_object *object, void *data, u32 size)
+{
+	struct nvc0_graph_priv *priv = (void *)object->engine;
+	union {
+		struct fermi_a_zbc_depth_v0 v0;
+	} *args = data;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		switch (args->v0.format) {
+		case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
+			ret = nvc0_graph_zbc_depth_get(priv, args->v0.format,
+							     args->v0.ds,
+							     args->v0.l2);
+			return (ret >= 0) ? 0 : -ENOSPC;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+nvc0_fermi_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+	switch (mthd) {
+	case FERMI_A_ZBC_COLOR:
+		return nvc0_fermi_mthd_zbc_color(object, data, size);
+	case FERMI_A_ZBC_DEPTH:
+		return nvc0_fermi_mthd_zbc_depth(object, data, size);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+struct nouveau_ofuncs
+nvc0_fermi_ofuncs = {
+	.ctor = _nouveau_object_ctor,
+	.dtor = nouveau_object_destroy,
+	.init = nouveau_object_init,
+	.fini = nouveau_object_fini,
+	.mthd = nvc0_fermi_mthd,
+};
+
+static int
+nvc0_graph_set_shader_exceptions(struct nouveau_object *object, u32 mthd,
+				 void *pdata, u32 size)
+{
+	struct nvc0_graph_priv *priv = (void *)nv_engine(object);
+	if (size >= sizeof(u32)) {
+		u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
+		nv_wr32(priv, 0x419e44, data);
+		nv_wr32(priv, 0x419e4c, data);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct nouveau_omthds
+nvc0_graph_9097_omthds[] = {
+	{ 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
+	{}
+};
+
+struct nouveau_omthds
+nvc0_graph_90c0_omthds[] = {
+	{ 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
+	{}
+};
+
 struct nouveau_oclass
 nvc0_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0x9039, &nouveau_object_ofuncs },
-	{ 0x9097, &nouveau_object_ofuncs },
-	{ 0x90c0, &nouveau_object_ofuncs },
+	{ FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
@@ -98,7 +315,7 @@ nvc0_graph_context_ctor(struct nouveau_o
 		u32 addr = mmio->addr;
 		u32 data = mmio->data;
 
-		if (mmio->shift) {
+		if (mmio->buffer >= 0) {
 			u64 info = chan->data[mmio->buffer].vma.offset;
 			data |= info >> mmio->shift;
 		}
@@ -407,6 +624,35 @@ nvc0_graph_pack_mmio[] = {
  ******************************************************************************/
 
 void
+nvc0_graph_zbc_init(struct nvc0_graph_priv *priv)
+{
+	const u32  zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+			      0x00000000, 0x00000000, 0x00000000, 0x00000000 };
+	const u32   one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+			      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+	const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+			      0x00000000, 0x00000000, 0x00000000, 0x00000000 };
+	const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+			      0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
+	struct nouveau_ltc *ltc = nouveau_ltc(priv);
+	int index;
+
+	if (!priv->zbc_color[0].format) {
+		nvc0_graph_zbc_color_get(priv, 1,  & zero[0],   &zero[4]);
+		nvc0_graph_zbc_color_get(priv, 2,  &  one[0],    &one[4]);
+		nvc0_graph_zbc_color_get(priv, 4,  &f32_0[0],  &f32_0[4]);
+		nvc0_graph_zbc_color_get(priv, 4,  &f32_1[0],  &f32_1[4]);
+		nvc0_graph_zbc_depth_get(priv, 1, 0x00000000, 0x00000000);
+		nvc0_graph_zbc_depth_get(priv, 1, 0x3f800000, 0x3f800000);
+	}
+
+	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
+		nvc0_graph_zbc_clear_color(priv, index);
+	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
+		nvc0_graph_zbc_clear_depth(priv, index);
+}
+
+void
 nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
 {
 	const struct nvc0_graph_pack *pack;
@@ -969,17 +1215,16 @@ nvc0_graph_init_ctxctl(struct nvc0_graph
 {
 	struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
 	struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
-	u32 r000260;
 	int i;
 
 	if (priv->firmware) {
 		/* load fuc microcode */
-		r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+		nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
 		nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c,
 						   &priv->fuc409d);
 		nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac,
 						   &priv->fuc41ad);
-		nv_wr32(priv, 0x000260, r000260);
+		nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
 
 		/* start both of them running */
 		nv_wr32(priv, 0x409840, 0xffffffff);
@@ -1066,7 +1311,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph
 	}
 
 	/* load HUB microcode */
-	r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
 	nv_wr32(priv, 0x4091c0, 0x01000000);
 	for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
 		nv_wr32(priv, 0x4091c4, oclass->fecs.ucode->data.data[i]);
@@ -1089,7 +1334,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph
 			nv_wr32(priv, 0x41a188, i >> 6);
 		nv_wr32(priv, 0x41a184, oclass->gpccs.ucode->code.data[i]);
 	}
-	nv_wr32(priv, 0x000260, r000260);
+	nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
 
 	/* load register lists */
 	nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
@@ -1224,6 +1469,9 @@ nvc0_graph_init(struct nouveau_object *o
 	nv_wr32(priv, 0x400134, 0xffffffff);
 
 	nv_wr32(priv, 0x400054, 0x34ce3464);
+
+	nvc0_graph_zbc_init(priv);
+
 	return nvc0_graph_init_ctxctl(priv);
 }
 
@@ -1287,7 +1535,7 @@ nvc0_graph_ctor(struct nouveau_object *p
 	struct nouveau_device *device = nv_device(parent);
 	struct nvc0_graph_priv *priv;
 	bool use_ext_fw, enable;
-	int ret, i;
+	int ret, i, j;
 
 	use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
 				     oclass->fecs.ucode == NULL);
@@ -1333,6 +1581,11 @@ nvc0_graph_ctor(struct nouveau_object *p
 	for (i = 0; i < priv->gpc_nr; i++) {
 		priv->tpc_nr[i]  = nv_rd32(priv, GPC_UNIT(i, 0x2608));
 		priv->tpc_total += priv->tpc_nr[i];
+		priv->ppc_nr[i]  = oclass->ppc_nr;
+		for (j = 0; j < priv->ppc_nr[i]; j++) {
+			u8 mask = nv_rd32(priv, GPC_UNIT(i, 0x0c30 + (j * 4)));
+			priv->ppc_tpc_nr[i][j] = hweight8(mask);
+		}
 	}
 
 	/*XXX: these need figuring out... though it might not even matter */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,10 +30,15 @@
 #include <core/gpuobj.h>
 #include <core/option.h>
 
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 #include <subdev/bar.h>
 #include <subdev/timer.h>
+#include <subdev/mc.h>
+#include <subdev/ltc.h>
 
 #include <engine/fifo.h>
 #include <engine/graph.h>
@@ -60,7 +65,7 @@ struct nvc0_graph_mmio {
 	u32 addr;
 	u32 data;
 	u32 shift;
-	u32 buffer;
+	int buffer;
 };
 
 struct nvc0_graph_fuc {
@@ -68,6 +73,18 @@ struct nvc0_graph_fuc {
 	u32  size;
 };
 
+struct nvc0_graph_zbc_color {
+	u32 format;
+	u32 ds[4];
+	u32 l2[4];
+};
+
+struct nvc0_graph_zbc_depth {
+	u32 format;
+	u32 ds;
+	u32 l2;
+};
+
 struct nvc0_graph_priv {
 	struct nouveau_graph base;
 
@@ -77,10 +94,15 @@ struct nvc0_graph_priv {
 	struct nvc0_graph_fuc fuc41ad;
 	bool firmware;
 
+	struct nvc0_graph_zbc_color zbc_color[NOUVEAU_LTC_MAX_ZBC_CNT];
+	struct nvc0_graph_zbc_depth zbc_depth[NOUVEAU_LTC_MAX_ZBC_CNT];
+
 	u8 rop_nr;
 	u8 gpc_nr;
 	u8 tpc_nr[GPC_MAX];
 	u8 tpc_total;
+	u8 ppc_nr[GPC_MAX];
+	u8 ppc_tpc_nr[GPC_MAX][4];
 
 	struct nouveau_gpuobj *unk4188b4;
 	struct nouveau_gpuobj *unk4188b8;
@@ -118,12 +140,20 @@ int  nvc0_graph_ctor(struct nouveau_obje
 		     struct nouveau_object **);
 void nvc0_graph_dtor(struct nouveau_object *);
 int  nvc0_graph_init(struct nouveau_object *);
+void nvc0_graph_zbc_init(struct nvc0_graph_priv *);
+
 int  nve4_graph_fini(struct nouveau_object *, bool);
 int  nve4_graph_init(struct nouveau_object *);
 
-extern struct nouveau_oclass nvc0_graph_sclass[];
+int  nvf0_graph_fini(struct nouveau_object *, bool);
+
+extern struct nouveau_ofuncs nvc0_fermi_ofuncs;
 
+extern struct nouveau_oclass nvc0_graph_sclass[];
+extern struct nouveau_omthds nvc0_graph_9097_omthds[];
+extern struct nouveau_omthds nvc0_graph_90c0_omthds[];
 extern struct nouveau_oclass nvc8_graph_sclass[];
+extern struct nouveau_oclass nvf0_graph_sclass[];
 
 struct nvc0_graph_init {
 	u32 addr;
@@ -149,6 +179,9 @@ struct nvc0_graph_ucode {
 extern struct nvc0_graph_ucode nvc0_graph_fecs_ucode;
 extern struct nvc0_graph_ucode nvc0_graph_gpccs_ucode;
 
+extern struct nvc0_graph_ucode nvf0_graph_fecs_ucode;
+extern struct nvc0_graph_ucode nvf0_graph_gpccs_ucode;
+
 struct nvc0_graph_oclass {
 	struct nouveau_oclass base;
 	struct nouveau_oclass **cclass;
@@ -160,6 +193,7 @@ struct nvc0_graph_oclass {
 	struct {
 		struct nvc0_graph_ucode *ucode;
 	} gpccs;
+	int ppc_nr;
 };
 
 void nvc0_graph_mmio(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
@@ -223,9 +257,11 @@ extern const struct nvc0_graph_init nve4
 extern const struct nvc0_graph_pack nve4_graph_pack_mmio[];
 
 extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
+extern const struct nvc0_graph_init nvf0_graph_init_ds_0[];
 extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
 extern const struct nvc0_graph_init nvf0_graph_init_cwd_0[];
 extern const struct nvc0_graph_init nvf0_graph_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvf0_graph_init_tex_0[];
 extern const struct nvc0_graph_init nvf0_graph_init_sm_0[];
 
 extern const struct nvc0_graph_init nv108_graph_init_gpc_unk_0[];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,9 +33,9 @@ static struct nouveau_oclass
 nvc1_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0x9039, &nouveau_object_ofuncs },
-	{ 0x9097, &nouveau_object_ofuncs },
-	{ 0x90c0, &nouveau_object_ofuncs },
-	{ 0x9197, &nouveau_object_ofuncs },
+	{ FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,10 +33,10 @@ struct nouveau_oclass
 nvc8_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0x9039, &nouveau_object_ofuncs },
-	{ 0x9097, &nouveau_object_ofuncs },
-	{ 0x90c0, &nouveau_object_ofuncs },
-	{ 0x9197, &nouveau_object_ofuncs },
-	{ 0x9297, &nouveau_object_ofuncs },
+	{ FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_C, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c	2014-09-28 17:29:07.000000000 -0400
@@ -133,4 +133,5 @@ nvd7_graph_oclass = &(struct nvc0_graph_
 	.mmio = nvd7_graph_pack_mmio,
 	.fecs.ucode = &nvd7_graph_fecs_ucode,
 	.gpccs.ucode = &nvd7_graph_gpccs_ucode,
+	.ppc_nr = 1,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
+#include <subdev/pwr.h>
+
 #include "nvc0.h"
 #include "ctxnvc0.h"
 
@@ -33,8 +35,8 @@ static struct nouveau_oclass
 nve4_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0xa040, &nouveau_object_ofuncs },
-	{ 0xa097, &nouveau_object_ofuncs },
-	{ 0xa0c0, &nouveau_object_ofuncs },
+	{ KEPLER_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ KEPLER_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
@@ -190,39 +192,20 @@ nve4_graph_pack_mmio[] = {
  ******************************************************************************/
 
 int
-nve4_graph_fini(struct nouveau_object *object, bool suspend)
-{
-	struct nvc0_graph_priv *priv = (void *)object;
-
-	/*XXX: this is a nasty hack to power on gr on certain boards
-	 *     where it's disabled by therm, somehow.  ideally it'd
-	 *     be nice to know when we should be doing this, and why,
-	 *     but, it's yet to be determined.  for now we test for
-	 *     the particular mmio error that occurs in the situation,
-	 *     and then bash therm in the way nvidia do.
-	 */
-	nv_mask(priv, 0x000200, 0x08001000, 0x08001000);
-	nv_rd32(priv, 0x000200);
-	if (nv_rd32(priv, 0x400700) == 0xbadf1000) {
-		nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
-		nv_rd32(priv, 0x000200);
-		nv_mask(priv, 0x020004, 0xc0000000, 0x40000000);
-	}
-
-	return nouveau_graph_fini(&priv->base, suspend);
-}
-
-int
 nve4_graph_init(struct nouveau_object *object)
 {
 	struct nvc0_graph_oclass *oclass = (void *)object->oclass;
 	struct nvc0_graph_priv *priv = (void *)object;
+	struct nouveau_pwr *ppwr = nouveau_pwr(priv);
 	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
 	u32 data[TPC_MAX / 8] = {};
 	u8  tpcnr[GPC_MAX];
 	int gpc, tpc, rop;
 	int ret, i;
 
+	if (ppwr)
+		ppwr->pgob(ppwr, false);
+
 	ret = nouveau_graph_init(&priv->base);
 	if (ret)
 		return ret;
@@ -320,6 +303,9 @@ nve4_graph_init(struct nouveau_object *o
 	nv_wr32(priv, 0x400134, 0xffffffff);
 
 	nv_wr32(priv, 0x400054, 0x34ce3464);
+
+	nvc0_graph_zbc_init(priv);
+
 	return nvc0_graph_init_ctxctl(priv);
 }
 
@@ -350,11 +336,12 @@ nve4_graph_oclass = &(struct nvc0_graph_
 		.ctor = nvc0_graph_ctor,
 		.dtor = nvc0_graph_dtor,
 		.init = nve4_graph_init,
-		.fini = nve4_graph_fini,
+		.fini = _nouveau_graph_fini,
 	},
 	.cclass = &nve4_grctx_oclass,
 	.sclass = nve4_graph_sclass,
 	.mmio = nve4_graph_pack_mmio,
 	.fecs.ucode = &nve4_graph_fecs_ucode,
 	.gpccs.ucode = &nve4_graph_gpccs_ucode,
+	.ppc_nr = 1,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,12 +29,12 @@
  * Graphics object classes
  ******************************************************************************/
 
-static struct nouveau_oclass
+struct nouveau_oclass
 nvf0_graph_sclass[] = {
 	{ 0x902d, &nouveau_object_ofuncs },
 	{ 0xa140, &nouveau_object_ofuncs },
-	{ 0xa197, &nouveau_object_ofuncs },
-	{ 0xa1c0, &nouveau_object_ofuncs },
+	{ KEPLER_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+	{ KEPLER_COMPUTE_B, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
 	{}
 };
 
@@ -50,7 +50,7 @@ nvf0_graph_init_fe_0[] = {
 	{}
 };
 
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
 nvf0_graph_init_ds_0[] = {
 	{ 0x405844,   1, 0x04, 0x00ffffff },
 	{ 0x405850,   1, 0x04, 0x00000000 },
@@ -88,7 +88,7 @@ nvf0_graph_init_gpc_unk_1[] = {
 	{}
 };
 
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
 nvf0_graph_init_tex_0[] = {
 	{ 0x419ab0,   1, 0x04, 0x00000000 },
 	{ 0x419ac8,   1, 0x04, 0x00000000 },
@@ -170,7 +170,7 @@ nvf0_graph_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static int
+int
 nvf0_graph_fini(struct nouveau_object *object, bool suspend)
 {
 	struct nvc0_graph_priv *priv = (void *)object;
@@ -209,7 +209,7 @@ nvf0_graph_fini(struct nouveau_object *o
 
 #include "fuc/hubnvf0.fuc.h"
 
-static struct nvc0_graph_ucode
+struct nvc0_graph_ucode
 nvf0_graph_fecs_ucode = {
 	.code.data = nvf0_grhub_code,
 	.code.size = sizeof(nvf0_grhub_code),
@@ -219,7 +219,7 @@ nvf0_graph_fecs_ucode = {
 
 #include "fuc/gpcnvf0.fuc.h"
 
-static struct nvc0_graph_ucode
+struct nvc0_graph_ucode
 nvf0_graph_gpccs_ucode = {
 	.code.data = nvf0_grgpc_code,
 	.code.size = sizeof(nvf0_grgpc_code),
@@ -241,4 +241,5 @@ nvf0_graph_oclass = &(struct nvc0_graph_
 	.mmio = nvf0_graph_pack_mmio,
 	.fecs.ucode = &nvf0_graph_fecs_ucode,
 	.gpccs.ucode = &nvf0_graph_gpccs_ucode,
+	.ppc_nr = 2,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 
 #include <core/client.h>
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/handle.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <subdev/fb.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/client.h>
 #include <core/engctx.h>
 #include <core/handle.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <subdev/vm.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <subdev/vm.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,11 @@
  * Authors: Ben Skeggs
  */
 
+#include <core/client.h>
 #include <core/option.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
 
 #include <subdev/clock.h>
 
@@ -101,24 +104,28 @@ nouveau_perfsig_wrap(struct nouveau_perf
  * Perfmon object classes
  ******************************************************************************/
 static int
-nouveau_perfctr_query(struct nouveau_object *object, u32 mthd,
-		      void *data, u32 size)
+nouveau_perfctr_query(struct nouveau_object *object, void *data, u32 size)
 {
+	union {
+		struct nvif_perfctr_query_v0 v0;
+	} *args = data;
 	struct nouveau_device *device = nv_device(object);
 	struct nouveau_perfmon *ppm = (void *)object->engine;
 	struct nouveau_perfdom *dom = NULL, *chk;
-	struct nv_perfctr_query *args = data;
 	const bool all = nouveau_boolopt(device->cfgopt, "NvPmShowAll", false);
 	const bool raw = nouveau_boolopt(device->cfgopt, "NvPmUnnamed", all);
 	const char *name;
 	int tmp = 0, di, si;
-	char path[64];
-
-	if (size < sizeof(*args))
-		return -EINVAL;
+	int ret;
 
-	di = (args->iter & 0xff000000) >> 24;
-	si = (args->iter & 0x00ffffff) - 1;
+	nv_ioctl(object, "perfctr query size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "perfctr query vers %d iter %08x\n",
+			 args->v0.version, args->v0.iter);
+		di = (args->v0.iter & 0xff000000) >> 24;
+		si = (args->v0.iter & 0x00ffffff) - 1;
+	} else
+		return ret;
 
 	list_for_each_entry(chk, &ppm->domains, head) {
 		if (tmp++ == di) {
@@ -132,19 +139,17 @@ nouveau_perfctr_query(struct nouveau_obj
 
 	if (si >= 0) {
 		if (raw || !(name = dom->signal[si].name)) {
-			snprintf(path, sizeof(path), "/%s/%02x", dom->name, si);
-			name = path;
+			snprintf(args->v0.name, sizeof(args->v0.name),
+				 "/%s/%02x", dom->name, si);
+		} else {
+			strncpy(args->v0.name, name, sizeof(args->v0.name));
 		}
-
-		if (args->name)
-			strncpy(args->name, name, args->size);
-		args->size = strlen(name) + 1;
 	}
 
 	do {
 		while (++si < dom->signal_nr) {
 			if (all || dom->signal[si].name) {
-				args->iter = (di << 24) | ++si;
+				args->v0.iter = (di << 24) | ++si;
 				return 0;
 			}
 		}
@@ -153,21 +158,26 @@ nouveau_perfctr_query(struct nouveau_obj
 		dom = list_entry(dom->head.next, typeof(*dom), head);
 	} while (&dom->head != &ppm->domains);
 
-	args->iter = 0xffffffff;
+	args->v0.iter = 0xffffffff;
 	return 0;
 }
 
 static int
-nouveau_perfctr_sample(struct nouveau_object *object, u32 mthd,
-		       void *data, u32 size)
+nouveau_perfctr_sample(struct nouveau_object *object, void *data, u32 size)
 {
+	union {
+		struct nvif_perfctr_sample none;
+	} *args = data;
 	struct nouveau_perfmon *ppm = (void *)object->engine;
 	struct nouveau_perfctr *ctr, *tmp;
 	struct nouveau_perfdom *dom;
-	struct nv_perfctr_sample *args = data;
+	int ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(object, "perfctr sample size %d\n", size);
+	if (nvif_unvers(args->none)) {
+		nv_ioctl(object, "perfctr sample\n");
+	} else
+		return ret;
 	ppm->sequence++;
 
 	list_for_each_entry(dom, &ppm->domains, head) {
@@ -206,22 +216,45 @@ nouveau_perfctr_sample(struct nouveau_ob
 }
 
 static int
-nouveau_perfctr_read(struct nouveau_object *object, u32 mthd,
-		     void *data, u32 size)
+nouveau_perfctr_read(struct nouveau_object *object, void *data, u32 size)
 {
+	union {
+		struct nvif_perfctr_read_v0 v0;
+	} *args = data;
 	struct nouveau_perfctr *ctr = (void *)object;
-	struct nv_perfctr_read *args = data;
+	int ret;
+
+	nv_ioctl(object, "perfctr read size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(object, "perfctr read vers %d\n", args->v0.version);
+	} else
+		return ret;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
 	if (!ctr->clk)
 		return -EAGAIN;
 
-	args->clk = ctr->clk;
-	args->ctr = ctr->ctr;
+	args->v0.clk = ctr->clk;
+	args->v0.ctr = ctr->ctr;
 	return 0;
 }
 
+static int
+nouveau_perfctr_mthd(struct nouveau_object *object, u32 mthd,
+		     void *data, u32 size)
+{
+	switch (mthd) {
+	case NVIF_PERFCTR_V0_QUERY:
+		return nouveau_perfctr_query(object, data, size);
+	case NVIF_PERFCTR_V0_SAMPLE:
+		return nouveau_perfctr_sample(object, data, size);
+	case NVIF_PERFCTR_V0_READ:
+		return nouveau_perfctr_read(object, data, size);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
 static void
 nouveau_perfctr_dtor(struct nouveau_object *object)
 {
@@ -237,19 +270,27 @@ nouveau_perfctr_ctor(struct nouveau_obje
 		     struct nouveau_oclass *oclass, void *data, u32 size,
 		     struct nouveau_object **pobject)
 {
+	union {
+		struct nvif_perfctr_v0 v0;
+	} *args = data;
 	struct nouveau_perfmon *ppm = (void *)engine;
 	struct nouveau_perfdom *dom = NULL;
 	struct nouveau_perfsig *sig[4] = {};
 	struct nouveau_perfctr *ctr;
-	struct nv_perfctr_class *args = data;
 	int ret, i;
 
-	if (size < sizeof(*args))
-		return -EINVAL;
+	nv_ioctl(parent, "create perfctr size %d\n", size);
+	if (nvif_unpack(args->v0, 0, 0, false)) {
+		nv_ioctl(parent, "create perfctr vers %d logic_op %04x\n",
+			 args->v0.version, args->v0.logic_op);
+	} else
+		return ret;
 
-	for (i = 0; i < ARRAY_SIZE(args->signal) && args->signal[i].name; i++) {
-		sig[i] = nouveau_perfsig_find(ppm, args->signal[i].name,
-					      args->signal[i].size, &dom);
+	for (i = 0; i < ARRAY_SIZE(args->v0.name) && args->v0.name[i][0]; i++) {
+		sig[i] = nouveau_perfsig_find(ppm, args->v0.name[i],
+					      strnlen(args->v0.name[i],
+					      sizeof(args->v0.name[i])),
+					      &dom);
 		if (!sig[i])
 			return -EINVAL;
 	}
@@ -260,7 +301,7 @@ nouveau_perfctr_ctor(struct nouveau_obje
 		return ret;
 
 	ctr->slot = -1;
-	ctr->logic_op = args->logic_op;
+	ctr->logic_op = args->v0.logic_op;
 	ctr->signal[0] = sig[0];
 	ctr->signal[1] = sig[1];
 	ctr->signal[2] = sig[2];
@@ -276,21 +317,13 @@ nouveau_perfctr_ofuncs = {
 	.dtor = nouveau_perfctr_dtor,
 	.init = nouveau_object_init,
 	.fini = nouveau_object_fini,
-};
-
-static struct nouveau_omthds
-nouveau_perfctr_omthds[] = {
-	{ NV_PERFCTR_QUERY, NV_PERFCTR_QUERY, nouveau_perfctr_query },
-	{ NV_PERFCTR_SAMPLE, NV_PERFCTR_SAMPLE, nouveau_perfctr_sample },
-	{ NV_PERFCTR_READ, NV_PERFCTR_READ, nouveau_perfctr_read },
-	{}
+	.mthd = nouveau_perfctr_mthd,
 };
 
 struct nouveau_oclass
 nouveau_perfmon_sclass[] = {
-	{ .handle = NV_PERFCTR_CLASS,
+	{ .handle = NVIF_IOCTL_NEW_V0_PERFCTR,
 	  .ofuncs = &nouveau_perfctr_ofuncs,
-	  .omthds =  nouveau_perfctr_omthds,
 	},
 	{},
 };
@@ -303,6 +336,7 @@ nouveau_perfctx_dtor(struct nouveau_obje
 {
 	struct nouveau_perfmon *ppm = (void *)object->engine;
 	mutex_lock(&nv_subdev(ppm)->mutex);
+	nouveau_engctx_destroy(&ppm->context->base);
 	ppm->context = NULL;
 	mutex_unlock(&nv_subdev(ppm)->mutex);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <engine/software.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv10.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv10.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv10.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 
 #include <engine/software.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,12 +23,12 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/namedb.h>
 #include <core/handle.h>
 #include <core/gpuobj.h>
 #include <core/event.h>
+#include <nvif/event.h>
 
 #include <subdev/bar.h>
 
@@ -86,10 +86,10 @@ nv50_software_mthd_vblsem_release(struct
 {
 	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
 	u32 head = *(u32 *)args;
-	if (head >= chan->vblank.nr_event)
+	if (head >= nouveau_disp(chan)->vblank.index_nr)
 		return -EINVAL;
 
-	nouveau_event_get(chan->vblank.event[head]);
+	nvkm_notify_get(&chan->vblank.notify[head]);
 	return 0;
 }
 
@@ -124,9 +124,10 @@ nv50_software_sclass[] = {
  ******************************************************************************/
 
 static int
-nv50_software_vblsem_release(void *data, u32 type, int head)
+nv50_software_vblsem_release(struct nvkm_notify *notify)
 {
-	struct nv50_software_chan *chan = data;
+	struct nv50_software_chan *chan =
+		container_of(notify, typeof(*chan), vblank.notify[notify->index]);
 	struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
 	struct nouveau_bar *bar = nouveau_bar(priv);
 
@@ -142,7 +143,7 @@ nv50_software_vblsem_release(void *data,
 		nv_wr32(priv, 0x060014, chan->vblank.value);
 	}
 
-	return NVKM_EVENT_DROP;
+	return NVKM_NOTIFY_DROP;
 }
 
 void
@@ -151,11 +152,8 @@ nv50_software_context_dtor(struct nouvea
 	struct nv50_software_chan *chan = (void *)object;
 	int i;
 
-	if (chan->vblank.event) {
-		for (i = 0; i < chan->vblank.nr_event; i++)
-			nouveau_event_ref(NULL, &chan->vblank.event[i]);
-		kfree(chan->vblank.event);
-	}
+	for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++)
+		nvkm_notify_fini(&chan->vblank.notify[i]);
 
 	nouveau_software_context_destroy(&chan->base);
 }
@@ -176,15 +174,14 @@ nv50_software_context_ctor(struct nouvea
 	if (ret)
 		return ret;
 
-	chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0;
-	chan->vblank.event = kzalloc(chan->vblank.nr_event *
-				     sizeof(*chan->vblank.event), GFP_KERNEL);
-	if (!chan->vblank.event)
-		return -ENOMEM;
-
-	for (i = 0; i < chan->vblank.nr_event; i++) {
-		ret = nouveau_event_new(pdisp->vblank, 1, i, pclass->vblank,
-					chan, &chan->vblank.event[i]);
+	for (i = 0; pdisp && i < pdisp->vblank.index_nr; i++) {
+		ret = nvkm_notify_init(&pdisp->vblank, pclass->vblank, false,
+				       &(struct nvif_notify_head_req_v0) {
+					.head = i,
+				       },
+				       sizeof(struct nvif_notify_head_req_v0),
+				       sizeof(struct nvif_notify_head_rep_v0),
+				       &chan->vblank.notify[i]);
 		if (ret)
 			return ret;
 	}
@@ -198,7 +195,7 @@ nv50_software_cclass = {
 	.base.handle = NV_ENGCTX(SW, 0x50),
 	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv50_software_context_ctor,
-		.dtor = _nouveau_software_context_dtor,
+		.dtor = nv50_software_context_dtor,
 		.init = _nouveau_software_context_init,
 		.fini = _nouveau_software_context_fini,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nv50.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,14 +19,13 @@ int  nv50_software_ctor(struct nouveau_o
 
 struct nv50_software_cclass {
 	struct nouveau_oclass base;
-	int (*vblank)(void *, u32, int);
+	int (*vblank)(struct nvkm_notify *);
 };
 
 struct nv50_software_chan {
 	struct nouveau_software_chan base;
 	struct {
-		struct nouveau_eventh **event;
-		int nr_event;
+		struct nvkm_notify notify[4];
 		u32 channel;
 		u32 ctxdma;
 		u64 offset;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
  */
 
 #include <core/os.h>
-#include <core/class.h>
 #include <core/engctx.h>
 #include <core/event.h>
 
@@ -104,9 +103,10 @@ nvc0_software_sclass[] = {
  ******************************************************************************/
 
 static int
-nvc0_software_vblsem_release(void *data, u32 type, int head)
+nvc0_software_vblsem_release(struct nvkm_notify *notify)
 {
-	struct nv50_software_chan *chan = data;
+	struct nv50_software_chan *chan =
+		container_of(notify, typeof(*chan), vblank.notify[notify->index]);
 	struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
 	struct nouveau_bar *bar = nouveau_bar(priv);
 
@@ -116,7 +116,7 @@ nvc0_software_vblsem_release(void *data,
 	nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
 	nv_wr32(priv, 0x060014, chan->vblank.value);
 
-	return NVKM_EVENT_DROP;
+	return NVKM_NOTIFY_DROP;
 }
 
 static struct nv50_software_cclass
@@ -124,7 +124,7 @@ nvc0_software_cclass = {
 	.base.handle = NV_ENGCTX(SW, 0xc0),
 	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv50_software_context_ctor,
-		.dtor = _nouveau_software_context_dtor,
+		.dtor = nv50_software_context_dtor,
 		.init = _nouveau_software_context_init,
 		.fini = _nouveau_software_context_fini,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/class.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/class.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/class.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/class.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,470 +0,0 @@
-#ifndef __NOUVEAU_CLASS_H__
-#define __NOUVEAU_CLASS_H__
-
-/* Device class
- *
- * 0080: NV_DEVICE
- */
-#define NV_DEVICE_CLASS                                              0x00000080
-
-#define NV_DEVICE_DISABLE_IDENTIFY                        0x0000000000000001ULL
-#define NV_DEVICE_DISABLE_MMIO                            0x0000000000000002ULL
-#define NV_DEVICE_DISABLE_VBIOS                           0x0000000000000004ULL
-#define NV_DEVICE_DISABLE_CORE                            0x0000000000000008ULL
-#define NV_DEVICE_DISABLE_DISP                            0x0000000000010000ULL
-#define NV_DEVICE_DISABLE_FIFO                            0x0000000000020000ULL
-#define NV_DEVICE_DISABLE_GRAPH                           0x0000000100000000ULL
-#define NV_DEVICE_DISABLE_MPEG                            0x0000000200000000ULL
-#define NV_DEVICE_DISABLE_ME                              0x0000000400000000ULL
-#define NV_DEVICE_DISABLE_VP                              0x0000000800000000ULL
-#define NV_DEVICE_DISABLE_CRYPT                           0x0000001000000000ULL
-#define NV_DEVICE_DISABLE_BSP                             0x0000002000000000ULL
-#define NV_DEVICE_DISABLE_PPP                             0x0000004000000000ULL
-#define NV_DEVICE_DISABLE_COPY0                           0x0000008000000000ULL
-#define NV_DEVICE_DISABLE_COPY1                           0x0000010000000000ULL
-#define NV_DEVICE_DISABLE_VIC                             0x0000020000000000ULL
-#define NV_DEVICE_DISABLE_VENC                            0x0000040000000000ULL
-
-struct nv_device_class {
-	u64 device;	/* device identifier, ~0 for client default */
-	u64 disable;	/* disable particular subsystems */
-	u64 debug0;	/* as above, but *internal* ids, and *NOT* ABI */
-};
-
-/* DMA object classes
- *
- * 0002: NV_DMA_FROM_MEMORY
- * 0003: NV_DMA_TO_MEMORY
- * 003d: NV_DMA_IN_MEMORY
- */
-#define NV_DMA_FROM_MEMORY_CLASS                                     0x00000002
-#define NV_DMA_TO_MEMORY_CLASS                                       0x00000003
-#define NV_DMA_IN_MEMORY_CLASS                                       0x0000003d
-
-#define NV_DMA_TARGET_MASK                                           0x000000ff
-#define NV_DMA_TARGET_VM                                             0x00000000
-#define NV_DMA_TARGET_VRAM                                           0x00000001
-#define NV_DMA_TARGET_PCI                                            0x00000002
-#define NV_DMA_TARGET_PCI_US                                         0x00000003
-#define NV_DMA_TARGET_AGP                                            0x00000004
-#define NV_DMA_ACCESS_MASK                                           0x00000f00
-#define NV_DMA_ACCESS_VM                                             0x00000000
-#define NV_DMA_ACCESS_RD                                             0x00000100
-#define NV_DMA_ACCESS_WR                                             0x00000200
-#define NV_DMA_ACCESS_RDWR                                           0x00000300
-
-/* NV50:NVC0 */
-#define NV50_DMA_CONF0_ENABLE                                        0x80000000
-#define NV50_DMA_CONF0_PRIV                                          0x00300000
-#define NV50_DMA_CONF0_PRIV_VM                                       0x00000000
-#define NV50_DMA_CONF0_PRIV_US                                       0x00100000
-#define NV50_DMA_CONF0_PRIV__S                                       0x00200000
-#define NV50_DMA_CONF0_PART                                          0x00030000
-#define NV50_DMA_CONF0_PART_VM                                       0x00000000
-#define NV50_DMA_CONF0_PART_256                                      0x00010000
-#define NV50_DMA_CONF0_PART_1KB                                      0x00020000
-#define NV50_DMA_CONF0_COMP                                          0x00000180
-#define NV50_DMA_CONF0_COMP_NONE                                     0x00000000
-#define NV50_DMA_CONF0_COMP_VM                                       0x00000180
-#define NV50_DMA_CONF0_TYPE                                          0x0000007f
-#define NV50_DMA_CONF0_TYPE_LINEAR                                   0x00000000
-#define NV50_DMA_CONF0_TYPE_VM                                       0x0000007f
-
-/* NVC0:NVD9 */
-#define NVC0_DMA_CONF0_ENABLE                                        0x80000000
-#define NVC0_DMA_CONF0_PRIV                                          0x00300000
-#define NVC0_DMA_CONF0_PRIV_VM                                       0x00000000
-#define NVC0_DMA_CONF0_PRIV_US                                       0x00100000
-#define NVC0_DMA_CONF0_PRIV__S                                       0x00200000
-#define NVC0_DMA_CONF0_UNKN /* PART? */                              0x00030000
-#define NVC0_DMA_CONF0_TYPE                                          0x000000ff
-#define NVC0_DMA_CONF0_TYPE_LINEAR                                   0x00000000
-#define NVC0_DMA_CONF0_TYPE_VM                                       0x000000ff
-
-/* NVD9- */
-#define NVD0_DMA_CONF0_ENABLE                                        0x80000000
-#define NVD0_DMA_CONF0_PAGE                                          0x00000400
-#define NVD0_DMA_CONF0_PAGE_LP                                       0x00000000
-#define NVD0_DMA_CONF0_PAGE_SP                                       0x00000400
-#define NVD0_DMA_CONF0_TYPE                                          0x000000ff
-#define NVD0_DMA_CONF0_TYPE_LINEAR                                   0x00000000
-#define NVD0_DMA_CONF0_TYPE_VM                                       0x000000ff
-
-struct nv_dma_class {
-	u32 flags;
-	u32 pad0;
-	u64 start;
-	u64 limit;
-	u32 conf0;
-};
-
-/* Perfmon counter class
- *
- * XXXX: NV_PERFCTR
- */
-#define NV_PERFCTR_CLASS                                             0x0000ffff
-#define NV_PERFCTR_QUERY                                             0x00000000
-#define NV_PERFCTR_SAMPLE                                            0x00000001
-#define NV_PERFCTR_READ                                              0x00000002
-
-struct nv_perfctr_class {
-	u16 logic_op;
-	struct {
-		char __user *name; /*XXX: use cfu when exposed to userspace */
-		u32 size;
-	} signal[4];
-};
-
-struct nv_perfctr_query {
-	u32 iter;
-	u32 size;
-	char __user *name; /*XXX: use ctu when exposed to userspace */
-};
-
-struct nv_perfctr_sample {
-};
-
-struct nv_perfctr_read {
-	u32 ctr;
-	u32 clk;
-};
-
-/* Device control class
- *
- * XXXX: NV_CONTROL
- */
-#define NV_CONTROL_CLASS                                             0x0000fffe
-
-#define NV_CONTROL_PSTATE_INFO                                       0x00000000
-#define NV_CONTROL_PSTATE_INFO_USTATE_DISABLE                              (-1)
-#define NV_CONTROL_PSTATE_INFO_USTATE_PERFMON                              (-2)
-#define NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN                              (-1)
-#define NV_CONTROL_PSTATE_INFO_PSTATE_PERFMON                              (-2)
-#define NV_CONTROL_PSTATE_ATTR                                       0x00000001
-#define NV_CONTROL_PSTATE_ATTR_STATE_CURRENT                               (-1)
-#define NV_CONTROL_PSTATE_USER                                       0x00000002
-#define NV_CONTROL_PSTATE_USER_STATE_UNKNOWN                               (-1)
-#define NV_CONTROL_PSTATE_USER_STATE_PERFMON                               (-2)
-
-struct nv_control_pstate_info {
-	u32 count; /* out: number of power states */
-	s32 ustate; /* out: current target pstate index */
-	u32 pstate; /* out: current pstate index */
-};
-
-struct nv_control_pstate_attr {
-	s32 state; /*  in: index of pstate to query
-		    * out: pstate identifier
-		    */
-	u32 index; /*  in: index of attribute to query
-		    * out: index of next attribute, or 0 if no more
-		    */
-	char name[32];
-	char unit[16];
-	u32 min;
-	u32 max;
-};
-
-struct nv_control_pstate_user {
-	s32 state; /*  in: pstate identifier */
-};
-
-/* DMA FIFO channel classes
- *
- * 006b: NV03_CHANNEL_DMA
- * 006e: NV10_CHANNEL_DMA
- * 176e: NV17_CHANNEL_DMA
- * 406e: NV40_CHANNEL_DMA
- * 506e: NV50_CHANNEL_DMA
- * 826e: NV84_CHANNEL_DMA
- */
-#define NV03_CHANNEL_DMA_CLASS                                       0x0000006b
-#define NV10_CHANNEL_DMA_CLASS                                       0x0000006e
-#define NV17_CHANNEL_DMA_CLASS                                       0x0000176e
-#define NV40_CHANNEL_DMA_CLASS                                       0x0000406e
-#define NV50_CHANNEL_DMA_CLASS                                       0x0000506e
-#define NV84_CHANNEL_DMA_CLASS                                       0x0000826e
-
-struct nv03_channel_dma_class {
-	u32 pushbuf;
-	u32 pad0;
-	u64 offset;
-};
-
-/* Indirect FIFO channel classes
- *
- * 506f: NV50_CHANNEL_IND
- * 826f: NV84_CHANNEL_IND
- * 906f: NVC0_CHANNEL_IND
- * a06f: NVE0_CHANNEL_IND
- */
-
-#define NV50_CHANNEL_IND_CLASS                                       0x0000506f
-#define NV84_CHANNEL_IND_CLASS                                       0x0000826f
-#define NVC0_CHANNEL_IND_CLASS                                       0x0000906f
-#define NVE0_CHANNEL_IND_CLASS                                       0x0000a06f
-
-struct nv50_channel_ind_class {
-	u32 pushbuf;
-	u32 ilength;
-	u64 ioffset;
-};
-
-#define NVE0_CHANNEL_IND_ENGINE_GR                                   0x00000001
-#define NVE0_CHANNEL_IND_ENGINE_VP                                   0x00000002
-#define NVE0_CHANNEL_IND_ENGINE_PPP                                  0x00000004
-#define NVE0_CHANNEL_IND_ENGINE_BSP                                  0x00000008
-#define NVE0_CHANNEL_IND_ENGINE_CE0                                  0x00000010
-#define NVE0_CHANNEL_IND_ENGINE_CE1                                  0x00000020
-#define NVE0_CHANNEL_IND_ENGINE_ENC                                  0x00000040
-
-struct nve0_channel_ind_class {
-	u32 pushbuf;
-	u32 ilength;
-	u64 ioffset;
-	u32 engine;
-};
-
-/* 0046: NV04_DISP
- */
-
-#define NV04_DISP_CLASS                                              0x00000046
-
-#define NV04_DISP_MTHD                                               0x00000000
-#define NV04_DISP_MTHD_HEAD                                          0x00000001
-
-#define NV04_DISP_SCANOUTPOS                                         0x00000000
-
-struct nv04_display_class {
-};
-
-struct nv04_display_scanoutpos {
-	s64 time[2];
-	u32 vblanks;
-	u32 vblanke;
-	u32 vtotal;
-	u32 vline;
-	u32 hblanks;
-	u32 hblanke;
-	u32 htotal;
-	u32 hline;
-};
-
-/* 5070: NV50_DISP
- * 8270: NV84_DISP
- * 8370: NVA0_DISP
- * 8870: NV94_DISP
- * 8570: NVA3_DISP
- * 9070: NVD0_DISP
- * 9170: NVE0_DISP
- * 9270: NVF0_DISP
- * 9470: GM107_DISP
- */
-
-#define NV50_DISP_CLASS                                              0x00005070
-#define NV84_DISP_CLASS                                              0x00008270
-#define NVA0_DISP_CLASS                                              0x00008370
-#define NV94_DISP_CLASS                                              0x00008870
-#define NVA3_DISP_CLASS                                              0x00008570
-#define NVD0_DISP_CLASS                                              0x00009070
-#define NVE0_DISP_CLASS                                              0x00009170
-#define NVF0_DISP_CLASS                                              0x00009270
-#define GM107_DISP_CLASS                                             0x00009470
-
-#define NV50_DISP_MTHD                                               0x00000000
-#define NV50_DISP_MTHD_HEAD                                          0x00000003
-
-#define NV50_DISP_SCANOUTPOS                                         0x00000000
-
-#define NV50_DISP_SOR_MTHD                                           0x00010000
-#define NV50_DISP_SOR_MTHD_TYPE                                      0x0000f000
-#define NV50_DISP_SOR_MTHD_HEAD                                      0x00000018
-#define NV50_DISP_SOR_MTHD_LINK                                      0x00000004
-#define NV50_DISP_SOR_MTHD_OR                                        0x00000003
-
-#define NV50_DISP_SOR_PWR                                            0x00010000
-#define NV50_DISP_SOR_PWR_STATE                                      0x00000001
-#define NV50_DISP_SOR_PWR_STATE_ON                                   0x00000001
-#define NV50_DISP_SOR_PWR_STATE_OFF                                  0x00000000
-#define NVA3_DISP_SOR_HDA_ELD                                        0x00010100
-#define NV84_DISP_SOR_HDMI_PWR                                       0x00012000
-#define NV84_DISP_SOR_HDMI_PWR_STATE                                 0x40000000
-#define NV84_DISP_SOR_HDMI_PWR_STATE_OFF                             0x00000000
-#define NV84_DISP_SOR_HDMI_PWR_STATE_ON                              0x40000000
-#define NV84_DISP_SOR_HDMI_PWR_MAX_AC_PACKET                         0x001f0000
-#define NV84_DISP_SOR_HDMI_PWR_REKEY                                 0x0000007f
-#define NV50_DISP_SOR_LVDS_SCRIPT                                    0x00013000
-#define NV50_DISP_SOR_LVDS_SCRIPT_ID                                 0x0000ffff
-#define NV94_DISP_SOR_DP_PWR                                         0x00016000
-#define NV94_DISP_SOR_DP_PWR_STATE                                   0x00000001
-#define NV94_DISP_SOR_DP_PWR_STATE_OFF                               0x00000000
-#define NV94_DISP_SOR_DP_PWR_STATE_ON                                0x00000001
-
-#define NV50_DISP_DAC_MTHD                                           0x00020000
-#define NV50_DISP_DAC_MTHD_TYPE                                      0x0000f000
-#define NV50_DISP_DAC_MTHD_OR                                        0x00000003
-
-#define NV50_DISP_DAC_PWR                                            0x00020000
-#define NV50_DISP_DAC_PWR_HSYNC                                      0x00000001
-#define NV50_DISP_DAC_PWR_HSYNC_ON                                   0x00000000
-#define NV50_DISP_DAC_PWR_HSYNC_LO                                   0x00000001
-#define NV50_DISP_DAC_PWR_VSYNC                                      0x00000004
-#define NV50_DISP_DAC_PWR_VSYNC_ON                                   0x00000000
-#define NV50_DISP_DAC_PWR_VSYNC_LO                                   0x00000004
-#define NV50_DISP_DAC_PWR_DATA                                       0x00000010
-#define NV50_DISP_DAC_PWR_DATA_ON                                    0x00000000
-#define NV50_DISP_DAC_PWR_DATA_LO                                    0x00000010
-#define NV50_DISP_DAC_PWR_STATE                                      0x00000040
-#define NV50_DISP_DAC_PWR_STATE_ON                                   0x00000000
-#define NV50_DISP_DAC_PWR_STATE_OFF                                  0x00000040
-#define NV50_DISP_DAC_LOAD                                           0x00020100
-#define NV50_DISP_DAC_LOAD_VALUE                                     0x00000007
-
-#define NV50_DISP_PIOR_MTHD                                          0x00030000
-#define NV50_DISP_PIOR_MTHD_TYPE                                     0x0000f000
-#define NV50_DISP_PIOR_MTHD_OR                                       0x00000003
-
-#define NV50_DISP_PIOR_PWR                                           0x00030000
-#define NV50_DISP_PIOR_PWR_STATE                                     0x00000001
-#define NV50_DISP_PIOR_PWR_STATE_ON                                  0x00000001
-#define NV50_DISP_PIOR_PWR_STATE_OFF                                 0x00000000
-#define NV50_DISP_PIOR_TMDS_PWR                                      0x00032000
-#define NV50_DISP_PIOR_TMDS_PWR_STATE                                0x00000001
-#define NV50_DISP_PIOR_TMDS_PWR_STATE_ON                             0x00000001
-#define NV50_DISP_PIOR_TMDS_PWR_STATE_OFF                            0x00000000
-#define NV50_DISP_PIOR_DP_PWR                                        0x00036000
-#define NV50_DISP_PIOR_DP_PWR_STATE                                  0x00000001
-#define NV50_DISP_PIOR_DP_PWR_STATE_ON                               0x00000001
-#define NV50_DISP_PIOR_DP_PWR_STATE_OFF                              0x00000000
-
-struct nv50_display_class {
-};
-
-/* 507a: NV50_DISP_CURS
- * 827a: NV84_DISP_CURS
- * 837a: NVA0_DISP_CURS
- * 887a: NV94_DISP_CURS
- * 857a: NVA3_DISP_CURS
- * 907a: NVD0_DISP_CURS
- * 917a: NVE0_DISP_CURS
- * 927a: NVF0_DISP_CURS
- * 947a: GM107_DISP_CURS
- */
-
-#define NV50_DISP_CURS_CLASS                                         0x0000507a
-#define NV84_DISP_CURS_CLASS                                         0x0000827a
-#define NVA0_DISP_CURS_CLASS                                         0x0000837a
-#define NV94_DISP_CURS_CLASS                                         0x0000887a
-#define NVA3_DISP_CURS_CLASS                                         0x0000857a
-#define NVD0_DISP_CURS_CLASS                                         0x0000907a
-#define NVE0_DISP_CURS_CLASS                                         0x0000917a
-#define NVF0_DISP_CURS_CLASS                                         0x0000927a
-#define GM107_DISP_CURS_CLASS                                        0x0000947a
-
-struct nv50_display_curs_class {
-	u32 head;
-};
-
-/* 507b: NV50_DISP_OIMM
- * 827b: NV84_DISP_OIMM
- * 837b: NVA0_DISP_OIMM
- * 887b: NV94_DISP_OIMM
- * 857b: NVA3_DISP_OIMM
- * 907b: NVD0_DISP_OIMM
- * 917b: NVE0_DISP_OIMM
- * 927b: NVE0_DISP_OIMM
- * 947b: GM107_DISP_OIMM
- */
-
-#define NV50_DISP_OIMM_CLASS                                         0x0000507b
-#define NV84_DISP_OIMM_CLASS                                         0x0000827b
-#define NVA0_DISP_OIMM_CLASS                                         0x0000837b
-#define NV94_DISP_OIMM_CLASS                                         0x0000887b
-#define NVA3_DISP_OIMM_CLASS                                         0x0000857b
-#define NVD0_DISP_OIMM_CLASS                                         0x0000907b
-#define NVE0_DISP_OIMM_CLASS                                         0x0000917b
-#define NVF0_DISP_OIMM_CLASS                                         0x0000927b
-#define GM107_DISP_OIMM_CLASS                                        0x0000947b
-
-struct nv50_display_oimm_class {
-	u32 head;
-};
-
-/* 507c: NV50_DISP_SYNC
- * 827c: NV84_DISP_SYNC
- * 837c: NVA0_DISP_SYNC
- * 887c: NV94_DISP_SYNC
- * 857c: NVA3_DISP_SYNC
- * 907c: NVD0_DISP_SYNC
- * 917c: NVE0_DISP_SYNC
- * 927c: NVF0_DISP_SYNC
- * 947c: GM107_DISP_SYNC
- */
-
-#define NV50_DISP_SYNC_CLASS                                         0x0000507c
-#define NV84_DISP_SYNC_CLASS                                         0x0000827c
-#define NVA0_DISP_SYNC_CLASS                                         0x0000837c
-#define NV94_DISP_SYNC_CLASS                                         0x0000887c
-#define NVA3_DISP_SYNC_CLASS                                         0x0000857c
-#define NVD0_DISP_SYNC_CLASS                                         0x0000907c
-#define NVE0_DISP_SYNC_CLASS                                         0x0000917c
-#define NVF0_DISP_SYNC_CLASS                                         0x0000927c
-#define GM107_DISP_SYNC_CLASS                                        0x0000947c
-
-struct nv50_display_sync_class {
-	u32 pushbuf;
-	u32 head;
-};
-
-/* 507d: NV50_DISP_MAST
- * 827d: NV84_DISP_MAST
- * 837d: NVA0_DISP_MAST
- * 887d: NV94_DISP_MAST
- * 857d: NVA3_DISP_MAST
- * 907d: NVD0_DISP_MAST
- * 917d: NVE0_DISP_MAST
- * 927d: NVF0_DISP_MAST
- * 947d: GM107_DISP_MAST
- */
-
-#define NV50_DISP_MAST_CLASS                                         0x0000507d
-#define NV84_DISP_MAST_CLASS                                         0x0000827d
-#define NVA0_DISP_MAST_CLASS                                         0x0000837d
-#define NV94_DISP_MAST_CLASS                                         0x0000887d
-#define NVA3_DISP_MAST_CLASS                                         0x0000857d
-#define NVD0_DISP_MAST_CLASS                                         0x0000907d
-#define NVE0_DISP_MAST_CLASS                                         0x0000917d
-#define NVF0_DISP_MAST_CLASS                                         0x0000927d
-#define GM107_DISP_MAST_CLASS                                        0x0000947d
-
-struct nv50_display_mast_class {
-	u32 pushbuf;
-};
-
-/* 507e: NV50_DISP_OVLY
- * 827e: NV84_DISP_OVLY
- * 837e: NVA0_DISP_OVLY
- * 887e: NV94_DISP_OVLY
- * 857e: NVA3_DISP_OVLY
- * 907e: NVD0_DISP_OVLY
- * 917e: NVE0_DISP_OVLY
- * 927e: NVF0_DISP_OVLY
- * 947e: GM107_DISP_OVLY
- */
-
-#define NV50_DISP_OVLY_CLASS                                         0x0000507e
-#define NV84_DISP_OVLY_CLASS                                         0x0000827e
-#define NVA0_DISP_OVLY_CLASS                                         0x0000837e
-#define NV94_DISP_OVLY_CLASS                                         0x0000887e
-#define NVA3_DISP_OVLY_CLASS                                         0x0000857e
-#define NVD0_DISP_OVLY_CLASS                                         0x0000907e
-#define NVE0_DISP_OVLY_CLASS                                         0x0000917e
-#define NVF0_DISP_OVLY_CLASS                                         0x0000927e
-#define GM107_DISP_OVLY_CLASS                                        0x0000947e
-
-struct nv50_display_ovly_class {
-	u32 pushbuf;
-	u32 head;
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/client.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/client.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/client.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/client.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,11 @@ struct nouveau_client {
 	char name[32];
 	u32 debug;
 	struct nouveau_vm *vm;
+	bool super;
+	void *data;
+
+	int (*ntfy)(const void *, u32, const void *, u32);
+	struct nvkm_client_notify *notify[16];
 };
 
 static inline struct nouveau_client *
@@ -43,4 +48,10 @@ int  nouveau_client_init(struct nouveau_
 int  nouveau_client_fini(struct nouveau_client *, bool suspend);
 const char *nouveau_client_name(void *obj);
 
+int nvkm_client_notify_new(struct nouveau_client *, struct nvkm_event *,
+			   void *data, u32 size);
+int nvkm_client_notify_del(struct nouveau_client *, int index);
+int nvkm_client_notify_get(struct nouveau_client *, int index);
+int nvkm_client_notify_put(struct nouveau_client *, int index);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/device.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/device.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/device.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/device.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
 #include <core/object.h>
 #include <core/subdev.h>
 #include <core/engine.h>
+#include <core/event.h>
 
 enum nv_subdev_type {
 	NVDEV_ENGINE_DEVICE,
@@ -28,7 +29,7 @@ enum nv_subdev_type {
 	NVDEV_SUBDEV_BUS,
 	NVDEV_SUBDEV_TIMER,
 	NVDEV_SUBDEV_FB,
-	NVDEV_SUBDEV_LTCG,
+	NVDEV_SUBDEV_LTC,
 	NVDEV_SUBDEV_IBUS,
 	NVDEV_SUBDEV_INSTMEM,
 	NVDEV_SUBDEV_VM,
@@ -69,6 +70,8 @@ struct nouveau_device {
 	struct platform_device *platformdev;
 	u64 handle;
 
+	struct nvkm_event event;
+
 	const char *cfgopt;
 	const char *dbgopt;
 	const char *name;
@@ -84,7 +87,6 @@ struct nouveau_device {
 		NV_40    = 0x40,
 		NV_50    = 0x50,
 		NV_C0    = 0xc0,
-		NV_D0    = 0xd0,
 		NV_E0    = 0xe0,
 		GM100    = 0x110,
 	} card_type;
@@ -93,8 +95,14 @@ struct nouveau_device {
 
 	struct nouveau_oclass *oclass[NVDEV_SUBDEV_NR];
 	struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
+
+	struct {
+		struct notifier_block nb;
+	} acpi;
 };
 
+int nouveau_device_list(u64 *name, int size);
+
 static inline struct nouveau_device *
 nv_device(void *obj)
 {
@@ -162,12 +170,6 @@ nv_device_resource_start(struct nouveau_
 resource_size_t
 nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
 
-dma_addr_t
-nv_device_map_page(struct nouveau_device *device, struct page *page);
-
-void
-nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);
-
 int
 nv_device_get_irq(struct nouveau_device *device, bool stall);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/event.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/event.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/event.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/event.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,47 +1,34 @@
 #ifndef __NVKM_EVENT_H__
 #define __NVKM_EVENT_H__
 
-/* return codes from event handlers */
-#define NVKM_EVENT_DROP 0
-#define NVKM_EVENT_KEEP 1
-
-/* nouveau_eventh.flags bit #s */
-#define NVKM_EVENT_ENABLE 0
+#include <core/notify.h>
 
-struct nouveau_eventh {
-	struct nouveau_event *event;
-	struct list_head head;
-	unsigned long flags;
-	u32 types;
-	int index;
-	int (*func)(void *, u32, int);
-	void *priv;
+struct nvkm_event_func {
+	int  (*ctor)(void *data, u32 size, struct nvkm_notify *);
+	void (*send)(void *data, u32 size, struct nvkm_notify *);
+	void (*init)(struct nvkm_event *, int type, int index);
+	void (*fini)(struct nvkm_event *, int type, int index);
 };
 
-struct nouveau_event {
-	void *priv;
-	int (*check)(struct nouveau_event *, u32 type, int index);
-	void (*enable)(struct nouveau_event *, int type, int index);
-	void (*disable)(struct nouveau_event *, int type, int index);
+struct nvkm_event {
+	const struct nvkm_event_func *func;
 
 	int types_nr;
 	int index_nr;
 
-	spinlock_t list_lock;
-	struct list_head *list;
 	spinlock_t refs_lock;
-	int refs[];
+	spinlock_t list_lock;
+	struct list_head list;
+	int *refs;
 };
 
-int  nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **);
-void nouveau_event_destroy(struct nouveau_event **);
-void nouveau_event_trigger(struct nouveau_event *, u32 types, int index);
-
-int  nouveau_event_new(struct nouveau_event *, u32 types, int index,
-		       int (*func)(void *, u32, int), void *,
-		       struct nouveau_eventh **);
-void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **);
-void nouveau_event_get(struct nouveau_eventh *);
-void nouveau_event_put(struct nouveau_eventh *);
+int  nvkm_event_init(const struct nvkm_event_func *func,
+		     int types_nr, int index_nr,
+		     struct nvkm_event *);
+void nvkm_event_fini(struct nvkm_event *);
+void nvkm_event_get(struct nvkm_event *, u32 types, int index);
+void nvkm_event_put(struct nvkm_event *, u32 types, int index);
+void nvkm_event_send(struct nvkm_event *, u32 types, int index,
+		     void *data, u32 size);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/handle.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/handle.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/handle.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/handle.h	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,9 @@ struct nouveau_handle {
 	u32 name;
 	u32 priv;
 
+	u8  route;
+	u64 token;
+
 	struct nouveau_handle *parent;
 	struct nouveau_object *object;
 };
@@ -20,6 +23,11 @@ void nouveau_handle_destroy(struct nouve
 int  nouveau_handle_init(struct nouveau_handle *);
 int  nouveau_handle_fini(struct nouveau_handle *, bool suspend);
 
+int  nouveau_handle_new(struct nouveau_object *, u32 parent, u32 handle,
+			u16 oclass, void *data, u32 size,
+			struct nouveau_object **);
+int  nouveau_handle_del(struct nouveau_object *, u32 parent, u32 handle);
+
 struct nouveau_object *
 nouveau_handle_ref(struct nouveau_object *, u32 name);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/ioctl.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/ioctl.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/ioctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/ioctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef __NVKM_IOCTL_H__
+#define __NVKM_IOCTL_H__
+
+int nvkm_ioctl(struct nouveau_client *, bool, void *, u32, void **);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/notify.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/notify.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/notify.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/notify.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,36 @@
+#ifndef __NVKM_NOTIFY_H__
+#define __NVKM_NOTIFY_H__
+
+struct nvkm_notify {
+	struct nvkm_event *event;
+	struct list_head head;
+#define NVKM_NOTIFY_USER 0
+#define NVKM_NOTIFY_WORK 1
+	unsigned long flags;
+	int block;
+#define NVKM_NOTIFY_DROP 0
+#define NVKM_NOTIFY_KEEP 1
+	int (*func)(struct nvkm_notify *);
+
+	/* set by nvkm_event ctor */
+	u32 types;
+	int index;
+	u32 size;
+
+	struct work_struct work;
+	/* this is const for a *very* good reason - the data might be on the
+	 * stack from an irq handler.  if you're not core/notify.c then you
+	 * should probably think twice before casting it away...
+	 */
+	const void *data;
+};
+
+int  nvkm_notify_init(struct nvkm_event *, int (*func)(struct nvkm_notify *),
+		      bool work, void *data, u32 size, u32 reply,
+		      struct nvkm_notify *);
+void nvkm_notify_fini(struct nvkm_notify *);
+void nvkm_notify_get(struct nvkm_notify *);
+void nvkm_notify_put(struct nvkm_notify *);
+void nvkm_notify_send(struct nvkm_notify *, void *data, u32 size);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/object.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/object.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/object.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,10 @@ void nouveau_object_destroy(struct nouve
 int  nouveau_object_init(struct nouveau_object *);
 int  nouveau_object_fini(struct nouveau_object *, bool suspend);
 
+int _nouveau_object_ctor(struct nouveau_object *, struct nouveau_object *,
+			 struct nouveau_oclass *, void *, u32,
+			 struct nouveau_object **);
+
 extern struct nouveau_ofuncs nouveau_object_ofuncs;
 
 /* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
@@ -78,6 +82,7 @@ struct nouveau_omthds {
 	int (*call)(struct nouveau_object *, u32, void *, u32);
 };
 
+struct nvkm_event;
 struct nouveau_ofuncs {
 	int  (*ctor)(struct nouveau_object *, struct nouveau_object *,
 		     struct nouveau_oclass *, void *data, u32 size,
@@ -85,6 +90,9 @@ struct nouveau_ofuncs {
 	void (*dtor)(struct nouveau_object *);
 	int  (*init)(struct nouveau_object *);
 	int  (*fini)(struct nouveau_object *, bool suspend);
+	int  (*mthd)(struct nouveau_object *, u32, void *, u32);
+	int  (*ntfy)(struct nouveau_object *, u32, struct nvkm_event **);
+	int  (* map)(struct nouveau_object *, u64 *, u32 *);
 	u8   (*rd08)(struct nouveau_object *, u64 offset);
 	u16  (*rd16)(struct nouveau_object *, u64 offset);
 	u32  (*rd32)(struct nouveau_object *, u64 offset);
@@ -106,10 +114,6 @@ void nouveau_object_ref(struct nouveau_o
 int nouveau_object_inc(struct nouveau_object *);
 int nouveau_object_dec(struct nouveau_object *, bool suspend);
 
-int nouveau_object_new(struct nouveau_object *, u32 parent, u32 handle,
-		       u16 oclass, void *data, u32 size,
-		       struct nouveau_object **);
-int nouveau_object_del(struct nouveau_object *, u32 parent, u32 handle);
 void nouveau_object_debug(void);
 
 static inline int
@@ -199,4 +203,21 @@ nv_memcmp(void *obj, u32 addr, const cha
 	return 0;
 }
 
+#include <core/handle.h>
+
+static inline int
+nouveau_object_new(struct nouveau_object *client, u32 parent, u32 handle,
+		   u16 oclass, void *data, u32 size,
+		   struct nouveau_object **pobject)
+{
+	return nouveau_handle_new(client, parent, handle, oclass,
+				  data, size, pobject);
+}
+
+static inline int
+nouveau_object_del(struct nouveau_object *client, u32 parent, u32 handle)
+{
+	return nouveau_handle_del(client, parent, handle);
+}
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/parent.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/parent.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/parent.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/parent.h	2014-09-28 17:29:07.000000000 -0400
@@ -57,5 +57,6 @@ void _nouveau_parent_dtor(struct nouveau
 int nouveau_parent_sclass(struct nouveau_object *, u16 handle,
 			  struct nouveau_object **pengine,
 			  struct nouveau_oclass **poclass);
+int nouveau_parent_lclass(struct nouveau_object *, u32 *, int);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/printk.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/printk.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/core/printk.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/core/printk.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@ nv_printk_(struct nouveau_object *, int,
 #define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a)
 #define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a)
 #define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a)
+#define nv_ioctl(o,f,a...) nv_trace(nouveau_client(o), "ioctl: "f, ##a)
 
 #define nv_assert(f,a...) do {                                                 \
 	if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG)                              \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/disp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/disp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/disp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/disp.h	2014-09-28 17:29:07.000000000 -0400
@@ -6,20 +6,13 @@
 #include <core/device.h>
 #include <core/event.h>
 
-enum nvkm_hpd_event {
-	NVKM_HPD_PLUG = 1,
-	NVKM_HPD_UNPLUG = 2,
-	NVKM_HPD_IRQ = 4,
-	NVKM_HPD = (NVKM_HPD_PLUG | NVKM_HPD_UNPLUG | NVKM_HPD_IRQ)
-};
-
 struct nouveau_disp {
 	struct nouveau_engine base;
 
 	struct list_head outp;
-	struct nouveau_event *hpd;
 
-	struct nouveau_event *vblank;
+	struct nvkm_event hpd;
+	struct nvkm_event vblank;
 };
 
 static inline struct nouveau_disp *
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,37 +12,20 @@ struct nouveau_dmaobj {
 	u32 access;
 	u64 start;
 	u64 limit;
-	u32 conf0;
 };
 
 struct nouveau_dmaeng {
 	struct nouveau_engine base;
 
 	/* creates a "physical" dma object from a struct nouveau_dmaobj */
-	int (*bind)(struct nouveau_dmaeng *dmaeng,
+	int (*bind)(struct nouveau_dmaobj *dmaobj,
 		    struct nouveau_object *parent,
-		    struct nouveau_dmaobj *dmaobj,
 		    struct nouveau_gpuobj **);
 };
 
-#define nouveau_dmaeng_create(p,e,c,d)                                         \
-	nouveau_engine_create((p), (e), (c), true, "DMAOBJ", "dmaobj", (d))
-#define nouveau_dmaeng_destroy(p)                                              \
-	nouveau_engine_destroy(&(p)->base)
-#define nouveau_dmaeng_init(p)                                                 \
-	nouveau_engine_init(&(p)->base)
-#define nouveau_dmaeng_fini(p,s)                                               \
-	nouveau_engine_fini(&(p)->base, (s))
-
-#define _nouveau_dmaeng_dtor _nouveau_engine_dtor
-#define _nouveau_dmaeng_init _nouveau_engine_init
-#define _nouveau_dmaeng_fini _nouveau_engine_fini
-
-extern struct nouveau_oclass nv04_dmaeng_oclass;
-extern struct nouveau_oclass nv50_dmaeng_oclass;
-extern struct nouveau_oclass nvc0_dmaeng_oclass;
-extern struct nouveau_oclass nvd0_dmaeng_oclass;
-
-extern struct nouveau_oclass nouveau_dmaobj_sclass[];
+extern struct nouveau_oclass *nv04_dmaeng_oclass;
+extern struct nouveau_oclass *nv50_dmaeng_oclass;
+extern struct nouveau_oclass *nvc0_dmaeng_oclass;
+extern struct nouveau_oclass *nvd0_dmaeng_oclass;
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/fifo.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/fifo.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/fifo.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,12 +4,14 @@
 #include <core/namedb.h>
 #include <core/gpuobj.h>
 #include <core/engine.h>
+#include <core/event.h>
 
 struct nouveau_fifo_chan {
 	struct nouveau_namedb base;
 	struct nouveau_dmaobj *pushdma;
 	struct nouveau_gpuobj *pushgpu;
 	void __iomem *user;
+	u64 addr;
 	u32 size;
 	u16 chid;
 	atomic_t refcnt; /* NV04_NVSW_SET_REF */
@@ -40,8 +42,10 @@ void nouveau_fifo_channel_destroy(struct
 #define _nouveau_fifo_channel_fini _nouveau_namedb_fini
 
 void _nouveau_fifo_channel_dtor(struct nouveau_object *);
+int  _nouveau_fifo_channel_map(struct nouveau_object *, u64 *, u32 *);
 u32  _nouveau_fifo_channel_rd32(struct nouveau_object *, u64);
 void _nouveau_fifo_channel_wr32(struct nouveau_object *, u64, u32);
+int  _nouveau_fifo_channel_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
 
 struct nouveau_fifo_base {
 	struct nouveau_gpuobj base;
@@ -65,8 +69,8 @@ struct nouveau_fifo_base {
 struct nouveau_fifo {
 	struct nouveau_engine base;
 
-	struct nouveau_event *cevent; /* channel creation event */
-	struct nouveau_event *uevent; /* async user trigger */
+	struct nvkm_event cevent; /* channel creation event */
+	struct nvkm_event uevent; /* async user trigger */
 
 	struct nouveau_object **channel;
 	spinlock_t lock;
@@ -112,6 +116,9 @@ extern struct nouveau_oclass *nve0_fifo_
 extern struct nouveau_oclass *gk20a_fifo_oclass;
 extern struct nouveau_oclass *nv108_fifo_oclass;
 
+int  nouveau_fifo_uevent_ctor(void *, u32, struct nvkm_notify *);
+void nouveau_fifo_uevent(struct nouveau_fifo *);
+
 void nv04_fifo_intr(struct nouveau_subdev *);
 int  nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/graph.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/graph.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/graph.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/graph.h	2014-09-28 17:29:07.000000000 -0400
@@ -70,6 +70,7 @@ extern struct nouveau_oclass *nvd9_graph
 extern struct nouveau_oclass *nve4_graph_oclass;
 extern struct nouveau_oclass *gk20a_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
+extern struct nouveau_oclass *gk110b_graph_oclass;
 extern struct nouveau_oclass *nv108_graph_oclass;
 extern struct nouveau_oclass *gm107_graph_oclass;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,6 @@
 #include <core/device.h>
 #include <core/engine.h>
 #include <core/engctx.h>
-#include <core/class.h>
 
 struct nouveau_perfdom;
 struct nouveau_perfctr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/bar.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/bar.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/bar.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,9 @@ struct nouveau_bar {
 		    u32 flags, struct nouveau_vma *);
 	void (*unmap)(struct nouveau_bar *, struct nouveau_vma *);
 	void (*flush)(struct nouveau_bar *);
+
+	/* whether the BAR supports to be ioremapped WC or should be uncached */
+	bool iomap_uncached;
 };
 
 static inline struct nouveau_bar *
@@ -30,5 +33,6 @@ nouveau_bar(void *obj)
 
 extern struct nouveau_oclass nv50_bar_oclass;
 extern struct nouveau_oclass nvc0_bar_oclass;
+extern struct nouveau_oclass gk20a_bar_oclass;
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/clock.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/clock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/clock.h	2014-09-28 17:29:07.000000000 -0400
@@ -71,8 +71,15 @@ struct nouveau_clock {
 	struct list_head states;
 	int state_nr;
 
+	struct work_struct work;
+	wait_queue_head_t wait;
+	atomic_t waiting;
+
+	struct nvkm_notify pwrsrc_ntfy;
+	int pwrsrc;
 	int pstate; /* current */
-	int ustate; /* user-requested (-1 disabled, -2 perfmon) */
+	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+) */
@@ -108,8 +115,9 @@ struct nouveau_clocks {
 	int mdiv;
 };
 
-#define nouveau_clock_create(p,e,o,i,r,d)                                      \
-	nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
+#define nouveau_clock_create(p,e,o,i,r,s,n,d)                                  \
+	nouveau_clock_create_((p), (e), (o), (i), (r), (s), (n), sizeof(**d),  \
+			      (void **)d)
 #define nouveau_clock_destroy(p) ({                                            \
 	struct nouveau_clock *clk = (p);                                       \
 	_nouveau_clock_dtor(nv_object(clk));                                   \
@@ -118,15 +126,18 @@ struct nouveau_clocks {
 	struct nouveau_clock *clk = (p);                                       \
 	_nouveau_clock_init(nv_object(clk));                                   \
 })
-#define nouveau_clock_fini(p,s)                                                \
-	nouveau_subdev_fini(&(p)->base, (s))
+#define nouveau_clock_fini(p,s) ({                                             \
+	struct nouveau_clock *clk = (p);                                       \
+	_nouveau_clock_fini(nv_object(clk), (s));                              \
+})
 
 int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
 			   struct nouveau_oclass *,
-			   struct nouveau_clocks *, bool, int, void **);
+			   struct nouveau_clocks *, struct nouveau_pstate *,
+			   int, bool, int, void **);
 void _nouveau_clock_dtor(struct nouveau_object *);
-int _nouveau_clock_init(struct nouveau_object *);
-#define _nouveau_clock_fini _nouveau_subdev_fini
+int  _nouveau_clock_init(struct nouveau_object *);
+int  _nouveau_clock_fini(struct nouveau_object *, bool);
 
 extern struct nouveau_oclass nv04_clock_oclass;
 extern struct nouveau_oclass nv40_clock_oclass;
@@ -136,6 +147,7 @@ extern struct nouveau_oclass *nvaa_clock
 extern struct nouveau_oclass nva3_clock_oclass;
 extern struct nouveau_oclass nvc0_clock_oclass;
 extern struct nouveau_oclass nve0_clock_oclass;
+extern struct nouveau_oclass gk20a_clock_oclass;
 
 int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq);
 int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
@@ -145,7 +157,7 @@ int nv04_clock_pll_prog(struct nouveau_c
 int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
 			int clk, struct nouveau_pll_vals *);
 
-int nouveau_clock_ustate(struct nouveau_clock *, int req);
+int nouveau_clock_ustate(struct nouveau_clock *, int req, int pwr);
 int nouveau_clock_astate(struct nouveau_clock *, int req, int rel);
 int nouveau_clock_dstate(struct nouveau_clock *, int req, int rel);
 int nouveau_clock_tstate(struct nouveau_clock *, int req, int rel);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h	2014-09-28 17:29:07.000000000 -0400
@@ -8,16 +8,22 @@
 #include <subdev/bios.h>
 #include <subdev/bios/gpio.h>
 
-enum nvkm_gpio_event {
-	NVKM_GPIO_HI = 1,
-	NVKM_GPIO_LO = 2,
-	NVKM_GPIO_TOGGLED = (NVKM_GPIO_HI | NVKM_GPIO_LO),
+struct nvkm_gpio_ntfy_req {
+#define NVKM_GPIO_HI                                                       0x01
+#define NVKM_GPIO_LO                                                       0x02
+#define NVKM_GPIO_TOGGLED                                                  0x03
+	u8 mask;
+	u8 line;
+};
+
+struct nvkm_gpio_ntfy_rep {
+	u8 mask;
 };
 
 struct nouveau_gpio {
 	struct nouveau_subdev base;
 
-	struct nouveau_event *events;
+	struct nvkm_event event;
 
 	void (*reset)(struct nouveau_gpio *, u8 func);
 	int  (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,15 +14,18 @@
 #define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)
 #define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8)
 
-enum nvkm_i2c_event {
-	NVKM_I2C_PLUG = 1,
-	NVKM_I2C_UNPLUG = 2,
-	NVKM_I2C_IRQ = 4,
-	NVKM_I2C_DONE = 8,
-	NVKM_I2C_ANY = (NVKM_I2C_PLUG |
-			NVKM_I2C_UNPLUG |
-			NVKM_I2C_IRQ |
-			NVKM_I2C_DONE),
+struct nvkm_i2c_ntfy_req {
+#define NVKM_I2C_PLUG                                                      0x01
+#define NVKM_I2C_UNPLUG                                                    0x02
+#define NVKM_I2C_IRQ                                                       0x04
+#define NVKM_I2C_DONE                                                      0x08
+#define NVKM_I2C_ANY                                                       0x0f
+	u8 mask;
+	u8 port;
+};
+
+struct nvkm_i2c_ntfy_rep {
+	u8 mask;
 };
 
 struct nouveau_i2c_port {
@@ -56,7 +59,7 @@ struct nouveau_i2c_board_info {
 
 struct nouveau_i2c {
 	struct nouveau_subdev base;
-	struct nouveau_event *ntfy;
+	struct nvkm_event event;
 
 	struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);
 	struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-#ifndef __NOUVEAU_LTCG_H__
-#define __NOUVEAU_LTCG_H__
-
-#include <core/subdev.h>
-#include <core/device.h>
-
-struct nouveau_mm_node;
-
-struct nouveau_ltcg {
-	struct nouveau_subdev base;
-
-	int  (*tags_alloc)(struct nouveau_ltcg *, u32 count,
-	                   struct nouveau_mm_node **);
-	void (*tags_free)(struct nouveau_ltcg *, struct nouveau_mm_node **);
-	void (*tags_clear)(struct nouveau_ltcg *, u32 first, u32 count);
-};
-
-static inline struct nouveau_ltcg *
-nouveau_ltcg(void *obj)
-{
-	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG];
-}
-
-#define nouveau_ltcg_create(p,e,o,d)                                           \
-	nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2",            \
-			       sizeof(**d), (void **)d)
-#define nouveau_ltcg_destroy(p)                                                \
-	nouveau_subdev_destroy(&(p)->base)
-#define nouveau_ltcg_init(p)                                                   \
-	nouveau_subdev_init(&(p)->base)
-#define nouveau_ltcg_fini(p,s)                                                 \
-	nouveau_subdev_fini(&(p)->base, (s))
-
-#define _nouveau_ltcg_dtor _nouveau_subdev_dtor
-#define _nouveau_ltcg_init _nouveau_subdev_init
-#define _nouveau_ltcg_fini _nouveau_subdev_fini
-
-extern struct nouveau_oclass *gf100_ltcg_oclass;
-extern struct nouveau_oclass *gm107_ltcg_oclass;
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,35 @@
+#ifndef __NOUVEAU_LTC_H__
+#define __NOUVEAU_LTC_H__
+
+#include <core/subdev.h>
+#include <core/device.h>
+
+#define NOUVEAU_LTC_MAX_ZBC_CNT 16
+
+struct nouveau_mm_node;
+
+struct nouveau_ltc {
+	struct nouveau_subdev base;
+
+	int  (*tags_alloc)(struct nouveau_ltc *, u32 count,
+	                   struct nouveau_mm_node **);
+	void (*tags_free)(struct nouveau_ltc *, struct nouveau_mm_node **);
+	void (*tags_clear)(struct nouveau_ltc *, u32 first, u32 count);
+
+	int zbc_min;
+	int zbc_max;
+	int (*zbc_color_get)(struct nouveau_ltc *, int index, const u32[4]);
+	int (*zbc_depth_get)(struct nouveau_ltc *, int index, const u32);
+};
+
+static inline struct nouveau_ltc *
+nouveau_ltc(void *obj)
+{
+	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTC];
+}
+
+extern struct nouveau_oclass *gf100_ltc_oclass;
+extern struct nouveau_oclass *gk104_ltc_oclass;
+extern struct nouveau_oclass *gm107_ltc_oclass;
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/mc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/mc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/mc.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,15 +4,11 @@
 #include <core/subdev.h>
 #include <core/device.h>
 
-struct nouveau_mc_intr {
-	u32 stat;
-	u32 unit;
-};
-
 struct nouveau_mc {
 	struct nouveau_subdev base;
 	bool use_msi;
 	unsigned int irq;
+	void (*unk260)(struct nouveau_mc *, u32);
 };
 
 static inline struct nouveau_mc *
@@ -21,30 +17,6 @@ nouveau_mc(void *obj)
 	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
 }
 
-#define nouveau_mc_create(p,e,o,d)                                             \
-	nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_mc_destroy(p) ({                                               \
-	struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
-})
-#define nouveau_mc_init(p) ({                                                  \
-	struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc));        \
-})
-#define nouveau_mc_fini(p,s) ({                                                \
-	struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s));   \
-})
-
-int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
-			struct nouveau_oclass *, int, void **);
-void _nouveau_mc_dtor(struct nouveau_object *);
-int  _nouveau_mc_init(struct nouveau_object *);
-int  _nouveau_mc_fini(struct nouveau_object *, bool);
-
-struct nouveau_mc_oclass {
-	struct nouveau_oclass base;
-	const struct nouveau_mc_intr *intr;
-	void (*msi_rearm)(struct nouveau_mc *);
-};
-
 extern struct nouveau_oclass *nv04_mc_oclass;
 extern struct nouveau_oclass *nv40_mc_oclass;
 extern struct nouveau_oclass *nv44_mc_oclass;
@@ -54,5 +26,6 @@ extern struct nouveau_oclass *nv94_mc_oc
 extern struct nouveau_oclass *nv98_mc_oclass;
 extern struct nouveau_oclass *nvc0_mc_oclass;
 extern struct nouveau_oclass *nvc3_mc_oclass;
+extern struct nouveau_oclass *gk20a_mc_oclass;
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h	2014-09-28 17:29:07.000000000 -0400
@@ -8,18 +8,6 @@ struct nouveau_pwr {
 	struct nouveau_subdev base;
 
 	struct {
-		u32 limit;
-		u32 *data;
-		u32  size;
-	} code;
-
-	struct {
-		u32 limit;
-		u32 *data;
-		u32  size;
-	} data;
-
-	struct {
 		u32 base;
 		u32 size;
 	} send;
@@ -35,7 +23,8 @@ struct nouveau_pwr {
 		u32 data[2];
 	} recv;
 
-	int (*message)(struct nouveau_pwr *, u32[2], u32, u32, u32, u32);
+	int  (*message)(struct nouveau_pwr *, u32[2], u32, u32, u32, u32);
+	void (*pgob)(struct nouveau_pwr *, bool);
 };
 
 static inline struct nouveau_pwr *
@@ -44,29 +33,11 @@ nouveau_pwr(void *obj)
 	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_PWR];
 }
 
-#define nouveau_pwr_create(p, e, o, d)                                         \
-	nouveau_pwr_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_pwr_destroy(p)                                                 \
-	nouveau_subdev_destroy(&(p)->base)
-#define nouveau_pwr_init(p) ({                                                 \
-	struct nouveau_pwr *ppwr = (p);                                        \
-	_nouveau_pwr_init(nv_object(ppwr));                                    \
-})
-#define nouveau_pwr_fini(p,s) ({                                               \
-	struct nouveau_pwr *ppwr = (p);                                        \
-	_nouveau_pwr_fini(nv_object(ppwr), (s));                               \
-})
-
-int nouveau_pwr_create_(struct nouveau_object *, struct nouveau_object *,
-			   struct nouveau_oclass *, int, void **);
-#define _nouveau_pwr_dtor _nouveau_subdev_dtor
-int _nouveau_pwr_init(struct nouveau_object *);
-int _nouveau_pwr_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nva3_pwr_oclass;
-extern struct nouveau_oclass nvc0_pwr_oclass;
-extern struct nouveau_oclass nvd0_pwr_oclass;
-extern struct nouveau_oclass nv108_pwr_oclass;
+extern struct nouveau_oclass *nva3_pwr_oclass;
+extern struct nouveau_oclass *nvc0_pwr_oclass;
+extern struct nouveau_oclass *nvd0_pwr_oclass;
+extern struct nouveau_oclass *gk104_pwr_oclass;
+extern struct nouveau_oclass *nv108_pwr_oclass;
 
 /* interface to MEMX process running on PPWR */
 struct nouveau_memx;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/os.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/os.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/os.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/os.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,8 @@
 #include <linux/interrupt.h>
 #include <linux/log2.h>
 #include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
+#include <linux/clk.h>
 
 #include <asm/unaligned.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,8 +99,13 @@ nouveau_bar_alloc(struct nouveau_bar *ba
 		  struct nouveau_mem *mem, struct nouveau_object **pobject)
 {
 	struct nouveau_object *engine = nv_object(bar);
-	return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass,
-				   mem, 0, pobject);
+	int ret = -ENOMEM;
+	if (bar->iomem) {
+		ret = nouveau_object_ctor(parent, engine,
+					  &nouveau_barobj_oclass,
+					  mem, 0, pobject);
+	}
+	return ret;
 }
 
 int
@@ -118,9 +123,12 @@ nouveau_bar_create_(struct nouveau_objec
 	if (ret)
 		return ret;
 
-	if (nv_device_resource_len(device, 3) != 0)
+	if (nv_device_resource_len(device, 3) != 0) {
 		bar->iomem = ioremap(nv_device_resource_start(device, 3),
 				     nv_device_resource_len(device, 3));
+		if (!bar->iomem)
+			nv_warn(bar, "PRAMIN ioremap failed\n");
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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 <subdev/bar.h>
+
+#include "priv.h"
+
+int
+gk20a_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+	       struct nouveau_oclass *oclass, void *data, u32 size,
+	       struct nouveau_object **pobject)
+{
+	struct nouveau_bar *bar;
+	int ret;
+
+	ret = nvc0_bar_ctor(parent, engine, oclass, data, size, pobject);
+	if (ret)
+		return ret;
+
+	bar = (struct nouveau_bar *)*pobject;
+	bar->iomap_uncached = true;
+
+	return 0;
+}
+
+struct nouveau_oclass
+gk20a_bar_oclass = {
+	.handle = NV_SUBDEV(BAR, 0xea),
+	.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = gk20a_bar_ctor,
+		.dtor = nvc0_bar_dtor,
+		.init = nvc0_bar_init,
+		.fini = _nouveau_bar_fini,
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -133,7 +133,7 @@ nvc0_bar_init_vm(struct nvc0_bar_priv *p
 	return 0;
 }
 
-static int
+int
 nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	      struct nouveau_oclass *oclass, void *data, u32 size,
 	      struct nouveau_object **pobject)
@@ -169,7 +169,7 @@ nvc0_bar_ctor(struct nouveau_object *par
 	return 0;
 }
 
-static void
+void
 nvc0_bar_dtor(struct nouveau_object *object)
 {
 	struct nvc0_bar_priv *priv = (void *)object;
@@ -188,7 +188,7 @@ nvc0_bar_dtor(struct nouveau_object *obj
 	nouveau_bar_destroy(&priv->base);
 }
 
-static int
+int
 nvc0_bar_init(struct nouveau_object *object)
 {
 	struct nvc0_bar_priv *priv = (void *)object;
@@ -200,7 +200,6 @@ nvc0_bar_init(struct nouveau_object *obj
 
 	nv_mask(priv, 0x000200, 0x00000100, 0x00000000);
 	nv_mask(priv, 0x000200, 0x00000100, 0x00000100);
-	nv_mask(priv, 0x100c80, 0x00000001, 0x00000000);
 
 	nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12);
 	if (priv->bar[0].mem)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,4 +23,10 @@ int  nouveau_bar_alloc(struct nouveau_ba
 
 void nv84_bar_flush(struct nouveau_bar *);
 
+int nvc0_bar_ctor(struct nouveau_object *, struct nouveau_object *,
+		  struct nouveau_oclass *, void *, u32,
+		  struct nouveau_object **);
+void nvc0_bar_dtor(struct nouveau_object *);
+int nvc0_bar_init(struct nouveau_object *);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,16 +90,20 @@ nouveau_cstate_prog(struct nouveau_clock
 		cstate = &pstate->base;
 	}
 
-	ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
-	if (ret && ret != -ENODEV) {
-		nv_error(clk, "failed to raise fan speed: %d\n", ret);
-		return ret;
+	if (ptherm) {
+		ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
+		if (ret && ret != -ENODEV) {
+			nv_error(clk, "failed to raise fan speed: %d\n", ret);
+			return ret;
+		}
 	}
 
-	ret = volt->set_id(volt, cstate->voltage, +1);
-	if (ret && ret != -ENODEV) {
-		nv_error(clk, "failed to raise voltage: %d\n", ret);
-		return ret;
+	if (volt) {
+		ret = volt->set_id(volt, cstate->voltage, +1);
+		if (ret && ret != -ENODEV) {
+			nv_error(clk, "failed to raise voltage: %d\n", ret);
+			return ret;
+		}
 	}
 
 	ret = clk->calc(clk, cstate);
@@ -108,13 +112,17 @@ nouveau_cstate_prog(struct nouveau_clock
 		clk->tidy(clk);
 	}
 
-	ret = volt->set_id(volt, cstate->voltage, -1);
-	if (ret && ret != -ENODEV)
-		nv_error(clk, "failed to lower voltage: %d\n", ret);
+	if (volt) {
+		ret = volt->set_id(volt, cstate->voltage, -1);
+		if (ret && ret != -ENODEV)
+			nv_error(clk, "failed to lower voltage: %d\n", ret);
+	}
 
-	ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
-	if (ret && ret != -ENODEV)
-		nv_error(clk, "failed to lower fan speed: %d\n", ret);
+	if (ptherm) {
+		ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
+		if (ret && ret != -ENODEV)
+			nv_error(clk, "failed to lower fan speed: %d\n", ret);
+	}
 
 	return 0;
 }
@@ -194,16 +202,23 @@ nouveau_pstate_prog(struct nouveau_clock
 	return nouveau_cstate_prog(clk, pstate, 0);
 }
 
-static int
-nouveau_pstate_calc(struct nouveau_clock *clk)
+static void
+nouveau_pstate_work(struct work_struct *work)
 {
-	int pstate, ret = 0;
+	struct nouveau_clock *clk = container_of(work, typeof(*clk), work);
+	int pstate;
 
-	nv_trace(clk, "P %d U %d A %d T %d D %d\n", clk->pstate,
-		 clk->ustate, clk->astate, clk->tstate, clk->dstate);
+	if (!atomic_xchg(&clk->waiting, 0))
+		return;
+	clk->pwrsrc = power_supply_is_system_supplied();
 
-	if (clk->state_nr && clk->ustate != -1) {
-		pstate = (clk->ustate < 0) ? clk->astate : clk->ustate;
+	nv_trace(clk, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
+		 clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
+		 clk->astate, clk->tstate, 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 = max(pstate, clk->dstate);
 	} else {
@@ -211,9 +226,26 @@ nouveau_pstate_calc(struct nouveau_clock
 	}
 
 	nv_trace(clk, "-> %d\n", pstate);
-	if (pstate != clk->pstate)
-		ret = nouveau_pstate_prog(clk, pstate);
-	return ret;
+	if (pstate != clk->pstate) {
+		int ret = nouveau_pstate_prog(clk, pstate);
+		if (ret) {
+			nv_error(clk, "error setting pstate %d: %d\n",
+				 pstate, ret);
+		}
+	}
+
+	wake_up_all(&clk->wait);
+	nvkm_notify_get(&clk->pwrsrc_ntfy);
+}
+
+static int
+nouveau_pstate_calc(struct nouveau_clock *clk, bool wait)
+{
+	atomic_set(&clk->waiting, 1);
+	schedule_work(&clk->work);
+	if (wait)
+		wait_event(clk->wait, !atomic_read(&clk->waiting));
+	return 0;
 }
 
 static void
@@ -361,17 +393,40 @@ nouveau_clock_ustate_update(struct nouve
 		req = i;
 	}
 
-	clk->ustate = req;
-	return 0;
+	return req + 2;
+}
+
+static int
+nouveau_clock_nstate(struct nouveau_clock *clk, const char *mode, int arglen)
+{
+	int ret = 1;
+
+	if (strncasecmpz(mode, "disabled", arglen)) {
+		char save = mode[arglen];
+		long v;
+
+		((char *)mode)[arglen] = '\0';
+		if (!kstrtol(mode, 0, &v)) {
+			ret = nouveau_clock_ustate_update(clk, v);
+			if (ret < 0)
+				ret = 1;
+		}
+		((char *)mode)[arglen] = save;
+	}
+
+	return ret - 2;
 }
 
 int
-nouveau_clock_ustate(struct nouveau_clock *clk, int req)
+nouveau_clock_ustate(struct nouveau_clock *clk, int req, int pwr)
 {
 	int ret = nouveau_clock_ustate_update(clk, req);
-	if (ret)
-		return ret;
-	return nouveau_pstate_calc(clk);
+	if (ret >= 0) {
+		if (ret -= 2, pwr) clk->ustate_ac = ret;
+		else		   clk->ustate_dc = ret;
+		return nouveau_pstate_calc(clk, true);
+	}
+	return ret;
 }
 
 int
@@ -381,7 +436,7 @@ nouveau_clock_astate(struct nouveau_cloc
 	if ( rel) clk->astate += rel;
 	clk->astate = min(clk->astate, clk->state_nr - 1);
 	clk->astate = max(clk->astate, 0);
-	return nouveau_pstate_calc(clk);
+	return nouveau_pstate_calc(clk, true);
 }
 
 int
@@ -391,7 +446,7 @@ nouveau_clock_tstate(struct nouveau_cloc
 	if ( rel) clk->tstate += rel;
 	clk->tstate = min(clk->tstate, 0);
 	clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
-	return nouveau_pstate_calc(clk);
+	return nouveau_pstate_calc(clk, true);
 }
 
 int
@@ -401,12 +456,30 @@ nouveau_clock_dstate(struct nouveau_cloc
 	if ( rel) clk->dstate += rel;
 	clk->dstate = min(clk->dstate, clk->state_nr - 1);
 	clk->dstate = max(clk->dstate, 0);
-	return nouveau_pstate_calc(clk);
+	return nouveau_pstate_calc(clk, true);
+}
+
+static int
+nouveau_clock_pwrsrc(struct nvkm_notify *notify)
+{
+	struct nouveau_clock *clk =
+		container_of(notify, typeof(*clk), pwrsrc_ntfy);
+	nouveau_pstate_calc(clk, false);
+	return NVKM_NOTIFY_DROP;
 }
 
 /******************************************************************************
  * subdev base class implementation
  *****************************************************************************/
+
+int
+_nouveau_clock_fini(struct nouveau_object *object, bool suspend)
+{
+	struct nouveau_clock *clk = (void *)object;
+	nvkm_notify_put(&clk->pwrsrc_ntfy);
+	return nouveau_subdev_fini(&clk->base, suspend);
+}
+
 int
 _nouveau_clock_init(struct nouveau_object *object)
 {
@@ -414,6 +487,10 @@ _nouveau_clock_init(struct nouveau_objec
 	struct nouveau_clocks *clock = clk->domains;
 	int ret;
 
+	ret = nouveau_subdev_init(&clk->base);
+	if (ret)
+		return ret;
+
 	memset(&clk->bstate, 0x00, sizeof(clk->bstate));
 	INIT_LIST_HEAD(&clk->bstate.list);
 	clk->bstate.pstate = 0xff;
@@ -434,7 +511,7 @@ _nouveau_clock_init(struct nouveau_objec
 	clk->tstate = 0;
 	clk->dstate = 0;
 	clk->pstate = -1;
-	nouveau_pstate_calc(clk);
+	nouveau_pstate_calc(clk, true);
 	return 0;
 }
 
@@ -444,6 +521,8 @@ _nouveau_clock_dtor(struct nouveau_objec
 	struct nouveau_clock *clk = (void *)object;
 	struct nouveau_pstate *pstate, *temp;
 
+	nvkm_notify_fini(&clk->pwrsrc_ntfy);
+
 	list_for_each_entry_safe(pstate, temp, &clk->states, head) {
 		nouveau_pstate_del(pstate);
 	}
@@ -456,6 +535,7 @@ nouveau_clock_create_(struct nouveau_obj
 		      struct nouveau_object *engine,
 		      struct nouveau_oclass *oclass,
 		      struct nouveau_clocks *clocks,
+		      struct nouveau_pstate *pstates, int nb_pstates,
 		      bool allow_reclock,
 		      int length, void **object)
 {
@@ -472,29 +552,46 @@ nouveau_clock_create_(struct nouveau_obj
 
 	INIT_LIST_HEAD(&clk->states);
 	clk->domains = clocks;
-	clk->ustate = -1;
+	clk->ustate_ac = -1;
+	clk->ustate_dc = -1;
 
-	idx = 0;
-	do {
-		ret = nouveau_pstate_new(clk, idx++);
-	} while (ret == 0);
+	INIT_WORK(&clk->work, nouveau_pstate_work);
+	init_waitqueue_head(&clk->wait);
+	atomic_set(&clk->waiting, 0);
+
+	/* If no pstates are provided, try and fetch them from the BIOS */
+	if (!pstates) {
+		idx = 0;
+		do {
+			ret = nouveau_pstate_new(clk, idx++);
+		} while (ret == 0);
+	} else {
+		for (idx = 0; idx < nb_pstates; idx++)
+			list_add_tail(&pstates[idx].head, &clk->states);
+		clk->state_nr = nb_pstates;
+	}
 
 	clk->allow_reclock = allow_reclock;
 
+	ret = nvkm_notify_init(&device->event, nouveau_clock_pwrsrc, true,
+			       NULL, 0, 0, &clk->pwrsrc_ntfy);
+	if (ret)
+		return ret;
+
 	mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
 	if (mode) {
-		if (!strncasecmpz(mode, "disabled", arglen)) {
-			clk->ustate = -1;
-		} else {
-			char save = mode[arglen];
-			long v;
-
-			((char *)mode)[arglen] = '\0';
-			if (!kstrtol(mode, 0, &v))
-				nouveau_clock_ustate_update(clk, v);
-			((char *)mode)[arglen] = save;
-		}
+		clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
+		clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
 	}
 
+	mode = nouveau_stropt(device->cfgopt, "NvClkModeAC", &arglen);
+	if (mode)
+		clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
+
+	mode = nouveau_stropt(device->cfgopt, "NvClkModeDC", &arglen);
+	if (mode)
+		clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
+
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2014, 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.
+ *
+ * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c
+ *
+ */
+
+#define MHZ (1000 * 1000)
+
+#define MASK(w)	((1 << w) - 1)
+
+#define SYS_GPCPLL_CFG_BASE			0x00137000
+#define GPC_BCASE_GPCPLL_CFG_BASE		0x00132800
+
+#define GPCPLL_CFG		(SYS_GPCPLL_CFG_BASE + 0)
+#define GPCPLL_CFG_ENABLE	BIT(0)
+#define GPCPLL_CFG_IDDQ		BIT(1)
+#define GPCPLL_CFG_LOCK_DET_OFF	BIT(4)
+#define GPCPLL_CFG_LOCK		BIT(17)
+
+#define GPCPLL_COEFF		(SYS_GPCPLL_CFG_BASE + 4)
+#define GPCPLL_COEFF_M_SHIFT	0
+#define GPCPLL_COEFF_M_WIDTH	8
+#define GPCPLL_COEFF_N_SHIFT	8
+#define GPCPLL_COEFF_N_WIDTH	8
+#define GPCPLL_COEFF_P_SHIFT	16
+#define GPCPLL_COEFF_P_WIDTH	6
+
+#define GPCPLL_CFG2			(SYS_GPCPLL_CFG_BASE + 0xc)
+#define GPCPLL_CFG2_SETUP2_SHIFT	16
+#define GPCPLL_CFG2_PLL_STEPA_SHIFT	24
+
+#define GPCPLL_CFG3			(SYS_GPCPLL_CFG_BASE + 0x18)
+#define GPCPLL_CFG3_PLL_STEPB_SHIFT	16
+
+#define GPCPLL_NDIV_SLOWDOWN			(SYS_GPCPLL_CFG_BASE + 0x1c)
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT	0
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT	8
+#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT	16
+#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT	22
+#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT	31
+
+#define SEL_VCO				(SYS_GPCPLL_CFG_BASE + 0x100)
+#define SEL_VCO_GPC2CLK_OUT_SHIFT	0
+
+#define GPC2CLK_OUT			(SYS_GPCPLL_CFG_BASE + 0x250)
+#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH	1
+#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT	31
+#define GPC2CLK_OUT_SDIV14_INDIV4_MODE	1
+#define GPC2CLK_OUT_VCODIV_WIDTH	6
+#define GPC2CLK_OUT_VCODIV_SHIFT	8
+#define GPC2CLK_OUT_VCODIV1		0
+#define GPC2CLK_OUT_VCODIV_MASK		(MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \
+					GPC2CLK_OUT_VCODIV_SHIFT)
+#define	GPC2CLK_OUT_BYPDIV_WIDTH	6
+#define GPC2CLK_OUT_BYPDIV_SHIFT	0
+#define GPC2CLK_OUT_BYPDIV31		0x3c
+#define GPC2CLK_OUT_INIT_MASK	((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \
+		GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\
+		| (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\
+		| (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT))
+#define GPC2CLK_OUT_INIT_VAL	((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \
+		GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \
+		| (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \
+		| (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT))
+
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG	(GPC_BCASE_GPCPLL_CFG_BASE + 0xa0)
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT	24
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
+	    (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
+
+#include <subdev/clock.h>
+#include <subdev/timer.h>
+
+#ifdef __KERNEL__
+#include <nouveau_platform.h>
+#endif
+
+static const u8 pl_to_div[] = {
+/* PL:   0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
+/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
+};
+
+/* All frequencies in Mhz */
+struct gk20a_clk_pllg_params {
+	u32 min_vco, max_vco;
+	u32 min_u, max_u;
+	u32 min_m, max_m;
+	u32 min_n, max_n;
+	u32 min_pl, max_pl;
+};
+
+static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
+	.min_vco = 1000, .max_vco = 1700,
+	.min_u = 12, .max_u = 38,
+	.min_m = 1, .max_m = 255,
+	.min_n = 8, .max_n = 255,
+	.min_pl = 1, .max_pl = 32,
+};
+
+struct gk20a_clock_priv {
+	struct nouveau_clock base;
+	const struct gk20a_clk_pllg_params *params;
+	u32 m, n, pl;
+	u32 parent_rate;
+};
+#define to_gk20a_clock(base) container_of(base, struct gk20a_clock_priv, base)
+
+static void
+gk20a_pllg_read_mnp(struct gk20a_clock_priv *priv)
+{
+	u32 val;
+
+	val = nv_rd32(priv, GPCPLL_COEFF);
+	priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+	priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH);
+	priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+}
+
+static u32
+gk20a_pllg_calc_rate(struct gk20a_clock_priv *priv)
+{
+	u32 rate;
+	u32 divider;
+
+	rate = priv->parent_rate * priv->n;
+	divider = priv->m * pl_to_div[priv->pl];
+	do_div(rate, divider);
+
+	return rate / 2;
+}
+
+static int
+gk20a_pllg_calc_mnp(struct gk20a_clock_priv *priv, unsigned long rate)
+{
+	u32 target_clk_f, ref_clk_f, target_freq;
+	u32 min_vco_f, max_vco_f;
+	u32 low_pl, high_pl, best_pl;
+	u32 target_vco_f, vco_f;
+	u32 best_m, best_n;
+	u32 u_f;
+	u32 m, n, n2;
+	u32 delta, lwv, best_delta = ~0;
+	u32 pl;
+
+	target_clk_f = rate * 2 / MHZ;
+	ref_clk_f = priv->parent_rate / MHZ;
+
+	max_vco_f = priv->params->max_vco;
+	min_vco_f = priv->params->min_vco;
+	best_m = priv->params->max_m;
+	best_n = priv->params->min_n;
+	best_pl = priv->params->min_pl;
+
+	target_vco_f = target_clk_f + target_clk_f / 50;
+	if (max_vco_f < target_vco_f)
+		max_vco_f = target_vco_f;
+
+	/* min_pl <= high_pl <= max_pl */
+	high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
+	high_pl = min(high_pl, priv->params->max_pl);
+	high_pl = max(high_pl, priv->params->min_pl);
+
+	/* min_pl <= low_pl <= max_pl */
+	low_pl = min_vco_f / target_vco_f;
+	low_pl = min(low_pl, priv->params->max_pl);
+	low_pl = max(low_pl, priv->params->min_pl);
+
+	/* Find Indices of high_pl and low_pl */
+	for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+		if (pl_to_div[pl] >= low_pl) {
+			low_pl = pl;
+			break;
+		}
+	}
+	for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+		if (pl_to_div[pl] >= high_pl) {
+			high_pl = pl;
+			break;
+		}
+	}
+
+	nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
+		 pl_to_div[low_pl], high_pl, pl_to_div[high_pl]);
+
+	/* Select lowest possible VCO */
+	for (pl = low_pl; pl <= high_pl; pl++) {
+		target_vco_f = target_clk_f * pl_to_div[pl];
+		for (m = priv->params->min_m; m <= priv->params->max_m; m++) {
+			u_f = ref_clk_f / m;
+
+			if (u_f < priv->params->min_u)
+				break;
+			if (u_f > priv->params->max_u)
+				continue;
+
+			n = (target_vco_f * m) / ref_clk_f;
+			n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
+
+			if (n > priv->params->max_n)
+				break;
+
+			for (; n <= n2; n++) {
+				if (n < priv->params->min_n)
+					continue;
+				if (n > priv->params->max_n)
+					break;
+
+				vco_f = ref_clk_f * n / m;
+
+				if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
+					lwv = (vco_f + (pl_to_div[pl] / 2))
+						/ pl_to_div[pl];
+					delta = abs(lwv - target_clk_f);
+
+					if (delta < best_delta) {
+						best_delta = delta;
+						best_m = m;
+						best_n = n;
+						best_pl = pl;
+
+						if (best_delta == 0)
+							goto found_match;
+					}
+				}
+			}
+		}
+	}
+
+found_match:
+	WARN_ON(best_delta == ~0);
+
+	if (best_delta != 0)
+		nv_debug(priv, "no best match for target @ %dMHz on gpc_pll",
+			 target_clk_f);
+
+	priv->m = best_m;
+	priv->n = best_n;
+	priv->pl = best_pl;
+
+	target_freq = gk20a_pllg_calc_rate(priv) / MHZ;
+
+	nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
+		 target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]);
+
+	return 0;
+}
+
+static int
+gk20a_pllg_slide(struct gk20a_clock_priv *priv, u32 n)
+{
+	u32 val;
+	int ramp_timeout;
+
+	/* get old coefficients */
+	val = nv_rd32(priv, GPCPLL_COEFF);
+	/* do nothing if NDIV is the same */
+	if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH)))
+		return 0;
+
+	/* setup */
+	nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
+		0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
+	nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
+		0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
+
+	/* pll slowdown mode */
+	nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+		BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
+		BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
+
+	/* new ndiv ready for ramp */
+	val = nv_rd32(priv, GPCPLL_COEFF);
+	val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT);
+	val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
+	udelay(1);
+	nv_wr32(priv, GPCPLL_COEFF, val);
+
+	/* dynamic ramp to new ndiv */
+	val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+	val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT;
+	udelay(1);
+	nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val);
+
+	for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) {
+		udelay(1);
+		val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG);
+		if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK)
+			break;
+	}
+
+	/* exit slowdown mode */
+	nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+		BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
+		BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
+	nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+
+	if (ramp_timeout <= 0) {
+		nv_error(priv, "gpcpll dynamic ramp timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static void
+_gk20a_pllg_enable(struct gk20a_clock_priv *priv)
+{
+	nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
+	nv_rd32(priv, GPCPLL_CFG);
+}
+
+static void
+_gk20a_pllg_disable(struct gk20a_clock_priv *priv)
+{
+	nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
+	nv_rd32(priv, GPCPLL_CFG);
+}
+
+static int
+_gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv, bool allow_slide)
+{
+	u32 val, cfg;
+	u32 m_old, pl_old, n_lo;
+
+	/* get old coefficients */
+	val = nv_rd32(priv, GPCPLL_COEFF);
+	m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+	pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+
+	/* do NDIV slide if there is no change in M and PL */
+	cfg = nv_rd32(priv, GPCPLL_CFG);
+	if (allow_slide && priv->m == m_old && priv->pl == pl_old &&
+	    (cfg & GPCPLL_CFG_ENABLE)) {
+		return gk20a_pllg_slide(priv, priv->n);
+	}
+
+	/* slide down to NDIV_LO */
+	n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco,
+			    priv->parent_rate / MHZ);
+	if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) {
+		int ret = gk20a_pllg_slide(priv, n_lo);
+
+		if (ret)
+			return ret;
+	}
+
+	/* split FO-to-bypass jump in halfs by setting out divider 1:2 */
+	nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
+		0x2 << GPC2CLK_OUT_VCODIV_SHIFT);
+
+	/* put PLL in bypass before programming it */
+	val = nv_rd32(priv, SEL_VCO);
+	val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+	udelay(2);
+	nv_wr32(priv, SEL_VCO, val);
+
+	/* get out from IDDQ */
+	val = nv_rd32(priv, GPCPLL_CFG);
+	if (val & GPCPLL_CFG_IDDQ) {
+		val &= ~GPCPLL_CFG_IDDQ;
+		nv_wr32(priv, GPCPLL_CFG, val);
+		nv_rd32(priv, GPCPLL_CFG);
+		udelay(2);
+	}
+
+	_gk20a_pllg_disable(priv);
+
+	nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n,
+		 priv->pl);
+
+	n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco,
+			    priv->parent_rate / MHZ);
+	val = priv->m << GPCPLL_COEFF_M_SHIFT;
+	val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT;
+	val |= priv->pl << GPCPLL_COEFF_P_SHIFT;
+	nv_wr32(priv, GPCPLL_COEFF, val);
+
+	_gk20a_pllg_enable(priv);
+
+	val = nv_rd32(priv, GPCPLL_CFG);
+	if (val & GPCPLL_CFG_LOCK_DET_OFF) {
+		val &= ~GPCPLL_CFG_LOCK_DET_OFF;
+		nv_wr32(priv, GPCPLL_CFG, val);
+	}
+
+	if (!nouveau_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK,
+				   GPCPLL_CFG_LOCK)) {
+		nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	/* switch to VCO mode */
+	nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+
+	/* restore out divider 1:1 */
+	val = nv_rd32(priv, GPC2CLK_OUT);
+	val &= ~GPC2CLK_OUT_VCODIV_MASK;
+	udelay(2);
+	nv_wr32(priv, GPC2CLK_OUT, val);
+
+	/* slide up to new NDIV */
+	return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0;
+}
+
+static int
+gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv)
+{
+	int err;
+
+	err = _gk20a_pllg_program_mnp(priv, true);
+	if (err)
+		err = _gk20a_pllg_program_mnp(priv, false);
+
+	return err;
+}
+
+static void
+gk20a_pllg_disable(struct gk20a_clock_priv *priv)
+{
+	u32 val;
+
+	/* slide to VCO min */
+	val = nv_rd32(priv, GPCPLL_CFG);
+	if (val & GPCPLL_CFG_ENABLE) {
+		u32 coeff, m, n_lo;
+
+		coeff = nv_rd32(priv, GPCPLL_COEFF);
+		m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+		n_lo = DIV_ROUND_UP(m * priv->params->min_vco,
+				    priv->parent_rate / MHZ);
+		gk20a_pllg_slide(priv, n_lo);
+	}
+
+	/* put PLL in bypass before disabling it */
+	nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
+
+	_gk20a_pllg_disable(priv);
+}
+
+#define GK20A_CLK_GPC_MDIV 1000
+
+static struct nouveau_clocks
+gk20a_domains[] = {
+	{ nv_clk_src_crystal, 0xff },
+	{ nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
+	{ nv_clk_src_max }
+};
+
+static struct nouveau_pstate
+gk20a_pstates[] = {
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 72000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 108000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 180000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 252000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 324000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 396000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 468000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 540000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 612000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 648000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 684000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 708000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 756000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 804000,
+		},
+	},
+	{
+		.base = {
+			.domain[nv_clk_src_gpc] = 852000,
+		},
+	},
+};
+
+static int
+gk20a_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
+{
+	struct gk20a_clock_priv *priv = (void *)clk;
+
+	switch (src) {
+	case nv_clk_src_crystal:
+		return nv_device(clk)->crystal;
+	case nv_clk_src_gpc:
+		gk20a_pllg_read_mnp(priv);
+		return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV;
+	default:
+		nv_error(clk, "invalid clock source %d\n", src);
+		return -EINVAL;
+	}
+}
+
+static int
+gk20a_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
+{
+	struct gk20a_clock_priv *priv = (void *)clk;
+
+	return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] *
+					 GK20A_CLK_GPC_MDIV);
+}
+
+static int
+gk20a_clock_prog(struct nouveau_clock *clk)
+{
+	struct gk20a_clock_priv *priv = (void *)clk;
+
+	return gk20a_pllg_program_mnp(priv);
+}
+
+static void
+gk20a_clock_tidy(struct nouveau_clock *clk)
+{
+}
+
+static int
+gk20a_clock_fini(struct nouveau_object *object, bool suspend)
+{
+	struct gk20a_clock_priv *priv = (void *)object;
+	int ret;
+
+	ret = nouveau_clock_fini(&priv->base, false);
+
+	gk20a_pllg_disable(priv);
+
+	return ret;
+}
+
+static int
+gk20a_clock_init(struct nouveau_object *object)
+{
+	struct gk20a_clock_priv *priv = (void *)object;
+	int ret;
+
+	nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL);
+
+	ret = nouveau_clock_init(&priv->base);
+	if (ret)
+		return ret;
+
+	ret = gk20a_clock_prog(&priv->base);
+	if (ret) {
+		nv_error(priv, "cannot initialize clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+gk20a_clock_ctor(struct nouveau_object *parent,  struct nouveau_object *engine,
+		 struct nouveau_oclass *oclass, void *data, u32 size,
+		 struct nouveau_object **pobject)
+{
+	struct gk20a_clock_priv *priv;
+	struct nouveau_platform_device *plat;
+	int ret;
+	int i;
+
+	/* Finish initializing the pstates */
+	for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) {
+		INIT_LIST_HEAD(&gk20a_pstates[i].list);
+		gk20a_pstates[i].pstate = i + 1;
+	}
+
+	ret = nouveau_clock_create(parent, engine, oclass, gk20a_domains,
+			gk20a_pstates, ARRAY_SIZE(gk20a_pstates), true, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	priv->params = &gk20a_pllg_params;
+
+	plat = nv_device_to_platform(nv_device(parent));
+	priv->parent_rate = clk_get_rate(plat->gpu->clk);
+	nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ);
+
+	priv->base.read = gk20a_clock_read;
+	priv->base.calc = gk20a_clock_calc;
+	priv->base.prog = gk20a_clock_prog;
+	priv->base.tidy = gk20a_clock_tidy;
+
+	return 0;
+}
+
+struct nouveau_oclass
+gk20a_clock_oclass = {
+	.handle = NV_SUBDEV(CLOCK, 0xea),
+	.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = gk20a_clock_ctor,
+		.dtor = _nouveau_subdev_dtor,
+		.init = gk20a_clock_init,
+		.fini = gk20a_clock_fini,
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,8 +82,8 @@ nv04_clock_ctor(struct nouveau_object *p
 	struct nv04_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, NULL, 0,
+				   false, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c	2014-09-28 17:29:07.000000000 -0400
@@ -213,8 +213,8 @@ nv40_clock_ctor(struct nouveau_object *p
 	struct nv40_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, NULL, 0,
+				   true, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *p
 	int ret;
 
 	ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
-				   false, &priv);
+				   NULL, 0, false, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -302,8 +302,8 @@ nva3_clock_ctor(struct nouveau_object *p
 	struct nva3_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, NULL, 0,
+				   false, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c	2014-09-28 17:29:07.000000000 -0400
@@ -421,8 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *p
 	struct nvaa_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, NULL,
+				   0, true, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -437,8 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *p
 	struct nvc0_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, NULL, 0,
+				   false, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c	2014-09-28 17:29:07.000000000 -0400
@@ -475,8 +475,8 @@ nve0_clock_ctor(struct nouveau_object *p
 	struct nve0_clock_priv *priv;
 	int ret;
 
-	ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
-				   &priv);
+	ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, NULL, 0,
+				   true, &priv);
 	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c	2014-09-28 17:29:07.000000000 -0400
@@ -250,9 +250,11 @@ nv50_fb_ctor(struct nouveau_object *pare
 
 	priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
 	if (priv->r100c08_page) {
-		priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
-		if (!priv->r100c08)
-			nv_warn(priv, "failed 0x100c08 page map\n");
+		priv->r100c08 = dma_map_page(nv_device_base(device),
+					     priv->r100c08_page, 0, PAGE_SIZE,
+					     DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(nv_device_base(device), priv->r100c08))
+			return -EFAULT;
 	} else {
 		nv_warn(priv, "failed 0x100c08 page alloc\n");
 	}
@@ -268,7 +270,8 @@ nv50_fb_dtor(struct nouveau_object *obje
 	struct nv50_fb_priv *priv = (void *)object;
 
 	if (priv->r100c08_page) {
-		nv_device_unmap_page(device, priv->r100c08);
+		dma_unmap_page(nv_device_base(device), priv->r100c08, PAGE_SIZE,
+			       DMA_BIDIRECTIONAL);
 		__free_page(priv->r100c08_page);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,6 +60,7 @@ nvc0_fb_init(struct nouveau_object *obje
 
 	if (priv->r100c10_page)
 		nv_wr32(priv, 0x100c10, priv->r100c10 >> 8);
+	nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
 	return 0;
 }
 
@@ -70,7 +71,8 @@ nvc0_fb_dtor(struct nouveau_object *obje
 	struct nvc0_fb_priv *priv = (void *)object;
 
 	if (priv->r100c10_page) {
-		nv_device_unmap_page(device, priv->r100c10);
+		dma_unmap_page(nv_device_base(device), priv->r100c10, PAGE_SIZE,
+			       DMA_BIDIRECTIONAL);
 		__free_page(priv->r100c10_page);
 	}
 
@@ -93,8 +95,10 @@ nvc0_fb_ctor(struct nouveau_object *pare
 
 	priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
 	if (priv->r100c10_page) {
-		priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
-		if (!priv->r100c10)
+		priv->r100c10 = dma_map_page(nv_device_base(device),
+					     priv->r100c10_page, 0, PAGE_SIZE,
+					     DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(nv_device_base(device), priv->r100c10))
 			return -EFAULT;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 #include <subdev/bios/pll.h>
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
 
 #include <subdev/clock.h>
 #include <subdev/clock/pll.h>
@@ -425,7 +425,7 @@ extern const u8 nvc0_pte_storage_type_ma
 void
 nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
 {
-	struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
+	struct nouveau_ltc *ltc = nouveau_ltc(pfb);
 	struct nouveau_mem *mem = *pmem;
 
 	*pmem = NULL;
@@ -434,7 +434,7 @@ nvc0_ram_put(struct nouveau_fb *pfb, str
 
 	mutex_lock(&pfb->base.mutex);
 	if (mem->tag)
-		ltcg->tags_free(ltcg, &mem->tag);
+		ltc->tags_free(ltc, &mem->tag);
 	__nv50_ram_put(pfb, mem);
 	mutex_unlock(&pfb->base.mutex);
 
@@ -468,12 +468,12 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64
 
 	mutex_lock(&pfb->base.mutex);
 	if (comp) {
-		struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
+		struct nouveau_ltc *ltc = nouveau_ltc(pfb);
 
 		/* compression only works with lpages */
 		if (align == (1 << (17 - 12))) {
 			int n = size >> 5;
-			ltcg->tags_alloc(ltcg, n, &mem->tag);
+			ltc->tags_alloc(ltc, n, &mem->tag);
 		}
 
 		if (unlikely(!mem->tag))
@@ -554,13 +554,13 @@ nvc0_ram_create_(struct nouveau_object *
 	} else {
 		/* otherwise, address lowest common amount from 0GiB */
 		ret = nouveau_mm_init(&pfb->vram, rsvd_head,
-				      (bsize << 8) * parts, 1);
+				      (bsize << 8) * parts - rsvd_head, 1);
 		if (ret)
 			return ret;
 
 		/* and the rest starting from (8GiB + common_size) */
 		offset = (0x0200000000ULL >> 12) + (bsize << 8);
-		length = (ram->size >> 12) - (bsize << 8) - rsvd_tail;
+		length = (ram->size >> 12) - ((bsize * parts) << 8) - rsvd_tail;
 
 		ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
 		if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,39 +106,59 @@ nouveau_gpio_get(struct nouveau_gpio *gp
 }
 
 static void
-nouveau_gpio_intr_disable(struct nouveau_event *event, int type, int index)
+nouveau_gpio_intr_fini(struct nvkm_event *event, int type, int index)
 {
-	struct nouveau_gpio *gpio = nouveau_gpio(event->priv);
+	struct nouveau_gpio *gpio = container_of(event, typeof(*gpio), event);
 	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
 	impl->intr_mask(gpio, type, 1 << index, 0);
 }
 
 static void
-nouveau_gpio_intr_enable(struct nouveau_event *event, int type, int index)
+nouveau_gpio_intr_init(struct nvkm_event *event, int type, int index)
 {
-	struct nouveau_gpio *gpio = nouveau_gpio(event->priv);
+	struct nouveau_gpio *gpio = container_of(event, typeof(*gpio), event);
 	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
 	impl->intr_mask(gpio, type, 1 << index, 1 << index);
 }
 
+static int
+nouveau_gpio_intr_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	struct nvkm_gpio_ntfy_req *req = data;
+	if (!WARN_ON(size != sizeof(*req))) {
+		notify->size  = sizeof(struct nvkm_gpio_ntfy_rep);
+		notify->types = req->mask;
+		notify->index = req->line;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static void
 nouveau_gpio_intr(struct nouveau_subdev *subdev)
 {
 	struct nouveau_gpio *gpio = nouveau_gpio(subdev);
 	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
-	u32 hi, lo, e, i;
+	u32 hi, lo, i;
 
 	impl->intr_stat(gpio, &hi, &lo);
 
-	for (i = 0; e = 0, (hi | lo) && i < impl->lines; i++) {
-		if (hi & (1 << i))
-			e |= NVKM_GPIO_HI;
-		if (lo & (1 << i))
-			e |= NVKM_GPIO_LO;
-		nouveau_event_trigger(gpio->events, e, i);
+	for (i = 0; (hi | lo) && i < impl->lines; i++) {
+		struct nvkm_gpio_ntfy_rep rep = {
+			.mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
+				(NVKM_GPIO_LO * !!(lo & (1 << i))),
+		};
+		nvkm_event_send(&gpio->event, rep.mask, i, &rep, sizeof(rep));
 	}
 }
 
+static const struct nvkm_event_func
+nouveau_gpio_intr_func = {
+	.ctor = nouveau_gpio_intr_ctor,
+	.init = nouveau_gpio_intr_init,
+	.fini = nouveau_gpio_intr_fini,
+};
+
 int
 _nouveau_gpio_fini(struct nouveau_object *object, bool suspend)
 {
@@ -183,7 +203,7 @@ void
 _nouveau_gpio_dtor(struct nouveau_object *object)
 {
 	struct nouveau_gpio *gpio = (void *)object;
-	nouveau_event_destroy(&gpio->events);
+	nvkm_event_fini(&gpio->event);
 	nouveau_subdev_destroy(&gpio->base);
 }
 
@@ -208,13 +228,11 @@ nouveau_gpio_create_(struct nouveau_obje
 	gpio->get  = nouveau_gpio_get;
 	gpio->reset = impl->reset;
 
-	ret = nouveau_event_create(2, impl->lines, &gpio->events);
+	ret = nvkm_event_init(&nouveau_gpio_intr_func, 2, impl->lines,
+			      &gpio->event);
 	if (ret)
 		return ret;
 
-	gpio->events->priv = gpio;
-	gpio->events->enable = nouveau_gpio_intr_enable;
-	gpio->events->disable = nouveau_gpio_intr_disable;
 	nv_subdev(gpio)->intr = nouveau_gpio_intr;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -326,9 +326,9 @@ nouveau_i2c_identify(struct nouveau_i2c
 }
 
 static void
-nouveau_i2c_intr_disable(struct nouveau_event *event, int type, int index)
+nouveau_i2c_intr_fini(struct nvkm_event *event, int type, int index)
 {
-	struct nouveau_i2c *i2c = nouveau_i2c(event->priv);
+	struct nouveau_i2c *i2c = container_of(event, typeof(*i2c), event);
 	struct nouveau_i2c_port *port = i2c->find(i2c, index);
 	const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass;
 	if (port && port->aux >= 0)
@@ -336,15 +336,28 @@ nouveau_i2c_intr_disable(struct nouveau_
 }
 
 static void
-nouveau_i2c_intr_enable(struct nouveau_event *event, int type, int index)
+nouveau_i2c_intr_init(struct nvkm_event *event, int type, int index)
 {
-	struct nouveau_i2c *i2c = nouveau_i2c(event->priv);
+	struct nouveau_i2c *i2c = container_of(event, typeof(*i2c), event);
 	struct nouveau_i2c_port *port = i2c->find(i2c, index);
 	const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass;
 	if (port && port->aux >= 0)
 		impl->aux_mask(i2c, type, 1 << port->aux, 1 << port->aux);
 }
 
+static int
+nouveau_i2c_intr_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+	struct nvkm_i2c_ntfy_req *req = data;
+	if (!WARN_ON(size != sizeof(*req))) {
+		notify->size  = sizeof(struct nvkm_i2c_ntfy_rep);
+		notify->types = req->mask;
+		notify->index = req->port;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static void
 nouveau_i2c_intr(struct nouveau_subdev *subdev)
 {
@@ -364,13 +377,26 @@ nouveau_i2c_intr(struct nouveau_subdev *
 				if (lo & (1 << port->aux)) e |= NVKM_I2C_UNPLUG;
 				if (rq & (1 << port->aux)) e |= NVKM_I2C_IRQ;
 				if (tx & (1 << port->aux)) e |= NVKM_I2C_DONE;
-
-				nouveau_event_trigger(i2c->ntfy, e, port->index);
+				if (e) {
+					struct nvkm_i2c_ntfy_rep rep = {
+						.mask = e,
+					};
+					nvkm_event_send(&i2c->event, rep.mask,
+							port->index, &rep,
+							sizeof(rep));
+				}
 			}
 		}
 	}
 }
 
+static const struct nvkm_event_func
+nouveau_i2c_intr_func = {
+	.ctor = nouveau_i2c_intr_ctor,
+	.init = nouveau_i2c_intr_init,
+	.fini = nouveau_i2c_intr_fini,
+};
+
 int
 _nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
 {
@@ -431,7 +457,7 @@ _nouveau_i2c_dtor(struct nouveau_object
 	struct nouveau_i2c *i2c = (void *)object;
 	struct nouveau_i2c_port *port, *temp;
 
-	nouveau_event_destroy(&i2c->ntfy);
+	nvkm_event_fini(&i2c->event);
 
 	list_for_each_entry_safe(port, temp, &i2c->ports, head) {
 		nouveau_object_ref(NULL, (struct nouveau_object **)&port);
@@ -547,13 +573,10 @@ nouveau_i2c_create_(struct nouveau_objec
 		}
 	}
 
-	ret = nouveau_event_create(4, index, &i2c->ntfy);
+	ret = nvkm_event_init(&nouveau_i2c_intr_func, 4, index, &i2c->event);
 	if (ret)
 		return ret;
 
-	i2c->ntfy->priv = i2c;
-	i2c->ntfy->enable = nouveau_i2c_intr_enable;
-	i2c->ntfy->disable = nouveau_i2c_intr_disable;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2014 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 int
+nvkm_ltc_tags_alloc(struct nouveau_ltc *ltc, u32 n,
+		    struct nouveau_mm_node **pnode)
+{
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	int ret;
+
+	ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
+	if (ret)
+		*pnode = NULL;
+
+	return ret;
+}
+
+static void
+nvkm_ltc_tags_free(struct nouveau_ltc *ltc, struct nouveau_mm_node **pnode)
+{
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	nouveau_mm_free(&priv->tags, pnode);
+}
+
+static void
+nvkm_ltc_tags_clear(struct nouveau_ltc *ltc, u32 first, u32 count)
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	const u32 limit = first + count - 1;
+
+	BUG_ON((first > limit) || (limit >= priv->num_tags));
+
+	impl->cbc_clear(priv, first, limit);
+	impl->cbc_wait(priv);
+}
+
+static int
+nvkm_ltc_zbc_color_get(struct nouveau_ltc *ltc, int index, const u32 color[4])
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	memcpy(priv->zbc_color[index], color, sizeof(priv->zbc_color[index]));
+	impl->zbc_clear_color(priv, index, color);
+	return index;
+}
+
+static int
+nvkm_ltc_zbc_depth_get(struct nouveau_ltc *ltc, int index, const u32 depth)
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	priv->zbc_depth[index] = depth;
+	impl->zbc_clear_depth(priv, index, depth);
+	return index;
+}
+
+int
+_nvkm_ltc_init(struct nouveau_object *object)
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(object);
+	struct nvkm_ltc_priv *priv = (void *)object;
+	int ret, i;
+
+	ret = nouveau_subdev_init(&priv->base.base);
+	if (ret)
+		return ret;
+
+	for (i = priv->base.zbc_min; i <= priv->base.zbc_max; i++) {
+		impl->zbc_clear_color(priv, i, priv->zbc_color[i]);
+		impl->zbc_clear_depth(priv, i, priv->zbc_depth[i]);
+	}
+
+	return 0;
+}
+
+int
+nvkm_ltc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
+		 struct nouveau_oclass *oclass, int length, void **pobject)
+{
+	const struct nvkm_ltc_impl *impl = (void *)oclass;
+	struct nvkm_ltc_priv *priv;
+	int ret;
+
+	ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PLTCG",
+				     "l2c", length, pobject);
+	priv = *pobject;
+	if (ret)
+		return ret;
+
+	memset(priv->zbc_color, 0x00, sizeof(priv->zbc_color));
+	memset(priv->zbc_depth, 0x00, sizeof(priv->zbc_depth));
+
+	priv->base.base.intr = impl->intr;
+	priv->base.tags_alloc = nvkm_ltc_tags_alloc;
+	priv->base.tags_free = nvkm_ltc_tags_free;
+	priv->base.tags_clear = nvkm_ltc_tags_clear;
+	priv->base.zbc_min = 1; /* reserve 0 for disabled */
+	priv->base.zbc_max = min(impl->zbc, NOUVEAU_LTC_MAX_ZBC_CNT) - 1;
+	priv->base.zbc_color_get = nvkm_ltc_zbc_color_get;
+	priv->base.zbc_depth_get = nvkm_ltc_zbc_depth_get;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * 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 <subdev/fb.h>
+#include <subdev/timer.h>
+
+#include "priv.h"
+
+void
+gf100_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit)
+{
+	nv_wr32(priv, 0x17e8cc, start);
+	nv_wr32(priv, 0x17e8d0, limit);
+	nv_wr32(priv, 0x17e8c8, 0x00000004);
+}
+
+void
+gf100_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
+{
+	int c, s;
+	for (c = 0; c < priv->ltc_nr; c++) {
+		for (s = 0; s < priv->lts_nr; s++)
+			nv_wait(priv, 0x1410c8 + c * 0x2000 + s * 0x400, ~0, 0);
+	}
+}
+
+void
+gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+	nv_mask(priv, 0x17ea44, 0x0000000f, i);
+	nv_wr32(priv, 0x17ea48, color[0]);
+	nv_wr32(priv, 0x17ea4c, color[1]);
+	nv_wr32(priv, 0x17ea50, color[2]);
+	nv_wr32(priv, 0x17ea54, color[3]);
+}
+
+void
+gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+	nv_mask(priv, 0x17ea44, 0x0000000f, i);
+	nv_wr32(priv, 0x17ea58, depth);
+}
+
+static void
+gf100_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
+{
+	u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
+	u32 stat = nv_rd32(priv, base + 0x020);
+
+	if (stat) {
+		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+		nv_wr32(priv, base + 0x020, stat);
+	}
+}
+
+void
+gf100_ltc_intr(struct nouveau_subdev *subdev)
+{
+	struct nvkm_ltc_priv *priv = (void *)subdev;
+	u32 mask;
+
+	mask = nv_rd32(priv, 0x00017c);
+	while (mask) {
+		u32 lts, ltc = __ffs(mask);
+		for (lts = 0; lts < priv->lts_nr; lts++)
+			gf100_ltc_lts_isr(priv, ltc, lts);
+		mask &= ~(1 << ltc);
+	}
+
+	/* we do something horribly wrong and upset PMFB a lot, so mask off
+	 * interrupts from it after the first one until it's fixed
+	 */
+	nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
+}
+
+static int
+gf100_ltc_init(struct nouveau_object *object)
+{
+	struct nvkm_ltc_priv *priv = (void *)object;
+	u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
+	int ret;
+
+	ret = nvkm_ltc_init(priv);
+	if (ret)
+		return ret;
+
+	nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+	nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
+	nv_wr32(priv, 0x17e8d4, priv->tag_base);
+	nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
+	return 0;
+}
+
+void
+gf100_ltc_dtor(struct nouveau_object *object)
+{
+	struct nouveau_fb *pfb = nouveau_fb(object);
+	struct nvkm_ltc_priv *priv = (void *)object;
+
+	nouveau_mm_fini(&priv->tags);
+	nouveau_mm_free(&pfb->vram, &priv->tag_ram);
+
+	nvkm_ltc_destroy(priv);
+}
+
+/* TODO: Figure out tag memory details and drop the over-cautious allocation.
+ */
+int
+gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv)
+{
+	u32 tag_size, tag_margin, tag_align;
+	int ret;
+
+	/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
+	priv->num_tags = (pfb->ram->size >> 17) / 4;
+	if (priv->num_tags > (1 << 17))
+		priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
+	priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
+
+	tag_align = priv->ltc_nr * 0x800;
+	tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
+
+	/* 4 part 4 sub: 0x2000 bytes for 56 tags */
+	/* 3 part 4 sub: 0x6000 bytes for 168 tags */
+	/*
+	 * About 147 bytes per tag. Let's be safe and allocate x2, which makes
+	 * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags.
+	 *
+	 * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %.
+	 */
+	tag_size  = (priv->num_tags / 64) * 0x6000 + tag_margin;
+	tag_size += tag_align;
+	tag_size  = (tag_size + 0xfff) >> 12; /* round up */
+
+	ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
+	                      &priv->tag_ram);
+	if (ret) {
+		priv->num_tags = 0;
+	} else {
+		u64 tag_base = ((u64)priv->tag_ram->offset << 12) + tag_margin;
+
+		tag_base += tag_align - 1;
+		ret = do_div(tag_base, tag_align);
+
+		priv->tag_base = tag_base;
+	}
+
+	ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
+	return ret;
+}
+
+int
+gf100_ltc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+	       struct nouveau_oclass *oclass, void *data, u32 size,
+	       struct nouveau_object **pobject)
+{
+	struct nouveau_fb *pfb = nouveau_fb(parent);
+	struct nvkm_ltc_priv *priv;
+	u32 parts, mask;
+	int ret, i;
+
+	ret = nvkm_ltc_create(parent, engine, oclass, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	parts = nv_rd32(priv, 0x022438);
+	mask = nv_rd32(priv, 0x022554);
+	for (i = 0; i < parts; i++) {
+		if (!(mask & (1 << i)))
+			priv->ltc_nr++;
+	}
+	priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
+
+	ret = gf100_ltc_init_tag_ram(pfb, priv);
+	if (ret)
+		return ret;
+
+	nv_subdev(priv)->intr = gf100_ltc_intr;
+	return 0;
+}
+
+struct nouveau_oclass *
+gf100_ltc_oclass = &(struct nvkm_ltc_impl) {
+	.base.handle = NV_SUBDEV(LTC, 0xc0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = gf100_ltc_ctor,
+		.dtor = gf100_ltc_dtor,
+		.init = gf100_ltc_init,
+		.fini = _nvkm_ltc_fini,
+	},
+	.intr = gf100_ltc_intr,
+	.cbc_clear = gf100_ltc_cbc_clear,
+	.cbc_wait = gf100_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gf100_ltc_zbc_clear_color,
+	.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * 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 "priv.h"
+
+static int
+gk104_ltc_init(struct nouveau_object *object)
+{
+	struct nvkm_ltc_priv *priv = (void *)object;
+	u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
+	int ret;
+
+	ret = nvkm_ltc_init(priv);
+	if (ret)
+		return ret;
+
+	nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
+	nv_wr32(priv, 0x17e000, priv->ltc_nr);
+	nv_wr32(priv, 0x17e8d4, priv->tag_base);
+	nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
+	return 0;
+}
+
+struct nouveau_oclass *
+gk104_ltc_oclass = &(struct nvkm_ltc_impl) {
+	.base.handle = NV_SUBDEV(LTC, 0xe4),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = gf100_ltc_ctor,
+		.dtor = gf100_ltc_dtor,
+		.init = gk104_ltc_init,
+		.fini = _nvkm_ltc_fini,
+	},
+	.intr = gf100_ltc_intr,
+	.cbc_clear = gf100_ltc_cbc_clear,
+	.cbc_wait = gf100_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gf100_ltc_zbc_clear_color,
+	.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014 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 <subdev/fb.h>
+#include <subdev/timer.h>
+
+#include "priv.h"
+
+static void
+gm107_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit)
+{
+	nv_wr32(priv, 0x17e270, start);
+	nv_wr32(priv, 0x17e274, limit);
+	nv_wr32(priv, 0x17e26c, 0x00000004);
+}
+
+static void
+gm107_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
+{
+	int c, s;
+	for (c = 0; c < priv->ltc_nr; c++) {
+		for (s = 0; s < priv->lts_nr; s++)
+			nv_wait(priv, 0x14046c + c * 0x2000 + s * 0x200, ~0, 0);
+	}
+}
+
+static void
+gm107_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+	nv_mask(priv, 0x17e338, 0x0000000f, i);
+	nv_wr32(priv, 0x17e33c, color[0]);
+	nv_wr32(priv, 0x17e340, color[1]);
+	nv_wr32(priv, 0x17e344, color[2]);
+	nv_wr32(priv, 0x17e348, color[3]);
+}
+
+static void
+gm107_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+	nv_mask(priv, 0x17e338, 0x0000000f, i);
+	nv_wr32(priv, 0x17e34c, depth);
+}
+
+static void
+gm107_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
+{
+	u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
+	u32 stat = nv_rd32(priv, base + 0x00c);
+
+	if (stat) {
+		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+		nv_wr32(priv, base + 0x00c, stat);
+	}
+}
+
+static void
+gm107_ltc_intr(struct nouveau_subdev *subdev)
+{
+	struct nvkm_ltc_priv *priv = (void *)subdev;
+	u32 mask;
+
+	mask = nv_rd32(priv, 0x00017c);
+	while (mask) {
+		u32 lts, ltc = __ffs(mask);
+		for (lts = 0; lts < priv->lts_nr; lts++)
+			gm107_ltc_lts_isr(priv, ltc, lts);
+		mask &= ~(1 << ltc);
+	}
+
+	/* we do something horribly wrong and upset PMFB a lot, so mask off
+	 * interrupts from it after the first one until it's fixed
+	 */
+	nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
+}
+
+static int
+gm107_ltc_init(struct nouveau_object *object)
+{
+	struct nvkm_ltc_priv *priv = (void *)object;
+	u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
+	int ret;
+
+	ret = nvkm_ltc_init(priv);
+	if (ret)
+		return ret;
+
+	nv_wr32(priv, 0x17e27c, priv->ltc_nr);
+	nv_wr32(priv, 0x17e278, priv->tag_base);
+	nv_mask(priv, 0x17e264, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
+	return 0;
+}
+
+static int
+gm107_ltc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+	       struct nouveau_oclass *oclass, void *data, u32 size,
+	       struct nouveau_object **pobject)
+{
+	struct nouveau_fb *pfb = nouveau_fb(parent);
+	struct nvkm_ltc_priv *priv;
+	u32 parts, mask;
+	int ret, i;
+
+	ret = nvkm_ltc_create(parent, engine, oclass, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	parts = nv_rd32(priv, 0x022438);
+	mask = nv_rd32(priv, 0x021c14);
+	for (i = 0; i < parts; i++) {
+		if (!(mask & (1 << i)))
+			priv->ltc_nr++;
+	}
+	priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
+
+	ret = gf100_ltc_init_tag_ram(pfb, priv);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+struct nouveau_oclass *
+gm107_ltc_oclass = &(struct nvkm_ltc_impl) {
+	.base.handle = NV_SUBDEV(LTC, 0xff),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = gm107_ltc_ctor,
+		.dtor = gf100_ltc_dtor,
+		.init = gm107_ltc_init,
+		.fini = _nvkm_ltc_fini,
+	},
+	.intr = gm107_ltc_intr,
+	.cbc_clear = gm107_ltc_cbc_clear,
+	.cbc_wait = gm107_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gm107_ltc_zbc_clear_color,
+	.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,69 @@
+#ifndef __NVKM_LTC_PRIV_H__
+#define __NVKM_LTC_PRIV_H__
+
+#include <subdev/ltc.h>
+#include <subdev/fb.h>
+
+struct nvkm_ltc_priv {
+	struct nouveau_ltc base;
+	u32 ltc_nr;
+	u32 lts_nr;
+
+	u32 num_tags;
+	u32 tag_base;
+	struct nouveau_mm tags;
+	struct nouveau_mm_node *tag_ram;
+
+	u32 zbc_color[NOUVEAU_LTC_MAX_ZBC_CNT][4];
+	u32 zbc_depth[NOUVEAU_LTC_MAX_ZBC_CNT];
+};
+
+#define nvkm_ltc_create(p,e,o,d)                                               \
+	nvkm_ltc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nvkm_ltc_destroy(p) ({                                                 \
+	struct nvkm_ltc_priv *_priv = (p);                                     \
+	_nvkm_ltc_dtor(nv_object(_priv));                                      \
+})
+#define nvkm_ltc_init(p) ({                                                    \
+	struct nvkm_ltc_priv *_priv = (p);                                     \
+	_nvkm_ltc_init(nv_object(_priv));                                      \
+})
+#define nvkm_ltc_fini(p,s) ({                                                  \
+	struct nvkm_ltc_priv *_priv = (p);                                     \
+	_nvkm_ltc_fini(nv_object(_priv), (s));                                 \
+})
+
+int  nvkm_ltc_create_(struct nouveau_object *, struct nouveau_object *,
+		      struct nouveau_oclass *, int, void **);
+
+#define _nvkm_ltc_dtor _nouveau_subdev_dtor
+int _nvkm_ltc_init(struct nouveau_object *);
+#define _nvkm_ltc_fini _nouveau_subdev_fini
+
+int  gf100_ltc_ctor(struct nouveau_object *, struct nouveau_object *,
+		    struct nouveau_oclass *, void *, u32,
+		    struct nouveau_object **);
+void gf100_ltc_dtor(struct nouveau_object *);
+int  gf100_ltc_init_tag_ram(struct nouveau_fb *, struct nvkm_ltc_priv *);
+int  gf100_ltc_tags_alloc(struct nouveau_ltc *, u32, struct nouveau_mm_node **);
+void gf100_ltc_tags_free(struct nouveau_ltc *, struct nouveau_mm_node **);
+
+struct nvkm_ltc_impl {
+	struct nouveau_oclass base;
+	void (*intr)(struct nouveau_subdev *);
+
+	void (*cbc_clear)(struct nvkm_ltc_priv *, u32 start, u32 limit);
+	void (*cbc_wait)(struct nvkm_ltc_priv *);
+
+	int zbc;
+	void (*zbc_clear_color)(struct nvkm_ltc_priv *, int, const u32[4]);
+	void (*zbc_clear_depth)(struct nvkm_ltc_priv *, int, const u32);
+};
+
+void gf100_ltc_intr(struct nouveau_subdev *);
+void gf100_ltc_cbc_clear(struct nvkm_ltc_priv *, u32, u32);
+void gf100_ltc_cbc_wait(struct nvkm_ltc_priv *);
+void gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *, int, const u32[4]);
+void gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *, int, const u32);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,226 +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 <subdev/fb.h>
-#include <subdev/timer.h>
-
-#include "gf100.h"
-
-static void
-gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
-{
-	u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
-	u32 stat = nv_rd32(priv, base + 0x020);
-
-	if (stat) {
-		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
-		nv_wr32(priv, base + 0x020, stat);
-	}
-}
-
-static void
-gf100_ltcg_intr(struct nouveau_subdev *subdev)
-{
-	struct gf100_ltcg_priv *priv = (void *)subdev;
-	u32 mask;
-
-	mask = nv_rd32(priv, 0x00017c);
-	while (mask) {
-		u32 lts, ltc = __ffs(mask);
-		for (lts = 0; lts < priv->lts_nr; lts++)
-			gf100_ltcg_lts_isr(priv, ltc, lts);
-		mask &= ~(1 << ltc);
-	}
-
-	/* we do something horribly wrong and upset PMFB a lot, so mask off
-	 * interrupts from it after the first one until it's fixed
-	 */
-	nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
-}
-
-int
-gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
-		     struct nouveau_mm_node **pnode)
-{
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	int ret;
-
-	ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
-	if (ret)
-		*pnode = NULL;
-
-	return ret;
-}
-
-void
-gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
-{
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-
-	nouveau_mm_free(&priv->tags, pnode);
-}
-
-static void
-gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
-{
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	u32 last = first + count - 1;
-	int p, i;
-
-	BUG_ON((first > last) || (last >= priv->num_tags));
-
-	nv_wr32(priv, 0x17e8cc, first);
-	nv_wr32(priv, 0x17e8d0, last);
-	nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
-
-	/* wait until it's finished with clearing */
-	for (p = 0; p < priv->ltc_nr; ++p) {
-		for (i = 0; i < priv->lts_nr; ++i)
-			nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
-	}
-}
-
-/* TODO: Figure out tag memory details and drop the over-cautious allocation.
- */
-int
-gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
-{
-	u32 tag_size, tag_margin, tag_align;
-	int ret;
-
-	/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
-	priv->num_tags = (pfb->ram->size >> 17) / 4;
-	if (priv->num_tags > (1 << 17))
-		priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
-	priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
-
-	tag_align = priv->ltc_nr * 0x800;
-	tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
-
-	/* 4 part 4 sub: 0x2000 bytes for 56 tags */
-	/* 3 part 4 sub: 0x6000 bytes for 168 tags */
-	/*
-	 * About 147 bytes per tag. Let's be safe and allocate x2, which makes
-	 * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags.
-	 *
-	 * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %.
-	 */
-	tag_size  = (priv->num_tags / 64) * 0x6000 + tag_margin;
-	tag_size += tag_align;
-	tag_size  = (tag_size + 0xfff) >> 12; /* round up */
-
-	ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
-	                      &priv->tag_ram);
-	if (ret) {
-		priv->num_tags = 0;
-	} else {
-		u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
-
-		tag_base += tag_align - 1;
-		ret = do_div(tag_base, tag_align);
-
-		priv->tag_base = tag_base;
-	}
-	ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
-
-	return ret;
-}
-
-static int
-gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	       struct nouveau_oclass *oclass, void *data, u32 size,
-	       struct nouveau_object **pobject)
-{
-	struct gf100_ltcg_priv *priv;
-	struct nouveau_fb *pfb = nouveau_fb(parent);
-	u32 parts, mask;
-	int ret, i;
-
-	ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	parts = nv_rd32(priv, 0x022438);
-	mask = nv_rd32(priv, 0x022554);
-	for (i = 0; i < parts; i++) {
-		if (!(mask & (1 << i)))
-			priv->ltc_nr++;
-	}
-	priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
-
-	ret = gf100_ltcg_init_tag_ram(pfb, priv);
-	if (ret)
-		return ret;
-
-	priv->base.tags_alloc = gf100_ltcg_tags_alloc;
-	priv->base.tags_free  = gf100_ltcg_tags_free;
-	priv->base.tags_clear = gf100_ltcg_tags_clear;
-
-	nv_subdev(priv)->intr = gf100_ltcg_intr;
-	return 0;
-}
-
-void
-gf100_ltcg_dtor(struct nouveau_object *object)
-{
-	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
-
-	nouveau_mm_fini(&priv->tags);
-	nouveau_mm_free(&pfb->vram, &priv->tag_ram);
-
-	nouveau_ltcg_destroy(ltcg);
-}
-
-static int
-gf100_ltcg_init(struct nouveau_object *object)
-{
-	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	int ret;
-
-	ret = nouveau_ltcg_init(ltcg);
-	if (ret)
-		return ret;
-
-	nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
-	nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
-	if (nv_device(ltcg)->card_type >= NV_E0)
-		nv_wr32(priv, 0x17e000, priv->ltc_nr);
-	nv_wr32(priv, 0x17e8d4, priv->tag_base);
-	return 0;
-}
-
-struct nouveau_oclass *
-gf100_ltcg_oclass = &(struct nouveau_oclass) {
-	.handle = NV_SUBDEV(LTCG, 0xc0),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = gf100_ltcg_ctor,
-		.dtor = gf100_ltcg_dtor,
-		.init = gf100_ltcg_init,
-		.fini = _nouveau_ltcg_fini,
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-#ifndef __NVKM_LTCG_PRIV_GF100_H__
-#define __NVKM_LTCG_PRIV_GF100_H__
-
-#include <subdev/ltcg.h>
-
-struct gf100_ltcg_priv {
-	struct nouveau_ltcg base;
-	u32 ltc_nr;
-	u32 lts_nr;
-	u32 num_tags;
-	u32 tag_base;
-	struct nouveau_mm tags;
-	struct nouveau_mm_node *tag_ram;
-};
-
-void gf100_ltcg_dtor(struct nouveau_object *);
-int  gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *);
-int  gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **);
-void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/*
- * Copyright 2014 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 <subdev/fb.h>
-#include <subdev/timer.h>
-
-#include "gf100.h"
-
-static void
-gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
-{
-	u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
-	u32 stat = nv_rd32(priv, base + 0x00c);
-
-	if (stat) {
-		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
-		nv_wr32(priv, base + 0x00c, stat);
-	}
-}
-
-static void
-gm107_ltcg_intr(struct nouveau_subdev *subdev)
-{
-	struct gf100_ltcg_priv *priv = (void *)subdev;
-	u32 mask;
-
-	mask = nv_rd32(priv, 0x00017c);
-	while (mask) {
-		u32 lts, ltc = __ffs(mask);
-		for (lts = 0; lts < priv->lts_nr; lts++)
-			gm107_ltcg_lts_isr(priv, ltc, lts);
-		mask &= ~(1 << ltc);
-	}
-
-	/* we do something horribly wrong and upset PMFB a lot, so mask off
-	 * interrupts from it after the first one until it's fixed
-	 */
-	nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
-}
-
-static void
-gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
-{
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	u32 last = first + count - 1;
-	int p, i;
-
-	BUG_ON((first > last) || (last >= priv->num_tags));
-
-	nv_wr32(priv, 0x17e270, first);
-	nv_wr32(priv, 0x17e274, last);
-	nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */
-
-	/* wait until it's finished with clearing */
-	for (p = 0; p < priv->ltc_nr; ++p) {
-		for (i = 0; i < priv->lts_nr; ++i)
-			nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0);
-	}
-}
-
-static int
-gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	       struct nouveau_oclass *oclass, void *data, u32 size,
-	       struct nouveau_object **pobject)
-{
-	struct gf100_ltcg_priv *priv;
-	struct nouveau_fb *pfb = nouveau_fb(parent);
-	u32 parts, mask;
-	int ret, i;
-
-	ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	parts = nv_rd32(priv, 0x022438);
-	mask = nv_rd32(priv, 0x021c14);
-	for (i = 0; i < parts; i++) {
-		if (!(mask & (1 << i)))
-			priv->ltc_nr++;
-	}
-	priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
-
-	ret = gf100_ltcg_init_tag_ram(pfb, priv);
-	if (ret)
-		return ret;
-
-	priv->base.tags_alloc = gf100_ltcg_tags_alloc;
-	priv->base.tags_free  = gf100_ltcg_tags_free;
-	priv->base.tags_clear = gm107_ltcg_tags_clear;
-
-	nv_subdev(priv)->intr = gm107_ltcg_intr;
-	return 0;
-}
-
-static int
-gm107_ltcg_init(struct nouveau_object *object)
-{
-	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
-	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-	int ret;
-
-	ret = nouveau_ltcg_init(ltcg);
-	if (ret)
-		return ret;
-
-	nv_wr32(priv, 0x17e27c, priv->ltc_nr);
-	nv_wr32(priv, 0x17e278, priv->tag_base);
-	return 0;
-}
-
-struct nouveau_oclass *
-gm107_ltcg_oclass = &(struct nouveau_oclass) {
-	.handle = NV_SUBDEV(LTCG, 0xff),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = gm107_ltcg_ctor,
-		.dtor = gf100_ltcg_dtor,
-		.init = gm107_ltcg_init,
-		.fini = _nouveau_ltcg_fini,
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,17 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/mc.h>
+#include "priv.h"
 #include <core/option.h>
 
+static inline void
+nouveau_mc_unk260(struct nouveau_mc *pmc, u32 data)
+{
+	const struct nouveau_mc_oclass *impl = (void *)nv_oclass(pmc);
+	if (impl->unk260)
+		impl->unk260(pmc, data);
+}
+
 static inline u32
 nouveau_mc_intr_mask(struct nouveau_mc *pmc)
 {
@@ -114,6 +122,8 @@ nouveau_mc_create_(struct nouveau_object
 	if (ret)
 		return ret;
 
+	pmc->unk260 = nouveau_mc_unk260;
+
 	if (nv_device_is_pci(device))
 		switch (device->pdev->device & 0x0ff0) {
 		case 0x00f0:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c	2014-09-28 17:29:07.000000000 -0400
@@ -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 "nv04.h"
+
+struct nouveau_oclass *
+gk20a_mc_oclass = &(struct nouveau_mc_oclass) {
+	.base.handle = NV_SUBDEV(MC, 0xea),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_mc_ctor,
+		.dtor = _nouveau_mc_dtor,
+		.init = nv50_mc_init,
+		.fini = _nouveau_mc_fini,
+	},
+	.intr = nvc0_mc_intr,
+	.msi_rearm = nv40_mc_msi_rearm,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __NVKM_MC_NV04_H__
 #define __NVKM_MC_NV04_H__
 
-#include <subdev/mc.h>
+#include "priv.h"
 
 struct nv04_mc_priv {
 	struct nouveau_mc base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ nvc0_mc_intr[] = {
 	{ 0x00200000, NVDEV_SUBDEV_GPIO },	/* PMGR->GPIO */
 	{ 0x00200000, NVDEV_SUBDEV_I2C },	/* PMGR->I2C/AUX */
 	{ 0x01000000, NVDEV_SUBDEV_PWR },
-	{ 0x02000000, NVDEV_SUBDEV_LTCG },
+	{ 0x02000000, NVDEV_SUBDEV_LTC },
 	{ 0x08000000, NVDEV_SUBDEV_FB },
 	{ 0x10000000, NVDEV_SUBDEV_BUS },
 	{ 0x40000000, NVDEV_SUBDEV_IBUS },
@@ -56,6 +56,12 @@ nvc0_mc_msi_rearm(struct nouveau_mc *pmc
 	nv_wr32(priv, 0x088704, 0x00000000);
 }
 
+void
+nvc0_mc_unk260(struct nouveau_mc *pmc, u32 data)
+{
+	nv_wr32(pmc, 0x000260, data);
+}
+
 struct nouveau_oclass *
 nvc0_mc_oclass = &(struct nouveau_mc_oclass) {
 	.base.handle = NV_SUBDEV(MC, 0xc0),
@@ -67,4 +73,5 @@ nvc0_mc_oclass = &(struct nouveau_mc_ocl
 	},
 	.intr = nvc0_mc_intr,
 	.msi_rearm = nvc0_mc_msi_rearm,
+	.unk260 = nvc0_mc_unk260,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,4 +35,5 @@ nvc3_mc_oclass = &(struct nouveau_mc_ocl
 	},
 	.intr = nvc0_mc_intr,
 	.msi_rearm = nv40_mc_msi_rearm,
+	.unk260 = nvc0_mc_unk260,
 }.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,38 @@
+#ifndef __NVKM_MC_PRIV_H__
+#define __NVKM_MC_PRIV_H__
+
+#include <subdev/mc.h>
+
+#define nouveau_mc_create(p,e,o,d)                                             \
+	nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_destroy(p) ({                                               \
+	struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
+})
+#define nouveau_mc_init(p) ({                                                  \
+	struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc));        \
+})
+#define nouveau_mc_fini(p,s) ({                                                \
+	struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s));   \
+})
+
+int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, int, void **);
+void _nouveau_mc_dtor(struct nouveau_object *);
+int  _nouveau_mc_init(struct nouveau_object *);
+int  _nouveau_mc_fini(struct nouveau_object *, bool);
+
+struct nouveau_mc_intr {
+	u32 stat;
+	u32 unit;
+};
+
+struct nouveau_mc_oclass {
+	struct nouveau_oclass base;
+	const struct nouveau_mc_intr *intr;
+	void (*msi_rearm)(struct nouveau_mc *);
+	void (*unk260)(struct nouveau_mc *, u32);
+};
+
+void nvc0_mc_unk260(struct nouveau_mc *, u32);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,18 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/pwr.h>
 #include <subdev/timer.h>
 
+#include "priv.h"
+
+static void
+nouveau_pwr_pgob(struct nouveau_pwr *ppwr, bool enable)
+{
+	const struct nvkm_pwr_impl *impl = (void *)nv_oclass(ppwr);
+	if (impl->pgob)
+		impl->pgob(ppwr, enable);
+}
+
 static int
 nouveau_pwr_send(struct nouveau_pwr *ppwr, u32 reply[2],
 		 u32 process, u32 message, u32 data0, u32 data1)
@@ -177,6 +186,7 @@ _nouveau_pwr_fini(struct nouveau_object
 int
 _nouveau_pwr_init(struct nouveau_object *object)
 {
+	const struct nvkm_pwr_impl *impl = (void *)object->oclass;
 	struct nouveau_pwr *ppwr = (void *)object;
 	int ret, i;
 
@@ -186,6 +196,7 @@ _nouveau_pwr_init(struct nouveau_object
 
 	nv_subdev(ppwr)->intr = nouveau_pwr_intr;
 	ppwr->message = nouveau_pwr_send;
+	ppwr->pgob = nouveau_pwr_pgob;
 
 	/* prevent previous ucode from running, wait for idle, reset */
 	nv_wr32(ppwr, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */
@@ -195,15 +206,15 @@ _nouveau_pwr_init(struct nouveau_object
 
 	/* upload data segment */
 	nv_wr32(ppwr, 0x10a1c0, 0x01000000);
-	for (i = 0; i < ppwr->data.size / 4; i++)
-		nv_wr32(ppwr, 0x10a1c4, ppwr->data.data[i]);
+	for (i = 0; i < impl->data.size / 4; i++)
+		nv_wr32(ppwr, 0x10a1c4, impl->data.data[i]);
 
 	/* upload code segment */
 	nv_wr32(ppwr, 0x10a180, 0x01000000);
-	for (i = 0; i < ppwr->code.size / 4; i++) {
+	for (i = 0; i < impl->code.size / 4; i++) {
 		if ((i & 0x3f) == 0)
 			nv_wr32(ppwr, 0x10a188, i >> 6);
-		nv_wr32(ppwr, 0x10a184, ppwr->code.data[i]);
+		nv_wr32(ppwr, 0x10a184, impl->code.data[i]);
 	}
 
 	/* start it running */
@@ -245,3 +256,15 @@ nouveau_pwr_create_(struct nouveau_objec
 	init_waitqueue_head(&ppwr->recv.wait);
 	return 0;
 }
+
+int
+_nouveau_pwr_ctor(struct nouveau_object *parent,
+		  struct nouveau_object *engine,
+		  struct nouveau_oclass *oclass, void *data, u32 size,
+		  struct nouveau_object **pobject)
+{
+	struct nouveau_pwr *ppwr;
+	int ret = nouveau_pwr_create(parent, engine, oclass, &ppwr);
+	*pobject = nv_object(ppwr);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc	2014-09-28 17:29:07.000000000 -0400
@@ -242,7 +242,7 @@
 */	push reg /*
 */	pop $r13 /*
 */	pop $r14 /*
-*/	call(wr32) /*
+*/	call(wr32)
 #else
 #define nv_wr32(addr,reg) /*
 */ 	sethi $r0 0x14000000 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000046f,
-	0x00000461,
+	0x00000464,
+	0x00000456,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000473,
-	0x00000471,
+	0x00000468,
+	0x00000466,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000877,
-	0x0000071e,
+	0x0000086c,
+	0x00000713,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000898,
-	0x00000879,
+	0x0000088d,
+	0x0000086e,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x000008a3,
-	0x000008a1,
+	0x00000898,
+	0x00000896,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -239,10 +239,10 @@ uint32_t nv108_pwr_data[] = {
 	0x000003df,
 	0x00040003,
 	0x00000000,
-	0x00000407,
+	0x000003fc,
 	0x00010004,
 	0x00000000,
-	0x00000421,
+	0x00000416,
 /* 0x03ac: memx_func_tail */
 /* 0x03ac: memx_data_head */
 	0x00000000,
@@ -1080,375 +1080,375 @@ uint32_t nv108_pwr_code[] = {
 	0x50f960f9,
 	0xe0fcd0fc,
 	0x00002e7e,
-	0x140003f1,
-	0xa00506fd,
-	0xb604bd05,
-	0x1bf40242,
-/* 0x0407: memx_func_wait */
-	0x0800f8dd,
-	0x0088cf2c,
-	0x98001e98,
-	0x1c98011d,
-	0x031b9802,
-	0x7e1010b6,
-	0xf8000071,
-/* 0x0421: memx_func_delay */
+	0xf40242b6,
+	0x00f8e81b,
+/* 0x03fc: memx_func_wait */
+	0x88cf2c08,
 	0x001e9800,
-	0x7e0410b6,
-	0xf800005d,
-/* 0x042d: memx_exec */
-	0xf9e0f900,
-	0xb2c1b2d0,
-/* 0x0435: memx_exec_next */
-	0x001398b2,
-	0x950410b6,
-	0x30f01034,
-	0xde35980c,
-	0x12a655f9,
-	0xfced1ef4,
-	0x7ee0fcd0,
-	0xf800023f,
-/* 0x0455: memx_info */
-	0x03ac4c00,
-	0x7e08004b,
-	0xf800023f,
-/* 0x0461: memx_recv */
-	0x01d6b000,
-	0xb0c90bf4,
-	0x0bf400d6,
-/* 0x046f: memx_init */
-	0xf800f8eb,
-/* 0x0471: perf_recv */
-/* 0x0473: perf_init */
-	0xf800f800,
-/* 0x0475: i2c_drive_scl */
-	0x0036b000,
-	0x400d0bf4,
-	0x01f607e0,
-	0xf804bd00,
-/* 0x0485: i2c_drive_scl_lo */
-	0x07e44000,
-	0xbd0001f6,
-/* 0x048f: i2c_drive_sda */
-	0xb000f804,
-	0x0bf40036,
-	0x07e0400d,
-	0xbd0002f6,
-/* 0x049f: i2c_drive_sda_lo */
-	0x4000f804,
-	0x02f607e4,
-	0xf804bd00,
-/* 0x04a9: i2c_sense_scl */
-	0x0132f400,
-	0xcf07c443,
-	0x31fd0033,
-	0x060bf404,
-/* 0x04bb: i2c_sense_scl_done */
-	0xf80131f4,
-/* 0x04bd: i2c_sense_sda */
-	0x0132f400,
-	0xcf07c443,
-	0x32fd0033,
-	0x060bf404,
-/* 0x04cf: i2c_sense_sda_done */
-	0xf80131f4,
-/* 0x04d1: i2c_raise_scl */
-	0x4440f900,
-	0x01030898,
-	0x0004757e,
-/* 0x04dc: i2c_raise_scl_wait */
-	0x7e03e84e,
-	0x7e00005d,
-	0xf40004a9,
-	0x42b60901,
-	0xef1bf401,
-/* 0x04f0: i2c_raise_scl_done */
-	0x00f840fc,
-/* 0x04f4: i2c_start */
-	0x0004a97e,
-	0x7e0d11f4,
-	0xf40004bd,
-	0x0ef40611,
-/* 0x0505: i2c_start_rep */
-	0x7e00032e,
-	0x03000475,
-	0x048f7e01,
-	0x0076bb00,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0xd17e50fc,
-	0x64b60004,
-	0x1d11f404,
-/* 0x0530: i2c_start_send */
-	0x8f7e0003,
-	0x884e0004,
-	0x005d7e13,
-	0x7e000300,
-	0x4e000475,
-	0x5d7e1388,
-/* 0x054a: i2c_start_out */
-	0x00f80000,
-/* 0x054c: i2c_stop */
-	0x757e0003,
-	0x00030004,
-	0x00048f7e,
-	0x7e03e84e,
-	0x0300005d,
-	0x04757e01,
-	0x13884e00,
+	0x98011d98,
+	0x1b98021c,
+	0x1010b603,
+	0x0000717e,
+/* 0x0416: memx_func_delay */
+	0x1e9800f8,
+	0x0410b600,
 	0x00005d7e,
-	0x8f7e0103,
-	0x884e0004,
-	0x005d7e13,
-/* 0x057b: i2c_bitw */
-	0x7e00f800,
-	0x4e00048f,
-	0x5d7e03e8,
-	0x76bb0000,
+/* 0x0422: memx_exec */
+	0xe0f900f8,
+	0xc1b2d0f9,
+/* 0x042a: memx_exec_next */
+	0x1398b2b2,
+	0x0410b600,
+	0xf0103495,
+	0x35980c30,
+	0xa655f9de,
+	0xed1ef412,
+	0xe0fcd0fc,
+	0x00023f7e,
+/* 0x044a: memx_info */
+	0xac4c00f8,
+	0x08004b03,
+	0x00023f7e,
+/* 0x0456: memx_recv */
+	0xd6b000f8,
+	0xc90bf401,
+	0xf400d6b0,
+	0x00f8eb0b,
+/* 0x0464: memx_init */
+/* 0x0466: perf_recv */
+	0x00f800f8,
+/* 0x0468: perf_init */
+/* 0x046a: i2c_drive_scl */
+	0x36b000f8,
+	0x0d0bf400,
+	0xf607e040,
+	0x04bd0001,
+/* 0x047a: i2c_drive_scl_lo */
+	0xe44000f8,
+	0x0001f607,
+	0x00f804bd,
+/* 0x0484: i2c_drive_sda */
+	0xf40036b0,
+	0xe0400d0b,
+	0x0002f607,
+	0x00f804bd,
+/* 0x0494: i2c_drive_sda_lo */
+	0xf607e440,
+	0x04bd0002,
+/* 0x049e: i2c_sense_scl */
+	0x32f400f8,
+	0x07c44301,
+	0xfd0033cf,
+	0x0bf40431,
+	0x0131f406,
+/* 0x04b0: i2c_sense_scl_done */
+/* 0x04b2: i2c_sense_sda */
+	0x32f400f8,
+	0x07c44301,
+	0xfd0033cf,
+	0x0bf40432,
+	0x0131f406,
+/* 0x04c4: i2c_sense_sda_done */
+/* 0x04c6: i2c_raise_scl */
+	0x40f900f8,
+	0x03089844,
+	0x046a7e01,
+/* 0x04d1: i2c_raise_scl_wait */
+	0x03e84e00,
+	0x00005d7e,
+	0x00049e7e,
+	0xb60901f4,
+	0x1bf40142,
+/* 0x04e5: i2c_raise_scl_done */
+	0xf840fcef,
+/* 0x04e9: i2c_start */
+	0x049e7e00,
+	0x0d11f400,
+	0x0004b27e,
+	0xf40611f4,
+/* 0x04fa: i2c_start_rep */
+	0x00032e0e,
+	0x00046a7e,
+	0x847e0103,
+	0x76bb0004,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb60004d1,
+	0xb60004c6,
 	0x11f40464,
-	0x13884e17,
+/* 0x0525: i2c_start_send */
+	0x7e00031d,
+	0x4e000484,
+	0x5d7e1388,
+	0x00030000,
+	0x00046a7e,
+	0x7e13884e,
+/* 0x053f: i2c_start_out */
+	0xf800005d,
+/* 0x0541: i2c_stop */
+	0x7e000300,
+	0x0300046a,
+	0x04847e00,
+	0x03e84e00,
 	0x00005d7e,
-	0x757e0003,
+	0x6a7e0103,
 	0x884e0004,
 	0x005d7e13,
-/* 0x05b9: i2c_bitw_out */
-/* 0x05bb: i2c_bitr */
-	0x0300f800,
-	0x048f7e01,
-	0x03e84e00,
-	0x00005d7e,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0x04d17e50,
-	0x0464b600,
-	0x7e1a11f4,
-	0x030004bd,
-	0x04757e00,
-	0x13884e00,
-	0x00005d7e,
-	0xf4013cf0,
-/* 0x05fe: i2c_bitr_done */
-	0x00f80131,
-/* 0x0600: i2c_get_byte */
-	0x08040005,
-/* 0x0604: i2c_get_byte_next */
-	0xbb0154b6,
+	0x7e010300,
+	0x4e000484,
+	0x5d7e1388,
+	0x00f80000,
+/* 0x0570: i2c_bitw */
+	0x0004847e,
+	0x7e03e84e,
+	0xbb00005d,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x0005bb7e,
+	0x0004c67e,
 	0xf40464b6,
-	0x53fd2a11,
-	0x0142b605,
-	0x03d81bf4,
-	0x0076bb01,
+	0x884e1711,
+	0x005d7e13,
+	0x7e000300,
+	0x4e00046a,
+	0x5d7e1388,
+/* 0x05ae: i2c_bitw_out */
+	0x00f80000,
+/* 0x05b0: i2c_bitr */
+	0x847e0103,
+	0xe84e0004,
+	0x005d7e03,
+	0x0076bb00,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
-	0x7b7e50fc,
-	0x64b60005,
-/* 0x064d: i2c_get_byte_done */
-/* 0x064f: i2c_put_byte */
-	0x0400f804,
-/* 0x0651: i2c_put_byte_next */
-	0x0142b608,
-	0xbb3854ff,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x00057b7e,
-	0xf40464b6,
-	0x46b03411,
-	0xd81bf400,
+	0xc67e50fc,
+	0x64b60004,
+	0x1a11f404,
+	0x0004b27e,
+	0x6a7e0003,
+	0x884e0004,
+	0x005d7e13,
+	0x013cf000,
+/* 0x05f3: i2c_bitr_done */
+	0xf80131f4,
+/* 0x05f5: i2c_get_byte */
+	0x04000500,
+/* 0x05f9: i2c_get_byte_next */
+	0x0154b608,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x05bb7e50,
+	0x05b07e50,
 	0x0464b600,
-	0xbb0f11f4,
-	0x36b00076,
-	0x061bf401,
-/* 0x06a7: i2c_put_byte_done */
-	0xf80132f4,
-/* 0x06a9: i2c_addr */
-	0x0076bb00,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0xf47e50fc,
-	0x64b60004,
-	0x2911f404,
-	0x012ec3e7,
-	0xfd0134b6,
-	0x76bb0553,
+	0xfd2a11f4,
+	0x42b60553,
+	0xd81bf401,
+	0x76bb0103,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb600064f,
-/* 0x06ee: i2c_addr_done */
+	0xb6000570,
+/* 0x0642: i2c_get_byte_done */
 	0x00f80464,
-/* 0x06f0: i2c_acquire_addr */
-	0xb6f8cec7,
-	0xe0b705e4,
-	0x00f8d014,
-/* 0x06fc: i2c_acquire */
-	0x0006f07e,
-	0x0000047e,
-	0x7e03d9f0,
-	0xf800002e,
-/* 0x070d: i2c_release */
-	0x06f07e00,
-	0x00047e00,
-	0x03daf000,
-	0x00002e7e,
-/* 0x071e: i2c_recv */
-	0x32f400f8,
-	0xf8c1c701,
-	0xb00214b6,
-	0x1ff52816,
-	0x13b80137,
-	0x98000bd4,
-	0x13b80032,
-	0x98000bac,
-	0x31f40031,
-	0xf9d0f902,
-	0xf1d0f9e0,
-	0xf1000067,
-	0x92100063,
-	0x76bb0167,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0x7e50fc04,
-	0xb60006fc,
-	0xd0fc0464,
-	0xf500d6b0,
-	0x0500b01b,
-	0x0076bb00,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0xa97e50fc,
-	0x64b60006,
-	0xcc11f504,
-	0xe0c5c700,
+/* 0x0644: i2c_put_byte */
+/* 0x0646: i2c_put_byte_next */
+	0x42b60804,
+	0x3854ff01,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x064f7e50,
+	0x05707e50,
 	0x0464b600,
-	0x00a911f5,
-	0x76bb0105,
+	0xb03411f4,
+	0x1bf40046,
+	0x0076bbd8,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0xb07e50fc,
+	0x64b60005,
+	0x0f11f404,
+	0xb00076bb,
+	0x1bf40136,
+	0x0132f406,
+/* 0x069c: i2c_put_byte_done */
+/* 0x069e: i2c_addr */
+	0x76bb00f8,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb60006a9,
-	0x11f50464,
-	0x76bb0087,
+	0xb60004e9,
+	0x11f40464,
+	0x2ec3e729,
+	0x0134b601,
+	0xbb0553fd,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x0006447e,
+/* 0x06e3: i2c_addr_done */
+	0xf80464b6,
+/* 0x06e5: i2c_acquire_addr */
+	0xf8cec700,
+	0xb705e4b6,
+	0xf8d014e0,
+/* 0x06f1: i2c_acquire */
+	0x06e57e00,
+	0x00047e00,
+	0x03d9f000,
+	0x00002e7e,
+/* 0x0702: i2c_release */
+	0xe57e00f8,
+	0x047e0006,
+	0xdaf00000,
+	0x002e7e03,
+/* 0x0713: i2c_recv */
+	0xf400f800,
+	0xc1c70132,
+	0x0214b6f8,
+	0xf52816b0,
+	0xb801371f,
+	0x000bd413,
+	0xb8003298,
+	0x000bac13,
+	0xf4003198,
+	0xd0f90231,
+	0xd0f9e0f9,
+	0x000067f1,
+	0x100063f1,
+	0xbb016792,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x0006f17e,
+	0xfc0464b6,
+	0x00d6b0d0,
+	0x00b01bf5,
+	0x76bb0005,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb6000600,
-	0x11f40464,
-	0xe05bcb67,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0x054c7e50,
-	0x0464b600,
-	0x74bd5bb2,
-/* 0x0823: i2c_recv_not_rd08 */
-	0xb0410ef4,
-	0x1bf401d6,
-	0x7e00053b,
-	0xf40006a9,
-	0xc5c73211,
-	0x064f7ee0,
-	0x2811f400,
-	0xa97e0005,
+	0xb600069e,
+	0x11f50464,
+	0xc5c700cc,
+	0x0076bbe0,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x447e50fc,
+	0x64b60006,
+	0xa911f504,
+	0xbb010500,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x00069e7e,
+	0xf50464b6,
+	0xbb008711,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x0005f57e,
+	0xf40464b6,
+	0x5bcb6711,
+	0x0076bbe0,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x417e50fc,
+	0x64b60005,
+	0xbd5bb204,
+	0x410ef474,
+/* 0x0818: i2c_recv_not_rd08 */
+	0xf401d6b0,
+	0x00053b1b,
+	0x00069e7e,
+	0xc73211f4,
+	0x447ee0c5,
 	0x11f40006,
-	0xe0b5c71f,
-	0x00064f7e,
-	0x7e1511f4,
-	0xbd00054c,
-	0x08c5c774,
-	0xf4091bf4,
-	0x0ef40232,
-/* 0x0861: i2c_recv_not_wr08 */
-/* 0x0861: i2c_recv_done */
-	0xf8cec703,
-	0x00070d7e,
-	0xd0fce0fc,
-	0xb20912f4,
-	0x023f7e7c,
-/* 0x0875: i2c_recv_exit */
-/* 0x0877: i2c_init */
-	0xf800f800,
-/* 0x0879: test_recv */
-	0x04584100,
-	0xb60011cf,
-	0x58400110,
-	0x0001f604,
-	0xe7f104bd,
-	0xe3f1d900,
-	0x967e134f,
-	0x00f80001,
-/* 0x0898: test_init */
-	0x7e08004e,
-	0xf8000196,
-/* 0x08a1: idle_recv */
-/* 0x08a3: idle */
-	0xf400f800,
-	0x54410031,
+	0x7e000528,
+	0xf400069e,
+	0xb5c71f11,
+	0x06447ee0,
+	0x1511f400,
+	0x0005417e,
+	0xc5c774bd,
+	0x091bf408,
+	0xf40232f4,
+/* 0x0856: i2c_recv_not_wr08 */
+/* 0x0856: i2c_recv_done */
+	0xcec7030e,
+	0x07027ef8,
+	0xfce0fc00,
+	0x0912f4d0,
+	0x3f7e7cb2,
+/* 0x086a: i2c_recv_exit */
+	0x00f80002,
+/* 0x086c: i2c_init */
+/* 0x086e: test_recv */
+	0x584100f8,
 	0x0011cf04,
 	0x400110b6,
-	0x01f60454,
-/* 0x08b7: idle_loop */
-	0x0104bd00,
-	0x0232f458,
-/* 0x08bc: idle_proc */
-/* 0x08bc: idle_proc_exec */
-	0x1eb210f9,
-	0x0002487e,
-	0x11f410fc,
-	0x0231f409,
-/* 0x08cf: idle_proc_next */
-	0xb6f00ef4,
-	0x1fa65810,
-	0xf4e81bf4,
-	0x28f4e002,
-	0xc60ef400,
+	0x01f60458,
+	0xf104bd00,
+	0xf1d900e7,
+	0x7e134fe3,
+	0xf8000196,
+/* 0x088d: test_init */
+	0x08004e00,
+	0x0001967e,
+/* 0x0896: idle_recv */
+	0x00f800f8,
+/* 0x0898: idle */
+	0x410031f4,
+	0x11cf0454,
+	0x0110b600,
+	0xf6045440,
+	0x04bd0001,
+/* 0x08ac: idle_loop */
+	0x32f45801,
+/* 0x08b1: idle_proc */
+/* 0x08b1: idle_proc_exec */
+	0xb210f902,
+	0x02487e1e,
+	0xf410fc00,
+	0x31f40911,
+	0xf00ef402,
+/* 0x08c4: idle_proc_next */
+	0xa65810b6,
+	0xe81bf41f,
+	0xf4e002f4,
+	0x0ef40028,
+	0x000000c6,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000054e,
-	0x00000540,
+	0x00000542,
+	0x00000534,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000552,
-	0x00000550,
+	0x00000546,
+	0x00000544,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000982,
-	0x00000825,
+	0x00000976,
+	0x00000819,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x000009ab,
-	0x00000984,
+	0x0000099f,
+	0x00000978,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x000009b7,
-	0x000009b5,
+	0x000009ab,
+	0x000009a9,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -239,10 +239,10 @@ uint32_t nva3_pwr_data[] = {
 	0x000004b7,
 	0x00040003,
 	0x00000000,
-	0x000004df,
+	0x000004d3,
 	0x00010004,
 	0x00000000,
-	0x000004fc,
+	0x000004f0,
 /* 0x03ac: memx_func_tail */
 /* 0x03ac: memx_data_head */
 	0x00000000,
@@ -1198,13 +1198,10 @@ uint32_t nva3_pwr_code[] = {
 	0x0810b601,
 	0x50f960f9,
 	0xe0fcd0fc,
-	0xf13f21f4,
-	0xfd140003,
-	0x05800506,
-	0xb604bd00,
+	0xb63f21f4,
 	0x1bf40242,
-/* 0x04df: memx_func_wait */
-	0xf000f8dd,
+/* 0x04d3: memx_func_wait */
+	0xf000f8e9,
 	0x84b62c87,
 	0x0088cf06,
 	0x98001e98,
@@ -1212,14 +1209,14 @@ uint32_t nva3_pwr_code[] = {
 	0x031b9802,
 	0xf41010b6,
 	0x00f89c21,
-/* 0x04fc: memx_func_delay */
+/* 0x04f0: memx_func_delay */
 	0xb6001e98,
 	0x21f40410,
-/* 0x0507: memx_exec */
+/* 0x04fb: memx_exec */
 	0xf900f87f,
 	0xb9d0f9e0,
 	0xb2b902c1,
-/* 0x0511: memx_exec_next */
+/* 0x0505: memx_exec_next */
 	0x00139802,
 	0x950410b6,
 	0x30f01034,
@@ -1228,112 +1225,112 @@ uint32_t nva3_pwr_code[] = {
 	0xec1ef406,
 	0xe0fcd0fc,
 	0x02b921f5,
-/* 0x0532: memx_info */
+/* 0x0526: memx_info */
 	0xc7f100f8,
 	0xb7f103ac,
 	0x21f50800,
 	0x00f802b9,
-/* 0x0540: memx_recv */
+/* 0x0534: memx_recv */
 	0xf401d6b0,
 	0xd6b0c40b,
 	0xe90bf400,
-/* 0x054e: memx_init */
+/* 0x0542: memx_init */
 	0x00f800f8,
-/* 0x0550: perf_recv */
-/* 0x0552: perf_init */
+/* 0x0544: perf_recv */
+/* 0x0546: perf_init */
 	0x00f800f8,
-/* 0x0554: i2c_drive_scl */
+/* 0x0548: i2c_drive_scl */
 	0xf40036b0,
 	0x07f1110b,
 	0x04b607e0,
 	0x0001d006,
 	0x00f804bd,
-/* 0x0568: i2c_drive_scl_lo */
+/* 0x055c: i2c_drive_scl_lo */
 	0x07e407f1,
 	0xd00604b6,
 	0x04bd0001,
-/* 0x0576: i2c_drive_sda */
+/* 0x056a: i2c_drive_sda */
 	0x36b000f8,
 	0x110bf400,
 	0x07e007f1,
 	0xd00604b6,
 	0x04bd0002,
-/* 0x058a: i2c_drive_sda_lo */
+/* 0x057e: i2c_drive_sda_lo */
 	0x07f100f8,
 	0x04b607e4,
 	0x0002d006,
 	0x00f804bd,
-/* 0x0598: i2c_sense_scl */
+/* 0x058c: i2c_sense_scl */
 	0xf10132f4,
 	0xb607c437,
 	0x33cf0634,
 	0x0431fd00,
 	0xf4060bf4,
-/* 0x05ae: i2c_sense_scl_done */
+/* 0x05a2: i2c_sense_scl_done */
 	0x00f80131,
-/* 0x05b0: i2c_sense_sda */
+/* 0x05a4: i2c_sense_sda */
 	0xf10132f4,
 	0xb607c437,
 	0x33cf0634,
 	0x0432fd00,
 	0xf4060bf4,
-/* 0x05c6: i2c_sense_sda_done */
+/* 0x05ba: i2c_sense_sda_done */
 	0x00f80131,
-/* 0x05c8: i2c_raise_scl */
+/* 0x05bc: i2c_raise_scl */
 	0x47f140f9,
 	0x37f00898,
-	0x5421f501,
-/* 0x05d5: i2c_raise_scl_wait */
+	0x4821f501,
+/* 0x05c9: i2c_raise_scl_wait */
 	0xe8e7f105,
 	0x7f21f403,
-	0x059821f5,
+	0x058c21f5,
 	0xb60901f4,
 	0x1bf40142,
-/* 0x05e9: i2c_raise_scl_done */
+/* 0x05dd: i2c_raise_scl_done */
 	0xf840fcef,
-/* 0x05ed: i2c_start */
-	0x9821f500,
+/* 0x05e1: i2c_start */
+	0x8c21f500,
 	0x0d11f405,
-	0x05b021f5,
+	0x05a421f5,
 	0xf40611f4,
-/* 0x05fe: i2c_start_rep */
+/* 0x05f2: i2c_start_rep */
 	0x37f0300e,
-	0x5421f500,
+	0x4821f500,
 	0x0137f005,
-	0x057621f5,
+	0x056a21f5,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xc821f550,
+	0xbc21f550,
 	0x0464b605,
-/* 0x062b: i2c_start_send */
+/* 0x061f: i2c_start_send */
 	0xf01f11f4,
 	0x21f50037,
-	0xe7f10576,
+	0xe7f1056a,
 	0x21f41388,
 	0x0037f07f,
-	0x055421f5,
+	0x054821f5,
 	0x1388e7f1,
-/* 0x0647: i2c_start_out */
+/* 0x063b: i2c_start_out */
 	0xf87f21f4,
-/* 0x0649: i2c_stop */
+/* 0x063d: i2c_stop */
 	0x0037f000,
-	0x055421f5,
+	0x054821f5,
 	0xf50037f0,
-	0xf1057621,
+	0xf1056a21,
 	0xf403e8e7,
 	0x37f07f21,
-	0x5421f501,
+	0x4821f501,
 	0x88e7f105,
 	0x7f21f413,
 	0xf50137f0,
-	0xf1057621,
+	0xf1056a21,
 	0xf41388e7,
 	0x00f87f21,
-/* 0x067c: i2c_bitw */
-	0x057621f5,
+/* 0x0670: i2c_bitw */
+	0x056a21f5,
 	0x03e8e7f1,
 	0xbb7f21f4,
 	0x65b60076,
@@ -1341,18 +1338,18 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x05c821f5,
+	0x05bc21f5,
 	0xf40464b6,
 	0xe7f11811,
 	0x21f41388,
 	0x0037f07f,
-	0x055421f5,
+	0x054821f5,
 	0x1388e7f1,
-/* 0x06bb: i2c_bitw_out */
+/* 0x06af: i2c_bitw_out */
 	0xf87f21f4,
-/* 0x06bd: i2c_bitr */
+/* 0x06b1: i2c_bitr */
 	0x0137f000,
-	0x057621f5,
+	0x056a21f5,
 	0x03e8e7f1,
 	0xbb7f21f4,
 	0x65b60076,
@@ -1360,19 +1357,19 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x05c821f5,
+	0x05bc21f5,
 	0xf40464b6,
 	0x21f51b11,
-	0x37f005b0,
-	0x5421f500,
+	0x37f005a4,
+	0x4821f500,
 	0x88e7f105,
 	0x7f21f413,
 	0xf4013cf0,
-/* 0x0702: i2c_bitr_done */
+/* 0x06f6: i2c_bitr_done */
 	0x00f80131,
-/* 0x0704: i2c_get_byte */
+/* 0x06f8: i2c_get_byte */
 	0xf00057f0,
-/* 0x070a: i2c_get_byte_next */
+/* 0x06fe: i2c_get_byte_next */
 	0x54b60847,
 	0x0076bb01,
 	0xf90465b6,
@@ -1380,7 +1377,7 @@ uint32_t nva3_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b606bd,
+	0x64b606b1,
 	0x2b11f404,
 	0xb60553fd,
 	0x1bf40142,
@@ -1390,12 +1387,12 @@ uint32_t nva3_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x7c21f550,
+	0x7021f550,
 	0x0464b606,
-/* 0x0754: i2c_get_byte_done */
-/* 0x0756: i2c_put_byte */
+/* 0x0748: i2c_get_byte_done */
+/* 0x074a: i2c_put_byte */
 	0x47f000f8,
-/* 0x0759: i2c_put_byte_next */
+/* 0x074d: i2c_put_byte_next */
 	0x0142b608,
 	0xbb3854ff,
 	0x65b60076,
@@ -1403,7 +1400,7 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x067c21f5,
+	0x067021f5,
 	0xf40464b6,
 	0x46b03411,
 	0xd81bf400,
@@ -1412,21 +1409,21 @@ uint32_t nva3_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xbd21f550,
+	0xb121f550,
 	0x0464b606,
 	0xbb0f11f4,
 	0x36b00076,
 	0x061bf401,
-/* 0x07af: i2c_put_byte_done */
+/* 0x07a3: i2c_put_byte_done */
 	0xf80132f4,
-/* 0x07b1: i2c_addr */
+/* 0x07a5: i2c_addr */
 	0x0076bb00,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b605ed,
+	0x64b605e1,
 	0x2911f404,
 	0x012ec3e7,
 	0xfd0134b6,
@@ -1436,24 +1433,24 @@ uint32_t nva3_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6075621,
-/* 0x07f6: i2c_addr_done */
+	0xb6074a21,
+/* 0x07ea: i2c_addr_done */
 	0x00f80464,
-/* 0x07f8: i2c_acquire_addr */
+/* 0x07ec: i2c_acquire_addr */
 	0xb6f8cec7,
 	0xe0b702e4,
 	0xee980bfc,
-/* 0x0807: i2c_acquire */
+/* 0x07fb: i2c_acquire */
 	0xf500f800,
-	0xf407f821,
+	0xf407ec21,
 	0xd9f00421,
 	0x3f21f403,
-/* 0x0816: i2c_release */
+/* 0x080a: i2c_release */
 	0x21f500f8,
-	0x21f407f8,
+	0x21f407ec,
 	0x03daf004,
 	0xf83f21f4,
-/* 0x0825: i2c_recv */
+/* 0x0819: i2c_recv */
 	0x0132f400,
 	0xb6f8c1c7,
 	0x16b00214,
@@ -1472,7 +1469,7 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x080721f5,
+	0x07fb21f5,
 	0xfc0464b6,
 	0x00d6b0d0,
 	0x00b31bf5,
@@ -1482,7 +1479,7 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x07b121f5,
+	0x07a521f5,
 	0xf50464b6,
 	0xc700d011,
 	0x76bbe0c5,
@@ -1491,7 +1488,7 @@ uint32_t nva3_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6075621,
+	0xb6074a21,
 	0x11f50464,
 	0x57f000ad,
 	0x0076bb01,
@@ -1500,7 +1497,7 @@ uint32_t nva3_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b607b1,
+	0x64b607a5,
 	0x8a11f504,
 	0x0076bb00,
 	0xf90465b6,
@@ -1508,7 +1505,7 @@ uint32_t nva3_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60704,
+	0x64b606f8,
 	0x6a11f404,
 	0xbbe05bcb,
 	0x65b60076,
@@ -1516,38 +1513,38 @@ uint32_t nva3_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x064921f5,
+	0x063d21f5,
 	0xb90464b6,
 	0x74bd025b,
-/* 0x092b: i2c_recv_not_rd08 */
+/* 0x091f: i2c_recv_not_rd08 */
 	0xb0430ef4,
 	0x1bf401d6,
 	0x0057f03d,
-	0x07b121f5,
+	0x07a521f5,
 	0xc73311f4,
 	0x21f5e0c5,
-	0x11f40756,
+	0x11f4074a,
 	0x0057f029,
-	0x07b121f5,
+	0x07a521f5,
 	0xc71f11f4,
 	0x21f5e0b5,
-	0x11f40756,
-	0x4921f515,
+	0x11f4074a,
+	0x3d21f515,
 	0xc774bd06,
 	0x1bf408c5,
 	0x0232f409,
-/* 0x096b: i2c_recv_not_wr08 */
-/* 0x096b: i2c_recv_done */
+/* 0x095f: i2c_recv_not_wr08 */
+/* 0x095f: i2c_recv_done */
 	0xc7030ef4,
 	0x21f5f8ce,
-	0xe0fc0816,
+	0xe0fc080a,
 	0x12f4d0fc,
 	0x027cb90a,
 	0x02b921f5,
-/* 0x0980: i2c_recv_exit */
-/* 0x0982: i2c_init */
+/* 0x0974: i2c_recv_exit */
+/* 0x0976: i2c_init */
 	0x00f800f8,
-/* 0x0984: test_recv */
+/* 0x0978: test_recv */
 	0x05d817f1,
 	0xcf0614b6,
 	0x10b60011,
@@ -1557,12 +1554,12 @@ uint32_t nva3_pwr_code[] = {
 	0x00e7f104,
 	0x4fe3f1d9,
 	0xf521f513,
-/* 0x09ab: test_init */
+/* 0x099f: test_init */
 	0xf100f801,
 	0xf50800e7,
 	0xf801f521,
-/* 0x09b5: idle_recv */
-/* 0x09b7: idle */
+/* 0x09a9: idle_recv */
+/* 0x09ab: idle */
 	0xf400f800,
 	0x17f10031,
 	0x14b605d4,
@@ -1570,20 +1567,23 @@ uint32_t nva3_pwr_code[] = {
 	0xf10110b6,
 	0xb605d407,
 	0x01d00604,
-/* 0x09d3: idle_loop */
+/* 0x09c7: idle_loop */
 	0xf004bd00,
 	0x32f45817,
-/* 0x09d9: idle_proc */
-/* 0x09d9: idle_proc_exec */
+/* 0x09cd: idle_proc */
+/* 0x09cd: idle_proc_exec */
 	0xb910f902,
 	0x21f5021e,
 	0x10fc02c2,
 	0xf40911f4,
 	0x0ef40231,
-/* 0x09ed: idle_proc_next */
+/* 0x09e1: idle_proc_next */
 	0x5810b6ef,
 	0xf4061fb8,
 	0x02f4e61b,
 	0x0028f4dd,
 	0x00bb0ef4,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000054e,
-	0x00000540,
+	0x00000542,
+	0x00000534,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000552,
-	0x00000550,
+	0x00000546,
+	0x00000544,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000982,
-	0x00000825,
+	0x00000976,
+	0x00000819,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x000009ab,
-	0x00000984,
+	0x0000099f,
+	0x00000978,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x000009b7,
-	0x000009b5,
+	0x000009ab,
+	0x000009a9,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -239,10 +239,10 @@ uint32_t nvc0_pwr_data[] = {
 	0x000004b7,
 	0x00040003,
 	0x00000000,
-	0x000004df,
+	0x000004d3,
 	0x00010004,
 	0x00000000,
-	0x000004fc,
+	0x000004f0,
 /* 0x03ac: memx_func_tail */
 /* 0x03ac: memx_data_head */
 	0x00000000,
@@ -1198,13 +1198,10 @@ uint32_t nvc0_pwr_code[] = {
 	0x0810b601,
 	0x50f960f9,
 	0xe0fcd0fc,
-	0xf13f21f4,
-	0xfd140003,
-	0x05800506,
-	0xb604bd00,
+	0xb63f21f4,
 	0x1bf40242,
-/* 0x04df: memx_func_wait */
-	0xf000f8dd,
+/* 0x04d3: memx_func_wait */
+	0xf000f8e9,
 	0x84b62c87,
 	0x0088cf06,
 	0x98001e98,
@@ -1212,14 +1209,14 @@ uint32_t nvc0_pwr_code[] = {
 	0x031b9802,
 	0xf41010b6,
 	0x00f89c21,
-/* 0x04fc: memx_func_delay */
+/* 0x04f0: memx_func_delay */
 	0xb6001e98,
 	0x21f40410,
-/* 0x0507: memx_exec */
+/* 0x04fb: memx_exec */
 	0xf900f87f,
 	0xb9d0f9e0,
 	0xb2b902c1,
-/* 0x0511: memx_exec_next */
+/* 0x0505: memx_exec_next */
 	0x00139802,
 	0x950410b6,
 	0x30f01034,
@@ -1228,112 +1225,112 @@ uint32_t nvc0_pwr_code[] = {
 	0xec1ef406,
 	0xe0fcd0fc,
 	0x02b921f5,
-/* 0x0532: memx_info */
+/* 0x0526: memx_info */
 	0xc7f100f8,
 	0xb7f103ac,
 	0x21f50800,
 	0x00f802b9,
-/* 0x0540: memx_recv */
+/* 0x0534: memx_recv */
 	0xf401d6b0,
 	0xd6b0c40b,
 	0xe90bf400,
-/* 0x054e: memx_init */
+/* 0x0542: memx_init */
 	0x00f800f8,
-/* 0x0550: perf_recv */
-/* 0x0552: perf_init */
+/* 0x0544: perf_recv */
+/* 0x0546: perf_init */
 	0x00f800f8,
-/* 0x0554: i2c_drive_scl */
+/* 0x0548: i2c_drive_scl */
 	0xf40036b0,
 	0x07f1110b,
 	0x04b607e0,
 	0x0001d006,
 	0x00f804bd,
-/* 0x0568: i2c_drive_scl_lo */
+/* 0x055c: i2c_drive_scl_lo */
 	0x07e407f1,
 	0xd00604b6,
 	0x04bd0001,
-/* 0x0576: i2c_drive_sda */
+/* 0x056a: i2c_drive_sda */
 	0x36b000f8,
 	0x110bf400,
 	0x07e007f1,
 	0xd00604b6,
 	0x04bd0002,
-/* 0x058a: i2c_drive_sda_lo */
+/* 0x057e: i2c_drive_sda_lo */
 	0x07f100f8,
 	0x04b607e4,
 	0x0002d006,
 	0x00f804bd,
-/* 0x0598: i2c_sense_scl */
+/* 0x058c: i2c_sense_scl */
 	0xf10132f4,
 	0xb607c437,
 	0x33cf0634,
 	0x0431fd00,
 	0xf4060bf4,
-/* 0x05ae: i2c_sense_scl_done */
+/* 0x05a2: i2c_sense_scl_done */
 	0x00f80131,
-/* 0x05b0: i2c_sense_sda */
+/* 0x05a4: i2c_sense_sda */
 	0xf10132f4,
 	0xb607c437,
 	0x33cf0634,
 	0x0432fd00,
 	0xf4060bf4,
-/* 0x05c6: i2c_sense_sda_done */
+/* 0x05ba: i2c_sense_sda_done */
 	0x00f80131,
-/* 0x05c8: i2c_raise_scl */
+/* 0x05bc: i2c_raise_scl */
 	0x47f140f9,
 	0x37f00898,
-	0x5421f501,
-/* 0x05d5: i2c_raise_scl_wait */
+	0x4821f501,
+/* 0x05c9: i2c_raise_scl_wait */
 	0xe8e7f105,
 	0x7f21f403,
-	0x059821f5,
+	0x058c21f5,
 	0xb60901f4,
 	0x1bf40142,
-/* 0x05e9: i2c_raise_scl_done */
+/* 0x05dd: i2c_raise_scl_done */
 	0xf840fcef,
-/* 0x05ed: i2c_start */
-	0x9821f500,
+/* 0x05e1: i2c_start */
+	0x8c21f500,
 	0x0d11f405,
-	0x05b021f5,
+	0x05a421f5,
 	0xf40611f4,
-/* 0x05fe: i2c_start_rep */
+/* 0x05f2: i2c_start_rep */
 	0x37f0300e,
-	0x5421f500,
+	0x4821f500,
 	0x0137f005,
-	0x057621f5,
+	0x056a21f5,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xc821f550,
+	0xbc21f550,
 	0x0464b605,
-/* 0x062b: i2c_start_send */
+/* 0x061f: i2c_start_send */
 	0xf01f11f4,
 	0x21f50037,
-	0xe7f10576,
+	0xe7f1056a,
 	0x21f41388,
 	0x0037f07f,
-	0x055421f5,
+	0x054821f5,
 	0x1388e7f1,
-/* 0x0647: i2c_start_out */
+/* 0x063b: i2c_start_out */
 	0xf87f21f4,
-/* 0x0649: i2c_stop */
+/* 0x063d: i2c_stop */
 	0x0037f000,
-	0x055421f5,
+	0x054821f5,
 	0xf50037f0,
-	0xf1057621,
+	0xf1056a21,
 	0xf403e8e7,
 	0x37f07f21,
-	0x5421f501,
+	0x4821f501,
 	0x88e7f105,
 	0x7f21f413,
 	0xf50137f0,
-	0xf1057621,
+	0xf1056a21,
 	0xf41388e7,
 	0x00f87f21,
-/* 0x067c: i2c_bitw */
-	0x057621f5,
+/* 0x0670: i2c_bitw */
+	0x056a21f5,
 	0x03e8e7f1,
 	0xbb7f21f4,
 	0x65b60076,
@@ -1341,18 +1338,18 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x05c821f5,
+	0x05bc21f5,
 	0xf40464b6,
 	0xe7f11811,
 	0x21f41388,
 	0x0037f07f,
-	0x055421f5,
+	0x054821f5,
 	0x1388e7f1,
-/* 0x06bb: i2c_bitw_out */
+/* 0x06af: i2c_bitw_out */
 	0xf87f21f4,
-/* 0x06bd: i2c_bitr */
+/* 0x06b1: i2c_bitr */
 	0x0137f000,
-	0x057621f5,
+	0x056a21f5,
 	0x03e8e7f1,
 	0xbb7f21f4,
 	0x65b60076,
@@ -1360,19 +1357,19 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x05c821f5,
+	0x05bc21f5,
 	0xf40464b6,
 	0x21f51b11,
-	0x37f005b0,
-	0x5421f500,
+	0x37f005a4,
+	0x4821f500,
 	0x88e7f105,
 	0x7f21f413,
 	0xf4013cf0,
-/* 0x0702: i2c_bitr_done */
+/* 0x06f6: i2c_bitr_done */
 	0x00f80131,
-/* 0x0704: i2c_get_byte */
+/* 0x06f8: i2c_get_byte */
 	0xf00057f0,
-/* 0x070a: i2c_get_byte_next */
+/* 0x06fe: i2c_get_byte_next */
 	0x54b60847,
 	0x0076bb01,
 	0xf90465b6,
@@ -1380,7 +1377,7 @@ uint32_t nvc0_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b606bd,
+	0x64b606b1,
 	0x2b11f404,
 	0xb60553fd,
 	0x1bf40142,
@@ -1390,12 +1387,12 @@ uint32_t nvc0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x7c21f550,
+	0x7021f550,
 	0x0464b606,
-/* 0x0754: i2c_get_byte_done */
-/* 0x0756: i2c_put_byte */
+/* 0x0748: i2c_get_byte_done */
+/* 0x074a: i2c_put_byte */
 	0x47f000f8,
-/* 0x0759: i2c_put_byte_next */
+/* 0x074d: i2c_put_byte_next */
 	0x0142b608,
 	0xbb3854ff,
 	0x65b60076,
@@ -1403,7 +1400,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x067c21f5,
+	0x067021f5,
 	0xf40464b6,
 	0x46b03411,
 	0xd81bf400,
@@ -1412,21 +1409,21 @@ uint32_t nvc0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xbd21f550,
+	0xb121f550,
 	0x0464b606,
 	0xbb0f11f4,
 	0x36b00076,
 	0x061bf401,
-/* 0x07af: i2c_put_byte_done */
+/* 0x07a3: i2c_put_byte_done */
 	0xf80132f4,
-/* 0x07b1: i2c_addr */
+/* 0x07a5: i2c_addr */
 	0x0076bb00,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b605ed,
+	0x64b605e1,
 	0x2911f404,
 	0x012ec3e7,
 	0xfd0134b6,
@@ -1436,24 +1433,24 @@ uint32_t nvc0_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6075621,
-/* 0x07f6: i2c_addr_done */
+	0xb6074a21,
+/* 0x07ea: i2c_addr_done */
 	0x00f80464,
-/* 0x07f8: i2c_acquire_addr */
+/* 0x07ec: i2c_acquire_addr */
 	0xb6f8cec7,
 	0xe0b702e4,
 	0xee980bfc,
-/* 0x0807: i2c_acquire */
+/* 0x07fb: i2c_acquire */
 	0xf500f800,
-	0xf407f821,
+	0xf407ec21,
 	0xd9f00421,
 	0x3f21f403,
-/* 0x0816: i2c_release */
+/* 0x080a: i2c_release */
 	0x21f500f8,
-	0x21f407f8,
+	0x21f407ec,
 	0x03daf004,
 	0xf83f21f4,
-/* 0x0825: i2c_recv */
+/* 0x0819: i2c_recv */
 	0x0132f400,
 	0xb6f8c1c7,
 	0x16b00214,
@@ -1472,7 +1469,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x080721f5,
+	0x07fb21f5,
 	0xfc0464b6,
 	0x00d6b0d0,
 	0x00b31bf5,
@@ -1482,7 +1479,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x07b121f5,
+	0x07a521f5,
 	0xf50464b6,
 	0xc700d011,
 	0x76bbe0c5,
@@ -1491,7 +1488,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6075621,
+	0xb6074a21,
 	0x11f50464,
 	0x57f000ad,
 	0x0076bb01,
@@ -1500,7 +1497,7 @@ uint32_t nvc0_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b607b1,
+	0x64b607a5,
 	0x8a11f504,
 	0x0076bb00,
 	0xf90465b6,
@@ -1508,7 +1505,7 @@ uint32_t nvc0_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60704,
+	0x64b606f8,
 	0x6a11f404,
 	0xbbe05bcb,
 	0x65b60076,
@@ -1516,38 +1513,38 @@ uint32_t nvc0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x064921f5,
+	0x063d21f5,
 	0xb90464b6,
 	0x74bd025b,
-/* 0x092b: i2c_recv_not_rd08 */
+/* 0x091f: i2c_recv_not_rd08 */
 	0xb0430ef4,
 	0x1bf401d6,
 	0x0057f03d,
-	0x07b121f5,
+	0x07a521f5,
 	0xc73311f4,
 	0x21f5e0c5,
-	0x11f40756,
+	0x11f4074a,
 	0x0057f029,
-	0x07b121f5,
+	0x07a521f5,
 	0xc71f11f4,
 	0x21f5e0b5,
-	0x11f40756,
-	0x4921f515,
+	0x11f4074a,
+	0x3d21f515,
 	0xc774bd06,
 	0x1bf408c5,
 	0x0232f409,
-/* 0x096b: i2c_recv_not_wr08 */
-/* 0x096b: i2c_recv_done */
+/* 0x095f: i2c_recv_not_wr08 */
+/* 0x095f: i2c_recv_done */
 	0xc7030ef4,
 	0x21f5f8ce,
-	0xe0fc0816,
+	0xe0fc080a,
 	0x12f4d0fc,
 	0x027cb90a,
 	0x02b921f5,
-/* 0x0980: i2c_recv_exit */
-/* 0x0982: i2c_init */
+/* 0x0974: i2c_recv_exit */
+/* 0x0976: i2c_init */
 	0x00f800f8,
-/* 0x0984: test_recv */
+/* 0x0978: test_recv */
 	0x05d817f1,
 	0xcf0614b6,
 	0x10b60011,
@@ -1557,12 +1554,12 @@ uint32_t nvc0_pwr_code[] = {
 	0x00e7f104,
 	0x4fe3f1d9,
 	0xf521f513,
-/* 0x09ab: test_init */
+/* 0x099f: test_init */
 	0xf100f801,
 	0xf50800e7,
 	0xf801f521,
-/* 0x09b5: idle_recv */
-/* 0x09b7: idle */
+/* 0x09a9: idle_recv */
+/* 0x09ab: idle */
 	0xf400f800,
 	0x17f10031,
 	0x14b605d4,
@@ -1570,20 +1567,23 @@ uint32_t nvc0_pwr_code[] = {
 	0xf10110b6,
 	0xb605d407,
 	0x01d00604,
-/* 0x09d3: idle_loop */
+/* 0x09c7: idle_loop */
 	0xf004bd00,
 	0x32f45817,
-/* 0x09d9: idle_proc */
-/* 0x09d9: idle_proc_exec */
+/* 0x09cd: idle_proc */
+/* 0x09cd: idle_proc_exec */
 	0xb910f902,
 	0x21f5021e,
 	0x10fc02c2,
 	0xf40911f4,
 	0x0ef40231,
-/* 0x09ed: idle_proc_next */
+/* 0x09e1: idle_proc_next */
 	0x5810b6ef,
 	0xf4061fb8,
 	0x02f4e61b,
 	0x0028f4dd,
 	0x00bb0ef4,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x000004c4,
-	0x000004b6,
+	0x000004b8,
+	0x000004aa,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x000004c8,
-	0x000004c6,
+	0x000004bc,
+	0x000004ba,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x000008e3,
-	0x00000786,
+	0x000008d7,
+	0x0000077a,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000906,
-	0x000008e5,
+	0x000008fa,
+	0x000008d9,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000912,
-	0x00000910,
+	0x00000906,
+	0x00000904,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -239,10 +239,10 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000430,
 	0x00040003,
 	0x00000000,
-	0x00000458,
+	0x0000044c,
 	0x00010004,
 	0x00000000,
-	0x00000472,
+	0x00000466,
 /* 0x03ac: memx_func_tail */
 /* 0x03ac: memx_data_head */
 	0x00000000,
@@ -1100,26 +1100,23 @@ uint32_t nvd0_pwr_code[] = {
 	0xf960f908,
 	0xfcd0fc50,
 	0x3321f4e0,
-	0x140003f1,
-	0x800506fd,
-	0x04bd0005,
 	0xf40242b6,
-	0x00f8dd1b,
-/* 0x0458: memx_func_wait */
+	0x00f8e91b,
+/* 0x044c: memx_func_wait */
 	0xcf2c87f0,
 	0x1e980088,
 	0x011d9800,
 	0x98021c98,
 	0x10b6031b,
 	0x7e21f410,
-/* 0x0472: memx_func_delay */
+/* 0x0466: memx_func_delay */
 	0x1e9800f8,
 	0x0410b600,
 	0xf86721f4,
-/* 0x047d: memx_exec */
+/* 0x0471: memx_exec */
 	0xf9e0f900,
 	0x02c1b9d0,
-/* 0x0487: memx_exec_next */
+/* 0x047b: memx_exec_next */
 	0x9802b2b9,
 	0x10b60013,
 	0x10349504,
@@ -1129,107 +1126,107 @@ uint32_t nvd0_pwr_code[] = {
 	0xd0fcec1e,
 	0x21f5e0fc,
 	0x00f8026b,
-/* 0x04a8: memx_info */
+/* 0x049c: memx_info */
 	0x03acc7f1,
 	0x0800b7f1,
 	0x026b21f5,
-/* 0x04b6: memx_recv */
+/* 0x04aa: memx_recv */
 	0xd6b000f8,
 	0xc40bf401,
 	0xf400d6b0,
 	0x00f8e90b,
-/* 0x04c4: memx_init */
-/* 0x04c6: perf_recv */
+/* 0x04b8: memx_init */
+/* 0x04ba: perf_recv */
 	0x00f800f8,
-/* 0x04c8: perf_init */
-/* 0x04ca: i2c_drive_scl */
+/* 0x04bc: perf_init */
+/* 0x04be: i2c_drive_scl */
 	0x36b000f8,
 	0x0e0bf400,
 	0x07e007f1,
 	0xbd0001d0,
-/* 0x04db: i2c_drive_scl_lo */
+/* 0x04cf: i2c_drive_scl_lo */
 	0xf100f804,
 	0xd007e407,
 	0x04bd0001,
-/* 0x04e6: i2c_drive_sda */
+/* 0x04da: i2c_drive_sda */
 	0x36b000f8,
 	0x0e0bf400,
 	0x07e007f1,
 	0xbd0002d0,
-/* 0x04f7: i2c_drive_sda_lo */
+/* 0x04eb: i2c_drive_sda_lo */
 	0xf100f804,
 	0xd007e407,
 	0x04bd0002,
-/* 0x0502: i2c_sense_scl */
+/* 0x04f6: i2c_sense_scl */
 	0x32f400f8,
 	0xc437f101,
 	0x0033cf07,
 	0xf40431fd,
 	0x31f4060b,
-/* 0x0515: i2c_sense_scl_done */
-/* 0x0517: i2c_sense_sda */
+/* 0x0509: i2c_sense_scl_done */
+/* 0x050b: i2c_sense_sda */
 	0xf400f801,
 	0x37f10132,
 	0x33cf07c4,
 	0x0432fd00,
 	0xf4060bf4,
-/* 0x052a: i2c_sense_sda_done */
+/* 0x051e: i2c_sense_sda_done */
 	0x00f80131,
-/* 0x052c: i2c_raise_scl */
+/* 0x0520: i2c_raise_scl */
 	0x47f140f9,
 	0x37f00898,
-	0xca21f501,
-/* 0x0539: i2c_raise_scl_wait */
+	0xbe21f501,
+/* 0x052d: i2c_raise_scl_wait */
 	0xe8e7f104,
 	0x6721f403,
-	0x050221f5,
+	0x04f621f5,
 	0xb60901f4,
 	0x1bf40142,
-/* 0x054d: i2c_raise_scl_done */
+/* 0x0541: i2c_raise_scl_done */
 	0xf840fcef,
-/* 0x0551: i2c_start */
-	0x0221f500,
-	0x0d11f405,
-	0x051721f5,
+/* 0x0545: i2c_start */
+	0xf621f500,
+	0x0d11f404,
+	0x050b21f5,
 	0xf40611f4,
-/* 0x0562: i2c_start_rep */
+/* 0x0556: i2c_start_rep */
 	0x37f0300e,
-	0xca21f500,
+	0xbe21f500,
 	0x0137f004,
-	0x04e621f5,
+	0x04da21f5,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x2c21f550,
+	0x2021f550,
 	0x0464b605,
-/* 0x058f: i2c_start_send */
+/* 0x0583: i2c_start_send */
 	0xf01f11f4,
 	0x21f50037,
-	0xe7f104e6,
+	0xe7f104da,
 	0x21f41388,
 	0x0037f067,
-	0x04ca21f5,
+	0x04be21f5,
 	0x1388e7f1,
-/* 0x05ab: i2c_start_out */
+/* 0x059f: i2c_start_out */
 	0xf86721f4,
-/* 0x05ad: i2c_stop */
+/* 0x05a1: i2c_stop */
 	0x0037f000,
-	0x04ca21f5,
+	0x04be21f5,
 	0xf50037f0,
-	0xf104e621,
+	0xf104da21,
 	0xf403e8e7,
 	0x37f06721,
-	0xca21f501,
+	0xbe21f501,
 	0x88e7f104,
 	0x6721f413,
 	0xf50137f0,
-	0xf104e621,
+	0xf104da21,
 	0xf41388e7,
 	0x00f86721,
-/* 0x05e0: i2c_bitw */
-	0x04e621f5,
+/* 0x05d4: i2c_bitw */
+	0x04da21f5,
 	0x03e8e7f1,
 	0xbb6721f4,
 	0x65b60076,
@@ -1237,18 +1234,18 @@ uint32_t nvd0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x052c21f5,
+	0x052021f5,
 	0xf40464b6,
 	0xe7f11811,
 	0x21f41388,
 	0x0037f067,
-	0x04ca21f5,
+	0x04be21f5,
 	0x1388e7f1,
-/* 0x061f: i2c_bitw_out */
+/* 0x0613: i2c_bitw_out */
 	0xf86721f4,
-/* 0x0621: i2c_bitr */
+/* 0x0615: i2c_bitr */
 	0x0137f000,
-	0x04e621f5,
+	0x04da21f5,
 	0x03e8e7f1,
 	0xbb6721f4,
 	0x65b60076,
@@ -1256,19 +1253,19 @@ uint32_t nvd0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x052c21f5,
+	0x052021f5,
 	0xf40464b6,
 	0x21f51b11,
-	0x37f00517,
-	0xca21f500,
+	0x37f0050b,
+	0xbe21f500,
 	0x88e7f104,
 	0x6721f413,
 	0xf4013cf0,
-/* 0x0666: i2c_bitr_done */
+/* 0x065a: i2c_bitr_done */
 	0x00f80131,
-/* 0x0668: i2c_get_byte */
+/* 0x065c: i2c_get_byte */
 	0xf00057f0,
-/* 0x066e: i2c_get_byte_next */
+/* 0x0662: i2c_get_byte_next */
 	0x54b60847,
 	0x0076bb01,
 	0xf90465b6,
@@ -1276,7 +1273,7 @@ uint32_t nvd0_pwr_code[] = {
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60621,
+	0x64b60615,
 	0x2b11f404,
 	0xb60553fd,
 	0x1bf40142,
@@ -1286,12 +1283,12 @@ uint32_t nvd0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xe021f550,
+	0xd421f550,
 	0x0464b605,
-/* 0x06b8: i2c_get_byte_done */
-/* 0x06ba: i2c_put_byte */
+/* 0x06ac: i2c_get_byte_done */
+/* 0x06ae: i2c_put_byte */
 	0x47f000f8,
-/* 0x06bd: i2c_put_byte_next */
+/* 0x06b1: i2c_put_byte_next */
 	0x0142b608,
 	0xbb3854ff,
 	0x65b60076,
@@ -1299,7 +1296,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x05e021f5,
+	0x05d421f5,
 	0xf40464b6,
 	0x46b03411,
 	0xd81bf400,
@@ -1308,21 +1305,21 @@ uint32_t nvd0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x2121f550,
+	0x1521f550,
 	0x0464b606,
 	0xbb0f11f4,
 	0x36b00076,
 	0x061bf401,
-/* 0x0713: i2c_put_byte_done */
+/* 0x0707: i2c_put_byte_done */
 	0xf80132f4,
-/* 0x0715: i2c_addr */
+/* 0x0709: i2c_addr */
 	0x0076bb00,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60551,
+	0x64b60545,
 	0x2911f404,
 	0x012ec3e7,
 	0xfd0134b6,
@@ -1332,23 +1329,23 @@ uint32_t nvd0_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb606ba21,
-/* 0x075a: i2c_addr_done */
+	0xb606ae21,
+/* 0x074e: i2c_addr_done */
 	0x00f80464,
-/* 0x075c: i2c_acquire_addr */
+/* 0x0750: i2c_acquire_addr */
 	0xb6f8cec7,
 	0xe0b705e4,
 	0x00f8d014,
-/* 0x0768: i2c_acquire */
-	0x075c21f5,
+/* 0x075c: i2c_acquire */
+	0x075021f5,
 	0xf00421f4,
 	0x21f403d9,
-/* 0x0777: i2c_release */
+/* 0x076b: i2c_release */
 	0xf500f833,
-	0xf4075c21,
+	0xf4075021,
 	0xdaf00421,
 	0x3321f403,
-/* 0x0786: i2c_recv */
+/* 0x077a: i2c_recv */
 	0x32f400f8,
 	0xf8c1c701,
 	0xb00214b6,
@@ -1367,7 +1364,7 @@ uint32_t nvd0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x6821f550,
+	0x5c21f550,
 	0x0464b607,
 	0xd6b0d0fc,
 	0xb31bf500,
@@ -1377,7 +1374,7 @@ uint32_t nvd0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x1521f550,
+	0x0921f550,
 	0x0464b607,
 	0x00d011f5,
 	0xbbe0c5c7,
@@ -1386,7 +1383,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x06ba21f5,
+	0x06ae21f5,
 	0xf50464b6,
 	0xf000ad11,
 	0x76bb0157,
@@ -1395,7 +1392,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6071521,
+	0xb6070921,
 	0x11f50464,
 	0x76bb008a,
 	0x0465b600,
@@ -1403,7 +1400,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6066821,
+	0xb6065c21,
 	0x11f40464,
 	0xe05bcb6a,
 	0xb60076bb,
@@ -1411,38 +1408,38 @@ uint32_t nvd0_pwr_code[] = {
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0xad21f550,
+	0xa121f550,
 	0x0464b605,
 	0xbd025bb9,
 	0x430ef474,
-/* 0x088c: i2c_recv_not_rd08 */
+/* 0x0880: i2c_recv_not_rd08 */
 	0xf401d6b0,
 	0x57f03d1b,
-	0x1521f500,
+	0x0921f500,
 	0x3311f407,
 	0xf5e0c5c7,
-	0xf406ba21,
+	0xf406ae21,
 	0x57f02911,
-	0x1521f500,
+	0x0921f500,
 	0x1f11f407,
 	0xf5e0b5c7,
-	0xf406ba21,
+	0xf406ae21,
 	0x21f51511,
-	0x74bd05ad,
+	0x74bd05a1,
 	0xf408c5c7,
 	0x32f4091b,
 	0x030ef402,
-/* 0x08cc: i2c_recv_not_wr08 */
-/* 0x08cc: i2c_recv_done */
+/* 0x08c0: i2c_recv_not_wr08 */
+/* 0x08c0: i2c_recv_done */
 	0xf5f8cec7,
-	0xfc077721,
+	0xfc076b21,
 	0xf4d0fce0,
 	0x7cb90a12,
 	0x6b21f502,
-/* 0x08e1: i2c_recv_exit */
-/* 0x08e3: i2c_init */
+/* 0x08d5: i2c_recv_exit */
+/* 0x08d7: i2c_init */
 	0xf800f802,
-/* 0x08e5: test_recv */
+/* 0x08d9: test_recv */
 	0xd817f100,
 	0x0011cf05,
 	0xf10110b6,
@@ -1451,28 +1448,28 @@ uint32_t nvd0_pwr_code[] = {
 	0xd900e7f1,
 	0x134fe3f1,
 	0x01b621f5,
-/* 0x0906: test_init */
+/* 0x08fa: test_init */
 	0xe7f100f8,
 	0x21f50800,
 	0x00f801b6,
-/* 0x0910: idle_recv */
-/* 0x0912: idle */
+/* 0x0904: idle_recv */
+/* 0x0906: idle */
 	0x31f400f8,
 	0xd417f100,
 	0x0011cf05,
 	0xf10110b6,
 	0xd005d407,
 	0x04bd0001,
-/* 0x0928: idle_loop */
+/* 0x091c: idle_loop */
 	0xf45817f0,
-/* 0x092e: idle_proc */
-/* 0x092e: idle_proc_exec */
+/* 0x0922: idle_proc */
+/* 0x0922: idle_proc_exec */
 	0x10f90232,
 	0xf5021eb9,
 	0xfc027421,
 	0x0911f410,
 	0xf40231f4,
-/* 0x0942: idle_proc_next */
+/* 0x0936: idle_proc_next */
 	0x10b6ef0e,
 	0x061fb858,
 	0xf4e61bf4,
@@ -1481,6 +1478,9 @@ uint32_t nvd0_pwr_code[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 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"
+
+#define nvd0_pwr_code gk104_pwr_code
+#define nvd0_pwr_data gk104_pwr_data
+#include "fuc/nvd0.fuc.h"
+
+static void
+gk104_pwr_pgob(struct nouveau_pwr *ppwr, bool enable)
+{
+	nv_mask(ppwr, 0x000200, 0x00001000, 0x00000000);
+	nv_rd32(ppwr, 0x000200);
+	nv_mask(ppwr, 0x000200, 0x08000000, 0x08000000);
+	msleep(50);
+
+	nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000002);
+	nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001);
+	nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000);
+
+	nv_mask(ppwr, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000);
+	msleep(50);
+
+	nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000000);
+	nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001);
+	nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000);
+
+	nv_mask(ppwr, 0x000200, 0x08000000, 0x00000000);
+	nv_mask(ppwr, 0x000200, 0x00001000, 0x00001000);
+	nv_rd32(ppwr, 0x000200);
+}
+
+struct nouveau_oclass *
+gk104_pwr_oclass = &(struct nvkm_pwr_impl) {
+	.base.handle = NV_SUBDEV(PWR, 0xe4),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nouveau_pwr_ctor,
+		.dtor = _nouveau_pwr_dtor,
+		.init = _nouveau_pwr_init,
+		.fini = _nouveau_pwr_fini,
+	},
+	.code.data = gk104_pwr_code,
+	.code.size = sizeof(gk104_pwr_code),
+	.data.data = gk104_pwr_data,
+	.data.size = sizeof(gk104_pwr_data),
+	.pgob = gk104_pwr_pgob,
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,7 @@
 #ifndef __NVKM_PWR_MEMX_H__
 #define __NVKM_PWR_MEMX_H__
 
-#include <subdev/pwr.h>
-#include <subdev/pwr/fuc/os.h>
+#include "priv.h"
 
 struct nouveau_memx {
 	struct nouveau_pwr *ppwr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,41 +22,20 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/pwr.h>
-
+#include "priv.h"
 #include "fuc/nv108.fuc.h"
 
-struct nv108_pwr_priv {
-	struct nouveau_pwr base;
-};
-
-static int
-nv108_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	       struct nouveau_oclass *oclass, void *data, u32 size,
-	       struct nouveau_object **pobject)
-{
-	struct nv108_pwr_priv *priv;
-	int ret;
-
-	ret = nouveau_pwr_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.code.data = nv108_pwr_code;
-	priv->base.code.size = sizeof(nv108_pwr_code);
-	priv->base.data.data = nv108_pwr_data;
-	priv->base.data.size = sizeof(nv108_pwr_data);
-	return 0;
-}
-
-struct nouveau_oclass
-nv108_pwr_oclass = {
-	.handle = NV_SUBDEV(PWR, 0x00),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv108_pwr_ctor,
+struct nouveau_oclass *
+nv108_pwr_oclass = &(struct nvkm_pwr_impl) {
+	.base.handle = NV_SUBDEV(PWR, 0x00),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nouveau_pwr_ctor,
 		.dtor = _nouveau_pwr_dtor,
 		.init = _nouveau_pwr_init,
 		.fini = _nouveau_pwr_fini,
 	},
-};
+	.code.data = nv108_pwr_code,
+	.code.size = sizeof(nv108_pwr_code),
+	.data.data = nv108_pwr_data,
+	.data.size = sizeof(nv108_pwr_data),
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,50 +22,29 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/pwr.h>
-
+#include "priv.h"
 #include "fuc/nva3.fuc.h"
 
-struct nva3_pwr_priv {
-	struct nouveau_pwr base;
-};
-
 static int
 nva3_pwr_init(struct nouveau_object *object)
 {
-	struct nva3_pwr_priv *priv = (void *)object;
-	nv_mask(priv, 0x022210, 0x00000001, 0x00000000);
-	nv_mask(priv, 0x022210, 0x00000001, 0x00000001);
-	return nouveau_pwr_init(&priv->base);
-}
-
-static int
-nva3_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	      struct nouveau_oclass *oclass, void *data, u32 size,
-	      struct nouveau_object **pobject)
-{
-	struct nva3_pwr_priv *priv;
-	int ret;
-
-	ret = nouveau_pwr_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.code.data = nva3_pwr_code;
-	priv->base.code.size = sizeof(nva3_pwr_code);
-	priv->base.data.data = nva3_pwr_data;
-	priv->base.data.size = sizeof(nva3_pwr_data);
-	return 0;
+	struct nouveau_pwr *ppwr = (void *)object;
+	nv_mask(ppwr, 0x022210, 0x00000001, 0x00000000);
+	nv_mask(ppwr, 0x022210, 0x00000001, 0x00000001);
+	return nouveau_pwr_init(ppwr);
 }
 
-struct nouveau_oclass
-nva3_pwr_oclass = {
-	.handle = NV_SUBDEV(PWR, 0xa3),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nva3_pwr_ctor,
+struct nouveau_oclass *
+nva3_pwr_oclass = &(struct nvkm_pwr_impl) {
+	.base.handle = NV_SUBDEV(PWR, 0xa3),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nouveau_pwr_ctor,
 		.dtor = _nouveau_pwr_dtor,
 		.init = nva3_pwr_init,
 		.fini = _nouveau_pwr_fini,
 	},
-};
+	.code.data = nva3_pwr_code,
+	.code.size = sizeof(nva3_pwr_code),
+	.data.data = nva3_pwr_data,
+	.data.size = sizeof(nva3_pwr_data),
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,41 +22,20 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/pwr.h>
-
+#include "priv.h"
 #include "fuc/nvc0.fuc.h"
 
-struct nvc0_pwr_priv {
-	struct nouveau_pwr base;
-};
-
-static int
-nvc0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	      struct nouveau_oclass *oclass, void *data, u32 size,
-	      struct nouveau_object **pobject)
-{
-	struct nvc0_pwr_priv *priv;
-	int ret;
-
-	ret = nouveau_pwr_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.code.data = nvc0_pwr_code;
-	priv->base.code.size = sizeof(nvc0_pwr_code);
-	priv->base.data.data = nvc0_pwr_data;
-	priv->base.data.size = sizeof(nvc0_pwr_data);
-	return 0;
-}
-
-struct nouveau_oclass
-nvc0_pwr_oclass = {
-	.handle = NV_SUBDEV(PWR, 0xc0),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nvc0_pwr_ctor,
+struct nouveau_oclass *
+nvc0_pwr_oclass = &(struct nvkm_pwr_impl) {
+	.base.handle = NV_SUBDEV(PWR, 0xc0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nouveau_pwr_ctor,
 		.dtor = _nouveau_pwr_dtor,
 		.init = _nouveau_pwr_init,
 		.fini = _nouveau_pwr_fini,
 	},
-};
+	.code.data = nvc0_pwr_code,
+	.code.size = sizeof(nvc0_pwr_code),
+	.data.data = nvc0_pwr_data,
+	.data.size = sizeof(nvc0_pwr_data),
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,41 +22,20 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/pwr.h>
-
+#include "priv.h"
 #include "fuc/nvd0.fuc.h"
 
-struct nvd0_pwr_priv {
-	struct nouveau_pwr base;
-};
-
-static int
-nvd0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	      struct nouveau_oclass *oclass, void *data, u32 size,
-	      struct nouveau_object **pobject)
-{
-	struct nvd0_pwr_priv *priv;
-	int ret;
-
-	ret = nouveau_pwr_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.code.data = nvd0_pwr_code;
-	priv->base.code.size = sizeof(nvd0_pwr_code);
-	priv->base.data.data = nvd0_pwr_data;
-	priv->base.data.size = sizeof(nvd0_pwr_data);
-	return 0;
-}
-
-struct nouveau_oclass
-nvd0_pwr_oclass = {
-	.handle = NV_SUBDEV(PWR, 0xd0),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nvd0_pwr_ctor,
+struct nouveau_oclass *
+nvd0_pwr_oclass = &(struct nvkm_pwr_impl) {
+	.base.handle = NV_SUBDEV(PWR, 0xd0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = _nouveau_pwr_ctor,
 		.dtor = _nouveau_pwr_dtor,
 		.init = _nouveau_pwr_init,
 		.fini = _nouveau_pwr_fini,
 	},
-};
+	.code.data = nvd0_pwr_code,
+	.code.size = sizeof(nvd0_pwr_code),
+	.data.data = nvd0_pwr_data,
+	.data.size = sizeof(nvd0_pwr_data),
+}.base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,44 @@
+#ifndef __NVKM_PWR_PRIV_H__
+#define __NVKM_PWR_PRIV_H__
+
+#include <subdev/pwr.h>
+#include <subdev/pwr/fuc/os.h>
+
+#define nouveau_pwr_create(p, e, o, d)                                         \
+	nouveau_pwr_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_pwr_destroy(p)                                                 \
+	nouveau_subdev_destroy(&(p)->base)
+#define nouveau_pwr_init(p) ({                                                 \
+	struct nouveau_pwr *_ppwr = (p);                                       \
+	_nouveau_pwr_init(nv_object(_ppwr));                                   \
+})
+#define nouveau_pwr_fini(p,s) ({                                               \
+	struct nouveau_pwr *_ppwr = (p);                                       \
+	_nouveau_pwr_fini(nv_object(_ppwr), (s));                              \
+})
+
+int nouveau_pwr_create_(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, int, void **);
+
+int _nouveau_pwr_ctor(struct nouveau_object *, struct nouveau_object *,
+		      struct nouveau_oclass *, void *, u32,
+		      struct nouveau_object **);
+#define _nouveau_pwr_dtor _nouveau_subdev_dtor
+int _nouveau_pwr_init(struct nouveau_object *);
+int _nouveau_pwr_fini(struct nouveau_object *, bool);
+
+struct nvkm_pwr_impl {
+	struct nouveau_oclass base;
+	struct {
+		u32 *data;
+		u32  size;
+	} code;
+	struct {
+		u32 *data;
+		u32  size;
+	} data;
+
+	void (*pgob)(struct nouveau_pwr *, bool);
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 #include <subdev/timer.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
 #include <subdev/bar.h>
 
 struct nvc0_vmmgr_priv {
@@ -116,12 +116,12 @@ nvc0_vm_map(struct nouveau_vma *vma, str
 	pte <<= 3;
 
 	if (mem->tag) {
-		struct nouveau_ltcg *ltcg =
-			nouveau_ltcg(vma->vm->vmm->base.base.parent);
+		struct nouveau_ltc *ltc =
+			nouveau_ltc(vma->vm->vmm->base.base.parent);
 		u32 tag = mem->tag->offset + (delta >> 17);
 		phys |= (u64)tag << (32 + 12);
 		next |= (u64)1   << (32 + 12);
-		ltcg->tags_clear(ltcg, tag, cnt);
+		ltc->tags_clear(ltc, tag, cnt);
 	}
 
 	while (cnt--) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c	2014-09-28 17:29:07.000000000 -0400
@@ -198,12 +198,12 @@ nv04_update_arb(struct drm_device *dev,
 		int *burst, int *lwm)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nv_fifo_info fifo_data;
 	struct nv_sim_state sim_data;
 	int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY);
 	int NVClk = nouveau_hw_get_clock(dev, PLL_CORE);
-	uint32_t cfg1 = nv_rd32(device, NV04_PFB_CFG1);
+	uint32_t cfg1 = nvif_rd32(device, NV04_PFB_CFG1);
 
 	sim_data.pclk_khz = VClk;
 	sim_data.mclk_khz = MClk;
@@ -221,13 +221,13 @@ nv04_update_arb(struct drm_device *dev,
 		sim_data.mem_latency = 3;
 		sim_data.mem_page_miss = 10;
 	} else {
-		sim_data.memory_type = nv_rd32(device, NV04_PFB_CFG0) & 0x1;
-		sim_data.memory_width = (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
+		sim_data.memory_type = nvif_rd32(device, NV04_PFB_CFG0) & 0x1;
+		sim_data.memory_width = (nvif_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
 		sim_data.mem_latency = cfg1 & 0xf;
 		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
 	}
 
-	if (nv_device(drm->device)->card_type == NV_04)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT)
 		nv04_calc_arb(&fifo_data, &sim_data);
 	else
 		nv10_calc_arb(&fifo_data, &sim_data);
@@ -254,7 +254,7 @@ nouveau_calc_arb(struct drm_device *dev,
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
-	if (nv_device(drm->device)->card_type < NV_20)
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_KELVIN)
 		nv04_update_arb(dev, vclk, bpp, burst, lwm);
 	else if ((dev->pdev->device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ ||
 		 (dev->pdev->device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,8 +111,8 @@ static void nv_crtc_calc_state_ext(struc
 {
 	struct drm_device *dev = crtc->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_bios *bios = nouveau_bios(drm->device);
-	struct nouveau_clock *clk = nouveau_clock(drm->device);
+	struct nouveau_bios *bios = nvkm_bios(&drm->device);
+	struct nouveau_clock *clk = nvkm_clock(&drm->device);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
 	struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index];
@@ -136,7 +136,7 @@ static void nv_crtc_calc_state_ext(struc
 	 * has yet been observed in allowing the use a single stage pll on all
 	 * nv43 however.  the behaviour of single stage use is untested on nv40
 	 */
-	if (nv_device(drm->device)->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2))
+	if (drm->device.info.chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2))
 		memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2));
 
 
@@ -146,10 +146,10 @@ static void nv_crtc_calc_state_ext(struc
 	state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK;
 
 	/* The blob uses this always, so let's do the same */
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE;
 	/* again nv40 and some nv43 act more like nv3x as described above */
-	if (nv_device(drm->device)->chipset < 0x41)
+	if (drm->device.info.chipset < 0x41)
 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL |
 				 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL;
 	state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK;
@@ -275,7 +275,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *cr
 		horizEnd = horizTotal - 2;
 		horizBlankEnd = horizTotal + 4;
 #if 0
-		if (dev->overlayAdaptor && nv_device(drm->device)->card_type >= NV_10)
+		if (dev->overlayAdaptor && drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
 			/* This reportedly works around some video overlay bandwidth problems */
 			horizTotal += 2;
 #endif
@@ -509,7 +509,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *c
 	regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 |
 			     NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 |
 			     NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM;
-	if (nv_device(drm->device)->chipset >= 0x11)
+	if (drm->device.info.chipset >= 0x11)
 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32;
 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE;
@@ -550,26 +550,26 @@ nv_crtc_mode_set_regs(struct drm_crtc *c
 	 * 1 << 30 on 0x60.830), for no apparent reason */
 	regp->CRTC[NV_CIO_CRE_59] = off_chip_digital;
 
-	if (nv_device(drm->device)->card_type >= NV_30)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 		regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1;
 
 	regp->crtc_830 = mode->crtc_vdisplay - 3;
 	regp->crtc_834 = mode->crtc_vdisplay - 1;
 
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		/* This is what the blob does */
 		regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850);
 
-	if (nv_device(drm->device)->card_type >= NV_30)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 		regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT);
 
-	if (nv_device(drm->device)->card_type >= NV_10)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
 		regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC;
 	else
 		regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC;
 
 	/* Some misc regs */
-	if (nv_device(drm->device)->card_type == NV_40) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
 		regp->CRTC[NV_CIO_CRE_85] = 0xFF;
 		regp->CRTC[NV_CIO_CRE_86] = 0x1;
 	}
@@ -581,7 +581,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *c
 
 	/* Generic PRAMDAC regs */
 
-	if (nv_device(drm->device)->card_type >= NV_10)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
 		/* Only bit that bios and blob set. */
 		regp->nv10_cursync = (1 << 25);
 
@@ -590,7 +590,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *c
 				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
 	if (crtc->primary->fb->depth == 16)
 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
-	if (nv_device(drm->device)->chipset >= 0x11)
+	if (drm->device.info.chipset >= 0x11)
 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
 
 	regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */
@@ -653,7 +653,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc,
 
 	nv_crtc_mode_set_vga(crtc, adjusted_mode);
 	/* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk);
 	nv_crtc_mode_set_regs(crtc, adjusted_mode);
 	nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock);
@@ -714,7 +714,7 @@ static void nv_crtc_prepare(struct drm_c
 
 	/* Some more preparation. */
 	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
-	if (nv_device(drm->device)->card_type == NV_40) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
 		uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900);
 		NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000);
 	}
@@ -888,7 +888,7 @@ nv04_crtc_do_mode_set_base(struct drm_cr
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
 
-	if (nv_device(drm->device)->card_type >= NV_20) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN) {
 		regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
 		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
 	}
@@ -915,9 +915,9 @@ nv04_crtc_mode_set_base_atomic(struct dr
 	struct drm_device *dev = drm->dev;
 
 	if (state == ENTER_ATOMIC_MODE_SET)
-		nouveau_fbcon_save_disable_accel(dev);
+		nouveau_fbcon_accel_save_disable(dev);
 	else
-		nouveau_fbcon_restore_accel(dev);
+		nouveau_fbcon_accel_restore(dev);
 
 	return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
 }
@@ -969,7 +969,7 @@ static void nv11_cursor_upload(struct dr
 		{
 			struct nouveau_drm *drm = nouveau_drm(dev);
 
-			if (nv_device(drm->device)->chipset == 0x11) {
+			if (drm->device.info.chipset == 0x11) {
 				pixel = ((pixel & 0x000000ff) << 24) |
 					((pixel & 0x0000ff00) << 8) |
 					((pixel & 0x00ff0000) >> 8) |
@@ -1010,7 +1010,7 @@ nv04_crtc_cursor_set(struct drm_crtc *cr
 	if (ret)
 		goto out;
 
-	if (nv_device(drm->device)->chipset >= 0x11)
+	if (drm->device.info.chipset >= 0x11)
 		nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
 	else
 		nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,7 @@ nv04_cursor_set_offset(struct nouveau_cr
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		nv_fix_nv40_hw_cursor(dev, nv_crtc->index);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,8 +65,8 @@ int nv04_dac_output_offset(struct drm_en
 
 static int sample_load_twice(struct drm_device *dev, bool sense[2])
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	struct nouveau_timer *ptimer = nouveau_timer(device);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	struct nouveau_timer *ptimer = nvkm_timer(device);
 	int i;
 
 	for (i = 0; i < 2; i++) {
@@ -95,15 +95,15 @@ static int sample_load_twice(struct drm_
 
 		udelay(100);
 		/* when level triggers, sense is _LO_ */
-		sense_a = nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+		sense_a = nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
 
 		/* take another reading until it agrees with sense_a... */
 		do {
 			udelay(100);
-			sense_b = nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+			sense_b = nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
 			if (sense_a != sense_b) {
 				sense_b_prime =
-					nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+					nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
 				if (sense_b == sense_b_prime) {
 					/* ... unless two consecutive subsequent
 					 * samples agree; sense_a is replaced */
@@ -128,7 +128,7 @@ static enum drm_connector_status nv04_da
 						 struct drm_connector *connector)
 {
 	struct drm_device *dev = encoder->dev;
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode;
 	uint8_t saved_palette0[3], saved_palette_mask;
@@ -164,11 +164,11 @@ static enum drm_connector_status nv04_da
 	saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX);
 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0);
 
-	nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
+	nvif_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
 	for (i = 0; i < 3; i++)
-		saved_palette0[i] = nv_rd08(device, NV_PRMDIO_PALETTE_DATA);
-	saved_palette_mask = nv_rd08(device, NV_PRMDIO_PIXEL_MASK);
-	nv_wr08(device, NV_PRMDIO_PIXEL_MASK, 0);
+		saved_palette0[i] = nvif_rd08(device, NV_PRMDIO_PALETTE_DATA);
+	saved_palette_mask = nvif_rd08(device, NV_PRMDIO_PIXEL_MASK);
+	nvif_wr08(device, NV_PRMDIO_PIXEL_MASK, 0);
 
 	saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL);
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL,
@@ -181,11 +181,11 @@ static enum drm_connector_status nv04_da
 	do {
 		bool sense_pair[2];
 
-		nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
-		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
-		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
+		nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+		nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
+		nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
 		/* testing blue won't find monochrome monitors.  I don't care */
-		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, blue);
+		nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, blue);
 
 		i = 0;
 		/* take sample pairs until both samples in the pair agree */
@@ -208,11 +208,11 @@ static enum drm_connector_status nv04_da
 	} while (++blue < 0x18 && sense);
 
 out:
-	nv_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
+	nvif_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl);
-	nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+	nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
 	for (i = 0; i < 3; i++)
-		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
+		nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl);
 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi);
 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1);
@@ -231,8 +231,8 @@ uint32_t nv17_dac_sample_load(struct drm
 {
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nouveau_dev(dev);
-	struct nouveau_gpio *gpio = nouveau_gpio(device);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	struct nouveau_gpio *gpio = nvkm_gpio(device);
 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
 	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
@@ -256,12 +256,12 @@ uint32_t nv17_dac_sample_load(struct drm
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
 		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
 
-	saved_powerctrl_2 = nv_rd32(device, NV_PBUS_POWERCTRL_2);
+	saved_powerctrl_2 = nvif_rd32(device, NV_PBUS_POWERCTRL_2);
 
-	nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
+	nvif_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
 	if (regoffset == 0x68) {
-		saved_powerctrl_4 = nv_rd32(device, NV_PBUS_POWERCTRL_4);
-		nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
+		saved_powerctrl_4 = nvif_rd32(device, NV_PBUS_POWERCTRL_4);
+		nvif_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
 	}
 
 	if (gpio) {
@@ -283,7 +283,7 @@ uint32_t nv17_dac_sample_load(struct drm
 	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
 	routput = (saved_routput & 0xfffffece) | head << 8;
 
-	if (nv_device(drm->device)->card_type >= NV_40) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CURIE) {
 		if (dcb->type == DCB_OUTPUT_TV)
 			routput |= 0x1a << 16;
 		else
@@ -316,8 +316,8 @@ uint32_t nv17_dac_sample_load(struct drm
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
 	if (regoffset == 0x68)
-		nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
-	nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
+		nvif_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
+	nvif_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
 
 	if (gpio) {
 		gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1);
@@ -398,7 +398,7 @@ static void nv04_dac_mode_set(struct drm
 	}
 
 	/* This could use refinement for flatpanels, but it should work this way */
-	if (nv_device(drm->device)->chipset < 0x44)
+	if (drm->device.info.chipset < 0x44)
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
 	else
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c	2014-09-28 17:29:07.000000000 -0400
@@ -281,7 +281,7 @@ static void nv04_dfp_mode_set(struct drm
 			      struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
@@ -335,7 +335,7 @@ static void nv04_dfp_mode_set(struct drm
 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE;
 	else /* gpu needs to scale */
 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE;
-	if (nv_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
+	if (nvif_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
 	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP &&
 	    output_mode->clock > 165000)
@@ -416,7 +416,7 @@ static void nv04_dfp_mode_set(struct drm
 	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
 	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
 	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
-		if (nv_device(drm->device)->chipset == 0x11)
+		if (drm->device.info.chipset == 0x11)
 			regp->dither = savep->dither | 0x00010000;
 		else {
 			int i;
@@ -427,7 +427,7 @@ static void nv04_dfp_mode_set(struct drm
 			}
 		}
 	} else {
-		if (nv_device(drm->device)->chipset != 0x11) {
+		if (drm->device.info.chipset != 0x11) {
 			/* reset them */
 			int i;
 			for (i = 0; i < 3; i++) {
@@ -463,7 +463,7 @@ static void nv04_dfp_commit(struct drm_e
 		NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
 
 	/* This could use refinement for flatpanels, but it should work this way */
-	if (nv_device(drm->device)->chipset < 0x44)
+	if (drm->device.info.chipset < 0x44)
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
 	else
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
@@ -485,7 +485,7 @@ static void nv04_dfp_update_backlight(st
 {
 #ifdef __powerpc__
 	struct drm_device *dev = encoder->dev;
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 
 	/* BIOS scripts usually take care of the backlight, thanks
 	 * Apple for your consistency.
@@ -623,7 +623,7 @@ static void nv04_tmds_slave_init(struct
 	struct drm_device *dev = encoder->dev;
 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct nouveau_i2c_port *port = i2c->find(i2c, 2);
 	struct nouveau_i2c_board_info info[] = {
 		{
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,6 @@
  * Author: Ben Skeggs
  */
 
-#include <core/object.h>
-#include <core/class.h>
-
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -34,8 +31,6 @@
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
 
-#include <subdev/i2c.h>
-
 int
 nv04_display_early_init(struct drm_device *dev)
 {
@@ -58,7 +53,7 @@ int
 nv04_display_create(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct dcb_table *dcb = &drm->vbios.dcb;
 	struct drm_connector *connector, *ct;
 	struct drm_encoder *encoder;
@@ -70,6 +65,8 @@ nv04_display_create(struct drm_device *d
 	if (!disp)
 		return -ENOMEM;
 
+	nvif_object_map(nvif_object(&drm->device));
+
 	nouveau_display(dev)->priv = disp;
 	nouveau_display(dev)->dtor = nv04_display_destroy;
 	nouveau_display(dev)->init = nv04_display_init;
@@ -144,6 +141,7 @@ void
 nv04_display_destroy(struct drm_device *dev)
 {
 	struct nv04_display *disp = nv04_display(dev);
+	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
 
@@ -170,6 +168,8 @@ nv04_display_destroy(struct drm_device *
 
 	nouveau_display(dev)->priv = NULL;
 	kfree(disp);
+
+	nvif_object_unmap(nvif_object(&drm->device));
 }
 
 int
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h	2014-09-28 17:29:07.000000000 -0400
@@ -131,7 +131,7 @@ nv_two_heads(struct drm_device *dev)
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	const int impl = dev->pdev->device & 0x0ff0;
 
-	if (nv_device(drm->device)->card_type >= NV_10 && impl != 0x0100 &&
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS && impl != 0x0100 &&
 	    impl != 0x0150 && impl != 0x01a0 && impl != 0x0200)
 		return true;
 
@@ -150,7 +150,7 @@ nv_two_reg_pll(struct drm_device *dev)
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	const int impl = dev->pdev->device & 0x0ff0;
 
-	if (impl == 0x0310 || impl == 0x0340 || nv_device(drm->device)->card_type >= NV_40)
+	if (impl == 0x0310 || impl == 0x0340 || drm->device.info.family >= NV_DEVICE_INFO_V0_CURIE)
 		return true;
 	return false;
 }
@@ -171,8 +171,8 @@ static inline void
 nouveau_bios_run_init_table(struct drm_device *dev, u16 table,
 			    struct dcb_output *outp, int crtc)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	struct nouveau_bios *bios = nouveau_bios(device);
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_bios *bios = nvkm_bios(&drm->device);
 	struct nvbios_init init = {
 		.subdev = nv_subdev(bios),
 		.bios = bios,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,9 +27,6 @@
 #include "hw.h"
 
 #include <subdev/bios/pll.h>
-#include <subdev/fb.h>
-#include <subdev/clock.h>
-#include <subdev/timer.h>
 
 #define CHIPSET_NFORCE 0x01a0
 #define CHIPSET_NFORCE2 0x01f0
@@ -92,7 +89,7 @@ NVSetOwner(struct drm_device *dev, int o
 	if (owner == 1)
 		owner *= 3;
 
-	if (nv_device(drm->device)->chipset == 0x11) {
+	if (drm->device.info.chipset == 0x11) {
 		/* This might seem stupid, but the blob does it and
 		 * omitting it often locks the system up.
 		 */
@@ -103,7 +100,7 @@ NVSetOwner(struct drm_device *dev, int o
 	/* CR44 is always changed on CRTC0 */
 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner);
 
-	if (nv_device(drm->device)->chipset == 0x11) {	/* set me harder */
+	if (drm->device.info.chipset == 0x11) {	/* set me harder */
 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
 	}
@@ -152,7 +149,7 @@ nouveau_hw_decode_pll(struct drm_device
 		pllvals->NM1 = pll1 & 0xffff;
 		if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2)
 			pllvals->NM2 = pll2 & 0xffff;
-		else if (nv_device(drm->device)->chipset == 0x30 || nv_device(drm->device)->chipset == 0x35) {
+		else if (drm->device.info.chipset == 0x30 || drm->device.info.chipset == 0x35) {
 			pllvals->M1 &= 0xf; /* only 4 bits */
 			if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
 				pllvals->M2 = (pll1 >> 4) & 0x7;
@@ -168,8 +165,8 @@ nouveau_hw_get_pllvals(struct drm_device
 		       struct nouveau_pll_vals *pllvals)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_bios *bios = nouveau_bios(device);
+	struct nvif_device *device = &drm->device;
+	struct nouveau_bios *bios = nvkm_bios(device);
 	uint32_t reg1, pll1, pll2 = 0;
 	struct nvbios_pll pll_lim;
 	int ret;
@@ -178,16 +175,16 @@ nouveau_hw_get_pllvals(struct drm_device
 	if (ret || !(reg1 = pll_lim.reg))
 		return -ENOENT;
 
-	pll1 = nv_rd32(device, reg1);
+	pll1 = nvif_rd32(device, reg1);
 	if (reg1 <= 0x405c)
-		pll2 = nv_rd32(device, reg1 + 4);
+		pll2 = nvif_rd32(device, reg1 + 4);
 	else if (nv_two_reg_pll(dev)) {
 		uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70);
 
-		pll2 = nv_rd32(device, reg2);
+		pll2 = nvif_rd32(device, reg2);
 	}
 
-	if (nv_device(drm->device)->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
 		uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580);
 
 		/* check whether vpll has been forced into single stage mode */
@@ -255,9 +252,9 @@ nouveau_hw_fix_bad_vpll(struct drm_devic
 	 */
 
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_clock *clk = nouveau_clock(device);
-	struct nouveau_bios *bios = nouveau_bios(device);
+	struct nvif_device *device = &drm->device;
+	struct nouveau_clock *clk = nvkm_clock(device);
+	struct nouveau_bios *bios = nvkm_bios(device);
 	struct nvbios_pll pll_lim;
 	struct nouveau_pll_vals pv;
 	enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0;
@@ -394,21 +391,21 @@ nv_save_state_ramdac(struct drm_device *
 	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
 	int i;
 
-	if (nv_device(drm->device)->card_type >= NV_10)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
 		regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC);
 
 	nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, &regp->pllvals);
 	state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
 	if (nv_two_heads(dev))
 		state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK);
-	if (nv_device(drm->device)->chipset == 0x11)
+	if (drm->device.info.chipset == 0x11)
 		regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11);
 
 	regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL);
 
 	if (nv_gf4_disp_arch(dev))
 		regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630);
-	if (nv_device(drm->device)->chipset >= 0x30)
+	if (drm->device.info.chipset >= 0x30)
 		regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634);
 
 	regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP);
@@ -450,7 +447,7 @@ nv_save_state_ramdac(struct drm_device *
 	if (nv_gf4_disp_arch(dev))
 		regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0);
 
-	if (nv_device(drm->device)->card_type == NV_40) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
 		regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20);
 		regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24);
 		regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34);
@@ -466,26 +463,26 @@ nv_load_state_ramdac(struct drm_device *
 		     struct nv04_mode_state *state)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_clock *clk = nouveau_clock(drm->device);
+	struct nouveau_clock *clk = nvkm_clock(&drm->device);
 	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
 	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
 	int i;
 
-	if (nv_device(drm->device)->card_type >= NV_10)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
 		NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
 
 	clk->pll_prog(clk, pllreg, &regp->pllvals);
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
 	if (nv_two_heads(dev))
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
-	if (nv_device(drm->device)->chipset == 0x11)
+	if (drm->device.info.chipset == 0x11)
 		NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither);
 
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
 
 	if (nv_gf4_disp_arch(dev))
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630);
-	if (nv_device(drm->device)->chipset >= 0x30)
+	if (drm->device.info.chipset >= 0x30)
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634);
 
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup);
@@ -522,7 +519,7 @@ nv_load_state_ramdac(struct drm_device *
 	if (nv_gf4_disp_arch(dev))
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0);
 
-	if (nv_device(drm->device)->card_type == NV_40) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20);
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24);
 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34);
@@ -603,10 +600,10 @@ nv_save_state_ext(struct drm_device *dev
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_21);
 
-	if (nv_device(drm->device)->card_type >= NV_20)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN)
 		rd_cio_state(dev, head, regp, NV_CIO_CRE_47);
 
-	if (nv_device(drm->device)->card_type >= NV_30)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 		rd_cio_state(dev, head, regp, 0x9f);
 
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_49);
@@ -615,14 +612,14 @@ nv_save_state_ext(struct drm_device *dev
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
 
-	if (nv_device(drm->device)->card_type >= NV_10) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
 		regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830);
 		regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834);
 
-		if (nv_device(drm->device)->card_type >= NV_30)
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 			regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT);
 
-		if (nv_device(drm->device)->card_type == NV_40)
+		if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 			regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850);
 
 		if (nv_two_heads(dev))
@@ -634,7 +631,7 @@ nv_save_state_ext(struct drm_device *dev
 
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
-	if (nv_device(drm->device)->card_type >= NV_10) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
 		rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
 		rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
 		rd_cio_state(dev, head, regp, NV_CIO_CRE_4B);
@@ -663,14 +660,13 @@ nv_load_state_ext(struct drm_device *dev
 		  struct nv04_mode_state *state)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_timer *ptimer = nouveau_timer(device);
-	struct nouveau_fb *pfb = nouveau_fb(device);
+	struct nvif_device *device = &drm->device;
+	struct nouveau_timer *ptimer = nvkm_timer(device);
 	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
 	uint32_t reg900;
 	int i;
 
-	if (nv_device(drm->device)->card_type >= NV_10) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
 		if (nv_two_heads(dev))
 			/* setting ENGINE_CTRL (EC) *must* come before
 			 * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in
@@ -678,24 +674,24 @@ nv_load_state_ext(struct drm_device *dev
 			 */
 			NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl);
 
-		nv_wr32(device, NV_PVIDEO_STOP, 1);
-		nv_wr32(device, NV_PVIDEO_INTR_EN, 0);
-		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);
-		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0);
-		nv_wr32(device, NV_PVIDEO_LIMIT(0), pfb->ram->size - 1);
-		nv_wr32(device, NV_PVIDEO_LIMIT(1), pfb->ram->size - 1);
-		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), pfb->ram->size - 1);
-		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), pfb->ram->size - 1);
-		nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);
+		nvif_wr32(device, NV_PVIDEO_STOP, 1);
+		nvif_wr32(device, NV_PVIDEO_INTR_EN, 0);
+		nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);
+		nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0);
+		nvif_wr32(device, NV_PVIDEO_LIMIT(0), device->info.ram_size - 1);
+		nvif_wr32(device, NV_PVIDEO_LIMIT(1), device->info.ram_size - 1);
+		nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), device->info.ram_size - 1);
+		nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), device->info.ram_size - 1);
+		nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
 
 		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
 		NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830);
 		NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834);
 
-		if (nv_device(drm->device)->card_type >= NV_30)
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 			NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext);
 
-		if (nv_device(drm->device)->card_type == NV_40) {
+		if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
 			NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850);
 
 			reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900);
@@ -718,23 +714,23 @@ nv_load_state_ext(struct drm_device *dev
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
 
-	if (nv_device(drm->device)->card_type >= NV_20)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN)
 		wr_cio_state(dev, head, regp, NV_CIO_CRE_47);
 
-	if (nv_device(drm->device)->card_type >= NV_30)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
 		wr_cio_state(dev, head, regp, 0x9f);
 
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_49);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		nv_fix_nv40_hw_cursor(dev, head);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
 
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
-	if (nv_device(drm->device)->card_type >= NV_10) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
 		wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
 		wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
 		wr_cio_state(dev, head, regp, NV_CIO_CRE_4B);
@@ -742,7 +738,7 @@ nv_load_state_ext(struct drm_device *dev
 	}
 	/* NV11 and NV20 stop at 0x52. */
 	if (nv_gf4_disp_arch(dev)) {
-		if (nv_device(drm->device)->card_type < NV_20) {
+		if (drm->device.info.family < NV_DEVICE_INFO_V0_KELVIN) {
 			/* Not waiting for vertical retrace before modifying
 			   CRE_53/CRE_54 causes lockups. */
 			nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
@@ -769,15 +765,15 @@ static void
 nv_save_state_palette(struct drm_device *dev, int head,
 		      struct nv04_mode_state *state)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	int head_offset = head * NV_PRMDIO_SIZE, i;
 
-	nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
+	nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
 				NV_PRMDIO_PIXEL_MASK_MASK);
-	nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
+	nvif_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
 
 	for (i = 0; i < 768; i++) {
-		state->crtc_reg[head].DAC[i] = nv_rd08(device,
+		state->crtc_reg[head].DAC[i] = nvif_rd08(device,
 				NV_PRMDIO_PALETTE_DATA + head_offset);
 	}
 
@@ -788,15 +784,15 @@ void
 nouveau_hw_load_state_palette(struct drm_device *dev, int head,
 			      struct nv04_mode_state *state)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	int head_offset = head * NV_PRMDIO_SIZE, i;
 
-	nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
+	nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
 				NV_PRMDIO_PIXEL_MASK_MASK);
-	nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
+	nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
 
 	for (i = 0; i < 768; i++) {
-		nv_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset,
+		nvif_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset,
 				state->crtc_reg[head].DAC[i]);
 	}
 
@@ -808,7 +804,7 @@ void nouveau_hw_save_state(struct drm_de
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
-	if (nv_device(drm->device)->chipset == 0x11)
+	if (drm->device.info.chipset == 0x11)
 		/* NB: no attempt is made to restore the bad pll later on */
 		nouveau_hw_fix_bad_vpll(dev, head);
 	nv_save_state_ramdac(dev, head, state);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -60,41 +60,41 @@ extern void nouveau_calc_arb(struct drm_
 static inline uint32_t NVReadCRTC(struct drm_device *dev,
 					int head, uint32_t reg)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	uint32_t val;
 	if (head)
 		reg += NV_PCRTC0_SIZE;
-	val = nv_rd32(device, reg);
+	val = nvif_rd32(device, reg);
 	return val;
 }
 
 static inline void NVWriteCRTC(struct drm_device *dev,
 					int head, uint32_t reg, uint32_t val)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	if (head)
 		reg += NV_PCRTC0_SIZE;
-	nv_wr32(device, reg, val);
+	nvif_wr32(device, reg, val);
 }
 
 static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
 					int head, uint32_t reg)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	uint32_t val;
 	if (head)
 		reg += NV_PRAMDAC0_SIZE;
-	val = nv_rd32(device, reg);
+	val = nvif_rd32(device, reg);
 	return val;
 }
 
 static inline void NVWriteRAMDAC(struct drm_device *dev,
 					int head, uint32_t reg, uint32_t val)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	if (head)
 		reg += NV_PRAMDAC0_SIZE;
-	nv_wr32(device, reg, val);
+	nvif_wr32(device, reg, val);
 }
 
 static inline uint8_t nv_read_tmds(struct drm_device *dev,
@@ -120,18 +120,18 @@ static inline void nv_write_tmds(struct
 static inline void NVWriteVgaCrtc(struct drm_device *dev,
 					int head, uint8_t index, uint8_t value)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
-	nv_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+	nvif_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
 }
 
 static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
 					int head, uint8_t index)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	uint8_t val;
-	nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
-	val = nv_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
+	nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+	val = nvif_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
 	return val;
 }
 
@@ -165,74 +165,74 @@ static inline uint8_t NVReadVgaCrtc5758(
 static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
 					int head, uint32_t reg)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	uint8_t val;
 
 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 	 * NVSetOwner for the relevant head to be programmed */
-	if (head && nv_device(drm->device)->card_type == NV_40)
+	if (head && drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		reg += NV_PRMVIO_SIZE;
 
-	val = nv_rd08(device, reg);
+	val = nvif_rd08(device, reg);
 	return val;
 }
 
 static inline void NVWritePRMVIO(struct drm_device *dev,
 					int head, uint32_t reg, uint8_t value)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 	 * NVSetOwner for the relevant head to be programmed */
-	if (head && nv_device(drm->device)->card_type == NV_40)
+	if (head && drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		reg += NV_PRMVIO_SIZE;
 
-	nv_wr08(device, reg, value);
+	nvif_wr08(device, reg, value);
 }
 
 static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
-	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
 }
 
 static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
-	return !(nv_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	return !(nvif_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
 }
 
 static inline void NVWriteVgaAttr(struct drm_device *dev,
 					int head, uint8_t index, uint8_t value)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	if (NVGetEnablePalette(dev, head))
 		index &= ~0x20;
 	else
 		index |= 0x20;
 
-	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
-	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
-	nv_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
+	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+	nvif_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
 }
 
 static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
 					int head, uint8_t index)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	uint8_t val;
 	if (NVGetEnablePalette(dev, head))
 		index &= ~0x20;
 	else
 		index |= 0x20;
 
-	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
-	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
-	val = nv_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
+	nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+	val = nvif_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
 	return val;
 }
 
@@ -259,11 +259,11 @@ static inline void NVVgaProtect(struct d
 static inline bool
 nv_heads_tied(struct drm_device *dev)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
-	if (nv_device(drm->device)->chipset == 0x11)
-		return !!(nv_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
+	if (drm->device.info.chipset == 0x11)
+		return !!(nvif_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
 
 	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
 }
@@ -318,7 +318,7 @@ NVLockVgaCrtcs(struct drm_device *dev, b
 	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
 		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
 	/* NV11 has independently lockable extended crtcs, except when tied */
-	if (nv_device(drm->device)->chipset == 0x11 && !nv_heads_tied(dev))
+	if (drm->device.info.chipset == 0x11 && !nv_heads_tied(dev))
 		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
 			       lock ? NV_CIO_SR_LOCK_VALUE :
 				      NV_CIO_SR_UNLOCK_RW_VALUE);
@@ -335,7 +335,7 @@ static inline int nv_cursor_width(struct
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
-	return nv_device(drm->device)->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
+	return drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
 }
 
 static inline void
@@ -357,7 +357,7 @@ nv_set_crtc_base(struct drm_device *dev,
 
 	NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
 
-	if (nv_device(drm->device)->card_type == NV_04) {
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT) {
 		/*
 		 * Hilarious, the 24th bit doesn't want to stick to
 		 * PCRTC_START...
@@ -382,7 +382,7 @@ nv_show_cursor(struct drm_device *dev, i
 		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
 
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		nv_fix_nv40_hw_cursor(dev, head);
 }
 
@@ -398,7 +398,7 @@ nv_pitch_align(struct drm_device *dev, u
 		bpp = 8;
 
 	/* Alignment requirements taken from the Haiku driver */
-	if (nv_device(drm->device)->card_type == NV_04)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT)
 		mask = 128 / bpp - 1;
 	else
 		mask = 512 / bpp - 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2014-09-28 17:29:07.000000000 -0400
@@ -96,7 +96,7 @@ nv10_update_plane(struct drm_plane *plan
 		  uint32_t src_x, uint32_t src_y,
 		  uint32_t src_w, uint32_t src_h)
 {
-	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -117,7 +117,7 @@ nv10_update_plane(struct drm_plane *plan
 	if (format > 0xffff)
 		return -ERANGE;
 
-	if (dev->chipset >= 0x30) {
+	if (dev->info.chipset >= 0x30) {
 		if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
 			return -ERANGE;
 	} else {
@@ -131,17 +131,17 @@ nv10_update_plane(struct drm_plane *plan
 
 	nv_plane->cur = nv_fb->nvbo;
 
-	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
-	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
+	nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
+	nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
 
-	nv_wr32(dev, NV_PVIDEO_BASE(flip), 0);
-	nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset);
-	nv_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
-	nv_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
-	nv_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
-	nv_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
-	nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
-	nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
+	nvif_wr32(dev, NV_PVIDEO_BASE(flip), 0);
+	nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset);
+	nvif_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
+	nvif_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
+	nvif_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
+	nvif_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
+	nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
+	nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
 
 	if (fb->pixel_format != DRM_FORMAT_UYVY)
 		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
@@ -153,14 +153,14 @@ nv10_update_plane(struct drm_plane *plan
 		format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
 
 	if (fb->pixel_format == DRM_FORMAT_NV12) {
-		nv_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
-		nv_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
+		nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
+		nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
 			nv_fb->nvbo->bo.offset + fb->offsets[1]);
 	}
-	nv_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
-	nv_wr32(dev, NV_PVIDEO_STOP, 0);
+	nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
+	nvif_wr32(dev, NV_PVIDEO_STOP, 0);
 	/* TODO: wait for vblank? */
-	nv_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
+	nvif_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
 	nv_plane->flip = !flip;
 
 	if (cur)
@@ -172,10 +172,10 @@ nv10_update_plane(struct drm_plane *plan
 static int
 nv10_disable_plane(struct drm_plane *plane)
 {
-	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 
-	nv_wr32(dev, NV_PVIDEO_STOP, 1);
+	nvif_wr32(dev, NV_PVIDEO_STOP, 1);
 	if (nv_plane->cur) {
 		nouveau_bo_unpin(nv_plane->cur);
 		nv_plane->cur = NULL;
@@ -195,24 +195,24 @@ nv_destroy_plane(struct drm_plane *plane
 static void
 nv10_set_params(struct nouveau_plane *plane)
 {
-	struct nouveau_device *dev = nouveau_dev(plane->base.dev);
+	struct nvif_device *dev = &nouveau_drm(plane->base.dev)->device;
 	u32 luma = (plane->brightness - 512) << 16 | plane->contrast;
 	u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) |
 		(cos_mul(plane->hue, plane->saturation) & 0xffff);
 	u32 format = 0;
 
-	nv_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
-	nv_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
-	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
-	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
-	nv_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
+	nvif_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
+	nvif_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
+	nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
+	nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
+	nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
 
 	if (plane->cur) {
 		if (plane->iturbt_709)
 			format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
 		if (plane->colorkey & (1 << 24))
 			format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
-		nv_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
+		nvif_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
 			NV_PVIDEO_FORMAT_MATRIX_ITURBT709 |
 			NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY,
 			format);
@@ -256,7 +256,7 @@ static const struct drm_plane_funcs nv10
 static void
 nv10_overlay_init(struct drm_device *device)
 {
-	struct nouveau_device *dev = nouveau_dev(device);
+	struct nouveau_drm *drm = nouveau_drm(device);
 	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
 	int num_formats = ARRAY_SIZE(formats);
 	int ret;
@@ -264,7 +264,7 @@ nv10_overlay_init(struct drm_device *dev
 	if (!plane)
 		return;
 
-	switch (dev->chipset) {
+	switch (drm->device.info.chipset) {
 	case 0x10:
 	case 0x11:
 	case 0x15:
@@ -333,7 +333,7 @@ cleanup:
 	drm_plane_cleanup(&plane->base);
 err:
 	kfree(plane);
-	nv_error(dev, "Failed to create plane\n");
+	NV_ERROR(drm, "Failed to create plane\n");
 }
 
 static int
@@ -343,7 +343,7 @@ nv04_update_plane(struct drm_plane *plan
 		  uint32_t src_x, uint32_t src_y,
 		  uint32_t src_w, uint32_t src_h)
 {
-	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
 	struct nouveau_bo *cur = nv_plane->cur;
@@ -375,43 +375,43 @@ nv04_update_plane(struct drm_plane *plan
 
 	nv_plane->cur = nv_fb->nvbo;
 
-	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
-	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
-	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+	nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+	nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+	nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);
 
 	for (i = 0; i < 2; i++) {
-		nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+		nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
 			nv_fb->nvbo->bo.offset);
-		nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
-		nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+		nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
+		nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
 	}
-	nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
-	nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
-	nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
+	nvif_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
+	nvif_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
+	nvif_wr32(dev, NV_PVIDEO_STEP_SIZE,
 		(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
 
 	/* It should be possible to convert hue/contrast to this */
-	nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
-	nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
-	nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
-	nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
+	nvif_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
+	nvif_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
+	nvif_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
+	nvif_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
 
-	nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
-	nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
+	nvif_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
+	nvif_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
 
-	nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
-	nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
+	nvif_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
+	nvif_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
 
-	nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
+	nvif_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
 
 	if (nv_plane->colorkey & (1 << 24))
 		overlay |= 0x10;
 	if (fb->pixel_format == DRM_FORMAT_YUYV)
 		overlay |= 0x100;
 
-	nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
+	nvif_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
 
-	nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
+	nvif_wr32(dev, NV_PVIDEO_SU_STATE, nvif_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
 
 	if (cur)
 		nouveau_bo_unpin(cur);
@@ -422,13 +422,13 @@ nv04_update_plane(struct drm_plane *plan
 static int
 nv04_disable_plane(struct drm_plane *plane)
 {
-	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 
-	nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
-	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
-	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
-	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+	nvif_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
+	nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+	nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+	nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);
 	if (nv_plane->cur) {
 		nouveau_bo_unpin(nv_plane->cur);
 		nv_plane->cur = NULL;
@@ -447,7 +447,7 @@ static const struct drm_plane_funcs nv04
 static void
 nv04_overlay_init(struct drm_device *device)
 {
-	struct nouveau_device *dev = nouveau_dev(device);
+	struct nouveau_drm *drm = nouveau_drm(device);
 	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
 	int ret;
 
@@ -483,15 +483,15 @@ cleanup:
 	drm_plane_cleanup(&plane->base);
 err:
 	kfree(plane);
-	nv_error(dev, "Failed to create plane\n");
+	NV_ERROR(drm, "Failed to create plane\n");
 }
 
 void
 nouveau_overlay_init(struct drm_device *device)
 {
-	struct nouveau_device *dev = nouveau_dev(device);
-	if (dev->chipset < 0x10)
+	struct nvif_device *dev = &nouveau_drm(device)->device;
+	if (dev->info.chipset < 0x10)
 		nv04_overlay_init(device);
-	else if (dev->chipset <= 0x40)
+	else if (dev->info.chipset <= 0x40)
 		nv10_overlay_init(device);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,6 @@
 
 #include <drm/i2c/ch7006.h>
 
-#include <subdev/i2c.h>
-
 static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {
 	{
 		{
@@ -56,7 +54,7 @@ static struct nouveau_i2c_board_info nv0
 int nv04_tv_identify(struct drm_device *dev, int i2c_index)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 
 	return i2c->identify(i2c, i2c_index, "TV encoder",
 			     nv04_tv_encoder_info, NULL, NULL);
@@ -206,7 +204,7 @@ nv04_tv_create(struct drm_connector *con
 	struct drm_encoder *encoder;
 	struct drm_device *dev = connector->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
 	int type, ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,11 +34,6 @@
 #include "hw.h"
 #include "tvnv17.h"
 
-#include <core/device.h>
-
-#include <subdev/bios/gpio.h>
-#include <subdev/gpio.h>
-
 MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
 		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
 		 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
@@ -51,7 +46,7 @@ static uint32_t nv42_tv_sample_load(stru
 {
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+	struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
 	uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
 		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
@@ -135,17 +130,17 @@ static bool
 get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_object *device = drm->device;
+	struct nvif_device *device = &drm->device;
 
 	/* Zotac FX5200 */
-	if (nv_device_match(device, 0x0322, 0x19da, 0x1035) ||
-	    nv_device_match(device, 0x0322, 0x19da, 0x2035)) {
+	if (nv_device_match(nvkm_object(device), 0x0322, 0x19da, 0x1035) ||
+	    nv_device_match(nvkm_object(device), 0x0322, 0x19da, 0x2035)) {
 		*pin_mask = 0xc;
 		return false;
 	}
 
 	/* MSI nForce2 IGP */
-	if (nv_device_match(device, 0x01f0, 0x1462, 0x5710)) {
+	if (nv_device_match(nvkm_object(device), 0x01f0, 0x1462, 0x5710)) {
 		*pin_mask = 0xc;
 		return false;
 	}
@@ -167,8 +162,8 @@ nv17_tv_detect(struct drm_encoder *encod
 		return connector_status_disconnected;
 
 	if (reliable) {
-		if (nv_device(drm->device)->chipset == 0x42 ||
-		    nv_device(drm->device)->chipset == 0x43)
+		if (drm->device.info.chipset == 0x42 ||
+		    drm->device.info.chipset == 0x43)
 			tv_enc->pin_mask =
 				nv42_tv_sample_load(encoder) >> 28 & 0xe;
 		else
@@ -375,7 +370,7 @@ static void  nv17_tv_dpms(struct drm_enc
 {
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+	struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
 	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 
@@ -448,7 +443,7 @@ static void nv17_tv_prepare(struct drm_e
 	/* Set the DACCLK register */
 	dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1;
 
-	if (nv_device(drm->device)->card_type == NV_40)
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
 		dacclk |= 0x1a << 16;
 
 	if (tv_norm->kind == CTV_ENC_MODE) {
@@ -505,7 +500,7 @@ static void nv17_tv_mode_set(struct drm_
 			tv_regs->ptv_614 = 0x13;
 		}
 
-		if (nv_device(drm->device)->card_type >= NV_30) {
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE) {
 			tv_regs->ptv_500 = 0xe8e0;
 			tv_regs->ptv_504 = 0x1710;
 			tv_regs->ptv_604 = 0x0;
@@ -600,7 +595,7 @@ static void nv17_tv_commit(struct drm_en
 	nv17_tv_state_load(dev, &to_tv_enc(encoder)->state);
 
 	/* This could use refinement for flatpanels, but it should work */
-	if (nv_device(drm->device)->chipset < 0x44)
+	if (drm->device.info.chipset < 0x44)
 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
 					nv04_dac_output_offset(encoder),
 					0xf0000000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h	2014-09-28 17:29:07.000000000 -0400
@@ -130,14 +130,14 @@ void nv17_ctv_update_rescaler(struct drm
 static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg,
 				uint32_t val)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	nv_wr32(device, reg, val);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	nvif_wr32(device, reg, val);
 }
 
 static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
-	return nv_rd32(device, reg);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
+	return nvif_rd32(device, reg);
 }
 
 static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 config DRM_NOUVEAU
-	tristate "Nouveau (nVidia) cards"
+	tristate "Nouveau (NVIDIA) cards"
 	depends on DRM && PCI
         select FW_LOADER
 	select DRM_KMS_HELPER
@@ -23,7 +23,15 @@ config DRM_NOUVEAU
 	select THERMAL if ACPI && X86
 	select ACPI_VIDEO if ACPI && X86
 	help
-	  Choose this option for open-source nVidia support.
+	  Choose this option for open-source NVIDIA support.
+
+config NOUVEAU_PLATFORM_DRIVER
+	tristate "Nouveau (NVIDIA) SoC GPUs"
+	depends on DRM_NOUVEAU && ARCH_TEGRA
+	default y
+	help
+	  Support for Nouveau platform driver, used for SoC GPUs as found
+	  on NVIDIA Tegra K1.
 
 config NOUVEAU_DEBUG
 	int "Maximum debug level"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -14,8 +14,10 @@ nouveau-y += core/core/enum.o
 nouveau-y += core/core/event.o
 nouveau-y += core/core/gpuobj.o
 nouveau-y += core/core/handle.o
+nouveau-y += core/core/ioctl.o
 nouveau-y += core/core/mm.o
 nouveau-y += core/core/namedb.o
+nouveau-y += core/core/notify.o
 nouveau-y += core/core/object.o
 nouveau-y += core/core/option.o
 nouveau-y += core/core/parent.o
@@ -26,6 +28,7 @@ nouveau-y += core/core/subdev.o
 nouveau-y += core/subdev/bar/base.o
 nouveau-y += core/subdev/bar/nv50.o
 nouveau-y += core/subdev/bar/nvc0.o
+nouveau-y += core/subdev/bar/gk20a.o
 nouveau-y += core/subdev/bios/base.o
 nouveau-y += core/subdev/bios/bit.o
 nouveau-y += core/subdev/bios/boost.o
@@ -64,6 +67,7 @@ nouveau-y += core/subdev/clock/nva3.o
 nouveau-y += core/subdev/clock/nvaa.o
 nouveau-y += core/subdev/clock/nvc0.o
 nouveau-y += core/subdev/clock/nve0.o
+nouveau-y += core/subdev/clock/gk20a.o
 nouveau-y += core/subdev/clock/pllnv04.o
 nouveau-y += core/subdev/clock/pllnva3.o
 nouveau-y += core/subdev/devinit/base.o
@@ -149,8 +153,10 @@ nouveau-y += core/subdev/instmem/base.o
 nouveau-y += core/subdev/instmem/nv04.o
 nouveau-y += core/subdev/instmem/nv40.o
 nouveau-y += core/subdev/instmem/nv50.o
-nouveau-y += core/subdev/ltcg/gf100.o
-nouveau-y += core/subdev/ltcg/gm107.o
+nouveau-y += core/subdev/ltc/base.o
+nouveau-y += core/subdev/ltc/gf100.o
+nouveau-y += core/subdev/ltc/gk104.o
+nouveau-y += core/subdev/ltc/gm107.o
 nouveau-y += core/subdev/mc/base.o
 nouveau-y += core/subdev/mc/nv04.o
 nouveau-y += core/subdev/mc/nv40.o
@@ -161,6 +167,7 @@ nouveau-y += core/subdev/mc/nv94.o
 nouveau-y += core/subdev/mc/nv98.o
 nouveau-y += core/subdev/mc/nvc0.o
 nouveau-y += core/subdev/mc/nvc3.o
+nouveau-y += core/subdev/mc/gk20a.o
 nouveau-y += core/subdev/mxm/base.o
 nouveau-y += core/subdev/mxm/mxms.o
 nouveau-y += core/subdev/mxm/nv50.o
@@ -169,6 +176,7 @@ nouveau-y += core/subdev/pwr/memx.o
 nouveau-y += core/subdev/pwr/nva3.o
 nouveau-y += core/subdev/pwr/nvc0.o
 nouveau-y += core/subdev/pwr/nvd0.o
+nouveau-y += core/subdev/pwr/gk104.o
 nouveau-y += core/subdev/pwr/nv108.o
 nouveau-y += core/subdev/therm/base.o
 nouveau-y += core/subdev/therm/fan.o
@@ -211,6 +219,7 @@ nouveau-y += core/engine/copy/nvc0.o
 nouveau-y += core/engine/copy/nve0.o
 nouveau-y += core/engine/crypt/nv84.o
 nouveau-y += core/engine/crypt/nv98.o
+nouveau-y += core/engine/device/acpi.o
 nouveau-y += core/engine/device/base.o
 nouveau-y += core/engine/device/ctrl.o
 nouveau-y += core/engine/device/nv04.o
@@ -270,6 +279,7 @@ nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
 nouveau-y += core/engine/graph/ctxgk20a.o
 nouveau-y += core/engine/graph/ctxnvf0.o
+nouveau-y += core/engine/graph/ctxgk110b.o
 nouveau-y += core/engine/graph/ctxnv108.o
 nouveau-y += core/engine/graph/ctxgm107.o
 nouveau-y += core/engine/graph/nv04.o
@@ -291,6 +301,7 @@ nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
 nouveau-y += core/engine/graph/gk20a.o
 nouveau-y += core/engine/graph/nvf0.o
+nouveau-y += core/engine/graph/gk110b.o
 nouveau-y += core/engine/graph/nv108.o
 nouveau-y += core/engine/graph/gm107.o
 nouveau-y += core/engine/mpeg/nv31.o
@@ -318,11 +329,18 @@ nouveau-y += core/engine/vp/nv98.o
 nouveau-y += core/engine/vp/nvc0.o
 nouveau-y += core/engine/vp/nve0.o
 
+# nvif
+nouveau-y += nvif/object.o
+nouveau-y += nvif/client.o
+nouveau-y += nvif/device.o
+nouveau-y += nvif/notify.o
+
 # drm/core
 nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
 nouveau-y += nouveau_vga.o nouveau_agp.o
 nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
 nouveau-y += nouveau_prime.o nouveau_abi16.o
+nouveau-y += nouveau_nvif.o nouveau_usif.o
 nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
 nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o
 
@@ -349,3 +367,6 @@ nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT)
 nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o
 
 obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
+
+# platform driver
+obj-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,16 +21,10 @@
  *
  */
 
-#include <core/object.h>
-#include <core/client.h>
-#include <core/device.h>
-#include <core/class.h>
-#include <core/mm.h>
-
-#include <subdev/fb.h>
-#include <subdev/timer.h>
-#include <subdev/instmem.h>
-#include <engine/graph.h>
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/ioctl.h>
+#include <nvif/class.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -47,20 +41,20 @@ nouveau_abi16_get(struct drm_file *file_
 		struct nouveau_abi16 *abi16;
 		cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL);
 		if (cli->abi16) {
+			struct nv_device_v0 args = {
+				.device = ~0ULL,
+			};
+
 			INIT_LIST_HEAD(&abi16->channels);
-			abi16->client = nv_object(cli);
 
 			/* allocate device object targeting client's default
 			 * device (ie. the one that belongs to the fd it
 			 * opened)
 			 */
-			if (nouveau_object_new(abi16->client, NVDRM_CLIENT,
-					       NVDRM_DEVICE, 0x0080,
-					       &(struct nv_device_class) {
-						.device = ~0ULL,
-					       },
-					       sizeof(struct nv_device_class),
-					       &abi16->device) == 0)
+			if (nvif_device_init(&cli->base.base, NULL,
+					     NOUVEAU_ABI16_DEVICE, NV_DEVICE,
+					     &args, sizeof(args),
+					     &abi16->device) == 0)
 				return cli->abi16;
 
 			kfree(cli->abi16);
@@ -75,7 +69,7 @@ nouveau_abi16_get(struct drm_file *file_
 int
 nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
 {
-	struct nouveau_cli *cli = (void *)abi16->client;
+	struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base);
 	mutex_unlock(&cli->mutex);
 	return ret;
 }
@@ -83,21 +77,19 @@ nouveau_abi16_put(struct nouveau_abi16 *
 u16
 nouveau_abi16_swclass(struct nouveau_drm *drm)
 {
-	switch (nv_device(drm->device)->card_type) {
-	case NV_04:
+	switch (drm->device.info.family) {
+	case NV_DEVICE_INFO_V0_TNT:
 		return 0x006e;
-	case NV_10:
-	case NV_11:
-	case NV_20:
-	case NV_30:
-	case NV_40:
+	case NV_DEVICE_INFO_V0_CELSIUS:
+	case NV_DEVICE_INFO_V0_KELVIN:
+	case NV_DEVICE_INFO_V0_RANKINE:
+	case NV_DEVICE_INFO_V0_CURIE:
 		return 0x016e;
-	case NV_50:
+	case NV_DEVICE_INFO_V0_TESLA:
 		return 0x506e;
-	case NV_C0:
-	case NV_D0:
-	case NV_E0:
-	case GM100:
+	case NV_DEVICE_INFO_V0_FERMI:
+	case NV_DEVICE_INFO_V0_KEPLER:
+	case NV_DEVICE_INFO_V0_MAXWELL:
 		return 0x906e;
 	}
 
@@ -140,7 +132,7 @@ nouveau_abi16_chan_fini(struct nouveau_a
 
 	/* destroy channel object, all children will be killed too */
 	if (chan->chan) {
-		abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));
+		abi16->handles &= ~(1ULL << (chan->chan->object->handle & 0xffff));
 		nouveau_channel_del(&chan->chan);
 	}
 
@@ -151,7 +143,7 @@ nouveau_abi16_chan_fini(struct nouveau_a
 void
 nouveau_abi16_fini(struct nouveau_abi16 *abi16)
 {
-	struct nouveau_cli *cli = (void *)abi16->client;
+	struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base);
 	struct nouveau_abi16_chan *chan, *temp;
 
 	/* cleanup channels */
@@ -160,7 +152,7 @@ nouveau_abi16_fini(struct nouveau_abi16
 	}
 
 	/* destroy the device object */
-	nouveau_object_del(abi16->client, NVDRM_CLIENT, NVDRM_DEVICE);
+	nvif_device_fini(&abi16->device);
 
 	kfree(cli->abi16);
 	cli->abi16 = NULL;
@@ -169,30 +161,31 @@ nouveau_abi16_fini(struct nouveau_abi16
 int
 nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
 {
+	struct nouveau_cli *cli = nouveau_cli(file_priv);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_timer *ptimer = nouveau_timer(device);
-	struct nouveau_graph *graph = (void *)nouveau_engine(device, NVDEV_ENGINE_GR);
+	struct nvif_device *device = &drm->device;
+	struct nouveau_timer *ptimer = nvkm_timer(device);
+	struct nouveau_graph *graph = nvkm_gr(device);
 	struct drm_nouveau_getparam *getparam = data;
 
 	switch (getparam->param) {
 	case NOUVEAU_GETPARAM_CHIPSET_ID:
-		getparam->value = device->chipset;
+		getparam->value = device->info.chipset;
 		break;
 	case NOUVEAU_GETPARAM_PCI_VENDOR:
-		if (nv_device_is_pci(device))
+		if (nv_device_is_pci(nvkm_device(device)))
 			getparam->value = dev->pdev->vendor;
 		else
 			getparam->value = 0;
 		break;
 	case NOUVEAU_GETPARAM_PCI_DEVICE:
-		if (nv_device_is_pci(device))
+		if (nv_device_is_pci(nvkm_device(device)))
 			getparam->value = dev->pdev->device;
 		else
 			getparam->value = 0;
 		break;
 	case NOUVEAU_GETPARAM_BUS_TYPE:
-		if (!nv_device_is_pci(device))
+		if (!nv_device_is_pci(nvkm_device(device)))
 			getparam->value = 3;
 		else
 		if (drm_pci_device_is_agp(dev))
@@ -225,7 +218,7 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL
 		getparam->value = graph->units ? graph->units(graph) : 0;
 		break;
 	default:
-		nv_debug(device, "unknown parameter %lld\n", getparam->param);
+		NV_PRINTK(debug, cli, "unknown parameter %lld\n", getparam->param);
 		return -EINVAL;
 	}
 
@@ -246,10 +239,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
 	struct nouveau_abi16_chan *chan;
-	struct nouveau_client *client;
-	struct nouveau_device *device;
-	struct nouveau_instmem *imem;
-	struct nouveau_fb *pfb;
+	struct nvif_device *device;
 	int ret;
 
 	if (unlikely(!abi16))
@@ -258,21 +248,18 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_
 	if (!drm->channel)
 		return nouveau_abi16_put(abi16, -ENODEV);
 
-	client = nv_client(abi16->client);
-	device = nv_device(abi16->device);
-	imem   = nouveau_instmem(device);
-	pfb    = nouveau_fb(device);
+	device = &abi16->device;
 
 	/* hack to allow channel engine type specification on kepler */
-	if (device->card_type >= NV_E0) {
+	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
 		if (init->fb_ctxdma_handle != ~0)
-			init->fb_ctxdma_handle = NVE0_CHANNEL_IND_ENGINE_GR;
+			init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
 		else
 			init->fb_ctxdma_handle = init->tt_ctxdma_handle;
 
 		/* allow flips to be executed if this is a graphics channel */
 		init->tt_ctxdma_handle = 0;
-		if (init->fb_ctxdma_handle == NVE0_CHANNEL_IND_ENGINE_GR)
+		if (init->fb_ctxdma_handle == KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR)
 			init->tt_ctxdma_handle = 1;
 	}
 
@@ -293,13 +280,14 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_
 	abi16->handles |= (1ULL << init->channel);
 
 	/* create channel object and initialise dma and fence management */
-	ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN |
-				  init->channel, init->fb_ctxdma_handle,
+	ret = nouveau_channel_new(drm, device,
+				  NOUVEAU_ABI16_CHAN(init->channel),
+				  init->fb_ctxdma_handle,
 				  init->tt_ctxdma_handle, &chan->chan);
 	if (ret)
 		goto done;
 
-	if (device->card_type >= NV_50)
+	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
 		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
 					NOUVEAU_GEM_DOMAIN_GART;
 	else
@@ -308,10 +296,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_
 	else
 		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
 
-	if (device->card_type < NV_10) {
+	if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 		init->subchan[0].handle = 0x00000000;
 		init->subchan[0].grclass = 0x0000;
-		init->subchan[1].handle = NvSw;
+		init->subchan[1].handle = chan->chan->nvsw.handle;
 		init->subchan[1].grclass = 0x506e;
 		init->nr_subchan = 2;
 	}
@@ -324,8 +312,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_
 	if (ret)
 		goto done;
 
-	if (device->card_type >= NV_50) {
-		ret = nouveau_bo_vma_add(chan->ntfy, client->vm,
+	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		ret = nouveau_bo_vma_add(chan->ntfy, cli->vm,
 					&chan->ntfy_vma);
 		if (ret)
 			goto done;
@@ -343,6 +331,18 @@ done:
 	return nouveau_abi16_put(abi16, ret);
 }
 
+static struct nouveau_abi16_chan *
+nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
+{
+	struct nouveau_abi16_chan *chan;
+
+	list_for_each_entry(chan, &abi16->channels, head) {
+		if (chan->chan->object->handle == NOUVEAU_ABI16_CHAN(channel))
+			return chan;
+	}
+
+	return NULL;
+}
 
 int
 nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
@@ -350,28 +350,38 @@ nouveau_abi16_ioctl_channel_free(ABI16_I
 	struct drm_nouveau_channel_free *req = data;
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
 	struct nouveau_abi16_chan *chan;
-	int ret = -ENOENT;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
 
-	list_for_each_entry(chan, &abi16->channels, head) {
-		if (chan->chan->handle == (NVDRM_CHAN | req->channel)) {
-			nouveau_abi16_chan_fini(abi16, chan);
-			return nouveau_abi16_put(abi16, 0);
-		}
-	}
-
-	return nouveau_abi16_put(abi16, ret);
+	chan = nouveau_abi16_chan(abi16, req->channel);
+	if (!chan)
+		return nouveau_abi16_put(abi16, -ENOENT);
+	nouveau_abi16_chan_fini(abi16, chan);
+	return nouveau_abi16_put(abi16, 0);
 }
 
 int
 nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
 {
 	struct drm_nouveau_grobj_alloc *init = data;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_new_v0 new;
+	} args = {
+		.ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY,
+		.ioctl.type = NVIF_IOCTL_V0_NEW,
+		.ioctl.path_nr = 3,
+		.ioctl.path[2] = NOUVEAU_ABI16_CLIENT,
+		.ioctl.path[1] = NOUVEAU_ABI16_DEVICE,
+		.ioctl.path[0] = NOUVEAU_ABI16_CHAN(init->channel),
+		.new.route = NVDRM_OBJECT_ABI16,
+		.new.handle = init->handle,
+		.new.oclass = init->class,
+	};
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_object *object;
+	struct nvif_client *client;
 	int ret;
 
 	if (unlikely(!abi16))
@@ -379,6 +389,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IO
 
 	if (init->handle == ~0)
 		return nouveau_abi16_put(abi16, -EINVAL);
+	client = nvif_client(nvif_object(&abi16->device));
 
 	/* compatibility with userspace that assumes 506e for all chipsets */
 	if (init->class == 0x506e) {
@@ -387,8 +398,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IO
 			return nouveau_abi16_put(abi16, 0);
 	}
 
-	ret = nouveau_object_new(abi16->client, NVDRM_CHAN | init->channel,
-				  init->handle, init->class, NULL, 0, &object);
+	ret = nvif_client_ioctl(client, &args, sizeof(args));
 	return nouveau_abi16_put(abi16, ret);
 }
 
@@ -396,29 +406,38 @@ int
 nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
 {
 	struct drm_nouveau_notifierobj_alloc *info = data;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_new_v0 new;
+		struct nv_dma_v0 ctxdma;
+	} args = {
+		.ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY,
+		.ioctl.type = NVIF_IOCTL_V0_NEW,
+		.ioctl.path_nr = 3,
+		.ioctl.path[2] = NOUVEAU_ABI16_CLIENT,
+		.ioctl.path[1] = NOUVEAU_ABI16_DEVICE,
+		.ioctl.path[0] = NOUVEAU_ABI16_CHAN(info->channel),
+		.new.route = NVDRM_OBJECT_ABI16,
+		.new.handle = info->handle,
+		.new.oclass = NV_DMA_IN_MEMORY,
+	};
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan = NULL, *temp;
+	struct nouveau_abi16_chan *chan;
 	struct nouveau_abi16_ntfy *ntfy;
-	struct nouveau_object *object;
-	struct nv_dma_class args = {};
+	struct nvif_device *device = &abi16->device;
+	struct nvif_client *client;
 	int ret;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
 
 	/* completely unnecessary for these chipsets... */
-	if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
+	if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI))
 		return nouveau_abi16_put(abi16, -EINVAL);
+	client = nvif_client(nvif_object(&abi16->device));
 
-	list_for_each_entry(temp, &abi16->channels, head) {
-		if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
-			chan = temp;
-			break;
-		}
-	}
-
+	chan = nouveau_abi16_chan(abi16, info->channel);
 	if (!chan)
 		return nouveau_abi16_put(abi16, -ENOENT);
 
@@ -434,26 +453,29 @@ nouveau_abi16_ioctl_notifierobj_alloc(AB
 	if (ret)
 		goto done;
 
-	args.start = ntfy->node->offset;
-	args.limit = ntfy->node->offset + ntfy->node->length - 1;
-	if (device->card_type >= NV_50) {
-		args.flags  = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
-		args.start += chan->ntfy_vma.offset;
-		args.limit += chan->ntfy_vma.offset;
+	args.ctxdma.start = ntfy->node->offset;
+	args.ctxdma.limit = ntfy->node->offset + ntfy->node->length - 1;
+	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		args.ctxdma.target = NV_DMA_V0_TARGET_VM;
+		args.ctxdma.access = NV_DMA_V0_ACCESS_VM;
+		args.ctxdma.start += chan->ntfy_vma.offset;
+		args.ctxdma.limit += chan->ntfy_vma.offset;
 	} else
 	if (drm->agp.stat == ENABLED) {
-		args.flags  = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
-		args.start += drm->agp.base + chan->ntfy->bo.offset;
-		args.limit += drm->agp.base + chan->ntfy->bo.offset;
+		args.ctxdma.target = NV_DMA_V0_TARGET_AGP;
+		args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR;
+		args.ctxdma.start += drm->agp.base + chan->ntfy->bo.offset;
+		args.ctxdma.limit += drm->agp.base + chan->ntfy->bo.offset;
+		client->super = true;
 	} else {
-		args.flags  = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
-		args.start += chan->ntfy->bo.offset;
-		args.limit += chan->ntfy->bo.offset;
+		args.ctxdma.target = NV_DMA_V0_TARGET_VM;
+		args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR;
+		args.ctxdma.start += chan->ntfy->bo.offset;
+		args.ctxdma.limit += chan->ntfy->bo.offset;
 	}
 
-	ret = nouveau_object_new(abi16->client, chan->chan->handle,
-				 ntfy->handle, 0x003d, &args,
-				 sizeof(args), &object);
+	ret = nvif_client_ioctl(client, &args, sizeof(args));
+	client->super = false;
 	if (ret)
 		goto done;
 
@@ -469,28 +491,36 @@ int
 nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
 {
 	struct drm_nouveau_gpuobj_free *fini = data;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_del del;
+	} args = {
+		.ioctl.owner = NVDRM_OBJECT_ABI16,
+		.ioctl.type = NVIF_IOCTL_V0_DEL,
+		.ioctl.path_nr = 4,
+		.ioctl.path[3] = NOUVEAU_ABI16_CLIENT,
+		.ioctl.path[2] = NOUVEAU_ABI16_DEVICE,
+		.ioctl.path[1] = NOUVEAU_ABI16_CHAN(fini->channel),
+		.ioctl.path[0] = fini->handle,
+	};
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan = NULL, *temp;
+	struct nouveau_abi16_chan *chan;
 	struct nouveau_abi16_ntfy *ntfy;
+	struct nvif_client *client;
 	int ret;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
 
-	list_for_each_entry(temp, &abi16->channels, head) {
-		if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
-			chan = temp;
-			break;
-		}
-	}
-
+	chan = nouveau_abi16_chan(abi16, fini->channel);
 	if (!chan)
 		return nouveau_abi16_put(abi16, -ENOENT);
+	client = nvif_client(nvif_object(&abi16->device));
 
 	/* synchronize with the user channel and destroy the gpu object */
 	nouveau_channel_idle(chan->chan);
 
-	ret = nouveau_object_del(abi16->client, chan->chan->handle, fini->handle);
+	ret = nvif_client_ioctl(client, &args, sizeof(args));
 	if (ret)
 		return nouveau_abi16_put(abi16, ret);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,8 +28,7 @@ struct nouveau_abi16_chan {
 };
 
 struct nouveau_abi16 {
-	struct nouveau_object *client;
-	struct nouveau_object *device;
+	struct nvif_device device;
 	struct list_head channels;
 	u64 handles;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,6 @@ static struct nouveau_dsm_priv {
 	bool dsm_detected;
 	bool optimus_detected;
 	acpi_handle dhandle;
-	acpi_handle other_handle;
 	acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
@@ -222,10 +221,9 @@ static int nouveau_dsm_pci_probe(struct
 	if (!dhandle)
 		return false;
 
-	if (!acpi_has_method(dhandle, "_DSM")) {
-		nouveau_dsm_priv.other_handle = dhandle;
+	if (!acpi_has_method(dhandle, "_DSM"))
 		return false;
-	}
+
 	if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
 			   1 << NOUVEAU_DSM_POWER))
 		retval |= NOUVEAU_DSM_HAS_MUX;
@@ -301,16 +299,6 @@ static bool nouveau_dsm_detect(void)
 		printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
 			acpi_method_name);
 		nouveau_dsm_priv.dsm_detected = true;
-		/*
-		 * On some systems hotplug events are generated for the device
-		 * being switched off when _DSM is executed.  They cause ACPI
-		 * hotplug to trigger and attempt to remove the device from
-		 * the system, which causes it to break down.  Prevent that from
-		 * happening by setting the no_hotplug flag for the involved
-		 * ACPI device objects.
-		 */
-		acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
-		acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
 		ret = true;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_agp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_agp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_agp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_agp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,5 @@
 #include <linux/module.h>
 
-#include <core/device.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_agp.h"
 #include "nouveau_reg.h"
@@ -29,7 +27,7 @@ static struct nouveau_agpmode_quirk nouv
 static unsigned long
 get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
 {
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list;
 	int agpmode = nouveau_agpmode;
 	unsigned long mode = info->mode;
@@ -38,7 +36,7 @@ get_agp_mode(struct nouveau_drm *drm, co
 	 * FW seems to be broken on nv18, it makes the card lock up
 	 * randomly.
 	 */
-	if (device->chipset == 0x18)
+	if (device->info.chipset == 0x18)
 		mode &= ~PCI_AGP_COMMAND_FW;
 
 	/*
@@ -47,10 +45,10 @@ get_agp_mode(struct nouveau_drm *drm, co
 	while (agpmode == -1 && quirk->hostbridge_vendor) {
 		if (info->id_vendor == quirk->hostbridge_vendor &&
 		    info->id_device == quirk->hostbridge_device &&
-		    device->pdev->vendor == quirk->chip_vendor &&
-		    device->pdev->device == quirk->chip_device) {
+		    nvkm_device(device)->pdev->vendor == quirk->chip_vendor &&
+		    nvkm_device(device)->pdev->device == quirk->chip_device) {
 			agpmode = quirk->mode;
-			nv_info(device, "Forcing agp mode to %dX. Use agpmode to override.\n",
+			NV_INFO(drm, "Forcing agp mode to %dX. Use agpmode to override.\n",
 				agpmode);
 			break;
 		}
@@ -104,7 +102,7 @@ void
 nouveau_agp_reset(struct nouveau_drm *drm)
 {
 #if __OS_HAS_AGP
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct drm_device *dev = drm->dev;
 	u32 save[2];
 	int ret;
@@ -115,7 +113,7 @@ nouveau_agp_reset(struct nouveau_drm *dr
 	/* First of all, disable fast writes, otherwise if it's
 	 * already enabled in the AGP bridge and we disable the card's
 	 * AGP controller we might be locking ourselves out of it. */
-	if ((nv_rd32(device, NV04_PBUS_PCI_NV_19) |
+	if ((nvif_rd32(device, NV04_PBUS_PCI_NV_19) |
 	     dev->agp->mode) & PCI_AGP_COMMAND_FW) {
 		struct drm_agp_info info;
 		struct drm_agp_mode mode;
@@ -134,15 +132,15 @@ nouveau_agp_reset(struct nouveau_drm *dr
 
 
 	/* clear busmaster bit, and disable AGP */
-	save[0] = nv_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000);
-	nv_wr32(device, NV04_PBUS_PCI_NV_19, 0);
+	save[0] = nvif_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000);
+	nvif_wr32(device, NV04_PBUS_PCI_NV_19, 0);
 
 	/* reset PGRAPH, PFIFO and PTIMER */
-	save[1] = nv_mask(device, 0x000200, 0x00011100, 0x00000000);
-	nv_mask(device, 0x000200, 0x00011100, save[1]);
+	save[1] = nvif_mask(device, 0x000200, 0x00011100, 0x00000000);
+	nvif_mask(device, 0x000200, 0x00011100, save[1]);
 
 	/* and restore bustmaster bit (gives effect of resetting AGP) */
-	nv_wr32(device, NV04_PBUS_PCI_NV_1, save[0]);
+	nvif_wr32(device, NV04_PBUS_PCI_NV_1, save[0]);
 #endif
 }
 
@@ -150,7 +148,6 @@ void
 nouveau_agp_init(struct nouveau_drm *drm)
 {
 #if __OS_HAS_AGP
-	struct nouveau_device *device = nv_device(drm->device);
 	struct drm_device *dev = drm->dev;
 	struct drm_agp_info info;
 	struct drm_agp_mode mode;
@@ -162,13 +159,13 @@ nouveau_agp_init(struct nouveau_drm *drm
 
 	ret = drm_agp_acquire(dev);
 	if (ret) {
-		nv_error(device, "unable to acquire AGP: %d\n", ret);
+		NV_ERROR(drm, "unable to acquire AGP: %d\n", ret);
 		return;
 	}
 
 	ret = drm_agp_info(dev, &info);
 	if (ret) {
-		nv_error(device, "unable to get AGP info: %d\n", ret);
+		NV_ERROR(drm, "unable to get AGP info: %d\n", ret);
 		return;
 	}
 
@@ -177,7 +174,7 @@ nouveau_agp_init(struct nouveau_drm *drm
 
 	ret = drm_agp_enable(dev, mode);
 	if (ret) {
-		nv_error(device, "unable to enable AGP: %d\n", ret);
+		NV_ERROR(drm, "unable to enable AGP: %d\n", ret);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,8 @@ static int
 nv40_get_intensity(struct backlight_device *bd)
 {
 	struct nouveau_drm *drm = bl_get_data(bd);
-	struct nouveau_device *device = nv_device(drm->device);
-	int val = (nv_rd32(device, NV40_PMC_BACKLIGHT) &
+	struct nvif_device *device = &drm->device;
+	int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
 				   NV40_PMC_BACKLIGHT_MASK) >> 16;
 
 	return val;
@@ -51,11 +51,11 @@ static int
 nv40_set_intensity(struct backlight_device *bd)
 {
 	struct nouveau_drm *drm = bl_get_data(bd);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int val = bd->props.brightness;
-	int reg = nv_rd32(device, NV40_PMC_BACKLIGHT);
+	int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
 
-	nv_wr32(device, NV40_PMC_BACKLIGHT,
+	nvif_wr32(device, NV40_PMC_BACKLIGHT,
 		 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
 
 	return 0;
@@ -71,11 +71,11 @@ static int
 nv40_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct backlight_properties props;
 	struct backlight_device *bd;
 
-	if (!(nv_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
+	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
@@ -97,12 +97,12 @@ nv50_get_intensity(struct backlight_devi
 {
 	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int or = nv_encoder->or;
 	u32 div = 1025;
 	u32 val;
 
-	val  = nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
+	val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
 	val &= NV50_PDISP_SOR_PWM_CTL_VAL;
 	return ((val * 100) + (div / 2)) / div;
 }
@@ -112,12 +112,12 @@ nv50_set_intensity(struct backlight_devi
 {
 	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int or = nv_encoder->or;
 	u32 div = 1025;
 	u32 val = (bd->props.brightness * div) / 100;
 
-	nv_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
+	nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
 			NV50_PDISP_SOR_PWM_CTL_NEW | val);
 	return 0;
 }
@@ -133,12 +133,12 @@ nva3_get_intensity(struct backlight_devi
 {
 	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int or = nv_encoder->or;
 	u32 div, val;
 
-	div  = nv_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
-	val  = nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
+	div  = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
+	val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
 	val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
 	if (div && div >= val)
 		return ((val * 100) + (div / 2)) / div;
@@ -151,14 +151,14 @@ nva3_set_intensity(struct backlight_devi
 {
 	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int or = nv_encoder->or;
 	u32 div, val;
 
-	div = nv_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
+	div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
 	val = (bd->props.brightness * div) / 100;
 	if (div) {
-		nv_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
+		nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
 				NV50_PDISP_SOR_PWM_CTL_NEW |
 				NVA3_PDISP_SOR_PWM_CTL_UNK);
 		return 0;
@@ -177,7 +177,7 @@ static int
 nv50_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct nouveau_encoder *nv_encoder;
 	struct backlight_properties props;
 	struct backlight_device *bd;
@@ -190,12 +190,12 @@ nv50_backlight_init(struct drm_connector
 			return -ENODEV;
 	}
 
-	if (!nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
+	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
 		return 0;
 
-	if (device->chipset <= 0xa0 ||
-	    device->chipset == 0xaa ||
-	    device->chipset == 0xac)
+	if (device->info.chipset <= 0xa0 ||
+	    device->info.chipset == 0xaa ||
+	    device->info.chipset == 0xac)
 		ops = &nv50_bl_ops;
 	else
 		ops = &nva3_bl_ops;
@@ -218,7 +218,7 @@ int
 nouveau_backlight_init(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct drm_connector *connector;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -226,13 +226,12 @@ nouveau_backlight_init(struct drm_device
 		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
-		switch (device->card_type) {
-		case NV_40:
+		switch (device->info.family) {
+		case NV_DEVICE_INFO_V0_CURIE:
 			return nv40_backlight_init(connector);
-		case NV_50:
-		case NV_C0:
-		case NV_D0:
-		case NV_E0:
+		case NV_DEVICE_INFO_V0_TESLA:
+		case NV_DEVICE_INFO_V0_FERMI:
+		case NV_DEVICE_INFO_V0_KEPLER:
 			return nv50_backlight_init(connector);
 		default:
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,6 @@
  * SOFTWARE.
  */
 
-#include <subdev/bios.h>
-
 #include <drm/drmP.h>
 
 #include "nouveau_drm.h"
@@ -217,7 +215,7 @@ int call_lvds_script(struct drm_device *
 	 */
 
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct nvbios *bios = &drm->vbios;
 	uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
 	uint32_t sel_clk_binding, sel_clk;
@@ -240,7 +238,7 @@ int call_lvds_script(struct drm_device *
 	NV_INFO(drm, "Calling LVDS script %d:\n", script);
 
 	/* don't let script change pll->head binding */
-	sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
+	sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
 
 	if (lvds_ver < 0x30)
 		ret = call_lvds_manufacturer_script(dev, dcbent, head, script);
@@ -252,7 +250,7 @@ int call_lvds_script(struct drm_device *
 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
 	/* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
-	nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);
+	nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
 
 	return ret;
 }
@@ -320,7 +318,7 @@ static int parse_lvds_manufacturer_table
 static int
 get_fp_strap(struct drm_device *dev, struct nvbios *bios)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 
 	/*
 	 * The fp strap is normally dictated by the "User Strap" in
@@ -334,10 +332,10 @@ get_fp_strap(struct drm_device *dev, str
 	if (bios->major_version < 5 && bios->data[0x48] & 0x4)
 		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
 
-	if (device->card_type >= NV_50)
-		return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
+	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
+		return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
 	else
-		return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
+		return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
 }
 
 static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
@@ -636,7 +634,7 @@ int run_tmds_table(struct drm_device *de
 	 */
 
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct nvbios *bios = &drm->vbios;
 	int cv = bios->chip_version;
 	uint16_t clktable = 0, scriptptr;
@@ -670,7 +668,7 @@ int run_tmds_table(struct drm_device *de
 	}
 
 	/* don't let script change pll->head binding */
-	sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
+	sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
 	run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000);
 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
@@ -1253,7 +1251,7 @@ olddcb_table(struct drm_device *dev)
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	u8 *dcb = NULL;
 
-	if (nv_device(drm->device)->card_type > NV_04)
+	if (drm->device.info.family > NV_DEVICE_INFO_V0_TNT)
 		dcb = ROMPTR(dev, drm->vbios.data[0x36]);
 	if (!dcb) {
 		NV_WARN(drm, "No DCB data found in VBIOS\n");
@@ -1399,6 +1397,7 @@ parse_dcb20_entry(struct drm_device *dev
 		  uint32_t conn, uint32_t conf, struct dcb_output *entry)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
+	int link = 0;
 
 	entry->type = conn & 0xf;
 	entry->i2c_index = (conn >> 4) & 0xf;
@@ -1444,6 +1443,7 @@ parse_dcb20_entry(struct drm_device *dev
 			if (conf & 0x4)
 				entry->lvdsconf.use_power_scripts = true;
 			entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4;
+			link = entry->lvdsconf.sor.link;
 		}
 		if (conf & mask) {
 			/*
@@ -1492,17 +1492,18 @@ parse_dcb20_entry(struct drm_device *dev
 			entry->dpconf.link_nr = 1;
 			break;
 		}
+		link = entry->dpconf.sor.link;
 		break;
 	case DCB_OUTPUT_TMDS:
 		if (dcb->version >= 0x40) {
 			entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
 			entry->extdev = (conf & 0x0000ff00) >> 8;
+			link = entry->tmdsconf.sor.link;
 		}
 		else if (dcb->version >= 0x30)
 			entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
 		else if (dcb->version >= 0x22)
 			entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
-
 		break;
 	case DCB_OUTPUT_EOL:
 		/* weird g80 mobile type that "nv" treats as a terminator */
@@ -1526,6 +1527,8 @@ parse_dcb20_entry(struct drm_device *dev
 	if (conf & 0x100000)
 		entry->i2c_upper_default = true;
 
+	entry->hasht = (entry->location << 4) | entry->type;
+	entry->hashm = (entry->heads << 8) | (link << 6) | entry->or;
 	return true;
 }
 
@@ -1908,7 +1911,7 @@ static int load_nv17_hwsq_ucode_entry(st
 	 */
 
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	uint8_t bytes_to_write;
 	uint16_t hwsq_entry_offset;
 	int i;
@@ -1931,15 +1934,15 @@ static int load_nv17_hwsq_ucode_entry(st
 	hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
 
 	/* set sequencer control */
-	nv_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
+	nvif_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
 	bytes_to_write -= 4;
 
 	/* write ucode */
 	for (i = 0; i < bytes_to_write; i += 4)
-		nv_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
+		nvif_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
 
 	/* twiddle NV_PBUS_DEBUG_4 */
-	nv_wr32(device, NV_PBUS_DEBUG_4, nv_rd32(device, NV_PBUS_DEBUG_4) | 0x18);
+	nvif_wr32(device, NV_PBUS_DEBUG_4, nvif_rd32(device, NV_PBUS_DEBUG_4) | 0x18);
 
 	return 0;
 }
@@ -2002,7 +2005,7 @@ uint8_t *nouveau_bios_embedded_edid(stru
 static bool NVInitVBIOS(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_bios *bios = nouveau_bios(drm->device);
+	struct nouveau_bios *bios = nvkm_bios(&drm->device);
 	struct nvbios *legacy = &drm->vbios;
 
 	memset(legacy, 0, sizeof(struct nvbios));
@@ -2054,7 +2057,7 @@ nouveau_bios_posted(struct drm_device *d
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	unsigned htotal;
 
-	if (nv_device(drm->device)->card_type >= NV_50)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 		return true;
 
 	htotal  = NVReadVgaCrtc(dev, 0, 0x06);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,13 +27,9 @@
  *	    Jeremy Kolb  <jkolb@brandeis.edu>
  */
 
-#include <core/engine.h>
+#include <linux/dma-mapping.h>
 #include <linux/swiotlb.h>
 
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/bar.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
@@ -52,7 +48,7 @@ nv10_bo_update_tile_region(struct drm_de
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	int i = reg - drm->tile.reg;
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	struct nouveau_fb_tile *tile = &pfb->tile.region[i];
 	struct nouveau_engine *engine;
 
@@ -109,7 +105,7 @@ nv10_bo_set_tiling(struct drm_device *de
 		   u32 size, u32 pitch, u32 flags)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	struct nouveau_drm_tile *tile, *found = NULL;
 	int i;
 
@@ -153,23 +149,23 @@ nouveau_bo_fixup_align(struct nouveau_bo
 		       int *align, int *size)
 {
 	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 
-	if (device->card_type < NV_50) {
+	if (device->info.family < NV_DEVICE_INFO_V0_TESLA) {
 		if (nvbo->tile_mode) {
-			if (device->chipset >= 0x40) {
+			if (device->info.chipset >= 0x40) {
 				*align = 65536;
 				*size = roundup(*size, 64 * nvbo->tile_mode);
 
-			} else if (device->chipset >= 0x30) {
+			} else if (device->info.chipset >= 0x30) {
 				*align = 32768;
 				*size = roundup(*size, 64 * nvbo->tile_mode);
 
-			} else if (device->chipset >= 0x20) {
+			} else if (device->info.chipset >= 0x20) {
 				*align = 16384;
 				*size = roundup(*size, 64 * nvbo->tile_mode);
 
-			} else if (device->chipset >= 0x10) {
+			} else if (device->info.chipset >= 0x10) {
 				*align = 16384;
 				*size = roundup(*size, 32 * nvbo->tile_mode);
 			}
@@ -196,12 +192,12 @@ nouveau_bo_new(struct drm_device *dev, i
 	int lpg_shift = 12;
 	int max_size;
 
-	if (drm->client.base.vm)
-		lpg_shift = drm->client.base.vm->vmm->lpg_shift;
+	if (drm->client.vm)
+		lpg_shift = drm->client.vm->vmm->lpg_shift;
 	max_size = INT_MAX & ~((1 << lpg_shift) - 1);
 
 	if (size <= 0 || size > max_size) {
-		nv_warn(drm, "skipped size %x\n", (u32)size);
+		NV_WARN(drm, "skipped size %x\n", (u32)size);
 		return -EINVAL;
 	}
 
@@ -219,9 +215,9 @@ nouveau_bo_new(struct drm_device *dev, i
 	nvbo->bo.bdev = &drm->ttm.bdev;
 
 	nvbo->page_shift = 12;
-	if (drm->client.base.vm) {
+	if (drm->client.vm) {
 		if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024)
-			nvbo->page_shift = drm->client.base.vm->vmm->lpg_shift;
+			nvbo->page_shift = drm->client.vm->vmm->lpg_shift;
 	}
 
 	nouveau_bo_fixup_align(nvbo, flags, &align, &size);
@@ -261,11 +257,9 @@ static void
 set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
 {
 	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
-	u32 vram_pages = pfb->ram->size >> PAGE_SHIFT;
+	u32 vram_pages = drm->device.info.ram_size >> PAGE_SHIFT;
 
-	if ((nv_device(drm->device)->card_type == NV_10 ||
-	     nv_device(drm->device)->card_type == NV_11) &&
+	if (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
 	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
 	    nvbo->bo.mem.num_pages < vram_pages / 4) {
 		/*
@@ -309,7 +303,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo,
 	struct ttm_buffer_object *bo = &nvbo->bo;
 	int ret;
 
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	ret = ttm_bo_reserve(bo, false, false, false, NULL);
 	if (ret)
 		goto out;
 
@@ -350,7 +344,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo
 	struct ttm_buffer_object *bo = &nvbo->bo;
 	int ret, ref;
 
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	ret = ttm_bo_reserve(bo, false, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -385,7 +379,7 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -500,21 +494,28 @@ nouveau_bo_init_mem_type(struct ttm_bo_d
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		break;
 	case TTM_PL_VRAM:
-		if (nv_device(drm->device)->card_type >= NV_50) {
+		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;
+
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+			/* Some BARs do not support being ioremapped WC */
+			if (nvkm_bar(&drm->device)->iomap_uncached) {
+				man->available_caching = TTM_PL_FLAG_UNCACHED;
+				man->default_caching = TTM_PL_FLAG_UNCACHED;
+			}
+
 			man->func = &nouveau_vram_manager;
 			man->io_reserve_fastpath = false;
 			man->use_io_reserve_lru = true;
 		} else {
 			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;
 	case TTM_PL_TT:
-		if (nv_device(drm->device)->card_type >= NV_50)
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 			man->func = &nouveau_gart_manager;
 		else
 		if (drm->agp.stat != ENABLED)
@@ -763,9 +764,9 @@ nv50_bo_move_init(struct nouveau_channel
 		BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
 		OUT_RING  (chan, handle);
 		BEGIN_NV04(chan, NvSubCopy, 0x0180, 3);
-		OUT_RING  (chan, NvNotify0);
-		OUT_RING  (chan, NvDmaFB);
-		OUT_RING  (chan, NvDmaFB);
+		OUT_RING  (chan, chan->drm->ntfy.handle);
+		OUT_RING  (chan, chan->vram.handle);
+		OUT_RING  (chan, chan->vram.handle);
 	}
 
 	return ret;
@@ -852,7 +853,7 @@ nv04_bo_move_init(struct nouveau_channel
 		BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
 		OUT_RING  (chan, handle);
 		BEGIN_NV04(chan, NvSubCopy, 0x0180, 1);
-		OUT_RING  (chan, NvNotify0);
+		OUT_RING  (chan, chan->drm->ntfy.handle);
 	}
 
 	return ret;
@@ -864,7 +865,7 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_
 {
 	if (mem->mem_type == TTM_PL_TT)
 		return NvDmaTT;
-	return NvDmaFB;
+	return chan->vram.handle;
 }
 
 static int
@@ -922,12 +923,12 @@ nouveau_bo_move_prep(struct nouveau_drm
 	u64 size = (u64)mem->num_pages << PAGE_SHIFT;
 	int ret;
 
-	ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift,
+	ret = nouveau_vm_get(drm->client.vm, size, old_node->page_shift,
 			     NV_MEM_ACCESS_RW, &old_node->vma[0]);
 	if (ret)
 		return ret;
 
-	ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift,
+	ret = nouveau_vm_get(drm->client.vm, size, new_node->page_shift,
 			     NV_MEM_ACCESS_RW, &old_node->vma[1]);
 	if (ret) {
 		nouveau_vm_put(&old_node->vma[0]);
@@ -945,6 +946,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_o
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct nouveau_channel *chan = drm->ttm.chan;
+	struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
 	struct nouveau_fence *fence;
 	int ret;
 
@@ -952,13 +954,13 @@ nouveau_bo_move_m2mf(struct ttm_buffer_o
 	 * old nouveau_mem node, these will get cleaned up after ttm has
 	 * destroyed the ttm_mem_reg
 	 */
-	if (nv_device(drm->device)->card_type >= NV_50) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
 		ret = nouveau_bo_move_prep(drm, bo, new_mem);
 		if (ret)
 			return ret;
 	}
 
-	mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
+	mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
 	ret = nouveau_fence_sync(bo->sync_obj, chan);
 	if (ret == 0) {
 		ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
@@ -973,7 +975,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_o
 			}
 		}
 	}
-	mutex_unlock(&chan->cli->mutex);
+	mutex_unlock(&cli->mutex);
 	return ret;
 }
 
@@ -1005,9 +1007,7 @@ nouveau_bo_move_init(struct nouveau_drm
 	int ret;
 
 	do {
-		struct nouveau_object *object;
 		struct nouveau_channel *chan;
-		u32 handle = (mthd->engine << 16) | mthd->oclass;
 
 		if (mthd->engine)
 			chan = drm->cechan;
@@ -1016,13 +1016,14 @@ nouveau_bo_move_init(struct nouveau_drm
 		if (chan == NULL)
 			continue;
 
-		ret = nouveau_object_new(nv_object(drm), chan->handle, handle,
-					 mthd->oclass, NULL, 0, &object);
+		ret = nvif_object_init(chan->object, NULL,
+				       mthd->oclass | (mthd->engine << 16),
+				       mthd->oclass, NULL, 0,
+				       &drm->ttm.copy);
 		if (ret == 0) {
-			ret = mthd->init(chan, handle);
+			ret = mthd->init(chan, drm->ttm.copy.handle);
 			if (ret) {
-				nouveau_object_del(nv_object(drm),
-						   chan->handle, handle);
+				nvif_object_fini(&drm->ttm.copy);
 				continue;
 			}
 
@@ -1135,7 +1136,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_obj
 	if (new_mem->mem_type != TTM_PL_VRAM)
 		return 0;
 
-	if (nv_device(drm->device)->card_type >= NV_10) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
 		*new_tile = nv10_bo_set_tiling(dev, offset, new_mem->size,
 						nvbo->tile_mode,
 						nvbo->tile_flags);
@@ -1166,7 +1167,7 @@ nouveau_bo_move(struct ttm_buffer_object
 	struct nouveau_drm_tile *new_tile = NULL;
 	int ret = 0;
 
-	if (nv_device(drm->device)->card_type < NV_50) {
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 		ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
 		if (ret)
 			return ret;
@@ -1203,7 +1204,7 @@ nouveau_bo_move(struct ttm_buffer_object
 		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
 
 out:
-	if (nv_device(drm->device)->card_type < NV_50) {
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 		if (ret)
 			nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
 		else
@@ -1227,7 +1228,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
 	struct nouveau_drm *drm = nouveau_bdev(bdev);
 	struct nouveau_mem *node = mem->mm_node;
-	struct drm_device *dev = drm->dev;
 	int ret;
 
 	mem->bus.addr = NULL;
@@ -1246,19 +1246,19 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 		if (drm->agp.stat == ENABLED) {
 			mem->bus.offset = mem->start << PAGE_SHIFT;
 			mem->bus.base = drm->agp.base;
-			mem->bus.is_iomem = !dev->agp->cant_use_aperture;
+			mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture;
 		}
 #endif
-		if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
+		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype)
 			/* untiled */
 			break;
 		/* fallthrough, tiled memory */
 	case TTM_PL_VRAM:
 		mem->bus.offset = mem->start << PAGE_SHIFT;
-		mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);
+		mem->bus.base = nv_device_resource_start(nvkm_device(&drm->device), 1);
 		mem->bus.is_iomem = true;
-		if (nv_device(drm->device)->card_type >= NV_50) {
-			struct nouveau_bar *bar = nouveau_bar(drm->device);
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+			struct nouveau_bar *bar = nvkm_bar(&drm->device);
 
 			ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,
 					&node->bar_vma);
@@ -1278,7 +1278,7 @@ static void
 nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
 	struct nouveau_drm *drm = nouveau_bdev(bdev);
-	struct nouveau_bar *bar = nouveau_bar(drm->device);
+	struct nouveau_bar *bar = nvkm_bar(&drm->device);
 	struct nouveau_mem *node = mem->mm_node;
 
 	if (!node->bar_vma.node)
@@ -1292,15 +1292,15 @@ nouveau_ttm_fault_reserve_notify(struct
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct nouveau_device *device = nv_device(drm->device);
-	u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT;
+	struct nvif_device *device = &drm->device;
+	u32 mappable = nv_device_resource_len(nvkm_device(device), 1) >> PAGE_SHIFT;
 	int ret;
 
 	/* as long as the bo isn't in vram, and isn't tiled, we've got
 	 * nothing to do here.
 	 */
 	if (bo->mem.mem_type != TTM_PL_VRAM) {
-		if (nv_device(drm->device)->card_type < NV_50 ||
+		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA ||
 		    !nouveau_bo_tile_layout(nvbo))
 			return 0;
 
@@ -1315,7 +1315,7 @@ nouveau_ttm_fault_reserve_notify(struct
 	}
 
 	/* make sure bo is in mappable vram */
-	if (nv_device(drm->device)->card_type >= NV_50 ||
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA ||
 	    bo->mem.start + bo->mem.num_pages < mappable)
 		return 0;
 
@@ -1333,6 +1333,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *t
 	struct nouveau_drm *drm;
 	struct nouveau_device *device;
 	struct drm_device *dev;
+	struct device *pdev;
 	unsigned i;
 	int r;
 	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1349,8 +1350,9 @@ nouveau_ttm_tt_populate(struct ttm_tt *t
 	}
 
 	drm = nouveau_bdev(ttm->bdev);
-	device = nv_device(drm->device);
+	device = nvkm_device(&drm->device);
 	dev = drm->dev;
+	pdev = nv_device_base(device);
 
 #if __OS_HAS_AGP
 	if (drm->agp.stat == ENABLED) {
@@ -1370,17 +1372,22 @@ nouveau_ttm_tt_populate(struct ttm_tt *t
 	}
 
 	for (i = 0; i < ttm->num_pages; i++) {
-		ttm_dma->dma_address[i] = nv_device_map_page(device,
-							     ttm->pages[i]);
-		if (!ttm_dma->dma_address[i]) {
+		dma_addr_t addr;
+
+		addr = dma_map_page(pdev, ttm->pages[i], 0, PAGE_SIZE,
+				    DMA_BIDIRECTIONAL);
+
+		if (dma_mapping_error(pdev, addr)) {
 			while (--i) {
-				nv_device_unmap_page(device,
-						     ttm_dma->dma_address[i]);
+				dma_unmap_page(pdev, ttm_dma->dma_address[i],
+					       PAGE_SIZE, DMA_BIDIRECTIONAL);
 				ttm_dma->dma_address[i] = 0;
 			}
 			ttm_pool_unpopulate(ttm);
 			return -EFAULT;
 		}
+
+		ttm_dma->dma_address[i] = addr;
 	}
 	return 0;
 }
@@ -1392,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt
 	struct nouveau_drm *drm;
 	struct nouveau_device *device;
 	struct drm_device *dev;
+	struct device *pdev;
 	unsigned i;
 	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
 
@@ -1399,8 +1407,9 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt
 		return;
 
 	drm = nouveau_bdev(ttm->bdev);
-	device = nv_device(drm->device);
+	device = nvkm_device(&drm->device);
 	dev = drm->dev;
+	pdev = nv_device_base(device);
 
 #if __OS_HAS_AGP
 	if (drm->agp.stat == ENABLED) {
@@ -1418,7 +1427,8 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt
 
 	for (i = 0; i < ttm->num_pages; i++) {
 		if (ttm_dma->dma_address[i]) {
-			nv_device_unmap_page(device, ttm_dma->dma_address[i]);
+			dma_unmap_page(pdev, ttm_dma->dma_address[i], PAGE_SIZE,
+				       DMA_BIDIRECTIONAL);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,16 +22,11 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/object.h>
-#include <core/client.h>
-#include <core/device.h>
-#include <core/class.h>
-
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/instmem.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
 
-#include <engine/software.h>
+/*XXX*/
+#include <core/client.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -47,7 +42,7 @@ module_param_named(vram_pushbuf, nouveau
 int
 nouveau_channel_idle(struct nouveau_channel *chan)
 {
-	struct nouveau_cli *cli = chan->cli;
+	struct nouveau_cli *cli = (void *)nvif_client(chan->object);
 	struct nouveau_fence *fence = NULL;
 	int ret;
 
@@ -58,8 +53,8 @@ nouveau_channel_idle(struct nouveau_chan
 	}
 
 	if (ret)
-		NV_ERROR(cli, "failed to idle channel 0x%08x [%s]\n",
-			 chan->handle, cli->base.name);
+		NV_PRINTK(error, cli, "failed to idle channel 0x%08x [%s]\n",
+			  chan->object->handle, nvkm_client(&cli->base)->name);
 	return ret;
 }
 
@@ -68,36 +63,34 @@ nouveau_channel_del(struct nouveau_chann
 {
 	struct nouveau_channel *chan = *pchan;
 	if (chan) {
-		struct nouveau_object *client = nv_object(chan->cli);
 		if (chan->fence) {
 			nouveau_channel_idle(chan);
 			nouveau_fence(chan->drm)->context_del(chan);
 		}
-		nouveau_object_del(client, NVDRM_DEVICE, chan->handle);
-		nouveau_object_del(client, NVDRM_DEVICE, chan->push.handle);
+		nvif_object_fini(&chan->nvsw);
+		nvif_object_fini(&chan->gart);
+		nvif_object_fini(&chan->vram);
+		nvif_object_ref(NULL, &chan->object);
+		nvif_object_fini(&chan->push.ctxdma);
 		nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma);
 		nouveau_bo_unmap(chan->push.buffer);
 		if (chan->push.buffer && chan->push.buffer->pin_refcnt)
 			nouveau_bo_unpin(chan->push.buffer);
 		nouveau_bo_ref(NULL, &chan->push.buffer);
+		nvif_device_ref(NULL, &chan->device);
 		kfree(chan);
 	}
 	*pchan = NULL;
 }
 
 static int
-nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
-		     u32 parent, u32 handle, u32 size,
-		     struct nouveau_channel **pchan)
+nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
+		     u32 handle, u32 size, struct nouveau_channel **pchan)
 {
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_instmem *imem = nouveau_instmem(device);
-	struct nouveau_vmmgr *vmm = nouveau_vmmgr(device);
-	struct nouveau_fb *pfb = nouveau_fb(device);
-	struct nouveau_client *client = &cli->base;
-	struct nv_dma_class args = {};
+	struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+	struct nouveau_vmmgr *vmm = nvkm_vmmgr(device);
+	struct nv_dma_v0 args = {};
 	struct nouveau_channel *chan;
-	struct nouveau_object *push;
 	u32 target;
 	int ret;
 
@@ -105,9 +98,8 @@ nouveau_channel_prep(struct nouveau_drm
 	if (!chan)
 		return -ENOMEM;
 
-	chan->cli = cli;
+	nvif_device_ref(device, &chan->device);
 	chan->drm = drm;
-	chan->handle = handle;
 
 	/* allocate memory for dma push buffer */
 	target = TTM_PL_FLAG_TT;
@@ -132,51 +124,54 @@ nouveau_channel_prep(struct nouveau_drm
 	 * we be able to call out to other (indirect) push buffers
 	 */
 	chan->push.vma.offset = chan->push.buffer->bo.offset;
-	chan->push.handle = NVDRM_PUSH | (handle & 0xffff);
 
-	if (device->card_type >= NV_50) {
-		ret = nouveau_bo_vma_add(chan->push.buffer, client->vm,
+	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		ret = nouveau_bo_vma_add(chan->push.buffer, cli->vm,
 					&chan->push.vma);
 		if (ret) {
 			nouveau_channel_del(pchan);
 			return ret;
 		}
 
-		args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+		args.target = NV_DMA_V0_TARGET_VM;
+		args.access = NV_DMA_V0_ACCESS_VM;
 		args.start = 0;
-		args.limit = client->vm->vmm->limit - 1;
+		args.limit = cli->vm->vmm->limit - 1;
 	} else
 	if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
-		u64 limit = pfb->ram->size - imem->reserved - 1;
-		if (device->card_type == NV_04) {
+		if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
 			/* nv04 vram pushbuf hack, retarget to its location in
 			 * the framebuffer bar rather than direct vram access..
 			 * nfi why this exists, it came from the -nv ddx.
 			 */
-			args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR;
-			args.start = nv_device_resource_start(device, 1);
-			args.limit = args.start + limit;
+			args.target = NV_DMA_V0_TARGET_PCI;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
+			args.start = nv_device_resource_start(nvkm_device(device), 1);
+			args.limit = args.start + device->info.ram_user - 1;
 		} else {
-			args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_VRAM;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = 0;
-			args.limit = limit;
+			args.limit = device->info.ram_user - 1;
 		}
 	} else {
 		if (chan->drm->agp.stat == ENABLED) {
-			args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_AGP;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = chan->drm->agp.base;
 			args.limit = chan->drm->agp.base +
 				     chan->drm->agp.size - 1;
 		} else {
-			args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_VM;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = 0;
 			args.limit = vmm->limit - 1;
 		}
 	}
 
-	ret = nouveau_object_new(nv_object(chan->cli), parent,
-				 chan->push.handle, 0x0002,
-				 &args, sizeof(args), &push);
+	ret = nvif_object_init(nvif_object(device), NULL, NVDRM_PUSH |
+			       (handle & 0xffff), NV_DMA_FROM_MEMORY,
+			       &args, sizeof(args), &chan->push.ctxdma);
 	if (ret) {
 		nouveau_channel_del(pchan);
 		return ret;
@@ -186,38 +181,56 @@ nouveau_channel_prep(struct nouveau_drm
 }
 
 static int
-nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli,
-		    u32 parent, u32 handle, u32 engine,
-		    struct nouveau_channel **pchan)
+nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
+		    u32 handle, u32 engine, struct nouveau_channel **pchan)
 {
-	static const u16 oclasses[] = { NVE0_CHANNEL_IND_CLASS,
-					NVC0_CHANNEL_IND_CLASS,
-					NV84_CHANNEL_IND_CLASS,
-					NV50_CHANNEL_IND_CLASS,
+	static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A,
+					FERMI_CHANNEL_GPFIFO,
+					G82_CHANNEL_GPFIFO,
+					NV50_CHANNEL_GPFIFO,
 					0 };
 	const u16 *oclass = oclasses;
-	struct nve0_channel_ind_class args;
+	union {
+		struct nv50_channel_gpfifo_v0 nv50;
+		struct kepler_channel_gpfifo_a_v0 kepler;
+	} args, *retn;
 	struct nouveau_channel *chan;
+	u32 size;
 	int ret;
 
 	/* allocate dma push buffer */
-	ret = nouveau_channel_prep(drm, cli, parent, handle, 0x12000, &chan);
+	ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan);
 	*pchan = chan;
 	if (ret)
 		return ret;
 
 	/* create channel object */
-	args.pushbuf = chan->push.handle;
-	args.ioffset = 0x10000 + chan->push.vma.offset;
-	args.ilength = 0x02000;
-	args.engine  = engine;
-
 	do {
-		ret = nouveau_object_new(nv_object(cli), parent, handle,
-					 *oclass++, &args, sizeof(args),
-					 &chan->object);
-		if (ret == 0)
+		if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
+			args.kepler.version = 0;
+			args.kepler.engine  = engine;
+			args.kepler.pushbuf = chan->push.ctxdma.handle;
+			args.kepler.ilength = 0x02000;
+			args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
+			size = sizeof(args.kepler);
+		} else {
+			args.nv50.version = 0;
+			args.nv50.pushbuf = chan->push.ctxdma.handle;
+			args.nv50.ilength = 0x02000;
+			args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
+			size = sizeof(args.nv50);
+		}
+
+		ret = nvif_object_new(nvif_object(device), handle, *oclass++,
+				      &args, size, &chan->object);
+		if (ret == 0) {
+			retn = chan->object->data;
+			if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A)
+				chan->chid = retn->kepler.chid;
+			else
+				chan->chid = retn->nv50.chid;
 			return ret;
+		}
 	} while (*oclass);
 
 	nouveau_channel_del(pchan);
@@ -225,35 +238,38 @@ nouveau_channel_ind(struct nouveau_drm *
 }
 
 static int
-nouveau_channel_dma(struct nouveau_drm *drm, struct nouveau_cli *cli,
-		    u32 parent, u32 handle, struct nouveau_channel **pchan)
+nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
+		    u32 handle, struct nouveau_channel **pchan)
 {
-	static const u16 oclasses[] = { NV40_CHANNEL_DMA_CLASS,
-					NV17_CHANNEL_DMA_CLASS,
-					NV10_CHANNEL_DMA_CLASS,
-					NV03_CHANNEL_DMA_CLASS,
+	static const u16 oclasses[] = { NV40_CHANNEL_DMA,
+					NV17_CHANNEL_DMA,
+					NV10_CHANNEL_DMA,
+					NV03_CHANNEL_DMA,
 					0 };
 	const u16 *oclass = oclasses;
-	struct nv03_channel_dma_class args;
+	struct nv03_channel_dma_v0 args, *retn;
 	struct nouveau_channel *chan;
 	int ret;
 
 	/* allocate dma push buffer */
-	ret = nouveau_channel_prep(drm, cli, parent, handle, 0x10000, &chan);
+	ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan);
 	*pchan = chan;
 	if (ret)
 		return ret;
 
 	/* create channel object */
-	args.pushbuf = chan->push.handle;
+	args.version = 0;
+	args.pushbuf = chan->push.ctxdma.handle;
 	args.offset = chan->push.vma.offset;
 
 	do {
-		ret = nouveau_object_new(nv_object(cli), parent, handle,
-					 *oclass++, &args, sizeof(args),
-					 &chan->object);
-		if (ret == 0)
+		ret = nvif_object_new(nvif_object(device), handle, *oclass++,
+				      &args, sizeof(args), &chan->object);
+		if (ret == 0) {
+			retn = chan->object->data;
+			chan->chid = retn->chid;
 			return ret;
+		}
 	} while (ret && *oclass);
 
 	nouveau_channel_del(pchan);
@@ -263,60 +279,63 @@ nouveau_channel_dma(struct nouveau_drm *
 static int
 nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
 {
-	struct nouveau_client *client = nv_client(chan->cli);
-	struct nouveau_device *device = nv_device(chan->drm->device);
-	struct nouveau_instmem *imem = nouveau_instmem(device);
-	struct nouveau_vmmgr *vmm = nouveau_vmmgr(device);
-	struct nouveau_fb *pfb = nouveau_fb(device);
+	struct nvif_device *device = chan->device;
+	struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+	struct nouveau_vmmgr *vmm = nvkm_vmmgr(device);
 	struct nouveau_software_chan *swch;
-	struct nouveau_object *object;
-	struct nv_dma_class args = {};
+	struct nv_dma_v0 args = {};
 	int ret, i;
 
+	nvif_object_map(chan->object);
+
 	/* allocate dma objects to cover all allowed vram, and gart */
-	if (device->card_type < NV_C0) {
-		if (device->card_type >= NV_50) {
-			args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+	if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
+		if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+			args.target = NV_DMA_V0_TARGET_VM;
+			args.access = NV_DMA_V0_ACCESS_VM;
 			args.start = 0;
-			args.limit = client->vm->vmm->limit - 1;
+			args.limit = cli->vm->vmm->limit - 1;
 		} else {
-			args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_VRAM;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = 0;
-			args.limit = pfb->ram->size - imem->reserved - 1;
+			args.limit = device->info.ram_user - 1;
 		}
 
-		ret = nouveau_object_new(nv_object(client), chan->handle, vram,
-					 0x003d, &args, sizeof(args), &object);
+		ret = nvif_object_init(chan->object, NULL, vram,
+				       NV_DMA_IN_MEMORY, &args,
+				       sizeof(args), &chan->vram);
 		if (ret)
 			return ret;
 
-		if (device->card_type >= NV_50) {
-			args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+		if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+			args.target = NV_DMA_V0_TARGET_VM;
+			args.access = NV_DMA_V0_ACCESS_VM;
 			args.start = 0;
-			args.limit = client->vm->vmm->limit - 1;
+			args.limit = cli->vm->vmm->limit - 1;
 		} else
 		if (chan->drm->agp.stat == ENABLED) {
-			args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_AGP;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = chan->drm->agp.base;
 			args.limit = chan->drm->agp.base +
 				     chan->drm->agp.size - 1;
 		} else {
-			args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
+			args.target = NV_DMA_V0_TARGET_VM;
+			args.access = NV_DMA_V0_ACCESS_RDWR;
 			args.start = 0;
 			args.limit = vmm->limit - 1;
 		}
 
-		ret = nouveau_object_new(nv_object(client), chan->handle, gart,
-					 0x003d, &args, sizeof(args), &object);
+		ret = nvif_object_init(chan->object, NULL, gart,
+				       NV_DMA_IN_MEMORY, &args,
+				       sizeof(args), &chan->gart);
 		if (ret)
 			return ret;
-
-		chan->vram = vram;
-		chan->gart = gart;
 	}
 
 	/* initialise dma tracking parameters */
-	switch (nv_hclass(chan->object) & 0x00ff) {
+	switch (chan->object->oclass & 0x00ff) {
 	case 0x006b:
 	case 0x006e:
 		chan->user_put = 0x40;
@@ -347,13 +366,13 @@ nouveau_channel_init(struct nouveau_chan
 		OUT_RING(chan, 0x00000000);
 
 	/* allocate software object class (used for fences on <= nv05) */
-	if (device->card_type < NV_10) {
-		ret = nouveau_object_new(nv_object(client), chan->handle,
-					 NvSw, 0x006e, NULL, 0, &object);
+	if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
+		ret = nvif_object_init(chan->object, NULL, 0x006e, 0x006e,
+				       NULL, 0, &chan->nvsw);
 		if (ret)
 			return ret;
 
-		swch = (void *)object->parent;
+		swch = (void *)nvkm_object(&chan->nvsw)->parent;
 		swch->flip = nouveau_flip_complete;
 		swch->flip_data = chan;
 
@@ -362,7 +381,7 @@ nouveau_channel_init(struct nouveau_chan
 			return ret;
 
 		BEGIN_NV04(chan, NvSubSw, 0x0000, 1);
-		OUT_RING  (chan, NvSw);
+		OUT_RING  (chan, chan->nvsw.handle);
 		FIRE_RING (chan);
 	}
 
@@ -371,25 +390,26 @@ nouveau_channel_init(struct nouveau_chan
 }
 
 int
-nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli,
-		    u32 parent, u32 handle, u32 arg0, u32 arg1,
+nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
+		    u32 handle, u32 arg0, u32 arg1,
 		    struct nouveau_channel **pchan)
 {
+	struct nouveau_cli *cli = (void *)nvif_client(&device->base);
 	int ret;
 
-	ret = nouveau_channel_ind(drm, cli, parent, handle, arg0, pchan);
+	ret = nouveau_channel_ind(drm, device, handle, arg0, pchan);
 	if (ret) {
-		NV_DEBUG(cli, "ib channel create, %d\n", ret);
-		ret = nouveau_channel_dma(drm, cli, parent, handle, pchan);
+		NV_PRINTK(debug, cli, "ib channel create, %d\n", ret);
+		ret = nouveau_channel_dma(drm, device, handle, pchan);
 		if (ret) {
-			NV_DEBUG(cli, "dma channel create, %d\n", ret);
+			NV_PRINTK(debug, cli, "dma channel create, %d\n", ret);
 			return ret;
 		}
 	}
 
 	ret = nouveau_channel_init(*pchan, arg0, arg1);
 	if (ret) {
-		NV_ERROR(cli, "channel failed to initialise, %d\n", ret);
+		NV_PRINTK(error, cli, "channel failed to initialise, %d\n", ret);
 		nouveau_channel_del(pchan);
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_chan.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_chan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,20 +1,23 @@
 #ifndef __NOUVEAU_CHAN_H__
 #define __NOUVEAU_CHAN_H__
 
-struct nouveau_cli;
+#include <nvif/object.h>
+struct nvif_device;
 
 struct nouveau_channel {
-	struct nouveau_cli *cli;
+	struct nvif_device *device;
 	struct nouveau_drm *drm;
 
-	u32 handle;
-	u32 vram;
-	u32 gart;
+	int chid;
+
+	struct nvif_object vram;
+	struct nvif_object gart;
+	struct nvif_object nvsw;
 
 	struct {
 		struct nouveau_bo *buffer;
 		struct nouveau_vma vma;
-		u32 handle;
+		struct nvif_object ctxdma;
 	} push;
 
 	/* TODO: this will be reworked in the near future */
@@ -34,12 +37,12 @@ struct nouveau_channel {
 	u32 user_get;
 	u32 user_put;
 
-	struct nouveau_object *object;
+	struct nvif_object *object;
 };
 
 
-int  nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *,
-			 u32 parent, u32 handle, u32 arg0, u32 arg1,
+int  nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
+			 u32 handle, u32 arg0, u32 arg1,
 			 struct nouveau_channel **);
 void nouveau_channel_del(struct nouveau_channel **);
 int  nouveau_channel_idle(struct nouveau_channel *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,7 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 
-#include <subdev/i2c.h>
-#include <subdev/gpio.h>
-#include <engine/disp.h>
+#include <nvif/event.h>
 
 MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
 static int nouveau_tv_disable = 0;
@@ -63,7 +61,7 @@ find_encoder(struct drm_connector *conne
 {
 	struct drm_device *dev = connector->dev;
 	struct nouveau_encoder *nv_encoder;
-	struct drm_mode_object *obj;
+	struct drm_encoder *enc;
 	int i, id;
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
@@ -71,10 +69,10 @@ find_encoder(struct drm_connector *conne
 		if (!id)
 			break;
 
-		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		enc = drm_encoder_find(dev, id);
+		if (!enc)
 			continue;
-		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+		nv_encoder = nouveau_encoder(enc);
 
 		if (type == DCB_OUTPUT_ANY ||
 		    (nv_encoder->dcb && nv_encoder->dcb->type == type))
@@ -102,9 +100,9 @@ static void
 nouveau_connector_destroy(struct drm_connector *connector)
 {
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
-	nouveau_event_ref(NULL, &nv_connector->hpd);
+	nvif_notify_fini(&nv_connector->hpd);
 	kfree(nv_connector->edid);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	if (nv_connector->aux.transfer)
 		drm_dp_aux_unregister(&nv_connector->aux);
@@ -117,9 +115,9 @@ nouveau_connector_ddc_detect(struct drm_
 	struct drm_device *dev = connector->dev;
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+	struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
 	struct nouveau_encoder *nv_encoder;
-	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
 	int i, panel = -ENODEV;
 
 	/* eDP panels need powering on by us (if the VBIOS doesn't default it
@@ -139,10 +137,10 @@ nouveau_connector_ddc_detect(struct drm_
 		if (id == 0)
 			break;
 
-		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(dev, id);
+		if (!encoder)
 			continue;
-		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+		nv_encoder = nouveau_encoder(encoder);
 
 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
 			int ret = nouveau_dp_detect(nv_encoder);
@@ -206,7 +204,7 @@ nouveau_connector_set_encoder(struct drm
 		return;
 	nv_connector->detected_encoder = nv_encoder;
 
-	if (nv_device(drm->device)->card_type >= NV_50) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
 		connector->interlace_allowed = true;
 		connector->doublescan_allowed = true;
 	} else
@@ -216,9 +214,8 @@ nouveau_connector_set_encoder(struct drm
 		connector->interlace_allowed = false;
 	} else {
 		connector->doublescan_allowed = true;
-		if (nv_device(drm->device)->card_type == NV_20 ||
-		    ((nv_device(drm->device)->card_type == NV_10 ||
-		      nv_device(drm->device)->card_type == NV_11) &&
+		if (drm->device.info.family == NV_DEVICE_INFO_V0_KELVIN ||
+		    (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
 		     (dev->pdev->device & 0x0ff0) != 0x0100 &&
 		     (dev->pdev->device & 0x0ff0) != 0x0150))
 			/* HW is broken */
@@ -802,11 +799,11 @@ get_tmds_link_bandwidth(struct drm_conne
 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
 
 	if (dcb->location != DCB_LOC_ON_CHIP ||
-	    nv_device(drm->device)->chipset >= 0x46)
+	    drm->device.info.chipset >= 0x46)
 		return 165000;
-	else if (nv_device(drm->device)->chipset >= 0x40)
+	else if (drm->device.info.chipset >= 0x40)
 		return 155000;
-	else if (nv_device(drm->device)->chipset >= 0x18)
+	else if (drm->device.info.chipset >= 0x18)
 		return 135000;
 	else
 		return 112000;
@@ -939,18 +936,19 @@ nouveau_connector_funcs_dp = {
 	.force = nouveau_connector_force
 };
 
-static void
-nouveau_connector_hotplug_work(struct work_struct *work)
+static int
+nouveau_connector_hotplug(struct nvif_notify *notify)
 {
 	struct nouveau_connector *nv_connector =
-		container_of(work, typeof(*nv_connector), work);
+		container_of(notify, typeof(*nv_connector), hpd);
 	struct drm_connector *connector = &nv_connector->base;
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	const struct nvif_notify_conn_rep_v0 *rep = notify->data;
 	const char *name = connector->name;
 
-	if (nv_connector->status & NVKM_HPD_IRQ) {
+	if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
 	} else {
-		bool plugged = (nv_connector->status != NVKM_HPD_UNPLUG);
+		bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
 
 		NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
 
@@ -961,16 +959,7 @@ nouveau_connector_hotplug_work(struct wo
 		drm_helper_hpd_irq_event(connector->dev);
 	}
 
-	nouveau_event_get(nv_connector->hpd);
-}
-
-static int
-nouveau_connector_hotplug(void *data, u32 type, int index)
-{
-	struct nouveau_connector *nv_connector = data;
-	nv_connector->status = type;
-	schedule_work(&nv_connector->work);
-	return NVKM_EVENT_DROP;
+	return NVIF_NOTIFY_KEEP;
 }
 
 static ssize_t
@@ -1040,7 +1029,6 @@ nouveau_connector_create(struct drm_devi
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_display *disp = nouveau_display(dev);
 	struct nouveau_connector *nv_connector = NULL;
-	struct nouveau_disp *pdisp = nouveau_disp(drm->device);
 	struct drm_connector *connector;
 	int type, ret = 0;
 	bool dummy;
@@ -1194,7 +1182,7 @@ nouveau_connector_create(struct drm_devi
 
 	switch (nv_connector->type) {
 	case DCB_CONNECTOR_VGA:
-		if (nv_device(drm->device)->card_type >= NV_50) {
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
 			drm_object_attach_property(&connector->base,
 					dev->mode_config.scaling_mode_property,
 					nv_connector->scaling_mode);
@@ -1226,16 +1214,20 @@ nouveau_connector_create(struct drm_devi
 		break;
 	}
 
-	ret = nouveau_event_new(pdisp->hpd, NVKM_HPD, index,
-				nouveau_connector_hotplug,
-				nv_connector, &nv_connector->hpd);
+	ret = nvif_notify_init(&disp->disp, NULL, nouveau_connector_hotplug,
+				true, NV04_DISP_NTFY_CONN,
+			       &(struct nvif_notify_conn_req_v0) {
+				.mask = NVIF_NOTIFY_CONN_V0_ANY,
+				.conn = index,
+			       },
+			       sizeof(struct nvif_notify_conn_req_v0),
+			       sizeof(struct nvif_notify_conn_rep_v0),
+			       &nv_connector->hpd);
 	if (ret)
 		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 	else
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-	INIT_WORK(&nv_connector->work, nouveau_connector_hotplug_work);
-
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return connector;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,14 +27,12 @@
 #ifndef __NOUVEAU_CONNECTOR_H__
 #define __NOUVEAU_CONNECTOR_H__
 
+#include <nvif/notify.h>
+
 #include <drm/drm_edid.h>
 #include <drm/drm_dp_helper.h>
 #include "nouveau_crtc.h"
 
-#include <core/event.h>
-
-#include <subdev/bios.h>
-
 struct nouveau_i2c_port;
 
 enum nouveau_underscan_type {
@@ -67,9 +65,7 @@ struct nouveau_connector {
 	u8 index;
 	u8 *dcb;
 
-	struct nouveau_eventh *hpd;
-	u32 status;
-	struct work_struct work;
+	struct nvif_notify hpd;
 
 	struct drm_dp_aux aux;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,10 +27,13 @@
 #ifndef __NOUVEAU_CRTC_H__
 #define __NOUVEAU_CRTC_H__
 
+#include <nvif/notify.h>
+
 struct nouveau_crtc {
 	struct drm_crtc base;
 
 	int index;
+	struct nvif_notify vblank;
 
 	uint32_t dpms_saved_fp_control;
 	uint32_t fp_users;
@@ -46,7 +49,7 @@ struct nouveau_crtc {
 		int cpp;
 		bool blanked;
 		uint32_t offset;
-		uint32_t tile_flags;
+		uint32_t handle;
 	} fb;
 
 	struct {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
+#include <nvif/class.h>
+
 #include "nouveau_fbcon.h"
 #include "dispnv04/hw.h"
 #include "nouveau_crtc.h"
@@ -37,35 +39,42 @@
 
 #include "nouveau_fence.h"
 
-#include <engine/disp.h>
-
-#include <core/class.h>
+#include <nvif/event.h>
 
 static int
-nouveau_display_vblank_handler(void *data, u32 type, int head)
+nouveau_display_vblank_handler(struct nvif_notify *notify)
 {
-	struct nouveau_drm *drm = data;
-	drm_handle_vblank(drm->dev, head);
-	return NVKM_EVENT_KEEP;
+	struct nouveau_crtc *nv_crtc =
+		container_of(notify, typeof(*nv_crtc), vblank);
+	drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index);
+	return NVIF_NOTIFY_KEEP;
 }
 
 int
 nouveau_display_vblank_enable(struct drm_device *dev, int head)
 {
-	struct nouveau_display *disp = nouveau_display(dev);
-	if (disp) {
-		nouveau_event_get(disp->vblank[head]);
-		return 0;
+	struct drm_crtc *crtc;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		if (nv_crtc->index == head) {
+			nvif_notify_get(&nv_crtc->vblank);
+			return 0;
+		}
 	}
-	return -EIO;
+	return -EINVAL;
 }
 
 void
 nouveau_display_vblank_disable(struct drm_device *dev, int head)
 {
-	struct nouveau_display *disp = nouveau_display(dev);
-	if (disp)
-		nouveau_event_put(disp->vblank[head]);
+	struct drm_crtc *crtc;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		if (nv_crtc->index == head) {
+			nvif_notify_put(&nv_crtc->vblank);
+			return;
+		}
+	}
 }
 
 static inline int
@@ -86,17 +95,22 @@ int
 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
 				ktime_t *stime, ktime_t *etime)
 {
-	const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
+	struct {
+		struct nv04_disp_mthd_v0 base;
+		struct nv04_disp_scanoutpos_v0 scan;
+	} args = {
+		.base.method = NV04_DISP_SCANOUTPOS,
+		.base.head = nouveau_crtc(crtc)->index,
+	};
 	struct nouveau_display *disp = nouveau_display(crtc->dev);
-	struct nv04_display_scanoutpos args;
 	int ret, retry = 1;
 
 	do {
-		ret = nv_exec(disp->core, mthd, &args, sizeof(args));
+		ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
 		if (ret != 0)
 			return 0;
 
-		if (args.vline) {
+		if (args.scan.vline) {
 			ret |= DRM_SCANOUTPOS_ACCURATE;
 			ret |= DRM_SCANOUTPOS_VALID;
 			break;
@@ -105,10 +119,11 @@ nouveau_display_scanoutpos_head(struct d
 		if (retry) ndelay(crtc->linedur_ns);
 	} while (retry--);
 
-	*hpos = args.hline;
-	*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
-	if (stime) *stime = ns_to_ktime(args.time[0]);
-	if (etime) *etime = ns_to_ktime(args.time[1]);
+	*hpos = args.scan.hline;
+	*vpos = calc(args.scan.vblanks, args.scan.vblanke,
+		     args.scan.vtotal, args.scan.vline);
+	if (stime) *stime = ns_to_ktime(args.scan.time[0]);
+	if (etime) *etime = ns_to_ktime(args.scan.time[1]);
 
 	if (*vpos < 0)
 		ret |= DRM_SCANOUTPOS_INVBL;
@@ -151,16 +166,13 @@ nouveau_display_vblstamp(struct drm_devi
 static void
 nouveau_display_vblank_fini(struct drm_device *dev)
 {
-	struct nouveau_display *disp = nouveau_display(dev);
-	int i;
+	struct drm_crtc *crtc;
 
 	drm_vblank_cleanup(dev);
 
-	if (disp->vblank) {
-		for (i = 0; i < dev->mode_config.num_crtc; i++)
-			nouveau_event_ref(NULL, &disp->vblank[i]);
-		kfree(disp->vblank);
-		disp->vblank = NULL;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		nvif_notify_fini(&nv_crtc->vblank);
 	}
 }
 
@@ -168,19 +180,20 @@ static int
 nouveau_display_vblank_init(struct drm_device *dev)
 {
 	struct nouveau_display *disp = nouveau_display(dev);
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-	int ret, i;
-
-	disp->vblank = kzalloc(dev->mode_config.num_crtc *
-			       sizeof(*disp->vblank), GFP_KERNEL);
-	if (!disp->vblank)
-		return -ENOMEM;
+	struct drm_crtc *crtc;
+	int ret;
 
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		ret = nouveau_event_new(pdisp->vblank, 1, i,
-					nouveau_display_vblank_handler,
-					drm, &disp->vblank[i]);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		ret = nvif_notify_init(&disp->disp, NULL,
+				       nouveau_display_vblank_handler, false,
+				       NV04_DISP_NTFY_VBLANK,
+				       &(struct nvif_notify_head_req_v0) {
+					.head = nv_crtc->index,
+				       },
+				       sizeof(struct nvif_notify_head_req_v0),
+				       sizeof(struct nvif_notify_head_rep_v0),
+				       &nv_crtc->vblank);
 		if (ret) {
 			nouveau_display_vblank_fini(dev);
 			return ret;
@@ -200,6 +213,10 @@ 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);
@@ -229,63 +246,24 @@ nouveau_framebuffer_init(struct drm_devi
 			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct nouveau_bo *nvbo)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_display *disp = nouveau_display(dev);
 	struct drm_framebuffer *fb = &nv_fb->base;
 	int ret;
 
 	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
 	nv_fb->nvbo = nvbo;
 
-	if (nv_device(drm->device)->card_type >= NV_50) {
-		u32 tile_flags = nouveau_bo_tile_layout(nvbo);
-		if (tile_flags == 0x7a00 ||
-		    tile_flags == 0xfe00)
-			nv_fb->r_dma = NvEvoFB32;
-		else
-		if (tile_flags == 0x7000)
-			nv_fb->r_dma = NvEvoFB16;
-		else
-			nv_fb->r_dma = NvEvoVRAM_LP;
-
-		switch (fb->depth) {
-		case  8: nv_fb->r_format = 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;
-		}
-
-		if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
-			NV_ERROR(drm, "framebuffer requires contiguous bo\n");
-			return -EINVAL;
-		}
-
-		if (nv_device(drm->device)->chipset == 0x50)
-			nv_fb->r_format |= (tile_flags << 8);
-
-		if (!tile_flags) {
-			if (nv_device(drm->device)->card_type < NV_D0)
-				nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
-			else
-				nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
-		} else {
-			u32 mode = nvbo->tile_mode;
-			if (nv_device(drm->device)->card_type >= NV_C0)
-				mode >>= 4;
-			nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
-		}
-	}
-
 	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
-	if (ret) {
+	if (ret)
 		return ret;
+
+	if (disp->fb_ctor) {
+		ret = disp->fb_ctor(fb);
+		if (ret)
+			disp->fb_dtor(fb);
 	}
 
-	return 0;
+	return ret;
 }
 
 static struct drm_framebuffer *
@@ -393,7 +371,7 @@ nouveau_display_init(struct drm_device *
 	/* enable hotplug interrupts */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct nouveau_connector *conn = nouveau_connector(connector);
-		if (conn->hpd) nouveau_event_get(conn->hpd);
+		nvif_notify_get(&conn->hpd);
 	}
 
 	return ret;
@@ -404,37 +382,32 @@ nouveau_display_fini(struct drm_device *
 {
 	struct nouveau_display *disp = nouveau_display(dev);
 	struct drm_connector *connector;
+	int head;
+
+	/* 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);
 
 	/* disable hotplug interrupts */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct nouveau_connector *conn = nouveau_connector(connector);
-		if (conn->hpd) nouveau_event_put(conn->hpd);
+		nvif_notify_put(&conn->hpd);
 	}
 
 	drm_kms_helper_poll_disable(dev);
 	disp->fini(dev);
 }
 
-int
-nouveau_display_create(struct drm_device *dev)
+static void
+nouveau_display_create_properties(struct drm_device *dev)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nouveau_dev(dev);
-	struct nouveau_display *disp;
-	int ret, gen;
-
-	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
-	if (!disp)
-		return -ENOMEM;
-
-	drm_mode_config_init(dev);
-	drm_mode_create_scaling_mode_property(dev);
-	drm_mode_create_dvi_i_properties(dev);
+	struct nouveau_display *disp = nouveau_display(dev);
+	int gen;
 
-	if (nv_device(drm->device)->card_type < NV_50)
+	if (disp->disp.oclass < NV50_DISP)
 		gen = 0;
 	else
-	if (nv_device(drm->device)->card_type < NV_D0)
+	if (disp->disp.oclass < GF110_DISP)
 		gen = 1;
 	else
 		gen = 2;
@@ -449,26 +422,43 @@ nouveau_display_create(struct drm_device
 	disp->underscan_vborder_property =
 		drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
 
-	if (gen >= 1) {
-		/* -90..+90 */
-		disp->vibrant_hue_property =
-			drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
+	if (gen < 1)
+		return;
 
-		/* -100..+100 */
-		disp->color_vibrance_property =
-			drm_property_create_range(dev, 0, "color vibrance", 0, 200);
-	}
+	/* -90..+90 */
+	disp->vibrant_hue_property =
+		drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
+
+	/* -100..+100 */
+	disp->color_vibrance_property =
+		drm_property_create_range(dev, 0, "color vibrance", 0, 200);
+}
+
+int
+nouveau_display_create(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_display *disp;
+	int ret;
+
+	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp)
+		return -ENOMEM;
+
+	drm_mode_config_init(dev);
+	drm_mode_create_scaling_mode_property(dev);
+	drm_mode_create_dvi_i_properties(dev);
 
 	dev->mode_config.funcs = &nouveau_mode_config_funcs;
-	dev->mode_config.fb_base = nv_device_resource_start(device, 1);
+	dev->mode_config.fb_base = nv_device_resource_start(nvkm_device(&drm->device), 1);
 
 	dev->mode_config.min_width = 0;
 	dev->mode_config.min_height = 0;
-	if (nv_device(drm->device)->card_type < NV_10) {
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 		dev->mode_config.max_width = 2048;
 		dev->mode_config.max_height = 2048;
 	} else
-	if (nv_device(drm->device)->card_type < NV_50) {
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 		dev->mode_config.max_width = 4096;
 		dev->mode_config.max_height = 4096;
 	} else {
@@ -479,7 +469,7 @@ nouveau_display_create(struct drm_device
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.prefer_shadow = 1;
 
-	if (nv_device(drm->device)->chipset < 0x11)
+	if (drm->device.info.chipset < 0x11)
 		dev->mode_config.async_page_flip = false;
 	else
 		dev->mode_config.async_page_flip = true;
@@ -487,29 +477,30 @@ nouveau_display_create(struct drm_device
 	drm_kms_helper_poll_init(dev);
 	drm_kms_helper_poll_disable(dev);
 
-	if (drm->vbios.dcb.entries) {
+	if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
 		static const u16 oclass[] = {
-			GM107_DISP_CLASS,
-			NVF0_DISP_CLASS,
-			NVE0_DISP_CLASS,
-			NVD0_DISP_CLASS,
-			NVA3_DISP_CLASS,
-			NV94_DISP_CLASS,
-			NVA0_DISP_CLASS,
-			NV84_DISP_CLASS,
-			NV50_DISP_CLASS,
-			NV04_DISP_CLASS,
+			GM107_DISP,
+			GK110_DISP,
+			GK104_DISP,
+			GF110_DISP,
+			GT214_DISP,
+			GT206_DISP,
+			GT200_DISP,
+			G82_DISP,
+			NV50_DISP,
+			NV04_DISP,
 		};
 		int i;
 
 		for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
-			ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
-						 NVDRM_DISPLAY, oclass[i],
-						 NULL, 0, &disp->core);
+			ret = nvif_object_init(nvif_object(&drm->device), NULL,
+					       NVDRM_DISPLAY, oclass[i],
+					       NULL, 0, &disp->disp);
 		}
 
 		if (ret == 0) {
-			if (nv_mclass(disp->core) < NV50_DISP_CLASS)
+			nouveau_display_create_properties(dev);
+			if (disp->disp.oclass < NV50_DISP)
 				ret = nv04_display_create(dev);
 			else
 				ret = nv50_display_create(dev);
@@ -542,7 +533,6 @@ void
 nouveau_display_destroy(struct drm_device *dev)
 {
 	struct nouveau_display *disp = nouveau_display(dev);
-	struct nouveau_drm *drm = nouveau_drm(dev);
 
 	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
@@ -553,7 +543,7 @@ nouveau_display_destroy(struct drm_devic
 	if (disp->dtor)
 		disp->dtor(dev);
 
-	nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY);
+	nvif_object_fini(&disp->disp);
 
 	nouveau_drm(dev)->display = NULL;
 	kfree(disp);
@@ -602,7 +592,9 @@ nouveau_display_repin(struct drm_device
 		if (!nouveau_fb || !nouveau_fb->nvbo)
 			continue;
 
-		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+		ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+		if (ret)
+			NV_ERROR(drm, "Could not pin framebuffer\n");
 	}
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -620,6 +612,8 @@ void
 nouveau_display_resume(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
+	int head;
+
 	nouveau_display_init(dev);
 
 	/* Force CLUT to get re-loaded during modeset */
@@ -629,6 +623,10 @@ nouveau_display_resume(struct drm_device
 		nv_crtc->lut.depth = 0;
 	}
 
+	/* 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);
+
 	drm_helper_resume_force_mode(dev);
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -669,7 +667,7 @@ nouveau_page_flip_emit(struct nouveau_ch
 	if (ret)
 		goto fail;
 
-	if (nv_device(drm->device)->card_type < NV_C0)
+	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);
@@ -698,12 +696,15 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
 	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
 	struct nouveau_page_flip_state *s;
-	struct nouveau_channel *chan = drm->channel;
+	struct nouveau_channel *chan;
+	struct nouveau_cli *cli;
 	struct nouveau_fence *fence;
 	int ret;
 
-	if (!drm->channel)
+	chan = drm->channel;
+	if (!chan)
 		return -ENODEV;
+	cli = (void *)nvif_client(&chan->device->base);
 
 	s = kzalloc(sizeof(*s), GFP_KERNEL);
 	if (!s)
@@ -715,7 +716,7 @@ nouveau_crtc_page_flip(struct drm_crtc *
 			goto fail_free;
 	}
 
-	mutex_lock(&chan->cli->mutex);
+	mutex_lock(&cli->mutex);
 
 	/* synchronise rendering channel with the kernel's channel */
 	spin_lock(&new_bo->bo.bdev->fence_lock);
@@ -740,7 +741,7 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	drm_vblank_get(dev, nouveau_crtc(crtc)->index);
 
 	/* Emit a page flip */
-	if (nv_device(drm->device)->card_type >= NV_50) {
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
 		ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
 		if (ret)
 			goto fail_unreserve;
@@ -769,7 +770,7 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
 	if (ret)
 		goto fail_unreserve;
-	mutex_unlock(&chan->cli->mutex);
+	mutex_unlock(&cli->mutex);
 
 	/* Update the crtc struct and cleanup */
 	crtc->primary->fb = fb;
@@ -785,7 +786,7 @@ fail_unreserve:
 	drm_vblank_put(dev, nouveau_crtc(crtc)->index);
 	ttm_bo_unreserve(&old_bo->bo);
 fail_unpin:
-	mutex_unlock(&chan->cli->mutex);
+	mutex_unlock(&cli->mutex);
 	if (old_bo != new_bo)
 		nouveau_bo_unpin(new_bo);
 fail_free:
@@ -815,7 +816,7 @@ nouveau_finish_page_flip(struct nouveau_
 	s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
 	if (s->event) {
 		/* Vblank timestamps/counts are only correct on >= NV-50 */
-		if (nv_device(drm->device)->card_type >= NV_50)
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 			crtcid = s->crtc;
 
 		drm_send_vblank_event(dev, crtcid, s->event);
@@ -841,7 +842,7 @@ nouveau_flip_complete(void *data)
 	struct nouveau_page_flip_state state;
 
 	if (!nouveau_finish_page_flip(chan, &state)) {
-		if (nv_device(drm->device)->card_type < NV_50) {
+		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 			nv_set_crtc_base(drm->dev, state.crtc, state.offset +
 					 state.y * state.pitch +
 					 state.x * state.bpp / 8);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_display.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_display.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,9 +9,11 @@ struct nouveau_framebuffer {
 	struct drm_framebuffer base;
 	struct nouveau_bo *nvbo;
 	struct nouveau_vma vma;
-	u32 r_dma;
+	u32 r_handle;
 	u32 r_format;
 	u32 r_pitch;
+	struct nvif_object h_base[4];
+	struct nvif_object h_core;
 };
 
 static inline struct nouveau_framebuffer *
@@ -36,8 +38,10 @@ struct nouveau_display {
 	int  (*init)(struct drm_device *);
 	void (*fini)(struct drm_device *);
 
-	struct nouveau_object *core;
-	struct nouveau_eventh **vblank;
+	int  (*fb_ctor)(struct drm_framebuffer *);
+	void (*fb_dtor)(struct drm_framebuffer *);
+
+	struct nvif_object disp;
 
 	struct drm_property *dithering_mode;
 	struct drm_property *dithering_depth;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,8 +24,6 @@
  *
  */
 
-#include <core/client.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 
@@ -54,9 +52,9 @@ READ_GET(struct nouveau_channel *chan, u
 {
 	uint64_t val;
 
-	val = nv_ro32(chan->object, chan->user_get);
+	val = nvif_rd32(chan, chan->user_get);
         if (chan->user_get_hi)
-                val |= (uint64_t)nv_ro32(chan->object, chan->user_get_hi) << 32;
+                val |= (uint64_t)nvif_rd32(chan, chan->user_get_hi) << 32;
 
 	/* reset counter as long as GET is still advancing, this is
 	 * to avoid misdetecting a GPU lockup if the GPU happens to
@@ -84,12 +82,13 @@ void
 nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
 	      int delta, int length)
 {
+	struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
 	struct nouveau_bo *pb = chan->push.buffer;
 	struct nouveau_vma *vma;
 	int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
 	u64 offset;
 
-	vma = nouveau_bo_vma_find(bo, nv_client(chan->cli)->vm);
+	vma = nouveau_bo_vma_find(bo, cli->vm);
 	BUG_ON(!vma);
 	offset = vma->offset + delta;
 
@@ -104,7 +103,7 @@ nv50_dma_push(struct nouveau_channel *ch
 	/* Flush writes. */
 	nouveau_bo_rd32(pb, 0);
 
-	nv_wo32(chan->object, 0x8c, chan->dma.ib_put);
+	nvif_wr32(chan, 0x8c, chan->dma.ib_put);
 	chan->dma.ib_free--;
 }
 
@@ -114,7 +113,7 @@ nv50_dma_push_wait(struct nouveau_channe
 	uint32_t cnt = 0, prev_get = 0;
 
 	while (chan->dma.ib_free < count) {
-		uint32_t get = nv_ro32(chan->object, 0x88);
+		uint32_t get = nvif_rd32(chan, 0x88);
 		if (get != prev_get) {
 			prev_get = get;
 			cnt = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h	2014-09-28 17:29:07.000000000 -0400
@@ -58,31 +58,14 @@ enum {
 	FermiSw		= 5, /* DO NOT CHANGE (well.. 6/7 will work...) */
 };
 
-/* Object handles. */
+/* Object handles - for stuff that's doesn't use handle == oclass. */
 enum {
-	NvM2MF		= 0x80000001,
 	NvDmaFB		= 0x80000002,
 	NvDmaTT		= 0x80000003,
 	NvNotify0       = 0x80000006,
-	Nv2D		= 0x80000007,
-	NvCtxSurf2D	= 0x80000008,
-	NvRop		= 0x80000009,
-	NvImagePatt	= 0x8000000a,
-	NvClipRect	= 0x8000000b,
-	NvGdiRect	= 0x8000000c,
-	NvImageBlit	= 0x8000000d,
-	NvSw		= 0x8000000e,
 	NvSema		= 0x8000000f,
 	NvEvoSema0	= 0x80000010,
 	NvEvoSema1	= 0x80000011,
-	NvNotify1       = 0x80000012,
-
-	/* G80+ display objects */
-	NvEvoVRAM	= 0x01000000,
-	NvEvoFB16	= 0x01000001,
-	NvEvoFB32	= 0x01000002,
-	NvEvoVRAM_LP	= 0x01000003,
-	NvEvoSync	= 0xcafe0000
 };
 
 #define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
@@ -157,7 +140,7 @@ BEGIN_IMC0(struct nouveau_channel *chan,
 #define WRITE_PUT(val) do {                                                    \
 	mb();                                                   \
 	nouveau_bo_rd32(chan->push.buffer, 0);                                 \
-	nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset);  \
+	nvif_wr32(chan, chan->user_put, ((val) << 2) + chan->push.vma.offset); \
 } while (0)
 
 static inline void
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,11 +30,6 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 
-#include <core/class.h>
-
-#include <subdev/gpio.h>
-#include <subdev/i2c.h>
-
 static void
 nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
 		     u8 *dpcd)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,21 +27,14 @@
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include <linux/vga_switcheroo.h>
+
 #include "drmP.h"
 #include "drm_crtc_helper.h"
+
 #include <core/device.h>
-#include <core/client.h>
 #include <core/gpuobj.h>
-#include <core/class.h>
 #include <core/option.h>
 
-#include <engine/device.h>
-#include <engine/disp.h>
-#include <engine/fifo.h>
-#include <engine/software.h>
-
-#include <subdev/vm.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_ttm.h"
@@ -57,6 +50,7 @@
 #include "nouveau_fbcon.h"
 #include "nouveau_fence.h"
 #include "nouveau_debugfs.h"
+#include "nouveau_usif.h"
 
 MODULE_PARM_DESC(config, "option string to pass to driver core");
 static char *nouveau_config;
@@ -109,40 +103,37 @@ static int
 nouveau_cli_create(u64 name, const char *sname,
 		   int size, void **pcli)
 {
-	struct nouveau_cli *cli;
-	int ret;
-
-	*pcli = NULL;
-	ret = nouveau_client_create_(sname, name, nouveau_config,
-				     nouveau_debug, size, pcli);
-	cli = *pcli;
-	if (ret) {
-		if (cli)
-			nouveau_client_destroy(&cli->base);
-		*pcli = NULL;
+	struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL);
+	if (cli) {
+		int ret = nvif_client_init(NULL, NULL, sname, name,
+					   nouveau_config, nouveau_debug,
+					  &cli->base);
+		if (ret == 0) {
+			mutex_init(&cli->mutex);
+			usif_client_init(cli);
+		}
 		return ret;
 	}
-
-	mutex_init(&cli->mutex);
-	return 0;
+	return -ENOMEM;
 }
 
 static void
 nouveau_cli_destroy(struct nouveau_cli *cli)
 {
-	struct nouveau_object *client = nv_object(cli);
-	nouveau_vm_ref(NULL, &cli->base.vm, NULL);
-	nouveau_client_fini(&cli->base, false);
-	atomic_set(&client->refcount, 1);
-	nouveau_object_ref(NULL, &client);
+	nouveau_vm_ref(NULL, &nvkm_client(&cli->base)->vm, NULL);
+	nvif_client_fini(&cli->base);
+	usif_client_fini(cli);
 }
 
 static void
 nouveau_accel_fini(struct nouveau_drm *drm)
 {
-	nouveau_gpuobj_ref(NULL, &drm->notify);
 	nouveau_channel_del(&drm->channel);
+	nvif_object_fini(&drm->ntfy);
+	nouveau_gpuobj_ref(NULL, &drm->notify);
+	nvif_object_fini(&drm->nvsw);
 	nouveau_channel_del(&drm->cechan);
+	nvif_object_fini(&drm->ttm.copy);
 	if (drm->fence)
 		nouveau_fence(drm)->dtor(drm);
 }
@@ -150,46 +141,71 @@ nouveau_accel_fini(struct nouveau_drm *d
 static void
 nouveau_accel_init(struct nouveau_drm *drm)
 {
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_object *object;
+	struct nvif_device *device = &drm->device;
 	u32 arg0, arg1;
-	int ret;
+	u32 sclass[16];
+	int ret, i;
 
-	if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/)
+	if (nouveau_noaccel)
 		return;
 
 	/* initialise synchronisation routines */
-	if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-	else if (device->card_type < NV_11 ||
-		 device->chipset   <  0x17) ret = nv10_fence_create(drm);
-	else if (device->card_type < NV_50) ret = nv17_fence_create(drm);
-	else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
-	else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
-	else                                ret = nvc0_fence_create(drm);
+	/*XXX: this is crap, but the fence/channel stuff is a little
+	 *     backwards in some places.  this will be fixed.
+	 */
+	ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass));
+	if (ret < 0)
+		return;
+
+	for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) {
+		switch (sclass[i]) {
+		case NV03_CHANNEL_DMA:
+			ret = nv04_fence_create(drm);
+			break;
+		case NV10_CHANNEL_DMA:
+			ret = nv10_fence_create(drm);
+			break;
+		case NV17_CHANNEL_DMA:
+		case NV40_CHANNEL_DMA:
+			ret = nv17_fence_create(drm);
+			break;
+		case NV50_CHANNEL_GPFIFO:
+			ret = nv50_fence_create(drm);
+			break;
+		case G82_CHANNEL_GPFIFO:
+			ret = nv84_fence_create(drm);
+			break;
+		case FERMI_CHANNEL_GPFIFO:
+		case KEPLER_CHANNEL_GPFIFO_A:
+			ret = nvc0_fence_create(drm);
+			break;
+		default:
+			break;
+		}
+	}
+
 	if (ret) {
 		NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret);
 		nouveau_accel_fini(drm);
 		return;
 	}
 
-	if (device->card_type >= NV_E0) {
-		ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE,
-					  NVDRM_CHAN + 1,
-					  NVE0_CHANNEL_IND_ENGINE_CE0 |
-					  NVE0_CHANNEL_IND_ENGINE_CE1, 0,
-					  &drm->cechan);
+	if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
+		ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+					  KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
+					  KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
+					  0, &drm->cechan);
 		if (ret)
 			NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
-		arg0 = NVE0_CHANNEL_IND_ENGINE_GR;
+		arg0 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
 		arg1 = 1;
 	} else
-	if (device->chipset >= 0xa3 &&
-	    device->chipset != 0xaa &&
-	    device->chipset != 0xac) {
-		ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE,
-					  NVDRM_CHAN + 1, NvDmaFB, NvDmaTT,
-					  &drm->cechan);
+	if (device->info.chipset >= 0xa3 &&
+	    device->info.chipset != 0xaa &&
+	    device->info.chipset != 0xac) {
+		ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+					  NvDmaFB, NvDmaTT, &drm->cechan);
 		if (ret)
 			NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
@@ -200,30 +216,30 @@ nouveau_accel_init(struct nouveau_drm *d
 		arg1 = NvDmaTT;
 	}
 
-	ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN,
-				  arg0, arg1, &drm->channel);
+	ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1,
+				 &drm->channel);
 	if (ret) {
 		NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
 		nouveau_accel_fini(drm);
 		return;
 	}
 
-	ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW,
-				 nouveau_abi16_swclass(drm), NULL, 0, &object);
+	ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW,
+			       nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw);
 	if (ret == 0) {
-		struct nouveau_software_chan *swch = (void *)object->parent;
+		struct nouveau_software_chan *swch;
 		ret = RING_SPACE(drm->channel, 2);
 		if (ret == 0) {
-			if (device->card_type < NV_C0) {
+			if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
 				BEGIN_NV04(drm->channel, NvSubSw, 0, 1);
 				OUT_RING  (drm->channel, NVDRM_NVSW);
 			} else
-			if (device->card_type < NV_E0) {
+			if (device->info.family < NV_DEVICE_INFO_V0_KEPLER) {
 				BEGIN_NVC0(drm->channel, FermiSw, 0, 1);
 				OUT_RING  (drm->channel, 0x001f0000);
 			}
 		}
-		swch = (void *)object->parent;
+		swch = (void *)nvkm_object(&drm->nvsw)->parent;
 		swch->flip = nouveau_flip_complete;
 		swch->flip_data = drm->channel;
 	}
@@ -234,24 +250,24 @@ nouveau_accel_init(struct nouveau_drm *d
 		return;
 	}
 
-	if (device->card_type < NV_C0) {
-		ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0,
-					&drm->notify);
+	if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
+		ret = nouveau_gpuobj_new(nvkm_object(&drm->device), NULL, 32,
+					 0, 0, &drm->notify);
 		if (ret) {
 			NV_ERROR(drm, "failed to allocate notifier, %d\n", ret);
 			nouveau_accel_fini(drm);
 			return;
 		}
 
-		ret = nouveau_object_new(nv_object(drm),
-					 drm->channel->handle, NvNotify0,
-					 0x003d, &(struct nv_dma_class) {
-						.flags = NV_DMA_TARGET_VRAM |
-							 NV_DMA_ACCESS_RDWR,
+		ret = nvif_object_init(drm->channel->object, NULL, NvNotify0,
+				       NV_DMA_IN_MEMORY,
+				       &(struct nv_dma_v0) {
+						.target = NV_DMA_V0_TARGET_VRAM,
+						.access = NV_DMA_V0_ACCESS_RDWR,
 						.start = drm->notify->addr,
 						.limit = drm->notify->addr + 31
-						}, sizeof(struct nv_dma_class),
-					 &object);
+				       }, sizeof(struct nv_dma_v0),
+				       &drm->ntfy);
 		if (ret) {
 			nouveau_accel_fini(drm);
 			return;
@@ -294,7 +310,8 @@ static int nouveau_drm_probe(struct pci_
 #ifdef CONFIG_X86
 	boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
 #endif
-	remove_conflicting_framebuffers(aper, "nouveaufb", boot);
+	if (nouveau_modeset != 2)
+		remove_conflicting_framebuffers(aper, "nouveaufb", boot);
 	kfree(aper);
 
 	ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
@@ -348,7 +365,6 @@ static int
 nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 {
 	struct pci_dev *pdev = dev->pdev;
-	struct nouveau_device *device;
 	struct nouveau_drm *drm;
 	int ret;
 
@@ -359,7 +375,8 @@ nouveau_drm_load(struct drm_device *dev,
 
 	dev->dev_private = drm;
 	drm->dev = dev;
-	nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");
+	nvkm_client(&drm->client.base)->debug =
+		nouveau_dbgopt(nouveau_debug, "DRM");
 
 	INIT_LIST_HEAD(&drm->clients);
 	spin_lock_init(&drm->tile.lock);
@@ -370,33 +387,34 @@ nouveau_drm_load(struct drm_device *dev,
 	 * (possibly) execute vbios init tables (see nouveau_agp.h)
 	 */
 	if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
+		const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY |
+				    NV_DEVICE_V0_DISABLE_MMIO;
 		/* dummy device object, doesn't init anything, but allows
 		 * agp code access to registers
 		 */
-		ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT,
-					 NVDRM_DEVICE, 0x0080,
-					 &(struct nv_device_class) {
+		ret = nvif_device_init(&drm->client.base.base, NULL,
+				       NVDRM_DEVICE, NV_DEVICE,
+				       &(struct nv_device_v0) {
 						.device = ~0,
-						.disable =
-						 ~(NV_DEVICE_DISABLE_MMIO |
-						   NV_DEVICE_DISABLE_IDENTIFY),
+						.disable = ~enables,
 						.debug0 = ~0,
-					 }, sizeof(struct nv_device_class),
-					 &drm->device);
+				       }, sizeof(struct nv_device_v0),
+				       &drm->device);
 		if (ret)
 			goto fail_device;
 
 		nouveau_agp_reset(drm);
-		nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE);
+		nvif_device_fini(&drm->device);
 	}
 
-	ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE,
-				 0x0080, &(struct nv_device_class) {
+	ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,
+			       NV_DEVICE,
+			       &(struct nv_device_v0) {
 					.device = ~0,
 					.disable = 0,
 					.debug0 = 0,
-				 }, sizeof(struct nv_device_class),
-				 &drm->device);
+			       }, sizeof(struct nv_device_v0),
+			       &drm->device);
 	if (ret)
 		goto fail_device;
 
@@ -406,18 +424,19 @@ nouveau_drm_load(struct drm_device *dev,
 	 * nosnoop capability.  hopefully won't cause issues until a
 	 * better fix is found - assuming there is one...
 	 */
-	device = nv_device(drm->device);
-	if (nv_device(drm->device)->chipset == 0xc1)
-		nv_mask(device, 0x00088080, 0x00000800, 0x00000000);
+	if (drm->device.info.chipset == 0xc1)
+		nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000);
 
 	nouveau_vga_init(drm);
 	nouveau_agp_init(drm);
 
-	if (device->card_type >= NV_50) {
-		ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
-				     0x1000, &drm->client.base.vm);
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
+				     0x1000, &drm->client.vm);
 		if (ret)
 			goto fail_device;
+
+		nvkm_client(&drm->client.base)->vm = drm->client.vm;
 	}
 
 	ret = nouveau_ttm_init(drm);
@@ -463,6 +482,7 @@ fail_ttm:
 	nouveau_agp_fini(drm);
 	nouveau_vga_fini(drm);
 fail_device:
+	nvif_device_fini(&drm->device);
 	nouveau_cli_destroy(&drm->client);
 	return ret;
 }
@@ -488,26 +508,37 @@ nouveau_drm_unload(struct drm_device *de
 	nouveau_agp_fini(drm);
 	nouveau_vga_fini(drm);
 
+	nvif_device_fini(&drm->device);
 	if (drm->hdmi_device)
 		pci_dev_put(drm->hdmi_device);
 	nouveau_cli_destroy(&drm->client);
 	return 0;
 }
 
-static void
-nouveau_drm_remove(struct pci_dev *pdev)
+void
+nouveau_drm_device_remove(struct drm_device *dev)
 {
-	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_client *client;
 	struct nouveau_object *device;
 
 	dev->irq_enabled = false;
-	device = drm->client.base.device;
+	client = nvkm_client(&drm->client.base);
+	device = client->device;
 	drm_put_dev(dev);
 
 	nouveau_object_ref(NULL, &device);
 	nouveau_object_debug();
 }
+EXPORT_SYMBOL(nouveau_drm_device_remove);
+
+static void
+nouveau_drm_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	nouveau_drm_device_remove(dev);
+}
 
 static int
 nouveau_do_suspend(struct drm_device *dev, bool runtime)
@@ -548,13 +579,13 @@ nouveau_do_suspend(struct drm_device *de
 	}
 
 	list_for_each_entry(cli, &drm->clients, head) {
-		ret = nouveau_client_fini(&cli->base, true);
+		ret = nvif_client_suspend(&cli->base);
 		if (ret)
 			goto fail_client;
 	}
 
 	NV_INFO(drm, "suspending kernel object tree...\n");
-	ret = nouveau_client_fini(&drm->client.base, true);
+	ret = nvif_client_suspend(&drm->client.base);
 	if (ret)
 		goto fail_client;
 
@@ -563,7 +594,7 @@ nouveau_do_suspend(struct drm_device *de
 
 fail_client:
 	list_for_each_entry_continue_reverse(cli, &drm->clients, head) {
-		nouveau_client_init(&cli->base);
+		nvif_client_resume(&cli->base);
 	}
 
 	if (drm->fence && nouveau_fence(drm)->resume)
@@ -596,6 +627,7 @@ int nouveau_pmops_suspend(struct device
 
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
+	pci_ignore_hotplug(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
 	return 0;
 }
@@ -611,7 +643,7 @@ nouveau_do_resume(struct drm_device *dev
 	nouveau_agp_reset(drm);
 
 	NV_INFO(drm, "resuming kernel object tree...\n");
-	nouveau_client_init(&drm->client.base);
+	nvif_client_resume(&drm->client.base);
 	nouveau_agp_init(drm);
 
 	NV_INFO(drm, "resuming client object trees...\n");
@@ -619,7 +651,7 @@ nouveau_do_resume(struct drm_device *dev
 		nouveau_fence(drm)->resume(drm);
 
 	list_for_each_entry(cli, &drm->clients, head) {
-		nouveau_client_init(&cli->base);
+		nvif_client_resume(&cli->base);
 	}
 
 	nouveau_run_vbios_init(dev);
@@ -715,13 +747,17 @@ nouveau_drm_open(struct drm_device *dev,
 	if (ret)
 		goto out_suspend;
 
-	if (nv_device(drm->device)->card_type >= NV_50) {
-		ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
-				     0x1000, &cli->base.vm);
+	cli->base.super = false;
+
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
+				     0x1000, &cli->vm);
 		if (ret) {
 			nouveau_cli_destroy(cli);
 			goto out_suspend;
 		}
+
+		nvkm_client(&cli->base)->vm = cli->vm;
 	}
 
 	fpriv->driver_priv = cli;
@@ -779,24 +815,31 @@ nouveau_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
 };
 
-long nouveau_drm_ioctl(struct file *filp,
-		       unsigned int cmd, unsigned long arg)
+long
+nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct drm_file *file_priv = filp->private_data;
-	struct drm_device *dev;
+	struct drm_file *filp = file->private_data;
+	struct drm_device *dev = filp->minor->dev;
 	long ret;
-	dev = file_priv->minor->dev;
 
 	ret = pm_runtime_get_sync(dev->dev);
 	if (ret < 0 && ret != -EACCES)
 		return ret;
 
-	ret = drm_ioctl(filp, cmd, arg);
+	switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) {
+	case DRM_NOUVEAU_NVIF:
+		ret = usif_ioctl(filp, (void __user *)arg, _IOC_SIZE(cmd));
+		break;
+	default:
+		ret = drm_ioctl(file, cmd, arg);
+		break;
+	}
 
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
 }
+
 static const struct file_operations
 nouveau_driver_fops = {
 	.owner = THIS_MODULE,
@@ -845,6 +888,7 @@ driver = {
 	.gem_prime_export = drm_gem_prime_export,
 	.gem_prime_import = drm_gem_prime_import,
 	.gem_prime_pin = nouveau_gem_prime_pin,
+	.gem_prime_res_obj = nouveau_gem_prime_res_obj,
 	.gem_prime_unpin = nouveau_gem_prime_unpin,
 	.gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table,
 	.gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table,
@@ -920,7 +964,7 @@ static int nouveau_pmops_runtime_resume(
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	struct nouveau_device *device = nouveau_dev(drm_dev);
+	struct nvif_device *device = &nouveau_drm(drm_dev)->device;
 	int ret;
 
 	if (nouveau_runtime_pm == 0)
@@ -936,7 +980,7 @@ static int nouveau_pmops_runtime_resume(
 	ret = nouveau_do_resume(drm_dev);
 	drm_kms_helper_poll_enable(drm_dev);
 	/* do magic */
-	nv_mask(device, 0x88488, (1 << 25), (1 << 25));
+	nvif_mask(device, 0x88488, (1 << 25), (1 << 25));
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
 	nv_debug_level(NORMAL);
@@ -1004,24 +1048,41 @@ nouveau_drm_pci_driver = {
 	.driver.pm = &nouveau_pm_ops,
 };
 
-int nouveau_drm_platform_probe(struct platform_device *pdev)
+struct drm_device *
+nouveau_platform_device_create_(struct platform_device *pdev, int size,
+				void **pobject)
 {
-	struct nouveau_device *device;
-	int ret;
+	struct drm_device *drm;
+	int err;
 
-	ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
+	err = nouveau_device_create_(pdev, NOUVEAU_BUS_PLATFORM,
 				    nouveau_platform_name(pdev),
 				    dev_name(&pdev->dev), nouveau_config,
-				    nouveau_debug, &device);
+				    nouveau_debug, size, pobject);
+	if (err)
+		return ERR_PTR(err);
 
-	ret = drm_platform_init(&driver, pdev);
-	if (ret) {
-		nouveau_object_ref(NULL, (struct nouveau_object **)&device);
-		return ret;
+	drm = drm_dev_alloc(&driver, &pdev->dev);
+	if (!drm) {
+		err = -ENOMEM;
+		goto err_free;
 	}
 
-	return ret;
+	err = drm_dev_set_unique(drm, "%s", dev_name(&pdev->dev));
+	if (err < 0)
+		goto err_free;
+
+	drm->platformdev = pdev;
+	platform_set_drvdata(pdev, drm);
+
+	return drm;
+
+err_free:
+	nouveau_object_ref(NULL, (struct nouveau_object **)pobject);
+
+	return ERR_PTR(err);
 }
+EXPORT_SYMBOL(nouveau_platform_device_create_);
 
 static int __init
 nouveau_drm_init(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,8 +9,8 @@
 #define DRIVER_DATE		"20120801"
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		1
-#define DRIVER_PATCHLEVEL	1
+#define DRIVER_MINOR		2
+#define DRIVER_PATCHLEVEL	0
 
 /*
  * 1.1.1:
@@ -21,15 +21,17 @@
  *        to control registers on the MPs to enable performance counters,
  *        and to control the warp error enable mask (OpenGL requires out of
  *        bounds access to local memory to be silently ignored / return 0).
+ * 1.1.2:
+ *      - fixes multiple bugs in flip completion events and timestamping
+ * 1.2.0:
+ * 	- object api exposed to userspace
+ * 	- fermi,kepler,maxwell zbc
  */
 
-#include <core/client.h>
-#include <core/event.h>
-
-#include <subdev/vm.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
 
 #include <drmP.h>
-#include <drm/nouveau_drm.h>
 
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
@@ -38,7 +40,10 @@
 #include <drm/ttm/ttm_module.h>
 #include <drm/ttm/ttm_page_alloc.h>
 
+#include "uapi/drm/nouveau_drm.h"
+
 struct nouveau_channel;
+struct platform_device;
 
 #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
@@ -50,6 +55,17 @@ struct nouveau_drm_tile {
 	bool used;
 };
 
+enum nouveau_drm_object_route {
+	NVDRM_OBJECT_NVIF = 0,
+	NVDRM_OBJECT_USIF,
+	NVDRM_OBJECT_ABI16,
+};
+
+enum nouveau_drm_notify_route {
+	NVDRM_NOTIFY_NVIF = 0,
+	NVDRM_NOTIFY_USIF
+};
+
 enum nouveau_drm_handle {
 	NVDRM_CLIENT  = 0xffffffff,
 	NVDRM_DEVICE  = 0xdddddddd,
@@ -61,10 +77,13 @@ enum nouveau_drm_handle {
 };
 
 struct nouveau_cli {
-	struct nouveau_client base;
+	struct nvif_client base;
+	struct nouveau_vm *vm; /*XXX*/
 	struct list_head head;
 	struct mutex mutex;
 	void *abi16;
+	struct list_head objects;
+	struct list_head notifys;
 };
 
 static inline struct nouveau_cli *
@@ -73,13 +92,16 @@ nouveau_cli(struct drm_file *fpriv)
 	return fpriv ? fpriv->driver_priv : NULL;
 }
 
+#include <nvif/object.h>
+#include <nvif/device.h>
+
 extern int nouveau_runtime_pm;
 
 struct nouveau_drm {
 	struct nouveau_cli client;
 	struct drm_device *dev;
 
-	struct nouveau_object *device;
+	struct nvif_device device;
 	struct list_head clients;
 
 	struct {
@@ -102,6 +124,7 @@ struct nouveau_drm {
 			    struct ttm_buffer_object *,
 			    struct ttm_mem_reg *, struct ttm_mem_reg *);
 		struct nouveau_channel *chan;
+		struct nvif_object copy;
 		int mtrr;
 	} ttm;
 
@@ -119,6 +142,8 @@ struct nouveau_drm {
 	struct nouveau_channel *channel;
 	struct nouveau_gpuobj *notify;
 	struct nouveau_fbdev *fbcon;
+	struct nvif_object nvsw;
+	struct nvif_object ntfy;
 
 	/* nv10-nv40 tiling regions */
 	struct {
@@ -148,20 +173,25 @@ nouveau_drm(struct drm_device *dev)
 	return dev->dev_private;
 }
 
-static inline struct nouveau_device *
-nouveau_dev(struct drm_device *dev)
-{
-	return nv_device(nouveau_drm(dev)->device);
-}
-
 int nouveau_pmops_suspend(struct device *);
 int nouveau_pmops_resume(struct device *);
 
-#define NV_FATAL(cli, fmt, args...) nv_fatal((cli), fmt, ##args)
-#define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
-#define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)
-#define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args)
-#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)
+#define nouveau_platform_device_create(p, u)                                   \
+	nouveau_platform_device_create_(p, sizeof(**u), (void **)u)
+struct drm_device *
+nouveau_platform_device_create_(struct platform_device *pdev,
+				int size, void **pobject);
+void nouveau_drm_device_remove(struct drm_device *dev);
+
+#define NV_PRINTK(l,c,f,a...) do {                                             \
+	struct nouveau_cli *_cli = (c);                                        \
+	nv_##l(_cli->base.base.priv, f, ##a);                                  \
+} while(0)
+#define NV_FATAL(drm,f,a...) NV_PRINTK(fatal, &(drm)->client, f, ##a)
+#define NV_ERROR(drm,f,a...) NV_PRINTK(error, &(drm)->client, f, ##a)
+#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
+#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
+#define NV_DEBUG(drm,f,a...) NV_PRINTK(debug, &(drm)->client, f, ##a)
 
 extern int nouveau_modeset;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,11 +51,6 @@
 
 #include "nouveau_crtc.h"
 
-#include <core/client.h>
-#include <core/device.h>
-
-#include <subdev/fb.h>
-
 MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
 static int nouveau_nofbaccel = 0;
 module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
@@ -65,7 +60,7 @@ nouveau_fbcon_fillrect(struct fb_info *i
 {
 	struct nouveau_fbdev *fbcon = info->par;
 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int ret;
 
 	if (info->state != FBINFO_STATE_RUNNING)
@@ -74,10 +69,10 @@ nouveau_fbcon_fillrect(struct fb_info *i
 	ret = -ENODEV;
 	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
 	    mutex_trylock(&drm->client.mutex)) {
-		if (device->card_type < NV_50)
+		if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
 			ret = nv04_fbcon_fillrect(info, rect);
 		else
-		if (device->card_type < NV_C0)
+		if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
 			ret = nv50_fbcon_fillrect(info, rect);
 		else
 			ret = nvc0_fbcon_fillrect(info, rect);
@@ -97,7 +92,7 @@ nouveau_fbcon_copyarea(struct fb_info *i
 {
 	struct nouveau_fbdev *fbcon = info->par;
 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int ret;
 
 	if (info->state != FBINFO_STATE_RUNNING)
@@ -106,10 +101,10 @@ nouveau_fbcon_copyarea(struct fb_info *i
 	ret = -ENODEV;
 	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
 	    mutex_trylock(&drm->client.mutex)) {
-		if (device->card_type < NV_50)
+		if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
 			ret = nv04_fbcon_copyarea(info, image);
 		else
-		if (device->card_type < NV_C0)
+		if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
 			ret = nv50_fbcon_copyarea(info, image);
 		else
 			ret = nvc0_fbcon_copyarea(info, image);
@@ -129,7 +124,7 @@ nouveau_fbcon_imageblit(struct fb_info *
 {
 	struct nouveau_fbdev *fbcon = info->par;
 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	int ret;
 
 	if (info->state != FBINFO_STATE_RUNNING)
@@ -138,10 +133,10 @@ nouveau_fbcon_imageblit(struct fb_info *
 	ret = -ENODEV;
 	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
 	    mutex_trylock(&drm->client.mutex)) {
-		if (device->card_type < NV_50)
+		if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
 			ret = nv04_fbcon_imageblit(info, image);
 		else
-		if (device->card_type < NV_C0)
+		if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
 			ret = nv50_fbcon_imageblit(info, image);
 		else
 			ret = nvc0_fbcon_imageblit(info, image);
@@ -212,6 +207,65 @@ static struct fb_ops nouveau_fbcon_sw_op
 	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
+void
+nouveau_fbcon_accel_save_disable(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	if (drm->fbcon) {
+		drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
+		drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+}
+
+void
+nouveau_fbcon_accel_restore(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	if (drm->fbcon) {
+		drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
+	}
+}
+
+static void
+nouveau_fbcon_accel_fini(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_fbdev *fbcon = drm->fbcon;
+	if (fbcon && drm->channel) {
+		console_lock();
+		fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+		console_unlock();
+		nouveau_channel_idle(drm->channel);
+		nvif_object_fini(&fbcon->twod);
+		nvif_object_fini(&fbcon->blit);
+		nvif_object_fini(&fbcon->gdi);
+		nvif_object_fini(&fbcon->patt);
+		nvif_object_fini(&fbcon->rop);
+		nvif_object_fini(&fbcon->clip);
+		nvif_object_fini(&fbcon->surf2d);
+	}
+}
+
+static void
+nouveau_fbcon_accel_init(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_fbdev *fbcon = drm->fbcon;
+	struct fb_info *info = fbcon->helper.fbdev;
+	int ret;
+
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA)
+		ret = nv04_fbcon_accel_init(info);
+	else
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
+		ret = nv50_fbcon_accel_init(info);
+	else
+		ret = nvc0_fbcon_accel_init(info);
+
+	if (ret == 0)
+		info->fbops = &nouveau_fbcon_ops;
+}
+
 static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 				    u16 blue, int regno)
 {
@@ -257,7 +311,7 @@ nouveau_fbcon_create(struct drm_fb_helpe
 	struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper;
 	struct drm_device *dev = fbcon->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
 	struct nouveau_framebuffer *nouveau_fb;
@@ -299,8 +353,8 @@ nouveau_fbcon_create(struct drm_fb_helpe
 	}
 
 	chan = nouveau_nofbaccel ? NULL : drm->channel;
-	if (chan && device->card_type >= NV_50) {
-		ret = nouveau_bo_vma_add(nvbo, nv_client(chan->cli)->vm,
+	if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+		ret = nouveau_bo_vma_add(nvbo, drm->client.vm,
 					&fbcon->nouveau_fb.vma);
 		if (ret) {
 			NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
@@ -357,20 +411,8 @@ nouveau_fbcon_create(struct drm_fb_helpe
 
 	mutex_unlock(&dev->struct_mutex);
 
-	if (chan) {
-		ret = -ENODEV;
-		if (device->card_type < NV_50)
-			ret = nv04_fbcon_accel_init(info);
-		else
-		if (device->card_type < NV_C0)
-			ret = nv50_fbcon_accel_init(info);
-		else
-			ret = nvc0_fbcon_accel_init(info);
-
-		if (ret == 0)
-			info->fbops = &nouveau_fbcon_ops;
-	}
-
+	if (chan)
+		nouveau_fbcon_accel_init(dev);
 	nouveau_fbcon_zfill(dev, fbcon);
 
 	/* To allow resizeing without swapping buffers */
@@ -438,7 +480,7 @@ void nouveau_fbcon_gpu_lockup(struct fb_
 	info->flags |= FBINFO_HWACCEL_DISABLED;
 }
 
-static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
+static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
 	.gamma_set = nouveau_fbcon_gamma_set,
 	.gamma_get = nouveau_fbcon_gamma_get,
 	.fb_probe = nouveau_fbcon_create,
@@ -449,7 +491,6 @@ int
 nouveau_fbcon_init(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
 	struct nouveau_fbdev *fbcon;
 	int preferred_bpp;
 	int ret;
@@ -464,7 +505,8 @@ nouveau_fbcon_init(struct drm_device *de
 
 	fbcon->dev = dev;
 	drm->fbcon = fbcon;
-	fbcon->helper.funcs = &nouveau_fbcon_helper_funcs;
+
+	drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
 
 	ret = drm_fb_helper_init(dev, &fbcon->helper,
 				 dev->mode_config.num_crtc, 4);
@@ -475,10 +517,10 @@ nouveau_fbcon_init(struct drm_device *de
 
 	drm_fb_helper_single_add_all_connectors(&fbcon->helper);
 
-	if (pfb->ram->size <= 32 * 1024 * 1024)
+	if (drm->device.info.ram_size <= 32 * 1024 * 1024)
 		preferred_bpp = 8;
 	else
-	if (pfb->ram->size <= 64 * 1024 * 1024)
+	if (drm->device.info.ram_size <= 64 * 1024 * 1024)
 		preferred_bpp = 16;
 	else
 		preferred_bpp = 32;
@@ -498,43 +540,25 @@ nouveau_fbcon_fini(struct drm_device *de
 	if (!drm->fbcon)
 		return;
 
+	nouveau_fbcon_accel_fini(dev);
 	nouveau_fbcon_destroy(dev, drm->fbcon);
 	kfree(drm->fbcon);
 	drm->fbcon = NULL;
 }
 
 void
-nouveau_fbcon_save_disable_accel(struct drm_device *dev)
-{
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	if (drm->fbcon) {
-		drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
-		drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
-	}
-}
-
-void
-nouveau_fbcon_restore_accel(struct drm_device *dev)
-{
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	if (drm->fbcon) {
-		drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
-	}
-}
-
-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 == 1)
-			nouveau_fbcon_save_disable_accel(dev);
-		fb_set_suspend(drm->fbcon->helper.fbdev, state);
 		if (state == 0) {
-			nouveau_fbcon_restore_accel(dev);
+			nouveau_fbcon_accel_restore(dev);
 			nouveau_fbcon_zfill(dev, drm->fbcon);
 		}
+		fb_set_suspend(drm->fbcon->helper.fbdev, state);
+		if (state == 1)
+			nouveau_fbcon_accel_save_disable(dev);
 		console_unlock();
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,13 @@ struct nouveau_fbdev {
 	struct list_head fbdev_list;
 	struct drm_device *dev;
 	unsigned int saved_flags;
+	struct nvif_object surf2d;
+	struct nvif_object clip;
+	struct nvif_object rop;
+	struct nvif_object patt;
+	struct nvif_object gdi;
+	struct nvif_object blit;
+	struct nvif_object twod;
 };
 
 void nouveau_fbcon_restore(void);
@@ -61,8 +68,8 @@ void nouveau_fbcon_gpu_lockup(struct fb_
 int nouveau_fbcon_init(struct drm_device *dev);
 void nouveau_fbcon_fini(struct drm_device *dev);
 void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
-void nouveau_fbcon_save_disable_accel(struct drm_device *dev);
-void nouveau_fbcon_restore_accel(struct drm_device *dev);
+void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
+void nouveau_fbcon_accel_restore(struct drm_device *dev);
 
 void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
 #endif /* __NV50_FBCON_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,12 +29,13 @@
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
 
+#include <nvif/notify.h>
+#include <nvif/event.h>
+
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
-#include <engine/fifo.h>
-
 struct fence_work {
 	struct work_struct base;
 	struct list_head head;
@@ -165,12 +166,18 @@ nouveau_fence_done(struct nouveau_fence
 	return !fence->channel;
 }
 
+struct nouveau_fence_wait {
+	struct nouveau_fence_priv *priv;
+	struct nvif_notify notify;
+};
+
 static int
-nouveau_fence_wait_uevent_handler(void *data, u32 type, int index)
+nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
 {
-	struct nouveau_fence_priv *priv = data;
-	wake_up_all(&priv->waiting);
-	return NVKM_EVENT_KEEP;
+	struct nouveau_fence_wait *wait =
+		container_of(notify, typeof(*wait), notify);
+	wake_up_all(&wait->priv->waiting);
+	return NVIF_NOTIFY_KEEP;
 }
 
 static int
@@ -178,18 +185,22 @@ nouveau_fence_wait_uevent(struct nouveau
 
 {
 	struct nouveau_channel *chan = fence->channel;
-	struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);
 	struct nouveau_fence_priv *priv = chan->drm->fence;
-	struct nouveau_eventh *handler;
+	struct nouveau_fence_wait wait = { .priv = priv };
 	int ret = 0;
 
-	ret = nouveau_event_new(pfifo->uevent, 1, 0,
-				nouveau_fence_wait_uevent_handler,
-				priv, &handler);
+	ret = nvif_notify_init(chan->object, NULL,
+			       nouveau_fence_wait_uevent_handler, false,
+			       G82_CHANNEL_DMA_V0_NTFY_UEVENT,
+			       &(struct nvif_notify_uevent_req) {
+			       },
+			       sizeof(struct nvif_notify_uevent_req),
+			       sizeof(struct nvif_notify_uevent_rep),
+			       &wait.notify);
 	if (ret)
 		return ret;
 
-	nouveau_event_get(handler);
+	nvif_notify_get(&wait.notify);
 
 	if (fence->timeout) {
 		unsigned long timeout = fence->timeout - jiffies;
@@ -221,7 +232,7 @@ nouveau_fence_wait_uevent(struct nouveau
 		}
 	}
 
-	nouveau_event_ref(NULL, &handler);
+	nvif_notify_fini(&wait.notify);
 	if (unlikely(ret < 0))
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,8 +24,6 @@
  *
  */
 
-#include <subdev/fb.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
@@ -58,14 +56,14 @@ nouveau_gem_object_open(struct drm_gem_o
 	struct nouveau_vma *vma;
 	int ret;
 
-	if (!cli->base.vm)
+	if (!cli->vm)
 		return 0;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
 	if (ret)
 		return ret;
 
-	vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+	vma = nouveau_bo_vma_find(nvbo, cli->vm);
 	if (!vma) {
 		vma = kzalloc(sizeof(*vma), GFP_KERNEL);
 		if (!vma) {
@@ -73,7 +71,7 @@ nouveau_gem_object_open(struct drm_gem_o
 			goto out;
 		}
 
-		ret = nouveau_bo_vma_add(nvbo, cli->base.vm, vma);
+		ret = nouveau_bo_vma_add(nvbo, cli->vm, vma);
 		if (ret) {
 			kfree(vma);
 			goto out;
@@ -129,14 +127,14 @@ nouveau_gem_object_close(struct drm_gem_
 	struct nouveau_vma *vma;
 	int ret;
 
-	if (!cli->base.vm)
+	if (!cli->vm)
 		return;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
 	if (ret)
 		return;
 
-	vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+	vma = nouveau_bo_vma_find(nvbo, cli->vm);
 	if (vma) {
 		if (--vma->refcount == 0)
 			nouveau_gem_object_unmap(nvbo, vma);
@@ -173,7 +171,7 @@ nouveau_gem_new(struct drm_device *dev,
 	 */
 	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
 			      NOUVEAU_GEM_DOMAIN_GART;
-	if (nv_device(drm->device)->card_type >= NV_50)
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 		nvbo->valid_domains &= domain;
 
 	/* Initialize the embedded gem-object. We return a single gem-reference
@@ -202,8 +200,8 @@ nouveau_gem_info(struct drm_file *file_p
 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
 
 	rep->offset = nvbo->bo.offset;
-	if (cli->base.vm) {
-		vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+	if (cli->vm) {
+		vma = nouveau_bo_vma_find(nvbo, cli->vm);
 		if (!vma)
 			return -EINVAL;
 
@@ -223,13 +221,13 @@ nouveau_gem_ioctl_new(struct drm_device
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	struct drm_nouveau_gem_new *req = data;
 	struct nouveau_bo *nvbo = NULL;
 	int ret = 0;
 
 	if (!pfb->memtype_valid(pfb, req->info.tile_flags)) {
-		NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
+		NV_PRINTK(error, cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
 		return -EINVAL;
 	}
 
@@ -350,7 +348,7 @@ validate_init(struct nouveau_channel *ch
 	ww_acquire_init(&op->ticket, &reservation_ww_class);
 retry:
 	if (++trycnt > 100000) {
-		NV_ERROR(cli, "%s failed and gave up.\n", __func__);
+		NV_PRINTK(error, cli, "%s failed and gave up.\n", __func__);
 		return -EINVAL;
 	}
 
@@ -361,7 +359,7 @@ retry:
 
 		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
 		if (!gem) {
-			NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
+			NV_PRINTK(error, cli, "Unknown handle 0x%08x\n", b->handle);
 			ww_acquire_done(&op->ticket);
 			validate_fini(op, NULL);
 			return -ENOENT;
@@ -374,7 +372,7 @@ retry:
 		}
 
 		if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
-			NV_ERROR(cli, "multiple instances of buffer %d on "
+			NV_PRINTK(error, cli, "multiple instances of buffer %d on "
 				      "validation list\n", b->handle);
 			drm_gem_object_unreference_unlocked(gem);
 			ww_acquire_done(&op->ticket);
@@ -396,7 +394,7 @@ retry:
 				ww_acquire_fini(&op->ticket);
 				drm_gem_object_unreference_unlocked(gem);
 				if (ret != -ERESTARTSYS)
-					NV_ERROR(cli, "fail reserve\n");
+					NV_PRINTK(error, cli, "fail reserve\n");
 				return ret;
 			}
 		}
@@ -414,7 +412,7 @@ retry:
 		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
 			list_add_tail(&nvbo->entry, &op->gart_list);
 		else {
-			NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
+			NV_PRINTK(error, cli, "invalid valid domains: 0x%08x\n",
 				 b->valid_domains);
 			list_add_tail(&nvbo->entry, &op->both_list);
 			ww_acquire_done(&op->ticket);
@@ -465,24 +463,24 @@ validate_list(struct nouveau_channel *ch
 					     b->write_domains,
 					     b->valid_domains);
 		if (unlikely(ret)) {
-			NV_ERROR(cli, "fail set_domain\n");
+			NV_PRINTK(error, cli, "fail set_domain\n");
 			return ret;
 		}
 
 		ret = nouveau_bo_validate(nvbo, true, false);
 		if (unlikely(ret)) {
 			if (ret != -ERESTARTSYS)
-				NV_ERROR(cli, "fail ttm_validate\n");
+				NV_PRINTK(error, cli, "fail ttm_validate\n");
 			return ret;
 		}
 
 		ret = validate_sync(chan, nvbo);
 		if (unlikely(ret)) {
-			NV_ERROR(cli, "fail post-validate sync\n");
+			NV_PRINTK(error, cli, "fail post-validate sync\n");
 			return ret;
 		}
 
-		if (nv_device(drm->device)->card_type < NV_50) {
+		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
 			if (nvbo->bo.offset == b->presumed.offset &&
 			    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
 			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
@@ -527,14 +525,14 @@ nouveau_gem_pushbuf_validate(struct nouv
 	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
 	if (unlikely(ret)) {
 		if (ret != -ERESTARTSYS)
-			NV_ERROR(cli, "validate_init\n");
+			NV_PRINTK(error, cli, "validate_init\n");
 		return ret;
 	}
 
 	ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
 		if (ret != -ERESTARTSYS)
-			NV_ERROR(cli, "validate vram_list\n");
+			NV_PRINTK(error, cli, "validate vram_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -543,7 +541,7 @@ nouveau_gem_pushbuf_validate(struct nouv
 	ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
 		if (ret != -ERESTARTSYS)
-			NV_ERROR(cli, "validate gart_list\n");
+			NV_PRINTK(error, cli, "validate gart_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -552,7 +550,7 @@ nouveau_gem_pushbuf_validate(struct nouv
 	ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
 		if (ret != -ERESTARTSYS)
-			NV_ERROR(cli, "validate both_list\n");
+			NV_PRINTK(error, cli, "validate both_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -613,7 +611,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 		uint32_t data;
 
 		if (unlikely(r->bo_index > req->nr_buffers)) {
-			NV_ERROR(cli, "reloc bo index invalid\n");
+			NV_PRINTK(error, cli, "reloc bo index invalid\n");
 			ret = -EINVAL;
 			break;
 		}
@@ -623,7 +621,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 			continue;
 
 		if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
-			NV_ERROR(cli, "reloc container bo index invalid\n");
+			NV_PRINTK(error, cli, "reloc container bo index invalid\n");
 			ret = -EINVAL;
 			break;
 		}
@@ -631,7 +629,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 
 		if (unlikely(r->reloc_bo_offset + 4 >
 			     nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
-			NV_ERROR(cli, "reloc outside of bo\n");
+			NV_PRINTK(error, cli, "reloc outside of bo\n");
 			ret = -EINVAL;
 			break;
 		}
@@ -640,7 +638,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 			ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
 					  &nvbo->kmap);
 			if (ret) {
-				NV_ERROR(cli, "failed kmap for reloc\n");
+				NV_PRINTK(error, cli, "failed kmap for reloc\n");
 				break;
 			}
 			nvbo->validate_mapped = true;
@@ -665,7 +663,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 		ret = ttm_bo_wait(&nvbo->bo, false, false, false);
 		spin_unlock(&nvbo->bo.bdev->fence_lock);
 		if (ret) {
-			NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret);
+			NV_PRINTK(error, cli, "reloc wait_idle failed: %d\n", ret);
 			break;
 		}
 
@@ -696,7 +694,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 		return -ENOMEM;
 
 	list_for_each_entry(temp, &abi16->channels, head) {
-		if (temp->chan->handle == (NVDRM_CHAN | req->channel)) {
+		if (temp->chan->object->handle == (NVDRM_CHAN | req->channel)) {
 			chan = temp->chan;
 			break;
 		}
@@ -711,19 +709,19 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 		goto out_next;
 
 	if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
-		NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n",
+		NV_PRINTK(error, cli, "pushbuf push count exceeds limit: %d max %d\n",
 			 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
 		return nouveau_abi16_put(abi16, -EINVAL);
 	}
 
 	if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
-		NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n",
+		NV_PRINTK(error, cli, "pushbuf bo count exceeds limit: %d max %d\n",
 			 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
 		return nouveau_abi16_put(abi16, -EINVAL);
 	}
 
 	if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
-		NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n",
+		NV_PRINTK(error, cli, "pushbuf reloc count exceeds limit: %d max %d\n",
 			 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
 		return nouveau_abi16_put(abi16, -EINVAL);
 	}
@@ -741,7 +739,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	/* Ensure all push buffers are on validate list */
 	for (i = 0; i < req->nr_push; i++) {
 		if (push[i].bo_index >= req->nr_buffers) {
-			NV_ERROR(cli, "push %d buffer not in list\n", i);
+			NV_PRINTK(error, cli, "push %d buffer not in list\n", i);
 			ret = -EINVAL;
 			goto out_prevalid;
 		}
@@ -752,7 +750,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 					   req->nr_buffers, &op, &do_reloc);
 	if (ret) {
 		if (ret != -ERESTARTSYS)
-			NV_ERROR(cli, "validate: %d\n", ret);
+			NV_PRINTK(error, cli, "validate: %d\n", ret);
 		goto out_prevalid;
 	}
 
@@ -760,7 +758,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	if (do_reloc) {
 		ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo);
 		if (ret) {
-			NV_ERROR(cli, "reloc apply: %d\n", ret);
+			NV_PRINTK(error, cli, "reloc apply: %d\n", ret);
 			goto out;
 		}
 	}
@@ -768,7 +766,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	if (chan->dma.ib_max) {
 		ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
 		if (ret) {
-			NV_ERROR(cli, "nv50cal_space: %d\n", ret);
+			NV_PRINTK(error, cli, "nv50cal_space: %d\n", ret);
 			goto out;
 		}
 
@@ -780,10 +778,10 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 				      push[i].length);
 		}
 	} else
-	if (nv_device(drm->device)->chipset >= 0x25) {
+	if (drm->device.info.chipset >= 0x25) {
 		ret = RING_SPACE(chan, req->nr_push * 2);
 		if (ret) {
-			NV_ERROR(cli, "cal_space: %d\n", ret);
+			NV_PRINTK(error, cli, "cal_space: %d\n", ret);
 			goto out;
 		}
 
@@ -797,7 +795,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	} else {
 		ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
 		if (ret) {
-			NV_ERROR(cli, "jmp_space: %d\n", ret);
+			NV_PRINTK(error, cli, "jmp_space: %d\n", ret);
 			goto out;
 		}
 
@@ -835,7 +833,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 
 	ret = nouveau_fence_new(chan, false, &fence);
 	if (ret) {
-		NV_ERROR(cli, "error fencing pushbuf: %d\n", ret);
+		NV_PRINTK(error, cli, "error fencing pushbuf: %d\n", ret);
 		WIND_RING(chan);
 		goto out;
 	}
@@ -853,7 +851,7 @@ out_next:
 		req->suffix0 = 0x00000000;
 		req->suffix1 = 0x00000000;
 	} else
-	if (nv_device(drm->device)->chipset >= 0x25) {
+	if (drm->device.info.chipset >= 0x25) {
 		req->suffix0 = 0x00020000;
 		req->suffix1 = 0x00000000;
 	} else {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@ extern int nouveau_gem_ioctl_info(struct
 				  struct drm_file *);
 
 extern int nouveau_gem_prime_pin(struct drm_gem_object *);
+struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *);
 extern void nouveau_gem_prime_unpin(struct drm_gem_object *);
 extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *);
 extern struct drm_gem_object *nouveau_gem_prime_import_sg_table(
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,17 +34,13 @@
 #include "nouveau_drm.h"
 #include "nouveau_hwmon.h"
 
-#include <subdev/gpio.h>
-#include <subdev/timer.h>
-#include <subdev/therm.h>
-
 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 static ssize_t
 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int temp = therm->temp_get(therm);
 
 	if (temp < 0)
@@ -70,7 +66,7 @@ nouveau_hwmon_temp1_auto_point1_temp(str
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	      therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST) * 1000);
@@ -82,7 +78,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -103,7 +99,7 @@ nouveau_hwmon_temp1_auto_point1_temp_hys
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
@@ -115,7 +111,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -135,7 +131,7 @@ nouveau_hwmon_max_temp(struct device *d,
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	       therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK) * 1000);
@@ -146,7 +142,7 @@ nouveau_hwmon_set_max_temp(struct device
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -166,7 +162,7 @@ nouveau_hwmon_max_temp_hyst(struct devic
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	  therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
@@ -177,7 +173,7 @@ nouveau_hwmon_set_max_temp_hyst(struct d
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -198,7 +194,7 @@ nouveau_hwmon_critical_temp(struct devic
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	       therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL) * 1000);
@@ -210,7 +206,7 @@ nouveau_hwmon_set_critical_temp(struct d
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -231,7 +227,7 @@ nouveau_hwmon_critical_temp_hyst(struct
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	  therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
@@ -244,7 +240,7 @@ nouveau_hwmon_set_critical_temp_hyst(str
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -264,7 +260,7 @@ nouveau_hwmon_emergency_temp(struct devi
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	       therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN) * 1000);
@@ -276,7 +272,7 @@ nouveau_hwmon_set_emergency_temp(struct
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -297,7 +293,7 @@ nouveau_hwmon_emergency_temp_hyst(struct
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 	  therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
@@ -310,7 +306,7 @@ nouveau_hwmon_set_emergency_temp_hyst(st
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 
 	if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -350,7 +346,7 @@ nouveau_hwmon_show_fan1_input(struct dev
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm));
 }
@@ -363,7 +359,7 @@ nouveau_hwmon_get_pwm1_enable(struct dev
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int ret;
 
 	ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MODE);
@@ -379,7 +375,7 @@ nouveau_hwmon_set_pwm1_enable(struct dev
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 	int ret;
 
@@ -402,7 +398,7 @@ nouveau_hwmon_get_pwm1(struct device *d,
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int ret;
 
 	ret = therm->fan_get(therm);
@@ -418,7 +414,7 @@ nouveau_hwmon_set_pwm1(struct device *d,
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int ret = -ENODEV;
 	long value;
 
@@ -442,7 +438,7 @@ nouveau_hwmon_get_pwm1_min(struct device
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int ret;
 
 	ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MIN_DUTY);
@@ -458,7 +454,7 @@ nouveau_hwmon_set_pwm1_min(struct device
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 	int ret;
 
@@ -482,7 +478,7 @@ nouveau_hwmon_get_pwm1_max(struct device
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	int ret;
 
 	ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MAX_DUTY);
@@ -498,7 +494,7 @@ nouveau_hwmon_set_pwm1_max(struct device
 {
 	struct drm_device *dev = dev_get_drvdata(d);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	long value;
 	int ret;
 
@@ -565,7 +561,7 @@ nouveau_hwmon_init(struct drm_device *de
 {
 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_therm *therm = nouveau_therm(drm->device);
+	struct nouveau_therm *therm = nvkm_therm(&drm->device);
 	struct nouveau_hwmon *hwmon;
 	struct device *hwmon_dev;
 	int ret = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2014 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>
+ */
+
+/*******************************************************************************
+ * NVIF client driver - NVKM directly linked
+ ******************************************************************************/
+
+#include <core/client.h>
+#include <core/notify.h>
+#include <core/ioctl.h>
+
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/event.h>
+#include <nvif/ioctl.h>
+
+#include "nouveau_drm.h"
+#include "nouveau_usif.h"
+
+static void
+nvkm_client_unmap(void *priv, void *ptr, u32 size)
+{
+	iounmap(ptr);
+}
+
+static void *
+nvkm_client_map(void *priv, u64 handle, u32 size)
+{
+	return ioremap(handle, size);
+}
+
+static int
+nvkm_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)
+{
+	return nvkm_ioctl(priv, super, data, size, hack);
+}
+
+static int
+nvkm_client_resume(void *priv)
+{
+	return nouveau_client_init(priv);
+}
+
+static int
+nvkm_client_suspend(void *priv)
+{
+	return nouveau_client_fini(priv, true);
+}
+
+static void
+nvkm_client_fini(void *priv)
+{
+	struct nouveau_object *client = priv;
+	nouveau_client_fini(nv_client(client), false);
+	atomic_set(&client->refcount, 1);
+	nouveau_object_ref(NULL, &client);
+}
+
+static int
+nvkm_client_ntfy(const void *header, u32 length, const void *data, u32 size)
+{
+	const union {
+		struct nvif_notify_req_v0 v0;
+	} *args = header;
+	u8 route;
+
+	if (length == sizeof(args->v0) && args->v0.version == 0) {
+		route = args->v0.route;
+	} else {
+		WARN_ON(1);
+		return NVKM_NOTIFY_DROP;
+	}
+
+	switch (route) {
+	case NVDRM_NOTIFY_NVIF:
+		return nvif_notify(header, length, data, size);
+	case NVDRM_NOTIFY_USIF:
+		return usif_notify(header, length, data, size);
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	return NVKM_NOTIFY_DROP;
+}
+
+static int
+nvkm_client_init(const char *name, u64 device, const char *cfg,
+		 const char *dbg, void **ppriv)
+{
+	struct nouveau_client *client;
+	int ret;
+
+	ret = nouveau_client_create(name, device, cfg, dbg, &client);
+	*ppriv = client;
+	if (ret)
+		return ret;
+
+	client->ntfy = nvkm_client_ntfy;
+	return 0;
+}
+
+const struct nvif_driver
+nvif_driver_nvkm = {
+	.name = "nvkm",
+	.init = nvkm_client_init,
+	.fini = nvkm_client_fini,
+	.suspend = nvkm_client_suspend,
+	.resume = nvkm_client_resume,
+	.ioctl = nvkm_client_ioctl,
+	.map = nvkm_client_map,
+	.unmap = nvkm_client_unmap,
+	.keep = false,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014, 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 <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#include <linux/regulator/consumer.h>
+#include <soc/tegra/pmc.h>
+
+#include "nouveau_drm.h"
+#include "nouveau_platform.h"
+
+static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu)
+{
+	int err;
+
+	err = regulator_enable(gpu->vdd);
+	if (err)
+		goto err_power;
+
+	err = clk_prepare_enable(gpu->clk);
+	if (err)
+		goto err_clk;
+	err = clk_prepare_enable(gpu->clk_pwr);
+	if (err)
+		goto err_clk_pwr;
+	clk_set_rate(gpu->clk_pwr, 204000000);
+	udelay(10);
+
+	reset_control_assert(gpu->rst);
+	udelay(10);
+
+	err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
+	if (err)
+		goto err_clamp;
+	udelay(10);
+
+	reset_control_deassert(gpu->rst);
+	udelay(10);
+
+	return 0;
+
+err_clamp:
+	clk_disable_unprepare(gpu->clk_pwr);
+err_clk_pwr:
+	clk_disable_unprepare(gpu->clk);
+err_clk:
+	regulator_disable(gpu->vdd);
+err_power:
+	return err;
+}
+
+static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
+{
+	int err;
+
+	reset_control_assert(gpu->rst);
+	udelay(10);
+
+	clk_disable_unprepare(gpu->clk_pwr);
+	clk_disable_unprepare(gpu->clk);
+	udelay(10);
+
+	err = regulator_disable(gpu->vdd);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int nouveau_platform_probe(struct platform_device *pdev)
+{
+	struct nouveau_platform_gpu *gpu;
+	struct nouveau_platform_device *device;
+	struct drm_device *drm;
+	int err;
+
+	gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL);
+	if (!gpu)
+		return -ENOMEM;
+
+	gpu->vdd = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(gpu->vdd))
+		return PTR_ERR(gpu->vdd);
+
+	gpu->rst = devm_reset_control_get(&pdev->dev, "gpu");
+	if (IS_ERR(gpu->rst))
+		return PTR_ERR(gpu->rst);
+
+	gpu->clk = devm_clk_get(&pdev->dev, "gpu");
+	if (IS_ERR(gpu->clk))
+		return PTR_ERR(gpu->clk);
+
+	gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
+	if (IS_ERR(gpu->clk_pwr))
+		return PTR_ERR(gpu->clk_pwr);
+
+	err = nouveau_platform_power_up(gpu);
+	if (err)
+		return err;
+
+	drm = nouveau_platform_device_create(pdev, &device);
+	if (IS_ERR(drm)) {
+		err = PTR_ERR(drm);
+		goto power_down;
+	}
+
+	device->gpu = gpu;
+
+	err = drm_dev_register(drm, 0);
+	if (err < 0)
+		goto err_unref;
+
+	return 0;
+
+err_unref:
+	drm_dev_unref(drm);
+
+	return 0;
+
+power_down:
+	nouveau_platform_power_down(gpu);
+
+	return err;
+}
+
+static int nouveau_platform_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm_dev = platform_get_drvdata(pdev);
+	struct nouveau_drm *drm = nouveau_drm(drm_dev);
+	struct nouveau_device *device = nvkm_device(&drm->device);
+	struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
+
+	nouveau_drm_device_remove(drm_dev);
+
+	return nouveau_platform_power_down(gpu);
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id nouveau_platform_match[] = {
+	{ .compatible = "nvidia,gk20a" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, nouveau_platform_match);
+#endif
+
+struct platform_driver nouveau_platform_driver = {
+	.driver = {
+		.name = "nouveau",
+		.of_match_table = of_match_ptr(nouveau_platform_match),
+	},
+	.probe = nouveau_platform_probe,
+	.remove = nouveau_platform_remove,
+};
+
+module_platform_driver(nouveau_platform_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef __NOUVEAU_PLATFORM_H__
+#define __NOUVEAU_PLATFORM_H__
+
+#include "core/device.h"
+
+struct reset_control;
+struct clk;
+struct regulator;
+
+struct nouveau_platform_gpu {
+	struct reset_control *rst;
+	struct clk *clk;
+	struct clk *clk_pwr;
+
+	struct regulator *vdd;
+};
+
+struct nouveau_platform_device {
+	struct nouveau_device device;
+
+	struct nouveau_platform_gpu *gpu;
+};
+
+#define nv_device_to_platform(d)                                               \
+	container_of(d, struct nouveau_platform_device, device)
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,3 +102,10 @@ void nouveau_gem_prime_unpin(struct drm_
 
 	nouveau_bo_unpin(nvbo);
 }
+
+struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+	struct nouveau_bo *nvbo = nouveau_gem_object(obj);
+
+	return nvbo->bo.resv;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,6 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 
-#include <subdev/fb.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_ttm.h"
 
@@ -104,7 +102,7 @@ nouveau_sgdma_create_ttm(struct ttm_bo_d
 		return NULL;
 
 	nvbe->dev = drm->dev;
-	if (nv_device(drm->device)->card_type < NV_50)
+	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA)
 		nvbe->ttm.ttm.func = &nv04_sgdma_backend;
 	else
 		nvbe->ttm.ttm.func = &nv50_sgdma_backend;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,10 +22,15 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
+#include <nvif/os.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
+
 #include "nouveau_sysfs.h"
 
-#include <core/object.h>
-#include <core/class.h>
+MODULE_PARM_DESC(pstate, "enable sysfs pstate file, which will be moved in the future");
+static int nouveau_pstate;
+module_param_named(pstate, nouveau_pstate, int, 0400);
 
 static inline struct drm_device *
 drm_device(struct device *d)
@@ -43,38 +48,42 @@ static ssize_t
 nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
 {
 	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
-	struct nv_control_pstate_info info;
+	struct nvif_control_pstate_info_v0 info = {};
 	size_t cnt = PAGE_SIZE;
 	char *buf = b;
 	int ret, i;
 
-	ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_INFO, &info, sizeof(info));
+	ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_INFO,
+			&info, sizeof(info));
 	if (ret)
 		return ret;
 
 	for (i = 0; i < info.count + 1; i++) {
 		const s32 state = i < info.count ? i :
-			NV_CONTROL_PSTATE_ATTR_STATE_CURRENT;
-		struct nv_control_pstate_attr attr = {
+			NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
+		struct nvif_control_pstate_attr_v0 attr = {
 			.state = state,
 			.index = 0,
 		};
 
-		ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR,
-			     &attr, sizeof(attr));
+		ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_ATTR,
+				&attr, sizeof(attr));
 		if (ret)
 			return ret;
 
 		if (i < info.count)
 			snappendf(buf, cnt, "%02x:", attr.state);
 		else
-			snappendf(buf, cnt, "--:");
+			snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" :
+						   info.pwrsrc == 1 ? "AC" :
+						   "--");
 
 		attr.index = 0;
 		do {
 			attr.state = state;
-			ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR,
-				     &attr, sizeof(attr));
+			ret = nvif_mthd(&sysfs->ctrl,
+					NVIF_CONTROL_PSTATE_ATTR,
+					&attr, sizeof(attr));
 			if (ret)
 				return ret;
 
@@ -84,9 +93,20 @@ nouveau_sysfs_pstate_get(struct device *
 			snappendf(buf, cnt, " %s", attr.unit);
 		} while (attr.index);
 
-		if ((state >= 0 && info.pstate == state) ||
-		    (state <  0 && info.ustate < 0))
-			snappendf(buf, cnt, " *");
+		if (state >= 0) {
+			if (info.ustate_ac == state)
+				snappendf(buf, cnt, " AC");
+			if (info.ustate_dc == state)
+				snappendf(buf, cnt, " DC");
+			if (info.pstate == state)
+				snappendf(buf, cnt, " *");
+		} else {
+			if (info.ustate_ac < -1)
+				snappendf(buf, cnt, " AC");
+			if (info.ustate_dc < -1)
+				snappendf(buf, cnt, " DC");
+		}
+
 		snappendf(buf, cnt, "\n");
 	}
 
@@ -98,26 +118,36 @@ nouveau_sysfs_pstate_set(struct device *
 			 const char *buf, size_t count)
 {
 	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
-	struct nv_control_pstate_user args;
+	struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
 	long value, ret;
 	char *tmp;
 
 	if ((tmp = strchr(buf, '\n')))
 		*tmp = '\0';
 
+	if (!strncasecmp(buf, "dc:", 3)) {
+		args.pwrsrc = 0;
+		buf += 3;
+	} else
+	if (!strncasecmp(buf, "ac:", 3)) {
+		args.pwrsrc = 1;
+		buf += 3;
+	}
+
 	if (!strcasecmp(buf, "none"))
-		args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
+		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
 	else
 	if (!strcasecmp(buf, "auto"))
-		args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
+		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
 	else {
 		ret = kstrtol(buf, 16, &value);
 		if (ret)
 			return ret;
-		args.state = value;
+		args.ustate = value;
 	}
 
-	ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args));
+	ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_USER,
+			&args, sizeof(args));
 	if (ret < 0)
 		return ret;
 
@@ -132,11 +162,11 @@ nouveau_sysfs_fini(struct drm_device *de
 {
 	struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 
-	if (sysfs->ctrl) {
-		device_remove_file(nv_device_base(device), &dev_attr_pstate);
-		nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL);
+	if (sysfs && sysfs->ctrl.priv) {
+		device_remove_file(nv_device_base(nvkm_device(device)), &dev_attr_pstate);
+		nvif_object_fini(&sysfs->ctrl);
 	}
 
 	drm->sysfs = NULL;
@@ -147,18 +177,22 @@ int
 nouveau_sysfs_init(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nouveau_device *device = nv_device(drm->device);
+	struct nvif_device *device = &drm->device;
 	struct nouveau_sysfs *sysfs;
 	int ret;
 
+	if (!nouveau_pstate)
+		return 0;
+
 	sysfs = drm->sysfs = kzalloc(sizeof(*sysfs), GFP_KERNEL);
 	if (!sysfs)
 		return -ENOMEM;
 
-	ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL,
-				 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl);
+	ret = nvif_object_init(nvif_object(device), NULL, NVDRM_CONTROL,
+			       NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0,
+			      &sysfs->ctrl);
 	if (ret == 0)
-		device_create_file(nv_device_base(device), &dev_attr_pstate);
+		device_create_file(nv_device_base(nvkm_device(device)), &dev_attr_pstate);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_sysfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,7 @@
 #include "nouveau_drm.h"
 
 struct nouveau_sysfs {
-	struct nouveau_object *ctrl;
+	struct nvif_object ctrl;
 };
 
 static inline struct nouveau_sysfs *
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,10 +24,6 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/instmem.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
@@ -36,7 +32,7 @@ static int
 nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
 {
 	struct nouveau_drm *drm = nouveau_bdev(man->bdev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	man->priv = pfb;
 	return 0;
 }
@@ -67,7 +63,7 @@ nouveau_vram_manager_del(struct ttm_mem_
 			 struct ttm_mem_reg *mem)
 {
 	struct nouveau_drm *drm = nouveau_bdev(man->bdev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	nouveau_mem_node_cleanup(mem->mm_node);
 	pfb->ram->put(pfb, (struct nouveau_mem **)&mem->mm_node);
 }
@@ -76,10 +72,11 @@ static int
 nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 			 struct ttm_buffer_object *bo,
 			 struct ttm_placement *placement,
+			 uint32_t flags,
 			 struct ttm_mem_reg *mem)
 {
 	struct nouveau_drm *drm = nouveau_bdev(man->bdev);
-	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+	struct nouveau_fb *pfb = nvkm_fb(&drm->device);
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	struct nouveau_mem *node;
 	u32 size_nc = 0;
@@ -162,6 +159,7 @@ static int
 nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
 			 struct ttm_buffer_object *bo,
 			 struct ttm_placement *placement,
+			 uint32_t flags,
 			 struct ttm_mem_reg *mem)
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
@@ -174,14 +172,13 @@ nouveau_gart_manager_new(struct ttm_mem_
 
 	node->page_shift = 12;
 
-	switch (nv_device(drm->device)->card_type) {
-	case NV_50:
-		if (nv_device(drm->device)->chipset != 0x50)
+	switch (drm->device.info.family) {
+	case NV_DEVICE_INFO_V0_TESLA:
+		if (drm->device.info.chipset != 0x50)
 			node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
 		break;
-	case NV_C0:
-	case NV_D0:
-	case NV_E0:
+	case NV_DEVICE_INFO_V0_FERMI:
+	case NV_DEVICE_INFO_V0_KEPLER:
 		node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
 		break;
 	default:
@@ -206,12 +203,13 @@ const struct ttm_mem_type_manager_func n
 	nouveau_gart_manager_debug
 };
 
+/*XXX*/
 #include <core/subdev/vm/nv04.h>
 static int
 nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
 {
 	struct nouveau_drm *drm = nouveau_bdev(man->bdev);
-	struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device);
+	struct nouveau_vmmgr *vmm = nvkm_vmmgr(&drm->device);
 	struct nv04_vmmgr_priv *priv = (void *)vmm;
 	struct nouveau_vm *vm = NULL;
 	nouveau_vm_ref(priv->vm, &vm, NULL);
@@ -242,6 +240,7 @@ static int
 nv04_gart_manager_new(struct ttm_mem_type_manager *man,
 		      struct ttm_buffer_object *bo,
 		      struct ttm_placement *placement,
+		      uint32_t flags,
 		      struct ttm_mem_reg *mem)
 {
 	struct nouveau_mem *node;
@@ -354,12 +353,11 @@ int
 nouveau_ttm_init(struct nouveau_drm *drm)
 {
 	struct drm_device *dev = drm->dev;
-	struct nouveau_device *device = nv_device(drm->device);
 	u32 bits;
 	int ret;
 
-	bits = nouveau_vmmgr(drm->device)->dma_bits;
-	if (nv_device_is_pci(device)) {
+	bits = nvkm_vmmgr(&drm->device)->dma_bits;
+	if (nv_device_is_pci(nvkm_device(&drm->device))) {
 		if (drm->agp.stat == ENABLED ||
 		     !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
 			bits = 32;
@@ -391,8 +389,7 @@ nouveau_ttm_init(struct nouveau_drm *drm
 	}
 
 	/* VRAM init */
-	drm->gem.vram_available  = nouveau_fb(drm->device)->ram->size;
-	drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved;
+	drm->gem.vram_available = drm->device.info.ram_user;
 
 	ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM,
 			      drm->gem.vram_available >> PAGE_SHIFT);
@@ -401,12 +398,12 @@ nouveau_ttm_init(struct nouveau_drm *drm
 		return ret;
 	}
 
-	drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1),
-					 nv_device_resource_len(device, 1));
+	drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(nvkm_device(&drm->device), 1),
+					 nv_device_resource_len(nvkm_device(&drm->device), 1));
 
 	/* GART init */
 	if (drm->agp.stat != ENABLED) {
-		drm->gem.gart_available = nouveau_vmmgr(drm->device)->limit;
+		drm->gem.gart_available = nvkm_vmmgr(&drm->device)->limit;
 	} else {
 		drm->gem.gart_available = drm->agp.size;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2014 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 "nouveau_drm.h"
+#include "nouveau_usif.h"
+
+#include <nvif/notify.h>
+#include <nvif/unpack.h>
+#include <nvif/client.h>
+#include <nvif/event.h>
+#include <nvif/ioctl.h>
+
+struct usif_notify_p {
+	struct drm_pending_event base;
+	struct {
+		struct drm_event base;
+		u8 data[];
+	} e;
+};
+
+struct usif_notify {
+	struct list_head head;
+	atomic_t enabled;
+	u32 handle;
+	u16 reply;
+	u8  route;
+	u64 token;
+	struct usif_notify_p *p;
+};
+
+static inline struct usif_notify *
+usif_notify_find(struct drm_file *filp, u32 handle)
+{
+	struct nouveau_cli *cli = nouveau_cli(filp);
+	struct usif_notify *ntfy;
+	list_for_each_entry(ntfy, &cli->notifys, head) {
+		if (ntfy->handle == handle)
+			return ntfy;
+	}
+	return NULL;
+}
+
+static inline void
+usif_notify_dtor(struct usif_notify *ntfy)
+{
+	list_del(&ntfy->head);
+	kfree(ntfy);
+}
+
+int
+usif_notify(const void *header, u32 length, const void *data, u32 size)
+{
+	struct usif_notify *ntfy = NULL;
+	const union {
+		struct nvif_notify_rep_v0 v0;
+	} *rep = header;
+	struct drm_device *dev;
+	struct drm_file *filp;
+	unsigned long flags;
+
+	if (length == sizeof(rep->v0) && rep->v0.version == 0) {
+		if (WARN_ON(!(ntfy = (void *)(unsigned long)rep->v0.token)))
+			return NVIF_NOTIFY_DROP;
+		BUG_ON(rep->v0.route != NVDRM_NOTIFY_USIF);
+	} else
+	if (WARN_ON(1))
+		return NVIF_NOTIFY_DROP;
+
+	if (WARN_ON(!ntfy->p || ntfy->reply != (length + size)))
+		return NVIF_NOTIFY_DROP;
+	filp = ntfy->p->base.file_priv;
+	dev = filp->minor->dev;
+
+	memcpy(&ntfy->p->e.data[0], header, length);
+	memcpy(&ntfy->p->e.data[length], data, size);
+	switch (rep->v0.version) {
+	case 0: {
+		struct nvif_notify_rep_v0 *rep = (void *)ntfy->p->e.data;
+		rep->route = ntfy->route;
+		rep->token = ntfy->token;
+	}
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (!WARN_ON(filp->event_space < ntfy->p->e.base.length)) {
+		list_add_tail(&ntfy->p->base.link, &filp->event_list);
+		filp->event_space -= ntfy->p->e.base.length;
+	}
+	wake_up_interruptible(&filp->event_wait);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	atomic_set(&ntfy->enabled, 0);
+	return NVIF_NOTIFY_DROP;
+}
+
+static int
+usif_notify_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(f);
+	struct nvif_client *client = &cli->base;
+	union {
+		struct nvif_ioctl_ntfy_new_v0 v0;
+	} *args = data;
+	union {
+		struct nvif_notify_req_v0 v0;
+	} *req;
+	struct usif_notify *ntfy;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		if (usif_notify_find(f, args->v0.index))
+			return -EEXIST;
+	} else
+		return ret;
+	req = data;
+
+	if (!(ntfy = kmalloc(sizeof(*ntfy), GFP_KERNEL)))
+		return -ENOMEM;
+	atomic_set(&ntfy->enabled, 0);
+
+	if (nvif_unpack(req->v0, 0, 0, true)) {
+		ntfy->reply = sizeof(struct nvif_notify_rep_v0) + req->v0.reply;
+		ntfy->route = req->v0.route;
+		ntfy->token = req->v0.token;
+		req->v0.route = NVDRM_NOTIFY_USIF;
+		req->v0.token = (unsigned long)(void *)ntfy;
+		ret = nvif_client_ioctl(client, argv, argc);
+		req->v0.token = ntfy->token;
+		req->v0.route = ntfy->route;
+		ntfy->handle = args->v0.index;
+	}
+
+	if (ret == 0)
+		list_add(&ntfy->head, &cli->notifys);
+	if (ret)
+		kfree(ntfy);
+	return ret;
+}
+
+static int
+usif_notify_del(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(f);
+	struct nvif_client *client = &cli->base;
+	union {
+		struct nvif_ioctl_ntfy_del_v0 v0;
+	} *args = data;
+	struct usif_notify *ntfy;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		if (!(ntfy = usif_notify_find(f, args->v0.index)))
+			return -ENOENT;
+	} else
+		return ret;
+
+	ret = nvif_client_ioctl(client, argv, argc);
+	if (ret == 0)
+		usif_notify_dtor(ntfy);
+	return ret;
+}
+
+static int
+usif_notify_get(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(f);
+	struct nvif_client *client = &cli->base;
+	union {
+		struct nvif_ioctl_ntfy_del_v0 v0;
+	} *args = data;
+	struct usif_notify *ntfy;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		if (!(ntfy = usif_notify_find(f, args->v0.index)))
+			return -ENOENT;
+	} else
+		return ret;
+
+	if (atomic_xchg(&ntfy->enabled, 1))
+		return 0;
+
+	ntfy->p = kmalloc(sizeof(*ntfy->p) + ntfy->reply, GFP_KERNEL);
+	if (ret = -ENOMEM, !ntfy->p)
+		goto done;
+	ntfy->p->base.event = &ntfy->p->e.base;
+	ntfy->p->base.file_priv = f;
+	ntfy->p->base.pid = current->pid;
+	ntfy->p->base.destroy =(void(*)(struct drm_pending_event *))kfree;
+	ntfy->p->e.base.type = DRM_NOUVEAU_EVENT_NVIF;
+	ntfy->p->e.base.length = sizeof(ntfy->p->e.base) + ntfy->reply;
+
+	ret = nvif_client_ioctl(client, argv, argc);
+done:
+	if (ret) {
+		atomic_set(&ntfy->enabled, 0);
+		kfree(ntfy->p);
+	}
+	return ret;
+}
+
+static int
+usif_notify_put(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(f);
+	struct nvif_client *client = &cli->base;
+	union {
+		struct nvif_ioctl_ntfy_put_v0 v0;
+	} *args = data;
+	struct usif_notify *ntfy;
+	int ret;
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		if (!(ntfy = usif_notify_find(f, args->v0.index)))
+			return -ENOENT;
+	} else
+		return ret;
+
+	ret = nvif_client_ioctl(client, argv, argc);
+	if (ret == 0 && atomic_xchg(&ntfy->enabled, 0))
+		kfree(ntfy->p);
+	return ret;
+}
+
+struct usif_object {
+	struct list_head head;
+	struct list_head ntfy;
+	u8  route;
+	u64 token;
+};
+
+static void
+usif_object_dtor(struct usif_object *object)
+{
+	list_del(&object->head);
+	kfree(object);
+}
+
+static int
+usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(f);
+	struct nvif_client *client = &cli->base;
+	union {
+		struct nvif_ioctl_new_v0 v0;
+	} *args = data;
+	struct usif_object *object;
+	int ret;
+
+	if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
+		return -ENOMEM;
+	list_add(&object->head, &cli->objects);
+
+	if (nvif_unpack(args->v0, 0, 0, true)) {
+		object->route = args->v0.route;
+		object->token = args->v0.token;
+		args->v0.route = NVDRM_OBJECT_USIF;
+		args->v0.token = (unsigned long)(void *)object;
+		ret = nvif_client_ioctl(client, argv, argc);
+		args->v0.token = object->token;
+		args->v0.route = object->route;
+	}
+
+	if (ret)
+		usif_object_dtor(object);
+	return ret;
+}
+
+int
+usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
+{
+	struct nouveau_cli *cli = nouveau_cli(filp);
+	struct nvif_client *client = &cli->base;
+	void *data = kmalloc(argc, GFP_KERNEL);
+	u32   size = argc;
+	union {
+		struct nvif_ioctl_v0 v0;
+	} *argv = data;
+	struct usif_object *object;
+	u8 owner;
+	int ret;
+
+	if (ret = -ENOMEM, !argv)
+		goto done;
+	if (ret = -EFAULT, copy_from_user(argv, user, size))
+		goto done;
+
+	if (nvif_unpack(argv->v0, 0, 0, true)) {
+		/* block access to objects not created via this interface */
+		owner = argv->v0.owner;
+		argv->v0.owner = NVDRM_OBJECT_USIF;
+	} else
+		goto done;
+
+	mutex_lock(&cli->mutex);
+	switch (argv->v0.type) {
+	case NVIF_IOCTL_V0_NEW:
+		/* ... except if we're creating children */
+		argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+		ret = usif_object_new(filp, data, size, argv, argc);
+		break;
+	case NVIF_IOCTL_V0_NTFY_NEW:
+		ret = usif_notify_new(filp, data, size, argv, argc);
+		break;
+	case NVIF_IOCTL_V0_NTFY_DEL:
+		ret = usif_notify_del(filp, data, size, argv, argc);
+		break;
+	case NVIF_IOCTL_V0_NTFY_GET:
+		ret = usif_notify_get(filp, data, size, argv, argc);
+		break;
+	case NVIF_IOCTL_V0_NTFY_PUT:
+		ret = usif_notify_put(filp, data, size, argv, argc);
+		break;
+	default:
+		ret = nvif_client_ioctl(client, argv, argc);
+		break;
+	}
+	if (argv->v0.route == NVDRM_OBJECT_USIF) {
+		object = (void *)(unsigned long)argv->v0.token;
+		argv->v0.route = object->route;
+		argv->v0.token = object->token;
+		if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) {
+			list_del(&object->head);
+			kfree(object);
+		}
+	} else {
+		argv->v0.route = NVIF_IOCTL_V0_ROUTE_HIDDEN;
+		argv->v0.token = 0;
+	}
+	argv->v0.owner = owner;
+	mutex_unlock(&cli->mutex);
+
+	if (copy_to_user(user, argv, argc))
+		ret = -EFAULT;
+done:
+	kfree(argv);
+	return ret;
+}
+
+void
+usif_client_fini(struct nouveau_cli *cli)
+{
+	struct usif_object *object, *otemp;
+	struct usif_notify *notify, *ntemp;
+
+	list_for_each_entry_safe(notify, ntemp, &cli->notifys, head) {
+		usif_notify_dtor(notify);
+	}
+
+	list_for_each_entry_safe(object, otemp, &cli->objects, head) {
+		usif_object_dtor(object);
+	}
+}
+
+void
+usif_client_init(struct nouveau_cli *cli)
+{
+	INIT_LIST_HEAD(&cli->objects);
+	INIT_LIST_HEAD(&cli->notifys);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_usif.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_usif.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef __NOUVEAU_USIF_H__
+#define __NOUVEAU_USIF_H__
+
+void usif_client_init(struct nouveau_cli *);
+void usif_client_fini(struct nouveau_cli *);
+int  usif_ioctl(struct drm_file *, void __user *, u32);
+int  usif_notify(const void *, u32, const void *, u32);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,14 +12,16 @@
 static unsigned int
 nouveau_vga_set_decode(void *priv, bool state)
 {
-	struct nouveau_device *device = nouveau_dev(priv);
+	struct nvif_device *device = &nouveau_drm(priv)->device;
 
-	if (device->card_type == NV_40 && device->chipset >= 0x4c)
-		nv_wr32(device, 0x088060, state);
-	else if (device->chipset >= 0x40)
-		nv_wr32(device, 0x088054, state);
+	if (device->info.family == NV_DEVICE_INFO_V0_CURIE &&
+	    device->info.chipset >= 0x4c)
+		nvif_wr32(device, 0x088060, state);
 	else
-		nv_wr32(device, 0x001854, state);
+	if (device->info.chipset >= 0x40)
+		nvif_wr32(device, 0x088054, state);
+	else
+		nvif_wr32(device, 0x001854, state);
 
 	if (state)
 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
@@ -106,7 +108,16 @@ void
 nouveau_vga_fini(struct nouveau_drm *drm)
 {
 	struct drm_device *dev = drm->dev;
+	bool runtime = false;
+
+	if (nouveau_runtime_pm == 1)
+		runtime = true;
+	if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
+		runtime = true;
+
 	vga_switcheroo_unregister_client(dev->pdev);
+	if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
+		vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
 	vga_client_register(dev->pdev, NULL, NULL, NULL);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <core/object.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fbcon.h"
@@ -141,8 +139,7 @@ nv04_fbcon_accel_init(struct fb_info *in
 	struct drm_device *dev = nfbdev->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
-	struct nouveau_device *device = nv_device(drm->device);
-	struct nouveau_object *object;
+	struct nvif_device *device = &drm->device;
 	int surface_fmt, pattern_fmt, rect_fmt;
 	int ret;
 
@@ -174,35 +171,35 @@ nv04_fbcon_accel_init(struct fb_info *in
 		return -EINVAL;
 	}
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvCtxSurf2D,
-				 device->card_type >= NV_10 ? 0x0062 : 0x0042,
-				 NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x0062,
+			       device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ?
+			       0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvClipRect,
-				 0x0019, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x0019, 0x0019, NULL, 0,
+			       &nfbdev->clip);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvRop,
-				 0x0043, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x0043, 0x0043, NULL, 0,
+			       &nfbdev->rop);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImagePatt,
-				 0x0044, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x0044, 0x0044, NULL, 0,
+			       &nfbdev->patt);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvGdiRect,
-				 0x004a, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x004a, 0x004a, NULL, 0,
+			       &nfbdev->gdi);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImageBlit,
-				 device->chipset >= 0x11 ? 0x009f : 0x005f,
-				 NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x005f,
+			       device->info.chipset >= 0x11 ? 0x009f : 0x005f,
+			       NULL, 0, &nfbdev->blit);
 	if (ret)
 		return ret;
 
@@ -212,10 +209,10 @@ nv04_fbcon_accel_init(struct fb_info *in
 	}
 
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
-	OUT_RING(chan, NvCtxSurf2D);
+	OUT_RING(chan, nfbdev->surf2d.handle);
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0184, 2);
-	OUT_RING(chan, NvDmaFB);
-	OUT_RING(chan, NvDmaFB);
+	OUT_RING(chan, chan->vram.handle);
+	OUT_RING(chan, chan->vram.handle);
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 4);
 	OUT_RING(chan, surface_fmt);
 	OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
@@ -223,12 +220,12 @@ nv04_fbcon_accel_init(struct fb_info *in
 	OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
 
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
-	OUT_RING(chan, NvRop);
+	OUT_RING(chan, nfbdev->rop.handle);
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 1);
 	OUT_RING(chan, 0x55);
 
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
-	OUT_RING(chan, NvImagePatt);
+	OUT_RING(chan, nfbdev->patt.handle);
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 8);
 	OUT_RING(chan, pattern_fmt);
 #ifdef __BIG_ENDIAN
@@ -244,18 +241,18 @@ nv04_fbcon_accel_init(struct fb_info *in
 	OUT_RING(chan, ~0);
 
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
-	OUT_RING(chan, NvClipRect);
+	OUT_RING(chan, nfbdev->clip.handle);
 	BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 2);
 	OUT_RING(chan, 0);
 	OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
 
 	BEGIN_NV04(chan, NvSubImageBlit, 0x0000, 1);
-	OUT_RING(chan, NvImageBlit);
+	OUT_RING(chan, nfbdev->blit.handle);
 	BEGIN_NV04(chan, NvSubImageBlit, 0x019c, 1);
-	OUT_RING(chan, NvCtxSurf2D);
+	OUT_RING(chan, nfbdev->surf2d.handle);
 	BEGIN_NV04(chan, NvSubImageBlit, 0x02fc, 1);
 	OUT_RING(chan, 3);
-	if (device->chipset >= 0x11 /*XXX: oclass == 0x009f*/) {
+	if (device->info.chipset >= 0x11 /*XXX: oclass == 0x009f*/) {
 		BEGIN_NV04(chan, NvSubImageBlit, 0x0120, 3);
 		OUT_RING(chan, 0);
 		OUT_RING(chan, 1);
@@ -263,12 +260,12 @@ nv04_fbcon_accel_init(struct fb_info *in
 	}
 
 	BEGIN_NV04(chan, NvSubGdiRect, 0x0000, 1);
-	OUT_RING(chan, NvGdiRect);
+	OUT_RING(chan, nfbdev->gdi.handle);
 	BEGIN_NV04(chan, NvSubGdiRect, 0x0198, 1);
-	OUT_RING(chan, NvCtxSurf2D);
+	OUT_RING(chan, nfbdev->surf2d.handle);
 	BEGIN_NV04(chan, NvSubGdiRect, 0x0188, 2);
-	OUT_RING(chan, NvImagePatt);
-	OUT_RING(chan, NvRop);
+	OUT_RING(chan, nfbdev->patt.handle);
+	OUT_RING(chan, nfbdev->rop.handle);
 	BEGIN_NV04(chan, NvSubGdiRect, 0x0304, 1);
 	OUT_RING(chan, 1);
 	BEGIN_NV04(chan, NvSubGdiRect, 0x0300, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv04_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv04_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#include <engine/fifo.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
@@ -59,7 +57,7 @@ nv04_fence_sync(struct nouveau_fence *fe
 static u32
 nv04_fence_read(struct nouveau_channel *chan)
 {
-	struct nouveau_fifo_chan *fifo = (void *)chan->object;
+	struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(chan);;
 	return atomic_read(&fifo->refcnt);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv10_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv10_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,6 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include <core/object.h>
-#include <core/class.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nv10_fence.h"
@@ -53,14 +50,18 @@ nv10_fence_sync(struct nouveau_fence *fe
 u32
 nv10_fence_read(struct nouveau_channel *chan)
 {
-	return nv_ro32(chan->object, 0x0048);
+	return nvif_rd32(chan, 0x0048);
 }
 
 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;
 	kfree(fctx);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv10_fence.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv10_fence.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv10_fence.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv10_fence.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,13 @@
 #ifndef __NV10_FENCE_H_
 #define __NV10_FENCE_H_
 
-#include <core/os.h>
 #include "nouveau_fence.h"
 #include "nouveau_bo.h"
 
 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-3.16-gnu/drivers/gpu/drm/nouveau/nv17_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv17_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,8 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include <core/object.h>
-#include <core/class.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -33,11 +33,13 @@ int
 nv17_fence_sync(struct nouveau_fence *fence,
 		struct nouveau_channel *prev, struct nouveau_channel *chan)
 {
+	struct nouveau_cli *cli = (void *)nvif_client(&prev->device->base);
 	struct nv10_fence_priv *priv = chan->drm->fence;
+	struct nv10_fence_chan *fctx = chan->fence;
 	u32 value;
 	int ret;
 
-	if (!mutex_trylock(&prev->cli->mutex))
+	if (!mutex_trylock(&cli->mutex))
 		return -EBUSY;
 
 	spin_lock(&priv->lock);
@@ -48,7 +50,7 @@ nv17_fence_sync(struct nouveau_fence *fe
 	ret = RING_SPACE(prev, 5);
 	if (!ret) {
 		BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
-		OUT_RING  (prev, NvSema);
+		OUT_RING  (prev, fctx->sema.handle);
 		OUT_RING  (prev, 0);
 		OUT_RING  (prev, value + 0);
 		OUT_RING  (prev, value + 1);
@@ -57,14 +59,14 @@ nv17_fence_sync(struct nouveau_fence *fe
 
 	if (!ret && !(ret = RING_SPACE(chan, 5))) {
 		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
-		OUT_RING  (chan, NvSema);
+		OUT_RING  (chan, fctx->sema.handle);
 		OUT_RING  (chan, 0);
 		OUT_RING  (chan, value + 1);
 		OUT_RING  (chan, value + 2);
 		FIRE_RING (chan);
 	}
 
-	mutex_unlock(&prev->cli->mutex);
+	mutex_unlock(&cli->mutex);
 	return 0;
 }
 
@@ -74,7 +76,6 @@ nv17_fence_context_new(struct nouveau_ch
 	struct nv10_fence_priv *priv = chan->drm->fence;
 	struct nv10_fence_chan *fctx;
 	struct ttm_mem_reg *mem = &priv->bo->bo.mem;
-	struct nouveau_object *object;
 	u32 start = mem->start * PAGE_SIZE;
 	u32 limit = start + mem->size - 1;
 	int ret = 0;
@@ -88,15 +89,14 @@ nv17_fence_context_new(struct nouveau_ch
 	fctx->base.read = nv10_fence_read;
 	fctx->base.sync = nv17_fence_sync;
 
-	ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
-				 NvSema, 0x0002,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
+	ret = nvif_object_init(chan->object, NULL, NvSema, NV_DMA_FROM_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_class),
-				 &object);
+			       }, sizeof(struct nv_dma_v0),
+			       &fctx->sema);
 	if (ret)
 		nv10_fence_context_del(chan);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,8 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_dp_helper.h>
 
+#include <nvif/class.h>
+
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_gem.h"
@@ -37,15 +39,6 @@
 #include "nouveau_fence.h"
 #include "nv50_display.h"
 
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <core/class.h>
-
-#include <subdev/timer.h>
-#include <subdev/bar.h>
-#include <subdev/fb.h>
-#include <subdev/i2c.h>
-
 #define EVO_DMA_NR 9
 
 #define EVO_MASTER  (0x00)
@@ -60,45 +53,34 @@
 #define EVO_FLIP_SEM0(c)  EVO_SYNC((c) + 1, 0x00)
 #define EVO_FLIP_SEM1(c)  EVO_SYNC((c) + 1, 0x10)
 
-#define EVO_CORE_HANDLE      (0xd1500000)
-#define EVO_CHAN_HANDLE(t,i) (0xd15c0000 | (((t) & 0x00ff) << 8) | (i))
-#define EVO_CHAN_OCLASS(t,c) ((nv_hclass(c) & 0xff00) | ((t) & 0x00ff))
-#define EVO_PUSH_HANDLE(t,i) (0xd15b0000 | (i) |                               \
-			      (((NV50_DISP_##t##_CLASS) & 0x00ff) << 8))
-
 /******************************************************************************
  * EVO channel
  *****************************************************************************/
 
 struct nv50_chan {
-	struct nouveau_object *user;
-	u32 handle;
+	struct nvif_object user;
 };
 
 static int
-nv50_chan_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_chan_create(struct nvif_object *disp, const u32 *oclass, u8 head,
 		 void *data, u32 size, struct nv50_chan *chan)
 {
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	const u32 oclass = EVO_CHAN_OCLASS(bclass, core);
-	const u32 handle = EVO_CHAN_HANDLE(bclass, head);
-	int ret;
-
-	ret = nouveau_object_new(client, EVO_CORE_HANDLE, handle,
-				 oclass, data, size, &chan->user);
-	if (ret)
-		return ret;
-
-	chan->handle = handle;
-	return 0;
+	while (oclass[0]) {
+		int ret = nvif_object_init(disp, NULL, (oclass[0] << 16) | head,
+					   oclass[0], data, size,
+					  &chan->user);
+		if (oclass++, ret == 0) {
+			nvif_object_map(&chan->user);
+			return ret;
+		}
+	}
+	return -ENOSYS;
 }
 
 static void
-nv50_chan_destroy(struct nouveau_object *core, struct nv50_chan *chan)
+nv50_chan_destroy(struct nv50_chan *chan)
 {
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	if (chan->handle)
-		nouveau_object_del(client, EVO_CORE_HANDLE, chan->handle);
+	nvif_object_fini(&chan->user);
 }
 
 /******************************************************************************
@@ -110,16 +92,70 @@ struct nv50_pioc {
 };
 
 static void
-nv50_pioc_destroy(struct nouveau_object *core, struct nv50_pioc *pioc)
+nv50_pioc_destroy(struct nv50_pioc *pioc)
 {
-	nv50_chan_destroy(core, &pioc->base);
+	nv50_chan_destroy(&pioc->base);
 }
 
 static int
-nv50_pioc_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head,
 		 void *data, u32 size, struct nv50_pioc *pioc)
 {
-	return nv50_chan_create(core, bclass, head, data, size, &pioc->base);
+	return nv50_chan_create(disp, oclass, head, data, size, &pioc->base);
+}
+
+/******************************************************************************
+ * Cursor Immediate
+ *****************************************************************************/
+
+struct nv50_curs {
+	struct nv50_pioc base;
+};
+
+static int
+nv50_curs_create(struct nvif_object *disp, int head, struct nv50_curs *curs)
+{
+	struct nv50_disp_cursor_v0 args = {
+		.head = head,
+	};
+	static const u32 oclass[] = {
+		GK104_DISP_CURSOR,
+		GF110_DISP_CURSOR,
+		GT214_DISP_CURSOR,
+		G82_DISP_CURSOR,
+		NV50_DISP_CURSOR,
+		0
+	};
+
+	return nv50_pioc_create(disp, oclass, head, &args, sizeof(args),
+			       &curs->base);
+}
+
+/******************************************************************************
+ * Overlay Immediate
+ *****************************************************************************/
+
+struct nv50_oimm {
+	struct nv50_pioc base;
+};
+
+static int
+nv50_oimm_create(struct nvif_object *disp, int head, struct nv50_oimm *oimm)
+{
+	struct nv50_disp_cursor_v0 args = {
+		.head = head,
+	};
+	static const u32 oclass[] = {
+		GK104_DISP_OVERLAY,
+		GF110_DISP_OVERLAY,
+		GT214_DISP_OVERLAY,
+		G82_DISP_OVERLAY,
+		NV50_DISP_OVERLAY,
+		0
+	};
+
+	return nv50_pioc_create(disp, oclass, head, &args, sizeof(args),
+			       &oimm->base);
 }
 
 /******************************************************************************
@@ -131,6 +167,9 @@ struct nv50_dmac {
 	dma_addr_t handle;
 	u32 *ptr;
 
+	struct nvif_object sync;
+	struct nvif_object vram;
+
 	/* Protects against concurrent pushbuf access to this channel, lock is
 	 * grabbed by evo_wait (if the pushbuf reservation is successful) and
 	 * dropped again by evo_kick. */
@@ -138,207 +177,113 @@ struct nv50_dmac {
 };
 
 static void
-nv50_dmac_destroy(struct nouveau_object *core, struct nv50_dmac *dmac)
+nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp)
 {
+	nvif_object_fini(&dmac->vram);
+	nvif_object_fini(&dmac->sync);
+
+	nv50_chan_destroy(&dmac->base);
+
 	if (dmac->ptr) {
-		struct pci_dev *pdev = nv_device(core)->pdev;
+		struct pci_dev *pdev = nvkm_device(nvif_device(disp))->pdev;
 		pci_free_consistent(pdev, PAGE_SIZE, dmac->ptr, dmac->handle);
 	}
-
-	nv50_chan_destroy(core, &dmac->base);
-}
-
-static int
-nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
-	struct nouveau_fb *pfb = nouveau_fb(core);
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	struct nouveau_object *object;
-	int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
-				     NV_DMA_IN_MEMORY_CLASS,
-				     &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NV50_DMA_CONF0_ENABLE |
-					         NV50_DMA_CONF0_PART_256,
-				     }, sizeof(struct nv_dma_class), &object);
-	if (ret)
-		return ret;
-
-	ret = nouveau_object_new(client, parent, NvEvoFB16,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NV50_DMA_CONF0_ENABLE | 0x70 |
-					         NV50_DMA_CONF0_PART_256,
-				 }, sizeof(struct nv_dma_class), &object);
-	if (ret)
-		return ret;
-
-	ret = nouveau_object_new(client, parent, NvEvoFB32,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NV50_DMA_CONF0_ENABLE | 0x7a |
-					         NV50_DMA_CONF0_PART_256,
-				 }, sizeof(struct nv_dma_class), &object);
-	return ret;
-}
-
-static int
-nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
-	struct nouveau_fb *pfb = nouveau_fb(core);
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	struct nouveau_object *object;
-	int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
-				     NV_DMA_IN_MEMORY_CLASS,
-				     &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NVC0_DMA_CONF0_ENABLE,
-				     }, sizeof(struct nv_dma_class), &object);
-	if (ret)
-		return ret;
-
-	ret = nouveau_object_new(client, parent, NvEvoFB16,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
-				 }, sizeof(struct nv_dma_class), &object);
-	if (ret)
-		return ret;
-
-	ret = nouveau_object_new(client, parent, NvEvoFB32,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
-				 }, sizeof(struct nv_dma_class), &object);
-	return ret;
-}
-
-static int
-nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
-	struct nouveau_fb *pfb = nouveau_fb(core);
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	struct nouveau_object *object;
-	int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
-				     NV_DMA_IN_MEMORY_CLASS,
-				     &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NVD0_DMA_CONF0_ENABLE |
-						 NVD0_DMA_CONF0_PAGE_LP,
-				     }, sizeof(struct nv_dma_class), &object);
-	if (ret)
-		return ret;
-
-	ret = nouveau_object_new(client, parent, NvEvoFB32,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
-					.start = 0,
-					.limit = pfb->ram->size - 1,
-					.conf0 = NVD0_DMA_CONF0_ENABLE | 0xfe |
-						 NVD0_DMA_CONF0_PAGE_LP,
-				 }, sizeof(struct nv_dma_class), &object);
-	return ret;
 }
 
 static int
-nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head,
 		 void *data, u32 size, u64 syncbuf,
 		 struct nv50_dmac *dmac)
 {
-	struct nouveau_fb *pfb = nouveau_fb(core);
-	struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
-	struct nouveau_object *object;
-	u32 pushbuf = *(u32 *)data;
+	struct nvif_device *device = nvif_device(disp);
+	struct nv50_disp_core_channel_dma_v0 *args = data;
+	struct nvif_object pushbuf;
 	int ret;
 
 	mutex_init(&dmac->lock);
 
-	dmac->ptr = pci_alloc_consistent(nv_device(core)->pdev, PAGE_SIZE,
-					&dmac->handle);
+	dmac->ptr = pci_alloc_consistent(nvkm_device(device)->pdev,
+					 PAGE_SIZE, &dmac->handle);
 	if (!dmac->ptr)
 		return -ENOMEM;
 
-	ret = nouveau_object_new(client, NVDRM_DEVICE, pushbuf,
-				 NV_DMA_FROM_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_PCI_US |
-						 NV_DMA_ACCESS_RD,
+	ret = nvif_object_init(nvif_object(device), NULL,
+			       args->pushbuf, NV_DMA_FROM_MEMORY,
+			       &(struct nv_dma_v0) {
+					.target = NV_DMA_V0_TARGET_PCI_US,
+					.access = NV_DMA_V0_ACCESS_RD,
 					.start = dmac->handle + 0x0000,
 					.limit = dmac->handle + 0x0fff,
-				 }, sizeof(struct nv_dma_class), &object);
+			       }, sizeof(struct nv_dma_v0), &pushbuf);
 	if (ret)
 		return ret;
 
-	ret = nv50_chan_create(core, bclass, head, data, size, &dmac->base);
+	ret = nv50_chan_create(disp, oclass, head, data, size, &dmac->base);
+	nvif_object_fini(&pushbuf);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(client, dmac->base.handle, NvEvoSync,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
+	ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000000,
+			       NV_DMA_IN_MEMORY,
+			       &(struct nv_dma_v0) {
+					.target = NV_DMA_V0_TARGET_VRAM,
+					.access = NV_DMA_V0_ACCESS_RDWR,
 					.start = syncbuf + 0x0000,
 					.limit = syncbuf + 0x0fff,
-				 }, sizeof(struct nv_dma_class), &object);
+			       }, sizeof(struct nv_dma_v0),
+			       &dmac->sync);
 	if (ret)
 		return ret;
 
-	ret = nouveau_object_new(client, dmac->base.handle, NvEvoVRAM,
-				 NV_DMA_IN_MEMORY_CLASS,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
+	ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000001,
+			       NV_DMA_IN_MEMORY,
+			       &(struct nv_dma_v0) {
+					.target = NV_DMA_V0_TARGET_VRAM,
+					.access = NV_DMA_V0_ACCESS_RDWR,
 					.start = 0,
-					.limit = pfb->ram->size - 1,
-				 }, sizeof(struct nv_dma_class), &object);
+					.limit = device->info.ram_user - 1,
+			       }, sizeof(struct nv_dma_v0),
+			       &dmac->vram);
 	if (ret)
 		return ret;
 
-	if (nv_device(core)->card_type < NV_C0)
-		ret = nv50_dmac_create_fbdma(core, dmac->base.handle);
-	else
-	if (nv_device(core)->card_type < NV_D0)
-		ret = nvc0_dmac_create_fbdma(core, dmac->base.handle);
-	else
-		ret = nvd0_dmac_create_fbdma(core, dmac->base.handle);
 	return ret;
 }
 
+/******************************************************************************
+ * Core
+ *****************************************************************************/
+
 struct nv50_mast {
 	struct nv50_dmac base;
 };
 
-struct nv50_curs {
-	struct nv50_pioc base;
-};
+static int
+nv50_core_create(struct nvif_object *disp, u64 syncbuf, struct nv50_mast *core)
+{
+	struct nv50_disp_core_channel_dma_v0 args = {
+		.pushbuf = 0xb0007d00,
+	};
+	static const u32 oclass[] = {
+		GM107_DISP_CORE_CHANNEL_DMA,
+		GK110_DISP_CORE_CHANNEL_DMA,
+		GK104_DISP_CORE_CHANNEL_DMA,
+		GF110_DISP_CORE_CHANNEL_DMA,
+		GT214_DISP_CORE_CHANNEL_DMA,
+		GT206_DISP_CORE_CHANNEL_DMA,
+		GT200_DISP_CORE_CHANNEL_DMA,
+		G82_DISP_CORE_CHANNEL_DMA,
+		NV50_DISP_CORE_CHANNEL_DMA,
+		0
+	};
+
+	return nv50_dmac_create(disp, oclass, 0, &args, sizeof(args), syncbuf,
+			       &core->base);
+}
+
+/******************************************************************************
+ * Base
+ *****************************************************************************/
 
 struct nv50_sync {
 	struct nv50_dmac base;
@@ -346,13 +291,58 @@ struct nv50_sync {
 	u32 data;
 };
 
+static int
+nv50_base_create(struct nvif_object *disp, int head, u64 syncbuf,
+		 struct nv50_sync *base)
+{
+	struct nv50_disp_base_channel_dma_v0 args = {
+		.pushbuf = 0xb0007c00 | head,
+		.head = head,
+	};
+	static const u32 oclass[] = {
+		GK110_DISP_BASE_CHANNEL_DMA,
+		GK104_DISP_BASE_CHANNEL_DMA,
+		GF110_DISP_BASE_CHANNEL_DMA,
+		GT214_DISP_BASE_CHANNEL_DMA,
+		GT200_DISP_BASE_CHANNEL_DMA,
+		G82_DISP_BASE_CHANNEL_DMA,
+		NV50_DISP_BASE_CHANNEL_DMA,
+		0
+	};
+
+	return nv50_dmac_create(disp, oclass, head, &args, sizeof(args),
+				syncbuf, &base->base);
+}
+
+/******************************************************************************
+ * Overlay
+ *****************************************************************************/
+
 struct nv50_ovly {
 	struct nv50_dmac base;
 };
 
-struct nv50_oimm {
-	struct nv50_pioc base;
-};
+static int
+nv50_ovly_create(struct nvif_object *disp, int head, u64 syncbuf,
+		 struct nv50_ovly *ovly)
+{
+	struct nv50_disp_overlay_channel_dma_v0 args = {
+		.pushbuf = 0xb0007e00 | head,
+		.head = head,
+	};
+	static const u32 oclass[] = {
+		GK104_DISP_OVERLAY_CONTROL_DMA,
+		GF110_DISP_OVERLAY_CONTROL_DMA,
+		GT214_DISP_OVERLAY_CHANNEL_DMA,
+		GT200_DISP_OVERLAY_CHANNEL_DMA,
+		G82_DISP_OVERLAY_CHANNEL_DMA,
+		NV50_DISP_OVERLAY_CHANNEL_DMA,
+		0
+	};
+
+	return nv50_dmac_create(disp, oclass, head, &args, sizeof(args),
+				syncbuf, &ovly->base);
+}
 
 struct nv50_head {
 	struct nouveau_crtc base;
@@ -369,13 +359,19 @@ struct nv50_head {
 #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) nv_mclass(nv50_chan(c)->user)
+#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 nouveau_object *core;
+	struct nvif_object *disp;
 	struct nv50_mast mast;
 
-	u32 modeset;
+	struct list_head fbdma;
 
 	struct nouveau_bo *sync;
 };
@@ -401,16 +397,16 @@ static u32 *
 evo_wait(void *evoc, int nr)
 {
 	struct nv50_dmac *dmac = evoc;
-	u32 put = nv_ro32(dmac->base.user, 0x0000) / 4;
+	u32 put = nvif_rd32(&dmac->base.user, 0x0000) / 4;
 
 	mutex_lock(&dmac->lock);
 	if (put + nr >= (PAGE_SIZE / 4) - 8) {
 		dmac->ptr[put] = 0x20000000;
 
-		nv_wo32(dmac->base.user, 0x0000, 0x00000000);
-		if (!nv_wait(dmac->base.user, 0x0004, ~0, 0x00000000)) {
+		nvif_wr32(&dmac->base.user, 0x0000, 0x00000000);
+		if (!nvkm_wait(&dmac->base.user, 0x0004, ~0, 0x00000000)) {
 			mutex_unlock(&dmac->lock);
-			NV_ERROR(dmac->base.user, "channel stalled\n");
+			nv_error(nvkm_object(&dmac->base.user), "channel stalled\n");
 			return NULL;
 		}
 
@@ -424,7 +420,7 @@ static void
 evo_kick(u32 *push, void *evoc)
 {
 	struct nv50_dmac *dmac = evoc;
-	nv_wo32(dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
+	nvif_wr32(&dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
 	mutex_unlock(&dmac->lock);
 }
 
@@ -443,7 +439,7 @@ evo_sync_wait(void *data)
 static int
 evo_sync(struct drm_device *dev)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	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);
@@ -455,7 +451,7 @@ evo_sync(struct drm_device *dev)
 		evo_data(push, 0x00000000);
 		evo_data(push, 0x00000000);
 		evo_kick(push, mast);
-		if (nv_wait_cb(device, evo_sync_wait, disp->sync))
+		if (nv_wait_cb(nvkm_device(device), evo_sync_wait, disp->sync))
 			return 0;
 	}
 
@@ -490,7 +486,7 @@ nv50_display_flip_wait(void *data)
 void
 nv50_display_flip_stop(struct drm_crtc *crtc)
 {
-	struct nouveau_device *device = nouveau_dev(crtc->dev);
+	struct nvif_device *device = &nouveau_drm(crtc->dev)->device;
 	struct nv50_display_flip flip = {
 		.disp = nv50_disp(crtc->dev),
 		.chan = nv50_sync(crtc),
@@ -510,7 +506,7 @@ nv50_display_flip_stop(struct drm_crtc *
 		evo_kick(push, flip.chan);
 	}
 
-	nv_wait_cb(device, nv50_display_flip_wait, &flip);
+	nv_wait_cb(nvkm_device(device), nv50_display_flip_wait, &flip);
 }
 
 int
@@ -534,7 +530,7 @@ nv50_display_flip_next(struct drm_crtc *
 	if (unlikely(push == NULL))
 		return -EBUSY;
 
-	if (chan && nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) {
+	if (chan && chan->object->oclass < G82_CHANNEL_GPFIFO) {
 		ret = RING_SPACE(chan, 8);
 		if (ret)
 			return ret;
@@ -548,14 +544,14 @@ nv50_display_flip_next(struct drm_crtc *
 		OUT_RING  (chan, sync->addr);
 		OUT_RING  (chan, sync->data);
 	} else
-	if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
+	if (chan && chan->object->oclass < FERMI_CHANNEL_GPFIFO) {
 		u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
 		ret = RING_SPACE(chan, 12);
 		if (ret)
 			return ret;
 
 		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
-		OUT_RING  (chan, chan->vram);
+		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));
@@ -606,16 +602,16 @@ nv50_display_flip_next(struct drm_crtc *
 	evo_data(push, sync->addr);
 	evo_data(push, sync->data++);
 	evo_data(push, sync->data);
-	evo_data(push, NvEvoSync);
+	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_dma);
+	evo_data(push, nv_fb->r_handle);
 	evo_mthd(push, 0x0110, 2);
 	evo_data(push, 0x00000000);
 	evo_data(push, 0x00000000);
-	if (nv50_vers(sync) < NVD0_DISP_SYNC_CLASS) {
+	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);
@@ -667,11 +663,11 @@ nv50_crtc_set_dither(struct nouveau_crtc
 
 	push = evo_wait(mast, 4);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		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) < NVE0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GK104_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0490 + (nv_crtc->index * 0x0300), 1);
 			evo_data(push, mode);
 		} else {
@@ -762,7 +758,7 @@ nv50_crtc_set_scale(struct nouveau_crtc
 
 	push = evo_wait(mast, 8);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		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);
@@ -807,7 +803,7 @@ nv50_crtc_set_color_vibrance(struct nouv
 
 	push = evo_wait(mast, 16);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		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 {
@@ -835,7 +831,7 @@ nv50_crtc_set_image(struct nouveau_crtc
 
 	push = evo_wait(mast, 16);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		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);
@@ -844,9 +840,9 @@ nv50_crtc_set_image(struct nouveau_crtc
 			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_MAST_CLASS) {
+			if (nv50_vers(mast) > NV50_DISP_CORE_CHANNEL_DMA) {
 				evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-				evo_data(push, nvfb->r_dma);
+				evo_data(push, nvfb->r_handle);
 			}
 		} else {
 			evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
@@ -855,7 +851,7 @@ nv50_crtc_set_image(struct nouveau_crtc
 			evo_data(push, (fb->height << 16) | fb->width);
 			evo_data(push, nvfb->r_pitch);
 			evo_data(push, nvfb->r_format);
-			evo_data(push, nvfb->r_dma);
+			evo_data(push, nvfb->r_handle);
 			evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
 			evo_data(push, (y << 16) | x);
 		}
@@ -867,7 +863,7 @@ nv50_crtc_set_image(struct nouveau_crtc
 		evo_kick(push, mast);
 	}
 
-	nv_crtc->fb.tile_flags = nvfb->r_dma;
+	nv_crtc->fb.handle = nvfb->r_handle;
 	return 0;
 }
 
@@ -877,23 +873,23 @@ nv50_crtc_cursor_show(struct nouveau_crt
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
 	u32 *push = evo_wait(mast, 16);
 	if (push) {
-		if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+		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) < NVD0_DISP_MAST_CLASS) {
+		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, NvEvoVRAM);
+			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, NvEvoVRAM);
+			evo_data(push, mast->base.vram.handle);
 		}
 		evo_kick(push, mast);
 	}
@@ -905,11 +901,11 @@ nv50_crtc_cursor_hide(struct nouveau_crt
 	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
 	u32 *push = evo_wait(mast, 16);
 	if (push) {
-		if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
 			evo_data(push, 0x05000000);
 		} else
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
 			evo_data(push, 0x05000000);
 			evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
@@ -960,13 +956,13 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
 
 	push = evo_wait(mast, 6);
 	if (push) {
-		if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+		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);
 			evo_data(push, 0x40000000);
 		} else
-		if (nv50_vers(mast) <  NVD0_DISP_MAST_CLASS) {
+		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);
@@ -997,31 +993,31 @@ nv50_crtc_commit(struct drm_crtc *crtc)
 
 	push = evo_wait(mast, 32);
 	if (push) {
-		if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, NvEvoVRAM_LP);
+			evo_data(push, nv_crtc->fb.handle);
 			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
 			evo_data(push, 0xc0000000);
 			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
 		} else
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, nv_crtc->fb.tile_flags);
+			evo_data(push, nv_crtc->fb.handle);
 			evo_mthd(push, 0x0840 + (nv_crtc->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, NvEvoVRAM);
+			evo_data(push, mast->base.vram.handle);
 		} else {
 			evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, nv_crtc->fb.tile_flags);
+			evo_data(push, nv_crtc->fb.handle);
 			evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
 			evo_data(push, 0x83000000);
 			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
 			evo_data(push, 0x00000000);
 			evo_data(push, 0x00000000);
 			evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
-			evo_data(push, NvEvoVRAM);
+			evo_data(push, mast->base.vram.handle);
 			evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
 			evo_data(push, 0xffffff00);
 		}
@@ -1099,7 +1095,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc
 
 	push = evo_wait(mast, 64);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		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);
@@ -1192,7 +1188,7 @@ nv50_crtc_lut_load(struct drm_crtc *crtc
 		u16 g = nv_crtc->lut.g[i] >> 2;
 		u16 b = nv_crtc->lut.b[i] >> 2;
 
-		if (nv_mclass(disp->core) < NVD0_DISP_CLASS) {
+		if (disp->disp->oclass < GF110_DISP) {
 			writew(r + 0x0000, lut + (i * 0x08) + 0);
 			writew(g + 0x0000, lut + (i * 0x08) + 2);
 			writew(b + 0x0000, lut + (i * 0x08) + 4);
@@ -1259,8 +1255,8 @@ nv50_crtc_cursor_move(struct drm_crtc *c
 {
 	struct nv50_curs *curs = nv50_curs(crtc);
 	struct nv50_chan *chan = nv50_chan(curs);
-	nv_wo32(chan->user, 0x0084, (y << 16) | (x & 0xffff));
-	nv_wo32(chan->user, 0x0080, 0x00000000);
+	nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
+	nvif_wr32(&chan->user, 0x0080, 0x00000000);
 	return 0;
 }
 
@@ -1287,11 +1283,16 @@ nv50_crtc_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;
 
-	nv50_dmac_destroy(disp->core, &head->ovly.base);
-	nv50_pioc_destroy(disp->core, &head->oimm.base);
-	nv50_dmac_destroy(disp->core, &head->sync.base);
-	nv50_pioc_destroy(disp->core, &head->curs.base);
+	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
@@ -1346,7 +1347,7 @@ nv50_cursor_set_offset(struct nouveau_cr
 }
 
 static int
-nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
+nv50_crtc_create(struct drm_device *dev, int index)
 {
 	struct nv50_disp *disp = nv50_disp(dev);
 	struct nv50_head *head;
@@ -1395,11 +1396,7 @@ nv50_crtc_create(struct drm_device *dev,
 	nv50_crtc_lut_load(crtc);
 
 	/* allocate cursor resources */
-	ret = nv50_pioc_create(disp->core, NV50_DISP_CURS_CLASS, index,
-			      &(struct nv50_display_curs_class) {
-					.head = index,
-			      }, sizeof(struct nv50_display_curs_class),
-			      &head->curs.base);
+	ret = nv50_curs_create(disp->disp, index, &head->curs);
 	if (ret)
 		goto out;
 
@@ -1420,12 +1417,8 @@ nv50_crtc_create(struct drm_device *dev,
 		goto out;
 
 	/* allocate page flip / sync resources */
-	ret = nv50_dmac_create(disp->core, NV50_DISP_SYNC_CLASS, index,
-			      &(struct nv50_display_sync_class) {
-					.pushbuf = EVO_PUSH_HANDLE(SYNC, index),
-					.head = index,
-			      }, sizeof(struct nv50_display_sync_class),
-			      disp->sync->bo.offset, &head->sync.base);
+	ret = nv50_base_create(disp->disp, index, disp->sync->bo.offset,
+			      &head->sync);
 	if (ret)
 		goto out;
 
@@ -1433,20 +1426,12 @@ nv50_crtc_create(struct drm_device *dev,
 	head->sync.data = 0x00000000;
 
 	/* allocate overlay resources */
-	ret = nv50_pioc_create(disp->core, NV50_DISP_OIMM_CLASS, index,
-			      &(struct nv50_display_oimm_class) {
-					.head = index,
-			      }, sizeof(struct nv50_display_oimm_class),
-			      &head->oimm.base);
+	ret = nv50_oimm_create(disp->disp, index, &head->oimm);
 	if (ret)
 		goto out;
 
-	ret = nv50_dmac_create(disp->core, NV50_DISP_OVLY_CLASS, index,
-			      &(struct nv50_display_ovly_class) {
-					.pushbuf = EVO_PUSH_HANDLE(OVLY, index),
-					.head = index,
-			      }, sizeof(struct nv50_display_ovly_class),
-			      disp->sync->bo.offset, &head->ovly.base);
+	ret = nv50_ovly_create(disp->disp, index, disp->sync->bo.offset,
+			      &head->ovly);
 	if (ret)
 		goto out;
 
@@ -1464,16 +1449,23 @@ nv50_dac_dpms(struct drm_encoder *encode
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	int or = nv_encoder->or;
-	u32 dpms_ctrl;
-
-	dpms_ctrl = 0x00000000;
-	if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
-		dpms_ctrl |= 0x00000001;
-	if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
-		dpms_ctrl |= 0x00000004;
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_dac_pwr_v0 pwr;
+	} args = {
+		.base.version = 1,
+		.base.method = NV50_DISP_MTHD_V1_DAC_PWR,
+		.base.hasht  = nv_encoder->dcb->hasht,
+		.base.hashm  = nv_encoder->dcb->hashm,
+		.pwr.state = 1,
+		.pwr.data  = 1,
+		.pwr.vsync = (mode != DRM_MODE_DPMS_SUSPEND &&
+			      mode != DRM_MODE_DPMS_OFF),
+		.pwr.hsync = (mode != DRM_MODE_DPMS_STANDBY &&
+			      mode != DRM_MODE_DPMS_OFF),
+	};
 
-	nv_call(disp->core, NV50_DISP_DAC_PWR + or, dpms_ctrl);
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
 static bool
@@ -1514,7 +1506,7 @@ nv50_dac_mode_set(struct drm_encoder *en
 
 	push = evo_wait(mast, 8);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			u32 syncs = 0x00000000;
 
 			if (mode->flags & DRM_MODE_FLAG_NHSYNC)
@@ -1563,7 +1555,7 @@ nv50_dac_disconnect(struct drm_encoder *
 
 		push = evo_wait(mast, 4);
 		if (push) {
-			if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 				evo_mthd(push, 0x0400 + (or * 0x080), 1);
 				evo_data(push, 0x00000000);
 			} else {
@@ -1580,14 +1572,25 @@ nv50_dac_disconnect(struct drm_encoder *
 static enum drm_connector_status
 nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	int ret, or = nouveau_encoder(encoder)->or;
-	u32 load = nouveau_drm(encoder->dev)->vbios.dactestval;
-	if (load == 0)
-		load = 340;
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_dac_load_v0 load;
+	} args = {
+		.base.version = 1,
+		.base.method = NV50_DISP_MTHD_V1_DAC_LOAD,
+		.base.hasht  = nv_encoder->dcb->hasht,
+		.base.hashm  = nv_encoder->dcb->hashm,
+	};
+	int ret;
 
-	ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
-	if (ret || !load)
+	args.load.data = nouveau_drm(encoder->dev)->vbios.dactestval;
+	if (args.load.data == 0)
+		args.load.data = 340;
+
+	ret = nvif_mthd(disp->disp, 0, &args, sizeof(args));
+	if (ret || !args.load.load)
 		return connector_status_disconnected;
 
 	return connector_status_connected;
@@ -1619,7 +1622,7 @@ static int
 nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
 	int type = DRM_MODE_ENCODER_DAC;
@@ -1650,16 +1653,25 @@ nv50_audio_mode_set(struct drm_encoder *
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_connector *nv_connector;
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_hda_eld_v0 eld;
+		u8 data[sizeof(nv_connector->base.eld)];
+	} args = {
+		.base.version = 1,
+		.base.method  = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
+		.base.hasht   = nv_encoder->dcb->hasht,
+		.base.hashm   = nv_encoder->dcb->hashm,
+	};
 
 	nv_connector = nouveau_encoder_connector_get(nv_encoder);
 	if (!drm_detect_monitor_audio(nv_connector->edid))
 		return;
 
 	drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
+	memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
 
-	nv_exec(disp->core, NVA3_DISP_SOR_HDA_ELD + nv_encoder->or,
-			    nv_connector->base.eld,
-			    nv_connector->base.eld[2] * 4);
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
 static void
@@ -1667,8 +1679,17 @@ nv50_audio_disconnect(struct drm_encoder
 {
 	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   = nv_encoder->dcb->hashm,
+	};
 
-	nv_exec(disp->core, NVA3_DISP_SOR_HDA_ELD + nv_encoder->or, NULL, 0);
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
 /******************************************************************************
@@ -1679,10 +1700,20 @@ nv50_hdmi_mode_set(struct drm_encoder *e
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
-	struct nouveau_connector *nv_connector;
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	const u32 moff = (nv_crtc->index << 3) | nv_encoder->or;
-	u32 rekey = 56; /* binary driver, and tegra constant */
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+	} 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),
+		.pwr.state = 1,
+		.pwr.rekey = 56, /* binary driver, and tegra, constant */
+	};
+	struct nouveau_connector *nv_connector;
 	u32 max_ac_packet;
 
 	nv_connector = nouveau_encoder_connector_get(nv_encoder);
@@ -1690,14 +1721,11 @@ nv50_hdmi_mode_set(struct drm_encoder *e
 		return;
 
 	max_ac_packet  = mode->htotal - mode->hdisplay;
-	max_ac_packet -= rekey;
+	max_ac_packet -= args.pwr.rekey;
 	max_ac_packet -= 18; /* constant from tegra */
-	max_ac_packet /= 32;
-
-	nv_call(disp->core, NV84_DISP_SOR_HDMI_PWR + moff,
-			    NV84_DISP_SOR_HDMI_PWR_STATE_ON |
-			    (max_ac_packet << 16) | rekey);
+	args.pwr.max_ac_packet = max_ac_packet / 32;
 
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 	nv50_audio_mode_set(encoder, mode);
 }
 
@@ -1706,11 +1734,20 @@ nv50_hdmi_disconnect(struct drm_encoder
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	const u32 moff = (nv_crtc->index << 3) | nv_encoder->or;
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+	} 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),
+	};
 
 	nv50_audio_disconnect(encoder);
 
-	nv_call(disp->core, NV84_DISP_SOR_HDMI_PWR + moff, 0x00000000);
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
 /******************************************************************************
@@ -1720,10 +1757,29 @@ static void
 nv50_sor_dpms(struct drm_encoder *encoder, int mode)
 {
 	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_pwr_v0 pwr;
+	} args = {
+		.base.version = 1,
+		.base.method = NV50_DISP_MTHD_V1_SOR_PWR,
+		.base.hasht  = nv_encoder->dcb->hasht,
+		.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 nv50_disp *disp = nv50_disp(dev);
 	struct drm_encoder *partner;
-	u32 mthd;
 
 	nv_encoder->last_dpms = mode;
 
@@ -1741,18 +1797,13 @@ nv50_sor_dpms(struct drm_encoder *encode
 		}
 	}
 
-	mthd  = (ffs(nv_encoder->dcb->heads) - 1) << 3;
-	mthd |= (ffs(nv_encoder->dcb->sorconf.link) - 1) << 2;
-	mthd |= nv_encoder->or;
-
 	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
-		nv_call(disp->core, NV50_DISP_SOR_PWR | mthd, 1);
-		mthd |= NV94_DISP_SOR_DP_PWR;
+		args.pwr.state = 1;
+		nvif_mthd(disp->disp, 0, &args, sizeof(args));
+		nvif_mthd(disp->disp, 0, &link, sizeof(link));
 	} else {
-		mthd |= NV50_DISP_SOR_PWR;
+		nvif_mthd(disp->disp, 0, &args, sizeof(args));
 	}
-
-	nv_call(disp->core, mthd, (mode == DRM_MODE_DPMS_ON));
 }
 
 static bool
@@ -1781,7 +1832,7 @@ nv50_sor_ctrl(struct nouveau_encoder *nv
 	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) < NVD0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1);
 			evo_data(push, (nv_encoder->ctrl = temp));
 		} else {
@@ -1817,15 +1868,24 @@ static void
 nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
 		  struct drm_display_mode *mode)
 {
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_lvds_script_v0 lvds;
+	} lvds = {
+		.base.version = 1,
+		.base.method  = NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT,
+		.base.hasht   = nv_encoder->dcb->hasht,
+		.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_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
 	struct nouveau_connector *nv_connector;
 	struct nvbios *bios = &drm->vbios;
-	u32 lvds = 0, mask, ctrl;
+	u32 mask, ctrl;
 	u8 owner = 1 << nv_crtc->index;
 	u8 proto = 0xf;
 	u8 depth = 0x0;
@@ -1851,31 +1911,31 @@ nv50_sor_mode_set(struct drm_encoder *en
 
 		if (bios->fp_no_ddc) {
 			if (bios->fp.dual_link)
-				lvds |= 0x0100;
+				lvds.lvds.script |= 0x0100;
 			if (bios->fp.if_is_24bit)
-				lvds |= 0x0200;
+				lvds.lvds.script |= 0x0200;
 		} else {
 			if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
 				if (((u8 *)nv_connector->edid)[121] == 2)
-					lvds |= 0x0100;
+					lvds.lvds.script |= 0x0100;
 			} else
 			if (mode->clock >= bios->fp.duallink_transition_clk) {
-				lvds |= 0x0100;
+				lvds.lvds.script |= 0x0100;
 			}
 
-			if (lvds & 0x0100) {
+			if (lvds.lvds.script & 0x0100) {
 				if (bios->fp.strapless_is_24bit & 2)
-					lvds |= 0x0200;
+					lvds.lvds.script |= 0x0200;
 			} else {
 				if (bios->fp.strapless_is_24bit & 1)
-					lvds |= 0x0200;
+					lvds.lvds.script |= 0x0200;
 			}
 
 			if (nv_connector->base.display_info.bpc == 8)
-				lvds |= 0x0200;
+				lvds.lvds.script |= 0x0200;
 		}
 
-		nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, lvds);
+		nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
 		break;
 	case DCB_OUTPUT_DP:
 		if (nv_connector->base.display_info.bpc == 6) {
@@ -1902,7 +1962,7 @@ nv50_sor_mode_set(struct drm_encoder *en
 
 	nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON);
 
-	if (nv50_vers(mast) >= NVD0_DISP_CLASS) {
+	if (nv50_vers(mast) >= GF110_DISP) {
 		u32 *push = evo_wait(mast, 3);
 		if (push) {
 			u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
@@ -1961,7 +2021,7 @@ static int
 nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
 	int type;
@@ -2002,9 +2062,19 @@ nv50_pior_dpms(struct drm_encoder *encod
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or;
-	u32 ctrl = (mode == DRM_MODE_DPMS_ON);
-	nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl);
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_pior_pwr_v0 pwr;
+	} args = {
+		.base.version = 1,
+		.base.method = NV50_DISP_MTHD_V1_PIOR_PWR,
+		.base.hasht  = nv_encoder->dcb->hasht,
+		.base.hashm  = nv_encoder->dcb->hashm,
+		.pwr.state = mode == DRM_MODE_DPMS_ON,
+		.pwr.type = nv_encoder->dcb->type,
+	};
+
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
 static bool
@@ -2067,7 +2137,7 @@ nv50_pior_mode_set(struct drm_encoder *e
 
 	push = evo_wait(mast, 8);
 	if (push) {
-		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 			u32 ctrl = (depth << 16) | (proto << 8) | owner;
 			if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 				ctrl |= 0x00001000;
@@ -2096,7 +2166,7 @@ nv50_pior_disconnect(struct drm_encoder
 
 		push = evo_wait(mast, 4);
 		if (push) {
-			if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
 				evo_mthd(push, 0x0700 + (or * 0x040), 1);
 				evo_data(push, 0x00000000);
 			}
@@ -2132,7 +2202,7 @@ static int
 nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+	struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
 	struct nouveau_i2c_port *ddc = NULL;
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
@@ -2169,8 +2239,151 @@ nv50_pior_create(struct drm_connector *c
 }
 
 /******************************************************************************
+ * Framebuffer
+ *****************************************************************************/
+
+static void
+nv50_fbdma_fini(struct nv50_fbdma *fbdma)
+{
+	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);
+}
+
+static int
+nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kind)
+{
+	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 gf110_dma_v0 gf110;
+		};
+	} args = {};
+	struct nv50_fbdma *fbdma;
+	struct drm_crtc *crtc;
+	u32 size = sizeof(args.base);
+	int ret;
+
+	list_for_each_entry(fbdma, &disp->fbdma, head) {
+		if (fbdma->core.handle == name)
+			return 0;
+	}
+
+	fbdma = kzalloc(sizeof(*fbdma), GFP_KERNEL);
+	if (!fbdma)
+		return -ENOMEM;
+	list_add(&fbdma->head, &disp->fbdma);
+
+	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;
+
+	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.gf110.page = GF110_DMA_V0_PAGE_LP;
+		args.gf110.kind = kind;
+		size += sizeof(args.gf110);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nv50_head *head = nv50_head(crtc);
+		int ret = nvif_object_init(&head->sync.base.base.user, NULL,
+					    name, NV_DMA_IN_MEMORY, &args, size,
+					   &fbdma->base[head->base.index]);
+		if (ret) {
+			nv50_fbdma_fini(fbdma);
+			return ret;
+		}
+	}
+
+	ret = nvif_object_init(&mast->base.base.user, NULL, name,
+				NV_DMA_IN_MEMORY, &args, size,
+			       &fbdma->core);
+	if (ret) {
+		nv50_fbdma_fini(fbdma);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void
+nv50_fb_dtor(struct drm_framebuffer *fb)
+{
+}
+
+static int
+nv50_fb_ctor(struct drm_framebuffer *fb)
+{
+	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;
+
+	if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
+		NV_ERROR(drm, "framebuffer requires contiguous bo\n");
+		return -EINVAL;
+	}
+
+	if (drm->device.info.chipset >= 0xc0)
+		tile >>= 4; /* yep.. */
+
+	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;
+	}
+
+	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);
+	}
+	nv_fb->r_handle = 0xffff0000 | kind;
+
+	return nv50_fbdma_init(fb->dev, nv_fb->r_handle, 0,
+			       drm->device.info.ram_user, kind);
+}
+
+/******************************************************************************
  * Init
  *****************************************************************************/
+
 void
 nv50_display_fini(struct drm_device *dev)
 {
@@ -2193,7 +2406,7 @@ nv50_display_init(struct drm_device *dev
 	}
 
 	evo_mthd(push, 0x0088, 1);
-	evo_data(push, NvEvoSync);
+	evo_data(push, nv50_mast(dev)->base.sync.handle);
 	evo_kick(push, nv50_mast(dev));
 	return 0;
 }
@@ -2202,8 +2415,13 @@ void
 nv50_display_destroy(struct drm_device *dev)
 {
 	struct nv50_disp *disp = nv50_disp(dev);
+	struct nv50_fbdma *fbdma, *fbtmp;
 
-	nv50_dmac_destroy(disp->core, &disp->mast.base);
+	list_for_each_entry_safe(fbdma, fbtmp, &disp->fbdma, head) {
+		nv50_fbdma_fini(fbdma);
+	}
+
+	nv50_dmac_destroy(&disp->mast.base, disp->disp);
 
 	nouveau_bo_unmap(disp->sync);
 	if (disp->sync)
@@ -2217,7 +2435,7 @@ nv50_display_destroy(struct drm_device *
 int
 nv50_display_create(struct drm_device *dev)
 {
-	struct nouveau_device *device = nouveau_dev(dev);
+	struct nvif_device *device = &nouveau_drm(dev)->device;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct dcb_table *dcb = &drm->vbios.dcb;
 	struct drm_connector *connector, *tmp;
@@ -2228,12 +2446,15 @@ nv50_display_create(struct drm_device *d
 	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
 	if (!disp)
 		return -ENOMEM;
+	INIT_LIST_HEAD(&disp->fbdma);
 
 	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;
-	disp->core = nouveau_display(dev)->core;
+	nouveau_display(dev)->fb_ctor = nv50_fb_ctor;
+	nouveau_display(dev)->fb_dtor = nv50_fb_dtor;
+	disp->disp = &nouveau_display(dev)->disp;
 
 	/* small shared memory area we use for notifiers and semaphores */
 	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2253,22 +2474,19 @@ nv50_display_create(struct drm_device *d
 		goto out;
 
 	/* allocate master evo channel */
-	ret = nv50_dmac_create(disp->core, NV50_DISP_MAST_CLASS, 0,
-			      &(struct nv50_display_mast_class) {
-					.pushbuf = EVO_PUSH_HANDLE(MAST, 0),
-			      }, sizeof(struct nv50_display_mast_class),
-			      disp->sync->bo.offset, &disp->mast.base);
+	ret = nv50_core_create(disp->disp, disp->sync->bo.offset,
+			      &disp->mast);
 	if (ret)
 		goto out;
 
 	/* create crtc objects to represent the hw heads */
-	if (nv_mclass(disp->core) >= NVD0_DISP_CLASS)
-		crtcs = nv_rd32(device, 0x022448);
+	if (disp->disp->oclass >= GF110_DISP)
+		crtcs = nvif_rd32(device, 0x022448);
 	else
 		crtcs = 2;
 
 	for (i = 0; i < crtcs; i++) {
-		ret = nv50_crtc_create(dev, disp->core, i);
+		ret = nv50_crtc_create(dev, i);
 		if (ret)
 			goto out;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -154,7 +154,6 @@ nv50_fbcon_accel_init(struct fb_info *in
 	struct drm_device *dev = nfbdev->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
-	struct nouveau_object *object;
 	int ret, format;
 
 	switch (info->var.bits_per_pixel) {
@@ -184,8 +183,8 @@ nv50_fbcon_accel_init(struct fb_info *in
 		return -EINVAL;
 	}
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D,
-				 0x502d, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x502d, 0x502d, NULL, 0,
+			       &nfbdev->twod);
 	if (ret)
 		return ret;
 
@@ -196,11 +195,11 @@ nv50_fbcon_accel_init(struct fb_info *in
 	}
 
 	BEGIN_NV04(chan, NvSub2D, 0x0000, 1);
-	OUT_RING(chan, Nv2D);
+	OUT_RING(chan, nfbdev->twod.handle);
 	BEGIN_NV04(chan, NvSub2D, 0x0184, 3);
-	OUT_RING(chan, NvDmaFB);
-	OUT_RING(chan, NvDmaFB);
-	OUT_RING(chan, NvDmaFB);
+	OUT_RING(chan, chan->vram.handle);
+	OUT_RING(chan, chan->vram.handle);
+	OUT_RING(chan, chan->vram.handle);
 	BEGIN_NV04(chan, NvSub2D, 0x0290, 1);
 	OUT_RING(chan, 0);
 	BEGIN_NV04(chan, NvSub2D, 0x0888, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,8 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include <core/object.h>
-#include <core/class.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -38,7 +38,6 @@ nv50_fence_context_new(struct nouveau_ch
 	struct nv10_fence_priv *priv = chan->drm->fence;
 	struct nv10_fence_chan *fctx;
 	struct ttm_mem_reg *mem = &priv->bo->bo.mem;
-	struct nouveau_object *object;
 	u32 start = mem->start * PAGE_SIZE;
 	u32 limit = start + mem->size - 1;
 	int ret, i;
@@ -52,15 +51,14 @@ nv50_fence_context_new(struct nouveau_ch
 	fctx->base.read = nv10_fence_read;
 	fctx->base.sync = nv17_fence_sync;
 
-	ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
-				 NvSema, 0x003d,
-				 &(struct nv_dma_class) {
-					.flags = NV_DMA_TARGET_VRAM |
-						 NV_DMA_ACCESS_RDWR,
+	ret = nvif_object_init(chan->object, NULL, NvSema, 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_class),
-				 &object);
+			       }, 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++) {
@@ -68,15 +66,14 @@ nv50_fence_context_new(struct nouveau_ch
 		u32 start = bo->bo.mem.start * PAGE_SIZE;
 		u32 limit = start + bo->bo.mem.size - 1;
 
-		ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
-					 NvEvoSema0 + i, 0x003d,
-					 &(struct nv_dma_class) {
-						.flags = NV_DMA_TARGET_VRAM |
-							 NV_DMA_ACCESS_RDWR,
+		ret = nvif_object_init(chan->object, NULL, 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_class),
-					 &object);
+				       }, sizeof(struct nv_dma_v0),
+				       &fctx->head[i]);
 	}
 
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv84_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv84_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,12 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/object.h>
-#include <core/client.h>
-#include <core/class.h>
-
-#include <engine/fifo.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
@@ -47,7 +41,7 @@ nv84_fence_emit32(struct nouveau_channel
 	int ret = RING_SPACE(chan, 8);
 	if (ret == 0) {
 		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
-		OUT_RING  (chan, chan->vram);
+		OUT_RING  (chan, chan->vram.handle);
 		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
 		OUT_RING  (chan, upper_32_bits(virtual));
 		OUT_RING  (chan, lower_32_bits(virtual));
@@ -65,7 +59,7 @@ nv84_fence_sync32(struct nouveau_channel
 	int ret = RING_SPACE(chan, 7);
 	if (ret == 0) {
 		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
-		OUT_RING  (chan, chan->vram);
+		OUT_RING  (chan, chan->vram.handle);
 		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
 		OUT_RING  (chan, upper_32_bits(virtual));
 		OUT_RING  (chan, lower_32_bits(virtual));
@@ -81,8 +75,7 @@ nv84_fence_emit(struct nouveau_fence *fe
 {
 	struct nouveau_channel *chan = fence->channel;
 	struct nv84_fence_chan *fctx = chan->fence;
-	struct nouveau_fifo_chan *fifo = (void *)chan->object;
-	u64 addr = fifo->chid * 16;
+	u64 addr = chan->chid * 16;
 
 	if (fence->sysmem)
 		addr += fctx->vma_gart.offset;
@@ -97,8 +90,7 @@ nv84_fence_sync(struct nouveau_fence *fe
 		struct nouveau_channel *prev, struct nouveau_channel *chan)
 {
 	struct nv84_fence_chan *fctx = chan->fence;
-	struct nouveau_fifo_chan *fifo = (void *)prev->object;
-	u64 addr = fifo->chid * 16;
+	u64 addr = prev->chid * 16;
 
 	if (fence->sysmem)
 		addr += fctx->vma_gart.offset;
@@ -111,9 +103,8 @@ nv84_fence_sync(struct nouveau_fence *fe
 static u32
 nv84_fence_read(struct nouveau_channel *chan)
 {
-	struct nouveau_fifo_chan *fifo = (void *)chan->object;
 	struct nv84_fence_priv *priv = chan->drm->fence;
-	return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
+	return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
 }
 
 static void
@@ -139,8 +130,7 @@ nv84_fence_context_del(struct nouveau_ch
 int
 nv84_fence_context_new(struct nouveau_channel *chan)
 {
-	struct nouveau_fifo_chan *fifo = (void *)chan->object;
-	struct nouveau_client *client = nouveau_client(fifo);
+	struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
 	struct nv84_fence_priv *priv = chan->drm->fence;
 	struct nv84_fence_chan *fctx;
 	int ret, i;
@@ -156,19 +146,19 @@ nv84_fence_context_new(struct nouveau_ch
 	fctx->base.emit32 = nv84_fence_emit32;
 	fctx->base.sync32 = nv84_fence_sync32;
 
-	ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
+	ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
 	if (ret == 0) {
-		ret = nouveau_bo_vma_add(priv->bo_gart, client->vm,
+		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, client->vm, &fctx->dispc_vma[i]);
+		ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
 	}
 
-	nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
+	nouveau_bo_wr32(priv->bo, chan->chid * 16/4, 0x00000000);
 
 	if (ret)
 		nv84_fence_context_del(chan);
@@ -178,7 +168,7 @@ nv84_fence_context_new(struct nouveau_ch
 static bool
 nv84_fence_suspend(struct nouveau_drm *drm)
 {
-	struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+	struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
 	struct nv84_fence_priv *priv = drm->fence;
 	int i;
 
@@ -194,7 +184,7 @@ nv84_fence_suspend(struct nouveau_drm *d
 static void
 nv84_fence_resume(struct nouveau_drm *drm)
 {
-	struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+	struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
 	struct nv84_fence_priv *priv = drm->fence;
 	int i;
 
@@ -225,7 +215,7 @@ nv84_fence_destroy(struct nouveau_drm *d
 int
 nv84_fence_create(struct nouveau_drm *drm)
 {
-	struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+	struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
 	struct nv84_fence_priv *priv;
 	int ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -154,11 +154,10 @@ nvc0_fbcon_accel_init(struct fb_info *in
 	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
-	struct nouveau_object *object;
 	int ret, format;
 
-	ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D,
-				 0x902d, NULL, 0, &object);
+	ret = nvif_object_init(chan->object, NULL, 0x902d, 0x902d, NULL, 0,
+			       &nfbdev->twod);
 	if (ret)
 		return ret;
 
@@ -197,7 +196,7 @@ nvc0_fbcon_accel_init(struct fb_info *in
 	}
 
 	BEGIN_NVC0(chan, NvSub2D, 0x0000, 1);
-	OUT_RING  (chan, 0x0000902d);
+	OUT_RING  (chan, nfbdev->twod.handle);
 	BEGIN_NVC0(chan, NvSub2D, 0x0290, 1);
 	OUT_RING  (chan, 0);
 	BEGIN_NVC0(chan, NvSub2D, 0x0888, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,12 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#include <core/object.h>
-#include <core/client.h>
-#include <core/class.h>
-
-#include <engine/fifo.h>
-
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/class.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/class.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/class.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/class.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,558 @@
+#ifndef __NVIF_CLASS_H__
+#define __NVIF_CLASS_H__
+
+/*******************************************************************************
+ * class identifiers
+ ******************************************************************************/
+
+/* the below match nvidia-assigned (either in hw, or sw) class numbers */
+#define NV_DEVICE                                                    0x00000080
+
+#define NV_DMA_FROM_MEMORY                                           0x00000002
+#define NV_DMA_TO_MEMORY                                             0x00000003
+#define NV_DMA_IN_MEMORY                                             0x0000003d
+
+#define NV04_DISP                                                    0x00000046
+
+#define NV03_CHANNEL_DMA                                             0x0000006b
+#define NV10_CHANNEL_DMA                                             0x0000006e
+#define NV17_CHANNEL_DMA                                             0x0000176e
+#define NV40_CHANNEL_DMA                                             0x0000406e
+#define NV50_CHANNEL_DMA                                             0x0000506e
+#define G82_CHANNEL_DMA                                              0x0000826e
+
+#define NV50_CHANNEL_GPFIFO                                          0x0000506f
+#define G82_CHANNEL_GPFIFO                                           0x0000826f
+#define FERMI_CHANNEL_GPFIFO                                         0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A                                      0x0000a06f
+
+#define NV50_DISP                                                    0x00005070
+#define G82_DISP                                                     0x00008270
+#define GT200_DISP                                                   0x00008370
+#define GT214_DISP                                                   0x00008570
+#define GT206_DISP                                                   0x00008870
+#define GF110_DISP                                                   0x00009070
+#define GK104_DISP                                                   0x00009170
+#define GK110_DISP                                                   0x00009270
+#define GM107_DISP                                                   0x00009470
+
+#define NV50_DISP_CURSOR                                             0x0000507a
+#define G82_DISP_CURSOR                                              0x0000827a
+#define GT214_DISP_CURSOR                                            0x0000857a
+#define GF110_DISP_CURSOR                                            0x0000907a
+#define GK104_DISP_CURSOR                                            0x0000917a
+
+#define NV50_DISP_OVERLAY                                            0x0000507b
+#define G82_DISP_OVERLAY                                             0x0000827b
+#define GT214_DISP_OVERLAY                                           0x0000857b
+#define GF110_DISP_OVERLAY                                           0x0000907b
+#define GK104_DISP_OVERLAY                                           0x0000917b
+
+#define NV50_DISP_BASE_CHANNEL_DMA                                   0x0000507c
+#define G82_DISP_BASE_CHANNEL_DMA                                    0x0000827c
+#define GT200_DISP_BASE_CHANNEL_DMA                                  0x0000837c
+#define GT214_DISP_BASE_CHANNEL_DMA                                  0x0000857c
+#define GF110_DISP_BASE_CHANNEL_DMA                                  0x0000907c
+#define GK104_DISP_BASE_CHANNEL_DMA                                  0x0000917c
+#define GK110_DISP_BASE_CHANNEL_DMA                                  0x0000927c
+
+#define NV50_DISP_CORE_CHANNEL_DMA                                   0x0000507d
+#define G82_DISP_CORE_CHANNEL_DMA                                    0x0000827d
+#define GT200_DISP_CORE_CHANNEL_DMA                                  0x0000837d
+#define GT214_DISP_CORE_CHANNEL_DMA                                  0x0000857d
+#define GT206_DISP_CORE_CHANNEL_DMA                                  0x0000887d
+#define GF110_DISP_CORE_CHANNEL_DMA                                  0x0000907d
+#define GK104_DISP_CORE_CHANNEL_DMA                                  0x0000917d
+#define GK110_DISP_CORE_CHANNEL_DMA                                  0x0000927d
+#define GM107_DISP_CORE_CHANNEL_DMA                                  0x0000947d
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA                                0x0000507e
+#define G82_DISP_OVERLAY_CHANNEL_DMA                                 0x0000827e
+#define GT200_DISP_OVERLAY_CHANNEL_DMA                               0x0000837e
+#define GT214_DISP_OVERLAY_CHANNEL_DMA                               0x0000857e
+#define GF110_DISP_OVERLAY_CONTROL_DMA                               0x0000907e
+#define GK104_DISP_OVERLAY_CONTROL_DMA                               0x0000917e
+
+#define FERMI_A                                                      0x00009097
+#define FERMI_B                                                      0x00009197
+#define FERMI_C                                                      0x00009297
+
+#define KEPLER_A                                                     0x0000a097
+#define KEPLER_B                                                     0x0000a197
+#define KEPLER_C                                                     0x0000a297
+
+#define MAXWELL_A                                                    0x0000b097
+
+#define FERMI_COMPUTE_A                                              0x000090c0
+#define FERMI_COMPUTE_B                                              0x000091c0
+
+#define KEPLER_COMPUTE_A                                             0x0000a0c0
+#define KEPLER_COMPUTE_B                                             0x0000a1c0
+
+#define MAXWELL_COMPUTE_A                                            0x0000b0c0
+
+
+/*******************************************************************************
+ * client
+ ******************************************************************************/
+
+#define NV_CLIENT_DEVLIST                                                  0x00
+
+struct nv_client_devlist_v0 {
+	__u8  version;
+	__u8  count;
+	__u8  pad02[6];
+	__u64 device[];
+};
+
+
+/*******************************************************************************
+ * device
+ ******************************************************************************/
+
+struct nv_device_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u64 device;	/* device identifier, ~0 for client default */
+#define NV_DEVICE_V0_DISABLE_IDENTIFY                     0x0000000000000001ULL
+#define NV_DEVICE_V0_DISABLE_MMIO                         0x0000000000000002ULL
+#define NV_DEVICE_V0_DISABLE_VBIOS                        0x0000000000000004ULL
+#define NV_DEVICE_V0_DISABLE_CORE                         0x0000000000000008ULL
+#define NV_DEVICE_V0_DISABLE_DISP                         0x0000000000010000ULL
+#define NV_DEVICE_V0_DISABLE_FIFO                         0x0000000000020000ULL
+#define NV_DEVICE_V0_DISABLE_GRAPH                        0x0000000100000000ULL
+#define NV_DEVICE_V0_DISABLE_MPEG                         0x0000000200000000ULL
+#define NV_DEVICE_V0_DISABLE_ME                           0x0000000400000000ULL
+#define NV_DEVICE_V0_DISABLE_VP                           0x0000000800000000ULL
+#define NV_DEVICE_V0_DISABLE_CRYPT                        0x0000001000000000ULL
+#define NV_DEVICE_V0_DISABLE_BSP                          0x0000002000000000ULL
+#define NV_DEVICE_V0_DISABLE_PPP                          0x0000004000000000ULL
+#define NV_DEVICE_V0_DISABLE_COPY0                        0x0000008000000000ULL
+#define NV_DEVICE_V0_DISABLE_COPY1                        0x0000010000000000ULL
+#define NV_DEVICE_V0_DISABLE_VIC                          0x0000020000000000ULL
+#define NV_DEVICE_V0_DISABLE_VENC                         0x0000040000000000ULL
+	__u64 disable;	/* disable particular subsystems */
+	__u64 debug0;	/* as above, but *internal* ids, and *NOT* ABI */
+};
+
+#define NV_DEVICE_V0_INFO                                                  0x00
+
+struct nv_device_info_v0 {
+	__u8  version;
+#define NV_DEVICE_INFO_V0_IGP                                              0x00
+#define NV_DEVICE_INFO_V0_PCI                                              0x01
+#define NV_DEVICE_INFO_V0_AGP                                              0x02
+#define NV_DEVICE_INFO_V0_PCIE                                             0x03
+#define NV_DEVICE_INFO_V0_SOC                                              0x04
+	__u8  platform;
+	__u16 chipset;	/* from NV_PMC_BOOT_0 */
+	__u8  revision;	/* from NV_PMC_BOOT_0 */
+#define NV_DEVICE_INFO_V0_TNT                                              0x01
+#define NV_DEVICE_INFO_V0_CELSIUS                                          0x02
+#define NV_DEVICE_INFO_V0_KELVIN                                           0x03
+#define NV_DEVICE_INFO_V0_RANKINE                                          0x04
+#define NV_DEVICE_INFO_V0_CURIE                                            0x05
+#define NV_DEVICE_INFO_V0_TESLA                                            0x06
+#define NV_DEVICE_INFO_V0_FERMI                                            0x07
+#define NV_DEVICE_INFO_V0_KEPLER                                           0x08
+#define NV_DEVICE_INFO_V0_MAXWELL                                          0x09
+	__u8  family;
+	__u8  pad06[2];
+	__u64 ram_size;
+	__u64 ram_user;
+};
+
+
+/*******************************************************************************
+ * context dma
+ ******************************************************************************/
+
+struct nv_dma_v0 {
+	__u8  version;
+#define NV_DMA_V0_TARGET_VM                                                0x00
+#define NV_DMA_V0_TARGET_VRAM                                              0x01
+#define NV_DMA_V0_TARGET_PCI                                               0x02
+#define NV_DMA_V0_TARGET_PCI_US                                            0x03
+#define NV_DMA_V0_TARGET_AGP                                               0x04
+	__u8  target;
+#define NV_DMA_V0_ACCESS_VM                                                0x00
+#define NV_DMA_V0_ACCESS_RD                                                0x01
+#define NV_DMA_V0_ACCESS_WR                                                0x02
+#define NV_DMA_V0_ACCESS_RDWR                 (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
+	__u8  access;
+	__u8  pad03[5];
+	__u64 start;
+	__u64 limit;
+	/* ... chipset-specific class data */
+};
+
+struct nv50_dma_v0 {
+	__u8  version;
+#define NV50_DMA_V0_PRIV_VM                                                0x00
+#define NV50_DMA_V0_PRIV_US                                                0x01
+#define NV50_DMA_V0_PRIV__S                                                0x02
+	__u8  priv;
+#define NV50_DMA_V0_PART_VM                                                0x00
+#define NV50_DMA_V0_PART_256                                               0x01
+#define NV50_DMA_V0_PART_1KB                                               0x02
+	__u8  part;
+#define NV50_DMA_V0_COMP_NONE                                              0x00
+#define NV50_DMA_V0_COMP_1                                                 0x01
+#define NV50_DMA_V0_COMP_2                                                 0x02
+#define NV50_DMA_V0_COMP_VM                                                0x03
+	__u8  comp;
+#define NV50_DMA_V0_KIND_PITCH                                             0x00
+#define NV50_DMA_V0_KIND_VM                                                0x7f
+	__u8  kind;
+	__u8  pad05[3];
+};
+
+struct gf100_dma_v0 {
+	__u8  version;
+#define GF100_DMA_V0_PRIV_VM                                               0x00
+#define GF100_DMA_V0_PRIV_US                                               0x01
+#define GF100_DMA_V0_PRIV__S                                               0x02
+	__u8  priv;
+#define GF100_DMA_V0_KIND_PITCH                                            0x00
+#define GF100_DMA_V0_KIND_VM                                               0xff
+	__u8  kind;
+	__u8  pad03[5];
+};
+
+struct gf110_dma_v0 {
+	__u8  version;
+#define GF110_DMA_V0_PAGE_LP                                               0x00
+#define GF110_DMA_V0_PAGE_SP                                               0x01
+	__u8  page;
+#define GF110_DMA_V0_KIND_PITCH                                            0x00
+#define GF110_DMA_V0_KIND_VM                                               0xff
+	__u8  kind;
+	__u8  pad03[5];
+};
+
+
+/*******************************************************************************
+ * perfmon
+ ******************************************************************************/
+
+struct nvif_perfctr_v0 {
+	__u8  version;
+	__u8  pad01[1];
+	__u16 logic_op;
+	__u8  pad04[4];
+	char  name[4][64];
+};
+
+#define NVIF_PERFCTR_V0_QUERY                                              0x00
+#define NVIF_PERFCTR_V0_SAMPLE                                             0x01
+#define NVIF_PERFCTR_V0_READ                                               0x02
+
+struct nvif_perfctr_query_v0 {
+	__u8  version;
+	__u8  pad01[3];
+	__u32 iter;
+	char  name[64];
+};
+
+struct nvif_perfctr_sample {
+};
+
+struct nvif_perfctr_read_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u32 ctr;
+	__u32 clk;
+};
+
+
+/*******************************************************************************
+ * device control
+ ******************************************************************************/
+
+#define NVIF_CONTROL_PSTATE_INFO                                           0x00
+#define NVIF_CONTROL_PSTATE_ATTR                                           0x01
+#define NVIF_CONTROL_PSTATE_USER                                           0x02
+
+struct nvif_control_pstate_info_v0 {
+	__u8  version;
+	__u8  count; /* out: number of power states */
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE                         (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON                         (-2)
+	__s8  ustate_ac; /* out: target pstate index */
+	__s8  ustate_dc; /* out: target pstate index */
+	__s8  pwrsrc; /* out: current power source */
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN                         (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON                         (-2)
+	__s8  pstate; /* out: current pstate index */
+	__u8  pad06[2];
+};
+
+struct nvif_control_pstate_attr_v0 {
+	__u8  version;
+#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT                          (-1)
+	__s8  state; /*  in: index of pstate to query
+		      * out: pstate identifier
+		      */
+	__u8  index; /*  in: index of attribute to query
+		      * out: index of next attribute, or 0 if no more
+		      */
+	__u8  pad03[5];
+	__u32 min;
+	__u32 max;
+	char  name[32];
+	char  unit[16];
+};
+
+struct nvif_control_pstate_user_v0 {
+	__u8  version;
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN                          (-1)
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON                          (-2)
+	__s8  ustate; /*  in: pstate identifier */
+	__s8  pwrsrc; /*  in: target power source */
+	__u8  pad03[5];
+};
+
+
+/*******************************************************************************
+ * DMA FIFO channels
+ ******************************************************************************/
+
+struct nv03_channel_dma_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[2];
+	__u32 pushbuf;
+	__u64 offset;
+};
+
+#define G82_CHANNEL_DMA_V0_NTFY_UEVENT                                     0x00
+
+/*******************************************************************************
+ * GPFIFO channels
+ ******************************************************************************/
+
+struct nv50_channel_gpfifo_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad01[6];
+	__u32 pushbuf;
+	__u32 ilength;
+	__u64 ioffset;
+};
+
+struct kepler_channel_gpfifo_a_v0 {
+	__u8  version;
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR                               0x01
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_VP                               0x02
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_PPP                              0x04
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_BSP                              0x08
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0                              0x10
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1                              0x20
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC                              0x40
+	__u8  engine;
+	__u16 chid;
+	__u8  pad04[4];
+	__u32 pushbuf;
+	__u32 ilength;
+	__u64 ioffset;
+};
+
+/*******************************************************************************
+ * legacy display
+ ******************************************************************************/
+
+#define NV04_DISP_NTFY_VBLANK                                              0x00
+#define NV04_DISP_NTFY_CONN                                                0x01
+
+struct nv04_disp_mthd_v0 {
+	__u8  version;
+#define NV04_DISP_SCANOUTPOS                                               0x00
+	__u8  method;
+	__u8  head;
+	__u8  pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__s64 time[2];
+	__u16 vblanks;
+	__u16 vblanke;
+	__u16 vtotal;
+	__u16 vline;
+	__u16 hblanks;
+	__u16 hblanke;
+	__u16 htotal;
+	__u16 hline;
+};
+
+/*******************************************************************************
+ * display
+ ******************************************************************************/
+
+#define NV50_DISP_MTHD                                                     0x00
+
+struct nv50_disp_mthd_v0 {
+	__u8  version;
+#define NV50_DISP_SCANOUTPOS                                               0x00
+	__u8  method;
+	__u8  head;
+	__u8  pad03[5];
+};
+
+struct nv50_disp_mthd_v1 {
+	__u8  version;
+#define NV50_DISP_MTHD_V1_DAC_PWR                                          0x10
+#define NV50_DISP_MTHD_V1_DAC_LOAD                                         0x11
+#define NV50_DISP_MTHD_V1_SOR_PWR                                          0x20
+#define NV50_DISP_MTHD_V1_SOR_HDA_ELD                                      0x21
+#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_PIOR_PWR                                         0x30
+	__u8  method;
+	__u16 hasht;
+	__u16 hashm;
+	__u8  pad06[2];
+};
+
+struct nv50_disp_dac_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  data;
+	__u8  vsync;
+	__u8  hsync;
+	__u8  pad05[3];
+};
+
+struct nv50_disp_dac_load_v0 {
+	__u8  version;
+	__u8  load;
+	__u8  pad02[2];
+	__u32 data;
+};
+
+struct nv50_disp_sor_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  pad02[6];
+};
+
+struct nv50_disp_sor_hda_eld_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u8  data[];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  max_ac_packet;
+	__u8  rekey;
+	__u8  pad04[4];
+};
+
+struct nv50_disp_sor_lvds_script_v0 {
+	__u8  version;
+	__u8  pad01[1];
+	__u16 script;
+	__u8  pad04[4];
+};
+
+struct nv50_disp_sor_dp_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  pad02[6];
+};
+
+struct nv50_disp_pior_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  type;
+	__u8  pad03[5];
+};
+
+/* core */
+struct nv50_disp_core_channel_dma_v0 {
+	__u8  version;
+	__u8  pad01[3];
+	__u32 pushbuf;
+};
+
+/* cursor immediate */
+struct nv50_disp_cursor_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+};
+
+/* base */
+struct nv50_disp_base_channel_dma_v0 {
+	__u8  version;
+	__u8  pad01[2];
+	__u8  head;
+	__u32 pushbuf;
+};
+
+/* overlay */
+struct nv50_disp_overlay_channel_dma_v0 {
+	__u8  version;
+	__u8  pad01[2];
+	__u8  head;
+	__u32 pushbuf;
+};
+
+/* overlay immediate */
+struct nv50_disp_overlay_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+};
+
+
+/*******************************************************************************
+ * fermi
+ ******************************************************************************/
+
+#define FERMI_A_ZBC_COLOR                                                  0x00
+#define FERMI_A_ZBC_DEPTH                                                  0x01
+
+struct fermi_a_zbc_color_v0 {
+	__u8  version;
+#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO                                      0x01
+#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE                                 0x02
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32                       0x04
+#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16                           0x08
+#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16                       0x0c
+#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16                       0x10
+#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16                       0x14
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16                       0x16
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8                                  0x18
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8                               0x1c
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10                               0x20
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10                           0x24
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8                                  0x28
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8                               0x2c
+#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8                              0x30
+#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8                              0x34
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8                              0x38
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10                               0x3c
+#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11                              0x40
+	__u8  format;
+	__u8  index;
+	__u8  pad03[5];
+	__u32 ds[4];
+	__u32 l2[4];
+};
+
+struct fermi_a_zbc_depth_v0 {
+	__u8  version;
+#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32                                      0x01
+	__u8  format;
+	__u8  index;
+	__u8  pad03[5];
+	__u32 ds;
+	__u32 l2;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/client.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/client.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/client.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/client.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013 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 "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_client_ioctl(struct nvif_client *client, void *data, u32 size)
+{
+	return client->driver->ioctl(client->base.priv, client->super, data, size, NULL);
+}
+
+int
+nvif_client_suspend(struct nvif_client *client)
+{
+	return client->driver->suspend(client->base.priv);
+}
+
+int
+nvif_client_resume(struct nvif_client *client)
+{
+	return client->driver->resume(client->base.priv);
+}
+
+void
+nvif_client_fini(struct nvif_client *client)
+{
+	if (client->driver) {
+		client->driver->fini(client->base.priv);
+		client->driver = NULL;
+		client->base.parent = NULL;
+		nvif_object_fini(&client->base);
+	}
+}
+
+const struct nvif_driver *
+nvif_drivers[] = {
+#ifdef __KERNEL__
+	&nvif_driver_nvkm,
+#else
+	&nvif_driver_drm,
+	&nvif_driver_lib,
+#endif
+	NULL
+};
+
+int
+nvif_client_init(void (*dtor)(struct nvif_client *), const char *driver,
+		 const char *name, u64 device, const char *cfg, const char *dbg,
+		 struct nvif_client *client)
+{
+	int ret, i;
+
+	ret = nvif_object_init(NULL, (void*)dtor, 0, 0, NULL, 0, &client->base);
+	if (ret)
+		return ret;
+
+	client->base.parent = &client->base;
+	client->base.handle = ~0;
+	client->object = &client->base;
+	client->super = true;
+
+	for (i = 0, ret = -EINVAL; (client->driver = nvif_drivers[i]); i++) {
+		if (!driver || !strcmp(client->driver->name, driver)) {
+			ret = client->driver->init(name, device, cfg, dbg,
+						  &client->base.priv);
+			if (!ret || driver)
+				break;
+		}
+	}
+
+	if (ret)
+		nvif_client_fini(client);
+	return ret;
+}
+
+static void
+nvif_client_del(struct nvif_client *client)
+{
+	nvif_client_fini(client);
+	kfree(client);
+}
+
+int
+nvif_client_new(const char *driver, const char *name, u64 device,
+		const char *cfg, const char *dbg,
+		struct nvif_client **pclient)
+{
+	struct nvif_client *client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client) {
+		int ret = nvif_client_init(nvif_client_del, driver, name,
+					   device, cfg, dbg, client);
+		if (ret) {
+			kfree(client);
+			client = NULL;
+		}
+		*pclient = client;
+		return ret;
+	}
+	return -ENOMEM;
+}
+
+void
+nvif_client_ref(struct nvif_client *client, struct nvif_client **pclient)
+{
+	nvif_object_ref(&client->base, (struct nvif_object **)pclient);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/client.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/client.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/client.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/client.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+#ifndef __NVIF_CLIENT_H__
+#define __NVIF_CLIENT_H__
+
+#include "object.h"
+
+struct nvif_client {
+	struct nvif_object base;
+	struct nvif_object *object; /*XXX: hack for nvif_object() */
+	const struct nvif_driver *driver;
+	bool super;
+};
+
+static inline struct nvif_client *
+nvif_client(struct nvif_object *object)
+{
+	while (object && object->parent != object)
+		object = object->parent;
+	return (void *)object;
+}
+
+int  nvif_client_init(void (*dtor)(struct nvif_client *), const char *,
+		      const char *, u64, const char *, const char *,
+		      struct nvif_client *);
+void nvif_client_fini(struct nvif_client *);
+int  nvif_client_new(const char *, const char *, u64, const char *,
+		     const char *, struct nvif_client **);
+void nvif_client_ref(struct nvif_client *, struct nvif_client **);
+int  nvif_client_ioctl(struct nvif_client *, void *, u32);
+int  nvif_client_suspend(struct nvif_client *);
+int  nvif_client_resume(struct nvif_client *);
+
+/*XXX*/
+#include <core/client.h>
+#define nvkm_client(a) ({ \
+	struct nvif_client *_client = nvif_client(nvif_object(a)); \
+	nouveau_client(_client->base.priv); \
+})
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/device.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/device.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/device.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 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 "device.h"
+
+void
+nvif_device_fini(struct nvif_device *device)
+{
+	nvif_object_fini(&device->base);
+}
+
+int
+nvif_device_init(struct nvif_object *parent, void (*dtor)(struct nvif_device *),
+		 u32 handle, u32 oclass, void *data, u32 size,
+		 struct nvif_device *device)
+{
+	int ret = nvif_object_init(parent, (void *)dtor, handle, oclass,
+				   data, size, &device->base);
+	if (ret == 0) {
+		device->object = &device->base;
+		device->info.version = 0;
+		ret = nvif_object_mthd(&device->base, NV_DEVICE_V0_INFO,
+				       &device->info, sizeof(device->info));
+	}
+	return ret;
+}
+
+static void
+nvif_device_del(struct nvif_device *device)
+{
+	nvif_device_fini(device);
+	kfree(device);
+}
+
+int
+nvif_device_new(struct nvif_object *parent, u32 handle, u32 oclass,
+		void *data, u32 size, struct nvif_device **pdevice)
+{
+	struct nvif_device *device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (device) {
+		int ret = nvif_device_init(parent, nvif_device_del, handle,
+					   oclass, data, size, device);
+		if (ret) {
+			kfree(device);
+			device = NULL;
+		}
+		*pdevice = device;
+		return ret;
+	}
+	return -ENOMEM;
+}
+
+void
+nvif_device_ref(struct nvif_device *device, struct nvif_device **pdevice)
+{
+	nvif_object_ref(&device->base, (struct nvif_object **)pdevice);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/device.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/device.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/device.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/device.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,62 @@
+#ifndef __NVIF_DEVICE_H__
+#define __NVIF_DEVICE_H__
+
+#include "object.h"
+#include "class.h"
+
+struct nvif_device {
+	struct nvif_object base;
+	struct nvif_object *object; /*XXX: hack for nvif_object() */
+	struct nv_device_info_v0 info;
+};
+
+static inline struct nvif_device *
+nvif_device(struct nvif_object *object)
+{
+	while (object && object->oclass != 0x0080 /*XXX: NV_DEVICE_CLASS*/ )
+		object = object->parent;
+	return (void *)object;
+}
+
+int  nvif_device_init(struct nvif_object *, void (*dtor)(struct nvif_device *),
+		      u32 handle, u32 oclass, void *, u32,
+		      struct nvif_device *);
+void nvif_device_fini(struct nvif_device *);
+int  nvif_device_new(struct nvif_object *, u32 handle, u32 oclass,
+		     void *, u32, struct nvif_device **);
+void nvif_device_ref(struct nvif_device *, struct nvif_device **);
+
+/*XXX*/
+#include <subdev/bios.h>
+#include <subdev/fb.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/gpio.h>
+#include <subdev/clock.h>
+#include <subdev/i2c.h>
+#include <subdev/timer.h>
+#include <subdev/therm.h>
+
+#define nvkm_device(a) nv_device(nvkm_object((a)))
+#define nvkm_bios(a) nouveau_bios(nvkm_device(a))
+#define nvkm_fb(a) nouveau_fb(nvkm_device(a))
+#define nvkm_vmmgr(a) nouveau_vmmgr(nvkm_device(a))
+#define nvkm_bar(a) nouveau_bar(nvkm_device(a))
+#define nvkm_gpio(a) nouveau_gpio(nvkm_device(a))
+#define nvkm_clock(a) nouveau_clock(nvkm_device(a))
+#define nvkm_i2c(a) nouveau_i2c(nvkm_device(a))
+#define nvkm_timer(a) nouveau_timer(nvkm_device(a))
+#define nvkm_wait(a,b,c,d) nv_wait(nvkm_timer(a), (b), (c), (d))
+#define nvkm_wait_cb(a,b,c) nv_wait_cb(nvkm_timer(a), (b), (c))
+#define nvkm_therm(a) nouveau_therm(nvkm_device(a))
+
+#include <engine/device.h>
+#include <engine/fifo.h>
+#include <engine/graph.h>
+#include <engine/software.h>
+
+#define nvkm_fifo(a) nouveau_fifo(nvkm_device(a))
+#define nvkm_fifo_chan(a) ((struct nouveau_fifo_chan *)nvkm_object(a))
+#define nvkm_gr(a) ((struct nouveau_graph *)nouveau_engine(nvkm_object(a), NVDEV_ENGINE_GR))
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/driver.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/driver.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/driver.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/driver.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,21 @@
+#ifndef __NVIF_DRIVER_H__
+#define __NVIF_DRIVER_H__
+
+struct nvif_driver {
+	const char *name;
+	int (*init)(const char *name, u64 device, const char *cfg,
+		    const char *dbg, void **priv);
+	void (*fini)(void *priv);
+	int (*suspend)(void *priv);
+	int (*resume)(void *priv);
+	int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack);
+	void *(*map)(void *priv, u64 handle, u32 size);
+	void (*unmap)(void *priv, void *ptr, u32 size);
+	bool keep;
+};
+
+extern const struct nvif_driver nvif_driver_nvkm;
+extern const struct nvif_driver nvif_driver_drm;
+extern const struct nvif_driver nvif_driver_lib;
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/event.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/event.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/event.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/event.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,62 @@
+#ifndef __NVIF_EVENT_H__
+#define __NVIF_EVENT_H__
+
+struct nvif_notify_req_v0 {
+	__u8  version;
+	__u8  reply;
+	__u8  pad02[5];
+#define NVIF_NOTIFY_V0_ROUTE_NVIF                                          0x00
+	__u8  route;
+	__u64 token;	/* must be unique */
+	__u8  data[];	/* request data (below) */
+};
+
+struct nvif_notify_rep_v0 {
+	__u8  version;
+	__u8  pad01[6];
+	__u8  route;
+	__u64 token;
+	__u8  data[];	/* reply data (below) */
+};
+
+struct nvif_notify_head_req_v0 {
+	/* nvif_notify_req ... */
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+};
+
+struct nvif_notify_head_rep_v0 {
+	/* nvif_notify_rep ... */
+	__u8  version;
+	__u8  pad01[7];
+};
+
+struct nvif_notify_conn_req_v0 {
+	/* nvif_notify_req ... */
+	__u8  version;
+#define NVIF_NOTIFY_CONN_V0_PLUG                                           0x01
+#define NVIF_NOTIFY_CONN_V0_UNPLUG                                         0x02
+#define NVIF_NOTIFY_CONN_V0_IRQ                                            0x04
+#define NVIF_NOTIFY_CONN_V0_ANY                                            0x07
+	__u8  mask;
+	__u8  conn;
+	__u8  pad03[5];
+};
+
+struct nvif_notify_conn_rep_v0 {
+	/* nvif_notify_rep ... */
+	__u8  version;
+	__u8  mask;
+	__u8  pad02[6];
+};
+
+struct nvif_notify_uevent_req {
+	/* nvif_notify_req ... */
+};
+
+struct nvif_notify_uevent_rep {
+	/* nvif_notify_rep ... */
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/ioctl.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/ioctl.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/ioctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/ioctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,128 @@
+#ifndef __NVIF_IOCTL_H__
+#define __NVIF_IOCTL_H__
+
+struct nvif_ioctl_v0 {
+	__u8  version;
+#define NVIF_IOCTL_V0_OWNER_NVIF                                           0x00
+#define NVIF_IOCTL_V0_OWNER_ANY                                            0xff
+	__u8  owner;
+#define NVIF_IOCTL_V0_NOP                                                  0x00
+#define NVIF_IOCTL_V0_SCLASS                                               0x01
+#define NVIF_IOCTL_V0_NEW                                                  0x02
+#define NVIF_IOCTL_V0_DEL                                                  0x03
+#define NVIF_IOCTL_V0_MTHD                                                 0x04
+#define NVIF_IOCTL_V0_RD                                                   0x05
+#define NVIF_IOCTL_V0_WR                                                   0x06
+#define NVIF_IOCTL_V0_MAP                                                  0x07
+#define NVIF_IOCTL_V0_UNMAP                                                0x08
+#define NVIF_IOCTL_V0_NTFY_NEW                                             0x09
+#define NVIF_IOCTL_V0_NTFY_DEL                                             0x0a
+#define NVIF_IOCTL_V0_NTFY_GET                                             0x0b
+#define NVIF_IOCTL_V0_NTFY_PUT                                             0x0c
+	__u8  type;
+	__u8  path_nr;
+#define NVIF_IOCTL_V0_ROUTE_NVIF                                           0x00
+#define NVIF_IOCTL_V0_ROUTE_HIDDEN                                         0xff
+	__u8  pad04[3];
+	__u8  route;
+	__u64 token;
+	__u32 path[8];		/* in reverse */
+	__u8  data[];		/* ioctl data (below) */
+};
+
+struct nvif_ioctl_nop {
+};
+
+struct nvif_ioctl_sclass_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  count;
+	__u8  pad02[6];
+	__u32 oclass[];
+};
+
+struct nvif_ioctl_new_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  pad01[6];
+	__u8  route;
+	__u64 token;
+	__u32 handle;
+/* these class numbers are made up by us, and not nvidia-assigned */
+#define NVIF_IOCTL_NEW_V0_PERFCTR                                    0x0000ffff
+#define NVIF_IOCTL_NEW_V0_CONTROL                                    0x0000fffe
+	__u32 oclass;
+	__u8  data[];		/* class data (class.h) */
+};
+
+struct nvif_ioctl_del {
+};
+
+struct nvif_ioctl_rd_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  size;
+	__u8  pad02[2];
+	__u32 data;
+	__u64 addr;
+};
+
+struct nvif_ioctl_wr_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  size;
+	__u8  pad02[2];
+	__u32 data;
+	__u64 addr;
+};
+
+struct nvif_ioctl_map_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  pad01[3];
+	__u32 length;
+	__u64 handle;
+};
+
+struct nvif_ioctl_unmap {
+};
+
+struct nvif_ioctl_ntfy_new_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  event;
+	__u8  index;
+	__u8  pad03[5];
+	__u8  data[];		/* event request data (event.h) */
+};
+
+struct nvif_ioctl_ntfy_del_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  index;
+	__u8  pad02[6];
+};
+
+struct nvif_ioctl_ntfy_get_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  index;
+	__u8  pad02[6];
+};
+
+struct nvif_ioctl_ntfy_put_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  index;
+	__u8  pad02[6];
+};
+
+struct nvif_ioctl_mthd_v0 {
+	/* nvif_ioctl ... */
+	__u8  version;
+	__u8  method;
+	__u8  pad02[6];
+	__u8  data[];		/* method data (class.h) */
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/list.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/list.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/list.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/list.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ * Copyright Â© 2010 Francisco Jerez <currojerez@riseup.net>
+ *
+ * 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.
+ *
+ */
+
+/* Modified by Ben Skeggs <bskeggs@redhat.com> to match kernel list APIs */
+
+#ifndef _XORG_LIST_H_
+#define _XORG_LIST_H_
+
+/**
+ * @file Classic doubly-link circular list implementation.
+ * For real usage examples of the linked list, see the file test/list.c
+ *
+ * Example:
+ * We need to keep a list of struct foo in the parent struct bar, i.e. what
+ * we want is something like this.
+ *
+ *     struct bar {
+ *          ...
+ *          struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{}
+ *          ...
+ *     }
+ *
+ * We need one list head in bar and a list element in all list_of_foos (both are of
+ * data type 'struct list_head').
+ *
+ *     struct bar {
+ *          ...
+ *          struct list_head list_of_foos;
+ *          ...
+ *     }
+ *
+ *     struct foo {
+ *          ...
+ *          struct list_head entry;
+ *          ...
+ *     }
+ *
+ * Now we initialize the list head:
+ *
+ *     struct bar bar;
+ *     ...
+ *     INIT_LIST_HEAD(&bar.list_of_foos);
+ *
+ * Then we create the first element and add it to this list:
+ *
+ *     struct foo *foo = malloc(...);
+ *     ....
+ *     list_add(&foo->entry, &bar.list_of_foos);
+ *
+ * Repeat the above for each element you want to add to the list. Deleting
+ * works with the element itself.
+ *      list_del(&foo->entry);
+ *      free(foo);
+ *
+ * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty
+ * list again.
+ *
+ * Looping through the list requires a 'struct foo' as iterator and the
+ * name of the field the subnodes use.
+ *
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar.list_of_foos, entry) {
+ *      if (iterator->something == ...)
+ *             ...
+ * }
+ *
+ * Note: You must not call list_del() on the iterator if you continue the
+ * loop. You need to run the safe for-each loop instead:
+ *
+ * struct foo *iterator, *next;
+ * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) {
+ *      if (...)
+ *              list_del(&iterator->entry);
+ * }
+ *
+ */
+
+/**
+ * The linkage struct for list nodes. This struct must be part of your
+ * to-be-linked struct. struct list_head is required for both the head of the
+ * list and for each list node.
+ *
+ * Position and name of the struct list_head field is irrelevant.
+ * There are no requirements that elements of a list are of the same type.
+ * There are no requirements for a list head, any struct list_head can be a list
+ * head.
+ */
+struct list_head {
+    struct list_head *next, *prev;
+};
+
+/**
+ * Initialize the list as an empty list.
+ *
+ * Example:
+ * INIT_LIST_HEAD(&bar->list_of_foos);
+ *
+ * @param The list to initialized.
+ */
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void
+INIT_LIST_HEAD(struct list_head *list)
+{
+    list->next = list->prev = list;
+}
+
+static inline void
+__list_add(struct list_head *entry,
+                struct list_head *prev, struct list_head *next)
+{
+    next->prev = entry;
+    entry->next = next;
+    entry->prev = prev;
+    prev->next = entry;
+}
+
+/**
+ * Insert a new element after the given list head. The new element does not
+ * need to be initialised as empty list.
+ * The list changes from:
+ *      head â†’ some element â†’ ...
+ * to
+ *      head â†’ new element â†’ older element â†’ ...
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add(struct list_head *entry, struct list_head *head)
+{
+    __list_add(entry, head, head->next);
+}
+
+/**
+ * Append a new element to the end of the list given with this list head.
+ *
+ * The list changes from:
+ *      head â†’ some element â†’ ... â†’ lastelement
+ * to
+ *      head â†’ some element â†’ ... â†’ lastelement â†’ new element
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add_tail(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add_tail(struct list_head *entry, struct list_head *head)
+{
+    __list_add(entry, head->prev, head);
+}
+
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
+{
+    next->prev = prev;
+    prev->next = next;
+}
+
+/**
+ * Remove the element from the list it is in. Using this function will reset
+ * the pointers to/from this element so it is removed from the list. It does
+ * NOT free the element itself or manipulate it otherwise.
+ *
+ * Using list_del on a pure list head (like in the example at the top of
+ * this file) will NOT remove the first element from
+ * the list but rather reset the list as empty list.
+ *
+ * Example:
+ * list_del(&foo->entry);
+ *
+ * @param entry The element to remove.
+ */
+static inline void
+list_del(struct list_head *entry)
+{
+    __list_del(entry->prev, entry->next);
+}
+
+static inline void
+list_del_init(struct list_head *entry)
+{
+    __list_del(entry->prev, entry->next);
+    INIT_LIST_HEAD(entry);
+}
+
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+	__list_del(list->prev, list->next);
+	list_add_tail(list, head);
+}
+
+/**
+ * Check if the list is empty.
+ *
+ * Example:
+ * list_empty(&bar->list_of_foos);
+ *
+ * @return True if the list contains one or more elements or False otherwise.
+ */
+static inline bool
+list_empty(struct list_head *head)
+{
+    return head->next == head;
+}
+
+/**
+ * Returns a pointer to the container of this list element.
+ *
+ * Example:
+ * struct foo* f;
+ * f = container_of(&foo->entry, struct foo, entry);
+ * assert(f == foo);
+ *
+ * @param ptr Pointer to the struct list_head.
+ * @param type Data type of the list element.
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the data struct containing the list head.
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) \
+    (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+#endif
+
+/**
+ * Alias of container_of
+ */
+#define list_entry(ptr, type, member) \
+    container_of(ptr, type, member)
+
+/**
+ * Retrieve the first list entry for the given list pointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the first list element.
+ */
+#define list_first_entry(ptr, type, member) \
+    list_entry((ptr)->next, type, member)
+
+/**
+ * Retrieve the last list entry for the given listpointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the last list element.
+ */
+#define list_last_entry(ptr, type, member) \
+    list_entry((ptr)->prev, type, member)
+
+#define __container_of(ptr, sample, member)				\
+    (void *)container_of((ptr), typeof(*(sample)), member)
+
+/**
+ * Loop through the list given by head and set pos to struct in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar->list_of_foos, entry) {
+ *      [modify iterator]
+ * }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param pos Iterator variable of the type of the list elements.
+ * @param head List head
+ * @param member Member name of the struct list_head in the list elements.
+ *
+ */
+#define list_for_each_entry(pos, head, member)				\
+    for (pos = __container_of((head)->next, pos, member);		\
+	 &pos->member != (head);					\
+	 pos = __container_of(pos->member.next, pos, member))
+
+/**
+ * Loop through the list, keeping a backup pointer to the element. This
+ * macro allows for the deletion of a list element while looping through the
+ * list.
+ *
+ * See list_for_each_entry for more details.
+ */
+#define list_for_each_entry_safe(pos, tmp, head, member)		\
+    for (pos = __container_of((head)->next, pos, member),		\
+	 tmp = __container_of(pos->member.next, pos, member);		\
+	 &pos->member != (head);					\
+	 pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
+
+
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = __container_of((head)->prev, pos, member);		\
+	     &pos->member != (head);					\
+	     pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_continue(pos, head, member)			\
+	for (pos = __container_of(pos->member.next, pos, member);	\
+	     &pos->member != (head);					\
+	     pos = __container_of(pos->member.next, pos, member))
+
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = __container_of(pos->member.prev, pos, member);	\
+	     &pos->member != (head);					\
+	     pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_from(pos, head, member)			\
+	for (;								\
+	     &pos->member != (head);					\
+	     pos = __container_of(pos->member.next, pos, member))
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/notify.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/notify.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/notify.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/notify.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2014 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 <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/object.h>
+#include <nvif/ioctl.h>
+#include <nvif/event.h>
+
+static inline int
+nvif_notify_put_(struct nvif_notify *notify)
+{
+	struct nvif_object *object = notify->object;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_ntfy_put_v0 ntfy;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_NTFY_PUT,
+		.ntfy.index = notify->index,
+	};
+
+	if (atomic_inc_return(&notify->putcnt) != 1)
+		return 0;
+
+	return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_put(struct nvif_notify *notify)
+{
+	if (likely(notify->object) &&
+	    test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
+		int ret = nvif_notify_put_(notify);
+		if (test_bit(NVIF_NOTIFY_WORK, &notify->flags))
+			flush_work(&notify->work);
+		return ret;
+	}
+	return 0;
+}
+
+static inline int
+nvif_notify_get_(struct nvif_notify *notify)
+{
+	struct nvif_object *object = notify->object;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_ntfy_get_v0 ntfy;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_NTFY_GET,
+		.ntfy.index = notify->index,
+	};
+
+	if (atomic_dec_return(&notify->putcnt) != 0)
+		return 0;
+
+	return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_get(struct nvif_notify *notify)
+{
+	if (likely(notify->object) &&
+	    !test_and_set_bit(NVIF_NOTIFY_USER, &notify->flags))
+		return nvif_notify_get_(notify);
+	return 0;
+}
+
+static inline int
+nvif_notify_func(struct nvif_notify *notify, bool keep)
+{
+	int ret = notify->func(notify);
+	if (ret == NVIF_NOTIFY_KEEP ||
+	    !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+		if (!keep)
+			atomic_dec(&notify->putcnt);
+		else
+			nvif_notify_get_(notify);
+	}
+	return ret;
+}
+
+static void
+nvif_notify_work(struct work_struct *work)
+{
+	struct nvif_notify *notify = container_of(work, typeof(*notify), work);
+	nvif_notify_func(notify, true);
+}
+
+int
+nvif_notify(const void *header, u32 length, const void *data, u32 size)
+{
+	struct nvif_notify *notify = NULL;
+	const union {
+		struct nvif_notify_rep_v0 v0;
+	} *args = header;
+	int ret = NVIF_NOTIFY_DROP;
+
+	if (length == sizeof(args->v0) && args->v0.version == 0) {
+		if (WARN_ON(args->v0.route))
+			return NVIF_NOTIFY_DROP;
+		notify = (void *)(unsigned long)args->v0.token;
+	}
+
+	if (!WARN_ON(notify == NULL)) {
+		struct nvif_client *client = nvif_client(notify->object);
+		if (!WARN_ON(notify->size != size)) {
+			atomic_inc(&notify->putcnt);
+			if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
+				memcpy((void *)notify->data, data, size);
+				schedule_work(&notify->work);
+				return NVIF_NOTIFY_DROP;
+			}
+			notify->data = data;
+			ret = nvif_notify_func(notify, client->driver->keep);
+			notify->data = NULL;
+		}
+	}
+
+	return ret;
+}
+
+int
+nvif_notify_fini(struct nvif_notify *notify)
+{
+	struct nvif_object *object = notify->object;
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_ntfy_del_v0 ntfy;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_NTFY_DEL,
+		.ntfy.index = notify->index,
+	};
+	int ret = nvif_notify_put(notify);
+	if (ret >= 0 && object) {
+		ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+		if (ret == 0) {
+			nvif_object_ref(NULL, &notify->object);
+			kfree((void *)notify->data);
+		}
+	}
+	return ret;
+}
+
+int
+nvif_notify_init(struct nvif_object *object, void (*dtor)(struct nvif_notify *),
+		 int (*func)(struct nvif_notify *), bool work, u8 event,
+		 void *data, u32 size, u32 reply, struct nvif_notify *notify)
+{
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_ntfy_new_v0 ntfy;
+		struct nvif_notify_req_v0 req;
+	} *args;
+	int ret = -ENOMEM;
+
+	notify->object = NULL;
+	nvif_object_ref(object, &notify->object);
+	notify->flags = 0;
+	atomic_set(&notify->putcnt, 1);
+	notify->dtor = dtor;
+	notify->func = func;
+	notify->data = NULL;
+	notify->size = reply;
+	if (work) {
+		INIT_WORK(&notify->work, nvif_notify_work);
+		set_bit(NVIF_NOTIFY_WORK, &notify->flags);
+		notify->data = kmalloc(notify->size, GFP_KERNEL);
+		if (!notify->data)
+			goto done;
+	}
+
+	if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+		goto done;
+	args->ioctl.version = 0;
+	args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW;
+	args->ntfy.version = 0;
+	args->ntfy.event = event;
+	args->req.version = 0;
+	args->req.reply = notify->size;
+	args->req.route = 0;
+	args->req.token = (unsigned long)(void *)notify;
+
+	memcpy(args->req.data, data, size);
+	ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+	notify->index = args->ntfy.index;
+	kfree(args);
+done:
+	if (ret)
+		nvif_notify_fini(notify);
+	return ret;
+}
+
+static void
+nvif_notify_del(struct nvif_notify *notify)
+{
+	nvif_notify_fini(notify);
+	kfree(notify);
+}
+
+void
+nvif_notify_ref(struct nvif_notify *notify, struct nvif_notify **pnotify)
+{
+	BUG_ON(notify != NULL);
+	if (*pnotify)
+		(*pnotify)->dtor(*pnotify);
+	*pnotify = notify;
+}
+
+int
+nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *),
+		bool work, u8 type, void *data, u32 size, u32 reply,
+		struct nvif_notify **pnotify)
+{
+	struct nvif_notify *notify = kzalloc(sizeof(*notify), GFP_KERNEL);
+	if (notify) {
+		int ret = nvif_notify_init(object, nvif_notify_del, func, work,
+					   type, data, size, reply, notify);
+		if (ret) {
+			kfree(notify);
+			notify = NULL;
+		}
+		*pnotify = notify;
+		return ret;
+	}
+	return -ENOMEM;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/notify.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/notify.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/notify.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/notify.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+#ifndef __NVIF_NOTIFY_H__
+#define __NVIF_NOTIFY_H__
+
+struct nvif_notify {
+	struct nvif_object *object;
+	int index;
+
+#define NVIF_NOTIFY_USER 0
+#define NVIF_NOTIFY_WORK 1
+	unsigned long flags;
+	atomic_t putcnt;
+	void (*dtor)(struct nvif_notify *);
+#define NVIF_NOTIFY_DROP 0
+#define NVIF_NOTIFY_KEEP 1
+	int  (*func)(struct nvif_notify *);
+
+	/* this is const for a *very* good reason - the data might be on the
+	 * stack from an irq handler.  if you're not nvif/notify.c then you
+	 * should probably think twice before casting it away...
+	 */
+	const void *data;
+	u32 size;
+	struct work_struct work;
+};
+
+int  nvif_notify_init(struct nvif_object *, void (*dtor)(struct nvif_notify *),
+		      int (*func)(struct nvif_notify *), bool work, u8 type,
+		      void *data, u32 size, u32 reply, struct nvif_notify *);
+int  nvif_notify_fini(struct nvif_notify *);
+int  nvif_notify_get(struct nvif_notify *);
+int  nvif_notify_put(struct nvif_notify *);
+int  nvif_notify(const void *, u32, const void *, u32);
+
+int  nvif_notify_new(struct nvif_object *, int (*func)(struct nvif_notify *),
+		     bool work, u8 type, void *data, u32 size, u32 reply,
+		     struct nvif_notify **);
+void nvif_notify_ref(struct nvif_notify *, struct nvif_notify **);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/object.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/object.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/object.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/object.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2014 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 "object.h"
+#include "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
+{
+	struct nvif_client *client = nvif_client(object);
+	union {
+		struct nvif_ioctl_v0 v0;
+	} *args = data;
+
+	if (size >= sizeof(*args) && args->v0.version == 0) {
+		args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+		args->v0.path_nr = 0;
+		while (args->v0.path_nr < ARRAY_SIZE(args->v0.path)) {
+			args->v0.path[args->v0.path_nr++] = object->handle;
+			if (object->parent == object)
+				break;
+			object = object->parent;
+		}
+	} else
+		return -ENOSYS;
+
+	return client->driver->ioctl(client->base.priv, client->super, data, size, hack);
+}
+
+int
+nvif_object_sclass(struct nvif_object *object, u32 *oclass, int count)
+{
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_sclass_v0 sclass;
+	} *args;
+	u32 size = count * sizeof(args->sclass.oclass[0]);
+	int ret;
+
+	if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+		return -ENOMEM;
+	args->ioctl.version = 0;
+	args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
+	args->sclass.version = 0;
+	args->sclass.count = count;
+
+	memcpy(args->sclass.oclass, oclass, size);
+	ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+	ret = ret ? ret : args->sclass.count;
+	memcpy(oclass, args->sclass.oclass, size);
+	kfree(args);
+	return ret;
+}
+
+u32
+nvif_object_rd(struct nvif_object *object, int size, u64 addr)
+{
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_rd_v0 rd;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_RD,
+		.rd.size = size,
+		.rd.addr = addr,
+	};
+	int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+	if (ret) {
+		/*XXX: warn? */
+		return 0;
+	}
+	return args.rd.data;
+}
+
+void
+nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data)
+{
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_wr_v0 wr;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_WR,
+		.wr.size = size,
+		.wr.addr = addr,
+		.wr.data = data,
+	};
+	int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+	if (ret) {
+		/*XXX: warn? */
+	}
+}
+
+int
+nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
+{
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_mthd_v0 mthd;
+	} *args;
+	u8 stack[128];
+	int ret;
+
+	if (sizeof(*args) + size > sizeof(stack)) {
+		if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+			return -ENOMEM;
+	} else {
+		args = (void *)stack;
+	}
+	args->ioctl.version = 0;
+	args->ioctl.type = NVIF_IOCTL_V0_MTHD;
+	args->mthd.version = 0;
+	args->mthd.method = mthd;
+
+	memcpy(args->mthd.data, data, size);
+	ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+	memcpy(data, args->mthd.data, size);
+	if (args != (void *)stack)
+		kfree(args);
+	return ret;
+}
+
+void
+nvif_object_unmap(struct nvif_object *object)
+{
+	if (object->map.size) {
+		struct nvif_client *client = nvif_client(object);
+		struct {
+			struct nvif_ioctl_v0 ioctl;
+			struct nvif_ioctl_unmap unmap;
+		} args = {
+			.ioctl.type = NVIF_IOCTL_V0_UNMAP,
+		};
+
+		if (object->map.ptr) {
+			client->driver->unmap(client, object->map.ptr,
+						      object->map.size);
+			object->map.ptr = NULL;
+		}
+
+		nvif_object_ioctl(object, &args, sizeof(args), NULL);
+		object->map.size = 0;
+	}
+}
+
+int
+nvif_object_map(struct nvif_object *object)
+{
+	struct nvif_client *client = nvif_client(object);
+	struct {
+		struct nvif_ioctl_v0 ioctl;
+		struct nvif_ioctl_map_v0 map;
+	} args = {
+		.ioctl.type = NVIF_IOCTL_V0_MAP,
+	};
+	int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+	if (ret == 0) {
+		object->map.size = args.map.length;
+		object->map.ptr = client->driver->map(client, args.map.handle,
+						      object->map.size);
+		if (ret = -ENOMEM, object->map.ptr)
+			return 0;
+		nvif_object_unmap(object);
+	}
+	return ret;
+}
+
+struct ctor {
+	struct nvif_ioctl_v0 ioctl;
+	struct nvif_ioctl_new_v0 new;
+};
+
+void
+nvif_object_fini(struct nvif_object *object)
+{
+	struct ctor *ctor = container_of(object->data, typeof(*ctor), new.data);
+	if (object->parent) {
+		struct {
+			struct nvif_ioctl_v0 ioctl;
+			struct nvif_ioctl_del del;
+		} args = {
+			.ioctl.type = NVIF_IOCTL_V0_DEL,
+		};
+
+		nvif_object_unmap(object);
+		nvif_object_ioctl(object, &args, sizeof(args), NULL);
+		if (object->data) {
+			object->size = 0;
+			object->data = NULL;
+			kfree(ctor);
+		}
+		nvif_object_ref(NULL, &object->parent);
+	}
+}
+
+int
+nvif_object_init(struct nvif_object *parent, void (*dtor)(struct nvif_object *),
+		 u32 handle, u32 oclass, void *data, u32 size,
+		 struct nvif_object *object)
+{
+	struct ctor *ctor;
+	int ret = 0;
+
+	object->parent = NULL;
+	object->object = object;
+	nvif_object_ref(parent, &object->parent);
+	kref_init(&object->refcount);
+	object->handle = handle;
+	object->oclass = oclass;
+	object->data = NULL;
+	object->size = 0;
+	object->dtor = dtor;
+	object->map.ptr = NULL;
+	object->map.size = 0;
+
+	if (object->parent) {
+		if (!(ctor = kmalloc(sizeof(*ctor) + size, GFP_KERNEL))) {
+			nvif_object_fini(object);
+			return -ENOMEM;
+		}
+		object->data = ctor->new.data;
+		object->size = size;
+		memcpy(object->data, data, size);
+
+		ctor->ioctl.version = 0;
+		ctor->ioctl.type = NVIF_IOCTL_V0_NEW;
+		ctor->new.version = 0;
+		ctor->new.route = NVIF_IOCTL_V0_ROUTE_NVIF;
+		ctor->new.token = (unsigned long)(void *)object;
+		ctor->new.handle = handle;
+		ctor->new.oclass = oclass;
+
+		ret = nvif_object_ioctl(parent, ctor, sizeof(*ctor) +
+					object->size, &object->priv);
+	}
+
+	if (ret)
+		nvif_object_fini(object);
+	return ret;
+}
+
+static void
+nvif_object_del(struct nvif_object *object)
+{
+	nvif_object_fini(object);
+	kfree(object);
+}
+
+int
+nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass,
+		void *data, u32 size, struct nvif_object **pobject)
+{
+	struct nvif_object *object = kzalloc(sizeof(*object), GFP_KERNEL);
+	if (object) {
+		int ret = nvif_object_init(parent, nvif_object_del, handle,
+					   oclass, data, size, object);
+		if (ret) {
+			kfree(object);
+			object = NULL;
+		}
+		*pobject = object;
+		return ret;
+	}
+	return -ENOMEM;
+}
+
+static void
+nvif_object_put(struct kref *kref)
+{
+	struct nvif_object *object =
+		container_of(kref, typeof(*object), refcount);
+	object->dtor(object);
+}
+
+void
+nvif_object_ref(struct nvif_object *object, struct nvif_object **pobject)
+{
+	if (object)
+		kref_get(&object->refcount);
+	if (*pobject)
+		kref_put(&(*pobject)->refcount, nvif_object_put);
+	*pobject = object;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/object.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/object.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/object.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/object.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,75 @@
+#ifndef __NVIF_OBJECT_H__
+#define __NVIF_OBJECT_H__
+
+#include <nvif/os.h>
+
+struct nvif_object {
+	struct nvif_object *parent;
+	struct nvif_object *object; /*XXX: hack for nvif_object() */
+	struct kref refcount;
+	u32 handle;
+	u32 oclass;
+	void *data;
+	u32   size;
+	void *priv; /*XXX: hack */
+	void (*dtor)(struct nvif_object *);
+	struct {
+		void *ptr;
+		u32 size;
+	} map;
+};
+
+int  nvif_object_init(struct nvif_object *, void (*dtor)(struct nvif_object *),
+		      u32 handle, u32 oclass, void *, u32,
+		      struct nvif_object *);
+void nvif_object_fini(struct nvif_object *);
+int  nvif_object_new(struct nvif_object *, u32 handle, u32 oclass,
+		     void *, u32, struct nvif_object **);
+void nvif_object_ref(struct nvif_object *, struct nvif_object **);
+int  nvif_object_ioctl(struct nvif_object *, void *, u32, void **);
+int  nvif_object_sclass(struct nvif_object *, u32 *, int);
+u32  nvif_object_rd(struct nvif_object *, int, u64);
+void nvif_object_wr(struct nvif_object *, int, u64, u32);
+int  nvif_object_mthd(struct nvif_object *, u32, void *, u32);
+int  nvif_object_map(struct nvif_object *);
+void nvif_object_unmap(struct nvif_object *);
+
+#define nvif_object(a) (a)->object
+
+#define ioread8_native ioread8
+#define iowrite8_native iowrite8
+#define nvif_rd(a,b,c) ({                                                      \
+	struct nvif_object *_object = nvif_object(a);                          \
+	u32 _data;                                                             \
+	if (likely(_object->map.ptr))                                          \
+		_data = ioread##b##_native((u8 *)_object->map.ptr + (c));      \
+	else                                                                   \
+		_data = nvif_object_rd(_object, (b) / 8, (c));                 \
+	_data;                                                                 \
+})
+#define nvif_wr(a,b,c,d) ({                                                    \
+	struct nvif_object *_object = nvif_object(a);                          \
+	if (likely(_object->map.ptr))                                          \
+		iowrite##b##_native((d), (u8 *)_object->map.ptr + (c));        \
+	else                                                                   \
+		nvif_object_wr(_object, (b) / 8, (c), (d));                    \
+})
+#define nvif_rd08(a,b) ({ u8  _v = nvif_rd((a), 8, (b)); _v; })
+#define nvif_rd16(a,b) ({ u16 _v = nvif_rd((a), 16, (b)); _v; })
+#define nvif_rd32(a,b) ({ u32 _v = nvif_rd((a), 32, (b)); _v; })
+#define nvif_wr08(a,b,c) nvif_wr((a), 8, (b), (u8)(c))
+#define nvif_wr16(a,b,c) nvif_wr((a), 16, (b), (u16)(c))
+#define nvif_wr32(a,b,c) nvif_wr((a), 32, (b), (u32)(c))
+#define nvif_mask(a,b,c,d) ({                                                  \
+	u32 _v = nvif_rd32(nvif_object(a), (b));                               \
+	nvif_wr32(nvif_object(a), (b), (_v & ~(c)) | (d));                     \
+	_v;                                                                    \
+})
+
+#define nvif_mthd(a,b,c,d) nvif_object_mthd(nvif_object(a), (b), (c), (d))
+
+/*XXX*/
+#include <core/object.h>
+#define nvkm_object(a) ((struct nouveau_object *)nvif_object(a)->priv)
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/unpack.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/unpack.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/nouveau/nvif/unpack.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/nouveau/nvif/unpack.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,24 @@
+#ifndef __NVIF_UNPACK_H__
+#define __NVIF_UNPACK_H__
+
+#define nvif_unvers(d) ({                                                      \
+	ret = (size == sizeof(d)) ? 0 : -ENOSYS;                               \
+	(ret == 0);                                                            \
+})
+
+#define nvif_unpack(d,vl,vh,m) ({                                              \
+	if ((vl) == 0 || ret == -ENOSYS) {                                     \
+		int _size = sizeof(d);                                         \
+		if (_size <= size && (d).version >= (vl) &&                    \
+				     (d).version <= (vh)) {                    \
+			data = (u8 *)data + _size;                             \
+			size = size - _size;                                   \
+			ret = ((m) || !size) ? 0 : -E2BIG;                     \
+		} else {                                                       \
+			ret = -ENOSYS;                                         \
+		}                                                              \
+	}                                                                      \
+	(ret == 0);                                                            \
+})
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_connector.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_connector.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_connector.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_connector.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,8 +32,16 @@ struct omap_connector {
 	struct drm_connector base;
 	struct omap_dss_device *dssdev;
 	struct drm_encoder *encoder;
+	bool hdmi_mode;
 };
 
+bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
+{
+	struct omap_connector *omap_connector = to_omap_connector(connector);
+
+	return omap_connector->hdmi_mode;
+}
+
 void copy_timings_omap_to_drm(struct drm_display_mode *mode,
 		struct omap_video_timings *timings)
 {
@@ -130,7 +138,7 @@ static void omap_connector_destroy(struc
 	struct omap_dss_device *dssdev = omap_connector->dssdev;
 
 	DBG("%s", omap_connector->dssdev->name);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(omap_connector);
 
@@ -162,10 +170,14 @@ static int omap_connector_get_modes(stru
 			drm_mode_connector_update_edid_property(
 					connector, edid);
 			n = drm_add_edid_modes(connector, edid);
+
+			omap_connector->hdmi_mode =
+				drm_detect_hdmi_monitor(edid);
 		} else {
 			drm_mode_connector_update_edid_property(
 					connector, NULL);
 		}
+
 		kfree(edid);
 	} else {
 		struct drm_display_mode *mode = drm_mode_create(dev);
@@ -307,7 +319,7 @@ struct drm_connector *omap_connector_ini
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	return connector;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,7 +199,7 @@ static struct dmm_txn *dmm_txn_init(stru
 static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 		struct page **pages, uint32_t npages, uint32_t roll)
 {
-	dma_addr_t pat_pa = 0;
+	dma_addr_t pat_pa = 0, data_pa = 0;
 	uint32_t *data;
 	struct pat *pat;
 	struct refill_engine *engine = txn->engine_handle;
@@ -223,7 +223,9 @@ static void dmm_txn_append(struct dmm_tx
 			.lut_id = engine->tcm->lut_id,
 		};
 
-	data = alloc_dma(txn, 4*i, &pat->data_pa);
+	data = alloc_dma(txn, 4*i, &data_pa);
+	/* FIXME: what if data_pa is more than 32-bit ? */
+	pat->data_pa = data_pa;
 
 	while (i--) {
 		int n = i + roll;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -119,13 +119,6 @@ struct omap_drm_private {
 	struct omap_drm_irq error_handler;
 };
 
-/* this should probably be in drm-core to standardize amongst drivers */
-#define DRM_ROTATE_0	0
-#define DRM_ROTATE_90	1
-#define DRM_ROTATE_180	2
-#define DRM_ROTATE_270	3
-#define DRM_REFLECT_X	4
-#define DRM_REFLECT_Y	5
 
 #ifdef CONFIG_DEBUG_FS
 int omap_debugfs_init(struct drm_minor *minor);
@@ -194,6 +187,7 @@ struct drm_encoder *omap_connector_attac
 		struct drm_connector *connector);
 void omap_connector_flush(struct drm_connector *connector,
 		int x, int y, int w, int h);
+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);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_edid.h>
+
 #include "omap_drv.h"
 
 #include "drm_crtc.h"
@@ -89,6 +91,31 @@ static void omap_encoder_mode_set(struct
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
+	struct drm_device *dev = encoder->dev;
+	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+	struct omap_dss_device *dssdev = omap_encoder->dssdev;
+	struct drm_connector *connector;
+	bool hdmi_mode;
+	int r;
+
+	hdmi_mode = false;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			hdmi_mode = omap_connector_get_hdmi_mode(connector);
+			break;
+		}
+	}
+
+	if (dssdev->driver->set_hdmi_mode)
+		dssdev->driver->set_hdmi_mode(dssdev, hdmi_mode);
+
+	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
+		struct hdmi_avi_infoframe avi;
+
+		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
+		if (r == 0)
+			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
+	}
 }
 
 static void omap_encoder_prepare(struct drm_encoder *encoder)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -281,7 +281,7 @@ fail:
 	return ret;
 }
 
-static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs omap_fb_helper_funcs = {
 	.fb_probe = omap_fbdev_create,
 };
 
@@ -325,7 +325,7 @@ struct drm_fb_helper *omap_fbdev_init(st
 
 	helper = &fbdev->base;
 
-	helper->funcs = &omap_fb_helper_funcs;
+	drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(dev, helper,
 			priv->num_crtcs, priv->num_connectors);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -233,11 +233,7 @@ static int omap_gem_attach_pages(struct
 
 	WARN_ON(omap_obj->pages);
 
-	/* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the
-	 * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
-	 * we actually want CMA memory for it all anyways..
-	 */
-	pages = drm_gem_get_pages(obj, GFP_KERNEL);
+	pages = drm_gem_get_pages(obj);
 	if (IS_ERR(pages)) {
 		dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
 		return PTR_ERR(pages);
@@ -791,7 +787,7 @@ int omap_gem_get_paddr(struct drm_gem_ob
 			omap_obj->paddr = tiler_ssptr(block);
 			omap_obj->block = block;
 
-			DBG("got paddr: %08x", omap_obj->paddr);
+			DBG("got paddr: %pad", &omap_obj->paddr);
 		}
 
 		omap_obj->paddr_cnt++;
@@ -985,9 +981,9 @@ void omap_gem_describe(struct drm_gem_ob
 
 	off = drm_vma_node_start(&obj->vma_node);
 
-	seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
+	seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
 			omap_obj->flags, obj->name, obj->refcount.refcount.counter,
-			off, omap_obj->paddr, omap_obj->paddr_cnt,
+			off, &omap_obj->paddr, omap_obj->paddr_cnt,
 			omap_obj->vaddr, omap_obj->roll);
 
 	if (omap_obj->flags & OMAP_BO_TILED) {
@@ -1183,9 +1179,7 @@ int omap_gem_op_sync(struct drm_gem_obje
 			}
 		}
 		spin_unlock(&sync_lock);
-
-		if (waiter)
-			kfree(waiter);
+		kfree(waiter);
 	}
 	return ret;
 }
@@ -1347,6 +1341,7 @@ struct drm_gem_object *omap_gem_new(stru
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_gem_object *omap_obj;
 	struct drm_gem_object *obj = NULL;
+	struct address_space *mapping;
 	size_t size;
 	int ret;
 
@@ -1404,14 +1399,16 @@ struct drm_gem_object *omap_gem_new(stru
 		omap_obj->height = gsize.tiled.height;
 	}
 
-	ret = 0;
-	if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
+	if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) {
 		drm_gem_private_object_init(dev, obj, size);
-	else
+	} else {
 		ret = drm_gem_object_init(dev, obj, size);
+		if (ret)
+			goto fail;
 
-	if (ret)
-		goto fail;
+		mapping = file_inode(obj->filp)->i_mapping;
+		mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
+	}
 
 	return obj;
 
@@ -1467,8 +1464,8 @@ void omap_gem_init(struct drm_device *de
 			entry->paddr = tiler_ssptr(block);
 			entry->block = block;
 
-			DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h,
-					entry->paddr,
+			DBG("%d:%d: %dx%d: paddr=%pad stride=%d", i, j, w, h,
+					&entry->paddr,
 					usergart[i].stride_pfn << PAGE_SHIFT);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -171,7 +171,7 @@ static struct dma_buf_ops omap_dmabuf_op
 struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
 		struct drm_gem_object *obj, int flags)
 {
-	return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
+	return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags, NULL);
 }
 
 struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_plane.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_plane.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,8 +142,8 @@ static void omap_plane_pre_apply(struct
 	DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
 			info->out_width, info->out_height,
 			info->screen_width);
-	DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
-			info->paddr, info->p_uv_addr);
+	DBG("%d,%d %pad %pad", info->pos_x, info->pos_y,
+			&info->paddr, &info->p_uv_addr);
 
 	/* TODO: */
 	ilace = false;
@@ -308,16 +308,13 @@ void omap_plane_install_properties(struc
 	if (priv->has_dmm) {
 		prop = priv->rotation_prop;
 		if (!prop) {
-			const struct drm_prop_enum_list props[] = {
-					{ DRM_ROTATE_0,   "rotate-0" },
-					{ DRM_ROTATE_90,  "rotate-90" },
-					{ DRM_ROTATE_180, "rotate-180" },
-					{ DRM_ROTATE_270, "rotate-270" },
-					{ DRM_REFLECT_X,  "reflect-x" },
-					{ DRM_REFLECT_Y,  "reflect-y" },
-			};
-			prop = drm_property_create_bitmask(dev, 0, "rotation",
-					props, ARRAY_SIZE(props));
+			prop = drm_mode_create_rotation_property(dev,
+								 BIT(DRM_ROTATE_0) |
+								 BIT(DRM_ROTATE_90) |
+								 BIT(DRM_ROTATE_180) |
+								 BIT(DRM_ROTATE_270) |
+								 BIT(DRM_REFLECT_X) |
+								 BIT(DRM_REFLECT_Y));
 			if (prop == NULL)
 				return;
 			priv->rotation_prop = prop;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/panel/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/panel/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,7 +5,7 @@ config DRM_PANEL
 	  Panel registration and lookup framework.
 
 menu "Display Panels"
-	depends on DRM_PANEL
+	depends on DRM && DRM_PANEL
 
 config DRM_PANEL_SIMPLE
 	tristate "support for simple panels"
@@ -18,14 +18,11 @@ config DRM_PANEL_SIMPLE
 
 config DRM_PANEL_LD9040
 	tristate "LD9040 RGB/SPI panel"
-	depends on DRM && DRM_PANEL
-	depends on OF
-	select SPI
+	depends on OF && SPI
 	select VIDEOMODE_HELPERS
 
 config DRM_PANEL_S6E8AA0
 	tristate "S6E8AA0 DSI video mode panel"
-	depends on DRM && DRM_PANEL
 	depends on OF
 	select DRM_MIPI_DSI
 	select VIDEOMODE_HELPERS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-ld9040.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-ld9040.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-ld9040.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-ld9040.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,7 +110,10 @@ struct ld9040 {
 	int error;
 };
 
-#define panel_to_ld9040(p) container_of(p, struct ld9040, panel)
+static inline struct ld9040 *panel_to_ld9040(struct drm_panel *panel)
+{
+	return container_of(panel, struct ld9040, panel);
+}
 
 static int ld9040_clear_error(struct ld9040 *ctx)
 {
@@ -216,6 +219,11 @@ static int ld9040_power_off(struct ld904
 
 static int ld9040_disable(struct drm_panel *panel)
 {
+	return 0;
+}
+
+static int ld9040_unprepare(struct drm_panel *panel)
+{
 	struct ld9040 *ctx = panel_to_ld9040(panel);
 
 	msleep(120);
@@ -228,7 +236,7 @@ static int ld9040_disable(struct drm_pan
 	return ld9040_power_off(ctx);
 }
 
-static int ld9040_enable(struct drm_panel *panel)
+static int ld9040_prepare(struct drm_panel *panel)
 {
 	struct ld9040 *ctx = panel_to_ld9040(panel);
 	int ret;
@@ -242,11 +250,16 @@ static int ld9040_enable(struct drm_pane
 	ret = ld9040_clear_error(ctx);
 
 	if (ret < 0)
-		ld9040_disable(panel);
+		ld9040_unprepare(panel);
 
 	return ret;
 }
 
+static int ld9040_enable(struct drm_panel *panel)
+{
+	return 0;
+}
+
 static int ld9040_get_modes(struct drm_panel *panel)
 {
 	struct drm_connector *connector = panel->connector;
@@ -273,6 +286,8 @@ static int ld9040_get_modes(struct drm_p
 
 static const struct drm_panel_funcs ld9040_drm_funcs = {
 	.disable = ld9040_disable,
+	.unprepare = ld9040_unprepare,
+	.prepare = ld9040_prepare,
 	.enable = ld9040_enable,
 	.get_modes = ld9040_get_modes,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-s6e8aa0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-s6e8aa0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-s6e8aa0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-s6e8aa0.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,7 +120,10 @@ struct s6e8aa0 {
 	int error;
 };
 
-#define panel_to_s6e8aa0(p) container_of(p, struct s6e8aa0, panel)
+static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6e8aa0, panel);
+}
 
 static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
 {
@@ -133,14 +136,14 @@ static int s6e8aa0_clear_error(struct s6
 static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
 {
 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-	int ret;
+	ssize_t ret;
 
 	if (ctx->error < 0)
 		return;
 
-	ret = mipi_dsi_dcs_write(dsi, dsi->channel, data, len);
+	ret = mipi_dsi_dcs_write(dsi, data, len);
 	if (ret < 0) {
-		dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len,
+		dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret, len,
 			data);
 		ctx->error = ret;
 	}
@@ -154,7 +157,7 @@ static int s6e8aa0_dcs_read(struct s6e8a
 	if (ctx->error < 0)
 		return ctx->error;
 
-	ret = mipi_dsi_dcs_read(dsi, dsi->channel, cmd, data, len);
+	ret = mipi_dsi_dcs_read(dsi, cmd, data, len);
 	if (ret < 0) {
 		dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
 		ctx->error = ret;
@@ -889,6 +892,11 @@ static int s6e8aa0_power_off(struct s6e8
 
 static int s6e8aa0_disable(struct drm_panel *panel)
 {
+	return 0;
+}
+
+static int s6e8aa0_unprepare(struct drm_panel *panel)
+{
 	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 
 	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
@@ -900,7 +908,7 @@ static int s6e8aa0_disable(struct drm_pa
 	return s6e8aa0_power_off(ctx);
 }
 
-static int s6e8aa0_enable(struct drm_panel *panel)
+static int s6e8aa0_prepare(struct drm_panel *panel)
 {
 	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 	int ret;
@@ -913,11 +921,16 @@ static int s6e8aa0_enable(struct drm_pan
 	ret = ctx->error;
 
 	if (ret < 0)
-		s6e8aa0_disable(panel);
+		s6e8aa0_unprepare(panel);
 
 	return ret;
 }
 
+static int s6e8aa0_enable(struct drm_panel *panel)
+{
+	return 0;
+}
+
 static int s6e8aa0_get_modes(struct drm_panel *panel)
 {
 	struct drm_connector *connector = panel->connector;
@@ -944,6 +957,8 @@ static int s6e8aa0_get_modes(struct drm_
 
 static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
 	.disable = s6e8aa0_disable,
+	.unprepare = s6e8aa0_unprepare,
+	.prepare = s6e8aa0_prepare,
 	.enable = s6e8aa0_enable,
 	.get_modes = s6e8aa0_get_modes,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-simple.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-simple.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/panel/panel-simple.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/panel/panel-simple.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,14 +37,35 @@ struct panel_desc {
 	const struct drm_display_mode *modes;
 	unsigned int num_modes;
 
+	unsigned int bpc;
+
 	struct {
 		unsigned int width;
 		unsigned int height;
 	} size;
+
+	/**
+	 * @prepare: the time (in milliseconds) that it takes for the panel to
+	 *           become ready and start receiving video data
+	 * @enable: the time (in milliseconds) that it takes for the panel to
+	 *          display the first valid frame after starting to receive
+	 *          video data
+	 * @disable: the time (in milliseconds) that it takes for the panel to
+	 *           turn the display off (no content is visible)
+	 * @unprepare: the time (in milliseconds) that it takes for the panel
+	 *             to power itself down completely
+	 */
+	struct {
+		unsigned int prepare;
+		unsigned int enable;
+		unsigned int disable;
+		unsigned int unprepare;
+	} delay;
 };
 
 struct panel_simple {
 	struct drm_panel base;
+	bool prepared;
 	bool enabled;
 
 	const struct panel_desc *desc;
@@ -87,6 +108,7 @@ static int panel_simple_get_fixed_modes(
 		num++;
 	}
 
+	connector->display_info.bpc = panel->desc->bpc;
 	connector->display_info.width_mm = panel->desc->size.width;
 	connector->display_info.height_mm = panel->desc->size.height;
 
@@ -105,21 +127,40 @@ static int panel_simple_disable(struct d
 		backlight_update_status(p->backlight);
 	}
 
+	if (p->desc->delay.disable)
+		msleep(p->desc->delay.disable);
+
+	p->enabled = false;
+
+	return 0;
+}
+
+static int panel_simple_unprepare(struct drm_panel *panel)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+
+	if (!p->prepared)
+		return 0;
+
 	if (p->enable_gpio)
 		gpiod_set_value_cansleep(p->enable_gpio, 0);
 
 	regulator_disable(p->supply);
-	p->enabled = false;
+
+	if (p->desc->delay.unprepare)
+		msleep(p->desc->delay.unprepare);
+
+	p->prepared = false;
 
 	return 0;
 }
 
-static int panel_simple_enable(struct drm_panel *panel)
+static int panel_simple_prepare(struct drm_panel *panel)
 {
 	struct panel_simple *p = to_panel_simple(panel);
 	int err;
 
-	if (p->enabled)
+	if (p->prepared)
 		return 0;
 
 	err = regulator_enable(p->supply);
@@ -131,6 +172,24 @@ static int panel_simple_enable(struct dr
 	if (p->enable_gpio)
 		gpiod_set_value_cansleep(p->enable_gpio, 1);
 
+	if (p->desc->delay.prepare)
+		msleep(p->desc->delay.prepare);
+
+	p->prepared = true;
+
+	return 0;
+}
+
+static int panel_simple_enable(struct drm_panel *panel)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+
+	if (p->enabled)
+		return 0;
+
+	if (p->desc->delay.enable)
+		msleep(p->desc->delay.enable);
+
 	if (p->backlight) {
 		p->backlight->props.power = FB_BLANK_UNBLANK;
 		backlight_update_status(p->backlight);
@@ -164,6 +223,8 @@ static int panel_simple_get_modes(struct
 
 static const struct drm_panel_funcs panel_simple_funcs = {
 	.disable = panel_simple_disable,
+	.unprepare = panel_simple_unprepare,
+	.prepare = panel_simple_prepare,
 	.enable = panel_simple_enable,
 	.get_modes = panel_simple_get_modes,
 };
@@ -179,22 +240,21 @@ static int panel_simple_probe(struct dev
 		return -ENOMEM;
 
 	panel->enabled = false;
+	panel->prepared = false;
 	panel->desc = desc;
 
 	panel->supply = devm_regulator_get(dev, "power");
 	if (IS_ERR(panel->supply))
 		return PTR_ERR(panel->supply);
 
-	panel->enable_gpio = devm_gpiod_get(dev, "enable");
+	panel->enable_gpio = devm_gpiod_get_optional(dev, "enable");
 	if (IS_ERR(panel->enable_gpio)) {
 		err = PTR_ERR(panel->enable_gpio);
-		if (err != -ENOENT) {
-			dev_err(dev, "failed to request GPIO: %d\n", err);
-			return err;
-		}
+		dev_err(dev, "failed to request GPIO: %d\n", err);
+		return err;
+	}
 
-		panel->enable_gpio = NULL;
-	} else {
+	if (panel->enable_gpio) {
 		err = gpiod_direction_output(panel->enable_gpio, 0);
 		if (err < 0) {
 			dev_err(dev, "failed to setup GPIO: %d\n", err);
@@ -285,6 +345,7 @@ static const struct drm_display_mode auo
 static const struct panel_desc auo_b101aw03 = {
 	.modes = &auo_b101aw03_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 223,
 		.height = 125,
@@ -307,12 +368,40 @@ static const struct drm_display_mode auo
 static const struct panel_desc auo_b133xtn01 = {
 	.modes = &auo_b133xtn01_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 293,
 		.height = 165,
 	},
 };
 
+static const struct drm_display_mode auo_b133htn01_mode = {
+	.clock = 150660,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 172,
+	.hsync_end = 1920 + 172 + 80,
+	.htotal = 1920 + 172 + 80 + 60,
+	.vdisplay = 1080,
+	.vsync_start = 1080 + 25,
+	.vsync_end = 1080 + 25 + 10,
+	.vtotal = 1080 + 25 + 10 + 10,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc auo_b133htn01 = {
+	.modes = &auo_b133htn01_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 293,
+		.height = 165,
+	},
+	.delay = {
+		.prepare = 105,
+		.enable = 20,
+		.unprepare = 50,
+	},
+};
+
 static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
 	.clock = 72070,
 	.hdisplay = 1366,
@@ -329,6 +418,7 @@ static const struct drm_display_mode chu
 static const struct panel_desc chunghwa_claa101wa01a = {
 	.modes = &chunghwa_claa101wa01a_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 220,
 		.height = 120,
@@ -351,6 +441,7 @@ static const struct drm_display_mode chu
 static const struct panel_desc chunghwa_claa101wb01 = {
 	.modes = &chunghwa_claa101wb01_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 223,
 		.height = 125,
@@ -374,6 +465,7 @@ static const struct drm_display_mode edt
 static const struct panel_desc edt_et057090dhu = {
 	.modes = &edt_et057090dhu_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 115,
 		.height = 86,
@@ -397,12 +489,82 @@ static const struct drm_display_mode edt
 static const struct panel_desc edt_etm0700g0dh6 = {
 	.modes = &edt_etm0700g0dh6_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 152,
 		.height = 91,
 	},
 };
 
+static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
+	.clock = 32260,
+	.hdisplay = 800,
+	.hsync_start = 800 + 168,
+	.hsync_end = 800 + 168 + 64,
+	.htotal = 800 + 168 + 64 + 88,
+	.vdisplay = 480,
+	.vsync_start = 480 + 37,
+	.vsync_end = 480 + 37 + 2,
+	.vtotal = 480 + 37 + 2 + 8,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc foxlink_fl500wvr00_a0t = {
+	.modes = &foxlink_fl500wvr00_a0t_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 108,
+		.height = 65,
+	},
+};
+
+static const struct drm_display_mode innolux_n116bge_mode = {
+	.clock = 71000,
+	.hdisplay = 1366,
+	.hsync_start = 1366 + 64,
+	.hsync_end = 1366 + 64 + 6,
+	.htotal = 1366 + 64 + 6 + 64,
+	.vdisplay = 768,
+	.vsync_start = 768 + 8,
+	.vsync_end = 768 + 8 + 4,
+	.vtotal = 768 + 8 + 4 + 8,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+};
+
+static const struct panel_desc innolux_n116bge = {
+	.modes = &innolux_n116bge_mode,
+	.num_modes = 1,
+	.bpc = 6,
+	.size = {
+		.width = 256,
+		.height = 144,
+	},
+};
+
+static const struct drm_display_mode innolux_n156bge_l21_mode = {
+	.clock = 69300,
+	.hdisplay = 1366,
+	.hsync_start = 1366 + 16,
+	.hsync_end = 1366 + 16 + 34,
+	.htotal = 1366 + 16 + 34 + 50,
+	.vdisplay = 768,
+	.vsync_start = 768 + 2,
+	.vsync_end = 768 + 2 + 6,
+	.vtotal = 768 + 2 + 6 + 12,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc innolux_n156bge_l21 = {
+	.modes = &innolux_n156bge_l21_mode,
+	.num_modes = 1,
+	.bpc = 6,
+	.size = {
+		.width = 344,
+		.height = 193,
+	},
+};
+
 static const struct drm_display_mode lg_lp129qe_mode = {
 	.clock = 285250,
 	.hdisplay = 2560,
@@ -419,6 +581,7 @@ static const struct drm_display_mode lg_
 static const struct panel_desc lg_lp129qe = {
 	.modes = &lg_lp129qe_mode,
 	.num_modes = 1,
+	.bpc = 8,
 	.size = {
 		.width = 272,
 		.height = 181,
@@ -441,6 +604,7 @@ static const struct drm_display_mode sam
 static const struct panel_desc samsung_ltn101nt05 = {
 	.modes = &samsung_ltn101nt05_mode,
 	.num_modes = 1,
+	.bpc = 6,
 	.size = {
 		.width = 1024,
 		.height = 600,
@@ -452,6 +616,9 @@ static const struct of_device_id platfor
 		.compatible = "auo,b101aw03",
 		.data = &auo_b101aw03,
 	}, {
+		.compatible = "auo,b133htn01",
+		.data = &auo_b133htn01,
+	}, {
 		.compatible = "auo,b133xtn01",
 		.data = &auo_b133xtn01,
 	}, {
@@ -470,14 +637,21 @@ static const struct of_device_id platfor
 		.compatible = "edt,etm0700g0dh6",
 		.data = &edt_etm0700g0dh6,
 	}, {
+		.compatible = "foxlink,fl500wvr00-a0t",
+		.data = &foxlink_fl500wvr00_a0t,
+	}, {
+		.compatible = "innolux,n116bge",
+		.data = &innolux_n116bge,
+	}, {
+		.compatible = "innolux,n156bge-l21",
+		.data = &innolux_n156bge_l21,
+	}, {
 		.compatible = "lg,lp129qe",
 		.data = &lg_lp129qe,
 	}, {
 		.compatible = "samsung,ltn101nt05",
 		.data = &samsung_ltn101nt05,
 	}, {
-		.compatible = "simple-panel",
-	}, {
 		/* sentinel */
 	}
 };
@@ -545,7 +719,7 @@ static const struct panel_desc_dsi lg_ld
 			.height = 151,
 		},
 	},
-	.flags = MIPI_DSI_MODE_VIDEO,
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS,
 	.format = MIPI_DSI_FMT_RGB888,
 	.lanes = 4,
 };
@@ -599,7 +773,8 @@ static const struct panel_desc_dsi panas
 			.height = 136,
 		},
 	},
-	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+		 MIPI_DSI_CLOCK_NON_CONTINUOUS,
 	.format = MIPI_DSI_FMT_RGB888,
 	.lanes = 4,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_display.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_display.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -835,7 +835,7 @@ static void qxl_conn_destroy(struct drm_
 	struct qxl_output *qxl_output =
 		drm_connector_to_qxl_output(connector);
 
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(qxl_output);
 }
@@ -902,7 +902,7 @@ static int qdev_output_init(struct drm_d
 
 	drm_object_attach_property(&connector->base,
 				   qdev->hotplug_mode_update_property, 0);
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
 #include "qxl_object.h"
 
 extern int qxl_max_ioctls;
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
 	{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8,
 	  0xffff00, 0 },
 	{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_OTHER << 8,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -660,7 +660,7 @@ static int qxl_fbdev_destroy(struct drm_
 	return 0;
 }
 
-static struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
 	.fb_probe = qxl_fb_find_or_create_single,
 };
 
@@ -676,9 +676,12 @@ int qxl_fbdev_init(struct qxl_device *qd
 
 	qfbdev->qdev = qdev;
 	qdev->mode_info.qfbdev = qfbdev;
-	qfbdev->helper.funcs = &qxl_fb_helper_funcs;
 	spin_lock_init(&qfbdev->delayed_ops_lock);
 	INIT_LIST_HEAD(&qfbdev->delayed_ops);
+
+	drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper,
+			      &qxl_fb_helper_funcs);
+
 	ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper,
 				 qxl_num_crtc /* num_crtc - QXL supports just 1 */,
 				 QXLFB_CONN_LIMIT);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_object.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_object.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/qxl/qxl_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/qxl/qxl_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@ static inline int qxl_bo_reserve(struct
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS) {
 			struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
@@ -67,7 +67,7 @@ static inline int qxl_bo_wait(struct qxl
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS) {
 			struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/atombios_dp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/atombios_dp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2014-09-28 17:29:07.000000000 -0400
@@ -405,16 +405,13 @@ bool radeon_dp_getdpcd(struct radeon_con
 	u8 msg[DP_DPCD_SIZE];
 	int ret;
 
-	char dpcd_hex_dump[DP_DPCD_SIZE * 3];
-
 	ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg,
 			       DP_DPCD_SIZE);
 	if (ret > 0) {
 		memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
 
-		hex_dump_to_buffer(dig_connector->dpcd, sizeof(dig_connector->dpcd),
-				   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
-		DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
+		DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd),
+			      dig_connector->dpcd);
 
 		radeon_dp_probe_oui(radeon_connector);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,12 +331,10 @@ static bool radeon_atom_mode_fixup(struc
 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
 
-	/* get the native mode for LVDS */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+	/* get the native mode for scaling */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
 		radeon_panel_mode_fixup(encoder, adjusted_mode);
-
-	/* get the native mode for TV */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+	} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
 		if (tv_dac) {
 			if (tv_dac->tv_std == TV_STD_NTSC ||
@@ -346,6 +344,8 @@ static bool radeon_atom_mode_fixup(struc
 			else
 				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
 		}
+	} else if (radeon_encoder->rmx_type != RMX_OFF) {
+		radeon_panel_mode_fixup(encoder, adjusted_mode);
 	}
 
 	if (ASIC_IS_DCE3(rdev) &&
@@ -716,7 +716,7 @@ atombios_get_encoder_mode(struct drm_enc
 			if (radeon_connector->use_digital &&
 			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
 				return ATOM_ENCODER_MODE_HDMI;
-			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
 				return ATOM_ENCODER_MODE_HDMI;
 			else if (radeon_connector->use_digital)
@@ -735,7 +735,7 @@ atombios_get_encoder_mode(struct drm_enc
 		if (radeon_audio != 0) {
 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
 				return ATOM_ENCODER_MODE_HDMI;
-			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
 				return ATOM_ENCODER_MODE_HDMI;
 			else
@@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_enc
 		} else if (radeon_audio != 0) {
 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
 				return ATOM_ENCODER_MODE_HDMI;
-			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+			else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
 				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
 				return ATOM_ENCODER_MODE_HDMI;
 			else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ci_dpm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ci_dpm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ci_dpm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ci_dpm.c	2014-09-28 17:29:07.000000000 -0400
@@ -869,6 +869,9 @@ static int ci_set_thermal_temperature_ra
 	WREG32_SMC(CG_THERMAL_CTRL, tmp);
 #endif
 
+	rdev->pm.dpm.thermal.min_temp = low_temp;
+	rdev->pm.dpm.thermal.max_temp = high_temp;
+
 	return 0;
 }
 
@@ -940,7 +943,18 @@ static void ci_get_leakage_voltages(stru
 	pi->vddc_leakage.count = 0;
 	pi->vddci_leakage.count = 0;
 
-	if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
+	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
+		for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
+			virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+			if (radeon_atom_get_voltage_evv(rdev, virtual_voltage_id, &vddc) != 0)
+				continue;
+			if (vddc != 0 && vddc != virtual_voltage_id) {
+				pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc;
+				pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id;
+				pi->vddc_leakage.count++;
+			}
+		}
+	} else if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
 		for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
 			virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
 			if (radeon_atom_get_leakage_vddc_based_on_leakage_params(rdev, &vddc, &vddci,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/cik.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/cik.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/cik.c	2014-08-07 04:46:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/cik.c	2014-09-28 21:27:16.000000000 -0400
@@ -1725,27 +1725,44 @@ static void cik_srbm_select(struct radeo
  */
 int ci_mc_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
+	const __be32 *fw_data = NULL;
+	const __le32 *new_fw_data = NULL;
 	u32 running, blackout = 0;
-	u32 *io_mc_regs;
+	u32 *io_mc_regs = NULL;
+	const __le32 *new_io_mc_regs = NULL;
 	int i, regs_size, ucode_size;
 
 	if (!rdev->mc_fw)
 		return -EINVAL;
 
-	ucode_size = rdev->mc_fw->size / 4;
+	if (rdev->new_fw) {
+		const struct mc_firmware_header_v1_0 *hdr =
+			(const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
 
-	switch (rdev->family) {
-	case CHIP_BONAIRE:
-		io_mc_regs = (u32 *)&bonaire_io_mc_regs;
-		regs_size = BONAIRE_IO_MC_REGS_SIZE;
-		break;
-	case CHIP_HAWAII:
-		io_mc_regs = (u32 *)&hawaii_io_mc_regs;
-		regs_size = HAWAII_IO_MC_REGS_SIZE;
-		break;
-	default:
-		return -EINVAL;
+		radeon_ucode_print_mc_hdr(&hdr->header);
+
+		regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
+		new_io_mc_regs = (const __le32 *)
+			(rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
+		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+		new_fw_data = (const __le32 *)
+			(rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+	} else {
+		ucode_size = rdev->mc_fw->size / 4;
+
+		switch (rdev->family) {
+		case CHIP_BONAIRE:
+			io_mc_regs = (u32 *)&bonaire_io_mc_regs;
+			regs_size = BONAIRE_IO_MC_REGS_SIZE;
+			break;
+		case CHIP_HAWAII:
+			io_mc_regs = (u32 *)&hawaii_io_mc_regs;
+			regs_size = HAWAII_IO_MC_REGS_SIZE;
+			break;
+		default:
+			return -EINVAL;
+		}
+		fw_data = (const __be32 *)rdev->mc_fw->data;
 	}
 
 	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1762,13 +1779,21 @@ int ci_mc_load_microcode(struct radeon_d
 
 		/* load mc io regs */
 		for (i = 0; i < regs_size; i++) {
-			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
-			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+			if (rdev->new_fw) {
+				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++));
+			} else {
+				WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
+				WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+			}
 		}
 		/* load the MC ucode */
-		fw_data = (const __be32 *)rdev->mc_fw->data;
-		for (i = 0; i < ucode_size; i++)
-			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+		for (i = 0; i < ucode_size; i++) {
+			if (rdev->new_fw)
+				WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+			else
+				WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+		}
 
 		/* put the engine back into the active state */
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
@@ -1806,17 +1831,21 @@ int ci_mc_load_microcode(struct radeon_d
 static int cik_init_microcode(struct radeon_device *rdev)
 {
 	const char *chip_name;
+	const char *new_chip_name;
 	size_t pfp_req_size, me_req_size, ce_req_size,
 		mec_req_size, rlc_req_size, mc_req_size = 0,
 		sdma_req_size, smc_req_size = 0, mc2_req_size = 0;
 	char fw_name[30];
+	int new_fw = 0;
 	int err;
+	int num_fw;
 
 	DRM_DEBUG("\n");
 
 	switch (rdev->family) {
 	case CHIP_BONAIRE:
 		chip_name = "BONAIRE";
+		new_chip_name = "bonaire";
 		pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
 		me_req_size = CIK_ME_UCODE_SIZE * 4;
 		ce_req_size = CIK_CE_UCODE_SIZE * 4;
@@ -1826,9 +1855,11 @@ static int cik_init_microcode(struct rad
 		mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4;
 		sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4);
+		num_fw = 8;
 		break;
 	case CHIP_HAWAII:
 		chip_name = "HAWAII";
+		new_chip_name = "hawaii";
 		pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
 		me_req_size = CIK_ME_UCODE_SIZE * 4;
 		ce_req_size = CIK_CE_UCODE_SIZE * 4;
@@ -1838,142 +1869,285 @@ static int cik_init_microcode(struct rad
 		mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4;
 		sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4);
+		num_fw = 8;
 		break;
 	case CHIP_KAVERI:
 		chip_name = "KAVERI";
+		new_chip_name = "kaveri";
 		pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
 		me_req_size = CIK_ME_UCODE_SIZE * 4;
 		ce_req_size = CIK_CE_UCODE_SIZE * 4;
 		mec_req_size = CIK_MEC_UCODE_SIZE * 4;
 		rlc_req_size = KV_RLC_UCODE_SIZE * 4;
 		sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+		num_fw = 7;
 		break;
 	case CHIP_KABINI:
 		chip_name = "KABINI";
+		new_chip_name = "kabini";
 		pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
 		me_req_size = CIK_ME_UCODE_SIZE * 4;
 		ce_req_size = CIK_CE_UCODE_SIZE * 4;
 		mec_req_size = CIK_MEC_UCODE_SIZE * 4;
 		rlc_req_size = KB_RLC_UCODE_SIZE * 4;
 		sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+		num_fw = 6;
 		break;
 	case CHIP_MULLINS:
 		chip_name = "MULLINS";
+		new_chip_name = "mullins";
 		pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
 		me_req_size = CIK_ME_UCODE_SIZE * 4;
 		ce_req_size = CIK_CE_UCODE_SIZE * 4;
 		mec_req_size = CIK_MEC_UCODE_SIZE * 4;
 		rlc_req_size = ML_RLC_UCODE_SIZE * 4;
 		sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+		num_fw = 6;
 		break;
 	default: BUG();
 	}
 
-	DRM_INFO("Loading %s Microcode\n", chip_name);
+	DRM_INFO("Loading %s Microcode\n", new_chip_name);
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->pfp_fw->size != pfp_req_size) {
-		printk(KERN_ERR
-		       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->pfp_fw->size, fw_name);
-		err = -EINVAL;
-		goto out;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->pfp_fw->size != pfp_req_size) {
+			printk(KERN_ERR
+			       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->pfp_fw->size, fw_name);
+			err = -EINVAL;
+			goto out;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->pfp_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->me_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->me_fw->size != me_req_size) {
-		printk(KERN_ERR
-		       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->me_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->me_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->me_fw->size != me_req_size) {
+			printk(KERN_ERR
+			       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->me_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->me_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->ce_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->ce_fw->size != ce_req_size) {
-		printk(KERN_ERR
-		       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->ce_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->ce_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->ce_fw->size != ce_req_size) {
+			printk(KERN_ERR
+			       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->ce_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->ce_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->mec_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->mec_fw->size != mec_req_size) {
-		printk(KERN_ERR
-		       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->mec_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->mec_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->mec_fw->size != mec_req_size) {
+			printk(KERN_ERR
+			       "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->mec_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->mec_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	if (rdev->family == CHIP_KAVERI) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
+		err = reject_firmware(&rdev->mec2_fw, fw_name, rdev->dev);
+		if (err) {
+			goto out;
+		} else {
+			err = radeon_ucode_validate(rdev->mec2_fw);
+			if (err) {
+				goto out;
+			} else {
+				new_fw++;
+			}
+		}
+	}
+
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->rlc_fw->size != rlc_req_size) {
-		printk(KERN_ERR
-		       "cik_rlc: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->rlc_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->rlc_fw->size != rlc_req_size) {
+			printk(KERN_ERR
+			       "cik_rlc: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->rlc_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->rlc_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->sdma_fw->size != sdma_req_size) {
-		printk(KERN_ERR
-		       "cik_sdma: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->sdma_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->sdma_fw->size != sdma_req_size) {
+			printk(KERN_ERR
+			       "cik_sdma: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->sdma_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->sdma_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "cik_fw: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
 	/* No SMC, MC ucode on APUs */
 	if (!(rdev->flags & RADEON_IS_IGP)) {
-		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		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);
 			err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
-			if (err)
+			if (err) {
+				snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+				err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+				if (err)
+					goto out;
+			}
+			if ((rdev->mc_fw->size != mc_req_size) &&
+			    (rdev->mc_fw->size != mc2_req_size)){
+				printk(KERN_ERR
+				       "cik_mc: Bogus length %zu in firmware \"%s\"\n",
+				       rdev->mc_fw->size, fw_name);
+				err = -EINVAL;
+			}
+			DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
+		} else {
+			err = radeon_ucode_validate(rdev->mc_fw);
+			if (err) {
+				printk(KERN_ERR
+				       "cik_fw: validation failed for firmware \"%s\"\n",
+				       fw_name);
 				goto out;
+			} else {
+				new_fw++;
+			}
 		}
-		if ((rdev->mc_fw->size != mc_req_size) &&
-		    (rdev->mc_fw->size != mc2_req_size)){
-			printk(KERN_ERR
-			       "cik_mc: Bogus length %zu in firmware \"%s\"\n",
-			       rdev->mc_fw->size, fw_name);
-			err = -EINVAL;
-		}
-		DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
 
-		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 		err = reject_firmware(&rdev->smc_fw, fw_name, rdev->dev);
 		if (err) {
-			printk(KERN_ERR
-			       "smc: error loading firmware \"%s\"\n",
-			       fw_name);
-			release_firmware(rdev->smc_fw);
-			rdev->smc_fw = NULL;
-			err = 0;
-		} else if (rdev->smc_fw->size != smc_req_size) {
-			printk(KERN_ERR
-			       "cik_smc: Bogus length %zu in firmware \"%s\"\n",
-			       rdev->smc_fw->size, fw_name);
-			err = -EINVAL;
+			snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+			err = reject_firmware(&rdev->smc_fw, fw_name, rdev->dev);
+			if (err) {
+				printk(KERN_ERR
+				       "smc: error loading firmware \"%s\"\n",
+				       fw_name);
+				release_firmware(rdev->smc_fw);
+				rdev->smc_fw = NULL;
+				err = 0;
+			} else if (rdev->smc_fw->size != smc_req_size) {
+				printk(KERN_ERR
+				       "cik_smc: Bogus length %zu in firmware \"%s\"\n",
+				       rdev->smc_fw->size, fw_name);
+				err = -EINVAL;
+			}
+		} else {
+			err = radeon_ucode_validate(rdev->smc_fw);
+			if (err) {
+				printk(KERN_ERR
+				       "cik_fw: validation failed for firmware \"%s\"\n",
+				       fw_name);
+				goto out;
+			} else {
+				new_fw++;
+			}
 		}
 	}
 
+	if (new_fw == 0) {
+		rdev->new_fw = false;
+	} else if (new_fw < num_fw) {
+		printk(KERN_ERR "ci_fw: mixing new and old firmware!\n");
+		err = -EINVAL;
+	} else {
+		rdev->new_fw = true;
+	}
+
 out:
 	if (err) {
 		if (err != -EINVAL)
@@ -1986,8 +2160,14 @@ out:
 		rdev->me_fw = NULL;
 		release_firmware(rdev->ce_fw);
 		rdev->ce_fw = NULL;
+		release_firmware(rdev->mec_fw);
+		rdev->mec_fw = NULL;
+		release_firmware(rdev->mec2_fw);
+		rdev->mec2_fw = NULL;
 		release_firmware(rdev->rlc_fw);
 		rdev->rlc_fw = NULL;
+		release_firmware(rdev->sdma_fw);
+		rdev->sdma_fw = NULL;
 		release_firmware(rdev->mc_fw);
 		rdev->mc_fw = NULL;
 		release_firmware(rdev->smc_fw);
@@ -3224,7 +3404,7 @@ static void cik_gpu_init(struct radeon_d
 	u32 mc_shared_chmap, mc_arb_ramcfg;
 	u32 hdp_host_path_cntl;
 	u32 tmp;
-	int i, j, k;
+	int i, j;
 
 	switch (rdev->family) {
 	case CHIP_BONAIRE:
@@ -3285,6 +3465,7 @@ static void cik_gpu_init(struct radeon_d
 			   (rdev->pdev->device == 0x130B) ||
 			   (rdev->pdev->device == 0x130E) ||
 			   (rdev->pdev->device == 0x1315) ||
+			   (rdev->pdev->device == 0x1318) ||
 			   (rdev->pdev->device == 0x131B)) {
 			rdev->config.cik.max_cu_per_sh = 4;
 			rdev->config.cik.max_backends_per_se = 1;
@@ -3413,12 +3594,11 @@ static void cik_gpu_init(struct radeon_d
 		     rdev->config.cik.max_sh_per_se,
 		     rdev->config.cik.max_backends_per_se);
 
+	rdev->config.cik.active_cus = 0;
 	for (i = 0; i < rdev->config.cik.max_shader_engines; i++) {
 		for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) {
-			for (k = 0; k < rdev->config.cik.max_cu_per_sh; k++) {
-				rdev->config.cik.active_cus +=
-					hweight32(cik_get_cu_active_bitmap(rdev, i, j));
-			}
+			rdev->config.cik.active_cus +=
+				hweight32(cik_get_cu_active_bitmap(rdev, i, j));
 		}
 	}
 
@@ -3542,7 +3722,7 @@ int cik_ring_test(struct radeon_device *
 	radeon_ring_write(ring, PACKET3(PACKET3_SET_UCONFIG_REG, 1));
 	radeon_ring_write(ring, ((scratch - PACKET3_SET_UCONFIG_REG_START) >> 2));
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = RREG32(scratch);
@@ -3631,8 +3811,6 @@ void cik_fence_gfx_ring_emit(struct rade
 	radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | DATA_SEL(1) | INT_SEL(2));
 	radeon_ring_write(ring, fence->seq);
 	radeon_ring_write(ring, 0);
-	/* HDP flush */
-	cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -3661,10 +3839,19 @@ void cik_fence_compute_ring_emit(struct
 	radeon_ring_write(ring, upper_32_bits(addr));
 	radeon_ring_write(ring, fence->seq);
 	radeon_ring_write(ring, 0);
-	/* HDP flush */
-	cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
+/**
+ * cik_semaphore_ring_emit - emit a semaphore on the CP ring
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring buffer object
+ * @semaphore: radeon semaphore object
+ * @emit_wait: Is this a sempahore wait?
+ *
+ * Emits a semaphore signal/wait packet to the CP ring and prevents the PFP
+ * from running ahead of semaphore waits.
+ */
 bool cik_semaphore_ring_emit(struct radeon_device *rdev,
 			     struct radeon_ring *ring,
 			     struct radeon_semaphore *semaphore,
@@ -3677,6 +3864,12 @@ bool cik_semaphore_ring_emit(struct rade
 	radeon_ring_write(ring, lower_32_bits(addr));
 	radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel);
 
+	if (emit_wait && ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
+		/* Prevent the PFP from running ahead of the semaphore wait */
+		radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+		radeon_ring_write(ring, 0x0);
+	}
+
 	return true;
 }
 
@@ -3749,7 +3942,7 @@ int cik_copy_cpdma(struct radeon_device
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
@@ -3848,7 +4041,7 @@ int cik_ib_test(struct radeon_device *rd
 	ib.ptr[1] = ((scratch - PACKET3_SET_UCONFIG_REG_START) >> 2);
 	ib.ptr[2] = 0xDEADBEEF;
 	ib.length_dw = 3;
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		radeon_scratch_free(rdev, scratch);
 		radeon_ib_free(rdev, &ib);
@@ -3934,7 +4127,6 @@ static void cik_cp_gfx_enable(struct rad
  */
 static int cik_cp_gfx_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
 	int i;
 
 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
@@ -3942,26 +4134,70 @@ static int cik_cp_gfx_load_microcode(str
 
 	cik_cp_gfx_enable(rdev, false);
 
-	/* PFP */
-	fw_data = (const __be32 *)rdev->pfp_fw->data;
-	WREG32(CP_PFP_UCODE_ADDR, 0);
-	for (i = 0; i < CIK_PFP_UCODE_SIZE; i++)
-		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_PFP_UCODE_ADDR, 0);
+	if (rdev->new_fw) {
+		const struct gfx_firmware_header_v1_0 *pfp_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+		const struct gfx_firmware_header_v1_0 *ce_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+		const struct gfx_firmware_header_v1_0 *me_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+		const __le32 *fw_data;
+		u32 fw_size;
 
-	/* CE */
-	fw_data = (const __be32 *)rdev->ce_fw->data;
-	WREG32(CP_CE_UCODE_ADDR, 0);
-	for (i = 0; i < CIK_CE_UCODE_SIZE; i++)
-		WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_CE_UCODE_ADDR, 0);
+		radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
+		radeon_ucode_print_gfx_hdr(&ce_hdr->header);
+		radeon_ucode_print_gfx_hdr(&me_hdr->header);
 
-	/* ME */
-	fw_data = (const __be32 *)rdev->me_fw->data;
-	WREG32(CP_ME_RAM_WADDR, 0);
-	for (i = 0; i < CIK_ME_UCODE_SIZE; i++)
-		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_ME_RAM_WADDR, 0);
+		/* PFP */
+		fw_data = (const __le32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+
+		/* CE */
+		fw_data = (const __le32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_CE_UCODE_ADDR, 0);
+
+		/* ME */
+		fw_data = (const __be32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_ME_RAM_WADDR, 0);
+	} else {
+		const __be32 *fw_data;
+
+		/* PFP */
+		fw_data = (const __be32 *)rdev->pfp_fw->data;
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+		for (i = 0; i < CIK_PFP_UCODE_SIZE; i++)
+			WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+
+		/* CE */
+		fw_data = (const __be32 *)rdev->ce_fw->data;
+		WREG32(CP_CE_UCODE_ADDR, 0);
+		for (i = 0; i < CIK_CE_UCODE_SIZE; i++)
+			WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_CE_UCODE_ADDR, 0);
+
+		/* ME */
+		fw_data = (const __be32 *)rdev->me_fw->data;
+		WREG32(CP_ME_RAM_WADDR, 0);
+		for (i = 0; i < CIK_ME_UCODE_SIZE; i++)
+			WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_ME_RAM_WADDR, 0);
+	}
 
 	WREG32(CP_PFP_UCODE_ADDR, 0);
 	WREG32(CP_CE_UCODE_ADDR, 0);
@@ -4026,7 +4262,7 @@ static int cik_cp_gfx_start(struct radeo
 	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
 	radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	return 0;
 }
@@ -4226,7 +4462,6 @@ static void cik_cp_compute_enable(struct
  */
 static int cik_cp_compute_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
 	int i;
 
 	if (!rdev->mec_fw)
@@ -4234,20 +4469,55 @@ static int cik_cp_compute_load_microcode
 
 	cik_cp_compute_enable(rdev, false);
 
-	/* MEC1 */
-	fw_data = (const __be32 *)rdev->mec_fw->data;
-	WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
-	for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
-		WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+	if (rdev->new_fw) {
+		const struct gfx_firmware_header_v1_0 *mec_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
+		const __le32 *fw_data;
+		u32 fw_size;
+
+		radeon_ucode_print_gfx_hdr(&mec_hdr->header);
+
+		/* MEC1 */
+		fw_data = (const __le32 *)
+			(rdev->mec_fw->data + le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
+		fw_size = le32_to_cpu(mec_hdr->header.ucode_size_bytes) / 4;
+		WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
 
-	if (rdev->family == CHIP_KAVERI) {
 		/* MEC2 */
+		if (rdev->family == CHIP_KAVERI) {
+			const struct gfx_firmware_header_v1_0 *mec2_hdr =
+				(const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
+
+			fw_data = (const __le32 *)
+				(rdev->mec2_fw->data +
+				 le32_to_cpu(mec2_hdr->header.ucode_array_offset_bytes));
+			fw_size = le32_to_cpu(mec2_hdr->header.ucode_size_bytes) / 4;
+			WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+			for (i = 0; i < fw_size; i++)
+				WREG32(CP_MEC_ME2_UCODE_DATA, le32_to_cpup(fw_data++));
+			WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+		}
+	} else {
+		const __be32 *fw_data;
+
+		/* MEC1 */
 		fw_data = (const __be32 *)rdev->mec_fw->data;
-		WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+		WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
 		for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
-			WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++));
-		WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+			WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+
+		if (rdev->family == CHIP_KAVERI) {
+			/* MEC2 */
+			fw_data = (const __be32 *)rdev->mec_fw->data;
+			WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+			for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
+				WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++));
+			WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+		}
 	}
 
 	return 0;
@@ -4340,7 +4610,7 @@ static int cik_mec_init(struct radeon_de
 		r = radeon_bo_create(rdev,
 				     rdev->mec.num_mec *rdev->mec.num_pipe * MEC_HPD_SIZE * 2,
 				     PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_GTT, NULL,
+				     RADEON_GEM_DOMAIN_GTT, 0, NULL,
 				     &rdev->mec.hpd_eop_obj);
 		if (r) {
 			dev_warn(rdev->dev, "(%d) create HDP EOP bo failed\n", r);
@@ -4454,7 +4724,7 @@ struct bonaire_mqd
  */
 static int cik_cp_compute_resume(struct radeon_device *rdev)
 {
-	int r, i, idx;
+	int r, i, j, idx;
 	u32 tmp;
 	bool use_doorbell = true;
 	u64 hqd_gpu_addr;
@@ -4510,7 +4780,7 @@ static int cik_cp_compute_resume(struct
 			r = radeon_bo_create(rdev,
 					     sizeof(struct bonaire_mqd),
 					     PAGE_SIZE, true,
-					     RADEON_GEM_DOMAIN_GTT, NULL,
+					     RADEON_GEM_DOMAIN_GTT, 0, NULL,
 					     &rdev->ring[idx].mqd_obj);
 			if (r) {
 				dev_warn(rdev->dev, "(%d) create MQD bo failed\n", r);
@@ -4573,7 +4843,7 @@ static int cik_cp_compute_resume(struct
 		mqd->queue_state.cp_hqd_pq_wptr= 0;
 		if (RREG32(CP_HQD_ACTIVE) & 1) {
 			WREG32(CP_HQD_DEQUEUE_REQUEST, 1);
-			for (i = 0; i < rdev->usec_timeout; i++) {
+			for (j = 0; j < rdev->usec_timeout; j++) {
 				if (!(RREG32(CP_HQD_ACTIVE) & 1))
 					break;
 				udelay(1);
@@ -5367,7 +5637,6 @@ static int cik_pcie_gart_enable(struct r
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Setup TLB control */
 	WREG32(MC_VM_MX_L1_TLB_CNTL,
 	       (0xA << 7) |
@@ -5401,20 +5670,17 @@ static int cik_pcie_gart_enable(struct r
 	WREG32(0x15D8, 0);
 	WREG32(0x15DC, 0);
 
-	/* empty context1-15 */
-	/* FIXME start with 4G, once using 2 level pt switch to full
-	 * vm size space
-	 */
+	/* restore 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, rdev->vm_manager.max_pfn);
 	for (i = 1; i < 16; i++) {
 		if (i < 8)
 			WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-			       rdev->gart.table_addr >> 12);
+			       rdev->vm_manager.saved_table_addr[i]);
 		else
 			WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2),
-			       rdev->gart.table_addr >> 12);
+			       rdev->vm_manager.saved_table_addr[i]);
 	}
 
 	/* enable context1-15 */
@@ -5479,6 +5745,17 @@ static int cik_pcie_gart_enable(struct r
  */
 static void cik_pcie_gart_disable(struct radeon_device *rdev)
 {
+	unsigned i;
+
+	for (i = 1; i < 16; ++i) {
+		uint32_t reg;
+		if (i < 8)
+			reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2);
+		else
+			reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2);
+		rdev->vm_manager.saved_table_addr[i] = RREG32(reg);
+	}
+
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
 	WREG32(VM_CONTEXT1_CNTL, 0);
@@ -5607,12 +5884,13 @@ static void cik_vm_decode_fault(struct r
 void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
 {
 	struct radeon_ring *ring = &rdev->ring[ridx];
+	int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX);
 
 	if (vm == NULL)
 		return;
 
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 				 WRITE_DATA_DST_SEL(0)));
 	if (vm->id < 8) {
 		radeon_ring_write(ring,
@@ -5626,14 +5904,14 @@ void cik_vm_flush(struct radeon_device *
 
 	/* update SH_MEM_* regs */
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
 	radeon_ring_write(ring, 0);
 	radeon_ring_write(ring, VMID(vm->id));
 
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 6));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, SH_MEM_BASES >> 2);
 	radeon_ring_write(ring, 0);
@@ -5644,7 +5922,7 @@ void cik_vm_flush(struct radeon_device *
 	radeon_ring_write(ring, 0); /* SH_MEM_APE1_LIMIT */
 
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
 	radeon_ring_write(ring, 0);
@@ -5655,14 +5933,14 @@ void cik_vm_flush(struct radeon_device *
 
 	/* bits 0-15 are the VM contexts0-15 */
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
 	radeon_ring_write(ring, 0);
 	radeon_ring_write(ring, 1 << vm->id);
 
 	/* compute doesn't have PFP */
-	if (ridx == RADEON_RING_TYPE_GFX_INDEX) {
+	if (usepfp) {
 		/* sync PFP to ME, otherwise we might get invalid PFP reads */
 		radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
 		radeon_ring_write(ring, 0x0);
@@ -5830,28 +6108,10 @@ static void cik_rlc_start(struct radeon_
 static int cik_rlc_resume(struct radeon_device *rdev)
 {
 	u32 i, size, tmp;
-	const __be32 *fw_data;
 
 	if (!rdev->rlc_fw)
 		return -EINVAL;
 
-	switch (rdev->family) {
-	case CHIP_BONAIRE:
-	case CHIP_HAWAII:
-	default:
-		size = BONAIRE_RLC_UCODE_SIZE;
-		break;
-	case CHIP_KAVERI:
-		size = KV_RLC_UCODE_SIZE;
-		break;
-	case CHIP_KABINI:
-		size = KB_RLC_UCODE_SIZE;
-		break;
-	case CHIP_MULLINS:
-		size = ML_RLC_UCODE_SIZE;
-		break;
-	}
-
 	cik_rlc_stop(rdev);
 
 	/* disable CG */
@@ -5875,11 +6135,45 @@ static int cik_rlc_resume(struct radeon_
 	WREG32(RLC_MC_CNTL, 0);
 	WREG32(RLC_UCODE_CNTL, 0);
 
-	fw_data = (const __be32 *)rdev->rlc_fw->data;
+	if (rdev->new_fw) {
+		const struct rlc_firmware_header_v1_0 *hdr =
+			(const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
+		const __le32 *fw_data = (const __le32 *)
+			(rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+		radeon_ucode_print_rlc_hdr(&hdr->header);
+
+		size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
 		WREG32(RLC_GPM_UCODE_ADDR, 0);
-	for (i = 0; i < size; i++)
-		WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(RLC_GPM_UCODE_ADDR, 0);
+		for (i = 0; i < size; i++)
+			WREG32(RLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(RLC_GPM_UCODE_ADDR, 0);
+	} else {
+		const __be32 *fw_data;
+
+		switch (rdev->family) {
+		case CHIP_BONAIRE:
+		case CHIP_HAWAII:
+		default:
+			size = BONAIRE_RLC_UCODE_SIZE;
+			break;
+		case CHIP_KAVERI:
+			size = KV_RLC_UCODE_SIZE;
+			break;
+		case CHIP_KABINI:
+			size = KB_RLC_UCODE_SIZE;
+			break;
+		case CHIP_MULLINS:
+			size = ML_RLC_UCODE_SIZE;
+			break;
+		}
+
+		fw_data = (const __be32 *)rdev->rlc_fw->data;
+		WREG32(RLC_GPM_UCODE_ADDR, 0);
+		for (i = 0; i < size; i++)
+			WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(RLC_GPM_UCODE_ADDR, 0);
+	}
 
 	/* XXX - find out what chips support lbpw */
 	cik_enable_lbpw(rdev, false);
@@ -6313,11 +6607,10 @@ static void cik_enable_gds_pg(struct rad
 
 void cik_init_cp_pg_table(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
 	volatile u32 *dst_ptr;
 	int me, i, max_me = 4;
 	u32 bo_offset = 0;
-	u32 table_offset;
+	u32 table_offset, table_size;
 
 	if (rdev->family == CHIP_KAVERI)
 		max_me = 5;
@@ -6328,24 +6621,71 @@ void cik_init_cp_pg_table(struct radeon_
 	/* write the cp table buffer */
 	dst_ptr = rdev->rlc.cp_table_ptr;
 	for (me = 0; me < max_me; me++) {
-		if (me == 0) {
-			fw_data = (const __be32 *)rdev->ce_fw->data;
-			table_offset = CP_ME_TABLE_OFFSET;
-		} else if (me == 1) {
-			fw_data = (const __be32 *)rdev->pfp_fw->data;
-			table_offset = CP_ME_TABLE_OFFSET;
-		} else if (me == 2) {
-			fw_data = (const __be32 *)rdev->me_fw->data;
-			table_offset = CP_ME_TABLE_OFFSET;
+		if (rdev->new_fw) {
+			const __le32 *fw_data;
+			const struct gfx_firmware_header_v1_0 *hdr;
+
+			if (me == 0) {
+				hdr = (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+				fw_data = (const __le32 *)
+					(rdev->ce_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+				table_offset = le32_to_cpu(hdr->jt_offset);
+				table_size = le32_to_cpu(hdr->jt_size);
+			} else if (me == 1) {
+				hdr = (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+				fw_data = (const __le32 *)
+					(rdev->pfp_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+				table_offset = le32_to_cpu(hdr->jt_offset);
+				table_size = le32_to_cpu(hdr->jt_size);
+			} else if (me == 2) {
+				hdr = (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+				fw_data = (const __le32 *)
+					(rdev->me_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+				table_offset = le32_to_cpu(hdr->jt_offset);
+				table_size = le32_to_cpu(hdr->jt_size);
+			} else if (me == 3) {
+				hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
+				fw_data = (const __le32 *)
+					(rdev->mec_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+				table_offset = le32_to_cpu(hdr->jt_offset);
+				table_size = le32_to_cpu(hdr->jt_size);
+			} else {
+				hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
+				fw_data = (const __le32 *)
+					(rdev->mec2_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+				table_offset = le32_to_cpu(hdr->jt_offset);
+				table_size = le32_to_cpu(hdr->jt_size);
+			}
+
+			for (i = 0; i < table_size; i ++) {
+				dst_ptr[bo_offset + i] =
+					cpu_to_le32(le32_to_cpu(fw_data[table_offset + i]));
+			}
+			bo_offset += table_size;
 		} else {
-			fw_data = (const __be32 *)rdev->mec_fw->data;
-			table_offset = CP_MEC_TABLE_OFFSET;
-		}
+			const __be32 *fw_data;
+			table_size = CP_ME_TABLE_SIZE;
 
-		for (i = 0; i < CP_ME_TABLE_SIZE; i ++) {
-			dst_ptr[bo_offset + i] = cpu_to_le32(be32_to_cpu(fw_data[table_offset + i]));
+			if (me == 0) {
+				fw_data = (const __be32 *)rdev->ce_fw->data;
+				table_offset = CP_ME_TABLE_OFFSET;
+			} else if (me == 1) {
+				fw_data = (const __be32 *)rdev->pfp_fw->data;
+				table_offset = CP_ME_TABLE_OFFSET;
+			} else if (me == 2) {
+				fw_data = (const __be32 *)rdev->me_fw->data;
+				table_offset = CP_ME_TABLE_OFFSET;
+			} else {
+				fw_data = (const __be32 *)rdev->mec_fw->data;
+				table_offset = CP_MEC_TABLE_OFFSET;
+			}
+
+			for (i = 0; i < table_size; i ++) {
+				dst_ptr[bo_offset + i] =
+					cpu_to_le32(be32_to_cpu(fw_data[table_offset + i]));
+			}
+			bo_offset += table_size;
 		}
-		bo_offset += CP_ME_TABLE_SIZE;
 	}
 }
 
@@ -7332,17 +7672,17 @@ static inline u32 cik_get_ih_wptr(struct
 		wptr = RREG32(IH_RB_WPTR);
 
 	if (wptr & RB_OVERFLOW) {
+		wptr &= ~RB_OVERFLOW;
 		/* When a ring buffer overflow happen start parsing interrupt
 		 * from the last not overwritten vector (wptr + 16). Hopefully
 		 * this should allow us to catchup.
 		 */
-		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
-			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+			 wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
 		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_WPTR_OVERFLOW_CLEAR;
 		WREG32(IH_RB_CNTL, tmp);
-		wptr &= ~RB_OVERFLOW;
 	}
 	return (wptr & rdev->ih.ptr_mask);
 }
@@ -7583,7 +7923,8 @@ restart_ih:
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
 			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			if (radeon_use_pflipirq > 0)
+				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
@@ -7831,6 +8172,7 @@ restart_ih:
 		/* wptr/rptr are in bytes! */
 		rptr += 16;
 		rptr &= rdev->ih.ptr_mask;
+		WREG32(IH_RB_RPTR, rptr);
 	}
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
@@ -7839,7 +8181,6 @@ restart_ih:
 	if (queue_thermal)
 		schedule_work(&rdev->pm.dpm.thermal.work);
 	rdev->ih.rptr = rptr;
-	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	atomic_set(&rdev->ih.lock, 0);
 
 	/* make sure wptr hasn't changed while processing */
@@ -7865,6 +8206,7 @@ restart_ih:
 static int cik_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
+	u32 nop;
 	int r;
 
 	/* enable pcie gen2/3 link */
@@ -7998,9 +8340,18 @@ static int cik_startup(struct radeon_dev
 	}
 	cik_irq_set(rdev);
 
+	if (rdev->family == CHIP_HAWAII) {
+		if (rdev->new_fw)
+			nop = PACKET3(PACKET3_NOP, 0x3FFF);
+		else
+			nop = RADEON_CP_PACKET2;
+	} else {
+		nop = PACKET3(PACKET3_NOP, 0x3FFF);
+	}
+
 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-			     PACKET3(PACKET3_NOP, 0x3FFF));
+			     nop);
 	if (r)
 		return r;
 
@@ -8008,7 +8359,7 @@ static int cik_startup(struct radeon_dev
 	/* type-2 packets are deprecated on MEC, use type-3 instead */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
 	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
-			     PACKET3(PACKET3_NOP, 0x3FFF));
+			     nop);
 	if (r)
 		return r;
 	ring->me = 1; /* first MEC */
@@ -8019,7 +8370,7 @@ static int cik_startup(struct radeon_dev
 	/* type-2 packets are deprecated on MEC, use type-3 instead */
 	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
 	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
-			     PACKET3(PACKET3_NOP, 0x3FFF));
+			     nop);
 	if (r)
 		return r;
 	/* dGPU only have 1 MEC */
@@ -9133,6 +9484,9 @@ static void cik_pcie_gen3_enable(struct
 	int ret, i;
 	u16 tmp16;
 
+	if (pci_is_root_bus(rdev->pdev->bus))
+		return;
+
 	if (radeon_pcie_gen2 == 0)
 		return;
 
@@ -9359,7 +9713,8 @@ static void cik_program_aspm(struct rade
 			if (orig != data)
 				WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
 
-			if (!disable_clkreq) {
+			if (!disable_clkreq &&
+			    !pci_is_root_bus(rdev->pdev->bus)) {
 				struct pci_dev *root = rdev->pdev->bus->self;
 				u32 lnkcap;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/cik_sdma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/cik_sdma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/cik_sdma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/cik_sdma.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_ucode.h"
 #include "radeon_asic.h"
 #include "radeon_trace.h"
 #include "cikd.h"
@@ -118,6 +119,7 @@ void cik_sdma_set_wptr(struct radeon_dev
 		reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
 
 	WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+	(void)RREG32(reg);
 }
 
 /**
@@ -419,7 +421,6 @@ static int cik_sdma_rlc_resume(struct ra
  */
 static int cik_sdma_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
 	int i;
 
 	if (!rdev->sdma_fw)
@@ -428,19 +429,48 @@ static int cik_sdma_load_microcode(struc
 	/* halt the MEs */
 	cik_sdma_enable(rdev, false);
 
-	/* sdma0 */
-	fw_data = (const __be32 *)rdev->sdma_fw->data;
-	WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
-	for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
-		WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
-	WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+	if (rdev->new_fw) {
+		const struct sdma_firmware_header_v1_0 *hdr =
+			(const struct sdma_firmware_header_v1_0 *)rdev->sdma_fw->data;
+		const __le32 *fw_data;
+		u32 fw_size;
 
-	/* sdma1 */
-	fw_data = (const __be32 *)rdev->sdma_fw->data;
-	WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
-	for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
-		WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
-	WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+		radeon_ucode_print_sdma_hdr(&hdr->header);
+
+		/* sdma0 */
+		fw_data = (const __le32 *)
+			(rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+		fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+		WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+		for (i = 0; i < fw_size; i++)
+			WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+		WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+		/* sdma1 */
+		fw_data = (const __le32 *)
+			(rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+		fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+		WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+		for (i = 0; i < fw_size; i++)
+			WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+		WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+	} else {
+		const __be32 *fw_data;
+
+		/* sdma0 */
+		fw_data = (const __be32 *)rdev->sdma_fw->data;
+		WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+		for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+			WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+		WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+		/* sdma1 */
+		fw_data = (const __be32 *)rdev->sdma_fw->data;
+		WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+		for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+			WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+		WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+	}
 
 	WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
 	WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
@@ -459,13 +489,6 @@ int cik_sdma_resume(struct radeon_device
 {
 	int r;
 
-	/* Reset dma */
-	WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1);
-	RREG32(SRBM_SOFT_RESET);
-	udelay(50);
-	WREG32(SRBM_SOFT_RESET, 0);
-	RREG32(SRBM_SOFT_RESET);
-
 	r = cik_sdma_load_microcode(rdev);
 	if (r)
 		return r;
@@ -566,7 +589,7 @@ int cik_copy_dma(struct radeon_device *r
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
@@ -608,7 +631,7 @@ int cik_sdma_ring_test(struct radeon_dev
 	radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr));
 	radeon_ring_write(ring, 1); /* number of DWs to follow */
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = readl(ptr);
@@ -665,7 +688,7 @@ int cik_sdma_ib_test(struct radeon_devic
 	ib.ptr[4] = 0xDEADBEEF;
 	ib.length_dw = 5;
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		radeon_ib_free(rdev, &ib);
 		DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
@@ -719,7 +742,43 @@ bool cik_sdma_is_lockup(struct radeon_de
 }
 
 /**
- * cik_sdma_vm_set_page - update the page tables using sDMA
+ * cik_sdma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using sDMA (CIK).
+ */
+void cik_sdma_vm_copy_pages(struct radeon_device *rdev,
+			    struct radeon_ib *ib,
+			    uint64_t pe, uint64_t src,
+			    unsigned count)
+{
+	while (count) {
+		unsigned bytes = count * 8;
+		if (bytes > 0x1FFFF8)
+			bytes = 0x1FFFF8;
+
+		ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY,
+			SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+		ib->ptr[ib->length_dw++] = bytes;
+		ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
+		ib->ptr[ib->length_dw++] = lower_32_bits(src);
+		ib->ptr[ib->length_dw++] = upper_32_bits(src);
+		ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+
+		pe += bytes;
+		src += bytes;
+		count -= bytes / 8;
+	}
+}
+
+/**
+ * cik_sdma_vm_write_pages - update PTEs by writing them manually
  *
  * @rdev: radeon_device pointer
  * @ib: indirect buffer to fill with commands
@@ -729,84 +788,103 @@ bool cik_sdma_is_lockup(struct radeon_de
  * @incr: increase next addr by incr bytes
  * @flags: access flags
  *
- * Update the page tables using sDMA (CIK).
+ * Update PTEs by writing them manually using sDMA (CIK).
  */
-void cik_sdma_vm_set_page(struct radeon_device *rdev,
-			  struct radeon_ib *ib,
-			  uint64_t pe,
-			  uint64_t addr, unsigned count,
-			  uint32_t incr, uint32_t flags)
+void cik_sdma_vm_write_pages(struct radeon_device *rdev,
+			     struct radeon_ib *ib,
+			     uint64_t pe,
+			     uint64_t addr, unsigned count,
+			     uint32_t incr, uint32_t flags)
 {
 	uint64_t value;
 	unsigned ndw;
 
-	trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
-	if (flags == R600_PTE_GART) {
-		uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
-		while (count) {
-			unsigned bytes = count * 8;
-			if (bytes > 0x1FFFF8)
-				bytes = 0x1FFFF8;
-
-			ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
-			ib->ptr[ib->length_dw++] = bytes;
-			ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
-			ib->ptr[ib->length_dw++] = lower_32_bits(src);
-			ib->ptr[ib->length_dw++] = upper_32_bits(src);
-			ib->ptr[ib->length_dw++] = lower_32_bits(pe);
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe);
-
-			pe += bytes;
-			src += bytes;
-			count -= bytes / 8;
-		}
-	} else if (flags & R600_PTE_SYSTEM) {
-		while (count) {
-			ndw = count * 2;
-			if (ndw > 0xFFFFE)
-				ndw = 0xFFFFE;
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
 
-			/* for non-physically contiguous pages (system) */
-			ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
-			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 non-physically contiguous pages (system) */
+		ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+			SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+		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) {
+			if (flags & R600_PTE_SYSTEM) {
 				value = radeon_vm_map_gart(rdev, addr);
 				value &= 0xFFFFFFFFFFFFF000ULL;
-				addr += incr;
-				value |= flags;
-				ib->ptr[ib->length_dw++] = value;
-				ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			}
-		}
-	} else {
-		while (count) {
-			ndw = count;
-			if (ndw > 0x7FFFF)
-				ndw = 0x7FFFF;
-
-			if (flags & R600_PTE_VALID)
+			} else if (flags & R600_PTE_VALID) {
 				value = addr;
-			else
+			} else {
 				value = 0;
-			/* for physically contiguous pages (vram) */
-			ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
-			ib->ptr[ib->length_dw++] = pe; /* dst addr */
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe);
-			ib->ptr[ib->length_dw++] = flags; /* mask */
-			ib->ptr[ib->length_dw++] = 0;
-			ib->ptr[ib->length_dw++] = value; /* value */
+			}
+			addr += incr;
+			value |= flags;
+			ib->ptr[ib->length_dw++] = value;
 			ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			ib->ptr[ib->length_dw++] = incr; /* increment size */
-			ib->ptr[ib->length_dw++] = 0;
-			ib->ptr[ib->length_dw++] = ndw; /* number of entries */
-			pe += ndw * 8;
-			addr += ndw * incr;
-			count -= ndw;
 		}
 	}
+}
+
+/**
+ * cik_sdma_vm_set_pages - update the page tables using sDMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: access flags
+ *
+ * Update the page tables using sDMA (CIK).
+ */
+void cik_sdma_vm_set_pages(struct radeon_device *rdev,
+			   struct radeon_ib *ib,
+			   uint64_t pe,
+			   uint64_t addr, unsigned count,
+			   uint32_t incr, uint32_t flags)
+{
+	uint64_t value;
+	unsigned ndw;
+
+	while (count) {
+		ndw = count;
+		if (ndw > 0x7FFFF)
+			ndw = 0x7FFFF;
+
+		if (flags & R600_PTE_VALID)
+			value = addr;
+		else
+			value = 0;
+
+		/* for physically contiguous pages (vram) */
+		ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
+		ib->ptr[ib->length_dw++] = pe; /* dst addr */
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+		ib->ptr[ib->length_dw++] = flags; /* mask */
+		ib->ptr[ib->length_dw++] = 0;
+		ib->ptr[ib->length_dw++] = value; /* value */
+		ib->ptr[ib->length_dw++] = upper_32_bits(value);
+		ib->ptr[ib->length_dw++] = incr; /* increment size */
+		ib->ptr[ib->length_dw++] = 0;
+		ib->ptr[ib->length_dw++] = ndw; /* number of entries */
+
+		pe += ndw * 8;
+		addr += ndw * incr;
+		count -= ndw;
+	}
+}
+
+/**
+ * cik_sdma_vm_pad_ib - pad the IB to the required number of dw
+ *
+ * @ib: indirect buffer to fill with padding
+ *
+ */
+void cik_sdma_vm_pad_ib(struct radeon_ib *ib)
+{
 	while (ib->length_dw & 0x7)
 		ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ci_smc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ci_smc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ci_smc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ci_smc.c	2014-09-28 17:29:07.000000000 -0400
@@ -213,24 +213,37 @@ int ci_load_smc_ucode(struct radeon_devi
 	if (!rdev->smc_fw)
 		return -EINVAL;
 
-	switch (rdev->family) {
-	case CHIP_BONAIRE:
-		ucode_start_address = BONAIRE_SMC_UCODE_START;
-		ucode_size = BONAIRE_SMC_UCODE_SIZE;
-		break;
-	case CHIP_HAWAII:
-		ucode_start_address = HAWAII_SMC_UCODE_START;
-		ucode_size = HAWAII_SMC_UCODE_SIZE;
-		break;
-	default:
-		DRM_ERROR("unknown asic in smc ucode loader\n");
-		BUG();
+	if (rdev->new_fw) {
+		const struct smc_firmware_header_v1_0 *hdr =
+			(const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
+
+		radeon_ucode_print_smc_hdr(&hdr->header);
+
+		ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
+		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
+		src = (const u8 *)
+			(rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+	} else {
+		switch (rdev->family) {
+		case CHIP_BONAIRE:
+			ucode_start_address = BONAIRE_SMC_UCODE_START;
+			ucode_size = BONAIRE_SMC_UCODE_SIZE;
+			break;
+		case CHIP_HAWAII:
+			ucode_start_address = HAWAII_SMC_UCODE_START;
+			ucode_size = HAWAII_SMC_UCODE_SIZE;
+			break;
+		default:
+			DRM_ERROR("unknown asic in smc ucode loader\n");
+			BUG();
+		}
+
+		src = (const u8 *)rdev->smc_fw->data;
 	}
 
 	if (ucode_size & 3)
 		return -EINVAL;
 
-	src = (const u8 *)rdev->smc_fw->data;
 	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
 	WREG32(SMC_IND_INDEX_0, ucode_start_address);
 	WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/dce6_afmt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/dce6_afmt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/dce6_afmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/dce6_afmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,13 +136,13 @@ void dce6_afmt_write_latency_fields(stru
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
 				AUDIO_LIPSYNC(connector->audio_latency[1]);
 		else
-			tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
 	} else {
 		if (connector->latency_present[0])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[0]) |
 				AUDIO_LIPSYNC(connector->audio_latency[0]);
 		else
-			tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+			tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
 	}
 	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
 }
@@ -164,8 +164,10 @@ void dce6_afmt_write_speaker_allocation(
 	offset = dig->afmt->pin->offset;
 
 	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder)
+		if (connector->encoder == encoder) {
 			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
 	}
 
 	if (!radeon_connector) {
@@ -173,7 +175,7 @@ void dce6_afmt_write_speaker_allocation(
 		return;
 	}
 
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
 	if (sad_count <= 0) {
 		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
 		return;
@@ -225,8 +227,10 @@ void dce6_afmt_write_sad_regs(struct drm
 	offset = dig->afmt->pin->offset;
 
 	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder)
+		if (connector->encoder == encoder) {
 			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
 	}
 
 	if (!radeon_connector) {
@@ -234,7 +238,7 @@ void dce6_afmt_write_sad_regs(struct drm
 		return;
 	}
 
-	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
 	if (sad_count <= 0) {
 		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen.c	2014-09-28 17:29:07.000000000 -0400
@@ -2424,7 +2424,6 @@ static int evergreen_pcie_gart_enable(st
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Setup L2 cache */
 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
 				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
@@ -2677,7 +2676,7 @@ void evergreen_mc_resume(struct radeon_d
 		if (save->crtc_enabled[i]) {
 			if (ASIC_IS_DCE6(rdev)) {
 				tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
-				tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+				tmp &= ~EVERGREEN_CRTC_BLANK_DATA_EN;
 				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
 				WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
 				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
@@ -2870,7 +2869,7 @@ static int evergreen_cp_start(struct rad
 	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
 	radeon_ring_write(ring, 0);
 	radeon_ring_write(ring, 0);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	cp_me = 0xff;
 	WREG32(CP_ME_CNTL, cp_me);
@@ -2913,7 +2912,7 @@ static int evergreen_cp_start(struct rad
 	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
 	radeon_ring_write(ring, 0x00000010); /*  */
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	return 0;
 }
@@ -4023,7 +4022,8 @@ int sumo_rlc_init(struct radeon_device *
 		/* save restore block */
 		if (rdev->rlc.save_restore_obj == NULL) {
 			r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
-					     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj);
+					     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+					     &rdev->rlc.save_restore_obj);
 			if (r) {
 				dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r);
 				return r;
@@ -4101,7 +4101,8 @@ int sumo_rlc_init(struct radeon_device *
 
 		if (rdev->rlc.clear_state_obj == NULL) {
 			r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
-					     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.clear_state_obj);
+					     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+					     &rdev->rlc.clear_state_obj);
 			if (r) {
 				dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r);
 				sumo_rlc_fini(rdev);
@@ -4175,8 +4176,10 @@ int sumo_rlc_init(struct radeon_device *
 
 	if (rdev->rlc.cp_table_size) {
 		if (rdev->rlc.cp_table_obj == NULL) {
-			r = radeon_bo_create(rdev, rdev->rlc.cp_table_size, PAGE_SIZE, true,
-					     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.cp_table_obj);
+			r = radeon_bo_create(rdev, rdev->rlc.cp_table_size,
+					     PAGE_SIZE, true,
+					     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+					     &rdev->rlc.cp_table_obj);
 			if (r) {
 				dev_warn(rdev->dev, "(%d) create RLC cp table bo failed\n", r);
 				sumo_rlc_fini(rdev);
@@ -4746,17 +4749,17 @@ static u32 evergreen_get_ih_wptr(struct
 		wptr = RREG32(IH_RB_WPTR);
 
 	if (wptr & RB_OVERFLOW) {
+		wptr &= ~RB_OVERFLOW;
 		/* When a ring buffer overflow happen start parsing interrupt
 		 * from the last not overwritten vector (wptr + 16). Hopefully
 		 * this should allow us to catchup.
 		 */
-		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
-			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+			 wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
 		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_WPTR_OVERFLOW_CLEAR;
 		WREG32(IH_RB_CNTL, tmp);
-		wptr &= ~RB_OVERFLOW;
 	}
 	return (wptr & rdev->ih.ptr_mask);
 }
@@ -4961,7 +4964,8 @@ restart_ih:
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
 			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			if (radeon_use_pflipirq > 0)
+				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
@@ -5133,6 +5137,7 @@ restart_ih:
 		/* wptr/rptr are in bytes! */
 		rptr += 16;
 		rptr &= rdev->ih.ptr_mask;
+		WREG32(IH_RB_RPTR, rptr);
 	}
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
@@ -5141,7 +5146,6 @@ restart_ih:
 	if (queue_thermal && rdev->pm.dpm_enabled)
 		schedule_work(&rdev->pm.dpm.thermal.work);
 	rdev->ih.rptr = rptr;
-	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	atomic_set(&rdev->ih.lock, 0);
 
 	/* make sure wptr hasn't changed while processing */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -155,7 +155,7 @@ int evergreen_copy_dma(struct radeon_dev
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,7 +117,7 @@ static void dce4_afmt_write_speaker_allo
 		return;
 	}
 
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
 	if (sad_count <= 0) {
 		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
 		return;
@@ -172,7 +172,7 @@ static void evergreen_hdmi_write_sad_reg
 		return;
 	}
 
-	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
 	if (sad_count <= 0) {
 		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/kv_dpm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/kv_dpm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/kv_dpm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/kv_dpm.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,8 @@
 #define KV_MINIMUM_ENGINE_CLOCK         800
 #define SMC_RAM_END                     0x40000
 
+static int kv_enable_nb_dpm(struct radeon_device *rdev,
+			    bool enable);
 static void kv_init_graphics_levels(struct radeon_device *rdev);
 static int kv_calculate_ds_divider(struct radeon_device *rdev);
 static int kv_calculate_nbps_level_settings(struct radeon_device *rdev);
@@ -1295,6 +1297,9 @@ void kv_dpm_disable(struct radeon_device
 {
 	kv_smc_bapm_enable(rdev, false);
 
+	if (rdev->family == CHIP_MULLINS)
+		kv_enable_nb_dpm(rdev, false);
+
 	/* powerup blocks */
 	kv_dpm_powergate_acp(rdev, false);
 	kv_dpm_powergate_samu(rdev, false);
@@ -1438,14 +1443,14 @@ static int kv_update_uvd_dpm(struct rade
 	return kv_enable_uvd_dpm(rdev, !gate);
 }
 
-static u8 kv_get_vce_boot_level(struct radeon_device *rdev)
+static u8 kv_get_vce_boot_level(struct radeon_device *rdev, u32 evclk)
 {
 	u8 i;
 	struct radeon_vce_clock_voltage_dependency_table *table =
 		&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
 
 	for (i = 0; i < table->count; i++) {
-		if (table->entries[i].evclk >= 0) /* XXX */
+		if (table->entries[i].evclk >= evclk)
 			break;
 	}
 
@@ -1468,7 +1473,7 @@ static int kv_update_vce_dpm(struct rade
 		if (pi->caps_stable_p_state)
 			pi->vce_boot_level = table->count - 1;
 		else
-			pi->vce_boot_level = kv_get_vce_boot_level(rdev);
+			pi->vce_boot_level = kv_get_vce_boot_level(rdev, radeon_new_state->evclk);
 
 		ret = kv_copy_bytes_to_smc(rdev,
 					   pi->dpm_table_start +
@@ -1769,15 +1774,24 @@ static int kv_update_dfs_bypass_settings
 	return ret;
 }
 
-static int kv_enable_nb_dpm(struct radeon_device *rdev)
+static int kv_enable_nb_dpm(struct radeon_device *rdev,
+			    bool enable)
 {
 	struct kv_power_info *pi = kv_get_pi(rdev);
 	int ret = 0;
 
-	if (pi->enable_nb_dpm && !pi->nb_dpm_enabled) {
-		ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_NBDPM_Enable);
-		if (ret == 0)
-			pi->nb_dpm_enabled = true;
+	if (enable) {
+		if (pi->enable_nb_dpm && !pi->nb_dpm_enabled) {
+			ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_NBDPM_Enable);
+			if (ret == 0)
+				pi->nb_dpm_enabled = true;
+		}
+	} else {
+		if (pi->enable_nb_dpm && pi->nb_dpm_enabled) {
+			ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_NBDPM_Disable);
+			if (ret == 0)
+				pi->nb_dpm_enabled = false;
+		}
 	}
 
 	return ret;
@@ -1864,7 +1878,7 @@ int kv_dpm_set_power_state(struct radeon
 			}
 			kv_update_sclk_t(rdev);
 			if (rdev->family == CHIP_MULLINS)
-				kv_enable_nb_dpm(rdev);
+				kv_enable_nb_dpm(rdev, true);
 		}
 	} else {
 		if (pi->enable_dpm) {
@@ -1889,7 +1903,7 @@ int kv_dpm_set_power_state(struct radeon
 			}
 			kv_update_acp_boot_level(rdev);
 			kv_update_sclk_t(rdev);
-			kv_enable_nb_dpm(rdev);
+			kv_enable_nb_dpm(rdev, true);
 		}
 	}
 
@@ -2726,7 +2740,10 @@ int kv_dpm_init(struct radeon_device *rd
 	pi->caps_sclk_ds = true;
 	pi->enable_auto_thermal_throttling = true;
 	pi->disable_nb_ps3_in_battery = false;
-	pi->bapm_enable = true;
+	if (radeon_bapm == 0)
+		pi->bapm_enable = false;
+	else
+		pi->bapm_enable = true;
 	pi->voltage_drop_t = 0;
 	pi->caps_sclk_throttle_low_notification = false;
 	pi->caps_fps = false; /* true? */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -76,11 +76,11 @@ radeon-y += radeon_device.o radeon_asic.
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
 	evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
 	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
-	si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
+	si_blit_shaders.o radeon_prime.o cik.o cik_blit_shaders.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
 	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
 	trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
-	ci_dpm.o dce6_afmt.o radeon_vm.o
+	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o
 
 # add async DMA block
 radeon-y += \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ni.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ni.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ni.c	2014-08-07 04:46:20.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ni.c	2014-09-28 21:27:03.000000000 -0400
@@ -1209,7 +1209,6 @@ static int cayman_pcie_gart_enable(struc
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Setup TLB control */
 	WREG32(MC_VM_MX_L1_TLB_CNTL,
 	       (0xA << 7) |
@@ -1252,7 +1251,7 @@ static int cayman_pcie_gart_enable(struc
 		WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
 		WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
 		WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-			rdev->gart.table_addr >> 12);
+		       rdev->vm_manager.saved_table_addr[i]);
 	}
 
 	/* enable context1-7 */
@@ -1284,6 +1283,13 @@ static int cayman_pcie_gart_enable(struc
 
 static void cayman_pcie_gart_disable(struct radeon_device *rdev)
 {
+	unsigned i;
+
+	for (i = 1; i < 8; ++i) {
+		rdev->vm_manager.saved_table_addr[i] = RREG32(
+			VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2));
+	}
+
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
 	WREG32(VM_CONTEXT1_CNTL, 0);
@@ -1486,7 +1492,7 @@ static int cayman_cp_start(struct radeon
 	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
 	radeon_ring_write(ring, 0);
 	radeon_ring_write(ring, 0);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	cayman_cp_enable(rdev, true);
 
@@ -1528,7 +1534,7 @@ static int cayman_cp_start(struct radeon
 	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
 	radeon_ring_write(ring, 0x00000010); /*  */
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	/* XXX init other rings */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ni_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ni_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/ni_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/ni_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -191,12 +191,6 @@ int cayman_dma_resume(struct radeon_devi
 	u32 reg_offset, wb_offset;
 	int i, r;
 
-	/* Reset dma */
-	WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
-	RREG32(SRBM_SOFT_RESET);
-	udelay(50);
-	WREG32(SRBM_SOFT_RESET, 0);
-
 	for (i = 0; i < 2; i++) {
 		if (i == 0) {
 			ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
@@ -307,7 +301,43 @@ bool cayman_dma_is_lockup(struct radeon_
 }
 
 /**
- * cayman_dma_vm_set_page - update the page tables using the DMA
+ * cayman_dma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr where to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using the DMA (cayman/TN).
+ */
+void cayman_dma_vm_copy_pages(struct radeon_device *rdev,
+			      struct radeon_ib *ib,
+			      uint64_t pe, uint64_t src,
+			      unsigned count)
+{
+	unsigned ndw;
+
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
+
+		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
+						      0, 0, ndw);
+		ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+		ib->ptr[ib->length_dw++] = lower_32_bits(src);
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
+
+		pe += ndw * 4;
+		src += ndw * 4;
+		count -= ndw / 2;
+	}
+}
+
+/**
+ * cayman_dma_vm_write_pages - update PTEs by writing them manually
  *
  * @rdev: radeon_device pointer
  * @ib: indirect buffer to fill with commands
@@ -315,71 +345,103 @@ bool cayman_dma_is_lockup(struct radeon_
  * @addr: dst addr to write into pe
  * @count: number of page entries to update
  * @incr: increase next addr by incr bytes
- * @flags: hw access flags 
+ * @flags: hw access flags
  *
- * Update the page tables using the DMA (cayman/TN).
+ * Update PTEs by writing them manually using the DMA (cayman/TN).
  */
-void cayman_dma_vm_set_page(struct radeon_device *rdev,
-			    struct radeon_ib *ib,
-			    uint64_t pe,
-			    uint64_t addr, unsigned count,
-			    uint32_t incr, uint32_t flags)
+void cayman_dma_vm_write_pages(struct radeon_device *rdev,
+			       struct radeon_ib *ib,
+			       uint64_t pe,
+			       uint64_t addr, unsigned count,
+			       uint32_t incr, uint32_t flags)
 {
 	uint64_t value;
 	unsigned ndw;
 
-	trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
-	if ((flags & R600_PTE_SYSTEM) || (count == 1)) {
-		while (count) {
-			ndw = count * 2;
-			if (ndw > 0xFFFFE)
-				ndw = 0xFFFFE;
-
-			/* for non-physically contiguous pages (system) */
-			ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw);
-			ib->ptr[ib->length_dw++] = pe;
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
-			for (; ndw > 0; ndw -= 2, --count, pe += 8) {
-				if (flags & R600_PTE_SYSTEM) {
-					value = radeon_vm_map_gart(rdev, addr);
-					value &= 0xFFFFFFFFFFFFF000ULL;
-				} else if (flags & R600_PTE_VALID) {
-					value = addr;
-				} else {
-					value = 0;
-				}
-				addr += incr;
-				value |= flags;
-				ib->ptr[ib->length_dw++] = value;
-				ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			}
-		}
-	} else {
-		while (count) {
-			ndw = count * 2;
-			if (ndw > 0xFFFFE)
-				ndw = 0xFFFFE;
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
 
-			if (flags & R600_PTE_VALID)
+		/* for non-physically contiguous pages (system) */
+		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE,
+						      0, 0, ndw);
+		ib->ptr[ib->length_dw++] = pe;
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+			if (flags & R600_PTE_SYSTEM) {
+				value = radeon_vm_map_gart(rdev, addr);
+				value &= 0xFFFFFFFFFFFFF000ULL;
+			} else if (flags & R600_PTE_VALID) {
 				value = addr;
-			else
+			} else {
 				value = 0;
-			/* for physically contiguous pages (vram) */
-			ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
-			ib->ptr[ib->length_dw++] = pe; /* dst addr */
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
-			ib->ptr[ib->length_dw++] = flags; /* mask */
-			ib->ptr[ib->length_dw++] = 0;
-			ib->ptr[ib->length_dw++] = value; /* value */
+			}
+			addr += incr;
+			value |= flags;
+			ib->ptr[ib->length_dw++] = value;
 			ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			ib->ptr[ib->length_dw++] = incr; /* increment size */
-			ib->ptr[ib->length_dw++] = 0;
-			pe += ndw * 4;
-			addr += (ndw / 2) * incr;
-			count -= ndw / 2;
 		}
 	}
+}
+
+/**
+ * cayman_dma_vm_set_pages - update the page tables using the DMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: hw access flags
+ *
+ * Update the page tables using the DMA (cayman/TN).
+ */
+void cayman_dma_vm_set_pages(struct radeon_device *rdev,
+			     struct radeon_ib *ib,
+			     uint64_t pe,
+			     uint64_t addr, unsigned count,
+			     uint32_t incr, uint32_t flags)
+{
+	uint64_t value;
+	unsigned ndw;
+
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
+
+		if (flags & R600_PTE_VALID)
+			value = addr;
+		else
+			value = 0;
+
+		/* for physically contiguous pages (vram) */
+		ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+		ib->ptr[ib->length_dw++] = pe; /* dst addr */
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		ib->ptr[ib->length_dw++] = flags; /* mask */
+		ib->ptr[ib->length_dw++] = 0;
+		ib->ptr[ib->length_dw++] = value; /* value */
+		ib->ptr[ib->length_dw++] = upper_32_bits(value);
+		ib->ptr[ib->length_dw++] = incr; /* increment size */
+		ib->ptr[ib->length_dw++] = 0;
+
+		pe += ndw * 4;
+		addr += (ndw / 2) * incr;
+		count -= ndw / 2;
+	}
+}
+
+/**
+ * cayman_dma_vm_pad_ib - pad the IB to the required number of dw
+ *
+ * @ib: indirect buffer to fill with padding
+ *
+ */
+void cayman_dma_vm_pad_ib(struct radeon_ib *ib)
+{
 	while (ib->length_dw & 0x7)
 		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r100.c	2014-08-07 04:46:09.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r100.c	2014-09-28 21:26:52.000000000 -0400
@@ -646,7 +646,6 @@ int r100_pci_gart_enable(struct radeon_d
 {
 	uint32_t tmp;
 
-	radeon_gart_restore(rdev);
 	/* discard memory request outside of configured range */
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
 	WREG32(RADEON_AIC_CNTL, tmp);
@@ -677,7 +676,7 @@ void r100_pci_gart_disable(struct radeon
 }
 
 void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i,
-			    uint64_t addr)
+			    uint64_t addr, uint32_t flags)
 {
 	u32 *gtt = rdev->gart.ptr;
 	gtt[i] = cpu_to_le32(lower_32_bits(addr));
@@ -816,6 +815,20 @@ u32 r100_get_vblank_counter(struct radeo
 		return RREG32(RADEON_CRTC2_CRNT_FRAME);
 }
 
+/**
+ * r100_ring_hdp_flush - flush Host Data Path via the ring buffer
+ * rdev: radeon device structure
+ * ring: ring buffer struct for emitting packets
+ */
+static void r100_ring_hdp_flush(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(ring, rdev->config.r100.hdp_cntl |
+				RADEON_HDP_READ_BUFFER_INVALIDATE);
+	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(ring, rdev->config.r100.hdp_cntl);
+}
+
 /* Who ever call radeon_fence_emit should call ring_lock and ask
  * for enough space (today caller are ib schedule and buffer move) */
 void r100_fence_ring_emit(struct radeon_device *rdev,
@@ -832,11 +845,7 @@ void r100_fence_ring_emit(struct radeon_
 	/* Wait until IDLE & CLEAN */
 	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
 	radeon_ring_write(ring, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
-	radeon_ring_write(ring, rdev->config.r100.hdp_cntl |
-				RADEON_HDP_READ_BUFFER_INVALIDATE);
-	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
-	radeon_ring_write(ring, rdev->config.r100.hdp_cntl);
+	r100_ring_hdp_flush(rdev, ring);
 	/* Emit fence sequence & fire IRQ */
 	radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0));
 	radeon_ring_write(ring, fence->seq);
@@ -924,7 +933,7 @@ int r100_copy_blit(struct radeon_device
 	if (fence) {
 		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
 	}
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	return r;
 }
 
@@ -957,7 +966,7 @@ void r100_ring_start(struct radeon_devic
 			  RADEON_ISYNC_ANY3D_IDLE2D |
 			  RADEON_ISYNC_WAIT_IDLEGUI |
 			  RADEON_ISYNC_CPSCRATCH_IDLEGUI);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 }
 
 
@@ -1395,7 +1404,6 @@ int r100_cs_parse_packet0(struct radeon_
  */
 int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 {
-	struct drm_mode_object *obj;
 	struct drm_crtc *crtc;
 	struct radeon_crtc *radeon_crtc;
 	struct radeon_cs_packet p3reloc, waitreloc;
@@ -1435,12 +1443,11 @@ int r100_cs_packet_parse_vline(struct ra
 	header = radeon_get_ib_value(p, h_idx);
 	crtc_id = radeon_get_ib_value(p, h_idx + 5);
 	reg = R100_CP_PACKET0_GET_REG(header);
-	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
-	if (!obj) {
+	crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+	if (!crtc) {
 		DRM_ERROR("cannot find crtc %d\n", crtc_id);
 		return -ENOENT;
 	}
-	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
 	crtc_id = radeon_crtc->crtc_id;
 
@@ -3625,7 +3632,7 @@ int r100_ring_test(struct radeon_device
 	}
 	radeon_ring_write(ring, PACKET0(scratch, 0));
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = RREG32(scratch);
 		if (tmp == 0xDEADBEEF) {
@@ -3687,7 +3694,7 @@ int r100_ib_test(struct radeon_device *r
 	ib.ptr[6] = PACKET2(0);
 	ib.ptr[7] = PACKET2(0);
 	ib.length_dw = 8;
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
 		goto free_ib;
@@ -4061,39 +4068,6 @@ int r100_init(struct radeon_device *rdev
 	return 0;
 }
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
-		      bool always_indirect)
-{
-	if (reg < rdev->rmmio_size && !always_indirect)
-		return readl(((void __iomem *)rdev->rmmio) + reg);
-	else {
-		unsigned long flags;
-		uint32_t ret;
-
-		spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
-		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-		ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
-		spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
-
-		return ret;
-	}
-}
-
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
-		  bool always_indirect)
-{
-	if (reg < rdev->rmmio_size && !always_indirect)
-		writel(v, ((void __iomem *)rdev->rmmio) + reg);
-	else {
-		unsigned long flags;
-
-		spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
-		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
-		spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
-	}
-}
-
 u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
 {
 	if (reg < rdev->rio_mem_size)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r200.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r200.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r200.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,7 +121,7 @@ int r200_copy_dma(struct radeon_device *
 	if (fence) {
 		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
 	}
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r300.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r300.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r300.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r300.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,17 +69,23 @@ void rv370_pcie_gart_tlb_flush(struct ra
 	mb();
 }
 
+#define R300_PTE_UNSNOOPED (1 << 0)
 #define R300_PTE_WRITEABLE (1 << 2)
 #define R300_PTE_READABLE  (1 << 3)
 
 void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i,
-			      uint64_t addr)
+			      uint64_t addr, uint32_t flags)
 {
 	void __iomem *ptr = rdev->gart.ptr;
 
 	addr = (lower_32_bits(addr) >> 8) |
-	       ((upper_32_bits(addr) & 0xff) << 24) |
-	       R300_PTE_WRITEABLE | R300_PTE_READABLE;
+		((upper_32_bits(addr) & 0xff) << 24);
+	if (flags & RADEON_GART_PAGE_READ)
+		addr |= R300_PTE_READABLE;
+	if (flags & RADEON_GART_PAGE_WRITE)
+		addr |= R300_PTE_WRITEABLE;
+	if (!(flags & RADEON_GART_PAGE_SNOOP))
+		addr |= R300_PTE_UNSNOOPED;
 	/* on x86 we want this to be CPU endian, on powerpc
 	 * on powerpc without HW swappers, it'll get swapped on way
 	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
@@ -120,7 +126,6 @@ int rv370_pcie_gart_enable(struct radeon
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* discard memory request outside of configured range */
 	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
@@ -290,7 +295,7 @@ void r300_ring_start(struct radeon_devic
 	radeon_ring_write(ring,
 			  R300_GEOMETRY_ROUND_NEAREST |
 			  R300_COLOR_ROUND_NEAREST);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 }
 
 static void r300_errata(struct radeon_device *rdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r420.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r420.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r420.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r420.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,7 @@ static void r420_cp_errata_init(struct r
 	radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1));
 	radeon_ring_write(ring, rdev->config.r300.resync_scratch);
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 }
 
 static void r420_cp_errata_fini(struct radeon_device *rdev)
@@ -232,7 +232,7 @@ static void r420_cp_errata_fini(struct r
 	radeon_ring_lock(rdev, ring, 8);
 	radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
 	radeon_ring_write(ring, R300_RB3D_DC_FINISH);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_scratch_free(rdev, rdev->config.r300.resync_scratch);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600.c	2014-08-07 04:46:13.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600.c	2014-09-28 21:26:57.000000000 -0400
@@ -920,7 +920,6 @@ static int r600_pcie_gart_enable(struct
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 
 	/* Setup L2 cache */
 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
@@ -1291,7 +1290,7 @@ int r600_vram_scratch_init(struct radeon
 	if (rdev->vram_scratch.robj == NULL) {
 		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     NULL, &rdev->vram_scratch.robj);
+				     0, NULL, &rdev->vram_scratch.robj);
 		if (r) {
 			return r;
 		}
@@ -1765,7 +1764,6 @@ static void r600_gpu_init(struct radeon_
 {
 	u32 tiling_config;
 	u32 ramcfg;
-	u32 cc_rb_backend_disable;
 	u32 cc_gc_shader_pipe_config;
 	u32 tmp;
 	int i, j;
@@ -1892,29 +1890,20 @@ static void r600_gpu_init(struct radeon_
 	}
 	tiling_config |= BANK_SWAPS(1);
 
-	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-	tmp = R6XX_MAX_BACKENDS -
-		r600_count_pipe_bits((cc_rb_backend_disable >> 16) & R6XX_MAX_BACKENDS_MASK);
-	if (tmp < rdev->config.r600.max_backends) {
-		rdev->config.r600.max_backends = tmp;
-	}
-
 	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00;
-	tmp = R6XX_MAX_PIPES -
-		r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R6XX_MAX_PIPES_MASK);
-	if (tmp < rdev->config.r600.max_pipes) {
-		rdev->config.r600.max_pipes = tmp;
-	}
-	tmp = R6XX_MAX_SIMDS -
-		r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK);
-	if (tmp < rdev->config.r600.max_simds) {
-		rdev->config.r600.max_simds = tmp;
-	}
 	tmp = rdev->config.r600.max_simds -
 		r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK);
 	rdev->config.r600.active_simds = tmp;
 
 	disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK;
+	tmp = 0;
+	for (i = 0; i < rdev->config.r600.max_backends; i++)
+		tmp |= (1 << i);
+	/* if all the backends are disabled, fix it up here */
+	if ((disabled_rb_mask & tmp) == tmp) {
+		for (i = 0; i < rdev->config.r600.max_backends; i++)
+			disabled_rb_mask &= ~(1 << i);
+	}
 	tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT;
 	tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends,
 					R6XX_MAX_BACKENDS, disabled_rb_mask);
@@ -2500,7 +2489,7 @@ int r600_cp_start(struct radeon_device *
 	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
 	radeon_ring_write(ring, 0);
 	radeon_ring_write(ring, 0);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	cp_me = 0xff;
 	WREG32(R_0086D8_CP_ME_CNTL, cp_me);
@@ -2636,7 +2625,7 @@ int r600_ring_test(struct radeon_device
 	radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
 	radeon_ring_write(ring, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = RREG32(scratch);
 		if (tmp == 0xDEADBEEF)
@@ -2706,6 +2695,17 @@ void r600_fence_ring_emit(struct radeon_
 	}
 }
 
+/**
+ * r600_semaphore_ring_emit - emit a semaphore on the CP ring
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring buffer object
+ * @semaphore: radeon semaphore object
+ * @emit_wait: Is this a sempahore wait?
+ *
+ * Emits a semaphore signal/wait packet to the CP ring and prevents the PFP
+ * from running ahead of semaphore waits.
+ */
 bool r600_semaphore_ring_emit(struct radeon_device *rdev,
 			      struct radeon_ring *ring,
 			      struct radeon_semaphore *semaphore,
@@ -2721,6 +2721,13 @@ bool r600_semaphore_ring_emit(struct rad
 	radeon_ring_write(ring, lower_32_bits(addr));
 	radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel);
 
+	/* PFP_SYNC_ME packet only exists on 7xx+, only enable it on eg+ */
+	if (emit_wait && (rdev->family >= CHIP_CEDAR)) {
+		/* Prevent the PFP from running ahead of the semaphore wait */
+		radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+		radeon_ring_write(ring, 0x0);
+	}
+
 	return true;
 }
 
@@ -2798,7 +2805,7 @@ int r600_copy_cpdma(struct radeon_device
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
@@ -3118,7 +3125,7 @@ int r600_ib_test(struct radeon_device *r
 	ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
 	ib.ptr[2] = 0xDEADBEEF;
 	ib.length_dw = 3;
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
 		goto free_ib;
@@ -3179,7 +3186,7 @@ int r600_ih_ring_alloc(struct radeon_dev
 	if (rdev->ih.ring_obj == NULL) {
 		r = radeon_bo_create(rdev, rdev->ih.ring_size,
 				     PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_GTT,
+				     RADEON_GEM_DOMAIN_GTT, 0,
 				     NULL, &rdev->ih.ring_obj);
 		if (r) {
 			DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r);
@@ -3737,17 +3744,17 @@ static u32 r600_get_ih_wptr(struct radeo
 		wptr = RREG32(IH_RB_WPTR);
 
 	if (wptr & RB_OVERFLOW) {
+		wptr &= ~RB_OVERFLOW;
 		/* When a ring buffer overflow happen start parsing interrupt
 		 * from the last not overwritten vector (wptr + 16). Hopefully
 		 * this should allow us to catchup.
 		 */
-		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
-			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+			 wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
 		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_WPTR_OVERFLOW_CLEAR;
 		WREG32(IH_RB_CNTL, tmp);
-		wptr &= ~RB_OVERFLOW;
 	}
 	return (wptr & rdev->ih.ptr_mask);
 }
@@ -3876,11 +3883,13 @@ restart_ih:
 			break;
 		case 9: /* D1 pflip */
 			DRM_DEBUG("IH: D1 flip\n");
-			radeon_crtc_handle_flip(rdev, 0);
+			if (radeon_use_pflipirq > 0)
+				radeon_crtc_handle_flip(rdev, 0);
 			break;
 		case 11: /* D2 pflip */
 			DRM_DEBUG("IH: D2 flip\n");
-			radeon_crtc_handle_flip(rdev, 1);
+			if (radeon_use_pflipirq > 0)
+				radeon_crtc_handle_flip(rdev, 1);
 			break;
 		case 19: /* HPD/DAC hotplug */
 			switch (src_data) {
@@ -3991,6 +4000,7 @@ restart_ih:
 		/* wptr/rptr are in bytes! */
 		rptr += 16;
 		rptr &= rdev->ih.ptr_mask;
+		WREG32(IH_RB_RPTR, rptr);
 	}
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
@@ -3999,7 +4009,6 @@ restart_ih:
 	if (queue_thermal && rdev->pm.dpm_enabled)
 		schedule_work(&rdev->pm.dpm.thermal.work);
 	rdev->ih.rptr = rptr;
-	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	atomic_set(&rdev->ih.lock, 0);
 
 	/* make sure wptr hasn't changed while processing */
@@ -4041,16 +4050,15 @@ int r600_debugfs_mc_info_init(struct rad
 }
 
 /**
- * r600_ioctl_wait_idle - flush host path cache on wait idle ioctl
+ * r600_mmio_hdp_flush - flush Host Data Path cache via MMIO
  * rdev: radeon device structure
- * bo: buffer object struct which userspace is waiting for idle
  *
- * Some R6XX/R7XX doesn't seems to take into account HDP flush performed
- * through ring buffer, this leads to corruption in rendering, see
- * http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we
- * directly perform HDP flush by writing register through MMIO.
+ * Some R6XX/R7XX don't seem to take into account HDP flushes performed
+ * through the ring buffer. This leads to corruption in rendering, see
+ * http://bugzilla.kernel.org/show_bug.cgi?id=15186 . To avoid this, we
+ * directly perform the HDP flush by writing the register through MMIO.
  */
-void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
+void r600_mmio_hdp_flush(struct radeon_device *rdev)
 {
 	/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
 	 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600_cs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -825,7 +825,6 @@ int r600_cs_common_vline_parse(struct ra
 			       uint32_t *vline_start_end,
 			       uint32_t *vline_status)
 {
-	struct drm_mode_object *obj;
 	struct drm_crtc *crtc;
 	struct radeon_crtc *radeon_crtc;
 	struct radeon_cs_packet p3reloc, wait_reg_mem;
@@ -887,12 +886,11 @@ int r600_cs_common_vline_parse(struct ra
 	crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
 	reg = R600_CP_PACKET0_GET_REG(header);
 
-	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
-	if (!obj) {
+	crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+	if (!crtc) {
 		DRM_ERROR("cannot find crtc %d\n", crtc_id);
 		return -ENOENT;
 	}
-	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
 	crtc_id = radeon_crtc->crtc_id;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600d.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600d.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600d.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600d.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,13 +44,6 @@
 #define R6XX_MAX_PIPES				8
 #define R6XX_MAX_PIPES_MASK			0xff
 
-/* PTE flags */
-#define PTE_VALID				(1 << 0)
-#define PTE_SYSTEM				(1 << 1)
-#define PTE_SNOOPED				(1 << 2)
-#define PTE_READABLE				(1 << 5)
-#define PTE_WRITEABLE				(1 << 6)
-
 /* tiling bits */
 #define     ARRAY_LINEAR_GENERAL              0x00000000
 #define     ARRAY_LINEAR_ALIGNED              0x00000001
@@ -1597,6 +1590,7 @@
 		 */
 #              define PACKET3_CP_DMA_CMD_SAIC      (1 << 28)
 #              define PACKET3_CP_DMA_CMD_DAIC      (1 << 29)
+#define	PACKET3_PFP_SYNC_ME				0x42 /* r7xx+ only */
 #define	PACKET3_SURFACE_SYNC				0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_FULL_CACHE_ENA       (1 << 20) /* r7xx+ only */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/r600_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/r600_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,15 +124,6 @@ int r600_dma_resume(struct radeon_device
 	u32 rb_bufsz;
 	int r;
 
-	/* Reset dma */
-	if (rdev->family >= CHIP_RV770)
-		WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA);
-	else
-		WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
-	RREG32(SRBM_SOFT_RESET);
-	udelay(50);
-	WREG32(SRBM_SOFT_RESET, 0);
-
 	WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0);
 	WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0);
 
@@ -261,7 +252,7 @@ int r600_dma_ring_test(struct radeon_dev
 	radeon_ring_write(ring, rdev->vram_scratch.gpu_addr & 0xfffffffc);
 	radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xff);
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = readl(ptr);
@@ -368,7 +359,7 @@ int r600_dma_ib_test(struct radeon_devic
 	ib.ptr[3] = 0xDEADBEEF;
 	ib.length_dw = 4;
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		radeon_ib_free(rdev, &ib);
 		DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
@@ -493,7 +484,7 @@ int r600_copy_dma(struct radeon_device *
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,7 +194,7 @@ static struct radeon_asic r100_asic = {
 	.resume = &r100_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r100_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r100_mc_wait_for_idle,
 	.gart = {
@@ -260,7 +260,7 @@ static struct radeon_asic r200_asic = {
 	.resume = &r100_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r100_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r100_mc_wait_for_idle,
 	.gart = {
@@ -340,7 +340,7 @@ static struct radeon_asic r300_asic = {
 	.resume = &r300_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r300_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
 	.gart = {
@@ -406,7 +406,7 @@ static struct radeon_asic r300_asic_pcie
 	.resume = &r300_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r300_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
 	.gart = {
@@ -472,7 +472,7 @@ static struct radeon_asic r420_asic = {
 	.resume = &r420_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r300_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
 	.gart = {
@@ -538,7 +538,7 @@ static struct radeon_asic rs400_asic = {
 	.resume = &rs400_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &r300_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs400_mc_wait_for_idle,
 	.gart = {
@@ -604,7 +604,7 @@ static struct radeon_asic rs600_asic = {
 	.resume = &rs600_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &rs600_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs600_mc_wait_for_idle,
 	.gart = {
@@ -672,7 +672,7 @@ static struct radeon_asic rs690_asic = {
 	.resume = &rs690_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &rs600_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs690_mc_wait_for_idle,
 	.gart = {
@@ -740,7 +740,7 @@ static struct radeon_asic rv515_asic = {
 	.resume = &rv515_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &rs600_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rv515_mc_wait_for_idle,
 	.gart = {
@@ -806,7 +806,7 @@ static struct radeon_asic r520_asic = {
 	.resume = &r520_resume,
 	.vga_set_state = &r100_vga_set_state,
 	.asic_reset = &rs600_asic_reset,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r520_mc_wait_for_idle,
 	.gart = {
@@ -898,7 +898,7 @@ static struct radeon_asic r600_asic = {
 	.resume = &r600_resume,
 	.vga_set_state = &r600_vga_set_state,
 	.asic_reset = &r600_asic_reset,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
@@ -970,7 +970,7 @@ static struct radeon_asic rv6xx_asic = {
 	.resume = &r600_resume,
 	.vga_set_state = &r600_vga_set_state,
 	.asic_reset = &r600_asic_reset,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
@@ -1060,7 +1060,7 @@ static struct radeon_asic rs780_asic = {
 	.resume = &r600_resume,
 	.vga_set_state = &r600_vga_set_state,
 	.asic_reset = &r600_asic_reset,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
@@ -1163,7 +1163,7 @@ static struct radeon_asic rv770_asic = {
 	.resume = &rv770_resume,
 	.asic_reset = &r600_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
@@ -1281,7 +1281,7 @@ static struct radeon_asic evergreen_asic
 	.resume = &evergreen_resume,
 	.asic_reset = &evergreen_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
@@ -1373,7 +1373,7 @@ static struct radeon_asic sumo_asic = {
 	.resume = &evergreen_resume,
 	.asic_reset = &evergreen_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
@@ -1464,7 +1464,7 @@ static struct radeon_asic btc_asic = {
 	.resume = &evergreen_resume,
 	.asic_reset = &evergreen_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
@@ -1599,7 +1599,7 @@ static struct radeon_asic cayman_asic =
 	.resume = &cayman_resume,
 	.asic_reset = &cayman_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
@@ -1611,7 +1611,10 @@ static struct radeon_asic cayman_asic =
 	.vm = {
 		.init = &cayman_vm_init,
 		.fini = &cayman_vm_fini,
-		.set_page = &cayman_dma_vm_set_page,
+		.copy_pages = &cayman_dma_vm_copy_pages,
+		.write_pages = &cayman_dma_vm_write_pages,
+		.set_pages = &cayman_dma_vm_set_pages,
+		.pad_ib = &cayman_dma_vm_pad_ib,
 	},
 	.ring = {
 		[RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
@@ -1699,7 +1702,7 @@ static struct radeon_asic trinity_asic =
 	.resume = &cayman_resume,
 	.asic_reset = &cayman_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
@@ -1711,7 +1714,10 @@ static struct radeon_asic trinity_asic =
 	.vm = {
 		.init = &cayman_vm_init,
 		.fini = &cayman_vm_fini,
-		.set_page = &cayman_dma_vm_set_page,
+		.copy_pages = &cayman_dma_vm_copy_pages,
+		.write_pages = &cayman_dma_vm_write_pages,
+		.set_pages = &cayman_dma_vm_set_pages,
+		.pad_ib = &cayman_dma_vm_pad_ib,
 	},
 	.ring = {
 		[RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
@@ -1829,7 +1835,7 @@ static struct radeon_asic si_asic = {
 	.resume = &si_resume,
 	.asic_reset = &si_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = r600_ioctl_wait_idle,
+	.mmio_hdp_flush = r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &si_get_xclk,
@@ -1841,7 +1847,10 @@ static struct radeon_asic si_asic = {
 	.vm = {
 		.init = &si_vm_init,
 		.fini = &si_vm_fini,
-		.set_page = &si_dma_vm_set_page,
+		.copy_pages = &si_dma_vm_copy_pages,
+		.write_pages = &si_dma_vm_write_pages,
+		.set_pages = &si_dma_vm_set_pages,
+		.pad_ib = &cayman_dma_vm_pad_ib,
 	},
 	.ring = {
 		[RADEON_RING_TYPE_GFX_INDEX] = &si_gfx_ring,
@@ -1987,7 +1996,7 @@ static struct radeon_asic ci_asic = {
 	.resume = &cik_resume,
 	.asic_reset = &cik_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = &r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &cik_get_xclk,
@@ -1999,7 +2008,10 @@ static struct radeon_asic ci_asic = {
 	.vm = {
 		.init = &cik_vm_init,
 		.fini = &cik_vm_fini,
-		.set_page = &cik_sdma_vm_set_page,
+		.copy_pages = &cik_sdma_vm_copy_pages,
+		.write_pages = &cik_sdma_vm_write_pages,
+		.set_pages = &cik_sdma_vm_set_pages,
+		.pad_ib = &cik_sdma_vm_pad_ib,
 	},
 	.ring = {
 		[RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
@@ -2091,7 +2103,7 @@ static struct radeon_asic kv_asic = {
 	.resume = &cik_resume,
 	.asic_reset = &cik_asic_reset,
 	.vga_set_state = &r600_vga_set_state,
-	.ioctl_wait_idle = NULL,
+	.mmio_hdp_flush = &r600_mmio_hdp_flush,
 	.gui_idle = &r600_gui_idle,
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &cik_get_xclk,
@@ -2103,7 +2115,10 @@ static struct radeon_asic kv_asic = {
 	.vm = {
 		.init = &cik_vm_init,
 		.fini = &cik_vm_fini,
-		.set_page = &cik_sdma_vm_set_page,
+		.copy_pages = &cik_sdma_vm_copy_pages,
+		.write_pages = &cik_sdma_vm_write_pages,
+		.set_pages = &cik_sdma_vm_set_pages,
+		.pad_ib = &cik_sdma_vm_pad_ib,
 	},
 	.ring = {
 		[RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
@@ -2457,7 +2472,7 @@ int radeon_asic_init(struct radeon_devic
 			rdev->cg_flags =
 				RADEON_CG_SUPPORT_GFX_MGCG |
 				RADEON_CG_SUPPORT_GFX_MGLS |
-				RADEON_CG_SUPPORT_GFX_CGCG |
+				/*RADEON_CG_SUPPORT_GFX_CGCG |*/
 				RADEON_CG_SUPPORT_GFX_CGLS |
 				RADEON_CG_SUPPORT_GFX_CGTS |
 				RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2476,7 +2491,7 @@ int radeon_asic_init(struct radeon_devic
 			rdev->cg_flags =
 				RADEON_CG_SUPPORT_GFX_MGCG |
 				RADEON_CG_SUPPORT_GFX_MGLS |
-				RADEON_CG_SUPPORT_GFX_CGCG |
+				/*RADEON_CG_SUPPORT_GFX_CGCG |*/
 				RADEON_CG_SUPPORT_GFX_CGLS |
 				RADEON_CG_SUPPORT_GFX_CGTS |
 				RADEON_CG_SUPPORT_GFX_CP_LS |
@@ -2502,7 +2517,7 @@ int radeon_asic_init(struct radeon_devic
 			rdev->cg_flags =
 				RADEON_CG_SUPPORT_GFX_MGCG |
 				RADEON_CG_SUPPORT_GFX_MGLS |
-				RADEON_CG_SUPPORT_GFX_CGCG |
+				/*RADEON_CG_SUPPORT_GFX_CGCG |*/
 				RADEON_CG_SUPPORT_GFX_CGLS |
 				RADEON_CG_SUPPORT_GFX_CGTS |
 				RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2530,7 +2545,7 @@ int radeon_asic_init(struct radeon_devic
 			rdev->cg_flags =
 				RADEON_CG_SUPPORT_GFX_MGCG |
 				RADEON_CG_SUPPORT_GFX_MGLS |
-				RADEON_CG_SUPPORT_GFX_CGCG |
+				/*RADEON_CG_SUPPORT_GFX_CGCG |*/
 				RADEON_CG_SUPPORT_GFX_CGLS |
 				RADEON_CG_SUPPORT_GFX_CGTS |
 				RADEON_CG_SUPPORT_GFX_CGTS_LS |
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ int r100_asic_reset(struct radeon_device
 u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
 void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
 void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i,
-			    uint64_t addr);
+			    uint64_t addr, uint32_t flags);
 void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring);
 int r100_irq_set(struct radeon_device *rdev);
 int r100_irq_process(struct radeon_device *rdev);
@@ -173,7 +173,7 @@ extern void r300_fence_ring_emit(struct
 extern int r300_cs_parse(struct radeon_cs_parser *p);
 extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
 extern void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i,
-				     uint64_t addr);
+				     uint64_t addr, uint32_t flags);
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
 extern void r300_set_reg_safe(struct radeon_device *rdev);
@@ -209,7 +209,7 @@ extern int rs400_suspend(struct radeon_d
 extern int rs400_resume(struct radeon_device *rdev);
 void rs400_gart_tlb_flush(struct radeon_device *rdev);
 void rs400_gart_set_page(struct radeon_device *rdev, unsigned i,
-			 uint64_t addr);
+			 uint64_t addr, uint32_t flags);
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 int rs400_gart_init(struct radeon_device *rdev);
@@ -233,7 +233,7 @@ void rs600_irq_disable(struct radeon_dev
 u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
 void rs600_gart_tlb_flush(struct radeon_device *rdev);
 void rs600_gart_set_page(struct radeon_device *rdev, unsigned i,
-			 uint64_t addr);
+			 uint64_t addr, uint32_t flags);
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs600_bandwidth_update(struct radeon_device *rdev);
@@ -351,7 +351,7 @@ void r600_hpd_fini(struct radeon_device
 bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
 void r600_hpd_set_polarity(struct radeon_device *rdev,
 			   enum radeon_hpd_id hpd);
-extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
+extern void r600_mmio_hdp_flush(struct radeon_device *rdev);
 extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_pm_misc(struct radeon_device *rdev);
 extern void r600_pm_init_profile(struct radeon_device *rdev);
@@ -606,11 +606,22 @@ void cayman_dma_ring_ib_execute(struct r
 				struct radeon_ib *ib);
 bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
-void cayman_dma_vm_set_page(struct radeon_device *rdev,
-			    struct radeon_ib *ib,
-			    uint64_t pe,
-			    uint64_t addr, unsigned count,
-			    uint32_t incr, uint32_t flags);
+
+void cayman_dma_vm_copy_pages(struct radeon_device *rdev,
+			      struct radeon_ib *ib,
+			      uint64_t pe, uint64_t src,
+			      unsigned count);
+void cayman_dma_vm_write_pages(struct radeon_device *rdev,
+			       struct radeon_ib *ib,
+			       uint64_t pe,
+			       uint64_t addr, unsigned count,
+			       uint32_t incr, uint32_t flags);
+void cayman_dma_vm_set_pages(struct radeon_device *rdev,
+			     struct radeon_ib *ib,
+			     uint64_t pe,
+			     uint64_t addr, unsigned count,
+			     uint32_t incr, uint32_t flags);
+void cayman_dma_vm_pad_ib(struct radeon_ib *ib);
 
 void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 
@@ -693,11 +704,22 @@ int si_copy_dma(struct radeon_device *rd
 		uint64_t src_offset, uint64_t dst_offset,
 		unsigned num_gpu_pages,
 		struct radeon_fence **fence);
-void si_dma_vm_set_page(struct radeon_device *rdev,
-			struct radeon_ib *ib,
-			uint64_t pe,
-			uint64_t addr, unsigned count,
-			uint32_t incr, uint32_t flags);
+
+void si_dma_vm_copy_pages(struct radeon_device *rdev,
+			  struct radeon_ib *ib,
+			  uint64_t pe, uint64_t src,
+			  unsigned count);
+void si_dma_vm_write_pages(struct radeon_device *rdev,
+			   struct radeon_ib *ib,
+			   uint64_t pe,
+			   uint64_t addr, unsigned count,
+			   uint32_t incr, uint32_t flags);
+void si_dma_vm_set_pages(struct radeon_device *rdev,
+			 struct radeon_ib *ib,
+			 uint64_t pe,
+			 uint64_t addr, unsigned count,
+			 uint32_t incr, uint32_t flags);
+
 void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 u32 si_get_xclk(struct radeon_device *rdev);
 uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
@@ -771,11 +793,23 @@ int cik_irq_process(struct radeon_device
 int cik_vm_init(struct radeon_device *rdev);
 void cik_vm_fini(struct radeon_device *rdev);
 void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
-void cik_sdma_vm_set_page(struct radeon_device *rdev,
-			  struct radeon_ib *ib,
-			  uint64_t pe,
-			  uint64_t addr, unsigned count,
-			  uint32_t incr, uint32_t flags);
+
+void cik_sdma_vm_copy_pages(struct radeon_device *rdev,
+			    struct radeon_ib *ib,
+			    uint64_t pe, uint64_t src,
+			    unsigned count);
+void cik_sdma_vm_write_pages(struct radeon_device *rdev,
+			     struct radeon_ib *ib,
+			     uint64_t pe,
+			     uint64_t addr, unsigned count,
+			     uint32_t incr, uint32_t flags);
+void cik_sdma_vm_set_pages(struct radeon_device *rdev,
+			   struct radeon_ib *ib,
+			   uint64_t pe,
+			   uint64_t addr, unsigned count,
+			   uint32_t incr, uint32_t flags);
+void cik_sdma_vm_pad_ib(struct radeon_ib *ib);
+
 void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
 u32 cik_gfx_get_rptr(struct radeon_device *rdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2014-09-28 17:29:07.000000000 -0400
@@ -447,6 +447,13 @@ static bool radeon_atom_apply_quirks(str
 		}
 	}
 
+	/* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */
+	if ((dev->pdev->device == 0x9805) &&
+	    (dev->pdev->subsystem_vendor == 0x1734) &&
+	    (dev->pdev->subsystem_device == 0x11bd)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_VGA)
+			return false;
+	}
 
 	return true;
 }
@@ -1963,7 +1970,7 @@ static const char *thermal_controller_na
 	"adm1032",
 	"adm1030",
 	"max6649",
-	"lm64",
+	"lm63", /* lm64 */
 	"f75375",
 	"asc7xxx",
 };
@@ -1974,7 +1981,7 @@ static const char *pp_lib_thermal_contro
 	"adm1032",
 	"adm1030",
 	"max6649",
-	"lm64",
+	"lm63", /* lm64 */
 	"f75375",
 	"RV6xx",
 	"RV770",
@@ -2281,19 +2288,31 @@ static void radeon_atombios_add_pplib_th
 				 (controller->ucFanParameters &
 				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 			rdev->pm.int_thermal_type = THERMAL_TYPE_KV;
-		} else if ((controller->ucType ==
-			    ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
-			   (controller->ucType ==
-			    ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) ||
-			   (controller->ucType ==
-			    ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
-			DRM_INFO("Special thermal controller config\n");
+		} else if (controller->ucType ==
+			   ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
+			DRM_INFO("External GPIO thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
+		} else if (controller->ucType ==
+			   ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
+			DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
+		} else if (controller->ucType ==
+			   ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
+			DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
 		} else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
 			DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
 				 pp_lib_thermal_controller_names[controller->ucType],
 				 controller->ucI2cAddress >> 1,
 				 (controller->ucFanParameters &
 				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
 			i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
 			rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
 			if (rdev->pm.i2c_bus) {
@@ -3236,6 +3255,41 @@ int radeon_atom_get_leakage_vddc_based_o
 	return 0;
 }
 
+union get_voltage_info {
+	struct  _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in;
+	struct  _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out;
+};
+
+int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
+				u16 virtual_voltage_id,
+				u16 *voltage)
+{
+	int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo);
+	u32 entry_id;
+	u32 count = rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count;
+	union get_voltage_info args;
+
+	for (entry_id = 0; entry_id < count; entry_id++) {
+		if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].v ==
+		    virtual_voltage_id)
+			break;
+	}
+
+	if (entry_id >= count)
+		return -EINVAL;
+
+	args.in.ucVoltageType = VOLTAGE_TYPE_VDDC;
+	args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;
+	args.in.ulSCLKFreq =
+		cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	*voltage = le16_to_cpu(args.evv_out.usVoltageLevel);
+
+	return 0;
+}
+
 int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev,
 					  u16 voltage_level, u8 voltage_type,
 					  u32 *gpio_value, u32 *gpio_mask)
@@ -3397,6 +3451,50 @@ radeon_atom_is_voltage_gpio(struct radeo
 	return false;
 }
 
+int radeon_atom_get_svi2_info(struct radeon_device *rdev,
+			      u8 voltage_type,
+			      u8 *svd_gpio_id, u8 *svc_gpio_id)
+{
+	int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
+	u8 frev, crev;
+	u16 data_offset, size;
+	union voltage_object_info *voltage_info;
+	union voltage_object *voltage_object = NULL;
+
+	if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
+				   &frev, &crev, &data_offset)) {
+		voltage_info = (union voltage_object_info *)
+			(rdev->mode_info.atom_context->bios + data_offset);
+
+		switch (frev) {
+		case 3:
+			switch (crev) {
+			case 1:
+				voltage_object = (union voltage_object *)
+					atom_lookup_voltage_object_v3(&voltage_info->v3,
+								      voltage_type,
+								      VOLTAGE_OBJ_SVID2);
+				if (voltage_object) {
+					*svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
+					*svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
+				} else {
+					return -EINVAL;
+				}
+				break;
+			default:
+				DRM_ERROR("unknown voltage object table\n");
+				return -EINVAL;
+			}
+			break;
+		default:
+			DRM_ERROR("unknown voltage object table\n");
+			return -EINVAL;
+		}
+
+	}
+	return 0;
+}
+
 int radeon_atom_get_max_voltage(struct radeon_device *rdev,
 				u8 voltage_type, u16 *max_voltage)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ static struct radeon_atpx_priv {
 	bool atpx_detected;
 	/* handle for device - and atpx */
 	acpi_handle dhandle;
-	acpi_handle other_handle;
 	struct radeon_atpx atpx;
 } radeon_atpx_priv;
 
@@ -453,10 +452,9 @@ static bool radeon_atpx_pci_probe_handle
 		return false;
 
 	status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
-	if (ACPI_FAILURE(status)) {
-		radeon_atpx_priv.other_handle = dhandle;
+	if (ACPI_FAILURE(status))
 		return false;
-	}
+
 	radeon_atpx_priv.dhandle = dhandle;
 	radeon_atpx_priv.atpx.handle = atpx_handle;
 	return true;
@@ -540,16 +538,6 @@ static bool radeon_atpx_detect(void)
 		printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
 		       acpi_method_name);
 		radeon_atpx_priv.atpx_detected = true;
-		/*
-		 * On some systems hotplug events are generated for the device
-		 * being switched off when ATPX is executed.  They cause ACPI
-		 * hotplug to trigger and attempt to remove the device from
-		 * the system, which causes it to break down.  Prevent that from
-		 * happening by setting the no_hotplug flag for the involved
-		 * ACPI device objects.
-		 */
-		acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
-		acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
 		return true;
 	}
 	return false;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ static void radeon_benchmark_move(struct
 	int time;
 
 	n = RADEON_BENCHMARK_ITERATIONS;
-	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, NULL, &sobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, 0, NULL, &sobj);
 	if (r) {
 		goto out_cleanup;
 	}
@@ -109,7 +109,7 @@ static void radeon_benchmark_move(struct
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, NULL, &dobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, 0, NULL, &dobj);
 	if (r) {
 		goto out_cleanup;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@ int radeon_get_monitor_bpc(struct drm_co
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_HDMIB:
 		if (radeon_connector->use_digital) {
-			if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+			if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 				if (connector->display_info.bpc)
 					bpc = connector->display_info.bpc;
 			}
@@ -115,7 +115,7 @@ int radeon_get_monitor_bpc(struct drm_co
 		break;
 	case DRM_MODE_CONNECTOR_DVID:
 	case DRM_MODE_CONNECTOR_HDMIA:
-		if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+		if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 			if (connector->display_info.bpc)
 				bpc = connector->display_info.bpc;
 		}
@@ -124,7 +124,7 @@ int radeon_get_monitor_bpc(struct drm_co
 		dig_connector = radeon_connector->con_priv;
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
-		    drm_detect_hdmi_monitor(radeon_connector->edid)) {
+		    drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 			if (connector->display_info.bpc)
 				bpc = connector->display_info.bpc;
 		}
@@ -148,7 +148,7 @@ int radeon_get_monitor_bpc(struct drm_co
 		break;
 	}
 
-	if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+	if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 		/* hdmi deep color only implemented on DCE4+ */
 		if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
 			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
@@ -197,10 +197,19 @@ int radeon_get_monitor_bpc(struct drm_co
 						  connector->name, bpc);
 			}
 		}
+		else if (bpc > 8) {
+			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
+			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
+					  connector->name);
+			bpc = 8;
+		}
 	}
 
-	if ((radeon_deep_color == 0) && (bpc > 8))
+	if ((radeon_deep_color == 0) && (bpc > 8)) {
+		DRM_DEBUG("%s: Deep color disabled. Set radeon module param deep_color=1 to enable.\n",
+				  connector->name);
 		bpc = 8;
+	}
 
 	DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
 			  connector->name, connector->display_info.bpc, bpc);
@@ -216,7 +225,6 @@ radeon_connector_update_scratch_regs(str
 	struct drm_encoder *best_encoder = NULL;
 	struct drm_encoder *encoder = NULL;
 	struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-	struct drm_mode_object *obj;
 	bool connected;
 	int i;
 
@@ -226,14 +234,11 @@ radeon_connector_update_scratch_regs(str
 		if (connector->encoder_ids[i] == 0)
 			break;
 
-		obj = drm_mode_object_find(connector->dev,
-					   connector->encoder_ids[i],
-					   DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(connector->dev,
+					   connector->encoder_ids[i]);
+		if (!encoder)
 			continue;
 
-		encoder = obj_to_encoder(obj);
-
 		if ((encoder == best_encoder) && (status == connector_status_connected))
 			connected = true;
 		else
@@ -249,7 +254,6 @@ radeon_connector_update_scratch_regs(str
 
 static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
 {
-	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	int i;
 
@@ -257,34 +261,134 @@ static struct drm_encoder *radeon_find_e
 		if (connector->encoder_ids[i] == 0)
 			break;
 
-		obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+		if (!encoder)
 			continue;
 
-		encoder = obj_to_encoder(obj);
 		if (encoder->encoder_type == encoder_type)
 			return encoder;
 	}
 	return NULL;
 }
 
+struct edid *radeon_connector_edid(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
+
+	if (radeon_connector->edid) {
+		return radeon_connector->edid;
+	} else if (edid_blob) {
+		struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
+		if (edid)
+			radeon_connector->edid = edid;
+	}
+	return radeon_connector->edid;
+}
+
+static void radeon_connector_get_edid(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_connector->edid)
+		return;
+
+	/* on hw with routers, select right port */
+	if (radeon_connector->router.ddc_valid)
+		radeon_router_select_ddc_port(radeon_connector);
+
+	if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+	     ENCODER_OBJECT_ID_NONE) &&
+	    radeon_connector->ddc_bus->has_aux) {
+		radeon_connector->edid = drm_get_edid(connector,
+						      &radeon_connector->ddc_bus->aux.ddc);
+	} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+		   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
+		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
+		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
+		    radeon_connector->ddc_bus->has_aux)
+			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+							      &radeon_connector->ddc_bus->aux.ddc);
+		else if (radeon_connector->ddc_bus)
+			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+							      &radeon_connector->ddc_bus->adapter);
+	} else if (radeon_connector->ddc_bus) {
+		radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+						      &radeon_connector->ddc_bus->adapter);
+	}
+
+	if (!radeon_connector->edid) {
+		if (rdev->is_atom_bios) {
+			/* some laptops provide a hardcoded edid in rom for LCDs */
+			if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
+			     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
+				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+		} else {
+			/* some servers provide a hardcoded edid in rom for KVMs */
+			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+		}
+	}
+}
+
+static void radeon_connector_free_edid(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_connector->edid) {
+		kfree(radeon_connector->edid);
+		radeon_connector->edid = NULL;
+	}
+}
+
+static int radeon_ddc_get_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret;
+
+	if (radeon_connector->edid) {
+		drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
+		ret = drm_add_edid_modes(connector, radeon_connector->edid);
+		drm_edid_to_eld(connector, radeon_connector->edid);
+		return ret;
+	}
+	drm_mode_connector_update_edid_property(connector, NULL);
+	return 0;
+}
+
 static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
 	/* pick the encoder ids */
-	if (enc_id) {
-		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
+static void radeon_get_native_mode(struct drm_connector *connector)
+{
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct radeon_encoder *radeon_encoder;
+
+	if (encoder == NULL)
+		return;
+
+	radeon_encoder = to_radeon_encoder(encoder);
+
+	if (!list_empty(&connector->probed_modes)) {
+		struct drm_display_mode *preferred_mode =
+			list_first_entry(&connector->probed_modes,
+					 struct drm_display_mode, head);
+
+		radeon_encoder->native_mode = *preferred_mode;
+	} else {
+		radeon_encoder->native_mode.clock = 0;
+	}
+}
+
 /*
  * radeon_connector_analog_encoder_conflict_solve
  * - search for other connectors sharing this encoder
@@ -585,6 +689,35 @@ static int radeon_connector_set_property
 		radeon_property_change_mode(&radeon_encoder->base);
 	}
 
+	if (property == dev->mode_config.scaling_mode_property) {
+		enum radeon_rmx_type rmx_type;
+
+		if (connector->encoder)
+			radeon_encoder = to_radeon_encoder(connector->encoder);
+		else {
+			struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
+			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+		}
+
+		switch (val) {
+		default:
+		case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
+		case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
+		case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
+		case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
+		}
+		if (radeon_encoder->rmx_type == rmx_type)
+			return 0;
+
+		if ((rmx_type != DRM_MODE_SCALE_NONE) &&
+		    (radeon_encoder->native_mode.clock == 0))
+			return 0;
+
+		radeon_encoder->rmx_type = rmx_type;
+
+		radeon_property_change_mode(&radeon_encoder->base);
+	}
+
 	return 0;
 }
 
@@ -625,22 +758,20 @@ static void radeon_fixup_lvds_native_mod
 
 static int radeon_lvds_get_modes(struct drm_connector *connector)
 {
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder;
 	int ret = 0;
 	struct drm_display_mode *mode;
 
-	if (radeon_connector->ddc_bus) {
-		ret = radeon_ddc_get_modes(radeon_connector);
-		if (ret > 0) {
-			encoder = radeon_best_single_encoder(connector);
-			if (encoder) {
-				radeon_fixup_lvds_native_mode(encoder, connector);
-				/* add scaled modes */
-				radeon_add_common_modes(encoder, connector);
-			}
-			return ret;
+	radeon_connector_get_edid(connector);
+	ret = radeon_ddc_get_modes(connector);
+	if (ret > 0) {
+		encoder = radeon_best_single_encoder(connector);
+		if (encoder) {
+			radeon_fixup_lvds_native_mode(encoder, connector);
+			/* add scaled modes */
+			radeon_add_common_modes(encoder, connector);
 		}
+		return ret;
 	}
 
 	encoder = radeon_best_single_encoder(connector);
@@ -715,16 +846,9 @@ radeon_lvds_detect(struct drm_connector
 	}
 
 	/* check for edid as well */
+	radeon_connector_get_edid(connector);
 	if (radeon_connector->edid)
 		ret = connector_status_connected;
-	else {
-		if (radeon_connector->ddc_bus) {
-			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
-							      &radeon_connector->ddc_bus->adapter);
-			if (radeon_connector->edid)
-				ret = connector_status_connected;
-		}
-	}
 	/* check acpi lid status ??? */
 
 	radeon_connector_update_scratch_regs(connector, ret);
@@ -737,10 +861,9 @@ static void radeon_connector_destroy(str
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
-	if (radeon_connector->edid)
-		kfree(radeon_connector->edid);
+	radeon_connector_free_edid(connector);
 	kfree(radeon_connector->con_priv);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -797,10 +920,12 @@ static const struct drm_connector_funcs
 
 static int radeon_vga_get_modes(struct drm_connector *connector)
 {
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	int ret;
 
-	ret = radeon_ddc_get_modes(radeon_connector);
+	radeon_connector_get_edid(connector);
+	ret = radeon_ddc_get_modes(connector);
+
+	radeon_get_native_mode(connector);
 
 	return ret;
 }
@@ -843,28 +968,26 @@ radeon_vga_detect(struct drm_connector *
 		dret = radeon_ddc_probe(radeon_connector, false);
 	if (dret) {
 		radeon_connector->detected_by_load = false;
-		if (radeon_connector->edid) {
-			kfree(radeon_connector->edid);
-			radeon_connector->edid = NULL;
-		}
-		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+		radeon_connector_free_edid(connector);
+		radeon_connector_get_edid(connector);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
 					connector->name);
 			ret = connector_status_connected;
 		} else {
-			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
+			radeon_connector->use_digital =
+				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
 			/* some oems have boards with separate digital and analog connectors
 			 * with a shared ddc line (often vga + hdmi)
 			 */
 			if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
-				kfree(radeon_connector->edid);
-				radeon_connector->edid = NULL;
+				radeon_connector_free_edid(connector);
 				ret = connector_status_disconnected;
-			} else
+			} else {
 				ret = connector_status_connected;
+			}
 		}
 	} else {
 
@@ -999,15 +1122,6 @@ static const struct drm_connector_funcs
 	.set_property = radeon_connector_set_property,
 };
 
-static int radeon_dvi_get_modes(struct drm_connector *connector)
-{
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	int ret;
-
-	ret = radeon_ddc_get_modes(radeon_connector);
-	return ret;
-}
-
 static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -1048,7 +1162,6 @@ radeon_dvi_detect(struct drm_connector *
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder = NULL;
 	struct drm_encoder_helper_funcs *encoder_funcs;
-	struct drm_mode_object *obj;
 	int i, r;
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false, broken_edid = false;
@@ -1066,18 +1179,16 @@ radeon_dvi_detect(struct drm_connector *
 		dret = radeon_ddc_probe(radeon_connector, false);
 	if (dret) {
 		radeon_connector->detected_by_load = false;
-		if (radeon_connector->edid) {
-			kfree(radeon_connector->edid);
-			radeon_connector->edid = NULL;
-		}
-		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+		radeon_connector_free_edid(connector);
+		radeon_connector_get_edid(connector);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
 					connector->name);
 			/* rs690 seems to have a problem with connectors not existing and always
 			 * return a block of 0's. If we see this just stop polling on this output */
-			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
+			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) &&
+			    radeon_connector->base.null_edid_counter) {
 				ret = connector_status_disconnected;
 				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
 					  connector->name);
@@ -1087,18 +1198,18 @@ radeon_dvi_detect(struct drm_connector *
 				broken_edid = true; /* defer use_digital to later */
 			}
 		} else {
-			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
+			radeon_connector->use_digital =
+				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
 			/* some oems have boards with separate digital and analog connectors
 			 * with a shared ddc line (often vga + hdmi)
 			 */
 			if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
-				kfree(radeon_connector->edid);
-				radeon_connector->edid = NULL;
+				radeon_connector_free_edid(connector);
 				ret = connector_status_disconnected;
-			} else
+			} else {
 				ret = connector_status_connected;
-
+			}
 			/* This gets complicated.  We have boards with VGA + HDMI with a
 			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
 			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
@@ -1118,8 +1229,7 @@ radeon_dvi_detect(struct drm_connector *
 						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
 							/* hpd is our only option in this case */
 							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
-								kfree(radeon_connector->edid);
-								radeon_connector->edid = NULL;
+								radeon_connector_free_edid(connector);
 								ret = connector_status_disconnected;
 							}
 						}
@@ -1153,14 +1263,11 @@ radeon_dvi_detect(struct drm_connector *
 			if (connector->encoder_ids[i] == 0)
 				break;
 
-			obj = drm_mode_object_find(connector->dev,
-						   connector->encoder_ids[i],
-						   DRM_MODE_OBJECT_ENCODER);
-			if (!obj)
+			encoder = drm_encoder_find(connector->dev,
+						   connector->encoder_ids[i]);
+			if (!encoder)
 				continue;
 
-			encoder = obj_to_encoder(obj);
-
 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
 			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
 				continue;
@@ -1225,19 +1332,16 @@ static struct drm_encoder *radeon_dvi_en
 {
 	int enc_id = connector->encoder_ids[0];
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	int i;
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 		if (connector->encoder_ids[i] == 0)
 			break;
 
-		obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+		if (!encoder)
 			continue;
 
-		encoder = obj_to_encoder(obj);
-
 		if (radeon_connector->use_digital == true) {
 			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
 				return encoder;
@@ -1252,13 +1356,8 @@ static struct drm_encoder *radeon_dvi_en
 
 	/* then check use digitial */
 	/* pick the first one */
-	if (enc_id) {
-		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
-			return NULL;
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
 	return NULL;
 }
 
@@ -1291,7 +1390,7 @@ static int radeon_dvi_mode_valid(struct
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
 			return MODE_OK;
-		else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+		else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 			/* HDMI 1.3+ supports max clock of 340 Mhz */
 			if (mode->clock > 340000)
 				return MODE_CLOCK_HIGH;
@@ -1310,7 +1409,7 @@ static int radeon_dvi_mode_valid(struct
 }
 
 static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
-	.get_modes = radeon_dvi_get_modes,
+	.get_modes = radeon_vga_get_modes,
 	.mode_valid = radeon_dvi_mode_valid,
 	.best_encoder = radeon_dvi_encoder,
 };
@@ -1339,7 +1438,8 @@ static int radeon_dp_get_modes(struct dr
 			if (!radeon_dig_connector->edp_on)
 				atombios_set_edp_panel_power(connector,
 							     ATOM_TRANSMITTER_ACTION_POWER_ON);
-			ret = radeon_ddc_get_modes(radeon_connector);
+			radeon_connector_get_edid(connector);
+			ret = radeon_ddc_get_modes(connector);
 			if (!radeon_dig_connector->edp_on)
 				atombios_set_edp_panel_power(connector,
 							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
@@ -1350,7 +1450,8 @@ static int radeon_dp_get_modes(struct dr
 				if (encoder)
 					radeon_atom_ext_encoder_setup_ddc(encoder);
 			}
-			ret = radeon_ddc_get_modes(radeon_connector);
+			radeon_connector_get_edid(connector);
+			ret = radeon_ddc_get_modes(connector);
 		}
 
 		if (ret > 0) {
@@ -1383,7 +1484,10 @@ static int radeon_dp_get_modes(struct dr
 			if (encoder)
 				radeon_atom_ext_encoder_setup_ddc(encoder);
 		}
-		ret = radeon_ddc_get_modes(radeon_connector);
+		radeon_connector_get_edid(connector);
+		ret = radeon_ddc_get_modes(connector);
+
+		radeon_get_native_mode(connector);
 	}
 
 	return ret;
@@ -1391,7 +1495,6 @@ static int radeon_dp_get_modes(struct dr
 
 u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
 {
-	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	struct radeon_encoder *radeon_encoder;
 	int i;
@@ -1400,11 +1503,10 @@ u16 radeon_connector_encoder_get_dp_brid
 		if (connector->encoder_ids[i] == 0)
 			break;
 
-		obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+		if (!encoder)
 			continue;
 
-		encoder = obj_to_encoder(obj);
 		radeon_encoder = to_radeon_encoder(encoder);
 
 		switch (radeon_encoder->encoder_id) {
@@ -1419,9 +1521,8 @@ u16 radeon_connector_encoder_get_dp_brid
 	return ENCODER_OBJECT_ID_NONE;
 }
 
-bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
+static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
 {
-	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	struct radeon_encoder *radeon_encoder;
 	int i;
@@ -1431,11 +1532,10 @@ bool radeon_connector_encoder_is_hbr2(st
 		if (connector->encoder_ids[i] == 0)
 			break;
 
-		obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
-		if (!obj)
+		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+		if (!encoder)
 			continue;
 
-		encoder = obj_to_encoder(obj);
 		radeon_encoder = to_radeon_encoder(encoder);
 		if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
 			found = true;
@@ -1478,10 +1578,7 @@ radeon_dp_detect(struct drm_connector *c
 		goto out;
 	}
 
-	if (radeon_connector->edid) {
-		kfree(radeon_connector->edid);
-		radeon_connector->edid = NULL;
-	}
+	radeon_connector_free_edid(connector);
 
 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
@@ -1587,7 +1684,7 @@ static int radeon_dp_mode_valid(struct d
 		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
 			return radeon_dp_mode_valid_helper(connector, mode);
 		} else {
-			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 				/* HDMI 1.3+ supports max clock of 340 Mhz */
 				if (mode->clock > 340000)
 					return MODE_CLOCK_HIGH;
@@ -1747,6 +1844,9 @@ radeon_add_atom_connector(struct drm_dev
 			drm_object_attach_property(&radeon_connector->base.base,
 						      rdev->mode_info.load_detect_property,
 						      1);
+			drm_object_attach_property(&radeon_connector->base.base,
+						   dev->mode_config.scaling_mode_property,
+						   DRM_MODE_SCALE_NONE);
 			break;
 		case DRM_MODE_CONNECTOR_DVII:
 		case DRM_MODE_CONNECTOR_DVID:
@@ -1768,6 +1868,10 @@ radeon_add_atom_connector(struct drm_dev
 						      0);
 
 			drm_object_attach_property(&radeon_connector->base.base,
+						      dev->mode_config.scaling_mode_property,
+						      DRM_MODE_SCALE_NONE);
+
+			drm_object_attach_property(&radeon_connector->base.base,
 						   rdev->mode_info.dither_property,
 						   RADEON_FMT_DITHER_DISABLE);
 
@@ -1817,6 +1921,10 @@ radeon_add_atom_connector(struct drm_dev
 			drm_object_attach_property(&radeon_connector->base.base,
 						      rdev->mode_info.load_detect_property,
 						      1);
+			if (ASIC_IS_AVIVO(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   dev->mode_config.scaling_mode_property,
+							   DRM_MODE_SCALE_NONE);
 			/* no HPD on analog connectors */
 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
 			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -1835,6 +1943,10 @@ radeon_add_atom_connector(struct drm_dev
 			drm_object_attach_property(&radeon_connector->base.base,
 						      rdev->mode_info.load_detect_property,
 						      1);
+			if (ASIC_IS_AVIVO(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   dev->mode_config.scaling_mode_property,
+							   DRM_MODE_SCALE_NONE);
 			/* no HPD on analog connectors */
 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
 			connector->interlace_allowed = true;
@@ -1868,17 +1980,18 @@ radeon_add_atom_connector(struct drm_dev
 				drm_object_attach_property(&radeon_connector->base.base,
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.dither_property,
+							   RADEON_FMT_DITHER_DISABLE);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   dev->mode_config.scaling_mode_property,
+							   DRM_MODE_SCALE_NONE);
 			}
 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
 			}
-			if (ASIC_IS_AVIVO(rdev)) {
-				drm_object_attach_property(&radeon_connector->base.base,
-							   rdev->mode_info.dither_property,
-							   RADEON_FMT_DITHER_DISABLE);
-			}
 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
 				radeon_connector->dac_load_detect = true;
 				drm_object_attach_property(&radeon_connector->base.base,
@@ -1918,17 +2031,18 @@ radeon_add_atom_connector(struct drm_dev
 				drm_object_attach_property(&radeon_connector->base.base,
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.dither_property,
+							   RADEON_FMT_DITHER_DISABLE);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   dev->mode_config.scaling_mode_property,
+							   DRM_MODE_SCALE_NONE);
 			}
 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
 			}
-			if (ASIC_IS_AVIVO(rdev)) {
-				drm_object_attach_property(&radeon_connector->base.base,
-							   rdev->mode_info.dither_property,
-							   RADEON_FMT_DITHER_DISABLE);
-			}
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1965,18 +2079,18 @@ radeon_add_atom_connector(struct drm_dev
 				drm_object_attach_property(&radeon_connector->base.base,
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.dither_property,
+							   RADEON_FMT_DITHER_DISABLE);
+				drm_object_attach_property(&radeon_connector->base.base,
+							   dev->mode_config.scaling_mode_property,
+							   DRM_MODE_SCALE_NONE);
 			}
 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
 			}
-			if (ASIC_IS_AVIVO(rdev)) {
-				drm_object_attach_property(&radeon_connector->base.base,
-							   rdev->mode_info.dither_property,
-							   RADEON_FMT_DITHER_DISABLE);
-
-			}
 			connector->interlace_allowed = true;
 			/* in theory with a DP to VGA converter... */
 			connector->doublescan_allowed = false;
@@ -2050,7 +2164,7 @@ radeon_add_atom_connector(struct drm_dev
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 
 	connector->display_info.subpixel_order = subpixel_order;
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	if (has_aux)
 		radeon_dp_aux_init(radeon_connector);
@@ -2211,5 +2325,5 @@ radeon_add_legacy_connector(struct drm_d
 	} else
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,7 +132,8 @@ static int radeon_cs_parser_relocs(struc
 		 * the buffers used for read only, which doubles the range
 		 * to 0 to 31. 32 is reserved for the kernel driver.
 		 */
-		priority = (r->flags & 0xf) * 2 + !!r->write_domain;
+		priority = (r->flags & RADEON_RELOC_PRIO_MASK) * 2
+			   + !!r->write_domain;
 
 		/* the first reloc of an UVD job is the msg and that must be in
 		   VRAM, also but everything into VRAM on AGP cards to avoid
@@ -450,7 +451,7 @@ static int radeon_cs_ib_chunk(struct rad
 		radeon_vce_note_usage(rdev);
 
 	radeon_cs_sync_rings(parser);
-	r = radeon_ib_schedule(rdev, &parser->ib, NULL);
+	r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
 	if (r) {
 		DRM_ERROR("Failed to schedule IB !\n");
 	}
@@ -500,7 +501,8 @@ static int radeon_bo_vm_update_pte(struc
 		if (r)
 			return r;
 	}
-	return 0;
+
+	return radeon_vm_clear_invalids(rdev, vm);
 }
 
 static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
@@ -540,9 +542,9 @@ static int radeon_cs_ib_vm_chunk(struct
 
 	if ((rdev->family >= CHIP_TAHITI) &&
 	    (parser->chunk_const_ib_idx != -1)) {
-		r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib);
+		r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib, true);
 	} else {
-		r = radeon_ib_schedule(rdev, &parser->ib, NULL);
+		r = radeon_ib_schedule(rdev, &parser->ib, NULL, true);
 	}
 
 out:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_device.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,6 +103,35 @@ static const char radeon_family_name[][1
 	"LAST",
 };
 
+#define RADEON_PX_QUIRK_DISABLE_PX  (1 << 0)
+#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
+
+struct radeon_px_quirk {
+	u32 chip_vendor;
+	u32 chip_device;
+	u32 subsys_vendor;
+	u32 subsys_device;
+	u32 px_quirk_flags;
+};
+
+static struct radeon_px_quirk radeon_px_quirk_list[] = {
+	/* Acer aspire 5560g (CPU: AMD A4-3305M; GPU: AMD Radeon HD 6480g + 7470m)
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=74551
+	 */
+	{ PCI_VENDOR_ID_ATI, 0x6760, 0x1025, 0x0672, RADEON_PX_QUIRK_DISABLE_PX },
+	/* Asus K73TA laptop with AMD A6-3400M APU and Radeon 6550 GPU
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=51381
+	 */
+	{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX },
+	/* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=51381
+	 */
+	{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
+	/* macbook pro 8.2 */
+	{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
+	{ 0, 0, 0, 0, 0 },
+};
+
 bool radeon_is_px(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
@@ -112,6 +141,26 @@ bool radeon_is_px(struct drm_device *dev
 	return false;
 }
 
+static void radeon_device_handle_px_quirks(struct radeon_device *rdev)
+{
+	struct radeon_px_quirk *p = radeon_px_quirk_list;
+
+	/* Apply PX quirks */
+	while (p && p->chip_device != 0) {
+		if (rdev->pdev->vendor == p->chip_vendor &&
+		    rdev->pdev->device == p->chip_device &&
+		    rdev->pdev->subsystem_vendor == p->subsys_vendor &&
+		    rdev->pdev->subsystem_device == p->subsys_device) {
+			rdev->px_quirk_flags = p->px_quirk_flags;
+			break;
+		}
+		++p;
+	}
+
+	if (rdev->px_quirk_flags & RADEON_PX_QUIRK_DISABLE_PX)
+		rdev->flags &= ~RADEON_IS_PX;
+}
+
 /**
  * radeon_program_register_sequence - program an array of registers.
  *
@@ -385,7 +434,8 @@ int radeon_wb_init(struct radeon_device
 
 	if (rdev->wb.wb_obj == NULL) {
 		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_GTT, NULL, &rdev->wb.wb_obj);
+				     RADEON_GEM_DOMAIN_GTT, 0, NULL,
+				     &rdev->wb.wb_obj);
 		if (r) {
 			dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
 			return r;
@@ -1077,7 +1127,19 @@ static void radeon_check_arguments(struc
 	/* defines number of bits in page table versus page directory,
 	 * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
 	 * page table and the remaining bits are in the page directory */
-	if (radeon_vm_block_size < 9) {
+	if (radeon_vm_block_size == -1) {
+
+		/* Total bits covered by PD + PTs */
+		unsigned bits = ilog2(radeon_vm_size) + 17;
+
+		/* Make sure the PD is 4K in size up to 8GB address space.
+		   Above that split equal between PD and PTs */
+		if (radeon_vm_size <= 8)
+			radeon_vm_block_size = bits - 9;
+		else
+			radeon_vm_block_size = (bits + 3) / 2;
+
+	} else if (radeon_vm_block_size < 9) {
 		dev_warn(rdev->dev, "VM page table size (%d) too small\n",
 			 radeon_vm_block_size);
 		radeon_vm_block_size = 9;
@@ -1092,25 +1154,6 @@ static void radeon_check_arguments(struc
 }
 
 /**
- * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is
- * needed for waking up.
- *
- * @pdev: pci dev pointer
- */
-static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
-{
-
-	/* 6600m in a macbook pro */
-	if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
-	    pdev->subsystem_device == 0x00e2) {
-		printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n");
-		return true;
-	}
-
-	return false;
-}
-
-/**
  * radeon_switcheroo_set_state - set switcheroo state
  *
  * @pdev: pci dev pointer
@@ -1122,6 +1165,7 @@ static bool radeon_switcheroo_quirk_long
 static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct radeon_device *rdev = dev->dev_private;
 
 	if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
 		return;
@@ -1133,7 +1177,7 @@ static void radeon_switcheroo_set_state(
 		/* don't suspend or resume card normally */
 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 
-		if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
+		if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
 			dev->pdev->d3_delay = 20;
 
 		radeon_resume_kms(dev, true, true);
@@ -1337,6 +1381,9 @@ int radeon_device_init(struct radeon_dev
 	if (rdev->rio_mem == NULL)
 		DRM_ERROR("Unable to find PCI I/O BAR\n");
 
+	if (rdev->flags & RADEON_IS_PX)
+		radeon_device_handle_px_quirks(rdev);
+
 	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
 	/* this will fail for cards that aren't VGA class devices, just
 	 * ignore it */
@@ -1350,7 +1397,7 @@ int radeon_device_init(struct radeon_dev
 
 	r = radeon_init(rdev);
 	if (r)
-		return r;
+		goto failed;
 
 	r = radeon_ib_ring_tests(rdev);
 	if (r)
@@ -1370,7 +1417,7 @@ int radeon_device_init(struct radeon_dev
 		radeon_agp_disable(rdev);
 		r = radeon_init(rdev);
 		if (r)
-			return r;
+			goto failed;
 	}
 
 	if ((radeon_testing & 1)) {
@@ -1392,6 +1439,11 @@ int radeon_device_init(struct radeon_dev
 			DRM_INFO("radeon: acceleration disabled, skipping benchmarks\n");
 	}
 	return 0;
+
+failed:
+	if (runtime)
+		vga_switcheroo_fini_domain_pm_ops(rdev->dev);
+	return r;
 }
 
 static void radeon_debugfs_remove_files(struct radeon_device *rdev);
@@ -1412,6 +1464,8 @@ void radeon_device_fini(struct radeon_de
 	radeon_bo_evict_vram(rdev);
 	radeon_fini(rdev);
 	vga_switcheroo_unregister_client(rdev->pdev);
+	if (rdev->flags & RADEON_IS_PX)
+		vga_switcheroo_fini_domain_pm_ops(rdev->dev);
 	vga_client_register(rdev->pdev, NULL, NULL, NULL);
 	if (rdev->rio_mem)
 		pci_iounmap(rdev->pdev, rdev->rio_mem);
@@ -1637,8 +1691,8 @@ int radeon_gpu_reset(struct radeon_devic
 	radeon_save_bios_scratch_regs(rdev);
 	/* block TTM */
 	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
-	radeon_pm_suspend(rdev);
 	radeon_suspend(rdev);
+	radeon_hpd_fini(rdev);
 
 	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
 		ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i],
@@ -1683,9 +1737,39 @@ retry:
 		}
 	}
 
-	radeon_pm_resume(rdev);
+	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+		/* do dpm late init */
+		r = radeon_pm_late_init(rdev);
+		if (r) {
+			rdev->pm.dpm_enabled = false;
+			DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+		}
+	} else {
+		/* resume old pm late */
+		radeon_pm_resume(rdev);
+	}
+
+	/* init dig PHYs, disp eng pll */
+	if (rdev->is_atom_bios) {
+		radeon_atom_encoder_init(rdev);
+		radeon_atom_disp_eng_pll_init(rdev);
+		/* turn on the BL */
+		if (rdev->mode_info.bl_encoder) {
+			u8 bl_level = radeon_get_backlight_level(rdev,
+								 rdev->mode_info.bl_encoder);
+			radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder,
+						   bl_level);
+		}
+	}
+	/* reset hpd state */
+	radeon_hpd_init(rdev);
+
 	drm_helper_resume_force_mode(rdev->ddev);
 
+	/* set the power state here in case we are a PX system or headless */
+	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
+		radeon_pm_compute_clocks(rdev);
+
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
 	if (r) {
 		/* bad news, how to tell it to userspace ? */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -293,6 +293,18 @@ void radeon_crtc_handle_vblank(struct ra
 	if (radeon_crtc == NULL)
 		return;
 
+	/* Skip the pageflip completion check below (based on polling) on
+	 * asics which reliably support hw pageflip completion irqs. pflip
+	 * irqs are a reliable and race-free method of handling pageflip
+	 * completion detection. A use_pflipirq module parameter < 2 allows
+	 * to override this in case of asics with faulty pflip irqs.
+	 * A module parameter of 0 would only use this polling based path,
+	 * a parameter of 1 would use pflip irq only as a backup to this
+	 * path, as in Linux 3.16.
+	 */
+	if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev))
+		return;
+
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
 	if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
 		DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
@@ -823,64 +835,6 @@ static bool radeon_setup_enc_conn(struct
 	return ret;
 }
 
-int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
-{
-	struct drm_device *dev = radeon_connector->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
-	int ret = 0;
-
-	/* don't leak the edid if we already fetched it in detect() */
-	if (radeon_connector->edid)
-		goto got_edid;
-
-	/* on hw with routers, select right port */
-	if (radeon_connector->router.ddc_valid)
-		radeon_router_select_ddc_port(radeon_connector);
-
-	if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
-	    ENCODER_OBJECT_ID_NONE) {
-		if (radeon_connector->ddc_bus->has_aux)
-			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
-							      &radeon_connector->ddc_bus->aux.ddc);
-	} else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
-		   (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
-		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
-
-		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
-		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
-		    radeon_connector->ddc_bus->has_aux)
-			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
-							      &radeon_connector->ddc_bus->aux.ddc);
-		else if (radeon_connector->ddc_bus && !radeon_connector->edid)
-			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
-							      &radeon_connector->ddc_bus->adapter);
-	} else {
-		if (radeon_connector->ddc_bus && !radeon_connector->edid)
-			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
-							      &radeon_connector->ddc_bus->adapter);
-	}
-
-	if (!radeon_connector->edid) {
-		if (rdev->is_atom_bios) {
-			/* some laptops provide a hardcoded edid in rom for LCDs */
-			if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) ||
-			     (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)))
-				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
-		} else
-			/* some servers provide a hardcoded edid in rom for KVMs */
-			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
-	}
-	if (radeon_connector->edid) {
-got_edid:
-		drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
-		ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
-		drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
-		return ret;
-	}
-	drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
-	return 0;
-}
-
 /* avivo */
 
 /**
@@ -1749,7 +1703,7 @@ bool radeon_crtc_scaling_mode_fixup(stru
 			    (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
 			    ((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
 			     ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
-			      drm_detect_hdmi_monitor(radeon_connector->edid) &&
+			      drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
 			      is_hdtv_mode(mode)))) {
 				if (radeon_encoder->underscan_hborder != 0)
 					radeon_crtc->h_border = radeon_encoder->underscan_hborder;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,9 +82,11 @@
  *   2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN),
  *            CIK: 1D and linear tiling modes contain valid PIPE_CONFIG
  *   2.39.0 - Add INFO query for number of active CUs
+ *   2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting
+ *            CS to GPU on >= r600
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	39
+#define KMS_DRIVER_MINOR	40
 #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);
@@ -132,6 +134,7 @@ struct drm_gem_object *radeon_gem_prime_
 							struct sg_table *sg);
 int radeon_gem_prime_pin(struct drm_gem_object *obj);
 void radeon_gem_prime_unpin(struct drm_gem_object *obj);
+struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *);
 void *radeon_gem_prime_vmap(struct drm_gem_object *obj);
 void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd,
@@ -173,9 +176,12 @@ int radeon_dpm = -1;
 int radeon_aspm = -1;
 int radeon_runtime_pm = -1;
 int radeon_hard_reset = 0;
-int radeon_vm_size = 4;
-int radeon_vm_block_size = 9;
+int radeon_vm_size = 8;
+int radeon_vm_block_size = -1;
 int radeon_deep_color = 0;
+int radeon_use_pflipirq = 2;
+int radeon_bapm = -1;
+int radeon_backlight = -1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -246,12 +252,21 @@ module_param_named(hard_reset, radeon_ha
 MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 4GB)");
 module_param_named(vm_size, radeon_vm_size, int, 0444);
 
-MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default 9)");
+MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default depending on vm_size)");
 module_param_named(vm_block_size, radeon_vm_block_size, int, 0444);
 
 MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
 module_param_named(deep_color, radeon_deep_color, int, 0444);
 
+MODULE_PARM_DESC(use_pflipirq, "Pflip irqs for pageflip completion (0 = disable, 1 = as fallback, 2 = exclusive (default))");
+module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444);
+
+MODULE_PARM_DESC(bapm, "BAPM support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(bapm, radeon_bapm, int, 0444);
+
+MODULE_PARM_DESC(backlight, "backlight support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(backlight, radeon_backlight, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 	radeon_PCI_IDS
 };
@@ -429,6 +444,7 @@ static int radeon_pmops_runtime_suspend(
 	ret = radeon_suspend_kms(drm_dev, false, false);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
+	pci_ignore_hotplug(pdev);
 	pci_set_power_state(pdev, PCI_D3cold);
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
 
@@ -566,6 +582,7 @@ static struct drm_driver kms_driver = {
 	.gem_prime_import = drm_gem_prime_import,
 	.gem_prime_pin = radeon_gem_prime_pin,
 	.gem_prime_unpin = radeon_gem_prime_unpin,
+	.gem_prime_res_obj = radeon_gem_prime_res_obj,
 	.gem_prime_get_sg_table = radeon_gem_prime_get_sg_table,
 	.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
 	.gem_prime_vmap = radeon_gem_prime_vmap,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_encoders.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_encoders.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,10 +158,43 @@ radeon_get_encoder_enum(struct drm_devic
 	return ret;
 }
 
+static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
+					 struct drm_connector *connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	bool use_bl = false;
+
+	if (!(radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)))
+		return;
+
+	if (radeon_backlight == 0) {
+		return;
+	} else if (radeon_backlight == 1) {
+		use_bl = true;
+	} else if (radeon_backlight == -1) {
+		/* Quirks */
+		/* Amilo Xi 2550 only works with acpi bl */
+		if ((rdev->pdev->device == 0x9583) &&
+		    (rdev->pdev->subsystem_vendor == 0x1734) &&
+		    (rdev->pdev->subsystem_device == 0x1107))
+			use_bl = false;
+		else
+			use_bl = true;
+	}
+
+	if (use_bl) {
+		if (rdev->is_atom_bios)
+			radeon_atom_backlight_init(radeon_encoder, connector);
+		else
+			radeon_legacy_backlight_init(radeon_encoder, connector);
+		rdev->mode_info.bl_encoder = radeon_encoder;
+	}
+}
+
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
-	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	struct drm_encoder *encoder;
@@ -174,13 +207,8 @@ radeon_link_encoder_connector(struct drm
 			radeon_encoder = to_radeon_encoder(encoder);
 			if (radeon_encoder->devices & radeon_connector->devices) {
 				drm_mode_connector_attach_encoder(connector, encoder);
-				if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-					if (rdev->is_atom_bios)
-						radeon_atom_backlight_init(radeon_encoder, connector);
-					else
-						radeon_legacy_backlight_init(radeon_encoder, connector);
-					rdev->mode_info.bl_encoder = radeon_encoder;
-				}
+				if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+					radeon_encoder_add_backlight(radeon_encoder, connector);
 			}
 		}
 	}
@@ -343,7 +371,7 @@ bool radeon_dig_monitor_is_duallink(stru
 	case DRM_MODE_CONNECTOR_HDMIB:
 		if (radeon_connector->use_digital) {
 			/* HDMI 1.3 supports up to 340 Mhz over single link */
-			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 				if (pixel_clock > 340000)
 					return true;
 				else
@@ -365,7 +393,7 @@ bool radeon_dig_monitor_is_duallink(stru
 			return false;
 		else {
 			/* HDMI 1.3 supports up to 340 Mhz over single link */
-			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
 				if (pixel_clock > 340000)
 					return true;
 				else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -127,8 +127,7 @@ static int radeonfb_create_pinned_object
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = radeon_gem_object_create(rdev, aligned_size, 0,
 				       RADEON_GEM_DOMAIN_VRAM,
-				       false, true,
-				       &gobj);
+				       0, true, &gobj);
 	if (ret) {
 		printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
 		       aligned_size);
@@ -331,7 +330,7 @@ static int radeon_fbdev_destroy(struct d
 	return 0;
 }
 
-static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
 	.gamma_set = radeon_crtc_fb_gamma_set,
 	.gamma_get = radeon_crtc_fb_gamma_get,
 	.fb_probe = radeonfb_create,
@@ -353,7 +352,9 @@ int radeon_fbdev_init(struct radeon_devi
 
 	rfbdev->rdev = rdev;
 	rdev->mode_info.rfbdev = rfbdev;
-	rfbdev->helper.funcs = &radeon_fb_helper_funcs;
+
+	drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
+			      &radeon_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
 				 rdev->num_crtc,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_gart.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_gart.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2014-09-28 17:29:07.000000000 -0400
@@ -128,7 +128,7 @@ int radeon_gart_table_vram_alloc(struct
 	if (rdev->gart.robj == NULL) {
 		r = radeon_bo_create(rdev, rdev->gart.table_size,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     NULL, &rdev->gart.robj);
+				     0, NULL, &rdev->gart.robj);
 		if (r) {
 			return r;
 		}
@@ -243,7 +243,8 @@ void radeon_gart_unbind(struct radeon_de
 			page_base = rdev->gart.pages_addr[p];
 			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
 				if (rdev->gart.ptr) {
-					radeon_gart_set_page(rdev, t, page_base);
+					radeon_gart_set_page(rdev, t, page_base,
+							     RADEON_GART_PAGE_DUMMY);
 				}
 				page_base += RADEON_GPU_PAGE_SIZE;
 			}
@@ -261,13 +262,15 @@ void radeon_gart_unbind(struct radeon_de
  * @pages: number of pages to bind
  * @pagelist: pages to bind
  * @dma_addr: DMA addresses of pages
+ * @flags: RADEON_GART_PAGE_* flags
  *
  * Binds the requested pages to the gart page table
  * (all asics).
  * Returns 0 for success, -EINVAL for failure.
  */
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-		     int pages, struct page **pagelist, dma_addr_t *dma_addr)
+		     int pages, struct page **pagelist, dma_addr_t *dma_addr,
+		     uint32_t flags)
 {
 	unsigned t;
 	unsigned p;
@@ -287,7 +290,7 @@ int radeon_gart_bind(struct radeon_devic
 		if (rdev->gart.ptr) {
 			page_base = rdev->gart.pages_addr[p];
 			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-				radeon_gart_set_page(rdev, t, page_base);
+				radeon_gart_set_page(rdev, t, page_base, flags);
 				page_base += RADEON_GPU_PAGE_SIZE;
 			}
 		}
@@ -298,33 +301,6 @@ int radeon_gart_bind(struct radeon_devic
 }
 
 /**
- * radeon_gart_restore - bind all pages in the gart page table
- *
- * @rdev: radeon_device pointer
- *
- * Binds all pages in the gart page table (all asics).
- * Used to rebuild the gart table on device startup or resume.
- */
-void radeon_gart_restore(struct radeon_device *rdev)
-{
-	int i, j, t;
-	u64 page_base;
-
-	if (!rdev->gart.ptr) {
-		return;
-	}
-	for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
-		page_base = rdev->gart.pages_addr[i];
-		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-			radeon_gart_set_page(rdev, t, page_base);
-			page_base += RADEON_GPU_PAGE_SIZE;
-		}
-	}
-	mb();
-	radeon_gart_tlb_flush(rdev);
-}
-
-/**
  * radeon_gart_init - init the driver info for managing the gart
  *
  * @rdev: radeon_device pointer
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,9 @@ void radeon_gem_object_free(struct drm_g
 	}
 }
 
-int radeon_gem_object_create(struct radeon_device *rdev, int size,
+int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
 				int alignment, int initial_domain,
-				bool discardable, bool kernel,
+				u32 flags, bool kernel,
 				struct drm_gem_object **obj)
 {
 	struct radeon_bo *robj;
@@ -55,23 +55,26 @@ int radeon_gem_object_create(struct rade
 		alignment = PAGE_SIZE;
 	}
 
-	/* maximun bo size is the minimun btw visible vram and gtt size */
-	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+	/* Maximum bo size is the unpinned gtt size since we use the gtt to
+	 * handle vram to system pool migrations.
+	 */
+	max_size = rdev->mc.gtt_size - rdev->gart_pin_size;
 	if (size > max_size) {
-		printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
-		       __func__, __LINE__, size >> 20, max_size >> 20);
+		DRM_DEBUG("Allocation size %ldMb bigger than %ldMb limit\n",
+			  size >> 20, max_size >> 20);
 		return -ENOMEM;
 	}
 
 retry:
-	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
+	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain,
+			     flags, NULL, &robj);
 	if (r) {
 		if (r != -ERESTARTSYS) {
 			if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
 				initial_domain |= RADEON_GEM_DOMAIN_GTT;
 				goto retry;
 			}
-			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
+			DRM_ERROR("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
 				  size, initial_domain, alignment, r);
 		}
 		return r;
@@ -208,18 +211,15 @@ int radeon_gem_info_ioctl(struct drm_dev
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_radeon_gem_info *args = data;
 	struct ttm_mem_type_manager *man;
-	unsigned i;
 
 	man = &rdev->mman.bdev.man[TTM_PL_VRAM];
 
 	args->vram_size = rdev->mc.real_vram_size;
 	args->vram_visible = (u64)man->size << PAGE_SHIFT;
-	if (rdev->stollen_vga_memory)
-		args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
-	args->vram_visible -= radeon_fbdev_total_size(rdev);
-	args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024;
-	for(i = 0; i < RADEON_NUM_RINGS; ++i)
-		args->gart_size -= rdev->ring[i].ring_size;
+	args->vram_visible -= rdev->vram_pin_size;
+	args->gart_size = rdev->mc.gtt_size;
+	args->gart_size -= rdev->gart_pin_size;
+
 	return 0;
 }
 
@@ -252,8 +252,8 @@ int radeon_gem_create_ioctl(struct drm_d
 	/* create a gem object to contain this object in */
 	args->size = roundup(args->size, PAGE_SIZE);
 	r = radeon_gem_object_create(rdev, args->size, args->alignment,
-					args->initial_domain, false,
-					false, &gobj);
+				     args->initial_domain, args->flags,
+				     false, &gobj);
 	if (r) {
 		up_read(&rdev->exclusive_lock);
 		r = radeon_gem_handle_lockup(rdev, r);
@@ -358,16 +358,18 @@ int radeon_gem_wait_idle_ioctl(struct dr
 	struct drm_gem_object *gobj;
 	struct radeon_bo *robj;
 	int r;
+	uint32_t cur_placement = 0;
 
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
 	robj = gem_to_radeon_bo(gobj);
-	r = radeon_bo_wait(robj, NULL, false);
-	/* callback hw specific functions if any */
-	if (rdev->asic->ioctl_wait_idle)
-		robj->rdev->asic->ioctl_wait_idle(rdev, robj);
+	r = radeon_bo_wait(robj, &cur_placement, false);
+	/* Flush HDP cache via MMIO if necessary */
+	if (rdev->asic->mmio_hdp_flush &&
+	    radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM)
+		robj->rdev->asic->mmio_hdp_flush(rdev);
 	drm_gem_object_unreference_unlocked(gobj);
 	r = radeon_gem_handle_lockup(rdev, r);
 	return r;
@@ -461,11 +463,6 @@ int radeon_gem_va_ioctl(struct drm_devic
 		args->operation = RADEON_VA_RESULT_ERROR;
 		return -EINVAL;
 	}
-	if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) {
-		dev_err(&dev->pdev->dev, "only supported snooped mapping for now\n");
-		args->operation = RADEON_VA_RESULT_ERROR;
-		return -EINVAL;
-	}
 
 	switch (args->operation) {
 	case RADEON_VA_MAP:
@@ -499,9 +496,9 @@ int radeon_gem_va_ioctl(struct drm_devic
 
 	switch (args->operation) {
 	case RADEON_VA_MAP:
-		if (bo_va->soffset) {
+		if (bo_va->it.start) {
 			args->operation = RADEON_VA_RESULT_VA_EXIST;
-			args->offset = bo_va->soffset;
+			args->offset = bo_va->it.start * RADEON_GPU_PAGE_SIZE;
 			goto out;
 		}
 		r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, args->flags);
@@ -572,9 +569,8 @@ int radeon_mode_dumb_create(struct drm_f
 	args->size = ALIGN(args->size, PAGE_SIZE);
 
 	r = radeon_gem_object_create(rdev, args->size, 0,
-				     RADEON_GEM_DOMAIN_VRAM,
-				     false, ttm_bo_type_device,
-				     &gobj);
+				     RADEON_GEM_DOMAIN_VRAM, 0,
+				     false, &gobj);
 	if (r)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon.h	2014-09-28 17:29:07.000000000 -0400
@@ -64,6 +64,7 @@
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/kref.h>
+#include <linux/interval_tree.h>
 
 #include <ttm/ttm_bo_api.h>
 #include <ttm/ttm_bo_driver.h>
@@ -103,6 +104,9 @@ extern int radeon_hard_reset;
 extern int radeon_vm_size;
 extern int radeon_vm_block_size;
 extern int radeon_deep_color;
+extern int radeon_use_pflipirq;
+extern int radeon_bapm;
+extern int radeon_backlight;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -304,6 +308,9 @@ int radeon_atom_get_leakage_vddc_based_o
 							 u16 *vddc, u16 *vddci,
 							 u16 virtual_voltage_id,
 							 u16 vbios_voltage_id);
+int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
+				u16 virtual_voltage_id,
+				u16 *voltage);
 int radeon_atom_round_to_true_voltage(struct radeon_device *rdev,
 				      u8 voltage_type,
 				      u16 nominal_voltage,
@@ -317,6 +324,9 @@ int radeon_atom_get_voltage_table(struct
 				  struct atom_voltage_table *voltage_table);
 bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
 				 u8 voltage_type, u8 voltage_mode);
+int radeon_atom_get_svi2_info(struct radeon_device *rdev,
+			      u8 voltage_type,
+			      u8 *svd_gpio_id, u8 *svc_gpio_id);
 void radeon_atom_update_memory_dll(struct radeon_device *rdev,
 				   u32 mem_clock);
 void radeon_atom_set_ac_timing(struct radeon_device *rdev,
@@ -441,14 +451,12 @@ struct radeon_mman {
 struct radeon_bo_va {
 	/* protected by bo being reserved */
 	struct list_head		bo_list;
-	uint64_t			soffset;
-	uint64_t			eoffset;
 	uint32_t			flags;
-	bool				valid;
+	uint64_t			addr;
 	unsigned			ref_count;
 
 	/* protected by vm mutex */
-	struct list_head		vm_list;
+	struct interval_tree_node	it;
 	struct list_head		vm_status;
 
 	/* constant after initialization */
@@ -465,6 +473,7 @@ struct radeon_bo {
 	struct ttm_placement		placement;
 	struct ttm_buffer_object	tbo;
 	struct ttm_bo_kmap_obj		kmap;
+	u32				flags;
 	unsigned			pin_count;
 	void				*kptr;
 	u32				tiling_flags;
@@ -543,9 +552,9 @@ struct radeon_gem {
 
 int radeon_gem_init(struct radeon_device *rdev);
 void radeon_gem_fini(struct radeon_device *rdev);
-int radeon_gem_object_create(struct radeon_device *rdev, int size,
+int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
 				int alignment, int initial_domain,
-				bool discardable, bool kernel,
+				u32 flags, bool kernel,
 				struct drm_gem_object **obj);
 
 int radeon_mode_dumb_create(struct drm_file *file_priv,
@@ -590,6 +599,12 @@ struct radeon_mc;
 #define RADEON_GPU_PAGE_SHIFT 12
 #define RADEON_GPU_PAGE_ALIGN(a) (((a) + RADEON_GPU_PAGE_MASK) & ~RADEON_GPU_PAGE_MASK)
 
+#define RADEON_GART_PAGE_DUMMY  0
+#define RADEON_GART_PAGE_VALID	(1 << 0)
+#define RADEON_GART_PAGE_READ	(1 << 1)
+#define RADEON_GART_PAGE_WRITE	(1 << 2)
+#define RADEON_GART_PAGE_SNOOP	(1 << 3)
+
 struct radeon_gart {
 	dma_addr_t			table_addr;
 	struct radeon_bo		*robj;
@@ -614,8 +629,7 @@ void radeon_gart_unbind(struct radeon_de
 			int pages);
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
 		     int pages, struct page **pagelist,
-		     dma_addr_t *dma_addr);
-void radeon_gart_restore(struct radeon_device *rdev);
+		     dma_addr_t *dma_addr, uint32_t flags);
 
 
 /*
@@ -855,9 +869,9 @@ struct radeon_mec {
 #define R600_PTE_FRAG_64KB	(4 << 7)
 #define R600_PTE_FRAG_256KB	(6 << 7)
 
-/* flags used for GART page table entries on R600+ */
-#define R600_PTE_GART	( R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED \
-			| R600_PTE_READABLE | R600_PTE_WRITEABLE)
+/* flags needed to be set so we can copy directly from the GART table */
+#define R600_PTE_GART_MASK	( R600_PTE_READABLE | R600_PTE_WRITEABLE | \
+				  R600_PTE_SYSTEM | R600_PTE_VALID )
 
 struct radeon_vm_pt {
 	struct radeon_bo		*bo;
@@ -865,9 +879,12 @@ struct radeon_vm_pt {
 };
 
 struct radeon_vm {
-	struct list_head		va;
+	struct rb_root			va;
 	unsigned			id;
 
+	/* BOs moved, but not yet updated in the PT */
+	struct list_head		invalidated;
+
 	/* BOs freed, but not yet updated in the PT */
 	struct list_head		freed;
 
@@ -899,6 +916,8 @@ struct radeon_vm_manager {
 	u64				vram_base_offset;
 	/* is vm enabled? */
 	bool				enabled;
+	/* for hw to save the PD addr on suspend/resume */
+	uint32_t			saved_table_addr[RADEON_NUM_VM];
 };
 
 /*
@@ -952,7 +971,7 @@ int radeon_ib_get(struct radeon_device *
 		  unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
-		       struct radeon_ib *const_ib);
+		       struct radeon_ib *const_ib, bool hdp_flush);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
 int radeon_ib_ring_tests(struct radeon_device *rdev);
@@ -962,8 +981,10 @@ bool radeon_ring_supports_scratch_reg(st
 void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
 int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
-void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp);
-void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp);
+void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp,
+			bool hdp_flush);
+void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp,
+			       bool hdp_flush);
 void radeon_ring_undo(struct radeon_ring *ring);
 void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
@@ -1740,6 +1761,7 @@ struct radeon_asic_ring {
 	/* command emmit functions */
 	void (*ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
 	void (*emit_fence)(struct radeon_device *rdev, struct radeon_fence *fence);
+	void (*hdp_flush)(struct radeon_device *rdev, struct radeon_ring *ring);
 	bool (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp,
 			       struct radeon_semaphore *semaphore, bool emit_wait);
 	void (*vm_flush)(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
@@ -1763,13 +1785,8 @@ struct radeon_asic {
 	int (*suspend)(struct radeon_device *rdev);
 	void (*vga_set_state)(struct radeon_device *rdev, bool state);
 	int (*asic_reset)(struct radeon_device *rdev);
-	/* ioctl hw specific callback. Some hw might want to perform special
-	 * operation on specific ioctl. For instance on wait idle some hw
-	 * might want to perform and HDP flush through MMIO as it seems that
-	 * some R6XX/R7XX hw doesn't take HDP flush into account if programmed
-	 * through ring.
-	 */
-	void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
+	/* Flush the HDP cache via MMIO */
+	void (*mmio_hdp_flush)(struct radeon_device *rdev);
 	/* check if 3D engine is idle */
 	bool (*gui_idle)(struct radeon_device *rdev);
 	/* wait for mc_idle */
@@ -1782,16 +1799,26 @@ struct radeon_asic {
 	struct {
 		void (*tlb_flush)(struct radeon_device *rdev);
 		void (*set_page)(struct radeon_device *rdev, unsigned i,
-				 uint64_t addr);
+				 uint64_t addr, uint32_t flags);
 	} gart;
 	struct {
 		int (*init)(struct radeon_device *rdev);
 		void (*fini)(struct radeon_device *rdev);
-		void (*set_page)(struct radeon_device *rdev,
-				 struct radeon_ib *ib,
-				 uint64_t pe,
-				 uint64_t addr, unsigned count,
-				 uint32_t incr, uint32_t flags);
+		void (*copy_pages)(struct radeon_device *rdev,
+				   struct radeon_ib *ib,
+				   uint64_t pe, uint64_t src,
+				   unsigned count);
+		void (*write_pages)(struct radeon_device *rdev,
+				    struct radeon_ib *ib,
+				    uint64_t pe,
+				    uint64_t addr, unsigned count,
+				    uint32_t incr, uint32_t flags);
+		void (*set_pages)(struct radeon_device *rdev,
+				  struct radeon_ib *ib,
+				  uint64_t pe,
+				  uint64_t addr, unsigned count,
+				  uint32_t incr, uint32_t flags);
+		void (*pad_ib)(struct radeon_ib *ib);
 	} vm;
 	/* ring specific callbacks */
 	struct radeon_asic_ring *ring[RADEON_NUM_RINGS];
@@ -2299,10 +2326,12 @@ struct radeon_device {
 	const struct firmware *mc_fw;	/* NI MC firmware */
 	const struct firmware *ce_fw;	/* SI CE firmware */
 	const struct firmware *mec_fw;	/* CIK MEC firmware */
+	const struct firmware *mec2_fw;	/* KV MEC2 firmware */
 	const struct firmware *sdma_fw;	/* CIK SDMA firmware */
 	const struct firmware *smc_fw;	/* SMC firmware */
 	const struct firmware *uvd_fw;	/* UVD firmware */
 	const struct firmware *vce_fw;	/* VCE firmware */
+	bool new_fw;
 	struct r600_vram_scratch vram_scratch;
 	int msi_enabled; /* msi enabled */
 	struct r600_ih ih; /* r6/700 interrupt ring */
@@ -2342,6 +2371,11 @@ struct radeon_device {
 
 	struct dev_pm_domain vga_pm_domain;
 	bool have_disp_power_ref;
+	u32 px_quirk_flags;
+
+	/* tracking pinned memory */
+	u64 vram_pin_size;
+	u64 gart_pin_size;
 };
 
 bool radeon_is_px(struct drm_device *dev);
@@ -2352,10 +2386,42 @@ int radeon_device_init(struct radeon_dev
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
-		      bool always_indirect);
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
-		  bool always_indirect);
+#define RADEON_MIN_MMIO_SIZE 0x10000
+
+static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+				    bool always_indirect)
+{
+	/* The mmio size is 64kb at minimum. Allows the if to be optimized out. */
+	if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
+		return readl(((void __iomem *)rdev->rmmio) + reg);
+	else {
+		unsigned long flags;
+		uint32_t ret;
+
+		spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+		spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+		return ret;
+	}
+}
+
+static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+				bool always_indirect)
+{
+	if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
+		writel(v, ((void __iomem *)rdev->rmmio) + reg);
+	else {
+		unsigned long flags;
+
+		spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+		spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+	}
+}
+
 u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
 void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 
@@ -2709,10 +2775,13 @@ void radeon_ring_write(struct radeon_rin
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
 #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
-#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p))
+#define radeon_gart_set_page(rdev, i, p, f) (rdev)->asic->gart.set_page((rdev), (i), (p), (f))
 #define radeon_asic_vm_init(rdev) (rdev)->asic->vm.init((rdev))
 #define radeon_asic_vm_fini(rdev) (rdev)->asic->vm.fini((rdev))
-#define radeon_asic_vm_set_page(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.set_page((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_copy_pages(rdev, ib, pe, src, count) ((rdev)->asic->vm.copy_pages((rdev), (ib), (pe), (src), (count)))
+#define radeon_asic_vm_write_pages(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.write_pages((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_set_pages(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.set_pages((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_pad_ib(rdev, ib) ((rdev)->asic->vm.pad_ib((ib)))
 #define radeon_ring_start(rdev, r, cp) (rdev)->asic->ring[(r)]->ring_start((rdev), (cp))
 #define radeon_ring_test(rdev, r, cp) (rdev)->asic->ring[(r)]->ring_test((rdev), (cp))
 #define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)]->ib_test((rdev), (cp))
@@ -2840,6 +2909,8 @@ int radeon_vm_update_page_directory(stru
 				    struct radeon_vm *vm);
 int radeon_vm_clear_freed(struct radeon_device *rdev,
 			  struct radeon_vm *vm);
+int radeon_vm_clear_invalids(struct radeon_device *rdev,
+			     struct radeon_vm *vm);
 int radeon_vm_bo_update(struct radeon_device *rdev,
 			struct radeon_bo_va *bo_va,
 			struct ttm_mem_reg *mem);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ib.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ib.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ib.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ *          Christian KÃ¶nig
+ */
+#include <drm/drmP.h>
+#include "radeon.h"
+
+/*
+ * IB
+ * IBs (Indirect Buffers) and areas of GPU accessible memory where
+ * commands are stored.  You can put a pointer to the IB in the
+ * command ring and the hw will fetch the commands from the IB
+ * and execute them.  Generally userspace acceleration drivers
+ * produce command buffers which are send to the kernel and
+ * put in IBs for execution by the requested ring.
+ */
+static int radeon_debugfs_sa_init(struct radeon_device *rdev);
+
+/**
+ * radeon_ib_get - request an IB (Indirect Buffer)
+ *
+ * @rdev: radeon_device pointer
+ * @ring: ring index the IB is associated with
+ * @ib: IB object returned
+ * @size: requested IB size
+ *
+ * Request an IB (all asics).  IBs are allocated using the
+ * suballocator.
+ * Returns 0 on success, error on failure.
+ */
+int radeon_ib_get(struct radeon_device *rdev, int ring,
+		  struct radeon_ib *ib, struct radeon_vm *vm,
+		  unsigned size)
+{
+	int r;
+
+	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256);
+	if (r) {
+		dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
+		return r;
+	}
+
+	r = radeon_semaphore_create(rdev, &ib->semaphore);
+	if (r) {
+		return r;
+	}
+
+	ib->ring = ring;
+	ib->fence = NULL;
+	ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo);
+	ib->vm = vm;
+	if (vm) {
+		/* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address
+		 * space and soffset is the offset inside the pool bo
+		 */
+		ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET;
+	} else {
+		ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
+	}
+	ib->is_const_ib = false;
+
+	return 0;
+}
+
+/**
+ * radeon_ib_free - free an IB (Indirect Buffer)
+ *
+ * @rdev: radeon_device pointer
+ * @ib: IB object to free
+ *
+ * Free an IB (all asics).
+ */
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
+	radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);
+	radeon_fence_unref(&ib->fence);
+}
+
+/**
+ * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
+ *
+ * @rdev: radeon_device pointer
+ * @ib: IB object to schedule
+ * @const_ib: Const IB to schedule (SI only)
+ * @hdp_flush: Whether or not to perform an HDP cache flush
+ *
+ * Schedule an IB on the associated ring (all asics).
+ * Returns 0 on success, error on failure.
+ *
+ * On SI, there are two parallel engines fed from the primary ring,
+ * the CE (Constant Engine) and the DE (Drawing Engine).  Since
+ * resource descriptors have moved to memory, the CE allows you to
+ * prime the caches while the DE is updating register state so that
+ * the resource descriptors will be already in cache when the draw is
+ * processed.  To accomplish this, the userspace driver submits two
+ * IBs, one for the CE and one for the DE.  If there is a CE IB (called
+ * a CONST_IB), it will be put on the ring prior to the DE IB.  Prior
+ * to SI there was just a DE IB.
+ */
+int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
+		       struct radeon_ib *const_ib, bool hdp_flush)
+{
+	struct radeon_ring *ring = &rdev->ring[ib->ring];
+	int r = 0;
+
+	if (!ib->length_dw || !ring->ready) {
+		/* TODO: Nothings in the ib we should report. */
+		dev_err(rdev->dev, "couldn't schedule ib\n");
+		return -EINVAL;
+	}
+
+	/* 64 dwords should be enough for fence too */
+	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
+	if (r) {
+		dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
+		return r;
+	}
+
+	/* grab a vm id if necessary */
+	if (ib->vm) {
+		struct radeon_fence *vm_id_fence;
+		vm_id_fence = radeon_vm_grab_id(rdev, ib->vm, ib->ring);
+        	radeon_semaphore_sync_to(ib->semaphore, vm_id_fence);
+	}
+
+	/* sync with other rings */
+	r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring);
+	if (r) {
+		dev_err(rdev->dev, "failed to sync rings (%d)\n", r);
+		radeon_ring_unlock_undo(rdev, ring);
+		return r;
+	}
+
+	if (ib->vm)
+		radeon_vm_flush(rdev, ib->vm, ib->ring);
+
+	if (const_ib) {
+		radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
+		radeon_semaphore_free(rdev, &const_ib->semaphore, NULL);
+	}
+	radeon_ring_ib_execute(rdev, ib->ring, ib);
+	r = radeon_fence_emit(rdev, &ib->fence, ib->ring);
+	if (r) {
+		dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r);
+		radeon_ring_unlock_undo(rdev, ring);
+		return r;
+	}
+	if (const_ib) {
+		const_ib->fence = radeon_fence_ref(ib->fence);
+	}
+
+	if (ib->vm)
+		radeon_vm_fence(rdev, ib->vm, ib->fence);
+
+	radeon_ring_unlock_commit(rdev, ring, hdp_flush);
+	return 0;
+}
+
+/**
+ * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the suballocator to manage a pool of memory
+ * for use as IBs (all asics).
+ * Returns 0 on success, error on failure.
+ */
+int radeon_ib_pool_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->ib_pool_ready) {
+		return 0;
+	}
+
+	if (rdev->family >= CHIP_BONAIRE) {
+		r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
+					      RADEON_IB_POOL_SIZE*64*1024,
+					      RADEON_GPU_PAGE_SIZE,
+					      RADEON_GEM_DOMAIN_GTT,
+					      RADEON_GEM_GTT_WC);
+	} else {
+		/* Before CIK, it's better to stick to cacheable GTT due
+		 * to the command stream checking
+		 */
+		r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
+					      RADEON_IB_POOL_SIZE*64*1024,
+					      RADEON_GPU_PAGE_SIZE,
+					      RADEON_GEM_DOMAIN_GTT, 0);
+	}
+	if (r) {
+		return r;
+	}
+
+	r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo);
+	if (r) {
+		return r;
+	}
+
+	rdev->ib_pool_ready = true;
+	if (radeon_debugfs_sa_init(rdev)) {
+		dev_err(rdev->dev, "failed to register debugfs file for SA\n");
+	}
+	return 0;
+}
+
+/**
+ * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Tear down the suballocator managing the pool of memory
+ * for use as IBs (all asics).
+ */
+void radeon_ib_pool_fini(struct radeon_device *rdev)
+{
+	if (rdev->ib_pool_ready) {
+		radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo);
+		radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo);
+		rdev->ib_pool_ready = false;
+	}
+}
+
+/**
+ * radeon_ib_ring_tests - test IBs on the rings
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Test an IB (Indirect Buffer) on each ring.
+ * If the test fails, disable the ring.
+ * Returns 0 on success, error if the primary GFX ring
+ * IB test fails.
+ */
+int radeon_ib_ring_tests(struct radeon_device *rdev)
+{
+	unsigned i;
+	int r;
+
+	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+		struct radeon_ring *ring = &rdev->ring[i];
+
+		if (!ring->ready)
+			continue;
+
+		r = radeon_ib_test(rdev, i, ring);
+		if (r) {
+			ring->ready = false;
+			rdev->needs_reset = false;
+
+			if (i == RADEON_RING_TYPE_GFX_INDEX) {
+				/* oh, oh, that's really bad */
+				DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r);
+		                rdev->accel_working = false;
+				return r;
+
+			} else {
+				/* still not good, but we can live with it */
+				DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r);
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+
+static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
+
+	return 0;
+
+}
+
+static struct drm_info_list radeon_debugfs_sa_list[] = {
+        {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
+};
+
+#endif
+
+static int radeon_debugfs_sa_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
+#else
+	return 0;
+#endif
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -254,7 +254,18 @@ static int radeon_info_ioctl(struct drm_
 		}
 		break;
 	case RADEON_INFO_ACCEL_WORKING2:
-		*value = rdev->accel_working;
+		if (rdev->family == CHIP_HAWAII) {
+			if (rdev->accel_working) {
+				if (rdev->new_fw)
+					*value = 3;
+				else
+					*value = 2;
+			} else {
+				*value = 0;
+			}
+		} else {
+			*value = rdev->accel_working;
+		}
 		break;
 	case RADEON_INFO_TILING_CONFIG:
 		if (rdev->family >= CHIP_BONAIRE)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2014-09-28 17:29:07.000000000 -0400
@@ -685,10 +685,11 @@ extern bool radeon_dig_monitor_is_dualli
 
 extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
 extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
-extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
 extern int radeon_get_monitor_bpc(struct drm_connector *connector);
 
+extern struct edid *radeon_connector_edid(struct drm_connector *connector);
+
 extern void radeon_connector_hotplug(struct drm_connector *connector);
 extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
 				       struct drm_display_mode *mode);
@@ -738,7 +739,6 @@ extern void radeon_i2c_put_byte(struct r
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux);
-extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,16 +46,6 @@ static void radeon_bo_clear_surface_reg(
  * function are calling it.
  */
 
-static void radeon_bo_clear_va(struct radeon_bo *bo)
-{
-	struct radeon_bo_va *bo_va, *tmp;
-
-	list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) {
-		/* remove from all vm address space */
-		radeon_vm_bo_rmv(bo->rdev, bo_va);
-	}
-}
-
 static void radeon_update_memory_usage(struct radeon_bo *bo,
 				       unsigned mem_type, int sign)
 {
@@ -90,7 +80,7 @@ static void radeon_ttm_bo_destroy(struct
 	list_del_init(&bo->list);
 	mutex_unlock(&bo->rdev->gem.mutex);
 	radeon_bo_clear_surface_reg(bo);
-	radeon_bo_clear_va(bo);
+	WARN_ON(!list_empty(&bo->va));
 	drm_gem_object_release(&bo->gem_base);
 	kfree(bo);
 }
@@ -114,15 +104,23 @@ void radeon_ttm_placement_from_domain(st
 		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
 					TTM_PL_FLAG_VRAM;
 	if (domain & RADEON_GEM_DOMAIN_GTT) {
-		if (rbo->rdev->flags & RADEON_IS_AGP) {
-			rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
+		if (rbo->flags & RADEON_GEM_GTT_UC) {
+			rbo->placements[c++] = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_TT;
+		} else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
+			   (rbo->rdev->flags & RADEON_IS_AGP)) {
+			rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
+				TTM_PL_FLAG_TT;
 		} else {
 			rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
 		}
 	}
 	if (domain & RADEON_GEM_DOMAIN_CPU) {
-		if (rbo->rdev->flags & RADEON_IS_AGP) {
-			rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM;
+		if (rbo->flags & RADEON_GEM_GTT_UC) {
+			rbo->placements[c++] = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_SYSTEM;
+		} else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
+		    rbo->rdev->flags & RADEON_IS_AGP) {
+			rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
+				TTM_PL_FLAG_SYSTEM;
 		} else {
 			rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
 		}
@@ -146,7 +144,7 @@ void radeon_ttm_placement_from_domain(st
 
 int radeon_bo_create(struct radeon_device *rdev,
 		     unsigned long size, int byte_align, bool kernel, u32 domain,
-		     struct sg_table *sg, struct radeon_bo **bo_ptr)
+		     u32 flags, struct sg_table *sg, struct radeon_bo **bo_ptr)
 {
 	struct radeon_bo *bo;
 	enum ttm_bo_type type;
@@ -183,6 +181,12 @@ int radeon_bo_create(struct radeon_devic
 	bo->initial_domain = domain & (RADEON_GEM_DOMAIN_VRAM |
 	                               RADEON_GEM_DOMAIN_GTT |
 	                               RADEON_GEM_DOMAIN_CPU);
+
+	bo->flags = flags;
+	/* PCI GART is always snooped */
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
+
 	radeon_ttm_placement_from_domain(bo, domain);
 	/* Kernel allocation are uninterruptible */
 	down_read(&rdev->pm.mclk_lock);
@@ -232,6 +236,15 @@ void radeon_bo_kunmap(struct radeon_bo *
 	ttm_bo_kunmap(&bo->kmap);
 }
 
+struct radeon_bo *radeon_bo_ref(struct radeon_bo *bo)
+{
+	if (bo == NULL)
+		return NULL;
+
+	ttm_bo_reference(&bo->tbo);
+	return bo;
+}
+
 void radeon_bo_unref(struct radeon_bo **bo)
 {
 	struct ttm_buffer_object *tbo;
@@ -241,9 +254,7 @@ void radeon_bo_unref(struct radeon_bo **
 		return;
 	rdev = (*bo)->rdev;
 	tbo = &((*bo)->tbo);
-	down_read(&rdev->pm.mclk_lock);
 	ttm_bo_unref(&tbo);
-	up_read(&rdev->pm.mclk_lock);
 	if (tbo == NULL)
 		*bo = NULL;
 }
@@ -292,9 +303,13 @@ int radeon_bo_pin_restricted(struct rade
 		bo->pin_count = 1;
 		if (gpu_addr != NULL)
 			*gpu_addr = radeon_bo_gpu_offset(bo);
-	}
-	if (unlikely(r != 0))
+		if (domain == RADEON_GEM_DOMAIN_VRAM)
+			bo->rdev->vram_pin_size += radeon_bo_size(bo);
+		else
+			bo->rdev->gart_pin_size += radeon_bo_size(bo);
+	} else {
 		dev_err(bo->rdev->dev, "%p pin failed\n", bo);
+	}
 	return r;
 }
 
@@ -317,8 +332,14 @@ int radeon_bo_unpin(struct radeon_bo *bo
 	for (i = 0; i < bo->placement.num_placement; i++)
 		bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
-	if (unlikely(r != 0))
+	if (likely(r == 0)) {
+		if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
+			bo->rdev->vram_pin_size -= radeon_bo_size(bo);
+		else
+			bo->rdev->gart_pin_size -= radeon_bo_size(bo);
+	} else {
 		dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
+	}
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -124,11 +124,12 @@ extern int radeon_bo_wait(struct radeon_
 
 extern int radeon_bo_create(struct radeon_device *rdev,
 			    unsigned long size, int byte_align,
-			    bool kernel, u32 domain,
+			    bool kernel, u32 domain, u32 flags,
 			    struct sg_table *sg,
 			    struct radeon_bo **bo_ptr);
 extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
+extern struct radeon_bo *radeon_bo_ref(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
 extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
 extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
@@ -170,7 +171,8 @@ static inline void * radeon_sa_bo_cpu_ad
 
 extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,
 				     struct radeon_sa_manager *sa_manager,
-				     unsigned size, u32 align, u32 domain);
+				     unsigned size, u32 align, u32 domain,
+				     u32 flags);
 extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
 				      struct radeon_sa_manager *sa_manager);
 extern int radeon_sa_bo_manager_start(struct radeon_device *rdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -460,10 +460,6 @@ static ssize_t radeon_get_dpm_state(stru
 	struct radeon_device *rdev = ddev->dev_private;
 	enum radeon_pm_state_type pm = rdev->pm.dpm.user_state;
 
-	if  ((rdev->flags & RADEON_IS_PX) &&
-	     (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
-		return snprintf(buf, PAGE_SIZE, "off\n");
-
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			(pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
 			(pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance");
@@ -477,11 +473,6 @@ static ssize_t radeon_set_dpm_state(stru
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct radeon_device *rdev = ddev->dev_private;
 
-	/* Can't set dpm state when the card is off */
-	if  ((rdev->flags & RADEON_IS_PX) &&
-	     (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
-		return -EINVAL;
-
 	mutex_lock(&rdev->pm.mutex);
 	if (strncmp("battery", buf, strlen("battery")) == 0)
 		rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY;
@@ -495,7 +486,12 @@ static ssize_t radeon_set_dpm_state(stru
 		goto fail;
 	}
 	mutex_unlock(&rdev->pm.mutex);
-	radeon_pm_compute_clocks(rdev);
+
+	/* Can't set dpm state when the card is off */
+	if (!(rdev->flags & RADEON_IS_PX) ||
+	    (ddev->switch_power_state == DRM_SWITCH_POWER_ON))
+		radeon_pm_compute_clocks(rdev);
+
 fail:
 	return count;
 }
@@ -1303,10 +1299,6 @@ int radeon_pm_init(struct radeon_device
 	case CHIP_RS780:
 	case CHIP_RS880:
 	case CHIP_RV770:
-	case CHIP_BARTS:
-	case CHIP_TURKS:
-	case CHIP_CAICOS:
-	case CHIP_CAYMAN:
 		/* DPM requires the RLC, RV770+ dGPU requires SMC */
 		if (!rdev->rlc_fw)
 			rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1330,6 +1322,10 @@ int radeon_pm_init(struct radeon_device
 	case CHIP_PALM:
 	case CHIP_SUMO:
 	case CHIP_SUMO2:
+	case CHIP_BARTS:
+	case CHIP_TURKS:
+	case CHIP_CAICOS:
+	case CHIP_CAYMAN:
 	case CHIP_ARUBA:
 	case CHIP_TAHITI:
 	case CHIP_PITCAIRN:
@@ -1400,9 +1396,7 @@ static void radeon_pm_fini_old(struct ra
 	}
 
 	radeon_hwmon_fini(rdev);
-
-	if (rdev->pm.power_state)
-		kfree(rdev->pm.power_state);
+	kfree(rdev->pm.power_state);
 }
 
 static void radeon_pm_fini_dpm(struct radeon_device *rdev)
@@ -1421,9 +1415,7 @@ static void radeon_pm_fini_dpm(struct ra
 	radeon_dpm_fini(rdev);
 
 	radeon_hwmon_fini(rdev);
-
-	if (rdev->pm.power_state)
-		kfree(rdev->pm.power_state);
+	kfree(rdev->pm.power_state);
 }
 
 void radeon_pm_fini(struct radeon_device *rdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_prime.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_prime.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_prime.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_prime.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@ struct drm_gem_object *radeon_gem_prime_
 	int ret;
 
 	ret = radeon_bo_create(rdev, size, PAGE_SIZE, false,
-			       RADEON_GEM_DOMAIN_GTT, sg, &bo);
+			       RADEON_GEM_DOMAIN_GTT, 0, sg, &bo);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -103,3 +103,11 @@ void radeon_gem_prime_unpin(struct drm_g
 	radeon_bo_unpin(bo);
 	radeon_bo_unreserve(bo);
 }
+
+
+struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+	struct radeon_bo *bo = gem_to_radeon_bo(obj);
+
+	return bo->tbo.resv;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,258 +26,8 @@
  *          Jerome Glisse
  *          Christian KÃ¶nig
  */
-#include <linux/seq_file.h>
-#include <linux/slab.h>
 #include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_reg.h"
 #include "radeon.h"
-#include "atom.h"
-
-/*
- * IB
- * IBs (Indirect Buffers) and areas of GPU accessible memory where
- * commands are stored.  You can put a pointer to the IB in the
- * command ring and the hw will fetch the commands from the IB
- * and execute them.  Generally userspace acceleration drivers
- * produce command buffers which are send to the kernel and
- * put in IBs for execution by the requested ring.
- */
-static int radeon_debugfs_sa_init(struct radeon_device *rdev);
-
-/**
- * radeon_ib_get - request an IB (Indirect Buffer)
- *
- * @rdev: radeon_device pointer
- * @ring: ring index the IB is associated with
- * @ib: IB object returned
- * @size: requested IB size
- *
- * Request an IB (all asics).  IBs are allocated using the
- * suballocator.
- * Returns 0 on success, error on failure.
- */
-int radeon_ib_get(struct radeon_device *rdev, int ring,
-		  struct radeon_ib *ib, struct radeon_vm *vm,
-		  unsigned size)
-{
-	int r;
-
-	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256);
-	if (r) {
-		dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
-		return r;
-	}
-
-	r = radeon_semaphore_create(rdev, &ib->semaphore);
-	if (r) {
-		return r;
-	}
-
-	ib->ring = ring;
-	ib->fence = NULL;
-	ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo);
-	ib->vm = vm;
-	if (vm) {
-		/* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address
-		 * space and soffset is the offset inside the pool bo
-		 */
-		ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET;
-	} else {
-		ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
-	}
-	ib->is_const_ib = false;
-
-	return 0;
-}
-
-/**
- * radeon_ib_free - free an IB (Indirect Buffer)
- *
- * @rdev: radeon_device pointer
- * @ib: IB object to free
- *
- * Free an IB (all asics).
- */
-void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
-{
-	radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
-	radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);
-	radeon_fence_unref(&ib->fence);
-}
-
-/**
- * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
- *
- * @rdev: radeon_device pointer
- * @ib: IB object to schedule
- * @const_ib: Const IB to schedule (SI only)
- *
- * Schedule an IB on the associated ring (all asics).
- * Returns 0 on success, error on failure.
- *
- * On SI, there are two parallel engines fed from the primary ring,
- * the CE (Constant Engine) and the DE (Drawing Engine).  Since
- * resource descriptors have moved to memory, the CE allows you to
- * prime the caches while the DE is updating register state so that
- * the resource descriptors will be already in cache when the draw is
- * processed.  To accomplish this, the userspace driver submits two
- * IBs, one for the CE and one for the DE.  If there is a CE IB (called
- * a CONST_IB), it will be put on the ring prior to the DE IB.  Prior
- * to SI there was just a DE IB.
- */
-int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
-		       struct radeon_ib *const_ib)
-{
-	struct radeon_ring *ring = &rdev->ring[ib->ring];
-	int r = 0;
-
-	if (!ib->length_dw || !ring->ready) {
-		/* TODO: Nothings in the ib we should report. */
-		dev_err(rdev->dev, "couldn't schedule ib\n");
-		return -EINVAL;
-	}
-
-	/* 64 dwords should be enough for fence too */
-	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
-	if (r) {
-		dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
-		return r;
-	}
-
-	/* grab a vm id if necessary */
-	if (ib->vm) {
-		struct radeon_fence *vm_id_fence;
-		vm_id_fence = radeon_vm_grab_id(rdev, ib->vm, ib->ring);
-        	radeon_semaphore_sync_to(ib->semaphore, vm_id_fence);
-	}
-
-	/* sync with other rings */
-	r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring);
-	if (r) {
-		dev_err(rdev->dev, "failed to sync rings (%d)\n", r);
-		radeon_ring_unlock_undo(rdev, ring);
-		return r;
-	}
-
-	if (ib->vm)
-		radeon_vm_flush(rdev, ib->vm, ib->ring);
-
-	if (const_ib) {
-		radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
-		radeon_semaphore_free(rdev, &const_ib->semaphore, NULL);
-	}
-	radeon_ring_ib_execute(rdev, ib->ring, ib);
-	r = radeon_fence_emit(rdev, &ib->fence, ib->ring);
-	if (r) {
-		dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r);
-		radeon_ring_unlock_undo(rdev, ring);
-		return r;
-	}
-	if (const_ib) {
-		const_ib->fence = radeon_fence_ref(ib->fence);
-	}
-
-	if (ib->vm)
-		radeon_vm_fence(rdev, ib->vm, ib->fence);
-
-	radeon_ring_unlock_commit(rdev, ring);
-	return 0;
-}
-
-/**
- * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool
- *
- * @rdev: radeon_device pointer
- *
- * Initialize the suballocator to manage a pool of memory
- * for use as IBs (all asics).
- * Returns 0 on success, error on failure.
- */
-int radeon_ib_pool_init(struct radeon_device *rdev)
-{
-	int r;
-
-	if (rdev->ib_pool_ready) {
-		return 0;
-	}
-	r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
-				      RADEON_IB_POOL_SIZE*64*1024,
-				      RADEON_GPU_PAGE_SIZE,
-				      RADEON_GEM_DOMAIN_GTT);
-	if (r) {
-		return r;
-	}
-
-	r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo);
-	if (r) {
-		return r;
-	}
-
-	rdev->ib_pool_ready = true;
-	if (radeon_debugfs_sa_init(rdev)) {
-		dev_err(rdev->dev, "failed to register debugfs file for SA\n");
-	}
-	return 0;
-}
-
-/**
- * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool
- *
- * @rdev: radeon_device pointer
- *
- * Tear down the suballocator managing the pool of memory
- * for use as IBs (all asics).
- */
-void radeon_ib_pool_fini(struct radeon_device *rdev)
-{
-	if (rdev->ib_pool_ready) {
-		radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo);
-		radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo);
-		rdev->ib_pool_ready = false;
-	}
-}
-
-/**
- * radeon_ib_ring_tests - test IBs on the rings
- *
- * @rdev: radeon_device pointer
- *
- * Test an IB (Indirect Buffer) on each ring.
- * If the test fails, disable the ring.
- * Returns 0 on success, error if the primary GFX ring
- * IB test fails.
- */
-int radeon_ib_ring_tests(struct radeon_device *rdev)
-{
-	unsigned i;
-	int r;
-
-	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-		struct radeon_ring *ring = &rdev->ring[i];
-
-		if (!ring->ready)
-			continue;
-
-		r = radeon_ib_test(rdev, i, ring);
-		if (r) {
-			ring->ready = false;
-			rdev->needs_reset = false;
-
-			if (i == RADEON_RING_TYPE_GFX_INDEX) {
-				/* oh, oh, that's really bad */
-				DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r);
-		                rdev->accel_working = false;
-				return r;
-
-			} else {
-				/* still not good, but we can live with it */
-				DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r);
-			}
-		}
-	}
-	return 0;
-}
 
 /*
  * Rings
@@ -427,17 +177,29 @@ int radeon_ring_lock(struct radeon_devic
  *
  * @rdev: radeon_device pointer
  * @ring: radeon_ring structure holding ring information
+ * @hdp_flush: Whether or not to perform an HDP cache flush
  *
  * Update the wptr (write pointer) to tell the GPU to
  * execute new commands on the ring buffer (all asics).
  */
-void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
+void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring,
+			bool hdp_flush)
 {
+	/* If we are emitting the HDP flush via the ring buffer, we need to
+	 * do it before padding.
+	 */
+	if (hdp_flush && rdev->asic->ring[ring->idx]->hdp_flush)
+		rdev->asic->ring[ring->idx]->hdp_flush(rdev, ring);
 	/* We pad to match fetch size */
 	while (ring->wptr & ring->align_mask) {
 		radeon_ring_write(ring, ring->nop);
 	}
 	mb();
+	/* If we are emitting the HDP flush via MMIO, we need to do it after
+	 * all CPU writes to VRAM finished.
+	 */
+	if (hdp_flush && rdev->asic->mmio_hdp_flush)
+		rdev->asic->mmio_hdp_flush(rdev);
 	radeon_ring_set_wptr(rdev, ring);
 }
 
@@ -447,12 +209,14 @@ void radeon_ring_commit(struct radeon_de
  *
  * @rdev: radeon_device pointer
  * @ring: radeon_ring structure holding ring information
+ * @hdp_flush: Whether or not to perform an HDP cache flush
  *
  * Call radeon_ring_commit() then unlock the ring (all asics).
  */
-void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
+void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring,
+			       bool hdp_flush)
 {
-	radeon_ring_commit(rdev, ring);
+	radeon_ring_commit(rdev, ring, hdp_flush);
 	mutex_unlock(&rdev->ring_lock);
 }
 
@@ -612,7 +376,7 @@ int radeon_ring_restore(struct radeon_de
 		radeon_ring_write(ring, data[i]);
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	kfree(data);
 	return 0;
 }
@@ -640,7 +404,7 @@ int radeon_ring_init(struct radeon_devic
 	/* Allocate ring buffer */
 	if (ring->ring_obj == NULL) {
 		r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_GTT,
+				     RADEON_GEM_DOMAIN_GTT, 0,
 				     NULL, &ring->ring_obj);
 		if (r) {
 			dev_err(rdev->dev, "(%d) ring create failed\n", r);
@@ -791,22 +555,6 @@ static struct drm_info_list radeon_debug
 	{"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index},
 };
 
-static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
-{
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
-
-	return 0;
-
-}
-
-static struct drm_info_list radeon_debugfs_sa_list[] = {
-        {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
-};
-
 #endif
 
 static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring)
@@ -828,12 +576,3 @@ static int radeon_debugfs_ring_init(stru
 #endif
 	return 0;
 }
-
-static int radeon_debugfs_sa_init(struct radeon_device *rdev)
-{
-#if defined(CONFIG_DEBUG_FS)
-	return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
-#else
-	return 0;
-#endif
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_sa.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_sa.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_sa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_sa.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,7 @@ static void radeon_sa_bo_try_free(struct
 
 int radeon_sa_bo_manager_init(struct radeon_device *rdev,
 			      struct radeon_sa_manager *sa_manager,
-			      unsigned size, u32 align, u32 domain)
+			      unsigned size, u32 align, u32 domain, u32 flags)
 {
 	int i, r;
 
@@ -65,7 +65,7 @@ int radeon_sa_bo_manager_init(struct rad
 	}
 
 	r = radeon_bo_create(rdev, size, align, true,
-			     domain, NULL, &sa_manager->bo);
+			     domain, flags, NULL, &sa_manager->bo);
 	if (r) {
 		dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);
 		return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_semaphore.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_semaphore.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_semaphore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_semaphore.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@
 int radeon_semaphore_create(struct radeon_device *rdev,
 			    struct radeon_semaphore **semaphore)
 {
-	uint32_t *cpu_addr;
+	uint64_t *cpu_addr;
 	int i, r;
 
 	*semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
@@ -179,7 +179,7 @@ int radeon_semaphore_sync_rings(struct r
 			continue;
 		}
 
-		radeon_ring_commit(rdev, &rdev->ring[i]);
+		radeon_ring_commit(rdev, &rdev->ring[i], false);
 		radeon_fence_note_sync(fence, ring);
 
 		semaphore->gpu_addr += 8;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_test.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_test.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_test.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_test.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,13 +56,7 @@ static void radeon_do_test_moves(struct
 	/* Number of tests =
 	 * (Total GTT - IB pool - writeback page - ring buffers) / test size
 	 */
-	n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024;
-	for (i = 0; i < RADEON_NUM_RINGS; ++i)
-		n -= rdev->ring[i].ring_size;
-	if (rdev->wb.wb_obj)
-		n -= RADEON_GPU_PAGE_SIZE;
-	if (rdev->ih.ring_obj)
-		n -= rdev->ih.ring_size;
+	n = rdev->mc.gtt_size - rdev->gart_pin_size;
 	n /= size;
 
 	gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
@@ -73,7 +67,7 @@ static void radeon_do_test_moves(struct
 	}
 
 	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-			     NULL, &vram_obj);
+			     0, NULL, &vram_obj);
 	if (r) {
 		DRM_ERROR("Failed to create VRAM object\n");
 		goto out_cleanup;
@@ -93,7 +87,7 @@ static void radeon_do_test_moves(struct
 		struct radeon_fence *fence = NULL;
 
 		r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i);
+				     RADEON_GEM_DOMAIN_GTT, 0, NULL, gtt_obj + i);
 		if (r) {
 			DRM_ERROR("Failed to create GTT object %d\n", i);
 			goto out_lclean;
@@ -294,7 +288,7 @@ static int radeon_test_create_and_emit_f
 			return r;
 		}
 		radeon_fence_emit(rdev, fence, ring->idx);
-		radeon_ring_unlock_commit(rdev, ring);
+		radeon_ring_unlock_commit(rdev, ring, false);
 	}
 	return 0;
 }
@@ -319,7 +313,7 @@ void radeon_test_ring_sync(struct radeon
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringA);
+	radeon_ring_unlock_commit(rdev, ringA, false);
 
 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1);
 	if (r)
@@ -331,7 +325,7 @@ void radeon_test_ring_sync(struct radeon
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringA);
+	radeon_ring_unlock_commit(rdev, ringA, false);
 
 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2);
 	if (r)
@@ -350,7 +344,7 @@ void radeon_test_ring_sync(struct radeon
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringB);
+	radeon_ring_unlock_commit(rdev, ringB, false);
 
 	r = radeon_fence_wait(fence1, false);
 	if (r) {
@@ -371,7 +365,7 @@ void radeon_test_ring_sync(struct radeon
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringB);
+	radeon_ring_unlock_commit(rdev, ringB, false);
 
 	r = radeon_fence_wait(fence2, false);
 	if (r) {
@@ -414,7 +408,7 @@ static void radeon_test_ring_sync2(struc
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringA);
+	radeon_ring_unlock_commit(rdev, ringA, false);
 
 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA);
 	if (r)
@@ -426,7 +420,7 @@ static void radeon_test_ring_sync2(struc
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringB);
+	radeon_ring_unlock_commit(rdev, ringB, false);
 	r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB);
 	if (r)
 		goto out_cleanup;
@@ -448,7 +442,7 @@ static void radeon_test_ring_sync2(struc
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringC);
+	radeon_ring_unlock_commit(rdev, ringC, false);
 
 	for (i = 0; i < 30; ++i) {
 		mdelay(100);
@@ -474,7 +468,7 @@ static void radeon_test_ring_sync2(struc
 		goto out_cleanup;
 	}
 	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
-	radeon_ring_unlock_commit(rdev, ringC);
+	radeon_ring_unlock_commit(rdev, ringC, false);
 
 	mdelay(1000);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_trace.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_trace.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_trace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_trace.h	2014-09-28 17:29:07.000000000 -0400
@@ -72,8 +72,8 @@ TRACE_EVENT(radeon_vm_bo_update,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->soffset = bo_va->soffset;
-			   __entry->eoffset = bo_va->eoffset;
+			   __entry->soffset = bo_va->it.start;
+			   __entry->eoffset = bo_va->it.last + 1;
 			   __entry->flags = bo_va->flags;
 			   ),
 	    TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
@@ -104,6 +104,24 @@ TRACE_EVENT(radeon_vm_set_page,
 		      __entry->flags, __entry->count)
 );
 
+TRACE_EVENT(radeon_vm_flush,
+	    TP_PROTO(uint64_t pd_addr, unsigned ring, unsigned id),
+	    TP_ARGS(pd_addr, ring, id),
+	    TP_STRUCT__entry(
+			     __field(u64, pd_addr)
+			     __field(u32, ring)
+			     __field(u32, id)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->pd_addr = pd_addr;
+			   __entry->ring = ring;
+			   __entry->id = id;
+			   ),
+	    TP_printk("pd_addr=%010Lx, ring=%u, id=%u",
+		      __entry->pd_addr, __entry->ring, __entry->id)
+);
+
 DECLARE_EVENT_CLASS(radeon_fence_request,
 
 	    TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2014-09-28 17:29:07.000000000 -0400
@@ -521,6 +521,8 @@ static int radeon_ttm_backend_bind(struc
 				   struct ttm_mem_reg *bo_mem)
 {
 	struct radeon_ttm_tt *gtt = (void*)ttm;
+	uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ |
+		RADEON_GART_PAGE_WRITE;
 	int r;
 
 	gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT);
@@ -528,8 +530,10 @@ static int radeon_ttm_backend_bind(struc
 		WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
 		     ttm->num_pages, bo_mem, ttm);
 	}
-	r = radeon_gart_bind(gtt->rdev, gtt->offset,
-			     ttm->num_pages, ttm->pages, gtt->ttm.dma_address);
+	if (ttm->caching_state == tt_cached)
+		flags |= RADEON_GART_PAGE_SNOOP;
+	r = radeon_gart_bind(gtt->rdev, gtt->offset, ttm->num_pages,
+			     ttm->pages, gtt->ttm.dma_address, flags);
 	if (r) {
 		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
 			  ttm->num_pages, (unsigned)gtt->offset);
@@ -726,7 +730,7 @@ int radeon_ttm_init(struct radeon_device
 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 
 	r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_VRAM,
+			     RADEON_GEM_DOMAIN_VRAM, 0,
 			     NULL, &rdev->stollen_vga_memory);
 	if (r) {
 		return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ucode.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ucode.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ucode.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ucode.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 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.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_ucode.h"
+
+static void radeon_ucode_print_common_hdr(const struct common_firmware_header *hdr)
+{
+	DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes));
+	DRM_DEBUG("header_size_bytes: %u\n", le32_to_cpu(hdr->header_size_bytes));
+	DRM_DEBUG("header_version_major: %u\n", le16_to_cpu(hdr->header_version_major));
+	DRM_DEBUG("header_version_minor: %u\n", le16_to_cpu(hdr->header_version_minor));
+	DRM_DEBUG("ip_version_major: %u\n", le16_to_cpu(hdr->ip_version_major));
+	DRM_DEBUG("ip_version_minor: %u\n", le16_to_cpu(hdr->ip_version_minor));
+	DRM_DEBUG("ucode_version: 0x%08x\n", le32_to_cpu(hdr->ucode_version));
+	DRM_DEBUG("ucode_size_bytes: %u\n", le32_to_cpu(hdr->ucode_size_bytes));
+	DRM_DEBUG("ucode_array_offset_bytes: %u\n",
+		  le32_to_cpu(hdr->ucode_array_offset_bytes));
+	DRM_DEBUG("crc32: 0x%08x\n", le32_to_cpu(hdr->crc32));
+}
+
+void radeon_ucode_print_mc_hdr(const struct common_firmware_header *hdr)
+{
+	uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+	uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+	DRM_DEBUG("MC\n");
+	radeon_ucode_print_common_hdr(hdr);
+
+	if (version_major == 1) {
+		const struct mc_firmware_header_v1_0 *mc_hdr =
+			container_of(hdr, struct mc_firmware_header_v1_0, header);
+
+		DRM_DEBUG("io_debug_size_bytes: %u\n",
+			  le32_to_cpu(mc_hdr->io_debug_size_bytes));
+		DRM_DEBUG("io_debug_array_offset_bytes: %u\n",
+			  le32_to_cpu(mc_hdr->io_debug_array_offset_bytes));
+	} else {
+		DRM_ERROR("Unknown MC ucode version: %u.%u\n", version_major, version_minor);
+	}
+}
+
+void radeon_ucode_print_smc_hdr(const struct common_firmware_header *hdr)
+{
+	uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+	uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+	DRM_DEBUG("SMC\n");
+	radeon_ucode_print_common_hdr(hdr);
+
+	if (version_major == 1) {
+		const struct smc_firmware_header_v1_0 *smc_hdr =
+			container_of(hdr, struct smc_firmware_header_v1_0, header);
+
+		DRM_DEBUG("ucode_start_addr: %u\n", le32_to_cpu(smc_hdr->ucode_start_addr));
+	} else {
+		DRM_ERROR("Unknown SMC ucode version: %u.%u\n", version_major, version_minor);
+	}
+}
+
+void radeon_ucode_print_gfx_hdr(const struct common_firmware_header *hdr)
+{
+	uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+	uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+	DRM_DEBUG("GFX\n");
+	radeon_ucode_print_common_hdr(hdr);
+
+	if (version_major == 1) {
+		const struct gfx_firmware_header_v1_0 *gfx_hdr =
+			container_of(hdr, struct gfx_firmware_header_v1_0, header);
+
+		DRM_DEBUG("ucode_feature_version: %u\n",
+			  le32_to_cpu(gfx_hdr->ucode_feature_version));
+		DRM_DEBUG("jt_offset: %u\n", le32_to_cpu(gfx_hdr->jt_offset));
+		DRM_DEBUG("jt_size: %u\n", le32_to_cpu(gfx_hdr->jt_size));
+	} else {
+		DRM_ERROR("Unknown GFX ucode version: %u.%u\n", version_major, version_minor);
+	}
+}
+
+void radeon_ucode_print_rlc_hdr(const struct common_firmware_header *hdr)
+{
+	uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+	uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+	DRM_DEBUG("RLC\n");
+	radeon_ucode_print_common_hdr(hdr);
+
+	if (version_major == 1) {
+		const struct rlc_firmware_header_v1_0 *rlc_hdr =
+			container_of(hdr, struct rlc_firmware_header_v1_0, header);
+
+		DRM_DEBUG("ucode_feature_version: %u\n",
+			  le32_to_cpu(rlc_hdr->ucode_feature_version));
+		DRM_DEBUG("save_and_restore_offset: %u\n",
+			  le32_to_cpu(rlc_hdr->save_and_restore_offset));
+		DRM_DEBUG("clear_state_descriptor_offset: %u\n",
+			  le32_to_cpu(rlc_hdr->clear_state_descriptor_offset));
+		DRM_DEBUG("avail_scratch_ram_locations: %u\n",
+			  le32_to_cpu(rlc_hdr->avail_scratch_ram_locations));
+		DRM_DEBUG("master_pkt_description_offset: %u\n",
+			  le32_to_cpu(rlc_hdr->master_pkt_description_offset));
+	} else {
+		DRM_ERROR("Unknown RLC ucode version: %u.%u\n", version_major, version_minor);
+	}
+}
+
+void radeon_ucode_print_sdma_hdr(const struct common_firmware_header *hdr)
+{
+	uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+	uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+	DRM_DEBUG("SDMA\n");
+	radeon_ucode_print_common_hdr(hdr);
+
+	if (version_major == 1) {
+		const struct sdma_firmware_header_v1_0 *sdma_hdr =
+			container_of(hdr, struct sdma_firmware_header_v1_0, header);
+
+		DRM_DEBUG("ucode_feature_version: %u\n",
+			  le32_to_cpu(sdma_hdr->ucode_feature_version));
+		DRM_DEBUG("ucode_change_version: %u\n",
+			  le32_to_cpu(sdma_hdr->ucode_change_version));
+		DRM_DEBUG("jt_offset: %u\n", le32_to_cpu(sdma_hdr->jt_offset));
+		DRM_DEBUG("jt_size: %u\n", le32_to_cpu(sdma_hdr->jt_size));
+	} else {
+		DRM_ERROR("Unknown SDMA ucode version: %u.%u\n",
+			  version_major, version_minor);
+	}
+}
+
+int radeon_ucode_validate(const struct firmware *fw)
+{
+	const struct common_firmware_header *hdr =
+		(const struct common_firmware_header *)fw->data;
+
+	if (fw->size == le32_to_cpu(hdr->size_bytes))
+		return 0;
+
+	return -EINVAL;
+}
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ucode.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ucode.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_ucode.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_ucode.h	2014-09-28 17:29:07.000000000 -0400
@@ -153,4 +153,75 @@
 #define HAWAII_SMC_UCODE_START       0x20000
 #define HAWAII_SMC_UCODE_SIZE        0x1FDEC
 
+struct common_firmware_header {
+	uint32_t size_bytes; /* size of the entire header+image(s) in bytes */
+	uint32_t header_size_bytes; /* size of just the header in bytes */
+	uint16_t header_version_major; /* header version */
+	uint16_t header_version_minor; /* header version */
+	uint16_t ip_version_major; /* IP version */
+	uint16_t ip_version_minor; /* IP version */
+	uint32_t ucode_version;
+	uint32_t ucode_size_bytes; /* size of ucode in bytes */
+	uint32_t ucode_array_offset_bytes; /* payload offset from the start of the header */
+	uint32_t crc32;  /* crc32 checksum of the payload */
+};
+
+/* version_major=1, version_minor=0 */
+struct mc_firmware_header_v1_0 {
+	struct common_firmware_header header;
+	uint32_t io_debug_size_bytes; /* size of debug array in dwords */
+	uint32_t io_debug_array_offset_bytes; /* payload offset from the start of the header */
+};
+
+/* version_major=1, version_minor=0 */
+struct smc_firmware_header_v1_0 {
+	struct common_firmware_header header;
+	uint32_t ucode_start_addr;
+};
+
+/* version_major=1, version_minor=0 */
+struct gfx_firmware_header_v1_0 {
+	struct common_firmware_header header;
+	uint32_t ucode_feature_version;
+	uint32_t jt_offset; /* jt location */
+	uint32_t jt_size;  /* size of jt */
+};
+
+/* version_major=1, version_minor=0 */
+struct rlc_firmware_header_v1_0 {
+	struct common_firmware_header header;
+	uint32_t ucode_feature_version;
+	uint32_t save_and_restore_offset;
+	uint32_t clear_state_descriptor_offset;
+	uint32_t avail_scratch_ram_locations;
+	uint32_t master_pkt_description_offset;
+};
+
+/* version_major=1, version_minor=0 */
+struct sdma_firmware_header_v1_0 {
+	struct common_firmware_header header;
+	uint32_t ucode_feature_version;
+	uint32_t ucode_change_version;
+	uint32_t jt_offset; /* jt location */
+	uint32_t jt_size; /* size of jt */
+};
+
+/* header is fixed size */
+union radeon_firmware_header {
+	struct common_firmware_header common;
+	struct mc_firmware_header_v1_0 mc;
+	struct smc_firmware_header_v1_0 smc;
+	struct gfx_firmware_header_v1_0 gfx;
+	struct rlc_firmware_header_v1_0 rlc;
+	struct sdma_firmware_header_v1_0 sdma;
+	uint8_t raw[0x100];
+};
+
+void radeon_ucode_print_mc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_smc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_gfx_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
+int radeon_ucode_validate(const struct firmware *fw);
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_uvd.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_uvd.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2014-08-07 04:46:39.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2014-09-28 21:27:18.000000000 -0400
@@ -113,7 +113,7 @@ int radeon_uvd_init(struct radeon_device
 	bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
 		  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
 	r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
+			     RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->uvd.vcpu_bo);
 	if (r) {
 		dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r);
 		return r;
@@ -642,7 +642,7 @@ static int radeon_uvd_send_msg(struct ra
 		ib.ptr[i] = PACKET2(0);
 	ib.length_dw = 16;
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r)
 		goto err;
 	ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence);
@@ -670,7 +670,7 @@ int radeon_uvd_get_create_msg(struct rad
 	int r, i;
 
 	r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
+			     RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
 	if (r)
 		return r;
 
@@ -716,7 +716,7 @@ int radeon_uvd_get_destroy_msg(struct ra
 	int r, i;
 
 	r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
+			     RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
 	if (r)
 		return r;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_vce.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_vce.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_vce.c	2014-08-07 04:46:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_vce.c	2014-09-28 21:27:21.000000000 -0400
@@ -126,7 +126,7 @@ int radeon_vce_init(struct radeon_device
 	size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
 	       RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
 	r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
+			     RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->vce.vcpu_bo);
 	if (r) {
 		dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
 		return r;
@@ -368,7 +368,7 @@ int radeon_vce_get_create_msg(struct rad
 	for (i = ib.length_dw; i < ib_size_dw; ++i)
 		ib.ptr[i] = 0x0;
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 	        DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
 	}
@@ -425,7 +425,7 @@ int radeon_vce_get_destroy_msg(struct ra
 	for (i = ib.length_dw; i < ib_size_dw; ++i)
 		ib.ptr[i] = 0x0;
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 	        DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
 	}
@@ -715,7 +715,7 @@ int radeon_vce_ring_test(struct radeon_d
 		return r;
 	}
 	radeon_ring_write(ring, VCE_CMD_END);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 	        if (vce_v1_0_get_rptr(rdev, ring) != rptr)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_vm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_vm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/radeon_vm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/radeon_vm.c	2014-09-28 17:29:07.000000000 -0400
@@ -238,8 +238,8 @@ void radeon_vm_flush(struct radeon_devic
 	uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory);
 
 	/* if we can't remember our last VM flush then flush now! */
-	/* XXX figure out why we have to flush all the time */
-	if (!vm->last_flush || true || pd_addr != vm->pd_gpu_addr) {
+	if (!vm->last_flush || pd_addr != vm->pd_gpu_addr) {
+		trace_radeon_vm_flush(pd_addr, ring, vm->id);
 		vm->pd_gpu_addr = pd_addr;
 		radeon_ring_vm_flush(rdev, ring, vm);
 	}
@@ -325,17 +325,15 @@ struct radeon_bo_va *radeon_vm_bo_add(st
 	}
 	bo_va->vm = vm;
 	bo_va->bo = bo;
-	bo_va->soffset = 0;
-	bo_va->eoffset = 0;
+	bo_va->it.start = 0;
+	bo_va->it.last = 0;
 	bo_va->flags = 0;
-	bo_va->valid = false;
+	bo_va->addr = 0;
 	bo_va->ref_count = 1;
 	INIT_LIST_HEAD(&bo_va->bo_list);
-	INIT_LIST_HEAD(&bo_va->vm_list);
 	INIT_LIST_HEAD(&bo_va->vm_status);
 
 	mutex_lock(&vm->mutex);
-	list_add(&bo_va->vm_list, &vm->va);
 	list_add_tail(&bo_va->bo_list, &bo->va);
 	mutex_unlock(&vm->mutex);
 
@@ -343,6 +341,42 @@ struct radeon_bo_va *radeon_vm_bo_add(st
 }
 
 /**
+ * radeon_vm_set_pages - helper to call the right asic function
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: hw access flags
+ *
+ * Traces the parameters and calls the right asic functions
+ * to setup the page table using the DMA.
+ */
+static void radeon_vm_set_pages(struct radeon_device *rdev,
+				struct radeon_ib *ib,
+				uint64_t pe,
+				uint64_t addr, unsigned count,
+				uint32_t incr, uint32_t flags)
+{
+	trace_radeon_vm_set_page(pe, addr, count, incr, flags);
+
+	if ((flags & R600_PTE_GART_MASK) == R600_PTE_GART_MASK) {
+		uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
+		radeon_asic_vm_copy_pages(rdev, ib, pe, src, count);
+
+	} else if ((flags & R600_PTE_SYSTEM) || (count < 3)) {
+		radeon_asic_vm_write_pages(rdev, ib, pe, addr,
+					   count, incr, flags);
+
+	} else {
+		radeon_asic_vm_set_pages(rdev, ib, pe, addr,
+					 count, incr, flags);
+	}
+}
+
+/**
  * radeon_vm_clear_bo - initially clear the page dir/table
  *
  * @rdev: radeon_device pointer
@@ -376,16 +410,17 @@ static int radeon_vm_clear_bo(struct rad
 	addr = radeon_bo_gpu_offset(bo);
 	entries = radeon_bo_size(bo) / 8;
 
-	r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib,
-			  NULL, entries * 2 + 64);
+	r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, 256);
 	if (r)
                 goto error;
 
 	ib.length_dw = 0;
 
-	radeon_asic_vm_set_page(rdev, &ib, addr, 0, entries, 0, 0);
+	radeon_vm_set_pages(rdev, &ib, addr, 0, entries, 0, 0);
+	radeon_asic_vm_pad_ib(rdev, &ib);
+	WARN_ON(ib.length_dw > 64);
 
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r)
                 goto error;
 
@@ -419,11 +454,9 @@ int radeon_vm_bo_set_addr(struct radeon_
 			  uint32_t flags)
 {
 	uint64_t size = radeon_bo_size(bo_va->bo);
-	uint64_t eoffset, last_offset = 0;
 	struct radeon_vm *vm = bo_va->vm;
-	struct radeon_bo_va *tmp;
-	struct list_head *head;
 	unsigned last_pfn, pt_idx;
+	uint64_t eoffset;
 	int r;
 
 	if (soffset) {
@@ -445,51 +478,53 @@ int radeon_vm_bo_set_addr(struct radeon_
 	}
 
 	mutex_lock(&vm->mutex);
-	head = &vm->va;
-	last_offset = 0;
-	list_for_each_entry(tmp, &vm->va, vm_list) {
-		if (bo_va == tmp) {
-			/* skip over currently modified bo */
-			continue;
+	if (bo_va->it.start || bo_va->it.last) {
+		if (bo_va->addr) {
+			/* add a clone of the bo_va to clear the old address */
+			struct radeon_bo_va *tmp;
+			tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
+			if (!tmp) {
+				mutex_unlock(&vm->mutex);
+				return -ENOMEM;
+			}
+			tmp->it.start = bo_va->it.start;
+			tmp->it.last = bo_va->it.last;
+			tmp->vm = vm;
+			tmp->addr = bo_va->addr;
+			tmp->bo = radeon_bo_ref(bo_va->bo);
+			list_add(&tmp->vm_status, &vm->freed);
 		}
 
-		if (soffset >= last_offset && eoffset <= tmp->soffset) {
-			/* bo can be added before this one */
-			break;
-		}
-		if (eoffset > tmp->soffset && soffset < tmp->eoffset) {
-			/* bo and tmp overlap, invalid offset */
-			dev_err(rdev->dev, "bo %p va 0x%08X conflict with (bo %p 0x%08X 0x%08X)\n",
-				bo_va->bo, (unsigned)bo_va->soffset, tmp->bo,
-				(unsigned)tmp->soffset, (unsigned)tmp->eoffset);
-			mutex_unlock(&vm->mutex);
-			return -EINVAL;
-		}
-		last_offset = tmp->eoffset;
-		head = &tmp->vm_list;
+		interval_tree_remove(&bo_va->it, &vm->va);
+		bo_va->it.start = 0;
+		bo_va->it.last = 0;
 	}
 
-	if (bo_va->soffset) {
-		/* add a clone of the bo_va to clear the old address */
-		tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
-		if (!tmp) {
+	soffset /= RADEON_GPU_PAGE_SIZE;
+	eoffset /= RADEON_GPU_PAGE_SIZE;
+	if (soffset || eoffset) {
+		struct interval_tree_node *it;
+		it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
+		if (it) {
+			struct radeon_bo_va *tmp;
+			tmp = container_of(it, struct radeon_bo_va, it);
+			/* bo and tmp overlap, invalid offset */
+			dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
+				"(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
+				soffset, tmp->bo, tmp->it.start, tmp->it.last);
 			mutex_unlock(&vm->mutex);
-			return -ENOMEM;
+			return -EINVAL;
 		}
-		tmp->soffset = bo_va->soffset;
-		tmp->eoffset = bo_va->eoffset;
-		tmp->vm = vm;
-		list_add(&tmp->vm_status, &vm->freed);
+		bo_va->it.start = soffset;
+		bo_va->it.last = eoffset - 1;
+		interval_tree_insert(&bo_va->it, &vm->va);
 	}
 
-	bo_va->soffset = soffset;
-	bo_va->eoffset = eoffset;
 	bo_va->flags = flags;
-	bo_va->valid = false;
-	list_move(&bo_va->vm_list, head);
+	bo_va->addr = 0;
 
-	soffset = (soffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size;
-	eoffset = (eoffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size;
+	soffset >>= radeon_vm_block_size;
+	eoffset >>= radeon_vm_block_size;
 
 	BUG_ON(eoffset >= radeon_vm_num_pdes(rdev));
 
@@ -510,7 +545,7 @@ int radeon_vm_bo_set_addr(struct radeon_
 
 		r = radeon_bo_create(rdev, RADEON_VM_PTE_COUNT * 8,
 				     RADEON_GPU_PAGE_SIZE, true,
-				     RADEON_GEM_DOMAIN_VRAM, NULL, &pt);
+				     RADEON_GEM_DOMAIN_VRAM, 0, NULL, &pt);
 		if (r)
 			return r;
 
@@ -611,7 +646,7 @@ int radeon_vm_update_page_directory(stru
 	ndw = 64;
 
 	/* assume the worst case */
-	ndw += vm->max_pde_used * 16;
+	ndw += vm->max_pde_used * 6;
 
 	/* update too big for an IB */
 	if (ndw > 0xfffff)
@@ -640,9 +675,9 @@ int radeon_vm_update_page_directory(stru
 		    ((last_pt + incr * count) != pt)) {
 
 			if (count) {
-				radeon_asic_vm_set_page(rdev, &ib, last_pde,
-							last_pt, count, incr,
-							R600_PTE_VALID);
+				radeon_vm_set_pages(rdev, &ib, last_pde,
+						    last_pt, count, incr,
+						    R600_PTE_VALID);
 			}
 
 			count = 1;
@@ -654,13 +689,15 @@ int radeon_vm_update_page_directory(stru
 	}
 
 	if (count)
-		radeon_asic_vm_set_page(rdev, &ib, last_pde, last_pt, count,
-					incr, R600_PTE_VALID);
+		radeon_vm_set_pages(rdev, &ib, last_pde, last_pt, count,
+				    incr, R600_PTE_VALID);
 
 	if (ib.length_dw != 0) {
+		radeon_asic_vm_pad_ib(rdev, &ib);
 		radeon_semaphore_sync_to(ib.semaphore, pd->tbo.sync_obj);
 		radeon_semaphore_sync_to(ib.semaphore, vm->last_id_use);
-		r = radeon_ib_schedule(rdev, &ib, NULL);
+		WARN_ON(ib.length_dw > ndw);
+		r = radeon_ib_schedule(rdev, &ib, NULL, false);
 		if (r) {
 			radeon_ib_free(rdev, &ib);
 			return r;
@@ -725,30 +762,30 @@ static void radeon_vm_frag_ptes(struct r
 	    (frag_start >= frag_end)) {
 
 		count = (pe_end - pe_start) / 8;
-		radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
-					RADEON_GPU_PAGE_SIZE, flags);
+		radeon_vm_set_pages(rdev, ib, pe_start, addr, count,
+				    RADEON_GPU_PAGE_SIZE, flags);
 		return;
 	}
 
 	/* handle the 4K area at the beginning */
 	if (pe_start != frag_start) {
 		count = (frag_start - pe_start) / 8;
-		radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
-					RADEON_GPU_PAGE_SIZE, flags);
+		radeon_vm_set_pages(rdev, ib, pe_start, addr, count,
+				    RADEON_GPU_PAGE_SIZE, flags);
 		addr += RADEON_GPU_PAGE_SIZE * count;
 	}
 
 	/* handle the area in the middle */
 	count = (frag_end - frag_start) / 8;
-	radeon_asic_vm_set_page(rdev, ib, frag_start, addr, count,
-				RADEON_GPU_PAGE_SIZE, flags | frag_flags);
+	radeon_vm_set_pages(rdev, ib, frag_start, addr, count,
+			    RADEON_GPU_PAGE_SIZE, flags | frag_flags);
 
 	/* handle the 4K area at the end */
 	if (frag_end != pe_end) {
 		addr += RADEON_GPU_PAGE_SIZE * count;
 		count = (pe_end - frag_end) / 8;
-		radeon_asic_vm_set_page(rdev, ib, frag_end, addr, count,
-					RADEON_GPU_PAGE_SIZE, flags);
+		radeon_vm_set_pages(rdev, ib, frag_end, addr, count,
+				    RADEON_GPU_PAGE_SIZE, flags);
 	}
 }
 
@@ -777,9 +814,6 @@ static void radeon_vm_update_ptes(struct
 	unsigned count = 0;
 	uint64_t addr;
 
-	start = start / RADEON_GPU_PAGE_SIZE;
-	end = end / RADEON_GPU_PAGE_SIZE;
-
 	/* walk over the address space and update the page tables */
 	for (addr = start; addr < end; ) {
 		uint64_t pt_idx = addr >> radeon_vm_block_size;
@@ -842,55 +876,73 @@ int radeon_vm_bo_update(struct radeon_de
 {
 	struct radeon_vm *vm = bo_va->vm;
 	struct radeon_ib ib;
-	unsigned nptes, ndw;
+	unsigned nptes, ncmds, ndw;
 	uint64_t addr;
+	uint32_t flags;
 	int r;
 
-
-	if (!bo_va->soffset) {
+	if (!bo_va->it.start) {
 		dev_err(rdev->dev, "bo %p don't has a mapping in vm %p\n",
 			bo_va->bo, vm);
 		return -EINVAL;
 	}
 
-	if ((bo_va->valid && mem) || (!bo_va->valid && mem == NULL))
-		return 0;
+	list_del_init(&bo_va->vm_status);
 
 	bo_va->flags &= ~RADEON_VM_PAGE_VALID;
 	bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM;
+	bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED;
 	if (mem) {
 		addr = mem->start << PAGE_SHIFT;
 		if (mem->mem_type != TTM_PL_SYSTEM) {
 			bo_va->flags |= RADEON_VM_PAGE_VALID;
-			bo_va->valid = true;
 		}
 		if (mem->mem_type == TTM_PL_TT) {
 			bo_va->flags |= RADEON_VM_PAGE_SYSTEM;
+			if (!(bo_va->bo->flags & (RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC)))
+				bo_va->flags |= RADEON_VM_PAGE_SNOOPED;
+
 		} else {
 			addr += rdev->vm_manager.vram_base_offset;
 		}
 	} else {
 		addr = 0;
-		bo_va->valid = false;
 	}
 
+	if (addr == bo_va->addr)
+		return 0;
+	bo_va->addr = addr;
+
 	trace_radeon_vm_bo_update(bo_va);
 
-	nptes = (bo_va->eoffset - bo_va->soffset) / RADEON_GPU_PAGE_SIZE;
+	nptes = bo_va->it.last - bo_va->it.start + 1;
+
+	/* reserve space for one command every (1 << BLOCK_SIZE) entries
+	   or 2k dwords (whatever is smaller) */
+	ncmds = (nptes >> min(radeon_vm_block_size, 11)) + 1;
 
 	/* padding, etc. */
 	ndw = 64;
 
-	if (radeon_vm_block_size > 11)
-		/* reserve space for one header for every 2k dwords */
-		ndw += (nptes >> 11) * 4;
-	else
-		/* reserve space for one header for
-		    every (1 << BLOCK_SIZE) entries */
-		ndw += (nptes >> radeon_vm_block_size) * 4;
+	flags = radeon_vm_page_flags(bo_va->flags);
+	if ((flags & R600_PTE_GART_MASK) == R600_PTE_GART_MASK) {
+		/* only copy commands needed */
+		ndw += ncmds * 7;
 
-	/* reserve space for pte addresses */
-	ndw += nptes * 2;
+	} else if (flags & R600_PTE_SYSTEM) {
+		/* header for write data commands */
+		ndw += ncmds * 4;
+
+		/* body of write data command */
+		ndw += nptes * 2;
+
+	} else {
+		/* set page commands needed */
+		ndw += ncmds * 10;
+
+		/* two extra commands for begin/end of fragment */
+		ndw += 2 * 10;
+	}
 
 	/* update too big for an IB */
 	if (ndw > 0xfffff)
@@ -901,11 +953,15 @@ int radeon_vm_bo_update(struct radeon_de
 		return r;
 	ib.length_dw = 0;
 
-	radeon_vm_update_ptes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset,
-			      addr, radeon_vm_page_flags(bo_va->flags));
+	radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start,
+			      bo_va->it.last + 1, addr,
+			      radeon_vm_page_flags(bo_va->flags));
+
+	radeon_asic_vm_pad_ib(rdev, &ib);
+	WARN_ON(ib.length_dw > ndw);
 
 	radeon_semaphore_sync_to(ib.semaphore, vm->fence);
-	r = radeon_ib_schedule(rdev, &ib, NULL);
+	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
 		radeon_ib_free(rdev, &ib);
 		return r;
@@ -936,8 +992,8 @@ int radeon_vm_clear_freed(struct radeon_
 	int r;
 
 	list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) {
-		list_del(&bo_va->vm_status);
 		r = radeon_vm_bo_update(rdev, bo_va, NULL);
+		radeon_bo_unref(&bo_va->bo);
 		kfree(bo_va);
 		if (r)
 			return r;
@@ -947,6 +1003,31 @@ int radeon_vm_clear_freed(struct radeon_
 }
 
 /**
+ * radeon_vm_clear_invalids - clear invalidated BOs in the PT
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ *
+ * Make sure all invalidated BOs are cleared in the PT.
+ * Returns 0 for success.
+ *
+ * PTs have to be reserved and mutex must be locked!
+ */
+int radeon_vm_clear_invalids(struct radeon_device *rdev,
+			     struct radeon_vm *vm)
+{
+	struct radeon_bo_va *bo_va, *tmp;
+	int r;
+
+	list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, vm_status) {
+		r = radeon_vm_bo_update(rdev, bo_va, NULL);
+		if (r)
+			return r;
+	}
+	return 0;
+}
+
+/**
  * radeon_vm_bo_rmv - remove a bo to a specific vm
  *
  * @rdev: radeon_device pointer
@@ -964,10 +1045,11 @@ void radeon_vm_bo_rmv(struct radeon_devi
 	list_del(&bo_va->bo_list);
 
 	mutex_lock(&vm->mutex);
-	list_del(&bo_va->vm_list);
+	interval_tree_remove(&bo_va->it, &vm->va);
+	list_del(&bo_va->vm_status);
 
-	if (bo_va->soffset) {
-		bo_va->bo = NULL;
+	if (bo_va->addr) {
+		bo_va->bo = radeon_bo_ref(bo_va->bo);
 		list_add(&bo_va->vm_status, &vm->freed);
 	} else {
 		kfree(bo_va);
@@ -991,7 +1073,12 @@ void radeon_vm_bo_invalidate(struct rade
 	struct radeon_bo_va *bo_va;
 
 	list_for_each_entry(bo_va, &bo->va, bo_list) {
-		bo_va->valid = false;
+		if (bo_va->addr) {
+			mutex_lock(&bo_va->vm->mutex);
+			list_del(&bo_va->vm_status);
+			list_add(&bo_va->vm_status, &bo_va->vm->invalidated);
+			mutex_unlock(&bo_va->vm->mutex);
+		}
 	}
 }
 
@@ -1016,7 +1103,8 @@ int radeon_vm_init(struct radeon_device
 	vm->last_flush = NULL;
 	vm->last_id_use = NULL;
 	mutex_init(&vm->mutex);
-	INIT_LIST_HEAD(&vm->va);
+	vm->va = RB_ROOT;
+	INIT_LIST_HEAD(&vm->invalidated);
 	INIT_LIST_HEAD(&vm->freed);
 
 	pd_size = radeon_vm_directory_size(rdev);
@@ -1031,7 +1119,7 @@ int radeon_vm_init(struct radeon_device
 	}
 
 	r = radeon_bo_create(rdev, pd_size, align, true,
-			     RADEON_GEM_DOMAIN_VRAM, NULL,
+			     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
 			     &vm->page_directory);
 	if (r)
 		return r;
@@ -1060,11 +1148,11 @@ void radeon_vm_fini(struct radeon_device
 	struct radeon_bo_va *bo_va, *tmp;
 	int i, r;
 
-	if (!list_empty(&vm->va)) {
+	if (!RB_EMPTY_ROOT(&vm->va)) {
 		dev_err(rdev->dev, "still active bo inside vm\n");
 	}
-	list_for_each_entry_safe(bo_va, tmp, &vm->va, vm_list) {
-		list_del_init(&bo_va->vm_list);
+	rbtree_postorder_for_each_entry_safe(bo_va, tmp, &vm->va, it.rb) {
+		interval_tree_remove(&bo_va->it, &vm->va);
 		r = radeon_bo_reserve(bo_va->bo, false);
 		if (!r) {
 			list_del_init(&bo_va->bo_list);
@@ -1072,8 +1160,10 @@ void radeon_vm_fini(struct radeon_device
 			kfree(bo_va);
 		}
 	}
-	list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status)
+	list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) {
+		radeon_bo_unref(&bo_va->bo);
 		kfree(bo_va);
+	}
 
 	for (i = 0; i < radeon_vm_num_pdes(rdev); i++)
 		radeon_bo_unref(&vm->page_tables[i].bo);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rs400.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rs400.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rs400.c	2014-09-28 17:29:07.000000000 -0400
@@ -109,7 +109,6 @@ int rs400_gart_enable(struct radeon_devi
 	uint32_t size_reg;
 	uint32_t tmp;
 
-	radeon_gart_restore(rdev);
 	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
 	tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
 	WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
@@ -209,17 +208,24 @@ void rs400_gart_fini(struct radeon_devic
 	radeon_gart_table_ram_free(rdev);
 }
 
+#define RS400_PTE_UNSNOOPED (1 << 0)
 #define RS400_PTE_WRITEABLE (1 << 2)
 #define RS400_PTE_READABLE  (1 << 3)
 
-void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr)
+void rs400_gart_set_page(struct radeon_device *rdev, unsigned i,
+			 uint64_t addr, uint32_t flags)
 {
 	uint32_t entry;
 	u32 *gtt = rdev->gart.ptr;
 
 	entry = (lower_32_bits(addr) & PAGE_MASK) |
-		((upper_32_bits(addr) & 0xff) << 4) |
-		RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
+		((upper_32_bits(addr) & 0xff) << 4);
+	if (flags & RADEON_GART_PAGE_READ)
+		entry |= RS400_PTE_READABLE;
+	if (flags & RADEON_GART_PAGE_WRITE)
+		entry |= RS400_PTE_WRITEABLE;
+	if (!(flags & RADEON_GART_PAGE_SNOOP))
+		entry |= RS400_PTE_UNSNOOPED;
 	entry = cpu_to_le32(entry);
 	gtt[i] = entry;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rs600.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rs600.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rs600.c	2014-09-28 17:29:07.000000000 -0400
@@ -555,7 +555,6 @@ static int rs600_gart_enable(struct rade
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Enable bus master */
 	tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
 	WREG32(RADEON_BUS_CNTL, tmp);
@@ -626,15 +625,21 @@ static void rs600_gart_fini(struct radeo
 	radeon_gart_table_vram_free(rdev);
 }
 
-void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr)
+void rs600_gart_set_page(struct radeon_device *rdev, unsigned i,
+			 uint64_t addr, uint32_t flags)
 {
 	void __iomem *ptr = (void *)rdev->gart.ptr;
 
 	addr = addr & 0xFFFFFFFFFFFFF000ULL;
-	if (addr == rdev->dummy_page.addr)
-		addr |= R600_PTE_SYSTEM | R600_PTE_SNOOPED;
-	else
-		addr |= R600_PTE_GART;
+	addr |= R600_PTE_SYSTEM;
+	if (flags & RADEON_GART_PAGE_VALID)
+		addr |= R600_PTE_VALID;
+	if (flags & RADEON_GART_PAGE_READ)
+		addr |= R600_PTE_READABLE;
+	if (flags & RADEON_GART_PAGE_WRITE)
+		addr |= R600_PTE_WRITEABLE;
+	if (flags & RADEON_GART_PAGE_SNOOP)
+		addr |= R600_PTE_SNOOPED;
 	writeq(addr, ptr + (i * 8));
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv515.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv515.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv515.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv515.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,7 +124,7 @@ void rv515_ring_start(struct radeon_devi
 	radeon_ring_write(ring, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
 	radeon_ring_write(ring, PACKET0(0x20C8, 0));
 	radeon_ring_write(ring, 0);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 }
 
 int rv515_mc_wait_for_idle(struct radeon_device *rdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv770.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv770.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv770.c	2014-09-28 17:29:07.000000000 -0400
@@ -900,7 +900,6 @@ static int rv770_pcie_gart_enable(struct
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Setup L2 cache */
 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
 				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
@@ -1178,7 +1177,6 @@ static void rv770_gpu_init(struct radeon
 	u32 hdp_host_path_cntl;
 	u32 sq_dyn_gpr_size_simd_ab_0;
 	u32 gb_tiling_config = 0;
-	u32 cc_rb_backend_disable = 0;
 	u32 cc_gc_shader_pipe_config = 0;
 	u32 mc_arb_ramcfg;
 	u32 db_debug4, tmp;
@@ -1312,21 +1310,7 @@ static void rv770_gpu_init(struct radeon
 		WREG32(SPI_CONFIG_CNTL, 0);
 	}
 
-	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-	tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16);
-	if (tmp < rdev->config.rv770.max_backends) {
-		rdev->config.rv770.max_backends = tmp;
-	}
-
 	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
-	tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK);
-	if (tmp < rdev->config.rv770.max_pipes) {
-		rdev->config.rv770.max_pipes = tmp;
-	}
-	tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK);
-	if (tmp < rdev->config.rv770.max_simds) {
-		rdev->config.rv770.max_simds = tmp;
-	}
 	tmp = rdev->config.rv770.max_simds -
 		r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK);
 	rdev->config.rv770.active_simds = tmp;
@@ -1349,6 +1333,14 @@ static void rv770_gpu_init(struct radeon
 	rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
 
 	disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK;
+	tmp = 0;
+	for (i = 0; i < rdev->config.rv770.max_backends; i++)
+		tmp |= (1 << i);
+	/* if all the backends are disabled, fix it up here */
+	if ((disabled_rb_mask & tmp) == tmp) {
+		for (i = 0; i < rdev->config.rv770.max_backends; i++)
+			disabled_rb_mask &= ~(1 << i);
+	}
 	tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT;
 	tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends,
 					R7XX_MAX_BACKENDS, disabled_rb_mask);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv770_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv770_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/rv770_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/rv770_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,7 @@ int rv770_copy_dma(struct radeon_device
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si.c	2014-08-07 04:46:25.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si.c	2014-09-28 21:27:10.000000000 -0400
@@ -1436,38 +1436,54 @@ static const u32 hainan_io_mc_regs[TAHIT
 /* ucode loading */
 int si_mc_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
+	const __be32 *fw_data = NULL;
+	const __le32 *new_fw_data = NULL;
 	u32 running, blackout = 0;
-	u32 *io_mc_regs;
+	u32 *io_mc_regs = NULL;
+	const __le32 *new_io_mc_regs = NULL;
 	int i, regs_size, ucode_size;
 
 	if (!rdev->mc_fw)
 		return -EINVAL;
 
-	ucode_size = rdev->mc_fw->size / 4;
+	if (rdev->new_fw) {
+		const struct mc_firmware_header_v1_0 *hdr =
+			(const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
 
-	switch (rdev->family) {
-	case CHIP_TAHITI:
-		io_mc_regs = (u32 *)&tahiti_io_mc_regs;
-		regs_size = TAHITI_IO_MC_REGS_SIZE;
-		break;
-	case CHIP_PITCAIRN:
-		io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
-		regs_size = TAHITI_IO_MC_REGS_SIZE;
-		break;
-	case CHIP_VERDE:
-	default:
-		io_mc_regs = (u32 *)&verde_io_mc_regs;
-		regs_size = TAHITI_IO_MC_REGS_SIZE;
-		break;
-	case CHIP_OLAND:
-		io_mc_regs = (u32 *)&oland_io_mc_regs;
-		regs_size = TAHITI_IO_MC_REGS_SIZE;
-		break;
-	case CHIP_HAINAN:
-		io_mc_regs = (u32 *)&hainan_io_mc_regs;
-		regs_size = TAHITI_IO_MC_REGS_SIZE;
-		break;
+		radeon_ucode_print_mc_hdr(&hdr->header);
+		regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
+		new_io_mc_regs = (const __le32 *)
+			(rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
+		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+		new_fw_data = (const __le32 *)
+			(rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+	} else {
+		ucode_size = rdev->mc_fw->size / 4;
+
+		switch (rdev->family) {
+		case CHIP_TAHITI:
+			io_mc_regs = (u32 *)&tahiti_io_mc_regs;
+			regs_size = TAHITI_IO_MC_REGS_SIZE;
+			break;
+		case CHIP_PITCAIRN:
+			io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
+			regs_size = TAHITI_IO_MC_REGS_SIZE;
+			break;
+		case CHIP_VERDE:
+		default:
+			io_mc_regs = (u32 *)&verde_io_mc_regs;
+			regs_size = TAHITI_IO_MC_REGS_SIZE;
+			break;
+		case CHIP_OLAND:
+			io_mc_regs = (u32 *)&oland_io_mc_regs;
+			regs_size = TAHITI_IO_MC_REGS_SIZE;
+			break;
+		case CHIP_HAINAN:
+			io_mc_regs = (u32 *)&hainan_io_mc_regs;
+			regs_size = TAHITI_IO_MC_REGS_SIZE;
+			break;
+		}
+		fw_data = (const __be32 *)rdev->mc_fw->data;
 	}
 
 	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1484,13 +1500,21 @@ int si_mc_load_microcode(struct radeon_d
 
 		/* load mc io regs */
 		for (i = 0; i < regs_size; i++) {
-			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
-			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+			if (rdev->new_fw) {
+				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++));
+			} else {
+				WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
+				WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+			}
 		}
 		/* load the MC ucode */
-		fw_data = (const __be32 *)rdev->mc_fw->data;
-		for (i = 0; i < ucode_size; i++)
-			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+		for (i = 0; i < ucode_size; i++) {
+			if (rdev->new_fw)
+				WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+			else
+				WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+		}
 
 		/* put the engine back into the active state */
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
@@ -1519,18 +1543,19 @@ int si_mc_load_microcode(struct radeon_d
 static int si_init_microcode(struct radeon_device *rdev)
 {
 	const char *chip_name;
-	const char *rlc_chip_name;
+	const char *new_chip_name;
 	size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
 	size_t smc_req_size, mc2_req_size;
 	char fw_name[30];
 	int err;
+	int new_fw = 0;
 
 	DRM_DEBUG("\n");
 
 	switch (rdev->family) {
 	case CHIP_TAHITI:
 		chip_name = "TAHITI";
-		rlc_chip_name = "TAHITI";
+		new_chip_name = "tahiti";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1541,7 +1566,7 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_PITCAIRN:
 		chip_name = "PITCAIRN";
-		rlc_chip_name = "PITCAIRN";
+		new_chip_name = "pitcairn";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1552,7 +1577,7 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_VERDE:
 		chip_name = "VERDE";
-		rlc_chip_name = "VERDE";
+		new_chip_name = "verde";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1563,7 +1588,7 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_OLAND:
 		chip_name = "OLAND";
-		rlc_chip_name = "OLAND";
+		new_chip_name = "oland";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1573,7 +1598,7 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_HAINAN:
 		chip_name = "HAINAN";
-		rlc_chip_name = "HAINAN";
+		new_chip_name = "hainan";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1584,86 +1609,178 @@ static int si_init_microcode(struct rade
 	default: BUG();
 	}
 
-	DRM_INFO("Loading %s Microcode\n", chip_name);
+	DRM_INFO("Loading %s Microcode\n", new_chip_name);
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->pfp_fw->size != pfp_req_size) {
-		printk(KERN_ERR
-		       "si_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->pfp_fw->size, fw_name);
-		err = -EINVAL;
-		goto out;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->pfp_fw->size != pfp_req_size) {
+			printk(KERN_ERR
+			       "si_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->pfp_fw->size, fw_name);
+			err = -EINVAL;
+			goto out;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->pfp_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->me_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->me_fw->size != me_req_size) {
-		printk(KERN_ERR
-		       "si_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->me_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->me_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->me_fw->size != me_req_size) {
+			printk(KERN_ERR
+			       "si_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->me_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->me_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->ce_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->ce_fw->size != ce_req_size) {
-		printk(KERN_ERR
-		       "si_cp: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->ce_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->ce_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->ce_fw->size != ce_req_size) {
+			printk(KERN_ERR
+			       "si_cp: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->ce_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->ce_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", rlc_chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->rlc_fw->size != rlc_req_size) {
-		printk(KERN_ERR
-		       "si_rlc: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->rlc_fw->size, fw_name);
-		err = -EINVAL;
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+		if (rdev->rlc_fw->size != rlc_req_size) {
+			printk(KERN_ERR
+			       "si_rlc: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->rlc_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->rlc_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	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);
 		err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
-		if (err)
+		if (err) {
+			snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+			err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+			if (err)
+				goto out;
+		}
+		if ((rdev->mc_fw->size != mc_req_size) &&
+		    (rdev->mc_fw->size != mc2_req_size)) {
+			printk(KERN_ERR
+			       "si_mc: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->mc_fw->size, fw_name);
+			err = -EINVAL;
+		}
+		DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
+	} else {
+		err = radeon_ucode_validate(rdev->mc_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
 			goto out;
+		} else {
+			new_fw++;
+		}
 	}
-	if ((rdev->mc_fw->size != mc_req_size) &&
-	    (rdev->mc_fw->size != mc2_req_size)) {
-		printk(KERN_ERR
-		       "si_mc: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->mc_fw->size, fw_name);
-		err = -EINVAL;
-	}
-	DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->smc_fw, fw_name, rdev->dev);
 	if (err) {
-		printk(KERN_ERR
-		       "smc: error loading firmware \"%s\"\n",
-		       fw_name);
-		release_firmware(rdev->smc_fw);
-		rdev->smc_fw = NULL;
-		err = 0;
-	} else if (rdev->smc_fw->size != smc_req_size) {
-		printk(KERN_ERR
-		       "si_smc: Bogus length %zu in firmware \"%s\"\n",
-		       rdev->smc_fw->size, fw_name);
-		err = -EINVAL;
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+		err = reject_firmware(&rdev->smc_fw, fw_name, rdev->dev);
+		if (err) {
+			printk(KERN_ERR
+			       "smc: error loading firmware \"%s\"\n",
+			       fw_name);
+			release_firmware(rdev->smc_fw);
+			rdev->smc_fw = NULL;
+			err = 0;
+		} else if (rdev->smc_fw->size != smc_req_size) {
+			printk(KERN_ERR
+			       "si_smc: Bogus length %zu in firmware \"%s\"\n",
+			       rdev->smc_fw->size, fw_name);
+			err = -EINVAL;
+		}
+	} else {
+		err = radeon_ucode_validate(rdev->smc_fw);
+		if (err) {
+			printk(KERN_ERR
+			       "si_cp: validation failed for firmware \"%s\"\n",
+			       fw_name);
+			goto out;
+		} else {
+			new_fw++;
+		}
 	}
 
+	if (new_fw == 0) {
+		rdev->new_fw = false;
+	} else if (new_fw < 6) {
+		printk(KERN_ERR "si_fw: mixing new and old firmware!\n");
+		err = -EINVAL;
+	} else {
+		rdev->new_fw = true;
+	}
 out:
 	if (err) {
 		if (err != -EINVAL)
@@ -2867,7 +2984,7 @@ static void si_gpu_init(struct radeon_de
 	u32 sx_debug_1;
 	u32 hdp_host_path_cntl;
 	u32 tmp;
-	int i, j, k;
+	int i, j;
 
 	switch (rdev->family) {
 	case CHIP_TAHITI:
@@ -3065,12 +3182,11 @@ static void si_gpu_init(struct radeon_de
 		     rdev->config.si.max_sh_per_se,
 		     rdev->config.si.max_cu_per_sh);
 
+	rdev->config.si.active_cus = 0;
 	for (i = 0; i < rdev->config.si.max_shader_engines; i++) {
 		for (j = 0; j < rdev->config.si.max_sh_per_se; j++) {
-			for (k = 0; k < rdev->config.si.max_cu_per_sh; k++) {
-				rdev->config.si.active_cus +=
-					hweight32(si_get_cu_active_bitmap(rdev, i, j));
-			}
+			rdev->config.si.active_cus +=
+				hweight32(si_get_cu_active_bitmap(rdev, i, j));
 		}
 	}
 
@@ -3248,34 +3364,77 @@ static void si_cp_enable(struct radeon_d
 
 static int si_cp_load_microcode(struct radeon_device *rdev)
 {
-	const __be32 *fw_data;
 	int i;
 
-	if (!rdev->me_fw || !rdev->pfp_fw)
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
 		return -EINVAL;
 
 	si_cp_enable(rdev, false);
 
-	/* PFP */
-	fw_data = (const __be32 *)rdev->pfp_fw->data;
-	WREG32(CP_PFP_UCODE_ADDR, 0);
-	for (i = 0; i < SI_PFP_UCODE_SIZE; i++)
-		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_PFP_UCODE_ADDR, 0);
+	if (rdev->new_fw) {
+		const struct gfx_firmware_header_v1_0 *pfp_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+		const struct gfx_firmware_header_v1_0 *ce_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+		const struct gfx_firmware_header_v1_0 *me_hdr =
+			(const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+		const __le32 *fw_data;
+		u32 fw_size;
 
-	/* CE */
-	fw_data = (const __be32 *)rdev->ce_fw->data;
-	WREG32(CP_CE_UCODE_ADDR, 0);
-	for (i = 0; i < SI_CE_UCODE_SIZE; i++)
-		WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_CE_UCODE_ADDR, 0);
+		radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
+		radeon_ucode_print_gfx_hdr(&ce_hdr->header);
+		radeon_ucode_print_gfx_hdr(&me_hdr->header);
 
-	/* ME */
-	fw_data = (const __be32 *)rdev->me_fw->data;
-	WREG32(CP_ME_RAM_WADDR, 0);
-	for (i = 0; i < SI_PM4_UCODE_SIZE; i++)
-		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
-	WREG32(CP_ME_RAM_WADDR, 0);
+		/* PFP */
+		fw_data = (const __le32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+
+		/* CE */
+		fw_data = (const __le32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_CE_UCODE_ADDR, 0);
+
+		/* ME */
+		fw_data = (const __be32 *)
+			(rdev->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);
+		for (i = 0; i < fw_size; i++)
+			WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+		WREG32(CP_ME_RAM_WADDR, 0);
+	} else {
+		const __be32 *fw_data;
+
+		/* PFP */
+		fw_data = (const __be32 *)rdev->pfp_fw->data;
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+		for (i = 0; i < SI_PFP_UCODE_SIZE; i++)
+			WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_PFP_UCODE_ADDR, 0);
+
+		/* CE */
+		fw_data = (const __be32 *)rdev->ce_fw->data;
+		WREG32(CP_CE_UCODE_ADDR, 0);
+		for (i = 0; i < SI_CE_UCODE_SIZE; i++)
+			WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_CE_UCODE_ADDR, 0);
+
+		/* ME */
+		fw_data = (const __be32 *)rdev->me_fw->data;
+		WREG32(CP_ME_RAM_WADDR, 0);
+		for (i = 0; i < SI_PM4_UCODE_SIZE; i++)
+			WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+		WREG32(CP_ME_RAM_WADDR, 0);
+	}
 
 	WREG32(CP_PFP_UCODE_ADDR, 0);
 	WREG32(CP_CE_UCODE_ADDR, 0);
@@ -3308,7 +3467,7 @@ static int si_cp_start(struct radeon_dev
 	radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE));
 	radeon_ring_write(ring, 0xc000);
 	radeon_ring_write(ring, 0xe000);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	si_cp_enable(rdev, true);
 
@@ -3337,7 +3496,7 @@ static int si_cp_start(struct radeon_dev
 	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
 	radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) {
 		ring = &rdev->ring[i];
@@ -3347,7 +3506,7 @@ static int si_cp_start(struct radeon_dev
 		radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0));
 		radeon_ring_write(ring, 0);
 
-		radeon_ring_unlock_commit(rdev, ring);
+		radeon_ring_unlock_commit(rdev, ring, false);
 	}
 
 	return 0;
@@ -4014,7 +4173,6 @@ static int si_pcie_gart_enable(struct ra
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
-	radeon_gart_restore(rdev);
 	/* Setup TLB control */
 	WREG32(MC_VM_MX_L1_TLB_CNTL,
 	       (0xA << 7) |
@@ -4059,10 +4217,10 @@ static int si_pcie_gart_enable(struct ra
 	for (i = 1; i < 16; i++) {
 		if (i < 8)
 			WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-			       rdev->gart.table_addr >> 12);
+			       rdev->vm_manager.saved_table_addr[i]);
 		else
 			WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2),
-			       rdev->gart.table_addr >> 12);
+			       rdev->vm_manager.saved_table_addr[i]);
 	}
 
 	/* enable context1-15 */
@@ -4094,6 +4252,17 @@ static int si_pcie_gart_enable(struct ra
 
 static void si_pcie_gart_disable(struct radeon_device *rdev)
 {
+	unsigned i;
+
+	for (i = 1; i < 16; ++i) {
+		uint32_t reg;
+		if (i < 8)
+			reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2);
+		else
+			reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2);
+		rdev->vm_manager.saved_table_addr[i] = RREG32(reg);
+	}
+
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
 	WREG32(VM_CONTEXT1_CNTL, 0);
@@ -4781,7 +4950,7 @@ void si_vm_flush(struct radeon_device *r
 
 	/* write new base address */
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
 
 	if (vm->id < 8) {
@@ -4796,7 +4965,7 @@ void si_vm_flush(struct radeon_device *r
 
 	/* flush hdp cache */
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
 	radeon_ring_write(ring, 0);
@@ -4804,7 +4973,7 @@ void si_vm_flush(struct radeon_device *r
 
 	/* bits 0-15 are the VM contexts0-15 */
 	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
 	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
 	radeon_ring_write(ring, 0);
@@ -5558,7 +5727,6 @@ static void si_enable_lbpw(struct radeon
 static int si_rlc_resume(struct radeon_device *rdev)
 {
 	u32 i;
-	const __be32 *fw_data;
 
 	if (!rdev->rlc_fw)
 		return -EINVAL;
@@ -5581,10 +5749,26 @@ static int si_rlc_resume(struct radeon_d
 	WREG32(RLC_MC_CNTL, 0);
 	WREG32(RLC_UCODE_CNTL, 0);
 
-	fw_data = (const __be32 *)rdev->rlc_fw->data;
-	for (i = 0; i < SI_RLC_UCODE_SIZE; i++) {
-		WREG32(RLC_UCODE_ADDR, i);
-		WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+	if (rdev->new_fw) {
+		const struct rlc_firmware_header_v1_0 *hdr =
+			(const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
+		u32 fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+		const __le32 *fw_data = (const __le32 *)
+			(rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+		radeon_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++));
+		}
+	} else {
+		const __be32 *fw_data =
+			(const __be32 *)rdev->rlc_fw->data;
+		for (i = 0; i < SI_RLC_UCODE_SIZE; i++) {
+			WREG32(RLC_UCODE_ADDR, i);
+			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+		}
 	}
 	WREG32(RLC_UCODE_ADDR, 0);
 
@@ -6059,17 +6243,17 @@ static inline u32 si_get_ih_wptr(struct
 		wptr = RREG32(IH_RB_WPTR);
 
 	if (wptr & RB_OVERFLOW) {
+		wptr &= ~RB_OVERFLOW;
 		/* When a ring buffer overflow happen start parsing interrupt
 		 * from the last not overwritten vector (wptr + 16). Hopefully
 		 * this should allow us to catchup.
 		 */
-		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
-			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+			 wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
 		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_WPTR_OVERFLOW_CLEAR;
 		WREG32(IH_RB_CNTL, tmp);
-		wptr &= ~RB_OVERFLOW;
 	}
 	return (wptr & rdev->ih.ptr_mask);
 }
@@ -6284,7 +6468,8 @@ restart_ih:
 		case 16: /* D5 page flip */
 		case 18: /* D6 page flip */
 			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
-			radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+			if (radeon_use_pflipirq > 0)
+				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
 			break;
 		case 42: /* HPD hotplug */
 			switch (src_data) {
@@ -6406,13 +6591,13 @@ restart_ih:
 		/* wptr/rptr are in bytes! */
 		rptr += 16;
 		rptr &= rdev->ih.ptr_mask;
+		WREG32(IH_RB_RPTR, rptr);
 	}
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
 	if (queue_thermal && rdev->pm.dpm_enabled)
 		schedule_work(&rdev->pm.dpm.thermal.work);
 	rdev->ih.rptr = rptr;
-	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	atomic_set(&rdev->ih.lock, 0);
 
 	/* make sure wptr hasn't changed while processing */
@@ -6930,6 +7115,9 @@ static void si_pcie_gen3_enable(struct r
 	int ret, i;
 	u16 tmp16;
 
+	if (pci_is_root_bus(rdev->pdev->bus))
+		return;
+
 	if (radeon_pcie_gen2 == 0)
 		return;
 
@@ -7207,7 +7395,8 @@ static void si_program_aspm(struct radeo
 			if (orig != data)
 				WREG32_PIF_PHY1(PB1_PIF_CNTL, data);
 
-			if (!disable_clkreq) {
+			if (!disable_clkreq &&
+			    !pci_is_root_bus(rdev->pdev->bus)) {
 				struct pci_dev *root = rdev->pdev->bus->self;
 				u32 lnkcap;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,41 @@ bool si_dma_is_lockup(struct radeon_devi
 }
 
 /**
- * si_dma_vm_set_page - update the page tables using the DMA
+ * si_dma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr where to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using the DMA (SI).
+ */
+void si_dma_vm_copy_pages(struct radeon_device *rdev,
+			  struct radeon_ib *ib,
+			  uint64_t pe, uint64_t src,
+			  unsigned count)
+{
+	while (count) {
+		unsigned bytes = count * 8;
+		if (bytes > 0xFFFF8)
+			bytes = 0xFFFF8;
+
+		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
+						      1, 0, 0, bytes);
+		ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+		ib->ptr[ib->length_dw++] = lower_32_bits(src);
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
+
+		pe += bytes;
+		src += bytes;
+		count -= bytes / 8;
+	}
+}
+
+/**
+ * si_dma_vm_write_pages - update PTEs by writing them manually
  *
  * @rdev: radeon_device pointer
  * @ib: indirect buffer to fill with commands
@@ -66,83 +100,89 @@ bool si_dma_is_lockup(struct radeon_devi
  * @incr: increase next addr by incr bytes
  * @flags: access flags
  *
- * Update the page tables using the DMA (SI).
+ * Update PTEs by writing them manually using the DMA (SI).
  */
-void si_dma_vm_set_page(struct radeon_device *rdev,
-			struct radeon_ib *ib,
-			uint64_t pe,
-			uint64_t addr, unsigned count,
-			uint32_t incr, uint32_t flags)
+void si_dma_vm_write_pages(struct radeon_device *rdev,
+			   struct radeon_ib *ib,
+			   uint64_t pe,
+			   uint64_t addr, unsigned count,
+			   uint32_t incr, uint32_t flags)
 {
 	uint64_t value;
 	unsigned ndw;
 
-	trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
-	if (flags == R600_PTE_GART) {
-		uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
-		while (count) {
-			unsigned bytes = count * 8;
-			if (bytes > 0xFFFF8)
-				bytes = 0xFFFF8;
-
-			ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
-							      1, 0, 0, bytes);
-			ib->ptr[ib->length_dw++] = lower_32_bits(pe);
-			ib->ptr[ib->length_dw++] = lower_32_bits(src);
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
-			ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
-
-			pe += bytes;
-			src += bytes;
-			count -= bytes / 8;
-		}
-	} else if (flags & R600_PTE_SYSTEM) {
-		while (count) {
-			ndw = count * 2;
-			if (ndw > 0xFFFFE)
-				ndw = 0xFFFFE;
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
 
-			/* for non-physically contiguous pages (system) */
-			ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw);
-			ib->ptr[ib->length_dw++] = pe;
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
-			for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+		/* for non-physically contiguous pages (system) */
+		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw);
+		ib->ptr[ib->length_dw++] = pe;
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+			if (flags & R600_PTE_SYSTEM) {
 				value = radeon_vm_map_gart(rdev, addr);
 				value &= 0xFFFFFFFFFFFFF000ULL;
-				addr += incr;
-				value |= flags;
-				ib->ptr[ib->length_dw++] = value;
-				ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			}
-		}
-	} else {
-		while (count) {
-			ndw = count * 2;
-			if (ndw > 0xFFFFE)
-				ndw = 0xFFFFE;
-
-			if (flags & R600_PTE_VALID)
+			} else if (flags & R600_PTE_VALID) {
 				value = addr;
-			else
+			} else {
 				value = 0;
-			/* for physically contiguous pages (vram) */
-			ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
-			ib->ptr[ib->length_dw++] = pe; /* dst addr */
-			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
-			ib->ptr[ib->length_dw++] = flags; /* mask */
-			ib->ptr[ib->length_dw++] = 0;
-			ib->ptr[ib->length_dw++] = value; /* value */
+			}
+			addr += incr;
+			value |= flags;
+			ib->ptr[ib->length_dw++] = value;
 			ib->ptr[ib->length_dw++] = upper_32_bits(value);
-			ib->ptr[ib->length_dw++] = incr; /* increment size */
-			ib->ptr[ib->length_dw++] = 0;
-			pe += ndw * 4;
-			addr += (ndw / 2) * incr;
-			count -= ndw / 2;
 		}
 	}
-	while (ib->length_dw & 0x7)
-		ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0);
+}
+
+/**
+ * si_dma_vm_set_pages - update the page tables using the DMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: access flags
+ *
+ * Update the page tables using the DMA (SI).
+ */
+void si_dma_vm_set_pages(struct radeon_device *rdev,
+			 struct radeon_ib *ib,
+			 uint64_t pe,
+			 uint64_t addr, unsigned count,
+			 uint32_t incr, uint32_t flags)
+{
+	uint64_t value;
+	unsigned ndw;
+
+	while (count) {
+		ndw = count * 2;
+		if (ndw > 0xFFFFE)
+			ndw = 0xFFFFE;
+
+		if (flags & R600_PTE_VALID)
+			value = addr;
+		else
+			value = 0;
+
+		/* for physically contiguous pages (vram) */
+		ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+		ib->ptr[ib->length_dw++] = pe; /* dst addr */
+		ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+		ib->ptr[ib->length_dw++] = flags; /* mask */
+		ib->ptr[ib->length_dw++] = 0;
+		ib->ptr[ib->length_dw++] = value; /* value */
+		ib->ptr[ib->length_dw++] = upper_32_bits(value);
+		ib->ptr[ib->length_dw++] = incr; /* increment size */
+		ib->ptr[ib->length_dw++] = 0;
+		pe += ndw * 4;
+		addr += (ndw / 2) * incr;
+		count -= ndw / 2;
+	}
 }
 
 void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
@@ -235,7 +275,7 @@ int si_copy_dma(struct radeon_device *rd
 		return r;
 	}
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	radeon_semaphore_free(rdev, &sem, *fence);
 
 	return r;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dpm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dpm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dpm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dpm.c	2014-09-28 17:29:07.000000000 -0400
@@ -3812,6 +3812,27 @@ void si_trim_voltage_table_to_fit_state_
 	voltage_table->count = max_voltage_steps;
 }
 
+static int si_get_svi2_voltage_table(struct radeon_device *rdev,
+				     struct radeon_clock_voltage_dependency_table *voltage_dependency_table,
+				     struct atom_voltage_table *voltage_table)
+{
+	u32 i;
+
+	if (voltage_dependency_table == NULL)
+		return -EINVAL;
+
+	voltage_table->mask_low = 0;
+	voltage_table->phase_delay = 0;
+
+	voltage_table->count = voltage_dependency_table->count;
+	for (i = 0; i < voltage_table->count; i++) {
+		voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
+		voltage_table->entries[i].smio_low = 0;
+	}
+
+	return 0;
+}
+
 static int si_construct_voltage_tables(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -3819,15 +3840,25 @@ static int si_construct_voltage_tables(s
 	struct si_power_info *si_pi = si_get_pi(rdev);
 	int ret;
 
-	ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
-					    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
-	if (ret)
-		return ret;
+	if (pi->voltage_control) {
+		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
+						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
+		if (ret)
+			return ret;
 
-	if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
-		si_trim_voltage_table_to_fit_state_table(rdev,
-							 SISLANDS_MAX_NO_VREG_STEPS,
-							 &eg_pi->vddc_voltage_table);
+		if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
+			si_trim_voltage_table_to_fit_state_table(rdev,
+								 SISLANDS_MAX_NO_VREG_STEPS,
+								 &eg_pi->vddc_voltage_table);
+	} else if (si_pi->voltage_control_svi2) {
+		ret = si_get_svi2_voltage_table(rdev,
+						&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+						&eg_pi->vddc_voltage_table);
+		if (ret)
+			return ret;
+	} else {
+		return -EINVAL;
+	}
 
 	if (eg_pi->vddci_control) {
 		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI,
@@ -3840,6 +3871,13 @@ static int si_construct_voltage_tables(s
 								 SISLANDS_MAX_NO_VREG_STEPS,
 								 &eg_pi->vddci_voltage_table);
 	}
+	if (si_pi->vddci_control_svi2) {
+		ret = si_get_svi2_voltage_table(rdev,
+						&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+						&eg_pi->vddci_voltage_table);
+		if (ret)
+			return ret;
+	}
 
 	if (pi->mvdd_control) {
 		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC,
@@ -3893,46 +3931,55 @@ static int si_populate_smc_voltage_table
 	struct si_power_info *si_pi = si_get_pi(rdev);
 	u8 i;
 
-	if (eg_pi->vddc_voltage_table.count) {
-		si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
-		table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
-			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
+	if (si_pi->voltage_control_svi2) {
+		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
+			si_pi->svc_gpio_id);
+		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
+			si_pi->svd_gpio_id);
+		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
+					   2);
+	} else {
+		if (eg_pi->vddc_voltage_table.count) {
+			si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
+			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
+				cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
 
-		for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
-			if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
-				table->maxVDDCIndexInPPTable = i;
-				break;
+			for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
+				if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
+					table->maxVDDCIndexInPPTable = i;
+					break;
+				}
 			}
 		}
-	}
 
-	if (eg_pi->vddci_voltage_table.count) {
-		si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
+		if (eg_pi->vddci_voltage_table.count) {
+			si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
 
-		table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
-			cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
-	}
+			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
+				cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
+		}
 
 
-	if (si_pi->mvdd_voltage_table.count) {
-		si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
+		if (si_pi->mvdd_voltage_table.count) {
+			si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
 
-		table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
-			cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
-	}
+			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
+				cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
+		}
 
-	if (si_pi->vddc_phase_shed_control) {
-		if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
-						      &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
-			si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
+		if (si_pi->vddc_phase_shed_control) {
+			if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
+							      &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
+				si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
 
-			table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
-				cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
+				table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
+					cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
 
-			si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
-						   (u32)si_pi->vddc_phase_shed_table.phase_delay);
-		} else {
-			si_pi->vddc_phase_shed_control = false;
+				si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
+							   (u32)si_pi->vddc_phase_shed_table.phase_delay);
+			} else {
+				si_pi->vddc_phase_shed_control = false;
+			}
 		}
 	}
 
@@ -5798,16 +5845,17 @@ int si_dpm_enable(struct radeon_device *
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct si_power_info *si_pi = si_get_pi(rdev);
 	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 	int ret;
 
 	if (si_is_smc_running(rdev))
 		return -EINVAL;
-	if (pi->voltage_control)
+	if (pi->voltage_control || si_pi->voltage_control_svi2)
 		si_enable_voltage_control(rdev, true);
 	if (pi->mvdd_control)
 		si_get_mvdd_configuration(rdev);
-	if (pi->voltage_control) {
+	if (pi->voltage_control || si_pi->voltage_control_svi2) {
 		ret = si_construct_voltage_tables(rdev);
 		if (ret) {
 			DRM_ERROR("si_construct_voltage_tables failed\n");
@@ -6406,16 +6454,32 @@ int si_dpm_init(struct radeon_device *rd
 	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
 
 	pi->voltage_control =
-		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_GPIO_LUT);
+		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+					    VOLTAGE_OBJ_GPIO_LUT);
+	if (!pi->voltage_control) {
+		si_pi->voltage_control_svi2 =
+			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+						    VOLTAGE_OBJ_SVID2);
+		if (si_pi->voltage_control_svi2)
+			radeon_atom_get_svi2_info(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+						  &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
+	}
 
 	pi->mvdd_control =
-		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, VOLTAGE_OBJ_GPIO_LUT);
+		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
+					    VOLTAGE_OBJ_GPIO_LUT);
 
 	eg_pi->vddci_control =
-		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, VOLTAGE_OBJ_GPIO_LUT);
+		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
+					    VOLTAGE_OBJ_GPIO_LUT);
+	if (!eg_pi->vddci_control)
+		si_pi->vddci_control_svi2 =
+			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
+						    VOLTAGE_OBJ_SVID2);
 
 	si_pi->vddc_phase_shed_control =
-		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT);
+		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+					    VOLTAGE_OBJ_PHASE_LUT);
 
 	rv770_get_engine_memory_ss(rdev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dpm.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dpm.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_dpm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_dpm.h	2014-09-28 17:29:07.000000000 -0400
@@ -170,6 +170,8 @@ struct si_power_info {
 	bool vddc_phase_shed_control;
 	bool pspp_notify_required;
 	bool sclk_deep_sleep_above_low;
+	bool voltage_control_svi2;
+	bool vddci_control_svi2;
 	/* smc offsets */
 	u32 sram_end;
 	u32 state_table_start;
@@ -192,6 +194,9 @@ struct si_power_info {
 	SMC_SIslands_MCRegisters smc_mc_reg_table;
 	SISLANDS_SMC_STATETABLE smc_statetable;
 	PP_SIslands_PAPMParameters papm_parm;
+	/* SVI2 */
+	u8 svd_gpio_id;
+	u8 svc_gpio_id;
 };
 
 #define SISLANDS_INITIAL_STATE_ARB_INDEX    0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/sislands_smc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/sislands_smc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/sislands_smc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/sislands_smc.h	2014-09-28 17:29:07.000000000 -0400
@@ -241,6 +241,9 @@ typedef struct SISLANDS_SMC_STATETABLE S
 #define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width  0xF4
 #define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen   0xFC
 #define SI_SMC_SOFT_REGISTER_vr_hot_gpio              0x100
+#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type     0x118
+#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd   0x11c
+#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc   0x120
 
 #define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
 #define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_smc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_smc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/si_smc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/si_smc.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,36 +219,48 @@ int si_load_smc_ucode(struct radeon_devi
 	if (!rdev->smc_fw)
 		return -EINVAL;
 
-	switch (rdev->family) {
-	case CHIP_TAHITI:
-		ucode_start_address = TAHITI_SMC_UCODE_START;
-		ucode_size = TAHITI_SMC_UCODE_SIZE;
-		break;
-	case CHIP_PITCAIRN:
-		ucode_start_address = PITCAIRN_SMC_UCODE_START;
-		ucode_size = PITCAIRN_SMC_UCODE_SIZE;
-		break;
-	case CHIP_VERDE:
-		ucode_start_address = VERDE_SMC_UCODE_START;
-		ucode_size = VERDE_SMC_UCODE_SIZE;
-		break;
-	case CHIP_OLAND:
-		ucode_start_address = OLAND_SMC_UCODE_START;
-		ucode_size = OLAND_SMC_UCODE_SIZE;
-		break;
-	case CHIP_HAINAN:
-		ucode_start_address = HAINAN_SMC_UCODE_START;
-		ucode_size = HAINAN_SMC_UCODE_SIZE;
-		break;
-	default:
-		DRM_ERROR("unknown asic in smc ucode loader\n");
-		BUG();
+	if (rdev->new_fw) {
+		const struct smc_firmware_header_v1_0 *hdr =
+			(const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
+
+		radeon_ucode_print_smc_hdr(&hdr->header);
+
+		ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
+		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
+		src = (const u8 *)
+			(rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+	} else {
+		switch (rdev->family) {
+		case CHIP_TAHITI:
+			ucode_start_address = TAHITI_SMC_UCODE_START;
+			ucode_size = TAHITI_SMC_UCODE_SIZE;
+			break;
+		case CHIP_PITCAIRN:
+			ucode_start_address = PITCAIRN_SMC_UCODE_START;
+			ucode_size = PITCAIRN_SMC_UCODE_SIZE;
+			break;
+		case CHIP_VERDE:
+			ucode_start_address = VERDE_SMC_UCODE_START;
+			ucode_size = VERDE_SMC_UCODE_SIZE;
+			break;
+		case CHIP_OLAND:
+			ucode_start_address = OLAND_SMC_UCODE_START;
+			ucode_size = OLAND_SMC_UCODE_SIZE;
+			break;
+		case CHIP_HAINAN:
+			ucode_start_address = HAINAN_SMC_UCODE_START;
+			ucode_size = HAINAN_SMC_UCODE_SIZE;
+			break;
+		default:
+			DRM_ERROR("unknown asic in smc ucode loader\n");
+			BUG();
+		}
+		src = (const u8 *)rdev->smc_fw->data;
 	}
 
 	if (ucode_size & 3)
 		return -EINVAL;
 
-	src = (const u8 *)rdev->smc_fw->data;
 	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
 	WREG32(SMC_IND_INDEX_0, ucode_start_address);
 	WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/trinity_dpm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/trinity_dpm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/trinity_dpm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/trinity_dpm.c	2014-09-28 17:29:07.000000000 -0400
@@ -1874,16 +1874,22 @@ int trinity_dpm_init(struct radeon_devic
 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
 		pi->at[i] = TRINITY_AT_DFLT;
 
-	/* There are stability issues reported on with
-	 * bapm enabled when switching between AC and battery
-	 * power.  At the same time, some MSI boards hang
-	 * if it's not enabled and dpm is enabled.  Just enable
-	 * it for MSI boards right now.
-	 */
-	if (rdev->pdev->subsystem_vendor == 0x1462)
-		pi->enable_bapm = true;
-	else
+	if (radeon_bapm == -1) {
+		/* There are stability issues reported on with
+		 * bapm enabled when switching between AC and battery
+		 * power.  At the same time, some MSI boards hang
+		 * if it's not enabled and dpm is enabled.  Just enable
+		 * it for MSI boards right now.
+		 */
+		if (rdev->pdev->subsystem_vendor == 0x1462)
+			pi->enable_bapm = true;
+		else
+			pi->enable_bapm = false;
+	} else if (radeon_bapm == 0) {
 		pi->enable_bapm = false;
+	} else {
+		pi->enable_bapm = true;
+	}
 	pi->enable_nbps_policy = true;
 	pi->enable_sclk_ds = true;
 	pi->enable_gfx_power_gating = true;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,7 +124,7 @@ int uvd_v1_0_init(struct radeon_device *
 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
 	radeon_ring_write(ring, 3);
 
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 
 done:
 	/* lower clocks again */
@@ -331,7 +331,7 @@ int uvd_v1_0_ring_test(struct radeon_dev
 	}
 	radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
 	radeon_ring_write(ring, 0xDEADBEEF);
-	radeon_ring_unlock_commit(rdev, ring);
+	radeon_ring_unlock_commit(rdev, ring, false);
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = RREG32(UVD_CONTEXT_ID);
 		if (tmp == 0xDEADBEEF)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -187,7 +187,7 @@ static struct drm_driver rcar_du_driver
  * Power management
  */
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int rcar_du_pm_suspend(struct device *dev)
 {
 	struct rcar_du_device *rcdu = dev_get_drvdata(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,7 +135,9 @@ rcar_du_fb_create(struct drm_device *dev
 {
 	struct rcar_du_device *rcdu = dev->dev_private;
 	const struct rcar_du_format_info *format;
+	unsigned int max_pitch;
 	unsigned int align;
+	unsigned int bpp;
 
 	format = rcar_du_format_info(mode_cmd->pixel_format);
 	if (format == NULL) {
@@ -144,13 +146,20 @@ rcar_du_fb_create(struct drm_device *dev
 		return ERR_PTR(-EINVAL);
 	}
 
+	/*
+	 * The pitch and alignment constraints are expressed in pixels on the
+	 * hardware side and in bytes in the DRM API.
+	 */
+	bpp = format->planes == 2 ? 1 : format->bpp / 8;
+	max_pitch =  4096 * bpp;
+
 	if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
 		align = 128;
 	else
-		align = 16 * format->bpp / 8;
+		align = 16 * bpp;
 
 	if (mode_cmd->pitches[0] & (align - 1) ||
-	    mode_cmd->pitches[0] >= 8192) {
+	    mode_cmd->pitches[0] >= max_pitch) {
 		dev_dbg(dev->dev, "invalid pitch value %u\n",
 			mode_cmd->pitches[0]);
 		return ERR_PTR(-EINVAL);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c	2014-09-28 17:29:07.000000000 -0400
@@ -64,7 +64,7 @@ static const struct drm_connector_helper
 
 static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 
@@ -105,7 +105,7 @@ int rcar_du_lvds_connector_init(struct r
 		return ret;
 
 	drm_connector_helper_add(connector, &connector_helper_funcs);
-	ret = drm_sysfs_connector_add(connector);
+	ret = drm_connector_register(connector);
 	if (ret < 0)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@ static const struct drm_connector_helper
 
 static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 
@@ -70,7 +70,7 @@ int rcar_du_vga_connector_init(struct rc
 		return ret;
 
 	drm_connector_helper_add(connector, &connector_helper_funcs);
-	ret = drm_sysfs_connector_add(connector);
+	ret = drm_connector_register(connector);
 	if (ret < 0)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -692,7 +692,7 @@ static void shmob_drm_connector_destroy(
 	struct shmob_drm_connector *scon = to_shmob_connector(connector);
 
 	shmob_drm_backlight_exit(scon);
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 
@@ -726,7 +726,7 @@ int shmob_drm_connector_create(struct sh
 		return ret;
 
 	drm_connector_helper_add(connector, &connector_helper_funcs);
-	ret = drm_sysfs_connector_add(connector);
+	ret = drm_connector_register(connector);
 	if (ret < 0)
 		goto err_cleanup;
 
@@ -749,7 +749,7 @@ int shmob_drm_connector_create(struct sh
 err_backlight:
 	shmob_drm_backlight_exit(&sdev->connector);
 err_sysfs:
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 err_cleanup:
 	drm_connector_cleanup(connector);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -297,7 +297,7 @@ static struct drm_driver shmob_drm_drive
  * Power management
  */
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int shmob_drm_pm_suspend(struct device *dev)
 {
 	struct shmob_drm_device *sdev = dev_get_drvdata(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/Kconfig linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/Kconfig
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,15 @@
+config DRM_STI
+	tristate "DRM Support for STMicroelectronics SoC stiH41x Series"
+	depends on DRM && (SOC_STIH415 || SOC_STIH416 || ARCH_MULTIPLATFORM)
+	select RESET_CONTROLLER
+	select DRM_KMS_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	help
+	  Choose this option to enable DRM on STM stiH41x chipset
+
+config DRM_STI_FBDEV
+	bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
+	depends on DRM_STI
+	help
+	  Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,21 @@
+sticompositor-y := \
+	sti_layer.o \
+	sti_mixer.o \
+	sti_gdp.o \
+	sti_vid.o \
+	sti_compositor.o \
+	sti_drm_crtc.o \
+	sti_drm_plane.o
+
+stihdmi-y := sti_hdmi.o \
+	sti_hdmi_tx3g0c55phy.o \
+	sti_hdmi_tx3g4c28phy.o \
+
+obj-$(CONFIG_DRM_STI) = \
+	sti_vtg.o \
+	sti_vtac.o \
+	stihdmi.o \
+	sti_hda.o \
+	sti_tvout.o \
+	sticompositor.o \
+	sti_drm_drv.o
\ No newline at end of file
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/NOTES linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/NOTES
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/NOTES	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/NOTES	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,58 @@
+1. stiH display hardware IP
+---------------------------
+The STMicroelectronics stiH SoCs use a common chain of HW display IP blocks:
+- The High Quality Video Display Processor (HQVDP) gets video frames from a
+  video decoder and does high quality video processing, including scaling.
+
+- The Compositor is a multiplane, dual-mixer (Main & Aux) digital processor. It
+  has several inputs:
+  - The graphics planes are internally processed by the Generic Display
+    Pipeline (GDP).
+  - The video plug (VID) connects to the HQVDP output.
+  - The cursor handles ... a cursor.
+- The TV OUT pre-formats (convert, clip, round) the compositor output data
+- The HDMI / DVO / HD Analog / SD analog IP builds the video signals
+  - DVO (Digital Video Output) handles a 24bits parallel signal
+  - The HD analog signal is typically driven by a YCbCr cable, supporting up to
+    1080i mode.
+  - The SD analog signal is typically used for legacy TV
+- The VTG (Video Timing Generators) build Vsync signals used by the other HW IP
+Note that some stiH drivers support only a subset of thee HW IP.
+
+                  .-------------.   .-----------.   .-----------.
+GPU >-------------+GDP     Main |   |           +---+    HDMI   +--> HDMI
+GPU >-------------+GDP     mixer+---+           |   :===========:
+GPU >-------------+Cursor       |   |           +---+    DVO    +--> 24b//
+        -------   |  COMPOSITOR |   |  TV OUT   |   :===========:
+       |       |  |             |   |           +---+ HD analog +--> YCbCr
+Vid >--+ HQVDP +--+VID     Aux  +---+           |   :===========:
+dec    |       |  |        mixer|   |           +---+ SD analog +--> CVBS
+       '-------'  '-------------'   '-----------'   '-----------'
+                   .-----------.
+                   |       main+--> Vsync
+                   | VTG       |
+                   |        aux+--> Vsync
+                   '-----------'
+
+2. DRM / HW mapping
+-------------------
+These IP are mapped to the DRM objects as following:
+- The CRTCs are mapped to the Compositor Main and Aux Mixers
+- The Framebuffers and planes are mapped to the Compositor GDP (non video
+  buffers) and to HQVDP+VID (video buffers)
+- The Cursor is mapped to the Compositor Cursor
+- The Encoders are mapped to the TVOut
+- The Bridges/Connectors are mapped to the HDMI / DVO / HD Analog / SD analog
+
+FB & planes         Cursor      CRTC     Encoders    Bridges/Connectors
+   |                   |          |         |                       |
+   |                   |          |         |                       |
+   |              .-------------. | .-----------.   .-----------.   |
+   +------------> |GDP |   Main | | |       +-> |   |    HDMI   | <-+
+   +------------> |GDP v   mixer|<+ |       |   |   :===========:   |
+   |              |Cursor       | | |       +-> |   |    DVO    | <-+
+   |    -------   |  COMPOSITOR | | |TV OUT |   |   :===========:   |
+   |   |       |  |             | | |       +-> |   | HD analog | <-+
+   +-> | HQVDP |  |VID     Aux  |<+ |       |   |   :===========:   |
+       |       |  |        mixer|   |       +-> |   | SD analog | <-+
+       '-------'  '-------------'   '-----------'   '-----------'
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_compositor.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_compositor.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_compositor.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_compositor.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+
+#include "sti_compositor.h"
+#include "sti_drm_crtc.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_plane.h"
+#include "sti_gdp.h"
+#include "sti_vtg.h"
+
+/*
+ * stiH407 compositor properties
+ */
+struct sti_compositor_data stih407_compositor_data = {
+	.nb_subdev = 6,
+	.subdev_desc = {
+			{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
+			{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
+			{STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
+			{STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
+			{STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
+			{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
+	},
+};
+
+/*
+ * stiH416 compositor properties
+ * Note:
+ * on stih416 MIXER_AUX has a different base address from MIXER_MAIN
+ * Moreover, GDPx is different for Main and Aux Mixer. So this subdev map does
+ * not fit for stiH416 if we want to enable the MIXER_AUX.
+ */
+struct sti_compositor_data stih416_compositor_data = {
+	.nb_subdev = 3,
+	.subdev_desc = {
+			{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
+			{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
+			{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
+	},
+};
+
+static int sti_compositor_init_subdev(struct sti_compositor *compo,
+		struct sti_compositor_subdev_descriptor *desc,
+		unsigned int array_size)
+{
+	unsigned int i, mixer_id = 0, layer_id = 0;
+
+	for (i = 0; i < array_size; i++) {
+		switch (desc[i].type) {
+		case STI_MIXER_MAIN_SUBDEV:
+		case STI_MIXER_AUX_SUBDEV:
+			compo->mixer[mixer_id++] =
+			    sti_mixer_create(compo->dev, desc[i].id,
+					     compo->regs + desc[i].offset);
+			break;
+		case STI_GPD_SUBDEV:
+		case STI_VID_SUBDEV:
+			compo->layer[layer_id++] =
+			    sti_layer_create(compo->dev, desc[i].id,
+					     compo->regs + desc[i].offset);
+			break;
+			/* case STI_CURSOR_SUBDEV : TODO */
+		default:
+			DRM_ERROR("Unknow subdev compoment type\n");
+			return 1;
+		}
+
+	}
+	compo->nb_mixers = mixer_id;
+	compo->nb_layers = layer_id;
+
+	return 0;
+}
+
+static int sti_compositor_bind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	unsigned int i, crtc = 0, plane = 0;
+	struct sti_drm_private *dev_priv = drm_dev->dev_private;
+	struct drm_plane *cursor = NULL;
+	struct drm_plane *primary = NULL;
+
+	dev_priv->compo = compo;
+
+	for (i = 0; i < compo->nb_layers; i++) {
+		if (compo->layer[i]) {
+			enum sti_layer_desc desc = compo->layer[i]->desc;
+			enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
+			enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
+
+			if (compo->mixer[crtc])
+				plane_type = DRM_PLANE_TYPE_PRIMARY;
+
+			switch (type) {
+			case STI_CUR:
+				cursor = sti_drm_plane_init(drm_dev,
+						compo->layer[i],
+						(1 << crtc) - 1,
+						DRM_PLANE_TYPE_CURSOR);
+				break;
+			case STI_GDP:
+			case STI_VID:
+				primary = sti_drm_plane_init(drm_dev,
+						compo->layer[i],
+						(1 << crtc) - 1, plane_type);
+				plane++;
+				break;
+			case STI_BCK:
+				break;
+			}
+
+			/* The first planes are reserved for primary planes*/
+			if (compo->mixer[crtc]) {
+				sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
+						primary, cursor);
+				crtc++;
+				cursor = NULL;
+			}
+		}
+	}
+
+	drm_vblank_init(drm_dev, crtc);
+	/* Allow usage of vblank without having to call drm_irq_install */
+	drm_dev->irq_enabled = 1;
+
+	DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
+			 crtc, plane);
+	DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");
+
+	return 0;
+}
+
+static void sti_compositor_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops sti_compositor_ops = {
+	.bind	= sti_compositor_bind,
+	.unbind	= sti_compositor_unbind,
+};
+
+static const struct of_device_id compositor_of_match[] = {
+	{
+		.compatible = "st,stih416-compositor",
+		.data = &stih416_compositor_data,
+	}, {
+		.compatible = "st,stih407-compositor",
+		.data = &stih407_compositor_data,
+	}, {
+		/* end node */
+	}
+};
+MODULE_DEVICE_TABLE(of, compositor_of_match);
+
+static int sti_compositor_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *vtg_np;
+	struct sti_compositor *compo;
+	struct resource *res;
+	int err;
+
+	compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
+	if (!compo) {
+		DRM_ERROR("Failed to allocate compositor context\n");
+		return -ENOMEM;
+	}
+	compo->dev = dev;
+	compo->vtg_vblank_nb.notifier_call = sti_drm_crtc_vblank_cb;
+
+	/* populate data structure depending on compatibility */
+	BUG_ON(!of_match_node(compositor_of_match, np)->data);
+
+	memcpy(&compo->data, of_match_node(compositor_of_match, np)->data,
+	       sizeof(struct sti_compositor_data));
+
+	/* Get Memory ressources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		DRM_ERROR("Get memory resource failed\n");
+		return -ENXIO;
+	}
+	compo->regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (compo->regs == NULL) {
+		DRM_ERROR("Register mapping failed\n");
+		return -ENXIO;
+	}
+
+	/* Get clock resources */
+	compo->clk_compo_main = devm_clk_get(dev, "compo_main");
+	if (IS_ERR(compo->clk_compo_main)) {
+		DRM_ERROR("Cannot get compo_main clock\n");
+		return PTR_ERR(compo->clk_compo_main);
+	}
+
+	compo->clk_compo_aux = devm_clk_get(dev, "compo_aux");
+	if (IS_ERR(compo->clk_compo_aux)) {
+		DRM_ERROR("Cannot get compo_aux clock\n");
+		return PTR_ERR(compo->clk_compo_aux);
+	}
+
+	compo->clk_pix_main = devm_clk_get(dev, "pix_main");
+	if (IS_ERR(compo->clk_pix_main)) {
+		DRM_ERROR("Cannot get pix_main clock\n");
+		return PTR_ERR(compo->clk_pix_main);
+	}
+
+	compo->clk_pix_aux = devm_clk_get(dev, "pix_aux");
+	if (IS_ERR(compo->clk_pix_aux)) {
+		DRM_ERROR("Cannot get pix_aux clock\n");
+		return PTR_ERR(compo->clk_pix_aux);
+	}
+
+	/* Get reset resources */
+	compo->rst_main = devm_reset_control_get(dev, "compo-main");
+	/* Take compo main out of reset */
+	if (!IS_ERR(compo->rst_main))
+		reset_control_deassert(compo->rst_main);
+
+	compo->rst_aux = devm_reset_control_get(dev, "compo-aux");
+	/* Take compo aux out of reset */
+	if (!IS_ERR(compo->rst_aux))
+		reset_control_deassert(compo->rst_aux);
+
+	vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
+	if (vtg_np)
+		compo->vtg_main = of_vtg_find(vtg_np);
+
+	vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1);
+	if (vtg_np)
+		compo->vtg_aux = of_vtg_find(vtg_np);
+
+	/* Initialize compositor subdevices */
+	err = sti_compositor_init_subdev(compo, compo->data.subdev_desc,
+					 compo->data.nb_subdev);
+	if (err)
+		return err;
+
+	platform_set_drvdata(pdev, compo);
+
+	return component_add(&pdev->dev, &sti_compositor_ops);
+}
+
+static int sti_compositor_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sti_compositor_ops);
+	return 0;
+}
+
+static struct platform_driver sti_compositor_driver = {
+	.driver = {
+		.name = "sti-compositor",
+		.owner = THIS_MODULE,
+		.of_match_table = compositor_of_match,
+	},
+	.probe = sti_compositor_probe,
+	.remove = sti_compositor_remove,
+};
+
+module_platform_driver(sti_compositor_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_compositor.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_compositor.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_compositor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_compositor.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_COMPOSITOR_H_
+#define _STI_COMPOSITOR_H_
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+
+#include "sti_layer.h"
+#include "sti_mixer.h"
+
+#define WAIT_NEXT_VSYNC_MS      50 /*ms*/
+
+#define STI_MAX_LAYER 8
+#define STI_MAX_MIXER 2
+
+enum sti_compositor_subdev_type {
+	STI_MIXER_MAIN_SUBDEV,
+	STI_MIXER_AUX_SUBDEV,
+	STI_GPD_SUBDEV,
+	STI_VID_SUBDEV,
+	STI_CURSOR_SUBDEV,
+};
+
+struct sti_compositor_subdev_descriptor {
+	enum sti_compositor_subdev_type type;
+	int id;
+	unsigned int offset;
+};
+
+/**
+ * STI Compositor data structure
+ *
+ * @nb_subdev: number of subdevices supported by the compositor
+ * @subdev_desc: subdev list description
+ */
+#define MAX_SUBDEV 9
+struct sti_compositor_data {
+	unsigned int nb_subdev;
+	struct sti_compositor_subdev_descriptor subdev_desc[MAX_SUBDEV];
+};
+
+/**
+ * STI Compositor structure
+ *
+ * @dev: driver device
+ * @regs: registers (main)
+ * @data: device data
+ * @clk_compo_main: clock for main compo
+ * @clk_compo_aux: clock for aux compo
+ * @clk_pix_main: pixel clock for main path
+ * @clk_pix_aux: pixel clock for aux path
+ * @rst_main: reset control of the main path
+ * @rst_aux: reset control of the aux path
+ * @mixer: array of mixers
+ * @vtg_main: vtg for main data path
+ * @vtg_aux: vtg for auxillary data path
+ * @layer: array of layers
+ * @nb_mixers: number of mixers for this compositor
+ * @nb_layers: number of layers (GDP,VID,...) for this compositor
+ * @enable: true if compositor is enable else false
+ * @vtg_vblank_nb: callback for VTG VSYNC notification
+ */
+struct sti_compositor {
+	struct device *dev;
+	void __iomem *regs;
+	struct sti_compositor_data data;
+	struct clk *clk_compo_main;
+	struct clk *clk_compo_aux;
+	struct clk *clk_pix_main;
+	struct clk *clk_pix_aux;
+	struct reset_control *rst_main;
+	struct reset_control *rst_aux;
+	struct sti_mixer *mixer[STI_MAX_MIXER];
+	struct sti_vtg *vtg_main;
+	struct sti_vtg *vtg_aux;
+	struct sti_layer *layer[STI_MAX_LAYER];
+	int nb_mixers;
+	int nb_layers;
+	bool enable;
+	struct notifier_block vtg_vblank_nb;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_crtc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_crtc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_crtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_crtc.h"
+#include "sti_vtg.h"
+
+static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	DRM_DEBUG_KMS("\n");
+}
+
+static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+
+	compo->enable = true;
+
+	/* Prepare and enable the compo IP clock */
+	if (mixer->id == STI_MIXER_MAIN) {
+		if (clk_prepare_enable(compo->clk_compo_main))
+			DRM_INFO("Failed to prepare/enable compo_main clk\n");
+	} else {
+		if (clk_prepare_enable(compo->clk_compo_aux))
+			DRM_INFO("Failed to prepare/enable compo_aux clk\n");
+	}
+}
+
+static void sti_drm_crtc_commit(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct sti_layer *layer;
+
+	if ((!mixer || !compo)) {
+		DRM_ERROR("Can not find mixer or compositor)\n");
+		return;
+	}
+
+	/* get GDP which is reserved to the CRTC FB */
+	layer = to_sti_layer(crtc->primary);
+	if (layer)
+		sti_layer_commit(layer);
+	else
+		DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");
+
+	/* Enable layer on mixer */
+	if (sti_mixer_set_layer_status(mixer, layer, true))
+		DRM_ERROR("Can not enable layer at mixer\n");
+}
+
+static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+				    const struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	/* accept the provided drm_display_mode, do not fix it up */
+	return true;
+}
+
+static int
+sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		      struct drm_display_mode *adjusted_mode, int x, int y,
+		      struct drm_framebuffer *old_fb)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct sti_layer *layer;
+	struct clk *clk;
+	int rate = mode->clock * 1000;
+	int res;
+	unsigned int w, h;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      crtc->primary->fb->base.id, mode->base.id, mode->name);
+
+	DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
+		      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);
+
+	/* Set rate and prepare/enable pixel clock */
+	if (mixer->id == STI_MIXER_MAIN)
+		clk = compo->clk_pix_main;
+	else
+		clk = compo->clk_pix_aux;
+
+	res = clk_set_rate(clk, rate);
+	if (res < 0) {
+		DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
+		return -EINVAL;
+	}
+	if (clk_prepare_enable(clk)) {
+		DRM_ERROR("Failed to prepare/enable pix clk\n");
+		return -EINVAL;
+	}
+
+	sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux, &crtc->mode);
+
+	/* a GDP is reserved to the CRTC FB */
+	layer = to_sti_layer(crtc->primary);
+	if (!layer) {
+		DRM_ERROR("Can not find GDP0)\n");
+		return -EINVAL;
+	}
+
+	/* copy the mode data adjusted by mode_fixup() into crtc->mode
+	 * so that hardware can be set to proper mode
+	 */
+	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
+
+	res = sti_mixer_set_layer_depth(mixer, layer);
+	if (res) {
+		DRM_ERROR("Can not set layer depth\n");
+		return -EINVAL;
+	}
+	res = sti_mixer_active_video_area(mixer, &crtc->mode);
+	if (res) {
+		DRM_ERROR("Can not set active video area\n");
+		return -EINVAL;
+	}
+
+	w = crtc->primary->fb->width - x;
+	h = crtc->primary->fb->height - y;
+
+	return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
+			mixer->id, 0, 0, w, h, x, y, w, h);
+}
+
+static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+				      struct drm_framebuffer *old_fb)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct sti_layer *layer;
+	unsigned int w, h;
+	int ret;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      crtc->primary->fb->base.id, x, y);
+
+	/* GDP is reserved to the CRTC FB */
+	layer = to_sti_layer(crtc->primary);
+	if (!layer) {
+		DRM_ERROR("Can not find GDP0)\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	w = crtc->primary->fb->width - crtc->x;
+	h = crtc->primary->fb->height - crtc->y;
+
+	ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
+				mixer->id, 0, 0, w, h,
+				crtc->x, crtc->y, w, h);
+	if (ret) {
+		DRM_ERROR("Can not prepare layer\n");
+		goto out;
+	}
+
+	sti_drm_crtc_commit(crtc);
+out:
+	return ret;
+}
+
+static void sti_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+	/* do nothing */
+}
+
+static void sti_drm_crtc_disable(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	struct device *dev = mixer->dev;
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	struct sti_layer *layer;
+
+	if (!compo->enable)
+		return;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
+
+	/* Disable Background */
+	sti_mixer_set_background_status(mixer, false);
+
+	/* Disable GDP */
+	layer = to_sti_layer(crtc->primary);
+	if (!layer) {
+		DRM_ERROR("Cannot find GDP0\n");
+		return;
+	}
+
+	/* Disable layer at mixer level */
+	if (sti_mixer_set_layer_status(mixer, layer, false))
+		DRM_ERROR("Can not disable %s layer at mixer\n",
+				sti_layer_to_str(layer));
+
+	/* Wait a while to be sure that a Vsync event is received */
+	msleep(WAIT_NEXT_VSYNC_MS);
+
+	/* Then disable layer itself */
+	sti_layer_disable(layer);
+
+	drm_vblank_off(crtc->dev, mixer->id);
+
+	/* Disable pixel clock and compo IP clocks */
+	if (mixer->id == STI_MIXER_MAIN) {
+		clk_disable_unprepare(compo->clk_pix_main);
+		clk_disable_unprepare(compo->clk_compo_main);
+	} else {
+		clk_disable_unprepare(compo->clk_pix_aux);
+		clk_disable_unprepare(compo->clk_compo_aux);
+	}
+
+	compo->enable = false;
+}
+
+static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
+	.dpms = sti_drm_crtc_dpms,
+	.prepare = sti_drm_crtc_prepare,
+	.commit = sti_drm_crtc_commit,
+	.mode_fixup = sti_drm_crtc_mode_fixup,
+	.mode_set = sti_drm_crtc_mode_set,
+	.mode_set_base = sti_drm_crtc_mode_set_base,
+	.load_lut = sti_drm_crtc_load_lut,
+	.disable = sti_drm_crtc_disable,
+};
+
+static int sti_drm_crtc_page_flip(struct drm_crtc *crtc,
+				  struct drm_framebuffer *fb,
+				  struct drm_pending_vblank_event *event,
+				  uint32_t page_flip_flags)
+{
+	struct drm_device *drm_dev = crtc->dev;
+	struct drm_framebuffer *old_fb;
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	unsigned long flags;
+	int ret;
+
+	DRM_DEBUG_KMS("fb %d --> fb %d\n",
+			crtc->primary->fb->base.id, fb->base.id);
+
+	mutex_lock(&drm_dev->struct_mutex);
+
+	old_fb = crtc->primary->fb;
+	crtc->primary->fb = fb;
+	ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+	if (ret) {
+		DRM_ERROR("failed\n");
+		crtc->primary->fb = old_fb;
+		goto out;
+	}
+
+	if (event) {
+		event->pipe = mixer->id;
+
+		ret = drm_vblank_get(drm_dev, event->pipe);
+		if (ret) {
+			DRM_ERROR("Cannot get vblank\n");
+			goto out;
+		}
+
+		spin_lock_irqsave(&drm_dev->event_lock, flags);
+		if (mixer->pending_event) {
+			drm_vblank_put(drm_dev, event->pipe);
+			ret = -EBUSY;
+		} else {
+			mixer->pending_event = event;
+		}
+		spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+	}
+out:
+	mutex_unlock(&drm_dev->struct_mutex);
+	return ret;
+}
+
+static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("\n");
+	drm_crtc_cleanup(crtc);
+}
+
+static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
+				     struct drm_property *property,
+				     uint64_t val)
+{
+	DRM_DEBUG_KMS("\n");
+	return 0;
+}
+
+int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
+			   unsigned long event, void *data)
+{
+	struct drm_device *drm_dev;
+	struct sti_compositor *compo =
+		container_of(nb, struct sti_compositor, vtg_vblank_nb);
+	int *crtc = data;
+	unsigned long flags;
+	struct sti_drm_private *priv;
+
+	drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
+	priv = drm_dev->dev_private;
+
+	if ((event != VTG_TOP_FIELD_EVENT) &&
+	    (event != VTG_BOTTOM_FIELD_EVENT)) {
+		DRM_ERROR("unknown event: %lu\n", event);
+		return -EINVAL;
+	}
+
+	drm_handle_vblank(drm_dev, *crtc);
+
+	spin_lock_irqsave(&drm_dev->event_lock, flags);
+	if (compo->mixer[*crtc]->pending_event) {
+		drm_send_vblank_event(drm_dev, -1,
+				compo->mixer[*crtc]->pending_event);
+		drm_vblank_put(drm_dev, *crtc);
+		compo->mixer[*crtc]->pending_event = NULL;
+	}
+	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+
+	return 0;
+}
+
+int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct sti_drm_private *dev_priv = dev->dev_private;
+	struct sti_compositor *compo = dev_priv->compo;
+	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+
+	if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux,
+			vtg_vblank_nb, crtc)) {
+		DRM_ERROR("Cannot register VTG notifier\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);
+
+void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct sti_drm_private *priv = dev->dev_private;
+	struct sti_compositor *compo = priv->compo;
+	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+	unsigned long flags;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
+		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
+
+	/* free the resources of the pending requests */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (compo->mixer[crtc]->pending_event) {
+		drm_vblank_put(dev, crtc);
+		compo->mixer[crtc]->pending_event = NULL;
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+}
+EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
+
+static struct drm_crtc_funcs sti_crtc_funcs = {
+	.set_config = drm_crtc_helper_set_config,
+	.page_flip = sti_drm_crtc_page_flip,
+	.destroy = sti_drm_crtc_destroy,
+	.set_property = sti_drm_crtc_set_property,
+};
+
+bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+
+	if (mixer->id == STI_MIXER_MAIN)
+		return true;
+
+	return false;
+}
+
+int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+		struct drm_plane *primary, struct drm_plane *cursor)
+{
+	struct drm_crtc *crtc = &mixer->drm_crtc;
+	int res;
+
+	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
+			&sti_crtc_funcs);
+	if (res) {
+		DRM_ERROR("Can not initialze CRTC\n");
+		return -EINVAL;
+	}
+
+	drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
+
+	DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
+			 crtc->base.id, sti_mixer_to_str(mixer));
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_crtc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_crtc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_crtc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_CRTC_H_
+#define _STI_DRM_CRTC_H_
+
+#include <drm/drmP.h>
+
+struct sti_mixer;
+
+int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+		struct drm_plane *primary, struct drm_plane *cursor);
+int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
+		unsigned long event, void *data);
+bool sti_drm_crtc_is_main(struct drm_crtc *drm_crtc);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/component.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "sti_drm_drv.h"
+#include "sti_drm_crtc.h"
+
+#define DRIVER_NAME	"sti"
+#define DRIVER_DESC	"STMicroelectronics SoC DRM"
+#define DRIVER_DATE	"20140601"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+#define STI_MAX_FB_HEIGHT	4096
+#define STI_MAX_FB_WIDTH	4096
+
+static struct drm_mode_config_funcs sti_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+};
+
+static void sti_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	/*
+	 * set max width and height as default value.
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
+	dev->mode_config.max_height = STI_MAX_FB_WIDTH;
+
+	dev->mode_config.funcs = &sti_drm_mode_config_funcs;
+}
+
+static int sti_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	struct sti_drm_private *private;
+	int ret;
+
+	private = kzalloc(sizeof(struct sti_drm_private), GFP_KERNEL);
+	if (!private) {
+		DRM_ERROR("Failed to allocate private\n");
+		return -ENOMEM;
+	}
+	dev->dev_private = (void *)private;
+	private->drm_dev = dev;
+
+	drm_mode_config_init(dev);
+	drm_kms_helper_poll_init(dev);
+
+	sti_drm_mode_config_init(dev);
+
+	ret = component_bind_all(dev->dev, dev);
+	if (ret)
+		return ret;
+
+	drm_helper_disable_unused_functions(dev);
+
+#ifdef CONFIG_DRM_STI_FBDEV
+	drm_fbdev_cma_init(dev, 32,
+		   dev->mode_config.num_crtc,
+		   dev->mode_config.num_connector);
+#endif
+	return 0;
+}
+
+static const struct file_operations sti_drm_driver_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.mmap = drm_gem_cma_mmap,
+	.poll = drm_poll,
+	.read = drm_read,
+	.unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.release = drm_release,
+};
+
+static struct dma_buf *sti_drm_gem_prime_export(struct drm_device *dev,
+						struct drm_gem_object *obj,
+						int flags)
+{
+	/* we want to be able to write in mmapped buffer */
+	flags |= O_RDWR;
+	return drm_gem_prime_export(dev, obj, flags);
+}
+
+static struct drm_driver sti_drm_driver = {
+	.driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
+	    DRIVER_GEM | DRIVER_PRIME,
+	.load = sti_drm_load,
+	.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,
+	.fops = &sti_drm_driver_fops,
+
+	.get_vblank_counter = drm_vblank_count,
+	.enable_vblank = sti_drm_crtc_enable_vblank,
+	.disable_vblank = sti_drm_crtc_disable_vblank,
+
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = sti_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,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int sti_drm_bind(struct device *dev)
+{
+	return drm_platform_init(&sti_drm_driver, to_platform_device(dev));
+}
+
+static void sti_drm_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops sti_drm_ops = {
+	.bind = sti_drm_bind,
+	.unbind = sti_drm_unbind,
+};
+
+static int sti_drm_master_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->parent->of_node;
+	struct device_node *child_np;
+	struct component_match *match = NULL;
+
+	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+
+	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);
+		child_np = of_get_next_available_child(node, child_np);
+	}
+
+	return component_master_add_with_match(dev, &sti_drm_ops, match);
+}
+
+static int sti_drm_master_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &sti_drm_ops);
+	return 0;
+}
+
+static struct platform_driver sti_drm_master_driver = {
+	.probe = sti_drm_master_probe,
+	.remove = sti_drm_master_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME "__master",
+	},
+};
+
+static int sti_drm_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct platform_device *master;
+
+	of_platform_populate(node, NULL, NULL, dev);
+
+	platform_driver_register(&sti_drm_master_driver);
+	master = platform_device_register_resndata(dev,
+			DRIVER_NAME "__master", -1,
+			NULL, 0, NULL, 0);
+	if (IS_ERR(master))
+               return PTR_ERR(master);
+
+	platform_set_drvdata(pdev, master);
+	return 0;
+}
+
+static int sti_drm_platform_remove(struct platform_device *pdev)
+{
+	struct platform_device *master = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(&pdev->dev);
+	platform_device_unregister(master);
+	platform_driver_unregister(&sti_drm_master_driver);
+	return 0;
+}
+
+static const struct of_device_id sti_drm_dt_ids[] = {
+	{ .compatible = "st,sti-display-subsystem", },
+	{ /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, sti_drm_dt_ids);
+
+static struct platform_driver sti_drm_platform_driver = {
+	.probe = sti_drm_platform_probe,
+	.remove = sti_drm_platform_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+		.of_match_table = sti_drm_dt_ids,
+	},
+};
+
+module_platform_driver(sti_drm_platform_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_DRV_H_
+#define _STI_DRM_DRV_H_
+
+#include <drm/drmP.h>
+
+struct sti_compositor;
+struct sti_tvout;
+
+/**
+ * STI drm private structure
+ * This structure is stored as private in the drm_device
+ *
+ * @compo:                 compositor
+ * @plane_zorder_property: z-order property for CRTC planes
+ * @drm_dev:               drm device
+ */
+struct sti_drm_private {
+	struct sti_compositor *compo;
+	struct drm_property *plane_zorder_property;
+	struct drm_device *drm_dev;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_plane.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_plane.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_plane.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_plane.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include "sti_compositor.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_plane.h"
+#include "sti_vtg.h"
+
+enum sti_layer_desc sti_layer_default_zorder[] = {
+	STI_GDP_0,
+	STI_VID_0,
+	STI_GDP_1,
+	STI_VID_1,
+	STI_GDP_2,
+	STI_GDP_3,
+};
+
+/* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
+
+static int
+sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		     struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		     unsigned int crtc_w, unsigned int crtc_h,
+		     uint32_t src_x, uint32_t src_y,
+		     uint32_t src_w, uint32_t src_h)
+{
+	struct sti_layer *layer = to_sti_layer(plane);
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+	int res;
+
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s) drm fb:%d\n",
+		      crtc->base.id, sti_mixer_to_str(mixer),
+		      plane->base.id, sti_layer_to_str(layer), fb->base.id);
+	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
+
+	res = sti_mixer_set_layer_depth(mixer, layer);
+	if (res) {
+		DRM_ERROR("Can not set layer depth\n");
+		return res;
+	}
+
+	/* src_x are in 16.16 format. */
+	res = sti_layer_prepare(layer, fb, &crtc->mode, mixer->id,
+			crtc_x, crtc_y, crtc_w, crtc_h,
+			src_x >> 16, src_y >> 16,
+			src_w >> 16, src_h >> 16);
+	if (res) {
+		DRM_ERROR("Layer prepare failed\n");
+		return res;
+	}
+
+	res = sti_layer_commit(layer);
+	if (res) {
+		DRM_ERROR("Layer commit failed\n");
+		return res;
+	}
+
+	res = sti_mixer_set_layer_status(mixer, layer, true);
+	if (res) {
+		DRM_ERROR("Can not enable layer at mixer\n");
+		return res;
+	}
+
+	return 0;
+}
+
+static int sti_drm_disable_plane(struct drm_plane *plane)
+{
+	struct sti_layer *layer;
+	struct sti_mixer *mixer;
+	int lay_res, mix_res;
+
+	if (!plane->crtc) {
+		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
+		return 0;
+	}
+	layer = to_sti_layer(plane);
+	mixer = to_sti_mixer(plane->crtc);
+
+	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+			plane->crtc->base.id, sti_mixer_to_str(mixer),
+			plane->base.id, sti_layer_to_str(layer));
+
+	/* Disable layer at mixer level */
+	mix_res = sti_mixer_set_layer_status(mixer, layer, false);
+	if (mix_res)
+		DRM_ERROR("Can not disable layer at mixer\n");
+
+	/* Wait a while to be sure that a Vsync event is received */
+	msleep(WAIT_NEXT_VSYNC_MS);
+
+	/* Then disable layer itself */
+	lay_res = sti_layer_disable(layer);
+	if (lay_res)
+		DRM_ERROR("Layer disable failed\n");
+
+	if (lay_res || mix_res)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void sti_drm_plane_destroy(struct drm_plane *plane)
+{
+	DRM_DEBUG_DRIVER("\n");
+
+	sti_drm_disable_plane(plane);
+	drm_plane_cleanup(plane);
+}
+
+static int sti_drm_plane_set_property(struct drm_plane *plane,
+				      struct drm_property *property,
+				      uint64_t val)
+{
+	struct drm_device *dev = plane->dev;
+	struct sti_drm_private *private = dev->dev_private;
+	struct sti_layer *layer = to_sti_layer(plane);
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (property == private->plane_zorder_property) {
+		layer->zorder = val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct drm_plane_funcs sti_drm_plane_funcs = {
+	.update_plane = sti_drm_update_plane,
+	.disable_plane = sti_drm_disable_plane,
+	.destroy = sti_drm_plane_destroy,
+	.set_property = sti_drm_plane_set_property,
+};
+
+static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
+						 uint64_t default_val)
+{
+	struct drm_device *dev = plane->dev;
+	struct sti_drm_private *private = dev->dev_private;
+	struct drm_property *prop;
+	struct sti_layer *layer = to_sti_layer(plane);
+
+	prop = private->plane_zorder_property;
+	if (!prop) {
+		prop = drm_property_create_range(dev, 0, "zpos", 0,
+						 GAM_MIXER_NB_DEPTH_LEVEL - 1);
+		if (!prop)
+			return;
+
+		private->plane_zorder_property = prop;
+	}
+
+	drm_object_attach_property(&plane->base, prop, default_val);
+	layer->zorder = default_val;
+}
+
+struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
+				     struct sti_layer *layer,
+				     unsigned int possible_crtcs,
+				     enum drm_plane_type type)
+{
+	int err, i;
+	uint64_t default_zorder = 0;
+
+	err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
+			     &sti_drm_plane_funcs,
+			     sti_layer_get_formats(layer),
+			     sti_layer_get_nb_formats(layer), type);
+	if (err) {
+		DRM_ERROR("Failed to initialize plane\n");
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
+		if (sti_layer_default_zorder[i] == layer->desc)
+			break;
+
+	default_zorder = i;
+
+	if (type == DRM_PLANE_TYPE_OVERLAY)
+		sti_drm_plane_attach_zorder_property(&layer->plane,
+				default_zorder);
+
+	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
+			 layer->plane.base.id,
+			 sti_layer_to_str(layer), default_zorder);
+
+	return &layer->plane;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_plane.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_plane.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_drm_plane.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_drm_plane.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_PLANE_H_
+#define _STI_DRM_PLANE_H_
+
+#include <drm/drmP.h>
+
+struct sti_layer;
+
+struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
+		struct sti_layer *layer,
+		unsigned int possible_crtcs,
+		enum drm_plane_type type);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_gdp.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_gdp.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_gdp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_gdp.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
+#include "sti_compositor.h"
+#include "sti_gdp.h"
+#include "sti_layer.h"
+#include "sti_vtg.h"
+
+#define ENA_COLOR_FILL  BIT(8)
+#define WAIT_NEXT_VSYNC BIT(31)
+
+/* GDP color formats */
+#define GDP_RGB565      0x00
+#define GDP_RGB888      0x01
+#define GDP_RGB888_32   0x02
+#define GDP_ARGB8565    0x04
+#define GDP_ARGB8888    0x05
+#define GDP_ARGB1555    0x06
+#define GDP_ARGB4444    0x07
+#define GDP_CLUT8       0x0B
+#define GDP_YCBR888     0x10
+#define GDP_YCBR422R    0x12
+#define GDP_AYCBR8888   0x15
+
+#define GAM_GDP_CTL_OFFSET      0x00
+#define GAM_GDP_AGC_OFFSET      0x04
+#define GAM_GDP_VPO_OFFSET      0x0C
+#define GAM_GDP_VPS_OFFSET      0x10
+#define GAM_GDP_PML_OFFSET      0x14
+#define GAM_GDP_PMP_OFFSET      0x18
+#define GAM_GDP_SIZE_OFFSET     0x1C
+#define GAM_GDP_NVN_OFFSET      0x24
+#define GAM_GDP_KEY1_OFFSET     0x28
+#define GAM_GDP_KEY2_OFFSET     0x2C
+#define GAM_GDP_PPT_OFFSET      0x34
+#define GAM_GDP_CML_OFFSET      0x3C
+#define GAM_GDP_MST_OFFSET      0x68
+
+#define GAM_GDP_ALPHARANGE_255  BIT(5)
+#define GAM_GDP_AGC_FULL_RANGE  0x00808080
+#define GAM_GDP_PPT_IGNORE      (BIT(1) | BIT(0))
+#define GAM_GDP_SIZE_MAX        0x7FF
+
+#define GDP_NODE_NB_BANK	2
+#define GDP_NODE_PER_FIELD	2
+
+struct sti_gdp_node {
+	u32 gam_gdp_ctl;
+	u32 gam_gdp_agc;
+	u32 reserved1;
+	u32 gam_gdp_vpo;
+	u32 gam_gdp_vps;
+	u32 gam_gdp_pml;
+	u32 gam_gdp_pmp;
+	u32 gam_gdp_size;
+	u32 reserved2;
+	u32 gam_gdp_nvn;
+	u32 gam_gdp_key1;
+	u32 gam_gdp_key2;
+	u32 reserved3;
+	u32 gam_gdp_ppt;
+	u32 reserved4;
+	u32 gam_gdp_cml;
+};
+
+struct sti_gdp_node_list {
+	struct sti_gdp_node *top_field;
+	struct sti_gdp_node *btm_field;
+};
+
+/**
+ * STI GDP structure
+ *
+ * @layer:		layer structure
+ * @clk_pix:            pixel clock for the current gdp
+ * @vtg_field_nb:       callback for VTG FIELD (top or bottom) notification
+ * @is_curr_top:        true if the current node processed is the top field
+ * @node_list:		array of node list
+ */
+struct sti_gdp {
+	struct sti_layer layer;
+	struct clk *clk_pix;
+	struct notifier_block vtg_field_nb;
+	bool is_curr_top;
+	struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK];
+};
+
+#define to_sti_gdp(x) container_of(x, struct sti_gdp, layer)
+
+static const uint32_t gdp_supported_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_AYUV,
+	DRM_FORMAT_YUV444,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_C8,
+};
+
+static const uint32_t *sti_gdp_get_formats(struct sti_layer *layer)
+{
+	return gdp_supported_formats;
+}
+
+static unsigned int sti_gdp_get_nb_formats(struct sti_layer *layer)
+{
+	return ARRAY_SIZE(gdp_supported_formats);
+}
+
+static int sti_gdp_fourcc2format(int fourcc)
+{
+	switch (fourcc) {
+	case DRM_FORMAT_XRGB8888:
+		return GDP_RGB888_32;
+	case DRM_FORMAT_ARGB8888:
+		return GDP_ARGB8888;
+	case DRM_FORMAT_ARGB4444:
+		return GDP_ARGB4444;
+	case DRM_FORMAT_ARGB1555:
+		return GDP_ARGB1555;
+	case DRM_FORMAT_RGB565:
+		return GDP_RGB565;
+	case DRM_FORMAT_RGB888:
+		return GDP_RGB888;
+	case DRM_FORMAT_AYUV:
+		return GDP_AYCBR8888;
+	case DRM_FORMAT_YUV444:
+		return GDP_YCBR888;
+	case DRM_FORMAT_VYUY:
+		return GDP_YCBR422R;
+	case DRM_FORMAT_C8:
+		return GDP_CLUT8;
+	}
+	return -1;
+}
+
+static int sti_gdp_get_alpharange(int format)
+{
+	switch (format) {
+	case GDP_ARGB8565:
+	case GDP_ARGB8888:
+	case GDP_AYCBR8888:
+		return GAM_GDP_ALPHARANGE_255;
+	}
+	return 0;
+}
+
+/**
+ * sti_gdp_get_free_nodes
+ * @layer: gdp layer
+ *
+ * Look for a GDP node list that is not currently read by the HW.
+ *
+ * RETURNS:
+ * Pointer to the free GDP node list
+ */
+static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
+{
+	int hw_nvn;
+	void *virt_nvn;
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	unsigned int i;
+
+	hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+	if (!hw_nvn)
+		goto end;
+
+	virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn);
+
+	for (i = 0; i < GDP_NODE_NB_BANK; i++)
+		if ((virt_nvn != gdp->node_list[i].btm_field) &&
+		    (virt_nvn != gdp->node_list[i].top_field))
+			return &gdp->node_list[i];
+
+	/* in hazardious cases restart with the first node */
+	DRM_ERROR("inconsistent NVN for %s: 0x%08X\n",
+			sti_layer_to_str(layer), hw_nvn);
+
+end:
+	return &gdp->node_list[0];
+}
+
+/**
+ * sti_gdp_get_current_nodes
+ * @layer: GDP layer
+ *
+ * Look for GDP nodes that are currently read by the HW.
+ *
+ * RETURNS:
+ * Pointer to the current GDP node list
+ */
+static
+struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
+{
+	int hw_nvn;
+	void *virt_nvn;
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	unsigned int i;
+
+	hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+	if (!hw_nvn)
+		goto end;
+
+	virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn);
+
+	for (i = 0; i < GDP_NODE_NB_BANK; i++)
+		if ((virt_nvn == gdp->node_list[i].btm_field) ||
+				(virt_nvn == gdp->node_list[i].top_field))
+			return &gdp->node_list[i];
+
+end:
+	DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n",
+				hw_nvn, sti_layer_to_str(layer));
+
+	return NULL;
+}
+
+/**
+ * sti_gdp_prepare_layer
+ * @lay: gdp layer
+ * @first_prepare: true if it is the first time this function is called
+ *
+ * Update the free GDP node list according to the layer properties.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
+{
+	struct sti_gdp_node_list *list;
+	struct sti_gdp_node *top_field, *btm_field;
+	struct drm_display_mode *mode = layer->mode;
+	struct device *dev = layer->dev;
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct sti_compositor *compo = dev_get_drvdata(dev);
+	int format;
+	unsigned int depth, bpp;
+	int rate = mode->clock * 1000;
+	int res;
+	u32 ydo, xdo, yds, xds;
+
+	list = sti_gdp_get_free_nodes(layer);
+	top_field = list->top_field;
+	btm_field = list->btm_field;
+
+	dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
+			sti_layer_to_str(layer), top_field, btm_field);
+
+	/* Build the top field from layer params */
+	top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
+	top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
+	format = sti_gdp_fourcc2format(layer->format);
+	if (format == -1) {
+		DRM_ERROR("Format not supported by GDP %.4s\n",
+			  (char *)&layer->format);
+		return 1;
+	}
+	top_field->gam_gdp_ctl |= format;
+	top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
+	top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
+
+	/* pixel memory location */
+	drm_fb_get_bpp_depth(layer->format, &depth, &bpp);
+	top_field->gam_gdp_pml = (u32) layer->paddr + layer->offsets[0];
+	top_field->gam_gdp_pml += layer->src_x * (bpp >> 3);
+	top_field->gam_gdp_pml += layer->src_y * layer->pitches[0];
+
+	/* input parameters */
+	top_field->gam_gdp_pmp = layer->pitches[0];
+	top_field->gam_gdp_size =
+	    clamp_val(layer->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
+	    clamp_val(layer->src_w, 0, GAM_GDP_SIZE_MAX);
+
+	/* output parameters */
+	ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
+	yds = sti_vtg_get_line_number(*mode, layer->dst_y + layer->dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, layer->dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, layer->dst_x + layer->dst_w - 1);
+	top_field->gam_gdp_vpo = (ydo << 16) | xdo;
+	top_field->gam_gdp_vps = (yds << 16) | xds;
+
+	/* Same content and chained together */
+	memcpy(btm_field, top_field, sizeof(*btm_field));
+	top_field->gam_gdp_nvn = virt_to_dma(dev, btm_field);
+	btm_field->gam_gdp_nvn = virt_to_dma(dev, top_field);
+
+	/* Interlaced mode */
+	if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE)
+		btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
+		    layer->pitches[0];
+
+	if (first_prepare) {
+		/* Register gdp callback */
+		if (sti_vtg_register_client(layer->mixer_id == STI_MIXER_MAIN ?
+				compo->vtg_main : compo->vtg_aux,
+				&gdp->vtg_field_nb, layer->mixer_id)) {
+			DRM_ERROR("Cannot register VTG notifier\n");
+			return 1;
+		}
+
+		/* Set and enable gdp clock */
+		if (gdp->clk_pix) {
+			res = clk_set_rate(gdp->clk_pix, rate);
+			if (res < 0) {
+				DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
+						rate);
+				return 1;
+			}
+
+			if (clk_prepare_enable(gdp->clk_pix)) {
+				DRM_ERROR("Failed to prepare/enable gdp\n");
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * sti_gdp_commit_layer
+ * @lay: gdp layer
+ *
+ * Update the NVN field of the 'right' field of the current GDP node (being
+ * used by the HW) with the address of the updated ('free') top field GDP node.
+ * - In interlaced mode the 'right' field is the bottom field as we update
+ *   frames starting from their top field
+ * - In progressive mode, we update both bottom and top fields which are
+ *   equal nodes.
+ * At the next VSYNC, the updated node list will be used by the HW.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_commit_layer(struct sti_layer *layer)
+{
+	struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(layer);
+	struct sti_gdp_node *updated_top_node = updated_list->top_field;
+	struct sti_gdp_node *updated_btm_node = updated_list->btm_field;
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	u32 dma_updated_top = virt_to_dma(layer->dev, updated_top_node);
+	u32 dma_updated_btm = virt_to_dma(layer->dev, updated_btm_node);
+	struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer);
+
+	dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
+			sti_layer_to_str(layer),
+			updated_top_node, updated_btm_node);
+	dev_dbg(layer->dev, "Current NVN:0x%X\n",
+		readl(layer->regs + GAM_GDP_NVN_OFFSET));
+	dev_dbg(layer->dev, "Posted buff: %lx current buff: %x\n",
+		(unsigned long)layer->paddr,
+		readl(layer->regs + GAM_GDP_PML_OFFSET));
+
+	if (curr_list == NULL) {
+		/* First update or invalid node should directly write in the
+		 * hw register */
+		DRM_DEBUG_DRIVER("%s first update (or invalid node)",
+				sti_layer_to_str(layer));
+
+		writel(gdp->is_curr_top == true ?
+				dma_updated_btm : dma_updated_top,
+				layer->regs + GAM_GDP_NVN_OFFSET);
+		return 0;
+	}
+
+	if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		if (gdp->is_curr_top == true) {
+			/* Do not update in the middle of the frame, but
+			 * postpone the update after the bottom field has
+			 * been displayed */
+			curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
+		} else {
+			/* Direct update to avoid one frame delay */
+			writel(dma_updated_top,
+				layer->regs + GAM_GDP_NVN_OFFSET);
+		}
+	} else {
+		/* Direct update for progressive to avoid one frame delay */
+		writel(dma_updated_top, layer->regs + GAM_GDP_NVN_OFFSET);
+	}
+
+	return 0;
+}
+
+/**
+ * sti_gdp_disable_layer
+ * @lay: gdp layer
+ *
+ * Disable a GDP.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_disable_layer(struct sti_layer *layer)
+{
+	unsigned int i;
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct sti_compositor *compo = dev_get_drvdata(layer->dev);
+
+	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+
+	/* Set the nodes as 'to be ignored on mixer' */
+	for (i = 0; i < GDP_NODE_NB_BANK; i++) {
+		gdp->node_list[i].top_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
+		gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
+	}
+
+	if (sti_vtg_unregister_client(layer->mixer_id == STI_MIXER_MAIN ?
+			compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb))
+		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
+
+	if (gdp->clk_pix)
+		clk_disable_unprepare(gdp->clk_pix);
+
+	return 0;
+}
+
+/**
+ * sti_gdp_field_cb
+ * @nb: notifier block
+ * @event: event message
+ * @data: private data
+ *
+ * Handle VTG top field and bottom field event.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+int sti_gdp_field_cb(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	struct sti_gdp *gdp = container_of(nb, struct sti_gdp, vtg_field_nb);
+
+	switch (event) {
+	case VTG_TOP_FIELD_EVENT:
+		gdp->is_curr_top = true;
+		break;
+	case VTG_BOTTOM_FIELD_EVENT:
+		gdp->is_curr_top = false;
+		break;
+	default:
+		DRM_ERROR("unsupported event: %lu\n", event);
+		break;
+	}
+
+	return 0;
+}
+
+static void sti_gdp_init(struct sti_layer *layer)
+{
+	struct sti_gdp *gdp = to_sti_gdp(layer);
+	struct device_node *np = layer->dev->of_node;
+	dma_addr_t dma;
+	void *base;
+	unsigned int i, size;
+
+	/* Allocate all the nodes within a single memory page */
+	size = sizeof(struct sti_gdp_node) *
+	    GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK;
+
+	base = dma_alloc_writecombine(layer->dev,
+			size, &dma, GFP_KERNEL | GFP_DMA);
+	if (!base) {
+		DRM_ERROR("Failed to allocate memory for GDP node\n");
+		return;
+	}
+	memset(base, 0, size);
+
+	for (i = 0; i < GDP_NODE_NB_BANK; i++) {
+		if (virt_to_dma(layer->dev, base) & 0xF) {
+			DRM_ERROR("Mem alignment failed\n");
+			return;
+		}
+		gdp->node_list[i].top_field = base;
+		DRM_DEBUG_DRIVER("node[%d].top_field=%p\n", i, base);
+		base += sizeof(struct sti_gdp_node);
+
+		if (virt_to_dma(layer->dev, base) & 0xF) {
+			DRM_ERROR("Mem alignment failed\n");
+			return;
+		}
+		gdp->node_list[i].btm_field = base;
+		DRM_DEBUG_DRIVER("node[%d].btm_field=%p\n", i, base);
+		base += sizeof(struct sti_gdp_node);
+	}
+
+	if (of_device_is_compatible(np, "st,stih407-compositor")) {
+		/* GDP of STiH407 chip have its own pixel clock */
+		char *clk_name;
+
+		switch (layer->desc) {
+		case STI_GDP_0:
+			clk_name = "pix_gdp1";
+			break;
+		case STI_GDP_1:
+			clk_name = "pix_gdp2";
+			break;
+		case STI_GDP_2:
+			clk_name = "pix_gdp3";
+			break;
+		case STI_GDP_3:
+			clk_name = "pix_gdp4";
+			break;
+		default:
+			DRM_ERROR("GDP id not recognized\n");
+			return;
+		}
+
+		gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
+		if (IS_ERR(gdp->clk_pix))
+			DRM_ERROR("Cannot get %s clock\n", clk_name);
+	}
+}
+
+static const struct sti_layer_funcs gdp_ops = {
+	.get_formats = sti_gdp_get_formats,
+	.get_nb_formats = sti_gdp_get_nb_formats,
+	.init = sti_gdp_init,
+	.prepare = sti_gdp_prepare_layer,
+	.commit = sti_gdp_commit_layer,
+	.disable = sti_gdp_disable_layer,
+};
+
+struct sti_layer *sti_gdp_create(struct device *dev, int id)
+{
+	struct sti_gdp *gdp;
+
+	gdp = devm_kzalloc(dev, sizeof(*gdp), GFP_KERNEL);
+	if (!gdp) {
+		DRM_ERROR("Failed to allocate memory for GDP\n");
+		return NULL;
+	}
+
+	gdp->layer.ops = &gdp_ops;
+	gdp->vtg_field_nb.notifier_call = sti_gdp_field_cb;
+
+	return (struct sti_layer *)gdp;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_gdp.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_gdp.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_gdp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_gdp.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_GDP_H_
+#define _STI_GDP_H_
+
+#include <linux/types.h>
+
+struct sti_layer *sti_gdp_create(struct device *dev, int id);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hda.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hda.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hda.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hda.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+/* HDformatter registers */
+#define HDA_ANA_CFG                     0x0000
+#define HDA_ANA_SCALE_CTRL_Y            0x0004
+#define HDA_ANA_SCALE_CTRL_CB           0x0008
+#define HDA_ANA_SCALE_CTRL_CR           0x000C
+#define HDA_ANA_ANC_CTRL                0x0010
+#define HDA_ANA_SRC_Y_CFG               0x0014
+#define HDA_COEFF_Y_PH1_TAP123          0x0018
+#define HDA_COEFF_Y_PH1_TAP456          0x001C
+#define HDA_COEFF_Y_PH2_TAP123          0x0020
+#define HDA_COEFF_Y_PH2_TAP456          0x0024
+#define HDA_COEFF_Y_PH3_TAP123          0x0028
+#define HDA_COEFF_Y_PH3_TAP456          0x002C
+#define HDA_COEFF_Y_PH4_TAP123          0x0030
+#define HDA_COEFF_Y_PH4_TAP456          0x0034
+#define HDA_ANA_SRC_C_CFG               0x0040
+#define HDA_COEFF_C_PH1_TAP123          0x0044
+#define HDA_COEFF_C_PH1_TAP456          0x0048
+#define HDA_COEFF_C_PH2_TAP123          0x004C
+#define HDA_COEFF_C_PH2_TAP456          0x0050
+#define HDA_COEFF_C_PH3_TAP123          0x0054
+#define HDA_COEFF_C_PH3_TAP456          0x0058
+#define HDA_COEFF_C_PH4_TAP123          0x005C
+#define HDA_COEFF_C_PH4_TAP456          0x0060
+#define HDA_SYNC_AWGI                   0x0300
+
+/* HDA_ANA_CFG */
+#define CFG_AWG_ASYNC_EN                BIT(0)
+#define CFG_AWG_ASYNC_HSYNC_MTD         BIT(1)
+#define CFG_AWG_ASYNC_VSYNC_MTD         BIT(2)
+#define CFG_AWG_SYNC_DEL                BIT(3)
+#define CFG_AWG_FLTR_MODE_SHIFT         4
+#define CFG_AWG_FLTR_MODE_MASK          (0xF << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_SD            (0 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_ED            (1 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_HD            (2 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_SYNC_ON_PBPR_MASK           BIT(8)
+#define CFG_PREFILTER_EN_MASK           BIT(9)
+#define CFG_PBPR_SYNC_OFF_SHIFT         16
+#define CFG_PBPR_SYNC_OFF_MASK          (0x7FF << CFG_PBPR_SYNC_OFF_SHIFT)
+#define CFG_PBPR_SYNC_OFF_VAL           0x117 /* Voltage dependent. stiH416 */
+
+/* Default scaling values */
+#define SCALE_CTRL_Y_DFLT               0x00C50256
+#define SCALE_CTRL_CB_DFLT              0x00DB0249
+#define SCALE_CTRL_CR_DFLT              0x00DB0249
+
+/* Video DACs control */
+#define VIDEO_DACS_CONTROL_MASK         0x0FFF
+#define VIDEO_DACS_CONTROL_SYSCFG2535   0x085C /* for stih416 */
+#define DAC_CFG_HD_OFF_SHIFT            5
+#define DAC_CFG_HD_OFF_MASK             (0x7 << DAC_CFG_HD_OFF_SHIFT)
+#define VIDEO_DACS_CONTROL_SYSCFG5072   0x0120 /* for stih407 */
+#define DAC_CFG_HD_HZUVW_OFF_MASK       BIT(1)
+
+
+/* Upsampler values for the alternative 2X Filter */
+#define SAMPLER_COEF_NB                 8
+#define HDA_ANA_SRC_Y_CFG_ALT_2X        0x01130000
+static u32 coef_y_alt_2x[] = {
+	0x00FE83FB, 0x1F900401, 0x00000000, 0x00000000,
+	0x00F408F9, 0x055F7C25, 0x00000000, 0x00000000
+};
+
+#define HDA_ANA_SRC_C_CFG_ALT_2X        0x01750004
+static u32 coef_c_alt_2x[] = {
+	0x001305F7, 0x05274BD0, 0x00000000, 0x00000000,
+	0x0004907C, 0x09C80B9D, 0x00000000, 0x00000000
+};
+
+/* Upsampler values for the 4X Filter */
+#define HDA_ANA_SRC_Y_CFG_4X            0x01ED0005
+#define HDA_ANA_SRC_C_CFG_4X            0x01ED0004
+static u32 coef_yc_4x[] = {
+	0x00FC827F, 0x008FE20B, 0x00F684FC, 0x050F7C24,
+	0x00F4857C, 0x0A1F402E, 0x00FA027F, 0x0E076E1D
+};
+
+/* AWG instructions for some video modes */
+#define AWG_MAX_INST                    64
+
+/* 720p@50 */
+static u32 AWGi_720p_50[] = {
+	0x00000971, 0x00000C26, 0x0000013B, 0x00000CDA,
+	0x00000104, 0x00000E7E, 0x00000E7F, 0x0000013B,
+	0x00000D8E, 0x00000104, 0x00001804, 0x00000971,
+	0x00000C26, 0x0000003B, 0x00000FB4, 0x00000FB5,
+	0x00000104, 0x00001AE8
+};
+
+#define NN_720p_50 ARRAY_SIZE(AWGi_720p_50)
+
+/* 720p@60 */
+static u32 AWGi_720p_60[] = {
+	0x00000971, 0x00000C26, 0x0000013B, 0x00000CDA,
+	0x00000104, 0x00000E7E, 0x00000E7F, 0x0000013B,
+	0x00000C44, 0x00000104, 0x00001804, 0x00000971,
+	0x00000C26, 0x0000003B, 0x00000F0F, 0x00000F10,
+	0x00000104, 0x00001AE8
+};
+
+#define NN_720p_60 ARRAY_SIZE(AWGi_720p_60)
+
+/* 1080p@30 */
+static u32 AWGi_1080p_30[] = {
+	0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+	0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+	0x00000C2A, 0x00000104, 0x00001804, 0x00000971,
+	0x00000C2A, 0x0000003B, 0x00000EBE, 0x00000EBF,
+	0x00000EBF, 0x00000104, 0x00001A2F, 0x00001C4B,
+	0x00001C52
+};
+
+#define NN_1080p_30 ARRAY_SIZE(AWGi_1080p_30)
+
+/* 1080p@25 */
+static u32 AWGi_1080p_25[] = {
+	0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+	0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+	0x00000DE2, 0x00000104, 0x00001804, 0x00000971,
+	0x00000C2A, 0x0000003B, 0x00000F51, 0x00000F51,
+	0x00000F52, 0x00000104, 0x00001A2F, 0x00001C4B,
+	0x00001C52
+};
+
+#define NN_1080p_25 ARRAY_SIZE(AWGi_1080p_25)
+
+/* 1080p@24 */
+static u32 AWGi_1080p_24[] = {
+	0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+	0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+	0x00000E50, 0x00000104, 0x00001804, 0x00000971,
+	0x00000C2A, 0x0000003B, 0x00000F76, 0x00000F76,
+	0x00000F76, 0x00000104, 0x00001A2F, 0x00001C4B,
+	0x00001C52
+};
+
+#define NN_1080p_24 ARRAY_SIZE(AWGi_1080p_24)
+
+/* 720x480p@60 */
+static u32 AWGi_720x480p_60[] = {
+	0x00000904, 0x00000F18, 0x0000013B, 0x00001805,
+	0x00000904, 0x00000C3D, 0x0000003B, 0x00001A06
+};
+
+#define NN_720x480p_60 ARRAY_SIZE(AWGi_720x480p_60)
+
+/* Video mode category */
+enum sti_hda_vid_cat {
+	VID_SD,
+	VID_ED,
+	VID_HD_74M,
+	VID_HD_148M
+};
+
+struct sti_hda_video_config {
+	struct drm_display_mode mode;
+	u32 *awg_instr;
+	int nb_instr;
+	enum sti_hda_vid_cat vid_cat;
+};
+
+/* HD analog supported modes
+ * Interlaced modes may be added when supported by the whole display chain
+ */
+static const struct sti_hda_video_config hda_supported_modes[] = {
+	/* 1080p30 74.250Mhz */
+	{{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_1080p_30, NN_1080p_30, VID_HD_74M},
+	/* 1080p30 74.176Mhz */
+	{{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74176, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_1080p_30, NN_1080p_30, VID_HD_74M},
+	/* 1080p24 74.250Mhz */
+	{{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_1080p_24, NN_1080p_24, VID_HD_74M},
+	/* 1080p24 74.176Mhz */
+	{{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74176, 1920, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_1080p_24, NN_1080p_24, VID_HD_74M},
+	/* 1080p25 74.250Mhz */
+	{{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_1080p_25, NN_1080p_25, VID_HD_74M},
+	/* 720p60 74.250Mhz */
+	{{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
+		   1430, 1650, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_720p_60, NN_720p_60, VID_HD_74M},
+	/* 720p60 74.176Mhz */
+	{{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74176, 1280, 1390,
+		   1430, 1650, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_720p_60, NN_720p_60, VID_HD_74M},
+	/* 720p50 74.250Mhz */
+	{{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
+		   1760, 1980, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+	 AWGi_720p_50, NN_720p_50, VID_HD_74M},
+	/* 720x480p60 27.027Mhz */
+	{{DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27027, 720, 736,
+		   798, 858, 0, 480, 489, 495, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)},
+	 AWGi_720x480p_60, NN_720x480p_60, VID_ED},
+	/* 720x480p60 27.000Mhz */
+	{{DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
+		   798, 858, 0, 480, 489, 495, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)},
+	 AWGi_720x480p_60, NN_720x480p_60, VID_ED}
+};
+
+/**
+ * STI hd analog structure
+ *
+ * @dev: driver device
+ * @drm_dev: pointer to drm device
+ * @mode: current display mode selected
+ * @regs: HD analog register
+ * @video_dacs_ctrl: video DACS control register
+ * @enabled: true if HD analog is enabled else false
+ */
+struct sti_hda {
+	struct device dev;
+	struct drm_device *drm_dev;
+	struct drm_display_mode mode;
+	void __iomem *regs;
+	void __iomem *video_dacs_ctrl;
+	struct clk *clk_pix;
+	struct clk *clk_hddac;
+	bool enabled;
+};
+
+struct sti_hda_connector {
+	struct drm_connector drm_connector;
+	struct drm_encoder *encoder;
+	struct sti_hda *hda;
+};
+
+#define to_sti_hda_connector(x) \
+	container_of(x, struct sti_hda_connector, drm_connector)
+
+static u32 hda_read(struct sti_hda *hda, int offset)
+{
+	return readl(hda->regs + offset);
+}
+
+static void hda_write(struct sti_hda *hda, u32 val, int offset)
+{
+	writel(val, hda->regs + offset);
+}
+
+/**
+ * Search for a video mode in the supported modes table
+ *
+ * @mode: mode being searched
+ * @idx: index of the found mode
+ *
+ * Return true if mode is found
+ */
+static bool hda_get_mode_idx(struct drm_display_mode mode, int *idx)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(hda_supported_modes); i++)
+		if (drm_mode_equal(&hda_supported_modes[i].mode, &mode)) {
+			*idx = i;
+			return true;
+		}
+	return false;
+}
+
+/**
+ * Enable the HD DACS
+ *
+ * @hda: pointer to HD analog structure
+ * @enable: true if HD DACS need to be enabled, else false
+ */
+static void hda_enable_hd_dacs(struct sti_hda *hda, bool enable)
+{
+	u32 mask;
+
+	if (hda->video_dacs_ctrl) {
+		u32 val;
+
+		switch ((u32)hda->video_dacs_ctrl & VIDEO_DACS_CONTROL_MASK) {
+		case VIDEO_DACS_CONTROL_SYSCFG2535:
+			mask = DAC_CFG_HD_OFF_MASK;
+			break;
+		case VIDEO_DACS_CONTROL_SYSCFG5072:
+			mask = DAC_CFG_HD_HZUVW_OFF_MASK;
+			break;
+		default:
+			DRM_INFO("Video DACS control register not supported!");
+			return;
+		}
+
+		val = readl(hda->video_dacs_ctrl);
+		if (enable)
+			val &= ~mask;
+		else
+			val |= mask;
+
+		writel(val, hda->video_dacs_ctrl);
+	}
+}
+
+/**
+ * Configure AWG, writing instructions
+ *
+ * @hda: pointer to HD analog structure
+ * @awg_instr: pointer to AWG instructions table
+ * @nb: nb of AWG instructions
+ */
+static void sti_hda_configure_awg(struct sti_hda *hda, u32 *awg_instr, int nb)
+{
+	unsigned int i;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	for (i = 0; i < nb; i++)
+		hda_write(hda, awg_instr[i], HDA_SYNC_AWGI + i * 4);
+	for (i = nb; i < AWG_MAX_INST; i++)
+		hda_write(hda, 0, HDA_SYNC_AWGI + i * 4);
+}
+
+static void sti_hda_disable(struct drm_bridge *bridge)
+{
+	struct sti_hda *hda = bridge->driver_private;
+	u32 val;
+
+	if (!hda->enabled)
+		return;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* Disable HD DAC and AWG */
+	val = hda_read(hda, HDA_ANA_CFG);
+	val &= ~CFG_AWG_ASYNC_EN;
+	hda_write(hda, val, HDA_ANA_CFG);
+	hda_write(hda, 0, HDA_ANA_ANC_CTRL);
+
+	hda_enable_hd_dacs(hda, false);
+
+	/* Disable/unprepare hda clock */
+	clk_disable_unprepare(hda->clk_hddac);
+	clk_disable_unprepare(hda->clk_pix);
+
+	hda->enabled = false;
+}
+
+static void sti_hda_pre_enable(struct drm_bridge *bridge)
+{
+	struct sti_hda *hda = bridge->driver_private;
+	u32 val, i, mode_idx;
+	u32 src_filter_y, src_filter_c;
+	u32 *coef_y, *coef_c;
+	u32 filter_mode;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (hda->enabled)
+		return;
+
+	/* Prepare/enable clocks */
+	if (clk_prepare_enable(hda->clk_pix))
+		DRM_ERROR("Failed to prepare/enable hda_pix clk\n");
+	if (clk_prepare_enable(hda->clk_hddac))
+		DRM_ERROR("Failed to prepare/enable hda_hddac clk\n");
+
+	if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
+		DRM_ERROR("Undefined mode\n");
+		return;
+	}
+
+	switch (hda_supported_modes[mode_idx].vid_cat) {
+	case VID_HD_148M:
+		DRM_ERROR("Beyond HD analog capabilities\n");
+		return;
+	case VID_HD_74M:
+		/* HD use alternate 2x filter */
+		filter_mode = CFG_AWG_FLTR_MODE_HD;
+		src_filter_y = HDA_ANA_SRC_Y_CFG_ALT_2X;
+		src_filter_c = HDA_ANA_SRC_C_CFG_ALT_2X;
+		coef_y = coef_y_alt_2x;
+		coef_c = coef_c_alt_2x;
+		break;
+	case VID_ED:
+		/* ED uses 4x filter */
+		filter_mode = CFG_AWG_FLTR_MODE_ED;
+		src_filter_y = HDA_ANA_SRC_Y_CFG_4X;
+		src_filter_c = HDA_ANA_SRC_C_CFG_4X;
+		coef_y = coef_yc_4x;
+		coef_c = coef_yc_4x;
+		break;
+	case VID_SD:
+		DRM_ERROR("Not supported\n");
+		return;
+	default:
+		DRM_ERROR("Undefined resolution\n");
+		return;
+	}
+	DRM_DEBUG_DRIVER("Using HDA mode #%d\n", mode_idx);
+
+	/* Enable HD Video DACs */
+	hda_enable_hd_dacs(hda, true);
+
+	/* Configure scaler */
+	hda_write(hda, SCALE_CTRL_Y_DFLT, HDA_ANA_SCALE_CTRL_Y);
+	hda_write(hda, SCALE_CTRL_CB_DFLT, HDA_ANA_SCALE_CTRL_CB);
+	hda_write(hda, SCALE_CTRL_CR_DFLT, HDA_ANA_SCALE_CTRL_CR);
+
+	/* Configure sampler */
+	hda_write(hda , src_filter_y, HDA_ANA_SRC_Y_CFG);
+	hda_write(hda, src_filter_c,  HDA_ANA_SRC_C_CFG);
+	for (i = 0; i < SAMPLER_COEF_NB; i++) {
+		hda_write(hda, coef_y[i], HDA_COEFF_Y_PH1_TAP123 + i * 4);
+		hda_write(hda, coef_c[i], HDA_COEFF_C_PH1_TAP123 + i * 4);
+	}
+
+	/* Configure main HDFormatter */
+	val = 0;
+	val |= (hda->mode.flags & DRM_MODE_FLAG_INTERLACE) ?
+	    0 : CFG_AWG_ASYNC_VSYNC_MTD;
+	val |= (CFG_PBPR_SYNC_OFF_VAL << CFG_PBPR_SYNC_OFF_SHIFT);
+	val |= filter_mode;
+	hda_write(hda, val, HDA_ANA_CFG);
+
+	/* Configure AWG */
+	sti_hda_configure_awg(hda, hda_supported_modes[mode_idx].awg_instr,
+			      hda_supported_modes[mode_idx].nb_instr);
+
+	/* Enable AWG */
+	val = hda_read(hda, HDA_ANA_CFG);
+	val |= CFG_AWG_ASYNC_EN;
+	hda_write(hda, val, HDA_ANA_CFG);
+
+	hda->enabled = true;
+}
+
+static void sti_hda_set_mode(struct drm_bridge *bridge,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	struct sti_hda *hda = bridge->driver_private;
+	u32 mode_idx;
+	int hddac_rate;
+	int ret;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	memcpy(&hda->mode, mode, sizeof(struct drm_display_mode));
+
+	if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
+		DRM_ERROR("Undefined mode\n");
+		return;
+	}
+
+	switch (hda_supported_modes[mode_idx].vid_cat) {
+	case VID_HD_74M:
+		/* HD use alternate 2x filter */
+		hddac_rate = mode->clock * 1000 * 2;
+		break;
+	case VID_ED:
+		/* ED uses 4x filter */
+		hddac_rate = mode->clock * 1000 * 4;
+		break;
+	default:
+		DRM_ERROR("Undefined mode\n");
+		return;
+	}
+
+	/* HD DAC = 148.5Mhz or 108 Mhz */
+	ret = clk_set_rate(hda->clk_hddac, hddac_rate);
+	if (ret < 0)
+		DRM_ERROR("Cannot set rate (%dHz) for hda_hddac clk\n",
+			  hddac_rate);
+
+	/* HDformatter clock = compositor clock */
+	ret = clk_set_rate(hda->clk_pix, mode->clock * 1000);
+	if (ret < 0)
+		DRM_ERROR("Cannot set rate (%dHz) for hda_pix clk\n",
+			  mode->clock * 1000);
+}
+
+static void sti_hda_bridge_nope(struct drm_bridge *bridge)
+{
+	/* do nothing */
+}
+
+static void sti_hda_brigde_destroy(struct drm_bridge *bridge)
+{
+	drm_bridge_cleanup(bridge);
+	kfree(bridge);
+}
+
+static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
+	.pre_enable = sti_hda_pre_enable,
+	.enable = sti_hda_bridge_nope,
+	.disable = sti_hda_disable,
+	.post_disable = sti_hda_bridge_nope,
+	.mode_set = sti_hda_set_mode,
+	.destroy = sti_hda_brigde_destroy,
+};
+
+static int sti_hda_connector_get_modes(struct drm_connector *connector)
+{
+	unsigned int i;
+	int count = 0;
+	struct sti_hda_connector *hda_connector
+		= to_sti_hda_connector(connector);
+	struct sti_hda *hda = hda_connector->hda;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	for (i = 0; i < ARRAY_SIZE(hda_supported_modes); i++) {
+		struct drm_display_mode *mode =
+			drm_mode_duplicate(hda->drm_dev,
+					&hda_supported_modes[i].mode);
+		if (!mode)
+			continue;
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
+		/* the first mode is the preferred mode */
+		if (i == 0)
+			mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+		drm_mode_probed_add(connector, mode);
+		count++;
+	}
+
+	drm_mode_sort(&connector->modes);
+
+	return count;
+}
+
+#define CLK_TOLERANCE_HZ 50
+
+static int sti_hda_connector_mode_valid(struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	int target = mode->clock * 1000;
+	int target_min = target - CLK_TOLERANCE_HZ;
+	int target_max = target + CLK_TOLERANCE_HZ;
+	int result;
+	int idx;
+	struct sti_hda_connector *hda_connector
+		= to_sti_hda_connector(connector);
+	struct sti_hda *hda = hda_connector->hda;
+
+	if (!hda_get_mode_idx(*mode, &idx)) {
+		return MODE_BAD;
+	} else {
+		result = clk_round_rate(hda->clk_pix, target);
+
+		DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
+				 target, result);
+
+		if ((result < target_min) || (result > target_max)) {
+			DRM_DEBUG_DRIVER("hda pixclk=%d not supported\n",
+					 target);
+			return MODE_BAD;
+		}
+	}
+
+	return MODE_OK;
+}
+
+struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
+{
+	struct sti_hda_connector *hda_connector
+		= to_sti_hda_connector(connector);
+
+	/* Best encoder is the one associated during connector creation */
+	return hda_connector->encoder;
+}
+
+static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
+	.get_modes = sti_hda_connector_get_modes,
+	.mode_valid = sti_hda_connector_mode_valid,
+	.best_encoder = sti_hda_best_encoder,
+};
+
+static enum drm_connector_status
+sti_hda_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void sti_hda_connector_destroy(struct drm_connector *connector)
+{
+	struct sti_hda_connector *hda_connector
+		= to_sti_hda_connector(connector);
+
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(hda_connector);
+}
+
+static struct drm_connector_funcs sti_hda_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = sti_hda_connector_detect,
+	.destroy = sti_hda_connector_destroy,
+};
+
+static struct drm_encoder *sti_hda_find_encoder(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
+			return encoder;
+	}
+
+	return NULL;
+}
+
+static int sti_hda_bind(struct device *dev, struct device *master, void *data)
+{
+	struct sti_hda *hda = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	struct drm_encoder *encoder;
+	struct sti_hda_connector *connector;
+	struct drm_connector *drm_connector;
+	struct drm_bridge *bridge;
+	int err;
+
+	/* Set the drm device handle */
+	hda->drm_dev = drm_dev;
+
+	encoder = sti_hda_find_encoder(drm_dev);
+	if (!encoder)
+		return -ENOMEM;
+
+	connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
+	if (!connector)
+		return -ENOMEM;
+
+	connector->hda = hda;
+
+		bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver_private = hda;
+	drm_bridge_init(drm_dev, bridge, &sti_hda_bridge_funcs);
+
+	encoder->bridge = bridge;
+	connector->encoder = encoder;
+
+	drm_connector = (struct drm_connector *)connector;
+
+	drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	drm_connector_init(drm_dev, drm_connector,
+			&sti_hda_connector_funcs, DRM_MODE_CONNECTOR_Component);
+	drm_connector_helper_add(drm_connector,
+			&sti_hda_connector_helper_funcs);
+
+	err = drm_connector_register(drm_connector);
+	if (err)
+		goto err_connector;
+
+	err = drm_mode_connector_attach_encoder(drm_connector, encoder);
+	if (err) {
+		DRM_ERROR("Failed to attach a connector to a encoder\n");
+		goto err_sysfs;
+	}
+
+	return 0;
+
+err_sysfs:
+	drm_connector_unregister(drm_connector);
+err_connector:
+	drm_bridge_cleanup(bridge);
+	drm_connector_cleanup(drm_connector);
+	return -EINVAL;
+}
+
+static void sti_hda_unbind(struct device *dev,
+		struct device *master, void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops sti_hda_ops = {
+	.bind = sti_hda_bind,
+	.unbind = sti_hda_unbind,
+};
+
+static int sti_hda_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sti_hda *hda;
+	struct resource *res;
+
+	DRM_INFO("%s\n", __func__);
+
+	hda = devm_kzalloc(dev, sizeof(*hda), GFP_KERNEL);
+	if (!hda)
+		return -ENOMEM;
+
+	hda->dev = pdev->dev;
+
+	/* Get resources */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hda-reg");
+	if (!res) {
+		DRM_ERROR("Invalid hda resource\n");
+		return -ENOMEM;
+	}
+	hda->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!hda->regs)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"video-dacs-ctrl");
+	if (res) {
+		hda->video_dacs_ctrl = devm_ioremap_nocache(dev, res->start,
+				resource_size(res));
+		if (!hda->video_dacs_ctrl)
+			return -ENOMEM;
+	} else {
+		/* If no existing video-dacs-ctrl resource continue the probe */
+		DRM_DEBUG_DRIVER("No video-dacs-ctrl resource\n");
+		hda->video_dacs_ctrl = NULL;
+	}
+
+	/* Get clock resources */
+	hda->clk_pix = devm_clk_get(dev, "pix");
+	if (IS_ERR(hda->clk_pix)) {
+		DRM_ERROR("Cannot get hda_pix clock\n");
+		return PTR_ERR(hda->clk_pix);
+	}
+
+	hda->clk_hddac = devm_clk_get(dev, "hddac");
+	if (IS_ERR(hda->clk_hddac)) {
+		DRM_ERROR("Cannot get hda_hddac clock\n");
+		return PTR_ERR(hda->clk_hddac);
+	}
+
+	platform_set_drvdata(pdev, hda);
+
+	return component_add(&pdev->dev, &sti_hda_ops);
+}
+
+static int sti_hda_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sti_hda_ops);
+	return 0;
+}
+
+static const struct of_device_id hda_of_match[] = {
+	{ .compatible = "st,stih416-hda", },
+	{ .compatible = "st,stih407-hda", },
+	{ /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, hda_of_match);
+
+struct platform_driver sti_hda_driver = {
+	.driver = {
+		.name = "sti-hda",
+		.owner = THIS_MODULE,
+		.of_match_table = hda_of_match,
+	},
+	.probe = sti_hda_probe,
+	.remove = sti_hda_remove,
+};
+
+module_platform_driver(sti_hda_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,809 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/hdmi.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+
+#include "sti_hdmi.h"
+#include "sti_hdmi_tx3g4c28phy.h"
+#include "sti_hdmi_tx3g0c55phy.h"
+#include "sti_vtg.h"
+
+#define HDMI_CFG                        0x0000
+#define HDMI_INT_EN                     0x0004
+#define HDMI_INT_STA                    0x0008
+#define HDMI_INT_CLR                    0x000C
+#define HDMI_STA                        0x0010
+#define HDMI_ACTIVE_VID_XMIN            0x0100
+#define HDMI_ACTIVE_VID_XMAX            0x0104
+#define HDMI_ACTIVE_VID_YMIN            0x0108
+#define HDMI_ACTIVE_VID_YMAX            0x010C
+#define HDMI_DFLT_CHL0_DAT              0x0110
+#define HDMI_DFLT_CHL1_DAT              0x0114
+#define HDMI_DFLT_CHL2_DAT              0x0118
+#define HDMI_SW_DI_1_HEAD_WORD          0x0210
+#define HDMI_SW_DI_1_PKT_WORD0          0x0214
+#define HDMI_SW_DI_1_PKT_WORD1          0x0218
+#define HDMI_SW_DI_1_PKT_WORD2          0x021C
+#define HDMI_SW_DI_1_PKT_WORD3          0x0220
+#define HDMI_SW_DI_1_PKT_WORD4          0x0224
+#define HDMI_SW_DI_1_PKT_WORD5          0x0228
+#define HDMI_SW_DI_1_PKT_WORD6          0x022C
+#define HDMI_SW_DI_CFG                  0x0230
+
+#define HDMI_IFRAME_SLOT_AVI            1
+
+#define  XCAT(prefix, x, suffix)        prefix ## x ## suffix
+#define  HDMI_SW_DI_N_HEAD_WORD(x)      XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
+#define  HDMI_SW_DI_N_PKT_WORD0(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD0)
+#define  HDMI_SW_DI_N_PKT_WORD1(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD1)
+#define  HDMI_SW_DI_N_PKT_WORD2(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD2)
+#define  HDMI_SW_DI_N_PKT_WORD3(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD3)
+#define  HDMI_SW_DI_N_PKT_WORD4(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD4)
+#define  HDMI_SW_DI_N_PKT_WORD5(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD5)
+#define  HDMI_SW_DI_N_PKT_WORD6(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD6)
+
+#define HDMI_IFRAME_DISABLED            0x0
+#define HDMI_IFRAME_SINGLE_SHOT         0x1
+#define HDMI_IFRAME_FIELD               0x2
+#define HDMI_IFRAME_FRAME               0x3
+#define HDMI_IFRAME_MASK                0x3
+#define HDMI_IFRAME_CFG_DI_N(x, n)       ((x) << ((n-1)*4)) /* n from 1 to 6 */
+
+#define HDMI_CFG_DEVICE_EN              BIT(0)
+#define HDMI_CFG_HDMI_NOT_DVI           BIT(1)
+#define HDMI_CFG_HDCP_EN                BIT(2)
+#define HDMI_CFG_ESS_NOT_OESS           BIT(3)
+#define HDMI_CFG_H_SYNC_POL_NEG         BIT(4)
+#define HDMI_CFG_SINK_TERM_DET_EN       BIT(5)
+#define HDMI_CFG_V_SYNC_POL_NEG         BIT(6)
+#define HDMI_CFG_422_EN                 BIT(8)
+#define HDMI_CFG_FIFO_OVERRUN_CLR       BIT(12)
+#define HDMI_CFG_FIFO_UNDERRUN_CLR      BIT(13)
+#define HDMI_CFG_SW_RST_EN              BIT(31)
+
+#define HDMI_INT_GLOBAL                 BIT(0)
+#define HDMI_INT_SW_RST                 BIT(1)
+#define HDMI_INT_PIX_CAP                BIT(3)
+#define HDMI_INT_HOT_PLUG               BIT(4)
+#define HDMI_INT_DLL_LCK                BIT(5)
+#define HDMI_INT_NEW_FRAME              BIT(6)
+#define HDMI_INT_GENCTRL_PKT            BIT(7)
+#define HDMI_INT_SINK_TERM_PRESENT      BIT(11)
+
+#define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
+			| HDMI_INT_DLL_LCK \
+			| HDMI_INT_HOT_PLUG \
+			| HDMI_INT_GLOBAL)
+
+#define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
+			| HDMI_INT_GENCTRL_PKT \
+			| HDMI_INT_NEW_FRAME \
+			| HDMI_INT_DLL_LCK \
+			| HDMI_INT_HOT_PLUG \
+			| HDMI_INT_PIX_CAP \
+			| HDMI_INT_SW_RST \
+			| HDMI_INT_GLOBAL)
+
+#define HDMI_STA_SW_RST                 BIT(1)
+
+struct sti_hdmi_connector {
+	struct drm_connector drm_connector;
+	struct drm_encoder *encoder;
+	struct sti_hdmi *hdmi;
+};
+
+#define to_sti_hdmi_connector(x) \
+	container_of(x, struct sti_hdmi_connector, drm_connector)
+
+u32 hdmi_read(struct sti_hdmi *hdmi, int offset)
+{
+	return readl(hdmi->regs + offset);
+}
+
+void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset)
+{
+	writel(val, hdmi->regs + offset);
+}
+
+/**
+ * HDMI interrupt handler threaded
+ *
+ * @irq: irq number
+ * @arg: connector structure
+ */
+static irqreturn_t hdmi_irq_thread(int irq, void *arg)
+{
+	struct sti_hdmi *hdmi = arg;
+
+	/* Hot plug/unplug IRQ */
+	if (hdmi->irq_status & HDMI_INT_HOT_PLUG) {
+		/* read gpio to get the status */
+		hdmi->hpd = gpio_get_value(hdmi->hpd_gpio);
+		if (hdmi->drm_dev)
+			drm_helper_hpd_irq_event(hdmi->drm_dev);
+	}
+
+	/* Sw reset and PLL lock are exclusive so we can use the same
+	 * event to signal them
+	 */
+	if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {
+		hdmi->event_received = true;
+		wake_up_interruptible(&hdmi->wait_event);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * HDMI interrupt handler
+ *
+ * @irq: irq number
+ * @arg: connector structure
+ */
+static irqreturn_t hdmi_irq(int irq, void *arg)
+{
+	struct sti_hdmi *hdmi = arg;
+
+	/* read interrupt status */
+	hdmi->irq_status = hdmi_read(hdmi, HDMI_INT_STA);
+
+	/* clear interrupt status */
+	hdmi_write(hdmi, hdmi->irq_status, HDMI_INT_CLR);
+
+	/* force sync bus write */
+	hdmi_read(hdmi, HDMI_INT_STA);
+
+	return IRQ_WAKE_THREAD;
+}
+
+/**
+ * Set hdmi active area depending on the drm display mode selected
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void hdmi_active_area(struct sti_hdmi *hdmi)
+{
+	u32 xmin, xmax;
+	u32 ymin, ymax;
+
+	xmin = sti_vtg_get_pixel_number(hdmi->mode, 0);
+	xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay - 1);
+	ymin = sti_vtg_get_line_number(hdmi->mode, 0);
+	ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1);
+
+	hdmi_write(hdmi, xmin, HDMI_ACTIVE_VID_XMIN);
+	hdmi_write(hdmi, xmax, HDMI_ACTIVE_VID_XMAX);
+	hdmi_write(hdmi, ymin, HDMI_ACTIVE_VID_YMIN);
+	hdmi_write(hdmi, ymax, HDMI_ACTIVE_VID_YMAX);
+}
+
+/**
+ * Overall hdmi configuration
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void hdmi_config(struct sti_hdmi *hdmi)
+{
+	u32 conf;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* Clear overrun and underrun fifo */
+	conf = HDMI_CFG_FIFO_OVERRUN_CLR | HDMI_CFG_FIFO_UNDERRUN_CLR;
+
+	/* Enable HDMI mode not DVI */
+	conf |= HDMI_CFG_HDMI_NOT_DVI | HDMI_CFG_ESS_NOT_OESS;
+
+	/* Enable sink term detection */
+	conf |= HDMI_CFG_SINK_TERM_DET_EN;
+
+	/* Set Hsync polarity */
+	if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
+		DRM_DEBUG_DRIVER("H Sync Negative\n");
+		conf |= HDMI_CFG_H_SYNC_POL_NEG;
+	}
+
+	/* Set Vsync polarity */
+	if (hdmi->mode.flags & DRM_MODE_FLAG_NVSYNC) {
+		DRM_DEBUG_DRIVER("V Sync Negative\n");
+		conf |= HDMI_CFG_V_SYNC_POL_NEG;
+	}
+
+	/* Enable HDMI */
+	conf |= HDMI_CFG_DEVICE_EN;
+
+	hdmi_write(hdmi, conf, HDMI_CFG);
+}
+
+/**
+ * Prepare and configure the AVI infoframe
+ *
+ * AVI infoframe are transmitted at least once per two video field and
+ * contains information about HDMI transmission mode such as color space,
+ * colorimetry, ...
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return negative value if error occurs
+ */
+static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
+{
+	struct drm_display_mode *mode = &hdmi->mode;
+	struct hdmi_avi_infoframe infoframe;
+	u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
+	u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE;
+	u32 val;
+	int ret;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
+	if (ret < 0) {
+		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
+		return ret;
+	}
+
+	/* fixed infoframe configuration not linked to the mode */
+	infoframe.colorspace = HDMI_COLORSPACE_RGB;
+	infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+	infoframe.colorimetry = HDMI_COLORIMETRY_NONE;
+
+	ret = hdmi_avi_infoframe_pack(&infoframe, buffer, sizeof(buffer));
+	if (ret < 0) {
+		DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
+		return ret;
+	}
+
+	/* Disable transmission slot for AVI infoframe */
+	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
+	val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, HDMI_IFRAME_SLOT_AVI);
+	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
+
+	/* Infoframe header */
+	val = buffer[0x0];
+	val |= buffer[0x1] << 8;
+	val |= buffer[0x2] << 16;
+	hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI));
+
+	/* Infoframe packet bytes */
+	val = frame[0x0];
+	val |= frame[0x1] << 8;
+	val |= frame[0x2] << 16;
+	val |= frame[0x3] << 24;
+	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI));
+
+	val = frame[0x4];
+	val |= frame[0x5] << 8;
+	val |= frame[0x6] << 16;
+	val |= frame[0x7] << 24;
+	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI));
+
+	val = frame[0x8];
+	val |= frame[0x9] << 8;
+	val |= frame[0xA] << 16;
+	val |= frame[0xB] << 24;
+	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI));
+
+	val = frame[0xC];
+	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI));
+
+	/* Enable transmission slot for AVI infoframe
+	 * According to the hdmi specification, AVI infoframe should be
+	 * transmitted at least once per two video fields
+	 */
+	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
+	val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI);
+	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
+
+	return 0;
+}
+
+/**
+ * Software reset of the hdmi subsystem
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ */
+#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */
+static void hdmi_swreset(struct sti_hdmi *hdmi)
+{
+	u32 val;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* Enable hdmi_audio clock only during hdmi reset */
+	if (clk_prepare_enable(hdmi->clk_audio))
+		DRM_INFO("Failed to prepare/enable hdmi_audio clk\n");
+
+	/* Sw reset */
+	hdmi->event_received = false;
+
+	val = hdmi_read(hdmi, HDMI_CFG);
+	val |= HDMI_CFG_SW_RST_EN;
+	hdmi_write(hdmi, val, HDMI_CFG);
+
+	/* Wait reset completed */
+	wait_event_interruptible_timeout(hdmi->wait_event,
+					 hdmi->event_received == true,
+					 msecs_to_jiffies
+					 (HDMI_TIMEOUT_SWRESET));
+
+	/*
+	 * HDMI_STA_SW_RST bit is set to '1' when SW_RST bit in HDMI_CFG is
+	 * set to '1' and clk_audio is running.
+	 */
+	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_SW_RST) == 0)
+		DRM_DEBUG_DRIVER("Warning: HDMI sw reset timeout occurs\n");
+
+	val = hdmi_read(hdmi, HDMI_CFG);
+	val &= ~HDMI_CFG_SW_RST_EN;
+	hdmi_write(hdmi, val, HDMI_CFG);
+
+	/* Disable hdmi_audio clock. Not used anymore for drm purpose */
+	clk_disable_unprepare(hdmi->clk_audio);
+}
+
+static void sti_hdmi_disable(struct drm_bridge *bridge)
+{
+	struct sti_hdmi *hdmi = bridge->driver_private;
+
+	u32 val = hdmi_read(hdmi, HDMI_CFG);
+
+	if (!hdmi->enabled)
+		return;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* Disable HDMI */
+	val &= ~HDMI_CFG_DEVICE_EN;
+	hdmi_write(hdmi, val, HDMI_CFG);
+
+	hdmi_write(hdmi, 0xffffffff, HDMI_INT_CLR);
+
+	/* Stop the phy */
+	hdmi->phy_ops->stop(hdmi);
+
+	/* Set the default channel data to be a dark red */
+	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);
+	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL1_DAT);
+	hdmi_write(hdmi, 0x0060, HDMI_DFLT_CHL2_DAT);
+
+	/* Disable/unprepare hdmi clock */
+	clk_disable_unprepare(hdmi->clk_phy);
+	clk_disable_unprepare(hdmi->clk_tmds);
+	clk_disable_unprepare(hdmi->clk_pix);
+
+	hdmi->enabled = false;
+}
+
+static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
+{
+	struct sti_hdmi *hdmi = bridge->driver_private;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (hdmi->enabled)
+		return;
+
+	/* Prepare/enable clocks */
+	if (clk_prepare_enable(hdmi->clk_pix))
+		DRM_ERROR("Failed to prepare/enable hdmi_pix clk\n");
+	if (clk_prepare_enable(hdmi->clk_tmds))
+		DRM_ERROR("Failed to prepare/enable hdmi_tmds clk\n");
+	if (clk_prepare_enable(hdmi->clk_phy))
+		DRM_ERROR("Failed to prepare/enable hdmi_rejec_pll clk\n");
+
+	hdmi->enabled = true;
+
+	/* Program hdmi serializer and start phy */
+	if (!hdmi->phy_ops->start(hdmi)) {
+		DRM_ERROR("Unable to start hdmi phy\n");
+		return;
+	}
+
+	/* Program hdmi active area */
+	hdmi_active_area(hdmi);
+
+	/* Enable working interrupts */
+	hdmi_write(hdmi, HDMI_WORKING_INT, HDMI_INT_EN);
+
+	/* Program hdmi config */
+	hdmi_config(hdmi);
+
+	/* Program AVI infoframe */
+	if (hdmi_avi_infoframe_config(hdmi))
+		DRM_ERROR("Unable to configure AVI infoframe\n");
+
+	/* Sw reset */
+	hdmi_swreset(hdmi);
+}
+
+static void sti_hdmi_set_mode(struct drm_bridge *bridge,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	struct sti_hdmi *hdmi = bridge->driver_private;
+	int ret;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	/* Copy the drm display mode in the connector local structure */
+	memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
+
+	/* Update clock framerate according to the selected mode */
+	ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
+	if (ret < 0) {
+		DRM_ERROR("Cannot set rate (%dHz) for hdmi_pix clk\n",
+			  mode->clock * 1000);
+		return;
+	}
+	ret = clk_set_rate(hdmi->clk_phy, mode->clock * 1000);
+	if (ret < 0) {
+		DRM_ERROR("Cannot set rate (%dHz) for hdmi_rejection_pll clk\n",
+			  mode->clock * 1000);
+		return;
+	}
+}
+
+static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
+{
+	/* do nothing */
+}
+
+static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge)
+{
+	drm_bridge_cleanup(bridge);
+	kfree(bridge);
+}
+
+static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
+	.pre_enable = sti_hdmi_pre_enable,
+	.enable = sti_hdmi_bridge_nope,
+	.disable = sti_hdmi_disable,
+	.post_disable = sti_hdmi_bridge_nope,
+	.mode_set = sti_hdmi_set_mode,
+	.destroy = sti_hdmi_brigde_destroy,
+};
+
+static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+	struct i2c_adapter *i2c_adap;
+	struct edid *edid;
+	int count;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	i2c_adap = i2c_get_adapter(1);
+	if (!i2c_adap)
+		goto fail;
+
+	edid = drm_get_edid(connector, i2c_adap);
+	if (!edid)
+		goto fail;
+
+	count = drm_add_edid_modes(connector, edid);
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	kfree(edid);
+	return count;
+
+fail:
+	DRM_ERROR("Can not read HDMI EDID\n");
+	return 0;
+}
+
+#define CLK_TOLERANCE_HZ 50
+
+static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	int target = mode->clock * 1000;
+	int target_min = target - CLK_TOLERANCE_HZ;
+	int target_max = target + CLK_TOLERANCE_HZ;
+	int result;
+	struct sti_hdmi_connector *hdmi_connector
+		= to_sti_hdmi_connector(connector);
+	struct sti_hdmi *hdmi = hdmi_connector->hdmi;
+
+
+	result = clk_round_rate(hdmi->clk_pix, target);
+
+	DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
+			 target, result);
+
+	if ((result < target_min) || (result > target_max)) {
+		DRM_DEBUG_DRIVER("hdmi pixclk=%d not supported\n", target);
+		return MODE_BAD;
+	}
+
+	return MODE_OK;
+}
+
+struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
+{
+	struct sti_hdmi_connector *hdmi_connector
+		= to_sti_hdmi_connector(connector);
+
+	/* Best encoder is the one associated during connector creation */
+	return hdmi_connector->encoder;
+}
+
+static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
+	.get_modes = sti_hdmi_connector_get_modes,
+	.mode_valid = sti_hdmi_connector_mode_valid,
+	.best_encoder = sti_hdmi_best_encoder,
+};
+
+/* get detection status of display device */
+static enum drm_connector_status
+sti_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct sti_hdmi_connector *hdmi_connector
+		= to_sti_hdmi_connector(connector);
+	struct sti_hdmi *hdmi = hdmi_connector->hdmi;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (hdmi->hpd) {
+		DRM_DEBUG_DRIVER("hdmi cable connected\n");
+		return connector_status_connected;
+	}
+
+	DRM_DEBUG_DRIVER("hdmi cable disconnected\n");
+	return connector_status_disconnected;
+}
+
+static void sti_hdmi_connector_destroy(struct drm_connector *connector)
+{
+	struct sti_hdmi_connector *hdmi_connector
+		= to_sti_hdmi_connector(connector);
+
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(hdmi_connector);
+}
+
+static struct drm_connector_funcs sti_hdmi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = sti_hdmi_connector_detect,
+	.destroy = sti_hdmi_connector_destroy,
+};
+
+static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
+			return encoder;
+	}
+
+	return NULL;
+}
+
+static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct sti_hdmi *hdmi = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	struct drm_encoder *encoder;
+	struct sti_hdmi_connector *connector;
+	struct drm_connector *drm_connector;
+	struct drm_bridge *bridge;
+	struct i2c_adapter *i2c_adap;
+	int err;
+
+	i2c_adap = i2c_get_adapter(1);
+	if (!i2c_adap)
+		return -EPROBE_DEFER;
+
+	/* Set the drm device handle */
+	hdmi->drm_dev = drm_dev;
+
+	encoder = sti_hdmi_find_encoder(drm_dev);
+	if (!encoder)
+		return -ENOMEM;
+
+	connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
+	if (!connector)
+		return -ENOMEM;
+
+	connector->hdmi = hdmi;
+
+	bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver_private = hdmi;
+	drm_bridge_init(drm_dev, bridge, &sti_hdmi_bridge_funcs);
+
+	encoder->bridge = bridge;
+	connector->encoder = encoder;
+
+	drm_connector = (struct drm_connector *)connector;
+
+	drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	drm_connector_init(drm_dev, drm_connector,
+			&sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
+	drm_connector_helper_add(drm_connector,
+			&sti_hdmi_connector_helper_funcs);
+
+	err = drm_connector_register(drm_connector);
+	if (err)
+		goto err_connector;
+
+	err = drm_mode_connector_attach_encoder(drm_connector, encoder);
+	if (err) {
+		DRM_ERROR("Failed to attach a connector to a encoder\n");
+		goto err_sysfs;
+	}
+
+	/* Enable default interrupts */
+	hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);
+
+	return 0;
+
+err_sysfs:
+	drm_connector_unregister(drm_connector);
+err_connector:
+	drm_bridge_cleanup(bridge);
+	drm_connector_cleanup(drm_connector);
+	return -EINVAL;
+}
+
+static void sti_hdmi_unbind(struct device *dev,
+		struct device *master, void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops sti_hdmi_ops = {
+	.bind = sti_hdmi_bind,
+	.unbind = sti_hdmi_unbind,
+};
+
+static const struct of_device_id hdmi_of_match[] = {
+	{
+		.compatible = "st,stih416-hdmi",
+		.data = &tx3g0c55phy_ops,
+	}, {
+		.compatible = "st,stih407-hdmi",
+		.data = &tx3g4c28phy_ops,
+	}, {
+		/* end node */
+	}
+};
+MODULE_DEVICE_TABLE(of, hdmi_of_match);
+
+static int sti_hdmi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sti_hdmi *hdmi;
+	struct device_node *np = dev->of_node;
+	struct resource *res;
+	int ret;
+
+	DRM_INFO("%s\n", __func__);
+
+	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	hdmi->dev = pdev->dev;
+
+	/* Get resources */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
+	if (!res) {
+		DRM_ERROR("Invalid hdmi resource\n");
+		return -ENOMEM;
+	}
+	hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!hdmi->regs)
+		return -ENOMEM;
+
+	if (of_device_is_compatible(np, "st,stih416-hdmi")) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "syscfg");
+		if (!res) {
+			DRM_ERROR("Invalid syscfg resource\n");
+			return -ENOMEM;
+		}
+		hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
+						    resource_size(res));
+		if (!hdmi->syscfg)
+			return -ENOMEM;
+
+	}
+
+	hdmi->phy_ops = (struct hdmi_phy_ops *)
+		of_match_node(hdmi_of_match, np)->data;
+
+	/* Get clock resources */
+	hdmi->clk_pix = devm_clk_get(dev, "pix");
+	if (IS_ERR(hdmi->clk_pix)) {
+		DRM_ERROR("Cannot get hdmi_pix clock\n");
+		return PTR_ERR(hdmi->clk_pix);
+	}
+
+	hdmi->clk_tmds = devm_clk_get(dev, "tmds");
+	if (IS_ERR(hdmi->clk_tmds)) {
+		DRM_ERROR("Cannot get hdmi_tmds clock\n");
+		return PTR_ERR(hdmi->clk_tmds);
+	}
+
+	hdmi->clk_phy = devm_clk_get(dev, "phy");
+	if (IS_ERR(hdmi->clk_phy)) {
+		DRM_ERROR("Cannot get hdmi_phy clock\n");
+		return PTR_ERR(hdmi->clk_phy);
+	}
+
+	hdmi->clk_audio = devm_clk_get(dev, "audio");
+	if (IS_ERR(hdmi->clk_audio)) {
+		DRM_ERROR("Cannot get hdmi_audio clock\n");
+		return PTR_ERR(hdmi->clk_audio);
+	}
+
+	hdmi->hpd_gpio = of_get_named_gpio(np, "hdmi,hpd-gpio", 0);
+	if (hdmi->hpd_gpio < 0) {
+		DRM_ERROR("Failed to get hdmi hpd-gpio\n");
+		return -EIO;
+	}
+
+	hdmi->hpd = gpio_get_value(hdmi->hpd_gpio);
+
+	init_waitqueue_head(&hdmi->wait_event);
+
+	hdmi->irq = platform_get_irq_byname(pdev, "irq");
+
+	ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
+			hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
+	if (ret) {
+		DRM_ERROR("Failed to register HDMI interrupt\n");
+		return ret;
+	}
+
+	hdmi->reset = devm_reset_control_get(dev, "hdmi");
+	/* Take hdmi out of reset */
+	if (!IS_ERR(hdmi->reset))
+		reset_control_deassert(hdmi->reset);
+
+	platform_set_drvdata(pdev, hdmi);
+
+	return component_add(&pdev->dev, &sti_hdmi_ops);
+}
+
+static int sti_hdmi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sti_hdmi_ops);
+	return 0;
+}
+
+struct platform_driver sti_hdmi_driver = {
+	.driver = {
+		.name = "sti-hdmi",
+		.owner = THIS_MODULE,
+		.of_match_table = hdmi_of_match,
+	},
+	.probe = sti_hdmi_probe,
+	.remove = sti_hdmi_remove,
+};
+
+module_platform_driver(sti_hdmi_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_H_
+#define _STI_HDMI_H_
+
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+#define HDMI_STA           0x0010
+#define HDMI_STA_DLL_LCK   BIT(5)
+
+struct sti_hdmi;
+
+struct hdmi_phy_ops {
+	bool (*start)(struct sti_hdmi *hdmi);
+	void (*stop)(struct sti_hdmi *hdmi);
+};
+
+/**
+ * STI hdmi structure
+ *
+ * @dev: driver device
+ * @drm_dev: pointer to drm device
+ * @mode: current display mode selected
+ * @regs: hdmi register
+ * @syscfg: syscfg register for pll rejection configuration
+ * @clk_pix: hdmi pixel clock
+ * @clk_tmds: hdmi tmds clock
+ * @clk_phy: hdmi phy clock
+ * @clk_audio: hdmi audio clock
+ * @irq: hdmi interrupt number
+ * @irq_status: interrupt status register
+ * @phy_ops: phy start/stop operations
+ * @enabled: true if hdmi is enabled else false
+ * @hpd_gpio: hdmi hot plug detect gpio number
+ * @hpd: hot plug detect status
+ * @wait_event: wait event
+ * @event_received: wait event status
+ * @reset: reset control of the hdmi phy
+ */
+struct sti_hdmi {
+	struct device dev;
+	struct drm_device *drm_dev;
+	struct drm_display_mode mode;
+	void __iomem *regs;
+	void __iomem *syscfg;
+	struct clk *clk_pix;
+	struct clk *clk_tmds;
+	struct clk *clk_phy;
+	struct clk *clk_audio;
+	int irq;
+	u32 irq_status;
+	struct hdmi_phy_ops *phy_ops;
+	bool enabled;
+	int hpd_gpio;
+	bool hpd;
+	wait_queue_head_t wait_event;
+	bool event_received;
+	struct reset_control *reset;
+};
+
+u32 hdmi_read(struct sti_hdmi *hdmi, int offset);
+void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset);
+
+/**
+ * hdmi phy config structure
+ *
+ * A pointer to an array of these structures is passed to a TMDS (HDMI) output
+ * via the control interface to provide board and SoC specific
+ * configurations of the HDMI PHY. Each entry in the array specifies a hardware
+ * specific configuration for a given TMDS clock frequency range.
+ *
+ * @min_tmds_freq: Lower bound of TMDS clock frequency this entry applies to
+ * @max_tmds_freq: Upper bound of TMDS clock frequency this entry applies to
+ * @config: SoC specific register configuration
+ */
+struct hdmi_phy_config {
+	u32 min_tmds_freq;
+	u32 max_tmds_freq;
+	u32 config[4];
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include "sti_hdmi_tx3g0c55phy.h"
+
+#define HDMI_SRZ_PLL_CFG                0x0504
+#define HDMI_SRZ_TAP_1                  0x0508
+#define HDMI_SRZ_TAP_2                  0x050C
+#define HDMI_SRZ_TAP_3                  0x0510
+#define HDMI_SRZ_CTRL                   0x0514
+
+#define HDMI_SRZ_PLL_CFG_POWER_DOWN     BIT(0)
+#define HDMI_SRZ_PLL_CFG_VCOR_SHIFT     1
+#define HDMI_SRZ_PLL_CFG_VCOR_425MHZ    0
+#define HDMI_SRZ_PLL_CFG_VCOR_850MHZ    1
+#define HDMI_SRZ_PLL_CFG_VCOR_1700MHZ   2
+#define HDMI_SRZ_PLL_CFG_VCOR_3000MHZ   3
+#define HDMI_SRZ_PLL_CFG_VCOR_MASK      3
+#define HDMI_SRZ_PLL_CFG_VCOR(x)        (x << HDMI_SRZ_PLL_CFG_VCOR_SHIFT)
+#define HDMI_SRZ_PLL_CFG_NDIV_SHIFT     8
+#define HDMI_SRZ_PLL_CFG_NDIV_MASK      (0x1F << HDMI_SRZ_PLL_CFG_NDIV_SHIFT)
+#define HDMI_SRZ_PLL_CFG_MODE_SHIFT     16
+#define HDMI_SRZ_PLL_CFG_MODE_13_5_MHZ  0x1
+#define HDMI_SRZ_PLL_CFG_MODE_25_2_MHZ  0x4
+#define HDMI_SRZ_PLL_CFG_MODE_27_MHZ    0x5
+#define HDMI_SRZ_PLL_CFG_MODE_33_75_MHZ 0x6
+#define HDMI_SRZ_PLL_CFG_MODE_40_5_MHZ  0x7
+#define HDMI_SRZ_PLL_CFG_MODE_54_MHZ    0x8
+#define HDMI_SRZ_PLL_CFG_MODE_67_5_MHZ  0x9
+#define HDMI_SRZ_PLL_CFG_MODE_74_25_MHZ 0xA
+#define HDMI_SRZ_PLL_CFG_MODE_81_MHZ    0xB
+#define HDMI_SRZ_PLL_CFG_MODE_82_5_MHZ  0xC
+#define HDMI_SRZ_PLL_CFG_MODE_108_MHZ   0xD
+#define HDMI_SRZ_PLL_CFG_MODE_148_5_MHZ 0xE
+#define HDMI_SRZ_PLL_CFG_MODE_165_MHZ   0xF
+#define HDMI_SRZ_PLL_CFG_MODE_MASK      0xF
+#define HDMI_SRZ_PLL_CFG_MODE(x)        (x << HDMI_SRZ_PLL_CFG_MODE_SHIFT)
+
+#define HDMI_SRZ_CTRL_POWER_DOWN        (1 << 0)
+#define HDMI_SRZ_CTRL_EXTERNAL_DATA_EN  (1 << 1)
+
+/* sysconf registers */
+#define HDMI_REJECTION_PLL_CONFIGURATION 0x0858	/* SYSTEM_CONFIG2534 */
+#define HDMI_REJECTION_PLL_STATUS        0x0948	/* SYSTEM_CONFIG2594 */
+
+#define REJECTION_PLL_HDMI_ENABLE_SHIFT 0
+#define REJECTION_PLL_HDMI_ENABLE_MASK  (0x1 << REJECTION_PLL_HDMI_ENABLE_SHIFT)
+#define REJECTION_PLL_HDMI_PDIV_SHIFT   24
+#define REJECTION_PLL_HDMI_PDIV_MASK    (0x7 << REJECTION_PLL_HDMI_PDIV_SHIFT)
+#define REJECTION_PLL_HDMI_NDIV_SHIFT   16
+#define REJECTION_PLL_HDMI_NDIV_MASK    (0xFF << REJECTION_PLL_HDMI_NDIV_SHIFT)
+#define REJECTION_PLL_HDMI_MDIV_SHIFT   8
+#define REJECTION_PLL_HDMI_MDIV_MASK    (0xFF << REJECTION_PLL_HDMI_MDIV_SHIFT)
+
+#define REJECTION_PLL_HDMI_REJ_PLL_LOCK BIT(0)
+
+#define HDMI_TIMEOUT_PLL_LOCK  50   /*milliseconds */
+
+/**
+ * pll mode structure
+ *
+ * A pointer to an array of these structures is passed to a TMDS (HDMI) output
+ * via the control interface to provide board and SoC specific
+ * configurations of the HDMI PHY. Each entry in the array specifies a hardware
+ * specific configuration for a given TMDS clock frequency range. The array
+ * should be terminated with an entry that has all fields set to zero.
+ *
+ * @min: Lower bound of TMDS clock frequency this entry applies to
+ * @max: Upper bound of TMDS clock frequency this entry applies to
+ * @mode: SoC specific register configuration
+ */
+struct pllmode {
+	u32 min;
+	u32 max;
+	u32 mode;
+};
+
+#define NB_PLL_MODE 7
+static struct pllmode pllmodes[NB_PLL_MODE] = {
+	{13500000, 13513500, HDMI_SRZ_PLL_CFG_MODE_13_5_MHZ},
+	{25174800, 25200000, HDMI_SRZ_PLL_CFG_MODE_25_2_MHZ},
+	{27000000, 27027000, HDMI_SRZ_PLL_CFG_MODE_27_MHZ},
+	{54000000, 54054000, HDMI_SRZ_PLL_CFG_MODE_54_MHZ},
+	{72000000, 74250000, HDMI_SRZ_PLL_CFG_MODE_74_25_MHZ},
+	{108000000, 108108000, HDMI_SRZ_PLL_CFG_MODE_108_MHZ},
+	{148351648, 297000000, HDMI_SRZ_PLL_CFG_MODE_148_5_MHZ}
+};
+
+#define NB_HDMI_PHY_CONFIG 5
+static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
+	{0, 40000000, {0x00101010, 0x00101010, 0x00101010, 0x02} },
+	{40000000, 140000000, {0x00111111, 0x00111111, 0x00111111, 0x02} },
+	{140000000, 160000000, {0x00131313, 0x00101010, 0x00101010, 0x02} },
+	{160000000, 250000000, {0x00131313, 0x00111111, 0x00111111, 0x03FE} },
+	{250000000, 300000000, {0x00151515, 0x00101010, 0x00101010, 0x03FE} },
+};
+
+#define PLL_CHANGE_DELAY	1 /* ms */
+
+/**
+ * Disable the pll rejection
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * return true if the pll has been disabled
+ */
+static bool disable_pll_rejection(struct sti_hdmi *hdmi)
+{
+	u32 val;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+	val &= ~REJECTION_PLL_HDMI_ENABLE_MASK;
+	writel(val, hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+	msleep(PLL_CHANGE_DELAY);
+	val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_STATUS);
+
+	return !(val & REJECTION_PLL_HDMI_REJ_PLL_LOCK);
+}
+
+/**
+ * Enable the old BCH/rejection PLL is now reused to provide the CLKPXPLL
+ * clock input to the new PHY PLL that generates the serializer clock
+ * (TMDS*10) and the TMDS clock which is now fed back into the HDMI
+ * formatter instead of the TMDS clock line from ClockGenB.
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * return true if pll has been correctly set
+ */
+static bool enable_pll_rejection(struct sti_hdmi *hdmi)
+{
+	unsigned int inputclock;
+	u32 mdiv, ndiv, pdiv, val;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	if (!disable_pll_rejection(hdmi))
+		return false;
+
+	inputclock = hdmi->mode.clock * 1000;
+
+	DRM_DEBUG_DRIVER("hdmi rejection pll input clock = %dHz\n", inputclock);
+
+
+	/* Power up the HDMI rejection PLL
+	 * Note: On this SoC (stiH416) we are forced to have the input clock
+	 * be equal to the HDMI pixel clock.
+	 *
+	 * The values here have been suggested by validation however they are
+	 * still provisional and subject to change.
+	 *
+	 * PLLout = (Fin*Mdiv) / ((2 * Ndiv) / 2^Pdiv)
+	 */
+	if (inputclock < 50000000) {
+		/*
+		 * For slower clocks we need to multiply more to keep the
+		 * internal VCO frequency within the physical specification
+		 * of the PLL.
+		 */
+		pdiv = 4;
+		ndiv = 240;
+		mdiv = 30;
+	} else {
+		pdiv = 2;
+		ndiv = 60;
+		mdiv = 30;
+	}
+
+	val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+	val &= ~(REJECTION_PLL_HDMI_PDIV_MASK |
+		REJECTION_PLL_HDMI_NDIV_MASK |
+		REJECTION_PLL_HDMI_MDIV_MASK |
+		REJECTION_PLL_HDMI_ENABLE_MASK);
+
+	val |=	(pdiv << REJECTION_PLL_HDMI_PDIV_SHIFT) |
+		(ndiv << REJECTION_PLL_HDMI_NDIV_SHIFT) |
+		(mdiv << REJECTION_PLL_HDMI_MDIV_SHIFT) |
+		(0x1 << REJECTION_PLL_HDMI_ENABLE_SHIFT);
+
+	writel(val, hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+	msleep(PLL_CHANGE_DELAY);
+	val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_STATUS);
+
+	return (val & REJECTION_PLL_HDMI_REJ_PLL_LOCK);
+}
+
+/**
+ * Start hdmi phy macro cell tx3g0c55
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return false if an error occur
+ */
+static bool sti_hdmi_tx3g0c55phy_start(struct sti_hdmi *hdmi)
+{
+	u32 ckpxpll = hdmi->mode.clock * 1000;
+	u32 val, tmdsck, freqvco, pllctrl = 0;
+	unsigned int i;
+
+	if (!enable_pll_rejection(hdmi))
+		return false;
+
+	DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);
+
+	/* Assuming no pixel repetition and 24bits color */
+	tmdsck = ckpxpll;
+	pllctrl = 2 << HDMI_SRZ_PLL_CFG_NDIV_SHIFT;
+
+	/*
+	 * Setup the PLL mode parameter based on the ckpxpll. If we haven't got
+	 * a clock frequency supported by one of the specific PLL modes then we
+	 * will end up using the generic mode (0) which only supports a 10x
+	 * multiplier, hence only 24bit color.
+	 */
+	for (i = 0; i < NB_PLL_MODE; i++) {
+		if (ckpxpll >= pllmodes[i].min && ckpxpll <= pllmodes[i].max)
+			pllctrl |= HDMI_SRZ_PLL_CFG_MODE(pllmodes[i].mode);
+	}
+
+	freqvco = tmdsck * 10;
+	if (freqvco <= 425000000UL)
+		pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_425MHZ);
+	else if (freqvco <= 850000000UL)
+		pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_850MHZ);
+	else if (freqvco <= 1700000000UL)
+		pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_1700MHZ);
+	else if (freqvco <= 2970000000UL)
+		pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_3000MHZ);
+	else {
+		DRM_ERROR("PHY serializer clock out of range\n");
+		goto err;
+	}
+
+	/*
+	 * Configure and power up the PHY PLL
+	 */
+	hdmi->event_received = false;
+	DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
+	hdmi_write(hdmi, pllctrl, HDMI_SRZ_PLL_CFG);
+
+	/* wait PLL interrupt */
+	wait_event_interruptible_timeout(hdmi->wait_event,
+					 hdmi->event_received == true,
+					 msecs_to_jiffies
+					 (HDMI_TIMEOUT_PLL_LOCK));
+
+	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
+		DRM_ERROR("hdmi phy pll not locked\n");
+		goto err;
+	}
+
+	DRM_DEBUG_DRIVER("got PHY PLL Lock\n");
+
+	/*
+	 * To configure the source termination and pre-emphasis appropriately
+	 * for different high speed TMDS clock frequencies a phy configuration
+	 * table must be provided, tailored to the SoC and board combination.
+	 */
+	for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {
+		if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&
+		    (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {
+			val = hdmiphy_config[i].config[0];
+			hdmi_write(hdmi, val, HDMI_SRZ_TAP_1);
+			val = hdmiphy_config[i].config[1];
+			hdmi_write(hdmi, val, HDMI_SRZ_TAP_2);
+			val = hdmiphy_config[i].config[2];
+			hdmi_write(hdmi, val, HDMI_SRZ_TAP_3);
+			val = hdmiphy_config[i].config[3];
+			val |= HDMI_SRZ_CTRL_EXTERNAL_DATA_EN;
+			val &= ~HDMI_SRZ_CTRL_POWER_DOWN;
+			hdmi_write(hdmi, val, HDMI_SRZ_CTRL);
+
+			DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x 0x%x\n",
+					 hdmiphy_config[i].config[0],
+					 hdmiphy_config[i].config[1],
+					 hdmiphy_config[i].config[2],
+					 hdmiphy_config[i].config[3]);
+			return true;
+		}
+	}
+
+	/*
+	 * Default, power up the serializer with no pre-emphasis or source
+	 * termination.
+	 */
+	hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_1);
+	hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_2);
+	hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_3);
+	hdmi_write(hdmi, HDMI_SRZ_CTRL_EXTERNAL_DATA_EN, HDMI_SRZ_CTRL);
+
+	return true;
+
+err:
+	disable_pll_rejection(hdmi);
+
+	return false;
+}
+
+/**
+ * Stop hdmi phy macro cell tx3g0c55
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void sti_hdmi_tx3g0c55phy_stop(struct sti_hdmi *hdmi)
+{
+	DRM_DEBUG_DRIVER("\n");
+
+	hdmi->event_received = false;
+
+	hdmi_write(hdmi, HDMI_SRZ_CTRL_POWER_DOWN, HDMI_SRZ_CTRL);
+	hdmi_write(hdmi, HDMI_SRZ_PLL_CFG_POWER_DOWN, HDMI_SRZ_PLL_CFG);
+
+	/* wait PLL interrupt */
+	wait_event_interruptible_timeout(hdmi->wait_event,
+					 hdmi->event_received == true,
+					 msecs_to_jiffies
+					 (HDMI_TIMEOUT_PLL_LOCK));
+
+	if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)
+		DRM_ERROR("hdmi phy pll not well disabled\n");
+
+	disable_pll_rejection(hdmi);
+}
+
+struct hdmi_phy_ops tx3g0c55phy_ops = {
+	.start = sti_hdmi_tx3g0c55phy_start,
+	.stop = sti_hdmi_tx3g0c55phy_stop,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_TX3G0C55PHY_H_
+#define _STI_HDMI_TX3G0C55PHY_H_
+
+#include "sti_hdmi.h"
+
+extern struct hdmi_phy_ops tx3g0c55phy_ops;
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include "sti_hdmi_tx3g4c28phy.h"
+
+#define HDMI_SRZ_CFG                             0x504
+#define HDMI_SRZ_PLL_CFG                         0x510
+#define HDMI_SRZ_ICNTL                           0x518
+#define HDMI_SRZ_CALCODE_EXT                     0x520
+
+#define HDMI_SRZ_CFG_EN                          BIT(0)
+#define HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT BIT(1)
+#define HDMI_SRZ_CFG_EXTERNAL_DATA               BIT(16)
+#define HDMI_SRZ_CFG_RBIAS_EXT                   BIT(17)
+#define HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION      BIT(18)
+#define HDMI_SRZ_CFG_EN_BIASRES_DETECTION        BIT(19)
+#define HDMI_SRZ_CFG_EN_SRC_TERMINATION          BIT(24)
+
+#define HDMI_SRZ_CFG_INTERNAL_MASK  (HDMI_SRZ_CFG_EN     | \
+		HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT | \
+		HDMI_SRZ_CFG_EXTERNAL_DATA               | \
+		HDMI_SRZ_CFG_RBIAS_EXT                   | \
+		HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION      | \
+		HDMI_SRZ_CFG_EN_BIASRES_DETECTION        | \
+		HDMI_SRZ_CFG_EN_SRC_TERMINATION)
+
+#define PLL_CFG_EN                               BIT(0)
+#define PLL_CFG_NDIV_SHIFT                       (8)
+#define PLL_CFG_IDF_SHIFT                        (16)
+#define PLL_CFG_ODF_SHIFT                        (24)
+
+#define ODF_DIV_1                                (0)
+#define ODF_DIV_2                                (1)
+#define ODF_DIV_4                                (2)
+#define ODF_DIV_8                                (3)
+
+#define HDMI_TIMEOUT_PLL_LOCK  50  /*milliseconds */
+
+struct plldividers_s {
+	uint32_t min;
+	uint32_t max;
+	uint32_t idf;
+	uint32_t odf;
+};
+
+/*
+ * Functional specification recommended values
+ */
+#define NB_PLL_MODE 5
+static struct plldividers_s plldividers[NB_PLL_MODE] = {
+	{0, 20000000, 1, ODF_DIV_8},
+	{20000000, 42500000, 2, ODF_DIV_8},
+	{42500000, 85000000, 4, ODF_DIV_4},
+	{85000000, 170000000, 8, ODF_DIV_2},
+	{170000000, 340000000, 16, ODF_DIV_1}
+};
+
+#define NB_HDMI_PHY_CONFIG 2
+static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
+	{0, 250000000, {0x0, 0x0, 0x0, 0x0} },
+	{250000000, 300000000, {0x1110, 0x0, 0x0, 0x0} },
+};
+
+/**
+ * Start hdmi phy macro cell tx3g4c28
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return false if an error occur
+ */
+static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi)
+{
+	u32 ckpxpll = hdmi->mode.clock * 1000;
+	u32 val, tmdsck, idf, odf, pllctrl = 0;
+	bool foundplldivides = false;
+	int i;
+
+	DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);
+
+	for (i = 0; i < NB_PLL_MODE; i++) {
+		if (ckpxpll >= plldividers[i].min &&
+		    ckpxpll < plldividers[i].max) {
+			idf = plldividers[i].idf;
+			odf = plldividers[i].odf;
+			foundplldivides = true;
+			break;
+		}
+	}
+
+	if (!foundplldivides) {
+		DRM_ERROR("input TMDS clock speed (%d) not supported\n",
+			  ckpxpll);
+		goto err;
+	}
+
+	/* Assuming no pixel repetition and 24bits color */
+	tmdsck = ckpxpll;
+	pllctrl |= 40 << PLL_CFG_NDIV_SHIFT;
+
+	if (tmdsck > 340000000) {
+		DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck);
+		goto err;
+	}
+
+	pllctrl |= idf << PLL_CFG_IDF_SHIFT;
+	pllctrl |= odf << PLL_CFG_ODF_SHIFT;
+
+	/*
+	 * Configure and power up the PHY PLL
+	 */
+	hdmi->event_received = false;
+	DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
+	hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG);
+
+	/* wait PLL interrupt */
+	wait_event_interruptible_timeout(hdmi->wait_event,
+					 hdmi->event_received == true,
+					 msecs_to_jiffies
+					 (HDMI_TIMEOUT_PLL_LOCK));
+
+	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
+		DRM_ERROR("hdmi phy pll not locked\n");
+		goto err;
+	}
+
+	DRM_DEBUG_DRIVER("got PHY PLL Lock\n");
+
+	val = (HDMI_SRZ_CFG_EN |
+	       HDMI_SRZ_CFG_EXTERNAL_DATA |
+	       HDMI_SRZ_CFG_EN_BIASRES_DETECTION |
+	       HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION);
+
+	if (tmdsck > 165000000)
+		val |= HDMI_SRZ_CFG_EN_SRC_TERMINATION;
+
+	/*
+	 * To configure the source termination and pre-emphasis appropriately
+	 * for different high speed TMDS clock frequencies a phy configuration
+	 * table must be provided, tailored to the SoC and board combination.
+	 */
+	for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {
+		if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&
+		    (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {
+			val |= (hdmiphy_config[i].config[0]
+				& ~HDMI_SRZ_CFG_INTERNAL_MASK);
+			hdmi_write(hdmi, val, HDMI_SRZ_CFG);
+
+			val = hdmiphy_config[i].config[1];
+			hdmi_write(hdmi, val, HDMI_SRZ_ICNTL);
+
+			val = hdmiphy_config[i].config[2];
+			hdmi_write(hdmi, val, HDMI_SRZ_CALCODE_EXT);
+
+			DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x\n",
+					 hdmiphy_config[i].config[0],
+					 hdmiphy_config[i].config[1],
+					 hdmiphy_config[i].config[2]);
+			return true;
+		}
+	}
+
+	/*
+	 * Default, power up the serializer with no pre-emphasis or
+	 * output swing correction
+	 */
+	hdmi_write(hdmi, val,  HDMI_SRZ_CFG);
+	hdmi_write(hdmi, 0x0, HDMI_SRZ_ICNTL);
+	hdmi_write(hdmi, 0x0, HDMI_SRZ_CALCODE_EXT);
+
+	return true;
+
+err:
+	return false;
+}
+
+/**
+ * Stop hdmi phy macro cell tx3g4c28
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void sti_hdmi_tx3g4c28phy_stop(struct sti_hdmi *hdmi)
+{
+	int val = 0;
+
+	DRM_DEBUG_DRIVER("\n");
+
+	hdmi->event_received = false;
+
+	val = HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION;
+	val |= HDMI_SRZ_CFG_EN_BIASRES_DETECTION;
+
+	hdmi_write(hdmi, val, HDMI_SRZ_CFG);
+	hdmi_write(hdmi, 0, HDMI_SRZ_PLL_CFG);
+
+	/* wait PLL interrupt */
+	wait_event_interruptible_timeout(hdmi->wait_event,
+					 hdmi->event_received == true,
+					 msecs_to_jiffies
+					 (HDMI_TIMEOUT_PLL_LOCK));
+
+	if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)
+		DRM_ERROR("hdmi phy pll not well disabled\n");
+}
+
+struct hdmi_phy_ops tx3g4c28phy_ops = {
+	.start = sti_hdmi_tx3g4c28phy_start,
+	.stop = sti_hdmi_tx3g4c28phy_stop,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_TX3G4C28PHY_H_
+#define _STI_HDMI_TX3G4C28PHY_H_
+
+#include "sti_hdmi.h"
+
+extern struct hdmi_phy_ops tx3g4c28phy_ops;
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_layer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_layer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_layer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_layer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_gdp.h"
+#include "sti_layer.h"
+#include "sti_vid.h"
+
+const char *sti_layer_to_str(struct sti_layer *layer)
+{
+	switch (layer->desc) {
+	case STI_GDP_0:
+		return "GDP0";
+	case STI_GDP_1:
+		return "GDP1";
+	case STI_GDP_2:
+		return "GDP2";
+	case STI_GDP_3:
+		return "GDP3";
+	case STI_VID_0:
+		return "VID0";
+	case STI_VID_1:
+		return "VID1";
+	case STI_CURSOR:
+		return "CURSOR";
+	default:
+		return "<UNKNOWN LAYER>";
+	}
+}
+
+struct sti_layer *sti_layer_create(struct device *dev, int desc,
+				   void __iomem *baseaddr)
+{
+
+	struct sti_layer *layer = NULL;
+
+	switch (desc & STI_LAYER_TYPE_MASK) {
+	case STI_GDP:
+		layer = sti_gdp_create(dev, desc);
+		break;
+	case STI_VID:
+		layer = sti_vid_create(dev);
+		break;
+	}
+
+	if (!layer) {
+		DRM_ERROR("Failed to create layer\n");
+		return NULL;
+	}
+
+	layer->desc = desc;
+	layer->dev = dev;
+	layer->regs = baseaddr;
+
+	layer->ops->init(layer);
+
+	DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer));
+
+	return layer;
+}
+
+int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb,
+		      struct drm_display_mode *mode, int mixer_id,
+		      int dest_x, int dest_y, int dest_w, int dest_h,
+		      int src_x, int src_y, int src_w, int src_h)
+{
+	int ret;
+	unsigned int i;
+	struct drm_gem_cma_object *cma_obj;
+
+	if (!layer || !fb || !mode) {
+		DRM_ERROR("Null fb, layer or mode\n");
+		return 1;
+	}
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_ERROR("Can't get CMA GEM object for fb\n");
+		return 1;
+	}
+
+	layer->fb = fb;
+	layer->mode = mode;
+	layer->mixer_id = mixer_id;
+	layer->dst_x = dest_x;
+	layer->dst_y = dest_y;
+	layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
+	layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
+	layer->src_x = src_x;
+	layer->src_y = src_y;
+	layer->src_w = src_w;
+	layer->src_h = src_h;
+	layer->format = fb->pixel_format;
+	layer->paddr = cma_obj->paddr;
+	for (i = 0; i < 4; i++) {
+		layer->pitches[i] = fb->pitches[i];
+		layer->offsets[i] = fb->offsets[i];
+	}
+
+	DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
+			 sti_layer_to_str(layer),
+			 layer->mixer_id);
+	DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+			 sti_layer_to_str(layer),
+			 layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y,
+			 layer->src_w, layer->src_h, layer->src_x,
+			 layer->src_y);
+
+	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+			 (char *)&layer->format, (unsigned long)layer->paddr);
+
+	if (!layer->ops->prepare)
+		goto err_no_prepare;
+
+	ret = layer->ops->prepare(layer, !layer->enabled);
+	if (!ret)
+		layer->enabled = true;
+
+	return ret;
+
+err_no_prepare:
+	DRM_ERROR("Cannot prepare\n");
+	return 1;
+}
+
+int sti_layer_commit(struct sti_layer *layer)
+{
+	if (!layer)
+		return 1;
+
+	if (!layer->ops->commit)
+		goto err_no_commit;
+
+	return layer->ops->commit(layer);
+
+err_no_commit:
+	DRM_ERROR("Cannot commit\n");
+	return 1;
+}
+
+int sti_layer_disable(struct sti_layer *layer)
+{
+	int ret;
+
+	DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+	if (!layer)
+		return 1;
+
+	if (!layer->enabled)
+		return 0;
+
+	if (!layer->ops->disable)
+		goto err_no_disable;
+
+	ret = layer->ops->disable(layer);
+	if (!ret)
+		layer->enabled = false;
+	else
+		DRM_ERROR("Disable failed\n");
+
+	return ret;
+
+err_no_disable:
+	DRM_ERROR("Cannot disable\n");
+	return 1;
+}
+
+const uint32_t *sti_layer_get_formats(struct sti_layer *layer)
+{
+	if (!layer)
+		return NULL;
+
+	if (!layer->ops->get_formats)
+		return NULL;
+
+	return layer->ops->get_formats(layer);
+}
+
+unsigned int sti_layer_get_nb_formats(struct sti_layer *layer)
+{
+	if (!layer)
+		return 0;
+
+	if (!layer->ops->get_nb_formats)
+		return 0;
+
+	return layer->ops->get_nb_formats(layer);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_layer.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_layer.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_layer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_layer.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_LAYER_H_
+#define _STI_LAYER_H_
+
+#include <drm/drmP.h>
+
+#define to_sti_layer(x) container_of(x, struct sti_layer, plane)
+
+#define STI_LAYER_TYPE_SHIFT 8
+#define STI_LAYER_TYPE_MASK (~((1<<STI_LAYER_TYPE_SHIFT)-1))
+
+struct sti_layer;
+
+enum sti_layer_type {
+	STI_GDP = 1 << STI_LAYER_TYPE_SHIFT,
+	STI_VID = 2 << STI_LAYER_TYPE_SHIFT,
+	STI_CUR = 3 << STI_LAYER_TYPE_SHIFT,
+	STI_BCK = 4 << STI_LAYER_TYPE_SHIFT
+};
+
+enum sti_layer_id_of_type {
+	STI_ID_0 = 0,
+	STI_ID_1 = 1,
+	STI_ID_2 = 2,
+	STI_ID_3 = 3
+};
+
+enum sti_layer_desc {
+	STI_GDP_0       = STI_GDP | STI_ID_0,
+	STI_GDP_1       = STI_GDP | STI_ID_1,
+	STI_GDP_2       = STI_GDP | STI_ID_2,
+	STI_GDP_3       = STI_GDP | STI_ID_3,
+	STI_VID_0       = STI_VID | STI_ID_0,
+	STI_VID_1       = STI_VID | STI_ID_1,
+	STI_CURSOR      = STI_CUR,
+	STI_BACK        = STI_BCK
+};
+
+/**
+ * STI layer functions structure
+ *
+ * @get_formats:	get layer supported formats
+ * @get_nb_formats:	get number of format supported
+ * @init:               initialize the layer
+ * @prepare:		prepare layer before rendering
+ * @commit:		set layer for rendering
+ * @disable:		disable layer
+ */
+struct sti_layer_funcs {
+	const uint32_t* (*get_formats)(struct sti_layer *layer);
+	unsigned int (*get_nb_formats)(struct sti_layer *layer);
+	void (*init)(struct sti_layer *layer);
+	int (*prepare)(struct sti_layer *layer, bool first_prepare);
+	int (*commit)(struct sti_layer *layer);
+	int (*disable)(struct sti_layer *layer);
+};
+
+/**
+ * STI layer structure
+ *
+ * @plane:              drm plane it is bound to (if any)
+ * @fb:                 drm fb it is bound to
+ * @mode:               display mode
+ * @desc:               layer type & id
+ * @device:		driver device
+ * @regs:		layer registers
+ * @ops:                layer functions
+ * @zorder:             layer z-order
+ * @mixer_id:           id of the mixer used to display the layer
+ * @enabled:            to know if the layer is active or not
+ * @src_x src_y:        coordinates of the input (fb) area
+ * @src_w src_h:        size of the input (fb) area
+ * @dst_x dst_y:        coordinates of the output (crtc) area
+ * @dst_w dst_h:        size of the output (crtc) area
+ * @format:             format
+ * @pitches:            pitch of 'planes' (eg: Y, U, V)
+ * @offsets:            offset of 'planes'
+ * @paddr:              physical address of the input buffer
+ */
+struct sti_layer {
+	struct drm_plane plane;
+	struct drm_framebuffer *fb;
+	struct drm_display_mode *mode;
+	enum sti_layer_desc desc;
+	struct device *dev;
+	void __iomem *regs;
+	const struct sti_layer_funcs *ops;
+	int zorder;
+	int mixer_id;
+	bool enabled;
+	int src_x, src_y;
+	int src_w, src_h;
+	int dst_x, dst_y;
+	int dst_w, dst_h;
+	uint32_t format;
+	unsigned int pitches[4];
+	unsigned int offsets[4];
+	dma_addr_t paddr;
+};
+
+struct sti_layer *sti_layer_create(struct device *dev, int desc,
+			void __iomem *baseaddr);
+int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb,
+			struct drm_display_mode *mode,
+			int mixer_id,
+			int dest_x, int dest_y,
+			int dest_w, int dest_h,
+			int src_x, int src_y,
+			int src_w, int src_h);
+int sti_layer_commit(struct sti_layer *layer);
+int sti_layer_disable(struct sti_layer *layer);
+const uint32_t *sti_layer_get_formats(struct sti_layer *layer);
+unsigned int sti_layer_get_nb_formats(struct sti_layer *layer);
+const char *sti_layer_to_str(struct sti_layer *layer);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_mixer.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_mixer.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_mixer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_mixer.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include "sti_compositor.h"
+#include "sti_mixer.h"
+#include "sti_vtg.h"
+
+/* Identity: G=Y , B=Cb , R=Cr */
+static const u32 mixerColorSpaceMatIdentity[] = {
+	0x10000000, 0x00000000, 0x10000000, 0x00001000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+/* regs offset */
+#define GAM_MIXER_CTL      0x00
+#define GAM_MIXER_BKC      0x04
+#define GAM_MIXER_BCO      0x0C
+#define GAM_MIXER_BCS      0x10
+#define GAM_MIXER_AVO      0x28
+#define GAM_MIXER_AVS      0x2C
+#define GAM_MIXER_CRB      0x34
+#define GAM_MIXER_ACT      0x38
+#define GAM_MIXER_MBP      0x3C
+#define GAM_MIXER_MX0      0x80
+
+/* id for depth of CRB reg */
+#define GAM_DEPTH_VID0_ID  1
+#define GAM_DEPTH_VID1_ID  2
+#define GAM_DEPTH_GDP0_ID  3
+#define GAM_DEPTH_GDP1_ID  4
+#define GAM_DEPTH_GDP2_ID  5
+#define GAM_DEPTH_GDP3_ID  6
+#define GAM_DEPTH_MASK_ID  7
+
+/* mask in CTL reg */
+#define GAM_CTL_BACK_MASK  BIT(0)
+#define GAM_CTL_VID0_MASK  BIT(1)
+#define GAM_CTL_VID1_MASK  BIT(2)
+#define GAM_CTL_GDP0_MASK  BIT(3)
+#define GAM_CTL_GDP1_MASK  BIT(4)
+#define GAM_CTL_GDP2_MASK  BIT(5)
+#define GAM_CTL_GDP3_MASK  BIT(6)
+
+const char *sti_mixer_to_str(struct sti_mixer *mixer)
+{
+	switch (mixer->id) {
+	case STI_MIXER_MAIN:
+		return "MAIN_MIXER";
+	case STI_MIXER_AUX:
+		return "AUX_MIXER";
+	default:
+		return "<UNKNOWN MIXER>";
+	}
+}
+
+static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
+{
+	return readl(mixer->regs + reg_id);
+}
+
+static inline void sti_mixer_reg_write(struct sti_mixer *mixer,
+				       u32 reg_id, u32 val)
+{
+	writel(val, mixer->regs + reg_id);
+}
+
+void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
+{
+	u32 val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
+
+	val &= ~GAM_CTL_BACK_MASK;
+	val |= enable;
+	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
+}
+
+static void sti_mixer_set_background_color(struct sti_mixer *mixer,
+					   u8 red, u8 green, u8 blue)
+{
+	u32 val = (red << 16) | (green << 8) | blue;
+
+	sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
+}
+
+static void sti_mixer_set_background_area(struct sti_mixer *mixer,
+					  struct drm_display_mode *mode)
+{
+	u32 ydo, xdo, yds, xds;
+
+	ydo = sti_vtg_get_line_number(*mode, 0);
+	yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, 0);
+	xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
+
+	sti_mixer_reg_write(mixer, GAM_MIXER_BCO, ydo << 16 | xdo);
+	sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);
+}
+
+int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
+{
+	int layer_id = 0, depth = layer->zorder;
+	u32 mask, val;
+
+	if (depth >= GAM_MIXER_NB_DEPTH_LEVEL)
+		return 1;
+
+	switch (layer->desc) {
+	case STI_GDP_0:
+		layer_id = GAM_DEPTH_GDP0_ID;
+		break;
+	case STI_GDP_1:
+		layer_id = GAM_DEPTH_GDP1_ID;
+		break;
+	case STI_GDP_2:
+		layer_id = GAM_DEPTH_GDP2_ID;
+		break;
+	case STI_GDP_3:
+		layer_id = GAM_DEPTH_GDP3_ID;
+		break;
+	case STI_VID_0:
+		layer_id = GAM_DEPTH_VID0_ID;
+		break;
+	case STI_VID_1:
+		layer_id = GAM_DEPTH_VID1_ID;
+		break;
+	default:
+		DRM_ERROR("Unknown layer %d\n", layer->desc);
+		return 1;
+	}
+	mask = GAM_DEPTH_MASK_ID << (3 * depth);
+	layer_id = layer_id << (3 * depth);
+
+	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
+			 sti_layer_to_str(layer), depth);
+	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
+		layer_id, mask);
+
+	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
+	val &= ~mask;
+	val |= layer_id;
+	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
+
+	dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
+		sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
+	return 0;
+}
+
+int sti_mixer_active_video_area(struct sti_mixer *mixer,
+				struct drm_display_mode *mode)
+{
+	u32 ydo, xdo, yds, xds;
+
+	ydo = sti_vtg_get_line_number(*mode, 0);
+	yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, 0);
+	xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
+
+	DRM_DEBUG_DRIVER("%s active video area xdo:%d ydo:%d xds:%d yds:%d\n",
+			 sti_mixer_to_str(mixer), xdo, ydo, xds, yds);
+	sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
+	sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
+
+	sti_mixer_set_background_color(mixer, 0xFF, 0, 0);
+
+	sti_mixer_set_background_area(mixer, mode);
+	sti_mixer_set_background_status(mixer, true);
+	return 0;
+}
+
+static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
+{
+	switch (layer->desc) {
+	case STI_BACK:
+		return GAM_CTL_BACK_MASK;
+	case STI_GDP_0:
+		return GAM_CTL_GDP0_MASK;
+	case STI_GDP_1:
+		return GAM_CTL_GDP1_MASK;
+	case STI_GDP_2:
+		return GAM_CTL_GDP2_MASK;
+	case STI_GDP_3:
+		return GAM_CTL_GDP3_MASK;
+	case STI_VID_0:
+		return GAM_CTL_VID0_MASK;
+	case STI_VID_1:
+		return GAM_CTL_VID1_MASK;
+	default:
+		return 0;
+	}
+}
+
+int sti_mixer_set_layer_status(struct sti_mixer *mixer,
+			       struct sti_layer *layer, bool status)
+{
+	u32 mask, val;
+
+	DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
+			 sti_mixer_to_str(mixer), sti_layer_to_str(layer));
+
+	mask = sti_mixer_get_layer_mask(layer);
+	if (!mask) {
+		DRM_ERROR("Can not find layer mask\n");
+		return -EINVAL;
+	}
+
+	val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
+	val &= ~mask;
+	val |= status ? mask : 0;
+	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
+
+	return 0;
+}
+
+void sti_mixer_set_matrix(struct sti_mixer *mixer)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(mixerColorSpaceMatIdentity); i++)
+		sti_mixer_reg_write(mixer, GAM_MIXER_MX0 + (i * 4),
+				    mixerColorSpaceMatIdentity[i]);
+}
+
+struct sti_mixer *sti_mixer_create(struct device *dev, int id,
+				   void __iomem *baseaddr)
+{
+	struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	struct device_node *np = dev->of_node;
+
+	dev_dbg(dev, "%s\n", __func__);
+	if (!mixer) {
+		DRM_ERROR("Failed to allocated memory for mixer\n");
+		return NULL;
+	}
+	mixer->regs = baseaddr;
+	mixer->dev = dev;
+	mixer->id = id;
+
+	if (of_device_is_compatible(np, "st,stih416-compositor"))
+		sti_mixer_set_matrix(mixer);
+
+	DRM_DEBUG_DRIVER("%s created. Regs=%p\n",
+			 sti_mixer_to_str(mixer), mixer->regs);
+
+	return mixer;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_mixer.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_mixer.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_mixer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_mixer.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_MIXER_H_
+#define _STI_MIXER_H_
+
+#include <drm/drmP.h>
+
+#include "sti_layer.h"
+
+#define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
+
+/**
+ * STI Mixer subdevice structure
+ *
+ * @dev: driver device
+ * @regs: mixer registers
+ * @id: id of the mixer
+ * @drm_crtc: crtc object link to the mixer
+ * @pending_event: set if a flip event is pending on crtc
+ */
+struct sti_mixer {
+	struct device *dev;
+	void __iomem *regs;
+	int id;
+	struct drm_crtc	drm_crtc;
+	struct drm_pending_vblank_event *pending_event;
+};
+
+const char *sti_mixer_to_str(struct sti_mixer *mixer);
+
+struct sti_mixer *sti_mixer_create(struct device *dev, int id,
+		void __iomem *baseaddr);
+
+int sti_mixer_set_layer_status(struct sti_mixer *mixer,
+		struct sti_layer *layer, bool status);
+int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer);
+int sti_mixer_active_video_area(struct sti_mixer *mixer,
+		struct drm_display_mode *mode);
+
+void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
+
+/* depth in Cross-bar control = z order */
+#define GAM_MIXER_NB_DEPTH_LEVEL 7
+
+#define STI_MIXER_MAIN 0
+#define STI_MIXER_AUX  1
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_tvout.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_tvout.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_tvout.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_tvout.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Vincent Abriou <vincent.abriou@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+/* glue registers */
+#define TVO_CSC_MAIN_M0                  0x000
+#define TVO_CSC_MAIN_M1                  0x004
+#define TVO_CSC_MAIN_M2                  0x008
+#define TVO_CSC_MAIN_M3                  0x00c
+#define TVO_CSC_MAIN_M4                  0x010
+#define TVO_CSC_MAIN_M5                  0x014
+#define TVO_CSC_MAIN_M6                  0x018
+#define TVO_CSC_MAIN_M7                  0x01c
+#define TVO_MAIN_IN_VID_FORMAT           0x030
+#define TVO_CSC_AUX_M0                   0x100
+#define TVO_CSC_AUX_M1                   0x104
+#define TVO_CSC_AUX_M2                   0x108
+#define TVO_CSC_AUX_M3                   0x10c
+#define TVO_CSC_AUX_M4                   0x110
+#define TVO_CSC_AUX_M5                   0x114
+#define TVO_CSC_AUX_M6                   0x118
+#define TVO_CSC_AUX_M7                   0x11c
+#define TVO_AUX_IN_VID_FORMAT            0x130
+#define TVO_VIP_HDF                      0x400
+#define TVO_HD_SYNC_SEL                  0x418
+#define TVO_HD_DAC_CFG_OFF               0x420
+#define TVO_VIP_HDMI                     0x500
+#define TVO_HDMI_FORCE_COLOR_0           0x504
+#define TVO_HDMI_FORCE_COLOR_1           0x508
+#define TVO_HDMI_CLIP_VALUE_B_CB         0x50c
+#define TVO_HDMI_CLIP_VALUE_Y_G          0x510
+#define TVO_HDMI_CLIP_VALUE_R_CR         0x514
+#define TVO_HDMI_SYNC_SEL                0x518
+#define TVO_HDMI_DFV_OBS                 0x540
+
+#define TVO_IN_FMT_SIGNED                BIT(0)
+#define TVO_SYNC_EXT                     BIT(4)
+
+#define TVO_VIP_REORDER_R_SHIFT          24
+#define TVO_VIP_REORDER_G_SHIFT          20
+#define TVO_VIP_REORDER_B_SHIFT          16
+#define TVO_VIP_REORDER_MASK             0x3
+#define TVO_VIP_REORDER_Y_G_SEL          0
+#define TVO_VIP_REORDER_CB_B_SEL         1
+#define TVO_VIP_REORDER_CR_R_SEL         2
+
+#define TVO_VIP_CLIP_SHIFT               8
+#define TVO_VIP_CLIP_MASK                0x7
+#define TVO_VIP_CLIP_DISABLED            0
+#define TVO_VIP_CLIP_EAV_SAV             1
+#define TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y 2
+#define TVO_VIP_CLIP_LIMITED_RANGE_CB_CR 3
+#define TVO_VIP_CLIP_PROG_RANGE          4
+
+#define TVO_VIP_RND_SHIFT                4
+#define TVO_VIP_RND_MASK                 0x3
+#define TVO_VIP_RND_8BIT_ROUNDED         0
+#define TVO_VIP_RND_10BIT_ROUNDED        1
+#define TVO_VIP_RND_12BIT_ROUNDED        2
+
+#define TVO_VIP_SEL_INPUT_MASK           0xf
+#define TVO_VIP_SEL_INPUT_MAIN           0x0
+#define TVO_VIP_SEL_INPUT_AUX            0x8
+#define TVO_VIP_SEL_INPUT_FORCE_COLOR    0xf
+#define TVO_VIP_SEL_INPUT_BYPASS_MASK    0x1
+#define TVO_VIP_SEL_INPUT_BYPASSED       1
+
+#define TVO_SYNC_MAIN_VTG_SET_REF        0x00
+#define TVO_SYNC_MAIN_VTG_SET_1          0x01
+#define TVO_SYNC_MAIN_VTG_SET_2          0x02
+#define TVO_SYNC_MAIN_VTG_SET_3          0x03
+#define TVO_SYNC_MAIN_VTG_SET_4          0x04
+#define TVO_SYNC_MAIN_VTG_SET_5          0x05
+#define TVO_SYNC_MAIN_VTG_SET_6          0x06
+#define TVO_SYNC_AUX_VTG_SET_REF         0x10
+#define TVO_SYNC_AUX_VTG_SET_1           0x11
+#define TVO_SYNC_AUX_VTG_SET_2           0x12
+#define TVO_SYNC_AUX_VTG_SET_3           0x13
+#define TVO_SYNC_AUX_VTG_SET_4           0x14
+#define TVO_SYNC_AUX_VTG_SET_5           0x15
+#define TVO_SYNC_AUX_VTG_SET_6           0x16
+
+#define TVO_SYNC_HD_DCS_SHIFT            8
+
+#define ENCODER_MAIN_CRTC_MASK           BIT(0)
+
+/* enum listing the supported output data format */
+enum sti_tvout_video_out_type {
+	STI_TVOUT_VIDEO_OUT_RGB,
+	STI_TVOUT_VIDEO_OUT_YUV,
+};
+
+struct sti_tvout {
+	struct device *dev;
+	struct drm_device *drm_dev;
+	void __iomem *regs;
+	struct reset_control *reset;
+	struct drm_encoder *hdmi;
+	struct drm_encoder *hda;
+};
+
+struct sti_tvout_encoder {
+	struct drm_encoder encoder;
+	struct sti_tvout *tvout;
+};
+
+#define to_sti_tvout_encoder(x) \
+	container_of(x, struct sti_tvout_encoder, encoder)
+
+#define to_sti_tvout(x) to_sti_tvout_encoder(x)->tvout
+
+/* preformatter conversion matrix */
+static const u32 rgb_to_ycbcr_601[8] = {
+	0xF927082E, 0x04C9FEAB, 0x01D30964, 0xFA95FD3D,
+	0x0000082E, 0x00002000, 0x00002000, 0x00000000
+};
+
+/* 709 RGB to YCbCr */
+static const u32 rgb_to_ycbcr_709[8] = {
+	0xF891082F, 0x0367FF40, 0x01280B71, 0xF9B1FE20,
+	0x0000082F, 0x00002000, 0x00002000, 0x00000000
+};
+
+static u32 tvout_read(struct sti_tvout *tvout, int offset)
+{
+	return readl(tvout->regs + offset);
+}
+
+static void tvout_write(struct sti_tvout *tvout, u32 val, int offset)
+{
+	writel(val, tvout->regs + offset);
+}
+
+/**
+ * Set the clipping mode of a VIP
+ *
+ * @tvout: tvout structure
+ * @cr_r:
+ * @y_g:
+ * @cb_b:
+ */
+static void tvout_vip_set_color_order(struct sti_tvout *tvout,
+				      u32 cr_r, u32 y_g, u32 cb_b)
+{
+	u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT);
+	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT);
+	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT);
+	val |= cr_r << TVO_VIP_REORDER_R_SHIFT;
+	val |= y_g << TVO_VIP_REORDER_G_SHIFT;
+	val |= cb_b << TVO_VIP_REORDER_B_SHIFT;
+
+	tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Set the clipping mode of a VIP
+ *
+ * @tvout: tvout structure
+ * @range: clipping range
+ */
+static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range)
+{
+	u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+	val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT);
+	val |= range << TVO_VIP_CLIP_SHIFT;
+	tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Set the rounded value of a VIP
+ *
+ * @tvout: tvout structure
+ * @rnd: rounded val per component
+ */
+static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd)
+{
+	u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+	val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT);
+	val |= rnd << TVO_VIP_RND_SHIFT;
+	tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Select the VIP input
+ *
+ * @tvout: tvout structure
+ * @sel_input: selected_input (main/aux + conv)
+ */
+static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
+				    bool main_path,
+				    bool sel_input_logic_inverted,
+				    enum sti_tvout_video_out_type video_out)
+{
+	u32 sel_input;
+	u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+	if (main_path)
+		sel_input = TVO_VIP_SEL_INPUT_MAIN;
+	else
+		sel_input = TVO_VIP_SEL_INPUT_AUX;
+
+	switch (video_out) {
+	case STI_TVOUT_VIDEO_OUT_RGB:
+		sel_input |= TVO_VIP_SEL_INPUT_BYPASSED;
+		break;
+	case STI_TVOUT_VIDEO_OUT_YUV:
+		sel_input &= ~TVO_VIP_SEL_INPUT_BYPASSED;
+		break;
+	}
+
+	/* on stih407 chip the sel_input bypass mode logic is inverted */
+	if (sel_input_logic_inverted)
+		sel_input = sel_input ^ TVO_VIP_SEL_INPUT_BYPASS_MASK;
+
+	val &= ~TVO_VIP_SEL_INPUT_MASK;
+	val |= sel_input;
+	tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Select the input video signed or unsigned
+ *
+ * @tvout: tvout structure
+ * @in_vid_signed: used video input format
+ */
+static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt)
+{
+	u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+	val &= ~TVO_IN_FMT_SIGNED;
+	val |= in_vid_fmt;
+	tvout_write(tvout, val, TVO_MAIN_IN_VID_FORMAT);
+}
+
+/**
+ * Start VIP block for HDMI output
+ *
+ * @tvout: pointer on tvout structure
+ * @main_path: true if main path has to be used in the vip configuration
+ *	  else aux path is used.
+ */
+static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
+{
+	struct device_node *node = tvout->dev->of_node;
+	bool sel_input_logic_inverted = false;
+
+	dev_dbg(tvout->dev, "%s\n", __func__);
+
+	if (main_path) {
+		DRM_DEBUG_DRIVER("main vip for hdmi\n");
+		/* select the input sync for hdmi = VTG set 1 */
+		tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL);
+	} else {
+		DRM_DEBUG_DRIVER("aux vip for hdmi\n");
+		/* select the input sync for hdmi = VTG set 1 */
+		tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL);
+	}
+
+	/* set color channel order */
+	tvout_vip_set_color_order(tvout,
+				  TVO_VIP_REORDER_CR_R_SEL,
+				  TVO_VIP_REORDER_Y_G_SEL,
+				  TVO_VIP_REORDER_CB_B_SEL);
+
+	/* set clipping mode (Limited range RGB/Y) */
+	tvout_vip_set_clip_mode(tvout, TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y);
+
+	/* set round mode (rounded to 8-bit per component) */
+	tvout_vip_set_rnd(tvout, TVO_VIP_RND_8BIT_ROUNDED);
+
+	if (of_device_is_compatible(node, "st,stih407-tvout")) {
+		/* set input video format */
+		tvout_vip_set_in_vid_fmt(tvout->regs + TVO_MAIN_IN_VID_FORMAT,
+					 TVO_IN_FMT_SIGNED);
+		sel_input_logic_inverted = true;
+	}
+
+	/* input selection */
+	tvout_vip_set_sel_input(tvout, main_path,
+			sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB);
+}
+
+/**
+ * Start HDF VIP and HD DAC
+ *
+ * @tvout: pointer on tvout structure
+ * @main_path: true if main path has to be used in the vip configuration
+ *	  else aux path is used.
+ */
+static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
+{
+	struct device_node *node = tvout->dev->of_node;
+	bool sel_input_logic_inverted = false;
+
+	dev_dbg(tvout->dev, "%s\n", __func__);
+
+	if (!main_path) {
+		DRM_ERROR("HD Analog on aux not implemented\n");
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("main vip for HDF\n");
+
+	/* set color channel order */
+	tvout_vip_set_color_order(tvout->regs + TVO_VIP_HDF,
+				  TVO_VIP_REORDER_CR_R_SEL,
+				  TVO_VIP_REORDER_Y_G_SEL,
+				  TVO_VIP_REORDER_CB_B_SEL);
+
+	/* set clipping mode (Limited range RGB/Y) */
+	tvout_vip_set_clip_mode(tvout->regs + TVO_VIP_HDF,
+				TVO_VIP_CLIP_LIMITED_RANGE_CB_CR);
+
+	/* set round mode (rounded to 10-bit per component) */
+	tvout_vip_set_rnd(tvout->regs + TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);
+
+	if (of_device_is_compatible(node, "st,stih407-tvout")) {
+		/* set input video format */
+		tvout_vip_set_in_vid_fmt(tvout, TVO_IN_FMT_SIGNED);
+		sel_input_logic_inverted = true;
+	}
+
+	/* Input selection */
+	tvout_vip_set_sel_input(tvout->regs + TVO_VIP_HDF,
+				main_path,
+				sel_input_logic_inverted,
+				STI_TVOUT_VIDEO_OUT_YUV);
+
+	/* select the input sync for HD analog = VTG set 3
+	 * and HD DCS = VTG set 2 */
+	tvout_write(tvout,
+		(TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT)
+		| TVO_SYNC_MAIN_VTG_SET_3,
+		TVO_HD_SYNC_SEL);
+
+	/* power up HD DAC */
+	tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
+}
+
+static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+static bool sti_tvout_encoder_mode_fixup(struct drm_encoder *encoder,
+				       const struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void sti_tvout_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void sti_tvout_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder);
+
+	drm_encoder_cleanup(encoder);
+	kfree(sti_encoder);
+}
+
+static const struct drm_encoder_funcs sti_tvout_encoder_funcs = {
+	.destroy = sti_tvout_encoder_destroy,
+};
+
+static void sti_hda_encoder_commit(struct drm_encoder *encoder)
+{
+	struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+	tvout_hda_start(tvout, true);
+}
+
+static void sti_hda_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+	/* reset VIP register */
+	tvout_write(tvout, 0x0, TVO_VIP_HDF);
+
+	/* power down HD DAC */
+	tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF);
+}
+
+static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = {
+	.dpms = sti_tvout_encoder_dpms,
+	.mode_fixup = sti_tvout_encoder_mode_fixup,
+	.mode_set = sti_tvout_encoder_mode_set,
+	.prepare = sti_tvout_encoder_prepare,
+	.commit = sti_hda_encoder_commit,
+	.disable = sti_hda_encoder_disable,
+};
+
+static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
+		struct sti_tvout *tvout)
+{
+	struct sti_tvout_encoder *encoder;
+	struct drm_encoder *drm_encoder;
+
+	encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
+	if (!encoder)
+		return NULL;
+
+	encoder->tvout = tvout;
+
+	drm_encoder = (struct drm_encoder *) encoder;
+
+	drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+	drm_encoder->possible_clones = 1 << 0;
+
+	drm_encoder_init(dev, drm_encoder,
+			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC);
+
+	drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs);
+
+	return drm_encoder;
+}
+
+static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
+{
+	struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+	tvout_hdmi_start(tvout, true);
+}
+
+static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+	/* reset VIP register */
+	tvout_write(tvout, 0x0, TVO_VIP_HDMI);
+}
+
+static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = {
+	.dpms = sti_tvout_encoder_dpms,
+	.mode_fixup = sti_tvout_encoder_mode_fixup,
+	.mode_set = sti_tvout_encoder_mode_set,
+	.prepare = sti_tvout_encoder_prepare,
+	.commit = sti_hdmi_encoder_commit,
+	.disable = sti_hdmi_encoder_disable,
+};
+
+static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
+		struct sti_tvout *tvout)
+{
+	struct sti_tvout_encoder *encoder;
+	struct drm_encoder *drm_encoder;
+
+	encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
+	if (!encoder)
+		return NULL;
+
+	encoder->tvout = tvout;
+
+	drm_encoder = (struct drm_encoder *) encoder;
+
+	drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+	drm_encoder->possible_clones = 1 << 1;
+
+	drm_encoder_init(dev, drm_encoder,
+			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS);
+
+	drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs);
+
+	return drm_encoder;
+}
+
+static void sti_tvout_create_encoders(struct drm_device *dev,
+		struct sti_tvout *tvout)
+{
+	tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout);
+	tvout->hda = sti_tvout_create_hda_encoder(dev, tvout);
+}
+
+static void sti_tvout_destroy_encoders(struct sti_tvout *tvout)
+{
+	if (tvout->hdmi)
+		drm_encoder_cleanup(tvout->hdmi);
+	tvout->hdmi = NULL;
+
+	if (tvout->hda)
+		drm_encoder_cleanup(tvout->hda);
+	tvout->hda = NULL;
+}
+
+static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
+{
+	struct sti_tvout *tvout = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	unsigned int i;
+	int ret;
+
+	tvout->drm_dev = drm_dev;
+
+	/* set preformatter matrix */
+	for (i = 0; i < 8; i++) {
+		tvout_write(tvout, rgb_to_ycbcr_601[i],
+			TVO_CSC_MAIN_M0 + (i * 4));
+		tvout_write(tvout, rgb_to_ycbcr_601[i],
+			TVO_CSC_AUX_M0 + (i * 4));
+	}
+
+	sti_tvout_create_encoders(drm_dev, tvout);
+
+	ret = component_bind_all(dev, drm_dev);
+	if (ret)
+		sti_tvout_destroy_encoders(tvout);
+
+	return ret;
+}
+
+static void sti_tvout_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops sti_tvout_ops = {
+	.bind	= sti_tvout_bind,
+	.unbind	= sti_tvout_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int sti_tvout_master_bind(struct device *dev)
+{
+	return 0;
+}
+
+static void sti_tvout_master_unbind(struct device *dev)
+{
+	/* do nothing */
+}
+
+static const struct component_master_ops sti_tvout_master_ops = {
+	.bind = sti_tvout_master_bind,
+	.unbind = sti_tvout_master_unbind,
+};
+
+static int sti_tvout_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct sti_tvout *tvout;
+	struct resource *res;
+	struct device_node *child_np;
+	struct component_match *match = NULL;
+
+	DRM_INFO("%s\n", __func__);
+
+	if (!node)
+		return -ENODEV;
+
+	tvout = devm_kzalloc(dev, sizeof(*tvout), GFP_KERNEL);
+	if (!tvout)
+		return -ENOMEM;
+
+	tvout->dev = dev;
+
+	/* get Memory ressources */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg");
+	if (!res) {
+		DRM_ERROR("Invalid glue resource\n");
+		return -ENOMEM;
+	}
+	tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!tvout->regs)
+		return -ENOMEM;
+
+	/* get reset resources */
+	tvout->reset = devm_reset_control_get(dev, "tvout");
+	/* take tvout out of reset */
+	if (!IS_ERR(tvout->reset))
+		reset_control_deassert(tvout->reset);
+
+	platform_set_drvdata(pdev, tvout);
+
+	of_platform_populate(node, NULL, NULL, dev);
+
+	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);
+		child_np = of_get_next_available_child(node, child_np);
+	}
+
+	component_master_add_with_match(dev, &sti_tvout_master_ops, match);
+
+	return component_add(dev, &sti_tvout_ops);
+}
+
+static int sti_tvout_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &sti_tvout_master_ops);
+	component_del(&pdev->dev, &sti_tvout_ops);
+	return 0;
+}
+
+static const struct of_device_id tvout_of_match[] = {
+	{ .compatible = "st,stih416-tvout", },
+	{ .compatible = "st,stih407-tvout", },
+	{ /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, tvout_of_match);
+
+struct platform_driver sti_tvout_driver = {
+	.driver = {
+		.name = "sti-tvout",
+		.owner = THIS_MODULE,
+		.of_match_table = tvout_of_match,
+	},
+	.probe = sti_tvout_probe,
+	.remove = sti_tvout_remove,
+};
+
+module_platform_driver(sti_tvout_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vid.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vid.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vid.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vid.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+
+#include "sti_layer.h"
+#include "sti_vid.h"
+#include "sti_vtg.h"
+
+/* Registers */
+#define VID_CTL                 0x00
+#define VID_ALP                 0x04
+#define VID_CLF                 0x08
+#define VID_VPO                 0x0C
+#define VID_VPS                 0x10
+#define VID_KEY1                0x28
+#define VID_KEY2                0x2C
+#define VID_MPR0                0x30
+#define VID_MPR1                0x34
+#define VID_MPR2                0x38
+#define VID_MPR3                0x3C
+#define VID_MST                 0x68
+#define VID_BC                  0x70
+#define VID_TINT                0x74
+#define VID_CSAT                0x78
+
+/* Registers values */
+#define VID_CTL_IGNORE          (BIT(31) | BIT(30))
+#define VID_CTL_PSI_ENABLE      (BIT(2) | BIT(1) | BIT(0))
+#define VID_ALP_OPAQUE          0x00000080
+#define VID_BC_DFLT             0x00008000
+#define VID_TINT_DFLT           0x00000000
+#define VID_CSAT_DFLT           0x00000080
+/* YCbCr to RGB BT709:
+ * R = Y+1.5391Cr
+ * G = Y-0.4590Cr-0.1826Cb
+ * B = Y+1.8125Cb */
+#define VID_MPR0_BT709          0x0A800000
+#define VID_MPR1_BT709          0x0AC50000
+#define VID_MPR2_BT709          0x07150545
+#define VID_MPR3_BT709          0x00000AE8
+
+static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
+{
+	u32 val;
+
+	/* Unmask */
+	val = readl(vid->regs + VID_CTL);
+	val &= ~VID_CTL_IGNORE;
+	writel(val, vid->regs + VID_CTL);
+
+	return 0;
+}
+
+static int sti_vid_commit_layer(struct sti_layer *vid)
+{
+	struct drm_display_mode *mode = vid->mode;
+	u32 ydo, xdo, yds, xds;
+
+	ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
+	yds = sti_vtg_get_line_number(*mode, vid->dst_y + vid->dst_h - 1);
+	xdo = sti_vtg_get_pixel_number(*mode, vid->dst_x);
+	xds = sti_vtg_get_pixel_number(*mode, vid->dst_x + vid->dst_w - 1);
+
+	writel((ydo << 16) | xdo, vid->regs + VID_VPO);
+	writel((yds << 16) | xds, vid->regs + VID_VPS);
+
+	return 0;
+}
+
+static int sti_vid_disable_layer(struct sti_layer *vid)
+{
+	u32 val;
+
+	/* Mask */
+	val = readl(vid->regs + VID_CTL);
+	val |= VID_CTL_IGNORE;
+	writel(val, vid->regs + VID_CTL);
+
+	return 0;
+}
+
+static const uint32_t *sti_vid_get_formats(struct sti_layer *layer)
+{
+	return NULL;
+}
+
+static unsigned int sti_vid_get_nb_formats(struct sti_layer *layer)
+{
+	return 0;
+}
+
+static void sti_vid_init(struct sti_layer *vid)
+{
+	/* Enable PSI, Mask layer */
+	writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
+
+	/* Opaque */
+	writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);
+
+	/* Color conversion parameters */
+	writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
+	writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
+	writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
+	writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
+
+	/* Brightness, contrast, tint, saturation */
+	writel(VID_BC_DFLT, vid->regs + VID_BC);
+	writel(VID_TINT_DFLT, vid->regs + VID_TINT);
+	writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
+}
+
+static const struct sti_layer_funcs vid_ops = {
+	.get_formats = sti_vid_get_formats,
+	.get_nb_formats = sti_vid_get_nb_formats,
+	.init = sti_vid_init,
+	.prepare = sti_vid_prepare_layer,
+	.commit = sti_vid_commit_layer,
+	.disable = sti_vid_disable_layer,
+};
+
+struct sti_layer *sti_vid_create(struct device *dev)
+{
+	struct sti_layer *vid;
+
+	vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
+	if (!vid) {
+		DRM_ERROR("Failed to allocate memory for VID\n");
+		return NULL;
+	}
+
+	vid->ops = &vid_ops;
+
+	return vid;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vid.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vid.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vid.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vid.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_VID_H_
+#define _STI_VID_H_
+
+struct sti_layer *sti_vid_create(struct device *dev);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtac.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtac.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtac.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+/* registers offset */
+#define VTAC_CONFIG                     0x00
+#define VTAC_RX_FIFO_CONFIG             0x04
+#define VTAC_FIFO_CONFIG_VAL            0x04
+
+#define VTAC_SYS_CFG8521                0x824
+#define VTAC_SYS_CFG8522                0x828
+
+/* Number of phyts per pixel */
+#define VTAC_2_5_PPP                    0x0005
+#define VTAC_3_PPP                      0x0006
+#define VTAC_4_PPP                      0x0008
+#define VTAC_5_PPP                      0x000A
+#define VTAC_6_PPP                      0x000C
+#define VTAC_13_PPP                     0x001A
+#define VTAC_14_PPP                     0x001C
+#define VTAC_15_PPP                     0x001E
+#define VTAC_16_PPP                     0x0020
+#define VTAC_17_PPP                     0x0022
+#define VTAC_18_PPP                     0x0024
+
+/* enable bits */
+#define VTAC_ENABLE                     0x3003
+
+#define VTAC_TX_PHY_ENABLE_CLK_PHY      BIT(0)
+#define VTAC_TX_PHY_ENABLE_CLK_DLL      BIT(1)
+#define VTAC_TX_PHY_PLL_NOT_OSC_MODE    BIT(3)
+#define VTAC_TX_PHY_RST_N_DLL_SWITCH    BIT(4)
+#define VTAC_TX_PHY_PROG_N3             BIT(9)
+
+
+/**
+ * VTAC mode structure
+ *
+ * @vid_in_width: Video Data Resolution
+ * @phyts_width: Width of phyt buses(phyt low and phyt high).
+ * @phyts_per_pixel: Number of phyts sent per pixel
+ */
+struct sti_vtac_mode {
+	u32 vid_in_width;
+	u32 phyts_width;
+	u32 phyts_per_pixel;
+};
+
+static const struct sti_vtac_mode vtac_mode_main = {0x2, 0x2, VTAC_5_PPP};
+static const struct sti_vtac_mode vtac_mode_aux = {0x1, 0x0, VTAC_17_PPP};
+
+/**
+ * VTAC structure
+ *
+ * @dev: pointer to device structure
+ * @regs: ioremapped registers for RX and TX devices
+ * @phy_regs: phy registers for TX device
+ * @clk: clock
+ * @mode: main or auxillary configuration mode
+ */
+struct sti_vtac {
+	struct device *dev;
+	void __iomem *regs;
+	void __iomem *phy_regs;
+	struct clk *clk;
+	const struct sti_vtac_mode *mode;
+};
+
+static void sti_vtac_rx_set_config(struct sti_vtac *vtac)
+{
+	u32 config;
+
+	/* Enable VTAC clock */
+	if (clk_prepare_enable(vtac->clk))
+		DRM_ERROR("Failed to prepare/enable vtac_rx clock.\n");
+
+	writel(VTAC_FIFO_CONFIG_VAL, vtac->regs + VTAC_RX_FIFO_CONFIG);
+
+	config = VTAC_ENABLE;
+	config |= vtac->mode->vid_in_width << 4;
+	config |= vtac->mode->phyts_width << 16;
+	config |= vtac->mode->phyts_per_pixel << 23;
+	writel(config, vtac->regs + VTAC_CONFIG);
+}
+
+static void sti_vtac_tx_set_config(struct sti_vtac *vtac)
+{
+	u32 phy_config;
+	u32 config;
+
+	/* Enable VTAC clock */
+	if (clk_prepare_enable(vtac->clk))
+		DRM_ERROR("Failed to prepare/enable vtac_tx clock.\n");
+
+	/* Configure vtac phy */
+	phy_config = 0x00000000;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8522);
+	phy_config = VTAC_TX_PHY_ENABLE_CLK_PHY;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config |= VTAC_TX_PHY_PROG_N3;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config |= VTAC_TX_PHY_ENABLE_CLK_DLL;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config |= VTAC_TX_PHY_RST_N_DLL_SWITCH;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+	phy_config |= VTAC_TX_PHY_PLL_NOT_OSC_MODE;
+	writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+
+	/* Configure vtac tx */
+	config = VTAC_ENABLE;
+	config |= vtac->mode->vid_in_width << 4;
+	config |= vtac->mode->phyts_width << 16;
+	config |= vtac->mode->phyts_per_pixel << 23;
+	writel(config, vtac->regs + VTAC_CONFIG);
+}
+
+static const struct of_device_id vtac_of_match[] = {
+	{
+		.compatible = "st,vtac-main",
+		.data = &vtac_mode_main,
+	}, {
+		.compatible = "st,vtac-aux",
+		.data = &vtac_mode_aux,
+	}, {
+		/* end node */
+	}
+};
+MODULE_DEVICE_TABLE(of, vtac_of_match);
+
+static int sti_vtac_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct of_device_id *id;
+	struct sti_vtac *vtac;
+	struct resource *res;
+
+	vtac = devm_kzalloc(dev, sizeof(*vtac), GFP_KERNEL);
+	if (!vtac)
+		return -ENOMEM;
+
+	vtac->dev = dev;
+
+	id = of_match_node(vtac_of_match, np);
+	if (!id)
+		return -ENOMEM;
+
+	vtac->mode = id->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		DRM_ERROR("Invalid resource\n");
+		return -ENOMEM;
+	}
+	vtac->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vtac->regs))
+		return PTR_ERR(vtac->regs);
+
+
+	vtac->clk = devm_clk_get(dev, "vtac");
+	if (IS_ERR(vtac->clk)) {
+		DRM_ERROR("Cannot get vtac clock\n");
+		return PTR_ERR(vtac->clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res) {
+		vtac->phy_regs = devm_ioremap_nocache(dev, res->start,
+						 resource_size(res));
+		sti_vtac_tx_set_config(vtac);
+	} else {
+
+		sti_vtac_rx_set_config(vtac);
+	}
+
+	platform_set_drvdata(pdev, vtac);
+	DRM_INFO("%s %s\n", __func__, dev_name(vtac->dev));
+
+	return 0;
+}
+
+static int sti_vtac_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+struct platform_driver sti_vtac_driver = {
+	.driver = {
+		.name = "sti-vtac",
+		.owner = THIS_MODULE,
+		.of_match_table = vtac_of_match,
+	},
+	.probe = sti_vtac_probe,
+	.remove = sti_vtac_remove,
+};
+
+module_platform_driver(sti_vtac_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtg.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtg.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtg.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          Vincent Abriou <vincent.abriou@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+#include "sti_vtg.h"
+
+#define VTG_TYPE_MASTER         0
+#define VTG_TYPE_SLAVE_BY_EXT0  1
+
+/* registers offset */
+#define VTG_MODE            0x0000
+#define VTG_CLKLN           0x0008
+#define VTG_HLFLN           0x000C
+#define VTG_DRST_AUTOC      0x0010
+#define VTG_VID_TFO         0x0040
+#define VTG_VID_TFS         0x0044
+#define VTG_VID_BFO         0x0048
+#define VTG_VID_BFS         0x004C
+
+#define VTG_HOST_ITS        0x0078
+#define VTG_HOST_ITS_BCLR   0x007C
+#define VTG_HOST_ITM_BCLR   0x0088
+#define VTG_HOST_ITM_BSET   0x008C
+
+#define VTG_H_HD_1          0x00C0
+#define VTG_TOP_V_VD_1      0x00C4
+#define VTG_BOT_V_VD_1      0x00C8
+#define VTG_TOP_V_HD_1      0x00CC
+#define VTG_BOT_V_HD_1      0x00D0
+
+#define VTG_H_HD_2          0x00E0
+#define VTG_TOP_V_VD_2      0x00E4
+#define VTG_BOT_V_VD_2      0x00E8
+#define VTG_TOP_V_HD_2      0x00EC
+#define VTG_BOT_V_HD_2      0x00F0
+
+#define VTG_H_HD_3          0x0100
+#define VTG_TOP_V_VD_3      0x0104
+#define VTG_BOT_V_VD_3      0x0108
+#define VTG_TOP_V_HD_3      0x010C
+#define VTG_BOT_V_HD_3      0x0110
+
+#define VTG_IRQ_BOTTOM      BIT(0)
+#define VTG_IRQ_TOP         BIT(1)
+#define VTG_IRQ_MASK        (VTG_IRQ_TOP | VTG_IRQ_BOTTOM)
+
+/* delay introduced by the Arbitrary Waveform Generator in nb of pixels */
+#define AWG_DELAY_HD        (-9)
+#define AWG_DELAY_ED        (-8)
+#define AWG_DELAY_SD        (-7)
+
+LIST_HEAD(vtg_lookup);
+
+/**
+ * STI VTG structure
+ *
+ * @dev: pointer to device driver
+ * @data: data associated to the device
+ * @irq: VTG irq
+ * @type: VTG type (main or aux)
+ * @notifier_list: notifier callback
+ * @crtc_id: the crtc id for vblank event
+ * @slave: slave vtg
+ * @link: List node to link the structure in lookup list
+ */
+struct sti_vtg {
+	struct device *dev;
+	struct device_node *np;
+	void __iomem *regs;
+	int irq;
+	u32 irq_status;
+	struct raw_notifier_head notifier_list;
+	int crtc_id;
+	struct sti_vtg *slave;
+	struct list_head link;
+};
+
+static void vtg_register(struct sti_vtg *vtg)
+{
+	list_add_tail(&vtg->link, &vtg_lookup);
+}
+
+struct sti_vtg *of_vtg_find(struct device_node *np)
+{
+	struct sti_vtg *vtg;
+
+	list_for_each_entry(vtg, &vtg_lookup, link) {
+		if (vtg->np == np)
+			return vtg;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(of_vtg_find);
+
+static void vtg_reset(struct sti_vtg *vtg)
+{
+	/* reset slave and then master */
+	if (vtg->slave)
+		vtg_reset(vtg->slave);
+
+	writel(1, vtg->regs + VTG_DRST_AUTOC);
+}
+
+static void vtg_set_mode(struct sti_vtg *vtg,
+			 int type, const struct drm_display_mode *mode)
+{
+	u32 tmp;
+
+	if (vtg->slave)
+		vtg_set_mode(vtg->slave, VTG_TYPE_SLAVE_BY_EXT0, mode);
+
+	writel(mode->htotal, vtg->regs + VTG_CLKLN);
+	writel(mode->vtotal * 2, vtg->regs + VTG_HLFLN);
+
+	tmp = (mode->vtotal - mode->vsync_start + 1) << 16;
+	tmp |= mode->htotal - mode->hsync_start;
+	writel(tmp, vtg->regs + VTG_VID_TFO);
+	writel(tmp, vtg->regs + VTG_VID_BFO);
+
+	tmp = (mode->vdisplay + mode->vtotal - mode->vsync_start + 1) << 16;
+	tmp |= mode->hdisplay + mode->htotal - mode->hsync_start;
+	writel(tmp, vtg->regs + VTG_VID_TFS);
+	writel(tmp, vtg->regs + VTG_VID_BFS);
+
+	/* prepare VTG set 1 and 2 for HDMI and VTG set 3 for HD DAC */
+	tmp = (mode->hsync_end - mode->hsync_start) << 16;
+	writel(tmp, vtg->regs + VTG_H_HD_1);
+	writel(tmp, vtg->regs + VTG_H_HD_2);
+
+	tmp = (mode->vsync_end - mode->vsync_start + 1) << 16;
+	tmp |= 1;
+	writel(tmp, vtg->regs + VTG_TOP_V_VD_1);
+	writel(tmp, vtg->regs + VTG_BOT_V_VD_1);
+	writel(0, vtg->regs + VTG_TOP_V_HD_1);
+	writel(0, vtg->regs + VTG_BOT_V_HD_1);
+
+	/* prepare VTG set 2 for for HD DCS */
+	writel(tmp, vtg->regs + VTG_TOP_V_VD_2);
+	writel(tmp, vtg->regs + VTG_BOT_V_VD_2);
+	writel(0, vtg->regs + VTG_TOP_V_HD_2);
+	writel(0, vtg->regs + VTG_BOT_V_HD_2);
+
+	/* prepare VTG set 3 for HD Analog in HD mode */
+	tmp = (mode->hsync_end - mode->hsync_start + AWG_DELAY_HD) << 16;
+	tmp |= mode->htotal + AWG_DELAY_HD;
+	writel(tmp, vtg->regs + VTG_H_HD_3);
+
+	tmp = (mode->vsync_end - mode->vsync_start) << 16;
+	tmp |= mode->vtotal;
+	writel(tmp, vtg->regs + VTG_TOP_V_VD_3);
+	writel(tmp, vtg->regs + VTG_BOT_V_VD_3);
+
+	tmp = (mode->htotal + AWG_DELAY_HD) << 16;
+	tmp |= mode->htotal + AWG_DELAY_HD;
+	writel(tmp, vtg->regs + VTG_TOP_V_HD_3);
+	writel(tmp, vtg->regs + VTG_BOT_V_HD_3);
+
+	/* mode */
+	writel(type, vtg->regs + VTG_MODE);
+}
+
+static void vtg_enable_irq(struct sti_vtg *vtg)
+{
+	/* clear interrupt status and mask */
+	writel(0xFFFF, vtg->regs + VTG_HOST_ITS_BCLR);
+	writel(0xFFFF, vtg->regs + VTG_HOST_ITM_BCLR);
+	writel(VTG_IRQ_MASK, vtg->regs + VTG_HOST_ITM_BSET);
+}
+
+void sti_vtg_set_config(struct sti_vtg *vtg,
+		const struct drm_display_mode *mode)
+{
+	/* write configuration */
+	vtg_set_mode(vtg, VTG_TYPE_MASTER, mode);
+
+	vtg_reset(vtg);
+
+	/* enable irq for the vtg vblank synchro */
+	if (vtg->slave)
+		vtg_enable_irq(vtg->slave);
+	else
+		vtg_enable_irq(vtg);
+}
+EXPORT_SYMBOL(sti_vtg_set_config);
+
+/**
+ * sti_vtg_get_line_number
+ *
+ * @mode: display mode to be used
+ * @y:    line
+ *
+ * Return the line number according to the display mode taking
+ * into account the Sync and Back Porch information.
+ * Video frame line numbers start at 1, y starts at 0.
+ * In interlaced modes the start line is the field line number of the odd
+ * field, but y is still defined as a progressive frame.
+ */
+u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
+{
+	u32 start_line = mode.vtotal - mode.vsync_start + 1;
+
+	if (mode.flags & DRM_MODE_FLAG_INTERLACE)
+		start_line *= 2;
+
+	return start_line + y;
+}
+EXPORT_SYMBOL(sti_vtg_get_line_number);
+
+/**
+ * sti_vtg_get_pixel_number
+ *
+ * @mode: display mode to be used
+ * @x:    row
+ *
+ * Return the pixel number according to the display mode taking
+ * into account the Sync and Back Porch information.
+ * Pixels are counted from 0.
+ */
+u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
+{
+	return mode.htotal - mode.hsync_start + x;
+}
+EXPORT_SYMBOL(sti_vtg_get_pixel_number);
+
+int sti_vtg_register_client(struct sti_vtg *vtg,
+		struct notifier_block *nb, int crtc_id)
+{
+	if (vtg->slave)
+		return sti_vtg_register_client(vtg->slave, nb, crtc_id);
+
+	vtg->crtc_id = crtc_id;
+	return raw_notifier_chain_register(&vtg->notifier_list, nb);
+}
+EXPORT_SYMBOL(sti_vtg_register_client);
+
+int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
+{
+	if (vtg->slave)
+		return sti_vtg_unregister_client(vtg->slave, nb);
+
+	return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
+}
+EXPORT_SYMBOL(sti_vtg_unregister_client);
+
+static irqreturn_t vtg_irq_thread(int irq, void *arg)
+{
+	struct sti_vtg *vtg = arg;
+	u32 event;
+
+	event = (vtg->irq_status & VTG_IRQ_TOP) ?
+		VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
+
+	raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t vtg_irq(int irq, void *arg)
+{
+	struct sti_vtg *vtg = arg;
+
+	vtg->irq_status = readl(vtg->regs + VTG_HOST_ITS);
+
+	writel(vtg->irq_status, vtg->regs + VTG_HOST_ITS_BCLR);
+
+	/* force sync bus write */
+	readl(vtg->regs + VTG_HOST_ITS);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static int vtg_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np;
+	struct sti_vtg *vtg;
+	struct resource *res;
+	char irq_name[32];
+	int ret;
+
+	vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL);
+	if (!vtg)
+		return -ENOMEM;
+
+	vtg->dev = dev;
+	vtg->np = pdev->dev.of_node;
+
+	/* Get Memory ressources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		DRM_ERROR("Get memory resource failed\n");
+		return -ENOMEM;
+	}
+	vtg->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+
+	np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0);
+	if (np) {
+		vtg->slave = of_vtg_find(np);
+
+		if (!vtg->slave)
+			return -EPROBE_DEFER;
+	} else {
+		vtg->irq = platform_get_irq(pdev, 0);
+		if (IS_ERR_VALUE(vtg->irq)) {
+			DRM_ERROR("Failed to get VTG interrupt\n");
+			return vtg->irq;
+		}
+
+		snprintf(irq_name, sizeof(irq_name), "vsync-%s",
+				dev_name(vtg->dev));
+
+		RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list);
+
+		ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
+				vtg_irq_thread, IRQF_ONESHOT, irq_name, vtg);
+		if (IS_ERR_VALUE(ret)) {
+			DRM_ERROR("Failed to register VTG interrupt\n");
+			return ret;
+		}
+	}
+
+	vtg_register(vtg);
+	platform_set_drvdata(pdev, vtg);
+
+	DRM_INFO("%s %s\n", __func__, dev_name(vtg->dev));
+
+	return 0;
+}
+
+static int vtg_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id vtg_of_match[] = {
+	{ .compatible = "st,vtg", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vtg_of_match);
+
+struct platform_driver sti_vtg_driver = {
+	.driver = {
+		.name = "sti-vtg",
+		.owner = THIS_MODULE,
+		.of_match_table = vtg_of_match,
+	},
+	.probe	= vtg_probe,
+	.remove = vtg_remove,
+};
+
+module_platform_driver(sti_vtg_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtg.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtg.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/sti/sti_vtg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/sti/sti_vtg.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_VTG_H_
+#define _STI_VTG_H_
+
+#define VTG_TOP_FIELD_EVENT     1
+#define VTG_BOTTOM_FIELD_EVENT  2
+
+struct sti_vtg;
+struct drm_display_mode;
+struct notifier_block;
+
+struct sti_vtg *of_vtg_find(struct device_node *np);
+void sti_vtg_set_config(struct sti_vtg *vtg,
+		const struct drm_display_mode *mode);
+int sti_vtg_register_client(struct sti_vtg *vtg,
+		struct notifier_block *nb, int crtc_id);
+int sti_vtg_unregister_client(struct sti_vtg *vtg,
+		struct notifier_block *nb);
+
+u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y);
+u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dc.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,8 @@
 struct tegra_dc_soc_info {
 	bool supports_interlacing;
 	bool supports_cursor;
+	bool supports_block_linear;
+	unsigned int pitch_align;
 };
 
 struct tegra_plane {
@@ -212,15 +214,44 @@ static int tegra_dc_setup_window(struct
 	tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
 	tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
 
-	if (window->tiled) {
-		value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
-			DC_WIN_BUFFER_ADDR_MODE_TILE;
+	if (dc->soc->supports_block_linear) {
+		unsigned long height = window->tiling.value;
+
+		switch (window->tiling.mode) {
+		case TEGRA_BO_TILING_MODE_PITCH:
+			value = DC_WINBUF_SURFACE_KIND_PITCH;
+			break;
+
+		case TEGRA_BO_TILING_MODE_TILED:
+			value = DC_WINBUF_SURFACE_KIND_TILED;
+			break;
+
+		case TEGRA_BO_TILING_MODE_BLOCK:
+			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+				DC_WINBUF_SURFACE_KIND_BLOCK;
+			break;
+		}
+
+		tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
 	} else {
-		value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
-			DC_WIN_BUFFER_ADDR_MODE_LINEAR;
-	}
+		switch (window->tiling.mode) {
+		case TEGRA_BO_TILING_MODE_PITCH:
+			value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+				DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+			break;
 
-	tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+		case TEGRA_BO_TILING_MODE_TILED:
+			value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+				DC_WIN_BUFFER_ADDR_MODE_TILE;
+			break;
+
+		case TEGRA_BO_TILING_MODE_BLOCK:
+			DRM_ERROR("hardware doesn't support block linear mode\n");
+			return -EINVAL;
+		}
+
+		tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+	}
 
 	value = WIN_ENABLE;
 
@@ -288,6 +319,7 @@ static int tegra_plane_update(struct drm
 	struct tegra_dc *dc = to_tegra_dc(crtc);
 	struct tegra_dc_window window;
 	unsigned int i;
+	int err;
 
 	memset(&window, 0, sizeof(window));
 	window.src.x = src_x >> 16;
@@ -301,7 +333,10 @@ static int tegra_plane_update(struct drm
 	window.format = tegra_dc_format(fb->pixel_format, &window.swap);
 	window.bits_per_pixel = fb->bits_per_pixel;
 	window.bottom_up = tegra_fb_is_bottom_up(fb);
-	window.tiled = tegra_fb_is_tiled(fb);
+
+	err = tegra_fb_get_tiling(fb, &window.tiling);
+	if (err < 0)
+		return err;
 
 	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
 		struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
@@ -402,8 +437,14 @@ static int tegra_dc_set_base(struct tegr
 {
 	struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
 	unsigned int h_offset = 0, v_offset = 0;
+	struct tegra_bo_tiling tiling;
 	unsigned int format, swap;
 	unsigned long value;
+	int err;
+
+	err = tegra_fb_get_tiling(fb, &tiling);
+	if (err < 0)
+		return err;
 
 	tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
 
@@ -417,15 +458,44 @@ static int tegra_dc_set_base(struct tegr
 	tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
 	tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
 
-	if (tegra_fb_is_tiled(fb)) {
-		value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
-			DC_WIN_BUFFER_ADDR_MODE_TILE;
+	if (dc->soc->supports_block_linear) {
+		unsigned long height = tiling.value;
+
+		switch (tiling.mode) {
+		case TEGRA_BO_TILING_MODE_PITCH:
+			value = DC_WINBUF_SURFACE_KIND_PITCH;
+			break;
+
+		case TEGRA_BO_TILING_MODE_TILED:
+			value = DC_WINBUF_SURFACE_KIND_TILED;
+			break;
+
+		case TEGRA_BO_TILING_MODE_BLOCK:
+			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+				DC_WINBUF_SURFACE_KIND_BLOCK;
+			break;
+		}
+
+		tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
 	} else {
-		value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
-			DC_WIN_BUFFER_ADDR_MODE_LINEAR;
-	}
+		switch (tiling.mode) {
+		case TEGRA_BO_TILING_MODE_PITCH:
+			value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+				DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+			break;
 
-	tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+		case TEGRA_BO_TILING_MODE_TILED:
+			value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+				DC_WIN_BUFFER_ADDR_MODE_TILE;
+			break;
+
+		case TEGRA_BO_TILING_MODE_BLOCK:
+			DRM_ERROR("hardware doesn't support block linear mode\n");
+			return -EINVAL;
+		}
+
+		tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+	}
 
 	/* make sure bottom-up buffers are properly displayed */
 	if (tegra_fb_is_bottom_up(fb)) {
@@ -1214,12 +1284,20 @@ static int tegra_dc_init(struct host1x_c
 {
 	struct drm_device *drm = dev_get_drvdata(client->parent);
 	struct tegra_dc *dc = host1x_client_to_dc(client);
+	struct tegra_drm *tegra = drm->dev_private;
 	int err;
 
 	drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
 
+	/*
+	 * Keep track of the minimum pitch alignment across all display
+	 * controllers.
+	 */
+	if (dc->soc->pitch_align > tegra->pitch_align)
+		tegra->pitch_align = dc->soc->pitch_align;
+
 	err = tegra_dc_rgb_init(drm, dc);
 	if (err < 0 && err != -ENODEV) {
 		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
@@ -1277,16 +1355,29 @@ static const struct host1x_client_ops dc
 static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.supports_interlacing = false,
 	.supports_cursor = false,
+	.supports_block_linear = false,
+	.pitch_align = 8,
 };
 
 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.supports_interlacing = false,
 	.supports_cursor = false,
+	.supports_block_linear = false,
+	.pitch_align = 8,
+};
+
+static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
+	.supports_interlacing = false,
+	.supports_cursor = false,
+	.supports_block_linear = false,
+	.pitch_align = 64,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.supports_interlacing = true,
 	.supports_cursor = true,
+	.supports_block_linear = true,
+	.pitch_align = 64,
 };
 
 static const struct of_device_id tegra_dc_of_match[] = {
@@ -1303,6 +1394,7 @@ static const struct of_device_id tegra_d
 		/* sentinel */
 	}
 };
+MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
 
 static int tegra_dc_parse_dt(struct tegra_dc *dc)
 {
@@ -1430,6 +1522,7 @@ static int tegra_dc_remove(struct platfo
 		return err;
 	}
 
+	reset_control_assert(dc->rst);
 	clk_disable_unprepare(dc->clk);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dc.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dc.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dc.h	2014-09-28 17:29:07.000000000 -0400
@@ -428,6 +428,11 @@
 #define DC_WINBUF_ADDR_V_OFFSET_NS		0x809
 
 #define DC_WINBUF_UFLOW_STATUS			0x80a
+#define DC_WINBUF_SURFACE_KIND			0x80b
+#define DC_WINBUF_SURFACE_KIND_PITCH	(0 << 0)
+#define DC_WINBUF_SURFACE_KIND_TILED	(1 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK	(2 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
 
 #define DC_WINBUF_AD_UFLOW_STATUS		0xbca
 #define DC_WINBUF_BD_UFLOW_STATUS		0xdca
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dpaux.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dpaux.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dpaux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dpaux.c	2014-09-28 17:29:07.000000000 -0400
@@ -382,6 +382,7 @@ static const struct of_device_id tegra_d
 	{ .compatible = "nvidia,tegra124-dpaux", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
 
 struct platform_driver tegra_dpaux_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/drm.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/drm.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/drm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/drm.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,12 @@ static int tegra_drm_load(struct drm_dev
 
 	drm_mode_config_init(drm);
 
+	err = tegra_drm_fb_prepare(drm);
+	if (err < 0)
+		return err;
+
+	drm_kms_helper_poll_init(drm);
+
 	err = host1x_device_init(device);
 	if (err < 0)
 		return err;
@@ -59,8 +65,6 @@ static int tegra_drm_load(struct drm_dev
 	if (err < 0)
 		return err;
 
-	drm_kms_helper_poll_init(drm);
-
 	return 0;
 }
 
@@ -128,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm,
 	return &bo->base;
 }
 
+static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
+				       struct drm_tegra_reloc __user *src,
+				       struct drm_device *drm,
+				       struct drm_file *file)
+{
+	u32 cmdbuf, target;
+	int err;
+
+	err = get_user(cmdbuf, &src->cmdbuf.handle);
+	if (err < 0)
+		return err;
+
+	err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset);
+	if (err < 0)
+		return err;
+
+	err = get_user(target, &src->target.handle);
+	if (err < 0)
+		return err;
+
+	err = get_user(dest->target.offset, &src->cmdbuf.offset);
+	if (err < 0)
+		return err;
+
+	err = get_user(dest->shift, &src->shift);
+	if (err < 0)
+		return err;
+
+	dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf);
+	if (!dest->cmdbuf.bo)
+		return -ENOENT;
+
+	dest->target.bo = host1x_bo_lookup(drm, file, target);
+	if (!dest->target.bo)
+		return -ENOENT;
+
+	return 0;
+}
+
 int tegra_drm_submit(struct tegra_drm_context *context,
 		     struct drm_tegra_submit *args, struct drm_device *drm,
 		     struct drm_file *file)
@@ -180,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_co
 		cmdbufs++;
 	}
 
-	if (copy_from_user(job->relocarray, relocs,
-			   sizeof(*relocs) * num_relocs)) {
-		err = -EFAULT;
-		goto fail;
-	}
-
+	/* copy and resolve relocations from submit */
 	while (num_relocs--) {
-		struct host1x_reloc *reloc = &job->relocarray[num_relocs];
-		struct host1x_bo *cmdbuf, *target;
-
-		cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
-		target = host1x_bo_lookup(drm, file, (u32)reloc->target);
-
-		reloc->cmdbuf = cmdbuf;
-		reloc->target = target;
-
-		if (!reloc->target || !reloc->cmdbuf) {
-			err = -ENOENT;
+		err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
+						  &relocs[num_relocs], drm,
+						  file);
+		if (err < 0)
 			goto fail;
-		}
 	}
 
 	if (copy_from_user(job->waitchk, waitchks,
@@ -451,11 +481,151 @@ static int tegra_get_syncpt_base(struct
 
 	return 0;
 }
+
+static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
+				struct drm_file *file)
+{
+	struct drm_tegra_gem_set_tiling *args = data;
+	enum tegra_bo_tiling_mode mode;
+	struct drm_gem_object *gem;
+	unsigned long value = 0;
+	struct tegra_bo *bo;
+
+	switch (args->mode) {
+	case DRM_TEGRA_GEM_TILING_MODE_PITCH:
+		mode = TEGRA_BO_TILING_MODE_PITCH;
+
+		if (args->value != 0)
+			return -EINVAL;
+
+		break;
+
+	case DRM_TEGRA_GEM_TILING_MODE_TILED:
+		mode = TEGRA_BO_TILING_MODE_TILED;
+
+		if (args->value != 0)
+			return -EINVAL;
+
+		break;
+
+	case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
+		mode = TEGRA_BO_TILING_MODE_BLOCK;
+
+		if (args->value > 5)
+			return -EINVAL;
+
+		value = args->value;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	gem = drm_gem_object_lookup(drm, file, args->handle);
+	if (!gem)
+		return -ENOENT;
+
+	bo = to_tegra_bo(gem);
+
+	bo->tiling.mode = mode;
+	bo->tiling.value = value;
+
+	drm_gem_object_unreference(gem);
+
+	return 0;
+}
+
+static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
+				struct drm_file *file)
+{
+	struct drm_tegra_gem_get_tiling *args = data;
+	struct drm_gem_object *gem;
+	struct tegra_bo *bo;
+	int err = 0;
+
+	gem = drm_gem_object_lookup(drm, file, args->handle);
+	if (!gem)
+		return -ENOENT;
+
+	bo = to_tegra_bo(gem);
+
+	switch (bo->tiling.mode) {
+	case TEGRA_BO_TILING_MODE_PITCH:
+		args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
+		args->value = 0;
+		break;
+
+	case TEGRA_BO_TILING_MODE_TILED:
+		args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
+		args->value = 0;
+		break;
+
+	case TEGRA_BO_TILING_MODE_BLOCK:
+		args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+		args->value = bo->tiling.value;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	drm_gem_object_unreference(gem);
+
+	return err;
+}
+
+static int tegra_gem_set_flags(struct drm_device *drm, void *data,
+			       struct drm_file *file)
+{
+	struct drm_tegra_gem_set_flags *args = data;
+	struct drm_gem_object *gem;
+	struct tegra_bo *bo;
+
+	if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
+		return -EINVAL;
+
+	gem = drm_gem_object_lookup(drm, file, args->handle);
+	if (!gem)
+		return -ENOENT;
+
+	bo = to_tegra_bo(gem);
+	bo->flags = 0;
+
+	if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
+		bo->flags |= TEGRA_BO_BOTTOM_UP;
+
+	drm_gem_object_unreference(gem);
+
+	return 0;
+}
+
+static int tegra_gem_get_flags(struct drm_device *drm, void *data,
+			       struct drm_file *file)
+{
+	struct drm_tegra_gem_get_flags *args = data;
+	struct drm_gem_object *gem;
+	struct tegra_bo *bo;
+
+	gem = drm_gem_object_lookup(drm, file, args->handle);
+	if (!gem)
+		return -ENOENT;
+
+	bo = to_tegra_bo(gem);
+	args->flags = 0;
+
+	if (bo->flags & TEGRA_BO_BOTTOM_UP)
+		args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
+
+	drm_gem_object_unreference(gem);
+
+	return 0;
+}
 #endif
 
 static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
 #ifdef CONFIG_DRM_TEGRA_STAGING
-	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
@@ -465,6 +635,10 @@ static const struct drm_ioctl_desc tegra
 	DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
 #endif
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/drm.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/drm.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/drm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/drm.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fixed.h>
 
+#include "gem.h"
+
 struct reset_control;
 
 struct tegra_fb {
@@ -43,6 +45,8 @@ struct tegra_drm {
 #ifdef CONFIG_DRM_TEGRA_FBDEV
 	struct tegra_fbdev *fbdev;
 #endif
+
+	unsigned int pitch_align;
 };
 
 struct tegra_drm_client;
@@ -160,7 +164,8 @@ struct tegra_dc_window {
 	unsigned int stride[2];
 	unsigned long base[3];
 	bool bottom_up;
-	bool tiled;
+
+	struct tegra_bo_tiling tiling;
 };
 
 /* from dc.c */
@@ -279,7 +284,9 @@ int tegra_dpaux_train(struct tegra_dpaux
 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
 				    unsigned int index);
 bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+			struct tegra_bo_tiling *tiling);
+int tegra_drm_fb_prepare(struct drm_device *drm);
 int tegra_drm_fb_init(struct drm_device *drm);
 void tegra_drm_fb_exit(struct drm_device *drm);
 #ifdef CONFIG_DRM_TEGRA_FBDEV
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dsi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dsi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/dsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/dsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -474,7 +474,8 @@ static int tegra_output_dsi_enable(struc
 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
 
 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
-	value |= DSI_CONTROL_HS_CLK_CTRL;
+	if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+		value |= DSI_CONTROL_HS_CLK_CTRL;
 	value &= ~DSI_CONTROL_TX_TRIG(3);
 	value &= ~DSI_CONTROL_DCS_ENABLE;
 	value |= DSI_CONTROL_VIDEO_ENABLE;
@@ -982,6 +983,7 @@ static const struct of_device_id tegra_d
 	{ .compatible = "nvidia,tegra114-dsi", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
 
 struct platform_driver tegra_dsi_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_fr
 	return false;
 }
 
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+			struct tegra_bo_tiling *tiling)
 {
 	struct tegra_fb *fb = to_tegra_fb(framebuffer);
 
-	if (fb->planes[0]->flags & TEGRA_BO_TILED)
-		return true;
+	/* TODO: handle YUV formats? */
+	*tiling = fb->planes[0]->tiling;
 
-	return false;
+	return 0;
 }
 
 static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
@@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_
 			     struct drm_fb_helper_surface_size *sizes)
 {
 	struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
+	struct tegra_drm *tegra = helper->dev->dev_private;
 	struct drm_device *drm = helper->dev;
 	struct drm_mode_fb_cmd2 cmd = { 0 };
 	unsigned int bytes_per_pixel;
@@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_
 
 	cmd.width = sizes->surface_width;
 	cmd.height = sizes->surface_height;
-	cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+	cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
+				  tegra->pitch_align);
 	cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
 						     sizes->surface_depth);
 
@@ -267,18 +270,13 @@ release:
 	return err;
 }
 
-static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
 	.fb_probe = tegra_fbdev_probe,
 };
 
-static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
-					      unsigned int preferred_bpp,
-					      unsigned int num_crtc,
-					      unsigned int max_connectors)
+static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm)
 {
-	struct drm_fb_helper *helper;
 	struct tegra_fbdev *fbdev;
-	int err;
 
 	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
 	if (!fbdev) {
@@ -286,13 +284,23 @@ static struct tegra_fbdev *tegra_fbdev_c
 		return ERR_PTR(-ENOMEM);
 	}
 
-	fbdev->base.funcs = &tegra_fb_helper_funcs;
-	helper = &fbdev->base;
+	drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
+
+	return fbdev;
+}
+
+static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
+			    unsigned int preferred_bpp,
+			    unsigned int num_crtc,
+			    unsigned int max_connectors)
+{
+	struct drm_device *drm = fbdev->base.dev;
+	int err;
 
 	err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
 	if (err < 0) {
 		dev_err(drm->dev, "failed to initialize DRM FB helper\n");
-		goto free;
+		return err;
 	}
 
 	err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
@@ -301,21 +309,17 @@ static struct tegra_fbdev *tegra_fbdev_c
 		goto fini;
 	}
 
-	drm_helper_disable_unused_functions(drm);
-
 	err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
 	if (err < 0) {
 		dev_err(drm->dev, "failed to set initial configuration\n");
 		goto fini;
 	}
 
-	return fbdev;
+	return 0;
 
 fini:
 	drm_fb_helper_fini(&fbdev->base);
-free:
-	kfree(fbdev);
-	return ERR_PTR(err);
+	return err;
 }
 
 static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
@@ -366,7 +370,7 @@ static const struct drm_mode_config_func
 #endif
 };
 
-int tegra_drm_fb_init(struct drm_device *drm)
+int tegra_drm_fb_prepare(struct drm_device *drm)
 {
 #ifdef CONFIG_DRM_TEGRA_FBDEV
 	struct tegra_drm *tegra = drm->dev_private;
@@ -381,13 +385,27 @@ int tegra_drm_fb_init(struct drm_device
 	drm->mode_config.funcs = &tegra_drm_mode_funcs;
 
 #ifdef CONFIG_DRM_TEGRA_FBDEV
-	tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
-					  drm->mode_config.num_connector);
+	tegra->fbdev = tegra_fbdev_create(drm);
 	if (IS_ERR(tegra->fbdev))
 		return PTR_ERR(tegra->fbdev);
 #endif
 
 	return 0;
+}
+
+int tegra_drm_fb_init(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_TEGRA_FBDEV
+	struct tegra_drm *tegra = drm->dev_private;
+	int err;
+
+	err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc,
+			       drm->mode_config.num_connector);
+	if (err < 0)
+		return err;
+#endif
+
+	return 0;
 }
 
 void tegra_drm_fb_exit(struct drm_device *drm)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/dma-buf.h>
 #include <drm/tegra_drm.h>
 
+#include "drm.h"
 #include "gem.h"
 
 static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
@@ -126,7 +127,7 @@ struct tegra_bo *tegra_bo_create(struct
 		goto err_mmap;
 
 	if (flags & DRM_TEGRA_GEM_CREATE_TILED)
-		bo->flags |= TEGRA_BO_TILED;
+		bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
 
 	if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
 		bo->flags |= TEGRA_BO_BOTTOM_UP;
@@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file
 			 struct drm_mode_create_dumb *args)
 {
 	int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	struct tegra_drm *tegra = drm->dev_private;
 	struct tegra_bo *bo;
 
+	min_pitch = round_up(min_pitch, tegra->pitch_align);
 	if (args->pitch < min_pitch)
 		args->pitch = min_pitch;
 
@@ -420,7 +423,7 @@ struct dma_buf *tegra_gem_prime_export(s
 				       int flags)
 {
 	return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size,
-			      flags);
+			      flags, NULL);
 }
 
 struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gem.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gem.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gem.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,8 +16,18 @@
 #include <drm/drm.h>
 #include <drm/drmP.h>
 
-#define TEGRA_BO_TILED     (1 << 0)
-#define TEGRA_BO_BOTTOM_UP (1 << 1)
+#define TEGRA_BO_BOTTOM_UP (1 << 0)
+
+enum tegra_bo_tiling_mode {
+	TEGRA_BO_TILING_MODE_PITCH,
+	TEGRA_BO_TILING_MODE_TILED,
+	TEGRA_BO_TILING_MODE_BLOCK,
+};
+
+struct tegra_bo_tiling {
+	enum tegra_bo_tiling_mode mode;
+	unsigned long value;
+};
 
 struct tegra_bo {
 	struct drm_gem_object gem;
@@ -26,6 +36,8 @@ struct tegra_bo {
 	struct sg_table *sgt;
 	dma_addr_t paddr;
 	void *vaddr;
+
+	struct tegra_bo_tiling tiling;
 };
 
 static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gr2d.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gr2d.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gr2d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gr2d.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,6 +121,7 @@ static const struct of_device_id gr2d_ma
 	{ .compatible = "nvidia,tegra20-gr2d" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, gr2d_match);
 
 static const u32 gr2d_addr_regs[] = {
 	GR2D_UA_BASE_ADDR,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gr3d.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gr3d.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/gr3d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/gr3d.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,8 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
 
 #include "drm.h"
 #include "gem.h"
@@ -130,6 +131,7 @@ static const struct of_device_id tegra_g
 	{ .compatible = "nvidia,tegra20-gr3d" },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, tegra_gr3d_match);
 
 static const u32 gr3d_addr_regs[] = {
 	GR3D_IDX_ATTRIBUTE( 0),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/hdmi.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/hdmi.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/hdmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/hdmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1450,6 +1450,7 @@ static const struct of_device_id tegra_h
 	{ .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match);
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/output.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/output.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/output.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/output.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,7 +105,7 @@ static void drm_connector_clear(struct d
 
 static void tegra_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	drm_connector_clear(connector);
 }
@@ -140,7 +140,9 @@ static void tegra_encoder_dpms(struct dr
 	if (mode != DRM_MODE_DPMS_ON) {
 		drm_panel_disable(panel);
 		tegra_output_disable(output);
+		drm_panel_unprepare(panel);
 	} else {
+		drm_panel_prepare(panel);
 		tegra_output_enable(output);
 		drm_panel_enable(panel);
 	}
@@ -318,7 +320,7 @@ int tegra_output_init(struct drm_device
 	drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
 
 	drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
-	drm_sysfs_connector_add(&output->connector);
+	drm_connector_register(&output->connector);
 
 	output->encoder.possible_crtcs = 0x3;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tegra/sor.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/sor.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tegra/sor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tegra/sor.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
 
 #include <drm/drm_dp_helper.h>
 
@@ -516,7 +517,7 @@ static int tegra_output_sor_enable(struc
 		if (err < 0) {
 			dev_err(sor->dev, "failed to probe eDP link: %d\n",
 				err);
-			return err;
+			goto unlock;
 		}
 	}
 
@@ -525,7 +526,7 @@ static int tegra_output_sor_enable(struc
 		dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
 
 	memset(&config, 0, sizeof(config));
-	config.bits_per_pixel = 24; /* XXX: don't hardcode? */
+	config.bits_per_pixel = output->connector.display_info.bpc * 3;
 
 	err = tegra_sor_calc_config(sor, mode, &config, &link);
 	if (err < 0)
@@ -815,12 +816,22 @@ static int tegra_output_sor_enable(struc
 	 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
 	 * raster, associate with display controller)
 	 */
-	value = SOR_STATE_ASY_VSYNCPOL |
-		SOR_STATE_ASY_HSYNCPOL |
-		SOR_STATE_ASY_PROTOCOL_DP_A |
+	value = SOR_STATE_ASY_PROTOCOL_DP_A |
 		SOR_STATE_ASY_CRC_MODE_COMPLETE |
 		SOR_STATE_ASY_OWNER(dc->pipe + 1);
 
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		value &= ~SOR_STATE_ASY_HSYNCPOL;
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		value |= SOR_STATE_ASY_HSYNCPOL;
+
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		value &= ~SOR_STATE_ASY_VSYNCPOL;
+
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		value |= SOR_STATE_ASY_VSYNCPOL;
+
 	switch (config.bits_per_pixel) {
 	case 24:
 		value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
@@ -1455,6 +1466,7 @@ static const struct of_device_id tegra_s
 	{ .compatible = "nvidia,tegra124-sor", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
 
 struct platform_driver tegra_sor_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,8 +120,8 @@ static int cpufreq_transition(struct not
 static int tilcdc_unload(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
-	struct tilcdc_module *mod, *cur;
 
+	drm_fbdev_cma_fini(priv->fbdev);
 	drm_kms_helper_poll_fini(dev);
 	drm_mode_config_cleanup(dev);
 	drm_vblank_cleanup(dev);
@@ -148,11 +148,6 @@ static int tilcdc_unload(struct drm_devi
 
 	pm_runtime_disable(dev->dev);
 
-	list_for_each_entry_safe(mod, cur, &module_list, list) {
-		DBG("destroying module: %s", mod->name);
-		mod->funcs->destroy(mod);
-	}
-
 	kfree(priv);
 
 	return 0;
@@ -628,13 +623,13 @@ static int __init tilcdc_drm_init(void)
 static void __exit tilcdc_drm_fini(void)
 {
 	DBG("fini");
-	tilcdc_tfp410_fini();
-	tilcdc_slave_fini();
-	tilcdc_panel_fini();
 	platform_driver_unregister(&tilcdc_platform_driver);
+	tilcdc_panel_fini();
+	tilcdc_slave_fini();
+	tilcdc_tfp410_fini();
 }
 
-late_initcall(tilcdc_drm_init);
+module_init(tilcdc_drm_init);
 module_exit(tilcdc_drm_fini);
 
 MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -98,7 +98,6 @@ struct tilcdc_module;
 struct tilcdc_module_ops {
 	/* create appropriate encoders/connectors: */
 	int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
-	void (*destroy)(struct tilcdc_module *mod);
 #ifdef CONFIG_DEBUG_FS
 	/* create debugfs nodes (can be NULL): */
 	int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c	2014-09-28 17:29:07.000000000 -0400
@@ -151,6 +151,7 @@ struct panel_connector {
 static void panel_connector_destroy(struct drm_connector *connector)
 {
 	struct panel_connector *panel_connector = to_panel_connector(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(panel_connector);
 }
@@ -247,7 +248,7 @@ static struct drm_connector *panel_conne
 	if (ret)
 		goto fail;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	return connector;
 
@@ -281,23 +282,8 @@ static int panel_modeset_init(struct til
 	return 0;
 }
 
-static void panel_destroy(struct tilcdc_module *mod)
-{
-	struct panel_module *panel_mod = to_panel_module(mod);
-
-	if (panel_mod->timings) {
-		display_timings_release(panel_mod->timings);
-		kfree(panel_mod->timings);
-	}
-
-	tilcdc_module_cleanup(mod);
-	kfree(panel_mod->info);
-	kfree(panel_mod);
-}
-
 static const struct tilcdc_module_ops panel_module_ops = {
 		.modeset_init = panel_modeset_init,
-		.destroy = panel_destroy,
 };
 
 /*
@@ -373,6 +359,7 @@ static int panel_probe(struct platform_d
 		return -ENOMEM;
 
 	mod = &panel_mod->base;
+	pdev->dev.platform_data = mod;
 
 	tilcdc_module_init(mod, "panel", &panel_module_ops);
 
@@ -380,17 +367,16 @@ static int panel_probe(struct platform_d
 	if (IS_ERR(pinctrl))
 		dev_warn(&pdev->dev, "pins are not configured\n");
 
-
 	panel_mod->timings = of_get_display_timings(node);
 	if (!panel_mod->timings) {
 		dev_err(&pdev->dev, "could not get panel timings\n");
-		goto fail;
+		goto fail_free;
 	}
 
 	panel_mod->info = of_get_panel_info(node);
 	if (!panel_mod->info) {
 		dev_err(&pdev->dev, "could not get panel info\n");
-		goto fail;
+		goto fail_timings;
 	}
 
 	mod->preferred_bpp = panel_mod->info->bpp;
@@ -401,13 +387,26 @@ static int panel_probe(struct platform_d
 
 	return 0;
 
-fail:
-	panel_destroy(mod);
+fail_timings:
+	display_timings_release(panel_mod->timings);
+
+fail_free:
+	kfree(panel_mod);
+	tilcdc_module_cleanup(mod);
 	return ret;
 }
 
 static int panel_remove(struct platform_device *pdev)
 {
+	struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+	struct panel_module *panel_mod = to_panel_module(mod);
+
+	display_timings_release(panel_mod->timings);
+
+	tilcdc_module_cleanup(mod);
+	kfree(panel_mod->info);
+	kfree(panel_mod);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,6 +166,7 @@ struct slave_connector {
 static void slave_connector_destroy(struct drm_connector *connector)
 {
 	struct slave_connector *slave_connector = to_slave_connector(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(slave_connector);
 }
@@ -261,7 +262,7 @@ static struct drm_connector *slave_conne
 	if (ret)
 		goto fail;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	return connector;
 
@@ -295,17 +296,8 @@ static int slave_modeset_init(struct til
 	return 0;
 }
 
-static void slave_destroy(struct tilcdc_module *mod)
-{
-	struct slave_module *slave_mod = to_slave_module(mod);
-
-	tilcdc_module_cleanup(mod);
-	kfree(slave_mod);
-}
-
 static const struct tilcdc_module_ops slave_module_ops = {
 		.modeset_init = slave_modeset_init,
-		.destroy = slave_destroy,
 };
 
 /*
@@ -355,10 +347,13 @@ static int slave_probe(struct platform_d
 	}
 
 	slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
-	if (!slave_mod)
-		return -ENOMEM;
+	if (!slave_mod) {
+		ret = -ENOMEM;
+		goto fail_adapter;
+	}
 
 	mod = &slave_mod->base;
+	pdev->dev.platform_data = mod;
 
 	mod->preferred_bpp = slave_info.bpp;
 
@@ -373,10 +368,20 @@ static int slave_probe(struct platform_d
 	tilcdc_slave_probedefer(false);
 
 	return 0;
+
+fail_adapter:
+	i2c_put_adapter(slavei2c);
+	return ret;
 }
 
 static int slave_remove(struct platform_device *pdev)
 {
+	struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+	struct slave_module *slave_mod = to_slave_module(mod);
+
+	tilcdc_module_cleanup(mod);
+	kfree(slave_mod);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,6 +167,7 @@ struct tfp410_connector {
 static void tfp410_connector_destroy(struct drm_connector *connector)
 {
 	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(tfp410_connector);
 }
@@ -261,7 +262,7 @@ static struct drm_connector *tfp410_conn
 	if (ret)
 		goto fail;
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 
 	return connector;
 
@@ -295,23 +296,8 @@ static int tfp410_modeset_init(struct ti
 	return 0;
 }
 
-static void tfp410_destroy(struct tilcdc_module *mod)
-{
-	struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
-
-	if (tfp410_mod->i2c)
-		i2c_put_adapter(tfp410_mod->i2c);
-
-	if (!IS_ERR_VALUE(tfp410_mod->gpio))
-		gpio_free(tfp410_mod->gpio);
-
-	tilcdc_module_cleanup(mod);
-	kfree(tfp410_mod);
-}
-
 static const struct tilcdc_module_ops tfp410_module_ops = {
 		.modeset_init = tfp410_modeset_init,
-		.destroy = tfp410_destroy,
 };
 
 /*
@@ -341,6 +327,7 @@ static int tfp410_probe(struct platform_
 		return -ENOMEM;
 
 	mod = &tfp410_mod->base;
+	pdev->dev.platform_data = mod;
 
 	tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
 
@@ -364,6 +351,7 @@ static int tfp410_probe(struct platform_
 	tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
 	if (!tfp410_mod->i2c) {
 		dev_err(&pdev->dev, "could not get i2c\n");
+		of_node_put(i2c_node);
 		goto fail;
 	}
 
@@ -377,19 +365,32 @@ static int tfp410_probe(struct platform_
 		ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
 		if (ret) {
 			dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
-			goto fail;
+			goto fail_adapter;
 		}
 	}
 
 	return 0;
 
+fail_adapter:
+	i2c_put_adapter(tfp410_mod->i2c);
+
 fail:
-	tfp410_destroy(mod);
+	kfree(tfp410_mod);
+	tilcdc_module_cleanup(mod);
 	return ret;
 }
 
 static int tfp410_remove(struct platform_device *pdev)
 {
+	struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+	struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
+
+	i2c_put_adapter(tfp410_mod->i2c);
+	gpio_free(tfp410_mod->gpio);
+
+	tilcdc_module_cleanup(mod);
+	kfree(tfp410_mod);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2014-09-28 17:29:07.000000000 -0400
@@ -412,7 +412,7 @@ static void ttm_bo_cleanup_refs_or_queue
 	int ret;
 
 	spin_lock(&glob->lru_lock);
-	ret = __ttm_bo_reserve(bo, false, true, false, 0);
+	ret = __ttm_bo_reserve(bo, false, true, false, NULL);
 
 	spin_lock(&bdev->fence_lock);
 	(void) ttm_bo_wait(bo, false, false, true);
@@ -514,7 +514,7 @@ static int ttm_bo_cleanup_refs_and_unloc
 			return ret;
 
 		spin_lock(&glob->lru_lock);
-		ret = __ttm_bo_reserve(bo, false, true, false, 0);
+		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
 
 		/*
 		 * We raced, and lost, someone else holds the reservation now,
@@ -577,11 +577,11 @@ static int ttm_bo_delayed_delete(struct
 			kref_get(&nentry->list_kref);
 		}
 
-		ret = __ttm_bo_reserve(entry, false, true, false, 0);
+		ret = __ttm_bo_reserve(entry, false, true, false, NULL);
 		if (remove_all && ret) {
 			spin_unlock(&glob->lru_lock);
 			ret = __ttm_bo_reserve(entry, false, false,
-					       false, 0);
+					       false, NULL);
 			spin_lock(&glob->lru_lock);
 		}
 
@@ -726,7 +726,7 @@ 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, false, 0);
+		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
 		if (!ret)
 			break;
 	}
@@ -784,7 +784,7 @@ static int ttm_bo_mem_force_space(struct
 	int ret;
 
 	do {
-		ret = (*man->func->get_node)(man, bo, placement, mem);
+		ret = (*man->func->get_node)(man, bo, placement, 0, mem);
 		if (unlikely(ret != 0))
 			return ret;
 		if (mem->mm_node)
@@ -897,7 +897,8 @@ int ttm_bo_mem_space(struct ttm_buffer_o
 
 		if (man->has_type && man->use_type) {
 			type_found = true;
-			ret = (*man->func->get_node)(man, bo, placement, mem);
+			ret = (*man->func->get_node)(man, bo, placement,
+						     cur_flags, mem);
 			if (unlikely(ret))
 				return ret;
 		}
@@ -937,7 +938,6 @@ int ttm_bo_mem_space(struct ttm_buffer_o
 		ttm_flag_masked(&cur_flags, placement->busy_placement[i],
 				~TTM_PL_MASK_MEMTYPE);
 
-
 		if (mem_type == TTM_PL_SYSTEM) {
 			mem->mem_type = mem_type;
 			mem->placement = cur_flags;
@@ -1595,7 +1595,7 @@ int ttm_bo_synccpu_write_grab(struct ttm
 	 * Using ttm_bo_reserve makes sure the lru lists are updated.
 	 */
 
-	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
+	ret = ttm_bo_reserve(bo, true, no_wait, false, NULL);
 	if (unlikely(ret != 0))
 		return ret;
 	spin_lock(&bdev->fence_lock);
@@ -1630,7 +1630,7 @@ static int ttm_bo_swapout(struct ttm_mem
 
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &glob->swap_lru, swap) {
-		ret = __ttm_bo_reserve(bo, false, true, false, 0);
+		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
 		if (!ret)
 			break;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo_manager.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo_manager.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo_manager.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo_manager.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,7 @@ struct ttm_range_manager {
 static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
 			       struct ttm_buffer_object *bo,
 			       struct ttm_placement *placement,
+			       uint32_t flags,
 			       struct ttm_mem_reg *mem)
 {
 	struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv;
@@ -67,7 +68,7 @@ static int ttm_bo_man_get_node(struct tt
 	if (!node)
 		return -ENOMEM;
 
-	if (bo->mem.placement & TTM_PL_FLAG_TOPDOWN)
+	if (flags & TTM_PL_FLAG_TOPDOWN)
 		aflags = DRM_MM_CREATE_TOP;
 
 	spin_lock(&rman->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2014-09-28 17:29:07.000000000 -0400
@@ -500,7 +500,7 @@ pgprot_t ttm_io_prot(uint32_t caching_fl
 			pgprot_val(tmp) |= _PAGE_GUARDED;
 	}
 #endif
-#if defined(__ia64__)
+#if defined(__ia64__) || defined(__arm__)
 	if (caching_flags & TTM_PL_FLAG_WC)
 		tmp = pgprot_writecombine(tmp);
 	else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_module.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_module.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_module.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
 #include <drm/drm_sysfs.h>
 
 static DECLARE_WAIT_QUEUE_HEAD(exit_q);
-atomic_t device_released;
+static atomic_t device_released;
 
 static struct device_type ttm_drm_class_type = {
 	.name = "ttm",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_object.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_object.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -695,7 +695,7 @@ int ttm_prime_handle_to_fd(struct ttm_ob
 		}
 
 		dma_buf = dma_buf_export(prime, &tdev->ops,
-					 prime->size, flags);
+					 prime->size, flags, NULL);
 		if (IS_ERR(dma_buf)) {
 			ret = PTR_ERR(dma_buf);
 			ttm_mem_global_free(tdev->mem_glob,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2014-09-28 17:29:07.000000000 -0400
@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(
  *
  * @pool: to free the pages from
  * @free_all: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
+static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
+			      gfp_t gfp)
 {
 	unsigned long irq_flags;
 	struct page *p;
@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm
 	if (NUM_PAGES_TO_ALLOC < nr_free)
 		npages_to_free = NUM_PAGES_TO_ALLOC;
 
-	pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-			GFP_KERNEL);
+	pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
 	if (!pages_to_free) {
 		pr_err("Failed to allocate memory for pool free operation\n");
 		return 0;
@@ -382,32 +383,35 @@ out:
  *
  * XXX: (dchinner) Deadlock warning!
  *
- * ttm_page_pool_free() does memory allocation using GFP_KERNEL.  that means
- * this can deadlock when called a sc->gfp_mask that is not equal to
- * GFP_KERNEL.
+ * We need to pass sc->gfp_mask to ttm_page_pool_free().
  *
  * This code is crying out for a shrinker per pool....
  */
 static unsigned long
 ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
-	static atomic_t start_pool = ATOMIC_INIT(0);
+	static DEFINE_MUTEX(lock);
+	static unsigned start_pool;
 	unsigned i;
-	unsigned pool_offset = atomic_add_return(1, &start_pool);
+	unsigned pool_offset;
 	struct ttm_page_pool *pool;
 	int shrink_pages = sc->nr_to_scan;
 	unsigned long freed = 0;
 
-	pool_offset = pool_offset % NUM_POOLS;
+	if (!mutex_trylock(&lock))
+		return SHRINK_STOP;
+	pool_offset = ++start_pool % NUM_POOLS;
 	/* select start pool in round robin fashion */
 	for (i = 0; i < NUM_POOLS; ++i) {
 		unsigned nr_free = shrink_pages;
 		if (shrink_pages == 0)
 			break;
 		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
-		shrink_pages = ttm_page_pool_free(pool, nr_free);
+		shrink_pages = ttm_page_pool_free(pool, nr_free,
+						  sc->gfp_mask);
 		freed += nr_free - shrink_pages;
 	}
+	mutex_unlock(&lock);
 	return freed;
 }
 
@@ -706,7 +710,7 @@ static void ttm_put_pages(struct page **
 	}
 	spin_unlock_irqrestore(&pool->lock, irq_flags);
 	if (npages)
-		ttm_page_pool_free(pool, npages);
+		ttm_page_pool_free(pool, npages, GFP_KERNEL);
 }
 
 /*
@@ -790,7 +794,7 @@ static int ttm_get_pages(struct page **p
 	return 0;
 }
 
-static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags,
+static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
 		char *name)
 {
 	spin_lock_init(&pool->lock);
@@ -846,7 +850,8 @@ void ttm_page_alloc_fini(void)
 	ttm_pool_mm_shrink_fini(_manager);
 
 	for (i = 0; i < NUM_POOLS; ++i)
-		ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
+		ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
+				   GFP_KERNEL);
 
 	kobject_put(&_manager->kobj);
 	_manager = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_
  *
  * @pool: to free the pages from
  * @nr_free: If set to true will free all pages in pool
+ * @gfp: GFP flags.
  **/
-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
+static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
+				       gfp_t gfp)
 {
 	unsigned long irq_flags;
 	struct dma_page *dma_p, *tmp;
@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(s
 			 npages_to_free, nr_free);
 	}
 #endif
-	pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
-			GFP_KERNEL);
+	pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
 
 	if (!pages_to_free) {
 		pr_err("%s: Failed to allocate memory for pool free operation\n",
@@ -530,7 +531,7 @@ static void ttm_dma_free_pool(struct dev
 		if (pool->type != type)
 			continue;
 		/* Takes a spinlock.. */
-		ttm_dma_page_pool_free(pool, FREE_ALL_PAGES);
+		ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL);
 		WARN_ON(((pool->npages_in_use + pool->npages_free) != 0));
 		/* This code path is called after _all_ references to the
 		 * struct device has been dropped - so nobody should be
@@ -847,6 +848,7 @@ static int ttm_dma_pool_get_pages(struct
 	if (count) {
 		d_page = list_first_entry(&pool->free_list, struct dma_page, page_list);
 		ttm->pages[index] = d_page->p;
+		ttm_dma->cpu_address[index] = d_page->vaddr;
 		ttm_dma->dma_address[index] = d_page->dma;
 		list_move_tail(&d_page->page_list, &ttm_dma->pages_list);
 		r = 0;
@@ -978,12 +980,13 @@ void ttm_dma_unpopulate(struct ttm_dma_t
 	INIT_LIST_HEAD(&ttm_dma->pages_list);
 	for (i = 0; i < ttm->num_pages; i++) {
 		ttm->pages[i] = NULL;
+		ttm_dma->cpu_address[i] = 0;
 		ttm_dma->dma_address[i] = 0;
 	}
 
 	/* shrink pool if necessary (only on !is_cached pools)*/
 	if (npages)
-		ttm_dma_page_pool_free(pool, npages);
+		ttm_dma_page_pool_free(pool, npages, GFP_KERNEL);
 	ttm->state = tt_unpopulated;
 }
 EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
@@ -993,10 +996,7 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
  *
  * XXX: (dchinner) Deadlock warning!
  *
- * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention
- * needs to be paid to sc->gfp_mask to determine if this can be done or not.
- * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really
- * bad.
+ * We need to pass sc->gfp_mask to ttm_dma_page_pool_free().
  *
  * I'm getting sadder as I hear more pathetical whimpers about needing per-pool
  * shrinkers
@@ -1004,9 +1004,9 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
 static unsigned long
 ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
-	static atomic_t start_pool = ATOMIC_INIT(0);
+	static unsigned start_pool;
 	unsigned idx = 0;
-	unsigned pool_offset = atomic_add_return(1, &start_pool);
+	unsigned pool_offset;
 	unsigned shrink_pages = sc->nr_to_scan;
 	struct device_pools *p;
 	unsigned long freed = 0;
@@ -1014,8 +1014,11 @@ ttm_dma_pool_shrink_scan(struct shrinker
 	if (list_empty(&_manager->pools))
 		return SHRINK_STOP;
 
-	mutex_lock(&_manager->lock);
-	pool_offset = pool_offset % _manager->npools;
+	if (!mutex_trylock(&_manager->lock))
+		return SHRINK_STOP;
+	if (!_manager->npools)
+		goto out;
+	pool_offset = ++start_pool % _manager->npools;
 	list_for_each_entry(p, &_manager->pools, pools) {
 		unsigned nr_free;
 
@@ -1027,13 +1030,15 @@ ttm_dma_pool_shrink_scan(struct shrinker
 		if (++idx < pool_offset)
 			continue;
 		nr_free = shrink_pages;
-		shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free);
+		shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free,
+						      sc->gfp_mask);
 		freed += nr_free - shrink_pages;
 
 		pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",
 			 p->pool->dev_name, p->pool->name, current->pid,
 			 nr_free, shrink_pages);
 	}
+out:
 	mutex_unlock(&_manager->lock);
 	return freed;
 }
@@ -1044,7 +1049,8 @@ ttm_dma_pool_shrink_count(struct shrinke
 	struct device_pools *p;
 	unsigned long count = 0;
 
-	mutex_lock(&_manager->lock);
+	if (!mutex_trylock(&_manager->lock))
+		return 0;
 	list_for_each_entry(p, &_manager->pools, pools)
 		count += p->pool->npages_free;
 	mutex_unlock(&_manager->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_tt.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_tt.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,9 +55,12 @@ static void ttm_tt_alloc_page_directory(
 
 static void ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm)
 {
-	ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages, sizeof(void*));
-	ttm->dma_address = drm_calloc_large(ttm->ttm.num_pages,
-					    sizeof(*ttm->dma_address));
+	ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages,
+					  sizeof(*ttm->ttm.pages) +
+					  sizeof(*ttm->dma_address) +
+					  sizeof(*ttm->cpu_address));
+	ttm->cpu_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages);
+	ttm->dma_address = (void *) (ttm->cpu_address + ttm->ttm.num_pages);
 }
 
 #ifdef CONFIG_X86
@@ -228,7 +231,7 @@ int ttm_dma_tt_init(struct ttm_dma_tt *t
 
 	INIT_LIST_HEAD(&ttm_dma->pages_list);
 	ttm_dma_tt_alloc_page_directory(ttm_dma);
-	if (!ttm->pages || !ttm_dma->dma_address) {
+	if (!ttm->pages) {
 		ttm_tt_destroy(ttm);
 		pr_err("Failed allocating page table\n");
 		return -ENOMEM;
@@ -243,7 +246,7 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *
 
 	drm_free_large(ttm->pages);
 	ttm->pages = NULL;
-	drm_free_large(ttm_dma->dma_address);
+	ttm_dma->cpu_address = NULL;
 	ttm_dma->dma_address = NULL;
 }
 EXPORT_SYMBOL(ttm_dma_tt_fini);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_connector.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_connector.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_connector.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_connector.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,14 +105,7 @@ static struct drm_encoder*
 udl_best_single_encoder(struct drm_connector *connector)
 {
 	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
-	obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
-	if (!obj)
-		return NULL;
-	encoder = obj_to_encoder(obj);
-	return encoder;
+	return drm_encoder_find(connector->dev, enc_id);
 }
 
 static int udl_connector_set_property(struct drm_connector *connector,
@@ -124,7 +117,7 @@ static int udl_connector_set_property(st
 
 static void udl_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
@@ -154,7 +147,7 @@ int udl_connector_init(struct drm_device
 	drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_DVII);
 	drm_connector_helper_add(connector, &udl_connector_helper_funcs);
 
-	drm_sysfs_connector_add(connector);
+	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	drm_object_attach_property(&connector->base,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_fb.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_fb.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_fb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_fb.c	2014-09-28 17:29:07.000000000 -0400
@@ -550,7 +550,7 @@ out:
 	return ret;
 }
 
-static struct drm_fb_helper_funcs udl_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs udl_fb_helper_funcs = {
 	.fb_probe = udlfb_create,
 };
 
@@ -583,7 +583,8 @@ int udl_fbdev_init(struct drm_device *de
 		return -ENOMEM;
 
 	udl->fbdev = ufbdev;
-	ufbdev->helper.funcs = &udl_fb_helper_funcs;
+
+	drm_fb_helper_prepare(dev, &ufbdev->helper, &udl_fb_helper_funcs);
 
 	ret = drm_fb_helper_init(dev, &ufbdev->helper,
 				 1, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_gem.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_gem.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_gem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_gem.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,14 +107,14 @@ int udl_gem_fault(struct vm_area_struct
 	}
 }
 
-static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
+static int udl_gem_get_pages(struct udl_gem_object *obj)
 {
 	struct page **pages;
 
 	if (obj->pages)
 		return 0;
 
-	pages = drm_gem_get_pages(&obj->base, gfpmask);
+	pages = drm_gem_get_pages(&obj->base);
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
@@ -147,7 +147,7 @@ int udl_gem_vmap(struct udl_gem_object *
 		return 0;
 	}
 		
-	ret = udl_gem_get_pages(obj, GFP_KERNEL);
+	ret = udl_gem_get_pages(obj);
 	if (ret)
 		return ret;
 
@@ -205,7 +205,7 @@ int udl_gem_mmap(struct drm_file *file,
 	}
 	gobj = to_udl_bo(obj);
 
-	ret = udl_gem_get_pages(gobj, GFP_KERNEL);
+	ret = udl_gem_get_pages(gobj);
 	if (ret)
 		goto out;
 	ret = drm_gem_create_mmap_offset(obj);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_main.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_main.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -306,10 +306,23 @@ int udl_driver_load(struct drm_device *d
 
 	DRM_DEBUG("\n");
 	ret = udl_modeset_init(dev);
+	if (ret)
+		goto err;
 
 	ret = udl_fbdev_init(dev);
+	if (ret)
+		goto err;
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret)
+		goto err_fb;
+
 	return 0;
+err_fb:
+	udl_fbdev_cleanup(dev);
 err:
+	if (udl->urbs.count)
+		udl_free_urb_list(dev);
 	kfree(udl);
 	DRM_ERROR("%d\n", ret);
 	return ret;
@@ -325,6 +338,8 @@ int udl_driver_unload(struct drm_device
 {
 	struct udl_device *udl = dev->dev_private;
 
+	drm_vblank_cleanup(dev);
+
 	if (udl->urbs.count)
 		udl_free_urb_list(dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_modeset.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_modeset.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/udl/udl_modeset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/udl/udl_modeset.c	2014-09-28 17:29:07.000000000 -0400
@@ -363,6 +363,26 @@ static void udl_crtc_destroy(struct drm_
 	kfree(crtc);
 }
 
+static int udl_crtc_page_flip(struct drm_crtc *crtc,
+			      struct drm_framebuffer *fb,
+			      struct drm_pending_vblank_event *event,
+			      uint32_t page_flip_flags)
+{
+	struct udl_framebuffer *ufb = to_udl_fb(fb);
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+
+	udl_handle_damage(ufb, 0, 0, fb->width, fb->height);
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (event)
+		drm_send_vblank_event(dev, 0, event);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	crtc->primary->fb = fb;
+
+	return 0;
+}
+
 static void udl_crtc_prepare(struct drm_crtc *crtc)
 {
 }
@@ -384,6 +404,7 @@ static struct drm_crtc_helper_funcs udl_
 static const struct drm_crtc_funcs udl_crtc_funcs = {
 	.set_config = drm_crtc_helper_set_config,
 	.destroy = udl_crtc_destroy,
+	.page_flip = udl_crtc_page_flip,
 };
 
 static int udl_crtc_init(struct drm_device *dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/Makefile linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/Makefile
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.
 	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
 	    vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
 	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
-	    vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o
+	    vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
+	    vmwgfx_cmdbuf_res.o \
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,341 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2014 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+
+#define VMW_CMDBUF_RES_MAN_HT_ORDER 12
+
+enum vmw_cmdbuf_res_state {
+	VMW_CMDBUF_RES_COMMITED,
+	VMW_CMDBUF_RES_ADD,
+	VMW_CMDBUF_RES_DEL
+};
+
+/**
+ * struct vmw_cmdbuf_res - Command buffer managed resource entry.
+ *
+ * @res: Refcounted pointer to a struct vmw_resource.
+ * @hash: Hash entry for the manager hash table.
+ * @head: List head used either by the staging list or the manager list
+ * of commited resources.
+ * @state: Staging state of this resource entry.
+ * @man: Pointer to a resource manager for this entry.
+ */
+struct vmw_cmdbuf_res {
+	struct vmw_resource *res;
+	struct drm_hash_item hash;
+	struct list_head head;
+	enum vmw_cmdbuf_res_state state;
+	struct vmw_cmdbuf_res_manager *man;
+};
+
+/**
+ * struct vmw_cmdbuf_res_manager - Command buffer resource manager.
+ *
+ * @resources: Hash table containing staged and commited command buffer
+ * resources
+ * @list: List of commited command buffer resources.
+ * @dev_priv: Pointer to a device private structure.
+ *
+ * @resources and @list are protected by the cmdbuf mutex for now.
+ */
+struct vmw_cmdbuf_res_manager {
+	struct drm_open_hash resources;
+	struct list_head list;
+	struct vmw_private *dev_priv;
+};
+
+
+/**
+ * vmw_cmdbuf_res_lookup - Look up a command buffer resource
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @resource_type: The resource type, that combined with the user key
+ * identifies the resource.
+ * @user_key: The user key.
+ *
+ * Returns a valid refcounted struct vmw_resource pointer on success,
+ * an error pointer on failure.
+ */
+struct vmw_resource *
+vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+		      enum vmw_cmdbuf_res_type res_type,
+		      u32 user_key)
+{
+	struct drm_hash_item *hash;
+	int ret;
+	unsigned long key = user_key | (res_type << 24);
+
+	ret = drm_ht_find_item(&man->resources, key, &hash);
+	if (unlikely(ret != 0))
+		return ERR_PTR(ret);
+
+	return vmw_resource_reference
+		(drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res);
+}
+
+/**
+ * vmw_cmdbuf_res_free - Free a command buffer resource.
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @entry: Pointer to a struct vmw_cmdbuf_res.
+ *
+ * Frees a struct vmw_cmdbuf_res entry and drops its reference to the
+ * struct vmw_resource.
+ */
+static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
+				struct vmw_cmdbuf_res *entry)
+{
+	list_del(&entry->head);
+	WARN_ON(drm_ht_remove_item(&man->resources, &entry->hash));
+	vmw_resource_unreference(&entry->res);
+	kfree(entry);
+}
+
+/**
+ * vmw_cmdbuf_res_commit - Commit a list of command buffer resource actions
+ *
+ * @list: Caller's list of command buffer resource actions.
+ *
+ * This function commits a list of command buffer resource
+ * additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions has commited the fifo contents to the device.
+ */
+void vmw_cmdbuf_res_commit(struct list_head *list)
+{
+	struct vmw_cmdbuf_res *entry, *next;
+
+	list_for_each_entry_safe(entry, next, list, head) {
+		list_del(&entry->head);
+		switch (entry->state) {
+		case VMW_CMDBUF_RES_ADD:
+			entry->state = VMW_CMDBUF_RES_COMMITED;
+			list_add_tail(&entry->head, &entry->man->list);
+			break;
+		case VMW_CMDBUF_RES_DEL:
+			vmw_resource_unreference(&entry->res);
+			kfree(entry);
+			break;
+		default:
+			BUG();
+			break;
+		}
+	}
+}
+
+/**
+ * vmw_cmdbuf_res_revert - Revert a list of command buffer resource actions
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @list: Caller's list of command buffer resource action
+ *
+ * This function reverts a list of command buffer resource
+ * additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions failed for some reason, and the command stream was never
+ * submitted.
+ */
+void vmw_cmdbuf_res_revert(struct list_head *list)
+{
+	struct vmw_cmdbuf_res *entry, *next;
+	int ret;
+
+	list_for_each_entry_safe(entry, next, list, head) {
+		switch (entry->state) {
+		case VMW_CMDBUF_RES_ADD:
+			vmw_cmdbuf_res_free(entry->man, entry);
+			break;
+		case VMW_CMDBUF_RES_DEL:
+			ret = drm_ht_insert_item(&entry->man->resources,
+						 &entry->hash);
+			list_del(&entry->head);
+			list_add_tail(&entry->head, &entry->man->list);
+			entry->state = VMW_CMDBUF_RES_COMMITED;
+			break;
+		default:
+			BUG();
+			break;
+		}
+	}
+}
+
+/**
+ * vmw_cmdbuf_res_add - Stage a command buffer managed resource for addition.
+ *
+ * @man: Pointer to the command buffer resource manager.
+ * @res_type: The resource type.
+ * @user_key: The user-space id of the resource.
+ * @res: Valid (refcount != 0) pointer to a struct vmw_resource.
+ * @list: The staging list.
+ *
+ * This function allocates a struct vmw_cmdbuf_res entry and adds the
+ * resource to the hash table of the manager identified by @man. The
+ * entry is then put on the staging list identified by @list.
+ */
+int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
+		       enum vmw_cmdbuf_res_type res_type,
+		       u32 user_key,
+		       struct vmw_resource *res,
+		       struct list_head *list)
+{
+	struct vmw_cmdbuf_res *cres;
+	int ret;
+
+	cres = kzalloc(sizeof(*cres), GFP_KERNEL);
+	if (unlikely(cres == NULL))
+		return -ENOMEM;
+
+	cres->hash.key = user_key | (res_type << 24);
+	ret = drm_ht_insert_item(&man->resources, &cres->hash);
+	if (unlikely(ret != 0))
+		goto out_invalid_key;
+
+	cres->state = VMW_CMDBUF_RES_ADD;
+	cres->res = vmw_resource_reference(res);
+	cres->man = man;
+	list_add_tail(&cres->head, list);
+
+out_invalid_key:
+	return ret;
+}
+
+/**
+ * vmw_cmdbuf_res_remove - Stage a command buffer managed resource for removal.
+ *
+ * @man: Pointer to the command buffer resource manager.
+ * @res_type: The resource type.
+ * @user_key: The user-space id of the resource.
+ * @list: The staging list.
+ *
+ * This function looks up the struct vmw_cmdbuf_res entry from the manager
+ * hash table and, if it exists, removes it. Depending on its current staging
+ * state it then either removes the entry from the staging list or adds it
+ * to it with a staging state of removal.
+ */
+int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+			  enum vmw_cmdbuf_res_type res_type,
+			  u32 user_key,
+			  struct list_head *list)
+{
+	struct vmw_cmdbuf_res *entry;
+	struct drm_hash_item *hash;
+	int ret;
+
+	ret = drm_ht_find_item(&man->resources, user_key, &hash);
+	if (likely(ret != 0))
+		return -EINVAL;
+
+	entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
+
+	switch (entry->state) {
+	case VMW_CMDBUF_RES_ADD:
+		vmw_cmdbuf_res_free(man, entry);
+		break;
+	case VMW_CMDBUF_RES_COMMITED:
+		(void) drm_ht_remove_item(&man->resources, &entry->hash);
+		list_del(&entry->head);
+		entry->state = VMW_CMDBUF_RES_DEL;
+		list_add_tail(&entry->head, list);
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	return 0;
+}
+
+/**
+ * vmw_cmdbuf_res_man_create - Allocate a command buffer managed resource
+ * manager.
+ *
+ * @dev_priv: Pointer to a struct vmw_private
+ *
+ * Allocates and initializes a command buffer managed resource manager. Returns
+ * an error pointer on failure.
+ */
+struct vmw_cmdbuf_res_manager *
+vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
+{
+	struct vmw_cmdbuf_res_manager *man;
+	int ret;
+
+	man = kzalloc(sizeof(*man), GFP_KERNEL);
+	if (man == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	man->dev_priv = dev_priv;
+	INIT_LIST_HEAD(&man->list);
+	ret = drm_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
+	if (ret == 0)
+		return man;
+
+	kfree(man);
+	return ERR_PTR(ret);
+}
+
+/**
+ * vmw_cmdbuf_res_man_destroy - Destroy a command buffer managed resource
+ * manager.
+ *
+ * @man: Pointer to the  manager to destroy.
+ *
+ * This function destroys a command buffer managed resource manager and
+ * unreferences / frees all command buffer managed resources and -entries
+ * associated with it.
+ */
+void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
+{
+	struct vmw_cmdbuf_res *entry, *next;
+
+	list_for_each_entry_safe(entry, next, &man->list, head)
+		vmw_cmdbuf_res_free(man, entry);
+
+	kfree(man);
+}
+
+/**
+ *
+ * vmw_cmdbuf_res_man_size - Return the size of a command buffer managed
+ * resource manager
+ *
+ * Returns the approximate allocation size of a command buffer managed
+ * resource manager.
+ */
+size_t vmw_cmdbuf_res_man_size(void)
+{
+	static size_t res_man_size;
+
+	if (unlikely(res_man_size == 0))
+		res_man_size =
+			ttm_round_pot(sizeof(struct vmw_cmdbuf_res_manager)) +
+			ttm_round_pot(sizeof(struct hlist_head) <<
+				      VMW_CMDBUF_RES_MAN_HT_ORDER);
+
+	return res_man_size;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_context.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_context.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_context.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@ struct vmw_user_context {
 	struct ttm_base_object base;
 	struct vmw_resource res;
 	struct vmw_ctx_binding_state cbs;
+	struct vmw_cmdbuf_res_manager *man;
 };
 
 
@@ -103,7 +104,8 @@ static const vmw_scrub_func vmw_scrub_fu
 
 static void vmw_hw_context_destroy(struct vmw_resource *res)
 {
-
+	struct vmw_user_context *uctx =
+		container_of(res, struct vmw_user_context, res);
 	struct vmw_private *dev_priv = res->dev_priv;
 	struct {
 		SVGA3dCmdHeader header;
@@ -113,9 +115,9 @@ static void vmw_hw_context_destroy(struc
 
 	if (res->func->destroy == vmw_gb_context_destroy) {
 		mutex_lock(&dev_priv->cmdbuf_mutex);
+		vmw_cmdbuf_res_man_destroy(uctx->man);
 		mutex_lock(&dev_priv->binding_mutex);
-		(void) vmw_context_binding_state_kill
-			(&container_of(res, struct vmw_user_context, res)->cbs);
+		(void) vmw_context_binding_state_kill(&uctx->cbs);
 		(void) vmw_gb_context_destroy(res);
 		mutex_unlock(&dev_priv->binding_mutex);
 		if (dev_priv->pinned_bo != NULL &&
@@ -152,13 +154,16 @@ static int vmw_gb_context_init(struct vm
 	ret = vmw_resource_init(dev_priv, res, true,
 				res_free, &vmw_gb_context_func);
 	res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
+	if (unlikely(ret != 0))
+		goto out_err;
 
-	if (unlikely(ret != 0)) {
-		if (res_free)
-			res_free(res);
-		else
-			kfree(res);
-		return ret;
+	if (dev_priv->has_mob) {
+		uctx->man = vmw_cmdbuf_res_man_create(dev_priv);
+		if (unlikely(IS_ERR(uctx->man))) {
+			ret = PTR_ERR(uctx->man);
+			uctx->man = NULL;
+			goto out_err;
+		}
 	}
 
 	memset(&uctx->cbs, 0, sizeof(uctx->cbs));
@@ -166,6 +171,13 @@ static int vmw_gb_context_init(struct vm
 
 	vmw_resource_activate(res, vmw_hw_context_destroy);
 	return 0;
+
+out_err:
+	if (res_free)
+		res_free(res);
+	else
+		kfree(res);
+	return ret;
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -471,7 +483,8 @@ int vmw_context_define_ioctl(struct drm_
 	 */
 
 	if (unlikely(vmw_user_context_size == 0))
-		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128 +
+		  ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0);
 
 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
 	if (unlikely(ret != 0))
@@ -901,3 +914,8 @@ struct list_head *vmw_context_binding_li
 {
 	return &(container_of(ctx, struct vmw_user_context, res)->cbs.list);
 }
+
+struct vmw_cmdbuf_res_manager *vmw_context_res_man(struct vmw_resource *ctx)
+{
+	return container_of(ctx, struct vmw_user_context, res)->man;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ int vmw_dmabuf_to_placement(struct vmw_p
 
 	vmw_execbuf_release_pinned_bo(dev_priv);
 
-	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
 	if (unlikely(ret != 0))
 		goto err;
 
@@ -105,7 +105,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw
 	if (pin)
 		vmw_execbuf_release_pinned_bo(dev_priv);
 
-	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
 	if (unlikely(ret != 0))
 		goto err;
 
@@ -212,7 +212,7 @@ int vmw_dmabuf_to_start_of_vram(struct v
 
 	if (pin)
 		vmw_execbuf_release_pinned_bo(dev_priv);
-	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
 	if (unlikely(ret != 0))
 		goto err_unlock;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -316,7 +316,7 @@ static int vmw_dummy_query_bo_create(str
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = ttm_bo_reserve(bo, false, true, false, 0);
+	ret = ttm_bo_reserve(bo, false, true, false, NULL);
 	BUG_ON(ret != 0);
 
 	ret = ttm_bo_kmap(bo, 0, 1, &map);
@@ -946,7 +946,6 @@ static void vmw_postclose(struct drm_dev
 		drm_master_put(&vmw_fp->locked_master);
 	}
 
-	vmw_compat_shader_man_destroy(vmw_fp->shman);
 	ttm_object_file_release(&vmw_fp->tfile);
 	kfree(vmw_fp);
 }
@@ -966,16 +965,10 @@ static int vmw_driver_open(struct drm_de
 	if (unlikely(vmw_fp->tfile == NULL))
 		goto out_no_tfile;
 
-	vmw_fp->shman = vmw_compat_shader_man_create(dev_priv);
-	if (IS_ERR(vmw_fp->shman))
-		goto out_no_shman;
-
 	file_priv->driver_priv = vmw_fp;
 
 	return 0;
 
-out_no_shman:
-	ttm_object_file_release(&vmw_fp->tfile);
 out_no_tfile:
 	kfree(vmw_fp);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,10 +40,10 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20140325"
+#define VMWGFX_DRIVER_DATE "20140704"
 #define VMWGFX_DRIVER_MAJOR 2
 #define VMWGFX_DRIVER_MINOR 6
-#define VMWGFX_DRIVER_PATCHLEVEL 0
+#define VMWGFX_DRIVER_PATCHLEVEL 1
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_RELOCATIONS 2048
@@ -75,14 +75,11 @@
 #define VMW_RES_FENCE ttm_driver_type3
 #define VMW_RES_SHADER ttm_driver_type4
 
-struct vmw_compat_shader_manager;
-
 struct vmw_fpriv {
 	struct drm_master *locked_master;
 	struct ttm_object_file *tfile;
 	struct list_head fence_events;
 	bool gb_aware;
-	struct vmw_compat_shader_manager *shman;
 };
 
 struct vmw_dma_buffer {
@@ -124,6 +121,10 @@ struct vmw_resource {
 	void (*hw_destroy) (struct vmw_resource *res);
 };
 
+
+/*
+ * Resources that are managed using ioctls.
+ */
 enum vmw_res_type {
 	vmw_res_context,
 	vmw_res_surface,
@@ -132,6 +133,15 @@ enum vmw_res_type {
 	vmw_res_max
 };
 
+/*
+ * Resources that are managed using command streams.
+ */
+enum vmw_cmdbuf_res_type {
+	vmw_cmdbuf_res_compat_shader
+};
+
+struct vmw_cmdbuf_res_manager;
+
 struct vmw_cursor_snooper {
 	struct drm_crtc *crtc;
 	size_t age;
@@ -159,8 +169,8 @@ struct vmw_surface {
 
 struct vmw_marker_queue {
 	struct list_head head;
-	struct timespec lag;
-	struct timespec lag_time;
+	u64 lag;
+	u64 lag_time;
 	spinlock_t lock;
 };
 
@@ -341,7 +351,7 @@ struct vmw_sw_context{
 	bool needs_post_query_barrier;
 	struct vmw_resource *error_resource;
 	struct vmw_ctx_binding_state staged_bindings;
-	struct list_head staged_shaders;
+	struct list_head staged_cmd_res;
 };
 
 struct vmw_legacy_display;
@@ -974,7 +984,8 @@ extern void vmw_context_binding_res_list
 extern void vmw_context_binding_res_list_scrub(struct list_head *head);
 extern int vmw_context_rebind_all(struct vmw_resource *ctx);
 extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
-
+extern struct vmw_cmdbuf_res_manager *
+vmw_context_res_man(struct vmw_resource *ctx);
 /*
  * Surface management - vmwgfx_surface.c
  */
@@ -1008,27 +1019,42 @@ extern int vmw_shader_define_ioctl(struc
 				   struct drm_file *file_priv);
 extern int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
 				    struct drm_file *file_priv);
-extern int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
-				    SVGA3dShaderType shader_type,
-				    u32 *user_key);
-extern void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
-				      struct list_head *list);
-extern void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
-				      struct list_head *list);
-extern int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
-				    u32 user_key,
-				    SVGA3dShaderType shader_type,
-				    struct list_head *list);
-extern int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+extern int vmw_compat_shader_add(struct vmw_private *dev_priv,
+				 struct vmw_cmdbuf_res_manager *man,
 				 u32 user_key, const void *bytecode,
 				 SVGA3dShaderType shader_type,
 				 size_t size,
-				 struct ttm_object_file *tfile,
 				 struct list_head *list);
-extern struct vmw_compat_shader_manager *
-vmw_compat_shader_man_create(struct vmw_private *dev_priv);
-extern void
-vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man);
+extern int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man,
+				    u32 user_key, SVGA3dShaderType shader_type,
+				    struct list_head *list);
+extern struct vmw_resource *
+vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man,
+			 u32 user_key, SVGA3dShaderType shader_type);
+
+/*
+ * Command buffer managed resources - vmwgfx_cmdbuf_res.c
+ */
+
+extern struct vmw_cmdbuf_res_manager *
+vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv);
+extern void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man);
+extern size_t vmw_cmdbuf_res_man_size(void);
+extern struct vmw_resource *
+vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+		      enum vmw_cmdbuf_res_type res_type,
+		      u32 user_key);
+extern void vmw_cmdbuf_res_revert(struct list_head *list);
+extern void vmw_cmdbuf_res_commit(struct list_head *list);
+extern int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
+			      enum vmw_cmdbuf_res_type res_type,
+			      u32 user_key,
+			      struct vmw_resource *res,
+			      struct list_head *list);
+extern int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+				 enum vmw_cmdbuf_res_type res_type,
+				 u32 user_key,
+				 struct list_head *list);
 
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -422,28 +422,90 @@ static int vmw_resources_validate(struct
 	return 0;
 }
 
+
 /**
- * vmw_cmd_compat_res_check - Check that a resource is present and if so, put it
+ * vmw_cmd_res_reloc_add - Add a resource to a software context's
+ * relocation- and validation lists.
+ *
+ * @dev_priv: Pointer to a struct vmw_private identifying the device.
+ * @sw_context: Pointer to the software context.
+ * @res_type: Resource type.
+ * @id_loc: Pointer to where the id that needs translation is located.
+ * @res: Valid pointer to a struct vmw_resource.
+ * @p_val: If non null, a pointer to the struct vmw_resource_validate_node
+ * used for this resource is returned here.
+ */
+static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
+				 struct vmw_sw_context *sw_context,
+				 enum vmw_res_type res_type,
+				 uint32_t *id_loc,
+				 struct vmw_resource *res,
+				 struct vmw_resource_val_node **p_val)
+{
+	int ret;
+	struct vmw_resource_val_node *node;
+
+	*p_val = NULL;
+	ret = vmw_resource_relocation_add(&sw_context->res_relocations,
+					  res,
+					  id_loc - sw_context->buf_start);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_resource_val_add(sw_context, res, &node);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (res_type == vmw_res_context && dev_priv->has_mob &&
+	    node->first_usage) {
+
+		/*
+		 * Put contexts first on the list to be able to exit
+		 * list traversal for contexts early.
+		 */
+		list_del(&node->head);
+		list_add(&node->head, &sw_context->resource_list);
+
+		ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
+		if (unlikely(ret != 0))
+			return ret;
+		node->staged_bindings =
+			kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
+		if (node->staged_bindings == NULL) {
+			DRM_ERROR("Failed to allocate context binding "
+				  "information.\n");
+			return -ENOMEM;
+		}
+		INIT_LIST_HEAD(&node->staged_bindings->list);
+	}
+
+	if (p_val)
+		*p_val = node;
+
+	return 0;
+}
+
+
+/**
+ * vmw_cmd_res_check - Check that a resource is present and if so, put it
  * on the resource validate list unless it's already there.
  *
  * @dev_priv: Pointer to a device private structure.
  * @sw_context: Pointer to the software context.
  * @res_type: Resource type.
  * @converter: User-space visisble type specific information.
- * @id: user-space resource id handle.
  * @id_loc: Pointer to the location in the command buffer currently being
  * parsed from where the user-space resource id handle is located.
  * @p_val: Pointer to pointer to resource validalidation node. Populated
  * on exit.
  */
 static int
-vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
-			 struct vmw_sw_context *sw_context,
-			 enum vmw_res_type res_type,
-			 const struct vmw_user_resource_conv *converter,
-			 uint32_t id,
-			 uint32_t *id_loc,
-			 struct vmw_resource_val_node **p_val)
+vmw_cmd_res_check(struct vmw_private *dev_priv,
+		  struct vmw_sw_context *sw_context,
+		  enum vmw_res_type res_type,
+		  const struct vmw_user_resource_conv *converter,
+		  uint32_t *id_loc,
+		  struct vmw_resource_val_node **p_val)
 {
 	struct vmw_res_cache_entry *rcache =
 		&sw_context->res_cache[res_type];
@@ -451,7 +513,7 @@ vmw_cmd_compat_res_check(struct vmw_priv
 	struct vmw_resource_val_node *node;
 	int ret;
 
-	if (id == SVGA3D_INVALID_ID) {
+	if (*id_loc == SVGA3D_INVALID_ID) {
 		if (p_val)
 			*p_val = NULL;
 		if (res_type == vmw_res_context) {
@@ -466,7 +528,7 @@ vmw_cmd_compat_res_check(struct vmw_priv
 	 * resource
 	 */
 
-	if (likely(rcache->valid && id == rcache->handle)) {
+	if (likely(rcache->valid && *id_loc == rcache->handle)) {
 		const struct vmw_resource *res = rcache->res;
 
 		rcache->node->first_usage = false;
@@ -480,49 +542,28 @@ vmw_cmd_compat_res_check(struct vmw_priv
 
 	ret = vmw_user_resource_lookup_handle(dev_priv,
 					      sw_context->fp->tfile,
-					      id,
+					      *id_loc,
 					      converter,
 					      &res);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Could not find or use resource 0x%08x.\n",
-			  (unsigned) id);
+			  (unsigned) *id_loc);
 		dump_stack();
 		return ret;
 	}
 
 	rcache->valid = true;
 	rcache->res = res;
-	rcache->handle = id;
-
-	ret = vmw_resource_relocation_add(&sw_context->res_relocations,
-					  res,
-					  id_loc - sw_context->buf_start);
-	if (unlikely(ret != 0))
-		goto out_no_reloc;
+	rcache->handle = *id_loc;
 
-	ret = vmw_resource_val_add(sw_context, res, &node);
+	ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, res_type, id_loc,
+				    res, &node);
 	if (unlikely(ret != 0))
 		goto out_no_reloc;
 
 	rcache->node = node;
 	if (p_val)
 		*p_val = node;
-
-	if (dev_priv->has_mob && node->first_usage &&
-	    res_type == vmw_res_context) {
-		ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
-		if (unlikely(ret != 0))
-			goto out_no_reloc;
-		node->staged_bindings =
-			kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
-		if (node->staged_bindings == NULL) {
-			DRM_ERROR("Failed to allocate context binding "
-				  "information.\n");
-			goto out_no_reloc;
-		}
-		INIT_LIST_HEAD(&node->staged_bindings->list);
-	}
-
 	vmw_resource_unreference(&res);
 	return 0;
 
@@ -534,31 +575,6 @@ out_no_reloc:
 }
 
 /**
- * vmw_cmd_res_check - Check that a resource is present and if so, put it
- * on the resource validate list unless it's already there.
- *
- * @dev_priv: Pointer to a device private structure.
- * @sw_context: Pointer to the software context.
- * @res_type: Resource type.
- * @converter: User-space visisble type specific information.
- * @id_loc: Pointer to the location in the command buffer currently being
- * parsed from where the user-space resource id handle is located.
- * @p_val: Pointer to pointer to resource validalidation node. Populated
- * on exit.
- */
-static int
-vmw_cmd_res_check(struct vmw_private *dev_priv,
-		  struct vmw_sw_context *sw_context,
-		  enum vmw_res_type res_type,
-		  const struct vmw_user_resource_conv *converter,
-		  uint32_t *id_loc,
-		  struct vmw_resource_val_node **p_val)
-{
-	return vmw_cmd_compat_res_check(dev_priv, sw_context, res_type,
-					converter, *id_loc, id_loc, p_val);
-}
-
-/**
  * vmw_rebind_contexts - Rebind all resources previously bound to
  * referenced contexts.
  *
@@ -572,8 +588,8 @@ static int vmw_rebind_contexts(struct vm
 	int ret;
 
 	list_for_each_entry(val, &sw_context->resource_list, head) {
-		if (likely(!val->staged_bindings))
-			continue;
+		if (unlikely(!val->staged_bindings))
+			break;
 
 		ret = vmw_context_rebind_all(val->res);
 		if (unlikely(ret != 0)) {
@@ -1626,13 +1642,14 @@ static int vmw_cmd_shader_define(struct
 	} *cmd;
 	int ret;
 	size_t size;
+	struct vmw_resource_val_node *val;
 
 	cmd = container_of(header, struct vmw_shader_define_cmd,
 			   header);
 
 	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
 				user_context_converter, &cmd->body.cid,
-				NULL);
+				&val);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1640,11 +1657,11 @@ static int vmw_cmd_shader_define(struct
 		return 0;
 
 	size = cmd->header.size - sizeof(cmd->body);
-	ret = vmw_compat_shader_add(sw_context->fp->shman,
+	ret = vmw_compat_shader_add(dev_priv,
+				    vmw_context_res_man(val->res),
 				    cmd->body.shid, cmd + 1,
 				    cmd->body.type, size,
-				    sw_context->fp->tfile,
-				    &sw_context->staged_shaders);
+				    &sw_context->staged_cmd_res);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1672,23 +1689,24 @@ static int vmw_cmd_shader_destroy(struct
 		SVGA3dCmdDestroyShader body;
 	} *cmd;
 	int ret;
+	struct vmw_resource_val_node *val;
 
 	cmd = container_of(header, struct vmw_shader_destroy_cmd,
 			   header);
 
 	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
 				user_context_converter, &cmd->body.cid,
-				NULL);
+				&val);
 	if (unlikely(ret != 0))
 		return ret;
 
 	if (unlikely(!dev_priv->has_mob))
 		return 0;
 
-	ret = vmw_compat_shader_remove(sw_context->fp->shman,
+	ret = vmw_compat_shader_remove(vmw_context_res_man(val->res),
 				       cmd->body.shid,
 				       cmd->body.type,
-				       &sw_context->staged_shaders);
+				       &sw_context->staged_cmd_res);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1715,7 +1733,9 @@ static int vmw_cmd_set_shader(struct vmw
 		SVGA3dCmdHeader header;
 		SVGA3dCmdSetShader body;
 	} *cmd;
-	struct vmw_resource_val_node *ctx_node;
+	struct vmw_resource_val_node *ctx_node, *res_node = NULL;
+	struct vmw_ctx_bindinfo bi;
+	struct vmw_resource *res = NULL;
 	int ret;
 
 	cmd = container_of(header, struct vmw_set_shader_cmd,
@@ -1727,32 +1747,40 @@ static int vmw_cmd_set_shader(struct vmw
 	if (unlikely(ret != 0))
 		return ret;
 
-	if (dev_priv->has_mob) {
-		struct vmw_ctx_bindinfo bi;
-		struct vmw_resource_val_node *res_node;
-		u32 shid = cmd->body.shid;
+	if (!dev_priv->has_mob)
+		return 0;
 
-		if (shid != SVGA3D_INVALID_ID)
-			(void) vmw_compat_shader_lookup(sw_context->fp->shman,
-							cmd->body.type,
-							&shid);
+	if (cmd->body.shid != SVGA3D_INVALID_ID) {
+		res = vmw_compat_shader_lookup
+			(vmw_context_res_man(ctx_node->res),
+			 cmd->body.shid,
+			 cmd->body.type);
 
-		ret = vmw_cmd_compat_res_check(dev_priv, sw_context,
-					       vmw_res_shader,
-					       user_shader_converter,
-					       shid,
-					       &cmd->body.shid, &res_node);
+		if (!IS_ERR(res)) {
+			ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
+						    vmw_res_shader,
+						    &cmd->body.shid, res,
+						    &res_node);
+			vmw_resource_unreference(&res);
+			if (unlikely(ret != 0))
+				return ret;
+		}
+	}
+
+	if (!res_node) {
+		ret = vmw_cmd_res_check(dev_priv, sw_context,
+					vmw_res_shader,
+					user_shader_converter,
+					&cmd->body.shid, &res_node);
 		if (unlikely(ret != 0))
 			return ret;
-
-		bi.ctx = ctx_node->res;
-		bi.res = res_node ? res_node->res : NULL;
-		bi.bt = vmw_ctx_binding_shader;
-		bi.i1.shader_type = cmd->body.type;
-		return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
 	}
 
-	return 0;
+	bi.ctx = ctx_node->res;
+	bi.res = res_node ? res_node->res : NULL;
+	bi.bt = vmw_ctx_binding_shader;
+	bi.i1.shader_type = cmd->body.type;
+	return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
 }
 
 /**
@@ -2394,6 +2422,8 @@ vmw_execbuf_copy_fence_user(struct vmw_p
 	}
 }
 
+
+
 int vmw_execbuf_process(struct drm_file *file_priv,
 			struct vmw_private *dev_priv,
 			void __user *user_commands,
@@ -2453,7 +2483,7 @@ int vmw_execbuf_process(struct drm_file
 			goto out_unlock;
 		sw_context->res_ht_initialized = true;
 	}
-	INIT_LIST_HEAD(&sw_context->staged_shaders);
+	INIT_LIST_HEAD(&sw_context->staged_cmd_res);
 
 	INIT_LIST_HEAD(&resource_list);
 	ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
@@ -2548,8 +2578,7 @@ int vmw_execbuf_process(struct drm_file
 	}
 
 	list_splice_init(&sw_context->resource_list, &resource_list);
-	vmw_compat_shaders_commit(sw_context->fp->shman,
-				  &sw_context->staged_shaders);
+	vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res);
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
 
 	/*
@@ -2576,8 +2605,7 @@ out_unlock:
 	list_splice_init(&sw_context->resource_list, &resource_list);
 	error_resource = sw_context->error_resource;
 	sw_context->error_resource = NULL;
-	vmw_compat_shaders_revert(sw_context->fp->shman,
-				  &sw_context->staged_shaders);
+	vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2014-09-28 17:29:07.000000000 -0400
@@ -180,8 +180,9 @@ void vmw_fifo_release(struct vmw_private
 
 	mutex_lock(&dev_priv->hw_mutex);
 
+	vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
 	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
-		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+		;
 
 	dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,7 @@ struct vmwgfx_gmrid_man {
 static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
 				  struct ttm_buffer_object *bo,
 				  struct ttm_placement *placement,
+				  uint32_t flags,
 				  struct ttm_mem_reg *mem)
 {
 	struct vmwgfx_gmrid_man *gman =
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,7 @@ void vmw_display_unit_cleanup(struct vmw
 		vmw_surface_unreference(&du->cursor_surface);
 	if (du->cursor_dmabuf)
 		vmw_dmabuf_unreference(&du->cursor_dmabuf);
-	drm_sysfs_connector_remove(&du->connector);
+	drm_connector_unregister(&du->connector);
 	drm_crtc_cleanup(&du->crtc);
 	drm_encoder_cleanup(&du->encoder);
 	drm_connector_cleanup(&du->connector);
@@ -136,7 +136,7 @@ int vmw_cursor_update_dmabuf(struct vmw_
 	kmap_offset = 0;
 	kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
-	ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+	ret = ttm_bo_reserve(&dmabuf->base, true, false, false, NULL);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("reserve failed\n");
 		return -EINVAL;
@@ -343,7 +343,7 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 	kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
 	kmap_num = (64*64*4) >> PAGE_SHIFT;
 
-	ret = ttm_bo_reserve(bo, true, false, false, 0);
+	ret = ttm_bo_reserve(bo, true, false, false, NULL);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("reserve failed\n");
 		return;
@@ -1501,7 +1501,6 @@ int vmw_kms_cursor_bypass_ioctl(struct d
 {
 	struct drm_vmw_cursor_bypass_arg *arg = data;
 	struct vmw_display_unit *du;
-	struct drm_mode_object *obj;
 	struct drm_crtc *crtc;
 	int ret = 0;
 
@@ -1519,13 +1518,12 @@ int vmw_kms_cursor_bypass_ioctl(struct d
 		return 0;
 	}
 
-	obj = drm_mode_object_find(dev, arg->crtc_id, DRM_MODE_OBJECT_CRTC);
-	if (!obj) {
+	crtc = drm_crtc_find(dev, arg->crtc_id);
+	if (!crtc) {
 		ret = -ENOENT;
 		goto out;
 	}
 
-	crtc = obj_to_crtc(obj);
 	du = vmw_crtc_to_du(crtc);
 
 	du->hotspot_x = arg->xhot;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2014-09-28 17:29:07.000000000 -0400
@@ -371,7 +371,7 @@ static int vmw_ldu_init(struct vmw_priva
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
-	(void) drm_sysfs_connector_add(connector);
+	(void) drm_connector_register(connector);
 
 	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,14 +31,14 @@
 struct vmw_marker {
 	struct list_head head;
 	uint32_t seqno;
-	struct timespec submitted;
+	u64 submitted;
 };
 
 void vmw_marker_queue_init(struct vmw_marker_queue *queue)
 {
 	INIT_LIST_HEAD(&queue->head);
-	queue->lag = ns_to_timespec(0);
-	getrawmonotonic(&queue->lag_time);
+	queue->lag = 0;
+	queue->lag_time = ktime_get_raw_ns();
 	spin_lock_init(&queue->lock);
 }
 
@@ -62,7 +62,7 @@ int vmw_marker_push(struct vmw_marker_qu
 		return -ENOMEM;
 
 	marker->seqno = seqno;
-	getrawmonotonic(&marker->submitted);
+	marker->submitted = ktime_get_raw_ns();
 	spin_lock(&queue->lock);
 	list_add_tail(&marker->head, &queue->head);
 	spin_unlock(&queue->lock);
@@ -74,14 +74,14 @@ int vmw_marker_pull(struct vmw_marker_qu
 		   uint32_t signaled_seqno)
 {
 	struct vmw_marker *marker, *next;
-	struct timespec now;
 	bool updated = false;
+	u64 now;
 
 	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
+	now = ktime_get_raw_ns();
 
 	if (list_empty(&queue->head)) {
-		queue->lag = ns_to_timespec(0);
+		queue->lag = 0;
 		queue->lag_time = now;
 		updated = true;
 		goto out_unlock;
@@ -91,7 +91,7 @@ int vmw_marker_pull(struct vmw_marker_qu
 		if (signaled_seqno - marker->seqno > (1 << 30))
 			continue;
 
-		queue->lag = timespec_sub(now, marker->submitted);
+		queue->lag = now - marker->submitted;
 		queue->lag_time = now;
 		updated = true;
 		list_del(&marker->head);
@@ -104,27 +104,13 @@ out_unlock:
 	return (updated) ? 0 : -EBUSY;
 }
 
-static struct timespec vmw_timespec_add(struct timespec t1,
-					struct timespec t2)
-{
-	t1.tv_sec += t2.tv_sec;
-	t1.tv_nsec += t2.tv_nsec;
-	if (t1.tv_nsec >= 1000000000L) {
-		t1.tv_sec += 1;
-		t1.tv_nsec -= 1000000000L;
-	}
-
-	return t1;
-}
-
-static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
+static u64 vmw_fifo_lag(struct vmw_marker_queue *queue)
 {
-	struct timespec now;
+	u64 now;
 
 	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
-	queue->lag = vmw_timespec_add(queue->lag,
-				      timespec_sub(now, queue->lag_time));
+	now = ktime_get_raw_ns();
+	queue->lag += now - queue->lag_time;
 	queue->lag_time = now;
 	spin_unlock(&queue->lock);
 	return queue->lag;
@@ -134,11 +120,9 @@ static struct timespec vmw_fifo_lag(stru
 static bool vmw_lag_lt(struct vmw_marker_queue *queue,
 		       uint32_t us)
 {
-	struct timespec lag, cond;
+	u64 cond = (u64) us * NSEC_PER_USEC;
 
-	cond = ns_to_timespec((s64) us * 1000);
-	lag = vmw_fifo_lag(queue);
-	return (timespec_compare(&lag, &cond) < 1);
+	return vmw_fifo_lag(queue) <= cond;
 }
 
 int vmw_wait_lag(struct vmw_private *dev_priv,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2014-09-28 17:29:07.000000000 -0400
@@ -127,7 +127,7 @@ static void vmw_resource_release(struct
 	if (res->backup) {
 		struct ttm_buffer_object *bo = &res->backup->base;
 
-		ttm_bo_reserve(bo, false, false, false, 0);
+		ttm_bo_reserve(bo, false, false, false, NULL);
 		if (!list_empty(&res->mob_head) &&
 		    res->func->unbind != NULL) {
 			struct ttm_validate_buffer val_buf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2014-09-28 17:29:07.000000000 -0400
@@ -467,7 +467,7 @@ static int vmw_sou_init(struct vmw_priva
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
-	(void) drm_sysfs_connector_add(connector);
+	(void) drm_connector_register(connector);
 
 	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
--- linux-libre-3.16-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,8 +29,6 @@
 #include "vmwgfx_resource_priv.h"
 #include "ttm/ttm_placement.h"
 
-#define VMW_COMPAT_SHADER_HT_ORDER 12
-
 struct vmw_shader {
 	struct vmw_resource res;
 	SVGA3dShaderType type;
@@ -42,49 +40,8 @@ struct vmw_user_shader {
 	struct vmw_shader shader;
 };
 
-/**
- * enum vmw_compat_shader_state - Staging state for compat shaders
- */
-enum vmw_compat_shader_state {
-	VMW_COMPAT_COMMITED,
-	VMW_COMPAT_ADD,
-	VMW_COMPAT_DEL
-};
-
-/**
- * struct vmw_compat_shader - Metadata for compat shaders.
- *
- * @handle: The TTM handle of the guest backed shader.
- * @tfile: The struct ttm_object_file the guest backed shader is registered
- * with.
- * @hash: Hash item for lookup.
- * @head: List head for staging lists or the compat shader manager list.
- * @state: Staging state.
- *
- * The structure is protected by the cmdbuf lock.
- */
-struct vmw_compat_shader {
-	u32 handle;
-	struct ttm_object_file *tfile;
-	struct drm_hash_item hash;
-	struct list_head head;
-	enum vmw_compat_shader_state state;
-};
-
-/**
- * struct vmw_compat_shader_manager - Compat shader manager.
- *
- * @shaders: Hash table containing staged and commited compat shaders
- * @list: List of commited shaders.
- * @dev_priv: Pointer to a device private structure.
- *
- * @shaders and @list are protected by the cmdbuf mutex for now.
- */
-struct vmw_compat_shader_manager {
-	struct drm_open_hash shaders;
-	struct list_head list;
-	struct vmw_private *dev_priv;
-};
+static uint64_t vmw_user_shader_size;
+static uint64_t vmw_shader_size;
 
 static void vmw_user_shader_free(struct vmw_resource *res);
 static struct vmw_resource *
@@ -98,8 +55,6 @@ static int vmw_gb_shader_unbind(struct v
 				 struct ttm_validate_buffer *val_buf);
 static int vmw_gb_shader_destroy(struct vmw_resource *res);
 
-static uint64_t vmw_user_shader_size;
-
 static const struct vmw_user_resource_conv user_shader_conv = {
 	.object_type = VMW_RES_SHADER,
 	.base_obj_to_res = vmw_user_shader_base_to_res,
@@ -347,6 +302,16 @@ static void vmw_user_shader_free(struct
 			    vmw_user_shader_size);
 }
 
+static void vmw_shader_free(struct vmw_resource *res)
+{
+	struct vmw_shader *shader = vmw_res_to_shader(res);
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	kfree(shader);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_shader_size);
+}
+
 /**
  * This function is called when user space has no more references on the
  * base object. It releases the base-object's reference on the resource object.
@@ -371,13 +336,13 @@ int vmw_shader_destroy_ioctl(struct drm_
 					 TTM_REF_USAGE);
 }
 
-static int vmw_shader_alloc(struct vmw_private *dev_priv,
-			    struct vmw_dma_buffer *buffer,
-			    size_t shader_size,
-			    size_t offset,
-			    SVGA3dShaderType shader_type,
-			    struct ttm_object_file *tfile,
-			    u32 *handle)
+static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
+				 struct vmw_dma_buffer *buffer,
+				 size_t shader_size,
+				 size_t offset,
+				 SVGA3dShaderType shader_type,
+				 struct ttm_object_file *tfile,
+				 u32 *handle)
 {
 	struct vmw_user_shader *ushader;
 	struct vmw_resource *res, *tmp;
@@ -442,6 +407,56 @@ out:
 }
 
 
+struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
+				      struct vmw_dma_buffer *buffer,
+				      size_t shader_size,
+				      size_t offset,
+				      SVGA3dShaderType shader_type)
+{
+	struct vmw_shader *shader;
+	struct vmw_resource *res;
+	int ret;
+
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of shaders anyway.
+	 */
+	if (unlikely(vmw_shader_size == 0))
+		vmw_shader_size =
+			ttm_round_pot(sizeof(struct vmw_shader)) + 128;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_shader_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for shader "
+				  "creation.\n");
+		goto out_err;
+	}
+
+	shader = kzalloc(sizeof(*shader), GFP_KERNEL);
+	if (unlikely(shader == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_shader_size);
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	res = &shader->res;
+
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+	ret = vmw_gb_shader_init(dev_priv, res, shader_size,
+				 offset, shader_type, buffer,
+				 vmw_shader_free);
+
+out_err:
+	return ret ? ERR_PTR(ret) : res;
+}
+
+
 int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv)
 {
@@ -490,8 +505,8 @@ int vmw_shader_define_ioctl(struct drm_d
 	if (unlikely(ret != 0))
 		goto out_bad_arg;
 
-	ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
-			       shader_type, tfile, &arg->shader_handle);
+	ret = vmw_user_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
+				    shader_type, tfile, &arg->shader_handle);
 
 	ttm_read_unlock(&dev_priv->reservation_sem);
 out_bad_arg:
@@ -500,202 +515,83 @@ out_bad_arg:
 }
 
 /**
- * vmw_compat_shader_lookup - Look up a compat shader
- *
- * @man: Pointer to the compat shader manager.
- * @shader_type: The shader type, that combined with the user_key identifies
- * the shader.
- * @user_key: On entry, this should be a pointer to the user_key.
- * On successful exit, it will contain the guest-backed shader's TTM handle.
- *
- * Returns 0 on success. Non-zero on failure, in which case the value pointed
- * to by @user_key is unmodified.
- */
-int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
-			     SVGA3dShaderType shader_type,
-			     u32 *user_key)
-{
-	struct drm_hash_item *hash;
-	int ret;
-	unsigned long key = *user_key | (shader_type << 24);
-
-	ret = drm_ht_find_item(&man->shaders, key, &hash);
-	if (unlikely(ret != 0))
-		return ret;
-
-	*user_key = drm_hash_entry(hash, struct vmw_compat_shader,
-				   hash)->handle;
-
-	return 0;
-}
-
-/**
- * vmw_compat_shader_free - Free a compat shader.
- *
- * @man: Pointer to the compat shader manager.
- * @entry: Pointer to a struct vmw_compat_shader.
- *
- * Frees a struct vmw_compat_shder entry and drops its reference to the
- * guest backed shader.
- */
-static void vmw_compat_shader_free(struct vmw_compat_shader_manager *man,
-				   struct vmw_compat_shader *entry)
-{
-	list_del(&entry->head);
-	WARN_ON(drm_ht_remove_item(&man->shaders, &entry->hash));
-	WARN_ON(ttm_ref_object_base_unref(entry->tfile, entry->handle,
-					  TTM_REF_USAGE));
-	kfree(entry);
-}
-
-/**
- * vmw_compat_shaders_commit - Commit a list of compat shader actions.
+ * vmw_compat_shader_id_ok - Check whether a compat shader user key and
+ * shader type are within valid bounds.
  *
- * @man: Pointer to the compat shader manager.
- * @list: Caller's list of compat shader actions.
+ * @user_key: User space id of the shader.
+ * @shader_type: Shader type.
  *
- * This function commits a list of compat shader additions or removals.
- * It is typically called when the execbuf ioctl call triggering these
- * actions has commited the fifo contents to the device.
+ * Returns true if valid false if not.
  */
-void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
-			       struct list_head *list)
+static bool vmw_compat_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
 {
-	struct vmw_compat_shader *entry, *next;
-
-	list_for_each_entry_safe(entry, next, list, head) {
-		list_del(&entry->head);
-		switch (entry->state) {
-		case VMW_COMPAT_ADD:
-			entry->state = VMW_COMPAT_COMMITED;
-			list_add_tail(&entry->head, &man->list);
-			break;
-		case VMW_COMPAT_DEL:
-			ttm_ref_object_base_unref(entry->tfile, entry->handle,
-						  TTM_REF_USAGE);
-			kfree(entry);
-			break;
-		default:
-			BUG();
-			break;
-		}
-	}
+	return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
 }
 
 /**
- * vmw_compat_shaders_revert - Revert a list of compat shader actions
+ * vmw_compat_shader_key - Compute a hash key suitable for a compat shader.
  *
- * @man: Pointer to the compat shader manager.
- * @list: Caller's list of compat shader actions.
+ * @user_key: User space id of the shader.
+ * @shader_type: Shader type.
  *
- * This function reverts a list of compat shader additions or removals.
- * It is typically called when the execbuf ioctl call triggering these
- * actions failed for some reason, and the command stream was never
- * submitted.
+ * Returns a hash key suitable for a command buffer managed resource
+ * manager hash table.
  */
-void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
-			       struct list_head *list)
+static u32 vmw_compat_shader_key(u32 user_key, SVGA3dShaderType shader_type)
 {
-	struct vmw_compat_shader *entry, *next;
-	int ret;
-
-	list_for_each_entry_safe(entry, next, list, head) {
-		switch (entry->state) {
-		case VMW_COMPAT_ADD:
-			vmw_compat_shader_free(man, entry);
-			break;
-		case VMW_COMPAT_DEL:
-			ret = drm_ht_insert_item(&man->shaders, &entry->hash);
-			list_del(&entry->head);
-			list_add_tail(&entry->head, &man->list);
-			entry->state = VMW_COMPAT_COMMITED;
-			break;
-		default:
-			BUG();
-			break;
-		}
-	}
+	return user_key | (shader_type << 20);
 }
 
 /**
  * vmw_compat_shader_remove - Stage a compat shader for removal.
  *
- * @man: Pointer to the compat shader manager
+ * @man: Pointer to the compat shader manager identifying the shader namespace.
  * @user_key: The key that is used to identify the shader. The key is
  * unique to the shader type.
  * @shader_type: Shader type.
- * @list: Caller's list of staged shader actions.
- *
- * This function stages a compat shader for removal and removes the key from
- * the shader manager's hash table. If the shader was previously only staged
- * for addition it is completely removed (But the execbuf code may keep a
- * reference if it was bound to a context between addition and removal). If
- * it was previously commited to the manager, it is staged for removal.
+ * @list: Caller's list of staged command buffer resource actions.
  */
-int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
+int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man,
 			     u32 user_key, SVGA3dShaderType shader_type,
 			     struct list_head *list)
 {
-	struct vmw_compat_shader *entry;
-	struct drm_hash_item *hash;
-	int ret;
-
-	ret = drm_ht_find_item(&man->shaders, user_key | (shader_type << 24),
-			       &hash);
-	if (likely(ret != 0))
+	if (!vmw_compat_shader_id_ok(user_key, shader_type))
 		return -EINVAL;
 
-	entry = drm_hash_entry(hash, struct vmw_compat_shader, hash);
-
-	switch (entry->state) {
-	case VMW_COMPAT_ADD:
-		vmw_compat_shader_free(man, entry);
-		break;
-	case VMW_COMPAT_COMMITED:
-		(void) drm_ht_remove_item(&man->shaders, &entry->hash);
-		list_del(&entry->head);
-		entry->state = VMW_COMPAT_DEL;
-		list_add_tail(&entry->head, list);
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	return 0;
+	return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_compat_shader,
+				     vmw_compat_shader_key(user_key,
+							   shader_type),
+				     list);
 }
 
 /**
- * vmw_compat_shader_add - Create a compat shader and add the
- * key to the manager
+ * vmw_compat_shader_add - Create a compat shader and stage it for addition
+ * as a command buffer managed resource.
  *
- * @man: Pointer to the compat shader manager
+ * @man: Pointer to the compat shader manager identifying the shader namespace.
  * @user_key: The key that is used to identify the shader. The key is
  * unique to the shader type.
  * @bytecode: Pointer to the bytecode of the shader.
  * @shader_type: Shader type.
  * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
  * to be created with.
- * @list: Caller's list of staged shader actions.
+ * @list: Caller's list of staged command buffer resource actions.
  *
- * Note that only the key is added to the shader manager's hash table.
- * The shader is not yet added to the shader manager's list of shaders.
  */
-int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+int vmw_compat_shader_add(struct vmw_private *dev_priv,
+			  struct vmw_cmdbuf_res_manager *man,
 			  u32 user_key, const void *bytecode,
 			  SVGA3dShaderType shader_type,
 			  size_t size,
-			  struct ttm_object_file *tfile,
 			  struct list_head *list)
 {
 	struct vmw_dma_buffer *buf;
 	struct ttm_bo_kmap_obj map;
 	bool is_iomem;
-	struct vmw_compat_shader *compat;
-	u32 handle;
 	int ret;
+	struct vmw_resource *res;
 
-	if (user_key > ((1 << 24) - 1) || (unsigned) shader_type > 16)
+	if (!vmw_compat_shader_id_ok(user_key, shader_type))
 		return -EINVAL;
 
 	/* Allocate and pin a DMA buffer */
@@ -703,7 +599,7 @@ int vmw_compat_shader_add(struct vmw_com
 	if (unlikely(buf == NULL))
 		return -ENOMEM;
 
-	ret = vmw_dmabuf_init(man->dev_priv, buf, size, &vmw_sys_ne_placement,
+	ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement,
 			      true, vmw_dmabuf_bo_free);
 	if (unlikely(ret != 0))
 		goto out;
@@ -728,84 +624,40 @@ int vmw_compat_shader_add(struct vmw_com
 	WARN_ON(ret != 0);
 	ttm_bo_unreserve(&buf->base);
 
-	/* Create a guest-backed shader container backed by the dma buffer */
-	ret = vmw_shader_alloc(man->dev_priv, buf, size, 0, shader_type,
-			       tfile, &handle);
-	vmw_dmabuf_unreference(&buf);
+	res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
 	if (unlikely(ret != 0))
 		goto no_reserve;
-	/*
-	 * Create a compat shader structure and stage it for insertion
-	 * in the manager
-	 */
-	compat = kzalloc(sizeof(*compat), GFP_KERNEL);
-	if (compat == NULL)
-		goto no_compat;
-
-	compat->hash.key = user_key |  (shader_type << 24);
-	ret = drm_ht_insert_item(&man->shaders, &compat->hash);
-	if (unlikely(ret != 0))
-		goto out_invalid_key;
 
-	compat->state = VMW_COMPAT_ADD;
-	compat->handle = handle;
-	compat->tfile = tfile;
-	list_add_tail(&compat->head, list);
-
-	return 0;
-
-out_invalid_key:
-	kfree(compat);
-no_compat:
-	ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
+	ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_compat_shader,
+				 vmw_compat_shader_key(user_key, shader_type),
+				 res, list);
+	vmw_resource_unreference(&res);
 no_reserve:
+	vmw_dmabuf_unreference(&buf);
 out:
 	return ret;
 }
 
 /**
- * vmw_compat_shader_man_create - Create a compat shader manager
- *
- * @dev_priv: Pointer to a device private structure.
- *
- * Typically done at file open time. If successful returns a pointer to a
- * compat shader manager. Otherwise returns an error pointer.
- */
-struct vmw_compat_shader_manager *
-vmw_compat_shader_man_create(struct vmw_private *dev_priv)
-{
-	struct vmw_compat_shader_manager *man;
-	int ret;
-
-	man = kzalloc(sizeof(*man), GFP_KERNEL);
-	if (man == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	man->dev_priv = dev_priv;
-	INIT_LIST_HEAD(&man->list);
-	ret = drm_ht_create(&man->shaders, VMW_COMPAT_SHADER_HT_ORDER);
-	if (ret == 0)
-		return man;
-
-	kfree(man);
-	return ERR_PTR(ret);
-}
-
-/**
- * vmw_compat_shader_man_destroy - Destroy a compat shader manager
+ * vmw_compat_shader_lookup - Look up a compat shader
  *
- * @man: Pointer to the shader manager to destroy.
+ * @man: Pointer to the command buffer managed resource manager identifying
+ * the shader namespace.
+ * @user_key: The user space id of the shader.
+ * @shader_type: The shader type.
  *
- * Typically done at file close time.
+ * Returns a refcounted pointer to a struct vmw_resource if the shader was
+ * found. An error pointer otherwise.
  */
-void vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man)
+struct vmw_resource *
+vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man,
+			 u32 user_key,
+			 SVGA3dShaderType shader_type)
 {
-	struct vmw_compat_shader *entry, *next;
-
-	mutex_lock(&man->dev_priv->cmdbuf_mutex);
-	list_for_each_entry_safe(entry, next, &man->list, head)
-		vmw_compat_shader_free(man, entry);
+	if (!vmw_compat_shader_id_ok(user_key, shader_type))
+		return ERR_PTR(-EINVAL);
 
-	mutex_unlock(&man->dev_priv->cmdbuf_mutex);
-	kfree(man);
+	return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_compat_shader,
+				     vmw_compat_shader_key(user_key,
+							   shader_type));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/host1x/job.c linux-libre-3.17-rc7-gnu/drivers/gpu/host1x/job.c
--- linux-libre-3.16-gnu/drivers/gpu/host1x/job.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/host1x/job.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,16 +185,16 @@ static unsigned int pin_job(struct host1
 		struct sg_table *sgt;
 		dma_addr_t phys_addr;
 
-		reloc->target = host1x_bo_get(reloc->target);
-		if (!reloc->target)
+		reloc->target.bo = host1x_bo_get(reloc->target.bo);
+		if (!reloc->target.bo)
 			goto unpin;
 
-		phys_addr = host1x_bo_pin(reloc->target, &sgt);
+		phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
 		if (!phys_addr)
 			goto unpin;
 
 		job->addr_phys[job->num_unpins] = phys_addr;
-		job->unpins[job->num_unpins].bo = reloc->target;
+		job->unpins[job->num_unpins].bo = reloc->target.bo;
 		job->unpins[job->num_unpins].sgt = sgt;
 		job->num_unpins++;
 	}
@@ -235,21 +235,21 @@ static unsigned int do_relocs(struct hos
 	for (i = 0; i < job->num_relocs; i++) {
 		struct host1x_reloc *reloc = &job->relocarray[i];
 		u32 reloc_addr = (job->reloc_addr_phys[i] +
-			reloc->target_offset) >> reloc->shift;
+				  reloc->target.offset) >> reloc->shift;
 		u32 *target;
 
 		/* skip all other gathers */
-		if (cmdbuf != reloc->cmdbuf)
+		if (cmdbuf != reloc->cmdbuf.bo)
 			continue;
 
-		if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) {
+		if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
 			if (cmdbuf_page_addr)
 				host1x_bo_kunmap(cmdbuf, last_page,
 						 cmdbuf_page_addr);
 
 			cmdbuf_page_addr = host1x_bo_kmap(cmdbuf,
-					reloc->cmdbuf_offset >> PAGE_SHIFT);
-			last_page = reloc->cmdbuf_offset >> PAGE_SHIFT;
+					reloc->cmdbuf.offset >> PAGE_SHIFT);
+			last_page = reloc->cmdbuf.offset >> PAGE_SHIFT;
 
 			if (unlikely(!cmdbuf_page_addr)) {
 				pr_err("Could not map cmdbuf for relocation\n");
@@ -257,7 +257,7 @@ static unsigned int do_relocs(struct hos
 			}
 		}
 
-		target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK);
+		target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
 		*target = reloc_addr;
 	}
 
@@ -272,7 +272,7 @@ static bool check_reloc(struct host1x_re
 {
 	offset *= sizeof(u32);
 
-	if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset)
+	if (reloc->cmdbuf.bo != cmdbuf || reloc->cmdbuf.offset != offset)
 		return false;
 
 	return true;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/vga/vgaarb.c linux-libre-3.17-rc7-gnu/drivers/gpu/vga/vgaarb.c
--- linux-libre-3.16-gnu/drivers/gpu/vga/vgaarb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/vga/vgaarb.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
+#include <linux/screen_info.h>
 
 #include <linux/uaccess.h>
 
@@ -112,10 +113,8 @@ both:
 	return 1;
 }
 
-#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 /* this is only used a cookie - it should not be dereferenced */
 static struct pci_dev *vga_default;
-#endif
 
 static void vga_arb_device_card_gone(struct pci_dev *pdev);
 
@@ -131,7 +130,6 @@ static struct vga_device *vgadev_find(st
 }
 
 /* Returns the default VGA device (vgacon's babe) */
-#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 struct pci_dev *vga_default_device(void)
 {
 	return vga_default;
@@ -147,7 +145,6 @@ void vga_set_default_device(struct pci_d
 	pci_dev_put(vga_default);
 	vga_default = pci_dev_get(pdev);
 }
-#endif
 
 static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
 {
@@ -237,12 +234,10 @@ static struct vga_device *__vga_tryget(s
 		if (conflict->locks & lwants)
 			return conflict;
 
-		/* Ok, now check if he owns the resource we want. We don't need
-		 * to check "decodes" since it should be impossible to own
-		 * own legacy resources you don't decode unless I have a bug
-		 * in this code...
+		/* Ok, now check if it owns the resource we want.  We can
+		 * lock resources that are not decoded, therefore a device
+		 * can own resources it doesn't decode.
 		 */
-		WARN_ON(conflict->owns & ~conflict->decodes);
 		match = lwants & conflict->owns;
 		if (!match)
 			continue;
@@ -254,13 +249,19 @@ static struct vga_device *__vga_tryget(s
 		flags = 0;
 		pci_bits = 0;
 
+		/* If we can't control legacy resources via the bridge, we
+		 * also need to disable normal decoding.
+		 */
 		if (!conflict->bridge_has_one_vga) {
-			vga_irq_set_state(conflict, false);
-			flags |= PCI_VGA_STATE_CHANGE_DECODES;
-			if (match & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
+			if ((match & conflict->decodes) & VGA_RSRC_LEGACY_MEM)
 				pci_bits |= PCI_COMMAND_MEMORY;
-			if (match & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
+			if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO)
 				pci_bits |= PCI_COMMAND_IO;
+
+			if (pci_bits) {
+				vga_irq_set_state(conflict, false);
+				flags |= PCI_VGA_STATE_CHANGE_DECODES;
+			}
 		}
 
 		if (change_bridge)
@@ -268,18 +269,19 @@ static struct vga_device *__vga_tryget(s
 
 		pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
 		conflict->owns &= ~match;
-		/* If he also owned non-legacy, that is no longer the case */
-		if (match & VGA_RSRC_LEGACY_MEM)
+
+		/* If we disabled normal decoding, reflect it in owns */
+		if (pci_bits & PCI_COMMAND_MEMORY)
 			conflict->owns &= ~VGA_RSRC_NORMAL_MEM;
-		if (match & VGA_RSRC_LEGACY_IO)
+		if (pci_bits & PCI_COMMAND_IO)
 			conflict->owns &= ~VGA_RSRC_NORMAL_IO;
 	}
 
 enable_them:
 	/* ok dude, we got it, everybody conflicting has been disabled, let's
-	 * enable us. Make sure we don't mark a bit in "owns" that we don't
-	 * also have in "decodes". We can lock resources we don't decode but
-	 * not own them.
+	 * enable us.  Mark any bits in "owns" regardless of whether we
+	 * decoded them.  We can lock resources we don't decode, therefore
+	 * we must track them via "owns".
 	 */
 	flags = 0;
 	pci_bits = 0;
@@ -291,7 +293,7 @@ enable_them:
 		if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
 			pci_bits |= PCI_COMMAND_IO;
 	}
-	if (!!(wants & VGA_RSRC_LEGACY_MASK))
+	if (wants & VGA_RSRC_LEGACY_MASK)
 		flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
 
 	pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
@@ -299,7 +301,7 @@ enable_them:
 	if (!vgadev->bridge_has_one_vga) {
 		vga_irq_set_state(vgadev, true);
 	}
-	vgadev->owns |= (wants & vgadev->decodes);
+	vgadev->owns |= wants;
 lock_them:
 	vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
 	if (rsrc & VGA_RSRC_LEGACY_IO)
@@ -578,11 +580,12 @@ static bool vga_arbiter_add_pci_device(s
 	/* Deal with VGA default device. Use first enabled one
 	 * by default if arch doesn't have it's own hook
 	 */
-#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == NULL &&
-	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
+	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
+		pr_info("vgaarb: setting as boot device: PCI:%s\n",
+			pci_name(pdev));
 		vga_set_default_device(pdev);
-#endif
+	}
 
 	vga_arbiter_check_bridge_sharing(vgadev);
 
@@ -616,10 +619,8 @@ static bool vga_arbiter_del_pci_device(s
 		goto bail;
 	}
 
-#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == pdev)
 		vga_set_default_device(NULL);
-#endif
 
 	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
 		vga_decode_count--;
@@ -649,7 +650,6 @@ static inline void vga_update_device_dec
 	old_decodes = vgadev->decodes;
 	decodes_removed = ~new_decodes & old_decodes;
 	decodes_unlocked = vgadev->locks & decodes_removed;
-	vgadev->owns &= ~decodes_removed;
 	vgadev->decodes = new_decodes;
 
 	pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
@@ -1316,6 +1316,38 @@ static int __init vga_arb_device_init(vo
 	pr_info("vgaarb: loaded\n");
 
 	list_for_each_entry(vgadev, &vga_list, list) {
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+		/* Override I/O based detection done by vga_arbiter_add_pci_device()
+		 * as it may take the wrong device (e.g. on Apple system under EFI).
+		 *
+		 * Select the device owning the boot framebuffer if there is one.
+		 */
+		resource_size_t start, end;
+		int i;
+
+		/* Does firmware framebuffer belong to us? */
+		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+			if (!(pci_resource_flags(vgadev->pdev, i) & IORESOURCE_MEM))
+				continue;
+
+			start = pci_resource_start(vgadev->pdev, i);
+			end  = pci_resource_end(vgadev->pdev, i);
+
+			if (!start || !end)
+				continue;
+
+			if (screen_info.lfb_base < start ||
+			    (screen_info.lfb_base + screen_info.lfb_size) >= end)
+				continue;
+			if (!vga_default_device())
+				pr_info("vgaarb: setting as boot device: PCI:%s\n",
+					pci_name(vgadev->pdev));
+			else if (vgadev->pdev != vga_default_device())
+				pr_info("vgaarb: overriding boot device: PCI:%s\n",
+					pci_name(vgadev->pdev));
+			vga_set_default_device(vgadev->pdev);
+		}
+#endif
 		if (vgadev->bridge_has_one_vga)
 			pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev));
 		else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/gpu/vga/vga_switcheroo.c linux-libre-3.17-rc7-gnu/drivers/gpu/vga/vga_switcheroo.c
--- linux-libre-3.16-gnu/drivers/gpu/vga/vga_switcheroo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/gpu/vga/vga_switcheroo.c	2014-09-28 17:29:07.000000000 -0400
@@ -660,6 +660,12 @@ int vga_switcheroo_init_domain_pm_ops(st
 }
 EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops);
 
+void vga_switcheroo_fini_domain_pm_ops(struct device *dev)
+{
+	dev->pm_domain = NULL;
+}
+EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
+
 static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-cherry.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-cherry.c
--- linux-libre-3.16-gnu/drivers/hid/hid-cherry.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-cherry.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+	if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
 		hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
 		rdesc[11] = rdesc[16] = 0xff;
 		rdesc[12] = rdesc[17] = 0x03;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-core.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-core.c
--- linux-libre-3.16-gnu/drivers/hid/hid-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -783,10 +783,21 @@ static int hid_scan_report(struct hid_de
 	* Vendor specific handlings
 	*/
 	if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) &&
-	    (hid->group == HID_GROUP_GENERIC))
+	    (hid->group == HID_GROUP_GENERIC) &&
+	    /* only bind to the mouse interface of composite USB devices */
+	    (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
 		/* hid-rmi should take care of them, not hid-generic */
 		hid->group = HID_GROUP_RMI;
 
+	/*
+	 * Vendor specific handlings
+	 */
+	switch (hid->vendor) {
+	case USB_VENDOR_ID_WACOM:
+		hid->group = HID_GROUP_WACOM;
+		break;
+	}
+
 	vfree(parser);
 	return 0;
 }
@@ -1782,7 +1793,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
@@ -1796,8 +1807,10 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+#if IS_ENABLED(CONFIG_HID_LENOVO)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
 #endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
@@ -1845,6 +1858,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
@@ -1933,8 +1947,6 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
@@ -2266,6 +2278,7 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
@@ -2339,7 +2352,6 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-cp2112.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-cp2112.c
--- linux-libre-3.16-gnu/drivers/hid/hid-cp2112.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-cp2112.c	2014-09-28 17:29:07.000000000 -0400
@@ -240,8 +240,6 @@ static int cp2112_gpio_direction_output(
 	u8 buf[5];
 	int ret;
 
-	cp2112_gpio_set(chip, offset, value);
-
 	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
 				       sizeof(buf), HID_FEATURE_REPORT,
 				       HID_REQ_GET_REPORT);
@@ -260,6 +258,12 @@ static int cp2112_gpio_direction_output(
 		return ret;
 	}
 
+	/*
+	 * Set gpio value when output direction is already set,
+	 * as specified in AN495, Rev. 0.2, cpt. 4.4
+	 */
+	cp2112_gpio_set(chip, offset, value);
+
 	return 0;
 }
 
@@ -425,6 +429,105 @@ static int cp2112_write_req(void *buf, u
 	return data_length + 4;
 }
 
+static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
+				u8 data_length)
+{
+	struct cp2112_write_req_report *report = buf;
+
+	if (data_length > sizeof(report->data))
+		return -EINVAL;
+
+	report->report = CP2112_DATA_WRITE_REQUEST;
+	report->slave_address = slave_address << 1;
+	report->length = data_length;
+	memcpy(report->data, data, data_length);
+	return data_length + 3;
+}
+
+static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			   int num)
+{
+	struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
+	struct hid_device *hdev = dev->hdev;
+	u8 buf[64];
+	ssize_t count;
+	unsigned int retries;
+	int ret;
+
+	hid_dbg(hdev, "I2C %d messages\n", num);
+
+	if (num != 1) {
+		hid_err(hdev,
+			"Multi-message I2C transactions not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (msgs->flags & I2C_M_RD)
+		count = cp2112_read_req(buf, msgs->addr, msgs->len);
+	else
+		count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf,
+					     msgs->len);
+
+	if (count < 0)
+		return count;
+
+	ret = hid_hw_power(hdev, PM_HINT_FULLON);
+	if (ret < 0) {
+		hid_err(hdev, "power management error: %d\n", ret);
+		return ret;
+	}
+
+	ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
+	if (ret < 0) {
+		hid_warn(hdev, "Error starting transaction: %d\n", ret);
+		goto power_normal;
+	}
+
+	for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
+		ret = cp2112_xfer_status(dev);
+		if (-EBUSY == ret)
+			continue;
+		if (ret < 0)
+			goto power_normal;
+		break;
+	}
+
+	if (XFER_STATUS_RETRIES <= retries) {
+		hid_warn(hdev, "Transfer timed out, cancelling.\n");
+		buf[0] = CP2112_CANCEL_TRANSFER;
+		buf[1] = 0x01;
+
+		ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
+		if (ret < 0)
+			hid_warn(hdev, "Error cancelling transaction: %d\n",
+				 ret);
+
+		ret = -ETIMEDOUT;
+		goto power_normal;
+	}
+
+	if (!(msgs->flags & I2C_M_RD))
+		goto finish;
+
+	ret = cp2112_read(dev, msgs->buf, msgs->len);
+	if (ret < 0)
+		goto power_normal;
+	if (ret != msgs->len) {
+		hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len);
+		ret = -EIO;
+		goto power_normal;
+	}
+
+finish:
+	/* return the number of transferred messages */
+	ret = 1;
+
+power_normal:
+	hid_hw_power(hdev, PM_HINT_NORMAL);
+	hid_dbg(hdev, "I2C transfer finished: %d\n", ret);
+	return ret;
+}
+
 static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
 		       unsigned short flags, char read_write, u8 command,
 		       int size, union i2c_smbus_data *data)
@@ -591,7 +694,8 @@ power_normal:
 
 static u32 cp2112_functionality(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_SMBUS_BYTE |
+	return I2C_FUNC_I2C |
+		I2C_FUNC_SMBUS_BYTE |
 		I2C_FUNC_SMBUS_BYTE_DATA |
 		I2C_FUNC_SMBUS_WORD_DATA |
 		I2C_FUNC_SMBUS_BLOCK_DATA |
@@ -601,6 +705,7 @@ static u32 cp2112_functionality(struct i
 }
 
 static const struct i2c_algorithm smbus_algorithm = {
+	.master_xfer	= cp2112_i2c_xfer,
 	.smbus_xfer	= cp2112_xfer,
 	.functionality	= cp2112_functionality,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-gt683r.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-gt683r.c
--- linux-libre-3.16-gnu/drivers/hid/hid-gt683r.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-gt683r.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,321 @@
+/*
+ * MSI GT683R led driver
+ *
+ * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@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/device.h>
+#include <linux/hid.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define GT683R_BUFFER_SIZE			8
+
+/*
+ * GT683R_LED_OFF: all LEDs are off
+ * GT683R_LED_AUDIO: LEDs brightness depends on sound level
+ * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
+ * GT683R_LED_NORMAL: LEDs are fully on when enabled
+ */
+enum gt683r_led_mode {
+	GT683R_LED_OFF = 0,
+	GT683R_LED_AUDIO = 2,
+	GT683R_LED_BREATHING = 3,
+	GT683R_LED_NORMAL = 5
+};
+
+enum gt683r_panels {
+	GT683R_LED_BACK = 0,
+	GT683R_LED_SIDE = 1,
+	GT683R_LED_FRONT = 2,
+	GT683R_LED_COUNT,
+};
+
+static const char * const gt683r_panel_names[] = {
+	"back",
+	"side",
+	"front",
+};
+
+struct gt683r_led {
+	struct hid_device *hdev;
+	struct led_classdev led_devs[GT683R_LED_COUNT];
+	struct mutex lock;
+	struct work_struct work;
+	enum led_brightness brightnesses[GT683R_LED_COUNT];
+	enum gt683r_led_mode mode;
+};
+
+static const struct hid_device_id gt683r_led_id[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+	{ }
+};
+
+static void gt683r_brightness_set(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
+{
+	int i;
+	struct device *dev = led_cdev->dev->parent;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct gt683r_led *led = hid_get_drvdata(hdev);
+
+	for (i = 0; i < GT683R_LED_COUNT; i++) {
+		if (led_cdev == &led->led_devs[i])
+			break;
+	}
+
+	if (i < GT683R_LED_COUNT) {
+		led->brightnesses[i] = brightness;
+		schedule_work(&led->work);
+	}
+}
+
+static ssize_t mode_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	u8 sysfs_mode;
+	struct hid_device *hdev = container_of(dev->parent,
+					struct hid_device, dev);
+	struct gt683r_led *led = hid_get_drvdata(hdev);
+
+	if (led->mode == GT683R_LED_NORMAL)
+		sysfs_mode = 0;
+	else if (led->mode == GT683R_LED_AUDIO)
+		sysfs_mode = 1;
+	else
+		sysfs_mode = 2;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
+}
+
+static ssize_t mode_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	u8 sysfs_mode;
+	struct hid_device *hdev = container_of(dev->parent,
+					struct hid_device, dev);
+	struct gt683r_led *led = hid_get_drvdata(hdev);
+
+
+	if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
+		return -EINVAL;
+
+	mutex_lock(&led->lock);
+
+	if (sysfs_mode == 0)
+		led->mode = GT683R_LED_NORMAL;
+	else if (sysfs_mode == 1)
+		led->mode = GT683R_LED_AUDIO;
+	else
+		led->mode = GT683R_LED_BREATHING;
+
+	mutex_unlock(&led->lock);
+	schedule_work(&led->work);
+
+	return count;
+}
+
+static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
+{
+	int ret;
+
+	ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
+				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+	if (ret != GT683R_BUFFER_SIZE) {
+		hid_err(led->hdev,
+			"failed to send set report request: %i\n", ret);
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
+{
+	int ret;
+	u8 *buffer;
+
+	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buffer[0] = 0x01;
+	buffer[1] = 0x02;
+	buffer[2] = 0x30;
+	buffer[3] = leds;
+	ret = gt683r_led_snd_msg(led, buffer);
+
+	kfree(buffer);
+	return ret;
+}
+
+static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
+{
+	int ret;
+	u8 *buffer;
+
+	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buffer[0] = 0x01;
+	buffer[1] = 0x02;
+	buffer[2] = 0x20;
+	buffer[3] = mode;
+	buffer[4] = 0x01;
+	ret = gt683r_led_snd_msg(led, buffer);
+
+	kfree(buffer);
+	return ret;
+}
+
+static void gt683r_led_work(struct work_struct *work)
+{
+	int i;
+	u8 leds = 0;
+	u8 mode;
+	struct gt683r_led *led = container_of(work, struct gt683r_led, work);
+
+	mutex_lock(&led->lock);
+
+	for (i = 0; i < GT683R_LED_COUNT; i++) {
+		if (led->brightnesses[i])
+			leds |= BIT(i);
+	}
+
+	if (gt683r_leds_set(led, leds))
+		goto fail;
+
+	if (leds)
+		mode = led->mode;
+	else
+		mode = GT683R_LED_OFF;
+
+	gt683r_mode_set(led, mode);
+fail:
+	mutex_unlock(&led->lock);
+}
+
+static DEVICE_ATTR_RW(mode);
+
+static struct attribute *gt683r_led_attrs[] = {
+	&dev_attr_mode.attr,
+	NULL
+};
+
+static const struct attribute_group gt683r_led_group = {
+	.name = "gt683r",
+	.attrs = gt683r_led_attrs,
+};
+
+static const struct attribute_group *gt683r_led_groups[] = {
+	&gt683r_led_group,
+	NULL
+};
+
+static int gt683r_led_probe(struct hid_device *hdev,
+			const struct hid_device_id *id)
+{
+	int i;
+	int ret;
+	int name_sz;
+	char *name;
+	struct gt683r_led *led;
+
+	led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	mutex_init(&led->lock);
+	INIT_WORK(&led->work, gt683r_led_work);
+
+	led->mode = GT683R_LED_NORMAL;
+	led->hdev = hdev;
+	hid_set_drvdata(hdev, led);
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "hid parsing failed\n");
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	for (i = 0; i < GT683R_LED_COUNT; i++) {
+		name_sz = strlen(dev_name(&hdev->dev)) +
+				strlen(gt683r_panel_names[i]) + 3;
+
+		name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+		if (!name) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		snprintf(name, name_sz, "%s::%s",
+				dev_name(&hdev->dev), gt683r_panel_names[i]);
+		led->led_devs[i].name = name;
+		led->led_devs[i].max_brightness = 1;
+		led->led_devs[i].brightness_set = gt683r_brightness_set;
+		led->led_devs[i].groups = gt683r_led_groups;
+
+		ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
+		if (ret) {
+			hid_err(hdev, "could not register led device\n");
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	for (i = i - 1; i >= 0; i--)
+		led_classdev_unregister(&led->led_devs[i]);
+	hid_hw_stop(hdev);
+	return ret;
+}
+
+static void gt683r_led_remove(struct hid_device *hdev)
+{
+	int i;
+	struct gt683r_led *led = hid_get_drvdata(hdev);
+
+	for (i = 0; i < GT683R_LED_COUNT; i++)
+		led_classdev_unregister(&led->led_devs[i]);
+	flush_work(&led->work);
+	hid_hw_stop(hdev);
+}
+
+static struct hid_driver gt683r_led_driver = {
+	.probe = gt683r_led_probe,
+	.remove = gt683r_led_remove,
+	.name = "gt683r_led",
+	.id_table = gt683r_led_id,
+};
+
+module_hid_driver(gt683r_led_driver);
+
+MODULE_AUTHOR("Janne Kanniainen");
+MODULE_DESCRIPTION("MSI GT683R led driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-huion.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-huion.c
--- linux-libre-3.16-gnu/drivers/hid/hid-huion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-huion.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,7 @@
  *  HID driver for Huion devices not fully compliant with HID standard
  *
  *  Copyright (c) 2013 Martin Rusko
+ *  Copyright (c) 2014 Nikolai Kondrashov
  */
 
 /*
@@ -15,67 +16,98 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <asm/unaligned.h>
 #include "usbhid/usbhid.h"
 
 #include "hid-ids.h"
 
-/* Original Huion 580 report descriptor size */
-#define HUION_580_RDESC_ORIG_SIZE	177
+/* Report descriptor template placeholder head */
+#define HUION_PH_HEAD	0xFE, 0xED, 0x1D
 
-/* Fixed Huion 580 report descriptor */
-static __u8 huion_580_rdesc_fixed[] = {
-	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
-	0x09, 0x02,         /*  Usage (Pen),                        */
-	0xA1, 0x01,         /*  Collection (Application),           */
-	0x85, 0x07,         /*      Report ID (7),                  */
-	0x09, 0x20,         /*      Usage (Stylus),                 */
-	0xA0,               /*      Collection (Physical),          */
-	0x14,               /*          Logical Minimum (0),        */
-	0x25, 0x01,         /*          Logical Maximum (1),        */
-	0x75, 0x01,         /*          Report Size (1),            */
-	0x09, 0x42,         /*          Usage (Tip Switch),         */
-	0x09, 0x44,         /*          Usage (Barrel Switch),      */
-	0x09, 0x46,         /*          Usage (Tablet Pick),        */
-	0x95, 0x03,         /*          Report Count (3),           */
-	0x81, 0x02,         /*          Input (Variable),           */
-	0x95, 0x03,         /*          Report Count (3),           */
-	0x81, 0x03,         /*          Input (Constant, Variable), */
-	0x09, 0x32,         /*          Usage (In Range),           */
-	0x95, 0x01,         /*          Report Count (1),           */
-	0x81, 0x02,         /*          Input (Variable),           */
-	0x95, 0x01,         /*          Report Count (1),           */
-	0x81, 0x03,         /*          Input (Constant, Variable), */
-	0x75, 0x10,         /*          Report Size (16),           */
-	0x95, 0x01,         /*          Report Count (1),           */
-	0xA4,               /*          Push,                       */
-	0x05, 0x01,         /*          Usage Page (Desktop),       */
-	0x65, 0x13,         /*          Unit (Inch),                */
-	0x55, 0xFD,         /*          Unit Exponent (-3),         */
-	0x34,               /*          Physical Minimum (0),       */
-	0x09, 0x30,         /*          Usage (X),                  */
-	0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
-	0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
-	0x81, 0x02,         /*          Input (Variable),           */
-	0x09, 0x31,         /*          Usage (Y),                  */
-	0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
-	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
-	0x81, 0x02,         /*          Input (Variable),           */
-	0xB4,               /*          Pop,                        */
-	0x09, 0x30,         /*          Usage (Tip Pressure),       */
-	0x26, 0xFF, 0x07,   /*          Logical Maximum (2047),     */
-	0x81, 0x02,         /*          Input (Variable),           */
-	0xC0,               /*      End Collection,                 */
-	0xC0                /*  End Collection                      */
+/* Report descriptor template placeholder IDs */
+enum huion_ph_id {
+	HUION_PH_ID_X_LM,
+	HUION_PH_ID_X_PM,
+	HUION_PH_ID_Y_LM,
+	HUION_PH_ID_Y_PM,
+	HUION_PH_ID_PRESSURE_LM,
+	HUION_PH_ID_NUM
+};
+
+/* Report descriptor template placeholder */
+#define HUION_PH(_ID) HUION_PH_HEAD, HUION_PH_ID_##_ID
+
+/* Fixed report descriptor template */
+static const __u8 huion_tablet_rdesc_template[] = {
+	0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
+	0x09, 0x02,             /*  Usage (Pen),                            */
+	0xA1, 0x01,             /*  Collection (Application),               */
+	0x85, 0x07,             /*      Report ID (7),                      */
+	0x09, 0x20,             /*      Usage (Stylus),                     */
+	0xA0,                   /*      Collection (Physical),              */
+	0x14,                   /*          Logical Minimum (0),            */
+	0x25, 0x01,             /*          Logical Maximum (1),            */
+	0x75, 0x01,             /*          Report Size (1),                */
+	0x09, 0x42,             /*          Usage (Tip Switch),             */
+	0x09, 0x44,             /*          Usage (Barrel Switch),          */
+	0x09, 0x46,             /*          Usage (Tablet Pick),            */
+	0x95, 0x03,             /*          Report Count (3),               */
+	0x81, 0x02,             /*          Input (Variable),               */
+	0x95, 0x03,             /*          Report Count (3),               */
+	0x81, 0x03,             /*          Input (Constant, Variable),     */
+	0x09, 0x32,             /*          Usage (In Range),               */
+	0x95, 0x01,             /*          Report Count (1),               */
+	0x81, 0x02,             /*          Input (Variable),               */
+	0x95, 0x01,             /*          Report Count (1),               */
+	0x81, 0x03,             /*          Input (Constant, Variable),     */
+	0x75, 0x10,             /*          Report Size (16),               */
+	0x95, 0x01,             /*          Report Count (1),               */
+	0xA4,                   /*          Push,                           */
+	0x05, 0x01,             /*          Usage Page (Desktop),           */
+	0x65, 0x13,             /*          Unit (Inch),                    */
+	0x55, 0xFD,             /*          Unit Exponent (-3),             */
+	0x34,                   /*          Physical Minimum (0),           */
+	0x09, 0x30,             /*          Usage (X),                      */
+	0x27, HUION_PH(X_LM),   /*          Logical Maximum (PLACEHOLDER),  */
+	0x47, HUION_PH(X_PM),   /*          Physical Maximum (PLACEHOLDER), */
+	0x81, 0x02,             /*          Input (Variable),               */
+	0x09, 0x31,             /*          Usage (Y),                      */
+	0x27, HUION_PH(Y_LM),   /*          Logical Maximum (PLACEHOLDER),  */
+	0x47, HUION_PH(Y_PM),   /*          Physical Maximum (PLACEHOLDER), */
+	0x81, 0x02,             /*          Input (Variable),               */
+	0xB4,                   /*          Pop,                            */
+	0x09, 0x30,             /*          Usage (Tip Pressure),           */
+	0x27,
+	HUION_PH(PRESSURE_LM),  /*          Logical Maximum (PLACEHOLDER),  */
+	0x81, 0x02,             /*          Input (Variable),               */
+	0xC0,                   /*      End Collection,                     */
+	0xC0                    /*  End Collection                          */
+};
+
+/* Parameter indices */
+enum huion_prm {
+	HUION_PRM_X_LM		= 1,
+	HUION_PRM_Y_LM		= 2,
+	HUION_PRM_PRESSURE_LM	= 4,
+	HUION_PRM_RESOLUTION	= 5,
+	HUION_PRM_NUM
+};
+
+/* Driver data */
+struct huion_drvdata {
+	__u8 *rdesc;
+	unsigned int rsize;
 };
 
 static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
+	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
 	switch (hdev->product) {
-	case USB_DEVICE_ID_HUION_580:
-		if (*rsize == HUION_580_RDESC_ORIG_SIZE) {
-			rdesc = huion_580_rdesc_fixed;
-			*rsize = sizeof(huion_580_rdesc_fixed);
+	case USB_DEVICE_ID_HUION_TABLET:
+		if (drvdata->rdesc != NULL) {
+			rdesc = drvdata->rdesc;
+			*rsize = drvdata->rsize;
 		}
 		break;
 	}
@@ -83,82 +115,163 @@ static __u8 *huion_report_fixup(struct h
 }
 
 /**
- * Enable fully-functional tablet mode by reading special string
- * descriptor.
+ * Enable fully-functional tablet mode and determine device parameters.
  *
  * @hdev:	HID device
- *
- * The specific string descriptor and data were discovered by sniffing
- * the Windows driver traffic.
  */
 static int huion_tablet_enable(struct hid_device *hdev)
 {
 	int rc;
-	char buf[22];
+	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
+	__le16 *buf = NULL;
+	size_t len;
+	s32 params[HUION_PH_ID_NUM];
+	s32 resolution;
+	__u8 *p;
+	s32 v;
 
-	rc = usb_string(hid_to_usb_dev(hdev), 0x64, buf, sizeof(buf));
-	if (rc < 0)
-		return rc;
+	/*
+	 * Read string descriptor containing tablet parameters. The specific
+	 * string descriptor and data were discovered by sniffing the Windows
+	 * driver traffic.
+	 * NOTE: This enables fully-functional tablet mode.
+	 */
+	len = HUION_PRM_NUM * sizeof(*buf);
+	buf = kmalloc(len, GFP_KERNEL);
+	if (buf == NULL) {
+		hid_err(hdev, "failed to allocate parameter buffer\n");
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+				(USB_DT_STRING << 8) + 0x64,
+				0x0409, buf, len,
+				USB_CTRL_GET_TIMEOUT);
+	if (rc == -EPIPE) {
+		hid_err(hdev, "device parameters not found\n");
+		rc = -ENODEV;
+		goto cleanup;
+	} else if (rc < 0) {
+		hid_err(hdev, "failed to get device parameters: %d\n", rc);
+		rc = -ENODEV;
+		goto cleanup;
+	} else if (rc != len) {
+		hid_err(hdev, "invalid device parameters\n");
+		rc = -ENODEV;
+		goto cleanup;
+	}
 
-	return 0;
+	/* Extract device parameters */
+	params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
+	params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
+	params[HUION_PH_ID_PRESSURE_LM] =
+		le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
+	resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
+	if (resolution == 0) {
+		params[HUION_PH_ID_X_PM] = 0;
+		params[HUION_PH_ID_Y_PM] = 0;
+	} else {
+		params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
+						1000 / resolution;
+		params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
+						1000 / resolution;
+	}
+
+	/* Allocate fixed report descriptor */
+	drvdata->rdesc = devm_kmalloc(&hdev->dev,
+				sizeof(huion_tablet_rdesc_template),
+				GFP_KERNEL);
+	if (drvdata->rdesc == NULL) {
+		hid_err(hdev, "failed to allocate fixed rdesc\n");
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+	drvdata->rsize = sizeof(huion_tablet_rdesc_template);
+
+	/* Format fixed report descriptor */
+	memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
+		drvdata->rsize);
+	for (p = drvdata->rdesc;
+	     p <= drvdata->rdesc + drvdata->rsize - 4;) {
+		if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
+		    p[3] < sizeof(params)) {
+			v = params[p[3]];
+			put_unaligned(cpu_to_le32(v), (s32 *)p);
+			p += 4;
+		} else {
+			p++;
+		}
+	}
+
+	rc = 0;
+
+cleanup:
+	kfree(buf);
+	return rc;
 }
 
 static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	int ret;
+	int rc;
 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct huion_drvdata *drvdata;
+
+	/* Allocate and assign driver data */
+	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (drvdata == NULL) {
+		hid_err(hdev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, drvdata);
 
-	/* Ignore interfaces 1 (mouse) and 2 (keyboard) for Huion 580 tablet,
-	 * as they are not used
-	 */
 	switch (id->product) {
-	case USB_DEVICE_ID_HUION_580:
-		if (intf->cur_altsetting->desc.bInterfaceNumber != 0x00)
-			return -ENODEV;
+	case USB_DEVICE_ID_HUION_TABLET:
+		/* If this is the pen interface */
+		if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+			rc = huion_tablet_enable(hdev);
+			if (rc) {
+				hid_err(hdev, "tablet enabling failed\n");
+				return rc;
+			}
+		}
 		break;
 	}
 
-	ret = hid_parse(hdev);
-	if (ret) {
+	rc = hid_parse(hdev);
+	if (rc) {
 		hid_err(hdev, "parse failed\n");
-		goto err;
+		return rc;
 	}
 
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
+	rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (rc) {
 		hid_err(hdev, "hw start failed\n");
-		goto err;
-	}
-
-	switch (id->product) {
-	case USB_DEVICE_ID_HUION_580:
-		ret = huion_tablet_enable(hdev);
-		if (ret) {
-			hid_err(hdev, "tablet enabling failed\n");
-			goto enabling_err;
-		}
-		break;
+		return rc;
 	}
 
 	return 0;
-enabling_err:
-	hid_hw_stop(hdev);
-err:
-	return ret;
 }
 
 static int huion_raw_event(struct hid_device *hdev, struct hid_report *report,
 			u8 *data, int size)
 {
-	/* If this is a pen input report then invert the in-range bit */
-	if (report->type == HID_INPUT_REPORT && report->id == 0x07 && size >= 2)
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+	/* If this is a pen input report */
+	if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
+	    report->type == HID_INPUT_REPORT &&
+	    report->id == 0x07 && size >= 2)
+		/* Invert the in-range bit */
 		data[1] ^= 0x40;
 
 	return 0;
 }
 
 static const struct hid_device_id huion_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, huion_devices);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-hyperv.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-hyperv.c
--- linux-libre-3.16-gnu/drivers/hid/hid-hyperv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-hyperv.c	2014-09-28 17:29:07.000000000 -0400
@@ -308,6 +308,9 @@ static void mousevsc_on_receive(struct h
 		memcpy(input_dev->input_buf, input_report->buffer, len);
 		hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
 				 input_dev->input_buf, len, 1);
+
+		pm_wakeup_event(&input_dev->device->device, 0);
+
 		break;
 	default:
 		pr_err("unsupported hid msg type - type %d len %d",
@@ -549,6 +552,8 @@ static int mousevsc_probe(struct hv_devi
 		goto probe_err2;
 	}
 
+	device_init_wakeup(&device->device, true);
+
 	input_dev->connected = true;
 	input_dev->init_complete = true;
 
@@ -571,6 +576,7 @@ static int mousevsc_remove(struct hv_dev
 {
 	struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
 
+	device_init_wakeup(&dev->device, false);
 	vmbus_close(dev->channel);
 	hid_hw_stop(input_dev->hid_device);
 	hid_destroy_device(input_dev->hid_device);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-ids.h linux-libre-3.17-rc7-gnu/drivers/hid/hid-ids.h
--- linux-libre-3.16-gnu/drivers/hid/hid-ids.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-ids.h	2014-09-28 17:29:07.000000000 -0400
@@ -448,7 +448,7 @@
 #define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
 
 #define USB_VENDOR_ID_HUION		0x256c
-#define USB_DEVICE_ID_HUION_580		0x006e
+#define USB_DEVICE_ID_HUION_TABLET	0x006e
 
 #define USB_VENDOR_ID_IDEACOM		0x1cb6
 #define USB_DEVICE_ID_IDEACOM_IDC6650	0x6650
@@ -479,6 +479,7 @@
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070	0xa070
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072	0xa072
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
+#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096	0xa096
 
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
@@ -489,6 +490,7 @@
 #define USB_VENDOR_ID_JABRA		0x0b0e
 #define USB_DEVICE_ID_JABRA_SPEAK_410	0x0412
 #define USB_DEVICE_ID_JABRA_SPEAK_510	0x0420
+#define USB_DEVICE_ID_JABRA_GN9350E	0x9350
 
 #define USB_VENDOR_ID_JESS		0x0c45
 #define USB_DEVICE_ID_JESS_YUREX	0x1010
@@ -561,6 +563,8 @@
 
 #define USB_VENDOR_ID_LENOVO		0x17ef
 #define USB_DEVICE_ID_LENOVO_TPKBD	0x6009
+#define USB_DEVICE_ID_LENOVO_CUSBKBD	0x6047
+#define USB_DEVICE_ID_LENOVO_CBTKBD	0x6048
 
 #define USB_VENDOR_ID_LG		0x1fd2
 #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
@@ -646,7 +650,7 @@
 #define USB_DEVICE_ID_GENIUS_KB29E	0x3004
 
 #define USB_VENDOR_ID_MSI		0x1770
-#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL	0xff00
+#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
 
 #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
 #define USB_DEVICE_ID_N_S_HARMONY	0xc359
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-kye.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-kye.c
--- linux-libre-3.16-gnu/drivers/hid/hid-kye.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-kye.c	2014-09-28 17:29:07.000000000 -0400
@@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid
 		 *   - change the button usage range to 4-7 for the extra
 		 *     buttons
 		 */
-		if (*rsize >= 74 &&
+		if (*rsize >= 75 &&
 			rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
 			rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
 			rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-lenovo.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-lenovo.c
--- linux-libre-3.16-gnu/drivers/hid/hid-lenovo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-lenovo.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,708 @@
+/*
+ *  HID driver for Lenovo:
+ *  - ThinkPad USB Keyboard with TrackPoint (tpkbd)
+ *  - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
+ *  - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
+ *
+ *  Copyright (c) 2012 Bernhard Seibold
+ *  Copyright (c) 2014 Jamie Lentin <jm@lentin.co.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.
+ */
+
+#include <linux/module.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+
+#include "hid-ids.h"
+
+struct lenovo_drvdata_tpkbd {
+	int led_state;
+	struct led_classdev led_mute;
+	struct led_classdev led_micmute;
+	int press_to_select;
+	int dragging;
+	int release_to_select;
+	int select_right;
+	int sensitivity;
+	int press_speed;
+};
+
+struct lenovo_drvdata_cptkbd {
+	bool fn_lock;
+};
+
+#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
+
+static int lenovo_input_mapping_tpkbd(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_UP_BUTTON | 0x0010)) {
+		/* This sub-device contains trackpoint, mark it */
+		hid_set_drvdata(hdev, (void *)1);
+		map_key_clear(KEY_MICMUTE);
+		return 1;
+	}
+	return 0;
+}
+
+static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	/* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
+	    (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
+		set_bit(EV_REP, hi->input->evbit);
+		switch (usage->hid & HID_USAGE) {
+		case 0x00f1: /* Fn-F4: Mic mute */
+			map_key_clear(KEY_MICMUTE);
+			return 1;
+		case 0x00f2: /* Fn-F5: Brightness down */
+			map_key_clear(KEY_BRIGHTNESSDOWN);
+			return 1;
+		case 0x00f3: /* Fn-F6: Brightness up */
+			map_key_clear(KEY_BRIGHTNESSUP);
+			return 1;
+		case 0x00f4: /* Fn-F7: External display (projector) */
+			map_key_clear(KEY_SWITCHVIDEOMODE);
+			return 1;
+		case 0x00f5: /* Fn-F8: Wireless */
+			map_key_clear(KEY_WLAN);
+			return 1;
+		case 0x00f6: /* Fn-F9: Control panel */
+			map_key_clear(KEY_CONFIG);
+			return 1;
+		case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
+			map_key_clear(KEY_SCALE);
+			return 1;
+		case 0x00fa: /* Fn-Esc: Fn-lock toggle */
+			map_key_clear(KEY_FN_ESC);
+			return 1;
+		case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */
+			/* NB: This mapping is invented in raw_event below */
+			map_key_clear(KEY_FILE);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int lenovo_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
+		return lenovo_input_mapping_tpkbd(hdev, hi, field,
+							usage, bit, max);
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		return lenovo_input_mapping_cptkbd(hdev, hi, field,
+							usage, bit, max);
+	default:
+		return 0;
+	}
+}
+
+#undef map_key_clear
+
+/* Send a config command to the keyboard */
+static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
+			unsigned char byte2, unsigned char byte3)
+{
+	int ret;
+	unsigned char buf[] = {0x18, byte2, byte3};
+
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+		ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf),
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+		break;
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		ret = hid_hw_output_report(hdev, buf, sizeof(buf));
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
+}
+
+static void lenovo_features_set_cptkbd(struct hid_device *hdev)
+{
+	int ret;
+	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+
+	ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
+	if (ret)
+		hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
+}
+
+static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
+}
+
+static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	cptkbd_data->fn_lock = !!value;
+	lenovo_features_set_cptkbd(hdev);
+
+	return count;
+}
+
+static struct device_attribute dev_attr_fn_lock_cptkbd =
+	__ATTR(fn_lock, S_IWUSR | S_IRUGO,
+			attr_fn_lock_show_cptkbd,
+			attr_fn_lock_store_cptkbd);
+
+static struct attribute *lenovo_attributes_cptkbd[] = {
+	&dev_attr_fn_lock_cptkbd.attr,
+	NULL
+};
+
+static const struct attribute_group lenovo_attr_group_cptkbd = {
+	.attrs = lenovo_attributes_cptkbd,
+};
+
+static int lenovo_raw_event(struct hid_device *hdev,
+			struct hid_report *report, u8 *data, int size)
+{
+	/*
+	 * Compact USB keyboard's Fn-F12 report holds down many other keys, and
+	 * its own key is outside the usage page range. Remove extra
+	 * keypresses and remap to inside usage page.
+	 */
+	if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+			&& size == 3
+			&& data[0] == 0x15
+			&& data[1] == 0x94
+			&& data[2] == 0x01)) {
+		data[1] = 0x0;
+		data[2] = 0x4;
+	}
+
+	return 0;
+}
+
+static int lenovo_features_set_tpkbd(struct hid_device *hdev)
+{
+	struct hid_report *report;
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
+
+	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
+	report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
+	report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
+	report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
+	report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
+	report->field[2]->value[0] = data_pointer->sensitivity;
+	report->field[3]->value[0] = data_pointer->press_speed;
+
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+	return 0;
+}
+
+static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
+}
+
+static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	data_pointer->press_to_select = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static ssize_t attr_dragging_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
+}
+
+static ssize_t attr_dragging_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	data_pointer->dragging = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
+}
+
+static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	data_pointer->release_to_select = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static ssize_t attr_select_right_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
+}
+
+static ssize_t attr_select_right_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	data_pointer->select_right = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		data_pointer->sensitivity);
+}
+
+static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+		return -EINVAL;
+
+	data_pointer->sensitivity = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		data_pointer->press_speed);
+}
+
+static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+		return -EINVAL;
+
+	data_pointer->press_speed = value;
+	lenovo_features_set_tpkbd(hdev);
+
+	return count;
+}
+
+static struct device_attribute dev_attr_press_to_select_tpkbd =
+	__ATTR(press_to_select, S_IWUSR | S_IRUGO,
+			attr_press_to_select_show_tpkbd,
+			attr_press_to_select_store_tpkbd);
+
+static struct device_attribute dev_attr_dragging_tpkbd =
+	__ATTR(dragging, S_IWUSR | S_IRUGO,
+			attr_dragging_show_tpkbd,
+			attr_dragging_store_tpkbd);
+
+static struct device_attribute dev_attr_release_to_select_tpkbd =
+	__ATTR(release_to_select, S_IWUSR | S_IRUGO,
+			attr_release_to_select_show_tpkbd,
+			attr_release_to_select_store_tpkbd);
+
+static struct device_attribute dev_attr_select_right_tpkbd =
+	__ATTR(select_right, S_IWUSR | S_IRUGO,
+			attr_select_right_show_tpkbd,
+			attr_select_right_store_tpkbd);
+
+static struct device_attribute dev_attr_sensitivity_tpkbd =
+	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
+			attr_sensitivity_show_tpkbd,
+			attr_sensitivity_store_tpkbd);
+
+static struct device_attribute dev_attr_press_speed_tpkbd =
+	__ATTR(press_speed, S_IWUSR | S_IRUGO,
+			attr_press_speed_show_tpkbd,
+			attr_press_speed_store_tpkbd);
+
+static struct attribute *lenovo_attributes_tpkbd[] = {
+	&dev_attr_press_to_select_tpkbd.attr,
+	&dev_attr_dragging_tpkbd.attr,
+	&dev_attr_release_to_select_tpkbd.attr,
+	&dev_attr_select_right_tpkbd.attr,
+	&dev_attr_sensitivity_tpkbd.attr,
+	&dev_attr_press_speed_tpkbd.attr,
+	NULL
+};
+
+static const struct attribute_group lenovo_attr_group_tpkbd = {
+	.attrs = lenovo_attributes_tpkbd,
+};
+
+static enum led_brightness lenovo_led_brightness_get_tpkbd(
+			struct led_classdev *led_cdev)
+{
+	struct device *dev = led_cdev->dev->parent;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	int led_nr = 0;
+
+	if (led_cdev == &data_pointer->led_micmute)
+		led_nr = 1;
+
+	return data_pointer->led_state & (1 << led_nr)
+				? LED_FULL
+				: LED_OFF;
+}
+
+static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
+			enum led_brightness value)
+{
+	struct device *dev = led_cdev->dev->parent;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+	struct hid_report *report;
+	int led_nr = 0;
+
+	if (led_cdev == &data_pointer->led_micmute)
+		led_nr = 1;
+
+	if (value == LED_OFF)
+		data_pointer->led_state &= ~(1 << led_nr);
+	else
+		data_pointer->led_state |= 1 << led_nr;
+
+	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
+	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
+	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+}
+
+static int lenovo_probe_tpkbd(struct hid_device *hdev)
+{
+	struct device *dev = &hdev->dev;
+	struct lenovo_drvdata_tpkbd *data_pointer;
+	size_t name_sz = strlen(dev_name(dev)) + 16;
+	char *name_mute, *name_micmute;
+	int i;
+	int ret;
+
+	/*
+	 * Only register extra settings against subdevice where input_mapping
+	 * set drvdata to 1, i.e. the trackpoint.
+	 */
+	if (!hid_get_drvdata(hdev))
+		return 0;
+
+	hid_set_drvdata(hdev, NULL);
+
+	/* Validate required reports. */
+	for (i = 0; i < 4; i++) {
+		if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
+			return -ENODEV;
+	}
+	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
+		return -ENODEV;
+
+	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
+	if (ret)
+		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
+
+	data_pointer = devm_kzalloc(&hdev->dev,
+				    sizeof(struct lenovo_drvdata_tpkbd),
+				    GFP_KERNEL);
+	if (data_pointer == NULL) {
+		hid_err(hdev, "Could not allocate memory for driver data\n");
+		return -ENOMEM;
+	}
+
+	// set same default values as windows driver
+	data_pointer->sensitivity = 0xa0;
+	data_pointer->press_speed = 0x38;
+
+	name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+	name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+	if (name_mute == NULL || name_micmute == NULL) {
+		hid_err(hdev, "Could not allocate memory for led data\n");
+		return -ENOMEM;
+	}
+	snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
+	snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
+
+	hid_set_drvdata(hdev, data_pointer);
+
+	data_pointer->led_mute.name = name_mute;
+	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
+	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
+	data_pointer->led_mute.dev = dev;
+	led_classdev_register(dev, &data_pointer->led_mute);
+
+	data_pointer->led_micmute.name = name_micmute;
+	data_pointer->led_micmute.brightness_get =
+		lenovo_led_brightness_get_tpkbd;
+	data_pointer->led_micmute.brightness_set =
+		lenovo_led_brightness_set_tpkbd;
+	data_pointer->led_micmute.dev = dev;
+	led_classdev_register(dev, &data_pointer->led_micmute);
+
+	lenovo_features_set_tpkbd(hdev);
+
+	return 0;
+}
+
+static int lenovo_probe_cptkbd(struct hid_device *hdev)
+{
+	int ret;
+	struct lenovo_drvdata_cptkbd *cptkbd_data;
+
+	/* All the custom action happens on the USBMOUSE device for USB */
+	if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+			&& hdev->type != HID_TYPE_USBMOUSE) {
+		hid_dbg(hdev, "Ignoring keyboard half of device\n");
+		return 0;
+	}
+
+	cptkbd_data = devm_kzalloc(&hdev->dev,
+					sizeof(*cptkbd_data),
+					GFP_KERNEL);
+	if (cptkbd_data == NULL) {
+		hid_err(hdev, "can't alloc keyboard descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, cptkbd_data);
+
+	/*
+	 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
+	 * regular keys
+	 */
+	ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
+	if (ret)
+		hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
+
+	/* Turn Fn-Lock on by default */
+	cptkbd_data->fn_lock = true;
+	lenovo_features_set_cptkbd(hdev);
+
+	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
+	if (ret)
+		hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
+
+	return 0;
+}
+
+static int lenovo_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "hid_parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "hid_hw_start failed\n");
+		goto err;
+	}
+
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
+		ret = lenovo_probe_tpkbd(hdev);
+		break;
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		ret = lenovo_probe_cptkbd(hdev);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	if (ret)
+		goto err_hid;
+
+	return 0;
+err_hid:
+	hid_hw_stop(hdev);
+err:
+	return ret;
+}
+
+static void lenovo_remove_tpkbd(struct hid_device *hdev)
+{
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+	/*
+	 * Only the trackpoint half of the keyboard has drvdata and stuff that
+	 * needs unregistering.
+	 */
+	if (data_pointer == NULL)
+		return;
+
+	sysfs_remove_group(&hdev->dev.kobj,
+			&lenovo_attr_group_tpkbd);
+
+	led_classdev_unregister(&data_pointer->led_micmute);
+	led_classdev_unregister(&data_pointer->led_mute);
+
+	hid_set_drvdata(hdev, NULL);
+}
+
+static void lenovo_remove_cptkbd(struct hid_device *hdev)
+{
+	sysfs_remove_group(&hdev->dev.kobj,
+			&lenovo_attr_group_cptkbd);
+}
+
+static void lenovo_remove(struct hid_device *hdev)
+{
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
+		lenovo_remove_tpkbd(hdev);
+		break;
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		lenovo_remove_cptkbd(hdev);
+		break;
+	}
+
+	hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lenovo_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, lenovo_devices);
+
+static struct hid_driver lenovo_driver = {
+	.name = "lenovo",
+	.id_table = lenovo_devices,
+	.input_mapping = lenovo_input_mapping,
+	.probe = lenovo_probe,
+	.remove = lenovo_remove,
+	.raw_event = lenovo_raw_event,
+};
+module_hid_driver(lenovo_driver);
+
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-lenovo-tpkbd.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-lenovo-tpkbd.c
--- linux-libre-3.16-gnu/drivers/hid/hid-lenovo-tpkbd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-lenovo-tpkbd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,462 +0,0 @@
-/*
- *  HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
- *
- *  Copyright (c) 2012 Bernhard Seibold
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/module.h>
-#include <linux/sysfs.h>
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-
-#include "hid-ids.h"
-
-/* This is only used for the trackpoint part of the driver, hence _tp */
-struct tpkbd_data_pointer {
-	int led_state;
-	struct led_classdev led_mute;
-	struct led_classdev led_micmute;
-	int press_to_select;
-	int dragging;
-	int release_to_select;
-	int select_right;
-	int sensitivity;
-	int press_speed;
-};
-
-#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
-
-static int tpkbd_input_mapping(struct hid_device *hdev,
-		struct hid_input *hi, struct hid_field *field,
-		struct hid_usage *usage, unsigned long **bit, int *max)
-{
-	if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
-		/* mark the device as pointer */
-		hid_set_drvdata(hdev, (void *)1);
-		map_key_clear(KEY_MICMUTE);
-		return 1;
-	}
-	return 0;
-}
-
-#undef map_key_clear
-
-static int tpkbd_features_set(struct hid_device *hdev)
-{
-	struct hid_report *report;
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
-
-	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
-	report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
-	report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
-	report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
-	report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
-	report->field[2]->value[0] = data_pointer->sensitivity;
-	report->field[3]->value[0] = data_pointer->press_speed;
-
-	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
-	return 0;
-}
-
-static ssize_t pointer_press_to_select_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
-}
-
-static ssize_t pointer_press_to_select_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value))
-		return -EINVAL;
-	if (value < 0 || value > 1)
-		return -EINVAL;
-
-	data_pointer->press_to_select = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static ssize_t pointer_dragging_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
-}
-
-static ssize_t pointer_dragging_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value))
-		return -EINVAL;
-	if (value < 0 || value > 1)
-		return -EINVAL;
-
-	data_pointer->dragging = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static ssize_t pointer_release_to_select_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
-}
-
-static ssize_t pointer_release_to_select_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value))
-		return -EINVAL;
-	if (value < 0 || value > 1)
-		return -EINVAL;
-
-	data_pointer->release_to_select = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static ssize_t pointer_select_right_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
-}
-
-static ssize_t pointer_select_right_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value))
-		return -EINVAL;
-	if (value < 0 || value > 1)
-		return -EINVAL;
-
-	data_pointer->select_right = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static ssize_t pointer_sensitivity_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-		data_pointer->sensitivity);
-}
-
-static ssize_t pointer_sensitivity_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
-		return -EINVAL;
-
-	data_pointer->sensitivity = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static ssize_t pointer_press_speed_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-		data_pointer->press_speed);
-}
-
-static ssize_t pointer_press_speed_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int value;
-
-	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
-		return -EINVAL;
-
-	data_pointer->press_speed = value;
-	tpkbd_features_set(hdev);
-
-	return count;
-}
-
-static struct device_attribute dev_attr_pointer_press_to_select =
-	__ATTR(press_to_select, S_IWUSR | S_IRUGO,
-			pointer_press_to_select_show,
-			pointer_press_to_select_store);
-
-static struct device_attribute dev_attr_pointer_dragging =
-	__ATTR(dragging, S_IWUSR | S_IRUGO,
-			pointer_dragging_show,
-			pointer_dragging_store);
-
-static struct device_attribute dev_attr_pointer_release_to_select =
-	__ATTR(release_to_select, S_IWUSR | S_IRUGO,
-			pointer_release_to_select_show,
-			pointer_release_to_select_store);
-
-static struct device_attribute dev_attr_pointer_select_right =
-	__ATTR(select_right, S_IWUSR | S_IRUGO,
-			pointer_select_right_show,
-			pointer_select_right_store);
-
-static struct device_attribute dev_attr_pointer_sensitivity =
-	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
-			pointer_sensitivity_show,
-			pointer_sensitivity_store);
-
-static struct device_attribute dev_attr_pointer_press_speed =
-	__ATTR(press_speed, S_IWUSR | S_IRUGO,
-			pointer_press_speed_show,
-			pointer_press_speed_store);
-
-static struct attribute *tpkbd_attributes_pointer[] = {
-	&dev_attr_pointer_press_to_select.attr,
-	&dev_attr_pointer_dragging.attr,
-	&dev_attr_pointer_release_to_select.attr,
-	&dev_attr_pointer_select_right.attr,
-	&dev_attr_pointer_sensitivity.attr,
-	&dev_attr_pointer_press_speed.attr,
-	NULL
-};
-
-static const struct attribute_group tpkbd_attr_group_pointer = {
-	.attrs = tpkbd_attributes_pointer,
-};
-
-static enum led_brightness tpkbd_led_brightness_get(
-			struct led_classdev *led_cdev)
-{
-	struct device *dev = led_cdev->dev->parent;
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	int led_nr = 0;
-
-	if (led_cdev == &data_pointer->led_micmute)
-		led_nr = 1;
-
-	return data_pointer->led_state & (1 << led_nr)
-				? LED_FULL
-				: LED_OFF;
-}
-
-static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
-			enum led_brightness value)
-{
-	struct device *dev = led_cdev->dev->parent;
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-	struct hid_report *report;
-	int led_nr = 0;
-
-	if (led_cdev == &data_pointer->led_micmute)
-		led_nr = 1;
-
-	if (value == LED_OFF)
-		data_pointer->led_state &= ~(1 << led_nr);
-	else
-		data_pointer->led_state |= 1 << led_nr;
-
-	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
-	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
-	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
-	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
-}
-
-static int tpkbd_probe_tp(struct hid_device *hdev)
-{
-	struct device *dev = &hdev->dev;
-	struct tpkbd_data_pointer *data_pointer;
-	size_t name_sz = strlen(dev_name(dev)) + 16;
-	char *name_mute, *name_micmute;
-	int i;
-
-	/* Validate required reports. */
-	for (i = 0; i < 4; i++) {
-		if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
-			return -ENODEV;
-	}
-	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
-		return -ENODEV;
-
-	if (sysfs_create_group(&hdev->dev.kobj,
-				&tpkbd_attr_group_pointer)) {
-		hid_warn(hdev, "Could not create sysfs group\n");
-	}
-
-	data_pointer = devm_kzalloc(&hdev->dev,
-				    sizeof(struct tpkbd_data_pointer),
-				    GFP_KERNEL);
-	if (data_pointer == NULL) {
-		hid_err(hdev, "Could not allocate memory for driver data\n");
-		return -ENOMEM;
-	}
-
-	// set same default values as windows driver
-	data_pointer->sensitivity = 0xa0;
-	data_pointer->press_speed = 0x38;
-
-	name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
-	name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
-	if (name_mute == NULL || name_micmute == NULL) {
-		hid_err(hdev, "Could not allocate memory for led data\n");
-		return -ENOMEM;
-	}
-	snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
-	snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
-
-	hid_set_drvdata(hdev, data_pointer);
-
-	data_pointer->led_mute.name = name_mute;
-	data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
-	data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
-	data_pointer->led_mute.dev = dev;
-	led_classdev_register(dev, &data_pointer->led_mute);
-
-	data_pointer->led_micmute.name = name_micmute;
-	data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
-	data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
-	data_pointer->led_micmute.dev = dev;
-	led_classdev_register(dev, &data_pointer->led_micmute);
-
-	tpkbd_features_set(hdev);
-
-	return 0;
-}
-
-static int tpkbd_probe(struct hid_device *hdev,
-		const struct hid_device_id *id)
-{
-	int ret;
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "hid_parse failed\n");
-		goto err;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
-		hid_err(hdev, "hid_hw_start failed\n");
-		goto err;
-	}
-
-	if (hid_get_drvdata(hdev)) {
-		hid_set_drvdata(hdev, NULL);
-		ret = tpkbd_probe_tp(hdev);
-		if (ret)
-			goto err_hid;
-	}
-
-	return 0;
-err_hid:
-	hid_hw_stop(hdev);
-err:
-	return ret;
-}
-
-static void tpkbd_remove_tp(struct hid_device *hdev)
-{
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
-	sysfs_remove_group(&hdev->dev.kobj,
-			&tpkbd_attr_group_pointer);
-
-	led_classdev_unregister(&data_pointer->led_micmute);
-	led_classdev_unregister(&data_pointer->led_mute);
-
-	hid_set_drvdata(hdev, NULL);
-}
-
-static void tpkbd_remove(struct hid_device *hdev)
-{
-	if (hid_get_drvdata(hdev))
-		tpkbd_remove_tp(hdev);
-
-	hid_hw_stop(hdev);
-}
-
-static const struct hid_device_id tpkbd_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(hid, tpkbd_devices);
-
-static struct hid_driver tpkbd_driver = {
-	.name = "lenovo_tpkbd",
-	.id_table = tpkbd_devices,
-	.input_mapping = tpkbd_input_mapping,
-	.probe = tpkbd_probe,
-	.remove = tpkbd_remove,
-};
-module_hid_driver(tpkbd_driver);
-
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-lg4ff.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-lg4ff.c
--- linux-libre-3.16-gnu/drivers/hid/hid-lg4ff.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-lg4ff.c	2014-09-28 17:29:07.000000000 -0400
@@ -451,13 +451,13 @@ static ssize_t lg4ff_range_store(struct
 	drv_data = hid_get_drvdata(hid);
 	if (!drv_data) {
 		hid_err(hid, "Private driver data not found!\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	entry = drv_data->device_props;
 	if (!entry) {
 		hid_err(hid, "Device properties not found!\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	if (range == 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-lg.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-lg.c
--- linux-libre-3.16-gnu/drivers/hid/hid-lg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-lg.c	2014-09-28 17:29:07.000000000 -0400
@@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_
 	struct usb_device_descriptor *udesc;
 	__u16 bcdDevice, rev_maj, rev_min;
 
-	if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
+	if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
 			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
 		hid_info(hdev,
 			 "fixing up Logitech keyboard report descriptor\n");
 		rdesc[84] = rdesc[89] = 0x4d;
 		rdesc[85] = rdesc[90] = 0x10;
 	}
-	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
+	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
 			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
 			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
 		hid_info(hdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-logitech-dj.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-logitech-dj.c
--- linux-libre-3.16-gnu/drivers/hid/hid-logitech-dj.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-logitech-dj.c	2014-09-28 17:29:07.000000000 -0400
@@ -238,13 +238,6 @@ static void logi_dj_recv_add_djhid_devic
 		return;
 	}
 
-	if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
-	    (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
-		dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
-			__func__, dj_report->device_index);
-		return;
-	}
-
 	if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
 		/* The device is already known. No need to reallocate it. */
 		dbg_hid("%s: device is already known\n", __func__);
@@ -557,7 +550,7 @@ static int logi_dj_ll_raw_request(struct
 	if (!out_buf)
 		return -ENOMEM;
 
-	if (count < DJREPORT_SHORT_LENGTH - 2)
+	if (count > DJREPORT_SHORT_LENGTH - 2)
 		count = DJREPORT_SHORT_LENGTH - 2;
 
 	out_buf[0] = REPORT_ID_DJ_SHORT;
@@ -663,7 +656,6 @@ static int logi_dj_raw_event(struct hid_
 	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
 	struct dj_report *dj_report = (struct dj_report *) data;
 	unsigned long flags;
-	bool report_processed = false;
 
 	dbg_hid("%s, size:%d\n", __func__, size);
 
@@ -691,27 +683,41 @@ static int logi_dj_raw_event(struct hid_
 	 * anything else with it.
 	 */
 
+	/* case 1) */
+	if (data[0] != REPORT_ID_DJ_SHORT)
+		return false;
+
+	if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
+	    (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
+		/*
+		 * Device index is wrong, bail out.
+		 * This driver can ignore safely the receiver notifications,
+		 * so ignore those reports too.
+		 */
+		if (dj_report->device_index != DJ_RECEIVER_INDEX)
+			dev_err(&hdev->dev, "%s: invalid device index:%d\n",
+				__func__, dj_report->device_index);
+		return false;
+	}
+
 	spin_lock_irqsave(&djrcv_dev->lock, flags);
-	if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
-		switch (dj_report->report_type) {
-		case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
-		case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
-			logi_dj_recv_queue_notification(djrcv_dev, dj_report);
-			break;
-		case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
-			if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
-			    STATUS_LINKLOSS) {
-				logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
-			}
-			break;
-		default:
-			logi_dj_recv_forward_report(djrcv_dev, dj_report);
+	switch (dj_report->report_type) {
+	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+		logi_dj_recv_queue_notification(djrcv_dev, dj_report);
+		break;
+	case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+		if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
+		    STATUS_LINKLOSS) {
+			logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
 		}
-		report_processed = true;
+		break;
+	default:
+		logi_dj_recv_forward_report(djrcv_dev, dj_report);
 	}
 	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
 
-	return report_processed;
+	return true;
 }
 
 static int logi_dj_probe(struct hid_device *hdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-logitech-dj.h linux-libre-3.17-rc7-gnu/drivers/hid/hid-logitech-dj.h
--- linux-libre-3.16-gnu/drivers/hid/hid-logitech-dj.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-logitech-dj.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 
 #define DJ_MAX_PAIRED_DEVICES			6
 #define DJ_MAX_NUMBER_NOTIFICATIONS		8
+#define DJ_RECEIVER_INDEX			0
 #define DJ_DEVICE_INDEX_MIN 			1
 #define DJ_DEVICE_INDEX_MAX 			6
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-magicmouse.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-magicmouse.c
--- linux-libre-3.16-gnu/drivers/hid/hid-magicmouse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-magicmouse.c	2014-09-28 17:29:07.000000000 -0400
@@ -290,6 +290,11 @@ static int magicmouse_raw_event(struct h
 		if (size < 4 || ((size - 4) % 9) != 0)
 			return 0;
 		npoints = (size - 4) / 9;
+		if (npoints > 15) {
+			hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n",
+					size);
+			return 0;
+		}
 		msc->ntouches = 0;
 		for (ii = 0; ii < npoints; ii++)
 			magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
@@ -307,6 +312,11 @@ static int magicmouse_raw_event(struct h
 		if (size < 6 || ((size - 6) % 8) != 0)
 			return 0;
 		npoints = (size - 6) / 8;
+		if (npoints > 15) {
+			hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n",
+					size);
+			return 0;
+		}
 		msc->ntouches = 0;
 		for (ii = 0; ii < npoints; ii++)
 			magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-monterey.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-monterey.c
--- linux-libre-3.16-gnu/drivers/hid/hid-monterey.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-monterey.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,7 @@
 static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
+	if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
 		hid_info(hdev, "fixing up button/consumer in HID report descriptor\n");
 		rdesc[30] = 0x0c;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-petalynx.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-petalynx.c
--- linux-libre-3.16-gnu/drivers/hid/hid-petalynx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-petalynx.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
+	if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
 			rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
 			rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
 		hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-picolcd_cir.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_cir.c
--- linux-libre-3.16-gnu/drivers/hid/hid-picolcd_cir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data
 
 	rdev->priv             = data;
 	rdev->driver_type      = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->open             = picolcd_cir_open;
 	rdev->close            = picolcd_cir_close;
 	rdev->input_name       = data->hdev->name;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-picolcd_core.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_core.c
--- linux-libre-3.16-gnu/drivers/hid/hid-picolcd_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -350,6 +350,12 @@ static int picolcd_raw_event(struct hid_
 	if (!data)
 		return 1;
 
+	if (size > 64) {
+		hid_warn(hdev, "invalid size value (%d) for picolcd raw event\n",
+				size);
+		return 0;
+	}
+
 	if (report->id == REPORT_KEY_STATE) {
 		if (data->input_keys)
 			ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-picolcd_debugfs.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_debugfs.c
--- linux-libre-3.16-gnu/drivers/hid/hid-picolcd_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-picolcd_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -883,16 +883,13 @@ void picolcd_exit_devfs(struct picolcd_d
 
 	dent = data->debug_reset;
 	data->debug_reset = NULL;
-	if (dent)
-		debugfs_remove(dent);
+	debugfs_remove(dent);
 	dent = data->debug_eeprom;
 	data->debug_eeprom = NULL;
-	if (dent)
-		debugfs_remove(dent);
+	debugfs_remove(dent);
 	dent = data->debug_flash;
 	data->debug_flash = NULL;
-	if (dent)
-		debugfs_remove(dent);
+	debugfs_remove(dent);
 	mutex_destroy(&data->mutex_flash);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-rmi.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-rmi.c
--- linux-libre-3.16-gnu/drivers/hid/hid-rmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-rmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -377,7 +377,7 @@ static int rmi_input_event(struct hid_de
 	irq_mask |= hdata->f30.irq_mask;
 
 	if (data[1] & ~irq_mask)
-		hid_warn(hdev, "unknown intr source:%02lx %s:%d\n",
+		hid_dbg(hdev, "unknown intr source:%02lx %s:%d\n",
 			data[1] & ~irq_mask, __FILE__, __LINE__);
 
 	if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) {
@@ -400,7 +400,7 @@ static int rmi_read_data_event(struct hi
 	struct rmi_data *hdata = hid_get_drvdata(hdev);
 
 	if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) {
-		hid_err(hdev, "no read request pending\n");
+		hid_dbg(hdev, "no read request pending\n");
 		return 0;
 	}
 
@@ -549,10 +549,12 @@ static int rmi_populate_f11(struct hid_d
 	u8 buf[20];
 	int ret;
 	bool has_query9;
-	bool has_query10;
+	bool has_query10 = false;
 	bool has_query11;
 	bool has_query12;
 	bool has_physical_props;
+	bool has_gestures;
+	bool has_rel;
 	unsigned x_size, y_size;
 	u16 query12_offset;
 
@@ -589,19 +591,32 @@ static int rmi_populate_f11(struct hid_d
 		return -ENODEV;
 	}
 
-	/* query 8 to find out if query 10 exists */
-	ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf);
-	if (ret) {
-		hid_err(hdev, "can not read gesture information: %d.\n", ret);
-		return ret;
+	has_rel = !!(buf[0] & BIT(3));
+	has_gestures = !!(buf[0] & BIT(5));
+
+	if (has_gestures) {
+		/* query 8 to find out if query 10 exists */
+		ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf);
+		if (ret) {
+			hid_err(hdev, "can not read gesture information: %d.\n",
+				ret);
+			return ret;
+		}
+		has_query10 = !!(buf[0] & BIT(2));
 	}
-	has_query10 = !!(buf[0] & BIT(2));
 
 	/*
-	 * At least 8 queries are guaranteed to be present in F11
-	 * +1 for query12.
+	 * At least 4 queries are guaranteed to be present in F11
+	 * +1 for query 5 which is present since absolute events are
+	 * reported and +1 for query 12.
 	 */
-	query12_offset = 9;
+	query12_offset = 6;
+
+	if (has_rel)
+		++query12_offset; /* query 6 is present */
+
+	if (has_gestures)
+		query12_offset += 2; /* query 7 and 8 are present */
 
 	if (has_query9)
 		++query12_offset;
@@ -833,6 +848,8 @@ static int rmi_probe(struct hid_device *
 	struct rmi_data *data = NULL;
 	int ret;
 	size_t alloc_size;
+	struct hid_report *input_report;
+	struct hid_report *output_report;
 
 	data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL);
 	if (!data)
@@ -851,12 +868,26 @@ static int rmi_probe(struct hid_device *
 		return ret;
 	}
 
-	data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT]
-		.report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3)
-		+ 1 /* report id */;
-	data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT]
-		.report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3)
-		+ 1 /* report id */;
+	input_report = hdev->report_enum[HID_INPUT_REPORT]
+			.report_id_hash[RMI_ATTN_REPORT_ID];
+	if (!input_report) {
+		hid_err(hdev, "device does not have expected input report\n");
+		ret = -ENODEV;
+		return ret;
+	}
+
+	data->input_report_size = (input_report->size >> 3) + 1 /* report id */;
+
+	output_report = hdev->report_enum[HID_OUTPUT_REPORT]
+			.report_id_hash[RMI_WRITE_REPORT_ID];
+	if (!output_report) {
+		hid_err(hdev, "device does not have expected output report\n");
+		ret = -ENODEV;
+		return ret;
+	}
+
+	data->output_report_size = (output_report->size >> 3)
+					+ 1 /* report id */;
 
 	alloc_size = data->output_report_size + data->input_report_size;
 
@@ -878,10 +909,15 @@ static int rmi_probe(struct hid_device *
 		return ret;
 	}
 
-	if (!test_bit(RMI_STARTED, &data->flags)) {
-		hid_hw_stop(hdev);
-		return -EIO;
-	}
+	if (!test_bit(RMI_STARTED, &data->flags))
+		/*
+		 * The device maybe in the bootloader if rmi_input_configured
+		 * failed to find F11 in the PDT. Print an error, but don't
+		 * return an error from rmi_probe so that hidraw will be
+		 * accessible from userspace. That way a userspace tool
+		 * can be used to reload working firmware on the touchpad.
+		 */
+		hid_err(hdev, "Device failed to be properly configured\n");
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-roccat-lua.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-roccat-lua.c
--- linux-libre-3.16-gnu/drivers/hid/hid-roccat-lua.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-roccat-lua.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ static ssize_t lua_sysfs_write(struct fi
 		return -EINVAL;
 
 	mutex_lock(&lua->lua_lock);
-	retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+	retval = roccat_common2_send(usb_dev, command, buf, real_size);
 	mutex_unlock(&lua->lua_lock);
 
 	return retval ? retval : real_size;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-sensor-hub.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-sensor-hub.c
--- linux-libre-3.16-gnu/drivers/hid/hid-sensor-hub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-sensor-hub.c	2014-09-28 17:29:07.000000000 -0400
@@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_d
 		ret = -EINVAL;
 		goto err_stop_hw;
 	}
-	sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
-						sizeof(struct mfd_cell),
-						GFP_KERNEL);
+	sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt *
+						      sizeof(struct mfd_cell),
+						      GFP_KERNEL);
 	if (sd->hid_sensor_hub_client_devs == NULL) {
 		hid_err(hdev, "Failed to allocate memory for mfd cells\n");
 			ret = -ENOMEM;
@@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_d
 
 		if (collection->type == HID_COLLECTION_PHYSICAL) {
 
-			hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
+			hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
+					     GFP_KERNEL);
 			if (!hsdev) {
 				hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
 				ret = -ENOMEM;
-				goto err_no_mem;
+				goto err_stop_hw;
 			}
 			hsdev->hdev = hdev;
 			hsdev->vendor_id = hdev->vendor;
@@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_d
 			if (last_hsdev)
 				last_hsdev->end_collection_index = i;
 			last_hsdev = hsdev;
-			name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
-					collection->usage);
+			name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+					      "HID-SENSOR-%x",
+					      collection->usage);
 			if (name == NULL) {
 				hid_err(hdev, "Failed MFD device name\n");
 					ret = -ENOMEM;
-					kfree(hsdev);
-					goto err_no_mem;
+					goto err_stop_hw;
 			}
 			sd->hid_sensor_hub_client_devs[
 				sd->hid_sensor_client_cnt].id =
@@ -661,16 +662,10 @@ static int sensor_hub_probe(struct hid_d
 	ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
 		sd->hid_sensor_client_cnt, NULL, 0, NULL);
 	if (ret < 0)
-		goto err_no_mem;
+		goto err_stop_hw;
 
 	return ret;
 
-err_no_mem:
-	for (i = 0; i < sd->hid_sensor_client_cnt; ++i) {
-		kfree(sd->hid_sensor_hub_client_devs[i].name);
-		kfree(sd->hid_sensor_hub_client_devs[i].platform_data);
-	}
-	kfree(sd->hid_sensor_hub_client_devs);
 err_stop_hw:
 	hid_hw_stop(hdev);
 
@@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid
 {
 	struct sensor_hub_data *data = hid_get_drvdata(hdev);
 	unsigned long flags;
-	int i;
 
 	hid_dbg(hdev, " hardware removed\n");
 	hid_hw_close(hdev);
@@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid
 		complete(&data->pending.ready);
 	spin_unlock_irqrestore(&data->lock, flags);
 	mfd_remove_devices(&hdev->dev);
-	for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
-		kfree(data->hid_sensor_hub_client_devs[i].name);
-		kfree(data->hid_sensor_hub_client_devs[i].platform_data);
-	}
-	kfree(data->hid_sensor_hub_client_devs);
 	hid_set_drvdata(hdev, NULL);
 	mutex_destroy(&data->mutex);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-sony.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-sony.c
--- linux-libre-3.16-gnu/drivers/hid/hid-sony.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-sony.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,32 +56,81 @@
 
 #define MAX_LEDS 4
 
-static const u8 sixaxis_rdesc_fixup[] = {
-	0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
-	0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
-	0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
-};
-
-static const u8 sixaxis_rdesc_fixup2[] = {
-	0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02,
-	0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00,
-	0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
-	0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45,
-	0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81,
-	0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff,
-	0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
-	0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95,
-	0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30,
-	0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02,
-	0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81,
-	0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95,
-	0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09,
-	0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02,
-	0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02,
-	0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95,
-	0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
-	0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
-	0xb1, 0x02, 0xc0, 0xc0,
+static __u8 sixaxis_rdesc[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),               */
+	0x09, 0x04,         /*  Usage (Joystik),                    */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0xA1, 0x02,         /*      Collection (Logical),           */
+	0x85, 0x01,         /*          Report ID (1),              */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x15, 0x00,         /*          Logical Minimum (0),        */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
+	0x81, 0x03,         /*          Input (Constant, Variable), */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x13,         /*          Report Count (19),          */
+	0x15, 0x00,         /*          Logical Minimum (0),        */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x35, 0x00,         /*          Physical Minimum (0),       */
+	0x45, 0x01,         /*          Physical Maximum (1),       */
+	0x05, 0x09,         /*          Usage Page (Button),        */
+	0x19, 0x01,         /*          Usage Minimum (01h),        */
+	0x29, 0x13,         /*          Usage Maximum (13h),        */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x0D,         /*          Report Count (13),          */
+	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+	0x81, 0x03,         /*          Input (Constant, Variable), */
+	0x15, 0x00,         /*          Logical Minimum (0),        */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0xA1, 0x00,         /*          Collection (Physical),      */
+	0x75, 0x08,         /*              Report Size (8),        */
+	0x95, 0x04,         /*              Report Count (4),       */
+	0x35, 0x00,         /*              Physical Minimum (0),   */
+	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
+	0x09, 0x30,         /*              Usage (X),              */
+	0x09, 0x31,         /*              Usage (Y),              */
+	0x09, 0x32,         /*              Usage (Z),              */
+	0x09, 0x35,         /*              Usage (Rz),             */
+	0x81, 0x02,         /*              Input (Variable),       */
+	0xC0,               /*          End Collection,             */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x95, 0x13,         /*          Report Count (19),          */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x95, 0x0C,         /*          Report Count (12),          */
+	0x81, 0x01,         /*          Input (Constant),           */
+	0x75, 0x10,         /*          Report Size (16),           */
+	0x95, 0x04,         /*          Report Count (4),           */
+	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xC0,               /*      End Collection,                 */
+	0xA1, 0x02,         /*      Collection (Logical),           */
+	0x85, 0x02,         /*          Report ID (2),              */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x30,         /*          Report Count (48),          */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0xB1, 0x02,         /*          Feature (Variable),         */
+	0xC0,               /*      End Collection,                 */
+	0xA1, 0x02,         /*      Collection (Logical),           */
+	0x85, 0xEE,         /*          Report ID (238),            */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x30,         /*          Report Count (48),          */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0xB1, 0x02,         /*          Feature (Variable),         */
+	0xC0,               /*      End Collection,                 */
+	0xA1, 0x02,         /*      Collection (Logical),           */
+	0x85, 0xEF,         /*          Report ID (239),            */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x30,         /*          Report Count (48),          */
+	0x09, 0x01,         /*          Usage (Pointer),            */
+	0xB1, 0x02,         /*          Feature (Variable),         */
+	0xC0,               /*      End Collection,                 */
+	0xC0                /*  End Collection                      */
 };
 
 /*
@@ -778,6 +827,13 @@ struct sony_sc {
 	__u8 led_count;
 };
 
+static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc,
+			     unsigned int *rsize)
+{
+	*rsize = sizeof(sixaxis_rdesc);
+	return sixaxis_rdesc;
+}
+
 static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
 			     unsigned int *rsize)
 {
@@ -819,8 +875,6 @@ static int ps3remote_mapping(struct hid_
 	return 1;
 }
 
-
-/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
 static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
@@ -857,20 +911,8 @@ static __u8 *sony_report_fixup(struct hi
 		*rsize = sizeof(dualshock4_bt_rdesc);
 	}
 
-	/* The HID descriptor exposed over BT has a trailing zero byte */
-	if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
-			((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
-			rdesc[83] == 0x75) {
-		hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
-		memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
-			sizeof(sixaxis_rdesc_fixup));
-	} else if (sc->quirks & SIXAXIS_CONTROLLER_USB &&
-		   *rsize > sizeof(sixaxis_rdesc_fixup2)) {
-		hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n",
-			 *rsize, (int)sizeof(sixaxis_rdesc_fixup2));
-		*rsize = sizeof(sixaxis_rdesc_fixup2);
-		memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
-	}
+	if (sc->quirks & SIXAXIS_CONTROLLER)
+		return sixaxis_fixup(hdev, rdesc, rsize);
 
 	if (sc->quirks & PS3REMOTE)
 		return ps3remote_fixup(hdev, rdesc, rsize);
@@ -1307,7 +1349,7 @@ static int sony_leds_init(struct sony_sc
 	static const char * const ds4_name_str[] = { "red", "green", "blue",
 						  "global" };
 	__u8 initial_values[MAX_LEDS] = { 0 };
-	__u8 max_brightness[MAX_LEDS] = { 1 };
+	__u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
 	__u8 use_hw_blink[MAX_LEDS] = { 0 };
 
 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
@@ -1830,9 +1872,7 @@ static int sony_probe(struct hid_device
 
 	if (sc->quirks & VAIO_RDESC_CONSTANT)
 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
-	else if (sc->quirks & SIXAXIS_CONTROLLER_USB)
-		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
-	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+	else if (sc->quirks & SIXAXIS_CONTROLLER)
 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
 
 	ret = hid_hw_start(hdev, connect_mask);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-sunplus.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-sunplus.c
--- linux-libre-3.16-gnu/drivers/hid/hid-sunplus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-sunplus.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,7 @@
 static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
+	if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
 			rdesc[106] == 0x03) {
 		hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n");
 		rdesc[105] = rdesc[110] = 0x03;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/hid-wacom.c linux-libre-3.17-rc7-gnu/drivers/hid/hid-wacom.c
--- linux-libre-3.16-gnu/drivers/hid/hid-wacom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/hid-wacom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,973 +0,0 @@
-/*
- *  Bluetooth Wacom Tablet support
- *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
- *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
- *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
- *  Copyright (c) 2011 PrzemysÅ‚aw Firszt <przemo@firszt.eu>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include <linux/power_supply.h>
-
-#include "hid-ids.h"
-
-#define PAD_DEVICE_ID	0x0F
-
-#define WAC_CMD_LED_CONTROL     0x20
-#define WAC_CMD_ICON_START_STOP     0x21
-#define WAC_CMD_ICON_TRANSFER       0x26
-
-struct wacom_data {
-	__u16 tool;
-	__u16 butstate;
-	__u8 whlstate;
-	__u8 features;
-	__u32 id;
-	__u32 serial;
-	unsigned char high_speed;
-	__u8 battery_capacity;
-	__u8 power_raw;
-	__u8 ps_connected;
-	__u8 bat_charging;
-	struct power_supply battery;
-	struct power_supply ac;
-	__u8 led_selector;
-	struct led_classdev *leds[4];
-};
-
-/*percent of battery capacity for Graphire
-  8th value means AC online and show 100% capacity */
-static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
-/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
-static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
-
-static enum power_supply_property wacom_battery_props[] = {
-	POWER_SUPPLY_PROP_PRESENT,
-	POWER_SUPPLY_PROP_CAPACITY,
-	POWER_SUPPLY_PROP_SCOPE,
-	POWER_SUPPLY_PROP_STATUS,
-};
-
-static enum power_supply_property wacom_ac_props[] = {
-	POWER_SUPPLY_PROP_PRESENT,
-	POWER_SUPPLY_PROP_ONLINE,
-	POWER_SUPPLY_PROP_SCOPE,
-};
-
-static void wacom_scramble(__u8 *image)
-{
-	__u16 mask;
-	__u16 s1;
-	__u16 s2;
-	__u16 r1 ;
-	__u16 r2 ;
-	__u16 r;
-	__u8 buf[256];
-	int i, w, x, y, z;
-
-	for (x = 0; x < 32; x++) {
-		for (y = 0; y < 8; y++)
-			buf[(8 * x) + (7 - y)] = image[(8 * x) + y];
-	}
-
-	/* Change 76543210 into GECA6420 as required by Intuos4 WL
-	 *        HGFEDCBA      HFDB7531
-	 */
-	for (x = 0; x < 4; x++) {
-		for (y = 0; y < 4; y++) {
-			for (z = 0; z < 8; z++) {
-				mask = 0x0001;
-				r1 = 0;
-				r2 = 0;
-				i = (x << 6) + (y << 4) + z;
-				s1 = buf[i];
-				s2 = buf[i+8];
-				for (w = 0; w < 8; w++) {
-					r1 |= (s1 & mask);
-					r2 |= (s2 & mask);
-					s1 <<= 1;
-					s2 <<= 1;
-					mask <<= 2;
-				}
-				r = r1 | (r2 << 1);
-				i = (x << 6) + (y << 4) + (z << 1);
-				image[i] = 0xFF & r;
-				image[i+1] = (0xFF00 & r) >> 8;
-			}
-		}
-	}
-}
-
-static void wacom_set_image(struct hid_device *hdev, const char *image,
-						__u8 icon_no)
-{
-	__u8 rep_data[68];
-	__u8 p[256];
-	int ret, i, j;
-
-	for (i = 0; i < 256; i++)
-		p[i] = image[i];
-
-	rep_data[0] = WAC_CMD_ICON_START_STOP;
-	rep_data[1] = 0;
-	ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
-				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-	if (ret < 0)
-		goto err;
-
-	rep_data[0] = WAC_CMD_ICON_TRANSFER;
-	rep_data[1] = icon_no & 0x07;
-
-	wacom_scramble(p);
-
-	for (i = 0; i < 4; i++) {
-		for (j = 0; j < 64; j++)
-			rep_data[j + 3] = p[(i << 6) + j];
-
-		rep_data[2] = i;
-		ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 67,
-					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-	}
-
-	rep_data[0] = WAC_CMD_ICON_START_STOP;
-	rep_data[1] = 0;
-
-	ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
-				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-
-err:
-	return;
-}
-
-static void wacom_leds_set_brightness(struct led_classdev *led_dev,
-						enum led_brightness value)
-{
-	struct device *dev = led_dev->dev->parent;
-	struct hid_device *hdev;
-	struct wacom_data *wdata;
-	unsigned char *buf;
-	__u8 led = 0;
-	int i;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	wdata = hid_get_drvdata(hdev);
-	for (i = 0; i < 4; ++i) {
-		if (wdata->leds[i] == led_dev)
-			wdata->led_selector = i;
-	}
-
-	led = wdata->led_selector | 0x04;
-	buf = kzalloc(9, GFP_KERNEL);
-	if (buf) {
-		buf[0] = WAC_CMD_LED_CONTROL;
-		buf[1] = led;
-		buf[2] = value >> 2;
-		buf[3] = value;
-		/* use fixed brightness for OLEDs */
-		buf[4] = 0x08;
-		hid_hw_raw_request(hdev, buf[0], buf, 9, HID_FEATURE_REPORT,
-				   HID_REQ_SET_REPORT);
-		kfree(buf);
-	}
-
-	return;
-}
-
-static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev)
-{
-	struct wacom_data *wdata;
-	struct device *dev = led_dev->dev->parent;
-	int value = 0;
-	int i;
-
-	wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
-
-	for (i = 0; i < 4; ++i) {
-		if (wdata->leds[i] == led_dev) {
-			value = wdata->leds[i]->brightness;
-			break;
-		}
-	}
-
-	return value;
-}
-
-
-static int wacom_initialize_leds(struct hid_device *hdev)
-{
-	struct wacom_data *wdata = hid_get_drvdata(hdev);
-	struct led_classdev *led;
-	struct device *dev = &hdev->dev;
-	size_t namesz = strlen(dev_name(dev)) + 12;
-	char *name;
-	int i, ret;
-
-	wdata->led_selector = 0;
-
-	for (i = 0; i < 4; i++) {
-		led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
-		if (!led) {
-			hid_warn(hdev,
-				 "can't allocate memory for LED selector\n");
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		name = (void *)&led[1];
-		snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i);
-		led->name = name;
-		led->brightness = 0;
-		led->max_brightness = 127;
-		led->brightness_get = wacom_leds_get_brightness;
-		led->brightness_set = wacom_leds_set_brightness;
-
-		wdata->leds[i] = led;
-
-		ret = led_classdev_register(dev, wdata->leds[i]);
-
-		if (ret) {
-			wdata->leds[i] = NULL;
-			kfree(led);
-			hid_warn(hdev, "can't register LED\n");
-			goto err;
-		}
-	}
-
-err:
-	return ret;
-}
-
-static void wacom_destroy_leds(struct hid_device *hdev)
-{
-	struct wacom_data *wdata = hid_get_drvdata(hdev);
-	struct led_classdev *led;
-	int i;
-
-	for (i = 0; i < 4; ++i) {
-		if (wdata->leds[i]) {
-			led = wdata->leds[i];
-			wdata->leds[i] = NULL;
-			led_classdev_unregister(led);
-			kfree(led);
-		}
-	}
-
-}
-
-static int wacom_battery_get_property(struct power_supply *psy,
-				enum power_supply_property psp,
-				union power_supply_propval *val)
-{
-	struct wacom_data *wdata = container_of(psy,
-					struct wacom_data, battery);
-	int ret = 0;
-
-	switch (psp) {
-	case POWER_SUPPLY_PROP_PRESENT:
-		val->intval = 1;
-		break;
-	case POWER_SUPPLY_PROP_SCOPE:
-		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
-		break;
-	case POWER_SUPPLY_PROP_CAPACITY:
-		val->intval = wdata->battery_capacity;
-		break;
-	case POWER_SUPPLY_PROP_STATUS:
-		if (wdata->bat_charging)
-			val->intval = POWER_SUPPLY_STATUS_CHARGING;
-		else
-			if (wdata->battery_capacity == 100 && wdata->ps_connected)
-				val->intval = POWER_SUPPLY_STATUS_FULL;
-			else
-				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int wacom_ac_get_property(struct power_supply *psy,
-				enum power_supply_property psp,
-				union power_supply_propval *val)
-{
-	struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
-	int ret = 0;
-
-	switch (psp) {
-	case POWER_SUPPLY_PROP_PRESENT:
-		/* fall through */
-	case POWER_SUPPLY_PROP_ONLINE:
-		val->intval = wdata->ps_connected;
-		break;
-	case POWER_SUPPLY_PROP_SCOPE:
-		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static void wacom_set_features(struct hid_device *hdev, u8 speed)
-{
-	struct wacom_data *wdata = hid_get_drvdata(hdev);
-	int limit, ret;
-	__u8 rep_data[2];
-
-	switch (hdev->product) {
-	case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
-		rep_data[0] = 0x03 ; rep_data[1] = 0x00;
-		limit = 3;
-		do {
-			ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
-					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-		} while (ret < 0 && limit-- > 0);
-
-		if (ret >= 0) {
-			if (speed == 0)
-				rep_data[0] = 0x05;
-			else
-				rep_data[0] = 0x06;
-
-			rep_data[1] = 0x00;
-			limit = 3;
-			do {
-				ret = hid_hw_raw_request(hdev, rep_data[0],
-					rep_data, 2, HID_FEATURE_REPORT,
-					HID_REQ_SET_REPORT);
-			} while (ret < 0 && limit-- > 0);
-
-			if (ret >= 0) {
-				wdata->high_speed = speed;
-				return;
-			}
-		}
-
-		/*
-		 * Note that if the raw queries fail, it's not a hard failure
-		 * and it is safe to continue
-		 */
-		hid_warn(hdev, "failed to poke device, command %d, err %d\n",
-			 rep_data[0], ret);
-		break;
-	case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
-		if (speed == 1)
-			wdata->features &= ~0x20;
-		else
-			wdata->features |= 0x20;
-
-		rep_data[0] = 0x03;
-		rep_data[1] = wdata->features;
-
-		ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
-				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-		if (ret >= 0)
-			wdata->high_speed = speed;
-		break;
-	}
-
-	return;
-}
-
-static ssize_t wacom_show_speed(struct device *dev,
-				struct device_attribute
-				*attr, char *buf)
-{
-	struct wacom_data *wdata = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
-}
-
-static ssize_t wacom_store_speed(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	int new_speed;
-
-	if (sscanf(buf, "%1d", &new_speed ) != 1)
-		return -EINVAL;
-
-	if (new_speed == 0 || new_speed == 1) {
-		wacom_set_features(hdev, new_speed);
-		return strnlen(buf, PAGE_SIZE);
-	} else
-		return -EINVAL;
-}
-
-static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
-		wacom_show_speed, wacom_store_speed);
-
-#define WACOM_STORE(OLED_ID)						\
-static ssize_t wacom_oled##OLED_ID##_store(struct device *dev,		\
-				struct device_attribute *attr,		\
-				const char *buf, size_t count)		\
-{									\
-	struct hid_device *hdev = container_of(dev, struct hid_device,	\
-				dev);					\
-									\
-	if (count != 256)						\
-		return -EINVAL;						\
-									\
-	wacom_set_image(hdev, buf, OLED_ID);				\
-									\
-	return count;							\
-}									\
-									\
-static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL,	\
-				wacom_oled##OLED_ID##_store)
-
-WACOM_STORE(0);
-WACOM_STORE(1);
-WACOM_STORE(2);
-WACOM_STORE(3);
-WACOM_STORE(4);
-WACOM_STORE(5);
-WACOM_STORE(6);
-WACOM_STORE(7);
-
-static int wacom_gr_parse_report(struct hid_device *hdev,
-			struct wacom_data *wdata,
-			struct input_dev *input, unsigned char *data)
-{
-	int tool, x, y, rw;
-
-	tool = 0;
-	/* Get X & Y positions */
-	x = le16_to_cpu(*(__le16 *) &data[2]);
-	y = le16_to_cpu(*(__le16 *) &data[4]);
-
-	/* Get current tool identifier */
-	if (data[1] & 0x90) { /* If pen is in the in/active area */
-		switch ((data[1] >> 5) & 3) {
-		case 0:	/* Pen */
-			tool = BTN_TOOL_PEN;
-			break;
-
-		case 1: /* Rubber */
-			tool = BTN_TOOL_RUBBER;
-			break;
-
-		case 2: /* Mouse with wheel */
-		case 3: /* Mouse without wheel */
-			tool = BTN_TOOL_MOUSE;
-			break;
-		}
-
-		/* Reset tool if out of active tablet area */
-		if (!(data[1] & 0x10))
-			tool = 0;
-	}
-
-	/* If tool changed, notify input subsystem */
-	if (wdata->tool != tool) {
-		if (wdata->tool) {
-			/* Completely reset old tool state */
-			if (wdata->tool == BTN_TOOL_MOUSE) {
-				input_report_key(input, BTN_LEFT, 0);
-				input_report_key(input, BTN_RIGHT, 0);
-				input_report_key(input, BTN_MIDDLE, 0);
-				input_report_abs(input, ABS_DISTANCE,
-					input_abs_get_max(input, ABS_DISTANCE));
-			} else {
-				input_report_key(input, BTN_TOUCH, 0);
-				input_report_key(input, BTN_STYLUS, 0);
-				input_report_key(input, BTN_STYLUS2, 0);
-				input_report_abs(input, ABS_PRESSURE, 0);
-			}
-			input_report_key(input, wdata->tool, 0);
-			input_sync(input);
-		}
-		wdata->tool = tool;
-		if (tool)
-			input_report_key(input, tool, 1);
-	}
-
-	if (tool) {
-		input_report_abs(input, ABS_X, x);
-		input_report_abs(input, ABS_Y, y);
-
-		switch ((data[1] >> 5) & 3) {
-		case 2: /* Mouse with wheel */
-			input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
-			rw = (data[6] & 0x01) ? -1 :
-				(data[6] & 0x02) ? 1 : 0;
-			input_report_rel(input, REL_WHEEL, rw);
-			/* fall through */
-
-		case 3: /* Mouse without wheel */
-			input_report_key(input, BTN_LEFT, data[1] & 0x01);
-			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
-			/* Compute distance between mouse and tablet */
-			rw = 44 - (data[6] >> 2);
-			if (rw < 0)
-				rw = 0;
-			else if (rw > 31)
-				rw = 31;
-			input_report_abs(input, ABS_DISTANCE, rw);
-			break;
-
-		default:
-			input_report_abs(input, ABS_PRESSURE,
-					data[6] | (((__u16) (data[1] & 0x08)) << 5));
-			input_report_key(input, BTN_TOUCH, data[1] & 0x01);
-			input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-			input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
-			break;
-		}
-
-		input_sync(input);
-	}
-
-	/* Report the state of the two buttons at the top of the tablet
-	 * as two extra fingerpad keys (buttons 4 & 5). */
-	rw = data[7] & 0x03;
-	if (rw != wdata->butstate) {
-		wdata->butstate = rw;
-		input_report_key(input, BTN_0, rw & 0x02);
-		input_report_key(input, BTN_1, rw & 0x01);
-		input_report_key(input, BTN_TOOL_FINGER, 0xf0);
-		input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
-		input_sync(input);
-	}
-
-	/* Store current battery capacity and power supply state*/
-	rw = (data[7] >> 2 & 0x07);
-	if (rw != wdata->power_raw) {
-		wdata->power_raw = rw;
-		wdata->battery_capacity = batcap_gr[rw];
-		if (rw == 7)
-			wdata->ps_connected = 1;
-		else
-			wdata->ps_connected = 0;
-	}
-	return 1;
-}
-
-static void wacom_i4_parse_button_report(struct wacom_data *wdata,
-			struct input_dev *input, unsigned char *data)
-{
-	__u16 new_butstate;
-	__u8 new_whlstate;
-	__u8 sync = 0;
-
-	new_whlstate = data[1];
-	if (new_whlstate != wdata->whlstate) {
-		wdata->whlstate = new_whlstate;
-		if (new_whlstate & 0x80) {
-			input_report_key(input, BTN_TOUCH, 1);
-			input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f));
-			input_report_key(input, BTN_TOOL_FINGER, 1);
-		} else {
-			input_report_key(input, BTN_TOUCH, 0);
-			input_report_abs(input, ABS_WHEEL, 0);
-			input_report_key(input, BTN_TOOL_FINGER, 0);
-		}
-		sync = 1;
-	}
-
-	new_butstate = (data[3] << 1) | (data[2] & 0x01);
-	if (new_butstate != wdata->butstate) {
-		wdata->butstate = new_butstate;
-		input_report_key(input, BTN_0, new_butstate & 0x001);
-		input_report_key(input, BTN_1, new_butstate & 0x002);
-		input_report_key(input, BTN_2, new_butstate & 0x004);
-		input_report_key(input, BTN_3, new_butstate & 0x008);
-		input_report_key(input, BTN_4, new_butstate & 0x010);
-		input_report_key(input, BTN_5, new_butstate & 0x020);
-		input_report_key(input, BTN_6, new_butstate & 0x040);
-		input_report_key(input, BTN_7, new_butstate & 0x080);
-		input_report_key(input, BTN_8, new_butstate & 0x100);
-		input_report_key(input, BTN_TOOL_FINGER, 1);
-		sync = 1;
-	}
-
-	if (sync) {
-		input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-		input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
-		input_sync(input);
-	}
-}
-
-static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
-			struct input_dev *input, unsigned char *data)
-{
-	__u16 x, y, pressure;
-	__u8 distance;
-	__u8 tilt_x, tilt_y;
-
-	switch (data[1]) {
-	case 0x80: /* Out of proximity report */
-		input_report_key(input, BTN_TOUCH, 0);
-		input_report_abs(input, ABS_PRESSURE, 0);
-		input_report_key(input, BTN_STYLUS, 0);
-		input_report_key(input, BTN_STYLUS2, 0);
-		input_report_key(input, wdata->tool, 0);
-		input_report_abs(input, ABS_MISC, 0);
-		input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
-		wdata->tool = 0;
-		input_sync(input);
-		break;
-	case 0xC2: /* Tool report */
-		wdata->id = ((data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) |
-			((data[8] & 0xf0) << 12));
-		wdata->serial = ((data[3] & 0x0f) << 28) +
-				(data[4] << 20) + (data[5] << 12) +
-				(data[6] << 4) + (data[7] >> 4);
-
-		switch (wdata->id) {
-		case 0x100802:
-			wdata->tool = BTN_TOOL_PEN;
-			break;
-		case 0x10080A:
-			wdata->tool = BTN_TOOL_RUBBER;
-			break;
-		}
-		break;
-	default: /* Position/pressure report */
-		x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
-		y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
-		pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
-			| (data[1] & 0x01);
-		distance = (data[9] >> 2) & 0x3f;
-		tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7);
-		tilt_y = data[8] & 0x7f;
-
-		input_report_key(input, BTN_TOUCH, pressure > 1);
-
-		input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-		input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
-		input_report_key(input, wdata->tool, 1);
-		input_report_abs(input, ABS_X, x);
-		input_report_abs(input, ABS_Y, y);
-		input_report_abs(input, ABS_PRESSURE, pressure);
-		input_report_abs(input, ABS_DISTANCE, distance);
-		input_report_abs(input, ABS_TILT_X, tilt_x);
-		input_report_abs(input, ABS_TILT_Y, tilt_y);
-		input_report_abs(input, ABS_MISC, wdata->id);
-		input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
-		input_report_key(input, wdata->tool, 1);
-		input_sync(input);
-		break;
-	}
-
-	return;
-}
-
-static void wacom_i4_parse_report(struct hid_device *hdev,
-			struct wacom_data *wdata,
-			struct input_dev *input, unsigned char *data)
-{
-	switch (data[0]) {
-	case 0x00: /* Empty report */
-		break;
-	case 0x02: /* Pen report */
-		wacom_i4_parse_pen_report(wdata, input, data);
-		break;
-	case 0x03: /* Features Report */
-		wdata->features = data[2];
-		break;
-	case 0x0C: /* Button report */
-		wacom_i4_parse_button_report(wdata, input, data);
-		break;
-	default:
-		hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
-		break;
-	}
-}
-
-static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
-		u8 *raw_data, int size)
-{
-	struct wacom_data *wdata = hid_get_drvdata(hdev);
-	struct hid_input *hidinput;
-	struct input_dev *input;
-	unsigned char *data = (unsigned char *) raw_data;
-	int i;
-	__u8 power_raw;
-
-	if (!(hdev->claimed & HID_CLAIMED_INPUT))
-		return 0;
-
-	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
-	input = hidinput->input;
-
-	switch (hdev->product) {
-	case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
-		if (data[0] == 0x03) {
-			return wacom_gr_parse_report(hdev, wdata, input, data);
-		} else {
-			hid_err(hdev, "Unknown report: %d,%d size:%d\n",
-					data[0], data[1], size);
-			return 0;
-		}
-		break;
-	case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
-		i = 1;
-
-		switch (data[0]) {
-		case 0x04:
-			wacom_i4_parse_report(hdev, wdata, input, data + i);
-			i += 10;
-			/* fall through */
-		case 0x03:
-			wacom_i4_parse_report(hdev, wdata, input, data + i);
-			i += 10;
-			wacom_i4_parse_report(hdev, wdata, input, data + i);
-			power_raw = data[i+10];
-			if (power_raw != wdata->power_raw) {
-				wdata->power_raw = power_raw;
-				wdata->battery_capacity = batcap_i4[power_raw & 0x07];
-				wdata->bat_charging = (power_raw & 0x08) ? 1 : 0;
-				wdata->ps_connected = (power_raw & 0x10) ? 1 : 0;
-			}
-
-			break;
-		default:
-			hid_err(hdev, "Unknown report: %d,%d size:%d\n",
-					data[0], data[1], size);
-			return 0;
-		}
-	}
-	return 1;
-}
-
-static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-	struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
-								int *max)
-{
-	struct input_dev *input = hi->input;
-
-	__set_bit(INPUT_PROP_POINTER, input->propbit);
-
-	/* Basics */
-	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
-	__set_bit(REL_WHEEL, input->relbit);
-
-	__set_bit(BTN_TOOL_PEN, input->keybit);
-	__set_bit(BTN_TOUCH, input->keybit);
-	__set_bit(BTN_STYLUS, input->keybit);
-	__set_bit(BTN_STYLUS2, input->keybit);
-	__set_bit(BTN_LEFT, input->keybit);
-	__set_bit(BTN_RIGHT, input->keybit);
-	__set_bit(BTN_MIDDLE, input->keybit);
-
-	/* Pad */
-	input_set_capability(input, EV_MSC, MSC_SERIAL);
-
-	__set_bit(BTN_0, input->keybit);
-	__set_bit(BTN_1, input->keybit);
-	__set_bit(BTN_TOOL_FINGER, input->keybit);
-
-	/* Distance, rubber and mouse */
-	__set_bit(BTN_TOOL_RUBBER, input->keybit);
-	__set_bit(BTN_TOOL_MOUSE, input->keybit);
-
-	switch (hdev->product) {
-	case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
-		input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
-		input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
-		input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
-		input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
-		break;
-	case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
-		__set_bit(ABS_WHEEL, input->absbit);
-		__set_bit(ABS_MISC, input->absbit);
-		__set_bit(BTN_2, input->keybit);
-		__set_bit(BTN_3, input->keybit);
-		__set_bit(BTN_4, input->keybit);
-		__set_bit(BTN_5, input->keybit);
-		__set_bit(BTN_6, input->keybit);
-		__set_bit(BTN_7, input->keybit);
-		__set_bit(BTN_8, input->keybit);
-		input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0);
-		input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
-		input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
-		input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
-		input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0);
-		input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0);
-		input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0);
-		break;
-	}
-
-	return 0;
-}
-
-static int wacom_probe(struct hid_device *hdev,
-		const struct hid_device_id *id)
-{
-	struct wacom_data *wdata;
-	int ret;
-
-	wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
-	if (wdata == NULL) {
-		hid_err(hdev, "can't alloc wacom descriptor\n");
-		return -ENOMEM;
-	}
-
-	hid_set_drvdata(hdev, wdata);
-
-	/* Parse the HID report now */
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "parse failed\n");
-		goto err_free;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
-		hid_err(hdev, "hw start failed\n");
-		goto err_free;
-	}
-
-	ret = device_create_file(&hdev->dev, &dev_attr_speed);
-	if (ret)
-		hid_warn(hdev,
-			 "can't create sysfs speed attribute err: %d\n", ret);
-
-#define OLED_INIT(OLED_ID)						\
-	do {								\
-		ret = device_create_file(&hdev->dev,			\
-				&dev_attr_oled##OLED_ID##_img);		\
-		if (ret)						\
-			hid_warn(hdev,					\
-			 "can't create sysfs oled attribute, err: %d\n", ret);\
-	} while (0)
-
-OLED_INIT(0);
-OLED_INIT(1);
-OLED_INIT(2);
-OLED_INIT(3);
-OLED_INIT(4);
-OLED_INIT(5);
-OLED_INIT(6);
-OLED_INIT(7);
-
-	wdata->features = 0;
-	wacom_set_features(hdev, 1);
-
-	if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
-		sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
-		ret = wacom_initialize_leds(hdev);
-		if (ret)
-			hid_warn(hdev,
-				 "can't create led attribute, err: %d\n", ret);
-	}
-
-	wdata->battery.properties = wacom_battery_props;
-	wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
-	wdata->battery.get_property = wacom_battery_get_property;
-	wdata->battery.name = "wacom_battery";
-	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-	wdata->battery.use_for_apm = 0;
-
-
-	ret = power_supply_register(&hdev->dev, &wdata->battery);
-	if (ret) {
-		hid_err(hdev, "can't create sysfs battery attribute, err: %d\n",
-			ret);
-		goto err_battery;
-	}
-
-	power_supply_powers(&wdata->battery, &hdev->dev);
-
-	wdata->ac.properties = wacom_ac_props;
-	wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
-	wdata->ac.get_property = wacom_ac_get_property;
-	wdata->ac.name = "wacom_ac";
-	wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
-	wdata->ac.use_for_apm = 0;
-
-	ret = power_supply_register(&hdev->dev, &wdata->ac);
-	if (ret) {
-		hid_err(hdev,
-			"can't create ac battery attribute, err: %d\n", ret);
-		goto err_ac;
-	}
-
-	power_supply_powers(&wdata->ac, &hdev->dev);
-	return 0;
-
-err_ac:
-	power_supply_unregister(&wdata->battery);
-err_battery:
-	wacom_destroy_leds(hdev);
-	device_remove_file(&hdev->dev, &dev_attr_oled0_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled1_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled2_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled3_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled4_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled5_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled6_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled7_img);
-	device_remove_file(&hdev->dev, &dev_attr_speed);
-	hid_hw_stop(hdev);
-err_free:
-	kfree(wdata);
-	return ret;
-}
-
-static void wacom_remove(struct hid_device *hdev)
-{
-	struct wacom_data *wdata = hid_get_drvdata(hdev);
-
-	wacom_destroy_leds(hdev);
-	device_remove_file(&hdev->dev, &dev_attr_oled0_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled1_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled2_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled3_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled4_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled5_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled6_img);
-	device_remove_file(&hdev->dev, &dev_attr_oled7_img);
-	device_remove_file(&hdev->dev, &dev_attr_speed);
-	hid_hw_stop(hdev);
-
-	power_supply_unregister(&wdata->battery);
-	power_supply_unregister(&wdata->ac);
-	kfree(hid_get_drvdata(hdev));
-}
-
-static const struct hid_device_id wacom_devices[] = {
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
-
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, wacom_devices);
-
-static struct hid_driver wacom_driver = {
-	.name = "wacom",
-	.id_table = wacom_devices,
-	.probe = wacom_probe,
-	.remove = wacom_remove,
-	.raw_event = wacom_raw_event,
-	.input_mapped = wacom_input_mapped,
-};
-module_hid_driver(wacom_driver);
-
-MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/i2c-hid/i2c-hid.c linux-libre-3.17-rc7-gnu/drivers/hid/i2c-hid/i2c-hid.c
--- linux-libre-3.16-gnu/drivers/hid/i2c-hid/i2c-hid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/i2c-hid/i2c-hid.c	2014-09-28 17:29:07.000000000 -0400
@@ -1054,21 +1054,29 @@ static int i2c_hid_remove(struct i2c_cli
 static int i2c_hid_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct hid_device *hid = ihid->hid;
+	int ret = 0;
 
 	disable_irq(client->irq);
 	if (device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
 
+	if (hid->driver && hid->driver->suspend)
+		ret = hid->driver->suspend(hid, PMSG_SUSPEND);
+
 	/* Save some power */
 	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
 
-	return 0;
+	return ret;
 }
 
 static int i2c_hid_resume(struct device *dev)
 {
 	int ret;
 	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct hid_device *hid = ihid->hid;
 
 	enable_irq(client->irq);
 	ret = i2c_hid_hwreset(client);
@@ -1078,6 +1086,11 @@ static int i2c_hid_resume(struct device
 	if (device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 
+	if (hid->driver && hid->driver->reset_resume) {
+		ret = hid->driver->reset_resume(hid);
+		return ret;
+	}
+
 	return 0;
 }
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/Kconfig linux-libre-3.17-rc7-gnu/drivers/hid/Kconfig
--- linux-libre-3.16-gnu/drivers/hid/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -261,6 +261,20 @@ config HOLTEK_FF
 	  Say Y here if you have a Holtek On Line Grip based game controller
 	  and want to have force feedback support for it.
 
+config HID_GT683R
+	tristate "MSI GT68xR LED support"
+	depends on LEDS_CLASS && USB_HID
+	---help---
+	Say Y here if you want to enable support for the three MSI GT68xR LEDs
+
+	This driver support following modes:
+	  - Normal: LEDs are fully on when enabled
+	  - Audio:  LEDs brightness depends on sound level
+	  - Breathing: LEDs brightness varies at human breathing rate
+
+	Currently the following devices are know to be supported:
+	  - MSI GT683R
+
 config HID_HUION
 	tristate "Huion tablets"
 	depends on USB_HID
@@ -331,18 +345,20 @@ config HID_LCPOWER
 	---help---
 	Support for LC-Power RC1000MCE RF remote control.
 
-config HID_LENOVO_TPKBD
-	tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
+config HID_LENOVO
+	tristate "Lenovo / Thinkpad devices"
 	depends on HID
 	select NEW_LEDS
 	select LEDS_CLASS
 	---help---
-	Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
+	Support for Lenovo devices that are not fully compliant with HID standard.
 
-	Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
-	and would like to use device-specific features like changing the
-	sensitivity of the trackpoint, using the microphone mute button or
-	controlling the mute and microphone mute LEDs.
+	Say Y if you want support for the non-compliant features of the Lenovo
+	Thinkpad standalone keyboards, e.g:
+	- ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
+	  configuration)
+	- ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
+	- ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
 
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
@@ -748,12 +764,17 @@ config THRUSTMASTER_FF
 	  Rumble Force or Force Feedback Wheel.
 
 config HID_WACOM
-	tristate "Wacom Bluetooth devices support"
+	tristate "Wacom Intuos/Graphire tablet support (USB)"
 	depends on HID
-	depends on LEDS_CLASS
 	select POWER_SUPPLY
-	---help---
-	Support for Wacom Graphire Bluetooth and Intuos4 WL tablets.
+	select NEW_LEDS
+	select LEDS_CLASS
+	help
+	  Say Y here if you want to use the USB or BT version of the Wacom Intuos
+	  or Graphire tablet.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wacom.
 
 config HID_WIIMOTE
 	tristate "Nintendo Wii / Wii U peripherals"
@@ -785,7 +806,7 @@ config HID_XINMO
 	depends on HID
 	---help---
 	Support for Xin-Mo devices that are not fully compliant with the HID
-	standard. Currently only supports the Xin-Mo Dual Arcade. Say YÂ here
+	standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
 	if you have a Xin-Mo Dual Arcade controller.
 
 config HID_ZEROPLUS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/Makefile linux-libre-3.17-rc7-gnu/drivers/hid/Makefile
--- linux-libre-3.16-gnu/drivers/hid/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,7 @@ obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_ELO)		+= hid-elo.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
+obj-$(CONFIG_HID_GT683R)	+= hid-gt683r.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-mouse.o
@@ -59,7 +60,7 @@ obj-$(CONFIG_HID_KENSINGTON)	+= hid-kens
 obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
 obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
-obj-$(CONFIG_HID_LENOVO_TPKBD)	+= hid-lenovo-tpkbd.o
+obj-$(CONFIG_HID_LENOVO)	+= hid-lenovo.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
@@ -115,7 +116,9 @@ obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic
 obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
 obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
-obj-$(CONFIG_HID_WACOM)		+= hid-wacom.o
+
+wacom-objs			:= wacom_wac.o wacom_sys.o
+obj-$(CONFIG_HID_WACOM)		+= wacom.o
 obj-$(CONFIG_HID_WALTOP)	+= hid-waltop.o
 obj-$(CONFIG_HID_WIIMOTE)	+= hid-wiimote.o
 obj-$(CONFIG_HID_SENSOR_HUB)	+= hid-sensor-hub.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/usbhid/hid-core.c linux-libre-3.17-rc7-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-3.16-gnu/drivers/hid/usbhid/hid-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/usbhid/hid-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ module_param_named(ignoreled, ignoreled,
 MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds");
 
 /* Quirks specified at module load time */
-static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+static char *quirks_param[MAX_USBHID_BOOT_QUIRKS];
 module_param_array_named(quirks, quirks_param, charp, NULL, 0444);
 MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
 		" quirks=vendorID:productID:quirks"
@@ -536,7 +536,8 @@ static void __usbhid_submit_report(struc
 	int head;
 	struct usbhid_device *usbhid = hid->driver_data;
 
-	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+	if (((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) ||
+		test_bit(HID_DISCONNECTED, &usbhid->iofl))
 		return;
 
 	if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
@@ -1366,6 +1367,9 @@ static void usbhid_disconnect(struct usb
 		return;
 
 	usbhid = hid->driver_data;
+	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
+	set_bit(HID_DISCONNECTED, &usbhid->iofl);
+	spin_unlock_irq(&usbhid->lock);
 	hid_destroy_device(hid);
 	kfree(usbhid);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/usbhid/hid-quirks.c linux-libre-3.17-rc7-gnu/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-3.16-gnu/drivers/hid/usbhid/hid-quirks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hid/usbhid/hid-quirks.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@ static const struct hid_blacklist {
 	{ 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_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, 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 },
 	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET },
@@ -124,6 +124,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_INPUT_REPORTS },
 
 	{ 0, 0 }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/wacom.h linux-libre-3.17-rc7-gnu/drivers/hid/wacom.h
--- linux-libre-3.16-gnu/drivers/hid/wacom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/wacom.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,146 @@
+/*
+ * drivers/input/tablet/wacom.h
+ *
+ *  USB Wacom tablet support
+ *
+ *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
+ *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
+ *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
+ *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
+ *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
+ *  Copyright (c) 2002-2011 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2014 Benjamin Tissoires	<benjamin.tissoires@redhat.com>
+ *
+ *  ChangeLog:
+ *      v0.1 (vp)  - Initial release
+ *      v0.2 (aba) - Support for all buttons / combinations
+ *      v0.3 (vp)  - Support for Intuos added
+ *	v0.4 (sm)  - Support for more Intuos models, menustrip
+ *			relative mode, proximity.
+ *	v0.5 (vp)  - Big cleanup, nifty features removed,
+ *			they belong in userspace
+ *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
+ *			use input_report_key instead of report_btn and
+ *			other cleanups
+ *	v1.11 (vp) - Add URB ->dev setting for new kernels
+ *	v1.11 (jb) - Add support for the 4D Mouse & Lens
+ *	v1.12 (de) - Add support for two more inking pen IDs
+ *	v1.14 (vp) - Use new USB device id probing scheme.
+ *		     Fix Wacom Graphire mouse wheel
+ *	v1.18 (vp) - Fix mouse wheel direction
+ *		     Make mouse relative
+ *      v1.20 (fl) - Report tool id for Intuos devices
+ *                 - Multi tools support
+ *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ *                 - Add PL models support
+ *		   - Fix Wacom Graphire mouse wheel again
+ *	v1.21 (vp) - Removed protocol descriptions
+ *		   - Added MISC_SERIAL for tool serial numbers
+ *	      (gb) - Identify version on module load.
+ *    v1.21.1 (fl) - added Graphire2 support
+ *    v1.21.2 (fl) - added Intuos2 support
+ *                 - added all the PL ids
+ *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
+ *                 - added smooth filter for Graphire from Peri Hankey
+ *                 - added PenPartner support from Olaf van Es
+ *                 - new tool ids from Ole Martin Bjoerndalen
+ *	v1.29 (pc) - Add support for more tablets
+ *		   - Fix pressure reporting
+ *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
+ *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
+ *		   - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
+ *	v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
+ *	v1.43 (pc) - Added support for Cintiq 21UX
+ *		   - Fixed a Graphire bug
+ *		   - Merged wacom_intuos3_irq into wacom_intuos_irq
+ *	v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
+ *		   - Report Device IDs
+ *      v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ *                 - Minor data report fix
+ *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
+ *		   - where wacom_sys.c deals with system specific code,
+ *		   - and wacom_wac.c deals with Wacom specific code
+ *		   - Support Intuos3 4x6
+ *      v1.47 (pc) - Added support for Bamboo
+ *      v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
+ *      v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
+ *      v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
+ *      v1.51 (pc) - Added support for Intuos4
+ *      v1.52 (pc) - Query Wacom data upon system resume
+ *                 - add defines for features->type
+ *                 - add new devices (0x9F, 0xE2, and 0XE3)
+ *      v2.00 (bt) - conversion to a HID driver
+ *                 - integration of the Bluetooth devices
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef WACOM_H
+#define WACOM_H
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/usb/input.h>
+#include <linux/power_supply.h>
+#include <asm/unaligned.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v2.00"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB Wacom tablet driver"
+#define DRIVER_LICENSE "GPL"
+
+#define USB_VENDOR_ID_WACOM	0x056a
+#define USB_VENDOR_ID_LENOVO	0x17ef
+
+struct wacom {
+	struct usb_device *usbdev;
+	struct usb_interface *intf;
+	struct wacom_wac wacom_wac;
+	struct hid_device *hdev;
+	struct mutex lock;
+	struct work_struct work;
+	struct wacom_led {
+		u8 select[2]; /* status led selector (0..3) */
+		u8 llv;       /* status led brightness no button (1..127) */
+		u8 hlv;       /* status led brightness button pressed (1..127) */
+		u8 img_lum;   /* OLED matrix display brightness */
+	} led;
+	bool led_initialized;
+	struct power_supply battery;
+	struct power_supply ac;
+};
+
+static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
+{
+	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+	schedule_work(&wacom->work);
+}
+
+static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
+{
+	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+
+	power_supply_changed(&wacom->battery);
+}
+
+extern const struct hid_device_id wacom_ids[];
+
+void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
+void wacom_setup_device_quirks(struct wacom_features *features);
+int wacom_setup_input_capabilities(struct input_dev *input_dev,
+				   struct wacom_wac *wacom_wac);
+int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
+				       struct wacom_wac *wacom_wac);
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/wacom_sys.c linux-libre-3.17-rc7-gnu/drivers/hid/wacom_sys.c
--- linux-libre-3.16-gnu/drivers/hid/wacom_sys.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/wacom_sys.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1458 @@
+/*
+ * drivers/input/tablet/wacom_sys.c
+ *
+ *  USB Wacom tablet support - system specific code
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "wacom_wac.h"
+#include "wacom.h"
+#include <linux/hid.h>
+
+#define WAC_MSG_RETRIES		5
+
+#define WAC_CMD_LED_CONTROL	0x20
+#define WAC_CMD_ICON_START	0x21
+#define WAC_CMD_ICON_XFER	0x23
+#define WAC_CMD_ICON_BT_XFER	0x26
+#define WAC_CMD_RETRIES		10
+
+static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
+			    void *buf, size_t size, unsigned int retries)
+{
+	int retval;
+
+	do {
+		retval = hid_hw_raw_request(hdev, id, buf, size, type,
+				HID_REQ_GET_REPORT);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
+}
+
+static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf,
+			    size_t size, unsigned int retries)
+{
+	int retval;
+
+	do {
+		retval = hid_hw_raw_request(hdev, buf[0], buf, size, type,
+				HID_REQ_SET_REPORT);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
+}
+
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+
+	if (size > WACOM_PKGLEN_MAX)
+		return 1;
+
+	memcpy(wacom->wacom_wac.data, raw_data, size);
+
+	wacom_wac_irq(&wacom->wacom_wac, size);
+
+	return 0;
+}
+
+static int wacom_open(struct input_dev *dev)
+{
+	struct wacom *wacom = input_get_drvdata(dev);
+	int retval;
+
+	mutex_lock(&wacom->lock);
+	retval = hid_hw_open(wacom->hdev);
+	mutex_unlock(&wacom->lock);
+
+	return retval;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+	struct wacom *wacom = input_get_drvdata(dev);
+
+	mutex_lock(&wacom->lock);
+	hid_hw_close(wacom->hdev);
+	mutex_unlock(&wacom->lock);
+}
+
+/*
+ * Calculate the resolution of the X or Y axis using hidinput_calc_abs_res.
+ */
+static int wacom_calc_hid_res(int logical_extents, int physical_extents,
+			       unsigned unit, int exponent)
+{
+	struct hid_field field = {
+		.logical_maximum = logical_extents,
+		.physical_maximum = physical_extents,
+		.unit = unit,
+		.unit_exponent = exponent,
+	};
+
+	return hidinput_calc_abs_res(&field, ABS_X);
+}
+
+static void wacom_feature_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_features *features = &wacom->wacom_wac.features;
+
+	switch (usage->hid) {
+	case HID_DG_CONTACTMAX:
+		/* leave touch_max as is if predefined */
+		if (!features->touch_max)
+			features->touch_max = field->value[0];
+		break;
+	}
+}
+
+/*
+ * Interface Descriptor of wacom devices can be incomplete and
+ * inconsistent so wacom_features table is used to store stylus
+ * device's packet lengths, various maximum values, and tablet
+ * resolution based on product ID's.
+ *
+ * For devices that contain 2 interfaces, wacom_features table is
+ * inaccurate for the touch interface.  Since the Interface Descriptor
+ * for touch interfaces has pretty complete data, this function exists
+ * to query tablet for this missing information instead of hard coding in
+ * an additional table.
+ *
+ * A typical Interface Descriptor for a stylus will contain a
+ * boot mouse application collection that is not of interest and this
+ * function will ignore it.
+ *
+ * It also contains a digitizer application collection that also is not
+ * of interest since any information it contains would be duplicate
+ * of what is in wacom_features. Usually it defines a report of an array
+ * of bytes that could be used as max length of the stylus packet returned.
+ * If it happens to define a Digitizer-Stylus Physical Collection then
+ * the X and Y logical values contain valid data but it is ignored.
+ *
+ * A typical Interface Descriptor for a touch interface will contain a
+ * Digitizer-Finger Physical Collection which will define both logical
+ * X/Y maximum as well as the physical size of tablet. Since touch
+ * interfaces haven't supported pressure or distance, this is enough
+ * information to override invalid values in the wacom_features table.
+ *
+ * Intuos5 touch interface and 3rd gen Bamboo Touch do not contain useful
+ * data. We deal with them after returning from this function.
+ */
+static void wacom_usage_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_features *features = &wacom->wacom_wac.features;
+	bool finger = (field->logical == HID_DG_FINGER) ||
+		      (field->physical == HID_DG_FINGER);
+	bool pen = (field->logical == HID_DG_STYLUS) ||
+		   (field->physical == HID_DG_STYLUS);
+
+	/*
+	* Requiring Stylus Usage will ignore boot mouse
+	* X/Y values and some cases of invalid Digitizer X/Y
+	* values commonly reported.
+	*/
+	if (!pen && !finger)
+		return;
+
+	if (finger && !features->touch_max)
+		/* touch device at least supports one touch point */
+		features->touch_max = 1;
+
+	switch (usage->hid) {
+	case HID_GD_X:
+		features->x_max = field->logical_maximum;
+		if (finger) {
+			features->device_type = BTN_TOOL_FINGER;
+			features->x_phy = field->physical_maximum;
+			if (features->type != BAMBOO_PT) {
+				features->unit = field->unit;
+				features->unitExpo = field->unit_exponent;
+			}
+		} else {
+			features->device_type = BTN_TOOL_PEN;
+		}
+		break;
+	case HID_GD_Y:
+		features->y_max = field->logical_maximum;
+		if (finger) {
+			features->y_phy = field->physical_maximum;
+			if (features->type != BAMBOO_PT) {
+				features->unit = field->unit;
+				features->unitExpo = field->unit_exponent;
+			}
+		}
+		break;
+	case HID_DG_TIPPRESSURE:
+		if (pen)
+			features->pressure_max = field->logical_maximum;
+		break;
+	}
+}
+
+static void wacom_parse_hid(struct hid_device *hdev,
+			   struct wacom_features *features)
+{
+	struct hid_report_enum *rep_enum;
+	struct hid_report *hreport;
+	int i, j;
+
+	/* check features first */
+	rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+	list_for_each_entry(hreport, &rep_enum->report_list, list) {
+		for (i = 0; i < hreport->maxfield; i++) {
+			/* Ignore if report count is out of bounds. */
+			if (hreport->field[i]->report_count < 1)
+				continue;
+
+			for (j = 0; j < hreport->field[i]->maxusage; j++) {
+				wacom_feature_mapping(hdev, hreport->field[i],
+						hreport->field[i]->usage + j);
+			}
+		}
+	}
+
+	/* now check the input usages */
+	rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+	list_for_each_entry(hreport, &rep_enum->report_list, list) {
+
+		if (!hreport->maxfield)
+			continue;
+
+		for (i = 0; i < hreport->maxfield; i++)
+			for (j = 0; j < hreport->field[i]->maxusage; j++)
+				wacom_usage_mapping(hdev, hreport->field[i],
+						hreport->field[i]->usage + j);
+	}
+}
+
+static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
+		int length, int mode)
+{
+	unsigned char *rep_data;
+	int error = -ENOMEM, limit = 0;
+
+	rep_data = kzalloc(length, GFP_KERNEL);
+	if (!rep_data)
+		return error;
+
+	do {
+		rep_data[0] = report_id;
+		rep_data[1] = mode;
+
+		error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data,
+					 length, 1);
+		if (error >= 0)
+			error = wacom_get_report(hdev, HID_FEATURE_REPORT,
+			                         report_id, rep_data, length, 1);
+	} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
+
+	kfree(rep_data);
+
+	return error < 0 ? error : 0;
+}
+
+static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
+		struct wacom_features *features)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	int ret;
+	u8 rep_data[2];
+
+	switch (features->type) {
+	case GRAPHIRE_BT:
+		rep_data[0] = 0x03;
+		rep_data[1] = 0x00;
+		ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+					3);
+
+		if (ret >= 0) {
+			rep_data[0] = speed == 0 ? 0x05 : 0x06;
+			rep_data[1] = 0x00;
+
+			ret = wacom_set_report(hdev, HID_FEATURE_REPORT,
+						rep_data, 2, 3);
+
+			if (ret >= 0) {
+				wacom->wacom_wac.bt_high_speed = speed;
+				return 0;
+			}
+		}
+
+		/*
+		 * Note that if the raw queries fail, it's not a hard failure
+		 * and it is safe to continue
+		 */
+		hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+			 rep_data[0], ret);
+		break;
+	case INTUOS4WL:
+		if (speed == 1)
+			wacom->wacom_wac.bt_features &= ~0x20;
+		else
+			wacom->wacom_wac.bt_features |= 0x20;
+
+		rep_data[0] = 0x03;
+		rep_data[1] = wacom->wacom_wac.bt_features;
+
+		ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+					1);
+		if (ret >= 0)
+			wacom->wacom_wac.bt_high_speed = speed;
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Switch the tablet into its most-capable mode. Wacom tablets are
+ * typically configured to power-up in a mode which sends mouse-like
+ * reports to the OS. To get absolute position, pressure data, etc.
+ * from the tablet, it is necessary to switch the tablet out of this
+ * mode and into one which sends the full range of tablet data.
+ */
+static int wacom_query_tablet_data(struct hid_device *hdev,
+		struct wacom_features *features)
+{
+	if (hdev->bus == BUS_BLUETOOTH)
+		return wacom_bt_query_tablet_data(hdev, 1, features);
+
+	if (features->device_type == BTN_TOOL_FINGER) {
+		if (features->type > TABLETPC) {
+			/* MT Tablet PC touch */
+			return wacom_set_device_mode(hdev, 3, 4, 4);
+		}
+		else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
+			return wacom_set_device_mode(hdev, 18, 3, 2);
+		}
+	} else if (features->device_type == BTN_TOOL_PEN) {
+		if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
+			return wacom_set_device_mode(hdev, 2, 2, 2);
+		}
+	}
+
+	return 0;
+}
+
+static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
+					 struct wacom_features *features)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct usb_interface *intf = wacom->intf;
+
+	/* default features */
+	features->device_type = BTN_TOOL_PEN;
+	features->x_fuzz = 4;
+	features->y_fuzz = 4;
+	features->pressure_fuzz = 0;
+	features->distance_fuzz = 0;
+
+	/*
+	 * The wireless device HID is basic and layout conflicts with
+	 * other tablets (monitor and touch interface can look like pen).
+	 * Skip the query for this type and modify defaults based on
+	 * interface number.
+	 */
+	if (features->type == WIRELESS) {
+		if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+			features->device_type = 0;
+		} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
+			features->device_type = BTN_TOOL_FINGER;
+			features->pktlen = WACOM_PKGLEN_BBTOUCH3;
+		}
+	}
+
+	/* only devices that support touch need to retrieve the info */
+	if (features->type < BAMBOO_PT)
+		return;
+
+	wacom_parse_hid(hdev, features);
+}
+
+struct wacom_hdev_data {
+	struct list_head list;
+	struct kref kref;
+	struct hid_device *dev;
+	struct wacom_shared shared;
+};
+
+static LIST_HEAD(wacom_udev_list);
+static DEFINE_MUTEX(wacom_udev_list_lock);
+
+static bool wacom_are_sibling(struct hid_device *hdev,
+		struct hid_device *sibling)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_features *features = &wacom->wacom_wac.features;
+	int vid = features->oVid;
+	int pid = features->oPid;
+	int n1,n2;
+
+	if (vid == 0 && pid == 0) {
+		vid = hdev->vendor;
+		pid = hdev->product;
+	}
+
+	if (vid != sibling->vendor || pid != sibling->product)
+		return false;
+
+	/* Compare the physical path. */
+	n1 = strrchr(hdev->phys, '.') - hdev->phys;
+	n2 = strrchr(sibling->phys, '.') - sibling->phys;
+	if (n1 != n2 || n1 <= 0 || n2 <= 0)
+		return false;
+
+	return !strncmp(hdev->phys, sibling->phys, n1);
+}
+
+static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
+{
+	struct wacom_hdev_data *data;
+
+	list_for_each_entry(data, &wacom_udev_list, list) {
+		if (wacom_are_sibling(hdev, data->dev)) {
+			kref_get(&data->kref);
+			return data;
+		}
+	}
+
+	return NULL;
+}
+
+static int wacom_add_shared_data(struct hid_device *hdev)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_hdev_data *data;
+	int retval = 0;
+
+	mutex_lock(&wacom_udev_list_lock);
+
+	data = wacom_get_hdev_data(hdev);
+	if (!data) {
+		data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
+		if (!data) {
+			retval = -ENOMEM;
+			goto out;
+		}
+
+		kref_init(&data->kref);
+		data->dev = hdev;
+		list_add_tail(&data->list, &wacom_udev_list);
+	}
+
+	wacom_wac->shared = &data->shared;
+
+out:
+	mutex_unlock(&wacom_udev_list_lock);
+	return retval;
+}
+
+static void wacom_release_shared_data(struct kref *kref)
+{
+	struct wacom_hdev_data *data =
+		container_of(kref, struct wacom_hdev_data, kref);
+
+	mutex_lock(&wacom_udev_list_lock);
+	list_del(&data->list);
+	mutex_unlock(&wacom_udev_list_lock);
+
+	kfree(data);
+}
+
+static void wacom_remove_shared_data(struct wacom_wac *wacom)
+{
+	struct wacom_hdev_data *data;
+
+	if (wacom->shared) {
+		data = container_of(wacom->shared, struct wacom_hdev_data, shared);
+		kref_put(&data->kref, wacom_release_shared_data);
+		wacom->shared = NULL;
+	}
+}
+
+static int wacom_led_control(struct wacom *wacom)
+{
+	unsigned char *buf;
+	int retval;
+
+	buf = kzalloc(9, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (wacom->wacom_wac.features.type >= INTUOS5S &&
+	    wacom->wacom_wac.features.type <= INTUOSPL) {
+		/*
+		 * Touch Ring and crop mark LED luminance may take on
+		 * one of four values:
+		 *    0 = Low; 1 = Medium; 2 = High; 3 = Off
+		 */
+		int ring_led = wacom->led.select[0] & 0x03;
+		int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03;
+		int crop_lum = 0;
+
+		buf[0] = WAC_CMD_LED_CONTROL;
+		buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
+	}
+	else {
+		int led = wacom->led.select[0] | 0x4;
+
+		if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
+		    wacom->wacom_wac.features.type == WACOM_24HD)
+			led |= (wacom->led.select[1] << 4) | 0x40;
+
+		buf[0] = WAC_CMD_LED_CONTROL;
+		buf[1] = led;
+		buf[2] = wacom->led.llv;
+		buf[3] = wacom->led.hlv;
+		buf[4] = wacom->led.img_lum;
+	}
+
+	retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9,
+				  WAC_CMD_RETRIES);
+	kfree(buf);
+
+	return retval;
+}
+
+static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id,
+		const unsigned len, const void *img)
+{
+	unsigned char *buf;
+	int i, retval;
+	const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
+
+	buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Send 'start' command */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 1;
+	retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+				  WAC_CMD_RETRIES);
+	if (retval < 0)
+		goto out;
+
+	buf[0] = xfer_id;
+	buf[1] = button_id & 0x07;
+	for (i = 0; i < 4; i++) {
+		buf[2] = i;
+		memcpy(buf + 3, img + i * chunk_len, chunk_len);
+
+		retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
+					  buf, chunk_len + 3, WAC_CMD_RETRIES);
+		if (retval < 0)
+			break;
+	}
+
+	/* Send 'stop' */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 0;
+	wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+			 WAC_CMD_RETRIES);
+
+out:
+	kfree(buf);
+	return retval;
+}
+
+static ssize_t wacom_led_select_store(struct device *dev, int set_id,
+				      const char *buf, size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	unsigned int id;
+	int err;
+
+	err = kstrtouint(buf, 10, &id);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	wacom->led.select[set_id] = id & 0x3;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LED_SELECT_ATTR(SET_ID)					\
+static ssize_t wacom_led##SET_ID##_select_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_led_select_store(dev, SET_ID, buf, count);		\
+}									\
+static ssize_t wacom_led##SET_ID##_select_show(struct device *dev,	\
+	struct device_attribute *attr, char *buf)			\
+{									\
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+	struct wacom *wacom = hid_get_drvdata(hdev);			\
+	return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);	\
+}									\
+static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR,	\
+		    wacom_led##SET_ID##_select_show,			\
+		    wacom_led##SET_ID##_select_store)
+
+DEVICE_LED_SELECT_ATTR(0);
+DEVICE_LED_SELECT_ATTR(1);
+
+static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
+				     const char *buf, size_t count)
+{
+	unsigned int value;
+	int err;
+
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	*dest = value & 0x7f;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LUMINANCE_ATTR(name, field)				\
+static ssize_t wacom_##name##_luminance_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+	struct wacom *wacom = hid_get_drvdata(hdev);			\
+									\
+	return wacom_luminance_store(wacom, &wacom->led.field,		\
+				     buf, count);			\
+}									\
+static DEVICE_ATTR(name##_luminance, S_IWUSR,				\
+		   NULL, wacom_##name##_luminance_store)
+
+DEVICE_LUMINANCE_ATTR(status0, llv);
+DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(buttons, img_lum);
+
+static ssize_t wacom_button_image_store(struct device *dev, int button_id,
+					const char *buf, size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	int err;
+	unsigned len;
+	u8 xfer_id;
+
+	if (hdev->bus == BUS_BLUETOOTH) {
+		len = 256;
+		xfer_id = WAC_CMD_ICON_BT_XFER;
+	} else {
+		len = 1024;
+		xfer_id = WAC_CMD_ICON_XFER;
+	}
+
+	if (count != len)
+		return -EINVAL;
+
+	mutex_lock(&wacom->lock);
+
+	err = wacom_led_putimage(wacom, button_id, xfer_id, len, buf);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_BTNIMG_ATTR(BUTTON_ID)					\
+static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_button_image_store(dev, BUTTON_ID, buf, count);	\
+}									\
+static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR,			\
+		   NULL, wacom_btnimg##BUTTON_ID##_store)
+
+DEVICE_BTNIMG_ATTR(0);
+DEVICE_BTNIMG_ATTR(1);
+DEVICE_BTNIMG_ATTR(2);
+DEVICE_BTNIMG_ATTR(3);
+DEVICE_BTNIMG_ATTR(4);
+DEVICE_BTNIMG_ATTR(5);
+DEVICE_BTNIMG_ATTR(6);
+DEVICE_BTNIMG_ATTR(7);
+
+static struct attribute *cintiq_led_attrs[] = {
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_status_led1_select.attr,
+	NULL
+};
+
+static struct attribute_group cintiq_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = cintiq_led_attrs,
+};
+
+static struct attribute *intuos4_led_attrs[] = {
+	&dev_attr_status0_luminance.attr,
+	&dev_attr_status1_luminance.attr,
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_buttons_luminance.attr,
+	&dev_attr_button0_rawimg.attr,
+	&dev_attr_button1_rawimg.attr,
+	&dev_attr_button2_rawimg.attr,
+	&dev_attr_button3_rawimg.attr,
+	&dev_attr_button4_rawimg.attr,
+	&dev_attr_button5_rawimg.attr,
+	&dev_attr_button6_rawimg.attr,
+	&dev_attr_button7_rawimg.attr,
+	NULL
+};
+
+static struct attribute_group intuos4_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = intuos4_led_attrs,
+};
+
+static struct attribute *intuos5_led_attrs[] = {
+	&dev_attr_status0_luminance.attr,
+	&dev_attr_status_led0_select.attr,
+	NULL
+};
+
+static struct attribute_group intuos5_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = intuos5_led_attrs,
+};
+
+static int wacom_initialize_leds(struct wacom *wacom)
+{
+	int error;
+
+	/* Initialize default values */
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4S:
+	case INTUOS4:
+	case INTUOS4WL:
+	case INTUOS4L:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 10;
+		wacom->led.hlv = 20;
+		wacom->led.img_lum = 10;
+		error = sysfs_create_group(&wacom->hdev->dev.kobj,
+					   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_24HD:
+	case WACOM_21UX2:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 0;
+		wacom->led.hlv = 0;
+		wacom->led.img_lum = 0;
+
+		error = sysfs_create_group(&wacom->hdev->dev.kobj,
+					   &cintiq_led_attr_group);
+		break;
+
+	case INTUOS5S:
+	case INTUOS5:
+	case INTUOS5L:
+	case INTUOSPS:
+	case INTUOSPM:
+	case INTUOSPL:
+		if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) {
+			wacom->led.select[0] = 0;
+			wacom->led.select[1] = 0;
+			wacom->led.llv = 32;
+			wacom->led.hlv = 0;
+			wacom->led.img_lum = 0;
+
+			error = sysfs_create_group(&wacom->hdev->dev.kobj,
+						  &intuos5_led_attr_group);
+		} else
+			return 0;
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (error) {
+		hid_err(wacom->hdev,
+			"cannot create sysfs group err: %d\n", error);
+		return error;
+	}
+	wacom_led_control(wacom);
+	wacom->led_initialized = true;
+
+	return 0;
+}
+
+static void wacom_destroy_leds(struct wacom *wacom)
+{
+	if (!wacom->led_initialized)
+		return;
+
+	wacom->led_initialized = false;
+
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4S:
+	case INTUOS4:
+	case INTUOS4WL:
+	case INTUOS4L:
+		sysfs_remove_group(&wacom->hdev->dev.kobj,
+				   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_24HD:
+	case WACOM_21UX2:
+		sysfs_remove_group(&wacom->hdev->dev.kobj,
+				   &cintiq_led_attr_group);
+		break;
+
+	case INTUOS5S:
+	case INTUOS5:
+	case INTUOS5L:
+	case INTUOSPS:
+	case INTUOSPM:
+	case INTUOSPL:
+		if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN)
+			sysfs_remove_group(&wacom->hdev->dev.kobj,
+					   &intuos5_led_attr_group);
+		break;
+	}
+}
+
+static enum power_supply_property wacom_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_CAPACITY
+};
+
+static enum power_supply_property wacom_ac_props[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_SCOPE,
+};
+
+static int wacom_battery_get_property(struct power_supply *psy,
+				      enum power_supply_property psp,
+				      union power_supply_propval *val)
+{
+	struct wacom *wacom = container_of(psy, struct wacom, battery);
+	int ret = 0;
+
+	switch (psp) {
+		case POWER_SUPPLY_PROP_SCOPE:
+			val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+			break;
+		case POWER_SUPPLY_PROP_CAPACITY:
+			val->intval =
+				wacom->wacom_wac.battery_capacity;
+			break;
+		case POWER_SUPPLY_PROP_STATUS:
+			if (wacom->wacom_wac.bat_charging)
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+			else if (wacom->wacom_wac.battery_capacity == 100 &&
+				    wacom->wacom_wac.ps_connected)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int wacom_ac_get_property(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct wacom *wacom = container_of(psy, struct wacom, ac);
+	int ret = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		/* fall through */
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = wacom->wacom_wac.ps_connected;
+		break;
+	case POWER_SUPPLY_PROP_SCOPE:
+		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int wacom_initialize_battery(struct wacom *wacom)
+{
+	static atomic_t battery_no = ATOMIC_INIT(0);
+	int error;
+	unsigned long n;
+
+	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) {
+		n = atomic_inc_return(&battery_no) - 1;
+
+		wacom->battery.properties = wacom_battery_props;
+		wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
+		wacom->battery.get_property = wacom_battery_get_property;
+		sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n);
+		wacom->battery.name = wacom->wacom_wac.bat_name;
+		wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+		wacom->battery.use_for_apm = 0;
+
+		wacom->ac.properties = wacom_ac_props;
+		wacom->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
+		wacom->ac.get_property = wacom_ac_get_property;
+		sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n);
+		wacom->ac.name = wacom->wacom_wac.ac_name;
+		wacom->ac.type = POWER_SUPPLY_TYPE_MAINS;
+		wacom->ac.use_for_apm = 0;
+
+		error = power_supply_register(&wacom->hdev->dev,
+					      &wacom->battery);
+		if (error)
+			return error;
+
+		power_supply_powers(&wacom->battery, &wacom->hdev->dev);
+
+		error = power_supply_register(&wacom->hdev->dev, &wacom->ac);
+		if (error) {
+			power_supply_unregister(&wacom->battery);
+			return error;
+		}
+
+		power_supply_powers(&wacom->ac, &wacom->hdev->dev);
+	}
+
+	return 0;
+}
+
+static void wacom_destroy_battery(struct wacom *wacom)
+{
+	if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
+	     wacom->battery.dev) {
+		power_supply_unregister(&wacom->battery);
+		wacom->battery.dev = NULL;
+		power_supply_unregister(&wacom->ac);
+		wacom->ac.dev = NULL;
+	}
+}
+
+static ssize_t wacom_show_speed(struct device *dev,
+				struct device_attribute
+				*attr, char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct wacom *wacom = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%i\n", wacom->wacom_wac.bt_high_speed);
+}
+
+static ssize_t wacom_store_speed(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	u8 new_speed;
+
+	if (kstrtou8(buf, 0, &new_speed))
+		return -EINVAL;
+
+	if (new_speed != 0 && new_speed != 1)
+		return -EINVAL;
+
+	wacom_bt_query_tablet_data(hdev, new_speed, &wacom->wacom_wac.features);
+
+	return count;
+}
+
+static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
+		wacom_show_speed, wacom_store_speed);
+
+static struct input_dev *wacom_allocate_input(struct wacom *wacom)
+{
+	struct input_dev *input_dev;
+	struct hid_device *hdev = wacom->hdev;
+	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+
+	input_dev = input_allocate_device();
+	if (!input_dev)
+		return NULL;
+
+	input_dev->name = wacom_wac->name;
+	input_dev->phys = hdev->phys;
+	input_dev->dev.parent = &hdev->dev;
+	input_dev->open = wacom_open;
+	input_dev->close = wacom_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, wacom);
+
+	return input_dev;
+}
+
+static void wacom_unregister_inputs(struct wacom *wacom)
+{
+	if (wacom->wacom_wac.input)
+		input_unregister_device(wacom->wacom_wac.input);
+	if (wacom->wacom_wac.pad_input)
+		input_unregister_device(wacom->wacom_wac.pad_input);
+	wacom->wacom_wac.input = NULL;
+	wacom->wacom_wac.pad_input = NULL;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
+{
+	struct input_dev *input_dev, *pad_input_dev;
+	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+	int error;
+
+	input_dev = wacom_allocate_input(wacom);
+	pad_input_dev = wacom_allocate_input(wacom);
+	if (!input_dev || !pad_input_dev) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+
+	wacom_wac->input = input_dev;
+	wacom_wac->pad_input = pad_input_dev;
+	wacom_wac->pad_input->name = wacom_wac->pad_name;
+
+	error = wacom_setup_input_capabilities(input_dev, wacom_wac);
+	if (error)
+		goto fail2;
+
+	error = input_register_device(input_dev);
+	if (error)
+		goto fail2;
+
+	error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
+	if (error) {
+		/* no pad in use on this interface */
+		input_free_device(pad_input_dev);
+		wacom_wac->pad_input = NULL;
+		pad_input_dev = NULL;
+	} else {
+		error = input_register_device(pad_input_dev);
+		if (error)
+			goto fail3;
+	}
+
+	return 0;
+
+fail3:
+	input_unregister_device(input_dev);
+	input_dev = NULL;
+fail2:
+	wacom_wac->input = NULL;
+	wacom_wac->pad_input = NULL;
+fail1:
+	if (input_dev)
+		input_free_device(input_dev);
+	if (pad_input_dev)
+		input_free_device(pad_input_dev);
+	return error;
+}
+
+static void wacom_wireless_work(struct work_struct *work)
+{
+	struct wacom *wacom = container_of(work, struct wacom, work);
+	struct usb_device *usbdev = wacom->usbdev;
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct hid_device *hdev1, *hdev2;
+	struct wacom *wacom1, *wacom2;
+	struct wacom_wac *wacom_wac1, *wacom_wac2;
+	int error;
+
+	/*
+	 * Regardless if this is a disconnect or a new tablet,
+	 * remove any existing input and battery devices.
+	 */
+
+	wacom_destroy_battery(wacom);
+
+	/* Stylus interface */
+	hdev1 = usb_get_intfdata(usbdev->config->interface[1]);
+	wacom1 = hid_get_drvdata(hdev1);
+	wacom_wac1 = &(wacom1->wacom_wac);
+	wacom_unregister_inputs(wacom1);
+
+	/* Touch interface */
+	hdev2 = usb_get_intfdata(usbdev->config->interface[2]);
+	wacom2 = hid_get_drvdata(hdev2);
+	wacom_wac2 = &(wacom2->wacom_wac);
+	wacom_unregister_inputs(wacom2);
+
+	if (wacom_wac->pid == 0) {
+		hid_info(wacom->hdev, "wireless tablet disconnected\n");
+		wacom_wac1->shared->type = 0;
+	} else {
+		const struct hid_device_id *id = wacom_ids;
+
+		hid_info(wacom->hdev, "wireless tablet connected with PID %x\n",
+			 wacom_wac->pid);
+
+		while (id->bus) {
+			if (id->vendor == USB_VENDOR_ID_WACOM &&
+			    id->product == wacom_wac->pid)
+				break;
+			id++;
+		}
+
+		if (!id->bus) {
+			hid_info(wacom->hdev, "ignoring unknown PID.\n");
+			return;
+		}
+
+		/* Stylus interface */
+		wacom_wac1->features =
+			*((struct wacom_features *)id->driver_data);
+		wacom_wac1->features.device_type = BTN_TOOL_PEN;
+		snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
+			 wacom_wac1->features.name);
+		snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
+			 wacom_wac1->features.name);
+		wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
+		wacom_wac1->shared->type = wacom_wac1->features.type;
+		error = wacom_register_inputs(wacom1);
+		if (error)
+			goto fail;
+
+		/* Touch interface */
+		if (wacom_wac1->features.touch_max ||
+		    wacom_wac1->features.type == INTUOSHT) {
+			wacom_wac2->features =
+				*((struct wacom_features *)id->driver_data);
+			wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
+			wacom_wac2->features.device_type = BTN_TOOL_FINGER;
+			wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
+			if (wacom_wac2->features.touch_max)
+				snprintf(wacom_wac2->name, WACOM_NAME_MAX,
+					 "%s (WL) Finger",wacom_wac2->features.name);
+			else
+				snprintf(wacom_wac2->name, WACOM_NAME_MAX,
+					 "%s (WL) Pad",wacom_wac2->features.name);
+			snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
+				 "%s (WL) Pad", wacom_wac2->features.name);
+			error = wacom_register_inputs(wacom2);
+			if (error)
+				goto fail;
+
+			if (wacom_wac1->features.type == INTUOSHT &&
+			    wacom_wac1->features.touch_max)
+				wacom_wac->shared->touch_input = wacom_wac2->input;
+		}
+
+		error = wacom_initialize_battery(wacom);
+		if (error)
+			goto fail;
+	}
+
+	return;
+
+fail:
+	wacom_unregister_inputs(wacom1);
+	wacom_unregister_inputs(wacom2);
+	return;
+}
+
+/*
+ * Not all devices report physical dimensions from HID.
+ * Compute the default from hardcoded logical dimension
+ * and resolution before driver overwrites them.
+ */
+static void wacom_set_default_phy(struct wacom_features *features)
+{
+	if (features->x_resolution) {
+		features->x_phy = (features->x_max * 100) /
+					features->x_resolution;
+		features->y_phy = (features->y_max * 100) /
+					features->y_resolution;
+	}
+}
+
+static void wacom_calculate_res(struct wacom_features *features)
+{
+	features->x_resolution = wacom_calc_hid_res(features->x_max,
+						    features->x_phy,
+						    features->unit,
+						    features->unitExpo);
+	features->y_resolution = wacom_calc_hid_res(features->y_max,
+						    features->y_phy,
+						    features->unit,
+						    features->unitExpo);
+}
+
+static int wacom_hid_report_len(struct hid_report *report)
+{
+	/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
+	return ((report->size - 1) >> 3) + 1 + (report->id > 0);
+}
+
+static size_t wacom_compute_pktlen(struct hid_device *hdev)
+{
+	struct hid_report_enum *report_enum;
+	struct hid_report *report;
+	size_t size = 0;
+
+	report_enum = hdev->report_enum + HID_INPUT_REPORT;
+
+	list_for_each_entry(report, &report_enum->report_list, list) {
+		size_t report_size = wacom_hid_report_len(report);
+		if (report_size > size)
+			size = report_size;
+	}
+
+	return size;
+}
+
+static int wacom_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct wacom *wacom;
+	struct wacom_wac *wacom_wac;
+	struct wacom_features *features;
+	int error;
+
+	if (!id->driver_data)
+		return -EINVAL;
+
+	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+	if (!wacom)
+		return -ENOMEM;
+
+	hid_set_drvdata(hdev, wacom);
+	wacom->hdev = hdev;
+
+	/* ask for the report descriptor to be loaded by HID */
+	error = hid_parse(hdev);
+	if (error) {
+		hid_err(hdev, "parse failed\n");
+		goto fail1;
+	}
+
+	wacom_wac = &wacom->wacom_wac;
+	wacom_wac->features = *((struct wacom_features *)id->driver_data);
+	features = &wacom_wac->features;
+	features->pktlen = wacom_compute_pktlen(hdev);
+	if (features->pktlen > WACOM_PKGLEN_MAX) {
+		error = -EINVAL;
+		goto fail1;
+	}
+
+	if (features->check_for_hid_type && features->hid_type != hdev->type) {
+		error = -ENODEV;
+		goto fail1;
+	}
+
+	wacom->usbdev = dev;
+	wacom->intf = intf;
+	mutex_init(&wacom->lock);
+	INIT_WORK(&wacom->work, wacom_wireless_work);
+
+	/* set the default size in case we do not get them from hid */
+	wacom_set_default_phy(features);
+
+	/* Retrieve the physical and logical size for touch devices */
+	wacom_retrieve_hid_descriptor(hdev, features);
+
+	/*
+	 * Intuos5 has no useful data about its touch interface in its
+	 * HID descriptor. If this is the touch interface (PacketSize
+	 * of WACOM_PKGLEN_BBTOUCH3), override the table values.
+	 */
+	if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
+		if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
+			features->device_type = BTN_TOOL_FINGER;
+
+			features->x_max = 4096;
+			features->y_max = 4096;
+		} else {
+			features->device_type = BTN_TOOL_PEN;
+		}
+	}
+
+	/*
+	 * Same thing for Bamboo 3rd gen.
+	 */
+	if ((features->type == BAMBOO_PT) &&
+	    (features->pktlen == WACOM_PKGLEN_BBTOUCH3) &&
+	    (features->device_type == BTN_TOOL_PEN)) {
+		features->device_type = BTN_TOOL_FINGER;
+
+		features->x_max = 4096;
+		features->y_max = 4096;
+	}
+
+	if (hdev->bus == BUS_BLUETOOTH)
+		features->quirks |= WACOM_QUIRK_BATTERY;
+
+	wacom_setup_device_quirks(features);
+
+	/* set unit to "100th of a mm" for devices not reported by HID */
+	if (!features->unit) {
+		features->unit = 0x11;
+		features->unitExpo = -3;
+	}
+	wacom_calculate_res(features);
+
+	strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
+	snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name),
+		"%s Pad", features->name);
+
+	if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+		/* Append the device type to the name */
+		if (features->device_type != BTN_TOOL_FINGER)
+			strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
+		else if (features->touch_max)
+			strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX);
+		else
+			strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
+
+		error = wacom_add_shared_data(hdev);
+		if (error)
+			goto fail1;
+	}
+
+	error = wacom_initialize_leds(wacom);
+	if (error)
+		goto fail2;
+
+	if (!(features->quirks & WACOM_QUIRK_MONITOR) &&
+	     (features->quirks & WACOM_QUIRK_BATTERY)) {
+		error = wacom_initialize_battery(wacom);
+		if (error)
+			goto fail3;
+	}
+
+	if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
+		error = wacom_register_inputs(wacom);
+		if (error)
+			goto fail4;
+	}
+
+	if (hdev->bus == BUS_BLUETOOTH) {
+		error = device_create_file(&hdev->dev, &dev_attr_speed);
+		if (error)
+			hid_warn(hdev,
+				 "can't create sysfs speed attribute err: %d\n",
+				 error);
+	}
+
+	/* Note that if query fails it is not a hard failure */
+	wacom_query_tablet_data(hdev, features);
+
+	/* Regular HID work starts now */
+	error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (error) {
+		hid_err(hdev, "hw start failed\n");
+		goto fail5;
+	}
+
+	if (features->quirks & WACOM_QUIRK_MONITOR)
+		error = hid_hw_open(hdev);
+
+	if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) {
+		if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
+			wacom_wac->shared->touch_input = wacom_wac->input;
+	}
+
+	return 0;
+
+ fail5:	if (hdev->bus == BUS_BLUETOOTH)
+		device_remove_file(&hdev->dev, &dev_attr_speed);
+	wacom_unregister_inputs(wacom);
+ fail4:	wacom_destroy_battery(wacom);
+ fail3:	wacom_destroy_leds(wacom);
+ fail2:	wacom_remove_shared_data(wacom_wac);
+ fail1:	kfree(wacom);
+	hid_set_drvdata(hdev, NULL);
+	return error;
+}
+
+static void wacom_remove(struct hid_device *hdev)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+
+	hid_hw_stop(hdev);
+
+	cancel_work_sync(&wacom->work);
+	wacom_unregister_inputs(wacom);
+	if (hdev->bus == BUS_BLUETOOTH)
+		device_remove_file(&hdev->dev, &dev_attr_speed);
+	wacom_destroy_battery(wacom);
+	wacom_destroy_leds(wacom);
+	wacom_remove_shared_data(&wacom->wacom_wac);
+
+	hid_set_drvdata(hdev, NULL);
+	kfree(wacom);
+}
+
+#ifdef CONFIG_PM
+static int wacom_resume(struct hid_device *hdev)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_features *features = &wacom->wacom_wac.features;
+
+	mutex_lock(&wacom->lock);
+
+	/* switch to wacom mode first */
+	wacom_query_tablet_data(hdev, features);
+	wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return 0;
+}
+
+static int wacom_reset_resume(struct hid_device *hdev)
+{
+	return wacom_resume(hdev);
+}
+#endif /* CONFIG_PM */
+
+static struct hid_driver wacom_driver = {
+	.name =		"wacom",
+	.id_table =	wacom_ids,
+	.probe =	wacom_probe,
+	.remove =	wacom_remove,
+#ifdef CONFIG_PM
+	.resume =	wacom_resume,
+	.reset_resume =	wacom_reset_resume,
+#endif
+	.raw_event =	wacom_raw_event,
+};
+module_hid_driver(wacom_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/wacom_wac.c linux-libre-3.17-rc7-gnu/drivers/hid/wacom_wac.c
--- linux-libre-3.16-gnu/drivers/hid/wacom_wac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/wacom_wac.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2721 @@
+/*
+ * drivers/input/tablet/wacom_wac.c
+ *
+ *  USB Wacom tablet support - Wacom specific code
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "wacom_wac.h"
+#include "wacom.h"
+#include <linux/input/mt.h>
+#include <linux/hid.h>
+
+/* resolution for penabled devices */
+#define WACOM_PL_RES		20
+#define WACOM_PENPRTN_RES	40
+#define WACOM_VOLITO_RES	50
+#define WACOM_GRAPHIRE_RES	80
+#define WACOM_INTUOS_RES	100
+#define WACOM_INTUOS3_RES	200
+
+/*
+ * Scale factor relating reported contact size to logical contact area.
+ * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
+ */
+#define WACOM_CONTACT_AREA_SCALE 2607
+
+/*
+ * Percent of battery capacity for Graphire.
+ * 8th value means AC online and show 100% capacity.
+ */
+static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
+
+/*
+ * Percent of battery capacity for Intuos4 WL, AC has a separate bit.
+ */
+static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
+
+static int wacom_penpartner_irq(struct wacom_wac *wacom)
+{
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+
+	switch (data[0]) {
+	case 1:
+		if (data[5] & 0x80) {
+			wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+			wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
+			input_report_key(input, wacom->tool[0], 1);
+			input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
+			input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
+			input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
+			input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
+			input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127));
+			input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
+		} else {
+			input_report_key(input, wacom->tool[0], 0);
+			input_report_abs(input, ABS_MISC, 0); /* report tool id */
+			input_report_abs(input, ABS_PRESSURE, -1);
+			input_report_key(input, BTN_TOUCH, 0);
+		}
+		break;
+
+	case 2:
+		input_report_key(input, BTN_TOOL_PEN, 1);
+		input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
+		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
+		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
+		input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
+		input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
+		input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
+		break;
+
+	default:
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d\n", __func__, data[0]);
+		return 0;
+        }
+
+	return 1;
+}
+
+static int wacom_pl_irq(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	int prox, pressure;
+
+	if (data[0] != WACOM_REPORT_PENABLED) {
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d\n", __func__, data[0]);
+		return 0;
+	}
+
+	prox = data[1] & 0x40;
+
+	if (prox) {
+		wacom->id[0] = ERASER_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 going from out of proximity into proximity select between the eraser
+		 * and the pen based on the state of the stylus2 button, choose eraser if
+		 * pressed else choose pen. if not a proximity change from out to in, send
+		 * an out of proximity for previous tool then a in for new tool.
+		 */
+		if (!wacom->tool[0]) {
+			/* Eraser bit set for DTF */
+			if (data[1] & 0x10)
+				wacom->tool[1] = BTN_TOOL_RUBBER;
+			else
+				/* Going into proximity select tool */
+				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		} else {
+			/* was entered with stylus2 pressed */
+			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
+				/* report out proximity for previous tool */
+				input_report_key(input, wacom->tool[1], 0);
+				input_sync(input);
+				wacom->tool[1] = BTN_TOOL_PEN;
+				return 0;
+			}
+		}
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+			wacom->id[0] = STYLUS_DEVICE_ID;
+		}
+		input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */
+		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
+		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[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
+	} else {
+		/* report proximity-out of a (valid) tool */
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+		}
+		input_report_key(input, wacom->tool[1], prox);
+	}
+
+	wacom->tool[0] = prox; /* Save proximity state */
+	return 1;
+}
+
+static int wacom_ptu_irq(struct wacom_wac *wacom)
+{
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+
+	if (data[0] != WACOM_REPORT_PENABLED) {
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d\n", __func__, data[0]);
+		return 0;
+	}
+
+	if (data[1] & 0x04) {
+		input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20);
+		input_report_key(input, BTN_TOUCH, data[1] & 0x08);
+		wacom->id[0] = ERASER_DEVICE_ID;
+	} else {
+		input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20);
+		input_report_key(input, BTN_TOUCH, data[1] & 0x01);
+		wacom->id[0] = STYLUS_DEVICE_ID;
+	}
+	input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
+	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
+	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
+	input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
+	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
+	return 1;
+}
+
+static int wacom_dtu_irq(struct wacom_wac *wacom)
+{
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	int prox = data[1] & 0x20;
+
+	dev_dbg(input->dev.parent,
+		"%s: received report #%d", __func__, data[0]);
+
+	if (prox) {
+		/* Going into proximity select tool */
+		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		if (wacom->tool[0] == BTN_TOOL_PEN)
+			wacom->id[0] = STYLUS_DEVICE_ID;
+		else
+			wacom->id[0] = ERASER_DEVICE_ID;
+	}
+	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
+	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
+	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
+	input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
+	input_report_key(input, BTN_TOUCH, data[1] & 0x05);
+	if (!prox) /* out-prox */
+		wacom->id[0] = 0;
+	input_report_key(input, wacom->tool[0], prox);
+	input_report_abs(input, ABS_MISC, wacom->id[0]);
+	return 1;
+}
+
+static int wacom_dtus_irq(struct wacom_wac *wacom)
+{
+	char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	unsigned short prox, pressure = 0;
+
+	if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) {
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d", __func__, data[0]);
+		return 0;
+	} else if (data[0] == WACOM_REPORT_DTUSPAD) {
+		input = wacom->pad_input;
+		input_report_key(input, BTN_0, (data[1] & 0x01));
+		input_report_key(input, BTN_1, (data[1] & 0x02));
+		input_report_key(input, BTN_2, (data[1] & 0x04));
+		input_report_key(input, BTN_3, (data[1] & 0x08));
+		input_report_abs(input, ABS_MISC,
+				 data[1] & 0x0f ? PAD_DEVICE_ID : 0);
+		return 1;
+	} else {
+		prox = data[1] & 0x80;
+		if (prox) {
+			switch ((data[1] >> 3) & 3) {
+			case 1: /* Rubber */
+				wacom->tool[0] = BTN_TOOL_RUBBER;
+				wacom->id[0] = ERASER_DEVICE_ID;
+				break;
+
+			case 2: /* Pen */
+				wacom->tool[0] = BTN_TOOL_PEN;
+				wacom->id[0] = STYLUS_DEVICE_ID;
+				break;
+			}
+		}
+
+		input_report_key(input, BTN_STYLUS, data[1] & 0x20);
+		input_report_key(input, BTN_STYLUS2, data[1] & 0x40);
+		input_report_abs(input, ABS_X, get_unaligned_be16(&data[3]));
+		input_report_abs(input, ABS_Y, get_unaligned_be16(&data[5]));
+		pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff);
+		input_report_abs(input, ABS_PRESSURE, pressure);
+		input_report_key(input, BTN_TOUCH, pressure > 10);
+
+		if (!prox) /* out-prox */
+			wacom->id[0] = 0;
+		input_report_key(input, wacom->tool[0], prox);
+		input_report_abs(input, ABS_MISC, wacom->id[0]);
+		return 1;
+	}
+}
+
+static int wacom_graphire_irq(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	struct input_dev *pad_input = wacom->pad_input;
+	int battery_capacity, ps_connected;
+	int prox;
+	int rw = 0;
+	int retval = 0;
+
+	if (features->type == GRAPHIRE_BT) {
+		if (data[0] != WACOM_REPORT_PENABLED_BT) {
+			dev_dbg(input->dev.parent,
+				"%s: received unknown report #%d\n", __func__,
+				data[0]);
+			goto exit;
+		}
+	} else if (data[0] != WACOM_REPORT_PENABLED) {
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d\n", __func__, data[0]);
+		goto exit;
+	}
+
+	prox = data[1] & 0x80;
+	if (prox || wacom->id[0]) {
+		if (prox) {
+			switch ((data[1] >> 5) & 3) {
+
+			case 0:	/* Pen */
+				wacom->tool[0] = BTN_TOOL_PEN;
+				wacom->id[0] = STYLUS_DEVICE_ID;
+				break;
+
+			case 1: /* Rubber */
+				wacom->tool[0] = BTN_TOOL_RUBBER;
+				wacom->id[0] = ERASER_DEVICE_ID;
+				break;
+
+			case 2: /* Mouse with wheel */
+				input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
+				/* fall through */
+
+			case 3: /* Mouse without wheel */
+				wacom->tool[0] = BTN_TOOL_MOUSE;
+				wacom->id[0] = CURSOR_DEVICE_ID;
+				break;
+			}
+		}
+		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
+		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
+		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+			if (features->type == GRAPHIRE_BT)
+				input_report_abs(input, ABS_PRESSURE, data[6] |
+					(((__u16) (data[1] & 0x08)) << 5));
+			else
+				input_report_abs(input, ABS_PRESSURE, data[6] |
+					((data[7] & 0x03) << 8));
+			input_report_key(input, BTN_TOUCH, data[1] & 0x01);
+			input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+			input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
+		} else {
+			input_report_key(input, BTN_LEFT, data[1] & 0x01);
+			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
+			if (features->type == WACOM_G4 ||
+					features->type == WACOM_MO) {
+				input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
+				rw = (data[7] & 0x04) - (data[7] & 0x03);
+			} else if (features->type == GRAPHIRE_BT) {
+				/* Compute distance between mouse and tablet */
+				rw = 44 - (data[6] >> 2);
+				rw = clamp_val(rw, 0, 31);
+				input_report_abs(input, ABS_DISTANCE, rw);
+				if (((data[1] >> 5) & 3) == 2) {
+					/* Mouse with wheel */
+					input_report_key(input, BTN_MIDDLE,
+							data[1] & 0x04);
+					rw = (data[6] & 0x01) ? -1 :
+						(data[6] & 0x02) ? 1 : 0;
+				} else {
+					rw = 0;
+				}
+			} else {
+				input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
+				rw = -(signed char)data[6];
+			}
+			input_report_rel(input, REL_WHEEL, rw);
+		}
+
+		if (!prox)
+			wacom->id[0] = 0;
+		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
+		input_report_key(input, wacom->tool[0], prox);
+		input_sync(input); /* sync last event */
+	}
+
+	/* send pad data */
+	switch (features->type) {
+	case WACOM_G4:
+		prox = data[7] & 0xf8;
+		if (prox || wacom->id[1]) {
+			wacom->id[1] = PAD_DEVICE_ID;
+			input_report_key(pad_input, BTN_BACK, (data[7] & 0x40));
+			input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x80));
+			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
+			input_report_rel(pad_input, REL_WHEEL, rw);
+			if (!prox)
+				wacom->id[1] = 0;
+			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
+			retval = 1;
+		}
+		break;
+
+	case WACOM_MO:
+		prox = (data[7] & 0xf8) || data[8];
+		if (prox || wacom->id[1]) {
+			wacom->id[1] = PAD_DEVICE_ID;
+			input_report_key(pad_input, BTN_BACK, (data[7] & 0x08));
+			input_report_key(pad_input, BTN_LEFT, (data[7] & 0x20));
+			input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x10));
+			input_report_key(pad_input, BTN_RIGHT, (data[7] & 0x40));
+			input_report_abs(pad_input, ABS_WHEEL, (data[8] & 0x7f));
+			if (!prox)
+				wacom->id[1] = 0;
+			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
+			retval = 1;
+		}
+		break;
+	case GRAPHIRE_BT:
+		prox = data[7] & 0x03;
+		if (prox || wacom->id[1]) {
+			wacom->id[1] = PAD_DEVICE_ID;
+			input_report_key(pad_input, BTN_0, (data[7] & 0x02));
+			input_report_key(pad_input, BTN_1, (data[7] & 0x01));
+			if (!prox)
+				wacom->id[1] = 0;
+			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
+			retval = 1;
+		}
+		break;
+	}
+
+	/* Store current battery capacity and power supply state */
+	if (features->type == GRAPHIRE_BT) {
+		rw = (data[7] >> 2 & 0x07);
+		battery_capacity = batcap_gr[rw];
+		ps_connected = rw == 7;
+		if ((wacom->battery_capacity != battery_capacity) ||
+		    (wacom->ps_connected != ps_connected)) {
+			wacom->battery_capacity = battery_capacity;
+			wacom->ps_connected = ps_connected;
+			wacom_notify_battery(wacom);
+		}
+	}
+exit:
+	return retval;
+}
+
+static int wacom_intuos_inout(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	int idx = 0;
+
+	/* tool number */
+	if (features->type == INTUOS)
+		idx = data[1] & 0x01;
+
+	/* Enter report */
+	if ((data[1] & 0xfc) == 0xc0) {
+		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+			wacom->shared->stylus_in_proximity = true;
+
+		/* serial number of the tool */
+		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+			(data[4] << 20) + (data[5] << 12) +
+			(data[6] << 4) + (data[7] >> 4);
+
+		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
+			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
+
+		switch (wacom->id[idx]) {
+		case 0x812: /* Inking pen */
+		case 0x801: /* Intuos3 Inking pen */
+		case 0x120802: /* Intuos4/5 Inking Pen */
+		case 0x012:
+			wacom->tool[idx] = BTN_TOOL_PENCIL;
+			break;
+
+		case 0x822: /* Pen */
+		case 0x842:
+		case 0x852:
+		case 0x823: /* Intuos3 Grip Pen */
+		case 0x813: /* Intuos3 Classic Pen */
+		case 0x885: /* Intuos3 Marker Pen */
+		case 0x802: /* Intuos4/5 13HD/24HD General Pen */
+		case 0x804: /* Intuos4/5 13HD/24HD Marker 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 */
+			wacom->tool[idx] = BTN_TOOL_PEN;
+			break;
+
+		case 0x832: /* Stroke pen */
+		case 0x032:
+			wacom->tool[idx] = BTN_TOOL_BRUSH;
+			break;
+
+		case 0x007: /* Mouse 4D and 2D */
+		case 0x09c:
+		case 0x094:
+		case 0x017: /* Intuos3 2D Mouse */
+		case 0x806: /* Intuos4 Mouse */
+			wacom->tool[idx] = BTN_TOOL_MOUSE;
+			break;
+
+		case 0x096: /* Lens cursor */
+		case 0x097: /* Intuos3 Lens cursor */
+		case 0x006: /* Intuos4 Lens cursor */
+			wacom->tool[idx] = BTN_TOOL_LENS;
+			break;
+
+		case 0x82a: /* Eraser */
+		case 0x85a:
+		case 0x91a:
+		case 0xd1a:
+		case 0x0fa:
+		case 0x82b: /* Intuos3 Grip Pen Eraser */
+		case 0x81b: /* Intuos3 Classic Pen Eraser */
+		case 0x91b: /* Intuos3 Airbrush Eraser */
+		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 */
+			wacom->tool[idx] = BTN_TOOL_RUBBER;
+			break;
+
+		case 0xd12:
+		case 0x912:
+		case 0x112:
+		case 0x913: /* Intuos3 Airbrush */
+		case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
+		case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
+			wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+			break;
+
+		default: /* Unknown tool */
+			wacom->tool[idx] = BTN_TOOL_PEN;
+			break;
+		}
+		return 1;
+	}
+
+	/* older I4 styli don't work with new Cintiqs */
+	if (!((wacom->id[idx] >> 20) & 0x01) &&
+			(features->type == WACOM_21UX2))
+		return 1;
+
+	/* Range Report */
+	if ((data[1] & 0xfe) == 0x20) {
+		input_report_key(input, BTN_TOUCH, 0);
+		input_report_abs(input, ABS_PRESSURE, 0);
+		input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
+		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+			wacom->shared->stylus_in_proximity = true;
+	}
+
+	/* Exit report */
+	if ((data[1] & 0xfe) == 0x80) {
+		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+			wacom->shared->stylus_in_proximity = false;
+
+		/*
+		 * Reset all states otherwise we lose the initial states
+		 * when in-prox next time
+		 */
+		input_report_abs(input, ABS_X, 0);
+		input_report_abs(input, ABS_Y, 0);
+		input_report_abs(input, ABS_DISTANCE, 0);
+		input_report_abs(input, ABS_TILT_X, 0);
+		input_report_abs(input, ABS_TILT_Y, 0);
+		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
+			input_report_key(input, BTN_LEFT, 0);
+			input_report_key(input, BTN_MIDDLE, 0);
+			input_report_key(input, BTN_RIGHT, 0);
+			input_report_key(input, BTN_SIDE, 0);
+			input_report_key(input, BTN_EXTRA, 0);
+			input_report_abs(input, ABS_THROTTLE, 0);
+			input_report_abs(input, ABS_RZ, 0);
+		} else {
+			input_report_abs(input, ABS_PRESSURE, 0);
+			input_report_key(input, BTN_STYLUS, 0);
+			input_report_key(input, BTN_STYLUS2, 0);
+			input_report_key(input, BTN_TOUCH, 0);
+			input_report_abs(input, ABS_WHEEL, 0);
+			if (features->type >= INTUOS3S)
+				input_report_abs(input, ABS_Z, 0);
+		}
+		input_report_key(input, wacom->tool[idx], 0);
+		input_report_abs(input, ABS_MISC, 0); /* reset tool id */
+		input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		wacom->id[idx] = 0;
+		return 2;
+	}
+	return 0;
+}
+
+static void wacom_intuos_general(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	unsigned int t;
+
+	/* general pen packet */
+	if ((data[1] & 0xb8) == 0xa0) {
+		t = (data[6] << 2) | ((data[7] >> 6) & 3);
+		if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) {
+			t = (t << 1) | (data[1] & 1);
+		}
+		input_report_abs(input, ABS_PRESSURE, t);
+		input_report_abs(input, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+		input_report_key(input, BTN_STYLUS, data[1] & 2);
+		input_report_key(input, BTN_STYLUS2, data[1] & 4);
+		input_report_key(input, BTN_TOUCH, t > 10);
+	}
+
+	/* airbrush second packet */
+	if ((data[1] & 0xbc) == 0xb4) {
+		input_report_abs(input, ABS_WHEEL,
+				(data[6] << 2) | ((data[7] >> 6) & 3));
+		input_report_abs(input, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+	}
+}
+
+static int wacom_intuos_irq(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	unsigned int t;
+	int idx = 0, result;
+
+	if (data[0] != WACOM_REPORT_PENABLED &&
+	    data[0] != WACOM_REPORT_INTUOSREAD &&
+	    data[0] != WACOM_REPORT_INTUOSWRITE &&
+	    data[0] != WACOM_REPORT_INTUOSPAD &&
+	    data[0] != WACOM_REPORT_INTUOS5PAD) {
+		dev_dbg(input->dev.parent,
+			"%s: received unknown report #%d\n", __func__, data[0]);
+                return 0;
+	}
+
+	/* tool number */
+	if (features->type == INTUOS)
+		idx = data[1] & 0x01;
+
+	/* pad packets. Works as a second tool and is always in prox */
+	if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
+		input = wacom->pad_input;
+		if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
+			input_report_key(input, BTN_0, (data[2] & 0x01));
+			input_report_key(input, BTN_1, (data[3] & 0x01));
+			input_report_key(input, BTN_2, (data[3] & 0x02));
+			input_report_key(input, BTN_3, (data[3] & 0x04));
+			input_report_key(input, BTN_4, (data[3] & 0x08));
+			input_report_key(input, BTN_5, (data[3] & 0x10));
+			input_report_key(input, BTN_6, (data[3] & 0x20));
+			if (data[1] & 0x80) {
+				input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
+			} else {
+				/* Out of proximity, clear wheel value. */
+				input_report_abs(input, ABS_WHEEL, 0);
+			}
+			if (features->type != INTUOS4S) {
+				input_report_key(input, BTN_7, (data[3] & 0x40));
+				input_report_key(input, BTN_8, (data[3] & 0x80));
+			}
+			if (data[1] | (data[2] & 0x01) | data[3]) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		} else if (features->type == DTK) {
+			input_report_key(input, BTN_0, (data[6] & 0x01));
+			input_report_key(input, BTN_1, (data[6] & 0x02));
+			input_report_key(input, BTN_2, (data[6] & 0x04));
+			input_report_key(input, BTN_3, (data[6] & 0x08));
+			input_report_key(input, BTN_4, (data[6] & 0x10));
+			input_report_key(input, BTN_5, (data[6] & 0x20));
+			if (data[6] & 0x3f) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		} else if (features->type == WACOM_13HD) {
+			input_report_key(input, BTN_0, (data[3] & 0x01));
+			input_report_key(input, BTN_1, (data[4] & 0x01));
+			input_report_key(input, BTN_2, (data[4] & 0x02));
+			input_report_key(input, BTN_3, (data[4] & 0x04));
+			input_report_key(input, BTN_4, (data[4] & 0x08));
+			input_report_key(input, BTN_5, (data[4] & 0x10));
+			input_report_key(input, BTN_6, (data[4] & 0x20));
+			input_report_key(input, BTN_7, (data[4] & 0x40));
+			input_report_key(input, BTN_8, (data[4] & 0x80));
+			if ((data[3] & 0x01) | data[4]) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		} else if (features->type == WACOM_24HD) {
+			input_report_key(input, BTN_0, (data[6] & 0x01));
+			input_report_key(input, BTN_1, (data[6] & 0x02));
+			input_report_key(input, BTN_2, (data[6] & 0x04));
+			input_report_key(input, BTN_3, (data[6] & 0x08));
+			input_report_key(input, BTN_4, (data[6] & 0x10));
+			input_report_key(input, BTN_5, (data[6] & 0x20));
+			input_report_key(input, BTN_6, (data[6] & 0x40));
+			input_report_key(input, BTN_7, (data[6] & 0x80));
+			input_report_key(input, BTN_8, (data[8] & 0x01));
+			input_report_key(input, BTN_9, (data[8] & 0x02));
+			input_report_key(input, BTN_A, (data[8] & 0x04));
+			input_report_key(input, BTN_B, (data[8] & 0x08));
+			input_report_key(input, BTN_C, (data[8] & 0x10));
+			input_report_key(input, BTN_X, (data[8] & 0x20));
+			input_report_key(input, BTN_Y, (data[8] & 0x40));
+			input_report_key(input, BTN_Z, (data[8] & 0x80));
+
+			/*
+			 * Three "buttons" are available on the 24HD which are
+			 * physically implemented as a touchstrip. Each button
+			 * is approximately 3 bits wide with a 2 bit spacing.
+			 * The raw touchstrip bits are stored at:
+			 *    ((data[3] & 0x1f) << 8) | data[4])
+			 */
+			input_report_key(input, KEY_PROG1, data[4] & 0x07);
+			input_report_key(input, KEY_PROG2, data[4] & 0xE0);
+			input_report_key(input, KEY_PROG3, data[3] & 0x1C);
+
+			if (data[1] & 0x80) {
+				input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
+			} else {
+				/* Out of proximity, clear wheel value. */
+				input_report_abs(input, ABS_WHEEL, 0);
+			}
+
+			if (data[2] & 0x80) {
+				input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
+			} else {
+				/* Out of proximity, clear second wheel value. */
+				input_report_abs(input, ABS_THROTTLE, 0);
+			}
+
+			if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		} else if (features->type == CINTIQ_HYBRID) {
+			/*
+			 * Do not send hardware buttons under Android. They
+			 * are already sent to the system through GPIO (and
+			 * have different meaning).
+			 */
+			input_report_key(input, BTN_1, (data[4] & 0x01));
+			input_report_key(input, BTN_2, (data[4] & 0x02));
+			input_report_key(input, BTN_3, (data[4] & 0x04));
+			input_report_key(input, BTN_4, (data[4] & 0x08));
+
+			input_report_key(input, BTN_5, (data[4] & 0x10));  /* Right  */
+			input_report_key(input, BTN_6, (data[4] & 0x20));  /* Up     */
+			input_report_key(input, BTN_7, (data[4] & 0x40));  /* Left   */
+			input_report_key(input, BTN_8, (data[4] & 0x80));  /* Down   */
+			input_report_key(input, BTN_0, (data[3] & 0x01));  /* Center */
+		} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
+			int i;
+
+			/* Touch ring mode switch has no capacitive sensor */
+			input_report_key(input, BTN_0, (data[3] & 0x01));
+
+			/*
+			 * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
+			 * addition to the mechanical switch. Switch data is
+			 * stored in data[4], capacitive data in data[5].
+			 */
+			for (i = 0; i < 8; i++)
+				input_report_key(input, BTN_1 + i, data[4] & (1 << i));
+
+			if (data[2] & 0x80) {
+				input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
+			} else {
+				/* Out of proximity, clear wheel value. */
+				input_report_abs(input, ABS_WHEEL, 0);
+			}
+
+			if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		} else {
+			if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
+				input_report_key(input, BTN_0, (data[5] & 0x01));
+				input_report_key(input, BTN_1, (data[6] & 0x01));
+				input_report_key(input, BTN_2, (data[6] & 0x02));
+				input_report_key(input, BTN_3, (data[6] & 0x04));
+				input_report_key(input, BTN_4, (data[6] & 0x08));
+				input_report_key(input, BTN_5, (data[6] & 0x10));
+				input_report_key(input, BTN_6, (data[6] & 0x20));
+				input_report_key(input, BTN_7, (data[6] & 0x40));
+				input_report_key(input, BTN_8, (data[6] & 0x80));
+				input_report_key(input, BTN_9, (data[7] & 0x01));
+				input_report_key(input, BTN_A, (data[8] & 0x01));
+				input_report_key(input, BTN_B, (data[8] & 0x02));
+				input_report_key(input, BTN_C, (data[8] & 0x04));
+				input_report_key(input, BTN_X, (data[8] & 0x08));
+				input_report_key(input, BTN_Y, (data[8] & 0x10));
+				input_report_key(input, BTN_Z, (data[8] & 0x20));
+				input_report_key(input, BTN_BASE, (data[8] & 0x40));
+				input_report_key(input, BTN_BASE2, (data[8] & 0x80));
+
+				if (features->type == WACOM_22HD) {
+					input_report_key(input, KEY_PROG1, data[9] & 0x01);
+					input_report_key(input, KEY_PROG2, data[9] & 0x02);
+					input_report_key(input, KEY_PROG3, data[9] & 0x04);
+				}
+			} else {
+				input_report_key(input, BTN_0, (data[5] & 0x01));
+				input_report_key(input, BTN_1, (data[5] & 0x02));
+				input_report_key(input, BTN_2, (data[5] & 0x04));
+				input_report_key(input, BTN_3, (data[5] & 0x08));
+				input_report_key(input, BTN_4, (data[6] & 0x01));
+				input_report_key(input, BTN_5, (data[6] & 0x02));
+				input_report_key(input, BTN_6, (data[6] & 0x04));
+				input_report_key(input, BTN_7, (data[6] & 0x08));
+				input_report_key(input, BTN_8, (data[5] & 0x10));
+				input_report_key(input, BTN_9, (data[6] & 0x10));
+			}
+			input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+			input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+			if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
+				data[2] | (data[3] & 0x1f) | data[4] | data[8] |
+				(data[7] & 0x01)) {
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_abs(input, ABS_MISC, 0);
+			}
+		}
+                return 1;
+	}
+
+	/* process in/out prox events */
+	result = wacom_intuos_inout(wacom);
+	if (result)
+                return result - 1;
+
+	/* don't proceed if we don't know the ID */
+	if (!wacom->id[idx])
+		return 0;
+
+	/* Only large Intuos support Lense Cursor */
+	if (wacom->tool[idx] == BTN_TOOL_LENS &&
+	    (features->type == INTUOS3 ||
+	     features->type == INTUOS3S ||
+	     features->type == INTUOS4 ||
+	     features->type == INTUOS4S ||
+	     features->type == INTUOS5 ||
+	     features->type == INTUOS5S ||
+	     features->type == INTUOSPM ||
+	     features->type == INTUOSPS)) {
+
+		return 0;
+	}
+
+	/* Cintiq doesn't send data when RDY bit isn't set */
+	if (features->type == CINTIQ && !(data[1] & 0x40))
+                 return 0;
+
+	if (features->type >= INTUOS3S) {
+		input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
+		input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
+		input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+	} else {
+		input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
+		input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
+		input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
+	}
+
+	/* process general packets */
+	wacom_intuos_general(wacom);
+
+	/* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
+	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
+
+		if (data[1] & 0x02) {
+			/* Rotation packet */
+			if (features->type >= INTUOS3S) {
+				/* I3 marker pen rotation */
+				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+					((t-1) / 2 + 450)) : (450 - t / 2) ;
+				input_report_abs(input, ABS_Z, t);
+			} else {
+				/* 4D mouse rotation packet */
+				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+				input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
+					((t - 1) / 2) : -t / 2);
+			}
+
+		} else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
+			/* 4D mouse packet */
+			input_report_key(input, BTN_LEFT,   data[8] & 0x01);
+			input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
+			input_report_key(input, BTN_RIGHT,  data[8] & 0x04);
+
+			input_report_key(input, BTN_SIDE,   data[8] & 0x20);
+			input_report_key(input, BTN_EXTRA,  data[8] & 0x10);
+			t = (data[6] << 2) | ((data[7] >> 6) & 3);
+			input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
+
+		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
+			/* I4 mouse */
+			if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
+				input_report_key(input, BTN_LEFT,   data[6] & 0x01);
+				input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
+				input_report_key(input, BTN_RIGHT,  data[6] & 0x04);
+				input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
+						 - ((data[7] & 0x40) >> 6));
+				input_report_key(input, BTN_SIDE,   data[6] & 0x08);
+				input_report_key(input, BTN_EXTRA,  data[6] & 0x10);
+
+				input_report_abs(input, ABS_TILT_X,
+					((data[7] << 1) & 0x7e) | (data[8] >> 7));
+				input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
+			} else {
+				/* 2D mouse packet */
+				input_report_key(input, BTN_LEFT,   data[8] & 0x04);
+				input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
+				input_report_key(input, BTN_RIGHT,  data[8] & 0x10);
+				input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
+						 - ((data[8] & 0x02) >> 1));
+
+				/* I3 2D mouse side buttons */
+				if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
+					input_report_key(input, BTN_SIDE,   data[8] & 0x40);
+					input_report_key(input, BTN_EXTRA,  data[8] & 0x20);
+				}
+			}
+		} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
+				features->type == INTUOS4L || features->type == INTUOS5L ||
+				features->type == INTUOSPL) &&
+			   wacom->tool[idx] == BTN_TOOL_LENS) {
+			/* Lens cursor packets */
+			input_report_key(input, BTN_LEFT,   data[8] & 0x01);
+			input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
+			input_report_key(input, BTN_RIGHT,  data[8] & 0x04);
+			input_report_key(input, BTN_SIDE,   data[8] & 0x10);
+			input_report_key(input, BTN_EXTRA,  data[8] & 0x08);
+		}
+	}
+
+	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_key(input, wacom->tool[idx], 1);
+	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+	return 1;
+}
+
+static int int_dist(int x1, int y1, int x2, int y2)
+{
+	int x = x2 - x1;
+	int y = y2 - y1;
+
+	return int_sqrt(x*x + y*y);
+}
+
+static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
+		unsigned char *data)
+{
+	memcpy(wacom->data, data, 10);
+	wacom_intuos_irq(wacom);
+
+	input_sync(wacom->input);
+	if (wacom->pad_input)
+		input_sync(wacom->pad_input);
+}
+
+static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
+{
+	unsigned char data[WACOM_PKGLEN_MAX];
+	int i = 1;
+	unsigned power_raw, battery_capacity, bat_charging, ps_connected;
+
+	memcpy(data, wacom->data, len);
+
+	switch (data[0]) {
+	case 0x04:
+		wacom_intuos_bt_process_data(wacom, data + i);
+		i += 10;
+		/* fall through */
+	case 0x03:
+		wacom_intuos_bt_process_data(wacom, data + i);
+		i += 10;
+		wacom_intuos_bt_process_data(wacom, data + i);
+		i += 10;
+		power_raw = data[i];
+		bat_charging = (power_raw & 0x08) ? 1 : 0;
+		ps_connected = (power_raw & 0x10) ? 1 : 0;
+		battery_capacity = batcap_i4[power_raw & 0x07];
+		if ((wacom->battery_capacity != battery_capacity) ||
+		    (wacom->bat_charging != bat_charging) ||
+		    (wacom->ps_connected != ps_connected)) {
+			wacom->battery_capacity = battery_capacity;
+			wacom->bat_charging = bat_charging;
+			wacom->ps_connected = ps_connected;
+			wacom_notify_battery(wacom);
+		}
+
+		break;
+	default:
+		dev_dbg(wacom->input->dev.parent,
+				"Unknown report: %d,%d size:%zu\n",
+				data[0], data[1], len);
+		return 0;
+	}
+	return 0;
+}
+
+static int wacom_24hdt_irq(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int i;
+	int current_num_contacts = data[61];
+	int contacts_to_send = 0;
+
+	/*
+	 * First packet resets the counter since only the first
+	 * packet in series will have non-zero current_num_contacts.
+	 */
+	if (current_num_contacts)
+		wacom->num_contacts_left = current_num_contacts;
+
+	/* There are at most 4 contacts per packet */
+	contacts_to_send = min(4, wacom->num_contacts_left);
+
+	for (i = 0; i < contacts_to_send; i++) {
+		int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
+		bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+		int slot = input_mt_get_slot_by_key(input, data[offset + 1]);
+
+		if (slot < 0)
+			continue;
+		input_mt_slot(input, slot);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+		if (touch) {
+			int t_x = get_unaligned_le16(&data[offset + 2]);
+			int c_x = get_unaligned_le16(&data[offset + 4]);
+			int t_y = get_unaligned_le16(&data[offset + 6]);
+			int c_y = get_unaligned_le16(&data[offset + 8]);
+			int w = get_unaligned_le16(&data[offset + 10]);
+			int h = get_unaligned_le16(&data[offset + 12]);
+
+			input_report_abs(input, ABS_MT_POSITION_X, t_x);
+			input_report_abs(input, ABS_MT_POSITION_Y, t_y);
+			input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+			input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+			input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+			input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+		}
+	}
+	input_mt_report_pointer_emulation(input, true);
+
+	wacom->num_contacts_left -= contacts_to_send;
+	if (wacom->num_contacts_left <= 0)
+		wacom->num_contacts_left = 0;
+
+	return 1;
+}
+
+static int wacom_mt_touch(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int i;
+	int current_num_contacts = data[2];
+	int contacts_to_send = 0;
+	int x_offset = 0;
+
+	/* MTTPC does not support Height and Width */
+	if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
+		x_offset = -4;
+
+	/*
+	 * First packet resets the counter since only the first
+	 * packet in series will have non-zero current_num_contacts.
+	 */
+	if (current_num_contacts)
+		wacom->num_contacts_left = current_num_contacts;
+
+	/* There are at most 5 contacts per packet */
+	contacts_to_send = min(5, wacom->num_contacts_left);
+
+	for (i = 0; i < contacts_to_send; i++) {
+		int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3;
+		bool touch = data[offset] & 0x1;
+		int id = get_unaligned_le16(&data[offset + 1]);
+		int slot = input_mt_get_slot_by_key(input, id);
+
+		if (slot < 0)
+			continue;
+
+		input_mt_slot(input, slot);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+		if (touch) {
+			int x = get_unaligned_le16(&data[offset + x_offset + 7]);
+			int y = get_unaligned_le16(&data[offset + x_offset + 9]);
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+		}
+	}
+	input_mt_report_pointer_emulation(input, true);
+
+	wacom->num_contacts_left -= contacts_to_send;
+	if (wacom->num_contacts_left < 0)
+		wacom->num_contacts_left = 0;
+
+	return 1;
+}
+
+static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int contact_with_no_pen_down_count = 0;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		int p = data[1] & (1 << i);
+		bool touch = p && !wacom->shared->stylus_in_proximity;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+		if (touch) {
+			int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
+			int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
+
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+			contact_with_no_pen_down_count++;
+		}
+	}
+	input_mt_report_pointer_emulation(input, true);
+
+	/* keep touch state for pen event */
+	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+
+	return 1;
+}
+
+static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
+{
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	bool prox;
+	int x = 0, y = 0;
+
+	if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
+		return 0;
+
+	if (!wacom->shared->stylus_in_proximity) {
+		if (len == WACOM_PKGLEN_TPC1FG) {
+			prox = data[0] & 0x01;
+			x = get_unaligned_le16(&data[1]);
+			y = get_unaligned_le16(&data[3]);
+		} else if (len == WACOM_PKGLEN_TPC1FG_B) {
+			prox = data[2] & 0x01;
+			x = get_unaligned_le16(&data[3]);
+			y = get_unaligned_le16(&data[5]);
+		} else {
+			prox = data[1] & 0x01;
+			x = le16_to_cpup((__le16 *)&data[2]);
+			y = le16_to_cpup((__le16 *)&data[4]);
+		}
+	} else
+		/* force touch out when pen is in prox */
+		prox = 0;
+
+	if (prox) {
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+	}
+	input_report_key(input, BTN_TOUCH, prox);
+
+	/* keep touch state for pen events */
+	wacom->shared->touch_down = prox;
+
+	return 1;
+}
+
+static int wacom_tpc_pen(struct wacom_wac *wacom)
+{
+	unsigned char *data = wacom->data;
+	struct input_dev *input = wacom->input;
+	bool prox = data[1] & 0x20;
+
+	if (!wacom->shared->stylus_in_proximity) /* first in prox */
+		/* Going into proximity select tool */
+		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+
+	/* keep pen state for touch events */
+	wacom->shared->stylus_in_proximity = prox;
+
+	/* send pen events only when touch is up or forced out */
+	if (!wacom->shared->touch_down) {
+		input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
+		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
+		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
+		input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x07) << 8) | data[6]);
+		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
+		input_report_key(input, wacom->tool[0], prox);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+{
+	unsigned char *data = wacom->data;
+
+	dev_dbg(wacom->input->dev.parent,
+		"%s: received report #%d\n", __func__, data[0]);
+
+	switch (len) {
+	case WACOM_PKGLEN_TPC1FG:
+		return wacom_tpc_single_touch(wacom, len);
+
+	case WACOM_PKGLEN_TPC2FG:
+		return wacom_tpc_mt_touch(wacom);
+
+	case WACOM_PKGLEN_PENABLED:
+		return wacom_tpc_pen(wacom);
+
+	default:
+		switch (data[0]) {
+		case WACOM_REPORT_TPC1FG:
+		case WACOM_REPORT_TPCHID:
+		case WACOM_REPORT_TPCST:
+		case WACOM_REPORT_TPC1FGE:
+			return wacom_tpc_single_touch(wacom, len);
+
+		case WACOM_REPORT_TPCMT:
+		case WACOM_REPORT_TPCMT2:
+			return wacom_mt_touch(wacom);
+
+		case WACOM_REPORT_PENABLED:
+			return wacom_tpc_pen(wacom);
+		}
+	}
+
+	return 0;
+}
+
+static int wacom_bpt_touch(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	struct input_dev *input = wacom->input;
+	struct input_dev *pad_input = wacom->pad_input;
+	unsigned char *data = wacom->data;
+	int i;
+
+	if (data[0] != 0x02)
+	    return 0;
+
+	for (i = 0; i < 2; i++) {
+		int offset = (data[1] & 0x80) ? (8 * i) : (9 * i);
+		bool touch = data[offset + 3] & 0x80;
+
+		/*
+		 * Touch events need to be disabled while stylus is
+		 * in proximity because user's hand is resting on touchpad
+		 * and sending unwanted events.  User expects tablet buttons
+		 * to continue working though.
+		 */
+		touch = touch && !wacom->shared->stylus_in_proximity;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+		if (touch) {
+			int x = get_unaligned_be16(&data[offset + 3]) & 0x7ff;
+			int y = get_unaligned_be16(&data[offset + 5]) & 0x7ff;
+			if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
+				x <<= 5;
+				y <<= 5;
+			}
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+		}
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+
+	input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0);
+	input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
+	input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
+	input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
+
+	return 1;
+}
+
+static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
+{
+	struct wacom_features *features = &wacom->features;
+	struct input_dev *input = wacom->input;
+	bool touch = data[1] & 0x80;
+	int slot = input_mt_get_slot_by_key(input, data[0]);
+
+	if (slot < 0)
+		return;
+
+	touch = touch && !wacom->shared->stylus_in_proximity;
+
+	input_mt_slot(input, slot);
+	input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+	if (touch) {
+		int x = (data[2] << 4) | (data[4] >> 4);
+		int y = (data[3] << 4) | (data[4] & 0x0f);
+		int width, height;
+
+		if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
+			width  = data[5] * 100;
+			height = data[6] * 100;
+		} else {
+			/*
+			 * "a" is a scaled-down area which we assume is
+			 * roughly circular and which can be described as:
+			 * a=(pi*r^2)/C.
+			 */
+			int a = data[5];
+			int x_res = input_abs_get_res(input, ABS_MT_POSITION_X);
+			int y_res = input_abs_get_res(input, ABS_MT_POSITION_Y);
+			width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
+			height = width * y_res / x_res;
+		}
+
+		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, width);
+		input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
+	}
+}
+
+static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
+{
+	struct input_dev *input = wacom->pad_input;
+	struct wacom_features *features = &wacom->features;
+
+	if (features->type == INTUOSHT) {
+		input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
+		input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
+	} else {
+		input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+		input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+	}
+	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+	input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+}
+
+static int wacom_bpt3_touch(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int count = data[1] & 0x07;
+	int i;
+
+	if (data[0] != 0x02)
+	    return 0;
+
+	/* data has up to 7 fixed sized 8-byte messages starting at data[2] */
+	for (i = 0; i < count; i++) {
+		int offset = (8 * i) + 2;
+		int msg_id = data[offset];
+
+		if (msg_id >= 2 && msg_id <= 17)
+			wacom_bpt3_touch_msg(wacom, data + offset);
+		else if (msg_id == 128)
+			wacom_bpt3_button_msg(wacom, data + offset);
+
+	}
+	input_mt_report_pointer_emulation(input, true);
+
+	return 1;
+}
+
+static int wacom_bpt_pen(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+	if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
+	    return 0;
+
+	if (data[0] == WACOM_REPORT_USB) {
+		if (features->type == INTUOSHT && features->touch_max) {
+			input_report_switch(wacom->shared->touch_input,
+					    SW_MUTE_DEVICE, data[8] & 0x40);
+			input_sync(wacom->shared->touch_input);
+		}
+		return 0;
+	}
+
+	prox = (data[1] & 0x20) == 0x20;
+
+	/*
+	 * All reports shared between PEN and RUBBER tool must be
+	 * forced to a known starting value (zero) when transitioning to
+	 * out-of-prox.
+	 *
+	 * If not reset then, to userspace, it will look like lost events
+	 * if new tool comes in-prox with same values as previous tool sent.
+	 *
+	 * Hardware does report zero in most out-of-prox cases but not all.
+	 */
+	if (prox) {
+		if (!wacom->shared->stylus_in_proximity) {
+			if (data[1] & 0x08) {
+				wacom->tool[0] = BTN_TOOL_RUBBER;
+				wacom->id[0] = ERASER_DEVICE_ID;
+			} else {
+				wacom->tool[0] = BTN_TOOL_PEN;
+				wacom->id[0] = STYLUS_DEVICE_ID;
+			}
+			wacom->shared->stylus_in_proximity = true;
+		}
+		x = le16_to_cpup((__le16 *)&data[2]);
+		y = le16_to_cpup((__le16 *)&data[4]);
+		p = le16_to_cpup((__le16 *)&data[6]);
+		/*
+		 * Convert distance from out prox to distance from tablet.
+		 * distance will be greater than distance_max once
+		 * touching and applying pressure; do not report negative
+		 * distance.
+		 */
+		if (data[8] <= features->distance_max)
+			d = features->distance_max - data[8];
+
+		pen = data[1] & 0x01;
+		btn1 = data[1] & 0x02;
+		btn2 = data[1] & 0x04;
+	}
+
+	input_report_key(input, BTN_TOUCH, pen);
+	input_report_key(input, BTN_STYLUS, btn1);
+	input_report_key(input, BTN_STYLUS2, btn2);
+
+	input_report_abs(input, ABS_X, x);
+	input_report_abs(input, ABS_Y, y);
+	input_report_abs(input, ABS_PRESSURE, p);
+	input_report_abs(input, ABS_DISTANCE, d);
+
+	if (!prox) {
+		wacom->id[0] = 0;
+		wacom->shared->stylus_in_proximity = false;
+	}
+
+	input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
+	input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
+
+	return 1;
+}
+
+static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
+{
+	if (len == WACOM_PKGLEN_BBTOUCH)
+		return wacom_bpt_touch(wacom);
+	else if (len == WACOM_PKGLEN_BBTOUCH3)
+		return wacom_bpt3_touch(wacom);
+	else if (len == WACOM_PKGLEN_BBFUN || len == WACOM_PKGLEN_BBPEN)
+		return wacom_bpt_pen(wacom);
+
+	return 0;
+}
+
+static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
+{
+	unsigned char *data = wacom->data;
+	int connected;
+
+	if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL)
+		return 0;
+
+	connected = data[1] & 0x01;
+	if (connected) {
+		int pid, battery, ps_connected;
+
+		if ((wacom->shared->type == INTUOSHT) &&
+				wacom->shared->touch_max) {
+			input_report_switch(wacom->shared->touch_input,
+					SW_MUTE_DEVICE, data[5] & 0x40);
+			input_sync(wacom->shared->touch_input);
+		}
+
+		pid = get_unaligned_be16(&data[6]);
+		battery = (data[5] & 0x3f) * 100 / 31;
+		ps_connected = !!(data[5] & 0x80);
+		if (wacom->pid != pid) {
+			wacom->pid = pid;
+			wacom_schedule_work(wacom);
+		}
+
+		if (wacom->shared->type &&
+		    (battery != wacom->battery_capacity ||
+		     ps_connected != wacom->ps_connected)) {
+			wacom->battery_capacity = battery;
+			wacom->ps_connected = ps_connected;
+			wacom->bat_charging = ps_connected &&
+						wacom->battery_capacity < 100;
+			wacom_notify_battery(wacom);
+		}
+	} else if (wacom->pid != 0) {
+		/* disconnected while previously connected */
+		wacom->pid = 0;
+		wacom_schedule_work(wacom);
+		wacom->battery_capacity = 0;
+		wacom->bat_charging = 0;
+		wacom->ps_connected = 0;
+	}
+
+	return 0;
+}
+
+void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
+{
+	bool sync;
+
+	switch (wacom_wac->features.type) {
+	case PENPARTNER:
+		sync = wacom_penpartner_irq(wacom_wac);
+		break;
+
+	case PL:
+		sync = wacom_pl_irq(wacom_wac);
+		break;
+
+	case WACOM_G4:
+	case GRAPHIRE:
+	case GRAPHIRE_BT:
+	case WACOM_MO:
+		sync = wacom_graphire_irq(wacom_wac);
+		break;
+
+	case PTU:
+		sync = wacom_ptu_irq(wacom_wac);
+		break;
+
+	case DTU:
+		sync = wacom_dtu_irq(wacom_wac);
+		break;
+
+	case DTUS:
+		sync = wacom_dtus_irq(wacom_wac);
+		break;
+
+	case INTUOS:
+	case INTUOS3S:
+	case INTUOS3:
+	case INTUOS3L:
+	case INTUOS4S:
+	case INTUOS4:
+	case INTUOS4L:
+	case CINTIQ:
+	case WACOM_BEE:
+	case WACOM_13HD:
+	case WACOM_21UX2:
+	case WACOM_22HD:
+	case WACOM_24HD:
+	case DTK:
+	case CINTIQ_HYBRID:
+		sync = wacom_intuos_irq(wacom_wac);
+		break;
+
+	case INTUOS4WL:
+		sync = wacom_intuos_bt_irq(wacom_wac, len);
+		break;
+
+	case WACOM_24HDT:
+		sync = wacom_24hdt_irq(wacom_wac);
+		break;
+
+	case INTUOS5S:
+	case INTUOS5:
+	case INTUOS5L:
+	case INTUOSPS:
+	case INTUOSPM:
+	case INTUOSPL:
+		if (len == WACOM_PKGLEN_BBTOUCH3)
+			sync = wacom_bpt3_touch(wacom_wac);
+		else
+			sync = wacom_intuos_irq(wacom_wac);
+		break;
+
+	case TABLETPC:
+	case TABLETPCE:
+	case TABLETPC2FG:
+	case MTSCREEN:
+	case MTTPC:
+	case MTTPC_B:
+		sync = wacom_tpc_irq(wacom_wac, len);
+		break;
+
+	case BAMBOO_PT:
+	case INTUOSHT:
+		sync = wacom_bpt_irq(wacom_wac, len);
+		break;
+
+	case WIRELESS:
+		sync = wacom_wireless_irq(wacom_wac, len);
+		break;
+
+	default:
+		sync = false;
+		break;
+	}
+
+	if (sync) {
+		input_sync(wacom_wac->input);
+		if (wacom_wac->pad_input)
+			input_sync(wacom_wac->pad_input);
+	}
+}
+
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
+{
+	struct input_dev *input_dev = wacom_wac->input;
+
+	input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
+
+	__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+	__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+	__set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
+	__set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
+	__set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
+	__set_bit(BTN_STYLUS, input_dev->keybit);
+	__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_DISTANCE,
+			     0, wacom_wac->features.distance_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+}
+
+static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+{
+	struct input_dev *input_dev = wacom_wac->input;
+
+	input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+	wacom_setup_cintiq(wacom_wac);
+
+	__set_bit(BTN_LEFT, input_dev->keybit);
+	__set_bit(BTN_RIGHT, input_dev->keybit);
+	__set_bit(BTN_MIDDLE, input_dev->keybit);
+	__set_bit(BTN_SIDE, input_dev->keybit);
+	__set_bit(BTN_EXTRA, input_dev->keybit);
+	__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+	__set_bit(BTN_TOOL_LENS, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+	input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
+}
+
+void wacom_setup_device_quirks(struct wacom_features *features)
+{
+
+	/* touch device found but size is not defined. use default */
+	if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
+		features->x_max = 1023;
+		features->y_max = 1023;
+	}
+
+	/* these device have multiple inputs */
+	if (features->type >= WIRELESS ||
+	    (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
+	    (features->oVid && features->oPid))
+		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
+
+	/* quirk for bamboo touch with 2 low res touches */
+	if (features->type == BAMBOO_PT &&
+	    features->pktlen == WACOM_PKGLEN_BBTOUCH) {
+		features->x_max <<= 5;
+		features->y_max <<= 5;
+		features->x_fuzz <<= 5;
+		features->y_fuzz <<= 5;
+		features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
+	}
+
+	if (features->type == WIRELESS) {
+
+		/* monitor never has input and pen/touch have delayed create */
+		features->quirks |= WACOM_QUIRK_NO_INPUT;
+
+		/* must be monitor interface if no device_type set */
+		if (!features->device_type) {
+			features->quirks |= WACOM_QUIRK_MONITOR;
+			features->quirks |= WACOM_QUIRK_BATTERY;
+		}
+	}
+}
+
+static void wacom_abs_set_axis(struct input_dev *input_dev,
+			       struct wacom_wac *wacom_wac)
+{
+	struct wacom_features *features = &wacom_wac->features;
+
+	if (features->device_type == BTN_TOOL_PEN) {
+		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_PRESSURE, 0,
+			features->pressure_max, features->pressure_fuzz, 0);
+
+		/* penabled devices have fixed resolution for each model */
+		input_abs_set_res(input_dev, ABS_X, features->x_resolution);
+		input_abs_set_res(input_dev, ABS_Y, features->y_resolution);
+	} else {
+		if (features->touch_max == 1) {
+			input_set_abs_params(input_dev, ABS_X, 0,
+				features->x_max, features->x_fuzz, 0);
+			input_set_abs_params(input_dev, ABS_Y, 0,
+				features->y_max, features->y_fuzz, 0);
+			input_abs_set_res(input_dev, ABS_X,
+					  features->x_resolution);
+			input_abs_set_res(input_dev, ABS_Y,
+					  features->y_resolution);
+		}
+
+		if (features->touch_max > 1) {
+			input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+				features->x_max, features->x_fuzz, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+				features->y_max, features->y_fuzz, 0);
+			input_abs_set_res(input_dev, ABS_MT_POSITION_X,
+					  features->x_resolution);
+			input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
+					  features->y_resolution);
+		}
+	}
+}
+
+int wacom_setup_input_capabilities(struct input_dev *input_dev,
+				   struct wacom_wac *wacom_wac)
+{
+	struct wacom_features *features = &wacom_wac->features;
+
+	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(ABS_MISC, input_dev->absbit);
+
+	wacom_abs_set_axis(input_dev, wacom_wac);
+
+	switch (features->type) {
+	case WACOM_MO:
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		/* fall through */
+
+	case WACOM_G4:
+		/* fall through */
+
+	case GRAPHIRE:
+		input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_RIGHT, input_dev->keybit);
+		__set_bit(BTN_MIDDLE, input_dev->keybit);
+
+		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+		__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+		__set_bit(BTN_STYLUS, input_dev->keybit);
+		__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+		break;
+
+	case GRAPHIRE_BT:
+		__clear_bit(ABS_MISC, input_dev->absbit);
+		input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+					      features->distance_max,
+					      0, 0);
+
+		input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_RIGHT, input_dev->keybit);
+		__set_bit(BTN_MIDDLE, input_dev->keybit);
+
+		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+		__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+		__set_bit(BTN_STYLUS, input_dev->keybit);
+		__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+		break;
+
+	case WACOM_24HD:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+		/* fall through */
+
+	case DTK:
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+		wacom_setup_cintiq(wacom_wac);
+		break;
+
+	case WACOM_22HD:
+	case WACOM_21UX2:
+	case WACOM_BEE:
+	case CINTIQ:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+		wacom_setup_cintiq(wacom_wac);
+		break;
+
+	case WACOM_13HD:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+		wacom_setup_cintiq(wacom_wac);
+		break;
+
+	case INTUOS3:
+	case INTUOS3L:
+	case INTUOS3S:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		/* fall through */
+
+	case INTUOS:
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+		wacom_setup_intuos(wacom_wac);
+		break;
+
+	case INTUOS5:
+	case INTUOS5L:
+	case INTUOSPM:
+	case INTUOSPL:
+	case INTUOS5S:
+	case INTUOSPS:
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+		if (features->device_type == BTN_TOOL_PEN) {
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+					      features->distance_max,
+					      0, 0);
+
+			input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+
+			wacom_setup_intuos(wacom_wac);
+		} else if (features->device_type == BTN_TOOL_FINGER) {
+			__clear_bit(ABS_MISC, input_dev->absbit);
+
+			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			                     0, features->x_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+			                     0, features->y_max, 0, 0);
+			input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER);
+		}
+		break;
+
+	case INTUOS4:
+	case INTUOS4WL:
+	case INTUOS4L:
+	case INTUOS4S:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		wacom_setup_intuos(wacom_wac);
+
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+		break;
+
+	case WACOM_24HDT:
+		if (features->device_type == BTN_TOOL_FINGER) {
+			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+		}
+		/* fall through */
+
+	case MTSCREEN:
+	case MTTPC:
+	case MTTPC_B:
+	case TABLETPC2FG:
+		if (features->device_type == BTN_TOOL_FINGER && features->touch_max > 1)
+			input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT);
+		/* fall through */
+
+	case TABLETPC:
+	case TABLETPCE:
+		__clear_bit(ABS_MISC, input_dev->absbit);
+
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+		if (features->device_type != BTN_TOOL_PEN)
+			break;  /* no need to process stylus stuff */
+
+		/* fall through */
+
+	case DTUS:
+	case PL:
+	case DTU:
+		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+		__set_bit(BTN_STYLUS, input_dev->keybit);
+		__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+		break;
+
+	case PTU:
+		__set_bit(BTN_STYLUS2, input_dev->keybit);
+		/* fall through */
+
+	case PENPARTNER:
+		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+		__set_bit(BTN_STYLUS, input_dev->keybit);
+
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+		break;
+
+	case INTUOSHT:
+		if (features->touch_max &&
+		    features->device_type == BTN_TOOL_FINGER) {
+			input_dev->evbit[0] |= BIT_MASK(EV_SW);
+			__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
+		}
+		/* fall through */
+
+	case BAMBOO_PT:
+		__clear_bit(ABS_MISC, input_dev->absbit);
+
+		if (features->device_type == BTN_TOOL_FINGER) {
+
+			if (features->touch_max) {
+				if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
+					input_set_abs_params(input_dev,
+						     ABS_MT_TOUCH_MAJOR,
+						     0, features->x_max, 0, 0);
+					input_set_abs_params(input_dev,
+						     ABS_MT_TOUCH_MINOR,
+						     0, features->y_max, 0, 0);
+				}
+				input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER);
+			} else {
+				/* buttons/keys only interface */
+				__clear_bit(ABS_X, input_dev->absbit);
+				__clear_bit(ABS_Y, input_dev->absbit);
+				__clear_bit(BTN_TOUCH, input_dev->keybit);
+			}
+		} else if (features->device_type == BTN_TOOL_PEN) {
+			__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+			__set_bit(BTN_STYLUS, input_dev->keybit);
+			__set_bit(BTN_STYLUS2, input_dev->keybit);
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+					      features->distance_max,
+					      0, 0);
+		}
+		break;
+
+	case CINTIQ_HYBRID:
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+		wacom_setup_cintiq(wacom_wac);
+		break;
+	}
+	return 0;
+}
+
+int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
+				   struct wacom_wac *wacom_wac)
+{
+	struct wacom_features *features = &wacom_wac->features;
+	int i;
+
+	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+	/* kept for making legacy xf86-input-wacom working with the wheels */
+	__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);
+
+	switch (features->type) {
+	case GRAPHIRE_BT:
+		__set_bit(BTN_0, input_dev->keybit);
+		__set_bit(BTN_1, input_dev->keybit);
+		break;
+
+	case WACOM_MO:
+		__set_bit(BTN_BACK, input_dev->keybit);
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_FORWARD, input_dev->keybit);
+		__set_bit(BTN_RIGHT, input_dev->keybit);
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		break;
+
+	case WACOM_G4:
+		__set_bit(BTN_BACK, input_dev->keybit);
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_FORWARD, input_dev->keybit);
+		__set_bit(BTN_RIGHT, input_dev->keybit);
+		input_set_capability(input_dev, EV_REL, REL_WHEEL);
+		break;
+
+	case WACOM_24HD:
+		__set_bit(BTN_A, input_dev->keybit);
+		__set_bit(BTN_B, input_dev->keybit);
+		__set_bit(BTN_C, input_dev->keybit);
+		__set_bit(BTN_X, input_dev->keybit);
+		__set_bit(BTN_Y, input_dev->keybit);
+		__set_bit(BTN_Z, input_dev->keybit);
+
+		for (i = 0; i < 10; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		__set_bit(KEY_PROG1, input_dev->keybit);
+		__set_bit(KEY_PROG2, input_dev->keybit);
+		__set_bit(KEY_PROG3, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+		break;
+
+	case DTK:
+		for (i = 0; i < 6; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		break;
+
+	case WACOM_22HD:
+		__set_bit(KEY_PROG1, input_dev->keybit);
+		__set_bit(KEY_PROG2, input_dev->keybit);
+		__set_bit(KEY_PROG3, input_dev->keybit);
+		/* fall through */
+
+	case WACOM_21UX2:
+		__set_bit(BTN_A, input_dev->keybit);
+		__set_bit(BTN_B, input_dev->keybit);
+		__set_bit(BTN_C, input_dev->keybit);
+		__set_bit(BTN_X, input_dev->keybit);
+		__set_bit(BTN_Y, input_dev->keybit);
+		__set_bit(BTN_Z, input_dev->keybit);
+		__set_bit(BTN_BASE, input_dev->keybit);
+		__set_bit(BTN_BASE2, input_dev->keybit);
+		/* fall through */
+
+	case WACOM_BEE:
+		__set_bit(BTN_8, input_dev->keybit);
+		__set_bit(BTN_9, input_dev->keybit);
+		/* fall through */
+
+	case CINTIQ:
+		for (i = 0; i < 8; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+		break;
+
+	case WACOM_13HD:
+		for (i = 0; i < 9; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		break;
+
+	case INTUOS3:
+	case INTUOS3L:
+		__set_bit(BTN_4, input_dev->keybit);
+		__set_bit(BTN_5, input_dev->keybit);
+		__set_bit(BTN_6, input_dev->keybit);
+		__set_bit(BTN_7, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+		/* fall through */
+
+	case INTUOS3S:
+		__set_bit(BTN_0, input_dev->keybit);
+		__set_bit(BTN_1, input_dev->keybit);
+		__set_bit(BTN_2, input_dev->keybit);
+		__set_bit(BTN_3, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+		break;
+
+	case INTUOS5:
+	case INTUOS5L:
+	case INTUOSPM:
+	case INTUOSPL:
+		__set_bit(BTN_7, input_dev->keybit);
+		__set_bit(BTN_8, input_dev->keybit);
+		/* fall through */
+
+	case INTUOS5S:
+	case INTUOSPS:
+		/* touch interface does not have the pad device */
+		if (features->device_type != BTN_TOOL_PEN)
+			return 1;
+
+		for (i = 0; i < 7; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		break;
+
+	case INTUOS4WL:
+		/*
+		 * For Bluetooth devices, the udev rule does not work correctly
+		 * for pads unless we add a stylus capability, which forces
+		 * ID_INPUT_TABLET to be set.
+		 */
+		__set_bit(BTN_STYLUS, input_dev->keybit);
+		/* fall through */
+
+	case INTUOS4:
+	case INTUOS4L:
+		__set_bit(BTN_7, input_dev->keybit);
+		__set_bit(BTN_8, input_dev->keybit);
+		/* fall through */
+
+	case INTUOS4S:
+		for (i = 0; i < 7; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+		break;
+
+	case CINTIQ_HYBRID:
+		for (i = 0; i < 9; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		break;
+
+	case DTUS:
+		for (i = 0; i < 4; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+		break;
+
+	case INTUOSHT:
+	case BAMBOO_PT:
+		/* pad device is on the touch interface */
+		if (features->device_type != BTN_TOOL_FINGER)
+			return 1;
+
+		__clear_bit(ABS_MISC, input_dev->absbit);
+
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_FORWARD, input_dev->keybit);
+		__set_bit(BTN_BACK, input_dev->keybit);
+		__set_bit(BTN_RIGHT, input_dev->keybit);
+
+		break;
+
+	default:
+		/* no pad supported */
+		return 1;
+	}
+	return 0;
+}
+
+static const struct wacom_features wacom_features_0x00 =
+	{ "Wacom Penpartner", 5040, 3780, 255, 0,
+	  PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x10 =
+	{ "Wacom Graphire", 10206, 7422, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x81 =
+	{ "Wacom Graphire BT", 16704, 12064, 511, 32,
+	  GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x11 =
+	{ "Wacom Graphire2 4x5", 10206, 7422, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x12 =
+	{ "Wacom Graphire2 5x7", 13918, 10206, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x13 =
+	{ "Wacom Graphire3", 10208, 7424, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x14 =
+	{ "Wacom Graphire3 6x8", 16704, 12064, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x15 =
+	{ "Wacom Graphire4 4x5", 10208, 7424, 511, 63,
+	  WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x16 =
+	{ "Wacom Graphire4 6x8", 16704, 12064, 511, 63,
+	  WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x17 =
+	{ "Wacom BambooFun 4x5", 14760, 9225, 511, 63,
+	  WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x18 =
+	{ "Wacom BambooFun 6x8", 21648, 13530, 511, 63,
+	  WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x19 =
+	{ "Wacom Bamboo1 Medium", 16704, 12064, 511, 63,
+	  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x60 =
+	{ "Wacom Volito", 5104, 3712, 511, 63,
+	  GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+static const struct wacom_features wacom_features_0x61 =
+	{ "Wacom PenStation2", 3250, 2320, 255, 63,
+	  GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+static const struct wacom_features wacom_features_0x62 =
+	{ "Wacom Volito2 4x5", 5104, 3712, 511, 63,
+	  GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+static const struct wacom_features wacom_features_0x63 =
+	{ "Wacom Volito2 2x3", 3248, 2320, 511, 63,
+	  GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+static const struct wacom_features wacom_features_0x64 =
+	{ "Wacom PenPartner2", 3250, 2320, 511, 63,
+	  GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+static const struct wacom_features wacom_features_0x65 =
+	{ "Wacom Bamboo", 14760, 9225, 511, 63,
+	  WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x69 =
+	{ "Wacom Bamboo1", 5104, 3712, 511, 63,
+	  GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x6A =
+	{ "Wacom Bamboo1 4x6", 14760, 9225, 1023, 63,
+	  GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x6B =
+	{ "Wacom Bamboo1 5x8", 21648, 13530, 1023, 63,
+	  GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x20 =
+	{ "Wacom Intuos 4x5", 12700, 10600, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x21 =
+	{ "Wacom Intuos 6x8", 20320, 16240, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x22 =
+	{ "Wacom Intuos 9x12", 30480, 24060, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x23 =
+	{ "Wacom Intuos 12x12", 30480, 31680, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x24 =
+	{ "Wacom Intuos 12x18", 45720, 31680, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x30 =
+	{ "Wacom PL400", 5408, 4056, 255, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x31 =
+	{ "Wacom PL500", 6144, 4608, 255, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x32 =
+	{ "Wacom PL600", 6126, 4604, 255, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x33 =
+	{ "Wacom PL600SX", 6260, 5016, 255, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x34 =
+	{ "Wacom PL550", 6144, 4608, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x35 =
+	{ "Wacom PL800", 7220, 5780, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x37 =
+	{ "Wacom PL700", 6758, 5406, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x38 =
+	{ "Wacom PL510", 6282, 4762, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x39 =
+	{ "Wacom DTU710", 34080, 27660, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0xC4 =
+	{ "Wacom DTF521", 6282, 4762, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0xC0 =
+	{ "Wacom DTF720", 6858, 5506, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0xC2 =
+	{ "Wacom DTF720a", 6858, 5506, 511, 0,
+	  PL, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x03 =
+	{ "Wacom Cintiq Partner", 20480, 15360, 511, 0,
+	  PTU, WACOM_PL_RES, WACOM_PL_RES };
+static const struct wacom_features wacom_features_0x41 =
+	{ "Wacom Intuos2 4x5", 12700, 10600, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x42 =
+	{ "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x43 =
+	{ "Wacom Intuos2 9x12", 30480, 24060, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x44 =
+	{ "Wacom Intuos2 12x12", 30480, 31680, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x45 =
+	{ "Wacom Intuos2 12x18", 45720, 31680, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xB0 =
+	{ "Wacom Intuos3 4x5", 25400, 20320, 1023, 63,
+	  INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB1 =
+	{ "Wacom Intuos3 6x8", 40640, 30480, 1023, 63,
+	  INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB2 =
+	{ "Wacom Intuos3 9x12", 60960, 45720, 1023, 63,
+	  INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB3 =
+	{ "Wacom Intuos3 12x12", 60960, 60960, 1023, 63,
+	  INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB4 =
+	{ "Wacom Intuos3 12x19", 97536, 60960, 1023, 63,
+	  INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB5 =
+	{ "Wacom Intuos3 6x11", 54204, 31750, 1023, 63,
+	  INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB7 =
+	{ "Wacom Intuos3 4x6", 31496, 19685, 1023, 63,
+	  INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB8 =
+	{ "Wacom Intuos4 4x6", 31496, 19685, 2047, 63,
+	  INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xB9 =
+	{ "Wacom Intuos4 6x9", 44704, 27940, 2047, 63,
+	  INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBA =
+	{ "Wacom Intuos4 8x13", 65024, 40640, 2047, 63,
+	  INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBB =
+	{ "Wacom Intuos4 12x19", 97536, 60960, 2047, 63,
+	  INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBC =
+	{ "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
+	  INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBD =
+	{ "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
+	  INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x26 =
+	{ "Wacom Intuos5 touch S", 31496, 19685, 2047, 63,
+	  INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+static const struct wacom_features wacom_features_0x27 =
+	{ "Wacom Intuos5 touch M", 44704, 27940, 2047, 63,
+	  INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+static const struct wacom_features wacom_features_0x28 =
+	{ "Wacom Intuos5 touch L", 65024, 40640, 2047, 63,
+	  INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+static const struct wacom_features wacom_features_0x29 =
+	{ "Wacom Intuos5 S", 31496, 19685, 2047, 63,
+	  INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x2A =
+	{ "Wacom Intuos5 M", 44704, 27940, 2047, 63,
+	  INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x314 =
+	{ "Wacom Intuos Pro S", 31496, 19685, 2047, 63,
+	  INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x315 =
+	{ "Wacom Intuos Pro M", 44704, 27940, 2047, 63,
+	  INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x317 =
+	{ "Wacom Intuos Pro L", 65024, 40640, 2047, 63,
+	  INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0xF4 =
+	{ "Wacom Cintiq 24HD", 104280, 65400, 2047, 63,
+	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+static const struct wacom_features wacom_features_0xF8 =
+	{ "Wacom Cintiq 24HD touch", 104280, 65400, 2047, 63, /* Pen */
+	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+	  .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_0x3F =
+	{ "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
+	  CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xC5 =
+	{ "Wacom Cintiq 20WSX", 86680, 54180, 1023, 63,
+	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xC6 =
+	{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
+	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x304 =
+	{ "Wacom Cintiq 13HD", 59352, 33648, 1023, 63,
+	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+static const struct wacom_features wacom_features_0xC7 =
+	{ "Wacom DTU1931", 37832, 30305, 511, 0,
+	  PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xCE =
+	{ "Wacom DTU2231", 47864, 27011, 511, 0,
+	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE };
+static const struct wacom_features wacom_features_0xF0 =
+	{ "Wacom DTU1631", 34623, 19553, 511, 0,
+	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xFB =
+	{ "Wacom DTU1031", 22096, 13960, 511, 0,
+	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x57 =
+	{ "Wacom DTK2241", 95640, 54060, 2047, 63,
+	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+static const struct wacom_features wacom_features_0x59 = /* Pen */
+	{ "Wacom DTH2242", 95640, 54060, 2047, 63,
+	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+	  .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", 87000, 65400, 2047, 63,
+	  WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+static const struct wacom_features wacom_features_0xFA =
+	{ "Wacom Cintiq 22HD", 95640, 54060, 2047, 63,
+	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+static const struct wacom_features wacom_features_0x5B =
+	{ "Wacom Cintiq 22HDT", 95640, 54060, 2047, 63,
+	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
+static const struct wacom_features wacom_features_0x5E =
+	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
+	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x90 =
+	{ "Wacom ISDv4 90", 26202, 16325, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x93 =
+	{ "Wacom ISDv4 93", 26202, 16325, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x97 =
+	{ "Wacom ISDv4 97", 26202, 16325, 511, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x9A =
+	{ "Wacom ISDv4 9A", 26202, 16325, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x9F =
+	{ "Wacom ISDv4 9F", 26202, 16325, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xE2 =
+	{ "Wacom ISDv4 E2", 26202, 16325, 255, 0,
+	  TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xE3 =
+	{ "Wacom ISDv4 E3", 26202, 16325, 255, 0,
+	  TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xE5 =
+	{ "Wacom ISDv4 E5", 26202, 16325, 255, 0,
+	  MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xE6 =
+	{ "Wacom ISDv4 E6", 27760, 15694, 255, 0,
+	  TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xEC =
+	{ "Wacom ISDv4 EC", 25710, 14500, 255, 0,
+	  TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xED =
+	{ "Wacom ISDv4 ED", 26202, 16325, 255, 0,
+	  TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xEF =
+	{ "Wacom ISDv4 EF", 26202, 16325, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x100 =
+	{ "Wacom ISDv4 100", 26202, 16325, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x101 =
+	{ "Wacom ISDv4 101", 26202, 16325, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10D =
+	{ "Wacom ISDv4 10D", 26202, 16325, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10E =
+	{ "Wacom ISDv4 10E", 27760, 15694, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10F =
+	{ "Wacom ISDv4 10F", 27760, 15694, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x116 =
+	{ "Wacom ISDv4 116", 26202, 16325, 255, 0,
+	  TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x12C =
+	{ "Wacom ISDv4 12C", 27848, 15752, 2047, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x4001 =
+	{ "Wacom ISDv4 4001", 26202, 16325, 255, 0,
+	  MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x4004 =
+	{ "Wacom ISDv4 4004", 11060, 6220, 255, 0,
+	  MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x5000 =
+	{ "Wacom ISDv4 5000", 27848, 15752, 1023, 0,
+	  MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x5002 =
+	{ "Wacom ISDv4 5002", 29576, 16724, 1023, 0,
+	  MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x47 =
+	{ "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
+	  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x84 =
+	{ "Wacom Wireless Receiver", 0, 0, 0, 0,
+	  WIRELESS, 0, 0, .touch_max = 16 };
+static const struct wacom_features wacom_features_0xD0 =
+	{ "Wacom Bamboo 2FG", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD1 =
+	{ "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD2 =
+	{ "Wacom Bamboo Craft", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD3 =
+	{ "Wacom Bamboo 2FG 6x8", 21648, 13700, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD4 =
+	{ "Wacom Bamboo Pen", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD5 =
+	{ "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD6 =
+	{ "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD7 =
+	{ "Wacom BambooPT 2FG Small", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xD8 =
+	{ "Wacom Bamboo Comic 2FG", 21648, 13700, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xDA =
+	{ "Wacom Bamboo 2FG 4x5 SE", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xDB =
+	{ "Wacom Bamboo 2FG 6x8 SE", 21648, 13700, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+static const struct wacom_features wacom_features_0xDD =
+        { "Wacom Bamboo Connect", 14720, 9200, 1023, 31,
+          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xDE =
+        { "Wacom Bamboo 16FG 4x5", 14720, 9200, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
+static const struct wacom_features wacom_features_0xDF =
+        { "Wacom Bamboo 16FG 6x8", 21648, 13700, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
+static const struct wacom_features wacom_features_0x300 =
+	{ "Wacom Bamboo One S", 14720, 9225, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x301 =
+	{ "Wacom Bamboo One M", 21648, 13530, 1023, 31,
+	  BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x302 =
+	{ "Wacom Intuos PT S", 15200, 9500, 1023, 31,
+	  INTUOSHT, 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_0x303 =
+	{ "Wacom Intuos PT M", 21600, 13500, 1023, 31,
+	  INTUOSHT, 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_0x30E =
+	{ "Wacom Intuos S", 15200, 9500, 1023, 31,
+	  INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x6004 =
+	{ "ISD-V4", 12800, 8000, 255, 0,
+	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x307 =
+	{ "Wacom ISDv5 307", 59352, 33648, 2047, 63,
+	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+	  .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 };
+
+#define USB_DEVICE_WACOM(prod)						\
+	HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+
+#define BT_DEVICE_WACOM(prod)						\
+	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+
+#define USB_DEVICE_LENOVO(prod)					\
+	HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
+	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+
+const struct hid_device_id wacom_ids[] = {
+	{ USB_DEVICE_WACOM(0x00) },
+	{ USB_DEVICE_WACOM(0x03) },
+	{ USB_DEVICE_WACOM(0x10) },
+	{ USB_DEVICE_WACOM(0x11) },
+	{ USB_DEVICE_WACOM(0x12) },
+	{ USB_DEVICE_WACOM(0x13) },
+	{ USB_DEVICE_WACOM(0x14) },
+	{ USB_DEVICE_WACOM(0x15) },
+	{ USB_DEVICE_WACOM(0x16) },
+	{ USB_DEVICE_WACOM(0x17) },
+	{ USB_DEVICE_WACOM(0x18) },
+	{ USB_DEVICE_WACOM(0x19) },
+	{ USB_DEVICE_WACOM(0x20) },
+	{ USB_DEVICE_WACOM(0x21) },
+	{ USB_DEVICE_WACOM(0x22) },
+	{ USB_DEVICE_WACOM(0x23) },
+	{ USB_DEVICE_WACOM(0x24) },
+	{ USB_DEVICE_WACOM(0x26) },
+	{ USB_DEVICE_WACOM(0x27) },
+	{ USB_DEVICE_WACOM(0x28) },
+	{ USB_DEVICE_WACOM(0x29) },
+	{ USB_DEVICE_WACOM(0x2A) },
+	{ USB_DEVICE_WACOM(0x30) },
+	{ USB_DEVICE_WACOM(0x31) },
+	{ USB_DEVICE_WACOM(0x32) },
+	{ USB_DEVICE_WACOM(0x33) },
+	{ USB_DEVICE_WACOM(0x34) },
+	{ USB_DEVICE_WACOM(0x35) },
+	{ USB_DEVICE_WACOM(0x37) },
+	{ USB_DEVICE_WACOM(0x38) },
+	{ USB_DEVICE_WACOM(0x39) },
+	{ USB_DEVICE_WACOM(0x3F) },
+	{ USB_DEVICE_WACOM(0x41) },
+	{ USB_DEVICE_WACOM(0x42) },
+	{ USB_DEVICE_WACOM(0x43) },
+	{ USB_DEVICE_WACOM(0x44) },
+	{ USB_DEVICE_WACOM(0x45) },
+	{ USB_DEVICE_WACOM(0x47) },
+	{ USB_DEVICE_WACOM(0x57) },
+	{ USB_DEVICE_WACOM(0x59) },
+	{ USB_DEVICE_WACOM(0x5B) },
+	{ USB_DEVICE_WACOM(0x5D) },
+	{ USB_DEVICE_WACOM(0x5E) },
+	{ USB_DEVICE_WACOM(0x60) },
+	{ USB_DEVICE_WACOM(0x61) },
+	{ USB_DEVICE_WACOM(0x62) },
+	{ USB_DEVICE_WACOM(0x63) },
+	{ USB_DEVICE_WACOM(0x64) },
+	{ USB_DEVICE_WACOM(0x65) },
+	{ USB_DEVICE_WACOM(0x69) },
+	{ USB_DEVICE_WACOM(0x6A) },
+	{ USB_DEVICE_WACOM(0x6B) },
+	{ BT_DEVICE_WACOM(0x81) },
+	{ USB_DEVICE_WACOM(0x84) },
+	{ USB_DEVICE_WACOM(0x90) },
+	{ USB_DEVICE_WACOM(0x93) },
+	{ USB_DEVICE_WACOM(0x97) },
+	{ USB_DEVICE_WACOM(0x9A) },
+	{ USB_DEVICE_WACOM(0x9F) },
+	{ USB_DEVICE_WACOM(0xB0) },
+	{ USB_DEVICE_WACOM(0xB1) },
+	{ USB_DEVICE_WACOM(0xB2) },
+	{ USB_DEVICE_WACOM(0xB3) },
+	{ USB_DEVICE_WACOM(0xB4) },
+	{ USB_DEVICE_WACOM(0xB5) },
+	{ USB_DEVICE_WACOM(0xB7) },
+	{ USB_DEVICE_WACOM(0xB8) },
+	{ USB_DEVICE_WACOM(0xB9) },
+	{ USB_DEVICE_WACOM(0xBA) },
+	{ USB_DEVICE_WACOM(0xBB) },
+	{ USB_DEVICE_WACOM(0xBC) },
+	{ BT_DEVICE_WACOM(0xBD) },
+	{ USB_DEVICE_WACOM(0xC0) },
+	{ USB_DEVICE_WACOM(0xC2) },
+	{ USB_DEVICE_WACOM(0xC4) },
+	{ USB_DEVICE_WACOM(0xC5) },
+	{ USB_DEVICE_WACOM(0xC6) },
+	{ USB_DEVICE_WACOM(0xC7) },
+	{ USB_DEVICE_WACOM(0xCC) },
+	{ USB_DEVICE_WACOM(0xCE) },
+	{ USB_DEVICE_WACOM(0xD0) },
+	{ USB_DEVICE_WACOM(0xD1) },
+	{ USB_DEVICE_WACOM(0xD2) },
+	{ USB_DEVICE_WACOM(0xD3) },
+	{ USB_DEVICE_WACOM(0xD4) },
+	{ USB_DEVICE_WACOM(0xD5) },
+	{ USB_DEVICE_WACOM(0xD6) },
+	{ USB_DEVICE_WACOM(0xD7) },
+	{ USB_DEVICE_WACOM(0xD8) },
+	{ USB_DEVICE_WACOM(0xDA) },
+	{ USB_DEVICE_WACOM(0xDB) },
+	{ USB_DEVICE_WACOM(0xDD) },
+	{ USB_DEVICE_WACOM(0xDE) },
+	{ USB_DEVICE_WACOM(0xDF) },
+	{ USB_DEVICE_WACOM(0xE2) },
+	{ USB_DEVICE_WACOM(0xE3) },
+	{ USB_DEVICE_WACOM(0xE5) },
+	{ USB_DEVICE_WACOM(0xE6) },
+	{ USB_DEVICE_WACOM(0xEC) },
+	{ USB_DEVICE_WACOM(0xED) },
+	{ USB_DEVICE_WACOM(0xEF) },
+	{ USB_DEVICE_WACOM(0xF0) },
+	{ USB_DEVICE_WACOM(0xF4) },
+	{ USB_DEVICE_WACOM(0xF6) },
+	{ USB_DEVICE_WACOM(0xF8) },
+	{ USB_DEVICE_WACOM(0xFA) },
+	{ USB_DEVICE_WACOM(0xFB) },
+	{ USB_DEVICE_WACOM(0x100) },
+	{ USB_DEVICE_WACOM(0x101) },
+	{ USB_DEVICE_WACOM(0x10D) },
+	{ USB_DEVICE_WACOM(0x10E) },
+	{ USB_DEVICE_WACOM(0x10F) },
+	{ USB_DEVICE_WACOM(0x116) },
+	{ USB_DEVICE_WACOM(0x12C) },
+	{ USB_DEVICE_WACOM(0x300) },
+	{ USB_DEVICE_WACOM(0x301) },
+	{ USB_DEVICE_WACOM(0x302) },
+	{ USB_DEVICE_WACOM(0x303) },
+	{ USB_DEVICE_WACOM(0x304) },
+	{ USB_DEVICE_WACOM(0x307) },
+	{ USB_DEVICE_WACOM(0x309) },
+	{ USB_DEVICE_WACOM(0x30E) },
+	{ USB_DEVICE_WACOM(0x314) },
+	{ USB_DEVICE_WACOM(0x315) },
+	{ USB_DEVICE_WACOM(0x317) },
+	{ USB_DEVICE_WACOM(0x4001) },
+	{ USB_DEVICE_WACOM(0x4004) },
+	{ USB_DEVICE_WACOM(0x5000) },
+	{ USB_DEVICE_WACOM(0x5002) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, wacom_ids);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hid/wacom_wac.h linux-libre-3.17-rc7-gnu/drivers/hid/wacom_wac.h
--- linux-libre-3.16-gnu/drivers/hid/wacom_wac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hid/wacom_wac.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,179 @@
+/*
+ * drivers/input/tablet/wacom_wac.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef WACOM_WAC_H
+#define WACOM_WAC_H
+
+#include <linux/types.h>
+
+/* maximum packet length for USB devices */
+#define WACOM_PKGLEN_MAX	68
+
+#define WACOM_NAME_MAX		64
+
+/* packet length for individual models */
+#define WACOM_PKGLEN_PENPRTN	 7
+#define WACOM_PKGLEN_GRAPHIRE	 8
+#define WACOM_PKGLEN_BBFUN	 9
+#define WACOM_PKGLEN_INTUOS	10
+#define WACOM_PKGLEN_TPC1FG	 5
+#define WACOM_PKGLEN_TPC1FG_B	10
+#define WACOM_PKGLEN_TPC2FG	14
+#define WACOM_PKGLEN_BBTOUCH	20
+#define WACOM_PKGLEN_BBTOUCH3	64
+#define WACOM_PKGLEN_BBPEN	10
+#define WACOM_PKGLEN_WIRELESS	32
+#define WACOM_PKGLEN_MTOUCH	62
+#define WACOM_PKGLEN_MTTPC	40
+#define WACOM_PKGLEN_DTUS	68
+#define WACOM_PKGLEN_PENABLED	 8
+
+/* wacom data size per MT contact */
+#define WACOM_BYTES_PER_MT_PACKET	11
+#define WACOM_BYTES_PER_24HDT_PACKET	14
+
+/* device IDs */
+#define STYLUS_DEVICE_ID	0x02
+#define TOUCH_DEVICE_ID		0x03
+#define CURSOR_DEVICE_ID	0x06
+#define ERASER_DEVICE_ID	0x0A
+#define PAD_DEVICE_ID		0x0F
+
+/* wacom data packet report IDs */
+#define WACOM_REPORT_PENABLED		2
+#define WACOM_REPORT_PENABLED_BT	3
+#define WACOM_REPORT_INTUOSREAD		5
+#define WACOM_REPORT_INTUOSWRITE	6
+#define WACOM_REPORT_INTUOSPAD		12
+#define WACOM_REPORT_INTUOS5PAD		3
+#define WACOM_REPORT_DTUSPAD		21
+#define WACOM_REPORT_TPC1FG		6
+#define WACOM_REPORT_TPC2FG		13
+#define WACOM_REPORT_TPCMT		13
+#define WACOM_REPORT_TPCMT2		3
+#define WACOM_REPORT_TPCHID		15
+#define WACOM_REPORT_TPCST		16
+#define WACOM_REPORT_DTUS		17
+#define WACOM_REPORT_TPC1FGE		18
+#define WACOM_REPORT_24HDT		1
+#define WACOM_REPORT_WL			128
+#define WACOM_REPORT_USB		192
+
+/* device quirks */
+#define WACOM_QUIRK_MULTI_INPUT		0x0001
+#define WACOM_QUIRK_BBTOUCH_LOWRES	0x0002
+#define WACOM_QUIRK_NO_INPUT		0x0004
+#define WACOM_QUIRK_MONITOR		0x0008
+#define WACOM_QUIRK_BATTERY		0x0010
+
+enum {
+	PENPARTNER = 0,
+	GRAPHIRE,
+	GRAPHIRE_BT,
+	WACOM_G4,
+	PTU,
+	PL,
+	DTU,
+	DTUS,
+	INTUOS,
+	INTUOS3S,
+	INTUOS3,
+	INTUOS3L,
+	INTUOS4S,
+	INTUOS4,
+	INTUOS4WL,
+	INTUOS4L,
+	INTUOS5S,
+	INTUOS5,
+	INTUOS5L,
+	INTUOSPS,
+	INTUOSPM,
+	INTUOSPL,
+	INTUOSHT,
+	WACOM_21UX2,
+	WACOM_22HD,
+	DTK,
+	WACOM_24HD,
+	CINTIQ_HYBRID,
+	CINTIQ,
+	WACOM_BEE,
+	WACOM_13HD,
+	WACOM_MO,
+	WIRELESS,
+	BAMBOO_PT,
+	WACOM_24HDT,
+	TABLETPC,   /* add new TPC below */
+	TABLETPCE,
+	TABLETPC2FG,
+	MTSCREEN,
+	MTTPC,
+	MTTPC_B,
+	MAX_TYPE
+};
+
+struct wacom_features {
+	const char *name;
+	int x_max;
+	int y_max;
+	int pressure_max;
+	int distance_max;
+	int type;
+	int x_resolution;
+	int y_resolution;
+	int x_min;
+	int y_min;
+	int device_type;
+	int x_phy;
+	int y_phy;
+	unsigned unit;
+	int unitExpo;
+	int x_fuzz;
+	int y_fuzz;
+	int pressure_fuzz;
+	int distance_fuzz;
+	unsigned quirks;
+	unsigned touch_max;
+	int oVid;
+	int oPid;
+	int pktlen;
+	bool check_for_hid_type;
+	int hid_type;
+};
+
+struct wacom_shared {
+	bool stylus_in_proximity;
+	bool touch_down;
+	/* for wireless device to access USB interfaces */
+	unsigned touch_max;
+	int type;
+	struct input_dev *touch_input;
+};
+
+struct wacom_wac {
+	char name[WACOM_NAME_MAX];
+	char pad_name[WACOM_NAME_MAX];
+	char bat_name[WACOM_NAME_MAX];
+	char ac_name[WACOM_NAME_MAX];
+	unsigned char data[WACOM_PKGLEN_MAX];
+	int tool[2];
+	int id[2];
+	__u32 serial[2];
+	struct wacom_features features;
+	struct wacom_shared *shared;
+	struct input_dev *input;
+	struct input_dev *pad_input;
+	int pid;
+	int battery_capacity;
+	int num_contacts_left;
+	int bat_charging;
+	int ps_connected;
+	u8 bt_features;
+	u8 bt_high_speed;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hsi/clients/ssi_protocol.c linux-libre-3.17-rc7-gnu/drivers/hsi/clients/ssi_protocol.c
--- linux-libre-3.16-gnu/drivers/hsi/clients/ssi_protocol.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hsi/clients/ssi_protocol.c	2014-09-28 17:29:07.000000000 -0400
@@ -901,7 +901,7 @@ out:
 	ssip_free_data(msg);
 }
 
-void ssip_port_event(struct hsi_client *cl, unsigned long event)
+static void ssip_port_event(struct hsi_client *cl, unsigned long event)
 {
 	switch (event) {
 	case HSI_EVENT_START_RX:
@@ -1115,7 +1115,7 @@ static int ssi_protocol_probe(struct dev
 		goto out;
 	}
 
-	ssi->netdev = alloc_netdev(0, ifname, ssip_pn_setup);
+	ssi->netdev = alloc_netdev(0, ifname, NET_NAME_UNKNOWN, ssip_pn_setup);
 	if (!ssi->netdev) {
 		dev_err(dev, "No memory for netdev\n");
 		err = -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hsi/controllers/omap_ssi.c linux-libre-3.17-rc7-gnu/drivers/hsi/controllers/omap_ssi.c
--- linux-libre-3.16-gnu/drivers/hsi/controllers/omap_ssi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hsi/controllers/omap_ssi.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,14 +148,14 @@ static int __init ssi_debug_add_ctrl(str
 
 	/* SSI controller */
 	omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
-	if (IS_ERR(omap_ssi->dir))
-		return PTR_ERR(omap_ssi->dir);
+	if (!omap_ssi->dir)
+		return -ENOMEM;
 
 	debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
 								&ssi_regs_fops);
 	/* SSI GDD (DMA) */
 	dir = debugfs_create_dir("gdd", omap_ssi->dir);
-	if (IS_ERR(dir))
+	if (!dir)
 		goto rback;
 	debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
 
@@ -163,7 +163,7 @@ static int __init ssi_debug_add_ctrl(str
 rback:
 	debugfs_remove_recursive(omap_ssi->dir);
 
-	return PTR_ERR(dir);
+	return -ENOMEM;
 }
 
 static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
@@ -353,12 +353,12 @@ static int __init ssi_add_controller(str
 	err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
 	if (err < 0)
 		goto out_err;
-	omap_ssi->gdd_irq = platform_get_irq_byname(pd, "gdd_mpu");
-	if (omap_ssi->gdd_irq < 0) {
+	err = platform_get_irq_byname(pd, "gdd_mpu");
+	if (err < 0) {
 		dev_err(&pd->dev, "GDD IRQ resource missing\n");
-		err = omap_ssi->gdd_irq;
 		goto out_err;
 	}
+	omap_ssi->gdd_irq = err;
 	tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
 							(unsigned long)ssi);
 	err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hsi/controllers/omap_ssi_port.c linux-libre-3.17-rc7-gnu/drivers/hsi/controllers/omap_ssi_port.c
--- linux-libre-3.16-gnu/drivers/hsi/controllers/omap_ssi_port.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hsi/controllers/omap_ssi_port.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,13 +177,13 @@ static int __init ssi_debug_add_port(str
 	struct hsi_port *port = to_hsi_port(omap_port->dev);
 
 	dir = debugfs_create_dir(dev_name(omap_port->dev), dir);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
+	if (!dir)
+		return -ENOMEM;
 	omap_port->dir = dir;
 	debugfs_create_file("regs", S_IRUGO, dir, port, &ssi_port_regs_fops);
 	dir = debugfs_create_dir("sst", dir);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
+	if (!dir)
+		return -ENOMEM;
 	debugfs_create_file("divisor", S_IRUGO | S_IWUSR, dir, port,
 			    &ssi_sst_div_fops);
 
@@ -1013,11 +1013,12 @@ static int __init ssi_port_irq(struct hs
 	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
 	int err;
 
-	omap_port->irq = platform_get_irq(pd, 0);
-	if (omap_port->irq < 0) {
+	err = platform_get_irq(pd, 0);
+	if (err < 0) {
 		dev_err(&port->device, "Port IRQ resource missing\n");
-		return omap_port->irq;
+		return err;
 	}
+	omap_port->irq = err;
 	tasklet_init(&omap_port->pio_tasklet, ssi_pio_tasklet,
 							(unsigned long)port);
 	err = devm_request_irq(&port->device, omap_port->irq, ssi_pio_isr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hv/channel.c linux-libre-3.17-rc7-gnu/drivers/hv/channel.c
--- linux-libre-3.16-gnu/drivers/hv/channel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hv/channel.c	2014-09-28 17:29:07.000000000 -0400
@@ -808,12 +808,8 @@ int vmbus_recvpacket_raw(struct vmbus_ch
 
 	*buffer_actual_len = packetlen;
 
-	if (packetlen > bufferlen) {
-		pr_err("Buffer too small - needed %d bytes but "
-			"got space for only %d bytes\n",
-			packetlen, bufferlen);
+	if (packetlen > bufferlen)
 		return -ENOBUFS;
-	}
 
 	*requestid = desc.trans_id;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ad7414.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ad7414.c
--- linux-libre-3.16-gnu/drivers/hwmon/ad7414.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ad7414.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@
 static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW };
 
 struct ad7414_data {
-	struct device		*hwmon_dev;
+	struct i2c_client	*client;
 	struct mutex		lock;	/* atomic read data updates */
 	char			valid;	/* !=0 if following fields are valid */
 	unsigned long		next_update;	/* In jiffies */
@@ -72,8 +72,8 @@ static inline int ad7414_write(struct i2
 
 static struct ad7414_data *ad7414_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7414_data *data = i2c_get_clientdata(client);
+	struct ad7414_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->lock);
 
@@ -127,8 +127,8 @@ static ssize_t set_max_min(struct device
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7414_data *data = i2c_get_clientdata(client);
+	struct ad7414_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int index = to_sensor_dev_attr(attr)->index;
 	u8 reg = AD7414_REG_LIMIT[index];
 	long temp;
@@ -164,7 +164,7 @@ static ssize_t show_alarm(struct device
 static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3);
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 
-static struct attribute *ad7414_attributes[] = {
+static struct attribute *ad7414_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -173,27 +173,25 @@ static struct attribute *ad7414_attribut
 	NULL
 };
 
-static const struct attribute_group ad7414_group = {
-	.attrs = ad7414_attributes,
-};
+ATTRIBUTE_GROUPS(ad7414);
 
 static int ad7414_probe(struct i2c_client *client,
 			const struct i2c_device_id *dev_id)
 {
+	struct device *dev = &client->dev;
 	struct ad7414_data *data;
+	struct device *hwmon_dev;
 	int conf;
-	int err;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 				     I2C_FUNC_SMBUS_READ_WORD_DATA))
 		return -EOPNOTSUPP;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct ad7414_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct ad7414_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->lock);
 
 	dev_info(&client->dev, "chip found\n");
@@ -201,38 +199,16 @@ static int ad7414_probe(struct i2c_clien
 	/* Make sure the chip is powered up. */
 	conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF);
 	if (conf < 0)
-		dev_warn(&client->dev,
-			 "ad7414_probe unable to read config register.\n");
+		dev_warn(dev, "ad7414_probe unable to read config register.\n");
 	else {
 		conf &= ~(1 << 7);
 		i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf);
 	}
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &ad7414_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &ad7414_group);
-	return err;
-}
-
-static int ad7414_remove(struct i2c_client *client)
-{
-	struct ad7414_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ad7414_group);
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+							   client->name,
+							   data, ad7414_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ad7414_id[] = {
@@ -246,7 +222,6 @@ static struct i2c_driver ad7414_driver =
 		.name	= "ad7414",
 	},
 	.probe	= ad7414_probe,
-	.remove	= ad7414_remove,
 	.id_table = ad7414_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ad7418.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ad7418.c
--- linux-libre-3.16-gnu/drivers/hwmon/ad7418.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ad7418.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,8 +44,7 @@ static const u8 AD7418_REG_TEMP[] = { AD
 					AD7418_REG_TEMP_OS };
 
 struct ad7418_data {
-	struct device		*hwmon_dev;
-	struct attribute_group	attrs;
+	struct i2c_client	*client;
 	enum chips		type;
 	struct mutex		lock;
 	int			adc_max;	/* number of ADC channels */
@@ -55,48 +54,10 @@ struct ad7418_data {
 	u16			in[4];
 };
 
-static int ad7418_probe(struct i2c_client *client,
-			const struct i2c_device_id *id);
-static int ad7418_remove(struct i2c_client *client);
-
-static const struct i2c_device_id ad7418_id[] = {
-	{ "ad7416", ad7416 },
-	{ "ad7417", ad7417 },
-	{ "ad7418", ad7418 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, ad7418_id);
-
-static struct i2c_driver ad7418_driver = {
-	.driver = {
-		.name	= "ad7418",
-	},
-	.probe		= ad7418_probe,
-	.remove		= ad7418_remove,
-	.id_table	= ad7418_id,
-};
-
-static void ad7418_init_client(struct i2c_client *client)
-{
-	struct ad7418_data *data = i2c_get_clientdata(client);
-
-	int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
-	if (reg < 0) {
-		dev_err(&client->dev, "cannot read configuration register\n");
-	} else {
-		dev_info(&client->dev, "configuring for mode 1\n");
-		i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
-
-		if (data->type == ad7417 || data->type == ad7418)
-			i2c_smbus_write_byte_data(client,
-						AD7418_REG_CONF2, 0x00);
-	}
-}
-
 static struct ad7418_data *ad7418_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7418_data *data = i2c_get_clientdata(client);
+	struct ad7418_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->lock);
 
@@ -165,8 +126,8 @@ static ssize_t set_temp(struct device *d
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7418_data *data = i2c_get_clientdata(client);
+	struct ad7418_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	int ret = kstrtol(buf, 10, &temp);
 
@@ -193,14 +154,15 @@ static SENSOR_DEVICE_ATTR(in2_input, S_I
 static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2);
 static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3);
 
-static struct attribute *ad7416_attributes[] = {
+static struct attribute *ad7416_attrs[] = {
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	NULL
 };
+ATTRIBUTE_GROUPS(ad7416);
 
-static struct attribute *ad7417_attributes[] = {
+static struct attribute *ad7417_attrs[] = {
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -210,83 +172,100 @@ static struct attribute *ad7417_attribut
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	NULL
 };
+ATTRIBUTE_GROUPS(ad7417);
 
-static struct attribute *ad7418_attributes[] = {
+static struct attribute *ad7418_attrs[] = {
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	NULL
 };
+ATTRIBUTE_GROUPS(ad7418);
+
+static void ad7418_init_client(struct i2c_client *client)
+{
+	struct ad7418_data *data = i2c_get_clientdata(client);
+
+	int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+	if (reg < 0) {
+		dev_err(&client->dev, "cannot read configuration register\n");
+	} else {
+		dev_info(&client->dev, "configuring for mode 1\n");
+		i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
+
+		if (data->type == ad7417 || data->type == ad7418)
+			i2c_smbus_write_byte_data(client,
+						AD7418_REG_CONF2, 0x00);
+	}
+}
 
 static int ad7418_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct i2c_adapter *adapter = client->adapter;
 	struct ad7418_data *data;
-	int err;
+	struct device *hwmon_dev;
+	const struct attribute_group **attr_groups = NULL;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 					I2C_FUNC_SMBUS_WORD_DATA))
 		return -EOPNOTSUPP;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct ad7418_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 
 	mutex_init(&data->lock);
+	data->client = client;
 	data->type = id->driver_data;
 
 	switch (data->type) {
 	case ad7416:
 		data->adc_max = 0;
-		data->attrs.attrs = ad7416_attributes;
+		attr_groups = ad7416_groups;
 		break;
 
 	case ad7417:
 		data->adc_max = 4;
-		data->attrs.attrs = ad7417_attributes;
+		attr_groups = ad7417_groups;
 		break;
 
 	case ad7418:
 		data->adc_max = 1;
-		data->attrs.attrs = ad7418_attributes;
+		attr_groups = ad7418_groups;
 		break;
 	}
 
-	dev_info(&client->dev, "%s chip found\n", client->name);
+	dev_info(dev, "%s chip found\n", client->name);
 
 	/* Initialize the AD7418 chip */
 	ad7418_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+							   client->name,
+							   data, attr_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int ad7418_remove(struct i2c_client *client)
-{
-	struct ad7418_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	return 0;
-}
+static const struct i2c_device_id ad7418_id[] = {
+	{ "ad7416", ad7416 },
+	{ "ad7417", ad7417 },
+	{ "ad7418", ad7418 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad7418_id);
+
+static struct i2c_driver ad7418_driver = {
+	.driver = {
+		.name	= "ad7418",
+	},
+	.probe		= ad7418_probe,
+	.id_table	= ad7418_id,
+};
 
 module_i2c_driver(ad7418_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm1021.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1021.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm1021.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1021.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,41 +98,63 @@ struct adm1021_data {
 	u8 remote_temp_offset_prec;
 };
 
-static int adm1021_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm1021_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static void adm1021_init_client(struct i2c_client *client);
-static struct adm1021_data *adm1021_update_device(struct device *dev);
-
 /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
 static bool read_only;
 
+static struct adm1021_data *adm1021_update_device(struct device *dev)
+{
+	struct adm1021_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
-static const struct i2c_device_id adm1021_id[] = {
-	{ "adm1021", adm1021 },
-	{ "adm1023", adm1023 },
-	{ "max1617", max1617 },
-	{ "max1617a", max1617a },
-	{ "thmc10", thmc10 },
-	{ "lm84", lm84 },
-	{ "gl523sm", gl523sm },
-	{ "mc1066", mc1066 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm1021_id);
+	mutex_lock(&data->update_lock);
 
-/* This is the driver that will be inserted */
-static struct i2c_driver adm1021_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adm1021",
-	},
-	.probe		= adm1021_probe,
-	.id_table	= adm1021_id,
-	.detect		= adm1021_detect,
-	.address_list	= normal_i2c,
-};
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		int i;
+
+		dev_dbg(dev, "Starting adm1021 update\n");
+
+		for (i = 0; i < 2; i++) {
+			data->temp[i] = 1000 *
+				(s8) i2c_smbus_read_byte_data(
+					client, ADM1021_REG_TEMP(i));
+			data->temp_max[i] = 1000 *
+				(s8) i2c_smbus_read_byte_data(
+					client, ADM1021_REG_TOS_R(i));
+			if (data->type != lm84) {
+				data->temp_min[i] = 1000 *
+				  (s8) i2c_smbus_read_byte_data(client,
+							ADM1021_REG_THYST_R(i));
+			}
+		}
+		data->alarms = i2c_smbus_read_byte_data(client,
+						ADM1021_REG_STATUS) & 0x7c;
+		if (data->type == adm1023) {
+			/*
+			 * The ADM1023 provides 3 extra bits of precision for
+			 * the remote sensor in extra registers.
+			 */
+			data->temp[1] += 125 * (i2c_smbus_read_byte_data(
+				client, ADM1023_REG_REM_TEMP_PREC) >> 5);
+			data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
+				client, ADM1023_REG_REM_TOS_PREC) >> 5);
+			data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
+				client, ADM1023_REG_REM_THYST_PREC) >> 5);
+			data->remote_temp_offset =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_OFFSET);
+			data->remote_temp_offset_prec =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_OFFSET_PREC);
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 static ssize_t show_temp(struct device *dev,
 			 struct device_attribute *devattr, char *buf)
@@ -411,6 +433,15 @@ static int adm1021_detect(struct i2c_cli
 	return 0;
 }
 
+static void adm1021_init_client(struct i2c_client *client)
+{
+	/* Enable ADC and disable suspend mode */
+	i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
+		i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
+	/* Set Conversion rate to 1/sec (this can be tinkered with) */
+	i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
+}
+
 static int adm1021_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -440,69 +471,29 @@ static int adm1021_probe(struct i2c_clie
 	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static void adm1021_init_client(struct i2c_client *client)
-{
-	/* Enable ADC and disable suspend mode */
-	i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
-		i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
-	/* Set Conversion rate to 1/sec (this can be tinkered with) */
-	i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
-}
-
-static struct adm1021_data *adm1021_update_device(struct device *dev)
-{
-	struct adm1021_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		int i;
-
-		dev_dbg(dev, "Starting adm1021 update\n");
-
-		for (i = 0; i < 2; i++) {
-			data->temp[i] = 1000 *
-				(s8) i2c_smbus_read_byte_data(
-					client, ADM1021_REG_TEMP(i));
-			data->temp_max[i] = 1000 *
-				(s8) i2c_smbus_read_byte_data(
-					client, ADM1021_REG_TOS_R(i));
-			if (data->type != lm84) {
-				data->temp_min[i] = 1000 *
-				  (s8) i2c_smbus_read_byte_data(client,
-							ADM1021_REG_THYST_R(i));
-			}
-		}
-		data->alarms = i2c_smbus_read_byte_data(client,
-						ADM1021_REG_STATUS) & 0x7c;
-		if (data->type == adm1023) {
-			/*
-			 * The ADM1023 provides 3 extra bits of precision for
-			 * the remote sensor in extra registers.
-			 */
-			data->temp[1] += 125 * (i2c_smbus_read_byte_data(
-				client, ADM1023_REG_REM_TEMP_PREC) >> 5);
-			data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
-				client, ADM1023_REG_REM_TOS_PREC) >> 5);
-			data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
-				client, ADM1023_REG_REM_THYST_PREC) >> 5);
-			data->remote_temp_offset =
-				i2c_smbus_read_byte_data(client,
-						ADM1023_REG_REM_OFFSET);
-			data->remote_temp_offset_prec =
-				i2c_smbus_read_byte_data(client,
-						ADM1023_REG_REM_OFFSET_PREC);
-		}
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
-
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1021_id[] = {
+	{ "adm1021", adm1021 },
+	{ "adm1023", adm1023 },
+	{ "max1617", max1617 },
+	{ "max1617a", max1617a },
+	{ "thmc10", thmc10 },
+	{ "lm84", lm84 },
+	{ "gl523sm", gl523sm },
+	{ "mc1066", mc1066 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm1021_id);
 
-	return data;
-}
+static struct i2c_driver adm1021_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adm1021",
+	},
+	.probe		= adm1021_probe,
+	.id_table	= adm1021_id,
+	.detect		= adm1021_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm1021_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm1025.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1025.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm1025.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1025.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,46 +103,12 @@ static const int in_scale[6] = { 2500, 2
 				   (val) + 500) / 1000))
 
 /*
- * Functions declaration
- */
-
-static int adm1025_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm1025_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static void adm1025_init_client(struct i2c_client *client);
-static int adm1025_remove(struct i2c_client *client);
-static struct adm1025_data *adm1025_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id adm1025_id[] = {
-	{ "adm1025", adm1025 },
-	{ "ne1619", ne1619 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm1025_id);
-
-static struct i2c_driver adm1025_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adm1025",
-	},
-	.probe		= adm1025_probe,
-	.remove		= adm1025_remove,
-	.id_table	= adm1025_id,
-	.detect		= adm1025_detect,
-	.address_list	= normal_i2c,
-};
-
-/*
  * Client data (each client gets its own)
  */
 
 struct adm1025_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -158,6 +124,51 @@ struct adm1025_data {
 	u8 vrm;
 };
 
+static struct adm1025_data *adm1025_update_device(struct device *dev)
+{
+	struct adm1025_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
+		int i;
+
+		dev_dbg(&client->dev, "Updating data.\n");
+		for (i = 0; i < 6; i++) {
+			data->in[i] = i2c_smbus_read_byte_data(client,
+				      ADM1025_REG_IN(i));
+			data->in_min[i] = i2c_smbus_read_byte_data(client,
+					  ADM1025_REG_IN_MIN(i));
+			data->in_max[i] = i2c_smbus_read_byte_data(client,
+					  ADM1025_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 2; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+					ADM1025_REG_TEMP(i));
+			data->temp_min[i] = i2c_smbus_read_byte_data(client,
+					    ADM1025_REG_TEMP_LOW(i));
+			data->temp_max[i] = i2c_smbus_read_byte_data(client,
+					    ADM1025_REG_TEMP_HIGH(i));
+		}
+		data->alarms = i2c_smbus_read_byte_data(client,
+			       ADM1025_REG_STATUS1)
+			     | (i2c_smbus_read_byte_data(client,
+				ADM1025_REG_STATUS2) << 8);
+		data->vid = (i2c_smbus_read_byte_data(client,
+			     ADM1025_REG_VID) & 0x0f)
+			  | ((i2c_smbus_read_byte_data(client,
+			      ADM1025_REG_VID4) & 0x01) << 4);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
 /*
  * Sysfs stuff
  */
@@ -217,8 +228,8 @@ static ssize_t set_in_min(struct device
 			  const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	struct adm1025_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -238,8 +249,8 @@ static ssize_t set_in_max(struct device
 			  const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	struct adm1025_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -273,8 +284,8 @@ static ssize_t set_temp_min(struct devic
 			    const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	struct adm1025_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -294,8 +305,8 @@ static ssize_t set_temp_max(struct devic
 	const char *buf, size_t count)
 {
 	int index = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	struct adm1025_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -371,6 +382,9 @@ static ssize_t set_vrm(struct device *de
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
@@ -470,51 +484,6 @@ static int adm1025_detect(struct i2c_cli
 	return 0;
 }
 
-static int adm1025_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct adm1025_data *data;
-	int err;
-	u8 config;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct adm1025_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	/* Initialize the ADM1025 chip */
-	adm1025_init_client(client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &adm1025_group);
-	if (err)
-		return err;
-
-	/* Pin 11 is either in4 (+12V) or VID4 */
-	config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
-	if (!(config & 0x20)) {
-		err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4);
-		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;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &adm1025_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
-	return err;
-}
-
 static void adm1025_init_client(struct i2c_client *client)
 {
 	u8 reg;
@@ -557,61 +526,54 @@ static void adm1025_init_client(struct i
 					  (reg&0x7E)|0x01);
 }
 
-static int adm1025_remove(struct i2c_client *client)
+static int adm1025_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
-	struct adm1025_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm1025_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
-
-	return 0;
-}
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct adm1025_data *data;
+	u8 config;
 
-static struct adm1025_data *adm1025_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	data = devm_kzalloc(dev, sizeof(struct adm1025_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	mutex_lock(&data->update_lock);
+	i2c_set_clientdata(client, data);
+	data->client = client;
+	mutex_init(&data->update_lock);
 
-	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
-		int i;
+	/* Initialize the ADM1025 chip */
+	adm1025_init_client(client);
 
-		dev_dbg(&client->dev, "Updating data.\n");
-		for (i = 0; i < 6; i++) {
-			data->in[i] = i2c_smbus_read_byte_data(client,
-				      ADM1025_REG_IN(i));
-			data->in_min[i] = i2c_smbus_read_byte_data(client,
-					  ADM1025_REG_IN_MIN(i));
-			data->in_max[i] = i2c_smbus_read_byte_data(client,
-					  ADM1025_REG_IN_MAX(i));
-		}
-		for (i = 0; i < 2; i++) {
-			data->temp[i] = i2c_smbus_read_byte_data(client,
-					ADM1025_REG_TEMP(i));
-			data->temp_min[i] = i2c_smbus_read_byte_data(client,
-					    ADM1025_REG_TEMP_LOW(i));
-			data->temp_max[i] = i2c_smbus_read_byte_data(client,
-					    ADM1025_REG_TEMP_HIGH(i));
-		}
-		data->alarms = i2c_smbus_read_byte_data(client,
-			       ADM1025_REG_STATUS1)
-			     | (i2c_smbus_read_byte_data(client,
-				ADM1025_REG_STATUS2) << 8);
-		data->vid = (i2c_smbus_read_byte_data(client,
-			     ADM1025_REG_VID) & 0x0f)
-			  | ((i2c_smbus_read_byte_data(client,
-			      ADM1025_REG_VID4) & 0x01) << 4);
+	/* sysfs hooks */
+	data->groups[0] = &adm1025_group;
+	/* Pin 11 is either in4 (+12V) or VID4 */
+	config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
+	if (!(config & 0x20))
+		data->groups[1] = &adm1025_group_in4;
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1025_id[] = {
+	{ "adm1025", adm1025 },
+	{ "ne1619", ne1619 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm1025_id);
 
-	return data;
-}
+static struct i2c_driver adm1025_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adm1025",
+	},
+	.probe		= adm1025_probe,
+	.id_table	= adm1025_id,
+	.detect		= adm1025_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm1025_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm1026.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1026.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm1026.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1026.c	2014-09-28 17:29:07.000000000 -0400
@@ -266,7 +266,8 @@ struct pwm_data {
 };
 
 struct adm1026_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 
 	struct mutex update_lock;
 	int valid;		/* !=0 if following fields are valid */
@@ -298,37 +299,6 @@ struct adm1026_data {
 	u8 config3;		/* Register value */
 };
 
-static int adm1026_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm1026_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int adm1026_remove(struct i2c_client *client);
-static int adm1026_read_value(struct i2c_client *client, u8 reg);
-static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
-static void adm1026_print_gpio(struct i2c_client *client);
-static void adm1026_fixup_gpio(struct i2c_client *client);
-static struct adm1026_data *adm1026_update_device(struct device *dev);
-static void adm1026_init_client(struct i2c_client *client);
-
-
-static const struct i2c_device_id adm1026_id[] = {
-	{ "adm1026", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm1026_id);
-
-static struct i2c_driver adm1026_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adm1026",
-	},
-	.probe		= adm1026_probe,
-	.remove		= adm1026_remove,
-	.id_table	= adm1026_id,
-	.detect		= adm1026_detect,
-	.address_list	= normal_i2c,
-};
-
 static int adm1026_read_value(struct i2c_client *client, u8 reg)
 {
 	int res;
@@ -357,212 +327,10 @@ static int adm1026_write_value(struct i2
 	return res;
 }
 
-static void adm1026_init_client(struct i2c_client *client)
-{
-	int value, i;
-	struct adm1026_data *data = i2c_get_clientdata(client);
-
-	dev_dbg(&client->dev, "Initializing device\n");
-	/* Read chip config */
-	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
-	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
-	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
-
-	/* Inform user of chip config */
-	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
-		data->config1);
-	if ((data->config1 & CFG1_MONITOR) == 0) {
-		dev_dbg(&client->dev,
-			"Monitoring not currently enabled.\n");
-	}
-	if (data->config1 & CFG1_INT_ENABLE) {
-		dev_dbg(&client->dev,
-			"SMBALERT interrupts are enabled.\n");
-	}
-	if (data->config1 & CFG1_AIN8_9) {
-		dev_dbg(&client->dev,
-			"in8 and in9 enabled. temp3 disabled.\n");
-	} else {
-		dev_dbg(&client->dev,
-			"temp3 enabled.  in8 and in9 disabled.\n");
-	}
-	if (data->config1 & CFG1_THERM_HOT) {
-		dev_dbg(&client->dev,
-			"Automatic THERM, PWM, and temp limits enabled.\n");
-	}
-
-	if (data->config3 & CFG3_GPIO16_ENABLE) {
-		dev_dbg(&client->dev,
-			"GPIO16 enabled.  THERM pin disabled.\n");
-	} else {
-		dev_dbg(&client->dev,
-			"THERM pin enabled.  GPIO16 disabled.\n");
-	}
-	if (data->config3 & CFG3_VREF_250)
-		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
-	else
-		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
-	/* Read and pick apart the existing GPIO configuration */
-	value = 0;
-	for (i = 0; i <= 15; ++i) {
-		if ((i & 0x03) == 0) {
-			value = adm1026_read_value(client,
-					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
-		}
-		data->gpio_config[i] = value & 0x03;
-		value >>= 2;
-	}
-	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
-
-	/* ... and then print it */
-	adm1026_print_gpio(client);
-
-	/*
-	 * If the user asks us to reprogram the GPIO config, then
-	 * do it now.
-	 */
-	if (gpio_input[0] != -1 || gpio_output[0] != -1
-		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
-		|| gpio_fan[0] != -1) {
-		adm1026_fixup_gpio(client);
-	}
-
-	/*
-	 * WE INTENTIONALLY make no changes to the limits,
-	 *   offsets, pwms, fans and zones.  If they were
-	 *   configured, we don't want to mess with them.
-	 *   If they weren't, the default is 100% PWM, no
-	 *   control and will suffice until 'sensors -s'
-	 *   can be run by the user.  We DO set the default
-	 *   value for pwm1.auto_pwm_min to its maximum
-	 *   so that enabling automatic pwm fan control
-	 *   without first setting a value for pwm1.auto_pwm_min
-	 *   will not result in potentially dangerous fan speed decrease.
-	 */
-	data->pwm1.auto_pwm_min = 255;
-	/* Start monitoring */
-	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
-	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
-	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
-	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
-	data->config1 = value;
-	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
-
-	/* initialize fan_div[] to hardware defaults */
-	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
-		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
-	for (i = 0; i <= 7; ++i) {
-		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
-		value >>= 2;
-	}
-}
-
-static void adm1026_print_gpio(struct i2c_client *client)
-{
-	struct adm1026_data *data = i2c_get_clientdata(client);
-	int i;
-
-	dev_dbg(&client->dev, "GPIO config is:\n");
-	for (i = 0; i <= 7; ++i) {
-		if (data->config2 & (1 << i)) {
-			dev_dbg(&client->dev, "\t%sGP%s%d\n",
-				data->gpio_config[i] & 0x02 ? "" : "!",
-				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
-				i);
-		} else {
-			dev_dbg(&client->dev, "\tFAN%d\n", i);
-		}
-	}
-	for (i = 8; i <= 15; ++i) {
-		dev_dbg(&client->dev, "\t%sGP%s%d\n",
-			data->gpio_config[i] & 0x02 ? "" : "!",
-			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
-			i);
-	}
-	if (data->config3 & CFG3_GPIO16_ENABLE) {
-		dev_dbg(&client->dev, "\t%sGP%s16\n",
-			data->gpio_config[16] & 0x02 ? "" : "!",
-			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
-	} else {
-		/* GPIO16 is THERM */
-		dev_dbg(&client->dev, "\tTHERM\n");
-	}
-}
-
-static void adm1026_fixup_gpio(struct i2c_client *client)
-{
-	struct adm1026_data *data = i2c_get_clientdata(client);
-	int i;
-	int value;
-
-	/* Make the changes requested. */
-	/*
-	 * We may need to unlock/stop monitoring or soft-reset the
-	 *    chip before we can make changes.  This hasn't been
-	 *    tested much.  FIXME
-	 */
-
-	/* Make outputs */
-	for (i = 0; i <= 16; ++i) {
-		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
-			data->gpio_config[gpio_output[i]] |= 0x01;
-		/* if GPIO0-7 is output, it isn't a FAN tach */
-		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
-			data->config2 |= 1 << gpio_output[i];
-	}
-
-	/* Input overrides output */
-	for (i = 0; i <= 16; ++i) {
-		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
-			data->gpio_config[gpio_input[i]] &= ~0x01;
-		/* if GPIO0-7 is input, it isn't a FAN tach */
-		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
-			data->config2 |= 1 << gpio_input[i];
-	}
-
-	/* Inverted */
-	for (i = 0; i <= 16; ++i) {
-		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
-			data->gpio_config[gpio_inverted[i]] &= ~0x02;
-	}
-
-	/* Normal overrides inverted */
-	for (i = 0; i <= 16; ++i) {
-		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
-			data->gpio_config[gpio_normal[i]] |= 0x02;
-	}
-
-	/* Fan overrides input and output */
-	for (i = 0; i <= 7; ++i) {
-		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
-			data->config2 &= ~(1 << gpio_fan[i]);
-	}
-
-	/* Write new configs to registers */
-	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
-	data->config3 = (data->config3 & 0x3f)
-			| ((data->gpio_config[16] & 0x03) << 6);
-	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
-	for (i = 15, value = 0; i >= 0; --i) {
-		value <<= 2;
-		value |= data->gpio_config[i] & 0x03;
-		if ((i & 0x03) == 0) {
-			adm1026_write_value(client,
-					ADM1026_REG_GPIO_CFG_0_3 + i/4,
-					value);
-			value = 0;
-		}
-	}
-
-	/* Print the new config */
-	adm1026_print_gpio(client);
-}
-
-
 static struct adm1026_data *adm1026_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int i;
 	long value, alarms, gpio;
 
@@ -728,8 +496,8 @@ static ssize_t set_in_min(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -756,8 +524,8 @@ static ssize_t set_in_max(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -815,8 +583,8 @@ static ssize_t show_in16_min(struct devi
 static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -840,8 +608,8 @@ static ssize_t show_in16_max(struct devi
 static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -888,8 +656,8 @@ static ssize_t set_fan_min(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -923,8 +691,8 @@ fan_offset(8);
 /* Adjust fan_min to account for new fan divisor */
 static void fixup_fan_min(struct device *dev, int fan, int old_div)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int new_min;
 	int new_div = data->fan_div[fan];
 
@@ -952,8 +720,8 @@ static ssize_t set_fan_div(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int orig_div, new_div;
 	int err;
@@ -1024,8 +792,8 @@ static ssize_t set_temp_min(struct devic
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1053,8 +821,8 @@ static ssize_t set_temp_max(struct devic
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1097,8 +865,8 @@ static ssize_t set_temp_offset(struct de
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1153,8 +921,8 @@ static ssize_t set_temp_auto_point1_temp
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1192,8 +960,8 @@ static ssize_t show_temp_crit_enable(str
 static ssize_t set_temp_crit_enable(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1233,8 +1001,8 @@ static ssize_t set_temp_crit(struct devi
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1268,8 +1036,8 @@ static ssize_t set_analog_out_reg(struct
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1317,6 +1085,9 @@ static ssize_t store_vrm_reg(struct devi
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
@@ -1378,8 +1149,8 @@ static ssize_t show_alarm_mask(struct de
 static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long mask;
 	long val;
 	int err;
@@ -1420,8 +1191,8 @@ static ssize_t show_gpio(struct device *
 static ssize_t set_gpio(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long gpio;
 	long val;
 	int err;
@@ -1453,8 +1224,8 @@ static ssize_t show_gpio_mask(struct dev
 static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long mask;
 	long val;
 	int err;
@@ -1487,8 +1258,8 @@ static ssize_t show_pwm_reg(struct devic
 static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	if (data->pwm1.enable == 1) {
 		long val;
@@ -1517,8 +1288,8 @@ static ssize_t set_auto_pwm_min(struct d
 				struct device_attribute *attr, const char *buf,
 				size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1553,8 +1324,8 @@ static ssize_t show_pwm_enable(struct de
 static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int old_enable;
 	unsigned long val;
 	int err;
@@ -1829,18 +1600,220 @@ static int adm1026_detect(struct i2c_cli
 	return 0;
 }
 
+static void adm1026_print_gpio(struct i2c_client *client)
+{
+	struct adm1026_data *data = i2c_get_clientdata(client);
+	int i;
+
+	dev_dbg(&client->dev, "GPIO config is:\n");
+	for (i = 0; i <= 7; ++i) {
+		if (data->config2 & (1 << i)) {
+			dev_dbg(&client->dev, "\t%sGP%s%d\n",
+				data->gpio_config[i] & 0x02 ? "" : "!",
+				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
+				i);
+		} else {
+			dev_dbg(&client->dev, "\tFAN%d\n", i);
+		}
+	}
+	for (i = 8; i <= 15; ++i) {
+		dev_dbg(&client->dev, "\t%sGP%s%d\n",
+			data->gpio_config[i] & 0x02 ? "" : "!",
+			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
+			i);
+	}
+	if (data->config3 & CFG3_GPIO16_ENABLE) {
+		dev_dbg(&client->dev, "\t%sGP%s16\n",
+			data->gpio_config[16] & 0x02 ? "" : "!",
+			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
+	} else {
+		/* GPIO16 is THERM */
+		dev_dbg(&client->dev, "\tTHERM\n");
+	}
+}
+
+static void adm1026_fixup_gpio(struct i2c_client *client)
+{
+	struct adm1026_data *data = i2c_get_clientdata(client);
+	int i;
+	int value;
+
+	/* Make the changes requested. */
+	/*
+	 * We may need to unlock/stop monitoring or soft-reset the
+	 *    chip before we can make changes.  This hasn't been
+	 *    tested much.  FIXME
+	 */
+
+	/* Make outputs */
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
+			data->gpio_config[gpio_output[i]] |= 0x01;
+		/* if GPIO0-7 is output, it isn't a FAN tach */
+		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
+			data->config2 |= 1 << gpio_output[i];
+	}
+
+	/* Input overrides output */
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
+			data->gpio_config[gpio_input[i]] &= ~0x01;
+		/* if GPIO0-7 is input, it isn't a FAN tach */
+		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
+			data->config2 |= 1 << gpio_input[i];
+	}
+
+	/* Inverted */
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
+			data->gpio_config[gpio_inverted[i]] &= ~0x02;
+	}
+
+	/* Normal overrides inverted */
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
+			data->gpio_config[gpio_normal[i]] |= 0x02;
+	}
+
+	/* Fan overrides input and output */
+	for (i = 0; i <= 7; ++i) {
+		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
+			data->config2 &= ~(1 << gpio_fan[i]);
+	}
+
+	/* Write new configs to registers */
+	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
+	data->config3 = (data->config3 & 0x3f)
+			| ((data->gpio_config[16] & 0x03) << 6);
+	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
+	for (i = 15, value = 0; i >= 0; --i) {
+		value <<= 2;
+		value |= data->gpio_config[i] & 0x03;
+		if ((i & 0x03) == 0) {
+			adm1026_write_value(client,
+					ADM1026_REG_GPIO_CFG_0_3 + i/4,
+					value);
+			value = 0;
+		}
+	}
+
+	/* Print the new config */
+	adm1026_print_gpio(client);
+}
+
+static void adm1026_init_client(struct i2c_client *client)
+{
+	int value, i;
+	struct adm1026_data *data = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "Initializing device\n");
+	/* Read chip config */
+	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
+	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
+	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
+
+	/* Inform user of chip config */
+	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
+		data->config1);
+	if ((data->config1 & CFG1_MONITOR) == 0) {
+		dev_dbg(&client->dev,
+			"Monitoring not currently enabled.\n");
+	}
+	if (data->config1 & CFG1_INT_ENABLE) {
+		dev_dbg(&client->dev,
+			"SMBALERT interrupts are enabled.\n");
+	}
+	if (data->config1 & CFG1_AIN8_9) {
+		dev_dbg(&client->dev,
+			"in8 and in9 enabled. temp3 disabled.\n");
+	} else {
+		dev_dbg(&client->dev,
+			"temp3 enabled.  in8 and in9 disabled.\n");
+	}
+	if (data->config1 & CFG1_THERM_HOT) {
+		dev_dbg(&client->dev,
+			"Automatic THERM, PWM, and temp limits enabled.\n");
+	}
+
+	if (data->config3 & CFG3_GPIO16_ENABLE) {
+		dev_dbg(&client->dev,
+			"GPIO16 enabled.  THERM pin disabled.\n");
+	} else {
+		dev_dbg(&client->dev,
+			"THERM pin enabled.  GPIO16 disabled.\n");
+	}
+	if (data->config3 & CFG3_VREF_250)
+		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
+	else
+		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
+	/* Read and pick apart the existing GPIO configuration */
+	value = 0;
+	for (i = 0; i <= 15; ++i) {
+		if ((i & 0x03) == 0) {
+			value = adm1026_read_value(client,
+					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
+		}
+		data->gpio_config[i] = value & 0x03;
+		value >>= 2;
+	}
+	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
+
+	/* ... and then print it */
+	adm1026_print_gpio(client);
+
+	/*
+	 * If the user asks us to reprogram the GPIO config, then
+	 * do it now.
+	 */
+	if (gpio_input[0] != -1 || gpio_output[0] != -1
+		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
+		|| gpio_fan[0] != -1) {
+		adm1026_fixup_gpio(client);
+	}
+
+	/*
+	 * WE INTENTIONALLY make no changes to the limits,
+	 *   offsets, pwms, fans and zones.  If they were
+	 *   configured, we don't want to mess with them.
+	 *   If they weren't, the default is 100% PWM, no
+	 *   control and will suffice until 'sensors -s'
+	 *   can be run by the user.  We DO set the default
+	 *   value for pwm1.auto_pwm_min to its maximum
+	 *   so that enabling automatic pwm fan control
+	 *   without first setting a value for pwm1.auto_pwm_min
+	 *   will not result in potentially dangerous fan speed decrease.
+	 */
+	data->pwm1.auto_pwm_min = 255;
+	/* Start monitoring */
+	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
+	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
+	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
+	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
+	data->config1 = value;
+	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
+
+	/* initialize fan_div[] to hardware defaults */
+	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
+		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
+	for (i = 0; i <= 7; ++i) {
+		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
+		value >>= 2;
+	}
+}
+
 static int adm1026_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct adm1026_data *data;
-	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct adm1026_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Set the VRM version */
@@ -1849,48 +1822,34 @@ static int adm1026_probe(struct i2c_clie
 	/* Initialize the ADM1026 chip */
 	adm1026_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &adm1026_group);
-	if (err)
-		return err;
+	/* sysfs hooks */
+	data->groups[0] = &adm1026_group;
 	if (data->config1 & CFG1_AIN8_9)
-		err = sysfs_create_group(&client->dev.kobj,
-					 &adm1026_group_in8_9);
+		data->groups[1] = &adm1026_group_in8_9;
 	else
-		err = sysfs_create_group(&client->dev.kobj,
-					 &adm1026_group_temp3);
-	if (err)
-		goto exitremove;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exitremove;
-	}
-
-	return 0;
+		data->groups[1] = &adm1026_group_temp3;
 
-	/* Error out and cleanup code */
-exitremove:
-	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
-	if (data->config1 & CFG1_AIN8_9)
-		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
-	else
-		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int adm1026_remove(struct i2c_client *client)
-{
-	struct adm1026_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
-	if (data->config1 & CFG1_AIN8_9)
-		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
-	else
-		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
-	return 0;
-}
+static const struct i2c_device_id adm1026_id[] = {
+	{ "adm1026", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm1026_id);
+
+static struct i2c_driver adm1026_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adm1026",
+	},
+	.probe		= adm1026_probe,
+	.id_table	= adm1026_id,
+	.detect		= adm1026_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm1026_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm1029.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1029.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm1029.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1029.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,45 +106,11 @@ static const u8 ADM1029_REG_FAN_DIV[] =
 };
 
 /*
- * Functions declaration
- */
-
-static int adm1029_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm1029_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int adm1029_remove(struct i2c_client *client);
-static struct adm1029_data *adm1029_update_device(struct device *dev);
-static int adm1029_init_client(struct i2c_client *client);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id adm1029_id[] = {
-	{ "adm1029", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm1029_id);
-
-static struct i2c_driver adm1029_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name = "adm1029",
-	},
-	.probe		= adm1029_probe,
-	.remove		= adm1029_remove,
-	.id_table	= adm1029_id,
-	.detect		= adm1029_detect,
-	.address_list	= normal_i2c,
-};
-
-/*
  * Client data (each client gets its own)
  */
 
 struct adm1029_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;		/* zero until following fields are valid */
 	unsigned long last_updated;	/* in jiffies */
@@ -156,6 +122,50 @@ struct adm1029_data {
 };
 
 /*
+ * function that update the status of the chips (temperature for example)
+ */
+static struct adm1029_data *adm1029_update_device(struct device *dev)
+{
+	struct adm1029_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	mutex_lock(&data->update_lock);
+	/*
+	 * Use the "cache" Luke, don't recheck values
+	 * if there are already checked not a long time later
+	 */
+	if (time_after(jiffies, data->last_updated + HZ * 2)
+	 || !data->valid) {
+		int nr;
+
+		dev_dbg(&client->dev, "Updating adm1029 data\n");
+
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
+			data->temp[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_TEMP[nr]);
+		}
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
+			data->fan[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_FAN[nr]);
+		}
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
+			data->fan_div[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_FAN_DIV[nr]);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/*
  * Sysfs stuff
  */
 
@@ -197,8 +207,8 @@ show_fan_div(struct device *dev, struct
 static ssize_t set_fan_div(struct device *dev,
 	    struct device_attribute *devattr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1029_data *data = i2c_get_clientdata(client);
+	struct adm1029_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	u8 reg;
 	long val;
@@ -270,7 +280,7 @@ static SENSOR_DEVICE_ATTR(fan1_div, S_IR
 static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
 			  show_fan_div, set_fan_div, 1);
 
-static struct attribute *adm1029_attributes[] = {
+static struct attribute *adm1029_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -289,9 +299,7 @@ static struct attribute *adm1029_attribu
 	NULL
 };
 
-static const struct attribute_group adm1029_group = {
-	.attrs = adm1029_attributes,
-};
+ATTRIBUTE_GROUPS(adm1029);
 
 /*
  * Real code
@@ -340,48 +348,10 @@ static int adm1029_detect(struct i2c_cli
 	return 0;
 }
 
-static int adm1029_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct adm1029_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct adm1029_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	/*
-	 * Initialize the ADM1029 chip
-	 * Check config register
-	 */
-	if (adm1029_init_client(client) == 0)
-		return -ENODEV;
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &adm1029_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
- exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
-	return err;
-}
-
 static int adm1029_init_client(struct i2c_client *client)
 {
 	u8 config;
+
 	config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
 	if ((config & 0x10) == 0) {
 		i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG,
@@ -396,59 +366,49 @@ static int adm1029_init_client(struct i2
 	return 1;
 }
 
-static int adm1029_remove(struct i2c_client *client)
+static int adm1029_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
-	struct adm1029_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
+	struct device *dev = &client->dev;
+	struct adm1029_data *data;
+	struct device *hwmon_dev;
 
-	return 0;
-}
+	data = devm_kzalloc(dev, sizeof(struct adm1029_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-/*
- * function that update the status of the chips (temperature for example)
- */
-static struct adm1029_data *adm1029_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1029_data *data = i2c_get_clientdata(client);
+	data->client = client;
+	mutex_init(&data->update_lock);
 
-	mutex_lock(&data->update_lock);
 	/*
-	 * Use the "cache" Luke, don't recheck values
-	 * if there are already checked not a long time later
+	 * Initialize the ADM1029 chip
+	 * Check config register
 	 */
-	if (time_after(jiffies, data->last_updated + HZ * 2)
-	 || !data->valid) {
-		int nr;
-
-		dev_dbg(&client->dev, "Updating adm1029 data\n");
-
-		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
-			data->temp[nr] =
-			    i2c_smbus_read_byte_data(client,
-						     ADM1029_REG_TEMP[nr]);
-		}
-		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
-			data->fan[nr] =
-			    i2c_smbus_read_byte_data(client,
-						     ADM1029_REG_FAN[nr]);
-		}
-		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
-			data->fan_div[nr] =
-			    i2c_smbus_read_byte_data(client,
-						     ADM1029_REG_FAN_DIV[nr]);
-		}
+	if (adm1029_init_client(client) == 0)
+		return -ENODEV;
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   adm1029_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1029_id[] = {
+	{ "adm1029", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm1029_id);
 
-	return data;
-}
+static struct i2c_driver adm1029_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name = "adm1029",
+	},
+	.probe		= adm1029_probe,
+	.id_table	= adm1029_id,
+	.detect		= adm1029_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm1029_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm1031.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1031.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm1031.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm1031.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,8 @@ typedef u8 auto_chan_table_t[8][2];
 
 /* Each client has this additional data */
 struct adm1031_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	int chip_type;
 	char valid;		/* !=0 if following fields are valid */
@@ -105,34 +106,6 @@ struct adm1031_data {
 	s8 temp_crit[3];
 };
 
-static int adm1031_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm1031_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static void adm1031_init_client(struct i2c_client *client);
-static int adm1031_remove(struct i2c_client *client);
-static struct adm1031_data *adm1031_update_device(struct device *dev);
-
-static const struct i2c_device_id adm1031_id[] = {
-	{ "adm1030", adm1030 },
-	{ "adm1031", adm1031 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm1031_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver adm1031_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name = "adm1031",
-	},
-	.probe		= adm1031_probe,
-	.remove		= adm1031_remove,
-	.id_table	= adm1031_id,
-	.detect		= adm1031_detect,
-	.address_list	= normal_i2c,
-};
-
 static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
@@ -144,6 +117,96 @@ adm1031_write_value(struct i2c_client *c
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
+static struct adm1031_data *adm1031_update_device(struct device *dev)
+{
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	unsigned long next_update;
+	int chan;
+
+	mutex_lock(&data->update_lock);
+
+	next_update = data->last_updated
+	  + msecs_to_jiffies(data->update_interval);
+	if (time_after(jiffies, next_update) || !data->valid) {
+
+		dev_dbg(&client->dev, "Starting adm1031 update\n");
+		for (chan = 0;
+		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
+			u8 oldh, newh;
+
+			oldh =
+			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
+			data->ext_temp[chan] =
+			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
+			newh =
+			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
+			if (newh != oldh) {
+				data->ext_temp[chan] =
+				    adm1031_read_value(client,
+						       ADM1031_REG_EXT_TEMP);
+#ifdef DEBUG
+				oldh =
+				    adm1031_read_value(client,
+						       ADM1031_REG_TEMP(chan));
+
+				/* oldh is actually newer */
+				if (newh != oldh)
+					dev_warn(&client->dev,
+					  "Remote temperature may be wrong.\n");
+#endif
+			}
+			data->temp[chan] = newh;
+
+			data->temp_offset[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_TEMP_OFFSET(chan));
+			data->temp_min[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_TEMP_MIN(chan));
+			data->temp_max[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_TEMP_MAX(chan));
+			data->temp_crit[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_TEMP_CRIT(chan));
+			data->auto_temp[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_AUTO_TEMP(chan));
+
+		}
+
+		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
+		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
+
+		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
+		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
+		if (data->chip_type == adm1030)
+			data->alarm &= 0xc0ff;
+
+		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
+		     chan++) {
+			data->fan_div[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_FAN_DIV(chan));
+			data->fan_min[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_FAN_MIN(chan));
+			data->fan[chan] =
+			    adm1031_read_value(client,
+					       ADM1031_REG_FAN_SPEED(chan));
+			data->pwm[chan] =
+			  (adm1031_read_value(client,
+					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
 					((val + 500) / 1000)))
@@ -280,8 +343,8 @@ static ssize_t
 set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
 		     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	u8 reg;
@@ -355,8 +418,8 @@ static ssize_t
 set_auto_temp_min(struct device *dev, struct device_attribute *attr,
 		  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -385,8 +448,8 @@ static ssize_t
 set_auto_temp_max(struct device *dev, struct device_attribute *attr,
 		  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -428,8 +491,8 @@ static ssize_t show_pwm(struct device *d
 static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret, reg;
@@ -541,8 +604,8 @@ static ssize_t show_fan_min(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 adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -565,8 +628,8 @@ 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 adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	u8 tmp;
@@ -667,8 +730,8 @@ static ssize_t set_temp_offset(struct de
 			       struct device_attribute *attr, const char *buf,
 			       size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -688,8 +751,8 @@ static ssize_t set_temp_offset(struct de
 static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -709,8 +772,8 @@ static ssize_t set_temp_min(struct devic
 static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -730,8 +793,8 @@ static ssize_t set_temp_max(struct devic
 static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
 	int ret;
@@ -807,8 +870,7 @@ static const unsigned int update_interva
 static ssize_t show_update_interval(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%u\n", data->update_interval);
 }
@@ -817,8 +879,8 @@ static ssize_t set_update_interval(struc
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
+	struct adm1031_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int i, err;
 	u8 reg;
@@ -950,64 +1012,6 @@ static int adm1031_detect(struct i2c_cli
 	return 0;
 }
 
-static int adm1031_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct adm1031_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct adm1031_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	data->chip_type = id->driver_data;
-	mutex_init(&data->update_lock);
-
-	if (data->chip_type == adm1030)
-		data->chan_select_table = &auto_channel_select_table_adm1030;
-	else
-		data->chan_select_table = &auto_channel_select_table_adm1031;
-
-	/* Initialize the ADM1031 chip */
-	adm1031_init_client(client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
-	if (err)
-		return err;
-
-	if (data->chip_type == adm1031) {
-		err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
-		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;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
-	return err;
-}
-
-static int adm1031_remove(struct i2c_client *client)
-{
-	struct adm1031_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
-	return 0;
-}
-
 static void adm1031_init_client(struct i2c_client *client)
 {
 	unsigned int read_val;
@@ -1039,96 +1043,57 @@ static void adm1031_init_client(struct i
 	data->update_interval = update_intervals[i];
 }
 
-static struct adm1031_data *adm1031_update_device(struct device *dev)
+static int adm1031_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1031_data *data = i2c_get_clientdata(client);
-	unsigned long next_update;
-	int chan;
-
-	mutex_lock(&data->update_lock);
-
-	next_update = data->last_updated
-	  + msecs_to_jiffies(data->update_interval);
-	if (time_after(jiffies, next_update) || !data->valid) {
-
-		dev_dbg(&client->dev, "Starting adm1031 update\n");
-		for (chan = 0;
-		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
-			u8 oldh, newh;
-
-			oldh =
-			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
-			data->ext_temp[chan] =
-			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
-			newh =
-			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
-			if (newh != oldh) {
-				data->ext_temp[chan] =
-				    adm1031_read_value(client,
-						       ADM1031_REG_EXT_TEMP);
-#ifdef DEBUG
-				oldh =
-				    adm1031_read_value(client,
-						       ADM1031_REG_TEMP(chan));
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct adm1031_data *data;
 
-				/* oldh is actually newer */
-				if (newh != oldh)
-					dev_warn(&client->dev,
-					  "Remote temperature may be wrong.\n");
-#endif
-			}
-			data->temp[chan] = newh;
+	data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-			data->temp_offset[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_TEMP_OFFSET(chan));
-			data->temp_min[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_TEMP_MIN(chan));
-			data->temp_max[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_TEMP_MAX(chan));
-			data->temp_crit[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_TEMP_CRIT(chan));
-			data->auto_temp[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_AUTO_TEMP(chan));
+	i2c_set_clientdata(client, data);
+	data->client = client;
+	data->chip_type = id->driver_data;
+	mutex_init(&data->update_lock);
 
-		}
+	if (data->chip_type == adm1030)
+		data->chan_select_table = &auto_channel_select_table_adm1030;
+	else
+		data->chan_select_table = &auto_channel_select_table_adm1031;
 
-		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
-		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
+	/* Initialize the ADM1031 chip */
+	adm1031_init_client(client);
 
-		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
-		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
-		if (data->chip_type == adm1030)
-			data->alarm &= 0xc0ff;
+	/* sysfs hooks */
+	data->groups[0] = &adm1031_group;
+	if (data->chip_type == adm1031)
+		data->groups[1] = &adm1031_group_opt;
 
-		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
-		     chan++) {
-			data->fan_div[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_FAN_DIV(chan));
-			data->fan_min[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_FAN_MIN(chan));
-			data->fan[chan] =
-			    adm1031_read_value(client,
-					       ADM1031_REG_FAN_SPEED(chan));
-			data->pwm[chan] =
-			  (adm1031_read_value(client,
-					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
-		}
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1031_id[] = {
+	{ "adm1030", adm1030 },
+	{ "adm1031", adm1031 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm1031_id);
 
-	return data;
-}
+static struct i2c_driver adm1031_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name = "adm1031",
+	},
+	.probe		= adm1031_probe,
+	.id_table	= adm1031_id,
+	.detect		= adm1031_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm1031_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adm9240.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adm9240.c
--- linux-libre-3.16-gnu/drivers/hwmon/adm9240.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adm9240.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,38 +130,9 @@ static inline unsigned int AOUT_FROM_REG
 	return SCALE(reg, 1250, 255);
 }
 
-static int adm9240_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adm9240_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static void adm9240_init_client(struct i2c_client *client);
-static int adm9240_remove(struct i2c_client *client);
-static struct adm9240_data *adm9240_update_device(struct device *dev);
-
-/* driver data */
-static const struct i2c_device_id adm9240_id[] = {
-	{ "adm9240", adm9240 },
-	{ "ds1780", ds1780 },
-	{ "lm81", lm81 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adm9240_id);
-
-static struct i2c_driver adm9240_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adm9240",
-	},
-	.probe		= adm9240_probe,
-	.remove		= adm9240_remove,
-	.id_table	= adm9240_id,
-	.detect		= adm9240_detect,
-	.address_list	= normal_i2c,
-};
-
 /* per client data */
 struct adm9240_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;
 	unsigned long last_updated_measure;
@@ -181,6 +152,110 @@ struct adm9240_data {
 	u8 vrm;			/* --	vrm set on startup, no accessor */
 };
 
+/* write new fan div, callers must hold data->update_lock */
+static void adm9240_write_fan_div(struct i2c_client *client, int nr,
+		u8 fan_div)
+{
+	u8 reg, old, shift = (nr + 2) * 2;
+
+	reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
+	old = (reg >> shift) & 3;
+	reg &= ~(3 << shift);
+	reg |= (fan_div << shift);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
+	dev_dbg(&client->dev,
+		"fan%d clock divider changed from %u to %u\n",
+		nr + 1, 1 << old, 1 << fan_div);
+}
+
+static struct adm9240_data *adm9240_update_device(struct device *dev)
+{
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	/* minimum measurement cycle: 1.75 seconds */
+	if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
+			|| !data->valid) {
+
+		for (i = 0; i < 6; i++) { /* read voltages */
+			data->in[i] = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_IN(i));
+		}
+		data->alarms = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_INT(0)) |
+					i2c_smbus_read_byte_data(client,
+					ADM9240_REG_INT(1)) << 8;
+
+		/*
+		 * read temperature: assume temperature changes less than
+		 * 0.5'C per two measurement cycles thus ignore possible
+		 * but unlikely aliasing error on lsb reading. --Grant
+		 */
+		data->temp = ((i2c_smbus_read_byte_data(client,
+					ADM9240_REG_TEMP) << 8) |
+					i2c_smbus_read_byte_data(client,
+					ADM9240_REG_TEMP_CONF)) / 128;
+
+		for (i = 0; i < 2; i++) { /* read fans */
+			data->fan[i] = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_FAN(i));
+
+			/* adjust fan clock divider on overflow */
+			if (data->valid && data->fan[i] == 255 &&
+					data->fan_div[i] < 3) {
+
+				adm9240_write_fan_div(client, i,
+						++data->fan_div[i]);
+
+				/* adjust fan_min if active, but not to 0 */
+				if (data->fan_min[i] < 255 &&
+						data->fan_min[i] >= 2)
+					data->fan_min[i] /= 2;
+			}
+		}
+		data->last_updated_measure = jiffies;
+	}
+
+	/* minimum config reading cycle: 300 seconds */
+	if (time_after(jiffies, data->last_updated_config + (HZ * 300))
+			|| !data->valid) {
+
+		for (i = 0; i < 6; i++) {
+			data->in_min[i] = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_IN_MIN(i));
+			data->in_max[i] = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 2; i++) {
+			data->fan_min[i] = i2c_smbus_read_byte_data(client,
+					ADM9240_REG_FAN_MIN(i));
+		}
+		data->temp_max[0] = i2c_smbus_read_byte_data(client,
+				ADM9240_REG_TEMP_MAX(0));
+		data->temp_max[1] = i2c_smbus_read_byte_data(client,
+				ADM9240_REG_TEMP_MAX(1));
+
+		/* read fan divs and 5-bit VID */
+		i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
+		data->fan_div[0] = (i >> 4) & 3;
+		data->fan_div[1] = (i >> 6) & 3;
+		data->vid = i & 0x0f;
+		data->vid |= (i2c_smbus_read_byte_data(client,
+					ADM9240_REG_VID4) & 1) << 4;
+		/* read analog out */
+		data->aout = i2c_smbus_read_byte_data(client,
+				ADM9240_REG_ANALOG_OUT);
+
+		data->last_updated_config = jiffies;
+		data->valid = 1;
+	}
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
 /*** sysfs accessors ***/
 
 /* temperature */
@@ -203,8 +278,8 @@ static ssize_t set_max(struct device *de
 		const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -259,8 +334,8 @@ static ssize_t set_in_min(struct device
 		const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -281,8 +356,8 @@ static ssize_t set_in_max(struct device
 		const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -340,22 +415,6 @@ static ssize_t show_fan_div(struct devic
 	return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
 }
 
-/* write new fan div, callers must hold data->update_lock */
-static void adm9240_write_fan_div(struct i2c_client *client, int nr,
-		u8 fan_div)
-{
-	u8 reg, old, shift = (nr + 2) * 2;
-
-	reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
-	old = (reg >> shift) & 3;
-	reg &= ~(3 << shift);
-	reg |= (fan_div << shift);
-	i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
-	dev_dbg(&client->dev,
-		"fan%d clock divider changed from %u to %u\n",
-		nr + 1, 1 << old, 1 << fan_div);
-}
-
 /*
  * set fan speed low limit:
  *
@@ -372,8 +431,8 @@ static ssize_t set_fan_min(struct device
 		const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = attr->index;
 	u8 new_div;
 	unsigned long val;
@@ -485,8 +544,8 @@ static ssize_t set_aout(struct device *d
 		struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -506,8 +565,8 @@ static ssize_t chassis_clear(struct devi
 		struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
+	struct adm9240_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) || val != 0)
@@ -524,7 +583,7 @@ static ssize_t chassis_clear(struct devi
 static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm,
 		chassis_clear, 12);
 
-static struct attribute *adm9240_attributes[] = {
+static struct attribute *adm9240_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -568,9 +627,7 @@ static struct attribute *adm9240_attribu
 	NULL
 };
 
-static const struct attribute_group adm9240_group = {
-	.attrs = adm9240_attributes,
-};
+ATTRIBUTE_GROUPS(adm9240);
 
 
 /*** sensor chip detect and driver install ***/
@@ -620,49 +677,6 @@ static int adm9240_detect(struct i2c_cli
 	return 0;
 }
 
-static int adm9240_probe(struct i2c_client *new_client,
-			 const struct i2c_device_id *id)
-{
-	struct adm9240_data *data;
-	int err;
-
-	data = devm_kzalloc(&new_client->dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(new_client, data);
-	mutex_init(&data->update_lock);
-
-	adm9240_init_client(new_client);
-
-	/* populate sysfs filesystem */
-	err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
-	return err;
-}
-
-static int adm9240_remove(struct i2c_client *client)
-{
-	struct adm9240_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adm9240_group);
-
-	return 0;
-}
-
 static void adm9240_init_client(struct i2c_client *client)
 {
 	struct adm9240_data *data = i2c_get_clientdata(client);
@@ -705,93 +719,48 @@ static void adm9240_init_client(struct i
 	}
 }
 
-static struct adm9240_data *adm9240_update_device(struct device *dev)
+static int adm9240_probe(struct i2c_client *new_client,
+			 const struct i2c_device_id *id)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm9240_data *data = i2c_get_clientdata(client);
-	int i;
-
-	mutex_lock(&data->update_lock);
-
-	/* minimum measurement cycle: 1.75 seconds */
-	if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
-			|| !data->valid) {
-
-		for (i = 0; i < 6; i++) { /* read voltages */
-			data->in[i] = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_IN(i));
-		}
-		data->alarms = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_INT(0)) |
-					i2c_smbus_read_byte_data(client,
-					ADM9240_REG_INT(1)) << 8;
-
-		/*
-		 * read temperature: assume temperature changes less than
-		 * 0.5'C per two measurement cycles thus ignore possible
-		 * but unlikely aliasing error on lsb reading. --Grant
-		 */
-		data->temp = ((i2c_smbus_read_byte_data(client,
-					ADM9240_REG_TEMP) << 8) |
-					i2c_smbus_read_byte_data(client,
-					ADM9240_REG_TEMP_CONF)) / 128;
-
-		for (i = 0; i < 2; i++) { /* read fans */
-			data->fan[i] = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_FAN(i));
-
-			/* adjust fan clock divider on overflow */
-			if (data->valid && data->fan[i] == 255 &&
-					data->fan_div[i] < 3) {
+	struct device *dev = &new_client->dev;
+	struct device *hwmon_dev;
+	struct adm9240_data *data;
 
-				adm9240_write_fan_div(client, i,
-						++data->fan_div[i]);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-				/* adjust fan_min if active, but not to 0 */
-				if (data->fan_min[i] < 255 &&
-						data->fan_min[i] >= 2)
-					data->fan_min[i] /= 2;
-			}
-		}
-		data->last_updated_measure = jiffies;
-	}
+	i2c_set_clientdata(new_client, data);
+	data->client = new_client;
+	mutex_init(&data->update_lock);
 
-	/* minimum config reading cycle: 300 seconds */
-	if (time_after(jiffies, data->last_updated_config + (HZ * 300))
-			|| !data->valid) {
+	adm9240_init_client(new_client);
 
-		for (i = 0; i < 6; i++) {
-			data->in_min[i] = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_IN_MIN(i));
-			data->in_max[i] = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_IN_MAX(i));
-		}
-		for (i = 0; i < 2; i++) {
-			data->fan_min[i] = i2c_smbus_read_byte_data(client,
-					ADM9240_REG_FAN_MIN(i));
-		}
-		data->temp_max[0] = i2c_smbus_read_byte_data(client,
-				ADM9240_REG_TEMP_MAX(0));
-		data->temp_max[1] = i2c_smbus_read_byte_data(client,
-				ADM9240_REG_TEMP_MAX(1));
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+							   new_client->name,
+							   data,
+							   adm9240_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-		/* read fan divs and 5-bit VID */
-		i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
-		data->fan_div[0] = (i >> 4) & 3;
-		data->fan_div[1] = (i >> 6) & 3;
-		data->vid = i & 0x0f;
-		data->vid |= (i2c_smbus_read_byte_data(client,
-					ADM9240_REG_VID4) & 1) << 4;
-		/* read analog out */
-		data->aout = i2c_smbus_read_byte_data(client,
-				ADM9240_REG_ANALOG_OUT);
+static const struct i2c_device_id adm9240_id[] = {
+	{ "adm9240", adm9240 },
+	{ "ds1780", ds1780 },
+	{ "lm81", lm81 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adm9240_id);
 
-		data->last_updated_config = jiffies;
-		data->valid = 1;
-	}
-	mutex_unlock(&data->update_lock);
-	return data;
-}
+static struct i2c_driver adm9240_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adm9240",
+	},
+	.probe		= adm9240_probe,
+	.id_table	= adm9240_id,
+	.detect		= adm9240_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adm9240_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ads1015.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ads1015.c
--- linux-libre-3.16-gnu/drivers/hwmon/ads1015.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ads1015.c	2014-09-28 17:29:07.000000000 -0400
@@ -198,7 +198,7 @@ static int ads1015_get_channels_config_o
 		}
 
 		channel = be32_to_cpup(property);
-		if (channel > ADS1015_CHANNELS) {
+		if (channel >= ADS1015_CHANNELS) {
 			dev_err(&client->dev,
 				"invalid channel index %d on %s\n",
 				channel, node->full_name);
@@ -212,6 +212,7 @@ static int ads1015_get_channels_config_o
 				dev_err(&client->dev,
 					"invalid gain on %s\n",
 					node->full_name);
+				return -EINVAL;
 			}
 		}
 
@@ -222,6 +223,7 @@ static int ads1015_get_channels_config_o
 				dev_err(&client->dev,
 					"invalid data_rate on %s\n",
 					node->full_name);
+				return -EINVAL;
 			}
 		}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ads7828.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ads7828.c
--- linux-libre-3.16-gnu/drivers/hwmon/ads7828.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ads7828.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,7 +50,7 @@ enum ads7828_chips { ads7828, ads7830 };
 
 /* Client specific data */
 struct ads7828_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;	/* Mutex protecting updates */
 	unsigned long last_updated;	/* Last updated time (in jiffies) */
 	u16 adc_input[ADS7828_NCH];	/* ADS7828_NCH samples */
@@ -72,8 +72,8 @@ static inline u8 ads7828_cmd_byte(u8 cmd
 /* Update data for the device (all 8 channels) */
 static struct ads7828_data *ads7828_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ads7828_data *data = i2c_get_clientdata(client);
+	struct ads7828_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -116,7 +116,7 @@ static SENSOR_DEVICE_ATTR(in5_input, S_I
 static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6);
 static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7);
 
-static struct attribute *ads7828_attributes[] = {
+static struct attribute *ads7828_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -128,29 +128,17 @@ static struct attribute *ads7828_attribu
 	NULL
 };
 
-static const struct attribute_group ads7828_group = {
-	.attrs = ads7828_attributes,
-};
-
-static int ads7828_remove(struct i2c_client *client)
-{
-	struct ads7828_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-
-	return 0;
-}
+ATTRIBUTE_GROUPS(ads7828);
 
 static int ads7828_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	struct ads7828_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct device *dev = &client->dev;
+	struct ads7828_platform_data *pdata = dev_get_platdata(dev);
 	struct ads7828_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct ads7828_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -182,24 +170,13 @@ static int ads7828_probe(struct i2c_clie
 	if (!data->diff_input)
 		data->cmd_byte |= ADS7828_CMD_SD_SE;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
-	err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
-	}
-
-	return 0;
-
-error:
-	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   ads7828_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ads7828_device_ids[] = {
@@ -216,7 +193,6 @@ static struct i2c_driver ads7828_driver
 
 	.id_table = ads7828_device_ids,
 	.probe = ads7828_probe,
-	.remove = ads7828_remove,
 };
 
 module_i2c_driver(ads7828_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adt7411.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7411.c
--- linux-libre-3.16-gnu/drivers/hwmon/adt7411.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7411.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ struct adt7411_data {
 	struct mutex update_lock;
 	unsigned long next_update;
 	int vref_cached;
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 };
 
 /*
@@ -111,7 +111,8 @@ static int adt7411_modify_bit(struct i2c
 static ssize_t adt7411_show_vdd(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	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);
 
@@ -121,7 +122,8 @@ static ssize_t adt7411_show_vdd(struct d
 static ssize_t adt7411_show_temp(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
 			ADT7411_REG_INT_TEMP_MSB, 0);
 
@@ -137,8 +139,8 @@ static ssize_t adt7411_show_input(struct
 				  struct device_attribute *attr, char *buf)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7411_data *data = i2c_get_clientdata(client);
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int val;
 	u8 lsb_reg, lsb_shift;
 
@@ -180,7 +182,8 @@ static ssize_t adt7411_show_bit(struct d
 				struct device_attribute *attr, char *buf)
 {
 	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int ret = i2c_smbus_read_byte_data(client, attr2->index);
 
 	return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr));
@@ -191,8 +194,8 @@ static ssize_t adt7411_set_bit(struct de
 			       size_t count)
 {
 	struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7411_data *data = i2c_get_clientdata(client);
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int ret;
 	unsigned long flag;
 
@@ -245,9 +248,7 @@ static struct attribute *adt7411_attrs[]
 	NULL
 };
 
-static const struct attribute_group adt7411_attr_grp = {
-	.attrs = adt7411_attrs,
-};
+ATTRIBUTE_GROUPS(adt7411);
 
 static int adt7411_detect(struct i2c_client *client,
 			  struct i2c_board_info *info)
@@ -281,14 +282,17 @@ static int adt7411_detect(struct i2c_cli
 static int adt7411_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct adt7411_data *data;
+	struct device *hwmon_dev;
 	int ret;
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->device_lock);
 	mutex_init(&data->update_lock);
 
@@ -300,32 +304,10 @@ static int adt7411_probe(struct i2c_clie
 	/* force update on first occasion */
 	data->next_update = jiffies;
 
-	ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp);
-	if (ret)
-		return ret;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	dev_info(&client->dev, "successfully registered\n");
-
-	return 0;
-
- exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
-	return ret;
-}
-
-static int adt7411_remove(struct i2c_client *client)
-{
-	struct adt7411_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   adt7411_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id adt7411_id[] = {
@@ -339,7 +321,6 @@ static struct i2c_driver adt7411_driver
 		.name		= "adt7411",
 	},
 	.probe  = adt7411_probe,
-	.remove	= adt7411_remove,
 	.id_table = adt7411_id,
 	.detect = adt7411_detect,
 	.address_list = normal_i2c,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adt7462.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7462.c
--- linux-libre-3.16-gnu/drivers/hwmon/adt7462.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7462.c	2014-09-28 17:29:07.000000000 -0400
@@ -202,8 +202,7 @@ static const unsigned short normal_i2c[]
 	(((value) & prefix##_MASK) >> prefix##_SHIFT)
 
 struct adt7462_data {
-	struct device		*hwmon_dev;
-	struct attribute_group	attrs;
+	struct i2c_client	*client;
 	struct mutex		lock;
 	char			sensors_valid;
 	char			limits_valid;
@@ -232,30 +231,6 @@ struct adt7462_data {
 	u8			alarms[ADT7462_ALARM_REG_COUNT];
 };
 
-static int adt7462_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adt7462_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int adt7462_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7462_id[] = {
-	{ "adt7462", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adt7462_id);
-
-static struct i2c_driver adt7462_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adt7462",
-	},
-	.probe		= adt7462_probe,
-	.remove		= adt7462_remove,
-	.id_table	= adt7462_id,
-	.detect		= adt7462_detect,
-	.address_list	= normal_i2c,
-};
-
 /*
  * 16-bit registers on the ADT7462 are low-byte first.  The data sheet says
  * that the low byte must be read before the high byte.
@@ -705,8 +680,8 @@ static int find_trange_value(int trange)
 
 static struct adt7462_data *adt7462_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long local_jiffies = jiffies;
 	int i;
 
@@ -828,8 +803,8 @@ static ssize_t set_temp_min(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
@@ -866,8 +841,8 @@ static ssize_t set_temp_max(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
@@ -929,8 +904,8 @@ static ssize_t set_volt_max(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int x = voltage_multiplier(data, attr->index);
 	long temp;
 
@@ -971,8 +946,8 @@ static ssize_t set_volt_min(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int x = voltage_multiplier(data, attr->index);
 	long temp;
 
@@ -1061,8 +1036,8 @@ static ssize_t set_fan_min(struct device
 			   const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp) || !temp ||
@@ -1109,8 +1084,8 @@ static ssize_t set_force_pwm_max(struct
 				 const char *buf,
 				 size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	u8 reg;
 
@@ -1142,8 +1117,8 @@ static ssize_t set_pwm(struct device *de
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1172,8 +1147,8 @@ static ssize_t set_pwm_max(struct device
 			   const char *buf,
 			   size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1204,8 +1179,8 @@ static ssize_t set_pwm_min(struct device
 			   size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1238,8 +1213,8 @@ static ssize_t set_pwm_hyst(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1283,8 +1258,8 @@ static ssize_t set_pwm_tmax(struct devic
 {
 	int temp;
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int tmin, trange_value;
 	long trange;
 
@@ -1324,8 +1299,8 @@ static ssize_t set_pwm_tmin(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1381,8 +1356,8 @@ static ssize_t set_pwm_auto(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1440,8 +1415,8 @@ static ssize_t set_pwm_auto_temp(struct
 				 size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7462_data *data = i2c_get_clientdata(client);
+	struct adt7462_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -1725,7 +1700,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_chan
 static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
 		    show_pwm_auto_temp, set_pwm_auto_temp, 3);
 
-static struct attribute *adt7462_attr[] = {
+static struct attribute *adt7462_attrs[] = {
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp2_max.dev_attr.attr,
 	&sensor_dev_attr_temp3_max.dev_attr.attr,
@@ -1896,6 +1871,8 @@ static struct attribute *adt7462_attr[]
 	NULL
 };
 
+ATTRIBUTE_GROUPS(adt7462);
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int adt7462_detect(struct i2c_client *client,
 			  struct i2c_board_info *info)
@@ -1926,46 +1903,41 @@ static int adt7462_detect(struct i2c_cli
 static int adt7462_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct adt7462_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct adt7462_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->lock);
 
 	dev_info(&client->dev, "%s chip found\n", client->name);
 
-	/* Register sysfs hooks */
-	data->attrs.attrs = adt7462_attr;
-	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   adt7462_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int adt7462_remove(struct i2c_client *client)
-{
-	struct adt7462_data *data = i2c_get_clientdata(client);
+static const struct i2c_device_id adt7462_id[] = {
+	{ "adt7462", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adt7462_id);
 
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	return 0;
-}
+static struct i2c_driver adt7462_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adt7462",
+	},
+	.probe		= adt7462_probe,
+	.id_table	= adt7462_id,
+	.detect		= adt7462_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(adt7462_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/adt7470.c linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7470.c
--- linux-libre-3.16-gnu/drivers/hwmon/adt7470.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/adt7470.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,8 +143,7 @@ static const unsigned short normal_i2c[]
 #define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)
 
 struct adt7470_data {
-	struct device		*hwmon_dev;
-	struct attribute_group	attrs;
+	struct i2c_client	*client;
 	struct mutex		lock;
 	char			sensors_valid;
 	char			limits_valid;
@@ -175,30 +174,6 @@ struct adt7470_data {
 	unsigned int		auto_update_interval;
 };
 
-static int adt7470_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adt7470_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int adt7470_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7470_id[] = {
-	{ "adt7470", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adt7470_id);
-
-static struct i2c_driver adt7470_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adt7470",
-	},
-	.probe		= adt7470_probe,
-	.remove		= adt7470_remove,
-	.id_table	= adt7470_id,
-	.detect		= adt7470_detect,
-	.address_list	= normal_i2c,
-};
-
 /*
  * 16-bit registers on the ADT7470 are low-byte first.  The data sheet says
  * that the low byte must be read before the high byte.
@@ -218,18 +193,6 @@ static inline int adt7470_write_word_dat
 	       || i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
 }
 
-static void adt7470_init_client(struct i2c_client *client)
-{
-	int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
-
-	if (reg < 0) {
-		dev_err(&client->dev, "cannot read configuration register\n");
-	} else {
-		/* start monitoring (and do a self-test) */
-		i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);
-	}
-}
-
 /* Probe for temperature sensors.  Assumes lock is held */
 static int adt7470_read_temperatures(struct i2c_client *client,
 				     struct adt7470_data *data)
@@ -314,8 +277,8 @@ static int adt7470_update_thread(void *p
 
 static struct adt7470_data *adt7470_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long local_jiffies = jiffies;
 	u8 cfg;
 	int i;
@@ -445,8 +408,7 @@ static ssize_t set_auto_update_interval(
 					const char *buf,
 					size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -474,8 +436,7 @@ static ssize_t set_num_temp_sensors(stru
 				    const char *buf,
 				    size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -507,8 +468,8 @@ static ssize_t set_temp_min(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -541,8 +502,8 @@ static ssize_t set_temp_max(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -596,8 +557,8 @@ static ssize_t set_fan_max(struct device
 			   const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp) || !temp)
@@ -633,8 +594,8 @@ static ssize_t set_fan_min(struct device
 			   const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp) || !temp)
@@ -677,8 +638,8 @@ static ssize_t set_force_pwm_max(struct
 				 const char *buf,
 				 size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 	u8 reg;
 
@@ -710,8 +671,8 @@ static ssize_t set_pwm(struct device *de
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -742,8 +703,8 @@ static ssize_t set_pwm_max(struct device
 			   size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -775,8 +736,8 @@ static ssize_t set_pwm_min(struct device
 			   size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -818,8 +779,8 @@ static ssize_t set_pwm_tmin(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long temp;
 
 	if (kstrtol(buf, 10, &temp))
@@ -852,8 +813,8 @@ static ssize_t set_pwm_auto(struct devic
 			    size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index);
 	int pwm_auto_reg_mask;
 	long temp;
@@ -913,8 +874,8 @@ static ssize_t set_pwm_auto_temp(struct
 				 size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7470_data *data = i2c_get_clientdata(client);
+	struct adt7470_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index);
 	long temp;
 	u8 reg;
@@ -1131,7 +1092,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_chan
 static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
 		    show_pwm_auto_temp, set_pwm_auto_temp, 3);
 
-static struct attribute *adt7470_attr[] = {
+static struct attribute *adt7470_attrs[] = {
 	&dev_attr_alarm_mask.attr,
 	&dev_attr_num_temp_sensors.attr,
 	&dev_attr_auto_update_interval.attr,
@@ -1223,6 +1184,8 @@ static struct attribute *adt7470_attr[]
 	NULL
 };
 
+ATTRIBUTE_GROUPS(adt7470);
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int adt7470_detect(struct i2c_client *client,
 			  struct i2c_board_info *info)
@@ -1250,14 +1213,26 @@ static int adt7470_detect(struct i2c_cli
 	return 0;
 }
 
+static void adt7470_init_client(struct i2c_client *client)
+{
+	int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
+
+	if (reg < 0) {
+		dev_err(&client->dev, "cannot read configuration register\n");
+	} else {
+		/* start monitoring (and do a self-test) */
+		i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);
+	}
+}
+
 static int adt7470_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct adt7470_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct adt7470_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -1265,6 +1240,7 @@ static int adt7470_probe(struct i2c_clie
 	data->auto_update_interval = AUTO_UPDATE_INTERVAL;
 
 	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->lock);
 
 	dev_info(&client->dev, "%s chip found\n", client->name);
@@ -1273,32 +1249,21 @@ static int adt7470_probe(struct i2c_clie
 	adt7470_init_client(client);
 
 	/* Register sysfs hooks */
-	data->attrs.attrs = adt7470_attr;
-	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
-	if (err)
-		return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   adt7470_groups);
 
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
 	init_completion(&data->auto_update_stop);
 	data->auto_update = kthread_run(adt7470_update_thread, client, "%s",
-					dev_name(data->hwmon_dev));
+					dev_name(hwmon_dev));
 	if (IS_ERR(data->auto_update)) {
-		err = PTR_ERR(data->auto_update);
-		goto exit_unregister;
+		return PTR_ERR(data->auto_update);
 	}
 
 	return 0;
-
-exit_unregister:
-	hwmon_device_unregister(data->hwmon_dev);
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	return err;
 }
 
 static int adt7470_remove(struct i2c_client *client)
@@ -1307,11 +1272,27 @@ static int adt7470_remove(struct i2c_cli
 
 	kthread_stop(data->auto_update);
 	wait_for_completion(&data->auto_update_stop);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
 	return 0;
 }
 
+static const struct i2c_device_id adt7470_id[] = {
+	{ "adt7470", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adt7470_id);
+
+static struct i2c_driver adt7470_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adt7470",
+	},
+	.probe		= adt7470_probe,
+	.remove		= adt7470_remove,
+	.id_table	= adt7470_id,
+	.detect		= adt7470_detect,
+	.address_list	= normal_i2c,
+};
+
 module_i2c_driver(adt7470_driver);
 
 MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/amc6821.c linux-libre-3.17-rc7-gnu/drivers/hwmon/amc6821.c
--- linux-libre-3.16-gnu/drivers/hwmon/amc6821.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/amc6821.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-
 #include <linux/kernel.h>	/* Needed for KERN_INFO */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -33,7 +32,6 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 
-
 /*
  * Addresses to scan.
  */
@@ -41,8 +39,6 @@
 static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
 	0x4c, 0x4d, 0x4e, I2C_CLIENT_END};
 
-
-
 /*
  * Insmod parameters
  */
@@ -53,7 +49,6 @@ module_param(pwminv, int, S_IRUGO);
 static int init = 1; /*Power-on initialization.*/
 module_param(init, int, S_IRUGO);
 
-
 enum chips { amc6821 };
 
 #define AMC6821_REG_DEV_ID 0x3D
@@ -152,46 +147,12 @@ static const u8 fan_reg_hi[] = {AMC6821_
 			AMC6821_REG_TACH_LLIMITH,
 			AMC6821_REG_TACH_HLIMITH, };
 
-static int amc6821_probe(
-		struct i2c_client *client,
-		const struct i2c_device_id *id);
-static int amc6821_detect(
-		struct i2c_client *client,
-		struct i2c_board_info *info);
-static int amc6821_init_client(struct i2c_client *client);
-static int amc6821_remove(struct i2c_client *client);
-static struct amc6821_data *amc6821_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id amc6821_id[] = {
-	{ "amc6821", amc6821 },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(i2c, amc6821_id);
-
-static struct i2c_driver amc6821_driver = {
-	.class = I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "amc6821",
-	},
-	.probe = amc6821_probe,
-	.remove = amc6821_remove,
-	.id_table = amc6821_id,
-	.detect = amc6821_detect,
-	.address_list = normal_i2c,
-};
-
-
 /*
  * Client data (each client gets its own)
  */
 
 struct amc6821_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -213,6 +174,108 @@ struct amc6821_data {
 	u8 stat2;
 };
 
+static struct amc6821_data *amc6821_update_device(struct device *dev)
+{
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int timeout = HZ;
+	u8 reg;
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + timeout) ||
+			!data->valid) {
+
+		for (i = 0; i < TEMP_IDX_LEN; i++)
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+				temp_reg[i]);
+
+		data->stat1 = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_STAT1);
+		data->stat2 = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_STAT2);
+
+		data->pwm1 = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_DCY);
+		for (i = 0; i < FAN1_IDX_LEN; i++) {
+			data->fan[i] = i2c_smbus_read_byte_data(
+					client,
+					fan_reg_low[i]);
+			data->fan[i] += i2c_smbus_read_byte_data(
+					client,
+					fan_reg_hi[i]) << 8;
+		}
+		data->fan1_div = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_CONF4);
+		data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+
+		data->pwm1_auto_point_pwm[0] = 0;
+		data->pwm1_auto_point_pwm[2] = 255;
+		data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_DCY_LOW_TEMP);
+
+		data->temp1_auto_point_temp[0] =
+			i2c_smbus_read_byte_data(client,
+					AMC6821_REG_PSV_TEMP);
+		data->temp2_auto_point_temp[0] =
+				data->temp1_auto_point_temp[0];
+		reg = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_LTEMP_FAN_CTRL);
+		data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
+		reg &= 0x07;
+		reg = 0x20 >> reg;
+		if (reg > 0)
+			data->temp1_auto_point_temp[2] =
+				data->temp1_auto_point_temp[1] +
+				(data->pwm1_auto_point_pwm[2] -
+				data->pwm1_auto_point_pwm[1]) / reg;
+		else
+			data->temp1_auto_point_temp[2] = 255;
+
+		reg = i2c_smbus_read_byte_data(client,
+			AMC6821_REG_RTEMP_FAN_CTRL);
+		data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
+		reg &= 0x07;
+		reg = 0x20 >> reg;
+		if (reg > 0)
+			data->temp2_auto_point_temp[2] =
+				data->temp2_auto_point_temp[1] +
+				(data->pwm1_auto_point_pwm[2] -
+				data->pwm1_auto_point_pwm[1]) / reg;
+		else
+			data->temp2_auto_point_temp[2] = 255;
+
+		reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+		reg = (reg >> 5) & 0x3;
+		switch (reg) {
+		case 0: /*open loop: software sets pwm1*/
+			data->pwm1_auto_channels_temp = 0;
+			data->pwm1_enable = 1;
+			break;
+		case 2: /*closed loop: remote T (temp2)*/
+			data->pwm1_auto_channels_temp = 2;
+			data->pwm1_enable = 2;
+			break;
+		case 3: /*closed loop: local and remote T (temp2)*/
+			data->pwm1_auto_channels_temp = 3;
+			data->pwm1_enable = 3;
+			break;
+		case 1: /*
+			 * semi-open loop: software sets rpm, chip controls
+			 * pwm1, currently not implemented
+			 */
+			data->pwm1_auto_channels_temp = 0;
+			data->pwm1_enable = 0;
+			break;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+	mutex_unlock(&data->update_lock);
+	return data;
+}
 
 static ssize_t get_temp(
 		struct device *dev,
@@ -225,16 +288,14 @@ static ssize_t get_temp(
 	return sprintf(buf, "%d\n", data->temp[ix] * 1000);
 }
 
-
-
 static ssize_t set_temp(
 		struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int ix = to_sensor_dev_attr(attr)->index;
 	long val;
 
@@ -253,9 +314,6 @@ static ssize_t set_temp(
 	return count;
 }
 
-
-
-
 static ssize_t get_temp_alarm(
 	struct device *dev,
 	struct device_attribute *devattr,
@@ -294,9 +352,6 @@ static ssize_t get_temp_alarm(
 		return sprintf(buf, "0");
 }
 
-
-
-
 static ssize_t get_temp2_fault(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -324,8 +379,8 @@ static ssize_t set_pwm1(
 		const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int ret = kstrtol(buf, 10, &val);
 	if (ret)
@@ -353,18 +408,20 @@ static ssize_t set_pwm1_enable(
 		const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int config = kstrtol(buf, 10, &val);
 	if (config)
 		return config;
 
+	mutex_lock(&data->update_lock);
 	config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
 	if (config < 0) {
 			dev_err(&client->dev,
 			"Error reading configuration register, aborting.\n");
-			return config;
+			count = config;
+			goto unlock;
 	}
 
 	switch (val) {
@@ -381,19 +438,19 @@ static ssize_t set_pwm1_enable(
 		config |= AMC6821_CONF1_FDRC1;
 		break;
 	default:
-		return -EINVAL;
+		count = -EINVAL;
+		goto unlock;
 	}
-	mutex_lock(&data->update_lock);
 	if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
 			dev_err(&client->dev,
 			"Configuration register write error, aborting.\n");
 			count = -EIO;
 	}
+unlock:
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-
 static ssize_t get_pwm1_auto_channels_temp(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -403,7 +460,6 @@ static ssize_t get_pwm1_auto_channels_te
 	return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
 }
 
-
 static ssize_t get_temp_auto_point_temp(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -425,7 +481,6 @@ static ssize_t get_temp_auto_point_temp(
 	}
 }
 
-
 static ssize_t get_pwm1_auto_point_pwm(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -436,7 +491,6 @@ static ssize_t get_pwm1_auto_point_pwm(
 	return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
 }
 
-
 static inline ssize_t set_slope_register(struct i2c_client *client,
 		u8 reg,
 		u8 dpwm,
@@ -459,16 +513,14 @@ static inline ssize_t set_slope_register
 	return 0;
 }
 
-
-
 static ssize_t set_temp_auto_point_temp(
 		struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct amc6821_data *data = amc6821_update_device(dev);
+	struct i2c_client *client = data->client;
 	int ix = to_sensor_dev_attr_2(attr)->index;
 	int nr = to_sensor_dev_attr_2(attr)->nr;
 	u8 *ptemp;
@@ -493,8 +545,9 @@ static ssize_t set_temp_auto_point_temp(
 		return -EINVAL;
 	}
 
-	data->valid = 0;
 	mutex_lock(&data->update_lock);
+	data->valid = 0;
+
 	switch (ix) {
 	case 0:
 		ptemp[0] = clamp_val(val / 1000, 0,
@@ -533,16 +586,14 @@ EXIT:
 	return count;
 }
 
-
-
 static ssize_t set_pwm1_auto_point_pwm(
 		struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int dpwm;
 	long val;
 	int ret = kstrtol(buf, 10, &val);
@@ -587,8 +638,6 @@ static ssize_t get_fan(
 	return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
 }
 
-
-
 static ssize_t get_fan1_fault(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -601,15 +650,13 @@ static ssize_t get_fan1_fault(
 		return sprintf(buf, "0");
 }
 
-
-
 static ssize_t set_fan(
 		struct device *dev,
 		struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int ix = to_sensor_dev_attr(attr)->index;
 	int ret = kstrtol(buf, 10, &val);
@@ -635,8 +682,6 @@ EXIT:
 	return count;
 }
 
-
-
 static ssize_t get_fan1_div(
 		struct device *dev,
 		struct device_attribute *devattr,
@@ -651,20 +696,21 @@ static ssize_t set_fan1_div(
 		struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
+	struct amc6821_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int config = kstrtol(buf, 10, &val);
 	if (config)
 		return config;
 
+	mutex_lock(&data->update_lock);
 	config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
 	if (config < 0) {
 		dev_err(&client->dev,
 			"Error reading configuration register, aborting.\n");
-		return config;
+		count = config;
+		goto EXIT;
 	}
-	mutex_lock(&data->update_lock);
 	switch (val) {
 	case 2:
 		config &= ~AMC6821_CONF4_PSPR;
@@ -688,8 +734,6 @@ EXIT:
 	return count;
 }
 
-
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
 	get_temp, NULL, IDX_TEMP1_INPUT);
 static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp,
@@ -754,8 +798,6 @@ static SENSOR_DEVICE_ATTR_2(temp2_auto_p
 static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO,
 	get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2);
 
-
-
 static struct attribute *amc6821_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -792,11 +834,7 @@ static struct attribute *amc6821_attrs[]
 	NULL
 };
 
-static struct attribute_group amc6821_attr_grp = {
-	.attrs = amc6821_attrs,
-};
-
-
+ATTRIBUTE_GROUPS(amc6821);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int amc6821_detect(
@@ -844,53 +882,6 @@ static int amc6821_detect(
 	return 0;
 }
 
-static int amc6821_probe(
-	struct i2c_client *client,
-	const struct i2c_device_id *id)
-{
-	struct amc6821_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	/*
-	 * Initialize the amc6821 chip
-	 */
-	err = amc6821_init_client(client);
-	if (err)
-		return err;
-
-	err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (!IS_ERR(data->hwmon_dev))
-		return 0;
-
-	err = PTR_ERR(data->hwmon_dev);
-	dev_err(&client->dev, "error registering hwmon device.\n");
-	sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-	return err;
-}
-
-static int amc6821_remove(struct i2c_client *client)
-{
-	struct amc6821_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-
-	return 0;
-}
-
-
 static int amc6821_init_client(struct i2c_client *client)
 {
 	int config;
@@ -977,109 +968,51 @@ static int amc6821_init_client(struct i2
 	return 0;
 }
 
-
-static struct amc6821_data *amc6821_update_device(struct device *dev)
+static int amc6821_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct amc6821_data *data = i2c_get_clientdata(client);
-	int timeout = HZ;
-	u8 reg;
-	int i;
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + timeout) ||
-			!data->valid) {
-
-		for (i = 0; i < TEMP_IDX_LEN; i++)
-			data->temp[i] = i2c_smbus_read_byte_data(client,
-				temp_reg[i]);
+	struct device *dev = &client->dev;
+	struct amc6821_data *data;
+	struct device *hwmon_dev;
+	int err;
 
-		data->stat1 = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_STAT1);
-		data->stat2 = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_STAT2);
+	data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-		data->pwm1 = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_DCY);
-		for (i = 0; i < FAN1_IDX_LEN; i++) {
-			data->fan[i] = i2c_smbus_read_byte_data(
-					client,
-					fan_reg_low[i]);
-			data->fan[i] += i2c_smbus_read_byte_data(
-					client,
-					fan_reg_hi[i]) << 8;
-		}
-		data->fan1_div = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_CONF4);
-		data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+	data->client = client;
+	mutex_init(&data->update_lock);
 
-		data->pwm1_auto_point_pwm[0] = 0;
-		data->pwm1_auto_point_pwm[2] = 255;
-		data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_DCY_LOW_TEMP);
+	/*
+	 * Initialize the amc6821 chip
+	 */
+	err = amc6821_init_client(client);
+	if (err)
+		return err;
 
-		data->temp1_auto_point_temp[0] =
-			i2c_smbus_read_byte_data(client,
-					AMC6821_REG_PSV_TEMP);
-		data->temp2_auto_point_temp[0] =
-				data->temp1_auto_point_temp[0];
-		reg = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_LTEMP_FAN_CTRL);
-		data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
-		reg &= 0x07;
-		reg = 0x20 >> reg;
-		if (reg > 0)
-			data->temp1_auto_point_temp[2] =
-				data->temp1_auto_point_temp[1] +
-				(data->pwm1_auto_point_pwm[2] -
-				data->pwm1_auto_point_pwm[1]) / reg;
-		else
-			data->temp1_auto_point_temp[2] = 255;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   amc6821_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-		reg = i2c_smbus_read_byte_data(client,
-			AMC6821_REG_RTEMP_FAN_CTRL);
-		data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
-		reg &= 0x07;
-		reg = 0x20 >> reg;
-		if (reg > 0)
-			data->temp2_auto_point_temp[2] =
-				data->temp2_auto_point_temp[1] +
-				(data->pwm1_auto_point_pwm[2] -
-				data->pwm1_auto_point_pwm[1]) / reg;
-		else
-			data->temp2_auto_point_temp[2] = 255;
+static const struct i2c_device_id amc6821_id[] = {
+	{ "amc6821", amc6821 },
+	{ }
+};
 
-		reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
-		reg = (reg >> 5) & 0x3;
-		switch (reg) {
-		case 0: /*open loop: software sets pwm1*/
-			data->pwm1_auto_channels_temp = 0;
-			data->pwm1_enable = 1;
-			break;
-		case 2: /*closed loop: remote T (temp2)*/
-			data->pwm1_auto_channels_temp = 2;
-			data->pwm1_enable = 2;
-			break;
-		case 3: /*closed loop: local and remote T (temp2)*/
-			data->pwm1_auto_channels_temp = 3;
-			data->pwm1_enable = 3;
-			break;
-		case 1: /*
-			 * semi-open loop: software sets rpm, chip controls
-			 * pwm1, currently not implemented
-			 */
-			data->pwm1_auto_channels_temp = 0;
-			data->pwm1_enable = 0;
-			break;
-		}
+MODULE_DEVICE_TABLE(i2c, amc6821_id);
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
-	mutex_unlock(&data->update_lock);
-	return data;
-}
+static struct i2c_driver amc6821_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "amc6821",
+	},
+	.probe = amc6821_probe,
+	.id_table = amc6821_id,
+	.detect = amc6821_detect,
+	.address_list = normal_i2c,
+};
 
 module_i2c_driver(amc6821_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/asb100.c linux-libre-3.17-rc7-gnu/drivers/hwmon/asb100.c
--- linux-libre-3.16-gnu/drivers/hwmon/asb100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/asb100.c	2014-09-28 17:29:07.000000000 -0400
@@ -510,6 +510,10 @@ static ssize_t set_vrm(struct device *de
 	err = kstrtoul(buf, 10, &val);
 	if (err)
 		return err;
+
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/asc7621.c linux-libre-3.17-rc7-gnu/drivers/hwmon/asc7621.c
--- linux-libre-3.16-gnu/drivers/hwmon/asc7621.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/asc7621.c	2014-09-28 17:29:07.000000000 -0400
@@ -300,7 +300,7 @@ static ssize_t store_fan16(struct device
  * respectively. That doesn't mean that's what the motherboard provides. :)
  */
 
-static int asc7621_in_scaling[] = {
+static const int asc7621_in_scaling[] = {
 	2500, 2250, 3300, 5000, 12000
 };
 
@@ -451,7 +451,7 @@ static ssize_t store_temp62(struct devic
  * hwmon specs, we synthesize the auto_point_2 from them.
  */
 
-static u32 asc7621_range_map[] = {
+static const u32 asc7621_range_map[] = {
 	2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000,
 	13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000,
 };
@@ -512,7 +512,7 @@ static ssize_t show_pwm_ac(struct device
 {
 	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 config, altbit, regval;
-	u8 map[] = {
+	const u8 map[] = {
 		0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
 		0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f
 	};
@@ -533,7 +533,7 @@ static ssize_t store_pwm_ac(struct devic
 	SETUP_STORE_DATA_PARAM(dev, attr);
 	unsigned long reqval;
 	u8 currval, config, altbit, newval;
-	u16 map[] = {
+	const u16 map[] = {
 		0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06,
 		0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
 		0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -651,7 +651,7 @@ static ssize_t store_pwm_enable(struct d
 	return count;
 }
 
-static u32 asc7621_pwm_freq_map[] = {
+static const u32 asc7621_pwm_freq_map[] = {
 	10, 15, 23, 30, 38, 47, 62, 94,
 	23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000
 };
@@ -700,7 +700,7 @@ static ssize_t store_pwm_freq(struct dev
 	return count;
 }
 
-static u32 asc7621_pwm_auto_spinup_map[] =  {
+static const u32 asc7621_pwm_auto_spinup_map[] =  {
 	0, 100, 250, 400, 700, 1000, 2000, 4000
 };
 
@@ -749,7 +749,7 @@ static ssize_t store_pwm_ast(struct devi
 	return count;
 }
 
-static u32 asc7621_temp_smoothing_time_map[] = {
+static const u32 asc7621_temp_smoothing_time_map[] = {
 	35000, 17600, 11800, 7000, 4400, 3000, 1600, 800
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/asus_atk0110.c linux-libre-3.17-rc7-gnu/drivers/hwmon/asus_atk0110.c
--- linux-libre-3.16-gnu/drivers/hwmon/asus_atk0110.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/asus_atk0110.c	2014-09-28 17:29:07.000000000 -0400
@@ -688,7 +688,7 @@ static int atk_debugfs_gitm_get(void *p,
 DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
 			atk_debugfs_gitm_get,
 			NULL,
-			"0x%08llx\n")
+			"0x%08llx\n");
 
 static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/atxp1.c linux-libre-3.17-rc7-gnu/drivers/hwmon/atxp1.c
--- linux-libre-3.16-gnu/drivers/hwmon/atxp1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/atxp1.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@g
 static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
 
 struct atxp1_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	unsigned long last_updated;
 	u8 valid;
@@ -61,11 +61,8 @@ struct atxp1_data {
 
 static struct atxp1_data *atxp1_update_device(struct device *dev)
 {
-	struct i2c_client *client;
-	struct atxp1_data *data;
-
-	client = to_i2c_client(dev);
-	data = i2c_get_clientdata(client);
+	struct atxp1_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -105,15 +102,12 @@ static ssize_t atxp1_storevcore(struct d
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct atxp1_data *data;
-	struct i2c_client *client;
+	struct atxp1_data *data = atxp1_update_device(dev);
+	struct i2c_client *client = data->client;
 	int vid, cvid;
 	unsigned long vcore;
 	int err;
 
-	client = to_i2c_client(dev);
-	data = atxp1_update_device(dev);
-
 	err = kstrtoul(buf, 10, &vcore);
 	if (err)
 		return err;
@@ -184,14 +178,11 @@ static ssize_t atxp1_storegpio1(struct d
 				struct device_attribute *attr, const char *buf,
 				size_t count)
 {
-	struct atxp1_data *data;
-	struct i2c_client *client;
+	struct atxp1_data *data = atxp1_update_device(dev);
+	struct i2c_client *client = data->client;
 	unsigned long value;
 	int err;
 
-	client = to_i2c_client(dev);
-	data = atxp1_update_device(dev);
-
 	err = kstrtoul(buf, 16, &value);
 	if (err)
 		return err;
@@ -234,7 +225,7 @@ static ssize_t atxp1_storegpio2(struct d
 				const char *buf, size_t count)
 {
 	struct atxp1_data *data = atxp1_update_device(dev);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = data->client;
 	unsigned long value;
 	int err;
 
@@ -260,17 +251,13 @@ static ssize_t atxp1_storegpio2(struct d
  */
 static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
 
-static struct attribute *atxp1_attributes[] = {
+static struct attribute *atxp1_attrs[] = {
 	&dev_attr_gpio1.attr,
 	&dev_attr_gpio2.attr,
 	&dev_attr_cpu0_vid.attr,
 	NULL
 };
-
-static const struct attribute_group atxp1_group = {
-	.attrs = atxp1_attributes,
-};
-
+ATTRIBUTE_GROUPS(atxp1);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int atxp1_detect(struct i2c_client *new_client,
@@ -314,50 +301,30 @@ static int atxp1_detect(struct i2c_clien
 	return 0;
 }
 
-static int atxp1_probe(struct i2c_client *new_client,
+static int atxp1_probe(struct i2c_client *client,
 		       const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct atxp1_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&new_client->dev, sizeof(struct atxp1_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct atxp1_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	/* Get VRM */
 	data->vrm = vid_which_vrm();
 
-	i2c_set_clientdata(new_client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	dev_info(&new_client->dev, "Using VRM: %d.%d\n",
-			 data->vrm / 10, data->vrm % 10);
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
-	return err;
-};
-
-static int atxp1_remove(struct i2c_client *client)
-{
-	struct atxp1_data *data = i2c_get_clientdata(client);
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   atxp1_groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &atxp1_group);
+	dev_info(dev, "Using VRM: %d.%d\n", data->vrm / 10, data->vrm % 10);
 
 	return 0;
 };
@@ -374,7 +341,6 @@ static struct i2c_driver atxp1_driver =
 		.name	= "atxp1",
 	},
 	.probe		= atxp1_probe,
-	.remove		= atxp1_remove,
 	.id_table	= atxp1_id,
 	.detect		= atxp1_detect,
 	.address_list	= normal_i2c,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/dme1737.c linux-libre-3.17-rc7-gnu/drivers/hwmon/dme1737.c
--- linux-libre-3.16-gnu/drivers/hwmon/dme1737.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/dme1737.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,8 +247,8 @@ struct dme1737_data {
 	u8  pwm_acz[3];
 	u8  pwm_freq[6];
 	u8  pwm_rr[2];
-	u8  zone_low[3];
-	u8  zone_abs[3];
+	s8  zone_low[3];
+	s8  zone_abs[3];
 	u8  zone_hyst[2];
 	u32 alarms;
 };
@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, i
 	return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2));
 }
 
-static inline int IN_TO_REG(int val, int nominal)
+static inline int IN_TO_REG(long val, int nominal)
 {
 	return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255);
 }
@@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg,
 	return (reg * 1000) >> (res - 8);
 }
 
-static inline int TEMP_TO_REG(int val)
+static inline int TEMP_TO_REG(long val)
 {
 	return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127);
 }
@@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(in
 	return TEMP_RANGE[(reg >> 4) & 0x0f];
 }
 
-static int TEMP_RANGE_TO_REG(int val, int reg)
+static int TEMP_RANGE_TO_REG(long val, int reg)
 {
 	int i;
 
@@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int
 	return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000;
 }
 
-static inline int TEMP_HYST_TO_REG(int val, int ix, int reg)
+static inline int TEMP_HYST_TO_REG(long val, int ix, int reg)
 {
 	int hyst = clamp_val((val + 500) / 1000, 0, 15);
 
@@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg,
 		return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg;
 }
 
-static inline int FAN_TO_REG(int val, int tpc)
+static inline int FAN_TO_REG(long val, int tpc)
 {
 	if (tpc) {
 		return clamp_val(val / tpc, 0, 0xffff);
@@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int
 	return (edge > 0) ? 1 << (edge - 1) : 0;
 }
 
-static inline int FAN_TYPE_TO_REG(int val, int reg)
+static inline int FAN_TYPE_TO_REG(long val, int reg)
 {
 	int edge = (val == 4) ? 3 : val;
 
@@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg)
 	return 1000 + i * 500;
 }
 
-static int FAN_MAX_TO_REG(int val)
+static int FAN_MAX_TO_REG(long val)
 {
 	int i;
 
@@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int r
 	return acz[(reg >> 5) & 0x07];
 }
 
-static inline int PWM_ACZ_TO_REG(int val, int reg)
+static inline int PWM_ACZ_TO_REG(long val, int reg)
 {
 	int acz = (val == 4) ? 2 : val - 1;
 
@@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int
 	return PWM_FREQ[reg & 0x0f];
 }
 
-static int PWM_FREQ_TO_REG(int val, int reg)
+static int PWM_FREQ_TO_REG(long val, int reg)
 {
 	int i;
 
@@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int re
 	return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0;
 }
 
-static int PWM_RR_TO_REG(int val, int ix, int reg)
+static int PWM_RR_TO_REG(long val, int ix, int reg)
 {
 	int i;
 
@@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int
 	return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;
 }
 
-static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg)
+static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg)
 {
 	int en = (ix == 1) ? 0x80 : 0x08;
 
@@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *de
 		       const char *buf, size_t count)
 {
 	struct dme1737_data *data = dev_get_drvdata(dev);
-	long val;
+	unsigned long val;
 	int err;
 
-	err = kstrtol(buf, 10, &val);
+	err = kstrtoul(buf, 10, &val);
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ds1621.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ds1621.c
--- linux-libre-3.16-gnu/drivers/hwmon/ds1621.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ds1621.c	2014-09-28 17:29:07.000000000 -0400
@@ -309,6 +309,7 @@ static ssize_t set_convrate(struct devic
 	data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT);
 	i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf);
 	data->update_interval = ds1721_convrates[resol];
+	data->zbits = 7 - resol;
 	mutex_unlock(&data->update_lock);
 
 	return count;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ds620.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ds620.c
--- linux-libre-3.16-gnu/drivers/hwmon/ds620.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ds620.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,7 @@ static const u8 DS620_REG_TEMP[3] = {
 
 /* Each client has this additional data */
 struct ds620_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -106,8 +106,8 @@ static void ds620_init_client(struct i2c
 
 static struct ds620_data *ds620_update_client(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds620_data *data = i2c_get_clientdata(client);
+	struct ds620_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct ds620_data *ret = data;
 
 	mutex_lock(&data->update_lock);
@@ -158,8 +158,8 @@ static ssize_t set_temp(struct device *d
 	long val;
 
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds620_data *data = i2c_get_clientdata(client);
+	struct ds620_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	res = kstrtol(buf, 10, &val);
 
@@ -181,13 +181,15 @@ static ssize_t show_alarm(struct device
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct ds620_data *data = ds620_update_client(dev);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client;
 	u16 conf, new_conf;
 	int res;
 
 	if (IS_ERR(data))
 		return PTR_ERR(data);
 
+	client = data->client;
+
 	/* reset alarms if necessary */
 	res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 	if (res < 0)
@@ -213,7 +215,7 @@ static SENSOR_DEVICE_ATTR(temp1_min_alar
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
 			  DS620_REG_CONFIG_THF);
 
-static struct attribute *ds620_attributes[] = {
+static struct attribute *ds620_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -222,55 +224,28 @@ static struct attribute *ds620_attribute
 	NULL
 };
 
-static const struct attribute_group ds620_group = {
-	.attrs = ds620_attributes,
-};
+ATTRIBUTE_GROUPS(ds620);
 
 static int ds620_probe(struct i2c_client *client,
 		       const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct ds620_data *data;
-	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct ds620_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct ds620_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the DS620 chip */
 	ds620_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &ds620_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	dev_info(&client->dev, "temperature sensor found\n");
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &ds620_group);
-	return err;
-}
-
-static int ds620_remove(struct i2c_client *client)
-{
-	struct ds620_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ds620_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, ds620_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ds620_id[] = {
@@ -287,7 +262,6 @@ static struct i2c_driver ds620_driver =
 		   .name = "ds620",
 	},
 	.probe = ds620_probe,
-	.remove = ds620_remove,
 	.id_table = ds620_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/emc1403.c linux-libre-3.17-rc7-gnu/drivers/hwmon/emc1403.c
--- linux-libre-3.16-gnu/drivers/hwmon/emc1403.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/emc1403.c	2014-09-28 17:29:07.000000000 -0400
@@ -416,7 +416,7 @@ static bool emc1403_regmap_is_volatile(s
 	}
 }
 
-static struct regmap_config emc1403_regmap_config = {
+static const struct regmap_config emc1403_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.cache_type = REGCACHE_RBTREE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/emc2103.c linux-libre-3.17-rc7-gnu/drivers/hwmon/emc2103.c
--- linux-libre-3.16-gnu/drivers/hwmon/emc2103.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/emc2103.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,7 +66,8 @@ struct temperature {
 };
 
 struct emc2103_data {
-	struct device		*hwmon_dev;
+	struct i2c_client	*client;
+	const struct		attribute_group *groups[4];
 	struct mutex		update_lock;
 	bool			valid;		/* registers are valid */
 	bool			fan_rpm_control;
@@ -146,8 +147,8 @@ static void read_fan_config_from_i2c(str
 
 static struct emc2103_data *emc2103_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc2103_data *data = i2c_get_clientdata(client);
+	struct emc2103_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -242,8 +243,8 @@ static ssize_t set_temp_min(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(da)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc2103_data *data = i2c_get_clientdata(client);
+	struct emc2103_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 
 	int result = kstrtol(buf, 10, &val);
@@ -264,8 +265,8 @@ static ssize_t set_temp_max(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(da)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc2103_data *data = i2c_get_clientdata(client);
+	struct emc2103_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 
 	int result = kstrtol(buf, 10, &val);
@@ -310,7 +311,7 @@ static ssize_t set_fan_div(struct device
 			   const char *buf, size_t count)
 {
 	struct emc2103_data *data = emc2103_update_device(dev);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = data->client;
 	int new_range_bits, old_div = 8 / data->fan_multiplier;
 	long new_div;
 
@@ -385,7 +386,7 @@ static ssize_t set_fan_target(struct dev
 			      const char *buf, size_t count)
 {
 	struct emc2103_data *data = emc2103_update_device(dev);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = data->client;
 	unsigned long rpm_target;
 
 	int result = kstrtoul(buf, 10, &rpm_target);
@@ -428,8 +429,8 @@ show_pwm_enable(struct device *dev, stru
 static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da,
 			      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc2103_data *data = i2c_get_clientdata(client);
+	struct emc2103_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long new_value;
 	u8 conf_reg;
 
@@ -580,7 +581,8 @@ static int
 emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct emc2103_data *data;
-	int status;
+	struct device *hwmon_dev;
+	int status, idx = 0;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
@@ -591,6 +593,7 @@ emc2103_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */
@@ -624,60 +627,21 @@ emc2103_probe(struct i2c_client *client,
 		}
 	}
 
-	/* Register sysfs hooks */
-	status = sysfs_create_group(&client->dev.kobj, &emc2103_group);
-	if (status)
-		return status;
-
-	if (data->temp_count >= 3) {
-		status = sysfs_create_group(&client->dev.kobj,
-			&emc2103_temp3_group);
-		if (status)
-			goto exit_remove;
-	}
-
-	if (data->temp_count == 4) {
-		status = sysfs_create_group(&client->dev.kobj,
-			&emc2103_temp4_group);
-		if (status)
-			goto exit_remove_temp3;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		status = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_temp4;
-	}
-
-	dev_info(&client->dev, "%s: sensor '%s'\n",
-		 dev_name(data->hwmon_dev), client->name);
-
-	return 0;
-
-exit_remove_temp4:
-	if (data->temp_count == 4)
-		sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
-exit_remove_temp3:
+	/* sysfs hooks */
+	data->groups[idx++] = &emc2103_group;
 	if (data->temp_count >= 3)
-		sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
-	return status;
-}
-
-static int emc2103_remove(struct i2c_client *client)
-{
-	struct emc2103_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-
+		data->groups[idx++] = &emc2103_temp3_group;
 	if (data->temp_count == 4)
-		sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
+		data->groups[idx++] = &emc2103_temp4_group;
 
-	if (data->temp_count >= 3)
-		sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name, data,
+							   data->groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
-	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
+	dev_info(&client->dev, "%s: sensor '%s'\n",
+		 dev_name(hwmon_dev), client->name);
 
 	return 0;
 }
@@ -717,7 +681,6 @@ static struct i2c_driver emc2103_driver
 		.name	= "emc2103",
 	},
 	.probe		= emc2103_probe,
-	.remove		= emc2103_remove,
 	.id_table	= emc2103_ids,
 	.detect		= emc2103_detect,
 	.address_list	= normal_i2c,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/emc6w201.c linux-libre-3.17-rc7-gnu/drivers/hwmon/emc6w201.c
--- linux-libre-3.16-gnu/drivers/hwmon/emc6w201.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/emc6w201.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@ enum subfeature { input, min, max };
  */
 
 struct emc6w201_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -134,8 +134,8 @@ static int emc6w201_write8(struct i2c_cl
 
 static struct emc6w201_data *emc6w201_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc6w201_data *data = i2c_get_clientdata(client);
+	struct emc6w201_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr;
 
 	mutex_lock(&data->update_lock);
@@ -203,8 +203,8 @@ static ssize_t show_in(struct device *de
 static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
 		      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc6w201_data *data = i2c_get_clientdata(client);
+	struct emc6w201_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int sf = to_sensor_dev_attr_2(devattr)->index;
 	int nr = to_sensor_dev_attr_2(devattr)->nr;
 	int err;
@@ -240,8 +240,8 @@ static ssize_t show_temp(struct device *
 static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc6w201_data *data = i2c_get_clientdata(client);
+	struct emc6w201_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int sf = to_sensor_dev_attr_2(devattr)->index;
 	int nr = to_sensor_dev_attr_2(devattr)->nr;
 	int err;
@@ -252,12 +252,12 @@ static ssize_t set_temp(struct device *d
 	if (err < 0)
 		return err;
 
-	val /= 1000;
+	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, 128);
+	data->temp[sf][nr] = clamp_val(val, -127, 127);
 	err = emc6w201_write8(client, reg, data->temp[sf][nr]);
 	mutex_unlock(&data->update_lock);
 
@@ -283,8 +283,8 @@ static ssize_t show_fan(struct device *d
 static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct emc6w201_data *data = i2c_get_clientdata(client);
+	struct emc6w201_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int sf = to_sensor_dev_attr_2(devattr)->index;
 	int nr = to_sensor_dev_attr_2(devattr)->nr;
 	int err;
@@ -388,7 +388,7 @@ static SENSOR_DEVICE_ATTR_2(fan5_input,
 static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 			    4, min);
 
-static struct attribute *emc6w201_attributes[] = {
+static struct attribute *emc6w201_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -440,9 +440,7 @@ static struct attribute *emc6w201_attrib
 	NULL
 };
 
-static const struct attribute_group emc6w201_group = {
-	.attrs = emc6w201_attributes,
-};
+ATTRIBUTE_GROUPS(emc6w201);
 
 /*
  * Driver interface
@@ -488,44 +486,21 @@ static int emc6w201_detect(struct i2c_cl
 static int emc6w201_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct emc6w201_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct emc6w201_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct emc6w201_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
-	/* Create sysfs attribute */
-	err = sysfs_create_group(&client->dev.kobj, &emc6w201_group);
-	if (err)
-		return err;
-
-	/* Expose as a hwmon device */
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
- exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
-	return err;
-}
-
-static int emc6w201_remove(struct i2c_client *client)
-{
-	struct emc6w201_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   emc6w201_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id emc6w201_id[] = {
@@ -540,7 +515,6 @@ static struct i2c_driver emc6w201_driver
 		.name	= "emc6w201",
 	},
 	.probe		= emc6w201_probe,
-	.remove		= emc6w201_remove,
 	.id_table	= emc6w201_id,
 	.detect		= emc6w201_detect,
 	.address_list	= normal_i2c,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/fam15h_power.c linux-libre-3.17-rc7-gnu/drivers/hwmon/fam15h_power.c
--- linux-libre-3.16-gnu/drivers/hwmon/fam15h_power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/fam15h_power.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,9 +31,6 @@ MODULE_DESCRIPTION("AMD Family 15h CPU p
 MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
 MODULE_LICENSE("GPL");
 
-/* Family 16h Northbridge's function 4 PCI ID */
-#define PCI_DEVICE_ID_AMD_16H_NB_F4	0x1534
-
 /* D18F3 */
 #define REG_NORTHBRIDGE_CAP		0xe8
 
@@ -45,7 +42,7 @@ MODULE_LICENSE("GPL");
 #define REG_TDP_LIMIT3			0xe8
 
 struct fam15h_power_data {
-	struct device *hwmon_dev;
+	struct pci_dev *pdev;
 	unsigned int tdp_to_watts;
 	unsigned int base_tdp;
 	unsigned int processor_pwr_watts;
@@ -57,8 +54,8 @@ static ssize_t show_power(struct device
 	u32 val, tdp_limit, running_avg_range;
 	s32 running_avg_capture;
 	u64 curr_pwr_watts;
-	struct pci_dev *f4 = to_pci_dev(dev);
 	struct fam15h_power_data *data = dev_get_drvdata(dev);
+	struct pci_dev *f4 = data->pdev;
 
 	pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
 				  REG_TDP_RUNNING_AVERAGE, &val);
@@ -96,23 +93,29 @@ static ssize_t show_power_crit(struct de
 }
 static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL);
 
-static ssize_t show_name(struct device *dev,
-			 struct device_attribute *attr, char *buf)
+static umode_t fam15h_power_is_visible(struct kobject *kobj,
+				       struct attribute *attr,
+				       int index)
 {
-	return sprintf(buf, "fam15h_power\n");
+	/* power1_input is only reported for Fam15h, Models 00h-0fh */
+	if (attr == &dev_attr_power1_input.attr &&
+	   (boot_cpu_data.x86 != 0x15 || boot_cpu_data.x86_model > 0xf))
+		return 0;
+
+	return attr->mode;
 }
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static struct attribute *fam15h_power_attrs[] = {
 	&dev_attr_power1_input.attr,
 	&dev_attr_power1_crit.attr,
-	&dev_attr_name.attr,
 	NULL
 };
 
-static const struct attribute_group fam15h_power_attr_group = {
-	.attrs	= fam15h_power_attrs,
+static const struct attribute_group fam15h_power_group = {
+	.attrs = fam15h_power_attrs,
+	.is_visible = fam15h_power_is_visible,
 };
+__ATTRIBUTE_GROUPS(fam15h_power);
 
 static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
 {
@@ -202,7 +205,7 @@ static int fam15h_power_probe(struct pci
 {
 	struct fam15h_power_data *data;
 	struct device *dev = &pdev->dev;
-	int err;
+	struct device *hwmon_dev;
 
 	/*
 	 * though we ignore every other northbridge, we still have to
@@ -219,39 +222,19 @@ static int fam15h_power_probe(struct pci
 		return -ENOMEM;
 
 	fam15h_power_init_data(pdev, data);
+	data->pdev = pdev;
 
-	dev_set_drvdata(dev, data);
-	err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_group;
-	}
-
-	return 0;
-
-exit_remove_group:
-	sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
-	return err;
-}
-
-static void fam15h_power_remove(struct pci_dev *pdev)
-{
-	struct device *dev;
-	struct fam15h_power_data *data;
-
-	dev = &pdev->dev;
-	data = dev_get_drvdata(dev);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power",
+							   data,
+							   fam15h_power_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct pci_device_id fam15h_power_id_table[] = {
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, fam15h_power_id_table);
@@ -260,7 +243,6 @@ static struct pci_driver fam15h_power_dr
 	.name = "fam15h_power",
 	.id_table = fam15h_power_id_table,
 	.probe = fam15h_power_probe,
-	.remove = fam15h_power_remove,
 	.resume = fam15h_power_resume,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/g760a.c linux-libre-3.17-rc7-gnu/drivers/hwmon/g760a.c
--- linux-libre-3.16-gnu/drivers/hwmon/g760a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/g760a.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,6 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 
-static const struct i2c_device_id g760a_id[] = {
-	{ "g760a", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, g760a_id);
-
 enum g760a_regs {
 	G760A_REG_SET_CNT = 0x00,
 	G760A_REG_ACT_CNT = 0x01,
@@ -44,7 +38,6 @@ enum g760a_regs {
 
 struct g760a_data {
 	struct i2c_client *client;
-	struct device *hwmon_dev;
 	struct mutex update_lock;
 
 	/* board specific parameters */
@@ -74,20 +67,6 @@ static inline unsigned int rpm_from_cnt(
 	return ((val == 0x00) ? 0 : ((clk*30)/(val*div)));
 }
 
-/* new-style driver model */
-static int g760a_probe(struct i2c_client *client,
-			const struct i2c_device_id *id);
-static int g760a_remove(struct i2c_client *client);
-
-static struct i2c_driver g760a_driver = {
-	.driver = {
-		.name	= "g760a",
-	},
-	.probe	  = g760a_probe,
-	.remove	  = g760a_remove,
-	.id_table = g760a_id,
-};
-
 /* read/write wrappers */
 static int g760a_read_value(struct i2c_client *client, enum g760a_regs reg)
 {
@@ -106,8 +85,8 @@ static int g760a_write_value(struct i2c_
 
 static struct g760a_data *g760a_update_client(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct g760a_data *data = i2c_get_clientdata(client);
+	struct g760a_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 
@@ -163,8 +142,8 @@ static ssize_t get_pwm(struct device *de
 static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
 		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g760a_data *data = g760a_update_client(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val))
@@ -182,16 +161,14 @@ static DEVICE_ATTR(pwm1, S_IWUSR | S_IRU
 static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL);
 static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
 
-static struct attribute *g760a_attributes[] = {
+static struct attribute *g760a_attrs[] = {
 	&dev_attr_pwm1.attr,
 	&dev_attr_fan1_input.attr,
 	&dev_attr_fan1_alarm.attr,
 	NULL
 };
 
-static const struct attribute_group g760a_group = {
-	.attrs = g760a_attributes,
-};
+ATTRIBUTE_GROUPS(g760a);
 
 /*
  * new-style driver model code
@@ -200,20 +177,17 @@ static const struct attribute_group g760
 static int g760a_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct g760a_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	if (!i2c_check_functionality(client->adapter,
-				     I2C_FUNC_SMBUS_BYTE_DATA))
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct g760a_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct g760a_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
-
 	data->client = client;
 	mutex_init(&data->update_lock);
 
@@ -221,31 +195,25 @@ static int g760a_probe(struct i2c_client
 	data->fan_div = G760A_DEFAULT_FAN_DIV;
 	data->clk = G760A_DEFAULT_CLK;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &g760a_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error_hwmon_device_register;
-	}
-
-	return 0;
-
-error_hwmon_device_register:
-	sysfs_remove_group(&client->dev.kobj, &g760a_group);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   g760a_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int g760a_remove(struct i2c_client *client)
-{
-	struct g760a_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &g760a_group);
-	return 0;
-}
+static const struct i2c_device_id g760a_id[] = {
+	{ "g760a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, g760a_id);
+
+static struct i2c_driver g760a_driver = {
+	.driver = {
+		.name	= "g760a",
+	},
+	.probe	  = g760a_probe,
+	.id_table = g760a_id,
+};
 
 module_i2c_driver(g760a_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/g762.c linux-libre-3.17-rc7-gnu/drivers/hwmon/g762.c
--- linux-libre-3.16-gnu/drivers/hwmon/g762.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/g762.c	2014-09-28 17:29:07.000000000 -0400
@@ -128,8 +128,8 @@ enum g762_regs {
 			 G762_REG_FAN_CMD2_GEAR_MODE_1)) >> 2))
 
 struct g762_data {
-	struct i2c_client *client;
 	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct clk *clk;
 
 	/* update mutex */
@@ -206,8 +206,8 @@ static inline unsigned char cnt_from_rpm
 /* helper to grab and cache data, at most one time per second */
 static struct g762_data *g762_update_client(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct g762_data *data = i2c_get_clientdata(client);
+	struct g762_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int ret = 0;
 
 	mutex_lock(&data->update_lock);
@@ -266,8 +266,7 @@ static struct g762_data *g762_update_cli
  */
 static int do_set_clk_freq(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct g762_data *data = i2c_get_clientdata(client);
+	struct g762_data *data = dev_get_drvdata(dev);
 
 	if (val > 0xffffff)
 		return -EINVAL;
@@ -282,7 +281,6 @@ static int do_set_clk_freq(struct device
 /* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */
 static int do_set_pwm_mode(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -301,7 +299,7 @@ static int do_set_pwm_mode(struct device
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					data->fan_cmd1);
 	data->valid = false;
  out:
@@ -313,7 +311,6 @@ static int do_set_pwm_mode(struct device
 /* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */
 static int do_set_fan_div(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -342,7 +339,7 @@ static int do_set_fan_div(struct device
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					data->fan_cmd1);
 	data->valid = false;
  out:
@@ -354,7 +351,6 @@ static int do_set_fan_div(struct device
 /* Set fan gear mode. Accepts either 0, 1 or 2. */
 static int do_set_fan_gear_mode(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -379,7 +375,7 @@ static int do_set_fan_gear_mode(struct d
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
 					data->fan_cmd2);
 	data->valid = false;
  out:
@@ -391,7 +387,6 @@ static int do_set_fan_gear_mode(struct d
 /* Set number of fan pulses per revolution. Accepts either 2 or 4. */
 static int do_set_fan_pulses(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -410,7 +405,7 @@ static int do_set_fan_pulses(struct devi
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					data->fan_cmd1);
 	data->valid = false;
  out:
@@ -422,7 +417,6 @@ static int do_set_fan_pulses(struct devi
 /* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */
 static int do_set_pwm_enable(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -444,15 +438,15 @@ static int do_set_pwm_enable(struct devi
 		 * value of 254 if it is 255 when switching to open-loop.
 		 */
 		if (data->set_cnt == 0xff)
-			i2c_smbus_write_byte_data(client, G762_REG_SET_CNT,
-						  254);
+			i2c_smbus_write_byte_data(data->client,
+						  G762_REG_SET_CNT, 254);
 		break;
 	default:
 		ret = -EINVAL;
 		goto out;
 	}
 
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					data->fan_cmd1);
 	data->valid = false;
  out:
@@ -464,7 +458,6 @@ static int do_set_pwm_enable(struct devi
 /* Set PWM polarity. Accepts either 0 (positive duty) or 1 (negative duty) */
 static int do_set_pwm_polarity(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -483,7 +476,7 @@ static int do_set_pwm_polarity(struct de
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					data->fan_cmd1);
 	data->valid = false;
  out:
@@ -498,8 +491,8 @@ static int do_set_pwm_polarity(struct de
  */
 static int do_set_pwm(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct g762_data *data = i2c_get_clientdata(client);
+	struct g762_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int ret;
 
 	if (val > 255)
@@ -519,7 +512,6 @@ static int do_set_pwm(struct device *dev
  */
 static int do_set_fan_target(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -531,7 +523,7 @@ static int do_set_fan_target(struct devi
 				     G762_PULSE_FROM_REG(data->fan_cmd1),
 				     G762_CLKDIV_FROM_REG(data->fan_cmd1),
 				     G762_GEARMULT_FROM_REG(data->fan_cmd2));
-	ret = i2c_smbus_write_byte_data(client, G762_REG_SET_CNT,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_SET_CNT,
 					data->set_cnt);
 	data->valid = false;
 	mutex_unlock(&data->update_lock);
@@ -542,7 +534,6 @@ static int do_set_fan_target(struct devi
 /* Set fan startup voltage. Accepted values are either 0, 1, 2 or 3. */
 static int do_set_fan_startv(struct device *dev, unsigned long val)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 	int ret;
 
@@ -571,7 +562,7 @@ static int do_set_fan_startv(struct devi
 		ret = -EINVAL;
 		goto out;
 	}
-	ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2,
+	ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
 					data->fan_cmd2);
 	data->valid = false;
  out:
@@ -658,15 +649,12 @@ static int g762_of_prop_import_one(struc
 				   int (*psetter)(struct device *dev,
 						  unsigned long val))
 {
-	const __be32 *prop;
-	int len, ret;
+	int ret;
 	u32 pval;
 
-	prop = of_get_property(client->dev.of_node, pname, &len);
-	if (!prop || len != sizeof(u32))
+	if (of_property_read_u32(client->dev.of_node, pname, &pval))
 		return 0;
 
-	pval = be32_to_cpu(prop[0]);
 	dev_dbg(&client->dev, "found %s (%d)\n", pname, pval);
 	ret = (*psetter)(&client->dev, pval);
 	if (ret)
@@ -1026,7 +1014,7 @@ static DEVICE_ATTR(fan1_pulses, S_IWUSR
 		   get_fan_pulses, set_fan_pulses);
 
 /* Driver data */
-static struct attribute *g762_attributes[] = {
+static struct attribute *g762_attrs[] = {
 	&dev_attr_fan1_input.attr,
 	&dev_attr_fan1_alarm.attr,
 	&dev_attr_fan1_fault.attr,
@@ -1039,9 +1027,7 @@ static struct attribute *g762_attributes
 	NULL
 };
 
-static const struct attribute_group g762_group = {
-	.attrs = g762_attributes,
-};
+ATTRIBUTE_GROUPS(g762);
 
 /*
  * Enable both fan failure detection and fan out of control protection. The
@@ -1050,7 +1036,6 @@ static const struct attribute_group g762
  */
 static inline int g762_fan_init(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct g762_data *data = g762_update_client(dev);
 
 	if (IS_ERR(data))
@@ -1060,12 +1045,13 @@ static inline int g762_fan_init(struct d
 	data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC;
 	data->valid = false;
 
-	return i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+	return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
 					 data->fan_cmd1);
 }
 
 static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct g762_data *data;
 	int ret;
 
@@ -1073,7 +1059,7 @@ static int g762_probe(struct i2c_client
 				     I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct g762_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct g762_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -1082,7 +1068,7 @@ static int g762_probe(struct i2c_client
 	mutex_init(&data->update_lock);
 
 	/* Enable fan failure detection and fan out of control protection */
-	ret = g762_fan_init(&client->dev);
+	ret = g762_fan_init(dev);
 	if (ret)
 		return ret;
 
@@ -1098,22 +1084,17 @@ static int g762_probe(struct i2c_client
 	if (ret)
 		goto clock_dis;
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &g762_group);
-	if (ret)
-		goto clock_dis;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
+	data->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+								 client->name,
+								 data,
+								 g762_groups);
 	if (IS_ERR(data->hwmon_dev)) {
 		ret = PTR_ERR(data->hwmon_dev);
-		goto sysfs_rem;
+		goto clock_dis;
 	}
 
 	return 0;
 
- sysfs_rem:
-	sysfs_remove_group(&client->dev.kobj, &g762_group);
-
  clock_dis:
 	g762_of_clock_disable(client);
 
@@ -1125,7 +1106,6 @@ static int g762_remove(struct i2c_client
 	struct g762_data *data = i2c_get_clientdata(client);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &g762_group);
 	g762_of_clock_disable(client);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/gl518sm.c linux-libre-3.17-rc7-gnu/drivers/hwmon/gl518sm.c
--- linux-libre-3.16-gnu/drivers/hwmon/gl518sm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/gl518sm.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,8 @@ static inline u8 FAN_TO_REG(long rpm, in
 
 /* Each client has this additional data */
 struct gl518_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	enum chips type;
 
 	struct mutex update_lock;
@@ -137,33 +138,98 @@ struct gl518_data {
 	u8 beep_enable;		/* Boolean */
 };
 
-static int gl518_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id);
-static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info);
-static void gl518_init_client(struct i2c_client *client);
-static int gl518_remove(struct i2c_client *client);
-static int gl518_read_value(struct i2c_client *client, u8 reg);
-static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
-static struct gl518_data *gl518_update_device(struct device *dev);
+/*
+ * Registers 0x07 to 0x0c are word-sized, others are byte-sized
+ * GL518 uses a high-byte first convention, which is exactly opposite to
+ * the SMBus standard.
+ */
+static int gl518_read_value(struct i2c_client *client, u8 reg)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return i2c_smbus_read_word_swapped(client, reg);
+	else
+		return i2c_smbus_read_byte_data(client, reg);
+}
 
-static const struct i2c_device_id gl518_id[] = {
-	{ "gl518sm", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, gl518_id);
+static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return i2c_smbus_write_word_swapped(client, reg, value);
+	else
+		return i2c_smbus_write_byte_data(client, reg, value);
+}
 
-/* This is the driver that will be inserted */
-static struct i2c_driver gl518_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "gl518sm",
-	},
-	.probe		= gl518_probe,
-	.remove		= gl518_remove,
-	.id_table	= gl518_id,
-	.detect		= gl518_detect,
-	.address_list	= normal_i2c,
-};
+static struct gl518_data *gl518_update_device(struct device *dev)
+{
+	struct gl518_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int val;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		dev_dbg(&client->dev, "Starting gl518 update\n");
+
+		data->alarms = gl518_read_value(client, GL518_REG_INT);
+		data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
+
+		val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
+		data->voltage_min[0] = val & 0xff;
+		data->voltage_max[0] = (val >> 8) & 0xff;
+		val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
+		data->voltage_min[1] = val & 0xff;
+		data->voltage_max[1] = (val >> 8) & 0xff;
+		val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
+		data->voltage_min[2] = val & 0xff;
+		data->voltage_max[2] = (val >> 8) & 0xff;
+		val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
+		data->voltage_min[3] = val & 0xff;
+		data->voltage_max[3] = (val >> 8) & 0xff;
+
+		val = gl518_read_value(client, GL518_REG_FAN_COUNT);
+		data->fan_in[0] = (val >> 8) & 0xff;
+		data->fan_in[1] = val & 0xff;
+
+		val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
+		data->fan_min[0] = (val >> 8) & 0xff;
+		data->fan_min[1] = val & 0xff;
+
+		data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN);
+		data->temp_max =
+		    gl518_read_value(client, GL518_REG_TEMP_MAX);
+		data->temp_hyst =
+		    gl518_read_value(client, GL518_REG_TEMP_HYST);
+
+		val = gl518_read_value(client, GL518_REG_MISC);
+		data->fan_div[0] = (val >> 6) & 0x03;
+		data->fan_div[1] = (val >> 4) & 0x03;
+		data->fan_auto1  = (val >> 3) & 0x01;
+
+		data->alarms &= data->alarm_mask;
+
+		val = gl518_read_value(client, GL518_REG_CONF);
+		data->beep_enable = (val >> 2) & 1;
+
+		if (data->type != gl518sm_r00) {
+			data->voltage_in[0] =
+			    gl518_read_value(client, GL518_REG_VDD);
+			data->voltage_in[1] =
+			    gl518_read_value(client, GL518_REG_VIN1);
+			data->voltage_in[2] =
+			    gl518_read_value(client, GL518_REG_VIN2);
+		}
+		data->voltage_in[3] =
+		    gl518_read_value(client, GL518_REG_VIN3);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 /*
  * Sysfs stuff
@@ -228,8 +294,8 @@ static ssize_t set_##suffix(struct devic
 			    struct device_attribute *attr,		\
 			    const char *buf, size_t count)		\
 {									\
-	struct i2c_client *client = to_i2c_client(dev);			\
-	struct gl518_data *data = i2c_get_clientdata(client);		\
+	struct gl518_data *data = dev_get_drvdata(dev);			\
+	struct i2c_client *client = data->client;			\
 	long val;							\
 	int err = kstrtol(buf, 10, &val);				\
 	if (err)							\
@@ -247,8 +313,8 @@ static ssize_t set_##suffix(struct devic
 			    struct device_attribute *attr,		\
 			    const char *buf, size_t count)		\
 {									\
-	struct i2c_client *client = to_i2c_client(dev);			\
-	struct gl518_data *data = i2c_get_clientdata(client);		\
+	struct gl518_data *data = dev_get_drvdata(dev);			\
+	struct i2c_client *client = data->client;			\
 	int regvalue;							\
 	unsigned long val;						\
 	int err = kstrtoul(buf, 10, &val);				\
@@ -286,8 +352,8 @@ set(BEEP_MASK, beep_mask, beep_mask, GL5
 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 gl518_data *data = i2c_get_clientdata(client);
+	struct gl518_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
 	unsigned long val;
@@ -319,8 +385,8 @@ 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 gl518_data *data = i2c_get_clientdata(client);
+	struct gl518_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
 	unsigned long val;
@@ -420,8 +486,8 @@ static ssize_t show_beep(struct device *
 static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl518_data *data = i2c_get_clientdata(client);
+	struct gl518_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	unsigned long bit;
 	int err;
@@ -539,52 +605,6 @@ static int gl518_detect(struct i2c_clien
 	return 0;
 }
 
-static int gl518_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id)
-{
-	struct gl518_data *data;
-	int err, revision;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct gl518_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	revision = gl518_read_value(client, GL518_REG_REVISION);
-	data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
-	mutex_init(&data->update_lock);
-
-	/* Initialize the GL518SM chip */
-	data->alarm_mask = 0xff;
-	gl518_init_client(client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &gl518_group);
-	if (err)
-		return err;
-	if (data->type == gl518sm_r80) {
-		err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80);
-		if (err)
-			goto exit_remove_files;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &gl518_group);
-	if (data->type == gl518sm_r80)
-		sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
-	return err;
-}
-
-
 /*
  * Called when we have found a new GL518SM.
  * Note that we preserve D4:NoFan2 and D2:beep_enable.
@@ -605,110 +625,53 @@ static void gl518_init_client(struct i2c
 	gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
 }
 
-static int gl518_remove(struct i2c_client *client)
-{
-	struct gl518_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &gl518_group);
-	if (data->type == gl518sm_r80)
-		sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
-
-	return 0;
-}
-
-/*
- * Registers 0x07 to 0x0c are word-sized, others are byte-sized
- * GL518 uses a high-byte first convention, which is exactly opposite to
- * the SMBus standard.
- */
-static int gl518_read_value(struct i2c_client *client, u8 reg)
-{
-	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_read_word_swapped(client, reg);
-	else
-		return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_swapped(client, reg, value);
-	else
-		return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static struct gl518_data *gl518_update_device(struct device *dev)
+static int gl518_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl518_data *data = i2c_get_clientdata(client);
-	int val;
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		dev_dbg(&client->dev, "Starting gl518 update\n");
-
-		data->alarms = gl518_read_value(client, GL518_REG_INT);
-		data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
-
-		val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
-		data->voltage_min[0] = val & 0xff;
-		data->voltage_max[0] = (val >> 8) & 0xff;
-		val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
-		data->voltage_min[1] = val & 0xff;
-		data->voltage_max[1] = (val >> 8) & 0xff;
-		val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
-		data->voltage_min[2] = val & 0xff;
-		data->voltage_max[2] = (val >> 8) & 0xff;
-		val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
-		data->voltage_min[3] = val & 0xff;
-		data->voltage_max[3] = (val >> 8) & 0xff;
-
-		val = gl518_read_value(client, GL518_REG_FAN_COUNT);
-		data->fan_in[0] = (val >> 8) & 0xff;
-		data->fan_in[1] = val & 0xff;
-
-		val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
-		data->fan_min[0] = (val >> 8) & 0xff;
-		data->fan_min[1] = val & 0xff;
-
-		data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN);
-		data->temp_max =
-		    gl518_read_value(client, GL518_REG_TEMP_MAX);
-		data->temp_hyst =
-		    gl518_read_value(client, GL518_REG_TEMP_HYST);
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct gl518_data *data;
+	int revision;
 
-		val = gl518_read_value(client, GL518_REG_MISC);
-		data->fan_div[0] = (val >> 6) & 0x03;
-		data->fan_div[1] = (val >> 4) & 0x03;
-		data->fan_auto1  = (val >> 3) & 0x01;
+	data = devm_kzalloc(dev, sizeof(struct gl518_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-		data->alarms &= data->alarm_mask;
+	data->client = client;
+	revision = gl518_read_value(client, GL518_REG_REVISION);
+	data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
+	mutex_init(&data->update_lock);
 
-		val = gl518_read_value(client, GL518_REG_CONF);
-		data->beep_enable = (val >> 2) & 1;
+	/* Initialize the GL518SM chip */
+	data->alarm_mask = 0xff;
+	gl518_init_client(client);
 
-		if (data->type != gl518sm_r00) {
-			data->voltage_in[0] =
-			    gl518_read_value(client, GL518_REG_VDD);
-			data->voltage_in[1] =
-			    gl518_read_value(client, GL518_REG_VIN1);
-			data->voltage_in[2] =
-			    gl518_read_value(client, GL518_REG_VIN2);
-		}
-		data->voltage_in[3] =
-		    gl518_read_value(client, GL518_REG_VIN3);
+	/* sysfs hooks */
+	data->groups[0] = &gl518_group;
+	if (data->type == gl518sm_r80)
+		data->groups[1] = &gl518_group_r80;
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id gl518_id[] = {
+	{ "gl518sm", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, gl518_id);
 
-	return data;
-}
+static struct i2c_driver gl518_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "gl518sm",
+	},
+	.probe		= gl518_probe,
+	.id_table	= gl518_id,
+	.detect		= gl518_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(gl518_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/gl520sm.c linux-libre-3.17-rc7-gnu/drivers/hwmon/gl520sm.c
--- linux-libre-3.16-gnu/drivers/hwmon/gl520sm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/gl520sm.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,41 +73,10 @@ static const u8 GL520_REG_TEMP_MAX_HYST[
 #define GL520_REG_BEEP_MASK		0x10
 #define GL520_REG_BEEP_ENABLE		GL520_REG_CONF
 
-/*
- * Function declarations
- */
-
-static int gl520_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id);
-static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info);
-static void gl520_init_client(struct i2c_client *client);
-static int gl520_remove(struct i2c_client *client);
-static int gl520_read_value(struct i2c_client *client, u8 reg);
-static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
-static struct gl520_data *gl520_update_device(struct device *dev);
-
-/* Driver data */
-static const struct i2c_device_id gl520_id[] = {
-	{ "gl520sm", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, gl520_id);
-
-static struct i2c_driver gl520_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "gl520sm",
-	},
-	.probe		= gl520_probe,
-	.remove		= gl520_remove,
-	.id_table	= gl520_id,
-	.detect		= gl520_detect,
-	.address_list	= normal_i2c,
-};
-
 /* Client data */
 struct gl520_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	char valid;		/* zero until the following fields are valid */
 	unsigned long last_updated;	/* in jiffies */
@@ -132,6 +101,102 @@ struct gl520_data {
 };
 
 /*
+ * Registers 0x07 to 0x0c are word-sized, others are byte-sized
+ * GL520 uses a high-byte first convention
+ */
+static int gl520_read_value(struct i2c_client *client, u8 reg)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return i2c_smbus_read_word_swapped(client, reg);
+	else
+		return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return i2c_smbus_write_word_swapped(client, reg, value);
+	else
+		return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static struct gl520_data *gl520_update_device(struct device *dev)
+{
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int val, i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+
+		dev_dbg(&client->dev, "Starting gl520sm update\n");
+
+		data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
+		data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+		data->vid = gl520_read_value(client,
+					     GL520_REG_VID_INPUT) & 0x1f;
+
+		for (i = 0; i < 4; i++) {
+			data->in_input[i] = gl520_read_value(client,
+							GL520_REG_IN_INPUT[i]);
+			val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]);
+			data->in_min[i] = val & 0xff;
+			data->in_max[i] = (val >> 8) & 0xff;
+		}
+
+		val = gl520_read_value(client, GL520_REG_FAN_INPUT);
+		data->fan_input[0] = (val >> 8) & 0xff;
+		data->fan_input[1] = val & 0xff;
+
+		val = gl520_read_value(client, GL520_REG_FAN_MIN);
+		data->fan_min[0] = (val >> 8) & 0xff;
+		data->fan_min[1] = val & 0xff;
+
+		data->temp_input[0] = gl520_read_value(client,
+						GL520_REG_TEMP_INPUT[0]);
+		data->temp_max[0] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX[0]);
+		data->temp_max_hyst[0] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX_HYST[0]);
+
+		val = gl520_read_value(client, GL520_REG_FAN_DIV);
+		data->fan_div[0] = (val >> 6) & 0x03;
+		data->fan_div[1] = (val >> 4) & 0x03;
+		data->fan_off = (val >> 2) & 0x01;
+
+		data->alarms &= data->alarm_mask;
+
+		val = gl520_read_value(client, GL520_REG_CONF);
+		data->beep_enable = !((val >> 2) & 1);
+
+		/* Temp1 and Vin4 are the same input */
+		if (data->two_temps) {
+			data->temp_input[1] = gl520_read_value(client,
+						GL520_REG_TEMP_INPUT[1]);
+			data->temp_max[1] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX[1]);
+			data->temp_max_hyst[1] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX_HYST[1]);
+		} else {
+			data->in_input[4] = gl520_read_value(client,
+						GL520_REG_IN_INPUT[4]);
+			data->in_min[4] = gl520_read_value(client,
+						GL520_REG_IN_MIN[4]);
+			data->in_max[4] = gl520_read_value(client,
+						GL520_REG_IN_MAX[4]);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/*
  * Sysfs stuff
  */
 
@@ -191,8 +256,8 @@ static ssize_t get_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 gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	u8 r;
 	long v;
@@ -225,8 +290,8 @@ 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 gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	u8 r;
 	long v;
@@ -326,8 +391,8 @@ static ssize_t get_fan_off(struct device
 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 gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	u8 r;
 	unsigned long v;
@@ -365,8 +430,8 @@ 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 gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	u8 r;
 	unsigned long v;
@@ -414,8 +479,8 @@ static ssize_t set_fan_div(struct device
 static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 r;
 	unsigned long v;
 	int err;
@@ -482,8 +547,8 @@ static ssize_t get_temp_max_hyst(struct
 static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	long v;
 	int err;
@@ -502,8 +567,8 @@ static ssize_t set_temp_max(struct devic
 static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
 				 *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int n = to_sensor_dev_attr(attr)->index;
 	long v;
 	int err;
@@ -555,8 +620,8 @@ static ssize_t get_beep_mask(struct devi
 static ssize_t set_beep_enable(struct device *dev, struct device_attribute
 			       *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 r;
 	unsigned long v;
 	int err;
@@ -579,8 +644,8 @@ static ssize_t set_beep_enable(struct de
 static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long r;
 	int err;
 
@@ -633,8 +698,8 @@ static ssize_t get_beep(struct device *d
 static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct gl520_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	unsigned long bit;
 
@@ -772,52 +837,6 @@ static int gl520_detect(struct i2c_clien
 	return 0;
 }
 
-static int gl520_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id)
-{
-	struct gl520_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct gl520_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	/* Initialize the GL520SM chip */
-	gl520_init_client(client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &gl520_group);
-	if (err)
-		return err;
-
-	if (data->two_temps)
-		err = sysfs_create_group(&client->dev.kobj, &gl520_group_temp2);
-	else
-		err = sysfs_create_group(&client->dev.kobj, &gl520_group_in4);
-
-	if (err)
-		goto exit_remove_files;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &gl520_group);
-	sysfs_remove_group(&client->dev.kobj, &gl520_group_in4);
-	sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2);
-	return err;
-}
-
-
 /* Called when we have found a new GL520SM. */
 static void gl520_init_client(struct i2c_client *client)
 {
@@ -856,115 +875,53 @@ static void gl520_init_client(struct i2c
 	gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
 }
 
-static int gl520_remove(struct i2c_client *client)
+static int gl520_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
 {
-	struct gl520_data *data = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct gl520_data *data;
 
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &gl520_group);
-	sysfs_remove_group(&client->dev.kobj, &gl520_group_in4);
-	sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2);
+	data = devm_kzalloc(dev, sizeof(struct gl520_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	return 0;
-}
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+	data->client = client;
 
+	/* Initialize the GL520SM chip */
+	gl520_init_client(client);
 
-/*
- * Registers 0x07 to 0x0c are word-sized, others are byte-sized
- * GL520 uses a high-byte first convention
- */
-static int gl520_read_value(struct i2c_client *client, u8 reg)
-{
-	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_read_word_swapped(client, reg);
-	else
-		return i2c_smbus_read_byte_data(client, reg);
-}
+	/* sysfs hooks */
+	data->groups[0] = &gl520_group;
 
-static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_swapped(client, reg, value);
+	if (data->two_temps)
+		data->groups[1] = &gl520_group_temp2;
 	else
-		return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-
-static struct gl520_data *gl520_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct gl520_data *data = i2c_get_clientdata(client);
-	int val, i;
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
-
-		dev_dbg(&client->dev, "Starting gl520sm update\n");
-
-		data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
-		data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
-		data->vid = gl520_read_value(client,
-					     GL520_REG_VID_INPUT) & 0x1f;
-
-		for (i = 0; i < 4; i++) {
-			data->in_input[i] = gl520_read_value(client,
-							GL520_REG_IN_INPUT[i]);
-			val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]);
-			data->in_min[i] = val & 0xff;
-			data->in_max[i] = (val >> 8) & 0xff;
-		}
-
-		val = gl520_read_value(client, GL520_REG_FAN_INPUT);
-		data->fan_input[0] = (val >> 8) & 0xff;
-		data->fan_input[1] = val & 0xff;
-
-		val = gl520_read_value(client, GL520_REG_FAN_MIN);
-		data->fan_min[0] = (val >> 8) & 0xff;
-		data->fan_min[1] = val & 0xff;
-
-		data->temp_input[0] = gl520_read_value(client,
-						GL520_REG_TEMP_INPUT[0]);
-		data->temp_max[0] = gl520_read_value(client,
-						GL520_REG_TEMP_MAX[0]);
-		data->temp_max_hyst[0] = gl520_read_value(client,
-						GL520_REG_TEMP_MAX_HYST[0]);
-
-		val = gl520_read_value(client, GL520_REG_FAN_DIV);
-		data->fan_div[0] = (val >> 6) & 0x03;
-		data->fan_div[1] = (val >> 4) & 0x03;
-		data->fan_off = (val >> 2) & 0x01;
-
-		data->alarms &= data->alarm_mask;
-
-		val = gl520_read_value(client, GL520_REG_CONF);
-		data->beep_enable = !((val >> 2) & 1);
-
-		/* Temp1 and Vin4 are the same input */
-		if (data->two_temps) {
-			data->temp_input[1] = gl520_read_value(client,
-						GL520_REG_TEMP_INPUT[1]);
-			data->temp_max[1] = gl520_read_value(client,
-						GL520_REG_TEMP_MAX[1]);
-			data->temp_max_hyst[1] = gl520_read_value(client,
-						GL520_REG_TEMP_MAX_HYST[1]);
-		} else {
-			data->in_input[4] = gl520_read_value(client,
-						GL520_REG_IN_INPUT[4]);
-			data->in_min[4] = gl520_read_value(client,
-						GL520_REG_IN_MIN[4]);
-			data->in_max[4] = gl520_read_value(client,
-						GL520_REG_IN_MAX[4]);
-		}
+		data->groups[1] = &gl520_group_in4;
 
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id gl520_id[] = {
+	{ "gl520sm", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, gl520_id);
 
-	return data;
-}
+static struct i2c_driver gl520_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "gl520sm",
+	},
+	.probe		= gl520_probe,
+	.id_table	= gl520_id,
+	.detect		= gl520_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(gl520_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/gpio-fan.c linux-libre-3.17-rc7-gnu/drivers/hwmon/gpio-fan.c
--- linux-libre-3.16-gnu/drivers/hwmon/gpio-fan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/gpio-fan.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,7 +173,7 @@ static int get_fan_speed_index(struct gp
 	return -ENODEV;
 }
 
-static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
+static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm)
 {
 	struct gpio_fan_speed *speed = fan_data->speed;
 	int i;
@@ -537,9 +537,10 @@ static int gpio_fan_probe(struct platfor
 	}
 
 	/* Make this driver part of hwmon class. */
-	fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-						"gpio_fan", fan_data,
-						gpio_fan_groups);
+	fan_data->hwmon_dev =
+		devm_hwmon_device_register_with_groups(&pdev->dev,
+						       "gpio_fan", fan_data,
+						       gpio_fan_groups);
 	if (IS_ERR(fan_data->hwmon_dev))
 		return PTR_ERR(fan_data->hwmon_dev);
 
@@ -548,15 +549,6 @@ static int gpio_fan_probe(struct platfor
 	return 0;
 }
 
-static int gpio_fan_remove(struct platform_device *pdev)
-{
-	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(fan_data->hwmon_dev);
-
-	return 0;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int gpio_fan_suspend(struct device *dev)
 {
@@ -588,7 +580,6 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gp
 
 static struct platform_driver gpio_fan_driver = {
 	.probe		= gpio_fan_probe,
-	.remove		= gpio_fan_remove,
 	.driver	= {
 		.name	= "gpio-fan",
 		.pm	= GPIO_FAN_PM,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/hih6130.c linux-libre-3.17-rc7-gnu/drivers/hwmon/hih6130.c
--- linux-libre-3.16-gnu/drivers/hwmon/hih6130.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/hih6130.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@
  * @write_length: length for I2C measurement request
  */
 struct hih6130 {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex lock;
 	bool valid;
 	unsigned long last_update;
@@ -62,7 +62,6 @@ struct hih6130 {
  */
 static inline int hih6130_temp_ticks_to_millicelsius(int ticks)
 {
-
 	ticks = ticks >> 2;
 	/*
 	 * from data sheet section 5.0
@@ -78,7 +77,6 @@ static inline int hih6130_temp_ticks_to_
  */
 static inline int hih6130_rh_ticks_to_per_cent_mille(int ticks)
 {
-
 	ticks &= ~0xC000; /* clear status bits */
 	/*
 	 * from data sheet section 4.0
@@ -89,15 +87,16 @@ static inline int hih6130_rh_ticks_to_pe
 
 /**
  * hih6130_update_measurements() - get updated measurements from device
- * @client: I2C client device
+ * @dev: device
  *
  * Returns 0 on success, else negative errno.
  */
-static int hih6130_update_measurements(struct i2c_client *client)
+static int hih6130_update_measurements(struct device *dev)
 {
+	struct hih6130 *hih6130 = dev_get_drvdata(dev);
+	struct i2c_client *client = hih6130->client;
 	int ret = 0;
 	int t;
-	struct hih6130 *hih6130 = i2c_get_clientdata(client);
 	unsigned char tmp[4];
 	struct i2c_msg msgs[1] = {
 		{
@@ -176,9 +175,10 @@ static ssize_t hih6130_show_temperature(
 					struct device_attribute *attr,
 					char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct hih6130 *hih6130 = i2c_get_clientdata(client);
-	int ret = hih6130_update_measurements(client);
+	struct hih6130 *hih6130 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = hih6130_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", hih6130->temperature);
@@ -196,9 +196,10 @@ static ssize_t hih6130_show_temperature(
 static ssize_t hih6130_show_humidity(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct hih6130 *hih6130 = i2c_get_clientdata(client);
-	int ret = hih6130_update_measurements(client);
+	struct hih6130 *hih6130 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = hih6130_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", hih6130->humidity);
@@ -210,79 +211,40 @@ static SENSOR_DEVICE_ATTR(temp1_input, S
 static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, hih6130_show_humidity,
 	NULL, 0);
 
-static struct attribute *hih6130_attributes[] = {
+static struct attribute *hih6130_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_humidity1_input.dev_attr.attr,
 	NULL
 };
 
-static const struct attribute_group hih6130_attr_group = {
-	.attrs = hih6130_attributes,
-};
+ATTRIBUTE_GROUPS(hih6130);
 
-/**
- * hih6130_probe() - probe device
- * @client: I2C client device
- * @id: device ID
- *
- * Called by the I2C core when an entry in the ID table matches a
- * device's name.
- * Returns 0 on success.
- */
 static int hih6130_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct hih6130 *hih6130;
-	int err;
+	struct device *hwmon_dev;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		dev_err(&client->dev, "adapter does not support true I2C\n");
 		return -ENODEV;
 	}
 
-	hih6130 = devm_kzalloc(&client->dev, sizeof(*hih6130), GFP_KERNEL);
+	hih6130 = devm_kzalloc(dev, sizeof(*hih6130), GFP_KERNEL);
 	if (!hih6130)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, hih6130);
-
+	hih6130->client = client;
 	mutex_init(&hih6130->lock);
 
-	err = sysfs_create_group(&client->dev.kobj, &hih6130_attr_group);
-	if (err) {
-		dev_dbg(&client->dev, "could not create sysfs files\n");
-		return err;
-	}
-
-	hih6130->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(hih6130->hwmon_dev)) {
-		dev_dbg(&client->dev, "unable to register hwmon device\n");
-		err = PTR_ERR(hih6130->hwmon_dev);
-		goto fail_remove_sysfs;
-	}
-
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
 		hih6130->write_length = 1;
 
-	return 0;
-
-fail_remove_sysfs:
-	sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group);
-	return err;
-}
-
-/**
- * hih6130_remove() - remove device
- * @client: I2C client device
- */
-static int hih6130_remove(struct i2c_client *client)
-{
-	struct hih6130 *hih6130 = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(hih6130->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   hih6130,
+							   hih6130_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Device ID table */
@@ -295,7 +257,6 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id);
 static struct i2c_driver hih6130_driver = {
 	.driver.name = "hih6130",
 	.probe       = hih6130_probe,
-	.remove      = hih6130_remove,
 	.id_table    = hih6130_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/htu21.c linux-libre-3.17-rc7-gnu/drivers/hwmon/htu21.c
--- linux-libre-3.16-gnu/drivers/hwmon/htu21.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/htu21.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@
 #define HTU21_RH_MEASUREMENT_HM	0xE5
 
 struct htu21 {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex lock;
 	bool valid;
 	unsigned long last_update;
@@ -59,10 +59,11 @@ static inline int htu21_rh_ticks_to_per_
 	return ((15625 * ticks) >> 13) - 6000;
 }
 
-static int htu21_update_measurements(struct i2c_client *client)
+static int htu21_update_measurements(struct device *dev)
 {
+	struct htu21 *htu21 = dev_get_drvdata(dev);
+	struct i2c_client *client = htu21->client;
 	int ret = 0;
-	struct htu21 *htu21 = i2c_get_clientdata(client);
 
 	mutex_lock(&htu21->lock);
 
@@ -90,9 +91,10 @@ out:
 static ssize_t htu21_show_temperature(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct htu21 *htu21 = i2c_get_clientdata(client);
-	int ret = htu21_update_measurements(client);
+	struct htu21 *htu21 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = htu21_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", htu21->temperature);
@@ -101,9 +103,10 @@ static ssize_t htu21_show_temperature(st
 static ssize_t htu21_show_humidity(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct htu21 *htu21 = i2c_get_clientdata(client);
-	int ret = htu21_update_measurements(client);
+	struct htu21 *htu21 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = htu21_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", htu21->humidity);
@@ -114,21 +117,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S
 static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO,
 			  htu21_show_humidity, NULL, 0);
 
-static struct attribute *htu21_attributes[] = {
+static struct attribute *htu21_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_humidity1_input.dev_attr.attr,
 	NULL
 };
 
-static const struct attribute_group htu21_group = {
-	.attrs = htu21_attributes,
-};
+ATTRIBUTE_GROUPS(htu21);
 
 static int htu21_probe(struct i2c_client *client,
 		       const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct htu21 *htu21;
-	int err;
+	struct device *hwmon_dev;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_READ_WORD_DATA)) {
@@ -137,43 +139,17 @@ static int htu21_probe(struct i2c_client
 		return -ENODEV;
 	}
 
-	htu21 = devm_kzalloc(&client->dev, sizeof(*htu21), GFP_KERNEL);
+	htu21 = devm_kzalloc(dev, sizeof(*htu21), GFP_KERNEL);
 	if (!htu21)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, htu21);
-
+	htu21->client = client;
 	mutex_init(&htu21->lock);
 
-	err = sysfs_create_group(&client->dev.kobj, &htu21_group);
-	if (err) {
-		dev_dbg(&client->dev, "could not create sysfs files\n");
-		return err;
-	}
-	htu21->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(htu21->hwmon_dev)) {
-		dev_dbg(&client->dev, "unable to register hwmon device\n");
-		err = PTR_ERR(htu21->hwmon_dev);
-		goto error;
-	}
-
-	dev_info(&client->dev, "initialized\n");
-
-	return 0;
-
-error:
-	sysfs_remove_group(&client->dev.kobj, &htu21_group);
-	return err;
-}
-
-static int htu21_remove(struct i2c_client *client)
-{
-	struct htu21 *htu21 = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(htu21->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &htu21_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   htu21,
+							   htu21_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id htu21_id[] = {
@@ -188,7 +164,6 @@ static struct i2c_driver htu21_driver =
 		.name	= "htu21",
 	},
 	.probe       = htu21_probe,
-	.remove      = htu21_remove,
 	.id_table    = htu21_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ibmaem.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ibmaem.c
--- linux-libre-3.16-gnu/drivers/hwmon/ibmaem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ibmaem.c	2014-09-28 17:29:07.000000000 -0400
@@ -842,11 +842,10 @@ static ssize_t aem_show_power(struct dev
 	struct aem_data *data = dev_get_drvdata(dev);
 	u64 before, after, delta, time;
 	signed long leftover;
-	struct timespec b, a;
 
 	mutex_lock(&data->lock);
 	update_aem_energy_one(data, attr->index);
-	getnstimeofday(&b);
+	time = ktime_get_ns();
 	before = data->energy[attr->index];
 
 	leftover = schedule_timeout_interruptible(
@@ -858,11 +857,10 @@ static ssize_t aem_show_power(struct dev
 	}
 
 	update_aem_energy_one(data, attr->index);
-	getnstimeofday(&a);
+	time = ktime_get_ns() - time;
 	after = data->energy[attr->index];
 	mutex_unlock(&data->lock);
 
-	time = timespec_to_ns(&a) - timespec_to_ns(&b);
 	delta = (after - before) * UJ_PER_MJ;
 
 	return sprintf(buf, "%llu\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ibmpowernv.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ibmpowernv.c
--- linux-libre-3.16-gnu/drivers/hwmon/ibmpowernv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ibmpowernv.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,363 @@
+/*
+ * IBM PowerNV platform sensors for temperature/fan/voltage/power
+ * Copyright (C) 2014 IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+#define DRVNAME		"ibmpowernv"
+#define pr_fmt(fmt)	DRVNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <linux/platform_device.h>
+#include <asm/opal.h>
+#include <linux/err.h>
+
+#define MAX_ATTR_LEN	32
+
+/* Sensor suffix name from DT */
+#define DT_FAULT_ATTR_SUFFIX		"faulted"
+#define DT_DATA_ATTR_SUFFIX		"data"
+#define DT_THRESHOLD_ATTR_SUFFIX	"thrs"
+
+/*
+ * Enumerates all the types of sensors in the POWERNV platform and does index
+ * into 'struct sensor_group'
+ */
+enum sensors {
+	FAN,
+	AMBIENT_TEMP,
+	POWER_SUPPLY,
+	POWER_INPUT,
+	MAX_SENSOR_TYPE,
+};
+
+static struct sensor_group {
+	const char *name;
+	const char *compatible;
+	struct attribute_group group;
+	u32 attr_count;
+} sensor_groups[] = {
+	{"fan", "ibm,opal-sensor-cooling-fan"},
+	{"temp", "ibm,opal-sensor-amb-temp"},
+	{"in", "ibm,opal-sensor-power-supply"},
+	{"power", "ibm,opal-sensor-power"}
+};
+
+struct sensor_data {
+	u32 id; /* An opaque id of the firmware for each sensor */
+	enum sensors type;
+	char name[MAX_ATTR_LEN];
+	struct device_attribute dev_attr;
+};
+
+struct platform_data {
+	const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];
+	u32 sensors_count; /* Total count of sensors from each group */
+};
+
+/* Platform device representing all the ibmpowernv sensors */
+static struct platform_device *pdevice;
+
+static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
+			   char *buf)
+{
+	struct sensor_data *sdata = container_of(devattr, struct sensor_data,
+						 dev_attr);
+	ssize_t ret;
+	u32 x;
+
+	ret = opal_get_sensor_data(sdata->id, &x);
+	if (ret)
+		return ret;
+
+	/* Convert temperature to milli-degrees */
+	if (sdata->type == AMBIENT_TEMP)
+		x *= 1000;
+	/* Convert power to micro-watts */
+	else if (sdata->type == POWER_INPUT)
+		x *= 1000000;
+
+	return sprintf(buf, "%u\n", x);
+}
+
+static int __init get_sensor_index_attr(const char *name, u32 *index,
+					char *attr)
+{
+	char *hash_pos = strchr(name, '#');
+	char buf[8] = { 0 };
+	char *dash_pos;
+	u32 copy_len;
+	int err;
+
+	if (!hash_pos)
+		return -EINVAL;
+
+	dash_pos = strchr(hash_pos, '-');
+	if (!dash_pos)
+		return -EINVAL;
+
+	copy_len = dash_pos - hash_pos - 1;
+	if (copy_len >= sizeof(buf))
+		return -EINVAL;
+
+	strncpy(buf, hash_pos + 1, copy_len);
+
+	err = kstrtou32(buf, 10, index);
+	if (err)
+		return err;
+
+	strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
+
+	return 0;
+}
+
+/*
+ * This function translates the DT node name into the 'hwmon' attribute name.
+ * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
+ * which need to be mapped as fan2_input, temp1_max respectively before
+ * populating them inside hwmon device class.
+ */
+static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
+					 const char *node_name,
+					 char *hwmon_attr_name)
+{
+	char attr_suffix[MAX_ATTR_LEN];
+	char *attr_name;
+	u32 index;
+	int err;
+
+	err = get_sensor_index_attr(node_name, &index, attr_suffix);
+	if (err) {
+		dev_err(dev, "Sensor device node name '%s' is invalid\n",
+			node_name);
+		return err;
+	}
+
+	if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {
+		attr_name = "fault";
+	} else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {
+		attr_name = "input";
+	} else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {
+		if (type == AMBIENT_TEMP)
+			attr_name = "max";
+		else if (type == FAN)
+			attr_name = "min";
+		else
+			return -ENOENT;
+	} else {
+		return -ENOENT;
+	}
+
+	snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s",
+		 sensor_groups[type].name, index, attr_name);
+	return 0;
+}
+
+static int __init populate_attr_groups(struct platform_device *pdev)
+{
+	struct platform_data *pdata = platform_get_drvdata(pdev);
+	const struct attribute_group **pgroups = pdata->attr_groups;
+	struct device_node *opal, *np;
+	enum sensors type;
+
+	opal = of_find_node_by_path("/ibm,opal/sensors");
+	if (!opal) {
+		dev_err(&pdev->dev, "Opal node 'sensors' not found\n");
+		return -ENODEV;
+	}
+
+	for_each_child_of_node(opal, np) {
+		if (np->name == NULL)
+			continue;
+
+		for (type = 0; type < MAX_SENSOR_TYPE; type++)
+			if (of_device_is_compatible(np,
+					sensor_groups[type].compatible)) {
+				sensor_groups[type].attr_count++;
+				break;
+			}
+	}
+
+	of_node_put(opal);
+
+	for (type = 0; type < MAX_SENSOR_TYPE; type++) {
+		sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,
+					sizeof(struct attribute *) *
+					(sensor_groups[type].attr_count + 1),
+					GFP_KERNEL);
+		if (!sensor_groups[type].group.attrs)
+			return -ENOMEM;
+
+		pgroups[type] = &sensor_groups[type].group;
+		pdata->sensors_count += sensor_groups[type].attr_count;
+		sensor_groups[type].attr_count = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Iterate through the device tree for each child of 'sensors' node, create
+ * a sysfs attribute file, the file is named by translating the DT node name
+ * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
+ * etc..
+ */
+static int __init create_device_attrs(struct platform_device *pdev)
+{
+	struct platform_data *pdata = platform_get_drvdata(pdev);
+	const struct attribute_group **pgroups = pdata->attr_groups;
+	struct device_node *opal, *np;
+	struct sensor_data *sdata;
+	u32 sensor_id;
+	enum sensors type;
+	u32 count = 0;
+	int err = 0;
+
+	opal = of_find_node_by_path("/ibm,opal/sensors");
+	sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),
+			     GFP_KERNEL);
+	if (!sdata) {
+		err = -ENOMEM;
+		goto exit_put_node;
+	}
+
+	for_each_child_of_node(opal, np) {
+		if (np->name == NULL)
+			continue;
+
+		for (type = 0; type < MAX_SENSOR_TYPE; type++)
+			if (of_device_is_compatible(np,
+					sensor_groups[type].compatible))
+				break;
+
+		if (type == MAX_SENSOR_TYPE)
+			continue;
+
+		if (of_property_read_u32(np, "sensor-id", &sensor_id)) {
+			dev_info(&pdev->dev,
+				 "'sensor-id' missing in the node '%s'\n",
+				 np->name);
+			continue;
+		}
+
+		sdata[count].id = sensor_id;
+		sdata[count].type = type;
+		err = create_hwmon_attr_name(&pdev->dev, type, np->name,
+					     sdata[count].name);
+		if (err)
+			goto exit_put_node;
+
+		sysfs_attr_init(&sdata[count].dev_attr.attr);
+		sdata[count].dev_attr.attr.name = sdata[count].name;
+		sdata[count].dev_attr.attr.mode = S_IRUGO;
+		sdata[count].dev_attr.show = show_sensor;
+
+		pgroups[type]->attrs[sensor_groups[type].attr_count++] =
+				&sdata[count++].dev_attr.attr;
+	}
+
+exit_put_node:
+	of_node_put(opal);
+	return err;
+}
+
+static int __init ibmpowernv_probe(struct platform_device *pdev)
+{
+	struct platform_data *pdata;
+	struct device *hwmon_dev;
+	int err;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, pdata);
+	pdata->sensors_count = 0;
+	err = populate_attr_groups(pdev);
+	if (err)
+		return err;
+
+	/* Create sysfs attribute data for each sensor found in the DT */
+	err = create_device_attrs(pdev);
+	if (err)
+		return err;
+
+	/* Finally, register with hwmon */
+	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
+							   pdata,
+							   pdata->attr_groups);
+
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct platform_driver ibmpowernv_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRVNAME,
+	},
+};
+
+static int __init ibmpowernv_init(void)
+{
+	int err;
+
+	pdevice = platform_device_alloc(DRVNAME, 0);
+	if (!pdevice) {
+		pr_err("Device allocation failed\n");
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	err = platform_device_add(pdevice);
+	if (err) {
+		pr_err("Device addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
+	if (err) {
+		pr_err("Platfrom driver probe failed\n");
+		goto exit_device_del;
+	}
+
+	return 0;
+
+exit_device_del:
+	platform_device_del(pdevice);
+exit_device_put:
+	platform_device_put(pdevice);
+exit:
+	return err;
+}
+
+static void __exit ibmpowernv_exit(void)
+{
+	platform_driver_unregister(&ibmpowernv_driver);
+	platform_device_unregister(pdevice);
+}
+
+MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM POWERNV platform sensors");
+MODULE_LICENSE("GPL");
+
+module_init(ibmpowernv_init);
+module_exit(ibmpowernv_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/Kconfig linux-libre-3.17-rc7-gnu/drivers/hwmon/Kconfig
--- linux-libre-3.16-gnu/drivers/hwmon/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -554,6 +554,17 @@ config SENSORS_IBMPEX
 	  This driver can also be built as a module.  If so, the module
 	  will be called ibmpex.
 
+config SENSORS_IBMPOWERNV
+	tristate "IBM POWERNV platform sensors"
+	depends on PPC_POWERNV
+	default y
+	help
+	  If you say yes here you get support for the temperature/fan/power
+	  sensors on your PowerNV platform.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called ibmpowernv.
+
 config SENSORS_IIO_HWMON
 	tristate "Hwmon driver that uses channels specified via iio maps"
 	depends on IIO
@@ -608,6 +619,18 @@ config SENSORS_JC42
 	  This driver can also be built as a module.  If so, the module
 	  will be called jc42.
 
+config SENSORS_POWR1220
+	tristate "Lattice POWR1220 Power Monitoring"
+	depends on I2C
+	default n
+	help
+	  If you say yes here you get access to the hardware monitoring
+	  functions of the Lattice POWR1220 isp Power Supply Monitoring,
+	  Sequencing and Margining Controller.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called powr1220.
+
 config SENSORS_LINEAGE
 	tristate "Lineage Compact Power Line Power Entry Module"
 	depends on I2C
@@ -882,8 +905,8 @@ config SENSORS_LM75
 		- NXP's LM75A
 		- ST Microelectronics STDS75
 		- TelCom (now Microchip) TCN75
-		- Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
-		  TMP275
+		- Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75,
+		  TMP175, TMP275
 
 	  This driver supports driver model based binding through board
 	  specific I2C device tables.
@@ -1061,7 +1084,7 @@ config SENSORS_NTC_THERMISTOR
 
 	  Currently, this driver supports
 	  NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333
-	  from Murata.
+	  from Murata and B57330V2103 from EPCOS.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called ntc-thermistor.
@@ -1082,8 +1105,8 @@ config SENSORS_NCT6775
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware monitoring
-	  functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
-	  and compatible Super-I/O chips. This driver replaces the
+	  functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
+	  NCT6791D and compatible Super-I/O chips. This driver replaces the
 	  w83627ehf driver for NCT6775F and NCT6776F.
 
 	  This driver can also be built as a module.  If so, the module
@@ -1105,6 +1128,17 @@ config SENSORS_PCF8591
 
 source drivers/hwmon/pmbus/Kconfig
 
+config SENSORS_PWM_FAN
+	tristate "PWM fan"
+	depends on (PWM && OF) || COMPILE_TEST
+	help
+	  If you say yes here you get support for fans connected to PWM lines.
+	  The driver uses the generic PWM interface, thus it will work on a
+	  variety of SoCs.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pwm-fan.
+
 config SENSORS_SHT15
 	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
 	depends on GPIOLIB
@@ -1393,6 +1427,17 @@ config SENSORS_TMP102
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp102.
 
+config SENSORS_TMP103
+	tristate "Texas Instruments TMP103"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  If you say yes here you get support for Texas Instruments TMP103
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tmp103.
+
 config SENSORS_TMP401
 	tristate "Texas Instruments TMP401 and compatibles"
 	depends on I2C
@@ -1408,7 +1453,7 @@ config SENSORS_TMP421
 	depends on I2C
 	help
 	  If you say yes here you get support for Texas Instruments TMP421,
-	  TMP422 and TMP423 temperature sensor chips.
+	  TMP422, TMP423, TMP441, and TMP442 temperature sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp421.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lineage-pem.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lineage-pem.c
--- linux-libre-3.16-gnu/drivers/hwmon/lineage-pem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lineage-pem.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,8 @@
 #define FAN_SPEED_LEN		5
 
 struct pem_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[4];
 
 	struct mutex update_lock;
 	bool valid;
@@ -160,8 +161,8 @@ abort:
 
 static struct pem_data *pem_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pem_data *data = i2c_get_clientdata(client);
+	struct pem_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct pem_data *ret = data;
 
 	mutex_lock(&data->update_lock);
@@ -444,18 +445,20 @@ static int pem_probe(struct i2c_client *
 		     const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct pem_data *data;
-	int ret;
+	int ret, idx = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA
 				     | I2C_FUNC_SMBUS_WRITE_BYTE))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/*
@@ -471,14 +474,12 @@ static int pem_probe(struct i2c_client *
 	if (ret < 0)
 		return ret;
 
-	dev_info(&client->dev, "Firmware revision %d.%d.%d\n",
+	dev_info(dev, "Firmware revision %d.%d.%d\n",
 		 data->firmware_rev[0], data->firmware_rev[1],
 		 data->firmware_rev[2]);
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &pem_group);
-	if (ret)
-		return ret;
+	/* sysfs hooks */
+	data->groups[idx++] = &pem_group;
 
 	/*
 	 * Check if input readings are supported.
@@ -501,12 +502,9 @@ static int pem_probe(struct i2c_client *
 			    data->input_string[2] || data->input_string[3]))
 			data->input_length = sizeof(data->input_string);
 	}
-	ret = 0;
-	if (data->input_length) {
-		ret = sysfs_create_group(&client->dev.kobj, &pem_input_group);
-		if (ret)
-			goto out_remove_groups;
-	}
+
+	if (data->input_length)
+		data->groups[idx++] = &pem_input_group;
 
 	/*
 	 * Check if fan speed readings are supported.
@@ -520,37 +518,12 @@ static int pem_probe(struct i2c_client *
 	if (!ret && (data->fan_speed[0] || data->fan_speed[1] ||
 		     data->fan_speed[2] || data->fan_speed[3])) {
 		data->fans_supported = true;
-		ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group);
-		if (ret)
-			goto out_remove_groups;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto out_remove_groups;
+		data->groups[idx++] = &pem_fan_group;
 	}
 
-	return 0;
-
-out_remove_groups:
-	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
-	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
-	sysfs_remove_group(&client->dev.kobj, &pem_group);
-	return ret;
-}
-
-static int pem_remove(struct i2c_client *client)
-{
-	struct pem_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-
-	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
-	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
-	sysfs_remove_group(&client->dev.kobj, &pem_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id pem_id[] = {
@@ -564,7 +537,6 @@ static struct i2c_driver pem_driver = {
 		   .name = "lineage_pem",
 		   },
 	.probe = pem_probe,
-	.remove = pem_remove,
 	.id_table = pem_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm63.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm63.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm63.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm63.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,24 +126,17 @@ static const unsigned short normal_i2c[]
 #define FAN_TO_REG(val)		((val) <= 82 ? 0xFFFC : \
 				 (5400000 / (val)) & 0xFFFC)
 #define TEMP8_FROM_REG(reg)	((reg) * 1000)
-#define TEMP8_TO_REG(val)	((val) <= -128000 ? -128 : \
-				 (val) >= 127000 ? 127 : \
-				 (val) < 0 ? ((val) - 500) / 1000 : \
-				 ((val) + 500) / 1000)
-#define TEMP8U_TO_REG(val)	((val) <= 0 ? 0 : \
-				 (val) >= 255000 ? 255 : \
-				 ((val) + 500) / 1000)
+#define TEMP8_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+							    127000), 1000)
+#define TEMP8U_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, \
+							    255000), 1000)
 #define TEMP11_FROM_REG(reg)	((reg) / 32 * 125)
-#define TEMP11_TO_REG(val)	((val) <= -128000 ? 0x8000 : \
-				 (val) >= 127875 ? 0x7FE0 : \
-				 (val) < 0 ? ((val) - 62) / 125 * 32 : \
-				 ((val) + 62) / 125 * 32)
-#define TEMP11U_TO_REG(val)	((val) <= 0 ? 0 : \
-				 (val) >= 255875 ? 0xFFE0 : \
-				 ((val) + 62) / 125 * 32)
-#define HYST_TO_REG(val)	((val) <= 0 ? 0 : \
-				 (val) >= 127000 ? 127 : \
-				 ((val) + 500) / 1000)
+#define TEMP11_TO_REG(val)	(DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+							     127875), 125) * 32)
+#define TEMP11U_TO_REG(val)	(DIV_ROUND_CLOSEST(clamp_val((val), 0, \
+							     255875), 125) * 32)
+#define HYST_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
+						  1000)
 
 #define UPDATE_INTERVAL(max, rate) \
 			((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm75.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm75.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm75.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm75.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,6 +52,7 @@ enum lm75_type {		/* keep sorted in alph
 	tmp100,
 	tmp101,
 	tmp105,
+	tmp112,
 	tmp175,
 	tmp275,
 	tmp75,
@@ -255,6 +256,12 @@ lm75_probe(struct i2c_client *client, co
 		data->sample_time = HZ;
 		clr_mask |= 1 << 7;		/* not one-shot mode */
 		break;
+	case tmp112:
+		set_mask |= 3 << 5;		/* 12-bit mode */
+		clr_mask |= 1 << 7;		/* not one-shot mode */
+		data->resolution = 12;
+		data->sample_time = HZ / 4;
+		break;
 	case tmp105:
 	case tmp175:
 	case tmp275:
@@ -323,6 +330,7 @@ static const struct i2c_device_id lm75_i
 	{ "tmp100", tmp100, },
 	{ "tmp101", tmp101, },
 	{ "tmp105", tmp105, },
+	{ "tmp112", tmp112, },
 	{ "tmp175", tmp175, },
 	{ "tmp275", tmp275, },
 	{ "tmp75", tmp75, },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm77.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm77.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm77.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm77.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,8 +80,7 @@ struct lm77_data {
  */
 static inline s16 LM77_TEMP_TO_REG(int temp)
 {
-	int ntemp = clamp_val(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
-	return (ntemp / 500) * 8;
+	return (temp / 500) * 8;
 }
 
 static inline int LM77_TEMP_FROM_REG(s16 reg)
@@ -175,6 +174,7 @@ static ssize_t set_temp(struct device *d
 	if (err)
 		return err;
 
+	val = clamp_val(val, LM77_TEMP_MIN, LM77_TEMP_MAX);
 	mutex_lock(&data->update_lock);
 	data->temp[nr] = val;
 	lm77_write_value(client, temp_regs[nr], LM77_TEMP_TO_REG(val));
@@ -192,15 +192,16 @@ static ssize_t set_temp_hyst(struct devi
 {
 	struct lm77_data *data = dev_get_drvdata(dev);
 	struct i2c_client *client = data->client;
-	unsigned long val;
+	long val;
 	int err;
 
-	err = kstrtoul(buf, 10, &val);
+	err = kstrtol(buf, 10, &val);
 	if (err)
 		return err;
 
 	mutex_lock(&data->update_lock);
-	data->temp[t_hyst] = data->temp[t_crit] - val;
+	val = clamp_val(data->temp[t_crit] - val, LM77_TEMP_MIN, LM77_TEMP_MAX);
+	data->temp[t_hyst] = val;
 	lm77_write_value(client, LM77_REG_TEMP_HYST,
 			 LM77_TEMP_TO_REG(data->temp[t_hyst]));
 	mutex_unlock(&data->update_lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm78.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm78.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm78.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm78.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, i
  * TEMP: mC (-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)
 {
 	int nval = clamp_val(val, -128000, 127000) ;
 	return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000;
@@ -123,7 +123,6 @@ static inline int TEMP_FROM_REG(s8 val)
 
 struct lm78_data {
 	struct i2c_client *client;
-	struct device *hwmon_dev;
 	struct mutex lock;
 	enum chips type;
 
@@ -468,7 +467,7 @@ static SENSOR_DEVICE_ATTR(fan2_alarm, S_
 static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
 static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
 
-static struct attribute *lm78_attributes[] = {
+static struct attribute *lm78_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -519,9 +518,7 @@ static struct attribute *lm78_attributes
 	NULL
 };
 
-static const struct attribute_group lm78_group = {
-	.attrs = lm78_attributes,
-};
+ATTRIBUTE_GROUPS(lm78);
 
 /*
  * ISA related code
@@ -533,19 +530,6 @@ static struct platform_device *pdev;
 
 static unsigned short isa_address = 0x290;
 
-/*
- * I2C devices get this name attribute automatically, but for ISA devices
- * we must create it by ourselves.
- */
-static ssize_t show_name(struct device *dev, struct device_attribute
-			 *devattr, char *buf)
-{
-	struct lm78_data *data = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%s\n", data->name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
 static struct lm78_data *lm78_data_if_isa(void)
 {
 	return pdev ? platform_get_drvdata(pdev) : NULL;
@@ -661,46 +645,23 @@ static int lm78_i2c_detect(struct i2c_cl
 static int lm78_i2c_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct lm78_data *data;
-	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm78_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
 	data->client = client;
 	data->type = id->driver_data;
 
 	/* Initialize the LM78 chip */
 	lm78_init_device(data);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &lm78_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
-	}
-
-	return 0;
-
-error:
-	sysfs_remove_group(&client->dev.kobj, &lm78_group);
-	return err;
-}
-
-static int lm78_i2c_remove(struct i2c_client *client)
-{
-	struct lm78_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm78_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, lm78_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id lm78_i2c_id[] = {
@@ -716,7 +677,6 @@ static struct i2c_driver lm78_driver = {
 		.name	= "lm78",
 	},
 	.probe		= lm78_i2c_probe,
-	.remove		= lm78_i2c_remove,
 	.id_table	= lm78_i2c_id,
 	.detect		= lm78_i2c_detect,
 	.address_list	= normal_i2c,
@@ -839,17 +799,18 @@ static struct lm78_data *lm78_update_dev
 #ifdef CONFIG_ISA
 static int lm78_isa_probe(struct platform_device *pdev)
 {
-	int err;
+	struct device *dev = &pdev->dev;
+	struct device *hwmon_dev;
 	struct lm78_data *data;
 	struct resource *res;
 
 	/* Reserve the ISA region */
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!devm_request_region(&pdev->dev, res->start + LM78_ADDR_REG_OFFSET,
+	if (!devm_request_region(dev, res->start + LM78_ADDR_REG_OFFSET,
 				 2, "lm78"))
 		return -EBUSY;
 
-	data = devm_kzalloc(&pdev->dev, sizeof(struct lm78_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -868,37 +829,9 @@ static int lm78_isa_probe(struct platfor
 	/* Initialize the LM78 chip */
 	lm78_init_device(data);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&pdev->dev.kobj, &lm78_group);
-	if (err)
-		goto exit_remove_files;
-	err = device_create_file(&pdev->dev, &dev_attr_name);
-	if (err)
-		goto exit_remove_files;
-
-	data->hwmon_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
- exit_remove_files:
-	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-	return err;
-}
-
-static int lm78_isa_remove(struct platform_device *pdev)
-{
-	struct lm78_data *data = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
+							   data, lm78_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static struct platform_driver lm78_isa_driver = {
@@ -907,7 +840,6 @@ static struct platform_driver lm78_isa_d
 		.name	= "lm78",
 	},
 	.probe		= lm78_isa_probe,
-	.remove		= lm78_isa_remove,
 };
 
 /* return 1 if a supported chip is found, 0 otherwise */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm85.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm85.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm85.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm85.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,7 +121,6 @@ enum chips {
 #define EMC6D102_REG_EXTEND_ADC3	0x87
 #define EMC6D102_REG_EXTEND_ADC4	0x88
 
-
 /*
  * Conversions. Rounding and limit checking is only done on the TO_REG
  * variants. Note that you should be a bit careful with which arguments
@@ -155,7 +154,7 @@ static inline u16 FAN_TO_REG(unsigned lo
 
 /* Temperature is reported in .001 degC increments */
 #define TEMP_TO_REG(val)	\
-		clamp_val(SCALE(val, 1000, 1), -127, 127)
+		DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000)
 #define TEMPEXT_FROM_REG(val, ext)	\
 		SCALE(((val) << 4) + (ext), 16, 1000)
 #define TEMP_FROM_REG(val)	((val) * 1000)
@@ -189,7 +188,7 @@ static const int lm85_range_map[] = {
 	13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000
 };
 
-static int RANGE_TO_REG(int range)
+static int RANGE_TO_REG(long range)
 {
 	int i;
 
@@ -211,7 +210,7 @@ static const int adm1027_freq_map[8] = {
 	11, 15, 22, 29, 35, 44, 59, 88
 };
 
-static int FREQ_TO_REG(const int *map, int freq)
+static int FREQ_TO_REG(const int *map, unsigned long freq)
 {
 	int i;
 
@@ -303,7 +302,8 @@ struct lm85_autofan {
  * The structure is dynamically allocated.
  */
 struct lm85_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[6];
 	const int *freq_map;
 	enum chips type;
 
@@ -334,44 +334,235 @@ struct lm85_data {
 	struct lm85_zone zone[3];
 };
 
-static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info);
-static int lm85_probe(struct i2c_client *client,
-		      const struct i2c_device_id *id);
-static int lm85_remove(struct i2c_client *client);
+static int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+	int res;
 
-static int lm85_read_value(struct i2c_client *client, u8 reg);
-static void lm85_write_value(struct i2c_client *client, u8 reg, int value);
-static struct lm85_data *lm85_update_device(struct device *dev);
+	/* What size location is it? */
+	switch (reg) {
+	case LM85_REG_FAN(0):  /* Read WORD data */
+	case LM85_REG_FAN(1):
+	case LM85_REG_FAN(2):
+	case LM85_REG_FAN(3):
+	case LM85_REG_FAN_MIN(0):
+	case LM85_REG_FAN_MIN(1):
+	case LM85_REG_FAN_MIN(2):
+	case LM85_REG_FAN_MIN(3):
+	case LM85_REG_ALARM1:	/* Read both bytes at once */
+		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
+		res |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
+		break;
+	default:	/* Read BYTE data */
+		res = i2c_smbus_read_byte_data(client, reg);
+		break;
+	}
 
+	return res;
+}
 
-static const struct i2c_device_id lm85_id[] = {
-	{ "adm1027", adm1027 },
-	{ "adt7463", adt7463 },
-	{ "adt7468", adt7468 },
-	{ "lm85", lm85 },
-	{ "lm85b", lm85 },
-	{ "lm85c", lm85 },
-	{ "emc6d100", emc6d100 },
-	{ "emc6d101", emc6d100 },
-	{ "emc6d102", emc6d102 },
-	{ "emc6d103", emc6d103 },
-	{ "emc6d103s", emc6d103s },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, lm85_id);
+static void lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+	switch (reg) {
+	case LM85_REG_FAN(0):  /* Write WORD data */
+	case LM85_REG_FAN(1):
+	case LM85_REG_FAN(2):
+	case LM85_REG_FAN(3):
+	case LM85_REG_FAN_MIN(0):
+	case LM85_REG_FAN_MIN(1):
+	case LM85_REG_FAN_MIN(2):
+	case LM85_REG_FAN_MIN(3):
+	/* NOTE: ALARM is read only, so not included here */
+		i2c_smbus_write_byte_data(client, reg, value & 0xff);
+		i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
+		break;
+	default:	/* Write BYTE data */
+		i2c_smbus_write_byte_data(client, reg, value);
+		break;
+	}
+}
 
-static struct i2c_driver lm85_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name   = "lm85",
-	},
-	.probe		= lm85_probe,
-	.remove		= lm85_remove,
-	.id_table	= lm85_id,
-	.detect		= lm85_detect,
-	.address_list	= normal_i2c,
-};
+static struct lm85_data *lm85_update_device(struct device *dev)
+{
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (!data->valid ||
+	     time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) {
+		/* Things that change quickly */
+		dev_dbg(&client->dev, "Reading sensor values\n");
+
+		/*
+		 * Have to read extended bits first to "freeze" the
+		 * more significant bits that are read later.
+		 * There are 2 additional resolution bits per channel and we
+		 * have room for 4, so we shift them to the left.
+		 */
+		if (data->type == adm1027 || data->type == adt7463 ||
+		    data->type == adt7468) {
+			int ext1 = lm85_read_value(client,
+						   ADM1027_REG_EXTEND_ADC1);
+			int ext2 =  lm85_read_value(client,
+						    ADM1027_REG_EXTEND_ADC2);
+			int val = (ext1 << 8) + ext2;
+
+			for (i = 0; i <= 4; i++)
+				data->in_ext[i] =
+					((val >> (i * 2)) & 0x03) << 2;
+
+			for (i = 0; i <= 2; i++)
+				data->temp_ext[i] =
+					(val >> ((i + 4) * 2)) & 0x0c;
+		}
+
+		data->vid = lm85_read_value(client, LM85_REG_VID);
+
+		for (i = 0; i <= 3; ++i) {
+			data->in[i] =
+			    lm85_read_value(client, LM85_REG_IN(i));
+			data->fan[i] =
+			    lm85_read_value(client, LM85_REG_FAN(i));
+		}
+
+		if (!data->has_vid5)
+			data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
+
+		if (data->type == adt7468)
+			data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
+
+		for (i = 0; i <= 2; ++i) {
+			data->temp[i] =
+			    lm85_read_value(client, LM85_REG_TEMP(i));
+			data->pwm[i] =
+			    lm85_read_value(client, LM85_REG_PWM(i));
+
+			if (IS_ADT7468_OFF64(data))
+				data->temp[i] -= 64;
+		}
+
+		data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+		if (data->type == emc6d100) {
+			/* Three more voltage sensors */
+			for (i = 5; i <= 7; ++i) {
+				data->in[i] = lm85_read_value(client,
+							EMC6D100_REG_IN(i));
+			}
+			/* More alarm bits */
+			data->alarms |= lm85_read_value(client,
+						EMC6D100_REG_ALARM3) << 16;
+		} else if (data->type == emc6d102 || data->type == emc6d103 ||
+			   data->type == emc6d103s) {
+			/*
+			 * Have to read LSB bits after the MSB ones because
+			 * the reading of the MSB bits has frozen the
+			 * LSBs (backward from the ADM1027).
+			 */
+			int ext1 = lm85_read_value(client,
+						   EMC6D102_REG_EXTEND_ADC1);
+			int ext2 = lm85_read_value(client,
+						   EMC6D102_REG_EXTEND_ADC2);
+			int ext3 = lm85_read_value(client,
+						   EMC6D102_REG_EXTEND_ADC3);
+			int ext4 = lm85_read_value(client,
+						   EMC6D102_REG_EXTEND_ADC4);
+			data->in_ext[0] = ext3 & 0x0f;
+			data->in_ext[1] = ext4 & 0x0f;
+			data->in_ext[2] = ext4 >> 4;
+			data->in_ext[3] = ext3 >> 4;
+			data->in_ext[4] = ext2 >> 4;
+
+			data->temp_ext[0] = ext1 & 0x0f;
+			data->temp_ext[1] = ext2 & 0x0f;
+			data->temp_ext[2] = ext1 >> 4;
+		}
+
+		data->last_reading = jiffies;
+	}  /* last_reading */
 
+	if (!data->valid ||
+	     time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) {
+		/* Things that don't change often */
+		dev_dbg(&client->dev, "Reading config values\n");
+
+		for (i = 0; i <= 3; ++i) {
+			data->in_min[i] =
+			    lm85_read_value(client, LM85_REG_IN_MIN(i));
+			data->in_max[i] =
+			    lm85_read_value(client, LM85_REG_IN_MAX(i));
+			data->fan_min[i] =
+			    lm85_read_value(client, LM85_REG_FAN_MIN(i));
+		}
+
+		if (!data->has_vid5)  {
+			data->in_min[4] = lm85_read_value(client,
+					  LM85_REG_IN_MIN(4));
+			data->in_max[4] = lm85_read_value(client,
+					  LM85_REG_IN_MAX(4));
+		}
+
+		if (data->type == emc6d100) {
+			for (i = 5; i <= 7; ++i) {
+				data->in_min[i] = lm85_read_value(client,
+						EMC6D100_REG_IN_MIN(i));
+				data->in_max[i] = lm85_read_value(client,
+						EMC6D100_REG_IN_MAX(i));
+			}
+		}
+
+		for (i = 0; i <= 2; ++i) {
+			int val;
+
+			data->temp_min[i] =
+			    lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+			data->temp_max[i] =
+			    lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+
+			data->autofan[i].config =
+			    lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+			val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+			data->pwm_freq[i] = val & 0x07;
+			data->zone[i].range = val >> 4;
+			data->autofan[i].min_pwm =
+			    lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+			data->zone[i].limit =
+			    lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+			data->zone[i].critical =
+			    lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+
+			if (IS_ADT7468_OFF64(data)) {
+				data->temp_min[i] -= 64;
+				data->temp_max[i] -= 64;
+				data->zone[i].limit -= 64;
+				data->zone[i].critical -= 64;
+			}
+		}
+
+		if (data->type != emc6d103s) {
+			i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+			data->autofan[0].min_off = (i & 0x20) != 0;
+			data->autofan[1].min_off = (i & 0x40) != 0;
+			data->autofan[2].min_off = (i & 0x80) != 0;
+
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+			data->zone[0].hyst = i >> 4;
+			data->zone[1].hyst = i & 0x0f;
+
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+			data->zone[2].hyst = i >> 4;
+		}
+
+		data->last_config = jiffies;
+	}  /* last_config */
+
+	data->valid = 1;
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 /* 4 Fans */
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
@@ -394,8 +585,8 @@ static ssize_t set_fan_min(struct device
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -460,6 +651,9 @@ static ssize_t store_vrm_reg(struct devi
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
@@ -515,8 +709,8 @@ static ssize_t set_pwm(struct device *de
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -557,8 +751,8 @@ static ssize_t set_pwm_enable(struct dev
 		*attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 config;
 	unsigned long val;
 	int err;
@@ -615,8 +809,8 @@ static ssize_t set_pwm_freq(struct devic
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -682,8 +876,8 @@ static ssize_t set_in_min(struct device
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -710,8 +904,8 @@ static ssize_t set_in_max(struct device
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -766,8 +960,8 @@ static ssize_t set_temp_min(struct devic
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -797,8 +991,8 @@ static ssize_t set_temp_max(struct devic
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -843,8 +1037,8 @@ static ssize_t set_pwm_auto_channels(str
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -873,8 +1067,8 @@ static ssize_t set_pwm_auto_pwm_min(stru
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -902,8 +1096,8 @@ static ssize_t set_pwm_auto_pwm_minctl(s
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 tmp;
 	long val;
 	int err;
@@ -953,8 +1147,8 @@ static ssize_t set_temp_auto_temp_off(st
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int min;
 	long val;
 	int err;
@@ -990,8 +1184,8 @@ static ssize_t set_temp_auto_temp_min(st
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1029,8 +1223,8 @@ static ssize_t set_temp_auto_temp_max(st
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int min;
 	long val;
 	int err;
@@ -1063,8 +1257,8 @@ static ssize_t set_temp_auto_temp_crit(s
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
+	struct lm85_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1355,30 +1549,18 @@ static int lm85_detect(struct i2c_client
 	return 0;
 }
 
-static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
-{
-	sysfs_remove_group(&client->dev.kobj, &lm85_group);
-	if (data->type != emc6d103s) {
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
-	}
-	if (!data->has_vid5)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
-	if (data->type == emc6d100)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
-}
-
-static int lm85_probe(struct i2c_client *client,
-		      const struct i2c_device_id *id)
+static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct lm85_data *data;
-	int err;
+	int idx = 0;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm85_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm85_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	data->type = id->driver_data;
 	mutex_init(&data->update_lock);
 
@@ -1403,20 +1585,13 @@ static int lm85_probe(struct i2c_client
 	/* Initialize the LM85 chip */
 	lm85_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &lm85_group);
-	if (err)
-		return err;
+	/* sysfs hooks */
+	data->groups[idx++] = &lm85_group;
 
 	/* minctl and temp_off exist on all chips except emc6d103s */
 	if (data->type != emc6d103s) {
-		err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
-		if (err)
-			goto err_remove_files;
-		err = sysfs_create_group(&client->dev.kobj,
-					 &lm85_group_temp_off);
-		if (err)
-			goto err_remove_files;
+		data->groups[idx++] = &lm85_group_minctl;
+		data->groups[idx++] = &lm85_group_temp_off;
 	}
 
 	/*
@@ -1429,271 +1604,44 @@ static int lm85_probe(struct i2c_client
 			data->has_vid5 = true;
 	}
 
-	if (!data->has_vid5) {
-		err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4);
-		if (err)
-			goto err_remove_files;
-	}
+	if (!data->has_vid5)
+		data->groups[idx++] = &lm85_group_in4;
 
 	/* The EMC6D100 has 3 additional voltage inputs */
-	if (data->type == emc6d100) {
-		err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567);
-		if (err)
-			goto err_remove_files;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto err_remove_files;
-	}
-
-	return 0;
-
-	/* Error out and cleanup code */
- err_remove_files:
-	lm85_remove_files(client, data);
-	return err;
-}
-
-static int lm85_remove(struct i2c_client *client)
-{
-	struct lm85_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->hwmon_dev);
-	lm85_remove_files(client, data);
-	return 0;
-}
-
-
-static int lm85_read_value(struct i2c_client *client, u8 reg)
-{
-	int res;
-
-	/* What size location is it? */
-	switch (reg) {
-	case LM85_REG_FAN(0):  /* Read WORD data */
-	case LM85_REG_FAN(1):
-	case LM85_REG_FAN(2):
-	case LM85_REG_FAN(3):
-	case LM85_REG_FAN_MIN(0):
-	case LM85_REG_FAN_MIN(1):
-	case LM85_REG_FAN_MIN(2):
-	case LM85_REG_FAN_MIN(3):
-	case LM85_REG_ALARM1:	/* Read both bytes at once */
-		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
-		res |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
-		break;
-	default:	/* Read BYTE data */
-		res = i2c_smbus_read_byte_data(client, reg);
-		break;
-	}
-
-	return res;
-}
+	if (data->type == emc6d100)
+		data->groups[idx++] = &lm85_group_in567;
 
-static void lm85_write_value(struct i2c_client *client, u8 reg, int value)
-{
-	switch (reg) {
-	case LM85_REG_FAN(0):  /* Write WORD data */
-	case LM85_REG_FAN(1):
-	case LM85_REG_FAN(2):
-	case LM85_REG_FAN(3):
-	case LM85_REG_FAN_MIN(0):
-	case LM85_REG_FAN_MIN(1):
-	case LM85_REG_FAN_MIN(2):
-	case LM85_REG_FAN_MIN(3):
-	/* NOTE: ALARM is read only, so not included here */
-		i2c_smbus_write_byte_data(client, reg, value & 0xff);
-		i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
-		break;
-	default:	/* Write BYTE data */
-		i2c_smbus_write_byte_data(client, reg, value);
-		break;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static struct lm85_data *lm85_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
-	int i;
-
-	mutex_lock(&data->update_lock);
-
-	if (!data->valid ||
-	     time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) {
-		/* Things that change quickly */
-		dev_dbg(&client->dev, "Reading sensor values\n");
-
-		/*
-		 * Have to read extended bits first to "freeze" the
-		 * more significant bits that are read later.
-		 * There are 2 additional resolution bits per channel and we
-		 * have room for 4, so we shift them to the left.
-		 */
-		if (data->type == adm1027 || data->type == adt7463 ||
-		    data->type == adt7468) {
-			int ext1 = lm85_read_value(client,
-						   ADM1027_REG_EXTEND_ADC1);
-			int ext2 =  lm85_read_value(client,
-						    ADM1027_REG_EXTEND_ADC2);
-			int val = (ext1 << 8) + ext2;
-
-			for (i = 0; i <= 4; i++)
-				data->in_ext[i] =
-					((val >> (i * 2)) & 0x03) << 2;
-
-			for (i = 0; i <= 2; i++)
-				data->temp_ext[i] =
-					(val >> ((i + 4) * 2)) & 0x0c;
-		}
-
-		data->vid = lm85_read_value(client, LM85_REG_VID);
-
-		for (i = 0; i <= 3; ++i) {
-			data->in[i] =
-			    lm85_read_value(client, LM85_REG_IN(i));
-			data->fan[i] =
-			    lm85_read_value(client, LM85_REG_FAN(i));
-		}
-
-		if (!data->has_vid5)
-			data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
-
-		if (data->type == adt7468)
-			data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
-
-		for (i = 0; i <= 2; ++i) {
-			data->temp[i] =
-			    lm85_read_value(client, LM85_REG_TEMP(i));
-			data->pwm[i] =
-			    lm85_read_value(client, LM85_REG_PWM(i));
-
-			if (IS_ADT7468_OFF64(data))
-				data->temp[i] -= 64;
-		}
-
-		data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
-
-		if (data->type == emc6d100) {
-			/* Three more voltage sensors */
-			for (i = 5; i <= 7; ++i) {
-				data->in[i] = lm85_read_value(client,
-							EMC6D100_REG_IN(i));
-			}
-			/* More alarm bits */
-			data->alarms |= lm85_read_value(client,
-						EMC6D100_REG_ALARM3) << 16;
-		} else if (data->type == emc6d102 || data->type == emc6d103 ||
-			   data->type == emc6d103s) {
-			/*
-			 * Have to read LSB bits after the MSB ones because
-			 * the reading of the MSB bits has frozen the
-			 * LSBs (backward from the ADM1027).
-			 */
-			int ext1 = lm85_read_value(client,
-						   EMC6D102_REG_EXTEND_ADC1);
-			int ext2 = lm85_read_value(client,
-						   EMC6D102_REG_EXTEND_ADC2);
-			int ext3 = lm85_read_value(client,
-						   EMC6D102_REG_EXTEND_ADC3);
-			int ext4 = lm85_read_value(client,
-						   EMC6D102_REG_EXTEND_ADC4);
-			data->in_ext[0] = ext3 & 0x0f;
-			data->in_ext[1] = ext4 & 0x0f;
-			data->in_ext[2] = ext4 >> 4;
-			data->in_ext[3] = ext3 >> 4;
-			data->in_ext[4] = ext2 >> 4;
-
-			data->temp_ext[0] = ext1 & 0x0f;
-			data->temp_ext[1] = ext2 & 0x0f;
-			data->temp_ext[2] = ext1 >> 4;
-		}
-
-		data->last_reading = jiffies;
-	}  /* last_reading */
-
-	if (!data->valid ||
-	     time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) {
-		/* Things that don't change often */
-		dev_dbg(&client->dev, "Reading config values\n");
-
-		for (i = 0; i <= 3; ++i) {
-			data->in_min[i] =
-			    lm85_read_value(client, LM85_REG_IN_MIN(i));
-			data->in_max[i] =
-			    lm85_read_value(client, LM85_REG_IN_MAX(i));
-			data->fan_min[i] =
-			    lm85_read_value(client, LM85_REG_FAN_MIN(i));
-		}
-
-		if (!data->has_vid5)  {
-			data->in_min[4] = lm85_read_value(client,
-					  LM85_REG_IN_MIN(4));
-			data->in_max[4] = lm85_read_value(client,
-					  LM85_REG_IN_MAX(4));
-		}
-
-		if (data->type == emc6d100) {
-			for (i = 5; i <= 7; ++i) {
-				data->in_min[i] = lm85_read_value(client,
-						EMC6D100_REG_IN_MIN(i));
-				data->in_max[i] = lm85_read_value(client,
-						EMC6D100_REG_IN_MAX(i));
-			}
-		}
-
-		for (i = 0; i <= 2; ++i) {
-			int val;
-
-			data->temp_min[i] =
-			    lm85_read_value(client, LM85_REG_TEMP_MIN(i));
-			data->temp_max[i] =
-			    lm85_read_value(client, LM85_REG_TEMP_MAX(i));
-
-			data->autofan[i].config =
-			    lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
-			val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
-			data->pwm_freq[i] = val & 0x07;
-			data->zone[i].range = val >> 4;
-			data->autofan[i].min_pwm =
-			    lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
-			data->zone[i].limit =
-			    lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
-			data->zone[i].critical =
-			    lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
-
-			if (IS_ADT7468_OFF64(data)) {
-				data->temp_min[i] -= 64;
-				data->temp_max[i] -= 64;
-				data->zone[i].limit -= 64;
-				data->zone[i].critical -= 64;
-			}
-		}
-
-		if (data->type != emc6d103s) {
-			i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
-			data->autofan[0].min_off = (i & 0x20) != 0;
-			data->autofan[1].min_off = (i & 0x40) != 0;
-			data->autofan[2].min_off = (i & 0x80) != 0;
-
-			i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
-			data->zone[0].hyst = i >> 4;
-			data->zone[1].hyst = i & 0x0f;
-
-			i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
-			data->zone[2].hyst = i >> 4;
-		}
-
-		data->last_config = jiffies;
-	}  /* last_config */
-
-	data->valid = 1;
-
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id lm85_id[] = {
+	{ "adm1027", adm1027 },
+	{ "adt7463", adt7463 },
+	{ "adt7468", adt7468 },
+	{ "lm85", lm85 },
+	{ "lm85b", lm85 },
+	{ "lm85c", lm85 },
+	{ "emc6d100", emc6d100 },
+	{ "emc6d101", emc6d100 },
+	{ "emc6d102", emc6d102 },
+	{ "emc6d103", emc6d103 },
+	{ "emc6d103s", emc6d103s },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm85_id);
 
-	return data;
-}
+static struct i2c_driver lm85_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name   = "lm85",
+	},
+	.probe		= lm85_probe,
+	.id_table	= lm85_id,
+	.detect		= lm85_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(lm85_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm87.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm87.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm87.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm87.c	2014-09-28 17:29:07.000000000 -0400
@@ -617,6 +617,10 @@ static ssize_t set_vrm(struct device *de
 	err = kstrtoul(buf, 10, &val);
 	if (err)
 		return err;
+
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm92.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm92.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm92.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm92.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,12 +74,9 @@ static inline int TEMP_FROM_REG(s16 reg)
 	return reg / 8 * 625 / 10;
 }
 
-static inline s16 TEMP_TO_REG(int val)
+static inline s16 TEMP_TO_REG(long val)
 {
-	if (val <= -60000)
-		return -60000 * 10 / 625 * 8;
-	if (val >= 160000)
-		return 160000 * 10 / 625 * 8;
+	val = clamp_val(val, -60000, 160000);
 	return val * 10 / 625 * 8;
 }
 
@@ -206,10 +203,12 @@ static ssize_t set_temp_hyst(struct devi
 	if (err)
 		return err;
 
+	val = clamp_val(val, -120000, 220000);
 	mutex_lock(&data->update_lock);
-	data->temp[t_hyst] = TEMP_FROM_REG(data->temp[attr->index]) - val;
+	 data->temp[t_hyst] =
+		TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val);
 	i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
-				     TEMP_TO_REG(data->temp[t_hyst]));
+				     data->temp[t_hyst]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/lm93.c linux-libre-3.17-rc7-gnu/drivers/hwmon/lm93.c
--- linux-libre-3.16-gnu/drivers/hwmon/lm93.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/lm93.c	2014-09-28 17:29:07.000000000 -0400
@@ -207,7 +207,7 @@ struct block1_t {
  * Client-specific data
  */
 struct lm93_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 
 	struct mutex update_lock;
 	unsigned long last_updated;	/* In jiffies */
@@ -919,8 +919,8 @@ static void lm93_read_block(struct i2c_c
 
 static struct lm93_data *lm93_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	const unsigned long interval = HZ + (HZ / 2);
 
 	mutex_lock(&data->update_lock);
@@ -1158,8 +1158,8 @@ static ssize_t store_in_min(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int vccp = nr - 6;
 	long vid;
 	unsigned long val;
@@ -1239,8 +1239,8 @@ static ssize_t store_in_max(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int vccp = nr - 6;
 	long vid;
 	unsigned long val;
@@ -1323,8 +1323,8 @@ static ssize_t store_temp_min(struct dev
 			      const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1358,8 +1358,8 @@ static ssize_t store_temp_max(struct dev
 			      const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1394,8 +1394,8 @@ static ssize_t store_temp_auto_base(stru
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1430,8 +1430,8 @@ static ssize_t store_temp_auto_boost(str
 				     const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -1469,8 +1469,8 @@ static ssize_t store_temp_auto_boost_hys
 					  const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1520,8 +1520,8 @@ static ssize_t store_temp_auto_offset(st
 	struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
 	int nr = s_attr->index;
 	int ofs = s_attr->nr;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1632,8 +1632,8 @@ static ssize_t store_temp_auto_pwm_min(s
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 reg, ctl4;
 	unsigned long val;
 	int err;
@@ -1680,8 +1680,8 @@ static ssize_t store_temp_auto_offset_hy
 						const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 reg;
 	unsigned long val;
 	int err;
@@ -1741,8 +1741,8 @@ static ssize_t store_fan_min(struct devi
 				const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1824,8 +1824,8 @@ static ssize_t store_fan_smart_tach(stru
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -1880,8 +1880,8 @@ static ssize_t store_pwm(struct device *
 				const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ctl2, ctl4;
 	unsigned long val;
 	int err;
@@ -1928,8 +1928,8 @@ static ssize_t store_pwm_enable(struct d
 				const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ctl2;
 	unsigned long val;
 	int err;
@@ -2006,8 +2006,8 @@ static ssize_t store_pwm_freq(struct dev
 				const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ctl4;
 	unsigned long val;
 	int err;
@@ -2046,8 +2046,8 @@ static ssize_t store_pwm_auto_channels(s
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -2087,8 +2087,8 @@ static ssize_t store_pwm_auto_spinup_min
 						const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ctl3, ctl4;
 	unsigned long val;
 	int err;
@@ -2130,8 +2130,8 @@ static ssize_t store_pwm_auto_spinup_tim
 						const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ctl3;
 	unsigned long val;
 	int err;
@@ -2168,8 +2168,8 @@ static ssize_t store_pwm_auto_prochot_ra
 						struct device_attribute *attr,
 						const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ramp;
 	unsigned long val;
 	int err;
@@ -2202,8 +2202,8 @@ static ssize_t store_pwm_auto_vrdhot_ram
 						struct device_attribute *attr,
 						const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 ramp;
 	unsigned long val;
 	int err;
@@ -2270,8 +2270,8 @@ static ssize_t store_prochot_max(struct
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -2308,8 +2308,8 @@ static ssize_t store_prochot_override(st
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -2351,8 +2351,8 @@ static ssize_t store_prochot_interval(st
 					const char *buf, size_t count)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 tmp;
 	unsigned long val;
 	int err;
@@ -2390,8 +2390,8 @@ static ssize_t store_prochot_override_du
 						struct device_attribute *attr,
 						const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -2423,8 +2423,8 @@ static ssize_t store_prochot_short(struc
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm93_data *data = i2c_get_clientdata(client);
+	struct lm93_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -2631,9 +2631,7 @@ static struct attribute *lm93_attrs[] =
 	NULL
 };
 
-static struct attribute_group lm93_attr_grp = {
-	.attrs = lm93_attrs,
-};
+ATTRIBUTE_GROUPS(lm93);
 
 static void lm93_init_client(struct i2c_client *client)
 {
@@ -2726,61 +2724,42 @@ static int lm93_detect(struct i2c_client
 static int lm93_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct lm93_data *data;
-	int err, func;
+	struct device *hwmon_dev;
+	int func;
 	void (*update)(struct lm93_data *, struct i2c_client *);
 
 	/* choose update routine based on bus capabilities */
 	func = i2c_get_functionality(client->adapter);
 	if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
 			(!disable_block)) {
-		dev_dbg(&client->dev, "using SMBus block data transactions\n");
+		dev_dbg(dev, "using SMBus block data transactions\n");
 		update = lm93_update_client_full;
 	} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
-		dev_dbg(&client->dev,
-			"disabled SMBus block data transactions\n");
+		dev_dbg(dev, "disabled SMBus block data transactions\n");
 		update = lm93_update_client_min;
 	} else {
-		dev_dbg(&client->dev,
-			"detect failed, smbus byte and/or word data not supported!\n");
+		dev_dbg(dev, "detect failed, smbus byte and/or word data not supported!\n");
 		return -ENODEV;
 	}
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm93_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm93_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-	i2c_set_clientdata(client, data);
 
 	/* housekeeping */
+	data->client = client;
 	data->update = update;
 	mutex_init(&data->update_lock);
 
 	/* initialize the chip */
 	lm93_init_client(client);
 
-	err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp);
-	if (err)
-		return err;
-
-	/* Register hwmon driver class */
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (!IS_ERR(data->hwmon_dev))
-		return 0;
-
-	err = PTR_ERR(data->hwmon_dev);
-	dev_err(&client->dev, "error registering hwmon device.\n");
-	sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
-	return err;
-}
-
-static int lm93_remove(struct i2c_client *client)
-{
-	struct lm93_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   lm93_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id lm93_id[] = {
@@ -2796,7 +2775,6 @@ static struct i2c_driver lm93_driver = {
 		.name	= "lm93",
 	},
 	.probe		= lm93_probe,
-	.remove		= lm93_remove,
 	.id_table	= lm93_id,
 	.detect		= lm93_detect,
 	.address_list	= normal_i2c,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ltc2945.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc2945.c
--- linux-libre-3.16-gnu/drivers/hwmon/ltc2945.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc2945.c	2014-09-28 17:29:07.000000000 -0400
@@ -469,7 +469,7 @@ static struct attribute *ltc2945_attrs[]
 };
 ATTRIBUTE_GROUPS(ltc2945);
 
-static struct regmap_config ltc2945_regmap_config = {
+static const struct regmap_config ltc2945_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.max_register = LTC2945_MIN_ADIN_THRES_L,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ltc4222.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc4222.c
--- linux-libre-3.16-gnu/drivers/hwmon/ltc4222.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc4222.c	2014-09-28 17:29:07.000000000 -0400
@@ -186,7 +186,7 @@ static struct attribute *ltc4222_attrs[]
 };
 ATTRIBUTE_GROUPS(ltc4222);
 
-static struct regmap_config ltc4222_regmap_config = {
+static const struct regmap_config ltc4222_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.max_register = LTC4222_ADC_CONTROL,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ltc4260.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc4260.c
--- linux-libre-3.16-gnu/drivers/hwmon/ltc4260.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ltc4260.c	2014-09-28 17:29:07.000000000 -0400
@@ -150,7 +150,7 @@ static struct attribute *ltc4260_attrs[]
 };
 ATTRIBUTE_GROUPS(ltc4260);
 
-static struct regmap_config ltc4260_regmap_config = {
+static const struct regmap_config ltc4260_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.max_register = LTC4260_ADIN,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/Makefile linux-libre-3.17-rc7-gnu/drivers/hwmon/Makefile
--- linux-libre-3.16-gnu/drivers/hwmon/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45
 obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
+obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o
 obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
 obj-$(CONFIG_SENSORS_INA209)	+= ina209.o
 obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
@@ -120,6 +121,8 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR)	+=
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
+obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
+obj-$(CONFIG_SENSORS_PWM_FAN)	+= pwm-fan.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
 obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
 obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
@@ -135,6 +138,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc4
 obj-$(CONFIG_SENSORS_AMC6821)	+= amc6821.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_TMP102)	+= tmp102.o
+obj-$(CONFIG_SENSORS_TMP103)	+= tmp103.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-3.16-gnu/drivers/hwmon/max16065.c linux-libre-3.17-rc7-gnu/drivers/hwmon/max16065.c
--- linux-libre-3.16-gnu/drivers/hwmon/max16065.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/max16065.c	2014-09-28 17:29:07.000000000 -0400
@@ -642,10 +642,7 @@ static int max16065_probe(struct i2c_cli
 
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 							   data, data->groups);
-	if (unlikely(IS_ERR(hwmon_dev)))
-		return PTR_ERR(hwmon_dev);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id max16065_id[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/max1668.c linux-libre-3.17-rc7-gnu/drivers/hwmon/max1668.c
--- linux-libre-3.16-gnu/drivers/hwmon/max1668.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/max1668.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@
 #include <linux/mutex.h>
 
 /* Addresses to scan */
-static unsigned short max1668_addr_list[] = {
+static const unsigned short max1668_addr_list[] = {
 	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
 
 /* max1668 registers */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/max6639.c linux-libre-3.17-rc7-gnu/drivers/hwmon/max6639.c
--- linux-libre-3.16-gnu/drivers/hwmon/max6639.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/max6639.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
 #include <linux/i2c/max6639.h>
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
 
 /* The MAX6639 registers, valid channel numbers: 0, 1 */
 #define MAX6639_REG_TEMP(ch)			(0x00 + (ch))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/max6697.c linux-libre-3.17-rc7-gnu/drivers/hwmon/max6697.c
--- linux-libre-3.16-gnu/drivers/hwmon/max6697.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/max6697.c	2014-09-28 17:29:07.000000000 -0400
@@ -495,15 +495,13 @@ static void max6697_get_config_of(struct
 	int len;
 	const __be32 *prop;
 
-	prop = of_get_property(node, "smbus-timeout-disable", &len);
-	if (prop)
-		pdata->smbus_timeout_disable = true;
-	prop = of_get_property(node, "extended-range-enable", &len);
-	if (prop)
-		pdata->extended_range_enable = true;
-	prop = of_get_property(node, "beta-compensation-enable", &len);
-	if (prop)
-		pdata->beta_compensation = true;
+	pdata->smbus_timeout_disable =
+		of_property_read_bool(node, "smbus-timeout-disable");
+	pdata->extended_range_enable =
+		of_property_read_bool(node, "extended-range-enable");
+	pdata->beta_compensation =
+		of_property_read_bool(node, "beta-compensation-enable");
+
 	prop = of_get_property(node, "alert-mask", &len);
 	if (prop && len == sizeof(u32))
 		pdata->alert_mask = be32_to_cpu(prop[0]);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/nct6775.c linux-libre-3.17-rc7-gnu/drivers/hwmon/nct6775.c
--- linux-libre-3.16-gnu/drivers/hwmon/nct6775.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/nct6775.c	2014-09-28 17:29:07.000000000 -0400
@@ -735,7 +735,6 @@ struct nct6775_data {
 	enum kinds kind;
 	const char *name;
 
-	int num_attr_groups;
 	const struct attribute_group *groups[6];
 
 	u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
@@ -3276,6 +3275,7 @@ static int nct6775_probe(struct platform
 	u8 cr2a;
 	struct attribute_group *group;
 	struct device *hwmon_dev;
+	int num_attr_groups = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
@@ -3907,29 +3907,29 @@ static int nct6775_probe(struct platform
 	if (IS_ERR(group))
 		return PTR_ERR(group);
 
-	data->groups[data->num_attr_groups++] = group;
+	data->groups[num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
 					  fls(data->have_in));
 	if (IS_ERR(group))
 		return PTR_ERR(group);
 
-	data->groups[data->num_attr_groups++] = group;
+	data->groups[num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
 					  fls(data->has_fan));
 	if (IS_ERR(group))
 		return PTR_ERR(group);
 
-	data->groups[data->num_attr_groups++] = group;
+	data->groups[num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
 					  fls(data->have_temp));
 	if (IS_ERR(group))
 		return PTR_ERR(group);
 
-	data->groups[data->num_attr_groups++] = group;
-	data->groups[data->num_attr_groups++] = &nct6775_group_other;
+	data->groups[num_attr_groups++] = group;
+	data->groups[num_attr_groups++] = &nct6775_group_other;
 
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
 							   data, data->groups);
@@ -4221,7 +4221,7 @@ static void __exit sensors_nct6775_exit(
 }
 
 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
+MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D driver");
 MODULE_LICENSE("GPL");
 
 module_init(sensors_nct6775_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/ntc_thermistor.c linux-libre-3.17-rc7-gnu/drivers/hwmon/ntc_thermistor.c
--- linux-libre-3.16-gnu/drivers/hwmon/ntc_thermistor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/ntc_thermistor.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,6 +51,7 @@ static const struct platform_device_id n
 	{ "ncp21wb473", TYPE_NCPXXWB473 },
 	{ "ncp03wb473", TYPE_NCPXXWB473 },
 	{ "ncp15wl333", TYPE_NCPXXWL333 },
+	{ "b57330v2103", TYPE_B57330V2103},
 	{ },
 };
 
@@ -133,6 +134,47 @@ static const struct ntc_compensation ncp
 	{ .temp_c	= 125, .ohm	= 707 },
 };
 
+/*
+ * The following compensation table is from the specification of EPCOS NTC
+ * Thermistors Datasheet
+ */
+static const struct ntc_compensation b57330v2103[] = {
+	{ .temp_c	= -40, .ohm	= 190030 },
+	{ .temp_c	= -35, .ohm	= 145360 },
+	{ .temp_c	= -30, .ohm	= 112060 },
+	{ .temp_c	= -25, .ohm	= 87041 },
+	{ .temp_c	= -20, .ohm	= 68104 },
+	{ .temp_c	= -15, .ohm	= 53665 },
+	{ .temp_c	= -10, .ohm	= 42576 },
+	{ .temp_c	= -5, .ohm	= 34001 },
+	{ .temp_c	= 0, .ohm	= 27326 },
+	{ .temp_c	= 5, .ohm	= 22096 },
+	{ .temp_c	= 10, .ohm	= 17973 },
+	{ .temp_c	= 15, .ohm	= 14703 },
+	{ .temp_c	= 20, .ohm	= 12090 },
+	{ .temp_c	= 25, .ohm	= 10000 },
+	{ .temp_c	= 30, .ohm	= 8311 },
+	{ .temp_c	= 35, .ohm	= 6941 },
+	{ .temp_c	= 40, .ohm	= 5825 },
+	{ .temp_c	= 45, .ohm	= 4911 },
+	{ .temp_c	= 50, .ohm	= 4158 },
+	{ .temp_c	= 55, .ohm	= 3536 },
+	{ .temp_c	= 60, .ohm	= 3019 },
+	{ .temp_c	= 65, .ohm	= 2588 },
+	{ .temp_c	= 70, .ohm	= 2227 },
+	{ .temp_c	= 75, .ohm	= 1924 },
+	{ .temp_c	= 80, .ohm	= 1668 },
+	{ .temp_c	= 85, .ohm	= 1451 },
+	{ .temp_c	= 90, .ohm	= 1266 },
+	{ .temp_c	= 95, .ohm	= 1108 },
+	{ .temp_c	= 100, .ohm	= 973 },
+	{ .temp_c	= 105, .ohm	= 857 },
+	{ .temp_c	= 110, .ohm	= 757 },
+	{ .temp_c	= 115, .ohm	= 671 },
+	{ .temp_c	= 120, .ohm	= 596 },
+	{ .temp_c	= 125, .ohm	= 531 },
+};
+
 struct ntc_data {
 	struct device *hwmon_dev;
 	struct ntc_thermistor_platform_data *pdata;
@@ -173,6 +215,8 @@ static const struct of_device_id ntc_mat
 		.data = &ntc_thermistor_id[3] },
 	{ .compatible = "murata,ncp15wl333",
 		.data = &ntc_thermistor_id[4] },
+	{ .compatible = "epcos,b57330v2103",
+		.data = &ntc_thermistor_id[5]},
 
 	/* Usage of vendor name "ntc" is deprecated */
 	{ .compatible = "ntc,ncp15wb473",
@@ -490,6 +534,10 @@ static int ntc_thermistor_probe(struct p
 		data->comp = ncpXXwl333;
 		data->n_comp = ARRAY_SIZE(ncpXXwl333);
 		break;
+	case TYPE_B57330V2103:
+		data->comp = b57330v2103;
+		data->n_comp = ARRAY_SIZE(b57330v2103);
+		break;
 	default:
 		dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
 				pdev_id->driver_data, pdev_id->name);
@@ -546,7 +594,7 @@ static struct platform_driver ntc_thermi
 
 module_platform_driver(ntc_thermistor_driver);
 
-MODULE_DESCRIPTION("NTC Thermistor Driver from Murata");
+MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:ntc-thermistor");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pc87360.c linux-libre-3.17-rc7-gnu/drivers/hwmon/pc87360.c
--- linux-libre-3.16-gnu/drivers/hwmon/pc87360.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pc87360.c	2014-09-28 17:29:07.000000000 -0400
@@ -615,6 +615,9 @@ static ssize_t set_vrm(struct device *de
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pmbus/Kconfig linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/Kconfig
--- linux-libre-3.16-gnu/drivers/hwmon/pmbus/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,8 +20,7 @@ config SENSORS_PMBUS
 	help
 	  If you say yes here you get hardware monitoring support for generic
 	  PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
-	  MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, TPS40400,
-	  and TPS40422.
+	  MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called pmbus.
@@ -87,6 +86,16 @@ config SENSORS_MAX8688
 	  This driver can also be built as a module. If so, the module will
 	  be called max8688.
 
+config SENSORS_TPS40422
+	tristate "TI TPS40422"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for TI
+	  TPS40422.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called tps40422.
+
 config SENSORS_UCD9000
 	tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
 	default n
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pmbus/Makefile linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/Makefile
--- linux-libre-3.16-gnu/drivers/hwmon/pmbus/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@ obj-$(CONFIG_SENSORS_LTC2978)	+= ltc2978
 obj-$(CONFIG_SENSORS_MAX16064)	+= max16064.o
 obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
+obj-$(CONFIG_SENSORS_TPS40422)	+= tps40422.o
 obj-$(CONFIG_SENSORS_UCD9000)	+= ucd9000.o
 obj-$(CONFIG_SENSORS_UCD9200)	+= ucd9200.o
 obj-$(CONFIG_SENSORS_ZL6100)	+= zl6100.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pmbus/pmbus.c linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/pmbus.c
--- linux-libre-3.16-gnu/drivers/hwmon/pmbus/pmbus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/pmbus.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,7 +193,6 @@ static const struct i2c_device_id pmbus_
 	{"pdt012", 1},
 	{"pmbus", 0},
 	{"tps40400", 1},
-	{"tps40422", 2},
 	{"udt020", 1},
 	{}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pmbus/tps40422.c linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/tps40422.c
--- linux-libre-3.16-gnu/drivers/hwmon/pmbus/tps40422.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pmbus/tps40422.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Hardware monitoring driver for TI TPS40422
+ *
+ * Copyright (c) 2014 Nokia Solutions and Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info tps40422_info = {
+	.pages = 2,
+	.format[PSC_VOLTAGE_IN] = linear,
+	.format[PSC_VOLTAGE_OUT] = linear,
+	.format[PSC_TEMPERATURE] = linear,
+	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP
+		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+	.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP
+		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+};
+
+static int tps40422_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &tps40422_info);
+}
+
+static const struct i2c_device_id tps40422_id[] = {
+	{"tps40422", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tps40422_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver tps40422_driver = {
+	.driver = {
+		   .name = "tps40422",
+		   },
+	.probe = tps40422_probe,
+	.remove = pmbus_do_remove,
+	.id_table = tps40422_id,
+};
+
+module_i2c_driver(tps40422_driver);
+
+MODULE_AUTHOR("Zhu Laiwen <richard.zhu@nsn.com>");
+MODULE_DESCRIPTION("PMBus driver for TI TPS40422");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/powr1220.c linux-libre-3.17-rc7-gnu/drivers/hwmon/powr1220.c
--- linux-libre-3.16-gnu/drivers/hwmon/powr1220.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/powr1220.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,391 @@
+/*
+ * powr1220.c - Driver for the Lattice POWR1220 programmable power supply
+ * and monitor. Users can read all ADC inputs along with their labels
+ * using the sysfs nodes.
+ *
+ * Copyright (c) 2014 Echo360 http://www.echo360.com
+ * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#define ADC_STEP_MV			2
+#define ADC_MAX_LOW_MEASUREMENT_MV	2000
+
+enum powr1220_regs {
+	VMON_STATUS0,
+	VMON_STATUS1,
+	VMON_STATUS2,
+	OUTPUT_STATUS0,
+	OUTPUT_STATUS1,
+	OUTPUT_STATUS2,
+	INPUT_STATUS,
+	ADC_VALUE_LOW,
+	ADC_VALUE_HIGH,
+	ADC_MUX,
+	UES_BYTE0,
+	UES_BYTE1,
+	UES_BYTE2,
+	UES_BYTE3,
+	GP_OUTPUT1,
+	GP_OUTPUT2,
+	GP_OUTPUT3,
+	INPUT_VALUE,
+	RESET,
+	TRIM1_TRIM,
+	TRIM2_TRIM,
+	TRIM3_TRIM,
+	TRIM4_TRIM,
+	TRIM5_TRIM,
+	TRIM6_TRIM,
+	TRIM7_TRIM,
+	TRIM8_TRIM,
+	MAX_POWR1220_REGS
+};
+
+enum powr1220_adc_values {
+	VMON1,
+	VMON2,
+	VMON3,
+	VMON4,
+	VMON5,
+	VMON6,
+	VMON7,
+	VMON8,
+	VMON9,
+	VMON10,
+	VMON11,
+	VMON12,
+	VCCA,
+	VCCINP,
+	MAX_POWR1220_ADC_VALUES
+};
+
+struct powr1220_data {
+	struct i2c_client *client;
+	struct mutex update_lock;
+	bool adc_valid[MAX_POWR1220_ADC_VALUES];
+	 /* the next value is in jiffies */
+	unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES];
+
+	/* values */
+	int adc_maxes[MAX_POWR1220_ADC_VALUES];
+	int adc_values[MAX_POWR1220_ADC_VALUES];
+};
+
+static const char * const input_names[] = {
+	[VMON1]    = "vmon1",
+	[VMON2]    = "vmon2",
+	[VMON3]    = "vmon3",
+	[VMON4]    = "vmon4",
+	[VMON5]    = "vmon5",
+	[VMON6]    = "vmon6",
+	[VMON7]    = "vmon7",
+	[VMON8]    = "vmon8",
+	[VMON9]    = "vmon9",
+	[VMON10]   = "vmon10",
+	[VMON11]   = "vmon11",
+	[VMON12]   = "vmon12",
+	[VCCA]     = "vcca",
+	[VCCINP]   = "vccinp",
+};
+
+/* Reads the specified ADC channel */
+static int powr1220_read_adc(struct device *dev, int ch_num)
+{
+	struct powr1220_data *data = dev_get_drvdata(dev);
+	int reading;
+	int result;
+	int adc_range = 0;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) ||
+			!data->adc_valid[ch_num]) {
+		/*
+		 * figure out if we need to use the attenuator for
+		 * high inputs or inputs that we don't yet have a measurement
+		 * for. We dynamically set the attenuator depending on the
+		 * max reading.
+		 */
+		if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV ||
+				data->adc_maxes[ch_num] == 0)
+			adc_range = 1 << 4;
+
+		/* set the attenuator and mux */
+		result = i2c_smbus_write_byte_data(data->client, ADC_MUX,
+				adc_range | ch_num);
+		if (result)
+			goto exit;
+
+		/*
+		 * wait at least Tconvert time (200 us) for the
+		 * conversion to complete
+		 */
+		udelay(200);
+
+		/* get the ADC reading */
+		result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW);
+		if (result < 0)
+			goto exit;
+
+		reading = result >> 4;
+
+		/* get the upper half of the reading */
+		result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH);
+		if (result < 0)
+			goto exit;
+
+		reading |= result << 4;
+
+		/* now convert the reading to a voltage */
+		reading *= ADC_STEP_MV;
+		data->adc_values[ch_num] = reading;
+		data->adc_valid[ch_num] = true;
+		data->adc_last_updated[ch_num] = jiffies;
+		result = reading;
+
+		if (reading > data->adc_maxes[ch_num])
+			data->adc_maxes[ch_num] = reading;
+	} else {
+		result = data->adc_values[ch_num];
+	}
+
+exit:
+	mutex_unlock(&data->update_lock);
+
+	return result;
+}
+
+/* Shows the voltage associated with the specified ADC channel */
+static ssize_t powr1220_show_voltage(struct device *dev,
+	struct device_attribute *dev_attr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	int adc_val = powr1220_read_adc(dev, attr->index);
+
+	if (adc_val < 0)
+		return adc_val;
+
+	return sprintf(buf, "%d\n", adc_val);
+}
+
+/* Shows the maximum setting associated with the specified ADC channel */
+static ssize_t powr1220_show_max(struct device *dev,
+	struct device_attribute *dev_attr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct powr1220_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", data->adc_maxes[attr->index]);
+}
+
+/* Shows the label associated with the specified ADC channel */
+static ssize_t powr1220_show_label(struct device *dev,
+	struct device_attribute *dev_attr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%s\n", input_names[attr->index]);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON1);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON2);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON3);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON4);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON5);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON6);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON7);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON8);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON9);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON10);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON11);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VMON12);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VCCA);
+static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL,
+	VCCINP);
+
+static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON1);
+static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON2);
+static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON3);
+static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON4);
+static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON5);
+static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON6);
+static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON7);
+static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON8);
+static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON9);
+static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON10);
+static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON11);
+static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL,
+	VMON12);
+static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL,
+	VCCA);
+static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL,
+	VCCINP);
+
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON1);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON2);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON3);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON4);
+static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON5);
+static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON6);
+static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON7);
+static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON8);
+static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON9);
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON10);
+static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON11);
+static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL,
+	VMON12);
+static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL,
+	VCCA);
+static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL,
+	VCCINP);
+
+static struct attribute *powr1220_attrs[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in9_input.dev_attr.attr,
+	&sensor_dev_attr_in10_input.dev_attr.attr,
+	&sensor_dev_attr_in11_input.dev_attr.attr,
+	&sensor_dev_attr_in12_input.dev_attr.attr,
+	&sensor_dev_attr_in13_input.dev_attr.attr,
+
+	&sensor_dev_attr_in0_highest.dev_attr.attr,
+	&sensor_dev_attr_in1_highest.dev_attr.attr,
+	&sensor_dev_attr_in2_highest.dev_attr.attr,
+	&sensor_dev_attr_in3_highest.dev_attr.attr,
+	&sensor_dev_attr_in4_highest.dev_attr.attr,
+	&sensor_dev_attr_in5_highest.dev_attr.attr,
+	&sensor_dev_attr_in6_highest.dev_attr.attr,
+	&sensor_dev_attr_in7_highest.dev_attr.attr,
+	&sensor_dev_attr_in8_highest.dev_attr.attr,
+	&sensor_dev_attr_in9_highest.dev_attr.attr,
+	&sensor_dev_attr_in10_highest.dev_attr.attr,
+	&sensor_dev_attr_in11_highest.dev_attr.attr,
+	&sensor_dev_attr_in12_highest.dev_attr.attr,
+	&sensor_dev_attr_in13_highest.dev_attr.attr,
+
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	&sensor_dev_attr_in1_label.dev_attr.attr,
+	&sensor_dev_attr_in2_label.dev_attr.attr,
+	&sensor_dev_attr_in3_label.dev_attr.attr,
+	&sensor_dev_attr_in4_label.dev_attr.attr,
+	&sensor_dev_attr_in5_label.dev_attr.attr,
+	&sensor_dev_attr_in6_label.dev_attr.attr,
+	&sensor_dev_attr_in7_label.dev_attr.attr,
+	&sensor_dev_attr_in8_label.dev_attr.attr,
+	&sensor_dev_attr_in9_label.dev_attr.attr,
+	&sensor_dev_attr_in10_label.dev_attr.attr,
+	&sensor_dev_attr_in11_label.dev_attr.attr,
+	&sensor_dev_attr_in12_label.dev_attr.attr,
+	&sensor_dev_attr_in13_label.dev_attr.attr,
+
+	NULL
+};
+
+ATTRIBUTE_GROUPS(powr1220);
+
+static int powr1220_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct powr1220_data *data;
+	struct device *hwmon_dev;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	mutex_init(&data->update_lock);
+	data->client = client;
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+			client->name, data, powr1220_groups);
+
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id powr1220_ids[] = {
+	{ "powr1220", 0, },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, powr1220_ids);
+
+static struct i2c_driver powr1220_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "powr1220",
+	},
+	.probe		= powr1220_probe,
+	.id_table	= powr1220_ids,
+};
+
+module_i2c_driver(powr1220_driver);
+
+MODULE_AUTHOR("Scott Kanowitz");
+MODULE_DESCRIPTION("POWR1220 driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/pwm-fan.c linux-libre-3.17-rc7-gnu/drivers/hwmon/pwm-fan.c
--- linux-libre-3.16-gnu/drivers/hwmon/pwm-fan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/pwm-fan.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,193 @@
+/*
+ * pwm-fan.c - Hwmon driver for fans connected to PWM lines.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Author: Kamil Debski <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/sysfs.h>
+
+#define MAX_PWM 255
+
+struct pwm_fan_ctx {
+	struct mutex lock;
+	struct pwm_device *pwm;
+	unsigned char pwm_value;
+};
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+	unsigned long pwm, duty;
+	ssize_t ret;
+
+	if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
+		return -EINVAL;
+
+	mutex_lock(&ctx->lock);
+
+	if (ctx->pwm_value == pwm)
+		goto exit_set_pwm_no_change;
+
+	if (pwm == 0) {
+		pwm_disable(ctx->pwm);
+		goto exit_set_pwm;
+	}
+
+	duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
+	ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+	if (ret)
+		goto exit_set_pwm_err;
+
+	if (ctx->pwm_value == 0) {
+		ret = pwm_enable(ctx->pwm);
+		if (ret)
+			goto exit_set_pwm_err;
+	}
+
+exit_set_pwm:
+	ctx->pwm_value = pwm;
+exit_set_pwm_no_change:
+	ret = count;
+exit_set_pwm_err:
+	mutex_unlock(&ctx->lock);
+	return ret;
+}
+
+static ssize_t show_pwm(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", ctx->pwm_value);
+}
+
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+
+static struct attribute *pwm_fan_attrs[] = {
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(pwm_fan);
+
+static int pwm_fan_probe(struct platform_device *pdev)
+{
+	struct device *hwmon;
+	struct pwm_fan_ctx *ctx;
+	int duty_cycle;
+	int ret;
+
+	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_init(&ctx->lock);
+
+	ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
+	if (IS_ERR(ctx->pwm)) {
+		dev_err(&pdev->dev, "Could not get PWM\n");
+		return PTR_ERR(ctx->pwm);
+	}
+
+	platform_set_drvdata(pdev, ctx);
+
+	/* Set duty cycle to maximum allowed */
+	duty_cycle = ctx->pwm->period - 1;
+	ctx->pwm_value = MAX_PWM;
+
+	ret = pwm_config(ctx->pwm, duty_cycle, ctx->pwm->period);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to configure PWM\n");
+		return ret;
+	}
+
+	/* Enbale PWM output */
+	ret = pwm_enable(ctx->pwm);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to enable PWM\n");
+		return ret;
+	}
+
+	hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
+						       ctx, pwm_fan_groups);
+	if (IS_ERR(hwmon)) {
+		dev_err(&pdev->dev, "Failed to register hwmon device\n");
+		pwm_disable(ctx->pwm);
+		return PTR_ERR(hwmon);
+	}
+	return 0;
+}
+
+static int pwm_fan_remove(struct platform_device *pdev)
+{
+	struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
+
+	if (ctx->pwm_value)
+		pwm_disable(ctx->pwm);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pwm_fan_suspend(struct device *dev)
+{
+	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+	if (ctx->pwm_value)
+		pwm_disable(ctx->pwm);
+	return 0;
+}
+
+static int pwm_fan_resume(struct device *dev)
+{
+	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+	if (ctx->pwm_value)
+		return pwm_enable(ctx->pwm);
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume);
+
+static struct of_device_id of_pwm_fan_match[] = {
+	{ .compatible = "pwm-fan", },
+	{},
+};
+
+static struct platform_driver pwm_fan_driver = {
+	.probe		= pwm_fan_probe,
+	.remove		= pwm_fan_remove,
+	.driver	= {
+		.name		= "pwm-fan",
+		.pm		= &pwm_fan_pm,
+		.of_match_table	= of_pwm_fan_match,
+	},
+};
+
+module_platform_driver(pwm_fan_driver);
+
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_ALIAS("platform:pwm-fan");
+MODULE_DESCRIPTION("PWM FAN driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/sht21.c linux-libre-3.17-rc7-gnu/drivers/hwmon/sht21.c
--- linux-libre-3.16-gnu/drivers/hwmon/sht21.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/sht21.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@
  * @humidity: cached humidity measurement value
  */
 struct sht21 {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex lock;
 	char valid;
 	unsigned long last_update;
@@ -85,14 +85,15 @@ static inline int sht21_rh_ticks_to_per_
 
 /**
  * sht21_update_measurements() - get updated measurements from device
- * @client: I2C client device
+ * @dev: device
  *
  * Returns 0 on success, else negative errno.
  */
-static int sht21_update_measurements(struct i2c_client *client)
+static int sht21_update_measurements(struct device *dev)
 {
 	int ret = 0;
-	struct sht21 *sht21 = i2c_get_clientdata(client);
+	struct sht21 *sht21 = dev_get_drvdata(dev);
+	struct i2c_client *client = sht21->client;
 
 	mutex_lock(&sht21->lock);
 	/*
@@ -133,9 +134,10 @@ static ssize_t sht21_show_temperature(st
 	struct device_attribute *attr,
 	char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sht21 *sht21 = i2c_get_clientdata(client);
-	int ret = sht21_update_measurements(client);
+	struct sht21 *sht21 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = sht21_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", sht21->temperature);
@@ -154,9 +156,10 @@ static ssize_t sht21_show_humidity(struc
 	struct device_attribute *attr,
 	char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sht21 *sht21 = i2c_get_clientdata(client);
-	int ret = sht21_update_measurements(client);
+	struct sht21 *sht21 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = sht21_update_measurements(dev);
 	if (ret < 0)
 		return ret;
 	return sprintf(buf, "%d\n", sht21->humidity);
@@ -168,30 +171,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S
 static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
 	NULL, 0);
 
-static struct attribute *sht21_attributes[] = {
+static struct attribute *sht21_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_humidity1_input.dev_attr.attr,
 	NULL
 };
 
-static const struct attribute_group sht21_attr_group = {
-	.attrs = sht21_attributes,
-};
+ATTRIBUTE_GROUPS(sht21);
 
-/**
- * sht21_probe() - probe device
- * @client: I2C client device
- * @id: device ID
- *
- * Called by the I2C core when an entry in the ID table matches a
- * device's name.
- * Returns 0 on success.
- */
 static int sht21_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct sht21 *sht21;
-	int err;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -200,47 +193,17 @@ static int sht21_probe(struct i2c_client
 		return -ENODEV;
 	}
 
-	sht21 = devm_kzalloc(&client->dev, sizeof(*sht21), GFP_KERNEL);
+	sht21 = devm_kzalloc(dev, sizeof(*sht21), GFP_KERNEL);
 	if (!sht21)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, sht21);
+	sht21->client = client;
 
 	mutex_init(&sht21->lock);
 
-	err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
-	if (err) {
-		dev_dbg(&client->dev, "could not create sysfs files\n");
-		return err;
-	}
-	sht21->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(sht21->hwmon_dev)) {
-		dev_dbg(&client->dev, "unable to register hwmon device\n");
-		err = PTR_ERR(sht21->hwmon_dev);
-		goto fail_remove_sysfs;
-	}
-
-	dev_info(&client->dev, "initialized\n");
-
-	return 0;
-
-fail_remove_sysfs:
-	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
-	return err;
-}
-
-/**
- * sht21_remove() - remove device
- * @client: I2C client device
- */
-static int sht21_remove(struct i2c_client *client)
-{
-	struct sht21 *sht21 = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(sht21->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   sht21, sht21_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Device ID table */
@@ -253,7 +216,6 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
 static struct i2c_driver sht21_driver = {
 	.driver.name = "sht21",
 	.probe       = sht21_probe,
-	.remove      = sht21_remove,
 	.id_table    = sht21_id,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/sis5595.c linux-libre-3.17-rc7-gnu/drivers/hwmon/sis5595.c
--- linux-libre-3.16-gnu/drivers/hwmon/sis5595.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/sis5595.c	2014-09-28 17:29:07.000000000 -0400
@@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val)
 {
 	return val * 830 + 52120;
 }
-static inline s8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(long val)
 {
 	int nval = clamp_val(val, -54120, 157530) ;
 	return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/smm665.c linux-libre-3.17-rc7-gnu/drivers/hwmon/smm665.c
--- linux-libre-3.16-gnu/drivers/hwmon/smm665.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/smm665.c	2014-09-28 17:29:07.000000000 -0400
@@ -140,7 +140,7 @@ enum chips { smm465, smm665, smm665c, sm
 struct smm665_data {
 	enum chips type;
 	int conversion_time;		/* ADC conversion time */
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	bool valid;
 	unsigned long last_updated;	/* in jiffies */
@@ -239,8 +239,8 @@ static int smm665_read_adc(struct smm665
 
 static struct smm665_data *smm665_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smm665_data *data = i2c_get_clientdata(client);
+	struct smm665_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct smm665_data *ret = data;
 
 	mutex_lock(&data->update_lock);
@@ -315,32 +315,28 @@ static int smm665_convert(u16 adcval, in
 
 static int smm665_get_min(struct device *dev, int index)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smm665_data *data = i2c_get_clientdata(client);
+	struct smm665_data *data = dev_get_drvdata(dev);
 
 	return data->alarm_min_limit[index];
 }
 
 static int smm665_get_max(struct device *dev, int index)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smm665_data *data = i2c_get_clientdata(client);
+	struct smm665_data *data = dev_get_drvdata(dev);
 
 	return data->alarm_max_limit[index];
 }
 
 static int smm665_get_lcrit(struct device *dev, int index)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smm665_data *data = i2c_get_clientdata(client);
+	struct smm665_data *data = dev_get_drvdata(dev);
 
 	return data->critical_min_limit[index];
 }
 
 static int smm665_get_crit(struct device *dev, int index)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smm665_data *data = i2c_get_clientdata(client);
+	struct smm665_data *data = dev_get_drvdata(dev);
 
 	return data->critical_max_limit[index];
 }
@@ -486,7 +482,7 @@ SMM665_ATTR(temp1, crit_alarm, SMM665_FA
  * Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
  */
-static struct attribute *smm665_attributes[] = {
+static struct attribute *smm665_attrs[] = {
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
 	&sensor_dev_attr_in1_max.dev_attr.attr,
@@ -567,15 +563,14 @@ static struct attribute *smm665_attribut
 	NULL,
 };
 
-static const struct attribute_group smm665_group = {
-	.attrs = smm665_attributes,
-};
+ATTRIBUTE_GROUPS(smm665);
 
 static int smm665_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct smm665_data *data;
+	struct device *hwmon_dev;
 	int i, ret;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
@@ -592,6 +587,7 @@ static int smm665_probe(struct i2c_clien
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
+	data->client = client;
 	data->type = id->driver_data;
 	data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK)
 				     | SMM665_CMDREG_BASE);
@@ -662,21 +658,16 @@ static int smm665_probe(struct i2c_clien
 			data->alarm_max_limit[i] = smm665_convert(val, i);
 	}
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &smm665_group);
-	if (ret)
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name, data,
+							   smm665_groups);
+	if (IS_ERR(hwmon_dev)) {
+		ret = PTR_ERR(hwmon_dev);
 		goto out_unregister;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto out_remove_group;
 	}
 
 	return 0;
 
-out_remove_group:
-	sysfs_remove_group(&client->dev.kobj, &smm665_group);
 out_unregister:
 	i2c_unregister_device(data->cmdreg);
 	return ret;
@@ -687,9 +678,6 @@ static int smm665_remove(struct i2c_clie
 	struct smm665_data *data = i2c_get_clientdata(client);
 
 	i2c_unregister_device(data->cmdreg);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &smm665_group);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/smsc47m192.c linux-libre-3.17-rc7-gnu/drivers/hwmon/smsc47m192.c
--- linux-libre-3.16-gnu/drivers/hwmon/smsc47m192.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/smsc47m192.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,8 @@ static inline int TEMP_FROM_REG(s8 val)
 }
 
 struct smsc47m192_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -112,30 +113,69 @@ struct smsc47m192_data {
 	u8 vrm;
 };
 
-static int smsc47m192_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id);
-static int smsc47m192_detect(struct i2c_client *client,
-			     struct i2c_board_info *info);
-static int smsc47m192_remove(struct i2c_client *client);
-static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
+{
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int i, config;
 
-static const struct i2c_device_id smsc47m192_id[] = {
-	{ "smsc47m192", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
+	mutex_lock(&data->update_lock);
 
-static struct i2c_driver smsc47m192_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "smsc47m192",
-	},
-	.probe		= smsc47m192_probe,
-	.remove		= smsc47m192_remove,
-	.id_table	= smsc47m192_id,
-	.detect		= smsc47m192_detect,
-	.address_list	= normal_i2c,
-};
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	 || !data->valid) {
+		u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+		dev_dbg(&client->dev, "Starting smsc47m192 update\n");
+
+		for (i = 0; i <= 7; i++) {
+			data->in[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN(i));
+			data->in_min[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN_MIN(i));
+			data->in_max[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 3; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP[i]);
+			data->temp_max[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_MAX[i]);
+			data->temp_min[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_MIN[i]);
+		}
+		for (i = 1; i < 3; i++)
+			data->temp_offset[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_OFFSET(i));
+		/*
+		 * first offset is temp_offset[0] if SFR bit 4 is set,
+		 * temp_offset[1] otherwise
+		 */
+		if (sfr & 0x10) {
+			data->temp_offset[0] = data->temp_offset[1];
+			data->temp_offset[1] = 0;
+		} else
+			data->temp_offset[0] = 0;
+
+		data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
+			    & 0x0f;
+		config = i2c_smbus_read_byte_data(client,
+						  SMSC47M192_REG_CONFIG);
+		if (config & 0x20)
+			data->vid |= (i2c_smbus_read_byte_data(client,
+					SMSC47M192_REG_VID4) & 0x01) << 4;
+		data->alarms = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_ALARM1) |
+			       (i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_ALARM2) << 8);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 /* Voltages */
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
@@ -170,8 +210,8 @@ static ssize_t set_in_min(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -192,8 +232,8 @@ static ssize_t set_in_max(struct device
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -259,8 +299,8 @@ static ssize_t set_temp_min(struct devic
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -281,8 +321,8 @@ static ssize_t set_temp_max(struct devic
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -312,8 +352,8 @@ static ssize_t set_temp_offset(struct de
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
 	long val;
 	int err;
@@ -552,124 +592,50 @@ static int smsc47m192_detect(struct i2c_
 static int smsc47m192_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct smsc47m192_data *data;
 	int config;
-	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct smsc47m192_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct smsc47m192_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	data->vrm = vid_which_vrm();
 	mutex_init(&data->update_lock);
 
 	/* Initialize the SMSC47M192 chip */
 	smsc47m192_init_client(client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group);
-	if (err)
-		return err;
-
+	/* sysfs hooks */
+	data->groups[0] = &smsc47m192_group;
 	/* Pin 110 is either in4 (+12V) or VID4 */
 	config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
-	if (!(config & 0x20)) {
-		err = sysfs_create_group(&client->dev.kobj,
-					 &smsc47m192_group_in4);
-		if (err)
-			goto exit_remove_files;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
-	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
-	return err;
-}
-
-static int smsc47m192_remove(struct i2c_client *client)
-{
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
-	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
+	if (!(config & 0x20))
+		data->groups[1] = &smsc47m192_group_in4;
 
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
-	int i, config;
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	 || !data->valid) {
-		u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
-
-		dev_dbg(&client->dev, "Starting smsc47m192 update\n");
-
-		for (i = 0; i <= 7; i++) {
-			data->in[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_IN(i));
-			data->in_min[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_IN_MIN(i));
-			data->in_max[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_IN_MAX(i));
-		}
-		for (i = 0; i < 3; i++) {
-			data->temp[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_TEMP[i]);
-			data->temp_max[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_TEMP_MAX[i]);
-			data->temp_min[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_TEMP_MIN[i]);
-		}
-		for (i = 1; i < 3; i++)
-			data->temp_offset[i] = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_TEMP_OFFSET(i));
-		/*
-		 * first offset is temp_offset[0] if SFR bit 4 is set,
-		 * temp_offset[1] otherwise
-		 */
-		if (sfr & 0x10) {
-			data->temp_offset[0] = data->temp_offset[1];
-			data->temp_offset[1] = 0;
-		} else
-			data->temp_offset[0] = 0;
-
-		data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
-			    & 0x0f;
-		config = i2c_smbus_read_byte_data(client,
-						  SMSC47M192_REG_CONFIG);
-		if (config & 0x20)
-			data->vid |= (i2c_smbus_read_byte_data(client,
-					SMSC47M192_REG_VID4) & 0x01) << 4;
-		data->alarms = i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_ALARM1) |
-			       (i2c_smbus_read_byte_data(client,
-						SMSC47M192_REG_ALARM2) << 8);
-
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
-
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id smsc47m192_id[] = {
+	{ "smsc47m192", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
 
-	return data;
-}
+static struct i2c_driver smsc47m192_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "smsc47m192",
+	},
+	.probe		= smsc47m192_probe,
+	.id_table	= smsc47m192_id,
+	.detect		= smsc47m192_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(smsc47m192_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/smsc47m1.c linux-libre-3.17-rc7-gnu/drivers/hwmon/smsc47m1.c
--- linux-libre-3.16-gnu/drivers/hwmon/smsc47m1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/smsc47m1.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,11 +142,6 @@ struct smsc47m1_sio_data {
 	u8 activate;		/* Remember initial device state */
 };
 
-
-static int __exit smsc47m1_remove(struct platform_device *pdev);
-static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
-		int init);
-
 static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg)
 {
 	return inb_p(data->addr + reg);
@@ -158,13 +153,54 @@ static inline void smsc47m1_write_value(
 	outb_p(value, data->addr + reg);
 }
 
-static struct platform_driver smsc47m1_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= DRVNAME,
-	},
-	.remove		= __exit_p(smsc47m1_remove),
-};
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+		int init)
+{
+	struct smsc47m1_data *data = dev_get_drvdata(dev);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
+		int i, fan_nr;
+		fan_nr = data->type == smsc47m2 ? 3 : 2;
+
+		for (i = 0; i < fan_nr; i++) {
+			data->fan[i] = smsc47m1_read_value(data,
+				       SMSC47M1_REG_FAN[i]);
+			data->fan_preload[i] = smsc47m1_read_value(data,
+					       SMSC47M1_REG_FAN_PRELOAD[i]);
+			data->pwm[i] = smsc47m1_read_value(data,
+				       SMSC47M1_REG_PWM[i]);
+		}
+
+		i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = i >> 6;
+
+		data->alarms = smsc47m1_read_value(data,
+			       SMSC47M1_REG_ALARM) >> 6;
+		/* Clear alarms if needed */
+		if (data->alarms)
+			smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
+
+		if (fan_nr >= 3) {
+			data->fan_div[2] = (smsc47m1_read_value(data,
+					    SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
+			data->alarms |= (smsc47m1_read_value(data,
+					 SMSC47M2_REG_ALARM6) & 0x40) >> 4;
+			/* Clear alarm if needed */
+			if (data->alarms & 0x04)
+				smsc47m1_write_value(data,
+						     SMSC47M2_REG_ALARM6,
+						     0x40);
+		}
+
+		data->last_updated = jiffies;
+	}
+
+	mutex_unlock(&data->update_lock);
+	return data;
+}
 
 static ssize_t get_fan(struct device *dev, struct device_attribute
 		       *devattr, char *buf)
@@ -811,54 +847,13 @@ static int __exit smsc47m1_remove(struct
 	return 0;
 }
 
-static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
-		int init)
-{
-	struct smsc47m1_data *data = dev_get_drvdata(dev);
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
-		int i, fan_nr;
-		fan_nr = data->type == smsc47m2 ? 3 : 2;
-
-		for (i = 0; i < fan_nr; i++) {
-			data->fan[i] = smsc47m1_read_value(data,
-				       SMSC47M1_REG_FAN[i]);
-			data->fan_preload[i] = smsc47m1_read_value(data,
-					       SMSC47M1_REG_FAN_PRELOAD[i]);
-			data->pwm[i] = smsc47m1_read_value(data,
-				       SMSC47M1_REG_PWM[i]);
-		}
-
-		i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
-		data->fan_div[0] = (i >> 4) & 0x03;
-		data->fan_div[1] = i >> 6;
-
-		data->alarms = smsc47m1_read_value(data,
-			       SMSC47M1_REG_ALARM) >> 6;
-		/* Clear alarms if needed */
-		if (data->alarms)
-			smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
-
-		if (fan_nr >= 3) {
-			data->fan_div[2] = (smsc47m1_read_value(data,
-					    SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
-			data->alarms |= (smsc47m1_read_value(data,
-					 SMSC47M2_REG_ALARM6) & 0x40) >> 4;
-			/* Clear alarm if needed */
-			if (data->alarms & 0x04)
-				smsc47m1_write_value(data,
-						     SMSC47M2_REG_ALARM6,
-						     0x40);
-		}
-
-		data->last_updated = jiffies;
-	}
-
-	mutex_unlock(&data->update_lock);
-	return data;
-}
+static struct platform_driver smsc47m1_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.remove		= __exit_p(smsc47m1_remove),
+};
 
 static int __init smsc47m1_device_add(unsigned short address,
 				      const struct smsc47m1_sio_data *sio_data)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/thmc50.c linux-libre-3.17-rc7-gnu/drivers/hwmon/thmc50.c
--- linux-libre-3.16-gnu/drivers/hwmon/thmc50.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/thmc50.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,8 @@ static const u8 THMC50_REG_TEMP_DEFAULT[
 
 /* Each client has this additional data */
 struct thmc50_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 
 	struct mutex update_lock;
 	enum chips type;
@@ -85,32 +86,47 @@ struct thmc50_data {
 	u8 alarms;
 };
 
-static int thmc50_detect(struct i2c_client *client,
-			 struct i2c_board_info *info);
-static int thmc50_probe(struct i2c_client *client,
-			const struct i2c_device_id *id);
-static int thmc50_remove(struct i2c_client *client);
-static void thmc50_init_client(struct i2c_client *client);
-static struct thmc50_data *thmc50_update_device(struct device *dev);
+static struct thmc50_data *thmc50_update_device(struct device *dev)
+{
+	struct thmc50_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
 
-static const struct i2c_device_id thmc50_id[] = {
-	{ "adm1022", adm1022 },
-	{ "thmc50", thmc50 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, thmc50_id);
+	mutex_lock(&data->update_lock);
 
-static struct i2c_driver thmc50_driver = {
-	.class = I2C_CLASS_HWMON,
-	.driver = {
-		.name = "thmc50",
-	},
-	.probe = thmc50_probe,
-	.remove = thmc50_remove,
-	.id_table = thmc50_id,
-	.detect = thmc50_detect,
-	.address_list = normal_i2c,
-};
+	if (time_after(jiffies, data->last_updated + timeout)
+	    || !data->valid) {
+
+		int temps = data->has_temp3 ? 3 : 2;
+		int i;
+		int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+
+		prog &= THMC50_REG_CONF_PROGRAMMED;
+
+		for (i = 0; i < temps; i++) {
+			data->temp_input[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP[i]);
+			data->temp_max[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP_MAX[i]);
+			data->temp_min[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP_MIN[i]);
+			data->temp_critical[i] =
+				i2c_smbus_read_byte_data(client,
+					prog ? THMC50_REG_TEMP_CRITICAL[i]
+					     : THMC50_REG_TEMP_DEFAULT[i]);
+		}
+		data->analog_out =
+		    i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
+		data->alarms =
+		    i2c_smbus_read_byte_data(client, THMC50_REG_INTR);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 static ssize_t show_analog_out(struct device *dev,
 			       struct device_attribute *attr, char *buf)
@@ -123,8 +139,8 @@ static ssize_t set_analog_out(struct dev
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thmc50_data *data = i2c_get_clientdata(client);
+	struct thmc50_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int config;
 	unsigned long tmp;
 	int err;
@@ -177,8 +193,8 @@ static ssize_t set_temp_min(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thmc50_data *data = i2c_get_clientdata(client);
+	struct thmc50_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -206,8 +222,8 @@ static ssize_t set_temp_max(struct devic
 			    const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thmc50_data *data = i2c_get_clientdata(client);
+	struct thmc50_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -355,67 +371,9 @@ static int thmc50_detect(struct i2c_clie
 	return 0;
 }
 
-static int thmc50_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	struct thmc50_data *data;
-	int err;
-
-	data = devm_kzalloc(&client->dev, sizeof(struct thmc50_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	data->type = id->driver_data;
-	mutex_init(&data->update_lock);
-
-	thmc50_init_client(client);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &thmc50_group);
-	if (err)
-		return err;
-
-	/* Register ADM1022 sysfs hooks */
-	if (data->has_temp3) {
-		err = sysfs_create_group(&client->dev.kobj, &temp3_group);
-		if (err)
-			goto exit_remove_sysfs_thmc50;
-	}
-
-	/* Register a new directory entry with module sensors */
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_sysfs;
-	}
-
-	return 0;
-
-exit_remove_sysfs:
-	if (data->has_temp3)
-		sysfs_remove_group(&client->dev.kobj, &temp3_group);
-exit_remove_sysfs_thmc50:
-	sysfs_remove_group(&client->dev.kobj, &thmc50_group);
-	return err;
-}
-
-static int thmc50_remove(struct i2c_client *client)
-{
-	struct thmc50_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &thmc50_group);
-	if (data->has_temp3)
-		sysfs_remove_group(&client->dev.kobj, &temp3_group);
-
-	return 0;
-}
-
-static void thmc50_init_client(struct i2c_client *client)
+static void thmc50_init_client(struct thmc50_data *data)
 {
-	struct thmc50_data *data = i2c_get_clientdata(client);
+	struct i2c_client *client = data->client;
 	int config;
 
 	data->analog_out = i2c_smbus_read_byte_data(client,
@@ -433,48 +391,54 @@ static void thmc50_init_client(struct i2
 	i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
 }
 
-static struct thmc50_data *thmc50_update_device(struct device *dev)
+static int thmc50_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thmc50_data *data = i2c_get_clientdata(client);
-	int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
-
-	mutex_lock(&data->update_lock);
+	struct device *dev = &client->dev;
+	struct thmc50_data *data;
+	struct device *hwmon_dev;
+	int idx = 0;
 
-	if (time_after(jiffies, data->last_updated + timeout)
-	    || !data->valid) {
+	data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-		int temps = data->has_temp3 ? 3 : 2;
-		int i;
-		int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+	data->client = client;
+	data->type = id->driver_data;
+	mutex_init(&data->update_lock);
 
-		prog &= THMC50_REG_CONF_PROGRAMMED;
+	thmc50_init_client(data);
 
-		for (i = 0; i < temps; i++) {
-			data->temp_input[i] = i2c_smbus_read_byte_data(client,
-						THMC50_REG_TEMP[i]);
-			data->temp_max[i] = i2c_smbus_read_byte_data(client,
-						THMC50_REG_TEMP_MAX[i]);
-			data->temp_min[i] = i2c_smbus_read_byte_data(client,
-						THMC50_REG_TEMP_MIN[i]);
-			data->temp_critical[i] =
-				i2c_smbus_read_byte_data(client,
-					prog ? THMC50_REG_TEMP_CRITICAL[i]
-					     : THMC50_REG_TEMP_DEFAULT[i]);
-		}
-		data->analog_out =
-		    i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
-		data->alarms =
-		    i2c_smbus_read_byte_data(client, THMC50_REG_INTR);
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
+	/* sysfs hooks */
+	data->groups[idx++] = &thmc50_group;
 
-	mutex_unlock(&data->update_lock);
+	/* Register additional ADM1022 sysfs hooks */
+	if (data->has_temp3)
+		data->groups[idx++] = &temp3_group;
 
-	return data;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
+static const struct i2c_device_id thmc50_id[] = {
+	{ "adm1022", adm1022 },
+	{ "thmc50", thmc50 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, thmc50_id);
+
+static struct i2c_driver thmc50_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name = "thmc50",
+	},
+	.probe = thmc50_probe,
+	.id_table = thmc50_id,
+	.detect = thmc50_detect,
+	.address_list = normal_i2c,
+};
+
 module_i2c_driver(thmc50_driver);
 
 MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/tmp103.c linux-libre-3.17-rc7-gnu/drivers/hwmon/tmp103.c
--- linux-libre-3.16-gnu/drivers/hwmon/tmp103.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/tmp103.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,199 @@
+/*
+ * Texas Instruments TMP103 SMBus temperature sensor driver
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * Based on:
+ * Texas Instruments TMP102 SMBus temperature sensor driver
+ *
+ * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+#define TMP103_TEMP_REG		0x00
+#define TMP103_CONF_REG		0x01
+#define TMP103_TLOW_REG		0x02
+#define TMP103_THIGH_REG	0x03
+
+#define TMP103_CONF_M0		0x01
+#define TMP103_CONF_M1		0x02
+#define TMP103_CONF_LC		0x04
+#define TMP103_CONF_FL		0x08
+#define TMP103_CONF_FH		0x10
+#define TMP103_CONF_CR0		0x20
+#define TMP103_CONF_CR1		0x40
+#define TMP103_CONF_ID		0x80
+#define TMP103_CONF_SD		(TMP103_CONF_M1)
+#define TMP103_CONF_SD_MASK	(TMP103_CONF_M0 | TMP103_CONF_M1)
+
+#define TMP103_CONFIG		(TMP103_CONF_CR1 | TMP103_CONF_M1)
+#define TMP103_CONFIG_MASK	(TMP103_CONF_CR0 | TMP103_CONF_CR1 | \
+				 TMP103_CONF_M0 | TMP103_CONF_M1)
+
+static inline int tmp103_reg_to_mc(s8 val)
+{
+	return val * 1000;
+}
+
+static inline u8 tmp103_mc_to_reg(int val)
+{
+	return DIV_ROUND_CLOSEST(val, 1000);
+}
+
+static ssize_t tmp103_show_temp(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int regval;
+	int ret;
+
+	ret = regmap_read(regmap, sda->index, &regval);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval));
+}
+
+static ssize_t tmp103_set_temp(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	long val;
+	int ret;
+
+	if (kstrtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	val = clamp_val(val, -55000, 127000);
+	ret = regmap_write(regmap, sda->index, tmp103_mc_to_reg(val));
+	return ret ? ret : count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL ,
+			  TMP103_TEMP_REG);
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp,
+			  tmp103_set_temp, TMP103_TLOW_REG);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp,
+			  tmp103_set_temp, TMP103_THIGH_REG);
+
+static struct attribute *tmp103_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(tmp103);
+
+static bool tmp103_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == TMP103_TEMP_REG;
+}
+
+static const struct regmap_config tmp103_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = TMP103_THIGH_REG,
+	.volatile_reg = tmp103_regmap_is_volatile,
+};
+
+static int tmp103_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct regmap *regmap;
+	int ret;
+
+	regmap = devm_regmap_init_i2c(client, &tmp103_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	ret = regmap_update_bits(regmap, TMP103_CONF_REG, TMP103_CONFIG_MASK,
+				 TMP103_CONFIG);
+	if (ret < 0) {
+		dev_err(&client->dev, "error writing config register\n");
+		return ret;
+	}
+
+	i2c_set_clientdata(client, regmap);
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+						      regmap, tmp103_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+#ifdef CONFIG_PM
+static int tmp103_suspend(struct device *dev)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+
+	return regmap_update_bits(regmap, TMP103_CONF_REG,
+				  TMP103_CONF_SD_MASK, 0);
+}
+
+static int tmp103_resume(struct device *dev)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+
+	return regmap_update_bits(regmap, TMP103_CONF_REG,
+				  TMP103_CONF_SD_MASK, TMP103_CONF_SD);
+}
+
+static const struct dev_pm_ops tmp103_dev_pm_ops = {
+	.suspend	= tmp103_suspend,
+	.resume		= tmp103_resume,
+};
+
+#define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops)
+#else
+#define	TMP103_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id tmp103_id[] = {
+	{ "tmp103", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tmp103_id);
+
+static struct i2c_driver tmp103_driver = {
+	.driver = {
+		.name	= "tmp103",
+		.pm	= TMP103_DEV_PM_OPS,
+	},
+	.probe		= tmp103_probe,
+	.id_table	= tmp103_id,
+};
+
+module_i2c_driver(tmp103_driver);
+
+MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
+MODULE_DESCRIPTION("Texas Instruments TMP103 temperature sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/tmp421.c linux-libre-3.17-rc7-gnu/drivers/hwmon/tmp421.c
--- linux-libre-3.16-gnu/drivers/hwmon/tmp421.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/tmp421.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,15 +13,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.
  */
 
 /*
  * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC.
- * Supported models: TMP421, TMP422, TMP423
+ * Supported models: TMP421, TMP422, TMP423, TMP441, TMP442
  */
 
 #include <linux/module.h>
@@ -39,9 +35,10 @@
 static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f,
 					     I2C_CLIENT_END };
 
-enum chips { tmp421, tmp422, tmp423 };
+enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 };
 
 /* The TMP421 registers */
+#define TMP421_STATUS_REG			0x08
 #define TMP421_CONFIG_REG_1			0x09
 #define TMP421_CONVERSION_RATE_REG		0x0B
 #define TMP421_MANUFACTURER_ID_REG		0xFE
@@ -59,11 +56,15 @@ static const u8 TMP421_TEMP_LSB[4]		= {
 #define TMP421_DEVICE_ID			0x21
 #define TMP422_DEVICE_ID			0x22
 #define TMP423_DEVICE_ID			0x23
+#define TMP441_DEVICE_ID			0x41
+#define TMP442_DEVICE_ID			0x42
 
 static const struct i2c_device_id tmp421_id[] = {
 	{ "tmp421", 2 },
 	{ "tmp422", 3 },
 	{ "tmp423", 4 },
+	{ "tmp441", 2 },
+	{ "tmp442", 3 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tmp421_id);
@@ -234,7 +235,9 @@ static int tmp421_detect(struct i2c_clie
 {
 	enum chips kind;
 	struct i2c_adapter *adapter = client->adapter;
-	const char *names[] = { "TMP421", "TMP422", "TMP423" };
+	const char * const names[] = { "TMP421", "TMP422", "TMP423",
+				       "TMP441", "TMP442" };
+	int addr = client->addr;
 	u8 reg;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -244,17 +247,37 @@ static int tmp421_detect(struct i2c_clie
 	if (reg != TMP421_MANUFACTURER_ID)
 		return -ENODEV;
 
+	reg = i2c_smbus_read_byte_data(client, TMP421_CONVERSION_RATE_REG);
+	if (reg & 0xf8)
+		return -ENODEV;
+
+	reg = i2c_smbus_read_byte_data(client, TMP421_STATUS_REG);
+	if (reg & 0x7f)
+		return -ENODEV;
+
 	reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG);
 	switch (reg) {
 	case TMP421_DEVICE_ID:
 		kind = tmp421;
 		break;
 	case TMP422_DEVICE_ID:
+		if (addr == 0x2a)
+			return -ENODEV;
 		kind = tmp422;
 		break;
 	case TMP423_DEVICE_ID:
+		if (addr != 0x4c && addr != 0x4d)
+			return -ENODEV;
 		kind = tmp423;
 		break;
+	case TMP441_DEVICE_ID:
+		kind = tmp441;
+		break;
+	case TMP442_DEVICE_ID:
+		if (addr != 0x4c && addr != 0x4d)
+			return -ENODEV;
+		kind = tmp442;
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -305,5 +328,5 @@ static struct i2c_driver tmp421_driver =
 module_i2c_driver(tmp421_driver);
 
 MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
-MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver");
+MODULE_DESCRIPTION("Texas Instruments TMP421/422/423/441/442 temperature sensor driver");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/twl4030-madc-hwmon.c linux-libre-3.17-rc7-gnu/drivers/hwmon/twl4030-madc-hwmon.c
--- linux-libre-3.16-gnu/drivers/hwmon/twl4030-madc-hwmon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/twl4030-madc-hwmon.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@ static SENSOR_DEVICE_ATTR(in11_input, S_
 static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
 static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);
 
-static struct attribute *twl4030_madc_attributes[] = {
+static struct attribute *twl4030_madc_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -91,46 +91,20 @@ static struct attribute *twl4030_madc_at
 	&sensor_dev_attr_in15_input.dev_attr.attr,
 	NULL
 };
-
-static const struct attribute_group twl4030_madc_group = {
-	.attrs = twl4030_madc_attributes,
-};
+ATTRIBUTE_GROUPS(twl4030_madc);
 
 static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
 {
-	int ret;
 	struct device *hwmon;
 
-	ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
-	if (ret)
-		goto err_sysfs;
-	hwmon = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(hwmon)) {
-		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
-		ret = PTR_ERR(hwmon);
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
-err_sysfs:
-
-	return ret;
-}
-
-static int twl4030_madc_hwmon_remove(struct platform_device *pdev)
-{
-	hwmon_device_unregister(&pdev->dev);
-	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
-
-	return 0;
+	hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
+						       "twl4030_madc", NULL,
+						       twl4030_madc_groups);
+	return PTR_ERR_OR_ZERO(hwmon);
 }
 
 static struct platform_driver twl4030_madc_hwmon_driver = {
 	.probe = twl4030_madc_hwmon_probe,
-	.remove = twl4030_madc_hwmon_remove,
 	.driver = {
 		   .name = "twl4030_madc_hwmon",
 		   .owner = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/vt1211.c linux-libre-3.17-rc7-gnu/drivers/hwmon/vt1211.c
--- linux-libre-3.16-gnu/drivers/hwmon/vt1211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/vt1211.c	2014-09-28 17:29:07.000000000 -0400
@@ -879,6 +879,9 @@ static ssize_t set_vrm(struct device *de
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 
 	return count;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/w83627hf.c linux-libre-3.17-rc7-gnu/drivers/hwmon/w83627hf.c
--- linux-libre-3.16-gnu/drivers/hwmon/w83627hf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/w83627hf.c	2014-09-28 17:29:07.000000000 -0400
@@ -820,6 +820,9 @@ store_vrm_reg(struct device *dev, struct
 	err = kstrtoul(buf, 10, &val);
 	if (err)
 		return err;
+
+	if (val > 255)
+		return -EINVAL;
 	data->vrm = val;
 
 	return count;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/w83791d.c linux-libre-3.17-rc7-gnu/drivers/hwmon/w83791d.c
--- linux-libre-3.16-gnu/drivers/hwmon/w83791d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/w83791d.c	2014-09-28 17:29:07.000000000 -0400
@@ -249,19 +249,16 @@ static u8 fan_to_reg(long rpm, int div)
  * the bottom 7 bits will always be zero
  */
 #define TEMP23_FROM_REG(val)	((val) / 128 * 500)
-#define TEMP23_TO_REG(val)	((val) <= -128000 ? 0x8000 : \
-				 (val) >= 127500 ? 0x7F80 : \
-				 (val) < 0 ? ((val) - 250) / 500 * 128 : \
-				 ((val) + 250) / 500 * 128)
+#define TEMP23_TO_REG(val)	(DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+						   127500), 500) * 128)
 
 /* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */
-#define TARGET_TEMP_TO_REG(val)		((val) < 0 ? 0 : \
-					(val) >= 127000 ? 127 : \
-					((val) + 500) / 1000)
+#define TARGET_TEMP_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
+						  1000)
 
 /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
-#define TOL_TEMP_TO_REG(val)		((val) >= 15000 ? 15 : \
-					((val) + 500) / 1000)
+#define TOL_TEMP_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, 15000), \
+						  1000)
 
 #define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
 #define BEEP_MASK_FROM_REG(val)		((val) & 0xffffff)
@@ -1184,6 +1181,9 @@ static ssize_t store_vrm_reg(struct devi
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/w83793.c linux-libre-3.17-rc7-gnu/drivers/hwmon/w83793.c
--- linux-libre-3.16-gnu/drivers/hwmon/w83793.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/w83793.c	2014-09-28 17:29:07.000000000 -0400
@@ -353,6 +353,9 @@ store_vrm(struct device *dev, struct dev
 	if (err)
 		return err;
 
+	if (val > 255)
+		return -EINVAL;
+
 	data->vrm = val;
 	return count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/w83l786ng.c linux-libre-3.17-rc7-gnu/drivers/hwmon/w83l786ng.c
--- linux-libre-3.16-gnu/drivers/hwmon/w83l786ng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/w83l786ng.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,7 +124,7 @@ DIV_TO_REG(long val)
 }
 
 struct w83l786ng_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -148,32 +148,6 @@ struct w83l786ng_data {
 	u8 tolerance[2];
 };
 
-static int w83l786ng_probe(struct i2c_client *client,
-			   const struct i2c_device_id *id);
-static int w83l786ng_detect(struct i2c_client *client,
-			    struct i2c_board_info *info);
-static int w83l786ng_remove(struct i2c_client *client);
-static void w83l786ng_init_client(struct i2c_client *client);
-static struct w83l786ng_data *w83l786ng_update_device(struct device *dev);
-
-static const struct i2c_device_id w83l786ng_id[] = {
-	{ "w83l786ng", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, w83l786ng_id);
-
-static struct i2c_driver w83l786ng_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		   .name = "w83l786ng",
-	},
-	.probe		= w83l786ng_probe,
-	.remove		= w83l786ng_remove,
-	.id_table	= w83l786ng_id,
-	.detect		= w83l786ng_detect,
-	.address_list	= normal_i2c,
-};
-
 static u8
 w83l786ng_read_value(struct i2c_client *client, u8 reg)
 {
@@ -186,6 +160,77 @@ w83l786ng_write_value(struct i2c_client
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
+static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
+{
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int i, j;
+	u8 reg_tmp, pwmcfg;
+
+	mutex_lock(&data->update_lock);
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		dev_dbg(&client->dev, "Updating w83l786ng data.\n");
+
+		/* Update the voltages measured value and limits */
+		for (i = 0; i < 3; i++) {
+			data->in[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN(i));
+			data->in_min[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN_MIN(i));
+			data->in_max[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN_MAX(i));
+		}
+
+		/* Update the fan counts and limits */
+		for (i = 0; i < 2; i++) {
+			data->fan[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_FAN(i));
+			data->fan_min[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_FAN_MIN(i));
+		}
+
+		/* Update the fan divisor */
+		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
+		data->fan_div[0] = reg_tmp & 0x07;
+		data->fan_div[1] = (reg_tmp >> 4) & 0x07;
+
+		pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
+		for (i = 0; i < 2; i++) {
+			data->pwm_mode[i] =
+			    ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
+			    ? 0 : 1;
+			data->pwm_enable[i] =
+			    ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+			data->pwm[i] =
+			    (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+			     & 0x0f) * 0x11;
+		}
+
+
+		/* Update the temperature sensors */
+		for (i = 0; i < 2; i++) {
+			for (j = 0; j < 3; j++) {
+				data->temp[i][j] = w83l786ng_read_value(client,
+				    W83L786NG_REG_TEMP[i][j]);
+			}
+		}
+
+		/* Update Smart Fan I/II tolerance */
+		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE);
+		data->tolerance[0] = reg_tmp & 0x0f;
+		data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
 static ssize_t \
@@ -207,8 +252,8 @@ store_in_##reg(struct device *dev, struc
 	       const char *buf, size_t count) \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83l786ng_data *data = i2c_get_clientdata(client); \
+	struct w83l786ng_data *data = dev_get_drvdata(dev); \
+	struct i2c_client *client = data->client; \
 	unsigned long val; \
 	int err = kstrtoul(buf, 10, &val); \
 	if (err) \
@@ -260,8 +305,8 @@ store_fan_min(struct device *dev, struct
 	      const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -298,8 +343,8 @@ store_fan_div(struct device *dev, struct
 	      const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	unsigned long min;
 	u8 tmp_fan_div;
@@ -389,8 +434,8 @@ store_temp(struct device *dev, struct de
 	    to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	int err;
 
@@ -444,8 +489,8 @@ store_pwm_mode(struct device *dev, struc
 	       const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 reg;
 	unsigned long val;
 	int err;
@@ -472,8 +517,8 @@ store_pwm(struct device *dev, struct dev
 	  const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err;
 
@@ -496,8 +541,8 @@ store_pwm_enable(struct device *dev, str
 		 const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 reg;
 	unsigned long val;
 	int err;
@@ -552,8 +597,8 @@ store_tolerance(struct device *dev, stru
 		const char *buf, size_t count)
 {
 	int nr = to_sensor_dev_attr(attr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	struct w83l786ng_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 tol_tmp, tol_mask;
 	unsigned long val;
 	int err;
@@ -608,7 +653,7 @@ static struct sensor_device_attribute sd
 #define TOLERANCE_UNIT_ATTRS(X)	\
 	&sda_tolerance[X].dev_attr.attr
 
-static struct attribute *w83l786ng_attributes[] = {
+static struct attribute *w83l786ng_attrs[] = {
 	IN_UNIT_ATTRS(0),
 	IN_UNIT_ATTRS(1),
 	IN_UNIT_ATTRS(2),
@@ -623,9 +668,7 @@ static struct attribute *w83l786ng_attri
 	NULL
 };
 
-static const struct attribute_group w83l786ng_group = {
-	.attrs = w83l786ng_attributes,
-};
+ATTRIBUTE_GROUPS(w83l786ng);
 
 static int
 w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info)
@@ -662,20 +705,33 @@ w83l786ng_detect(struct i2c_client *clie
 	return 0;
 }
 
+static void w83l786ng_init_client(struct i2c_client *client)
+{
+	u8 tmp;
+
+	if (reset)
+		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80);
+
+	/* Start monitoring */
+	tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG);
+	if (!(tmp & 0x01))
+		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01);
+}
+
 static int
 w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
 	struct w83l786ng_data *data;
-	int i, err = 0;
+	struct device *hwmon_dev;
+	int i;
 	u8 reg_tmp;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct w83l786ng_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct w83l786ng_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the chip */
@@ -692,121 +748,28 @@ w83l786ng_probe(struct i2c_client *clien
 	data->fan_div[0] = reg_tmp & 0x07;
 	data->fan_div[1] = (reg_tmp >> 4) & 0x07;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group);
-	if (err)
-		goto exit_remove;
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-	/* Unregister sysfs hooks */
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
-	return err;
-}
-
-static int
-w83l786ng_remove(struct i2c_client *client)
-{
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
-
-	return 0;
-}
-
-static void
-w83l786ng_init_client(struct i2c_client *client)
-{
-	u8 tmp;
-
-	if (reset)
-		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80);
-
-	/* Start monitoring */
-	tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG);
-	if (!(tmp & 0x01))
-		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01);
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   w83l786ng_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	int i, j;
-	u8 reg_tmp, pwmcfg;
-
-	mutex_lock(&data->update_lock);
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		dev_dbg(&client->dev, "Updating w83l786ng data.\n");
-
-		/* Update the voltages measured value and limits */
-		for (i = 0; i < 3; i++) {
-			data->in[i] = w83l786ng_read_value(client,
-			    W83L786NG_REG_IN(i));
-			data->in_min[i] = w83l786ng_read_value(client,
-			    W83L786NG_REG_IN_MIN(i));
-			data->in_max[i] = w83l786ng_read_value(client,
-			    W83L786NG_REG_IN_MAX(i));
-		}
-
-		/* Update the fan counts and limits */
-		for (i = 0; i < 2; i++) {
-			data->fan[i] = w83l786ng_read_value(client,
-			    W83L786NG_REG_FAN(i));
-			data->fan_min[i] = w83l786ng_read_value(client,
-			    W83L786NG_REG_FAN_MIN(i));
-		}
-
-		/* Update the fan divisor */
-		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
-		data->fan_div[0] = reg_tmp & 0x07;
-		data->fan_div[1] = (reg_tmp >> 4) & 0x07;
-
-		pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
-		for (i = 0; i < 2; i++) {
-			data->pwm_mode[i] =
-			    ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
-			    ? 0 : 1;
-			data->pwm_enable[i] =
-			    ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
-			data->pwm[i] =
-			    (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
-			     & 0x0f) * 0x11;
-		}
-
-
-		/* Update the temperature sensors */
-		for (i = 0; i < 2; i++) {
-			for (j = 0; j < 3; j++) {
-				data->temp[i][j] = w83l786ng_read_value(client,
-				    W83L786NG_REG_TEMP[i][j]);
-			}
-		}
-
-		/* Update Smart Fan I/II tolerance */
-		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE);
-		data->tolerance[0] = reg_tmp & 0x0f;
-		data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
-
-		data->last_updated = jiffies;
-		data->valid = 1;
-
-	}
-
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id w83l786ng_id[] = {
+	{ "w83l786ng", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, w83l786ng_id);
 
-	return data;
-}
+static struct i2c_driver w83l786ng_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		   .name = "w83l786ng",
+	},
+	.probe		= w83l786ng_probe,
+	.id_table	= w83l786ng_id,
+	.detect		= w83l786ng_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(w83l786ng_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/wm831x-hwmon.c linux-libre-3.17-rc7-gnu/drivers/hwmon/wm831x-hwmon.c
--- linux-libre-3.16-gnu/drivers/hwmon/wm831x-hwmon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/wm831x-hwmon.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,17 +29,6 @@
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/auxadc.h>
 
-struct wm831x_hwmon {
-	struct wm831x *wm831x;
-	struct device *classdev;
-};
-
-static ssize_t show_name(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "wm831x\n");
-}
-
 static const char * const input_names[] = {
 	[WM831X_AUX_SYSVDD]    = "SYSVDD",
 	[WM831X_AUX_USB]       = "USB",
@@ -50,15 +39,14 @@ static const char * const input_names[]
 	[WM831X_AUX_BATT_TEMP] = "Battery",
 };
 
-
 static ssize_t show_voltage(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	struct wm831x_hwmon *hwmon = dev_get_drvdata(dev);
+	struct wm831x *wm831x = dev_get_drvdata(dev);
 	int channel = to_sensor_dev_attr(attr)->index;
 	int ret;
 
-	ret = wm831x_auxadc_read_uv(hwmon->wm831x, channel);
+	ret = wm831x_auxadc_read_uv(wm831x, channel);
 	if (ret < 0)
 		return ret;
 
@@ -68,11 +56,11 @@ static ssize_t show_voltage(struct devic
 static ssize_t show_chip_temp(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
-	struct wm831x_hwmon *hwmon = dev_get_drvdata(dev);
+	struct wm831x *wm831x = dev_get_drvdata(dev);
 	int channel = to_sensor_dev_attr(attr)->index;
 	int ret;
 
-	ret = wm831x_auxadc_read(hwmon->wm831x, channel);
+	ret = wm831x_auxadc_read(wm831x, channel);
 	if (ret < 0)
 		return ret;
 
@@ -100,8 +88,6 @@ static ssize_t show_label(struct device
 	static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label,	\
 				  NULL, name)
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
 WM831X_VOLTAGE(0, WM831X_AUX_AUX1);
 WM831X_VOLTAGE(1, WM831X_AUX_AUX2);
 WM831X_VOLTAGE(2, WM831X_AUX_AUX3);
@@ -126,9 +112,7 @@ static SENSOR_DEVICE_ATTR(temp2_input, S
 static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL,
 			  WM831X_AUX_BATT_TEMP);
 
-static struct attribute *wm831x_attributes[] = {
-	&dev_attr_name.attr,
-
+static struct attribute *wm831x_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -153,55 +137,21 @@ static struct attribute *wm831x_attribut
 	NULL
 };
 
-static const struct attribute_group wm831x_attr_group = {
-	.attrs	= wm831x_attributes,
-};
+ATTRIBUTE_GROUPS(wm831x);
 
 static int wm831x_hwmon_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_hwmon *hwmon;
-	int ret;
-
-	hwmon = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_hwmon),
-			     GFP_KERNEL);
-	if (!hwmon)
-		return -ENOMEM;
-
-	hwmon->wm831x = wm831x;
-
-	ret = sysfs_create_group(&pdev->dev.kobj, &wm831x_attr_group);
-	if (ret)
-		return ret;
-
-	hwmon->classdev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(hwmon->classdev)) {
-		ret = PTR_ERR(hwmon->classdev);
-		goto err_sysfs;
-	}
-
-	platform_set_drvdata(pdev, hwmon);
-
-	return 0;
-
-err_sysfs:
-	sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group);
-	return ret;
-}
-
-static int wm831x_hwmon_remove(struct platform_device *pdev)
-{
-	struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(hwmon->classdev);
-	sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group);
+	struct device *hwmon_dev;
 
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm831x",
+							   wm831x,
+							   wm831x_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static struct platform_driver wm831x_hwmon_driver = {
 	.probe = wm831x_hwmon_probe,
-	.remove = wm831x_hwmon_remove,
 	.driver = {
 		.name = "wm831x-hwmon",
 		.owner = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwmon/wm8350-hwmon.c linux-libre-3.17-rc7-gnu/drivers/hwmon/wm8350-hwmon.c
--- linux-libre-3.16-gnu/drivers/hwmon/wm8350-hwmon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwmon/wm8350-hwmon.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,19 +28,12 @@
 #include <linux/mfd/wm8350/core.h>
 #include <linux/mfd/wm8350/comparator.h>
 
-static ssize_t show_name(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "wm8350\n");
-}
-
 static const char * const input_names[] = {
 	[WM8350_AUXADC_USB]  = "USB",
 	[WM8350_AUXADC_LINE] = "Line",
 	[WM8350_AUXADC_BATT] = "Battery",
 };
 
-
 static ssize_t show_voltage(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -68,15 +61,11 @@ static ssize_t show_label(struct device
 	static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label,	\
 				  NULL, name)
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
 WM8350_NAMED_VOLTAGE(0, WM8350_AUXADC_USB);
 WM8350_NAMED_VOLTAGE(1, WM8350_AUXADC_BATT);
 WM8350_NAMED_VOLTAGE(2, WM8350_AUXADC_LINE);
 
-static struct attribute *wm8350_attributes[] = {
-	&dev_attr_name.attr,
-
+static struct attribute *wm8350_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_label.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -87,46 +76,21 @@ static struct attribute *wm8350_attribut
 	NULL,
 };
 
-static const struct attribute_group wm8350_attr_group = {
-	.attrs	= wm8350_attributes,
-};
+ATTRIBUTE_GROUPS(wm8350);
 
 static int wm8350_hwmon_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group);
-	if (ret)
-		goto err;
-
-	wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(wm8350->hwmon.classdev)) {
-		ret = PTR_ERR(wm8350->hwmon.classdev);
-		goto err_group;
-	}
-
-	return 0;
-
-err_group:
-	sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
-err:
-	return ret;
-}
-
-static int wm8350_hwmon_remove(struct platform_device *pdev)
-{
-	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(wm8350->hwmon.classdev);
-	sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
+	struct device *hwmon_dev;
 
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm8350",
+							   wm8350,
+							   wm8350_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static struct platform_driver wm8350_hwmon_driver = {
 	.probe = wm8350_hwmon_probe,
-	.remove = wm8350_hwmon_remove,
 	.driver = {
 		.name = "wm8350-hwmon",
 		.owner = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwspinlock/Kconfig linux-libre-3.17-rc7-gnu/drivers/hwspinlock/Kconfig
--- linux-libre-3.16-gnu/drivers/hwspinlock/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwspinlock/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@ menu "Hardware Spinlock drivers"
 
 config HWSPINLOCK_OMAP
 	tristate "OMAP Hardware Spinlock device"
-	depends on ARCH_OMAP4 || SOC_OMAP5
+	depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX
 	select HWSPINLOCK
 	help
 	  Say y here to support the OMAP Hardware Spinlock device (firstly
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/hwspinlock/omap_hwspinlock.c linux-libre-3.17-rc7-gnu/drivers/hwspinlock/omap_hwspinlock.c
--- linux-libre-3.16-gnu/drivers/hwspinlock/omap_hwspinlock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/hwspinlock/omap_hwspinlock.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,10 +98,29 @@ static int omap_hwspinlock_probe(struct
 	if (!io_base)
 		return -ENOMEM;
 
+	/*
+	 * make sure the module is enabled and clocked before reading
+	 * the module SYSSTATUS register
+	 */
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(&pdev->dev);
+		goto iounmap_base;
+	}
+
 	/* Determine number of locks */
 	i = readl(io_base + SYSSTATUS_OFFSET);
 	i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET;
 
+	/*
+	 * runtime PM will make sure the clock of this module is
+	 * enabled again iff at least one lock is requested
+	 */
+	ret = pm_runtime_put(&pdev->dev);
+	if (ret < 0)
+		goto iounmap_base;
+
 	/* one of the four lsb's must be set, and nothing else */
 	if (hweight_long(i & 0xf) != 1 || i > 8) {
 		ret = -EINVAL;
@@ -121,12 +140,6 @@ static int omap_hwspinlock_probe(struct
 	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
 		hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
 
-	/*
-	 * runtime PM will make sure the clock of this module is
-	 * enabled iff at least one lock is requested
-	 */
-	pm_runtime_enable(&pdev->dev);
-
 	ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
 						pdata->base_id, num_locks);
 	if (ret)
@@ -135,9 +148,9 @@ static int omap_hwspinlock_probe(struct
 	return 0;
 
 reg_fail:
-	pm_runtime_disable(&pdev->dev);
 	kfree(bank);
 iounmap_base:
+	pm_runtime_disable(&pdev->dev);
 	iounmap(io_base);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-at91.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-at91.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-at91.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-at91.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,6 +101,7 @@ struct at91_twi_dev {
 	unsigned twi_cwgr_reg;
 	struct at91_twi_pdata *pdata;
 	bool use_dma;
+	bool recv_len_abort;
 	struct at91_twi_dma dma;
 };
 
@@ -210,7 +211,7 @@ static void at91_twi_write_data_dma_call
 	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
 
 	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-			 dev->buf_len, DMA_MEM_TO_DEV);
+			 dev->buf_len, DMA_TO_DEVICE);
 
 	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
 }
@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(stru
 	*dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
 	--dev->buf_len;
 
+	/* return if aborting, we only needed to read RHR to clear RXRDY*/
+	if (dev->recv_len_abort)
+		return;
+
 	/* handle I2C_SMBUS_BLOCK_DATA */
 	if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
-		dev->msg->flags &= ~I2C_M_RECV_LEN;
-		dev->buf_len += *dev->buf;
-		dev->msg->len = dev->buf_len + 1;
-		dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
+		/* ensure length byte is a valid value */
+		if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
+			dev->msg->flags &= ~I2C_M_RECV_LEN;
+			dev->buf_len += *dev->buf;
+			dev->msg->len = dev->buf_len + 1;
+			dev_dbg(dev->dev, "received block length %d\n",
+					 dev->buf_len);
+		} else {
+			/* abort and send the stop by reading one more byte */
+			dev->recv_len_abort = true;
+			dev->buf_len = 1;
+		}
 	}
 
 	/* send stop if second but last byte has been read */
@@ -289,7 +302,7 @@ static void at91_twi_read_data_dma_callb
 	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
 
 	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-			 dev->buf_len, DMA_DEV_TO_MEM);
+			 dev->buf_len, DMA_FROM_DEVICE);
 
 	/* The last two bytes have to be read without using dma */
 	dev->buf += dev->buf_len - 2;
@@ -421,8 +434,8 @@ static int at91_do_twi_transfer(struct a
 		}
 	}
 
-	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-							dev->adapter.timeout);
+	ret = wait_for_completion_io_timeout(&dev->cmd_complete,
+					     dev->adapter.timeout);
 	if (ret == 0) {
 		dev_err(dev->dev, "controller timed out\n");
 		at91_init_twi_bus(dev);
@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct a
 		ret = -EIO;
 		goto error;
 	}
+	if (dev->recv_len_abort) {
+		dev_err(dev->dev, "invalid smbus block length recvd\n");
+		ret = -EPROTO;
+		goto error;
+	}
+
 	dev_dbg(dev->dev, "transfer complete\n");
 
 	return 0;
@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adap
 	dev->buf_len = m_start->len;
 	dev->buf = m_start->buf;
 	dev->msg = m_start;
+	dev->recv_len_abort = false;
 
 	ret = at91_do_twi_transfer(dev);
 
@@ -768,7 +788,7 @@ static int at91_twi_probe(struct platfor
 	snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
 	i2c_set_adapdata(&dev->adapter, dev);
 	dev->adapter.owner = THIS_MODULE;
-	dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	dev->adapter.class = I2C_CLASS_DEPRECATED;
 	dev->adapter.algo = &at91_twi_algorithm;
 	dev->adapter.dev.parent = dev->dev;
 	dev->adapter.nr = pdev->id;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-bcm2835.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-bcm2835.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-bcm2835.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-bcm2835.c	2014-09-28 17:29:07.000000000 -0400
@@ -277,7 +277,7 @@ static int bcm2835_i2c_probe(struct plat
 	adap = &i2c_dev->adapter;
 	i2c_set_adapdata(adap, i2c_dev);
 	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
 	adap->algo = &bcm2835_i2c_algo;
 	adap->dev.parent = &pdev->dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-bfin-twi.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-bfin-twi.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2014-09-28 17:29:07.000000000 -0400
@@ -648,7 +648,7 @@ static int i2c_bfin_twi_probe(struct pla
 	strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
 	p_adap->algo = &bfin_twi_algorithm;
 	p_adap->algo_data = iface;
-	p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
+	p_adap->class = I2C_CLASS_DEPRECATED;
 	p_adap->dev.parent = &pdev->dev;
 	p_adap->timeout = 5 * HZ;
 	p_adap->retries = 3;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-cros-ec-tunnel.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-cros-ec-tunnel.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-cros-ec-tunnel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-cros-ec-tunnel.c	2014-09-28 17:29:07.000000000 -0400
@@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapte
 	u8 *request = NULL;
 	u8 *response = NULL;
 	int result;
+	struct cros_ec_command msg;
 
 	request_len = ec_i2c_count_message(i2c_msgs, num);
 	if (request_len < 0) {
@@ -218,10 +219,16 @@ static int ec_i2c_xfer(struct i2c_adapte
 	}
 
 	ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
-	result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
-					   request, request_len,
-					   response, response_len);
-	if (result)
+
+	msg.version = 0;
+	msg.command = EC_CMD_I2C_PASSTHRU;
+	msg.outdata = request;
+	msg.outsize = request_len;
+	msg.indata = response;
+	msg.insize = response_len;
+
+	result = bus->ec->cmd_xfer(bus->ec, &msg);
+	if (result < 0)
 		goto exit;
 
 	result = ec_i2c_parse_response(response, i2c_msgs, &num);
@@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_
 	u32 remote_bus;
 	int err;
 
-	if (!ec->command_sendrecv) {
+	if (!ec->cmd_xfer) {
 		dev_err(dev, "Missing sendrecv\n");
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-davinci.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-davinci.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-davinci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-davinci.c	2014-09-28 17:29:07.000000000 -0400
@@ -712,7 +712,7 @@ static int davinci_i2c_probe(struct plat
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
 	adap->algo = &i2c_davinci_algo;
 	adap->dev.parent = &pdev->dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	2014-09-28 17:29:07.000000000 -0400
@@ -188,6 +188,7 @@ static struct  dw_pci_controller  dw_pci
 		.scl_sda_cfg = &hsw_config,
 	},
 };
+
 static struct i2c_algorithm i2c_dw_algo = {
 	.master_xfer	= i2c_dw_xfer,
 	.functionality	= i2c_dw_func,
@@ -350,6 +351,14 @@ static const struct pci_device_id i2_des
 	/* Haswell */
 	{ PCI_VDEVICE(INTEL, 0x9c61), haswell },
 	{ PCI_VDEVICE(INTEL, 0x9c62), haswell },
+	/* Braswell / Cherrytrail */
+	{ PCI_VDEVICE(INTEL, 0x22C1), baytrail,},
+	{ PCI_VDEVICE(INTEL, 0x22C2), baytrail },
+	{ PCI_VDEVICE(INTEL, 0x22C3), baytrail },
+	{ PCI_VDEVICE(INTEL, 0x22C4), baytrail },
+	{ PCI_VDEVICE(INTEL, 0x22C5), baytrail },
+	{ PCI_VDEVICE(INTEL, 0x22C6), baytrail },
+	{ PCI_VDEVICE(INTEL, 0x22C7), baytrail },
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-designware-platdrv.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-designware-platdrv.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,6 +106,7 @@ static const struct acpi_device_id dw_i2
 	{ "INT3432", 0 },
 	{ "INT3433", 0 },
 	{ "80860F41", 0 },
+	{ "808622C1", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -202,7 +203,7 @@ static int dw_i2c_probe(struct platform_
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
 			sizeof(adap->name));
 	adap->algo = &i2c_dw_algo;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-efm32.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-efm32.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-efm32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-efm32.c	2014-09-28 17:29:07.000000000 -0400
@@ -370,7 +370,13 @@ static int efm32_i2c_probe(struct platfo
 		return ret;
 	}
 
-	ret = of_property_read_u32(np, "efm32,location", &location);
+
+	ret = of_property_read_u32(np, "energymicro,location", &location);
+
+	if (ret)
+		/* fall back to wrongly namespaced property */
+		ret = of_property_read_u32(np, "efm32,location", &location);
+
 	if (!ret) {
 		dev_dbg(&pdev->dev, "using location %u\n", location);
 	} else {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-exynos5.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-exynos5.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-exynos5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-exynos5.c	2014-09-28 17:29:07.000000000 -0400
@@ -405,7 +405,6 @@ static irqreturn_t exynos5_i2c_irq(int i
 
 	int_status = readl(i2c->regs + HSI2C_INT_STATUS);
 	writel(int_status, i2c->regs + HSI2C_INT_STATUS);
-	fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
 
 	/* handle interrupt related to the transfer status */
 	if (int_status & HSI2C_INT_I2C) {
@@ -526,7 +525,7 @@ static void exynos5_i2c_message_start(st
 	if (i2c->msg->flags & I2C_M_RD) {
 		i2c_ctl |= HSI2C_RXCHON;
 
-		i2c_auto_conf = HSI2C_READ_WRITE;
+		i2c_auto_conf |= HSI2C_READ_WRITE;
 
 		trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
 			(i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
@@ -549,7 +548,6 @@ static void exynos5_i2c_message_start(st
 	writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
 	writel(i2c_ctl, i2c->regs + HSI2C_CTL);
 
-
 	/*
 	 * Enable interrupts before starting the transfer so that we don't
 	 * miss any INT_I2C interrupts.
@@ -789,8 +787,16 @@ static int exynos5_i2c_resume_noirq(stru
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(exynos5_i2c_dev_pm_ops, exynos5_i2c_suspend_noirq,
-			 exynos5_i2c_resume_noirq);
+static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+	.suspend_noirq = exynos5_i2c_suspend_noirq,
+	.resume_noirq = exynos5_i2c_resume_noirq,
+	.freeze_noirq = exynos5_i2c_suspend_noirq,
+	.thaw_noirq = exynos5_i2c_resume_noirq,
+	.poweroff_noirq = exynos5_i2c_suspend_noirq,
+	.restore_noirq = exynos5_i2c_resume_noirq,
+#endif
+};
 
 static struct platform_driver exynos5_i2c_driver = {
 	.probe		= exynos5_i2c_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-gpio.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-gpio.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -238,12 +238,10 @@ static int i2c_gpio_probe(struct platfor
 static int i2c_gpio_remove(struct platform_device *pdev)
 {
 	struct i2c_gpio_private_data *priv;
-	struct i2c_gpio_platform_data *pdata;
 	struct i2c_adapter *adap;
 
 	priv = platform_get_drvdata(pdev);
 	adap = &priv->adap;
-	pdata = &priv->pdata;
 
 	i2c_del_adapter(adap);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-i801.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-i801.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-i801.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-i801.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,57 +22,58 @@
 */
 
 /*
-  Supports the following Intel I/O Controller Hubs (ICH):
-
-                                  I/O                     Block   I2C
-                                  region  SMBus   Block   proc.   block
-  Chip name             PCI ID    size    PEC     buffer  call    read
-  ----------------------------------------------------------------------
-  82801AA  (ICH)        0x2413     16      no      no      no      no
-  82801AB  (ICH0)       0x2423     16      no      no      no      no
-  82801BA  (ICH2)       0x2443     16      no      no      no      no
-  82801CA  (ICH3)       0x2483     32     soft     no      no      no
-  82801DB  (ICH4)       0x24c3     32     hard     yes     no      no
-  82801E   (ICH5)       0x24d3     32     hard     yes     yes     yes
-  6300ESB               0x25a4     32     hard     yes     yes     yes
-  82801F   (ICH6)       0x266a     32     hard     yes     yes     yes
-  6310ESB/6320ESB       0x269b     32     hard     yes     yes     yes
-  82801G   (ICH7)       0x27da     32     hard     yes     yes     yes
-  82801H   (ICH8)       0x283e     32     hard     yes     yes     yes
-  82801I   (ICH9)       0x2930     32     hard     yes     yes     yes
-  EP80579 (Tolapai)     0x5032     32     hard     yes     yes     yes
-  ICH10                 0x3a30     32     hard     yes     yes     yes
-  ICH10                 0x3a60     32     hard     yes     yes     yes
-  5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes
-  6 Series (PCH)        0x1c22     32     hard     yes     yes     yes
-  Patsburg (PCH)        0x1d22     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d70     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d71     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
-  DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
-  Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
-  Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
-  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes
-  Avoton (SOC)          0x1f3c     32     hard     yes     yes     yes
-  Wellsburg (PCH)       0x8d22     32     hard     yes     yes     yes
-  Wellsburg (PCH) MS    0x8d7d     32     hard     yes     yes     yes
-  Wellsburg (PCH) MS    0x8d7e     32     hard     yes     yes     yes
-  Wellsburg (PCH) MS    0x8d7f     32     hard     yes     yes     yes
-  Coleto Creek (PCH)    0x23b0     32     hard     yes     yes     yes
-  Wildcat Point-LP (PCH)   0x9ca2     32     hard     yes     yes     yes
-  BayTrail (SOC)        0x0f12     32     hard     yes     yes     yes
-
-  Features supported by this driver:
-  Software PEC                     no
-  Hardware PEC                     yes
-  Block buffer                     yes
-  Block process call transaction   no
-  I2C block read transaction       yes  (doesn't use the block buffer)
-  Slave mode                       no
-  Interrupt processing             yes
-
-  See the file Documentation/i2c/busses/i2c-i801 for details.
-*/
+ * Supports the following Intel I/O Controller Hubs (ICH):
+ *
+ *					I/O			Block	I2C
+ *					region	SMBus	Block	proc.	block
+ * Chip name			PCI ID	size	PEC	buffer	call	read
+ * ---------------------------------------------------------------------------
+ * 82801AA (ICH)		0x2413	16	no	no	no	no
+ * 82801AB (ICH0)		0x2423	16	no	no	no	no
+ * 82801BA (ICH2)		0x2443	16	no	no	no	no
+ * 82801CA (ICH3)		0x2483	32	soft	no	no	no
+ * 82801DB (ICH4)		0x24c3	32	hard	yes	no	no
+ * 82801E (ICH5)		0x24d3	32	hard	yes	yes	yes
+ * 6300ESB			0x25a4	32	hard	yes	yes	yes
+ * 82801F (ICH6)		0x266a	32	hard	yes	yes	yes
+ * 6310ESB/6320ESB		0x269b	32	hard	yes	yes	yes
+ * 82801G (ICH7)		0x27da	32	hard	yes	yes	yes
+ * 82801H (ICH8)		0x283e	32	hard	yes	yes	yes
+ * 82801I (ICH9)		0x2930	32	hard	yes	yes	yes
+ * EP80579 (Tolapai)		0x5032	32	hard	yes	yes	yes
+ * ICH10			0x3a30	32	hard	yes	yes	yes
+ * ICH10			0x3a60	32	hard	yes	yes	yes
+ * 5/3400 Series (PCH)		0x3b30	32	hard	yes	yes	yes
+ * 6 Series (PCH)		0x1c22	32	hard	yes	yes	yes
+ * Patsburg (PCH)		0x1d22	32	hard	yes	yes	yes
+ * Patsburg (PCH) IDF		0x1d70	32	hard	yes	yes	yes
+ * Patsburg (PCH) IDF		0x1d71	32	hard	yes	yes	yes
+ * Patsburg (PCH) IDF		0x1d72	32	hard	yes	yes	yes
+ * DH89xxCC (PCH)		0x2330	32	hard	yes	yes	yes
+ * Panther Point (PCH)		0x1e22	32	hard	yes	yes	yes
+ * Lynx Point (PCH)		0x8c22	32	hard	yes	yes	yes
+ * Lynx Point-LP (PCH)		0x9c22	32	hard	yes	yes	yes
+ * Avoton (SOC)			0x1f3c	32	hard	yes	yes	yes
+ * Wellsburg (PCH)		0x8d22	32	hard	yes	yes	yes
+ * Wellsburg (PCH) MS		0x8d7d	32	hard	yes	yes	yes
+ * Wellsburg (PCH) MS		0x8d7e	32	hard	yes	yes	yes
+ * Wellsburg (PCH) MS		0x8d7f	32	hard	yes	yes	yes
+ * Coleto Creek (PCH)		0x23b0	32	hard	yes	yes	yes
+ * Wildcat Point (PCH)		0x8ca2	32	hard	yes	yes	yes
+ * Wildcat Point-LP (PCH)	0x9ca2	32	hard	yes	yes	yes
+ * BayTrail (SOC)		0x0f12	32	hard	yes	yes	yes
+ *
+ * Features supported by this driver:
+ * Software PEC				no
+ * Hardware PEC				yes
+ * Block buffer				yes
+ * Block process call transaction	no
+ * I2C block read transaction		yes (doesn't use the block buffer)
+ * Slave mode				no
+ * Interrupt processing			yes
+ *
+ * See the file Documentation/i2c/busses/i2c-i801 for details.
+ */
 
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -162,24 +163,26 @@
 				 STATUS_ERROR_FLAGS)
 
 /* Older devices have their ID defined in <linux/pci_ids.h> */
-#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS	0x0f12
-#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS	0x1c22
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS	0x1d22
+#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS		0x0f12
+#define PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS		0x2292
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS		0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS		0x1d22
 /* Patsburg also has three 'Integrated Device Function' SMBus controllers */
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0	0x1d70
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1	0x1d71
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2	0x1d72
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS	0x1e22
-#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS	0x1f3c
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330
-#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS	0x23b0
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS	0x8d22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0	0x8d7d
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1	0x8d7e
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2	0x8d7f
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS	0x9c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0		0x1d70
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1		0x1d71
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2		0x1d72
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS		0x1e22
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS		0x1f3c
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS		0x2330
+#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS		0x23b0
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS		0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS		0x8c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS		0x8ca2
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS		0x8d22
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0		0x8d7d
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1		0x8d7e
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2		0x8d7f
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS		0x9c22
 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS	0x9ca2
 
 struct i801_mux_config {
@@ -823,8 +826,10 @@ static const struct pci_device_id i801_i
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) },
 	{ 0, }
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-imx.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-imx.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -735,10 +735,7 @@ static int i2c_imx_probe(struct platform
 	clk_disable_unprepare(i2c_imx->clk);
 
 	dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
-	dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",
-		res->start, res->end);
-	dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",
-		resource_size(res), res->start);
+	dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
 	dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
 		i2c_imx->adapter.name);
 	dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-ismt.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-ismt.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-ismt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-ismt.c	2014-09-28 17:29:07.000000000 -0400
@@ -497,7 +497,7 @@ static int ismt_access(struct i2c_adapte
 			desc->wr_len_cmd = dma_size;
 			desc->control |= ISMT_DESC_BLK;
 			priv->dma_buffer[0] = command;
-			memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
+			memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
 		} else {
 			/* Block Read */
 			dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA:  READ\n");
@@ -525,7 +525,7 @@ static int ismt_access(struct i2c_adapte
 			desc->wr_len_cmd = dma_size;
 			desc->control |= ISMT_DESC_I2C;
 			priv->dma_buffer[0] = command;
-			memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
+			memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
 		} else {
 			/* i2c Block Read */
 			dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA:  READ\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mpc.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mpc.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -341,8 +341,7 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void
 			iounmap(reg);
 		}
 	}
-	if (node)
-		of_node_put(node);
+	of_node_put(node);
 
 	return val;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mv64xxx.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mv64xxx.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -746,8 +746,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_dat
 	}
 	tclk = clk_get_rate(drv_data->clk);
 
-	rc = of_property_read_u32(np, "clock-frequency", &bus_freq);
-	if (rc)
+	if (of_property_read_u32(np, "clock-frequency", &bus_freq))
 		bus_freq = 100000; /* 100kHz by default */
 
 	if (!mv64xxx_find_baud_factors(bus_freq, tclk,
@@ -863,7 +862,7 @@ mv64xxx_i2c_probe(struct platform_device
 	drv_data->adapter.dev.parent = &pd->dev;
 	drv_data->adapter.algo = &mv64xxx_i2c_algo;
 	drv_data->adapter.owner = THIS_MODULE;
-	drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
+	drv_data->adapter.class = I2C_CLASS_DEPRECATED;
 	drv_data->adapter.nr = pd->id;
 	drv_data->adapter.dev.of_node = pd->dev.of_node;
 	platform_set_drvdata(pd, drv_data);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mxs.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mxs.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-mxs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-mxs.c	2014-09-28 17:29:07.000000000 -0400
@@ -429,7 +429,7 @@ static int mxs_i2c_pio_setup_xfer(struct
 		ret = mxs_i2c_pio_wait_xfer_end(i2c);
 		if (ret) {
 			dev_err(i2c->dev,
-				"PIO: Failed to send SELECT command!\n");
+				"PIO: Failed to send READ command!\n");
 			goto cleanup;
 		}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-nomadik.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-nomadik.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-nomadik.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-nomadik.c	2014-09-28 17:29:07.000000000 -0400
@@ -1032,10 +1032,10 @@ static int nmk_i2c_probe(struct amba_dev
 	adap = &dev->adap;
 	adap->dev.of_node = np;
 	adap->dev.parent = &adev->dev;
-	adap->owner	= THIS_MODULE;
-	adap->class	= I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
-	adap->algo	= &nmk_i2c_algo;
-	adap->timeout	= msecs_to_jiffies(dev->timeout);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_DEPRECATED;
+	adap->algo = &nmk_i2c_algo;
+	adap->timeout = msecs_to_jiffies(dev->timeout);
 	snprintf(adap->name, sizeof(adap->name),
 		 "Nomadik I2C at %pR", &adev->res);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-ocores.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-ocores.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-ocores.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-ocores.c	2014-09-28 17:29:07.000000000 -0400
@@ -239,15 +239,15 @@ static u32 ocores_func(struct i2c_adapte
 }
 
 static const struct i2c_algorithm ocores_algorithm = {
-	.master_xfer	= ocores_xfer,
-	.functionality	= ocores_func,
+	.master_xfer = ocores_xfer,
+	.functionality = ocores_func,
 };
 
 static struct i2c_adapter ocores_adapter = {
-	.owner		= THIS_MODULE,
-	.name		= "i2c-ocores",
-	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
-	.algo		= &ocores_algorithm,
+	.owner = THIS_MODULE,
+	.name = "i2c-ocores",
+	.class = I2C_CLASS_DEPRECATED,
+	.algo = &ocores_algorithm,
 };
 
 static const struct of_device_id ocores_i2c_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-omap.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-omap.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-omap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-omap.c	2014-09-28 17:29:07.000000000 -0400
@@ -1236,7 +1236,7 @@ omap_i2c_probe(struct platform_device *p
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
 	adap->algo = &omap_i2c_algo;
 	adap->dev.parent = &pdev->dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-qup.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-qup.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-qup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-qup.c	2014-09-28 17:29:07.000000000 -0400
@@ -633,13 +633,17 @@ static int qup_i2c_probe(struct platform
 	 * associated with each byte written/received
 	 */
 	size = QUP_OUTPUT_BLOCK_SIZE(io_mode);
-	if (size >= ARRAY_SIZE(blk_sizes))
-		return -EIO;
+	if (size >= ARRAY_SIZE(blk_sizes)) {
+		ret = -EIO;
+		goto fail;
+	}
 	qup->out_blk_sz = blk_sizes[size] / 2;
 
 	size = QUP_INPUT_BLOCK_SIZE(io_mode);
-	if (size >= ARRAY_SIZE(blk_sizes))
-		return -EIO;
+	if (size >= ARRAY_SIZE(blk_sizes)) {
+		ret = -EIO;
+		goto fail;
+	}
 	qup->in_blk_sz = blk_sizes[size] / 2;
 
 	size = QUP_OUTPUT_FIFO_SIZE(io_mode);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-rcar.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-rcar.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-rcar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-rcar.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 /* register offsets */
 #define ICSCR	0x00	/* slave ctrl */
@@ -75,8 +76,8 @@
 #define RCAR_IRQ_RECV	(MNR | MAL | MST | MAT | MDR)
 #define RCAR_IRQ_STOP	(MST)
 
-#define RCAR_IRQ_ACK_SEND	(~(MAT | MDE))
-#define RCAR_IRQ_ACK_RECV	(~(MAT | MDR))
+#define RCAR_IRQ_ACK_SEND	(~(MAT | MDE) & 0xFF)
+#define RCAR_IRQ_ACK_RECV	(~(MAT | MDR) & 0xFF)
 
 #define ID_LAST_MSG	(1 << 0)
 #define ID_IOERROR	(1 << 1)
@@ -95,6 +96,7 @@ struct rcar_i2c_priv {
 	struct i2c_msg	*msg;
 	struct clk *clk;
 
+	spinlock_t lock;
 	wait_queue_head_t wait;
 
 	int pos;
@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq,
 	struct rcar_i2c_priv *priv = ptr;
 	u32 msr;
 
+	/*-------------- spin lock -----------------*/
+	spin_lock(&priv->lock);
+
 	msr = rcar_i2c_read(priv, ICMSR);
 
+	/* Only handle interrupts that are currently enabled */
+	msr &= rcar_i2c_read(priv, ICMIER);
+
 	/* Arbitration lost */
 	if (msr & MAL) {
 		rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
 		goto out;
 	}
 
-	/* Stop */
-	if (msr & MST) {
-		rcar_i2c_flags_set(priv, ID_DONE);
-		goto out;
-	}
-
 	/* Nack */
 	if (msr & MNR) {
 		/* go to stop phase */
@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq,
 		goto out;
 	}
 
+	/* Stop */
+	if (msr & MST) {
+		rcar_i2c_flags_set(priv, ID_DONE);
+		goto out;
+	}
+
 	if (rcar_i2c_is_recv(priv))
 		rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
 	else
@@ -400,6 +408,9 @@ out:
 		wake_up(&priv->wait);
 	}
 
+	spin_unlock(&priv->lock);
+	/*-------------- spin unlock -----------------*/
+
 	return IRQ_HANDLED;
 }
 
@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i
 {
 	struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
 	struct device *dev = rcar_i2c_priv_to_dev(priv);
+	unsigned long flags;
 	int i, ret, timeout;
 
 	pm_runtime_get_sync(dev);
 
+	/*-------------- spin lock -----------------*/
+	spin_lock_irqsave(&priv->lock, flags);
+
 	rcar_i2c_init(priv);
 	/* start clock */
 	rcar_i2c_write(priv, ICCCR, priv->icccr);
 
+	spin_unlock_irqrestore(&priv->lock, flags);
+	/*-------------- spin unlock -----------------*/
+
 	ret = rcar_i2c_bus_barrier(priv);
 	if (ret < 0)
 		goto out;
@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i
 			break;
 		}
 
+		/*-------------- spin lock -----------------*/
+		spin_lock_irqsave(&priv->lock, flags);
+
 		/* init each data */
 		priv->msg	= &msgs[i];
 		priv->pos	= 0;
@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i
 
 		ret = rcar_i2c_prepare_msg(priv);
 
+		spin_unlock_irqrestore(&priv->lock, flags);
+		/*-------------- spin unlock -----------------*/
+
 		if (ret < 0)
 			break;
 
@@ -540,14 +564,15 @@ static int rcar_i2c_probe(struct platfor
 
 	irq = platform_get_irq(pdev, 0);
 	init_waitqueue_head(&priv->wait);
+	spin_lock_init(&priv->lock);
 
-	adap			= &priv->adap;
-	adap->nr		= pdev->id;
-	adap->algo		= &rcar_i2c_algo;
-	adap->class		= I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
-	adap->retries		= 3;
-	adap->dev.parent	= dev;
-	adap->dev.of_node	= dev->of_node;
+	adap = &priv->adap;
+	adap->nr = pdev->id;
+	adap->algo = &rcar_i2c_algo;
+	adap->class = I2C_CLASS_DEPRECATED;
+	adap->retries = 3;
+	adap->dev.parent = dev;
+	adap->dev.of_node = dev->of_node;
 	i2c_set_adapdata(adap, priv);
 	strlcpy(adap->name, pdev->name, sizeof(adap->name));
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-rk3x.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-rk3x.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-rk3x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-rk3x.c	2014-09-28 17:29:07.000000000 -0400
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct
 	/* ack interrupt */
 	i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+	/* Can only handle a maximum of 32 bytes at a time */
+	if (len > 32)
+		len = 32;
+
 	/* read the data from receive buffer */
 	for (i = 0; i < len; ++i) {
 		if (i % 4 == 0)
@@ -399,7 +403,7 @@ static irqreturn_t rk3x_i2c_irq(int irqn
 	}
 
 	/* is there anything left to handle? */
-	if (unlikely(ipd == 0))
+	if (unlikely((ipd & REG_INT_ALL) == 0))
 		goto out;
 
 	switch (i2c->state) {
@@ -429,12 +433,11 @@ static void rk3x_i2c_set_scl_rate(struct
 	unsigned long i2c_rate = clk_get_rate(i2c->clk);
 	unsigned int div;
 
-	/* SCL rate = (clk rate) / (8 * DIV) */
-	div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
-
-	/* The lower and upper half of the CLKDIV reg describe the length of
-	 * SCL low & high periods. */
-	div = DIV_ROUND_UP(div, 2);
+	/* set DIV = DIVH = DIVL
+	 * SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
+	 *          = (clk rate) / (16 * (DIV + 1))
+	 */
+	div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
 
 	i2c_writel(i2c, (div << 16) | (div & 0xffff), REG_CLKDIV);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s3c2410.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s3c2410.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s3c2410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s3c2410.c	2014-09-28 17:29:07.000000000 -0400
@@ -1128,11 +1128,11 @@ static int s3c24xx_i2c_probe(struct plat
 		s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
 
 	strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
-	i2c->adap.owner   = THIS_MODULE;
-	i2c->adap.algo    = &s3c24xx_i2c_algorithm;
+	i2c->adap.owner = THIS_MODULE;
+	i2c->adap.algo = &s3c24xx_i2c_algorithm;
 	i2c->adap.retries = 2;
-	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
-	i2c->tx_setup     = 50;
+	i2c->adap.class = I2C_CLASS_DEPRECATED;
+	i2c->tx_setup = 50;
 
 	init_waitqueue_head(&i2c->wait);
 
@@ -1267,7 +1267,7 @@ static int s3c24xx_i2c_suspend_noirq(str
 	return 0;
 }
 
-static int s3c24xx_i2c_resume(struct device *dev)
+static int s3c24xx_i2c_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1285,7 +1285,11 @@ static int s3c24xx_i2c_resume(struct dev
 static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
 	.suspend_noirq = s3c24xx_i2c_suspend_noirq,
-	.resume = s3c24xx_i2c_resume,
+	.resume_noirq = s3c24xx_i2c_resume_noirq,
+	.freeze_noirq = s3c24xx_i2c_suspend_noirq,
+	.thaw_noirq = s3c24xx_i2c_resume_noirq,
+	.poweroff_noirq = s3c24xx_i2c_suspend_noirq,
+	.restore_noirq = s3c24xx_i2c_resume_noirq,
 #endif
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s6000.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s6000.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s6000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s6000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,404 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.c
- *
- * Description: Driver for S6000 Family I2C Interface
- * Copyright (c) 2008 emlix GmbH
- * Author:	Oskar Schirmer <oskar@scara.com>
- *
- * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
- * Copyright (c) 2005-2007 Analog Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/i2c/s6000.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "i2c-s6000.h"
-
-#define DRV_NAME "i2c-s6000"
-
-#define POLL_TIMEOUT	(2 * HZ)
-
-struct s6i2c_if {
-	u8 __iomem		*reg; /* memory mapped registers */
-	int			irq;
-	spinlock_t		lock;
-	struct i2c_msg		*msgs; /* messages currently handled */
-	int			msgs_num; /* nb of msgs to do */
-	int			msgs_push; /* nb of msgs read/written */
-	int			msgs_done; /* nb of msgs finally handled */
-	unsigned		push; /* nb of bytes read/written in msg */
-	unsigned		done; /* nb of bytes finally handled */
-	int			timeout_count; /* timeout retries left */
-	struct timer_list	timeout_timer;
-	struct i2c_adapter	adap;
-	struct completion	complete;
-	struct clk		*clk;
-	struct resource		*res;
-};
-
-static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n)
-{
-	return readw(iface->reg + (n));
-}
-
-static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v)
-{
-	writew(v, iface->reg + (n));
-}
-
-static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n)
-{
-	return readl(iface->reg + (n));
-}
-
-static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v)
-{
-	writel(v, iface->reg + (n));
-}
-
-static struct s6i2c_if s6i2c_if;
-
-static void s6i2c_handle_interrupt(struct s6i2c_if *iface)
-{
-	if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) {
-		i2c_rd16(iface, S6_I2C_CLRTXABRT);
-		i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-		complete(&iface->complete);
-		return;
-	}
-	if (iface->msgs_done >= iface->msgs_num) {
-		dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n",
-			i2c_rd16(iface, S6_I2C_INTRSTAT));
-		i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-		return;
-	}
-	while ((iface->msgs_push < iface->msgs_num)
-	    && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) {
-		struct i2c_msg *m = &iface->msgs[iface->msgs_push];
-		if (!(m->flags & I2C_M_RD))
-			i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]);
-		else
-			i2c_wr16(iface, S6_I2C_DATACMD,
-				 1 << S6_I2C_DATACMD_READ);
-		if (++iface->push >= m->len) {
-			iface->push = 0;
-			iface->msgs_push += 1;
-		}
-	}
-	do {
-		struct i2c_msg *m = &iface->msgs[iface->msgs_done];
-		if (!(m->flags & I2C_M_RD)) {
-			if (iface->msgs_done < iface->msgs_push)
-				iface->msgs_done += 1;
-			else
-				break;
-		} else if (i2c_rd16(iface, S6_I2C_STATUS)
-				& (1 << S6_I2C_STATUS_RFNE)) {
-			m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD);
-			if (++iface->done >= m->len) {
-				iface->done = 0;
-				iface->msgs_done += 1;
-			}
-		} else{
-			break;
-		}
-	} while (iface->msgs_done < iface->msgs_num);
-	if (iface->msgs_done >= iface->msgs_num) {
-		i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT);
-		complete(&iface->complete);
-	} else if (iface->msgs_push >= iface->msgs_num) {
-		i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
-						 (1 << S6_I2C_INTR_RXFULL));
-	} else {
-		i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
-						 (1 << S6_I2C_INTR_TXEMPTY) |
-						 (1 << S6_I2C_INTR_RXFULL));
-	}
-}
-
-static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id)
-{
-	struct s6i2c_if *iface = dev_id;
-	if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER)
-					      | (1 << S6_I2C_INTR_RXOVER)
-					      | (1 << S6_I2C_INTR_RXFULL)
-					      | (1 << S6_I2C_INTR_TXOVER)
-					      | (1 << S6_I2C_INTR_TXEMPTY)
-					      | (1 << S6_I2C_INTR_RDREQ)
-					      | (1 << S6_I2C_INTR_TXABRT)
-					      | (1 << S6_I2C_INTR_RXDONE)
-					      | (1 << S6_I2C_INTR_ACTIVITY)
-					      | (1 << S6_I2C_INTR_STOPDET)
-					      | (1 << S6_I2C_INTR_STARTDET)
-					      | (1 << S6_I2C_INTR_GENCALL))))
-		return IRQ_NONE;
-
-	spin_lock(&iface->lock);
-	del_timer(&iface->timeout_timer);
-	s6i2c_handle_interrupt(iface);
-	spin_unlock(&iface->lock);
-	return IRQ_HANDLED;
-}
-
-static void s6i2c_timeout(unsigned long data)
-{
-	struct s6i2c_if *iface = (struct s6i2c_if *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iface->lock, flags);
-	s6i2c_handle_interrupt(iface);
-	if (--iface->timeout_count > 0) {
-		iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-		add_timer(&iface->timeout_timer);
-	} else {
-		complete(&iface->complete);
-		i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-	}
-	spin_unlock_irqrestore(&iface->lock, flags);
-}
-
-static int s6i2c_master_xfer(struct i2c_adapter *adap,
-				struct i2c_msg *msgs, int num)
-{
-	struct s6i2c_if *iface = adap->algo_data;
-	int i;
-	if (num == 0)
-		return 0;
-	if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
-		yield();
-	i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-	i2c_rd16(iface, S6_I2C_CLRINTR);
-	for (i = 0; i < num; i++) {
-		if (msgs[i].flags & I2C_M_TEN) {
-			dev_err(&adap->dev,
-				"s6i2c: 10 bits addr not supported\n");
-			return -EINVAL;
-		}
-		if (msgs[i].len == 0) {
-			dev_err(&adap->dev,
-				"s6i2c: zero length message not supported\n");
-			return -EINVAL;
-		}
-		if (msgs[i].addr != msgs[0].addr) {
-			dev_err(&adap->dev,
-				"s6i2c: multiple xfer cannot change target\n");
-			return -EINVAL;
-		}
-	}
-
-	iface->msgs = msgs;
-	iface->msgs_num = num;
-	iface->msgs_push = 0;
-	iface->msgs_done = 0;
-	iface->push = 0;
-	iface->done = 0;
-	iface->timeout_count = 10;
-	i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr);
-	i2c_wr16(iface, S6_I2C_ENABLE, 1);
-	i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) |
-					 (1 << S6_I2C_INTR_TXABRT));
-
-	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-	add_timer(&iface->timeout_timer);
-	wait_for_completion(&iface->complete);
-	del_timer_sync(&iface->timeout_timer);
-	while (i2c_rd32(iface, S6_I2C_TXFLR) > 0)
-		schedule();
-	while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
-		schedule();
-
-	i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-	i2c_wr16(iface, S6_I2C_ENABLE, 0);
-	return iface->msgs_done;
-}
-
-static u32 s6i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm s6i2c_algorithm = {
-	.master_xfer   = s6i2c_master_xfer,
-	.functionality = s6i2c_functionality,
-};
-
-static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
-{
-	u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
-	if (dividend > 0xffff)
-		return 0xffff;
-	return dividend;
-}
-
-static int s6i2c_probe(struct platform_device *dev)
-{
-	struct s6i2c_if *iface = &s6i2c_if;
-	struct i2c_adapter *p_adap;
-	const char *clock;
-	int bus_num, rc;
-	spin_lock_init(&iface->lock);
-	init_completion(&iface->complete);
-	iface->irq = platform_get_irq(dev, 0);
-	if (iface->irq < 0) {
-		rc = iface->irq;
-		goto err_out;
-	}
-	iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!iface->res) {
-		rc = -ENXIO;
-		goto err_out;
-	}
-	iface->res = request_mem_region(iface->res->start,
-					resource_size(iface->res),
-					dev->dev.bus_id);
-	if (!iface->res) {
-		rc = -EBUSY;
-		goto err_out;
-	}
-	iface->reg = ioremap_nocache(iface->res->start,
-				     resource_size(iface->res));
-	if (!iface->reg) {
-		rc = -ENOMEM;
-		goto err_reg;
-	}
-
-	clock = 0;
-	bus_num = -1;
-	if (dev_get_platdata(&dev->dev)) {
-		struct s6_i2c_platform_data *pdata =
-			dev_get_platdata(&dev->dev);
-		bus_num = pdata->bus_num;
-		clock = pdata->clock;
-	}
-	iface->clk = clk_get(&dev->dev, clock);
-	if (IS_ERR(iface->clk)) {
-		rc = PTR_ERR(iface->clk);
-		goto err_map;
-	}
-	rc = clk_enable(iface->clk);
-	if (rc < 0)
-		goto err_clk_put;
-	init_timer(&iface->timeout_timer);
-	iface->timeout_timer.function = s6i2c_timeout;
-	iface->timeout_timer.data = (unsigned long)iface;
-
-	p_adap = &iface->adap;
-	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
-	p_adap->algo = &s6i2c_algorithm;
-	p_adap->algo_data = iface;
-	p_adap->nr = bus_num;
-	p_adap->class = 0;
-	p_adap->dev.parent = &dev->dev;
-	i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-	rc = request_irq(iface->irq, s6i2c_interrupt_entry,
-			 IRQF_SHARED, dev->name, iface);
-	if (rc) {
-		dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq);
-		goto err_clk_dis;
-	}
-
-	i2c_wr16(iface, S6_I2C_ENABLE, 0);
-	udelay(1);
-	i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST);
-	i2c_wr16(iface, S6_I2C_CLRTXABRT, 1);
-	i2c_wr16(iface, S6_I2C_CON,
-			(1 << S6_I2C_CON_MASTER) |
-			(S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) |
-			(0 << S6_I2C_CON_10BITSLAVE) |
-			(0 << S6_I2C_CON_10BITMASTER) |
-			(1 << S6_I2C_CON_RESTARTENA) |
-			(1 << S6_I2C_CON_SLAVEDISABLE));
-	i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000));
-	i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700));
-	i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600));
-	i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300));
-	i2c_wr16(iface, S6_I2C_RXTL, 0);
-	i2c_wr16(iface, S6_I2C_TXTL, 0);
-
-	platform_set_drvdata(dev, iface);
-	rc = i2c_add_numbered_adapter(p_adap);
-	if (rc)
-		goto err_irq_free;
-	return 0;
-
-err_irq_free:
-	free_irq(iface->irq, iface);
-err_clk_dis:
-	clk_disable(iface->clk);
-err_clk_put:
-	clk_put(iface->clk);
-err_map:
-	iounmap(iface->reg);
-err_reg:
-	release_mem_region(iface->res->start,
-			   resource_size(iface->res));
-err_out:
-	return rc;
-}
-
-static int s6i2c_remove(struct platform_device *pdev)
-{
-	struct s6i2c_if *iface = platform_get_drvdata(pdev);
-	i2c_wr16(iface, S6_I2C_ENABLE, 0);
-	i2c_del_adapter(&iface->adap);
-	free_irq(iface->irq, iface);
-	clk_disable(iface->clk);
-	clk_put(iface->clk);
-	iounmap(iface->reg);
-	release_mem_region(iface->res->start,
-			   resource_size(iface->res));
-	return 0;
-}
-
-static struct platform_driver s6i2c_driver = {
-	.probe		= s6i2c_probe,
-	.remove		= s6i2c_remove,
-	.driver		= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init s6i2c_init(void)
-{
-	pr_info("I2C: S6000 I2C driver\n");
-	return platform_driver_register(&s6i2c_driver);
-}
-
-static void __exit s6i2c_exit(void)
-{
-	platform_driver_unregister(&s6i2c_driver);
-}
-
-MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-
-subsys_initcall(s6i2c_init);
-module_exit(s6i2c_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s6000.h linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s6000.h
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-s6000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-s6000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2008 Emlix GmbH <info@emlix.com>
- * Author:	Oskar Schirmer <oskar@scara.com>
- */
-
-#ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H
-#define __DRIVERS_I2C_BUSSES_I2C_S6000_H
-
-#define S6_I2C_CON		0x000
-#define S6_I2C_CON_MASTER		0
-#define S6_I2C_CON_SPEED		1
-#define S6_I2C_CON_SPEED_NORMAL			1
-#define S6_I2C_CON_SPEED_FAST			2
-#define S6_I2C_CON_SPEED_MASK			3
-#define S6_I2C_CON_10BITSLAVE		3
-#define S6_I2C_CON_10BITMASTER		4
-#define S6_I2C_CON_RESTARTENA		5
-#define S6_I2C_CON_SLAVEDISABLE		6
-#define S6_I2C_TAR		0x004
-#define S6_I2C_TAR_GCORSTART		10
-#define S6_I2C_TAR_SPECIAL		11
-#define S6_I2C_SAR		0x008
-#define S6_I2C_HSMADDR		0x00C
-#define S6_I2C_DATACMD		0x010
-#define S6_I2C_DATACMD_READ		8
-#define S6_I2C_SSHCNT		0x014
-#define S6_I2C_SSLCNT		0x018
-#define S6_I2C_FSHCNT		0x01C
-#define S6_I2C_FSLCNT		0x020
-#define S6_I2C_INTRSTAT		0x02C
-#define S6_I2C_INTRMASK		0x030
-#define S6_I2C_RAWINTR		0x034
-#define S6_I2C_INTR_RXUNDER		0
-#define S6_I2C_INTR_RXOVER		1
-#define S6_I2C_INTR_RXFULL		2
-#define S6_I2C_INTR_TXOVER		3
-#define S6_I2C_INTR_TXEMPTY		4
-#define S6_I2C_INTR_RDREQ		5
-#define S6_I2C_INTR_TXABRT		6
-#define S6_I2C_INTR_RXDONE		7
-#define S6_I2C_INTR_ACTIVITY		8
-#define S6_I2C_INTR_STOPDET		9
-#define S6_I2C_INTR_STARTDET		10
-#define S6_I2C_INTR_GENCALL		11
-#define S6_I2C_RXTL		0x038
-#define S6_I2C_TXTL		0x03C
-#define S6_I2C_CLRINTR		0x040
-#define S6_I2C_CLRRXUNDER	0x044
-#define S6_I2C_CLRRXOVER	0x048
-#define S6_I2C_CLRTXOVER	0x04C
-#define S6_I2C_CLRRDREQ		0x050
-#define S6_I2C_CLRTXABRT	0x054
-#define S6_I2C_CLRRXDONE	0x058
-#define S6_I2C_CLRACTIVITY	0x05C
-#define S6_I2C_CLRSTOPDET	0x060
-#define S6_I2C_CLRSTARTDET	0x064
-#define S6_I2C_CLRGENCALL	0x068
-#define S6_I2C_ENABLE		0x06C
-#define S6_I2C_STATUS		0x070
-#define S6_I2C_STATUS_ACTIVITY		0
-#define S6_I2C_STATUS_TFNF		1
-#define S6_I2C_STATUS_TFE		2
-#define S6_I2C_STATUS_RFNE		3
-#define S6_I2C_STATUS_RFF		4
-#define S6_I2C_TXFLR		0x074
-#define S6_I2C_RXFLR		0x078
-#define S6_I2C_SRESET		0x07C
-#define S6_I2C_SRESET_IC_SRST		0
-#define S6_I2C_SRESET_IC_MASTER_SRST	1
-#define S6_I2C_SRESET_IC_SLAVE_SRST	2
-#define S6_I2C_TXABRTSOURCE	0x080
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-sirf.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-sirf.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-sirf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-sirf.c	2014-09-28 17:29:07.000000000 -0400
@@ -311,7 +311,7 @@ static int i2c_sirfsoc_probe(struct plat
 		goto out;
 	}
 	adap = &siic->adapter;
-	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	siic->base = devm_ioremap_resource(&pdev->dev, mem_res);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-st.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-st.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-st.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-st.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,25 +206,31 @@ static inline void st_i2c_clr_bits(void
 	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
 }
 
-/* From I2C Specifications v0.5 */
+/*
+ * From I2C Specifications v0.5.
+ *
+ * All the values below have +10% margin added to be
+ * compatible with some out-of-spec devices,
+ * like HDMI link of the Toshiba 19AV600 TV.
+ */
 static struct st_i2c_timings i2c_timings[] = {
 	[I2C_MODE_STANDARD] = {
 		.rate			= 100000,
-		.rep_start_hold		= 4000,
-		.rep_start_setup	= 4700,
-		.start_hold		= 4000,
-		.data_setup_time	= 250,
-		.stop_setup_time	= 4000,
-		.bus_free_time		= 4700,
+		.rep_start_hold		= 4400,
+		.rep_start_setup	= 5170,
+		.start_hold		= 4400,
+		.data_setup_time	= 275,
+		.stop_setup_time	= 4400,
+		.bus_free_time		= 5170,
 	},
 	[I2C_MODE_FAST] = {
 		.rate			= 400000,
-		.rep_start_hold		= 600,
-		.rep_start_setup	= 600,
-		.start_hold		= 600,
-		.data_setup_time	= 100,
-		.stop_setup_time	= 600,
-		.bus_free_time		= 1300,
+		.rep_start_hold		= 660,
+		.rep_start_setup	= 660,
+		.start_hold		= 660,
+		.data_setup_time	= 110,
+		.stop_setup_time	= 660,
+		.bus_free_time		= 1430,
 	},
 };
 
@@ -815,7 +821,7 @@ static int st_i2c_probe(struct platform_
 
 	adap = &i2c_dev->adap;
 	i2c_set_adapdata(adap, i2c_dev);
-	snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%x)", res->start);
+	snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%pa)", &res->start);
 	adap->owner = THIS_MODULE;
 	adap->timeout = 2 * HZ;
 	adap->retries = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-stu300.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-stu300.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-stu300.c	2014-09-28 17:29:07.000000000 -0400
@@ -909,7 +909,7 @@ static int stu300_probe(struct platform_
 	adap = &dev->adapter;
 	adap->owner = THIS_MODULE;
 	/* DDC class but actually often used for more generic I2C */
-	adap->class = I2C_CLASS_DDC | I2C_CLASS_DEPRECATED;
+	adap->class = I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
 		sizeof(adap->name));
 	adap->nr = bus_nr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-taos-evm.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-taos-evm.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-taos-evm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-taos-evm.c	2014-09-28 17:29:07.000000000 -0400
@@ -311,19 +311,8 @@ static struct serio_driver taos_drv = {
 	.interrupt	= taos_interrupt,
 };
 
-static int __init taos_init(void)
-{
-	return serio_register_driver(&taos_drv);
-}
-
-static void __exit taos_exit(void)
-{
-	serio_unregister_driver(&taos_drv);
-}
+module_serio_driver(taos_drv);
 
 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
 MODULE_DESCRIPTION("TAOS evaluation module driver");
 MODULE_LICENSE("GPL");
-
-module_init(taos_init);
-module_exit(taos_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-tegra.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-tegra.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -380,34 +380,33 @@ static inline int tegra_i2c_clock_enable
 {
 	int ret;
 	if (!i2c_dev->hw->has_single_clk_source) {
-		ret = clk_prepare_enable(i2c_dev->fast_clk);
+		ret = clk_enable(i2c_dev->fast_clk);
 		if (ret < 0) {
 			dev_err(i2c_dev->dev,
 				"Enabling fast clk failed, err %d\n", ret);
 			return ret;
 		}
 	}
-	ret = clk_prepare_enable(i2c_dev->div_clk);
+	ret = clk_enable(i2c_dev->div_clk);
 	if (ret < 0) {
 		dev_err(i2c_dev->dev,
 			"Enabling div clk failed, err %d\n", ret);
-		clk_disable_unprepare(i2c_dev->fast_clk);
+		clk_disable(i2c_dev->fast_clk);
 	}
 	return ret;
 }
 
 static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
 {
-	clk_disable_unprepare(i2c_dev->div_clk);
+	clk_disable(i2c_dev->div_clk);
 	if (!i2c_dev->hw->has_single_clk_source)
-		clk_disable_unprepare(i2c_dev->fast_clk);
+		clk_disable(i2c_dev->fast_clk);
 }
 
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 {
 	u32 val;
 	int err = 0;
-	int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
 	u32 clk_divisor;
 
 	err = tegra_i2c_clock_enable(i2c_dev);
@@ -428,9 +427,6 @@ static int tegra_i2c_init(struct tegra_i
 	i2c_writel(i2c_dev, val, I2C_CNFG);
 	i2c_writel(i2c_dev, 0, I2C_INT_MASK);
 
-	clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
-	clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * clk_multiplier);
-
 	/* Make sure clock divisor programmed correctly */
 	clk_divisor = i2c_dev->hw->clk_divisor_hs_mode;
 	clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode <<
@@ -712,6 +708,7 @@ static int tegra_i2c_probe(struct platfo
 	void __iomem *base;
 	int irq;
 	int ret = 0;
+	int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, res);
@@ -777,22 +774,44 @@ static int tegra_i2c_probe(struct platfo
 
 	platform_set_drvdata(pdev, i2c_dev);
 
+	if (!i2c_dev->hw->has_single_clk_source) {
+		ret = clk_prepare(i2c_dev->fast_clk);
+		if (ret < 0) {
+			dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
+			return ret;
+		}
+	}
+
+	clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
+	ret = clk_set_rate(i2c_dev->div_clk,
+			   i2c_dev->bus_clk_rate * clk_multiplier);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Clock rate change failed %d\n", ret);
+		goto unprepare_fast_clk;
+	}
+
+	ret = clk_prepare(i2c_dev->div_clk);
+	if (ret < 0) {
+		dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
+		goto unprepare_fast_clk;
+	}
+
 	ret = tegra_i2c_init(i2c_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to initialize i2c controller");
-		return ret;
+		goto unprepare_div_clk;
 	}
 
 	ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
 			tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
-		return ret;
+		goto unprepare_div_clk;
 	}
 
 	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
 	i2c_dev->adapter.owner = THIS_MODULE;
-	i2c_dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+	i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
 	strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
 		sizeof(i2c_dev->adapter.name));
 	i2c_dev->adapter.algo = &tegra_i2c_algo;
@@ -803,16 +822,30 @@ static int tegra_i2c_probe(struct platfo
 	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
-		return ret;
+		goto unprepare_div_clk;
 	}
 
 	return 0;
+
+unprepare_div_clk:
+	clk_unprepare(i2c_dev->div_clk);
+
+unprepare_fast_clk:
+	if (!i2c_dev->hw->has_single_clk_source)
+		clk_unprepare(i2c_dev->fast_clk);
+
+	return ret;
 }
 
 static int tegra_i2c_remove(struct platform_device *pdev)
 {
 	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 	i2c_del_adapter(&i2c_dev->adapter);
+
+	clk_unprepare(i2c_dev->div_clk);
+	if (!i2c_dev->hw->has_single_clk_source)
+		clk_unprepare(i2c_dev->fast_clk);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/i2c-xiic.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-xiic.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/i2c-xiic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/i2c-xiic.c	2014-09-28 17:29:07.000000000 -0400
@@ -677,15 +677,15 @@ static u32 xiic_func(struct i2c_adapter
 }
 
 static const struct i2c_algorithm xiic_algorithm = {
-	.master_xfer	= xiic_xfer,
-	.functionality	= xiic_func,
+	.master_xfer = xiic_xfer,
+	.functionality = xiic_func,
 };
 
 static struct i2c_adapter xiic_adapter = {
-	.owner		= THIS_MODULE,
-	.name		= DRIVER_NAME,
-	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
-	.algo		= &xiic_algorithm,
+	.owner = THIS_MODULE,
+	.name = DRIVER_NAME,
+	.class = I2C_CLASS_DEPRECATED,
+	.algo = &xiic_algorithm,
 };
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/Kconfig linux-libre-3.17-rc7-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-3.16-gnu/drivers/i2c/busses/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -109,6 +109,7 @@ config I2C_I801
 	    Avoton (SOC)
 	    Wellsburg (PCH)
 	    Coleto Creek (PCH)
+	    Wildcat Point (PCH)
 	    Wildcat Point-LP (PCH)
 	    BayTrail (SOC)
 
@@ -465,9 +466,9 @@ config I2C_EG20T
 config I2C_EXYNOS5
 	tristate "Exynos5 high-speed I2C driver"
 	depends on ARCH_EXYNOS5 && OF
+	default y
 	help
-	  Say Y here to include support for high-speed I2C controller in the
-	  Exynos5 based Samsung SoCs.
+	  High-speed I2C controller on Exynos5 based Samsung SoCs.
 
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
@@ -700,16 +701,6 @@ config I2C_S3C2410
 	  Say Y here to include support for I2C controller in the
 	  Samsung SoCs.
 
-config I2C_S6000
-	tristate "S6000 I2C support"
-	depends on XTENSA_VARIANT_S6000
-	help
-	  This driver supports the on chip I2C device on the
-	  S6000 xtensa processor family.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called i2c-s6000.
-
 config I2C_SH7760
 	tristate "Renesas SH7760 I2C Controller"
 	depends on CPU_SUBTYPE_SH7760
@@ -1018,37 +1009,6 @@ config I2C_CROS_EC_TUNNEL
 	  connected there. This will work whatever the interface used to
 	  talk to the EC (SPI, I2C or LPC).
 
-config SCx200_I2C
-	tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
-	depends on SCx200_GPIO
-	select I2C_ALGOBIT
-	help
-	  Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-
-	  If you don't know what to do here, say N.
-
-	  This support is also available as a module.  If so, the module
-	  will be called scx200_i2c.
-
-	  This driver is deprecated and will be dropped soon. Use i2c-gpio
-	  (or scx200_acb) instead.
-
-config SCx200_I2C_SCL
-	int "GPIO pin used for SCL"
-	depends on SCx200_I2C
-	default "12"
-	help
-	  Enter the GPIO pin number used for the SCL signal.  This value can
-	  also be specified with a module parameter.
-
-config SCx200_I2C_SDA
-	int "GPIO pin used for SDA"
-	depends on SCx200_I2C
-	default "13"
-	help
-	  Enter the GPIO pin number used for the SSA signal.  This value can
-	  also be specified with a module parameter.
-
 config SCx200_ACB
 	tristate "Geode ACCESS.bus support"
 	depends on X86_32 && PCI
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/Makefile linux-libre-3.17-rc7-gnu/drivers/i2c/busses/Makefile
--- linux-libre-3.16-gnu/drivers/i2c/busses/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,6 @@ obj-$(CONFIG_I2C_QUP)		+= i2c-qup.o
 obj-$(CONFIG_I2C_RIIC)		+= i2c-riic.o
 obj-$(CONFIG_I2C_RK3X)		+= i2c-rk3x.o
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
-obj-$(CONFIG_I2C_S6000)		+= i2c-s6000.o
 obj-$(CONFIG_I2C_SH7760)	+= i2c-sh7760.o
 obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
@@ -101,6 +100,5 @@ obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
-obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/busses/scx200_i2c.c linux-libre-3.17-rc7-gnu/drivers/i2c/busses/scx200_i2c.c
--- linux-libre-3.16-gnu/drivers/i2c/busses/scx200_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/busses/scx200_i2c.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,129 +0,0 @@
-/* linux/drivers/i2c/busses/scx200_i2c.c
-
-   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
-
-   National Semiconductor SCx200 I2C bus on GPIO pins
-
-   Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. Vogl
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/io.h>
-
-#include <linux/scx200_gpio.h>
-
-MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
-MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
-MODULE_LICENSE("GPL");
-
-static int scl = CONFIG_SCx200_I2C_SCL;
-static int sda = CONFIG_SCx200_I2C_SDA;
-
-module_param(scl, int, 0);
-MODULE_PARM_DESC(scl, "GPIO line for SCL");
-module_param(sda, int, 0);
-MODULE_PARM_DESC(sda, "GPIO line for SDA");
-
-static void scx200_i2c_setscl(void *data, int state)
-{
-	scx200_gpio_set(scl, state);
-}
-
-static void scx200_i2c_setsda(void *data, int state)
-{
-	scx200_gpio_set(sda, state);
-} 
-
-static int scx200_i2c_getscl(void *data)
-{
-	return scx200_gpio_get(scl);
-}
-
-static int scx200_i2c_getsda(void *data)
-{
-	return scx200_gpio_get(sda);
-}
-
-/* ------------------------------------------------------------------------
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
-
-static struct i2c_algo_bit_data scx200_i2c_data = {
-	.setsda		= scx200_i2c_setsda,
-	.setscl		= scx200_i2c_setscl,
-	.getsda		= scx200_i2c_getsda,
-	.getscl		= scx200_i2c_getscl,
-	.udelay		= 10,
-	.timeout	= HZ,
-};
-
-static struct i2c_adapter scx200_i2c_ops = {
-	.owner		   = THIS_MODULE,
-	.class             = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-	.algo_data	   = &scx200_i2c_data,
-	.name	= "NatSemi SCx200 I2C",
-};
-
-static int scx200_i2c_init(void)
-{
-	pr_debug("NatSemi SCx200 I2C Driver\n");
-
-	if (!scx200_gpio_present()) {
-		pr_err("no SCx200 gpio pins available\n");
-		return -ENODEV;
-	}
-
-	pr_debug("SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
-
-	if (scl == -1 || sda == -1 || scl == sda) {
-		pr_err("scl and sda must be specified\n");
-		return -EINVAL;
-	}
-
-	/* Configure GPIOs as open collector outputs */
-	scx200_gpio_configure(scl, ~2, 5);
-	scx200_gpio_configure(sda, ~2, 5);
-
-	if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) {
-		pr_err("adapter %s registration failed\n", scx200_i2c_ops.name);
-		return -ENODEV;
-	}
-	
-	return 0;
-}
-
-static void scx200_i2c_cleanup(void)
-{
-	i2c_del_adapter(&scx200_i2c_ops);
-}
-
-module_init(scx200_i2c_init);
-module_exit(scx200_i2c_cleanup);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
-        c-basic-offset: 8
-    End:
-*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/i2c-core.c linux-libre-3.17-rc7-gnu/drivers/i2c/i2c-core.c
--- linux-libre-3.16-gnu/drivers/i2c/i2c-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/i2c-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,8 @@
    OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
    (based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
    (c) 2013  Wolfram Sang <wsa@the-dreams.de>
+   I2C ACPI code Copyright (C) 2014 Intel Corp
+   Author: Lan Tianyu <tianyu.lan@intel.com>
  */
 
 #include <linux/module.h>
@@ -42,6 +44,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/clk/clk-conf.h>
 #include <linux/completion.h>
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
@@ -77,6 +80,368 @@ void i2c_transfer_trace_unreg(void)
 	static_key_slow_dec(&i2c_trace_msg);
 }
 
+#if defined(CONFIG_ACPI)
+struct acpi_i2c_handler_data {
+	struct acpi_connection_info info;
+	struct i2c_adapter *adapter;
+};
+
+struct gsb_buffer {
+	u8	status;
+	u8	len;
+	union {
+		u16	wdata;
+		u8	bdata;
+		u8	data[0];
+	};
+} __packed;
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+	struct i2c_board_info *info = data;
+
+	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+		struct acpi_resource_i2c_serialbus *sb;
+
+		sb = &ares->data.i2c_serial_bus;
+		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+			info->addr = sb->slave_address;
+			if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+				info->flags |= I2C_CLIENT_TEN;
+		}
+	} else if (info->irq < 0) {
+		struct resource r;
+
+		if (acpi_dev_resource_interrupt(ares, 0, &r))
+			info->irq = r.start;
+	}
+
+	/* Tell the ACPI core to skip this resource */
+	return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct i2c_adapter *adapter = data;
+	struct list_head resource_list;
+	struct i2c_board_info info;
+	struct acpi_device *adev;
+	int ret;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+	if (acpi_bus_get_status(adev) || !adev->status.present)
+		return AE_OK;
+
+	memset(&info, 0, sizeof(info));
+	info.acpi_node.companion = adev;
+	info.irq = -1;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     acpi_i2c_add_resource, &info);
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (ret < 0 || !info.addr)
+		return AE_OK;
+
+	adev->power.flags.ignore_parent = true;
+	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+	if (!i2c_new_device(adapter, &info)) {
+		adev->power.flags.ignore_parent = false;
+		dev_err(&adapter->dev,
+			"failed to add I2C device %s from ACPI\n",
+			dev_name(&adev->dev));
+	}
+
+	return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adap: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+static void acpi_i2c_register_devices(struct i2c_adapter *adap)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	if (!adap->dev.parent)
+		return;
+
+	handle = ACPI_HANDLE(adap->dev.parent);
+	if (!handle)
+		return;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				     acpi_i2c_add_device, NULL,
+				     adap, NULL);
+	if (ACPI_FAILURE(status))
+		dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+}
+
+#else /* CONFIG_ACPI */
+static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
+#endif /* CONFIG_ACPI */
+
+#ifdef CONFIG_ACPI_I2C_OPREGION
+static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
+		u8 cmd, u8 *data, u8 data_len)
+{
+
+	struct i2c_msg msgs[2];
+	int ret;
+	u8 *buffer;
+
+	buffer = kzalloc(data_len, GFP_KERNEL);
+	if (!buffer)
+		return AE_NO_MEMORY;
+
+	msgs[0].addr = client->addr;
+	msgs[0].flags = client->flags;
+	msgs[0].len = 1;
+	msgs[0].buf = &cmd;
+
+	msgs[1].addr = client->addr;
+	msgs[1].flags = client->flags | I2C_M_RD;
+	msgs[1].len = data_len;
+	msgs[1].buf = buffer;
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		dev_err(&client->adapter->dev, "i2c read failed\n");
+	else
+		memcpy(data, buffer, data_len);
+
+	kfree(buffer);
+	return ret;
+}
+
+static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
+		u8 cmd, u8 *data, u8 data_len)
+{
+
+	struct i2c_msg msgs[1];
+	u8 *buffer;
+	int ret = AE_OK;
+
+	buffer = kzalloc(data_len + 1, GFP_KERNEL);
+	if (!buffer)
+		return AE_NO_MEMORY;
+
+	buffer[0] = cmd;
+	memcpy(buffer + 1, data, data_len);
+
+	msgs[0].addr = client->addr;
+	msgs[0].flags = client->flags;
+	msgs[0].len = data_len + 1;
+	msgs[0].buf = buffer;
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		dev_err(&client->adapter->dev, "i2c write failed\n");
+
+	kfree(buffer);
+	return ret;
+}
+
+static acpi_status
+acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+			u32 bits, u64 *value64,
+			void *handler_context, void *region_context)
+{
+	struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
+	struct acpi_i2c_handler_data *data = handler_context;
+	struct acpi_connection_info *info = &data->info;
+	struct acpi_resource_i2c_serialbus *sb;
+	struct i2c_adapter *adapter = data->adapter;
+	struct i2c_client client;
+	struct acpi_resource *ares;
+	u32 accessor_type = function >> 16;
+	u8 action = function & ACPI_IO_MASK;
+	acpi_status ret = AE_OK;
+	int status;
+
+	ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
+	if (ACPI_FAILURE(ret))
+		return ret;
+
+	if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+		ret = AE_BAD_PARAMETER;
+		goto err;
+	}
+
+	sb = &ares->data.i2c_serial_bus;
+	if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+		ret = AE_BAD_PARAMETER;
+		goto err;
+	}
+
+	memset(&client, 0, sizeof(client));
+	client.adapter = adapter;
+	client.addr = sb->slave_address;
+	client.flags = 0;
+
+	if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+		client.flags |= I2C_CLIENT_TEN;
+
+	switch (accessor_type) {
+	case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
+		if (action == ACPI_READ) {
+			status = i2c_smbus_read_byte(&client);
+			if (status >= 0) {
+				gsb->bdata = status;
+				status = 0;
+			}
+		} else {
+			status = i2c_smbus_write_byte(&client, gsb->bdata);
+		}
+		break;
+
+	case ACPI_GSB_ACCESS_ATTRIB_BYTE:
+		if (action == ACPI_READ) {
+			status = i2c_smbus_read_byte_data(&client, command);
+			if (status >= 0) {
+				gsb->bdata = status;
+				status = 0;
+			}
+		} else {
+			status = i2c_smbus_write_byte_data(&client, command,
+					gsb->bdata);
+		}
+		break;
+
+	case ACPI_GSB_ACCESS_ATTRIB_WORD:
+		if (action == ACPI_READ) {
+			status = i2c_smbus_read_word_data(&client, command);
+			if (status >= 0) {
+				gsb->wdata = status;
+				status = 0;
+			}
+		} else {
+			status = i2c_smbus_write_word_data(&client, command,
+					gsb->wdata);
+		}
+		break;
+
+	case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
+		if (action == ACPI_READ) {
+			status = i2c_smbus_read_block_data(&client, command,
+					gsb->data);
+			if (status >= 0) {
+				gsb->len = status;
+				status = 0;
+			}
+		} else {
+			status = i2c_smbus_write_block_data(&client, command,
+					gsb->len, gsb->data);
+		}
+		break;
+
+	case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
+		if (action == ACPI_READ) {
+			status = acpi_gsb_i2c_read_bytes(&client, command,
+					gsb->data, info->access_length);
+			if (status > 0)
+				status = 0;
+		} else {
+			status = acpi_gsb_i2c_write_bytes(&client, command,
+					gsb->data, info->access_length);
+		}
+		break;
+
+	default:
+		pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
+		ret = AE_BAD_PARAMETER;
+		goto err;
+	}
+
+	gsb->status = status;
+
+ err:
+	ACPI_FREE(ares);
+	return ret;
+}
+
+
+static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{
+	acpi_handle handle;
+	struct acpi_i2c_handler_data *data;
+	acpi_status status;
+
+	if (!adapter->dev.parent)
+		return -ENODEV;
+
+	handle = ACPI_HANDLE(adapter->dev.parent);
+
+	if (!handle)
+		return -ENODEV;
+
+	data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->adapter = adapter;
+	status = acpi_bus_attach_private_data(handle, (void *)data);
+	if (ACPI_FAILURE(status)) {
+		kfree(data);
+		return -ENOMEM;
+	}
+
+	status = acpi_install_address_space_handler(handle,
+				ACPI_ADR_SPACE_GSBUS,
+				&acpi_i2c_space_handler,
+				NULL,
+				data);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&adapter->dev, "Error installing i2c space handler\n");
+		acpi_bus_detach_private_data(handle);
+		kfree(data);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{
+	acpi_handle handle;
+	struct acpi_i2c_handler_data *data;
+	acpi_status status;
+
+	if (!adapter->dev.parent)
+		return;
+
+	handle = ACPI_HANDLE(adapter->dev.parent);
+
+	if (!handle)
+		return;
+
+	acpi_remove_address_space_handler(handle,
+				ACPI_ADR_SPACE_GSBUS,
+				&acpi_i2c_space_handler);
+
+	status = acpi_bus_get_private_data(handle, (void **)&data);
+	if (ACPI_SUCCESS(status))
+		kfree(data);
+
+	acpi_bus_detach_private_data(handle);
+}
+#else /* CONFIG_ACPI_I2C_OPREGION */
+static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{ }
+
+static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{ return 0; }
+#endif /* CONFIG_ACPI_I2C_OPREGION */
+
 /* ------------------------------------------------------------------------- */
 
 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
@@ -274,6 +639,10 @@ static int i2c_device_probe(struct devic
 					client->flags & I2C_CLIENT_WAKE);
 	dev_dbg(dev, "probe\n");
 
+	status = of_clk_set_defaults(dev->of_node, false);
+	if (status < 0)
+		return status;
+
 	acpi_dev_pm_attach(&client->dev, true);
 	status = driver->probe(client, i2c_match_id(driver->id_table, client));
 	if (status)
@@ -1092,101 +1461,6 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_nod
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */
 
-/* ACPI support code */
-
-#if IS_ENABLED(CONFIG_ACPI)
-static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
-{
-	struct i2c_board_info *info = data;
-
-	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
-		struct acpi_resource_i2c_serialbus *sb;
-
-		sb = &ares->data.i2c_serial_bus;
-		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
-			info->addr = sb->slave_address;
-			if (sb->access_mode == ACPI_I2C_10BIT_MODE)
-				info->flags |= I2C_CLIENT_TEN;
-		}
-	} else if (info->irq < 0) {
-		struct resource r;
-
-		if (acpi_dev_resource_interrupt(ares, 0, &r))
-			info->irq = r.start;
-	}
-
-	/* Tell the ACPI core to skip this resource */
-	return 1;
-}
-
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
-				       void *data, void **return_value)
-{
-	struct i2c_adapter *adapter = data;
-	struct list_head resource_list;
-	struct i2c_board_info info;
-	struct acpi_device *adev;
-	int ret;
-
-	if (acpi_bus_get_device(handle, &adev))
-		return AE_OK;
-	if (acpi_bus_get_status(adev) || !adev->status.present)
-		return AE_OK;
-
-	memset(&info, 0, sizeof(info));
-	info.acpi_node.companion = adev;
-	info.irq = -1;
-
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list,
-				     acpi_i2c_add_resource, &info);
-	acpi_dev_free_resource_list(&resource_list);
-
-	if (ret < 0 || !info.addr)
-		return AE_OK;
-
-	adev->power.flags.ignore_parent = true;
-	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
-	if (!i2c_new_device(adapter, &info)) {
-		adev->power.flags.ignore_parent = false;
-		dev_err(&adapter->dev,
-			"failed to add I2C device %s from ACPI\n",
-			dev_name(&adev->dev));
-	}
-
-	return AE_OK;
-}
-
-/**
- * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
- * @adap: pointer to adapter
- *
- * Enumerate all I2C slave devices behind this adapter by walking the ACPI
- * namespace. When a device is found it will be added to the Linux device
- * model and bound to the corresponding ACPI handle.
- */
-static void acpi_i2c_register_devices(struct i2c_adapter *adap)
-{
-	acpi_handle handle;
-	acpi_status status;
-
-	if (!adap->dev.parent)
-		return;
-
-	handle = ACPI_HANDLE(adap->dev.parent);
-	if (!handle)
-		return;
-
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-				     acpi_i2c_add_device, NULL,
-				     adap, NULL);
-	if (ACPI_FAILURE(status))
-		dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
-}
-#else
-static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
-#endif /* CONFIG_ACPI */
-
 static int i2c_do_add_adapter(struct i2c_driver *driver,
 			      struct i2c_adapter *adap)
 {
@@ -1293,6 +1567,7 @@ exit_recovery:
 	/* create pre-declared device nodes */
 	of_i2c_register_devices(adap);
 	acpi_i2c_register_devices(adap);
+	acpi_i2c_install_space_handler(adap);
 
 	if (adap->nr < __i2c_first_dynamic_bus_num)
 		i2c_scan_static_board_info(adap);
@@ -1466,6 +1741,7 @@ void i2c_del_adapter(struct i2c_adapter
 		return;
 	}
 
+	acpi_i2c_remove_space_handler(adap);
 	/* Tell drivers about this removal */
 	mutex_lock(&core_lock);
 	bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -2008,6 +2284,16 @@ static int i2c_detect(struct i2c_adapter
 	if (!driver->detect || !address_list)
 		return 0;
 
+	/* Warn that the adapter lost class based instantiation */
+	if (adapter->class == I2C_CLASS_DEPRECATED) {
+		dev_dbg(&adapter->dev,
+			"This adapter dropped support for I2C classes and "
+			"won't auto-detect %s devices anymore. If you need it, check "
+			"'Documentation/i2c/instantiating-devices' for alternatives.\n",
+			driver->driver.name);
+		return 0;
+	}
+
 	/* Stop here if the classes do not match */
 	if (!(adapter->class & driver->class))
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/i2c-stub.c linux-libre-3.17-rc7-gnu/drivers/i2c/i2c-stub.c
--- linux-libre-3.16-gnu/drivers/i2c/i2c-stub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/i2c-stub.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
     i2c-stub.c - I2C/SMBus chip emulator
 
     Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
-    Copyright (C) 2007, 2012 Jean Delvare <jdelvare@suse.de>
+    Copyright (C) 2007-2014 Jean Delvare <jdelvare@suse.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
@@ -27,28 +27,109 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/list.h>
 
 #define MAX_CHIPS 10
-#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
-		   I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
-		   I2C_FUNC_SMBUS_I2C_BLOCK)
+
+/*
+ * Support for I2C_FUNC_SMBUS_BLOCK_DATA is disabled by default and must
+ * be enabled explicitly by setting the I2C_FUNC_SMBUS_BLOCK_DATA bits
+ * in the 'functionality' module parameter.
+ */
+#define STUB_FUNC_DEFAULT \
+		(I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
+		 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
+		 I2C_FUNC_SMBUS_I2C_BLOCK)
+
+#define STUB_FUNC_ALL \
+		(STUB_FUNC_DEFAULT | I2C_FUNC_SMBUS_BLOCK_DATA)
 
 static unsigned short chip_addr[MAX_CHIPS];
 module_param_array(chip_addr, ushort, NULL, S_IRUGO);
 MODULE_PARM_DESC(chip_addr,
 		 "Chip addresses (up to 10, between 0x03 and 0x77)");
 
-static unsigned long functionality = STUB_FUNC;
+static unsigned long functionality = STUB_FUNC_DEFAULT;
 module_param(functionality, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(functionality, "Override functionality bitfield");
 
+/* Some chips have banked register ranges */
+
+static u8 bank_reg[MAX_CHIPS];
+module_param_array(bank_reg, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_reg, "Bank register");
+
+static u8 bank_mask[MAX_CHIPS];
+module_param_array(bank_mask, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_mask, "Bank value mask");
+
+static u8 bank_start[MAX_CHIPS];
+module_param_array(bank_start, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_start, "First banked register");
+
+static u8 bank_end[MAX_CHIPS];
+module_param_array(bank_end, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_end, "Last banked register");
+
+struct smbus_block_data {
+	struct list_head node;
+	u8 command;
+	u8 len;
+	u8 block[I2C_SMBUS_BLOCK_MAX];
+};
+
 struct stub_chip {
 	u8 pointer;
 	u16 words[256];		/* Byte operations use the LSB as per SMBus
 				   specification */
+	struct list_head smbus_blocks;
+
+	/* For chips with banks, extra registers are allocated dynamically */
+	u8 bank_reg;
+	u8 bank_shift;
+	u8 bank_mask;
+	u8 bank_sel;		/* Currently selected bank */
+	u8 bank_start;
+	u8 bank_end;
+	u16 bank_size;
+	u16 *bank_words;	/* Room for bank_mask * bank_size registers */
 };
 
 static struct stub_chip *stub_chips;
+static int stub_chips_nr;
+
+static struct smbus_block_data *stub_find_block(struct device *dev,
+						struct stub_chip *chip,
+						u8 command, bool create)
+{
+	struct smbus_block_data *b, *rb = NULL;
+
+	list_for_each_entry(b, &chip->smbus_blocks, node) {
+		if (b->command == command) {
+			rb = b;
+			break;
+		}
+	}
+	if (rb == NULL && create) {
+		rb = devm_kzalloc(dev, sizeof(*rb), GFP_KERNEL);
+		if (rb == NULL)
+			return rb;
+		rb->command = command;
+		list_add(&rb->node, &chip->smbus_blocks);
+	}
+	return rb;
+}
+
+static u16 *stub_get_wordp(struct stub_chip *chip, u8 offset)
+{
+	if (chip->bank_sel &&
+	    offset >= chip->bank_start && offset <= chip->bank_end)
+		return chip->bank_words +
+		       (chip->bank_sel - 1) * chip->bank_size +
+		       offset - chip->bank_start;
+	else
+		return chip->words + offset;
+}
 
 /* Return negative errno on error. */
 static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
@@ -57,9 +138,11 @@ static s32 stub_xfer(struct i2c_adapter
 	s32 ret;
 	int i, len;
 	struct stub_chip *chip = NULL;
+	struct smbus_block_data *b;
+	u16 *wordp;
 
 	/* Search for the right chip */
-	for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+	for (i = 0; i < stub_chips_nr; i++) {
 		if (addr == chip_addr[i]) {
 			chip = stub_chips + i;
 			break;
@@ -82,7 +165,8 @@ static s32 stub_xfer(struct i2c_adapter
 				"smbus byte - addr 0x%02x, wrote 0x%02x.\n",
 				addr, command);
 		} else {
-			data->byte = chip->words[chip->pointer++] & 0xff;
+			wordp = stub_get_wordp(chip, chip->pointer++);
+			data->byte = *wordp & 0xff;
 			dev_dbg(&adap->dev,
 				"smbus byte - addr 0x%02x, read  0x%02x.\n",
 				addr, data->byte);
@@ -92,14 +176,25 @@ static s32 stub_xfer(struct i2c_adapter
 		break;
 
 	case I2C_SMBUS_BYTE_DATA:
+		wordp = stub_get_wordp(chip, command);
 		if (read_write == I2C_SMBUS_WRITE) {
-			chip->words[command] &= 0xff00;
-			chip->words[command] |= data->byte;
+			*wordp &= 0xff00;
+			*wordp |= data->byte;
 			dev_dbg(&adap->dev,
 				"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
 				addr, data->byte, command);
+
+			/* Set the bank as needed */
+			if (chip->bank_words && command == chip->bank_reg) {
+				chip->bank_sel =
+					(data->byte >> chip->bank_shift)
+					& chip->bank_mask;
+				dev_dbg(&adap->dev,
+					"switching to bank %u.\n",
+					chip->bank_sel);
+			}
 		} else {
-			data->byte = chip->words[command] & 0xff;
+			data->byte = *wordp & 0xff;
 			dev_dbg(&adap->dev,
 				"smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
 				addr, data->byte, command);
@@ -110,13 +205,14 @@ static s32 stub_xfer(struct i2c_adapter
 		break;
 
 	case I2C_SMBUS_WORD_DATA:
+		wordp = stub_get_wordp(chip, command);
 		if (read_write == I2C_SMBUS_WRITE) {
-			chip->words[command] = data->word;
+			*wordp = data->word;
 			dev_dbg(&adap->dev,
 				"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
 				addr, data->word, command);
 		} else {
-			data->word = chip->words[command];
+			data->word = *wordp;
 			dev_dbg(&adap->dev,
 				"smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
 				addr, data->word, command);
@@ -126,6 +222,12 @@ static s32 stub_xfer(struct i2c_adapter
 		break;
 
 	case I2C_SMBUS_I2C_BLOCK_DATA:
+		/*
+		 * We ignore banks here, because banked chips don't use I2C
+		 * block transfers
+		 */
+		if (data->block[0] > 256 - command)	/* Avoid overrun */
+			data->block[0] = 256 - command;
 		len = data->block[0];
 		if (read_write == I2C_SMBUS_WRITE) {
 			for (i = 0; i < len; i++) {
@@ -148,6 +250,55 @@ static s32 stub_xfer(struct i2c_adapter
 		ret = 0;
 		break;
 
+	case I2C_SMBUS_BLOCK_DATA:
+		/*
+		 * We ignore banks here, because chips typically don't use both
+		 * banks and SMBus block transfers
+		 */
+		b = stub_find_block(&adap->dev, chip, command, false);
+		if (read_write == I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
+				ret = -EINVAL;
+				break;
+			}
+			if (b == NULL) {
+				b = stub_find_block(&adap->dev, chip, command,
+						    true);
+				if (b == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+			}
+			/* Largest write sets read block length */
+			if (len > b->len)
+				b->len = len;
+			for (i = 0; i < len; i++)
+				b->block[i] = data->block[i + 1];
+			/* update for byte and word commands */
+			chip->words[command] = (b->block[0] << 8) | b->len;
+			dev_dbg(&adap->dev,
+				"smbus block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+				addr, len, command);
+		} else {
+			if (b == NULL) {
+				dev_dbg(&adap->dev,
+					"SMBus block read command without prior block write not supported\n");
+				ret = -EOPNOTSUPP;
+				break;
+			}
+			len = b->len;
+			data->block[0] = len;
+			for (i = 0; i < len; i++)
+				data->block[i + 1] = b->block[i];
+			dev_dbg(&adap->dev,
+				"smbus block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+				addr, len, command);
+		}
+
+		ret = 0;
+		break;
+
 	default:
 		dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
 		ret = -EOPNOTSUPP;
@@ -159,7 +310,7 @@ static s32 stub_xfer(struct i2c_adapter
 
 static u32 stub_func(struct i2c_adapter *adapter)
 {
-	return STUB_FUNC & functionality;
+	return STUB_FUNC_ALL & functionality;
 }
 
 static const struct i2c_algorithm smbus_algorithm = {
@@ -174,6 +325,43 @@ static struct i2c_adapter stub_adapter =
 	.name		= "SMBus stub driver",
 };
 
+static int __init i2c_stub_allocate_banks(int i)
+{
+	struct stub_chip *chip = stub_chips + i;
+
+	chip->bank_reg = bank_reg[i];
+	chip->bank_start = bank_start[i];
+	chip->bank_end = bank_end[i];
+	chip->bank_size = bank_end[i] - bank_start[i] + 1;
+
+	/* We assume that all bits in the mask are contiguous */
+	chip->bank_mask = bank_mask[i];
+	while (!(chip->bank_mask & 1)) {
+		chip->bank_shift++;
+		chip->bank_mask >>= 1;
+	}
+
+	chip->bank_words = kzalloc(chip->bank_mask * chip->bank_size *
+				   sizeof(u16), GFP_KERNEL);
+	if (!chip->bank_words)
+		return -ENOMEM;
+
+	pr_debug("i2c-stub: Allocated %u banks of %u words each (registers 0x%02x to 0x%02x)\n",
+		 chip->bank_mask, chip->bank_size, chip->bank_start,
+		 chip->bank_end);
+
+	return 0;
+}
+
+static void i2c_stub_free(void)
+{
+	int i;
+
+	for (i = 0; i < stub_chips_nr; i++)
+		kfree(stub_chips[i].bank_words);
+	kfree(stub_chips);
+}
+
 static int __init i2c_stub_init(void)
 {
 	int i, ret;
@@ -194,22 +382,39 @@ static int __init i2c_stub_init(void)
 	}
 
 	/* Allocate memory for all chips at once */
-	stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
+	stub_chips_nr = i;
+	stub_chips = kcalloc(stub_chips_nr, sizeof(struct stub_chip),
+			     GFP_KERNEL);
 	if (!stub_chips) {
 		pr_err("i2c-stub: Out of memory\n");
 		return -ENOMEM;
 	}
+	for (i = 0; i < stub_chips_nr; i++) {
+		INIT_LIST_HEAD(&stub_chips[i].smbus_blocks);
+
+		/* Allocate extra memory for banked register ranges */
+		if (bank_mask[i]) {
+			ret = i2c_stub_allocate_banks(i);
+			if (ret)
+				goto fail_free;
+		}
+	}
 
 	ret = i2c_add_adapter(&stub_adapter);
 	if (ret)
-		kfree(stub_chips);
+		goto fail_free;
+
+	return 0;
+
+ fail_free:
+	i2c_stub_free();
 	return ret;
 }
 
 static void __exit i2c_stub_exit(void)
 {
 	i2c_del_adapter(&stub_adapter);
-	kfree(stub_chips);
+	i2c_stub_free();
 }
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/Kconfig linux-libre-3.17-rc7-gnu/drivers/i2c/Kconfig
--- linux-libre-3.16-gnu/drivers/i2c/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,9 @@
 # I2C subsystem configuration
 #
 
-menuconfig I2C
+menu "I2C support"
+
+config I2C
 	tristate "I2C support"
 	select RT_MUTEXES
 	---help---
@@ -21,6 +23,15 @@ menuconfig I2C
 	  This I2C support can also be built as a module.  If so, the module
 	  will be called i2c-core.
 
+config ACPI_I2C_OPREGION
+	bool "ACPI I2C Operation region support"
+	depends on I2C=y && ACPI
+	default y
+	help
+	  Say Y here if you want to enable ACPI I2C operation region support.
+	  Operation Regions allow firmware (BIOS) code to access I2C slave devices,
+	  such as smart batteries through an I2C host controller driver.
+
 if I2C
 
 config I2C_BOARDINFO
@@ -124,3 +135,5 @@ config I2C_DEBUG_BUS
 	  on.
 
 endif # I2C
+
+endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c linux-libre-3.17-rc7-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c
--- linux-libre-3.16-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/i2c-mux.h>
 #include <linux/i2c/pca954x.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 
 #define PCA954X_MAX_NCHANS 8
@@ -273,9 +274,23 @@ static int pca954x_remove(struct i2c_cli
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pca954x_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pca954x *data = i2c_get_clientdata(client);
+
+	data->last_chan = 0;
+	return i2c_smbus_write_byte(client, 0);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume);
+
 static struct i2c_driver pca954x_driver = {
 	.driver		= {
 		.name	= "pca954x",
+		.pm	= &pca954x_pm,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pca954x_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ide/au1xxx-ide.c linux-libre-3.17-rc7-gnu/drivers/ide/au1xxx-ide.c
--- linux-libre-3.16-gnu/drivers/ide/au1xxx-ide.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ide/au1xxx-ide.c	2014-09-28 17:29:07.000000000 -0400
@@ -592,18 +592,7 @@ static struct platform_driver au1200_ide
 	.remove		= au_ide_remove,
 };
 
-static int __init au_ide_init(void)
-{
-	return platform_driver_register(&au1200_ide_driver);
-}
-
-static void __exit au_ide_exit(void)
-{
-	platform_driver_unregister(&au1200_ide_driver);
-}
+module_platform_driver(au1200_ide_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AU1200 IDE driver");
-
-module_init(au_ide_init);
-module_exit(au_ide_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ide/ide_platform.c linux-libre-3.17-rc7-gnu/drivers/ide/ide_platform.c
--- linux-libre-3.16-gnu/drivers/ide/ide_platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ide/ide_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,19 +131,8 @@ static struct platform_driver platform_i
 	.remove = plat_ide_remove,
 };
 
-static int __init platform_ide_init(void)
-{
-	return platform_driver_register(&platform_ide_driver);
-}
-
-static void __exit platform_ide_exit(void)
-{
-	platform_driver_unregister(&platform_ide_driver);
-}
+module_platform_driver(platform_ide_driver);
 
 MODULE_DESCRIPTION("Platform IDE driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:pata_platform");
-
-module_init(platform_ide_init);
-module_exit(platform_ide_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/idle/intel_idle.c linux-libre-3.17-rc7-gnu/drivers/idle/intel_idle.c
--- linux-libre-3.16-gnu/drivers/idle/intel_idle.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/idle/intel_idle.c	2014-09-28 17:29:07.000000000 -0400
@@ -89,6 +89,7 @@ struct idle_cpu {
 	 * Indicate which enable bits to clear here.
 	 */
 	unsigned long auto_demotion_disable_flags;
+	bool byt_auto_demotion_disable_flag;
 	bool disable_promotion_to_c1e;
 };
 
@@ -442,6 +443,66 @@ static struct cpuidle_state hsw_cstates[
 	{
 		.enter = NULL }
 };
+static struct cpuidle_state bdw_cstates[] = {
+	{
+		.name = "C1-BDW",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
+		.exit_latency = 2,
+		.target_residency = 2,
+		.enter = &intel_idle },
+	{
+		.name = "C1E-BDW",
+		.desc = "MWAIT 0x01",
+		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+		.exit_latency = 10,
+		.target_residency = 20,
+		.enter = &intel_idle },
+	{
+		.name = "C3-BDW",
+		.desc = "MWAIT 0x10",
+		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 40,
+		.target_residency = 100,
+		.enter = &intel_idle },
+	{
+		.name = "C6-BDW",
+		.desc = "MWAIT 0x20",
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 133,
+		.target_residency = 400,
+		.enter = &intel_idle },
+	{
+		.name = "C7s-BDW",
+		.desc = "MWAIT 0x32",
+		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 166,
+		.target_residency = 500,
+		.enter = &intel_idle },
+	{
+		.name = "C8-BDW",
+		.desc = "MWAIT 0x40",
+		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 300,
+		.target_residency = 900,
+		.enter = &intel_idle },
+	{
+		.name = "C9-BDW",
+		.desc = "MWAIT 0x50",
+		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 600,
+		.target_residency = 1800,
+		.enter = &intel_idle },
+	{
+		.name = "C10-BDW",
+		.desc = "MWAIT 0x60",
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 2600,
+		.target_residency = 7700,
+		.enter = &intel_idle },
+	{
+		.enter = NULL }
+};
 
 static struct cpuidle_state atom_cstates[] = {
 	{
@@ -613,6 +674,7 @@ static const struct idle_cpu idle_cpu_sn
 static const struct idle_cpu idle_cpu_byt = {
 	.state_table = byt_cstates,
 	.disable_promotion_to_c1e = true,
+	.byt_auto_demotion_disable_flag = true,
 };
 
 static const struct idle_cpu idle_cpu_ivb = {
@@ -630,6 +692,11 @@ static const struct idle_cpu idle_cpu_hs
 	.disable_promotion_to_c1e = true,
 };
 
+static const struct idle_cpu idle_cpu_bdw = {
+	.state_table = bdw_cstates,
+	.disable_promotion_to_c1e = true,
+};
+
 static const struct idle_cpu idle_cpu_avn = {
 	.state_table = avn_cstates,
 	.disable_promotion_to_c1e = true,
@@ -658,7 +725,10 @@ static const struct x86_cpu_id intel_idl
 	ICPU(0x3f, idle_cpu_hsw),
 	ICPU(0x45, idle_cpu_hsw),
 	ICPU(0x46, idle_cpu_hsw),
-	ICPU(0x4D, idle_cpu_avn),
+	ICPU(0x4d, idle_cpu_avn),
+	ICPU(0x3d, idle_cpu_bdw),
+	ICPU(0x4f, idle_cpu_bdw),
+	ICPU(0x56, idle_cpu_bdw),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
@@ -814,6 +884,11 @@ static int __init intel_idle_cpuidle_dri
 	if (icpu->auto_demotion_disable_flags)
 		on_each_cpu(auto_demotion_disable, NULL, 1);
 
+	if (icpu->byt_auto_demotion_disable_flag) {
+		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
+		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
+	}
+
 	if (icpu->disable_promotion_to_c1e)	/* each-cpu is redundant */
 		on_each_cpu(c1e_promotion_disable, NULL, 1);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/bma180.c linux-libre-3.17-rc7-gnu/drivers/iio/accel/bma180.c
--- linux-libre-3.16-gnu/drivers/iio/accel/bma180.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/bma180.c	2014-09-28 17:29:07.000000000 -0400
@@ -571,7 +571,7 @@ static int bma180_probe(struct i2c_clien
 	trig->ops = &bma180_trigger_ops;
 	iio_trigger_set_drvdata(trig, indio_dev);
 	data->trig = trig;
-	indio_dev->trig = trig;
+	indio_dev->trig = iio_trigger_get(trig);
 
 	ret = iio_trigger_register(trig);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/accel/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/accel/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -77,4 +77,16 @@ config MMA8452
 	  To compile this driver as a module, choose M here: the module
 	  will be called mma8452.
 
+config KXCJK1013
+	tristate "Kionix 3-Axis Accelerometer Driver"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say Y here if you want to build a driver for the Kionix KXCJK-1013
+	  triaxial acceleration sensor.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called kxcjk-1013.
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/kxcjk-1013.c linux-libre-3.17-rc7-gnu/drivers/iio/accel/kxcjk-1013.c
--- linux-libre-3.16-gnu/drivers/iio/accel/kxcjk-1013.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/kxcjk-1013.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,764 @@
+/*
+ * KXCJK-1013 3-axis accelerometer driver
+ * Copyright (c) 2014, 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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/accel/kxcjk_1013.h>
+
+#define KXCJK1013_DRV_NAME "kxcjk1013"
+#define KXCJK1013_IRQ_NAME "kxcjk1013_event"
+
+#define KXCJK1013_REG_XOUT_L		0x06
+/*
+ * From low byte X axis register, all the other addresses of Y and Z can be
+ * obtained by just applying axis offset. The following axis defines are just
+ * provide clarity, but not used.
+ */
+#define KXCJK1013_REG_XOUT_H		0x07
+#define KXCJK1013_REG_YOUT_L		0x08
+#define KXCJK1013_REG_YOUT_H		0x09
+#define KXCJK1013_REG_ZOUT_L		0x0A
+#define KXCJK1013_REG_ZOUT_H		0x0B
+
+#define KXCJK1013_REG_DCST_RESP		0x0C
+#define KXCJK1013_REG_WHO_AM_I		0x0F
+#define KXCJK1013_REG_INT_SRC1		0x16
+#define KXCJK1013_REG_INT_SRC2		0x17
+#define KXCJK1013_REG_STATUS_REG	0x18
+#define KXCJK1013_REG_INT_REL		0x1A
+#define KXCJK1013_REG_CTRL1		0x1B
+#define KXCJK1013_REG_CTRL2		0x1D
+#define KXCJK1013_REG_INT_CTRL1		0x1E
+#define KXCJK1013_REG_INT_CTRL2		0x1F
+#define KXCJK1013_REG_DATA_CTRL		0x21
+#define KXCJK1013_REG_WAKE_TIMER	0x29
+#define KXCJK1013_REG_SELF_TEST		0x3A
+#define KXCJK1013_REG_WAKE_THRES	0x6A
+
+#define KXCJK1013_REG_CTRL1_BIT_PC1	BIT(7)
+#define KXCJK1013_REG_CTRL1_BIT_RES	BIT(6)
+#define KXCJK1013_REG_CTRL1_BIT_DRDY	BIT(5)
+#define KXCJK1013_REG_CTRL1_BIT_GSEL1	BIT(4)
+#define KXCJK1013_REG_CTRL1_BIT_GSEL0	BIT(3)
+#define KXCJK1013_REG_CTRL1_BIT_WUFE	BIT(1)
+#define KXCJK1013_REG_INT_REG1_BIT_IEA	BIT(4)
+#define KXCJK1013_REG_INT_REG1_BIT_IEN	BIT(5)
+
+#define KXCJK1013_DATA_MASK_12_BIT	0x0FFF
+#define KXCJK1013_MAX_STARTUP_TIME_US	100000
+
+struct kxcjk1013_data {
+	struct i2c_client *client;
+	struct iio_trigger *trig;
+	bool trig_mode;
+	struct mutex mutex;
+	s16 buffer[8];
+	int power_state;
+	u8 odr_bits;
+	bool active_high_intr;
+};
+
+enum kxcjk1013_axis {
+	AXIS_X,
+	AXIS_Y,
+	AXIS_Z,
+};
+
+enum kxcjk1013_mode {
+	STANDBY,
+	OPERATION,
+};
+
+static const struct {
+	int val;
+	int val2;
+	int odr_bits;
+} samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09},
+			{3, 125000, 0x0A}, {6, 250000, 0x0B}, {12, 500000, 0},
+			{25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03},
+			{200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06},
+			{1600, 0, 0x07} };
+
+/* Refer to section 4 of the specification */
+static const struct {
+	int odr_bits;
+	int usec;
+} odr_start_up_times[] = { {0x08, 100000}, {0x09, 100000}, {0x0A, 100000},
+			   {0x0B, 100000}, { 0, 80000}, {0x01, 41000},
+			   {0x02, 21000}, {0x03, 11000}, {0x04, 6400},
+			   {0x05, 3900}, {0x06, 2700}, {0x07, 2100} };
+
+static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
+			      enum kxcjk1013_mode mode)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+		return ret;
+	}
+
+	if (mode == STANDBY)
+		ret &= ~KXCJK1013_REG_CTRL1_BIT_PC1;
+	else
+		ret |= KXCJK1013_REG_CTRL1_BIT_PC1;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					KXCJK1013_REG_CTRL1, ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading who_am_i\n");
+		return ret;
+	}
+
+	dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret);
+
+	ret = kxcjk1013_set_mode(data, STANDBY);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+		return ret;
+	}
+
+	/* Setting range to 4G */
+	ret |= KXCJK1013_REG_CTRL1_BIT_GSEL0;
+	ret &= ~KXCJK1013_REG_CTRL1_BIT_GSEL1;
+
+	/* Set 12 bit mode */
+	ret |= KXCJK1013_REG_CTRL1_BIT_RES;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1,
+					ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_ctrl\n");
+		return ret;
+	}
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
+		return ret;
+	}
+
+	data->odr_bits = ret;
+
+	/* Set up INT polarity */
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
+		return ret;
+	}
+
+	if (data->active_high_intr)
+		ret |= KXCJK1013_REG_INT_REG1_BIT_IEA;
+	else
+		ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEA;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
+					ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
+					  bool status)
+{
+	int ret;
+
+	/* This is requirement by spec to change state to STANDBY */
+	ret = kxcjk1013_set_mode(data, STANDBY);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
+		return ret;
+	}
+
+	if (status)
+		ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
+	else
+		ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
+					ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
+		return ret;
+	}
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+		return ret;
+	}
+
+	if (status)
+		ret |= KXCJK1013_REG_CTRL1_BIT_DRDY;
+	else
+		ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					KXCJK1013_REG_CTRL1, ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int kxcjk1013_convert_freq_to_bit(int val, int val2)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
+		if (samp_freq_table[i].val == val &&
+			samp_freq_table[i].val2 == val2) {
+			return samp_freq_table[i].odr_bits;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
+{
+	int ret;
+	int odr_bits;
+
+	odr_bits = kxcjk1013_convert_freq_to_bit(val, val2);
+	if (odr_bits < 0)
+		return odr_bits;
+
+	/* To change ODR, the chip must be set to STANDBY as per spec */
+	ret = kxcjk1013_set_mode(data, STANDBY);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL,
+					odr_bits);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing data_ctrl\n");
+		return ret;
+	}
+
+	data->odr_bits = odr_bits;
+
+	/* Check, if the ODR is changed after data enable */
+	if (data->power_state) {
+		/* Set the state back to operation */
+		ret = kxcjk1013_set_mode(data, OPERATION);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
+		if (samp_freq_table[i].odr_bits == data->odr_bits) {
+			*val = samp_freq_table[i].val;
+			*val2 = samp_freq_table[i].val2;
+			return IIO_VAL_INT_PLUS_MICRO;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis)
+{
+	u8 reg = KXCJK1013_REG_XOUT_L + axis * 2;
+	int ret;
+
+	ret = i2c_smbus_read_word_data(data->client, reg);
+	if (ret < 0) {
+		dev_err(&data->client->dev,
+			"failed to read accel_%c registers\n", 'x' + axis);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(odr_start_up_times); ++i) {
+		if (odr_start_up_times[i].odr_bits == data->odr_bits)
+			return odr_start_up_times[i].usec;
+	}
+
+	return KXCJK1013_MAX_STARTUP_TIME_US;
+}
+
+static int kxcjk1013_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan, int *val,
+			      int *val2, long mask)
+{
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&data->mutex);
+		if (iio_buffer_enabled(indio_dev))
+			ret = -EBUSY;
+		else {
+			int sleep_val;
+
+			ret = kxcjk1013_set_mode(data, OPERATION);
+			if (ret < 0) {
+				mutex_unlock(&data->mutex);
+				return ret;
+			}
+			++data->power_state;
+			sleep_val = kxcjk1013_get_startup_times(data);
+			if (sleep_val < 20000)
+				usleep_range(sleep_val, 20000);
+			else
+				msleep_interruptible(sleep_val/1000);
+			ret = kxcjk1013_get_acc_reg(data, chan->scan_index);
+			if (--data->power_state == 0)
+				kxcjk1013_set_mode(data, STANDBY);
+		}
+		mutex_unlock(&data->mutex);
+
+		if (ret < 0)
+			return ret;
+
+		*val = sign_extend32(ret >> 4, 11);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = 19163; /* range +-4g (4/2047*9.806650) */
+		return IIO_VAL_INT_PLUS_MICRO;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		mutex_lock(&data->mutex);
+		ret = kxcjk1013_get_odr(data, val, val2);
+		mutex_unlock(&data->mutex);
+		return ret;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int kxcjk1013_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan, int val,
+			       int val2, long mask)
+{
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		mutex_lock(&data->mutex);
+		ret = kxcjk1013_set_odr(data, val, val2);
+		mutex_unlock(&data->mutex);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev,
+				      struct iio_trigger *trig)
+{
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	if (data->trig != trig)
+		return -EINVAL;
+
+	return 0;
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
+	"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600");
+
+static struct attribute *kxcjk1013_attributes[] = {
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group kxcjk1013_attrs_group = {
+	.attrs = kxcjk1013_attributes,
+};
+
+#define KXCJK1013_CHANNEL(_axis) {					\
+	.type = IIO_ACCEL,						\
+	.modified = 1,							\
+	.channel2 = IIO_MOD_##_axis,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |		\
+				BIT(IIO_CHAN_INFO_SAMP_FREQ),		\
+	.scan_index = AXIS_##_axis,					\
+	.scan_type = {							\
+		.sign = 's',						\
+		.realbits = 12,						\
+		.storagebits = 16,					\
+		.shift = 4,						\
+		.endianness = IIO_CPU,					\
+	},								\
+}
+
+static const struct iio_chan_spec kxcjk1013_channels[] = {
+	KXCJK1013_CHANNEL(X),
+	KXCJK1013_CHANNEL(Y),
+	KXCJK1013_CHANNEL(Z),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_info kxcjk1013_info = {
+	.attrs			= &kxcjk1013_attrs_group,
+	.read_raw		= kxcjk1013_read_raw,
+	.write_raw		= kxcjk1013_write_raw,
+	.validate_trigger	= kxcjk1013_validate_trigger,
+	.driver_module		= THIS_MODULE,
+};
+
+static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int bit, ret, i = 0;
+
+	mutex_lock(&data->mutex);
+
+	for_each_set_bit(bit, indio_dev->buffer->scan_mask,
+			 indio_dev->masklength) {
+		ret = kxcjk1013_get_acc_reg(data, bit);
+		if (ret < 0) {
+			mutex_unlock(&data->mutex);
+			goto err;
+		}
+		data->buffer[i++] = ret;
+	}
+	mutex_unlock(&data->mutex);
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+					   pf->timestamp);
+err:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int kxcjk1013_trig_try_reen(struct iio_trigger *trig)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_int_rel\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	mutex_lock(&data->mutex);
+	if (state) {
+		kxcjk1013_chip_setup_interrupt(data, true);
+		kxcjk1013_set_mode(data, OPERATION);
+		++data->power_state;
+	} else {
+		if (--data->power_state) {
+			mutex_unlock(&data->mutex);
+			return 0;
+		}
+		kxcjk1013_chip_setup_interrupt(data, false);
+		kxcjk1013_set_mode(data, STANDBY);
+	}
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
+	.set_trigger_state = kxcjk1013_data_rdy_trigger_set_state,
+	.try_reenable = kxcjk1013_trig_try_reen,
+	.owner = THIS_MODULE,
+};
+
+static int kxcjk1013_acpi_gpio_probe(struct i2c_client *client,
+				     struct kxcjk1013_data *data)
+{
+	const struct acpi_device_id *id;
+	struct device *dev;
+	struct gpio_desc *gpio;
+	int ret;
+
+	if (!client)
+		return -EINVAL;
+
+	dev = &client->dev;
+	if (!ACPI_HANDLE(dev))
+		return -ENODEV;
+
+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
+	if (!id)
+		return -ENODEV;
+
+	/* data ready gpio interrupt pin */
+	gpio = devm_gpiod_get_index(dev, "kxcjk1013_int", 0);
+	if (IS_ERR(gpio)) {
+		dev_err(dev, "acpi gpio get index failed\n");
+		return PTR_ERR(gpio);
+	}
+
+	ret = gpiod_direction_input(gpio);
+	if (ret)
+		return ret;
+
+	ret = gpiod_to_irq(gpio);
+
+	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+	return ret;
+}
+
+static int kxcjk1013_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct kxcjk1013_data *data;
+	struct iio_dev *indio_dev;
+	struct iio_trigger *trig = NULL;
+	struct kxcjk_1013_platform_data *pdata;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+
+	pdata = dev_get_platdata(&client->dev);
+	if (pdata)
+		data->active_high_intr = pdata->active_high_intr;
+	else
+		data->active_high_intr = true; /* default polarity */
+
+	ret = kxcjk1013_chip_init(data);
+	if (ret < 0)
+		return ret;
+
+	mutex_init(&data->mutex);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = kxcjk1013_channels;
+	indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
+	indio_dev->name = KXCJK1013_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &kxcjk1013_info;
+
+	if (client->irq < 0)
+		client->irq = kxcjk1013_acpi_gpio_probe(client, data);
+
+	if (client->irq >= 0) {
+		trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+					 indio_dev->id);
+		if (!trig)
+			return -ENOMEM;
+
+		data->trig_mode = true;
+
+		ret = devm_request_irq(&client->dev, client->irq,
+					iio_trigger_generic_data_rdy_poll,
+					IRQF_TRIGGER_RISING,
+					KXCJK1013_IRQ_NAME,
+					trig);
+		if (ret) {
+			dev_err(&client->dev, "unable to request IRQ\n");
+			goto err_trigger_free;
+		}
+
+		trig->dev.parent = &client->dev;
+		trig->ops = &kxcjk1013_trigger_ops;
+		iio_trigger_set_drvdata(trig, indio_dev);
+		data->trig = trig;
+		indio_dev->trig = trig;
+		iio_trigger_get(indio_dev->trig);
+
+		ret = iio_trigger_register(trig);
+		if (ret)
+			goto err_trigger_free;
+
+		ret = iio_triggered_buffer_setup(indio_dev,
+						&iio_pollfunc_store_time,
+						kxcjk1013_trigger_handler,
+						NULL);
+		if (ret < 0) {
+			dev_err(&client->dev,
+					"iio triggered buffer setup failed\n");
+			goto err_trigger_unregister;
+		}
+	}
+
+	ret = devm_iio_device_register(&client->dev, indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "unable to register iio device\n");
+		goto err_buffer_cleanup;
+	}
+
+	return 0;
+
+err_buffer_cleanup:
+	if (data->trig_mode)
+		iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+	if (data->trig_mode)
+		iio_trigger_unregister(trig);
+err_trigger_free:
+	if (data->trig_mode)
+		iio_trigger_free(trig);
+
+	return ret;
+}
+
+static int kxcjk1013_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	if (data->trig_mode) {
+		iio_triggered_buffer_cleanup(indio_dev);
+		iio_trigger_unregister(data->trig);
+		iio_trigger_free(data->trig);
+	}
+
+	mutex_lock(&data->mutex);
+	kxcjk1013_set_mode(data, STANDBY);
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int kxcjk1013_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	mutex_lock(&data->mutex);
+	kxcjk1013_set_mode(data, STANDBY);
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+static int kxcjk1013_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	mutex_lock(&data->mutex);
+
+	if (data->power_state)
+		kxcjk1013_set_mode(data, OPERATION);
+
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(kxcjk1013_pm_ops, kxcjk1013_suspend, kxcjk1013_resume);
+#define KXCJK1013_PM_OPS (&kxcjk1013_pm_ops)
+#else
+#define KXCJK1013_PM_OPS NULL
+#endif
+
+static const struct acpi_device_id kx_acpi_match[] = {
+	{"KXCJ1013", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
+
+static const struct i2c_device_id kxcjk1013_id[] = {
+	{"kxcjk1013", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
+
+static struct i2c_driver kxcjk1013_driver = {
+	.driver = {
+		.name	= KXCJK1013_DRV_NAME,
+		.acpi_match_table = ACPI_PTR(kx_acpi_match),
+		.pm	= KXCJK1013_PM_OPS,
+	},
+	.probe		= kxcjk1013_probe,
+	.remove		= kxcjk1013_remove,
+	.id_table	= kxcjk1013_id,
+};
+module_i2c_driver(kxcjk1013_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("KXCJK1013 accelerometer driver");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/accel/Makefile
--- linux-libre-3.16-gnu/drivers/iio/accel/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
+obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
 obj-$(CONFIG_KXSD9)	+= kxsd9.o
 obj-$(CONFIG_MMA8452)	+= mma8452.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/mma8452.c linux-libre-3.17-rc7-gnu/drivers/iio/accel/mma8452.c
--- linux-libre-3.16-gnu/drivers/iio/accel/mma8452.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/mma8452.c	2014-09-28 17:29:07.000000000 -0400
@@ -429,9 +429,15 @@ static const struct i2c_device_id mma845
 };
 MODULE_DEVICE_TABLE(i2c, mma8452_id);
 
+static const struct of_device_id mma8452_dt_ids[] = {
+	{ .compatible = "fsl,mma8452" },
+	{ }
+};
+
 static struct i2c_driver mma8452_driver = {
 	.driver = {
 		.name	= "mma8452",
+		.of_match_table = of_match_ptr(mma8452_dt_ids),
 		.pm	= MMA8452_PM_OPS,
 	},
 	.probe = mma8452_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/st_accel_core.c linux-libre-3.17-rc7-gnu/drivers/iio/accel/st_accel_core.c
--- linux-libre-3.16-gnu/drivers/iio/accel/st_accel_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/st_accel_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -393,6 +393,9 @@ static int st_accel_read_raw(struct iio_
 		*val = 0;
 		*val2 = adata->current_fullscale->gain;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = adata->odr;
+		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
 	}
@@ -410,6 +413,13 @@ static int st_accel_write_raw(struct iio
 	case IIO_CHAN_INFO_SCALE:
 		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&indio_dev->mlock);
+		err = st_sensors_set_odr(indio_dev, val);
+		mutex_unlock(&indio_dev->mlock);
+		return err;
 	default:
 		return -EINVAL;
 	}
@@ -417,14 +427,12 @@ static int st_accel_write_raw(struct iio
 	return err;
 }
 
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
 
 static struct attribute *st_accel_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/accel/st_accel_i2c.c linux-libre-3.17-rc7-gnu/drivers/iio/accel/st_accel_i2c.c
--- linux-libre-3.16-gnu/drivers/iio/accel/st_accel_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/accel/st_accel_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,55 @@
 #include <linux/iio/common/st_sensors_i2c.h>
 #include "st_accel.h"
 
+#ifdef CONFIG_OF
+static const struct of_device_id st_accel_of_match[] = {
+	{
+		.compatible = "st,lsm303dlh-accel",
+		.data = LSM303DLH_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm303dlhc-accel",
+		.data = LSM303DLHC_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lis3dh-accel",
+		.data = LIS3DH_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330d-accel",
+		.data = LSM330D_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330dl-accel",
+		.data = LSM330DL_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330dlc-accel",
+		.data = LSM330DLC_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lis331dlh-accel",
+		.data = LIS331DLH_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm303dl-accel",
+		.data = LSM303DL_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm303dlm-accel",
+		.data = LSM303DLM_ACCEL_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330-accel",
+		.data = LSM330_ACCEL_DEV_NAME,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_accel_of_match);
+#else
+#define st_accel_of_match NULL
+#endif
+
 static int st_accel_i2c_probe(struct i2c_client *client,
 						const struct i2c_device_id *id)
 {
@@ -31,6 +80,7 @@ static int st_accel_i2c_probe(struct i2c
 
 	adata = iio_priv(indio_dev);
 	adata->dev = &client->dev;
+	st_sensors_of_i2c_probe(client, st_accel_of_match);
 
 	st_sensors_i2c_configure(indio_dev, client, adata);
 
@@ -67,6 +117,7 @@ static struct i2c_driver st_accel_driver
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "st-accel-i2c",
+		.of_match_table = of_match_ptr(st_accel_of_match),
 	},
 	.probe = st_accel_i2c_probe,
 	.remove = st_accel_i2c_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad7291.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7291.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad7291.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7291.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,585 @@
+/*
+ * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+
+#include <linux/platform_data/ad7291.h>
+
+/*
+ * Simplified handling
+ *
+ * If no events enabled - single polled channel read
+ * If event enabled direct reads disable unless channel
+ * is in the read mask.
+ *
+ * The noise-delayed bit as per datasheet suggestion is always enabled.
+ */
+
+/*
+ * AD7291 registers definition
+ */
+#define AD7291_COMMAND			0x00
+#define AD7291_VOLTAGE			0x01
+#define AD7291_T_SENSE			0x02
+#define AD7291_T_AVERAGE		0x03
+#define AD7291_DATA_HIGH(x)		((x) * 3 + 0x4)
+#define AD7291_DATA_LOW(x)		((x) * 3 + 0x5)
+#define AD7291_HYST(x)			((x) * 3 + 0x6)
+#define AD7291_VOLTAGE_ALERT_STATUS	0x1F
+#define AD7291_T_ALERT_STATUS		0x20
+
+#define AD7291_BITS			12
+#define AD7291_VOLTAGE_LIMIT_COUNT	8
+
+
+/*
+ * AD7291 command
+ */
+#define AD7291_AUTOCYCLE		BIT(0)
+#define AD7291_RESET			BIT(1)
+#define AD7291_ALERT_CLEAR		BIT(2)
+#define AD7291_ALERT_POLARITY		BIT(3)
+#define AD7291_EXT_REF			BIT(4)
+#define AD7291_NOISE_DELAY		BIT(5)
+#define AD7291_T_SENSE_MASK		BIT(7)
+#define AD7291_VOLTAGE_MASK		GENMASK(15, 8)
+#define AD7291_VOLTAGE_OFFSET		8
+
+/*
+ * AD7291 value masks
+ */
+#define AD7291_VALUE_MASK		GENMASK(11, 0)
+
+/*
+ * AD7291 alert register bits
+ */
+#define AD7291_T_LOW			BIT(0)
+#define AD7291_T_HIGH			BIT(1)
+#define AD7291_T_AVG_LOW		BIT(2)
+#define AD7291_T_AVG_HIGH		BIT(3)
+#define AD7291_V_LOW(x)			BIT((x) * 2)
+#define AD7291_V_HIGH(x)		BIT((x) * 2 + 1)
+
+
+struct ad7291_chip_info {
+	struct i2c_client	*client;
+	struct regulator	*reg;
+	u16			command;
+	u16			c_mask;	/* Active voltage channels for events */
+	struct mutex		state_lock;
+};
+
+static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
+{
+	struct i2c_client *client = chip->client;
+	int ret = 0;
+
+	ret = i2c_smbus_read_word_swapped(client, reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "I2C read error\n");
+		return ret;
+	}
+
+	*data = ret;
+
+	return 0;
+}
+
+static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_swapped(chip->client, reg, data);
+}
+
+static irqreturn_t ad7291_event_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct ad7291_chip_info *chip = iio_priv(private);
+	u16 t_status, v_status;
+	u16 command;
+	int i;
+	s64 timestamp = iio_get_time_ns();
+
+	if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
+		return IRQ_HANDLED;
+
+	if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
+		return IRQ_HANDLED;
+
+	if (!(t_status || v_status))
+		return IRQ_HANDLED;
+
+	command = chip->command | AD7291_ALERT_CLEAR;
+	ad7291_i2c_write(chip, AD7291_COMMAND, command);
+
+	command = chip->command & ~AD7291_ALERT_CLEAR;
+	ad7291_i2c_write(chip, AD7291_COMMAND, command);
+
+	/* For now treat t_sense and t_sense_average the same */
+	if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW))
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+						    0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_FALLING),
+			       timestamp);
+	if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH))
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+						    0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_RISING),
+			       timestamp);
+
+	for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
+		if (v_status & AD7291_V_LOW(i))
+			iio_push_event(indio_dev,
+				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+							    i,
+							    IIO_EV_TYPE_THRESH,
+							    IIO_EV_DIR_FALLING),
+				       timestamp);
+		if (v_status & AD7291_V_HIGH(i))
+			iio_push_event(indio_dev,
+				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+							    i,
+							    IIO_EV_TYPE_THRESH,
+							    IIO_EV_DIR_RISING),
+				       timestamp);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
+					 enum iio_event_direction dir,
+					 enum iio_event_info info)
+{
+	unsigned int offset;
+
+	switch (chan->type) {
+	case IIO_VOLTAGE:
+		offset = chan->channel;
+		break;
+	case IIO_TEMP:
+		offset = AD7291_VOLTAGE_OFFSET;
+		break;
+	default:
+	    return 0;
+	}
+
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+		if (dir == IIO_EV_DIR_FALLING)
+			return AD7291_DATA_HIGH(offset);
+		else
+			return AD7291_DATA_LOW(offset);
+	case IIO_EV_INFO_HYSTERESIS:
+		return AD7291_HYST(offset);
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int ad7291_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)
+{
+	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+	int ret;
+	u16 uval;
+
+	ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
+			      &uval);
+	if (ret < 0)
+		return ret;
+
+	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
+		*val = uval & AD7291_VALUE_MASK;
+
+	else
+		*val = sign_extend32(uval, 11);
+
+	return IIO_VAL_INT;
+}
+
+static int ad7291_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 ad7291_chip_info *chip = iio_priv(indio_dev);
+
+	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
+		if (val > AD7291_VALUE_MASK || val < 0)
+			return -EINVAL;
+	} else {
+		if (val > 2047 || val < -2048)
+			return -EINVAL;
+	}
+
+	return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
+				val);
+}
+
+static int ad7291_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 ad7291_chip_info *chip = iio_priv(indio_dev);
+	/*
+	 * To be enabled the channel must simply be on. If any are enabled
+	 * we are in continuous sampling mode
+	 */
+
+	switch (chan->type) {
+	case IIO_VOLTAGE:
+		return !!(chip->c_mask & BIT(15 - chan->channel));
+	case IIO_TEMP:
+		/* always on */
+		return 1;
+	default:
+		return -EINVAL;
+	}
+
+}
+
+static int ad7291_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)
+{
+	int ret = 0;
+	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+	unsigned int mask;
+	u16 regval;
+
+	mutex_lock(&chip->state_lock);
+	regval = chip->command;
+	/*
+	 * To be enabled the channel must simply be on. If any are enabled
+	 * use continuous sampling mode.
+	 * Possible to disable temp as well but that makes single read tricky.
+	 */
+
+	mask = BIT(15 - chan->channel);
+
+	switch (chan->type) {
+	case IIO_VOLTAGE:
+		if ((!state) && (chip->c_mask & mask))
+			chip->c_mask &= ~mask;
+		else if (state && (!(chip->c_mask & mask)))
+			chip->c_mask |= mask;
+		else
+			break;
+
+		regval &= ~AD7291_AUTOCYCLE;
+		regval |= chip->c_mask;
+		if (chip->c_mask) /* Enable autocycle? */
+			regval |= AD7291_AUTOCYCLE;
+
+		ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
+		if (ret < 0)
+			goto error_ret;
+
+		chip->command = regval;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+error_ret:
+	mutex_unlock(&chip->state_lock);
+	return ret;
+}
+
+static int ad7291_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long mask)
+{
+	int ret;
+	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+	u16 regval;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			mutex_lock(&chip->state_lock);
+			/* If in autocycle mode drop through */
+			if (chip->command & AD7291_AUTOCYCLE) {
+				mutex_unlock(&chip->state_lock);
+				return -EBUSY;
+			}
+			/* Enable this channel alone */
+			regval = chip->command & (~AD7291_VOLTAGE_MASK);
+			regval |= BIT(15 - chan->channel);
+			ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
+			if (ret < 0) {
+				mutex_unlock(&chip->state_lock);
+				return ret;
+			}
+			/* Read voltage */
+			ret = i2c_smbus_read_word_swapped(chip->client,
+							  AD7291_VOLTAGE);
+			if (ret < 0) {
+				mutex_unlock(&chip->state_lock);
+				return ret;
+			}
+			*val = ret & AD7291_VALUE_MASK;
+			mutex_unlock(&chip->state_lock);
+			return IIO_VAL_INT;
+		case IIO_TEMP:
+			/* Assumes tsense bit of command register always set */
+			ret = i2c_smbus_read_word_swapped(chip->client,
+							  AD7291_T_SENSE);
+			if (ret < 0)
+				return ret;
+			*val = sign_extend32(ret, 11);
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_AVERAGE_RAW:
+		ret = i2c_smbus_read_word_swapped(chip->client,
+						  AD7291_T_AVERAGE);
+			if (ret < 0)
+				return ret;
+			*val = sign_extend32(ret, 11);
+			return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			if (chip->reg) {
+				int vref;
+
+				vref = regulator_get_voltage(chip->reg);
+				if (vref < 0)
+					return vref;
+				*val = vref / 1000;
+			} else {
+				*val = 2500;
+			}
+			*val2 = AD7291_BITS;
+			return IIO_VAL_FRACTIONAL_LOG2;
+		case IIO_TEMP:
+			/*
+			 * One LSB of the ADC corresponds to 0.25 deg C.
+			 * The temperature reading is in 12-bit twos
+			 * complement format
+			 */
+			*val = 250;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_event_spec ad7291_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+	},
+};
+
+#define AD7291_VOLTAGE_CHAN(_chan)					\
+{									\
+	.type = IIO_VOLTAGE,						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
+	.indexed = 1,							\
+	.channel = _chan,						\
+	.event_spec = ad7291_events,					\
+	.num_event_specs = ARRAY_SIZE(ad7291_events),			\
+}
+
+static const struct iio_chan_spec ad7291_channels[] = {
+	AD7291_VOLTAGE_CHAN(0),
+	AD7291_VOLTAGE_CHAN(1),
+	AD7291_VOLTAGE_CHAN(2),
+	AD7291_VOLTAGE_CHAN(3),
+	AD7291_VOLTAGE_CHAN(4),
+	AD7291_VOLTAGE_CHAN(5),
+	AD7291_VOLTAGE_CHAN(6),
+	AD7291_VOLTAGE_CHAN(7),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
+				BIT(IIO_CHAN_INFO_SCALE),
+		.indexed = 1,
+		.channel = 0,
+		.event_spec = ad7291_events,
+		.num_event_specs = ARRAY_SIZE(ad7291_events),
+	}
+};
+
+static const struct iio_info ad7291_info = {
+	.read_raw = &ad7291_read_raw,
+	.read_event_config = &ad7291_read_event_config,
+	.write_event_config = &ad7291_write_event_config,
+	.read_event_value = &ad7291_read_event_value,
+	.write_event_value = &ad7291_write_event_value,
+	.driver_module = THIS_MODULE,
+};
+
+static int ad7291_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct ad7291_platform_data *pdata = client->dev.platform_data;
+	struct ad7291_chip_info *chip;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
+	chip = iio_priv(indio_dev);
+
+	if (pdata && pdata->use_external_ref) {
+		chip->reg = devm_regulator_get(&client->dev, "vref");
+		if (IS_ERR(chip->reg))
+			return PTR_ERR(chip->reg);
+
+		ret = regulator_enable(chip->reg);
+		if (ret)
+			return ret;
+	}
+
+	mutex_init(&chip->state_lock);
+	/* this is only used for device removal purposes */
+	i2c_set_clientdata(client, indio_dev);
+
+	chip->client = client;
+
+	chip->command = AD7291_NOISE_DELAY |
+			AD7291_T_SENSE_MASK | /* Tsense always enabled */
+			AD7291_ALERT_POLARITY; /* set irq polarity low level */
+
+	if (pdata && pdata->use_external_ref)
+		chip->command |= AD7291_EXT_REF;
+
+	indio_dev->name = id->name;
+	indio_dev->channels = ad7291_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ad7291_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET);
+	if (ret) {
+		ret = -EIO;
+		goto error_disable_reg;
+	}
+
+	ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
+	if (ret) {
+		ret = -EIO;
+		goto error_disable_reg;
+	}
+
+	if (client->irq > 0) {
+		ret = request_threaded_irq(client->irq,
+					   NULL,
+					   &ad7291_event_handler,
+					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					   id->name,
+					   indio_dev);
+		if (ret)
+			goto error_disable_reg;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unreg_irq;
+
+	return 0;
+
+error_unreg_irq:
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
+error_disable_reg:
+	if (chip->reg)
+		regulator_disable(chip->reg);
+
+	return ret;
+}
+
+static int ad7291_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
+
+	if (chip->reg)
+		regulator_disable(chip->reg);
+
+	return 0;
+}
+
+static const struct i2c_device_id ad7291_id[] = {
+	{ "ad7291", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad7291_id);
+
+static struct i2c_driver ad7291_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+	},
+	.probe = ad7291_probe,
+	.remove = ad7291_remove,
+	.id_table = ad7291_id,
+};
+module_i2c_driver(ad7291_driver);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad7298.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7298.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad7298.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7298.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -25,23 +26,19 @@
 
 #include <linux/platform_data/ad7298.h>
 
-#define AD7298_WRITE	(1 << 15) /* write to the control register */
-#define AD7298_REPEAT	(1 << 14) /* repeated conversion enable */
-#define AD7298_CH(x)	(1 << (13 - (x))) /* channel select */
-#define AD7298_TSENSE	(1 << 5) /* temperature conversion enable */
-#define AD7298_EXTREF	(1 << 2) /* external reference enable */
-#define AD7298_TAVG	(1 << 1) /* temperature sensor averaging enable */
-#define AD7298_PDD	(1 << 0) /* partial power down enable */
+#define AD7298_WRITE	BIT(15) /* write to the control register */
+#define AD7298_REPEAT	BIT(14) /* repeated conversion enable */
+#define AD7298_CH(x)	BIT(13 - (x)) /* channel select */
+#define AD7298_TSENSE	BIT(5) /* temperature conversion enable */
+#define AD7298_EXTREF	BIT(2) /* external reference enable */
+#define AD7298_TAVG	BIT(1) /* temperature sensor averaging enable */
+#define AD7298_PDD	BIT(0) /* partial power down enable */
 
 #define AD7298_MAX_CHAN		8
-#define AD7298_BITS		12
-#define AD7298_STORAGE_BITS	16
 #define AD7298_INTREF_mV	2500
 
 #define AD7298_CH_TEMP		9
 
-#define RES_MASK(bits)	((1 << (bits)) - 1)
-
 struct ad7298_state {
 	struct spi_device		*spi;
 	struct regulator		*reg;
@@ -257,7 +254,7 @@ static int ad7298_read_raw(struct iio_de
 			return ret;
 
 		if (chan->address != AD7298_CH_TEMP)
-			*val = ret & RES_MASK(AD7298_BITS);
+			*val = ret & GENMASK(chan->scan_type.realbits - 1, 0);
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad7476.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7476.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad7476.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7476.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -21,8 +22,6 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
-#define RES_MASK(bits)	((1 << (bits)) - 1)
-
 struct ad7476_state;
 
 struct ad7476_chip_info {
@@ -117,7 +116,7 @@ static int ad7476_read_raw(struct iio_de
 		if (ret < 0)
 			return ret;
 		*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
-			RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+			GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		if (!st->chip_info->int_vref_uv) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad7887.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7887.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad7887.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad7887.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -25,14 +26,14 @@
 
 #include <linux/platform_data/ad7887.h>
 
-#define AD7887_REF_DIS		(1 << 5) /* on-chip reference disable */
-#define AD7887_DUAL		(1 << 4) /* dual-channel mode */
-#define AD7887_CH_AIN1		(1 << 3) /* convert on channel 1, DUAL=1 */
-#define AD7887_CH_AIN0		(0 << 3) /* convert on channel 0, DUAL=0,1 */
-#define AD7887_PM_MODE1		(0)	 /* CS based shutdown */
-#define AD7887_PM_MODE2		(1)	 /* full on */
-#define AD7887_PM_MODE3		(2)	 /* auto shutdown after conversion */
-#define AD7887_PM_MODE4		(3)	 /* standby mode */
+#define AD7887_REF_DIS		BIT(5)	/* on-chip reference disable */
+#define AD7887_DUAL		BIT(4)	/* dual-channel mode */
+#define AD7887_CH_AIN1		BIT(3)	/* convert on channel 1, DUAL=1 */
+#define AD7887_CH_AIN0		0	/* convert on channel 0, DUAL=0,1 */
+#define AD7887_PM_MODE1		0	/* CS based shutdown */
+#define AD7887_PM_MODE2		1	/* full on */
+#define AD7887_PM_MODE3		2	/* auto shutdown after conversion */
+#define AD7887_PM_MODE4		3	/* standby mode */
 
 enum ad7887_channels {
 	AD7887_CH0,
@@ -40,8 +41,6 @@ enum ad7887_channels {
 	AD7887_CH1,
 };
 
-#define RES_MASK(bits)	((1 << (bits)) - 1)
-
 /**
  * struct ad7887_chip_info - chip specifc information
  * @int_vref_mv:	the internal reference voltage
@@ -167,7 +166,7 @@ static int ad7887_read_raw(struct iio_de
 		if (ret < 0)
 			return ret;
 		*val = ret >> chan->scan_type.shift;
-		*val &= RES_MASK(chan->scan_type.realbits);
+		*val &= GENMASK(chan->scan_type.realbits - 1, 0);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		if (st->reg) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad799x.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad799x.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad799x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad799x.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -41,7 +42,7 @@
 #include <linux/iio/triggered_buffer.h>
 
 #define AD799X_CHANNEL_SHIFT			4
-#define AD799X_STORAGEBITS			16
+
 /*
  * AD7991, AD7995 and AD7999 defines
  */
@@ -55,10 +56,10 @@
  * AD7992, AD7993, AD7994, AD7997 and AD7998 defines
  */
 
-#define AD7998_FLTR				0x08
-#define AD7998_ALERT_EN				0x04
-#define AD7998_BUSY_ALERT			0x02
-#define AD7998_BUSY_ALERT_POL			0x01
+#define AD7998_FLTR				BIT(3)
+#define AD7998_ALERT_EN				BIT(2)
+#define AD7998_BUSY_ALERT			BIT(1)
+#define AD7998_BUSY_ALERT_POL			BIT(0)
 
 #define AD7998_CONV_RES_REG			0x0
 #define AD7998_ALERT_STAT_REG			0x1
@@ -69,7 +70,7 @@
 #define AD7998_DATAHIGH_REG(x)			((x) * 3 + 0x5)
 #define AD7998_HYST_REG(x)			((x) * 3 + 0x6)
 
-#define AD7998_CYC_MASK				0x7
+#define AD7998_CYC_MASK				GENMASK(2, 0)
 #define AD7998_CYC_DIS				0x0
 #define AD7998_CYC_TCONF_32			0x1
 #define AD7998_CYC_TCONF_64			0x2
@@ -85,10 +86,8 @@
  * AD7997 and AD7997 defines
  */
 
-#define AD7997_8_READ_SINGLE			0x80
-#define AD7997_8_READ_SEQUENCE			0x70
-/* TODO: move this into a common header */
-#define RES_MASK(bits)	((1 << (bits)) - 1)
+#define AD7997_8_READ_SINGLE			BIT(7)
+#define AD7997_8_READ_SEQUENCE			(BIT(6) | BIT(5) | BIT(4))
 
 enum {
 	ad7991,
@@ -102,23 +101,32 @@ enum {
 };
 
 /**
- * struct ad799x_chip_info - chip specific information
+ * struct ad799x_chip_config - chip specific information
  * @channel:		channel specification
- * @num_channels:	number of channels
- * @monitor_mode:	whether the chip supports monitor interrupts
  * @default_config:	device default configuration
- * @event_attrs:	pointer to the monitor event attribute group
+ * @info:		pointer to iio_info struct
  */
-struct ad799x_chip_info {
-	struct iio_chan_spec		channel[9];
-	int				num_channels;
+struct ad799x_chip_config {
+	const struct iio_chan_spec	channel[9];
 	u16				default_config;
 	const struct iio_info		*info;
 };
 
+/**
+ * struct ad799x_chip_info - chip specific information
+ * @num_channels:	number of channels
+ * @noirq_config:	device configuration w/o IRQ
+ * @irq_config:		device configuration w/IRQ
+ */
+struct ad799x_chip_info {
+	int				num_channels;
+	const struct ad799x_chip_config	noirq_config;
+	const struct ad799x_chip_config	irq_config;
+};
+
 struct ad799x_state {
 	struct i2c_client		*client;
-	const struct ad799x_chip_info	*chip_info;
+	const struct ad799x_chip_config	*chip_config;
 	struct regulator		*reg;
 	struct regulator		*vref;
 	unsigned			id;
@@ -128,6 +136,30 @@ struct ad799x_state {
 	unsigned int			transfer_size;
 };
 
+static int ad799x_write_config(struct ad799x_state *st, u16 val)
+{
+	switch (st->id) {
+	case ad7997:
+	case ad7998:
+		return i2c_smbus_write_word_swapped(st->client, AD7998_CONF_REG,
+			val);
+	default:
+		return i2c_smbus_write_byte_data(st->client, AD7998_CONF_REG,
+			val);
+	}
+}
+
+static int ad799x_read_config(struct ad799x_state *st)
+{
+	switch (st->id) {
+	case ad7997:
+	case ad7998:
+		return i2c_smbus_read_word_swapped(st->client, AD7998_CONF_REG);
+	default:
+		return i2c_smbus_read_byte_data(st->client, AD7998_CONF_REG);
+	}
+}
+
 /**
  * ad799x_trigger_handler() bh of trigger launched polling to ring buffer
  *
@@ -176,66 +208,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-/*
- * ad799x register access by I2C
- */
-static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
-{
-	struct i2c_client *client = st->client;
-	int ret = 0;
-
-	ret = i2c_smbus_read_word_swapped(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = (u16)ret;
-
-	return 0;
-}
-
-static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data)
-{
-	struct i2c_client *client = st->client;
-	int ret = 0;
-
-	ret = i2c_smbus_read_byte_data(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = (u8)ret;
-
-	return 0;
-}
-
-static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
-{
-	struct i2c_client *client = st->client;
-	int ret = 0;
-
-	ret = i2c_smbus_write_word_swapped(client, reg, data);
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
-}
-
-static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
-{
-	struct i2c_client *client = st->client;
-	int ret = 0;
-
-	ret = i2c_smbus_write_byte_data(client, reg, data);
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
-}
-
-static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
+static int ad799x_update_scan_mode(struct iio_dev *indio_dev,
 	const unsigned long *scan_mask)
 {
 	struct ad799x_state *st = iio_priv(indio_dev);
@@ -248,33 +221,33 @@ static int ad7997_8_update_scan_mode(str
 	st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2;
 
 	switch (st->id) {
+	case ad7992:
+	case ad7993:
+	case ad7994:
 	case ad7997:
 	case ad7998:
-		return ad799x_i2c_write16(st, AD7998_CONF_REG,
-			st->config | (*scan_mask << AD799X_CHANNEL_SHIFT));
+		st->config &= ~(GENMASK(7, 0) << AD799X_CHANNEL_SHIFT);
+		st->config |= (*scan_mask << AD799X_CHANNEL_SHIFT);
+		return ad799x_write_config(st, st->config);
 	default:
-		break;
+		return 0;
 	}
-
-	return 0;
 }
 
 static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
 {
-	u16 rxbuf;
 	u8 cmd;
-	int ret;
 
 	switch (st->id) {
 	case ad7991:
 	case ad7995:
 	case ad7999:
-		cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT);
+		cmd = st->config | (BIT(ch) << AD799X_CHANNEL_SHIFT);
 		break;
 	case ad7992:
 	case ad7993:
 	case ad7994:
-		cmd = (1 << ch) << AD799X_CHANNEL_SHIFT;
+		cmd = BIT(ch) << AD799X_CHANNEL_SHIFT;
 		break;
 	case ad7997:
 	case ad7998:
@@ -284,11 +257,7 @@ static int ad799x_scan_direct(struct ad7
 		return -EINVAL;
 	}
 
-	ret = ad799x_i2c_read16(st, cmd, &rxbuf);
-	if (ret < 0)
-		return ret;
-
-	return rxbuf;
+	return i2c_smbus_read_word_swapped(st->client, cmd);
 }
 
 static int ad799x_read_raw(struct iio_dev *indio_dev,
@@ -312,7 +281,7 @@ static int ad799x_read_raw(struct iio_de
 		if (ret < 0)
 			return ret;
 		*val = (ret >> chan->scan_type.shift) &
-			RES_MASK(chan->scan_type.realbits);
+			GENMASK(chan->scan_type.realbits - 1, 0);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		ret = regulator_get_voltage(st->vref);
@@ -333,6 +302,7 @@ static const unsigned int ad7998_frequen
 	[AD7998_CYC_TCONF_1024]	= 488,
 	[AD7998_CYC_TCONF_2048]	= 244,
 };
+
 static ssize_t ad799x_read_frequency(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -340,15 +310,11 @@ static ssize_t ad799x_read_frequency(str
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad799x_state *st = iio_priv(indio_dev);
 
-	int ret;
-	u8 val;
-	ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val);
-	if (ret)
+	int ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG);
+	if (ret < 0)
 		return ret;
 
-	val &= AD7998_CYC_MASK;
-
-	return sprintf(buf, "%u\n", ad7998_frequencies[val]);
+	return sprintf(buf, "%u\n", ad7998_frequencies[ret & AD7998_CYC_MASK]);
 }
 
 static ssize_t ad799x_write_frequency(struct device *dev,
@@ -361,18 +327,17 @@ static ssize_t ad799x_write_frequency(st
 
 	long val;
 	int ret, i;
-	u8 t;
 
 	ret = kstrtol(buf, 10, &val);
 	if (ret)
 		return ret;
 
 	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t);
-	if (ret)
+	ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG);
+	if (ret < 0)
 		goto error_ret_mutex;
 	/* Wipe the bits clean */
-	t &= ~AD7998_CYC_MASK;
+	ret &= ~AD7998_CYC_MASK;
 
 	for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++)
 		if (val == ad7998_frequencies[i])
@@ -381,13 +346,17 @@ static ssize_t ad799x_write_frequency(st
 		ret = -EINVAL;
 		goto error_ret_mutex;
 	}
-	t |= i;
-	ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t);
+
+	ret = i2c_smbus_write_byte_data(st->client, AD7998_CYCLE_TMR_REG,
+		ret | i);
+	if (ret < 0)
+		goto error_ret_mutex;
+	ret = len;
 
 error_ret_mutex:
 	mutex_unlock(&indio_dev->mlock);
 
-	return ret ? ret : len;
+	return ret;
 }
 
 static int ad799x_read_event_config(struct iio_dev *indio_dev,
@@ -395,7 +364,48 @@ static int ad799x_read_event_config(stru
 				    enum iio_event_type type,
 				    enum iio_event_direction dir)
 {
-	return 1;
+	struct ad799x_state *st = iio_priv(indio_dev);
+
+	if (!(st->config & AD7998_ALERT_EN))
+		return 0;
+
+	if ((st->config >> AD799X_CHANNEL_SHIFT) & BIT(chan->scan_index))
+		return 1;
+
+	return 0;
+}
+
+static int ad799x_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 ad799x_state *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+	if (iio_buffer_enabled(indio_dev)) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	if (state)
+		st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT;
+	else
+		st->config &= ~(BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT);
+
+	if (st->config >> AD799X_CHANNEL_SHIFT)
+		st->config |= AD7998_ALERT_EN;
+	else
+		st->config &= ~AD7998_ALERT_EN;
+
+	ret = ad799x_write_config(st, st->config);
+
+done:
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
 }
 
 static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan,
@@ -427,11 +437,12 @@ static int ad799x_write_event_value(stru
 	int ret;
 	struct ad799x_state *st = iio_priv(indio_dev);
 
-	if (val < 0 || val > RES_MASK(chan->scan_type.realbits))
+	if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0))
 		return -EINVAL;
 
 	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info),
+	ret = i2c_smbus_write_word_swapped(st->client,
+		ad799x_threshold_reg(chan, dir, info),
 		val << chan->scan_type.shift);
 	mutex_unlock(&indio_dev->mlock);
 
@@ -447,16 +458,15 @@ static int ad799x_read_event_value(struc
 {
 	int ret;
 	struct ad799x_state *st = iio_priv(indio_dev);
-	u16 valin;
 
 	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info),
-		&valin);
+	ret = i2c_smbus_read_word_swapped(st->client,
+		ad799x_threshold_reg(chan, dir, info));
 	mutex_unlock(&indio_dev->mlock);
 	if (ret < 0)
 		return ret;
-	*val = (valin >> chan->scan_type.shift) &
-		RES_MASK(chan->scan_type.realbits);
+	*val = (ret >> chan->scan_type.shift) &
+		GENMASK(chan->scan_type.realbits - 1 , 0);
 
 	return IIO_VAL_INT;
 }
@@ -465,20 +475,18 @@ static irqreturn_t ad799x_event_handler(
 {
 	struct iio_dev *indio_dev = private;
 	struct ad799x_state *st = iio_priv(private);
-	u8 status;
 	int i, ret;
 
-	ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status);
-	if (ret)
+	ret = i2c_smbus_read_byte_data(st->client, AD7998_ALERT_STAT_REG);
+	if (ret <= 0)
 		goto done;
 
-	if (!status)
+	if (i2c_smbus_write_byte_data(st->client, AD7998_ALERT_STAT_REG,
+		AD7998_ALERT_STAT_CLEAR) < 0)
 		goto done;
 
-	ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR);
-
 	for (i = 0; i < 8; i++) {
-		if (status & (1 << i))
+		if (ret & BIT(i))
 			iio_push_event(indio_dev,
 				       i & 0x1 ?
 				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
@@ -517,14 +525,21 @@ static const struct iio_info ad7991_info
 	.driver_module = THIS_MODULE,
 };
 
-static const struct iio_info ad7993_4_7_8_info = {
+static const struct iio_info ad7993_4_7_8_noirq_info = {
+	.read_raw = &ad799x_read_raw,
+	.driver_module = THIS_MODULE,
+	.update_scan_mode = ad799x_update_scan_mode,
+};
+
+static const struct iio_info ad7993_4_7_8_irq_info = {
 	.read_raw = &ad799x_read_raw,
 	.event_attrs = &ad799x_event_attrs_group,
 	.read_event_config = &ad799x_read_event_config,
+	.write_event_config = &ad799x_write_event_config,
 	.read_event_value = &ad799x_read_event_value,
 	.write_event_value = &ad799x_write_event_value,
 	.driver_module = THIS_MODULE,
-	.update_scan_mode = ad7997_8_update_scan_mode,
+	.update_scan_mode = ad799x_update_scan_mode,
 };
 
 static const struct iio_event_spec ad799x_events[] = {
@@ -572,103 +587,175 @@ static const struct iio_event_spec ad799
 
 static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
 	[ad7991] = {
-		.channel = {
-			AD799X_CHANNEL(0, 12),
-			AD799X_CHANNEL(1, 12),
-			AD799X_CHANNEL(2, 12),
-			AD799X_CHANNEL(3, 12),
-			IIO_CHAN_SOFT_TIMESTAMP(4),
-		},
 		.num_channels = 5,
-		.info = &ad7991_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 12),
+				AD799X_CHANNEL(1, 12),
+				AD799X_CHANNEL(2, 12),
+				AD799X_CHANNEL(3, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.info = &ad7991_info,
+		},
 	},
 	[ad7995] = {
-		.channel = {
-			AD799X_CHANNEL(0, 10),
-			AD799X_CHANNEL(1, 10),
-			AD799X_CHANNEL(2, 10),
-			AD799X_CHANNEL(3, 10),
-			IIO_CHAN_SOFT_TIMESTAMP(4),
-		},
 		.num_channels = 5,
-		.info = &ad7991_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 10),
+				AD799X_CHANNEL(1, 10),
+				AD799X_CHANNEL(2, 10),
+				AD799X_CHANNEL(3, 10),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.info = &ad7991_info,
+		},
 	},
 	[ad7999] = {
-		.channel = {
-			AD799X_CHANNEL(0, 8),
-			AD799X_CHANNEL(1, 8),
-			AD799X_CHANNEL(2, 8),
-			AD799X_CHANNEL(3, 8),
-			IIO_CHAN_SOFT_TIMESTAMP(4),
-		},
 		.num_channels = 5,
-		.info = &ad7991_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 8),
+				AD799X_CHANNEL(1, 8),
+				AD799X_CHANNEL(2, 8),
+				AD799X_CHANNEL(3, 8),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.info = &ad7991_info,
+		},
 	},
 	[ad7992] = {
-		.channel = {
-			AD799X_CHANNEL_WITH_EVENTS(0, 12),
-			AD799X_CHANNEL_WITH_EVENTS(1, 12),
-			IIO_CHAN_SOFT_TIMESTAMP(3),
-		},
 		.num_channels = 3,
-		.default_config = AD7998_ALERT_EN,
-		.info = &ad7993_4_7_8_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 12),
+				AD799X_CHANNEL(1, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(3),
+			},
+			.info = &ad7993_4_7_8_noirq_info,
+		},
+		.irq_config = {
+			.channel = {
+				AD799X_CHANNEL_WITH_EVENTS(0, 12),
+				AD799X_CHANNEL_WITH_EVENTS(1, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(3),
+			},
+			.default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+			.info = &ad7993_4_7_8_irq_info,
+		},
 	},
 	[ad7993] = {
-		.channel = {
-			AD799X_CHANNEL_WITH_EVENTS(0, 10),
-			AD799X_CHANNEL_WITH_EVENTS(1, 10),
-			AD799X_CHANNEL_WITH_EVENTS(2, 10),
-			AD799X_CHANNEL_WITH_EVENTS(3, 10),
-			IIO_CHAN_SOFT_TIMESTAMP(4),
-		},
 		.num_channels = 5,
-		.default_config = AD7998_ALERT_EN,
-		.info = &ad7993_4_7_8_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 10),
+				AD799X_CHANNEL(1, 10),
+				AD799X_CHANNEL(2, 10),
+				AD799X_CHANNEL(3, 10),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.info = &ad7993_4_7_8_noirq_info,
+		},
+		.irq_config = {
+			.channel = {
+				AD799X_CHANNEL_WITH_EVENTS(0, 10),
+				AD799X_CHANNEL_WITH_EVENTS(1, 10),
+				AD799X_CHANNEL_WITH_EVENTS(2, 10),
+				AD799X_CHANNEL_WITH_EVENTS(3, 10),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+			.info = &ad7993_4_7_8_irq_info,
+		},
 	},
 	[ad7994] = {
-		.channel = {
-			AD799X_CHANNEL_WITH_EVENTS(0, 12),
-			AD799X_CHANNEL_WITH_EVENTS(1, 12),
-			AD799X_CHANNEL_WITH_EVENTS(2, 12),
-			AD799X_CHANNEL_WITH_EVENTS(3, 12),
-			IIO_CHAN_SOFT_TIMESTAMP(4),
-		},
 		.num_channels = 5,
-		.default_config = AD7998_ALERT_EN,
-		.info = &ad7993_4_7_8_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 12),
+				AD799X_CHANNEL(1, 12),
+				AD799X_CHANNEL(2, 12),
+				AD799X_CHANNEL(3, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.info = &ad7993_4_7_8_noirq_info,
+		},
+		.irq_config = {
+			.channel = {
+				AD799X_CHANNEL_WITH_EVENTS(0, 12),
+				AD799X_CHANNEL_WITH_EVENTS(1, 12),
+				AD799X_CHANNEL_WITH_EVENTS(2, 12),
+				AD799X_CHANNEL_WITH_EVENTS(3, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(4),
+			},
+			.default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+			.info = &ad7993_4_7_8_irq_info,
+		},
 	},
 	[ad7997] = {
-		.channel = {
-			AD799X_CHANNEL_WITH_EVENTS(0, 10),
-			AD799X_CHANNEL_WITH_EVENTS(1, 10),
-			AD799X_CHANNEL_WITH_EVENTS(2, 10),
-			AD799X_CHANNEL_WITH_EVENTS(3, 10),
-			AD799X_CHANNEL(4, 10),
-			AD799X_CHANNEL(5, 10),
-			AD799X_CHANNEL(6, 10),
-			AD799X_CHANNEL(7, 10),
-			IIO_CHAN_SOFT_TIMESTAMP(8),
-		},
 		.num_channels = 9,
-		.default_config = AD7998_ALERT_EN,
-		.info = &ad7993_4_7_8_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 10),
+				AD799X_CHANNEL(1, 10),
+				AD799X_CHANNEL(2, 10),
+				AD799X_CHANNEL(3, 10),
+				AD799X_CHANNEL(4, 10),
+				AD799X_CHANNEL(5, 10),
+				AD799X_CHANNEL(6, 10),
+				AD799X_CHANNEL(7, 10),
+				IIO_CHAN_SOFT_TIMESTAMP(8),
+			},
+			.info = &ad7993_4_7_8_noirq_info,
+		},
+		.irq_config = {
+			.channel = {
+				AD799X_CHANNEL_WITH_EVENTS(0, 10),
+				AD799X_CHANNEL_WITH_EVENTS(1, 10),
+				AD799X_CHANNEL_WITH_EVENTS(2, 10),
+				AD799X_CHANNEL_WITH_EVENTS(3, 10),
+				AD799X_CHANNEL(4, 10),
+				AD799X_CHANNEL(5, 10),
+				AD799X_CHANNEL(6, 10),
+				AD799X_CHANNEL(7, 10),
+				IIO_CHAN_SOFT_TIMESTAMP(8),
+			},
+			.default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+			.info = &ad7993_4_7_8_irq_info,
+		},
 	},
 	[ad7998] = {
-		.channel = {
-			AD799X_CHANNEL_WITH_EVENTS(0, 12),
-			AD799X_CHANNEL_WITH_EVENTS(1, 12),
-			AD799X_CHANNEL_WITH_EVENTS(2, 12),
-			AD799X_CHANNEL_WITH_EVENTS(3, 12),
-			AD799X_CHANNEL(4, 12),
-			AD799X_CHANNEL(5, 12),
-			AD799X_CHANNEL(6, 12),
-			AD799X_CHANNEL(7, 12),
-			IIO_CHAN_SOFT_TIMESTAMP(8),
-		},
 		.num_channels = 9,
-		.default_config = AD7998_ALERT_EN,
-		.info = &ad7993_4_7_8_info,
+		.noirq_config = {
+			.channel = {
+				AD799X_CHANNEL(0, 12),
+				AD799X_CHANNEL(1, 12),
+				AD799X_CHANNEL(2, 12),
+				AD799X_CHANNEL(3, 12),
+				AD799X_CHANNEL(4, 12),
+				AD799X_CHANNEL(5, 12),
+				AD799X_CHANNEL(6, 12),
+				AD799X_CHANNEL(7, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(8),
+			},
+			.info = &ad7993_4_7_8_noirq_info,
+		},
+		.irq_config = {
+			.channel = {
+				AD799X_CHANNEL_WITH_EVENTS(0, 12),
+				AD799X_CHANNEL_WITH_EVENTS(1, 12),
+				AD799X_CHANNEL_WITH_EVENTS(2, 12),
+				AD799X_CHANNEL_WITH_EVENTS(3, 12),
+				AD799X_CHANNEL(4, 12),
+				AD799X_CHANNEL(5, 12),
+				AD799X_CHANNEL(6, 12),
+				AD799X_CHANNEL(7, 12),
+				IIO_CHAN_SOFT_TIMESTAMP(8),
+			},
+			.default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+			.info = &ad7993_4_7_8_irq_info,
+		},
 	},
 };
 
@@ -678,6 +765,8 @@ static int ad799x_probe(struct i2c_clien
 	int ret;
 	struct ad799x_state *st;
 	struct iio_dev *indio_dev;
+	const struct ad799x_chip_info *chip_info =
+		&ad799x_chip_info_tbl[id->driver_data];
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
 	if (indio_dev == NULL)
@@ -688,8 +777,10 @@ static int ad799x_probe(struct i2c_clien
 	i2c_set_clientdata(client, indio_dev);
 
 	st->id = id->driver_data;
-	st->chip_info = &ad799x_chip_info_tbl[st->id];
-	st->config = st->chip_info->default_config;
+	if (client->irq > 0 && chip_info->irq_config.info)
+		st->chip_config = &chip_info->irq_config;
+	else
+		st->chip_config = &chip_info->noirq_config;
 
 	/* TODO: Add pdata options for filtering and bit delay */
 
@@ -712,11 +803,19 @@ static int ad799x_probe(struct i2c_clien
 
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->name = id->name;
-	indio_dev->info = st->chip_info->info;
+	indio_dev->info = st->chip_config->info;
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = st->chip_info->channel;
-	indio_dev->num_channels = st->chip_info->num_channels;
+	indio_dev->channels = st->chip_config->channel;
+	indio_dev->num_channels = chip_info->num_channels;
+
+	ret = ad799x_write_config(st, st->chip_config->default_config);
+	if (ret < 0)
+		goto error_disable_reg;
+	ret = ad799x_read_config(st);
+	if (ret < 0)
+		goto error_disable_reg;
+	st->config = ret;
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
 		&ad799x_trigger_handler, NULL);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/ad_sigma_delta.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad_sigma_delta.c
--- linux-libre-3.16-gnu/drivers/iio/adc/ad_sigma_delta.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/ad_sigma_delta.c	2014-09-28 17:29:07.000000000 -0400
@@ -410,7 +410,7 @@ static irqreturn_t ad_sd_data_rdy_trig_p
 	complete(&sigma_delta->completion);
 	disable_irq_nosync(irq);
 	sigma_delta->irq_dis = true;
-	iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
+	iio_trigger_poll(sigma_delta->trig);
 
 	return IRQ_HANDLED;
 }
@@ -472,7 +472,7 @@ static int ad_sd_probe_trigger(struct ii
 		goto error_free_irq;
 
 	/* select default trigger */
-	indio_dev->trig = sigma_delta->trig;
+	indio_dev->trig = iio_trigger_get(sigma_delta->trig);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/at91_adc.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/at91_adc.c
--- linux-libre-3.16-gnu/drivers/iio/adc/at91_adc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/at91_adc.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,6 +196,7 @@ struct at91_adc_state {
 	bool			done;
 	int			irq;
 	u16			last_value;
+	int			chnb;
 	struct mutex		lock;
 	u8			num_channels;
 	void __iomem		*reg_base;
@@ -272,9 +273,9 @@ void handle_adc_eoc_trigger(int irq, str
 
 	if (iio_buffer_enabled(idev)) {
 		disable_irq_nosync(irq);
-		iio_trigger_poll(idev->trig, iio_get_time_ns());
+		iio_trigger_poll(idev->trig);
 	} else {
-		st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
+		st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb));
 		st->done = true;
 		wake_up_interruptible(&st->wq_data_avail);
 	}
@@ -351,7 +352,7 @@ static irqreturn_t at91_adc_rl_interrupt
 	unsigned int reg;
 
 	status &= at91_adc_readl(st, AT91_ADC_IMR);
-	if (status & st->registers->drdy_mask)
+	if (status & GENMASK(st->num_channels - 1, 0))
 		handle_adc_eoc_trigger(irq, idev);
 
 	if (status & AT91RL_ADC_IER_PEN) {
@@ -418,7 +419,7 @@ static irqreturn_t at91_adc_9x5_interrup
 		AT91_ADC_IER_YRDY |
 		AT91_ADC_IER_PRDY;
 
-	if (status & st->registers->drdy_mask)
+	if (status & GENMASK(st->num_channels - 1, 0))
 		handle_adc_eoc_trigger(irq, idev);
 
 	if (status & AT91_ADC_IER_PEN) {
@@ -689,9 +690,10 @@ static int at91_adc_read_raw(struct iio_
 	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&st->lock);
 
+		st->chnb = chan->channel;
 		at91_adc_writel(st, AT91_ADC_CHER,
 				AT91_ADC_CH(chan->channel));
-		at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask);
+		at91_adc_writel(st, AT91_ADC_IER, BIT(chan->channel));
 		at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START);
 
 		ret = wait_event_interruptible_timeout(st->wq_data_avail,
@@ -708,7 +710,7 @@ static int at91_adc_read_raw(struct iio_
 
 		at91_adc_writel(st, AT91_ADC_CHDR,
 				AT91_ADC_CH(chan->channel));
-		at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask);
+		at91_adc_writel(st, AT91_ADC_IDR, BIT(chan->channel));
 
 		st->last_value = 0;
 		st->done = false;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/exynos_adc.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/exynos_adc.c
--- linux-libre-3.16-gnu/drivers/iio/adc/exynos_adc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/exynos_adc.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -39,11 +40,6 @@
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
-enum adc_version {
-	ADC_V1,
-	ADC_V2
-};
-
 /* EXYNOS4412/5250 ADC_V1 registers definitions */
 #define ADC_V1_CON(x)		((x) + 0x00)
 #define ADC_V1_DLY(x)		((x) + 0x08)
@@ -75,8 +71,9 @@ enum adc_version {
 #define ADC_V2_CON2_ACH_SEL(x)	(((x) & 0xF) << 0)
 #define ADC_V2_CON2_ACH_MASK	0xF
 
-#define MAX_ADC_V2_CHANNELS	10
-#define MAX_ADC_V1_CHANNELS	8
+#define MAX_ADC_V2_CHANNELS		10
+#define MAX_ADC_V1_CHANNELS		8
+#define MAX_EXYNOS3250_ADC_CHANNELS	2
 
 /* Bit definitions common for ADC_V1 and ADC_V2 */
 #define ADC_CON_EN_START	(1u << 0)
@@ -85,9 +82,12 @@ enum adc_version {
 #define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
 struct exynos_adc {
+	struct exynos_adc_data	*data;
+	struct device		*dev;
 	void __iomem		*regs;
 	void __iomem		*enable_reg;
 	struct clk		*clk;
+	struct clk		*sclk;
 	unsigned int		irq;
 	struct regulator	*vdd;
 
@@ -97,43 +97,213 @@ struct exynos_adc {
 	unsigned int            version;
 };
 
-static const struct of_device_id exynos_adc_match[] = {
-	{ .compatible = "samsung,exynos-adc-v1", .data = (void *)ADC_V1 },
-	{ .compatible = "samsung,exynos-adc-v2", .data = (void *)ADC_V2 },
-	{},
+struct exynos_adc_data {
+	int num_channels;
+	bool needs_sclk;
+
+	void (*init_hw)(struct exynos_adc *info);
+	void (*exit_hw)(struct exynos_adc *info);
+	void (*clear_irq)(struct exynos_adc *info);
+	void (*start_conv)(struct exynos_adc *info, unsigned long addr);
 };
-MODULE_DEVICE_TABLE(of, exynos_adc_match);
 
-static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
+static void exynos_adc_unprepare_clk(struct exynos_adc *info)
 {
-	const struct of_device_id *match;
+	if (info->data->needs_sclk)
+		clk_unprepare(info->sclk);
+	clk_unprepare(info->clk);
+}
 
-	match = of_match_node(exynos_adc_match, pdev->dev.of_node);
-	return (unsigned int)match->data;
+static int exynos_adc_prepare_clk(struct exynos_adc *info)
+{
+	int ret;
+
+	ret = clk_prepare(info->clk);
+	if (ret) {
+		dev_err(info->dev, "failed preparing adc clock: %d\n", ret);
+		return ret;
+	}
+
+	if (info->data->needs_sclk) {
+		ret = clk_prepare(info->sclk);
+		if (ret) {
+			clk_unprepare(info->clk);
+			dev_err(info->dev,
+				"failed preparing sclk_adc clock: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
 }
 
-static void exynos_adc_hw_init(struct exynos_adc *info)
+static void exynos_adc_disable_clk(struct exynos_adc *info)
+{
+	if (info->data->needs_sclk)
+		clk_disable(info->sclk);
+	clk_disable(info->clk);
+}
+
+static int exynos_adc_enable_clk(struct exynos_adc *info)
+{
+	int ret;
+
+	ret = clk_enable(info->clk);
+	if (ret) {
+		dev_err(info->dev, "failed enabling adc clock: %d\n", ret);
+		return ret;
+	}
+
+	if (info->data->needs_sclk) {
+		ret = clk_enable(info->sclk);
+		if (ret) {
+			clk_disable(info->clk);
+			dev_err(info->dev,
+				"failed enabling sclk_adc clock: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void exynos_adc_v1_init_hw(struct exynos_adc *info)
+{
+	u32 con1;
+
+	writel(1, info->enable_reg);
+
+	/* set default prescaler values and Enable prescaler */
+	con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+	/* Enable 12-bit ADC resolution */
+	con1 |= ADC_V1_CON_RES;
+	writel(con1, ADC_V1_CON(info->regs));
+}
+
+static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
+{
+	u32 con;
+
+	writel(0, info->enable_reg);
+
+	con = readl(ADC_V1_CON(info->regs));
+	con |= ADC_V1_CON_STANDBY;
+	writel(con, ADC_V1_CON(info->regs));
+}
+
+static void exynos_adc_v1_clear_irq(struct exynos_adc *info)
+{
+	writel(1, ADC_V1_INTCLR(info->regs));
+}
+
+static void exynos_adc_v1_start_conv(struct exynos_adc *info,
+				     unsigned long addr)
+{
+	u32 con1;
+
+	writel(addr, ADC_V1_MUX(info->regs));
+
+	con1 = readl(ADC_V1_CON(info->regs));
+	writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
+}
+
+static const struct exynos_adc_data exynos_adc_v1_data = {
+	.num_channels	= MAX_ADC_V1_CHANNELS,
+
+	.init_hw	= exynos_adc_v1_init_hw,
+	.exit_hw	= exynos_adc_v1_exit_hw,
+	.clear_irq	= exynos_adc_v1_clear_irq,
+	.start_conv	= exynos_adc_v1_start_conv,
+};
+
+static void exynos_adc_v2_init_hw(struct exynos_adc *info)
 {
 	u32 con1, con2;
 
-	if (info->version == ADC_V2) {
-		con1 = ADC_V2_CON1_SOFT_RESET;
-		writel(con1, ADC_V2_CON1(info->regs));
+	writel(1, info->enable_reg);
 
-		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
-			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
-		writel(con2, ADC_V2_CON2(info->regs));
+	con1 = ADC_V2_CON1_SOFT_RESET;
+	writel(con1, ADC_V2_CON1(info->regs));
 
-		/* Enable interrupts */
-		writel(1, ADC_V2_INT_EN(info->regs));
-	} else {
-		/* set default prescaler values and Enable prescaler */
-		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+	con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+		ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+	writel(con2, ADC_V2_CON2(info->regs));
 
-		/* Enable 12-bit ADC resolution */
-		con1 |= ADC_V1_CON_RES;
-		writel(con1, ADC_V1_CON(info->regs));
-	}
+	/* Enable interrupts */
+	writel(1, ADC_V2_INT_EN(info->regs));
+}
+
+static void exynos_adc_v2_exit_hw(struct exynos_adc *info)
+{
+	u32 con;
+
+	writel(0, info->enable_reg);
+
+	con = readl(ADC_V2_CON1(info->regs));
+	con &= ~ADC_CON_EN_START;
+	writel(con, ADC_V2_CON1(info->regs));
+}
+
+static void exynos_adc_v2_clear_irq(struct exynos_adc *info)
+{
+	writel(1, ADC_V2_INT_ST(info->regs));
+}
+
+static void exynos_adc_v2_start_conv(struct exynos_adc *info,
+				     unsigned long addr)
+{
+	u32 con1, con2;
+
+	con2 = readl(ADC_V2_CON2(info->regs));
+	con2 &= ~ADC_V2_CON2_ACH_MASK;
+	con2 |= ADC_V2_CON2_ACH_SEL(addr);
+	writel(con2, ADC_V2_CON2(info->regs));
+
+	con1 = readl(ADC_V2_CON1(info->regs));
+	writel(con1 | ADC_CON_EN_START, ADC_V2_CON1(info->regs));
+}
+
+static const struct exynos_adc_data exynos_adc_v2_data = {
+	.num_channels	= MAX_ADC_V2_CHANNELS,
+
+	.init_hw	= exynos_adc_v2_init_hw,
+	.exit_hw	= exynos_adc_v2_exit_hw,
+	.clear_irq	= exynos_adc_v2_clear_irq,
+	.start_conv	= exynos_adc_v2_start_conv,
+};
+
+static const struct exynos_adc_data exynos3250_adc_data = {
+	.num_channels	= MAX_EXYNOS3250_ADC_CHANNELS,
+	.needs_sclk	= true,
+
+	.init_hw	= exynos_adc_v2_init_hw,
+	.exit_hw	= exynos_adc_v2_exit_hw,
+	.clear_irq	= exynos_adc_v2_clear_irq,
+	.start_conv	= exynos_adc_v2_start_conv,
+};
+
+static const struct of_device_id exynos_adc_match[] = {
+	{
+		.compatible = "samsung,exynos-adc-v1",
+		.data = &exynos_adc_v1_data,
+	}, {
+		.compatible = "samsung,exynos-adc-v2",
+		.data = &exynos_adc_v2_data,
+	}, {
+		.compatible = "samsung,exynos3250-adc",
+		.data = &exynos3250_adc_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_adc_match);
+
+static struct exynos_adc_data *exynos_adc_get_data(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+
+	match = of_match_node(exynos_adc_match, pdev->dev.of_node);
+	return (struct exynos_adc_data *)match->data;
 }
 
 static int exynos_read_raw(struct iio_dev *indio_dev,
@@ -144,7 +314,6 @@ static int exynos_read_raw(struct iio_de
 {
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
-	u32 con1, con2;
 	int ret;
 
 	if (mask != IIO_CHAN_INFO_RAW)
@@ -154,28 +323,15 @@ static int exynos_read_raw(struct iio_de
 	reinit_completion(&info->completion);
 
 	/* Select the channel to be used and Trigger conversion */
-	if (info->version == ADC_V2) {
-		con2 = readl(ADC_V2_CON2(info->regs));
-		con2 &= ~ADC_V2_CON2_ACH_MASK;
-		con2 |= ADC_V2_CON2_ACH_SEL(chan->address);
-		writel(con2, ADC_V2_CON2(info->regs));
-
-		con1 = readl(ADC_V2_CON1(info->regs));
-		writel(con1 | ADC_CON_EN_START,
-				ADC_V2_CON1(info->regs));
-	} else {
-		writel(chan->address, ADC_V1_MUX(info->regs));
-
-		con1 = readl(ADC_V1_CON(info->regs));
-		writel(con1 | ADC_CON_EN_START,
-				ADC_V1_CON(info->regs));
-	}
+	if (info->data->start_conv)
+		info->data->start_conv(info, chan->address);
 
 	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
 	if (timeout == 0) {
 		dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
-		exynos_adc_hw_init(info);
+		if (info->data->init_hw)
+			info->data->init_hw(info);
 		ret = -ETIMEDOUT;
 	} else {
 		*val = info->value;
@@ -193,13 +349,11 @@ static irqreturn_t exynos_adc_isr(int ir
 	struct exynos_adc *info = (struct exynos_adc *)dev_id;
 
 	/* Read value */
-	info->value = readl(ADC_V1_DATX(info->regs)) &
-						ADC_DATX_MASK;
+	info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
+
 	/* clear irq */
-	if (info->version == ADC_V2)
-		writel(1, ADC_V2_INT_ST(info->regs));
-	else
-		writel(1, ADC_V1_INTCLR(info->regs));
+	if (info->data->clear_irq)
+		info->data->clear_irq(info);
 
 	complete(&info->completion);
 
@@ -277,6 +431,12 @@ static int exynos_adc_probe(struct platf
 
 	info = iio_priv(indio_dev);
 
+	info->data = exynos_adc_get_data(pdev);
+	if (!info->data) {
+		dev_err(&pdev->dev, "failed getting exynos_adc_data\n");
+		return -EINVAL;
+	}
+
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	info->regs = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(info->regs))
@@ -294,6 +454,7 @@ static int exynos_adc_probe(struct platf
 	}
 
 	info->irq = irq;
+	info->dev = &pdev->dev;
 
 	init_completion(&info->completion);
 
@@ -304,6 +465,16 @@ static int exynos_adc_probe(struct platf
 		return PTR_ERR(info->clk);
 	}
 
+	if (info->data->needs_sclk) {
+		info->sclk = devm_clk_get(&pdev->dev, "sclk");
+		if (IS_ERR(info->sclk)) {
+			dev_err(&pdev->dev,
+				"failed getting sclk clock, err = %ld\n",
+				PTR_ERR(info->sclk));
+			return PTR_ERR(info->sclk);
+		}
+	}
+
 	info->vdd = devm_regulator_get(&pdev->dev, "vdd");
 	if (IS_ERR(info->vdd)) {
 		dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
@@ -315,13 +486,13 @@ static int exynos_adc_probe(struct platf
 	if (ret)
 		return ret;
 
-	ret = clk_prepare_enable(info->clk);
+	ret = exynos_adc_prepare_clk(info);
 	if (ret)
 		goto err_disable_reg;
 
-	writel(1, info->enable_reg);
-
-	info->version = exynos_adc_get_version(pdev);
+	ret = exynos_adc_enable_clk(info);
+	if (ret)
+		goto err_unprepare_clk;
 
 	platform_set_drvdata(pdev, indio_dev);
 
@@ -331,11 +502,7 @@ static int exynos_adc_probe(struct platf
 	indio_dev->info = &exynos_adc_iio_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->channels = exynos_adc_iio_channels;
-
-	if (info->version == ADC_V1)
-		indio_dev->num_channels = MAX_ADC_V1_CHANNELS;
-	else
-		indio_dev->num_channels = MAX_ADC_V2_CHANNELS;
+	indio_dev->num_channels = info->data->num_channels;
 
 	ret = request_irq(info->irq, exynos_adc_isr,
 					0, dev_name(&pdev->dev), info);
@@ -349,7 +516,8 @@ static int exynos_adc_probe(struct platf
 	if (ret)
 		goto err_irq;
 
-	exynos_adc_hw_init(info);
+	if (info->data->init_hw)
+		info->data->init_hw(info);
 
 	ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
 	if (ret < 0) {
@@ -366,8 +534,11 @@ err_of_populate:
 err_irq:
 	free_irq(info->irq, info);
 err_disable_clk:
-	writel(0, info->enable_reg);
-	clk_disable_unprepare(info->clk);
+	if (info->data->exit_hw)
+		info->data->exit_hw(info);
+	exynos_adc_disable_clk(info);
+err_unprepare_clk:
+	exynos_adc_unprepare_clk(info);
 err_disable_reg:
 	regulator_disable(info->vdd);
 	return ret;
@@ -382,8 +553,10 @@ static int exynos_adc_remove(struct plat
 				exynos_adc_remove_devices);
 	iio_device_unregister(indio_dev);
 	free_irq(info->irq, info);
-	writel(0, info->enable_reg);
-	clk_disable_unprepare(info->clk);
+	if (info->data->exit_hw)
+		info->data->exit_hw(info);
+	exynos_adc_disable_clk(info);
+	exynos_adc_unprepare_clk(info);
 	regulator_disable(info->vdd);
 
 	return 0;
@@ -394,20 +567,10 @@ static int exynos_adc_suspend(struct dev
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct exynos_adc *info = iio_priv(indio_dev);
-	u32 con;
 
-	if (info->version == ADC_V2) {
-		con = readl(ADC_V2_CON1(info->regs));
-		con &= ~ADC_CON_EN_START;
-		writel(con, ADC_V2_CON1(info->regs));
-	} else {
-		con = readl(ADC_V1_CON(info->regs));
-		con |= ADC_V1_CON_STANDBY;
-		writel(con, ADC_V1_CON(info->regs));
-	}
-
-	writel(0, info->enable_reg);
-	clk_disable_unprepare(info->clk);
+	if (info->data->exit_hw)
+		info->data->exit_hw(info);
+	exynos_adc_disable_clk(info);
 	regulator_disable(info->vdd);
 
 	return 0;
@@ -423,12 +586,12 @@ static int exynos_adc_resume(struct devi
 	if (ret)
 		return ret;
 
-	ret = clk_prepare_enable(info->clk);
+	ret = exynos_adc_enable_clk(info);
 	if (ret)
 		return ret;
 
-	writel(1, info->enable_reg);
-	exynos_adc_hw_init(info);
+	if (info->data->init_hw)
+		info->data->init_hw(info);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/adc/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/adc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,16 @@ config AD7266
 	  Say yes here to build support for Analog Devices AD7265 and AD7266
 	  ADCs.
 
+config AD7291
+	tristate "Analog Devices AD7291 ADC driver"
+	depends on I2C
+	help
+	  Say yes here to build support for Analog Devices AD7291
+	  8 Channel ADC with temperature sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7291.
+
 config AD7298
 	tristate "Analog Devices AD7298 ADC driver"
 	depends on SPI
@@ -131,6 +141,15 @@ config LP8788_ADC
 	help
 	  Say yes here to build support for TI LP8788 ADC.
 
+config MAX1027
+	tristate "Maxim max1027 ADC driver"
+	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Maxim SPI ADC models
+	  max1027, max1029 and max1031.
+
 config MAX1363
 	tristate "Maxim max1363 ADC driver"
 	depends on I2C
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/adc/Makefile
--- linux-libre-3.16-gnu/drivers/iio/adc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7923) += ad7923.o
 obj-$(CONFIG_AD7476) += ad7476.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
 obj-$(CONFIG_MCP3422) += mcp3422.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/max1027.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/max1027.c
--- linux-libre-3.16-gnu/drivers/iio/adc/max1027.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/max1027.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,521 @@
+ /*
+  * iio/adc/max1027.c
+  * Copyright (C) 2014 Philippe Reynes
+  *
+  * based on linux/drivers/iio/ad7923.c
+  * Copyright 2011 Analog Devices Inc (from AD7923 Driver)
+  * Copyright 2012 CS Systemes d'Information
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  * max1027.c
+  *
+  * Partial support for max1027 and similar chips.
+  */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.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>
+
+#define MAX1027_CONV_REG  BIT(7)
+#define MAX1027_SETUP_REG BIT(6)
+#define MAX1027_AVG_REG   BIT(5)
+#define MAX1027_RST_REG   BIT(4)
+
+/* conversion register */
+#define MAX1027_TEMP      BIT(0)
+#define MAX1027_SCAN_0_N  (0x00 << 1)
+#define MAX1027_SCAN_N_M  (0x01 << 1)
+#define MAX1027_SCAN_N    (0x02 << 1)
+#define MAX1027_NOSCAN    (0x03 << 1)
+#define MAX1027_CHAN(n)   ((n) << 3)
+
+/* setup register */
+#define MAX1027_UNIPOLAR  0x02
+#define MAX1027_BIPOLAR   0x03
+#define MAX1027_REF_MODE0 (0x00 << 2)
+#define MAX1027_REF_MODE1 (0x01 << 2)
+#define MAX1027_REF_MODE2 (0x02 << 2)
+#define MAX1027_REF_MODE3 (0x03 << 2)
+#define MAX1027_CKS_MODE0 (0x00 << 4)
+#define MAX1027_CKS_MODE1 (0x01 << 4)
+#define MAX1027_CKS_MODE2 (0x02 << 4)
+#define MAX1027_CKS_MODE3 (0x03 << 4)
+
+/* averaging register */
+#define MAX1027_NSCAN_4   0x00
+#define MAX1027_NSCAN_8   0x01
+#define MAX1027_NSCAN_12  0x02
+#define MAX1027_NSCAN_16  0x03
+#define MAX1027_NAVG_4    (0x00 << 2)
+#define MAX1027_NAVG_8    (0x01 << 2)
+#define MAX1027_NAVG_16   (0x02 << 2)
+#define MAX1027_NAVG_32   (0x03 << 2)
+#define MAX1027_AVG_EN    BIT(4)
+
+enum max1027_id {
+	max1027,
+	max1029,
+	max1031,
+};
+
+static const struct spi_device_id max1027_id[] = {
+	{"max1027", max1027},
+	{"max1029", max1029},
+	{"max1031", max1031},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, max1027_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id max1027_adc_dt_ids[] = {
+	{ .compatible = "maxim,max1027" },
+	{ .compatible = "maxim,max1029" },
+	{ .compatible = "maxim,max1031" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
+#endif
+
+#define MAX1027_V_CHAN(index)						\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = index,					\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.scan_index = index + 1,				\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = 10,					\
+			.storagebits = 16,				\
+			.shift = 2,					\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+#define MAX1027_T_CHAN							\
+	{								\
+		.type = IIO_TEMP,					\
+		.channel = 0,						\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.scan_index = 0,					\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = 12,					\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+static const struct iio_chan_spec max1027_channels[] = {
+	MAX1027_T_CHAN,
+	MAX1027_V_CHAN(0),
+	MAX1027_V_CHAN(1),
+	MAX1027_V_CHAN(2),
+	MAX1027_V_CHAN(3),
+	MAX1027_V_CHAN(4),
+	MAX1027_V_CHAN(5),
+	MAX1027_V_CHAN(6),
+	MAX1027_V_CHAN(7)
+};
+
+static const struct iio_chan_spec max1029_channels[] = {
+	MAX1027_T_CHAN,
+	MAX1027_V_CHAN(0),
+	MAX1027_V_CHAN(1),
+	MAX1027_V_CHAN(2),
+	MAX1027_V_CHAN(3),
+	MAX1027_V_CHAN(4),
+	MAX1027_V_CHAN(5),
+	MAX1027_V_CHAN(6),
+	MAX1027_V_CHAN(7),
+	MAX1027_V_CHAN(8),
+	MAX1027_V_CHAN(9),
+	MAX1027_V_CHAN(10),
+	MAX1027_V_CHAN(11)
+};
+
+static const struct iio_chan_spec max1031_channels[] = {
+	MAX1027_T_CHAN,
+	MAX1027_V_CHAN(0),
+	MAX1027_V_CHAN(1),
+	MAX1027_V_CHAN(2),
+	MAX1027_V_CHAN(3),
+	MAX1027_V_CHAN(4),
+	MAX1027_V_CHAN(5),
+	MAX1027_V_CHAN(6),
+	MAX1027_V_CHAN(7),
+	MAX1027_V_CHAN(8),
+	MAX1027_V_CHAN(9),
+	MAX1027_V_CHAN(10),
+	MAX1027_V_CHAN(11),
+	MAX1027_V_CHAN(12),
+	MAX1027_V_CHAN(13),
+	MAX1027_V_CHAN(14),
+	MAX1027_V_CHAN(15)
+};
+
+static const unsigned long max1027_available_scan_masks[] = {
+	0x000001ff,
+	0x00000000,
+};
+
+static const unsigned long max1029_available_scan_masks[] = {
+	0x00001fff,
+	0x00000000,
+};
+
+static const unsigned long max1031_available_scan_masks[] = {
+	0x0001ffff,
+	0x00000000,
+};
+
+struct max1027_chip_info {
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+	const unsigned long *available_scan_masks;
+};
+
+static const struct max1027_chip_info max1027_chip_info_tbl[] = {
+	[max1027] = {
+		.channels = max1027_channels,
+		.num_channels = ARRAY_SIZE(max1027_channels),
+		.available_scan_masks = max1027_available_scan_masks,
+	},
+	[max1029] = {
+		.channels = max1029_channels,
+		.num_channels = ARRAY_SIZE(max1029_channels),
+		.available_scan_masks = max1029_available_scan_masks,
+	},
+	[max1031] = {
+		.channels = max1031_channels,
+		.num_channels = ARRAY_SIZE(max1031_channels),
+		.available_scan_masks = max1031_available_scan_masks,
+	},
+};
+
+struct max1027_state {
+	const struct max1027_chip_info	*info;
+	struct spi_device		*spi;
+	struct iio_trigger		*trig;
+	__be16				*buffer;
+	struct mutex			lock;
+
+	u8				reg ____cacheline_aligned;
+};
+
+static int max1027_read_single_value(struct iio_dev *indio_dev,
+				     struct iio_chan_spec const *chan,
+				     int *val)
+{
+	int ret;
+	struct max1027_state *st = iio_priv(indio_dev);
+
+	if (iio_buffer_enabled(indio_dev)) {
+		dev_warn(&indio_dev->dev, "trigger mode already enabled");
+		return -EBUSY;
+	}
+
+	/* Start acquisition on conversion register write */
+	st->reg = MAX1027_SETUP_REG | MAX1027_REF_MODE2 | MAX1027_CKS_MODE2;
+	ret = spi_write(st->spi, &st->reg, 1);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev,
+			"Failed to configure setup register\n");
+		return ret;
+	}
+
+	/* Configure conversion register with the requested chan */
+	st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) |
+		  MAX1027_NOSCAN | !!(chan->type == IIO_TEMP);
+	ret = spi_write(st->spi, &st->reg, 1);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev,
+			"Failed to configure conversion register\n");
+		return ret;
+	}
+
+	/*
+	 * For an unknown reason, when we use the mode "10" (write
+	 * conversion register), the interrupt doesn't occur every time.
+	 * So we just wait 1 ms.
+	 */
+	mdelay(1);
+
+	/* Read result */
+	ret = spi_read(st->spi, st->buffer, (chan->type == IIO_TEMP) ? 4 : 2);
+	if (ret < 0)
+		return ret;
+
+	*val = be16_to_cpu(st->buffer[0]);
+
+	return IIO_VAL_INT;
+}
+
+static int max1027_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	int ret = 0;
+	struct max1027_state *st = iio_priv(indio_dev);
+
+	mutex_lock(&st->lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = max1027_read_single_value(indio_dev, chan, val);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_TEMP:
+			*val = 1;
+			*val2 = 8;
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case IIO_VOLTAGE:
+			*val = 2500;
+			*val2 = 10;
+			ret = IIO_VAL_FRACTIONAL_LOG2;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static int max1027_debugfs_reg_access(struct iio_dev *indio_dev,
+				      unsigned reg, unsigned writeval,
+				      unsigned *readval)
+{
+	struct max1027_state *st = iio_priv(indio_dev);
+	u8 *val = (u8 *)st->buffer;
+
+	if (readval != NULL)
+		return -EINVAL;
+
+	*val = (u8)writeval;
+	return spi_write(st->spi, val, 1);
+}
+
+static int max1027_validate_trigger(struct iio_dev *indio_dev,
+				    struct iio_trigger *trig)
+{
+	struct max1027_state *st = iio_priv(indio_dev);
+
+	if (st->trig != trig)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int max1027_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct max1027_state *st = iio_priv(indio_dev);
+	int ret;
+
+	if (state) {
+		/* Start acquisition on cnvst */
+		st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE0 |
+			  MAX1027_REF_MODE2;
+		ret = spi_write(st->spi, &st->reg, 1);
+		if (ret < 0)
+			return ret;
+
+		/* Scan from 0 to max */
+		st->reg = MAX1027_CONV_REG | MAX1027_CHAN(0) |
+			  MAX1027_SCAN_N_M | MAX1027_TEMP;
+		ret = spi_write(st->spi, &st->reg, 1);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* Start acquisition on conversion register write */
+		st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE2	|
+			  MAX1027_REF_MODE2;
+		ret = spi_write(st->spi, &st->reg, 1);
+		if (ret < 0)
+			return ret;
+	}
+
+	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;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct max1027_state *st = iio_priv(indio_dev);
+
+	pr_debug("%s(irq=%d, private=0x%p)\n", __func__, irq, private);
+
+	/* fill buffer with all channel */
+	spi_read(st->spi, st->buffer, indio_dev->masklength * 2);
+
+	iio_push_to_buffers(indio_dev, st->buffer);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_trigger_ops max1027_trigger_ops = {
+	.owner = THIS_MODULE,
+	.validate_device = &max1027_validate_device,
+	.set_trigger_state = &max1027_set_trigger_state,
+};
+
+static const struct iio_info max1027_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &max1027_read_raw,
+	.validate_trigger = &max1027_validate_trigger,
+	.debugfs_reg_access = &max1027_debugfs_reg_access,
+};
+
+static int max1027_probe(struct spi_device *spi)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct max1027_state *st;
+
+	pr_debug("%s: probe(spi = 0x%p)\n", __func__, spi);
+
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (indio_dev == NULL) {
+		pr_err("Can't allocate iio device\n");
+		return -ENOMEM;
+	}
+
+	spi_set_drvdata(spi, indio_dev);
+
+	st = iio_priv(indio_dev);
+	st->spi = spi;
+	st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	mutex_init(&st->lock);
+
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &max1027_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->info->channels;
+	indio_dev->num_channels = st->info->num_channels;
+	indio_dev->available_scan_masks = st->info->available_scan_masks;
+
+	st->buffer = devm_kmalloc(&indio_dev->dev,
+				  indio_dev->num_channels * 2,
+				  GFP_KERNEL);
+	if (st->buffer == NULL) {
+		dev_err(&indio_dev->dev, "Can't allocate bufffer\n");
+		return -ENOMEM;
+	}
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+					 &max1027_trigger_handler, NULL);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed to setup buffer\n");
+		return ret;
+	}
+
+	st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger",
+							indio_dev->name);
+	if (st->trig == NULL) {
+		ret = -ENOMEM;
+		dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n");
+		goto fail_trigger_alloc;
+	}
+
+	st->trig->ops = &max1027_trigger_ops;
+	st->trig->dev.parent = &spi->dev;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
+	iio_trigger_register(st->trig);
+
+	ret = devm_request_threaded_irq(&spi->dev, spi->irq,
+					iio_trigger_generic_data_rdy_poll,
+					NULL,
+					IRQF_TRIGGER_FALLING,
+					spi->dev.driver->name, st->trig);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
+		goto fail_dev_register;
+	}
+
+	/* Disable averaging */
+	st->reg = MAX1027_AVG_REG;
+	ret = spi_write(st->spi, &st->reg, 1);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed to configure averaging register\n");
+		goto fail_dev_register;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed to register iio device\n");
+		goto fail_dev_register;
+	}
+
+	return 0;
+
+fail_dev_register:
+fail_trigger_alloc:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int max1027_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+	pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static struct spi_driver max1027_driver = {
+	.driver = {
+		.name	= "max1027",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max1027_probe,
+	.remove		= max1027_remove,
+	.id_table	= max1027_id,
+};
+module_spi_driver(max1027_driver);
+
+MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");
+MODULE_DESCRIPTION("MAX1027/MAX1029/MAX1031 ADC");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/xilinx-xadc-core.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/xilinx-xadc-core.c
--- linux-libre-3.16-gnu/drivers/iio/adc/xilinx-xadc-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/xilinx-xadc-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -486,7 +486,7 @@ static irqreturn_t xadc_axi_interrupt_ha
 		return IRQ_NONE;
 
 	if ((status & XADC_AXI_INT_EOS) && xadc->trigger)
-		iio_trigger_poll(xadc->trigger, 0);
+		iio_trigger_poll(xadc->trigger);
 
 	if (status & XADC_AXI_INT_ALARM_MASK) {
 		/*
@@ -1126,7 +1126,7 @@ static int xadc_parse_dt(struct iio_dev
 				chan->address = XADC_REG_VPVN;
 			} else {
 				chan->scan_index = 15 + reg;
-				chan->scan_index = XADC_REG_VAUX(reg - 1);
+				chan->address = XADC_REG_VAUX(reg - 1);
 			}
 			num_channels++;
 			chan++;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/adc/xilinx-xadc-events.c linux-libre-3.17-rc7-gnu/drivers/iio/adc/xilinx-xadc-events.c
--- linux-libre-3.16-gnu/drivers/iio/adc/xilinx-xadc-events.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/adc/xilinx-xadc-events.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,17 +31,11 @@ static const struct iio_chan_spec *xadc_
 static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
 {
 	const struct iio_chan_spec *chan;
-	unsigned int offset;
 
 	/* Temperature threshold error, we don't handle this yet */
 	if (event == 0)
 		return;
 
-	if (event < 4)
-		offset = event;
-	else
-		offset = event + 4;
-
 	chan = xadc_event_to_channel(indio_dev, event);
 
 	if (chan->type == IIO_TEMP) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c linux-libre-3.17-rc7-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
--- linux-libre-3.16-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,12 +26,12 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
-struct {
+static struct {
 	u32 usage_id;
 	int unit; /* 0 for default others from HID sensor spec */
 	int scale_val0; /* scale, whole number */
 	int scale_val1; /* scale, fraction in micros */
-} static unit_conversion[] = {
+} unit_conversion[] = {
 	{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
 	{HID_USAGE_SENSOR_ACCEL_3D,
 		HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
@@ -343,6 +343,7 @@ int hid_sensor_format_scale(u32 usage_id
 }
 EXPORT_SYMBOL(hid_sensor_format_scale);
 
+static
 int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
 					u32 usage_id,
 					struct hid_sensor_common *st)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c linux-libre-3.17-rc7-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
--- linux-libre-3.16-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c	2014-09-28 17:29:07.000000000 -0400
@@ -122,7 +122,8 @@ int hid_sensor_setup_trigger(struct iio_
 		dev_err(&indio_dev->dev, "Trigger Register Failed\n");
 		goto error_free_trig;
 	}
-	indio_dev->trig = attrb->trigger = trig;
+	attrb->trigger = trig;
+	indio_dev->trig = iio_trigger_get(trig);
 
 	return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_core.c linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_core.c
--- linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,8 +14,8 @@
 #include <linux/delay.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of.h>
 #include <asm/unaligned.h>
-
 #include <linux/iio/common/st_sensors.h>
 
 
@@ -265,14 +265,47 @@ static int st_sensors_set_drdy_int_pin(s
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
+		struct st_sensors_platform_data *defdata)
+{
+	struct st_sensors_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+	u32 val;
+
+	if (!np)
+		return NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2))
+		pdata->drdy_int_pin = (u8) val;
+	else
+		pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 1;
+
+	return pdata;
+}
+#else
+static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
+		struct st_sensors_platform_data *defdata)
+{
+	return NULL;
+}
+#endif
+
 int st_sensors_init_sensor(struct iio_dev *indio_dev,
 					struct st_sensors_platform_data *pdata)
 {
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
+	struct st_sensors_platform_data *of_pdata;
 	int err = 0;
 
 	mutex_init(&sdata->tb.buf_lock);
 
+	/* If OF/DT pdata exists, it will take precedence of anything else */
+	of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata);
+	if (of_pdata)
+		pdata = of_pdata;
+
 	if (pdata)
 		err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
 
@@ -463,35 +496,6 @@ read_wai_error:
 }
 EXPORT_SYMBOL(st_sensors_check_device_support);
 
-ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
-
-	return sprintf(buf, "%d\n", adata->odr);
-}
-EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
-
-ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	int err;
-	unsigned int odr;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-
-	err = kstrtoint(buf, 10, &odr);
-	if (err < 0)
-		goto conversion_error;
-
-	mutex_lock(&indio_dev->mlock);
-	err = st_sensors_set_odr(indio_dev, odr);
-	mutex_unlock(&indio_dev->mlock);
-
-conversion_error:
-	return err < 0 ? err : size;
-}
-EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
-
 ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_i2c.c linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_i2c.c
--- linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/iio/iio.h>
+#include <linux/of_device.h>
 
 #include <linux/iio/common/st_sensors_i2c.h>
 
@@ -76,6 +77,35 @@ void st_sensors_i2c_configure(struct iio
 }
 EXPORT_SYMBOL(st_sensors_i2c_configure);
 
+#ifdef CONFIG_OF
+/**
+ * st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
+ * @client: the I2C client device for the sensor
+ * @match: the OF match table for the device, containing compatible strings
+ *	but also a .data field with the corresponding internal kernel name
+ *	used by this sensor.
+ *
+ * In effect this function matches a compatible string to an internal kernel
+ * name for a certain sensor device, so that the rest of the autodetection can
+ * rely on that name from this point on. I2C client devices will be renamed
+ * to match the internal kernel convention.
+ */
+void st_sensors_of_i2c_probe(struct i2c_client *client,
+			     const struct of_device_id *match)
+{
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(match, &client->dev);
+	if (!of_id)
+		return;
+
+	/* The name from the OF match takes precedence if present */
+	strncpy(client->name, of_id->data, sizeof(client->name));
+	client->name[sizeof(client->name) - 1] = '\0';
+}
+EXPORT_SYMBOL(st_sensors_of_i2c_probe);
+#endif
+
 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c
--- linux-libre-3.16-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,7 @@ int st_sensors_allocate_trigger(struct i
 		dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
 		goto iio_trigger_register_error;
 	}
-	indio_dev->trig = sdata->trig;
+	indio_dev->trig = iio_trigger_get(sdata->trig);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/ad5504.c linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5504.c
--- linux-libre-3.16-gnu/drivers/iio/dac/ad5504.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5504.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,17 +15,16 @@
 #include <linux/sysfs.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
 #include <linux/iio/dac/ad5504.h>
 
-#define AD5505_BITS			12
-#define AD5504_RES_MASK			((1 << (AD5505_BITS)) - 1)
-
-#define AD5504_CMD_READ			(1 << 15)
-#define AD5504_CMD_WRITE		(0 << 15)
+#define AD5504_RES_MASK			GENMASK(11, 0)
+#define AD5504_CMD_READ			BIT(15)
+#define AD5504_CMD_WRITE		0
 #define AD5504_ADDR(addr)		((addr) << 12)
 
 /* Registers */
@@ -42,7 +41,7 @@
 
 /**
  * struct ad5446_state - driver instance specific data
- * @us:			spi_device
+ * @spi:			spi_device
  * @reg:		supply regulator
  * @vref_mv:		actual reference voltage used
  * @pwr_down_mask	power down mask
@@ -126,7 +125,6 @@ static int ad5504_write_raw(struct iio_d
 			       long mask)
 {
 	struct ad5504_state *st = iio_priv(indio_dev);
-	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -135,10 +133,8 @@ static int ad5504_write_raw(struct iio_d
 
 		return ad5504_spi_write(st, chan->address, val);
 	default:
-		ret = -EINVAL;
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 static const char * const ad5504_powerdown_modes[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/ad5624r_spi.c linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5624r_spi.c
--- linux-libre-3.16-gnu/drivers/iio/dac/ad5624r_spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5624r_spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,6 @@ static int ad5624r_write_raw(struct iio_
 			       long mask)
 {
 	struct ad5624r_state *st = iio_priv(indio_dev);
-	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -79,10 +78,8 @@ static int ad5624r_write_raw(struct iio_
 				chan->address, val,
 				chan->scan_type.shift);
 	default:
-		ret = -EINVAL;
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 static const char * const ad5624r_powerdown_modes[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/ad5686.c linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5686.c
--- linux-libre-3.16-gnu/drivers/iio/dac/ad5686.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5686.c	2014-09-28 17:29:07.000000000 -0400
@@ -313,7 +313,7 @@ static int ad5686_probe(struct spi_devic
 {
 	struct ad5686_state *st;
 	struct iio_dev *indio_dev;
-	int ret, regdone = 0, voltage_uv = 0;
+	int ret, voltage_uv = 0;
 
 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
@@ -355,7 +355,6 @@ static int ad5686_probe(struct spi_devic
 	indio_dev->channels = st->chip_info->channel;
 	indio_dev->num_channels = AD5686_DAC_CHANNELS;
 
-	regdone = 1;
 	ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
 				!!voltage_uv, 0);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/ad5791.c linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5791.c
--- linux-libre-3.16-gnu/drivers/iio/dac/ad5791.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/ad5791.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,17 +16,16 @@
 #include <linux/sysfs.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/dac/ad5791.h>
 
-#define AD5791_RES_MASK(x)		((1 << (x)) - 1)
-#define AD5791_DAC_MASK			AD5791_RES_MASK(20)
-#define AD5791_DAC_MSB			(1 << 19)
+#define AD5791_DAC_MASK			GENMASK(19, 0)
 
-#define AD5791_CMD_READ			(1 << 23)
-#define AD5791_CMD_WRITE		(0 << 23)
+#define AD5791_CMD_READ			BIT(23)
+#define AD5791_CMD_WRITE		0
 #define AD5791_ADDR(addr)		((addr) << 20)
 
 /* Registers */
@@ -37,11 +36,11 @@
 #define AD5791_ADDR_SW_CTRL		4
 
 /* Control Register */
-#define AD5791_CTRL_RBUF		(1 << 1)
-#define AD5791_CTRL_OPGND		(1 << 2)
-#define AD5791_CTRL_DACTRI		(1 << 3)
-#define AD5791_CTRL_BIN2SC		(1 << 4)
-#define AD5791_CTRL_SDODIS		(1 << 5)
+#define AD5791_CTRL_RBUF		BIT(1)
+#define AD5791_CTRL_OPGND		BIT(2)
+#define AD5791_CTRL_DACTRI		BIT(3)
+#define AD5791_CTRL_BIN2SC		BIT(4)
+#define AD5791_CTRL_SDODIS		BIT(5)
 #define AD5761_CTRL_LINCOMP(x)		((x) << 6)
 
 #define AD5791_LINCOMP_0_10		0
@@ -54,9 +53,9 @@
 #define AD5780_LINCOMP_10_20		12
 
 /* Software Control Register */
-#define AD5791_SWCTRL_LDAC		(1 << 0)
-#define AD5791_SWCTRL_CLR		(1 << 1)
-#define AD5791_SWCTRL_RESET		(1 << 2)
+#define AD5791_SWCTRL_LDAC		BIT(0)
+#define AD5791_SWCTRL_CLR		BIT(1)
+#define AD5791_SWCTRL_RESET		BIT(2)
 
 #define AD5791_DAC_PWRDN_6K		0
 #define AD5791_DAC_PWRDN_3STATE		1
@@ -72,7 +71,7 @@ struct ad5791_chip_info {
 
 /**
  * struct ad5791_state - driver instance specific data
- * @us:			spi_device
+ * @spi:			spi_device
  * @reg_vdd:		positive supply regulator
  * @reg_vss:		negative supply regulator
  * @chip_info:		chip model specific constants
@@ -328,7 +327,7 @@ static int ad5791_write_raw(struct iio_d
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		val &= AD5791_RES_MASK(chan->scan_type.realbits);
+		val &= GENMASK(chan->scan_type.realbits - 1, 0);
 		val <<= chan->scan_type.shift;
 
 		return ad5791_spi_write(st, chan->address, val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/dac/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/dac/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -163,4 +163,14 @@ config MCP4725
 	  To compile this driver as a module, choose M here: the module
 	  will be called mcp4725.
 
+config MCP4922
+	tristate "MCP4902, MCP4912, MCP4922 DAC driver"
+	depends on SPI
+	help
+	  Say yes here to build the driver for the Microchip MCP4902
+	  MCP4912, and MCP4922 DAC devices.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mcp4922.
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/dac/Makefile
--- linux-libre-3.16-gnu/drivers/iio/dac/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -18,3 +18,4 @@ obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_MAX517) += max517.o
 obj-$(CONFIG_MCP4725) += mcp4725.o
+obj-$(CONFIG_MCP4922) += mcp4922.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/dac/mcp4922.c linux-libre-3.17-rc7-gnu/drivers/iio/dac/mcp4922.c
--- linux-libre-3.16-gnu/drivers/iio/dac/mcp4922.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/dac/mcp4922.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,216 @@
+/*
+ * mcp4922.c
+ *
+ * Driver for Microchip Digital to Analog Converters.
+ * Supports MCP4902, MCP4912, and MCP4922.
+ *
+ * Copyright (c) 2014 EMAC 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/module.h>
+#include <linux/init.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/bitops.h>
+
+#define MCP4922_NUM_CHANNELS	2
+
+enum mcp4922_supported_device_ids {
+	ID_MCP4902,
+	ID_MCP4912,
+	ID_MCP4922,
+};
+
+struct mcp4922_state {
+	struct spi_device *spi;
+	unsigned int value[MCP4922_NUM_CHANNELS];
+	unsigned int vref_mv;
+	struct regulator *vref_reg;
+	u8 mosi[2] ____cacheline_aligned;
+};
+
+#define MCP4922_CHAN(chan, bits) {			\
+	.type = IIO_VOLTAGE,				\
+	.output = 1,					\
+	.indexed = 1,					\
+	.channel = chan,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+	.scan_type = {					\
+		.sign = 'u',				\
+		.realbits = (bits),			\
+		.storagebits = 16,			\
+		.shift = 12 - (bits),			\
+	},						\
+}
+
+static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val)
+{
+	state->mosi[1] = val & 0xff;
+	state->mosi[0] = (addr == 0) ? 0x00 : 0x80;
+	state->mosi[0] |= 0x30 | ((val >> 8) & 0x0f);
+
+	return spi_write(state->spi, state->mosi, 2);
+}
+
+static int mcp4922_read_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan,
+		int *val,
+		int *val2,
+		long mask)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		*val = state->value[chan->channel];
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = state->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int mcp4922_write_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan,
+		int val,
+		int val2,
+		long mask)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+
+	if (val2 != 0)
+		return -EINVAL;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (val > GENMASK(chan->scan_type.realbits-1, 0))
+			return -EINVAL;
+		val <<= chan->scan_type.shift;
+		state->value[chan->channel] = val;
+		return mcp4922_spi_write(state, chan->channel, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = {
+	[ID_MCP4902] = { MCP4922_CHAN(0, 8),	MCP4922_CHAN(1, 8) },
+	[ID_MCP4912] = { MCP4922_CHAN(0, 10),	MCP4922_CHAN(1, 10) },
+	[ID_MCP4922] = { MCP4922_CHAN(0, 12),	MCP4922_CHAN(1, 12) },
+};
+
+static const struct iio_info mcp4922_info = {
+	.read_raw = &mcp4922_read_raw,
+	.write_raw = &mcp4922_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int mcp4922_probe(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev;
+	struct mcp4922_state *state;
+	const struct spi_device_id *id;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	state = iio_priv(indio_dev);
+	state->spi = spi;
+	state->vref_reg = devm_regulator_get(&spi->dev, "vref");
+	if (IS_ERR(state->vref_reg)) {
+		dev_err(&spi->dev, "Vref regulator not specified\n");
+		return PTR_ERR(state->vref_reg);
+	}
+
+	ret = regulator_enable(state->vref_reg);
+	if (ret) {
+		dev_err(&spi->dev, "Failed to enable vref regulator: %d\n",
+				ret);
+		return ret;
+	}
+
+	ret = regulator_get_voltage(state->vref_reg);
+	if (ret < 0) {
+		dev_err(&spi->dev, "Failed to read vref regulator: %d\n",
+				ret);
+		goto error_disable_reg;
+	}
+	state->vref_mv = ret / 1000;
+
+	spi_set_drvdata(spi, indio_dev);
+	id = spi_get_device_id(spi);
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &mcp4922_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = mcp4922_channels[id->driver_data];
+	indio_dev->num_channels = MCP4922_NUM_CHANNELS;
+	indio_dev->name = id->name;
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&spi->dev, "Failed to register iio device: %d\n",
+				ret);
+		goto error_disable_reg;
+	}
+
+	return 0;
+
+error_disable_reg:
+	regulator_disable(state->vref_reg);
+
+	return ret;
+}
+
+static int mcp4922_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct mcp4922_state *state;
+
+	iio_device_unregister(indio_dev);
+	state = iio_priv(indio_dev);
+	regulator_disable(state->vref_reg);
+
+	return 0;
+}
+
+static const struct spi_device_id mcp4922_id[] = {
+	{"mcp4902", ID_MCP4902},
+	{"mcp4912", ID_MCP4912},
+	{"mcp4922", ID_MCP4922},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, mcp4922_id);
+
+static struct spi_driver mcp4922_driver = {
+	.driver = {
+		   .name = "mcp4922",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = mcp4922_probe,
+	.remove = mcp4922_remove,
+	.id_table = mcp4922_id,
+};
+module_spi_driver(mcp4922_driver);
+
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
+MODULE_DESCRIPTION("Microchip MCP4902, MCP4912, MCP4922 DAC");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/gyro/adis16260.c linux-libre-3.17-rc7-gnu/drivers/iio/gyro/adis16260.c
--- linux-libre-3.16-gnu/drivers/iio/gyro/adis16260.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/gyro/adis16260.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,65 +101,6 @@
 #define ADIS16260_SCAN_TEMP	3
 #define ADIS16260_SCAN_ANGL	4
 
-static ssize_t adis16260_read_frequency(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis *adis = iio_priv(indio_dev);
-	int ret, len = 0;
-	u16 t;
-	int sps;
-	ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t);
-	if (ret)
-		return ret;
-
-	if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */
-		sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
-	else
-		sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
-	sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
-	len = sprintf(buf, "%d\n", sps);
-	return len;
-}
-
-static ssize_t adis16260_write_frequency(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis *adis = iio_priv(indio_dev);
-	unsigned int val;
-	int ret;
-	u8 t;
-
-	ret = kstrtouint(buf, 10, &val);
-	if (ret)
-		return ret;
-
-	mutex_lock(&indio_dev->mlock);
-	if (spi_get_device_id(adis->spi)->driver_data)
-		t = 256 / val;
-	else
-		t = 2048 / val;
-
-	if (t > ADIS16260_SMPL_PRD_DIV_MASK)
-		t = ADIS16260_SMPL_PRD_DIV_MASK;
-	else if (t > 0)
-		t--;
-
-	if (t >= 0x0A)
-		adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
-	else
-		adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
-	ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
-
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret ? ret : len;
-}
-
 /* Power down the device */
 static int adis16260_stop_device(struct iio_dev *indio_dev)
 {
@@ -174,18 +115,19 @@ static int adis16260_stop_device(struct
 	return ret;
 }
 
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-		adis16260_read_frequency,
-		adis16260_write_frequency);
-
 static const struct iio_chan_spec adis16260_channels[] = {
 	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
 		BIT(IIO_CHAN_INFO_CALIBBIAS) |
-		BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
-	ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
-	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
-	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
-	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
+		BIT(IIO_CHAN_INFO_CALIBSCALE),
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+	ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
@@ -258,6 +200,20 @@ static int adis16260_read_raw(struct iio
 
 		*val = val16;
 		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
+		if (ret)
+			return ret;
+
+		if (spi_get_device_id(adis->spi)->driver_data)
+		/* If an adis16251 */
+			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
+				8 : 256;
+		else
+			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
+				66 : 2048;
+		*val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
+		return IIO_VAL_INT;
 	}
 	return -EINVAL;
 }
@@ -269,7 +225,9 @@ static int adis16260_write_raw(struct ii
 			       long mask)
 {
 	struct adis *adis = iio_priv(indio_dev);
+	int ret;
 	u8 addr;
+	u8 t;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_CALIBBIAS:
@@ -284,21 +242,31 @@ static int adis16260_write_raw(struct ii
 
 		addr = adis16260_addresses[chan->scan_index][1];
 		return adis_write_reg_16(adis, addr, val);
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		mutex_lock(&indio_dev->mlock);
+		if (spi_get_device_id(adis->spi)->driver_data)
+			t = 256 / val;
+		else
+			t = 2048 / val;
+
+		if (t > ADIS16260_SMPL_PRD_DIV_MASK)
+			t = ADIS16260_SMPL_PRD_DIV_MASK;
+		else if (t > 0)
+			t--;
+
+		if (t >= 0x0A)
+			adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
+		else
+			adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
+		ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
+
+		mutex_unlock(&indio_dev->mlock);
+		return ret;
 	}
 	return -EINVAL;
 }
 
-static struct attribute *adis16260_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group adis16260_attribute_group = {
-	.attrs = adis16260_attributes,
-};
-
 static const struct iio_info adis16260_info = {
-	.attrs = &adis16260_attribute_group,
 	.read_raw = &adis16260_read_raw,
 	.write_raw = &adis16260_write_raw,
 	.update_scan_mode = adis_update_scan_mode,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/gyro/itg3200_buffer.c linux-libre-3.17-rc7-gnu/drivers/iio/gyro/itg3200_buffer.c
--- linux-libre-3.16-gnu/drivers/iio/gyro/itg3200_buffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/gyro/itg3200_buffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,7 +132,7 @@ int itg3200_probe_trigger(struct iio_dev
 		goto error_free_irq;
 
 	/* select default trigger */
-	indio_dev->trig = st->trig;
+	indio_dev->trig = iio_trigger_get(st->trig);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/gyro/itg3200_core.c linux-libre-3.17-rc7-gnu/drivers/iio/gyro/itg3200_core.c
--- linux-libre-3.16-gnu/drivers/iio/gyro/itg3200_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/gyro/itg3200_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,6 +90,7 @@ static int itg3200_read_raw(struct iio_d
 {
 	int ret = 0;
 	u8 reg;
+	u8 regval;
 
 	switch (info) {
 	case IIO_CHAN_INFO_RAW:
@@ -107,65 +108,60 @@ static int itg3200_read_raw(struct iio_d
 		/* Only the temperature channel has an offset */
 		*val = 23000;
 		return IIO_VAL_INT;
-	default:
-		return -EINVAL;
-	}
-}
-
-static ssize_t itg3200_read_frequency(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	int ret, sps;
-	u8 val;
-
-	ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &val);
-	if (ret)
-		return ret;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &regval);
+		if (ret)
+			return ret;
 
-	sps = (val & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
+		*val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
 
-	ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, &val);
-	if (ret)
-		return ret;
+		ret = itg3200_read_reg_8(indio_dev,
+					 ITG3200_REG_SAMPLE_RATE_DIV,
+					 &regval);
+		if (ret)
+			return ret;
 
-	sps /= val + 1;
+		*val /= regval + 1;
+		return IIO_VAL_INT;
 
-	return sprintf(buf, "%d\n", sps);
+	default:
+		return -EINVAL;
+	}
 }
 
-static ssize_t itg3200_write_frequency(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
+static int itg3200_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val,
+			     int val2,
+			     long mask)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	unsigned val;
 	int ret;
 	u8 t;
 
-	ret = kstrtouint(buf, 10, &val);
-	if (ret)
-		return ret;
-
-	mutex_lock(&indio_dev->mlock);
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val == 0 || val2 != 0)
+			return -EINVAL;
 
-	ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
-	if (ret)
-		goto err_ret;
+		mutex_lock(&indio_dev->mlock);
 
-	if (val == 0) {
-		ret = -EINVAL;
-		goto err_ret;
-	}
-	t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
+		ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
+		if (ret) {
+			mutex_unlock(&indio_dev->mlock);
+			return ret;
+		}
+		t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
 
-	ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, t);
+		ret = itg3200_write_reg_8(indio_dev,
+					  ITG3200_REG_SAMPLE_RATE_DIV,
+					  t);
 
-err_ret:
-	mutex_unlock(&indio_dev->mlock);
+		mutex_unlock(&indio_dev->mlock);
+	return ret;
 
-	return ret ? ret : len;
+	default:
+		return -EINVAL;
+	}
 }
 
 /*
@@ -255,6 +251,7 @@ err_ret:
 	.channel2 = IIO_MOD_ ## _mod, \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
 	.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
 	.scan_type = ITG3200_ST, \
@@ -267,6 +264,7 @@ static const struct iio_chan_spec itg320
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
 		BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 		.address = ITG3200_REG_TEMP_OUT_H,
 		.scan_index = ITG3200_SCAN_TEMP,
 		.scan_type = ITG3200_ST,
@@ -277,22 +275,9 @@ static const struct iio_chan_spec itg320
 	IIO_CHAN_SOFT_TIMESTAMP(ITG3200_SCAN_ELEMENTS),
 };
 
-/* IIO device attributes */
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, itg3200_read_frequency,
-		itg3200_write_frequency);
-
-static struct attribute *itg3200_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group itg3200_attribute_group = {
-	.attrs = itg3200_attributes,
-};
-
 static const struct iio_info itg3200_info = {
-	.attrs = &itg3200_attribute_group,
 	.read_raw = &itg3200_read_raw,
+	.write_raw = &itg3200_write_raw,
 	.driver_module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/gyro/st_gyro_core.c linux-libre-3.17-rc7-gnu/drivers/iio/gyro/st_gyro_core.c
--- linux-libre-3.16-gnu/drivers/iio/gyro/st_gyro_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/gyro/st_gyro_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -245,6 +245,9 @@ static int st_gyro_read_raw(struct iio_d
 		*val = 0;
 		*val2 = gdata->current_fullscale->gain;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = gdata->odr;
+		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
 	}
@@ -262,6 +265,13 @@ static int st_gyro_write_raw(struct iio_
 	case IIO_CHAN_INFO_SCALE:
 		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&indio_dev->mlock);
+		err = st_sensors_set_odr(indio_dev, val);
+		mutex_unlock(&indio_dev->mlock);
+		return err;
 	default:
 		err = -EINVAL;
 	}
@@ -269,14 +279,12 @@ static int st_gyro_write_raw(struct iio_
 	return err;
 }
 
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
 
 static struct attribute *st_gyro_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/gyro/st_gyro_i2c.c linux-libre-3.17-rc7-gnu/drivers/iio/gyro/st_gyro_i2c.c
--- linux-libre-3.16-gnu/drivers/iio/gyro/st_gyro_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/gyro/st_gyro_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,43 @@
 #include <linux/iio/common/st_sensors_i2c.h>
 #include "st_gyro.h"
 
+#ifdef CONFIG_OF
+static const struct of_device_id st_gyro_of_match[] = {
+	{
+		.compatible = "st,l3g4200d-gyro",
+		.data = L3G4200D_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330d-gyro",
+		.data = LSM330D_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330dl-gyro",
+		.data = LSM330DL_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330dlc-gyro",
+		.data = LSM330DLC_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,l3gd20-gyro",
+		.data = L3GD20_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,l3g4is-gyro",
+		.data = L3G4IS_GYRO_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm330-gyro",
+		.data = LSM330_GYRO_DEV_NAME,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_gyro_of_match);
+#else
+#define st_gyro_of_match NULL
+#endif
+
 static int st_gyro_i2c_probe(struct i2c_client *client,
 						const struct i2c_device_id *id)
 {
@@ -31,6 +68,7 @@ static int st_gyro_i2c_probe(struct i2c_
 
 	gdata = iio_priv(indio_dev);
 	gdata->dev = &client->dev;
+	st_sensors_of_i2c_probe(client, st_gyro_of_match);
 
 	st_sensors_i2c_configure(indio_dev, client, gdata);
 
@@ -65,6 +103,7 @@ static struct i2c_driver st_gyro_driver
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "st-gyro-i2c",
+		.of_match_table = of_match_ptr(st_gyro_of_match),
 	},
 	.probe = st_gyro_i2c_probe,
 	.remove = st_gyro_i2c_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/imu/adis16400_buffer.c linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16400_buffer.c
--- linux-libre-3.16-gnu/drivers/iio/imu/adis16400_buffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16400_buffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,7 @@ int adis16400_update_scan_mode(struct ii
 {
 	struct adis16400_state *st = iio_priv(indio_dev);
 	struct adis *adis = &st->adis;
-	uint16_t *tx, *rx;
+	uint16_t *tx;
 
 	if (st->variant->flags & ADIS16400_NO_BURST)
 		return adis_update_scan_mode(indio_dev, scan_mask);
@@ -35,7 +35,6 @@ int adis16400_update_scan_mode(struct ii
 	if (!adis->buffer)
 		return -ENOMEM;
 
-	rx = adis->buffer;
 	tx = adis->buffer + indio_dev->scan_bytes;
 
 	tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/imu/adis16400_core.c linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16400_core.c
--- linux-libre-3.16-gnu/drivers/iio/imu/adis16400_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16400_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -214,21 +214,6 @@ static int adis16400_set_freq(struct adi
 	return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
 }
 
-static ssize_t adis16400_read_frequency(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16400_state *st = iio_priv(indio_dev);
-	int ret;
-
-	ret = st->variant->get_freq(st);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d.%.3d\n", ret / 1000, ret % 1000);
-}
-
 static const unsigned adis16400_3db_divisors[] = {
 	[0] = 2, /* Special case */
 	[1] = 6,
@@ -260,30 +245,6 @@ static int adis16400_set_filter(struct i
 	return ret;
 }
 
-static ssize_t adis16400_write_frequency(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16400_state *st = iio_priv(indio_dev);
-	int i, f, val;
-	int ret;
-
-	ret = iio_str_to_fixpoint(buf, 100, &i, &f);
-	if (ret)
-		return ret;
-
-	val = i * 1000 + f;
-
-	if (val <= 0)
-		return -EINVAL;
-
-	mutex_lock(&indio_dev->mlock);
-	st->variant->set_freq(st, val);
-	mutex_unlock(&indio_dev->mlock);
-
-	return len;
-}
-
 /* Power down the device */
 static int adis16400_stop_device(struct iio_dev *indio_dev)
 {
@@ -350,10 +311,6 @@ err_ret:
 	return ret;
 }
 
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-			      adis16400_read_frequency,
-			      adis16400_write_frequency);
-
 static const uint8_t adis16400_addresses[] = {
 	[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
 	[ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
@@ -394,6 +351,16 @@ static int adis16400_write_raw(struct ii
 			val * 1000 + val2 / 1000);
 		mutex_unlock(&indio_dev->mlock);
 		return ret;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		sps = val * 1000 + val2 / 1000;
+
+		if (sps <= 0)
+			return -EINVAL;
+
+		mutex_lock(&indio_dev->mlock);
+		ret = st->variant->set_freq(st, sps);
+		mutex_unlock(&indio_dev->mlock);
+		return ret;
 	default:
 		return -EINVAL;
 	}
@@ -474,6 +441,13 @@ static int adis16400_read_raw(struct iio
 		if (ret < 0)
 			return ret;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = st->variant->get_freq(st);
+		if (ret < 0)
+			return ret;
+		*val = ret / 1000;
+		*val2 = (ret % 1000) * 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
 	}
@@ -486,6 +460,7 @@ static int adis16400_read_raw(struct iio
 	.extend_name = name, \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
 		BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	.address = (addr), \
 	.scan_index = (si), \
 	.scan_type = { \
@@ -511,6 +486,7 @@ static int adis16400_read_raw(struct iio
 		BIT(IIO_CHAN_INFO_CALIBBIAS),		  \
 	.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 = addr, \
 	.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
 	.scan_type = { \
@@ -530,6 +506,7 @@ static int adis16400_read_raw(struct iio
 		BIT(IIO_CHAN_INFO_CALIBBIAS), \
 	.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 = (addr), \
 	.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
 	.scan_type = { \
@@ -548,6 +525,7 @@ static int adis16400_read_raw(struct iio
 	.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 = (addr), \
 	.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
 	.scan_type = { \
@@ -573,6 +551,7 @@ static int adis16400_read_raw(struct iio
 		BIT(IIO_CHAN_INFO_SCALE), \
 	.info_mask_shared_by_type = \
 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	.address = (addr), \
 	.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
 	.scan_type = { \
@@ -591,6 +570,7 @@ static int adis16400_read_raw(struct iio
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
 		BIT(IIO_CHAN_INFO_OFFSET) | \
 		BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	.address = (addr), \
 	.scan_index = ADIS16350_SCAN_TEMP_X, \
 	.scan_type = { \
@@ -608,6 +588,7 @@ static int adis16400_read_raw(struct iio
 	.channel2 = IIO_MOD_ ## mod, \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	.address = (addr), \
 	.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
 	.scan_type = { \
@@ -649,6 +630,7 @@ static const struct iio_chan_spec adis16
 		.type = IIO_PRESSURE,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 		.address = ADIS16448_BARO_OUT,
 		.scan_index = ADIS16400_SCAN_BARO,
 		.scan_type = {
@@ -704,15 +686,6 @@ static const struct iio_chan_spec adis16
 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
-static struct attribute *adis16400_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group adis16400_attribute_group = {
-	.attrs = adis16400_attributes,
-};
-
 static struct adis16400_chip_info adis16400_chips[] = {
 	[ADIS16300] = {
 		.channels = adis16300_channels,
@@ -813,7 +786,6 @@ static const struct iio_info adis16400_i
 	.driver_module = THIS_MODULE,
 	.read_raw = &adis16400_read_raw,
 	.write_raw = &adis16400_write_raw,
-	.attrs = &adis16400_attribute_group,
 	.update_scan_mode = adis16400_update_scan_mode,
 	.debugfs_reg_access = adis_debugfs_reg_access,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/imu/adis16480.c linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16480.c
--- linux-libre-3.16-gnu/drivers/iio/imu/adis16480.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/imu/adis16480.c	2014-09-28 17:29:07.000000000 -0400
@@ -257,11 +257,16 @@ static int adis16480_debugfs_init(struct
 
 #endif
 
-static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
+static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
 {
+	struct adis16480 *st = iio_priv(indio_dev);
 	unsigned int t;
 
-	t = 2460000 / freq;
+	t =  val * 1000 + val2 / 1000;
+	if (t <= 0)
+		return -EINVAL;
+
+	t = 2460000 / t;
 	if (t > 2048)
 		t = 2048;
 
@@ -271,65 +276,24 @@ static int adis16480_set_freq(struct adi
 	return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
 }
 
-static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq)
+static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
 {
+	struct adis16480 *st = iio_priv(indio_dev);
 	uint16_t t;
 	int ret;
+	unsigned freq;
 
 	ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
 	if (ret < 0)
 		return ret;
 
-	*freq = 2460000 / (t + 1);
-
-	return 0;
-}
-
-static ssize_t adis16480_read_frequency(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16480 *st = iio_priv(indio_dev);
-	unsigned int freq;
-	int ret;
-
-	ret = adis16480_get_freq(st, &freq);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000);
-}
-
-static ssize_t adis16480_write_frequency(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct adis16480 *st = iio_priv(indio_dev);
-	int freq_int, freq_fract;
-	long val;
-	int ret;
-
-	ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract);
-	if (ret)
-		return ret;
-
-	val = freq_int * 1000 + freq_fract;
-
-	if (val <= 0)
-		return -EINVAL;
-
-	ret = adis16480_set_freq(st, val);
+	freq = 2460000 / (t + 1);
+	*val = freq / 1000;
+	*val2 = (freq % 1000) * 1000;
 
-	return ret ? ret : len;
+	return IIO_VAL_INT_PLUS_MICRO;
 }
 
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-			      adis16480_read_frequency,
-			      adis16480_write_frequency);
-
 enum {
 	ADIS16480_SCAN_GYRO_X,
 	ADIS16480_SCAN_GYRO_Y,
@@ -571,6 +535,8 @@ static int adis16480_read_raw(struct iio
 		return adis16480_get_calibscale(indio_dev, chan, val);
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
 		return adis16480_get_filter_freq(indio_dev, chan, val);
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return adis16480_get_freq(indio_dev, val, val2);
 	default:
 		return -EINVAL;
 	}
@@ -586,6 +552,9 @@ static int adis16480_write_raw(struct ii
 		return adis16480_set_calibscale(indio_dev, chan, val);
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
 		return adis16480_set_filter_freq(indio_dev, chan, val);
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return adis16480_set_freq(indio_dev, val, val2);
+
 	default:
 		return -EINVAL;
 	}
@@ -600,6 +569,7 @@ static int adis16480_write_raw(struct ii
 			BIT(IIO_CHAN_INFO_CALIBBIAS) | \
 			_info_sep, \
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 		.address = (_address), \
 		.scan_index = (_si), \
 		.scan_type = { \
@@ -638,6 +608,7 @@ static int adis16480_write_raw(struct ii
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
 			BIT(IIO_CHAN_INFO_CALIBBIAS) | \
 			BIT(IIO_CHAN_INFO_SCALE), \
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 		.address = ADIS16480_REG_BAROM_OUT, \
 		.scan_index = ADIS16480_SCAN_BARO, \
 		.scan_type = { \
@@ -655,6 +626,7 @@ static int adis16480_write_raw(struct ii
 		.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), \
 		.address = ADIS16480_REG_TEMP_OUT, \
 		.scan_index = ADIS16480_SCAN_TEMP, \
 		.scan_type = { \
@@ -717,17 +689,7 @@ static const struct adis16480_chip_info
 	},
 };
 
-static struct attribute *adis16480_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group adis16480_attribute_group = {
-	.attrs = adis16480_attributes,
-};
-
 static const struct iio_info adis16480_info = {
-	.attrs = &adis16480_attribute_group,
 	.read_raw = &adis16480_read_raw,
 	.write_raw = &adis16480_write_raw,
 	.update_scan_mode = adis_update_scan_mode,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c linux-libre-3.17-rc7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
--- linux-libre-3.16-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,7 +135,7 @@ int inv_mpu6050_probe_trigger(struct iio
 	ret = iio_trigger_register(st->trig);
 	if (ret)
 		goto error_free_irq;
-	indio_dev->trig = st->trig;
+	indio_dev->trig = iio_trigger_get(st->trig);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/industrialio-buffer.c linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-buffer.c
--- linux-libre-3.16-gnu/drivers/iio/industrialio-buffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-buffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,10 +39,7 @@ static bool iio_buffer_is_active(struct
 
 static bool iio_buffer_data_available(struct iio_buffer *buf)
 {
-	if (buf->access->data_available)
-		return buf->access->data_available(buf);
-
-	return buf->stufftoread;
+	return buf->access->data_available(buf);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/industrialio-core.c linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-core.c
--- linux-libre-3.16-gnu/drivers/iio/industrialio-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,10 @@ static const char * const iio_modifier_n
 	[IIO_MOD_QUATERNION] = "quaternion",
 	[IIO_MOD_TEMP_AMBIENT] = "ambient",
 	[IIO_MOD_TEMP_OBJECT] = "object",
+	[IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
+	[IIO_MOD_NORTH_TRUE] = "from_north_true",
+	[IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
+	[IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
 };
 
 /* relies on pairs of these shared then separate */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/industrialio-event.c linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-event.c
--- linux-libre-3.16-gnu/drivers/iio/industrialio-event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-event.c	2014-09-28 17:29:07.000000000 -0400
@@ -209,6 +209,7 @@ static const char * const iio_ev_info_te
 	[IIO_EV_INFO_ENABLE] = "en",
 	[IIO_EV_INFO_VALUE] = "value",
 	[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
+	[IIO_EV_INFO_PERIOD] = "period",
 };
 
 static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/industrialio-trigger.c linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-trigger.c
--- linux-libre-3.16-gnu/drivers/iio/industrialio-trigger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/industrialio-trigger.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,7 @@ static struct iio_trigger *iio_trigger_f
 	return trig;
 }
 
-void iio_trigger_poll(struct iio_trigger *trig, s64 time)
+void iio_trigger_poll(struct iio_trigger *trig)
 {
 	int i;
 
@@ -133,12 +133,12 @@ EXPORT_SYMBOL(iio_trigger_poll);
 
 irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private)
 {
-	iio_trigger_poll(private, iio_get_time_ns());
+	iio_trigger_poll(private);
 	return IRQ_HANDLED;
 }
 EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
 
-void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
+void iio_trigger_poll_chained(struct iio_trigger *trig)
 {
 	int i;
 
@@ -161,7 +161,7 @@ void iio_trigger_notify_done(struct iio_
 		trig->ops->try_reenable)
 		if (trig->ops->try_reenable(trig))
 			/* Missed an interrupt so launch new poll now */
-			iio_trigger_poll(trig, 0);
+			iio_trigger_poll(trig);
 }
 EXPORT_SYMBOL(iio_trigger_notify_done);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/inkern.c linux-libre-3.17-rc7-gnu/drivers/iio/inkern.c
--- linux-libre-3.16-gnu/drivers/iio/inkern.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/inkern.c	2014-09-28 17:29:07.000000000 -0400
@@ -178,7 +178,7 @@ static struct iio_channel *of_iio_channe
 			index = of_property_match_string(np, "io-channel-names",
 							 name);
 		chan = of_iio_channel_get(np, index);
-		if (!IS_ERR(chan))
+		if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
 			break;
 		else if (name && index >= 0) {
 			pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/cm32181.c linux-libre-3.17-rc7-gnu/drivers/iio/light/cm32181.c
--- linux-libre-3.16-gnu/drivers/iio/light/cm32181.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/cm32181.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,7 +331,7 @@ static int cm32181_probe(struct i2c_clie
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
+	ret = devm_iio_device_register(&client->dev, indio_dev);
 	if (ret) {
 		dev_err(&client->dev,
 			"%s: regist device failed\n",
@@ -342,14 +342,6 @@ static int cm32181_probe(struct i2c_clie
 	return 0;
 }
 
-static int cm32181_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
-	iio_device_unregister(indio_dev);
-	return 0;
-}
-
 static const struct i2c_device_id cm32181_id[] = {
 	{ "cm32181", 0 },
 	{ }
@@ -370,7 +362,6 @@ static struct i2c_driver cm32181_driver
 	},
 	.id_table       = cm32181_id,
 	.probe		= cm32181_probe,
-	.remove		= cm32181_remove,
 };
 
 module_i2c_driver(cm32181_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/gp2ap020a00f.c linux-libre-3.17-rc7-gnu/drivers/iio/light/gp2ap020a00f.c
--- linux-libre-3.16-gnu/drivers/iio/light/gp2ap020a00f.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/gp2ap020a00f.c	2014-09-28 17:29:07.000000000 -0400
@@ -827,7 +827,7 @@ static void gp2ap020a00f_iio_trigger_wor
 	struct gp2ap020a00f_data *data =
 		container_of(work, struct gp2ap020a00f_data, work);
 
-	iio_trigger_poll(data->trig, 0);
+	iio_trigger_poll(data->trig);
 }
 
 static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/isl29125.c linux-libre-3.17-rc7-gnu/drivers/iio/light/isl29125.c
--- linux-libre-3.16-gnu/drivers/iio/light/isl29125.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/isl29125.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,347 @@
+/*
+ * isl29125.c - Support for Intersil ISL29125 RGB light sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * RGB light sensor with 16-bit channels for red, green, blue);
+ * 7-bit I2C slave address 0x44
+ *
+ * TODO: interrupt support, IR compensation, thresholds, 12bit
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define ISL29125_DRV_NAME "isl29125"
+
+#define ISL29125_DEVICE_ID 0x00
+#define ISL29125_CONF1 0x01
+#define ISL29125_CONF2 0x02
+#define ISL29125_CONF3 0x03
+#define ISL29125_STATUS 0x08
+#define ISL29125_GREEN_DATA 0x09
+#define ISL29125_RED_DATA 0x0b
+#define ISL29125_BLUE_DATA 0x0d
+
+#define ISL29125_ID 0x7d
+
+#define ISL29125_MODE_MASK GENMASK(2, 0)
+#define ISL29125_MODE_PD 0x0
+#define ISL29125_MODE_G 0x1
+#define ISL29125_MODE_R 0x2
+#define ISL29125_MODE_B 0x3
+#define ISL29125_MODE_RGB 0x5
+
+#define ISL29125_MODE_RANGE BIT(3)
+
+#define ISL29125_STATUS_CONV BIT(1)
+
+struct isl29125_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	u8 conf1;
+	u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */
+};
+
+#define ISL29125_CHANNEL(_color, _si) { \
+	.type = IIO_INTENSITY, \
+	.modified = 1, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+	.channel2 = IIO_MOD_LIGHT_##_color, \
+	.scan_index = _si, \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	}, \
+}
+
+static const struct iio_chan_spec isl29125_channels[] = {
+	ISL29125_CHANNEL(GREEN, 0),
+	ISL29125_CHANNEL(RED, 1),
+	ISL29125_CHANNEL(BLUE, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct {
+	u8 mode, data;
+} isl29125_regs[] = {
+	{ISL29125_MODE_G, ISL29125_GREEN_DATA},
+	{ISL29125_MODE_R, ISL29125_RED_DATA},
+	{ISL29125_MODE_B, ISL29125_BLUE_DATA},
+};
+
+static int isl29125_read_data(struct isl29125_data *data, int si)
+{
+	int tries = 5;
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		data->conf1 | isl29125_regs[si].mode);
+	if (ret < 0)
+		return ret;
+
+	msleep(101);
+
+	while (tries--) {
+		ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
+		if (ret < 0)
+			goto fail;
+		if (ret & ISL29125_STATUS_CONV)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(&data->client->dev, "data not ready\n");
+		ret = -EIO;
+		goto fail;
+	}
+
+	ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);
+
+fail:
+	i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
+	return ret;
+}
+
+static int isl29125_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct isl29125_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (iio_buffer_enabled(indio_dev))
+			return -EBUSY;
+		mutex_lock(&data->lock);
+		ret = isl29125_read_data(data, chan->scan_index);
+		mutex_unlock(&data->lock);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		if (data->conf1 & ISL29125_MODE_RANGE)
+			*val2 = 152590; /* 10k lux full range */
+		else
+			*val2 = 5722; /* 375 lux full range */
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int isl29125_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	struct isl29125_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		if (val != 0)
+			return -EINVAL;
+		if (val2 == 152590)
+			data->conf1 |= ISL29125_MODE_RANGE;
+		else if (val2 == 5722)
+			data->conf1 &= ~ISL29125_MODE_RANGE;
+		else
+			return -EINVAL;
+		return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+			data->conf1);
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t isl29125_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct isl29125_data *data = iio_priv(indio_dev);
+	int i, j = 0;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		int ret = i2c_smbus_read_word_data(data->client,
+			isl29125_regs[i].data);
+		if (ret < 0)
+			goto done;
+
+		data->buffer[j++] = ret;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_info isl29125_info = {
+	.read_raw = isl29125_read_raw,
+	.write_raw = isl29125_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct isl29125_data *data = iio_priv(indio_dev);
+
+	data->conf1 |= ISL29125_MODE_RGB;
+	return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		data->conf1);
+}
+
+static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct isl29125_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = iio_triggered_buffer_predisable(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	data->conf1 &= ~ISL29125_MODE_MASK;
+	data->conf1 |= ISL29125_MODE_PD;
+	return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		data->conf1);
+}
+
+static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
+	.preenable = isl29125_buffer_preenable,
+	.postenable = &iio_triggered_buffer_postenable,
+	.predisable = isl29125_buffer_predisable,
+};
+
+static int isl29125_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct isl29125_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	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;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &isl29125_info;
+	indio_dev->name = ISL29125_DRV_NAME;
+	indio_dev->channels = isl29125_channels;
+	indio_dev->num_channels = ARRAY_SIZE(isl29125_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID);
+	if (ret < 0)
+		return ret;
+	if (ret != ISL29125_ID)
+		return -ENODEV;
+
+	data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE;
+	ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		data->conf1);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		isl29125_trigger_handler, &isl29125_buffer_setup_ops);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int isl29125_powerdown(struct isl29125_data *data)
+{
+	return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		(data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD);
+}
+
+static int isl29125_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);
+	isl29125_powerdown(iio_priv(indio_dev));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int isl29125_suspend(struct device *dev)
+{
+	struct isl29125_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return isl29125_powerdown(data);
+}
+
+static int isl29125_resume(struct device *dev)
+{
+	struct isl29125_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+		data->conf1);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume);
+
+static const struct i2c_device_id isl29125_id[] = {
+	{ "isl29125", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, isl29125_id);
+
+static struct i2c_driver isl29125_driver = {
+	.driver = {
+		.name	= ISL29125_DRV_NAME,
+		.pm	= &isl29125_pm_ops,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= isl29125_probe,
+	.remove		= isl29125_remove,
+	.id_table	= isl29125_id,
+};
+module_i2c_driver(isl29125_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("ISL29125 RGB light sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/light/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/light/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -62,6 +62,18 @@ config GP2AP020A00F
 	  To compile this driver as a module, choose M here: the
 	  module will be called gp2ap020a00f.
 
+config ISL29125
+	tristate "Intersil ISL29125 digital color light sensor"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say Y here if you want to build a driver for the Intersil ISL29125
+	  RGB light sensor for I2C.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called isl29125.
+
 config HID_SENSOR_ALS
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
@@ -116,6 +128,18 @@ config LTR501
 	 This driver can also be built as a module.  If so, the module
          will be called ltr501.
 
+config TCS3414
+	tristate "TAOS TCS3414 digital color sensor"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	 If you say yes here you get support for the TAOS TCS3414
+	 family of digital color sensors.
+
+	 This driver can also be built as a module.  If so, the module
+	 will be called tcs3414.
+
 config TCS3472
 	tristate "TAOS TCS3472 color light-to-digital converter"
 	depends on I2C
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/light/Makefile
--- linux-libre-3.16-gnu/drivers/iio/light/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,9 +10,11 @@ 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_ISL29125)		+= isl29125.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_LTR501)		+= ltr501.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
+obj-$(CONFIG_TCS3414)		+= tcs3414.o
 obj-$(CONFIG_TCS3472)		+= tcs3472.o
 obj-$(CONFIG_TSL4531)		+= tsl4531.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/light/tcs3414.c linux-libre-3.17-rc7-gnu/drivers/iio/light/tcs3414.c
--- linux-libre-3.16-gnu/drivers/iio/light/tcs3414.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/light/tcs3414.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,405 @@
+/*
+ * tcs3414.c - Support for TAOS TCS3414 digital color sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Digital color sensor with 16-bit channels for red, green, blue, clear);
+ * 7-bit I2C slave address 0x39 (TCS3414) or 0x29, 0x49, 0x59 (TCS3413,
+ * TCS3415, TCS3416, resp.)
+ *
+ * TODO: sync, interrupt support, thresholds, prescaler
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define TCS3414_DRV_NAME "tcs3414"
+
+#define TCS3414_COMMAND BIT(7)
+#define TCS3414_COMMAND_WORD (TCS3414_COMMAND | BIT(5))
+
+#define TCS3414_CONTROL (TCS3414_COMMAND | 0x00)
+#define TCS3414_TIMING (TCS3414_COMMAND | 0x01)
+#define TCS3414_ID (TCS3414_COMMAND | 0x04)
+#define TCS3414_GAIN (TCS3414_COMMAND | 0x07)
+#define TCS3414_DATA_GREEN (TCS3414_COMMAND_WORD | 0x10)
+#define TCS3414_DATA_RED (TCS3414_COMMAND_WORD | 0x12)
+#define TCS3414_DATA_BLUE (TCS3414_COMMAND_WORD | 0x14)
+#define TCS3414_DATA_CLEAR (TCS3414_COMMAND_WORD | 0x16)
+
+#define TCS3414_CONTROL_ADC_VALID BIT(4)
+#define TCS3414_CONTROL_ADC_EN BIT(1)
+#define TCS3414_CONTROL_POWER BIT(0)
+
+#define TCS3414_INTEG_MASK GENMASK(1, 0)
+#define TCS3414_INTEG_12MS 0x0
+#define TCS3414_INTEG_100MS 0x1
+#define TCS3414_INTEG_400MS 0x2
+
+#define TCS3414_GAIN_MASK GENMASK(5, 4)
+#define TCS3414_GAIN_SHIFT 4
+
+struct tcs3414_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	u8 control;
+	u8 gain;
+	u8 timing;
+	u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */
+};
+
+#define TCS3414_CHANNEL(_color, _si, _addr) { \
+	.type = IIO_INTENSITY, \
+	.modified = 1, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_INT_TIME), \
+	.channel2 = IIO_MOD_LIGHT_##_color, \
+	.address = _addr, \
+	.scan_index = _si, \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	}, \
+}
+
+/* scale factors: 1/gain */
+static const int tcs3414_scales[][2] = {
+	{1, 0}, {0, 250000}, {0, 62500}, {0, 15625}
+};
+
+/* integration time in ms */
+static const int tcs3414_times[] = { 12, 100, 400 };
+
+static const struct iio_chan_spec tcs3414_channels[] = {
+	TCS3414_CHANNEL(GREEN, 0, TCS3414_DATA_GREEN),
+	TCS3414_CHANNEL(RED, 1, TCS3414_DATA_RED),
+	TCS3414_CHANNEL(BLUE, 2, TCS3414_DATA_BLUE),
+	TCS3414_CHANNEL(CLEAR, 3, TCS3414_DATA_CLEAR),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static int tcs3414_req_data(struct tcs3414_data *data)
+{
+	int tries = 25;
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control | TCS3414_CONTROL_ADC_EN);
+	if (ret < 0)
+		return ret;
+
+	while (tries--) {
+		ret = i2c_smbus_read_byte_data(data->client, TCS3414_CONTROL);
+		if (ret < 0)
+			return ret;
+		if (ret & TCS3414_CONTROL_ADC_VALID)
+			break;
+		msleep(20);
+	}
+
+	ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control);
+	if (ret < 0)
+		return ret;
+
+	if (tries < 0) {
+		dev_err(&data->client->dev, "data not ready\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tcs3414_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct tcs3414_data *data = iio_priv(indio_dev);
+	int i, ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (iio_buffer_enabled(indio_dev))
+			return -EBUSY;
+		mutex_lock(&data->lock);
+		ret = tcs3414_req_data(data);
+		if (ret < 0) {
+			mutex_unlock(&data->lock);
+			return ret;
+		}
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		mutex_unlock(&data->lock);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+	i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT;
+	*val = tcs3414_scales[i][0];
+		*val2 = tcs3414_scales[i][1];
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		*val2 = tcs3414_times[data->timing & TCS3414_INTEG_MASK] * 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int tcs3414_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	struct tcs3414_data *data = iio_priv(indio_dev);
+	int i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		for (i = 0; i < ARRAY_SIZE(tcs3414_scales); i++) {
+			if (val == tcs3414_scales[i][0] &&
+				val2 == tcs3414_scales[i][1]) {
+				data->gain &= ~TCS3414_GAIN_MASK;
+				data->gain |= i << TCS3414_GAIN_SHIFT;
+				return i2c_smbus_write_byte_data(
+					data->client, TCS3414_GAIN,
+					data->gain);
+			}
+		}
+		return -EINVAL;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) {
+			if (val == tcs3414_times[i] * 1000) {
+				data->timing &= ~TCS3414_INTEG_MASK;
+				data->timing |= i;
+				return i2c_smbus_write_byte_data(
+					data->client, TCS3414_TIMING,
+					data->timing);
+			}
+		}
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t tcs3414_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tcs3414_data *data = iio_priv(indio_dev);
+	int i, j = 0;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		int ret = i2c_smbus_read_word_data(data->client,
+			TCS3414_DATA_GREEN + 2*i);
+		if (ret < 0)
+			goto done;
+
+		data->buffer[j++] = ret;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static IIO_CONST_ATTR(scale_available, "1 0.25 0.0625 0.015625");
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4");
+
+static struct attribute *tcs3414_attributes[] = {
+	&iio_const_attr_scale_available.dev_attr.attr,
+	&iio_const_attr_integration_time_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tcs3414_attribute_group = {
+	.attrs = tcs3414_attributes,
+};
+
+static const struct iio_info tcs3414_info = {
+	.read_raw = tcs3414_read_raw,
+	.write_raw = tcs3414_write_raw,
+	.attrs = &tcs3414_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int tcs3414_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tcs3414_data *data = iio_priv(indio_dev);
+
+	data->control |= TCS3414_CONTROL_ADC_EN;
+	return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control);
+}
+
+static int tcs3414_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tcs3414_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = iio_triggered_buffer_predisable(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	data->control &= ~TCS3414_CONTROL_ADC_EN;
+	return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control);
+}
+
+static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
+	.preenable = tcs3414_buffer_preenable,
+	.postenable = &iio_triggered_buffer_postenable,
+	.predisable = tcs3414_buffer_predisable,
+};
+
+static int tcs3414_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct tcs3414_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	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;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &tcs3414_info;
+	indio_dev->name = TCS3414_DRV_NAME;
+	indio_dev->channels = tcs3414_channels;
+	indio_dev->num_channels = ARRAY_SIZE(tcs3414_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3414_ID);
+	if (ret < 0)
+		return ret;
+
+	switch (ret & 0xf0) {
+	case 0x00:
+		dev_info(&client->dev, "TCS3404 found\n");
+		break;
+	case 0x10:
+		dev_info(&client->dev, "TCS3413/14/15/16 found\n");
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	data->control = TCS3414_CONTROL_POWER;
+	ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control);
+	if (ret < 0)
+		return ret;
+
+	data->timing = TCS3414_INTEG_12MS; /* free running */
+	ret = i2c_smbus_write_byte_data(data->client, TCS3414_TIMING,
+		data->timing);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3414_GAIN);
+	if (ret < 0)
+		return ret;
+	data->gain = ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		tcs3414_trigger_handler, &tcs3414_buffer_setup_ops);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int tcs3414_powerdown(struct tcs3414_data *data)
+{
+	return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control & ~(TCS3414_CONTROL_POWER |
+		TCS3414_CONTROL_ADC_EN));
+}
+
+static int tcs3414_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);
+	tcs3414_powerdown(iio_priv(indio_dev));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tcs3414_suspend(struct device *dev)
+{
+	struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return tcs3414_powerdown(data);
+}
+
+static int tcs3414_resume(struct device *dev)
+{
+	struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+		data->control);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume);
+
+static const struct i2c_device_id tcs3414_id[] = {
+	{ "tcs3414", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tcs3414_id);
+
+static struct i2c_driver tcs3414_driver = {
+	.driver = {
+		.name	= TCS3414_DRV_NAME,
+		.pm	= &tcs3414_pm_ops,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tcs3414_probe,
+	.remove		= tcs3414_remove,
+	.id_table	= tcs3414_id,
+};
+module_i2c_driver(tcs3414_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TCS3414 digital color sensors driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/ak09911.c linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/ak09911.c
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/ak09911.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/ak09911.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,326 @@
+/*
+ * AK09911 3-axis compass driver
+ * Copyright (c) 2014, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+#include <linux/iio/iio.h>
+
+#define AK09911_REG_WIA1		0x00
+#define AK09911_REG_WIA2		0x01
+#define AK09911_WIA1_VALUE		0x48
+#define AK09911_WIA2_VALUE		0x05
+
+#define AK09911_REG_ST1			0x10
+#define AK09911_REG_HXL			0x11
+#define AK09911_REG_HXH			0x12
+#define AK09911_REG_HYL			0x13
+#define AK09911_REG_HYH			0x14
+#define AK09911_REG_HZL			0x15
+#define AK09911_REG_HZH			0x16
+
+#define AK09911_REG_ASAX		0x60
+#define AK09911_REG_ASAY		0x61
+#define AK09911_REG_ASAZ		0x62
+
+#define AK09911_REG_CNTL1		0x30
+#define AK09911_REG_CNTL2		0x31
+#define AK09911_REG_CNTL3		0x32
+
+#define AK09911_MODE_SNG_MEASURE	0x01
+#define AK09911_MODE_SELF_TEST		0x10
+#define AK09911_MODE_FUSE_ACCESS	0x1F
+#define AK09911_MODE_POWERDOWN		0x00
+#define AK09911_RESET_DATA		0x01
+
+#define AK09911_REG_CNTL1		0x30
+#define AK09911_REG_CNTL2		0x31
+#define AK09911_REG_CNTL3		0x32
+
+#define AK09911_RAW_TO_GAUSS(asa)	((((asa) + 128) * 6000) / 256)
+
+#define AK09911_MAX_CONVERSION_TIMEOUT_MS	500
+#define AK09911_CONVERSION_DONE_POLL_TIME_MS	10
+
+struct ak09911_data {
+	struct i2c_client	*client;
+	struct mutex		lock;
+	u8			asa[3];
+	long			raw_to_gauss[3];
+};
+
+static const int ak09911_index_to_reg[] = {
+	AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL,
+};
+
+static int ak09911_set_mode(struct i2c_client *client, u8 mode)
+{
+	int ret;
+
+	switch (mode) {
+	case AK09911_MODE_SNG_MEASURE:
+	case AK09911_MODE_SELF_TEST:
+	case AK09911_MODE_FUSE_ACCESS:
+	case AK09911_MODE_POWERDOWN:
+		ret = i2c_smbus_write_byte_data(client,
+						AK09911_REG_CNTL2, mode);
+		if (ret < 0) {
+			dev_err(&client->dev, "set_mode error\n");
+			return ret;
+		}
+		/* After mode change wait atleast 100us */
+		usleep_range(100, 500);
+		break;
+	default:
+		dev_err(&client->dev,
+			"%s: Unknown mode(%d).", __func__, mode);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/* Get Sensitivity Adjustment value */
+static int ak09911_get_asa(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak09911_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS);
+	if (ret < 0)
+		return ret;
+
+	/* Get asa data and store in the device data. */
+	ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX,
+					    3, data->asa);
+	if (ret < 0) {
+		dev_err(&client->dev, "Not able to read asa data\n");
+		return ret;
+	}
+
+	ret = ak09911_set_mode(client,  AK09911_MODE_POWERDOWN);
+	if (ret < 0)
+		return ret;
+
+	data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]);
+	data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]);
+	data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]);
+
+	return 0;
+}
+
+static int ak09911_verify_chip_id(struct i2c_client *client)
+{
+	u8 wia_val[2];
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1,
+					    2, wia_val);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error reading WIA\n");
+		return ret;
+	}
+
+	dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]);
+
+	if (wia_val[0] != AK09911_WIA1_VALUE ||
+		wia_val[1] != AK09911_WIA2_VALUE) {
+		dev_err(&client->dev, "Device ak09911 not found\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int wait_conversion_complete_polled(struct ak09911_data *data)
+{
+	struct i2c_client *client = data->client;
+	u8 read_status;
+	u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS;
+	int ret;
+
+	/* Wait for the conversion to complete. */
+	while (timeout_ms) {
+		msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS);
+		ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1);
+		if (ret < 0) {
+			dev_err(&client->dev, "Error in reading ST1\n");
+			return ret;
+		}
+		read_status = ret & 0x01;
+		if (read_status)
+			break;
+		timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS;
+	}
+	if (!timeout_ms) {
+		dev_err(&client->dev, "Conversion timeout happened\n");
+		return -EIO;
+	}
+
+	return read_status;
+}
+
+static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val)
+{
+	struct ak09911_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE);
+	if (ret < 0)
+		goto fn_exit;
+
+	ret = wait_conversion_complete_polled(data);
+	if (ret < 0)
+		goto fn_exit;
+
+	/* Read data */
+	ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]);
+	if (ret < 0) {
+		dev_err(&client->dev, "Read axis data fails\n");
+		goto fn_exit;
+	}
+
+	mutex_unlock(&data->lock);
+
+	/* Clamp to valid range. */
+	*val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13);
+
+	return IIO_VAL_INT;
+
+fn_exit:
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int ak09911_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2,
+			    long mask)
+{
+	struct ak09911_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return ak09911_read_axis(indio_dev, chan->address, val);
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = data->raw_to_gauss[chan->address];
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+
+	return -EINVAL;
+}
+
+#define AK09911_CHANNEL(axis, index)					\
+	{								\
+		.type = IIO_MAGN,					\
+		.modified = 1,						\
+		.channel2 = IIO_MOD_##axis,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+			     BIT(IIO_CHAN_INFO_SCALE),			\
+		.address = index,					\
+	}
+
+static const struct iio_chan_spec ak09911_channels[] = {
+	AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2),
+};
+
+static const struct iio_info ak09911_info = {
+	.read_raw = &ak09911_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static const struct acpi_device_id ak_acpi_match[] = {
+	{"AK009911", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
+
+static int ak09911_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct ak09911_data *data;
+	const char *name;
+	int ret;
+
+	ret = ak09911_verify_chip_id(client);
+	if (ret) {
+		dev_err(&client->dev, "AK00911 not detected\n");
+		return -ENODEV;
+	}
+
+	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;
+	mutex_init(&data->lock);
+
+	ret = ak09911_get_asa(client);
+	if (ret)
+		return ret;
+
+	if (id)
+		name = id->name;
+	else if (ACPI_HANDLE(&client->dev))
+		name = dev_name(&client->dev);
+	else
+		return -ENODEV;
+
+	dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = ak09911_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ak09911_channels);
+	indio_dev->info = &ak09911_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = name;
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id ak09911_id[] = {
+	{"ak09911", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak09911_id);
+
+static struct i2c_driver ak09911_driver = {
+	.driver = {
+		.name	= "ak09911",
+		.acpi_match_table = ACPI_PTR(ak_acpi_match),
+	},
+	.probe		= ak09911_probe,
+	.id_table	= ak09911_id,
+};
+module_i2c_driver(ak09911_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("AK09911 Compass driver");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/ak8975.c linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/ak8975.c
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/ak8975.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/ak8975.c	2014-09-28 17:29:07.000000000 -0400
@@ -165,7 +165,7 @@ static int ak8975_setup_irq(struct ak897
 	else
 		irq = gpio_to_irq(data->eoc_gpio);
 
-	rc = request_irq(irq, ak8975_irq_handler,
+	rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler,
 			 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 			 dev_name(&client->dev), data);
 	if (rc < 0) {
@@ -513,21 +513,21 @@ static int ak8975_probe(struct i2c_clien
 	/* We may not have a GPIO based IRQ to scan, that is fine, we will
 	   poll if so */
 	if (gpio_is_valid(eoc_gpio)) {
-		err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975");
+		err = devm_gpio_request_one(&client->dev, eoc_gpio,
+							GPIOF_IN, "ak_8975");
 		if (err < 0) {
 			dev_err(&client->dev,
 				"failed to request GPIO %d, error %d\n",
 							eoc_gpio, err);
-			goto exit;
+			return err;
 		}
 	}
 
 	/* Register with IIO */
-	indio_dev = iio_device_alloc(sizeof(*data));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit_gpio;
-	}
+	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);
 
@@ -542,17 +542,16 @@ static int ak8975_probe(struct i2c_clien
 		name = (char *) id->name;
 	} else if (ACPI_HANDLE(&client->dev))
 		name = ak8975_match_acpi_device(&client->dev, &data->chipset);
-	else {
-		err = -ENOSYS;
-		goto exit_free_iio;
-	}
+	else
+		return -ENOSYS;
+
 	dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
 
 	/* Perform some basic start-of-day setup of the device. */
 	err = ak8975_setup(client);
 	if (err < 0) {
 		dev_err(&client->dev, "AK8975 initialization fails\n");
-		goto exit_free_iio;
+		return err;
 	}
 
 	data->client = client;
@@ -564,37 +563,9 @@ static int ak8975_probe(struct i2c_clien
 	indio_dev->info = &ak8975_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->name = name;
-	err = iio_device_register(indio_dev);
+	err = devm_iio_device_register(&client->dev, indio_dev);
 	if (err < 0)
-		goto exit_free_iio;
-
-	return 0;
-
-exit_free_iio:
-	iio_device_free(indio_dev);
-	if (data->eoc_irq)
-		free_irq(data->eoc_irq, data);
-exit_gpio:
-	if (gpio_is_valid(eoc_gpio))
-		gpio_free(eoc_gpio);
-exit:
-	return err;
-}
-
-static int ak8975_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct ak8975_data *data = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-
-	if (data->eoc_irq)
-		free_irq(data->eoc_irq, data);
-
-	if (gpio_is_valid(data->eoc_gpio))
-		gpio_free(data->eoc_gpio);
-
-	iio_device_free(indio_dev);
+		return err;
 
 	return 0;
 }
@@ -621,7 +592,6 @@ static struct i2c_driver ak8975_driver =
 		.acpi_match_table = ACPI_PTR(ak_acpi_match),
 	},
 	.probe		= ak8975_probe,
-	.remove		= ak8975_remove,
 	.id_table	= ak8975_id,
 };
 module_i2c_driver(ak8975_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,10 @@ enum magn_3d_channel {
 	CHANNEL_SCAN_INDEX_X,
 	CHANNEL_SCAN_INDEX_Y,
 	CHANNEL_SCAN_INDEX_Z,
+	CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP,
+	CHANNEL_SCAN_INDEX_NORTH_TRUE_TILT_COMP,
+	CHANNEL_SCAN_INDEX_NORTH_MAGN,
+	CHANNEL_SCAN_INDEX_NORTH_TRUE,
 	MAGN_3D_CHANNEL_MAX,
 };
 
@@ -42,7 +46,12 @@ struct magn_3d_state {
 	struct hid_sensor_hub_callbacks callbacks;
 	struct hid_sensor_common common_attributes;
 	struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX];
-	u32 magn_val[MAGN_3D_CHANNEL_MAX];
+
+	/* dynamically sized array to hold sensor values */
+	u32 *iio_vals;
+	/* 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;
@@ -52,7 +61,11 @@ struct magn_3d_state {
 static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = {
 	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS,
 	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS,
-	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS
+	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS,
+	HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH,
+	HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH,
+	HID_USAGE_SENSOR_ORIENT_MAGN_NORTH,
+	HID_USAGE_SENSOR_ORIENT_TRUE_NORTH,
 };
 
 /* Channel definitions */
@@ -66,7 +79,6 @@ static const struct iio_chan_spec magn_3
 		BIT(IIO_CHAN_INFO_SCALE) |
 		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 		BIT(IIO_CHAN_INFO_HYSTERESIS),
-		.scan_index = CHANNEL_SCAN_INDEX_X,
 	}, {
 		.type = IIO_MAGN,
 		.modified = 1,
@@ -76,7 +88,6 @@ static const struct iio_chan_spec magn_3
 		BIT(IIO_CHAN_INFO_SCALE) |
 		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 		BIT(IIO_CHAN_INFO_HYSTERESIS),
-		.scan_index = CHANNEL_SCAN_INDEX_Y,
 	}, {
 		.type = IIO_MAGN,
 		.modified = 1,
@@ -86,7 +97,42 @@ static const struct iio_chan_spec magn_3
 		BIT(IIO_CHAN_INFO_SCALE) |
 		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 		BIT(IIO_CHAN_INFO_HYSTERESIS),
-		.scan_index = CHANNEL_SCAN_INDEX_Z,
+	}, {
+		.type = IIO_ROT,
+		.modified = 1,
+		.channel2 = IIO_MOD_NORTH_MAGN_TILT_COMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
+	}, {
+		.type = IIO_ROT,
+		.modified = 1,
+		.channel2 = IIO_MOD_NORTH_TRUE_TILT_COMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
+	}, {
+		.type = IIO_ROT,
+		.modified = 1,
+		.channel2 = IIO_MOD_NORTH_MAGN,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
+	}, {
+		.type = IIO_ROT,
+		.modified = 1,
+		.channel2 = IIO_MOD_NORTH_TRUE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 	}
 };
 
@@ -126,8 +172,8 @@ static int magn_3d_read_raw(struct iio_d
 		msleep_interruptible(poll_value * 2);
 
 		report_id =
-			magn_state->magn[chan->scan_index].report_id;
-		address = magn_3d_addresses[chan->scan_index];
+			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,
@@ -218,8 +264,8 @@ static int magn_3d_proc_event(struct hid
 	dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
 	if (atomic_read(&magn_state->common_attributes.data_ready))
 		hid_sensor_push_data(indio_dev,
-				magn_state->magn_val,
-				sizeof(magn_state->magn_val));
+				magn_state->iio_vals,
+				sizeof(magn_state->iio_vals));
 
 	return 0;
 }
@@ -233,52 +279,126 @@ static int magn_3d_capture_sample(struct
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
 	struct magn_3d_state *magn_state = iio_priv(indio_dev);
 	int offset;
-	int ret = -EINVAL;
+	int ret = 0;
+	u32 *iio_val = NULL;
 
 	switch (usage_id) {
 	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS:
 	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS:
 	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS:
-		offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS;
-		magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] =
-						*(u32 *)raw_data;
-		ret = 0;
+		offset = (usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS)
+				+ CHANNEL_SCAN_INDEX_X;
+	break;
+	case HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH:
+	case HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH:
+	case HID_USAGE_SENSOR_ORIENT_MAGN_NORTH:
+	case HID_USAGE_SENSOR_ORIENT_TRUE_NORTH:
+		offset = (usage_id - HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH)
+				+ CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP;
 	break;
 	default:
-		break;
+		return -EINVAL;
 	}
 
+	iio_val = magn_state->magn_val_addr[offset];
+
+	if (iio_val != NULL)
+		*iio_val = *((u32 *)raw_data);
+	else
+		ret = -EINVAL;
+
 	return ret;
 }
 
 /* Parse report which is specific to an usage id*/
 static int magn_3d_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
-				struct iio_chan_spec *channels,
+				struct iio_chan_spec **channels,
+				int *chan_count,
 				unsigned usage_id,
 				struct magn_3d_state *st)
 {
-	int ret;
 	int i;
+	int attr_count = 0;
+	struct iio_chan_spec *_channels;
 
-	for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
-		ret = sensor_hub_input_get_attribute_info(hsdev,
-				HID_INPUT_REPORT,
-				usage_id,
-				HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i,
-				&st->magn[CHANNEL_SCAN_INDEX_X + i]);
-		if (ret < 0)
-			break;
-		magn_3d_adjust_channel_bit_mask(channels,
-				CHANNEL_SCAN_INDEX_X + i,
-				st->magn[CHANNEL_SCAN_INDEX_X + i].size);
+	/* Scan for each usage attribute supported */
+	for (i = 0; i < MAGN_3D_CHANNEL_MAX; i++) {
+		int status;
+		u32 address = magn_3d_addresses[i];
+
+		/* Check if usage attribute exists in the sensor hub device */
+		status = sensor_hub_input_get_attribute_info(hsdev,
+			HID_INPUT_REPORT,
+			usage_id,
+			address,
+			&(st->magn[i]));
+		if (!status)
+			attr_count++;
 	}
-	dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n",
+
+	if (attr_count <= 0) {
+		dev_err(&pdev->dev,
+			"failed to find any supported usage attributes in report\n");
+		return  -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "magn_3d Found %d usage attributes\n",
+			attr_count);
+	dev_dbg(&pdev->dev, "magn_3d X: %x:%x Y: %x:%x Z: %x:%x\n",
 			st->magn[0].index,
 			st->magn[0].report_id,
 			st->magn[1].index, st->magn[1].report_id,
 			st->magn[2].index, st->magn[2].report_id);
 
+	/* Setup IIO channel array */
+	_channels = devm_kcalloc(&pdev->dev, attr_count,
+				sizeof(struct iio_chan_spec),
+				GFP_KERNEL);
+	if (!_channels) {
+		dev_err(&pdev->dev,
+			"failed to allocate space for iio channels\n");
+		return -ENOMEM;
+	}
+
+	st->iio_vals = devm_kcalloc(&pdev->dev, attr_count,
+				sizeof(u32),
+				GFP_KERNEL);
+	if (!st->iio_vals) {
+		dev_err(&pdev->dev,
+			"failed to allocate space for iio values array\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, *chan_count = 0;
+	i < MAGN_3D_CHANNEL_MAX && *chan_count < attr_count;
+	i++){
+		if (st->magn[i].index >= 0) {
+			/* Setup IIO channel struct */
+			(_channels[*chan_count]) = magn_3d_channels[i];
+			(_channels[*chan_count]).scan_index = *chan_count;
+			(_channels[*chan_count]).address = i;
+
+			/* Set magn_val_addr to iio value address */
+			st->magn_val_addr[i] = &(st->iio_vals[*chan_count]);
+			magn_3d_adjust_channel_bit_mask(_channels,
+							*chan_count,
+							st->magn[i].size);
+			(*chan_count)++;
+		}
+	}
+
+	if (*chan_count <= 0) {
+		dev_err(&pdev->dev,
+			"failed to find any magnetic channels setup\n");
+		return -EINVAL;
+	}
+
+	*channels = _channels;
+
+	dev_dbg(&pdev->dev, "magn_3d Setup %d IIO channels\n",
+			*chan_count);
+
 	st->scale_precision = hid_sensor_format_scale(
 				HID_USAGE_SENSOR_COMPASS_3D,
 				&st->magn[CHANNEL_SCAN_INDEX_X],
@@ -296,7 +416,7 @@ static int magn_3d_parse_report(struct p
 			st->common_attributes.sensitivity.report_id);
 	}
 
-	return ret;
+	return 0;
 }
 
 /* Function to initialize the processing for usage id */
@@ -308,6 +428,7 @@ static int hid_magn_3d_probe(struct plat
 	struct magn_3d_state *magn_state;
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 	struct iio_chan_spec *channels;
+	int chan_count = 0;
 
 	indio_dev = devm_iio_device_alloc(&pdev->dev,
 					  sizeof(struct magn_3d_state));
@@ -328,22 +449,16 @@ static int hid_magn_3d_probe(struct plat
 		return ret;
 	}
 
-	channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
-			   GFP_KERNEL);
-	if (!channels) {
-		dev_err(&pdev->dev, "failed to duplicate channels\n");
-		return -ENOMEM;
-	}
-
-	ret = magn_3d_parse_report(pdev, hsdev, channels,
+	ret = magn_3d_parse_report(pdev, hsdev,
+				&channels, &chan_count,
 				HID_USAGE_SENSOR_COMPASS_3D, magn_state);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to setup attributes\n");
-		goto error_free_dev_mem;
+		dev_err(&pdev->dev, "failed to parse report\n");
+		return ret;
 	}
 
 	indio_dev->channels = channels;
-	indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels);
+	indio_dev->num_channels = chan_count;
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->info = &magn_3d_info;
 	indio_dev->name = name;
@@ -353,7 +468,7 @@ static int hid_magn_3d_probe(struct plat
 		NULL, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
-		goto error_free_dev_mem;
+		return ret;
 	}
 	atomic_set(&magn_state->common_attributes.data_ready, 0);
 	ret = hid_sensor_setup_trigger(indio_dev, name,
@@ -387,8 +502,6 @@ error_remove_trigger:
 	hid_sensor_remove_trigger(&magn_state->common_attributes);
 error_unreg_buffer_funcs:
 	iio_triggered_buffer_cleanup(indio_dev);
-error_free_dev_mem:
-	kfree(indio_dev->channels);
 	return ret;
 }
 
@@ -403,7 +516,6 @@ static int hid_magn_3d_remove(struct pla
 	iio_device_unregister(indio_dev);
 	hid_sensor_remove_trigger(&magn_state->common_attributes);
 	iio_triggered_buffer_cleanup(indio_dev);
-	kfree(indio_dev->channels);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,16 @@ config AK8975
 	  To compile this driver as a module, choose M here: the module
 	  will be called ak8975.
 
+config AK09911
+	tristate "Asahi Kasei AK09911 3-axis Compass"
+	depends on I2C
+	help
+	  Say yes here to build support for Asahi Kasei AK09911 3-Axis
+	  Magnetometer.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ak09911.
+
 config MAG3110
 	tristate "Freescale MAG3110 3-Axis Magnetometer"
 	depends on I2C
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/Makefile
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AK09911)	+= ak09911.o
 obj-$(CONFIG_AK8975)	+= ak8975.o
 obj-$(CONFIG_MAG3110)	+= mag3110.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/st_magn_core.c linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/st_magn_core.c
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/st_magn_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/st_magn_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,8 @@
 #define ST_MAGN_FS_AVL_5600MG			5600
 #define ST_MAGN_FS_AVL_8000MG			8000
 #define ST_MAGN_FS_AVL_8100MG			8100
-#define ST_MAGN_FS_AVL_10000MG			10000
+#define ST_MAGN_FS_AVL_12000MG			12000
+#define ST_MAGN_FS_AVL_16000MG			16000
 
 /* CUSTOM VALUES FOR SENSOR 1 */
 #define ST_MAGN_1_WAI_EXP			0x3c
@@ -69,20 +70,20 @@
 #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		1100
-#define ST_MAGN_1_FS_AVL_1900_GAIN_XY		855
-#define ST_MAGN_1_FS_AVL_2500_GAIN_XY		670
-#define ST_MAGN_1_FS_AVL_4000_GAIN_XY		450
-#define ST_MAGN_1_FS_AVL_4700_GAIN_XY		400
-#define ST_MAGN_1_FS_AVL_5600_GAIN_XY		330
-#define ST_MAGN_1_FS_AVL_8100_GAIN_XY		230
-#define ST_MAGN_1_FS_AVL_1300_GAIN_Z		980
-#define ST_MAGN_1_FS_AVL_1900_GAIN_Z		760
-#define ST_MAGN_1_FS_AVL_2500_GAIN_Z		600
-#define ST_MAGN_1_FS_AVL_4000_GAIN_Z		400
-#define ST_MAGN_1_FS_AVL_4700_GAIN_Z		355
-#define ST_MAGN_1_FS_AVL_5600_GAIN_Z		295
-#define ST_MAGN_1_FS_AVL_8100_GAIN_Z		205
+#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 */
@@ -105,10 +106,12 @@
 #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_10000_VAL		0x02
-#define ST_MAGN_2_FS_AVL_4000_GAIN		430
-#define ST_MAGN_2_FS_AVL_8000_GAIN		230
-#define ST_MAGN_2_FS_AVL_10000_GAIN		230
+#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
 #define ST_MAGN_2_OUT_X_L_ADDR			0x28
 #define ST_MAGN_2_OUT_Y_L_ADDR			0x2a
@@ -266,9 +269,14 @@ static const struct st_sensors st_magn_s
 					.gain = ST_MAGN_2_FS_AVL_8000_GAIN,
 				},
 				[2] = {
-					.num = ST_MAGN_FS_AVL_10000MG,
-					.value = ST_MAGN_2_FS_AVL_10000_VAL,
-					.gain = ST_MAGN_2_FS_AVL_10000_GAIN,
+					.num = ST_MAGN_FS_AVL_12000MG,
+					.value = ST_MAGN_2_FS_AVL_12000_VAL,
+					.gain = ST_MAGN_2_FS_AVL_12000_GAIN,
+				},
+				[3] = {
+					.num = ST_MAGN_FS_AVL_16000MG,
+					.value = ST_MAGN_2_FS_AVL_16000_VAL,
+					.gain = ST_MAGN_2_FS_AVL_16000_GAIN,
 				},
 			},
 		},
@@ -299,6 +307,9 @@ static int st_magn_read_raw(struct iio_d
 		else
 			*val2 = mdata->current_fullscale->gain;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = mdata->odr;
+		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
 	}
@@ -316,6 +327,13 @@ static int st_magn_write_raw(struct iio_
 	case IIO_CHAN_INFO_SCALE:
 		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&indio_dev->mlock);
+		err = st_sensors_set_odr(indio_dev, val);
+		mutex_unlock(&indio_dev->mlock);
+		return err;
 	default:
 		err = -EINVAL;
 	}
@@ -323,14 +341,12 @@ static int st_magn_write_raw(struct iio_
 	return err;
 }
 
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
 
 static struct attribute *st_magn_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/magnetometer/st_magn_i2c.c linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/st_magn_i2c.c
--- linux-libre-3.16-gnu/drivers/iio/magnetometer/st_magn_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/magnetometer/st_magn_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,27 @@
 #include <linux/iio/common/st_sensors_i2c.h>
 #include "st_magn.h"
 
+#ifdef CONFIG_OF
+static const struct of_device_id st_magn_of_match[] = {
+	{
+		.compatible = "st,lsm303dlhc-magn",
+		.data = LSM303DLHC_MAGN_DEV_NAME,
+	},
+	{
+		.compatible = "st,lsm303dlm-magn",
+		.data = LSM303DLM_MAGN_DEV_NAME,
+	},
+	{
+		.compatible = "st,lis3mdl-magn",
+		.data = LIS3MDL_MAGN_DEV_NAME,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_magn_of_match);
+#else
+#define st_magn_of_match NULL
+#endif
+
 static int st_magn_i2c_probe(struct i2c_client *client,
 						const struct i2c_device_id *id)
 {
@@ -31,6 +52,7 @@ static int st_magn_i2c_probe(struct i2c_
 
 	mdata = iio_priv(indio_dev);
 	mdata->dev = &client->dev;
+	st_sensors_of_i2c_probe(client, st_magn_of_match);
 
 	st_sensors_i2c_configure(indio_dev, client, mdata);
 
@@ -61,6 +83,7 @@ static struct i2c_driver st_magn_driver
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "st-magn-i2c",
+		.of_match_table = of_match_ptr(st_magn_of_match),
 	},
 	.probe = st_magn_i2c_probe,
 	.remove = st_magn_i2c_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/pressure/Kconfig linux-libre-3.17-rc7-gnu/drivers/iio/pressure/Kconfig
--- linux-libre-3.16-gnu/drivers/iio/pressure/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/pressure/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -70,4 +70,14 @@ config IIO_ST_PRESS_SPI
 	depends on IIO_ST_PRESS
 	depends on IIO_ST_SENSORS_SPI
 
+config T5403
+	tristate "EPCOS T5403 digital barometric pressure sensor driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the EPCOS T5403 pressure sensor
+	  connected via I2C.
+
+          To compile this driver as a module, choose M here: the module
+          will be called t5403.
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/pressure/Makefile linux-libre-3.17-rc7-gnu/drivers/iio/pressure/Makefile
--- linux-libre-3.16-gnu/drivers/iio/pressure/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/pressure/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@ obj-$(CONFIG_MPL3115) += mpl3115.o
 obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
 st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
+obj-$(CONFIG_T5403) += t5403.o
 
 obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
 obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/pressure/st_pressure_core.c linux-libre-3.17-rc7-gnu/drivers/iio/pressure/st_pressure_core.c
--- linux-libre-3.16-gnu/drivers/iio/pressure/st_pressure_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/pressure/st_pressure_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -307,6 +307,27 @@ static const struct st_sensors st_press_
 	},
 };
 
+static int st_press_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *ch,
+			      int val,
+			      int val2,
+			      long mask)
+{
+	int err;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&indio_dev->mlock);
+		err = st_sensors_set_odr(indio_dev, val);
+		mutex_unlock(&indio_dev->mlock);
+		return err;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int st_press_read_raw(struct iio_dev *indio_dev,
 			struct iio_chan_spec const *ch, int *val,
 							int *val2, long mask)
@@ -349,6 +370,9 @@ static int st_press_read_raw(struct iio_
 		}
 
 		return IIO_VAL_FRACTIONAL;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = pdata->odr;
+		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
 	}
@@ -357,12 +381,10 @@ read_error:
 	return err;
 }
 
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 
 static struct attribute *st_press_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	NULL,
 };
 
@@ -374,6 +396,7 @@ static const struct iio_info press_info
 	.driver_module = THIS_MODULE,
 	.attrs = &st_press_attribute_group,
 	.read_raw = &st_press_read_raw,
+	.write_raw = &st_press_write_raw,
 };
 
 #ifdef CONFIG_IIO_TRIGGER
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/pressure/st_pressure_i2c.c linux-libre-3.17-rc7-gnu/drivers/iio/pressure/st_pressure_i2c.c
--- linux-libre-3.16-gnu/drivers/iio/pressure/st_pressure_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/pressure/st_pressure_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,27 @@
 #include <linux/iio/common/st_sensors_i2c.h>
 #include "st_pressure.h"
 
+#ifdef CONFIG_OF
+static const struct of_device_id st_press_of_match[] = {
+	{
+		.compatible = "st,lps001wp-press",
+		.data = LPS001WP_PRESS_DEV_NAME,
+	},
+	{
+		.compatible = "st,lps25h-press",
+		.data = LPS25H_PRESS_DEV_NAME,
+	},
+	{
+		.compatible = "st,lps331ap-press",
+		.data = LPS331AP_PRESS_DEV_NAME,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_press_of_match);
+#else
+#define st_press_of_match NULL
+#endif
+
 static int st_press_i2c_probe(struct i2c_client *client,
 						const struct i2c_device_id *id)
 {
@@ -31,6 +52,7 @@ static int st_press_i2c_probe(struct i2c
 
 	pdata = iio_priv(indio_dev);
 	pdata->dev = &client->dev;
+	st_sensors_of_i2c_probe(client, st_press_of_match);
 
 	st_sensors_i2c_configure(indio_dev, client, pdata);
 
@@ -60,6 +82,7 @@ static struct i2c_driver st_press_driver
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "st-press-i2c",
+		.of_match_table = of_match_ptr(st_press_of_match),
 	},
 	.probe = st_press_i2c_probe,
 	.remove = st_press_i2c_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/pressure/t5403.c linux-libre-3.17-rc7-gnu/drivers/iio/pressure/t5403.c
--- linux-libre-3.16-gnu/drivers/iio/pressure/t5403.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iio/pressure/t5403.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,275 @@
+/*
+ * t5403.c - Support for EPCOS T5403 pressure/temperature sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x77)
+ *
+ * TODO: end-of-conversion irq
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+
+#define T5403_DATA 0xf5 /* data, LSB first, 16 bit */
+#define T5403_CALIB_DATA 0x8e /* 10 calibration coeff., LSB first, 16 bit */
+#define T5403_SLAVE_ADDR 0x88 /* I2C slave address, 0x77 */
+#define T5403_COMMAND 0xf1
+
+/* command bits */
+#define T5403_MODE_SHIFT 3 /* conversion time: 2, 8, 16, 66 ms */
+#define T5403_PT BIT(1) /* 0 .. pressure, 1 .. temperature measurement */
+#define T5403_SCO BIT(0) /* start conversion */
+
+#define T5403_MODE_LOW 0
+#define T5403_MODE_STANDARD 1
+#define T5403_MODE_HIGH 2
+#define T5403_MODE_ULTRA_HIGH 3
+
+#define T5403_I2C_MASK (~BIT(7))
+#define T5403_I2C_ADDR 0x77
+
+static const int t5403_pressure_conv_ms[] = {2, 8, 16, 66};
+
+struct t5403_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	int mode;
+	__le16 c[10];
+};
+
+#define T5403_C_U16(i) le16_to_cpu(data->c[(i) - 1])
+#define T5403_C(i) sign_extend32(T5403_C_U16(i), 15)
+
+static int t5403_read(struct t5403_data *data, bool pressure)
+{
+	int wait_time = 3;  /* wakeup time in ms */
+
+	int ret = i2c_smbus_write_byte_data(data->client, T5403_COMMAND,
+		(pressure ? (data->mode << T5403_MODE_SHIFT) : T5403_PT) |
+		T5403_SCO);
+	if (ret < 0)
+		return ret;
+
+	wait_time += pressure ? t5403_pressure_conv_ms[data->mode] : 2;
+
+	msleep(wait_time);
+
+	return i2c_smbus_read_word_data(data->client, T5403_DATA);
+}
+
+static int t5403_comp_pressure(struct t5403_data *data, int *val, int *val2)
+{
+	int ret;
+	s16 t_r;
+	u16 p_r;
+	s32 S, O, X;
+
+	mutex_lock(&data->lock);
+
+	ret = t5403_read(data, false);
+	if (ret < 0)
+		goto done;
+	t_r = ret;
+
+	ret = t5403_read(data, true);
+	if (ret < 0)
+		goto done;
+	p_r = ret;
+
+	/* see EPCOS application note */
+	S = T5403_C_U16(3) + (s32) T5403_C_U16(4) * t_r / 0x20000 +
+		T5403_C(5) * t_r / 0x8000 * t_r / 0x80000 +
+		T5403_C(9) * t_r / 0x8000 * t_r / 0x8000 * t_r / 0x10000;
+
+	O = T5403_C(6) * 0x4000 + T5403_C(7) * t_r / 8 +
+		T5403_C(8) * t_r / 0x8000 * t_r / 16 +
+		T5403_C(9) * t_r / 0x8000 * t_r / 0x10000 * t_r;
+
+	X = (S * p_r + O) / 0x4000;
+
+	X += ((X - 75000) * (X - 75000) / 0x10000 - 9537) *
+	    T5403_C(10) / 0x10000;
+
+	*val = X / 1000;
+	*val2 = (X % 1000) * 1000;
+
+done:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static int t5403_comp_temp(struct t5403_data *data, int *val)
+{
+	int ret;
+	s16 t_r;
+
+	mutex_lock(&data->lock);
+	ret = t5403_read(data, false);
+	if (ret < 0)
+		goto done;
+	t_r = ret;
+
+	/* see EPCOS application note */
+	*val = ((s32) T5403_C_U16(1) * t_r / 0x100 +
+		(s32) T5403_C_U16(2) * 0x40) * 1000 / 0x10000;
+
+done:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static int t5403_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct t5403_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_PROCESSED:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			ret = t5403_comp_pressure(data, val, val2);
+			if (ret < 0)
+				return ret;
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			ret = t5403_comp_temp(data, val);
+			if (ret < 0)
+				return ret;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+	    }
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		*val2 = t5403_pressure_conv_ms[data->mode] * 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int t5403_write_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int val, int val2, long mask)
+{
+	struct t5403_data *data = iio_priv(indio_dev);
+	int i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(t5403_pressure_conv_ms); i++)
+			if (val2 == t5403_pressure_conv_ms[i] * 1000) {
+				mutex_lock(&data->lock);
+				data->mode = i;
+				mutex_unlock(&data->lock);
+				return 0;
+			}
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_chan_spec t5403_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+		    BIT(IIO_CHAN_INFO_INT_TIME),
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+	},
+};
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.002 0.008 0.016 0.066");
+
+static struct attribute *t5403_attributes[] = {
+	&iio_const_attr_integration_time_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group t5403_attribute_group = {
+	.attrs = t5403_attributes,
+};
+
+static const struct iio_info t5403_info = {
+	.read_raw = &t5403_read_raw,
+	.write_raw = &t5403_write_raw,
+	.attrs = &t5403_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int t5403_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct t5403_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_I2C_BLOCK))
+		return -ENODEV;
+
+	ret = i2c_smbus_read_byte_data(client, T5403_SLAVE_ADDR);
+	if (ret < 0)
+		return ret;
+	if ((ret & T5403_I2C_MASK) != T5403_I2C_ADDR)
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+
+	i2c_set_clientdata(client, indio_dev);
+	indio_dev->info = &t5403_info;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = t5403_channels;
+	indio_dev->num_channels = ARRAY_SIZE(t5403_channels);
+
+	data->mode = T5403_MODE_STANDARD;
+
+	ret = i2c_smbus_read_i2c_block_data(data->client, T5403_CALIB_DATA,
+	    sizeof(data->c), (u8 *) data->c);
+	if (ret < 0)
+		return ret;
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id t5403_id[] = {
+	{ "t5403", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, t5403_id);
+
+static struct i2c_driver t5403_driver = {
+	.driver = {
+		.name	= "t5403",
+	},
+	.probe = t5403_probe,
+	.id_table = t5403_id,
+};
+module_i2c_driver(t5403_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("EPCOS T5403 pressure/temperature sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/proximity/as3935.c linux-libre-3.17-rc7-gnu/drivers/iio/proximity/as3935.c
--- linux-libre-3.16-gnu/drivers/iio/proximity/as3935.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/proximity/as3935.c	2014-09-28 17:29:07.000000000 -0400
@@ -232,7 +232,7 @@ static void as3935_event_work(struct wor
 
 	switch (val) {
 	case AS3935_EVENT_INT:
-		iio_trigger_poll(st->trig, iio_get_time_ns());
+		iio_trigger_poll(st->trig);
 		break;
 	case AS3935_NOISE_INT:
 		dev_warn(&st->spi->dev, "noise level is too high");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/trigger/iio-trig-interrupt.c linux-libre-3.17-rc7-gnu/drivers/iio/trigger/iio-trig-interrupt.c
--- linux-libre-3.16-gnu/drivers/iio/trigger/iio-trig-interrupt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/trigger/iio-trig-interrupt.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,8 +24,7 @@ struct iio_interrupt_trigger_info {
 
 static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private)
 {
-	/* Timestamp not currently provided */
-	iio_trigger_poll(private, 0);
+	iio_trigger_poll(private);
 	return IRQ_HANDLED;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iio/trigger/iio-trig-sysfs.c linux-libre-3.17-rc7-gnu/drivers/iio/trigger/iio-trig-sysfs.c
--- linux-libre-3.16-gnu/drivers/iio/trigger/iio-trig-sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iio/trigger/iio-trig-sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -96,7 +96,7 @@ static void iio_sysfs_trigger_work(struc
 	struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig,
 							work);
 
-	iio_trigger_poll(trig->trig, 0);
+	iio_trigger_poll(trig->trig);
 }
 
 static ssize_t iio_sysfs_trigger_poll(struct device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/agent.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/agent.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/agent.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/agent.c	2014-09-28 17:29:07.000000000 -0400
@@ -94,14 +94,14 @@ void agent_send_response(struct ib_mad *
 		port_priv = ib_get_agent_port(device, port_num);
 
 	if (!port_priv) {
-		printk(KERN_ERR SPFX "Unable to find port agent\n");
+		dev_err(&device->dev, "Unable to find port agent\n");
 		return;
 	}
 
 	agent = port_priv->agent[qpn];
 	ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
 	if (IS_ERR(ah)) {
-		printk(KERN_ERR SPFX "ib_create_ah_from_wc error %ld\n",
+		dev_err(&device->dev, "ib_create_ah_from_wc error %ld\n",
 			PTR_ERR(ah));
 		return;
 	}
@@ -110,7 +110,7 @@ void agent_send_response(struct ib_mad *
 				      IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
 				      GFP_KERNEL);
 	if (IS_ERR(send_buf)) {
-		printk(KERN_ERR SPFX "ib_create_send_mad error\n");
+		dev_err(&device->dev, "ib_create_send_mad error\n");
 		goto err1;
 	}
 
@@ -125,7 +125,7 @@ void agent_send_response(struct ib_mad *
 	}
 
 	if (ib_post_send_mad(send_buf, NULL)) {
-		printk(KERN_ERR SPFX "ib_post_send_mad error\n");
+		dev_err(&device->dev, "ib_post_send_mad error\n");
 		goto err2;
 	}
 	return;
@@ -151,7 +151,7 @@ int ib_agent_port_open(struct ib_device
 	/* Create new device info */
 	port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
 	if (!port_priv) {
-		printk(KERN_ERR SPFX "No memory for ib_agent_port_private\n");
+		dev_err(&device->dev, "No memory for ib_agent_port_private\n");
 		ret = -ENOMEM;
 		goto error1;
 	}
@@ -161,7 +161,7 @@ int ib_agent_port_open(struct ib_device
 		port_priv->agent[0] = ib_register_mad_agent(device, port_num,
 							    IB_QPT_SMI, NULL, 0,
 							    &agent_send_handler,
-							    NULL, NULL);
+							    NULL, NULL, 0);
 		if (IS_ERR(port_priv->agent[0])) {
 			ret = PTR_ERR(port_priv->agent[0]);
 			goto error2;
@@ -172,7 +172,7 @@ int ib_agent_port_open(struct ib_device
 	port_priv->agent[1] = ib_register_mad_agent(device, port_num,
 						    IB_QPT_GSI, NULL, 0,
 						    &agent_send_handler,
-						    NULL, NULL);
+						    NULL, NULL, 0);
 	if (IS_ERR(port_priv->agent[1])) {
 		ret = PTR_ERR(port_priv->agent[1]);
 		goto error3;
@@ -202,7 +202,7 @@ int ib_agent_port_close(struct ib_device
 	port_priv = __ib_get_agent_port(device, port_num);
 	if (port_priv == NULL) {
 		spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
-		printk(KERN_ERR SPFX "Port %d not found\n", port_num);
+		dev_err(&device->dev, "Port %d not found\n", port_num);
 		return -ENODEV;
 	}
 	list_del(&port_priv->port_list);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/cm.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/cm.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/cm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/cm.c	2014-09-28 17:29:07.000000000 -0400
@@ -3753,7 +3753,7 @@ static void cm_add_one(struct ib_device
 	struct cm_port *port;
 	struct ib_mad_reg_req reg_req = {
 		.mgmt_class = IB_MGMT_CLASS_CM,
-		.mgmt_class_version = IB_CM_CLASS_VERSION
+		.mgmt_class_version = IB_CM_CLASS_VERSION,
 	};
 	struct ib_port_modify port_modify = {
 		.set_port_cap_mask = IB_PORT_CM_SUP
@@ -3801,7 +3801,8 @@ static void cm_add_one(struct ib_device
 							0,
 							cm_send_handler,
 							cm_recv_handler,
-							port);
+							port,
+							0);
 		if (IS_ERR(port->mad_agent))
 			goto error2;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/iwcm.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/iwcm.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/iwcm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/iwcm.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,7 @@
 #include <linux/completion.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/sysctl.h>
 
 #include <rdma/iw_cm.h>
 #include <rdma/ib_addr.h>
@@ -65,6 +66,20 @@ struct iwcm_work {
 	struct list_head free_list;
 };
 
+static unsigned int default_backlog = 256;
+
+static struct ctl_table_header *iwcm_ctl_table_hdr;
+static struct ctl_table iwcm_ctl_table[] = {
+	{
+		.procname	= "default_backlog",
+		.data		= &default_backlog,
+		.maxlen		= sizeof(default_backlog),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{ }
+};
+
 /*
  * The following services provide a mechanism for pre-allocating iwcm_work
  * elements.  The design pre-allocates them  based on the cm_id type:
@@ -425,6 +440,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id,
 
 	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
 
+	if (!backlog)
+		backlog = default_backlog;
+
 	ret = alloc_work_entries(cm_id_priv, backlog);
 	if (ret)
 		return ret;
@@ -1030,11 +1048,20 @@ static int __init iw_cm_init(void)
 	if (!iwcm_wq)
 		return -ENOMEM;
 
+	iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm",
+						 iwcm_ctl_table);
+	if (!iwcm_ctl_table_hdr) {
+		pr_err("iw_cm: couldn't register sysctl paths\n");
+		destroy_workqueue(iwcm_wq);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
 static void __exit iw_cm_cleanup(void)
 {
+	unregister_net_sysctl_table(iwcm_ctl_table_hdr);
 	destroy_workqueue(iwcm_wq);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,9 @@
  * SOFTWARE.
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -195,7 +198,8 @@ struct ib_mad_agent *ib_register_mad_age
 					   u8 rmpp_version,
 					   ib_mad_send_handler send_handler,
 					   ib_mad_recv_handler recv_handler,
-					   void *context)
+					   void *context,
+					   u32 registration_flags)
 {
 	struct ib_mad_port_private *port_priv;
 	struct ib_mad_agent *ret = ERR_PTR(-EINVAL);
@@ -211,68 +215,109 @@ struct ib_mad_agent *ib_register_mad_age
 
 	/* Validate parameters */
 	qpn = get_spl_qp_index(qp_type);
-	if (qpn == -1)
+	if (qpn == -1) {
+		dev_notice(&device->dev,
+			   "ib_register_mad_agent: invalid QP Type %d\n",
+			   qp_type);
 		goto error1;
+	}
 
-	if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION)
+	if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION) {
+		dev_notice(&device->dev,
+			   "ib_register_mad_agent: invalid RMPP Version %u\n",
+			   rmpp_version);
 		goto error1;
+	}
 
 	/* Validate MAD registration request if supplied */
 	if (mad_reg_req) {
-		if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION)
+		if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION) {
+			dev_notice(&device->dev,
+				   "ib_register_mad_agent: invalid Class Version %u\n",
+				   mad_reg_req->mgmt_class_version);
 			goto error1;
-		if (!recv_handler)
+		}
+		if (!recv_handler) {
+			dev_notice(&device->dev,
+				   "ib_register_mad_agent: no recv_handler\n");
 			goto error1;
+		}
 		if (mad_reg_req->mgmt_class >= MAX_MGMT_CLASS) {
 			/*
 			 * IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE is the only
 			 * one in this range currently allowed
 			 */
 			if (mad_reg_req->mgmt_class !=
-			    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+			    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+				dev_notice(&device->dev,
+					   "ib_register_mad_agent: Invalid Mgmt Class 0x%x\n",
+					   mad_reg_req->mgmt_class);
 				goto error1;
+			}
 		} else if (mad_reg_req->mgmt_class == 0) {
 			/*
 			 * Class 0 is reserved in IBA and is used for
 			 * aliasing of IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
 			 */
+			dev_notice(&device->dev,
+				   "ib_register_mad_agent: Invalid Mgmt Class 0\n");
 			goto error1;
 		} else if (is_vendor_class(mad_reg_req->mgmt_class)) {
 			/*
 			 * If class is in "new" vendor range,
 			 * ensure supplied OUI is not zero
 			 */
-			if (!is_vendor_oui(mad_reg_req->oui))
+			if (!is_vendor_oui(mad_reg_req->oui)) {
+				dev_notice(&device->dev,
+					   "ib_register_mad_agent: No OUI specified for class 0x%x\n",
+					   mad_reg_req->mgmt_class);
 				goto error1;
+			}
 		}
 		/* Make sure class supplied is consistent with RMPP */
 		if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
-			if (rmpp_version)
+			if (rmpp_version) {
+				dev_notice(&device->dev,
+					   "ib_register_mad_agent: RMPP version for non-RMPP class 0x%x\n",
+					   mad_reg_req->mgmt_class);
 				goto error1;
+			}
 		}
+
 		/* Make sure class supplied is consistent with QP type */
 		if (qp_type == IB_QPT_SMI) {
 			if ((mad_reg_req->mgmt_class !=
 					IB_MGMT_CLASS_SUBN_LID_ROUTED) &&
 			    (mad_reg_req->mgmt_class !=
-					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))
+					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) {
+				dev_notice(&device->dev,
+					   "ib_register_mad_agent: Invalid SM QP type: class 0x%x\n",
+					   mad_reg_req->mgmt_class);
 				goto error1;
+			}
 		} else {
 			if ((mad_reg_req->mgmt_class ==
 					IB_MGMT_CLASS_SUBN_LID_ROUTED) ||
 			    (mad_reg_req->mgmt_class ==
-					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))
+					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) {
+				dev_notice(&device->dev,
+					   "ib_register_mad_agent: Invalid GS QP type: class 0x%x\n",
+					   mad_reg_req->mgmt_class);
 				goto error1;
+			}
 		}
 	} else {
 		/* No registration request supplied */
 		if (!send_handler)
 			goto error1;
+		if (registration_flags & IB_MAD_USER_RMPP)
+			goto error1;
 	}
 
 	/* Validate device and port */
 	port_priv = ib_get_mad_port(device, port_num);
 	if (!port_priv) {
+		dev_notice(&device->dev, "ib_register_mad_agent: Invalid port\n");
 		ret = ERR_PTR(-ENODEV);
 		goto error1;
 	}
@@ -280,6 +325,8 @@ struct ib_mad_agent *ib_register_mad_age
 	/* Verify the QP requested is supported.  For example, Ethernet devices
 	 * will not have QP0 */
 	if (!port_priv->qp_info[qpn].qp) {
+		dev_notice(&device->dev,
+			   "ib_register_mad_agent: QP %d not supported\n", qpn);
 		ret = ERR_PTR(-EPROTONOSUPPORT);
 		goto error1;
 	}
@@ -316,6 +363,7 @@ struct ib_mad_agent *ib_register_mad_age
 	mad_agent_priv->agent.context = context;
 	mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp;
 	mad_agent_priv->agent.port_num = port_num;
+	mad_agent_priv->agent.flags = registration_flags;
 	spin_lock_init(&mad_agent_priv->lock);
 	INIT_LIST_HEAD(&mad_agent_priv->send_list);
 	INIT_LIST_HEAD(&mad_agent_priv->wait_list);
@@ -706,7 +754,7 @@ static int handle_outgoing_dr_smp(struct
 	     smi_handle_dr_smp_send(smp, device->node_type, port_num) ==
 	     IB_SMI_DISCARD) {
 		ret = -EINVAL;
-		printk(KERN_ERR PFX "Invalid directed route\n");
+		dev_err(&device->dev, "Invalid directed route\n");
 		goto out;
 	}
 
@@ -718,7 +766,7 @@ static int handle_outgoing_dr_smp(struct
 	local = kmalloc(sizeof *local, GFP_ATOMIC);
 	if (!local) {
 		ret = -ENOMEM;
-		printk(KERN_ERR PFX "No memory for ib_mad_local_private\n");
+		dev_err(&device->dev, "No memory for ib_mad_local_private\n");
 		goto out;
 	}
 	local->mad_priv = NULL;
@@ -726,7 +774,7 @@ static int handle_outgoing_dr_smp(struct
 	mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_ATOMIC);
 	if (!mad_priv) {
 		ret = -ENOMEM;
-		printk(KERN_ERR PFX "No memory for local response MAD\n");
+		dev_err(&device->dev, "No memory for local response MAD\n");
 		kfree(local);
 		goto out;
 	}
@@ -837,9 +885,9 @@ 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) {
-			printk(KERN_ERR "alloc_send_rmpp_segs: RMPP mem "
-			       "alloc failed for len %zd, gfp %#x\n",
-			       sizeof (*seg) + seg_size, gfp_mask);
+			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;
 		}
@@ -862,6 +910,12 @@ static int alloc_send_rmpp_list(struct i
 	return 0;
 }
 
+int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent)
+{
+	return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP);
+}
+EXPORT_SYMBOL(ib_mad_kernel_rmpp_agent);
+
 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
 					    u32 remote_qpn, u16 pkey_index,
 					    int rmpp_active,
@@ -878,10 +932,12 @@ struct ib_mad_send_buf * ib_create_send_
 	pad = get_pad_size(hdr_len, data_len);
 	message_size = hdr_len + data_len + pad;
 
-	if ((!mad_agent->rmpp_version &&
-	     (rmpp_active || message_size > sizeof(struct ib_mad))) ||
-	    (!rmpp_active && message_size > sizeof(struct ib_mad)))
-		return ERR_PTR(-EINVAL);
+	if (ib_mad_kernel_rmpp_agent(mad_agent)) {
+		if (!rmpp_active && message_size > sizeof(struct ib_mad))
+			return ERR_PTR(-EINVAL);
+	} else
+		if (rmpp_active || message_size > sizeof(struct ib_mad))
+			return ERR_PTR(-EINVAL);
 
 	size = rmpp_active ? hdr_len : sizeof(struct ib_mad);
 	buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask);
@@ -1135,7 +1191,7 @@ int ib_post_send_mad(struct ib_mad_send_
 			      &mad_agent_priv->send_list);
 		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
-		if (mad_agent_priv->agent.rmpp_version) {
+		if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
 			ret = ib_send_rmpp_mad(mad_send_wr);
 			if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED)
 				ret = ib_send_mad(mad_send_wr);
@@ -1199,7 +1255,8 @@ EXPORT_SYMBOL(ib_redirect_mad_qp);
 int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
 		      struct ib_wc *wc)
 {
-	printk(KERN_ERR PFX "ib_process_mad_wc() not implemented yet\n");
+	dev_err(&mad_agent->device->dev,
+		"ib_process_mad_wc() not implemented yet\n");
 	return 0;
 }
 EXPORT_SYMBOL(ib_process_mad_wc);
@@ -1211,7 +1268,7 @@ static int method_in_use(struct ib_mad_m
 
 	for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) {
 		if ((*method)->agent[i]) {
-			printk(KERN_ERR PFX "Method %d already in use\n", i);
+			pr_err("Method %d already in use\n", i);
 			return -EINVAL;
 		}
 	}
@@ -1223,8 +1280,7 @@ static int allocate_method_table(struct
 	/* Allocate management method table */
 	*method = kzalloc(sizeof **method, GFP_ATOMIC);
 	if (!*method) {
-		printk(KERN_ERR PFX "No memory for "
-		       "ib_mad_mgmt_method_table\n");
+		pr_err("No memory for ib_mad_mgmt_method_table\n");
 		return -ENOMEM;
 	}
 
@@ -1319,8 +1375,8 @@ static int add_nonoui_reg_req(struct ib_
 		/* Allocate management class table for "new" class version */
 		*class = kzalloc(sizeof **class, GFP_ATOMIC);
 		if (!*class) {
-			printk(KERN_ERR PFX "No memory for "
-			       "ib_mad_mgmt_class_table\n");
+			dev_err(&agent_priv->agent.device->dev,
+				"No memory for ib_mad_mgmt_class_table\n");
 			ret = -ENOMEM;
 			goto error1;
 		}
@@ -1386,8 +1442,8 @@ static int add_oui_reg_req(struct ib_mad
 		/* Allocate mgmt vendor class table for "new" class version */
 		vendor = kzalloc(sizeof *vendor, GFP_ATOMIC);
 		if (!vendor) {
-			printk(KERN_ERR PFX "No memory for "
-			       "ib_mad_mgmt_vendor_class_table\n");
+			dev_err(&agent_priv->agent.device->dev,
+				"No memory for ib_mad_mgmt_vendor_class_table\n");
 			goto error1;
 		}
 
@@ -1397,8 +1453,8 @@ static int add_oui_reg_req(struct ib_mad
 		/* Allocate table for this management vendor class */
 		vendor_class = kzalloc(sizeof *vendor_class, GFP_ATOMIC);
 		if (!vendor_class) {
-			printk(KERN_ERR PFX "No memory for "
-			       "ib_mad_mgmt_vendor_class\n");
+			dev_err(&agent_priv->agent.device->dev,
+				"No memory for ib_mad_mgmt_vendor_class\n");
 			goto error2;
 		}
 
@@ -1429,7 +1485,7 @@ static int add_oui_reg_req(struct ib_mad
 			goto check_in_use;
 		}
 	}
-	printk(KERN_ERR PFX "All OUI slots in use\n");
+	dev_err(&agent_priv->agent.device->dev, "All OUI slots in use\n");
 	goto error3;
 
 check_in_use:
@@ -1640,9 +1696,9 @@ find_mad_agent(struct ib_mad_port_privat
 		if (mad_agent->agent.recv_handler)
 			atomic_inc(&mad_agent->refcount);
 		else {
-			printk(KERN_NOTICE PFX "No receive handler for client "
-			       "%p on port %d\n",
-			       &mad_agent->agent, port_priv->port_num);
+			dev_notice(&port_priv->device->dev,
+				   "No receive handler for client %p on port %d\n",
+				   &mad_agent->agent, port_priv->port_num);
 			mad_agent = NULL;
 		}
 	}
@@ -1658,8 +1714,8 @@ static int validate_mad(struct ib_mad *m
 
 	/* Make sure MAD base version is understood */
 	if (mad->mad_hdr.base_version != IB_MGMT_BASE_VERSION) {
-		printk(KERN_ERR PFX "MAD received with unsupported base "
-		       "version %d\n", mad->mad_hdr.base_version);
+		pr_err("MAD received with unsupported base version %d\n",
+			mad->mad_hdr.base_version);
 		goto out;
 	}
 
@@ -1685,6 +1741,7 @@ static int is_data_mad(struct ib_mad_age
 
 	rmpp_mad = (struct ib_rmpp_mad *)mad_hdr;
 	return !mad_agent_priv->agent.rmpp_version ||
+		!ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) ||
 		!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
 				    IB_MGMT_RMPP_FLAG_ACTIVE) ||
 		(rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA);
@@ -1812,7 +1869,7 @@ static void ib_mad_complete_recv(struct
 
 	INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
 	list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
-	if (mad_agent_priv->agent.rmpp_version) {
+	if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
 		mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
 						      mad_recv_wc);
 		if (!mad_recv_wc) {
@@ -1827,23 +1884,39 @@ static void ib_mad_complete_recv(struct
 		mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
 		if (!mad_send_wr) {
 			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
-			ib_free_recv_mad(mad_recv_wc);
-			deref_mad_agent(mad_agent_priv);
-			return;
-		}
-		ib_mark_mad_done(mad_send_wr);
-		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+			if (!ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)
+			   && ib_is_mad_class_rmpp(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class)
+			   && (ib_get_rmpp_flags(&((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr)
+					& IB_MGMT_RMPP_FLAG_ACTIVE)) {
+				/* user rmpp is in effect
+				 * and this is an active RMPP MAD
+				 */
+				mad_recv_wc->wc->wr_id = 0;
+				mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
+								   mad_recv_wc);
+				atomic_dec(&mad_agent_priv->refcount);
+			} else {
+				/* not user rmpp, revert to normal behavior and
+				 * drop the mad */
+				ib_free_recv_mad(mad_recv_wc);
+				deref_mad_agent(mad_agent_priv);
+				return;
+			}
+		} else {
+			ib_mark_mad_done(mad_send_wr);
+			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
-		/* Defined behavior is to complete response before request */
-		mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
-		mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
-						   mad_recv_wc);
-		atomic_dec(&mad_agent_priv->refcount);
+			/* Defined behavior is to complete response before request */
+			mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
+			mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
+							   mad_recv_wc);
+			atomic_dec(&mad_agent_priv->refcount);
 
-		mad_send_wc.status = IB_WC_SUCCESS;
-		mad_send_wc.vendor_err = 0;
-		mad_send_wc.send_buf = &mad_send_wr->send_buf;
-		ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
+			mad_send_wc.status = IB_WC_SUCCESS;
+			mad_send_wc.vendor_err = 0;
+			mad_send_wc.send_buf = &mad_send_wr->send_buf;
+			ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
+		}
 	} else {
 		mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
 						   mad_recv_wc);
@@ -1911,8 +1984,8 @@ static void ib_mad_recv_done_handler(str
 
 	response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
 	if (!response) {
-		printk(KERN_ERR PFX "ib_mad_recv_done_handler no memory "
-		       "for response buffer\n");
+		dev_err(&port_priv->device->dev,
+			"ib_mad_recv_done_handler no memory for response buffer\n");
 		goto out;
 	}
 
@@ -2083,7 +2156,7 @@ void ib_mad_complete_send_wr(struct ib_m
 
 	mad_agent_priv = mad_send_wr->mad_agent_priv;
 	spin_lock_irqsave(&mad_agent_priv->lock, flags);
-	if (mad_agent_priv->agent.rmpp_version) {
+	if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
 		ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc);
 		if (ret == IB_RMPP_RESULT_CONSUMED)
 			goto done;
@@ -2176,7 +2249,8 @@ retry:
 		ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
 				   &bad_send_wr);
 		if (ret) {
-			printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
+			dev_err(&port_priv->device->dev,
+				"ib_post_send failed: %d\n", ret);
 			mad_send_wr = queued_send_wr;
 			wc->status = IB_WC_LOC_QP_OP_ERR;
 			goto retry;
@@ -2248,8 +2322,9 @@ static void mad_error_handler(struct ib_
 					   IB_QP_STATE | IB_QP_CUR_STATE);
 			kfree(attr);
 			if (ret)
-				printk(KERN_ERR PFX "mad_error_handler - "
-				       "ib_modify_qp to RTS : %d\n", ret);
+				dev_err(&port_priv->device->dev,
+					"mad_error_handler - ib_modify_qp to RTS : %d\n",
+					ret);
 			else
 				mark_sends_for_retry(qp_info);
 		}
@@ -2408,7 +2483,8 @@ static void local_completions(struct wor
 		if (local->mad_priv) {
 			recv_mad_agent = local->recv_mad_agent;
 			if (!recv_mad_agent) {
-				printk(KERN_ERR PFX "No receive MAD agent for local completion\n");
+				dev_err(&mad_agent_priv->agent.device->dev,
+					"No receive MAD agent for local completion\n");
 				free_mad = 1;
 				goto local_send_completion;
 			}
@@ -2476,7 +2552,7 @@ static int retry_send(struct ib_mad_send
 
 	mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
 
-	if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
+	if (ib_mad_kernel_rmpp_agent(&mad_send_wr->mad_agent_priv->agent)) {
 		ret = ib_retry_rmpp(mad_send_wr);
 		switch (ret) {
 		case IB_RMPP_RESULT_UNHANDLED:
@@ -2589,7 +2665,8 @@ static int ib_mad_post_receive_mads(stru
 		} else {
 			mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
 			if (!mad_priv) {
-				printk(KERN_ERR PFX "No memory for receive buffer\n");
+				dev_err(&qp_info->port_priv->device->dev,
+					"No memory for receive buffer\n");
 				ret = -ENOMEM;
 				break;
 			}
@@ -2625,7 +2702,8 @@ static int ib_mad_post_receive_mads(stru
 					      sizeof mad_priv->header,
 					    DMA_FROM_DEVICE);
 			kmem_cache_free(ib_mad_cache, mad_priv);
-			printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret);
+			dev_err(&qp_info->port_priv->device->dev,
+				"ib_post_recv failed: %d\n", ret);
 			break;
 		}
 	} while (post);
@@ -2681,7 +2759,8 @@ static int ib_mad_port_start(struct ib_m
 
 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
 	if (!attr) {
-		printk(KERN_ERR PFX "Couldn't kmalloc ib_qp_attr\n");
+		dev_err(&port_priv->device->dev,
+			"Couldn't kmalloc ib_qp_attr\n");
 		return -ENOMEM;
 	}
 
@@ -2705,16 +2784,18 @@ static int ib_mad_port_start(struct ib_m
 		ret = ib_modify_qp(qp, attr, IB_QP_STATE |
 					     IB_QP_PKEY_INDEX | IB_QP_QKEY);
 		if (ret) {
-			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "INIT: %d\n", i, ret);
+			dev_err(&port_priv->device->dev,
+				"Couldn't change QP%d state to INIT: %d\n",
+				i, ret);
 			goto out;
 		}
 
 		attr->qp_state = IB_QPS_RTR;
 		ret = ib_modify_qp(qp, attr, IB_QP_STATE);
 		if (ret) {
-			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "RTR: %d\n", i, ret);
+			dev_err(&port_priv->device->dev,
+				"Couldn't change QP%d state to RTR: %d\n",
+				i, ret);
 			goto out;
 		}
 
@@ -2722,16 +2803,18 @@ static int ib_mad_port_start(struct ib_m
 		attr->sq_psn = IB_MAD_SEND_Q_PSN;
 		ret = ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_SQ_PSN);
 		if (ret) {
-			printk(KERN_ERR PFX "Couldn't change QP%d state to "
-			       "RTS: %d\n", i, ret);
+			dev_err(&port_priv->device->dev,
+				"Couldn't change QP%d state to RTS: %d\n",
+				i, ret);
 			goto out;
 		}
 	}
 
 	ret = ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP);
 	if (ret) {
-		printk(KERN_ERR PFX "Failed to request completion "
-		       "notification: %d\n", ret);
+		dev_err(&port_priv->device->dev,
+			"Failed to request completion notification: %d\n",
+			ret);
 		goto out;
 	}
 
@@ -2741,7 +2824,8 @@ static int ib_mad_port_start(struct ib_m
 
 		ret = ib_mad_post_receive_mads(&port_priv->qp_info[i], NULL);
 		if (ret) {
-			printk(KERN_ERR PFX "Couldn't post receive WRs\n");
+			dev_err(&port_priv->device->dev,
+				"Couldn't post receive WRs\n");
 			goto out;
 		}
 	}
@@ -2755,7 +2839,8 @@ static void qp_event_handler(struct ib_e
 	struct ib_mad_qp_info	*qp_info = qp_context;
 
 	/* It's worse than that! He's dead, Jim! */
-	printk(KERN_ERR PFX "Fatal error (%d) on MAD QP (%d)\n",
+	dev_err(&qp_info->port_priv->device->dev,
+		"Fatal error (%d) on MAD QP (%d)\n",
 		event->event, qp_info->qp->qp_num);
 }
 
@@ -2801,8 +2886,9 @@ static int create_mad_qp(struct ib_mad_q
 	qp_init_attr.event_handler = qp_event_handler;
 	qp_info->qp = ib_create_qp(qp_info->port_priv->pd, &qp_init_attr);
 	if (IS_ERR(qp_info->qp)) {
-		printk(KERN_ERR PFX "Couldn't create ib_mad QP%d\n",
-		       get_spl_qp_index(qp_type));
+		dev_err(&qp_info->port_priv->device->dev,
+			"Couldn't create ib_mad QP%d\n",
+			get_spl_qp_index(qp_type));
 		ret = PTR_ERR(qp_info->qp);
 		goto error;
 	}
@@ -2840,7 +2926,7 @@ static int ib_mad_port_open(struct ib_de
 	/* Create new device info */
 	port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
 	if (!port_priv) {
-		printk(KERN_ERR PFX "No memory for ib_mad_port_private\n");
+		dev_err(&device->dev, "No memory for ib_mad_port_private\n");
 		return -ENOMEM;
 	}
 
@@ -2860,21 +2946,21 @@ static int ib_mad_port_open(struct ib_de
 				     ib_mad_thread_completion_handler,
 				     NULL, port_priv, cq_size, 0);
 	if (IS_ERR(port_priv->cq)) {
-		printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
+		dev_err(&device->dev, "Couldn't create ib_mad CQ\n");
 		ret = PTR_ERR(port_priv->cq);
 		goto error3;
 	}
 
 	port_priv->pd = ib_alloc_pd(device);
 	if (IS_ERR(port_priv->pd)) {
-		printk(KERN_ERR PFX "Couldn't create ib_mad PD\n");
+		dev_err(&device->dev, "Couldn't create ib_mad PD\n");
 		ret = PTR_ERR(port_priv->pd);
 		goto error4;
 	}
 
 	port_priv->mr = ib_get_dma_mr(port_priv->pd, IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(port_priv->mr)) {
-		printk(KERN_ERR PFX "Couldn't get ib_mad DMA MR\n");
+		dev_err(&device->dev, "Couldn't get ib_mad DMA MR\n");
 		ret = PTR_ERR(port_priv->mr);
 		goto error5;
 	}
@@ -2902,7 +2988,7 @@ static int ib_mad_port_open(struct ib_de
 
 	ret = ib_mad_port_start(port_priv);
 	if (ret) {
-		printk(KERN_ERR PFX "Couldn't start port\n");
+		dev_err(&device->dev, "Couldn't start port\n");
 		goto error9;
 	}
 
@@ -2946,7 +3032,7 @@ static int ib_mad_port_close(struct ib_d
 	port_priv = __ib_get_mad_port(device, port_num);
 	if (port_priv == NULL) {
 		spin_unlock_irqrestore(&ib_mad_port_list_lock, flags);
-		printk(KERN_ERR PFX "Port %d not found\n", port_num);
+		dev_err(&device->dev, "Port %d not found\n", port_num);
 		return -ENODEV;
 	}
 	list_del_init(&port_priv->port_list);
@@ -2984,14 +3070,12 @@ static void ib_mad_init_device(struct ib
 
 	for (i = start; i <= end; i++) {
 		if (ib_mad_port_open(device, i)) {
-			printk(KERN_ERR PFX "Couldn't open %s port %d\n",
-			       device->name, i);
+			dev_err(&device->dev, "Couldn't open port %d\n", i);
 			goto error;
 		}
 		if (ib_agent_port_open(device, i)) {
-			printk(KERN_ERR PFX "Couldn't open %s port %d "
-			       "for agents\n",
-			       device->name, i);
+			dev_err(&device->dev,
+				"Couldn't open port %d for agents\n", i);
 			goto error_agent;
 		}
 	}
@@ -2999,20 +3083,17 @@ static void ib_mad_init_device(struct ib
 
 error_agent:
 	if (ib_mad_port_close(device, i))
-		printk(KERN_ERR PFX "Couldn't close %s port %d\n",
-		       device->name, i);
+		dev_err(&device->dev, "Couldn't close port %d\n", i);
 
 error:
 	i--;
 
 	while (i >= start) {
 		if (ib_agent_port_close(device, i))
-			printk(KERN_ERR PFX "Couldn't close %s port %d "
-			       "for agents\n",
-			       device->name, i);
+			dev_err(&device->dev,
+				"Couldn't close port %d for agents\n", i);
 		if (ib_mad_port_close(device, i))
-			printk(KERN_ERR PFX "Couldn't close %s port %d\n",
-			       device->name, i);
+			dev_err(&device->dev, "Couldn't close port %d\n", i);
 		i--;
 	}
 }
@@ -3033,12 +3114,12 @@ static void ib_mad_remove_device(struct
 	}
 	for (i = 0; i < num_ports; i++, cur_port++) {
 		if (ib_agent_port_close(device, cur_port))
-			printk(KERN_ERR PFX "Couldn't close %s port %d "
-			       "for agents\n",
-			       device->name, cur_port);
+			dev_err(&device->dev,
+				"Couldn't close port %d for agents\n",
+				cur_port);
 		if (ib_mad_port_close(device, cur_port))
-			printk(KERN_ERR PFX "Couldn't close %s port %d\n",
-			       device->name, cur_port);
+			dev_err(&device->dev, "Couldn't close port %d\n",
+				cur_port);
 	}
 }
 
@@ -3064,7 +3145,7 @@ static int __init ib_mad_init_module(voi
 					 SLAB_HWCACHE_ALIGN,
 					 NULL);
 	if (!ib_mad_cache) {
-		printk(KERN_ERR PFX "Couldn't create ib_mad cache\n");
+		pr_err("Couldn't create ib_mad cache\n");
 		ret = -ENOMEM;
 		goto error1;
 	}
@@ -3072,7 +3153,7 @@ static int __init ib_mad_init_module(voi
 	INIT_LIST_HEAD(&ib_mad_port_list);
 
 	if (ib_register_client(&mad_client)) {
-		printk(KERN_ERR PFX "Couldn't register ib_mad client\n");
+		pr_err("Couldn't register ib_mad client\n");
 		ret = -EINVAL;
 		goto error2;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/mad_priv.h linux-libre-3.17-rc7-gnu/drivers/infiniband/core/mad_priv.h
--- linux-libre-3.16-gnu/drivers/infiniband/core/mad_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/mad_priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,6 @@
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
 
-
-#define PFX "ib_mad: "
-
 #define IB_MAD_QPS_CORE		2 /* Always QP0 and QP1 as a minimum */
 
 /* QP and CQ parameters */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/sa_query.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/sa_query.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/sa_query.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/sa_query.c	2014-09-28 17:29:07.000000000 -0400
@@ -1184,7 +1184,7 @@ static void ib_sa_add_one(struct ib_devi
 		sa_dev->port[i].agent =
 			ib_register_mad_agent(device, i + s, IB_QPT_GSI,
 					      NULL, 0, send_handler,
-					      recv_handler, sa_dev);
+					      recv_handler, sa_dev, 0);
 		if (IS_ERR(sa_dev->port[i].agent))
 			goto err;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/umem.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/umem.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/umem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/umem.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,6 +105,7 @@ struct ib_umem *ib_umem_get(struct ib_uc
 	umem->length    = size;
 	umem->offset    = addr & ~PAGE_MASK;
 	umem->page_size = PAGE_SIZE;
+	umem->pid       = get_task_pid(current, PIDTYPE_PID);
 	/*
 	 * We ask for writable memory if any access flags other than
 	 * "remote read" are set.  "Local write" and "remote write"
@@ -198,6 +199,7 @@ out:
 	if (ret < 0) {
 		if (need_release)
 			__ib_umem_release(context->device, umem, 0);
+		put_pid(umem->pid);
 		kfree(umem);
 	} else
 		current->mm->pinned_vm = locked;
@@ -230,15 +232,19 @@ void ib_umem_release(struct ib_umem *ume
 {
 	struct ib_ucontext *context = umem->context;
 	struct mm_struct *mm;
+	struct task_struct *task;
 	unsigned long diff;
 
 	__ib_umem_release(umem->context->device, umem, 1);
 
-	mm = get_task_mm(current);
-	if (!mm) {
-		kfree(umem);
-		return;
-	}
+	task = get_pid_task(umem->pid, PIDTYPE_PID);
+	put_pid(umem->pid);
+	if (!task)
+		goto out;
+	mm = get_task_mm(task);
+	put_task_struct(task);
+	if (!mm)
+		goto out;
 
 	diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
 
@@ -262,9 +268,10 @@ void ib_umem_release(struct ib_umem *ume
 	} else
 		down_write(&mm->mmap_sem);
 
-	current->mm->pinned_vm -= diff;
+	mm->pinned_vm -= diff;
 	up_write(&mm->mmap_sem);
 	mmput(mm);
+out:
 	kfree(umem);
 }
 EXPORT_SYMBOL(ib_umem_release);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/user_mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/user_mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/user_mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/user_mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,8 @@
  * SOFTWARE.
  */
 
+#define pr_fmt(fmt) "user_mad: " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -504,13 +506,15 @@ static ssize_t ib_umad_write(struct file
 
 	rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;
 	hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
-	if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) {
-		copy_offset = IB_MGMT_MAD_HDR;
-		rmpp_active = 0;
-	} else {
+
+	if (ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
+	    && ib_mad_kernel_rmpp_agent(agent)) {
 		copy_offset = IB_MGMT_RMPP_HDR;
 		rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
-			      IB_MGMT_RMPP_FLAG_ACTIVE;
+						IB_MGMT_RMPP_FLAG_ACTIVE;
+	} else {
+		copy_offset = IB_MGMT_MAD_HDR;
+		rmpp_active = 0;
 	}
 
 	data_len = count - hdr_size(file) - hdr_len;
@@ -556,14 +560,22 @@ static ssize_t ib_umad_write(struct file
 		rmpp_mad->mad_hdr.tid = *tid;
 	}
 
-	spin_lock_irq(&file->send_lock);
-	ret = is_duplicate(file, packet);
-	if (!ret)
+	if (!ib_mad_kernel_rmpp_agent(agent)
+	   && ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
+	   && (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) {
+		spin_lock_irq(&file->send_lock);
 		list_add_tail(&packet->list, &file->send_list);
-	spin_unlock_irq(&file->send_lock);
-	if (ret) {
-		ret = -EINVAL;
-		goto err_msg;
+		spin_unlock_irq(&file->send_lock);
+	} else {
+		spin_lock_irq(&file->send_lock);
+		ret = is_duplicate(file, packet);
+		if (!ret)
+			list_add_tail(&packet->list, &file->send_list);
+		spin_unlock_irq(&file->send_lock);
+		if (ret) {
+			ret = -EINVAL;
+			goto err_msg;
+		}
 	}
 
 	ret = ib_post_send_mad(packet->msg, NULL);
@@ -614,6 +626,8 @@ static int ib_umad_reg_agent(struct ib_u
 	mutex_lock(&file->mutex);
 
 	if (!file->port->ib_dev) {
+		dev_notice(file->port->dev,
+			   "ib_umad_reg_agent: invalid device\n");
 		ret = -EPIPE;
 		goto out;
 	}
@@ -624,6 +638,9 @@ static int ib_umad_reg_agent(struct ib_u
 	}
 
 	if (ureq.qpn != 0 && ureq.qpn != 1) {
+		dev_notice(file->port->dev,
+			   "ib_umad_reg_agent: invalid QPN %d specified\n",
+			   ureq.qpn);
 		ret = -EINVAL;
 		goto out;
 	}
@@ -632,11 +649,15 @@ static int ib_umad_reg_agent(struct ib_u
 		if (!__get_agent(file, agent_id))
 			goto found;
 
+	dev_notice(file->port->dev,
+		   "ib_umad_reg_agent: Max Agents (%u) reached\n",
+		   IB_UMAD_MAX_AGENTS);
 	ret = -ENOMEM;
 	goto out;
 
 found:
 	if (ureq.mgmt_class) {
+		memset(&req, 0, sizeof(req));
 		req.mgmt_class         = ureq.mgmt_class;
 		req.mgmt_class_version = ureq.mgmt_class_version;
 		memcpy(req.oui, ureq.oui, sizeof req.oui);
@@ -657,7 +678,7 @@ found:
 				      ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
 				      ureq.mgmt_class ? &req : NULL,
 				      ureq.rmpp_version,
-				      send_handler, recv_handler, file);
+				      send_handler, recv_handler, file, 0);
 	if (IS_ERR(agent)) {
 		ret = PTR_ERR(agent);
 		agent = NULL;
@@ -673,11 +694,124 @@ found:
 	if (!file->already_used) {
 		file->already_used = 1;
 		if (!file->use_pkey_index) {
-			printk(KERN_WARNING "user_mad: process %s did not enable "
-			       "P_Key index support.\n", current->comm);
-			printk(KERN_WARNING "user_mad:   Documentation/infiniband/user_mad.txt "
-			       "has info on the new ABI.\n");
+			dev_warn(file->port->dev,
+				"process %s did not enable P_Key index support.\n",
+				current->comm);
+			dev_warn(file->port->dev,
+				"   Documentation/infiniband/user_mad.txt has info on the new ABI.\n");
+		}
+	}
+
+	file->agent[agent_id] = agent;
+	ret = 0;
+
+out:
+	mutex_unlock(&file->mutex);
+
+	if (ret && agent)
+		ib_unregister_mad_agent(agent);
+
+	mutex_unlock(&file->port->file_mutex);
+
+	return ret;
+}
+
+static int ib_umad_reg_agent2(struct ib_umad_file *file, void __user *arg)
+{
+	struct ib_user_mad_reg_req2 ureq;
+	struct ib_mad_reg_req req;
+	struct ib_mad_agent *agent = NULL;
+	int agent_id;
+	int ret;
+
+	mutex_lock(&file->port->file_mutex);
+	mutex_lock(&file->mutex);
+
+	if (!file->port->ib_dev) {
+		dev_notice(file->port->dev,
+			   "ib_umad_reg_agent2: invalid device\n");
+		ret = -EPIPE;
+		goto out;
+	}
+
+	if (copy_from_user(&ureq, arg, sizeof(ureq))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (ureq.qpn != 0 && ureq.qpn != 1) {
+		dev_notice(file->port->dev,
+			   "ib_umad_reg_agent2: invalid QPN %d specified\n",
+			   ureq.qpn);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ureq.flags & ~IB_USER_MAD_REG_FLAGS_CAP) {
+		dev_notice(file->port->dev,
+			   "ib_umad_reg_agent2 failed: invalid registration flags specified 0x%x; supported 0x%x\n",
+			   ureq.flags, IB_USER_MAD_REG_FLAGS_CAP);
+		ret = -EINVAL;
+
+		if (put_user((u32)IB_USER_MAD_REG_FLAGS_CAP,
+				(u32 __user *) (arg + offsetof(struct
+				ib_user_mad_reg_req2, flags))))
+			ret = -EFAULT;
+
+		goto out;
+	}
+
+	for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id)
+		if (!__get_agent(file, agent_id))
+			goto found;
+
+	dev_notice(file->port->dev,
+		   "ib_umad_reg_agent2: Max Agents (%u) reached\n",
+		   IB_UMAD_MAX_AGENTS);
+	ret = -ENOMEM;
+	goto out;
+
+found:
+	if (ureq.mgmt_class) {
+		memset(&req, 0, sizeof(req));
+		req.mgmt_class         = ureq.mgmt_class;
+		req.mgmt_class_version = ureq.mgmt_class_version;
+		if (ureq.oui & 0xff000000) {
+			dev_notice(file->port->dev,
+				   "ib_umad_reg_agent2 failed: oui invalid 0x%08x\n",
+				   ureq.oui);
+			ret = -EINVAL;
+			goto out;
 		}
+		req.oui[2] =  ureq.oui & 0x0000ff;
+		req.oui[1] = (ureq.oui & 0x00ff00) >> 8;
+		req.oui[0] = (ureq.oui & 0xff0000) >> 16;
+		memcpy(req.method_mask, ureq.method_mask,
+			sizeof(req.method_mask));
+	}
+
+	agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num,
+				      ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
+				      ureq.mgmt_class ? &req : NULL,
+				      ureq.rmpp_version,
+				      send_handler, recv_handler, file,
+				      ureq.flags);
+	if (IS_ERR(agent)) {
+		ret = PTR_ERR(agent);
+		agent = NULL;
+		goto out;
+	}
+
+	if (put_user(agent_id,
+		     (u32 __user *)(arg +
+				offsetof(struct ib_user_mad_reg_req2, id)))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (!file->already_used) {
+		file->already_used = 1;
+		file->use_pkey_index = 1;
 	}
 
 	file->agent[agent_id] = agent;
@@ -694,6 +828,7 @@ out:
 	return ret;
 }
 
+
 static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
 {
 	struct ib_mad_agent *agent = NULL;
@@ -749,6 +884,8 @@ static long ib_umad_ioctl(struct file *f
 		return ib_umad_unreg_agent(filp->private_data, (__u32 __user *) arg);
 	case IB_USER_MAD_ENABLE_PKEY:
 		return ib_umad_enable_pkey(filp->private_data);
+	case IB_USER_MAD_REGISTER_AGENT2:
+		return ib_umad_reg_agent2(filp->private_data, (void __user *) arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -765,6 +902,8 @@ static long ib_umad_compat_ioctl(struct
 		return ib_umad_unreg_agent(filp->private_data, compat_ptr(arg));
 	case IB_USER_MAD_ENABLE_PKEY:
 		return ib_umad_enable_pkey(filp->private_data);
+	case IB_USER_MAD_REGISTER_AGENT2:
+		return ib_umad_reg_agent2(filp->private_data, compat_ptr(arg));
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -983,7 +1122,7 @@ static CLASS_ATTR_STRING(abi_version, S_
 
 static dev_t overflow_maj;
 static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
-static int find_overflow_devnum(void)
+static int find_overflow_devnum(struct ib_device *device)
 {
 	int ret;
 
@@ -991,7 +1130,8 @@ static int find_overflow_devnum(void)
 		ret = alloc_chrdev_region(&overflow_maj, 0, IB_UMAD_MAX_PORTS * 2,
 					  "infiniband_mad");
 		if (ret) {
-			printk(KERN_ERR "user_mad: couldn't register dynamic device number\n");
+			dev_err(&device->dev,
+				"couldn't register dynamic device number\n");
 			return ret;
 		}
 	}
@@ -1014,7 +1154,7 @@ static int ib_umad_init_port(struct ib_d
 	devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
 	if (devnum >= IB_UMAD_MAX_PORTS) {
 		spin_unlock(&port_lock);
-		devnum = find_overflow_devnum();
+		devnum = find_overflow_devnum(device);
 		if (devnum < 0)
 			return -1;
 
@@ -1200,14 +1340,14 @@ static int __init ib_umad_init(void)
 	ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
 				     "infiniband_mad");
 	if (ret) {
-		printk(KERN_ERR "user_mad: couldn't register device number\n");
+		pr_err("couldn't register device number\n");
 		goto out;
 	}
 
 	umad_class = class_create(THIS_MODULE, "infiniband_mad");
 	if (IS_ERR(umad_class)) {
 		ret = PTR_ERR(umad_class);
-		printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
+		pr_err("couldn't create class infiniband_mad\n");
 		goto out_chrdev;
 	}
 
@@ -1215,13 +1355,13 @@ static int __init ib_umad_init(void)
 
 	ret = class_create_file(umad_class, &class_attr_abi_version.attr);
 	if (ret) {
-		printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
+		pr_err("couldn't create abi_version attribute\n");
 		goto out_class;
 	}
 
 	ret = ib_register_client(&umad_client);
 	if (ret) {
-		printk(KERN_ERR "user_mad: couldn't register ib_umad client\n");
+		pr_err("couldn't register ib_umad client\n");
 		goto out_class;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_cmd.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_cmd.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1002,6 +1002,99 @@ err_free:
 	return ret;
 }
 
+ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
+			   const char __user *buf, int in_len,
+			   int out_len)
+{
+	struct ib_uverbs_rereg_mr      cmd;
+	struct ib_uverbs_rereg_mr_resp resp;
+	struct ib_udata              udata;
+	struct ib_pd                *pd = NULL;
+	struct ib_mr                *mr;
+	struct ib_pd		    *old_pd;
+	int                          ret;
+	struct ib_uobject	    *uobj;
+
+	if (out_len < sizeof(resp))
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof(cmd)))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof(cmd),
+		   (unsigned long) cmd.response + sizeof(resp),
+		   in_len - sizeof(cmd), out_len - sizeof(resp));
+
+	if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
+		return -EINVAL;
+
+	if ((cmd.flags & IB_MR_REREG_TRANS) &&
+	    (!cmd.start || !cmd.hca_va || 0 >= cmd.length ||
+	     (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)))
+			return -EINVAL;
+
+	uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle,
+			      file->ucontext);
+
+	if (!uobj)
+		return -EINVAL;
+
+	mr = uobj->object;
+
+	if (cmd.flags & IB_MR_REREG_ACCESS) {
+		ret = ib_check_mr_access(cmd.access_flags);
+		if (ret)
+			goto put_uobjs;
+	}
+
+	if (cmd.flags & IB_MR_REREG_PD) {
+		pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+		if (!pd) {
+			ret = -EINVAL;
+			goto put_uobjs;
+		}
+	}
+
+	if (atomic_read(&mr->usecnt)) {
+		ret = -EBUSY;
+		goto put_uobj_pd;
+	}
+
+	old_pd = mr->pd;
+	ret = mr->device->rereg_user_mr(mr, cmd.flags, cmd.start,
+					cmd.length, cmd.hca_va,
+					cmd.access_flags, pd, &udata);
+	if (!ret) {
+		if (cmd.flags & IB_MR_REREG_PD) {
+			atomic_inc(&pd->usecnt);
+			mr->pd = pd;
+			atomic_dec(&old_pd->usecnt);
+		}
+	} else {
+		goto put_uobj_pd;
+	}
+
+	memset(&resp, 0, sizeof(resp));
+	resp.lkey      = mr->lkey;
+	resp.rkey      = mr->rkey;
+
+	if (copy_to_user((void __user *)(unsigned long)cmd.response,
+			 &resp, sizeof(resp)))
+		ret = -EFAULT;
+	else
+		ret = in_len;
+
+put_uobj_pd:
+	if (cmd.flags & IB_MR_REREG_PD)
+		put_pd_read(pd);
+
+put_uobjs:
+
+	put_uobj_write(mr->uobject);
+
+	return ret;
+}
+
 ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
 			   const char __user *buf, int in_len,
 			   int out_len)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/uverbs.h linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs.h
--- linux-libre-3.16-gnu/drivers/infiniband/core/uverbs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs.h	2014-09-28 17:29:07.000000000 -0400
@@ -221,6 +221,7 @@ IB_UVERBS_DECLARE_CMD(query_port);
 IB_UVERBS_DECLARE_CMD(alloc_pd);
 IB_UVERBS_DECLARE_CMD(dealloc_pd);
 IB_UVERBS_DECLARE_CMD(reg_mr);
+IB_UVERBS_DECLARE_CMD(rereg_mr);
 IB_UVERBS_DECLARE_CMD(dereg_mr);
 IB_UVERBS_DECLARE_CMD(alloc_mw);
 IB_UVERBS_DECLARE_CMD(dealloc_mw);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_main.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,7 @@ static ssize_t (*uverbs_cmd_table[])(str
 	[IB_USER_VERBS_CMD_ALLOC_PD]		= ib_uverbs_alloc_pd,
 	[IB_USER_VERBS_CMD_DEALLOC_PD]		= ib_uverbs_dealloc_pd,
 	[IB_USER_VERBS_CMD_REG_MR]		= ib_uverbs_reg_mr,
+	[IB_USER_VERBS_CMD_REREG_MR]		= ib_uverbs_rereg_mr,
 	[IB_USER_VERBS_CMD_DEREG_MR]		= ib_uverbs_dereg_mr,
 	[IB_USER_VERBS_CMD_ALLOC_MW]		= ib_uverbs_alloc_mw,
 	[IB_USER_VERBS_CMD_DEALLOC_MW]		= ib_uverbs_dealloc_mw,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_marshall.c linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_marshall.c
--- linux-libre-3.16-gnu/drivers/infiniband/core/uverbs_marshall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/core/uverbs_marshall.c	2014-09-28 17:29:07.000000000 -0400
@@ -140,5 +140,9 @@ void ib_copy_path_rec_from_user(struct i
 	dst->packet_life_time	= src->packet_life_time;
 	dst->preference		= src->preference;
 	dst->packet_life_time_selector = src->packet_life_time_selector;
+
+	memset(dst->smac, 0, sizeof(dst->smac));
+	memset(dst->dmac, 0, sizeof(dst->dmac));
+	dst->vlan_id = 0xffff;
 }
 EXPORT_SYMBOL(ib_copy_path_rec_from_user);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2.c	2014-09-28 17:29:07.000000000 -0400
@@ -604,16 +604,14 @@ static int c2_up(struct net_device *netd
 	tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc);
 
 	c2_port->mem_size = tx_size + rx_size;
-	c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size,
-					    &c2_port->dma);
+	c2_port->mem = pci_zalloc_consistent(c2dev->pcidev, c2_port->mem_size,
+					     &c2_port->dma);
 	if (c2_port->mem == NULL) {
 		pr_debug("Unable to allocate memory for "
 			"host descriptor rings\n");
 		return -ENOMEM;
 	}
 
-	memset(c2_port->mem, 0, c2_port->mem_size);
-
 	/* Create the Rx host descriptor ring */
 	if ((ret =
 	     c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2_cq.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2_cq.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2_cq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2_cq.c	2014-09-28 17:29:07.000000000 -0400
@@ -260,11 +260,14 @@ static void c2_free_cq_buf(struct c2_dev
 			  mq->msg_pool.host, dma_unmap_addr(mq, mapping));
 }
 
-static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, int q_size,
-			   int msg_size)
+static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq,
+			   size_t q_size, size_t msg_size)
 {
 	u8 *pool_start;
 
+	if (q_size > SIZE_MAX / msg_size)
+		return -EINVAL;
+
 	pool_start = dma_alloc_coherent(&c2dev->pcidev->dev, q_size * msg_size,
 					&mq->host_dma, GFP_KERNEL);
 	if (!pool_start)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2_provider.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2_provider.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/amso1100/c2_provider.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/amso1100/c2_provider.c	2014-09-28 17:29:07.000000000 -0400
@@ -734,7 +734,7 @@ static struct net_device *c2_pseudo_netd
 	/* change ethxxx to iwxxx */
 	strcpy(name, "iw");
 	strcat(name, &c2dev->netdev->name[3]);
-	netdev = alloc_netdev(0, name, setup);
+	netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, setup);
 	if (!netdev) {
 		printk(KERN_ERR PFX "%s -  etherdev alloc failed",
 			__func__);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/cm.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/cm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/cm.c	2014-09-28 17:29:07.000000000 -0400
@@ -79,9 +79,10 @@ static int dack_mode = 1;
 module_param(dack_mode, int, 0644);
 MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
 
-int c4iw_max_read_depth = 8;
+uint c4iw_max_read_depth = 32;
 module_param(c4iw_max_read_depth, int, 0644);
-MODULE_PARM_DESC(c4iw_max_read_depth, "Per-connection max ORD/IRD (default=8)");
+MODULE_PARM_DESC(c4iw_max_read_depth,
+		 "Per-connection max ORD/IRD (default=32)");
 
 static int enable_tcp_timestamps;
 module_param(enable_tcp_timestamps, int, 0644);
@@ -474,7 +475,8 @@ static void send_flowc(struct c4iw_ep *e
 					  16)) | FW_WR_FLOWID(ep->hwtid));
 
 	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
-	flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
+	flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN
+					    (ep->com.dev->rdev.lldi.pf));
 	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
 	flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
 	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
@@ -821,6 +823,8 @@ static void send_mpa_req(struct c4iw_ep
 	if (mpa_rev_to_use == 2) {
 		mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
 					       sizeof (struct mpa_v2_conn_params));
+		PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+		     ep->ord);
 		mpa_v2_params.ird = htons((u16)ep->ird);
 		mpa_v2_params.ord = htons((u16)ep->ord);
 
@@ -1190,8 +1194,8 @@ static int connect_request_upcall(struct
 			sizeof(struct mpa_v2_conn_params);
 	} else {
 		/* this means MPA_v1 is used. Send max supported */
-		event.ord = c4iw_max_read_depth;
-		event.ird = c4iw_max_read_depth;
+		event.ord = cur_max_read_depth(ep->com.dev);
+		event.ird = cur_max_read_depth(ep->com.dev);
 		event.private_data_len = ep->plen;
 		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	}
@@ -1255,6 +1259,8 @@ static int update_rx_credits(struct c4iw
 	return credits;
 }
 
+#define RELAXED_IRD_NEGOTIATION 1
+
 static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
@@ -1366,17 +1372,33 @@ static int process_mpa_reply(struct c4iw
 				MPA_V2_IRD_ORD_MASK;
 			resp_ord = ntohs(mpa_v2_params->ord) &
 				MPA_V2_IRD_ORD_MASK;
+			PDBG("%s responder ird %u ord %u ep ird %u ord %u\n",
+			     __func__, resp_ird, resp_ord, ep->ird, ep->ord);
 
 			/*
 			 * This is a double-check. Ideally, below checks are
 			 * not required since ird/ord stuff has been taken
 			 * care of in c4iw_accept_cr
 			 */
-			if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+			if (ep->ird < resp_ord) {
+				if (RELAXED_IRD_NEGOTIATION && resp_ord <=
+				    ep->com.dev->rdev.lldi.max_ordird_qp)
+					ep->ird = resp_ord;
+				else
+					insuff_ird = 1;
+			} else if (ep->ird > resp_ord) {
+				ep->ird = resp_ord;
+			}
+			if (ep->ord > resp_ird) {
+				if (RELAXED_IRD_NEGOTIATION)
+					ep->ord = resp_ird;
+				else
+					insuff_ird = 1;
+			}
+			if (insuff_ird) {
 				err = -ENOMEM;
 				ep->ird = resp_ord;
 				ep->ord = resp_ird;
-				insuff_ird = 1;
 			}
 
 			if (ntohs(mpa_v2_params->ird) &
@@ -1579,6 +1601,8 @@ static void process_mpa_request(struct c
 				MPA_V2_IRD_ORD_MASK;
 			ep->ord = ntohs(mpa_v2_params->ord) &
 				MPA_V2_IRD_ORD_MASK;
+			PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+			     ep->ord);
 			if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
 				if (peer2peer) {
 					if (ntohs(mpa_v2_params->ord) &
@@ -1798,6 +1822,20 @@ static int is_neg_adv(unsigned int statu
 	       status == CPL_ERR_KEEPALV_NEG_ADVICE;
 }
 
+static char *neg_adv_str(unsigned int status)
+{
+	switch (status) {
+	case CPL_ERR_RTX_NEG_ADVICE:
+		return "Retransmit timeout";
+	case CPL_ERR_PERSIST_NEG_ADVICE:
+		return "Persist timeout";
+	case CPL_ERR_KEEPALV_NEG_ADVICE:
+		return "Keepalive timeout";
+	default:
+		return "Unknown";
+	}
+}
+
 static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
 {
 	ep->snd_win = snd_win;
@@ -1996,8 +2034,9 @@ static int act_open_rpl(struct c4iw_dev
 	     status, status2errno(status));
 
 	if (is_neg_adv(status)) {
-		printk(KERN_WARNING MOD "Connection problems for atid %u\n",
-			atid);
+		dev_warn(&dev->rdev.lldi.pdev->dev,
+			 "Connection problems for atid %u status %u (%s)\n",
+			 atid, status, neg_adv_str(status));
 		return 0;
 	}
 
@@ -2472,8 +2511,9 @@ static int peer_abort(struct c4iw_dev *d
 
 	ep = lookup_tid(t, tid);
 	if (is_neg_adv(req->status)) {
-		PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
-		     ep->hwtid);
+		dev_warn(&dev->rdev.lldi.pdev->dev,
+			 "Negative advice on abort - tid %u status %d (%s)\n",
+			 ep->hwtid, req->status, neg_adv_str(req->status));
 		return 0;
 	}
 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
@@ -2731,8 +2771,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 	BUG_ON(!qp);
 
 	set_bit(ULP_ACCEPT, &ep->com.history);
-	if ((conn_param->ord > c4iw_max_read_depth) ||
-	    (conn_param->ird > c4iw_max_read_depth)) {
+	if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
+	    (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
 		abort_connection(ep, NULL, GFP_KERNEL);
 		err = -EINVAL;
 		goto err;
@@ -2740,31 +2780,41 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 
 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
 		if (conn_param->ord > ep->ird) {
-			ep->ird = conn_param->ird;
-			ep->ord = conn_param->ord;
-			send_mpa_reject(ep, conn_param->private_data,
-					conn_param->private_data_len);
-			abort_connection(ep, NULL, GFP_KERNEL);
-			err = -ENOMEM;
-			goto err;
+			if (RELAXED_IRD_NEGOTIATION) {
+				ep->ord = ep->ird;
+			} else {
+				ep->ird = conn_param->ird;
+				ep->ord = conn_param->ord;
+				send_mpa_reject(ep, conn_param->private_data,
+						conn_param->private_data_len);
+				abort_connection(ep, NULL, GFP_KERNEL);
+				err = -ENOMEM;
+				goto err;
+			}
 		}
-		if (conn_param->ird > ep->ord) {
-			if (!ep->ord)
-				conn_param->ird = 1;
-			else {
+		if (conn_param->ird < ep->ord) {
+			if (RELAXED_IRD_NEGOTIATION &&
+			    ep->ord <= h->rdev.lldi.max_ordird_qp) {
+				conn_param->ird = ep->ord;
+			} else {
 				abort_connection(ep, NULL, GFP_KERNEL);
 				err = -ENOMEM;
 				goto err;
 			}
 		}
-
 	}
 	ep->ird = conn_param->ird;
 	ep->ord = conn_param->ord;
 
-	if (ep->mpa_attr.version != 2)
+	if (ep->mpa_attr.version == 1) {
 		if (peer2peer && ep->ird == 0)
 			ep->ird = 1;
+	} else {
+		if (peer2peer &&
+		    (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
+		    (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+			ep->ird = 1;
+	}
 
 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
@@ -2803,6 +2853,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 	return 0;
 err1:
 	ep->com.cm_id = NULL;
+	abort_connection(ep, NULL, GFP_KERNEL);
 	cm_id->rem_ref(cm_id);
 err:
 	mutex_unlock(&ep->com.mutex);
@@ -2886,8 +2937,8 @@ int c4iw_connect(struct iw_cm_id *cm_id,
 	int iptype;
 	int iwpm_err = 0;
 
-	if ((conn_param->ord > c4iw_max_read_depth) ||
-	    (conn_param->ird > c4iw_max_read_depth)) {
+	if ((conn_param->ord > cur_max_read_depth(dev)) ||
+	    (conn_param->ird > cur_max_read_depth(dev))) {
 		err = -EINVAL;
 		goto out;
 	}
@@ -3867,8 +3918,9 @@ static int peer_abort_intr(struct c4iw_d
 		return 0;
 	}
 	if (is_neg_adv(req->status)) {
-		PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
-		     ep->hwtid);
+		dev_warn(&dev->rdev.lldi.pdev->dev,
+			 "Negative advice on abort - tid %u status %d (%s)\n",
+			 ep->hwtid, req->status, neg_adv_str(req->status));
 		kfree_skb(skb);
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/cq.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/cq.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/cq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/cq.c	2014-09-28 17:29:07.000000000 -0400
@@ -633,11 +633,15 @@ proc_cqe:
 		wq->sq.cidx = (uint16_t)idx;
 		PDBG("%s completing sq idx %u\n", __func__, wq->sq.cidx);
 		*cookie = wq->sq.sw_sq[wq->sq.cidx].wr_id;
+		if (c4iw_wr_log)
+			c4iw_log_wr_stats(wq, hw_cqe);
 		t4_sq_consume(wq);
 	} else {
 		PDBG("%s completing rq idx %u\n", __func__, wq->rq.cidx);
 		*cookie = wq->rq.sw_rq[wq->rq.cidx].wr_id;
 		BUG_ON(t4_rq_empty(wq));
+		if (c4iw_wr_log)
+			c4iw_log_wr_stats(wq, hw_cqe);
 		t4_rq_consume(wq);
 		goto skip_cqe;
 	}
@@ -895,7 +899,7 @@ struct ib_cq *c4iw_create_cq(struct ib_d
 	/*
 	 * Make actual HW queue 2x to avoid cdix_inc overflows.
 	 */
-	hwentries = min(entries * 2, T4_MAX_IQ_SIZE);
+	hwentries = min(entries * 2, rhp->rdev.hw_queue.t4_max_iq_size);
 
 	/*
 	 * Make HW queue at least 64 entries so GTS updates aren't too
@@ -909,14 +913,8 @@ struct ib_cq *c4iw_create_cq(struct ib_d
 	/*
 	 * memsize must be a multiple of the page size if its a user cq.
 	 */
-	if (ucontext) {
+	if (ucontext)
 		memsize = roundup(memsize, PAGE_SIZE);
-		hwentries = memsize / sizeof *chp->cq.queue;
-		while (hwentries > T4_MAX_IQ_SIZE) {
-			memsize -= PAGE_SIZE;
-			hwentries = memsize / sizeof *chp->cq.queue;
-		}
-	}
 	chp->cq.size = hwentries;
 	chp->cq.memsize = memsize;
 	chp->cq.vector = vector;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/device.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/device.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/device.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/moduleparam.h>
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
+#include <linux/math64.h>
 
 #include <rdma/ib_verbs.h>
 
@@ -55,6 +56,15 @@ module_param(allow_db_coalescing_on_t5,
 MODULE_PARM_DESC(allow_db_coalescing_on_t5,
 		 "Allow DB Coalescing on T5 (default = 0)");
 
+int c4iw_wr_log = 0;
+module_param(c4iw_wr_log, int, 0444);
+MODULE_PARM_DESC(c4iw_wr_log, "Enables logging of work request timing data.");
+
+int c4iw_wr_log_size_order = 12;
+module_param(c4iw_wr_log_size_order, int, 0444);
+MODULE_PARM_DESC(c4iw_wr_log_size_order,
+		 "Number of entries (log2) in the work request timing log.");
+
 struct uld_ctx {
 	struct list_head entry;
 	struct cxgb4_lld_info lldi;
@@ -103,6 +113,117 @@ static ssize_t debugfs_read(struct file
 	return simple_read_from_buffer(buf, count, ppos, d->buf, d->pos);
 }
 
+void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe)
+{
+	struct wr_log_entry le;
+	int idx;
+
+	if (!wq->rdev->wr_log)
+		return;
+
+	idx = (atomic_inc_return(&wq->rdev->wr_log_idx) - 1) &
+		(wq->rdev->wr_log_size - 1);
+	le.poll_sge_ts = cxgb4_read_sge_timestamp(wq->rdev->lldi.ports[0]);
+	getnstimeofday(&le.poll_host_ts);
+	le.valid = 1;
+	le.cqe_sge_ts = CQE_TS(cqe);
+	if (SQ_TYPE(cqe)) {
+		le.qid = wq->sq.qid;
+		le.opcode = CQE_OPCODE(cqe);
+		le.post_host_ts = wq->sq.sw_sq[wq->sq.cidx].host_ts;
+		le.post_sge_ts = wq->sq.sw_sq[wq->sq.cidx].sge_ts;
+		le.wr_id = CQE_WRID_SQ_IDX(cqe);
+	} else {
+		le.qid = wq->rq.qid;
+		le.opcode = FW_RI_RECEIVE;
+		le.post_host_ts = wq->rq.sw_rq[wq->rq.cidx].host_ts;
+		le.post_sge_ts = wq->rq.sw_rq[wq->rq.cidx].sge_ts;
+		le.wr_id = CQE_WRID_MSN(cqe);
+	}
+	wq->rdev->wr_log[idx] = le;
+}
+
+static int wr_log_show(struct seq_file *seq, void *v)
+{
+	struct c4iw_dev *dev = seq->private;
+	struct timespec prev_ts = {0, 0};
+	struct wr_log_entry *lep;
+	int prev_ts_set = 0;
+	int idx, end;
+
+#define ts2ns(ts) div64_ul((ts) * dev->rdev.lldi.cclk_ps, 1000)
+
+	idx = atomic_read(&dev->rdev.wr_log_idx) &
+		(dev->rdev.wr_log_size - 1);
+	end = idx - 1;
+	if (end < 0)
+		end = dev->rdev.wr_log_size - 1;
+	lep = &dev->rdev.wr_log[idx];
+	while (idx != end) {
+		if (lep->valid) {
+			if (!prev_ts_set) {
+				prev_ts_set = 1;
+				prev_ts = lep->poll_host_ts;
+			}
+			seq_printf(seq, "%04u: sec %lu nsec %lu qid %u opcode "
+				   "%u %s 0x%x host_wr_delta sec %lu nsec %lu "
+				   "post_sge_ts 0x%llx cqe_sge_ts 0x%llx "
+				   "poll_sge_ts 0x%llx post_poll_delta_ns %llu "
+				   "cqe_poll_delta_ns %llu\n",
+				   idx,
+				   timespec_sub(lep->poll_host_ts,
+						prev_ts).tv_sec,
+				   timespec_sub(lep->poll_host_ts,
+						prev_ts).tv_nsec,
+				   lep->qid, lep->opcode,
+				   lep->opcode == FW_RI_RECEIVE ?
+							"msn" : "wrid",
+				   lep->wr_id,
+				   timespec_sub(lep->poll_host_ts,
+						lep->post_host_ts).tv_sec,
+				   timespec_sub(lep->poll_host_ts,
+						lep->post_host_ts).tv_nsec,
+				   lep->post_sge_ts, lep->cqe_sge_ts,
+				   lep->poll_sge_ts,
+				   ts2ns(lep->poll_sge_ts - lep->post_sge_ts),
+				   ts2ns(lep->poll_sge_ts - lep->cqe_sge_ts));
+			prev_ts = lep->poll_host_ts;
+		}
+		idx++;
+		if (idx > (dev->rdev.wr_log_size - 1))
+			idx = 0;
+		lep = &dev->rdev.wr_log[idx];
+	}
+#undef ts2ns
+	return 0;
+}
+
+static int wr_log_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wr_log_show, inode->i_private);
+}
+
+static ssize_t wr_log_clear(struct file *file, const char __user *buf,
+			    size_t count, loff_t *pos)
+{
+	struct c4iw_dev *dev = ((struct seq_file *)file->private_data)->private;
+	int i;
+
+	if (dev->rdev.wr_log)
+		for (i = 0; i < dev->rdev.wr_log_size; i++)
+			dev->rdev.wr_log[i].valid = 0;
+	return count;
+}
+
+static const struct file_operations wr_log_debugfs_fops = {
+	.owner   = THIS_MODULE,
+	.open    = wr_log_open,
+	.release = single_release,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.write   = wr_log_clear,
+};
+
 static int dump_qp(int id, void *p, void *data)
 {
 	struct c4iw_qp *qp = p;
@@ -241,12 +362,32 @@ static int dump_stag(int id, void *p, vo
 	struct c4iw_debugfs_data *stagd = data;
 	int space;
 	int cc;
+	struct fw_ri_tpte tpte;
+	int ret;
 
 	space = stagd->bufsize - stagd->pos - 1;
 	if (space == 0)
 		return 1;
 
-	cc = snprintf(stagd->buf + stagd->pos, space, "0x%x\n", id<<8);
+	ret = cxgb4_read_tpte(stagd->devp->rdev.lldi.ports[0], (u32)id<<8,
+			      (__be32 *)&tpte);
+	if (ret) {
+		dev_err(&stagd->devp->rdev.lldi.pdev->dev,
+			"%s cxgb4_read_tpte err %d\n", __func__, ret);
+		return ret;
+	}
+	cc = snprintf(stagd->buf + stagd->pos, space,
+		      "stag: idx 0x%x valid %d key 0x%x state %d pdid %d "
+		      "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
+		      (u32)id<<8,
+		      G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
+		      G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
+		      G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
+		      G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
+		      G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
+		      G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
+		      ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
+		      ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
 	if (cc < space)
 		stagd->pos += cc;
 	return 0;
@@ -259,7 +400,7 @@ static int stag_release(struct inode *in
 		printk(KERN_INFO "%s null stagd?\n", __func__);
 		return 0;
 	}
-	kfree(stagd->buf);
+	vfree(stagd->buf);
 	kfree(stagd);
 	return 0;
 }
@@ -282,8 +423,8 @@ static int stag_open(struct inode *inode
 	idr_for_each(&stagd->devp->mmidr, count_idrs, &count);
 	spin_unlock_irq(&stagd->devp->lock);
 
-	stagd->bufsize = count * sizeof("0x12345678\n");
-	stagd->buf = kmalloc(stagd->bufsize, GFP_KERNEL);
+	stagd->bufsize = count * 256;
+	stagd->buf = vmalloc(stagd->bufsize);
 	if (!stagd->buf) {
 		ret = -ENOMEM;
 		goto err1;
@@ -348,6 +489,7 @@ static int stats_show(struct seq_file *s
 		   dev->rdev.stats.act_ofld_conn_fails);
 	seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
 		   dev->rdev.stats.pas_ofld_conn_fails);
+	seq_printf(seq, "AVAILABLE IRD: %10u\n", dev->avail_ird);
 	return 0;
 }
 
@@ -583,6 +725,12 @@ static int setup_debugfs(struct c4iw_dev
 	if (de && de->d_inode)
 		de->d_inode->i_size = 4096;
 
+	if (c4iw_wr_log) {
+		de = debugfs_create_file("wr_log", S_IWUSR, devp->debugfs_root,
+					 (void *)devp, &wr_log_debugfs_fops);
+		if (de && de->d_inode)
+			de->d_inode->i_size = 4096;
+	}
 	return 0;
 }
 
@@ -696,7 +844,20 @@ static int c4iw_rdev_open(struct c4iw_rd
 		pr_err(MOD "error allocating status page\n");
 		goto err4;
 	}
+
+	if (c4iw_wr_log) {
+		rdev->wr_log = kzalloc((1 << c4iw_wr_log_size_order) *
+				       sizeof(*rdev->wr_log), GFP_KERNEL);
+		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->status_page->db_off = 0;
+
 	return 0;
 err4:
 	c4iw_rqtpool_destroy(rdev);
@@ -710,6 +871,7 @@ err1:
 
 static void c4iw_rdev_close(struct c4iw_rdev *rdev)
 {
+	kfree(rdev->wr_log);
 	free_page((unsigned long)rdev->status_page);
 	c4iw_pblpool_destroy(rdev);
 	c4iw_rqtpool_destroy(rdev);
@@ -768,6 +930,27 @@ static struct c4iw_dev *c4iw_alloc(const
 	}
 	devp->rdev.lldi = *infop;
 
+	/* init various hw-queue params based on lld info */
+	PDBG("%s: Ing. padding boundary is %d, egrsstatuspagesize = %d\n",
+	     __func__, devp->rdev.lldi.sge_ingpadboundary,
+	     devp->rdev.lldi.sge_egrstatuspagesize);
+
+	devp->rdev.hw_queue.t4_eq_status_entries =
+		devp->rdev.lldi.sge_ingpadboundary > 64 ? 2 : 1;
+	devp->rdev.hw_queue.t4_max_eq_size = 65520;
+	devp->rdev.hw_queue.t4_max_iq_size = 65520;
+	devp->rdev.hw_queue.t4_max_rq_size = 8192 -
+		devp->rdev.hw_queue.t4_eq_status_entries - 1;
+	devp->rdev.hw_queue.t4_max_sq_size =
+		devp->rdev.hw_queue.t4_max_eq_size -
+		devp->rdev.hw_queue.t4_eq_status_entries - 1;
+	devp->rdev.hw_queue.t4_max_qp_depth =
+		devp->rdev.hw_queue.t4_max_rq_size;
+	devp->rdev.hw_queue.t4_max_cq_depth =
+		devp->rdev.hw_queue.t4_max_iq_size - 2;
+	devp->rdev.hw_queue.t4_stat_len =
+		devp->rdev.lldi.sge_egrstatuspagesize;
+
 	/*
 	 * For T5 devices, we map all of BAR2 with WC.
 	 * For T4 devices with onchip qp mem, we map only that part
@@ -818,6 +1001,7 @@ static struct c4iw_dev *c4iw_alloc(const
 	mutex_init(&devp->rdev.stats.lock);
 	mutex_init(&devp->db_mutex);
 	INIT_LIST_HEAD(&devp->db_fc_list);
+	devp->avail_ird = devp->rdev.lldi.max_ird_adapter;
 
 	if (c4iw_debugfs_root) {
 		devp->debugfs_root = debugfs_create_dir(
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/ev.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/ev.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/ev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/ev.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,55 @@
 
 #include "iw_cxgb4.h"
 
+static void print_tpte(struct c4iw_dev *dev, u32 stag)
+{
+	int ret;
+	struct fw_ri_tpte tpte;
+
+	ret = cxgb4_read_tpte(dev->rdev.lldi.ports[0], stag,
+			      (__be32 *)&tpte);
+	if (ret) {
+		dev_err(&dev->rdev.lldi.pdev->dev,
+			"%s cxgb4_read_tpte err %d\n", __func__, ret);
+		return;
+	}
+	PDBG("stag idx 0x%x valid %d key 0x%x state %d pdid %d "
+	       "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
+	       stag & 0xffffff00,
+	       G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
+	       G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
+	       G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
+	       G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
+	       G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
+	       G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
+	       ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
+	       ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
+}
+
+static void dump_err_cqe(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
+{
+	__be64 *p = (void *)err_cqe;
+
+	dev_err(&dev->rdev.lldi.pdev->dev,
+		"AE qpid %d opcode %d status 0x%x "
+		"type %d len 0x%x wrid.hi 0x%x wrid.lo 0x%x\n",
+		CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
+		CQE_STATUS(err_cqe), CQE_TYPE(err_cqe), ntohl(err_cqe->len),
+		CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
+
+	PDBG("%016llx %016llx %016llx %016llx\n",
+	     be64_to_cpu(p[0]), be64_to_cpu(p[1]), be64_to_cpu(p[2]),
+	     be64_to_cpu(p[3]));
+
+	/*
+	 * Ingress WRITE and READ_RESP errors provide
+	 * the offending stag, so parse and log it.
+	 */
+	if (RQ_TYPE(err_cqe) && (CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE ||
+				 CQE_OPCODE(err_cqe) == FW_RI_READ_RESP))
+		print_tpte(dev, CQE_WRID_STAG(err_cqe));
+}
+
 static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
 			  struct c4iw_qp *qhp,
 			  struct t4_cqe *err_cqe,
@@ -44,11 +93,7 @@ static void post_qp_event(struct c4iw_de
 	struct c4iw_qp_attributes attrs;
 	unsigned long flag;
 
-	printk(KERN_ERR MOD "AE qpid 0x%x opcode %d status 0x%x "
-	       "type %d wrid.hi 0x%x wrid.lo 0x%x\n",
-	       CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
-	       CQE_STATUS(err_cqe), CQE_TYPE(err_cqe),
-	       CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
+	dump_err_cqe(dev, err_cqe);
 
 	if (qhp->attr.state == C4IW_QP_STATE_RTS) {
 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
@@ -182,6 +227,7 @@ int c4iw_ev_handler(struct c4iw_dev *dev
 
 	chp = get_chp(dev, qid);
 	if (chp) {
+		t4_clear_cq_armed(&chp->cq);
 		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2014-09-28 17:29:07.000000000 -0400
@@ -139,6 +139,29 @@ struct c4iw_stats {
 	u64  pas_ofld_conn_fails;
 };
 
+struct c4iw_hw_queue {
+	int t4_eq_status_entries;
+	int t4_max_eq_size;
+	int t4_max_iq_size;
+	int t4_max_rq_size;
+	int t4_max_sq_size;
+	int t4_max_qp_depth;
+	int t4_max_cq_depth;
+	int t4_stat_len;
+};
+
+struct wr_log_entry {
+	struct timespec post_host_ts;
+	struct timespec poll_host_ts;
+	u64 post_sge_ts;
+	u64 cqe_sge_ts;
+	u64 poll_sge_ts;
+	u16 qid;
+	u16 wr_id;
+	u8 opcode;
+	u8 valid;
+};
+
 struct c4iw_rdev {
 	struct c4iw_resource resource;
 	unsigned long qpshift;
@@ -156,7 +179,11 @@ struct c4iw_rdev {
 	unsigned long oc_mw_pa;
 	void __iomem *oc_mw_kva;
 	struct c4iw_stats stats;
+	struct c4iw_hw_queue hw_queue;
 	struct t4_dev_status_page *status_page;
+	atomic_t wr_log_idx;
+	struct wr_log_entry *wr_log;
+	int wr_log_size;
 };
 
 static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -166,7 +193,7 @@ static inline int c4iw_fatal_error(struc
 
 static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
 {
-	return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5));
+	return (int)(rdev->lldi.vr->stag.size >> 5);
 }
 
 #define C4IW_WR_TO (30*HZ)
@@ -237,6 +264,7 @@ struct c4iw_dev {
 	struct idr atid_idr;
 	struct idr stid_idr;
 	struct list_head db_fc_list;
+	u32 avail_ird;
 };
 
 static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
@@ -318,6 +346,13 @@ static inline void remove_handle_nolock(
 	_remove_handle(rhp, idr, id, 0);
 }
 
+extern uint c4iw_max_read_depth;
+
+static inline int cur_max_read_depth(struct c4iw_dev *dev)
+{
+	return min(dev->rdev.lldi.max_ordird_qp, c4iw_max_read_depth);
+}
+
 struct c4iw_pd {
 	struct ib_pd ibpd;
 	u32 pdid;
@@ -991,7 +1026,8 @@ void c4iw_ev_dispatch(struct c4iw_dev *d
 
 extern struct cxgb4_client t4c_client;
 extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
-extern int c4iw_max_read_depth;
+extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe);
+extern int c4iw_wr_log;
 extern int db_fc_threshold;
 extern int db_coalescing_threshold;
 extern int use_dsgl;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/provider.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/provider.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/provider.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/provider.c	2014-09-28 17:29:07.000000000 -0400
@@ -318,14 +318,16 @@ static int c4iw_query_device(struct ib_d
 	props->vendor_id = (u32)dev->rdev.lldi.pdev->vendor;
 	props->vendor_part_id = (u32)dev->rdev.lldi.pdev->device;
 	props->max_mr_size = T4_MAX_MR_SIZE;
-	props->max_qp = T4_MAX_NUM_QP;
-	props->max_qp_wr = T4_MAX_QP_DEPTH;
+	props->max_qp = dev->rdev.lldi.vr->qp.size / 2;
+	props->max_qp_wr = dev->rdev.hw_queue.t4_max_qp_depth;
 	props->max_sge = T4_MAX_RECV_SGE;
 	props->max_sge_rd = 1;
-	props->max_qp_rd_atom = c4iw_max_read_depth;
-	props->max_qp_init_rd_atom = c4iw_max_read_depth;
-	props->max_cq = T4_MAX_NUM_CQ;
-	props->max_cqe = T4_MAX_CQ_DEPTH;
+	props->max_res_rd_atom = dev->rdev.lldi.max_ird_adapter;
+	props->max_qp_rd_atom = min(dev->rdev.lldi.max_ordird_qp,
+				    c4iw_max_read_depth);
+	props->max_qp_init_rd_atom = props->max_qp_rd_atom;
+	props->max_cq = dev->rdev.lldi.vr->qp.size;
+	props->max_cqe = dev->rdev.hw_queue.t4_max_cq_depth;
 	props->max_mr = c4iw_num_stags(&dev->rdev);
 	props->max_pd = T4_MAX_NUM_PD;
 	props->local_ca_ack_delay = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/qp.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/qp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/qp.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,6 +58,31 @@ static int max_fr_immd = T4_MAX_FR_IMMD;
 module_param(max_fr_immd, int, 0644);
 MODULE_PARM_DESC(max_fr_immd, "fastreg threshold for using DSGL instead of immedate");
 
+static int alloc_ird(struct c4iw_dev *dev, u32 ird)
+{
+	int ret = 0;
+
+	spin_lock_irq(&dev->lock);
+	if (ird <= dev->avail_ird)
+		dev->avail_ird -= ird;
+	else
+		ret = -ENOMEM;
+	spin_unlock_irq(&dev->lock);
+
+	if (ret)
+		dev_warn(&dev->rdev.lldi.pdev->dev,
+			 "device IRD resources exhausted\n");
+
+	return ret;
+}
+
+static void free_ird(struct c4iw_dev *dev, int ird)
+{
+	spin_lock_irq(&dev->lock);
+	dev->avail_ird += ird;
+	spin_unlock_irq(&dev->lock);
+}
+
 static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
 {
 	unsigned long flag;
@@ -180,9 +205,9 @@ static int create_qp(struct c4iw_rdev *r
 	}
 
 	/*
-	 * RQT must be a power of 2.
+	 * RQT must be a power of 2 and at least 16 deep.
 	 */
-	wq->rq.rqt_size = roundup_pow_of_two(wq->rq.size);
+	wq->rq.rqt_size = roundup_pow_of_two(max_t(u16, wq->rq.size, 16));
 	wq->rq.rqt_hwaddr = c4iw_rqtpool_alloc(rdev, wq->rq.rqt_size);
 	if (!wq->rq.rqt_hwaddr) {
 		ret = -ENOMEM;
@@ -258,7 +283,8 @@ static int create_qp(struct c4iw_rdev *r
 	/*
 	 * eqsize is the number of 64B entries plus the status page size.
 	 */
-	eqsize = wq->sq.size * T4_SQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+	eqsize = wq->sq.size * T4_SQ_NUM_SLOTS +
+		rdev->hw_queue.t4_eq_status_entries;
 
 	res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
 		V_FW_RI_RES_WR_HOSTFCMODE(0) |	/* no host cidx updates */
@@ -283,7 +309,8 @@ static int create_qp(struct c4iw_rdev *r
 	/*
 	 * eqsize is the number of 64B entries plus the status page size.
 	 */
-	eqsize = wq->rq.size * T4_RQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+	eqsize = wq->rq.size * T4_RQ_NUM_SLOTS +
+		rdev->hw_queue.t4_eq_status_entries;
 	res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
 		V_FW_RI_RES_WR_HOSTFCMODE(0) |	/* no host cidx updates */
 		V_FW_RI_RES_WR_CPRIO(0) |	/* don't keep in chip cache */
@@ -796,6 +823,11 @@ int c4iw_post_send(struct ib_qp *ibqp, s
 				  qhp->sq_sig_all;
 		swsqe->flushed = 0;
 		swsqe->wr_id = wr->wr_id;
+		if (c4iw_wr_log) {
+			swsqe->sge_ts = cxgb4_read_sge_timestamp(
+					qhp->rhp->rdev.lldi.ports[0]);
+			getnstimeofday(&swsqe->host_ts);
+		}
 
 		init_wr_hdr(wqe, qhp->wq.sq.pidx, fw_opcode, fw_flags, len16);
 
@@ -859,6 +891,13 @@ int c4iw_post_receive(struct ib_qp *ibqp
 		}
 
 		qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].wr_id = wr->wr_id;
+		if (c4iw_wr_log) {
+			qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].sge_ts =
+				cxgb4_read_sge_timestamp(
+						qhp->rhp->rdev.lldi.ports[0]);
+			getnstimeofday(
+				&qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].host_ts);
+		}
 
 		wqe->recv.opcode = FW_RI_RECV_WR;
 		wqe->recv.r1 = 0;
@@ -1066,7 +1105,7 @@ static void __flush_qp(struct c4iw_qp *q
 		       struct c4iw_cq *schp)
 {
 	int count;
-	int flushed;
+	int rq_flushed, sq_flushed;
 	unsigned long flag;
 
 	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
@@ -1084,27 +1123,40 @@ static void __flush_qp(struct c4iw_qp *q
 
 	c4iw_flush_hw_cq(rchp);
 	c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
-	flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
+	rq_flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, flag);
-	if (flushed) {
-		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
-		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
-		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
-	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, flag);
 	spin_lock(&qhp->lock);
 	if (schp != rchp)
 		c4iw_flush_hw_cq(schp);
-	flushed = c4iw_flush_sq(qhp);
+	sq_flushed = c4iw_flush_sq(qhp);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, flag);
-	if (flushed) {
-		spin_lock_irqsave(&schp->comp_handler_lock, flag);
-		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
-		spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+
+	if (schp == rchp) {
+		if (t4_clear_cq_armed(&rchp->cq) &&
+		    (rq_flushed || sq_flushed)) {
+			spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+			(*rchp->ibcq.comp_handler)(&rchp->ibcq,
+						   rchp->ibcq.cq_context);
+			spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+		}
+	} else {
+		if (t4_clear_cq_armed(&rchp->cq) && rq_flushed) {
+			spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+			(*rchp->ibcq.comp_handler)(&rchp->ibcq,
+						   rchp->ibcq.cq_context);
+			spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+		}
+		if (t4_clear_cq_armed(&schp->cq) && sq_flushed) {
+			spin_lock_irqsave(&schp->comp_handler_lock, flag);
+			(*schp->ibcq.comp_handler)(&schp->ibcq,
+						   schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+		}
 	}
 }
 
@@ -1202,12 +1254,20 @@ static int rdma_init(struct c4iw_dev *rh
 	int ret;
 	struct sk_buff *skb;
 
-	PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
-	     qhp->ep->hwtid);
+	PDBG("%s qhp %p qid 0x%x tid %u ird %u ord %u\n", __func__, qhp,
+	     qhp->wq.sq.qid, qhp->ep->hwtid, qhp->ep->ird, qhp->ep->ord);
 
 	skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
+	if (!skb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	ret = alloc_ird(rhp, qhp->attr.max_ird);
+	if (ret) {
+		qhp->attr.max_ird = 0;
+		kfree_skb(skb);
+		goto out;
+	}
 	set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
 
 	wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
@@ -1258,10 +1318,14 @@ static int rdma_init(struct c4iw_dev *rh
 
 	ret = c4iw_ofld_send(&rhp->rdev, skb);
 	if (ret)
-		goto out;
+		goto err1;
 
 	ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
 				  qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
+	if (!ret)
+		goto out;
+err1:
+	free_ird(rhp, qhp->attr.max_ird);
 out:
 	PDBG("%s ret %d\n", __func__, ret);
 	return ret;
@@ -1306,7 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp,
 			newattr.max_ord = attrs->max_ord;
 		}
 		if (mask & C4IW_QP_ATTR_MAX_IRD) {
-			if (attrs->max_ird > c4iw_max_read_depth) {
+			if (attrs->max_ird > cur_max_read_depth(rhp)) {
 				ret = -EINVAL;
 				goto out;
 			}
@@ -1529,6 +1593,7 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 	if (!list_empty(&qhp->db_fc_entry))
 		list_del_init(&qhp->db_fc_entry);
 	spin_unlock_irq(&rhp->lock);
+	free_ird(rhp, qhp->attr.max_ird);
 
 	ucontext = ib_qp->uobject ?
 		   to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
@@ -1569,13 +1634,17 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 	if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
 		return ERR_PTR(-EINVAL);
 
-	rqsize = roundup(attrs->cap.max_recv_wr + 1, 16);
-	if (rqsize > T4_MAX_RQ_SIZE)
+	if (attrs->cap.max_recv_wr > rhp->rdev.hw_queue.t4_max_rq_size)
 		return ERR_PTR(-E2BIG);
+	rqsize = attrs->cap.max_recv_wr + 1;
+	if (rqsize < 8)
+		rqsize = 8;
 
-	sqsize = roundup(attrs->cap.max_send_wr + 1, 16);
-	if (sqsize > T4_MAX_SQ_SIZE)
+	if (attrs->cap.max_send_wr > rhp->rdev.hw_queue.t4_max_sq_size)
 		return ERR_PTR(-E2BIG);
+	sqsize = attrs->cap.max_send_wr + 1;
+	if (sqsize < 8)
+		sqsize = 8;
 
 	ucontext = pd->uobject ? to_c4iw_ucontext(pd->uobject->context) : NULL;
 
@@ -1583,19 +1652,20 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 	if (!qhp)
 		return ERR_PTR(-ENOMEM);
 	qhp->wq.sq.size = sqsize;
-	qhp->wq.sq.memsize = (sqsize + 1) * sizeof *qhp->wq.sq.queue;
+	qhp->wq.sq.memsize =
+		(sqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+		sizeof(*qhp->wq.sq.queue) + 16 * sizeof(__be64);
 	qhp->wq.sq.flush_cidx = -1;
 	qhp->wq.rq.size = rqsize;
-	qhp->wq.rq.memsize = (rqsize + 1) * sizeof *qhp->wq.rq.queue;
+	qhp->wq.rq.memsize =
+		(rqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+		sizeof(*qhp->wq.rq.queue);
 
 	if (ucontext) {
 		qhp->wq.sq.memsize = roundup(qhp->wq.sq.memsize, PAGE_SIZE);
 		qhp->wq.rq.memsize = roundup(qhp->wq.rq.memsize, PAGE_SIZE);
 	}
 
-	PDBG("%s sqsize %u sqmemsize %zu rqsize %u rqmemsize %zu\n",
-	     __func__, sqsize, qhp->wq.sq.memsize, rqsize, qhp->wq.rq.memsize);
-
 	ret = create_qp(&rhp->rdev, &qhp->wq, &schp->cq, &rchp->cq,
 			ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
 	if (ret)
@@ -1619,8 +1689,8 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 	qhp->attr.enable_rdma_read = 1;
 	qhp->attr.enable_rdma_write = 1;
 	qhp->attr.enable_bind = 1;
-	qhp->attr.max_ord = 1;
-	qhp->attr.max_ird = 1;
+	qhp->attr.max_ord = 0;
+	qhp->attr.max_ird = 0;
 	qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
 	spin_lock_init(&qhp->lock);
 	mutex_init(&qhp->mutex);
@@ -1714,9 +1784,11 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 	qhp->ibqp.qp_num = qhp->wq.sq.qid;
 	init_timer(&(qhp->timer));
 	INIT_LIST_HEAD(&qhp->db_fc_entry);
-	PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n",
-	     __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
-	     qhp->wq.sq.qid);
+	PDBG("%s sq id %u size %u memsize %zu num_entries %u "
+	     "rq id %u size %u memsize %zu num_entries %u\n", __func__,
+	     qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
+	     attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
+	     qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
 	return &qhp->ibqp;
 err8:
 	kfree(mm5);
@@ -1804,5 +1876,11 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp,
 	memset(attr, 0, sizeof *attr);
 	memset(init_attr, 0, sizeof *init_attr);
 	attr->qp_state = to_ib_qp_state(qhp->attr.state);
+	init_attr->cap.max_send_wr = qhp->attr.sq_num_entries;
+	init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries;
+	init_attr->cap.max_send_sge = qhp->attr.sq_max_sges;
+	init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges;
+	init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE;
+	init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h	2014-09-28 17:29:07.000000000 -0400
@@ -849,6 +849,5 @@ enum {                     /* TCP conges
 #define G_CONG_CNTRL(x) (((x) >> S_CONG_CNTRL) & M_CONG_CNTRL)
 
 #define CONG_CNTRL_VALID   (1 << 18)
-#define T5_OPT_2_VALID       (1 << 31)
 
 #endif /* _T4FW_RI_API_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/t4.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/t4.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/cxgb4/t4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/cxgb4/t4.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,22 +36,11 @@
 #include "t4_msg.h"
 #include "t4fw_ri_api.h"
 
-#define T4_MAX_NUM_QP 65536
-#define T4_MAX_NUM_CQ 65536
 #define T4_MAX_NUM_PD 65536
-#define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
-#define T4_MAX_EQ_SIZE (65520 - T4_EQ_STATUS_ENTRIES)
-#define T4_MAX_IQ_SIZE (65520 - 1)
-#define T4_MAX_RQ_SIZE (8192 - T4_EQ_STATUS_ENTRIES)
-#define T4_MAX_SQ_SIZE (T4_MAX_EQ_SIZE - 1)
-#define T4_MAX_QP_DEPTH (T4_MAX_RQ_SIZE - 1)
-#define T4_MAX_CQ_DEPTH (T4_MAX_IQ_SIZE - 1)
-#define T4_MAX_NUM_STAG (1<<15)
 #define T4_MAX_MR_SIZE (~0ULL)
 #define T4_PAGESIZE_MASK 0xffff000  /* 4KB-128MB */
 #define T4_STAG_UNSET 0xffffffff
 #define T4_FW_MAJ 0
-#define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
 #define A_PCIE_MA_SYNC 0x30b4
 
 struct t4_status_page {
@@ -244,8 +233,8 @@ struct t4_cqe {
 #define CQE_WRID_SQ_IDX(x)	((x)->u.scqe.cidx)
 
 /* generic accessor macros */
-#define CQE_WRID_HI(x)		((x)->u.gen.wrid_hi)
-#define CQE_WRID_LOW(x)		((x)->u.gen.wrid_low)
+#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))
 
 /* macros for flit 3 of the cqe */
 #define S_CQE_GENBIT	63
@@ -277,6 +266,8 @@ struct t4_swsqe {
 	int			signaled;
 	u16			idx;
 	int                     flushed;
+	struct timespec         host_ts;
+	u64                     sge_ts;
 };
 
 static inline pgprot_t t4_pgprot_wc(pgprot_t prot)
@@ -314,6 +305,8 @@ struct t4_sq {
 
 struct t4_swrqe {
 	u64 wr_id;
+	struct timespec host_ts;
+	u64 sge_ts;
 };
 
 struct t4_rq {
@@ -531,6 +524,10 @@ static inline int t4_wq_db_enabled(struc
 	return !wq->rq.queue[wq->rq.size].status.db_off;
 }
 
+enum t4_cq_flags {
+	CQ_ARMED	= 1,
+};
+
 struct t4_cq {
 	struct t4_cqe *queue;
 	dma_addr_t dma_addr;
@@ -551,12 +548,19 @@ struct t4_cq {
 	u16 cidx_inc;
 	u8 gen;
 	u8 error;
+	unsigned long flags;
 };
 
+static inline int t4_clear_cq_armed(struct t4_cq *cq)
+{
+	return test_and_clear_bit(CQ_ARMED, &cq->flags);
+}
+
 static inline int t4_arm_cq(struct t4_cq *cq, int se)
 {
 	u32 val;
 
+	set_bit(CQ_ARMED, &cq->flags);
 	while (cq->cidx_inc > CIDXINC_MASK) {
 		val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) |
 		      INGRESSQID(cq->cqid);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ipath/ipath_mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ipath/ipath_mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ipath/ipath_mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ipath/ipath_mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -726,7 +726,7 @@ bail:
  * @dd: the infinipath device
  * @pkeys: the PKEY table
  */
-static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys)
+static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys, u8 port)
 {
 	struct ipath_portdata *pd;
 	int i;
@@ -759,6 +759,7 @@ static int set_pkeys(struct ipath_devdat
 	}
 	if (changed) {
 		u64 pkey;
+		struct ib_event event;
 
 		pkey = (u64) dd->ipath_pkeys[0] |
 			((u64) dd->ipath_pkeys[1] << 16) |
@@ -768,12 +769,17 @@ static int set_pkeys(struct ipath_devdat
 			   (unsigned long long) pkey);
 		ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
 				 pkey);
+
+		event.event = IB_EVENT_PKEY_CHANGE;
+		event.device = &dd->verbs_dev->ibdev;
+		event.element.port_num = port;
+		ib_dispatch_event(&event);
 	}
 	return 0;
 }
 
 static int recv_subn_set_pkeytable(struct ib_smp *smp,
-				   struct ib_device *ibdev)
+				   struct ib_device *ibdev, u8 port)
 {
 	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
 	__be16 *p = (__be16 *) smp->data;
@@ -784,7 +790,7 @@ static int recv_subn_set_pkeytable(struc
 	for (i = 0; i < n; i++)
 		q[i] = be16_to_cpu(p[i]);
 
-	if (startpx != 0 || set_pkeys(dev->dd, q) != 0)
+	if (startpx != 0 || set_pkeys(dev->dd, q, port) != 0)
 		smp->status |= IB_SMP_INVALID_FIELD;
 
 	return recv_subn_get_pkeytable(smp, ibdev);
@@ -1342,7 +1348,7 @@ static int process_subn(struct ib_device
 			ret = recv_subn_set_portinfo(smp, ibdev, port_num);
 			goto bail;
 		case IB_SMP_ATTR_PKEY_TABLE:
-			ret = recv_subn_set_pkeytable(smp, ibdev);
+			ret = recv_subn_set_pkeytable(smp, ibdev, port_num);
 			goto bail;
 		case IB_SMP_ATTR_SM_INFO:
 			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ static void __ipath_release_user_pages(s
 
 /* call with current->mm->mmap_sem held */
 static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
-				  struct page **p, struct vm_area_struct **vma)
+				  struct page **p)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -74,7 +74,7 @@ static int __ipath_get_user_pages(unsign
 		ret = get_user_pages(current, current->mm,
 				     start_page + got * PAGE_SIZE,
 				     num_pages - got, 1, 1,
-				     p + got, vma);
+				     p + got, NULL);
 		if (ret < 0)
 			goto bail_release;
 	}
@@ -165,7 +165,7 @@ int ipath_get_user_pages(unsigned long s
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __ipath_get_user_pages(start_page, num_pages, p, NULL);
+	ret = __ipath_get_user_pages(start_page, num_pages, p);
 
 	up_write(&current->mm->mmap_sem);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -891,7 +891,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev
 				agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
 							      q ? IB_QPT_GSI : IB_QPT_SMI,
 							      NULL, 0, send_handler,
-							      NULL, NULL);
+							      NULL, NULL, 0);
 				if (IS_ERR(agent)) {
 					ret = PTR_ERR(agent);
 					goto err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,7 @@
 
 #define MLX4_IB_FLOW_MAX_PRIO 0xFFF
 #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF
+#define MLX4_IB_CARD_REV_A0   0xA0
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
@@ -119,6 +120,17 @@ static int check_flow_steering_support(s
 	return dmfs;
 }
 
+static int num_ib_ports(struct mlx4_dev *dev)
+{
+	int ib_ports = 0;
+	int i;
+
+	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+		ib_ports++;
+
+	return ib_ports;
+}
+
 static int mlx4_ib_query_device(struct ib_device *ibdev,
 				struct ib_device_attr *props)
 {
@@ -126,6 +138,7 @@ static int mlx4_ib_query_device(struct i
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
+	int have_ib_ports;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -142,6 +155,8 @@ static int mlx4_ib_query_device(struct i
 
 	memset(props, 0, sizeof *props);
 
+	have_ib_ports = num_ib_ports(dev->dev);
+
 	props->fw_ver = dev->dev->caps.fw_ver;
 	props->device_cap_flags    = IB_DEVICE_CHANGE_PHY_PORT |
 		IB_DEVICE_PORT_ACTIVE_EVENT		|
@@ -152,13 +167,15 @@ static int mlx4_ib_query_device(struct i
 		props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
 	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR)
 		props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
-	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM)
+	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM && have_ib_ports)
 		props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
 	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT)
 		props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
 	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
 		props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
-	if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH)
+	if (dev->dev->caps.max_gso_sz &&
+	    (dev->dev->rev_id != MLX4_IB_CARD_REV_A0) &&
+	    (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH))
 		props->device_cap_flags |= IB_DEVICE_UD_TSO;
 	if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
 		props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
@@ -357,7 +374,7 @@ static int eth_link_query_port(struct ib
 	props->state		= IB_PORT_DOWN;
 	props->phys_state	= state_to_phys_state(props->state);
 	props->active_mtu	= IB_MTU_256;
-	spin_lock(&iboe->lock);
+	spin_lock_bh(&iboe->lock);
 	ndev = iboe->netdevs[port - 1];
 	if (!ndev)
 		goto out_unlock;
@@ -369,7 +386,7 @@ static int eth_link_query_port(struct ib
 					IB_PORT_ACTIVE : IB_PORT_DOWN;
 	props->phys_state	= state_to_phys_state(props->state);
 out_unlock:
-	spin_unlock(&iboe->lock);
+	spin_unlock_bh(&iboe->lock);
 out:
 	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
 	return err;
@@ -811,11 +828,11 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *m
 	if (!mqp->port)
 		return 0;
 
-	spin_lock(&mdev->iboe.lock);
+	spin_lock_bh(&mdev->iboe.lock);
 	ndev = mdev->iboe.netdevs[mqp->port - 1];
 	if (ndev)
 		dev_hold(ndev);
-	spin_unlock(&mdev->iboe.lock);
+	spin_unlock_bh(&mdev->iboe.lock);
 
 	if (ndev) {
 		ret = 1;
@@ -910,8 +927,7 @@ static int __mlx4_ib_default_rules_match
 	const struct default_rules *pdefault_rules = default_table;
 	u8 link_layer = rdma_port_get_link_layer(qp->device, flow_attr->port);
 
-	for (i = 0; i < sizeof(default_table)/sizeof(default_table[0]); i++,
-	     pdefault_rules++) {
+	for (i = 0; i < ARRAY_SIZE(default_table); i++, pdefault_rules++) {
 		__u32 field_types[IB_FLOW_SPEC_SUPPORT_LAYERS];
 		memset(&field_types, 0, sizeof(field_types));
 
@@ -965,8 +981,7 @@ static int __mlx4_ib_create_default_rule
 	int size = 0;
 	int i;
 
-	for (i = 0; i < sizeof(pdefault_rules->rules_create_list)/
-			sizeof(pdefault_rules->rules_create_list[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
 		int ret;
 		union ib_flow_spec ib_spec;
 		switch (pdefault_rules->rules_create_list[i]) {
@@ -1091,6 +1106,30 @@ static int __mlx4_ib_destroy_flow(struct
 	return err;
 }
 
+static int mlx4_ib_tunnel_steer_add(struct ib_qp *qp, struct ib_flow_attr *flow_attr,
+				    u64 *reg_id)
+{
+	void *ib_flow;
+	union ib_flow_spec *ib_spec;
+	struct mlx4_dev	*dev = to_mdev(qp->device)->dev;
+	int err = 0;
+
+	if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
+		return 0; /* do nothing */
+
+	ib_flow = flow_attr + 1;
+	ib_spec = (union ib_flow_spec *)ib_flow;
+
+	if (ib_spec->type !=  IB_FLOW_SPEC_ETH || flow_attr->num_of_specs != 1)
+		return 0; /* do nothing */
+
+	err = mlx4_tunnel_steer_add(to_mdev(qp->device)->dev, ib_spec->eth.val.dst_mac,
+				    flow_attr->port, qp->qp_num,
+				    MLX4_DOMAIN_UVERBS | (flow_attr->priority & 0xff),
+				    reg_id);
+	return err;
+}
+
 static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
 				    struct ib_flow_attr *flow_attr,
 				    int domain)
@@ -1138,6 +1177,12 @@ static struct ib_flow *mlx4_ib_create_fl
 		i++;
 	}
 
+	if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
+		err = mlx4_ib_tunnel_steer_add(qp, flow_attr, &mflow->reg_id[i]);
+		if (err)
+			goto err_free;
+	}
+
 	return &mflow->ibflow;
 
 err_free:
@@ -1264,11 +1309,11 @@ static int mlx4_ib_mcg_detach(struct ib_
 	mutex_lock(&mqp->mutex);
 	ge = find_gid_entry(mqp, gid->raw);
 	if (ge) {
-		spin_lock(&mdev->iboe.lock);
+		spin_lock_bh(&mdev->iboe.lock);
 		ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL;
 		if (ndev)
 			dev_hold(ndev);
-		spin_unlock(&mdev->iboe.lock);
+		spin_unlock_bh(&mdev->iboe.lock);
 		if (ndev)
 			dev_put(ndev);
 		list_del(&ge->list);
@@ -1389,6 +1434,9 @@ static void update_gids_task(struct work
 	int err;
 	struct mlx4_dev	*dev = gw->dev->dev;
 
+	if (!gw->dev->ib_active)
+		return;
+
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox)) {
 		pr_warn("update gid table failed %ld\n", PTR_ERR(mailbox));
@@ -1419,6 +1467,9 @@ static void reset_gids_task(struct work_
 	int err;
 	struct mlx4_dev	*dev = gw->dev->dev;
 
+	if (!gw->dev->ib_active)
+		return;
+
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox)) {
 		pr_warn("reset gid table failed\n");
@@ -1553,7 +1604,7 @@ static int mlx4_ib_addr_event(int event,
 		return 0;
 
 	iboe = &ibdev->iboe;
-	spin_lock(&iboe->lock);
+	spin_lock_bh(&iboe->lock);
 
 	for (port = 1; port <= ibdev->dev->caps.num_ports; ++port)
 		if ((netif_is_bond_master(real_dev) &&
@@ -1563,7 +1614,7 @@ static int mlx4_ib_addr_event(int event,
 			update_gid_table(ibdev, port, gid,
 					 event == NETDEV_DOWN, 0);
 
-	spin_unlock(&iboe->lock);
+	spin_unlock_bh(&iboe->lock);
 	return 0;
 
 }
@@ -1636,13 +1687,21 @@ static void mlx4_ib_update_qps(struct ml
 	new_smac = mlx4_mac_to_u64(dev->dev_addr);
 	read_unlock(&dev_base_lock);
 
+	atomic64_set(&ibdev->iboe.mac[port - 1], new_smac);
+
+	/* no need for update QP1 and mac registration in non-SRIOV */
+	if (!mlx4_is_mfunc(ibdev->dev))
+		return;
+
 	mutex_lock(&ibdev->qp1_proxy_lock[port - 1]);
 	qp = ibdev->qp1_proxy[port - 1];
 	if (qp) {
 		int new_smac_index;
-		u64 old_smac = qp->pri.smac;
+		u64 old_smac;
 		struct mlx4_update_qp_params update_params;
 
+		mutex_lock(&qp->mutex);
+		old_smac = qp->pri.smac;
 		if (new_smac == old_smac)
 			goto unlock;
 
@@ -1652,22 +1711,25 @@ static void mlx4_ib_update_qps(struct ml
 			goto unlock;
 
 		update_params.smac_index = new_smac_index;
-		if (mlx4_update_qp(ibdev->dev, &qp->mqp, MLX4_UPDATE_QP_SMAC,
+		if (mlx4_update_qp(ibdev->dev, qp->mqp.qpn, MLX4_UPDATE_QP_SMAC,
 				   &update_params)) {
 			release_mac = new_smac;
 			goto unlock;
 		}
-
+		/* if old port was zero, no mac was yet registered for this QP */
+		if (qp->pri.smac_port)
+			release_mac = old_smac;
 		qp->pri.smac = new_smac;
+		qp->pri.smac_port = port;
 		qp->pri.smac_index = new_smac_index;
-
-		release_mac = old_smac;
 	}
 
 unlock:
-	mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]);
 	if (release_mac != MLX4_IB_INVALID_MAC)
 		mlx4_unregister_mac(ibdev->dev, port, release_mac);
+	if (qp)
+		mutex_unlock(&qp->mutex);
+	mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]);
 }
 
 static void mlx4_ib_get_dev_addr(struct net_device *dev,
@@ -1678,6 +1740,7 @@ static void mlx4_ib_get_dev_addr(struct
 	struct inet6_dev *in6_dev;
 	union ib_gid  *pgid;
 	struct inet6_ifaddr *ifp;
+	union ib_gid default_gid;
 #endif
 	union ib_gid gid;
 
@@ -1698,12 +1761,15 @@ static void mlx4_ib_get_dev_addr(struct
 		in_dev_put(in_dev);
 	}
 #if IS_ENABLED(CONFIG_IPV6)
+	mlx4_make_default_gid(dev, &default_gid);
 	/* IPv6 gids */
 	in6_dev = in6_dev_get(dev);
 	if (in6_dev) {
 		read_lock_bh(&in6_dev->lock);
 		list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
 			pgid = (union ib_gid *)&ifp->addr;
+			if (!memcmp(pgid, &default_gid, sizeof(*pgid)))
+				continue;
 			update_gid_table(ibdev, port, pgid, 0, 0);
 		}
 		read_unlock_bh(&in6_dev->lock);
@@ -1725,24 +1791,33 @@ static int mlx4_ib_init_gid_table(struct
 	struct	net_device *dev;
 	struct mlx4_ib_iboe *iboe = &ibdev->iboe;
 	int i;
+	int err = 0;
 
-	for (i = 1; i <= ibdev->num_ports; ++i)
-		if (reset_gid_table(ibdev, i))
-			return -1;
+	for (i = 1; i <= ibdev->num_ports; ++i) {
+		if (rdma_port_get_link_layer(&ibdev->ib_dev, i) ==
+		    IB_LINK_LAYER_ETHERNET) {
+			err = reset_gid_table(ibdev, i);
+			if (err)
+				goto out;
+		}
+	}
 
 	read_lock(&dev_base_lock);
-	spin_lock(&iboe->lock);
+	spin_lock_bh(&iboe->lock);
 
 	for_each_netdev(&init_net, dev) {
 		u8 port = mlx4_ib_get_dev_port(dev, ibdev);
-		if (port)
+		/* port will be non-zero only for ETH ports */
+		if (port) {
+			mlx4_ib_set_default_gid(ibdev, dev, port);
 			mlx4_ib_get_dev_addr(dev, ibdev, port);
+		}
 	}
 
-	spin_unlock(&iboe->lock);
+	spin_unlock_bh(&iboe->lock);
 	read_unlock(&dev_base_lock);
-
-	return 0;
+out:
+	return err;
 }
 
 static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev,
@@ -1756,7 +1831,7 @@ static void mlx4_ib_scan_netdevs(struct
 
 	iboe = &ibdev->iboe;
 
-	spin_lock(&iboe->lock);
+	spin_lock_bh(&iboe->lock);
 	mlx4_foreach_ib_transport_port(port, ibdev->dev) {
 		enum ib_port_state	port_state = IB_PORT_NOP;
 		struct net_device *old_master = iboe->masters[port - 1];
@@ -1788,35 +1863,47 @@ static void mlx4_ib_scan_netdevs(struct
 			port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ?
 						IB_PORT_ACTIVE : IB_PORT_DOWN;
 			mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
-		} else {
-			reset_gid_table(ibdev, port);
-		}
-		/* if using bonding/team and a slave port is down, we don't the bond IP
-		 * based gids in the table since flows that select port by gid may get
-		 * the down port.
-		 */
-		if (curr_master && (port_state == IB_PORT_DOWN)) {
-			reset_gid_table(ibdev, port);
-			mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
-		}
-		/* if bonding is used it is possible that we add it to masters
-		 * only after IP address is assigned to the net bonding
-		 * interface.
-		*/
-		if (curr_master && (old_master != curr_master)) {
-			reset_gid_table(ibdev, port);
-			mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
-			mlx4_ib_get_dev_addr(curr_master, ibdev, port);
-		}
+			if (curr_master) {
+				/* if using bonding/team and a slave port is down, we
+				 * don't want the bond IP based gids in the table since
+				 * flows that select port by gid may get the down port.
+				*/
+				if (port_state == IB_PORT_DOWN) {
+					reset_gid_table(ibdev, port);
+					mlx4_ib_set_default_gid(ibdev,
+								curr_netdev,
+								port);
+				} else {
+					/* gids from the upper dev (bond/team)
+					 * should appear in port's gid table
+					*/
+					mlx4_ib_get_dev_addr(curr_master,
+							     ibdev, port);
+				}
+			}
+			/* if bonding is used it is possible that we add it to
+			 * masters only after IP address is assigned to the
+			 * net bonding interface.
+			*/
+			if (curr_master && (old_master != curr_master)) {
+				reset_gid_table(ibdev, port);
+				mlx4_ib_set_default_gid(ibdev,
+							curr_netdev, port);
+				mlx4_ib_get_dev_addr(curr_master, ibdev, port);
+			}
 
-		if (!curr_master && (old_master != curr_master)) {
+			if (!curr_master && (old_master != curr_master)) {
+				reset_gid_table(ibdev, port);
+				mlx4_ib_set_default_gid(ibdev,
+							curr_netdev, port);
+				mlx4_ib_get_dev_addr(curr_netdev, ibdev, port);
+			}
+		} else {
 			reset_gid_table(ibdev, port);
-			mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
-			mlx4_ib_get_dev_addr(curr_netdev, ibdev, port);
 		}
 	}
 
-	spin_unlock(&iboe->lock);
+	spin_unlock_bh(&iboe->lock);
 
 	if (update_qps_port > 0)
 		mlx4_ib_update_qps(ibdev, dev, update_qps_port);
@@ -2007,6 +2094,7 @@ static void *mlx4_ib_add(struct mlx4_dev
 		(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_REREG_MR)		|
 		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|
 		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)	|
 		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)		|
@@ -2059,6 +2147,7 @@ static void *mlx4_ib_add(struct mlx4_dev
 	ibdev->ib_dev.req_notify_cq	= mlx4_ib_arm_cq;
 	ibdev->ib_dev.get_dma_mr	= mlx4_ib_get_dma_mr;
 	ibdev->ib_dev.reg_user_mr	= mlx4_ib_reg_user_mr;
+	ibdev->ib_dev.rereg_user_mr	= mlx4_ib_rereg_user_mr;
 	ibdev->ib_dev.dereg_mr		= mlx4_ib_dereg_mr;
 	ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
 	ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
@@ -2156,6 +2245,9 @@ static void *mlx4_ib_add(struct mlx4_dev
 			goto err_steer_free_bitmap;
 	}
 
+	for (j = 1; j <= ibdev->dev->caps.num_ports; j++)
+		atomic64_set(&iboe->mac[j - 1], ibdev->dev->caps.def_mac[j]);
+
 	if (ib_register_device(&ibdev->ib_dev, NULL))
 		goto err_steer_free_bitmap;
 
@@ -2192,12 +2284,8 @@ static void *mlx4_ib_add(struct mlx4_dev
 			}
 		}
 #endif
-		for (i = 1 ; i <= ibdev->num_ports ; ++i)
-			reset_gid_table(ibdev, i);
-		rtnl_lock();
-		mlx4_ib_scan_netdevs(ibdev, NULL, 0);
-		rtnl_unlock();
-		mlx4_ib_init_gid_table(ibdev);
+		if (mlx4_ib_init_gid_table(ibdev))
+			goto err_notif;
 	}
 
 	for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) {
@@ -2345,6 +2433,9 @@ static void mlx4_ib_remove(struct mlx4_d
 	struct mlx4_ib_dev *ibdev = ibdev_ptr;
 	int p;
 
+	ibdev->ib_active = false;
+	flush_workqueue(wq);
+
 	mlx4_ib_close_sriov(ibdev);
 	mlx4_ib_mad_cleanup(ibdev);
 	ib_unregister_device(&ibdev->ib_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2014-09-28 17:29:07.000000000 -0400
@@ -451,6 +451,7 @@ struct mlx4_ib_iboe {
 	spinlock_t		lock;
 	struct net_device      *netdevs[MLX4_MAX_PORTS];
 	struct net_device      *masters[MLX4_MAX_PORTS];
+	atomic64_t		mac[MLX4_MAX_PORTS];
 	struct notifier_block 	nb;
 	struct notifier_block	nb_inet;
 	struct notifier_block	nb_inet6;
@@ -788,5 +789,9 @@ int mlx4_ib_steer_qp_alloc(struct mlx4_i
 void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count);
 int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
 			 int is_attach);
+int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
+			  u64 start, u64 length, u64 virt_addr,
+			  int mr_access_flags, struct ib_pd *pd,
+			  struct ib_udata *udata);
 
 #endif /* MLX4_IB_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mr.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mr.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/mr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/mr.c	2014-09-28 17:29:07.000000000 -0400
@@ -144,8 +144,10 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct
 	if (!mr)
 		return ERR_PTR(-ENOMEM);
 
+	/* Force registering the memory as writable. */
+	/* Used for memory re-registeration. HCA protects the access */
 	mr->umem = ib_umem_get(pd->uobject->context, start, length,
-			       access_flags, 0);
+			       access_flags | IB_ACCESS_LOCAL_WRITE, 0);
 	if (IS_ERR(mr->umem)) {
 		err = PTR_ERR(mr->umem);
 		goto err_free;
@@ -183,6 +185,93 @@ err_free:
 	return ERR_PTR(err);
 }
 
+int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
+			  u64 start, u64 length, u64 virt_addr,
+			  int mr_access_flags, struct ib_pd *pd,
+			  struct ib_udata *udata)
+{
+	struct mlx4_ib_dev *dev = to_mdev(mr->device);
+	struct mlx4_ib_mr *mmr = to_mmr(mr);
+	struct mlx4_mpt_entry *mpt_entry;
+	struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
+	int err;
+
+	/* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
+	 * we assume that the calls can't run concurrently. Otherwise, a
+	 * race exists.
+	 */
+	err =  mlx4_mr_hw_get_mpt(dev->dev, &mmr->mmr, &pmpt_entry);
+
+	if (err)
+		return err;
+
+	if (flags & IB_MR_REREG_PD) {
+		err = mlx4_mr_hw_change_pd(dev->dev, *pmpt_entry,
+					   to_mpd(pd)->pdn);
+
+		if (err)
+			goto release_mpt_entry;
+	}
+
+	if (flags & IB_MR_REREG_ACCESS) {
+		err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry,
+					       convert_access(mr_access_flags));
+
+		if (err)
+			goto release_mpt_entry;
+	}
+
+	if (flags & IB_MR_REREG_TRANS) {
+		int shift;
+		int err;
+		int n;
+
+		mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr);
+		ib_umem_release(mmr->umem);
+		mmr->umem = ib_umem_get(mr->uobject->context, start, length,
+					mr_access_flags |
+					IB_ACCESS_LOCAL_WRITE,
+					0);
+		if (IS_ERR(mmr->umem)) {
+			err = PTR_ERR(mmr->umem);
+			/* Prevent mlx4_ib_dereg_mr from free'ing invalid pointer */
+			mmr->umem = NULL;
+			goto release_mpt_entry;
+		}
+		n = ib_umem_page_count(mmr->umem);
+		shift = ilog2(mmr->umem->page_size);
+
+		err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr,
+					      virt_addr, length, n, shift,
+					      *pmpt_entry);
+		if (err) {
+			ib_umem_release(mmr->umem);
+			goto release_mpt_entry;
+		}
+		mmr->mmr.iova       = virt_addr;
+		mmr->mmr.size       = length;
+
+		err = mlx4_ib_umem_write_mtt(dev, &mmr->mmr.mtt, mmr->umem);
+		if (err) {
+			mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr);
+			ib_umem_release(mmr->umem);
+			goto release_mpt_entry;
+		}
+	}
+
+	/* If we couldn't transfer the MR to the HCA, just remember to
+	 * return a failure. But dereg_mr will free the resources.
+	 */
+	err = mlx4_mr_hw_write_mpt(dev->dev, &mmr->mmr, pmpt_entry);
+	if (!err && flags & IB_MR_REREG_ACCESS)
+		mmr->mmr.access = mr_access_flags;
+
+release_mpt_entry:
+	mlx4_mr_hw_put_mpt(dev->dev, pmpt_entry);
+
+	return err;
+}
+
 int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
 {
 	struct mlx4_ib_mr *mr = to_mmr(ibmr);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/qp.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx4/qp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx4/qp.c	2014-09-28 17:29:07.000000000 -0400
@@ -964,9 +964,10 @@ static void destroy_qp_common(struct mlx
 				   MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp))
 			pr_warn("modify QP %06x to RESET failed.\n",
 			       qp->mqp.qpn);
-		if (qp->pri.smac) {
+		if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) {
 			mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
 			qp->pri.smac = 0;
+			qp->pri.smac_port = 0;
 		}
 		if (qp->alt.smac) {
 			mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
@@ -1325,7 +1326,8 @@ static int _mlx4_set_path(struct mlx4_ib
 		 * If one was already assigned, but the new mac differs,
 		 * unregister the old one and register the new one.
 		*/
-		if (!smac_info->smac || smac_info->smac != smac) {
+		if ((!smac_info->smac && !smac_info->smac_port) ||
+		    smac_info->smac != smac) {
 			/* register candidate now, unreg if needed, after success */
 			smac_index = mlx4_register_mac(dev->dev, port, smac);
 			if (smac_index >= 0) {
@@ -1390,21 +1392,13 @@ static void update_mcg_macs(struct mlx4_
 static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac,
 				    struct mlx4_qp_context *context)
 {
-	struct net_device *ndev;
 	u64 u64_mac;
 	int smac_index;
 
-
-	ndev = dev->iboe.netdevs[qp->port - 1];
-	if (ndev) {
-		smac = ndev->dev_addr;
-		u64_mac = mlx4_mac_to_u64(smac);
-	} else {
-		u64_mac = dev->dev->caps.def_mac[qp->port];
-	}
+	u64_mac = atomic64_read(&dev->iboe.mac[qp->port - 1]);
 
 	context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6);
-	if (!qp->pri.smac) {
+	if (!qp->pri.smac && !qp->pri.smac_port) {
 		smac_index = mlx4_register_mac(dev->dev, qp->port, u64_mac);
 		if (smac_index >= 0) {
 			qp->pri.candidate_smac_index = smac_index;
@@ -1432,6 +1426,12 @@ static int __mlx4_ib_modify_qp(struct ib
 	int steer_qp = 0;
 	int err = -EINVAL;
 
+	/* APM is not supported under RoCE */
+	if (attr_mask & IB_QP_ALT_PATH &&
+	    rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
+	    IB_LINK_LAYER_ETHERNET)
+		return -ENOTSUPP;
+
 	context = kzalloc(sizeof *context, GFP_KERNEL);
 	if (!context)
 		return -ENOMEM;
@@ -1677,9 +1677,15 @@ static int __mlx4_ib_modify_qp(struct ib
 		}
 	}
 
-	if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET)
+	if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
 		context->pri_path.ackto = (context->pri_path.ackto & 0xf8) |
 					MLX4_IB_LINK_TYPE_ETH;
+		if (dev->dev->caps.tunnel_offload_mode ==  MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+			/* set QP to receive both tunneled & non-tunneled packets */
+			if (!(context->flags & cpu_to_be32(1 << MLX4_RSS_QPC_FLAG_OFFSET)))
+				context->srqn = cpu_to_be32(7 << 28);
+		}
+	}
 
 	if (ibqp->qp_type == IB_QPT_UD && (new_state == IB_QPS_RTR)) {
 		int is_eth = rdma_port_get_link_layer(
@@ -1780,9 +1786,10 @@ static int __mlx4_ib_modify_qp(struct ib
 			if (qp->flags & MLX4_IB_QP_NETIF)
 				mlx4_ib_steer_qp_reg(dev, qp, 0);
 		}
-		if (qp->pri.smac) {
+		if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) {
 			mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
 			qp->pri.smac = 0;
+			qp->pri.smac_port = 0;
 		}
 		if (qp->alt.smac) {
 			mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
@@ -1806,11 +1813,12 @@ out:
 	if (err && steer_qp)
 		mlx4_ib_steer_qp_reg(dev, qp, 0);
 	kfree(context);
-	if (qp->pri.candidate_smac) {
+	if (qp->pri.candidate_smac ||
+	    (!qp->pri.candidate_smac && qp->pri.candidate_smac_port)) {
 		if (err) {
 			mlx4_unregister_mac(dev->dev, qp->pri.candidate_smac_port, qp->pri.candidate_smac);
 		} else {
-			if (qp->pri.smac)
+			if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port))
 				mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
 			qp->pri.smac = qp->pri.candidate_smac;
 			qp->pri.smac_index = qp->pri.candidate_smac_index;
@@ -2083,6 +2091,16 @@ static int build_sriov_qp0_header(struct
 	return 0;
 }
 
+static void mlx4_u64_to_smac(u8 *dst_mac, u64 src_mac)
+{
+	int i;
+
+	for (i = ETH_ALEN; i; i--) {
+		dst_mac[i - 1] = src_mac & 0xff;
+		src_mac >>= 8;
+	}
+}
+
 static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 			    void *wqe, unsigned *mlx_seg_len)
 {
@@ -2197,7 +2215,6 @@ static int build_mlx_header(struct mlx4_
 	}
 
 	if (is_eth) {
-		u8 *smac;
 		struct in6_addr in6;
 
 		u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13;
@@ -2210,12 +2227,17 @@ static int build_mlx_header(struct mlx4_
 		memcpy(&ctrl->imm, ah->av.eth.mac + 2, 4);
 		memcpy(&in6, sgid.raw, sizeof(in6));
 
-		if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev))
-			smac = to_mdev(sqp->qp.ibqp.device)->
-				iboe.netdevs[sqp->qp.port - 1]->dev_addr;
-		else	/* use the src mac of the tunnel */
-			smac = ah->av.eth.s_mac;
-		memcpy(sqp->ud_header.eth.smac_h, smac, 6);
+		if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
+			u64 mac = atomic64_read(&to_mdev(ib_dev)->iboe.mac[sqp->qp.port - 1]);
+			u8 smac[ETH_ALEN];
+
+			mlx4_u64_to_smac(smac, mac);
+			memcpy(sqp->ud_header.eth.smac_h, smac, ETH_ALEN);
+		} else {
+			/* use the src mac of the tunnel */
+			memcpy(sqp->ud_header.eth.smac_h, ah->av.eth.s_mac, ETH_ALEN);
+		}
+
 		if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))
 			mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
 		if (!is_vlan) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/cq.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/cq.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/cq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/cq.c	2014-09-28 17:29:07.000000000 -0400
@@ -180,7 +180,7 @@ static void handle_responder(struct ib_w
 		struct mlx5_core_srq *msrq = NULL;
 
 		if (qp->ibqp.xrcd) {
-			msrq = mlx5_core_get_srq(&dev->mdev,
+			msrq = mlx5_core_get_srq(dev->mdev,
 						 be32_to_cpu(cqe->srqn));
 			srq = to_mibsrq(msrq);
 		} else {
@@ -348,7 +348,7 @@ static void handle_atomic(struct mlx5_ib
 static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
 			   u16 tail, u16 head)
 {
-	int idx;
+	u16 idx;
 
 	do {
 		idx = tail & (qp->sq.wqe_cnt - 1);
@@ -364,7 +364,7 @@ static void handle_atomics(struct mlx5_i
 
 static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf)
 {
-	mlx5_buf_free(&dev->mdev, &buf->buf);
+	mlx5_buf_free(dev->mdev, &buf->buf);
 }
 
 static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
@@ -450,7 +450,7 @@ repoll:
 		 * because CQs will be locked while QPs are removed
 		 * from the table.
 		 */
-		mqp = __mlx5_qp_lookup(&dev->mdev, qpn);
+		mqp = __mlx5_qp_lookup(dev->mdev, qpn);
 		if (unlikely(!mqp)) {
 			mlx5_ib_warn(dev, "CQE@CQ %06x for unknown QPN %6x\n",
 				     cq->mcq.cqn, qpn);
@@ -514,11 +514,11 @@ repoll:
 	case MLX5_CQE_SIG_ERR:
 		sig_err_cqe = (struct mlx5_sig_err_cqe *)cqe64;
 
-		read_lock(&dev->mdev.priv.mr_table.lock);
-		mmr = __mlx5_mr_lookup(&dev->mdev,
+		read_lock(&dev->mdev->priv.mr_table.lock);
+		mmr = __mlx5_mr_lookup(dev->mdev,
 				       mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey)));
 		if (unlikely(!mmr)) {
-			read_unlock(&dev->mdev.priv.mr_table.lock);
+			read_unlock(&dev->mdev->priv.mr_table.lock);
 			mlx5_ib_warn(dev, "CQE@CQ %06x for unknown MR %6x\n",
 				     cq->mcq.cqn, be32_to_cpu(sig_err_cqe->mkey));
 			return -EINVAL;
@@ -536,7 +536,7 @@ repoll:
 			     mr->sig->err_item.expected,
 			     mr->sig->err_item.actual);
 
-		read_unlock(&dev->mdev.priv.mr_table.lock);
+		read_unlock(&dev->mdev->priv.mr_table.lock);
 		goto repoll;
 	}
 
@@ -575,8 +575,8 @@ int mlx5_ib_arm_cq(struct ib_cq *ibcq, e
 	mlx5_cq_arm(&to_mcq(ibcq)->mcq,
 		    (flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
 		    MLX5_CQ_DB_REQ_NOT_SOL : MLX5_CQ_DB_REQ_NOT,
-		    to_mdev(ibcq->device)->mdev.priv.uuari.uars[0].map,
-		    MLX5_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->mdev.priv.cq_uar_lock));
+		    to_mdev(ibcq->device)->mdev->priv.uuari.uars[0].map,
+		    MLX5_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->mdev->priv.cq_uar_lock));
 
 	return 0;
 }
@@ -586,7 +586,7 @@ static int alloc_cq_buf(struct mlx5_ib_d
 {
 	int err;
 
-	err = mlx5_buf_alloc(&dev->mdev, nent * cqe_size,
+	err = mlx5_buf_alloc(dev->mdev, nent * cqe_size,
 			     PAGE_SIZE * 2, &buf->buf);
 	if (err)
 		return err;
@@ -691,7 +691,7 @@ static int create_cq_kernel(struct mlx5_
 {
 	int err;
 
-	err = mlx5_db_alloc(&dev->mdev, &cq->db);
+	err = mlx5_db_alloc(dev->mdev, &cq->db);
 	if (err)
 		return err;
 
@@ -716,7 +716,7 @@ static int create_cq_kernel(struct mlx5_
 	mlx5_fill_page_array(&cq->buf.buf, (*cqb)->pas);
 
 	(*cqb)->ctx.log_pg_sz = cq->buf.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT;
-	*index = dev->mdev.priv.uuari.uars[0].index;
+	*index = dev->mdev->priv.uuari.uars[0].index;
 
 	return 0;
 
@@ -724,14 +724,14 @@ err_buf:
 	free_cq_buf(dev, &cq->buf);
 
 err_db:
-	mlx5_db_free(&dev->mdev, &cq->db);
+	mlx5_db_free(dev->mdev, &cq->db);
 	return err;
 }
 
 static void destroy_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq)
 {
 	free_cq_buf(dev, &cq->buf);
-	mlx5_db_free(&dev->mdev, &cq->db);
+	mlx5_db_free(dev->mdev, &cq->db);
 }
 
 struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
@@ -752,7 +752,7 @@ struct ib_cq *mlx5_ib_create_cq(struct i
 		return ERR_PTR(-EINVAL);
 
 	entries = roundup_pow_of_two(entries + 1);
-	if (entries > dev->mdev.caps.max_cqes)
+	if (entries > dev->mdev->caps.max_cqes)
 		return ERR_PTR(-EINVAL);
 
 	cq = kzalloc(sizeof(*cq), GFP_KERNEL);
@@ -789,7 +789,7 @@ struct ib_cq *mlx5_ib_create_cq(struct i
 	cqb->ctx.c_eqn = cpu_to_be16(eqn);
 	cqb->ctx.db_record_addr = cpu_to_be64(cq->db.dma);
 
-	err = mlx5_core_create_cq(&dev->mdev, &cq->mcq, cqb, inlen);
+	err = mlx5_core_create_cq(dev->mdev, &cq->mcq, cqb, inlen);
 	if (err)
 		goto err_cqb;
 
@@ -809,7 +809,7 @@ struct ib_cq *mlx5_ib_create_cq(struct i
 	return &cq->ibcq;
 
 err_cmd:
-	mlx5_core_destroy_cq(&dev->mdev, &cq->mcq);
+	mlx5_core_destroy_cq(dev->mdev, &cq->mcq);
 
 err_cqb:
 	mlx5_vfree(cqb);
@@ -834,7 +834,7 @@ int mlx5_ib_destroy_cq(struct ib_cq *cq)
 	if (cq->uobject)
 		context = cq->uobject->context;
 
-	mlx5_core_destroy_cq(&dev->mdev, &mcq->mcq);
+	mlx5_core_destroy_cq(dev->mdev, &mcq->mcq);
 	if (context)
 		destroy_cq_user(mcq, context);
 	else
@@ -919,7 +919,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq,
 	int err;
 	u32 fsel;
 
-	if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_CQ_MODER))
+	if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_CQ_MODER))
 		return -ENOSYS;
 
 	in = kzalloc(sizeof(*in), GFP_KERNEL);
@@ -931,7 +931,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq,
 	in->ctx.cq_period = cpu_to_be16(cq_period);
 	in->ctx.cq_max_count = cpu_to_be16(cq_count);
 	in->field_select = cpu_to_be32(fsel);
-	err = mlx5_core_modify_cq(&dev->mdev, &mcq->mcq, in, sizeof(*in));
+	err = mlx5_core_modify_cq(dev->mdev, &mcq->mcq, in, sizeof(*in));
 	kfree(in);
 
 	if (err)
@@ -1074,7 +1074,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq
 	int uninitialized_var(cqe_size);
 	unsigned long flags;
 
-	if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_RESIZE_CQ)) {
+	if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_RESIZE_CQ)) {
 		pr_info("Firmware does not support resize CQ\n");
 		return -ENOSYS;
 	}
@@ -1083,7 +1083,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq
 		return -EINVAL;
 
 	entries = roundup_pow_of_two(entries + 1);
-	if (entries > dev->mdev.caps.max_cqes + 1)
+	if (entries > dev->mdev->caps.max_cqes + 1)
 		return -EINVAL;
 
 	if (entries == ibcq->cqe + 1)
@@ -1128,7 +1128,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq
 	in->hdr.opmod = cpu_to_be16(MLX5_CQ_OPMOD_RESIZE);
 	in->cqn = cpu_to_be32(cq->mcq.cqn);
 
-	err = mlx5_core_modify_cq(&dev->mdev, &cq->mcq, in, inlen);
+	err = mlx5_core_modify_cq(dev->mdev, &cq->mcq, in, inlen);
 	if (err)
 		goto ex_alloc;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ enum {
 };
 
 int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
-		 int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+		 u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh,
 		 void *in_mad, void *response_mad)
 {
 	u8 op_modifier = 0;
@@ -54,7 +54,7 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev
 	if (ignore_bkey || !in_wc)
 		op_modifier |= 0x2;
 
-	return mlx5_core_mad_ifc(&dev->mdev, in_mad, response_mad, op_modifier, port);
+	return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port);
 }
 
 int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
@@ -129,7 +129,7 @@ int mlx5_query_ext_port_caps(struct mlx5
 
 	packet_error = be16_to_cpu(out_mad->status);
 
-	dev->mdev.caps.ext_port_cap[port - 1] = (!err && !packet_error) ?
+	dev->mdev->caps.ext_port_cap[port - 1] = (!err && !packet_error) ?
 		MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
 
 out:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/main.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,96 +54,17 @@ MODULE_DESCRIPTION("Mellanox Connect-IB
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRIVER_VERSION);
 
-static int prof_sel = 2;
-module_param_named(prof_sel, prof_sel, int, 0444);
-MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
+static int deprecated_prof_sel = 2;
+module_param_named(prof_sel, deprecated_prof_sel, int, 0444);
+MODULE_PARM_DESC(prof_sel, "profile selector. Deprecated here. Moved to module mlx5_core");
 
 static char mlx5_version[] =
 	DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v"
 	DRIVER_VERSION " (" DRIVER_RELDATE ")\n";
 
-static struct mlx5_profile profile[] = {
-	[0] = {
-		.mask		= 0,
-	},
-	[1] = {
-		.mask		= MLX5_PROF_MASK_QP_SIZE,
-		.log_max_qp	= 12,
-	},
-	[2] = {
-		.mask		= MLX5_PROF_MASK_QP_SIZE |
-				  MLX5_PROF_MASK_MR_CACHE,
-		.log_max_qp	= 17,
-		.mr_cache[0]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[1]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[2]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[3]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[4]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[5]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[6]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[7]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[8]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[9]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[10]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[11]	= {
-			.size	= 500,
-			.limit	= 250
-		},
-		.mr_cache[12]	= {
-			.size	= 64,
-			.limit	= 32
-		},
-		.mr_cache[13]	= {
-			.size	= 32,
-			.limit	= 16
-		},
-		.mr_cache[14]	= {
-			.size	= 16,
-			.limit	= 8
-		},
-		.mr_cache[15]	= {
-			.size	= 8,
-			.limit	= 4
-		},
-	},
-};
-
 int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn)
 {
-	struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+	struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
 	struct mlx5_eq *eq, *n;
 	int err = -ENOENT;
 
@@ -163,7 +84,7 @@ int mlx5_vector2eqn(struct mlx5_ib_dev *
 
 static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
 {
-	struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+	struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
 	char name[MLX5_MAX_EQ_NAME];
 	struct mlx5_eq *eq, *n;
 	int ncomp_vec;
@@ -182,9 +103,9 @@ static int alloc_comp_eqs(struct mlx5_ib
 		}
 
 		snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
-		err = mlx5_create_map_eq(&dev->mdev, eq,
+		err = mlx5_create_map_eq(dev->mdev, eq,
 					 i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
-					 name, &dev->mdev.priv.uuari.uars[0]);
+					 name, &dev->mdev->priv.uuari.uars[0]);
 		if (err) {
 			kfree(eq);
 			goto clean;
@@ -204,7 +125,7 @@ clean:
 	list_for_each_entry_safe(eq, n, &dev->eqs_list, list) {
 		list_del(&eq->list);
 		spin_unlock(&table->lock);
-		if (mlx5_destroy_unmap_eq(&dev->mdev, eq))
+		if (mlx5_destroy_unmap_eq(dev->mdev, eq))
 			mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn);
 		kfree(eq);
 		spin_lock(&table->lock);
@@ -215,14 +136,14 @@ clean:
 
 static void free_comp_eqs(struct mlx5_ib_dev *dev)
 {
-	struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+	struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
 	struct mlx5_eq *eq, *n;
 
 	spin_lock(&table->lock);
 	list_for_each_entry_safe(eq, n, &dev->eqs_list, list) {
 		list_del(&eq->list);
 		spin_unlock(&table->lock);
-		if (mlx5_destroy_unmap_eq(&dev->mdev, eq))
+		if (mlx5_destroy_unmap_eq(dev->mdev, eq))
 			mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn);
 		kfree(eq);
 		spin_lock(&table->lock);
@@ -255,14 +176,14 @@ static int mlx5_ib_query_device(struct i
 
 	memset(props, 0, sizeof(*props));
 
-	props->fw_ver = ((u64)fw_rev_maj(&dev->mdev) << 32) |
-		(fw_rev_min(&dev->mdev) << 16) |
-		fw_rev_sub(&dev->mdev);
+	props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) |
+		(fw_rev_min(dev->mdev) << 16) |
+		fw_rev_sub(dev->mdev);
 	props->device_cap_flags    = IB_DEVICE_CHANGE_PHY_PORT |
 		IB_DEVICE_PORT_ACTIVE_EVENT		|
 		IB_DEVICE_SYS_IMAGE_GUID		|
 		IB_DEVICE_RC_RNR_NAK_GEN;
-	flags = dev->mdev.caps.flags;
+	flags = dev->mdev->caps.flags;
 	if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR)
 		props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
 	if (flags & MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR)
@@ -292,30 +213,30 @@ static int mlx5_ib_query_device(struct i
 	memcpy(&props->sys_image_guid, out_mad->data +	4, 8);
 
 	props->max_mr_size	   = ~0ull;
-	props->page_size_cap	   = dev->mdev.caps.min_page_sz;
-	props->max_qp		   = 1 << dev->mdev.caps.log_max_qp;
-	props->max_qp_wr	   = dev->mdev.caps.max_wqes;
-	max_rq_sg = dev->mdev.caps.max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg);
-	max_sq_sg = (dev->mdev.caps.max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) /
+	props->page_size_cap	   = dev->mdev->caps.min_page_sz;
+	props->max_qp		   = 1 << dev->mdev->caps.log_max_qp;
+	props->max_qp_wr	   = dev->mdev->caps.max_wqes;
+	max_rq_sg = dev->mdev->caps.max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg);
+	max_sq_sg = (dev->mdev->caps.max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) /
 		sizeof(struct mlx5_wqe_data_seg);
 	props->max_sge = min(max_rq_sg, max_sq_sg);
-	props->max_cq		   = 1 << dev->mdev.caps.log_max_cq;
-	props->max_cqe		   = dev->mdev.caps.max_cqes - 1;
-	props->max_mr		   = 1 << dev->mdev.caps.log_max_mkey;
-	props->max_pd		   = 1 << dev->mdev.caps.log_max_pd;
-	props->max_qp_rd_atom	   = dev->mdev.caps.max_ra_req_qp;
-	props->max_qp_init_rd_atom = dev->mdev.caps.max_ra_res_qp;
+	props->max_cq		   = 1 << dev->mdev->caps.log_max_cq;
+	props->max_cqe		   = dev->mdev->caps.max_cqes - 1;
+	props->max_mr		   = 1 << dev->mdev->caps.log_max_mkey;
+	props->max_pd		   = 1 << dev->mdev->caps.log_max_pd;
+	props->max_qp_rd_atom	   = dev->mdev->caps.max_ra_req_qp;
+	props->max_qp_init_rd_atom = dev->mdev->caps.max_ra_res_qp;
 	props->max_res_rd_atom	   = props->max_qp_rd_atom * props->max_qp;
-	props->max_srq		   = 1 << dev->mdev.caps.log_max_srq;
-	props->max_srq_wr	   = dev->mdev.caps.max_srq_wqes - 1;
+	props->max_srq		   = 1 << dev->mdev->caps.log_max_srq;
+	props->max_srq_wr	   = dev->mdev->caps.max_srq_wqes - 1;
 	props->max_srq_sge	   = max_rq_sg - 1;
 	props->max_fast_reg_page_list_len = (unsigned int)-1;
-	props->local_ca_ack_delay  = dev->mdev.caps.local_ca_ack_delay;
+	props->local_ca_ack_delay  = dev->mdev->caps.local_ca_ack_delay;
 	props->atomic_cap	   = IB_ATOMIC_NONE;
 	props->masked_atomic_cap   = IB_ATOMIC_NONE;
 	props->max_pkeys	   = be16_to_cpup((__be16 *)(out_mad->data + 28));
-	props->max_mcast_grp	   = 1 << dev->mdev.caps.log_max_mcg;
-	props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg;
+	props->max_mcast_grp	   = 1 << dev->mdev->caps.log_max_mcg;
+	props->max_mcast_qp_attach = dev->mdev->caps.max_qp_mcg;
 	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 */
@@ -336,7 +257,7 @@ int mlx5_ib_query_port(struct ib_device
 	int ext_active_speed;
 	int err = -ENOMEM;
 
-	if (port < 1 || port > dev->mdev.caps.num_ports) {
+	if (port < 1 || port > dev->mdev->caps.num_ports) {
 		mlx5_ib_warn(dev, "invalid port number %d\n", port);
 		return -EINVAL;
 	}
@@ -367,8 +288,8 @@ int mlx5_ib_query_port(struct ib_device
 	props->phys_state	= out_mad->data[33] >> 4;
 	props->port_cap_flags	= be32_to_cpup((__be32 *)(out_mad->data + 20));
 	props->gid_tbl_len	= out_mad->data[50];
-	props->max_msg_sz	= 1 << to_mdev(ibdev)->mdev.caps.log_max_msg;
-	props->pkey_tbl_len	= to_mdev(ibdev)->mdev.caps.port[port - 1].pkey_table_len;
+	props->max_msg_sz	= 1 << to_mdev(ibdev)->mdev->caps.log_max_msg;
+	props->pkey_tbl_len	= to_mdev(ibdev)->mdev->caps.port[port - 1].pkey_table_len;
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *)(out_mad->data + 46));
 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *)(out_mad->data + 48));
 	props->active_width	= out_mad->data[31] & 0xf;
@@ -395,7 +316,7 @@ int mlx5_ib_query_port(struct ib_device
 
 	/* If reported active speed is QDR, check if is FDR-10 */
 	if (props->active_speed == 4) {
-		if (dev->mdev.caps.ext_port_cap[port - 1] &
+		if (dev->mdev->caps.ext_port_cap[port - 1] &
 		    MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
 			init_query_mad(in_mad);
 			in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
@@ -508,7 +429,7 @@ static int mlx5_ib_modify_device(struct
 	 * a 144 trap.  If cmd fails, just ignore.
 	 */
 	memcpy(&in, props->node_desc, 64);
-	err = mlx5_core_access_reg(&dev->mdev, &in, sizeof(in), &out,
+	err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,
 				   sizeof(out), MLX5_REG_NODE_DESC, 0, 1);
 	if (err)
 		return err;
@@ -535,7 +456,7 @@ static int mlx5_ib_modify_port(struct ib
 	tmp = (attr.port_cap_flags | props->set_port_cap_mask) &
 		~props->clr_port_cap_mask;
 
-	err = mlx5_set_port_caps(&dev->mdev, port, tmp);
+	err = mlx5_set_port_caps(dev->mdev, port, tmp);
 
 out:
 	mutex_unlock(&dev->cap_mask_mutex);
@@ -557,7 +478,7 @@ static struct ib_ucontext *mlx5_ib_alloc
 	int uuarn;
 	int err;
 	int i;
-	int reqlen;
+	size_t reqlen;
 
 	if (!dev->ib_active)
 		return ERR_PTR(-EAGAIN);
@@ -591,14 +512,14 @@ static struct ib_ucontext *mlx5_ib_alloc
 
 	num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
 	gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
-	resp.qp_tab_size      = 1 << dev->mdev.caps.log_max_qp;
-	resp.bf_reg_size      = dev->mdev.caps.bf_reg_size;
+	resp.qp_tab_size      = 1 << dev->mdev->caps.log_max_qp;
+	resp.bf_reg_size      = dev->mdev->caps.bf_reg_size;
 	resp.cache_line_size  = L1_CACHE_BYTES;
-	resp.max_sq_desc_sz = dev->mdev.caps.max_sq_desc_sz;
-	resp.max_rq_desc_sz = dev->mdev.caps.max_rq_desc_sz;
-	resp.max_send_wqebb = dev->mdev.caps.max_wqes;
-	resp.max_recv_wr = dev->mdev.caps.max_wqes;
-	resp.max_srq_recv_wr = dev->mdev.caps.max_srq_wqes;
+	resp.max_sq_desc_sz = dev->mdev->caps.max_sq_desc_sz;
+	resp.max_rq_desc_sz = dev->mdev->caps.max_rq_desc_sz;
+	resp.max_send_wqebb = dev->mdev->caps.max_wqes;
+	resp.max_recv_wr = dev->mdev->caps.max_wqes;
+	resp.max_srq_recv_wr = dev->mdev->caps.max_srq_wqes;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
@@ -635,7 +556,7 @@ static struct ib_ucontext *mlx5_ib_alloc
 	}
 
 	for (i = 0; i < num_uars; i++) {
-		err = mlx5_cmd_alloc_uar(&dev->mdev, &uars[i].index);
+		err = mlx5_cmd_alloc_uar(dev->mdev, &uars[i].index);
 		if (err)
 			goto out_count;
 	}
@@ -644,7 +565,7 @@ static struct ib_ucontext *mlx5_ib_alloc
 	mutex_init(&context->db_page_mutex);
 
 	resp.tot_uuars = req.total_num_uuars;
-	resp.num_ports = dev->mdev.caps.num_ports;
+	resp.num_ports = dev->mdev->caps.num_ports;
 	err = ib_copy_to_udata(udata, &resp,
 			       sizeof(resp) - sizeof(resp.reserved));
 	if (err)
@@ -658,7 +579,7 @@ static struct ib_ucontext *mlx5_ib_alloc
 
 out_uars:
 	for (i--; i >= 0; i--)
-		mlx5_cmd_free_uar(&dev->mdev, uars[i].index);
+		mlx5_cmd_free_uar(dev->mdev, uars[i].index);
 out_count:
 	kfree(uuari->count);
 
@@ -681,7 +602,7 @@ static int mlx5_ib_dealloc_ucontext(stru
 	int i;
 
 	for (i = 0; i < uuari->num_uars; i++) {
-		if (mlx5_cmd_free_uar(&dev->mdev, uuari->uars[i].index))
+		if (mlx5_cmd_free_uar(dev->mdev, uuari->uars[i].index))
 			mlx5_ib_warn(dev, "failed to free UAR 0x%x\n", uuari->uars[i].index);
 	}
 
@@ -695,7 +616,7 @@ static int mlx5_ib_dealloc_ucontext(stru
 
 static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev, int index)
 {
-	return (pci_resource_start(dev->mdev.pdev, 0) >> PAGE_SHIFT) + index;
+	return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + index;
 }
 
 static int get_command(unsigned long offset)
@@ -773,7 +694,7 @@ static int alloc_pa_mkey(struct mlx5_ib_
 	seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
 	seg->start_addr = 0;
 
-	err = mlx5_core_create_mkey(&dev->mdev, &mr, in, sizeof(*in),
+	err = mlx5_core_create_mkey(dev->mdev, &mr, in, sizeof(*in),
 				    NULL, NULL, NULL);
 	if (err) {
 		mlx5_ib_warn(dev, "failed to create mkey, %d\n", err);
@@ -798,7 +719,7 @@ static void free_pa_mkey(struct mlx5_ib_
 
 	memset(&mr, 0, sizeof(mr));
 	mr.key = key;
-	err = mlx5_core_destroy_mkey(&dev->mdev, &mr);
+	err = mlx5_core_destroy_mkey(dev->mdev, &mr);
 	if (err)
 		mlx5_ib_warn(dev, "failed to destroy mkey 0x%x\n", key);
 }
@@ -815,7 +736,7 @@ static struct ib_pd *mlx5_ib_alloc_pd(st
 	if (!pd)
 		return ERR_PTR(-ENOMEM);
 
-	err = mlx5_core_alloc_pd(&to_mdev(ibdev)->mdev, &pd->pdn);
+	err = mlx5_core_alloc_pd(to_mdev(ibdev)->mdev, &pd->pdn);
 	if (err) {
 		kfree(pd);
 		return ERR_PTR(err);
@@ -824,14 +745,14 @@ static struct ib_pd *mlx5_ib_alloc_pd(st
 	if (context) {
 		resp.pdn = pd->pdn;
 		if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
-			mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn);
+			mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
 			kfree(pd);
 			return ERR_PTR(-EFAULT);
 		}
 	} else {
 		err = alloc_pa_mkey(to_mdev(ibdev), &pd->pa_lkey, pd->pdn);
 		if (err) {
-			mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn);
+			mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
 			kfree(pd);
 			return ERR_PTR(err);
 		}
@@ -848,7 +769,7 @@ static int mlx5_ib_dealloc_pd(struct ib_
 	if (!pd->uobject)
 		free_pa_mkey(mdev, mpd->pa_lkey);
 
-	mlx5_core_dealloc_pd(&mdev->mdev, mpd->pdn);
+	mlx5_core_dealloc_pd(mdev->mdev, mpd->pdn);
 	kfree(mpd);
 
 	return 0;
@@ -859,7 +780,7 @@ static int mlx5_ib_mcg_attach(struct ib_
 	struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
 	int err;
 
-	err = mlx5_core_attach_mcg(&dev->mdev, gid, ibqp->qp_num);
+	err = mlx5_core_attach_mcg(dev->mdev, gid, ibqp->qp_num);
 	if (err)
 		mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n",
 			     ibqp->qp_num, gid->raw);
@@ -872,7 +793,7 @@ static int mlx5_ib_mcg_detach(struct ib_
 	struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
 	int err;
 
-	err = mlx5_core_detach_mcg(&dev->mdev, gid, ibqp->qp_num);
+	err = mlx5_core_detach_mcg(dev->mdev, gid, ibqp->qp_num);
 	if (err)
 		mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n",
 			     ibqp->qp_num, gid->raw);
@@ -906,7 +827,7 @@ static int init_node_data(struct mlx5_ib
 	if (err)
 		goto out;
 
-	dev->mdev.rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32));
+	dev->mdev->rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
@@ -921,7 +842,7 @@ static ssize_t show_fw_pages(struct devi
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
 
-	return sprintf(buf, "%d\n", dev->mdev.priv.fw_pages);
+	return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages);
 }
 
 static ssize_t show_reg_pages(struct device *device,
@@ -930,7 +851,7 @@ static ssize_t show_reg_pages(struct dev
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
 
-	return sprintf(buf, "%d\n", dev->mdev.priv.reg_pages);
+	return sprintf(buf, "%d\n", dev->mdev->priv.reg_pages);
 }
 
 static ssize_t show_hca(struct device *device, struct device_attribute *attr,
@@ -938,7 +859,7 @@ static ssize_t show_hca(struct device *d
 {
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-	return sprintf(buf, "MT%d\n", dev->mdev.pdev->device);
+	return sprintf(buf, "MT%d\n", dev->mdev->pdev->device);
 }
 
 static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
@@ -946,8 +867,8 @@ static ssize_t show_fw_ver(struct device
 {
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-	return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(&dev->mdev),
-		       fw_rev_min(&dev->mdev), fw_rev_sub(&dev->mdev));
+	return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(dev->mdev),
+		       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
 static ssize_t show_rev(struct device *device, struct device_attribute *attr,
@@ -955,7 +876,7 @@ static ssize_t show_rev(struct device *d
 {
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-	return sprintf(buf, "%x\n", dev->mdev.rev_id);
+	return sprintf(buf, "%x\n", dev->mdev->rev_id);
 }
 
 static ssize_t show_board(struct device *device, struct device_attribute *attr,
@@ -964,7 +885,7 @@ static ssize_t show_board(struct device
 	struct mlx5_ib_dev *dev =
 		container_of(device, struct mlx5_ib_dev, ib_dev.dev);
 	return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN,
-		       dev->mdev.board_id);
+		       dev->mdev->board_id);
 }
 
 static DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
@@ -983,11 +904,12 @@ static struct device_attribute *mlx5_cla
 	&dev_attr_reg_pages,
 };
 
-static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
-			  void *data)
+static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
+			  enum mlx5_dev_event event, unsigned long param)
 {
-	struct mlx5_ib_dev *ibdev = container_of(dev, struct mlx5_ib_dev, mdev);
+	struct mlx5_ib_dev *ibdev = (struct mlx5_ib_dev *)context;
 	struct ib_event ibev;
+
 	u8 port = 0;
 
 	switch (event) {
@@ -998,12 +920,12 @@ static void mlx5_ib_event(struct mlx5_co
 
 	case MLX5_DEV_EVENT_PORT_UP:
 		ibev.event = IB_EVENT_PORT_ACTIVE;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 
 	case MLX5_DEV_EVENT_PORT_DOWN:
 		ibev.event = IB_EVENT_PORT_ERR;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 
 	case MLX5_DEV_EVENT_PORT_INITIALIZED:
@@ -1012,22 +934,22 @@ static void mlx5_ib_event(struct mlx5_co
 
 	case MLX5_DEV_EVENT_LID_CHANGE:
 		ibev.event = IB_EVENT_LID_CHANGE;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 
 	case MLX5_DEV_EVENT_PKEY_CHANGE:
 		ibev.event = IB_EVENT_PKEY_CHANGE;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 
 	case MLX5_DEV_EVENT_GUID_CHANGE:
 		ibev.event = IB_EVENT_GID_CHANGE;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 
 	case MLX5_DEV_EVENT_CLIENT_REREG:
 		ibev.event = IB_EVENT_CLIENT_REREGISTER;
-		port = *(u8 *)data;
+		port = (u8)param;
 		break;
 	}
 
@@ -1047,7 +969,7 @@ static void get_ext_port_caps(struct mlx
 {
 	int port;
 
-	for (port = 1; port <= dev->mdev.caps.num_ports; port++)
+	for (port = 1; port <= dev->mdev->caps.num_ports; port++)
 		mlx5_query_ext_port_caps(dev, port);
 }
 
@@ -1072,14 +994,14 @@ static int get_port_caps(struct mlx5_ib_
 		goto out;
 	}
 
-	for (port = 1; port <= dev->mdev.caps.num_ports; port++) {
+	for (port = 1; port <= dev->mdev->caps.num_ports; port++) {
 		err = mlx5_ib_query_port(&dev->ib_dev, port, pprops);
 		if (err) {
 			mlx5_ib_warn(dev, "query_port %d failed %d\n", port, err);
 			break;
 		}
-		dev->mdev.caps.port[port - 1].pkey_table_len = dprops->max_pkeys;
-		dev->mdev.caps.port[port - 1].gid_table_len = pprops->gid_tbl_len;
+		dev->mdev->caps.port[port - 1].pkey_table_len = dprops->max_pkeys;
+		dev->mdev->caps.port[port - 1].gid_table_len = pprops->gid_tbl_len;
 		mlx5_ib_dbg(dev, "pkey_table_len %d, gid_table_len %d\n",
 			    dprops->max_pkeys, pprops->gid_tbl_len);
 	}
@@ -1328,10 +1250,8 @@ static void destroy_dev_resources(struct
 	mlx5_ib_dealloc_pd(devr->p0);
 }
 
-static int init_one(struct pci_dev *pdev,
-		    const struct pci_device_id *id)
+static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 {
-	struct mlx5_core_dev *mdev;
 	struct mlx5_ib_dev *dev;
 	int err;
 	int i;
@@ -1340,28 +1260,19 @@ static int init_one(struct pci_dev *pdev
 
 	dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
 	if (!dev)
-		return -ENOMEM;
+		return NULL;
 
-	mdev = &dev->mdev;
-	mdev->event = mlx5_ib_event;
-	if (prof_sel >= ARRAY_SIZE(profile)) {
-		pr_warn("selected pofile out of range, selceting default\n");
-		prof_sel = 0;
-	}
-	mdev->profile = &profile[prof_sel];
-	err = mlx5_dev_init(mdev, pdev);
-	if (err)
-		goto err_free;
+	dev->mdev = mdev;
 
 	err = get_port_caps(dev);
 	if (err)
-		goto err_cleanup;
+		goto err_dealloc;
 
 	get_ext_port_caps(dev);
 
 	err = alloc_comp_eqs(dev);
 	if (err)
-		goto err_cleanup;
+		goto err_dealloc;
 
 	MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock);
 
@@ -1480,7 +1391,7 @@ static int init_one(struct pci_dev *pdev
 
 	dev->ib_active = true;
 
-	return 0;
+	return dev;
 
 err_umrc:
 	destroy_umrc_res(dev);
@@ -1494,49 +1405,39 @@ err_rsrc:
 err_eqs:
 	free_comp_eqs(dev);
 
-err_cleanup:
-	mlx5_dev_cleanup(mdev);
-
-err_free:
+err_dealloc:
 	ib_dealloc_device((struct ib_device *)dev);
 
-	return err;
+	return NULL;
 }
 
-static void remove_one(struct pci_dev *pdev)
+static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
 {
-	struct mlx5_ib_dev *dev = mlx5_pci2ibdev(pdev);
-
+	struct mlx5_ib_dev *dev = context;
 	destroy_umrc_res(dev);
 	ib_unregister_device(&dev->ib_dev);
 	destroy_dev_resources(&dev->devr);
 	free_comp_eqs(dev);
-	mlx5_dev_cleanup(&dev->mdev);
 	ib_dealloc_device(&dev->ib_dev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(mlx5_ib_pci_table) = {
-	{ PCI_VDEVICE(MELLANOX, 4113) }, /* MT4113 Connect-IB */
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mlx5_ib_pci_table);
-
-static struct pci_driver mlx5_ib_driver = {
-	.name		= DRIVER_NAME,
-	.id_table	= mlx5_ib_pci_table,
-	.probe		= init_one,
-	.remove		= remove_one
+static struct mlx5_interface mlx5_ib_interface = {
+	.add            = mlx5_ib_add,
+	.remove         = mlx5_ib_remove,
+	.event          = mlx5_ib_event,
 };
 
 static int __init mlx5_ib_init(void)
 {
-	return pci_register_driver(&mlx5_ib_driver);
+	if (deprecated_prof_sel != 2)
+		pr_warn("prof_sel is deprecated for mlx5_ib, set it for mlx5_core\n");
+
+	return mlx5_register_interface(&mlx5_ib_interface);
 }
 
 static void __exit mlx5_ib_cleanup(void)
 {
-	pci_unregister_driver(&mlx5_ib_driver);
+	mlx5_unregister_interface(&mlx5_ib_interface);
 }
 
 module_init(mlx5_ib_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mem.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mem.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,7 +148,7 @@ int mlx5_ib_get_buf_offset(u64 addr, int
 	u64 off_mask;
 	u64 buf_off;
 
-	page_size = 1 << page_shift;
+	page_size = (u64)1 << page_shift;
 	page_mask = page_size - 1;
 	buf_off = addr & page_mask;
 	off_size = page_size >> 6;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h	2014-09-28 17:29:07.000000000 -0400
@@ -360,7 +360,7 @@ struct mlx5_ib_resources {
 
 struct mlx5_ib_dev {
 	struct ib_device		ib_dev;
-	struct mlx5_core_dev		mdev;
+	struct mlx5_core_dev		*mdev;
 	MLX5_DECLARE_DOORBELL_LOCK(uar_lock);
 	struct list_head		eqs_list;
 	int				num_ports;
@@ -454,16 +454,6 @@ static inline struct mlx5_ib_ah *to_mah(
 	return container_of(ibah, struct mlx5_ib_ah, ibah);
 }
 
-static inline struct mlx5_ib_dev *mlx5_core2ibdev(struct mlx5_core_dev *dev)
-{
-	return container_of(dev, struct mlx5_ib_dev, mdev);
-}
-
-static inline struct mlx5_ib_dev *mlx5_pci2ibdev(struct pci_dev *pdev)
-{
-	return mlx5_core2ibdev(pci2mlx5_core_dev(pdev));
-}
-
 int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
 			struct mlx5_db *db);
 void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db);
@@ -471,7 +461,7 @@ void __mlx5_ib_cq_clean(struct mlx5_ib_c
 void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
 void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
 int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
-		 int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+		 u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh,
 		 void *in_mad, void *response_mad);
 struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr,
 			   struct mlx5_ib_ah *ah);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mr.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mr.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/mr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/mr.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ static void reg_mr_callback(int status,
 	struct mlx5_cache_ent *ent = &cache->ent[c];
 	u8 key;
 	unsigned long flags;
-	struct mlx5_mr_table *table = &dev->mdev.priv.mr_table;
+	struct mlx5_mr_table *table = &dev->mdev->priv.mr_table;
 	int err;
 
 	spin_lock_irqsave(&ent->lock, flags);
@@ -97,9 +97,9 @@ static void reg_mr_callback(int status,
 		return;
 	}
 
-	spin_lock_irqsave(&dev->mdev.priv.mkey_lock, flags);
-	key = dev->mdev.priv.mkey_key++;
-	spin_unlock_irqrestore(&dev->mdev.priv.mkey_lock, flags);
+	spin_lock_irqsave(&dev->mdev->priv.mkey_lock, flags);
+	key = dev->mdev->priv.mkey_key++;
+	spin_unlock_irqrestore(&dev->mdev->priv.mkey_lock, flags);
 	mr->mmr.key = mlx5_idx_to_mkey(be32_to_cpu(mr->out.mkey) & 0xffffff) | key;
 
 	cache->last_add = jiffies;
@@ -155,7 +155,7 @@ static int add_keys(struct mlx5_ib_dev *
 		spin_lock_irq(&ent->lock);
 		ent->pending++;
 		spin_unlock_irq(&ent->lock);
-		err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in,
+		err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in,
 					    sizeof(*in), reg_mr_callback,
 					    mr, &mr->out);
 		if (err) {
@@ -188,7 +188,7 @@ static void remove_keys(struct mlx5_ib_d
 		ent->cur--;
 		ent->size--;
 		spin_unlock_irq(&ent->lock);
-		err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+		err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
 		if (err)
 			mlx5_ib_warn(dev, "failed destroy mkey\n");
 		else
@@ -479,7 +479,7 @@ static void clean_keys(struct mlx5_ib_de
 		ent->cur--;
 		ent->size--;
 		spin_unlock_irq(&ent->lock);
-		err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+		err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
 		if (err)
 			mlx5_ib_warn(dev, "failed destroy mkey\n");
 		else
@@ -496,7 +496,7 @@ static int mlx5_mr_cache_debugfs_init(st
 	if (!mlx5_debugfs_root)
 		return 0;
 
-	cache->root = debugfs_create_dir("mr_cache", dev->mdev.priv.dbg_root);
+	cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
 	if (!cache->root)
 		return -ENOMEM;
 
@@ -571,8 +571,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)
-			limit = dev->mdev.profile->mr_cache[i].limit;
+		if (dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE)
+			limit = dev->mdev->profile->mr_cache[i].limit;
 		else
 			limit = 0;
 
@@ -610,7 +610,7 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib
 struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
 {
 	struct mlx5_ib_dev *dev = to_mdev(pd->device);
-	struct mlx5_core_dev *mdev = &dev->mdev;
+	struct mlx5_core_dev *mdev = dev->mdev;
 	struct mlx5_create_mkey_mbox_in *in;
 	struct mlx5_mkey_seg *seg;
 	struct mlx5_ib_mr *mr;
@@ -846,7 +846,7 @@ static struct mlx5_ib_mr *reg_create(str
 	in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
 	in->xlat_oct_act_size = cpu_to_be32(get_octo_len(virt_addr, length,
 							 1 << page_shift));
-	err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, inlen, NULL,
+	err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, inlen, NULL,
 				    NULL, NULL);
 	if (err) {
 		mlx5_ib_warn(dev, "create mkey failed\n");
@@ -923,7 +923,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct
 	mr->umem = umem;
 	mr->npages = npages;
 	spin_lock(&dev->mr_lock);
-	dev->mdev.priv.reg_pages += npages;
+	dev->mdev->priv.reg_pages += npages;
 	spin_unlock(&dev->mr_lock);
 	mr->ibmr.lkey = mr->mmr.key;
 	mr->ibmr.rkey = mr->mmr.key;
@@ -978,7 +978,7 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
 	int err;
 
 	if (!umred) {
-		err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+		err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
 		if (err) {
 			mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
 				     mr->mmr.key, err);
@@ -996,7 +996,7 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
 	if (umem) {
 		ib_umem_release(umem);
 		spin_lock(&dev->mr_lock);
-		dev->mdev.priv.reg_pages -= npages;
+		dev->mdev->priv.reg_pages -= npages;
 		spin_unlock(&dev->mr_lock);
 	}
 
@@ -1044,7 +1044,7 @@ struct ib_mr *mlx5_ib_create_mr(struct i
 		}
 
 		/* create mem & wire PSVs */
-		err = mlx5_core_create_psv(&dev->mdev, to_mpd(pd)->pdn,
+		err = mlx5_core_create_psv(dev->mdev, to_mpd(pd)->pdn,
 					   2, psv_index);
 		if (err)
 			goto err_free_sig;
@@ -1060,7 +1060,7 @@ struct ib_mr *mlx5_ib_create_mr(struct i
 	}
 
 	in->seg.flags = MLX5_PERM_UMR_EN | access_mode;
-	err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in),
+	err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, sizeof(*in),
 				    NULL, NULL, NULL);
 	if (err)
 		goto err_destroy_psv;
@@ -1074,11 +1074,11 @@ struct ib_mr *mlx5_ib_create_mr(struct i
 
 err_destroy_psv:
 	if (mr->sig) {
-		if (mlx5_core_destroy_psv(&dev->mdev,
+		if (mlx5_core_destroy_psv(dev->mdev,
 					  mr->sig->psv_memory.psv_idx))
 			mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
 				     mr->sig->psv_memory.psv_idx);
-		if (mlx5_core_destroy_psv(&dev->mdev,
+		if (mlx5_core_destroy_psv(dev->mdev,
 					  mr->sig->psv_wire.psv_idx))
 			mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
 				     mr->sig->psv_wire.psv_idx);
@@ -1099,18 +1099,18 @@ int mlx5_ib_destroy_mr(struct ib_mr *ibm
 	int err;
 
 	if (mr->sig) {
-		if (mlx5_core_destroy_psv(&dev->mdev,
+		if (mlx5_core_destroy_psv(dev->mdev,
 					  mr->sig->psv_memory.psv_idx))
 			mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
 				     mr->sig->psv_memory.psv_idx);
-		if (mlx5_core_destroy_psv(&dev->mdev,
+		if (mlx5_core_destroy_psv(dev->mdev,
 					  mr->sig->psv_wire.psv_idx))
 			mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
 				     mr->sig->psv_wire.psv_idx);
 		kfree(mr->sig);
 	}
 
-	err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+	err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
 	if (err) {
 		mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
 			     mr->mmr.key, err);
@@ -1149,7 +1149,7 @@ struct ib_mr *mlx5_ib_alloc_fast_reg_mr(
 	 * TBD not needed - issue 197292 */
 	in->seg.log2_page_size = PAGE_SHIFT;
 
-	err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in), NULL,
+	err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, sizeof(*in), NULL,
 				    NULL, NULL);
 	kfree(in);
 	if (err)
@@ -1202,7 +1202,7 @@ void mlx5_ib_free_fast_reg_page_list(str
 	struct mlx5_ib_dev *dev = to_mdev(page_list->device);
 	int size = page_list->max_page_list_len * sizeof(u64);
 
-	dma_free_coherent(&dev->mdev.pdev->dev, size, mfrpl->mapped_page_list,
+	dma_free_coherent(&dev->mdev->pdev->dev, size, mfrpl->mapped_page_list,
 			  mfrpl->map);
 	kfree(mfrpl->ibfrpl.page_list);
 	kfree(mfrpl);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/qp.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/qp.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/qp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/qp.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,7 +162,7 @@ static int set_rq_size(struct mlx5_ib_de
 	int wq_size;
 
 	/* Sanity check RQ size before proceeding */
-	if (cap->max_recv_wr  > dev->mdev.caps.max_wqes)
+	if (cap->max_recv_wr  > dev->mdev->caps.max_wqes)
 		return -EINVAL;
 
 	if (!has_rq) {
@@ -182,10 +182,10 @@ static int set_rq_size(struct mlx5_ib_de
 			wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size;
 			wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB);
 			qp->rq.wqe_cnt = wq_size / wqe_size;
-			if (wqe_size > dev->mdev.caps.max_rq_desc_sz) {
+			if (wqe_size > dev->mdev->caps.max_rq_desc_sz) {
 				mlx5_ib_dbg(dev, "wqe_size %d, max %d\n",
 					    wqe_size,
-					    dev->mdev.caps.max_rq_desc_sz);
+					    dev->mdev->caps.max_rq_desc_sz);
 				return -EINVAL;
 			}
 			qp->rq.wqe_shift = ilog2(wqe_size);
@@ -277,9 +277,9 @@ static int calc_sq_size(struct mlx5_ib_d
 	if (wqe_size < 0)
 		return wqe_size;
 
-	if (wqe_size > dev->mdev.caps.max_sq_desc_sz) {
+	if (wqe_size > dev->mdev->caps.max_sq_desc_sz) {
 		mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
-			    wqe_size, dev->mdev.caps.max_sq_desc_sz);
+			    wqe_size, dev->mdev->caps.max_sq_desc_sz);
 		return -EINVAL;
 	}
 
@@ -292,9 +292,9 @@ 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 > dev->mdev.caps.max_wqes) {
+	if (qp->sq.wqe_cnt > dev->mdev->caps.max_wqes) {
 		mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
-			    qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+			    qp->sq.wqe_cnt, dev->mdev->caps.max_wqes);
 		return -ENOMEM;
 	}
 	qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
@@ -311,9 +311,9 @@ static int set_user_buf_size(struct mlx5
 {
 	int desc_sz = 1 << qp->sq.wqe_shift;
 
-	if (desc_sz > dev->mdev.caps.max_sq_desc_sz) {
+	if (desc_sz > dev->mdev->caps.max_sq_desc_sz) {
 		mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
-			     desc_sz, dev->mdev.caps.max_sq_desc_sz);
+			     desc_sz, dev->mdev->caps.max_sq_desc_sz);
 		return -EINVAL;
 	}
 
@@ -325,9 +325,9 @@ static int set_user_buf_size(struct mlx5
 
 	qp->sq.wqe_cnt = ucmd->sq_wqe_count;
 
-	if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+	if (qp->sq.wqe_cnt > dev->mdev->caps.max_wqes) {
 		mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n",
-			     qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+			     qp->sq.wqe_cnt, dev->mdev->caps.max_wqes);
 		return -EINVAL;
 	}
 
@@ -674,7 +674,7 @@ static int create_kernel_qp(struct mlx5_
 	int uuarn;
 	int err;
 
-	uuari = &dev->mdev.priv.uuari;
+	uuari = &dev->mdev->priv.uuari;
 	if (init_attr->create_flags & ~(IB_QP_CREATE_SIGNATURE_EN | IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK))
 		return -EINVAL;
 
@@ -700,7 +700,7 @@ static int create_kernel_qp(struct mlx5_
 	qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
 	qp->buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift);
 
-	err = mlx5_buf_alloc(&dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf);
+	err = mlx5_buf_alloc(dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf);
 	if (err) {
 		mlx5_ib_dbg(dev, "err %d\n", err);
 		goto err_uuar;
@@ -722,7 +722,7 @@ static int create_kernel_qp(struct mlx5_
 
 	mlx5_fill_page_array(&qp->buf, (*in)->pas);
 
-	err = mlx5_db_alloc(&dev->mdev, &qp->db);
+	err = mlx5_db_alloc(dev->mdev, &qp->db);
 	if (err) {
 		mlx5_ib_dbg(dev, "err %d\n", err);
 		goto err_free;
@@ -747,7 +747,7 @@ static int create_kernel_qp(struct mlx5_
 	return 0;
 
 err_wrid:
-	mlx5_db_free(&dev->mdev, &qp->db);
+	mlx5_db_free(dev->mdev, &qp->db);
 	kfree(qp->sq.wqe_head);
 	kfree(qp->sq.w_list);
 	kfree(qp->sq.wrid);
@@ -758,23 +758,23 @@ err_free:
 	mlx5_vfree(*in);
 
 err_buf:
-	mlx5_buf_free(&dev->mdev, &qp->buf);
+	mlx5_buf_free(dev->mdev, &qp->buf);
 
 err_uuar:
-	free_uuar(&dev->mdev.priv.uuari, uuarn);
+	free_uuar(&dev->mdev->priv.uuari, uuarn);
 	return err;
 }
 
 static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
 {
-	mlx5_db_free(&dev->mdev, &qp->db);
+	mlx5_db_free(dev->mdev, &qp->db);
 	kfree(qp->sq.wqe_head);
 	kfree(qp->sq.w_list);
 	kfree(qp->sq.wrid);
 	kfree(qp->sq.wr_data);
 	kfree(qp->rq.wrid);
-	mlx5_buf_free(&dev->mdev, &qp->buf);
-	free_uuar(&dev->mdev.priv.uuari, qp->bf->uuarn);
+	mlx5_buf_free(dev->mdev, &qp->buf);
+	free_uuar(&dev->mdev->priv.uuari, qp->bf->uuarn);
 }
 
 static __be32 get_rx_type(struct mlx5_ib_qp *qp, struct ib_qp_init_attr *attr)
@@ -812,7 +812,7 @@ static int create_qp_common(struct mlx5_
 	spin_lock_init(&qp->rq.lock);
 
 	if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
-		if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
+		if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
 			mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
 			return -EINVAL;
 		} else {
@@ -851,9 +851,9 @@ static int create_qp_common(struct mlx5_
 				mlx5_ib_dbg(dev, "invalid rq params\n");
 				return -EINVAL;
 			}
-			if (ucmd.sq_wqe_count > dev->mdev.caps.max_wqes) {
+			if (ucmd.sq_wqe_count > dev->mdev->caps.max_wqes) {
 				mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n",
-					    ucmd.sq_wqe_count, dev->mdev.caps.max_wqes);
+					    ucmd.sq_wqe_count, dev->mdev->caps.max_wqes);
 				return -EINVAL;
 			}
 			err = create_user_qp(dev, pd, qp, udata, &in, &resp, &inlen);
@@ -957,7 +957,7 @@ static int create_qp_common(struct mlx5_
 
 	in->ctx.db_rec_addr = cpu_to_be64(qp->db.dma);
 
-	err = mlx5_core_create_qp(&dev->mdev, &qp->mqp, in, inlen);
+	err = mlx5_core_create_qp(dev->mdev, &qp->mqp, in, inlen);
 	if (err) {
 		mlx5_ib_dbg(dev, "create qp failed\n");
 		goto err_create;
@@ -1081,7 +1081,7 @@ static void destroy_qp_common(struct mlx
 	if (!in)
 		return;
 	if (qp->state != IB_QPS_RESET)
-		if (mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(qp->state),
+		if (mlx5_core_qp_modify(dev->mdev, to_mlx5_state(qp->state),
 					MLX5_QP_STATE_RST, in, sizeof(*in), &qp->mqp))
 			mlx5_ib_warn(dev, "mlx5_ib: modify QP %06x to RESET failed\n",
 				     qp->mqp.qpn);
@@ -1097,7 +1097,7 @@ static void destroy_qp_common(struct mlx
 		mlx5_ib_unlock_cqs(send_cq, recv_cq);
 	}
 
-	err = mlx5_core_destroy_qp(&dev->mdev, &qp->mqp);
+	err = mlx5_core_destroy_qp(dev->mdev, &qp->mqp);
 	if (err)
 		mlx5_ib_warn(dev, "failed to destroy QP 0x%x\n", qp->mqp.qpn);
 	kfree(in);
@@ -1165,7 +1165,7 @@ struct ib_qp *mlx5_ib_create_qp(struct i
 	switch (init_attr->qp_type) {
 	case IB_QPT_XRC_TGT:
 	case IB_QPT_XRC_INI:
-		if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC)) {
+		if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_XRC)) {
 			mlx5_ib_dbg(dev, "XRC not supported\n");
 			return ERR_PTR(-ENOSYS);
 		}
@@ -1279,7 +1279,7 @@ static int ib_rate_to_mlx5(struct mlx5_i
 	} else {
 		while (rate != IB_RATE_2_5_GBPS &&
 		       !(1 << (rate + MLX5_STAT_RATE_OFFSET) &
-			 dev->mdev.caps.stat_rate_support))
+			 dev->mdev->caps.stat_rate_support))
 			--rate;
 	}
 
@@ -1318,9 +1318,9 @@ static int mlx5_set_path(struct mlx5_ib_
 	path->port = port;
 
 	if (ah->ah_flags & IB_AH_GRH) {
-		if (ah->grh.sgid_index >= dev->mdev.caps.port[port - 1].gid_table_len) {
+		if (ah->grh.sgid_index >= dev->mdev->caps.port[port - 1].gid_table_len) {
 			pr_err(KERN_ERR "sgid_index (%u) too large. max is %d\n",
-			       ah->grh.sgid_index, dev->mdev.caps.port[port - 1].gid_table_len);
+			       ah->grh.sgid_index, dev->mdev->caps.port[port - 1].gid_table_len);
 			return -EINVAL;
 		}
 
@@ -1539,7 +1539,7 @@ static int __mlx5_ib_modify_qp(struct ib
 			err = -EINVAL;
 			goto out;
 		}
-		context->mtu_msgmax = (attr->path_mtu << 5) | dev->mdev.caps.log_max_msg;
+		context->mtu_msgmax = (attr->path_mtu << 5) | dev->mdev->caps.log_max_msg;
 	}
 
 	if (attr_mask & IB_QP_DEST_QPN)
@@ -1637,7 +1637,7 @@ static int __mlx5_ib_modify_qp(struct ib
 	optpar = ib_mask_to_mlx5_opt(attr_mask);
 	optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st];
 	in->optparam = cpu_to_be32(optpar);
-	err = mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(cur_state),
+	err = mlx5_core_qp_modify(dev->mdev, to_mlx5_state(cur_state),
 				  to_mlx5_state(new_state), in, sqd_event,
 				  &qp->mqp);
 	if (err)
@@ -1699,21 +1699,21 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp
 		goto out;
 
 	if ((attr_mask & IB_QP_PORT) &&
-	    (attr->port_num == 0 || attr->port_num > dev->mdev.caps.num_ports))
+	    (attr->port_num == 0 || attr->port_num > dev->mdev->caps.num_ports))
 		goto out;
 
 	if (attr_mask & IB_QP_PKEY_INDEX) {
 		port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
-		if (attr->pkey_index >= dev->mdev.caps.port[port - 1].pkey_table_len)
+		if (attr->pkey_index >= dev->mdev->caps.port[port - 1].pkey_table_len)
 			goto out;
 	}
 
 	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
-	    attr->max_rd_atomic > dev->mdev.caps.max_ra_res_qp)
+	    attr->max_rd_atomic > dev->mdev->caps.max_ra_res_qp)
 		goto out;
 
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
-	    attr->max_dest_rd_atomic > dev->mdev.caps.max_ra_req_qp)
+	    attr->max_dest_rd_atomic > dev->mdev->caps.max_ra_req_qp)
 		goto out;
 
 	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
@@ -2479,7 +2479,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp
 {
 	struct mlx5_wqe_ctrl_seg *ctrl = NULL;  /* compiler warning */
 	struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
-	struct mlx5_core_dev *mdev = &dev->mdev;
+	struct mlx5_core_dev *mdev = dev->mdev;
 	struct mlx5_ib_qp *qp = to_mqp(ibqp);
 	struct mlx5_ib_mr *mr;
 	struct mlx5_wqe_data_seg *dpseg;
@@ -2501,7 +2501,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp
 	spin_lock_irqsave(&qp->sq.lock, flags);
 
 	for (nreq = 0; wr; nreq++, wr = wr->next) {
-		if (unlikely(wr->opcode >= sizeof(mlx5_ib_opcode) / sizeof(mlx5_ib_opcode[0]))) {
+		if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
 			mlx5_ib_warn(dev, "\n");
 			err = -EINVAL;
 			*bad_wr = wr;
@@ -2539,7 +2539,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp
 			case IB_WR_RDMA_WRITE_WITH_IMM:
 				set_raddr_seg(seg, wr->wr.rdma.remote_addr,
 					      wr->wr.rdma.rkey);
-				seg  += sizeof(struct mlx5_wqe_raddr_seg);
+				seg += sizeof(struct mlx5_wqe_raddr_seg);
 				size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
 				break;
 
@@ -2668,7 +2668,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp
 		case IB_QPT_SMI:
 		case IB_QPT_GSI:
 			set_datagram_seg(seg, wr);
-			seg  += sizeof(struct mlx5_wqe_datagram_seg);
+			seg += sizeof(struct mlx5_wqe_datagram_seg);
 			size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
 			if (unlikely((seg == qend)))
 				seg = mlx5_get_send_wqe(qp, 0);
@@ -2888,7 +2888,7 @@ static int to_ib_qp_access_flags(int mlx
 static void to_ib_ah_attr(struct mlx5_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr,
 				struct mlx5_qp_path *path)
 {
-	struct mlx5_core_dev *dev = &ibdev->mdev;
+	struct mlx5_core_dev *dev = ibdev->mdev;
 
 	memset(ib_ah_attr, 0, sizeof(*ib_ah_attr));
 	ib_ah_attr->port_num	  = path->port;
@@ -2931,7 +2931,7 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp,
 		goto out;
 	}
 	context = &outb->ctx;
-	err = mlx5_core_qp_query(&dev->mdev, &qp->mqp, outb, sizeof(*outb));
+	err = mlx5_core_qp_query(dev->mdev, &qp->mqp, outb, sizeof(*outb));
 	if (err)
 		goto out_free;
 
@@ -3014,14 +3014,14 @@ struct ib_xrcd *mlx5_ib_alloc_xrcd(struc
 	struct mlx5_ib_xrcd *xrcd;
 	int err;
 
-	if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC))
+	if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_XRC))
 		return ERR_PTR(-ENOSYS);
 
 	xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL);
 	if (!xrcd)
 		return ERR_PTR(-ENOMEM);
 
-	err = mlx5_core_xrcd_alloc(&dev->mdev, &xrcd->xrcdn);
+	err = mlx5_core_xrcd_alloc(dev->mdev, &xrcd->xrcdn);
 	if (err) {
 		kfree(xrcd);
 		return ERR_PTR(-ENOMEM);
@@ -3036,7 +3036,7 @@ int mlx5_ib_dealloc_xrcd(struct ib_xrcd
 	u32 xrcdn = to_mxrcd(xrcd)->xrcdn;
 	int err;
 
-	err = mlx5_core_xrcd_dealloc(&dev->mdev, xrcdn);
+	err = mlx5_core_xrcd_dealloc(dev->mdev, xrcdn);
 	if (err) {
 		mlx5_ib_warn(dev, "failed to dealloc xrcdn 0x%x\n", xrcdn);
 		return err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/srq.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/srq.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mlx5/srq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mlx5/srq.c	2014-09-28 17:29:07.000000000 -0400
@@ -159,7 +159,7 @@ static int create_srq_kernel(struct mlx5
 	int page_shift;
 	int npages;
 
-	err = mlx5_db_alloc(&dev->mdev, &srq->db);
+	err = mlx5_db_alloc(dev->mdev, &srq->db);
 	if (err) {
 		mlx5_ib_warn(dev, "alloc dbell rec failed\n");
 		return err;
@@ -167,7 +167,7 @@ static int create_srq_kernel(struct mlx5
 
 	*srq->db.db = 0;
 
-	if (mlx5_buf_alloc(&dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) {
+	if (mlx5_buf_alloc(dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) {
 		mlx5_ib_dbg(dev, "buf alloc failed\n");
 		err = -ENOMEM;
 		goto err_db;
@@ -212,10 +212,10 @@ err_in:
 	mlx5_vfree(*in);
 
 err_buf:
-	mlx5_buf_free(&dev->mdev, &srq->buf);
+	mlx5_buf_free(dev->mdev, &srq->buf);
 
 err_db:
-	mlx5_db_free(&dev->mdev, &srq->db);
+	mlx5_db_free(dev->mdev, &srq->db);
 	return err;
 }
 
@@ -229,8 +229,8 @@ static void destroy_srq_user(struct ib_p
 static void destroy_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq)
 {
 	kfree(srq->wrid);
-	mlx5_buf_free(&dev->mdev, &srq->buf);
-	mlx5_db_free(&dev->mdev, &srq->db);
+	mlx5_buf_free(dev->mdev, &srq->buf);
+	mlx5_db_free(dev->mdev, &srq->db);
 }
 
 struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
@@ -248,10 +248,10 @@ struct ib_srq *mlx5_ib_create_srq(struct
 	u32 flgs, xrcdn;
 
 	/* Sanity check SRQ size before proceeding */
-	if (init_attr->attr.max_wr >= dev->mdev.caps.max_srq_wqes) {
+	if (init_attr->attr.max_wr >= dev->mdev->caps.max_srq_wqes) {
 		mlx5_ib_dbg(dev, "max_wr %d, cap %d\n",
 			    init_attr->attr.max_wr,
-			    dev->mdev.caps.max_srq_wqes);
+			    dev->mdev->caps.max_srq_wqes);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -303,7 +303,7 @@ struct ib_srq *mlx5_ib_create_srq(struct
 
 	in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn);
 	in->ctx.db_record = cpu_to_be64(srq->db.dma);
-	err = mlx5_core_create_srq(&dev->mdev, &srq->msrq, in, inlen);
+	err = mlx5_core_create_srq(dev->mdev, &srq->msrq, in, inlen);
 	mlx5_vfree(in);
 	if (err) {
 		mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
@@ -327,7 +327,7 @@ struct ib_srq *mlx5_ib_create_srq(struct
 	return &srq->ibsrq;
 
 err_core:
-	mlx5_core_destroy_srq(&dev->mdev, &srq->msrq);
+	mlx5_core_destroy_srq(dev->mdev, &srq->msrq);
 
 err_usr_kern_srq:
 	if (pd->uobject)
@@ -357,7 +357,7 @@ int mlx5_ib_modify_srq(struct ib_srq *ib
 			return -EINVAL;
 
 		mutex_lock(&srq->mutex);
-		ret = mlx5_core_arm_srq(&dev->mdev, &srq->msrq, attr->srq_limit, 1);
+		ret = mlx5_core_arm_srq(dev->mdev, &srq->msrq, attr->srq_limit, 1);
 		mutex_unlock(&srq->mutex);
 
 		if (ret)
@@ -378,7 +378,7 @@ int mlx5_ib_query_srq(struct ib_srq *ibs
 	if (!out)
 		return -ENOMEM;
 
-	ret = mlx5_core_query_srq(&dev->mdev, &srq->msrq, out);
+	ret = mlx5_core_query_srq(dev->mdev, &srq->msrq, out);
 	if (ret)
 		goto out_box;
 
@@ -396,7 +396,7 @@ int mlx5_ib_destroy_srq(struct ib_srq *s
 	struct mlx5_ib_dev *dev = to_mdev(srq->device);
 	struct mlx5_ib_srq *msrq = to_msrq(srq);
 
-	mlx5_core_destroy_srq(&dev->mdev, &msrq->msrq);
+	mlx5_core_destroy_srq(dev->mdev, &msrq->msrq);
 
 	if (srq->uobject) {
 		mlx5_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/mthca/mthca_mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mthca/mthca_mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/mthca/mthca_mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/mthca/mthca_mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -294,7 +294,7 @@ int mthca_create_agents(struct mthca_dev
 			agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
 						      q ? IB_QPT_GSI : IB_QPT_SMI,
 						      NULL, 0, send_handler,
-						      NULL, NULL);
+						      NULL, NULL, 0);
 			if (IS_ERR(agent)) {
 				ret = PTR_ERR(agent);
 				goto err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/nes/nes_hw.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/nes/nes_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/nes/nes_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1003,13 +1003,13 @@ int nes_init_cqp(struct nes_device *nesd
 			(sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
 			sizeof(struct nes_hw_cqp_qp_context);
 
-	nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
-			&nesdev->cqp_pbase);
+	nesdev->cqp_vbase = pci_zalloc_consistent(nesdev->pcidev,
+						  nesdev->cqp_mem_size,
+						  &nesdev->cqp_pbase);
 	if (!nesdev->cqp_vbase) {
 		nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
 		return -ENOMEM;
 	}
-	memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
 
 	/* Allocate a twice the number of CQP requests as the SQ size */
 	nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
@@ -1691,13 +1691,13 @@ int nes_init_nic_qp(struct nes_device *n
 			(NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
 			sizeof(struct nes_hw_nic_qp_context);
 
-	nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
-			&nesvnic->nic_pbase);
+	nesvnic->nic_vbase = pci_zalloc_consistent(nesdev->pcidev,
+						   nesvnic->nic_mem_size,
+						   &nesvnic->nic_pbase);
 	if (!nesvnic->nic_vbase) {
 		nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
 		return -ENOMEM;
 	}
-	memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
 	nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
 			nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2014-09-28 17:29:07.000000000 -0400
@@ -1616,8 +1616,8 @@ static struct ib_cq *nes_create_cq(struc
 				entries, nescq->cq_mem_size, nescq->hw_cq.cq_number);
 
 		/* allocate the physical buffer space */
-		mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
-				&nescq->hw_cq.cq_pbase);
+		mem = pci_zalloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
+					    &nescq->hw_cq.cq_pbase);
 		if (!mem) {
 			printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n");
 			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
@@ -1625,7 +1625,6 @@ static struct ib_cq *nes_create_cq(struc
 			return ERR_PTR(-ENOMEM);
 		}
 
-		memset(mem, 0, nescq->cq_mem_size);
 		nescq->hw_cq.cq_vbase = mem;
 		nescq->hw_cq.cq_head = 0;
 		nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,10 @@
 #include "ocrdma_ah.h"
 #include "ocrdma_hw.h"
 
+#define OCRDMA_VID_PCP_SHIFT	0xD
+
 static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
-				struct ib_ah_attr *attr, int pdid)
+			struct ib_ah_attr *attr, union ib_gid *sgid, int pdid)
 {
 	int status = 0;
 	u16 vlan_tag; bool vlan_enabled = false;
@@ -47,15 +49,14 @@ static inline int set_av_attr(struct ocr
 	memset(&eth, 0, sizeof(eth));
 	memset(&grh, 0, sizeof(grh));
 
-	ah->sgid_index = attr->grh.sgid_index;
-
+	/* VLAN */
 	vlan_tag = attr->vlan_id;
 	if (!vlan_tag || (vlan_tag > 0xFFF))
 		vlan_tag = dev->pvid;
 	if (vlan_tag && (vlan_tag < 0x1000)) {
 		eth.eth_type = cpu_to_be16(0x8100);
 		eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
-		vlan_tag |= (attr->sl & 7) << 13;
+		vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
 		eth.vlan_tag = cpu_to_be16(vlan_tag);
 		eth_sz = sizeof(struct ocrdma_eth_vlan);
 		vlan_enabled = true;
@@ -63,15 +64,14 @@ static inline int set_av_attr(struct ocr
 		eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
 		eth_sz = sizeof(struct ocrdma_eth_basic);
 	}
+	/* MAC */
 	memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
-	memcpy(&eth.dmac[0], attr->dmac, ETH_ALEN);
 	status = ocrdma_resolve_dmac(dev, attr, &eth.dmac[0]);
 	if (status)
 		return status;
-	status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index,
-			(union ib_gid *)&grh.sgid[0]);
-	if (status)
-		return status;
+	ah->sgid_index = attr->grh.sgid_index;
+	memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
+	memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
 
 	grh.tclass_flow = cpu_to_be32((6 << 28) |
 			(attr->grh.traffic_class << 24) |
@@ -79,8 +79,7 @@ static inline int set_av_attr(struct ocr
 	/* 0x1b is next header value in GRH */
 	grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
 			(0x1b << 8) | attr->grh.hop_limit);
-
-	memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
+	/* Eth HDR */
 	memcpy(&ah->av->eth_hdr, &eth, eth_sz);
 	memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
 	if (vlan_enabled)
@@ -96,10 +95,14 @@ struct ib_ah *ocrdma_create_ah(struct ib
 	struct ocrdma_ah *ah;
 	struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
 	struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
+	union ib_gid sgid;
+	u8 zmac[ETH_ALEN];
 
 	if (!(attr->ah_flags & IB_AH_GRH))
 		return ERR_PTR(-EINVAL);
 
+	if (atomic_cmpxchg(&dev->update_sl, 1, 0))
+		ocrdma_init_service_level(dev);
 	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
 	if (!ah)
 		return ERR_PTR(-ENOMEM);
@@ -107,7 +110,27 @@ struct ib_ah *ocrdma_create_ah(struct ib
 	status = ocrdma_alloc_av(dev, ah);
 	if (status)
 		goto av_err;
-	status = set_av_attr(dev, ah, attr, pd->id);
+
+	status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index, &sgid);
+	if (status) {
+		pr_err("%s(): Failed to query sgid, status = %d\n",
+		      __func__, status);
+		goto av_conf_err;
+	}
+
+	memset(&zmac, 0, ETH_ALEN);
+	if (pd->uctx &&
+	    memcmp(attr->dmac, &zmac, ETH_ALEN)) {
+		status = rdma_addr_find_dmac_by_grh(&sgid, &attr->grh.dgid,
+                                        attr->dmac, &attr->vlan_id);
+		if (status) {
+			pr_err("%s(): Failed to resolve dmac from gid." 
+				"status = %d\n", __func__, status);
+			goto av_conf_err;
+		}
+	}
+
+	status = set_av_attr(dev, ah, attr, &sgid, pd->id);
 	if (status)
 		goto av_conf_err;
 
@@ -141,7 +164,7 @@ int ocrdma_query_ah(struct ib_ah *ibah,
 	struct ocrdma_av *av = ah->av;
 	struct ocrdma_grh *grh;
 	attr->ah_flags |= IB_AH_GRH;
-	if (ah->av->valid & Bit(1)) {
+	if (ah->av->valid & OCRDMA_AV_VALID) {
 		grh = (struct ocrdma_grh *)((u8 *)ah->av +
 				sizeof(struct ocrdma_eth_vlan));
 		attr->sl = be16_to_cpu(av->eth_hdr.vlan_tag) >> 13;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 #include <be_roce.h>
 #include "ocrdma_sli.h"
 
-#define OCRDMA_ROCE_DRV_VERSION "10.2.145.0u"
+#define OCRDMA_ROCE_DRV_VERSION "10.2.287.0u"
 
 #define OCRDMA_ROCE_DRV_DESC "Emulex OneConnect RoCE Driver"
 #define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA"
@@ -137,6 +137,7 @@ struct mqe_ctx {
 	u16 cqe_status;
 	u16 ext_status;
 	bool cmd_done;
+	bool fw_error_state;
 };
 
 struct ocrdma_hw_mr {
@@ -235,7 +236,10 @@ struct ocrdma_dev {
 	struct list_head entry;
 	struct rcu_head rcu;
 	int id;
-	u64 stag_arr[OCRDMA_MAX_STAG];
+	u64 *stag_arr;
+	u8 sl; /* service level */
+	bool pfc_state;
+	atomic_t update_sl;
 	u16 pvid;
 	u32 asic_id;
 
@@ -518,4 +522,22 @@ static inline u8 ocrdma_get_asic_type(st
 				OCRDMA_SLI_ASIC_GEN_NUM_SHIFT;
 }
 
+static inline u8 ocrdma_get_pfc_prio(u8 *pfc, u8 prio)
+{
+	return *(pfc + prio);
+}
+
+static inline u8 ocrdma_get_app_prio(u8 *app_prio, u8 prio)
+{
+	return *(app_prio + prio);
+}
+
+static inline u8 ocrdma_is_enabled_and_synced(u32 state)
+{	/* May also be used to interpret TC-state, QCN-state
+	 * Appl-state and Logical-link-state in future.
+	 */
+	return (state & OCRDMA_STATE_FLAG_ENABLED) &&
+		(state & OCRDMA_STATE_FLAG_SYNC);
+}
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -525,7 +525,7 @@ static int ocrdma_mbx_mq_cq_create(struc
 
 	cmd->ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
 	cmd->eqn = eq->id;
-	cmd->cqe_count = cq->size / sizeof(struct ocrdma_mcqe);
+	cmd->pdid_cqecnt = cq->size / sizeof(struct ocrdma_mcqe);
 
 	ocrdma_build_q_pages(&cmd->pa[0], cq->size / OCRDMA_MIN_Q_PAGE_SIZE,
 			     cq->dma, PAGE_SIZE_4K);
@@ -661,7 +661,7 @@ static void ocrdma_dispatch_ibevent(stru
 {
 	struct ocrdma_qp *qp = NULL;
 	struct ocrdma_cq *cq = NULL;
-	struct ib_event ib_evt = { 0 };
+	struct ib_event ib_evt;
 	int cq_event = 0;
 	int qp_event = 1;
 	int srq_event = 0;
@@ -674,6 +674,8 @@ static void ocrdma_dispatch_ibevent(stru
 	if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID)
 		cq = dev->cq_tbl[cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK];
 
+	memset(&ib_evt, 0, sizeof(ib_evt));
+
 	ib_evt.device = &dev->ibdev;
 
 	switch (type) {
@@ -771,6 +773,10 @@ static void ocrdma_process_grp5_aync(str
 					OCRDMA_AE_PVID_MCQE_TAG_MASK) >>
 					OCRDMA_AE_PVID_MCQE_TAG_SHIFT);
 		break;
+
+	case OCRDMA_ASYNC_EVENT_COS_VALUE:
+		atomic_set(&dev->update_sl, 1);
+		break;
 	default:
 		/* Not interested evts. */
 		break;
@@ -962,8 +968,12 @@ static int ocrdma_wait_mqe_cmpl(struct o
 				    msecs_to_jiffies(30000));
 	if (status)
 		return 0;
-	else
+	else {
+		dev->mqe_ctx.fw_error_state = true;
+		pr_err("%s(%d) mailbox timeout: fw not responding\n",
+		       __func__, dev->id);
 		return -1;
+	}
 }
 
 /* issue a mailbox command on the MQ */
@@ -975,6 +985,8 @@ static int ocrdma_mbx_cmd(struct ocrdma_
 	struct ocrdma_mbx_rsp *rsp = NULL;
 
 	mutex_lock(&dev->mqe_ctx.lock);
+	if (dev->mqe_ctx.fw_error_state)
+		goto mbx_err;
 	ocrdma_post_mqe(dev, mqe);
 	status = ocrdma_wait_mqe_cmpl(dev);
 	if (status)
@@ -1078,7 +1090,8 @@ static void ocrdma_get_attr(struct ocrdm
 	    OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT;
 	attr->max_mw = rsp->max_mw;
 	attr->max_mr = rsp->max_mr;
-	attr->max_mr_size = ~0ull;
+	attr->max_mr_size = ((u64)rsp->max_mr_size_hi << 32) |
+			      rsp->max_mr_size_lo;
 	attr->max_fmr = 0;
 	attr->max_pages_per_frmr = rsp->max_pages_per_frmr;
 	attr->max_num_mr_pbl = rsp->max_num_mr_pbl;
@@ -1252,7 +1265,9 @@ static int ocrdma_mbx_get_ctrl_attribs(s
 		ctrl_attr_rsp = (struct ocrdma_get_ctrl_attribs_rsp *)dma.va;
 		hba_attribs = &ctrl_attr_rsp->ctrl_attribs.hba_attribs;
 
-		dev->hba_port_num = hba_attribs->phy_port;
+		dev->hba_port_num = (hba_attribs->ptpnum_maxdoms_hbast_cv &
+					OCRDMA_HBA_ATTRB_PTNUM_MASK)
+					>> OCRDMA_HBA_ATTRB_PTNUM_SHIFT;
 		strncpy(dev->model_number,
 			hba_attribs->controller_model_number, 31);
 	}
@@ -1302,7 +1317,8 @@ int ocrdma_mbx_get_link_speed(struct ocr
 		goto mbx_err;
 
 	rsp = (struct ocrdma_get_link_speed_rsp *)cmd;
-	*lnk_speed = rsp->phys_port_speed;
+	*lnk_speed = (rsp->pflt_pps_ld_pnum & OCRDMA_PHY_PS_MASK)
+			>> OCRDMA_PHY_PS_SHIFT;
 
 mbx_err:
 	kfree(cmd);
@@ -1328,11 +1344,16 @@ static int ocrdma_mbx_get_phy_info(struc
 		goto mbx_err;
 
 	rsp = (struct ocrdma_get_phy_info_rsp *)cmd;
-	dev->phy.phy_type = le16_to_cpu(rsp->phy_type);
+	dev->phy.phy_type =
+			(rsp->ityp_ptyp & OCRDMA_PHY_TYPE_MASK);
+	dev->phy.interface_type =
+			(rsp->ityp_ptyp & OCRDMA_IF_TYPE_MASK)
+				>> OCRDMA_IF_TYPE_SHIFT;
 	dev->phy.auto_speeds_supported  =
-			le16_to_cpu(rsp->auto_speeds_supported);
+			(rsp->fspeed_aspeed & OCRDMA_ASPEED_SUPP_MASK);
 	dev->phy.fixed_speeds_supported =
-			le16_to_cpu(rsp->fixed_speeds_supported);
+			(rsp->fspeed_aspeed & OCRDMA_FSPEED_SUPP_MASK)
+				>> OCRDMA_FSPEED_SUPP_SHIFT;
 mbx_err:
 	kfree(cmd);
 	return status;
@@ -1457,8 +1478,8 @@ static int ocrdma_mbx_create_ah_tbl(stru
 
 	pbes = (struct ocrdma_pbe *)dev->av_tbl.pbl.va;
 	for (i = 0; i < dev->av_tbl.size / OCRDMA_MIN_Q_PAGE_SIZE; i++) {
-		pbes[i].pa_lo = (u32) (pa & 0xffffffff);
-		pbes[i].pa_hi = (u32) upper_32_bits(pa);
+		pbes[i].pa_lo = (u32)cpu_to_le32(pa & 0xffffffff);
+		pbes[i].pa_hi = (u32)cpu_to_le32(upper_32_bits(pa));
 		pa += PAGE_SIZE;
 	}
 	cmd->tbl_addr[0].lo = (u32)(dev->av_tbl.pbl.pa & 0xFFFFFFFF);
@@ -1501,6 +1522,7 @@ static void ocrdma_mbx_delete_ah_tbl(str
 	ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
 	dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
 			  dev->av_tbl.pa);
+	dev->av_tbl.va = NULL;
 	dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
 			  dev->av_tbl.pbl.pa);
 	kfree(cmd);
@@ -1624,14 +1646,16 @@ int ocrdma_mbx_create_cq(struct ocrdma_d
 			cmd->cmd.pgsz_pgcnt |= OCRDMA_CREATE_CQ_DPP <<
 				OCRDMA_CREATE_CQ_TYPE_SHIFT;
 		cq->phase_change = false;
-		cmd->cmd.cqe_count = (cq->len / cqe_size);
+		cmd->cmd.pdid_cqecnt = (cq->len / cqe_size);
 	} else {
-		cmd->cmd.cqe_count = (cq->len / cqe_size) - 1;
+		cmd->cmd.pdid_cqecnt = (cq->len / cqe_size) - 1;
 		cmd->cmd.ev_cnt_flags |= OCRDMA_CREATE_CQ_FLAGS_AUTO_VALID;
 		cq->phase_change = true;
 	}
 
-	cmd->cmd.pd_id = pd_id; /* valid only for v3 */
+	/* pd_id valid only for v3 */
+	cmd->cmd.pdid_cqecnt |= (pd_id <<
+		OCRDMA_CREATE_CQ_CMD_PDID_SHIFT);
 	ocrdma_build_q_pages(&cmd->cmd.pa[0], hw_pages, cq->pa, page_size);
 	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
 	if (status)
@@ -2206,7 +2230,8 @@ int ocrdma_mbx_create_qp(struct ocrdma_q
 				OCRDMA_CREATE_QP_REQ_RQ_CQID_MASK;
 	qp->rq_cq = cq;
 
-	if (pd->dpp_enabled && pd->num_dpp_qp) {
+	if (pd->dpp_enabled && attrs->cap.max_inline_data && pd->num_dpp_qp &&
+	    (attrs->cap.max_inline_data <= dev->attr.max_inline_data)) {
 		ocrdma_set_create_qp_dpp_cmd(cmd, pd, qp, enable_dpp_cq,
 					     dpp_cq_id);
 	}
@@ -2264,6 +2289,8 @@ static int ocrdma_set_av_params(struct o
 
 	if ((ah_attr->ah_flags & IB_AH_GRH) == 0)
 		return -EINVAL;
+	if (atomic_cmpxchg(&qp->dev->update_sl, 1, 0))
+		ocrdma_init_service_level(qp->dev);
 	cmd->params.tclass_sq_psn |=
 	    (ah_attr->grh.traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT);
 	cmd->params.rnt_rc_sl_fl |=
@@ -2297,6 +2324,8 @@ static int ocrdma_set_av_params(struct o
 		cmd->params.vlan_dmac_b4_to_b5 |=
 		    vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
 		cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID;
+		cmd->params.rnt_rc_sl_fl |=
+			(qp->dev->sl & 0x07) << OCRDMA_QP_PARAMS_SL_SHIFT;
 	}
 	return 0;
 }
@@ -2604,6 +2633,168 @@ int ocrdma_mbx_destroy_srq(struct ocrdma
 	return status;
 }
 
+static int ocrdma_mbx_get_dcbx_config(struct ocrdma_dev *dev, u32 ptype,
+				      struct ocrdma_dcbx_cfg *dcbxcfg)
+{
+	int status = 0;
+	dma_addr_t pa;
+	struct ocrdma_mqe cmd;
+
+	struct ocrdma_get_dcbx_cfg_req *req = NULL;
+	struct ocrdma_get_dcbx_cfg_rsp *rsp = NULL;
+	struct pci_dev *pdev = dev->nic_info.pdev;
+	struct ocrdma_mqe_sge *mqe_sge = cmd.u.nonemb_req.sge;
+
+	memset(&cmd, 0, sizeof(struct ocrdma_mqe));
+	cmd.hdr.pyld_len = max_t (u32, sizeof(struct ocrdma_get_dcbx_cfg_rsp),
+					sizeof(struct ocrdma_get_dcbx_cfg_req));
+	req = dma_alloc_coherent(&pdev->dev, cmd.hdr.pyld_len, &pa, GFP_KERNEL);
+	if (!req) {
+		status = -ENOMEM;
+		goto mem_err;
+	}
+
+	cmd.hdr.spcl_sge_cnt_emb |= (1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) &
+					OCRDMA_MQE_HDR_SGE_CNT_MASK;
+	mqe_sge->pa_lo = (u32) (pa & 0xFFFFFFFFUL);
+	mqe_sge->pa_hi = (u32) upper_32_bits(pa);
+	mqe_sge->len = cmd.hdr.pyld_len;
+
+	memset(req, 0, sizeof(struct ocrdma_get_dcbx_cfg_req));
+	ocrdma_init_mch(&req->hdr, OCRDMA_CMD_GET_DCBX_CONFIG,
+			OCRDMA_SUBSYS_DCBX, cmd.hdr.pyld_len);
+	req->param_type = ptype;
+
+	status = ocrdma_mbx_cmd(dev, &cmd);
+	if (status)
+		goto mbx_err;
+
+	rsp = (struct ocrdma_get_dcbx_cfg_rsp *)req;
+	ocrdma_le32_to_cpu(rsp, sizeof(struct ocrdma_get_dcbx_cfg_rsp));
+	memcpy(dcbxcfg, &rsp->cfg, sizeof(struct ocrdma_dcbx_cfg));
+
+mbx_err:
+	dma_free_coherent(&pdev->dev, cmd.hdr.pyld_len, req, pa);
+mem_err:
+	return status;
+}
+
+#define OCRDMA_MAX_SERVICE_LEVEL_INDEX	0x08
+#define OCRDMA_DEFAULT_SERVICE_LEVEL	0x05
+
+static int ocrdma_parse_dcbxcfg_rsp(struct ocrdma_dev *dev, int ptype,
+				    struct ocrdma_dcbx_cfg *dcbxcfg,
+				    u8 *srvc_lvl)
+{
+	int status = -EINVAL, indx, slindx;
+	int ventry_cnt;
+	struct ocrdma_app_parameter *app_param;
+	u8 valid, proto_sel;
+	u8 app_prio, pfc_prio;
+	u16 proto;
+
+	if (!(dcbxcfg->tcv_aev_opv_st & OCRDMA_DCBX_STATE_MASK)) {
+		pr_info("%s ocrdma%d DCBX is disabled\n",
+			dev_name(&dev->nic_info.pdev->dev), dev->id);
+		goto out;
+	}
+
+	if (!ocrdma_is_enabled_and_synced(dcbxcfg->pfc_state)) {
+		pr_info("%s ocrdma%d priority flow control(%s) is %s%s\n",
+			dev_name(&dev->nic_info.pdev->dev), dev->id,
+			(ptype > 0 ? "operational" : "admin"),
+			(dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_ENABLED) ?
+			"enabled" : "disabled",
+			(dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_SYNC) ?
+			"" : ", not sync'ed");
+		goto out;
+	} else {
+		pr_info("%s ocrdma%d priority flow control is enabled and sync'ed\n",
+			dev_name(&dev->nic_info.pdev->dev), dev->id);
+	}
+
+	ventry_cnt = (dcbxcfg->tcv_aev_opv_st >>
+				OCRDMA_DCBX_APP_ENTRY_SHIFT)
+				& OCRDMA_DCBX_STATE_MASK;
+
+	for (indx = 0; indx < ventry_cnt; indx++) {
+		app_param = &dcbxcfg->app_param[indx];
+		valid = (app_param->valid_proto_app >>
+				OCRDMA_APP_PARAM_VALID_SHIFT)
+				& OCRDMA_APP_PARAM_VALID_MASK;
+		proto_sel = (app_param->valid_proto_app
+				>>  OCRDMA_APP_PARAM_PROTO_SEL_SHIFT)
+				& OCRDMA_APP_PARAM_PROTO_SEL_MASK;
+		proto = app_param->valid_proto_app &
+				OCRDMA_APP_PARAM_APP_PROTO_MASK;
+
+		if (
+			valid && proto == OCRDMA_APP_PROTO_ROCE &&
+			proto_sel == OCRDMA_PROTO_SELECT_L2) {
+			for (slindx = 0; slindx <
+				OCRDMA_MAX_SERVICE_LEVEL_INDEX; slindx++) {
+				app_prio = ocrdma_get_app_prio(
+						(u8 *)app_param->app_prio,
+						slindx);
+				pfc_prio = ocrdma_get_pfc_prio(
+						(u8 *)dcbxcfg->pfc_prio,
+						slindx);
+
+				if (app_prio && pfc_prio) {
+					*srvc_lvl = slindx;
+					status = 0;
+					goto out;
+				}
+			}
+			if (slindx == OCRDMA_MAX_SERVICE_LEVEL_INDEX) {
+				pr_info("%s ocrdma%d application priority not set for 0x%x protocol\n",
+					dev_name(&dev->nic_info.pdev->dev),
+					dev->id, proto);
+			}
+		}
+	}
+
+out:
+	return status;
+}
+
+void ocrdma_init_service_level(struct ocrdma_dev *dev)
+{
+	int status = 0, indx;
+	struct ocrdma_dcbx_cfg dcbxcfg;
+	u8 srvc_lvl = OCRDMA_DEFAULT_SERVICE_LEVEL;
+	int ptype = OCRDMA_PARAMETER_TYPE_OPER;
+
+	for (indx = 0; indx < 2; indx++) {
+		status = ocrdma_mbx_get_dcbx_config(dev, ptype, &dcbxcfg);
+		if (status) {
+			pr_err("%s(): status=%d\n", __func__, status);
+			ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
+			continue;
+		}
+
+		status = ocrdma_parse_dcbxcfg_rsp(dev, ptype,
+						  &dcbxcfg, &srvc_lvl);
+		if (status) {
+			ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
+			continue;
+		}
+
+		break;
+	}
+
+	if (status)
+		pr_info("%s ocrdma%d service level default\n",
+			dev_name(&dev->nic_info.pdev->dev), dev->id);
+	else
+		pr_info("%s ocrdma%d service level %d\n",
+			dev_name(&dev->nic_info.pdev->dev), dev->id,
+			srvc_lvl);
+
+	dev->pfc_state = ocrdma_is_enabled_and_synced(dcbxcfg.pfc_state);
+	dev->sl = srvc_lvl;
+}
+
 int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
 {
 	int i;
@@ -2709,13 +2900,15 @@ int ocrdma_init_hw(struct ocrdma_dev *de
 		goto conf_err;
 	status = ocrdma_mbx_get_phy_info(dev);
 	if (status)
-		goto conf_err;
+		goto info_attrb_err;
 	status = ocrdma_mbx_get_ctrl_attribs(dev);
 	if (status)
-		goto conf_err;
+		goto info_attrb_err;
 
 	return 0;
 
+info_attrb_err:
+	ocrdma_mbx_delete_ah_tbl(dev);
 conf_err:
 	ocrdma_destroy_mq(dev);
 mq_err:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -135,4 +135,6 @@ int ocrdma_get_irq(struct ocrdma_dev *de
 
 int ocrdma_mbx_rdma_stats(struct ocrdma_dev *, bool reset);
 char *port_speed_string(struct ocrdma_dev *dev);
+void ocrdma_init_service_level(struct ocrdma_dev *);
+
 #endif				/* __OCRDMA_HW_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_main.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -324,6 +324,11 @@ static int ocrdma_alloc_resources(struct
 		if (!dev->qp_tbl)
 			goto alloc_err;
 	}
+
+	dev->stag_arr = kzalloc(sizeof(u64) * OCRDMA_MAX_STAG, GFP_KERNEL);
+	if (dev->stag_arr == NULL)
+		goto alloc_err;
+
 	spin_lock_init(&dev->av_tbl.lock);
 	spin_lock_init(&dev->flush_q_lock);
 	return 0;
@@ -334,6 +339,7 @@ alloc_err:
 
 static void ocrdma_free_resources(struct ocrdma_dev *dev)
 {
+	kfree(dev->stag_arr);
 	kfree(dev->qp_tbl);
 	kfree(dev->cq_tbl);
 	kfree(dev->sgid_tbl);
@@ -353,15 +359,25 @@ static ssize_t show_fw_ver(struct device
 {
 	struct ocrdma_dev *dev = dev_get_drvdata(device);
 
-	return scnprintf(buf, PAGE_SIZE, "%s", &dev->attr.fw_ver[0]);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", &dev->attr.fw_ver[0]);
+}
+
+static ssize_t show_hca_type(struct device *device,
+			     struct device_attribute *attr, char *buf)
+{
+	struct ocrdma_dev *dev = dev_get_drvdata(device);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n", &dev->model_number[0]);
 }
 
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
 static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+static DEVICE_ATTR(hca_type, S_IRUGO, show_hca_type, NULL);
 
 static struct device_attribute *ocrdma_attributes[] = {
 	&dev_attr_hw_rev,
-	&dev_attr_fw_ver
+	&dev_attr_fw_ver,
+	&dev_attr_hca_type
 };
 
 static void ocrdma_remove_sysfiles(struct ocrdma_dev *dev)
@@ -372,6 +388,58 @@ static void ocrdma_remove_sysfiles(struc
 		device_remove_file(&dev->ibdev.dev, ocrdma_attributes[i]);
 }
 
+static void ocrdma_init_ipv4_gids(struct ocrdma_dev *dev,
+				  struct net_device *net)
+{
+	struct in_device *in_dev;
+	union ib_gid gid;
+	in_dev = in_dev_get(net);
+	if (in_dev) {
+		for_ifa(in_dev) {
+			ipv6_addr_set_v4mapped(ifa->ifa_address,
+					       (struct in6_addr *)&gid);
+			ocrdma_add_sgid(dev, &gid);
+		}
+		endfor_ifa(in_dev);
+		in_dev_put(in_dev);
+	}
+}
+
+static void ocrdma_init_ipv6_gids(struct ocrdma_dev *dev,
+				  struct net_device *net)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	struct inet6_dev *in6_dev;
+	union ib_gid  *pgid;
+	struct inet6_ifaddr *ifp;
+	in6_dev = in6_dev_get(net);
+	if (in6_dev) {
+		read_lock_bh(&in6_dev->lock);
+		list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
+			pgid = (union ib_gid *)&ifp->addr;
+			ocrdma_add_sgid(dev, pgid);
+		}
+		read_unlock_bh(&in6_dev->lock);
+		in6_dev_put(in6_dev);
+	}
+#endif
+}
+
+static void ocrdma_init_gid_table(struct ocrdma_dev *dev)
+{
+	struct  net_device *net_dev;
+
+	for_each_netdev(&init_net, net_dev) {
+		struct net_device *real_dev = rdma_vlan_dev_real_dev(net_dev) ?
+				rdma_vlan_dev_real_dev(net_dev) : net_dev;
+
+		if (real_dev == dev->nic_info.netdev) {
+			ocrdma_init_ipv4_gids(dev, net_dev);
+			ocrdma_init_ipv6_gids(dev, net_dev);
+		}
+	}
+}
+
 static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
 {
 	int status = 0, i;
@@ -399,6 +467,8 @@ static struct ocrdma_dev *ocrdma_add(str
 	if (status)
 		goto alloc_err;
 
+	ocrdma_init_service_level(dev);
+	ocrdma_init_gid_table(dev);
 	status = ocrdma_register_device(dev);
 	if (status)
 		goto alloc_err;
@@ -508,6 +578,12 @@ static int ocrdma_close(struct ocrdma_de
 	return 0;
 }
 
+static void ocrdma_shutdown(struct ocrdma_dev *dev)
+{
+	ocrdma_close(dev);
+	ocrdma_remove(dev);
+}
+
 /* event handling via NIC driver ensures that all the NIC specific
  * initialization done before RoCE driver notifies
  * event to stack.
@@ -521,6 +597,9 @@ static void ocrdma_event_handler(struct
 	case BE_DEV_DOWN:
 		ocrdma_close(dev);
 		break;
+	case BE_DEV_SHUTDOWN:
+		ocrdma_shutdown(dev);
+		break;
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_sli.h linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_sli.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_sli.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,35 +44,39 @@ enum {
 #define OCRDMA_SUBSYS_ROCE 10
 enum {
 	OCRDMA_CMD_QUERY_CONFIG = 1,
-	OCRDMA_CMD_ALLOC_PD,
-	OCRDMA_CMD_DEALLOC_PD,
+	OCRDMA_CMD_ALLOC_PD = 2,
+	OCRDMA_CMD_DEALLOC_PD = 3,
 
-	OCRDMA_CMD_CREATE_AH_TBL,
-	OCRDMA_CMD_DELETE_AH_TBL,
+	OCRDMA_CMD_CREATE_AH_TBL = 4,
+	OCRDMA_CMD_DELETE_AH_TBL = 5,
 
-	OCRDMA_CMD_CREATE_QP,
-	OCRDMA_CMD_QUERY_QP,
-	OCRDMA_CMD_MODIFY_QP,
-	OCRDMA_CMD_DELETE_QP,
+	OCRDMA_CMD_CREATE_QP = 6,
+	OCRDMA_CMD_QUERY_QP = 7,
+	OCRDMA_CMD_MODIFY_QP = 8 ,
+	OCRDMA_CMD_DELETE_QP = 9,
 
-	OCRDMA_CMD_RSVD1,
-	OCRDMA_CMD_ALLOC_LKEY,
-	OCRDMA_CMD_DEALLOC_LKEY,
-	OCRDMA_CMD_REGISTER_NSMR,
-	OCRDMA_CMD_REREGISTER_NSMR,
-	OCRDMA_CMD_REGISTER_NSMR_CONT,
-	OCRDMA_CMD_QUERY_NSMR,
-	OCRDMA_CMD_ALLOC_MW,
-	OCRDMA_CMD_QUERY_MW,
+	OCRDMA_CMD_RSVD1 = 10,
+	OCRDMA_CMD_ALLOC_LKEY = 11,
+	OCRDMA_CMD_DEALLOC_LKEY = 12,
+	OCRDMA_CMD_REGISTER_NSMR = 13,
+	OCRDMA_CMD_REREGISTER_NSMR = 14,
+	OCRDMA_CMD_REGISTER_NSMR_CONT = 15,
+	OCRDMA_CMD_QUERY_NSMR = 16,
+	OCRDMA_CMD_ALLOC_MW = 17,
+	OCRDMA_CMD_QUERY_MW = 18,
 
-	OCRDMA_CMD_CREATE_SRQ,
-	OCRDMA_CMD_QUERY_SRQ,
-	OCRDMA_CMD_MODIFY_SRQ,
-	OCRDMA_CMD_DELETE_SRQ,
+	OCRDMA_CMD_CREATE_SRQ = 19,
+	OCRDMA_CMD_QUERY_SRQ = 20,
+	OCRDMA_CMD_MODIFY_SRQ = 21,
+	OCRDMA_CMD_DELETE_SRQ = 22,
 
-	OCRDMA_CMD_ATTACH_MCAST,
-	OCRDMA_CMD_DETACH_MCAST,
-	OCRDMA_CMD_GET_RDMA_STATS,
+	OCRDMA_CMD_ATTACH_MCAST = 23,
+	OCRDMA_CMD_DETACH_MCAST = 24,
+
+	OCRDMA_CMD_CREATE_RBQ = 25,
+	OCRDMA_CMD_DESTROY_RBQ = 26,
+
+	OCRDMA_CMD_GET_RDMA_STATS = 27,
 
 	OCRDMA_CMD_MAX
 };
@@ -103,7 +107,7 @@ enum {
 
 #define OCRDMA_MAX_QP    2048
 #define OCRDMA_MAX_CQ    2048
-#define OCRDMA_MAX_STAG  8192
+#define OCRDMA_MAX_STAG 16384
 
 enum {
 	OCRDMA_DB_RQ_OFFSET		= 0xE0,
@@ -422,7 +426,12 @@ struct ocrdma_ae_qp_mcqe {
 
 #define OCRDMA_ASYNC_RDMA_EVE_CODE 0x14
 #define OCRDMA_ASYNC_GRP5_EVE_CODE 0x5
-#define OCRDMA_ASYNC_EVENT_PVID_STATE 0x3
+
+enum ocrdma_async_grp5_events {
+	OCRDMA_ASYNC_EVENT_QOS_VALUE	= 0x01,
+	OCRDMA_ASYNC_EVENT_COS_VALUE	= 0x02,
+	OCRDMA_ASYNC_EVENT_PVID_STATE	= 0x03
+};
 
 enum OCRDMA_ASYNC_EVENT_TYPE {
 	OCRDMA_CQ_ERROR			= 0x00,
@@ -525,8 +534,8 @@ struct ocrdma_mbx_query_config {
 	u32 max_ird_ord_per_qp;
 	u32 max_shared_ird_ord;
 	u32 max_mr;
-	u32 max_mr_size_lo;
 	u32 max_mr_size_hi;
+	u32 max_mr_size_lo;
 	u32 max_num_mr_pbl;
 	u32 max_mw;
 	u32 max_fmr;
@@ -580,17 +589,26 @@ enum {
 	OCRDMA_FN_MODE_RDMA	= 0x4
 };
 
+enum {
+	OCRDMA_IF_TYPE_MASK		= 0xFFFF0000,
+	OCRDMA_IF_TYPE_SHIFT		= 0x10,
+	OCRDMA_PHY_TYPE_MASK		= 0x0000FFFF,
+	OCRDMA_FUTURE_DETAILS_MASK	= 0xFFFF0000,
+	OCRDMA_FUTURE_DETAILS_SHIFT	= 0x10,
+	OCRDMA_EX_PHY_DETAILS_MASK	= 0x0000FFFF,
+	OCRDMA_FSPEED_SUPP_MASK		= 0xFFFF0000,
+	OCRDMA_FSPEED_SUPP_SHIFT	= 0x10,
+	OCRDMA_ASPEED_SUPP_MASK		= 0x0000FFFF
+};
+
 struct ocrdma_get_phy_info_rsp {
 	struct ocrdma_mqe_hdr hdr;
 	struct ocrdma_mbx_rsp rsp;
 
-	u16 phy_type;
-	u16 interface_type;
+	u32 ityp_ptyp;
 	u32 misc_params;
-	u16 ext_phy_details;
-	u16 rsvd;
-	u16 auto_speeds_supported;
-	u16 fixed_speeds_supported;
+	u32 ftrdtl_exphydtl;
+	u32 fspeed_aspeed;
 	u32 future_use[2];
 };
 
@@ -603,19 +621,34 @@ enum {
 	OCRDMA_PHY_SPEED_40GBPS = 0x20
 };
 
+enum {
+	OCRDMA_PORT_NUM_MASK	= 0x3F,
+	OCRDMA_PT_MASK		= 0xC0,
+	OCRDMA_PT_SHIFT		= 0x6,
+	OCRDMA_LINK_DUP_MASK	= 0x0000FF00,
+	OCRDMA_LINK_DUP_SHIFT	= 0x8,
+	OCRDMA_PHY_PS_MASK	= 0x00FF0000,
+	OCRDMA_PHY_PS_SHIFT	= 0x10,
+	OCRDMA_PHY_PFLT_MASK	= 0xFF000000,
+	OCRDMA_PHY_PFLT_SHIFT	= 0x18,
+	OCRDMA_QOS_LNKSP_MASK	= 0xFFFF0000,
+	OCRDMA_QOS_LNKSP_SHIFT	= 0x10,
+	OCRDMA_LLST_MASK	= 0xFF,
+	OCRDMA_PLFC_MASK	= 0x00000400,
+	OCRDMA_PLFC_SHIFT	= 0x8,
+	OCRDMA_PLRFC_MASK	= 0x00000200,
+	OCRDMA_PLRFC_SHIFT	= 0x8,
+	OCRDMA_PLTFC_MASK	= 0x00000100,
+	OCRDMA_PLTFC_SHIFT	= 0x8
+};
 
 struct ocrdma_get_link_speed_rsp {
 	struct ocrdma_mqe_hdr hdr;
 	struct ocrdma_mbx_rsp rsp;
 
-	u8 pt_port_num;
-	u8 link_duplex;
-	u8 phys_port_speed;
-	u8 phys_port_fault;
-	u16 rsvd1;
-	u16 qos_lnk_speed;
-	u8 logical_lnk_status;
-	u8 rsvd2[3];
+	u32 pflt_pps_ld_pnum;
+	u32 qos_lsp;
+	u32 res_lls;
 };
 
 enum {
@@ -666,8 +699,7 @@ struct ocrdma_create_cq_cmd {
 	u32 pgsz_pgcnt;
 	u32 ev_cnt_flags;
 	u32 eqn;
-	u16 cqe_count;
-	u16 pd_id;
+	u32 pdid_cqecnt;
 	u32 rsvd6;
 	struct ocrdma_pa pa[OCRDMA_CREATE_CQ_MAX_PAGES];
 };
@@ -678,6 +710,10 @@ struct ocrdma_create_cq {
 };
 
 enum {
+	OCRDMA_CREATE_CQ_CMD_PDID_SHIFT	= 0x10
+};
+
+enum {
 	OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK	= 0xFFFF
 };
 
@@ -1231,7 +1267,6 @@ struct ocrdma_destroy_srq {
 
 enum {
 	OCRDMA_ALLOC_PD_ENABLE_DPP	= BIT(16),
-	OCRDMA_PD_MAX_DPP_ENABLED_QP	= 8,
 	OCRDMA_DPP_PAGE_SIZE		= 4096
 };
 
@@ -1896,12 +1931,62 @@ struct ocrdma_rdma_stats_resp {
 	struct ocrdma_rx_dbg_stats	rx_dbg_stats;
 } __packed;
 
+enum {
+	OCRDMA_HBA_ATTRB_EPROM_VER_LO_MASK	= 0xFF,
+	OCRDMA_HBA_ATTRB_EPROM_VER_HI_MASK	= 0xFF00,
+	OCRDMA_HBA_ATTRB_EPROM_VER_HI_SHIFT	= 0x08,
+	OCRDMA_HBA_ATTRB_CDBLEN_MASK		= 0xFFFF,
+	OCRDMA_HBA_ATTRB_ASIC_REV_MASK		= 0xFF0000,
+	OCRDMA_HBA_ATTRB_ASIC_REV_SHIFT		= 0x10,
+	OCRDMA_HBA_ATTRB_GUID0_MASK		= 0xFF000000,
+	OCRDMA_HBA_ATTRB_GUID0_SHIFT		= 0x18,
+	OCRDMA_HBA_ATTRB_GUID13_MASK		= 0xFF,
+	OCRDMA_HBA_ATTRB_GUID14_MASK		= 0xFF00,
+	OCRDMA_HBA_ATTRB_GUID14_SHIFT		= 0x08,
+	OCRDMA_HBA_ATTRB_GUID15_MASK		= 0xFF0000,
+	OCRDMA_HBA_ATTRB_GUID15_SHIFT		= 0x10,
+	OCRDMA_HBA_ATTRB_PCNT_MASK		= 0xFF000000,
+	OCRDMA_HBA_ATTRB_PCNT_SHIFT		= 0x18,
+	OCRDMA_HBA_ATTRB_LDTOUT_MASK		= 0xFFFF,
+	OCRDMA_HBA_ATTRB_ISCSI_VER_MASK		= 0xFF0000,
+	OCRDMA_HBA_ATTRB_ISCSI_VER_SHIFT	= 0x10,
+	OCRDMA_HBA_ATTRB_MFUNC_DEV_MASK		= 0xFF000000,
+	OCRDMA_HBA_ATTRB_MFUNC_DEV_SHIFT	= 0x18,
+	OCRDMA_HBA_ATTRB_CV_MASK		= 0xFF,
+	OCRDMA_HBA_ATTRB_HBA_ST_MASK		= 0xFF00,
+	OCRDMA_HBA_ATTRB_HBA_ST_SHIFT		= 0x08,
+	OCRDMA_HBA_ATTRB_MAX_DOMS_MASK		= 0xFF0000,
+	OCRDMA_HBA_ATTRB_MAX_DOMS_SHIFT		= 0x10,
+	OCRDMA_HBA_ATTRB_PTNUM_MASK		= 0x3F000000,
+	OCRDMA_HBA_ATTRB_PTNUM_SHIFT		= 0x18,
+	OCRDMA_HBA_ATTRB_PT_MASK		= 0xC0000000,
+	OCRDMA_HBA_ATTRB_PT_SHIFT		= 0x1E,
+	OCRDMA_HBA_ATTRB_ISCSI_FET_MASK		= 0xFF,
+	OCRDMA_HBA_ATTRB_ASIC_GEN_MASK		= 0xFF00,
+	OCRDMA_HBA_ATTRB_ASIC_GEN_SHIFT		= 0x08,
+	OCRDMA_HBA_ATTRB_PCI_VID_MASK		= 0xFFFF,
+	OCRDMA_HBA_ATTRB_PCI_DID_MASK		= 0xFFFF0000,
+	OCRDMA_HBA_ATTRB_PCI_DID_SHIFT		= 0x10,
+	OCRDMA_HBA_ATTRB_PCI_SVID_MASK		= 0xFFFF,
+	OCRDMA_HBA_ATTRB_PCI_SSID_MASK		= 0xFFFF0000,
+	OCRDMA_HBA_ATTRB_PCI_SSID_SHIFT		= 0x10,
+	OCRDMA_HBA_ATTRB_PCI_BUSNUM_MASK	= 0xFF,
+	OCRDMA_HBA_ATTRB_PCI_DEVNUM_MASK	= 0xFF00,
+	OCRDMA_HBA_ATTRB_PCI_DEVNUM_SHIFT	= 0x08,
+	OCRDMA_HBA_ATTRB_PCI_FUNCNUM_MASK	= 0xFF0000,
+	OCRDMA_HBA_ATTRB_PCI_FUNCNUM_SHIFT	= 0x10,
+	OCRDMA_HBA_ATTRB_IF_TYPE_MASK		= 0xFF000000,
+	OCRDMA_HBA_ATTRB_IF_TYPE_SHIFT		= 0x18,
+	OCRDMA_HBA_ATTRB_NETFIL_MASK		=0xFF
+};
 
 struct mgmt_hba_attribs {
 	u8 flashrom_version_string[32];
 	u8 manufacturer_name[32];
 	u32 supported_modes;
-	u32 rsvd0[3];
+	u32 rsvd_eprom_verhi_verlo;
+	u32 mbx_ds_ver;
+	u32 epfw_ds_ver;
 	u8 ncsi_ver_string[12];
 	u32 default_extended_timeout;
 	u8 controller_model_number[32];
@@ -1914,34 +1999,26 @@ struct mgmt_hba_attribs {
 	u8 driver_version_string[32];
 	u8 fw_on_flash_version_string[32];
 	u32 functionalities_supported;
-	u16 max_cdblength;
-	u8 asic_revision;
-	u8 generational_guid[16];
-	u8 hba_port_count;
-	u16 default_link_down_timeout;
-	u8 iscsi_ver_min_max;
-	u8 multifunction_device;
-	u8 cache_valid;
-	u8 hba_status;
-	u8 max_domains_supported;
-	u8 phy_port;
+	u32 guid0_asicrev_cdblen;
+	u8 generational_guid[12];
+	u32 portcnt_guid15;
+	u32 mfuncdev_iscsi_ldtout;
+	u32 ptpnum_maxdoms_hbast_cv;
 	u32 firmware_post_status;
 	u32 hba_mtu[8];
-	u32 rsvd1[4];
+	u32 res_asicgen_iscsi_feaures;
+	u32 rsvd1[3];
 };
 
 struct mgmt_controller_attrib {
 	struct mgmt_hba_attribs hba_attribs;
-	u16 pci_vendor_id;
-	u16 pci_device_id;
-	u16 pci_sub_vendor_id;
-	u16 pci_sub_system_id;
-	u8 pci_bus_number;
-	u8 pci_device_number;
-	u8 pci_function_number;
-	u8 interface_type;
-	u64 unique_identifier;
-	u32 rsvd0[5];
+	u32 pci_did_vid;
+	u32 pci_ssid_svid;
+	u32 ityp_fnum_devnum_bnum;
+	u32 uid_hi;
+	u32 uid_lo;
+	u32 res_nnetfil;
+	u32 rsvd0[4];
 };
 
 struct ocrdma_get_ctrl_attribs_rsp {
@@ -1949,5 +2026,79 @@ struct ocrdma_get_ctrl_attribs_rsp {
 	struct mgmt_controller_attrib ctrl_attribs;
 };
 
+#define OCRDMA_SUBSYS_DCBX 0x10
+
+enum OCRDMA_DCBX_OPCODE {
+	OCRDMA_CMD_GET_DCBX_CONFIG = 0x01
+};
+
+enum OCRDMA_DCBX_PARAM_TYPE {
+	OCRDMA_PARAMETER_TYPE_ADMIN	= 0x00,
+	OCRDMA_PARAMETER_TYPE_OPER	= 0x01,
+	OCRDMA_PARAMETER_TYPE_PEER	= 0x02
+};
+
+enum OCRDMA_DCBX_APP_PROTO {
+	OCRDMA_APP_PROTO_ROCE	= 0x8915
+};
+
+enum OCRDMA_DCBX_PROTO {
+	OCRDMA_PROTO_SELECT_L2	= 0x00,
+	OCRDMA_PROTO_SELECT_L4	= 0x01
+};
+
+enum OCRDMA_DCBX_APP_PARAM {
+	OCRDMA_APP_PARAM_APP_PROTO_MASK = 0xFFFF,
+	OCRDMA_APP_PARAM_PROTO_SEL_MASK = 0xFF,
+	OCRDMA_APP_PARAM_PROTO_SEL_SHIFT = 0x10,
+	OCRDMA_APP_PARAM_VALID_MASK	= 0xFF,
+	OCRDMA_APP_PARAM_VALID_SHIFT	= 0x18
+};
+
+enum OCRDMA_DCBX_STATE_FLAGS {
+	OCRDMA_STATE_FLAG_ENABLED	= 0x01,
+	OCRDMA_STATE_FLAG_ADDVERTISED	= 0x02,
+	OCRDMA_STATE_FLAG_WILLING	= 0x04,
+	OCRDMA_STATE_FLAG_SYNC		= 0x08,
+	OCRDMA_STATE_FLAG_UNSUPPORTED	= 0x40000000,
+	OCRDMA_STATE_FLAG_NEG_FAILD	= 0x80000000
+};
+
+enum OCRDMA_TCV_AEV_OPV_ST {
+	OCRDMA_DCBX_TC_SUPPORT_MASK	= 0xFF,
+	OCRDMA_DCBX_TC_SUPPORT_SHIFT	= 0x18,
+	OCRDMA_DCBX_APP_ENTRY_SHIFT	= 0x10,
+	OCRDMA_DCBX_OP_PARAM_SHIFT	= 0x08,
+	OCRDMA_DCBX_STATE_MASK		= 0xFF
+};
+
+struct ocrdma_app_parameter {
+	u32 valid_proto_app;
+	u32 oui;
+	u32 app_prio[2];
+};
+
+struct ocrdma_dcbx_cfg {
+	u32 tcv_aev_opv_st;
+	u32 tc_state;
+	u32 pfc_state;
+	u32 qcn_state;
+	u32 appl_state;
+	u32 ll_state;
+	u32 tc_bw[2];
+	u32 tc_prio[8];
+	u32 pfc_prio[2];
+	struct ocrdma_app_parameter app_param[15];
+};
+
+struct ocrdma_get_dcbx_cfg_req {
+	struct ocrdma_mbx_hdr hdr;
+	u32 param_type;
+} __packed;
+
+struct ocrdma_get_dcbx_cfg_rsp {
+	struct ocrdma_mbx_rsp hdr;
+	struct ocrdma_dcbx_cfg cfg;
+} __packed;
 
 #endif				/* __OCRDMA_SLI_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,11 +69,11 @@ int ocrdma_query_device(struct ib_device
 	memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
 	       min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver)));
 	ocrdma_get_guid(dev, (u8 *)&attr->sys_image_guid);
-	attr->max_mr_size = ~0ull;
+	attr->max_mr_size = dev->attr.max_mr_size;
 	attr->page_size_cap = 0xffff000;
 	attr->vendor_id = dev->nic_info.pdev->vendor;
 	attr->vendor_part_id = dev->nic_info.pdev->device;
-	attr->hw_ver = 0;
+	attr->hw_ver = dev->asic_id;
 	attr->max_qp = dev->attr.max_qp;
 	attr->max_ah = OCRDMA_MAX_AH;
 	attr->max_qp_wr = dev->attr.max_wqe;
@@ -101,7 +101,7 @@ int ocrdma_query_device(struct ib_device
 	attr->max_srq_sge = dev->attr.max_srq_sge;
 	attr->max_srq_wr = dev->attr.max_rqe;
 	attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
-	attr->max_fast_reg_page_list_len = 0;
+	attr->max_fast_reg_page_list_len = dev->attr.max_pages_per_frmr;
 	attr->max_pkeys = 1;
 	return 0;
 }
@@ -268,7 +268,8 @@ static struct ocrdma_pd *_ocrdma_alloc_p
 		pd->dpp_enabled =
 			ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R;
 		pd->num_dpp_qp =
-			pd->dpp_enabled ? OCRDMA_PD_MAX_DPP_ENABLED_QP : 0;
+			pd->dpp_enabled ? (dev->nic_info.db_page_size /
+					   dev->attr.wqe_size) : 0;
 	}
 
 retry:
@@ -328,7 +329,10 @@ static int ocrdma_dealloc_ucontext_pd(st
 	struct ocrdma_pd *pd = uctx->cntxt_pd;
 	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
 
-	BUG_ON(uctx->pd_in_use);
+	if (uctx->pd_in_use) {
+		pr_err("%s(%d) Freeing in use pdid=0x%x.\n",
+		       __func__, dev->id, pd->id);
+	}
 	uctx->cntxt_pd = NULL;
 	status = _ocrdma_dealloc_pd(dev, pd);
 	return status;
@@ -843,6 +847,13 @@ int ocrdma_dereg_mr(struct ib_mr *ib_mr)
 	if (mr->umem)
 		ib_umem_release(mr->umem);
 	kfree(mr);
+
+	/* Don't stop cleanup, in case FW is unresponsive */
+	if (dev->mqe_ctx.fw_error_state) {
+		status = 0;
+		pr_err("%s(%d) fw not responding.\n",
+		       __func__, dev->id);
+	}
 	return status;
 }
 
@@ -2054,6 +2065,13 @@ int ocrdma_post_send(struct ib_qp *ibqp,
 	}
 
 	while (wr) {
+		if (qp->qp_type == IB_QPT_UD &&
+		    (wr->opcode != IB_WR_SEND &&
+		     wr->opcode != IB_WR_SEND_WITH_IMM)) {
+			*bad_wr = wr;
+			status = -EINVAL;
+			break;
+		}
 		if (ocrdma_hwq_free_cnt(&qp->sq) == 0 ||
 		    wr->num_sge > qp->sq.max_sges) {
 			*bad_wr = wr;
@@ -2488,6 +2506,11 @@ static bool ocrdma_poll_err_scqe(struct
 			*stop = true;
 			expand = false;
 		}
+	} else if (is_hw_sq_empty(qp)) {
+		/* Do nothing */
+		expand = false;
+		*polled = false;
+		*stop = false;
 	} else {
 		*polled = true;
 		expand = ocrdma_update_err_scqe(ibwc, cqe, qp, status);
@@ -2593,6 +2616,11 @@ static bool ocrdma_poll_err_rcqe(struct
 			*stop = true;
 			expand = false;
 		}
+	} else if (is_hw_rq_empty(qp)) {
+		/* Do nothing */
+		expand = false;
+		*polled = false;
+		*stop = false;
 	} else {
 		*polled = true;
 		expand = ocrdma_update_err_rcqe(ibwc, cqe, qp, status);
@@ -2818,11 +2846,9 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, en
 	if (cq->first_arm) {
 		ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0);
 		cq->first_arm = false;
-		goto skip_defer;
 	}
-	cq->deferred_arm = true;
 
-skip_defer:
+	cq->deferred_arm = true;
 	cq->deferred_sol = sol_needed;
 	spin_unlock_irqrestore(&cq->cq_lock, flags);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_debugfs.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_debugfs.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,6 +193,7 @@ static void *_qp_stats_seq_start(struct
 	struct qib_qp_iter *iter;
 	loff_t n = *pos;
 
+	rcu_read_lock();
 	iter = qib_qp_iter_init(s->private);
 	if (!iter)
 		return NULL;
@@ -224,7 +225,7 @@ static void *_qp_stats_seq_next(struct s
 
 static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
 {
-	/* nothing for now */
+	rcu_read_unlock();
 }
 
 static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_init.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -1222,7 +1222,7 @@ static int qib_init_one(struct pci_dev *
 #define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: "
 #define PFX QIB_DRV_NAME ": "
 
-static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = {
+static const struct pci_device_id qib_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_QLOGIC_IB_6120) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7220) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7322) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_mad.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_mad.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -2476,7 +2476,7 @@ int qib_create_agents(struct qib_ibdev *
 		ibp = &dd->pport[p].ibport_data;
 		agent = ib_register_mad_agent(&dev->ibdev, p + 1, IB_QPT_SMI,
 					      NULL, 0, send_handler,
-					      NULL, NULL);
+					      NULL, NULL, 0);
 		if (IS_ERR(agent)) {
 			ret = PTR_ERR(agent);
 			goto err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_qp.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_qp.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_qp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_qp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1325,7 +1325,6 @@ int qib_qp_iter_next(struct qib_qp_iter
 	struct qib_qp *pqp = iter->qp;
 	struct qib_qp *qp;
 
-	rcu_read_lock();
 	for (; n < dev->qp_table_size; n++) {
 		if (pqp)
 			qp = rcu_dereference(pqp->next);
@@ -1333,18 +1332,11 @@ int qib_qp_iter_next(struct qib_qp_iter
 			qp = rcu_dereference(dev->qp_table[n]);
 		pqp = qp;
 		if (qp) {
-			if (iter->qp)
-				atomic_dec(&iter->qp->refcount);
-			atomic_inc(&qp->refcount);
-			rcu_read_unlock();
 			iter->qp = qp;
 			iter->n = n;
 			return 0;
 		}
 	}
-	rcu_read_unlock();
-	if (iter->qp)
-		atomic_dec(&iter->qp->refcount);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_user_pages.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_user_pages.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ static void __qib_release_user_pages(str
  * Call with current->mm->mmap_sem held.
  */
 static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
-				struct page **p, struct vm_area_struct **vma)
+				struct page **p)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -69,7 +69,7 @@ static int __qib_get_user_pages(unsigned
 		ret = get_user_pages(current, current->mm,
 				     start_page + got * PAGE_SIZE,
 				     num_pages - got, 1, 1,
-				     p + got, vma);
+				     p + got, NULL);
 		if (ret < 0)
 			goto bail_release;
 	}
@@ -136,7 +136,7 @@ int qib_get_user_pages(unsigned long sta
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __qib_get_user_pages(start_page, num_pages, p, NULL);
+	ret = __qib_get_user_pages(start_page, num_pages, p);
 
 	up_write(&current->mm->mmap_sem);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/hw/usnic/usnic_ib_main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/usnic/usnic_ib_main.c
--- linux-libre-3.16-gnu/drivers/infiniband/hw/usnic/usnic_ib_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/hw/usnic/usnic_ib_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -490,7 +490,7 @@ out:
 
 /* Start of PCI section */
 
-static DEFINE_PCI_DEVICE_TABLE(usnic_ib_pci_ids) = {
+static const struct pci_device_id usnic_ib_pci_ids[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
 	{0,}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2014-09-28 17:29:07.000000000 -0400
@@ -281,10 +281,8 @@ void ipoib_delete_debug_files(struct net
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	if (priv->mcg_dentry)
-		debugfs_remove(priv->mcg_dentry);
-	if (priv->path_dentry)
-		debugfs_remove(priv->path_dentry);
+	debugfs_remove(priv->mcg_dentry);
+	debugfs_remove(priv->path_dentry);
 }
 
 int ipoib_register_debugfs(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib.h linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib.h
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib.h	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,6 @@ enum {
 	IPOIB_FLAG_INITIALIZED	  = 1,
 	IPOIB_FLAG_ADMIN_UP	  = 2,
 	IPOIB_PKEY_ASSIGNED	  = 3,
-	IPOIB_PKEY_STOP		  = 4,
 	IPOIB_FLAG_SUBINTERFACE	  = 5,
 	IPOIB_MCAST_RUN		  = 6,
 	IPOIB_STOP_REAPER	  = 7,
@@ -132,6 +131,12 @@ struct ipoib_cb {
 	u8			hwaddr[INFINIBAND_ALEN];
 };
 
+static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb));
+	return (struct ipoib_cb *)skb->cb;
+}
+
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
 struct ipoib_mcast {
 	struct ib_sa_mcmember_rec mcmember;
@@ -312,7 +317,6 @@ struct ipoib_dev_priv {
 	struct list_head multicast_list;
 	struct rb_root multicast_tree;
 
-	struct delayed_work pkey_poll_task;
 	struct delayed_work mcast_task;
 	struct work_struct carrier_on_task;
 	struct work_struct flush_light;
@@ -473,10 +477,11 @@ void ipoib_ib_dev_flush_heavy(struct wor
 void ipoib_pkey_event(struct work_struct *work);
 void ipoib_ib_dev_cleanup(struct net_device *dev);
 
-int ipoib_ib_dev_open(struct net_device *dev);
+int ipoib_ib_dev_open(struct net_device *dev, int flush);
 int ipoib_ib_dev_up(struct net_device *dev);
 int ipoib_ib_dev_down(struct net_device *dev, int flush);
 int ipoib_ib_dev_stop(struct net_device *dev, int flush);
+void ipoib_pkey_dev_check_presence(struct net_device *dev);
 
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
 void ipoib_dev_cleanup(struct net_device *dev);
@@ -532,8 +537,7 @@ int  ipoib_set_mode(struct net_device *d
 
 void ipoib_setup(struct net_device *dev);
 
-void ipoib_pkey_poll(struct work_struct *work);
-int ipoib_pkey_dev_delay_open(struct net_device *dev);
+void ipoib_pkey_open(struct ipoib_dev_priv *priv);
 void ipoib_drain_cq(struct net_device *dev);
 
 void ipoib_set_ethtool_ops(struct net_device *dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2014-09-28 17:29:07.000000000 -0400
@@ -664,17 +664,18 @@ static void ipoib_ib_tx_timer_func(unsig
 	drain_tx_cq((struct net_device *)ctx);
 }
 
-int ipoib_ib_dev_open(struct net_device *dev)
+int ipoib_ib_dev_open(struct net_device *dev, int flush)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int ret;
 
-	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {
-		ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);
-		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+	ipoib_pkey_dev_check_presence(dev);
+
+	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
+		ipoib_warn(priv, "P_Key 0x%04x is %s\n", priv->pkey,
+			   (!(priv->pkey & 0x7fff) ? "Invalid" : "not found"));
 		return -1;
 	}
-	set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 
 	ret = ipoib_init_qp(dev);
 	if (ret) {
@@ -705,16 +706,17 @@ int ipoib_ib_dev_open(struct net_device
 dev_stop:
 	if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
 		napi_enable(&priv->napi);
-	ipoib_ib_dev_stop(dev, 1);
+	ipoib_ib_dev_stop(dev, flush);
 	return -1;
 }
 
-static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+void ipoib_pkey_dev_check_presence(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	u16 pkey_index = 0;
 
-	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
+	if (!(priv->pkey & 0x7fff) ||
+	    ib_find_pkey(priv->ca, priv->port, priv->pkey,
+			 &priv->pkey_index))
 		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 	else
 		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
@@ -745,14 +747,6 @@ int ipoib_ib_dev_down(struct net_device
 	clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
 	netif_carrier_off(dev);
 
-	/* Shutdown the P_Key thread if still active */
-	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
-		mutex_lock(&pkey_mutex);
-		set_bit(IPOIB_PKEY_STOP, &priv->flags);
-		cancel_delayed_work_sync(&priv->pkey_poll_task);
-		mutex_unlock(&pkey_mutex);
-	}
-
 	ipoib_mcast_stop_thread(dev, flush);
 	ipoib_mcast_dev_flush(dev);
 
@@ -924,7 +918,7 @@ int ipoib_ib_dev_init(struct net_device
 		    (unsigned long) dev);
 
 	if (dev->flags & IFF_UP) {
-		if (ipoib_ib_dev_open(dev)) {
+		if (ipoib_ib_dev_open(dev, 1)) {
 			ipoib_transport_dev_cleanup(dev);
 			return -ENODEV;
 		}
@@ -966,13 +960,27 @@ static inline int update_parent_pkey(str
 
 	return 1;
 }
+/*
+ * returns 0 if pkey value was found in a different slot.
+ */
+static inline int update_child_pkey(struct ipoib_dev_priv *priv)
+{
+	u16 old_index = priv->pkey_index;
+
+	priv->pkey_index = 0;
+	ipoib_pkey_dev_check_presence(priv->dev);
+
+	if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
+	    (old_index == priv->pkey_index))
+		return 1;
+	return 0;
+}
 
 static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
 				enum ipoib_flush_level level)
 {
 	struct ipoib_dev_priv *cpriv;
 	struct net_device *dev = priv->dev;
-	u16 new_index;
 	int result;
 
 	down_read(&priv->vlan_rwsem);
@@ -986,16 +994,20 @@ static void __ipoib_ib_dev_flush(struct
 
 	up_read(&priv->vlan_rwsem);
 
-	if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
-		/* for non-child devices must check/update the pkey value here */
-		if (level == IPOIB_FLUSH_HEAVY &&
-		    !test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
-			update_parent_pkey(priv);
+	if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) &&
+	    level != IPOIB_FLUSH_HEAVY) {
 		ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
 		return;
 	}
 
 	if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
+		/* interface is down. update pkey and leave. */
+		if (level == IPOIB_FLUSH_HEAVY) {
+			if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
+				update_parent_pkey(priv);
+			else
+				update_child_pkey(priv);
+		}
 		ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n");
 		return;
 	}
@@ -1005,20 +1017,13 @@ static void __ipoib_ib_dev_flush(struct
 		 * (parent) devices should always takes what present in pkey index 0
 		 */
 		if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
-			if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
-				clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
-				ipoib_ib_dev_down(dev, 0);
-				ipoib_ib_dev_stop(dev, 0);
-				if (ipoib_pkey_dev_delay_open(dev))
-					return;
-			}
-			/* restart QP only if P_Key index is changed */
-			if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
-			    new_index == priv->pkey_index) {
+			result = update_child_pkey(priv);
+			if (result) {
+				/* restart QP only if P_Key index is changed */
 				ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
 				return;
 			}
-			priv->pkey_index = new_index;
+
 		} else {
 			result = update_parent_pkey(priv);
 			/* restart QP only if P_Key value changed */
@@ -1038,8 +1043,12 @@ static void __ipoib_ib_dev_flush(struct
 		ipoib_ib_dev_down(dev, 0);
 
 	if (level == IPOIB_FLUSH_HEAVY) {
-		ipoib_ib_dev_stop(dev, 0);
-		ipoib_ib_dev_open(dev);
+		if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
+			ipoib_ib_dev_stop(dev, 0);
+		if (ipoib_ib_dev_open(dev, 0) != 0)
+			return;
+		if (netif_queue_stopped(dev))
+			netif_start_queue(dev);
 	}
 
 	/*
@@ -1094,54 +1103,4 @@ void ipoib_ib_dev_cleanup(struct net_dev
 	ipoib_transport_dev_cleanup(dev);
 }
 
-/*
- * Delayed P_Key Assigment Interim Support
- *
- * The following is initial implementation of delayed P_Key assigment
- * mechanism. It is using the same approach implemented for the multicast
- * group join. The single goal of this implementation is to quickly address
- * Bug #2507. This implementation will probably be removed when the P_Key
- * change async notification is available.
- */
-
-void ipoib_pkey_poll(struct work_struct *work)
-{
-	struct ipoib_dev_priv *priv =
-		container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);
-	struct net_device *dev = priv->dev;
-
-	ipoib_pkey_dev_check_presence(dev);
-
-	if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
-		ipoib_open(dev);
-	else {
-		mutex_lock(&pkey_mutex);
-		if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
-			queue_delayed_work(ipoib_workqueue,
-					   &priv->pkey_poll_task,
-					   HZ);
-		mutex_unlock(&pkey_mutex);
-	}
-}
-
-int ipoib_pkey_dev_delay_open(struct net_device *dev)
-{
-	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	/* Look for the interface pkey value in the IB Port P_Key table and */
-	/* set the interface pkey assigment flag                            */
-	ipoib_pkey_dev_check_presence(dev);
-
-	/* P_Key value not assigned yet - start polling */
-	if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
-		mutex_lock(&pkey_mutex);
-		clear_bit(IPOIB_PKEY_STOP, &priv->flags);
-		queue_delayed_work(ipoib_workqueue,
-				   &priv->pkey_poll_task,
-				   HZ);
-		mutex_unlock(&pkey_mutex);
-		return 1;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,11 +108,11 @@ int ipoib_open(struct net_device *dev)
 
 	set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
 
-	if (ipoib_pkey_dev_delay_open(dev))
-		return 0;
-
-	if (ipoib_ib_dev_open(dev))
+	if (ipoib_ib_dev_open(dev, 1)) {
+		if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
+			return 0;
 		goto err_disable;
+	}
 
 	if (ipoib_ib_dev_up(dev))
 		goto err_stop;
@@ -716,7 +716,7 @@ static int ipoib_start_xmit(struct sk_bu
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh;
-	struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+	struct ipoib_cb *cb = ipoib_skb_cb(skb);
 	struct ipoib_header *header;
 	unsigned long flags;
 
@@ -813,7 +813,7 @@ static int ipoib_hard_header(struct sk_b
 			     const void *daddr, const void *saddr, unsigned len)
 {
 	struct ipoib_header *header;
-	struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+	struct ipoib_cb *cb = ipoib_skb_cb(skb);
 
 	header = (struct ipoib_header *) skb_push(skb, sizeof *header);
 
@@ -1379,7 +1379,6 @@ void ipoib_setup(struct net_device *dev)
 	INIT_LIST_HEAD(&priv->dead_ahs);
 	INIT_LIST_HEAD(&priv->multicast_list);
 
-	INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
 	INIT_DELAYED_WORK(&priv->mcast_task,   ipoib_mcast_join_task);
 	INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task);
 	INIT_WORK(&priv->flush_light,   ipoib_ib_dev_flush_light);
@@ -1394,8 +1393,8 @@ struct ipoib_dev_priv *ipoib_intf_alloc(
 {
 	struct net_device *dev;
 
-	dev = alloc_netdev((int) sizeof (struct ipoib_dev_priv), name,
-			   ipoib_setup);
+	dev = alloc_netdev((int)sizeof(struct ipoib_dev_priv), name,
+			   NET_NAME_UNKNOWN, ipoib_setup);
 	if (!dev)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2014-09-28 17:29:07.000000000 -0400
@@ -529,21 +529,13 @@ void ipoib_mcast_join_task(struct work_s
 			  port_attr.state);
 		return;
 	}
+	priv->local_lid = port_attr.lid;
 
 	if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
 		ipoib_warn(priv, "ib_query_gid() failed\n");
 	else
 		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
 
-	{
-		struct ib_port_attr attr;
-
-		if (!ib_query_port(priv->ca, priv->port, &attr))
-			priv->local_lid = attr.lid;
-		else
-			ipoib_warn(priv, "ib_query_port failed\n");
-	}
-
 	if (!priv->broadcast) {
 		struct ipoib_mcast *broadcast;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2014-09-28 17:29:07.000000000 -0400
@@ -344,7 +344,6 @@ iscsi_iser_conn_bind(struct iscsi_cls_se
 		     int is_leading)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session;
 	struct iser_conn *ib_conn;
 	struct iscsi_endpoint *ep;
 	int error;
@@ -363,9 +362,17 @@ iscsi_iser_conn_bind(struct iscsi_cls_se
 	}
 	ib_conn = ep->dd_data;
 
-	session = conn->session;
-	if (iser_alloc_rx_descriptors(ib_conn, session))
-		return -ENOMEM;
+	mutex_lock(&ib_conn->state_mutex);
+	if (ib_conn->state != ISER_CONN_UP) {
+		error = -EINVAL;
+		iser_err("iser_conn %p state is %d, teardown started\n",
+			 ib_conn, ib_conn->state);
+		goto out;
+	}
+
+	error = iser_alloc_rx_descriptors(ib_conn, conn->session);
+	if (error)
+		goto out;
 
 	/* binds the iSER connection retrieved from the previously
 	 * connected ep_handle to the iSCSI layer connection. exchanges
@@ -375,7 +382,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_se
 	conn->dd_data = ib_conn;
 	ib_conn->iscsi_conn = conn;
 
-	return 0;
+out:
+	mutex_unlock(&ib_conn->state_mutex);
+	return error;
 }
 
 static int
@@ -596,20 +605,28 @@ iscsi_iser_ep_connect(struct Scsi_Host *
 	struct iser_conn *ib_conn;
 	struct iscsi_endpoint *ep;
 
-	ep = iscsi_create_endpoint(sizeof(*ib_conn));
+	ep = iscsi_create_endpoint(0);
 	if (!ep)
 		return ERR_PTR(-ENOMEM);
 
-	ib_conn = ep->dd_data;
+	ib_conn = kzalloc(sizeof(*ib_conn), GFP_KERNEL);
+	if (!ib_conn) {
+		err = -ENOMEM;
+		goto failure;
+	}
+
+	ep->dd_data = ib_conn;
 	ib_conn->ep = ep;
 	iser_conn_init(ib_conn);
 
-	err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr,
-			   non_blocking);
+	err = iser_connect(ib_conn, NULL, dst_addr, non_blocking);
 	if (err)
-		return ERR_PTR(err);
+		goto failure;
 
 	return ep;
+failure:
+	iscsi_destroy_endpoint(ep);
+	return ERR_PTR(err);
 }
 
 static int
@@ -619,15 +636,16 @@ iscsi_iser_ep_poll(struct iscsi_endpoint
 	int rc;
 
 	ib_conn = ep->dd_data;
-	rc = wait_event_interruptible_timeout(ib_conn->wait,
-			     ib_conn->state == ISER_CONN_UP,
-			     msecs_to_jiffies(timeout_ms));
-
+	rc = wait_for_completion_interruptible_timeout(&ib_conn->up_completion,
+						       msecs_to_jiffies(timeout_ms));
 	/* if conn establishment failed, return error code to iscsi */
-	if (!rc &&
-	    (ib_conn->state == ISER_CONN_TERMINATING ||
-	     ib_conn->state == ISER_CONN_DOWN))
-		rc = -1;
+	if (rc == 0) {
+		mutex_lock(&ib_conn->state_mutex);
+		if (ib_conn->state == ISER_CONN_TERMINATING ||
+		    ib_conn->state == ISER_CONN_DOWN)
+			rc = -1;
+		mutex_unlock(&ib_conn->state_mutex);
+	}
 
 	iser_info("ib conn %p rc = %d\n", ib_conn, rc);
 
@@ -646,19 +664,25 @@ iscsi_iser_ep_disconnect(struct iscsi_en
 
 	ib_conn = ep->dd_data;
 	iser_info("ep %p ib conn %p state %d\n", ep, ib_conn, ib_conn->state);
+	mutex_lock(&ib_conn->state_mutex);
 	iser_conn_terminate(ib_conn);
 
 	/*
-	 * if iser_conn and iscsi_conn are bound, we must wait iscsi_conn_stop
-	 * call and ISER_CONN_DOWN state before freeing the iser resources.
-	 * otherwise we are safe to free resources immediately.
+	 * if iser_conn and iscsi_conn are bound, we must wait for
+	 * iscsi_conn_stop and flush errors completion before freeing
+	 * the iser resources. Otherwise we are safe to free resources
+	 * immediately.
 	 */
 	if (ib_conn->iscsi_conn) {
 		INIT_WORK(&ib_conn->release_work, iser_release_work);
 		queue_work(release_wq, &ib_conn->release_work);
+		mutex_unlock(&ib_conn->state_mutex);
 	} else {
+		ib_conn->state = ISER_CONN_DOWN;
+		mutex_unlock(&ib_conn->state_mutex);
 		iser_conn_release(ib_conn);
 	}
+	iscsi_destroy_endpoint(ep);
 }
 
 static umode_t iser_attr_is_visible(int param_type, int param)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,7 +69,7 @@
 
 #define DRV_NAME	"iser"
 #define PFX		DRV_NAME ": "
-#define DRV_VER		"1.4"
+#define DRV_VER		"1.4.1"
 
 #define iser_dbg(fmt, arg...)				\
 	do {						\
@@ -326,7 +326,6 @@ struct iser_conn {
 	struct iser_device           *device;       /* device context          */
 	struct rdma_cm_id            *cma_id;       /* CMA ID		       */
 	struct ib_qp	             *qp;           /* QP 		       */
-	wait_queue_head_t	     wait;          /* waitq for conn/disconn  */
 	unsigned		     qp_max_recv_dtos; /* num of rx buffers */
 	unsigned		     qp_max_recv_dtos_mask; /* above minus 1 */
 	unsigned		     min_posted_rx; /* qp_max_recv_dtos >> 2 */
@@ -335,6 +334,9 @@ struct iser_conn {
 	char 			     name[ISER_OBJECT_NAME_SIZE];
 	struct work_struct	     release_work;
 	struct completion	     stop_completion;
+	struct mutex		     state_mutex;
+	struct completion	     flush_completion;
+	struct completion	     up_completion;
 	struct list_head	     conn_list;       /* entry in ig conn list */
 
 	char  			     *login_buf;
@@ -448,8 +450,8 @@ int  iser_reg_rdma_mem_fastreg(struct is
 			       enum iser_data_dir cmd_dir);
 
 int  iser_connect(struct iser_conn   *ib_conn,
-		  struct sockaddr_in *src_addr,
-		  struct sockaddr_in *dst_addr,
+		  struct sockaddr    *src_addr,
+		  struct sockaddr    *dst_addr,
 		  int                non_blocking);
 
 int  iser_reg_page_vec(struct iser_conn     *ib_conn,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iser_verbs.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iser_verbs.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ static int iser_create_device_ib_res(str
 {
 	struct iser_cq_desc *cq_desc;
 	struct ib_device_attr *dev_attr = &device->dev_attr;
-	int ret, i, j;
+	int ret, i;
 
 	ret = ib_query_device(device->ib_device, dev_attr);
 	if (ret) {
@@ -125,16 +125,20 @@ static int iser_create_device_ib_res(str
 					  iser_cq_event_callback,
 					  (void *)&cq_desc[i],
 					  ISER_MAX_RX_CQ_LEN, i);
-		if (IS_ERR(device->rx_cq[i]))
+		if (IS_ERR(device->rx_cq[i])) {
+			device->rx_cq[i] = NULL;
 			goto cq_err;
+		}
 
 		device->tx_cq[i] = ib_create_cq(device->ib_device,
 					  NULL, iser_cq_event_callback,
 					  (void *)&cq_desc[i],
 					  ISER_MAX_TX_CQ_LEN, i);
 
-		if (IS_ERR(device->tx_cq[i]))
+		if (IS_ERR(device->tx_cq[i])) {
+			device->tx_cq[i] = NULL;
 			goto cq_err;
+		}
 
 		if (ib_req_notify_cq(device->rx_cq[i], IB_CQ_NEXT_COMP))
 			goto cq_err;
@@ -160,14 +164,14 @@ static int iser_create_device_ib_res(str
 handler_err:
 	ib_dereg_mr(device->mr);
 dma_mr_err:
-	for (j = 0; j < device->cqs_used; j++)
-		tasklet_kill(&device->cq_tasklet[j]);
+	for (i = 0; i < device->cqs_used; i++)
+		tasklet_kill(&device->cq_tasklet[i]);
 cq_err:
-	for (j = 0; j < i; j++) {
-		if (device->tx_cq[j])
-			ib_destroy_cq(device->tx_cq[j]);
-		if (device->rx_cq[j])
-			ib_destroy_cq(device->rx_cq[j]);
+	for (i = 0; i < device->cqs_used; i++) {
+		if (device->tx_cq[i])
+			ib_destroy_cq(device->tx_cq[i]);
+		if (device->rx_cq[i])
+			ib_destroy_cq(device->rx_cq[i]);
 	}
 	ib_dealloc_pd(device->pd);
 pd_err:
@@ -491,10 +495,9 @@ out_err:
 }
 
 /**
- * releases the QP objects, returns 0 on success,
- * -1 on failure
+ * releases the QP object
  */
-static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
+static void iser_free_ib_conn_res(struct iser_conn *ib_conn)
 {
 	int cq_index;
 	BUG_ON(ib_conn == NULL);
@@ -513,8 +516,6 @@ static int iser_free_ib_conn_res(struct
 	}
 
 	ib_conn->qp	  = NULL;
-
-	return 0;
 }
 
 /**
@@ -568,31 +569,40 @@ static void iser_device_try_release(stru
 	mutex_unlock(&ig.device_list_mutex);
 }
 
+/**
+ * Called with state mutex held
+ **/
 static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
 				     enum iser_ib_conn_state comp,
 				     enum iser_ib_conn_state exch)
 {
 	int ret;
 
-	spin_lock_bh(&ib_conn->lock);
 	if ((ret = (ib_conn->state == comp)))
 		ib_conn->state = exch;
-	spin_unlock_bh(&ib_conn->lock);
 	return ret;
 }
 
 void iser_release_work(struct work_struct *work)
 {
 	struct iser_conn *ib_conn;
+	int rc;
 
 	ib_conn = container_of(work, struct iser_conn, release_work);
 
 	/* wait for .conn_stop callback */
-	wait_for_completion(&ib_conn->stop_completion);
+	rc = wait_for_completion_timeout(&ib_conn->stop_completion, 30 * HZ);
+	WARN_ON(rc == 0);
 
 	/* wait for the qp`s post send and post receive buffers to empty */
-	wait_event_interruptible(ib_conn->wait,
-				 ib_conn->state == ISER_CONN_DOWN);
+	rc = wait_for_completion_timeout(&ib_conn->flush_completion, 30 * HZ);
+	WARN_ON(rc == 0);
+
+	ib_conn->state = ISER_CONN_DOWN;
+
+	mutex_lock(&ib_conn->state_mutex);
+	ib_conn->state = ISER_CONN_DOWN;
+	mutex_unlock(&ib_conn->state_mutex);
 
 	iser_conn_release(ib_conn);
 }
@@ -604,23 +614,27 @@ void iser_conn_release(struct iser_conn
 {
 	struct iser_device  *device = ib_conn->device;
 
-	BUG_ON(ib_conn->state == ISER_CONN_UP);
-
 	mutex_lock(&ig.connlist_mutex);
 	list_del(&ib_conn->conn_list);
 	mutex_unlock(&ig.connlist_mutex);
+
+	mutex_lock(&ib_conn->state_mutex);
+	BUG_ON(ib_conn->state != ISER_CONN_DOWN);
+
 	iser_free_rx_descriptors(ib_conn);
 	iser_free_ib_conn_res(ib_conn);
 	ib_conn->device = NULL;
 	/* on EVENT_ADDR_ERROR there's no device yet for this conn */
 	if (device != NULL)
 		iser_device_try_release(device);
+	mutex_unlock(&ib_conn->state_mutex);
+
 	/* if cma handler context, the caller actually destroy the id */
 	if (ib_conn->cma_id != NULL) {
 		rdma_destroy_id(ib_conn->cma_id);
 		ib_conn->cma_id = NULL;
 	}
-	iscsi_destroy_endpoint(ib_conn->ep);
+	kfree(ib_conn);
 }
 
 /**
@@ -642,22 +656,31 @@ void iser_conn_terminate(struct iser_con
 			 ib_conn,err);
 }
 
+/**
+ * Called with state mutex held
+ **/
 static void iser_connect_error(struct rdma_cm_id *cma_id)
 {
 	struct iser_conn *ib_conn;
 
 	ib_conn = (struct iser_conn *)cma_id->context;
-
 	ib_conn->state = ISER_CONN_DOWN;
-	wake_up_interruptible(&ib_conn->wait);
 }
 
+/**
+ * Called with state mutex held
+ **/
 static void iser_addr_handler(struct rdma_cm_id *cma_id)
 {
 	struct iser_device *device;
 	struct iser_conn   *ib_conn;
 	int    ret;
 
+	ib_conn = (struct iser_conn *)cma_id->context;
+	if (ib_conn->state != ISER_CONN_PENDING)
+		/* bailout */
+		return;
+
 	device = iser_device_find_by_ib_device(cma_id);
 	if (!device) {
 		iser_err("device lookup/creation failed\n");
@@ -665,7 +688,6 @@ static void iser_addr_handler(struct rdm
 		return;
 	}
 
-	ib_conn = (struct iser_conn *)cma_id->context;
 	ib_conn->device = device;
 
 	/* connection T10-PI support */
@@ -689,18 +711,27 @@ static void iser_addr_handler(struct rdm
 	}
 }
 
+/**
+ * Called with state mutex held
+ **/
 static void iser_route_handler(struct rdma_cm_id *cma_id)
 {
 	struct rdma_conn_param conn_param;
 	int    ret;
 	struct iser_cm_hdr req_hdr;
+	struct iser_conn *ib_conn = (struct iser_conn *)cma_id->context;
+	struct iser_device *device = ib_conn->device;
+
+	if (ib_conn->state != ISER_CONN_PENDING)
+		/* bailout */
+		return;
 
 	ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context);
 	if (ret)
 		goto failure;
 
 	memset(&conn_param, 0, sizeof conn_param);
-	conn_param.responder_resources = 4;
+	conn_param.responder_resources = device->dev_attr.max_qp_rd_atom;
 	conn_param.initiator_depth     = 1;
 	conn_param.retry_count	       = 7;
 	conn_param.rnr_retry_count     = 6;
@@ -728,12 +759,16 @@ static void iser_connected_handler(struc
 	struct ib_qp_attr attr;
 	struct ib_qp_init_attr init_attr;
 
+	ib_conn = (struct iser_conn *)cma_id->context;
+	if (ib_conn->state != ISER_CONN_PENDING)
+		/* bailout */
+		return;
+
 	(void)ib_query_qp(cma_id->qp, &attr, ~0, &init_attr);
 	iser_info("remote qpn:%x my qpn:%x\n", attr.dest_qp_num, cma_id->qp->qp_num);
 
-	ib_conn = (struct iser_conn *)cma_id->context;
-	if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_PENDING, ISER_CONN_UP))
-		wake_up_interruptible(&ib_conn->wait);
+	ib_conn->state = ISER_CONN_UP;
+	complete(&ib_conn->up_completion);
 }
 
 static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
@@ -752,19 +787,25 @@ static void iser_disconnected_handler(st
 			iser_err("iscsi_iser connection isn't bound\n");
 	}
 
-	/* Complete the termination process if no posts are pending */
+	/* Complete the termination process if no posts are pending. This code
+	 * block also exists in iser_handle_comp_error(), but it is needed here
+	 * for cases of no flushes at all, e.g. discovery over rdma.
+	 */
 	if (ib_conn->post_recv_buf_count == 0 &&
 	    (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
-		ib_conn->state = ISER_CONN_DOWN;
-		wake_up_interruptible(&ib_conn->wait);
+		complete(&ib_conn->flush_completion);
 	}
 }
 
 static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 {
+	struct iser_conn *ib_conn;
+
+	ib_conn = (struct iser_conn *)cma_id->context;
 	iser_info("event %d status %d conn %p id %p\n",
 		  event->event, event->status, cma_id->context, cma_id);
 
+	mutex_lock(&ib_conn->state_mutex);
 	switch (event->event) {
 	case RDMA_CM_EVENT_ADDR_RESOLVED:
 		iser_addr_handler(cma_id);
@@ -785,24 +826,28 @@ static int iser_cma_handler(struct rdma_
 	case RDMA_CM_EVENT_DISCONNECTED:
 	case RDMA_CM_EVENT_DEVICE_REMOVAL:
 	case RDMA_CM_EVENT_ADDR_CHANGE:
+	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
 		iser_disconnected_handler(cma_id);
 		break;
 	default:
 		iser_err("Unexpected RDMA CM event (%d)\n", event->event);
 		break;
 	}
+	mutex_unlock(&ib_conn->state_mutex);
 	return 0;
 }
 
 void iser_conn_init(struct iser_conn *ib_conn)
 {
 	ib_conn->state = ISER_CONN_INIT;
-	init_waitqueue_head(&ib_conn->wait);
 	ib_conn->post_recv_buf_count = 0;
 	atomic_set(&ib_conn->post_send_buf_count, 0);
 	init_completion(&ib_conn->stop_completion);
+	init_completion(&ib_conn->flush_completion);
+	init_completion(&ib_conn->up_completion);
 	INIT_LIST_HEAD(&ib_conn->conn_list);
 	spin_lock_init(&ib_conn->lock);
+	mutex_init(&ib_conn->state_mutex);
 }
 
  /**
@@ -810,22 +855,21 @@ void iser_conn_init(struct iser_conn *ib
  * sleeps until the connection is established or rejected
  */
 int iser_connect(struct iser_conn   *ib_conn,
-		 struct sockaddr_in *src_addr,
-		 struct sockaddr_in *dst_addr,
+		 struct sockaddr    *src_addr,
+		 struct sockaddr    *dst_addr,
 		 int                 non_blocking)
 {
-	struct sockaddr *src, *dst;
 	int err = 0;
 
-	sprintf(ib_conn->name, "%pI4:%d",
-		&dst_addr->sin_addr.s_addr, dst_addr->sin_port);
+	mutex_lock(&ib_conn->state_mutex);
+
+	sprintf(ib_conn->name, "%pISp", dst_addr);
+
+	iser_info("connecting to: %s\n", ib_conn->name);
 
 	/* the device is known only --after-- address resolution */
 	ib_conn->device = NULL;
 
-	iser_info("connecting to: %pI4, port 0x%x\n",
-		  &dst_addr->sin_addr, dst_addr->sin_port);
-
 	ib_conn->state = ISER_CONN_PENDING;
 
 	ib_conn->cma_id = rdma_create_id(iser_cma_handler,
@@ -837,23 +881,21 @@ int iser_connect(struct iser_conn   *ib_
 		goto id_failure;
 	}
 
-	src = (struct sockaddr *)src_addr;
-	dst = (struct sockaddr *)dst_addr;
-	err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000);
+	err = rdma_resolve_addr(ib_conn->cma_id, src_addr, dst_addr, 1000);
 	if (err) {
 		iser_err("rdma_resolve_addr failed: %d\n", err);
 		goto addr_failure;
 	}
 
 	if (!non_blocking) {
-		wait_event_interruptible(ib_conn->wait,
-					 (ib_conn->state != ISER_CONN_PENDING));
+		wait_for_completion_interruptible(&ib_conn->up_completion);
 
 		if (ib_conn->state != ISER_CONN_UP) {
 			err =  -EIO;
 			goto connect_failure;
 		}
 	}
+	mutex_unlock(&ib_conn->state_mutex);
 
 	mutex_lock(&ig.connlist_mutex);
 	list_add(&ib_conn->conn_list, &ig.connlist);
@@ -865,6 +907,7 @@ id_failure:
 addr_failure:
 	ib_conn->state = ISER_CONN_DOWN;
 connect_failure:
+	mutex_unlock(&ib_conn->state_mutex);
 	iser_conn_release(ib_conn);
 	return err;
 }
@@ -1049,18 +1092,19 @@ static void iser_handle_comp_error(struc
 
 	if (ib_conn->post_recv_buf_count == 0 &&
 	    atomic_read(&ib_conn->post_send_buf_count) == 0) {
-		/* getting here when the state is UP means that the conn is *
-		 * being terminated asynchronously from the iSCSI layer's   *
-		 * perspective.                                             */
-		if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
-		    ISER_CONN_TERMINATING))
+		/**
+		 * getting here when the state is UP means that the conn is
+		 * being terminated asynchronously from the iSCSI layer's
+		 * perspective. It is safe to peek at the connection state
+		 * since iscsi_conn_failure is allowed to be called twice.
+		 **/
+		if (ib_conn->state == ISER_CONN_UP)
 			iscsi_conn_failure(ib_conn->iscsi_conn,
 					   ISCSI_ERR_CONN_FAILED);
 
 		/* no more non completed posts to the QP, complete the
 		 * termination process w.o worrying on disconnect event */
-		ib_conn->state = ISER_CONN_DOWN;
-		wake_up_interruptible(&ib_conn->wait);
+		complete(&ib_conn->flush_completion);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/isert/ib_isert.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/isert/ib_isert.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/isert/ib_isert.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/isert/ib_isert.c	2014-09-28 17:29:07.000000000 -0400
@@ -586,17 +586,12 @@ isert_connect_request(struct rdma_cm_id
 	init_completion(&isert_conn->conn_wait);
 	init_completion(&isert_conn->conn_wait_comp_err);
 	kref_init(&isert_conn->conn_kref);
-	kref_get(&isert_conn->conn_kref);
 	mutex_init(&isert_conn->conn_mutex);
 	spin_lock_init(&isert_conn->conn_lock);
 	INIT_LIST_HEAD(&isert_conn->conn_fr_pool);
 
 	cma_id->context = isert_conn;
 	isert_conn->conn_cm_id = cma_id;
-	isert_conn->responder_resources = event->param.conn.responder_resources;
-	isert_conn->initiator_depth = event->param.conn.initiator_depth;
-	pr_debug("Using responder_resources: %u initiator_depth: %u\n",
-		 isert_conn->responder_resources, isert_conn->initiator_depth);
 
 	isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
 					ISER_RX_LOGIN_SIZE, GFP_KERNEL);
@@ -643,6 +638,12 @@ isert_connect_request(struct rdma_cm_id
 		goto out_rsp_dma_map;
 	}
 
+	/* Set max inflight RDMA READ requests */
+	isert_conn->initiator_depth = min_t(u8,
+				event->param.conn.initiator_depth,
+				device->dev_attr.max_qp_init_rd_atom);
+	pr_debug("Using initiator_depth: %u\n", isert_conn->initiator_depth);
+
 	isert_conn->conn_device = device;
 	isert_conn->conn_pd = ib_alloc_pd(isert_conn->conn_device->ib_device);
 	if (IS_ERR(isert_conn->conn_pd)) {
@@ -746,7 +747,9 @@ isert_connect_release(struct isert_conn
 static void
 isert_connected_handler(struct rdma_cm_id *cma_id)
 {
-	return;
+	struct isert_conn *isert_conn = cma_id->context;
+
+	kref_get(&isert_conn->conn_kref);
 }
 
 static void
@@ -798,7 +801,6 @@ isert_disconnect_work(struct work_struct
 
 wake_up:
 	complete(&isert_conn->conn_wait);
-	isert_put_conn(isert_conn);
 }
 
 static void
@@ -3067,7 +3069,6 @@ isert_rdma_accept(struct isert_conn *ise
 	int ret;
 
 	memset(&cp, 0, sizeof(struct rdma_conn_param));
-	cp.responder_resources = isert_conn->responder_resources;
 	cp.initiator_depth = isert_conn->initiator_depth;
 	cp.retry_count = 7;
 	cp.rnr_retry_count = 7;
@@ -3215,7 +3216,7 @@ static void isert_wait_conn(struct iscsi
 	pr_debug("isert_wait_conn: Starting \n");
 
 	mutex_lock(&isert_conn->conn_mutex);
-	if (isert_conn->conn_cm_id) {
+	if (isert_conn->conn_cm_id && !isert_conn->disconnect) {
 		pr_debug("Calling rdma_disconnect from isert_wait_conn\n");
 		rdma_disconnect(isert_conn->conn_cm_id);
 	}
@@ -3234,6 +3235,7 @@ static void isert_wait_conn(struct iscsi
 	wait_for_completion(&isert_conn->conn_wait_comp_err);
 
 	wait_for_completion(&isert_conn->conn_wait);
+	isert_put_conn(isert_conn);
 }
 
 static void isert_free_conn(struct iscsi_conn *conn)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,6 +130,7 @@ static void srp_send_completion(struct i
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
 
 static struct scsi_transport_template *ib_srp_transport_template;
+static struct workqueue_struct *srp_remove_wq;
 
 static struct ib_client srp_client = {
 	.name   = "srp",
@@ -731,7 +732,7 @@ static bool srp_queue_remove_work(struct
 	spin_unlock_irq(&target->lock);
 
 	if (changed)
-		queue_work(system_long_wq, &target->remove_work);
+		queue_work(srp_remove_wq, &target->remove_work);
 
 	return changed;
 }
@@ -1643,10 +1644,14 @@ static void srp_process_rsp(struct srp_t
 				     SCSI_SENSE_BUFFERSIZE));
 		}
 
-		if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
-			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
-		else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
+		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
+		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DIOVER))
+			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_in_res_cnt));
+		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
+			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
+		else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
+			scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
 
 		srp_free_req(target, req, scmnd,
 			     be32_to_cpu(rsp->req_lim_delta));
@@ -3261,9 +3266,10 @@ static void srp_remove_one(struct ib_dev
 		spin_unlock(&host->target_lock);
 
 		/*
-		 * Wait for target port removal tasks.
+		 * Wait for tl_err and target port removal tasks.
 		 */
 		flush_workqueue(system_long_wq);
+		flush_workqueue(srp_remove_wq);
 
 		kfree(host);
 	}
@@ -3313,16 +3319,22 @@ static int __init srp_init_module(void)
 		indirect_sg_entries = cmd_sg_entries;
 	}
 
+	srp_remove_wq = create_workqueue("srp_remove");
+	if (!srp_remove_wq) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = -ENOMEM;
 	ib_srp_transport_template =
 		srp_attach_transport(&ib_srp_transport_functions);
 	if (!ib_srp_transport_template)
-		return -ENOMEM;
+		goto destroy_wq;
 
 	ret = class_register(&srp_class);
 	if (ret) {
 		pr_err("couldn't register class infiniband_srp\n");
-		srp_release_transport(ib_srp_transport_template);
-		return ret;
+		goto release_tr;
 	}
 
 	ib_sa_register_client(&srp_sa_client);
@@ -3330,13 +3342,22 @@ static int __init srp_init_module(void)
 	ret = ib_register_client(&srp_client);
 	if (ret) {
 		pr_err("couldn't register IB client\n");
-		srp_release_transport(ib_srp_transport_template);
-		ib_sa_unregister_client(&srp_sa_client);
-		class_unregister(&srp_class);
-		return ret;
+		goto unreg_sa;
 	}
 
-	return 0;
+out:
+	return ret;
+
+unreg_sa:
+	ib_sa_unregister_client(&srp_sa_client);
+	class_unregister(&srp_class);
+
+release_tr:
+	srp_release_transport(ib_srp_transport_template);
+
+destroy_wq:
+	destroy_workqueue(srp_remove_wq);
+	goto out;
 }
 
 static void __exit srp_cleanup_module(void)
@@ -3345,6 +3366,7 @@ static void __exit srp_cleanup_module(vo
 	ib_sa_unregister_client(&srp_sa_client);
 	class_unregister(&srp_class);
 	srp_release_transport(ib_srp_transport_template);
+	destroy_workqueue(srp_remove_wq);
 }
 
 module_init(srp_init_module);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c
--- linux-libre-3.16-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2014-09-28 17:29:07.000000000 -0400
@@ -198,6 +198,7 @@ static void srpt_event_handler(struct ib
 	case IB_EVENT_PKEY_CHANGE:
 	case IB_EVENT_SM_CHANGE:
 	case IB_EVENT_CLIENT_REREGISTER:
+	case IB_EVENT_GID_CHANGE:
 		/* Refresh port data asynchronously. */
 		if (event->element.port_num <= sdev->device->phys_port_cnt) {
 			sport = &sdev->port[event->element.port_num - 1];
@@ -563,7 +564,7 @@ static int srpt_refresh_port(struct srpt
 							 &reg_req, 0,
 							 srpt_mad_send_handler,
 							 srpt_mad_recv_handler,
-							 sport);
+							 sport, 0);
 		if (IS_ERR(sport->mad_agent)) {
 			ret = PTR_ERR(sport->mad_agent);
 			sport->mad_agent = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/evdev.c linux-libre-3.17-rc7-gnu/drivers/input/evdev.c
--- linux-libre-3.16-gnu/drivers/input/evdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/evdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,9 +108,8 @@ static void evdev_queue_syn_dropped(stru
 	struct input_event ev;
 	ktime_t time;
 
-	time = ktime_get();
-	if (client->clkid != CLOCK_MONOTONIC)
-		time = ktime_sub(time, ktime_get_monotonic_offset());
+	time = (client->clkid == CLOCK_MONOTONIC) ?
+		ktime_get() : ktime_get_real();
 
 	ev.time = ktime_to_timeval(time);
 	ev.type = EV_SYN;
@@ -202,7 +201,7 @@ static void evdev_events(struct input_ha
 	ktime_t time_mono, time_real;
 
 	time_mono = ktime_get();
-	time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
+	time_real = ktime_mono_to_real(time_mono);
 
 	rcu_read_lock();
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/input-mt.c linux-libre-3.17-rc7-gnu/drivers/input/input-mt.c
--- linux-libre-3.16-gnu/drivers/input/input-mt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/input-mt.c	2014-09-28 17:29:07.000000000 -0400
@@ -236,6 +236,35 @@ void input_mt_report_pointer_emulation(s
 }
 EXPORT_SYMBOL(input_mt_report_pointer_emulation);
 
+static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
+{
+	int i;
+
+	for (i = 0; i < mt->num_slots; i++) {
+		if (!input_mt_is_used(mt, &mt->slots[i])) {
+			input_mt_slot(dev, i);
+			input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+		}
+	}
+}
+
+/**
+ * input_mt_drop_unused() - Inactivate slots not seen in this frame
+ * @dev: input device with allocated MT slots
+ *
+ * Lift all slots not seen since the last call to this function.
+ */
+void input_mt_drop_unused(struct input_dev *dev)
+{
+	struct input_mt *mt = dev->mt;
+
+	if (mt) {
+		__input_mt_drop_unused(dev, mt);
+		mt->frame++;
+	}
+}
+EXPORT_SYMBOL(input_mt_drop_unused);
+
 /**
  * input_mt_sync_frame() - synchronize mt frame
  * @dev: input device with allocated MT slots
@@ -247,20 +276,13 @@ EXPORT_SYMBOL(input_mt_report_pointer_em
 void input_mt_sync_frame(struct input_dev *dev)
 {
 	struct input_mt *mt = dev->mt;
-	struct input_mt_slot *s;
 	bool use_count = false;
 
 	if (!mt)
 		return;
 
-	if (mt->flags & INPUT_MT_DROP_UNUSED) {
-		for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
-			if (input_mt_is_used(mt, s))
-				continue;
-			input_mt_slot(dev, s - mt->slots);
-			input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
-		}
-	}
+	if (mt->flags & INPUT_MT_DROP_UNUSED)
+		__input_mt_drop_unused(dev, mt);
 
 	if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
 		use_count = true;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/joystick/analog.c linux-libre-3.17-rc7-gnu/drivers/input/joystick/analog.c
--- linux-libre-3.16-gnu/drivers/input/joystick/analog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/joystick/analog.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,7 +158,7 @@ static unsigned int get_time_pit(void)
 #define GET_TIME(x)	rdtscl(x)
 #define DELTA(x,y)	((y)-(x))
 #define TIME_NAME	"TSC"
-#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE)
+#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE)
 #define GET_TIME(x)	do { x = get_cycles(); } while (0)
 #define DELTA(x,y)	((y)-(x))
 #define TIME_NAME	"get_cycles"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/joystick/xpad.c linux-libre-3.17-rc7-gnu/drivers/input/joystick/xpad.c
--- linux-libre-3.16-gnu/drivers/input/joystick/xpad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/joystick/xpad.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,8 @@
 #define XTYPE_XBOX        0
 #define XTYPE_XBOX360     1
 #define XTYPE_XBOX360W    2
-#define XTYPE_UNKNOWN     3
+#define XTYPE_XBOXONE     3
+#define XTYPE_UNKNOWN     4
 
 static bool dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -121,6 +122,7 @@ static const struct xpad_device {
 	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
 	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
 	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+	{ 0x045e, 0x02d1, "Microsoft X-Box One 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 },
@@ -231,10 +233,12 @@ static const signed short xpad_abs_trigg
 	-1
 };
 
-/* Xbox 360 has a vendor-specific class, so we cannot match it with only
+/*
+ * Xbox 360 has a vendor-specific class, so we cannot match it with only
  * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
  * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
- * wireless controllers have protocol 129. */
+ * wireless controllers have protocol 129.
+ */
 #define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
 	.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
 	.idVendor = (vend), \
@@ -245,9 +249,20 @@ static const signed short xpad_abs_trigg
 	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
 	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
 
+/* The Xbox One controller uses subclass 71 and protocol 208. */
+#define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
+	.idVendor = (vend), \
+	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+	.bInterfaceSubClass = 71, \
+	.bInterfaceProtocol = (pr)
+#define XPAD_XBOXONE_VENDOR(vend) \
+	{ XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }
+
 static struct usb_device_id xpad_table[] = {
 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
 	XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */
+	XPAD_XBOXONE_VENDOR(0x045e),		/* Microsoft X-Box One controllers */
 	XPAD_XBOX360_VENDOR(0x046d),		/* Logitech X-Box 360 style controllers */
 	XPAD_XBOX360_VENDOR(0x0738),		/* Mad Catz X-Box 360 controllers */
 	{ USB_DEVICE(0x0738, 0x4540) },		/* Mad Catz Beat Pad */
@@ -278,12 +293,10 @@ struct usb_xpad {
 	struct urb *bulk_out;
 	unsigned char *bdata;
 
-#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
 	struct urb *irq_out;		/* urb for interrupt out report */
 	unsigned char *odata;		/* output data */
 	dma_addr_t odata_dma;
 	struct mutex odata_mutex;
-#endif
 
 #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
 	struct xpad_led *led;
@@ -470,6 +483,105 @@ static void xpad360w_process_packet(stru
 	xpad360_process_packet(xpad, cmd, &data[4]);
 }
 
+/*
+ *	xpadone_process_buttons
+ *
+ *	Process a button update packet from an Xbox one controller.
+ */
+static void xpadone_process_buttons(struct usb_xpad *xpad,
+				struct input_dev *dev,
+				unsigned char *data)
+{
+	/* menu/view buttons */
+	input_report_key(dev, BTN_START,  data[4] & 0x04);
+	input_report_key(dev, BTN_SELECT, data[4] & 0x08);
+
+	/* buttons A,B,X,Y */
+	input_report_key(dev, BTN_A,	data[4] & 0x10);
+	input_report_key(dev, BTN_B,	data[4] & 0x20);
+	input_report_key(dev, BTN_X,	data[4] & 0x40);
+	input_report_key(dev, BTN_Y,	data[4] & 0x80);
+
+	/* digital pad */
+	if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
+		/* dpad as buttons (left, right, up, down) */
+		input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04);
+		input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08);
+		input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01);
+		input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02);
+	} else {
+		input_report_abs(dev, ABS_HAT0X,
+				 !!(data[5] & 0x08) - !!(data[5] & 0x04));
+		input_report_abs(dev, ABS_HAT0Y,
+				 !!(data[5] & 0x02) - !!(data[5] & 0x01));
+	}
+
+	/* TL/TR */
+	input_report_key(dev, BTN_TL,	data[5] & 0x10);
+	input_report_key(dev, BTN_TR,	data[5] & 0x20);
+
+	/* stick press left/right */
+	input_report_key(dev, BTN_THUMBL, data[5] & 0x40);
+	input_report_key(dev, BTN_THUMBR, data[5] & 0x80);
+
+	if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
+		/* left stick */
+		input_report_abs(dev, ABS_X,
+				 (__s16) le16_to_cpup((__le16 *)(data + 10)));
+		input_report_abs(dev, ABS_Y,
+				 ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+
+		/* right stick */
+		input_report_abs(dev, ABS_RX,
+				 (__s16) le16_to_cpup((__le16 *)(data + 14)));
+		input_report_abs(dev, ABS_RY,
+				 ~(__s16) le16_to_cpup((__le16 *)(data + 16)));
+	}
+
+	/* triggers left/right */
+	if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
+		input_report_key(dev, BTN_TL2,
+				 (__u16) le16_to_cpup((__le16 *)(data + 6)));
+		input_report_key(dev, BTN_TR2,
+				 (__u16) le16_to_cpup((__le16 *)(data + 8)));
+	} else {
+		input_report_abs(dev, ABS_Z,
+				 (__u16) le16_to_cpup((__le16 *)(data + 6)));
+		input_report_abs(dev, ABS_RZ,
+				 (__u16) le16_to_cpup((__le16 *)(data + 8)));
+	}
+
+	input_sync(dev);
+}
+
+/*
+ *	xpadone_process_packet
+ *
+ *	Completes a request by converting the data into events for the
+ *	input subsystem. This version is for the Xbox One controller.
+ *
+ *	The report format was gleaned from
+ *	https://github.com/kylelemons/xbox/blob/master/xbox.go
+ */
+
+static void xpadone_process_packet(struct usb_xpad *xpad,
+				u16 cmd, unsigned char *data)
+{
+	struct input_dev *dev = xpad->dev;
+
+	switch (data[0]) {
+	case 0x20:
+		xpadone_process_buttons(xpad, dev, data);
+		break;
+
+	case 0x07:
+		/* the xbox button has its own special report */
+		input_report_key(dev, BTN_MODE, data[4] & 0x01);
+		input_sync(dev);
+		break;
+	}
+}
+
 static void xpad_irq_in(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
@@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb)
 	case XTYPE_XBOX360W:
 		xpad360w_process_packet(xpad, 0, xpad->idata);
 		break;
+	case XTYPE_XBOXONE:
+		xpadone_process_packet(xpad, 0, xpad->idata);
+		break;
 	default:
 		xpad_process_packet(xpad, 0, xpad->idata);
 	}
@@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *ur
 	}
 }
 
-#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
 static void xpad_irq_out(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
@@ -573,6 +687,7 @@ exit:
 static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 {
 	struct usb_endpoint_descriptor *ep_irq_out;
+	int ep_irq_out_idx;
 	int error;
 
 	if (xpad->xtype == XTYPE_UNKNOWN)
@@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_i
 		goto fail2;
 	}
 
-	ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+	/* Xbox One controller has in/out endpoints swapped. */
+	ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1;
+	ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc;
+
 	usb_fill_int_urb(xpad->irq_out, xpad->udev,
 			 usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
 			 xpad->odata, XPAD_PKT_LEN,
@@ -621,11 +739,6 @@ static void xpad_deinit_output(struct us
 				xpad->odata, xpad->odata_dma);
 	}
 }
-#else
-static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
-static void xpad_deinit_output(struct usb_xpad *xpad) {}
-static void xpad_stop_output(struct usb_xpad *xpad) {}
-#endif
 
 #ifdef CONFIG_JOYSTICK_XPAD_FF
 static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
@@ -692,7 +805,7 @@ static int xpad_play_effect(struct input
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-	if (xpad->xtype == XTYPE_UNKNOWN)
+	if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE)
 		return 0;
 
 	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
@@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *d
 	if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
 		return -EIO;
 
+	if (xpad->xtype == XTYPE_XBOXONE) {
+		/* Xbox one controller needs to be initialized. */
+		xpad->odata[0] = 0x05;
+		xpad->odata[1] = 0x20;
+		xpad->irq_out->transfer_buffer_length = 2;
+		return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+	}
+
 	return 0;
 }
 
@@ -816,6 +937,7 @@ static void xpad_close(struct input_dev
 
 static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
 {
+	struct usb_xpad *xpad = input_get_drvdata(input_dev);
 	set_bit(abs, input_dev->absbit);
 
 	switch (abs) {
@@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input
 		break;
 	case ABS_Z:
 	case ABS_RZ:	/* the triggers (if mapped to axes) */
-		input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
+		if (xpad->xtype == XTYPE_XBOXONE)
+			input_set_abs_params(input_dev, abs, 0, 1023, 0, 0);
+		else
+			input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
 		break;
 	case ABS_HAT0X:
 	case ABS_HAT0Y:	/* the d-pad (only if dpad is mapped to axes */
@@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interfa
 	struct usb_xpad *xpad;
 	struct input_dev *input_dev;
 	struct usb_endpoint_descriptor *ep_irq_in;
+	int ep_irq_in_idx;
 	int i, error;
 
 	for (i = 0; xpad_device[i].idVendor; i++) {
@@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interfa
 			break;
 	}
 
+	if (xpad_device[i].xtype == XTYPE_XBOXONE &&
+	    intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+		/*
+		 * The Xbox One controller lists three interfaces all with the
+		 * same interface class, subclass and protocol. Differentiate by
+		 * interface number.
+		 */
+		return -ENODEV;
+	}
+
 	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!xpad || !input_dev) {
@@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interfa
 		__set_bit(xpad_common_btn[i], input_dev->keybit);
 
 	/* set up model-specific ones */
-	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
+	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
+	    xpad->xtype == XTYPE_XBOXONE) {
 		for (i = 0; xpad360_btn[i] >= 0; i++)
 			__set_bit(xpad360_btn[i], input_dev->keybit);
 	} else {
@@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interfa
 			__set_bit(xpad_btn_pad[i], input_dev->keybit);
 	} else {
 		for (i = 0; xpad_abs_pad[i] >= 0; i++)
-		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+			xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
 	}
 
 	if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
@@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interfa
 	if (error)
 		goto fail5;
 
-	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
+	/* Xbox One controller has in/out endpoints swapped. */
+	ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
+	ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;
+
 	usb_fill_int_urb(xpad->irq_in, udev,
 			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
 			 xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/atkbd.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/atkbd.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/atkbd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/atkbd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1791,14 +1791,6 @@ static const struct dmi_system_id atkbd_
 	{
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"),
-		},
-		.callback = atkbd_deactivate_fixup,
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"),
 		},
 		.callback = atkbd_deactivate_fixup,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/cap1106.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/cap1106.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/cap1106.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/cap1106.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,341 @@
+/*
+ * Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
+ *
+ * http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
+ *
+ * (c) 2014 Daniel Mack <linux@zonque.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/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+#define CAP1106_REG_MAIN_CONTROL	0x00
+#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT	(6)
+#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK	(0xc0)
+#define CAP1106_REG_MAIN_CONTROL_DLSEEP		BIT(4)
+#define CAP1106_REG_GENERAL_STATUS	0x02
+#define CAP1106_REG_SENSOR_INPUT	0x03
+#define CAP1106_REG_NOISE_FLAG_STATUS	0x0a
+#define CAP1106_REG_SENOR_DELTA(X)	(0x10 + (X))
+#define CAP1106_REG_SENSITIVITY_CONTROL	0x1f
+#define CAP1106_REG_CONFIG		0x20
+#define CAP1106_REG_SENSOR_ENABLE	0x21
+#define CAP1106_REG_SENSOR_CONFIG	0x22
+#define CAP1106_REG_SENSOR_CONFIG2	0x23
+#define CAP1106_REG_SAMPLING_CONFIG	0x24
+#define CAP1106_REG_CALIBRATION		0x26
+#define CAP1106_REG_INT_ENABLE		0x27
+#define CAP1106_REG_REPEAT_RATE		0x28
+#define CAP1106_REG_MT_CONFIG		0x2a
+#define CAP1106_REG_MT_PATTERN_CONFIG	0x2b
+#define CAP1106_REG_MT_PATTERN		0x2d
+#define CAP1106_REG_RECALIB_CONFIG	0x2f
+#define CAP1106_REG_SENSOR_THRESH(X)	(0x30 + (X))
+#define CAP1106_REG_SENSOR_NOISE_THRESH	0x38
+#define CAP1106_REG_STANDBY_CHANNEL	0x40
+#define CAP1106_REG_STANDBY_CONFIG	0x41
+#define CAP1106_REG_STANDBY_SENSITIVITY	0x42
+#define CAP1106_REG_STANDBY_THRESH	0x43
+#define CAP1106_REG_CONFIG2		0x44
+#define CAP1106_REG_SENSOR_BASE_CNT(X)	(0x50 + (X))
+#define CAP1106_REG_SENSOR_CALIB	(0xb1 + (X))
+#define CAP1106_REG_SENSOR_CALIB_LSB1	0xb9
+#define CAP1106_REG_SENSOR_CALIB_LSB2	0xba
+#define CAP1106_REG_PRODUCT_ID		0xfd
+#define CAP1106_REG_MANUFACTURER_ID	0xfe
+#define CAP1106_REG_REVISION		0xff
+
+#define CAP1106_NUM_CHN 6
+#define CAP1106_PRODUCT_ID	0x55
+#define CAP1106_MANUFACTURER_ID	0x5d
+
+struct cap1106_priv {
+	struct regmap *regmap;
+	struct input_dev *idev;
+
+	/* config */
+	unsigned short keycodes[CAP1106_NUM_CHN];
+};
+
+static const struct reg_default cap1106_reg_defaults[] = {
+	{ CAP1106_REG_MAIN_CONTROL,		0x00 },
+	{ CAP1106_REG_GENERAL_STATUS,		0x00 },
+	{ CAP1106_REG_SENSOR_INPUT,		0x00 },
+	{ CAP1106_REG_NOISE_FLAG_STATUS,	0x00 },
+	{ CAP1106_REG_SENSITIVITY_CONTROL,	0x2f },
+	{ CAP1106_REG_CONFIG,			0x20 },
+	{ CAP1106_REG_SENSOR_ENABLE,		0x3f },
+	{ CAP1106_REG_SENSOR_CONFIG,		0xa4 },
+	{ CAP1106_REG_SENSOR_CONFIG2,		0x07 },
+	{ CAP1106_REG_SAMPLING_CONFIG,		0x39 },
+	{ CAP1106_REG_CALIBRATION,		0x00 },
+	{ CAP1106_REG_INT_ENABLE,		0x3f },
+	{ CAP1106_REG_REPEAT_RATE,		0x3f },
+	{ CAP1106_REG_MT_CONFIG,		0x80 },
+	{ CAP1106_REG_MT_PATTERN_CONFIG,	0x00 },
+	{ CAP1106_REG_MT_PATTERN,		0x3f },
+	{ CAP1106_REG_RECALIB_CONFIG,		0x8a },
+	{ CAP1106_REG_SENSOR_THRESH(0),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(1),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(2),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(3),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(4),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(5),		0x40 },
+	{ CAP1106_REG_SENSOR_NOISE_THRESH,	0x01 },
+	{ CAP1106_REG_STANDBY_CHANNEL,		0x00 },
+	{ CAP1106_REG_STANDBY_CONFIG,		0x39 },
+	{ CAP1106_REG_STANDBY_SENSITIVITY,	0x02 },
+	{ CAP1106_REG_STANDBY_THRESH,		0x40 },
+	{ CAP1106_REG_CONFIG2,			0x40 },
+	{ CAP1106_REG_SENSOR_CALIB_LSB1,	0x00 },
+	{ CAP1106_REG_SENSOR_CALIB_LSB2,	0x00 },
+};
+
+static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CAP1106_REG_MAIN_CONTROL:
+	case CAP1106_REG_SENSOR_INPUT:
+	case CAP1106_REG_SENOR_DELTA(0):
+	case CAP1106_REG_SENOR_DELTA(1):
+	case CAP1106_REG_SENOR_DELTA(2):
+	case CAP1106_REG_SENOR_DELTA(3):
+	case CAP1106_REG_SENOR_DELTA(4):
+	case CAP1106_REG_SENOR_DELTA(5):
+	case CAP1106_REG_PRODUCT_ID:
+	case CAP1106_REG_MANUFACTURER_ID:
+	case CAP1106_REG_REVISION:
+		return true;
+	}
+
+	return false;
+}
+
+static const struct regmap_config cap1106_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CAP1106_REG_REVISION,
+	.reg_defaults = cap1106_reg_defaults,
+
+	.num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+	.volatile_reg = cap1106_volatile_reg,
+};
+
+static irqreturn_t cap1106_thread_func(int irq_num, void *data)
+{
+	struct cap1106_priv *priv = data;
+	unsigned int status;
+	int ret, i;
+
+	/*
+	 * Deassert interrupt. This needs to be done before reading the status
+	 * registers, which will not carry valid values otherwise.
+	 */
+	ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
+	if (ret < 0)
+		goto out;
+
+	for (i = 0; i < CAP1106_NUM_CHN; i++)
+		input_report_key(priv->idev, priv->keycodes[i],
+				 status & (1 << i));
+
+	input_sync(priv->idev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep)
+{
+	return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+				  CAP1106_REG_MAIN_CONTROL_DLSEEP,
+				  sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0);
+}
+
+static int cap1106_input_open(struct input_dev *idev)
+{
+	struct cap1106_priv *priv = input_get_drvdata(idev);
+
+	return cap1106_set_sleep(priv, false);
+}
+
+static void cap1106_input_close(struct input_dev *idev)
+{
+	struct cap1106_priv *priv = input_get_drvdata(idev);
+
+	cap1106_set_sleep(priv, true);
+}
+
+static int cap1106_i2c_probe(struct i2c_client *i2c_client,
+			     const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cap1106_priv *priv;
+	struct device_node *node;
+	int i, error, irq, gain = 0;
+	unsigned int val, rev;
+	u32 gain32, keycodes[CAP1106_NUM_CHN];
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	error = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
+	if (error)
+		return error;
+
+	if (val != CAP1106_PRODUCT_ID) {
+		dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
+			val, CAP1106_PRODUCT_ID);
+		return -ENODEV;
+	}
+
+	error = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
+	if (error)
+		return error;
+
+	if (val != CAP1106_MANUFACTURER_ID) {
+		dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
+			val, CAP1106_MANUFACTURER_ID);
+		return -ENODEV;
+	}
+
+	error = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
+	if (error < 0)
+		return error;
+
+	dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
+	i2c_set_clientdata(i2c_client, priv);
+	node = dev->of_node;
+
+	if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
+		if (is_power_of_2(gain32) && gain32 <= 8)
+			gain = ilog2(gain32);
+		else
+			dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
+	}
+
+	BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes));
+
+	/* Provide some useful defaults */
+	for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+		keycodes[i] = KEY_A + i;
+
+	of_property_read_u32_array(node, "linux,keycodes",
+				   keycodes, ARRAY_SIZE(keycodes));
+
+	for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+		priv->keycodes[i] = keycodes[i];
+
+	error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+				   CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
+				   gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
+	if (error)
+		return error;
+
+	/* Disable autorepeat. The Linux input system has its own handling. */
+	error = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
+	if (error)
+		return error;
+
+	priv->idev = devm_input_allocate_device(dev);
+	if (!priv->idev)
+		return -ENOMEM;
+
+	priv->idev->name = "CAP1106 capacitive touch sensor";
+	priv->idev->id.bustype = BUS_I2C;
+	priv->idev->evbit[0] = BIT_MASK(EV_KEY);
+
+	if (of_property_read_bool(node, "autorepeat"))
+		__set_bit(EV_REP, priv->idev->evbit);
+
+	for (i = 0; i < CAP1106_NUM_CHN; i++)
+		__set_bit(priv->keycodes[i], priv->idev->keybit);
+
+	__clear_bit(KEY_RESERVED, priv->idev->keybit);
+
+	priv->idev->keycode = priv->keycodes;
+	priv->idev->keycodesize = sizeof(priv->keycodes[0]);
+	priv->idev->keycodemax = ARRAY_SIZE(priv->keycodes);
+
+	priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
+	priv->idev->id.product = CAP1106_PRODUCT_ID;
+	priv->idev->id.version = rev;
+
+	priv->idev->open = cap1106_input_open;
+	priv->idev->close = cap1106_input_close;
+
+	input_set_drvdata(priv->idev, priv);
+
+	/*
+	 * Put the device in deep sleep mode for now.
+	 * ->open() will bring it back once the it is actually needed.
+	 */
+	cap1106_set_sleep(priv, true);
+
+	error = input_register_device(priv->idev);
+	if (error)
+		return error;
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (!irq) {
+		dev_err(dev, "Unable to parse or map IRQ\n");
+		return -ENXIO;
+	}
+
+	error = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
+					  IRQF_ONESHOT, dev_name(dev), priv);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static const struct of_device_id cap1106_dt_ids[] = {
+	{ .compatible = "microchip,cap1106", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
+
+static const struct i2c_device_id cap1106_i2c_ids[] = {
+	{ "cap1106", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
+
+static struct i2c_driver cap1106_i2c_driver = {
+	.driver = {
+		.name	= "cap1106",
+		.owner	= THIS_MODULE,
+		.of_match_table = cap1106_dt_ids,
+	},
+	.id_table	= cap1106_i2c_ids,
+	.probe		= cap1106_i2c_probe,
+};
+
+module_i2c_driver(cap1106_i2c_driver);
+
+MODULE_ALIAS("platform:cap1106");
+MODULE_DESCRIPTION("Microchip CAP1106 driver");
+MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/cros_ec_keyb.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/cros_ec_keyb.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/cros_ec_keyb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/cros_ec_keyb.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,8 +24,8 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
- * @event_notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
 	unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
 	struct device *dev;
 	struct input_dev *idev;
 	struct cros_ec_device *ec;
-	struct notifier_block notifier;
 };
 
 
@@ -173,41 +171,55 @@ static void cros_ec_keyb_process(struct
 	input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
 {
-	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_command msg = {
+		.version = 0,
+		.command = EC_CMD_MKBP_STATE,
+		.outdata = NULL,
+		.outsize = 0,
+		.indata = kb_state,
+		.insize = ckdev->cols,
+	};
 
-	return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
-						&ckdev->notifier);
+	return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
 {
-	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_keyb *ckdev = data;
+	struct cros_ec_device *ec = ckdev->ec;
+	int ret;
+	uint8_t kb_state[ckdev->cols];
 
-	blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
-					   &ckdev->notifier);
+	if (device_may_wakeup(ec->dev))
+		pm_wakeup_event(ec->dev, 0);
+
+	ret = cros_ec_keyb_get_state(ckdev, kb_state);
+	if (ret >= 0)
+		cros_ec_keyb_process(ckdev, kb_state, ret);
+	else
+		dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+
+	return IRQ_HANDLED;
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-	return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
-					  kb_state, ckdev->cols);
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_device *ec = ckdev->ec;
+
+	return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
+					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					"cros_ec_keyb", ckdev);
 }
 
-static int cros_ec_keyb_work(struct notifier_block *nb,
-		     unsigned long state, void *_notify)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
-	int ret;
-	struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
-						    notifier);
-	uint8_t kb_state[ckdev->cols];
-
-	ret = cros_ec_keyb_get_state(ckdev, kb_state);
-	if (ret >= 0)
-		cros_ec_keyb_process(ckdev, kb_state, ret);
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_device *ec = ckdev->ec;
 
-	return NOTIFY_DONE;
+	free_irq(ec->irq, ckdev);
 }
 
 static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -238,8 +250,12 @@ static int cros_ec_keyb_probe(struct pla
 	if (!idev)
 		return -ENOMEM;
 
+	if (!ec->irq) {
+		dev_err(dev, "no EC IRQ specified\n");
+		return -EINVAL;
+	}
+
 	ckdev->ec = ec;
-	ckdev->notifier.notifier_call = cros_ec_keyb_work;
 	ckdev->dev = dev;
 	dev_set_drvdata(&pdev->dev, ckdev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/imx_keypad.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/imx_keypad.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/imx_keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/imx_keypad.c	2014-09-28 17:29:07.000000000 -0400
@@ -531,8 +531,7 @@ static int imx_keypad_probe(struct platf
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int imx_kbd_suspend(struct device *dev)
+static int __maybe_unused imx_kbd_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -552,7 +551,7 @@ static int imx_kbd_suspend(struct device
 	return 0;
 }
 
-static int imx_kbd_resume(struct device *dev)
+static int __maybe_unused imx_kbd_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -575,7 +574,6 @@ err_clk:
 
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/Kconfig linux-libre-3.17-rc7-gnu/drivers/input/keyboard/Kconfig
--- linux-libre-3.16-gnu/drivers/input/keyboard/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC
 	  To compile this driver as a module, choose M here: the
 	  module will be called cros_ec_keyb.
 
+config KEYBOARD_CAP1106
+	tristate "Microchip CAP1106 touch sensor"
+	depends on OF && I2C
+	select REGMAP_I2C
+	help
+	  Say Y here to enable the CAP1106 touch sensor driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cap1106.
+
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/lm8323.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/lm8323.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/lm8323.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/lm8323.c	2014-09-28 17:29:07.000000000 -0400
@@ -558,6 +558,12 @@ static ssize_t lm8323_pwm_store_time(str
 }
 static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time);
 
+static struct attribute *lm8323_pwm_attrs[] = {
+	&dev_attr_time.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(lm8323_pwm);
+
 static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
 		    const char *name)
 {
@@ -580,16 +586,11 @@ static int init_pwm(struct lm8323_chip *
 	if (name) {
 		pwm->cdev.name = name;
 		pwm->cdev.brightness_set = lm8323_pwm_set_brightness;
+		pwm->cdev.groups = lm8323_pwm_groups;
 		if (led_classdev_register(dev, &pwm->cdev) < 0) {
 			dev_err(dev, "couldn't register PWM %d\n", id);
 			return -1;
 		}
-		if (device_create_file(pwm->cdev.dev,
-					&dev_attr_time) < 0) {
-			dev_err(dev, "couldn't register time attribute\n");
-			led_classdev_unregister(&pwm->cdev);
-			return -1;
-		}
 		pwm->enabled = true;
 	}
 
@@ -753,11 +754,8 @@ fail3:
 	device_remove_file(&client->dev, &dev_attr_disable_kp);
 fail2:
 	while (--pwm >= 0)
-		if (lm->pwm[pwm].enabled) {
-			device_remove_file(lm->pwm[pwm].cdev.dev,
-					   &dev_attr_time);
+		if (lm->pwm[pwm].enabled)
 			led_classdev_unregister(&lm->pwm[pwm].cdev);
-		}
 fail1:
 	input_free_device(idev);
 	kfree(lm);
@@ -777,10 +775,8 @@ static int lm8323_remove(struct i2c_clie
 	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
 
 	for (i = 0; i < 3; i++)
-		if (lm->pwm[i].enabled) {
-			device_remove_file(lm->pwm[i].cdev.dev, &dev_attr_time);
+		if (lm->pwm[i].enabled)
 			led_classdev_unregister(&lm->pwm[i].cdev);
-		}
 
 	kfree(lm);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/Makefile linux-libre-3.17-rc7-gnu/drivers/input/keyboard/Makefile
--- linux-libre-3.16-gnu/drivers/input/keyboard/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.
 obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
 obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
 obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CAP1106)		+= cap1106.o
 obj-$(CONFIG_KEYBOARD_CLPS711X)		+= clps711x-keypad.o
 obj-$(CONFIG_KEYBOARD_CROS_EC)		+= cros_ec_keyb.o
 obj-$(CONFIG_KEYBOARD_DAVINCI)		+= davinci_keyscan.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/matrix_keypad.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/matrix_keypad.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/matrix_keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/matrix_keypad.c	2014-09-28 17:29:07.000000000 -0400
@@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struc
 	}
 
 	if (pdata->clustered_irq > 0) {
-		err = request_irq(pdata->clustered_irq,
+		err = request_any_context_irq(pdata->clustered_irq,
 				matrix_keypad_interrupt,
 				pdata->clustered_irq_flags,
 				"matrix-keypad", keypad);
-		if (err) {
+		if (err < 0) {
 			dev_err(&pdev->dev,
 				"Unable to acquire clustered interrupt\n");
 			goto err_free_rows;
 		}
 	} else {
 		for (i = 0; i < pdata->num_row_gpios; i++) {
-			err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
+			err = request_any_context_irq(
+					gpio_to_irq(pdata->row_gpios[i]),
 					matrix_keypad_interrupt,
 					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING,
 					"matrix-keypad", keypad);
-			if (err) {
+			if (err < 0) {
 				dev_err(&pdev->dev,
 					"Unable to acquire interrupt for GPIO line %i\n",
 					pdata->row_gpios[i]);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/keyboard/max7359_keypad.c linux-libre-3.17-rc7-gnu/drivers/input/keyboard/max7359_keypad.c
--- linux-libre-3.16-gnu/drivers/input/keyboard/max7359_keypad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/keyboard/max7359_keypad.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,12 +203,17 @@ static int max7359_probe(struct i2c_clie
 
 	dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret);
 
-	keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!keypad || !input_dev) {
+	keypad = devm_kzalloc(&client->dev, sizeof(struct max7359_keypad),
+			      GFP_KERNEL);
+	if (!keypad) {
 		dev_err(&client->dev, "failed to allocate memory\n");
-		error = -ENOMEM;
-		goto failed_free_mem;
+		return -ENOMEM;
+	}
+
+	input_dev = devm_input_allocate_device(&client->dev);
+	if (!input_dev) {
+		dev_err(&client->dev, "failed to allocate input device\n");
+		return -ENOMEM;
 	}
 
 	keypad->client = client;
@@ -230,19 +235,20 @@ static int max7359_probe(struct i2c_clie
 
 	max7359_build_keycode(keypad, keymap_data);
 
-	error = request_threaded_irq(client->irq, NULL, max7359_interrupt,
-				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				     client->name, keypad);
+	error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+					  max7359_interrupt,
+					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					  client->name, keypad);
 	if (error) {
 		dev_err(&client->dev, "failed to register interrupt\n");
-		goto failed_free_mem;
+		return error;
 	}
 
 	/* Register the input device */
 	error = input_register_device(input_dev);
 	if (error) {
 		dev_err(&client->dev, "failed to register input device\n");
-		goto failed_free_irq;
+		return error;
 	}
 
 	/* Initialize MAX7359 */
@@ -252,24 +258,6 @@ static int max7359_probe(struct i2c_clie
 	device_init_wakeup(&client->dev, 1);
 
 	return 0;
-
-failed_free_irq:
-	free_irq(client->irq, keypad);
-failed_free_mem:
-	input_free_device(input_dev);
-	kfree(keypad);
-	return error;
-}
-
-static int max7359_remove(struct i2c_client *client)
-{
-	struct max7359_keypad *keypad = i2c_get_clientdata(client);
-
-	free_irq(client->irq, keypad);
-	input_unregister_device(keypad->input_dev);
-	kfree(keypad);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -313,7 +301,6 @@ static struct i2c_driver max7359_i2c_dri
 		.pm   = &max7359_pm,
 	},
 	.probe		= max7359_probe,
-	.remove		= max7359_remove,
 	.id_table	= max7359_ids,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/misc/keyspan_remote.c linux-libre-3.17-rc7-gnu/drivers/input/misc/keyspan_remote.c
--- linux-libre-3.16-gnu/drivers/input/misc/keyspan_remote.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/misc/keyspan_remote.c	2014-09-28 17:29:07.000000000 -0400
@@ -392,7 +392,6 @@ static void keyspan_irq_recv(struct urb
 
 	default:
 		goto resubmit;
-		break;
 	}
 
 	if (debug)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/misc/soc_button_array.c linux-libre-3.17-rc7-gnu/drivers/input/misc/soc_button_array.c
--- linux-libre-3.16-gnu/drivers/input/misc/soc_button_array.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/misc/soc_button_array.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,6 +83,9 @@ soc_button_device_create(struct pnp_dev
 				       sizeof(*gpio_keys_pdata) +
 					sizeof(*gpio_keys) * MAX_NBUTTONS,
 				       GFP_KERNEL);
+	if (!gpio_keys_pdata)
+		return ERR_PTR(-ENOMEM);
+
 	gpio_keys = (void *)(gpio_keys_pdata + 1);
 
 	for (info = button_info; info->name; info++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/misc/sparcspkr.c linux-libre-3.17-rc7-gnu/drivers/input/misc/sparcspkr.c
--- linux-libre-3.16-gnu/drivers/input/misc/sparcspkr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/misc/sparcspkr.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,13 +86,13 @@ static int bbc_spkr_event(struct input_d
 	spin_lock_irqsave(&state->lock, flags);
 
 	if (count) {
-		outb(0x01,                 info->regs + 0);
-		outb(0x00,                 info->regs + 2);
-		outb((count >> 16) & 0xff, info->regs + 3);
-		outb((count >>  8) & 0xff, info->regs + 4);
-		outb(0x00,                 info->regs + 5);
+		sbus_writeb(0x01,                 info->regs + 0);
+		sbus_writeb(0x00,                 info->regs + 2);
+		sbus_writeb((count >> 16) & 0xff, info->regs + 3);
+		sbus_writeb((count >>  8) & 0xff, info->regs + 4);
+		sbus_writeb(0x00,                 info->regs + 5);
 	} else {
-		outb(0x00,                 info->regs + 0);
+		sbus_writeb(0x00,                 info->regs + 0);
 	}
 
 	spin_unlock_irqrestore(&state->lock, flags);
@@ -123,15 +123,15 @@ static int grover_spkr_event(struct inpu
 
 	if (count) {
 		/* enable counter 2 */
-		outb(inb(info->enable_reg) | 3, info->enable_reg);
+		sbus_writeb(sbus_readb(info->enable_reg) | 3, info->enable_reg);
 		/* set command for counter 2, 2 byte write */
-		outb(0xB6, info->freq_regs + 1);
+		sbus_writeb(0xB6, info->freq_regs + 1);
 		/* select desired HZ */
-		outb(count & 0xff, info->freq_regs + 0);
-		outb((count >> 8) & 0xff, info->freq_regs + 0);
+		sbus_writeb(count & 0xff, info->freq_regs + 0);
+		sbus_writeb((count >> 8) & 0xff, info->freq_regs + 0);
 	} else {
 		/* disable counter 2 */
-		outb(inb_p(info->enable_reg) & 0xFC, info->enable_reg);
+		sbus_writeb(sbus_readb(info->enable_reg) & 0xFC, info->enable_reg);
 	}
 
 	spin_unlock_irqrestore(&state->lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/misc/uinput.c linux-libre-3.17-rc7-gnu/drivers/input/misc/uinput.c
--- linux-libre-3.16-gnu/drivers/input/misc/uinput.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/misc/uinput.c	2014-09-28 17:29:07.000000000 -0400
@@ -311,7 +311,14 @@ static int uinput_open(struct inode *ino
 static int uinput_validate_absbits(struct input_dev *dev)
 {
 	unsigned int cnt;
-	int retval = 0;
+	int nslot;
+
+	if (!test_bit(EV_ABS, dev->evbit))
+		return 0;
+
+	/*
+	 * Check if absmin/absmax/absfuzz/absflat are sane.
+	 */
 
 	for (cnt = 0; cnt < ABS_CNT; cnt++) {
 		int min, max;
@@ -327,8 +334,7 @@ static int uinput_validate_absbits(struc
 				UINPUT_NAME, cnt,
 				input_abs_get_min(dev, cnt),
 				input_abs_get_max(dev, cnt));
-			retval = -EINVAL;
-			break;
+			return -EINVAL;
 		}
 
 		if (input_abs_get_flat(dev, cnt) >
@@ -340,11 +346,18 @@ static int uinput_validate_absbits(struc
 				input_abs_get_flat(dev, cnt),
 				input_abs_get_min(dev, cnt),
 				input_abs_get_max(dev, cnt));
-			retval = -EINVAL;
-			break;
+			return -EINVAL;
 		}
 	}
-	return retval;
+
+	if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+		nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+		input_mt_init_slots(dev, nslot, 0);
+	} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+		input_set_events_per_packet(dev, 60);
+	}
+
+	return 0;
 }
 
 static int uinput_allocate_device(struct uinput_device *udev)
@@ -410,19 +423,9 @@ static int uinput_setup_device(struct ui
 		input_abs_set_flat(dev, i, user_dev->absflat[i]);
 	}
 
-	/* check if absmin/absmax/absfuzz/absflat are filled as
-	 * told in Documentation/input/input-programming.txt */
-	if (test_bit(EV_ABS, dev->evbit)) {
-		retval = uinput_validate_absbits(dev);
-		if (retval < 0)
-			goto exit;
-		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
-			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-			input_mt_init_slots(dev, nslot, 0);
-		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
-			input_set_events_per_packet(dev, 60);
-		}
-	}
+	retval = uinput_validate_absbits(dev);
+	if (retval < 0)
+		goto exit;
 
 	udev->state = UIST_SETUP_COMPLETE;
 	retval = count;
@@ -720,6 +723,12 @@ static long uinput_ioctl_handler(struct
 	}
 
 	switch (cmd) {
+		case UI_GET_VERSION:
+			if (put_user(UINPUT_VERSION,
+				     (unsigned int __user *)p))
+				retval = -EFAULT;
+			goto out;
+
 		case UI_DEV_CREATE:
 			retval = uinput_create_device(udev);
 			goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/alps.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/alps.c
--- linux-libre-3.16-gnu/drivers/input/mouse/alps.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/alps.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,8 @@ static const struct alps_nibble_commands
 #define ALPS_FOUR_BUTTONS	0x40	/* 4 direction button present */
 #define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
 					   6-byte ALPS packet */
+#define ALPS_IS_RUSHMORE	0x100	/* device is a rushmore */
+#define ALPS_BUTTONPAD		0x200	/* device is a clickpad */
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },	/* Toshiba Salellite Pro M10 */
@@ -281,11 +283,10 @@ static void alps_process_packet_v1_v2(st
  *
  * The bitmaps don't have enough data to track fingers, so this function
  * only generates points representing a bounding box of at most two contacts.
- * These two points are returned in x1, y1, x2, and y2.
+ * These two points are returned in fields->mt.
  */
 static void alps_process_bitmap_dolphin(struct alps_data *priv,
-					struct alps_fields *fields,
-					int *x1, int *y1, int *x2, int *y2)
+					struct alps_fields *fields)
 {
 	int box_middle_x, box_middle_y;
 	unsigned int x_map, y_map;
@@ -308,8 +309,6 @@ static void alps_process_bitmap_dolphin(
 	if (x_msb > priv->x_bits || y_msb > priv->y_bits)
 		return;
 
-	*x1 = *y1 = *x2 = *y2 = 0;
-
 	if (fields->fingers > 1) {
 		start_bit = priv->x_bits - x_msb;
 		end_bit = priv->x_bits - x_lsb;
@@ -320,10 +319,35 @@ static void alps_process_bitmap_dolphin(
 		end_bit = y_msb - 1;
 		box_middle_y = (priv->y_max * (start_bit + end_bit)) /
 				(2 * (priv->y_bits - 1));
-		*x1 = fields->x;
-		*y1 = fields->y;
-		*x2 = 2 * box_middle_x - *x1;
-		*y2 = 2 * box_middle_y - *y1;
+		fields->mt[0] = fields->st;
+		fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x;
+		fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y;
+	}
+}
+
+static void alps_get_bitmap_points(unsigned int map,
+				   struct alps_bitmap_point *low,
+				   struct alps_bitmap_point *high,
+				   int *fingers)
+{
+	struct alps_bitmap_point *point;
+	int i, bit, prev_bit = 0;
+
+	point = low;
+	for (i = 0; map != 0; i++, map >>= 1) {
+		bit = map & 1;
+		if (bit) {
+			if (!prev_bit) {
+				point->start_bit = i;
+				point->num_bits = 0;
+				(*fingers)++;
+			}
+			point->num_bits++;
+		} else {
+			if (prev_bit)
+				point = high;
+		}
+		prev_bit = bit;
 	}
 }
 
@@ -334,71 +358,21 @@ static void alps_process_bitmap_dolphin(
  *
  * The bitmaps don't have enough data to track fingers, so this function
  * only generates points representing a bounding box of all contacts.
- * These points are returned in x1, y1, x2, and y2 when the return value
+ * These points are returned in fields->mt when the return value
  * is greater than 0.
  */
 static int alps_process_bitmap(struct alps_data *priv,
-			       unsigned int x_map, unsigned int y_map,
-			       int *x1, int *y1, int *x2, int *y2)
+			       struct alps_fields *fields)
 {
-	struct alps_bitmap_point {
-		int start_bit;
-		int num_bits;
-	};
-
-	int fingers_x = 0, fingers_y = 0, fingers;
-	int i, bit, prev_bit;
+	int i, fingers_x = 0, fingers_y = 0, fingers;
 	struct alps_bitmap_point x_low = {0,}, x_high = {0,};
 	struct alps_bitmap_point y_low = {0,}, y_high = {0,};
-	struct alps_bitmap_point *point;
 
-	if (!x_map || !y_map)
+	if (!fields->x_map || !fields->y_map)
 		return 0;
 
-	*x1 = *y1 = *x2 = *y2 = 0;
-
-	prev_bit = 0;
-	point = &x_low;
-	for (i = 0; x_map != 0; i++, x_map >>= 1) {
-		bit = x_map & 1;
-		if (bit) {
-			if (!prev_bit) {
-				point->start_bit = i;
-				fingers_x++;
-			}
-			point->num_bits++;
-		} else {
-			if (prev_bit)
-				point = &x_high;
-			else
-				point->num_bits = 0;
-		}
-		prev_bit = bit;
-	}
-
-	/*
-	 * y bitmap is reversed for what we need (lower positions are in
-	 * higher bits), so we process from the top end.
-	 */
-	y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits);
-	prev_bit = 0;
-	point = &y_low;
-	for (i = 0; y_map != 0; i++, y_map <<= 1) {
-		bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1));
-		if (bit) {
-			if (!prev_bit) {
-				point->start_bit = i;
-				fingers_y++;
-			}
-			point->num_bits++;
-		} else {
-			if (prev_bit)
-				point = &y_high;
-			else
-				point->num_bits = 0;
-		}
-		prev_bit = bit;
-	}
+	alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
+	alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
 
 	/*
 	 * Fingers can overlap, so we use the maximum count of fingers
@@ -407,58 +381,91 @@ static int alps_process_bitmap(struct al
 	fingers = max(fingers_x, fingers_y);
 
 	/*
-	 * If total fingers is > 1 but either axis reports only a single
-	 * contact, we have overlapping or adjacent fingers. For the
-	 * purposes of creating a bounding box, divide the single contact
-	 * (roughly) equally between the two points.
+	 * If an axis reports only a single contact, we have overlapping or
+	 * adjacent fingers. Divide the single contact between the two points.
 	 */
-	if (fingers > 1) {
-		if (fingers_x == 1) {
-			i = x_low.num_bits / 2;
-			x_low.num_bits = x_low.num_bits - i;
-			x_high.start_bit = x_low.start_bit + i;
-			x_high.num_bits = max(i, 1);
-		} else if (fingers_y == 1) {
-			i = y_low.num_bits / 2;
-			y_low.num_bits = y_low.num_bits - i;
-			y_high.start_bit = y_low.start_bit + i;
-			y_high.num_bits = max(i, 1);
-		}
+	if (fingers_x == 1) {
+		i = (x_low.num_bits - 1) / 2;
+		x_low.num_bits = x_low.num_bits - i;
+		x_high.start_bit = x_low.start_bit + i;
+		x_high.num_bits = max(i, 1);
+	}
+	if (fingers_y == 1) {
+		i = (y_low.num_bits - 1) / 2;
+		y_low.num_bits = y_low.num_bits - i;
+		y_high.start_bit = y_low.start_bit + i;
+		y_high.num_bits = max(i, 1);
 	}
 
-	*x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
-	      (2 * (priv->x_bits - 1));
-	*y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
-	      (2 * (priv->y_bits - 1));
+	fields->mt[0].x =
+		(priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
+		(2 * (priv->x_bits - 1));
+	fields->mt[0].y =
+		(priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
+		(2 * (priv->y_bits - 1));
 
-	if (fingers > 1) {
-		*x2 = (priv->x_max *
-		       (2 * x_high.start_bit + x_high.num_bits - 1)) /
-		      (2 * (priv->x_bits - 1));
-		*y2 = (priv->y_max *
-		       (2 * y_high.start_bit + y_high.num_bits - 1)) /
-		      (2 * (priv->y_bits - 1));
+	fields->mt[1].x =
+		(priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
+		(2 * (priv->x_bits - 1));
+	fields->mt[1].y =
+		(priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
+		(2 * (priv->y_bits - 1));
+
+	/* y-bitmap order is reversed, except on rushmore */
+	if (!(priv->flags & ALPS_IS_RUSHMORE)) {
+		fields->mt[0].y = priv->y_max - fields->mt[0].y;
+		fields->mt[1].y = priv->y_max - fields->mt[1].y;
 	}
 
 	return fingers;
 }
 
-static void alps_set_slot(struct input_dev *dev, int slot, bool active,
-			  int x, int y)
+static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
 {
 	input_mt_slot(dev, slot);
-	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
-	if (active) {
-		input_report_abs(dev, ABS_MT_POSITION_X, x);
-		input_report_abs(dev, ABS_MT_POSITION_Y, y);
-	}
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+	input_report_abs(dev, ABS_MT_POSITION_X, x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, y);
 }
 
-static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers,
-				     int x1, int y1, int x2, int y2)
+static void alps_report_mt_data(struct psmouse *psmouse, int n)
 {
-	alps_set_slot(dev, 0, num_fingers != 0, x1, y1);
-	alps_set_slot(dev, 1, num_fingers == 2, x2, y2);
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+	int i, slot[MAX_TOUCHES];
+
+	input_mt_assign_slots(dev, slot, f->mt, n);
+	for (i = 0; i < n; i++)
+		alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
+
+	input_mt_sync_frame(dev);
+}
+
+static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+
+	/* Use st data when we don't have mt data */
+	if (fingers < 2) {
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+		fingers = f->pressure > 0 ? 1 : 0;
+	}
+
+	alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2);
+
+	input_mt_report_finger_count(dev, fingers);
+
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
+
+	input_report_abs(dev, ABS_PRESSURE, f->pressure);
+
+	input_sync(dev);
 }
 
 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
@@ -532,7 +539,7 @@ static void alps_decode_buttons_v3(struc
 	f->ts_middle = !!(p[3] & 0x40);
 }
 
-static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
+static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
 				 struct psmouse *psmouse)
 {
 	f->first_mp = !!(p[4] & 0x40);
@@ -546,24 +553,31 @@ static void alps_decode_pinnacle(struct
 		   ((p[2] & 0x7f) << 1) |
 		   (p[4] & 0x01);
 
-	f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
+	f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
 	       ((p[0] & 0x30) >> 4);
-	f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
-	f->z = p[5] & 0x7f;
+	f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
+	f->pressure = p[5] & 0x7f;
 
 	alps_decode_buttons_v3(f, p);
+
+	return 0;
 }
 
-static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
+static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
 				 struct psmouse *psmouse)
 {
 	alps_decode_pinnacle(f, p, psmouse);
 
+	/* Rushmore's packet decode has a bit difference with Pinnacle's */
+	f->is_mp = !!(p[5] & 0x40);
+	f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
 	f->x_map |= (p[5] & 0x10) << 11;
 	f->y_map |= (p[5] & 0x20) << 6;
+
+	return 0;
 }
 
-static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
+static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
 				struct psmouse *psmouse)
 {
 	u64 palm_data = 0;
@@ -573,9 +587,9 @@ static void alps_decode_dolphin(struct a
 	f->is_mp = !!(p[0] & 0x20);
 
 	if (!f->is_mp) {
-		f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
-		f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
-		f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
+		f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
+		f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
+		f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
 		alps_decode_buttons_v3(f, p);
 	} else {
 		f->fingers = ((p[0] & 0x6) >> 1 |
@@ -596,19 +610,21 @@ static void alps_decode_dolphin(struct a
 		f->x_map = (palm_data >> priv->y_bits) &
 			   (BIT(priv->x_bits) - 1);
 	}
+
+	return 0;
 }
 
 static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev2 = priv->dev2;
-	int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
-	int fingers = 0, bmap_fn;
-	struct alps_fields f = {0};
+	struct alps_fields *f = &priv->f;
+	int fingers = 0;
 
-	priv->decode_fields(&f, packet, psmouse);
+	memset(f, 0, sizeof(*f));
+
+	priv->decode_fields(f, packet, psmouse);
 
 	/*
 	 * There's no single feature of touchpad position and bitmap packets
@@ -623,22 +639,14 @@ static void alps_process_touchpad_packet
 		 * packet. Check for this, and when it happens process the
 		 * position packet as usual.
 		 */
-		if (f.is_mp) {
-			fingers = f.fingers;
+		if (f->is_mp) {
+			fingers = f->fingers;
 			if (priv->proto_version == ALPS_PROTO_V3) {
-				bmap_fn = alps_process_bitmap(priv, f.x_map,
-							      f.y_map, &x1, &y1,
-							      &x2, &y2);
-
-				/*
-				 * We shouldn't report more than one finger if
-				 * we don't have two coordinates.
-				 */
-				if (fingers > 1 && bmap_fn < 2)
-					fingers = bmap_fn;
+				if (alps_process_bitmap(priv, f) == 0)
+					fingers = 0; /* Use st data */
 
 				/* Now process position packet */
-				priv->decode_fields(&f, priv->multi_data,
+				priv->decode_fields(f, priv->multi_data,
 						    psmouse);
 			} else {
 				/*
@@ -647,15 +655,14 @@ static void alps_process_touchpad_packet
 				 * calculate Pt2, so we need to do position
 				 * packet decode first.
 				 */
-				priv->decode_fields(&f, priv->multi_data,
+				priv->decode_fields(f, priv->multi_data,
 						    psmouse);
 
 				/*
 				 * Since Dolphin's finger number is reliable,
 				 * there is no need to compare with bmap_fn.
 				 */
-				alps_process_bitmap_dolphin(priv, &f, &x1, &y1,
-							    &x2, &y2);
+				alps_process_bitmap_dolphin(priv, f);
 			}
 		} else {
 			priv->multi_packet = 0;
@@ -670,10 +677,10 @@ static void alps_process_touchpad_packet
 	 * out misidentified bitmap packets, we reject anything with this
 	 * bit set.
 	 */
-	if (f.is_mp)
+	if (f->is_mp)
 		return;
 
-	if (!priv->multi_packet && f.first_mp) {
+	if (!priv->multi_packet && f->first_mp) {
 		priv->multi_packet = 1;
 		memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
 		return;
@@ -687,44 +694,15 @@ static void alps_process_touchpad_packet
 	 * with x, y, and z all zero, so these seem to be flukes.
 	 * Ignore them.
 	 */
-	if (f.x && f.y && !f.z)
+	if (f->st.x && f->st.y && !f->pressure)
 		return;
 
-	/*
-	 * If we don't have MT data or the bitmaps were empty, we have
-	 * to rely on ST data.
-	 */
-	if (!fingers) {
-		x1 = f.x;
-		y1 = f.y;
-		fingers = f.z > 0 ? 1 : 0;
-	}
-
-	if (f.z >= 64)
-		input_report_key(dev, BTN_TOUCH, 1);
-	else
-		input_report_key(dev, BTN_TOUCH, 0);
-
-	alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
-
-	input_mt_report_finger_count(dev, fingers);
-
-	input_report_key(dev, BTN_LEFT, f.left);
-	input_report_key(dev, BTN_RIGHT, f.right);
-	input_report_key(dev, BTN_MIDDLE, f.middle);
-
-	if (f.z > 0) {
-		input_report_abs(dev, ABS_X, f.x);
-		input_report_abs(dev, ABS_Y, f.y);
-	}
-	input_report_abs(dev, ABS_PRESSURE, f.z);
-
-	input_sync(dev);
+	alps_report_semi_mt_data(psmouse, fingers);
 
 	if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
-		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_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);
 	}
 }
@@ -823,13 +801,8 @@ static void alps_process_packet_v4(struc
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
 	int offset;
-	int x, y, z;
-	int left, right;
-	int x1, y1, x2, y2;
-	int fingers = 0;
-	unsigned int x_bitmap, y_bitmap;
 
 	/*
 	 * v4 has a 6-byte encoding for bitmap data, but this data is
@@ -851,71 +824,207 @@ static void alps_process_packet_v4(struc
 	if (++priv->multi_packet > 2) {
 		priv->multi_packet = 0;
 
-		x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
+		f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
 			   ((priv->multi_data[3] & 0x60) << 3) |
 			   ((priv->multi_data[0] & 0x3f) << 2) |
 			   ((priv->multi_data[1] & 0x60) >> 5);
-		y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
+		f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
 			   ((priv->multi_data[3] & 0x1f) << 5) |
 			    (priv->multi_data[1] & 0x1f);
 
-		fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap,
-					      &x1, &y1, &x2, &y2);
-
-		/* Store MT data.*/
-		priv->fingers = fingers;
-		priv->x1 = x1;
-		priv->x2 = x2;
-		priv->y1 = y1;
-		priv->y2 = y2;
+		f->fingers = alps_process_bitmap(priv, f);
 	}
 
-	left = packet[4] & 0x01;
-	right = packet[4] & 0x02;
+	f->left = packet[4] & 0x01;
+	f->right = packet[4] & 0x02;
 
-	x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
-	    ((packet[0] & 0x30) >> 4);
-	y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
-	z = packet[5] & 0x7f;
+	f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
+		  ((packet[0] & 0x30) >> 4);
+	f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
+	f->pressure = packet[5] & 0x7f;
 
-	/*
-	 * If there were no contacts in the bitmap, use ST
-	 * points in MT reports.
-	 * If there were two contacts or more, report MT data.
-	 */
-	if (priv->fingers < 2) {
-		x1 = x;
-		y1 = y;
-		fingers = z > 0 ? 1 : 0;
-	} else {
-		fingers = priv->fingers;
-		x1 = priv->x1;
-		x2 = priv->x2;
-		y1 = priv->y1;
-		y2 = priv->y2;
+	alps_report_semi_mt_data(psmouse, f->fingers);
+}
+
+static bool alps_is_valid_package_v7(struct psmouse *psmouse)
+{
+	switch (psmouse->pktcnt) {
+	case 3:
+		return (psmouse->packet[2] & 0x40) == 0x40;
+	case 4:
+		return (psmouse->packet[3] & 0x48) == 0x48;
+	case 6:
+		return (psmouse->packet[5] & 0x40) == 0x00;
 	}
+	return true;
+}
 
-	if (z >= 64)
-		input_report_key(dev, BTN_TOUCH, 1);
+static unsigned char alps_get_packet_id_v7(char *byte)
+{
+	unsigned char packet_id;
+
+	if (byte[4] & 0x40)
+		packet_id = V7_PACKET_ID_TWO;
+	else if (byte[4] & 0x01)
+		packet_id = V7_PACKET_ID_MULTI;
+	else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
+		packet_id = V7_PACKET_ID_NEW;
+	else if (byte[1] == 0x00 && byte[4] == 0x00)
+		packet_id = V7_PACKET_ID_IDLE;
 	else
-		input_report_key(dev, BTN_TOUCH, 0);
+		packet_id = V7_PACKET_ID_UNKNOWN;
 
-	alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	return packet_id;
+}
 
-	input_mt_report_finger_count(dev, fingers);
+static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
+					  unsigned char *pkt,
+					  unsigned char pkt_id)
+{
+	mt[0].x = ((pkt[2] & 0x80) << 4);
+	mt[0].x |= ((pkt[2] & 0x3F) << 5);
+	mt[0].x |= ((pkt[3] & 0x30) >> 1);
+	mt[0].x |= (pkt[3] & 0x07);
+	mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
+	mt[1].x = ((pkt[3] & 0x80) << 4);
+	mt[1].x |= ((pkt[4] & 0x80) << 3);
+	mt[1].x |= ((pkt[4] & 0x3F) << 4);
+	mt[1].y = ((pkt[5] & 0x80) << 3);
+	mt[1].y |= ((pkt[5] & 0x3F) << 4);
 
-	if (z > 0) {
-		input_report_abs(dev, ABS_X, x);
-		input_report_abs(dev, ABS_Y, y);
+	switch (pkt_id) {
+	case V7_PACKET_ID_TWO:
+		mt[1].x &= ~0x000F;
+		mt[1].y |= 0x000F;
+		break;
+
+	case V7_PACKET_ID_MULTI:
+		mt[1].x &= ~0x003F;
+		mt[1].y &= ~0x0020;
+		mt[1].y |= ((pkt[4] & 0x02) << 4);
+		mt[1].y |= 0x001F;
+		break;
+
+	case V7_PACKET_ID_NEW:
+		mt[1].x &= ~0x003F;
+		mt[1].x |= (pkt[0] & 0x20);
+		mt[1].y |= 0x000F;
+		break;
 	}
-	input_report_abs(dev, ABS_PRESSURE, z);
+
+	mt[0].y = 0x7FF - mt[0].y;
+	mt[1].y = 0x7FF - mt[1].y;
+}
+
+static int alps_get_mt_count(struct input_mt_pos *mt)
+{
+	int i;
+
+	for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
+		/* empty */;
+
+	return i;
+}
+
+static int alps_decode_packet_v7(struct alps_fields *f,
+				  unsigned char *p,
+				  struct psmouse *psmouse)
+{
+	unsigned char pkt_id;
+
+	pkt_id = alps_get_packet_id_v7(p);
+	if (pkt_id == V7_PACKET_ID_IDLE)
+		return 0;
+	if (pkt_id == V7_PACKET_ID_UNKNOWN)
+		return -1;
+
+	alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
+
+	if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
+		f->left = (p[0] & 0x80) >> 7;
+		f->right = (p[0] & 0x20) >> 5;
+		f->middle = (p[0] & 0x10) >> 4;
+	}
+
+	if (pkt_id == V7_PACKET_ID_TWO)
+		f->fingers = alps_get_mt_count(f->mt);
+	else if (pkt_id == V7_PACKET_ID_MULTI)
+		f->fingers = 3 + (p[5] & 0x03);
+
+	return 0;
+}
+
+static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	struct input_dev *dev2 = priv->dev2;
+	int x, y, z, left, right, middle;
+
+	/*
+	 *        b7 b6 b5 b4 b3 b2 b1 b0
+	 * Byte0   0  1  0  0  1  0  0  0
+	 * Byte1   1  1  *  *  1  M  R  L
+	 * Byte2  X7  1 X5 X4 X3 X2 X1 X0
+	 * Byte3  Z6  1 Y6 X6  1 Y2 Y1 Y0
+	 * Byte4  Y7  0 Y5 Y4 Y3  1  1  0
+	 * Byte5 T&P  0 Z5 Z4 Z3 Z2 Z1 Z0
+	 * M / R / L: Middle / Right / Left button
+	 */
+
+	x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
+	y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
+	    ((packet[3] & 0x20) << 1);
+	z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
+
+	left = (packet[1] & 0x01);
+	right = (packet[1] & 0x02) >> 1;
+	middle = (packet[1] & 0x04) >> 2;
+
+	/* Divide 2 since trackpoint's speed is too fast */
+	input_report_rel(dev2, REL_X, (char)x / 2);
+	input_report_rel(dev2, REL_Y, -((char)y / 2));
+
+	input_report_key(dev2, BTN_LEFT, left);
+	input_report_key(dev2, BTN_RIGHT, right);
+	input_report_key(dev2, BTN_MIDDLE, middle);
+
+	input_sync(dev2);
+}
+
+static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev = psmouse->dev;
+	struct alps_fields *f = &priv->f;
+
+	memset(f, 0, sizeof(*f));
+
+	if (priv->decode_fields(f, psmouse->packet, psmouse))
+		return;
+
+	alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
+
+	input_mt_report_finger_count(dev, f->fingers);
+
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
 
 	input_sync(dev);
 }
 
+static void alps_process_packet_v7(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06)
+		alps_process_trackstick_packet_v7(psmouse);
+	else
+		alps_process_touchpad_packet_v7(psmouse);
+}
+
 static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
 					unsigned char packet[],
 					bool report_buttons)
@@ -1080,6 +1189,14 @@ static psmouse_ret_t alps_process_byte(s
 		return PSMOUSE_BAD_DATA;
 	}
 
+	if (priv->proto_version == ALPS_PROTO_V7 &&
+	    !alps_is_valid_package_v7(psmouse)) {
+		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+			    psmouse->pktcnt - 1,
+			    psmouse->packet[psmouse->pktcnt - 1]);
+		return PSMOUSE_BAD_DATA;
+	}
+
 	if (psmouse->pktcnt == psmouse->pktsize) {
 		priv->process_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
@@ -1192,6 +1309,22 @@ static int alps_rpt_cmd(struct psmouse *
 	return 0;
 }
 
+static bool alps_check_valid_firmware_id(unsigned char id[])
+{
+	if (id[0] == 0x73)
+		return true;
+
+	if (id[0] == 0x88 &&
+	    (id[1] == 0x07 ||
+	     id[1] == 0x08 ||
+	     (id[1] & 0xf0) == 0xb0 ||
+	     (id[1] & 0xf0) == 0xc0)) {
+		return true;
+	}
+
+	return false;
+}
+
 static int alps_enter_command_mode(struct psmouse *psmouse)
 {
 	unsigned char param[4];
@@ -1201,8 +1334,7 @@ static int alps_enter_command_mode(struc
 		return -1;
 	}
 
-	if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
-	    param[0] != 0x73) {
+	if (!alps_check_valid_firmware_id(param)) {
 		psmouse_dbg(psmouse,
 			    "unknown response while entering command mode\n");
 		return -1;
@@ -1660,6 +1792,45 @@ error:
 	return -1;
 }
 
+static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
+{
+	int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys;
+	struct alps_data *priv = psmouse->private;
+
+	reg = alps_command_mode_read_reg(psmouse, reg_pitch);
+	if (reg < 0)
+		return reg;
+
+	x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+	x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
+
+	y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
+	y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
+
+	reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
+	if (reg < 0)
+		return reg;
+
+	x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+	x_electrode = 17 + x_electrode;
+
+	y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
+	y_electrode = 13 + y_electrode;
+
+	x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
+	y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */
+
+	priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
+	priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
+
+	psmouse_dbg(psmouse,
+		    "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n",
+		    x_pitch, y_pitch, x_electrode, y_electrode,
+		    x_phys / 10, y_phys / 10, priv->x_res, priv->y_res);
+
+	return 0;
+}
+
 static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -1680,6 +1851,9 @@ static int alps_hw_init_rushmore_v3(stru
 	    alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
 		goto error;
 
+	if (alps_get_v3_v7_resolution(psmouse, 0xc2da))
+		goto error;
+
 	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
 	if (reg_val == -1)
 		goto error;
@@ -1856,6 +2030,35 @@ static int alps_hw_init_dolphin_v1(struc
 	return 0;
 }
 
+static int alps_hw_init_v7(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	int reg_val, ret = -1;
+
+	if (alps_enter_command_mode(psmouse) ||
+	    alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
+		goto error;
+
+	if (alps_get_v3_v7_resolution(psmouse, 0xc397))
+		goto error;
+
+	if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
+		goto error;
+
+	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
+	if (reg_val == -1)
+		goto error;
+	if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
+		goto error;
+
+	alps_exit_command_mode(psmouse);
+	return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+error:
+	alps_exit_command_mode(psmouse);
+	return ret;
+}
+
 static void alps_set_defaults(struct alps_data *priv)
 {
 	priv->byte0 = 0x8f;
@@ -1914,6 +2117,21 @@ static void alps_set_defaults(struct alp
 		priv->x_max = 2047;
 		priv->y_max = 1535;
 		break;
+	case ALPS_PROTO_V7:
+		priv->hw_init = alps_hw_init_v7;
+		priv->process_packet = alps_process_packet_v7;
+		priv->decode_fields = alps_decode_packet_v7;
+		priv->set_abs_params = alps_set_abs_params_mt;
+		priv->nibble_commands = alps_v3_nibble_commands;
+		priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+		priv->x_max = 0xfff;
+		priv->y_max = 0x7ff;
+		priv->byte0 = 0x48;
+		priv->mask0 = 0x48;
+
+		if (priv->fw_ver[1] != 0xba)
+			priv->flags |= ALPS_BUTTONPAD;
+		break;
 	}
 }
 
@@ -1972,6 +2190,9 @@ static int alps_identify(struct psmouse
 	    alps_exit_command_mode(psmouse))
 		return -EIO;
 
+	/* Save the Firmware version */
+	memcpy(priv->fw_ver, ec, 3);
+
 	if (alps_match_table(psmouse, priv, e7, ec) == 0) {
 		return 0;
 	} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
@@ -1982,6 +2203,12 @@ static int alps_identify(struct psmouse
 			return -EIO;
 		else
 			return 0;
+	} else if (ec[0] == 0x88 &&
+		   ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
+		priv->proto_version = ALPS_PROTO_V7;
+		alps_set_defaults(priv);
+
+		return 0;
 	} else if (ec[0] == 0x88 && ec[1] == 0x08) {
 		priv->proto_version = ALPS_PROTO_V3;
 		alps_set_defaults(priv);
@@ -1990,6 +2217,7 @@ static int alps_identify(struct psmouse
 		priv->decode_fields = alps_decode_rushmore;
 		priv->x_bits = 16;
 		priv->y_bits = 12;
+		priv->flags |= ALPS_IS_RUSHMORE;
 
 		/* hack to make addr_command, nibble_command available */
 		psmouse->private = priv;
@@ -2006,8 +2234,8 @@ static int alps_identify(struct psmouse
 		return 0;
 	}
 
-	psmouse_info(psmouse,
-		     "Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
+	psmouse_dbg(psmouse,
+		    "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
 
 	return -EINVAL;
 }
@@ -2044,17 +2272,21 @@ static void alps_set_abs_params_st(struc
 static void alps_set_abs_params_mt(struct alps_data *priv,
 				   struct input_dev *dev1)
 {
-	set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
-	input_mt_init_slots(dev1, 2, 0);
 	input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
 	input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
 
-	set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
+	input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res);
+	input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res);
+
+	input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER |
+		INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT);
+
 	set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
 	set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
 
-	input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
-	input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
+	/* V7 is real multi-touch */
+	if (priv->proto_version == ALPS_PROTO_V7)
+		clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
 }
 
 int alps_init(struct psmouse *psmouse)
@@ -2100,7 +2332,9 @@ int alps_init(struct psmouse *psmouse)
 	dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
 
 	priv->set_abs_params(priv, dev1);
-	input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
+	/* No pressure on V7 */
+	if (priv->proto_version != ALPS_PROTO_V7)
+		input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
 
 	if (priv->flags & ALPS_WHEEL) {
 		dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
@@ -2117,6 +2351,9 @@ int alps_init(struct psmouse *psmouse)
 		dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
 		dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
 		dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+	} else if (priv->flags & ALPS_BUTTONPAD) {
+		set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
+		clear_bit(BTN_RIGHT, dev1->keybit);
 	} else {
 		dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
 	}
@@ -2136,6 +2373,10 @@ int alps_init(struct psmouse *psmouse)
 	dev2->keybit[BIT_WORD(BTN_LEFT)] =
 		BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
 
+	__set_bit(INPUT_PROP_POINTER, dev2->propbit);
+	if (priv->flags & ALPS_DUALPOINT)
+		__set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
+
 	if (input_register_device(priv->dev2))
 		goto init_fail;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/alps.h linux-libre-3.17-rc7-gnu/drivers/input/mouse/alps.h
--- linux-libre-3.16-gnu/drivers/input/mouse/alps.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/alps.h	2014-09-28 17:29:07.000000000 -0400
@@ -12,17 +12,39 @@
 #ifndef _ALPS_H
 #define _ALPS_H
 
+#include <linux/input/mt.h>
+
 #define ALPS_PROTO_V1	1
 #define ALPS_PROTO_V2	2
 #define ALPS_PROTO_V3	3
 #define ALPS_PROTO_V4	4
 #define ALPS_PROTO_V5	5
 #define ALPS_PROTO_V6	6
+#define ALPS_PROTO_V7	7	/* t3btl t4s */
+
+#define MAX_TOUCHES	2
 
 #define DOLPHIN_COUNT_PER_ELECTRODE	64
 #define DOLPHIN_PROFILE_XOFFSET		8	/* x-electrode offset */
 #define DOLPHIN_PROFILE_YOFFSET		1	/* y-electrode offset */
 
+/*
+ * enum V7_PACKET_ID - defines the packet type for V7
+ * V7_PACKET_ID_IDLE: There's no finger and no button activity.
+ * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
+ *  or there's button activities.
+ * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
+ * V7_PACKET_ID_NEW: The finger position in slot is not continues from
+ *  previous packet.
+*/
+enum V7_PACKET_ID {
+	 V7_PACKET_ID_IDLE,
+	 V7_PACKET_ID_TWO,
+	 V7_PACKET_ID_MULTI,
+	 V7_PACKET_ID_NEW,
+	 V7_PACKET_ID_UNKNOWN,
+};
+
 /**
  * struct alps_model_info - touchpad ID table
  * @signature: E7 response string to match.
@@ -46,7 +68,7 @@ struct alps_model_info {
 	unsigned char command_mode_resp;
 	unsigned char proto_version;
 	unsigned char byte0, mask0;
-	unsigned char flags;
+	int flags;
 };
 
 /**
@@ -65,14 +87,19 @@ struct alps_nibble_commands {
 	unsigned char data;
 };
 
+struct alps_bitmap_point {
+	int start_bit;
+	int num_bits;
+};
+
 /**
  * struct alps_fields - decoded version of the report packet
  * @x_map: Bitmap of active X positions for MT.
  * @y_map: Bitmap of active Y positions for MT.
  * @fingers: Number of fingers for MT.
- * @x: X position for ST.
- * @y: Y position for ST.
- * @z: Z position for ST.
+ * @pressure: Pressure.
+ * @st: position for ST.
+ * @mt: position for MT.
  * @first_mp: Packet is the first of a multi-packet report.
  * @is_mp: Packet is part of a multi-packet report.
  * @left: Left touchpad button is active.
@@ -86,9 +113,11 @@ struct alps_fields {
 	unsigned int x_map;
 	unsigned int y_map;
 	unsigned int fingers;
-	unsigned int x;
-	unsigned int y;
-	unsigned int z;
+
+	int pressure;
+	struct input_mt_pos st;
+	struct input_mt_pos mt[MAX_TOUCHES];
+
 	unsigned int first_mp:1;
 	unsigned int is_mp:1;
 
@@ -113,6 +142,7 @@ struct alps_fields {
  *   known format for this model.  The first byte of the report, ANDed with
  *   mask0, should match byte0.
  * @mask0: The mask used to check the first byte of the report.
+ * @fw_ver: cached copy of firmware version (EC report)
  * @flags: Additional device capabilities (passthrough port, trackstick, etc.).
  * @x_max: Largest possible X position value.
  * @y_max: Largest possible Y position value.
@@ -125,11 +155,7 @@ struct alps_fields {
  * @prev_fin: Finger bit from previous packet.
  * @multi_packet: Multi-packet data in progress.
  * @multi_data: Saved multi-packet data.
- * @x1: First X coordinate from last MT report.
- * @x2: Second X coordinate from last MT report.
- * @y1: First Y coordinate from last MT report.
- * @y2: Second Y coordinate from last MT report.
- * @fingers: Number of fingers from last MT report.
+ * @f: Decoded packet data fields.
  * @quirks: Bitmap of ALPS_QUIRK_*.
  * @timer: Timer for flushing out the final report packet in the stream.
  */
@@ -142,23 +168,25 @@ struct alps_data {
 	int addr_command;
 	unsigned char proto_version;
 	unsigned char byte0, mask0;
-	unsigned char flags;
+	unsigned char fw_ver[3];
+	int flags;
 	int x_max;
 	int y_max;
 	int x_bits;
 	int y_bits;
+	unsigned int x_res;
+	unsigned int y_res;
 
 	int (*hw_init)(struct psmouse *psmouse);
 	void (*process_packet)(struct psmouse *psmouse);
-	void (*decode_fields)(struct alps_fields *f, unsigned char *p,
+	int (*decode_fields)(struct alps_fields *f, unsigned char *p,
 			      struct psmouse *psmouse);
 	void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
 
 	int prev_fin;
 	int multi_packet;
 	unsigned char multi_data[6];
-	int x1, x2, y1, y2;
-	int fingers;
+	struct alps_fields f;
 	u8 quirks;
 	struct timer_list timer;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/elantech.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/elantech.c
--- linux-libre-3.16-gnu/drivers/input/mouse/elantech.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/elantech.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/libps2.h>
+#include <asm/unaligned.h>
 #include "psmouse.h"
 #include "elantech.h"
 
@@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(
 	input_sync(dev);
 }
 
+static void elantech_report_trackpoint(struct psmouse *psmouse,
+				       int packet_type)
+{
+	/*
+	 * byte 0:  0   0  sx  sy   0   M   R   L
+	 * byte 1:~sx   0   0   0   0   0   0   0
+	 * byte 2:~sy   0   0   0   0   0   0   0
+	 * byte 3:  0   0 ~sy ~sx   0   1   1   0
+	 * byte 4: x7  x6  x5  x4  x3  x2  x1  x0
+	 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+	 *
+	 * x and y are written in two's complement spread
+	 * over 9 bits with sx/sy the relative top bit and
+	 * x7..x0 and y7..y0 the lower bits.
+	 * The sign of y is opposite to what the input driver
+	 * expects for a relative movement
+	 */
+
+	struct elantech_data *etd = psmouse->private;
+	struct input_dev *tp_dev = etd->tp_dev;
+	unsigned char *packet = psmouse->packet;
+	int x, y;
+	u32 t;
+
+	if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
+			  !tp_dev,
+			  psmouse_fmt("Unexpected trackpoint message\n"))) {
+		if (etd->debug == 1)
+			elantech_packet_dump(psmouse);
+		return;
+	}
+
+	t = get_unaligned_le32(&packet[0]);
+
+	switch (t & ~7U) {
+	case 0x06000030U:
+	case 0x16008020U:
+	case 0x26800010U:
+	case 0x36808000U:
+		x = packet[4] - (int)((packet[1]^0x80) << 1);
+		y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+		input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
+		input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
+		input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+
+		input_report_rel(tp_dev, REL_X, x);
+		input_report_rel(tp_dev, REL_Y, y);
+
+		input_sync(tp_dev);
+
+		break;
+
+	default:
+		/* Dump unexpected packet sequences if debug=1 (default) */
+		if (etd->debug == 1)
+			elantech_packet_dump(psmouse);
+
+		break;
+	}
+}
+
 /*
  * Interpret complete data packets and report absolute mode input events for
  * hardware version 3. (12 byte packets for two fingers)
@@ -715,6 +778,8 @@ static int elantech_packet_check_v3(stru
 
 		if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
 			return PACKET_V3_TAIL;
+		if ((packet[3] & 0x0f) == 0x06)
+			return PACKET_TRACKPOINT;
 	}
 
 	return PACKET_UNKNOWN;
@@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_by
 
 	case 3:
 		packet_type = elantech_packet_check_v3(psmouse);
-		/* ignore debounce */
-		if (packet_type == PACKET_DEBOUNCE)
-			return PSMOUSE_FULL_PACKET;
-
-		if (packet_type == PACKET_UNKNOWN)
+		switch (packet_type) {
+		case PACKET_UNKNOWN:
 			return PSMOUSE_BAD_DATA;
 
-		elantech_report_absolute_v3(psmouse, packet_type);
+		case PACKET_DEBOUNCE:
+			/* ignore debounce */
+			break;
+
+		case PACKET_TRACKPOINT:
+			elantech_report_trackpoint(psmouse, packet_type);
+			break;
+
+		default:
+			elantech_report_absolute_v3(psmouse, packet_type);
+			break;
+		}
+
 		break;
 
 	case 4:
@@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(st
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
  * Lenovo L430             0x350f02        b9, 15, 0c      2 hw buttons (*)
+ * Lenovo L530             0x350f02        b9, 15, 0c      2 hw buttons (*)
  * Samsung NF210           0x150b00        78, 14, 0a      2 hw buttons
  * Samsung NP770Z5E        0x575f01        10, 15, 0f      clickpad
  * Samsung NP700Z5B        0x361f06        21, 15, 0f      clickpad
@@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(st
  * Samsung RF710           0x450f00        ?               2 hw buttons
  * System76 Pangolin       0x250f01        ?               2 hw buttons
  * (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
  */
 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
 {
@@ -1253,6 +1331,13 @@ static bool elantech_is_signature_valid(
 	if (param[1] == 0)
 		return true;
 
+	/*
+	 * Some models have a revision higher then 20. Meaning param[2] may
+	 * be 10 or 20, skip the rates check for these.
+	 */
+	if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
+		return true;
+
 	for (i = 0; i < ARRAY_SIZE(rates); i++)
 		if (param[2] == rates[i])
 			return false;
@@ -1324,6 +1409,10 @@ int elantech_detect(struct psmouse *psmo
  */
 static void elantech_disconnect(struct psmouse *psmouse)
 {
+	struct elantech_data *etd = psmouse->private;
+
+	if (etd->tp_dev)
+		input_unregister_device(etd->tp_dev);
 	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
 			   &elantech_attr_group);
 	kfree(psmouse->private);
@@ -1438,8 +1527,10 @@ static int elantech_set_properties(struc
 int elantech_init(struct psmouse *psmouse)
 {
 	struct elantech_data *etd;
-	int i, error;
+	int i;
+	int error = -EINVAL;
 	unsigned char param[3];
+	struct input_dev *tp_dev;
 
 	psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
 	if (!etd)
@@ -1498,14 +1589,53 @@ int elantech_init(struct psmouse *psmous
 		goto init_fail;
 	}
 
+	/* The MSB indicates the presence of the trackpoint */
+	if ((etd->capabilities[0] & 0x80) == 0x80) {
+		tp_dev = input_allocate_device();
+
+		if (!tp_dev) {
+			error = -ENOMEM;
+			goto init_fail_tp_alloc;
+		}
+
+		etd->tp_dev = tp_dev;
+		snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
+			psmouse->ps2dev.serio->phys);
+		tp_dev->phys = etd->tp_phys;
+		tp_dev->name = "Elantech PS/2 TrackPoint";
+		tp_dev->id.bustype = BUS_I8042;
+		tp_dev->id.vendor  = 0x0002;
+		tp_dev->id.product = PSMOUSE_ELANTECH;
+		tp_dev->id.version = 0x0000;
+		tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+		tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+		tp_dev->relbit[BIT_WORD(REL_X)] =
+			BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+		tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
+			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+			BIT_MASK(BTN_RIGHT);
+
+		__set_bit(INPUT_PROP_POINTER, tp_dev->propbit);
+		__set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit);
+
+		error = input_register_device(etd->tp_dev);
+		if (error < 0)
+			goto init_fail_tp_reg;
+	}
+
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
 	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
-
+ init_fail_tp_reg:
+	input_free_device(tp_dev);
+ init_fail_tp_alloc:
+	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
+			   &elantech_attr_group);
  init_fail:
+	psmouse_reset(psmouse);
 	kfree(etd);
-	return -1;
+	return error;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/elantech.h linux-libre-3.17-rc7-gnu/drivers/input/mouse/elantech.h
--- linux-libre-3.16-gnu/drivers/input/mouse/elantech.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/elantech.h	2014-09-28 17:29:07.000000000 -0400
@@ -94,6 +94,7 @@
 #define PACKET_V4_HEAD			0x05
 #define PACKET_V4_MOTION		0x06
 #define PACKET_V4_STATUS		0x07
+#define PACKET_TRACKPOINT		0x08
 
 /*
  * track up to 5 fingers for v4 hardware
@@ -114,6 +115,8 @@ struct finger_pos {
 };
 
 struct elantech_data {
+	struct input_dev *tp_dev;	/* Relative device for trackpoint */
+	char tp_phys[32];
 	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/psmouse-base.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/psmouse-base.c
--- linux-libre-3.16-gnu/drivers/input/mouse/psmouse-base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/psmouse-base.c	2014-09-28 17:29:07.000000000 -0400
@@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struc
 	__set_bit(REL_X, input_dev->relbit);
 	__set_bit(REL_Y, input_dev->relbit);
 
+	__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
 	psmouse->set_rate = psmouse_set_rate;
 	psmouse->set_resolution = psmouse_set_resolution;
 	psmouse->poll = psmouse_poll;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/synaptics.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-3.16-gnu/drivers/input/mouse/synaptics.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psm
 }
 
 #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+
+static bool cr48_profile_sensor;
+
 struct min_max_quirk {
 	const char * const *pnp_ids;
 	int x_min, x_max, y_min, y_max;
@@ -626,10 +629,61 @@ static int synaptics_parse_hw_state(cons
 			 ((buf[0] & 0x04) >> 1) |
 			 ((buf[3] & 0x04) >> 2));
 
+		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+		    hw->w == 2) {
+			synaptics_parse_agm(buf, priv, hw);
+			return 1;
+		}
+
+		hw->x = (((buf[3] & 0x10) << 8) |
+			 ((buf[1] & 0x0f) << 8) |
+			 buf[4]);
+		hw->y = (((buf[3] & 0x20) << 7) |
+			 ((buf[1] & 0xf0) << 4) |
+			 buf[5]);
+		hw->z = buf[2];
+
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 
-		if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+		if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) {
+			/*
+			 * ForcePads, like Clickpads, use middle button
+			 * bits to report primary button clicks.
+			 * Unfortunately they report primary button not
+			 * only when user presses on the pad above certain
+			 * threshold, but also when there are more than one
+			 * finger on the touchpad, which interferes with
+			 * out multi-finger gestures.
+			 */
+			if (hw->z == 0) {
+				/* No contacts */
+				priv->press = priv->report_press = false;
+			} else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
+				/*
+				 * Single-finger touch with pressure above
+				 * the threshold. If pressure stays long
+				 * enough, we'll start reporting primary
+				 * button. We rely on the device continuing
+				 * sending data even if finger does not
+				 * move.
+				 */
+				if  (!priv->press) {
+					priv->press_start = jiffies;
+					priv->press = true;
+				} else if (time_after(jiffies,
+						priv->press_start +
+							msecs_to_jiffies(50))) {
+					priv->report_press = true;
+				}
+			} else {
+				priv->press = false;
+			}
+
+			hw->left = priv->report_press;
+
+		} else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
 			/*
 			 * Clickpad's button is transmitted as middle button,
 			 * however, since it is primary button, we will report
@@ -648,21 +702,6 @@ static int synaptics_parse_hw_state(cons
 			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
 
-		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
-			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
-		    hw->w == 2) {
-			synaptics_parse_agm(buf, priv, hw);
-			return 1;
-		}
-
-		hw->x = (((buf[3] & 0x10) << 8) |
-			 ((buf[1] & 0x0f) << 8) |
-			 buf[4]);
-		hw->y = (((buf[3] & 0x20) << 7) |
-			 ((buf[1] & 0xf0) << 4) |
-			 buf[5]);
-		hw->z = buf[2];
-
 		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
 		    ((buf[0] ^ buf[3]) & 0x02)) {
 			switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
@@ -1152,6 +1191,42 @@ static void synaptics_image_sensor_proce
 	priv->agm_pending = false;
 }
 
+static void synaptics_profile_sensor_process(struct psmouse *psmouse,
+					     struct synaptics_hw_state *sgm,
+					     int num_fingers)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
+	struct input_mt_pos pos[2];
+	int slot[2], nsemi, i;
+
+	nsemi = clamp_val(num_fingers, 0, 2);
+
+	for (i = 0; i < nsemi; i++) {
+		pos[i].x = hw[i]->x;
+		pos[i].y = synaptics_invert_y(hw[i]->y);
+	}
+
+	input_mt_assign_slots(dev, slot, pos, nsemi);
+
+	for (i = 0; i < nsemi; i++) {
+		input_mt_slot(dev, slot[i]);
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+		input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
+		input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
+	}
+
+	input_mt_drop_unused(dev);
+	input_mt_report_pointer_emulation(dev, false);
+	input_mt_report_finger_count(dev, num_fingers);
+
+	synaptics_report_buttons(psmouse, sgm);
+
+	input_sync(dev);
+}
+
 /*
  *  called for each full received packet from the touchpad
  */
@@ -1215,6 +1290,11 @@ static void synaptics_process_packet(str
 		finger_width = 0;
 	}
 
+	if (cr48_profile_sensor) {
+		synaptics_profile_sensor_process(psmouse, &hw, num_fingers);
+		return;
+	}
+
 	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
 		synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
 					      num_fingers);
@@ -1360,6 +1440,9 @@ static void set_input_params(struct psmo
 	set_abs_position_params(dev, priv, ABS_X, ABS_Y);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
+	if (cr48_profile_sensor)
+		input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
 	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
@@ -1371,11 +1454,16 @@ static void set_input_params(struct psmo
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
 		__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
 	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
-		/* Non-image sensors with AGM use semi-mt */
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
-		input_mt_init_slots(dev, 2, 0);
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
+		/*
+		 * Profile sensor in CR-48 tracks contacts reasonably well,
+		 * other non-image sensors with AGM use semi-mt.
+		 */
+		input_mt_init_slots(dev, 2,
+				    INPUT_MT_POINTER |
+				    (cr48_profile_sensor ?
+					INPUT_MT_TRACK : INPUT_MT_SEMI_MT));
 	}
 
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -1577,10 +1665,24 @@ static const struct dmi_system_id olpc_d
 	{ }
 };
 
+static const struct dmi_system_id __initconst cr48_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+	{
+		/* Cr-48 Chromebook (Codename Mario) */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
+		},
+	},
+#endif
+	{ }
+};
+
 void __init synaptics_module_init(void)
 {
 	impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
 	broken_olpc_ec = dmi_check_system(olpc_dmi_table);
+	cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
 }
 
 static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/synaptics.h linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics.h
--- linux-libre-3.16-gnu/drivers/input/mouse/synaptics.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics.h	2014-09-28 17:29:07.000000000 -0400
@@ -78,6 +78,11 @@
  * 2	0x08	image sensor		image sensor tracks 5 fingers, but only
  *					reports 2.
  * 2	0x20	report min		query 0x0f gives min coord reported
+ * 2	0x80	forcepad		forcepad is a variant of clickpad that
+ *					does not have physical buttons but rather
+ *					uses pressure above certain threshold to
+ *					report primary clicks. Forcepads also have
+ *					clickpad bit set.
  */
 #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)	((ex0c) & 0x000100) /* 2-button ClickPad */
@@ -86,6 +91,7 @@
 #define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
 #define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
 #define SYN_CAP_IMAGE_SENSOR(ex0c)	((ex0c) & 0x000800)
+#define SYN_CAP_FORCEPAD(ex0c)		((ex0c) & 0x008000)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -177,6 +183,11 @@ struct synaptics_data {
 	 */
 	struct synaptics_hw_state agm;
 	bool agm_pending;			/* new AGM packet received */
+
+	/* ForcePad handling */
+	unsigned long				press_start;
+	bool					press;
+	bool					report_press;
 };
 
 void synaptics_module_init(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/synaptics_usb.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics_usb.c
--- linux-libre-3.16-gnu/drivers/input/mouse/synaptics_usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/synaptics_usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_inter
 		__set_bit(EV_REL, input_dev->evbit);
 		__set_bit(REL_X, input_dev->relbit);
 		__set_bit(REL_Y, input_dev->relbit);
+		__set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit);
 		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0);
 	} else {
 		input_set_abs_params(input_dev, ABS_X,
@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_inter
 		__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 	}
 
+	if (synusb->flags & SYNUSB_TOUCHSCREEN)
+		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+	else
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
 	__set_bit(BTN_LEFT, input_dev->keybit);
 	__set_bit(BTN_RIGHT, input_dev->keybit);
 	__set_bit(BTN_MIDDLE, input_dev->keybit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/mouse/trackpoint.c linux-libre-3.17-rc7-gnu/drivers/input/mouse/trackpoint.c
--- linux-libre-3.16-gnu/drivers/input/mouse/trackpoint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/mouse/trackpoint.c	2014-09-28 17:29:07.000000000 -0400
@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *ps
 	if ((button_info & 0x0f) >= 3)
 		__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
 
+	__set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit);
+	__set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit);
+
 	trackpoint_defaults(psmouse->private);
 
 	error = trackpoint_power_on_reset(&psmouse->ps2dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/serio/hyperv-keyboard.c linux-libre-3.17-rc7-gnu/drivers/input/serio/hyperv-keyboard.c
--- linux-libre-3.16-gnu/drivers/input/serio/hyperv-keyboard.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/serio/hyperv-keyboard.c	2014-09-28 17:29:07.000000000 -0400
@@ -170,6 +170,15 @@ static void hv_kbd_on_receive(struct hv_
 			serio_interrupt(kbd_dev->hv_serio, scan_code, 0);
 		}
 		spin_unlock_irqrestore(&kbd_dev->lock, flags);
+
+		/*
+		 * Only trigger a wakeup on key down, otherwise
+		 * "echo freeze > /sys/power/state" can't really enter the
+		 * state because the Enter-UP can trigger a wakeup at once.
+		 */
+		if (!(info & IS_BREAK))
+			pm_wakeup_event(&hv_dev->device, 0);
+
 		break;
 
 	default:
@@ -376,6 +385,9 @@ static int hv_kbd_probe(struct hv_device
 		goto err_close_vmbus;
 
 	serio_register_port(kbd_dev->hv_serio);
+
+	device_init_wakeup(&hv_dev->device, true);
+
 	return 0;
 
 err_close_vmbus:
@@ -390,6 +402,7 @@ static int hv_kbd_remove(struct hv_devic
 {
 	struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
 
+	device_init_wakeup(&hv_dev->device, false);
 	serio_unregister_port(kbd_dev->hv_serio);
 	vmbus_close(hv_dev->channel);
 	kfree(kbd_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/serio/i8042.c linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042.c
--- linux-libre-3.16-gnu/drivers/input/serio/i8042.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042.c	2014-09-28 17:29:07.000000000 -0400
@@ -1254,6 +1254,8 @@ static int __init i8042_create_aux_port(
 	} else {
 		snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx);
 		snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1);
+		strlcpy(serio->firmware_id, i8042_aux_firmware_id,
+			sizeof(serio->firmware_id));
 	}
 
 	port->serio = serio;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/serio/i8042-sparcio.h linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042-sparcio.h
--- linux-libre-3.16-gnu/drivers/input/serio/i8042-sparcio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042-sparcio.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,7 +17,6 @@ static int i8042_aux_irq = -1;
 #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
 
 static void __iomem *kbd_iobase;
-static struct resource *kbd_res;
 
 #define I8042_COMMAND_REG	(kbd_iobase + 0x64UL)
 #define I8042_DATA_REG		(kbd_iobase + 0x60UL)
@@ -44,6 +43,8 @@ static inline void i8042_write_command(i
 
 #ifdef CONFIG_PCI
 
+static struct resource *kbd_res;
+
 #define OBP_PS2KBD_NAME1	"kb_ps2"
 #define OBP_PS2KBD_NAME2	"keyboard"
 #define OBP_PS2MS_NAME1		"kdmouse"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.16-gnu/drivers/input/serio/i8042-x86ia64io.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/serio/i8042-x86ia64io.h	2014-09-28 17:29:07.000000000 -0400
@@ -465,6 +465,20 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
 		},
 	},
+	{
+		/* Asus X450LCP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+		},
+	},
+	{
+		/* Avatar AVIU-145A6 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
+		},
+	},
 	{ }
 };
 
@@ -608,6 +622,14 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
 		},
 	},
+	{
+		/* Fujitsu U574 laptop */
+		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+		},
+	},
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/serio/serport.c linux-libre-3.17-rc7-gnu/drivers/input/serio/serport.c
--- linux-libre-3.16-gnu/drivers/input/serio/serport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/serio/serport.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/tty.h>
+#include <linux/compat.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Input device TTY line discipline");
@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct
 	return 0;
 }
 
+static void serport_set_type(struct tty_struct *tty, unsigned long type)
+{
+	struct serport *serport = tty->disc_data;
+
+	serport->id.proto = type & 0x000000ff;
+	serport->id.id    = (type & 0x0000ff00) >> 8;
+	serport->id.extra = (type & 0x00ff0000) >> 16;
+}
+
 /*
  * serport_ldisc_ioctl() allows to set the port protocol, and device ID
  */
 
-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
+			       unsigned int cmd, unsigned long arg)
 {
-	struct serport *serport = (struct serport*) tty->disc_data;
-	unsigned long type;
-
 	if (cmd == SPIOCSTYPE) {
+		unsigned long type;
+
 		if (get_user(type, (unsigned long __user *) arg))
 			return -EFAULT;
 
-		serport->id.proto = type & 0x000000ff;
-		serport->id.id	  = (type & 0x0000ff00) >> 8;
-		serport->id.extra = (type & 0x00ff0000) >> 16;
+		serport_set_type(tty, type);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+#define COMPAT_SPIOCSTYPE	_IOW('q', 0x01, compat_ulong_t)
+static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
+				       struct file *file,
+				       unsigned int cmd, unsigned long arg)
+{
+	if (cmd == COMPAT_SPIOCSTYPE) {
+		void __user *uarg = compat_ptr(arg);
+		compat_ulong_t compat_type;
+
+		if (get_user(compat_type, (compat_ulong_t __user *)uarg))
+			return -EFAULT;
 
+		serport_set_type(tty, compat_type);
 		return 0;
 	}
 
 	return -EINVAL;
 }
+#endif
 
 static void serport_ldisc_write_wakeup(struct tty_struct * tty)
 {
@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldis
 	.close =	serport_ldisc_close,
 	.read =		serport_ldisc_read,
 	.ioctl =	serport_ldisc_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	serport_ldisc_compat_ioctl,
+#endif
 	.receive_buf =	serport_ldisc_receive,
 	.write_wakeup =	serport_ldisc_write_wakeup
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/Kconfig linux-libre-3.17-rc7-gnu/drivers/input/tablet/Kconfig
--- linux-libre-3.16-gnu/drivers/input/tablet/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -73,20 +73,14 @@ config TABLET_USB_KBTAB
 	  To compile this driver as a module, choose M here: the
 	  module will be called kbtab.
 
-config TABLET_USB_WACOM
-	tristate "Wacom Intuos/Graphire tablet support (USB)"
-	depends on USB_ARCH_HAS_HCD
-	select POWER_SUPPLY
-	select USB
-	select NEW_LEDS
-	select LEDS_CLASS
+config TABLET_SERIAL_WACOM4
+	tristate "Wacom protocol 4 serial tablet support"
+	select SERIO
 	help
-	  Say Y here if you want to use the USB version of the Wacom Intuos
-	  or Graphire tablet.  Make sure to say Y to "Mouse support"
-	  (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-	  (CONFIG_INPUT_EVDEV) as well.
+	  Say Y here if you want to use Wacom protocol 4 serial tablets.
+	  E.g. serial versions of the Cintiq, Graphire or Penpartner.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called wacom.
+	  module will be called wacom_serial4.
 
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/Makefile linux-libre-3.17-rc7-gnu/drivers/input/tablet/Makefile
--- linux-libre-3.16-gnu/drivers/input/tablet/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,12 +2,10 @@
 # Makefile for the tablet drivers
 #
 
-# Multipart objects.
-wacom-objs	:= wacom_wac.o wacom_sys.o
 
 obj-$(CONFIG_TABLET_USB_ACECAD)	+= acecad.o
 obj-$(CONFIG_TABLET_USB_AIPTEK)	+= aiptek.o
 obj-$(CONFIG_TABLET_USB_GTCO)	+= gtco.o
 obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
 obj-$(CONFIG_TABLET_USB_KBTAB)	+= kbtab.o
-obj-$(CONFIG_TABLET_USB_WACOM)	+= wacom.o
+obj-$(CONFIG_TABLET_SERIAL_WACOM4) += wacom_serial4.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/wacom.h linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom.h
--- linux-libre-3.16-gnu/drivers/input/tablet/wacom.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/*
- * drivers/input/tablet/wacom.h
- *
- *  USB Wacom tablet support
- *
- *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
- *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
- *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
- *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
- *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
- *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
- *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
- *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2011 Ping Cheng		<pingc@wacom.com>
- *
- *  ChangeLog:
- *      v0.1 (vp)  - Initial release
- *      v0.2 (aba) - Support for all buttons / combinations
- *      v0.3 (vp)  - Support for Intuos added
- *	v0.4 (sm)  - Support for more Intuos models, menustrip
- *			relative mode, proximity.
- *	v0.5 (vp)  - Big cleanup, nifty features removed,
- *			they belong in userspace
- *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
- *			use input_report_key instead of report_btn and
- *			other cleanups
- *	v1.11 (vp) - Add URB ->dev setting for new kernels
- *	v1.11 (jb) - Add support for the 4D Mouse & Lens
- *	v1.12 (de) - Add support for two more inking pen IDs
- *	v1.14 (vp) - Use new USB device id probing scheme.
- *		     Fix Wacom Graphire mouse wheel
- *	v1.18 (vp) - Fix mouse wheel direction
- *		     Make mouse relative
- *      v1.20 (fl) - Report tool id for Intuos devices
- *                 - Multi tools support
- *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
- *                 - Add PL models support
- *		   - Fix Wacom Graphire mouse wheel again
- *	v1.21 (vp) - Removed protocol descriptions
- *		   - Added MISC_SERIAL for tool serial numbers
- *	      (gb) - Identify version on module load.
- *    v1.21.1 (fl) - added Graphire2 support
- *    v1.21.2 (fl) - added Intuos2 support
- *                 - added all the PL ids
- *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
- *                 - added smooth filter for Graphire from Peri Hankey
- *                 - added PenPartner support from Olaf van Es
- *                 - new tool ids from Ole Martin Bjoerndalen
- *	v1.29 (pc) - Add support for more tablets
- *		   - Fix pressure reporting
- *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
- *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
- *		   - Cleanups here and there
- *    v1.30.1 (pi) - Added Graphire3 support
- *	v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
- *	v1.43 (pc) - Added support for Cintiq 21UX
- *		   - Fixed a Graphire bug
- *		   - Merged wacom_intuos3_irq into wacom_intuos_irq
- *	v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
- *		   - Report Device IDs
- *      v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
- *                 - Minor data report fix
- *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
- *		   - where wacom_sys.c deals with system specific code,
- *		   - and wacom_wac.c deals with Wacom specific code
- *		   - Support Intuos3 4x6
- *      v1.47 (pc) - Added support for Bamboo
- *      v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
- *      v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
- *      v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
- *      v1.51 (pc) - Added support for Intuos4
- *      v1.52 (pc) - Query Wacom data upon system resume
- *                 - add defines for features->type
- *                 - add new devices (0x9F, 0xE2, and 0XE3)
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 WACOM_H
-#define WACOM_H
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/usb/input.h>
-#include <linux/power_supply.h>
-#include <asm/unaligned.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.53"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom tablet driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-#define USB_VENDOR_ID_WACOM	0x056a
-#define USB_VENDOR_ID_LENOVO	0x17ef
-
-struct wacom {
-	dma_addr_t data_dma;
-	struct usb_device *usbdev;
-	struct usb_interface *intf;
-	struct urb *irq;
-	struct wacom_wac wacom_wac;
-	struct mutex lock;
-	struct work_struct work;
-	bool open;
-	char phys[32];
-	struct wacom_led {
-		u8 select[2]; /* status led selector (0..3) */
-		u8 llv;       /* status led brightness no button (1..127) */
-		u8 hlv;       /* status led brightness button pressed (1..127) */
-		u8 img_lum;   /* OLED matrix display brightness */
-	} led;
-	struct power_supply battery;
-};
-
-static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
-{
-	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
-	schedule_work(&wacom->work);
-}
-
-extern const struct usb_device_id wacom_ids[];
-
-void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
-void wacom_setup_device_quirks(struct wacom_features *features);
-int wacom_setup_input_capabilities(struct input_dev *input_dev,
-				   struct wacom_wac *wacom_wac);
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/wacom_serial4.c linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_serial4.c
--- linux-libre-3.16-gnu/drivers/input/tablet/wacom_serial4.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_serial4.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,620 @@
+/*
+ * Wacom protocol 4 serial tablet driver
+ *
+ * Copyright 2014      Hans de Goede <hdegoede@redhat.com>
+ * Copyright 2011-2012 Julian Squires <julian@cipht.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 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.
+ *
+ * Many thanks to Bill Seremetis, without whom PenPartner support
+ * would not have been possible. Thanks to Patrick Mahoney.
+ *
+ * This driver was developed with reference to much code written by others,
+ * particularly:
+ *  - elo, gunze drivers by Vojtech Pavlik <vojtech@ucw.cz>;
+ *  - wacom_w8001 driver by Jaya Kumar <jayakumar.lkml@gmail.com>;
+ *  - the USB wacom input driver, credited to many people
+ *    (see drivers/input/tablet/wacom.h);
+ *  - new and old versions of linuxwacom / xf86-input-wacom credited to
+ *    Frederic Lepied, France. <Lepied@XFree86.org> and
+ *    Ping Cheng, Wacom. <pingc@wacom.com>;
+ *  - and xf86wacom.c (a presumably ancient version of the linuxwacom code),
+ *    by Frederic Lepied and Raph Levien <raph@gtk.org>.
+ *
+ * To do:
+ *  - support pad buttons; (requires access to a model with pad buttons)
+ *  - support (protocol 4-style) tilt (requires access to a > 1.4 rom model)
+ */
+
+/*
+ * Wacom serial protocol 4 documentation taken from linuxwacom-0.9.9 code,
+ * protocol 4 uses 7 or 9 byte of data in the following format:
+ *
+ *	Byte 1
+ *	bit 7  Sync bit always 1
+ *	bit 6  Pointing device detected
+ *	bit 5  Cursor = 0 / Stylus = 1
+ *	bit 4  Reserved
+ *	bit 3  1 if a button on the pointing device has been pressed
+ *	bit 2  P0 (optional)
+ *	bit 1  X15
+ *	bit 0  X14
+ *
+ *	Byte 2
+ *	bit 7  Always 0
+ *	bits 6-0 = X13 - X7
+ *
+ *	Byte 3
+ *	bit 7  Always 0
+ *	bits 6-0 = X6 - X0
+ *
+ *	Byte 4
+ *	bit 7  Always 0
+ *	bit 6  B3
+ *	bit 5  B2
+ *	bit 4  B1
+ *	bit 3  B0
+ *	bit 2  P1 (optional)
+ *	bit 1  Y15
+ *	bit 0  Y14
+ *
+ *	Byte 5
+ *	bit 7  Always 0
+ *	bits 6-0 = Y13 - Y7
+ *
+ *	Byte 6
+ *	bit 7  Always 0
+ *	bits 6-0 = Y6 - Y0
+ *
+ *	Byte 7
+ *	bit 7 Always 0
+ *	bit 6  Sign of pressure data; or wheel-rel for cursor tool
+ *	bit 5  P7; or REL1 for cursor tool
+ *	bit 4  P6; or REL0 for cursor tool
+ *	bit 3  P5
+ *	bit 2  P4
+ *	bit 1  P3
+ *	bit 0  P2
+ *
+ *	byte 8 and 9 are optional and present only
+ *	in tilt mode.
+ *
+ *	Byte 8
+ *	bit 7 Always 0
+ *	bit 6 Sign of tilt X
+ *	bit 5  Xt6
+ *	bit 4  Xt5
+ *	bit 3  Xt4
+ *	bit 2  Xt3
+ *	bit 1  Xt2
+ *	bit 0  Xt1
+ *
+ *	Byte 9
+ *	bit 7 Always 0
+ *	bit 6 Sign of tilt Y
+ *	bit 5  Yt6
+ *	bit 4  Yt5
+ *	bit 3  Yt4
+ *	bit 2  Yt3
+ *	bit 1  Yt2
+ *	bit 0  Yt1
+ */
+
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+MODULE_AUTHOR("Julian Squires <julian@cipht.net>, Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Wacom protocol 4 serial tablet driver");
+MODULE_LICENSE("GPL");
+
+#define REQUEST_MODEL_AND_ROM_VERSION	"~#"
+#define REQUEST_MAX_COORDINATES		"~C\r"
+#define REQUEST_CONFIGURATION_STRING	"~R\r"
+#define REQUEST_RESET_TO_PROTOCOL_IV	"\r#"
+/*
+ * Note: sending "\r$\r" causes at least the Digitizer II to send
+ * packets in ASCII instead of binary.  "\r#" seems to undo that.
+ */
+
+#define COMMAND_START_SENDING_PACKETS		"ST\r"
+#define COMMAND_STOP_SENDING_PACKETS		"SP\r"
+#define COMMAND_MULTI_MODE_INPUT		"MU1\r"
+#define COMMAND_ORIGIN_IN_UPPER_LEFT		"OC1\r"
+#define COMMAND_ENABLE_ALL_MACRO_BUTTONS	"~M0\r"
+#define COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS	"~M1\r"
+#define COMMAND_TRANSMIT_AT_MAX_RATE		"IT0\r"
+#define COMMAND_DISABLE_INCREMENTAL_MODE	"IN0\r"
+#define COMMAND_ENABLE_CONTINUOUS_MODE		"SR\r"
+#define COMMAND_ENABLE_PRESSURE_MODE		"PH1\r"
+#define COMMAND_Z_FILTER			"ZF1\r"
+
+/* Note that this is a protocol 4 packet without tilt information. */
+#define PACKET_LENGTH		7
+#define DATA_SIZE		32
+
+/* flags */
+#define F_COVERS_SCREEN		0x01
+#define F_HAS_STYLUS2		0x02
+#define F_HAS_SCROLLWHEEL	0x04
+
+/* device IDs */
+#define STYLUS_DEVICE_ID	0x02
+#define CURSOR_DEVICE_ID	0x06
+#define ERASER_DEVICE_ID	0x0A
+
+enum { STYLUS = 1, ERASER, CURSOR };
+
+static const struct {
+	int device_id;
+	int input_id;
+} tools[] = {
+	{ 0, 0 },
+	{ STYLUS_DEVICE_ID, BTN_TOOL_PEN },
+	{ ERASER_DEVICE_ID, BTN_TOOL_RUBBER },
+	{ CURSOR_DEVICE_ID, BTN_TOOL_MOUSE },
+};
+
+struct wacom {
+	struct input_dev *dev;
+	struct completion cmd_done;
+	int result;
+	u8 expect;
+	u8 eraser_mask;
+	unsigned int extra_z_bits;
+	unsigned int flags;
+	unsigned int res_x, res_y;
+	unsigned int max_x, max_y;
+	unsigned int tool;
+	unsigned int idx;
+	u8 data[DATA_SIZE];
+	char phys[32];
+};
+
+enum {
+	MODEL_CINTIQ		= 0x504C, /* PL */
+	MODEL_CINTIQ2		= 0x4454, /* DT */
+	MODEL_DIGITIZER_II	= 0x5544, /* UD */
+	MODEL_GRAPHIRE		= 0x4554, /* ET */
+	MODEL_PENPARTNER	= 0x4354, /* CT */
+};
+
+static void wacom_handle_model_response(struct wacom *wacom)
+{
+	int major_v, minor_v, r = 0;
+	char *p;
+
+	p = strrchr(wacom->data, 'V');
+	if (p)
+		r = sscanf(p + 1, "%u.%u", &major_v, &minor_v);
+	if (r != 2)
+		major_v = minor_v = 0;
+
+	switch (wacom->data[2] << 8 | wacom->data[3]) {
+	case MODEL_CINTIQ:	/* UNTESTED */
+	case MODEL_CINTIQ2:
+		if ((wacom->data[2] << 8 | wacom->data[3]) == MODEL_CINTIQ) {
+			wacom->dev->name = "Wacom Cintiq";
+			wacom->dev->id.version = MODEL_CINTIQ;
+		} else {
+			wacom->dev->name = "Wacom Cintiq II";
+			wacom->dev->id.version = MODEL_CINTIQ2;
+		}
+		wacom->res_x = 508;
+		wacom->res_y = 508;
+
+		switch (wacom->data[5] << 8 | wacom->data[6]) {
+		case 0x3731: /* PL-710 */
+			wacom->res_x = 2540;
+			wacom->res_y = 2540;
+			/* fall through */
+		case 0x3535: /* PL-550 */
+		case 0x3830: /* PL-800 */
+			wacom->extra_z_bits = 2;
+		}
+
+		wacom->flags = F_COVERS_SCREEN;
+		break;
+
+	case MODEL_PENPARTNER:
+		wacom->dev->name = "Wacom Penpartner";
+		wacom->dev->id.version = MODEL_PENPARTNER;
+		wacom->res_x = 1000;
+		wacom->res_y = 1000;
+		break;
+
+	case MODEL_GRAPHIRE:
+		wacom->dev->name = "Wacom Graphire";
+		wacom->dev->id.version = MODEL_GRAPHIRE;
+		wacom->res_x = 1016;
+		wacom->res_y = 1016;
+		wacom->max_x = 5103;
+		wacom->max_y = 3711;
+		wacom->extra_z_bits = 2;
+		wacom->eraser_mask = 0x08;
+		wacom->flags = F_HAS_STYLUS2 | F_HAS_SCROLLWHEEL;
+		break;
+
+	case MODEL_DIGITIZER_II:
+		wacom->dev->name = "Wacom Digitizer II";
+		wacom->dev->id.version = MODEL_DIGITIZER_II;
+		if (major_v == 1 && minor_v <= 2)
+			wacom->extra_z_bits = 0; /* UNTESTED */
+		break;
+
+	default:
+		dev_err(&wacom->dev->dev, "Unsupported Wacom model %s\n",
+			wacom->data);
+		wacom->result = -ENODEV;
+		return;
+	}
+
+	dev_info(&wacom->dev->dev, "%s tablet, version %u.%u\n",
+		 wacom->dev->name, major_v, minor_v);
+}
+
+static void wacom_handle_configuration_response(struct wacom *wacom)
+{
+	int r, skip;
+
+	dev_dbg(&wacom->dev->dev, "Configuration string: %s\n", wacom->data);
+	r = sscanf(wacom->data, "~R%x,%u,%u,%u,%u", &skip, &skip, &skip,
+		   &wacom->res_x, &wacom->res_y);
+	if (r != 5)
+		dev_warn(&wacom->dev->dev, "could not get resolution\n");
+}
+
+static void wacom_handle_coordinates_response(struct wacom *wacom)
+{
+	int r;
+
+	dev_dbg(&wacom->dev->dev, "Coordinates string: %s\n", wacom->data);
+	r = sscanf(wacom->data, "~C%u,%u", &wacom->max_x, &wacom->max_y);
+	if (r != 2)
+		dev_warn(&wacom->dev->dev, "could not get max coordinates\n");
+}
+
+static void wacom_handle_response(struct wacom *wacom)
+{
+	if (wacom->data[0] != '~' || wacom->data[1] != wacom->expect) {
+		dev_err(&wacom->dev->dev,
+			"Wacom got an unexpected response: %s\n", wacom->data);
+		wacom->result = -EIO;
+	} else {
+		wacom->result = 0;
+
+		switch (wacom->data[1]) {
+		case '#':
+			wacom_handle_model_response(wacom);
+			break;
+		case 'R':
+			wacom_handle_configuration_response(wacom);
+			break;
+		case 'C':
+			wacom_handle_coordinates_response(wacom);
+			break;
+		}
+	}
+
+	complete(&wacom->cmd_done);
+}
+
+static void wacom_handle_packet(struct wacom *wacom)
+{
+	u8 in_proximity_p, stylus_p, button;
+	unsigned int tool;
+	int x, y, z;
+
+	in_proximity_p = wacom->data[0] & 0x40;
+	stylus_p = wacom->data[0] & 0x20;
+	button = (wacom->data[3] & 0x78) >> 3;
+	x = (wacom->data[0] & 3) << 14 | wacom->data[1]<<7 | wacom->data[2];
+	y = (wacom->data[3] & 3) << 14 | wacom->data[4]<<7 | wacom->data[5];
+
+	if (in_proximity_p && stylus_p) {
+		z = wacom->data[6] & 0x7f;
+		if (wacom->extra_z_bits >= 1)
+			z = z << 1 | (wacom->data[3] & 0x4) >> 2;
+		if (wacom->extra_z_bits > 1)
+			z = z << 1 | (wacom->data[0] & 0x4) >> 2;
+		z = z ^ (0x40 << wacom->extra_z_bits);
+	} else {
+		z = -1;
+	}
+
+	if (stylus_p)
+		tool = (button & wacom->eraser_mask) ? ERASER : STYLUS;
+	else
+		tool = CURSOR;
+
+	if (tool != wacom->tool && wacom->tool != 0) {
+		input_report_key(wacom->dev, tools[wacom->tool].input_id, 0);
+		input_sync(wacom->dev);
+	}
+	wacom->tool = tool;
+
+	input_report_key(wacom->dev, tools[tool].input_id, in_proximity_p);
+	input_report_abs(wacom->dev, ABS_MISC,
+			 in_proximity_p ? tools[tool].device_id : 0);
+	input_report_abs(wacom->dev, ABS_X, x);
+	input_report_abs(wacom->dev, ABS_Y, y);
+	input_report_abs(wacom->dev, ABS_PRESSURE, z);
+	if (stylus_p) {
+		input_report_key(wacom->dev, BTN_TOUCH, button & 1);
+		input_report_key(wacom->dev, BTN_STYLUS, button & 2);
+		input_report_key(wacom->dev, BTN_STYLUS2, button & 4);
+	} else {
+		input_report_key(wacom->dev, BTN_LEFT, button & 1);
+		input_report_key(wacom->dev, BTN_RIGHT, button & 2);
+		input_report_key(wacom->dev, BTN_MIDDLE, button & 4);
+		/* handle relative wheel for non-stylus device */
+		z = (wacom->data[6] & 0x30) >> 4;
+		if (wacom->data[6] & 0x40)
+			z = -z;
+		input_report_rel(wacom->dev, REL_WHEEL, z);
+	}
+	input_sync(wacom->dev);
+}
+
+static void wacom_clear_data_buf(struct wacom *wacom)
+{
+	memset(wacom->data, 0, DATA_SIZE);
+	wacom->idx = 0;
+}
+
+static irqreturn_t wacom_interrupt(struct serio *serio, unsigned char data,
+				   unsigned int flags)
+{
+	struct wacom *wacom = serio_get_drvdata(serio);
+
+	if (data & 0x80)
+		wacom->idx = 0;
+
+	/*
+	 * We're either expecting a carriage return-terminated ASCII
+	 * response string, or a seven-byte packet with the MSB set on
+	 * the first byte.
+	 *
+	 * Note however that some tablets (the PenPartner, for
+	 * example) don't send a carriage return at the end of a
+	 * command.  We handle these by waiting for timeout.
+	 */
+	if (data == '\r' && !(wacom->data[0] & 0x80)) {
+		wacom_handle_response(wacom);
+		wacom_clear_data_buf(wacom);
+		return IRQ_HANDLED;
+	}
+
+	/* Leave place for 0 termination */
+	if (wacom->idx > (DATA_SIZE - 2)) {
+		dev_dbg(&wacom->dev->dev,
+			"throwing away %d bytes of garbage\n", wacom->idx);
+		wacom_clear_data_buf(wacom);
+	}
+	wacom->data[wacom->idx++] = data;
+
+	if (wacom->idx == PACKET_LENGTH && (wacom->data[0] & 0x80)) {
+		wacom_handle_packet(wacom);
+		wacom_clear_data_buf(wacom);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void wacom_disconnect(struct serio *serio)
+{
+	struct wacom *wacom = serio_get_drvdata(serio);
+
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	input_unregister_device(wacom->dev);
+	kfree(wacom);
+}
+
+static int wacom_send(struct serio *serio, const u8 *command)
+{
+	int err = 0;
+
+	for (; !err && *command; command++)
+		err = serio_write(serio, *command);
+
+	return err;
+}
+
+static int wacom_send_setup_string(struct wacom *wacom, struct serio *serio)
+{
+	const u8 *cmd;
+
+	switch (wacom->dev->id.version) {
+	case MODEL_CINTIQ:	/* UNTESTED */
+		cmd = COMMAND_ORIGIN_IN_UPPER_LEFT
+			COMMAND_TRANSMIT_AT_MAX_RATE
+			COMMAND_ENABLE_CONTINUOUS_MODE
+			COMMAND_START_SENDING_PACKETS;
+		break;
+
+	case MODEL_PENPARTNER:
+		cmd = COMMAND_ENABLE_PRESSURE_MODE
+			COMMAND_START_SENDING_PACKETS;
+		break;
+
+	default:
+		cmd = COMMAND_MULTI_MODE_INPUT
+			COMMAND_ORIGIN_IN_UPPER_LEFT
+			COMMAND_ENABLE_ALL_MACRO_BUTTONS
+			COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS
+			COMMAND_TRANSMIT_AT_MAX_RATE
+			COMMAND_DISABLE_INCREMENTAL_MODE
+			COMMAND_ENABLE_CONTINUOUS_MODE
+			COMMAND_Z_FILTER
+			COMMAND_START_SENDING_PACKETS;
+		break;
+	}
+
+	return wacom_send(serio, cmd);
+}
+
+static int wacom_send_and_wait(struct wacom *wacom, struct serio *serio,
+			       const u8 *cmd, const char *desc)
+{
+	int err;
+	unsigned long u;
+
+	wacom->expect = cmd[1];
+	init_completion(&wacom->cmd_done);
+
+	err = wacom_send(serio, cmd);
+	if (err)
+		return err;
+
+	u = wait_for_completion_timeout(&wacom->cmd_done, HZ);
+	if (u == 0) {
+		/* Timeout, process what we've received. */
+		wacom_handle_response(wacom);
+	}
+
+	wacom->expect = 0;
+	return wacom->result;
+}
+
+static int wacom_setup(struct wacom *wacom, struct serio *serio)
+{
+	int err;
+
+	/* Note that setting the link speed is the job of inputattach.
+	 * We assume that reset negotiation has already happened,
+	 * here. */
+	err = wacom_send_and_wait(wacom, serio, REQUEST_MODEL_AND_ROM_VERSION,
+				  "model and version");
+	if (err)
+		return err;
+
+	if (!(wacom->res_x && wacom->res_y)) {
+		err = wacom_send_and_wait(wacom, serio,
+					  REQUEST_CONFIGURATION_STRING,
+					  "configuration string");
+		if (err)
+			return err;
+	}
+
+	if (!(wacom->max_x && wacom->max_y)) {
+		err = wacom_send_and_wait(wacom, serio,
+					  REQUEST_MAX_COORDINATES,
+					  "coordinates string");
+		if (err)
+			return err;
+	}
+
+	return wacom_send_setup_string(wacom, serio);
+}
+
+static int wacom_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct wacom *wacom;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
+
+	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!wacom || !input_dev)
+		goto free_device;
+
+	wacom->dev = input_dev;
+	wacom->extra_z_bits = 1;
+	wacom->eraser_mask = 0x04;
+	wacom->tool = wacom->idx = 0;
+	snprintf(wacom->phys, sizeof(wacom->phys), "%s/input0", serio->phys);
+	input_dev->phys = wacom->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor  = SERIO_WACOM_IV;
+	input_dev->id.product = serio->id.extra;
+	input_dev->dev.parent = &serio->dev;
+
+	input_dev->evbit[0] =
+		BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_REL);
+	set_bit(ABS_MISC, input_dev->absbit);
+	set_bit(BTN_TOOL_PEN, input_dev->keybit);
+	set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+	set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+	set_bit(BTN_TOUCH, input_dev->keybit);
+	set_bit(BTN_STYLUS, input_dev->keybit);
+	set_bit(BTN_LEFT, input_dev->keybit);
+	set_bit(BTN_RIGHT, input_dev->keybit);
+	set_bit(BTN_MIDDLE, input_dev->keybit);
+
+	serio_set_drvdata(serio, wacom);
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto free_device;
+
+	err = wacom_setup(wacom, serio);
+	if (err)
+		goto close_serio;
+
+	set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+	if (!(wacom->flags & F_COVERS_SCREEN))
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+	if (wacom->flags & F_HAS_STYLUS2)
+		__set_bit(BTN_STYLUS2, input_dev->keybit);
+
+	if (wacom->flags & F_HAS_SCROLLWHEEL)
+		__set_bit(REL_WHEEL, input_dev->relbit);
+
+	input_abs_set_res(wacom->dev, ABS_X, wacom->res_x);
+	input_abs_set_res(wacom->dev, ABS_Y, wacom->res_y);
+	input_set_abs_params(wacom->dev, ABS_X, 0, wacom->max_x, 0, 0);
+	input_set_abs_params(wacom->dev, ABS_Y, 0, wacom->max_y, 0, 0);
+	input_set_abs_params(wacom->dev, ABS_PRESSURE, -1,
+			     (1 << (7 + wacom->extra_z_bits)) - 1, 0, 0);
+
+	err = input_register_device(wacom->dev);
+	if (err)
+		goto close_serio;
+
+	return 0;
+
+close_serio:
+	serio_close(serio);
+free_device:
+	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(wacom);
+	return err;
+}
+
+static struct serio_device_id wacom_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_WACOM_IV,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, wacom_serio_ids);
+
+static struct serio_driver wacom_drv = {
+	.driver		= {
+		.name	= "wacom_serial4",
+	},
+	.description	= "Wacom protocol 4 serial tablet driver",
+	.id_table	= wacom_serio_ids,
+	.interrupt	= wacom_interrupt,
+	.connect	= wacom_connect,
+	.disconnect	= wacom_disconnect,
+};
+
+module_serio_driver(wacom_drv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/wacom_sys.c linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_sys.c
--- linux-libre-3.16-gnu/drivers/input/tablet/wacom_sys.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_sys.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1497 +0,0 @@
-/*
- * drivers/input/tablet/wacom_sys.c
- *
- *  USB Wacom tablet support - system specific code
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 "wacom_wac.h"
-#include "wacom.h"
-
-/* defines to get HID report descriptor */
-#define HID_DEVICET_HID		(USB_TYPE_CLASS | 0x01)
-#define HID_DEVICET_REPORT	(USB_TYPE_CLASS | 0x02)
-#define HID_USAGE_UNDEFINED		0x00
-#define HID_USAGE_PAGE			0x05
-#define HID_USAGE_PAGE_DIGITIZER	0x0d
-#define HID_USAGE_PAGE_DESKTOP		0x01
-#define HID_USAGE			0x09
-#define HID_USAGE_X			((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
-#define HID_USAGE_Y			((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
-#define HID_USAGE_PRESSURE		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
-#define HID_USAGE_X_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
-#define HID_USAGE_Y_TILT		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
-#define HID_USAGE_FINGER		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
-#define HID_USAGE_STYLUS		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
-#define HID_USAGE_CONTACTMAX		((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
-#define HID_COLLECTION			0xa1
-#define HID_COLLECTION_LOGICAL		0x02
-#define HID_COLLECTION_END		0xc0
-
-struct hid_descriptor {
-	struct usb_descriptor_header header;
-	__le16   bcdHID;
-	u8       bCountryCode;
-	u8       bNumDescriptors;
-	u8       bDescriptorType;
-	__le16   wDescriptorLength;
-} __attribute__ ((packed));
-
-/* defines to get/set USB message */
-#define USB_REQ_GET_REPORT	0x01
-#define USB_REQ_SET_REPORT	0x09
-
-#define WAC_HID_FEATURE_REPORT	0x03
-#define WAC_MSG_RETRIES		5
-
-#define WAC_CMD_LED_CONTROL	0x20
-#define WAC_CMD_ICON_START	0x21
-#define WAC_CMD_ICON_XFER	0x23
-#define WAC_CMD_RETRIES		10
-
-static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
-			    void *buf, size_t size, unsigned int retries)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	int retval;
-
-	do {
-		retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				USB_REQ_GET_REPORT,
-				USB_DIR_IN | USB_TYPE_CLASS |
-				USB_RECIP_INTERFACE,
-				(type << 8) + id,
-				intf->altsetting[0].desc.bInterfaceNumber,
-				buf, size, 100);
-	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
-
-	return retval;
-}
-
-static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
-			    void *buf, size_t size, unsigned int retries)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	int retval;
-
-	do {
-		retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				USB_REQ_SET_REPORT,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				(type << 8) + id,
-				intf->altsetting[0].desc.bInterfaceNumber,
-				buf, size, 1000);
-	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
-
-	return retval;
-}
-
-static void wacom_sys_irq(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	struct device *dev = &wacom->intf->dev;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dev_dbg(dev, "%s - urb shutting down with status: %d\n",
-			__func__, urb->status);
-		return;
-	default:
-		dev_dbg(dev, "%s - nonzero urb status received: %d\n",
-			__func__, urb->status);
-		goto exit;
-	}
-
-	wacom_wac_irq(&wacom->wacom_wac, urb->actual_length);
-
- exit:
-	usb_mark_last_busy(wacom->usbdev);
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
-			__func__, retval);
-}
-
-static int wacom_open(struct input_dev *dev)
-{
-	struct wacom *wacom = input_get_drvdata(dev);
-	int retval = 0;
-
-	if (usb_autopm_get_interface(wacom->intf) < 0)
-		return -EIO;
-
-	mutex_lock(&wacom->lock);
-
-	if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
-		retval = -EIO;
-		goto out;
-	}
-
-	wacom->open = true;
-	wacom->intf->needs_remote_wakeup = 1;
-
-out:
-	mutex_unlock(&wacom->lock);
-	usb_autopm_put_interface(wacom->intf);
-	return retval;
-}
-
-static void wacom_close(struct input_dev *dev)
-{
-	struct wacom *wacom = input_get_drvdata(dev);
-	int autopm_error;
-
-	autopm_error = usb_autopm_get_interface(wacom->intf);
-
-	mutex_lock(&wacom->lock);
-	usb_kill_urb(wacom->irq);
-	wacom->open = false;
-	wacom->intf->needs_remote_wakeup = 0;
-	mutex_unlock(&wacom->lock);
-
-	if (!autopm_error)
-		usb_autopm_put_interface(wacom->intf);
-}
-
-/*
- * Calculate the resolution of the X or Y axis, given appropriate HID data.
- * This function is little more than hidinput_calc_abs_res stripped down.
- */
-static int wacom_calc_hid_res(int logical_extents, int physical_extents,
-                              unsigned char unit, unsigned char exponent)
-{
-	int prev, unit_exponent;
-
-	/* Check if the extents are sane */
-	if (logical_extents <= 0 || physical_extents <= 0)
-		return 0;
-
-	/* Get signed value of nybble-sized twos-compliment exponent */
-	unit_exponent = exponent;
-	if (unit_exponent > 7)
-		unit_exponent -= 16;
-
-	/* Convert physical_extents to millimeters */
-	if (unit == 0x11) {		/* If centimeters */
-		unit_exponent += 1;
-	} else if (unit == 0x13) {	/* If inches */
-		prev = physical_extents;
-		physical_extents *= 254;
-		if (physical_extents < prev)
-			return 0;
-		unit_exponent -= 1;
-	} else {
-		return 0;
-	}
-
-	/* Apply negative unit exponent */
-	for (; unit_exponent < 0; unit_exponent++) {
-		prev = logical_extents;
-		logical_extents *= 10;
-		if (logical_extents < prev)
-			return 0;
-	}
-	/* Apply positive unit exponent */
-	for (; unit_exponent > 0; unit_exponent--) {
-		prev = physical_extents;
-		physical_extents *= 10;
-		if (physical_extents < prev)
-			return 0;
-	}
-
-	/* Calculate resolution */
-	return logical_extents / physical_extents;
-}
-
-static int wacom_parse_logical_collection(unsigned char *report,
-					  struct wacom_features *features)
-{
-	int length = 0;
-
-	if (features->type == BAMBOO_PT) {
-
-		/* Logical collection is only used by 3rd gen Bamboo Touch */
-		features->pktlen = WACOM_PKGLEN_BBTOUCH3;
-		features->device_type = BTN_TOOL_FINGER;
-
-		features->x_max = features->y_max =
-			get_unaligned_le16(&report[10]);
-
-		length = 11;
-	}
-	return length;
-}
-
-static void wacom_retrieve_report_data(struct usb_interface *intf,
-				       struct wacom_features *features)
-{
-	int result = 0;
-	unsigned char *rep_data;
-
-	rep_data = kmalloc(2, GFP_KERNEL);
-	if (rep_data) {
-
-		rep_data[0] = 12;
-		result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
-					  rep_data[0], rep_data, 2,
-					  WAC_MSG_RETRIES);
-
-		if (result >= 0 && rep_data[1] > 2)
-			features->touch_max = rep_data[1];
-
-		kfree(rep_data);
-	}
-}
-
-/*
- * Interface Descriptor of wacom devices can be incomplete and
- * inconsistent so wacom_features table is used to store stylus
- * device's packet lengths, various maximum values, and tablet
- * resolution based on product ID's.
- *
- * For devices that contain 2 interfaces, wacom_features table is
- * inaccurate for the touch interface.  Since the Interface Descriptor
- * for touch interfaces has pretty complete data, this function exists
- * to query tablet for this missing information instead of hard coding in
- * an additional table.
- *
- * A typical Interface Descriptor for a stylus will contain a
- * boot mouse application collection that is not of interest and this
- * function will ignore it.
- *
- * It also contains a digitizer application collection that also is not
- * of interest since any information it contains would be duplicate
- * of what is in wacom_features. Usually it defines a report of an array
- * of bytes that could be used as max length of the stylus packet returned.
- * If it happens to define a Digitizer-Stylus Physical Collection then
- * the X and Y logical values contain valid data but it is ignored.
- *
- * A typical Interface Descriptor for a touch interface will contain a
- * Digitizer-Finger Physical Collection which will define both logical
- * X/Y maximum as well as the physical size of tablet. Since touch
- * interfaces haven't supported pressure or distance, this is enough
- * information to override invalid values in the wacom_features table.
- *
- * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
- * Collection. Instead they define a Logical Collection with a single
- * Logical Maximum for both X and Y.
- *
- * Intuos5 touch interface does not contain useful data. We deal with
- * this after returning from this function.
- */
-static int wacom_parse_hid(struct usb_interface *intf,
-			   struct hid_descriptor *hid_desc,
-			   struct wacom_features *features)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	char limit = 0;
-	/* result has to be defined as int for some devices */
-	int result = 0, touch_max = 0;
-	int i = 0, page = 0, finger = 0, pen = 0;
-	unsigned char *report;
-
-	report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
-	if (!report)
-		return -ENOMEM;
-
-	/* retrive report descriptors */
-	do {
-		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			USB_REQ_GET_DESCRIPTOR,
-			USB_RECIP_INTERFACE | USB_DIR_IN,
-			HID_DEVICET_REPORT << 8,
-			intf->altsetting[0].desc.bInterfaceNumber, /* interface */
-			report,
-			hid_desc->wDescriptorLength,
-			5000); /* 5 secs */
-	} while (result < 0 && limit++ < WAC_MSG_RETRIES);
-
-	/* No need to parse the Descriptor. It isn't an error though */
-	if (result < 0)
-		goto out;
-
-	for (i = 0; i < hid_desc->wDescriptorLength; i++) {
-
-		switch (report[i]) {
-		case HID_USAGE_PAGE:
-			page = report[i + 1];
-			i++;
-			break;
-
-		case HID_USAGE:
-			switch (page << 16 | report[i + 1]) {
-			case HID_USAGE_X:
-				if (finger) {
-					features->device_type = BTN_TOOL_FINGER;
-					/* touch device at least supports one touch point */
-					touch_max = 1;
-					switch (features->type) {
-					case TABLETPC2FG:
-						features->pktlen = WACOM_PKGLEN_TPC2FG;
-						break;
-
-					case MTSCREEN:
-					case WACOM_24HDT:
-						features->pktlen = WACOM_PKGLEN_MTOUCH;
-						break;
-
-					case MTTPC:
-					case MTTPC_B:
-						features->pktlen = WACOM_PKGLEN_MTTPC;
-						break;
-
-					case BAMBOO_PT:
-						features->pktlen = WACOM_PKGLEN_BBTOUCH;
-						break;
-
-					default:
-						features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-						break;
-					}
-
-					switch (features->type) {
-					case BAMBOO_PT:
-						features->x_phy =
-							get_unaligned_le16(&report[i + 5]);
-						features->x_max =
-							get_unaligned_le16(&report[i + 8]);
-						i += 15;
-						break;
-
-					case WACOM_24HDT:
-						features->x_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->x_phy =
-							get_unaligned_le16(&report[i + 8]);
-						features->unit = report[i - 1];
-						features->unitExpo = report[i - 3];
-						i += 12;
-						break;
-
-					case MTTPC_B:
-						features->x_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->x_phy =
-							get_unaligned_le16(&report[i + 6]);
-						features->unit = report[i - 5];
-						features->unitExpo = report[i - 3];
-						i += 9;
-						break;
-
-					default:
-						features->x_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->x_phy =
-							get_unaligned_le16(&report[i + 6]);
-						features->unit = report[i + 9];
-						features->unitExpo = report[i + 11];
-						i += 12;
-						break;
-					}
-				} else if (pen) {
-					/* penabled only accepts exact bytes of data */
-					if (features->type >= TABLETPC)
-						features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-					features->device_type = BTN_TOOL_PEN;
-					features->x_max =
-						get_unaligned_le16(&report[i + 3]);
-					i += 4;
-				}
-				break;
-
-			case HID_USAGE_Y:
-				if (finger) {
-					switch (features->type) {
-					case TABLETPC2FG:
-					case MTSCREEN:
-					case MTTPC:
-						features->y_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->y_phy =
-							get_unaligned_le16(&report[i + 6]);
-						i += 7;
-						break;
-
-					case WACOM_24HDT:
-						features->y_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->y_phy =
-							get_unaligned_le16(&report[i - 2]);
-						i += 7;
-						break;
-
-					case BAMBOO_PT:
-						features->y_phy =
-							get_unaligned_le16(&report[i + 3]);
-						features->y_max =
-							get_unaligned_le16(&report[i + 6]);
-						i += 12;
-						break;
-
-					case MTTPC_B:
-						features->y_max =
-							get_unaligned_le16(&report[i + 3]);
-						features->y_phy =
-							get_unaligned_le16(&report[i + 6]);
-						i += 9;
-						break;
-
-					default:
-						features->y_max =
-							features->x_max;
-						features->y_phy =
-							get_unaligned_le16(&report[i + 3]);
-						i += 4;
-						break;
-					}
-				} else if (pen) {
-					features->y_max =
-						get_unaligned_le16(&report[i + 3]);
-					i += 4;
-				}
-				break;
-
-			case HID_USAGE_FINGER:
-				finger = 1;
-				i++;
-				break;
-
-			/*
-			 * Requiring Stylus Usage will ignore boot mouse
-			 * X/Y values and some cases of invalid Digitizer X/Y
-			 * values commonly reported.
-			 */
-			case HID_USAGE_STYLUS:
-				pen = 1;
-				i++;
-				break;
-
-			case HID_USAGE_CONTACTMAX:
-				/* leave touch_max as is if predefined */
-				if (!features->touch_max)
-					wacom_retrieve_report_data(intf, features);
-				i++;
-				break;
-
-			case HID_USAGE_PRESSURE:
-				if (pen) {
-					features->pressure_max =
-						get_unaligned_le16(&report[i + 3]);
-					i += 4;
-				}
-				break;
-			}
-			break;
-
-		case HID_COLLECTION_END:
-			/* reset UsagePage and Finger */
-			finger = page = 0;
-			break;
-
-		case HID_COLLECTION:
-			i++;
-			switch (report[i]) {
-			case HID_COLLECTION_LOGICAL:
-				i += wacom_parse_logical_collection(&report[i],
-								    features);
-				break;
-			}
-			break;
-		}
-	}
-
- out:
-	if (!features->touch_max && touch_max)
-		features->touch_max = touch_max;
-	result = 0;
-	kfree(report);
-	return result;
-}
-
-static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
-{
-	unsigned char *rep_data;
-	int error = -ENOMEM, limit = 0;
-
-	rep_data = kzalloc(length, GFP_KERNEL);
-	if (!rep_data)
-		return error;
-
-	do {
-		rep_data[0] = report_id;
-		rep_data[1] = mode;
-
-		error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
-		                         report_id, rep_data, length, 1);
-	} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
-
-	kfree(rep_data);
-
-	return error < 0 ? error : 0;
-}
-
-/*
- * Switch the tablet into its most-capable mode. Wacom tablets are
- * typically configured to power-up in a mode which sends mouse-like
- * reports to the OS. To get absolute position, pressure data, etc.
- * from the tablet, it is necessary to switch the tablet out of this
- * mode and into one which sends the full range of tablet data.
- */
-static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
-{
-	if (features->device_type == BTN_TOOL_FINGER) {
-		if (features->type > TABLETPC) {
-			/* MT Tablet PC touch */
-			return wacom_set_device_mode(intf, 3, 4, 4);
-		}
-		else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
-			return wacom_set_device_mode(intf, 18, 3, 2);
-		}
-	} else if (features->device_type == BTN_TOOL_PEN) {
-		if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
-			return wacom_set_device_mode(intf, 2, 2, 2);
-		}
-	}
-
-	return 0;
-}
-
-static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
-					 struct wacom_features *features)
-{
-	int error = 0;
-	struct usb_host_interface *interface = intf->cur_altsetting;
-	struct hid_descriptor *hid_desc;
-
-	/* default features */
-	features->device_type = BTN_TOOL_PEN;
-	features->x_fuzz = 4;
-	features->y_fuzz = 4;
-	features->pressure_fuzz = 0;
-	features->distance_fuzz = 0;
-
-	/*
-	 * The wireless device HID is basic and layout conflicts with
-	 * other tablets (monitor and touch interface can look like pen).
-	 * Skip the query for this type and modify defaults based on
-	 * interface number.
-	 */
-	if (features->type == WIRELESS) {
-		if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
-			features->device_type = 0;
-		} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
-			features->device_type = BTN_TOOL_FINGER;
-			features->pktlen = WACOM_PKGLEN_BBTOUCH3;
-		}
-	}
-
-	/* only devices that support touch need to retrieve the info */
-	if (features->type < BAMBOO_PT) {
-		goto out;
-	}
-
-	error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
-	if (error) {
-		error = usb_get_extra_descriptor(&interface->endpoint[0],
-						 HID_DEVICET_REPORT, &hid_desc);
-		if (error) {
-			dev_err(&intf->dev,
-				"can not retrieve extra class descriptor\n");
-			goto out;
-		}
-	}
-	error = wacom_parse_hid(intf, hid_desc, features);
-
- out:
-	return error;
-}
-
-struct wacom_usbdev_data {
-	struct list_head list;
-	struct kref kref;
-	struct usb_device *dev;
-	struct wacom_shared shared;
-};
-
-static LIST_HEAD(wacom_udev_list);
-static DEFINE_MUTEX(wacom_udev_list_lock);
-
-static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
-{
-	int port1;
-	struct usb_device *sibling;
-
-	if (vendor == 0 && product == 0)
-		return dev;
-
-	if (dev->parent == NULL)
-		return NULL;
-
-	usb_hub_for_each_child(dev->parent, port1, sibling) {
-		struct usb_device_descriptor *d;
-		if (sibling == NULL)
-			continue;
-
-		d = &sibling->descriptor;
-		if (d->idVendor == vendor && d->idProduct == product)
-			return sibling;
-	}
-
-	return NULL;
-}
-
-static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
-{
-	struct wacom_usbdev_data *data;
-
-	list_for_each_entry(data, &wacom_udev_list, list) {
-		if (data->dev == dev) {
-			kref_get(&data->kref);
-			return data;
-		}
-	}
-
-	return NULL;
-}
-
-static int wacom_add_shared_data(struct wacom_wac *wacom,
-				 struct usb_device *dev)
-{
-	struct wacom_usbdev_data *data;
-	int retval = 0;
-
-	mutex_lock(&wacom_udev_list_lock);
-
-	data = wacom_get_usbdev_data(dev);
-	if (!data) {
-		data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL);
-		if (!data) {
-			retval = -ENOMEM;
-			goto out;
-		}
-
-		kref_init(&data->kref);
-		data->dev = dev;
-		list_add_tail(&data->list, &wacom_udev_list);
-	}
-
-	wacom->shared = &data->shared;
-
-out:
-	mutex_unlock(&wacom_udev_list_lock);
-	return retval;
-}
-
-static void wacom_release_shared_data(struct kref *kref)
-{
-	struct wacom_usbdev_data *data =
-		container_of(kref, struct wacom_usbdev_data, kref);
-
-	mutex_lock(&wacom_udev_list_lock);
-	list_del(&data->list);
-	mutex_unlock(&wacom_udev_list_lock);
-
-	kfree(data);
-}
-
-static void wacom_remove_shared_data(struct wacom_wac *wacom)
-{
-	struct wacom_usbdev_data *data;
-
-	if (wacom->shared) {
-		data = container_of(wacom->shared, struct wacom_usbdev_data, shared);
-		kref_put(&data->kref, wacom_release_shared_data);
-		wacom->shared = NULL;
-	}
-}
-
-static int wacom_led_control(struct wacom *wacom)
-{
-	unsigned char *buf;
-	int retval;
-
-	buf = kzalloc(9, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (wacom->wacom_wac.features.type >= INTUOS5S &&
-	    wacom->wacom_wac.features.type <= INTUOSPL) {
-		/*
-		 * Touch Ring and crop mark LED luminance may take on
-		 * one of four values:
-		 *    0 = Low; 1 = Medium; 2 = High; 3 = Off
-		 */
-		int ring_led = wacom->led.select[0] & 0x03;
-		int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03;
-		int crop_lum = 0;
-
-		buf[0] = WAC_CMD_LED_CONTROL;
-		buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
-	}
-	else {
-		int led = wacom->led.select[0] | 0x4;
-
-		if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
-		    wacom->wacom_wac.features.type == WACOM_24HD)
-			led |= (wacom->led.select[1] << 4) | 0x40;
-
-		buf[0] = WAC_CMD_LED_CONTROL;
-		buf[1] = led;
-		buf[2] = wacom->led.llv;
-		buf[3] = wacom->led.hlv;
-		buf[4] = wacom->led.img_lum;
-	}
-
-	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
-				  buf, 9, WAC_CMD_RETRIES);
-	kfree(buf);
-
-	return retval;
-}
-
-static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
-{
-	unsigned char *buf;
-	int i, retval;
-
-	buf = kzalloc(259, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	/* Send 'start' command */
-	buf[0] = WAC_CMD_ICON_START;
-	buf[1] = 1;
-	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
-				  buf, 2, WAC_CMD_RETRIES);
-	if (retval < 0)
-		goto out;
-
-	buf[0] = WAC_CMD_ICON_XFER;
-	buf[1] = button_id & 0x07;
-	for (i = 0; i < 4; i++) {
-		buf[2] = i;
-		memcpy(buf + 3, img + i * 256, 256);
-
-		retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
-					  buf, 259, WAC_CMD_RETRIES);
-		if (retval < 0)
-			break;
-	}
-
-	/* Send 'stop' */
-	buf[0] = WAC_CMD_ICON_START;
-	buf[1] = 0;
-	wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
-			 buf, 2, WAC_CMD_RETRIES);
-
-out:
-	kfree(buf);
-	return retval;
-}
-
-static ssize_t wacom_led_select_store(struct device *dev, int set_id,
-				      const char *buf, size_t count)
-{
-	struct wacom *wacom = dev_get_drvdata(dev);
-	unsigned int id;
-	int err;
-
-	err = kstrtouint(buf, 10, &id);
-	if (err)
-		return err;
-
-	mutex_lock(&wacom->lock);
-
-	wacom->led.select[set_id] = id & 0x3;
-	err = wacom_led_control(wacom);
-
-	mutex_unlock(&wacom->lock);
-
-	return err < 0 ? err : count;
-}
-
-#define DEVICE_LED_SELECT_ATTR(SET_ID)					\
-static ssize_t wacom_led##SET_ID##_select_store(struct device *dev,	\
-	struct device_attribute *attr, const char *buf, size_t count)	\
-{									\
-	return wacom_led_select_store(dev, SET_ID, buf, count);		\
-}									\
-static ssize_t wacom_led##SET_ID##_select_show(struct device *dev,	\
-	struct device_attribute *attr, char *buf)			\
-{									\
-	struct wacom *wacom = dev_get_drvdata(dev);			\
-	return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);	\
-}									\
-static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR,	\
-		    wacom_led##SET_ID##_select_show,			\
-		    wacom_led##SET_ID##_select_store)
-
-DEVICE_LED_SELECT_ATTR(0);
-DEVICE_LED_SELECT_ATTR(1);
-
-static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
-				     const char *buf, size_t count)
-{
-	unsigned int value;
-	int err;
-
-	err = kstrtouint(buf, 10, &value);
-	if (err)
-		return err;
-
-	mutex_lock(&wacom->lock);
-
-	*dest = value & 0x7f;
-	err = wacom_led_control(wacom);
-
-	mutex_unlock(&wacom->lock);
-
-	return err < 0 ? err : count;
-}
-
-#define DEVICE_LUMINANCE_ATTR(name, field)				\
-static ssize_t wacom_##name##_luminance_store(struct device *dev,	\
-	struct device_attribute *attr, const char *buf, size_t count)	\
-{									\
-	struct wacom *wacom = dev_get_drvdata(dev);			\
-									\
-	return wacom_luminance_store(wacom, &wacom->led.field,		\
-				     buf, count);			\
-}									\
-static DEVICE_ATTR(name##_luminance, S_IWUSR,				\
-		   NULL, wacom_##name##_luminance_store)
-
-DEVICE_LUMINANCE_ATTR(status0, llv);
-DEVICE_LUMINANCE_ATTR(status1, hlv);
-DEVICE_LUMINANCE_ATTR(buttons, img_lum);
-
-static ssize_t wacom_button_image_store(struct device *dev, int button_id,
-					const char *buf, size_t count)
-{
-	struct wacom *wacom = dev_get_drvdata(dev);
-	int err;
-
-	if (count != 1024)
-		return -EINVAL;
-
-	mutex_lock(&wacom->lock);
-
-	err = wacom_led_putimage(wacom, button_id, buf);
-
-	mutex_unlock(&wacom->lock);
-
-	return err < 0 ? err : count;
-}
-
-#define DEVICE_BTNIMG_ATTR(BUTTON_ID)					\
-static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev,	\
-	struct device_attribute *attr, const char *buf, size_t count)	\
-{									\
-	return wacom_button_image_store(dev, BUTTON_ID, buf, count);	\
-}									\
-static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR,			\
-		   NULL, wacom_btnimg##BUTTON_ID##_store)
-
-DEVICE_BTNIMG_ATTR(0);
-DEVICE_BTNIMG_ATTR(1);
-DEVICE_BTNIMG_ATTR(2);
-DEVICE_BTNIMG_ATTR(3);
-DEVICE_BTNIMG_ATTR(4);
-DEVICE_BTNIMG_ATTR(5);
-DEVICE_BTNIMG_ATTR(6);
-DEVICE_BTNIMG_ATTR(7);
-
-static struct attribute *cintiq_led_attrs[] = {
-	&dev_attr_status_led0_select.attr,
-	&dev_attr_status_led1_select.attr,
-	NULL
-};
-
-static struct attribute_group cintiq_led_attr_group = {
-	.name = "wacom_led",
-	.attrs = cintiq_led_attrs,
-};
-
-static struct attribute *intuos4_led_attrs[] = {
-	&dev_attr_status0_luminance.attr,
-	&dev_attr_status1_luminance.attr,
-	&dev_attr_status_led0_select.attr,
-	&dev_attr_buttons_luminance.attr,
-	&dev_attr_button0_rawimg.attr,
-	&dev_attr_button1_rawimg.attr,
-	&dev_attr_button2_rawimg.attr,
-	&dev_attr_button3_rawimg.attr,
-	&dev_attr_button4_rawimg.attr,
-	&dev_attr_button5_rawimg.attr,
-	&dev_attr_button6_rawimg.attr,
-	&dev_attr_button7_rawimg.attr,
-	NULL
-};
-
-static struct attribute_group intuos4_led_attr_group = {
-	.name = "wacom_led",
-	.attrs = intuos4_led_attrs,
-};
-
-static struct attribute *intuos5_led_attrs[] = {
-	&dev_attr_status0_luminance.attr,
-	&dev_attr_status_led0_select.attr,
-	NULL
-};
-
-static struct attribute_group intuos5_led_attr_group = {
-	.name = "wacom_led",
-	.attrs = intuos5_led_attrs,
-};
-
-static int wacom_initialize_leds(struct wacom *wacom)
-{
-	int error;
-
-	/* Initialize default values */
-	switch (wacom->wacom_wac.features.type) {
-	case INTUOS4S:
-	case INTUOS4:
-	case INTUOS4L:
-		wacom->led.select[0] = 0;
-		wacom->led.select[1] = 0;
-		wacom->led.llv = 10;
-		wacom->led.hlv = 20;
-		wacom->led.img_lum = 10;
-		error = sysfs_create_group(&wacom->intf->dev.kobj,
-					   &intuos4_led_attr_group);
-		break;
-
-	case WACOM_24HD:
-	case WACOM_21UX2:
-		wacom->led.select[0] = 0;
-		wacom->led.select[1] = 0;
-		wacom->led.llv = 0;
-		wacom->led.hlv = 0;
-		wacom->led.img_lum = 0;
-
-		error = sysfs_create_group(&wacom->intf->dev.kobj,
-					   &cintiq_led_attr_group);
-		break;
-
-	case INTUOS5S:
-	case INTUOS5:
-	case INTUOS5L:
-	case INTUOSPS:
-	case INTUOSPM:
-	case INTUOSPL:
-		if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) {
-			wacom->led.select[0] = 0;
-			wacom->led.select[1] = 0;
-			wacom->led.llv = 32;
-			wacom->led.hlv = 0;
-			wacom->led.img_lum = 0;
-
-			error = sysfs_create_group(&wacom->intf->dev.kobj,
-						  &intuos5_led_attr_group);
-		} else
-			return 0;
-		break;
-
-	default:
-		return 0;
-	}
-
-	if (error) {
-		dev_err(&wacom->intf->dev,
-			"cannot create sysfs group err: %d\n", error);
-		return error;
-	}
-	wacom_led_control(wacom);
-
-	return 0;
-}
-
-static void wacom_destroy_leds(struct wacom *wacom)
-{
-	switch (wacom->wacom_wac.features.type) {
-	case INTUOS4S:
-	case INTUOS4:
-	case INTUOS4L:
-		sysfs_remove_group(&wacom->intf->dev.kobj,
-				   &intuos4_led_attr_group);
-		break;
-
-	case WACOM_24HD:
-	case WACOM_21UX2:
-		sysfs_remove_group(&wacom->intf->dev.kobj,
-				   &cintiq_led_attr_group);
-		break;
-
-	case INTUOS5S:
-	case INTUOS5:
-	case INTUOS5L:
-	case INTUOSPS:
-	case INTUOSPM:
-	case INTUOSPL:
-		if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN)
-			sysfs_remove_group(&wacom->intf->dev.kobj,
-					   &intuos5_led_attr_group);
-		break;
-	}
-}
-
-static enum power_supply_property wacom_battery_props[] = {
-	POWER_SUPPLY_PROP_SCOPE,
-	POWER_SUPPLY_PROP_CAPACITY
-};
-
-static int wacom_battery_get_property(struct power_supply *psy,
-				      enum power_supply_property psp,
-				      union power_supply_propval *val)
-{
-	struct wacom *wacom = container_of(psy, struct wacom, battery);
-	int ret = 0;
-
-	switch (psp) {
-		case POWER_SUPPLY_PROP_SCOPE:
-			val->intval = POWER_SUPPLY_SCOPE_DEVICE;
-			break;
-		case POWER_SUPPLY_PROP_CAPACITY:
-			val->intval =
-				wacom->wacom_wac.battery_capacity * 100 / 31;
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-	}
-
-	return ret;
-}
-
-static int wacom_initialize_battery(struct wacom *wacom)
-{
-	int error = 0;
-
-	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
-		wacom->battery.properties = wacom_battery_props;
-		wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
-		wacom->battery.get_property = wacom_battery_get_property;
-		wacom->battery.name = "wacom_battery";
-		wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-		wacom->battery.use_for_apm = 0;
-
-		error = power_supply_register(&wacom->usbdev->dev,
-					      &wacom->battery);
-
-		if (!error)
-			power_supply_powers(&wacom->battery,
-					    &wacom->usbdev->dev);
-	}
-
-	return error;
-}
-
-static void wacom_destroy_battery(struct wacom *wacom)
-{
-	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR &&
-	    wacom->battery.dev) {
-		power_supply_unregister(&wacom->battery);
-		wacom->battery.dev = NULL;
-	}
-}
-
-static int wacom_register_input(struct wacom *wacom)
-{
-	struct input_dev *input_dev;
-	struct usb_interface *intf = wacom->intf;
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
-	int error;
-
-	input_dev = input_allocate_device();
-	if (!input_dev) {
-		error = -ENOMEM;
-		goto fail1;
-	}
-
-	input_dev->name = wacom_wac->name;
-	input_dev->dev.parent = &intf->dev;
-	input_dev->open = wacom_open;
-	input_dev->close = wacom_close;
-	usb_to_input_id(dev, &input_dev->id);
-	input_set_drvdata(input_dev, wacom);
-
-	wacom_wac->input = input_dev;
-	error = wacom_setup_input_capabilities(input_dev, wacom_wac);
-	if (error)
-		goto fail1;
-
-	error = input_register_device(input_dev);
-	if (error)
-		goto fail2;
-
-	return 0;
-
-fail2:
-	input_free_device(input_dev);
-	wacom_wac->input = NULL;
-fail1:
-	return error;
-}
-
-static void wacom_wireless_work(struct work_struct *work)
-{
-	struct wacom *wacom = container_of(work, struct wacom, work);
-	struct usb_device *usbdev = wacom->usbdev;
-	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-	struct wacom *wacom1, *wacom2;
-	struct wacom_wac *wacom_wac1, *wacom_wac2;
-	int error;
-
-	/*
-	 * Regardless if this is a disconnect or a new tablet,
-	 * remove any existing input and battery devices.
-	 */
-
-	wacom_destroy_battery(wacom);
-
-	/* Stylus interface */
-	wacom1 = usb_get_intfdata(usbdev->config->interface[1]);
-	wacom_wac1 = &(wacom1->wacom_wac);
-	if (wacom_wac1->input)
-		input_unregister_device(wacom_wac1->input);
-	wacom_wac1->input = NULL;
-
-	/* Touch interface */
-	wacom2 = usb_get_intfdata(usbdev->config->interface[2]);
-	wacom_wac2 = &(wacom2->wacom_wac);
-	if (wacom_wac2->input)
-		input_unregister_device(wacom_wac2->input);
-	wacom_wac2->input = NULL;
-
-	if (wacom_wac->pid == 0) {
-		dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
-	} else {
-		const struct usb_device_id *id = wacom_ids;
-
-		dev_info(&wacom->intf->dev,
-			 "wireless tablet connected with PID %x\n",
-			 wacom_wac->pid);
-
-		while (id->match_flags) {
-			if (id->idVendor == USB_VENDOR_ID_WACOM &&
-			    id->idProduct == wacom_wac->pid)
-				break;
-			id++;
-		}
-
-		if (!id->match_flags) {
-			dev_info(&wacom->intf->dev,
-				 "ignoring unknown PID.\n");
-			return;
-		}
-
-		/* Stylus interface */
-		wacom_wac1->features =
-			*((struct wacom_features *)id->driver_info);
-		wacom_wac1->features.device_type = BTN_TOOL_PEN;
-		snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
-			 wacom_wac1->features.name);
-		wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
-		wacom_wac1->shared->type = wacom_wac1->features.type;
-		error = wacom_register_input(wacom1);
-		if (error)
-			goto fail;
-
-		/* Touch interface */
-		if (wacom_wac1->features.touch_max ||
-		    wacom_wac1->features.type == INTUOSHT) {
-			wacom_wac2->features =
-				*((struct wacom_features *)id->driver_info);
-			wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
-			wacom_wac2->features.device_type = BTN_TOOL_FINGER;
-			wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
-			if (wacom_wac2->features.touch_max)
-				snprintf(wacom_wac2->name, WACOM_NAME_MAX,
-					 "%s (WL) Finger",wacom_wac2->features.name);
-			else
-				snprintf(wacom_wac2->name, WACOM_NAME_MAX,
-					 "%s (WL) Pad",wacom_wac2->features.name);
-			error = wacom_register_input(wacom2);
-			if (error)
-				goto fail;
-
-			if (wacom_wac1->features.type == INTUOSHT &&
-			    wacom_wac1->features.touch_max)
-				wacom_wac->shared->touch_input = wacom_wac2->input;
-		}
-
-		error = wacom_initialize_battery(wacom);
-		if (error)
-			goto fail;
-	}
-
-	return;
-
-fail:
-	if (wacom_wac2->input) {
-		input_unregister_device(wacom_wac2->input);
-		wacom_wac2->input = NULL;
-	}
-
-	if (wacom_wac1->input) {
-		input_unregister_device(wacom_wac1->input);
-		wacom_wac1->input = NULL;
-	}
-	return;
-}
-
-/*
- * Not all devices report physical dimensions from HID.
- * Compute the default from hardcoded logical dimension
- * and resolution before driver overwrites them.
- */
-static void wacom_set_default_phy(struct wacom_features *features)
-{
-	if (features->x_resolution) {
-		features->x_phy = (features->x_max * 100) /
-					features->x_resolution;
-		features->y_phy = (features->y_max * 100) /
-					features->y_resolution;
-	}
-}
-
-static void wacom_calculate_res(struct wacom_features *features)
-{
-	features->x_resolution = wacom_calc_hid_res(features->x_max,
-						    features->x_phy,
-						    features->unit,
-						    features->unitExpo);
-	features->y_resolution = wacom_calc_hid_res(features->y_max,
-						    features->y_phy,
-						    features->unit,
-						    features->unitExpo);
-}
-
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_endpoint_descriptor *endpoint;
-	struct wacom *wacom;
-	struct wacom_wac *wacom_wac;
-	struct wacom_features *features;
-	int error;
-
-	if (!id->driver_info)
-		return -EINVAL;
-
-	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
-	if (!wacom)
-		return -ENOMEM;
-
-	wacom_wac = &wacom->wacom_wac;
-	wacom_wac->features = *((struct wacom_features *)id->driver_info);
-	features = &wacom_wac->features;
-	if (features->pktlen > WACOM_PKGLEN_MAX) {
-		error = -EINVAL;
-		goto fail1;
-	}
-
-	wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX,
-					     GFP_KERNEL, &wacom->data_dma);
-	if (!wacom_wac->data) {
-		error = -ENOMEM;
-		goto fail1;
-	}
-
-	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!wacom->irq) {
-		error = -ENOMEM;
-		goto fail2;
-	}
-
-	wacom->usbdev = dev;
-	wacom->intf = intf;
-	mutex_init(&wacom->lock);
-	INIT_WORK(&wacom->work, wacom_wireless_work);
-	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
-	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
-
-	endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
-	/* set the default size in case we do not get them from hid */
-	wacom_set_default_phy(features);
-
-	/* Retrieve the physical and logical size for touch devices */
-	error = wacom_retrieve_hid_descriptor(intf, features);
-	if (error)
-		goto fail3;
-
-	/*
-	 * Intuos5 has no useful data about its touch interface in its
-	 * HID descriptor. If this is the touch interface (wMaxPacketSize
-	 * of WACOM_PKGLEN_BBTOUCH3), override the table values.
-	 */
-	if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
-		if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
-			features->device_type = BTN_TOOL_FINGER;
-			features->pktlen = WACOM_PKGLEN_BBTOUCH3;
-
-			features->x_max = 4096;
-			features->y_max = 4096;
-		} else {
-			features->device_type = BTN_TOOL_PEN;
-		}
-	}
-
-	wacom_setup_device_quirks(features);
-
-	/* set unit to "100th of a mm" for devices not reported by HID */
-	if (!features->unit) {
-		features->unit = 0x11;
-		features->unitExpo = 16 - 3;
-	}
-	wacom_calculate_res(features);
-
-	strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
-
-	if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
-		struct usb_device *other_dev;
-
-		/* Append the device type to the name */
-		if (features->device_type != BTN_TOOL_FINGER)
-			strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
-		else if (features->touch_max)
-			strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX);
-		else
-			strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
-
-		other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
-		if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
-			other_dev = dev;
-		error = wacom_add_shared_data(wacom_wac, other_dev);
-		if (error)
-			goto fail3;
-	}
-
-	usb_fill_int_urb(wacom->irq, dev,
-			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-			 wacom_wac->data, features->pktlen,
-			 wacom_sys_irq, wacom, endpoint->bInterval);
-	wacom->irq->transfer_dma = wacom->data_dma;
-	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	error = wacom_initialize_leds(wacom);
-	if (error)
-		goto fail4;
-
-	if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
-		error = wacom_register_input(wacom);
-		if (error)
-			goto fail5;
-	}
-
-	/* Note that if query fails it is not a hard failure */
-	wacom_query_tablet_data(intf, features);
-
-	usb_set_intfdata(intf, wacom);
-
-	if (features->quirks & WACOM_QUIRK_MONITOR) {
-		if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
-			error = -EIO;
-			goto fail5;
-		}
-	}
-
-	if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) {
-		if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
-			wacom_wac->shared->touch_input = wacom_wac->input;
-	}
-
-	return 0;
-
- fail5: wacom_destroy_leds(wacom);
- fail4:	wacom_remove_shared_data(wacom_wac);
- fail3:	usb_free_urb(wacom->irq);
- fail2:	usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
- fail1:	kfree(wacom);
-	return error;
-}
-
-static void wacom_disconnect(struct usb_interface *intf)
-{
-	struct wacom *wacom = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	usb_kill_urb(wacom->irq);
-	cancel_work_sync(&wacom->work);
-	if (wacom->wacom_wac.input)
-		input_unregister_device(wacom->wacom_wac.input);
-	wacom_destroy_battery(wacom);
-	wacom_destroy_leds(wacom);
-	usb_free_urb(wacom->irq);
-	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
-			wacom->wacom_wac.data, wacom->data_dma);
-	wacom_remove_shared_data(&wacom->wacom_wac);
-	kfree(wacom);
-}
-
-static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct wacom *wacom = usb_get_intfdata(intf);
-
-	mutex_lock(&wacom->lock);
-	usb_kill_urb(wacom->irq);
-	mutex_unlock(&wacom->lock);
-
-	return 0;
-}
-
-static int wacom_resume(struct usb_interface *intf)
-{
-	struct wacom *wacom = usb_get_intfdata(intf);
-	struct wacom_features *features = &wacom->wacom_wac.features;
-	int rv = 0;
-
-	mutex_lock(&wacom->lock);
-
-	/* switch to wacom mode first */
-	wacom_query_tablet_data(intf, features);
-	wacom_led_control(wacom);
-
-	if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) &&
-	    usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
-		rv = -EIO;
-
-	mutex_unlock(&wacom->lock);
-
-	return rv;
-}
-
-static int wacom_reset_resume(struct usb_interface *intf)
-{
-	return wacom_resume(intf);
-}
-
-static struct usb_driver wacom_driver = {
-	.name =		"wacom",
-	.id_table =	wacom_ids,
-	.probe =	wacom_probe,
-	.disconnect =	wacom_disconnect,
-	.suspend =	wacom_suspend,
-	.resume =	wacom_resume,
-	.reset_resume =	wacom_reset_resume,
-	.supports_autosuspend = 1,
-};
-
-module_usb_driver(wacom_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/wacom_wac.c linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_wac.c
--- linux-libre-3.16-gnu/drivers/input/tablet/wacom_wac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_wac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2485 +0,0 @@
-/*
- * drivers/input/tablet/wacom_wac.c
- *
- *  USB Wacom tablet support - Wacom specific code
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 "wacom_wac.h"
-#include "wacom.h"
-#include <linux/input/mt.h>
-#include <linux/hid.h>
-
-/* resolution for penabled devices */
-#define WACOM_PL_RES		20
-#define WACOM_PENPRTN_RES	40
-#define WACOM_VOLITO_RES	50
-#define WACOM_GRAPHIRE_RES	80
-#define WACOM_INTUOS_RES	100
-#define WACOM_INTUOS3_RES	200
-
-/* Scale factor relating reported contact size to logical contact area.
- * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
- */
-#define WACOM_CONTACT_AREA_SCALE 2607
-
-static int wacom_penpartner_irq(struct wacom_wac *wacom)
-{
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-
-	switch (data[0]) {
-	case 1:
-		if (data[5] & 0x80) {
-			wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-			wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
-			input_report_key(input, wacom->tool[0], 1);
-			input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
-			input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
-			input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
-			input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
-			input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127));
-			input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
-		} else {
-			input_report_key(input, wacom->tool[0], 0);
-			input_report_abs(input, ABS_MISC, 0); /* report tool id */
-			input_report_abs(input, ABS_PRESSURE, -1);
-			input_report_key(input, BTN_TOUCH, 0);
-		}
-		break;
-
-	case 2:
-		input_report_key(input, BTN_TOOL_PEN, 1);
-		input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
-		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
-		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
-		input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
-		input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
-		input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
-		break;
-
-	default:
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d\n", __func__, data[0]);
-		return 0;
-        }
-
-	return 1;
-}
-
-static int wacom_pl_irq(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	int prox, pressure;
-
-	if (data[0] != WACOM_REPORT_PENABLED) {
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d\n", __func__, data[0]);
-		return 0;
-	}
-
-	prox = data[1] & 0x40;
-
-	if (prox) {
-		wacom->id[0] = ERASER_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 going from out of proximity into proximity select between the eraser
-		 * and the pen based on the state of the stylus2 button, choose eraser if
-		 * pressed else choose pen. if not a proximity change from out to in, send
-		 * an out of proximity for previous tool then a in for new tool.
-		 */
-		if (!wacom->tool[0]) {
-			/* Eraser bit set for DTF */
-			if (data[1] & 0x10)
-				wacom->tool[1] = BTN_TOOL_RUBBER;
-			else
-				/* Going into proximity select tool */
-				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-		} else {
-			/* was entered with stylus2 pressed */
-			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
-				/* report out proximity for previous tool */
-				input_report_key(input, wacom->tool[1], 0);
-				input_sync(input);
-				wacom->tool[1] = BTN_TOOL_PEN;
-				return 0;
-			}
-		}
-		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-			/* Unknown tool selected default to pen tool */
-			wacom->tool[1] = BTN_TOOL_PEN;
-			wacom->id[0] = STYLUS_DEVICE_ID;
-		}
-		input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */
-		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
-		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[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
-	} else {
-		/* report proximity-out of a (valid) tool */
-		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-			/* Unknown tool selected default to pen tool */
-			wacom->tool[1] = BTN_TOOL_PEN;
-		}
-		input_report_key(input, wacom->tool[1], prox);
-	}
-
-	wacom->tool[0] = prox; /* Save proximity state */
-	return 1;
-}
-
-static int wacom_ptu_irq(struct wacom_wac *wacom)
-{
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-
-	if (data[0] != WACOM_REPORT_PENABLED) {
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d\n", __func__, data[0]);
-		return 0;
-	}
-
-	if (data[1] & 0x04) {
-		input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20);
-		input_report_key(input, BTN_TOUCH, data[1] & 0x08);
-		wacom->id[0] = ERASER_DEVICE_ID;
-	} else {
-		input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20);
-		input_report_key(input, BTN_TOUCH, data[1] & 0x01);
-		wacom->id[0] = STYLUS_DEVICE_ID;
-	}
-	input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
-	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-	input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
-	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
-	return 1;
-}
-
-static int wacom_dtu_irq(struct wacom_wac *wacom)
-{
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	int prox = data[1] & 0x20;
-
-	dev_dbg(input->dev.parent,
-		"%s: received report #%d", __func__, data[0]);
-
-	if (prox) {
-		/* Going into proximity select tool */
-		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-		if (wacom->tool[0] == BTN_TOOL_PEN)
-			wacom->id[0] = STYLUS_DEVICE_ID;
-		else
-			wacom->id[0] = ERASER_DEVICE_ID;
-	}
-	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
-	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-	input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
-	input_report_key(input, BTN_TOUCH, data[1] & 0x05);
-	if (!prox) /* out-prox */
-		wacom->id[0] = 0;
-	input_report_key(input, wacom->tool[0], prox);
-	input_report_abs(input, ABS_MISC, wacom->id[0]);
-	return 1;
-}
-
-static int wacom_dtus_irq(struct wacom_wac *wacom)
-{
-	char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	unsigned short prox, pressure = 0;
-
-	if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) {
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d", __func__, data[0]);
-		return 0;
-	} else if (data[0] == WACOM_REPORT_DTUSPAD) {
-		input_report_key(input, BTN_0, (data[1] & 0x01));
-		input_report_key(input, BTN_1, (data[1] & 0x02));
-		input_report_key(input, BTN_2, (data[1] & 0x04));
-		input_report_key(input, BTN_3, (data[1] & 0x08));
-		input_report_abs(input, ABS_MISC,
-				 data[1] & 0x0f ? PAD_DEVICE_ID : 0);
-		/*
-		 * Serial number is required when expresskeys are
-		 * reported through pen interface.
-		 */
-		input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
-		return 1;
-	} else {
-		prox = data[1] & 0x80;
-		if (prox) {
-			switch ((data[1] >> 3) & 3) {
-			case 1: /* Rubber */
-				wacom->tool[0] = BTN_TOOL_RUBBER;
-				wacom->id[0] = ERASER_DEVICE_ID;
-				break;
-
-			case 2: /* Pen */
-				wacom->tool[0] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
-				break;
-			}
-		}
-
-		input_report_key(input, BTN_STYLUS, data[1] & 0x20);
-		input_report_key(input, BTN_STYLUS2, data[1] & 0x40);
-		input_report_abs(input, ABS_X, get_unaligned_be16(&data[3]));
-		input_report_abs(input, ABS_Y, get_unaligned_be16(&data[5]));
-		pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff);
-		input_report_abs(input, ABS_PRESSURE, pressure);
-		input_report_key(input, BTN_TOUCH, pressure > 10);
-
-		if (!prox) /* out-prox */
-			wacom->id[0] = 0;
-		input_report_key(input, wacom->tool[0], prox);
-		input_report_abs(input, ABS_MISC, wacom->id[0]);
-		input_event(input, EV_MSC, MSC_SERIAL, 1);
-		return 1;
-	}
-}
-
-static int wacom_graphire_irq(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	int prox;
-	int rw = 0;
-	int retval = 0;
-
-	if (data[0] != WACOM_REPORT_PENABLED) {
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d\n", __func__, data[0]);
-		goto exit;
-	}
-
-	prox = data[1] & 0x80;
-	if (prox || wacom->id[0]) {
-		if (prox) {
-			switch ((data[1] >> 5) & 3) {
-
-			case 0:	/* Pen */
-				wacom->tool[0] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
-				break;
-
-			case 1: /* Rubber */
-				wacom->tool[0] = BTN_TOOL_RUBBER;
-				wacom->id[0] = ERASER_DEVICE_ID;
-				break;
-
-			case 2: /* Mouse with wheel */
-				input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
-				/* fall through */
-
-			case 3: /* Mouse without wheel */
-				wacom->tool[0] = BTN_TOOL_MOUSE;
-				wacom->id[0] = CURSOR_DEVICE_ID;
-				break;
-			}
-		}
-		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
-			input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8));
-			input_report_key(input, BTN_TOUCH, data[1] & 0x01);
-			input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-			input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
-		} else {
-			input_report_key(input, BTN_LEFT, data[1] & 0x01);
-			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
-			if (features->type == WACOM_G4 ||
-					features->type == WACOM_MO) {
-				input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
-				rw = (data[7] & 0x04) - (data[7] & 0x03);
-			} else {
-				input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
-				rw = -(signed char)data[6];
-			}
-			input_report_rel(input, REL_WHEEL, rw);
-		}
-
-		if (!prox)
-			wacom->id[0] = 0;
-		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
-		input_report_key(input, wacom->tool[0], prox);
-		input_event(input, EV_MSC, MSC_SERIAL, 1);
-		input_sync(input); /* sync last event */
-	}
-
-	/* send pad data */
-	switch (features->type) {
-	case WACOM_G4:
-		prox = data[7] & 0xf8;
-		if (prox || wacom->id[1]) {
-			wacom->id[1] = PAD_DEVICE_ID;
-			input_report_key(input, BTN_BACK, (data[7] & 0x40));
-			input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
-			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
-			input_report_rel(input, REL_WHEEL, rw);
-			if (!prox)
-				wacom->id[1] = 0;
-			input_report_abs(input, ABS_MISC, wacom->id[1]);
-			input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
-			retval = 1;
-		}
-		break;
-
-	case WACOM_MO:
-		prox = (data[7] & 0xf8) || data[8];
-		if (prox || wacom->id[1]) {
-			wacom->id[1] = PAD_DEVICE_ID;
-			input_report_key(input, BTN_BACK, (data[7] & 0x08));
-			input_report_key(input, BTN_LEFT, (data[7] & 0x20));
-			input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
-			input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
-			input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
-			if (!prox)
-				wacom->id[1] = 0;
-			input_report_abs(input, ABS_MISC, wacom->id[1]);
-			input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
-			retval = 1;
-		}
-		break;
-	}
-exit:
-	return retval;
-}
-
-static int wacom_intuos_inout(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	int idx = 0;
-
-	/* tool number */
-	if (features->type == INTUOS)
-		idx = data[1] & 0x01;
-
-	/* Enter report */
-	if ((data[1] & 0xfc) == 0xc0) {
-		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-			wacom->shared->stylus_in_proximity = true;
-
-		/* serial number of the tool */
-		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
-			(data[4] << 20) + (data[5] << 12) +
-			(data[6] << 4) + (data[7] >> 4);
-
-		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
-
-		switch (wacom->id[idx]) {
-		case 0x812: /* Inking pen */
-		case 0x801: /* Intuos3 Inking pen */
-		case 0x120802: /* Intuos4/5 Inking Pen */
-		case 0x012:
-			wacom->tool[idx] = BTN_TOOL_PENCIL;
-			break;
-
-		case 0x822: /* Pen */
-		case 0x842:
-		case 0x852:
-		case 0x823: /* Intuos3 Grip Pen */
-		case 0x813: /* Intuos3 Classic Pen */
-		case 0x885: /* Intuos3 Marker Pen */
-		case 0x802: /* Intuos4/5 13HD/24HD General Pen */
-		case 0x804: /* Intuos4/5 13HD/24HD Marker 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 */
-			wacom->tool[idx] = BTN_TOOL_PEN;
-			break;
-
-		case 0x832: /* Stroke pen */
-		case 0x032:
-			wacom->tool[idx] = BTN_TOOL_BRUSH;
-			break;
-
-		case 0x007: /* Mouse 4D and 2D */
-		case 0x09c:
-		case 0x094:
-		case 0x017: /* Intuos3 2D Mouse */
-		case 0x806: /* Intuos4 Mouse */
-			wacom->tool[idx] = BTN_TOOL_MOUSE;
-			break;
-
-		case 0x096: /* Lens cursor */
-		case 0x097: /* Intuos3 Lens cursor */
-		case 0x006: /* Intuos4 Lens cursor */
-			wacom->tool[idx] = BTN_TOOL_LENS;
-			break;
-
-		case 0x82a: /* Eraser */
-		case 0x85a:
-		case 0x91a:
-		case 0xd1a:
-		case 0x0fa:
-		case 0x82b: /* Intuos3 Grip Pen Eraser */
-		case 0x81b: /* Intuos3 Classic Pen Eraser */
-		case 0x91b: /* Intuos3 Airbrush Eraser */
-		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 */
-			wacom->tool[idx] = BTN_TOOL_RUBBER;
-			break;
-
-		case 0xd12:
-		case 0x912:
-		case 0x112:
-		case 0x913: /* Intuos3 Airbrush */
-		case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
-		case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
-			wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
-			break;
-
-		default: /* Unknown tool */
-			wacom->tool[idx] = BTN_TOOL_PEN;
-			break;
-		}
-		return 1;
-	}
-
-	/* older I4 styli don't work with new Cintiqs */
-	if (!((wacom->id[idx] >> 20) & 0x01) &&
-			(features->type == WACOM_21UX2))
-		return 1;
-
-	/* Range Report */
-	if ((data[1] & 0xfe) == 0x20) {
-		input_report_key(input, BTN_TOUCH, 0);
-		input_report_abs(input, ABS_PRESSURE, 0);
-		input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
-		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-			wacom->shared->stylus_in_proximity = true;
-	}
-
-	/* Exit report */
-	if ((data[1] & 0xfe) == 0x80) {
-		if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-			wacom->shared->stylus_in_proximity = false;
-
-		/*
-		 * Reset all states otherwise we lose the initial states
-		 * when in-prox next time
-		 */
-		input_report_abs(input, ABS_X, 0);
-		input_report_abs(input, ABS_Y, 0);
-		input_report_abs(input, ABS_DISTANCE, 0);
-		input_report_abs(input, ABS_TILT_X, 0);
-		input_report_abs(input, ABS_TILT_Y, 0);
-		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
-			input_report_key(input, BTN_LEFT, 0);
-			input_report_key(input, BTN_MIDDLE, 0);
-			input_report_key(input, BTN_RIGHT, 0);
-			input_report_key(input, BTN_SIDE, 0);
-			input_report_key(input, BTN_EXTRA, 0);
-			input_report_abs(input, ABS_THROTTLE, 0);
-			input_report_abs(input, ABS_RZ, 0);
-		} else {
-			input_report_abs(input, ABS_PRESSURE, 0);
-			input_report_key(input, BTN_STYLUS, 0);
-			input_report_key(input, BTN_STYLUS2, 0);
-			input_report_key(input, BTN_TOUCH, 0);
-			input_report_abs(input, ABS_WHEEL, 0);
-			if (features->type >= INTUOS3S)
-				input_report_abs(input, ABS_Z, 0);
-		}
-		input_report_key(input, wacom->tool[idx], 0);
-		input_report_abs(input, ABS_MISC, 0); /* reset tool id */
-		input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		wacom->id[idx] = 0;
-		return 2;
-	}
-	return 0;
-}
-
-static void wacom_intuos_general(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	unsigned int t;
-
-	/* general pen packet */
-	if ((data[1] & 0xb8) == 0xa0) {
-		t = (data[6] << 2) | ((data[7] >> 6) & 3);
-		if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) {
-			t = (t << 1) | (data[1] & 1);
-		}
-		input_report_abs(input, ABS_PRESSURE, t);
-		input_report_abs(input, ABS_TILT_X,
-				((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
-		input_report_key(input, BTN_STYLUS, data[1] & 2);
-		input_report_key(input, BTN_STYLUS2, data[1] & 4);
-		input_report_key(input, BTN_TOUCH, t > 10);
-	}
-
-	/* airbrush second packet */
-	if ((data[1] & 0xbc) == 0xb4) {
-		input_report_abs(input, ABS_WHEEL,
-				(data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(input, ABS_TILT_X,
-				((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
-	}
-}
-
-static int wacom_intuos_irq(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	unsigned int t;
-	int idx = 0, result;
-
-	if (data[0] != WACOM_REPORT_PENABLED &&
-	    data[0] != WACOM_REPORT_INTUOSREAD &&
-	    data[0] != WACOM_REPORT_INTUOSWRITE &&
-	    data[0] != WACOM_REPORT_INTUOSPAD &&
-	    data[0] != WACOM_REPORT_INTUOS5PAD) {
-		dev_dbg(input->dev.parent,
-			"%s: received unknown report #%d\n", __func__, data[0]);
-                return 0;
-	}
-
-	/* tool number */
-	if (features->type == INTUOS)
-		idx = data[1] & 0x01;
-
-	/* pad packets. Works as a second tool and is always in prox */
-	if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
-		if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
-			input_report_key(input, BTN_0, (data[2] & 0x01));
-			input_report_key(input, BTN_1, (data[3] & 0x01));
-			input_report_key(input, BTN_2, (data[3] & 0x02));
-			input_report_key(input, BTN_3, (data[3] & 0x04));
-			input_report_key(input, BTN_4, (data[3] & 0x08));
-			input_report_key(input, BTN_5, (data[3] & 0x10));
-			input_report_key(input, BTN_6, (data[3] & 0x20));
-			if (data[1] & 0x80) {
-				input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-			} else {
-				/* Out of proximity, clear wheel value. */
-				input_report_abs(input, ABS_WHEEL, 0);
-			}
-			if (features->type != INTUOS4S) {
-				input_report_key(input, BTN_7, (data[3] & 0x40));
-				input_report_key(input, BTN_8, (data[3] & 0x80));
-			}
-			if (data[1] | (data[2] & 0x01) | data[3]) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		} else if (features->type == DTK) {
-			input_report_key(input, BTN_0, (data[6] & 0x01));
-			input_report_key(input, BTN_1, (data[6] & 0x02));
-			input_report_key(input, BTN_2, (data[6] & 0x04));
-			input_report_key(input, BTN_3, (data[6] & 0x08));
-			input_report_key(input, BTN_4, (data[6] & 0x10));
-			input_report_key(input, BTN_5, (data[6] & 0x20));
-			if (data[6] & 0x3f) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		} else if (features->type == WACOM_13HD) {
-			input_report_key(input, BTN_0, (data[3] & 0x01));
-			input_report_key(input, BTN_1, (data[4] & 0x01));
-			input_report_key(input, BTN_2, (data[4] & 0x02));
-			input_report_key(input, BTN_3, (data[4] & 0x04));
-			input_report_key(input, BTN_4, (data[4] & 0x08));
-			input_report_key(input, BTN_5, (data[4] & 0x10));
-			input_report_key(input, BTN_6, (data[4] & 0x20));
-			input_report_key(input, BTN_7, (data[4] & 0x40));
-			input_report_key(input, BTN_8, (data[4] & 0x80));
-			if ((data[3] & 0x01) | data[4]) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		} else if (features->type == WACOM_24HD) {
-			input_report_key(input, BTN_0, (data[6] & 0x01));
-			input_report_key(input, BTN_1, (data[6] & 0x02));
-			input_report_key(input, BTN_2, (data[6] & 0x04));
-			input_report_key(input, BTN_3, (data[6] & 0x08));
-			input_report_key(input, BTN_4, (data[6] & 0x10));
-			input_report_key(input, BTN_5, (data[6] & 0x20));
-			input_report_key(input, BTN_6, (data[6] & 0x40));
-			input_report_key(input, BTN_7, (data[6] & 0x80));
-			input_report_key(input, BTN_8, (data[8] & 0x01));
-			input_report_key(input, BTN_9, (data[8] & 0x02));
-			input_report_key(input, BTN_A, (data[8] & 0x04));
-			input_report_key(input, BTN_B, (data[8] & 0x08));
-			input_report_key(input, BTN_C, (data[8] & 0x10));
-			input_report_key(input, BTN_X, (data[8] & 0x20));
-			input_report_key(input, BTN_Y, (data[8] & 0x40));
-			input_report_key(input, BTN_Z, (data[8] & 0x80));
-
-			/*
-			 * Three "buttons" are available on the 24HD which are
-			 * physically implemented as a touchstrip. Each button
-			 * is approximately 3 bits wide with a 2 bit spacing.
-			 * The raw touchstrip bits are stored at:
-			 *    ((data[3] & 0x1f) << 8) | data[4])
-			 */
-			input_report_key(input, KEY_PROG1, data[4] & 0x07);
-			input_report_key(input, KEY_PROG2, data[4] & 0xE0);
-			input_report_key(input, KEY_PROG3, data[3] & 0x1C);
-
-			if (data[1] & 0x80) {
-				input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
-			} else {
-				/* Out of proximity, clear wheel value. */
-				input_report_abs(input, ABS_WHEEL, 0);
-			}
-
-			if (data[2] & 0x80) {
-				input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
-			} else {
-				/* Out of proximity, clear second wheel value. */
-				input_report_abs(input, ABS_THROTTLE, 0);
-			}
-
-			if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		} else if (features->type == CINTIQ_HYBRID) {
-			/*
-			 * Do not send hardware buttons under Android. They
-			 * are already sent to the system through GPIO (and
-			 * have different meaning).
-			 */
-			input_report_key(input, BTN_1, (data[4] & 0x01));
-			input_report_key(input, BTN_2, (data[4] & 0x02));
-			input_report_key(input, BTN_3, (data[4] & 0x04));
-			input_report_key(input, BTN_4, (data[4] & 0x08));
-
-			input_report_key(input, BTN_5, (data[4] & 0x10));  /* Right  */
-			input_report_key(input, BTN_6, (data[4] & 0x20));  /* Up     */
-			input_report_key(input, BTN_7, (data[4] & 0x40));  /* Left   */
-			input_report_key(input, BTN_8, (data[4] & 0x80));  /* Down   */
-			input_report_key(input, BTN_0, (data[3] & 0x01));  /* Center */
-		} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
-			int i;
-
-			/* Touch ring mode switch has no capacitive sensor */
-			input_report_key(input, BTN_0, (data[3] & 0x01));
-
-			/*
-			 * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
-			 * addition to the mechanical switch. Switch data is
-			 * stored in data[4], capacitive data in data[5].
-			 */
-			for (i = 0; i < 8; i++)
-				input_report_key(input, BTN_1 + i, data[4] & (1 << i));
-
-			if (data[2] & 0x80) {
-				input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
-			} else {
-				/* Out of proximity, clear wheel value. */
-				input_report_abs(input, ABS_WHEEL, 0);
-			}
-
-			if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		} else {
-			if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
-				input_report_key(input, BTN_0, (data[5] & 0x01));
-				input_report_key(input, BTN_1, (data[6] & 0x01));
-				input_report_key(input, BTN_2, (data[6] & 0x02));
-				input_report_key(input, BTN_3, (data[6] & 0x04));
-				input_report_key(input, BTN_4, (data[6] & 0x08));
-				input_report_key(input, BTN_5, (data[6] & 0x10));
-				input_report_key(input, BTN_6, (data[6] & 0x20));
-				input_report_key(input, BTN_7, (data[6] & 0x40));
-				input_report_key(input, BTN_8, (data[6] & 0x80));
-				input_report_key(input, BTN_9, (data[7] & 0x01));
-				input_report_key(input, BTN_A, (data[8] & 0x01));
-				input_report_key(input, BTN_B, (data[8] & 0x02));
-				input_report_key(input, BTN_C, (data[8] & 0x04));
-				input_report_key(input, BTN_X, (data[8] & 0x08));
-				input_report_key(input, BTN_Y, (data[8] & 0x10));
-				input_report_key(input, BTN_Z, (data[8] & 0x20));
-				input_report_key(input, BTN_BASE, (data[8] & 0x40));
-				input_report_key(input, BTN_BASE2, (data[8] & 0x80));
-
-				if (features->type == WACOM_22HD) {
-					input_report_key(input, KEY_PROG1, data[9] & 0x01);
-					input_report_key(input, KEY_PROG2, data[9] & 0x02);
-					input_report_key(input, KEY_PROG3, data[9] & 0x04);
-				}
-			} else {
-				input_report_key(input, BTN_0, (data[5] & 0x01));
-				input_report_key(input, BTN_1, (data[5] & 0x02));
-				input_report_key(input, BTN_2, (data[5] & 0x04));
-				input_report_key(input, BTN_3, (data[5] & 0x08));
-				input_report_key(input, BTN_4, (data[6] & 0x01));
-				input_report_key(input, BTN_5, (data[6] & 0x02));
-				input_report_key(input, BTN_6, (data[6] & 0x04));
-				input_report_key(input, BTN_7, (data[6] & 0x08));
-				input_report_key(input, BTN_8, (data[5] & 0x10));
-				input_report_key(input, BTN_9, (data[6] & 0x10));
-			}
-			input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
-			input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
-			if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
-				data[2] | (data[3] & 0x1f) | data[4] | data[8] |
-				(data[7] & 0x01)) {
-				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
-			} else {
-				input_report_abs(input, ABS_MISC, 0);
-			}
-		}
-		input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
-                return 1;
-	}
-
-	/* process in/out prox events */
-	result = wacom_intuos_inout(wacom);
-	if (result)
-                return result - 1;
-
-	/* don't proceed if we don't know the ID */
-	if (!wacom->id[idx])
-		return 0;
-
-	/* Only large Intuos support Lense Cursor */
-	if (wacom->tool[idx] == BTN_TOOL_LENS &&
-	    (features->type == INTUOS3 ||
-	     features->type == INTUOS3S ||
-	     features->type == INTUOS4 ||
-	     features->type == INTUOS4S ||
-	     features->type == INTUOS5 ||
-	     features->type == INTUOS5S ||
-	     features->type == INTUOSPM ||
-	     features->type == INTUOSPS)) {
-
-		return 0;
-	}
-
-	/* Cintiq doesn't send data when RDY bit isn't set */
-	if (features->type == CINTIQ && !(data[1] & 0x40))
-                 return 0;
-
-	if (features->type >= INTUOS3S) {
-		input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
-		input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
-		input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
-	} else {
-		input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
-		input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
-		input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
-	}
-
-	/* process general packets */
-	wacom_intuos_general(wacom);
-
-	/* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
-	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
-
-		if (data[1] & 0x02) {
-			/* Rotation packet */
-			if (features->type >= INTUOS3S) {
-				/* I3 marker pen rotation */
-				t = (data[6] << 3) | ((data[7] >> 5) & 7);
-				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
-					((t-1) / 2 + 450)) : (450 - t / 2) ;
-				input_report_abs(input, ABS_Z, t);
-			} else {
-				/* 4D mouse rotation packet */
-				t = (data[6] << 3) | ((data[7] >> 5) & 7);
-				input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
-					((t - 1) / 2) : -t / 2);
-			}
-
-		} else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
-			/* 4D mouse packet */
-			input_report_key(input, BTN_LEFT,   data[8] & 0x01);
-			input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
-			input_report_key(input, BTN_RIGHT,  data[8] & 0x04);
-
-			input_report_key(input, BTN_SIDE,   data[8] & 0x20);
-			input_report_key(input, BTN_EXTRA,  data[8] & 0x10);
-			t = (data[6] << 2) | ((data[7] >> 6) & 3);
-			input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
-
-		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
-			/* I4 mouse */
-			if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
-				input_report_key(input, BTN_LEFT,   data[6] & 0x01);
-				input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
-				input_report_key(input, BTN_RIGHT,  data[6] & 0x04);
-				input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
-						 - ((data[7] & 0x40) >> 6));
-				input_report_key(input, BTN_SIDE,   data[6] & 0x08);
-				input_report_key(input, BTN_EXTRA,  data[6] & 0x10);
-
-				input_report_abs(input, ABS_TILT_X,
-					((data[7] << 1) & 0x7e) | (data[8] >> 7));
-				input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f);
-			} else {
-				/* 2D mouse packet */
-				input_report_key(input, BTN_LEFT,   data[8] & 0x04);
-				input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
-				input_report_key(input, BTN_RIGHT,  data[8] & 0x10);
-				input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
-						 - ((data[8] & 0x02) >> 1));
-
-				/* I3 2D mouse side buttons */
-				if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
-					input_report_key(input, BTN_SIDE,   data[8] & 0x40);
-					input_report_key(input, BTN_EXTRA,  data[8] & 0x20);
-				}
-			}
-		} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
-				features->type == INTUOS4L || features->type == INTUOS5L ||
-				features->type == INTUOSPL) &&
-			   wacom->tool[idx] == BTN_TOOL_LENS) {
-			/* Lens cursor packets */
-			input_report_key(input, BTN_LEFT,   data[8] & 0x01);
-			input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
-			input_report_key(input, BTN_RIGHT,  data[8] & 0x04);
-			input_report_key(input, BTN_SIDE,   data[8] & 0x10);
-			input_report_key(input, BTN_EXTRA,  data[8] & 0x08);
-		}
-	}
-
-	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
-	input_report_key(input, wacom->tool[idx], 1);
-	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-	return 1;
-}
-
-static int int_dist(int x1, int y1, int x2, int y2)
-{
-	int x = x2 - x1;
-	int y = y2 - y1;
-
-	return int_sqrt(x*x + y*y);
-}
-
-static int wacom_24hdt_irq(struct wacom_wac *wacom)
-{
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int i;
-	int current_num_contacts = data[61];
-	int contacts_to_send = 0;
-
-	/*
-	 * First packet resets the counter since only the first
-	 * packet in series will have non-zero current_num_contacts.
-	 */
-	if (current_num_contacts)
-		wacom->num_contacts_left = current_num_contacts;
-
-	/* There are at most 4 contacts per packet */
-	contacts_to_send = min(4, wacom->num_contacts_left);
-
-	for (i = 0; i < contacts_to_send; i++) {
-		int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
-		bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
-		int slot = input_mt_get_slot_by_key(input, data[offset + 1]);
-
-		if (slot < 0)
-			continue;
-		input_mt_slot(input, slot);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-
-		if (touch) {
-			int t_x = get_unaligned_le16(&data[offset + 2]);
-			int c_x = get_unaligned_le16(&data[offset + 4]);
-			int t_y = get_unaligned_le16(&data[offset + 6]);
-			int c_y = get_unaligned_le16(&data[offset + 8]);
-			int w = get_unaligned_le16(&data[offset + 10]);
-			int h = get_unaligned_le16(&data[offset + 12]);
-
-			input_report_abs(input, ABS_MT_POSITION_X, t_x);
-			input_report_abs(input, ABS_MT_POSITION_Y, t_y);
-			input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
-			input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
-			input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
-			input_report_abs(input, ABS_MT_ORIENTATION, w > h);
-		}
-	}
-	input_mt_report_pointer_emulation(input, true);
-
-	wacom->num_contacts_left -= contacts_to_send;
-	if (wacom->num_contacts_left <= 0)
-		wacom->num_contacts_left = 0;
-
-	return 1;
-}
-
-static int wacom_mt_touch(struct wacom_wac *wacom)
-{
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int i;
-	int current_num_contacts = data[2];
-	int contacts_to_send = 0;
-	int x_offset = 0;
-
-	/* MTTPC does not support Height and Width */
-	if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
-		x_offset = -4;
-
-	/*
-	 * First packet resets the counter since only the first
-	 * packet in series will have non-zero current_num_contacts.
-	 */
-	if (current_num_contacts)
-		wacom->num_contacts_left = current_num_contacts;
-
-	/* There are at most 5 contacts per packet */
-	contacts_to_send = min(5, wacom->num_contacts_left);
-
-	for (i = 0; i < contacts_to_send; i++) {
-		int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3;
-		bool touch = data[offset] & 0x1;
-		int id = get_unaligned_le16(&data[offset + 1]);
-		int slot = input_mt_get_slot_by_key(input, id);
-
-		if (slot < 0)
-			continue;
-
-		input_mt_slot(input, slot);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-		if (touch) {
-			int x = get_unaligned_le16(&data[offset + x_offset + 7]);
-			int y = get_unaligned_le16(&data[offset + x_offset + 9]);
-			input_report_abs(input, ABS_MT_POSITION_X, x);
-			input_report_abs(input, ABS_MT_POSITION_Y, y);
-		}
-	}
-	input_mt_report_pointer_emulation(input, true);
-
-	wacom->num_contacts_left -= contacts_to_send;
-	if (wacom->num_contacts_left < 0)
-		wacom->num_contacts_left = 0;
-
-	return 1;
-}
-
-static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
-{
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int contact_with_no_pen_down_count = 0;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		int p = data[1] & (1 << i);
-		bool touch = p && !wacom->shared->stylus_in_proximity;
-
-		input_mt_slot(input, i);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-		if (touch) {
-			int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
-			int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
-
-			input_report_abs(input, ABS_MT_POSITION_X, x);
-			input_report_abs(input, ABS_MT_POSITION_Y, y);
-			contact_with_no_pen_down_count++;
-		}
-	}
-	input_mt_report_pointer_emulation(input, true);
-
-	/* keep touch state for pen event */
-	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
-
-	return 1;
-}
-
-static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
-{
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	bool prox;
-	int x = 0, y = 0;
-
-	if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
-		return 0;
-
-	if (!wacom->shared->stylus_in_proximity) {
-		if (len == WACOM_PKGLEN_TPC1FG) {
-			prox = data[0] & 0x01;
-			x = get_unaligned_le16(&data[1]);
-			y = get_unaligned_le16(&data[3]);
-		} else if (len == WACOM_PKGLEN_TPC1FG_B) {
-			prox = data[2] & 0x01;
-			x = get_unaligned_le16(&data[3]);
-			y = get_unaligned_le16(&data[5]);
-		} else {
-			prox = data[1] & 0x01;
-			x = le16_to_cpup((__le16 *)&data[2]);
-			y = le16_to_cpup((__le16 *)&data[4]);
-		}
-	} else
-		/* force touch out when pen is in prox */
-		prox = 0;
-
-	if (prox) {
-		input_report_abs(input, ABS_X, x);
-		input_report_abs(input, ABS_Y, y);
-	}
-	input_report_key(input, BTN_TOUCH, prox);
-
-	/* keep touch state for pen events */
-	wacom->shared->touch_down = prox;
-
-	return 1;
-}
-
-static int wacom_tpc_pen(struct wacom_wac *wacom)
-{
-	unsigned char *data = wacom->data;
-	struct input_dev *input = wacom->input;
-	bool prox = data[1] & 0x20;
-
-	if (!wacom->shared->stylus_in_proximity) /* first in prox */
-		/* Going into proximity select tool */
-		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-
-	/* keep pen state for touch events */
-	wacom->shared->stylus_in_proximity = prox;
-
-	/* send pen events only when touch is up or forced out */
-	if (!wacom->shared->touch_down) {
-		input_report_key(input, BTN_STYLUS, data[1] & 0x02);
-		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
-		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-		input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
-		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
-		input_report_key(input, wacom->tool[0], prox);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
-{
-	unsigned char *data = wacom->data;
-
-	dev_dbg(wacom->input->dev.parent,
-		"%s: received report #%d\n", __func__, data[0]);
-
-	switch (len) {
-	case WACOM_PKGLEN_TPC1FG:
-		return wacom_tpc_single_touch(wacom, len);
-
-	case WACOM_PKGLEN_TPC2FG:
-		return wacom_tpc_mt_touch(wacom);
-
-	case WACOM_PKGLEN_PENABLED:
-		return wacom_tpc_pen(wacom);
-
-	default:
-		switch (data[0]) {
-		case WACOM_REPORT_TPC1FG:
-		case WACOM_REPORT_TPCHID:
-		case WACOM_REPORT_TPCST:
-		case WACOM_REPORT_TPC1FGE:
-			return wacom_tpc_single_touch(wacom, len);
-
-		case WACOM_REPORT_TPCMT:
-		case WACOM_REPORT_TPCMT2:
-			return wacom_mt_touch(wacom);
-
-		case WACOM_REPORT_PENABLED:
-			return wacom_tpc_pen(wacom);
-		}
-	}
-
-	return 0;
-}
-
-static int wacom_bpt_touch(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int i;
-
-	if (data[0] != 0x02)
-	    return 0;
-
-	for (i = 0; i < 2; i++) {
-		int offset = (data[1] & 0x80) ? (8 * i) : (9 * i);
-		bool touch = data[offset + 3] & 0x80;
-
-		/*
-		 * Touch events need to be disabled while stylus is
-		 * in proximity because user's hand is resting on touchpad
-		 * and sending unwanted events.  User expects tablet buttons
-		 * to continue working though.
-		 */
-		touch = touch && !wacom->shared->stylus_in_proximity;
-
-		input_mt_slot(input, i);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-		if (touch) {
-			int x = get_unaligned_be16(&data[offset + 3]) & 0x7ff;
-			int y = get_unaligned_be16(&data[offset + 5]) & 0x7ff;
-			if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
-				x <<= 5;
-				y <<= 5;
-			}
-			input_report_abs(input, ABS_MT_POSITION_X, x);
-			input_report_abs(input, ABS_MT_POSITION_Y, y);
-		}
-	}
-
-	input_mt_report_pointer_emulation(input, true);
-
-	input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
-	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
-	input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
-	input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
-
-	input_sync(input);
-
-	return 0;
-}
-
-static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
-{
-	struct wacom_features *features = &wacom->features;
-	struct input_dev *input = wacom->input;
-	bool touch = data[1] & 0x80;
-	int slot = input_mt_get_slot_by_key(input, data[0]);
-
-	if (slot < 0)
-		return;
-
-	touch = touch && !wacom->shared->stylus_in_proximity;
-
-	input_mt_slot(input, slot);
-	input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-
-	if (touch) {
-		int x = (data[2] << 4) | (data[4] >> 4);
-		int y = (data[3] << 4) | (data[4] & 0x0f);
-		int width, height;
-
-		if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
-			width  = data[5] * 100;
-			height = data[6] * 100;
-		} else {
-			/*
-			 * "a" is a scaled-down area which we assume is
-			 * roughly circular and which can be described as:
-			 * a=(pi*r^2)/C.
-			 */
-			int a = data[5];
-			int x_res = input_abs_get_res(input, ABS_MT_POSITION_X);
-			int y_res = input_abs_get_res(input, ABS_MT_POSITION_Y);
-			width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
-			height = width * y_res / x_res;
-		}
-
-		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, width);
-		input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
-	}
-}
-
-static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
-{
-	struct input_dev *input = wacom->input;
-	struct wacom_features *features = &wacom->features;
-
-	if (features->type == INTUOSHT) {
-		input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
-		input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
-	} else {
-		input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
-		input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
-	}
-	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
-	input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
-}
-
-static int wacom_bpt3_touch(struct wacom_wac *wacom)
-{
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int count = data[1] & 0x07;
-	int i;
-
-	if (data[0] != 0x02)
-	    return 0;
-
-	/* data has up to 7 fixed sized 8-byte messages starting at data[2] */
-	for (i = 0; i < count; i++) {
-		int offset = (8 * i) + 2;
-		int msg_id = data[offset];
-
-		if (msg_id >= 2 && msg_id <= 17)
-			wacom_bpt3_touch_msg(wacom, data + offset);
-		else if (msg_id == 128)
-			wacom_bpt3_button_msg(wacom, data + offset);
-
-	}
-	input_mt_report_pointer_emulation(input, true);
-
-	input_sync(input);
-
-	return 0;
-}
-
-static int wacom_bpt_pen(struct wacom_wac *wacom)
-{
-	struct wacom_features *features = &wacom->features;
-	struct input_dev *input = wacom->input;
-	unsigned char *data = wacom->data;
-	int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
-
-	if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
-	    return 0;
-
-	if (data[0] == WACOM_REPORT_USB) {
-		if (features->type == INTUOSHT && features->touch_max) {
-			input_report_switch(wacom->shared->touch_input,
-					    SW_MUTE_DEVICE, data[8] & 0x40);
-			input_sync(wacom->shared->touch_input);
-		}
-		return 0;
-	}
-
-	prox = (data[1] & 0x20) == 0x20;
-
-	/*
-	 * All reports shared between PEN and RUBBER tool must be
-	 * forced to a known starting value (zero) when transitioning to
-	 * out-of-prox.
-	 *
-	 * If not reset then, to userspace, it will look like lost events
-	 * if new tool comes in-prox with same values as previous tool sent.
-	 *
-	 * Hardware does report zero in most out-of-prox cases but not all.
-	 */
-	if (prox) {
-		if (!wacom->shared->stylus_in_proximity) {
-			if (data[1] & 0x08) {
-				wacom->tool[0] = BTN_TOOL_RUBBER;
-				wacom->id[0] = ERASER_DEVICE_ID;
-			} else {
-				wacom->tool[0] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
-			}
-			wacom->shared->stylus_in_proximity = true;
-		}
-		x = le16_to_cpup((__le16 *)&data[2]);
-		y = le16_to_cpup((__le16 *)&data[4]);
-		p = le16_to_cpup((__le16 *)&data[6]);
-		/*
-		 * Convert distance from out prox to distance from tablet.
-		 * distance will be greater than distance_max once
-		 * touching and applying pressure; do not report negative
-		 * distance.
-		 */
-		if (data[8] <= features->distance_max)
-			d = features->distance_max - data[8];
-
-		pen = data[1] & 0x01;
-		btn1 = data[1] & 0x02;
-		btn2 = data[1] & 0x04;
-	}
-
-	input_report_key(input, BTN_TOUCH, pen);
-	input_report_key(input, BTN_STYLUS, btn1);
-	input_report_key(input, BTN_STYLUS2, btn2);
-
-	input_report_abs(input, ABS_X, x);
-	input_report_abs(input, ABS_Y, y);
-	input_report_abs(input, ABS_PRESSURE, p);
-	input_report_abs(input, ABS_DISTANCE, d);
-
-	if (!prox) {
-		wacom->id[0] = 0;
-		wacom->shared->stylus_in_proximity = false;
-	}
-
-	input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
-	input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
-
-	return 1;
-}
-
-static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
-{
-	if (len == WACOM_PKGLEN_BBTOUCH)
-		return wacom_bpt_touch(wacom);
-	else if (len == WACOM_PKGLEN_BBTOUCH3)
-		return wacom_bpt3_touch(wacom);
-	else if (len == WACOM_PKGLEN_BBFUN || len == WACOM_PKGLEN_BBPEN)
-		return wacom_bpt_pen(wacom);
-
-	return 0;
-}
-
-static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
-{
-	unsigned char *data = wacom->data;
-	int connected;
-
-	if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL)
-		return 0;
-
-	connected = data[1] & 0x01;
-	if (connected) {
-		int pid, battery;
-
-		if ((wacom->shared->type == INTUOSHT) &&
-				wacom->shared->touch_max) {
-			input_report_switch(wacom->shared->touch_input,
-					SW_MUTE_DEVICE, data[5] & 0x40);
-			input_sync(wacom->shared->touch_input);
-		}
-
-		pid = get_unaligned_be16(&data[6]);
-		battery = data[5] & 0x3f;
-		if (wacom->pid != pid) {
-			wacom->pid = pid;
-			wacom_schedule_work(wacom);
-		}
-		wacom->battery_capacity = battery;
-	} else if (wacom->pid != 0) {
-		/* disconnected while previously connected */
-		wacom->pid = 0;
-		wacom_schedule_work(wacom);
-		wacom->battery_capacity = 0;
-	}
-
-	return 0;
-}
-
-void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
-{
-	bool sync;
-
-	switch (wacom_wac->features.type) {
-	case PENPARTNER:
-		sync = wacom_penpartner_irq(wacom_wac);
-		break;
-
-	case PL:
-		sync = wacom_pl_irq(wacom_wac);
-		break;
-
-	case WACOM_G4:
-	case GRAPHIRE:
-	case WACOM_MO:
-		sync = wacom_graphire_irq(wacom_wac);
-		break;
-
-	case PTU:
-		sync = wacom_ptu_irq(wacom_wac);
-		break;
-
-	case DTU:
-		sync = wacom_dtu_irq(wacom_wac);
-		break;
-
-	case DTUS:
-		sync = wacom_dtus_irq(wacom_wac);
-		break;
-
-	case INTUOS:
-	case INTUOS3S:
-	case INTUOS3:
-	case INTUOS3L:
-	case INTUOS4S:
-	case INTUOS4:
-	case INTUOS4L:
-	case CINTIQ:
-	case WACOM_BEE:
-	case WACOM_13HD:
-	case WACOM_21UX2:
-	case WACOM_22HD:
-	case WACOM_24HD:
-	case DTK:
-	case CINTIQ_HYBRID:
-		sync = wacom_intuos_irq(wacom_wac);
-		break;
-
-	case WACOM_24HDT:
-		sync = wacom_24hdt_irq(wacom_wac);
-		break;
-
-	case INTUOS5S:
-	case INTUOS5:
-	case INTUOS5L:
-	case INTUOSPS:
-	case INTUOSPM:
-	case INTUOSPL:
-		if (len == WACOM_PKGLEN_BBTOUCH3)
-			sync = wacom_bpt3_touch(wacom_wac);
-		else
-			sync = wacom_intuos_irq(wacom_wac);
-		break;
-
-	case TABLETPC:
-	case TABLETPCE:
-	case TABLETPC2FG:
-	case MTSCREEN:
-	case MTTPC:
-	case MTTPC_B:
-		sync = wacom_tpc_irq(wacom_wac, len);
-		break;
-
-	case BAMBOO_PT:
-	case INTUOSHT:
-		sync = wacom_bpt_irq(wacom_wac, len);
-		break;
-
-	case WIRELESS:
-		sync = wacom_wireless_irq(wacom_wac, len);
-		break;
-
-	default:
-		sync = false;
-		break;
-	}
-
-	if (sync)
-		input_sync(wacom_wac->input);
-}
-
-static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
-{
-	struct input_dev *input_dev = wacom_wac->input;
-
-	input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-
-	__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-	__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-	__set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
-	__set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
-	__set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
-	__set_bit(BTN_STYLUS, input_dev->keybit);
-	__set_bit(BTN_STYLUS2, input_dev->keybit);
-
-	input_set_abs_params(input_dev, ABS_DISTANCE,
-			     0, wacom_wac->features.distance_max, 0, 0);
-	input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-	input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
-	input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
-}
-
-static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
-{
-	struct input_dev *input_dev = wacom_wac->input;
-
-	input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-	wacom_setup_cintiq(wacom_wac);
-
-	__set_bit(BTN_LEFT, input_dev->keybit);
-	__set_bit(BTN_RIGHT, input_dev->keybit);
-	__set_bit(BTN_MIDDLE, input_dev->keybit);
-	__set_bit(BTN_SIDE, input_dev->keybit);
-	__set_bit(BTN_EXTRA, input_dev->keybit);
-	__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
-	__set_bit(BTN_TOOL_LENS, input_dev->keybit);
-
-	input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
-	input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
-}
-
-void wacom_setup_device_quirks(struct wacom_features *features)
-{
-
-	/* touch device found but size is not defined. use default */
-	if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
-		features->x_max = 1023;
-		features->y_max = 1023;
-	}
-
-	/* these device have multiple inputs */
-	if (features->type >= WIRELESS ||
-	    (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
-	    (features->oVid && features->oPid))
-		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
-
-	/* quirk for bamboo touch with 2 low res touches */
-	if (features->type == BAMBOO_PT &&
-	    features->pktlen == WACOM_PKGLEN_BBTOUCH) {
-		features->x_max <<= 5;
-		features->y_max <<= 5;
-		features->x_fuzz <<= 5;
-		features->y_fuzz <<= 5;
-		features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
-	}
-
-	if (features->type == WIRELESS) {
-
-		/* monitor never has input and pen/touch have delayed create */
-		features->quirks |= WACOM_QUIRK_NO_INPUT;
-
-		/* must be monitor interface if no device_type set */
-		if (!features->device_type)
-			features->quirks |= WACOM_QUIRK_MONITOR;
-	}
-}
-
-static void wacom_abs_set_axis(struct input_dev *input_dev,
-			       struct wacom_wac *wacom_wac)
-{
-	struct wacom_features *features = &wacom_wac->features;
-
-	if (features->device_type == BTN_TOOL_PEN) {
-		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_PRESSURE, 0,
-			features->pressure_max, features->pressure_fuzz, 0);
-
-		/* penabled devices have fixed resolution for each model */
-		input_abs_set_res(input_dev, ABS_X, features->x_resolution);
-		input_abs_set_res(input_dev, ABS_Y, features->y_resolution);
-	} else {
-		if (features->touch_max == 1) {
-			input_set_abs_params(input_dev, ABS_X, 0,
-				features->x_max, features->x_fuzz, 0);
-			input_set_abs_params(input_dev, ABS_Y, 0,
-				features->y_max, features->y_fuzz, 0);
-			input_abs_set_res(input_dev, ABS_X,
-					  features->x_resolution);
-			input_abs_set_res(input_dev, ABS_Y,
-					  features->y_resolution);
-		}
-
-		if (features->touch_max > 1) {
-			input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
-				features->x_max, features->x_fuzz, 0);
-			input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
-				features->y_max, features->y_fuzz, 0);
-			input_abs_set_res(input_dev, ABS_MT_POSITION_X,
-					  features->x_resolution);
-			input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
-					  features->y_resolution);
-		}
-	}
-}
-
-int wacom_setup_input_capabilities(struct input_dev *input_dev,
-				   struct wacom_wac *wacom_wac)
-{
-	struct wacom_features *features = &wacom_wac->features;
-	int i;
-
-	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-	__set_bit(ABS_MISC, input_dev->absbit);
-
-	wacom_abs_set_axis(input_dev, wacom_wac);
-
-	switch (features->type) {
-	case WACOM_MO:
-		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
-		/* fall through */
-
-	case WACOM_G4:
-		input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-
-		__set_bit(BTN_BACK, input_dev->keybit);
-		__set_bit(BTN_FORWARD, input_dev->keybit);
-		/* fall through */
-
-	case GRAPHIRE:
-		input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-		__set_bit(BTN_LEFT, input_dev->keybit);
-		__set_bit(BTN_RIGHT, input_dev->keybit);
-		__set_bit(BTN_MIDDLE, input_dev->keybit);
-
-		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-		__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
-		__set_bit(BTN_STYLUS, input_dev->keybit);
-		__set_bit(BTN_STYLUS2, input_dev->keybit);
-
-		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-		break;
-
-	case WACOM_24HD:
-		__set_bit(BTN_A, input_dev->keybit);
-		__set_bit(BTN_B, input_dev->keybit);
-		__set_bit(BTN_C, input_dev->keybit);
-		__set_bit(BTN_X, input_dev->keybit);
-		__set_bit(BTN_Y, input_dev->keybit);
-		__set_bit(BTN_Z, input_dev->keybit);
-
-		for (i = 6; i < 10; i++)
-			__set_bit(BTN_0 + i, input_dev->keybit);
-
-		__set_bit(KEY_PROG1, input_dev->keybit);
-		__set_bit(KEY_PROG2, input_dev->keybit);
-		__set_bit(KEY_PROG3, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
-		/* fall through */
-
-	case DTK:
-		for (i = 0; i < 6; i++)
-			__set_bit(BTN_0 + i, input_dev->keybit);
-
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-		wacom_setup_cintiq(wacom_wac);
-		break;
-
-	case WACOM_22HD:
-		__set_bit(KEY_PROG1, input_dev->keybit);
-		__set_bit(KEY_PROG2, input_dev->keybit);
-		__set_bit(KEY_PROG3, input_dev->keybit);
-		/* fall through */
-
-	case WACOM_21UX2:
-		__set_bit(BTN_A, input_dev->keybit);
-		__set_bit(BTN_B, input_dev->keybit);
-		__set_bit(BTN_C, input_dev->keybit);
-		__set_bit(BTN_X, input_dev->keybit);
-		__set_bit(BTN_Y, input_dev->keybit);
-		__set_bit(BTN_Z, input_dev->keybit);
-		__set_bit(BTN_BASE, input_dev->keybit);
-		__set_bit(BTN_BASE2, input_dev->keybit);
-		/* fall through */
-
-	case WACOM_BEE:
-		__set_bit(BTN_8, input_dev->keybit);
-		__set_bit(BTN_9, input_dev->keybit);
-		/* fall through */
-
-	case CINTIQ:
-		for (i = 0; i < 8; i++)
-			__set_bit(BTN_0 + i, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
-		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-		wacom_setup_cintiq(wacom_wac);
-		break;
-
-	case WACOM_13HD:
-		for (i = 0; i < 9; i++)
-			__set_bit(BTN_0 + i, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-		wacom_setup_cintiq(wacom_wac);
-		break;
-
-	case INTUOS3:
-	case INTUOS3L:
-		__set_bit(BTN_4, input_dev->keybit);
-		__set_bit(BTN_5, input_dev->keybit);
-		__set_bit(BTN_6, input_dev->keybit);
-		__set_bit(BTN_7, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
-		/* fall through */
-
-	case INTUOS3S:
-		__set_bit(BTN_0, input_dev->keybit);
-		__set_bit(BTN_1, input_dev->keybit);
-		__set_bit(BTN_2, input_dev->keybit);
-		__set_bit(BTN_3, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-		/* fall through */
-
-	case INTUOS:
-		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-
-		wacom_setup_intuos(wacom_wac);
-		break;
-
-	case INTUOS5:
-	case INTUOS5L:
-	case INTUOSPM:
-	case INTUOSPL:
-		if (features->device_type == BTN_TOOL_PEN) {
-			__set_bit(BTN_7, input_dev->keybit);
-			__set_bit(BTN_8, input_dev->keybit);
-		}
-		/* fall through */
-
-	case INTUOS5S:
-	case INTUOSPS:
-		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-
-		if (features->device_type == BTN_TOOL_PEN) {
-			for (i = 0; i < 7; i++)
-				__set_bit(BTN_0 + i, input_dev->keybit);
-
-			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
-					      features->distance_max,
-					      0, 0);
-
-			input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-
-			wacom_setup_intuos(wacom_wac);
-		} else if (features->device_type == BTN_TOOL_FINGER) {
-			__clear_bit(ABS_MISC, input_dev->absbit);
-
-			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			                     0, features->x_max, 0, 0);
-			input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
-			                     0, features->y_max, 0, 0);
-			input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER);
-		}
-		break;
-
-	case INTUOS4:
-	case INTUOS4L:
-		__set_bit(BTN_7, input_dev->keybit);
-		__set_bit(BTN_8, input_dev->keybit);
-		/* fall through */
-
-	case INTUOS4S:
-		for (i = 0; i < 7; i++)
-			__set_bit(BTN_0 + i, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-		wacom_setup_intuos(wacom_wac);
-
-		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-		break;
-
-	case WACOM_24HDT:
-		if (features->device_type == BTN_TOOL_FINGER) {
-			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
-			input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
-			input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
-			input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
-		}
-		/* fall through */
-
-	case MTSCREEN:
-	case MTTPC:
-	case MTTPC_B:
-	case TABLETPC2FG:
-		if (features->device_type == BTN_TOOL_FINGER && features->touch_max > 1)
-			input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT);
-		/* fall through */
-
-	case TABLETPC:
-	case TABLETPCE:
-		__clear_bit(ABS_MISC, input_dev->absbit);
-
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-		if (features->device_type != BTN_TOOL_PEN)
-			break;  /* no need to process stylus stuff */
-
-		/* fall through */
-
-	case DTUS:
-	case PL:
-	case DTU:
-		if (features->type == DTUS) {
-			input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-			for (i = 0; i < 4; i++)
-				__set_bit(BTN_0 + i, input_dev->keybit);
-		}
-		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-		__set_bit(BTN_STYLUS, input_dev->keybit);
-		__set_bit(BTN_STYLUS2, input_dev->keybit);
-
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-		break;
-
-	case PTU:
-		__set_bit(BTN_STYLUS2, input_dev->keybit);
-		/* fall through */
-
-	case PENPARTNER:
-		__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-		__set_bit(BTN_STYLUS, input_dev->keybit);
-
-		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-		break;
-
-	case INTUOSHT:
-		if (features->touch_max &&
-		    features->device_type == BTN_TOOL_FINGER) {
-			input_dev->evbit[0] |= BIT_MASK(EV_SW);
-			__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
-		}
-		/* fall through */
-
-	case BAMBOO_PT:
-		__clear_bit(ABS_MISC, input_dev->absbit);
-
-		if (features->device_type == BTN_TOOL_FINGER) {
-
-			__set_bit(BTN_LEFT, input_dev->keybit);
-			__set_bit(BTN_FORWARD, input_dev->keybit);
-			__set_bit(BTN_BACK, input_dev->keybit);
-			__set_bit(BTN_RIGHT, input_dev->keybit);
-
-			if (features->touch_max) {
-				if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
-					input_set_abs_params(input_dev,
-						     ABS_MT_TOUCH_MAJOR,
-						     0, features->x_max, 0, 0);
-					input_set_abs_params(input_dev,
-						     ABS_MT_TOUCH_MINOR,
-						     0, features->y_max, 0, 0);
-				}
-				input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER);
-			} else {
-				/* buttons/keys only interface */
-				__clear_bit(ABS_X, input_dev->absbit);
-				__clear_bit(ABS_Y, input_dev->absbit);
-				__clear_bit(BTN_TOUCH, input_dev->keybit);
-			}
-		} else if (features->device_type == BTN_TOOL_PEN) {
-			__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-			__set_bit(BTN_STYLUS, input_dev->keybit);
-			__set_bit(BTN_STYLUS2, input_dev->keybit);
-			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
-					      features->distance_max,
-					      0, 0);
-		}
-		break;
-
-	case CINTIQ_HYBRID:
-		__set_bit(BTN_1, input_dev->keybit);
-		__set_bit(BTN_2, input_dev->keybit);
-		__set_bit(BTN_3, input_dev->keybit);
-		__set_bit(BTN_4, input_dev->keybit);
-
-		__set_bit(BTN_5, input_dev->keybit);
-		__set_bit(BTN_6, input_dev->keybit);
-		__set_bit(BTN_7, input_dev->keybit);
-		__set_bit(BTN_8, input_dev->keybit);
-		__set_bit(BTN_0, input_dev->keybit);
-
-		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-		wacom_setup_cintiq(wacom_wac);
-		break;
-	}
-	return 0;
-}
-
-static const struct wacom_features wacom_features_0x00 =
-	{ "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,
-	  0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
-static const struct wacom_features wacom_features_0x10 =
-	{ "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x11 =
-	{ "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x12 =
-	{ "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x13 =
-	{ "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x14 =
-	{ "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x15 =
-	{ "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511,
-	  63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x16 =
-	{ "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
-	  63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x17 =
-	{ "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511,
-	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x18 =
-	{ "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511,
-	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x19 =
-	{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
-	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
-static const struct wacom_features wacom_features_0x60 =
-	{ "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
-	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
-static const struct wacom_features wacom_features_0x61 =
-	{ "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255,
-	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
-static const struct wacom_features wacom_features_0x62 =
-	{ "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
-	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
-static const struct wacom_features wacom_features_0x63 =
-	{ "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511,
-	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
-static const struct wacom_features wacom_features_0x64 =
-	{ "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511,
-	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
-static const struct wacom_features wacom_features_0x65 =
-	{ "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511,
-	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x69 =
-	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
-	  63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
-static const struct wacom_features wacom_features_0x6A =
-	{ "Wacom Bamboo1 4x6",    WACOM_PKGLEN_GRAPHIRE,  14760,  9225, 1023,
-	  63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x6B =
-	{ "Wacom Bamboo1 5x8",    WACOM_PKGLEN_GRAPHIRE,  21648, 13530, 1023,
-	  63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x20 =
-	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x21 =
-	{ "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x22 =
-	{ "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x23 =
-	{ "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x24 =
-	{ "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x30 =
-	{ "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x31 =
-	{ "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x32 =
-	{ "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x33 =
-	{ "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x34 =
-	{ "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x35 =
-	{ "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x37 =
-	{ "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x38 =
-	{ "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x39 =
-	{ "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0xC4 =
-	{ "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0xC0 =
-	{ "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0xC2 =
-	{ "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,
-	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x03 =
-	{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,
-	  0, PTU, WACOM_PL_RES, WACOM_PL_RES };
-static const struct wacom_features wacom_features_0x41 =
-	{ "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x42 =
-	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x43 =
-	{ "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x44 =
-	{ "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x45 =
-	{ "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xB0 =
-	{ "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023,
-	  63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB1 =
-	{ "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023,
-	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB2 =
-	{ "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023,
-	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB3 =
-	{ "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023,
-	  63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB4 =
-	{ "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023,
-	  63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB5 =
-	{ "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023,
-	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB7 =
-	{ "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023,
-	  63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB8 =
-	{ "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047,
-	  63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xB9 =
-	{ "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047,
-	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xBA =
-	{ "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047,
-	  63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xBB =
-	{ "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047,
-	  63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xBC =
-	{ "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40640, 25400, 2047,
-	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0x26 =
-	{ "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS,  31496, 19685, 2047,
-	  63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x27 =
-	{ "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
-	  63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x28 =
-	{ "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
-	  63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x29 =
-	{ "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS,  31496, 19685, 2047,
-	  63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0x2A =
-	{ "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
-	  63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0x314 =
-	{ "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS,  31496, 19685, 2047,
-	  63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x315 =
-	{ "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
-	  63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x317 =
-	{ "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS,  65024, 40640, 2047,
-	  63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0xF4 =
-	{ "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104280, 65400, 2047,
-	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
-static const struct wacom_features wacom_features_0xF8 =
-	{ "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104280, 65400, 2047, /* Pen */
-	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
-	  .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 };
-static const struct wacom_features wacom_features_0x3F =
-	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
-	  63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xC5 =
-	{ "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023,
-	  63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0xC6 =
-	{ "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023,
-	  63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
-static const struct wacom_features wacom_features_0x304 =
-	{ "Wacom Cintiq 13HD",    WACOM_PKGLEN_INTUOS,    59352, 33648, 1023,
-	  63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
-static const struct wacom_features wacom_features_0xC7 =
-	{ "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,
-	  0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xCE =
-	{ "Wacom DTU2231",        WACOM_PKGLEN_GRAPHIRE,  47864, 27011,  511,
-	  0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xF0 =
-	{ "Wacom DTU1631",        WACOM_PKGLEN_GRAPHIRE,  34623, 19553,  511,
-	  0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xFB =
-	{ "Wacom DTU1031",        WACOM_PKGLEN_DTUS,      22096, 13960,  511,
-	  0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x57 =
-	{ "Wacom DTK2241",        WACOM_PKGLEN_INTUOS,    95640, 54060, 2047,
-	  63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
-static const struct wacom_features wacom_features_0x59 = /* Pen */
-	{ "Wacom DTH2242",        WACOM_PKGLEN_INTUOS,    95640, 54060, 2047,
-	  63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
-	  .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 };
-static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2",   WACOM_PKGLEN_INTUOS,    87000, 65400, 2047,
-	  63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
-static const struct wacom_features wacom_features_0xFA =
-	{ "Wacom Cintiq 22HD",    WACOM_PKGLEN_INTUOS,    95640, 54060, 2047,
-	  63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
-static const struct wacom_features wacom_features_0x5B =
-	{ "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS,      95640, 54060, 2047,
-	  63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
-	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
-static const struct wacom_features wacom_features_0x5E =
-	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
-	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10 };
-static const struct wacom_features wacom_features_0x90 =
-	{ "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x93 =
-	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x97 =
-	{ "Wacom ISDv4 97",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  511,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x9A =
-	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x9F =
-	{ "Wacom ISDv4 9F",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xE2 =
-	{ "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,
-	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xE3 =
-	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,
-	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xE5 =
-	{ "Wacom ISDv4 E5",       WACOM_PKGLEN_MTOUCH,    26202, 16325,  255,
-	  0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xE6 =
-	{ "Wacom ISDv4 E6",       WACOM_PKGLEN_TPC2FG,    27760, 15694,  255,
-	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xEC =
-	{ "Wacom ISDv4 EC",       WACOM_PKGLEN_GRAPHIRE,  25710, 14500,  255,
-	  0, TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xED =
-	{ "Wacom ISDv4 ED",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xEF =
-	{ "Wacom ISDv4 EF",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x100 =
-	{ "Wacom ISDv4 100",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x101 =
-	{ "Wacom ISDv4 101",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x10D =
-	{ "Wacom ISDv4 10D",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x10E =
-	{ "Wacom ISDv4 10E",      WACOM_PKGLEN_MTTPC,     27760, 15694,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x10F =
-	{ "Wacom ISDv4 10F",      WACOM_PKGLEN_MTTPC,     27760, 15694,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x116 =
-	{ "Wacom ISDv4 116",      WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
-	  0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x4001 =
-	{ "Wacom ISDv4 4001",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
-	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x4004 =
-	{ "Wacom ISDv4 4004",      WACOM_PKGLEN_MTTPC,     11060, 6220,  255,
-	  0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x5000 =
-	{ "Wacom ISDv4 5000",      WACOM_PKGLEN_MTTPC,     27848, 15752,  1023,
-	  0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x5002 =
-	{ "Wacom ISDv4 5002",      WACOM_PKGLEN_MTTPC,     29576, 16724,  1023,
-	  0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x47 =
-	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
-	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x84 =
-	{ "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0,
-	  0, WIRELESS, 0, 0, .touch_max = 16 };
-static const struct wacom_features wacom_features_0xD0 =
-	{ "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD1 =
-	{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD2 =
-	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD3 =
-	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13700, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD4 =
-	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xD5 =
-	{ "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xD6 =
-	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD7 =
-	{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xD8 =
-	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13700, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xDA =
-	{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xDB =
-	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 2 };
-static const struct wacom_features wacom_features_0xDD =
-        { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN,     14720,  9200, 1023,
-          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0xDE =
-        { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN,    14720,  9200, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0xDF =
-        { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN,    21648, 13700, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x300 =
-	{ "Wacom Bamboo One S",    WACOM_PKGLEN_BBPEN,    14720,  9225, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x301 =
-	{ "Wacom Bamboo One M",    WACOM_PKGLEN_BBPEN,    21648, 13530, 1023,
-	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x302 =
-	{ "Wacom Intuos PT S",     WACOM_PKGLEN_BBPEN,    15200,  9500, 1023,
-	  31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x303 =
-	{ "Wacom Intuos PT M",     WACOM_PKGLEN_BBPEN,    21600, 13500, 1023,
-	  31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-	  .touch_max = 16 };
-static const struct wacom_features wacom_features_0x30E =
-	{ "Wacom Intuos S",        WACOM_PKGLEN_BBPEN,    15200,  9500, 1023,
-	  31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x6004 =
-	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
-	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x0307 =
-	{ "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS,  59352,  33648, 2047,
-	  63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
-	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
-static const struct wacom_features wacom_features_0x0309 =
-	{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
-	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 };
-
-#define USB_DEVICE_WACOM(prod)					\
-	USB_DEVICE(USB_VENDOR_ID_WACOM, prod),			\
-	.driver_info = (kernel_ulong_t)&wacom_features_##prod
-
-#define USB_DEVICE_DETAILED(prod, class, sub, proto)			\
-	USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class,	\
-				      sub, proto),			\
-	.driver_info = (kernel_ulong_t)&wacom_features_##prod
-
-#define USB_DEVICE_LENOVO(prod)					\
-	USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
-	.driver_info = (kernel_ulong_t)&wacom_features_##prod
-
-const struct usb_device_id wacom_ids[] = {
-	{ USB_DEVICE_WACOM(0x00) },
-	{ USB_DEVICE_WACOM(0x10) },
-	{ USB_DEVICE_WACOM(0x11) },
-	{ USB_DEVICE_WACOM(0x12) },
-	{ USB_DEVICE_WACOM(0x13) },
-	{ USB_DEVICE_WACOM(0x14) },
-	{ USB_DEVICE_WACOM(0x15) },
-	{ USB_DEVICE_WACOM(0x16) },
-	{ USB_DEVICE_WACOM(0x17) },
-	{ USB_DEVICE_WACOM(0x18) },
-	{ USB_DEVICE_WACOM(0x19) },
-	{ USB_DEVICE_WACOM(0x60) },
-	{ USB_DEVICE_WACOM(0x61) },
-	{ USB_DEVICE_WACOM(0x62) },
-	{ USB_DEVICE_WACOM(0x63) },
-	{ USB_DEVICE_WACOM(0x64) },
-	{ USB_DEVICE_WACOM(0x65) },
-	{ USB_DEVICE_WACOM(0x69) },
-	{ USB_DEVICE_WACOM(0x6A) },
-	{ USB_DEVICE_WACOM(0x6B) },
-	{ USB_DEVICE_WACOM(0x20) },
-	{ USB_DEVICE_WACOM(0x21) },
-	{ USB_DEVICE_WACOM(0x22) },
-	{ USB_DEVICE_WACOM(0x23) },
-	{ USB_DEVICE_WACOM(0x24) },
-	{ USB_DEVICE_WACOM(0x30) },
-	{ USB_DEVICE_WACOM(0x31) },
-	{ USB_DEVICE_WACOM(0x32) },
-	{ USB_DEVICE_WACOM(0x33) },
-	{ USB_DEVICE_WACOM(0x34) },
-	{ USB_DEVICE_WACOM(0x35) },
-	{ USB_DEVICE_WACOM(0x37) },
-	{ USB_DEVICE_WACOM(0x38) },
-	{ USB_DEVICE_WACOM(0x39) },
-	{ USB_DEVICE_WACOM(0xC4) },
-	{ USB_DEVICE_WACOM(0xC0) },
-	{ USB_DEVICE_WACOM(0xC2) },
-	{ USB_DEVICE_WACOM(0x03) },
-	{ USB_DEVICE_WACOM(0x41) },
-	{ USB_DEVICE_WACOM(0x42) },
-	{ USB_DEVICE_WACOM(0x43) },
-	{ USB_DEVICE_WACOM(0x44) },
-	{ USB_DEVICE_WACOM(0x45) },
-	{ USB_DEVICE_WACOM(0x57) },
-	{ USB_DEVICE_WACOM(0x59) },
-	{ USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_WACOM(0x5B) },
-	{ USB_DEVICE_DETAILED(0x5E, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_WACOM(0xB0) },
-	{ USB_DEVICE_WACOM(0xB1) },
-	{ USB_DEVICE_WACOM(0xB2) },
-	{ USB_DEVICE_WACOM(0xB3) },
-	{ USB_DEVICE_WACOM(0xB4) },
-	{ USB_DEVICE_WACOM(0xB5) },
-	{ USB_DEVICE_WACOM(0xB7) },
-	{ USB_DEVICE_WACOM(0xB8) },
-	{ USB_DEVICE_WACOM(0xB9) },
-	{ USB_DEVICE_WACOM(0xBA) },
-	{ USB_DEVICE_WACOM(0xBB) },
-	{ USB_DEVICE_WACOM(0xBC) },
-	{ USB_DEVICE_WACOM(0x26) },
-	{ USB_DEVICE_WACOM(0x27) },
-	{ USB_DEVICE_WACOM(0x28) },
-	{ USB_DEVICE_WACOM(0x29) },
-	{ USB_DEVICE_WACOM(0x2A) },
-	{ USB_DEVICE_WACOM(0x3F) },
-	{ USB_DEVICE_WACOM(0xC5) },
-	{ USB_DEVICE_WACOM(0xC6) },
-	{ USB_DEVICE_WACOM(0xC7) },
-	/*
-	 * DTU-2231 has two interfaces on the same configuration,
-	 * only one is used.
-	 */
-	{ USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
-			      USB_INTERFACE_SUBCLASS_BOOT,
-			      USB_INTERFACE_PROTOCOL_MOUSE) },
-	{ USB_DEVICE_WACOM(0x84) },
-	{ USB_DEVICE_WACOM(0xD0) },
-	{ USB_DEVICE_WACOM(0xD1) },
-	{ USB_DEVICE_WACOM(0xD2) },
-	{ USB_DEVICE_WACOM(0xD3) },
-	{ USB_DEVICE_WACOM(0xD4) },
-	{ USB_DEVICE_WACOM(0xD5) },
-	{ USB_DEVICE_WACOM(0xD6) },
-	{ USB_DEVICE_WACOM(0xD7) },
-	{ USB_DEVICE_WACOM(0xD8) },
-	{ USB_DEVICE_WACOM(0xDA) },
-	{ USB_DEVICE_WACOM(0xDB) },
-	{ USB_DEVICE_WACOM(0xDD) },
-	{ USB_DEVICE_WACOM(0xDE) },
-	{ USB_DEVICE_WACOM(0xDF) },
-	{ USB_DEVICE_WACOM(0xF0) },
-	{ USB_DEVICE_WACOM(0xCC) },
-	{ USB_DEVICE_WACOM(0x90) },
-	{ USB_DEVICE_WACOM(0x93) },
-	{ USB_DEVICE_WACOM(0x97) },
-	{ USB_DEVICE_WACOM(0x9A) },
-	{ USB_DEVICE_WACOM(0x9F) },
-	{ USB_DEVICE_WACOM(0xE2) },
-	{ USB_DEVICE_WACOM(0xE3) },
-	{ USB_DEVICE_WACOM(0xE5) },
-	{ USB_DEVICE_WACOM(0xE6) },
-	{ USB_DEVICE_WACOM(0xEC) },
-	{ USB_DEVICE_WACOM(0xED) },
-	{ USB_DEVICE_WACOM(0xEF) },
-	{ USB_DEVICE_WACOM(0x100) },
-	{ USB_DEVICE_WACOM(0x101) },
-	{ USB_DEVICE_WACOM(0x10D) },
-	{ USB_DEVICE_WACOM(0x10E) },
-	{ USB_DEVICE_WACOM(0x10F) },
-	{ USB_DEVICE_WACOM(0x116) },
-	{ USB_DEVICE_WACOM(0x300) },
-	{ USB_DEVICE_WACOM(0x301) },
-	{ USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_WACOM(0x304) },
-	{ USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_WACOM(0x4001) },
-	{ USB_DEVICE_WACOM(0x4004) },
-	{ USB_DEVICE_WACOM(0x5000) },
-	{ USB_DEVICE_WACOM(0x5002) },
-	{ USB_DEVICE_WACOM(0x47) },
-	{ USB_DEVICE_WACOM(0xF4) },
-	{ USB_DEVICE_WACOM(0xF8) },
-	{ USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_WACOM(0xFA) },
-	{ USB_DEVICE_WACOM(0xFB) },
-	{ USB_DEVICE_WACOM(0x0307) },
-	{ USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) },
-	{ USB_DEVICE_LENOVO(0x6004) },
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, wacom_ids);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/tablet/wacom_wac.h linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_wac.h
--- linux-libre-3.16-gnu/drivers/input/tablet/wacom_wac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/tablet/wacom_wac.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,165 +0,0 @@
-/*
- * drivers/input/tablet/wacom_wac.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef WACOM_WAC_H
-#define WACOM_WAC_H
-
-#include <linux/types.h>
-
-/* maximum packet length for USB devices */
-#define WACOM_PKGLEN_MAX	68
-
-#define WACOM_NAME_MAX		64
-
-/* packet length for individual models */
-#define WACOM_PKGLEN_PENPRTN	 7
-#define WACOM_PKGLEN_GRAPHIRE	 8
-#define WACOM_PKGLEN_BBFUN	 9
-#define WACOM_PKGLEN_INTUOS	10
-#define WACOM_PKGLEN_TPC1FG	 5
-#define WACOM_PKGLEN_TPC1FG_B	10
-#define WACOM_PKGLEN_TPC2FG	14
-#define WACOM_PKGLEN_BBTOUCH	20
-#define WACOM_PKGLEN_BBTOUCH3	64
-#define WACOM_PKGLEN_BBPEN	10
-#define WACOM_PKGLEN_WIRELESS	32
-#define WACOM_PKGLEN_MTOUCH	62
-#define WACOM_PKGLEN_MTTPC	40
-#define WACOM_PKGLEN_DTUS	68
-#define WACOM_PKGLEN_PENABLED	 8
-
-/* wacom data size per MT contact */
-#define WACOM_BYTES_PER_MT_PACKET	11
-#define WACOM_BYTES_PER_24HDT_PACKET	14
-
-/* device IDs */
-#define STYLUS_DEVICE_ID	0x02
-#define TOUCH_DEVICE_ID		0x03
-#define CURSOR_DEVICE_ID	0x06
-#define ERASER_DEVICE_ID	0x0A
-#define PAD_DEVICE_ID		0x0F
-
-/* wacom data packet report IDs */
-#define WACOM_REPORT_PENABLED		2
-#define WACOM_REPORT_INTUOSREAD		5
-#define WACOM_REPORT_INTUOSWRITE	6
-#define WACOM_REPORT_INTUOSPAD		12
-#define WACOM_REPORT_INTUOS5PAD		3
-#define WACOM_REPORT_DTUSPAD		21
-#define WACOM_REPORT_TPC1FG		6
-#define WACOM_REPORT_TPC2FG		13
-#define WACOM_REPORT_TPCMT		13
-#define WACOM_REPORT_TPCMT2		3
-#define WACOM_REPORT_TPCHID		15
-#define WACOM_REPORT_TPCST		16
-#define WACOM_REPORT_DTUS		17
-#define WACOM_REPORT_TPC1FGE		18
-#define WACOM_REPORT_24HDT		1
-#define WACOM_REPORT_WL			128
-#define WACOM_REPORT_USB		192
-
-/* device quirks */
-#define WACOM_QUIRK_MULTI_INPUT		0x0001
-#define WACOM_QUIRK_BBTOUCH_LOWRES	0x0002
-#define WACOM_QUIRK_NO_INPUT		0x0004
-#define WACOM_QUIRK_MONITOR		0x0008
-
-enum {
-	PENPARTNER = 0,
-	GRAPHIRE,
-	WACOM_G4,
-	PTU,
-	PL,
-	DTU,
-	DTUS,
-	INTUOS,
-	INTUOS3S,
-	INTUOS3,
-	INTUOS3L,
-	INTUOS4S,
-	INTUOS4,
-	INTUOS4L,
-	INTUOS5S,
-	INTUOS5,
-	INTUOS5L,
-	INTUOSPS,
-	INTUOSPM,
-	INTUOSPL,
-	INTUOSHT,
-	WACOM_21UX2,
-	WACOM_22HD,
-	DTK,
-	WACOM_24HD,
-	CINTIQ_HYBRID,
-	CINTIQ,
-	WACOM_BEE,
-	WACOM_13HD,
-	WACOM_MO,
-	WIRELESS,
-	BAMBOO_PT,
-	WACOM_24HDT,
-	TABLETPC,   /* add new TPC below */
-	TABLETPCE,
-	TABLETPC2FG,
-	MTSCREEN,
-	MTTPC,
-	MTTPC_B,
-	MAX_TYPE
-};
-
-struct wacom_features {
-	const char *name;
-	int pktlen;
-	int x_max;
-	int y_max;
-	int pressure_max;
-	int distance_max;
-	int type;
-	int x_resolution;
-	int y_resolution;
-	int x_min;
-	int y_min;
-	int device_type;
-	int x_phy;
-	int y_phy;
-	unsigned char unit;
-	unsigned char unitExpo;
-	int x_fuzz;
-	int y_fuzz;
-	int pressure_fuzz;
-	int distance_fuzz;
-	unsigned quirks;
-	unsigned touch_max;
-	int oVid;
-	int oPid;
-};
-
-struct wacom_shared {
-	bool stylus_in_proximity;
-	bool touch_down;
-	/* for wireless device to access USB interfaces */
-	unsigned touch_max;
-	int type;
-	struct input_dev *touch_input;
-};
-
-struct wacom_wac {
-	char name[WACOM_NAME_MAX];
-	unsigned char *data;
-	int tool[2];
-	int id[2];
-	__u32 serial[2];
-	struct wacom_features features;
-	struct wacom_shared *shared;
-	struct input_dev *input;
-	int pid;
-	int battery_capacity;
-	int num_contacts_left;
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/ads7846.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/ads7846.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/ads7846.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/ads7846.c	2014-09-28 17:29:07.000000000 -0400
@@ -1302,8 +1302,10 @@ static int ads7846_probe(struct spi_devi
 	pdata = dev_get_platdata(&spi->dev);
 	if (!pdata) {
 		pdata = ads7846_probe_dt(&spi->dev);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
+		if (IS_ERR(pdata)) {
+			err = PTR_ERR(pdata);
+			goto err_free_mem;
+		}
 	}
 
 	ts->model = pdata->model ? : 7846;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/atmel_mxt_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/atmel_mxt_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	2014-08-07 04:58:47.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	2014-09-28 21:41:19.000000000 -0400
@@ -2,6 +2,7 @@
  * Atmel maXTouch Touchscreen driver
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Copyright (C) 2011-2014 Atmel Corporation
  * Copyright (C) 2012 Google, Inc.
  *
  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
@@ -22,6 +23,7 @@
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/input/mt.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 /* Version */
@@ -29,8 +31,10 @@
 #define MXT_VER_21		21
 #define MXT_VER_22		22
 
-/* Firmware */
+/* Firmware files */
 #define MXT_FW_NAME		"/*(DEBLOBBED)*/"
+#define MXT_CFG_NAME		"maxtouch.cfg"
+#define MXT_CFG_MAGIC		"OBP_RAW V1"
 
 /* Registers */
 #define MXT_INFO		0x00
@@ -44,6 +48,8 @@
 #define MXT_OBJECT_START	0x07
 
 #define MXT_OBJECT_SIZE		6
+#define MXT_INFO_CHECKSUM_SIZE	3
+#define MXT_MAX_BLOCK_WRITE	256
 
 /* Object types */
 #define MXT_DEBUG_DIAGNOSTIC_T37	37
@@ -74,6 +80,9 @@
 #define MXT_SPT_MESSAGECOUNT_T44	44
 #define MXT_SPT_CTECONFIG_T46		46
 
+/* MXT_GEN_MESSAGE_T5 object */
+#define MXT_RPTID_NOMSG		0xff
+
 /* MXT_GEN_COMMAND_T6 field */
 #define MXT_COMMAND_RESET	0
 #define MXT_COMMAND_BACKUPNV	1
@@ -83,11 +92,20 @@
 
 /* Define for T6 status byte */
 #define MXT_T6_STATUS_RESET	(1 << 7)
+#define MXT_T6_STATUS_OFL	(1 << 6)
+#define MXT_T6_STATUS_SIGERR	(1 << 5)
+#define MXT_T6_STATUS_CAL	(1 << 4)
+#define MXT_T6_STATUS_CFGERR	(1 << 3)
+#define MXT_T6_STATUS_COMSERR	(1 << 2)
 
 /* MXT_GEN_POWER_T7 field */
-#define MXT_POWER_IDLEACQINT	0
-#define MXT_POWER_ACTVACQINT	1
-#define MXT_POWER_ACTV2IDLETO	2
+struct t7_config {
+	u8 idle;
+	u8 active;
+} __packed;
+
+#define MXT_POWER_CFG_RUN		0
+#define MXT_POWER_CFG_DEEPSLEEP		1
 
 /* MXT_GEN_ACQUIRE_T8 field */
 #define MXT_ACQUIRE_CHRGTIME	0
@@ -99,7 +117,6 @@
 #define MXT_ACQUIRE_ATCHCALSTHR	7
 
 /* MXT_TOUCH_MULTI_T9 field */
-#define MXT_TOUCH_CTRL		0
 #define MXT_T9_ORIENT		9
 #define MXT_T9_RANGE		18
 
@@ -217,11 +234,6 @@ struct mxt_object {
 	u8 num_report_ids;
 } __packed;
 
-struct mxt_message {
-	u8 reportid;
-	u8 message[7];
-};
-
 /* Each client has this additional data */
 struct mxt_data {
 	struct i2c_client *client;
@@ -234,15 +246,28 @@ struct mxt_data {
 	unsigned int max_x;
 	unsigned int max_y;
 	bool in_bootloader;
+	u16 mem_size;
+	u8 max_reportid;
 	u32 config_crc;
+	u32 info_crc;
 	u8 bootloader_addr;
+	u8 *msg_buf;
+	u8 t6_status;
+	bool update_input;
+	u8 last_message_count;
+	u8 num_touchids;
+	struct t7_config t7_cfg;
 
 	/* Cached parameters from object table */
+	u16 T5_address;
+	u8 T5_msg_size;
 	u8 T6_reportid;
 	u16 T6_address;
+	u16 T7_address;
 	u8 T9_reportid_min;
 	u8 T9_reportid_max;
 	u8 T19_reportid;
+	u16 T44_address;
 
 	/* for fw update in bootloader */
 	struct completion bl_completion;
@@ -297,42 +322,10 @@ static bool mxt_object_readable(unsigned
 	}
 }
 
-static bool mxt_object_writable(unsigned int type)
-{
-	switch (type) {
-	case MXT_GEN_COMMAND_T6:
-	case MXT_GEN_POWER_T7:
-	case MXT_GEN_ACQUIRE_T8:
-	case MXT_TOUCH_MULTI_T9:
-	case MXT_TOUCH_KEYARRAY_T15:
-	case MXT_TOUCH_PROXIMITY_T23:
-	case MXT_TOUCH_PROXKEY_T52:
-	case MXT_PROCI_GRIPFACE_T20:
-	case MXT_PROCG_NOISE_T22:
-	case MXT_PROCI_ONETOUCH_T24:
-	case MXT_PROCI_TWOTOUCH_T27:
-	case MXT_PROCI_GRIP_T40:
-	case MXT_PROCI_PALM_T41:
-	case MXT_PROCI_TOUCHSUPPRESSION_T42:
-	case MXT_PROCI_STYLUS_T47:
-	case MXT_PROCG_NOISESUPPRESSION_T48:
-	case MXT_SPT_COMMSCONFIG_T18:
-	case MXT_SPT_GPIOPWM_T19:
-	case MXT_SPT_SELFTEST_T25:
-	case MXT_SPT_CTECONFIG_T28:
-	case MXT_SPT_DIGITIZER_T43:
-	case MXT_SPT_CTECONFIG_T46:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static void mxt_dump_message(struct device *dev,
-			     struct mxt_message *message)
+static void mxt_dump_message(struct mxt_data *data, u8 *message)
 {
-	dev_dbg(dev, "reportid: %u\tmessage: %*ph\n",
-		message->reportid, 7, message->message);
+	dev_dbg(&data->client->dev, "message: %*ph\n",
+		data->T5_msg_size, message);
 }
 
 static int mxt_wait_for_completion(struct mxt_data *data,
@@ -366,7 +359,6 @@ static int mxt_bootloader_read(struct mx
 	msg.buf = val;
 
 	ret = i2c_transfer(data->client->adapter, &msg, 1);
-
 	if (ret == 1) {
 		ret = 0;
 	} else {
@@ -401,7 +393,7 @@ static int mxt_bootloader_write(struct m
 	return ret;
 }
 
-static int mxt_lookup_bootloader_address(struct mxt_data *data)
+static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
 {
 	u8 appmode = data->client->addr;
 	u8 bootloader;
@@ -409,12 +401,19 @@ static int mxt_lookup_bootloader_address
 	switch (appmode) {
 	case 0x4a:
 	case 0x4b:
+		/* Chips after 1664S use different scheme */
+		if (retry || data->info.family_id >= 0xa2) {
+			bootloader = appmode - 0x24;
+			break;
+		}
+		/* Fall through for normal case */
 	case 0x4c:
 	case 0x4d:
 	case 0x5a:
 	case 0x5b:
 		bootloader = appmode - 0x26;
 		break;
+
 	default:
 		dev_err(&data->client->dev,
 			"Appmode i2c address 0x%02x not found\n",
@@ -426,6 +425,30 @@ static int mxt_lookup_bootloader_address
 	return 0;
 }
 
+static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address)
+{
+	struct device *dev = &data->client->dev;
+	int error;
+	u8 val;
+	bool crc_failure;
+
+	error = mxt_lookup_bootloader_address(data, alt_address);
+	if (error)
+		return error;
+
+	error = mxt_bootloader_read(data, &val, 1);
+	if (error)
+		return error;
+
+	/* Check app crc fail mode */
+	crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL;
+
+	dev_err(dev, "Detected bootloader, status:%02X%s\n",
+			val, crc_failure ? ", APP_CRC_FAIL" : "");
+
+	return 0;
+}
+
 static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
 {
 	struct device *dev = &data->client->dev;
@@ -447,14 +470,15 @@ static u8 mxt_get_bootloader_version(str
 	}
 }
 
-static int mxt_check_bootloader(struct mxt_data *data, unsigned int state)
+static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
+				bool wait)
 {
 	struct device *dev = &data->client->dev;
 	u8 val;
 	int ret;
 
 recheck:
-	if (state != MXT_WAITING_BOOTLOAD_CMD) {
+	if (wait) {
 		/*
 		 * In application update mode, the interrupt
 		 * line signals state transitions. We must wait for the
@@ -485,6 +509,7 @@ recheck:
 	switch (state) {
 	case MXT_WAITING_BOOTLOAD_CMD:
 	case MXT_WAITING_FRAME_DATA:
+	case MXT_APP_CRC_FAIL:
 		val &= ~MXT_BOOT_STATUS_MASK;
 		break;
 	case MXT_FRAME_CRC_PASS:
@@ -508,13 +533,18 @@ recheck:
 	return 0;
 }
 
-static int mxt_unlock_bootloader(struct mxt_data *data)
+static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
 {
 	int ret;
 	u8 buf[2];
 
-	buf[0] = MXT_UNLOCK_CMD_LSB;
-	buf[1] = MXT_UNLOCK_CMD_MSB;
+	if (unlock) {
+		buf[0] = MXT_UNLOCK_CMD_LSB;
+		buf[1] = MXT_UNLOCK_CMD_MSB;
+	} else {
+		buf[0] = 0x01;
+		buf[1] = 0x01;
+	}
 
 	ret = mxt_bootloader_write(data, buf, 2);
 	if (ret)
@@ -605,40 +635,44 @@ mxt_get_object(struct mxt_data *data, u8
 			return object;
 	}
 
-	dev_err(&data->client->dev, "Invalid object type T%u\n", type);
+	dev_warn(&data->client->dev, "Invalid object type T%u\n", type);
 	return NULL;
 }
 
-static int mxt_read_message(struct mxt_data *data,
-				 struct mxt_message *message)
+static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
 {
-	struct mxt_object *object;
-	u16 reg;
+	struct device *dev = &data->client->dev;
+	u8 status = msg[1];
+	u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
 
-	object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
-	if (!object)
-		return -EINVAL;
+	complete(&data->crc_completion);
 
-	reg = object->start_address;
-	return __mxt_read_reg(data->client, reg,
-			sizeof(struct mxt_message), message);
-}
+	if (crc != data->config_crc) {
+		data->config_crc = crc;
+		dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
+	}
 
-static int mxt_write_object(struct mxt_data *data,
-				 u8 type, u8 offset, u8 val)
-{
-	struct mxt_object *object;
-	u16 reg;
+	/* Detect reset */
+	if (status & MXT_T6_STATUS_RESET)
+		complete(&data->reset_completion);
 
-	object = mxt_get_object(data, type);
-	if (!object || offset >= mxt_obj_size(object))
-		return -EINVAL;
+	/* Output debug if status has changed */
+	if (status != data->t6_status)
+		dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n",
+			status,
+			status == 0 ? " OK" : "",
+			status & MXT_T6_STATUS_RESET ? " RESET" : "",
+			status & MXT_T6_STATUS_OFL ? " OFL" : "",
+			status & MXT_T6_STATUS_SIGERR ? " SIGERR" : "",
+			status & MXT_T6_STATUS_CAL ? " CAL" : "",
+			status & MXT_T6_STATUS_CFGERR ? " CFGERR" : "",
+			status & MXT_T6_STATUS_COMSERR ? " COMSERR" : "");
 
-	reg = object->start_address;
-	return mxt_write_reg(data->client, reg + offset, val);
+	/* Save current status */
+	data->t6_status = status;
 }
 
-static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
+static void mxt_input_button(struct mxt_data *data, u8 *message)
 {
 	struct input_dev *input = data->input_dev;
 	const struct mxt_platform_data *pdata = data->pdata;
@@ -649,30 +683,33 @@ static void mxt_input_button(struct mxt_
 	for (i = 0; i < pdata->t19_num_keys; i++) {
 		if (pdata->t19_keymap[i] == KEY_RESERVED)
 			continue;
-		button = !(message->message[0] & (1 << i));
+		button = !(message[1] & (1 << i));
 		input_report_key(input, pdata->t19_keymap[i], button);
 	}
 }
 
-static void mxt_input_sync(struct input_dev *input_dev)
+static void mxt_input_sync(struct mxt_data *data)
 {
-	input_mt_report_pointer_emulation(input_dev, false);
-	input_sync(input_dev);
+	input_mt_report_pointer_emulation(data->input_dev,
+					  data->pdata->t19_num_keys);
+	input_sync(data->input_dev);
 }
 
-static void mxt_input_touchevent(struct mxt_data *data,
-				      struct mxt_message *message, int id)
+static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
 {
 	struct device *dev = &data->client->dev;
-	u8 status = message->message[0];
 	struct input_dev *input_dev = data->input_dev;
+	int id;
+	u8 status;
 	int x;
 	int y;
 	int area;
 	int amplitude;
 
-	x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
-	y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+	id = message[0] - data->T9_reportid_min;
+	status = message[1];
+	x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
+	y = (message[3] << 4) | ((message[4] & 0xf));
 
 	/* Handle 10/12 bit switching */
 	if (data->max_x < 1024)
@@ -680,8 +717,8 @@ static void mxt_input_touchevent(struct
 	if (data->max_y < 1024)
 		y >>= 2;
 
-	area = message->message[4];
-	amplitude = message->message[5];
+	area = message[5];
+	amplitude = message[6];
 
 	dev_dbg(dev,
 		"[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
@@ -707,7 +744,7 @@ static void mxt_input_touchevent(struct
 		if (status & MXT_T9_RELEASE) {
 			input_mt_report_slot_state(input_dev,
 						   MT_TOOL_FINGER, 0);
-			mxt_input_sync(input_dev);
+			mxt_input_sync(data);
 		}
 
 		/* Touch active */
@@ -720,64 +757,184 @@ static void mxt_input_touchevent(struct
 		/* Touch no longer active, close out slot */
 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
 	}
+
+	data->update_input = true;
 }
 
-static u16 mxt_extract_T6_csum(const u8 *csum)
+static int mxt_proc_message(struct mxt_data *data, u8 *message)
 {
-	return csum[0] | (csum[1] << 8) | (csum[2] << 16);
+	u8 report_id = message[0];
+
+	if (report_id == MXT_RPTID_NOMSG)
+		return 0;
+
+	if (report_id == data->T6_reportid) {
+		mxt_proc_t6_messages(data, message);
+	} else if (!data->input_dev) {
+		/*
+		 * Do not report events if input device
+		 * is not yet registered.
+		 */
+		mxt_dump_message(data, message);
+	} else if (report_id >= data->T9_reportid_min
+	    && report_id <= data->T9_reportid_max) {
+		mxt_proc_t9_message(data, message);
+	} else if (report_id == data->T19_reportid) {
+		mxt_input_button(data, message);
+		data->update_input = true;
+	} else {
+		mxt_dump_message(data, message);
+	}
+
+	return 1;
 }
 
-static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+static int mxt_read_and_process_messages(struct mxt_data *data, u8 count)
 {
-	u8 id = msg->reportid;
-	return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
+	struct device *dev = &data->client->dev;
+	int ret;
+	int i;
+	u8 num_valid = 0;
+
+	/* Safety check for msg_buf */
+	if (count > data->max_reportid)
+		return -EINVAL;
+
+	/* Process remaining messages if necessary */
+	ret = __mxt_read_reg(data->client, data->T5_address,
+				data->T5_msg_size * count, data->msg_buf);
+	if (ret) {
+		dev_err(dev, "Failed to read %u messages (%d)\n", count, ret);
+		return ret;
+	}
+
+	for (i = 0;  i < count; i++) {
+		ret = mxt_proc_message(data,
+			data->msg_buf + data->T5_msg_size * i);
+
+		if (ret == 1)
+			num_valid++;
+	}
+
+	/* return number of messages read */
+	return num_valid;
 }
 
-static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
+static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
 {
-	struct mxt_message message;
-	const u8 *payload = &message.message[0];
 	struct device *dev = &data->client->dev;
-	u8 reportid;
-	bool update_input = false;
-	u32 crc;
+	int ret;
+	u8 count, num_left;
+
+	/* Read T44 and T5 together */
+	ret = __mxt_read_reg(data->client, data->T44_address,
+		data->T5_msg_size + 1, data->msg_buf);
+	if (ret) {
+		dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret);
+		return IRQ_NONE;
+	}
+
+	count = data->msg_buf[0];
+
+	if (count == 0) {
+		/*
+		 * This condition is caused by the CHG line being configured
+		 * in Mode 0. It results in unnecessary I2C operations but it
+		 * is benign.
+		 */
+		dev_dbg(dev, "Interrupt triggered but zero messages\n");
+		return IRQ_NONE;
+	} else if (count > data->max_reportid) {
+		dev_err(dev, "T44 count %d exceeded max report id\n", count);
+		count = data->max_reportid;
+	}
+
+	/* Process first message */
+	ret = mxt_proc_message(data, data->msg_buf + 1);
+	if (ret < 0) {
+		dev_warn(dev, "Unexpected invalid message\n");
+		return IRQ_NONE;
+	}
+
+	num_left = count - 1;
+
+	/* Process remaining messages if necessary */
+	if (num_left) {
+		ret = mxt_read_and_process_messages(data, num_left);
+		if (ret < 0)
+			goto end;
+		else if (ret != num_left)
+			dev_warn(dev, "Unexpected invalid message\n");
+	}
+
+end:
+	if (data->update_input) {
+		mxt_input_sync(data);
+		data->update_input = false;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mxt_process_messages_until_invalid(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	int count, read;
+	u8 tries = 2;
+
+	count = data->max_reportid;
 
+	/* Read messages until we force an invalid */
 	do {
-		if (mxt_read_message(data, &message)) {
-			dev_err(dev, "Failed to read message\n");
-			return IRQ_NONE;
-		}
+		read = mxt_read_and_process_messages(data, count);
+		if (read < count)
+			return 0;
+	} while (--tries);
 
-		reportid = message.reportid;
+	if (data->update_input) {
+		mxt_input_sync(data);
+		data->update_input = false;
+	}
 
-		if (reportid == data->T6_reportid) {
-			u8 status = payload[0];
+	dev_err(dev, "CHG pin isn't cleared\n");
+	return -EBUSY;
+}
 
-			crc = mxt_extract_T6_csum(&payload[1]);
-			if (crc != data->config_crc) {
-				data->config_crc = crc;
-				complete(&data->crc_completion);
-			}
+static irqreturn_t mxt_process_messages(struct mxt_data *data)
+{
+	int total_handled, num_handled;
+	u8 count = data->last_message_count;
 
-			dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
-				status, data->config_crc);
+	if (count < 1 || count > data->max_reportid)
+		count = 1;
 
-			if (status & MXT_T6_STATUS_RESET)
-				complete(&data->reset_completion);
-		} else if (mxt_is_T9_message(data, &message)) {
-			int id = reportid - data->T9_reportid_min;
-			mxt_input_touchevent(data, &message, id);
-			update_input = true;
-		} else if (message.reportid == data->T19_reportid) {
-			mxt_input_button(data, &message);
-			update_input = true;
-		} else {
-			mxt_dump_message(dev, &message);
-		}
-	} while (reportid != 0xff);
+	/* include final invalid message */
+	total_handled = mxt_read_and_process_messages(data, count + 1);
+	if (total_handled < 0)
+		return IRQ_NONE;
+	/* if there were invalid messages, then we are done */
+	else if (total_handled <= count)
+		goto update_count;
 
-	if (update_input)
-		mxt_input_sync(data->input_dev);
+	/* keep reading two msgs until one is invalid or reportid limit */
+	do {
+		num_handled = mxt_read_and_process_messages(data, 2);
+		if (num_handled < 0)
+			return IRQ_NONE;
+
+		total_handled += num_handled;
+
+		if (num_handled < 2)
+			break;
+	} while (total_handled < data->num_touchids);
+
+update_count:
+	data->last_message_count = total_handled;
+
+	if (data->update_input) {
+		mxt_input_sync(data);
+		data->update_input = false;
+	}
 
 	return IRQ_HANDLED;
 }
@@ -792,7 +949,14 @@ static irqreturn_t mxt_interrupt(int irq
 		return IRQ_HANDLED;
 	}
 
-	return mxt_process_messages_until_invalid(data);
+	if (!data->object_table)
+		return IRQ_HANDLED;
+
+	if (data->T44_address) {
+		return mxt_process_messages_t44(data);
+	} else {
+		return mxt_process_messages(data);
+	}
 }
 
 static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
@@ -866,78 +1030,337 @@ static void mxt_update_crc(struct mxt_da
 	mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
 }
 
-static int mxt_check_reg_init(struct mxt_data *data)
+static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
+{
+	static const unsigned int crcpoly = 0x80001B;
+	u32 result;
+	u32 data_word;
+
+	data_word = (secondbyte << 8) | firstbyte;
+	result = ((*crc << 1) ^ data_word);
+
+	if (result & 0x1000000)
+		result ^= crcpoly;
+
+	*crc = result;
+}
+
+static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
+{
+	u32 crc = 0;
+	u8 *ptr = base + start_off;
+	u8 *last_val = base + end_off - 1;
+
+	if (end_off < start_off)
+		return -EINVAL;
+
+	while (ptr < last_val) {
+		mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
+		ptr += 2;
+	}
+
+	/* if len is odd, fill the last byte with 0 */
+	if (ptr == last_val)
+		mxt_calc_crc24(&crc, *ptr, 0);
+
+	/* Mask to 24-bit */
+	crc &= 0x00FFFFFF;
+
+	return crc;
+}
+
+static int mxt_prepare_cfg_mem(struct mxt_data *data,
+			       const struct firmware *cfg,
+			       unsigned int data_pos,
+			       unsigned int cfg_start_ofs,
+			       u8 *config_mem,
+			       size_t config_mem_size)
 {
-	const struct mxt_platform_data *pdata = data->pdata;
-	struct mxt_object *object;
 	struct device *dev = &data->client->dev;
-	int index = 0;
-	int i, size;
+	struct mxt_object *object;
+	unsigned int type, instance, size, byte_offset;
+	int offset;
 	int ret;
+	int i;
+	u16 reg;
+	u8 val;
 
-	if (!pdata->config) {
-		dev_dbg(dev, "No cfg data defined, skipping reg init\n");
-		return 0;
+	while (data_pos < cfg->size) {
+		/* Read type, instance, length */
+		ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
+			     &type, &instance, &size, &offset);
+		if (ret == 0) {
+			/* EOF */
+			break;
+		} else if (ret != 3) {
+			dev_err(dev, "Bad format: failed to parse object\n");
+			return -EINVAL;
+		}
+		data_pos += offset;
+
+		object = mxt_get_object(data, type);
+		if (!object) {
+			/* Skip object */
+			for (i = 0; i < size; i++) {
+				ret = sscanf(cfg->data + data_pos, "%hhx%n",
+					     &val, &offset);
+				if (ret != 1) {
+					dev_err(dev, "Bad format in T%d at %d\n",
+						type, i);
+					return -EINVAL;
+				}
+				data_pos += offset;
+			}
+			continue;
+		}
+
+		if (size > mxt_obj_size(object)) {
+			/*
+			 * Either we are in fallback mode due to wrong
+			 * config or config from a later fw version,
+			 * or the file is corrupt or hand-edited.
+			 */
+			dev_warn(dev, "Discarding %zu byte(s) in T%u\n",
+				 size - mxt_obj_size(object), type);
+		} else if (mxt_obj_size(object) > size) {
+			/*
+			 * If firmware is upgraded, new bytes may be added to
+			 * end of objects. It is generally forward compatible
+			 * to zero these bytes - previous behaviour will be
+			 * retained. However this does invalidate the CRC and
+			 * will force fallback mode until the configuration is
+			 * updated. We warn here but do nothing else - the
+			 * malloc has zeroed the entire configuration.
+			 */
+			dev_warn(dev, "Zeroing %zu byte(s) in T%d\n",
+				 mxt_obj_size(object) - size, type);
+		}
+
+		if (instance >= mxt_obj_instances(object)) {
+			dev_err(dev, "Object instances exceeded!\n");
+			return -EINVAL;
+		}
+
+		reg = object->start_address + mxt_obj_size(object) * instance;
+
+		for (i = 0; i < size; i++) {
+			ret = sscanf(cfg->data + data_pos, "%hhx%n",
+				     &val,
+				     &offset);
+			if (ret != 1) {
+				dev_err(dev, "Bad format in T%d at %d\n",
+					type, i);
+				return -EINVAL;
+			}
+			data_pos += offset;
+
+			if (i > mxt_obj_size(object))
+				continue;
+
+			byte_offset = reg + i - cfg_start_ofs;
+
+			if (byte_offset >= 0 && byte_offset < config_mem_size) {
+				*(config_mem + byte_offset) = val;
+			} else {
+				dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
+					reg, object->type, byte_offset);
+				return -EINVAL;
+			}
+		}
 	}
 
-	mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
+	return 0;
+}
 
-	if (data->config_crc == pdata->config_crc) {
-		dev_info(dev, "Config CRC 0x%06X: OK\n", data->config_crc);
-		return 0;
+static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start,
+			      u8 *config_mem, size_t config_mem_size)
+{
+	unsigned int byte_offset = 0;
+	int error;
+
+	/* Write configuration as blocks */
+	while (byte_offset < config_mem_size) {
+		unsigned int size = config_mem_size - byte_offset;
+
+		if (size > MXT_MAX_BLOCK_WRITE)
+			size = MXT_MAX_BLOCK_WRITE;
+
+		error = __mxt_write_reg(data->client,
+					cfg_start + byte_offset,
+					size, config_mem + byte_offset);
+		if (error) {
+			dev_err(&data->client->dev,
+				"Config write error, ret=%d\n", error);
+			return error;
+		}
+
+		byte_offset += size;
 	}
 
-	dev_info(dev, "Config CRC 0x%06X: does not match 0x%06X\n",
-		 data->config_crc, pdata->config_crc);
+	return 0;
+}
 
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
+/*
+ * mxt_update_cfg - download configuration to chip
+ *
+ * Atmel Raw Config File Format
+ *
+ * The first four lines of the raw config file contain:
+ *  1) Version
+ *  2) Chip ID Information (first 7 bytes of device memory)
+ *  3) Chip Information Block 24-bit CRC Checksum
+ *  4) Chip Configuration 24-bit CRC Checksum
+ *
+ * The rest of the file consists of one line per object instance:
+ *   <TYPE> <INSTANCE> <SIZE> <CONTENTS>
+ *
+ *   <TYPE> - 2-byte object type as hex
+ *   <INSTANCE> - 2-byte object instance number as hex
+ *   <SIZE> - 2-byte object size as hex
+ *   <CONTENTS> - array of <SIZE> 1-byte hex values
+ */
+static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
+{
+	struct device *dev = &data->client->dev;
+	struct mxt_info cfg_info;
+	int ret;
+	int offset;
+	int data_pos;
+	int i;
+	int cfg_start_ofs;
+	u32 info_crc, config_crc, calculated_crc;
+	u8 *config_mem;
+	size_t config_mem_size;
 
-		if (!mxt_object_writable(object->type))
-			continue;
+	mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
 
-		size = mxt_obj_size(object) * mxt_obj_instances(object);
-		if (index + size > pdata->config_length) {
-			dev_err(dev, "Not enough config data!\n");
+	if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
+		dev_err(dev, "Unrecognised config file\n");
+		return -EINVAL;
+	}
+
+	data_pos = strlen(MXT_CFG_MAGIC);
+
+	/* Load information block and check */
+	for (i = 0; i < sizeof(struct mxt_info); i++) {
+		ret = sscanf(cfg->data + data_pos, "%hhx%n",
+			     (unsigned char *)&cfg_info + i,
+			     &offset);
+		if (ret != 1) {
+			dev_err(dev, "Bad format\n");
 			return -EINVAL;
 		}
 
-		ret = __mxt_write_reg(data->client, object->start_address,
-				size, &pdata->config[index]);
-		if (ret)
-			return ret;
-		index += size;
+		data_pos += offset;
+	}
+
+	if (cfg_info.family_id != data->info.family_id) {
+		dev_err(dev, "Family ID mismatch!\n");
+		return -EINVAL;
+	}
+
+	if (cfg_info.variant_id != data->info.variant_id) {
+		dev_err(dev, "Variant ID mismatch!\n");
+		return -EINVAL;
+	}
+
+	/* Read CRCs */
+	ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
+	if (ret != 1) {
+		dev_err(dev, "Bad format: failed to parse Info CRC\n");
+		return -EINVAL;
+	}
+	data_pos += offset;
+
+	ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
+	if (ret != 1) {
+		dev_err(dev, "Bad format: failed to parse Config CRC\n");
+		return -EINVAL;
 	}
+	data_pos += offset;
+
+	/*
+	 * The Info Block CRC is calculated over mxt_info and the object
+	 * table. If it does not match then we are trying to load the
+	 * configuration from a different chip or firmware version, so
+	 * the configuration CRC is invalid anyway.
+	 */
+	if (info_crc == data->info_crc) {
+		if (config_crc == 0 || data->config_crc == 0) {
+			dev_info(dev, "CRC zero, attempting to apply config\n");
+		} else if (config_crc == data->config_crc) {
+			dev_dbg(dev, "Config CRC 0x%06X: OK\n",
+				 data->config_crc);
+			return 0;
+		} else {
+			dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
+				 data->config_crc, config_crc);
+		}
+	} else {
+		dev_warn(dev,
+			 "Warning: Info CRC error - device=0x%06X file=0x%06X\n",
+			 data->info_crc, info_crc);
+	}
+
+	/* Malloc memory to store configuration */
+	cfg_start_ofs = MXT_OBJECT_START +
+			data->info.object_num * sizeof(struct mxt_object) +
+			MXT_INFO_CHECKSUM_SIZE;
+	config_mem_size = data->mem_size - cfg_start_ofs;
+	config_mem = kzalloc(config_mem_size, GFP_KERNEL);
+	if (!config_mem) {
+		dev_err(dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,
+				  config_mem, config_mem_size);
+	if (ret)
+		goto release_mem;
+
+	/* Calculate crc of the received configs (not the raw config file) */
+	if (data->T7_address < cfg_start_ofs) {
+		dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
+			data->T7_address, cfg_start_ofs);
+		ret = 0;
+		goto release_mem;
+	}
+
+	calculated_crc = mxt_calculate_crc(config_mem,
+					   data->T7_address - cfg_start_ofs,
+					   config_mem_size);
+
+	if (config_crc > 0 && config_crc != calculated_crc)
+		dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
+			 calculated_crc, config_crc);
+
+	ret = mxt_upload_cfg_mem(data, cfg_start_ofs,
+				 config_mem, config_mem_size);
+	if (ret)
+		goto release_mem;
 
 	mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
 
 	ret = mxt_soft_reset(data);
 	if (ret)
-		return ret;
+		goto release_mem;
 
 	dev_info(dev, "Config successfully updated\n");
 
-	return 0;
+release_mem:
+	kfree(config_mem);
+	return ret;
 }
 
-static int mxt_make_highchg(struct mxt_data *data)
+static int mxt_acquire_irq(struct mxt_data *data)
 {
-	struct device *dev = &data->client->dev;
-	struct mxt_message message;
-	int count = 10;
 	int error;
 
-	/* Read dummy message to make high CHG pin */
-	do {
-		error = mxt_read_message(data, &message);
-		if (error)
-			return error;
-	} while (message.reportid != 0xff && --count);
+	enable_irq(data->irq);
 
-	if (!count) {
-		dev_err(dev, "CHG pin isn't cleared\n");
-		return -EBUSY;
-	}
+	error = mxt_process_messages_until_invalid(data);
+	if (error)
+		return error;
 
 	return 0;
 }
@@ -956,24 +1379,60 @@ static int mxt_get_info(struct mxt_data
 	return 0;
 }
 
+static void mxt_free_input_device(struct mxt_data *data)
+{
+	if (data->input_dev) {
+		input_unregister_device(data->input_dev);
+		data->input_dev = NULL;
+	}
+}
+
+static void mxt_free_object_table(struct mxt_data *data)
+{
+	kfree(data->object_table);
+	data->object_table = NULL;
+	kfree(data->msg_buf);
+	data->msg_buf = NULL;
+	data->T5_address = 0;
+	data->T5_msg_size = 0;
+	data->T6_reportid = 0;
+	data->T7_address = 0;
+	data->T9_reportid_min = 0;
+	data->T9_reportid_max = 0;
+	data->T19_reportid = 0;
+	data->T44_address = 0;
+	data->max_reportid = 0;
+}
+
 static int mxt_get_object_table(struct mxt_data *data)
 {
 	struct i2c_client *client = data->client;
 	size_t table_size;
+	struct mxt_object *object_table;
 	int error;
 	int i;
 	u8 reportid;
+	u16 end_address;
 
 	table_size = data->info.object_num * sizeof(struct mxt_object);
+	object_table = kzalloc(table_size, GFP_KERNEL);
+	if (!object_table) {
+		dev_err(&data->client->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
 	error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
-			data->object_table);
-	if (error)
+			object_table);
+	if (error) {
+		kfree(object_table);
 		return error;
+	}
 
 	/* Valid Report IDs start counting from 1 */
 	reportid = 1;
+	data->mem_size = 0;
 	for (i = 0; i < data->info.object_num; i++) {
-		struct mxt_object *object = data->object_table + i;
+		struct mxt_object *object = object_table + i;
 		u8 min_id, max_id;
 
 		le16_to_cpus(&object->start_address);
@@ -995,31 +1454,74 @@ static int mxt_get_object_table(struct m
 			min_id, max_id);
 
 		switch (object->type) {
+		case MXT_GEN_MESSAGE_T5:
+			if (data->info.family_id == 0x80 &&
+			    data->info.version < 0x20) {
+				/*
+				 * On mXT224 firmware versions prior to V2.0
+				 * read and discard unused CRC byte otherwise
+				 * DMA reads are misaligned.
+				 */
+				data->T5_msg_size = mxt_obj_size(object);
+			} else {
+				/* CRC not enabled, so skip last byte */
+				data->T5_msg_size = mxt_obj_size(object) - 1;
+			}
+			data->T5_address = object->start_address;
+			break;
 		case MXT_GEN_COMMAND_T6:
 			data->T6_reportid = min_id;
 			data->T6_address = object->start_address;
 			break;
+		case MXT_GEN_POWER_T7:
+			data->T7_address = object->start_address;
+			break;
 		case MXT_TOUCH_MULTI_T9:
 			data->T9_reportid_min = min_id;
 			data->T9_reportid_max = max_id;
+			data->num_touchids = object->num_report_ids
+						* mxt_obj_instances(object);
+			break;
+		case MXT_SPT_MESSAGECOUNT_T44:
+			data->T44_address = object->start_address;
 			break;
 		case MXT_SPT_GPIOPWM_T19:
 			data->T19_reportid = min_id;
 			break;
 		}
+
+		end_address = object->start_address
+			+ mxt_obj_size(object) * mxt_obj_instances(object) - 1;
+
+		if (end_address >= data->mem_size)
+			data->mem_size = end_address + 1;
+	}
+
+	/* Store maximum reportid */
+	data->max_reportid = reportid;
+
+	/* If T44 exists, T5 position has to be directly after */
+	if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
+		dev_err(&client->dev, "Invalid T44 position\n");
+		error = -EINVAL;
+		goto free_object_table;
+	}
+
+	data->msg_buf = kcalloc(data->max_reportid,
+				data->T5_msg_size, GFP_KERNEL);
+	if (!data->msg_buf) {
+		dev_err(&client->dev, "Failed to allocate message buffer\n");
+		error = -ENOMEM;
+		goto free_object_table;
 	}
 
+	data->object_table = object_table;
+
 	return 0;
-}
 
-static void mxt_free_object_table(struct mxt_data *data)
-{
-	kfree(data->object_table);
-	data->object_table = NULL;
-	data->T6_reportid = 0;
-	data->T9_reportid_min = 0;
-	data->T9_reportid_max = 0;
-	data->T19_reportid = 0;
+free_object_table:
+	mxt_free_object_table(data);
+	return error;
 }
 
 static int mxt_read_t9_resolution(struct mxt_data *data)
@@ -1070,55 +1572,259 @@ static int mxt_read_t9_resolution(struct
 	return 0;
 }
 
-static int mxt_initialize(struct mxt_data *data)
+static int mxt_input_open(struct input_dev *dev);
+static void mxt_input_close(struct input_dev *dev);
+
+static int mxt_initialize_t9_input_device(struct mxt_data *data)
 {
-	struct i2c_client *client = data->client;
-	struct mxt_info *info = &data->info;
+	struct device *dev = &data->client->dev;
+	const struct mxt_platform_data *pdata = data->pdata;
+	struct input_dev *input_dev;
 	int error;
+	unsigned int num_mt_slots;
+	unsigned int mt_flags = 0;
+	int i;
 
-	error = mxt_get_info(data);
+	error = mxt_read_t9_resolution(data);
 	if (error)
-		return error;
+		dev_warn(dev, "Failed to initialize T9 resolution\n");
 
-	data->object_table = kcalloc(info->object_num,
-				     sizeof(struct mxt_object),
-				     GFP_KERNEL);
-	if (!data->object_table) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(dev, "Failed to allocate memory\n");
 		return -ENOMEM;
 	}
 
+	input_dev->name = "Atmel maXTouch Touchscreen";
+	input_dev->phys = data->phys;
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = dev;
+	input_dev->open = mxt_input_open;
+	input_dev->close = mxt_input_close;
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+
+	if (pdata->t19_num_keys) {
+		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
+
+		for (i = 0; i < pdata->t19_num_keys; i++)
+			if (pdata->t19_keymap[i] != KEY_RESERVED)
+				input_set_capability(input_dev, EV_KEY,
+						     pdata->t19_keymap[i]);
+
+		mt_flags |= INPUT_MT_POINTER;
+
+		input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
+		input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
+		input_abs_set_res(input_dev, ABS_MT_POSITION_X,
+				  MXT_PIXELS_PER_MM);
+		input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
+				  MXT_PIXELS_PER_MM);
+
+		input_dev->name = "Atmel maXTouch Touchpad";
+	}
+
+	/* For single touch */
+	input_set_abs_params(input_dev, ABS_X,
+			     0, data->max_x, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			     0, data->max_y, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE,
+			     0, 255, 0, 0);
+
+	/* For multi touch */
+	num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
+	error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
+	if (error) {
+		dev_err(dev, "Error %d initialising slots\n", error);
+		goto err_free_mem;
+	}
+
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			     0, MXT_MAX_AREA, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+			     0, data->max_x, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+			     0, data->max_y, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+			     0, 255, 0, 0);
+
+	input_set_drvdata(input_dev, data);
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(dev, "Error %d registering input device\n", error);
+		goto err_free_mem;
+	}
+
+	data->input_dev = input_dev;
+
+	return 0;
+
+err_free_mem:
+	input_free_device(input_dev);
+	return error;
+}
+
+static int mxt_configure_objects(struct mxt_data *data,
+				 const struct firmware *cfg);
+
+static void mxt_config_cb(const struct firmware *cfg, void *ctx)
+{
+	mxt_configure_objects(ctx, cfg);
+	release_firmware(cfg);
+}
+
+static int mxt_initialize(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	int recovery_attempts = 0;
+	int error;
+
+	while (1) {
+		error = mxt_get_info(data);
+		if (!error)
+			break;
+
+		/* Check bootloader state */
+		error = mxt_probe_bootloader(data, false);
+		if (error) {
+			dev_info(&client->dev, "Trying alternate bootloader address\n");
+			error = mxt_probe_bootloader(data, true);
+			if (error) {
+				/* Chip is not in appmode or bootloader mode */
+				return error;
+			}
+		}
+
+		/* OK, we are in bootloader, see if we can recover */
+		if (++recovery_attempts > 1) {
+			dev_err(&client->dev, "Could not recover from bootloader mode\n");
+			/*
+			 * We can reflash from this state, so do not
+			 * abort initialization.
+			 */
+			data->in_bootloader = true;
+			return 0;
+		}
+
+		/* Attempt to exit bootloader into app mode */
+		mxt_send_bootloader_cmd(data, false);
+		msleep(MXT_FW_RESET_TIME);
+	}
+
 	/* Get object table information */
 	error = mxt_get_object_table(data);
 	if (error) {
 		dev_err(&client->dev, "Error %d reading object table\n", error);
-		goto err_free_object_table;
+		return error;
 	}
 
-	/* Check register init values */
-	error = mxt_check_reg_init(data);
+	error = mxt_acquire_irq(data);
+	if (error)
+		goto err_free_object_table;
+
+	error = reject_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
+					&client->dev, GFP_KERNEL, data,
+					mxt_config_cb);
 	if (error) {
-		dev_err(&client->dev, "Error %d initializing configuration\n",
+		dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
 			error);
 		goto err_free_object_table;
 	}
 
-	error = mxt_read_t9_resolution(data);
+	return 0;
+
+err_free_object_table:
+	mxt_free_object_table(data);
+	return error;
+}
+
+static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
+{
+	struct device *dev = &data->client->dev;
+	int error;
+	struct t7_config *new_config;
+	struct t7_config deepsleep = { .active = 0, .idle = 0 };
+
+	if (sleep == MXT_POWER_CFG_DEEPSLEEP)
+		new_config = &deepsleep;
+	else
+		new_config = &data->t7_cfg;
+
+	error = __mxt_write_reg(data->client, data->T7_address,
+				sizeof(data->t7_cfg), new_config);
+	if (error)
+		return error;
+
+	dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n",
+		new_config->active, new_config->idle);
+
+	return 0;
+}
+
+static int mxt_init_t7_power_cfg(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	int error;
+	bool retry = false;
+
+recheck:
+	error = __mxt_read_reg(data->client, data->T7_address,
+				sizeof(data->t7_cfg), &data->t7_cfg);
+	if (error)
+		return error;
+
+	if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) {
+		if (!retry) {
+			dev_dbg(dev, "T7 cfg zero, resetting\n");
+			mxt_soft_reset(data);
+			retry = true;
+			goto recheck;
+		} else {
+			dev_dbg(dev, "T7 cfg zero after reset, overriding\n");
+			data->t7_cfg.active = 20;
+			data->t7_cfg.idle = 100;
+			return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+		}
+	}
+
+	dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n",
+		data->t7_cfg.active, data->t7_cfg.idle);
+	return 0;
+}
+
+static int mxt_configure_objects(struct mxt_data *data,
+				 const struct firmware *cfg)
+{
+	struct device *dev = &data->client->dev;
+	struct mxt_info *info = &data->info;
+	int error;
+
+	if (cfg) {
+		error = mxt_update_cfg(data, cfg);
+		if (error)
+			dev_warn(dev, "Error %d updating config\n", error);
+	}
+
+	error = mxt_init_t7_power_cfg(data);
 	if (error) {
-		dev_err(&client->dev, "Failed to initialize T9 resolution\n");
-		goto err_free_object_table;
+		dev_err(dev, "Failed to initialize power cfg\n");
+		return error;
 	}
 
-	dev_info(&client->dev,
+	error = mxt_initialize_t9_input_device(data);
+	if (error)
+		return error;
+
+	dev_info(dev,
 		 "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
 		 info->family_id, info->variant_id, info->version >> 4,
 		 info->version & 0xf, info->build, info->object_num);
 
 	return 0;
-
-err_free_object_table:
-	mxt_free_object_table(data);
-	return error;
 }
 
 /* Firmware Version is returned as Major.Minor.Build */
@@ -1245,30 +1951,47 @@ static int mxt_load_fw(struct device *de
 	if (ret)
 		goto release_firmware;
 
-	ret = mxt_lookup_bootloader_address(data);
-	if (ret)
-		goto release_firmware;
+	if (!data->in_bootloader) {
+		/* Change to the bootloader mode */
+		data->in_bootloader = true;
 
-	/* Change to the bootloader mode */
-	data->in_bootloader = true;
+		ret = mxt_t6_command(data, MXT_COMMAND_RESET,
+				     MXT_BOOT_VALUE, false);
+		if (ret)
+			goto release_firmware;
 
-	ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_BOOT_VALUE, false);
-	if (ret)
-		goto release_firmware;
+		msleep(MXT_RESET_TIME);
 
-	msleep(MXT_RESET_TIME);
+		/* Do not need to scan since we know family ID */
+		ret = mxt_lookup_bootloader_address(data, 0);
+		if (ret)
+			goto release_firmware;
+
+		mxt_free_input_device(data);
+		mxt_free_object_table(data);
+	} else {
+		enable_irq(data->irq);
+	}
 
 	reinit_completion(&data->bl_completion);
 
-	ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD);
-	if (ret)
-		goto disable_irq;
+	ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
+	if (ret) {
+		/* Bootloader may still be unlocked from previous attempt */
+		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
+		if (ret)
+			goto disable_irq;
+	} else {
+		dev_info(dev, "Unlocking bootloader\n");
 
-	/* Unlock bootloader */
-	mxt_unlock_bootloader(data);
+		/* Unlock bootloader */
+		ret = mxt_send_bootloader_cmd(data, true);
+		if (ret)
+			goto disable_irq;
+	}
 
 	while (pos < fw->size) {
-		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA);
+		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
 		if (ret)
 			goto disable_irq;
 
@@ -1282,7 +2005,7 @@ static int mxt_load_fw(struct device *de
 		if (ret)
 			goto disable_irq;
 
-		ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS);
+		ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
 		if (ret) {
 			retry++;
 
@@ -1342,13 +2065,7 @@ static ssize_t mxt_update_fw_store(struc
 	} else {
 		dev_info(dev, "The firmware update succeeded\n");
 
-		mxt_free_object_table(data);
-
-		mxt_initialize(data);
-
-		enable_irq(data->irq);
-
-		error = mxt_make_highchg(data);
+		error = mxt_initialize(data);
 		if (error)
 			return error;
 	}
@@ -1375,16 +2092,15 @@ static const struct attribute_group mxt_
 
 static void mxt_start(struct mxt_data *data)
 {
-	/* Touch enable */
-	mxt_write_object(data,
-			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
+	mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+
+	/* Recalibrate since chip has been in deep sleep */
+	mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
 }
 
 static void mxt_stop(struct mxt_data *data)
 {
-	/* Touch disable */
-	mxt_write_object(data,
-			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
+	mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
 }
 
 static int mxt_input_open(struct input_dev *dev)
@@ -1403,138 +2119,113 @@ static void mxt_input_close(struct input
 	mxt_stop(data);
 }
 
-static int mxt_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
+#ifdef CONFIG_OF
+static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+{
+	struct mxt_platform_data *pdata;
+	u32 *keymap;
+	u32 keycode;
+	int proplen, i, ret;
+
+	if (!client->dev.of_node)
+		return ERR_PTR(-ENODEV);
+
+	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	if (of_find_property(client->dev.of_node, "linux,gpio-keymap",
+			     &proplen)) {
+		pdata->t19_num_keys = proplen / sizeof(u32);
+
+		keymap = devm_kzalloc(&client->dev,
+				pdata->t19_num_keys * sizeof(keymap[0]),
+				GFP_KERNEL);
+		if (!keymap)
+			return ERR_PTR(-ENOMEM);
+
+		for (i = 0; i < pdata->t19_num_keys; i++) {
+			ret = of_property_read_u32_index(client->dev.of_node,
+					"linux,gpio-keymap", i, &keycode);
+			if (ret)
+				keycode = KEY_RESERVED;
+
+			keymap[i] = keycode;
+		}
+
+		pdata->t19_keymap = keymap;
+	}
+
+	return pdata;
+}
+#else
+static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+{
+	dev_dbg(&client->dev, "No platform data specified\n");
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct mxt_data *data;
-	struct input_dev *input_dev;
+	const struct mxt_platform_data *pdata;
 	int error;
-	unsigned int num_mt_slots;
-	unsigned int mt_flags = 0;
-	int i;
 
-	if (!pdata)
-		return -EINVAL;
+	pdata = dev_get_platdata(&client->dev);
+	if (!pdata) {
+		pdata = mxt_parse_dt(client);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
 
 	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!data || !input_dev) {
+	if (!data) {
 		dev_err(&client->dev, "Failed to allocate memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
+		return -ENOMEM;
 	}
 
-	input_dev->name = "Atmel maXTouch Touchscreen";
 	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
 		 client->adapter->nr, client->addr);
 
-	input_dev->phys = data->phys;
-
-	input_dev->id.bustype = BUS_I2C;
-	input_dev->dev.parent = &client->dev;
-	input_dev->open = mxt_input_open;
-	input_dev->close = mxt_input_close;
-
 	data->client = client;
-	data->input_dev = input_dev;
 	data->pdata = pdata;
 	data->irq = client->irq;
+	i2c_set_clientdata(client, data);
 
 	init_completion(&data->bl_completion);
 	init_completion(&data->reset_completion);
 	init_completion(&data->crc_completion);
 
-	error = mxt_initialize(data);
-	if (error)
-		goto err_free_mem;
-
-	__set_bit(EV_ABS, input_dev->evbit);
-	__set_bit(EV_KEY, input_dev->evbit);
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-
-	if (pdata->t19_num_keys) {
-		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
-
-		for (i = 0; i < pdata->t19_num_keys; i++)
-			if (pdata->t19_keymap[i] != KEY_RESERVED)
-				input_set_capability(input_dev, EV_KEY,
-						     pdata->t19_keymap[i]);
-
-		mt_flags |= INPUT_MT_POINTER;
-
-		input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
-		input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
-		input_abs_set_res(input_dev, ABS_MT_POSITION_X,
-				  MXT_PIXELS_PER_MM);
-		input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
-				  MXT_PIXELS_PER_MM);
-
-		input_dev->name = "Atmel maXTouch Touchpad";
-	}
-
-	/* For single touch */
-	input_set_abs_params(input_dev, ABS_X,
-			     0, data->max_x, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-			     0, data->max_y, 0, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE,
-			     0, 255, 0, 0);
-
-	/* For multi touch */
-	num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
-	error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
-	if (error)
-		goto err_free_object;
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     0, MXT_MAX_AREA, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     0, data->max_x, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     0, data->max_y, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_PRESSURE,
-			     0, 255, 0, 0);
-
-	input_set_drvdata(input_dev, data);
-	i2c_set_clientdata(client, data);
-
 	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
 				     pdata->irqflags | IRQF_ONESHOT,
 				     client->name, data);
 	if (error) {
 		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_free_object;
+		goto err_free_mem;
 	}
 
-	error = mxt_make_highchg(data);
-	if (error)
-		goto err_free_irq;
+	disable_irq(client->irq);
 
-	error = input_register_device(input_dev);
-	if (error) {
-		dev_err(&client->dev, "Error %d registering input device\n",
-			error);
+	error = mxt_initialize(data);
+	if (error)
 		goto err_free_irq;
-	}
 
 	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
 	if (error) {
 		dev_err(&client->dev, "Failure %d creating sysfs group\n",
 			error);
-		goto err_unregister_device;
+		goto err_free_object;
 	}
 
 	return 0;
 
-err_unregister_device:
-	input_unregister_device(input_dev);
-	input_dev = NULL;
+err_free_object:
+	mxt_free_input_device(data);
+	mxt_free_object_table(data);
 err_free_irq:
 	free_irq(client->irq, data);
-err_free_object:
-	kfree(data->object_table);
 err_free_mem:
-	input_free_device(input_dev);
 	kfree(data);
 	return error;
 }
@@ -1545,8 +2236,8 @@ static int mxt_remove(struct i2c_client
 
 	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
 	free_irq(data->irq, data);
-	input_unregister_device(data->input_dev);
-	kfree(data->object_table);
+	mxt_free_input_device(data);
+	mxt_free_object_table(data);
 	kfree(data);
 
 	return 0;
@@ -1575,8 +2266,6 @@ static int mxt_resume(struct device *dev
 	struct mxt_data *data = i2c_get_clientdata(client);
 	struct input_dev *input_dev = data->input_dev;
 
-	mxt_soft_reset(data);
-
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users)
@@ -1590,6 +2279,12 @@ static int mxt_resume(struct device *dev
 
 static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
 
+static const struct of_device_id mxt_of_match[] = {
+	{ .compatible = "atmel,maxtouch", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mxt_of_match);
+
 static const struct i2c_device_id mxt_id[] = {
 	{ "qt602240_ts", 0 },
 	{ "atmel_mxt_ts", 0 },
@@ -1603,6 +2298,7 @@ static struct i2c_driver mxt_driver = {
 	.driver = {
 		.name	= "atmel_mxt_ts",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(mxt_of_match),
 		.pm	= &mxt_pm_ops,
 	},
 	.probe		= mxt_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/edt-ft5x06.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/edt-ft5x06.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/edt-ft5x06.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/edt-ft5x06.c	2014-09-28 17:29:07.000000000 -0400
@@ -262,7 +262,6 @@ static int edt_ft5x06_register_write(str
 	case M06:
 		wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
 		wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
-		wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
 		wrbuf[2] = value;
 		wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
 		return edt_ft5x06_ts_readwrite(tsdata->client, 4,
@@ -733,8 +732,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt
 static void
 edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 {
-	if (tsdata->debug_dir)
-		debugfs_remove_recursive(tsdata->debug_dir);
+	debugfs_remove_recursive(tsdata->debug_dir);
 	kfree(tsdata->raw_buffer);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/ipaq-micro-ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/ipaq-micro-ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/ipaq-micro-ts.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/ipaq-micro-ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * h3600 atmel micro companion support, touchscreen subdevice
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Dmitry Artamonow <mad_soft@inbox.ru>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+#include <asm/byteorder.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/ipaq-micro.h>
+
+struct touchscreen_data {
+	struct input_dev *input;
+	struct ipaq_micro *micro;
+};
+
+static void micro_ts_receive(void *data, int len, unsigned char *msg)
+{
+	struct touchscreen_data *ts = data;
+
+	if (len == 4) {
+		input_report_abs(ts->input, ABS_X,
+				 be16_to_cpup((__be16 *) &msg[2]));
+		input_report_abs(ts->input, ABS_Y,
+				 be16_to_cpup((__be16 *) &msg[0]));
+		input_report_key(ts->input, BTN_TOUCH, 1);
+		input_sync(ts->input);
+	} else if (len == 0) {
+		input_report_abs(ts->input, ABS_X, 0);
+		input_report_abs(ts->input, ABS_Y, 0);
+		input_report_key(ts->input, BTN_TOUCH, 0);
+		input_sync(ts->input);
+	}
+}
+
+static void micro_ts_toggle_receive(struct touchscreen_data *ts, bool enable)
+{
+	struct ipaq_micro *micro = ts->micro;
+
+	spin_lock_irq(&micro->lock);
+
+	if (enable) {
+		micro->ts = micro_ts_receive;
+		micro->ts_data = ts;
+	} else {
+		micro->ts = NULL;
+		micro->ts_data = NULL;
+	}
+
+	spin_unlock_irq(&ts->micro->lock);
+}
+
+static int micro_ts_open(struct input_dev *input)
+{
+	struct touchscreen_data *ts = input_get_drvdata(input);
+
+	micro_ts_toggle_receive(ts, true);
+
+	return 0;
+}
+
+static void micro_ts_close(struct input_dev *input)
+{
+	struct touchscreen_data *ts = input_get_drvdata(input);
+
+	micro_ts_toggle_receive(ts, false);
+}
+
+static int micro_ts_probe(struct platform_device *pdev)
+{
+	struct ipaq_micro *micro = dev_get_drvdata(pdev->dev.parent);
+	struct touchscreen_data *ts;
+	int error;
+
+	ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->micro = micro;
+
+	ts->input = devm_input_allocate_device(&pdev->dev);
+	if (!ts->input) {
+		dev_err(&pdev->dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	ts->input->name = "ipaq micro ts";
+	ts->input->open = micro_ts_open;
+	ts->input->close = micro_ts_close;
+
+	input_set_drvdata(ts->input, ts);
+
+	input_set_capability(ts->input, EV_KEY, BTN_TOUCH);
+	input_set_capability(ts->input, EV_ABS, ABS_X);
+	input_set_capability(ts->input, EV_ABS, ABS_Y);
+	input_set_abs_params(ts->input, ABS_X, 0, 1023, 0, 0);
+	input_set_abs_params(ts->input, ABS_Y, 0, 1023, 0, 0);
+
+	error = input_register_device(ts->input);
+	if (error) {
+		dev_err(&pdev->dev, "error registering touch input\n");
+		return error;
+	}
+
+	platform_set_drvdata(pdev, ts);
+
+	dev_info(&pdev->dev, "iPAQ micro touchscreen\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int micro_ts_suspend(struct device *dev)
+{
+	struct touchscreen_data *ts = dev_get_drvdata(dev);
+
+	micro_ts_toggle_receive(ts, false);
+
+	return 0;
+}
+
+static int micro_ts_resume(struct device *dev)
+{
+	struct touchscreen_data *ts = dev_get_drvdata(dev);
+	struct input_dev *input = ts->input;
+
+	mutex_lock(&input->mutex);
+
+	if (input->users)
+		micro_ts_toggle_receive(ts, true);
+
+	mutex_unlock(&input->mutex);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops micro_ts_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)
+};
+
+static struct platform_driver micro_ts_device_driver = {
+	.driver	= {
+		.name	= "ipaq-micro-ts",
+		.pm	= &micro_ts_dev_pm_ops,
+	},
+	.probe	= micro_ts_probe,
+};
+module_platform_driver(micro_ts_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro touchscreen");
+MODULE_ALIAS("platform:ipaq-micro-ts");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/jornada720_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/jornada720_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/jornada720_ts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/jornada720_ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,22 +36,21 @@ struct jornada_ts {
 
 static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts)
 {
+	/* 3 low word X samples */
+	jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
+	jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
+	jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
 
-    /* 3 low word X samples */
-    jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
-    jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
-    jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
-
-    /* 3 low word Y samples */
-    jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
-    jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
-    jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
+	/* 3 low word Y samples */
+	jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
+	jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
+	jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
 
-    /* combined x samples bits */
-    jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
+	/* combined x samples bits */
+	jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
 
-    /* combined y samples bits */
-    jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
+	/* combined y samples bits */
+	jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
 }
 
 static int jornada720_ts_average(int coords[4])
@@ -104,13 +103,13 @@ static int jornada720_ts_probe(struct pl
 	struct input_dev *input_dev;
 	int error;
 
-	jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL);
-	input_dev = input_allocate_device();
+	jornada_ts = devm_kzalloc(&pdev->dev, sizeof(*jornada_ts), GFP_KERNEL);
+	if (!jornada_ts)
+		return -ENOMEM;
 
-	if (!jornada_ts || !input_dev) {
-		error = -ENOMEM;
-		goto fail1;
-	}
+	input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!input_dev)
+		return -ENOMEM;
 
 	platform_set_drvdata(pdev, jornada_ts);
 
@@ -126,36 +125,18 @@ static int jornada720_ts_probe(struct pl
 	input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0);
 	input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0);
 
-	error = request_irq(IRQ_GPIO9,
-			jornada720_ts_interrupt,
-			IRQF_TRIGGER_RISING,
-			"HP7XX Touchscreen driver", pdev);
+	error = devm_request_irq(&pdev->dev, IRQ_GPIO9,
+				 jornada720_ts_interrupt,
+				 IRQF_TRIGGER_RISING,
+				 "HP7XX Touchscreen driver", pdev);
 	if (error) {
-		printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
-		goto fail1;
+		dev_err(&pdev->dev, "HP7XX TS : Unable to acquire irq!\n");
+		return error;
 	}
 
 	error = input_register_device(jornada_ts->dev);
 	if (error)
-		goto fail2;
-
-	return 0;
-
- fail2:
-	free_irq(IRQ_GPIO9, pdev);
- fail1:
-	input_free_device(input_dev);
-	kfree(jornada_ts);
-	return error;
-}
-
-static int jornada720_ts_remove(struct platform_device *pdev)
-{
-	struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
-
-	free_irq(IRQ_GPIO9, pdev);
-	input_unregister_device(jornada_ts->dev);
-	kfree(jornada_ts);
+		return error;
 
 	return 0;
 }
@@ -165,7 +146,6 @@ MODULE_ALIAS("platform:jornada_ts");
 
 static struct platform_driver jornada720_ts_driver = {
 	.probe		= jornada720_ts_probe,
-	.remove		= jornada720_ts_remove,
 	.driver		= {
 		.name	= "jornada_ts",
 		.owner	= THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/Kconfig linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/Kconfig
--- linux-libre-3.16-gnu/drivers/input/touchscreen/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -471,6 +471,18 @@ config TOUCHSCREEN_HP7XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_ts.
 
+config TOUCHSCREEN_IPAQ_MICRO
+	tristate "HP iPAQ Atmel Micro ASIC touchscreen"
+	depends on MFD_IPAQ_MICRO
+	help
+	  Say Y here to enable support for the touchscreen attached to
+	  the Atmel Micro peripheral controller on iPAQ h3100/h3600/h3700
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ipaq-micro-ts.
+
 config TOUCHSCREEN_HTCPEN
 	tristate "HTC Shift X9500 touchscreen"
 	depends on ISA
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/Makefile linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/Makefile
--- linux-libre-3.16-gnu/drivers/input/touchscreen/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtou
 obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO)	+= ipaq-micro-ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/mcs5000_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/mcs5000_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/mcs5000_ts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/mcs5000_ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -248,8 +248,7 @@ static int mcs5000_ts_probe(struct i2c_c
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int mcs5000_ts_suspend(struct device *dev)
+static int __maybe_unused mcs5000_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -259,7 +258,7 @@ static int mcs5000_ts_suspend(struct dev
 	return 0;
 }
 
-static int mcs5000_ts_resume(struct device *dev)
+static int __maybe_unused mcs5000_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mcs5000_ts_data *data = i2c_get_clientdata(client);
@@ -269,7 +268,6 @@ static int mcs5000_ts_resume(struct devi
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/pixcir_i2c_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/pixcir_i2c_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/pixcir_i2c_ts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/pixcir_i2c_ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,22 +23,51 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+
+#define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
-	const struct pixcir_ts_platform_data *chip;
+	const struct pixcir_ts_platform_data *pdata;
 	bool running;
+	int max_fingers;	/* Max fingers supported in this instance */
 };
 
-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+struct pixcir_touch {
+	int x;
+	int y;
+	int id;
+};
+
+struct pixcir_report_data {
+	int num_touches;
+	struct pixcir_touch touches[PIXCIR_MAX_SLOTS];
+};
+
+static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
+			    struct pixcir_report_data *report)
 {
-	struct pixcir_i2c_ts_data *tsdata = data;
-	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
+	u8 wrbuf[1] = { 0 };
+	u8 *bufptr;
 	u8 touch;
-	int ret;
+	int ret, i;
+	int readsize;
+	const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
+
+	memset(report, 0, sizeof(struct pixcir_report_data));
+
+	i = chip->has_hw_ids ? 1 : 0;
+	readsize = 2 + tsdata->max_fingers * (4 + i);
+	if (readsize > sizeof(rdbuf))
+		readsize = sizeof(rdbuf);
 
 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
 	if (ret != sizeof(wrbuf)) {
@@ -48,7 +77,7 @@ static void pixcir_ts_poscheck(struct pi
 		return;
 	}
 
-	ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
 	if (ret != sizeof(rdbuf)) {
 		dev_err(&tsdata->client->dev,
 			"%s: i2c_master_recv failed(), ret=%d\n",
@@ -56,45 +85,103 @@ static void pixcir_ts_poscheck(struct pi
 		return;
 	}
 
-	touch = rdbuf[0];
-	if (touch) {
-		u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
-		u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
-		u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
-		u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
+	touch = rdbuf[0] & 0x7;
+	if (touch > tsdata->max_fingers)
+		touch = tsdata->max_fingers;
 
-		input_report_key(tsdata->input, BTN_TOUCH, 1);
-		input_report_abs(tsdata->input, ABS_X, posx1);
-		input_report_abs(tsdata->input, ABS_Y, posy1);
+	report->num_touches = touch;
+	bufptr = &rdbuf[2];
 
-		input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
-		input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
-		input_mt_sync(tsdata->input);
+	for (i = 0; i < touch; i++) {
+		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
+		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
 
-		if (touch == 2) {
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_X, posx2);
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_Y, posy2);
-			input_mt_sync(tsdata->input);
+		if (chip->has_hw_ids) {
+			report->touches[i].id = bufptr[4];
+			bufptr = bufptr + 5;
+		} else {
+			bufptr = bufptr + 4;
 		}
-	} else {
-		input_report_key(tsdata->input, BTN_TOUCH, 0);
 	}
+}
 
-	input_sync(tsdata->input);
+static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
+			     struct pixcir_report_data *report)
+{
+	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
+	int slots[PIXCIR_MAX_SLOTS];
+	struct pixcir_touch *touch;
+	int n, i, slot;
+	struct device *dev = &ts->client->dev;
+	const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
+
+	n = report->num_touches;
+	if (n > PIXCIR_MAX_SLOTS)
+		n = PIXCIR_MAX_SLOTS;
+
+	if (!chip->has_hw_ids) {
+		for (i = 0; i < n; i++) {
+			touch = &report->touches[i];
+			pos[i].x = touch->x;
+			pos[i].y = touch->y;
+		}
+
+		input_mt_assign_slots(ts->input, slots, pos, n);
+	}
+
+	for (i = 0; i < n; i++) {
+		touch = &report->touches[i];
+
+		if (chip->has_hw_ids) {
+			slot = input_mt_get_slot_by_key(ts->input, touch->id);
+			if (slot < 0) {
+				dev_dbg(dev, "no free slot for id 0x%x\n",
+					touch->id);
+				continue;
+			}
+		} else {
+			slot = slots[i];
+		}
+
+		input_mt_slot(ts->input, slot);
+		input_mt_report_slot_state(ts->input,
+					   MT_TOOL_FINGER, true);
+
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x);
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y);
+
+		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
+			i, slot, touch->x, touch->y);
+	}
+
+	input_mt_sync_frame(ts->input);
+	input_sync(ts->input);
 }
 
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
-	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+	const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
+	struct pixcir_report_data report;
 
 	while (tsdata->running) {
-		pixcir_ts_poscheck(tsdata);
+		/* parse packet */
+		pixcir_ts_parse(tsdata, &report);
 
-		if (gpio_get_value(pdata->gpio_attb))
+		/* report it */
+		pixcir_ts_report(tsdata, &report);
+
+		if (gpio_get_value(pdata->gpio_attb)) {
+			if (report.num_touches) {
+				/*
+				 * Last report with no finger up?
+				 * Do it now then.
+				 */
+				input_mt_sync_frame(tsdata->input);
+				input_sync(tsdata->input);
+			}
 			break;
+		}
 
 		msleep(20);
 	}
@@ -323,16 +410,69 @@ unlock:
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pixcir_of_match[];
+
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	struct pixcir_ts_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(pixcir_of_match), dev);
+	if (!match)
+		return ERR_PTR(-EINVAL);
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data;
+
+	pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0);
+	/* gpio_attb validity is checked in probe */
+
+	if (of_property_read_u32(np, "touchscreen-size-x", &pdata->x_max)) {
+		dev_err(dev, "Failed to get touchscreen-size-x property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->x_max -= 1;
+
+	if (of_property_read_u32(np, "touchscreen-size-y", &pdata->y_max)) {
+		dev_err(dev, "Failed to get touchscreen-size-y property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->y_max -= 1;
+
+	dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__,
+		pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb);
+
+	return pdata;
+}
+#else
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
 static int pixcir_i2c_ts_probe(struct i2c_client *client,
 					 const struct i2c_device_id *id)
 {
 	const struct pixcir_ts_platform_data *pdata =
 			dev_get_platdata(&client->dev);
 	struct device *dev = &client->dev;
+	struct device_node *np = dev->of_node;
 	struct pixcir_i2c_ts_data *tsdata;
 	struct input_dev *input;
 	int error;
 
+	if (np && !pdata) {
+		pdata = pixcir_parse_dt(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
+
 	if (!pdata) {
 		dev_err(&client->dev, "platform data not defined\n");
 		return -EINVAL;
@@ -343,6 +483,11 @@ static int pixcir_i2c_ts_probe(struct i2
 		return -EINVAL;
 	}
 
+	if (!pdata->chip.max_fingers) {
+		dev_err(dev, "Invalid max_fingers in pdata\n");
+		return -EINVAL;
+	}
+
 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
 	if (!tsdata)
 		return -ENOMEM;
@@ -355,7 +500,7 @@ static int pixcir_i2c_ts_probe(struct i2
 
 	tsdata->client = client;
 	tsdata->input = input;
-	tsdata->chip = pdata;
+	tsdata->pdata = pdata;
 
 	input->name = client->name;
 	input->id.bustype = BUS_I2C;
@@ -371,6 +516,20 @@ static int pixcir_i2c_ts_probe(struct i2
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
 
+	tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
+	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
+		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
+		dev_info(dev, "Limiting maximum fingers to %d\n",
+			 tsdata->max_fingers);
+	}
+
+	error = input_mt_init_slots(input, tsdata->max_fingers,
+				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (error) {
+		dev_err(dev, "Error initializing Multi-Touch slots\n");
+		return error;
+	}
+
 	input_set_drvdata(input, tsdata);
 
 	error = devm_gpio_request_one(dev, pdata->gpio_attb,
@@ -419,15 +578,36 @@ static int pixcir_i2c_ts_remove(struct i
 
 static const struct i2c_device_id pixcir_i2c_ts_id[] = {
 	{ "pixcir_ts", 0 },
+	{ "pixcir_tangoc", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
 
+#ifdef CONFIG_OF
+static const struct pixcir_i2c_chip_data pixcir_ts_data = {
+	.max_fingers = 2,
+	/* no hw id support */
+};
+
+static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
+	.max_fingers = 5,
+	.has_hw_ids = true,
+};
+
+static const struct of_device_id pixcir_of_match[] = {
+	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
+	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pixcir_of_match);
+#endif
+
 static struct i2c_driver pixcir_i2c_ts_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "pixcir_ts",
 		.pm	= &pixcir_dev_pm_ops,
+		.of_match_table = of_match_ptr(pixcir_of_match),
 	},
 	.probe		= pixcir_i2c_ts_probe,
 	.remove		= pixcir_i2c_ts_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/s3c2410_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/s3c2410_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/s3c2410_ts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/s3c2410_ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -264,7 +264,7 @@ static int s3c2410ts_probe(struct platfo
 		return -ENOENT;
 	}
 
-	clk_enable(ts.clock);
+	clk_prepare_enable(ts.clock);
 	dev_dbg(dev, "got and enabled clocks\n");
 
 	ts.irq_tc = ret = platform_get_irq(pdev, 0);
@@ -369,7 +369,7 @@ static int s3c2410ts_remove(struct platf
 	free_irq(ts.irq_tc, ts.input);
 	del_timer_sync(&touch_timer);
 
-	clk_disable(ts.clock);
+	clk_disable_unprepare(ts.clock);
 	clk_put(ts.clock);
 
 	input_unregister_device(ts.input);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/wm9712.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/wm9712.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/wm9712.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/wm9712.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
  */
 static int rpu = 8;
 module_param(rpu, int, 0);
-MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
 
 /*
  * Set current used for pressure measurement.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/wm9713.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/wm9713.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/wm9713.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/wm9713.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
  */
 static int rpu = 8;
 module_param(rpu, int, 0);
-MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
 
 /*
  * Set current used for pressure measurement.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/input/touchscreen/zforce_ts.c linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/zforce_ts.c
--- linux-libre-3.16-gnu/drivers/input/touchscreen/zforce_ts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/input/touchscreen/zforce_ts.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,8 @@
 #include <linux/sysfs.h>
 #include <linux/input/mt.h>
 #include <linux/platform_data/zforce_ts.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
@@ -117,6 +119,8 @@ struct zforce_ts {
 	const struct zforce_ts_platdata *pdata;
 	char			phys[32];
 
+	struct regulator	*reg_vdd;
+
 	bool			suspending;
 	bool			suspended;
 	bool			boot_complete;
@@ -690,6 +694,11 @@ static void zforce_reset(void *data)
 	struct zforce_ts *ts = data;
 
 	gpio_set_value(ts->pdata->gpio_rst, 0);
+
+	udelay(10);
+
+	if (!IS_ERR(ts->reg_vdd))
+		regulator_disable(ts->reg_vdd);
 }
 
 static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
@@ -765,10 +774,32 @@ static int zforce_probe(struct i2c_clien
 		return ret;
 	}
 
+	ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");
+	if (IS_ERR(ts->reg_vdd)) {
+		ret = PTR_ERR(ts->reg_vdd);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+	} else {
+		ret = regulator_enable(ts->reg_vdd);
+		if (ret)
+			return ret;
+
+		/*
+		 * according to datasheet add 100us grace time after regular
+		 * regulator enable delay.
+		 */
+		udelay(100);
+	}
+
 	ret = devm_add_action(&client->dev, zforce_reset, ts);
 	if (ret) {
 		dev_err(&client->dev, "failed to register reset action, %d\n",
 			ret);
+
+		/* hereafter the regulator will be disabled by the action */
+		if (!IS_ERR(ts->reg_vdd))
+			regulator_disable(ts->reg_vdd);
+
 		return ret;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/amd_iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/amd_iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,6 @@
 #include "amd_iommu_proto.h"
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
-#include "pci.h"
 
 #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
 
@@ -81,7 +80,7 @@ LIST_HEAD(hpet_map);
  */
 static struct protection_domain *pt_domain;
 
-static struct iommu_ops amd_iommu_ops;
+static const struct iommu_ops amd_iommu_ops;
 
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
@@ -133,9 +132,6 @@ static void free_dev_data(struct iommu_d
 	list_del(&dev_data->dev_data_list);
 	spin_unlock_irqrestore(&dev_data_list_lock, flags);
 
-	if (dev_data->group)
-		iommu_group_put(dev_data->group);
-
 	kfree(dev_data);
 }
 
@@ -264,167 +260,79 @@ static bool check_device(struct device *
 	return true;
 }
 
-static struct pci_bus *find_hosted_bus(struct pci_bus *bus)
-{
-	while (!bus->self) {
-		if (!pci_is_root_bus(bus))
-			bus = bus->parent;
-		else
-			return ERR_PTR(-ENODEV);
-	}
-
-	return bus;
-}
-
-#define REQ_ACS_FLAGS	(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
-static struct pci_dev *get_isolation_root(struct pci_dev *pdev)
-{
-	struct pci_dev *dma_pdev = pdev;
-
-	/* Account for quirked devices */
-	swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
-
-	/*
-	 * If it's a multifunction device that does not support our
-	 * required ACS flags, add to the same group as lowest numbered
-	 * function that also does not suport the required ACS flags.
-	 */
-	if (dma_pdev->multifunction &&
-	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
-		u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
-		for (i = 0; i < 8; i++) {
-			struct pci_dev *tmp;
-
-			tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
-			if (!tmp)
-				continue;
-
-			if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
-				swap_pci_ref(&dma_pdev, tmp);
-				break;
-			}
-			pci_dev_put(tmp);
-		}
-	}
-
-	/*
-	 * Devices on the root bus go through the iommu.  If that's not us,
-	 * find the next upstream device and test ACS up to the root bus.
-	 * Finding the next device may require skipping virtual buses.
-	 */
-	while (!pci_is_root_bus(dma_pdev->bus)) {
-		struct pci_bus *bus = find_hosted_bus(dma_pdev->bus);
-		if (IS_ERR(bus))
-			break;
-
-		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
-			break;
-
-		swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
-	}
-
-	return dma_pdev;
-}
-
-static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev)
+static int init_iommu_group(struct device *dev)
 {
-	struct iommu_group *group = iommu_group_get(&pdev->dev);
-	int ret;
+	struct iommu_group *group;
 
-	if (!group) {
-		group = iommu_group_alloc();
-		if (IS_ERR(group))
-			return PTR_ERR(group);
+	group = iommu_group_get_for_dev(dev);
 
-		WARN_ON(&pdev->dev != dev);
-	}
+	if (IS_ERR(group))
+		return PTR_ERR(group);
 
-	ret = iommu_group_add_device(group, dev);
 	iommu_group_put(group);
-	return ret;
+	return 0;
 }
 
-static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data,
-				    struct device *dev)
+static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
-	if (!dev_data->group) {
-		struct iommu_group *group = iommu_group_alloc();
-		if (IS_ERR(group))
-			return PTR_ERR(group);
-
-		dev_data->group = group;
-	}
-
-	return iommu_group_add_device(dev_data->group, dev);
+	*(u16 *)data = alias;
+	return 0;
 }
 
-static int init_iommu_group(struct device *dev)
+static u16 get_alias(struct device *dev)
 {
-	struct iommu_dev_data *dev_data;
-	struct iommu_group *group;
-	struct pci_dev *dma_pdev;
-	int ret;
-
-	group = iommu_group_get(dev);
-	if (group) {
-		iommu_group_put(group);
-		return 0;
-	}
-
-	dev_data = find_dev_data(get_device_id(dev));
-	if (!dev_data)
-		return -ENOMEM;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	u16 devid, ivrs_alias, pci_alias;
 
-	if (dev_data->alias_data) {
-		u16 alias;
-		struct pci_bus *bus;
+	devid = get_device_id(dev);
+	ivrs_alias = amd_iommu_alias_table[devid];
+	pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
 
-		if (dev_data->alias_data->group)
-			goto use_group;
+	if (ivrs_alias == pci_alias)
+		return ivrs_alias;
 
-		/*
-		 * If the alias device exists, it's effectively just a first
-		 * level quirk for finding the DMA source.
-		 */
-		alias = amd_iommu_alias_table[dev_data->devid];
-		dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
-		if (dma_pdev) {
-			dma_pdev = get_isolation_root(dma_pdev);
-			goto use_pdev;
+	/*
+	 * DMA alias showdown
+	 *
+	 * The IVRS is fairly reliable in telling us about aliases, but it
+	 * can't know about every screwy device.  If we don't have an IVRS
+	 * reported alias, use the PCI reported alias.  In that case we may
+	 * still need to initialize the rlookup and dev_table entries if the
+	 * alias is to a non-existent device.
+	 */
+	if (ivrs_alias == devid) {
+		if (!amd_iommu_rlookup_table[pci_alias]) {
+			amd_iommu_rlookup_table[pci_alias] =
+				amd_iommu_rlookup_table[devid];
+			memcpy(amd_iommu_dev_table[pci_alias].data,
+			       amd_iommu_dev_table[devid].data,
+			       sizeof(amd_iommu_dev_table[pci_alias].data));
 		}
 
-		/*
-		 * If the alias is virtual, try to find a parent device
-		 * and test whether the IOMMU group is actualy rooted above
-		 * the alias.  Be careful to also test the parent device if
-		 * we think the alias is the root of the group.
-		 */
-		bus = pci_find_bus(0, alias >> 8);
-		if (!bus)
-			goto use_group;
-
-		bus = find_hosted_bus(bus);
-		if (IS_ERR(bus) || !bus->self)
-			goto use_group;
+		return pci_alias;
+	}
 
-		dma_pdev = get_isolation_root(pci_dev_get(bus->self));
-		if (dma_pdev != bus->self || (dma_pdev->multifunction &&
-		    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)))
-			goto use_pdev;
+	pr_info("AMD-Vi: Using IVRS reported alias %02x:%02x.%d "
+		"for device %s[%04x:%04x], kernel reported alias "
+		"%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
+		PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device,
+		PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
+		PCI_FUNC(pci_alias));
 
-		pci_dev_put(dma_pdev);
-		goto use_group;
+	/*
+	 * If we don't have a PCI DMA alias and the IVRS alias is on the same
+	 * bus, then the IVRS table may know about a quirk that we don't.
+	 */
+	if (pci_alias == devid &&
+	    PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
+		pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
+		pdev->dma_alias_devfn = ivrs_alias & 0xff;
+		pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
+			PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
+			dev_name(dev));
 	}
 
-	dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
-use_pdev:
-	ret = use_pdev_iommu_group(dma_pdev, dev);
-	pci_dev_put(dma_pdev);
-	return ret;
-use_group:
-	return use_dev_data_iommu_group(dev_data->alias_data, dev);
+	return ivrs_alias;
 }
 
 static int iommu_init_device(struct device *dev)
@@ -441,7 +349,8 @@ static int iommu_init_device(struct devi
 	if (!dev_data)
 		return -ENOMEM;
 
-	alias = amd_iommu_alias_table[dev_data->devid];
+	alias = get_alias(dev);
+
 	if (alias != dev_data->devid) {
 		struct iommu_dev_data *alias_data;
 
@@ -470,6 +379,9 @@ static int iommu_init_device(struct devi
 
 	dev->archdata.iommu = dev_data;
 
+	iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
+			  dev);
+
 	return 0;
 }
 
@@ -489,12 +401,22 @@ static void iommu_ignore_device(struct d
 
 static void iommu_uninit_device(struct device *dev)
 {
+	struct iommu_dev_data *dev_data = search_dev_data(get_device_id(dev));
+
+	if (!dev_data)
+		return;
+
+	iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
+			    dev);
+
 	iommu_group_remove_device(dev);
 
+	/* Unlink from alias, it may change if another device is re-plugged */
+	dev_data->alias_data = NULL;
+
 	/*
-	 * Nothing to do here - we keep dev_data around for unplugged devices
-	 * and reuse it when the device is re-plugged - not doing so would
-	 * introduce a ton of races.
+	 * We keep dev_data around for unplugged devices and reuse it when the
+	 * device is re-plugged - not doing so would introduce a ton of races.
 	 */
 }
 
@@ -3227,14 +3149,16 @@ free_domains:
 
 static void cleanup_domain(struct protection_domain *domain)
 {
-	struct iommu_dev_data *dev_data, *next;
+	struct iommu_dev_data *entry;
 	unsigned long flags;
 
 	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
 
-	list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
-		__detach_device(dev_data);
-		atomic_set(&dev_data->bind, 0);
+	while (!list_empty(&domain->dev_list)) {
+		entry = list_first_entry(&domain->dev_list,
+					 struct iommu_dev_data, list);
+		__detach_device(entry);
+		atomic_set(&entry->bind, 0);
 	}
 
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
@@ -3473,7 +3397,7 @@ static int amd_iommu_domain_has_cap(stru
 	return 0;
 }
 
-static struct iommu_ops amd_iommu_ops = {
+static const struct iommu_ops amd_iommu_ops = {
 	.domain_init = amd_iommu_domain_init,
 	.domain_destroy = amd_iommu_domain_destroy,
 	.attach_dev = amd_iommu_attach_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/amd_iommu_init.c linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_init.c
--- linux-libre-3.16-gnu/drivers/iommu/amd_iommu_init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/msi.h>
 #include <linux/amd-iommu.h>
 #include <linux/export.h>
+#include <linux/iommu.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
@@ -1197,6 +1198,39 @@ static void init_iommu_perf_ctr(struct a
 	iommu->max_counters = (u8) ((val >> 7) & 0xf);
 }
 
+static ssize_t amd_iommu_show_cap(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct amd_iommu *iommu = dev_get_drvdata(dev);
+	return sprintf(buf, "%x\n", iommu->cap);
+}
+static DEVICE_ATTR(cap, S_IRUGO, amd_iommu_show_cap, NULL);
+
+static ssize_t amd_iommu_show_features(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct amd_iommu *iommu = dev_get_drvdata(dev);
+	return sprintf(buf, "%llx\n", iommu->features);
+}
+static DEVICE_ATTR(features, S_IRUGO, amd_iommu_show_features, NULL);
+
+static struct attribute *amd_iommu_attrs[] = {
+	&dev_attr_cap.attr,
+	&dev_attr_features.attr,
+	NULL,
+};
+
+static struct attribute_group amd_iommu_group = {
+	.name = "amd-iommu",
+	.attrs = amd_iommu_attrs,
+};
+
+static const struct attribute_group *amd_iommu_groups[] = {
+	&amd_iommu_group,
+	NULL,
+};
 
 static int iommu_init_pci(struct amd_iommu *iommu)
 {
@@ -1297,6 +1331,10 @@ static int iommu_init_pci(struct amd_iom
 
 	amd_iommu_erratum_746_workaround(iommu);
 
+	iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
+					       amd_iommu_groups, "ivhd%d",
+					       iommu->index);
+
 	return pci_enable_device(iommu->dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/amd_iommu_types.h linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_types.h
--- linux-libre-3.16-gnu/drivers/iommu/amd_iommu_types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_types.h	2014-09-28 17:29:07.000000000 -0400
@@ -390,12 +390,6 @@ struct amd_iommu_fault {
 
 };
 
-#define PPR_FAULT_EXEC	(1 << 1)
-#define PPR_FAULT_READ  (1 << 2)
-#define PPR_FAULT_WRITE (1 << 5)
-#define PPR_FAULT_USER  (1 << 6)
-#define PPR_FAULT_RSVD  (1 << 7)
-#define PPR_FAULT_GN    (1 << 8)
 
 struct iommu_domain;
 
@@ -432,7 +426,6 @@ struct iommu_dev_data {
 	struct iommu_dev_data *alias_data;/* The alias dev_data */
 	struct protection_domain *domain; /* Domain the device is bound to */
 	atomic_t bind;			  /* Domain attach reference count */
-	struct iommu_group *group;	  /* IOMMU group for virtual aliases */
 	u16 devid;			  /* PCI Device ID */
 	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
 	bool passthrough;		  /* Default for device is pt_domain */
@@ -578,6 +571,9 @@ struct amd_iommu {
 	/* default dma_ops domain for that IOMMU */
 	struct dma_ops_domain *default_dom;
 
+	/* IOMMU sysfs device */
+	struct device *iommu_dev;
+
 	/*
 	 * We can't rely on the BIOS to restore all values on reinit, so we
 	 * need to stash them
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/amd_iommu_v2.c linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_v2.c
--- linux-libre-3.16-gnu/drivers/iommu/amd_iommu_v2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/amd_iommu_v2.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,12 +47,13 @@ struct pasid_state {
 	atomic_t count;				/* Reference count */
 	unsigned mmu_notifier_count;		/* Counting nested mmu_notifier
 						   calls */
-	struct task_struct *task;		/* Task bound to this PASID */
 	struct mm_struct *mm;			/* mm_struct for the faults */
-	struct mmu_notifier mn;                 /* mmu_otifier handle */
+	struct mmu_notifier mn;                 /* mmu_notifier handle */
 	struct pri_queue pri[PRI_QUEUE_SIZE];	/* PRI tag states */
 	struct device_state *device_state;	/* Link to our device_state */
 	int pasid;				/* PASID index */
+	bool invalid;				/* Used during setup and
+						   teardown of the pasid */
 	spinlock_t lock;			/* Protect pri_queues and
 						   mmu_notifer_count */
 	wait_queue_head_t wq;			/* To wait for count == 0 */
@@ -99,7 +100,6 @@ static struct workqueue_struct *iommu_wq
 static u64 *empty_page_table;
 
 static void free_pasid_states(struct device_state *dev_state);
-static void unbind_pasid(struct device_state *dev_state, int pasid);
 
 static u16 device_id(struct pci_dev *pdev)
 {
@@ -297,37 +297,29 @@ static void put_pasid_state_wait(struct
 		schedule();
 
 	finish_wait(&pasid_state->wq, &wait);
-	mmput(pasid_state->mm);
 	free_pasid_state(pasid_state);
 }
 
-static void __unbind_pasid(struct pasid_state *pasid_state)
+static void unbind_pasid(struct pasid_state *pasid_state)
 {
 	struct iommu_domain *domain;
 
 	domain = pasid_state->device_state->domain;
 
+	/*
+	 * Mark pasid_state as invalid, no more faults will we added to the
+	 * work queue after this is visible everywhere.
+	 */
+	pasid_state->invalid = true;
+
+	/* Make sure this is visible */
+	smp_wmb();
+
+	/* After this the device/pasid can't access the mm anymore */
 	amd_iommu_domain_clear_gcr3(domain, pasid_state->pasid);
-	clear_pasid_state(pasid_state->device_state, pasid_state->pasid);
 
 	/* Make sure no more pending faults are in the queue */
 	flush_workqueue(iommu_wq);
-
-	mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
-
-	put_pasid_state(pasid_state); /* Reference taken in bind() function */
-}
-
-static void unbind_pasid(struct device_state *dev_state, int pasid)
-{
-	struct pasid_state *pasid_state;
-
-	pasid_state = get_pasid_state(dev_state, pasid);
-	if (pasid_state == NULL)
-		return;
-
-	__unbind_pasid(pasid_state);
-	put_pasid_state_wait(pasid_state); /* Reference taken in this function */
 }
 
 static void free_pasid_states_level1(struct pasid_state **tbl)
@@ -373,6 +365,12 @@ static void free_pasid_states(struct dev
 		 * unbind the PASID
 		 */
 		mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
+
+		put_pasid_state_wait(pasid_state); /* Reference taken in
+						      amd_iommu_bind_pasid */
+
+		/* Drop reference taken in amd_iommu_bind_pasid */
+		put_device_state(dev_state);
 	}
 
 	if (dev_state->pasid_levels == 2)
@@ -411,14 +409,6 @@ static int mn_clear_flush_young(struct m
 	return 0;
 }
 
-static void mn_change_pte(struct mmu_notifier *mn,
-			  struct mm_struct *mm,
-			  unsigned long address,
-			  pte_t pte)
-{
-	__mn_flush_page(mn, address);
-}
-
 static void mn_invalidate_page(struct mmu_notifier *mn,
 			       struct mm_struct *mm,
 			       unsigned long address)
@@ -472,22 +462,23 @@ static void mn_release(struct mmu_notifi
 {
 	struct pasid_state *pasid_state;
 	struct device_state *dev_state;
+	bool run_inv_ctx_cb;
 
 	might_sleep();
 
-	pasid_state = mn_to_state(mn);
-	dev_state   = pasid_state->device_state;
+	pasid_state    = mn_to_state(mn);
+	dev_state      = pasid_state->device_state;
+	run_inv_ctx_cb = !pasid_state->invalid;
 
-	if (pasid_state->device_state->inv_ctx_cb)
+	if (run_inv_ctx_cb && pasid_state->device_state->inv_ctx_cb)
 		dev_state->inv_ctx_cb(dev_state->pdev, pasid_state->pasid);
 
-	unbind_pasid(dev_state, pasid_state->pasid);
+	unbind_pasid(pasid_state);
 }
 
 static struct mmu_notifier_ops iommu_mn = {
 	.release		= mn_release,
 	.clear_flush_young      = mn_clear_flush_young,
-	.change_pte             = mn_change_pte,
 	.invalidate_page        = mn_invalidate_page,
 	.invalidate_range_start = mn_invalidate_range_start,
 	.invalidate_range_end   = mn_invalidate_range_end,
@@ -529,7 +520,7 @@ static void do_fault(struct work_struct
 	write = !!(fault->flags & PPR_FAULT_WRITE);
 
 	down_read(&fault->state->mm->mmap_sem);
-	npages = get_user_pages(fault->state->task, fault->state->mm,
+	npages = get_user_pages(NULL, fault->state->mm,
 				fault->address, 1, write, 0, &page, NULL);
 	up_read(&fault->state->mm->mmap_sem);
 
@@ -587,7 +578,7 @@ static int ppr_notifier(struct notifier_
 		goto out;
 
 	pasid_state = get_pasid_state(dev_state, iommu_fault->pasid);
-	if (pasid_state == NULL) {
+	if (pasid_state == NULL || pasid_state->invalid) {
 		/* We know the device but not the PASID -> send INVALID */
 		amd_iommu_complete_ppr(dev_state->pdev, iommu_fault->pasid,
 				       PPR_INVALID, tag);
@@ -612,6 +603,7 @@ static int ppr_notifier(struct notifier_
 	fault->state     = pasid_state;
 	fault->tag       = tag;
 	fault->finish    = finish;
+	fault->pasid     = iommu_fault->pasid;
 	fault->flags     = iommu_fault->flags;
 	INIT_WORK(&fault->work, do_fault);
 
@@ -620,6 +612,10 @@ static int ppr_notifier(struct notifier_
 	ret = NOTIFY_OK;
 
 out_drop_state:
+
+	if (ret != NOTIFY_OK && pasid_state)
+		put_pasid_state(pasid_state);
+
 	put_device_state(dev_state);
 
 out:
@@ -635,6 +631,7 @@ int amd_iommu_bind_pasid(struct pci_dev
 {
 	struct pasid_state *pasid_state;
 	struct device_state *dev_state;
+	struct mm_struct *mm;
 	u16 devid;
 	int ret;
 
@@ -658,20 +655,23 @@ int amd_iommu_bind_pasid(struct pci_dev
 	if (pasid_state == NULL)
 		goto out;
 
+
 	atomic_set(&pasid_state->count, 1);
 	init_waitqueue_head(&pasid_state->wq);
 	spin_lock_init(&pasid_state->lock);
 
-	pasid_state->task         = task;
-	pasid_state->mm           = get_task_mm(task);
+	mm                        = get_task_mm(task);
+	pasid_state->mm           = mm;
 	pasid_state->device_state = dev_state;
 	pasid_state->pasid        = pasid;
+	pasid_state->invalid      = true; /* Mark as valid only if we are
+					     done with setting up the pasid */
 	pasid_state->mn.ops       = &iommu_mn;
 
 	if (pasid_state->mm == NULL)
 		goto out_free;
 
-	mmu_notifier_register(&pasid_state->mn, pasid_state->mm);
+	mmu_notifier_register(&pasid_state->mn, mm);
 
 	ret = set_pasid_state(dev_state, pasid_state, pasid);
 	if (ret)
@@ -682,15 +682,26 @@ int amd_iommu_bind_pasid(struct pci_dev
 	if (ret)
 		goto out_clear_state;
 
+	/* Now we are ready to handle faults */
+	pasid_state->invalid = false;
+
+	/*
+	 * Drop the reference to the mm_struct here. We rely on the
+	 * mmu_notifier release call-back to inform us when the mm
+	 * is going away.
+	 */
+	mmput(mm);
+
 	return 0;
 
 out_clear_state:
 	clear_pasid_state(dev_state, pasid);
 
 out_unregister:
-	mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
+	mmu_notifier_unregister(&pasid_state->mn, mm);
 
 out_free:
+	mmput(mm);
 	free_pasid_state(pasid_state);
 
 out:
@@ -728,10 +739,22 @@ void amd_iommu_unbind_pasid(struct pci_d
 	 */
 	put_pasid_state(pasid_state);
 
-	/* This will call the mn_release function and unbind the PASID */
+	/* Clear the pasid state so that the pasid can be re-used */
+	clear_pasid_state(dev_state, pasid_state->pasid);
+
+	/*
+	 * Call mmu_notifier_unregister to drop our reference
+	 * to pasid_state->mm
+	 */
 	mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
 
+	put_pasid_state_wait(pasid_state); /* Reference taken in
+					      amd_iommu_bind_pasid */
 out:
+	/* Drop reference taken in this function */
+	put_device_state(dev_state);
+
+	/* Drop reference taken in amd_iommu_bind_pasid */
 	put_device_state(dev_state);
 }
 EXPORT_SYMBOL(amd_iommu_unbind_pasid);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/arm-smmu.c linux-libre-3.17-rc7-gnu/drivers/iommu/arm-smmu.c
--- linux-libre-3.16-gnu/drivers/iommu/arm-smmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/arm-smmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -145,6 +146,8 @@
 #define ID0_CTTW			(1 << 14)
 #define ID0_NUMIRPT_SHIFT		16
 #define ID0_NUMIRPT_MASK		0xff
+#define ID0_NUMSIDB_SHIFT		9
+#define ID0_NUMSIDB_MASK		0xf
 #define ID0_NUMSMRG_SHIFT		0
 #define ID0_NUMSMRG_MASK		0xff
 
@@ -316,9 +319,9 @@
 #define FSR_AFF				(1 << 2)
 #define FSR_TF				(1 << 1)
 
-#define FSR_IGN				(FSR_AFF | FSR_ASF | FSR_TLBMCF |	\
-					 FSR_TLBLKF)
-#define FSR_FAULT			(FSR_MULTI | FSR_SS | FSR_UUT |		\
+#define FSR_IGN				(FSR_AFF | FSR_ASF | \
+					 FSR_TLBMCF | FSR_TLBLKF)
+#define FSR_FAULT			(FSR_MULTI | FSR_SS | FSR_UUT | \
 					 FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
 
 #define FSYNR0_WNR			(1 << 4)
@@ -329,27 +332,20 @@ struct arm_smmu_smr {
 	u16				id;
 };
 
-struct arm_smmu_master {
-	struct device_node		*of_node;
-
-	/*
-	 * The following is specific to the master's position in the
-	 * SMMU chain.
-	 */
-	struct rb_node			node;
+struct arm_smmu_master_cfg {
 	int				num_streamids;
 	u16				streamids[MAX_MASTER_STREAMIDS];
-
-	/*
-	 * We only need to allocate these on the root SMMU, as we
-	 * configure unmatched streams to bypass translation.
-	 */
 	struct arm_smmu_smr		*smrs;
 };
 
+struct arm_smmu_master {
+	struct device_node		*of_node;
+	struct rb_node			node;
+	struct arm_smmu_master_cfg	cfg;
+};
+
 struct arm_smmu_device {
 	struct device			*dev;
-	struct device_node		*parent_of_node;
 
 	void __iomem			*base;
 	unsigned long			size;
@@ -387,7 +383,6 @@ struct arm_smmu_device {
 };
 
 struct arm_smmu_cfg {
-	struct arm_smmu_device		*smmu;
 	u8				cbndx;
 	u8				irptndx;
 	u32				cbar;
@@ -399,15 +394,8 @@ struct arm_smmu_cfg {
 #define ARM_SMMU_CB_VMID(cfg)		((cfg)->cbndx + 1)
 
 struct arm_smmu_domain {
-	/*
-	 * A domain can span across multiple, chained SMMUs and requires
-	 * all devices within the domain to follow the same translation
-	 * path.
-	 */
-	struct arm_smmu_device		*leaf_smmu;
-	struct arm_smmu_cfg		root_cfg;
-	phys_addr_t			output_mask;
-
+	struct arm_smmu_device		*smmu;
+	struct arm_smmu_cfg		cfg;
 	spinlock_t			lock;
 };
 
@@ -419,7 +407,7 @@ struct arm_smmu_option_prop {
 	const char *prop;
 };
 
-static struct arm_smmu_option_prop arm_smmu_options [] = {
+static struct arm_smmu_option_prop arm_smmu_options[] = {
 	{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
 	{ 0, NULL},
 };
@@ -427,6 +415,7 @@ static struct arm_smmu_option_prop arm_s
 static void parse_driver_options(struct arm_smmu_device *smmu)
 {
 	int i = 0;
+
 	do {
 		if (of_property_read_bool(smmu->dev->of_node,
 						arm_smmu_options[i].prop)) {
@@ -437,6 +426,19 @@ static void parse_driver_options(struct
 	} while (arm_smmu_options[++i].opt);
 }
 
+static struct device *dev_get_master_dev(struct device *dev)
+{
+	if (dev_is_pci(dev)) {
+		struct pci_bus *bus = to_pci_dev(dev)->bus;
+
+		while (!pci_is_root_bus(bus))
+			bus = bus->parent;
+		return bus->bridge->parent;
+	}
+
+	return dev;
+}
+
 static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
 						struct device_node *dev_node)
 {
@@ -444,6 +446,7 @@ static struct arm_smmu_master *find_smmu
 
 	while (node) {
 		struct arm_smmu_master *master;
+
 		master = container_of(node, struct arm_smmu_master, node);
 
 		if (dev_node < master->of_node)
@@ -457,6 +460,18 @@ static struct arm_smmu_master *find_smmu
 	return NULL;
 }
 
+static struct arm_smmu_master_cfg *
+find_smmu_master_cfg(struct arm_smmu_device *smmu, struct device *dev)
+{
+	struct arm_smmu_master *master;
+
+	if (dev_is_pci(dev))
+		return dev->archdata.iommu;
+
+	master = find_smmu_master(smmu, dev->of_node);
+	return master ? &master->cfg : NULL;
+}
+
 static int insert_smmu_master(struct arm_smmu_device *smmu,
 			      struct arm_smmu_master *master)
 {
@@ -465,8 +480,8 @@ static int insert_smmu_master(struct arm
 	new = &smmu->masters.rb_node;
 	parent = NULL;
 	while (*new) {
-		struct arm_smmu_master *this;
-		this = container_of(*new, struct arm_smmu_master, node);
+		struct arm_smmu_master *this
+			= container_of(*new, struct arm_smmu_master, node);
 
 		parent = *new;
 		if (master->of_node < this->of_node)
@@ -508,33 +523,39 @@ static int register_smmu_master(struct a
 	if (!master)
 		return -ENOMEM;
 
-	master->of_node		= masterspec->np;
-	master->num_streamids	= masterspec->args_count;
+	master->of_node			= masterspec->np;
+	master->cfg.num_streamids	= masterspec->args_count;
 
-	for (i = 0; i < master->num_streamids; ++i)
-		master->streamids[i] = masterspec->args[i];
+	for (i = 0; i < master->cfg.num_streamids; ++i) {
+		u16 streamid = masterspec->args[i];
 
+		if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
+		     (streamid >= smmu->num_mapping_groups)) {
+			dev_err(dev,
+				"stream ID for master device %s greater than maximum allowed (%d)\n",
+				masterspec->np->name, smmu->num_mapping_groups);
+			return -ERANGE;
+		}
+		master->cfg.streamids[i] = streamid;
+	}
 	return insert_smmu_master(smmu, master);
 }
 
-static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
 {
-	struct arm_smmu_device *parent;
-
-	if (!smmu->parent_of_node)
-		return NULL;
+	struct arm_smmu_device *smmu;
+	struct arm_smmu_master *master = NULL;
+	struct device_node *dev_node = dev_get_master_dev(dev)->of_node;
 
 	spin_lock(&arm_smmu_devices_lock);
-	list_for_each_entry(parent, &arm_smmu_devices, list)
-		if (parent->dev->of_node == smmu->parent_of_node)
-			goto out_unlock;
-
-	parent = NULL;
-	dev_warn(smmu->dev,
-		 "Failed to find SMMU parent despite parent in DT\n");
-out_unlock:
+	list_for_each_entry(smmu, &arm_smmu_devices, list) {
+		master = find_smmu_master(smmu, dev_node);
+		if (master)
+			break;
+	}
 	spin_unlock(&arm_smmu_devices_lock);
-	return parent;
+
+	return master ? smmu : NULL;
 }
 
 static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
@@ -574,9 +595,10 @@ static void arm_smmu_tlb_sync(struct arm
 	}
 }
 
-static void arm_smmu_tlb_inv_context(struct arm_smmu_cfg *cfg)
+static void arm_smmu_tlb_inv_context(struct arm_smmu_domain *smmu_domain)
 {
-	struct arm_smmu_device *smmu = cfg->smmu;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	void __iomem *base = ARM_SMMU_GR0(smmu);
 	bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
 
@@ -600,11 +622,11 @@ static irqreturn_t arm_smmu_context_faul
 	unsigned long iova;
 	struct iommu_domain *domain = dev;
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	struct arm_smmu_device *smmu = root_cfg->smmu;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	void __iomem *cb_base;
 
-	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 	fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
 
 	if (!(fsr & FSR_FAULT))
@@ -612,7 +634,7 @@ static irqreturn_t arm_smmu_context_faul
 
 	if (fsr & FSR_IGN)
 		dev_err_ratelimited(smmu->dev,
-				    "Unexpected context fault (fsr 0x%u)\n",
+				    "Unexpected context fault (fsr 0x%x)\n",
 				    fsr);
 
 	fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
@@ -631,7 +653,7 @@ static irqreturn_t arm_smmu_context_faul
 	} else {
 		dev_err_ratelimited(smmu->dev,
 		    "Unhandled context fault: iova=0x%08lx, fsynr=0x%x, cb=%d\n",
-		    iova, fsynr, root_cfg->cbndx);
+		    iova, fsynr, cfg->cbndx);
 		ret = IRQ_NONE;
 		resume = RESUME_TERMINATE;
 	}
@@ -696,19 +718,19 @@ static void arm_smmu_init_context_bank(s
 {
 	u32 reg;
 	bool stage1;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	struct arm_smmu_device *smmu = root_cfg->smmu;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	void __iomem *cb_base, *gr0_base, *gr1_base;
 
 	gr0_base = ARM_SMMU_GR0(smmu);
 	gr1_base = ARM_SMMU_GR1(smmu);
-	stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS;
-	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+	stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
+	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 
 	/* CBAR */
-	reg = root_cfg->cbar;
+	reg = cfg->cbar;
 	if (smmu->version == 1)
-	      reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
+		reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
 
 	/*
 	 * Use the weakest shareability/memory types, so they are
@@ -718,9 +740,9 @@ static void arm_smmu_init_context_bank(s
 		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
 			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
 	} else {
-		reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+		reg |= ARM_SMMU_CB_VMID(cfg) << CBAR_VMID_SHIFT;
 	}
-	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
+	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
 
 	if (smmu->version > 1) {
 		/* CBA2R */
@@ -730,7 +752,7 @@ static void arm_smmu_init_context_bank(s
 		reg = CBA2R_RW64_32BIT;
 #endif
 		writel_relaxed(reg,
-			       gr1_base + ARM_SMMU_GR1_CBA2R(root_cfg->cbndx));
+			       gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
 
 		/* TTBCR2 */
 		switch (smmu->input_size) {
@@ -741,6 +763,7 @@ static void arm_smmu_init_context_bank(s
 			reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
 			break;
 		case 39:
+		case 40:
 			reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
 			break;
 		case 42:
@@ -762,6 +785,7 @@ static void arm_smmu_init_context_bank(s
 			reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT);
 			break;
 		case 39:
+		case 40:
 			reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT);
 			break;
 		case 42:
@@ -780,13 +804,13 @@ static void arm_smmu_init_context_bank(s
 	}
 
 	/* TTBR0 */
-	arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+	arm_smmu_flush_pgtable(smmu, cfg->pgd,
 			       PTRS_PER_PGD * sizeof(pgd_t));
-	reg = __pa(root_cfg->pgd);
+	reg = __pa(cfg->pgd);
 	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
-	reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
+	reg = (phys_addr_t)__pa(cfg->pgd) >> 32;
 	if (stage1)
-		reg |= ARM_SMMU_CB_ASID(root_cfg) << TTBRn_HI_ASID_SHIFT;
+		reg |= ARM_SMMU_CB_ASID(cfg) << TTBRn_HI_ASID_SHIFT;
 	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI);
 
 	/*
@@ -800,6 +824,8 @@ static void arm_smmu_init_context_bank(s
 			reg = TTBCR_TG0_64K;
 
 		if (!stage1) {
+			reg |= (64 - smmu->s1_output_size) << TTBCR_T0SZ_SHIFT;
+
 			switch (smmu->s2_output_size) {
 			case 32:
 				reg |= (TTBCR2_ADDR_32 << TTBCR_PASIZE_SHIFT);
@@ -821,7 +847,7 @@ static void arm_smmu_init_context_bank(s
 				break;
 			}
 		} else {
-			reg |= (64 - smmu->s1_output_size) << TTBCR_T0SZ_SHIFT;
+			reg |= (64 - smmu->input_size) << TTBCR_T0SZ_SHIFT;
 		}
 	} else {
 		reg = 0;
@@ -830,8 +856,11 @@ static void arm_smmu_init_context_bank(s
 	reg |= TTBCR_EAE |
 	      (TTBCR_SH_IS << TTBCR_SH0_SHIFT) |
 	      (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) |
-	      (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) |
-	      (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT);
+	      (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT);
+
+	if (!stage1)
+		reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT);
+
 	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
 
 	/* MAIR0 (stage-1 only) */
@@ -853,83 +882,70 @@ static void arm_smmu_init_context_bank(s
 }
 
 static int arm_smmu_init_domain_context(struct iommu_domain *domain,
-					struct device *dev)
+					struct arm_smmu_device *smmu)
 {
-	int irq, ret, start;
+	int irq, start, ret = 0;
+	unsigned long flags;
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	struct arm_smmu_device *smmu, *parent;
-
-	/*
-	 * Walk the SMMU chain to find the root device for this chain.
-	 * We assume that no masters have translations which terminate
-	 * early, and therefore check that the root SMMU does indeed have
-	 * a StreamID for the master in question.
-	 */
-	parent = dev->archdata.iommu;
-	smmu_domain->output_mask = -1;
-	do {
-		smmu = parent;
-		smmu_domain->output_mask &= (1ULL << smmu->s2_output_size) - 1;
-	} while ((parent = find_parent_smmu(smmu)));
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 
-	if (!find_smmu_master(smmu, dev->of_node)) {
-		dev_err(dev, "unable to find root SMMU for device\n");
-		return -ENODEV;
-	}
+	spin_lock_irqsave(&smmu_domain->lock, flags);
+	if (smmu_domain->smmu)
+		goto out_unlock;
 
 	if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
 		/*
 		 * We will likely want to change this if/when KVM gets
 		 * involved.
 		 */
-		root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
+		cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
 		start = smmu->num_s2_context_banks;
-	} else if (smmu->features & ARM_SMMU_FEAT_TRANS_S2) {
-		root_cfg->cbar = CBAR_TYPE_S2_TRANS;
-		start = 0;
-	} else {
-		root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
+	} else if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) {
+		cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
 		start = smmu->num_s2_context_banks;
+	} else {
+		cfg->cbar = CBAR_TYPE_S2_TRANS;
+		start = 0;
 	}
 
 	ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
 				      smmu->num_context_banks);
 	if (IS_ERR_VALUE(ret))
-		return ret;
+		goto out_unlock;
 
-	root_cfg->cbndx = ret;
+	cfg->cbndx = ret;
 	if (smmu->version == 1) {
-		root_cfg->irptndx = atomic_inc_return(&smmu->irptndx);
-		root_cfg->irptndx %= smmu->num_context_irqs;
+		cfg->irptndx = atomic_inc_return(&smmu->irptndx);
+		cfg->irptndx %= smmu->num_context_irqs;
 	} else {
-		root_cfg->irptndx = root_cfg->cbndx;
+		cfg->irptndx = cfg->cbndx;
 	}
 
-	irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
+	ACCESS_ONCE(smmu_domain->smmu) = smmu;
+	arm_smmu_init_context_bank(smmu_domain);
+	spin_unlock_irqrestore(&smmu_domain->lock, flags);
+
+	irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
 	ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
 			  "arm-smmu-context-fault", domain);
 	if (IS_ERR_VALUE(ret)) {
 		dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
-			root_cfg->irptndx, irq);
-		root_cfg->irptndx = INVALID_IRPTNDX;
-		goto out_free_context;
+			cfg->irptndx, irq);
+		cfg->irptndx = INVALID_IRPTNDX;
 	}
 
-	root_cfg->smmu = smmu;
-	arm_smmu_init_context_bank(smmu_domain);
-	return ret;
+	return 0;
 
-out_free_context:
-	__arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx);
+out_unlock:
+	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 	return ret;
 }
 
 static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 {
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	struct arm_smmu_device *smmu = root_cfg->smmu;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 	void __iomem *cb_base;
 	int irq;
 
@@ -937,16 +953,16 @@ static void arm_smmu_destroy_domain_cont
 		return;
 
 	/* Disable the context bank and nuke the TLB before freeing it. */
-	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 	writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
-	arm_smmu_tlb_inv_context(root_cfg);
+	arm_smmu_tlb_inv_context(smmu_domain);
 
-	if (root_cfg->irptndx != INVALID_IRPTNDX) {
-		irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
+	if (cfg->irptndx != INVALID_IRPTNDX) {
+		irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
 		free_irq(irq, domain);
 	}
 
-	__arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx);
+	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 }
 
 static int arm_smmu_domain_init(struct iommu_domain *domain)
@@ -963,10 +979,10 @@ static int arm_smmu_domain_init(struct i
 	if (!smmu_domain)
 		return -ENOMEM;
 
-	pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+	pgd = kcalloc(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL);
 	if (!pgd)
 		goto out_free_domain;
-	smmu_domain->root_cfg.pgd = pgd;
+	smmu_domain->cfg.pgd = pgd;
 
 	spin_lock_init(&smmu_domain->lock);
 	domain->priv = smmu_domain;
@@ -980,7 +996,7 @@ out_free_domain:
 static void arm_smmu_free_ptes(pmd_t *pmd)
 {
 	pgtable_t table = pmd_pgtable(*pmd);
-	pgtable_page_dtor(table);
+
 	__free_page(table);
 }
 
@@ -1021,8 +1037,8 @@ static void arm_smmu_free_puds(pgd_t *pg
 static void arm_smmu_free_pgtables(struct arm_smmu_domain *smmu_domain)
 {
 	int i;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	pgd_t *pgd, *pgd_base = root_cfg->pgd;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+	pgd_t *pgd, *pgd_base = cfg->pgd;
 
 	/*
 	 * Recursively free the page tables for this domain. We don't
@@ -1054,7 +1070,7 @@ static void arm_smmu_domain_destroy(stru
 }
 
 static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
-					  struct arm_smmu_master *master)
+					  struct arm_smmu_master_cfg *cfg)
 {
 	int i;
 	struct arm_smmu_smr *smrs;
@@ -1063,18 +1079,18 @@ static int arm_smmu_master_configure_smr
 	if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH))
 		return 0;
 
-	if (master->smrs)
+	if (cfg->smrs)
 		return -EEXIST;
 
-	smrs = kmalloc(sizeof(*smrs) * master->num_streamids, GFP_KERNEL);
+	smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL);
 	if (!smrs) {
-		dev_err(smmu->dev, "failed to allocate %d SMRs for master %s\n",
-			master->num_streamids, master->of_node->name);
+		dev_err(smmu->dev, "failed to allocate %d SMRs\n",
+			cfg->num_streamids);
 		return -ENOMEM;
 	}
 
-	/* Allocate the SMRs on the root SMMU */
-	for (i = 0; i < master->num_streamids; ++i) {
+	/* Allocate the SMRs on the SMMU */
+	for (i = 0; i < cfg->num_streamids; ++i) {
 		int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
 						  smmu->num_mapping_groups);
 		if (IS_ERR_VALUE(idx)) {
@@ -1085,18 +1101,18 @@ static int arm_smmu_master_configure_smr
 		smrs[i] = (struct arm_smmu_smr) {
 			.idx	= idx,
 			.mask	= 0, /* We don't currently share SMRs */
-			.id	= master->streamids[i],
+			.id	= cfg->streamids[i],
 		};
 	}
 
 	/* It worked! Now, poke the actual hardware */
-	for (i = 0; i < master->num_streamids; ++i) {
+	for (i = 0; i < cfg->num_streamids; ++i) {
 		u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
 			  smrs[i].mask << SMR_MASK_SHIFT;
 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
 	}
 
-	master->smrs = smrs;
+	cfg->smrs = smrs;
 	return 0;
 
 err_free_smrs:
@@ -1107,68 +1123,44 @@ err_free_smrs:
 }
 
 static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
-				      struct arm_smmu_master *master)
+				      struct arm_smmu_master_cfg *cfg)
 {
 	int i;
 	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
-	struct arm_smmu_smr *smrs = master->smrs;
+	struct arm_smmu_smr *smrs = cfg->smrs;
+
+	if (!smrs)
+		return;
 
 	/* Invalidate the SMRs before freeing back to the allocator */
-	for (i = 0; i < master->num_streamids; ++i) {
+	for (i = 0; i < cfg->num_streamids; ++i) {
 		u8 idx = smrs[i].idx;
+
 		writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx));
 		__arm_smmu_free_bitmap(smmu->smr_map, idx);
 	}
 
-	master->smrs = NULL;
+	cfg->smrs = NULL;
 	kfree(smrs);
 }
 
-static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu,
-					   struct arm_smmu_master *master)
-{
-	int i;
-	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
-
-	for (i = 0; i < master->num_streamids; ++i) {
-		u16 sid = master->streamids[i];
-		writel_relaxed(S2CR_TYPE_BYPASS,
-			       gr0_base + ARM_SMMU_GR0_S2CR(sid));
-	}
-}
-
 static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
-				      struct arm_smmu_master *master)
+				      struct arm_smmu_master_cfg *cfg)
 {
 	int i, ret;
-	struct arm_smmu_device *parent, *smmu = smmu_domain->root_cfg.smmu;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 
-	ret = arm_smmu_master_configure_smrs(smmu, master);
+	ret = arm_smmu_master_configure_smrs(smmu, cfg);
 	if (ret)
 		return ret;
 
-	/* Bypass the leaves */
-	smmu = smmu_domain->leaf_smmu;
-	while ((parent = find_parent_smmu(smmu))) {
-		/*
-		 * We won't have a StreamID match for anything but the root
-		 * smmu, so we only need to worry about StreamID indexing,
-		 * where we must install bypass entries in the S2CRs.
-		 */
-		if (smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)
-			continue;
-
-		arm_smmu_bypass_stream_mapping(smmu, master);
-		smmu = parent;
-	}
-
-	/* Now we're at the root, time to point at our context bank */
-	for (i = 0; i < master->num_streamids; ++i) {
+	for (i = 0; i < cfg->num_streamids; ++i) {
 		u32 idx, s2cr;
-		idx = master->smrs ? master->smrs[i].idx : master->streamids[i];
+
+		idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
 		s2cr = S2CR_TYPE_TRANS |
-		       (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT);
+		       (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
 		writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
 	}
 
@@ -1176,72 +1168,76 @@ static int arm_smmu_domain_add_master(st
 }
 
 static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
-					  struct arm_smmu_master *master)
+					  struct arm_smmu_master_cfg *cfg)
 {
-	struct arm_smmu_device *smmu = smmu_domain->root_cfg.smmu;
+	int i;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 
 	/*
 	 * We *must* clear the S2CR first, because freeing the SMR means
 	 * that it can be re-allocated immediately.
 	 */
-	arm_smmu_bypass_stream_mapping(smmu, master);
-	arm_smmu_master_free_smrs(smmu, master);
+	for (i = 0; i < cfg->num_streamids; ++i) {
+		u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
+
+		writel_relaxed(S2CR_TYPE_BYPASS,
+			       gr0_base + ARM_SMMU_GR0_S2CR(idx));
+	}
+
+	arm_smmu_master_free_smrs(smmu, cfg);
 }
 
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	int ret = -EINVAL;
+	int ret;
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_device *device_smmu = dev->archdata.iommu;
-	struct arm_smmu_master *master;
-	unsigned long flags;
+	struct arm_smmu_device *smmu, *dom_smmu;
+	struct arm_smmu_master_cfg *cfg;
 
-	if (!device_smmu) {
+	smmu = dev_get_master_dev(dev)->archdata.iommu;
+	if (!smmu) {
 		dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
 		return -ENXIO;
 	}
 
 	/*
-	 * Sanity check the domain. We don't currently support domains
-	 * that cross between different SMMU chains.
+	 * Sanity check the domain. We don't support domains across
+	 * different SMMUs.
 	 */
-	spin_lock_irqsave(&smmu_domain->lock, flags);
-	if (!smmu_domain->leaf_smmu) {
+	dom_smmu = ACCESS_ONCE(smmu_domain->smmu);
+	if (!dom_smmu) {
 		/* Now that we have a master, we can finalise the domain */
-		ret = arm_smmu_init_domain_context(domain, dev);
+		ret = arm_smmu_init_domain_context(domain, smmu);
 		if (IS_ERR_VALUE(ret))
-			goto err_unlock;
+			return ret;
 
-		smmu_domain->leaf_smmu = device_smmu;
-	} else if (smmu_domain->leaf_smmu != device_smmu) {
+		dom_smmu = smmu_domain->smmu;
+	}
+
+	if (dom_smmu != smmu) {
 		dev_err(dev,
 			"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
-			dev_name(smmu_domain->leaf_smmu->dev),
-			dev_name(device_smmu->dev));
-		goto err_unlock;
+			dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
+		return -EINVAL;
 	}
-	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 
 	/* Looks ok, so add the device to the domain */
-	master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
-	if (!master)
+	cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
+	if (!cfg)
 		return -ENODEV;
 
-	return arm_smmu_domain_add_master(smmu_domain, master);
-
-err_unlock:
-	spin_unlock_irqrestore(&smmu_domain->lock, flags);
-	return ret;
+	return arm_smmu_domain_add_master(smmu_domain, cfg);
 }
 
 static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
 {
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_master *master;
+	struct arm_smmu_master_cfg *cfg;
 
-	master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
-	if (master)
-		arm_smmu_domain_remove_master(smmu_domain, master);
+	cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
+	if (cfg)
+		arm_smmu_domain_remove_master(smmu_domain, cfg);
 }
 
 static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
@@ -1261,14 +1257,11 @@ static int arm_smmu_alloc_init_pte(struc
 	if (pmd_none(*pmd)) {
 		/* Allocate a new set of tables */
 		pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
+
 		if (!table)
 			return -ENOMEM;
 
 		arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
-		if (!pgtable_page_ctor(table)) {
-			__free_page(table);
-			return -ENOMEM;
-		}
 		pmd_populate(NULL, pmd, table);
 		arm_smmu_flush_pgtable(smmu, pmd, sizeof(*pmd));
 	}
@@ -1326,6 +1319,7 @@ static int arm_smmu_alloc_init_pte(struc
 	 */
 	do {
 		int i = 1;
+
 		pteval &= ~ARM_SMMU_PTE_CONT;
 
 		if (arm_smmu_pte_is_contiguous_range(addr, end)) {
@@ -1340,7 +1334,8 @@ static int arm_smmu_alloc_init_pte(struc
 			idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1);
 			cont_start = pmd_page_vaddr(*pmd) + idx;
 			for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j)
-				pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT;
+				pte_val(*(cont_start + j)) &=
+					~ARM_SMMU_PTE_CONT;
 
 			arm_smmu_flush_pgtable(smmu, cont_start,
 					       sizeof(*pte) *
@@ -1429,12 +1424,12 @@ static int arm_smmu_handle_mapping(struc
 	int ret, stage;
 	unsigned long end;
 	phys_addr_t input_mask, output_mask;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-	pgd_t *pgd = root_cfg->pgd;
-	struct arm_smmu_device *smmu = root_cfg->smmu;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+	pgd_t *pgd = cfg->pgd;
 	unsigned long flags;
 
-	if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
+	if (cfg->cbar == CBAR_TYPE_S2_TRANS) {
 		stage = 2;
 		output_mask = (1ULL << smmu->s2_output_size) - 1;
 	} else {
@@ -1484,10 +1479,6 @@ static int arm_smmu_map(struct iommu_dom
 	if (!smmu_domain)
 		return -ENODEV;
 
-	/* Check for silent address truncation up the SMMU chain. */
-	if ((phys_addr_t)iova & ~smmu_domain->output_mask)
-		return -ERANGE;
-
 	return arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, prot);
 }
 
@@ -1498,7 +1489,7 @@ static size_t arm_smmu_unmap(struct iomm
 	struct arm_smmu_domain *smmu_domain = domain->priv;
 
 	ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
-	arm_smmu_tlb_inv_context(&smmu_domain->root_cfg);
+	arm_smmu_tlb_inv_context(smmu_domain);
 	return ret ? 0 : size;
 }
 
@@ -1510,9 +1501,9 @@ static phys_addr_t arm_smmu_iova_to_phys
 	pmd_t pmd;
 	pte_t pte;
 	struct arm_smmu_domain *smmu_domain = domain->priv;
-	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
+	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 
-	pgdp = root_cfg->pgd;
+	pgdp = cfg->pgd;
 	if (!pgdp)
 		return 0;
 
@@ -1538,19 +1529,29 @@ static phys_addr_t arm_smmu_iova_to_phys
 static int arm_smmu_domain_has_cap(struct iommu_domain *domain,
 				   unsigned long cap)
 {
-	unsigned long caps = 0;
 	struct arm_smmu_domain *smmu_domain = domain->priv;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	u32 features = smmu ? smmu->features : 0;
 
-	if (smmu_domain->root_cfg.smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
-		caps |= IOMMU_CAP_CACHE_COHERENCY;
+	switch (cap) {
+	case IOMMU_CAP_CACHE_COHERENCY:
+		return features & ARM_SMMU_FEAT_COHERENT_WALK;
+	case IOMMU_CAP_INTR_REMAP:
+		return 1; /* MSIs are just memory writes */
+	default:
+		return 0;
+	}
+}
 
-	return !!(cap & caps);
+static int __arm_smmu_get_pci_sid(struct pci_dev *pdev, u16 alias, void *data)
+{
+	*((u16 *)data) = alias;
+	return 0; /* Continue walking */
 }
 
 static int arm_smmu_add_device(struct device *dev)
 {
-	struct arm_smmu_device *child, *parent, *smmu;
-	struct arm_smmu_master *master = NULL;
+	struct arm_smmu_device *smmu;
 	struct iommu_group *group;
 	int ret;
 
@@ -1559,35 +1560,8 @@ static int arm_smmu_add_device(struct de
 		return -EINVAL;
 	}
 
-	spin_lock(&arm_smmu_devices_lock);
-	list_for_each_entry(parent, &arm_smmu_devices, list) {
-		smmu = parent;
-
-		/* Try to find a child of the current SMMU. */
-		list_for_each_entry(child, &arm_smmu_devices, list) {
-			if (child->parent_of_node == parent->dev->of_node) {
-				/* Does the child sit above our master? */
-				master = find_smmu_master(child, dev->of_node);
-				if (master) {
-					smmu = NULL;
-					break;
-				}
-			}
-		}
-
-		/* We found some children, so keep searching. */
-		if (!smmu) {
-			master = NULL;
-			continue;
-		}
-
-		master = find_smmu_master(smmu, dev->of_node);
-		if (master)
-			break;
-	}
-	spin_unlock(&arm_smmu_devices_lock);
-
-	if (!master)
+	smmu = find_smmu_for_device(dev);
+	if (!smmu)
 		return -ENODEV;
 
 	group = iommu_group_alloc();
@@ -1596,20 +1570,45 @@ static int arm_smmu_add_device(struct de
 		return PTR_ERR(group);
 	}
 
+	if (dev_is_pci(dev)) {
+		struct arm_smmu_master_cfg *cfg;
+		struct pci_dev *pdev = to_pci_dev(dev);
+
+		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+		if (!cfg) {
+			ret = -ENOMEM;
+			goto out_put_group;
+		}
+
+		cfg->num_streamids = 1;
+		/*
+		 * Assume Stream ID == Requester ID for now.
+		 * We need a way to describe the ID mappings in FDT.
+		 */
+		pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
+				       &cfg->streamids[0]);
+		dev->archdata.iommu = cfg;
+	} else {
+		dev->archdata.iommu = smmu;
+	}
+
 	ret = iommu_group_add_device(group, dev);
-	iommu_group_put(group);
-	dev->archdata.iommu = smmu;
 
+out_put_group:
+	iommu_group_put(group);
 	return ret;
 }
 
 static void arm_smmu_remove_device(struct device *dev)
 {
+	if (dev_is_pci(dev))
+		kfree(dev->archdata.iommu);
+
 	dev->archdata.iommu = NULL;
 	iommu_group_remove_device(dev);
 }
 
-static struct iommu_ops arm_smmu_ops = {
+static const struct iommu_ops arm_smmu_ops = {
 	.domain_init	= arm_smmu_domain_init,
 	.domain_destroy	= arm_smmu_domain_destroy,
 	.attach_dev	= arm_smmu_attach_dev,
@@ -1638,8 +1637,9 @@ static void arm_smmu_device_reset(struct
 
 	/* Mark all SMRn as invalid and all S2CRn as bypass */
 	for (i = 0; i < smmu->num_mapping_groups; ++i) {
-		writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i));
-		writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i));
+		writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i));
+		writel_relaxed(S2CR_TYPE_BYPASS,
+			gr0_base + ARM_SMMU_GR0_S2CR(i));
 	}
 
 	/* Make sure all context banks are disabled and clear CB_FSR  */
@@ -1772,6 +1772,9 @@ static int arm_smmu_device_cfg_probe(str
 		dev_notice(smmu->dev,
 			   "\tstream matching with %u register groups, mask 0x%x",
 			   smmu->num_mapping_groups, mask);
+	} else {
+		smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) &
+					   ID0_NUMSIDB_MASK;
 	}
 
 	/* ID1 */
@@ -1779,11 +1782,13 @@ static int arm_smmu_device_cfg_probe(str
 	smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K;
 
 	/* Check for size mismatch of SMMU address space from mapped region */
-	size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
+	size = 1 <<
+		(((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
 	size *= (smmu->pagesize << 1);
 	if (smmu->size != size)
-		dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs "
-			"from mapped region size (0x%lx)!\n", size, smmu->size);
+		dev_warn(smmu->dev,
+			"SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n",
+			size, smmu->size);
 
 	smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) &
 				      ID1_NUMS2CB_MASK;
@@ -1803,15 +1808,20 @@ static int arm_smmu_device_cfg_probe(str
 	 * Stage-1 output limited by stage-2 input size due to pgd
 	 * allocation (PTRS_PER_PGD).
 	 */
+	if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
 #ifdef CONFIG_64BIT
-	smmu->s1_output_size = min((unsigned long)VA_BITS, size);
+		smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
 #else
-	smmu->s1_output_size = min(32UL, size);
+		smmu->s1_output_size = min(32UL, size);
 #endif
+	} else {
+		smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT,
+					     size);
+	}
 
 	/* The stage-2 output mask is also applied for bypass */
 	size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
-	smmu->s2_output_size = min((unsigned long)PHYS_MASK_SHIFT, size);
+	smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size);
 
 	if (smmu->version == 1) {
 		smmu->input_size = 32;
@@ -1835,7 +1845,8 @@ static int arm_smmu_device_cfg_probe(str
 
 	dev_notice(smmu->dev,
 		   "\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n",
-		   smmu->input_size, smmu->s1_output_size, smmu->s2_output_size);
+		   smmu->input_size, smmu->s1_output_size,
+		   smmu->s2_output_size);
 	return 0;
 }
 
@@ -1843,7 +1854,6 @@ static int arm_smmu_device_dt_probe(stru
 {
 	struct resource *res;
 	struct arm_smmu_device *smmu;
-	struct device_node *dev_node;
 	struct device *dev = &pdev->dev;
 	struct rb_node *node;
 	struct of_phandle_args masterspec;
@@ -1890,6 +1900,7 @@ static int arm_smmu_device_dt_probe(stru
 
 	for (i = 0; i < num_irqs; ++i) {
 		int irq = platform_get_irq(pdev, i);
+
 		if (irq < 0) {
 			dev_err(dev, "failed to get irq index %d\n", i);
 			return -ENODEV;
@@ -1897,6 +1908,10 @@ static int arm_smmu_device_dt_probe(stru
 		smmu->irqs[i] = irq;
 	}
 
+	err = arm_smmu_device_cfg_probe(smmu);
+	if (err)
+		return err;
+
 	i = 0;
 	smmu->masters = RB_ROOT;
 	while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
@@ -1913,13 +1928,6 @@ static int arm_smmu_device_dt_probe(stru
 	}
 	dev_notice(dev, "registered %d master devices\n", i);
 
-	if ((dev_node = of_parse_phandle(dev->of_node, "smmu-parent", 0)))
-		smmu->parent_of_node = dev_node;
-
-	err = arm_smmu_device_cfg_probe(smmu);
-	if (err)
-		goto out_put_parent;
-
 	parse_driver_options(smmu);
 
 	if (smmu->version > 1 &&
@@ -1928,7 +1936,7 @@ static int arm_smmu_device_dt_probe(stru
 			"found only %d context interrupt(s) but %d required\n",
 			smmu->num_context_irqs, smmu->num_context_banks);
 		err = -ENODEV;
-		goto out_put_parent;
+		goto out_put_masters;
 	}
 
 	for (i = 0; i < smmu->num_global_irqs; ++i) {
@@ -1956,14 +1964,10 @@ out_free_irqs:
 	while (i--)
 		free_irq(smmu->irqs[i], smmu);
 
-out_put_parent:
-	if (smmu->parent_of_node)
-		of_node_put(smmu->parent_of_node);
-
 out_put_masters:
 	for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
-		struct arm_smmu_master *master;
-		master = container_of(node, struct arm_smmu_master, node);
+		struct arm_smmu_master *master
+			= container_of(node, struct arm_smmu_master, node);
 		of_node_put(master->of_node);
 	}
 
@@ -1990,12 +1994,9 @@ static int arm_smmu_device_remove(struct
 	if (!smmu)
 		return -ENODEV;
 
-	if (smmu->parent_of_node)
-		of_node_put(smmu->parent_of_node);
-
 	for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
-		struct arm_smmu_master *master;
-		master = container_of(node, struct arm_smmu_master, node);
+		struct arm_smmu_master *master
+			= container_of(node, struct arm_smmu_master, node);
 		of_node_put(master->of_node);
 	}
 
@@ -2006,7 +2007,7 @@ static int arm_smmu_device_remove(struct
 		free_irq(smmu->irqs[i], smmu);
 
 	/* Turn the thing off */
-	writel(sCR0_CLIENTPD,ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+	writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 	return 0;
 }
 
@@ -2048,6 +2049,11 @@ static int __init arm_smmu_init(void)
 		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
 #endif
 
+#ifdef CONFIG_PCI
+	if (!iommu_present(&pci_bus_type))
+		bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
+#endif
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/dmar.c linux-libre-3.17-rc7-gnu/drivers/iommu/dmar.c
--- linux-libre-3.16-gnu/drivers/iommu/dmar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/dmar.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/tboot.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/iommu.h>
 #include <asm/irq_remapping.h>
 #include <asm/iommu_table.h>
 
@@ -84,7 +85,7 @@ void *dmar_alloc_dev_scope(void *start,
 	*cnt = 0;
 	while (start < end) {
 		scope = start;
-		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ACPI ||
+		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_NAMESPACE ||
 		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
 		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
 			(*cnt)++;
@@ -380,7 +381,7 @@ static int __init dmar_parse_one_andd(st
 	struct acpi_dmar_andd *andd = (void *)header;
 
 	/* Check for NUL termination within the designated length */
-	if (strnlen(andd->object_name, header->length - 8) == header->length - 8) {
+	if (strnlen(andd->device_name, header->length - 8) == header->length - 8) {
 		WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
 			   "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
 			   "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
@@ -390,7 +391,7 @@ static int __init dmar_parse_one_andd(st
 		return -EINVAL;
 	}
 	pr_info("ANDD device: %x name: %s\n", andd->device_number,
-		andd->object_name);
+		andd->device_name);
 
 	return 0;
 }
@@ -448,17 +449,17 @@ dmar_table_print_dmar_entry(struct acpi_
 			(unsigned long long)rmrr->base_address,
 			(unsigned long long)rmrr->end_address);
 		break;
-	case ACPI_DMAR_TYPE_ATSR:
+	case ACPI_DMAR_TYPE_ROOT_ATS:
 		atsr = container_of(header, struct acpi_dmar_atsr, header);
 		pr_info("ATSR flags: %#x\n", atsr->flags);
 		break;
-	case ACPI_DMAR_HARDWARE_AFFINITY:
+	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
 		rhsa = container_of(header, struct acpi_dmar_rhsa, header);
 		pr_info("RHSA base: %#016Lx proximity domain: %#x\n",
 		       (unsigned long long)rhsa->base_address,
 		       rhsa->proximity_domain);
 		break;
-	case ACPI_DMAR_TYPE_ANDD:
+	case ACPI_DMAR_TYPE_NAMESPACE:
 		/* We don't print this here because we need to sanity-check
 		   it first. So print it in dmar_parse_one_andd() instead. */
 		break;
@@ -539,15 +540,15 @@ parse_dmar_table(void)
 		case ACPI_DMAR_TYPE_RESERVED_MEMORY:
 			ret = dmar_parse_one_rmrr(entry_header);
 			break;
-		case ACPI_DMAR_TYPE_ATSR:
+		case ACPI_DMAR_TYPE_ROOT_ATS:
 			ret = dmar_parse_one_atsr(entry_header);
 			break;
-		case ACPI_DMAR_HARDWARE_AFFINITY:
+		case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
 #ifdef CONFIG_ACPI_NUMA
 			ret = dmar_parse_one_rhsa(entry_header);
 #endif
 			break;
-		case ACPI_DMAR_TYPE_ANDD:
+		case ACPI_DMAR_TYPE_NAMESPACE:
 			ret = dmar_parse_one_andd(entry_header);
 			break;
 		default:
@@ -631,7 +632,7 @@ static void __init dmar_acpi_insert_dev_
 		for (scope = (void *)(drhd + 1);
 		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
 		     scope = ((void *)scope) + scope->length) {
-			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI)
+			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
 				continue;
 			if (scope->enumeration_id != device_number)
 				continue;
@@ -666,21 +667,20 @@ static int __init dmar_acpi_dev_scope_in
 	for (andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
 	     ((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length;
 	     andd = ((void *)andd) + andd->header.length) {
-		if (andd->header.type == ACPI_DMAR_TYPE_ANDD) {
+		if (andd->header.type == ACPI_DMAR_TYPE_NAMESPACE) {
 			acpi_handle h;
 			struct acpi_device *adev;
 
 			if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT,
-							  andd->object_name,
+							  andd->device_name,
 							  &h))) {
 				pr_err("Failed to find handle for ACPI object %s\n",
-				       andd->object_name);
+				       andd->device_name);
 				continue;
 			}
-			acpi_bus_get_device(h, &adev);
-			if (!adev) {
+			if (acpi_bus_get_device(h, &adev)) {
 				pr_err("Failed to get device for ACPI object %s\n",
-				       andd->object_name);
+				       andd->device_name);
 				continue;
 			}
 			dmar_acpi_insert_dev_scope(andd->device_number, adev);
@@ -980,6 +980,12 @@ static int alloc_iommu(struct dmar_drhd_
 	raw_spin_lock_init(&iommu->register_lock);
 
 	drhd->iommu = iommu;
+
+	if (intel_iommu_enabled)
+		iommu->iommu_dev = iommu_device_create(NULL, iommu,
+						       intel_iommu_groups,
+						       iommu->name);
+
 	return 0;
 
  err_unmap:
@@ -991,6 +997,8 @@ static int alloc_iommu(struct dmar_drhd_
 
 static void free_iommu(struct intel_iommu *iommu)
 {
+	iommu_device_destroy(iommu->iommu_dev);
+
 	if (iommu->irq) {
 		free_irq(iommu->irq, iommu);
 		irq_set_handler_data(iommu->irq, NULL);
@@ -1339,9 +1347,6 @@ int dmar_enable_qi(struct intel_iommu *i
 		return -ENOMEM;
 	}
 
-	qi->free_head = qi->free_tail = 0;
-	qi->free_cnt = QI_LENGTH;
-
 	raw_spin_lock_init(&qi->q_lock);
 
 	__dmar_enable_qi(iommu);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/exynos-iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/exynos-iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/exynos-iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/exynos-iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1170,7 +1170,7 @@ static void exynos_iommu_remove_device(s
 	iommu_group_remove_device(dev);
 }
 
-static struct iommu_ops exynos_iommu_ops = {
+static const struct iommu_ops exynos_iommu_ops = {
 	.domain_init = exynos_iommu_domain_init,
 	.domain_destroy = exynos_iommu_domain_destroy,
 	.attach_dev = exynos_iommu_attach_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/fsl_pamu.c linux-libre-3.17-rc7-gnu/drivers/iommu/fsl_pamu.c
--- linux-libre-3.16-gnu/drivers/iommu/fsl_pamu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/fsl_pamu.c	2014-09-28 17:29:07.000000000 -0400
@@ -92,7 +92,7 @@ struct gen_pool *spaace_pool;
  * subwindow count per liodn.
  *
  */
-u32 pamu_get_max_subwin_cnt()
+u32 pamu_get_max_subwin_cnt(void)
 {
 	return max_subwindow_count;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/fsl_pamu_domain.c linux-libre-3.17-rc7-gnu/drivers/iommu/fsl_pamu_domain.c
--- linux-libre-3.16-gnu/drivers/iommu/fsl_pamu_domain.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/fsl_pamu_domain.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,6 @@
 #include <sysdev/fsl_pci.h>
 
 #include "fsl_pamu_domain.h"
-#include "pci.h"
 
 /*
  * Global spinlock that needs to be held while
@@ -887,8 +886,6 @@ static int fsl_pamu_get_domain_attr(stru
 	return ret;
 }
 
-#define REQ_ACS_FLAGS	(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
 static struct iommu_group *get_device_iommu_group(struct device *dev)
 {
 	struct iommu_group *group;
@@ -945,74 +942,13 @@ static struct iommu_group *get_pci_devic
 	struct pci_controller *pci_ctl;
 	bool pci_endpt_partioning;
 	struct iommu_group *group = NULL;
-	struct pci_dev *bridge, *dma_pdev = NULL;
 
 	pci_ctl = pci_bus_to_host(pdev->bus);
 	pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl);
 	/* We can partition PCIe devices so assign device group to the device */
 	if (pci_endpt_partioning) {
-		bridge = pci_find_upstream_pcie_bridge(pdev);
-		if (bridge) {
-			if (pci_is_pcie(bridge))
-				dma_pdev = pci_get_domain_bus_and_slot(
-						pci_domain_nr(pdev->bus),
-						bridge->subordinate->number, 0);
-			if (!dma_pdev)
-				dma_pdev = pci_dev_get(bridge);
-		} else
-			dma_pdev = pci_dev_get(pdev);
-
-		/* Account for quirked devices */
-		swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
-
-		/*
-		 * If it's a multifunction device that does not support our
-		 * required ACS flags, add to the same group as lowest numbered
-		 * function that also does not suport the required ACS flags.
-		 */
-		if (dma_pdev->multifunction &&
-		    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
-			u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
-			for (i = 0; i < 8; i++) {
-				struct pci_dev *tmp;
-
-				tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
-				if (!tmp)
-					continue;
-
-				if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
-					swap_pci_ref(&dma_pdev, tmp);
-					break;
-				}
-				pci_dev_put(tmp);
-			}
-		}
-
-		/*
-		 * Devices on the root bus go through the iommu.  If that's not us,
-		 * find the next upstream device and test ACS up to the root bus.
-		 * Finding the next device may require skipping virtual buses.
-		 */
-		while (!pci_is_root_bus(dma_pdev->bus)) {
-			struct pci_bus *bus = dma_pdev->bus;
-
-			while (!bus->self) {
-				if (!pci_is_root_bus(bus))
-					bus = bus->parent;
-				else
-					goto root_bus;
-			}
-
-			if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
-				break;
-
-			swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
-		}
+		group = iommu_group_get_for_dev(&pdev->dev);
 
-root_bus:
-		group = get_device_iommu_group(&dma_pdev->dev);
-		pci_dev_put(dma_pdev);
 		/*
 		 * PCIe controller is not a paritionable entity
 		 * free the controller device iommu_group.
@@ -1048,7 +984,7 @@ static int fsl_pamu_add_device(struct de
 	struct iommu_group *group = ERR_PTR(-ENODEV);
 	struct pci_dev *pdev;
 	const u32 *prop;
-	int ret, len;
+	int ret = 0, len;
 
 	/*
 	 * For platform devices we allocate a separate group for
@@ -1071,7 +1007,13 @@ static int fsl_pamu_add_device(struct de
 	if (IS_ERR(group))
 		return PTR_ERR(group);
 
-	ret = iommu_group_add_device(group, dev);
+	/*
+	 * Check if device has already been added to an iommu group.
+	 * Group could have already been created for a PCI device in
+	 * the iommu_group_get_for_dev path.
+	 */
+	if (!dev->iommu_group)
+		ret = iommu_group_add_device(group, dev);
 
 	iommu_group_put(group);
 	return ret;
@@ -1116,8 +1058,7 @@ static int fsl_pamu_set_windows(struct i
 	ret = pamu_set_domain_geometry(dma_domain, &domain->geometry,
 				((w_count > 1) ? w_count : 0));
 	if (!ret) {
-		if (dma_domain->win_arr)
-			kfree(dma_domain->win_arr);
+		kfree(dma_domain->win_arr);
 		dma_domain->win_arr = kzalloc(sizeof(struct dma_window) *
 							  w_count, GFP_ATOMIC);
 		if (!dma_domain->win_arr) {
@@ -1138,7 +1079,7 @@ static u32 fsl_pamu_get_windows(struct i
 	return dma_domain->win_cnt;
 }
 
-static struct iommu_ops fsl_pamu_ops = {
+static const struct iommu_ops fsl_pamu_ops = {
 	.domain_init	= fsl_pamu_domain_init,
 	.domain_destroy = fsl_pamu_domain_destroy,
 	.attach_dev	= fsl_pamu_attach_device,
@@ -1155,7 +1096,7 @@ static struct iommu_ops fsl_pamu_ops = {
 	.remove_device	= fsl_pamu_remove_device,
 };
 
-int pamu_domain_init()
+int pamu_domain_init(void)
 {
 	int ret = 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/intel-iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/intel-iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/intel-iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/intel-iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,6 @@
 #include <asm/iommu.h>
 
 #include "irq_remapping.h"
-#include "pci.h"
 
 #define ROOT_SIZE		VTD_PAGE_SIZE
 #define CONTEXT_SIZE		VTD_PAGE_SIZE
@@ -304,7 +303,7 @@ static inline bool dma_pte_present(struc
 
 static inline bool dma_pte_superpage(struct dma_pte *pte)
 {
-	return (pte->val & (1 << 7));
+	return (pte->val & DMA_PTE_LARGE_PAGE);
 }
 
 static inline int first_pte_in_page(struct dma_pte *pte)
@@ -321,16 +320,13 @@ static inline int first_pte_in_page(stru
 static struct dmar_domain *si_domain;
 static int hw_pass_through = 1;
 
-/* devices under the same p2p bridge are owned in one domain */
-#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
-
 /* domain represents a virtual machine, more than one devices
  * across iommus may be owned in one domain, e.g. kvm guest.
  */
-#define DOMAIN_FLAG_VIRTUAL_MACHINE	(1 << 1)
+#define DOMAIN_FLAG_VIRTUAL_MACHINE	(1 << 0)
 
 /* si_domain contains mulitple devices */
-#define DOMAIN_FLAG_STATIC_IDENTITY	(1 << 2)
+#define DOMAIN_FLAG_STATIC_IDENTITY	(1 << 1)
 
 /* define the limit of IOMMUs supported in each domain */
 #ifdef	CONFIG_X86
@@ -429,6 +425,8 @@ static void domain_remove_one_dev_info(s
 				       struct device *dev);
 static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
 					   struct device *dev);
+static int domain_detach_iommu(struct dmar_domain *domain,
+			       struct intel_iommu *iommu);
 
 #ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
@@ -451,7 +449,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped
 static DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
-static struct iommu_ops intel_iommu_ops;
+static const struct iommu_ops intel_iommu_ops;
 
 static int __init intel_iommu_setup(char *str)
 {
@@ -540,6 +538,24 @@ void free_iova_mem(struct iova *iova)
 	kmem_cache_free(iommu_iova_cache, iova);
 }
 
+static inline int domain_type_is_vm(struct dmar_domain *domain)
+{
+	return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
+}
+
+static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
+{
+	return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
+				DOMAIN_FLAG_STATIC_IDENTITY);
+}
+
+static inline int domain_pfn_supported(struct dmar_domain *domain,
+				       unsigned long pfn)
+{
+	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+
+	return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
+}
 
 static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
 {
@@ -580,9 +596,7 @@ static struct intel_iommu *domain_get_io
 	int iommu_id;
 
 	/* si_domain and vm domain should not get here. */
-	BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
-	BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY);
-
+	BUG_ON(domain_type_is_vm_or_si(domain));
 	iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
 	if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
 		return NULL;
@@ -619,50 +633,56 @@ static void domain_update_iommu_coherenc
 	rcu_read_unlock();
 }
 
-static void domain_update_iommu_snooping(struct dmar_domain *domain)
+static int domain_update_iommu_snooping(struct intel_iommu *skip)
 {
-	int i;
-
-	domain->iommu_snooping = 1;
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+	int ret = 1;
 
-	for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
-		if (!ecap_sc_support(g_iommus[i]->ecap)) {
-			domain->iommu_snooping = 0;
-			break;
+	rcu_read_lock();
+	for_each_active_iommu(iommu, drhd) {
+		if (iommu != skip) {
+			if (!ecap_sc_support(iommu->ecap)) {
+				ret = 0;
+				break;
+			}
 		}
 	}
+	rcu_read_unlock();
+
+	return ret;
 }
 
-static void domain_update_iommu_superpage(struct dmar_domain *domain)
+static int domain_update_iommu_superpage(struct intel_iommu *skip)
 {
 	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu = NULL;
+	struct intel_iommu *iommu;
 	int mask = 0xf;
 
 	if (!intel_iommu_superpage) {
-		domain->iommu_superpage = 0;
-		return;
+		return 0;
 	}
 
 	/* set iommu_superpage to the smallest common denominator */
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd) {
-		mask &= cap_super_page_val(iommu->cap);
-		if (!mask) {
-			break;
+		if (iommu != skip) {
+			mask &= cap_super_page_val(iommu->cap);
+			if (!mask)
+				break;
 		}
 	}
 	rcu_read_unlock();
 
-	domain->iommu_superpage = fls(mask);
+	return fls(mask);
 }
 
 /* Some capabilities may be different across iommus */
 static void domain_update_iommu_cap(struct dmar_domain *domain)
 {
 	domain_update_iommu_coherency(domain);
-	domain_update_iommu_snooping(domain);
-	domain_update_iommu_superpage(domain);
+	domain->iommu_snooping = domain_update_iommu_snooping(NULL);
+	domain->iommu_superpage = domain_update_iommu_superpage(NULL);
 }
 
 static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
@@ -671,7 +691,7 @@ static struct intel_iommu *device_to_iom
 	struct intel_iommu *iommu;
 	struct device *tmp;
 	struct pci_dev *ptmp, *pdev = NULL;
-	u16 segment;
+	u16 segment = 0;
 	int i;
 
 	if (dev_is_pci(dev)) {
@@ -816,14 +836,13 @@ out:
 static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
 				      unsigned long pfn, int *target_level)
 {
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
 	struct dma_pte *parent, *pte = NULL;
 	int level = agaw_to_level(domain->agaw);
 	int offset;
 
 	BUG_ON(!domain->pgd);
 
-	if (addr_width < BITS_PER_LONG && pfn >> addr_width)
+	if (!domain_pfn_supported(domain, pfn))
 		/* Address beyond IOMMU's addressing capabilities. */
 		return NULL;
 
@@ -849,13 +868,11 @@ static struct dma_pte *pfn_to_dma_pte(st
 
 			domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
 			pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
-			if (cmpxchg64(&pte->val, 0ULL, pteval)) {
+			if (cmpxchg64(&pte->val, 0ULL, pteval))
 				/* Someone else set it while we were thinking; use theirs. */
 				free_pgtable_page(tmp_page);
-			} else {
-				dma_pte_addr(pte);
+			else
 				domain_flush_cache(domain, pte, sizeof(*pte));
-			}
 		}
 		if (level == 1)
 			break;
@@ -892,7 +909,7 @@ static struct dma_pte *dma_pfn_level_pte
 			break;
 		}
 
-		if (pte->val & DMA_PTE_LARGE_PAGE) {
+		if (dma_pte_superpage(pte)) {
 			*large_page = total;
 			return pte;
 		}
@@ -908,12 +925,11 @@ static void dma_pte_clear_range(struct d
 				unsigned long start_pfn,
 				unsigned long last_pfn)
 {
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
 	unsigned int large_page = 1;
 	struct dma_pte *first_pte, *pte;
 
-	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
-	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+	BUG_ON(!domain_pfn_supported(domain, start_pfn));
+	BUG_ON(!domain_pfn_supported(domain, last_pfn));
 	BUG_ON(start_pfn > last_pfn);
 
 	/* we don't need lock here; nobody else touches the iova range */
@@ -974,12 +990,12 @@ static void dma_pte_free_pagetable(struc
 				   unsigned long start_pfn,
 				   unsigned long last_pfn)
 {
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-
-	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
-	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+	BUG_ON(!domain_pfn_supported(domain, start_pfn));
+	BUG_ON(!domain_pfn_supported(domain, last_pfn));
 	BUG_ON(start_pfn > last_pfn);
 
+	dma_pte_clear_range(domain, start_pfn, last_pfn);
+
 	/* We don't need lock here; nobody else touches the iova range */
 	dma_pte_free_level(domain, agaw_to_level(domain->agaw),
 			   domain->pgd, 0, start_pfn, last_pfn);
@@ -1077,11 +1093,10 @@ struct page *domain_unmap(struct dmar_do
 			  unsigned long start_pfn,
 			  unsigned long last_pfn)
 {
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
 	struct page *freelist = NULL;
 
-	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
-	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+	BUG_ON(!domain_pfn_supported(domain, start_pfn));
+	BUG_ON(!domain_pfn_supported(domain, last_pfn));
 	BUG_ON(start_pfn > last_pfn);
 
 	/* we don't need lock here; nobody else touches the iova range */
@@ -1275,7 +1290,8 @@ iommu_support_dev_iotlb (struct dmar_dom
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	list_for_each_entry(info, &domain->devices, link)
-		if (info->bus == bus && info->devfn == devfn) {
+		if (info->iommu == iommu && info->bus == bus &&
+		    info->devfn == devfn) {
 			found = 1;
 			break;
 		}
@@ -1384,7 +1400,7 @@ static void iommu_disable_protect_mem_re
 	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
-static int iommu_enable_translation(struct intel_iommu *iommu)
+static void iommu_enable_translation(struct intel_iommu *iommu)
 {
 	u32 sts;
 	unsigned long flags;
@@ -1398,10 +1414,9 @@ static int iommu_enable_translation(stru
 		      readl, (sts & DMA_GSTS_TES), sts);
 
 	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
-	return 0;
 }
 
-static int iommu_disable_translation(struct intel_iommu *iommu)
+static void iommu_disable_translation(struct intel_iommu *iommu)
 {
 	u32 sts;
 	unsigned long flag;
@@ -1415,7 +1430,6 @@ static int iommu_disable_translation(str
 		      readl, (!(sts & DMA_GSTS_TES)), sts);
 
 	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
-	return 0;
 }
 
 
@@ -1462,8 +1476,7 @@ static int iommu_init_domains(struct int
 static void free_dmar_iommu(struct intel_iommu *iommu)
 {
 	struct dmar_domain *domain;
-	int i, count;
-	unsigned long flags;
+	int i;
 
 	if ((iommu->domains) && (iommu->domain_ids)) {
 		for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
@@ -1476,11 +1489,8 @@ static void free_dmar_iommu(struct intel
 
 			domain = iommu->domains[i];
 			clear_bit(i, iommu->domain_ids);
-
-			spin_lock_irqsave(&domain->iommu_lock, flags);
-			count = --domain->iommu_count;
-			spin_unlock_irqrestore(&domain->iommu_lock, flags);
-			if (count == 0)
+			if (domain_detach_iommu(domain, iommu) == 0 &&
+			    !domain_type_is_vm(domain))
 				domain_exit(domain);
 		}
 	}
@@ -1499,7 +1509,7 @@ static void free_dmar_iommu(struct intel
 	free_context_table(iommu);
 }
 
-static struct dmar_domain *alloc_domain(bool vm)
+static struct dmar_domain *alloc_domain(int flags)
 {
 	/* domain id for virtual machine, it won't be set in context */
 	static atomic_t vm_domid = ATOMIC_INIT(0);
@@ -1509,46 +1519,62 @@ static struct dmar_domain *alloc_domain(
 	if (!domain)
 		return NULL;
 
+	memset(domain, 0, sizeof(*domain));
 	domain->nid = -1;
-	domain->iommu_count = 0;
-	memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp));
-	domain->flags = 0;
+	domain->flags = flags;
 	spin_lock_init(&domain->iommu_lock);
 	INIT_LIST_HEAD(&domain->devices);
-	if (vm) {
+	if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
 		domain->id = atomic_inc_return(&vm_domid);
-		domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
-	}
 
 	return domain;
 }
 
-static int iommu_attach_domain(struct dmar_domain *domain,
-			       struct intel_iommu *iommu)
+static int __iommu_attach_domain(struct dmar_domain *domain,
+				 struct intel_iommu *iommu)
 {
 	int num;
 	unsigned long ndomains;
-	unsigned long flags;
 
 	ndomains = cap_ndoms(iommu->cap);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-
 	num = find_first_zero_bit(iommu->domain_ids, ndomains);
-	if (num >= ndomains) {
-		spin_unlock_irqrestore(&iommu->lock, flags);
-		printk(KERN_ERR "IOMMU: no free domain ids\n");
-		return -ENOMEM;
+	if (num < ndomains) {
+		set_bit(num, iommu->domain_ids);
+		iommu->domains[num] = domain;
+	} else {
+		num = -ENOSPC;
 	}
 
-	domain->id = num;
-	domain->iommu_count++;
-	set_bit(num, iommu->domain_ids);
-	set_bit(iommu->seq_id, domain->iommu_bmp);
-	iommu->domains[num] = domain;
+	return num;
+}
+
+static int iommu_attach_domain(struct dmar_domain *domain,
+			       struct intel_iommu *iommu)
+{
+	int num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	num = __iommu_attach_domain(domain, iommu);
 	spin_unlock_irqrestore(&iommu->lock, flags);
+	if (num < 0)
+		pr_err("IOMMU: no free domain ids\n");
 
-	return 0;
+	return num;
+}
+
+static int iommu_attach_vm_domain(struct dmar_domain *domain,
+				  struct intel_iommu *iommu)
+{
+	int num;
+	unsigned long ndomains;
+
+	ndomains = cap_ndoms(iommu->cap);
+	for_each_set_bit(num, iommu->domain_ids, ndomains)
+		if (iommu->domains[num] == domain)
+			return num;
+
+	return __iommu_attach_domain(domain, iommu);
 }
 
 static void iommu_detach_domain(struct dmar_domain *domain,
@@ -1558,17 +1584,53 @@ static void iommu_detach_domain(struct d
 	int num, ndomains;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	ndomains = cap_ndoms(iommu->cap);
-	for_each_set_bit(num, iommu->domain_ids, ndomains) {
-		if (iommu->domains[num] == domain) {
-			clear_bit(num, iommu->domain_ids);
-			iommu->domains[num] = NULL;
-			break;
+	if (domain_type_is_vm_or_si(domain)) {
+		ndomains = cap_ndoms(iommu->cap);
+		for_each_set_bit(num, iommu->domain_ids, ndomains) {
+			if (iommu->domains[num] == domain) {
+				clear_bit(num, iommu->domain_ids);
+				iommu->domains[num] = NULL;
+				break;
+			}
 		}
+	} else {
+		clear_bit(domain->id, iommu->domain_ids);
+		iommu->domains[domain->id] = NULL;
 	}
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
+static void domain_attach_iommu(struct dmar_domain *domain,
+			       struct intel_iommu *iommu)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&domain->iommu_lock, flags);
+	if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
+		domain->iommu_count++;
+		if (domain->iommu_count == 1)
+			domain->nid = iommu->node;
+		domain_update_iommu_cap(domain);
+	}
+	spin_unlock_irqrestore(&domain->iommu_lock, flags);
+}
+
+static int domain_detach_iommu(struct dmar_domain *domain,
+			       struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	int count = INT_MAX;
+
+	spin_lock_irqsave(&domain->iommu_lock, flags);
+	if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
+		count = --domain->iommu_count;
+		domain_update_iommu_cap(domain);
+	}
+	spin_unlock_irqrestore(&domain->iommu_lock, flags);
+
+	return count;
+}
+
 static struct iova_domain reserved_iova_list;
 static struct lock_class_key reserved_rbtree_key;
 
@@ -1706,9 +1768,7 @@ static void domain_exit(struct dmar_doma
 	/* clear attached or cached domains */
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd)
-		if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
-		    test_bit(iommu->seq_id, domain->iommu_bmp))
-			iommu_detach_domain(domain, iommu);
+		iommu_detach_domain(domain, iommu);
 	rcu_read_unlock();
 
 	dma_free_pagelist(freelist);
@@ -1723,8 +1783,6 @@ static int domain_context_mapping_one(st
 	struct context_entry *context;
 	unsigned long flags;
 	struct dma_pte *pgd;
-	unsigned long num;
-	unsigned long ndomains;
 	int id;
 	int agaw;
 	struct device_domain_info *info = NULL;
@@ -1748,31 +1806,14 @@ static int domain_context_mapping_one(st
 	id = domain->id;
 	pgd = domain->pgd;
 
-	if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
-	    domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) {
-		int found = 0;
-
-		/* find an available domain id for this device in iommu */
-		ndomains = cap_ndoms(iommu->cap);
-		for_each_set_bit(num, iommu->domain_ids, ndomains) {
-			if (iommu->domains[num] == domain) {
-				id = num;
-				found = 1;
-				break;
-			}
-		}
-
-		if (found == 0) {
-			num = find_first_zero_bit(iommu->domain_ids, ndomains);
-			if (num >= ndomains) {
+	if (domain_type_is_vm_or_si(domain)) {
+		if (domain_type_is_vm(domain)) {
+			id = iommu_attach_vm_domain(domain, iommu);
+			if (id < 0) {
 				spin_unlock_irqrestore(&iommu->lock, flags);
-				printk(KERN_ERR "IOMMU: no free domain ids\n");
+				pr_err("IOMMU: no free domain ids\n");
 				return -EFAULT;
 			}
-
-			set_bit(num, iommu->domain_ids);
-			iommu->domains[num] = domain;
-			id = num;
 		}
 
 		/* Skip top levels of page tables for
@@ -1824,72 +1865,68 @@ static int domain_context_mapping_one(st
 					   (((u16)bus) << 8) | devfn,
 					   DMA_CCMD_MASK_NOBIT,
 					   DMA_CCMD_DEVICE_INVL);
-		iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
+		iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH);
 	} else {
 		iommu_flush_write_buffer(iommu);
 	}
 	iommu_enable_dev_iotlb(info);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
-	spin_lock_irqsave(&domain->iommu_lock, flags);
-	if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
-		domain->iommu_count++;
-		if (domain->iommu_count == 1)
-			domain->nid = iommu->node;
-		domain_update_iommu_cap(domain);
-	}
-	spin_unlock_irqrestore(&domain->iommu_lock, flags);
+	domain_attach_iommu(domain, iommu);
+
 	return 0;
 }
 
+struct domain_context_mapping_data {
+	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
+	int translation;
+};
+
+static int domain_context_mapping_cb(struct pci_dev *pdev,
+				     u16 alias, void *opaque)
+{
+	struct domain_context_mapping_data *data = opaque;
+
+	return domain_context_mapping_one(data->domain, data->iommu,
+					  PCI_BUS_NUM(alias), alias & 0xff,
+					  data->translation);
+}
+
 static int
 domain_context_mapping(struct dmar_domain *domain, struct device *dev,
 		       int translation)
 {
-	int ret;
-	struct pci_dev *pdev, *tmp, *parent;
 	struct intel_iommu *iommu;
 	u8 bus, devfn;
+	struct domain_context_mapping_data data;
 
 	iommu = device_to_iommu(dev, &bus, &devfn);
 	if (!iommu)
 		return -ENODEV;
 
-	ret = domain_context_mapping_one(domain, iommu, bus, devfn,
-					 translation);
-	if (ret || !dev_is_pci(dev))
-		return ret;
-
-	/* dependent device mapping */
-	pdev = to_pci_dev(dev);
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (!tmp)
-		return 0;
-	/* Secondary interface's bus number and devfn 0 */
-	parent = pdev->bus->self;
-	while (parent != tmp) {
-		ret = domain_context_mapping_one(domain, iommu,
-						 parent->bus->number,
-						 parent->devfn, translation);
-		if (ret)
-			return ret;
-		parent = parent->bus->self;
-	}
-	if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
-		return domain_context_mapping_one(domain, iommu,
-					tmp->subordinate->number, 0,
-					translation);
-	else /* this is a legacy PCI bridge */
-		return domain_context_mapping_one(domain, iommu,
-						  tmp->bus->number,
-						  tmp->devfn,
+	if (!dev_is_pci(dev))
+		return domain_context_mapping_one(domain, iommu, bus, devfn,
 						  translation);
+
+	data.domain = domain;
+	data.iommu = iommu;
+	data.translation = translation;
+
+	return pci_for_each_dma_alias(to_pci_dev(dev),
+				      &domain_context_mapping_cb, &data);
+}
+
+static int domain_context_mapped_cb(struct pci_dev *pdev,
+				    u16 alias, void *opaque)
+{
+	struct intel_iommu *iommu = opaque;
+
+	return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
 }
 
 static int domain_context_mapped(struct device *dev)
 {
-	int ret;
-	struct pci_dev *pdev, *tmp, *parent;
 	struct intel_iommu *iommu;
 	u8 bus, devfn;
 
@@ -1897,30 +1934,11 @@ static int domain_context_mapped(struct
 	if (!iommu)
 		return -ENODEV;
 
-	ret = device_context_mapped(iommu, bus, devfn);
-	if (!ret || !dev_is_pci(dev))
-		return ret;
+	if (!dev_is_pci(dev))
+		return device_context_mapped(iommu, bus, devfn);
 
-	/* dependent device mapping */
-	pdev = to_pci_dev(dev);
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (!tmp)
-		return ret;
-	/* Secondary interface's bus number and devfn 0 */
-	parent = pdev->bus->self;
-	while (parent != tmp) {
-		ret = device_context_mapped(iommu, parent->bus->number,
-					    parent->devfn);
-		if (!ret)
-			return ret;
-		parent = parent->bus->self;
-	}
-	if (pci_is_pcie(tmp))
-		return device_context_mapped(iommu, tmp->subordinate->number,
-					     0);
-	else
-		return device_context_mapped(iommu, tmp->bus->number,
-					     tmp->devfn);
+	return !pci_for_each_dma_alias(to_pci_dev(dev),
+				       domain_context_mapped_cb, iommu);
 }
 
 /* Returns a number of VTD pages, but aligned to MM page size */
@@ -1965,12 +1983,11 @@ static int __domain_mapping(struct dmar_
 {
 	struct dma_pte *first_pte = NULL, *pte = NULL;
 	phys_addr_t uninitialized_var(pteval);
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
 	unsigned long sg_res;
 	unsigned int largepage_lvl = 0;
 	unsigned long lvl_pages = 0;
 
-	BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
+	BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
 
 	if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
 		return -EINVAL;
@@ -2004,12 +2021,14 @@ static int __domain_mapping(struct dmar_
 			/* It is large page*/
 			if (largepage_lvl > 1) {
 				pteval |= DMA_PTE_LARGE_PAGE;
-				/* Ensure that old small page tables are removed to make room
-				   for superpage, if they exist. */
-				dma_pte_clear_range(domain, iov_pfn,
-						    iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
+				lvl_pages = lvl_to_nr_pages(largepage_lvl);
+				/*
+				 * Ensure that old small page tables are
+				 * removed to make room for superpage,
+				 * if they exist.
+				 */
 				dma_pte_free_pagetable(domain, iov_pfn,
-						       iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
+						       iov_pfn + lvl_pages - 1);
 			} else {
 				pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
 			}
@@ -2102,31 +2121,20 @@ static inline void unlink_domain_info(st
 
 static void domain_remove_dev_info(struct dmar_domain *domain)
 {
-	struct device_domain_info *info;
-	unsigned long flags, flags2;
+	struct device_domain_info *info, *tmp;
+	unsigned long flags;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
-	while (!list_empty(&domain->devices)) {
-		info = list_entry(domain->devices.next,
-			struct device_domain_info, link);
+	list_for_each_entry_safe(info, tmp, &domain->devices, link) {
 		unlink_domain_info(info);
 		spin_unlock_irqrestore(&device_domain_lock, flags);
 
 		iommu_disable_dev_iotlb(info);
 		iommu_detach_dev(info->iommu, info->bus, info->devfn);
 
-		if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
+		if (domain_type_is_vm(domain)) {
 			iommu_detach_dependent_devices(info->iommu, info->dev);
-			/* clear this iommu in iommu_bmp, update iommu count
-			 * and capabilities
-			 */
-			spin_lock_irqsave(&domain->iommu_lock, flags2);
-			if (test_and_clear_bit(info->iommu->seq_id,
-					       domain->iommu_bmp)) {
-				domain->iommu_count--;
-				domain_update_iommu_cap(domain);
-			}
-			spin_unlock_irqrestore(&domain->iommu_lock, flags2);
+			domain_detach_iommu(domain, info->iommu);
 		}
 
 		free_devinfo_mem(info);
@@ -2181,8 +2189,6 @@ static struct dmar_domain *dmar_insert_d
 	info->dev = dev;
 	info->domain = domain;
 	info->iommu = iommu;
-	if (!dev)
-		domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	if (dev)
@@ -2209,79 +2215,86 @@ static struct dmar_domain *dmar_insert_d
 	return domain;
 }
 
+static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+	*(u16 *)opaque = alias;
+	return 0;
+}
+
 /* domain is initialized */
 static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
 {
-	struct dmar_domain *domain, *free = NULL;
-	struct intel_iommu *iommu = NULL;
+	struct dmar_domain *domain, *tmp;
+	struct intel_iommu *iommu;
 	struct device_domain_info *info;
-	struct pci_dev *dev_tmp = NULL;
+	u16 dma_alias;
 	unsigned long flags;
-	u8 bus, devfn, bridge_bus, bridge_devfn;
+	u8 bus, devfn;
 
 	domain = find_domain(dev);
 	if (domain)
 		return domain;
 
+	iommu = device_to_iommu(dev, &bus, &devfn);
+	if (!iommu)
+		return NULL;
+
 	if (dev_is_pci(dev)) {
 		struct pci_dev *pdev = to_pci_dev(dev);
-		u16 segment;
 
-		segment = pci_domain_nr(pdev->bus);
-		dev_tmp = pci_find_upstream_pcie_bridge(pdev);
-		if (dev_tmp) {
-			if (pci_is_pcie(dev_tmp)) {
-				bridge_bus = dev_tmp->subordinate->number;
-				bridge_devfn = 0;
-			} else {
-				bridge_bus = dev_tmp->bus->number;
-				bridge_devfn = dev_tmp->devfn;
-			}
-			spin_lock_irqsave(&device_domain_lock, flags);
-			info = dmar_search_domain_by_dev_info(segment,
-							      bridge_bus,
-							      bridge_devfn);
-			if (info) {
-				iommu = info->iommu;
-				domain = info->domain;
-			}
-			spin_unlock_irqrestore(&device_domain_lock, flags);
-			/* pcie-pci bridge already has a domain, uses it */
-			if (info)
-				goto found_domain;
+		pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
+
+		spin_lock_irqsave(&device_domain_lock, flags);
+		info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
+						      PCI_BUS_NUM(dma_alias),
+						      dma_alias & 0xff);
+		if (info) {
+			iommu = info->iommu;
+			domain = info->domain;
 		}
-	}
+		spin_unlock_irqrestore(&device_domain_lock, flags);
 
-	iommu = device_to_iommu(dev, &bus, &devfn);
-	if (!iommu)
-		goto error;
+		/* DMA alias already has a domain, uses it */
+		if (info)
+			goto found_domain;
+	}
 
 	/* Allocate and initialize new domain for the device */
-	domain = alloc_domain(false);
+	domain = alloc_domain(0);
 	if (!domain)
-		goto error;
-	if (iommu_attach_domain(domain, iommu)) {
+		return NULL;
+	domain->id = iommu_attach_domain(domain, iommu);
+	if (domain->id < 0) {
 		free_domain_mem(domain);
-		domain = NULL;
-		goto error;
+		return NULL;
+	}
+	domain_attach_iommu(domain, iommu);
+	if (domain_init(domain, gaw)) {
+		domain_exit(domain);
+		return NULL;
 	}
-	free = domain;
-	if (domain_init(domain, gaw))
-		goto error;
 
-	/* register pcie-to-pci device */
-	if (dev_tmp) {
-		domain = dmar_insert_dev_info(iommu, bridge_bus, bridge_devfn,
-					      NULL, domain);
+	/* register PCI DMA alias device */
+	if (dev_is_pci(dev)) {
+		tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias),
+					   dma_alias & 0xff, NULL, domain);
+
+		if (!tmp || tmp != domain) {
+			domain_exit(domain);
+			domain = tmp;
+		}
+
 		if (!domain)
-			goto error;
+			return NULL;
 	}
 
 found_domain:
-	domain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
-error:
-	if (free != domain)
-		domain_exit(free);
+	tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
+
+	if (!tmp || tmp != domain) {
+		domain_exit(domain);
+		domain = tmp;
+	}
 
 	return domain;
 }
@@ -2405,6 +2418,7 @@ static inline void iommu_prepare_isa(voi
 		printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
 		       "floppy might not work\n");
 
+	pci_dev_put(pdev);
 }
 #else
 static inline void iommu_prepare_isa(void)
@@ -2420,19 +2434,25 @@ static int __init si_domain_init(int hw)
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu;
 	int nid, ret = 0;
+	bool first = true;
 
-	si_domain = alloc_domain(false);
+	si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
 	if (!si_domain)
 		return -EFAULT;
 
-	si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
-
 	for_each_active_iommu(iommu, drhd) {
 		ret = iommu_attach_domain(si_domain, iommu);
-		if (ret) {
+		if (ret < 0) {
+			domain_exit(si_domain);
+			return -EFAULT;
+		} else if (first) {
+			si_domain->id = ret;
+			first = false;
+		} else if (si_domain->id != ret) {
 			domain_exit(si_domain);
 			return -EFAULT;
 		}
+		domain_attach_iommu(si_domain, iommu);
 	}
 
 	if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
@@ -2523,22 +2543,46 @@ static bool device_has_rmrr(struct devic
 	return false;
 }
 
+/*
+ * There are a couple cases where we need to restrict the functionality of
+ * devices associated with RMRRs.  The first is when evaluating a device for
+ * identity mapping because problems exist when devices are moved in and out
+ * of domains and their respective RMRR information is lost.  This means that
+ * a device with associated RMRRs will never be in a "passthrough" domain.
+ * The second is use of the device through the IOMMU API.  This interface
+ * expects to have full control of the IOVA space for the device.  We cannot
+ * satisfy both the requirement that RMRR access is maintained and have an
+ * unencumbered IOVA space.  We also have no ability to quiesce the device's
+ * use of the RMRR space or even inform the IOMMU API user of the restriction.
+ * We therefore prevent devices associated with an RMRR from participating in
+ * the IOMMU API, which eliminates them from device assignment.
+ *
+ * In both cases we assume that PCI USB devices with RMRRs have them largely
+ * for historical reasons and that the RMRR space is not actively used post
+ * boot.  This exclusion may change if vendors begin to abuse it.
+ */
+static bool device_is_rmrr_locked(struct device *dev)
+{
+	if (!device_has_rmrr(dev))
+		return false;
+
+	if (dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+
+		if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+			return false;
+	}
+
+	return true;
+}
+
 static int iommu_should_identity_map(struct device *dev, int startup)
 {
 
 	if (dev_is_pci(dev)) {
 		struct pci_dev *pdev = to_pci_dev(dev);
 
-		/*
-		 * We want to prevent any device associated with an RMRR from
-		 * getting placed into the SI Domain. This is done because
-		 * problems exist when devices are moved in and out of domains
-		 * and their respective RMRR info is lost. We exempt USB devices
-		 * from this process due to their usage of RMRRs that are known
-		 * to not be needed after BIOS hand-off to OS.
-		 */
-		if (device_has_rmrr(dev) &&
-		    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
+		if (device_is_rmrr_locked(dev))
 			return 0;
 
 		if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
@@ -2850,11 +2894,7 @@ static int __init init_dmars(void)
 
 		iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
 		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
-		ret = iommu_enable_translation(iommu);
-		if (ret)
-			goto free_iommu;
-
+		iommu_enable_translation(iommu);
 		iommu_disable_protect_mem_regions(iommu);
 	}
 
@@ -3091,10 +3131,10 @@ static void flush_unmaps(void)
 			/* On real hardware multiple invalidations are expensive */
 			if (cap_caching_mode(iommu->cap))
 				iommu_flush_iotlb_psi(iommu, domain->id,
-					iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1,
+					iova->pfn_lo, iova_size(iova),
 					!deferred_flush[i].freelist[j], 0);
 			else {
-				mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
+				mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
 				iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
 						(uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
 			}
@@ -3144,9 +3184,7 @@ static void add_unmap(struct dmar_domain
 	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
 }
 
-static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
-			     size_t size, enum dma_data_direction dir,
-			     struct dma_attrs *attrs)
+static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
 {
 	struct dmar_domain *domain;
 	unsigned long start_pfn, last_pfn;
@@ -3190,6 +3228,13 @@ static void intel_unmap_page(struct devi
 	}
 }
 
+static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
+			     size_t size, enum dma_data_direction dir,
+			     struct dma_attrs *attrs)
+{
+	intel_unmap(dev, dev_addr);
+}
+
 static void *intel_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags,
 				  struct dma_attrs *attrs)
@@ -3246,7 +3291,7 @@ static void intel_free_coherent(struct d
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
 
-	intel_unmap_page(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
+	intel_unmap(dev, dma_handle);
 	if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
 		__free_pages(page, order);
 }
@@ -3255,43 +3300,7 @@ static void intel_unmap_sg(struct device
 			   int nelems, enum dma_data_direction dir,
 			   struct dma_attrs *attrs)
 {
-	struct dmar_domain *domain;
-	unsigned long start_pfn, last_pfn;
-	struct iova *iova;
-	struct intel_iommu *iommu;
-	struct page *freelist;
-
-	if (iommu_no_mapping(dev))
-		return;
-
-	domain = find_domain(dev);
-	BUG_ON(!domain);
-
-	iommu = domain_get_iommu(domain);
-
-	iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
-	if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
-		      (unsigned long long)sglist[0].dma_address))
-		return;
-
-	start_pfn = mm_to_dma_pfn(iova->pfn_lo);
-	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
-	freelist = domain_unmap(domain, start_pfn, last_pfn);
-
-	if (intel_iommu_strict) {
-		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-				      last_pfn - start_pfn + 1, !freelist, 0);
-		/* free iova */
-		__free_iova(&domain->iovad, iova);
-		dma_free_pagelist(freelist);
-	} else {
-		add_unmap(domain, iova, freelist);
-		/*
-		 * queue up the release of the unmap to save the 1/6th of the
-		 * cpu used up by the iotlb flush operation...
-		 */
-	}
+	intel_unmap(dev, sglist[0].dma_address);
 }
 
 static int intel_nontranslate_map_sg(struct device *hddev,
@@ -3355,13 +3364,8 @@ static int intel_map_sg(struct device *d
 
 	ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
 	if (unlikely(ret)) {
-		/*  clear the page */
-		dma_pte_clear_range(domain, start_vpfn,
-				    start_vpfn + size - 1);
-		/* free page tables */
 		dma_pte_free_pagetable(domain, start_vpfn,
 				       start_vpfn + size - 1);
-		/* free iova */
 		__free_iova(&domain->iovad, iova);
 		return 0;
 	}
@@ -3568,10 +3572,8 @@ static int init_iommu_hw(void)
 
 		iommu->flush.flush_context(iommu, 0, 0, 0,
 					   DMA_CCMD_GLOBAL_INVL);
-		iommu->flush.flush_iotlb(iommu, 0, 0, 0,
-					 DMA_TLB_GLOBAL_FLUSH);
-		if (iommu_enable_translation(iommu))
-			return 1;
+		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+		iommu_enable_translation(iommu);
 		iommu_disable_protect_mem_regions(iommu);
 	}
 
@@ -3867,15 +3869,21 @@ static int device_notifier(struct notifi
 	    action != BUS_NOTIFY_DEL_DEVICE)
 		return 0;
 
+	/*
+	 * If the device is still attached to a device driver we can't
+	 * tear down the domain yet as DMA mappings may still be in use.
+	 * Wait for the BUS_NOTIFY_UNBOUND_DRIVER event to do that.
+	 */
+	if (action == BUS_NOTIFY_DEL_DEVICE && dev->driver != NULL)
+		return 0;
+
 	domain = find_domain(dev);
 	if (!domain)
 		return 0;
 
 	down_read(&dmar_global_lock);
 	domain_remove_one_dev_info(domain, dev);
-	if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
-	    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
-	    list_empty(&domain->devices))
+	if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
 		domain_exit(domain);
 	up_read(&dmar_global_lock);
 
@@ -3935,8 +3943,7 @@ static int intel_iommu_memory_notifier(s
 			rcu_read_lock();
 			for_each_active_iommu(iommu, drhd)
 				iommu_flush_iotlb_psi(iommu, si_domain->id,
-					iova->pfn_lo,
-					iova->pfn_hi - iova->pfn_lo + 1,
+					iova->pfn_lo, iova_size(iova),
 					!freelist, 0);
 			rcu_read_unlock();
 			dma_free_pagelist(freelist);
@@ -3955,6 +3962,63 @@ static struct notifier_block intel_iommu
 	.priority = 0
 };
 
+
+static ssize_t intel_iommu_show_version(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct intel_iommu *iommu = dev_get_drvdata(dev);
+	u32 ver = readl(iommu->reg + DMAR_VER_REG);
+	return sprintf(buf, "%d:%d\n",
+		       DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
+}
+static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
+
+static ssize_t intel_iommu_show_address(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct intel_iommu *iommu = dev_get_drvdata(dev);
+	return sprintf(buf, "%llx\n", iommu->reg_phys);
+}
+static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
+
+static ssize_t intel_iommu_show_cap(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct intel_iommu *iommu = dev_get_drvdata(dev);
+	return sprintf(buf, "%llx\n", iommu->cap);
+}
+static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
+
+static ssize_t intel_iommu_show_ecap(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct intel_iommu *iommu = dev_get_drvdata(dev);
+	return sprintf(buf, "%llx\n", iommu->ecap);
+}
+static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
+
+static struct attribute *intel_iommu_attrs[] = {
+	&dev_attr_version.attr,
+	&dev_attr_address.attr,
+	&dev_attr_cap.attr,
+	&dev_attr_ecap.attr,
+	NULL,
+};
+
+static struct attribute_group intel_iommu_group = {
+	.name = "intel-iommu",
+	.attrs = intel_iommu_attrs,
+};
+
+const struct attribute_group *intel_iommu_groups[] = {
+	&intel_iommu_group,
+	NULL,
+};
+
 int __init intel_iommu_init(void)
 {
 	int ret = -ENODEV;
@@ -4026,6 +4090,11 @@ int __init intel_iommu_init(void)
 
 	init_iommu_pm_ops();
 
+	for_each_active_iommu(iommu, drhd)
+		iommu->iommu_dev = iommu_device_create(NULL, iommu,
+						       intel_iommu_groups,
+						       iommu->name);
+
 	bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
 	bus_register_notifier(&pci_bus_type, &device_nb);
 	if (si_domain && !hw_pass_through)
@@ -4044,33 +4113,27 @@ out_free_dmar:
 	return ret;
 }
 
+static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+	struct intel_iommu *iommu = opaque;
+
+	iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
+	return 0;
+}
+
+/*
+ * NB - intel-iommu lacks any sort of reference counting for the users of
+ * dependent devices.  If multiple endpoints have intersecting dependent
+ * devices, unbinding the driver from any one of them will possibly leave
+ * the others unable to operate.
+ */
 static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
 					   struct device *dev)
 {
-	struct pci_dev *tmp, *parent, *pdev;
-
 	if (!iommu || !dev || !dev_is_pci(dev))
 		return;
 
-	pdev = to_pci_dev(dev);
-
-	/* dependent device detach */
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	/* Secondary interface's bus number and devfn 0 */
-	if (tmp) {
-		parent = pdev->bus->self;
-		while (parent != tmp) {
-			iommu_detach_dev(iommu, parent->bus->number,
-					 parent->devfn);
-			parent = parent->bus->self;
-		}
-		if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
-			iommu_detach_dev(iommu,
-				tmp->subordinate->number, 0);
-		else /* this is a legacy PCI bridge */
-			iommu_detach_dev(iommu, tmp->bus->number,
-					 tmp->devfn);
-	}
+	pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
 }
 
 static void domain_remove_one_dev_info(struct dmar_domain *domain,
@@ -4117,20 +4180,9 @@ static void domain_remove_one_dev_info(s
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 
 	if (found == 0) {
-		unsigned long tmp_flags;
-		spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
-		clear_bit(iommu->seq_id, domain->iommu_bmp);
-		domain->iommu_count--;
-		domain_update_iommu_cap(domain);
-		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
-
-		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
-		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
-			spin_lock_irqsave(&iommu->lock, tmp_flags);
-			clear_bit(domain->id, iommu->domain_ids);
-			iommu->domains[domain->id] = NULL;
-			spin_unlock_irqrestore(&iommu->lock, tmp_flags);
-		}
+		domain_detach_iommu(domain, iommu);
+		if (!domain_type_is_vm_or_si(domain))
+			iommu_detach_domain(domain, iommu);
 	}
 }
 
@@ -4150,7 +4202,6 @@ static int md_domain_init(struct dmar_do
 	domain->iommu_snooping = 0;
 	domain->iommu_superpage = 0;
 	domain->max_addr = 0;
-	domain->nid = -1;
 
 	/* always allocate the top pgd */
 	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
@@ -4164,7 +4215,7 @@ static int intel_iommu_domain_init(struc
 {
 	struct dmar_domain *dmar_domain;
 
-	dmar_domain = alloc_domain(true);
+	dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
 	if (!dmar_domain) {
 		printk(KERN_ERR
 			"intel_iommu_domain_init: dmar_domain == NULL\n");
@@ -4202,14 +4253,18 @@ static int intel_iommu_attach_device(str
 	int addr_width;
 	u8 bus, devfn;
 
+	if (device_is_rmrr_locked(dev)) {
+		dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement.  Contact your platform vendor.\n");
+		return -EPERM;
+	}
+
 	/* normally dev is not mapped */
 	if (unlikely(domain_context_mapped(dev))) {
 		struct dmar_domain *old_domain;
 
 		old_domain = find_domain(dev);
 		if (old_domain) {
-			if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
-			    dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
+			if (domain_type_is_vm_or_si(dmar_domain))
 				domain_remove_one_dev_info(old_domain, dev);
 			else
 				domain_remove_dev_info(old_domain);
@@ -4373,99 +4428,42 @@ static int intel_iommu_domain_has_cap(st
 	return 0;
 }
 
-#define REQ_ACS_FLAGS	(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
 static int intel_iommu_add_device(struct device *dev)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct pci_dev *bridge, *dma_pdev = NULL;
+	struct intel_iommu *iommu;
 	struct iommu_group *group;
-	int ret;
 	u8 bus, devfn;
 
-	if (!device_to_iommu(dev, &bus, &devfn))
+	iommu = device_to_iommu(dev, &bus, &devfn);
+	if (!iommu)
 		return -ENODEV;
 
-	bridge = pci_find_upstream_pcie_bridge(pdev);
-	if (bridge) {
-		if (pci_is_pcie(bridge))
-			dma_pdev = pci_get_domain_bus_and_slot(
-						pci_domain_nr(pdev->bus),
-						bridge->subordinate->number, 0);
-		if (!dma_pdev)
-			dma_pdev = pci_dev_get(bridge);
-	} else
-		dma_pdev = pci_dev_get(pdev);
-
-	/* Account for quirked devices */
-	swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
-
-	/*
-	 * If it's a multifunction device that does not support our
-	 * required ACS flags, add to the same group as lowest numbered
-	 * function that also does not suport the required ACS flags.
-	 */
-	if (dma_pdev->multifunction &&
-	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
-		u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
-		for (i = 0; i < 8; i++) {
-			struct pci_dev *tmp;
-
-			tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
-			if (!tmp)
-				continue;
-
-			if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
-				swap_pci_ref(&dma_pdev, tmp);
-				break;
-			}
-			pci_dev_put(tmp);
-		}
-	}
-
-	/*
-	 * Devices on the root bus go through the iommu.  If that's not us,
-	 * find the next upstream device and test ACS up to the root bus.
-	 * Finding the next device may require skipping virtual buses.
-	 */
-	while (!pci_is_root_bus(dma_pdev->bus)) {
-		struct pci_bus *bus = dma_pdev->bus;
-
-		while (!bus->self) {
-			if (!pci_is_root_bus(bus))
-				bus = bus->parent;
-			else
-				goto root_bus;
-		}
-
-		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
-			break;
-
-		swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
-	}
+	iommu_device_link(iommu->iommu_dev, dev);
 
-root_bus:
-	group = iommu_group_get(&dma_pdev->dev);
-	pci_dev_put(dma_pdev);
-	if (!group) {
-		group = iommu_group_alloc();
-		if (IS_ERR(group))
-			return PTR_ERR(group);
-	}
+	group = iommu_group_get_for_dev(dev);
 
-	ret = iommu_group_add_device(group, dev);
+	if (IS_ERR(group))
+		return PTR_ERR(group);
 
 	iommu_group_put(group);
-	return ret;
+	return 0;
 }
 
 static void intel_iommu_remove_device(struct device *dev)
 {
+	struct intel_iommu *iommu;
+	u8 bus, devfn;
+
+	iommu = device_to_iommu(dev, &bus, &devfn);
+	if (!iommu)
+		return;
+
 	iommu_group_remove_device(dev);
+
+	iommu_device_unlink(iommu->iommu_dev, dev);
 }
 
-static struct iommu_ops intel_iommu_ops = {
+static const struct iommu_ops intel_iommu_ops = {
 	.domain_init	= intel_iommu_domain_init,
 	.domain_destroy = intel_iommu_domain_destroy,
 	.attach_dev	= intel_iommu_attach_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/intel_irq_remapping.c linux-libre-3.17-rc7-gnu/drivers/iommu/intel_irq_remapping.c
--- linux-libre-3.16-gnu/drivers/iommu/intel_irq_remapping.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/intel_irq_remapping.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,6 +70,11 @@ static int get_irte(int irq, struct irte
 
 	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
+	if (unlikely(!irq_iommu->iommu)) {
+		raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+		return -1;
+	}
+
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	*entry = *(irq_iommu->iommu->ir_table->base + index);
 
@@ -369,29 +374,52 @@ static int set_hpet_sid(struct irte *irt
 	return 0;
 }
 
+struct set_msi_sid_data {
+	struct pci_dev *pdev;
+	u16 alias;
+};
+
+static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+	struct set_msi_sid_data *data = opaque;
+
+	data->pdev = pdev;
+	data->alias = alias;
+
+	return 0;
+}
+
 static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
 {
-	struct pci_dev *bridge;
+	struct set_msi_sid_data data;
 
 	if (!irte || !dev)
 		return -1;
 
-	/* PCIe device or Root Complex integrated PCI device */
-	if (pci_is_pcie(dev) || !dev->bus->parent) {
-		set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
-			     (dev->bus->number << 8) | dev->devfn);
-		return 0;
-	}
+	pci_for_each_dma_alias(dev, set_msi_sid_cb, &data);
 
-	bridge = pci_find_upstream_pcie_bridge(dev);
-	if (bridge) {
-		if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
-			set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
-				(bridge->bus->number << 8) | dev->bus->number);
-		else /* this is a legacy PCI bridge */
-			set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
-				(bridge->bus->number << 8) | bridge->devfn);
-	}
+	/*
+	 * DMA alias provides us with a PCI device and alias.  The only case
+	 * where the it will return an alias on a different bus than the
+	 * device is the case of a PCIe-to-PCI bridge, where the alias is for
+	 * the subordinate bus.  In this case we can only verify the bus.
+	 *
+	 * If the alias device is on a different bus than our source device
+	 * then we have a topology based alias, use it.
+	 *
+	 * Otherwise, the alias is for a device DMA quirk and we cannot
+	 * assume that MSI uses the same requester ID.  Therefore use the
+	 * original device.
+	 */
+	if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number)
+		set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
+			     PCI_DEVID(PCI_BUS_NUM(data.alias),
+				       dev->bus->number));
+	else if (data.pdev->bus->number != dev->bus->number)
+		set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias);
+	else
+		set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+			     PCI_DEVID(dev->bus->number, dev->devfn));
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,12 +29,17 @@
 #include <linux/idr.h>
 #include <linux/notifier.h>
 #include <linux/err.h>
+#include <linux/pci.h>
 #include <trace/events/iommu.h>
 
 static struct kset *iommu_group_kset;
 static struct ida iommu_group_ida;
 static struct mutex iommu_group_mutex;
 
+struct iommu_callback_data {
+	const struct iommu_ops *ops;
+};
+
 struct iommu_group {
 	struct kobject kobj;
 	struct kobject *devices_kobj;
@@ -514,9 +519,193 @@ int iommu_group_id(struct iommu_group *g
 }
 EXPORT_SYMBOL_GPL(iommu_group_id);
 
+/*
+ * To consider a PCI device isolated, we require ACS to support Source
+ * Validation, Request Redirection, Completer Redirection, and Upstream
+ * Forwarding.  This effectively means that devices cannot spoof their
+ * requester ID, requests and completions cannot be redirected, and all
+ * transactions are forwarded upstream, even as it passes through a
+ * bridge where the target device is downstream.
+ */
+#define REQ_ACS_FLAGS   (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
+
+struct group_for_pci_data {
+	struct pci_dev *pdev;
+	struct iommu_group *group;
+};
+
+/*
+ * DMA alias iterator callback, return the last seen device.  Stop and return
+ * the IOMMU group if we find one along the way.
+ */
+static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+	struct group_for_pci_data *data = opaque;
+
+	data->pdev = pdev;
+	data->group = iommu_group_get(&pdev->dev);
+
+	return data->group != NULL;
+}
+
+/*
+ * Use standard PCI bus topology, isolation features, and DMA alias quirks
+ * to find or create an IOMMU group for a device.
+ */
+static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
+{
+	struct group_for_pci_data data;
+	struct pci_bus *bus;
+	struct iommu_group *group = NULL;
+	struct pci_dev *tmp;
+
+	/*
+	 * Find the upstream DMA alias for the device.  A device must not
+	 * be aliased due to topology in order to have its own IOMMU group.
+	 * If we find an alias along the way that already belongs to a
+	 * group, use it.
+	 */
+	if (pci_for_each_dma_alias(pdev, get_pci_alias_or_group, &data))
+		return data.group;
+
+	pdev = data.pdev;
+
+	/*
+	 * Continue upstream from the point of minimum IOMMU granularity
+	 * due to aliases to the point where devices are protected from
+	 * peer-to-peer DMA by PCI ACS.  Again, if we find an existing
+	 * group, use it.
+	 */
+	for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) {
+		if (!bus->self)
+			continue;
+
+		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
+			break;
+
+		pdev = bus->self;
+
+		group = iommu_group_get(&pdev->dev);
+		if (group)
+			return group;
+	}
+
+	/*
+	 * Next we need to consider DMA alias quirks.  If one device aliases
+	 * to another, they should be grouped together.  It's theoretically
+	 * possible that aliases could create chains of devices where each
+	 * device aliases another device.  If we then factor in multifunction
+	 * ACS grouping requirements, each alias could incorporate a new slot
+	 * with multiple functions, each with aliases.  This is all extremely
+	 * unlikely as DMA alias quirks are typically only used for PCIe
+	 * devices where we usually have a single slot per bus.  Furthermore,
+	 * the alias quirk is usually to another function within the slot
+	 * (and ACS multifunction is not supported) or to a different slot
+	 * that doesn't physically exist.  The likely scenario is therefore
+	 * that everything on the bus gets grouped together.  To reduce the
+	 * problem space, share the IOMMU group for all devices on the bus
+	 * if a DMA alias quirk is present on the bus.
+	 */
+	tmp = NULL;
+	for_each_pci_dev(tmp) {
+		if (tmp->bus != pdev->bus ||
+		    !(tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN))
+			continue;
+
+		pci_dev_put(tmp);
+		tmp = NULL;
+
+		/* We have an alias quirk, search for an existing group */
+		for_each_pci_dev(tmp) {
+			struct iommu_group *group_tmp;
+
+			if (tmp->bus != pdev->bus)
+				continue;
+
+			group_tmp = iommu_group_get(&tmp->dev);
+			if (!group) {
+				group = group_tmp;
+				continue;
+			}
+
+			if (group_tmp) {
+				WARN_ON(group != group_tmp);
+				iommu_group_put(group_tmp);
+			}
+		}
+
+		return group ? group : iommu_group_alloc();
+	}
+
+	/*
+	 * Non-multifunction devices or multifunction devices supporting
+	 * ACS get their own group.
+	 */
+	if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS))
+		return iommu_group_alloc();
+
+	/*
+	 * Multifunction devices not supporting ACS share a group with other
+	 * similar devices in the same slot.
+	 */
+	tmp = NULL;
+	for_each_pci_dev(tmp) {
+		if (tmp == pdev || tmp->bus != pdev->bus ||
+		    PCI_SLOT(tmp->devfn) !=  PCI_SLOT(pdev->devfn) ||
+		    pci_acs_enabled(tmp, REQ_ACS_FLAGS))
+			continue;
+
+		group = iommu_group_get(&tmp->dev);
+		if (group) {
+			pci_dev_put(tmp);
+			return group;
+		}
+	}
+
+	/* No shared group found, allocate new */
+	return iommu_group_alloc();
+}
+
+/**
+ * iommu_group_get_for_dev - Find or create the IOMMU group for a device
+ * @dev: target device
+ *
+ * This function is intended to be called by IOMMU drivers and extended to
+ * support common, bus-defined algorithms when determining or creating the
+ * IOMMU group for a device.  On success, the caller will hold a reference
+ * to the returned IOMMU group, which will already include the provided
+ * device.  The reference should be released with iommu_group_put().
+ */
+struct iommu_group *iommu_group_get_for_dev(struct device *dev)
+{
+	struct iommu_group *group;
+	int ret;
+
+	group = iommu_group_get(dev);
+	if (group)
+		return group;
+
+	if (!dev_is_pci(dev))
+		return ERR_PTR(-EINVAL);
+
+	group = iommu_group_get_for_pci_dev(to_pci_dev(dev));
+
+	if (IS_ERR(group))
+		return group;
+
+	ret = iommu_group_add_device(group, dev);
+	if (ret) {
+		iommu_group_put(group);
+		return ERR_PTR(ret);
+	}
+
+	return group;
+}
+
 static int add_iommu_group(struct device *dev, void *data)
 {
-	struct iommu_ops *ops = data;
+	struct iommu_callback_data *cb = data;
+	const struct iommu_ops *ops = cb->ops;
 
 	if (!ops->add_device)
 		return -ENODEV;
@@ -532,7 +721,7 @@ static int iommu_bus_notifier(struct not
 			      unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct iommu_ops *ops = dev->bus->iommu_ops;
+	const struct iommu_ops *ops = dev->bus->iommu_ops;
 	struct iommu_group *group;
 	unsigned long group_action = 0;
 
@@ -585,10 +774,14 @@ static struct notifier_block iommu_bus_n
 	.notifier_call = iommu_bus_notifier,
 };
 
-static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
+static void iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
 {
+	struct iommu_callback_data cb = {
+		.ops = ops,
+	};
+
 	bus_register_notifier(bus, &iommu_bus_nb);
-	bus_for_each_dev(bus, NULL, ops, add_iommu_group);
+	bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
 }
 
 /**
@@ -604,7 +797,7 @@ static void iommu_bus_init(struct bus_ty
  * is set up. With this function the iommu-driver can set the iommu-ops
  * afterwards.
  */
-int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
+int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops)
 {
 	if (bus->iommu_ops != NULL)
 		return -EBUSY;
@@ -804,7 +997,7 @@ int iommu_map(struct iommu_domain *domai
 	size_t orig_size = size;
 	int ret = 0;
 
-	if (unlikely(domain->ops->unmap == NULL ||
+	if (unlikely(domain->ops->map == NULL ||
 		     domain->ops->pgsize_bitmap == 0UL))
 		return -ENODEV;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/iommu-sysfs.c linux-libre-3.17-rc7-gnu/drivers/iommu/iommu-sysfs.c
--- linux-libre-3.16-gnu/drivers/iommu/iommu-sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/iommu-sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * IOMMU sysfs class support
+ *
+ * Copyright (C) 2014 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@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/device.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/*
+ * We provide a common class "devices" group which initially has no attributes.
+ * As devices are added to the IOMMU, we'll add links to the group.
+ */
+static struct attribute *devices_attr[] = {
+	NULL,
+};
+
+static const struct attribute_group iommu_devices_attr_group = {
+	.name = "devices",
+	.attrs = devices_attr,
+};
+
+static const struct attribute_group *iommu_dev_groups[] = {
+	&iommu_devices_attr_group,
+	NULL,
+};
+
+static void iommu_release_device(struct device *dev)
+{
+	kfree(dev);
+}
+
+static struct class iommu_class = {
+	.name = "iommu",
+	.dev_release = iommu_release_device,
+	.dev_groups = iommu_dev_groups,
+};
+
+static int __init iommu_dev_init(void)
+{
+	return class_register(&iommu_class);
+}
+postcore_initcall(iommu_dev_init);
+
+/*
+ * Create an IOMMU device and return a pointer to it.  IOMMU specific
+ * attributes can be provided as an attribute group, allowing a unique
+ * namespace per IOMMU type.
+ */
+struct device *iommu_device_create(struct device *parent, void *drvdata,
+				   const struct attribute_group **groups,
+				   const char *fmt, ...)
+{
+	struct device *dev;
+	va_list vargs;
+	int ret;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	device_initialize(dev);
+
+	dev->class = &iommu_class;
+	dev->parent = parent;
+	dev->groups = groups;
+	dev_set_drvdata(dev, drvdata);
+
+	va_start(vargs, fmt);
+	ret = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
+	va_end(vargs);
+	if (ret)
+		goto error;
+
+	ret = device_add(dev);
+	if (ret)
+		goto error;
+
+	return dev;
+
+error:
+	put_device(dev);
+	return ERR_PTR(ret);
+}
+
+void iommu_device_destroy(struct device *dev)
+{
+	if (!dev || IS_ERR(dev))
+		return;
+
+	device_unregister(dev);
+}
+
+/*
+ * IOMMU drivers can indicate a device is managed by a given IOMMU using
+ * this interface.  A link to the device will be created in the "devices"
+ * directory of the IOMMU device in sysfs and an "iommu" link will be
+ * created under the linked device, pointing back at the IOMMU device.
+ */
+int iommu_device_link(struct device *dev, struct device *link)
+{
+	int ret;
+
+	if (!dev || IS_ERR(dev))
+		return -ENODEV;
+
+	ret = sysfs_add_link_to_group(&dev->kobj, "devices",
+				      &link->kobj, dev_name(link));
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_link_nowarn(&link->kobj, &dev->kobj, "iommu");
+	if (ret)
+		sysfs_remove_link_from_group(&dev->kobj, "devices",
+					     dev_name(link));
+
+	return ret;
+}
+
+void iommu_device_unlink(struct device *dev, struct device *link)
+{
+	if (!dev || IS_ERR(dev))
+		return;
+
+	sysfs_remove_link(&link->kobj, "iommu");
+	sysfs_remove_link_from_group(&dev->kobj, "devices", dev_name(link));
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/ipmmu-vmsa.c linux-libre-3.17-rc7-gnu/drivers/iommu/ipmmu-vmsa.c
--- linux-libre-3.16-gnu/drivers/iommu/ipmmu-vmsa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/ipmmu-vmsa.c	2014-09-28 17:29:07.000000000 -0400
@@ -1120,7 +1120,7 @@ static void ipmmu_remove_device(struct d
 	dev->archdata.iommu = NULL;
 }
 
-static struct iommu_ops ipmmu_ops = {
+static const struct iommu_ops ipmmu_ops = {
 	.domain_init = ipmmu_domain_init,
 	.domain_destroy = ipmmu_domain_destroy,
 	.attach_dev = ipmmu_attach_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/Kconfig linux-libre-3.17-rc7-gnu/drivers/iommu/Kconfig
--- linux-libre-3.16-gnu/drivers/iommu/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ config AMD_IOMMU_STATS
 
 config AMD_IOMMU_V2
 	tristate "AMD IOMMU Version 2 driver"
-	depends on AMD_IOMMU && PROFILING
+	depends on AMD_IOMMU
 	select MMU_NOTIFIER
 	---help---
 	  This option enables support for the AMD IOMMUv2 features of the IOMMU
@@ -143,16 +143,12 @@ config OMAP_IOMMU
 	depends on ARCH_OMAP2PLUS
 	select IOMMU_API
 
-config OMAP_IOVMM
-	tristate "OMAP IO Virtual Memory Manager Support"
-	depends on OMAP_IOMMU
-
 config OMAP_IOMMU_DEBUG
-       tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
-       depends on OMAP_IOVMM && DEBUG_FS
+       tristate "Export OMAP IOMMU internals in DebugFS"
+       depends on OMAP_IOMMU && DEBUG_FS
        help
          Select this to see extensive information about
-         the internal state of OMAP IOMMU/IOVMM in debugfs.
+         the internal state of OMAP IOMMU in debugfs.
 
          Say N unless you know you need this.
 
@@ -180,6 +176,7 @@ config EXYNOS_IOMMU
 	bool "Exynos IOMMU Support"
 	depends on ARCH_EXYNOS
 	select IOMMU_API
+	select ARM_DMA_USE_IOMMU
 	help
 	  Support for the IOMMU (System MMU) of Samsung Exynos application
 	  processor family. This enables H/W multimedia accelerators to see
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/Makefile linux-libre-3.17-rc7-gnu/drivers/iommu/Makefile
--- linux-libre-3.16-gnu/drivers/iommu/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,6 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
 obj-$(CONFIG_IOMMU_API) += iommu-traces.o
+obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
@@ -11,7 +12,6 @@ obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
-obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/msm_iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/msm_iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/msm_iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/msm_iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -674,7 +674,7 @@ fail:
 	return 0;
 }
 
-static struct iommu_ops msm_iommu_ops = {
+static const struct iommu_ops msm_iommu_ops = {
 	.domain_init = msm_iommu_domain_init,
 	.domain_destroy = msm_iommu_domain_destroy,
 	.attach_dev = msm_iommu_attach_dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/omap-iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/omap-iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -959,31 +959,18 @@ static int omap_iommu_probe(struct platf
 			return err;
 		if (obj->nr_tlb_entries != 32 && obj->nr_tlb_entries != 8)
 			return -EINVAL;
-		/*
-		 * da_start and da_end are needed for omap-iovmm, so hardcode
-		 * these values as used by OMAP3 ISP - the only user for
-		 * omap-iovmm
-		 */
-		obj->da_start = 0;
-		obj->da_end = 0xfffff000;
 		if (of_find_property(of, "ti,iommu-bus-err-back", NULL))
 			obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN;
 	} else {
 		obj->nr_tlb_entries = pdata->nr_tlb_entries;
 		obj->name = pdata->name;
-		obj->da_start = pdata->da_start;
-		obj->da_end = pdata->da_end;
 	}
-	if (obj->da_end <= obj->da_start)
-		return -EINVAL;
 
 	obj->dev = &pdev->dev;
 	obj->ctx = (void *)obj + sizeof(*obj);
 
 	spin_lock_init(&obj->iommu_lock);
-	mutex_init(&obj->mmap_lock);
 	spin_lock_init(&obj->page_table_lock);
-	INIT_LIST_HEAD(&obj->mmap);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	obj->regbase = devm_ioremap_resource(obj->dev, res);
@@ -1291,7 +1278,7 @@ static void omap_iommu_remove_device(str
 	kfree(arch_data);
 }
 
-static struct iommu_ops omap_iommu_ops = {
+static const struct iommu_ops omap_iommu_ops = {
 	.domain_init	= omap_iommu_domain_init,
 	.domain_destroy	= omap_iommu_domain_destroy,
 	.attach_dev	= omap_iommu_attach_dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/omap-iommu-debug.c linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu-debug.c
--- linux-libre-3.16-gnu/drivers/iommu/omap-iommu-debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu-debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -213,116 +213,6 @@ static ssize_t debug_read_pagetable(stru
 	return bytes;
 }
 
-static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct device *dev = file->private_data;
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	char *p, *buf;
-	struct iovm_struct *tmp;
-	int uninitialized_var(i);
-	ssize_t bytes;
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
-		     "No", "start", "end", "size", "flags");
-	p += sprintf(p, "-------------------------------------------------\n");
-
-	mutex_lock(&iommu_debug_lock);
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		size_t len;
-		const char *str = "%3d %08x-%08x %6x %8x\n";
-		const int maxcol = 39;
-
-		len = tmp->da_end - tmp->da_start;
-		p += snprintf(p, maxcol, str,
-			      i, tmp->da_start, tmp->da_end, len, tmp->flags);
-
-		if (PAGE_SIZE - (p - buf) < maxcol)
-			break;
-		i++;
-	}
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	struct device *dev = file->private_data;
-	char *p, *buf;
-	struct iovm_struct *area;
-	ssize_t bytes;
-
-	count = min_t(ssize_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	area = omap_find_iovm_area(dev, (u32)ppos);
-	if (!area) {
-		bytes = -EINVAL;
-		goto err_out;
-	}
-	memcpy(p, area->va, count);
-	p += count;
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct device *dev = file->private_data;
-	struct iovm_struct *area;
-	char *p, *buf;
-
-	count = min_t(size_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	if (copy_from_user(p, userbuf, count)) {
-		count =  -EFAULT;
-		goto err_out;
-	}
-
-	area = omap_find_iovm_area(dev, (u32)ppos);
-	if (!area) {
-		count = -EINVAL;
-		goto err_out;
-	}
-	memcpy(area->va, p, count);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return count;
-}
-
 #define DEBUG_FOPS(name)						\
 	static const struct file_operations debug_##name##_fops = {	\
 		.open = simple_open,					\
@@ -342,8 +232,6 @@ DEBUG_FOPS_RO(ver);
 DEBUG_FOPS_RO(regs);
 DEBUG_FOPS_RO(tlb);
 DEBUG_FOPS(pagetable);
-DEBUG_FOPS_RO(mmap);
-DEBUG_FOPS(mem);
 
 #define __DEBUG_ADD_FILE(attr, mode)					\
 	{								\
@@ -389,8 +277,6 @@ static int iommu_debug_register(struct d
 	DEBUG_ADD_FILE_RO(regs);
 	DEBUG_ADD_FILE_RO(tlb);
 	DEBUG_ADD_FILE(pagetable);
-	DEBUG_ADD_FILE_RO(mmap);
-	DEBUG_ADD_FILE(mem);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/omap-iommu.h linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu.h
--- linux-libre-3.16-gnu/drivers/iommu/omap-iommu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iommu.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,12 +46,7 @@ struct omap_iommu {
 
 	int		nr_tlb_entries;
 
-	struct list_head	mmap;
-	struct mutex		mmap_lock; /* protect mmap */
-
 	void *ctx; /* iommu context: registres saved area */
-	u32 da_start;
-	u32 da_end;
 
 	int has_bus_err_back;
 };
@@ -154,9 +149,12 @@ static inline struct omap_iommu *dev_to_
 #define MMU_RAM_PADDR_MASK \
 	((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
 
+#define MMU_RAM_ENDIAN_SHIFT	9
 #define MMU_RAM_ENDIAN_MASK	(1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ENDIAN_LITTLE	(0 << MMU_RAM_ENDIAN_SHIFT)
 #define MMU_RAM_ENDIAN_BIG	(1 << MMU_RAM_ENDIAN_SHIFT)
 
+#define MMU_RAM_ELSZ_SHIFT	7
 #define MMU_RAM_ELSZ_MASK	(3 << MMU_RAM_ELSZ_SHIFT)
 #define MMU_RAM_ELSZ_8		(0 << MMU_RAM_ELSZ_SHIFT)
 #define MMU_RAM_ELSZ_16		(1 << MMU_RAM_ELSZ_SHIFT)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/omap-iovmm.c linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iovmm.c
--- linux-libre-3.16-gnu/drivers/iommu/omap-iovmm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/omap-iovmm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,791 +0,0 @@
-/*
- * omap iommu: simple virtual address space management
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/scatterlist.h>
-#include <linux/iommu.h>
-#include <linux/omap-iommu.h>
-#include <linux/platform_data/iommu-omap.h>
-
-#include <asm/cacheflush.h>
-#include <asm/mach/map.h>
-
-#include "omap-iopgtable.h"
-#include "omap-iommu.h"
-
-/*
- * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
- *
- * lower 16 bit is used for h/w and upper 16 bit is for s/w.
- */
-#define IOVMF_SW_SHIFT		16
-
-/*
- * iovma: h/w flags derived from cam and ram attribute
- */
-#define IOVMF_CAM_MASK		(~((1 << 10) - 1))
-#define IOVMF_RAM_MASK		(~IOVMF_CAM_MASK)
-
-#define IOVMF_PGSZ_MASK		(3 << 0)
-#define IOVMF_PGSZ_1M		MMU_CAM_PGSZ_1M
-#define IOVMF_PGSZ_64K		MMU_CAM_PGSZ_64K
-#define IOVMF_PGSZ_4K		MMU_CAM_PGSZ_4K
-#define IOVMF_PGSZ_16M		MMU_CAM_PGSZ_16M
-
-#define IOVMF_ENDIAN_MASK	(1 << 9)
-#define IOVMF_ENDIAN_BIG	MMU_RAM_ENDIAN_BIG
-
-#define IOVMF_ELSZ_MASK		(3 << 7)
-#define IOVMF_ELSZ_16		MMU_RAM_ELSZ_16
-#define IOVMF_ELSZ_32		MMU_RAM_ELSZ_32
-#define IOVMF_ELSZ_NONE		MMU_RAM_ELSZ_NONE
-
-#define IOVMF_MIXED_MASK	(1 << 6)
-#define IOVMF_MIXED		MMU_RAM_MIXED
-
-/*
- * iovma: s/w flags, used for mapping and umapping internally.
- */
-#define IOVMF_MMIO		(1 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC		(2 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC_MASK	(3 << IOVMF_SW_SHIFT)
-
-/* "superpages" is supported just with physically linear pages */
-#define IOVMF_DISCONT		(1 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR		(2 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR_MASK	(3 << (2 + IOVMF_SW_SHIFT))
-
-#define IOVMF_DA_FIXED		(1 << (4 + IOVMF_SW_SHIFT))
-
-static struct kmem_cache *iovm_area_cachep;
-
-/* return the offset of the first scatterlist entry in a sg table */
-static unsigned int sgtable_offset(const struct sg_table *sgt)
-{
-	if (!sgt || !sgt->nents)
-		return 0;
-
-	return sgt->sgl->offset;
-}
-
-/* return total bytes of sg buffers */
-static size_t sgtable_len(const struct sg_table *sgt)
-{
-	unsigned int i, total = 0;
-	struct scatterlist *sg;
-
-	if (!sgt)
-		return 0;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-
-		bytes = sg->length + sg->offset;
-
-		if (!iopgsz_ok(bytes)) {
-			pr_err("%s: sg[%d] not iommu pagesize(%u %u)\n",
-			       __func__, i, bytes, sg->offset);
-			return 0;
-		}
-
-		if (i && sg->offset) {
-			pr_err("%s: sg[%d] offset not allowed in internal entries\n",
-				__func__, i);
-			return 0;
-		}
-
-		total += bytes;
-	}
-
-	return total;
-}
-#define sgtable_ok(x)	(!!sgtable_len(x))
-
-static unsigned max_alignment(u32 addr)
-{
-	int i;
-	unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
-	for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
-		;
-	return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
-}
-
-/*
- * calculate the optimal number sg elements from total bytes based on
- * iommu superpages
- */
-static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
-{
-	unsigned nr_entries = 0, ent_sz;
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
-		pr_err("%s: wrong size %08x\n", __func__, bytes);
-		return 0;
-	}
-
-	while (bytes) {
-		ent_sz = max_alignment(da | pa);
-		ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
-		nr_entries++;
-		da += ent_sz;
-		pa += ent_sz;
-		bytes -= ent_sz;
-	}
-
-	return nr_entries;
-}
-
-/* allocate and initialize sg_table header(a kind of 'superblock') */
-static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
-							u32 da, u32 pa)
-{
-	unsigned int nr_entries;
-	int err;
-	struct sg_table *sgt;
-
-	if (!bytes)
-		return ERR_PTR(-EINVAL);
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE))
-		return ERR_PTR(-EINVAL);
-
-	if (flags & IOVMF_LINEAR) {
-		nr_entries = sgtable_nents(bytes, da, pa);
-		if (!nr_entries)
-			return ERR_PTR(-EINVAL);
-	} else
-		nr_entries =  bytes / PAGE_SIZE;
-
-	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-	if (!sgt)
-		return ERR_PTR(-ENOMEM);
-
-	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
-	if (err) {
-		kfree(sgt);
-		return ERR_PTR(err);
-	}
-
-	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
-
-	return sgt;
-}
-
-/* free sg_table header(a kind of superblock) */
-static void sgtable_free(struct sg_table *sgt)
-{
-	if (!sgt)
-		return;
-
-	sg_free_table(sgt);
-	kfree(sgt);
-
-	pr_debug("%s: sgt:%p\n", __func__, sgt);
-}
-
-/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
-static void *vmap_sg(const struct sg_table *sgt)
-{
-	u32 va;
-	size_t total;
-	unsigned int i;
-	struct scatterlist *sg;
-	struct vm_struct *new;
-	const struct mem_type *mtype;
-
-	mtype = get_mem_type(MT_DEVICE);
-	if (!mtype)
-		return ERR_PTR(-EINVAL);
-
-	total = sgtable_len(sgt);
-	if (!total)
-		return ERR_PTR(-EINVAL);
-
-	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-	va = (u32)new->addr;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-		u32 pa;
-		int err;
-
-		pa = sg_phys(sg) - sg->offset;
-		bytes = sg->length + sg->offset;
-
-		BUG_ON(bytes != PAGE_SIZE);
-
-		err = ioremap_page(va,  pa, mtype);
-		if (err)
-			goto err_out;
-
-		va += bytes;
-	}
-
-	flush_cache_vmap((unsigned long)new->addr,
-				(unsigned long)(new->addr + total));
-	return new->addr;
-
-err_out:
-	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
-	vunmap(new->addr);
-	return ERR_PTR(-EAGAIN);
-}
-
-static inline void vunmap_sg(const void *va)
-{
-	vunmap(va);
-}
-
-static struct iovm_struct *__find_iovm_area(struct omap_iommu *obj,
-							const u32 da)
-{
-	struct iovm_struct *tmp;
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
-			size_t len;
-
-			len = tmp->da_end - tmp->da_start;
-
-			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
-				__func__, tmp->da_start, da, tmp->da_end, len,
-				tmp->flags);
-
-			return tmp;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * omap_find_iovm_area  -  find iovma which includes @da
- * @dev:	client device
- * @da:		iommu device virtual address
- *
- * Find the existing iovma starting at @da
- */
-struct iovm_struct *omap_find_iovm_area(struct device *dev, u32 da)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-	area = __find_iovm_area(obj, da);
-	mutex_unlock(&obj->mmap_lock);
-
-	return area;
-}
-EXPORT_SYMBOL_GPL(omap_find_iovm_area);
-
-/*
- * This finds the hole(area) which fits the requested address and len
- * in iovmas mmap, and returns the new allocated iovma.
- */
-static struct iovm_struct *alloc_iovm_area(struct omap_iommu *obj, u32 da,
-					   size_t bytes, u32 flags)
-{
-	struct iovm_struct *new, *tmp;
-	u32 start, prev_end, alignment;
-
-	if (!obj || !bytes)
-		return ERR_PTR(-EINVAL);
-
-	start = da;
-	alignment = PAGE_SIZE;
-
-	if (~flags & IOVMF_DA_FIXED) {
-		/* Don't map address 0 */
-		start = obj->da_start ? obj->da_start : alignment;
-
-		if (flags & IOVMF_LINEAR)
-			alignment = iopgsz_max(bytes);
-		start = roundup(start, alignment);
-	} else if (start < obj->da_start || start > obj->da_end ||
-					obj->da_end - start < bytes) {
-		return ERR_PTR(-EINVAL);
-	}
-
-	tmp = NULL;
-	if (list_empty(&obj->mmap))
-		goto found;
-
-	prev_end = 0;
-	list_for_each_entry(tmp, &obj->mmap, list) {
-
-		if (prev_end > start)
-			break;
-
-		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
-			goto found;
-
-		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
-			start = roundup(tmp->da_end + 1, alignment);
-
-		prev_end = tmp->da_end;
-	}
-
-	if ((start >= prev_end) && (obj->da_end - start >= bytes))
-		goto found;
-
-	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
-		__func__, da, bytes, flags);
-
-	return ERR_PTR(-EINVAL);
-
-found:
-	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-
-	new->iommu = obj;
-	new->da_start = start;
-	new->da_end = start + bytes;
-	new->flags = flags;
-
-	/*
-	 * keep ascending order of iovmas
-	 */
-	if (tmp)
-		list_add_tail(&new->list, &tmp->list);
-	else
-		list_add(&new->list, &obj->mmap);
-
-	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
-		__func__, new->da_start, start, new->da_end, bytes, flags);
-
-	return new;
-}
-
-static void free_iovm_area(struct omap_iommu *obj, struct iovm_struct *area)
-{
-	size_t bytes;
-
-	BUG_ON(!obj || !area);
-
-	bytes = area->da_end - area->da_start;
-
-	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
-		__func__, area->da_start, area->da_end, bytes, area->flags);
-
-	list_del(&area->list);
-	kmem_cache_free(iovm_area_cachep, area);
-}
-
-/**
- * omap_da_to_va - convert (d) to (v)
- * @dev:	client device
- * @da:		iommu device virtual address
- * @va:		mpu virtual address
- *
- * Returns mpu virtual addr which corresponds to a given device virtual addr
- */
-void *omap_da_to_va(struct device *dev, u32 da)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	void *va = NULL;
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-	va = area->va;
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return va;
-}
-EXPORT_SYMBOL_GPL(omap_da_to_va);
-
-static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
-{
-	unsigned int i;
-	struct scatterlist *sg;
-	void *va = _va;
-	void *va_end;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		struct page *pg;
-		const size_t bytes = PAGE_SIZE;
-
-		/*
-		 * iommu 'superpage' isn't supported with 'omap_iommu_vmalloc()'
-		 */
-		pg = vmalloc_to_page(va);
-		BUG_ON(!pg);
-		sg_set_page(sg, pg, bytes, 0);
-
-		va += bytes;
-	}
-
-	va_end = _va + PAGE_SIZE * i;
-}
-
-static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
-{
-	/*
-	 * Actually this is not necessary at all, just exists for
-	 * consistency of the code readability.
-	 */
-	BUG_ON(!sgt);
-}
-
-/* create 'da' <-> 'pa' mapping from 'sgt' */
-static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
-			const struct sg_table *sgt, u32 flags)
-{
-	int err;
-	unsigned int i, j;
-	struct scatterlist *sg;
-	u32 da = new->da_start;
-
-	if (!domain || !sgt)
-		return -EINVAL;
-
-	BUG_ON(!sgtable_ok(sgt));
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		u32 pa;
-		size_t bytes;
-
-		pa = sg_phys(sg) - sg->offset;
-		bytes = sg->length + sg->offset;
-
-		flags &= ~IOVMF_PGSZ_MASK;
-
-		if (bytes_to_iopgsz(bytes) < 0)
-			goto err_out;
-
-		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
-			 i, da, pa, bytes);
-
-		err = iommu_map(domain, da, pa, bytes, flags);
-		if (err)
-			goto err_out;
-
-		da += bytes;
-	}
-	return 0;
-
-err_out:
-	da = new->da_start;
-
-	for_each_sg(sgt->sgl, sg, i, j) {
-		size_t bytes;
-
-		bytes = sg->length + sg->offset;
-
-		/* ignore failures.. we're already handling one */
-		iommu_unmap(domain, da, bytes);
-
-		da += bytes;
-	}
-	return err;
-}
-
-/* release 'da' <-> 'pa' mapping */
-static void unmap_iovm_area(struct iommu_domain *domain, struct omap_iommu *obj,
-						struct iovm_struct *area)
-{
-	u32 start;
-	size_t total = area->da_end - area->da_start;
-	const struct sg_table *sgt = area->sgt;
-	struct scatterlist *sg;
-	int i;
-	size_t unmapped;
-
-	BUG_ON(!sgtable_ok(sgt));
-	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
-
-	start = area->da_start;
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-
-		bytes = sg->length + sg->offset;
-
-		unmapped = iommu_unmap(domain, start, bytes);
-		if (unmapped < bytes)
-			break;
-
-		dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
-				__func__, start, bytes, area->flags);
-
-		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
-		total -= bytes;
-		start += bytes;
-	}
-	BUG_ON(total);
-}
-
-/* template function for all unmapping */
-static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
-				      struct omap_iommu *obj, const u32 da,
-				      void (*fn)(const void *), u32 flags)
-{
-	struct sg_table *sgt = NULL;
-	struct iovm_struct *area;
-
-	if (!IS_ALIGNED(da, PAGE_SIZE)) {
-		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
-		return NULL;
-	}
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-
-	if ((area->flags & flags) != flags) {
-		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
-			area->flags);
-		goto out;
-	}
-	sgt = (struct sg_table *)area->sgt;
-
-	unmap_iovm_area(domain, obj, area);
-
-	fn(area->va);
-
-	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
-		area->da_start, da, area->da_end,
-		area->da_end - area->da_start, area->flags);
-
-	free_iovm_area(obj, area);
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return sgt;
-}
-
-static u32 map_iommu_region(struct iommu_domain *domain, struct omap_iommu *obj,
-				u32 da, const struct sg_table *sgt, void *va,
-				size_t bytes, u32 flags)
-{
-	int err = -ENOMEM;
-	struct iovm_struct *new;
-
-	mutex_lock(&obj->mmap_lock);
-
-	new = alloc_iovm_area(obj, da, bytes, flags);
-	if (IS_ERR(new)) {
-		err = PTR_ERR(new);
-		goto err_alloc_iovma;
-	}
-	new->va = va;
-	new->sgt = sgt;
-
-	if (map_iovm_area(domain, new, sgt, new->flags))
-		goto err_map;
-
-	mutex_unlock(&obj->mmap_lock);
-
-	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
-		__func__, new->da_start, bytes, new->flags, va);
-
-	return new->da_start;
-
-err_map:
-	free_iovm_area(obj, new);
-err_alloc_iovma:
-	mutex_unlock(&obj->mmap_lock);
-	return err;
-}
-
-static inline u32
-__iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj,
-				u32 da, const struct sg_table *sgt,
-				void *va, size_t bytes, u32 flags)
-{
-	return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
-}
-
-/**
- * omap_iommu_vmap  -  (d)-(p)-(v) address mapper
- * @domain:	iommu domain
- * @dev:	client device
- * @sgt:	address of scatter gather table
- * @flags:	iovma and page property
- *
- * Creates 1-n-1 mapping with given @sgt and returns @da.
- * All @sgt element must be io page size aligned.
- */
-u32 omap_iommu_vmap(struct iommu_domain *domain, struct device *dev, u32 da,
-		const struct sg_table *sgt, u32 flags)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	size_t bytes;
-	void *va = NULL;
-
-	if (!obj || !obj->dev || !sgt)
-		return -EINVAL;
-
-	bytes = sgtable_len(sgt);
-	if (!bytes)
-		return -EINVAL;
-	bytes = PAGE_ALIGN(bytes);
-
-	if (flags & IOVMF_MMIO) {
-		va = vmap_sg(sgt);
-		if (IS_ERR(va))
-			return PTR_ERR(va);
-	}
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_MMIO;
-
-	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		vunmap_sg(va);
-
-	return da + sgtable_offset(sgt);
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vmap);
-
-/**
- * omap_iommu_vunmap  -  release virtual mapping obtained by 'omap_iommu_vmap()'
- * @domain:	iommu domain
- * @dev:	client device
- * @da:		iommu device virtual address
- *
- * Free the iommu virtually contiguous memory area starting at
- * @da, which was returned by 'omap_iommu_vmap()'.
- */
-struct sg_table *
-omap_iommu_vunmap(struct iommu_domain *domain, struct device *dev, u32 da)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	struct sg_table *sgt;
-	/*
-	 * 'sgt' is allocated before 'omap_iommu_vmalloc()' is called.
-	 * Just returns 'sgt' to the caller to free
-	 */
-	da &= PAGE_MASK;
-	sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
-					IOVMF_DISCONT | IOVMF_MMIO);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	return sgt;
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vunmap);
-
-/**
- * omap_iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
- * @dev:	client device
- * @da:		contiguous iommu virtual memory
- * @bytes:	allocation size
- * @flags:	iovma and page property
- *
- * Allocate @bytes linearly and creates 1-n-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32
-omap_iommu_vmalloc(struct iommu_domain *domain, struct device *dev, u32 da,
-						size_t bytes, u32 flags)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	void *va;
-	struct sg_table *sgt;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = vmalloc(bytes);
-	if (!va)
-		return -ENOMEM;
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_ALLOC;
-
-	sgt = sgtable_alloc(bytes, flags, da, 0);
-	if (IS_ERR(sgt)) {
-		da = PTR_ERR(sgt);
-		goto err_sgt_alloc;
-	}
-	sgtable_fill_vmalloc(sgt, va);
-
-	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		goto err_iommu_vmap;
-
-	return da;
-
-err_iommu_vmap:
-	sgtable_drain_vmalloc(sgt);
-	sgtable_free(sgt);
-err_sgt_alloc:
-	vfree(va);
-	return da;
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vmalloc);
-
-/**
- * omap_iommu_vfree  -  release memory allocated by 'omap_iommu_vmalloc()'
- * @dev:	client device
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually continuous memory area starting at
- * @da, as obtained from 'omap_iommu_vmalloc()'.
- */
-void omap_iommu_vfree(struct iommu_domain *domain, struct device *dev,
-								const u32 da)
-{
-	struct omap_iommu *obj = dev_to_omap_iommu(dev);
-	struct sg_table *sgt;
-
-	sgt = unmap_vm_area(domain, obj, da, vfree,
-						IOVMF_DISCONT | IOVMF_ALLOC);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vfree);
-
-static int __init iovmm_init(void)
-{
-	const unsigned long flags = SLAB_HWCACHE_ALIGN;
-	struct kmem_cache *p;
-
-	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
-			      flags, NULL);
-	if (!p)
-		return -ENOMEM;
-	iovm_area_cachep = p;
-
-	return 0;
-}
-module_init(iovmm_init);
-
-static void __exit iovmm_exit(void)
-{
-	kmem_cache_destroy(iovm_area_cachep);
-}
-module_exit(iovmm_exit);
-
-MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/pci.h linux-libre-3.17-rc7-gnu/drivers/iommu/pci.h
--- linux-libre-3.16-gnu/drivers/iommu/pci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/pci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright (C) 2013 Red Hat, Inc.
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- */
-#ifndef __IOMMU_PCI_H
-#define __IOMMU_PCI_H
-
-/* Helper function for swapping pci device reference */
-static inline void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
-{
-	pci_dev_put(*from);
-	*from = to;
-}
-
-#endif  /* __IOMMU_PCI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/shmobile-iommu.c linux-libre-3.17-rc7-gnu/drivers/iommu/shmobile-iommu.c
--- linux-libre-3.16-gnu/drivers/iommu/shmobile-iommu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/shmobile-iommu.c	2014-09-28 17:29:07.000000000 -0400
@@ -354,7 +354,7 @@ static int shmobile_iommu_add_device(str
 	return 0;
 }
 
-static struct iommu_ops shmobile_iommu_ops = {
+static const struct iommu_ops shmobile_iommu_ops = {
 	.domain_init = shmobile_iommu_domain_init,
 	.domain_destroy = shmobile_iommu_domain_destroy,
 	.attach_dev = shmobile_iommu_attach_device,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/tegra-gart.c linux-libre-3.17-rc7-gnu/drivers/iommu/tegra-gart.c
--- linux-libre-3.16-gnu/drivers/iommu/tegra-gart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/tegra-gart.c	2014-09-28 17:29:07.000000000 -0400
@@ -309,7 +309,7 @@ static int gart_iommu_domain_has_cap(str
 	return 0;
 }
 
-static struct iommu_ops gart_iommu_ops = {
+static const struct iommu_ops gart_iommu_ops = {
 	.domain_init	= gart_iommu_domain_init,
 	.domain_destroy	= gart_iommu_domain_destroy,
 	.attach_dev	= gart_iommu_attach_dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/iommu/tegra-smmu.c linux-libre-3.17-rc7-gnu/drivers/iommu/tegra-smmu.c
--- linux-libre-3.16-gnu/drivers/iommu/tegra-smmu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/iommu/tegra-smmu.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,8 @@
 #include <linux/of_iommu.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
-#include <linux/tegra-ahb.h>
+
+#include <soc/tegra/ahb.h>
 
 #include <asm/page.h>
 #include <asm/cacheflush.h>
@@ -947,7 +948,7 @@ static void smmu_iommu_domain_destroy(st
 	dev_dbg(smmu->dev, "smmu_as@%p\n", as);
 }
 
-static struct iommu_ops smmu_iommu_ops = {
+static const struct iommu_ops smmu_iommu_ops = {
 	.domain_init	= smmu_iommu_domain_init,
 	.domain_destroy	= smmu_iommu_domain_destroy,
 	.attach_dev	= smmu_iommu_attach_dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ipack/carriers/tpci200.c linux-libre-3.17-rc7-gnu/drivers/ipack/carriers/tpci200.c
--- linux-libre-3.16-gnu/drivers/ipack/carriers/tpci200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ipack/carriers/tpci200.c	2014-09-28 17:29:07.000000000 -0400
@@ -618,7 +618,7 @@ static void tpci200_pci_remove(struct pc
 	__tpci200_pci_remove(tpci200);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
+static const struct pci_device_id tpci200_idtable[] = {
 	{ TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
 	  TPCI200_SUBDEVICE_ID },
 	{ 0, },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ipack/devices/ipoctal.c linux-libre-3.17-rc7-gnu/drivers/ipack/devices/ipoctal.c
--- linux-libre-3.16-gnu/drivers/ipack/devices/ipoctal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ipack/devices/ipoctal.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,19 +177,20 @@ static void ipoctal_irq_tx(struct ipocta
 	if (channel->nb_bytes == 0)
 		return;
 
+	spin_lock(&channel->lock);
 	value = channel->tty_port.xmit_buf[*pointer_write];
 	iowrite8(value, &channel->regs->w.thr);
 	channel->stats.tx++;
 	(*pointer_write)++;
 	*pointer_write = *pointer_write % PAGE_SIZE;
 	channel->nb_bytes--;
+	spin_unlock(&channel->lock);
 }
 
 static void ipoctal_irq_channel(struct ipoctal_channel *channel)
 {
 	u8 isr, sr;
 
-	spin_lock(&channel->lock);
 	/* The HW is organized in pair of channels.  See which register we need
 	 * to read from */
 	isr = ioread8(&channel->block_regs->r.isr);
@@ -213,8 +214,6 @@ static void ipoctal_irq_channel(struct i
 	/* TX of each character */
 	if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
 		ipoctal_irq_tx(channel);
-
-	spin_unlock(&channel->lock);
 }
 
 static irqreturn_t ipoctal_irq_handler(void *arg)
@@ -324,13 +323,6 @@ static int ipoctal_inst_slot(struct ipoc
 			 &block_regs[i].w.imr);
 	}
 
-	/*
-	 * IP-OCTAL has different addresses to copy its IRQ vector.
-	 * Depending of the carrier these addresses are accesible or not.
-	 * More info in the datasheet.
-	 */
-	ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
-				       ipoctal_irq_handler, ipoctal);
 	/* Dummy write */
 	iowrite8(1, ipoctal->mem8_space + 1);
 
@@ -391,6 +383,14 @@ static int ipoctal_inst_slot(struct ipoc
 		dev_set_drvdata(tty_dev, channel);
 	}
 
+	/*
+	 * IP-OCTAL has different addresses to copy its IRQ vector.
+	 * Depending of the carrier these addresses are accesible or not.
+	 * More info in the datasheet.
+	 */
+	ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
+				       ipoctal_irq_handler, ipoctal);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/exynos-combiner.c linux-libre-3.17-rc7-gnu/drivers/irqchip/exynos-combiner.c
--- linux-libre-3.16-gnu/drivers/irqchip/exynos-combiner.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/exynos-combiner.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic5.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic5.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic5.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Atmel AT91 AIC5 (Advanced Interrupt Controller) driver
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bitmap.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irq-atmel-aic-common.h"
+#include "irqchip.h"
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC5_IRQS	128
+
+#define AT91_AIC5_SSR		0x0
+#define AT91_AIC5_INTSEL_MSK	(0x7f << 0)
+
+#define AT91_AIC5_SMR			0x4
+
+#define AT91_AIC5_SVR			0x8
+#define AT91_AIC5_IVR			0x10
+#define AT91_AIC5_FVR			0x14
+#define AT91_AIC5_ISR			0x18
+
+#define AT91_AIC5_IPR0			0x20
+#define AT91_AIC5_IPR1			0x24
+#define AT91_AIC5_IPR2			0x28
+#define AT91_AIC5_IPR3			0x2c
+#define AT91_AIC5_IMR			0x30
+#define AT91_AIC5_CISR			0x34
+
+#define AT91_AIC5_IECR			0x40
+#define AT91_AIC5_IDCR			0x44
+#define AT91_AIC5_ICCR			0x48
+#define AT91_AIC5_ISCR			0x4c
+#define AT91_AIC5_EOICR			0x38
+#define AT91_AIC5_SPU			0x3c
+#define AT91_AIC5_DCR			0x6c
+
+#define AT91_AIC5_FFER			0x50
+#define AT91_AIC5_FFDR			0x54
+#define AT91_AIC5_FFSR			0x58
+
+static struct irq_domain *aic5_domain;
+
+static asmlinkage void __exception_irq_entry
+aic5_handle(struct pt_regs *regs)
+{
+	struct irq_domain_chip_generic *dgc = aic5_domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+	u32 irqnr;
+	u32 irqstat;
+
+	irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR);
+	irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR);
+
+	irqnr = irq_find_mapping(aic5_domain, irqnr);
+
+	if (!irqstat)
+		irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+	else
+		handle_IRQ(irqnr, regs);
+}
+
+static void aic5_mask(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+
+	/* Disable interrupt on AIC5 */
+	irq_gc_lock(gc);
+	irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+	irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+	gc->mask_cache &= ~d->mask;
+	irq_gc_unlock(gc);
+}
+
+static void aic5_unmask(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+
+	/* Enable interrupt on AIC5 */
+	irq_gc_lock(gc);
+	irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+	irq_reg_writel(1, gc->reg_base + AT91_AIC5_IECR);
+	gc->mask_cache |= d->mask;
+	irq_gc_unlock(gc);
+}
+
+static int aic5_retrigger(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+
+	/* Enable interrupt on AIC5 */
+	irq_gc_lock(gc);
+	irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+	irq_reg_writel(1, gc->reg_base + AT91_AIC5_ISCR);
+	irq_gc_unlock(gc);
+
+	return 0;
+}
+
+static int aic5_set_type(struct irq_data *d, unsigned type)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+	unsigned int smr;
+	int ret;
+
+	irq_gc_lock(gc);
+	irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+	smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
+	ret = aic_common_set_type(d, type, &smr);
+	if (!ret)
+		irq_reg_writel(smr, gc->reg_base + AT91_AIC5_SMR);
+	irq_gc_unlock(gc);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static void aic5_suspend(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *bgc = dgc->gc[0];
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int i;
+	u32 mask;
+
+	irq_gc_lock(bgc);
+	for (i = 0; i < dgc->irqs_per_chip; i++) {
+		mask = 1 << i;
+		if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+			continue;
+
+		irq_reg_writel(i + gc->irq_base,
+			       bgc->reg_base + AT91_AIC5_SSR);
+		if (mask & gc->wake_active)
+			irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+		else
+			irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+	}
+	irq_gc_unlock(bgc);
+}
+
+static void aic5_resume(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *bgc = dgc->gc[0];
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int i;
+	u32 mask;
+
+	irq_gc_lock(bgc);
+	for (i = 0; i < dgc->irqs_per_chip; i++) {
+		mask = 1 << i;
+		if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+			continue;
+
+		irq_reg_writel(i + gc->irq_base,
+			       bgc->reg_base + AT91_AIC5_SSR);
+		if (mask & gc->mask_cache)
+			irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+		else
+			irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+	}
+	irq_gc_unlock(bgc);
+}
+
+static void aic5_pm_shutdown(struct irq_data *d)
+{
+	struct irq_domain *domain = d->domain;
+	struct irq_domain_chip_generic *dgc = domain->gc;
+	struct irq_chip_generic *bgc = dgc->gc[0];
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int i;
+
+	irq_gc_lock(bgc);
+	for (i = 0; i < dgc->irqs_per_chip; i++) {
+		irq_reg_writel(i + gc->irq_base,
+			       bgc->reg_base + AT91_AIC5_SSR);
+		irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+		irq_reg_writel(1, bgc->reg_base + AT91_AIC5_ICCR);
+	}
+	irq_gc_unlock(bgc);
+}
+#else
+#define aic5_suspend		NULL
+#define aic5_resume		NULL
+#define aic5_pm_shutdown	NULL
+#endif /* CONFIG_PM */
+
+static void __init aic5_hw_init(struct irq_domain *domain)
+{
+	struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+	int i;
+
+	/*
+	 * Perform 8 End Of Interrupt Command to make sure AIC
+	 * will not Lock out nIRQ
+	 */
+	for (i = 0; i < 8; i++)
+		irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+
+	/*
+	 * Spurious Interrupt ID in Spurious Vector Register.
+	 * When there is no current interrupt, the IRQ Vector Register
+	 * reads the value stored in AIC_SPU
+	 */
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC5_SPU);
+
+	/* No debugging in AIC: Debug (Protect) Control Register */
+	irq_reg_writel(0, gc->reg_base + AT91_AIC5_DCR);
+
+	/* Disable and clear all interrupts initially */
+	for (i = 0; i < domain->revmap_size; i++) {
+		irq_reg_writel(i, gc->reg_base + AT91_AIC5_SSR);
+		irq_reg_writel(i, gc->reg_base + AT91_AIC5_SVR);
+		irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+		irq_reg_writel(1, gc->reg_base + AT91_AIC5_ICCR);
+	}
+}
+
+static int aic5_irq_domain_xlate(struct irq_domain *d,
+				 struct device_node *ctrlr,
+				 const u32 *intspec, unsigned int intsize,
+				 irq_hw_number_t *out_hwirq,
+				 unsigned int *out_type)
+{
+	struct irq_domain_chip_generic *dgc = d->gc;
+	struct irq_chip_generic *gc;
+	unsigned smr;
+	int ret;
+
+	if (!dgc)
+		return -EINVAL;
+
+	ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+					  out_hwirq, out_type);
+	if (ret)
+		return ret;
+
+	gc = dgc->gc[0];
+
+	irq_gc_lock(gc);
+	irq_reg_writel(*out_hwirq, gc->reg_base + AT91_AIC5_SSR);
+	smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
+	ret = aic_common_set_priority(intspec[2], &smr);
+	if (!ret)
+		irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR);
+	irq_gc_unlock(gc);
+
+	return ret;
+}
+
+static const struct irq_domain_ops aic5_irq_ops = {
+	.map	= irq_map_generic_chip,
+	.xlate	= aic5_irq_domain_xlate,
+};
+
+static void __init sama5d3_aic_irq_fixup(struct device_node *root)
+{
+	aic_common_rtc_irq_fixup(root);
+}
+
+static const struct of_device_id __initdata aic5_irq_fixups[] = {
+	{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
+	{ /* sentinel */ },
+};
+
+static int __init aic5_of_init(struct device_node *node,
+			       struct device_node *parent,
+			       int nirqs)
+{
+	struct irq_chip_generic *gc;
+	struct irq_domain *domain;
+	int nchips;
+	int i;
+
+	if (nirqs > NR_AIC5_IRQS)
+		return -EINVAL;
+
+	if (aic5_domain)
+		return -EEXIST;
+
+	domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
+				    nirqs);
+	if (IS_ERR(domain))
+		return PTR_ERR(domain);
+
+	aic_common_irq_fixup(aic5_irq_fixups);
+
+	aic5_domain = domain;
+	nchips = aic5_domain->revmap_size / 32;
+	for (i = 0; i < nchips; i++) {
+		gc = irq_get_domain_generic_chip(domain, i * 32);
+
+		gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
+		gc->chip_types[0].chip.irq_mask = aic5_mask;
+		gc->chip_types[0].chip.irq_unmask = aic5_unmask;
+		gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
+		gc->chip_types[0].chip.irq_set_type = aic5_set_type;
+		gc->chip_types[0].chip.irq_suspend = aic5_suspend;
+		gc->chip_types[0].chip.irq_resume = aic5_resume;
+		gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
+	}
+
+	aic5_hw_init(domain);
+	set_handle_irq(aic5_handle);
+
+	return 0;
+}
+
+#define NR_SAMA5D3_IRQS		50
+
+static int __init sama5d3_aic5_of_init(struct device_node *node,
+				       struct device_node *parent)
+{
+	return aic5_of_init(node, parent, NR_SAMA5D3_IRQS);
+}
+IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", sama5d3_aic5_of_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,262 @@
+/*
+ * Atmel AT91 AIC (Advanced Interrupt Controller) driver
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bitmap.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irq-atmel-aic-common.h"
+#include "irqchip.h"
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC_IRQS	32
+
+#define AT91_AIC_SMR(n)			((n) * 4)
+
+#define AT91_AIC_SVR(n)			(0x80 + ((n) * 4))
+#define AT91_AIC_IVR			0x100
+#define AT91_AIC_FVR			0x104
+#define AT91_AIC_ISR			0x108
+
+#define AT91_AIC_IPR			0x10c
+#define AT91_AIC_IMR			0x110
+#define AT91_AIC_CISR			0x114
+
+#define AT91_AIC_IECR			0x120
+#define AT91_AIC_IDCR			0x124
+#define AT91_AIC_ICCR			0x128
+#define AT91_AIC_ISCR			0x12c
+#define AT91_AIC_EOICR			0x130
+#define AT91_AIC_SPU			0x134
+#define AT91_AIC_DCR			0x138
+
+static struct irq_domain *aic_domain;
+
+static asmlinkage void __exception_irq_entry
+aic_handle(struct pt_regs *regs)
+{
+	struct irq_domain_chip_generic *dgc = aic_domain->gc;
+	struct irq_chip_generic *gc = dgc->gc[0];
+	u32 irqnr;
+	u32 irqstat;
+
+	irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
+	irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
+
+	irqnr = irq_find_mapping(aic_domain, irqnr);
+
+	if (!irqstat)
+		irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+	else
+		handle_IRQ(irqnr, regs);
+}
+
+static int aic_retrigger(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+	/* Enable interrupt on AIC5 */
+	irq_gc_lock(gc);
+	irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR);
+	irq_gc_unlock(gc);
+
+	return 0;
+}
+
+static int aic_set_type(struct irq_data *d, unsigned type)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	unsigned int smr;
+	int ret;
+
+	smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq));
+	ret = aic_common_set_type(d, type, &smr);
+	if (ret)
+		return ret;
+
+	irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void aic_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+	irq_gc_lock(gc);
+	irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR);
+	irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR);
+	irq_gc_unlock(gc);
+}
+
+static void aic_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+	irq_gc_lock(gc);
+	irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR);
+	irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR);
+	irq_gc_unlock(gc);
+}
+
+static void aic_pm_shutdown(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+	irq_gc_lock(gc);
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+	irq_gc_unlock(gc);
+}
+#else
+#define aic_suspend		NULL
+#define aic_resume		NULL
+#define aic_pm_shutdown		NULL
+#endif /* CONFIG_PM */
+
+static void __init aic_hw_init(struct irq_domain *domain)
+{
+	struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+	int i;
+
+	/*
+	 * Perform 8 End Of Interrupt Command to make sure AIC
+	 * will not Lock out nIRQ
+	 */
+	for (i = 0; i < 8; i++)
+		irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+
+	/*
+	 * Spurious Interrupt ID in Spurious Vector Register.
+	 * When there is no current interrupt, the IRQ Vector Register
+	 * reads the value stored in AIC_SPU
+	 */
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU);
+
+	/* No debugging in AIC: Debug (Protect) Control Register */
+	irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR);
+
+	/* Disable and clear all interrupts initially */
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+	irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+
+	for (i = 0; i < 32; i++)
+		irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i));
+}
+
+static int aic_irq_domain_xlate(struct irq_domain *d,
+				struct device_node *ctrlr,
+				const u32 *intspec, unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type)
+{
+	struct irq_domain_chip_generic *dgc = d->gc;
+	struct irq_chip_generic *gc;
+	unsigned smr;
+	int idx;
+	int ret;
+
+	if (!dgc)
+		return -EINVAL;
+
+	ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+					  out_hwirq, out_type);
+	if (ret)
+		return ret;
+
+	idx = intspec[0] / dgc->irqs_per_chip;
+	if (idx >= dgc->num_chips)
+		return -EINVAL;
+
+	gc = dgc->gc[idx];
+
+	irq_gc_lock(gc);
+	smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq));
+	ret = aic_common_set_priority(intspec[2], &smr);
+	if (!ret)
+		irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq));
+	irq_gc_unlock(gc);
+
+	return ret;
+}
+
+static const struct irq_domain_ops aic_irq_ops = {
+	.map	= irq_map_generic_chip,
+	.xlate	= aic_irq_domain_xlate,
+};
+
+static void __init at91sam9_aic_irq_fixup(struct device_node *root)
+{
+	aic_common_rtc_irq_fixup(root);
+}
+
+static const struct of_device_id __initdata aic_irq_fixups[] = {
+	{ .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup },
+	{ .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup },
+	{ .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup },
+	{ .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup },
+	{ /* sentinel */ },
+};
+
+static int __init aic_of_init(struct device_node *node,
+			      struct device_node *parent)
+{
+	struct irq_chip_generic *gc;
+	struct irq_domain *domain;
+
+	if (aic_domain)
+		return -EEXIST;
+
+	domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
+				    NR_AIC_IRQS);
+	if (IS_ERR(domain))
+		return PTR_ERR(domain);
+
+	aic_common_irq_fixup(aic_irq_fixups);
+
+	aic_domain = domain;
+	gc = irq_get_domain_generic_chip(domain, 0);
+
+	gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
+	gc->chip_types[0].regs.enable = AT91_AIC_IECR;
+	gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
+	gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+	gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+	gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
+	gc->chip_types[0].chip.irq_set_type = aic_set_type;
+	gc->chip_types[0].chip.irq_suspend = aic_suspend;
+	gc->chip_types[0].chip.irq_resume = aic_resume;
+	gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;
+
+	aic_hw_init(domain);
+	set_handle_irq(aic_handle);
+
+	return 0;
+}
+IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic-common.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic-common.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic-common.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,254 @@
+/*
+ * Atmel AT91 common AIC (Advanced Interrupt Controller) code shared by
+ * irq-atmel-aic and irq-atmel-aic5 drivers
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "irq-atmel-aic-common.h"
+
+#define AT91_AIC_PRIOR			GENMASK(2, 0)
+#define AT91_AIC_IRQ_MIN_PRIORITY	0
+#define AT91_AIC_IRQ_MAX_PRIORITY	7
+
+#define AT91_AIC_SRCTYPE		GENMASK(7, 6)
+#define AT91_AIC_SRCTYPE_LOW		(0 << 5)
+#define AT91_AIC_SRCTYPE_FALLING	(1 << 5)
+#define AT91_AIC_SRCTYPE_HIGH		(2 << 5)
+#define AT91_AIC_SRCTYPE_RISING		(3 << 5)
+
+struct aic_chip_data {
+	u32 ext_irqs;
+};
+
+static void aic_common_shutdown(struct irq_data *d)
+{
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
+	ct->chip.irq_mask(d);
+}
+
+int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct aic_chip_data *aic = gc->private;
+	unsigned aic_type;
+
+	switch (type) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		aic_type = AT91_AIC_SRCTYPE_HIGH;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		aic_type = AT91_AIC_SRCTYPE_RISING;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		if (!(d->mask & aic->ext_irqs))
+			return -EINVAL;
+
+		aic_type = AT91_AIC_SRCTYPE_LOW;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		if (!(d->mask & aic->ext_irqs))
+			return -EINVAL;
+
+		aic_type = AT91_AIC_SRCTYPE_FALLING;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*val &= AT91_AIC_SRCTYPE;
+	*val |= aic_type;
+
+	return 0;
+}
+
+int aic_common_set_priority(int priority, unsigned *val)
+{
+	if (priority < AT91_AIC_IRQ_MIN_PRIORITY ||
+	    priority > AT91_AIC_IRQ_MAX_PRIORITY)
+		return -EINVAL;
+
+	*val &= AT91_AIC_PRIOR;
+	*val |= priority;
+
+	return 0;
+}
+
+int aic_common_irq_domain_xlate(struct irq_domain *d,
+				struct device_node *ctrlr,
+				const u32 *intspec,
+				unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type)
+{
+	if (WARN_ON(intsize < 3))
+		return -EINVAL;
+
+	if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) ||
+		    (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
+		return -EINVAL;
+
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	return 0;
+}
+
+static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
+{
+	struct device_node *node = domain->of_node;
+	struct irq_chip_generic *gc;
+	struct aic_chip_data *aic;
+	struct property *prop;
+	const __be32 *p;
+	u32 hwirq;
+
+	gc = irq_get_domain_generic_chip(domain, 0);
+
+	aic = gc->private;
+	aic->ext_irqs |= 1;
+
+	of_property_for_each_u32(node, "atmel,external-irqs", prop, p, hwirq) {
+		gc = irq_get_domain_generic_chip(domain, hwirq);
+		if (!gc) {
+			pr_warn("AIC: external irq %d >= %d skip it\n",
+				hwirq, domain->revmap_size);
+			continue;
+		}
+
+		aic = gc->private;
+		aic->ext_irqs |= (1 << (hwirq % 32));
+	}
+}
+
+#define AT91_RTC_IDR           0x24
+#define AT91_RTC_IMR           0x28
+#define AT91_RTC_IRQ_MASK      0x1f
+
+void __init aic_common_rtc_irq_fixup(struct device_node *root)
+{
+	struct device_node *np;
+	void __iomem *regs;
+
+	np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc");
+	if (!np)
+		np = of_find_compatible_node(root, NULL,
+					     "atmel,at91sam9x5-rtc");
+
+	if (!np)
+		return;
+
+	regs = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!regs)
+		return;
+
+	writel(AT91_RTC_IRQ_MASK, regs + AT91_RTC_IDR);
+
+	iounmap(regs);
+}
+
+void __init aic_common_irq_fixup(const struct of_device_id *matches)
+{
+	struct device_node *root = of_find_node_by_path("/");
+	const struct of_device_id *match;
+
+	if (!root)
+		return;
+
+	match = of_match_node(matches, root);
+	of_node_put(root);
+
+	if (match) {
+		void (*fixup)(struct device_node *) = match->data;
+		fixup(root);
+	}
+
+	of_node_put(root);
+}
+
+struct irq_domain *__init aic_common_of_init(struct device_node *node,
+					     const struct irq_domain_ops *ops,
+					     const char *name, int nirqs)
+{
+	struct irq_chip_generic *gc;
+	struct irq_domain *domain;
+	struct aic_chip_data *aic;
+	void __iomem *reg_base;
+	int nchips;
+	int ret;
+	int i;
+
+	nchips = DIV_ROUND_UP(nirqs, 32);
+
+	reg_base = of_iomap(node, 0);
+	if (!reg_base)
+		return ERR_PTR(-ENOMEM);
+
+	aic = kcalloc(nchips, sizeof(*aic), GFP_KERNEL);
+	if (!aic) {
+		ret = -ENOMEM;
+		goto err_iounmap;
+	}
+
+	domain = irq_domain_add_linear(node, nchips * 32, ops, aic);
+	if (!domain) {
+		ret = -ENOMEM;
+		goto err_free_aic;
+	}
+
+	ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
+					     handle_level_irq, 0, 0,
+					     IRQCHIP_SKIP_SET_WAKE);
+	if (ret)
+		goto err_domain_remove;
+
+	for (i = 0; i < nchips; i++) {
+		gc = irq_get_domain_generic_chip(domain, i * 32);
+
+		gc->reg_base = reg_base;
+
+		gc->unused = 0;
+		gc->wake_enabled = ~0;
+		gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
+		gc->chip_types[0].handler = handle_fasteoi_irq;
+		gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
+		gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
+		gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
+		gc->private = &aic[i];
+	}
+
+	aic_common_ext_irq_of_init(domain);
+
+	return domain;
+
+err_domain_remove:
+	irq_domain_remove(domain);
+
+err_free_aic:
+	kfree(aic);
+
+err_iounmap:
+	iounmap(reg_base);
+
+	return ERR_PTR(ret);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic-common.h linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic-common.h
--- linux-libre-3.16-gnu/drivers/irqchip/irq-atmel-aic-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-atmel-aic-common.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * Atmel AT91 common AIC (Advanced Interrupt Controller) header file
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __IRQ_ATMEL_AIC_COMMON_H
+#define __IRQ_ATMEL_AIC_COMMON_H
+
+
+int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
+
+int aic_common_set_priority(int priority, unsigned *val);
+
+int aic_common_irq_domain_xlate(struct irq_domain *d,
+				struct device_node *ctrlr,
+				const u32 *intspec,
+				unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type);
+
+struct irq_domain *__init aic_common_of_init(struct device_node *node,
+					     const struct irq_domain_ops *ops,
+					     const char *name, int nirqs);
+
+void __init aic_common_rtc_irq_fixup(struct device_node *root);
+
+void __init aic_common_irq_fixup(const struct of_device_id *matches);
+
+#endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-crossbar.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-crossbar.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-crossbar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-crossbar.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,22 +15,31 @@
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/irq-crossbar.h>
 
 #define IRQ_FREE	-1
+#define IRQ_RESERVED	-2
+#define IRQ_SKIP	-3
 #define GIC_IRQ_START	32
 
-/*
+/**
+ * struct crossbar_device - crossbar device description
  * @int_max: maximum number of supported interrupts
+ * @safe_map: safe default value to initialize the crossbar
+ * @max_crossbar_sources: Maximum number of crossbar sources
  * @irq_map: array of interrupts to crossbar number mapping
  * @crossbar_base: crossbar base address
  * @register_offsets: offsets for each irq number
+ * @write: register write function pointer
  */
 struct crossbar_device {
 	uint int_max;
+	uint safe_map;
+	uint max_crossbar_sources;
 	uint *irq_map;
 	void __iomem *crossbar_base;
 	int *register_offsets;
-	void (*write) (int, int);
+	void (*write)(int, int);
 };
 
 static struct crossbar_device *cb;
@@ -50,11 +59,22 @@ static inline void crossbar_writeb(int i
 	writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
+static inline int get_prev_map_irq(int cb_no)
+{
+	int i;
+
+	for (i = cb->int_max - 1; i >= 0; i--)
+		if (cb->irq_map[i] == cb_no)
+			return i;
+
+	return -ENODEV;
+}
+
 static inline int allocate_free_irq(int cb_no)
 {
 	int i;
 
-	for (i = 0; i < cb->int_max; i++) {
+	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
 			cb->irq_map[i] = cb_no;
 			return i;
@@ -64,19 +84,47 @@ static inline int allocate_free_irq(int
 	return -ENODEV;
 }
 
+static inline bool needs_crossbar_write(irq_hw_number_t hw)
+{
+	int cb_no;
+
+	if (hw > GIC_IRQ_START) {
+		cb_no = cb->irq_map[hw - GIC_IRQ_START];
+		if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
+			return true;
+	}
+
+	return false;
+}
+
 static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
 			       irq_hw_number_t hw)
 {
-	cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+	if (needs_crossbar_write(hw))
+		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+
 	return 0;
 }
 
+/**
+ * crossbar_domain_unmap - unmap a crossbar<->irq connection
+ * @d: domain of irq to unmap
+ * @irq: virq number
+ *
+ * We do not maintain a use count of total number of map/unmap
+ * calls for a particular irq to find out if a irq can be really
+ * unmapped. This is because unmap is called during irq_dispose_mapping(irq),
+ * after which irq is anyways unusable. So an explicit map has to be called
+ * after that.
+ */
 static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
 	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
 
-	if (hw > GIC_IRQ_START)
+	if (needs_crossbar_write(hw)) {
 		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
+		cb->write(hw - GIC_IRQ_START, cb->safe_map);
+	}
 }
 
 static int crossbar_domain_xlate(struct irq_domain *d,
@@ -85,18 +133,41 @@ static int crossbar_domain_xlate(struct
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	unsigned long ret;
+	int ret;
+	int req_num = intspec[1];
+	int direct_map_num;
 
-	ret = allocate_free_irq(intspec[1]);
+	if (req_num >= cb->max_crossbar_sources) {
+		direct_map_num = req_num - cb->max_crossbar_sources;
+		if (direct_map_num < cb->int_max) {
+			ret = cb->irq_map[direct_map_num];
+			if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
+				/* We use the interrupt num as h/w irq num */
+				ret = direct_map_num;
+				goto found;
+			}
+		}
 
-	if (IS_ERR_VALUE(ret))
+		pr_err("%s: requested crossbar number %d > max %d\n",
+		       __func__, req_num, cb->max_crossbar_sources);
+		return -EINVAL;
+	}
+
+	ret = get_prev_map_irq(req_num);
+	if (ret >= 0)
+		goto found;
+
+	ret = allocate_free_irq(req_num);
+
+	if (ret < 0)
 		return ret;
 
+found:
 	*out_hwirq = ret + GIC_IRQ_START;
 	return 0;
 }
 
-const struct irq_domain_ops routable_irq_domain_ops = {
+static const struct irq_domain_ops routable_irq_domain_ops = {
 	.map = crossbar_domain_map,
 	.unmap = crossbar_domain_unmap,
 	.xlate = crossbar_domain_xlate
@@ -104,22 +175,36 @@ const struct irq_domain_ops routable_irq
 
 static int __init crossbar_of_init(struct device_node *node)
 {
-	int i, size, max, reserved = 0, entry;
+	int i, size, max = 0, reserved = 0, entry;
 	const __be32 *irqsr;
+	int ret = -ENOMEM;
 
 	cb = kzalloc(sizeof(*cb), GFP_KERNEL);
 
 	if (!cb)
-		return -ENOMEM;
+		return ret;
 
 	cb->crossbar_base = of_iomap(node, 0);
 	if (!cb->crossbar_base)
-		goto err1;
+		goto err_cb;
+
+	of_property_read_u32(node, "ti,max-crossbar-sources",
+			     &cb->max_crossbar_sources);
+	if (!cb->max_crossbar_sources) {
+		pr_err("missing 'ti,max-crossbar-sources' property\n");
+		ret = -EINVAL;
+		goto err_base;
+	}
 
 	of_property_read_u32(node, "ti,max-irqs", &max);
-	cb->irq_map = kzalloc(max * sizeof(int), GFP_KERNEL);
+	if (!max) {
+		pr_err("missing 'ti,max-irqs' property\n");
+		ret = -EINVAL;
+		goto err_base;
+	}
+	cb->irq_map = kcalloc(max, sizeof(int), GFP_KERNEL);
 	if (!cb->irq_map)
-		goto err2;
+		goto err_base;
 
 	cb->int_max = max;
 
@@ -135,17 +220,37 @@ static int __init crossbar_of_init(struc
 			of_property_read_u32_index(node,
 						   "ti,irqs-reserved",
 						   i, &entry);
-			if (entry > max) {
+			if (entry >= max) {
 				pr_err("Invalid reserved entry\n");
-				goto err3;
+				ret = -EINVAL;
+				goto err_irq_map;
 			}
-			cb->irq_map[entry] = 0;
+			cb->irq_map[entry] = IRQ_RESERVED;
 		}
 	}
 
-	cb->register_offsets = kzalloc(max * sizeof(int), GFP_KERNEL);
+	/* Skip irqs hardwired to bypass the crossbar */
+	irqsr = of_get_property(node, "ti,irqs-skip", &size);
+	if (irqsr) {
+		size /= sizeof(__be32);
+
+		for (i = 0; i < size; i++) {
+			of_property_read_u32_index(node,
+						   "ti,irqs-skip",
+						   i, &entry);
+			if (entry >= max) {
+				pr_err("Invalid skip entry\n");
+				ret = -EINVAL;
+				goto err_irq_map;
+			}
+			cb->irq_map[entry] = IRQ_SKIP;
+		}
+	}
+
+
+	cb->register_offsets = kcalloc(max, sizeof(int), GFP_KERNEL);
 	if (!cb->register_offsets)
-		goto err3;
+		goto err_irq_map;
 
 	of_property_read_u32(node, "ti,reg-size", &size);
 
@@ -161,7 +266,8 @@ static int __init crossbar_of_init(struc
 		break;
 	default:
 		pr_err("Invalid reg-size property\n");
-		goto err4;
+		ret = -EINVAL;
+		goto err_reg_offset;
 		break;
 	}
 
@@ -170,25 +276,37 @@ static int __init crossbar_of_init(struc
 	 * reserved irqs. so find and store the offsets once.
 	 */
 	for (i = 0; i < max; i++) {
-		if (!cb->irq_map[i])
+		if (cb->irq_map[i] == IRQ_RESERVED)
 			continue;
 
 		cb->register_offsets[i] = reserved;
 		reserved += size;
 	}
 
+	of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map);
+	/* Initialize the crossbar with safe map to start with */
+	for (i = 0; i < max; i++) {
+		if (cb->irq_map[i] == IRQ_RESERVED ||
+		    cb->irq_map[i] == IRQ_SKIP)
+			continue;
+
+		cb->write(i, cb->safe_map);
+	}
+
 	register_routable_domain_ops(&routable_irq_domain_ops);
 	return 0;
 
-err4:
+err_reg_offset:
 	kfree(cb->register_offsets);
-err3:
+err_irq_map:
 	kfree(cb->irq_map);
-err2:
+err_base:
 	iounmap(cb->crossbar_base);
-err1:
+err_cb:
 	kfree(cb);
-	return -ENOMEM;
+
+	cb = NULL;
+	return ret;
 }
 
 static const struct of_device_id crossbar_match[] __initconst = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-gic.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-gic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/arm/common/gic.c
- *
  *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -47,6 +45,7 @@
 #include <asm/exception.h>
 #include <asm/smp_plat.h>
 
+#include "irq-gic-common.h"
 #include "irqchip.h"
 
 union gic_base {
@@ -189,12 +188,6 @@ static int gic_set_type(struct irq_data
 {
 	void __iomem *base = gic_dist_base(d);
 	unsigned int gicirq = gic_irq(d);
-	u32 enablemask = 1 << (gicirq % 32);
-	u32 enableoff = (gicirq / 32) * 4;
-	u32 confmask = 0x2 << ((gicirq % 16) * 2);
-	u32 confoff = (gicirq / 16) * 4;
-	bool enabled = false;
-	u32 val;
 
 	/* Interrupt configuration for SGIs can't be changed */
 	if (gicirq < 16)
@@ -208,25 +201,7 @@ static int gic_set_type(struct irq_data
 	if (gic_arch_extn.irq_set_type)
 		gic_arch_extn.irq_set_type(d, type);
 
-	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
-	if (type == IRQ_TYPE_LEVEL_HIGH)
-		val &= ~confmask;
-	else if (type == IRQ_TYPE_EDGE_RISING)
-		val |= confmask;
-
-	/*
-	 * As recommended by the spec, disable the interrupt before changing
-	 * the configuration
-	 */
-	if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
-		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
-		enabled = true;
-	}
-
-	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
-
-	if (enabled)
-		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
+	gic_configure_irq(gicirq, type, base, NULL);
 
 	raw_spin_unlock(&irq_controller_lock);
 
@@ -388,12 +363,6 @@ static void __init gic_dist_init(struct
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Set all global interrupts to be level triggered, active low.
-	 */
-	for (i = 32; i < gic_irqs; i += 16)
-		writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
-
-	/*
 	 * Set all global interrupts to this CPU only.
 	 */
 	cpumask = gic_get_cpumask(gic);
@@ -402,18 +371,7 @@ static void __init gic_dist_init(struct
 	for (i = 32; i < gic_irqs; i += 4)
 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
-	/*
-	 * Set priority on all global interrupts.
-	 */
-	for (i = 32; i < gic_irqs; i += 4)
-		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
-
-	/*
-	 * Disable all interrupts.  Leave the PPI and SGIs alone
-	 * as these enables are banked registers.
-	 */
-	for (i = 32; i < gic_irqs; i += 32)
-		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+	gic_dist_config(base, gic_irqs, NULL);
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
 }
@@ -440,18 +398,7 @@ static void gic_cpu_init(struct gic_chip
 		if (i != cpu)
 			gic_cpu_map[i] &= ~cpu_mask;
 
-	/*
-	 * Deal with the banked PPI and SGI interrupts - disable all
-	 * PPI interrupts, ensure all SGI interrupts are enabled.
-	 */
-	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
-	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
-
-	/*
-	 * Set priority on PPI and SGI interrupts
-	 */
-	for (i = 0; i < 32; i += 4)
-		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+	gic_cpu_config(dist_base, NULL);
 
 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
 	writel_relaxed(1, base + GIC_CPU_CTRL);
@@ -920,7 +867,7 @@ static int gic_routable_irq_domain_xlate
 	return 0;
 }
 
-const struct irq_domain_ops gic_default_routable_irq_domain_ops = {
+static const struct irq_domain_ops gic_default_routable_irq_domain_ops = {
 	.map = gic_routable_irq_domain_map,
 	.unmap = gic_routable_irq_domain_unmap,
 	.xlate = gic_routable_irq_domain_xlate,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-gic-common.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-common.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-gic-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-common.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2002 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include "irq-gic-common.h"
+
+void gic_configure_irq(unsigned int irq, unsigned int type,
+		       void __iomem *base, void (*sync_access)(void))
+{
+	u32 enablemask = 1 << (irq % 32);
+	u32 enableoff = (irq / 32) * 4;
+	u32 confmask = 0x2 << ((irq % 16) * 2);
+	u32 confoff = (irq / 16) * 4;
+	bool enabled = false;
+	u32 val;
+
+	/*
+	 * Read current configuration register, and insert the config
+	 * for "irq", depending on "type".
+	 */
+	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
+	if (type == IRQ_TYPE_LEVEL_HIGH)
+		val &= ~confmask;
+	else if (type == IRQ_TYPE_EDGE_RISING)
+		val |= confmask;
+
+	/*
+	 * As recommended by the spec, disable the interrupt before changing
+	 * the configuration
+	 */
+	if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
+		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
+		if (sync_access)
+			sync_access();
+		enabled = true;
+	}
+
+	/*
+	 * Write back the new configuration, and possibly re-enable
+	 * the interrupt.
+	 */
+	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
+
+	if (enabled)
+		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
+
+	if (sync_access)
+		sync_access();
+}
+
+void __init gic_dist_config(void __iomem *base, int gic_irqs,
+			    void (*sync_access)(void))
+{
+	unsigned int i;
+
+	/*
+	 * Set all global interrupts to be level triggered, active low.
+	 */
+	for (i = 32; i < gic_irqs; i += 16)
+		writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4);
+
+	/*
+	 * Set priority on all global interrupts.
+	 */
+	for (i = 32; i < gic_irqs; i += 4)
+		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i);
+
+	/*
+	 * Disable all interrupts.  Leave the PPI and SGIs alone
+	 * as they are enabled by redistributor registers.
+	 */
+	for (i = 32; i < gic_irqs; i += 32)
+		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8);
+
+	if (sync_access)
+		sync_access();
+}
+
+void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
+{
+	int i;
+
+	/*
+	 * Deal with the banked PPI and SGI interrupts - disable all
+	 * PPI interrupts, ensure all SGI interrupts are enabled.
+	 */
+	writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR);
+	writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET);
+
+	/*
+	 * Set priority on PPI and SGI interrupts
+	 */
+	for (i = 0; i < 32; i += 4)
+		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+	if (sync_access)
+		sync_access();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-gic-common.h linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-common.h
--- linux-libre-3.16-gnu/drivers/irqchip/irq-gic-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-common.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2002 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 _IRQ_GIC_COMMON_H
+#define _IRQ_GIC_COMMON_H
+
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+
+void gic_configure_irq(unsigned int irq, unsigned int type,
+                       void __iomem *base, void (*sync_access)(void));
+void gic_dist_config(void __iomem *base, int gic_irqs,
+		     void (*sync_access)(void));
+void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+
+#endif /* _IRQ_GIC_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-gic-v3.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-v3.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-gic-v3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-gic-v3.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.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 <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+
+#include <linux/irqchip/arm-gic-v3.h>
+
+#include <asm/cputype.h>
+#include <asm/exception.h>
+#include <asm/smp_plat.h>
+
+#include "irq-gic-common.h"
+#include "irqchip.h"
+
+struct gic_chip_data {
+	void __iomem		*dist_base;
+	void __iomem		**redist_base;
+	void __iomem * __percpu	*rdist;
+	struct irq_domain	*domain;
+	u64			redist_stride;
+	u32			redist_regions;
+	unsigned int		irq_nr;
+};
+
+static struct gic_chip_data gic_data __read_mostly;
+
+#define gic_data_rdist()		(this_cpu_ptr(gic_data.rdist))
+#define gic_data_rdist_rd_base()	(*gic_data_rdist())
+#define gic_data_rdist_sgi_base()	(gic_data_rdist_rd_base() + SZ_64K)
+
+/* Our default, arbitrary priority value. Linux only uses one anyway. */
+#define DEFAULT_PMR_VALUE	0xf0
+
+static inline unsigned int gic_irq(struct irq_data *d)
+{
+	return d->hwirq;
+}
+
+static inline int gic_irq_in_rdist(struct irq_data *d)
+{
+	return gic_irq(d) < 32;
+}
+
+static inline void __iomem *gic_dist_base(struct irq_data *d)
+{
+	if (gic_irq_in_rdist(d))	/* SGI+PPI -> SGI_base for this CPU */
+		return gic_data_rdist_sgi_base();
+
+	if (d->hwirq <= 1023)		/* SPI -> dist_base */
+		return gic_data.dist_base;
+
+	if (d->hwirq >= 8192)
+		BUG();		/* LPI Detected!!! */
+
+	return NULL;
+}
+
+static void gic_do_wait_for_rwp(void __iomem *base)
+{
+	u32 count = 1000000;	/* 1s! */
+
+	while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
+		count--;
+		if (!count) {
+			pr_err_ratelimited("RWP timeout, gone fishing\n");
+			return;
+		}
+		cpu_relax();
+		udelay(1);
+	};
+}
+
+/* Wait for completion of a distributor change */
+static void gic_dist_wait_for_rwp(void)
+{
+	gic_do_wait_for_rwp(gic_data.dist_base);
+}
+
+/* Wait for completion of a redistributor change */
+static void gic_redist_wait_for_rwp(void)
+{
+	gic_do_wait_for_rwp(gic_data_rdist_rd_base());
+}
+
+/* Low level accessors */
+static u64 __maybe_unused gic_read_iar(void)
+{
+	u64 irqstat;
+
+	asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+	return irqstat;
+}
+
+static void __maybe_unused gic_write_pmr(u64 val)
+{
+	asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
+}
+
+static void __maybe_unused gic_write_ctlr(u64 val)
+{
+	asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
+	isb();
+}
+
+static void __maybe_unused gic_write_grpen1(u64 val)
+{
+	asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val));
+	isb();
+}
+
+static void __maybe_unused gic_write_sgi1r(u64 val)
+{
+	asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+}
+
+static void gic_enable_sre(void)
+{
+	u64 val;
+
+	asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
+	val |= ICC_SRE_EL1_SRE;
+	asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val));
+	isb();
+
+	/*
+	 * Need to check that the SRE bit has actually been set. If
+	 * not, it means that SRE is disabled at EL2. We're going to
+	 * die painfully, and there is nothing we can do about it.
+	 *
+	 * Kindly inform the luser.
+	 */
+	asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
+	if (!(val & ICC_SRE_EL1_SRE))
+		pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
+}
+
+static void gic_enable_redist(void)
+{
+	void __iomem *rbase;
+	u32 count = 1000000;	/* 1s! */
+	u32 val;
+
+	rbase = gic_data_rdist_rd_base();
+
+	/* Wake up this CPU redistributor */
+	val = readl_relaxed(rbase + GICR_WAKER);
+	val &= ~GICR_WAKER_ProcessorSleep;
+	writel_relaxed(val, rbase + GICR_WAKER);
+
+	while (readl_relaxed(rbase + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) {
+		count--;
+		if (!count) {
+			pr_err_ratelimited("redist didn't wake up...\n");
+			return;
+		}
+		cpu_relax();
+		udelay(1);
+	};
+}
+
+/*
+ * Routines to disable, enable, EOI and route interrupts
+ */
+static void gic_poke_irq(struct irq_data *d, u32 offset)
+{
+	u32 mask = 1 << (gic_irq(d) % 32);
+	void (*rwp_wait)(void);
+	void __iomem *base;
+
+	if (gic_irq_in_rdist(d)) {
+		base = gic_data_rdist_sgi_base();
+		rwp_wait = gic_redist_wait_for_rwp;
+	} else {
+		base = gic_data.dist_base;
+		rwp_wait = gic_dist_wait_for_rwp;
+	}
+
+	writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
+	rwp_wait();
+}
+
+static void gic_mask_irq(struct irq_data *d)
+{
+	gic_poke_irq(d, GICD_ICENABLER);
+}
+
+static void gic_unmask_irq(struct irq_data *d)
+{
+	gic_poke_irq(d, GICD_ISENABLER);
+}
+
+static void gic_eoi_irq(struct irq_data *d)
+{
+	gic_write_eoir(gic_irq(d));
+}
+
+static int gic_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int irq = gic_irq(d);
+	void (*rwp_wait)(void);
+	void __iomem *base;
+
+	/* Interrupt configuration for SGIs can't be changed */
+	if (irq < 16)
+		return -EINVAL;
+
+	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
+		return -EINVAL;
+
+	if (gic_irq_in_rdist(d)) {
+		base = gic_data_rdist_sgi_base();
+		rwp_wait = gic_redist_wait_for_rwp;
+	} else {
+		base = gic_data.dist_base;
+		rwp_wait = gic_dist_wait_for_rwp;
+	}
+
+	gic_configure_irq(irq, type, base, rwp_wait);
+
+	return 0;
+}
+
+static u64 gic_mpidr_to_affinity(u64 mpidr)
+{
+	u64 aff;
+
+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+	return aff;
+}
+
+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+	u64 irqnr;
+
+	do {
+		irqnr = gic_read_iar();
+
+		if (likely(irqnr > 15 && irqnr < 1020)) {
+			u64 irq = irq_find_mapping(gic_data.domain, irqnr);
+			if (likely(irq)) {
+				handle_IRQ(irq, regs);
+				continue;
+			}
+
+			WARN_ONCE(true, "Unexpected SPI received!\n");
+			gic_write_eoir(irqnr);
+		}
+		if (irqnr < 16) {
+			gic_write_eoir(irqnr);
+#ifdef CONFIG_SMP
+			handle_IPI(irqnr, regs);
+#else
+			WARN_ONCE(true, "Unexpected SGI received!\n");
+#endif
+			continue;
+		}
+	} while (irqnr != ICC_IAR1_EL1_SPURIOUS);
+}
+
+static void __init gic_dist_init(void)
+{
+	unsigned int i;
+	u64 affinity;
+	void __iomem *base = gic_data.dist_base;
+
+	/* Disable the distributor */
+	writel_relaxed(0, base + GICD_CTLR);
+	gic_dist_wait_for_rwp();
+
+	gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
+
+	/* Enable distributor with ARE, Group1 */
+	writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
+		       base + GICD_CTLR);
+
+	/*
+	 * Set all global interrupts to the boot CPU only. ARE must be
+	 * enabled.
+	 */
+	affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
+	for (i = 32; i < gic_data.irq_nr; i++)
+		writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
+}
+
+static int gic_populate_rdist(void)
+{
+	u64 mpidr = cpu_logical_map(smp_processor_id());
+	u64 typer;
+	u32 aff;
+	int i;
+
+	/*
+	 * Convert affinity to a 32bit value that can be matched to
+	 * GICR_TYPER bits [63:32].
+	 */
+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+	for (i = 0; i < gic_data.redist_regions; i++) {
+		void __iomem *ptr = gic_data.redist_base[i];
+		u32 reg;
+
+		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
+		if (reg != GIC_PIDR2_ARCH_GICv3 &&
+		    reg != GIC_PIDR2_ARCH_GICv4) { /* We're in trouble... */
+			pr_warn("No redistributor present @%p\n", ptr);
+			break;
+		}
+
+		do {
+			typer = readq_relaxed(ptr + GICR_TYPER);
+			if ((typer >> 32) == aff) {
+				gic_data_rdist_rd_base() = ptr;
+				pr_info("CPU%d: found redistributor %llx @%p\n",
+					smp_processor_id(),
+					(unsigned long long)mpidr, ptr);
+				return 0;
+			}
+
+			if (gic_data.redist_stride) {
+				ptr += gic_data.redist_stride;
+			} else {
+				ptr += SZ_64K * 2; /* Skip RD_base + SGI_base */
+				if (typer & GICR_TYPER_VLPIS)
+					ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
+			}
+		} while (!(typer & GICR_TYPER_LAST));
+	}
+
+	/* We couldn't even deal with ourselves... */
+	WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
+	     smp_processor_id(), (unsigned long long)mpidr);
+	return -ENODEV;
+}
+
+static void gic_cpu_init(void)
+{
+	void __iomem *rbase;
+
+	/* Register ourselves with the rest of the world */
+	if (gic_populate_rdist())
+		return;
+
+	gic_enable_redist();
+
+	rbase = gic_data_rdist_sgi_base();
+
+	gic_cpu_config(rbase, gic_redist_wait_for_rwp);
+
+	/* Enable system registers */
+	gic_enable_sre();
+
+	/* Set priority mask register */
+	gic_write_pmr(DEFAULT_PMR_VALUE);
+
+	/* EOI deactivates interrupt too (mode 0) */
+	gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
+
+	/* ... and let's hit the road... */
+	gic_write_grpen1(1);
+}
+
+#ifdef CONFIG_SMP
+static int gic_peek_irq(struct irq_data *d, u32 offset)
+{
+	u32 mask = 1 << (gic_irq(d) % 32);
+	void __iomem *base;
+
+	if (gic_irq_in_rdist(d))
+		base = gic_data_rdist_sgi_base();
+	else
+		base = gic_data.dist_base;
+
+	return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+}
+
+static int gic_secondary_init(struct notifier_block *nfb,
+			      unsigned long action, void *hcpu)
+{
+	if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+		gic_cpu_init();
+	return NOTIFY_OK;
+}
+
+/*
+ * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
+ * priority because the GIC needs to be up before the ARM generic timers.
+ */
+static struct notifier_block gic_cpu_notifier = {
+	.notifier_call = gic_secondary_init,
+	.priority = 100,
+};
+
+static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
+				   u64 cluster_id)
+{
+	int cpu = *base_cpu;
+	u64 mpidr = cpu_logical_map(cpu);
+	u16 tlist = 0;
+
+	while (cpu < nr_cpu_ids) {
+		/*
+		 * If we ever get a cluster of more than 16 CPUs, just
+		 * scream and skip that CPU.
+		 */
+		if (WARN_ON((mpidr & 0xff) >= 16))
+			goto out;
+
+		tlist |= 1 << (mpidr & 0xf);
+
+		cpu = cpumask_next(cpu, mask);
+		if (cpu == nr_cpu_ids)
+			goto out;
+
+		mpidr = cpu_logical_map(cpu);
+
+		if (cluster_id != (mpidr & ~0xffUL)) {
+			cpu--;
+			goto out;
+		}
+	}
+out:
+	*base_cpu = cpu;
+	return tlist;
+}
+
+static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
+{
+	u64 val;
+
+	val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48	|
+	       MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32	|
+	       irq << 24			    		|
+	       MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16	|
+	       tlist);
+
+	pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
+	gic_write_sgi1r(val);
+}
+
+static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+{
+	int cpu;
+
+	if (WARN_ON(irq >= 16))
+		return;
+
+	/*
+	 * Ensure that stores to Normal memory are visible to the
+	 * other CPUs before issuing the IPI.
+	 */
+	smp_wmb();
+
+	for_each_cpu_mask(cpu, *mask) {
+		u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
+		u16 tlist;
+
+		tlist = gic_compute_target_list(&cpu, mask, cluster_id);
+		gic_send_sgi(cluster_id, tlist, irq);
+	}
+
+	/* Force the above writes to ICC_SGI1R_EL1 to be executed */
+	isb();
+}
+
+static void gic_smp_init(void)
+{
+	set_smp_cross_call(gic_raise_softirq);
+	register_cpu_notifier(&gic_cpu_notifier);
+}
+
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+			    bool force)
+{
+	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	void __iomem *reg;
+	int enabled;
+	u64 val;
+
+	if (gic_irq_in_rdist(d))
+		return -EINVAL;
+
+	/* If interrupt was enabled, disable it first */
+	enabled = gic_peek_irq(d, GICD_ISENABLER);
+	if (enabled)
+		gic_mask_irq(d);
+
+	reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
+	val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
+
+	writeq_relaxed(val, reg);
+
+	/*
+	 * If the interrupt was enabled, enabled it again. Otherwise,
+	 * just wait for the distributor to have digested our changes.
+	 */
+	if (enabled)
+		gic_unmask_irq(d);
+	else
+		gic_dist_wait_for_rwp();
+
+	return IRQ_SET_MASK_OK;
+}
+#else
+#define gic_set_affinity	NULL
+#define gic_smp_init()		do { } while(0)
+#endif
+
+static struct irq_chip gic_chip = {
+	.name			= "GICv3",
+	.irq_mask		= gic_mask_irq,
+	.irq_unmask		= gic_unmask_irq,
+	.irq_eoi		= gic_eoi_irq,
+	.irq_set_type		= gic_set_type,
+	.irq_set_affinity	= gic_set_affinity,
+};
+
+static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+			      irq_hw_number_t hw)
+{
+	/* SGIs are private to the core kernel */
+	if (hw < 16)
+		return -EPERM;
+	/* PPIs */
+	if (hw < 32) {
+		irq_set_percpu_devid(irq);
+		irq_set_chip_and_handler(irq, &gic_chip,
+					 handle_percpu_devid_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+	}
+	/* SPIs */
+	if (hw >= 32 && hw < gic_data.irq_nr) {
+		irq_set_chip_and_handler(irq, &gic_chip,
+					 handle_fasteoi_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+	irq_set_chip_data(irq, d->host_data);
+	return 0;
+}
+
+static int gic_irq_domain_xlate(struct irq_domain *d,
+				struct device_node *controller,
+				const u32 *intspec, unsigned int intsize,
+				unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	switch(intspec[0]) {
+	case 0:			/* SPI */
+		*out_hwirq = intspec[1] + 32;
+		break;
+	case 1:			/* PPI */
+		*out_hwirq = intspec[1] + 16;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+static const struct irq_domain_ops gic_irq_domain_ops = {
+	.map = gic_irq_domain_map,
+	.xlate = gic_irq_domain_xlate,
+};
+
+static int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *dist_base;
+	void __iomem **redist_base;
+	u64 redist_stride;
+	u32 redist_regions;
+	u32 reg;
+	int gic_irqs;
+	int err;
+	int i;
+
+	dist_base = of_iomap(node, 0);
+	if (!dist_base) {
+		pr_err("%s: unable to map gic dist registers\n",
+			node->full_name);
+		return -ENXIO;
+	}
+
+	reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+		pr_err("%s: no distributor detected, giving up\n",
+			node->full_name);
+		err = -ENODEV;
+		goto out_unmap_dist;
+	}
+
+	if (of_property_read_u32(node, "#redistributor-regions", &redist_regions))
+		redist_regions = 1;
+
+	redist_base = kzalloc(sizeof(*redist_base) * redist_regions, GFP_KERNEL);
+	if (!redist_base) {
+		err = -ENOMEM;
+		goto out_unmap_dist;
+	}
+
+	for (i = 0; i < redist_regions; i++) {
+		redist_base[i] = of_iomap(node, 1 + i);
+		if (!redist_base[i]) {
+			pr_err("%s: couldn't map region %d\n",
+			       node->full_name, i);
+			err = -ENODEV;
+			goto out_unmap_rdist;
+		}
+	}
+
+	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
+		redist_stride = 0;
+
+	gic_data.dist_base = dist_base;
+	gic_data.redist_base = redist_base;
+	gic_data.redist_regions = redist_regions;
+	gic_data.redist_stride = redist_stride;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+	 */
+	gic_irqs = readl_relaxed(gic_data.dist_base + GICD_TYPER) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic_data.irq_nr = gic_irqs;
+
+	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
+					      &gic_data);
+	gic_data.rdist = alloc_percpu(typeof(*gic_data.rdist));
+
+	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdist)) {
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	set_handle_irq(gic_handle_irq);
+
+	gic_smp_init();
+	gic_dist_init();
+	gic_cpu_init();
+
+	return 0;
+
+out_free:
+	if (gic_data.domain)
+		irq_domain_remove(gic_data.domain);
+	free_percpu(gic_data.rdist);
+out_unmap_rdist:
+	for (i = 0; i < redist_regions; i++)
+		if (redist_base[i])
+			iounmap(redist_base[i]);
+	kfree(redist_base);
+out_unmap_dist:
+	iounmap(dist_base);
+	return err;
+}
+
+IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-nvic.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-nvic.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-nvic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-nvic.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,14 +49,6 @@ nvic_handle_irq(irq_hw_number_t hwirq, s
 	handle_IRQ(irq, regs);
 }
 
-static void nvic_eoi(struct irq_data *d)
-{
-	/*
-	 * This is a no-op as end of interrupt is signaled by the exception
-	 * return sequence.
-	 */
-}
-
 static int __init nvic_of_init(struct device_node *node,
 			       struct device_node *parent)
 {
@@ -102,7 +94,10 @@ static int __init nvic_of_init(struct de
 		gc->chip_types[0].regs.disable = NVIC_ICER;
 		gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
 		gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
-		gc->chip_types[0].chip.irq_eoi = nvic_eoi;
+		/* This is a no-op as end of interrupt is signaled by the
+		 * exception return sequence.
+		 */
+		gc->chip_types[0].chip.irq_eoi = irq_gc_noop;
 
 		/* disable interrupts */
 		writel_relaxed(~0, gc->reg_base + NVIC_ICER);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-or1k-pic.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-or1k-pic.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-or1k-pic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-or1k-pic.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include "irqchip.h"
+
+/* OR1K PIC implementation */
+
+struct or1k_pic_dev {
+	struct irq_chip chip;
+	irq_flow_handler_t handle;
+	unsigned long flags;
+};
+
+/*
+ * We're a couple of cycles faster than the generic implementations with
+ * these 'fast' versions.
+ */
+
+static void or1k_pic_mask(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+}
+
+static void or1k_pic_unmask(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
+}
+
+static void or1k_pic_ack(struct irq_data *data)
+{
+	mtspr(SPR_PICSR, (1UL << data->hwirq));
+}
+
+static void or1k_pic_mask_ack(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+	mtspr(SPR_PICSR, (1UL << data->hwirq));
+}
+
+/*
+ * There are two oddities with the OR1200 PIC implementation:
+ * i)  LEVEL-triggered interrupts are latched and need to be cleared
+ * ii) the interrupt latch is cleared by writing a 0 to the bit,
+ *     as opposed to a 1 as mandated by the spec
+ */
+static void or1k_pic_or1200_ack(struct irq_data *data)
+{
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
+}
+
+static void or1k_pic_or1200_mask_ack(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
+}
+
+static struct or1k_pic_dev or1k_pic_level = {
+	.chip = {
+		.name = "or1k-PIC-level",
+		.irq_unmask = or1k_pic_unmask,
+		.irq_mask = or1k_pic_mask,
+		.irq_mask_ack = or1k_pic_mask,
+	},
+	.handle = handle_level_irq,
+	.flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct or1k_pic_dev or1k_pic_edge = {
+	.chip = {
+		.name = "or1k-PIC-edge",
+		.irq_unmask = or1k_pic_unmask,
+		.irq_mask = or1k_pic_mask,
+		.irq_ack = or1k_pic_ack,
+		.irq_mask_ack = or1k_pic_mask_ack,
+	},
+	.handle = handle_edge_irq,
+	.flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct or1k_pic_dev or1k_pic_or1200 = {
+	.chip = {
+		.name = "or1200-PIC",
+		.irq_unmask = or1k_pic_unmask,
+		.irq_mask = or1k_pic_mask,
+		.irq_ack = or1k_pic_or1200_ack,
+		.irq_mask_ack = or1k_pic_or1200_mask_ack,
+	},
+	.handle = handle_level_irq,
+	.flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct irq_domain *root_domain;
+
+static inline int pic_get_irq(int first)
+{
+	int hwirq;
+
+	hwirq = ffs(mfspr(SPR_PICSR) >> first);
+	if (!hwirq)
+		return NO_IRQ;
+	else
+		hwirq = hwirq + first - 1;
+
+	return irq_find_mapping(root_domain, hwirq);
+}
+
+static void or1k_pic_handle_irq(struct pt_regs *regs)
+{
+	int irq = -1;
+
+	while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
+		handle_IRQ(irq, regs);
+}
+
+static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+	struct or1k_pic_dev *pic = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
+	irq_set_status_flags(irq, pic->flags);
+
+	return 0;
+}
+
+static const struct irq_domain_ops or1k_irq_domain_ops = {
+	.xlate = irq_domain_xlate_onecell,
+	.map = or1k_map,
+};
+
+/*
+ * This sets up the IRQ domain for the PIC built in to the OpenRISC
+ * 1000 CPU.  This is the "root" domain as these are the interrupts
+ * that directly trigger an exception in the CPU.
+ */
+static int __init or1k_pic_init(struct device_node *node,
+				 struct or1k_pic_dev *pic)
+{
+	/* Disable all interrupts until explicitly requested */
+	mtspr(SPR_PICMR, (0UL));
+
+	root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
+					    pic);
+
+	set_handle_irq(or1k_pic_handle_irq);
+
+	return 0;
+}
+
+static int __init or1k_pic_or1200_init(struct device_node *node,
+				       struct device_node *parent)
+{
+	return or1k_pic_init(node, &or1k_pic_or1200);
+}
+IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic", or1k_pic_or1200_init);
+IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic", or1k_pic_or1200_init);
+
+static int __init or1k_pic_level_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	return or1k_pic_init(node, &or1k_pic_level);
+}
+IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level",
+		or1k_pic_level_init);
+
+static int __init or1k_pic_edge_init(struct device_node *node,
+				     struct device_node *parent)
+{
+	return or1k_pic_init(node, &or1k_pic_edge);
+}
+IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge", or1k_pic_edge_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/irq-versatile-fpga.c linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-versatile-fpga.c
--- linux-libre-3.16-gnu/drivers/irqchip/irq-versatile-fpga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/irq-versatile-fpga.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,8 @@
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
+#include "irqchip.h"
+
 #define IRQ_STATUS		0x00
 #define IRQ_RAW_STATUS		0x04
 #define IRQ_ENABLE_SET		0x08
@@ -26,6 +28,8 @@
 #define FIQ_ENABLE_SET		0x28
 #define FIQ_ENABLE_CLEAR	0x2C
 
+#define PIC_ENABLES             0x20	/* set interrupt pass through bits */
+
 /**
  * struct fpga_irq_data - irq data container for the FPGA IRQ controller
  * @base: memory offset in virtual memory
@@ -201,14 +205,26 @@ int __init fpga_irq_of_init(struct devic
 
 	/* Some chips are cascaded from a parent IRQ */
 	parent_irq = irq_of_parse_and_map(node, 0);
-	if (!parent_irq)
+	if (!parent_irq) {
+		set_handle_irq(fpga_handle_irq);
 		parent_irq = -1;
+	}
 
 	fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
 
 	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
 	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
 
+	/*
+	 * On Versatile AB/PB, some secondary interrupts have a direct
+	 * pass-thru to the primary controller for IRQs 20 and 22-31 which need
+	 * to be enabled. See section 3.10 of the Versatile AB user guide.
+	 */
+	if (of_device_is_compatible(node, "arm,versatile-sic"))
+		writel(0xffd00000, base + PIC_ENABLES);
+
 	return 0;
 }
+IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
+IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/Kconfig linux-libre-3.17-rc7-gnu/drivers/irqchip/Kconfig
--- linux-libre-3.16-gnu/drivers/irqchip/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,11 @@ config ARM_GIC
 config GIC_NON_BANKED
 	bool
 
+config ARM_GIC_V3
+	bool
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+
 config ARM_NVIC
 	bool
 	select IRQ_DOMAIN
@@ -23,13 +28,26 @@ config ARM_VIC
 config ARM_VIC_NR
 	int
 	default 4 if ARCH_S5PV210
-	default 3 if ARCH_S5PC100
 	default 2
 	depends on ARM_VIC
 	help
 	  The maximum number of VICs available in the system, for
 	  power management.
 
+config ATMEL_AIC_IRQ
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+
+config ATMEL_AIC5_IRQ
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+
 config BRCMSTB_L2_IRQ
 	bool
 	depends on ARM
@@ -53,6 +71,10 @@ config CLPS711X_IRQCHIP
 	select SPARSE_IRQ
 	default y
 
+config OR1K_PIC
+	bool
+	select IRQ_DOMAIN
+
 config ORION_IRQCHIP
 	bool
 	select IRQ_DOMAIN
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/Makefile linux-libre-3.17-rc7-gnu/drivers/irqchip/Makefile
--- linux-libre-3.16-gnu/drivers/irqchip/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -11,13 +11,17 @@ obj-$(CONFIG_METAG)			+= irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
 obj-$(CONFIG_ARCH_MOXART)		+= irq-moxart.o
 obj-$(CONFIG_CLPS711X_IRQCHIP)		+= irq-clps711x.o
+obj-$(CONFIG_OR1K_PIC)			+= irq-or1k-pic.o
 obj-$(CONFIG_ORION_IRQCHIP)		+= irq-orion.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi-nmi.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
-obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
+obj-$(CONFIG_ARM_GIC)			+= irq-gic.o irq-gic-common.o
+obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-common.o
 obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
 obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
+obj-$(CONFIG_ATMEL_AIC_IRQ)		+= irq-atmel-aic-common.o irq-atmel-aic.o
+obj-$(CONFIG_ATMEL_AIC5_IRQ)	+= irq-atmel-aic-common.o irq-atmel-aic5.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/irqchip/spear-shirq.c linux-libre-3.17-rc7-gnu/drivers/irqchip/spear-shirq.c
--- linux-libre-3.16-gnu/drivers/irqchip/spear-shirq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/irqchip/spear-shirq.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
-#include <linux/irqchip/spear-shirq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -27,20 +26,73 @@
 
 #include "irqchip.h"
 
-static DEFINE_SPINLOCK(lock);
+/*
+ * struct spear_shirq: shared irq structure
+ *
+ * base:	Base register address
+ * status_reg:	Status register offset for chained interrupt handler
+ * mask_reg:	Mask register offset for irq chip
+ * mask:	Mask to apply to the status register
+ * virq_base:	Base virtual interrupt number
+ * nr_irqs:	Number of interrupts handled by this block
+ * offset:	Bit offset of the first interrupt
+ * irq_chip:	Interrupt controller chip used for this instance,
+ *		if NULL group is disabled, but accounted
+ */
+struct spear_shirq {
+	void __iomem		*base;
+	u32			status_reg;
+	u32			mask_reg;
+	u32			mask;
+	u32			virq_base;
+	u32			nr_irqs;
+	u32			offset;
+	struct irq_chip		*irq_chip;
+};
 
 /* spear300 shared irq registers offsets and masks */
 #define SPEAR300_INT_ENB_MASK_REG	0x54
 #define SPEAR300_INT_STS_MASK_REG	0x58
 
+static DEFINE_RAW_SPINLOCK(shirq_lock);
+
+static void shirq_irq_mask(struct irq_data *d)
+{
+	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+	u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
+	u32 __iomem *reg = shirq->base + shirq->mask_reg;
+
+	raw_spin_lock(&shirq_lock);
+	val = readl(reg) & ~(0x1 << shift);
+	writel(val, reg);
+	raw_spin_unlock(&shirq_lock);
+}
+
+static void shirq_irq_unmask(struct irq_data *d)
+{
+	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+	u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
+	u32 __iomem *reg = shirq->base + shirq->mask_reg;
+
+	raw_spin_lock(&shirq_lock);
+	val = readl(reg) | (0x1 << shift);
+	writel(val, reg);
+	raw_spin_unlock(&shirq_lock);
+}
+
+static struct irq_chip shirq_chip = {
+	.name		= "spear-shirq",
+	.irq_mask	= shirq_irq_mask,
+	.irq_unmask	= shirq_irq_unmask,
+};
+
 static struct spear_shirq spear300_shirq_ras1 = {
-	.irq_nr = 9,
-	.irq_bit_off = 0,
-	.regs = {
-		.enb_reg = SPEAR300_INT_ENB_MASK_REG,
-		.status_reg = SPEAR300_INT_STS_MASK_REG,
-		.clear_reg = -1,
-	},
+	.offset		= 0,
+	.nr_irqs	= 9,
+	.mask		= ((0x1 << 9) - 1) << 0,
+	.irq_chip	= &shirq_chip,
+	.status_reg	= SPEAR300_INT_STS_MASK_REG,
+	.mask_reg	= SPEAR300_INT_ENB_MASK_REG,
 };
 
 static struct spear_shirq *spear300_shirq_blocks[] = {
@@ -51,43 +103,35 @@ static struct spear_shirq *spear300_shir
 #define SPEAR310_INT_STS_MASK_REG	0x04
 
 static struct spear_shirq spear310_shirq_ras1 = {
-	.irq_nr = 8,
-	.irq_bit_off = 0,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.clear_reg = -1,
-	},
+	.offset		= 0,
+	.nr_irqs	= 8,
+	.mask		= ((0x1 << 8) - 1) << 0,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR310_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq spear310_shirq_ras2 = {
-	.irq_nr = 5,
-	.irq_bit_off = 8,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.clear_reg = -1,
-	},
+	.offset		= 8,
+	.nr_irqs	= 5,
+	.mask		= ((0x1 << 5) - 1) << 8,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR310_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq spear310_shirq_ras3 = {
-	.irq_nr = 1,
-	.irq_bit_off = 13,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.clear_reg = -1,
-	},
+	.offset		= 13,
+	.nr_irqs	= 1,
+	.mask		= ((0x1 << 1) - 1) << 13,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR310_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq spear310_shirq_intrcomm_ras = {
-	.irq_nr = 3,
-	.irq_bit_off = 14,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.clear_reg = -1,
-	},
+	.offset		= 14,
+	.nr_irqs	= 3,
+	.mask		= ((0x1 << 3) - 1) << 14,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR310_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq *spear310_shirq_blocks[] = {
@@ -102,50 +146,34 @@ static struct spear_shirq *spear310_shir
 #define SPEAR320_INT_CLR_MASK_REG		0x04
 #define SPEAR320_INT_ENB_MASK_REG		0x08
 
-static struct spear_shirq spear320_shirq_ras1 = {
-	.irq_nr = 3,
-	.irq_bit_off = 7,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
+static struct spear_shirq spear320_shirq_ras3 = {
+	.offset		= 0,
+	.nr_irqs	= 7,
+	.mask		= ((0x1 << 7) - 1) << 0,
 };
 
-static struct spear_shirq spear320_shirq_ras2 = {
-	.irq_nr = 1,
-	.irq_bit_off = 10,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
+static struct spear_shirq spear320_shirq_ras1 = {
+	.offset		= 7,
+	.nr_irqs	= 3,
+	.mask		= ((0x1 << 3) - 1) << 7,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR320_INT_STS_MASK_REG,
 };
 
-static struct spear_shirq spear320_shirq_ras3 = {
-	.irq_nr = 7,
-	.irq_bit_off = 0,
-	.invalid_irq = 1,
-	.regs = {
-		.enb_reg = SPEAR320_INT_ENB_MASK_REG,
-		.reset_to_enb = 1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
+static struct spear_shirq spear320_shirq_ras2 = {
+	.offset		= 10,
+	.nr_irqs	= 1,
+	.mask		= ((0x1 << 1) - 1) << 10,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR320_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq spear320_shirq_intrcomm_ras = {
-	.irq_nr = 11,
-	.irq_bit_off = 11,
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
+	.offset		= 11,
+	.nr_irqs	= 11,
+	.mask		= ((0x1 << 11) - 1) << 11,
+	.irq_chip	= &dummy_irq_chip,
+	.status_reg	= SPEAR320_INT_STS_MASK_REG,
 };
 
 static struct spear_shirq *spear320_shirq_blocks[] = {
@@ -155,104 +183,46 @@ static struct spear_shirq *spear320_shir
 	&spear320_shirq_intrcomm_ras,
 };
 
-static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
-{
-	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
-	u32 val, offset = d->irq - shirq->irq_base;
-	unsigned long flags;
-
-	if (shirq->regs.enb_reg == -1)
-		return;
-
-	spin_lock_irqsave(&lock, flags);
-	val = readl(shirq->base + shirq->regs.enb_reg);
-
-	if (mask ^ shirq->regs.reset_to_enb)
-		val &= ~(0x1 << shirq->irq_bit_off << offset);
-	else
-		val |= 0x1 << shirq->irq_bit_off << offset;
-
-	writel(val, shirq->base + shirq->regs.enb_reg);
-	spin_unlock_irqrestore(&lock, flags);
-
-}
-
-static void shirq_irq_mask(struct irq_data *d)
-{
-	shirq_irq_mask_unmask(d, 1);
-}
-
-static void shirq_irq_unmask(struct irq_data *d)
-{
-	shirq_irq_mask_unmask(d, 0);
-}
-
-static struct irq_chip shirq_chip = {
-	.name		= "spear-shirq",
-	.irq_ack	= shirq_irq_mask,
-	.irq_mask	= shirq_irq_mask,
-	.irq_unmask	= shirq_irq_unmask,
-};
-
 static void shirq_handler(unsigned irq, struct irq_desc *desc)
 {
-	u32 i, j, val, mask, tmp;
-	struct irq_chip *chip;
 	struct spear_shirq *shirq = irq_get_handler_data(irq);
+	u32 pend;
 
-	chip = irq_get_chip(irq);
-	chip->irq_ack(&desc->irq_data);
-
-	mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
-	while ((val = readl(shirq->base + shirq->regs.status_reg) &
-				mask)) {
-
-		val >>= shirq->irq_bit_off;
-		for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
-
-			if (!(j & val))
-				continue;
-
-			generic_handle_irq(shirq->irq_base + i);
+	pend = readl(shirq->base + shirq->status_reg) & shirq->mask;
+	pend >>= shirq->offset;
 
-			/* clear interrupt */
-			if (shirq->regs.clear_reg == -1)
-				continue;
+	while (pend) {
+		int irq = __ffs(pend);
 
-			tmp = readl(shirq->base + shirq->regs.clear_reg);
-			if (shirq->regs.reset_to_clear)
-				tmp &= ~(j << shirq->irq_bit_off);
-			else
-				tmp |= (j << shirq->irq_bit_off);
-			writel(tmp, shirq->base + shirq->regs.clear_reg);
-		}
+		pend &= ~(0x1 << irq);
+		generic_handle_irq(shirq->virq_base + irq);
 	}
-	chip->irq_unmask(&desc->irq_data);
 }
 
-static void __init spear_shirq_register(struct spear_shirq *shirq)
+static void __init spear_shirq_register(struct spear_shirq *shirq,
+					int parent_irq)
 {
 	int i;
 
-	if (shirq->invalid_irq)
+	if (!shirq->irq_chip)
 		return;
 
-	irq_set_chained_handler(shirq->irq, shirq_handler);
-	for (i = 0; i < shirq->irq_nr; i++) {
-		irq_set_chip_and_handler(shirq->irq_base + i,
-					 &shirq_chip, handle_simple_irq);
-		set_irq_flags(shirq->irq_base + i, IRQF_VALID);
-		irq_set_chip_data(shirq->irq_base + i, shirq);
-	}
+	irq_set_chained_handler(parent_irq, shirq_handler);
+	irq_set_handler_data(parent_irq, shirq);
 
-	irq_set_handler_data(shirq->irq, shirq);
+	for (i = 0; i < shirq->nr_irqs; i++) {
+		irq_set_chip_and_handler(shirq->virq_base + i,
+					 shirq->irq_chip, handle_simple_irq);
+		set_irq_flags(shirq->virq_base + i, IRQF_VALID);
+		irq_set_chip_data(shirq->virq_base + i, shirq);
+	}
 }
 
 static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
 		struct device_node *np)
 {
-	int i, irq_base, hwirq = 0, irq_nr = 0;
-	static struct irq_domain *shirq_domain;
+	int i, parent_irq, virq_base, hwirq = 0, nr_irqs = 0;
+	struct irq_domain *shirq_domain;
 	void __iomem *base;
 
 	base = of_iomap(np, 0);
@@ -262,15 +232,15 @@ static int __init shirq_init(struct spea
 	}
 
 	for (i = 0; i < block_nr; i++)
-		irq_nr += shirq_blocks[i]->irq_nr;
+		nr_irqs += shirq_blocks[i]->nr_irqs;
 
-	irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
-	if (IS_ERR_VALUE(irq_base)) {
+	virq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+	if (IS_ERR_VALUE(virq_base)) {
 		pr_err("%s: irq desc alloc failed\n", __func__);
 		goto err_unmap;
 	}
 
-	shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
+	shirq_domain = irq_domain_add_legacy(np, nr_irqs, virq_base, 0,
 			&irq_domain_simple_ops, NULL);
 	if (WARN_ON(!shirq_domain)) {
 		pr_warn("%s: irq domain init failed\n", __func__);
@@ -279,41 +249,41 @@ static int __init shirq_init(struct spea
 
 	for (i = 0; i < block_nr; i++) {
 		shirq_blocks[i]->base = base;
-		shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
+		shirq_blocks[i]->virq_base = irq_find_mapping(shirq_domain,
 				hwirq);
-		shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
 
-		spear_shirq_register(shirq_blocks[i]);
-		hwirq += shirq_blocks[i]->irq_nr;
+		parent_irq = irq_of_parse_and_map(np, i);
+		spear_shirq_register(shirq_blocks[i], parent_irq);
+		hwirq += shirq_blocks[i]->nr_irqs;
 	}
 
 	return 0;
 
 err_free_desc:
-	irq_free_descs(irq_base, irq_nr);
+	irq_free_descs(virq_base, nr_irqs);
 err_unmap:
 	iounmap(base);
 	return -ENXIO;
 }
 
-int __init spear300_shirq_of_init(struct device_node *np,
-		struct device_node *parent)
+static int __init spear300_shirq_of_init(struct device_node *np,
+					 struct device_node *parent)
 {
 	return shirq_init(spear300_shirq_blocks,
 			ARRAY_SIZE(spear300_shirq_blocks), np);
 }
 IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init);
 
-int __init spear310_shirq_of_init(struct device_node *np,
-		struct device_node *parent)
+static int __init spear310_shirq_of_init(struct device_node *np,
+					 struct device_node *parent)
 {
 	return shirq_init(spear310_shirq_blocks,
 			ARRAY_SIZE(spear310_shirq_blocks), np);
 }
 IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init);
 
-int __init spear320_shirq_of_init(struct device_node *np,
-		struct device_node *parent)
+static int __init spear320_shirq_of_init(struct device_node *np,
+					 struct device_node *parent)
 {
 	return shirq_init(spear320_shirq_blocks,
 			ARRAY_SIZE(spear320_shirq_blocks), np);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/isdn/capi/capi.c linux-libre-3.17-rc7-gnu/drivers/isdn/capi/capi.c
--- linux-libre-3.16-gnu/drivers/isdn/capi/capi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/isdn/capi/capi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1260,7 +1260,7 @@ static int __init capinc_tty_init(void)
 	if (capi_ttyminors <= 0)
 		capi_ttyminors = CAPINC_NR_PORTS;
 
-	capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors,
+	capiminors = kzalloc(sizeof(struct capiminor *) * capi_ttyminors,
 			     GFP_KERNEL);
 	if (!capiminors)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/isdn/hardware/eicon/xdi_msg.h linux-libre-3.17-rc7-gnu/drivers/isdn/hardware/eicon/xdi_msg.h
--- linux-libre-3.16-gnu/drivers/isdn/hardware/eicon/xdi_msg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/isdn/hardware/eicon/xdi_msg.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 /* $Id: xdi_msg.h,v 1.1.2.2 2001/02/16 08:40:36 armin Exp $ */
 
-#ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__
+#ifndef __DIVA_XDI_UM_CFG_MESSAGE_H__
 #define __DIVA_XDI_UM_CFG_MESSAGE_H__
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/isdn/i4l/isdn_net.c linux-libre-3.17-rc7-gnu/drivers/isdn/i4l/isdn_net.c
--- linux-libre-3.16-gnu/drivers/isdn/i4l/isdn_net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/isdn/i4l/isdn_net.c	2014-09-28 17:29:07.000000000 -0400
@@ -2588,7 +2588,8 @@ isdn_net_new(char *name, struct net_devi
 		printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
 		return NULL;
 	}
-	netdev->dev = alloc_netdev(sizeof(isdn_net_local), name, _isdn_setup);
+	netdev->dev = alloc_netdev(sizeof(isdn_net_local), name,
+				   NET_NAME_UNKNOWN, _isdn_setup);
 	if (!netdev->dev) {
 		printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
 		kfree(netdev);
@@ -2917,8 +2918,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
 			cfg->callback = 2;
 		cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
 		cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
-		cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
-		cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
+		cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
+		cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
 		cfg->cbdelay = lp->cbdelay;
 		cfg->dialmax = lp->dialmax;
 		cfg->triggercps = lp->triggercps;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/isdn/i4l/isdn_ppp.c linux-libre-3.17-rc7-gnu/drivers/isdn/i4l/isdn_ppp.c
--- linux-libre-3.16-gnu/drivers/isdn/i4l/isdn_ppp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/isdn/i4l/isdn_ppp.c	2014-09-28 17:29:07.000000000 -0400
@@ -379,12 +379,12 @@ isdn_ppp_release(int min, struct file *f
 #endif
 #ifdef CONFIG_IPPP_FILTER
 	if (is->pass_filter) {
-		sk_unattached_filter_destroy(is->pass_filter);
+		bpf_prog_destroy(is->pass_filter);
 		is->pass_filter = NULL;
 	}
 
 	if (is->active_filter) {
-		sk_unattached_filter_destroy(is->active_filter);
+		bpf_prog_destroy(is->active_filter);
 		is->active_filter = NULL;
 	}
 #endif
@@ -639,12 +639,11 @@ isdn_ppp_ioctl(int min, struct file *fil
 		fprog.filter = code;
 
 		if (is->pass_filter) {
-			sk_unattached_filter_destroy(is->pass_filter);
+			bpf_prog_destroy(is->pass_filter);
 			is->pass_filter = NULL;
 		}
 		if (fprog.filter != NULL)
-			err = sk_unattached_filter_create(&is->pass_filter,
-							  &fprog);
+			err = bpf_prog_create(&is->pass_filter, &fprog);
 		else
 			err = 0;
 		kfree(code);
@@ -664,12 +663,11 @@ isdn_ppp_ioctl(int min, struct file *fil
 		fprog.filter = code;
 
 		if (is->active_filter) {
-			sk_unattached_filter_destroy(is->active_filter);
+			bpf_prog_destroy(is->active_filter);
 			is->active_filter = NULL;
 		}
 		if (fprog.filter != NULL)
-			err = sk_unattached_filter_create(&is->active_filter,
-							  &fprog);
+			err = bpf_prog_create(&is->active_filter, &fprog);
 		else
 			err = 0;
 		kfree(code);
@@ -1174,14 +1172,14 @@ isdn_ppp_push_higher(isdn_net_dev *net_d
 	}
 
 	if (is->pass_filter
-	    && SK_RUN_FILTER(is->pass_filter, skb) == 0) {
+	    && BPF_PROG_RUN(is->pass_filter, skb) == 0) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
 		kfree_skb(skb);
 		return;
 	}
 	if (!(is->active_filter
-	      && SK_RUN_FILTER(is->active_filter, skb) == 0)) {
+	      && BPF_PROG_RUN(is->active_filter, skb) == 0)) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
 		lp->huptimer = 0;
@@ -1320,14 +1318,14 @@ isdn_ppp_xmit(struct sk_buff *skb, struc
 	}
 
 	if (ipt->pass_filter
-	    && SK_RUN_FILTER(ipt->pass_filter, skb) == 0) {
+	    && BPF_PROG_RUN(ipt->pass_filter, skb) == 0) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
 		kfree_skb(skb);
 		goto unlock;
 	}
 	if (!(ipt->active_filter
-	      && SK_RUN_FILTER(ipt->active_filter, skb) == 0)) {
+	      && BPF_PROG_RUN(ipt->active_filter, skb) == 0)) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
 		lp->huptimer = 0;
@@ -1517,9 +1515,9 @@ int isdn_ppp_autodial_filter(struct sk_b
 	}
 
 	drop |= is->pass_filter
-		&& SK_RUN_FILTER(is->pass_filter, skb) == 0;
+		&& BPF_PROG_RUN(is->pass_filter, skb) == 0;
 	drop |= is->active_filter
-		&& SK_RUN_FILTER(is->active_filter, skb) == 0;
+		&& BPF_PROG_RUN(is->active_filter, skb) == 0;
 
 	skb_push(skb, IPPP_MAX_HEADER - 4);
 	return drop;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/isdn/pcbit/drv.c linux-libre-3.17-rc7-gnu/drivers/isdn/pcbit/drv.c
--- linux-libre-3.16-gnu/drivers/isdn/pcbit/drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/isdn/pcbit/drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -1035,14 +1035,14 @@ static void pcbit_set_msn(struct pcbit_d
 		}
 		ptr->next = NULL;
 
-		ptr->msn = kmalloc(len, GFP_ATOMIC);
+		ptr->msn = kmalloc(len + 1, GFP_ATOMIC);
 		if (!ptr->msn) {
 			printk(KERN_WARNING "kmalloc failed\n");
 			kfree(ptr);
 			return;
 		}
 
-		memcpy(ptr->msn, sp, len - 1);
+		memcpy(ptr->msn, sp, len);
 		ptr->msn[len] = 0;
 
 #ifdef DEBUG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/Kconfig linux-libre-3.17-rc7-gnu/drivers/Kconfig
--- linux-libre-3.16-gnu/drivers/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -176,4 +176,8 @@ source "drivers/powercap/Kconfig"
 
 source "drivers/mcb/Kconfig"
 
+source "drivers/ras/Kconfig"
+
+source "drivers/thunderbolt/Kconfig"
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/Kconfig linux-libre-3.17-rc7-gnu/drivers/leds/Kconfig
--- linux-libre-3.16-gnu/drivers/leds/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -32,14 +32,6 @@ config LEDS_88PM860X
 	  This option enables support for on-chip LED drivers found on Marvell
 	  Semiconductor 88PM8606 PMIC.
 
-config LEDS_ATMEL_PWM
-	tristate "LED Support using Atmel PWM outputs"
-	depends on LEDS_CLASS
-	depends on ATMEL_PWM
-	help
-	  This option enables support for LEDs driven using outputs
-	  of the dedicated PWM controller found on newer Atmel SOCs.
-
 config LEDS_LM3530
 	tristate "LCD Backlight driver for LM3530"
 	depends on LEDS_CLASS
@@ -143,6 +135,13 @@ config LEDS_SUNFIRE
 	  This option enables support for the Left, Middle, and Right
 	  LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
 
+config LEDS_IPAQ_MICRO
+	tristate "LED Support for the Compaq iPAQ h3xxx"
+	depends on MFD_IPAQ_MICRO
+	help
+	  Choose this option if you want to use the notification LED on
+	  Compaq/HP iPAQ h3100 and h3600.
+
 config LEDS_HP6XX
 	tristate "LED Support for the HP Jornada 6xx"
 	depends on LEDS_CLASS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/led-class.c linux-libre-3.17-rc7-gnu/drivers/leds/led-class.c
--- linux-libre-3.16-gnu/drivers/leds/led-class.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/led-class.c	2014-09-28 17:29:07.000000000 -0400
@@ -210,8 +210,9 @@ static const struct dev_pm_ops leds_clas
  */
 int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 {
-	led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
-				      "%s", led_cdev->name);
+	led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
+					led_cdev, led_cdev->groups,
+					"%s", led_cdev->name);
 	if (IS_ERR(led_cdev->dev))
 		return PTR_ERR(led_cdev->dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-atmel-pwm.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-atmel-pwm.c
--- linux-libre-3.16-gnu/drivers/leds/leds-atmel-pwm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-atmel-pwm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,149 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/io.h>
-#include <linux/atmel_pwm.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-
-struct pwmled {
-	struct led_classdev	cdev;
-	struct pwm_channel	pwmc;
-	struct gpio_led		*desc;
-	u32			mult;
-	u8			active_low;
-};
-
-
-/*
- * For simplicity, we use "brightness" as if it were a linear function
- * of PWM duty cycle.  However, a logarithmic function of duty cycle is
- * probably a better match for perceived brightness: two is half as bright
- * as four, four is half as bright as eight, etc
- */
-static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
-{
-	struct pwmled		 *led;
-
-	/* update the duty cycle for the *next* period */
-	led = container_of(cdev, struct pwmled, cdev);
-	pwm_channel_writel(&led->pwmc, PWM_CUPD, led->mult * (unsigned) b);
-}
-
-/*
- * NOTE:  we reuse the platform_data structure of GPIO leds,
- * but repurpose its "gpio" number as a PWM channel number.
- */
-static int pwmled_probe(struct platform_device *pdev)
-{
-	const struct gpio_led_platform_data	*pdata;
-	struct pwmled				*leds;
-	int					i;
-	int					status;
-
-	pdata = dev_get_platdata(&pdev->dev);
-	if (!pdata || pdata->num_leds < 1)
-		return -ENODEV;
-
-	leds = devm_kzalloc(&pdev->dev, pdata->num_leds * sizeof(*leds),
-			GFP_KERNEL);
-	if (!leds)
-		return -ENOMEM;
-
-	for (i = 0; i < pdata->num_leds; i++) {
-		struct pwmled		*led = leds + i;
-		const struct gpio_led	*dat = pdata->leds + i;
-		u32			tmp;
-
-		led->cdev.name = dat->name;
-		led->cdev.brightness = LED_OFF;
-		led->cdev.brightness_set = pwmled_brightness;
-		led->cdev.default_trigger = dat->default_trigger;
-
-		led->active_low = dat->active_low;
-
-		status = pwm_channel_alloc(dat->gpio, &led->pwmc);
-		if (status < 0)
-			goto err;
-
-		/*
-		 * Prescale clock by 2^x, so PWM counts in low MHz.
-		 * Start each cycle with the LED active, so increasing
-		 * the duty cycle gives us more time on (== brighter).
-		 */
-		tmp = 5;
-		if (!led->active_low)
-			tmp |= PWM_CPR_CPOL;
-		pwm_channel_writel(&led->pwmc, PWM_CMR, tmp);
-
-		/*
-		 * Pick a period so PWM cycles at 100+ Hz; and a multiplier
-		 * for scaling duty cycle:  brightness * mult.
-		 */
-		tmp = (led->pwmc.mck / (1 << 5)) / 100;
-		tmp /= 255;
-		led->mult = tmp;
-		pwm_channel_writel(&led->pwmc, PWM_CDTY,
-				led->cdev.brightness * 255);
-		pwm_channel_writel(&led->pwmc, PWM_CPRD,
-				LED_FULL * tmp);
-
-		pwm_channel_enable(&led->pwmc);
-
-		/* Hand it over to the LED framework */
-		status = led_classdev_register(&pdev->dev, &led->cdev);
-		if (status < 0) {
-			pwm_channel_free(&led->pwmc);
-			goto err;
-		}
-	}
-
-	platform_set_drvdata(pdev, leds);
-	return 0;
-
-err:
-	if (i > 0) {
-		for (i = i - 1; i >= 0; i--) {
-			led_classdev_unregister(&leds[i].cdev);
-			pwm_channel_free(&leds[i].pwmc);
-		}
-	}
-
-	return status;
-}
-
-static int pwmled_remove(struct platform_device *pdev)
-{
-	const struct gpio_led_platform_data	*pdata;
-	struct pwmled				*leds;
-	unsigned				i;
-
-	pdata = dev_get_platdata(&pdev->dev);
-	leds = platform_get_drvdata(pdev);
-
-	for (i = 0; i < pdata->num_leds; i++) {
-		struct pwmled		*led = leds + i;
-
-		led_classdev_unregister(&led->cdev);
-		pwm_channel_free(&led->pwmc);
-	}
-
-	return 0;
-}
-
-static struct platform_driver pwmled_driver = {
-	.driver = {
-		.name =		"leds-atmel-pwm",
-		.owner =	THIS_MODULE,
-	},
-	/* REVISIT add suspend() and resume() methods */
-	.probe =	pwmled_probe,
-	.remove =	pwmled_remove,
-};
-
-module_platform_driver(pwmled_driver);
-
-MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:leds-atmel-pwm");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-ipaq-micro.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-ipaq-micro.c
--- linux-libre-3.16-gnu/drivers/leds/leds-ipaq-micro.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-ipaq-micro.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * h3xxx atmel micro companion support, notification LED subdevice
+ *
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ipaq-micro.h>
+#include <linux/leds.h>
+
+#define LED_YELLOW	0x00
+#define LED_GREEN	0x01
+
+#define LED_EN          (1 << 4)        /* LED ON/OFF 0:off, 1:on                       */
+#define LED_AUTOSTOP    (1 << 5)        /* LED ON/OFF auto stop set 0:disable, 1:enable */
+#define LED_ALWAYS      (1 << 6)        /* LED Interrupt Mask 0:No mask, 1:mask         */
+
+static void micro_leds_brightness_set(struct led_classdev *led_cdev,
+				      enum led_brightness value)
+{
+	struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
+	/*
+	 * In this message:
+	 * Byte 0 = LED color: 0 = yellow, 1 = green
+	 *          yellow LED is always ~30 blinks per minute
+	 * Byte 1 = duration (flags?) appears to be ignored
+	 * Byte 2 = green ontime in 1/10 sec (deciseconds)
+	 *          1 = 1/10 second
+	 *          0 = 256/10 second
+	 * Byte 3 = green offtime in 1/10 sec (deciseconds)
+	 *          1 = 1/10 second
+	 *          0 = 256/10 seconds
+	 */
+	struct ipaq_micro_msg msg = {
+		.id = MSG_NOTIFY_LED,
+		.tx_len = 4,
+	};
+
+	msg.tx_data[0] = LED_GREEN;
+	msg.tx_data[1] = 0;
+	if (value) {
+		msg.tx_data[2] = 0; /* Duty cycle 256 */
+		msg.tx_data[3] = 1;
+	} else {
+		msg.tx_data[2] = 1;
+		msg.tx_data[3] = 0; /* Duty cycle 256 */
+	}
+	ipaq_micro_tx_msg_sync(micro, &msg);
+}
+
+/* Maximum duty cycle in ms 256/10 sec = 25600 ms */
+#define IPAQ_LED_MAX_DUTY 25600
+
+static int micro_leds_blink_set(struct led_classdev *led_cdev,
+				unsigned long *delay_on,
+				unsigned long *delay_off)
+{
+	struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
+	/*
+	 * In this message:
+	 * Byte 0 = LED color: 0 = yellow, 1 = green
+	 *          yellow LED is always ~30 blinks per minute
+	 * Byte 1 = duration (flags?) appears to be ignored
+	 * Byte 2 = green ontime in 1/10 sec (deciseconds)
+	 *          1 = 1/10 second
+	 *          0 = 256/10 second
+	 * Byte 3 = green offtime in 1/10 sec (deciseconds)
+	 *          1 = 1/10 second
+	 *          0 = 256/10 seconds
+	 */
+	struct ipaq_micro_msg msg = {
+		.id = MSG_NOTIFY_LED,
+		.tx_len = 4,
+	};
+
+	msg.tx_data[0] = LED_GREEN;
+        if (*delay_on > IPAQ_LED_MAX_DUTY ||
+	    *delay_off > IPAQ_LED_MAX_DUTY)
+                return -EINVAL;
+
+        if (*delay_on == 0 && *delay_off == 0) {
+                *delay_on = 100;
+                *delay_off = 100;
+        }
+
+	msg.tx_data[1] = 0;
+	if (*delay_on >= IPAQ_LED_MAX_DUTY)
+		msg.tx_data[2] = 0;
+	else
+		msg.tx_data[2] = (u8) DIV_ROUND_CLOSEST(*delay_on, 100);
+	if (*delay_off >= IPAQ_LED_MAX_DUTY)
+		msg.tx_data[3] = 0;
+	else
+		msg.tx_data[3] = (u8) DIV_ROUND_CLOSEST(*delay_off, 100);
+	return ipaq_micro_tx_msg_sync(micro, &msg);
+}
+
+static struct led_classdev micro_led = {
+	.name			= "led-ipaq-micro",
+	.brightness_set		= micro_leds_brightness_set,
+	.blink_set		= micro_leds_blink_set,
+	.flags			= LED_CORE_SUSPENDRESUME,
+};
+
+static int micro_leds_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = led_classdev_register(&pdev->dev, &micro_led);
+	if (ret) {
+		dev_err(&pdev->dev, "registering led failed: %d\n", ret);
+		return ret;
+	}
+	dev_info(&pdev->dev, "iPAQ micro notification LED driver\n");
+
+	return 0;
+}
+
+static int micro_leds_remove(struct platform_device *pdev)
+{
+	led_classdev_unregister(&micro_led);
+	return 0;
+}
+
+static struct platform_driver micro_leds_device_driver = {
+	.driver = {
+		.name    = "ipaq-micro-leds",
+	},
+	.probe   = micro_leds_probe,
+	.remove  = micro_leds_remove,
+};
+module_platform_driver(micro_leds_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro leds");
+MODULE_ALIAS("platform:ipaq-micro-leds");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-lm3530.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3530.c
--- linux-libre-3.16-gnu/drivers/leds/leds-lm3530.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3530.c	2014-09-28 17:29:07.000000000 -0400
@@ -400,6 +400,12 @@ static ssize_t lm3530_mode_set(struct de
 }
 static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
 
+static struct attribute *lm3530_attrs[] = {
+	&dev_attr_mode.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(lm3530);
+
 static int lm3530_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
@@ -436,6 +442,7 @@ static int lm3530_probe(struct i2c_clien
 	drvdata->led_dev.name = LM3530_LED_DEV;
 	drvdata->led_dev.brightness_set = lm3530_brightness_set;
 	drvdata->led_dev.max_brightness = MAX_BRIGHTNESS;
+	drvdata->led_dev.groups = lm3530_groups;
 
 	i2c_set_clientdata(client, drvdata);
 
@@ -461,26 +468,13 @@ static int lm3530_probe(struct i2c_clien
 		return err;
 	}
 
-	err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
-	if (err < 0) {
-		dev_err(&client->dev, "File device creation failed: %d\n", err);
-		err = -ENODEV;
-		goto err_create_file;
-	}
-
 	return 0;
-
-err_create_file:
-	led_classdev_unregister(&drvdata->led_dev);
-	return err;
 }
 
 static int lm3530_remove(struct i2c_client *client)
 {
 	struct lm3530_data *drvdata = i2c_get_clientdata(client);
 
-	device_remove_file(drvdata->led_dev.dev, &dev_attr_mode);
-
 	lm3530_led_disable(drvdata);
 	led_classdev_unregister(&drvdata->led_dev);
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-lm3533.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3533.c
--- linux-libre-3.16-gnu/drivers/leds/leds-lm3533.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3533.c	2014-09-28 17:29:07.000000000 -0400
@@ -645,6 +645,11 @@ static struct attribute_group lm3533_led
 	.attrs		= lm3533_led_attributes
 };
 
+static const struct attribute_group *lm3533_led_attribute_groups[] = {
+	&lm3533_led_attribute_group,
+	NULL
+};
+
 static int lm3533_led_setup(struct lm3533_led *led,
 					struct lm3533_led_platform_data *pdata)
 {
@@ -692,6 +697,7 @@ static int lm3533_led_probe(struct platf
 	led->cdev.brightness_get = lm3533_led_get;
 	led->cdev.blink_set = lm3533_led_blink_set;
 	led->cdev.brightness = LED_OFF;
+	led->cdev.groups = lm3533_led_attribute_groups,
 	led->id = pdev->id;
 
 	mutex_init(&led->mutex);
@@ -715,25 +721,16 @@ static int lm3533_led_probe(struct platf
 
 	led->cb.dev = led->cdev.dev;
 
-	ret = sysfs_create_group(&led->cdev.dev->kobj,
-						&lm3533_led_attribute_group);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to create sysfs attributes\n");
-		goto err_unregister;
-	}
-
 	ret = lm3533_led_setup(led, pdata);
 	if (ret)
-		goto err_sysfs_remove;
+		goto err_unregister;
 
 	ret = lm3533_ctrlbank_enable(&led->cb);
 	if (ret)
-		goto err_sysfs_remove;
+		goto err_unregister;
 
 	return 0;
 
-err_sysfs_remove:
-	sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
 err_unregister:
 	led_classdev_unregister(&led->cdev);
 	flush_work(&led->work);
@@ -748,7 +745,6 @@ static int lm3533_led_remove(struct plat
 	dev_dbg(&pdev->dev, "%s\n", __func__);
 
 	lm3533_ctrlbank_disable(&led->cb);
-	sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
 	led_classdev_unregister(&led->cdev);
 	flush_work(&led->work);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-lm355x.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm355x.c
--- linux-libre-3.16-gnu/drivers/leds/leds-lm355x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm355x.c	2014-09-28 17:29:07.000000000 -0400
@@ -413,6 +413,12 @@ out:
 
 static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
 
+static struct attribute *lm355x_indicator_attrs[] = {
+	&dev_attr_pattern.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(lm355x_indicator);
+
 static const struct regmap_config lm355x_regmap = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -501,25 +507,18 @@ static int lm355x_probe(struct i2c_clien
 	else
 		chip->cdev_indicator.max_brightness = 8;
 	chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+	/* indicator pattern control only for LM3556 */
+	if (id->driver_data == CHIP_LM3556)
+		chip->cdev_indicator.groups = lm355x_indicator_groups;
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_indicator);
 	if (err < 0)
 		goto err_create_indicator_file;
-	/* indicator pattern control only for LM3554 */
-	if (id->driver_data == CHIP_LM3556) {
-		err =
-		    device_create_file(chip->cdev_indicator.dev,
-				       &dev_attr_pattern);
-		if (err < 0)
-			goto err_create_pattern_file;
-	}
 
 	dev_info(&client->dev, "%s is initialized\n",
 		 lm355x_name[id->driver_data]);
 	return 0;
 
-err_create_pattern_file:
-	led_classdev_unregister(&chip->cdev_indicator);
 err_create_indicator_file:
 	led_classdev_unregister(&chip->cdev_torch);
 err_create_torch_file:
@@ -534,8 +533,6 @@ static int lm355x_remove(struct i2c_clie
 	struct lm355x_reg_data *preg = chip->regs;
 
 	regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
-	if (chip->type == CHIP_LM3556)
-		device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
 	led_classdev_unregister(&chip->cdev_indicator);
 	flush_work(&chip->work_indicator);
 	led_classdev_unregister(&chip->cdev_torch);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-lm3642.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3642.c
--- linux-libre-3.16-gnu/drivers/leds/leds-lm3642.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-lm3642.c	2014-09-28 17:29:07.000000000 -0400
@@ -313,6 +313,18 @@ static const struct regmap_config lm3642
 	.max_register = REG_MAX,
 };
 
+static struct attribute *lm3642_flash_attrs[] = {
+	&dev_attr_strobe_pin.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(lm3642_flash);
+
+static struct attribute *lm3642_torch_attrs[] = {
+	&dev_attr_torch_pin.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(lm3642_torch);
+
 static int lm3642_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
@@ -364,17 +376,13 @@ static int lm3642_probe(struct i2c_clien
 	chip->cdev_flash.max_brightness = 16;
 	chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
 	chip->cdev_flash.default_trigger = "flash";
+	chip->cdev_flash.groups = lm3642_flash_groups,
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_flash);
 	if (err < 0) {
 		dev_err(chip->dev, "failed to register flash\n");
 		goto err_out;
 	}
-	err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
-	if (err < 0) {
-		dev_err(chip->dev, "failed to create strobe-pin file\n");
-		goto err_create_flash_pin_file;
-	}
 
 	/* torch */
 	INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
@@ -382,17 +390,13 @@ static int lm3642_probe(struct i2c_clien
 	chip->cdev_torch.max_brightness = 8;
 	chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
 	chip->cdev_torch.default_trigger = "torch";
+	chip->cdev_torch.groups = lm3642_torch_groups,
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_torch);
 	if (err < 0) {
 		dev_err(chip->dev, "failed to register torch\n");
 		goto err_create_torch_file;
 	}
-	err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
-	if (err < 0) {
-		dev_err(chip->dev, "failed to create torch-pin file\n");
-		goto err_create_torch_pin_file;
-	}
 
 	/* indicator */
 	INIT_WORK(&chip->work_indicator,
@@ -411,12 +415,8 @@ static int lm3642_probe(struct i2c_clien
 	return 0;
 
 err_create_indicator_file:
-	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
-err_create_torch_pin_file:
 	led_classdev_unregister(&chip->cdev_torch);
 err_create_torch_file:
-	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
-err_create_flash_pin_file:
 	led_classdev_unregister(&chip->cdev_flash);
 err_out:
 	return err;
@@ -428,10 +428,8 @@ static int lm3642_remove(struct i2c_clie
 
 	led_classdev_unregister(&chip->cdev_indicator);
 	flush_work(&chip->work_indicator);
-	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
 	led_classdev_unregister(&chip->cdev_torch);
 	flush_work(&chip->work_torch);
-	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
 	led_classdev_unregister(&chip->cdev_flash);
 	flush_work(&chip->work_flash);
 	regmap_write(chip->regmap, REG_ENABLE, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-lp55xx-common.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-lp55xx-common.c
--- linux-libre-3.16-gnu/drivers/leds/leds-lp55xx-common.c	2014-08-07 04:58:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-lp55xx-common.c	2014-09-28 21:41:16.000000000 -0400
@@ -127,15 +127,12 @@ static DEVICE_ATTR(led_current, S_IRUGO
 		lp55xx_store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL);
 
-static struct attribute *lp55xx_led_attributes[] = {
+static struct attribute *lp55xx_led_attrs[] = {
 	&dev_attr_led_current.attr,
 	&dev_attr_max_current.attr,
 	NULL,
 };
-
-static struct attribute_group lp55xx_led_attr_group = {
-	.attrs = lp55xx_led_attributes
-};
+ATTRIBUTE_GROUPS(lp55xx_led);
 
 static void lp55xx_set_brightness(struct led_classdev *cdev,
 			     enum led_brightness brightness)
@@ -176,6 +173,7 @@ static int lp55xx_init_led(struct lp55xx
 	}
 
 	led->cdev.brightness_set = lp55xx_set_brightness;
+	led->cdev.groups = lp55xx_led_groups;
 
 	if (pdata->led_config[chan].name) {
 		led->cdev.name = pdata->led_config[chan].name;
@@ -185,24 +183,12 @@ static int lp55xx_init_led(struct lp55xx
 		led->cdev.name = name;
 	}
 
-	/*
-	 * register led class device for each channel and
-	 * add device attributes
-	 */
-
 	ret = led_classdev_register(dev, &led->cdev);
 	if (ret) {
 		dev_err(dev, "led register err: %d\n", ret);
 		return ret;
 	}
 
-	ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group);
-	if (ret) {
-		dev_err(dev, "led sysfs err: %d\n", ret);
-		led_classdev_unregister(&led->cdev);
-		return ret;
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-max8997.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-max8997.c
--- linux-libre-3.16-gnu/drivers/leds/leds-max8997.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-max8997.c	2014-09-28 17:29:07.000000000 -0400
@@ -229,6 +229,12 @@ static ssize_t max8997_led_store_mode(st
 
 static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
 
+static struct attribute *max8997_attrs[] = {
+	&dev_attr_mode.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(max8997);
+
 static int max8997_led_probe(struct platform_device *pdev)
 {
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -253,6 +259,7 @@ static int max8997_led_probe(struct plat
 	led->cdev.brightness_set = max8997_led_brightness_set;
 	led->cdev.flags |= LED_CORE_SUSPENDRESUME;
 	led->cdev.brightness = 0;
+	led->cdev.groups = max8997_groups;
 	led->iodev = iodev;
 
 	/* initialize mode and brightness according to platform_data */
@@ -281,14 +288,6 @@ static int max8997_led_probe(struct plat
 	if (ret < 0)
 		return ret;
 
-	ret = device_create_file(led->cdev.dev, &dev_attr_mode);
-	if (ret != 0) {
-		dev_err(&pdev->dev,
-			"failed to create file: %d\n", ret);
-		led_classdev_unregister(&led->cdev);
-		return ret;
-	}
-
 	return 0;
 }
 
@@ -296,7 +295,6 @@ static int max8997_led_remove(struct pla
 {
 	struct max8997_led *led = platform_get_drvdata(pdev);
 
-	device_remove_file(led->cdev.dev, &dev_attr_mode);
 	led_classdev_unregister(&led->cdev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-netxbig.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-netxbig.c
--- linux-libre-3.16-gnu/drivers/leds/leds-netxbig.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-netxbig.c	2014-09-28 17:29:07.000000000 -0400
@@ -293,10 +293,14 @@ static ssize_t netxbig_led_sata_show(str
 
 static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
 
+static struct attribute *netxbig_led_attrs[] = {
+	&dev_attr_sata.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(netxbig_led);
+
 static void delete_netxbig_led(struct netxbig_led_data *led_dat)
 {
-	if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
-		device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
 	led_classdev_unregister(&led_dat->cdev);
 }
 
@@ -306,7 +310,6 @@ create_netxbig_led(struct platform_devic
 		   const struct netxbig_led *template)
 {
 	struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	int ret;
 
 	spin_lock_init(&led_dat->lock);
 	led_dat->gpio_ext = pdata->gpio_ext;
@@ -327,6 +330,12 @@ create_netxbig_led(struct platform_devic
 	led_dat->sata = 0;
 	led_dat->cdev.brightness = LED_OFF;
 	led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+	/*
+	 * If available, expose the SATA activity blink capability through
+	 * a "sata" sysfs attribute.
+	 */
+	if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
+		led_dat->cdev.groups = netxbig_led_groups;
 	led_dat->mode_addr = template->mode_addr;
 	led_dat->mode_val = template->mode_val;
 	led_dat->bright_addr = template->bright_addr;
@@ -334,21 +343,7 @@ create_netxbig_led(struct platform_devic
 	led_dat->timer = pdata->timer;
 	led_dat->num_timer = pdata->num_timer;
 
-	ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * If available, expose the SATA activity blink capability through
-	 * a "sata" sysfs attribute.
-	 */
-	if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
-		ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
-		if (ret)
-			led_classdev_unregister(&led_dat->cdev);
-	}
-
-	return ret;
+	return led_classdev_register(&pdev->dev, &led_dat->cdev);
 }
 
 static int netxbig_led_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-ns2.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-ns2.c
--- linux-libre-3.16-gnu/drivers/leds/leds-ns2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-ns2.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,6 +185,12 @@ static ssize_t ns2_led_sata_show(struct
 
 static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
 
+static struct attribute *ns2_led_attrs[] = {
+	&dev_attr_sata.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(ns2_led);
+
 static int
 create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 	       const struct ns2_led *template)
@@ -219,6 +225,7 @@ create_ns2_led(struct platform_device *p
 	led_dat->cdev.blink_set = NULL;
 	led_dat->cdev.brightness_set = ns2_led_set;
 	led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+	led_dat->cdev.groups = ns2_led_groups;
 	led_dat->cmd = template->cmd;
 	led_dat->slow = template->slow;
 
@@ -235,20 +242,11 @@ create_ns2_led(struct platform_device *p
 	if (ret < 0)
 		return ret;
 
-	ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
-	if (ret < 0)
-		goto err_free_cdev;
-
 	return 0;
-
-err_free_cdev:
-	led_classdev_unregister(&led_dat->cdev);
-	return ret;
 }
 
 static void delete_ns2_led(struct ns2_led_data *led_dat)
 {
-	device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
 	led_classdev_unregister(&led_dat->cdev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-pca963x.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-pca963x.c
--- linux-libre-3.16-gnu/drivers/leds/leds-pca963x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-pca963x.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,7 +12,7 @@
  * directory of this archive for more details.
  *
  * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
- * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.)
+ * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.)
  *
  * Note that hardware blinking violates the leds infrastructure driver
  * interface since the hardware only supports blinking all LEDs with the
@@ -52,6 +52,7 @@
 enum pca963x_type {
 	pca9633,
 	pca9634,
+	pca9635,
 };
 
 struct pca963x_chipdef {
@@ -74,6 +75,12 @@ static struct pca963x_chipdef pca963x_ch
 		.ledout_base	= 0xc,
 		.n_leds		= 8,
 	},
+	[pca9635] = {
+		.grppwm		= 0x12,
+		.grpfreq	= 0x13,
+		.ledout_base	= 0x14,
+		.n_leds		= 16,
+	},
 };
 
 /* Total blink period in milliseconds */
@@ -84,6 +91,7 @@ static const struct i2c_device_id pca963
 	{ "pca9632", pca9633 },
 	{ "pca9633", pca9633 },
 	{ "pca9634", pca9634 },
+	{ "pca9635", pca9635 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pca963x_id);
@@ -107,7 +115,7 @@ struct pca963x_led {
 	struct work_struct work;
 	enum led_brightness brightness;
 	struct led_classdev led_cdev;
-	int led_num; /* 0 .. 7 potentially */
+	int led_num; /* 0 .. 15 potentially */
 	enum pca963x_cmd cmd;
 	char name[32];
 	u8 gdc;
@@ -321,6 +329,7 @@ static const struct of_device_id of_pca9
 	{ .compatible = "nxp,pca9632", },
 	{ .compatible = "nxp,pca9633", },
 	{ .compatible = "nxp,pca9634", },
+	{ .compatible = "nxp,pca9635", },
 	{},
 };
 #else
@@ -375,9 +384,8 @@ static int pca963x_probe(struct i2c_clie
 	pca963x_chip->leds = pca963x;
 
 	/* Turn off LEDs by default*/
-	i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00);
-	if (chip->n_leds > 4)
-		i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00);
+	for (i = 0; i < chip->n_leds / 4; i++)
+		i2c_smbus_write_byte_data(client, chip->ledout_base + i, 0x00);
 
 	for (i = 0; i < chip->n_leds; i++) {
 		pca963x[i].led_num = i;
@@ -415,9 +423,13 @@ static int pca963x_probe(struct i2c_clie
 	/* Disable LED all-call address and set normal mode */
 	i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
 
-	/* Configure output: open-drain or totem pole (push-pull) */
-	if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN)
-		i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
+	if (pdata) {
+		/* Configure output: open-drain or totem pole (push-pull) */
+		if (pdata->outdrv == PCA963X_OPEN_DRAIN)
+			i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
+		else
+			i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x05);
+	}
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-ss4200.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-ss4200.c
--- linux-libre-3.16-gnu/drivers/leds/leds-ss4200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-ss4200.c	2014-09-28 17:29:07.000000000 -0400
@@ -469,6 +469,12 @@ static ssize_t nas_led_blink_store(struc
 
 static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
 
+static struct attribute *nasgpio_led_attrs[] = {
+	&dev_attr_blink.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(nasgpio_led);
+
 static int register_nasgpio_led(int led_nr)
 {
 	int ret;
@@ -481,20 +487,18 @@ static int register_nasgpio_led(int led_
 		led->brightness = LED_FULL;
 	led->brightness_set = nasgpio_led_set_brightness;
 	led->blink_set = nasgpio_led_set_blink;
+	led->groups = nasgpio_led_groups;
 	ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
 	if (ret)
 		return ret;
-	ret = device_create_file(led->dev, &dev_attr_blink);
-	if (ret)
-		led_classdev_unregister(led);
-	return ret;
+
+	return 0;
 }
 
 static void unregister_nasgpio_led(int led_nr)
 {
 	struct led_classdev *led = get_classdev_for_led_nr(led_nr);
 	led_classdev_unregister(led);
-	device_remove_file(led->dev, &dev_attr_blink);
 }
 /*
  * module load/initialization
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/leds-wm831x-status.c linux-libre-3.17-rc7-gnu/drivers/leds/leds-wm831x-status.c
--- linux-libre-3.16-gnu/drivers/leds/leds-wm831x-status.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/leds-wm831x-status.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,6 +219,12 @@ static ssize_t wm831x_status_src_store(s
 
 static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
 
+static struct attribute *wm831x_status_attrs[] = {
+	&dev_attr_src.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(wm831x_status);
+
 static int wm831x_status_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -232,8 +238,7 @@ static int wm831x_status_probe(struct pl
 	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "No register resource\n");
-		ret = -EINVAL;
-		goto err;
+		return -EINVAL;
 	}
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
@@ -284,31 +289,21 @@ static int wm831x_status_probe(struct pl
 	drvdata->cdev.default_trigger = pdata.default_trigger;
 	drvdata->cdev.brightness_set = wm831x_status_set;
 	drvdata->cdev.blink_set = wm831x_status_blink_set;
+	drvdata->cdev.groups = wm831x_status_groups;
 
 	ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
-		goto err_led;
+		return ret;
 	}
 
-	ret = device_create_file(drvdata->cdev.dev, &dev_attr_src);
-	if (ret != 0)
-		dev_err(&pdev->dev,
-			"No source control for LED: %d\n", ret);
-
 	return 0;
-
-err_led:
-	led_classdev_unregister(&drvdata->cdev);
-err:
-	return ret;
 }
 
 static int wm831x_status_remove(struct platform_device *pdev)
 {
 	struct wm831x_status *drvdata = platform_get_drvdata(pdev);
 
-	device_remove_file(drvdata->cdev.dev, &dev_attr_src);
 	led_classdev_unregister(&drvdata->cdev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/leds/Makefile linux-libre-3.17-rc7-gnu/drivers/leds/Makefile
--- linux-libre-3.16-gnu/drivers/leds/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/leds/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -6,7 +6,6 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= led-trig
 
 # LED Platform Drivers
 obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
-obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
 obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
@@ -31,6 +30,7 @@ obj-$(CONFIG_LEDS_LP8501)		+= leds-lp850
 obj-$(CONFIG_LEDS_LP8788)		+= leds-lp8788.o
 obj-$(CONFIG_LEDS_TCA6507)		+= leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
+obj-$(CONFIG_LEDS_IPAQ_MICRO)		+= leds-ipaq-micro.o
 obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
 obj-$(CONFIG_LEDS_OT200)		+= leds-ot200.o
 obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/lguest/core.c linux-libre-3.17-rc7-gnu/drivers/lguest/core.c
--- linux-libre-3.16-gnu/drivers/lguest/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/lguest/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,6 @@ DEFINE_MUTEX(lguest_lock);
 static __init int map_switcher(void)
 {
 	int i, err;
-	struct page **pagep;
 
 	/*
 	 * Map the Switcher in to high memory.
@@ -110,11 +109,9 @@ static __init int map_switcher(void)
 	 * This code actually sets up the pages we've allocated to appear at
 	 * switcher_addr.  map_vm_area() takes the vma we allocated above, the
 	 * kind of pages we're mapping (kernel pages), and a pointer to our
-	 * array of struct pages.  It increments that pointer, but we don't
-	 * care.
+	 * array of struct pages.
 	 */
-	pagep = lg_switcher_pages;
-	err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, &pagep);
+	err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);
 	if (err) {
 		printk("lguest: map_vm_area failed: %i\n", err);
 		goto free_vma;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/macintosh/via-pmu-backlight.c linux-libre-3.17-rc7-gnu/drivers/macintosh/via-pmu-backlight.c
--- linux-libre-3.16-gnu/drivers/macintosh/via-pmu-backlight.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/macintosh/via-pmu-backlight.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,13 +110,7 @@ static int pmu_backlight_update_status(s
 }
 
 
-static int pmu_backlight_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
 static const struct backlight_ops pmu_backlight_data = {
-	.get_brightness	= pmu_backlight_get_brightness,
 	.update_status	= pmu_backlight_update_status,
 
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/Kconfig linux-libre-3.17-rc7-gnu/drivers/mailbox/Kconfig
--- linux-libre-3.16-gnu/drivers/mailbox/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -16,26 +16,9 @@ config PL320_MBOX
 	  Management Engine, primarily for cpufreq. Say Y here if you want
 	  to use the PL320 IPCM support.
 
-config OMAP_MBOX
-	tristate
-	help
-	  This option is selected by any OMAP architecture specific mailbox
-	  driver such as CONFIG_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This
-	  enables the common OMAP mailbox framework code.
-
-config OMAP1_MBOX
-	tristate "OMAP1 Mailbox framework support"
-	depends on ARCH_OMAP1
-	select OMAP_MBOX
-	help
-	  Mailbox implementation for OMAP chips with hardware for
-	  interprocessor communication involving DSP in OMAP1. Say Y here
-	  if you want to use OMAP1 Mailbox framework support.
-
 config OMAP2PLUS_MBOX
 	tristate "OMAP2+ Mailbox framework support"
 	depends on ARCH_OMAP2PLUS
-	select OMAP_MBOX
 	help
 	  Mailbox implementation for OMAP family chips with hardware for
 	  interprocessor communication involving DSP, IVA1.0 and IVA2 in
@@ -44,7 +27,7 @@ config OMAP2PLUS_MBOX
 
 config OMAP_MBOX_KFIFO_SIZE
 	int "Mailbox kfifo default buffer size (bytes)"
-	depends on OMAP2PLUS_MBOX || OMAP1_MBOX
+	depends on OMAP2PLUS_MBOX
 	default 256
 	help
 	  Specify the default size of mailbox's kfifo buffers (bytes).
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/mailbox-omap1.c linux-libre-3.17-rc7-gnu/drivers/mailbox/mailbox-omap1.c
--- linux-libre-3.16-gnu/drivers/mailbox/mailbox-omap1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/mailbox-omap1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP1
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_ARM2DSP1		0x00
-#define MAILBOX_ARM2DSP1b		0x04
-#define MAILBOX_DSP2ARM1		0x08
-#define MAILBOX_DSP2ARM1b		0x0c
-#define MAILBOX_DSP2ARM2		0x10
-#define MAILBOX_DSP2ARM2b		0x14
-#define MAILBOX_ARM2DSP1_Flag		0x18
-#define MAILBOX_DSP2ARM1_Flag		0x1c
-#define MAILBOX_DSP2ARM2_Flag		0x20
-
-static void __iomem *mbox_base;
-
-struct omap_mbox1_fifo {
-	unsigned long cmd;
-	unsigned long data;
-	unsigned long flag;
-};
-
-struct omap_mbox1_priv {
-	struct omap_mbox1_fifo tx_fifo;
-	struct omap_mbox1_fifo rx_fifo;
-};
-
-static inline int mbox_read_reg(size_t ofs)
-{
-	return __raw_readw(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writew(val, mbox_base + ofs);
-}
-
-/* msg */
-static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-	mbox_msg_t msg;
-
-	msg = mbox_read_reg(fifo->data);
-	msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
-
-	return msg;
-}
-
-static void
-omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
-
-	mbox_write_reg(msg & 0xffff, fifo->data);
-	mbox_write_reg(msg >> 16, fifo->cmd);
-}
-
-static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	return 0;
-}
-
-static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-
-	return mbox_read_reg(fifo->flag);
-}
-
-/* irq */
-static void
-omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_RX)
-		enable_irq(mbox->irq);
-}
-
-static void
-omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_RX)
-		disable_irq(mbox->irq);
-}
-
-static int
-omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_TX)
-		return 0;
-	return 1;
-}
-
-static struct omap_mbox_ops omap1_mbox_ops = {
-	.type		= OMAP_MBOX_TYPE1,
-	.fifo_read	= omap1_mbox_fifo_read,
-	.fifo_write	= omap1_mbox_fifo_write,
-	.fifo_empty	= omap1_mbox_fifo_empty,
-	.fifo_full	= omap1_mbox_fifo_full,
-	.enable_irq	= omap1_mbox_enable_irq,
-	.disable_irq	= omap1_mbox_disable_irq,
-	.is_irq		= omap1_mbox_is_irq,
-};
-
-/* FIXME: the following struct should be created automatically by the user id */
-
-/* DSP */
-static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
-	.tx_fifo = {
-		.cmd	= MAILBOX_ARM2DSP1b,
-		.data	= MAILBOX_ARM2DSP1,
-		.flag	= MAILBOX_ARM2DSP1_Flag,
-	},
-	.rx_fifo = {
-		.cmd	= MAILBOX_DSP2ARM1b,
-		.data	= MAILBOX_DSP2ARM1,
-		.flag	= MAILBOX_DSP2ARM1_Flag,
-	},
-};
-
-static struct omap_mbox mbox_dsp_info = {
-	.name	= "dsp",
-	.ops	= &omap1_mbox_ops,
-	.priv	= &omap1_mbox_dsp_priv,
-};
-
-static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
-
-static int omap1_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list;
-
-	list = omap1_mboxes;
-	list[0]->irq = platform_get_irq_byname(pdev, "dsp");
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		return -ENOENT;
-
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base)
-		return -ENOMEM;
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret) {
-		iounmap(mbox_base);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int omap1_mbox_remove(struct platform_device *pdev)
-{
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	return 0;
-}
-
-static struct platform_driver omap1_mbox_driver = {
-	.probe	= omap1_mbox_probe,
-	.remove	= omap1_mbox_remove,
-	.driver	= {
-		.name	= "omap-mailbox",
-	},
-};
-
-static int __init omap1_mbox_init(void)
-{
-	return platform_driver_register(&omap1_mbox_driver);
-}
-
-static void __exit omap1_mbox_exit(void)
-{
-	platform_driver_unregister(&omap1_mbox_driver);
-}
-
-module_init(omap1_mbox_init);
-module_exit(omap1_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_ALIAS("platform:omap1-mailbox");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/mailbox-omap2.c linux-libre-3.17-rc7-gnu/drivers/mailbox/mailbox-omap2.c
--- linux-libre-3.16-gnu/drivers/mailbox/mailbox-omap2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/mailbox-omap2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,357 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP2/3
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *        and  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_data/mailbox-omap.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_REVISION		0x000
-#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
-#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
-#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
-#define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
-#define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))
-
-#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
-
-#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
-#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
-
-#define MBOX_REG_SIZE			0x120
-
-#define OMAP4_MBOX_REG_SIZE		0x130
-
-#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
-#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
-
-static void __iomem *mbox_base;
-
-struct omap_mbox2_fifo {
-	unsigned long msg;
-	unsigned long fifo_stat;
-	unsigned long msg_stat;
-};
-
-struct omap_mbox2_priv {
-	struct omap_mbox2_fifo tx_fifo;
-	struct omap_mbox2_fifo rx_fifo;
-	unsigned long irqenable;
-	unsigned long irqstatus;
-	u32 newmsg_bit;
-	u32 notfull_bit;
-	u32 ctx[OMAP4_MBOX_NR_REGS];
-	unsigned long irqdisable;
-	u32 intr_type;
-};
-
-static inline unsigned int mbox_read_reg(size_t ofs)
-{
-	return __raw_readl(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writel(val, mbox_base + ofs);
-}
-
-/* Mailbox H/W preparations */
-static int omap2_mbox_startup(struct omap_mbox *mbox)
-{
-	u32 l;
-
-	pm_runtime_enable(mbox->dev->parent);
-	pm_runtime_get_sync(mbox->dev->parent);
-
-	l = mbox_read_reg(MAILBOX_REVISION);
-	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
-	return 0;
-}
-
-static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
-	pm_runtime_put_sync(mbox->dev->parent);
-	pm_runtime_disable(mbox->dev->parent);
-}
-
-/* Mailbox FIFO handle functions */
-static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
-	return (mbox_msg_t) mbox_read_reg(fifo->msg);
-}
-
-static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
-	mbox_write_reg(msg, fifo->msg);
-}
-
-static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
-	return (mbox_read_reg(fifo->msg_stat) == 0);
-}
-
-static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
-	return mbox_read_reg(fifo->fifo_stat);
-}
-
-/* Mailbox IRQ handle functions */
-static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	l = mbox_read_reg(p->irqenable);
-	l |= bit;
-	mbox_write_reg(l, p->irqenable);
-}
-
-static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	/*
-	 * Read and update the interrupt configuration register for pre-OMAP4.
-	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
-	 */
-	if (!p->intr_type)
-		bit = mbox_read_reg(p->irqdisable) & ~bit;
-
-	mbox_write_reg(bit, p->irqdisable);
-}
-
-static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	mbox_write_reg(bit, p->irqstatus);
-
-	/* Flush posted write for irq status to avoid spurious interrupts */
-	mbox_read_reg(p->irqstatus);
-}
-
-static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-	u32 enable = mbox_read_reg(p->irqenable);
-	u32 status = mbox_read_reg(p->irqstatus);
-
-	return (int)(enable & status & bit);
-}
-
-static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-
-	if (p->intr_type)
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-
-	if (p->intr_type)
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		mbox_write_reg(p->ctx[i], i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static struct omap_mbox_ops omap2_mbox_ops = {
-	.type		= OMAP_MBOX_TYPE2,
-	.startup	= omap2_mbox_startup,
-	.shutdown	= omap2_mbox_shutdown,
-	.fifo_read	= omap2_mbox_fifo_read,
-	.fifo_write	= omap2_mbox_fifo_write,
-	.fifo_empty	= omap2_mbox_fifo_empty,
-	.fifo_full	= omap2_mbox_fifo_full,
-	.enable_irq	= omap2_mbox_enable_irq,
-	.disable_irq	= omap2_mbox_disable_irq,
-	.ack_irq	= omap2_mbox_ack_irq,
-	.is_irq		= omap2_mbox_is_irq,
-	.save_ctx	= omap2_mbox_save_ctx,
-	.restore_ctx	= omap2_mbox_restore_ctx,
-};
-
-static int omap2_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list, *mbox, *mboxblk;
-	struct omap_mbox2_priv *priv, *privblk;
-	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
-	struct omap_mbox_dev_info *info;
-	int i;
-
-	if (!pdata || !pdata->info_cnt || !pdata->info) {
-		pr_err("%s: platform not supported\n", __func__);
-		return -ENODEV;
-	}
-
-	/* allocate one extra for marking end of list */
-	list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-
-	mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
-	if (!mboxblk) {
-		ret = -ENOMEM;
-		goto free_list;
-	}
-
-	privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
-	if (!privblk) {
-		ret = -ENOMEM;
-		goto free_mboxblk;
-	}
-
-	info = pdata->info;
-	for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
-		priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
-		priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
-		priv->rx_fifo.msg =  MAILBOX_MESSAGE(info->rx_id);
-		priv->rx_fifo.msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
-		priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
-		priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
-		if (pdata->intr_type) {
-			priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
-			priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
-			priv->irqdisable =
-				OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
-		} else {
-			priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
-			priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
-			priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
-		}
-		priv->intr_type = pdata->intr_type;
-
-		mbox->priv = priv;
-		mbox->name = info->name;
-		mbox->ops = &omap2_mbox_ops;
-		mbox->irq = platform_get_irq(pdev, info->irq_id);
-		if (mbox->irq < 0) {
-			ret = mbox->irq;
-			goto free_privblk;
-		}
-		list[i] = mbox++;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		ret = -ENOENT;
-		goto free_privblk;
-	}
-
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base) {
-		ret = -ENOMEM;
-		goto free_privblk;
-	}
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret)
-		goto unmap_mbox;
-	platform_set_drvdata(pdev, list);
-
-	return 0;
-
-unmap_mbox:
-	iounmap(mbox_base);
-free_privblk:
-	kfree(privblk);
-free_mboxblk:
-	kfree(mboxblk);
-free_list:
-	kfree(list);
-	return ret;
-}
-
-static int omap2_mbox_remove(struct platform_device *pdev)
-{
-	struct omap_mbox2_priv *privblk;
-	struct omap_mbox **list = platform_get_drvdata(pdev);
-	struct omap_mbox *mboxblk = list[0];
-
-	privblk = mboxblk->priv;
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	kfree(privblk);
-	kfree(mboxblk);
-	kfree(list);
-
-	return 0;
-}
-
-static struct platform_driver omap2_mbox_driver = {
-	.probe	= omap2_mbox_probe,
-	.remove	= omap2_mbox_remove,
-	.driver	= {
-		.name = "omap-mailbox",
-	},
-};
-
-static int __init omap2_mbox_init(void)
-{
-	return platform_driver_register(&omap2_mbox_driver);
-}
-
-static void __exit omap2_mbox_exit(void)
-{
-	platform_driver_unregister(&omap2_mbox_driver);
-}
-
-module_init(omap2_mbox_init);
-module_exit(omap2_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_AUTHOR("Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/Makefile linux-libre-3.17-rc7-gnu/drivers/mailbox/Makefile
--- linux-libre-3.16-gnu/drivers/mailbox/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,3 @@
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
-obj-$(CONFIG_OMAP_MBOX)		+= omap-mailbox.o
-obj-$(CONFIG_OMAP1_MBOX)	+= mailbox_omap1.o
-mailbox_omap1-objs		:= mailbox-omap1.o
-obj-$(CONFIG_OMAP2PLUS_MBOX)	+= mailbox_omap2.o
-mailbox_omap2-objs		:= mailbox-omap2.o
+obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/omap-mailbox.c linux-libre-3.17-rc7-gnu/drivers/mailbox/omap-mailbox.c
--- linux-libre-3.16-gnu/drivers/mailbox/omap-mailbox.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/omap-mailbox.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,8 +2,10 @@
  * OMAP mailbox driver
  *
  * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2013-2014 Texas Instruments Inc.
  *
  * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *          Suman Anna <s-anna@ti.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -24,70 +26,164 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/kfifo.h>
 #include <linux/err.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/mailbox-omap.h>
+#include <linux/omap-mailbox.h>
 
-#include "omap-mbox.h"
+#define MAILBOX_REVISION		0x000
+#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
+#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
+#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
 
-static struct omap_mbox **mboxes;
+#define OMAP2_MAILBOX_IRQSTATUS(u)	(0x100 + 8 * (u))
+#define OMAP2_MAILBOX_IRQENABLE(u)	(0x104 + 8 * (u))
 
-static int mbox_configured;
-static DEFINE_MUTEX(mbox_configured_lock);
+#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
+
+#define MAILBOX_IRQSTATUS(type, u)	(type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
+						OMAP2_MAILBOX_IRQSTATUS(u))
+#define MAILBOX_IRQENABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE(u) : \
+						OMAP2_MAILBOX_IRQENABLE(u))
+#define MAILBOX_IRQDISABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
+						: OMAP2_MAILBOX_IRQENABLE(u))
+
+#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
+
+#define MBOX_REG_SIZE			0x120
+
+#define OMAP4_MBOX_REG_SIZE		0x130
+
+#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
+#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
+
+struct omap_mbox_fifo {
+	unsigned long msg;
+	unsigned long fifo_stat;
+	unsigned long msg_stat;
+	unsigned long irqenable;
+	unsigned long irqstatus;
+	unsigned long irqdisable;
+	u32 intr_bit;
+};
+
+struct omap_mbox_queue {
+	spinlock_t		lock;
+	struct kfifo		fifo;
+	struct work_struct	work;
+	struct tasklet_struct	tasklet;
+	struct omap_mbox	*mbox;
+	bool full;
+};
+
+struct omap_mbox_device {
+	struct device *dev;
+	struct mutex cfg_lock;
+	void __iomem *mbox_base;
+	u32 num_users;
+	u32 num_fifos;
+	struct omap_mbox **mboxes;
+	struct list_head elem;
+};
+
+struct omap_mbox {
+	const char		*name;
+	int			irq;
+	struct omap_mbox_queue	*txq, *rxq;
+	struct device		*dev;
+	struct omap_mbox_device *parent;
+	struct omap_mbox_fifo	tx_fifo;
+	struct omap_mbox_fifo	rx_fifo;
+	u32			ctx[OMAP4_MBOX_NR_REGS];
+	u32			intr_type;
+	int			use_count;
+	struct blocking_notifier_head	notifier;
+};
+
+/* global variables for the mailbox devices */
+static DEFINE_MUTEX(omap_mbox_devices_lock);
+static LIST_HEAD(omap_mbox_devices);
 
 static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
 module_param(mbox_kfifo_size, uint, S_IRUGO);
 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
 
+static inline
+unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
+{
+	return __raw_readl(mdev->mbox_base + ofs);
+}
+
+static inline
+void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
+{
+	__raw_writel(val, mdev->mbox_base + ofs);
+}
+
 /* Mailbox FIFO handle functions */
-static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
 {
-	return mbox->ops->fifo_read(mbox);
+	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
+	return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg);
 }
-static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+
+static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
 {
-	mbox->ops->fifo_write(mbox, msg);
+	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
+	mbox_write_reg(mbox->parent, msg, fifo->msg);
 }
-static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+
+static int mbox_fifo_empty(struct omap_mbox *mbox)
 {
-	return mbox->ops->fifo_empty(mbox);
+	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
+	return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
 }
-static inline int mbox_fifo_full(struct omap_mbox *mbox)
+
+static int mbox_fifo_full(struct omap_mbox *mbox)
 {
-	return mbox->ops->fifo_full(mbox);
+	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
+	return mbox_read_reg(mbox->parent, fifo->fifo_stat);
 }
 
 /* Mailbox IRQ handle functions */
-static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
-	if (mbox->ops->ack_irq)
-		mbox->ops->ack_irq(mbox, irq);
+	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqstatus = fifo->irqstatus;
+
+	mbox_write_reg(mbox->parent, bit, irqstatus);
+
+	/* Flush posted write for irq status to avoid spurious interrupts */
+	mbox_read_reg(mbox->parent, irqstatus);
 }
-static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+
+static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
-	return mbox->ops->is_irq(mbox, irq);
+	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqenable = fifo->irqenable;
+	u32 irqstatus = fifo->irqstatus;
+
+	u32 enable = mbox_read_reg(mbox->parent, irqenable);
+	u32 status = mbox_read_reg(mbox->parent, irqstatus);
+
+	return (int)(enable & status & bit);
 }
 
 /*
  * message sender
  */
-static int __mbox_poll_for_space(struct omap_mbox *mbox)
-{
-	int ret = 0, i = 1000;
-
-	while (mbox_fifo_full(mbox)) {
-		if (mbox->ops->type == OMAP_MBOX_TYPE2)
-			return -1;
-		if (--i == 0)
-			return -1;
-		udelay(1);
-	}
-	return ret;
-}
-
 int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
 {
 	struct omap_mbox_queue *mq = mbox->txq;
@@ -100,7 +196,7 @@ int omap_mbox_msg_send(struct omap_mbox
 		goto out;
 	}
 
-	if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+	if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
 		mbox_fifo_write(mbox, msg);
 		goto out;
 	}
@@ -118,35 +214,69 @@ EXPORT_SYMBOL(omap_mbox_msg_send);
 
 void omap_mbox_save_ctx(struct omap_mbox *mbox)
 {
-	if (!mbox->ops->save_ctx) {
-		dev_err(mbox->dev, "%s:\tno save\n", __func__);
-		return;
-	}
+	int i;
+	int nr_regs;
 
-	mbox->ops->save_ctx(mbox);
+	if (mbox->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, mbox->ctx[i]);
+	}
 }
 EXPORT_SYMBOL(omap_mbox_save_ctx);
 
 void omap_mbox_restore_ctx(struct omap_mbox *mbox)
 {
-	if (!mbox->ops->restore_ctx) {
-		dev_err(mbox->dev, "%s:\tno restore\n", __func__);
-		return;
-	}
+	int i;
+	int nr_regs;
 
-	mbox->ops->restore_ctx(mbox);
+	if (mbox->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, mbox->ctx[i]);
+	}
 }
 EXPORT_SYMBOL(omap_mbox_restore_ctx);
 
 void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
-	mbox->ops->enable_irq(mbox, irq);
+	u32 l;
+	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqenable = fifo->irqenable;
+
+	l = mbox_read_reg(mbox->parent, irqenable);
+	l |= bit;
+	mbox_write_reg(mbox->parent, l, irqenable);
 }
 EXPORT_SYMBOL(omap_mbox_enable_irq);
 
 void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
-	mbox->ops->disable_irq(mbox, irq);
+	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqdisable = fifo->irqdisable;
+
+	/*
+	 * Read and update the interrupt configuration register for pre-OMAP4.
+	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
+	 */
+	if (!mbox->intr_type)
+		bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
+
+	mbox_write_reg(mbox->parent, bit, irqdisable);
 }
 EXPORT_SYMBOL(omap_mbox_disable_irq);
 
@@ -158,7 +288,7 @@ static void mbox_tx_tasklet(unsigned lon
 	int ret;
 
 	while (kfifo_len(&mq->fifo)) {
-		if (__mbox_poll_for_space(mbox)) {
+		if (mbox_fifo_full(mbox)) {
 			omap_mbox_enable_irq(mbox, IRQ_TX);
 			break;
 		}
@@ -223,9 +353,6 @@ static void __mbox_rx_interrupt(struct o
 
 		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 		WARN_ON(len != sizeof(msg));
-
-		if (mbox->ops->type == OMAP_MBOX_TYPE1)
-			break;
 	}
 
 	/* no more messages in the fifo. clear IRQ source. */
@@ -283,16 +410,12 @@ static int omap_mbox_startup(struct omap
 {
 	int ret = 0;
 	struct omap_mbox_queue *mq;
+	struct omap_mbox_device *mdev = mbox->parent;
 
-	mutex_lock(&mbox_configured_lock);
-	if (!mbox_configured++) {
-		if (likely(mbox->ops->startup)) {
-			ret = mbox->ops->startup(mbox);
-			if (unlikely(ret))
-				goto fail_startup;
-		} else
-			goto fail_startup;
-	}
+	mutex_lock(&mdev->cfg_lock);
+	ret = pm_runtime_get_sync(mdev->dev);
+	if (unlikely(ret < 0))
+		goto fail_startup;
 
 	if (!mbox->use_count++) {
 		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
@@ -319,7 +442,7 @@ static int omap_mbox_startup(struct omap
 
 		omap_mbox_enable_irq(mbox, IRQ_RX);
 	}
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 	return 0;
 
 fail_request_irq:
@@ -327,18 +450,18 @@ fail_request_irq:
 fail_alloc_rxq:
 	mbox_queue_free(mbox->txq);
 fail_alloc_txq:
-	if (mbox->ops->shutdown)
-		mbox->ops->shutdown(mbox);
+	pm_runtime_put_sync(mdev->dev);
 	mbox->use_count--;
 fail_startup:
-	mbox_configured--;
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 	return ret;
 }
 
 static void omap_mbox_fini(struct omap_mbox *mbox)
 {
-	mutex_lock(&mbox_configured_lock);
+	struct omap_mbox_device *mdev = mbox->parent;
+
+	mutex_lock(&mdev->cfg_lock);
 
 	if (!--mbox->use_count) {
 		omap_mbox_disable_irq(mbox, IRQ_RX);
@@ -349,28 +472,43 @@ static void omap_mbox_fini(struct omap_m
 		mbox_queue_free(mbox->rxq);
 	}
 
-	if (likely(mbox->ops->shutdown)) {
-		if (!--mbox_configured)
-			mbox->ops->shutdown(mbox);
-	}
+	pm_runtime_put_sync(mdev->dev);
 
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 }
 
-struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
+					       const char *mbox_name)
 {
 	struct omap_mbox *_mbox, *mbox = NULL;
-	int i, ret;
+	struct omap_mbox **mboxes = mdev->mboxes;
+	int i;
 
 	if (!mboxes)
-		return ERR_PTR(-EINVAL);
+		return NULL;
 
 	for (i = 0; (_mbox = mboxes[i]); i++) {
-		if (!strcmp(_mbox->name, name)) {
+		if (!strcmp(_mbox->name, mbox_name)) {
 			mbox = _mbox;
 			break;
 		}
 	}
+	return mbox;
+}
+
+struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+{
+	struct omap_mbox *mbox = NULL;
+	struct omap_mbox_device *mdev;
+	int ret;
+
+	mutex_lock(&omap_mbox_devices_lock);
+	list_for_each_entry(mdev, &omap_mbox_devices, elem) {
+		mbox = omap_mbox_device_find(mdev, name);
+		if (mbox)
+			break;
+	}
+	mutex_unlock(&omap_mbox_devices_lock);
 
 	if (!mbox)
 		return ERR_PTR(-ENOENT);
@@ -397,19 +535,20 @@ EXPORT_SYMBOL(omap_mbox_put);
 
 static struct class omap_mbox_class = { .name = "mbox", };
 
-int omap_mbox_register(struct device *parent, struct omap_mbox **list)
+static int omap_mbox_register(struct omap_mbox_device *mdev)
 {
 	int ret;
 	int i;
+	struct omap_mbox **mboxes;
 
-	mboxes = list;
-	if (!mboxes)
+	if (!mdev || !mdev->mboxes)
 		return -EINVAL;
 
+	mboxes = mdev->mboxes;
 	for (i = 0; mboxes[i]; i++) {
 		struct omap_mbox *mbox = mboxes[i];
 		mbox->dev = device_create(&omap_mbox_class,
-				parent, 0, mbox, "%s", mbox->name);
+				mdev->dev, 0, mbox, "%s", mbox->name);
 		if (IS_ERR(mbox->dev)) {
 			ret = PTR_ERR(mbox->dev);
 			goto err_out;
@@ -417,6 +556,11 @@ int omap_mbox_register(struct device *pa
 
 		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
 	}
+
+	mutex_lock(&omap_mbox_devices_lock);
+	list_add(&mdev->elem, &omap_mbox_devices);
+	mutex_unlock(&omap_mbox_devices_lock);
+
 	return 0;
 
 err_out:
@@ -424,21 +568,148 @@ err_out:
 		device_unregister(mboxes[i]->dev);
 	return ret;
 }
-EXPORT_SYMBOL(omap_mbox_register);
 
-int omap_mbox_unregister(void)
+static int omap_mbox_unregister(struct omap_mbox_device *mdev)
 {
 	int i;
+	struct omap_mbox **mboxes;
 
-	if (!mboxes)
+	if (!mdev || !mdev->mboxes)
 		return -EINVAL;
 
+	mutex_lock(&omap_mbox_devices_lock);
+	list_del(&mdev->elem);
+	mutex_unlock(&omap_mbox_devices_lock);
+
+	mboxes = mdev->mboxes;
 	for (i = 0; mboxes[i]; i++)
 		device_unregister(mboxes[i]->dev);
-	mboxes = NULL;
 	return 0;
 }
-EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int omap_mbox_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+	struct omap_mbox **list, *mbox, *mboxblk;
+	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
+	struct omap_mbox_dev_info *info;
+	struct omap_mbox_device *mdev;
+	struct omap_mbox_fifo *fifo;
+	u32 intr_type;
+	u32 l;
+	int i;
+
+	if (!pdata || !pdata->info_cnt || !pdata->info) {
+		pr_err("%s: platform not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
+	if (!mdev)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(mdev->mbox_base))
+		return PTR_ERR(mdev->mbox_base);
+
+	/* allocate one extra for marking end of list */
+	list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
+			    GFP_KERNEL);
+	if (!list)
+		return -ENOMEM;
+
+	mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
+			       GFP_KERNEL);
+	if (!mboxblk)
+		return -ENOMEM;
+
+	info = pdata->info;
+	intr_type = pdata->intr_type;
+	mbox = mboxblk;
+	for (i = 0; i < pdata->info_cnt; i++, info++) {
+		fifo = &mbox->tx_fifo;
+		fifo->msg = MAILBOX_MESSAGE(info->tx_id);
+		fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
+		fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
+		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+		fifo = &mbox->rx_fifo;
+		fifo->msg =  MAILBOX_MESSAGE(info->rx_id);
+		fifo->msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
+		fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
+		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+		mbox->intr_type = intr_type;
+
+		mbox->parent = mdev;
+		mbox->name = info->name;
+		mbox->irq = platform_get_irq(pdev, info->irq_id);
+		if (mbox->irq < 0)
+			return mbox->irq;
+		list[i] = mbox++;
+	}
+
+	mutex_init(&mdev->cfg_lock);
+	mdev->dev = &pdev->dev;
+	mdev->num_users = pdata->num_users;
+	mdev->num_fifos = pdata->num_fifos;
+	mdev->mboxes = list;
+	ret = omap_mbox_register(mdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, mdev);
+	pm_runtime_enable(mdev->dev);
+
+	ret = pm_runtime_get_sync(mdev->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(mdev->dev);
+		goto unregister;
+	}
+
+	/*
+	 * just print the raw revision register, the format is not
+	 * uniform across all SoCs
+	 */
+	l = mbox_read_reg(mdev, MAILBOX_REVISION);
+	dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
+
+	ret = pm_runtime_put_sync(mdev->dev);
+	if (ret < 0)
+		goto unregister;
+
+	return 0;
+
+unregister:
+	pm_runtime_disable(mdev->dev);
+	omap_mbox_unregister(mdev);
+	return ret;
+}
+
+static int omap_mbox_remove(struct platform_device *pdev)
+{
+	struct omap_mbox_device *mdev = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(mdev->dev);
+	omap_mbox_unregister(mdev);
+
+	return 0;
+}
+
+static struct platform_driver omap_mbox_driver = {
+	.probe	= omap_mbox_probe,
+	.remove	= omap_mbox_remove,
+	.driver	= {
+		.name = "omap-mailbox",
+		.owner = THIS_MODULE,
+	},
+};
 
 static int __init omap_mbox_init(void)
 {
@@ -453,12 +724,13 @@ static int __init omap_mbox_init(void)
 	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
 							sizeof(mbox_msg_t));
 
-	return 0;
+	return platform_driver_register(&omap_mbox_driver);
 }
 subsys_initcall(omap_mbox_init);
 
 static void __exit omap_mbox_exit(void)
 {
+	platform_driver_unregister(&omap_mbox_driver);
 	class_unregister(&omap_mbox_class);
 }
 module_exit(omap_mbox_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mailbox/omap-mbox.h linux-libre-3.17-rc7-gnu/drivers/mailbox/omap-mbox.h
--- linux-libre-3.16-gnu/drivers/mailbox/omap-mbox.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mailbox/omap-mbox.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/*
- * omap-mbox.h: OMAP mailbox internal definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef OMAP_MBOX_H
-#define OMAP_MBOX_H
-
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/omap-mailbox.h>
-
-typedef int __bitwise omap_mbox_type_t;
-#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
-#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
-
-struct omap_mbox_ops {
-	omap_mbox_type_t	type;
-	int		(*startup)(struct omap_mbox *mbox);
-	void		(*shutdown)(struct omap_mbox *mbox);
-	/* fifo */
-	mbox_msg_t	(*fifo_read)(struct omap_mbox *mbox);
-	void		(*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
-	int		(*fifo_empty)(struct omap_mbox *mbox);
-	int		(*fifo_full)(struct omap_mbox *mbox);
-	/* irq */
-	void		(*enable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*disable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	int		(*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	/* ctx */
-	void		(*save_ctx)(struct omap_mbox *mbox);
-	void		(*restore_ctx)(struct omap_mbox *mbox);
-};
-
-struct omap_mbox_queue {
-	spinlock_t		lock;
-	struct kfifo		fifo;
-	struct work_struct	work;
-	struct tasklet_struct	tasklet;
-	struct omap_mbox	*mbox;
-	bool full;
-};
-
-struct omap_mbox {
-	const char		*name;
-	int			irq;
-	struct omap_mbox_queue	*txq, *rxq;
-	struct omap_mbox_ops	*ops;
-	struct device		*dev;
-	void			*priv;
-	int			use_count;
-	struct blocking_notifier_head	notifier;
-};
-
-int omap_mbox_register(struct device *parent, struct omap_mbox **);
-int omap_mbox_unregister(void);
-
-#endif /* OMAP_MBOX_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/Makefile linux-libre-3.17-rc7-gnu/drivers/Makefile
--- linux-libre-3.16-gnu/drivers/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,7 @@ obj-$(CONFIG_FB_INTEL)          += video
 
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ mfd/ nfc/
+obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-y				+= macintosh/
 obj-$(CONFIG_IDE)		+= ide/
@@ -158,3 +159,5 @@ obj-$(CONFIG_NTB)		+= ntb/
 obj-$(CONFIG_FMC)		+= fmc/
 obj-$(CONFIG_POWERCAP)		+= powercap/
 obj-$(CONFIG_MCB)		+= mcb/
+obj-$(CONFIG_RAS)		+= ras/
+obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/alloc.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/alloc.c
--- linux-libre-3.16-gnu/drivers/md/bcache/alloc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/alloc.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,7 +331,7 @@ static int bch_allocator_thread(void *ar
 				mutex_unlock(&ca->set->bucket_lock);
 				blkdev_issue_discard(ca->bdev,
 					bucket_to_sector(ca->set, bucket),
-					ca->sb.block_size, GFP_KERNEL, 0);
+					ca->sb.bucket_size, GFP_KERNEL, 0);
 				mutex_lock(&ca->set->bucket_lock);
 			}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/bcache.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/bcache.h
--- linux-libre-3.16-gnu/drivers/md/bcache/bcache.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/bcache.h	2014-09-28 17:29:07.000000000 -0400
@@ -477,9 +477,13 @@ struct gc_stat {
  * CACHE_SET_STOPPING always gets set first when we're closing down a cache set;
  * we'll continue to run normally for awhile with CACHE_SET_STOPPING set (i.e.
  * flushing dirty data).
+ *
+ * CACHE_SET_RUNNING means all cache devices have been registered and journal
+ * replay is complete.
  */
 #define CACHE_SET_UNREGISTERING		0
 #define	CACHE_SET_STOPPING		1
+#define	CACHE_SET_RUNNING		2
 
 struct cache_set {
 	struct closure		cl;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/bset.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/bset.c
--- linux-libre-3.16-gnu/drivers/md/bcache/bset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/bset.c	2014-09-28 17:29:07.000000000 -0400
@@ -1182,7 +1182,7 @@ static void __btree_sort(struct btree_ke
 {
 	uint64_t start_time;
 	bool used_mempool = false;
-	struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO,
+	struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOWAIT,
 						     order);
 	if (!out) {
 		struct page *outp;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/bset.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/bset.h
--- linux-libre-3.16-gnu/drivers/md/bcache/bset.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/bset.h	2014-09-28 17:29:07.000000000 -0400
@@ -453,7 +453,7 @@ static inline bool bch_bkey_equal_header
 {
 	return (KEY_DIRTY(l) == KEY_DIRTY(r) &&
 		KEY_PTRS(l) == KEY_PTRS(r) &&
-		KEY_CSUM(l) == KEY_CSUM(l));
+		KEY_CSUM(l) == KEY_CSUM(r));
 }
 
 /* Keylists */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/btree.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/btree.c
--- linux-libre-3.16-gnu/drivers/md/bcache/btree.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/btree.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,9 +117,9 @@
 ({									\
 	int _r, l = (b)->level - 1;					\
 	bool _w = l <= (op)->lock;					\
-	struct btree *_child = bch_btree_node_get((b)->c, op, key, l, _w);\
+	struct btree *_child = bch_btree_node_get((b)->c, op, key, l,	\
+						  _w, b);		\
 	if (!IS_ERR(_child)) {						\
-		_child->parent = (b);					\
 		_r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__);	\
 		rw_unlock(_w, _child);					\
 	} else								\
@@ -142,7 +142,6 @@
 		rw_lock(_w, _b, _b->level);				\
 		if (_b == (c)->root &&					\
 		    _w == insert_lock(op, _b)) {			\
-			_b->parent = NULL;				\
 			_r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__);	\
 		}							\
 		rw_unlock(_w, _b);					\
@@ -202,7 +201,7 @@ void bch_btree_node_read_done(struct btr
 	struct bset *i = btree_bset_first(b);
 	struct btree_iter *iter;
 
-	iter = mempool_alloc(b->c->fill_iter, GFP_NOWAIT);
+	iter = mempool_alloc(b->c->fill_iter, GFP_NOIO);
 	iter->size = b->c->sb.bucket_size / b->c->sb.block_size;
 	iter->used = 0;
 
@@ -421,7 +420,7 @@ static void do_btree_node_write(struct b
 	SET_PTR_OFFSET(&k.key, 0, PTR_OFFSET(&k.key, 0) +
 		       bset_sector_offset(&b->keys, i));
 
-	if (!bio_alloc_pages(b->bio, GFP_NOIO)) {
+	if (!bio_alloc_pages(b->bio, __GFP_NOWARN|GFP_NOWAIT)) {
 		int j;
 		struct bio_vec *bv;
 		void *base = (void *) ((unsigned long) i & ~(PAGE_SIZE - 1));
@@ -967,7 +966,8 @@ err:
  * level and op->lock.
  */
 struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
-				 struct bkey *k, int level, bool write)
+				 struct bkey *k, int level, bool write,
+				 struct btree *parent)
 {
 	int i = 0;
 	struct btree *b;
@@ -1002,6 +1002,7 @@ retry:
 		BUG_ON(b->level != level);
 	}
 
+	b->parent = parent;
 	b->accessed = 1;
 
 	for (; i <= b->keys.nsets && b->keys.set[i].size; i++) {
@@ -1022,15 +1023,16 @@ retry:
 	return b;
 }
 
-static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level)
+static void btree_node_prefetch(struct btree *parent, struct bkey *k)
 {
 	struct btree *b;
 
-	mutex_lock(&c->bucket_lock);
-	b = mca_alloc(c, NULL, k, level);
-	mutex_unlock(&c->bucket_lock);
+	mutex_lock(&parent->c->bucket_lock);
+	b = mca_alloc(parent->c, NULL, k, parent->level - 1);
+	mutex_unlock(&parent->c->bucket_lock);
 
 	if (!IS_ERR_OR_NULL(b)) {
+		b->parent = parent;
 		bch_btree_node_read(b);
 		rw_unlock(true, b);
 	}
@@ -1060,15 +1062,16 @@ static void btree_node_free(struct btree
 	mutex_unlock(&b->c->bucket_lock);
 }
 
-struct btree *bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
-				   int level)
+struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
+				     int level, bool wait,
+				     struct btree *parent)
 {
 	BKEY_PADDED(key) k;
 	struct btree *b = ERR_PTR(-EAGAIN);
 
 	mutex_lock(&c->bucket_lock);
 retry:
-	if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, op != NULL))
+	if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, wait))
 		goto err;
 
 	bkey_put(c, &k.key);
@@ -1085,6 +1088,7 @@ retry:
 	}
 
 	b->accessed = 1;
+	b->parent = parent;
 	bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb));
 
 	mutex_unlock(&c->bucket_lock);
@@ -1096,14 +1100,21 @@ err_free:
 err:
 	mutex_unlock(&c->bucket_lock);
 
-	trace_bcache_btree_node_alloc_fail(b);
+	trace_bcache_btree_node_alloc_fail(c);
 	return b;
 }
 
+static struct btree *bch_btree_node_alloc(struct cache_set *c,
+					  struct btree_op *op, int level,
+					  struct btree *parent)
+{
+	return __bch_btree_node_alloc(c, op, level, op != NULL, parent);
+}
+
 static struct btree *btree_node_alloc_replacement(struct btree *b,
 						  struct btree_op *op)
 {
-	struct btree *n = bch_btree_node_alloc(b->c, op, b->level);
+	struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
 	if (!IS_ERR_OR_NULL(n)) {
 		mutex_lock(&n->write_lock);
 		bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
@@ -1403,6 +1414,7 @@ static int btree_gc_coalesce(struct btre
 	BUG_ON(btree_bset_first(new_nodes[0])->keys);
 	btree_node_free(new_nodes[0]);
 	rw_unlock(true, new_nodes[0]);
+	new_nodes[0] = NULL;
 
 	for (i = 0; i < nodes; i++) {
 		if (__bch_keylist_realloc(&keylist, bkey_u64s(&r[i].b->key)))
@@ -1516,7 +1528,7 @@ static int btree_gc_recurse(struct btree
 		k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad);
 		if (k) {
 			r->b = bch_btree_node_get(b->c, op, k, b->level - 1,
-						  true);
+						  true, b);
 			if (IS_ERR(r->b)) {
 				ret = PTR_ERR(r->b);
 				break;
@@ -1811,7 +1823,7 @@ static int bch_btree_check_recurse(struc
 			k = bch_btree_iter_next_filter(&iter, &b->keys,
 						       bch_ptr_bad);
 			if (k)
-				btree_node_prefetch(b->c, k, b->level - 1);
+				btree_node_prefetch(b, k);
 
 			if (p)
 				ret = btree(check_recurse, p, b, op);
@@ -1976,12 +1988,12 @@ static int btree_split(struct btree *b,
 
 		trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys);
 
-		n2 = bch_btree_node_alloc(b->c, op, b->level);
+		n2 = bch_btree_node_alloc(b->c, op, b->level, b->parent);
 		if (IS_ERR(n2))
 			goto err_free1;
 
 		if (!b->parent) {
-			n3 = bch_btree_node_alloc(b->c, op, b->level + 1);
+			n3 = bch_btree_node_alloc(b->c, op, b->level + 1, NULL);
 			if (IS_ERR(n3))
 				goto err_free2;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/btree.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/btree.h
--- linux-libre-3.16-gnu/drivers/md/bcache/btree.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/btree.h	2014-09-28 17:29:07.000000000 -0400
@@ -242,9 +242,10 @@ void __bch_btree_node_write(struct btree
 void bch_btree_node_write(struct btree *, struct closure *);
 
 void bch_btree_set_root(struct btree *);
-struct btree *bch_btree_node_alloc(struct cache_set *, struct btree_op *, int);
+struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *,
+				     int, bool, struct btree *);
 struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *,
-				 struct bkey *, int, bool);
+				 struct bkey *, int, bool, struct btree *);
 
 int bch_btree_insert_check_key(struct btree *, struct btree_op *,
 			       struct bkey *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/extents.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/extents.c
--- linux-libre-3.16-gnu/drivers/md/bcache/extents.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/extents.c	2014-09-28 17:29:07.000000000 -0400
@@ -474,9 +474,8 @@ out:
 	return false;
 }
 
-static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k)
 {
-	struct btree *b = container_of(bk, struct btree, keys);
 	char buf[80];
 
 	if (!KEY_SIZE(k))
@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct bt
 	if (KEY_SIZE(k) > KEY_OFFSET(k))
 		goto bad;
 
-	if (__ptr_invalid(b->c, k))
+	if (__ptr_invalid(c, k))
 		goto bad;
 
 	return false;
 bad:
 	bch_extent_to_text(buf, sizeof(buf), k);
-	cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k));
+	cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
 	return true;
 }
 
+static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+{
+	struct btree *b = container_of(bk, struct btree, keys);
+	return __bch_extent_invalid(b->c, k);
+}
+
 static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
 				     unsigned ptr)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/extents.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/extents.h
--- linux-libre-3.16-gnu/drivers/md/bcache/extents.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/extents.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,5 +9,6 @@ struct cache_set;
 
 void bch_extent_to_text(char *, size_t, const struct bkey *);
 bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
+bool __bch_extent_invalid(struct cache_set *, const struct bkey *);
 
 #endif /* _BCACHE_EXTENTS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/journal.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/journal.c
--- linux-libre-3.16-gnu/drivers/md/bcache/journal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/journal.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@
 #include "bcache.h"
 #include "btree.h"
 #include "debug.h"
+#include "extents.h"
 
 #include <trace/events/bcache.h>
 
@@ -189,11 +190,15 @@ int bch_journal_read(struct cache_set *c
 			if (read_bucket(l))
 				goto bsearch;
 
-		if (list_empty(list))
+		/* no journal entries on this device? */
+		if (l == ca->sb.njournal_buckets)
 			continue;
 bsearch:
+		BUG_ON(list_empty(list));
+
 		/* Binary search */
-		m = r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
+		m = l;
+		r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
 		pr_debug("starting binary search, l %u r %u", l, r);
 
 		while (l + 1 < r) {
@@ -291,15 +296,16 @@ void bch_journal_mark(struct cache_set *
 
 		for (k = i->j.start;
 		     k < bset_bkey_last(&i->j);
-		     k = bkey_next(k)) {
-			unsigned j;
+		     k = bkey_next(k))
+			if (!__bch_extent_invalid(c, k)) {
+				unsigned j;
 
-			for (j = 0; j < KEY_PTRS(k); j++)
-				if (ptr_available(c, k, j))
-					atomic_inc(&PTR_BUCKET(c, k, j)->pin);
+				for (j = 0; j < KEY_PTRS(k); j++)
+					if (ptr_available(c, k, j))
+						atomic_inc(&PTR_BUCKET(c, k, j)->pin);
 
-			bch_initial_mark_key(c, 0, k);
-		}
+				bch_initial_mark_key(c, 0, k);
+			}
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/request.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/request.c
--- linux-libre-3.16-gnu/drivers/md/bcache/request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/request.c	2014-09-28 17:29:07.000000000 -0400
@@ -311,7 +311,8 @@ void bch_data_insert(struct closure *cl)
 {
 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
 
-	trace_bcache_write(op->bio, op->writeback, op->bypass);
+	trace_bcache_write(op->c, op->inode, op->bio,
+			   op->writeback, op->bypass);
 
 	bch_keylist_init(&op->insert_keys);
 	bio_get(op->bio);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/super.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/super.c
--- linux-libre-3.16-gnu/drivers/md/bcache/super.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/super.c	2014-09-28 17:29:07.000000000 -0400
@@ -733,8 +733,6 @@ static void bcache_device_detach(struct
 static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
 				 unsigned id)
 {
-	BUG_ON(test_bit(CACHE_SET_STOPPING, &c->flags));
-
 	d->id = id;
 	d->c = c;
 	c->devices[id] = d;
@@ -927,6 +925,7 @@ static void cached_dev_detach_finish(str
 	list_move(&dc->list, &uncached_devices);
 
 	clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
+	clear_bit(BCACHE_DEV_UNLINK_DONE, &dc->disk.flags);
 
 	mutex_unlock(&bch_register_lock);
 
@@ -1041,6 +1040,9 @@ int bch_cached_dev_attach(struct cached_
 	 */
 	atomic_set(&dc->count, 1);
 
+	if (bch_cached_dev_writeback_start(dc))
+		return -ENOMEM;
+
 	if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
 		bch_sectors_dirty_init(dc);
 		atomic_set(&dc->has_dirty, 1);
@@ -1070,7 +1072,8 @@ static void cached_dev_free(struct closu
 	struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
 
 	cancel_delayed_work_sync(&dc->writeback_rate_update);
-	kthread_stop(dc->writeback_thread);
+	if (!IS_ERR_OR_NULL(dc->writeback_thread))
+		kthread_stop(dc->writeback_thread);
 
 	mutex_lock(&bch_register_lock);
 
@@ -1081,12 +1084,8 @@ static void cached_dev_free(struct closu
 
 	mutex_unlock(&bch_register_lock);
 
-	if (!IS_ERR_OR_NULL(dc->bdev)) {
-		if (dc->bdev->bd_disk)
-			blk_sync_queue(bdev_get_queue(dc->bdev));
-
+	if (!IS_ERR_OR_NULL(dc->bdev))
 		blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-	}
 
 	wake_up(&unregister_wait);
 
@@ -1213,7 +1212,9 @@ void bch_flash_dev_release(struct kobjec
 static void flash_dev_free(struct closure *cl)
 {
 	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+	mutex_lock(&bch_register_lock);
 	bcache_device_free(d);
+	mutex_unlock(&bch_register_lock);
 	kobject_put(&d->kobj);
 }
 
@@ -1221,7 +1222,9 @@ static void flash_dev_flush(struct closu
 {
 	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
 
+	mutex_lock(&bch_register_lock);
 	bcache_device_unlink(d);
+	mutex_unlock(&bch_register_lock);
 	kobject_del(&d->kobj);
 	continue_at(cl, flash_dev_free, system_wq);
 }
@@ -1277,6 +1280,9 @@ int bch_flash_dev_create(struct cache_se
 	if (test_bit(CACHE_SET_STOPPING, &c->flags))
 		return -EINTR;
 
+	if (!test_bit(CACHE_SET_RUNNING, &c->flags))
+		return -EPERM;
+
 	u = uuid_find_empty(c);
 	if (!u) {
 		pr_err("Can't create volume, no room for UUID");
@@ -1346,8 +1352,11 @@ static void cache_set_free(struct closur
 	bch_journal_free(c);
 
 	for_each_cache(ca, c, i)
-		if (ca)
+		if (ca) {
+			ca->set = NULL;
+			c->cache[ca->sb.nr_this_dev] = NULL;
 			kobject_put(&ca->kobj);
+		}
 
 	bch_bset_sort_state_free(&c->sort);
 	free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
@@ -1405,9 +1414,11 @@ static void cache_set_flush(struct closu
 		if (ca->alloc_thread)
 			kthread_stop(ca->alloc_thread);
 
-	cancel_delayed_work_sync(&c->journal.work);
-	/* flush last journal entry if needed */
-	c->journal.work.work.func(&c->journal.work.work);
+	if (c->journal.cur) {
+		cancel_delayed_work_sync(&c->journal.work);
+		/* flush last journal entry if needed */
+		c->journal.work.work.func(&c->journal.work.work);
+	}
 
 	closure_return(cl);
 }
@@ -1586,7 +1597,7 @@ static void run_cache_set(struct cache_s
 			goto err;
 
 		err = "error reading btree root";
-		c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true);
+		c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL);
 		if (IS_ERR_OR_NULL(c->root))
 			goto err;
 
@@ -1661,7 +1672,7 @@ static void run_cache_set(struct cache_s
 			goto err;
 
 		err = "cannot allocate new btree root";
-		c->root = bch_btree_node_alloc(c, NULL, 0);
+		c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
 		if (IS_ERR_OR_NULL(c->root))
 			goto err;
 
@@ -1697,6 +1708,7 @@ static void run_cache_set(struct cache_s
 
 	flash_devs_run(c);
 
+	set_bit(CACHE_SET_RUNNING, &c->flags);
 	return;
 err:
 	closure_sync(&cl);
@@ -1760,6 +1772,7 @@ found:
 		pr_debug("set version = %llu", c->sb.version);
 	}
 
+	kobject_get(&ca->kobj);
 	ca->set = c;
 	ca->set->cache[ca->sb.nr_this_dev] = ca;
 	c->cache_by_alloc[c->caches_loaded++] = ca;
@@ -1780,8 +1793,10 @@ void bch_cache_release(struct kobject *k
 	struct cache *ca = container_of(kobj, struct cache, kobj);
 	unsigned i;
 
-	if (ca->set)
+	if (ca->set) {
+		BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
 		ca->set->cache[ca->sb.nr_this_dev] = NULL;
+	}
 
 	bio_split_pool_free(&ca->bio_split_hook);
 
@@ -1798,10 +1813,8 @@ void bch_cache_release(struct kobject *k
 	if (ca->sb_bio.bi_inline_vecs[0].bv_page)
 		put_page(ca->sb_bio.bi_io_vec[0].bv_page);
 
-	if (!IS_ERR_OR_NULL(ca->bdev)) {
-		blk_sync_queue(bdev_get_queue(ca->bdev));
+	if (!IS_ERR_OR_NULL(ca->bdev))
 		blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-	}
 
 	kfree(ca);
 	module_put(THIS_MODULE);
@@ -1844,7 +1857,7 @@ static int cache_alloc(struct cache_sb *
 }
 
 static void register_cache(struct cache_sb *sb, struct page *sb_page,
-				  struct block_device *bdev, struct cache *ca)
+				struct block_device *bdev, struct cache *ca)
 {
 	char name[BDEVNAME_SIZE];
 	const char *err = "cannot allocate memory";
@@ -1877,10 +1890,12 @@ static void register_cache(struct cache_
 		goto err;
 
 	pr_info("registered cache device %s", bdevname(bdev, name));
+out:
+	kobject_put(&ca->kobj);
 	return;
 err:
 	pr_notice("error opening %s: %s", bdevname(bdev, name), err);
-	kobject_put(&ca->kobj);
+	goto out;
 }
 
 /* Global interfaces/init */
@@ -1945,10 +1960,12 @@ static ssize_t register_bcache(struct ko
 	if (IS_ERR(bdev)) {
 		if (bdev == ERR_PTR(-EBUSY)) {
 			bdev = lookup_bdev(strim(path));
+			mutex_lock(&bch_register_lock);
 			if (!IS_ERR(bdev) && bch_is_open(bdev))
 				err = "device already registered";
 			else
 				err = "device busy";
+			mutex_unlock(&bch_register_lock);
 		}
 		goto err;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/util.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/util.h
--- linux-libre-3.16-gnu/drivers/md/bcache/util.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/util.h	2014-09-28 17:29:07.000000000 -0400
@@ -416,8 +416,8 @@ do {									\
 			  average_frequency,	frequency_units);	\
 	__print_time_stat(stats, name,					\
 			  average_duration,	duration_units);	\
-	__print_time_stat(stats, name,					\
-			  max_duration,		duration_units);	\
+	sysfs_print(name ## _ ##max_duration ## _ ## duration_units,	\
+			div_u64((stats)->max_duration, NSEC_PER_ ## duration_units));\
 									\
 	sysfs_print(name ## _last_ ## frequency_units, (stats)->last	\
 		    ? div_s64(local_clock() - (stats)->last,		\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/writeback.c linux-libre-3.17-rc7-gnu/drivers/md/bcache/writeback.c
--- linux-libre-3.16-gnu/drivers/md/bcache/writeback.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/writeback.c	2014-09-28 17:29:07.000000000 -0400
@@ -239,7 +239,7 @@ static void read_dirty(struct cached_dev
 		if (KEY_START(&w->key) != dc->last_read ||
 		    jiffies_to_msecs(delay) > 50)
 			while (!kthread_should_stop() && delay)
-				delay = schedule_timeout_uninterruptible(delay);
+				delay = schedule_timeout_interruptible(delay);
 
 		dc->last_read	= KEY_OFFSET(&w->key);
 
@@ -436,7 +436,7 @@ static int bch_writeback_thread(void *ar
 			while (delay &&
 			       !kthread_should_stop() &&
 			       !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
-				delay = schedule_timeout_uninterruptible(delay);
+				delay = schedule_timeout_interruptible(delay);
 		}
 	}
 
@@ -478,7 +478,7 @@ void bch_sectors_dirty_init(struct cache
 	dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
 }
 
-int bch_cached_dev_writeback_init(struct cached_dev *dc)
+void bch_cached_dev_writeback_init(struct cached_dev *dc)
 {
 	sema_init(&dc->in_flight, 64);
 	init_rwsem(&dc->writeback_lock);
@@ -494,14 +494,20 @@ int bch_cached_dev_writeback_init(struct
 	dc->writeback_rate_d_term	= 30;
 	dc->writeback_rate_p_term_inverse = 6000;
 
+	INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
+}
+
+int bch_cached_dev_writeback_start(struct cached_dev *dc)
+{
 	dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
 					      "bcache_writeback");
 	if (IS_ERR(dc->writeback_thread))
 		return PTR_ERR(dc->writeback_thread);
 
-	INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
 	schedule_delayed_work(&dc->writeback_rate_update,
 			      dc->writeback_rate_update_seconds * HZ);
 
+	bch_writeback_queue(dc);
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/bcache/writeback.h linux-libre-3.17-rc7-gnu/drivers/md/bcache/writeback.h
--- linux-libre-3.16-gnu/drivers/md/bcache/writeback.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/bcache/writeback.h	2014-09-28 17:29:07.000000000 -0400
@@ -85,6 +85,7 @@ static inline void bch_writeback_add(str
 void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
 
 void bch_sectors_dirty_init(struct cached_dev *dc);
-int bch_cached_dev_writeback_init(struct cached_dev *);
+void bch_cached_dev_writeback_init(struct cached_dev *);
+int bch_cached_dev_writeback_start(struct cached_dev *);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-bufio.c linux-libre-3.17-rc7-gnu/drivers/md/dm-bufio.c
--- linux-libre-3.16-gnu/drivers/md/dm-bufio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-bufio.c	2014-09-28 17:29:07.000000000 -0400
@@ -615,16 +615,6 @@ static void write_endio(struct bio *bio,
 }
 
 /*
- * This function is called when wait_on_bit is actually waiting.
- */
-static int do_io_schedule(void *word)
-{
-	io_schedule();
-
-	return 0;
-}
-
-/*
  * Initiate a write on a dirty buffer, but don't wait for it.
  *
  * - If the buffer is not dirty, exit.
@@ -640,8 +630,7 @@ static void __write_dirty_buffer(struct
 		return;
 
 	clear_bit(B_DIRTY, &b->state);
-	wait_on_bit_lock(&b->state, B_WRITING,
-			 do_io_schedule, TASK_UNINTERRUPTIBLE);
+	wait_on_bit_lock_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);
 
 	if (!write_list)
 		submit_io(b, WRITE, b->block, write_endio);
@@ -675,9 +664,9 @@ static void __make_buffer_clean(struct d
 	if (!b->state)	/* fast case */
 		return;
 
-	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
 	__write_dirty_buffer(b, NULL);
-	wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	wait_on_bit_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);
 }
 
 /*
@@ -1030,7 +1019,7 @@ static void *new_read(struct dm_bufio_cl
 	if (need_submit)
 		submit_io(b, READ, b->block, read_endio);
 
-	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
 
 	if (b->read_error) {
 		int error = b->read_error;
@@ -1209,15 +1198,13 @@ again:
 				dropped_lock = 1;
 				b->hold_count++;
 				dm_bufio_unlock(c);
-				wait_on_bit(&b->state, B_WRITING,
-					    do_io_schedule,
-					    TASK_UNINTERRUPTIBLE);
+				wait_on_bit_io(&b->state, B_WRITING,
+					       TASK_UNINTERRUPTIBLE);
 				dm_bufio_lock(c);
 				b->hold_count--;
 			} else
-				wait_on_bit(&b->state, B_WRITING,
-					    do_io_schedule,
-					    TASK_UNINTERRUPTIBLE);
+				wait_on_bit_io(&b->state, B_WRITING,
+					       TASK_UNINTERRUPTIBLE);
 		}
 
 		if (!test_bit(B_DIRTY, &b->state) &&
@@ -1321,15 +1308,15 @@ retry:
 
 	__write_dirty_buffer(b, NULL);
 	if (b->hold_count == 1) {
-		wait_on_bit(&b->state, B_WRITING,
-			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		wait_on_bit_io(&b->state, B_WRITING,
+			       TASK_UNINTERRUPTIBLE);
 		set_bit(B_DIRTY, &b->state);
 		__unlink_buffer(b);
 		__link_buffer(b, new_block, LIST_DIRTY);
 	} else {
 		sector_t old_block;
-		wait_on_bit_lock(&b->state, B_WRITING,
-				 do_io_schedule, TASK_UNINTERRUPTIBLE);
+		wait_on_bit_lock_io(&b->state, B_WRITING,
+				    TASK_UNINTERRUPTIBLE);
 		/*
 		 * Relink buffer to "new_block" so that write_callback
 		 * sees "new_block" as a block number.
@@ -1341,8 +1328,8 @@ retry:
 		__unlink_buffer(b);
 		__link_buffer(b, new_block, b->list_mode);
 		submit_io(b, WRITE, new_block, write_endio);
-		wait_on_bit(&b->state, B_WRITING,
-			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		wait_on_bit_io(&b->state, B_WRITING,
+			       TASK_UNINTERRUPTIBLE);
 		__unlink_buffer(b);
 		__link_buffer(b, old_block, b->list_mode);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-cache-metadata.c linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-metadata.c
--- linux-libre-3.16-gnu/drivers/md/dm-cache-metadata.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-metadata.c	2014-09-28 17:29:07.000000000 -0400
@@ -330,7 +330,7 @@ static int __write_initial_superblock(st
 	disk_super->discard_root = cpu_to_le64(cmd->discard_root);
 	disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size);
 	disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks));
-	disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE);
 	disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
 	disk_super->cache_blocks = cpu_to_le32(0);
 
@@ -478,7 +478,7 @@ static int __create_persistent_data_obje
 					    bool may_format_device)
 {
 	int r;
-	cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE,
+	cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
 					  CACHE_METADATA_CACHE_SIZE,
 					  CACHE_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(cmd->bm)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-cache-metadata.h linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-metadata.h
--- linux-libre-3.16-gnu/drivers/md/dm-cache-metadata.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-metadata.h	2014-09-28 17:29:07.000000000 -0400
@@ -9,19 +9,17 @@
 
 #include "dm-cache-block-types.h"
 #include "dm-cache-policy-internal.h"
+#include "persistent-data/dm-space-map-metadata.h"
 
 /*----------------------------------------------------------------*/
 
-#define DM_CACHE_METADATA_BLOCK_SIZE 4096
+#define DM_CACHE_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
 
 /* FIXME: remove this restriction */
 /*
  * The metadata device is currently limited in size.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
  */
-#define DM_CACHE_METADATA_MAX_SECTORS (255 * (1 << 14) * (DM_CACHE_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+#define DM_CACHE_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
 
 /*
  * A metadata device larger than 16GB triggers a warning.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-cache-target.c linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-target.c
--- linux-libre-3.16-gnu/drivers/md/dm-cache-target.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-cache-target.c	2014-09-28 17:29:07.000000000 -0400
@@ -718,6 +718,22 @@ static int bio_triggers_commit(struct ca
 	return bio->bi_rw & (REQ_FLUSH | REQ_FUA);
 }
 
+/*
+ * You must increment the deferred set whilst the prison cell is held.  To
+ * encourage this, we ask for 'cell' to be passed in.
+ */
+static void inc_ds(struct cache *cache, struct bio *bio,
+		   struct dm_bio_prison_cell *cell)
+{
+	size_t pb_data_size = get_per_bio_data_size(cache);
+	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
+
+	BUG_ON(!cell);
+	BUG_ON(pb->all_io_entry);
+
+	pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
+}
+
 static void issue(struct cache *cache, struct bio *bio)
 {
 	unsigned long flags;
@@ -737,6 +753,12 @@ static void issue(struct cache *cache, s
 	spin_unlock_irqrestore(&cache->lock, flags);
 }
 
+static void inc_and_issue(struct cache *cache, struct bio *bio, struct dm_bio_prison_cell *cell)
+{
+	inc_ds(cache, bio, cell);
+	issue(cache, bio);
+}
+
 static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
 {
 	unsigned long flags;
@@ -873,8 +895,8 @@ static void migration_success_pre_commit
 	struct cache *cache = mg->cache;
 
 	if (mg->writeback) {
-		cell_defer(cache, mg->old_ocell, false);
 		clear_dirty(cache, mg->old_oblock, mg->cblock);
+		cell_defer(cache, mg->old_ocell, false);
 		cleanup_migration(mg);
 		return;
 
@@ -929,13 +951,13 @@ static void migration_success_post_commi
 		}
 
 	} else {
+		clear_dirty(cache, mg->new_oblock, mg->cblock);
 		if (mg->requeue_holder)
 			cell_defer(cache, mg->new_ocell, true);
 		else {
 			bio_endio(mg->new_ocell->holder, 0);
 			cell_defer(cache, mg->new_ocell, false);
 		}
-		clear_dirty(cache, mg->new_oblock, mg->cblock);
 		cleanup_migration(mg);
 	}
 }
@@ -1015,6 +1037,11 @@ static void issue_overwrite(struct dm_ca
 
 	dm_hook_bio(&pb->hook_info, bio, overwrite_endio, mg);
 	remap_to_cache_dirty(mg->cache, bio, mg->new_oblock, mg->cblock);
+
+	/*
+	 * No need to inc_ds() here, since the cell will be held for the
+	 * duration of the io.
+	 */
 	generic_make_request(bio);
 }
 
@@ -1115,8 +1142,7 @@ static void check_for_quiesced_migration
 		return;
 
 	INIT_LIST_HEAD(&work);
-	if (pb->all_io_entry)
-		dm_deferred_entry_dec(pb->all_io_entry, &work);
+	dm_deferred_entry_dec(pb->all_io_entry, &work);
 
 	if (!list_empty(&work))
 		queue_quiesced_migrations(cache, &work);
@@ -1252,6 +1278,11 @@ static void process_flush_bio(struct cac
 	else
 		remap_to_cache(cache, bio, 0);
 
+	/*
+	 * REQ_FLUSH is not directed at any particular block so we don't
+	 * need to inc_ds().  REQ_FUA's are split into a write + REQ_FLUSH
+	 * by dm-core.
+	 */
 	issue(cache, bio);
 }
 
@@ -1301,15 +1332,6 @@ static void inc_miss_counter(struct cach
 		   &cache->stats.read_miss : &cache->stats.write_miss);
 }
 
-static void issue_cache_bio(struct cache *cache, struct bio *bio,
-			    struct per_bio_data *pb,
-			    dm_oblock_t oblock, dm_cblock_t cblock)
-{
-	pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-	remap_to_cache_dirty(cache, bio, oblock, cblock);
-	issue(cache, bio);
-}
-
 static void process_bio(struct cache *cache, struct prealloc *structs,
 			struct bio *bio)
 {
@@ -1318,8 +1340,6 @@ static void process_bio(struct cache *ca
 	dm_oblock_t block = get_bio_block(cache, bio);
 	struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
 	struct policy_result lookup_result;
-	size_t pb_data_size = get_per_bio_data_size(cache);
-	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 	bool discarded_block = is_discarded_oblock(cache, block);
 	bool passthrough = passthrough_mode(&cache->features);
 	bool can_migrate = !passthrough && (discarded_block || spare_migration_bandwidth(cache));
@@ -1359,9 +1379,8 @@ static void process_bio(struct cache *ca
 
 			} else {
 				/* FIXME: factor out issue_origin() */
-				pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 				remap_to_origin_clear_discard(cache, bio, block);
-				issue(cache, bio);
+				inc_and_issue(cache, bio, new_ocell);
 			}
 		} else {
 			inc_hit_counter(cache, bio);
@@ -1369,20 +1388,21 @@ static void process_bio(struct cache *ca
 			if (bio_data_dir(bio) == WRITE &&
 			    writethrough_mode(&cache->features) &&
 			    !is_dirty(cache, lookup_result.cblock)) {
-				pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 				remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
-				issue(cache, bio);
-			} else
-				issue_cache_bio(cache, bio, pb, block, lookup_result.cblock);
+				inc_and_issue(cache, bio, new_ocell);
+
+			} else  {
+				remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
+				inc_and_issue(cache, bio, new_ocell);
+			}
 		}
 
 		break;
 
 	case POLICY_MISS:
 		inc_miss_counter(cache, bio);
-		pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 		remap_to_origin_clear_discard(cache, bio, block);
-		issue(cache, bio);
+		inc_and_issue(cache, bio, new_ocell);
 		break;
 
 	case POLICY_NEW:
@@ -1501,6 +1521,9 @@ static void process_deferred_flush_bios(
 	bio_list_init(&cache->deferred_flush_bios);
 	spin_unlock_irqrestore(&cache->lock, flags);
 
+	/*
+	 * These bios have already been through inc_ds()
+	 */
 	while ((bio = bio_list_pop(&bios)))
 		submit_bios ? generic_make_request(bio) : bio_io_error(bio);
 }
@@ -1518,6 +1541,9 @@ static void process_deferred_writethroug
 	bio_list_init(&cache->deferred_writethrough_bios);
 	spin_unlock_irqrestore(&cache->lock, flags);
 
+	/*
+	 * These bios have already been through inc_ds()
+	 */
 	while ((bio = bio_list_pop(&bios)))
 		generic_make_request(bio);
 }
@@ -1694,6 +1720,7 @@ static void do_worker(struct work_struct
 
 		if (commit_if_needed(cache)) {
 			process_deferred_flush_bios(cache, false);
+			process_migrations(cache, &cache->need_commit_migrations, migration_failure);
 
 			/*
 			 * FIXME: rollback metadata or just go into a
@@ -2406,16 +2433,13 @@ out:
 	return r;
 }
 
-static int cache_map(struct dm_target *ti, struct bio *bio)
+static int __cache_map(struct cache *cache, struct bio *bio, struct dm_bio_prison_cell **cell)
 {
-	struct cache *cache = ti->private;
-
 	int r;
 	dm_oblock_t block = get_bio_block(cache, bio);
 	size_t pb_data_size = get_per_bio_data_size(cache);
 	bool can_migrate = false;
 	bool discarded_block;
-	struct dm_bio_prison_cell *cell;
 	struct policy_result lookup_result;
 	struct per_bio_data *pb = init_per_bio_data(bio, pb_data_size);
 
@@ -2437,15 +2461,15 @@ static int cache_map(struct dm_target *t
 	/*
 	 * Check to see if that block is currently migrating.
 	 */
-	cell = alloc_prison_cell(cache);
-	if (!cell) {
+	*cell = alloc_prison_cell(cache);
+	if (!*cell) {
 		defer_bio(cache, bio);
 		return DM_MAPIO_SUBMITTED;
 	}
 
-	r = bio_detain(cache, block, bio, cell,
+	r = bio_detain(cache, block, bio, *cell,
 		       (cell_free_fn) free_prison_cell,
-		       cache, &cell);
+		       cache, cell);
 	if (r) {
 		if (r < 0)
 			defer_bio(cache, bio);
@@ -2458,11 +2482,12 @@ static int cache_map(struct dm_target *t
 	r = policy_map(cache->policy, block, false, can_migrate, discarded_block,
 		       bio, &lookup_result);
 	if (r == -EWOULDBLOCK) {
-		cell_defer(cache, cell, true);
+		cell_defer(cache, *cell, true);
 		return DM_MAPIO_SUBMITTED;
 
 	} else if (r) {
 		DMERR_LIMIT("Unexpected return from cache replacement policy: %d", r);
+		cell_defer(cache, *cell, false);
 		bio_io_error(bio);
 		return DM_MAPIO_SUBMITTED;
 	}
@@ -2476,52 +2501,44 @@ static int cache_map(struct dm_target *t
 				 * We need to invalidate this block, so
 				 * defer for the worker thread.
 				 */
-				cell_defer(cache, cell, true);
+				cell_defer(cache, *cell, true);
 				r = DM_MAPIO_SUBMITTED;
 
 			} else {
-				pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 				inc_miss_counter(cache, bio);
 				remap_to_origin_clear_discard(cache, bio, block);
-
-				cell_defer(cache, cell, false);
 			}
 
 		} else {
 			inc_hit_counter(cache, bio);
-			pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-
 			if (bio_data_dir(bio) == WRITE && writethrough_mode(&cache->features) &&
 			    !is_dirty(cache, lookup_result.cblock))
 				remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
 			else
 				remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
-
-			cell_defer(cache, cell, false);
 		}
 		break;
 
 	case POLICY_MISS:
 		inc_miss_counter(cache, bio);
-		pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-
 		if (pb->req_nr != 0) {
 			/*
 			 * This is a duplicate writethrough io that is no
 			 * longer needed because the block has been demoted.
 			 */
 			bio_endio(bio, 0);
-			cell_defer(cache, cell, false);
-			return DM_MAPIO_SUBMITTED;
-		} else {
+			cell_defer(cache, *cell, false);
+			r = DM_MAPIO_SUBMITTED;
+
+		} else
 			remap_to_origin_clear_discard(cache, bio, block);
-			cell_defer(cache, cell, false);
-		}
+
 		break;
 
 	default:
 		DMERR_LIMIT("%s: erroring bio: unknown policy op: %u", __func__,
 			    (unsigned) lookup_result.op);
+		cell_defer(cache, *cell, false);
 		bio_io_error(bio);
 		r = DM_MAPIO_SUBMITTED;
 	}
@@ -2529,6 +2546,21 @@ static int cache_map(struct dm_target *t
 	return r;
 }
 
+static int cache_map(struct dm_target *ti, struct bio *bio)
+{
+	int r;
+	struct dm_bio_prison_cell *cell;
+	struct cache *cache = ti->private;
+
+	r = __cache_map(cache, bio, &cell);
+	if (r == DM_MAPIO_REMAPPED) {
+		inc_ds(cache, bio, cell);
+		cell_defer(cache, cell, false);
+	}
+
+	return r;
+}
+
 static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
 	struct cache *cache = ti->private;
@@ -2808,7 +2840,7 @@ static void cache_status(struct dm_targe
 		residency = policy_residency(cache->policy);
 
 		DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ",
-		       (unsigned)(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
+		       (unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
 		       (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
 		       (unsigned long long)nr_blocks_metadata,
 		       cache->sectors_per_block,
@@ -3062,7 +3094,7 @@ static void cache_io_hints(struct dm_tar
 	 */
 	if (io_opt_sectors < cache->sectors_per_block ||
 	    do_div(io_opt_sectors, cache->sectors_per_block)) {
-		blk_limits_io_min(limits, 0);
+		blk_limits_io_min(limits, cache->sectors_per_block << SECTOR_SHIFT);
 		blk_limits_io_opt(limits, cache->sectors_per_block << SECTOR_SHIFT);
 	}
 	set_discard_limits(cache, limits);
@@ -3072,7 +3104,7 @@ static void cache_io_hints(struct dm_tar
 
 static struct target_type cache_target = {
 	.name = "cache",
-	.version = {1, 4, 0},
+	.version = {1, 5, 0},
 	.module = THIS_MODULE,
 	.ctr = cache_ctr,
 	.dtr = cache_dtr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-crypt.c linux-libre-3.17-rc7-gnu/drivers/md/dm-crypt.c
--- linux-libre-3.16-gnu/drivers/md/dm-crypt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-crypt.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ struct dm_crypt_io {
 	int error;
 	sector_t sector;
 	struct dm_crypt_io *base_io;
-};
+} CRYPTO_MINALIGN_ATTR;
 
 struct dm_crypt_request {
 	struct convert_context *ctx;
@@ -162,6 +162,8 @@ struct crypt_config {
 	 */
 	unsigned int dmreq_start;
 
+	unsigned int per_bio_data_size;
+
 	unsigned long flags;
 	unsigned int key_size;
 	unsigned int key_parts;      /* independent parts in key buffer */
@@ -895,6 +897,15 @@ static void crypt_alloc_req(struct crypt
 	    kcryptd_async_done, dmreq_of_req(cc, ctx->req));
 }
 
+static void crypt_free_req(struct crypt_config *cc,
+			   struct ablkcipher_request *req, struct bio *base_bio)
+{
+	struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size);
+
+	if ((struct ablkcipher_request *)(io + 1) != req)
+		mempool_free(req, cc->req_pool);
+}
+
 /*
  * Encrypt / decrypt data from one bio to another one (can be the same one)
  */
@@ -1008,12 +1019,9 @@ static void crypt_free_buffer_pages(stru
 	}
 }
 
-static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc,
-					  struct bio *bio, sector_t sector)
+static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
+			  struct bio *bio, sector_t sector)
 {
-	struct dm_crypt_io *io;
-
-	io = mempool_alloc(cc->io_pool, GFP_NOIO);
 	io->cc = cc;
 	io->base_bio = bio;
 	io->sector = sector;
@@ -1021,8 +1029,6 @@ static struct dm_crypt_io *crypt_io_allo
 	io->base_io = NULL;
 	io->ctx.req = NULL;
 	atomic_set(&io->io_pending, 0);
-
-	return io;
 }
 
 static void crypt_inc_pending(struct dm_crypt_io *io)
@@ -1046,8 +1052,9 @@ static void crypt_dec_pending(struct dm_
 		return;
 
 	if (io->ctx.req)
-		mempool_free(io->ctx.req, cc->req_pool);
-	mempool_free(io, cc->io_pool);
+		crypt_free_req(cc, io->ctx.req, base_bio);
+	if (io != dm_per_bio_data(base_bio, cc->per_bio_data_size))
+		mempool_free(io, cc->io_pool);
 
 	if (likely(!base_io))
 		bio_endio(base_bio, error);
@@ -1255,8 +1262,8 @@ static void kcryptd_crypt_write_convert(
 		 * between fragments, so switch to a new dm_crypt_io structure.
 		 */
 		if (unlikely(!crypt_finished && remaining)) {
-			new_io = crypt_io_alloc(io->cc, io->base_bio,
-						sector);
+			new_io = mempool_alloc(cc->io_pool, GFP_NOIO);
+			crypt_io_init(new_io, io->cc, io->base_bio, sector);
 			crypt_inc_pending(new_io);
 			crypt_convert_init(cc, &new_io->ctx, NULL,
 					   io->base_bio, sector);
@@ -1325,7 +1332,7 @@ static void kcryptd_async_done(struct cr
 	if (error < 0)
 		io->error = -EIO;
 
-	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
+	crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
 
 	if (!atomic_dec_and_test(&ctx->cc_pending))
 		return;
@@ -1681,6 +1688,7 @@ static int crypt_ctr(struct dm_target *t
 	unsigned int key_size, opt_params;
 	unsigned long long tmpll;
 	int ret;
+	size_t iv_size_padding;
 	struct dm_arg_set as;
 	const char *opt_string;
 	char dummy;
@@ -1717,17 +1725,33 @@ static int crypt_ctr(struct dm_target *t
 
 	cc->dmreq_start = sizeof(struct ablkcipher_request);
 	cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc));
-	cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
-	cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) &
-			   ~(crypto_tfm_ctx_alignment() - 1);
+	cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request));
+
+	if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) {
+		/* Allocate the padding exactly */
+		iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request))
+				& crypto_ablkcipher_alignmask(any_tfm(cc));
+	} else {
+		/*
+		 * If the cipher requires greater alignment than kmalloc
+		 * alignment, we don't know the exact position of the
+		 * initialization vector. We must assume worst case.
+		 */
+		iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc));
+	}
 
 	cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
-			sizeof(struct dm_crypt_request) + cc->iv_size);
+			sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size);
 	if (!cc->req_pool) {
 		ti->error = "Cannot allocate crypt request mempool";
 		goto bad;
 	}
 
+	cc->per_bio_data_size = ti->per_bio_data_size =
+		ALIGN(sizeof(struct dm_crypt_io) + cc->dmreq_start +
+		      sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size,
+		      ARCH_KMALLOC_MINALIGN);
+
 	cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
 	if (!cc->page_pool) {
 		ti->error = "Cannot allocate page mempool";
@@ -1824,7 +1848,9 @@ static int crypt_map(struct dm_target *t
 		return DM_MAPIO_REMAPPED;
 	}
 
-	io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+	io = dm_per_bio_data(bio, cc->per_bio_data_size);
+	crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+	io->ctx.req = (struct ablkcipher_request *)(io + 1);
 
 	if (bio_data_dir(io->base_bio) == READ) {
 		if (kcryptd_io_read(io, GFP_NOWAIT))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm.h linux-libre-3.17-rc7-gnu/drivers/md/dm.h
--- linux-libre-3.16-gnu/drivers/md/dm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm.h	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,6 @@ int dm_table_any_busy_target(struct dm_t
 unsigned dm_table_get_type(struct dm_table *t);
 struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
-bool dm_table_supports_discards(struct dm_table *t);
 void dm_table_free_md_mempools(struct dm_table *t);
 struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-io.c linux-libre-3.17-rc7-gnu/drivers/md/dm-io.c
--- linux-libre-3.16-gnu/drivers/md/dm-io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-io.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ struct dm_io_client {
 struct io {
 	unsigned long error_bits;
 	atomic_t count;
-	struct completion *wait;
 	struct dm_io_client *client;
 	io_notify_fn callback;
 	void *context;
@@ -112,28 +111,27 @@ static void retrieve_io_and_region_from_
  * We need an io object to keep track of the number of bios that
  * have been dispatched for a particular io.
  *---------------------------------------------------------------*/
-static void dec_count(struct io *io, unsigned int region, int error)
+static void complete_io(struct io *io)
 {
-	if (error)
-		set_bit(region, &io->error_bits);
+	unsigned long error_bits = io->error_bits;
+	io_notify_fn fn = io->callback;
+	void *context = io->context;
 
-	if (atomic_dec_and_test(&io->count)) {
-		if (io->vma_invalidate_size)
-			invalidate_kernel_vmap_range(io->vma_invalidate_address,
-						     io->vma_invalidate_size);
+	if (io->vma_invalidate_size)
+		invalidate_kernel_vmap_range(io->vma_invalidate_address,
+					     io->vma_invalidate_size);
 
-		if (io->wait)
-			complete(io->wait);
+	mempool_free(io, io->client->pool);
+	fn(error_bits, context);
+}
 
-		else {
-			unsigned long r = io->error_bits;
-			io_notify_fn fn = io->callback;
-			void *context = io->context;
+static void dec_count(struct io *io, unsigned int region, int error)
+{
+	if (error)
+		set_bit(region, &io->error_bits);
 
-			mempool_free(io, io->client->pool);
-			fn(r, context);
-		}
-	}
+	if (atomic_dec_and_test(&io->count))
+		complete_io(io);
 }
 
 static void endio(struct bio *bio, int error)
@@ -376,41 +374,51 @@ static void dispatch_io(int rw, unsigned
 	dec_count(io, 0, 0);
 }
 
+struct sync_io {
+	unsigned long error_bits;
+	struct completion wait;
+};
+
+static void sync_io_complete(unsigned long error, void *context)
+{
+	struct sync_io *sio = context;
+
+	sio->error_bits = error;
+	complete(&sio->wait);
+}
+
 static int sync_io(struct dm_io_client *client, unsigned int num_regions,
 		   struct dm_io_region *where, int rw, struct dpages *dp,
 		   unsigned long *error_bits)
 {
-	/*
-	 * gcc <= 4.3 can't do the alignment for stack variables, so we must
-	 * align it on our own.
-	 * volatile prevents the optimizer from removing or reusing
-	 * "io_" field from the stack frame (allowed in ANSI C).
-	 */
-	volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1];
-	struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io));
-	DECLARE_COMPLETION_ONSTACK(wait);
+	struct io *io;
+	struct sync_io sio;
 
 	if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
 		WARN_ON(1);
 		return -EIO;
 	}
 
+	init_completion(&sio.wait);
+
+	io = mempool_alloc(client->pool, GFP_NOIO);
 	io->error_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
-	io->wait = &wait;
 	io->client = client;
+	io->callback = sync_io_complete;
+	io->context = &sio;
 
 	io->vma_invalidate_address = dp->vma_invalidate_address;
 	io->vma_invalidate_size = dp->vma_invalidate_size;
 
 	dispatch_io(rw, num_regions, where, dp, io, 1);
 
-	wait_for_completion_io(&wait);
+	wait_for_completion_io(&sio.wait);
 
 	if (error_bits)
-		*error_bits = io->error_bits;
+		*error_bits = sio.error_bits;
 
-	return io->error_bits ? -EIO : 0;
+	return sio.error_bits ? -EIO : 0;
 }
 
 static int async_io(struct dm_io_client *client, unsigned int num_regions,
@@ -428,7 +436,6 @@ static int async_io(struct dm_io_client
 	io = mempool_alloc(client->pool, GFP_NOIO);
 	io->error_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
-	io->wait = NULL;
 	io->client = client;
 	io->callback = fn;
 	io->context = context;
@@ -481,9 +488,9 @@ static int dp_init(struct dm_io_request
  * New collapsed (a)synchronous interface.
  *
  * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
- * the queue with blk_unplug() some time later or set REQ_SYNC in
-io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
- * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
+ * the queue with blk_unplug() some time later or set REQ_SYNC in io_req->bi_rw.
+ * If you fail to do one of these, the IO will be submitted to the disk after
+ * q->unplug_delay, which defaults to 3ms in blk-settings.c.
  */
 int dm_io(struct dm_io_request *io_req, unsigned num_regions,
 	  struct dm_io_region *where, unsigned long *sync_error_bits)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-mpath.c linux-libre-3.17-rc7-gnu/drivers/md/dm-mpath.c
--- linux-libre-3.16-gnu/drivers/md/dm-mpath.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-mpath.c	2014-09-28 17:29:07.000000000 -0400
@@ -373,8 +373,6 @@ static int __must_push_back(struct multi
 		 dm_noflush_suspending(m->ti)));
 }
 
-#define pg_ready(m) (!(m)->queue_io && !(m)->pg_init_required)
-
 /*
  * Map cloned requests
  */
@@ -402,11 +400,11 @@ static int multipath_map(struct dm_targe
 		if (!__must_push_back(m))
 			r = -EIO;	/* Failed */
 		goto out_unlock;
-	}
-	if (!pg_ready(m)) {
+	} else if (m->queue_io || m->pg_init_required) {
 		__pg_init_all_paths(m);
 		goto out_unlock;
 	}
+
 	if (set_mapinfo(m, map_context) < 0)
 		/* ENOMEM, requeue */
 		goto out_unlock;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-snap.c linux-libre-3.17-rc7-gnu/drivers/md/dm-snap.c
--- linux-libre-3.16-gnu/drivers/md/dm-snap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-snap.c	2014-09-28 17:29:07.000000000 -0400
@@ -1032,21 +1032,13 @@ static void start_merge(struct dm_snapsh
 		snapshot_merge_next_chunks(s);
 }
 
-static int wait_schedule(void *ptr)
-{
-	schedule();
-
-	return 0;
-}
-
 /*
  * Stop the merging process and wait until it finishes.
  */
 static void stop_merge(struct dm_snapshot *s)
 {
 	set_bit(SHUTDOWN_MERGE, &s->state_bits);
-	wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
-		    TASK_UNINTERRUPTIBLE);
+	wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE);
 	clear_bit(SHUTDOWN_MERGE, &s->state_bits);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-switch.c linux-libre-3.17-rc7-gnu/drivers/md/dm-switch.c
--- linux-libre-3.16-gnu/drivers/md/dm-switch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-switch.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,13 +137,23 @@ static void switch_get_position(struct s
 	*bit *= sctx->region_table_entry_bits;
 }
 
+static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
+{
+	unsigned long region_index;
+	unsigned bit;
+
+	switch_get_position(sctx, region_nr, &region_index, &bit);
+
+	return (ACCESS_ONCE(sctx->region_table[region_index]) >> bit) &
+		((1 << sctx->region_table_entry_bits) - 1);
+}
+
 /*
  * Find which path to use at given offset.
  */
 static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
 {
-	unsigned long region_index;
-	unsigned bit, path_nr;
+	unsigned path_nr;
 	sector_t p;
 
 	p = offset;
@@ -152,9 +162,7 @@ static unsigned switch_get_path_nr(struc
 	else
 		sector_div(p, sctx->region_size);
 
-	switch_get_position(sctx, p, &region_index, &bit);
-	path_nr = (ACCESS_ONCE(sctx->region_table[region_index]) >> bit) &
-	       ((1 << sctx->region_table_entry_bits) - 1);
+	path_nr = switch_region_table_read(sctx, p);
 
 	/* This can only happen if the processor uses non-atomic stores. */
 	if (unlikely(path_nr >= sctx->nr_paths))
@@ -363,7 +371,7 @@ static __always_inline unsigned long par
 }
 
 static int process_set_region_mappings(struct switch_ctx *sctx,
-			     unsigned argc, char **argv)
+				       unsigned argc, char **argv)
 {
 	unsigned i;
 	unsigned long region_index = 0;
@@ -372,6 +380,51 @@ static int process_set_region_mappings(s
 		unsigned long path_nr;
 		const char *string = argv[i];
 
+		if ((*string & 0xdf) == 'R') {
+			unsigned long cycle_length, num_write;
+
+			string++;
+			if (unlikely(*string == ',')) {
+				DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+				return -EINVAL;
+			}
+			cycle_length = parse_hex(&string);
+			if (unlikely(*string != ',')) {
+				DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+				return -EINVAL;
+			}
+			string++;
+			if (unlikely(!*string)) {
+				DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+				return -EINVAL;
+			}
+			num_write = parse_hex(&string);
+			if (unlikely(*string)) {
+				DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+				return -EINVAL;
+			}
+
+			if (unlikely(!cycle_length) || unlikely(cycle_length - 1 > region_index)) {
+				DMWARN("invalid set_region_mappings cycle length: %lu > %lu",
+				       cycle_length - 1, region_index);
+				return -EINVAL;
+			}
+			if (unlikely(region_index + num_write < region_index) ||
+			    unlikely(region_index + num_write >= sctx->nr_regions)) {
+				DMWARN("invalid set_region_mappings region number: %lu + %lu >= %lu",
+				       region_index, num_write, sctx->nr_regions);
+				return -EINVAL;
+			}
+
+			while (num_write--) {
+				region_index++;
+				path_nr = switch_region_table_read(sctx, region_index - cycle_length);
+				switch_region_table_write(sctx, region_index, path_nr);
+			}
+
+			continue;
+		}
+
 		if (*string == ':')
 			region_index++;
 		else {
@@ -500,7 +553,7 @@ static int switch_iterate_devices(struct
 
 static struct target_type switch_target = {
 	.name = "switch",
-	.version = {1, 0, 0},
+	.version = {1, 1, 0},
 	.module = THIS_MODULE,
 	.ctr = switch_ctr,
 	.dtr = switch_dtr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-table.c linux-libre-3.17-rc7-gnu/drivers/md/dm-table.c
--- linux-libre-3.16-gnu/drivers/md/dm-table.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-table.c	2014-09-28 17:29:07.000000000 -0400
@@ -1386,6 +1386,14 @@ static int device_is_not_random(struct d
 	return q && !blk_queue_add_random(q);
 }
 
+static int queue_supports_sg_merge(struct dm_target *ti, struct dm_dev *dev,
+				   sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && !test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags);
+}
+
 static bool dm_table_all_devices_attribute(struct dm_table *t,
 					   iterate_devices_callout_fn func)
 {
@@ -1430,6 +1438,43 @@ static bool dm_table_supports_write_same
 	return true;
 }
 
+static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
+				  sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && blk_queue_discard(q);
+}
+
+static bool dm_table_supports_discards(struct dm_table *t)
+{
+	struct dm_target *ti;
+	unsigned i = 0;
+
+	/*
+	 * Unless any target used by the table set discards_supported,
+	 * require at least one underlying device to support discards.
+	 * t->devices includes internal dm devices such as mirror logs
+	 * so we need to use iterate_devices here, which targets
+	 * supporting discard selectively must provide.
+	 */
+	while (i < dm_table_get_num_targets(t)) {
+		ti = dm_table_get_target(t, i++);
+
+		if (!ti->num_discard_bios)
+			continue;
+
+		if (ti->discards_supported)
+			return 1;
+
+		if (ti->type->iterate_devices &&
+		    ti->type->iterate_devices(ti, device_discard_capable, NULL))
+			return 1;
+	}
+
+	return 0;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 			       struct queue_limits *limits)
 {
@@ -1464,6 +1509,11 @@ void dm_table_set_restrictions(struct dm
 	if (!dm_table_supports_write_same(t))
 		q->limits.max_write_same_sectors = 0;
 
+	if (dm_table_all_devices_attribute(t, queue_supports_sg_merge))
+		queue_flag_clear_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
+	else
+		queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
+
 	dm_table_set_integrity(t);
 
 	/*
@@ -1636,39 +1686,3 @@ void dm_table_run_md_queue_async(struct
 }
 EXPORT_SYMBOL(dm_table_run_md_queue_async);
 
-static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
-				  sector_t start, sector_t len, void *data)
-{
-	struct request_queue *q = bdev_get_queue(dev->bdev);
-
-	return q && blk_queue_discard(q);
-}
-
-bool dm_table_supports_discards(struct dm_table *t)
-{
-	struct dm_target *ti;
-	unsigned i = 0;
-
-	/*
-	 * Unless any target used by the table set discards_supported,
-	 * require at least one underlying device to support discards.
-	 * t->devices includes internal dm devices such as mirror logs
-	 * so we need to use iterate_devices here, which targets
-	 * supporting discard selectively must provide.
-	 */
-	while (i < dm_table_get_num_targets(t)) {
-		ti = dm_table_get_target(t, i++);
-
-		if (!ti->num_discard_bios)
-			continue;
-
-		if (ti->discards_supported)
-			return 1;
-
-		if (ti->type->iterate_devices &&
-		    ti->type->iterate_devices(ti, device_discard_capable, NULL))
-			return 1;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/dm-thin.c linux-libre-3.17-rc7-gnu/drivers/md/dm-thin.c
--- linux-libre-3.16-gnu/drivers/md/dm-thin.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/dm-thin.c	2014-09-28 17:29:07.000000000 -0400
@@ -227,6 +227,7 @@ struct thin_c {
 	struct list_head list;
 	struct dm_dev *pool_dev;
 	struct dm_dev *origin_dev;
+	sector_t origin_size;
 	dm_thin_id dev_id;
 
 	struct pool *pool;
@@ -554,11 +555,16 @@ static void remap_and_issue(struct thin_
 struct dm_thin_new_mapping {
 	struct list_head list;
 
-	bool quiesced:1;
-	bool prepared:1;
 	bool pass_discard:1;
 	bool definitely_not_shared:1;
 
+	/*
+	 * Track quiescing, copying and zeroing preparation actions.  When this
+	 * counter hits zero the block is prepared and can be inserted into the
+	 * btree.
+	 */
+	atomic_t prepare_actions;
+
 	int err;
 	struct thin_c *tc;
 	dm_block_t virt_block;
@@ -575,43 +581,41 @@ struct dm_thin_new_mapping {
 	bio_end_io_t *saved_bi_end_io;
 };
 
-static void __maybe_add_mapping(struct dm_thin_new_mapping *m)
+static void __complete_mapping_preparation(struct dm_thin_new_mapping *m)
 {
 	struct pool *pool = m->tc->pool;
 
-	if (m->quiesced && m->prepared) {
+	if (atomic_dec_and_test(&m->prepare_actions)) {
 		list_add_tail(&m->list, &pool->prepared_mappings);
 		wake_worker(pool);
 	}
 }
 
-static void copy_complete(int read_err, unsigned long write_err, void *context)
+static void complete_mapping_preparation(struct dm_thin_new_mapping *m)
 {
 	unsigned long flags;
-	struct dm_thin_new_mapping *m = context;
 	struct pool *pool = m->tc->pool;
 
-	m->err = read_err || write_err ? -EIO : 0;
-
 	spin_lock_irqsave(&pool->lock, flags);
-	m->prepared = true;
-	__maybe_add_mapping(m);
+	__complete_mapping_preparation(m);
 	spin_unlock_irqrestore(&pool->lock, flags);
 }
 
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+	struct dm_thin_new_mapping *m = context;
+
+	m->err = read_err || write_err ? -EIO : 0;
+	complete_mapping_preparation(m);
+}
+
 static void overwrite_endio(struct bio *bio, int err)
 {
-	unsigned long flags;
 	struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 	struct dm_thin_new_mapping *m = h->overwrite_mapping;
-	struct pool *pool = m->tc->pool;
 
 	m->err = err;
-
-	spin_lock_irqsave(&pool->lock, flags);
-	m->prepared = true;
-	__maybe_add_mapping(m);
-	spin_unlock_irqrestore(&pool->lock, flags);
+	complete_mapping_preparation(m);
 }
 
 /*----------------------------------------------------------------*/
@@ -821,10 +825,31 @@ static struct dm_thin_new_mapping *get_n
 	return m;
 }
 
+static void ll_zero(struct thin_c *tc, struct dm_thin_new_mapping *m,
+		    sector_t begin, sector_t end)
+{
+	int r;
+	struct dm_io_region to;
+
+	to.bdev = tc->pool_dev->bdev;
+	to.sector = begin;
+	to.count = end - begin;
+
+	r = dm_kcopyd_zero(tc->pool->copier, 1, &to, 0, copy_complete, m);
+	if (r < 0) {
+		DMERR_LIMIT("dm_kcopyd_zero() failed");
+		copy_complete(1, 1, m);
+	}
+}
+
+/*
+ * A partial copy also needs to zero the uncopied region.
+ */
 static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
 			  struct dm_dev *origin, dm_block_t data_origin,
 			  dm_block_t data_dest,
-			  struct dm_bio_prison_cell *cell, struct bio *bio)
+			  struct dm_bio_prison_cell *cell, struct bio *bio,
+			  sector_t len)
 {
 	int r;
 	struct pool *pool = tc->pool;
@@ -835,8 +860,15 @@ static void schedule_copy(struct thin_c
 	m->data_block = data_dest;
 	m->cell = cell;
 
+	/*
+	 * quiesce action + copy action + an extra reference held for the
+	 * duration of this function (we may need to inc later for a
+	 * partial zero).
+	 */
+	atomic_set(&m->prepare_actions, 3);
+
 	if (!dm_deferred_set_add_work(pool->shared_read_ds, &m->list))
-		m->quiesced = true;
+		complete_mapping_preparation(m); /* already quiesced */
 
 	/*
 	 * IO to pool_dev remaps to the pool target's data_dev.
@@ -857,20 +889,38 @@ static void schedule_copy(struct thin_c
 
 		from.bdev = origin->bdev;
 		from.sector = data_origin * pool->sectors_per_block;
-		from.count = pool->sectors_per_block;
+		from.count = len;
 
 		to.bdev = tc->pool_dev->bdev;
 		to.sector = data_dest * pool->sectors_per_block;
-		to.count = pool->sectors_per_block;
+		to.count = len;
 
 		r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
 				   0, copy_complete, m);
 		if (r < 0) {
-			mempool_free(m, pool->mapping_pool);
 			DMERR_LIMIT("dm_kcopyd_copy() failed");
-			cell_error(pool, cell);
+			copy_complete(1, 1, m);
+
+			/*
+			 * We allow the zero to be issued, to simplify the
+			 * error path.  Otherwise we'd need to start
+			 * worrying about decrementing the prepare_actions
+			 * counter.
+			 */
+		}
+
+		/*
+		 * Do we need to zero a tail region?
+		 */
+		if (len < pool->sectors_per_block && pool->pf.zero_new_blocks) {
+			atomic_inc(&m->prepare_actions);
+			ll_zero(tc, m,
+				data_dest * pool->sectors_per_block + len,
+				(data_dest + 1) * pool->sectors_per_block);
 		}
 	}
+
+	complete_mapping_preparation(m); /* drop our ref */
 }
 
 static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block,
@@ -878,15 +928,8 @@ static void schedule_internal_copy(struc
 				   struct dm_bio_prison_cell *cell, struct bio *bio)
 {
 	schedule_copy(tc, virt_block, tc->pool_dev,
-		      data_origin, data_dest, cell, bio);
-}
-
-static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
-				   dm_block_t data_dest,
-				   struct dm_bio_prison_cell *cell, struct bio *bio)
-{
-	schedule_copy(tc, virt_block, tc->origin_dev,
-		      virt_block, data_dest, cell, bio);
+		      data_origin, data_dest, cell, bio,
+		      tc->pool->sectors_per_block);
 }
 
 static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
@@ -896,8 +939,7 @@ static void schedule_zero(struct thin_c
 	struct pool *pool = tc->pool;
 	struct dm_thin_new_mapping *m = get_next_mapping(pool);
 
-	m->quiesced = true;
-	m->prepared = false;
+	atomic_set(&m->prepare_actions, 1); /* no need to quiesce */
 	m->tc = tc;
 	m->virt_block = virt_block;
 	m->data_block = data_block;
@@ -919,21 +961,33 @@ static void schedule_zero(struct thin_c
 		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
 		inc_all_io_entry(pool, bio);
 		remap_and_issue(tc, bio, data_block);
-	} else {
-		int r;
-		struct dm_io_region to;
 
-		to.bdev = tc->pool_dev->bdev;
-		to.sector = data_block * pool->sectors_per_block;
-		to.count = pool->sectors_per_block;
+	} else
+		ll_zero(tc, m,
+			data_block * pool->sectors_per_block,
+			(data_block + 1) * pool->sectors_per_block);
+}
 
-		r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
-		if (r < 0) {
-			mempool_free(m, pool->mapping_pool);
-			DMERR_LIMIT("dm_kcopyd_zero() failed");
-			cell_error(pool, cell);
-		}
-	}
+static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
+				   dm_block_t data_dest,
+				   struct dm_bio_prison_cell *cell, struct bio *bio)
+{
+	struct pool *pool = tc->pool;
+	sector_t virt_block_begin = virt_block * pool->sectors_per_block;
+	sector_t virt_block_end = (virt_block + 1) * pool->sectors_per_block;
+
+	if (virt_block_end <= tc->origin_size)
+		schedule_copy(tc, virt_block, tc->origin_dev,
+			      virt_block, data_dest, cell, bio,
+			      pool->sectors_per_block);
+
+	else if (virt_block_begin < tc->origin_size)
+		schedule_copy(tc, virt_block, tc->origin_dev,
+			      virt_block, data_dest, cell, bio,
+			      tc->origin_size - virt_block_begin);
+
+	else
+		schedule_zero(tc, virt_block, data_dest, cell, bio);
 }
 
 /*
@@ -1315,7 +1369,18 @@ static void process_bio(struct thin_c *t
 			inc_all_io_entry(pool, bio);
 			cell_defer_no_holder(tc, cell);
 
-			remap_to_origin_and_issue(tc, bio);
+			if (bio_end_sector(bio) <= tc->origin_size)
+				remap_to_origin_and_issue(tc, bio);
+
+			else if (bio->bi_iter.bi_sector < tc->origin_size) {
+				zero_fill_bio(bio);
+				bio->bi_iter.bi_size = (tc->origin_size - bio->bi_iter.bi_sector) << SECTOR_SHIFT;
+				remap_to_origin_and_issue(tc, bio);
+
+			} else {
+				zero_fill_bio(bio);
+				bio_endio(bio, 0);
+			}
 		} else
 			provision_block(tc, bio, block, cell);
 		break;
@@ -3112,7 +3177,7 @@ static void pool_io_hints(struct dm_targ
 	 */
 	if (io_opt_sectors < pool->sectors_per_block ||
 	    do_div(io_opt_sectors, pool->sectors_per_block)) {
-		blk_limits_io_min(limits, 0);
+		blk_limits_io_min(limits, pool->sectors_per_block << SECTOR_SHIFT);
 		blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
 	}
 
@@ -3141,7 +3206,7 @@ static struct target_type pool_target =
 	.name = "thin-pool",
 	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
 		    DM_TARGET_IMMUTABLE,
-	.version = {1, 12, 0},
+	.version = {1, 13, 0},
 	.module = THIS_MODULE,
 	.ctr = pool_ctr,
 	.dtr = pool_dtr,
@@ -3361,8 +3426,7 @@ static int thin_endio(struct dm_target *
 		spin_lock_irqsave(&pool->lock, flags);
 		list_for_each_entry_safe(m, tmp, &work, list) {
 			list_del(&m->list);
-			m->quiesced = true;
-			__maybe_add_mapping(m);
+			__complete_mapping_preparation(m);
 		}
 		spin_unlock_irqrestore(&pool->lock, flags);
 	}
@@ -3401,6 +3465,16 @@ static void thin_postsuspend(struct dm_t
 	noflush_work(tc, do_noflush_stop);
 }
 
+static int thin_preresume(struct dm_target *ti)
+{
+	struct thin_c *tc = ti->private;
+
+	if (tc->origin_dev)
+		tc->origin_size = get_dev_size(tc->origin_dev->bdev);
+
+	return 0;
+}
+
 /*
  * <nr mapped sectors> <highest mapped sector>
  */
@@ -3483,12 +3557,13 @@ static int thin_iterate_devices(struct d
 
 static struct target_type thin_target = {
 	.name = "thin",
-	.version = {1, 12, 0},
+	.version = {1, 13, 0},
 	.module	= THIS_MODULE,
 	.ctr = thin_ctr,
 	.dtr = thin_dtr,
 	.map = thin_map,
 	.end_io = thin_endio,
+	.preresume = thin_preresume,
 	.presuspend = thin_presuspend,
 	.postsuspend = thin_postsuspend,
 	.status = thin_status,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/md.c linux-libre-3.17-rc7-gnu/drivers/md/md.c
--- linux-libre-3.16-gnu/drivers/md/md.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/md.c	2014-09-28 17:29:07.000000000 -0400
@@ -5961,7 +5961,7 @@ static int set_bitmap_file(struct mddev
 	int err = 0;
 
 	if (mddev->pers) {
-		if (!mddev->pers->quiesce)
+		if (!mddev->pers->quiesce || !mddev->thread)
 			return -EBUSY;
 		if (mddev->recovery || mddev->sync_thread)
 			return -EBUSY;
@@ -6263,7 +6263,7 @@ static int update_array_info(struct mdde
 		rv = update_raid_disks(mddev, info->raid_disks);
 
 	if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
-		if (mddev->pers->quiesce == NULL)
+		if (mddev->pers->quiesce == NULL || mddev->thread == NULL)
 			return -EINVAL;
 		if (mddev->recovery || mddev->sync_thread)
 			return -EBUSY;
@@ -7376,7 +7376,7 @@ void md_do_sync(struct md_thread *thread
 	struct mddev *mddev2;
 	unsigned int currspeed = 0,
 		 window;
-	sector_t max_sectors,j, io_sectors;
+	sector_t max_sectors,j, io_sectors, recovery_done;
 	unsigned long mark[SYNC_MARKS];
 	unsigned long update_time;
 	sector_t mark_cnt[SYNC_MARKS];
@@ -7652,7 +7652,8 @@ void md_do_sync(struct md_thread *thread
 		 */
 		cond_resched();
 
-		currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+		recovery_done = io_sectors - atomic_read(&mddev->recovery_active);
+		currspeed = ((unsigned long)(recovery_done - mddev->resync_mark_cnt))/2
 			/((jiffies-mddev->resync_mark)/HZ +1) +1;
 
 		if (currspeed > speed_min(mddev)) {
@@ -8592,7 +8593,7 @@ static int __init md_init(void)
 		goto err_mdp;
 	mdp_major = ret;
 
-	blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE,
+	blk_register_region(MKDEV(MD_MAJOR, 0), 512, THIS_MODULE,
 			    md_probe, NULL, NULL);
 	blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE,
 			    md_probe, NULL, NULL);
@@ -8687,7 +8688,7 @@ static __exit void md_exit(void)
 	struct list_head *tmp;
 	int delay = 1;
 
-	blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
+	blk_unregister_region(MKDEV(MD_MAJOR,0), 512);
 	blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS);
 
 	unregister_blkdev(MD_MAJOR,"md");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/raid0.c linux-libre-3.17-rc7-gnu/drivers/md/raid0.c
--- linux-libre-3.16-gnu/drivers/md/raid0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/raid0.c	2014-09-28 17:29:07.000000000 -0400
@@ -685,6 +685,12 @@ static void *raid0_takeover(struct mddev
 	 *  raid10 - assuming we have all necessary active disks
 	 *  raid1 - with (N -1) mirror drives faulty
 	 */
+
+	if (mddev->bitmap) {
+		printk(KERN_ERR "md/raid0: %s: cannot takeover array with bitmap\n",
+		       mdname(mddev));
+		return ERR_PTR(-EBUSY);
+	}
 	if (mddev->level == 4)
 		return raid0_takeover_raid45(mddev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/raid10.c linux-libre-3.17-rc7-gnu/drivers/md/raid10.c
--- linux-libre-3.16-gnu/drivers/md/raid10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/raid10.c	2014-09-28 17:29:07.000000000 -0400
@@ -1684,13 +1684,12 @@ static void error(struct mddev *mddev, s
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 		return;
 	}
-	if (test_and_clear_bit(In_sync, &rdev->flags)) {
+	if (test_and_clear_bit(In_sync, &rdev->flags))
 		mddev->degraded++;
-			/*
-		 * if recovery is running, make sure it aborts.
-		 */
-		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-	}
+	/*
+	 * If recovery is running, make sure it aborts.
+	 */
+	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(Blocked, &rdev->flags);
 	set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -2954,6 +2953,7 @@ static sector_t sync_request(struct mdde
 		 */
 		if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
 			end_reshape(conf);
+			close_sync(conf);
 			return 0;
 		}
 
@@ -3082,6 +3082,7 @@ static sector_t sync_request(struct mdde
 			}
 
 			r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+			r10_bio->state = 0;
 			raise_barrier(conf, rb2 != NULL);
 			atomic_set(&r10_bio->remaining, 0);
 
@@ -3270,6 +3271,7 @@ static sector_t sync_request(struct mdde
 		if (sync_blocks < max_sync)
 			max_sync = sync_blocks;
 		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+		r10_bio->state = 0;
 
 		r10_bio->mddev = mddev;
 		atomic_set(&r10_bio->remaining, 0);
@@ -4385,6 +4387,7 @@ static sector_t reshape_request(struct m
 read_more:
 	/* Now schedule reads for blocks from sector_nr to last */
 	r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+	r10_bio->state = 0;
 	raise_barrier(conf, sectors_done != 0);
 	atomic_set(&r10_bio->remaining, 0);
 	r10_bio->mddev = mddev;
@@ -4399,6 +4402,7 @@ read_more:
 		 * on all the target devices.
 		 */
 		// FIXME
+		mempool_free(r10_bio, conf->r10buf_pool);
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 		return sectors_done;
 	}
@@ -4411,7 +4415,7 @@ read_more:
 	read_bio->bi_private = r10_bio;
 	read_bio->bi_end_io = end_sync_read;
 	read_bio->bi_rw = READ;
-	read_bio->bi_flags &= ~(BIO_POOL_MASK - 1);
+	read_bio->bi_flags &= (~0UL << BIO_RESET_BITS);
 	read_bio->bi_flags |= 1 << BIO_UPTODATE;
 	read_bio->bi_vcnt = 0;
 	read_bio->bi_iter.bi_size = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/raid1.c linux-libre-3.17-rc7-gnu/drivers/md/raid1.c
--- linux-libre-3.16-gnu/drivers/md/raid1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/raid1.c	2014-09-28 17:29:07.000000000 -0400
@@ -540,11 +540,7 @@ static int read_balance(struct r1conf *c
 	has_nonrot_disk = 0;
 	choose_next_idle = 0;
 
-	if (conf->mddev->recovery_cp < MaxSector &&
-	    (this_sector + sectors >= conf->next_resync))
-		choose_first = 1;
-	else
-		choose_first = 0;
+	choose_first = (conf->mddev->recovery_cp < this_sector + sectors);
 
 	for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) {
 		sector_t dist;
@@ -831,7 +827,7 @@ static void flush_pending_writes(struct
  *    there is no normal IO happeing.  It must arrange to call
  *    lower_barrier when the particular background IO completes.
  */
-static void raise_barrier(struct r1conf *conf)
+static void raise_barrier(struct r1conf *conf, sector_t sector_nr)
 {
 	spin_lock_irq(&conf->resync_lock);
 
@@ -841,6 +837,7 @@ static void raise_barrier(struct r1conf
 
 	/* block any new IO from starting */
 	conf->barrier++;
+	conf->next_resync = sector_nr;
 
 	/* For these conditions we must wait:
 	 * A: while the array is in frozen state
@@ -849,14 +846,17 @@ static void raise_barrier(struct r1conf
 	 * C: next_resync + RESYNC_SECTORS > start_next_window, meaning
 	 *    next resync will reach to the window which normal bios are
 	 *    handling.
+	 * D: while there are any active requests in the current window.
 	 */
 	wait_event_lock_irq(conf->wait_barrier,
 			    !conf->array_frozen &&
 			    conf->barrier < RESYNC_DEPTH &&
+			    conf->current_window_requests == 0 &&
 			    (conf->start_next_window >=
 			     conf->next_resync + RESYNC_SECTORS),
 			    conf->resync_lock);
 
+	conf->nr_pending++;
 	spin_unlock_irq(&conf->resync_lock);
 }
 
@@ -866,6 +866,7 @@ static void lower_barrier(struct r1conf
 	BUG_ON(conf->barrier <= 0);
 	spin_lock_irqsave(&conf->resync_lock, flags);
 	conf->barrier--;
+	conf->nr_pending--;
 	spin_unlock_irqrestore(&conf->resync_lock, flags);
 	wake_up(&conf->wait_barrier);
 }
@@ -877,12 +878,10 @@ static bool need_to_wait_for_sync(struct
 	if (conf->array_frozen || !bio)
 		wait = true;
 	else if (conf->barrier && bio_data_dir(bio) == WRITE) {
-		if (conf->next_resync < RESYNC_WINDOW_SECTORS)
-			wait = true;
-		else if ((conf->next_resync - RESYNC_WINDOW_SECTORS
-				>= bio_end_sector(bio)) ||
-			 (conf->next_resync + NEXT_NORMALIO_DISTANCE
-				<= bio->bi_iter.bi_sector))
+		if ((conf->mddev->curr_resync_completed
+		     >= bio_end_sector(bio)) ||
+		    (conf->next_resync + NEXT_NORMALIO_DISTANCE
+		     <= bio->bi_iter.bi_sector))
 			wait = false;
 		else
 			wait = true;
@@ -919,8 +918,8 @@ static sector_t wait_barrier(struct r1co
 	}
 
 	if (bio && bio_data_dir(bio) == WRITE) {
-		if (conf->next_resync + NEXT_NORMALIO_DISTANCE
-		    <= bio->bi_iter.bi_sector) {
+		if (bio->bi_iter.bi_sector >=
+		    conf->mddev->curr_resync_completed) {
 			if (conf->start_next_window == MaxSector)
 				conf->start_next_window =
 					conf->next_resync +
@@ -1186,6 +1185,7 @@ read_again:
 				   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,
@@ -1501,12 +1501,12 @@ static void error(struct mddev *mddev, s
 		mddev->degraded++;
 		set_bit(Faulty, &rdev->flags);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
-		/*
-		 * if recovery is running, make sure it aborts.
-		 */
-		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	} else
 		set_bit(Faulty, &rdev->flags);
+	/*
+	 * if recovery is running, make sure it aborts.
+	 */
+	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	printk(KERN_ALERT
 	       "md/raid1:%s: Disk failure on %s, disabling device.\n"
@@ -1548,8 +1548,13 @@ static void close_sync(struct r1conf *co
 	mempool_destroy(conf->r1buf_pool);
 	conf->r1buf_pool = NULL;
 
+	spin_lock_irq(&conf->resync_lock);
 	conf->next_resync = 0;
 	conf->start_next_window = MaxSector;
+	conf->current_window_requests +=
+		conf->next_window_requests;
+	conf->next_window_requests = 0;
+	spin_unlock_irq(&conf->resync_lock);
 }
 
 static int raid1_spare_active(struct mddev *mddev)
@@ -2150,7 +2155,7 @@ static void fix_read_error(struct r1conf
 			d--;
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
-			    test_bit(In_sync, &rdev->flags))
+			    !test_bit(Faulty, &rdev->flags))
 				r1_sync_page_io(rdev, sect, s,
 						conf->tmppage, WRITE);
 		}
@@ -2162,7 +2167,7 @@ static void fix_read_error(struct r1conf
 			d--;
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
-			    test_bit(In_sync, &rdev->flags)) {
+			    !test_bit(Faulty, &rdev->flags)) {
 				if (r1_sync_page_io(rdev, sect, s,
 						    conf->tmppage, READ)) {
 					atomic_add(s, &rdev->corrected_errors);
@@ -2541,9 +2546,8 @@ static sector_t sync_request(struct mdde
 
 	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
 	r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
-	raise_barrier(conf);
 
-	conf->next_resync = sector_nr;
+	raise_barrier(conf, sector_nr);
 
 	rcu_read_lock();
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/md/raid5.c linux-libre-3.17-rc7-gnu/drivers/md/raid5.c
--- linux-libre-3.16-gnu/drivers/md/raid5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/md/raid5.c	2014-09-28 17:29:07.000000000 -0400
@@ -2922,7 +2922,7 @@ static int fetch_block(struct stripe_hea
 	      (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) &&
 	      !test_bit(R5_OVERWRITE, &fdev[0]->flags)) ||
 	     (sh->raid_conf->level == 6 && s->failed && s->to_write &&
-	      s->to_write < sh->raid_conf->raid_disks - 2 &&
+	      s->to_write - s->non_overwrite < sh->raid_conf->raid_disks - 2 &&
 	      (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))))) {
 		/* we would like to get this block, possibly by computing it,
 		 * otherwise read it if the backing disk is insync
@@ -3817,6 +3817,8 @@ static void handle_stripe(struct stripe_
 				set_bit(R5_Wantwrite, &dev->flags);
 				if (prexor)
 					continue;
+				if (s.failed > 1)
+					continue;
 				if (!test_bit(R5_Insync, &dev->flags) ||
 				    ((i == sh->pd_idx || i == sh->qd_idx)  &&
 				     s.failed == 0))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/common/cx2341x.c linux-libre-3.17-rc7-gnu/drivers/media/common/cx2341x.c
--- linux-libre-3.16-gnu/drivers/media/common/cx2341x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/common/cx2341x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1490,6 +1490,7 @@ static struct v4l2_ctrl *cx2341x_ctrl_ne
 {
 	struct v4l2_ctrl_config cfg;
 
+	memset(&cfg, 0, sizeof(cfg));
 	cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);
 	cfg.ops = &cx2341x_ops;
 	cfg.id = id;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/common/saa7146/saa7146_core.c linux-libre-3.17-rc7-gnu/drivers/media/common/saa7146/saa7146_core.c
--- linux-libre-3.16-gnu/drivers/media/common/saa7146/saa7146_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/common/saa7146/saa7146_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -421,23 +421,20 @@ static int saa7146_init_one(struct pci_d
 	err = -ENOMEM;
 
 	/* get memory for various stuff */
-	dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						    &dev->d_rps0.dma_handle);
+	dev->d_rps0.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+						     &dev->d_rps0.dma_handle);
 	if (!dev->d_rps0.cpu_addr)
 		goto err_free_irq;
-	memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
 
-	dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						    &dev->d_rps1.dma_handle);
+	dev->d_rps1.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+						     &dev->d_rps1.dma_handle);
 	if (!dev->d_rps1.cpu_addr)
 		goto err_free_rps0;
-	memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
 
-	dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						   &dev->d_i2c.dma_handle);
+	dev->d_i2c.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+						    &dev->d_i2c.dma_handle);
 	if (!dev->d_i2c.cpu_addr)
 		goto err_free_rps1;
-	memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
 
 	/* the rest + print status message */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/common/saa7146/saa7146_fops.c linux-libre-3.17-rc7-gnu/drivers/media/common/saa7146/saa7146_fops.c
--- linux-libre-3.16-gnu/drivers/media/common/saa7146/saa7146_fops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/common/saa7146/saa7146_fops.c	2014-09-28 17:29:07.000000000 -0400
@@ -520,26 +520,26 @@ int saa7146_vv_init(struct saa7146_dev*
 	   configuration data) */
 	dev->ext_vv_data = ext_vv;
 
-	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
+	vv->d_clipping.cpu_addr =
+		pci_zalloc_consistent(dev->pci, SAA7146_CLIPPING_MEM,
+				      &vv->d_clipping.dma_handle);
 	if( NULL == vv->d_clipping.cpu_addr ) {
 		ERR("out of memory. aborting.\n");
 		kfree(vv);
 		v4l2_ctrl_handler_free(hdl);
 		return -1;
 	}
-	memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
 
 	saa7146_video_uops.init(dev,vv);
 	if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 		saa7146_vbi_uops.init(dev,vv);
 
-	fmt = &vv->ov_fb.fmt;
-	fmt->width = vv->standard->h_max_out;
-	fmt->height = vv->standard->v_max_out;
-	fmt->pixelformat = V4L2_PIX_FMT_RGB565;
-	fmt->bytesperline = 2 * fmt->width;
-	fmt->sizeimage = fmt->bytesperline * fmt->height;
-	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	vv->ov_fb.fmt.width = vv->standard->h_max_out;
+	vv->ov_fb.fmt.height = vv->standard->v_max_out;
+	vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+	vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
+	vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
+	vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
 
 	fmt = &vv->video_fmt;
 	fmt->width = 384;
@@ -613,7 +613,6 @@ int saa7146_register_device(struct video
 	vfd->lock = &dev->v4l2_lock;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->tvnorms = 0;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
 		vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
 	strlcpy(vfd->name, name, sizeof(vfd->name));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/common/siano/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/common/siano/Kconfig
--- linux-libre-3.16-gnu/drivers/media/common/siano/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/common/siano/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS
 	bool "Enable debugfs for smsdvb"
 	depends on SMS_SIANO_MDTV
 	depends on DEBUG_FS
-	depends on SMS_USB_DRV
-	depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV
+	depends on SMS_USB_DRV = SMS_SDIO_DRV
 
 	---help---
 	  Choose Y to enable visualizing a dump of the frontend
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/common/siano/smsir.c linux-libre-3.17-rc7-gnu/drivers/media/common/siano/smsir.c
--- linux-libre-3.16-gnu/drivers/media/common/siano/smsir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/common/siano/smsir.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t
 
 	dev->priv = coredev;
 	dev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(dev, RC_BIT_ALL);
+	dev->allowed_protocols = RC_BIT_ALL;
 	dev->map_name = sms_get_board(board_id)->rc_codes;
 	dev->driver_name = MODULE_NAME;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-core/dvbdev.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvbdev.h
--- linux-libre-3.16-gnu/drivers/media/dvb-core/dvbdev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvbdev.h	2014-09-28 17:29:07.000000000 -0400
@@ -136,11 +136,15 @@ extern int dvb_usercopy(struct file *fil
 	__r; \
 })
 
+#define dvb_detach(FUNC)	symbol_put_addr(FUNC)
+
 #else
 #define dvb_attach(FUNCTION, ARGS...) ({ \
 	FUNCTION(ARGS); \
 })
 
+#define dvb_detach(FUNC)	{}
+
 #endif
 
 #endif /* #ifndef _DVBDEV_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_frontend.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_frontend.c
--- linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_frontend.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_frontend.c	2014-09-28 17:29:07.000000000 -0400
@@ -96,10 +96,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wai
  * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
  */
 
-#define DVB_FE_NO_EXIT	0
-#define DVB_FE_NORMAL_EXIT	1
-#define DVB_FE_DEVICE_REMOVED	2
-
 static DEFINE_MUTEX(frontend_mutex);
 
 struct dvb_frontend_private {
@@ -113,7 +109,6 @@ struct dvb_frontend_private {
 	wait_queue_head_t wait_queue;
 	struct task_struct *thread;
 	unsigned long release_jiffies;
-	unsigned int exit;
 	unsigned int wakeup;
 	fe_status_t status;
 	unsigned long tune_mode_flags;
@@ -565,7 +560,7 @@ static int dvb_frontend_is_exiting(struc
 {
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-	if (fepriv->exit != DVB_FE_NO_EXIT)
+	if (fe->exit != DVB_FE_NO_EXIT)
 		return 1;
 
 	if (fepriv->dvbdev->writers == 1)
@@ -629,7 +624,7 @@ restart:
 			/* got signal or quitting */
 			if (!down_interruptible(&fepriv->sem))
 				semheld = true;
-			fepriv->exit = DVB_FE_NORMAL_EXIT;
+			fe->exit = DVB_FE_NORMAL_EXIT;
 			break;
 		}
 
@@ -739,9 +734,9 @@ restart:
 
 	fepriv->thread = NULL;
 	if (kthread_should_stop())
-		fepriv->exit = DVB_FE_DEVICE_REMOVED;
+		fe->exit = DVB_FE_DEVICE_REMOVED;
 	else
-		fepriv->exit = DVB_FE_NO_EXIT;
+		fe->exit = DVB_FE_NO_EXIT;
 	mb();
 
 	if (semheld)
@@ -756,7 +751,8 @@ static void dvb_frontend_stop(struct dvb
 
 	dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
-	fepriv->exit = DVB_FE_NORMAL_EXIT;
+	if (fe->exit != DVB_FE_DEVICE_REMOVED)
+		fe->exit = DVB_FE_NORMAL_EXIT;
 	mb();
 
 	if (!fepriv->thread)
@@ -826,7 +822,7 @@ static int dvb_frontend_start(struct dvb
 	dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
 	if (fepriv->thread) {
-		if (fepriv->exit == DVB_FE_NO_EXIT)
+		if (fe->exit == DVB_FE_NO_EXIT)
 			return 0;
 		else
 			dvb_frontend_stop (fe);
@@ -838,7 +834,7 @@ static int dvb_frontend_start(struct dvb
 		return -EINTR;
 
 	fepriv->state = FESTATE_IDLE;
-	fepriv->exit = DVB_FE_NO_EXIT;
+	fe->exit = DVB_FE_NO_EXIT;
 	fepriv->thread = NULL;
 	mb();
 
@@ -1906,7 +1902,7 @@ static int dvb_frontend_ioctl(struct fil
 	if (down_interruptible(&fepriv->sem))
 		return -ERESTARTSYS;
 
-	if (fepriv->exit != DVB_FE_NO_EXIT) {
+	if (fe->exit != DVB_FE_NO_EXIT) {
 		up(&fepriv->sem);
 		return -ENODEV;
 	}
@@ -2424,7 +2420,7 @@ static int dvb_frontend_open(struct inod
 	int ret;
 
 	dev_dbg(fe->dvb->device, "%s:\n", __func__);
-	if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
+	if (fe->exit == DVB_FE_DEVICE_REMOVED)
 		return -ENODEV;
 
 	if (adapter->mfe_shared) {
@@ -2529,7 +2525,7 @@ static int dvb_frontend_release(struct i
 
 	if (dvbdev->users == -1) {
 		wake_up(&fepriv->wait_queue);
-		if (fepriv->exit != DVB_FE_NO_EXIT)
+		if (fe->exit != DVB_FE_NO_EXIT)
 			wake_up(&dvbdev->wait_queue);
 		if (fe->ops.ts_bus_ctrl)
 			fe->ops.ts_bus_ctrl(fe, 0);
@@ -2572,12 +2568,14 @@ int dvb_frontend_resume(struct dvb_front
 	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
 			fe->id);
 
+	fe->exit = DVB_FE_DEVICE_RESUME;
 	if (fe->ops.init)
 		ret = fe->ops.init(fe);
 
 	if (fe->ops.tuner_ops.init)
 		ret = fe->ops.tuner_ops.init(fe);
 
+	fe->exit = DVB_FE_NO_EXIT;
 	fepriv->state = FESTATE_RETUNE;
 	dvb_frontend_wakeup(fe);
 
@@ -2666,20 +2664,20 @@ void dvb_frontend_detach(struct dvb_fron
 
 	if (fe->ops.release_sec) {
 		fe->ops.release_sec(fe);
-		symbol_put_addr(fe->ops.release_sec);
+		dvb_detach(fe->ops.release_sec);
 	}
 	if (fe->ops.tuner_ops.release) {
 		fe->ops.tuner_ops.release(fe);
-		symbol_put_addr(fe->ops.tuner_ops.release);
+		dvb_detach(fe->ops.tuner_ops.release);
 	}
 	if (fe->ops.analog_ops.release) {
 		fe->ops.analog_ops.release(fe);
-		symbol_put_addr(fe->ops.analog_ops.release);
+		dvb_detach(fe->ops.analog_ops.release);
 	}
 	ptr = (void*)fe->ops.release;
 	if (ptr) {
 		fe->ops.release(fe);
-		symbol_put_addr(ptr);
+		dvb_detach(ptr);
 	}
 }
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_frontend.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_frontend.h
--- linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_frontend.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_frontend.h	2014-09-28 17:29:07.000000000 -0400
@@ -405,6 +405,11 @@ struct dtv_frontend_properties {
 	struct dtv_fe_stats	block_count;
 };
 
+#define DVB_FE_NO_EXIT  0
+#define DVB_FE_NORMAL_EXIT      1
+#define DVB_FE_DEVICE_REMOVED   2
+#define DVB_FE_DEVICE_RESUME    3
+
 struct dvb_frontend {
 	struct dvb_frontend_ops ops;
 	struct dvb_adapter *dvb;
@@ -418,6 +423,7 @@ struct dvb_frontend {
 #define DVB_FRONTEND_COMPONENT_DEMOD 1
 	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
 	int id;
+	unsigned int exit;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter *dvb,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_net.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_net.c
--- linux-libre-3.16-gnu/drivers/media/dvb-core/dvb_net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb_net.c	2014-09-28 17:29:07.000000000 -0400
@@ -1276,7 +1276,8 @@ static int dvb_net_add_if(struct dvb_net
 	if ((if_num = get_if(dvbnet)) < 0)
 		return -EINVAL;
 
-	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);
+	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb",
+			   NET_NAME_UNKNOWN, dvb_net_setup);
 	if (!net)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-core/dvb-usb-ids.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb-usb-ids.h
--- linux-libre-3.16-gnu/drivers/media/dvb-core/dvb-usb-ids.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-core/dvb-usb-ids.h	2014-09-28 17:29:07.000000000 -0400
@@ -244,6 +244,7 @@
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM	0x3009
 #define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d
+#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400		0x3014
 #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
@@ -279,6 +280,8 @@
 #define USB_PID_PCTV_400E				0x020f
 #define USB_PID_PCTV_450E				0x0222
 #define USB_PID_PCTV_452E				0x021f
+#define USB_PID_PCTV_78E				0x025a
+#define USB_PID_PCTV_79E				0x0262
 #define USB_PID_REALTEK_RTL2831U			0x2831
 #define USB_PID_REALTEK_RTL2832U			0x2832
 #define USB_PID_TECHNOTREND_CONNECT_S2_3600		0x3007
@@ -363,6 +366,7 @@
 #define USB_PID_TVWAY_PLUS				0x0002
 #define USB_PID_SVEON_STV20				0xe39d
 #define USB_PID_SVEON_STV20_RTL2832U			0xd39d
+#define USB_PID_SVEON_STV21				0xd3b0
 #define USB_PID_SVEON_STV22				0xe401
 #define USB_PID_SVEON_STV22_IT9137			0xe411
 #define USB_PID_AZUREWAVE_AZ6027			0x3275
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9013.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9013.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9013.c	2014-08-07 04:48:31.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9013.c	2014-09-28 21:29:25.000000000 -0400
@@ -470,7 +470,6 @@ static int af9013_statistics_snr_result(
 		break;
 	default:
 		goto err;
-		break;
 	}
 
 	for (i = 0; i < len; i++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9033.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9033.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9033.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9033.c	2014-09-28 17:29:07.000000000 -0400
@@ -314,6 +314,19 @@ static int af9033_init(struct dvb_fronte
 			goto err;
 	}
 
+	/* feed clock to RF tuner */
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		ret = af9033_wr_reg(state, 0x80fba8, 0x00);
+		if (ret < 0)
+			goto err;
+	}
+
 	/* settings for TS interface */
 	if (state->cfg.ts_mode == AF9033_TS_MODE_USB) {
 		ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9033_priv.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9033_priv.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/af9033_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/af9033_priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -1418,7 +1418,7 @@ static const struct reg_val tuner_init_i
 	{ 0x800068, 0x0a },
 	{ 0x80006a, 0x03 },
 	{ 0x800070, 0x0a },
-	{ 0x800071, 0x05 },
+	{ 0x800071, 0x0a },
 	{ 0x800072, 0x02 },
 	{ 0x800075, 0x8c },
 	{ 0x800076, 0x8c },
@@ -1484,7 +1484,6 @@ static const struct reg_val tuner_init_i
 	{ 0x800104, 0x02 },
 	{ 0x800105, 0xbe },
 	{ 0x800106, 0x00 },
-	{ 0x800109, 0x02 },
 	{ 0x800115, 0x0a },
 	{ 0x800116, 0x03 },
 	{ 0x80011a, 0xbe },
@@ -1510,7 +1509,6 @@ static const struct reg_val tuner_init_i
 	{ 0x80014b, 0x8c },
 	{ 0x80014d, 0xac },
 	{ 0x80014e, 0xc6 },
-	{ 0x80014f, 0x03 },
 	{ 0x800151, 0x1e },
 	{ 0x800153, 0xbc },
 	{ 0x800178, 0x09 },
@@ -1522,9 +1520,10 @@ static const struct reg_val tuner_init_i
 	{ 0x80018d, 0x5f },
 	{ 0x80018f, 0xa0 },
 	{ 0x800190, 0x5a },
-	{ 0x80ed02, 0xff },
-	{ 0x80ee42, 0xff },
-	{ 0x80ee82, 0xff },
+	{ 0x800191, 0x00 },
+	{ 0x80ed02, 0x40 },
+	{ 0x80ee42, 0x40 },
+	{ 0x80ee82, 0x40 },
 	{ 0x80f000, 0x0f },
 	{ 0x80f01f, 0x8c },
 	{ 0x80f020, 0x00 },
@@ -1699,7 +1698,6 @@ static const struct reg_val tuner_init_i
 	{ 0x800104, 0x02 },
 	{ 0x800105, 0xc8 },
 	{ 0x800106, 0x00 },
-	{ 0x800109, 0x02 },
 	{ 0x800115, 0x0a },
 	{ 0x800116, 0x03 },
 	{ 0x80011a, 0xc6 },
@@ -1725,7 +1723,6 @@ static const struct reg_val tuner_init_i
 	{ 0x80014b, 0x8c },
 	{ 0x80014d, 0xa8 },
 	{ 0x80014e, 0xc6 },
-	{ 0x80014f, 0x03 },
 	{ 0x800151, 0x28 },
 	{ 0x800153, 0xcc },
 	{ 0x800178, 0x09 },
@@ -1737,9 +1734,10 @@ static const struct reg_val tuner_init_i
 	{ 0x80018d, 0x5f },
 	{ 0x80018f, 0xfb },
 	{ 0x800190, 0x5c },
-	{ 0x80ed02, 0xff },
-	{ 0x80ee42, 0xff },
-	{ 0x80ee82, 0xff },
+	{ 0x800191, 0x00 },
+	{ 0x80ed02, 0x40 },
+	{ 0x80ee42, 0x40 },
+	{ 0x80ee82, 0x40 },
 	{ 0x80f000, 0x0f },
 	{ 0x80f01f, 0x8c },
 	{ 0x80f020, 0x00 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/au8522_decoder.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/au8522_decoder.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/au8522_decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/au8522_decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -220,7 +220,7 @@ static void setup_vbi(struct au8522_stat
 
 }
 
-static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
+static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
 {
 	int i;
 	int filter_coef_type;
@@ -237,13 +237,10 @@ static void setup_decoder_defaults(struc
 	/* Other decoder registers */
 	au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
 
-	if (input_mode == 0x23) {
-		/* S-Video input mapping */
+	if (is_svideo)
 		au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
-	} else {
-		/* All other modes (CVBS/ATVRF etc.) */
+	else
 		au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
-	}
 
 	au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
 			AU8522_TVDEC_PGA_REG012H_CVBS);
@@ -251,12 +248,23 @@ static void setup_decoder_defaults(struc
 			AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
 	au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
 			AU8522_TVDED_DBG_MODE_REG060H_CVBS);
-	au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
-			AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
-			AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
-			AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
-	au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
-			AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+
+	if (state->std == V4L2_STD_PAL_M) {
+		au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO);
+		au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+				AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M);
+	} else {
+		/* NTSC */
+		au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+				AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
+		au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+				AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+	}
 	au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
 			AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
 	au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
@@ -275,8 +283,7 @@ static void setup_decoder_defaults(struc
 			AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
 	au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
 			AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
-	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
-	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+	if (is_svideo) {
 		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
 				AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
 		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
@@ -317,8 +324,7 @@ static void setup_decoder_defaults(struc
 
 	setup_vbi(state, 0);
 
-	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
-	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+	if (is_svideo) {
 		/* Despite what the table says, for the HVR-950q we still need
 		   to be in CVBS mode for the S-Video input (reason unknown). */
 		/* filter_coef_type = 3; */
@@ -346,7 +352,7 @@ static void setup_decoder_defaults(struc
 	au8522_writereg(state, AU8522_REG436H, 0x3c);
 }
 
-static void au8522_setup_cvbs_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_mode(struct au8522_state *state, u8 input_mode)
 {
 	/* here we're going to try the pre-programmed route */
 	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -358,16 +364,16 @@ static void au8522_setup_cvbs_mode(struc
 	/* Enable clamping control */
 	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 
-	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
-			AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
 
-	setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+	setup_decoder_defaults(state, false);
 
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 }
 
-static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state,
+					 u8 input_mode)
 {
 	/* here we're going to try the pre-programmed route */
 	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -384,24 +390,22 @@ static void au8522_setup_cvbs_tuner_mode
 	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
 
 	/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
-	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
-			AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
 
-	setup_decoder_defaults(state,
-			       AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+	setup_decoder_defaults(state, false);
 
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 }
 
-static void au8522_setup_svideo_mode(struct au8522_state *state)
+static void au8522_setup_svideo_mode(struct au8522_state *state,
+				     u8 input_mode)
 {
 	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
 
 	/* Set input to Y on Channe1, C on Channel 3 */
-	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
-			AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
 
 	/* PGA in automatic mode */
 	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
@@ -409,8 +413,7 @@ static void au8522_setup_svideo_mode(str
 	/* Enable clamping control */
 	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 
-	setup_decoder_defaults(state,
-			       AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+	setup_decoder_defaults(state, true);
 
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
@@ -432,8 +435,9 @@ static void disable_audio_input(struct a
 }
 
 /* 0=disable, 1=SIF */
-static void set_audio_input(struct au8522_state *state, int aud_input)
+static void set_audio_input(struct au8522_state *state)
 {
+	int aud_input = state->aud_input;
 	int i;
 
 	/* Note that this function needs to be used in conjunction with setting
@@ -465,8 +469,9 @@ static void set_audio_input(struct au852
 	au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
 	msleep(150);
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
-	msleep(1);
-	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
+	msleep(10);
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 	msleep(50);
 	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
 	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
@@ -539,58 +544,109 @@ static int au8522_s_register(struct v4l2
 }
 #endif
 
+static void au8522_video_set(struct au8522_state *state)
+{
+	u8 input_mode;
+
+	au8522_writereg(state, 0xa4, 1 << 5);
+
+	switch (state->vid_input) {
+	case AU8522_COMPOSITE_CH1:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH1;
+		au8522_setup_cvbs_mode(state, input_mode);
+		break;
+	case AU8522_COMPOSITE_CH2:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH2;
+		au8522_setup_cvbs_mode(state, input_mode);
+		break;
+	case AU8522_COMPOSITE_CH3:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH3;
+		au8522_setup_cvbs_mode(state, input_mode);
+		break;
+	case AU8522_COMPOSITE_CH4:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4;
+		au8522_setup_cvbs_mode(state, input_mode);
+		break;
+	case AU8522_SVIDEO_CH13:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13;
+		au8522_setup_svideo_mode(state, input_mode);
+		break;
+	case AU8522_SVIDEO_CH24:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24;
+		au8522_setup_svideo_mode(state, input_mode);
+		break;
+	default:
+	case AU8522_COMPOSITE_CH4_SIF:
+		input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF;
+		au8522_setup_cvbs_tuner_mode(state, input_mode);
+		break;
+	}
+}
+
 static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct au8522_state *state = to_state(sd);
 
 	if (enable) {
+		/*
+		 * Clear out any state associated with the digital side of the
+		 * chip, so that when it gets powered back up it won't think
+		 * that it is already tuned
+		 */
+		state->current_frequency = 0;
+
 		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 				0x01);
-		msleep(1);
-		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
-				AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+		msleep(10);
+
+		au8522_video_set(state);
+		set_audio_input(state);
+
+		state->operational_mode = AU8522_ANALOG_MODE;
 	} else {
 		/* This does not completely power down the device
 		   (it only reduces it from around 140ma to 80ma) */
 		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 				1 << 5);
+		state->operational_mode = AU8522_SUSPEND_MODE;
 	}
 	return 0;
 }
 
-static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+					u32 input, u32 output, u32 config)
 {
 	struct au8522_state *state = to_state(sd);
 
-	state->operational_mode = AU8522_ANALOG_MODE;
-
-	/* Clear out any state associated with the digital side of the
-	   chip, so that when it gets powered back up it won't think
-	   that it is already tuned */
-	state->current_frequency = 0;
+	switch(input) {
+	case AU8522_COMPOSITE_CH1:
+	case AU8522_SVIDEO_CH13:
+	case AU8522_COMPOSITE_CH4_SIF:
+		state->vid_input = input;
+		break;
+	default:
+		printk(KERN_ERR "au8522 mode not currently supported\n");
+		return -EINVAL;
+	}
 
-	au8522_writereg(state, 0xa4, 1 << 5);
+	if (state->operational_mode == AU8522_ANALOG_MODE)
+		au8522_video_set(state);
 
 	return 0;
 }
 
-static int au8522_s_video_routing(struct v4l2_subdev *sd,
-					u32 input, u32 output, u32 config)
+static int au8522_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 {
 	struct au8522_state *state = to_state(sd);
 
-	au8522_reset(sd, 0);
-
-	if (input == AU8522_COMPOSITE_CH1) {
-		au8522_setup_cvbs_mode(state);
-	} else if (input == AU8522_SVIDEO_CH13) {
-		au8522_setup_svideo_mode(state);
-	} else if (input == AU8522_COMPOSITE_CH4_SIF) {
-		au8522_setup_cvbs_tuner_mode(state);
-	} else {
-		printk(KERN_ERR "au8522 mode not currently supported\n");
+	if ((std & (V4L2_STD_PAL_M | V4L2_STD_NTSC_M)) == 0)
 		return -EINVAL;
-	}
+
+	state->std = std;
+
+	if (state->operational_mode == AU8522_ANALOG_MODE)
+		au8522_video_set(state);
+
 	return 0;
 }
 
@@ -598,7 +654,12 @@ static int au8522_s_audio_routing(struct
 					u32 input, u32 output, u32 config)
 {
 	struct au8522_state *state = to_state(sd);
-	set_audio_input(state, input);
+
+	state->aud_input = input;
+
+	if (state->operational_mode == AU8522_ANALOG_MODE)
+		set_audio_input(state);
+
 	return 0;
 }
 
@@ -629,7 +690,6 @@ static int au8522_g_tuner(struct v4l2_su
 
 static const struct v4l2_subdev_core_ops au8522_core_ops = {
 	.log_status = v4l2_ctrl_subdev_log_status,
-	.reset = au8522_reset,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = au8522_g_register,
 	.s_register = au8522_s_register,
@@ -647,6 +707,7 @@ static const struct v4l2_subdev_audio_op
 static const struct v4l2_subdev_video_ops au8522_video_ops = {
 	.s_routing = au8522_s_video_routing,
 	.s_stream = au8522_s_stream,
+	.s_std = au8522_s_std,
 };
 
 static const struct v4l2_subdev_ops au8522_ops = {
@@ -729,6 +790,7 @@ static int au8522_probe(struct i2c_clien
 	}
 
 	state->c = client;
+	state->std = V4L2_STD_NTSC_M;
 	state->vid_input = AU8522_COMPOSITE_CH1;
 	state->aud_input = AU8522_AUDIO_NONE;
 	state->id = 8522;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/au8522_priv.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/au8522_priv.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/au8522_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/au8522_priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,7 @@
 
 #define AU8522_ANALOG_MODE 0
 #define AU8522_DIGITAL_MODE 1
+#define AU8522_SUSPEND_MODE 2
 
 struct au8522_state {
 	struct i2c_client *c;
@@ -347,6 +348,7 @@ int au8522_led_ctrl(struct au8522_state
 /* Format control 2 */
 #define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT	0x00
 #define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC		0x01
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M		0x02
 
 
 #define AU8522_INPUT_CONTROL_REG081H_ATSC               	0xC4
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/cx24123.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cx24123.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/cx24123.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cx24123.c	2014-09-28 17:29:07.000000000 -0400
@@ -1095,6 +1095,7 @@ struct dvb_frontend *cx24123_attach(cons
 		sizeof(state->tuner_i2c_adapter.name));
 	state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
 	state->tuner_i2c_adapter.algo_data = NULL;
+	state->tuner_i2c_adapter.dev.parent = i2c->dev.parent;
 	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
 	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
 		err("tuner i2c bus could not be initialized\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_c.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_c.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_c.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,7 @@ int cxd2820r_set_frontend_c(struct dvb_f
 		{ 0x1008b, 0x07, 0xff },
 		{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
 		{ 0x10070, priv->cfg.ts_mode, 0xff },
+		{ 0x10071, !priv->cfg.ts_clock_inv << 4, 0x10 },
 	};
 
 	dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r.h	2014-09-28 17:29:07.000000000 -0400
@@ -52,6 +52,12 @@ struct cxd2820r_config {
 	 */
 	u8 ts_mode;
 
+	/* TS clock inverted.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool ts_clock_inv;
+
 	/* IF AGC polarity.
 	 * Default: 0
 	 * Values: 0, 1
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_t2.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_t2.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_t2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_t2.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,7 @@ int cxd2820r_set_frontend_t2(struct dvb_
 		{ 0x02083, 0x0a, 0xff },
 		{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
 		{ 0x02070, priv->cfg.ts_mode, 0xff },
+		{ 0x02071, !priv->cfg.ts_clock_inv << 6, 0x40 },
 		{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
 		{ 0x02567, 0x07, 0x0f },
 		{ 0x02569, 0x03, 0x03 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_t.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_t.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/cxd2820r_t.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/cxd2820r_t.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,7 @@ int cxd2820r_set_frontend_t(struct dvb_f
 		{ 0x00088, 0x01, 0xff },
 
 		{ 0x00070, priv->cfg.ts_mode, 0xff },
+		{ 0x00071, !priv->cfg.ts_clock_inv << 4, 0x10 },
 		{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
 		{ 0x000a5, 0x00, 0x01 },
 		{ 0x00082, 0x20, 0x60 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib0090.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib0090.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib0090.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib0090.c	2014-09-28 17:29:07.000000000 -0400
@@ -2557,10 +2557,19 @@ static int dib0090_set_params(struct dvb
 
 	do {
 		ret = dib0090_tune(fe);
-		if (ret != FE_CALLBACK_TIME_NEVER)
-			msleep(ret / 10);
-		else
+		if (ret == FE_CALLBACK_TIME_NEVER)
 			break;
+
+		/*
+		 * Despite dib0090_tune returns time at a 0.1 ms range,
+		 * the actual sleep time depends on CONFIG_HZ. The worse case
+		 * is when CONFIG_HZ=100. In such case, the minimum granularity
+		 * is 10ms. On some real field tests, the tuner sometimes don't
+		 * lock when this timer is lower than 10ms. So, enforce a 10ms
+		 * granularity and use usleep_range() instead of msleep().
+		 */
+		ret = 10 * (ret + 99)/100;
+		usleep_range(ret * 1000, (ret + 1) * 1000);
 	} while (state->tune_state != CT_TUNER_STOP);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000m.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000m.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000m.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000m.c	2014-09-28 17:29:07.000000000 -0400
@@ -1041,10 +1041,7 @@ static int dib7000m_tune(struct dvb_fron
 	u16 value;
 
 	// we are already tuned - just resuming from suspend
-	if (ch != NULL)
-		dib7000m_set_channel(state, ch, 0);
-	else
-		return -EINVAL;
+	dib7000m_set_channel(state, ch, 0);
 
 	// restart demod
 	ret |= dib7000m_write_word(state, 898, 0x4000);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000p.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000p.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000p.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000p.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
+#include <asm/div64.h>
 
 #include "dvb_math.h"
 #include "dvb_frontend.h"
@@ -72,6 +73,12 @@ struct dib7000p_state {
 	struct mutex i2c_buffer_lock;
 
 	u8 input_mode_mpeg;
+
+	/* for DVBv5 stats */
+	s64 old_ucb;
+	unsigned long per_jiffies_stats;
+	unsigned long ber_jiffies_stats;
+	unsigned long get_stats_time;
 };
 
 enum dib7000p_power_mode {
@@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib
 	return 0;
 }
 
-int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
+static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
 {
 	struct dib7000p_state *state = demod->demodulator_priv;
 	if (value > 4095)
@@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_fron
 	state->wbd_ref = value;
 	return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
 }
-EXPORT_SYMBOL(dib7000p_set_wbd_ref);
 
-int dib7000p_get_agc_values(struct dvb_frontend *fe,
+static int dib7000p_get_agc_values(struct dvb_frontend *fe,
 		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
@@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_f
 
 	return 0;
 }
-EXPORT_SYMBOL(dib7000p_get_agc_values);
 
-int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
+static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	return dib7000p_write_word(state, 108,  v);
 }
-EXPORT_SYMBOL(dib7000p_set_agc1_min);
 
 static void dib7000p_reset_pll(struct dib7000p_state *state)
 {
@@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(st
 	return internal;
 }
 
-int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
@@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_front
 	}
 	return -EIO;
 }
-EXPORT_SYMBOL(dib7000p_update_pll);
 
 static int dib7000p_reset_gpio(struct dib7000p_state *st)
 {
@@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7
 	return 0;
 }
 
-int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
+static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
 {
 	struct dib7000p_state *state = demod->demodulator_priv;
 	return dib7000p_cfg_gpio(state, num, dir, val);
 }
-EXPORT_SYMBOL(dib7000p_set_gpio);
 
 static u16 dib7000p_defaults[] = {
 	// auto search configuration
@@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = {
 	0,
 };
 
+static void dib7000p_reset_stats(struct dvb_frontend *fe);
+
 static int dib7000p_demod_reset(struct dib7000p_state *state)
 {
 	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
@@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct
 
 }
 
-u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	switch (op) {
@@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_fronte
 	dib7000p_set_bandwidth(state, state->current_bandwidth);
 	return state->timf;
 }
-EXPORT_SYMBOL(dib7000p_ctrl_timf);
 
 static void dib7000p_set_channel(struct dib7000p_state *state,
 				 struct dtv_frontend_properties *ch, u8 seq)
@@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_fron
 		dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
 
 	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+	dib7000p_reset_stats(demod);
+
 	return 0;
 }
 
@@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct
 	return ret;
 }
 
+static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
+
 static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
@@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct d
 	if ((lock & 0x0038) == 0x38)
 		*stat |= FE_HAS_LOCK;
 
+	dib7000p_get_stats(fe, *stat);
+
 	return 0;
 }
 
@@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength
 	return 0;
 }
 
-static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
+static u32 dib7000p_get_snr(struct dvb_frontend *fe)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 val;
@@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_
 	else
 		result -= intlog10(2) * 10 * noise_exp - 100;
 
+	return result;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	u32 result;
+
+	result = dib7000p_get_snr(fe);
+
 	*snr = result / ((1 << 24) / 10);
 	return 0;
 }
 
+static void dib7000p_reset_stats(struct dvb_frontend *demod)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+	u32 ucb;
+
+	memset(&c->strength, 0, sizeof(c->strength));
+	memset(&c->cnr, 0, sizeof(c->cnr));
+	memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
+	memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
+	memset(&c->block_error, 0, sizeof(c->block_error));
+
+	c->strength.len = 1;
+	c->cnr.len = 1;
+	c->block_error.len = 1;
+	c->block_count.len = 1;
+	c->post_bit_error.len = 1;
+	c->post_bit_count.len = 1;
+
+	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+	c->strength.stat[0].uvalue = 0;
+
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	dib7000p_read_unc_blocks(demod, &ucb);
+
+	state->old_ucb = ucb;
+	state->ber_jiffies_stats = 0;
+	state->per_jiffies_stats = 0;
+}
+
+struct linear_segments {
+	unsigned x;
+	signed y;
+};
+
+/*
+ * Table to estimate signal strength in dBm.
+ * This table should be empirically determinated by measuring the signal
+ * strength generated by a RF generator directly connected into
+ * a device.
+ * This table was determinated by measuring the signal strength generated
+ * by a DTA-2111 RF generator directly connected into a dib7000p device
+ * (a Hauppauge Nova-TD stick), using a good quality 3 meters length
+ * RC6 cable and good RC6 connectors, connected directly to antenna 1.
+ * As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
+ * were used, for the lower power values.
+ * The real value can actually be on other devices, or even at the
+ * second antena input, depending on several factors, like if LNA
+ * is enabled or not, if diversity is enabled, type of connectors, etc.
+ * Yet, it is better to use this measure in dB than a random non-linear
+ * percentage value, especially for antenna adjustments.
+ * On my tests, the precision of the measure using this table is about
+ * 0.5 dB, with sounds reasonable enough to adjust antennas.
+ */
+#define DB_OFFSET 131000
+
+static struct linear_segments strength_to_db_table[] = {
+	{ 63630, DB_OFFSET - 20500},
+	{ 62273, DB_OFFSET - 21000},
+	{ 60162, DB_OFFSET - 22000},
+	{ 58730, DB_OFFSET - 23000},
+	{ 58294, DB_OFFSET - 24000},
+	{ 57778, DB_OFFSET - 25000},
+	{ 57320, DB_OFFSET - 26000},
+	{ 56779, DB_OFFSET - 27000},
+	{ 56293, DB_OFFSET - 28000},
+	{ 55724, DB_OFFSET - 29000},
+	{ 55145, DB_OFFSET - 30000},
+	{ 54680, DB_OFFSET - 31000},
+	{ 54293, DB_OFFSET - 32000},
+	{ 53813, DB_OFFSET - 33000},
+	{ 53427, DB_OFFSET - 34000},
+	{ 52981, DB_OFFSET - 35000},
+
+	{ 52636, DB_OFFSET - 36000},
+	{ 52014, DB_OFFSET - 37000},
+	{ 51674, DB_OFFSET - 38000},
+	{ 50692, DB_OFFSET - 39000},
+	{ 49824, DB_OFFSET - 40000},
+	{ 49052, DB_OFFSET - 41000},
+	{ 48436, DB_OFFSET - 42000},
+	{ 47836, DB_OFFSET - 43000},
+	{ 47368, DB_OFFSET - 44000},
+	{ 46468, DB_OFFSET - 45000},
+	{ 45597, DB_OFFSET - 46000},
+	{ 44586, DB_OFFSET - 47000},
+	{ 43667, DB_OFFSET - 48000},
+	{ 42673, DB_OFFSET - 49000},
+	{ 41816, DB_OFFSET - 50000},
+	{ 40876, DB_OFFSET - 51000},
+	{     0,      0},
+};
+
+static u32 interpolate_value(u32 value, struct linear_segments *segments,
+			     unsigned len)
+{
+	u64 tmp64;
+	u32 dx;
+	s32 dy;
+	int i, ret;
+
+	if (value >= segments[0].x)
+		return segments[0].y;
+	if (value < segments[len-1].x)
+		return segments[len-1].y;
+
+	for (i = 1; i < len - 1; i++) {
+		/* If value is identical, no need to interpolate */
+		if (value == segments[i].x)
+			return segments[i].y;
+		if (value > segments[i].x)
+			break;
+	}
+
+	/* Linear interpolation between the two (x,y) points */
+	dy = segments[i - 1].y - segments[i].y;
+	dx = segments[i - 1].x - segments[i].x;
+
+	tmp64 = value - segments[i].x;
+	tmp64 *= dy;
+	do_div(tmp64, dx);
+	ret = segments[i].y + tmp64;
+
+	return ret;
+}
+
+/* FIXME: may require changes - this one was borrowed from dib8000 */
+static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
+{
+	struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+	u64 time_us, tmp64;
+	u32 tmp, denom;
+	int guard, rate_num, rate_denum = 1, bits_per_symbol;
+	int interleaving = 0, fft_div;
+
+	switch (c->guard_interval) {
+	case GUARD_INTERVAL_1_4:
+		guard = 4;
+		break;
+	case GUARD_INTERVAL_1_8:
+		guard = 8;
+		break;
+	case GUARD_INTERVAL_1_16:
+		guard = 16;
+		break;
+	default:
+	case GUARD_INTERVAL_1_32:
+		guard = 32;
+		break;
+	}
+
+	switch (c->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		fft_div = 4;
+		break;
+	case TRANSMISSION_MODE_4K:
+		fft_div = 2;
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		fft_div = 1;
+		break;
+	}
+
+	switch (c->modulation) {
+	case DQPSK:
+	case QPSK:
+		bits_per_symbol = 2;
+		break;
+	case QAM_16:
+		bits_per_symbol = 4;
+		break;
+	default:
+	case QAM_64:
+		bits_per_symbol = 6;
+		break;
+	}
+
+	switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
+	case FEC_1_2:
+		rate_num = 1;
+		rate_denum = 2;
+		break;
+	case FEC_2_3:
+		rate_num = 2;
+		rate_denum = 3;
+		break;
+	case FEC_3_4:
+		rate_num = 3;
+		rate_denum = 4;
+		break;
+	case FEC_5_6:
+		rate_num = 5;
+		rate_denum = 6;
+		break;
+	default:
+	case FEC_7_8:
+		rate_num = 7;
+		rate_denum = 8;
+		break;
+	}
+
+	interleaving = interleaving;
+
+	denom = bits_per_symbol * rate_num * fft_div * 384;
+
+	/* If calculus gets wrong, wait for 1s for the next stats */
+	if (!denom)
+		return 0;
+
+	/* Estimate the period for the total bit rate */
+	time_us = rate_denum * (1008 * 1562500L);
+	tmp64 = time_us;
+	do_div(tmp64, guard);
+	time_us = time_us + tmp64;
+	time_us += denom / 2;
+	do_div(time_us, denom);
+
+	tmp = 1008 * 96 * interleaving;
+	time_us += tmp + tmp / guard;
+
+	return time_us;
+}
+
+static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+	int i;
+	int show_per_stats = 0;
+	u32 time_us = 0, val, snr;
+	u64 blocks, ucb;
+	s32 db;
+	u16 strength;
+
+	/* Get Signal strength */
+	dib7000p_read_signal_strength(demod, &strength);
+	val = strength;
+	db = interpolate_value(val,
+			       strength_to_db_table,
+			       ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
+	c->strength.stat[0].svalue = db;
+
+	/* UCB/BER/CNR measures require lock */
+	if (!(stat & FE_HAS_LOCK)) {
+		c->cnr.len = 1;
+		c->block_count.len = 1;
+		c->block_error.len = 1;
+		c->post_bit_error.len = 1;
+		c->post_bit_count.len = 1;
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		return 0;
+	}
+
+	/* Check if time for stats was elapsed */
+	if (time_after(jiffies, state->per_jiffies_stats)) {
+		state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
+
+		/* Get SNR */
+		snr = dib7000p_get_snr(demod);
+		if (snr)
+			snr = (1000L * snr) >> 24;
+		else
+			snr = 0;
+		c->cnr.stat[0].svalue = snr;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
+		/* Get UCB measures */
+		dib7000p_read_unc_blocks(demod, &val);
+		ucb = val - state->old_ucb;
+		if (val < state->old_ucb)
+			ucb += 0x100000000LL;
+
+		c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[0].uvalue = ucb;
+
+		/* Estimate the number of packets based on bitrate */
+		if (!time_us)
+			time_us = dib7000p_get_time_us(demod, -1);
+
+		if (time_us) {
+			blocks = 1250000ULL * 1000000ULL;
+			do_div(blocks, time_us * 8 * 204);
+			c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+			c->block_count.stat[0].uvalue += blocks;
+		}
+
+		show_per_stats = 1;
+	}
+
+	/* Get post-BER measures */
+	if (time_after(jiffies, state->ber_jiffies_stats)) {
+		time_us = dib7000p_get_time_us(demod, -1);
+		state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
+
+		dprintk("Next all layers stats available in %u us.", time_us);
+
+		dib7000p_read_ber(demod, &val);
+		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[0].uvalue += val;
+
+		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[0].uvalue += 100000000;
+	}
+
+	/* Get PER measures */
+	if (show_per_stats) {
+		dib7000p_read_unc_blocks(demod, &val);
+
+		c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[0].uvalue += val;
+
+		time_us = dib7000p_get_time_us(demod, i);
+		if (time_us) {
+			blocks = 1250000ULL * 1000000ULL;
+			do_div(blocks, time_us * 8 * 204);
+			c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+			c->block_count.stat[0].uvalue += blocks;
+		}
+	}
+	return 0;
+}
+
 static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 1000;
@@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_
 	kfree(st);
 }
 
-int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
 {
 	u8 *tx, *rx;
 	struct i2c_msg msg[2] = {
@@ -1688,16 +2039,14 @@ rx_memory_error:
 	kfree(tx);
 	return ret;
 }
-EXPORT_SYMBOL(dib7000pc_detection);
 
-struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
 {
 	struct dib7000p_state *st = demod->demodulator_priv;
 	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
 }
-EXPORT_SYMBOL(dib7000p_get_i2c_master);
 
-int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 val = dib7000p_read_word(state, 235) & 0xffef;
@@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_
 	dprintk("PID filter enabled %d", onoff);
 	return dib7000p_write_word(state, 235, val);
 }
-EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
 
-int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+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);
 	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
 }
-EXPORT_SYMBOL(dib7000p_pid_filter);
 
-int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
 {
 	struct dib7000p_state *dpst;
 	int k = 0;
@@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_
 	kfree(dpst);
 	return 0;
 }
-EXPORT_SYMBOL(dib7000p_i2c_enumeration);
 
 static const s32 lut_1000ln_mant[] = {
 	6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
@@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tune
 	.functionality = dib7000p_i2c_func,
 };
 
-struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
 {
 	struct dib7000p_state *st = fe->demodulator_priv;
 	return &st->dib7090_tuner_adap;
 }
-EXPORT_SYMBOL(dib7090_get_i2c_tuner);
 
 static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
 {
@@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struc
 	return ret;
 }
 
-int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 en_cur_state;
@@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_front
 
 	return 0;
 }
-EXPORT_SYMBOL(dib7090_tuner_sleep);
 
-int dib7090_get_adc_power(struct dvb_frontend *fe)
+static int dib7090_get_adc_power(struct dvb_frontend *fe)
 {
 	return dib7000p_get_adc_power(fe);
 }
-EXPORT_SYMBOL(dib7090_get_adc_power);
 
-int dib7090_slave_reset(struct dvb_frontend *fe)
+static int dib7090_slave_reset(struct dvb_frontend *fe)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 reg;
@@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_front
 	dib7000p_write_word(state, 1032, 0xffff);
 	return 0;
 }
-EXPORT_SYMBOL(dib7090_slave_reset);
 
 static struct dvb_frontend_ops dib7000p_ops;
-struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
 	struct dvb_frontend *demod;
 	struct dib7000p_state *st;
@@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(str
 
 	dib7000p_demod_reset(st);
 
+	dib7000p_reset_stats(demod);
+
 	if (st->version == SOC7090) {
 		dib7090_set_output_mode(demod, st->cfg.output_mode);
 		dib7090_set_diversity_in(demod, 0);
@@ -2434,6 +2778,31 @@ error:
 	kfree(st);
 	return NULL;
 }
+
+void *dib7000p_attach(struct dib7000p_ops *ops)
+{
+	if (!ops)
+		return NULL;
+
+	ops->slave_reset = dib7090_slave_reset;
+	ops->get_adc_power = dib7090_get_adc_power;
+	ops->dib7000pc_detection = dib7000pc_detection;
+	ops->get_i2c_tuner = dib7090_get_i2c_tuner;
+	ops->tuner_sleep = dib7090_tuner_sleep;
+	ops->init = dib7000p_init;
+	ops->set_agc1_min = dib7000p_set_agc1_min;
+	ops->set_gpio = dib7000p_set_gpio;
+	ops->i2c_enumeration = dib7000p_i2c_enumeration;
+	ops->pid_filter = dib7000p_pid_filter;
+	ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
+	ops->get_i2c_master = dib7000p_get_i2c_master;
+	ops->update_pll = dib7000p_update_pll;
+	ops->ctrl_timf = dib7000p_ctrl_timf;
+	ops->get_agc_values = dib7000p_get_agc_values;
+	ops->set_wbd_ref = dib7000p_set_wbd_ref;
+
+	return ops;
+}
 EXPORT_SYMBOL(dib7000p_attach);
 
 static struct dvb_frontend_ops dib7000p_ops = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000p.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000p.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib7000p.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib7000p.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,121 +46,34 @@ struct dib7000p_config {
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB7000P)
-extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
-extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
-extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
-extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib7090_get_adc_power(struct dvb_frontend *fe);
-extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib7090_slave_reset(struct dvb_frontend *fe);
-extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+struct dib7000p_ops {
+	int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
+	int (*get_agc_values)(struct dvb_frontend *fe,
 		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
-extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
-#else
-static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-
-static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
+	int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
+	int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
+	int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
+	u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
+	int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
+	struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
+	int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+	int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+	int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+	struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+	int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+	int (*get_adc_power)(struct dvb_frontend *fe);
+	int (*slave_reset)(struct dvb_frontend *fe);
+	struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+};
 
-static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+#if IS_ENABLED(CONFIG_DVB_DIB7000P)
+void *dib7000p_attach(struct dib7000p_ops *ops);
+#else
+static inline void *dib7000p_attach(struct dib7000p_ops *ops)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-
-static inline int dib7090_slave_reset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
-		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
 #endif
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib8000.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib8000.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib8000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib8000.c	2014-09-28 17:29:07.000000000 -0400
@@ -115,7 +115,7 @@ struct dib8000_state {
 	u16 found_guard;
 	u8 subchannel;
 	u8 symbol_duration;
-	u32 timeout;
+	unsigned long timeout;
 	u8 longest_intlv_layer;
 	u16 output_mode;
 
@@ -588,8 +588,8 @@ static int dib8000_set_adc_state(struct
 		break;
 
 	case DIBX000_ADC_OFF:	// leave the VBG voltage on
-		reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
-		reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+		reg_907 = (1 << 13) | (1 << 12);
+		reg_908 = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1);
 		break;
 
 	case DIBX000_VBG_ENABLE:
@@ -656,7 +656,7 @@ static int dib8000_sad_calib(struct dib8
 	return 0;
 }
 
-int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	if (value > 4095)
@@ -664,7 +664,6 @@ int dib8000_set_wbd_ref(struct dvb_front
 	state->wbd_ref = value;
 	return dib8000_write_word(state, 106, value);
 }
-EXPORT_SYMBOL(dib8000_set_wbd_ref);
 
 static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
 {
@@ -739,7 +738,7 @@ static void dib8000_reset_pll(struct dib
 	dib8000_reset_pll_common(state, pll);
 }
 
-int dib8000_update_pll(struct dvb_frontend *fe,
+static int dib8000_update_pll(struct dvb_frontend *fe,
 		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
@@ -815,8 +814,6 @@ int dib8000_update_pll(struct dvb_fronte
 
 	return 0;
 }
-EXPORT_SYMBOL(dib8000_update_pll);
-
 
 static int dib8000_reset_gpio(struct dib8000_state *st)
 {
@@ -849,13 +846,12 @@ static int dib8000_cfg_gpio(struct dib80
 	return 0;
 }
 
-int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	return dib8000_cfg_gpio(state, num, dir, val);
 }
 
-EXPORT_SYMBOL(dib8000_set_gpio);
 static const u16 dib8000_defaults[] = {
 	/* auto search configuration - lock0 by default waiting
 	 * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
@@ -1054,6 +1050,7 @@ static int dib8000_reset(struct dvb_fron
 	dib8000_write_word(state, 770, 0xffff);
 	dib8000_write_word(state, 771, 0xffff);
 	dib8000_write_word(state, 772, 0xfffc);
+	dib8000_write_word(state, 898, 0x000c);	/* restart sad */
 	if (state->revision == 0x8090)
 		dib8000_write_word(state, 1280, 0x0045);
 	else
@@ -1228,20 +1225,19 @@ static int dib8000_set_agc_config(struct
 	return 0;
 }
 
-void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+static void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	dib8000_set_adc_state(state, DIBX000_ADC_ON);
 	dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
 }
-EXPORT_SYMBOL(dib8000_pwm_agc_reset);
 
 static int dib8000_agc_soft_split(struct dib8000_state *state)
 {
 	u16 agc, split_offset;
 
 	if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
-		return FE_CALLBACK_TIME_NEVER;
+		return 0;
 
 	// n_agc_global
 	agc = dib8000_read_word(state, 390);
@@ -1881,14 +1877,13 @@ static struct i2c_algorithm dib8096p_tun
 	.functionality = dib8096p_i2c_func,
 };
 
-struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
 	return &st->dib8096p_tuner_adap;
 }
-EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
 
-int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 en_cur_state;
@@ -1912,14 +1907,13 @@ int dib8096p_tuner_sleep(struct dvb_fron
 
 	return 0;
 }
-EXPORT_SYMBOL(dib8096p_tuner_sleep);
 
 static const s32 lut_1000ln_mant[] =
 {
 	908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
 };
 
-s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+static s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
@@ -1937,9 +1931,8 @@ s32 dib8000_get_adc_power(struct dvb_fro
 	}
 	return val;
 }
-EXPORT_SYMBOL(dib8000_get_adc_power);
 
-int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+static int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	int val = 0;
@@ -1957,7 +1950,6 @@ int dib8090p_get_dc_power(struct dvb_fro
 
 	return val;
 }
-EXPORT_SYMBOL(dib8090p_get_dc_power);
 
 static void dib8000_update_timf(struct dib8000_state *state)
 {
@@ -1968,7 +1960,7 @@ static void dib8000_update_timf(struct d
 	dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
 }
 
-u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+static u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 
@@ -1986,21 +1978,11 @@ u32 dib8000_ctrl_timf(struct dvb_fronten
 
 	return state->timf;
 }
-EXPORT_SYMBOL(dib8000_ctrl_timf);
 
 static const u16 adc_target_16dB[11] = {
-	(1 << 13) - 825 - 117,
-	(1 << 13) - 837 - 117,
-	(1 << 13) - 811 - 117,
-	(1 << 13) - 766 - 117,
-	(1 << 13) - 737 - 117,
-	(1 << 13) - 693 - 117,
-	(1 << 13) - 648 - 117,
-	(1 << 13) - 619 - 117,
-	(1 << 13) - 575 - 117,
-	(1 << 13) - 531 - 117,
-	(1 << 13) - 501 - 117
+	7250, 7238, 7264, 7309, 7338, 7382, 7427, 7456, 7500, 7544, 7574
 };
+
 static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
 
 static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
@@ -2043,9 +2025,8 @@ static u16 dib8000_set_layer(struct dib8
 			break;
 	}
 
-	if ((c->layer[layer_index].interleaving > 0) && ((c->layer[layer_index].interleaving <= 3) || (c->layer[layer_index].interleaving == 4 && c->isdbt_sb_mode == 1)))
-		time_intlv = c->layer[layer_index].interleaving;
-	else
+	time_intlv = fls(c->layer[layer_index].interleaving);
+	if (time_intlv > 3 && !(time_intlv == 4 && c->isdbt_sb_mode == 1))
 		time_intlv = 0;
 
 	dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
@@ -2362,6 +2343,9 @@ static void dib8000_set_isdbt_common_cha
 	int init_prbs;
 	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
 
+	if (autosearching)
+		c->isdbt_partial_reception = 1;
+
 	/* P_mode */
 	dib8000_write_word(state, 10, (seq << 4));
 
@@ -2856,12 +2840,12 @@ static void dib8000_set_sync_wait(struct
 	dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
 }
 
-static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
+static unsigned long dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
 {
 	if (mode == SYMBOL_DEPENDENT_ON)
-		return systime() + (delay * state->symbol_duration);
-	else
-		return systime() + delay;
+		delay *= state->symbol_duration;
+
+	return jiffies + usecs_to_jiffies(delay * 100);
 }
 
 static s32 dib8000_get_status(struct dvb_frontend *fe)
@@ -2870,21 +2854,19 @@ static s32 dib8000_get_status(struct dvb
 	return state->status;
 }
 
-enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+static enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	return state->tune_state;
 }
-EXPORT_SYMBOL(dib8000_get_tune_state);
 
-int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+static int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 
 	state->tune_state = tune_state;
 	return 0;
 }
-EXPORT_SYMBOL(dib8000_set_tune_state);
 
 static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
 {
@@ -3015,8 +2997,8 @@ static int dib8000_tune(struct dvb_front
 	u16 locks, deeper_interleaver = 0, i;
 	int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
 
-	u32 *timeout = &state->timeout;
-	u32 now = systime();
+	unsigned long *timeout = &state->timeout;
+	unsigned long now = jiffies;
 #ifdef DIB8000_AGC_FREEZE
 	u16 agc1, agc2;
 #endif
@@ -3026,318 +3008,327 @@ 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 systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
+		dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu",
+			state->channel_parameters_set, *tune_state, state->autosearch_state, now);
 #endif
 
 	switch (*tune_state) {
 	case CT_DEMOD_START: /* 30 */
-			dib8000_reset_stats(fe);
+		dib8000_reset_stats(fe);
 
-			if (state->revision == 0x8090)
-				dib8090p_init_sdram(state);
-			state->status = FE_STATUS_TUNE_PENDING;
-			state->channel_parameters_set = is_manual_mode(c);
+		if (state->revision == 0x8090)
+			dib8090p_init_sdram(state);
+		state->status = FE_STATUS_TUNE_PENDING;
+		state->channel_parameters_set = is_manual_mode(c);
 
-			dprintk("Tuning channel on %s search mode",
-				state->channel_parameters_set ? "manual" : "auto");
+		dprintk("Tuning channel on %s search mode",
+			state->channel_parameters_set ? "manual" : "auto");
 
-			dib8000_viterbi_state(state, 0); /* force chan dec in restart */
+		dib8000_viterbi_state(state, 0); /* force chan dec in restart */
 
-			/* Layer monitor */
-			dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
+		/* Layer monitor */
+		dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
 
-			dib8000_set_frequency_offset(state);
-			dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
+		dib8000_set_frequency_offset(state);
+		dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
 
-			if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
+		if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
 #ifdef DIB8000_AGC_FREEZE
-				if (state->revision != 0x8090) {
-					state->agc1_max = dib8000_read_word(state, 108);
-					state->agc1_min = dib8000_read_word(state, 109);
-					state->agc2_max = dib8000_read_word(state, 110);
-					state->agc2_min = dib8000_read_word(state, 111);
-					agc1 = dib8000_read_word(state, 388);
-					agc2 = dib8000_read_word(state, 389);
-					dib8000_write_word(state, 108, agc1);
-					dib8000_write_word(state, 109, agc1);
-					dib8000_write_word(state, 110, agc2);
-					dib8000_write_word(state, 111, agc2);
-				}
-#endif
-				state->autosearch_state = AS_SEARCHING_FFT;
-				state->found_nfft = TRANSMISSION_MODE_AUTO;
-				state->found_guard = GUARD_INTERVAL_AUTO;
-				*tune_state = CT_DEMOD_SEARCH_NEXT;
-			} else { /* we already know the channel struct so TUNE only ! */
-				state->autosearch_state = AS_DONE;
-				*tune_state = CT_DEMOD_STEP_3;
+			if (state->revision != 0x8090) {
+				state->agc1_max = dib8000_read_word(state, 108);
+				state->agc1_min = dib8000_read_word(state, 109);
+				state->agc2_max = dib8000_read_word(state, 110);
+				state->agc2_min = dib8000_read_word(state, 111);
+				agc1 = dib8000_read_word(state, 388);
+				agc2 = dib8000_read_word(state, 389);
+				dib8000_write_word(state, 108, agc1);
+				dib8000_write_word(state, 109, agc1);
+				dib8000_write_word(state, 110, agc2);
+				dib8000_write_word(state, 111, agc2);
 			}
-			state->symbol_duration = dib8000_get_symbol_duration(state);
-			break;
+#endif
+			state->autosearch_state = AS_SEARCHING_FFT;
+			state->found_nfft = TRANSMISSION_MODE_AUTO;
+			state->found_guard = GUARD_INTERVAL_AUTO;
+			*tune_state = CT_DEMOD_SEARCH_NEXT;
+		} else { /* we already know the channel struct so TUNE only ! */
+			state->autosearch_state = AS_DONE;
+			*tune_state = CT_DEMOD_STEP_3;
+		}
+		state->symbol_duration = dib8000_get_symbol_duration(state);
+		break;
 
 	case CT_DEMOD_SEARCH_NEXT: /* 51 */
-			dib8000_autosearch_start(fe);
-			if (state->revision == 0x8090)
-				ret = 50;
-			else
-				ret = 15;
-			*tune_state = CT_DEMOD_STEP_1;
-			break;
+		dib8000_autosearch_start(fe);
+		if (state->revision == 0x8090)
+			ret = 50;
+		else
+			ret = 15;
+		*tune_state = CT_DEMOD_STEP_1;
+		break;
 
 	case CT_DEMOD_STEP_1: /* 31 */
-			switch (dib8000_autosearch_irq(fe)) {
-			case 1: /* fail */
-					state->status = FE_STATUS_TUNE_FAILED;
-					state->autosearch_state = AS_DONE;
-					*tune_state = CT_DEMOD_STOP; /* else we are done here */
-					break;
-			case 2: /* Succes */
-					state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
-					*tune_state = CT_DEMOD_STEP_3;
-					if (state->autosearch_state == AS_SEARCHING_GUARD)
-						*tune_state = CT_DEMOD_STEP_2;
-					else
-						state->autosearch_state = AS_DONE;
-					break;
-			case 3: /* Autosearch FFT max correlation endded */
-					*tune_state = CT_DEMOD_STEP_2;
-					break;
-			}
+		switch (dib8000_autosearch_irq(fe)) {
+		case 1: /* fail */
+			state->status = FE_STATUS_TUNE_FAILED;
+			state->autosearch_state = AS_DONE;
+			*tune_state = CT_DEMOD_STOP; /* else we are done here */
+			break;
+		case 2: /* Succes */
+			state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
+			*tune_state = CT_DEMOD_STEP_3;
+			if (state->autosearch_state == AS_SEARCHING_GUARD)
+				*tune_state = CT_DEMOD_STEP_2;
+			else
+				state->autosearch_state = AS_DONE;
 			break;
+		case 3: /* Autosearch FFT max correlation endded */
+			*tune_state = CT_DEMOD_STEP_2;
+			break;
+		}
+		break;
 
 	case CT_DEMOD_STEP_2:
-			switch (state->autosearch_state) {
-			case AS_SEARCHING_FFT:
-					/* searching for the correct FFT */
-				if (state->revision == 0x8090) {
-					corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
-					corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
-					corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
-				} else {
-					corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
-					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]); */
-
-					max_value = 0;
-					for (find_index = 1 ; find_index < 3 ; find_index++) {
-						if (corm[max_value] < corm[find_index])
-							max_value = find_index ;
-					}
-
-					switch (max_value) {
-					case 0:
-							state->found_nfft = TRANSMISSION_MODE_2K;
-							break;
-					case 1:
-							state->found_nfft = TRANSMISSION_MODE_4K;
-							break;
-					case 2:
-					default:
-							state->found_nfft = TRANSMISSION_MODE_8K;
-							break;
-					}
-					/* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+		switch (state->autosearch_state) {
+		case AS_SEARCHING_FFT:
+			/* searching for the correct FFT */
+			if (state->revision == 0x8090) {
+				corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+				corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+				corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
+			} else {
+				corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
+				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]); */
 
-					*tune_state = CT_DEMOD_SEARCH_NEXT;
-					state->autosearch_state = AS_SEARCHING_GUARD;
-					if (state->revision == 0x8090)
-						ret = 50;
-					else
-						ret = 10;
-					break;
-			case AS_SEARCHING_GUARD:
-					/* searching for the correct guard interval */
-					if (state->revision == 0x8090)
-						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); */
+			max_value = 0;
+			for (find_index = 1 ; find_index < 3 ; find_index++) {
+				if (corm[max_value] < corm[find_index])
+					max_value = find_index ;
+			}
 
-					*tune_state = CT_DEMOD_STEP_3;
-					break;
+			switch (max_value) {
+			case 0:
+				state->found_nfft = TRANSMISSION_MODE_2K;
+				break;
+			case 1:
+				state->found_nfft = TRANSMISSION_MODE_4K;
+				break;
+			case 2:
 			default:
-					/* the demod should never be in this state */
-					state->status = FE_STATUS_TUNE_FAILED;
-					state->autosearch_state = AS_DONE;
-					*tune_state = CT_DEMOD_STOP; /* else we are done here */
-					break;
+				state->found_nfft = TRANSMISSION_MODE_8K;
+				break;
 			}
+			/* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+
+			*tune_state = CT_DEMOD_SEARCH_NEXT;
+			state->autosearch_state = AS_SEARCHING_GUARD;
+			if (state->revision == 0x8090)
+				ret = 50;
+			else
+				ret = 10;
 			break;
+		case AS_SEARCHING_GUARD:
+			/* searching for the correct guard interval */
+			if (state->revision == 0x8090)
+				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); */
 
-	case CT_DEMOD_STEP_3: /* 33 */
-			state->symbol_duration = dib8000_get_symbol_duration(state);
-			dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
-			dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
-			*tune_state = CT_DEMOD_STEP_4;
+			*tune_state = CT_DEMOD_STEP_3;
+			break;
+		default:
+			/* the demod should never be in this state */
+			state->status = FE_STATUS_TUNE_FAILED;
+			state->autosearch_state = AS_DONE;
+			*tune_state = CT_DEMOD_STOP; /* else we are done here */
 			break;
+		}
+		break;
+
+	case CT_DEMOD_STEP_3: /* 33 */
+		dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
+		dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
+		*tune_state = CT_DEMOD_STEP_4;
+		break;
 
 	case CT_DEMOD_STEP_4: /* (34) */
-			dib8000_demod_restart(state);
+		dib8000_demod_restart(state);
 
-			dib8000_set_sync_wait(state);
-			dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+		dib8000_set_sync_wait(state);
+		dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
 
-			locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
-			/* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
-			*timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
-			*tune_state = CT_DEMOD_STEP_5;
-			break;
+		locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
+		/* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
+		*timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
+		*tune_state = CT_DEMOD_STEP_5;
+		break;
 
 	case CT_DEMOD_STEP_5: /* (35) */
-			locks = dib8000_read_lock(fe);
-			if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
-				dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
-				if (!state->differential_constellation) {
-					/* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
-					*timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
-					*tune_state = CT_DEMOD_STEP_7;
-				} else {
-					*tune_state = CT_DEMOD_STEP_8;
-				}
-			} else if (now > *timeout) {
-				*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+		locks = dib8000_read_lock(fe);
+		if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
+			dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
+			if (!state->differential_constellation) {
+				/* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
+				*timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
+				*tune_state = CT_DEMOD_STEP_7;
+			} else {
+				*tune_state = CT_DEMOD_STEP_8;
 			}
-			break;
+		} else if (time_after(now, *timeout)) {
+			*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+		}
+		break;
 
 	case CT_DEMOD_STEP_6: /* (36)  if there is an input (diversity) */
-			if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
-				/* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
-				if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
-					*tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
-				else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
-					*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
-					dib8000_viterbi_state(state, 1); /* start viterbi chandec */
-					dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
-					state->status = FE_STATUS_TUNE_FAILED;
-				}
-			} else {
+		if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
+			/* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
+			if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
+				*tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
+			else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
+				*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
 				dib8000_viterbi_state(state, 1); /* start viterbi chandec */
 				dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
-				*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
 				state->status = FE_STATUS_TUNE_FAILED;
 			}
-			break;
+		} else {
+			dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+			dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+			*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
+			state->status = FE_STATUS_TUNE_FAILED;
+		}
+		break;
 
 	case CT_DEMOD_STEP_7: /* 37 */
-			locks = dib8000_read_lock(fe);
-			if (locks & (1<<10)) { /* lmod4_lock */
-				ret = 14; /* wait for 14 symbols */
-				*tune_state = CT_DEMOD_STEP_8;
-			} else if (now > *timeout)
-				*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
-			break;
+		locks = dib8000_read_lock(fe);
+		if (locks & (1<<10)) { /* lmod4_lock */
+			ret = 14; /* wait for 14 symbols */
+			*tune_state = CT_DEMOD_STEP_8;
+		} else if (time_after(now, *timeout))
+			*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+		break;
 
 	case CT_DEMOD_STEP_8: /* 38 */
-			dib8000_viterbi_state(state, 1); /* start viterbi chandec */
-			dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+		dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+		dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
 
-			/* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
-			if (c->isdbt_sb_mode
-			    && c->isdbt_sb_subchannel < 14
-			    && !state->differential_constellation) {
-				state->subchannel = 0;
-				*tune_state = CT_DEMOD_STEP_11;
-			} else {
-				*tune_state = CT_DEMOD_STEP_9;
-				state->status = FE_STATUS_LOCKED;
-			}
-			break;
+		/* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
+		if (c->isdbt_sb_mode
+		    && c->isdbt_sb_subchannel < 14
+		    && !state->differential_constellation) {
+			state->subchannel = 0;
+			*tune_state = CT_DEMOD_STEP_11;
+		} else {
+			*tune_state = CT_DEMOD_STEP_9;
+			state->status = FE_STATUS_LOCKED;
+		}
+		break;
 
 	case CT_DEMOD_STEP_9: /* 39 */
-			if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
-				/* 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);
-						if (c->layer[i].segment_count > 0) { /* valid layer */
-							deeper_interleaver = c->layer[0].interleaving;
-							state->longest_intlv_layer = i;
-						}
+		if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
+			/* 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);
+					if (c->layer[i].segment_count > 0) { /* valid layer */
+						deeper_interleaver = c->layer[0].interleaving;
+						state->longest_intlv_layer = i;
 					}
 				}
+			}
 
-				if (deeper_interleaver == 0)
-					locks = 2; /* locks is the tmp local variable name */
-				else if (deeper_interleaver == 3)
-					locks = 8;
-				else
-					locks = 2 * deeper_interleaver;
+			if (deeper_interleaver == 0)
+				locks = 2; /* locks is the tmp local variable name */
+			else if (deeper_interleaver == 3)
+				locks = 8;
+			else
+				locks = 2 * deeper_interleaver;
 
-				if (state->diversity_onoff != 0) /* because of diversity sync */
-					locks *= 2;
+			if (state->diversity_onoff != 0) /* because of diversity sync */
+				locks *= 2;
 
-				*timeout = now + (2000 * 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 = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
+			*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",
+				deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
 
-				*tune_state = CT_DEMOD_STEP_10;
-			} else
-				*tune_state = CT_DEMOD_STOP;
-			break;
+			*tune_state = CT_DEMOD_STEP_10;
+		} else
+			*tune_state = CT_DEMOD_STOP;
+		break;
 
 	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("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
-				if (c->isdbt_sb_mode
-				    && c->isdbt_sb_subchannel < 14
-				    && !state->differential_constellation)
-					/* signal to the upper layer, that there was a channel found and the parameters can be read */
-					state->status = FE_STATUS_DEMOD_SUCCESS;
-				else
+		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",
+				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");
+			if (c->isdbt_sb_mode
+			    && c->isdbt_sb_subchannel < 14
+			    && !state->differential_constellation)
+				/* signal to the upper layer, that there was a channel found and the parameters can be read */
+				state->status = FE_STATUS_DEMOD_SUCCESS;
+			else
+				state->status = FE_STATUS_DATA_LOCKED;
+			*tune_state = CT_DEMOD_STOP;
+		} else if (time_after(now, *timeout)) {
+			if (c->isdbt_sb_mode
+			    && c->isdbt_sb_subchannel < 14
+			    && !state->differential_constellation) { /* continue to try init prbs autosearch */
+				state->subchannel += 3;
+				*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",
+						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",
+						c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
+
 					state->status = FE_STATUS_DATA_LOCKED;
+				} else
+					state->status = FE_STATUS_TUNE_FAILED;
 				*tune_state = CT_DEMOD_STOP;
-			} else if (now > *timeout) {
-				if (c->isdbt_sb_mode
-				    && c->isdbt_sb_subchannel < 14
-				    && !state->differential_constellation) { /* continue to try init prbs autosearch */
-					state->subchannel += 3;
-					*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("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
-						state->status = FE_STATUS_DATA_LOCKED;
-					} else
-						state->status = FE_STATUS_TUNE_FAILED;
-					*tune_state = CT_DEMOD_STOP;
-				}
 			}
-			break;
+		}
+		break;
 
 	case CT_DEMOD_STEP_11:  /* 41 : init prbs autosearch */
-			if (state->subchannel <= 41) {
-				dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
-				*tune_state = CT_DEMOD_STEP_9;
-			} else {
-				*tune_state = CT_DEMOD_STOP;
-				state->status = FE_STATUS_TUNE_FAILED;
-			}
-			break;
+		if (state->subchannel <= 41) {
+			dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+			*tune_state = CT_DEMOD_STEP_9;
+		} else {
+			*tune_state = CT_DEMOD_STOP;
+			state->status = FE_STATUS_TUNE_FAILED;
+		}
+		break;
 
 	default:
-			break;
+		break;
 	}
 
 	/* tuning is finished - cleanup the demod */
 	switch (*tune_state) {
 	case CT_DEMOD_STOP: /* (42) */
 #ifdef DIB8000_AGC_FREEZE
-			if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
-				dib8000_write_word(state, 108, state->agc1_max);
-				dib8000_write_word(state, 109, state->agc1_min);
-				dib8000_write_word(state, 110, state->agc2_max);
-				dib8000_write_word(state, 111, state->agc2_min);
-				state->agc1_max = 0;
-				state->agc1_min = 0;
-				state->agc2_max = 0;
-				state->agc2_min = 0;
-			}
+		if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
+			dib8000_write_word(state, 108, state->agc1_max);
+			dib8000_write_word(state, 109, state->agc1_min);
+			dib8000_write_word(state, 110, state->agc2_max);
+			dib8000_write_word(state, 111, state->agc2_min);
+			state->agc1_max = 0;
+			state->agc1_min = 0;
+			state->agc2_max = 0;
+			state->agc2_min = 0;
+		}
 #endif
-			ret = FE_CALLBACK_TIME_NEVER;
-			break;
+		ret = 0;
+		break;
 	default:
-			break;
+		break;
 	}
 
 	if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
@@ -3408,7 +3399,7 @@ static int dib8000_get_frontend(struct d
 	if (!(stat & FE_HAS_SYNC))
 		return 0;
 
-	dprintk("TMCC lock");
+	dprintk("dib8000_get_frontend: TMCC lock");
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
 		if (stat&FE_HAS_SYNC) {
@@ -3444,91 +3435,117 @@ static int dib8000_get_frontend(struct d
 	switch ((val & 0x30) >> 4) {
 	case 1:
 		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+		dprintk("dib8000_get_frontend: transmission mode 2K");
+		break;
+	case 2:
+		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
+		dprintk("dib8000_get_frontend: transmission mode 4K");
 		break;
 	case 3:
 	default:
 		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		dprintk("dib8000_get_frontend: transmission mode 8K");
 		break;
 	}
 
 	switch (val & 0x3) {
 	case 0:
 		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
-		dprintk("dib8000_get_frontend GI = 1/32 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/32 ");
 		break;
 	case 1:
 		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
-		dprintk("dib8000_get_frontend GI = 1/16 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/16 ");
 		break;
 	case 2:
-		dprintk("dib8000_get_frontend GI = 1/8 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/8 ");
 		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
 		break;
 	case 3:
-		dprintk("dib8000_get_frontend GI = 1/4 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/4 ");
 		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
 		break;
 	}
 
 	val = dib8000_read_word(state, 505);
 	fe->dtv_property_cache.isdbt_partial_reception = val & 1;
-	dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
+	dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
 
 	for (i = 0; i < 3; i++) {
-		val = dib8000_read_word(state, 493 + i);
-		fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
-		dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
+		int show;
+
+		val = dib8000_read_word(state, 493 + i) & 0x0f;
+		fe->dtv_property_cache.layer[i].segment_count = val;
+
+		if (val == 0 || val > 13)
+			show = 0;
+		else
+			show = 1;
+
+		if (show)
+			dprintk("dib8000_get_frontend: Layer %d segments = %d ",
+				i, fe->dtv_property_cache.layer[i].segment_count);
 
 		val = dib8000_read_word(state, 499 + i) & 0x3;
 		/* Interleaving can be 0, 1, 2 or 4 */
 		if (val == 3)
 			val = 4;
 		fe->dtv_property_cache.layer[i].interleaving = val;
-		dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ",
-			i, fe->dtv_property_cache.layer[i].interleaving);
+		if (show)
+			dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ",
+				i, fe->dtv_property_cache.layer[i].interleaving);
 
 		val = dib8000_read_word(state, 481 + i);
 		switch (val & 0x7) {
 		case 1:
 			fe->dtv_property_cache.layer[i].fec = FEC_1_2;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i);
 			break;
 		case 2:
 			fe->dtv_property_cache.layer[i].fec = FEC_2_3;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i);
 			break;
 		case 3:
 			fe->dtv_property_cache.layer[i].fec = FEC_3_4;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i);
 			break;
 		case 5:
 			fe->dtv_property_cache.layer[i].fec = FEC_5_6;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i);
 			break;
 		default:
 			fe->dtv_property_cache.layer[i].fec = FEC_7_8;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i);
 			break;
 		}
 
 		val = dib8000_read_word(state, 487 + i);
 		switch (val & 0x3) {
 		case 0:
-			dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
 			fe->dtv_property_cache.layer[i].modulation = DQPSK;
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d DQPSK ", i);
 			break;
 		case 1:
 			fe->dtv_property_cache.layer[i].modulation = QPSK;
-			dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d QPSK ", i);
 			break;
 		case 2:
 			fe->dtv_property_cache.layer[i].modulation = QAM_16;
-			dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d QAM16 ", i);
 			break;
 		case 3:
 		default:
-			dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
 			fe->dtv_property_cache.layer[i].modulation = QAM_64;
+			if (show)
+				dprintk("dib8000_get_frontend: Layer %d QAM64 ", i);
 			break;
 		}
 	}
@@ -3554,9 +3571,9 @@ static int dib8000_set_frontend(struct d
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
-	int l, i, active, time, time_slave = FE_CALLBACK_TIME_NEVER;
+	int l, i, active, time, time_slave = 0;
 	u8 exit_condition, index_frontend;
-	u32 delay, callback_time;
+	unsigned long delay, callback_time;
 
 	if (c->frequency == 0) {
 		dprintk("dib8000: must at least specify frequency ");
@@ -3608,15 +3625,24 @@ static int dib8000_set_frontend(struct d
 		time = dib8000_agc_startup(state->fe[0]);
 		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 			time_slave = dib8000_agc_startup(state->fe[index_frontend]);
-			if (time == FE_CALLBACK_TIME_NEVER)
+			if (time == 0)
 				time = time_slave;
-			else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
+			else if ((time_slave != 0) && (time_slave > time))
 				time = time_slave;
 		}
-		if (time != FE_CALLBACK_TIME_NEVER)
-			msleep(time / 10);
-		else
+		if (time == 0)
 			break;
+
+		/*
+		 * Despite dib8000_agc_startup returns time at a 0.1 ms range,
+		 * the actual sleep time depends on CONFIG_HZ. The worse case
+		 * is when CONFIG_HZ=100. In such case, the minimum granularity
+		 * is 10ms. On some real field tests, the tuner sometimes don't
+		 * lock when this timer is lower than 10ms. So, enforce a 10ms
+		 * granularity.
+		 */
+		time = 10 * (time + 99)/100;
+		usleep_range(time * 1000, (time + 1) * 1000);
 		exit_condition = 1;
 		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 			if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
@@ -3631,11 +3657,14 @@ static int dib8000_set_frontend(struct d
 
 	active = 1;
 	do {
-		callback_time = FE_CALLBACK_TIME_NEVER;
+		callback_time = 0;
 		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 			delay = dib8000_tune(state->fe[index_frontend]);
-			if (delay != FE_CALLBACK_TIME_NEVER)
-				delay += systime();
+			if (delay != 0) {
+				delay = jiffies + usecs_to_jiffies(100 * delay);
+				if (!callback_time || delay < callback_time)
+					callback_time = delay;
+			}
 
 			/* we are in autosearch */
 			if (state->channel_parameters_set == 0) { /* searching */
@@ -3646,6 +3675,7 @@ static int dib8000_set_frontend(struct d
 
 					for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
 						if (l != index_frontend) { /* and for all frontend except the successful one */
+							dprintk("Restarting frontend %d\n", l);
 							dib8000_tune_restart_from_demod(state->fe[l]);
 
 							state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@@ -3664,8 +3694,6 @@ static int dib8000_set_frontend(struct d
 					}
 				}
 			}
-			if (delay < callback_time)
-				callback_time = delay;
 		}
 		/* tuning is done when the master frontend is done (failed or success) */
 		if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
@@ -3681,12 +3709,12 @@ static int dib8000_set_frontend(struct d
 				dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
 		}
 
-		if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
+		if ((active == 1) && (callback_time == 0)) {
 			dprintk("strange callback time something went wrong");
 			active = 0;
 		}
 
-		while ((active == 1) && (systime() < callback_time))
+		while ((active == 1) && (time_before(jiffies, callback_time)))
 			msleep(100);
 	} while (active);
 
@@ -4201,7 +4229,7 @@ static int dib8000_get_stats(struct dvb_
 	return 0;
 }
 
-int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+static int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u8 index_frontend = 1;
@@ -4217,9 +4245,8 @@ int dib8000_set_slave_frontend(struct dv
 	dprintk("too many slave frontend");
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(dib8000_set_slave_frontend);
 
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+static int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u8 index_frontend = 1;
@@ -4235,9 +4262,8 @@ int dib8000_remove_slave_frontend(struct
 	dprintk("no frontend to be removed");
 	return -ENODEV;
 }
-EXPORT_SYMBOL(dib8000_remove_slave_frontend);
 
-struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 
@@ -4245,10 +4271,8 @@ struct dvb_frontend *dib8000_get_slave_f
 		return NULL;
 	return state->fe[slave_index];
 }
-EXPORT_SYMBOL(dib8000_get_slave_frontend);
 
-
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
 		u8 default_addr, u8 first_addr, u8 is_dib8096p)
 {
 	int k = 0, ret = 0;
@@ -4325,7 +4349,6 @@ error_memory_read:
 	return ret;
 }
 
-EXPORT_SYMBOL(dib8000_i2c_enumeration);
 static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 1000;
@@ -4348,15 +4371,13 @@ static void dib8000_release(struct dvb_f
 	kfree(st);
 }
 
-struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
 	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
 }
 
-EXPORT_SYMBOL(dib8000_get_i2c_master);
-
-int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
 	u16 val = dib8000_read_word(st, 299) & 0xffef;
@@ -4365,15 +4386,13 @@ int dib8000_pid_filter_ctrl(struct dvb_f
 	dprintk("pid filter enabled %d", onoff);
 	return dib8000_write_word(st, 299, val);
 }
-EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
 
-int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+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);
 	return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
 }
-EXPORT_SYMBOL(dib8000_pid_filter);
 
 static const struct dvb_frontend_ops dib8000_ops = {
 	.delsys = { SYS_ISDBT },
@@ -4405,12 +4424,12 @@ static const struct dvb_frontend_ops dib
 	.read_ucblocks = dib8000_read_unc_blocks,
 };
 
-struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
+static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
 {
 	struct dvb_frontend *fe;
 	struct dib8000_state *state;
 
-	dprintk("dib8000_attach");
+	dprintk("dib8000_init");
 
 	state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
 	if (state == NULL)
@@ -4467,6 +4486,33 @@ error:
 	return NULL;
 }
 
+void *dib8000_attach(struct dib8000_ops *ops)
+{
+	if (!ops)
+		return NULL;
+
+	ops->pwm_agc_reset = dib8000_pwm_agc_reset;
+	ops->get_dc_power = dib8090p_get_dc_power;
+	ops->set_gpio = dib8000_set_gpio;
+	ops->get_slave_frontend = dib8000_get_slave_frontend;
+	ops->set_tune_state = dib8000_set_tune_state;
+	ops->pid_filter_ctrl = dib8000_pid_filter_ctrl;
+	ops->remove_slave_frontend = dib8000_remove_slave_frontend;
+	ops->get_adc_power = dib8000_get_adc_power;
+	ops->update_pll = dib8000_update_pll;
+	ops->tuner_sleep = dib8096p_tuner_sleep;
+	ops->get_tune_state = dib8000_get_tune_state;
+	ops->get_i2c_tuner = dib8096p_get_i2c_tuner;
+	ops->set_slave_frontend = dib8000_set_slave_frontend;
+	ops->pid_filter = dib8000_pid_filter;
+	ops->ctrl_timf = dib8000_ctrl_timf;
+	ops->init = dib8000_init;
+	ops->get_i2c_master = dib8000_get_i2c_master;
+	ops->i2c_enumeration = dib8000_i2c_enumeration;
+	ops->set_wbd_ref = dib8000_set_wbd_ref;
+
+	return ops;
+}
 EXPORT_SYMBOL(dib8000_attach);
 
 MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib8000.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib8000.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib8000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib8000.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,134 +39,34 @@ struct dib8000_config {
 
 #define DEFAULT_DIB8000_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB8000)
-extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
-extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+struct dib8000_ops {
+	int (*set_wbd_ref)(struct dvb_frontend *fe, u16 value);
+	int (*update_pll)(struct dvb_frontend *fe,
+		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
+	int (*set_gpio)(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
+	void (*pwm_agc_reset)(struct dvb_frontend *fe);
+	struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+	int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+	s32 (*get_adc_power)(struct dvb_frontend *fe, u8 mode);
+	int (*get_dc_power)(struct dvb_frontend *fe, u8 IQ);
+	u32 (*ctrl_timf)(struct dvb_frontend *fe, uint8_t op, uint32_t timf);
+	enum frontend_tune_state (*get_tune_state)(struct dvb_frontend *fe);
+	int (*set_tune_state)(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+	int (*set_slave_frontend)(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+	int (*remove_slave_frontend)(struct dvb_frontend *fe);
+	struct dvb_frontend *(*get_slave_frontend)(struct dvb_frontend *fe, int slave_index);
+	int (*i2c_enumeration)(struct i2c_adapter *host, int no_of_demods,
 		u8 default_addr, u8 first_addr, u8 is_dib8096p);
+	struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
+	int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+	int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+	struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
+};
 
-extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
-extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
-extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
-extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
-extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
-extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
-extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
-		uint8_t op, uint32_t timf);
-extern int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
-extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
-extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
-extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+#if IS_ENABLED(CONFIG_DVB_DIB8000)
+void *dib8000_attach(struct dib8000_ops *ops);
 #else
-static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
-		int no_of_demods, u8 default_addr, u8 first_addr,
-		u8 is_dib8096p)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return CT_SHUTDOWN;
-}
-static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
-		uint8_t op, uint32_t timf)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static inline int dib8000_attach(struct dib8000_ops *ops)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib9000.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib9000.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/dib9000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/dib9000.c	2014-09-28 17:29:07.000000000 -0400
@@ -1040,13 +1040,18 @@ static int dib9000_risc_apb_access_write
 	if (address >= 1024 || !state->platform.risc.fw_is_running)
 		return -EINVAL;
 
+	if (len > 18)
+		return -EINVAL;
+
 	/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
 
-	mb[0] = (unsigned short)address;
-	for (i = 0; i < len && i < 20; i += 2)
-		mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
+	mb[0] = (u16)address;
+	for (i = 0; i + 1 < len; i += 2)
+		mb[1 + i / 2] = b[i] << 8 | b[i + 1];
+	if (len & 1)
+		mb[1 + len / 2] = b[len - 1] << 8;
 
-	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
+	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, (3 + len) / 2, attribute);
 	return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c	2014-08-07 04:48:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c	2014-09-28 21:29:45.000000000 -0400
@@ -2159,7 +2159,7 @@ int drxj_dap_atomic_read_write_block(str
 	return 0;
 
 rw_error:
-	return -EIO;
+	return rc;
 
 }
 
@@ -2252,7 +2252,7 @@ static int hi_cfg_command(const struct d
 	return 0;
 
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -2363,7 +2363,7 @@ hi_command(struct i2c_device_addr *dev_a
 	/* if ( powerdown_cmd == true ) */
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -2434,7 +2434,7 @@ static int init_hi(const struct drx_demo
 	return 0;
 
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -2650,7 +2650,7 @@ static int get_device_capabilities(struc
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -3338,7 +3338,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demo
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -3421,7 +3421,7 @@ static int set_mpegtei_handling(struct d
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -3464,7 +3464,7 @@ static int bit_reverse_mpeg_output(struc
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -3508,7 +3508,7 @@ static int set_mpeg_start_width(struct d
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -3652,7 +3652,7 @@ static int ctrl_set_uio_cfg(struct drx_d
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -3854,7 +3854,7 @@ ctrl_uio_write(struct drx_demod_instance
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*---------------------------------------------------------------------------*/
@@ -3969,7 +3969,7 @@ static int smart_ant_init(struct drx_dem
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
@@ -4109,7 +4109,7 @@ static int scu_command(struct i2c_device
 	return 0;
 
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -4178,7 +4178,7 @@ int drxj_dap_scu_atomic_read_write_block
 	return 0;
 
 rw_error:
-	return -EIO;
+	return rc;
 
 }
 
@@ -4290,7 +4290,7 @@ static int adc_sync_measurement(struct d
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -4349,7 +4349,7 @@ static int adc_synchronization(struct dr
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -4734,7 +4734,7 @@ static int init_agc(struct drx_demod_ins
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -4831,7 +4831,7 @@ set_frequency(struct drx_demod_instance
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -4879,7 +4879,7 @@ static int get_acc_pkt_err(struct drx_de
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 #endif
 
@@ -5097,7 +5097,7 @@ set_agc_rf(struct drx_demod_instance *de
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -5326,7 +5326,7 @@ set_agc_if(struct drx_demod_instance *de
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -5362,7 +5362,7 @@ static int set_iqm_af(struct drx_demod_i
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -5470,7 +5470,7 @@ static int power_down_vsb(struct drx_dem
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -5686,7 +5686,7 @@ static int set_vsb_leak_n_gain(struct dr
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -6192,7 +6192,7 @@ static int set_vsb(struct drx_demod_inst
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -6231,7 +6231,7 @@ static int get_vsb_post_rs_pck_err(struc
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -6276,7 +6276,7 @@ static int get_vs_bpost_viterbi_ber(stru
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -6321,7 +6321,7 @@ static int get_vsbmer(struct i2c_device_
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 
@@ -6434,7 +6434,7 @@ static int power_down_qam(struct drx_dem
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -6646,7 +6646,7 @@ set_qam_measurement(struct drx_demod_ins
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -6881,7 +6881,7 @@ static int set_qam16(struct drx_demod_in
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -7116,7 +7116,7 @@ static int set_qam32(struct drx_demod_in
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -7351,7 +7351,7 @@ static int set_qam64(struct drx_demod_in
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -7586,7 +7586,7 @@ static int set_qam128(struct drx_demod_i
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -7821,7 +7821,7 @@ static int set_qam256(struct drx_demod_i
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -8650,7 +8650,7 @@ set_qam(struct drx_demod_instance *demod
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -8831,7 +8831,7 @@ static int qam_flip_spec(struct drx_demo
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 
 }
 
@@ -8984,7 +8984,7 @@ qam64auto(struct drx_demod_instance *dem
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -9068,7 +9068,7 @@ qam256auto(struct drx_demod_instance *de
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -9273,7 +9273,7 @@ rw_error:
 	/* restore starting value */
 	if (auto_flag)
 		channel->constellation = DRX_CONSTELLATION_AUTO;
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -9344,7 +9344,7 @@ get_qamrs_err_count(struct i2c_device_ad
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -9425,8 +9425,8 @@ static int get_sig_strength(struct drx_d
 		*sig_strength = 0;
 
 	return 0;
-	rw_error:
-	return -EIO;
+rw_error:
+	return rc;
 }
 
 /**
@@ -9643,7 +9643,7 @@ rw_error:
 	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 
-	return -EIO;
+	return rc;
 }
 
 #endif /* #ifndef DRXJ_VSB_ONLY */
@@ -9810,7 +9810,7 @@ power_down_atv(struct drx_demod_instance
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -9840,7 +9840,7 @@ static int power_down_aud(struct drx_dem
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -9874,7 +9874,7 @@ static int set_orx_nsu_aox(struct drx_de
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /**
@@ -10398,7 +10398,7 @@ static int ctrl_set_oob(struct drx_demod
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -10638,7 +10638,7 @@ ctrl_set_channel(struct drx_demod_instan
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*=============================================================================
@@ -10756,7 +10756,7 @@ ctrl_sig_quality(struct drx_demod_instan
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -10844,7 +10844,7 @@ ctrl_lock_status(struct drx_demod_instan
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -10941,7 +10941,7 @@ ctrl_set_standard(struct drx_demod_insta
 rw_error:
 	/* Don't know what the standard is now ... try again */
 	ext_attr->standard = DRX_STANDARD_UNKNOWN;
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -11222,7 +11222,7 @@ ctrl_set_cfg_pre_saw(struct drx_demod_in
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -11303,7 +11303,7 @@ ctrl_set_cfg_afe_gain(struct drx_demod_i
 
 	return 0;
 rw_error:
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -11315,6 +11315,7 @@ rw_error:
 static int drx_ctrl_u_code(struct drx_demod_instance *demod,
 		       struct drxu_code_info *mc_info,
 		       enum drxu_code_action action);
+static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state);
 
 /**
 * \fn drxj_open()
@@ -11527,10 +11528,11 @@ static int drxj_open(struct drx_demod_in
 	ext_attr->aud_data = drxj_default_aud_data_g;
 
 	demod->my_common_attr->is_opened = true;
+	drxj_set_lna_state(demod, false);
 	return 0;
 rw_error:
 	common_attr->is_opened = false;
-	return -EIO;
+	return rc;
 }
 
 /*============================================================================*/
@@ -11578,7 +11580,7 @@ static int drxj_close(struct drx_demod_i
 rw_error:
 	DRX_ATTR_ISOPENED(demod) = false;
 
-	return -EIO;
+	return rc;
 }
 
 /*
@@ -11890,6 +11892,33 @@ release:
 	return rc;
 }
 
+/* caller is expeced to check if lna is supported before enabling */
+static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
+{
+	struct drxuio_cfg uio_cfg;
+	struct drxuio_data uio_data;
+	int result;
+
+	uio_cfg.uio = DRX_UIO1;
+	uio_cfg.mode = DRX_UIO_MODE_READWRITE;
+	/* Configure user-I/O #3: enable read/write */
+	result = ctrl_set_uio_cfg(demod, &uio_cfg);
+	if (result) {
+		pr_err("Failed to setup LNA GPIO!\n");
+		return result;
+	}
+
+	uio_data.uio = DRX_UIO1;
+	uio_data.value = state;
+	result = ctrl_uio_write(demod, &uio_data);
+	if (result != 0) {
+		pr_err("Failed to %sable LNA!\n",
+		       state ? "en" : "dis");
+		return result;
+	}
+	return 0;
+}
+
 /*
  * The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
  *
@@ -12040,7 +12069,6 @@ static int drx39xxj_set_frontend(struct
 	enum drx_standard standard = DRX_STANDARD_8VSB;
 	struct drx_channel channel;
 	int result;
-	struct drxuio_data uio_data;
 	static const struct drx_channel def_channel = {
 		/* frequency      */ 0,
 		/* bandwidth      */ DRX_BANDWIDTH_6MHZ,
@@ -12125,13 +12153,7 @@ static int drx39xxj_set_frontend(struct
 		return -EINVAL;
 	}
 	/* Just for giggles, let's shut off the LNA again.... */
-	uio_data.uio = DRX_UIO1;
-	uio_data.value = false;
-	result = ctrl_uio_write(demod, &uio_data);
-	if (result != 0) {
-		pr_err("Failed to disable LNA!\n");
-		return 0;
-	}
+	drxj_set_lna_state(demod, false);
 
 	/* After set_frontend, except for strength, stats aren't available */
 	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
@@ -12180,21 +12202,28 @@ static int drx39xxj_i2c_gate_ctrl(struct
 
 static int drx39xxj_init(struct dvb_frontend *fe)
 {
-	/* Bring the demod out of sleep */
-	drx39xxj_set_powerstate(fe, 1);
+	struct drx39xxj_state *state = fe->demodulator_priv;
+	struct drx_demod_instance *demod = state->demod;
+	int rc = 0;
 
-	return 0;
+	if (fe->exit == DVB_FE_DEVICE_RESUME) {
+		/* so drxj_open() does what it needs to do */
+		demod->my_common_attr->is_opened = false;
+		rc = drxj_open(demod);
+		if (rc != 0)
+			pr_err("drx39xxj_init(): DRX open failed rc=%d!\n", rc);
+	} else
+		drx39xxj_set_powerstate(fe, 1);
+
+	return rc;
 }
 
 static int drx39xxj_set_lna(struct dvb_frontend *fe)
 {
-	int result;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct drx39xxj_state *state = fe->demodulator_priv;
 	struct drx_demod_instance *demod = state->demod;
 	struct drxj_data *ext_attr = demod->my_ext_attr;
-	struct drxuio_cfg uio_cfg;
-	struct drxuio_data uio_data;
 
 	if (c->lna) {
 		if (!ext_attr->has_lna) {
@@ -12204,26 +12233,7 @@ static int drx39xxj_set_lna(struct dvb_f
 		}
 	}
 
-	/* Turn off the LNA */
-	uio_cfg.uio = DRX_UIO1;
-	uio_cfg.mode = DRX_UIO_MODE_READWRITE;
-	/* Configure user-I/O #3: enable read/write */
-	result = ctrl_set_uio_cfg(demod, &uio_cfg);
-	if (result) {
-		pr_err("Failed to setup LNA GPIO!\n");
-		return result;
-	}
-
-	uio_data.uio = DRX_UIO1;
-	uio_data.value = c->lna;
-	result = ctrl_uio_write(demod, &uio_data);
-	if (result != 0) {
-		pr_err("Failed to %sable LNA!\n",
-		       c->lna ? "en" : "dis");
-		return result;
-	}
-
-	return 0;
+	return drxj_set_lna_state(demod, c->lna);
 }
 
 static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
@@ -12238,7 +12248,9 @@ static void drx39xxj_release(struct dvb_
 	struct drx39xxj_state *state = fe->demodulator_priv;
 	struct drx_demod_instance *demod = state->demod;
 
-	drxj_close(demod);
+	/* if device is removed don't access it */
+	if (fe->exit != DVB_FE_DEVICE_REMOVED)
+		drxj_close(demod);
 
 	kfree(demod->my_ext_attr);
 	kfree(demod->my_common_attr);
@@ -12259,8 +12271,6 @@ struct dvb_frontend *drx39xxj_attach(str
 	struct drxj_data *demod_ext_attr = NULL;
 	struct drx_demod_instance *demod = NULL;
 	struct dtv_frontend_properties *p;
-	struct drxuio_cfg uio_cfg;
-	struct drxuio_data uio_data;
 	int result;
 
 	/* allocate memory for the internal state */
@@ -12272,22 +12282,20 @@ struct dvb_frontend *drx39xxj_attach(str
 	if (demod == NULL)
 		goto error;
 
-	demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
+	demod_addr = kmemdup(&drxj_default_addr_g,
+			     sizeof(struct i2c_device_addr), GFP_KERNEL);
 	if (demod_addr == NULL)
 		goto error;
-	memcpy(demod_addr, &drxj_default_addr_g,
-	       sizeof(struct i2c_device_addr));
 
-	demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
+	demod_comm_attr = kmemdup(&drxj_default_comm_attr_g,
+				  sizeof(struct drx_common_attr), GFP_KERNEL);
 	if (demod_comm_attr == NULL)
 		goto error;
-	memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
-	       sizeof(struct drx_common_attr));
 
-	demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
+	demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data),
+				 GFP_KERNEL);
 	if (demod_ext_attr == NULL)
 		goto error;
-	memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
 
 	/* setup the state */
 	state->i2c = i2c;
@@ -12313,24 +12321,6 @@ struct dvb_frontend *drx39xxj_attach(str
 		goto error;
 	}
 
-	/* Turn off the LNA */
-	uio_cfg.uio = DRX_UIO1;
-	uio_cfg.mode = DRX_UIO_MODE_READWRITE;
-	/* Configure user-I/O #3: enable read/write */
-	result = ctrl_set_uio_cfg(demod, &uio_cfg);
-	if (result) {
-		pr_err("Failed to setup LNA GPIO!\n");
-		goto error;
-	}
-
-	uio_data.uio = DRX_UIO1;
-	uio_data.value = false;
-	result = ctrl_uio_write(demod, &uio_data);
-	if (result != 0) {
-		pr_err("Failed to disable LNA!\n");
-		goto error;
-	}
-
 	/* create dvb_frontend */
 	memcpy(&state->frontend.ops, &drx39xxj_ops,
 	       sizeof(struct dvb_frontend_ops));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/drxd.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drxd.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/drxd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drxd.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,5 +69,4 @@ struct dvb_frontend *drxd_attach(const s
 }
 #endif
 
-extern int drxd_config_i2c(struct dvb_frontend *, int);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/drxd_hard.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drxd_hard.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/drxd_hard.c	2014-08-07 04:49:25.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/drxd_hard.c	2014-09-28 21:30:34.000000000 -0400
@@ -2840,7 +2840,7 @@ static int drxd_init(struct dvb_frontend
 	return err;
 }
 
-int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
+static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
 {
 	struct drxd_state *state = fe->demodulator_priv;
 
@@ -2849,7 +2849,6 @@ int drxd_config_i2c(struct dvb_frontend
 
 	return DRX_ConfigureI2CBridge(state, onoff);
 }
-EXPORT_SYMBOL(drxd_config_i2c);
 
 static int drxd_get_tune_settings(struct dvb_frontend *fe,
 				  struct dvb_frontend_tune_settings *sets)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/Kconfig
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,15 @@ config DVB_TDA18271C2DD
 
 	  Say Y when you want to support this tuner.
 
+config DVB_SI2165
+	tristate "Silicon Labs si2165 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-C/T demodulator.
+
+	  Say Y when you want to support this frontend.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
@@ -446,6 +455,15 @@ config DVB_RTL2832
 	help
 	  Say Y when you want to support this frontend.
 
+config DVB_RTL2832_SDR
+	tristate "Realtek RTL2832 SDR"
+	depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT && USB
+	select DVB_RTL2832
+	select VIDEOBUF2_VMALLOC
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this SDR module.
+
 config DVB_SI2168
 	tristate "Silicon Labs Si2168"
 	depends on DVB_CORE && I2C && I2C_MUX
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/m88ds3103.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/m88ds3103.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/m88ds3103.c	2014-08-07 04:48:51.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/m88ds3103.c	2014-09-28 21:29:51.000000000 -0400
@@ -879,7 +879,7 @@ static int m88ds3103_read_snr(struct dvb
 		/* SNR(X) dB = 10 * ln(X) / ln(10) dB */
 		tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS);
 		if (tmp)
-			*snr = 100ul * intlog2(tmp) / intlog2(10);
+			*snr = div_u64((u64) 100 * intlog2(tmp), intlog2(10));
 		else
 			*snr = 0;
 		break;
@@ -908,7 +908,7 @@ static int m88ds3103_read_snr(struct dvb
 		/* SNR(X) dB = 10 * log10(X) dB */
 		if (signal > noise) {
 			tmp = signal / noise;
-			*snr = 100ul * intlog10(tmp) / (1 << 24);
+			*snr = div_u64((u64) 100 * intlog10(tmp), (1 << 24));
 		} else {
 			*snr = 0;
 		}
@@ -926,6 +926,86 @@ err:
 	return ret;
 }
 
+static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct m88ds3103_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	unsigned int utmp;
+	u8 buf[3], u8tmp;
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
+		if (ret)
+			goto err;
+
+		ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
+		if (ret)
+			goto err;
+
+		if (!(u8tmp & 0x10)) {
+			u8tmp |= 0x10;
+
+			ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
+			if (ret)
+				goto err;
+
+			priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+			/* restart counters */
+			ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
+			if (ret)
+				goto err;
+		}
+		break;
+	case SYS_DVBS2:
+		ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
+		if (ret)
+			goto err;
+
+		utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
+
+		if (utmp > 3000) {
+			ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
+			if (ret)
+				goto err;
+
+			priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+			/* restart counters */
+			ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
+			if (ret)
+				goto err;
+
+			ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
+			if (ret)
+				goto err;
+
+			ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
+			if (ret)
+				goto err;
+
+			ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
+			if (ret)
+				goto err;
+		}
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	*ber = priv->ber;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
 
 static int m88ds3103_set_tone(struct dvb_frontend *fe,
 	fe_sec_tone_mode_t fe_sec_tone_mode)
@@ -1284,6 +1364,7 @@ static struct dvb_frontend_ops m88ds3103
 
 	.read_status = m88ds3103_read_status,
 	.read_snr = m88ds3103_read_snr,
+	.read_ber = m88ds3103_read_ber,
 
 	.diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
 	.diseqc_send_burst = m88ds3103_diseqc_send_burst,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/m88ds3103_priv.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/m88ds3103_priv.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/m88ds3103_priv.h	2014-08-07 04:48:53.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/m88ds3103_priv.h	2014-09-28 21:29:53.000000000 -0400
@@ -22,6 +22,7 @@
 #include "dvb_math.h"
 #include <linux/firmware.h>
 #include <linux/i2c-mux.h>
+#include <linux/math64.h>
 
 #define M88DS3103_FIRMWARE "/*(DEBLOBBED)*/"
 #define M88DS3103_MCLK_KHZ 96000
@@ -34,6 +35,7 @@ struct m88ds3103_priv {
 	struct dvb_frontend fe;
 	fe_delivery_system_t delivery_system;
 	fe_status_t fe_status;
+	u32 ber;
 	bool warm; /* FW running */
 	struct i2c_adapter *i2c_adapter;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/Makefile linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/Makefile
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,11 @@
 ccflags-y += -I$(srctree)/drivers/media/dvb-core/
 ccflags-y += -I$(srctree)/drivers/media/tuners/
 
+# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
+ifdef CONFIG_DVB_RTL2832_SDR
+	ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
+endif
+
 stb0899-objs := stb0899_drv.o stb0899_algo.o
 stv0900-objs := stv0900_core.o stv0900_sw.o
 drxd-objs := drxd_firm.o drxd_hard.o
@@ -100,10 +105,12 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_SI2165) += si2165.o
 obj-$(CONFIG_DVB_A8293) += a8293.o
 obj-$(CONFIG_DVB_TDA10071) += tda10071.o
 obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
 obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
+obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
 obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
 obj-$(CONFIG_DVB_AF9033) += af9033.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/mb86a20s.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/mb86a20s.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/mb86a20s.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/mb86a20s.c	2014-09-28 17:29:07.000000000 -0400
@@ -459,6 +459,9 @@ static int mb86a20s_get_interleaving(str
 				     unsigned layer)
 {
 	int rc;
+	int interleaving[] = {
+		0, 1, 2, 4, 8
+	};
 
 	static unsigned char reg[] = {
 		[0] = 0x88,	/* Layer A */
@@ -475,20 +478,7 @@ static int mb86a20s_get_interleaving(str
 	if (rc < 0)
 		return rc;
 
-	switch ((rc >> 4) & 0x07) {
-	case 1:
-		return GUARD_INTERVAL_1_4;
-	case 2:
-		return GUARD_INTERVAL_1_8;
-	case 3:
-		return GUARD_INTERVAL_1_16;
-	case 4:
-		return GUARD_INTERVAL_1_32;
-
-	default:
-	case 0:
-		return GUARD_INTERVAL_AUTO;
-	}
+	return interleaving[(rc >> 4) & 0x07];
 }
 
 static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
@@ -566,7 +556,7 @@ static u32 isdbt_rate[3][5][4] = {
 
 static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
 				   u32 modulation, u32 forward_error_correction,
-				   u32 interleaving,
+				   u32 guard_interval,
 				   u32 segment)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
@@ -574,7 +564,7 @@ static void mb86a20s_layer_bitrate(struc
 	int mod, fec, guard;
 
 	/*
-	 * If modulation/fec/interleaving is not detected, the default is
+	 * If modulation/fec/guard is not detected, the default is
 	 * to consider the lowest bit rate, to avoid taking too long time
 	 * to get BER.
 	 */
@@ -612,7 +602,7 @@ static void mb86a20s_layer_bitrate(struc
 		break;
 	}
 
-	switch (interleaving) {
+	switch (guard_interval) {
 	default:
 	case GUARD_INTERVAL_1_4:
 		guard = 0;
@@ -703,7 +693,7 @@ static int mb86a20s_get_frontend(struct
 		c->layer[layer].interleaving = rc;
 		mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation,
 				       c->layer[layer].fec,
-				       c->layer[layer].interleaving,
+				       c->guard_interval,
 				       c->layer[layer].segment_count);
 	}
 
@@ -721,11 +711,10 @@ static int mb86a20s_get_frontend(struct
 	rc = mb86a20s_readreg(state, 0x07);
 	if (rc < 0)
 		return rc;
+	c->transmission_mode = TRANSMISSION_MODE_AUTO;
 	if ((rc & 0x60) == 0x20) {
-		switch (rc & 0x0c >> 2) {
-		case 0:
-			c->transmission_mode = TRANSMISSION_MODE_2K;
-			break;
+		/* Only modes 2 and 3 are supported */
+		switch ((rc >> 2) & 0x03) {
 		case 1:
 			c->transmission_mode = TRANSMISSION_MODE_4K;
 			break;
@@ -734,7 +723,9 @@ static int mb86a20s_get_frontend(struct
 			break;
 		}
 	}
+	c->guard_interval = GUARD_INTERVAL_AUTO;
 	if (!(rc & 0x10)) {
+		/* Guard interval 1/32 is not supported */
 		switch (rc & 0x3) {
 		case 0:
 			c->guard_interval = GUARD_INTERVAL_1_4;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/rtl2832_sdr.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/rtl2832_sdr.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/rtl2832_sdr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/rtl2832_sdr.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1551 @@
+/*
+ * Realtek RTL2832U SDR driver
+ *
+ * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * GNU Radio plugin "gr-kernel" for device usage will be on:
+ * http://git.linuxtv.org/anttip/gr-kernel.git
+ *
+ */
+
+#include "dvb_frontend.h"
+#include "rtl2832_sdr.h"
+#include "dvb_usb.h"
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include <linux/jiffies.h>
+#include <linux/math64.h>
+
+static bool rtl2832_sdr_emulated_fmt;
+module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
+#define MAX_BULK_BUFS            (10)
+#define BULK_BUFFER_SIZE         (128 * 512)
+
+static const struct v4l2_frequency_band bands_adc[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  300000,
+		.rangehigh  =  300000,
+	},
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 1,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  900001,
+		.rangehigh  = 2800000,
+	},
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 2,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   = 3200000,
+		.rangehigh  = 3200000,
+	},
+};
+
+static const struct v4l2_frequency_band bands_fm[] = {
+	{
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =    50000000,
+		.rangehigh  =  2000000000,
+	},
+};
+
+/* stream formats */
+struct rtl2832_sdr_format {
+	char	*name;
+	u32	pixelformat;
+	u32	buffersize;
+};
+
+static struct rtl2832_sdr_format formats[] = {
+	{
+		.name		= "Complex U8",
+		.pixelformat	= V4L2_SDR_FMT_CU8,
+		.buffersize	= BULK_BUFFER_SIZE,
+	}, {
+		.name		= "Complex U16LE (emulated)",
+		.pixelformat	= V4L2_SDR_FMT_CU16LE,
+		.buffersize	= BULK_BUFFER_SIZE * 2,
+	},
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct rtl2832_sdr_frame_buf {
+	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct list_head list;
+};
+
+struct rtl2832_sdr_state {
+#define POWER_ON           (1 << 1)
+#define URB_BUF            (1 << 2)
+	unsigned long flags;
+
+	const struct rtl2832_config *cfg;
+	struct dvb_frontend *fe;
+	struct dvb_usb_device *d;
+	struct i2c_adapter *i2c;
+	u8 bank;
+
+	struct video_device vdev;
+	struct v4l2_device v4l2_dev;
+
+	/* videobuf2 queue and queued buffers list */
+	struct vb2_queue vb_queue;
+	struct list_head queued_bufs;
+	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+	unsigned sequence;	     /* buffer sequence counter */
+
+	/* Note if taking both locks v4l2_lock must always be locked first! */
+	struct mutex v4l2_lock;      /* Protects everything else */
+	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
+
+	/* Pointer to our usb_device, will be NULL after unplug */
+	struct usb_device *udev; /* Both mutexes most be hold when setting! */
+
+	unsigned int vb_full; /* vb is full and packets dropped */
+
+	struct urb     *urb_list[MAX_BULK_BUFS];
+	int            buf_num;
+	unsigned long  buf_size;
+	u8             *buf_list[MAX_BULK_BUFS];
+	dma_addr_t     dma_addr[MAX_BULK_BUFS];
+	int urbs_initialized;
+	int urbs_submitted;
+
+	unsigned int f_adc, f_tuner;
+	u32 pixelformat;
+	u32 buffersize;
+	unsigned int num_formats;
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *bandwidth_auto;
+	struct v4l2_ctrl *bandwidth;
+
+	/* for sample rate calc */
+	unsigned int sample;
+	unsigned int sample_measured;
+	unsigned long jiffies_next;
+};
+
+/* write multiple hardware registers */
+static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val,
+		int len)
+{
+	int ret;
+#define MAX_WR_LEN 24
+#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1)
+	u8 buf[MAX_WR_XFER_LEN];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = s->cfg->i2c_addr,
+			.flags = 0,
+			.len = 1 + len,
+			.buf = buf,
+		}
+	};
+
+	if (WARN_ON(len > MAX_WR_LEN))
+		return -EINVAL;
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(s->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_err(&s->i2c->dev,
+			"%s: I2C wr failed=%d reg=%02x len=%d\n",
+			KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple hardware registers */
+static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
+{
+	int ret;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = s->cfg->i2c_addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = s->cfg->i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	ret = i2c_transfer(s->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_err(&s->i2c->dev,
+				"%s: I2C rd failed=%d reg=%02x len=%d\n",
+				KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write multiple registers */
+static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
+		const u8 *val, int len)
+{
+	int ret;
+	u8 reg2 = (reg >> 0) & 0xff;
+	u8 bank = (reg >> 8) & 0xff;
+
+	/* switch bank if needed */
+	if (bank != s->bank) {
+		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+
+		s->bank = bank;
+	}
+
+	return rtl2832_sdr_wr(s, reg2, val, len);
+}
+
+/* read multiple registers */
+static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
+		int len)
+{
+	int ret;
+	u8 reg2 = (reg >> 0) & 0xff;
+	u8 bank = (reg >> 8) & 0xff;
+
+	/* switch bank if needed */
+	if (bank != s->bank) {
+		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+
+		s->bank = bank;
+	}
+
+	return rtl2832_sdr_rd(s, reg2, val, len);
+}
+
+/* write single register */
+static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val)
+{
+	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
+}
+
+#if 0
+/* read single register */
+static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
+{
+	return rtl2832_sdr_rd_regs(s, reg, val, 1);
+}
+#endif
+
+/* write single register with mask */
+static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
+		u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
+}
+
+#if 0
+/* read single register with mask */
+static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
+		u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+#endif
+
+/* Private functions */
+static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
+		struct rtl2832_sdr_state *s)
+{
+	unsigned long flags = 0;
+	struct rtl2832_sdr_frame_buf *buf = NULL;
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	if (list_empty(&s->queued_bufs))
+		goto leave;
+
+	buf = list_entry(s->queued_bufs.next,
+			struct rtl2832_sdr_frame_buf, list);
+	list_del(&buf->list);
+leave:
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	return buf;
+}
+
+static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
+		void *dst, const u8 *src, unsigned int src_len)
+{
+	unsigned int dst_len;
+
+	if (s->pixelformat ==  V4L2_SDR_FMT_CU8) {
+		/* native stream, no need to convert */
+		memcpy(dst, src, src_len);
+		dst_len = src_len;
+	} else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) {
+		/* convert u8 to u16 */
+		unsigned int i;
+		u16 *u16dst = dst;
+
+		for (i = 0; i < src_len; i++)
+			*u16dst++ = (src[i] << 8) | (src[i] >> 0);
+		dst_len = 2 * src_len;
+	} else {
+		dst_len = 0;
+	}
+
+	/* calculate samping rate and output it in 10 seconds intervals */
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+#define MSECS 10000UL
+		unsigned int samples = s->sample - s->sample_measured;
+
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample_measured = s->sample;
+		dev_dbg(&s->udev->dev,
+				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
+	}
+
+	/* total number of I+Q pairs */
+	s->sample += src_len / 2;
+
+	return dst_len;
+}
+
+/*
+ * This gets called for the bulk stream pipe. This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void rtl2832_sdr_urb_complete(struct urb *urb)
+{
+	struct rtl2832_sdr_state *s = urb->context;
+	struct rtl2832_sdr_frame_buf *fbuf;
+
+	dev_dbg_ratelimited(&s->udev->dev,
+			"%s: status=%d length=%d/%d errors=%d\n",
+			__func__, urb->status, urb->actual_length,
+			urb->transfer_buffer_length, urb->error_count);
+
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:            /* error */
+		dev_err_ratelimited(&s->udev->dev, "urb failed=%d\n",
+				urb->status);
+		break;
+	}
+
+	if (likely(urb->actual_length > 0)) {
+		void *ptr;
+		unsigned int len;
+		/* get free framebuffer */
+		fbuf = rtl2832_sdr_get_next_fill_buf(s);
+		if (unlikely(fbuf == NULL)) {
+			s->vb_full++;
+			dev_notice_ratelimited(&s->udev->dev,
+					"videobuf is full, %d packets dropped\n",
+					s->vb_full);
+			goto skip;
+		}
+
+		/* fill framebuffer */
+		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+		len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer,
+				urb->actual_length);
+		vb2_set_plane_payload(&fbuf->vb, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
+		fbuf->vb.v4l2_buf.sequence = s->sequence++;
+		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+	}
+skip:
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s)
+{
+	int i;
+
+	for (i = s->urbs_submitted - 1; i >= 0; i--) {
+		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
+		/* stop the URB */
+		usb_kill_urb(s->urb_list[i]);
+	}
+	s->urbs_submitted = 0;
+
+	return 0;
+}
+
+static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s)
+{
+	int i, ret;
+
+	for (i = 0; i < s->urbs_initialized; i++) {
+		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
+		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+		if (ret) {
+			dev_err(&s->udev->dev,
+					"Could not submit urb no. %d - get them all back\n",
+					i);
+			rtl2832_sdr_kill_urbs(s);
+			return ret;
+		}
+		s->urbs_submitted++;
+	}
+
+	return 0;
+}
+
+static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s)
+{
+	if (s->flags & USB_STATE_URB_BUF) {
+		while (s->buf_num) {
+			s->buf_num--;
+			dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
+					__func__, s->buf_num);
+			usb_free_coherent(s->udev, s->buf_size,
+					  s->buf_list[s->buf_num],
+					  s->dma_addr[s->buf_num]);
+		}
+	}
+	s->flags &= ~USB_STATE_URB_BUF;
+
+	return 0;
+}
+
+static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s)
+{
+	s->buf_num = 0;
+	s->buf_size = BULK_BUFFER_SIZE;
+
+	dev_dbg(&s->udev->dev,
+			"%s: all in all I will use %u bytes for streaming\n",
+			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
+		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+				BULK_BUFFER_SIZE, GFP_ATOMIC,
+				&s->dma_addr[s->buf_num]);
+		if (!s->buf_list[s->buf_num]) {
+			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
+					__func__, s->buf_num);
+			rtl2832_sdr_free_stream_bufs(s);
+			return -ENOMEM;
+		}
+
+		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+				__func__, s->buf_num,
+				s->buf_list[s->buf_num],
+				(long long)s->dma_addr[s->buf_num]);
+		s->flags |= USB_STATE_URB_BUF;
+	}
+
+	return 0;
+}
+
+static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s)
+{
+	int i;
+
+	rtl2832_sdr_kill_urbs(s);
+
+	for (i = s->urbs_initialized - 1; i >= 0; i--) {
+		if (s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
+					__func__, i);
+			/* free the URBs */
+			usb_free_urb(s->urb_list[i]);
+		}
+	}
+	s->urbs_initialized = 0;
+
+	return 0;
+}
+
+static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
+{
+	int i, j;
+
+	/* allocate the URBs */
+	for (i = 0; i < MAX_BULK_BUFS; i++) {
+		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
+			for (j = 0; j < i; j++)
+				usb_free_urb(s->urb_list[j]);
+			return -ENOMEM;
+		}
+		usb_fill_bulk_urb(s->urb_list[i],
+				s->udev,
+				usb_rcvbulkpipe(s->udev, 0x81),
+				s->buf_list[i],
+				BULK_BUFFER_SIZE,
+				rtl2832_sdr_urb_complete, s);
+
+		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+		s->urb_list[i]->transfer_dma = s->dma_addr[i];
+		s->urbs_initialized++;
+	}
+
+	return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
+{
+	unsigned long flags = 0;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	while (!list_empty(&s->queued_bufs)) {
+		struct rtl2832_sdr_frame_buf *buf;
+
+		buf = list_entry(s->queued_bufs.next,
+				struct rtl2832_sdr_frame_buf, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
+{
+	struct rtl2832_sdr_state *s = fe->sec_priv;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->vb_queue_lock);
+	mutex_lock(&s->v4l2_lock);
+	/* No need to keep the urbs around after disconnection */
+	s->udev = NULL;
+
+	v4l2_device_disconnect(&s->v4l2_dev);
+	video_unregister_device(&s->vdev);
+	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&s->vb_queue_lock);
+
+	v4l2_device_put(&s->v4l2_dev);
+
+	fe->sec_priv = NULL;
+}
+
+static int rtl2832_sdr_querycap(struct file *file, void *fh,
+		struct v4l2_capability *cap)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+/* Videobuf2 operations */
+static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+	/* Need at least 8 buffers */
+	if (vq->num_buffers + *nbuffers < 8)
+		*nbuffers = 8 - vq->num_buffers;
+	*nplanes = 1;
+	sizes[0] = PAGE_ALIGN(s->buffersize);
+	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+			__func__, *nbuffers, sizes[0]);
+	return 0;
+}
+
+static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
+{
+	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+
+	/* Don't allow queing new buffers after device disconnection */
+	if (!s->udev)
+		return -ENODEV;
+
+	return 0;
+}
+
+static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
+{
+	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct rtl2832_sdr_frame_buf *buf =
+			container_of(vb, struct rtl2832_sdr_frame_buf, vb);
+	unsigned long flags = 0;
+
+	/* Check the device has not disconnected between prep and queuing */
+	if (!s->udev) {
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	list_add_tail(&buf->list, &s->queued_bufs);
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
+{
+	struct dvb_frontend *fe = s->fe;
+	int ret;
+	unsigned int f_sr, f_if;
+	u8 buf[4], u8tmp1, u8tmp2;
+	u64 u64tmp;
+	u32 u32tmp;
+
+	dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
+
+	if (!test_bit(POWER_ON, &s->flags))
+		return 0;
+
+	if (s->f_adc == 0)
+		return 0;
+
+	f_sr = s->f_adc;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4);
+	if (ret)
+		goto err;
+
+	/* get IF from tuner */
+	if (fe->ops.tuner_ops.get_if_frequency)
+		ret = fe->ops.tuner_ops.get_if_frequency(fe, &f_if);
+	else
+		ret = -EINVAL;
+
+	if (ret)
+		goto err;
+
+	/* program IF */
+	u64tmp = f_if % s->cfg->xtal;
+	u64tmp *= 0x400000;
+	u64tmp = div_u64(u64tmp, s->cfg->xtal);
+	u64tmp = -u64tmp;
+	u32tmp = u64tmp & 0x3fffff;
+
+	dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n",
+			__func__, f_if, u32tmp);
+
+	buf[0] = (u32tmp >> 16) & 0xff;
+	buf[1] = (u32tmp >>  8) & 0xff;
+	buf[2] = (u32tmp >>  0) & 0xff;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3);
+	if (ret)
+		goto err;
+
+	/* BB / IF mode */
+	/* POR: 0x1b1=0x1f, 0x008=0x0d, 0x006=0x80 */
+	if (f_if) {
+		u8tmp1 = 0x1a; /* disable Zero-IF */
+		u8tmp2 = 0x8d; /* enable ADC I */
+	} else {
+		u8tmp1 = 0x1b; /* enable Zero-IF, DC, IQ */
+		u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
+	}
+
+	ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80);
+	if (ret)
+		goto err;
+
+	/* program sampling rate (resampling down) */
+	u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U);
+	u32tmp <<= 2;
+	buf[0] = (u32tmp >> 24) & 0xff;
+	buf[1] = (u32tmp >> 16) & 0xff;
+	buf[2] = (u32tmp >>  8) & 0xff;
+	buf[3] = (u32tmp >>  0) & 0xff;
+	ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4);
+	if (ret)
+		goto err;
+
+	/* low-pass filter */
+	ret = rtl2832_sdr_wr_regs(s, 0x11c,
+			"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+			20);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+	if (ret)
+		goto err;
+
+	/* mode */
+	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
+	if (ret)
+		goto err;
+
+	/* FSM */
+	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3);
+	if (ret)
+		goto err;
+
+	/* PID filter */
+	ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1);
+	if (ret)
+		goto err;
+
+	/* used RF tuner based settings */
+	switch (s->cfg->tuner) {
+	case RTL2832_TUNER_E4000:
+		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
+		break;
+	case RTL2832_TUNER_FC0012:
+	case RTL2832_TUNER_FC0013:
+		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
+		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+		break;
+	case RTL2832_TUNER_R820T:
+		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
+		break;
+	default:
+		dev_notice(&s->udev->dev, "Unsupported tuner\n");
+	}
+
+	/* software reset */
+	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04);
+	if (ret)
+		goto err;
+err:
+	return ret;
+};
+
+static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s)
+{
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	/* PID filter */
+	ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1);
+	if (ret)
+		goto err;
+
+	/* mode */
+	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+	if (ret)
+		goto err;
+
+	/* FSM */
+	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4);
+	if (ret)
+		goto err;
+err:
+	return;
+};
+
+static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
+{
+	struct dvb_frontend *fe = s->fe;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct v4l2_ctrl *bandwidth_auto;
+	struct v4l2_ctrl *bandwidth;
+
+	/*
+	 * tuner RF (Hz)
+	 */
+	if (s->f_tuner == 0)
+		return 0;
+
+	/*
+	 * bandwidth (Hz)
+	 */
+	bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+					V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
+	bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
+	if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
+		c->bandwidth_hz = s->f_adc;
+		v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
+	} else {
+		c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth);
+	}
+
+	c->frequency = s->f_tuner;
+	c->delivery_system = SYS_DVBT;
+
+	dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n",
+			__func__, c->frequency, c->bandwidth_hz);
+
+	if (!test_bit(POWER_ON, &s->flags))
+		return 0;
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	return 0;
+};
+
+static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+{
+	struct dvb_frontend *fe = s->fe;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (fe->ops.tuner_ops.init)
+		fe->ops.tuner_ops.init(fe);
+
+	return 0;
+};
+
+static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
+{
+	struct dvb_frontend *fe = s->fe;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (fe->ops.tuner_ops.sleep)
+		fe->ops.tuner_ops.sleep(fe);
+
+	return;
+};
+
+static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (!s->udev)
+		return -ENODEV;
+
+	if (mutex_lock_interruptible(&s->v4l2_lock))
+		return -ERESTARTSYS;
+
+	if (s->d->props->power_ctrl)
+		s->d->props->power_ctrl(s->d, 1);
+
+	set_bit(POWER_ON, &s->flags);
+
+	ret = rtl2832_sdr_set_tuner(s);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_set_tuner_freq(s);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_set_adc(s);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_alloc_stream_bufs(s);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_sdr_alloc_urbs(s);
+	if (ret)
+		goto err;
+
+	s->sequence = 0;
+
+	ret = rtl2832_sdr_submit_urbs(s);
+	if (ret)
+		goto err;
+
+err:
+	mutex_unlock(&s->v4l2_lock);
+
+	return ret;
+}
+
+static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
+{
+	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->v4l2_lock);
+
+	rtl2832_sdr_kill_urbs(s);
+	rtl2832_sdr_free_urbs(s);
+	rtl2832_sdr_free_stream_bufs(s);
+	rtl2832_sdr_cleanup_queued_bufs(s);
+	rtl2832_sdr_unset_adc(s);
+	rtl2832_sdr_unset_tuner(s);
+
+	clear_bit(POWER_ON, &s->flags);
+
+	if (s->d->props->power_ctrl)
+		s->d->props->power_ctrl(s->d, 0);
+
+	mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops rtl2832_sdr_vb2_ops = {
+	.queue_setup            = rtl2832_sdr_queue_setup,
+	.buf_prepare            = rtl2832_sdr_buf_prepare,
+	.buf_queue              = rtl2832_sdr_buf_queue,
+	.start_streaming        = rtl2832_sdr_start_streaming,
+	.stop_streaming         = rtl2832_sdr_stop_streaming,
+	.wait_prepare           = vb2_ops_wait_prepare,
+	.wait_finish            = vb2_ops_wait_finish,
+};
+
+static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *v)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
+			__func__, v->index, v->type);
+
+	if (v->index == 0) {
+		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =   300000;
+		v->rangehigh = 3200000;
+	} else if (v->index == 1) {
+		strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
+		v->type = V4L2_TUNER_RF;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =    50000000;
+		v->rangehigh = 2000000000;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *v)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (v->index > 1)
+		return -EINVAL;
+	return 0;
+}
+
+static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->tuner == 0) {
+		if (band->index >= ARRAY_SIZE(bands_adc))
+			return -EINVAL;
+
+		*band = bands_adc[band->index];
+	} else if (band->tuner == 1) {
+		if (band->index >= ARRAY_SIZE(bands_fm))
+			return -EINVAL;
+
+		*band = bands_fm[band->index];
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	int ret  = 0;
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+			__func__, f->tuner, f->type);
+
+	if (f->tuner == 0) {
+		f->frequency = s->f_adc;
+		f->type = V4L2_TUNER_ADC;
+	} else if (f->tuner == 1) {
+		f->frequency = s->f_tuner;
+		f->type = V4L2_TUNER_RF;
+	} else {
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
+		const struct v4l2_frequency *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	int ret, band;
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	/* ADC band midpoints */
+	#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
+	#define BAND_ADC_1 ((bands_adc[1].rangehigh + bands_adc[2].rangelow) / 2)
+
+	if (f->tuner == 0 && f->type == V4L2_TUNER_ADC) {
+		if (f->frequency < BAND_ADC_0)
+			band = 0;
+		else if (f->frequency < BAND_ADC_1)
+			band = 1;
+		else
+			band = 2;
+
+		s->f_adc = clamp_t(unsigned int, f->frequency,
+				bands_adc[band].rangelow,
+				bands_adc[band].rangehigh);
+
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = rtl2832_sdr_set_adc(s);
+	} else if (f->tuner == 1) {
+		s->f_tuner = clamp_t(unsigned int, f->frequency,
+				bands_fm[0].rangelow,
+				bands_fm[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+				__func__, f->frequency);
+
+		ret = rtl2832_sdr_set_tuner_freq(s);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_fmtdesc *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (f->index >= s->num_formats)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
+
+	return 0;
+}
+
+static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	f->fmt.sdr.pixelformat = s->pixelformat;
+	f->fmt.sdr.buffersize = s->buffersize;
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+
+	return 0;
+}
+
+static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct vb2_queue *q = &s->vb_queue;
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < s->num_formats; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			s->pixelformat = formats[i].pixelformat;
+			s->buffersize = formats[i].buffersize;
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct rtl2832_sdr_state *s = video_drvdata(file);
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < s->num_formats; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
+	.vidioc_querycap          = rtl2832_sdr_querycap,
+
+	.vidioc_enum_fmt_sdr_cap  = rtl2832_sdr_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = rtl2832_sdr_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = rtl2832_sdr_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = rtl2832_sdr_try_fmt_sdr_cap,
+
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
+
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
+
+	.vidioc_g_tuner           = rtl2832_sdr_g_tuner,
+	.vidioc_s_tuner           = rtl2832_sdr_s_tuner,
+
+	.vidioc_enum_freq_bands   = rtl2832_sdr_enum_freq_bands,
+	.vidioc_g_frequency       = rtl2832_sdr_g_frequency,
+	.vidioc_s_frequency       = rtl2832_sdr_s_frequency,
+
+	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_log_status        = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations rtl2832_sdr_fops = {
+	.owner                    = THIS_MODULE,
+	.open                     = v4l2_fh_open,
+	.release                  = vb2_fop_release,
+	.read                     = vb2_fop_read,
+	.poll                     = vb2_fop_poll,
+	.mmap                     = vb2_fop_mmap,
+	.unlocked_ioctl           = video_ioctl2,
+};
+
+static struct video_device rtl2832_sdr_template = {
+	.name                     = "Realtek RTL2832 SDR",
+	.release                  = video_device_release_empty,
+	.fops                     = &rtl2832_sdr_fops,
+	.ioctl_ops                = &rtl2832_sdr_ioctl_ops,
+};
+
+static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct rtl2832_sdr_state *s =
+			container_of(ctrl->handler, struct rtl2832_sdr_state,
+					hdl);
+	struct dvb_frontend *fe = s->fe;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+
+	dev_dbg(&s->udev->dev,
+			"%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
+			__func__, ctrl->id, ctrl->name, ctrl->val,
+			ctrl->minimum, ctrl->maximum, ctrl->step);
+
+	switch (ctrl->id) {
+	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
+	case V4L2_CID_RF_TUNER_BANDWIDTH:
+		/* TODO: these controls should be moved to tuner drivers */
+		if (s->bandwidth_auto->val) {
+			/* Round towards the closest legal value */
+			s32 val = s->f_adc + div_u64(s->bandwidth->step, 2);
+			u32 offset;
+
+			val = clamp_t(s32, val, s->bandwidth->minimum,
+				      s->bandwidth->maximum);
+			offset = val - s->bandwidth->minimum;
+			offset = s->bandwidth->step *
+				div_u64(offset, s->bandwidth->step);
+			s->bandwidth->val = s->bandwidth->minimum + offset;
+		}
+		c->bandwidth_hz = s->bandwidth->val;
+
+		if (!test_bit(POWER_ON, &s->flags))
+			return 0;
+
+		if (fe->ops.tuner_ops.set_params)
+			ret = fe->ops.tuner_ops.set_params(fe);
+		else
+			ret = 0;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = {
+	.s_ctrl = rtl2832_sdr_s_ctrl,
+};
+
+static void rtl2832_sdr_video_release(struct v4l2_device *v)
+{
+	struct rtl2832_sdr_state *s =
+			container_of(v, struct rtl2832_sdr_state, v4l2_dev);
+
+	v4l2_ctrl_handler_free(&s->hdl);
+	v4l2_device_unregister(&s->v4l2_dev);
+	kfree(s);
+}
+
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+		struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+		struct v4l2_subdev *sd)
+{
+	int ret;
+	struct rtl2832_sdr_state *s;
+	const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
+	struct dvb_usb_device *d = i2c_get_adapdata(i2c);
+
+	s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
+	if (s == NULL) {
+		dev_err(&d->udev->dev,
+				"Could not allocate memory for rtl2832_sdr_state\n");
+		return NULL;
+	}
+
+	/* setup the state */
+	s->fe = fe;
+	s->d = d;
+	s->udev = d->udev;
+	s->i2c = i2c;
+	s->cfg = cfg;
+	s->f_adc = bands_adc[0].rangelow;
+	s->f_tuner = bands_fm[0].rangelow;
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+	s->num_formats = NUM_FORMATS;
+	if (rtl2832_sdr_emulated_fmt == false)
+		s->num_formats -= 1;
+
+	mutex_init(&s->v4l2_lock);
+	mutex_init(&s->vb_queue_lock);
+	spin_lock_init(&s->queued_bufs_lock);
+	INIT_LIST_HEAD(&s->queued_bufs);
+
+	/* Init videobuf2 queue structure */
+	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	s->vb_queue.drv_priv = s;
+	s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
+	s->vb_queue.ops = &rtl2832_sdr_vb2_ops;
+	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	ret = vb2_queue_init(&s->vb_queue);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+		goto err_free_mem;
+	}
+
+	/* Register controls */
+	switch (s->cfg->tuner) {
+	case RTL2832_TUNER_E4000:
+		v4l2_ctrl_handler_init(&s->hdl, 9);
+		if (sd)
+			v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
+		break;
+	case RTL2832_TUNER_R820T:
+		v4l2_ctrl_handler_init(&s->hdl, 2);
+		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+						      V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+						      0, 1, 1, 1);
+		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+						 V4L2_CID_RF_TUNER_BANDWIDTH,
+						 0, 8000000, 100000, 0);
+		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+		break;
+	case RTL2832_TUNER_FC0012:
+	case RTL2832_TUNER_FC0013:
+		v4l2_ctrl_handler_init(&s->hdl, 2);
+		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+						      V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+						      0, 1, 1, 1);
+		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+						 V4L2_CID_RF_TUNER_BANDWIDTH,
+						 6000000, 8000000, 1000000,
+						 6000000);
+		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+		break;
+	default:
+		v4l2_ctrl_handler_init(&s->hdl, 0);
+		dev_notice(&s->udev->dev, "%s: Unsupported tuner\n",
+				KBUILD_MODNAME);
+		goto err_free_controls;
+	}
+
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->udev->dev, "Could not initialize controls\n");
+		goto err_free_controls;
+	}
+
+	/* Init video_device structure */
+	s->vdev = rtl2832_sdr_template;
+	s->vdev.queue = &s->vb_queue;
+	s->vdev.queue->lock = &s->vb_queue_lock;
+	video_set_drvdata(&s->vdev, s);
+
+	/* Register the v4l2_device structure */
+	s->v4l2_dev.release = rtl2832_sdr_video_release;
+	ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register v4l2-device (%d)\n", ret);
+		goto err_free_controls;
+	}
+
+	s->v4l2_dev.ctrl_handler = &s->hdl;
+	s->vdev.v4l2_dev = &s->v4l2_dev;
+	s->vdev.lock = &s->v4l2_lock;
+	s->vdev.vfl_dir = VFL_DIR_RX;
+
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register as video device (%d)\n",
+				ret);
+		goto err_unregister_v4l2_dev;
+	}
+	dev_info(&s->udev->dev, "Registered as %s\n",
+			video_device_node_name(&s->vdev));
+
+	fe->sec_priv = s;
+	fe->ops.release_sec = rtl2832_sdr_release_sec;
+
+	dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
+			KBUILD_MODNAME);
+	dev_notice(&s->udev->dev,
+			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
+			KBUILD_MODNAME);
+	return fe;
+
+err_unregister_v4l2_dev:
+	v4l2_device_unregister(&s->v4l2_dev);
+err_free_controls:
+	v4l2_ctrl_handler_free(&s->hdl);
+err_free_mem:
+	kfree(s);
+	return NULL;
+}
+EXPORT_SYMBOL(rtl2832_sdr_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Realtek RTL2832 SDR driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/rtl2832_sdr.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/rtl2832_sdr.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/rtl2832_sdr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/rtl2832_sdr.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Realtek RTL2832U SDR driver
+ *
+ * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * GNU Radio plugin "gr-kernel" for device usage will be on:
+ * http://git.linuxtv.org/anttip/gr-kernel.git
+ *
+ * TODO:
+ * Help is very highly welcome for these + all the others you could imagine:
+ * - move controls to V4L2 API
+ * - use libv4l2 for stream format conversions
+ * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
+ * - SDRSharp support
+ */
+
+#ifndef RTL2832_SDR_H
+#define RTL2832_SDR_H
+
+#include <linux/kconfig.h>
+#include <media/v4l2-subdev.h>
+
+/* for config struct */
+#include "rtl2832.h"
+
+#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
+extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd)
+{
+	dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* RTL2832_SDR_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165.c	2014-09-28 21:30:04.000000000 -0400
@@ -0,0 +1,1040 @@
+/*
+    Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+    Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.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.
+
+    References:
+    http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "si2165_priv.h"
+#include "si2165.h"
+
+/* Hauppauge WinTV-HVR-930C-HD B130 / PCTV QuatroStick 521e 1113xx
+ * uses 16 MHz xtal */
+
+/* Hauppauge WinTV-HVR-930C-HD B131 / PCTV QuatroStick 522e 1114xx
+ * uses 24 MHz clock provided by tuner */
+
+struct si2165_state {
+	struct i2c_adapter *i2c;
+
+	struct dvb_frontend frontend;
+
+	struct si2165_config config;
+
+	/* chip revision */
+	u8 revcode;
+	/* chip type */
+	u8 chip_type;
+
+	/* calculated by xtal and div settings */
+	u32 fvco_hz;
+	u32 sys_clk;
+	u32 adc_clk;
+
+	bool has_dvbc;
+	bool has_dvbt;
+	bool firmware_loaded;
+};
+
+#define DEBUG_OTHER	0x01
+#define DEBUG_I2C_WRITE	0x02
+#define DEBUG_I2C_READ	0x04
+#define DEBUG_REG_READ	0x08
+#define DEBUG_REG_WRITE	0x10
+#define DEBUG_FW_LOAD	0x20
+
+static int debug = 0x00;
+
+#define dprintk(args...) \
+	do { \
+		if (debug & DEBUG_OTHER) \
+			printk(KERN_DEBUG "si2165: " args); \
+	} while (0)
+
+#define deb_i2c_write(args...) \
+	do { \
+		if (debug & DEBUG_I2C_WRITE) \
+			printk(KERN_DEBUG "si2165: i2c write: " args); \
+	} while (0)
+
+#define deb_i2c_read(args...) \
+	do { \
+		if (debug & DEBUG_I2C_READ) \
+			printk(KERN_DEBUG "si2165: i2c read: " args); \
+	} while (0)
+
+#define deb_readreg(args...) \
+	do { \
+		if (debug & DEBUG_REG_READ) \
+			printk(KERN_DEBUG "si2165: reg read: " args); \
+	} while (0)
+
+#define deb_writereg(args...) \
+	do { \
+		if (debug & DEBUG_REG_WRITE) \
+			printk(KERN_DEBUG "si2165: reg write: " args); \
+	} while (0)
+
+#define deb_fw_load(args...) \
+	do { \
+		if (debug & DEBUG_FW_LOAD) \
+			printk(KERN_DEBUG "si2165: fw load: " args); \
+	} while (0)
+
+static int si2165_write(struct si2165_state *state, const u16 reg,
+		       const u8 *src, const int count)
+{
+	int ret;
+	struct i2c_msg msg;
+	u8 buf[2 + 4]; /* write a maximum of 4 bytes of data */
+
+	if (count + 2 > sizeof(buf)) {
+		dev_warn(&state->i2c->dev,
+			  "%s: i2c wr reg=%04x: count=%d is too big!\n",
+			  KBUILD_MODNAME, reg, count);
+		return -EINVAL;
+	}
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(buf + 2, src, count);
+
+	msg.addr = state->config.i2c_addr;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = count + 2;
+
+	if (debug & DEBUG_I2C_WRITE)
+		deb_i2c_write("reg: 0x%04x, data: %*ph\n", reg, count, src);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1) {
+		dev_err(&state->i2c->dev, "%s: ret == %d\n", __func__, ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int si2165_read(struct si2165_state *state,
+		       const u16 reg, u8 *val, const int count)
+{
+	int ret;
+	u8 reg_buf[] = { reg >> 8, reg & 0xff };
+	struct i2c_msg msg[] = {
+		{ .addr = state->config.i2c_addr,
+		  .flags = 0, .buf = reg_buf, .len = 2 },
+		{ .addr = state->config.i2c_addr,
+		  .flags = I2C_M_RD, .buf = val, .len = count },
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		dev_err(&state->i2c->dev, "%s: error (addr %02x reg %04x error (ret == %i)\n",
+			__func__, state->config.i2c_addr, reg, ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+
+	if (debug & DEBUG_I2C_READ)
+		deb_i2c_read("reg: 0x%04x, data: %*ph\n", reg, count, val);
+
+	return 0;
+}
+
+static int si2165_readreg8(struct si2165_state *state,
+		       const u16 reg, u8 *val)
+{
+	int ret;
+
+	ret = si2165_read(state, reg, val, 1);
+	deb_readreg("R(0x%04x)=0x%02x\n", reg, *val);
+	return ret;
+}
+
+static int si2165_readreg16(struct si2165_state *state,
+		       const u16 reg, u16 *val)
+{
+	u8 buf[2];
+
+	int ret = si2165_read(state, reg, buf, 2);
+	*val = buf[0] | buf[1] << 8;
+	deb_readreg("R(0x%04x)=0x%04x\n", reg, *val);
+	return ret;
+}
+
+static int si2165_writereg8(struct si2165_state *state, const u16 reg, u8 val)
+{
+	return si2165_write(state, reg, &val, 1);
+}
+
+static int si2165_writereg16(struct si2165_state *state, const u16 reg, u16 val)
+{
+	u8 buf[2] = { val & 0xff, (val >> 8) & 0xff };
+
+	return si2165_write(state, reg, buf, 2);
+}
+
+static int si2165_writereg24(struct si2165_state *state, const u16 reg, u32 val)
+{
+	u8 buf[3] = { val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff };
+
+	return si2165_write(state, reg, buf, 3);
+}
+
+static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val)
+{
+	u8 buf[4] = {
+		val & 0xff,
+		(val >> 8) & 0xff,
+		(val >> 16) & 0xff,
+		(val >> 24) & 0xff
+	};
+	return si2165_write(state, reg, buf, 4);
+}
+
+static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg,
+				 u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	if (mask != 0xff) {
+		ret = si2165_readreg8(state, reg, &tmp);
+		if (ret < 0)
+			goto err;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	ret = si2165_writereg8(state, reg, val);
+err:
+	return ret;
+}
+
+static int si2165_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 1000;
+	return 0;
+}
+
+static int si2165_init_pll(struct si2165_state *state)
+{
+	u32 ref_freq_Hz = state->config.ref_freq_Hz;
+	u8 divr = 1; /* 1..7 */
+	u8 divp = 1; /* only 1 or 4 */
+	u8 divn = 56; /* 1..63 */
+	u8 divm = 8;
+	u8 divl = 12;
+	u8 buf[4];
+
+	/* hardcoded values can be deleted if calculation is verified
+	 * or it yields the same values as the windows driver */
+	switch (ref_freq_Hz) {
+	case 16000000u:
+		divn = 56;
+		break;
+	case 24000000u:
+		divr = 2;
+		divp = 4;
+		divn = 19;
+		break;
+	default:
+		/* ref_freq / divr must be between 4 and 16 MHz */
+		if (ref_freq_Hz > 16000000u)
+			divr = 2;
+
+		/* now select divn and divp such that
+		 * fvco is in 1624..1824 MHz */
+		if (1624000000u * divr > ref_freq_Hz * 2u * 63u)
+			divp = 4;
+
+		/* is this already correct regarding rounding? */
+		divn = 1624000000u * divr / (ref_freq_Hz * 2u * divp);
+		break;
+	}
+
+	/* adc_clk and sys_clk depend on xtal and pll settings */
+	state->fvco_hz = ref_freq_Hz / divr
+			* 2u * divn * divp;
+	state->adc_clk = state->fvco_hz / (divm * 4u);
+	state->sys_clk = state->fvco_hz / (divl * 2u);
+
+	/* write pll registers 0x00a0..0x00a3 at once */
+	buf[0] = divl;
+	buf[1] = divm;
+	buf[2] = (divn & 0x3f) | ((divp == 1) ? 0x40 : 0x00) | 0x80;
+	buf[3] = divr;
+	return si2165_write(state, 0x00a0, buf, 4);
+}
+
+static int si2165_adjust_pll_divl(struct si2165_state *state, u8 divl)
+{
+	state->sys_clk = state->fvco_hz / (divl * 2u);
+	return si2165_writereg8(state, 0x00a0, divl); /* pll_divl */
+}
+
+static u32 si2165_get_fe_clk(struct si2165_state *state)
+{
+	/* assume Oversampling mode Ovr4 is used */
+	return state->adc_clk;
+}
+
+static bool si2165_wait_init_done(struct si2165_state *state)
+{
+	int ret = -EINVAL;
+	u8 val = 0;
+	int i;
+
+	for (i = 0; i < 3; ++i) {
+		si2165_readreg8(state, 0x0054, &val);
+		if (val == 0x01)
+			return 0;
+		usleep_range(1000, 50000);
+	}
+	dev_err(&state->i2c->dev, "%s: init_done was not set\n",
+		KBUILD_MODNAME);
+	return ret;
+}
+
+static int si2165_upload_firmware_block(struct si2165_state *state,
+	const u8 *data, u32 len, u32 *poffset, u32 block_count)
+{
+	int ret;
+	u8 buf_ctrl[4] = { 0x00, 0x00, 0x00, 0xc0 };
+	u8 wordcount;
+	u32 cur_block = 0;
+	u32 offset = poffset ? *poffset : 0;
+
+	if (len < 4)
+		return -EINVAL;
+	if (len % 4 != 0)
+		return -EINVAL;
+
+	deb_fw_load("si2165_upload_firmware_block called with len=0x%x offset=0x%x blockcount=0x%x\n",
+				len, offset, block_count);
+	while (offset+12 <= len && cur_block < block_count) {
+		deb_fw_load("si2165_upload_firmware_block in while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
+					len, offset, cur_block, block_count);
+		wordcount = data[offset];
+		if (wordcount < 1 || data[offset+1] ||
+		    data[offset+2] || data[offset+3]) {
+			dev_warn(&state->i2c->dev,
+				 "%s: bad fw data[0..3] = %*ph\n",
+				KBUILD_MODNAME, 4, data);
+			return -EINVAL;
+		}
+
+		if (offset + 8 + wordcount * 4 > len) {
+			dev_warn(&state->i2c->dev,
+				 "%s: len is too small for block len=%d, wordcount=%d\n",
+				KBUILD_MODNAME, len, wordcount);
+			return -EINVAL;
+		}
+
+		buf_ctrl[0] = wordcount - 1;
+
+		ret = si2165_write(state, 0x0364, buf_ctrl, 4);
+		if (ret < 0)
+			goto error;
+		ret = si2165_write(state, 0x0368, data+offset+4, 4);
+		if (ret < 0)
+			goto error;
+
+		offset += 8;
+
+		while (wordcount > 0) {
+			ret = si2165_write(state, 0x36c, data+offset, 4);
+			if (ret < 0)
+				goto error;
+			wordcount--;
+			offset += 4;
+		}
+		cur_block++;
+	}
+
+	deb_fw_load("si2165_upload_firmware_block after while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
+				len, offset, cur_block, block_count);
+
+	if (poffset)
+		*poffset = offset;
+
+	deb_fw_load("si2165_upload_firmware_block returned offset=0x%x\n",
+				offset);
+
+	return 0;
+error:
+	return ret;
+}
+
+static int si2165_upload_firmware(struct si2165_state *state)
+{
+	/* int ret; */
+	u8 val[3];
+	u16 val16;
+	int ret;
+
+	const struct firmware *fw = NULL;
+	u8 *fw_file = SI2165_FIRMWARE;
+	const u8 *data;
+	u32 len;
+	u32 offset;
+	u8 patch_version;
+	u8 block_count;
+	u16 crc_expected;
+
+	/* request the firmware, this will block and timeout */
+	ret = reject_firmware(&fw, fw_file, state->i2c->dev.parent);
+	if (ret) {
+		dev_warn(&state->i2c->dev, "%s: firmare file '%s' not found\n",
+				KBUILD_MODNAME, fw_file);
+		goto error;
+	}
+
+	data = fw->data;
+	len = fw->size;
+
+	dev_info(&state->i2c->dev, "%s: downloading firmware from file '%s' size=%d\n",
+			KBUILD_MODNAME, fw_file, len);
+
+	if (len % 4 != 0) {
+		dev_warn(&state->i2c->dev, "%s: firmware size is not multiple of 4\n",
+				KBUILD_MODNAME);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* check header (8 bytes) */
+	if (len < 8) {
+		dev_warn(&state->i2c->dev, "%s: firmware header is missing\n",
+				KBUILD_MODNAME);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (data[0] != 1 || data[1] != 0) {
+		dev_warn(&state->i2c->dev, "%s: firmware file version is wrong\n",
+				KBUILD_MODNAME);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	patch_version = data[2];
+	block_count = data[4];
+	crc_expected = data[7] << 8 | data[6];
+
+	/* start uploading fw */
+	/* boot/wdog status */
+	ret = si2165_writereg8(state, 0x0341, 0x00);
+	if (ret < 0)
+		goto error;
+	/* reset */
+	ret = si2165_writereg8(state, 0x00c0, 0x00);
+	if (ret < 0)
+		goto error;
+	/* boot/wdog status */
+	ret = si2165_readreg8(state, 0x0341, val);
+	if (ret < 0)
+		goto error;
+
+	/* enable reset on error */
+	ret = si2165_readreg8(state, 0x035c, val);
+	if (ret < 0)
+		goto error;
+	ret = si2165_readreg8(state, 0x035c, val);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x035c, 0x02);
+	if (ret < 0)
+		goto error;
+
+	/* start right after the header */
+	offset = 8;
+
+	dev_info(&state->i2c->dev, "%s: si2165_upload_firmware extracted patch_version=0x%02x, block_count=0x%02x, crc_expected=0x%04x\n",
+		KBUILD_MODNAME, patch_version, block_count, crc_expected);
+
+	ret = si2165_upload_firmware_block(state, data, len, &offset, 1);
+	if (ret < 0)
+		goto error;
+
+	ret = si2165_writereg8(state, 0x0344, patch_version);
+	if (ret < 0)
+		goto error;
+
+	/* reset crc */
+	ret = si2165_writereg8(state, 0x0379, 0x01);
+	if (ret)
+		return ret;
+
+	ret = si2165_upload_firmware_block(state, data, len,
+					   &offset, block_count);
+	if (ret < 0) {
+		dev_err(&state->i2c->dev,
+			"%s: firmare could not be uploaded\n",
+			KBUILD_MODNAME);
+		goto error;
+	}
+
+	/* read crc */
+	ret = si2165_readreg16(state, 0x037a, &val16);
+	if (ret)
+		goto error;
+
+	if (val16 != crc_expected) {
+		dev_err(&state->i2c->dev,
+			"%s: firmware crc mismatch %04x != %04x\n",
+			KBUILD_MODNAME, val16, crc_expected);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = si2165_upload_firmware_block(state, data, len, &offset, 5);
+	if (ret)
+		goto error;
+
+	if (len != offset) {
+		dev_err(&state->i2c->dev,
+			"%s: firmare len mismatch %04x != %04x\n",
+			KBUILD_MODNAME, len, offset);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* reset watchdog error register */
+	ret = si2165_writereg_mask8(state, 0x0341, 0x02, 0x02);
+	if (ret < 0)
+		goto error;
+
+	/* enable reset on error */
+	ret = si2165_writereg_mask8(state, 0x035c, 0x01, 0x01);
+	if (ret < 0)
+		goto error;
+
+	dev_info(&state->i2c->dev, "%s: fw load finished\n", KBUILD_MODNAME);
+
+	ret = 0;
+	state->firmware_loaded = true;
+error:
+	if (fw) {
+		release_firmware(fw);
+		fw = NULL;
+	}
+
+	return ret;
+}
+
+static int si2165_init(struct dvb_frontend *fe)
+{
+	int ret = 0;
+	struct si2165_state *state = fe->demodulator_priv;
+	u8 val;
+	u8 patch_version = 0x00;
+
+	dprintk("%s: called\n", __func__);
+
+	/* powerup */
+	ret = si2165_writereg8(state, 0x0000, state->config.chip_mode);
+	if (ret < 0)
+		goto error;
+	/* dsp_clock_enable */
+	ret = si2165_writereg8(state, 0x0104, 0x01);
+	if (ret < 0)
+		goto error;
+	ret = si2165_readreg8(state, 0x0000, &val); /* verify chip_mode */
+	if (ret < 0)
+		goto error;
+	if (val != state->config.chip_mode) {
+		dev_err(&state->i2c->dev, "%s: could not set chip_mode\n",
+			KBUILD_MODNAME);
+		return -EINVAL;
+	}
+
+	/* agc */
+	ret = si2165_writereg8(state, 0x018b, 0x00);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x0190, 0x01);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x0170, 0x00);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x0171, 0x07);
+	if (ret < 0)
+		goto error;
+	/* rssi pad */
+	ret = si2165_writereg8(state, 0x0646, 0x00);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x0641, 0x00);
+	if (ret < 0)
+		goto error;
+
+	ret = si2165_init_pll(state);
+	if (ret < 0)
+		goto error;
+
+	/* enable chip_init */
+	ret = si2165_writereg8(state, 0x0050, 0x01);
+	if (ret < 0)
+		goto error;
+	/* set start_init */
+	ret = si2165_writereg8(state, 0x0096, 0x01);
+	if (ret < 0)
+		goto error;
+	ret = si2165_wait_init_done(state);
+	if (ret < 0)
+		goto error;
+
+	/* disable chip_init */
+	ret = si2165_writereg8(state, 0x0050, 0x00);
+	if (ret < 0)
+		goto error;
+
+	/* ber_pkt */
+	ret = si2165_writereg16(state, 0x0470 , 0x7530);
+	if (ret < 0)
+		goto error;
+
+	ret = si2165_readreg8(state, 0x0344, &patch_version);
+	if (ret < 0)
+		goto error;
+
+	ret = si2165_writereg8(state, 0x00cb, 0x00);
+	if (ret < 0)
+		goto error;
+
+	/* dsp_addr_jump */
+	ret = si2165_writereg32(state, 0x0348, 0xf4000000);
+	if (ret < 0)
+		goto error;
+	/* boot/wdog status */
+	ret = si2165_readreg8(state, 0x0341, &val);
+	if (ret < 0)
+		goto error;
+
+	if (patch_version == 0x00) {
+		ret = si2165_upload_firmware(state);
+		if (ret < 0)
+			goto error;
+	}
+
+	/* write adc values after each reset*/
+	ret = si2165_writereg8(state, 0x012a, 0x46);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x012c, 0x00);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x012e, 0x0a);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x012f, 0xff);
+	if (ret < 0)
+		goto error;
+	ret = si2165_writereg8(state, 0x0123, 0x70);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+error:
+	return ret;
+}
+
+static int si2165_sleep(struct dvb_frontend *fe)
+{
+	int ret;
+	struct si2165_state *state = fe->demodulator_priv;
+
+	/* dsp clock disable */
+	ret = si2165_writereg8(state, 0x0104, 0x00);
+	if (ret < 0)
+		return ret;
+	/* chip mode */
+	ret = si2165_writereg8(state, 0x0000, SI2165_MODE_OFF);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int si2165_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	int ret;
+	u8 fec_lock = 0;
+	struct si2165_state *state = fe->demodulator_priv;
+
+	if (!state->has_dvbt)
+		return -EINVAL;
+
+	/* check fec_lock */
+	ret = si2165_readreg8(state, 0x4e0, &fec_lock);
+	if (ret < 0)
+		return ret;
+	*status = 0;
+	if (fec_lock & 0x01) {
+		*status |= FE_HAS_SIGNAL;
+		*status |= FE_HAS_CARRIER;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_SYNC;
+		*status |= FE_HAS_LOCK;
+	}
+
+	return 0;
+}
+
+static int si2165_set_oversamp(struct si2165_state *state, u32 dvb_rate)
+{
+	u64 oversamp;
+	u32 reg_value;
+
+	oversamp = si2165_get_fe_clk(state);
+	oversamp <<= 23;
+	do_div(oversamp, dvb_rate);
+	reg_value = oversamp & 0x3fffffff;
+
+	/* oversamp, usbdump contained 0x03100000; */
+	return si2165_writereg32(state, 0x00e4, reg_value);
+}
+
+static int si2165_set_if_freq_shift(struct si2165_state *state, u32 IF)
+{
+	u64 if_freq_shift;
+	s32 reg_value = 0;
+	u32 fe_clk = si2165_get_fe_clk(state);
+
+	if_freq_shift = IF;
+	if_freq_shift <<= 29;
+
+	do_div(if_freq_shift, fe_clk);
+	reg_value = (s32)if_freq_shift;
+
+	if (state->config.inversion)
+		reg_value = -reg_value;
+
+	reg_value = reg_value & 0x1fffffff;
+
+	/* if_freq_shift, usbdump contained 0x023ee08f; */
+	return si2165_writereg32(state, 0x00e8, reg_value);
+}
+
+static int si2165_set_parameters(struct dvb_frontend *fe)
+{
+	int ret;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct si2165_state *state = fe->demodulator_priv;
+	u8 val[3];
+	u32 IF;
+	u32 dvb_rate = 0;
+	u16 bw10k;
+
+	dprintk("%s: called\n", __func__);
+
+	if (!fe->ops.tuner_ops.get_if_frequency) {
+		dev_err(&state->i2c->dev,
+			"%s: Error: get_if_frequency() not defined at tuner. Can't work without it!\n",
+			KBUILD_MODNAME);
+		return -EINVAL;
+	}
+
+	if (!state->has_dvbt)
+		return -EINVAL;
+
+	if (p->bandwidth_hz > 0) {
+		dvb_rate = p->bandwidth_hz * 8 / 7;
+		bw10k = p->bandwidth_hz / 10000;
+	} else {
+		dvb_rate = 8 * 8 / 7;
+		bw10k = 800;
+	}
+
+	/* standard = DVB-T */
+	ret = si2165_writereg8(state, 0x00ec, 0x01);
+	if (ret < 0)
+		return ret;
+	ret = si2165_adjust_pll_divl(state, 12);
+	if (ret < 0)
+		return ret;
+
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	ret = si2165_set_if_freq_shift(state, IF);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x08f8, 0x00);
+	if (ret < 0)
+		return ret;
+	/* ts output config */
+	ret = si2165_writereg8(state, 0x04e4, 0x20);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg16(state, 0x04ef, 0x00fe);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg24(state, 0x04f4, 0x555555);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x04e5, 0x01);
+	if (ret < 0)
+		return ret;
+	/* bandwidth in 10KHz steps */
+	ret = si2165_writereg16(state, 0x0308, bw10k);
+	if (ret < 0)
+		return ret;
+	ret = si2165_set_oversamp(state, dvb_rate);
+	if (ret < 0)
+		return ret;
+	/* impulsive_noise_remover */
+	ret = si2165_writereg8(state, 0x031c, 0x01);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x00cb, 0x00);
+	if (ret < 0)
+		return ret;
+	/* agc2 */
+	ret = si2165_writereg8(state, 0x016e, 0x41);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x016c, 0x0e);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x016d, 0x10);
+	if (ret < 0)
+		return ret;
+	/* agc */
+	ret = si2165_writereg8(state, 0x015b, 0x03);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x0150, 0x78);
+	if (ret < 0)
+		return ret;
+	/* agc */
+	ret = si2165_writereg8(state, 0x01a0, 0x78);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x01c8, 0x68);
+	if (ret < 0)
+		return ret;
+	/* freq_sync_range */
+	ret = si2165_writereg16(state, 0x030c, 0x0064);
+	if (ret < 0)
+		return ret;
+	/* gp_reg0 */
+	ret = si2165_readreg8(state, 0x0387, val);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x0387, 0x00);
+	if (ret < 0)
+		return ret;
+	/* dsp_addr_jump */
+	ret = si2165_writereg32(state, 0x0348, 0xf4000000);
+	if (ret < 0)
+		return ret;
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* recalc if_freq_shift if IF might has changed */
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	ret = si2165_set_if_freq_shift(state, IF);
+	if (ret < 0)
+		return ret;
+
+	/* boot/wdog status */
+	ret = si2165_readreg8(state, 0x0341, val);
+	if (ret < 0)
+		return ret;
+	ret = si2165_writereg8(state, 0x0341, 0x00);
+	if (ret < 0)
+		return ret;
+	/* reset all */
+	ret = si2165_writereg8(state, 0x00c0, 0x00);
+	if (ret < 0)
+		return ret;
+	/* gp_reg0 */
+	ret = si2165_writereg32(state, 0x0384, 0x00000000);
+	if (ret < 0)
+		return ret;
+	/* start_synchro */
+	ret = si2165_writereg8(state, 0x02e0, 0x01);
+	if (ret < 0)
+		return ret;
+	/* boot/wdog status */
+	ret = si2165_readreg8(state, 0x0341, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void si2165_release(struct dvb_frontend *fe)
+{
+	struct si2165_state *state = fe->demodulator_priv;
+
+	dprintk("%s: called\n", __func__);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops si2165_ops = {
+	.info = {
+		.name = "Silicon Labs Si2165",
+		.caps =	FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_32 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 |
+			FE_CAN_QAM_256 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_MUTE_TS |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_RECOVER
+	},
+
+	.get_tune_settings = si2165_get_tune_settings,
+
+	.init = si2165_init,
+	.sleep = si2165_sleep,
+
+	.set_frontend      = si2165_set_parameters,
+	.read_status       = si2165_read_status,
+
+	.release = si2165_release,
+};
+
+struct dvb_frontend *si2165_attach(const struct si2165_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct si2165_state *state = NULL;
+	int n;
+	int io_ret;
+	u8 val;
+
+	if (config == NULL || i2c == NULL)
+		goto error;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct si2165_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	state->config = *config;
+
+	if (state->config.ref_freq_Hz < 4000000
+	    || state->config.ref_freq_Hz > 27000000) {
+		dev_err(&state->i2c->dev, "%s: ref_freq of %d Hz not supported by this driver\n",
+			 KBUILD_MODNAME, state->config.ref_freq_Hz);
+		goto error;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &si2165_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* powerup */
+	io_ret = si2165_writereg8(state, 0x0000, state->config.chip_mode);
+	if (io_ret < 0)
+		goto error;
+
+	io_ret = si2165_readreg8(state, 0x0000, &val);
+	if (io_ret < 0)
+		goto error;
+	if (val != state->config.chip_mode)
+		goto error;
+
+	io_ret = si2165_readreg8(state, 0x0023 , &state->revcode);
+	if (io_ret < 0)
+		goto error;
+
+	io_ret = si2165_readreg8(state, 0x0118, &state->chip_type);
+	if (io_ret < 0)
+		goto error;
+
+	/* powerdown */
+	io_ret = si2165_writereg8(state, 0x0000, SI2165_MODE_OFF);
+	if (io_ret < 0)
+		goto error;
+
+	dev_info(&state->i2c->dev, "%s: hardware revision 0x%02x, chip type 0x%02x\n",
+		 KBUILD_MODNAME, state->revcode, state->chip_type);
+
+	/* It is a guess that register 0x0118 (chip type?) can be used to
+	 * differ between si2161, si2163 and si2165
+	 * Only si2165 has been tested.
+	 */
+	if (state->revcode == 0x03 && state->chip_type == 0x07) {
+		state->has_dvbt = true;
+		state->has_dvbc = true;
+	} else {
+		dev_err(&state->i2c->dev, "%s: Unsupported chip.\n",
+			KBUILD_MODNAME);
+		goto error;
+	}
+
+	n = 0;
+	if (state->has_dvbt) {
+		state->frontend.ops.delsys[n++] = SYS_DVBT;
+		strlcat(state->frontend.ops.info.name, " DVB-T",
+			sizeof(state->frontend.ops.info.name));
+	}
+	if (state->has_dvbc)
+		dev_warn(&state->i2c->dev, "%s: DVB-C is not yet supported.\n",
+		       KBUILD_MODNAME);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(si2165_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver");
+MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
+MODULE_LICENSE("GPL");
+/*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+    Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+    Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.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.
+
+    References:
+    http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
+*/
+
+#ifndef _DVB_SI2165_H
+#define _DVB_SI2165_H
+
+#include <linux/dvb/frontend.h>
+
+enum {
+	SI2165_MODE_OFF = 0x00,
+	SI2165_MODE_PLL_EXT = 0x20,
+	SI2165_MODE_PLL_XTAL = 0x21
+};
+
+struct si2165_config {
+	/* i2c addr
+	 * possible values: 0x64,0x65,0x66,0x67 */
+	u8 i2c_addr;
+
+	/* external clock or XTAL */
+	u8 chip_mode;
+
+	/* frequency of external clock or xtal in Hz
+	 * possible values: 4000000, 16000000, 20000000, 240000000, 27000000
+	 */
+	u32 ref_freq_Hz;
+
+	/* invert the spectrum */
+	bool inversion;
+};
+
+#if IS_ENABLED(CONFIG_DVB_SI2165)
+struct dvb_frontend *si2165_attach(
+	const struct si2165_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *si2165_attach(
+	const struct si2165_config *config,
+	struct i2c_adapter *i2c)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_SI2165 */
+
+#endif /* _DVB_SI2165_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165_priv.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165_priv.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2165_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2165_priv.h	2014-09-28 21:30:06.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+    Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+    Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.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 _DVB_SI2165_PRIV
+#define _DVB_SI2165_PRIV
+
+#define SI2165_FIRMWARE "/*(DEBLOBBED)*/"
+
+#endif /* _DVB_SI2165_PRIV */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2168.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2168.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2168.c	2014-08-07 04:49:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2168.c	2014-09-28 21:30:09.000000000 -0400
@@ -95,20 +95,17 @@ static int si2168_read_status(struct dvb
 
 	switch (c->delivery_system) {
 	case SYS_DVBT:
-		cmd.args[0] = 0xa0;
-		cmd.args[1] = 0x01;
+		memcpy(cmd.args, "\xa0\x01", 2);
 		cmd.wlen = 2;
 		cmd.rlen = 13;
 		break;
 	case SYS_DVBC_ANNEX_A:
-		cmd.args[0] = 0x90;
-		cmd.args[1] = 0x01;
+		memcpy(cmd.args, "\x90\x01", 2);
 		cmd.wlen = 2;
 		cmd.rlen = 9;
 		break;
 	case SYS_DVBT2:
-		cmd.args[0] = 0x50;
-		cmd.args[1] = 0x01;
+		memcpy(cmd.args, "\x50\x01", 2);
 		cmd.wlen = 2;
 		cmd.rlen = 14;
 		break;
@@ -144,6 +141,15 @@ static int si2168_read_status(struct dvb
 
 	s->fe_status = *status;
 
+	if (*status & FE_HAS_LOCK) {
+		c->cnr.len = 1;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+		c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
+	} else {
+		c->cnr.len = 1;
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
 	dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
 			__func__, *status, cmd.rlen, cmd.args);
 
@@ -243,51 +249,23 @@ static int si2168_set_frontend(struct dv
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
 	memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
@@ -295,124 +273,66 @@ static int si2168_set_frontend(struct dv
 	memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
 	cmd.args[4] = delivery_system | bandwidth;
 	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
+	/* set DVB-C symbol rate */
+	if (c->delivery_system == SYS_DVBC_ANNEX_A) {
+		memcpy(cmd.args, "\x14\x00\x02\x11", 4);
+		cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
+		cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+		cmd.wlen = 6;
+		cmd.rlen = 4;
+		ret = si2168_cmd_execute(s, &cmd);
+		if (ret)
+			goto err;
+	}
 
 	memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+	memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
-	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
+	memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
+	memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
 	cmd.wlen = 6;
-	cmd.rlen = 1;
+	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	cmd.args[0] = 0x85;
+	memcpy(cmd.args, "\x85", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 1;
 	ret = si2168_cmd_execute(s, &cmd);
@@ -432,59 +352,61 @@ static int si2168_init(struct dvb_fronte
 	struct si2168 *s = fe->demodulator_priv;
 	int ret, len, remaining;
 	const struct firmware *fw = NULL;
-	u8 *fw_file = SI2168_FIRMWARE;
+	u8 *fw_file;
 	const unsigned int i2c_wr_max = 8;
 	struct si2168_cmd cmd;
+	unsigned int chip_id;
 
 	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
-	cmd.args[0] = 0x13;
-	cmd.wlen = 1;
-	cmd.rlen = 0;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	cmd.args[0] = 0xc0;
-	cmd.args[1] = 0x12;
-	cmd.args[2] = 0x00;
-	cmd.args[3] = 0x0c;
-	cmd.args[4] = 0x00;
-	cmd.args[5] = 0x0d;
-	cmd.args[6] = 0x16;
-	cmd.args[7] = 0x00;
-	cmd.args[8] = 0x00;
-	cmd.args[9] = 0x00;
-	cmd.args[10] = 0x00;
-	cmd.args[11] = 0x00;
-	cmd.args[12] = 0x00;
+	memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
 	cmd.wlen = 13;
 	cmd.rlen = 0;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	cmd.args[0] = 0xc0;
-	cmd.args[1] = 0x06;
-	cmd.args[2] = 0x01;
-	cmd.args[3] = 0x0f;
-	cmd.args[4] = 0x00;
-	cmd.args[5] = 0x20;
-	cmd.args[6] = 0x20;
-	cmd.args[7] = 0x01;
+	memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
 	cmd.wlen = 8;
 	cmd.rlen = 1;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	cmd.args[0] = 0x02;
+	/* query chip revision */
+	memcpy(cmd.args, "\x02", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 13;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
+	chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+			cmd.args[4] << 0;
+
+	#define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
+	#define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
+	#define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
+
+	switch (chip_id) {
+	case SI2168_A20:
+		fw_file = SI2168_A20_FIRMWARE;
+		break;
+	case SI2168_A30:
+		fw_file = SI2168_A30_FIRMWARE;
+		break;
+	case SI2168_B40:
+		fw_file = SI2168_B40_FIRMWARE;
+		break;
+	default:
+		dev_err(&s->client->dev,
+				"%s: unkown chip version Si21%d-%c%c%c\n",
+				KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+				cmd.args[3], cmd.args[4]);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	/* cold state - try to download firmware */
 	dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
 			KBUILD_MODNAME, si2168_ops.info.name);
@@ -492,9 +414,22 @@ static int si2168_init(struct dvb_fronte
 	/* request the firmware, this will block and timeout */
 	ret = reject_firmware(&fw, fw_file, &s->client->dev);
 	if (ret) {
-		dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
-				KBUILD_MODNAME, fw_file);
-		goto err;
+		/* fallback mechanism to handle old name for Si2168 B40 fw */
+		if (chip_id == SI2168_B40) {
+			fw_file = SI2168_B40_FIRMWARE_FALLBACK;
+			ret = reject_firmware(&fw, fw_file, &s->client->dev);
+		}
+
+		if (ret == 0) {
+			dev_notice(&s->client->dev,
+					"%s: please install firmware file '%s'\n",
+					KBUILD_MODNAME, SI2168_B40_FIRMWARE);
+		} else {
+			dev_err(&s->client->dev,
+					"%s: firmware file '%s' not found\n",
+					KBUILD_MODNAME, fw_file);
+			goto err;
+		}
 	}
 
 	dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
@@ -520,8 +455,7 @@ static int si2168_init(struct dvb_fronte
 	release_firmware(fw);
 	fw = NULL;
 
-	cmd.args[0] = 0x01;
-	cmd.args[1] = 0x01;
+	memcpy(cmd.args, "\x01\x01", 2);
 	cmd.wlen = 2;
 	cmd.rlen = 1;
 	ret = si2168_cmd_execute(s, &cmd);
@@ -545,12 +479,24 @@ err:
 static int si2168_sleep(struct dvb_frontend *fe)
 {
 	struct si2168 *s = fe->demodulator_priv;
+	int ret;
+	struct si2168_cmd cmd;
 
 	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
 	s->active = false;
 
+	memcpy(cmd.args, "\x13", 1);
+	cmd.wlen = 1;
+	cmd.rlen = 0;
+	ret = si2168_cmd_execute(s, &cmd);
+	if (ret)
+		goto err;
+
 	return 0;
+err:
+	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
 }
 
 static int si2168_get_tune_settings(struct dvb_frontend *fe,
@@ -660,7 +606,6 @@ static int si2168_probe(struct i2c_clien
 	struct si2168_config *config = client->dev.platform_data;
 	struct si2168 *s;
 	int ret;
-	struct si2168_cmd cmd;
 
 	dev_dbg(&client->dev, "%s:\n", __func__);
 
@@ -674,18 +619,13 @@ static int si2168_probe(struct i2c_clien
 	s->client = client;
 	mutex_init(&s->i2c_mutex);
 
-	/* check if the demod is there */
-	cmd.wlen = 0;
-	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
 	/* create mux i2c adapter for tuner */
 	s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
 			0, 0, 0, si2168_select, si2168_deselect);
-	if (s->adapter == NULL)
+	if (s->adapter == NULL) {
+		ret = -ENODEV;
 		goto err;
+	}
 
 	/* create dvb_frontend */
 	memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2168_priv.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2168_priv.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/si2168_priv.h	2014-08-07 04:49:04.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/si2168_priv.h	2014-09-28 21:30:11.000000000 -0400
@@ -22,7 +22,10 @@
 #include <linux/firmware.h>
 #include <linux/i2c-mux.h>
 
-#define SI2168_FIRMWARE "/*(DEBLOBBED)*/"
+#define SI2168_A20_FIRMWARE "/*(DEBLOBBED)*/"
+#define SI2168_A30_FIRMWARE "/*(DEBLOBBED)*/"
+#define SI2168_B40_FIRMWARE "/*(DEBLOBBED)*/"
+#define SI2168_B40_FIRMWARE_FALLBACK "/*(DEBLOBBED)*/"
 
 /* state struct */
 struct si2168 {
@@ -36,9 +39,9 @@ struct si2168 {
 };
 
 /* firmare command struct */
-#define SI2157_ARGLEN      30
+#define SI2168_ARGLEN      30
 struct si2168_cmd {
-	u8 args[SI2157_ARGLEN];
+	u8 args[SI2168_ARGLEN];
 	unsigned wlen;
 	unsigned rlen;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/stb6100_cfg.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stb6100_cfg.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/stb6100_cfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stb6100_cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,17 +21,14 @@
 
 static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	t_state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
@@ -42,18 +39,16 @@ static int stb6100_get_frequency(struct
 
 static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	t_state;
 	int err = 0;
 
 	t_state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
+
 	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+		err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
@@ -68,12 +63,9 @@ static int stb6100_get_bandwidth(struct
 	struct tuner_state	t_state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
@@ -84,18 +76,16 @@ static int stb6100_get_bandwidth(struct
 
 static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	t_state;
 	int err = 0;
 
 	t_state.bandwidth = bandwidth;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
+
 	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+		err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/stb6100_proc.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stb6100_proc.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/stb6100_proc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stb6100_proc.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,15 +19,11 @@
 
 static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
 		if (frontend_ops->i2c_gate_ctrl)
 			frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -49,16 +45,13 @@ static int stb6100_get_freq(struct dvb_f
 
 static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	state;
 	int err = 0;
 
 	state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
+
 	if (tuner_ops->set_state) {
 		if (frontend_ops->i2c_gate_ctrl)
 			frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -79,15 +72,11 @@ static int stb6100_set_freq(struct dvb_f
 
 static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
 		if (frontend_ops->i2c_gate_ctrl)
 			frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -109,16 +98,13 @@ static int stb6100_get_bandw(struct dvb_
 
 static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	state;
 	int err = 0;
 
 	state.bandwidth = bandwidth;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
+
 	if (tuner_ops->set_state) {
 		if (frontend_ops->i2c_gate_ctrl)
 			frontend_ops->i2c_gate_ctrl(fe, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/stv0367.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stv0367.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/stv0367.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/stv0367.c	2014-09-28 17:29:07.000000000 -0400
@@ -922,18 +922,13 @@ static int stv0367ter_gate_ctrl(struct d
 
 static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	u32 freq = 0;
 	int err = 0;
 
 	dprintk("%s:\n", __func__);
 
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_frequency) {
 		err = tuner_ops->get_frequency(fe, &freq);
 		if (err < 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda18271c2dd.c linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda18271c2dd.c
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda18271c2dd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda18271c2dd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1030,7 +1030,7 @@ static int ChannelConfiguration(struct t
 			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
 
 		if ((Standard == HF_FM_Radio) && state->m_bFMInput)
-			state->m_Regs[EP4] |= 80;
+			state->m_Regs[EP4] |= 0x80;
 
 		state->m_Regs[MPD] &= ~0x80;
 		if (Standard > HF_AnalogMax)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda18271c2dd_maps.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda18271c2dd_maps.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda18271c2dd_maps.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda18271c2dd_maps.h	2014-09-28 17:29:07.000000000 -0400
@@ -5,7 +5,7 @@ enum HF_S {
 	HF_DVBC_8MHZ, HF_DVBC
 };
 
-struct SStandardParam m_StandardTable[] = {
+static struct SStandardParam m_StandardTable[] = {
 	{       0,        0, 0x00, 0x00 },    /* HF_None */
 	{ 6000000,  7000000, 0x1D, 0x2C },    /* HF_B, */
 	{ 6900000,  8000000, 0x1E, 0x2C },    /* HF_DK, */
@@ -27,7 +27,7 @@ struct SStandardParam m_StandardTable[]
 	{       0,        0, 0x00, 0x00 },    /* HF_DVBC (Unused) */
 };
 
-struct SMap  m_BP_Filter_Map[] = {
+static struct SMap  m_BP_Filter_Map[] = {
 	{   62000000,  0x00 },
 	{   84000000,  0x01 },
 	{  100000000,  0x02 },
@@ -799,14 +799,14 @@ static struct SRFBandMap  m_RF_Band_Map[
 	{  865000000,  489500000,   697500000,  842000000},
 };
 
-u8 m_Thermometer_Map_1[16] = {
+static u8 m_Thermometer_Map_1[16] = {
 	60, 62, 66, 64,
 	74, 72, 68, 70,
 	90, 88, 84, 86,
 	76, 78, 82, 80,
 };
 
-u8 m_Thermometer_Map_2[16] = {
+static u8 m_Thermometer_Map_2[16] = {
 	92, 94, 98, 96,
 	106, 104, 100, 102,
 	122, 120, 116, 118,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda8261_cfg.h linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda8261_cfg.h
--- linux-libre-3.16-gnu/drivers/media/dvb-frontends/tda8261_cfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/dvb-frontends/tda8261_cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,17 +19,14 @@
 
 static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	t_state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
@@ -41,18 +38,16 @@ static int tda8261_get_frequency(struct
 
 static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
 {
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
 	struct tuner_state	t_state;
 	int err = 0;
 
 	t_state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
+
 	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+		err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
@@ -68,12 +63,9 @@ static int tda8261_get_bandwidth(struct
 	struct tuner_state	t_state;
 	int err = 0;
 
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
 	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+		if (err < 0) {
 			printk("%s: Invalid parameter\n", __func__);
 			return err;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/adv7180.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/adv7180.c
--- linux-libre-3.16-gnu/drivers/media/i2c/adv7180.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/adv7180.c	2014-09-28 17:29:07.000000000 -0400
@@ -663,7 +663,6 @@ static int adv7180_remove(struct i2c_cli
 	if (state->irq > 0)
 		free_irq(client->irq, state);
 
-	v4l2_device_unregister_subdev(sd);
 	adv7180_exit_controls(state);
 	mutex_destroy(&state->mutex);
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/adv7604.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/adv7604.c
--- linux-libre-3.16-gnu/drivers/media/i2c/adv7604.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/adv7604.c	2014-09-28 17:29:07.000000000 -0400
@@ -2325,7 +2325,7 @@ static int adv7604_log_status(struct v4l
 	v4l2_info(sd, "HDCP keys read: %s%s\n",
 			(hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no",
 			(hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : "");
-	if (!is_hdmi(sd)) {
+	if (is_hdmi(sd)) {
 		bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01;
 		bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01;
 		bool audio_mute = io_read(sd, 0x65) & 0x40;
@@ -2588,8 +2588,11 @@ static const struct adv7604_reg_seq adv7
 };
 
 static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+	/* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
 	{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
-	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
 	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
 	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
 	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/ir-kbd-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/ir-kbd-i2c.c
--- linux-libre-3.16-gnu/drivers/media/i2c/ir-kbd-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/ir-kbd-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,8 +62,8 @@ module_param(debug, int, 0644);    /* de
 
 /* ----------------------------------------------------------------------- */
 
-static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
-			       int size, int offset)
+static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol,
+			       u32 *scancode, u8 *ptoggle, int size, int offset)
 {
 	unsigned char buf[6];
 	int start, range, toggle, dev, code, ircode;
@@ -86,19 +86,10 @@ static int get_key_haup_common(struct IR
 	if (!start)
 		/* no key pressed */
 		return 0;
-	/*
-	 * Hauppauge remotes (black/silver) always use
-	 * specific device ids. If we do not filter the
-	 * device ids then messages destined for devices
-	 * such as TVs (id=0) will get through causing
-	 * mis-fired events.
-	 *
-	 * We also filter out invalid key presses which
-	 * produce annoying debug log entries.
-	 */
-	ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
-	if ((ircode & 0x1fff)==0x1fff)
-		/* invalid key press */
+
+	/* filter out invalid key presses */
+	ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
+	if ((ircode & 0x1fff) == 0x1fff)
 		return 0;
 
 	if (!range)
@@ -107,18 +98,20 @@ static int get_key_haup_common(struct IR
 	dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
 		start, range, toggle, dev, code);
 
-	/* return key */
-	*ir_key = (dev << 8) | code;
-	*ir_raw = ircode;
+	*protocol = RC_TYPE_RC5;
+	*scancode = RC_SCANCODE_RC5(dev, code);
+	*ptoggle = toggle;
 	return 1;
 }
 
-static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,
+			u32 *scancode, u8 *toggle)
 {
-	return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+	return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0);
 }
 
-static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,
+			    u32 *scancode, u8 *toggle)
 {
 	int ret;
 	unsigned char buf[1] = { 0 };
@@ -133,10 +126,11 @@ static int get_key_haup_xvr(struct IR_i2
 	if (ret != 1)
 		return (ret < 0) ? ret : -EINVAL;
 
-	return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+	return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3);
 }
 
-static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol,
+			     u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 
@@ -145,12 +139,15 @@ static int get_key_pixelview(struct IR_i
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
-	*ir_key = b;
-	*ir_raw = b;
+
+	*protocol = RC_TYPE_OTHER;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_type *protocol,
+			      u32 *scancode, u8 *toggle)
 {
 	unsigned char buf[4];
 
@@ -168,13 +165,14 @@ static int get_key_fusionhdtv(struct IR_
 	if(buf[0] != 0x1 ||  buf[1] != 0xfe)
 		return 0;
 
-	*ir_key = buf[2];
-	*ir_raw = (buf[2] << 8) | buf[3];
-
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = buf[2];
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_knc1(struct IR_i2c *ir, enum rc_type *protocol,
+			u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 
@@ -197,13 +195,14 @@ static int get_key_knc1(struct IR_i2c *i
 		/* keep old data */
 		return 1;
 
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_avermedia_cardbus(struct IR_i2c *ir,
-				     u32 *ir_key, u32 *ir_raw)
+static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_type *protocol,
+				     u32 *scancode, u8 *toggle)
 {
 	unsigned char subaddr, key, keygroup;
 	struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
@@ -237,12 +236,11 @@ static int get_key_avermedia_cardbus(str
 	}
 	key |= (keygroup & 1) << 6;
 
-	*ir_key = key;
-	*ir_raw = key;
-	if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
-		*ir_key |= keygroup << 8;
-		*ir_raw |= keygroup << 8;
-	}
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = key;
+	if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */
+		*scancode |= keygroup << 8;
+	*toggle = 0;
 	return 1;
 }
 
@@ -250,19 +248,22 @@ static int get_key_avermedia_cardbus(str
 
 static int ir_key_poll(struct IR_i2c *ir)
 {
-	static u32 ir_key, ir_raw;
+	enum rc_type protocol;
+	u32 scancode;
+	u8 toggle;
 	int rc;
 
 	dprintk(3, "%s\n", __func__);
-	rc = ir->get_key(ir, &ir_key, &ir_raw);
+	rc = ir->get_key(ir, &protocol, &scancode, &toggle);
 	if (rc < 0) {
 		dprintk(2,"error\n");
 		return rc;
 	}
 
 	if (rc) {
-		dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
-		rc_keydown(ir->rc, ir_key, 0);
+		dprintk(1, "%s: proto = 0x%04x, scancode = 0x%08x\n",
+			__func__, protocol, scancode);
+		rc_keydown(ir->rc, protocol, scancode, toggle);
 	}
 	return 0;
 }
@@ -327,7 +328,7 @@ static int ir_probe(struct i2c_client *c
 	case 0x6b:
 		name        = "FusionHDTV";
 		ir->get_key = get_key_fusionhdtv;
-		rc_type     = RC_BIT_RC5;
+		rc_type     = RC_BIT_UNKNOWN;
 		ir_codes    = RC_MAP_FUSIONHDTV_MCE;
 		break;
 	case 0x40:
@@ -431,8 +432,8 @@ static int ir_probe(struct i2c_client *c
 	 * Initialize the other fields of rc_dev
 	 */
 	rc->map_name       = ir->ir_codes;
-	rc_set_allowed_protocols(rc, rc_type);
-	rc_set_enabled_protocols(rc, rc_type);
+	rc->allowed_protocols = rc_type;
+	rc->enabled_protocols = rc_type;
 	if (!rc->driver_name)
 		rc->driver_name = MODULE_NAME;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/i2c/Kconfig
--- linux-libre-3.16-gnu/drivers/media/i2c/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -551,6 +551,7 @@ config VIDEO_MT9V032
 	tristate "Micron MT9V032 sensor support"
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
 	depends on MEDIA_CAMERA_SUPPORT
+	select REGMAP_I2C
 	---help---
 	  This is a Video4Linux2 sensor-level driver for the Micron
 	  MT9V032 752x480 CMOS sensor.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/mt9v032.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/mt9v032.c
--- linux-libre-3.16-gnu/drivers/media/i2c/mt9v032.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/mt9v032.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Driver for MT9V032 CMOS Image Sensor from Micron
+ * Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
  *
  * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  *
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/mutex.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/v4l2-mediabus.h>
@@ -87,6 +88,7 @@
 #define		MT9V032_READ_MODE_COLUMN_FLIP		(1 << 5)
 #define		MT9V032_READ_MODE_DARK_COLUMNS		(1 << 6)
 #define		MT9V032_READ_MODE_DARK_ROWS		(1 << 7)
+#define		MT9V032_READ_MODE_RESERVED		0x0300
 #define MT9V032_PIXEL_OPERATION_MODE			0x0f
 #define		MT9V034_PIXEL_OPERATION_MODE_HDR	(1 << 0)
 #define		MT9V034_PIXEL_OPERATION_MODE_COLOR	(1 << 1)
@@ -133,8 +135,12 @@
 #define MT9V032_THERMAL_INFO				0xc1
 
 enum mt9v032_model {
-	MT9V032_MODEL_V032_COLOR,
-	MT9V032_MODEL_V032_MONO,
+	MT9V032_MODEL_V022_COLOR,	/* MT9V022IX7ATC */
+	MT9V032_MODEL_V022_MONO,	/* MT9V022IX7ATM */
+	MT9V032_MODEL_V024_COLOR,	/* MT9V024IA7XTC */
+	MT9V032_MODEL_V024_MONO,	/* MT9V024IA7XTM */
+	MT9V032_MODEL_V032_COLOR,	/* MT9V032C12STM */
+	MT9V032_MODEL_V032_MONO,	/* MT9V032C12STC */
 	MT9V032_MODEL_V034_COLOR,
 	MT9V032_MODEL_V034_MONO,
 };
@@ -160,14 +166,14 @@ struct mt9v032_model_info {
 };
 
 static const struct mt9v032_model_version mt9v032_versions[] = {
-	{ MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
-	{ MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
-	{ MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
+	{ MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
+	{ MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
+	{ MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
 };
 
 static const struct mt9v032_model_data mt9v032_model_data[] = {
 	{
-		/* MT9V032 revisions 1/2/3 */
+		/* MT9V022, MT9V032 revisions 1/2/3 */
 		.min_row_time = 660,
 		.min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
 		.min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
@@ -176,7 +182,7 @@ static const struct mt9v032_model_data m
 		.max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
 		.pclk_reg = MT9V032_PIXEL_CLOCK,
 	}, {
-		/* MT9V034 */
+		/* MT9V024, MT9V034 */
 		.min_row_time = 690,
 		.min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
 		.min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
@@ -188,6 +194,22 @@ static const struct mt9v032_model_data m
 };
 
 static const struct mt9v032_model_info mt9v032_models[] = {
+	[MT9V032_MODEL_V022_COLOR] = {
+		.data = &mt9v032_model_data[0],
+		.color = true,
+	},
+	[MT9V032_MODEL_V022_MONO] = {
+		.data = &mt9v032_model_data[0],
+		.color = false,
+	},
+	[MT9V032_MODEL_V024_COLOR] = {
+		.data = &mt9v032_model_data[1],
+		.color = true,
+	},
+	[MT9V032_MODEL_V024_MONO] = {
+		.data = &mt9v032_model_data[1],
+		.color = false,
+	},
 	[MT9V032_MODEL_V032_COLOR] = {
 		.data = &mt9v032_model_data[0],
 		.color = true,
@@ -224,6 +246,7 @@ struct mt9v032 {
 	struct mutex power_lock;
 	int power_count;
 
+	struct regmap *regmap;
 	struct clk *clk;
 
 	struct mt9v032_platform_data *pdata;
@@ -231,7 +254,6 @@ struct mt9v032 {
 	const struct mt9v032_model_version *version;
 
 	u32 sysclk;
-	u16 chip_control;
 	u16 aec_agc;
 	u16 hblank;
 	struct {
@@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct
 	return container_of(sd, struct mt9v032, subdev);
 }
 
-static int mt9v032_read(struct i2c_client *client, const u8 reg)
-{
-	s32 data = i2c_smbus_read_word_swapped(client, reg);
-	dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
-		data, reg);
-	return data;
-}
-
-static int mt9v032_write(struct i2c_client *client, const u8 reg,
-			 const u16 data)
-{
-	dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
-		data, reg);
-	return i2c_smbus_write_word_swapped(client, reg, data);
-}
-
-static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
-	u16 value = (mt9v032->chip_control & ~clear) | set;
-	int ret;
-
-	ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
-	if (ret < 0)
-		return ret;
-
-	mt9v032->chip_control = value;
-	return 0;
-}
-
 static int
 mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	struct regmap *map = mt9v032->regmap;
 	u16 value = mt9v032->aec_agc;
 	int ret;
 
@@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *m
 	else
 		value &= ~which;
 
-	ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
+	ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
 	if (ret < 0)
 		return ret;
 
@@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *m
 static int
 mt9v032_update_hblank(struct mt9v032 *mt9v032)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
 	struct v4l2_rect *crop = &mt9v032->crop;
 	unsigned int min_hblank = mt9v032->model->data->min_hblank;
 	unsigned int hblank;
 
 	if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
 		min_hblank += (mt9v032->hratio - 1) * 10;
-	min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
-			   (int)min_hblank);
+	min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
+			   min_hblank);
 	hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
 
-	return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
+	return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
+			    hblank);
 }
 
 static int mt9v032_power_on(struct mt9v032 *mt9v032)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	struct regmap *map = mt9v032->regmap;
 	int ret;
 
 	ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
@@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v0
 	udelay(1);
 
 	/* Reset the chip and stop data read out */
-	ret = mt9v032_write(client, MT9V032_RESET, 1);
+	ret = regmap_write(map, MT9V032_RESET, 1);
 	if (ret < 0)
 		return ret;
 
-	ret = mt9v032_write(client, MT9V032_RESET, 0);
+	ret = regmap_write(map, MT9V032_RESET, 0);
 	if (ret < 0)
 		return ret;
 
-	return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
+	return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
 }
 
 static void mt9v032_power_off(struct mt9v032 *mt9v032)
@@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9
 
 static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	struct regmap *map = mt9v032->regmap;
 	int ret;
 
 	if (!on) {
@@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt
 
 	/* Configure the pixel clock polarity */
 	if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
-		ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
+		ret = regmap_write(map, mt9v032->model->data->pclk_reg,
 				MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
 		if (ret < 0)
 			return ret;
 	}
 
 	/* Disable the noise correction algorithm and restore the controls. */
-	ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
+	ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
 	if (ret < 0)
 		return ret;
 
@@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_
 	const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
 		       | MT9V032_CHIP_CONTROL_DOUT_ENABLE
 		       | MT9V032_CHIP_CONTROL_SEQUENTIAL;
-	struct i2c_client *client = v4l2_get_subdevdata(subdev);
 	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 	struct v4l2_rect *crop = &mt9v032->crop;
+	struct regmap *map = mt9v032->regmap;
 	unsigned int hbin;
 	unsigned int vbin;
 	int ret;
 
 	if (!enable)
-		return mt9v032_set_chip_control(mt9v032, mode, 0);
+		return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
 
 	/* Configure the window size and row/column bin */
 	hbin = fls(mt9v032->hratio) - 1;
 	vbin = fls(mt9v032->vratio) - 1;
-	ret = mt9v032_write(client, MT9V032_READ_MODE,
-			    hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
-			    vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
+	ret = regmap_update_bits(map, MT9V032_READ_MODE,
+				 ~MT9V032_READ_MODE_RESERVED,
+				 hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
+				 vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
 	if (ret < 0)
 		return ret;
 
-	ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
+	ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
 	if (ret < 0)
 		return ret;
 
-	ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
+	ret = regmap_write(map, MT9V032_ROW_START, crop->top);
 	if (ret < 0)
 		return ret;
 
-	ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
+	ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
 	if (ret < 0)
 		return ret;
 
-	ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
+	ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
 	if (ret < 0)
 		return ret;
 
@@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_
 		return ret;
 
 	/* Switch to master "normal" mode */
-	return mt9v032_set_chip_control(mt9v032, 0, mode);
+	return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
 }
 
 static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ct
 {
 	struct mt9v032 *mt9v032 =
 			container_of(ctrl->handler, struct mt9v032, ctrls);
-	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	struct regmap *map = mt9v032->regmap;
 	u32 freq;
 	u16 data;
 
@@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ct
 					      ctrl->val);
 
 	case V4L2_CID_GAIN:
-		return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
+		return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
 
 	case V4L2_CID_EXPOSURE_AUTO:
 		return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
 					      !ctrl->val);
 
 	case V4L2_CID_EXPOSURE:
-		return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
-				     ctrl->val);
+		return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
+				    ctrl->val);
 
 	case V4L2_CID_HBLANK:
 		mt9v032->hblank = ctrl->val;
 		return mt9v032_update_hblank(mt9v032);
 
 	case V4L2_CID_VBLANK:
-		return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
-				     ctrl->val);
+		return regmap_write(map, MT9V032_VERTICAL_BLANKING,
+				    ctrl->val);
 
 	case V4L2_CID_PIXEL_RATE:
 	case V4L2_CID_LINK_FREQ:
@@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ct
 			break;
 
 		freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
-		mt9v032->pixel_rate->val64 = freq;
+		*mt9v032->pixel_rate->p_new.p_s64 = freq;
 		mt9v032->sysclk = freq;
 		break;
 
@@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ct
 			     | MT9V032_TEST_PATTERN_FLIP;
 			break;
 		}
-		return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
+		return regmap_write(map, MT9V032_TEST_PATTERN, data);
 	}
 
 	return 0;
@@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l
 	struct i2c_client *client = v4l2_get_subdevdata(subdev);
 	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 	unsigned int i;
-	s32 version;
+	u32 version;
 	int ret;
 
 	dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l
 	}
 
 	/* Read and check the sensor version */
-	version = mt9v032_read(client, MT9V032_CHIP_VERSION);
-	if (version < 0) {
+	ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
+	if (ret < 0) {
 		dev_err(&client->dev, "Failed reading chip version\n");
-		return version;
+		return ret;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
@@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal
 	.close = mt9v032_close,
 };
 
+static const struct regmap_config mt9v032_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 /* -----------------------------------------------------------------------------
  * Driver initialization and probing
  */
@@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_clie
 	if (!mt9v032)
 		return -ENOMEM;
 
+	mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
+	if (IS_ERR(mt9v032->regmap))
+		return PTR_ERR(mt9v032->regmap);
+
 	mt9v032->clk = devm_clk_get(&client->dev, NULL);
 	if (IS_ERR(mt9v032->clk))
 		return PTR_ERR(mt9v032->clk);
@@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_clie
 
 	mt9v032->pixel_rate =
 		v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
-				  V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+				  V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
 
 	if (pdata && pdata->link_freqs) {
 		unsigned int def = 0;
@@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_clie
 
 	mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
 	ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
+	if (ret < 0)
+		goto err;
 
+	mt9v032->subdev.dev = &client->dev;
+	ret = v4l2_async_register_subdev(&mt9v032->subdev);
 	if (ret < 0)
-		v4l2_ctrl_handler_free(&mt9v032->ctrls);
+		goto err;
 
+	return 0;
+
+err:
+	media_entity_cleanup(&mt9v032->subdev.entity);
+	v4l2_ctrl_handler_free(&mt9v032->ctrls);
 	return ret;
 }
 
@@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_cli
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 
+	v4l2_async_unregister_subdev(subdev);
 	v4l2_ctrl_handler_free(&mt9v032->ctrls);
 	v4l2_device_unregister_subdev(subdev);
 	media_entity_cleanup(&subdev->entity);
@@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_cli
 }
 
 static const struct i2c_device_id mt9v032_id[] = {
+	{ "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
+	{ "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
+	{ "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
+	{ "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
 	{ "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
 	{ "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
 	{ "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/noon010pc30.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/noon010pc30.c
--- linux-libre-3.16-gnu/drivers/media/i2c/noon010pc30.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/noon010pc30.c	2014-09-28 17:29:07.000000000 -0400
@@ -554,6 +554,7 @@ static int noon010_set_fmt(struct v4l2_s
 	nf = noon010_try_fmt(sd, &fmt->format);
 	noon010_try_frame_size(&fmt->format, &size);
 	fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+	fmt->format.field = V4L2_FIELD_NONE;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
 		if (fh) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/s5k4ecgx.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k4ecgx.c
--- linux-libre-3.16-gnu/drivers/media/i2c/s5k4ecgx.c	2014-08-07 04:50:51.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k4ecgx.c	2014-09-28 21:32:08.000000000 -0400
@@ -594,6 +594,7 @@ static int s5k4ecgx_set_fmt(struct v4l2_
 	pf = s5k4ecgx_try_fmt(sd, &fmt->format);
 	s5k4ecgx_try_frame_size(&fmt->format, &fsize);
 	fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+	fmt->format.field = V4L2_FIELD_NONE;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
 		if (fh) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/s5k5baf.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k5baf.c
--- linux-libre-3.16-gnu/drivers/media/i2c/s5k5baf.c	2014-08-07 04:50:54.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k5baf.c	2014-09-28 21:32:11.000000000 -0400
@@ -1313,6 +1313,8 @@ static int s5k5baf_set_fmt(struct v4l2_s
 	const struct s5k5baf_pixfmt *pixfmt;
 	int ret = 0;
 
+	mf->field = V4L2_FIELD_NONE;
+
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
 		*v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/s5k6a3.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k6a3.c
--- linux-libre-3.16-gnu/drivers/media/i2c/s5k6a3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/s5k6a3.c	2014-09-28 17:29:07.000000000 -0400
@@ -115,6 +115,7 @@ static void s5k6a3_try_format(struct v4l
 
 	fmt = find_sensor_format(mf);
 	mf->code = fmt->code;
+	mf->field = V4L2_FIELD_NONE;
 	v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
 			      S5K6A3_SENSOR_MAX_WIDTH, 0,
 			      &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/smiapp/smiapp-core.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/smiapp/smiapp-core.c
--- linux-libre-3.16-gnu/drivers/media/i2c/smiapp/smiapp-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/smiapp/smiapp-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smia
 	if (rval < 0)
 		return rval;
 
-	sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
-	sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
+	*sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz;
+	*sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi;
 
 	return 0;
 }
@@ -533,7 +533,7 @@ static int smiapp_init_controls(struct s
 
 	sensor->pixel_rate_parray = v4l2_ctrl_new_std(
 		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
-		V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+		V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
 
 	if (sensor->pixel_array->ctrl_handler.error) {
 		dev_err(&client->dev,
@@ -562,7 +562,7 @@ static int smiapp_init_controls(struct s
 
 	sensor->pixel_rate_csi = v4l2_ctrl_new_std(
 		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
-		V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+		V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
 
 	if (sensor->src->ctrl_handler.error) {
 		dev_err(&client->dev,
@@ -1282,19 +1282,12 @@ static int smiapp_set_power(struct v4l2_
 
 	mutex_lock(&sensor->power_mutex);
 
-	/*
-	 * If the power count is modified from 0 to != 0 or from != 0
-	 * to 0, update the power state.
-	 */
-	if (!sensor->power_count == !on)
-		goto out;
-
-	if (on) {
+	if (on && !sensor->power_count) {
 		/* Power on and perform initialisation. */
 		ret = smiapp_power_on(sensor);
 		if (ret < 0)
 			goto out;
-	} else {
+	} else if (!on && sensor->power_count == 1) {
 		smiapp_power_off(sensor);
 	}
 
@@ -1554,6 +1547,7 @@ static int __smiapp_get_format(struct v4
 		fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
 		fmt->format.width = r->width;
 		fmt->format.height = r->height;
+		fmt->format.field = V4L2_FIELD_NONE;
 	}
 
 	return 0;
@@ -1687,6 +1681,7 @@ static int smiapp_set_format(struct v4l2
 	fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
 	fmt->format.width &= ~1;
 	fmt->format.height &= ~1;
+	fmt->format.field = V4L2_FIELD_NONE;
 
 	fmt->format.width =
 		clamp(fmt->format.width,
@@ -2544,9 +2539,9 @@ static int smiapp_registered(struct v4l2
 		}
 
 		snprintf(this->sd.name,
-			 sizeof(this->sd.name), "%s %d-%4.4x %s",
-			 sensor->minfo.name, i2c_adapter_id(client->adapter),
-			 client->addr, _this->name);
+			 sizeof(this->sd.name), "%s %s %d-%4.4x",
+			 sensor->minfo.name, _this->name,
+			 i2c_adapter_id(client->adapter), client->addr);
 
 		this->sink_fmt.width =
 			sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@@ -2570,7 +2565,7 @@ static int smiapp_registered(struct v4l2
 
 		this->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 		this->sd.internal_ops = &smiapp_internal_ops;
-		this->sd.owner = NULL;
+		this->sd.owner = THIS_MODULE;
 		v4l2_set_subdevdata(&this->sd, client);
 
 		rval = media_entity_init(&this->sd.entity,
@@ -2674,6 +2669,7 @@ static int smiapp_open(struct v4l2_subde
 		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;
 
 		try_crop->top = 0;
 		try_crop->left = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9m001.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9m001.c
--- linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9m001.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9m001.c	2014-09-28 17:29:07.000000000 -0400
@@ -403,7 +403,7 @@ static int mt9m001_s_ctrl(struct v4l2_ct
 		if (ctrl->val <= ctrl->default_value) {
 			/* Pack it into 0..1 step 0.125, register values 0..8 */
 			unsigned long range = ctrl->default_value - ctrl->minimum;
-			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+			data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&client->dev, "Setting gain %d\n", data);
 			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -413,7 +413,7 @@ static int mt9m001_s_ctrl(struct v4l2_ct
 			/* Pack it into 1.125..15 variable step, register values 9..67 */
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
 			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
-			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+			unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
 					       111 + range / 2) / range + 9;
 
 			if (gain <= 32)
@@ -434,7 +434,7 @@ static int mt9m001_s_ctrl(struct v4l2_ct
 	case V4L2_CID_EXPOSURE_AUTO:
 		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
 			unsigned long range = exp->maximum - exp->minimum;
-			unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
+			unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 +
 						 range / 2) / range + 1;
 
 			dev_dbg(&client->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9m111.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9m111.c
--- linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9m111.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9m111.c	2014-09-28 17:29:07.000000000 -0400
@@ -931,6 +931,12 @@ static int mt9m111_probe(struct i2c_clie
 	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
 	int ret;
 
+	if (client->dev.of_node) {
+		ssdd = devm_kzalloc(&client->dev, sizeof(*ssdd), GFP_KERNEL);
+		if (!ssdd)
+			return -ENOMEM;
+		client->dev.platform_data = ssdd;
+	}
 	if (!ssdd) {
 		dev_err(&client->dev, "mt9m111: driver needs platform data\n");
 		return -EINVAL;
@@ -1015,6 +1021,11 @@ static int mt9m111_remove(struct i2c_cli
 
 	return 0;
 }
+static const struct of_device_id mt9m111_of_match[] = {
+	{ .compatible = "micron,mt9m111", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mt9m111_of_match);
 
 static const struct i2c_device_id mt9m111_id[] = {
 	{ "mt9m111", 0 },
@@ -1025,6 +1036,7 @@ MODULE_DEVICE_TABLE(i2c, mt9m111_id);
 static struct i2c_driver mt9m111_i2c_driver = {
 	.driver = {
 		.name = "mt9m111",
+		.of_match_table = of_match_ptr(mt9m111_of_match),
 	},
 	.probe		= mt9m111_probe,
 	.remove		= mt9m111_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9t031.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9t031.c
--- linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9t031.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9t031.c	2014-09-28 17:29:07.000000000 -0400
@@ -474,7 +474,7 @@ static int mt9t031_s_ctrl(struct v4l2_ct
 		if (ctrl->val <= ctrl->default_value) {
 			/* Pack it into 0..1 step 0.125, register values 0..8 */
 			unsigned long range = ctrl->default_value - ctrl->minimum;
-			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+			data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&client->dev, "Setting gain %d\n", data);
 			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@@ -485,7 +485,7 @@ static int mt9t031_s_ctrl(struct v4l2_ct
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
 			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
 			/* calculated gain: map 65..127 to 9..1024 step 0.125 */
-			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+			unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
 					       1015 + range / 2) / range + 9;
 
 			if (gain <= 32)		/* calculated gain 9..32 -> 9..32 */
@@ -507,7 +507,7 @@ static int mt9t031_s_ctrl(struct v4l2_ct
 	case V4L2_CID_EXPOSURE_AUTO:
 		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
 			unsigned int range = exp->maximum - exp->minimum;
-			unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+			unsigned int shutter = ((exp->val - (s32)exp->minimum) * 1048 +
 						 range / 2) / range + 1;
 			u32 old;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9v022.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9v022.c
--- linux-libre-3.16-gnu/drivers/media/i2c/soc_camera/mt9v022.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/soc_camera/mt9v022.c	2014-09-28 17:29:07.000000000 -0400
@@ -583,7 +583,7 @@ static int mt9v022_s_ctrl(struct v4l2_ct
 			/* mt9v022 has minimum == default */
 			unsigned long range = gain->maximum - gain->minimum;
 			/* Valid values 16 to 64, 32 to 64 must be even. */
-			unsigned long gain_val = ((gain->val - gain->minimum) *
+			unsigned long gain_val = ((gain->val - (s32)gain->minimum) *
 					      48 + range / 2) / range + 16;
 
 			if (gain_val >= 32)
@@ -608,7 +608,7 @@ static int mt9v022_s_ctrl(struct v4l2_ct
 		} else {
 			struct v4l2_ctrl *exp = mt9v022->exposure;
 			unsigned long range = exp->maximum - exp->minimum;
-			unsigned long shutter = ((exp->val - exp->minimum) *
+			unsigned long shutter = ((exp->val - (s32)exp->minimum) *
 					479 + range / 2) / range + 1;
 
 			/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/i2c/tvp5150.c linux-libre-3.17-rc7-gnu/drivers/media/i2c/tvp5150.c
--- linux-libre-3.16-gnu/drivers/media/i2c/tvp5150.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/i2c/tvp5150.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,38 +56,29 @@ static inline struct v4l2_subdev *to_sd(
 static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
 {
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
-	unsigned char buffer[1];
 	int rc;
-	struct i2c_msg msg[] = {
-		{ .addr = c->addr, .flags = 0,
-		  .buf = &addr, .len = 1 },
-		{ .addr = c->addr, .flags = I2C_M_RD,
-		  .buf = buffer, .len = 1 }
-	};
 
-	rc = i2c_transfer(c->adapter, msg, 2);
-	if (rc < 0 || rc != 2) {
-		v4l2_err(sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
-		return rc < 0 ? rc : -EIO;
+	rc = i2c_smbus_read_byte_data(c, addr);
+	if (rc < 0) {
+		v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
+		return rc;
 	}
 
-	v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
+	v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, rc);
 
-	return (buffer[0]);
+	return rc;
 }
 
 static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
 				 unsigned char value)
 {
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
-	unsigned char buffer[2];
 	int rc;
 
-	buffer[0] = addr;
-	buffer[1] = value;
-	v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
-	if (2 != (rc = i2c_master_send(c, buffer, 2)))
-		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
+	v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
+	rc = i2c_smbus_write_byte_data(c, addr, value);
+	if (rc < 0)
+		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc);
 }
 
 static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@@ -1148,10 +1139,10 @@ static int tvp5150_probe(struct i2c_clie
 		/* Is TVP5150A */
 		if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
 			v4l2_info(sd, "tvp%02x%02xa detected.\n",
-				  tvp5150_id[2], tvp5150_id[3]);
+				  tvp5150_id[0], tvp5150_id[1]);
 		} else {
 			v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
-				  tvp5150_id[2], tvp5150_id[3]);
+				  tvp5150_id[0], tvp5150_id[1]);
 			v4l2_info(sd, "*** Rom ver is %d.%d\n",
 				  tvp5150_id[2], tvp5150_id[3]);
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/Kconfig
--- linux-libre-3.16-gnu/drivers/media/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,13 @@ config MEDIA_RADIO_SUPPORT
 		support radio reception. Disabling this option will
 		disable support for them.
 
+config MEDIA_SDR_SUPPORT
+	bool "Software defined radio support"
+	---help---
+	  Enable software defined radio support.
+
+	  Say Y when you have a software defined radio device.
+
 config MEDIA_RC_SUPPORT
 	bool "Remote Controller support"
 	depends on INPUT
@@ -95,7 +102,7 @@ config MEDIA_CONTROLLER
 config VIDEO_DEV
 	tristate
 	depends on MEDIA_SUPPORT
-	depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
+	depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
 	default y
 
 config VIDEO_V4L2_SUBDEV_API
@@ -171,7 +178,7 @@ comment "Media ancillary drivers (tuners
 
 config MEDIA_SUBDRV_AUTOSELECT
 	bool "Autoselect ancillary drivers (tuners, sensors, i2c, frontends)"
-	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
+	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT || MEDIA_SDR_SUPPORT
 	depends on HAS_IOMEM
 	select I2C
 	select I2C_MUX
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/media-device.c linux-libre-3.17-rc7-gnu/drivers/media/media-device.c
--- linux-libre-3.16-gnu/drivers/media/media-device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/media-device.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,8 +106,6 @@ static long media_device_enum_entities(s
 	if (ent->name) {
 		strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
 		u_ent.name[sizeof(u_ent.name) - 1] = '\0';
-	} else {
-		memset(u_ent.name, 0, sizeof(u_ent.name));
 	}
 	u_ent.type = ent->type;
 	u_ent.revision = ent->revision;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/parport/bw-qcam.c linux-libre-3.17-rc7-gnu/drivers/media/parport/bw-qcam.c
--- linux-libre-3.16-gnu/drivers/media/parport/bw-qcam.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/parport/bw-qcam.c	2014-09-28 17:29:07.000000000 -0400
@@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct fil
 	pix->sizeimage = pix->width * pix->height;
 	/* Just a guess */
 	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	pix->priv = 0;
 	return 0;
 }
 
@@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct f
 	pix->sizeimage = pix->width * pix->height;
 	/* Just a guess */
 	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	pix->priv = 0;
 	return 0;
 }
 
@@ -990,7 +988,6 @@ static struct qcam *qcam_init(struct par
 	qcam->vdev.fops = &qcam_fops;
 	qcam->vdev.lock = &qcam->lock;
 	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
-	set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
 	qcam->vdev.release = video_device_release_empty;
 	video_set_drvdata(&qcam->vdev, qcam);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/parport/c-qcam.c linux-libre-3.17-rc7-gnu/drivers/media/parport/c-qcam.c
--- linux-libre-3.16-gnu/drivers/media/parport/c-qcam.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/parport/c-qcam.c	2014-09-28 17:29:07.000000000 -0400
@@ -761,7 +761,6 @@ static struct qcam *qcam_init(struct par
 	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
 	qcam->vdev.release = video_device_release_empty;
 	qcam->vdev.ctrl_handler = &qcam->hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
 	video_set_drvdata(&qcam->vdev, qcam);
 
 	mutex_init(&qcam->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/parport/pms.c linux-libre-3.17-rc7-gnu/drivers/media/parport/pms.c
--- linux-libre-3.16-gnu/drivers/media/parport/pms.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/parport/pms.c	2014-09-28 17:29:07.000000000 -0400
@@ -1091,7 +1091,6 @@ static int pms_probe(struct device *pdev
 	dev->vdev.release = video_device_release_empty;
 	dev->vdev.lock = &dev->lock;
 	dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 	video_set_drvdata(&dev->vdev, dev);
 	dev->std = V4L2_STD_NTSC_M;
 	dev->height = 240;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/parport/w9966.c linux-libre-3.17-rc7-gnu/drivers/media/parport/w9966.c
--- linux-libre-3.16-gnu/drivers/media/parport/w9966.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/parport/w9966.c	2014-09-28 17:29:07.000000000 -0400
@@ -883,7 +883,6 @@ static int w9966_init(struct w9966 *cam,
 	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
 	cam->vdev.release = video_device_release_empty;
 	cam->vdev.ctrl_handler = &cam->hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
 	video_set_drvdata(&cam->vdev, cam);
 
 	mutex_init(&cam->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bt878.c linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bt878.c
--- linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bt878.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bt878.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,28 +101,20 @@ static int bt878_mem_alloc(struct bt878
 	if (!bt->buf_cpu) {
 		bt->buf_size = 128 * 1024;
 
-		bt->buf_cpu =
-		    pci_alloc_consistent(bt->dev, bt->buf_size,
-					 &bt->buf_dma);
-
+		bt->buf_cpu = pci_zalloc_consistent(bt->dev, bt->buf_size,
+						    &bt->buf_dma);
 		if (!bt->buf_cpu)
 			return -ENOMEM;
-
-		memset(bt->buf_cpu, 0, bt->buf_size);
 	}
 
 	if (!bt->risc_cpu) {
 		bt->risc_size = PAGE_SIZE;
-		bt->risc_cpu =
-		    pci_alloc_consistent(bt->dev, bt->risc_size,
-					 &bt->risc_dma);
-
+		bt->risc_cpu = pci_zalloc_consistent(bt->dev, bt->risc_size,
+						     &bt->risc_dma);
 		if (!bt->risc_cpu) {
 			bt878_mem_free(bt);
 			return -ENOMEM;
 		}
-
-		memset(bt->risc_cpu, 0, bt->risc_size);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttv-driver.c linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttv-driver.c
--- linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttv-driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttv-driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -3886,7 +3886,6 @@ static struct video_device *vdev_init(st
 	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = bttv_debug;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	video_set_drvdata(vfd, btv);
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttv-input.c linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttv-input.c
--- linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttv-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttv-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *b
 
 	if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
 	    (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 	} else {
 		/* HACK: Probably, ir->mask_keydown is missing
 		   for this board */
 		if (btv->c.type == BTTV_BOARD_WINFAST2000)
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 
 		rc_keyup(ir->dev);
 	}
@@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct b
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "up/down");
 
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		if (keyup)
 			rc_keyup(ir->dev);
 	} else {
@@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct b
 		if (keyup)
 			rc_keyup(ir->dev);
 		else
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 	}
 
 	ir->last_gpio = data | keyup;
@@ -154,10 +154,10 @@ static void bttv_input_timer(unsigned lo
  * testing.
  */
 
-#define RC5_START(x)	(((x) >> 12) & 3)
-#define RC5_TOGGLE(x)	(((x) >> 11) & 1)
-#define RC5_ADDR(x)	(((x) >> 6) & 31)
-#define RC5_INSTR(x)	((x) & 63)
+#define RC5_START(x)	(((x) >> 12) & 0x03)
+#define RC5_TOGGLE(x)	(((x) >> 11) & 0x01)
+#define RC5_ADDR(x)	(((x) >> 6)  & 0x1f)
+#define RC5_INSTR(x)	(((x) >> 0)  & 0x3f)
 
 /* decode raw bit pattern to RC5 code */
 static u32 bttv_rc5_decode(unsigned int code)
@@ -195,8 +195,8 @@ static void bttv_rc5_timer_end(unsigned
 {
 	struct bttv_ir *ir = (struct bttv_ir *)data;
 	struct timeval tv;
-	u32 gap;
-	u32 rc5 = 0;
+	u32 gap, rc5, scancode;
+	u8 toggle, command, system;
 
 	/* get time */
 	do_gettimeofday(&tv);
@@ -221,26 +221,29 @@ static void bttv_rc5_timer_end(unsigned
 	if (ir->last_bit < 20) {
 		/* ignore spurious codes (caused by light/other remotes) */
 		dprintk("short code: %x\n", ir->code);
-	} else {
-		ir->code = (ir->code << ir->shift_by) | 1;
-		rc5 = bttv_rc5_decode(ir->code);
+		return;
+	}
 
-		/* two start bits? */
-		if (RC5_START(rc5) != ir->start) {
-			pr_info(DEVNAME ":"
-			       " rc5 start bits invalid: %u\n", RC5_START(rc5));
+	ir->code = (ir->code << ir->shift_by) | 1;
+	rc5 = bttv_rc5_decode(ir->code);
 
-			/* right address? */
-		} else if (RC5_ADDR(rc5) == ir->addr) {
-			u32 toggle = RC5_TOGGLE(rc5);
-			u32 instr = RC5_INSTR(rc5);
+	toggle = RC5_TOGGLE(rc5);
+	system = RC5_ADDR(rc5);
+	command = RC5_INSTR(rc5);
 
-			/* Good code */
-			rc_keydown(ir->dev, instr, toggle);
-			dprintk("instruction %x, toggle %x\n",
-				instr, toggle);
-		}
+	switch (RC5_START(rc5)) {
+	case 0x3:
+		break;
+	case 0x2:
+		command += 0x40;
+		break;
+	default:
+		return;
 	}
+
+	scancode = RC_SCANCODE_RC5(system, command);
+	rc_keydown(ir->dev, RC_TYPE_RC5, scancode, toggle);
+	dprintk("scancode %x, toggle %x\n", scancode, toggle);
 }
 
 static int bttv_rc5_irq(struct bttv *btv)
@@ -310,8 +313,6 @@ static void bttv_ir_start(struct bttv *b
 		/* set timer_end for code completion */
 		setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
 		ir->shift_by = 1;
-		ir->start = 3;
-		ir->addr = 0x0;
 		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 }
@@ -335,7 +336,8 @@ static void bttv_ir_stop(struct bttv *bt
  * Get_key functions used by I2C remotes
  */
 
-static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pv951(struct IR_i2c *ir, enum rc_type *protocol,
+			 u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 
@@ -362,8 +364,9 @@ static int get_key_pv951(struct IR_i2c *
 	 * 	   the device is bound to the vendor-provided RC.
 	 */
 
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
@@ -490,8 +493,8 @@ int bttv_input_init(struct bttv *btv)
 		ir->polling      = 50; // ms
 		break;
 	case BTTV_BOARD_NEBULA_DIGITV:
-		ir_codes = RC_MAP_NEBULA;
-		ir->rc5_gpio = true;
+		ir_codes         = RC_MAP_NEBULA;
+		ir->rc5_gpio     = true;
 		break;
 	case BTTV_BOARD_MACHTV_MAGICTV:
 		ir_codes         = RC_MAP_APAC_VIEWCOMP;
@@ -514,7 +517,8 @@ int bttv_input_init(struct bttv *btv)
 						   ir->mask_keycode);
 		break;
 	}
-	if (NULL == ir_codes) {
+
+	if (!ir_codes) {
 		dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
 		err = -ENODEV;
 		goto err_out_free;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttvp.h linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttvp.h
--- linux-libre-3.16-gnu/drivers/media/pci/bt8xx/bttvp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/bt8xx/bttvp.h	2014-09-28 17:29:07.000000000 -0400
@@ -133,8 +133,6 @@ struct bttv_ir {
 	u32                     polling;
 	u32                     last_gpio;
 	int                     shift_by;
-	int                     start; // What should RC5_START() be
-	int                     addr; // What RC5_ADDR() should be.
 	int                     rc5_remote_gap;
 
 	/* RC5 gpio */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-alsa.h linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-alsa.h
--- linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-alsa.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-alsa.h	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,6 @@ static inline void snd_cx18_unlock(struc
 }
 
 #define CX18_ALSA_DBGFLG_WARN  (1 << 0)
-#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
 #define CX18_ALSA_DBGFLG_INFO  (1 << 1)
 
 #define CX18_ALSA_DEBUG(x, type, fmt, args...) \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-driver.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-driver.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-driver.c	2014-08-07 04:50:08.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-driver.c	2014-09-28 21:31:23.000000000 -0400
@@ -1091,6 +1091,7 @@ static int cx18_probe(struct pci_dev *pc
 		setup.addr = ADDR_UNSET;
 		setup.type = cx->options.tuner;
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		setup.config = NULL;
 		if (cx->options.radio > 0)
 			setup.mode_mask |= T_RADIO;
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-ioctl.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-ioctl.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct fil
 	pixfmt->height = cx->cxhdl.height;
 	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pixfmt->field = V4L2_FIELD_INTERLACED;
-	pixfmt->priv = 0;
 	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = s->pixelformat;
 		pixfmt->sizeimage = s->vb_bytes_per_frame;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-streams.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-streams.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx18/cx18-streams.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx18/cx18-streams.c	2014-09-28 17:29:07.000000000 -0400
@@ -375,7 +375,6 @@ static int cx18_prep_dev(struct cx18 *cx
 	s->video_dev->release = video_device_release;
 	s->video_dev->tvnorms = V4L2_STD_ALL;
 	s->video_dev->lock = &cx->serialize_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
 	cx18_set_funcs(s->video_dev);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-417.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-417.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-417.c	2014-08-07 04:50:14.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-417.c	2014-09-28 21:31:29.000000000 -0400
@@ -1266,7 +1266,7 @@ static int vidioc_g_tuner(struct file *f
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	if (UNSET == dev->tuner_type)
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1284,7 +1284,7 @@ static int vidioc_s_tuner(struct file *f
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	if (UNSET == dev->tuner_type)
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 
 	/* Update the A/V core */
@@ -1299,7 +1299,7 @@ static int vidioc_g_frequency(struct fil
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	if (UNSET == dev->tuner_type)
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	f->type = V4L2_TUNER_ANALOG_TV;
 	f->frequency = dev->freq;
@@ -1347,7 +1347,7 @@ static int vidioc_querycap(struct file *
 		V4L2_CAP_READWRITE     |
 		V4L2_CAP_STREAMING     |
 		0;
-	if (UNSET != dev->tuner_type)
+	if (dev->tuner_type != TUNER_ABSENT)
 		cap->capabilities |= V4L2_CAP_TUNER;
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-cards.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-cards.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-cards.c	2014-08-07 04:50:17.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-cards.c	2014-09-28 21:31:32.000000000 -0400
@@ -619,7 +619,12 @@ struct cx23885_board cx23885_boards[] =
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR4400] = {
 		.name		= "Hauppauge WinTV-HVR4400",
+		.porta		= CX23885_ANALOG_VIDEO,
 		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_NXP_TDA18271,
+		.tuner_addr	= 0x60, /* 0xc0 >> 1 */
+		.tuner_bus	= 1,
 	},
 	[CX23885_BOARD_AVERMEDIA_HC81R] = {
 		.name		= "AVerTV Hybrid Express Slim HC81R",
@@ -649,7 +654,31 @@ struct cx23885_board cx23885_boards[] =
 				  CX25840_NONE1_CH3,
 			.amux   = CX25840_AUDIO6,
 		} },
-	}
+	},
+	[CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2] = {
+		.name		= "DViCO FusionHDTV DVB-T Dual Express2",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_IMPACTVCBE] = {
+		.name		= "Hauppauge ImpactVCB-e",
+		.tuner_type	= TUNER_ABSENT,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_VIN7_CH3 |
+				  CX25840_VIN4_CH2 |
+				  CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = CX25840_VIN7_CH3 |
+				  CX25840_VIN4_CH2 |
+				  CX25840_VIN8_CH1 |
+				  CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -897,6 +926,14 @@ struct cx23885_subid cx23885_subids[] =
 		.subvendor = 0x1461,
 		.subdevice = 0xd939,
 		.card      = CX23885_BOARD_AVERMEDIA_HC81R,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7133,
+		.card      = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb98,
+		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -977,6 +1014,9 @@ static void hauppauge_eeprom(struct cx23
 	case 71009:
 		/* WinTV-HVR1200 (PCIe, Retail, full height)
 		 * DVB-T and basic analog */
+	case 71100:
+		/* WinTV-ImpactVCB-e (PCIe, Retail, half height)
+		 * Basic analog */
 	case 71359:
 		/* WinTV-HVR1200 (PCIe, OEM, half height)
 		 * DVB-T and basic analog */
@@ -1137,6 +1177,7 @@ int cx23885_tuner_callback(void *priv, i
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
 		/* Two identical tuners on two different i2c buses,
 		 * we need to reset the correct gpio. */
 		if (port->nr == 1)
@@ -1280,6 +1321,7 @@ void cx23885_gpio_setup(struct cx23885_d
 		cx_set(GP0_IO, 0x000f000f);
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
 		/* GPIO-0 portb xc3028 reset */
 		/* GPIO-1 portb zl10353 reset */
 		/* GPIO-2 portc xc3028 reset */
@@ -1449,13 +1491,16 @@ void cx23885_gpio_setup(struct cx23885_d
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR4400:
 		/* GPIO-8 tda10071 demod reset */
+		/* GPIO-9 si2165 demod reset */
 
 		/* Put the parts into reset and back */
-		cx23885_gpio_enable(dev, GPIO_8, 1);
-		cx23885_gpio_clear(dev, GPIO_8);
+		cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
+
+		cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
 		mdelay(100);
-		cx23885_gpio_set(dev, GPIO_8);
+		cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
 		mdelay(100);
+
 		break;
 	case CX23885_BOARD_AVERMEDIA_HC81R:
 		cx_clear(MC417_CTL, 1);
@@ -1585,6 +1630,7 @@ int cx23885_ir_init(struct cx23885_dev *
 				 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
 		request_module("ir-kbd-i2c");
 		break;
 	}
@@ -1701,6 +1747,7 @@ void cx23885_card_setup(struct cx23885_d
 	case CX23885_BOARD_HAUPPAUGE_HVR1850:
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
 	case CX23885_BOARD_HAUPPAUGE_HVR4400:
+	case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
 		if (dev->i2c_bus[0].i2c_rc == 0)
 			hauppauge_eeprom(dev, eeprom+0xc0);
 		break;
@@ -1720,6 +1767,7 @@ void cx23885_card_setup(struct cx23885_d
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
 		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1799,6 +1847,9 @@ void cx23885_card_setup(struct cx23885_d
 		ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
@@ -1807,6 +1858,7 @@ void cx23885_card_setup(struct cx23885_d
 	case CX23885_BOARD_HAUPPAUGE_HVR1200:
 	case CX23885_BOARD_HAUPPAUGE_HVR1700:
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+	case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
@@ -1835,6 +1887,7 @@ void cx23885_card_setup(struct cx23885_d
 			break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+	case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
 	case CX23885_BOARD_HAUPPAUGE_HVR1700:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-dvb.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-dvb.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-dvb.c	2014-08-07 04:47:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-dvb.c	2014-09-28 21:27:55.000000000 -0400
@@ -44,6 +44,7 @@
 #include "tuner-xc2028.h"
 #include "tuner-simple.h"
 #include "dib7000p.h"
+#include "dib0070.h"
 #include "dibx000_common.h"
 #include "zl10353.h"
 #include "stv0900.h"
@@ -71,6 +72,7 @@
 #include "tda10071.h"
 #include "a8293.h"
 #include "mb86a20s.h"
+#include "si2165.h"
 
 static unsigned int debug;
 
@@ -302,6 +304,11 @@ static struct tda18271_config hauppauge_
 	.output_opt = TDA18271_OUTPUT_LT_OFF,
 };
 
+static struct tda18271_config hauppauge_hvr4400_tuner_config = {
+	.gate    = TDA18271_GATE_DIGITAL,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
 static struct tda18271_std_map hauppauge_hvr127x_std_map = {
 	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
 		      .if_lvl = 1, .rfagc_top = 0x58 },
@@ -702,6 +709,12 @@ static const struct a8293_config hauppau
 	.i2c_addr = 0x0b,
 };
 
+static const struct si2165_config hauppauge_hvr4400_si2165_config = {
+	.i2c_addr	= 0x64,
+	.chip_mode	= SI2165_MODE_PLL_XTAL,
+	.ref_freq_Hz	= 16000000,
+};
+
 static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
 	struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -746,8 +759,108 @@ static int netup_altera_fpga_rw(void *de
 	return 0;
 };
 
+static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+	struct dib7000p_ops *dib7000p_ops = fe->sec_priv;
+
+	return dib7000p_ops->set_gpio(fe, 8, 0, !onoff);
+}
+
+static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	return 0;
+}
+
+static struct dib0070_config dib7070p_dib0070_config = {
+	.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+	.reset = dib7070_tuner_reset,
+	.sleep = dib7070_tuner_sleep,
+	.clock_khz = 12000,
+	.freq_offset_khz_vhf = 550,
+	/* .flip_chip = 1, */
+};
+
+/* DIB7070 generic */
+static struct dibx000_agc_config dib7070_agc_config = {
+	.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+
+	/*
+	 * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
+	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
+	 */
+	.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
+		 (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+	.inv_gain = 600,
+	.time_stabiliz = 10,
+	.alpha_level = 0,
+	.thlock = 118,
+	.wbd_inv = 0,
+	.wbd_ref = 3530,
+	.wbd_sel = 1,
+	.wbd_alpha = 5,
+	.agc1_max = 65535,
+	.agc1_min = 0,
+	.agc2_max = 65535,
+	.agc2_min = 0,
+	.agc1_pt1 = 0,
+	.agc1_pt2 = 40,
+	.agc1_pt3 = 183,
+	.agc1_slope1 = 206,
+	.agc1_slope2 = 255,
+	.agc2_pt1 = 72,
+	.agc2_pt2 = 152,
+	.agc2_slope1 = 88,
+	.agc2_slope2 = 90,
+	.alpha_mant = 17,
+	.alpha_exp = 27,
+	.beta_mant = 23,
+	.beta_exp = 51,
+	.perform_agc_softsplit = 0,
+};
+
+static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
+	.internal = 60000,
+	.sampling = 15000,
+	.pll_prediv = 1,
+	.pll_ratio = 20,
+	.pll_range = 3,
+	.pll_reset = 1,
+	.pll_bypass = 0,
+	.enable_refdiv = 0,
+	.bypclk_div = 0,
+	.IO_CLK_en_core = 1,
+	.ADClkSrc = 1,
+	.modulo = 2,
+	/* refsel, sel, freq_15k */
+	.sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
+	.ifreq = (0 << 25) | 0,
+	.timf = 20452225,
+	.xtal_hz = 12000000,
+};
+
+static struct dib7000p_config dib7070p_dib7000p_config = {
+	/* .output_mode = OUTMODE_MPEG2_FIFO, */
+	.output_mode = OUTMODE_MPEG2_SERIAL,
+	/* .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, */
+	.output_mpeg2_in_188_bytes = 1,
+
+	.agc_config_count = 1,
+	.agc = &dib7070_agc_config,
+	.bw  = &dib7070_bw_config_12_mhz,
+	.tuner_is_baseband = 1,
+	.spur_protect = 1,
+
+	.gpio_dir = 0xfcef, /* DIB7000P_GPIO_DEFAULT_DIRECTIONS, */
+	.gpio_val = 0x0110, /* DIB7000P_GPIO_DEFAULT_VALUES, */
+	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+	.hostbus_diversity = 1,
+};
+
 static int dvb_register(struct cx23885_tsport *port)
 {
+	struct dib7000p_ops dib7000p_ops;
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
 	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
@@ -925,8 +1038,11 @@ static int dvb_register(struct cx23885_t
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 		i2c_bus = &dev->i2c_bus[0];
-		fe0->dvb.frontend = dvb_attach(dib7000p_attach,
-			&i2c_bus->i2c_adap,
+
+		if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
+			return -ENODEV;
+
+		fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
 			0x12, &hauppauge_hvr1400_dib7000_config);
 		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend *fe;
@@ -989,6 +1105,30 @@ static int dvb_register(struct cx23885_t
 		}
 		break;
 	}
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2: {
+		i2c_bus = &dev->i2c_bus[port->nr - 1];
+		/* cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); */
+		/* cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); */
+
+		if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
+			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");
+			return -ENODEV;
+		}
+		fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap, 0x80, &dib7070p_dib7000p_config);
+		if (fe0->dvb.frontend != NULL) {
+			struct i2c_adapter *tun_i2c;
+
+			fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL);
+			memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops));
+			tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1);
+			if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config))
+				return -ENODEV;
+		}
+		break;
+	}
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
@@ -1331,13 +1471,34 @@ static int dvb_register(struct cx23885_t
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR4400:
 		i2c_bus = &dev->i2c_bus[0];
-		fe0->dvb.frontend = dvb_attach(tda10071_attach,
+		i2c_bus2 = &dev->i2c_bus[1];
+		switch (port->nr) {
+		/* port b */
+		case 1:
+			fe0->dvb.frontend = dvb_attach(tda10071_attach,
 						&hauppauge_tda10071_config,
 						&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
-			dvb_attach(a8293_attach, fe0->dvb.frontend,
-				   &i2c_bus->i2c_adap,
-				   &hauppauge_a8293_config);
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
+						&i2c_bus->i2c_adap,
+						&hauppauge_a8293_config))
+					goto frontend_detach;
+			}
+			break;
+		/* port c */
+		case 2:
+			fe0->dvb.frontend = dvb_attach(si2165_attach,
+					&hauppauge_hvr4400_si2165_config,
+					&i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				fe0->dvb.frontend->ops.i2c_gate_ctrl = 0;
+				if (!dvb_attach(tda18271_attach,
+						fe0->dvb.frontend,
+						0x60, &i2c_bus2->i2c_adap,
+					  &hauppauge_hvr4400_tuner_config))
+					goto frontend_detach;
+			}
+			break;
 		}
 		break;
 	default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885.h linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885.h
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885.h	2014-09-28 17:29:07.000000000 -0400
@@ -96,6 +96,8 @@
 #define CX23885_BOARD_TBS_6981                 40
 #define CX23885_BOARD_TBS_6980                 41
 #define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
+#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE     43
+#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-input.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-input.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_de
 	}
 	rc->dev.parent = &dev->pci->dev;
 	rc->driver_type = driver_type;
-	rc_set_allowed_protocols(rc, allowed_protos);
+	rc->allowed_protocols = allowed_protos;
 	rc->priv = kernel_ir;
 	rc->open = cx23885_input_ir_open;
 	rc->close = cx23885_input_ir_close;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-video.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-video.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/cx23885-video.c	2014-08-07 04:50:20.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/cx23885-video.c	2014-09-28 21:31:34.000000000 -0400
@@ -507,6 +507,7 @@ static int cx23885_video_mux(struct cx23
 	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
 		(dev->board == CX23885_BOARD_MPX885) ||
 		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+		(dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) ||
 		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
 		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
 		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
@@ -1156,7 +1157,7 @@ static int vidioc_querycap(struct file *
 		V4L2_CAP_READWRITE     |
 		V4L2_CAP_STREAMING     |
 		V4L2_CAP_VBI_CAPTURE;
-	if (UNSET != dev->tuner_type)
+	if (dev->tuner_type != TUNER_ABSENT)
 		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
 }
@@ -1474,7 +1475,7 @@ static int vidioc_g_tuner(struct file *f
 {
 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-	if (unlikely(UNSET == dev->tuner_type))
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1490,7 +1491,7 @@ static int vidioc_s_tuner(struct file *f
 {
 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-	if (UNSET == dev->tuner_type)
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1506,7 +1507,7 @@ static int vidioc_g_frequency(struct fil
 	struct cx23885_fh *fh = priv;
 	struct cx23885_dev *dev = fh->dev;
 
-	if (unlikely(UNSET == dev->tuner_type))
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 
 	/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
@@ -1522,7 +1523,7 @@ static int cx23885_set_freq(struct cx238
 {
 	struct v4l2_control ctrl;
 
-	if (unlikely(UNSET == dev->tuner_type))
+	if (dev->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx23885/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/Kconfig
--- linux-libre-3.16-gnu/drivers/media/pci/cx23885/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx23885/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -31,12 +31,14 @@ config VIDEO_CX23885
 	select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  This is a video4linux driver for Conexant 23885 based
 	  TV cards.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx25821/cx25821-video.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx25821/cx25821-video.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx25821/cx25821-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx25821/cx25821-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(
 	f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_ca
 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_ou
 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1109,7 +1106,6 @@ int cx25821_video_register(struct cx2582
 		else
 			vdev->vfl_dir = VFL_DIR_TX;
 		vdev->lock = &dev->lock;
-		set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
 		snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
 		video_set_drvdata(vdev, chan);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx88/cx88-core.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx88/cx88-core.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx88/cx88-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx88/cx88-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1045,7 +1045,6 @@ struct video_device *cx88_vdev_init(stru
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 core->name, type, core->board.name);
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	return vfd;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/cx88/cx88-input.c linux-libre-3.17-rc7-gnu/drivers/media/pci/cx88/cx88-input.c
--- linux-libre-3.16-gnu/drivers/media/pci/cx88/cx88-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/cx88/cx88-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,25 +130,41 @@ static void cx88_ir_handle_key(struct cx
 
 		data = (data << 4) | ((gpio_key & 0xf0) >> 4);
 
-		rc_keydown(ir->dev, data, 0);
+		rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
+
+	} else if (ir->core->boardnr == CX88_BOARD_PROLINK_PLAYTVPVR ||
+		   ir->core->boardnr == CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO) {
+		/* bit cleared on keydown, NEC scancode, 0xAAAACC, A = 0x866b */
+		u16 addr;
+		u8 cmd;
+		u32 scancode;
+
+		addr = (data >> 8) & 0xffff;
+		cmd  = (data >> 0) & 0x00ff;
+		scancode = RC_SCANCODE_NECX(addr, cmd);
+
+		if (0 == (gpio & ir->mask_keyup))
+			rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
+		else
+			rc_keyup(ir->dev);
 
 	} else if (ir->mask_keydown) {
 		/* bit set on keydown */
 		if (gpio & ir->mask_keydown)
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		else
 			rc_keyup(ir->dev);
 
 	} else if (ir->mask_keyup) {
 		/* bit cleared on keydown */
 		if (0 == (gpio & ir->mask_keyup))
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		else
 			rc_keyup(ir->dev);
 
 	} else {
 		/* can't distinguish keydown/up :-/ */
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		rc_keyup(ir->dev);
 	}
 }
@@ -329,6 +345,7 @@ int cx88_ir_init(struct cx88_core *core,
 		 * 002-T mini RC, provided with newer PV hardware
 		 */
 		ir_codes = RC_MAP_PIXELVIEW_MK12;
+		rc_type = RC_BIT_NEC;
 		ir->gpio_addr = MO_GP1_IO;
 		ir->mask_keyup = 0x80;
 		ir->polling = 10; /* ms */
@@ -416,7 +433,6 @@ int cx88_ir_init(struct cx88_core *core,
 		break;
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-		rc_type          = RC_BIT_NEC;
 		ir->sampling     = 0xff00; /* address */
 		break;
 	}
@@ -462,14 +478,14 @@ int cx88_ir_init(struct cx88_core *core,
 	dev->priv = core;
 	dev->open = cx88_ir_open;
 	dev->close = cx88_ir_close;
-	dev->scanmask = hardware_mask;
+	dev->scancode_mask = hardware_mask;
 
 	if (ir->sampling) {
 		dev->driver_type = RC_DRIVER_IR_RAW;
 		dev->timeout = 10 * 1000 * 1000; /* 10 ms */
 	} else {
 		dev->driver_type = RC_DRIVER_SCANCODE;
-		rc_set_allowed_protocols(dev, rc_type);
+		dev->allowed_protocols = rc_type;
 	}
 
 	ir->core = core;
@@ -539,7 +555,8 @@ void cx88_ir_irq(struct cx88_core *core)
 	ir_raw_event_handle(ir->dev);
 }
 
-static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
+			   u32 *scancode, u8 *toggle)
 {
 	int flags, code;
 
@@ -563,8 +580,9 @@ static int get_key_pvr2000(struct IR_i2c
 	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
 		   code & 0xff, flags & 0xff);
 
-	*ir_key = code & 0xff;
-	*ir_raw = code;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = code & 0xff;
+	*toggle = 0;
 	return 1;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ddbridge/ddbridge-core.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ddbridge/ddbridge-core.c
--- linux-libre-3.16-gnu/drivers/media/pci/ddbridge/ddbridge-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ddbridge/ddbridge-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1663,11 +1663,40 @@ static struct ddb_info ddb_octopus_le =
 	.port_num = 2,
 };
 
+static struct ddb_info ddb_octopus_mini = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus Mini",
+	.port_num = 4,
+};
+
 static struct ddb_info ddb_v6 = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Cine S2 V6 DVB adapter",
 	.port_num = 3,
 };
+static struct ddb_info ddb_v6_5 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
+	.port_num = 4,
+};
+
+static struct ddb_info ddb_dvbct = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
+	.port_num = 3,
+};
+
+static struct ddb_info ddb_satixS2v3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
+	.port_num = 3,
+};
+
+static struct ddb_info ddb_octopusv3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus V3 DVB adapter",
+	.port_num = 4,
+};
 
 #define DDVID 0xdd01 /* Digital Devices Vendor ID */
 
@@ -1680,8 +1709,12 @@ static const struct pci_device_id ddb_id
 	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
+	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
+	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
 	/* in case sub-ids got deleted in flash */
 	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
 	{0}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/dm1105/dm1105.c linux-libre-3.17-rc7-gnu/drivers/media/pci/dm1105/dm1105.c
--- linux-libre-3.16-gnu/drivers/media/pci/dm1105/dm1105.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/dm1105/dm1105.c	2014-09-28 17:29:07.000000000 -0400
@@ -678,7 +678,8 @@ static void dm1105_emit_key(struct work_
 
 	data = (ircom >> 8) & 0x7f;
 
-	rc_keydown(ir->dev, data, 0);
+	/* FIXME: UNKNOWN because we don't generate a full NEC scancode (yet?) */
+	rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 }
 
 /* work handler */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-controls.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-controls.c
--- linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-controls.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-controls.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,8 +135,8 @@ static int ivtv_g_volatile_ctrl(struct v
 	/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
 	   control cluster */
 	case V4L2_CID_MPEG_VIDEO_DEC_PTS:
-		return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
-					     &itv->ctrl_frame->val64);
+		return ivtv_g_pts_frame(itv, itv->ctrl_pts->p_new.p_s64,
+					     itv->ctrl_frame->p_new.p_s64);
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-i2c.c
--- linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,7 +148,8 @@ static const char * const hw_devicenames
 	"ir_video",		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
 };
 
-static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_adaptec(struct IR_i2c *ir, enum rc_type *protocol,
+			   u32 *scancode, u8 *toggle)
 {
 	unsigned char keybuf[4];
 
@@ -167,9 +168,9 @@ static int get_key_adaptec(struct IR_i2c
 	keybuf[2] &= 0x7f;
 	keybuf[3] |= 0x80;
 
-	*ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
-	*ir_raw = *ir_key;
-
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
+	*toggle = 0;
 	return 1;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-ioctl.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-ioctl.c
--- linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct fil
 	pixfmt->height = itv->cxhdl.height;
 	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pixfmt->field = V4L2_FIELD_INTERLACED;
-	pixfmt->priv = 0;
 	if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
 		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct fil
 	pixfmt->height = itv->main_rect.height;
 	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pixfmt->field = V4L2_FIELD_INTERLACED;
-	pixfmt->priv = 0;
 	if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
 		switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
 		case IVTV_YUV_MODE_INTERLACED:
@@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file
 	fb->fmt.bytesperline = fb->fmt.width;
 	fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	fb->fmt.field = V4L2_FIELD_INTERLACED;
-	fb->fmt.priv = 0;
 	if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
 		fb->fmt.bytesperline *= 2;
 	if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-streams.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-streams.c
--- linux-libre-3.16-gnu/drivers/media/pci/ivtv/ivtv-streams.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ivtv/ivtv-streams.c	2014-09-28 17:29:07.000000000 -0400
@@ -251,7 +251,6 @@ static int ivtv_prep_dev(struct ivtv *it
 		v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
 		v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
 	}
-	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
 	ivtv_set_funcs(s->vdev);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/pci/Kconfig
--- linux-libre-3.16-gnu/drivers/media/pci/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@ if MEDIA_ANALOG_TV_SUPPORT
 source "drivers/media/pci/ivtv/Kconfig"
 source "drivers/media/pci/zoran/Kconfig"
 source "drivers/media/pci/saa7146/Kconfig"
+source "drivers/media/pci/solo6x10/Kconfig"
 endif
 
 if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/Makefile linux-libre-3.17-rc7-gnu/drivers/media/pci/Makefile
--- linux-libre-3.16-gnu/drivers/media/pci/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -24,3 +24,4 @@ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
 obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
 obj-$(CONFIG_VIDEO_MEYE) += meye/
 obj-$(CONFIG_STA2X11_VIP) += sta2x11/
+obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/meye/meye.c linux-libre-3.17-rc7-gnu/drivers/media/pci/meye/meye.c
--- linux-libre-3.16-gnu/drivers/media/pci/meye/meye.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/meye/meye.c	2014-09-28 17:29:07.000000000 -0400
@@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct
 	f->fmt.pix.sizeimage = f->fmt.pix.height *
 			       f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct f
 	f->fmt.pix.sizeimage = f->fmt.pix.height *
 			       f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1749,7 +1747,6 @@ static int meye_probe(struct pci_dev *pc
 
 	v4l2_ctrl_handler_setup(&meye.hdl);
 	meye.vdev->ctrl_handler = &meye.hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
 
 	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
 				  video_nr) < 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ngene/ngene-core.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ngene/ngene-core.c
--- linux-libre-3.16-gnu/drivers/media/pci/ngene/ngene-core.c	2014-08-07 04:49:28.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ngene/ngene-core.c	2014-09-28 21:30:37.000000000 -0400
@@ -910,7 +910,6 @@ static int AllocateRingBuffers(struct pc
 {
 	dma_addr_t tmp;
 	u32 i, j;
-	int status = 0;
 	u32 SCListMemSize = pRingBuffer->NumBuffers
 		* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
 		    NUM_SCATTER_GATHER_ENTRIES)
@@ -1010,14 +1009,12 @@ static int AllocateRingBuffers(struct pc
 
 	}
 
-	return status;
+	return 0;
 }
 
 static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
 			    struct SRingBufferDescriptor *pRingBuffer)
 {
-	int status = 0;
-
 	/* Copy pointer to scatter gather list in TSRingbuffer
 	   structure for buffer 2
 	   Load number of buffer
@@ -1038,7 +1035,7 @@ static int FillTSIdleBuffer(struct SRing
 			pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
 		Cur = Cur->Next;
 	}
-	return status;
+	return 0;
 }
 
 static u32 RingBufferSizes[MAX_STREAM] = {
@@ -1078,12 +1075,11 @@ static int AllocCommonBuffers(struct nge
 	dev->ngenetohost = dev->FWInterfaceBuffer + 256;
 	dev->EventBuffer = dev->FWInterfaceBuffer + 512;
 
-	dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev,
-						   OVERFLOW_BUFFER_SIZE,
-						   &dev->PAOverflowBuffer);
+	dev->OverflowBuffer = pci_zalloc_consistent(dev->pci_dev,
+						    OVERFLOW_BUFFER_SIZE,
+						    &dev->PAOverflowBuffer);
 	if (!dev->OverflowBuffer)
 		return -ENOMEM;
-	memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE);
 
 	for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
 		int type = dev->card_info->io_type[i];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-core.c linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-core.c
--- linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -811,7 +811,6 @@ static struct video_device *vdev_init(st
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 dev->name, type, saa7134_boards[dev->board].name);
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	video_set_drvdata(vfd, dev);
 	return vfd;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-empress.c linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-empress.c
--- linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-empress.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-empress.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struc
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -270,7 +267,6 @@ static int empress_init(struct saa7134_d
 	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
 		 "%s empress (%s)", dev->name,
 		 saa7134_boards[dev->board].name);
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
 	v4l2_ctrl_handler_init(hdl, 21);
 	v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
 	if (dev->empress_sd)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-input.c linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-input.c
--- linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,14 +83,14 @@ static int build_key(struct saa7134_dev
 		if (data == ir->mask_keycode)
 			rc_keyup(ir->dev);
 		else
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		return 0;
 	}
 
 	if (ir->polling) {
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		} else {
 			rc_keyup(ir->dev);
 		}
@@ -98,7 +98,7 @@ static int build_key(struct saa7134_dev
 	else {	/* IRQ driven mode - handle key press and release in one go */
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 			rc_keyup(ir->dev);
 		}
 	}
@@ -108,7 +108,8 @@ static int build_key(struct saa7134_dev
 
 /* --------------------- Chip specific I2C key builders ----------------- */
 
-static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
+			       u32 *scancode, u8 *toggle)
 {
 	int gpio;
 	int attempt = 0;
@@ -132,10 +133,6 @@ static int get_key_flydvb_trio(struct IR
 	if (0x40000 & ~gpio)
 		return 0; /* No button press */
 
-	/* No button press - only before first key pressed */
-	if (b == 0xFF)
-		return 0;
-
 	/* poll IR chip */
 	/* weak up the IR chip */
 	b = 0;
@@ -158,13 +155,14 @@ static int get_key_flydvb_trio(struct IR
 		return -EIO;
 	}
 
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
-				       u32 *ir_raw)
+static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol,
+				       u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 	int gpio;
@@ -205,14 +203,15 @@ static int get_key_msi_tvanywhere_plus(s
 	/* Button pressed */
 
 	dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
 /* copied and modified from get_key_msi_tvanywhere_plus() */
-static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
-					u32 *ir_raw)
+static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
+				 u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 	unsigned int gpio;
@@ -253,12 +252,14 @@ static int get_key_kworld_pc150u(struct
 	/* Button pressed */
 
 	dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol,
+			    u32 *scancode, u8 *toggle)
 {
 	unsigned char b;
 
@@ -276,12 +277,14 @@ static int get_key_purpletv(struct IR_i2
 	if (b & 0x80)
 		return 1;
 
-	*ir_key = b;
-	*ir_raw = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
+	*toggle = 0;
 	return 1;
 }
 
-static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_hvr1110(struct IR_i2c *ir, enum rc_type *protocol,
+			   u32 *scancode, u8 *toggle)
 {
 	unsigned char buf[5];
 
@@ -299,14 +302,20 @@ static int get_key_hvr1110(struct IR_i2c
 	 * by preserving it into two separate readings
 	 * buf[4] bits 0 and 1, and buf[1] and buf[2] are always
 	 * zero.
+	 *
+	 * Note that the keymap which the hvr1110 uses is RC5.
+	 *
+	 * FIXME: start bits could maybe be used...?
 	 */
-	*ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
-	*ir_raw = *ir_key;
+	*protocol = RC_TYPE_RC5;
+	*scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2);
+	*toggle = !!(buf[3] & 0x40);
 	return 1;
 }
 
 
-static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol,
+			      u32 *scancode, u8 *toggle)
 {
 	unsigned char data[12];
 	u32 gpio;
@@ -332,17 +341,18 @@ static int get_key_beholdm6xx(struct IR_
 	if (data[9] != (unsigned char)(~data[8]))
 		return 0;
 
-	*ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
-	*ir_key = *ir_raw;
-
+	*protocol = RC_TYPE_NEC;
+	*scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
+	*toggle = 0;
 	return 1;
 }
 
 /* Common (grey or coloured) pinnacle PCTV remote handling
  *
  */
-static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
-			    int parity_offset, int marker, int code_modulo)
+static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
+			    u32 *scancode, u8 *toggle, int parity_offset,
+			    int marker, int code_modulo)
 {
 	unsigned char b[4];
 	unsigned int start = 0,parity = 0,code = 0;
@@ -377,11 +387,11 @@ static int get_key_pinnacle(struct IR_i2
 
 	code %= code_modulo;
 
-	*ir_raw = code;
-	*ir_key = code;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = code;
+	*toggle = 0;
 
 	i2cdprintk("Pinnacle PCTV key %02x\n", code);
-
 	return 1;
 }
 
@@ -394,10 +404,11 @@ static int get_key_pinnacle(struct IR_i2
  *
  * Sylvain Pasche <sylvain.pasche@gmail.com>
  */
-static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_type *protocol,
+				 u32 *scancode, u8 *toggle)
 {
 
-	return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
+	return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff);
 }
 
 
@@ -405,7 +416,8 @@ static int get_key_pinnacle_grey(struct
  *
  * Ricardo Cerqueira <v4l@cerqueira.org>
  */
-static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_type *protocol,
+				  u32 *scancode, u8 *toggle)
 {
 	/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
 	 *
@@ -413,7 +425,7 @@ static int get_key_pinnacle_color(struct
 	 * codes < 128
 	 */
 
-	return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
+	return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88);
 }
 
 void saa7134_input_irq(struct saa7134_dev *dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-video.c linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-video.c
--- linux-libre-3.16-gnu/drivers/media/pci/saa7134/saa7134-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7134/saa7134-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struc
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/saa7164/saa7164-dvb.c linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7164/saa7164-dvb.c
--- linux-libre-3.16-gnu/drivers/media/pci/saa7164/saa7164-dvb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/saa7164/saa7164-dvb.c	2014-09-28 17:29:07.000000000 -0400
@@ -242,16 +242,14 @@ static int saa7164_dvb_start_feed(struct
 	if (!demux->dmx.frontend)
 		return -EINVAL;
 
-	if (dvb) {
-		mutex_lock(&dvb->lock);
-		if (dvb->feeding++ == 0) {
-			/* Start transport */
-			ret = saa7164_dvb_start_port(port);
-		}
-		mutex_unlock(&dvb->lock);
-		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
-			__func__, port->nr, dvb->feeding);
+	mutex_lock(&dvb->lock);
+	if (dvb->feeding++ == 0) {
+		/* Start transport */
+		ret = saa7164_dvb_start_port(port);
 	}
+	mutex_unlock(&dvb->lock);
+	dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+		__func__, port->nr, dvb->feeding);
 
 	return ret;
 }
@@ -266,16 +264,14 @@ static int saa7164_dvb_stop_feed(struct
 
 	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
 
-	if (dvb) {
-		mutex_lock(&dvb->lock);
-		if (--dvb->feeding == 0) {
-			/* Stop transport */
-			ret = saa7164_dvb_stop_streaming(port);
-		}
-		mutex_unlock(&dvb->lock);
-		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
-			__func__, port->nr, dvb->feeding);
+	mutex_lock(&dvb->lock);
+	if (--dvb->feeding == 0) {
+		/* Stop transport */
+		ret = saa7164_dvb_stop_streaming(port);
 	}
+	mutex_unlock(&dvb->lock);
+	dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+		__func__, port->nr, dvb->feeding);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/Kconfig
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+config VIDEO_SOLO6X10
+	tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
+	depends on PCI && VIDEO_DEV && SND && I2C
+	select BITREVERSE
+	select FONT_SUPPORT
+	select FONT_8x16
+	select VIDEOBUF2_DMA_SG
+	select VIDEOBUF2_DMA_CONTIG
+	select SND_PCM
+	select FONT_8x16
+	---help---
+	  This driver supports the Bluecherry H.264 and MPEG-4 hardware
+	  compression capture cards and other Softlogic-based ones.
+
+	  Following cards have been tested:
+	  * Bluecherry BC-H16480A (PCIe, 16 port, H.264)
+	  * Bluecherry BC-H04120A (PCIe, 4 port, H.264)
+	  * Bluecherry BC-H04120A-MPCI (Mini-PCI, 4 port, H.264)
+	  * Bluecherry BC-04120A (PCIe, 4 port, MPEG-4)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/Makefile linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/Makefile
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,5 @@
+solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
+		solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
+		solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
+
+obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-core.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-core.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
+MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>");
+MODULE_VERSION(SOLO6X10_VERSION);
+MODULE_LICENSE("GPL");
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
+
+static int full_eeprom; /* default is only top 64B */
+module_param(full_eeprom, uint, 0644);
+MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
+
+
+static void solo_set_time(struct solo_dev *solo_dev)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+
+	solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
+	solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
+}
+
+static void solo_timer_sync(struct solo_dev *solo_dev)
+{
+	u32 sec, usec;
+	struct timespec ts;
+	long diff;
+
+	if (solo_dev->type != SOLO_DEV_6110)
+		return;
+
+	if (++solo_dev->time_sync < 60)
+		return;
+
+	solo_dev->time_sync = 0;
+
+	sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
+	usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
+
+	ktime_get_ts(&ts);
+
+	diff = (long)ts.tv_sec - (long)sec;
+	diff = (diff * 1000000)
+		+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
+
+	if (diff > 1000 || diff < -1000) {
+		solo_set_time(solo_dev);
+	} else if (diff) {
+		long usec_lsb = solo_dev->usec_lsb;
+
+		usec_lsb -= diff / 4;
+		if (usec_lsb < 0)
+			usec_lsb = 0;
+		else if (usec_lsb > 255)
+			usec_lsb = 255;
+
+		solo_dev->usec_lsb = usec_lsb;
+		solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
+			       solo_dev->usec_lsb);
+	}
+}
+
+static irqreturn_t solo_isr(int irq, void *data)
+{
+	struct solo_dev *solo_dev = data;
+	u32 status;
+	int i;
+
+	status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & ~solo_dev->irq_mask) {
+		solo_reg_write(solo_dev, SOLO_IRQ_STAT,
+			       status & ~solo_dev->irq_mask);
+		status &= solo_dev->irq_mask;
+	}
+
+	if (status & SOLO_IRQ_PCI_ERR)
+		solo_p2m_error_isr(solo_dev);
+
+	for (i = 0; i < SOLO_NR_P2M; i++)
+		if (status & SOLO_IRQ_P2M(i))
+			solo_p2m_isr(solo_dev, i);
+
+	if (status & SOLO_IRQ_IIC)
+		solo_i2c_isr(solo_dev);
+
+	if (status & SOLO_IRQ_VIDEO_IN) {
+		solo_video_in_isr(solo_dev);
+		solo_timer_sync(solo_dev);
+	}
+
+	if (status & SOLO_IRQ_ENCODER)
+		solo_enc_v4l2_isr(solo_dev);
+
+	if (status & SOLO_IRQ_G723)
+		solo_g723_isr(solo_dev);
+
+	/* Clear all interrupts handled */
+	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+
+	return IRQ_HANDLED;
+}
+
+static void free_solo_dev(struct solo_dev *solo_dev)
+{
+	struct pci_dev *pdev;
+
+	if (!solo_dev)
+		return;
+
+	if (solo_dev->dev.parent)
+		device_unregister(&solo_dev->dev);
+
+	pdev = solo_dev->pdev;
+
+	/* If we never initialized the PCI device, then nothing else
+	 * below here needs cleanup */
+	if (!pdev) {
+		kfree(solo_dev);
+		return;
+	}
+
+	if (solo_dev->reg_base) {
+		/* Bring down the sub-devices first */
+		solo_g723_exit(solo_dev);
+		solo_enc_v4l2_exit(solo_dev);
+		solo_enc_exit(solo_dev);
+		solo_v4l2_exit(solo_dev);
+		solo_disp_exit(solo_dev);
+		solo_gpio_exit(solo_dev);
+		solo_p2m_exit(solo_dev);
+		solo_i2c_exit(solo_dev);
+
+		/* Now cleanup the PCI device */
+		solo_irq_off(solo_dev, ~0);
+		pci_iounmap(pdev, solo_dev->reg_base);
+		if (pdev->irq)
+			free_irq(pdev->irq, solo_dev);
+	}
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	v4l2_device_unregister(&solo_dev->v4l2_dev);
+	pci_set_drvdata(pdev, NULL);
+
+	kfree(solo_dev);
+}
+
+static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned short *p = (unsigned short *)buf;
+	int i;
+
+	if (count & 0x1)
+		dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
+
+	if (!full_eeprom && count > 64) {
+		dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
+		count = 64;
+	} else if (full_eeprom && count > 128) {
+		dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
+		count = 128;
+	}
+
+	solo_eeprom_ewen(solo_dev, 1);
+
+	for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
+					       (int)(count / 2)); i++)
+		solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
+
+	solo_eeprom_ewen(solo_dev, 0);
+
+	return count;
+}
+
+static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned short *p = (unsigned short *)buf;
+	int count = (full_eeprom ? 128 : 64);
+	int i;
+
+	for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
+		p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
+
+	return count;
+}
+
+static ssize_t p2m_timeouts_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
+}
+
+static ssize_t sdram_size_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
+}
+
+static ssize_t tw28xx_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
+		       hweight32(solo_dev->tw2815),
+		       hweight32(solo_dev->tw2864),
+		       hweight32(solo_dev->tw2865));
+}
+
+static ssize_t input_map_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned int val;
+	char *out = buf;
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
+	out += sprintf(out, "Channel 0   => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 1   => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 2   => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 3   => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Channel 4   => Input %d\n", (val >> 20) & 0x1f);
+	out += sprintf(out, "Channel 5   => Input %d\n", (val >> 25) & 0x1f);
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
+	out += sprintf(out, "Channel 6   => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 7   => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 8   => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 9   => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Channel 10  => Input %d\n", (val >> 20) & 0x1f);
+	out += sprintf(out, "Channel 11  => Input %d\n", (val >> 25) & 0x1f);
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
+	out += sprintf(out, "Channel 12  => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 13  => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 14  => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 15  => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
+
+	return out - buf;
+}
+
+static ssize_t p2m_timeout_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned long ms;
+	int ret = kstrtoul(buf, 10, &ms);
+
+	if (ret < 0 || ms > 200)
+		return -EINVAL;
+	solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
+
+	return count;
+}
+
+static ssize_t p2m_timeout_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
+}
+
+static ssize_t intervals_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	char *out = buf;
+	int fps = solo_dev->fps;
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
+			       i, solo_dev->v4l2_enc[i]->interval, fps,
+			       solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
+	}
+
+	return out - buf;
+}
+
+static ssize_t sdram_offsets_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	char *out = buf;
+
+	out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
+		       SOLO_DISP_EXT_ADDR,
+		       SOLO_DISP_EXT_SIZE);
+
+	out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_EOSD_EXT_ADDR,
+		       SOLO_EOSD_EXT_AREA(solo_dev),
+		       SOLO_EOSD_EXT_SIZE(solo_dev),
+		       SOLO_EOSD_EXT_AREA(solo_dev) /
+		       SOLO_EOSD_EXT_SIZE(solo_dev));
+
+	out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
+		       SOLO_MOTION_EXT_ADDR(solo_dev),
+		       SOLO_MOTION_EXT_SIZE);
+
+	out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
+		       SOLO_G723_EXT_ADDR(solo_dev),
+		       SOLO_G723_EXT_SIZE);
+
+	out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_CAP_EXT_ADDR(solo_dev),
+		       SOLO_CAP_EXT_SIZE(solo_dev),
+		       SOLO_CAP_PAGE_SIZE,
+		       SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
+
+	out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_EREF_EXT_ADDR(solo_dev),
+		       SOLO_EREF_EXT_AREA(solo_dev),
+		       SOLO_EREF_EXT_SIZE,
+		       SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
+
+	out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
+		       SOLO_MP4E_EXT_ADDR(solo_dev),
+		       SOLO_MP4E_EXT_SIZE(solo_dev));
+
+	out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
+		       SOLO_JPEG_EXT_ADDR(solo_dev),
+		       SOLO_JPEG_EXT_SIZE(solo_dev));
+
+	return out - buf;
+}
+
+static ssize_t sdram_show(struct file *file, struct kobject *kobj,
+			  struct bin_attribute *a, char *buf,
+			  loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	const int size = solo_dev->sdram_size;
+
+	if (off >= size)
+		return 0;
+
+	if (off + count > size)
+		count = size - off;
+
+	if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
+		return -EIO;
+
+	return count;
+}
+
+static const struct device_attribute solo_dev_attrs[] = {
+	__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
+	__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
+	__ATTR_RO(p2m_timeouts),
+	__ATTR_RO(sdram_size),
+	__ATTR_RO(tw28xx),
+	__ATTR_RO(input_map),
+	__ATTR_RO(intervals),
+	__ATTR_RO(sdram_offsets),
+};
+
+static void solo_device_release(struct device *dev)
+{
+	/* Do nothing */
+}
+
+static int solo_sysfs_init(struct solo_dev *solo_dev)
+{
+	struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
+	struct device *dev = &solo_dev->dev;
+	const char *driver;
+	int i;
+
+	if (solo_dev->type == SOLO_DEV_6110)
+		driver = "solo6110";
+	else
+		driver = "solo6010";
+
+	dev->release = solo_device_release;
+	dev->parent = &solo_dev->pdev->dev;
+	set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
+	dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
+		     solo_dev->nr_chans);
+
+	if (device_register(dev)) {
+		dev->parent = NULL;
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
+		if (device_create_file(dev, &solo_dev_attrs[i])) {
+			device_unregister(dev);
+			return -ENOMEM;
+		}
+	}
+
+	sysfs_attr_init(&sdram_attr->attr);
+	sdram_attr->attr.name = "sdram";
+	sdram_attr->attr.mode = 0440;
+	sdram_attr->read = sdram_show;
+	sdram_attr->size = solo_dev->sdram_size;
+
+	if (device_create_bin_file(dev, sdram_attr)) {
+		device_unregister(dev);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct solo_dev *solo_dev;
+	int ret;
+	u8 chip_id;
+
+	solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
+	if (solo_dev == NULL)
+		return -ENOMEM;
+
+	if (id->driver_data == SOLO_DEV_6010)
+		dev_info(&pdev->dev, "Probing Softlogic 6010\n");
+	else
+		dev_info(&pdev->dev, "Probing Softlogic 6110\n");
+
+	solo_dev->type = id->driver_data;
+	solo_dev->pdev = pdev;
+	spin_lock_init(&solo_dev->reg_io_lock);
+	ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Only for during init */
+	solo_dev->p2m_jiffies = msecs_to_jiffies(100);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto fail_probe;
+
+	pci_set_master(pdev);
+
+	/* RETRY/TRDY Timeout disabled */
+	pci_write_config_byte(pdev, 0x40, 0x00);
+	pci_write_config_byte(pdev, 0x41, 0x00);
+
+	ret = pci_request_regions(pdev, SOLO6X10_NAME);
+	if (ret)
+		goto fail_probe;
+
+	solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
+	if (solo_dev->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto fail_probe;
+	}
+
+	chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
+				SOLO_CHIP_ID_MASK;
+	switch (chip_id) {
+	case 7:
+		solo_dev->nr_chans = 16;
+		solo_dev->nr_ext = 5;
+		break;
+	case 6:
+		solo_dev->nr_chans = 8;
+		solo_dev->nr_ext = 2;
+		break;
+	default:
+		dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
+			 chip_id);
+	case 5:
+		solo_dev->nr_chans = 4;
+		solo_dev->nr_ext = 1;
+	}
+
+	/* Disable all interrupts to start */
+	solo_irq_off(solo_dev, ~0);
+
+	/* Initial global settings */
+	if (solo_dev->type == SOLO_DEV_6010) {
+		solo_dev->clock_mhz = 108;
+		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
+			| SOLO_SYS_CFG_INPUTDIV(25)
+			| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
+			| SOLO_SYS_CFG_OUTDIV(3);
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+	} else {
+		u32 divq, divf;
+
+		solo_dev->clock_mhz = 135;
+
+		if (solo_dev->clock_mhz < 125) {
+			divq = 3;
+			divf = (solo_dev->clock_mhz * 4) / 3 - 1;
+		} else {
+			divq = 2;
+			divf = (solo_dev->clock_mhz * 2) / 3 - 1;
+		}
+
+		solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
+			       (1 << 20) | /* PLL_RANGE */
+			       (8 << 15) | /* PLL_DIVR  */
+			       (divq << 12) |
+			       (divf <<  4) |
+			       (1 <<  1)   /* PLL_FSEN */);
+
+		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
+	}
+
+	solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+	solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
+		       solo_dev->clock_mhz - 1);
+
+	/* PLL locking time of 1ms */
+	mdelay(1);
+
+	ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
+			  solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Handle this from the start */
+	solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
+
+	ret = solo_i2c_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Setup the DMA engine */
+	solo_reg_write(solo_dev, SOLO_DMA_CTRL,
+		       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
+		       SOLO_DMA_CTRL_SDRAM_SIZE(2) |
+		       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
+		       SOLO_DMA_CTRL_READ_CLK_SELECT |
+		       SOLO_DMA_CTRL_LATENCY(1));
+
+	/* Undocumented crap */
+	solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
+		       solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
+
+	if (solo_dev->type != SOLO_DEV_6010) {
+		solo_dev->usec_lsb = 0x3f;
+		solo_set_time(solo_dev);
+	}
+
+	/* Disable watchdog */
+	solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
+
+	/* Initialize sub components */
+
+	ret = solo_p2m_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_disp_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_gpio_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_tw28_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_v4l2_init(solo_dev, video_nr);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_enc_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_enc_v4l2_init(solo_dev, video_nr);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_g723_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_sysfs_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Now that init is over, set this lower */
+	solo_dev->p2m_jiffies = msecs_to_jiffies(20);
+
+	return 0;
+
+fail_probe:
+	free_solo_dev(solo_dev);
+	return ret;
+}
+
+static void solo_pci_remove(struct pci_dev *pdev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+	struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
+
+	free_solo_dev(solo_dev);
+}
+
+static const struct pci_device_id solo_id_table[] = {
+	/* 6010 based cards */
+	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
+	  .driver_data = SOLO_DEV_6010 },
+	/* 6110 based cards */
+	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
+	  .driver_data = SOLO_DEV_6110 },
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, solo_id_table);
+
+static struct pci_driver solo_pci_driver = {
+	.name = SOLO6X10_NAME,
+	.id_table = solo_id_table,
+	.probe = solo_pci_probe,
+	.remove = solo_pci_remove,
+};
+
+module_pci_driver(solo_pci_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-disp.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-disp.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-disp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-disp.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ioctl.h>
+
+#include "solo6x10.h"
+
+#define SOLO_VCLK_DELAY			3
+#define SOLO_PROGRESSIVE_VSIZE		1024
+
+#define SOLO_MOT_THRESH_W		64
+#define SOLO_MOT_THRESH_H		64
+#define SOLO_MOT_THRESH_SIZE		8192
+#define SOLO_MOT_THRESH_REAL		(SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
+#define SOLO_MOT_FLAG_SIZE		1024
+#define SOLO_MOT_FLAG_AREA		(SOLO_MOT_FLAG_SIZE * 16)
+
+static void solo_vin_config(struct solo_dev *solo_dev)
+{
+	solo_dev->vin_hstart = 8;
+	solo_dev->vin_vstart = 2;
+
+	solo_reg_write(solo_dev, SOLO_SYS_VCLK,
+		       SOLO_VCLK_SELECT(2) |
+		       SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
+		       SOLO_VI_H_START(solo_dev->vin_hstart) |
+		       SOLO_VI_V_START(solo_dev->vin_vstart) |
+		       SOLO_VI_V_STOP(solo_dev->vin_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
+		       SOLO_VI_H_START(solo_dev->vout_hstart) |
+		       SOLO_VI_V_START(solo_dev->vout_vstart) |
+		       SOLO_VI_V_STOP(solo_dev->vout_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_P,
+		       SOLO_VI_H_START(0) |
+		       SOLO_VI_V_START(1) |
+		       SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
+
+	solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
+		       SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
+
+	/* On 6110, initialize mozaic darkness stength */
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
+	else
+		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
+
+	solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
+			       SOLO_VI_PB_USER_MODE);
+		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
+			       SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
+		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
+			       SOLO_VI_PB_VSTART(4) |
+			       SOLO_VI_PB_VSTOP(4 + 240));
+	} else {
+		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
+			       SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
+		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
+			       SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
+		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
+			       SOLO_VI_PB_VSTART(4) |
+			       SOLO_VI_PB_VSTOP(4 + 288));
+	}
+	solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
+		       SOLO_VI_PB_HSTOP(16 + 720));
+}
+
+static void solo_vout_config_cursor(struct solo_dev *dev)
+{
+	int i;
+
+	/* Load (blank) cursor bitmap mask (2bpp) */
+	for (i = 0; i < 20; i++)
+		solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
+
+	solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
+
+	solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
+		       (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
+	solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
+}
+
+static void solo_vout_config(struct solo_dev *solo_dev)
+{
+	solo_dev->vout_hstart = 6;
+	solo_dev->vout_vstart = 8;
+
+	solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
+		       solo_dev->video_type |
+		       SOLO_VO_USER_COLOR_SET_NAV |
+		       SOLO_VO_USER_COLOR_SET_NAH |
+		       SOLO_VO_NA_COLOR_Y(0) |
+		       SOLO_VO_NA_COLOR_CB(0) |
+		       SOLO_VO_NA_COLOR_CR(0));
+
+	solo_reg_write(solo_dev, SOLO_VO_ACT_H,
+		       SOLO_VO_H_START(solo_dev->vout_hstart) |
+		       SOLO_VO_H_STOP(solo_dev->vout_hstart +
+				      solo_dev->video_hsize));
+
+	solo_reg_write(solo_dev, SOLO_VO_ACT_V,
+		       SOLO_VO_V_START(solo_dev->vout_vstart) |
+		       SOLO_VO_V_STOP(solo_dev->vout_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
+		       SOLO_VO_H_LEN(solo_dev->video_hsize) |
+		       SOLO_VO_V_LEN(solo_dev->video_vsize));
+
+	/* Border & background colors */
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
+		       (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
+		       (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
+	solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
+		       (16 << 24) | (128 << 16) | (16 << 8) | 128);
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
+
+	solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
+		       SOLO_VO_DISP_ERASE_COUNT(8) |
+		       SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
+
+
+	solo_vout_config_cursor(solo_dev);
+
+	/* Enable channels we support */
+	solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
+		       (1 << solo_dev->nr_chans) - 1);
+}
+
+static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
+			       u16 val, int reg_size)
+{
+	u16 *buf;
+	const int n = 64, size = n * sizeof(*buf);
+	int i, ret = 0;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++)
+		buf[i] = cpu_to_le16(val);
+
+	for (i = 0; i < reg_size; i += size) {
+		ret = solo_p2m_dma(solo_dev, 1, buf,
+				   SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
+				   size, 0, 0);
+
+		if (ret)
+			break;
+	}
+
+	kfree(buf);
+	return ret;
+}
+
+int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
+{
+	if (ch > solo_dev->nr_chans)
+		return -EINVAL;
+
+	return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
+				   (ch * SOLO_MOT_THRESH_SIZE * 2),
+				   val, SOLO_MOT_THRESH_SIZE);
+}
+
+int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
+		const u16 *thresholds)
+{
+	const unsigned size = sizeof(u16) * 64;
+	u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
+	u16 *buf;
+	int x, y;
+	int ret = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+	for (y = 0; y < SOLO_MOTION_SZ; y++) {
+		for (x = 0; x < SOLO_MOTION_SZ; x++)
+			buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
+		ret |= solo_p2m_dma(solo_dev, 1, buf,
+			SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
+			size, 0, 0);
+	}
+	kfree(buf);
+	return ret;
+}
+
+/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
+ * threshold and working table for each channel. Atleast that's what the
+ * spec says. However, this code (taken from rdk) has some mystery 8k
+ * block right after the flag area, before the first thresh table. */
+static void solo_motion_config(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		/* Clear motion flag area */
+		solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
+				    SOLO_MOT_FLAG_SIZE);
+
+		/* Clear working cache table */
+		solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
+				    (i * SOLO_MOT_THRESH_SIZE * 2) +
+				    SOLO_MOT_THRESH_SIZE, 0x0000,
+				    SOLO_MOT_THRESH_SIZE);
+
+		/* Set default threshold table */
+		solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
+	}
+
+	/* Default motion settings */
+	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
+		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
+	solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
+		       SOLO_VI_MOTION_FRAME_COUNT(3) |
+		       SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
+		       /* | SOLO_VI_MOTION_INTR_START_STOP */
+		       | SOLO_VI_MOTION_SAMPLE_COUNT(10));
+
+	solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
+	solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
+}
+
+int solo_disp_init(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_dev->video_hsize = 704;
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+		solo_dev->video_vsize = 240;
+		solo_dev->fps = 30;
+	} else {
+		solo_dev->video_vsize = 288;
+		solo_dev->fps = 25;
+	}
+
+	solo_vin_config(solo_dev);
+	solo_motion_config(solo_dev);
+	solo_vout_config(solo_dev);
+
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
+
+	return 0;
+}
+
+void solo_disp_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
+		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
+		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
+	}
+
+	/* Set default border */
+	for (i = 0; i < 5; i++)
+		solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
+
+	for (i = 0; i < 5; i++)
+		solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-eeprom.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-eeprom.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-eeprom.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "solo6x10.h"
+
+/* Control */
+#define EE_SHIFT_CLK	0x04
+#define EE_CS		0x08
+#define EE_DATA_WRITE	0x02
+#define EE_DATA_READ	0x01
+#define EE_ENB		(0x80 | EE_CS)
+
+#define eeprom_delay()	udelay(100)
+#if 0
+#define eeprom_delay()	solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
+#define eeprom_delay()	({				\
+	int i, ret;					\
+	udelay(100);					\
+	for (i = ret = 0; i < 1000 && !ret; i++)	\
+		ret = solo_eeprom_reg_read(solo_dev);	\
+})
+#endif
+#define ADDR_LEN	6
+
+/* Commands */
+#define EE_EWEN_CMD	4
+#define EE_EWDS_CMD	4
+#define EE_WRITE_CMD	5
+#define EE_READ_CMD	6
+#define EE_ERASE_CMD	7
+
+static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
+{
+	return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
+}
+
+static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
+{
+	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
+	eeprom_delay();
+}
+
+static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
+{
+	int i;
+
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+
+	for (i = 4 + ADDR_LEN; i >= 0; i--) {
+		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK | dataval);
+	}
+
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+}
+
+unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
+{
+	int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
+	unsigned int retval = 0;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, ewen_cmd);
+
+	for (i = 0; i < 16; i++) {
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+	}
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+	retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+
+	return retval;
+}
+
+unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
+{
+	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
+	unsigned short retval = 0;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, read_cmd);
+
+	for (i = 0; i < 16; i++) {
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+	}
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+
+	return retval;
+}
+
+int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
+		      unsigned short data)
+{
+	int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
+	unsigned int retval;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, write_cmd);
+
+	for (i = 15; i >= 0; i--) {
+		unsigned int dataval = (data >> i) & 1;
+
+		solo_eeprom_reg_write(solo_dev, EE_ENB);
+		solo_eeprom_reg_write(solo_dev,
+				      EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
+	}
+
+	solo_eeprom_reg_write(solo_dev, EE_ENB);
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+	solo_eeprom_reg_write(solo_dev, EE_ENB);
+
+	for (i = retval = 0; i < 10000 && !retval; i++)
+		retval = solo_eeprom_reg_read(solo_dev);
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+
+	return !retval;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-enc.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-enc.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-enc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-enc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/font.h>
+#include <linux/bitrev.h>
+#include <linux/slab.h>
+
+#include "solo6x10.h"
+
+#define VI_PROG_HSIZE			(1280 - 16)
+#define VI_PROG_VSIZE			(1024 - 16)
+
+#define IRQ_LEVEL			2
+
+static void solo_capture_config(struct solo_dev *solo_dev)
+{
+	unsigned long height;
+	unsigned long width;
+	void *buf;
+	int i;
+
+	solo_reg_write(solo_dev, SOLO_CAP_BASE,
+		       SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
+					  - SOLO_CAP_PAGE_SIZE) >> 16)
+		       | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
+
+	/* XXX: Undocumented bits at b17 and b24 */
+	if (solo_dev->type == SOLO_DEV_6110) {
+		/* NOTE: Ref driver has (62 << 24) here as well, but it causes
+		 * wacked out frame timing on 4-port 6110. */
+		solo_reg_write(solo_dev, SOLO_CAP_BTW,
+			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
+			       SOLO_CAP_MAX_BANDWIDTH(36));
+	} else {
+		solo_reg_write(solo_dev, SOLO_CAP_BTW,
+			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
+			       SOLO_CAP_MAX_BANDWIDTH(32));
+	}
+
+	/* Set scale 1, 9 dimension */
+	width = solo_dev->video_hsize;
+	height = solo_dev->video_vsize;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 2, 10 dimension */
+	width = solo_dev->video_hsize / 2;
+	height = solo_dev->video_vsize;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 3, 11 dimension */
+	width = solo_dev->video_hsize / 2;
+	height = solo_dev->video_vsize / 2;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 4, 12 dimension */
+	width = solo_dev->video_hsize / 3;
+	height = solo_dev->video_vsize / 3;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 5, 13 dimension */
+	width = solo_dev->video_hsize / 4;
+	height = solo_dev->video_vsize / 2;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Progressive */
+	width = VI_PROG_HSIZE;
+	height = VI_PROG_VSIZE;
+	solo_reg_write(solo_dev, SOLO_DIM_PROG,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Clear OSD */
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
+	solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
+		       0xF0 << 16 | 0x80 << 8 | 0x80);
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
+			       SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
+	else
+		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
+			       | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
+
+	/* Clear OSG buffer */
+	buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
+	if (!buf)
+		return;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_p2m_dma(solo_dev, 1, buf,
+			     SOLO_EOSD_EXT_ADDR +
+			     (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
+			     SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
+	}
+	kfree(buf);
+}
+
+#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
+
+/* Should be called with enable_lock held */
+int solo_osd_print(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	unsigned char *str = solo_enc->osd_text;
+	u8 *buf = solo_enc->osd_buf;
+	u32 reg;
+	const struct font_desc *vga = find_font("VGA8x16");
+	const unsigned char *vga_data;
+	int i, j;
+
+	if (WARN_ON_ONCE(!vga))
+		return -ENODEV;
+
+	reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
+	if (!*str) {
+		/* Disable OSD on this channel */
+		reg &= ~(1 << solo_enc->ch);
+		goto out;
+	}
+
+	memset(buf, 0, SOLO_OSD_WRITE_SIZE);
+	vga_data = (const unsigned char *)vga->data;
+
+	for (i = 0; *str; i++, str++) {
+		for (j = 0; j < 16; j++) {
+			buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
+			    bitrev8(vga_data[(*str << 4) | j]);
+		}
+	}
+
+	solo_p2m_dma(solo_dev, 1, buf,
+		     SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
+		     SOLO_OSD_WRITE_SIZE, 0, 0);
+
+	/* Enable OSD on this channel */
+	reg |= (1 << solo_enc->ch);
+
+out:
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
+	return 0;
+}
+
+/**
+ * Set channel Quality Profile (0-3).
+ */
+void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
+		    unsigned int qp)
+{
+	unsigned long flags;
+	unsigned int idx, reg;
+
+	if ((ch > 31) || (qp > 3))
+		return;
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		return;
+
+	if (ch < 16) {
+		idx = 0;
+		reg = SOLO_VE_JPEG_QP_CH_L;
+	} else {
+		ch -= 16;
+		idx = 1;
+		reg = SOLO_VE_JPEG_QP_CH_H;
+	}
+	ch *= 2;
+
+	spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
+
+	solo_dev->jpeg_qp[idx] &= ~(3 << ch);
+	solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
+
+	solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
+
+	spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
+}
+
+int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
+{
+	int idx;
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		return 2;
+
+	if (WARN_ON_ONCE(ch > 31))
+		return 2;
+
+	if (ch < 16) {
+		idx = 0;
+	} else {
+		ch -= 16;
+		idx = 1;
+	}
+	ch *= 2;
+
+	return (solo_dev->jpeg_qp[idx] >> ch) & 3;
+}
+
+#define SOLO_QP_INIT 0xaaaaaaaa
+
+static void solo_jpeg_config(struct solo_dev *solo_dev)
+{
+	if (solo_dev->type == SOLO_DEV_6010) {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
+			       (2 << 24) | (2 << 16) | (2 << 8) | 2);
+	} else {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
+			       (4 << 24) | (3 << 16) | (2 << 8) | 1);
+	}
+
+	spin_lock_init(&solo_dev->jpeg_qp_lock);
+
+	/* Initialize Quality Profile for all channels */
+	solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
+
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
+		(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
+		((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
+	if (solo_dev->type == SOLO_DEV_6110) {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
+			       (0 << 16) | (30 << 8) | 60);
+	}
+}
+
+static void solo_mp4e_config(struct solo_dev *solo_dev)
+{
+	int i;
+	u32 cfg;
+
+	solo_reg_write(solo_dev, SOLO_VE_CFG0,
+		       SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
+		       SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
+		       SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
+
+
+	cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
+		| SOLO_VE_MOTION_MODE(0);
+	if (solo_dev->type != SOLO_DEV_6010) {
+		cfg |= SOLO_VE_MPEG_SIZE_H(
+			(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
+		cfg |= SOLO_VE_JPEG_SIZE_H(
+			(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
+	}
+	solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
+
+	solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
+	if (solo_dev->type == SOLO_DEV_6110)
+		solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
+	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
+
+	solo_reg_write(solo_dev, SOLO_VE_ATTR,
+		       SOLO_VE_LITTLE_ENDIAN |
+		       SOLO_COMP_ATTR_FCODE(1) |
+		       SOLO_COMP_TIME_INC(0) |
+		       SOLO_COMP_TIME_WIDTH(15) |
+		       SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
+			       (SOLO_EREF_EXT_ADDR(solo_dev) +
+			       (i * SOLO_EREF_EXT_SIZE)) >> 16);
+		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
+			       (SOLO_EREF_EXT_ADDR(solo_dev) +
+			       ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
+	}
+
+	if (solo_dev->type == SOLO_DEV_6110) {
+		solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
+	} else {
+		for (i = 0; i < solo_dev->nr_chans; i++)
+			solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
+	}
+}
+
+int solo_enc_init(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_capture_config(solo_dev);
+	solo_mp4e_config(solo_dev);
+	solo_jpeg_config(solo_dev);
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
+	}
+
+	return 0;
+}
+
+void solo_enc_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-g723.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-g723.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-g723.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-g723.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/poll.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/control.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+#define G723_FDMA_PAGES		32
+#define G723_PERIOD_BYTES	48
+#define G723_PERIOD_BLOCK	1024
+#define G723_FRAMES_PER_PAGE	48
+
+/* Sets up channels 16-19 for decoding and 0-15 for encoding */
+#define OUTMODE_MASK		0x300
+
+#define SAMPLERATE		8000
+#define BITRATE			25
+
+/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
+ * is broken down to 20 * 48 byte regions (one for each channel possible)
+ * with the rest of the page being dummy data. */
+#define G723_MAX_BUFFER		(G723_PERIOD_BYTES * PERIODS_MAX)
+#define G723_INTR_ORDER		4 /* 0 - 4 */
+#define PERIODS_MIN		(1 << G723_INTR_ORDER)
+#define PERIODS_MAX		G723_FDMA_PAGES
+
+struct solo_snd_pcm {
+	int				on;
+	spinlock_t			lock;
+	struct solo_dev		*solo_dev;
+	unsigned char			*g723_buf;
+	dma_addr_t			g723_dma;
+};
+
+static void solo_g723_config(struct solo_dev *solo_dev)
+{
+	int clk_div;
+
+	clk_div = (solo_dev->clock_mhz * 1000000)
+		/ (SAMPLERATE * (BITRATE * 2) * 2);
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
+		       SOLO_AUDIO_BITRATE(BITRATE)
+		       | SOLO_AUDIO_CLK_DIV(clk_div));
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
+		       SOLO_AUDIO_FDMA_INTERVAL(1)
+		       | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER)
+		       | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
+		       SOLO_AUDIO_ENABLE
+		       | SOLO_AUDIO_I2S_MODE
+		       | SOLO_AUDIO_I2S_MULTI(3)
+		       | SOLO_AUDIO_MODE(OUTMODE_MASK));
+}
+
+void solo_g723_isr(struct solo_dev *solo_dev)
+{
+	struct snd_pcm_str *pstr =
+		&solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
+	struct snd_pcm_substream *ss;
+	struct solo_snd_pcm *solo_pcm;
+
+	for (ss = pstr->substream; ss != NULL; ss = ss->next) {
+		if (snd_pcm_substream_chip(ss) == NULL)
+			continue;
+
+		/* This means open() hasn't been called on this one */
+		if (snd_pcm_substream_chip(ss) == solo_dev)
+			continue;
+
+		/* Haven't triggered a start yet */
+		solo_pcm = snd_pcm_substream_chip(ss);
+		if (!solo_pcm->on)
+			continue;
+
+		snd_pcm_period_elapsed(ss);
+	}
+}
+
+static int snd_solo_hw_params(struct snd_pcm_substream *ss,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
+}
+
+static int snd_solo_hw_free(struct snd_pcm_substream *ss)
+{
+	return snd_pcm_lib_free_pages(ss);
+}
+
+static const struct snd_pcm_hardware snd_solo_pcm_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP |
+				   SNDRV_PCM_INFO_INTERLEAVED |
+				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				   SNDRV_PCM_INFO_MMAP_VALID),
+	.formats		= SNDRV_PCM_FMTBIT_U8,
+	.rates			= SNDRV_PCM_RATE_8000,
+	.rate_min		= SAMPLERATE,
+	.rate_max		= SAMPLERATE,
+	.channels_min		= 1,
+	.channels_max		= 1,
+	.buffer_bytes_max	= G723_MAX_BUFFER,
+	.period_bytes_min	= G723_PERIOD_BYTES,
+	.period_bytes_max	= G723_PERIOD_BYTES,
+	.periods_min		= PERIODS_MIN,
+	.periods_max		= PERIODS_MAX,
+};
+
+static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
+{
+	struct solo_dev *solo_dev = snd_pcm_substream_chip(ss);
+	struct solo_snd_pcm *solo_pcm;
+
+	solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
+	if (solo_pcm == NULL)
+		goto oom;
+
+	solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev,
+						  G723_PERIOD_BYTES,
+						  &solo_pcm->g723_dma);
+	if (solo_pcm->g723_buf == NULL)
+		goto oom;
+
+	spin_lock_init(&solo_pcm->lock);
+	solo_pcm->solo_dev = solo_dev;
+	ss->runtime->hw = snd_solo_pcm_hw;
+
+	snd_pcm_substream_chip(ss) = solo_pcm;
+
+	return 0;
+
+oom:
+	kfree(solo_pcm);
+	return -ENOMEM;
+}
+
+static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+
+	snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
+	pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES,
+			    solo_pcm->g723_buf, solo_pcm->g723_dma);
+	kfree(solo_pcm);
+
+	return 0;
+}
+
+static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	int ret = 0;
+
+	spin_lock(&solo_pcm->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		if (solo_pcm->on == 0) {
+			/* If this is the first user, switch on interrupts */
+			if (atomic_inc_return(&solo_dev->snd_users) == 1)
+				solo_irq_on(solo_dev, SOLO_IRQ_G723);
+			solo_pcm->on = 1;
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		if (solo_pcm->on) {
+			/* If this was our last user, switch them off */
+			if (atomic_dec_return(&solo_dev->snd_users) == 0)
+				solo_irq_off(solo_dev, SOLO_IRQ_G723);
+			solo_pcm->on = 0;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock(&solo_pcm->lock);
+
+	return ret;
+}
+
+static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
+{
+	return 0;
+}
+
+static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f;
+
+	return idx * G723_FRAMES_PER_PAGE;
+}
+
+static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
+			     snd_pcm_uframes_t pos, void __user *dst,
+			     snd_pcm_uframes_t count)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	int err, i;
+
+	for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
+		int page = (pos / G723_FRAMES_PER_PAGE) + i;
+
+		err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
+				     SOLO_G723_EXT_ADDR(solo_dev) +
+				     (page * G723_PERIOD_BLOCK) +
+				     (ss->number * G723_PERIOD_BYTES),
+				     G723_PERIOD_BYTES, 0, 0);
+		if (err)
+			return err;
+
+		err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
+				   solo_pcm->g723_buf, G723_PERIOD_BYTES);
+
+		if (err)
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static struct snd_pcm_ops snd_solo_pcm_ops = {
+	.open = snd_solo_pcm_open,
+	.close = snd_solo_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_solo_hw_params,
+	.hw_free = snd_solo_hw_free,
+	.prepare = snd_solo_pcm_prepare,
+	.trigger = snd_solo_pcm_trigger,
+	.pointer = snd_solo_pcm_pointer,
+	.copy = snd_solo_pcm_copy,
+};
+
+static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = 1;
+	info->value.integer.min = 0;
+	info->value.integer.max = 15;
+	info->value.integer.step = 1;
+
+	return 0;
+}
+
+static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
+	u8 ch = value->id.numid - 1;
+
+	value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);
+
+	return 0;
+}
+
+static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
+	u8 ch = value->id.numid - 1;
+	u8 old_val;
+
+	old_val = tw28_get_audio_gain(solo_dev, ch);
+	if (old_val == value->value.integer.value[0])
+		return 0;
+
+	tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new snd_solo_capture_volume = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Capture Volume",
+	.info = snd_solo_capture_volume_info,
+	.get = snd_solo_capture_volume_get,
+	.put = snd_solo_capture_volume_put,
+};
+
+static int solo_snd_pcm_init(struct solo_dev *solo_dev)
+{
+	struct snd_card *card = solo_dev->snd_card;
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *ss;
+	int ret;
+	int i;
+
+	ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans,
+			  &pcm);
+	if (ret < 0)
+		return ret;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_solo_pcm_ops);
+
+	snd_pcm_chip(pcm) = solo_dev;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, card->shortname);
+
+	for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	     ss; ss = ss->next, i++)
+		sprintf(ss->name, "Camera #%d Audio", i);
+
+	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+					SNDRV_DMA_TYPE_CONTINUOUS,
+					snd_dma_continuous_data(GFP_KERNEL),
+					G723_MAX_BUFFER, G723_MAX_BUFFER);
+	if (ret < 0)
+		return ret;
+
+	solo_dev->snd_pcm = pcm;
+
+	return 0;
+}
+
+int solo_g723_init(struct solo_dev *solo_dev)
+{
+	static struct snd_device_ops ops = { NULL };
+	struct snd_card *card;
+	struct snd_kcontrol_new kctl;
+	char name[32];
+	int ret;
+
+	atomic_set(&solo_dev->snd_users, 0);
+
+	/* Allows for easier mapping between video and audio */
+	sprintf(name, "Softlogic%d", solo_dev->vfd->num);
+
+	ret = snd_card_new(&solo_dev->pdev->dev,
+			   SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
+			   &solo_dev->snd_card);
+	if (ret < 0)
+		return ret;
+
+	card = solo_dev->snd_card;
+
+	strcpy(card->driver, SOLO6X10_NAME);
+	strcpy(card->shortname, "SOLO-6x10 Audio");
+	sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
+		pci_name(solo_dev->pdev), solo_dev->pdev->irq);
+
+	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
+	if (ret < 0)
+		goto snd_error;
+
+	/* Mixer controls */
+	strcpy(card->mixername, "SOLO-6x10");
+	kctl = snd_solo_capture_volume;
+	kctl.count = solo_dev->nr_chans;
+
+	ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
+	if (ret < 0)
+		return ret;
+
+	ret = solo_snd_pcm_init(solo_dev);
+	if (ret < 0)
+		goto snd_error;
+
+	ret = snd_card_register(card);
+	if (ret < 0)
+		goto snd_error;
+
+	solo_g723_config(solo_dev);
+
+	dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name);
+
+	return 0;
+
+snd_error:
+	snd_card_free(card);
+	return ret;
+}
+
+void solo_g723_exit(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->snd_card)
+		return;
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
+	solo_irq_off(solo_dev, SOLO_IRQ_G723);
+
+	snd_card_free(solo_dev->snd_card);
+	solo_dev->snd_card = NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-gpio.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-gpio.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+
+#include "solo6x10.h"
+
+static void solo_gpio_mode(struct solo_dev *solo_dev,
+			   unsigned int port_mask, unsigned int mode)
+{
+	int port;
+	unsigned int ret;
+
+	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
+
+	/* To set gpio */
+	for (port = 0; port < 16; port++) {
+		if (!((1 << port) & port_mask))
+			continue;
+
+		ret &= (~(3 << (port << 1)));
+		ret |= ((mode & 3) << (port << 1));
+	}
+
+	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
+
+	/* To set extended gpio - sensor */
+	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
+
+	for (port = 0; port < 16; port++) {
+		if (!((1 << (port + 16)) & port_mask))
+			continue;
+
+		if (!mode)
+			ret &= ~(1 << port);
+		else
+			ret |= 1 << port;
+	}
+
+	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
+}
+
+static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
+{
+	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
+		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
+}
+
+static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
+{
+	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
+		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
+}
+
+static void solo_gpio_config(struct solo_dev *solo_dev)
+{
+	/* Video reset */
+	solo_gpio_mode(solo_dev, 0x30, 1);
+	solo_gpio_clear(solo_dev, 0x30);
+	udelay(100);
+	solo_gpio_set(solo_dev, 0x30);
+	udelay(100);
+
+	/* Warning: Don't touch the next line unless you're sure of what
+	 * you're doing: first four gpio [0-3] are used for video. */
+	solo_gpio_mode(solo_dev, 0x0f, 2);
+
+	/* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */
+	solo_gpio_mode(solo_dev, 0xff00, 1);
+
+	/* Initially set relay status to 0 */
+	solo_gpio_clear(solo_dev, 0xff00);
+}
+
+int solo_gpio_init(struct solo_dev *solo_dev)
+{
+	solo_gpio_config(solo_dev);
+	return 0;
+}
+
+void solo_gpio_exit(struct solo_dev *solo_dev)
+{
+	solo_gpio_clear(solo_dev, 0x30);
+	solo_gpio_config(solo_dev);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10.h linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10.h
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOLO6X10_H
+#define __SOLO6X10_H
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/stringify.h>
+#include <linux/io.h>
+#include <linux/atomic.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+
+#include "solo6x10-regs.h"
+
+#ifndef PCI_VENDOR_ID_SOFTLOGIC
+#define PCI_VENDOR_ID_SOFTLOGIC		0x9413
+#define PCI_DEVICE_ID_SOLO6010		0x6010
+#define PCI_DEVICE_ID_SOLO6110		0x6110
+#endif
+
+#ifndef PCI_VENDOR_ID_BLUECHERRY
+#define PCI_VENDOR_ID_BLUECHERRY	0x1BB3
+/* Neugent Softlogic 6010 based cards */
+#define PCI_DEVICE_ID_NEUSOLO_4		0x4304
+#define PCI_DEVICE_ID_NEUSOLO_9		0x4309
+#define PCI_DEVICE_ID_NEUSOLO_16	0x4310
+/* Bluecherry Softlogic 6010 based cards */
+#define PCI_DEVICE_ID_BC_SOLO_4		0x4E04
+#define PCI_DEVICE_ID_BC_SOLO_9		0x4E09
+#define PCI_DEVICE_ID_BC_SOLO_16	0x4E10
+/* Bluecherry Softlogic 6110 based cards */
+#define PCI_DEVICE_ID_BC_6110_4		0x5304
+#define PCI_DEVICE_ID_BC_6110_8		0x5308
+#define PCI_DEVICE_ID_BC_6110_16	0x5310
+#endif /* Bluecherry */
+
+/* Used in pci_device_id, and solo_dev->type */
+#define SOLO_DEV_6010			0
+#define SOLO_DEV_6110			1
+
+#define SOLO6X10_NAME			"solo6x10"
+
+#define SOLO_MAX_CHANNELS		16
+
+#define SOLO6X10_VERSION		"3.0.0"
+
+/*
+ * The SOLO6x10 actually has 8 i2c channels, but we only use 2.
+ * 0 - Techwell chip(s)
+ * 1 - SAA7128
+ */
+#define SOLO_I2C_ADAPTERS		2
+#define SOLO_I2C_TW			0
+#define SOLO_I2C_SAA			1
+
+/* DMA Engine setup */
+#define SOLO_NR_P2M			4
+#define SOLO_NR_P2M_DESC		256
+#define SOLO_P2M_DESC_SIZE		(SOLO_NR_P2M_DESC * 16)
+
+/* Encoder standard modes */
+#define SOLO_ENC_MODE_CIF		2
+#define SOLO_ENC_MODE_HD1		1
+#define SOLO_ENC_MODE_D1		9
+
+#define SOLO_DEFAULT_QP			3
+
+#define SOLO_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
+#define V4L2_CID_MOTION_TRACE		(SOLO_CID_CUSTOM_BASE+2)
+#define V4L2_CID_OSD_TEXT		(SOLO_CID_CUSTOM_BASE+3)
+
+/*
+ * Motion thresholds are in a table of 64x64 samples, with
+ * each sample representing 16x16 pixels of the source. In
+ * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
+ * The 5th sample on the 10th row is (10*64)+5 = 645.
+ *
+ * Internally it is stored as a 45x45 array (45*16 = 720, which is the
+ * maximum PAL/NTSC width).
+ */
+#define SOLO_MOTION_SZ (45)
+
+enum SOLO_I2C_STATE {
+	IIC_STATE_IDLE,
+	IIC_STATE_START,
+	IIC_STATE_READ,
+	IIC_STATE_WRITE,
+	IIC_STATE_STOP
+};
+
+/* Defined in Table 4-16, Page 68-69 of the 6010 Datasheet */
+struct solo_p2m_desc {
+	u32	ctrl;
+	u32	cfg;
+	u32	dma_addr;
+	u32	ext_addr;
+};
+
+struct solo_p2m_dev {
+	struct mutex		mutex;
+	struct completion	completion;
+	int			desc_count;
+	int			desc_idx;
+	struct solo_p2m_desc	*descs;
+	int			error;
+};
+
+#define OSD_TEXT_MAX		44
+
+struct solo_vb2_buf {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
+enum solo_enc_types {
+	SOLO_ENC_TYPE_STD,
+	SOLO_ENC_TYPE_EXT,
+};
+
+struct solo_enc_dev {
+	struct solo_dev	*solo_dev;
+	/* V4L2 Items */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *md_thresholds;
+	struct video_device	*vfd;
+	/* General accounting */
+	struct mutex		lock;
+	spinlock_t		motion_lock;
+	u8			ch;
+	u8			mode, gop, qp, interlaced, interval;
+	u8			bw_weight;
+	u16			motion_thresh;
+	bool			motion_global;
+	bool			motion_enabled;
+	bool			motion_last_state;
+	u8			frames_since_last_motion;
+	u16			width;
+	u16			height;
+
+	/* OSD buffers */
+	char			osd_text[OSD_TEXT_MAX + 1];
+	u8			osd_buf[SOLO_EOSD_EXT_SIZE_MAX]
+					__aligned(4);
+
+	/* VOP stuff */
+	unsigned char		vop[64];
+	int			vop_len;
+	unsigned char		jpeg_header[1024];
+	int			jpeg_len;
+
+	u32			fmt;
+	enum solo_enc_types	type;
+	u32			sequence;
+	struct vb2_queue	vidq;
+	struct list_head	vidq_active;
+	int			desc_count;
+	int			desc_nelts;
+	struct solo_p2m_desc	*desc_items;
+	dma_addr_t		desc_dma;
+	spinlock_t		av_lock;
+};
+
+/* The SOLO6x10 PCI Device */
+struct solo_dev {
+	/* General stuff */
+	struct pci_dev		*pdev;
+	int			type;
+	unsigned int		time_sync;
+	unsigned int		usec_lsb;
+	unsigned int		clock_mhz;
+	u8 __iomem		*reg_base;
+	int			nr_chans;
+	int			nr_ext;
+	u32			irq_mask;
+	u32			motion_mask;
+	spinlock_t		reg_io_lock;
+	struct v4l2_device	v4l2_dev;
+
+	/* tw28xx accounting */
+	u8			tw2865, tw2864, tw2815;
+	u8			tw28_cnt;
+
+	/* i2c related items */
+	struct i2c_adapter	i2c_adap[SOLO_I2C_ADAPTERS];
+	enum SOLO_I2C_STATE	i2c_state;
+	struct mutex		i2c_mutex;
+	int			i2c_id;
+	wait_queue_head_t	i2c_wait;
+	struct i2c_msg		*i2c_msg;
+	unsigned int		i2c_msg_num;
+	unsigned int		i2c_msg_ptr;
+
+	/* P2M DMA Engine */
+	struct solo_p2m_dev	p2m_dev[SOLO_NR_P2M];
+	atomic_t		p2m_count;
+	int			p2m_jiffies;
+	unsigned int		p2m_timeouts;
+
+	/* V4L2 Display items */
+	struct video_device	*vfd;
+	unsigned int		erasing;
+	unsigned int		frame_blank;
+	u8			cur_disp_ch;
+	wait_queue_head_t	disp_thread_wait;
+	struct v4l2_ctrl_handler disp_hdl;
+
+	/* V4L2 Encoder items */
+	struct solo_enc_dev	*v4l2_enc[SOLO_MAX_CHANNELS];
+	u16			enc_bw_remain;
+	/* IDX into hw mp4 encoder */
+	u8			enc_idx;
+
+	/* Current video settings */
+	u32			video_type;
+	u16			video_hsize, video_vsize;
+	u16			vout_hstart, vout_vstart;
+	u16			vin_hstart, vin_vstart;
+	u8			fps;
+
+	/* JPEG Qp setting */
+	spinlock_t      jpeg_qp_lock;
+	u32		jpeg_qp[2];
+
+	/* Audio components */
+	struct snd_card		*snd_card;
+	struct snd_pcm		*snd_pcm;
+	atomic_t		snd_users;
+	int			g723_hw_idx;
+
+	/* sysfs stuffs */
+	struct device		dev;
+	int			sdram_size;
+	struct bin_attribute	sdram_attr;
+	unsigned int		sys_config;
+
+	/* Ring thread */
+	struct task_struct	*ring_thread;
+	wait_queue_head_t	ring_thread_wait;
+
+	/* VOP_HEADER handling */
+	void                    *vh_buf;
+	dma_addr_t		vh_dma;
+	int			vh_size;
+
+	/* Buffer handling */
+	struct vb2_queue	vidq;
+	struct vb2_alloc_ctx	*alloc_ctx;
+	u32			sequence;
+	struct task_struct      *kthread;
+	struct mutex		lock;
+	spinlock_t		slock;
+	int			old_write;
+	struct list_head	vidq_active;
+};
+
+static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
+{
+	unsigned long flags;
+	u32 ret;
+	u16 val;
+
+	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
+
+	ret = readl(solo_dev->reg_base + reg);
+	rmb();
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
+	rmb();
+
+	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
+
+	return ret;
+}
+
+static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
+				  u32 data)
+{
+	unsigned long flags;
+	u16 val;
+
+	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
+
+	writel(data, solo_dev->reg_base + reg);
+	wmb();
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
+	rmb();
+
+	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
+}
+
+static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
+{
+	dev->irq_mask |= mask;
+	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
+}
+
+static inline void solo_irq_off(struct solo_dev *dev, u32 mask)
+{
+	dev->irq_mask &= ~mask;
+	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
+}
+
+/* Init/exit routines for subsystems */
+int solo_disp_init(struct solo_dev *solo_dev);
+void solo_disp_exit(struct solo_dev *solo_dev);
+
+int solo_gpio_init(struct solo_dev *solo_dev);
+void solo_gpio_exit(struct solo_dev *solo_dev);
+
+int solo_i2c_init(struct solo_dev *solo_dev);
+void solo_i2c_exit(struct solo_dev *solo_dev);
+
+int solo_p2m_init(struct solo_dev *solo_dev);
+void solo_p2m_exit(struct solo_dev *solo_dev);
+
+int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
+void solo_v4l2_exit(struct solo_dev *solo_dev);
+
+int solo_enc_init(struct solo_dev *solo_dev);
+void solo_enc_exit(struct solo_dev *solo_dev);
+
+int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
+void solo_enc_v4l2_exit(struct solo_dev *solo_dev);
+
+int solo_g723_init(struct solo_dev *solo_dev);
+void solo_g723_exit(struct solo_dev *solo_dev);
+
+/* ISR's */
+int solo_i2c_isr(struct solo_dev *solo_dev);
+void solo_p2m_isr(struct solo_dev *solo_dev, int id);
+void solo_p2m_error_isr(struct solo_dev *solo_dev);
+void solo_enc_v4l2_isr(struct solo_dev *solo_dev);
+void solo_g723_isr(struct solo_dev *solo_dev);
+void solo_motion_isr(struct solo_dev *solo_dev);
+void solo_video_in_isr(struct solo_dev *solo_dev);
+
+/* i2c read/write */
+u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off);
+void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off,
+			u8 data);
+
+/* P2M DMA */
+int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
+		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
+		   int repeat, u32 ext_size);
+int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
+		 void *sys_addr, u32 ext_addr, u32 size,
+		 int repeat, u32 ext_size);
+void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
+			dma_addr_t dma_addr, u32 ext_addr, u32 size,
+			int repeat, u32 ext_size);
+int solo_p2m_dma_desc(struct solo_dev *solo_dev,
+		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
+		      int desc_cnt);
+
+/* Global s_std ioctl */
+int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz);
+void solo_update_mode(struct solo_enc_dev *solo_enc);
+
+/* Set the threshold for motion detection */
+int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
+int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
+		const u16 *thresholds);
+#define SOLO_DEF_MOT_THRESH		0x0300
+
+/* Write text on OSD */
+int solo_osd_print(struct solo_enc_dev *solo_enc);
+
+/* EEPROM commands */
+unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en);
+unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc);
+int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
+		      unsigned short data);
+
+/* JPEG Qp functions */
+void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
+		    unsigned int qp);
+int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch);
+
+#define CHK_FLAGS(v, flags) (((v) & (flags)) == (flags))
+
+#endif /* __SOLO6X10_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-i2c.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
+ * channel. The bus can only handle one i2c event at a time. The below handles
+ * this all wrong. We should be using the status registers to see if the bus
+ * is in use, and have a global lock to check the status register. Also,
+ * the bulk of the work should be handled out-of-interrupt. The ugly loops
+ * that occur during interrupt scare me. The ISR should merely signal
+ * thread context, ACK the interrupt, and move on. -- BenC */
+
+#include <linux/kernel.h>
+
+#include "solo6x10.h"
+
+u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
+{
+	struct i2c_msg msgs[2];
+	u8 data;
+
+	msgs[0].flags = 0;
+	msgs[0].addr = addr;
+	msgs[0].len = 1;
+	msgs[0].buf = &off;
+
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].addr = addr;
+	msgs[1].len = 1;
+	msgs[1].buf = &data;
+
+	i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);
+
+	return data;
+}
+
+void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr,
+			u8 off, u8 data)
+{
+	struct i2c_msg msgs;
+	u8 buf[2];
+
+	buf[0] = off;
+	buf[1] = data;
+	msgs.flags = 0;
+	msgs.addr = addr;
+	msgs.len = 2;
+	msgs.buf = buf;
+
+	i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1);
+}
+
+static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
+{
+	u32 ctrl;
+
+	ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);
+
+	if (solo_dev->i2c_state == IIC_STATE_START)
+		ctrl |= SOLO_IIC_START;
+
+	if (wr) {
+		ctrl |= SOLO_IIC_WRITE;
+	} else {
+		ctrl |= SOLO_IIC_READ;
+		if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
+			ctrl |= SOLO_IIC_ACK_EN;
+	}
+
+	if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
+		ctrl |= SOLO_IIC_STOP;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
+}
+
+static void solo_i2c_start(struct solo_dev *solo_dev)
+{
+	u32 addr = solo_dev->i2c_msg->addr << 1;
+
+	if (solo_dev->i2c_msg->flags & I2C_M_RD)
+		addr |= 1;
+
+	solo_dev->i2c_state = IIC_STATE_START;
+	solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
+	solo_i2c_flush(solo_dev, 1);
+}
+
+static void solo_i2c_stop(struct solo_dev *solo_dev)
+{
+	solo_irq_off(solo_dev, SOLO_IRQ_IIC);
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
+	solo_dev->i2c_state = IIC_STATE_STOP;
+	wake_up(&solo_dev->i2c_wait);
+}
+
+static int solo_i2c_handle_read(struct solo_dev *solo_dev)
+{
+prepare_read:
+	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
+		solo_i2c_flush(solo_dev, 0);
+		return 0;
+	}
+
+	solo_dev->i2c_msg_ptr = 0;
+	solo_dev->i2c_msg++;
+	solo_dev->i2c_msg_num--;
+
+	if (solo_dev->i2c_msg_num == 0) {
+		solo_i2c_stop(solo_dev);
+		return 0;
+	}
+
+	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
+		solo_i2c_start(solo_dev);
+	} else {
+		if (solo_dev->i2c_msg->flags & I2C_M_RD)
+			goto prepare_read;
+		else
+			solo_i2c_stop(solo_dev);
+	}
+
+	return 0;
+}
+
+static int solo_i2c_handle_write(struct solo_dev *solo_dev)
+{
+retry_write:
+	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
+		solo_reg_write(solo_dev, SOLO_IIC_TXD,
+			       solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
+		solo_dev->i2c_msg_ptr++;
+		solo_i2c_flush(solo_dev, 1);
+		return 0;
+	}
+
+	solo_dev->i2c_msg_ptr = 0;
+	solo_dev->i2c_msg++;
+	solo_dev->i2c_msg_num--;
+
+	if (solo_dev->i2c_msg_num == 0) {
+		solo_i2c_stop(solo_dev);
+		return 0;
+	}
+
+	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
+		solo_i2c_start(solo_dev);
+	} else {
+		if (solo_dev->i2c_msg->flags & I2C_M_RD)
+			solo_i2c_stop(solo_dev);
+		else
+			goto retry_write;
+	}
+
+	return 0;
+}
+
+int solo_i2c_isr(struct solo_dev *solo_dev)
+{
+	u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
+	int ret = -EINVAL;
+
+
+	if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR)
+	    || solo_dev->i2c_id < 0) {
+		solo_i2c_stop(solo_dev);
+		return -ENXIO;
+	}
+
+	switch (solo_dev->i2c_state) {
+	case IIC_STATE_START:
+		if (solo_dev->i2c_msg->flags & I2C_M_RD) {
+			solo_dev->i2c_state = IIC_STATE_READ;
+			ret = solo_i2c_handle_read(solo_dev);
+			break;
+		}
+
+		solo_dev->i2c_state = IIC_STATE_WRITE;
+	case IIC_STATE_WRITE:
+		ret = solo_i2c_handle_write(solo_dev);
+		break;
+
+	case IIC_STATE_READ:
+		solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] =
+			solo_reg_read(solo_dev, SOLO_IIC_RXD);
+		solo_dev->i2c_msg_ptr++;
+
+		ret = solo_i2c_handle_read(solo_dev);
+		break;
+
+	default:
+		solo_i2c_stop(solo_dev);
+	}
+
+	return ret;
+}
+
+static int solo_i2c_master_xfer(struct i2c_adapter *adap,
+				struct i2c_msg msgs[], int num)
+{
+	struct solo_dev *solo_dev = adap->algo_data;
+	unsigned long timeout;
+	int ret;
+	int i;
+	DEFINE_WAIT(wait);
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		if (&solo_dev->i2c_adap[i] == adap)
+			break;
+	}
+
+	if (i == SOLO_I2C_ADAPTERS)
+		return num; /* XXX Right return value for failure? */
+
+	mutex_lock(&solo_dev->i2c_mutex);
+	solo_dev->i2c_id = i;
+	solo_dev->i2c_msg = msgs;
+	solo_dev->i2c_msg_num = num;
+	solo_dev->i2c_msg_ptr = 0;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
+	solo_irq_on(solo_dev, SOLO_IRQ_IIC);
+	solo_i2c_start(solo_dev);
+
+	timeout = HZ / 2;
+
+	for (;;) {
+		prepare_to_wait(&solo_dev->i2c_wait, &wait,
+				TASK_INTERRUPTIBLE);
+
+		if (solo_dev->i2c_state == IIC_STATE_STOP)
+			break;
+
+		timeout = schedule_timeout(timeout);
+		if (!timeout)
+			break;
+
+		if (signal_pending(current))
+			break;
+	}
+
+	finish_wait(&solo_dev->i2c_wait, &wait);
+	ret = num - solo_dev->i2c_msg_num;
+	solo_dev->i2c_state = IIC_STATE_IDLE;
+	solo_dev->i2c_id = -1;
+
+	mutex_unlock(&solo_dev->i2c_mutex);
+
+	return ret;
+}
+
+static u32 solo_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm solo_i2c_algo = {
+	.master_xfer	= solo_i2c_master_xfer,
+	.functionality	= solo_i2c_functionality,
+};
+
+int solo_i2c_init(struct solo_dev *solo_dev)
+{
+	int i;
+	int ret;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CFG,
+		       SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);
+
+	solo_dev->i2c_id = -1;
+	solo_dev->i2c_state = IIC_STATE_IDLE;
+	init_waitqueue_head(&solo_dev->i2c_wait);
+	mutex_init(&solo_dev->i2c_mutex);
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
+
+		snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
+			 SOLO6X10_NAME, i);
+		adap->algo = &solo_i2c_algo;
+		adap->algo_data = solo_dev;
+		adap->retries = 1;
+		adap->dev.parent = &solo_dev->pdev->dev;
+
+		ret = i2c_add_adapter(adap);
+		if (ret) {
+			adap->algo_data = NULL;
+			break;
+		}
+	}
+
+	if (ret) {
+		for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+			if (!solo_dev->i2c_adap[i].algo_data)
+				break;
+			i2c_del_adapter(&solo_dev->i2c_adap[i]);
+			solo_dev->i2c_adap[i].algo_data = NULL;
+		}
+		return ret;
+	}
+
+	return 0;
+}
+
+void solo_i2c_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		if (!solo_dev->i2c_adap[i].algo_data)
+			continue;
+		i2c_del_adapter(&solo_dev->i2c_adap[i]);
+		solo_dev->i2c_adap[i].algo_data = NULL;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-jpeg.h linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-jpeg.h
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-jpeg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-jpeg.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOLO6X10_JPEG_H
+#define __SOLO6X10_JPEG_H
+
+static const unsigned char jpeg_header[] = {
+	0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
+	0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
+	0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
+	0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c,
+	0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30,
+	0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50,
+	0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e,
+	0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a,
+	0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4,
+	0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0,
+	0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb,
+	0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a,
+	0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70,
+	0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00,
+	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
+	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+	0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
+	0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
+	0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
+	0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
+	0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+	0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
+	0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
+	0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
+	0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
+	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+	0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
+	0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
+	0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
+	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
+	0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+	0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+	0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+	0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
+	0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
+	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
+	0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
+	0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
+	0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
+	0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
+	0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
+	0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
+	0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
+	0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
+	0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
+	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
+	0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
+	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
+	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
+	0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
+	0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+	0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+	0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+	0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
+	0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
+	0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
+	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
+	0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
+	0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
+	0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
+	0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+};
+
+/* This is the byte marker for the start of SOF0: 0xffc0 marker */
+#define SOF0_START	575
+
+/* This is the byte marker for the start of the DQT */
+#define DQT_START	17
+#define DQT_LEN		138
+static const unsigned char jpeg_dqt[4][DQT_LEN] = {
+	{
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
+		0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
+		0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
+		0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
+		0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
+		0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
+		0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
+		0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
+		0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+		0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+		0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+		0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+		0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+		0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+		0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+		0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+		0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c,
+		0x1a, 0x1c, 0x24, 0x22, 0x20, 0x26, 0x30, 0x50,
+		0x34, 0x30, 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a,
+		0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66,
+		0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88,
+		0xae, 0x8a, 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae,
+		0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2,
+		0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+		0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x30, 0x21, 0x24, 0x2a, 0x24, 0x1e, 0x30, 0x2a,
+		0x27, 0x2a, 0x36, 0x33, 0x30, 0x39, 0x48, 0x78,
+		0x4e, 0x48, 0x42, 0x42, 0x48, 0x93, 0x69, 0x6f,
+		0x57, 0x78, 0xae, 0x99, 0xb7, 0xb4, 0xab, 0x99,
+		0xa8, 0xa5, 0xc0, 0xd8, 0xff, 0xea, 0xc0, 0xcc,
+		0xff, 0xcf, 0xa5, 0xa8, 0xf0, 0xff, 0xf3, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xe7, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x33, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+		0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	}
+};
+
+#endif /* __SOLO6X10_JPEG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-offsets.h linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-offsets.h
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-offsets.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-offsets.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOLO6X10_OFFSETS_H
+#define __SOLO6X10_OFFSETS_H
+
+#define SOLO_DISP_EXT_ADDR			0x00000000
+#define SOLO_DISP_EXT_SIZE			0x00480000
+
+#define SOLO_EOSD_EXT_ADDR \
+	(SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE)
+#define SOLO_EOSD_EXT_SIZE(__solo) \
+	(__solo->type == SOLO_DEV_6010 ? 0x10000 : 0x20000)
+#define SOLO_EOSD_EXT_SIZE_MAX			0x20000
+#define SOLO_EOSD_EXT_AREA(__solo) \
+	(SOLO_EOSD_EXT_SIZE(__solo) * 32)
+#define SOLO_EOSD_EXT_ADDR_CHAN(__solo, ch) \
+	(SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_SIZE(__solo) * (ch))
+
+#define SOLO_MOTION_EXT_ADDR(__solo) \
+	(SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_AREA(__solo))
+#define SOLO_MOTION_EXT_SIZE			0x00080000
+
+#define SOLO_G723_EXT_ADDR(__solo) \
+	(SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE)
+#define SOLO_G723_EXT_SIZE			0x00010000
+
+#define SOLO_CAP_EXT_ADDR(__solo) \
+	(SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE)
+
+/* 18 is the maximum number of pages required for PAL@D1, the largest frame
+ * possible */
+#define SOLO_CAP_PAGE_SIZE			(18 << 16)
+
+/* Always allow the encoder enough for 16 channels, even if we have less. The
+ * exception is if we have card with only 32Megs of memory. */
+#define SOLO_CAP_EXT_SIZE(__solo) \
+	((((__solo->sdram_size <= (32 << 20)) ? 4 : 16) + 1)	\
+	 * SOLO_CAP_PAGE_SIZE)
+
+#define SOLO_EREF_EXT_ADDR(__solo) \
+	(SOLO_CAP_EXT_ADDR(__solo) + SOLO_CAP_EXT_SIZE(__solo))
+#define SOLO_EREF_EXT_SIZE			0x00140000
+#define SOLO_EREF_EXT_AREA(__solo) \
+	(SOLO_EREF_EXT_SIZE * __solo->nr_chans * 2)
+
+#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
+
+#define SOLO_MP4E_EXT_ADDR(__solo) \
+	(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
+#define SOLO_MP4E_EXT_SIZE(__solo) \
+	max((__solo->nr_chans * 0x00080000),				\
+	    min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) -	\
+		 __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
+
+#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
+#define SOLO_JPEG_EXT_ADDR(__solo) \
+		(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
+#define SOLO_JPEG_EXT_SIZE(__solo) \
+	max(__SOLO_JPEG_MIN_SIZE(__solo),				\
+	    min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
+
+#define SOLO_SDRAM_END(__solo) \
+	(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
+
+#endif /* __SOLO6X10_OFFSETS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-p2m.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-p2m.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-p2m.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-p2m.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "solo6x10.h"
+
+static int multi_p2m;
+module_param(multi_p2m, uint, 0644);
+MODULE_PARM_DESC(multi_p2m,
+		 "Use multiple P2M DMA channels (default: no, 6010-only)");
+
+static int desc_mode;
+module_param(desc_mode, uint, 0644);
+MODULE_PARM_DESC(desc_mode,
+		 "Allow use of descriptor mode DMA (default: no, 6010-only)");
+
+int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
+		 void *sys_addr, u32 ext_addr, u32 size,
+		 int repeat, u32 ext_size)
+{
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03))
+		return -EINVAL;
+	if (WARN_ON_ONCE(!size))
+		return -EINVAL;
+
+	dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
+				  wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+	if (pci_dma_mapping_error(solo_dev->pdev, dma_addr))
+		return -ENOMEM;
+
+	ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size,
+			     repeat, ext_size);
+
+	pci_unmap_single(solo_dev->pdev, dma_addr, size,
+			 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+
+	return ret;
+}
+
+/* Mutex must be held for p2m_id before calling this!! */
+int solo_p2m_dma_desc(struct solo_dev *solo_dev,
+		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
+		      int desc_cnt)
+{
+	struct solo_p2m_dev *p2m_dev;
+	unsigned int timeout;
+	unsigned int config = 0;
+	int ret = 0;
+	int p2m_id = 0;
+
+	/* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
+	if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) {
+		p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
+		if (p2m_id < 0)
+			p2m_id = -p2m_id;
+	}
+
+	p2m_dev = &solo_dev->p2m_dev[p2m_id];
+
+	if (mutex_lock_interruptible(&p2m_dev->mutex))
+		return -EINTR;
+
+	reinit_completion(&p2m_dev->completion);
+	p2m_dev->error = 0;
+
+	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) {
+		/* For 6010 with more than one desc, we can do a one-shot */
+		p2m_dev->desc_count = p2m_dev->desc_idx = 0;
+		config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));
+
+		solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
+		solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
+			       SOLO_P2M_DESC_MODE);
+	} else {
+		/* For single descriptors and 6110, we need to run each desc */
+		p2m_dev->desc_count = desc_cnt;
+		p2m_dev->desc_idx = 1;
+		p2m_dev->descs = desc;
+
+		solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id),
+			       desc[1].dma_addr);
+		solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id),
+			       desc[1].ext_addr);
+		solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id),
+			       desc[1].cfg);
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id),
+			       desc[1].ctrl);
+	}
+
+	timeout = wait_for_completion_timeout(&p2m_dev->completion,
+					      solo_dev->p2m_jiffies);
+
+	if (WARN_ON_ONCE(p2m_dev->error))
+		ret = -EIO;
+	else if (timeout == 0) {
+		solo_dev->p2m_timeouts++;
+		ret = -EAGAIN;
+	}
+
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);
+
+	/* Don't write here for the no_desc_mode case, because config is 0.
+	 * We can't test no_desc_mode again, it might race. */
+	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config)
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);
+
+	mutex_unlock(&p2m_dev->mutex);
+
+	return ret;
+}
+
+void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
+			dma_addr_t dma_addr, u32 ext_addr, u32 size,
+			int repeat, u32 ext_size)
+{
+	WARN_ON_ONCE(dma_addr & 0x03);
+	WARN_ON_ONCE(!size);
+
+	desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2);
+	desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
+		(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;
+
+	if (repeat) {
+		desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2);
+		desc->ctrl |=  SOLO_P2M_PCI_INC(size >> 2) |
+			 SOLO_P2M_REPEAT(repeat);
+	}
+
+	desc->dma_addr = dma_addr;
+	desc->ext_addr = ext_addr;
+}
+
+int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
+		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
+		   int repeat, u32 ext_size)
+{
+	struct solo_p2m_desc desc[2];
+
+	solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat,
+			   ext_size);
+
+	/* No need for desc_dma since we know it is a single-shot */
+	return solo_p2m_dma_desc(solo_dev, desc, 0, 1);
+}
+
+void solo_p2m_isr(struct solo_dev *solo_dev, int id)
+{
+	struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
+	struct solo_p2m_desc *desc;
+
+	if (p2m_dev->desc_count <= p2m_dev->desc_idx) {
+		complete(&p2m_dev->completion);
+		return;
+	}
+
+	/* Setup next descriptor */
+	p2m_dev->desc_idx++;
+	desc = &p2m_dev->descs[p2m_dev->desc_idx];
+
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
+	solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr);
+	solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr);
+	solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg);
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl);
+}
+
+void solo_p2m_error_isr(struct solo_dev *solo_dev)
+{
+	unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
+	struct solo_p2m_dev *p2m_dev;
+	int i;
+
+	if (!(err & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC)))
+		return;
+
+	for (i = 0; i < SOLO_NR_P2M; i++) {
+		p2m_dev = &solo_dev->p2m_dev[i];
+		p2m_dev->error = 1;
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
+		complete(&p2m_dev->completion);
+	}
+}
+
+void solo_p2m_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < SOLO_NR_P2M; i++)
+		solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
+}
+
+static int solo_p2m_test(struct solo_dev *solo_dev, int base, int size)
+{
+	u32 *wr_buf;
+	u32 *rd_buf;
+	int i;
+	int ret = -EIO;
+	int order = get_order(size);
+
+	wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
+	if (wr_buf == NULL)
+		return -1;
+
+	rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
+	if (rd_buf == NULL) {
+		free_pages((unsigned long)wr_buf, order);
+		return -1;
+	}
+
+	for (i = 0; i < (size >> 3); i++)
+		*(wr_buf + i) = (i << 16) | (i + 1);
+
+	for (i = (size >> 3); i < (size >> 2); i++)
+		*(wr_buf + i) = ~((i << 16) | (i + 1));
+
+	memset(rd_buf, 0x55, size);
+
+	if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0))
+		goto test_fail;
+
+	if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0))
+		goto test_fail;
+
+	for (i = 0; i < (size >> 2); i++) {
+		if (*(wr_buf + i) != *(rd_buf + i))
+			goto test_fail;
+	}
+
+	ret = 0;
+
+test_fail:
+	free_pages((unsigned long)wr_buf, order);
+	free_pages((unsigned long)rd_buf, order);
+
+	return ret;
+}
+
+int solo_p2m_init(struct solo_dev *solo_dev)
+{
+	struct solo_p2m_dev *p2m_dev;
+	int i;
+
+	for (i = 0; i < SOLO_NR_P2M; i++) {
+		p2m_dev = &solo_dev->p2m_dev[i];
+
+		mutex_init(&p2m_dev->mutex);
+		init_completion(&p2m_dev->completion);
+
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
+			       SOLO_P2M_CSC_16BIT_565 |
+			       SOLO_P2M_DESC_INTR_OPT |
+			       SOLO_P2M_DMA_INTERVAL(0) |
+			       SOLO_P2M_PCI_MASTER_MODE);
+		solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
+	}
+
+	/* Find correct SDRAM size */
+	for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) {
+		solo_reg_write(solo_dev, SOLO_DMA_CTRL,
+			       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
+			       SOLO_DMA_CTRL_SDRAM_SIZE(i) |
+			       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
+			       SOLO_DMA_CTRL_READ_CLK_SELECT |
+			       SOLO_DMA_CTRL_LATENCY(1));
+
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config |
+			       SOLO_SYS_CFG_RESET);
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+
+		switch (i) {
+		case 2:
+			if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) ||
+			    solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000))
+				continue;
+			break;
+
+		case 1:
+			if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000))
+				continue;
+			break;
+
+		default:
+			if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000))
+				continue;
+		}
+
+		solo_dev->sdram_size = (32 << 20) << i;
+		break;
+	}
+
+	if (!solo_dev->sdram_size) {
+		dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n");
+		return -EIO;
+	}
+
+	if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) {
+		dev_err(&solo_dev->pdev->dev,
+			"SDRAM is not large enough (%u < %u)\n",
+			solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev));
+		return -EIO;
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-regs.h linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-regs.h
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,635 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOLO6X10_REGISTERS_H
+#define __SOLO6X10_REGISTERS_H
+
+#include "solo6x10-offsets.h"
+
+/* Global 6010 system configuration */
+#define SOLO_SYS_CFG				0x0000
+#define   SOLO_SYS_CFG_FOUT_EN			0x00000001
+#define   SOLO_SYS_CFG_PLL_BYPASS		0x00000002
+#define   SOLO_SYS_CFG_PLL_PWDN			0x00000004
+#define   SOLO_SYS_CFG_OUTDIV(__n)		(((__n) & 0x003) << 3)
+#define   SOLO_SYS_CFG_FEEDBACKDIV(__n)		(((__n) & 0x1ff) << 5)
+#define   SOLO_SYS_CFG_INPUTDIV(__n)		(((__n) & 0x01f) << 14)
+#define   SOLO_SYS_CFG_CLOCK_DIV		0x00080000
+#define   SOLO_SYS_CFG_NCLK_DELAY(__n)		(((__n) & 0x003) << 24)
+#define   SOLO_SYS_CFG_PCLK_DELAY(__n)		(((__n) & 0x00f) << 26)
+#define   SOLO_SYS_CFG_SDRAM64BIT		0x40000000
+#define   SOLO_SYS_CFG_RESET			0x80000000
+
+#define	SOLO_DMA_CTRL				0x0004
+#define	  SOLO_DMA_CTRL_REFRESH_CYCLE(n)	((n)<<8)
+/* 0=16/32MB, 1=32/64MB, 2=64/128MB, 3=128/256MB */
+#define	  SOLO_DMA_CTRL_SDRAM_SIZE(n)		((n)<<6)
+#define	  SOLO_DMA_CTRL_SDRAM_CLK_INVERT	(1<<5)
+#define	  SOLO_DMA_CTRL_STROBE_SELECT		(1<<4)
+#define	  SOLO_DMA_CTRL_READ_DATA_SELECT	(1<<3)
+#define	  SOLO_DMA_CTRL_READ_CLK_SELECT		(1<<2)
+#define	  SOLO_DMA_CTRL_LATENCY(n)		((n)<<0)
+
+/* Some things we set in this are undocumented. Why Softlogic?!?! */
+#define SOLO_DMA_CTRL1				0x0008
+
+#define SOLO_SYS_VCLK				0x000C
+#define	  SOLO_VCLK_INVERT			(1<<22)
+/* 0=sys_clk/4, 1=sys_clk/2, 2=clk_in/2 of system input */
+#define	  SOLO_VCLK_SELECT(n)			((n)<<20)
+#define	  SOLO_VCLK_VIN1415_DELAY(n)		((n)<<14)
+#define	  SOLO_VCLK_VIN1213_DELAY(n)		((n)<<12)
+#define	  SOLO_VCLK_VIN1011_DELAY(n)		((n)<<10)
+#define	  SOLO_VCLK_VIN0809_DELAY(n)		((n)<<8)
+#define	  SOLO_VCLK_VIN0607_DELAY(n)		((n)<<6)
+#define	  SOLO_VCLK_VIN0405_DELAY(n)		((n)<<4)
+#define	  SOLO_VCLK_VIN0203_DELAY(n)		((n)<<2)
+#define	  SOLO_VCLK_VIN0001_DELAY(n)		((n)<<0)
+
+#define SOLO_IRQ_STAT				0x0010
+#define SOLO_IRQ_MASK				0x0014
+#define	  SOLO_IRQ_P2M(n)			(1<<((n)+17))
+#define	  SOLO_IRQ_GPIO				(1<<16)
+#define	  SOLO_IRQ_VIDEO_LOSS			(1<<15)
+#define	  SOLO_IRQ_VIDEO_IN			(1<<14)
+#define	  SOLO_IRQ_MOTION			(1<<13)
+#define	  SOLO_IRQ_ATA_CMD			(1<<12)
+#define	  SOLO_IRQ_ATA_DIR			(1<<11)
+#define	  SOLO_IRQ_PCI_ERR			(1<<10)
+#define	  SOLO_IRQ_PS2_1			(1<<9)
+#define	  SOLO_IRQ_PS2_0			(1<<8)
+#define	  SOLO_IRQ_SPI				(1<<7)
+#define	  SOLO_IRQ_IIC				(1<<6)
+#define	  SOLO_IRQ_UART(n)			(1<<((n) + 4))
+#define	  SOLO_IRQ_G723				(1<<3)
+#define	  SOLO_IRQ_DECODER			(1<<1)
+#define	  SOLO_IRQ_ENCODER			(1<<0)
+
+#define SOLO_CHIP_OPTION			0x001C
+#define   SOLO_CHIP_ID_MASK			0x00000007
+
+#define SOLO_PLL_CONFIG				0x0020 /* 6110 Only */
+
+#define SOLO_EEPROM_CTRL			0x0060
+#define	  SOLO_EEPROM_ACCESS_EN			(1<<7)
+#define	  SOLO_EEPROM_CS			(1<<3)
+#define	  SOLO_EEPROM_CLK			(1<<2)
+#define	  SOLO_EEPROM_DO			(1<<1)
+#define	  SOLO_EEPROM_DI			(1<<0)
+#define	  SOLO_EEPROM_ENABLE (SOLO_EEPROM_ACCESS_EN | SOLO_EEPROM_CS)
+
+#define SOLO_PCI_ERR				0x0070
+#define   SOLO_PCI_ERR_FATAL			0x00000001
+#define   SOLO_PCI_ERR_PARITY			0x00000002
+#define   SOLO_PCI_ERR_TARGET			0x00000004
+#define   SOLO_PCI_ERR_TIMEOUT			0x00000008
+#define   SOLO_PCI_ERR_P2M			0x00000010
+#define   SOLO_PCI_ERR_ATA			0x00000020
+#define   SOLO_PCI_ERR_P2M_DESC			0x00000040
+#define   SOLO_PCI_ERR_FSM0(__s)		(((__s) >> 16) & 0x0f)
+#define   SOLO_PCI_ERR_FSM1(__s)		(((__s) >> 20) & 0x0f)
+#define   SOLO_PCI_ERR_FSM2(__s)		(((__s) >> 24) & 0x1f)
+
+#define SOLO_P2M_BASE				0x0080
+
+#define SOLO_P2M_CONFIG(n)			(0x0080 + ((n)*0x20))
+#define	  SOLO_P2M_DMA_INTERVAL(n)		((n)<<6)/* N*32 clocks */
+#define	  SOLO_P2M_CSC_BYTE_REORDER		(1<<5)	/* BGR -> RGB */
+/* 0:r=[14:10] g=[9:5] b=[4:0], 1:r=[15:11] g=[10:5] b=[4:0] */
+#define	  SOLO_P2M_CSC_16BIT_565		(1<<4)
+#define	  SOLO_P2M_UV_SWAP			(1<<3)
+#define	  SOLO_P2M_PCI_MASTER_MODE		(1<<2)
+#define	  SOLO_P2M_DESC_INTR_OPT		(1<<1)	/* 1:Empty, 0:Each */
+#define	  SOLO_P2M_DESC_MODE			(1<<0)
+
+#define SOLO_P2M_DES_ADR(n)			(0x0084 + ((n)*0x20))
+
+#define SOLO_P2M_DESC_ID(n)			(0x0088 + ((n)*0x20))
+#define	  SOLO_P2M_UPDATE_ID(n)			((n)<<0)
+
+#define SOLO_P2M_STATUS(n)			(0x008C + ((n)*0x20))
+#define	  SOLO_P2M_COMMAND_DONE			(1<<8)
+#define	  SOLO_P2M_CURRENT_ID(stat)		(0xff & (stat))
+
+#define SOLO_P2M_CONTROL(n)			(0x0090 + ((n)*0x20))
+#define	  SOLO_P2M_PCI_INC(n)			((n)<<20)
+#define	  SOLO_P2M_REPEAT(n)			((n)<<10)
+/* 0:512, 1:256, 2:128, 3:64, 4:32, 5:128(2page) */
+#define	  SOLO_P2M_BURST_SIZE(n)		((n)<<7)
+#define	    SOLO_P2M_BURST_512			0
+#define	    SOLO_P2M_BURST_256			1
+#define	    SOLO_P2M_BURST_128			2
+#define	    SOLO_P2M_BURST_64			3
+#define	    SOLO_P2M_BURST_32			4
+#define	  SOLO_P2M_CSC_16BIT			(1<<6)	/* 0:24bit, 1:16bit */
+/* 0:Y[0]<-0(OFF), 1:Y[0]<-1(ON), 2:Y[0]<-G[0], 3:Y[0]<-Bit[15] */
+#define	  SOLO_P2M_ALPHA_MODE(n)		((n)<<4)
+#define	  SOLO_P2M_CSC_ON			(1<<3)
+#define	  SOLO_P2M_INTERRUPT_REQ		(1<<2)
+#define	  SOLO_P2M_WRITE			(1<<1)
+#define	  SOLO_P2M_TRANS_ON			(1<<0)
+
+#define SOLO_P2M_EXT_CFG(n)			(0x0094 + ((n)*0x20))
+#define	  SOLO_P2M_EXT_INC(n)			((n)<<20)
+#define	  SOLO_P2M_COPY_SIZE(n)			((n)<<0)
+
+#define SOLO_P2M_TAR_ADR(n)			(0x0098 + ((n)*0x20))
+
+#define SOLO_P2M_EXT_ADR(n)			(0x009C + ((n)*0x20))
+
+#define SOLO_P2M_BUFFER(i)			(0x2000 + ((i)*4))
+
+#define SOLO_VI_CH_SWITCH_0			0x0100
+#define SOLO_VI_CH_SWITCH_1			0x0104
+#define SOLO_VI_CH_SWITCH_2			0x0108
+
+#define	SOLO_VI_CH_ENA				0x010C
+#define	SOLO_VI_CH_FORMAT			0x0110
+#define	  SOLO_VI_FD_SEL_MASK(n)		((n)<<16)
+#define	  SOLO_VI_PROG_MASK(n)			((n)<<0)
+
+#define SOLO_VI_FMT_CFG				0x0114
+#define	  SOLO_VI_FMT_CHECK_VCOUNT		(1<<31)
+#define	  SOLO_VI_FMT_CHECK_HCOUNT		(1<<30)
+#define   SOLO_VI_FMT_TEST_SIGNAL		(1<<28)
+
+#define	SOLO_VI_PAGE_SW				0x0118
+#define	  SOLO_FI_INV_DISP_LIVE(n)		((n)<<8)
+#define	  SOLO_FI_INV_DISP_OUT(n)		((n)<<7)
+#define	  SOLO_DISP_SYNC_FI(n)			((n)<<6)
+#define	  SOLO_PIP_PAGE_ADD(n)			((n)<<3)
+#define	  SOLO_NORMAL_PAGE_ADD(n)		((n)<<0)
+
+#define	SOLO_VI_ACT_I_P				0x011C
+#define	SOLO_VI_ACT_I_S				0x0120
+#define	SOLO_VI_ACT_P				0x0124
+#define	  SOLO_VI_FI_INVERT			(1<<31)
+#define	  SOLO_VI_H_START(n)			((n)<<21)
+#define	  SOLO_VI_V_START(n)			((n)<<11)
+#define	  SOLO_VI_V_STOP(n)			((n)<<0)
+
+#define SOLO_VI_STATUS0				0x0128
+#define   SOLO_VI_STATUS0_PAGE(__n)		((__n) & 0x07)
+#define SOLO_VI_STATUS1				0x012C
+
+/* XXX: Might be better off in kernel level disp.h */
+#define DISP_PAGE(stat)				((stat) & 0x07)
+
+#define SOLO_VI_PB_CONFIG			0x0130
+#define	  SOLO_VI_PB_USER_MODE			(1<<1)
+#define	  SOLO_VI_PB_PAL			(1<<0)
+#define SOLO_VI_PB_RANGE_HV			0x0134
+#define	  SOLO_VI_PB_HSIZE(h)			((h)<<12)
+#define	  SOLO_VI_PB_VSIZE(v)			((v)<<0)
+#define SOLO_VI_PB_ACT_H			0x0138
+#define	  SOLO_VI_PB_HSTART(n)			((n)<<12)
+#define	  SOLO_VI_PB_HSTOP(n)			((n)<<0)
+#define SOLO_VI_PB_ACT_V			0x013C
+#define	  SOLO_VI_PB_VSTART(n)			((n)<<12)
+#define	  SOLO_VI_PB_VSTOP(n)			((n)<<0)
+
+#define	SOLO_VI_MOSAIC(ch)			(0x0140 + ((ch)*4))
+#define	  SOLO_VI_MOSAIC_SX(x)			((x)<<24)
+#define	  SOLO_VI_MOSAIC_EX(x)			((x)<<16)
+#define	  SOLO_VI_MOSAIC_SY(x)			((x)<<8)
+#define	  SOLO_VI_MOSAIC_EY(x)			((x)<<0)
+
+#define	SOLO_VI_WIN_CTRL0(ch)			(0x0180 + ((ch)*4))
+#define	SOLO_VI_WIN_CTRL1(ch)			(0x01C0 + ((ch)*4))
+
+#define	  SOLO_VI_WIN_CHANNEL(n)		((n)<<28)
+
+#define	  SOLO_VI_WIN_PIP(n)			((n)<<27)
+#define	  SOLO_VI_WIN_SCALE(n)			((n)<<24)
+
+#define	  SOLO_VI_WIN_SX(x)			((x)<<12)
+#define	  SOLO_VI_WIN_EX(x)			((x)<<0)
+
+#define	  SOLO_VI_WIN_SY(x)			((x)<<12)
+#define	  SOLO_VI_WIN_EY(x)			((x)<<0)
+
+#define	SOLO_VI_WIN_ON(ch)			(0x0200 + ((ch)*4))
+
+#define SOLO_VI_WIN_SW				0x0240
+#define SOLO_VI_WIN_LIVE_AUTO_MUTE		0x0244
+
+#define	SOLO_VI_MOT_ADR				0x0260
+#define	  SOLO_VI_MOTION_EN(mask)		((mask)<<16)
+#define	SOLO_VI_MOT_CTRL			0x0264
+#define	  SOLO_VI_MOTION_FRAME_COUNT(n)		((n)<<24)
+#define	  SOLO_VI_MOTION_SAMPLE_LENGTH(n)	((n)<<16)
+#define	  SOLO_VI_MOTION_INTR_START_STOP	(1<<15)
+#define	  SOLO_VI_MOTION_FREEZE_DATA		(1<<14)
+#define	  SOLO_VI_MOTION_SAMPLE_COUNT(n)	((n)<<0)
+#define SOLO_VI_MOT_CLEAR			0x0268
+#define SOLO_VI_MOT_STATUS			0x026C
+#define	  SOLO_VI_MOTION_CNT(n)			((n)<<0)
+#define SOLO_VI_MOTION_BORDER			0x0270
+#define SOLO_VI_MOTION_BAR			0x0274
+#define	  SOLO_VI_MOTION_Y_SET			(1<<29)
+#define	  SOLO_VI_MOTION_Y_ADD			(1<<28)
+#define	  SOLO_VI_MOTION_CB_SET			(1<<27)
+#define	  SOLO_VI_MOTION_CB_ADD			(1<<26)
+#define	  SOLO_VI_MOTION_CR_SET			(1<<25)
+#define	  SOLO_VI_MOTION_CR_ADD			(1<<24)
+#define	  SOLO_VI_MOTION_Y_VALUE(v)		((v)<<16)
+#define	  SOLO_VI_MOTION_CB_VALUE(v)		((v)<<8)
+#define	  SOLO_VI_MOTION_CR_VALUE(v)		((v)<<0)
+
+#define	SOLO_VO_FMT_ENC				0x0300
+#define	  SOLO_VO_SCAN_MODE_PROGRESSIVE		(1<<31)
+#define	  SOLO_VO_FMT_TYPE_PAL			(1<<30)
+#define   SOLO_VO_FMT_TYPE_NTSC			0
+#define	  SOLO_VO_USER_SET			(1<<29)
+
+#define	  SOLO_VO_FI_CHANGE			(1<<20)
+#define	  SOLO_VO_USER_COLOR_SET_VSYNC		(1<<19)
+#define	  SOLO_VO_USER_COLOR_SET_HSYNC		(1<<18)
+#define	  SOLO_VO_USER_COLOR_SET_NAH		(1<<17)
+#define	  SOLO_VO_USER_COLOR_SET_NAV		(1<<16)
+#define	  SOLO_VO_NA_COLOR_Y(Y)			((Y)<<8)
+#define	  SOLO_VO_NA_COLOR_CB(CB)		(((CB)/16)<<4)
+#define	  SOLO_VO_NA_COLOR_CR(CR)		(((CR)/16)<<0)
+
+#define	SOLO_VO_ACT_H				0x0304
+#define	  SOLO_VO_H_BLANK(n)			((n)<<22)
+#define	  SOLO_VO_H_START(n)			((n)<<11)
+#define	  SOLO_VO_H_STOP(n)			((n)<<0)
+
+#define	SOLO_VO_ACT_V				0x0308
+#define	  SOLO_VO_V_BLANK(n)			((n)<<22)
+#define	  SOLO_VO_V_START(n)			((n)<<11)
+#define	  SOLO_VO_V_STOP(n)			((n)<<0)
+
+#define	SOLO_VO_RANGE_HV			0x030C
+#define	  SOLO_VO_SYNC_INVERT			(1<<24)
+#define	  SOLO_VO_HSYNC_INVERT			(1<<23)
+#define	  SOLO_VO_VSYNC_INVERT			(1<<22)
+#define	  SOLO_VO_H_LEN(n)			((n)<<11)
+#define	  SOLO_VO_V_LEN(n)			((n)<<0)
+
+#define	SOLO_VO_DISP_CTRL			0x0310
+#define	  SOLO_VO_DISP_ON			(1<<31)
+#define	  SOLO_VO_DISP_ERASE_COUNT(n)		((n&0xf)<<24)
+#define	  SOLO_VO_DISP_DOUBLE_SCAN		(1<<22)
+#define	  SOLO_VO_DISP_SINGLE_PAGE		(1<<21)
+#define	  SOLO_VO_DISP_BASE(n)			(((n)>>16) & 0xffff)
+
+#define SOLO_VO_DISP_ERASE			0x0314
+#define	  SOLO_VO_DISP_ERASE_ON			(1<<0)
+
+#define	SOLO_VO_ZOOM_CTRL			0x0318
+#define	  SOLO_VO_ZOOM_VER_ON			(1<<24)
+#define	  SOLO_VO_ZOOM_HOR_ON			(1<<23)
+#define	  SOLO_VO_ZOOM_V_COMP			(1<<22)
+#define	  SOLO_VO_ZOOM_SX(h)			(((h)/2)<<11)
+#define	  SOLO_VO_ZOOM_SY(v)			(((v)/2)<<0)
+
+#define SOLO_VO_FREEZE_CTRL			0x031C
+#define	  SOLO_VO_FREEZE_ON			(1<<1)
+#define	  SOLO_VO_FREEZE_INTERPOLATION		(1<<0)
+
+#define	SOLO_VO_BKG_COLOR			0x0320
+#define	  SOLO_BG_Y(y)				((y)<<16)
+#define	  SOLO_BG_U(u)				((u)<<8)
+#define	  SOLO_BG_V(v)				((v)<<0)
+
+#define	SOLO_VO_DEINTERLACE			0x0324
+#define	  SOLO_VO_DEINTERLACE_THRESHOLD(n)	((n)<<8)
+#define	  SOLO_VO_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
+
+#define SOLO_VO_BORDER_LINE_COLOR		0x0330
+#define SOLO_VO_BORDER_FILL_COLOR		0x0334
+#define SOLO_VO_BORDER_LINE_MASK		0x0338
+#define SOLO_VO_BORDER_FILL_MASK		0x033c
+
+#define SOLO_VO_BORDER_X(n)			(0x0340+((n)*4))
+#define SOLO_VO_BORDER_Y(n)			(0x0354+((n)*4))
+
+#define SOLO_VO_CELL_EXT_SET			0x0368
+#define SOLO_VO_CELL_EXT_START			0x036c
+#define SOLO_VO_CELL_EXT_STOP			0x0370
+
+#define SOLO_VO_CELL_EXT_SET2			0x0374
+#define SOLO_VO_CELL_EXT_START2			0x0378
+#define SOLO_VO_CELL_EXT_STOP2			0x037c
+
+#define SOLO_VO_RECTANGLE_CTRL(n)		(0x0368+((n)*12))
+#define SOLO_VO_RECTANGLE_START(n)		(0x036c+((n)*12))
+#define SOLO_VO_RECTANGLE_STOP(n)		(0x0370+((n)*12))
+
+#define SOLO_VO_CURSOR_POS			(0x0380)
+#define SOLO_VO_CURSOR_CLR			(0x0384)
+#define SOLO_VO_CURSOR_CLR2			(0x0388)
+#define SOLO_VO_CURSOR_MASK(id)			(0x0390+((id)*4))
+
+#define SOLO_VO_EXPANSION(id)			(0x0250+((id)*4))
+
+#define	SOLO_OSG_CONFIG				0x03E0
+#define	  SOLO_VO_OSG_ON			(1<<31)
+#define	  SOLO_VO_OSG_COLOR_MUTE		(1<<28)
+#define	  SOLO_VO_OSG_ALPHA_RATE(n)		((n)<<22)
+#define	  SOLO_VO_OSG_ALPHA_BG_RATE(n)		((n)<<16)
+#define	  SOLO_VO_OSG_BASE(offset)		(((offset)>>16)&0xffff)
+
+#define SOLO_OSG_ERASE				0x03E4
+#define	  SOLO_OSG_ERASE_ON			(0x80)
+#define	  SOLO_OSG_ERASE_OFF			(0x00)
+
+#define SOLO_VO_OSG_BLINK			0x03E8
+#define	  SOLO_VO_OSG_BLINK_ON			(1<<1)
+#define	  SOLO_VO_OSG_BLINK_INTREVAL18		(1<<0)
+
+#define SOLO_CAP_BASE				0x0400
+#define	  SOLO_CAP_MAX_PAGE(n)			((n)<<16)
+#define	  SOLO_CAP_BASE_ADDR(n)			((n)<<0)
+#define SOLO_CAP_BTW				0x0404
+#define	  SOLO_CAP_PROG_BANDWIDTH(n)		((n)<<8)
+#define	  SOLO_CAP_MAX_BANDWIDTH(n)		((n)<<0)
+
+#define SOLO_DIM_SCALE1				0x0408
+#define SOLO_DIM_SCALE2				0x040C
+#define SOLO_DIM_SCALE3				0x0410
+#define SOLO_DIM_SCALE4				0x0414
+#define SOLO_DIM_SCALE5				0x0418
+#define	  SOLO_DIM_V_MB_NUM_FRAME(n)		((n)<<16)
+#define	  SOLO_DIM_V_MB_NUM_FIELD(n)		((n)<<8)
+#define	  SOLO_DIM_H_MB_NUM(n)			((n)<<0)
+
+#define SOLO_DIM_PROG				0x041C
+#define SOLO_CAP_STATUS				0x0420
+
+#define SOLO_CAP_CH_SCALE(ch)			(0x0440+((ch)*4))
+#define SOLO_CAP_CH_COMP_ENA_E(ch)		(0x0480+((ch)*4))
+#define SOLO_CAP_CH_INTV(ch)			(0x04C0+((ch)*4))
+#define SOLO_CAP_CH_INTV_E(ch)			(0x0500+((ch)*4))
+
+
+#define SOLO_VE_CFG0				0x0610
+#define	  SOLO_VE_TWO_PAGE_MODE			(1<<31)
+#define	  SOLO_VE_INTR_CTRL(n)			((n)<<24)
+#define	  SOLO_VE_BLOCK_SIZE(n)			((n)<<16)
+#define	  SOLO_VE_BLOCK_BASE(n)			((n)<<0)
+
+#define SOLO_VE_CFG1				0x0614
+#define	  SOLO_VE_BYTE_ALIGN(n)			((n)<<24)
+#define	  SOLO_VE_INSERT_INDEX			(1<<18)
+#define	  SOLO_VE_MOTION_MODE(n)		((n)<<16)
+#define	  SOLO_VE_MOTION_BASE(n)		((n)<<0)
+#define   SOLO_VE_MPEG_SIZE_H(n)		((n)<<28) /* 6110 Only */
+#define   SOLO_VE_JPEG_SIZE_H(n)		((n)<<20) /* 6110 Only */
+#define   SOLO_VE_INSERT_INDEX_JPEG		(1<<19)   /* 6110 Only */
+
+#define SOLO_VE_WMRK_POLY			0x061C
+#define SOLO_VE_VMRK_INIT_KEY			0x0620
+#define SOLO_VE_WMRK_STRL			0x0624
+#define SOLO_VE_ENCRYP_POLY			0x0628
+#define SOLO_VE_ENCRYP_INIT			0x062C
+#define SOLO_VE_ATTR				0x0630
+#define	  SOLO_VE_LITTLE_ENDIAN			(1<<31)
+#define	  SOLO_COMP_ATTR_RN			(1<<30)
+#define	  SOLO_COMP_ATTR_FCODE(n)		((n)<<27)
+#define	  SOLO_COMP_TIME_INC(n)			((n)<<25)
+#define	  SOLO_COMP_TIME_WIDTH(n)		((n)<<21)
+#define	  SOLO_DCT_INTERVAL(n)			((n)<<16)
+#define SOLO_VE_COMPT_MOT			0x0634 /* 6110 Only */
+
+#define SOLO_VE_STATE(n)			(0x0640+((n)*4))
+
+#define SOLO_VE_JPEG_QP_TBL			0x0670
+#define SOLO_VE_JPEG_QP_CH_L			0x0674
+#define SOLO_VE_JPEG_QP_CH_H			0x0678
+#define SOLO_VE_JPEG_CFG			0x067C
+#define SOLO_VE_JPEG_CTRL			0x0680
+#define SOLO_VE_CODE_ENCRYPT			0x0684 /* 6110 Only */
+#define SOLO_VE_JPEG_CFG1			0x0688 /* 6110 Only */
+#define SOLO_VE_WMRK_ENABLE			0x068C /* 6110 Only */
+#define SOLO_VE_OSD_CH				0x0690
+#define SOLO_VE_OSD_BASE			0x0694
+#define SOLO_VE_OSD_CLR				0x0698
+#define SOLO_VE_OSD_OPT				0x069C
+#define   SOLO_VE_OSD_V_DOUBLE			(1<<16) /* 6110 Only */
+#define   SOLO_VE_OSD_H_SHADOW			(1<<15)
+#define   SOLO_VE_OSD_V_SHADOW			(1<<14)
+#define   SOLO_VE_OSD_H_OFFSET(n)		((n & 0x7f)<<7)
+#define   SOLO_VE_OSD_V_OFFSET(n)		(n & 0x7f)
+
+#define SOLO_VE_CH_INTL(ch)			(0x0700+((ch)*4))
+#define SOLO_VE_CH_MOT(ch)			(0x0740+((ch)*4))
+#define SOLO_VE_CH_QP(ch)			(0x0780+((ch)*4))
+#define SOLO_VE_CH_QP_E(ch)			(0x07C0+((ch)*4))
+#define SOLO_VE_CH_GOP(ch)			(0x0800+((ch)*4))
+#define SOLO_VE_CH_GOP_E(ch)			(0x0840+((ch)*4))
+#define SOLO_VE_CH_REF_BASE(ch)			(0x0880+((ch)*4))
+#define SOLO_VE_CH_REF_BASE_E(ch)		(0x08C0+((ch)*4))
+
+#define SOLO_VE_MPEG4_QUE(n)			(0x0A00+((n)*8))
+#define SOLO_VE_JPEG_QUE(n)			(0x0A04+((n)*8))
+
+#define SOLO_VD_CFG0				0x0900
+#define	  SOLO_VD_CFG_NO_WRITE_NO_WINDOW	(1<<24)
+#define	  SOLO_VD_CFG_BUSY_WIAT_CODE		(1<<23)
+#define	  SOLO_VD_CFG_BUSY_WIAT_REF		(1<<22)
+#define	  SOLO_VD_CFG_BUSY_WIAT_RES		(1<<21)
+#define	  SOLO_VD_CFG_BUSY_WIAT_MS		(1<<20)
+#define	  SOLO_VD_CFG_SINGLE_MODE		(1<<18)
+#define	  SOLO_VD_CFG_SCAL_MANUAL		(1<<17)
+#define	  SOLO_VD_CFG_USER_PAGE_CTRL		(1<<16)
+#define	  SOLO_VD_CFG_LITTLE_ENDIAN		(1<<15)
+#define	  SOLO_VD_CFG_START_FI			(1<<14)
+#define	  SOLO_VD_CFG_ERR_LOCK			(1<<13)
+#define	  SOLO_VD_CFG_ERR_INT_ENA		(1<<12)
+#define	  SOLO_VD_CFG_TIME_WIDTH(n)		((n)<<8)
+#define	  SOLO_VD_CFG_DCT_INTERVAL(n)		((n)<<0)
+
+#define SOLO_VD_CFG1				0x0904
+
+#define	SOLO_VD_DEINTERLACE			0x0908
+#define	  SOLO_VD_DEINTERLACE_THRESHOLD(n)	((n)<<8)
+#define	  SOLO_VD_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
+
+#define SOLO_VD_CODE_ADR			0x090C
+
+#define SOLO_VD_CTRL				0x0910
+#define	  SOLO_VD_OPER_ON			(1<<31)
+#define	  SOLO_VD_MAX_ITEM(n)			((n)<<0)
+
+#define SOLO_VD_STATUS0				0x0920
+#define	  SOLO_VD_STATUS0_INTR_ACK		(1<<22)
+#define	  SOLO_VD_STATUS0_INTR_EMPTY		(1<<21)
+#define	  SOLO_VD_STATUS0_INTR_ERR		(1<<20)
+
+#define SOLO_VD_STATUS1				0x0924
+
+#define SOLO_VD_IDX0				0x0930
+#define	  SOLO_VD_IDX_INTERLACE			(1<<30)
+#define	  SOLO_VD_IDX_CHANNEL(n)		((n)<<24)
+#define	  SOLO_VD_IDX_SIZE(n)			((n)<<0)
+
+#define SOLO_VD_IDX1				0x0934
+#define	  SOLO_VD_IDX_SRC_SCALE(n)		((n)<<28)
+#define	  SOLO_VD_IDX_WINDOW(n)			((n)<<24)
+#define	  SOLO_VD_IDX_DEINTERLACE		(1<<16)
+#define	  SOLO_VD_IDX_H_BLOCK(n)		((n)<<8)
+#define	  SOLO_VD_IDX_V_BLOCK(n)		((n)<<0)
+
+#define SOLO_VD_IDX2				0x0938
+#define	  SOLO_VD_IDX_REF_BASE_SIDE		(1<<31)
+#define	  SOLO_VD_IDX_REF_BASE(n)		(((n)>>16)&0xffff)
+
+#define SOLO_VD_IDX3				0x093C
+#define	  SOLO_VD_IDX_DISP_SCALE(n)		((n)<<28)
+#define	  SOLO_VD_IDX_INTERLACE_WR		(1<<27)
+#define	  SOLO_VD_IDX_INTERPOL			(1<<26)
+#define	  SOLO_VD_IDX_HOR2X			(1<<25)
+#define	  SOLO_VD_IDX_OFFSET_X(n)		((n)<<12)
+#define	  SOLO_VD_IDX_OFFSET_Y(n)		((n)<<0)
+
+#define SOLO_VD_IDX4				0x0940
+#define	  SOLO_VD_IDX_DEC_WR_PAGE(n)		((n)<<8)
+#define	  SOLO_VD_IDX_DISP_RD_PAGE(n)		((n)<<0)
+
+#define SOLO_VD_WR_PAGE(n)			(0x03F0 + ((n) * 4))
+
+
+#define SOLO_GPIO_CONFIG_0			0x0B00
+#define SOLO_GPIO_CONFIG_1			0x0B04
+#define SOLO_GPIO_DATA_OUT			0x0B08
+#define SOLO_GPIO_DATA_IN			0x0B0C
+#define SOLO_GPIO_INT_ACK_STA			0x0B10
+#define SOLO_GPIO_INT_ENA			0x0B14
+#define SOLO_GPIO_INT_CFG_0			0x0B18
+#define SOLO_GPIO_INT_CFG_1			0x0B1C
+
+
+#define SOLO_IIC_CFG				0x0B20
+#define	  SOLO_IIC_ENABLE			(1<<8)
+#define	  SOLO_IIC_PRESCALE(n)			((n)<<0)
+
+#define SOLO_IIC_CTRL				0x0B24
+#define	  SOLO_IIC_AUTO_CLEAR			(1<<20)
+#define	  SOLO_IIC_STATE_RX_ACK			(1<<19)
+#define	  SOLO_IIC_STATE_BUSY			(1<<18)
+#define	  SOLO_IIC_STATE_SIG_ERR		(1<<17)
+#define	  SOLO_IIC_STATE_TRNS			(1<<16)
+#define	  SOLO_IIC_CH_SET(n)			((n)<<5)
+#define	  SOLO_IIC_ACK_EN			(1<<4)
+#define	  SOLO_IIC_START			(1<<3)
+#define	  SOLO_IIC_STOP				(1<<2)
+#define	  SOLO_IIC_READ				(1<<1)
+#define	  SOLO_IIC_WRITE			(1<<0)
+
+#define SOLO_IIC_TXD				0x0B28
+#define SOLO_IIC_RXD				0x0B2C
+
+/*
+ *	UART REGISTER
+ */
+#define SOLO_UART_CONTROL(n)			(0x0BA0 + ((n)*0x20))
+#define	  SOLO_UART_CLK_DIV(n)			((n)<<24)
+#define	  SOLO_MODEM_CTRL_EN			(1<<20)
+#define	  SOLO_PARITY_ERROR_DROP		(1<<18)
+#define	  SOLO_IRQ_ERR_EN			(1<<17)
+#define	  SOLO_IRQ_RX_EN			(1<<16)
+#define	  SOLO_IRQ_TX_EN			(1<<15)
+#define	  SOLO_RX_EN				(1<<14)
+#define	  SOLO_TX_EN				(1<<13)
+#define	  SOLO_UART_HALF_DUPLEX			(1<<12)
+#define	  SOLO_UART_LOOPBACK			(1<<11)
+
+#define	  SOLO_BAUDRATE_230400			((0<<9)|(0<<6))
+#define	  SOLO_BAUDRATE_115200			((0<<9)|(1<<6))
+#define	  SOLO_BAUDRATE_57600			((0<<9)|(2<<6))
+#define	  SOLO_BAUDRATE_38400			((0<<9)|(3<<6))
+#define	  SOLO_BAUDRATE_19200			((0<<9)|(4<<6))
+#define	  SOLO_BAUDRATE_9600			((0<<9)|(5<<6))
+#define	  SOLO_BAUDRATE_4800			((0<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_2400			((1<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_1200			((2<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_300			((3<<9)|(6<<6))
+
+#define	  SOLO_UART_DATA_BIT_8			(3<<4)
+#define	  SOLO_UART_DATA_BIT_7			(2<<4)
+#define	  SOLO_UART_DATA_BIT_6			(1<<4)
+#define	  SOLO_UART_DATA_BIT_5			(0<<4)
+
+#define	  SOLO_UART_STOP_BIT_1			(0<<2)
+#define	  SOLO_UART_STOP_BIT_2			(1<<2)
+
+#define	  SOLO_UART_PARITY_NONE			(0<<0)
+#define	  SOLO_UART_PARITY_EVEN			(2<<0)
+#define	  SOLO_UART_PARITY_ODD			(3<<0)
+
+#define SOLO_UART_STATUS(n)			(0x0BA4 + ((n)*0x20))
+#define	  SOLO_UART_CTS				(1<<15)
+#define	  SOLO_UART_RX_BUSY			(1<<14)
+#define	  SOLO_UART_OVERRUN			(1<<13)
+#define	  SOLO_UART_FRAME_ERR			(1<<12)
+#define	  SOLO_UART_PARITY_ERR			(1<<11)
+#define	  SOLO_UART_TX_BUSY			(1<<5)
+
+#define	  SOLO_UART_RX_BUFF_CNT(stat)		(((stat)>>6) & 0x1f)
+#define	  SOLO_UART_RX_BUFF_SIZE		8
+#define	  SOLO_UART_TX_BUFF_CNT(stat)		(((stat)>>0) & 0x1f)
+#define	  SOLO_UART_TX_BUFF_SIZE		8
+
+#define SOLO_UART_TX_DATA(n)			(0x0BA8 + ((n)*0x20))
+#define	  SOLO_UART_TX_DATA_PUSH		(1<<8)
+#define SOLO_UART_RX_DATA(n)			(0x0BAC + ((n)*0x20))
+#define	  SOLO_UART_RX_DATA_POP			(1<<8)
+
+#define SOLO_TIMER_CLOCK_NUM			0x0be0
+#define SOLO_TIMER_USEC				0x0be8
+#define SOLO_TIMER_SEC				0x0bec
+#define SOLO_TIMER_USEC_LSB			0x0d20 /* 6110 Only */
+
+#define SOLO_AUDIO_CONTROL			0x0D00
+#define	  SOLO_AUDIO_ENABLE			(1<<31)
+#define	  SOLO_AUDIO_MASTER_MODE		(1<<30)
+#define	  SOLO_AUDIO_I2S_MODE			(1<<29)
+#define	  SOLO_AUDIO_I2S_LR_SWAP		(1<<27)
+#define	  SOLO_AUDIO_I2S_8BIT			(1<<26)
+#define	  SOLO_AUDIO_I2S_MULTI(n)		((n)<<24)
+#define	  SOLO_AUDIO_MIX_9TO0			(1<<23)
+#define	  SOLO_AUDIO_DEC_9TO0_VOL(n)		((n)<<20)
+#define	  SOLO_AUDIO_MIX_19TO10			(1<<19)
+#define	  SOLO_AUDIO_DEC_19TO10_VOL(n)		((n)<<16)
+#define	  SOLO_AUDIO_MODE(n)			((n)<<0)
+#define SOLO_AUDIO_SAMPLE			0x0D04
+#define	  SOLO_AUDIO_EE_MODE_ON			(1<<30)
+#define	  SOLO_AUDIO_EE_ENC_CH(ch)		((ch)<<25)
+#define	  SOLO_AUDIO_BITRATE(n)			((n)<<16)
+#define	  SOLO_AUDIO_CLK_DIV(n)			((n)<<0)
+#define SOLO_AUDIO_FDMA_INTR			0x0D08
+#define	  SOLO_AUDIO_FDMA_INTERVAL(n)		((n)<<19)
+#define	  SOLO_AUDIO_INTR_ORDER(n)		((n)<<16)
+#define	  SOLO_AUDIO_FDMA_BASE(n)		((n)<<0)
+#define SOLO_AUDIO_EVOL_0			0x0D0C
+#define SOLO_AUDIO_EVOL_1			0x0D10
+#define	  SOLO_AUDIO_EVOL(ch, value)		((value)<<((ch)%10))
+#define SOLO_AUDIO_STA				0x0D14
+
+/*
+ * Watchdog configuration
+ */
+#define SOLO_WATCHDOG				0x0be4
+#define SOLO_WATCHDOG_SET(status, sec)		(status << 8 | (sec & 0xff))
+
+#endif /* __SOLO6X10_REGISTERS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+#define DEFAULT_HDELAY_NTSC		(32 - 8)
+#define DEFAULT_HACTIVE_NTSC		(720 + 16)
+#define DEFAULT_VDELAY_NTSC		(7 - 2)
+#define DEFAULT_VACTIVE_NTSC		(240 + 4)
+
+#define DEFAULT_HDELAY_PAL		(32 + 4)
+#define DEFAULT_HACTIVE_PAL		(864-DEFAULT_HDELAY_PAL)
+#define DEFAULT_VDELAY_PAL		(6)
+#define DEFAULT_VACTIVE_PAL		(312-DEFAULT_VDELAY_PAL)
+
+
+static const u8 tbl_tw2864_ntsc_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
+	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
+	0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
+	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
+	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
+	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
+};
+
+static const u8 tbl_tw2864_pal_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
+	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01,
+	0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
+	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
+	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
+	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
+};
+
+static const u8 tbl_tw2865_ntsc_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, /* 0x40 */
+	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
+	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
+	0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
+	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
+	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
+	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
+	0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
+	0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
+	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
+	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
+};
+
+static const u8 tbl_tw2865_pal_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, /* 0x40 */
+	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
+	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
+	0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
+	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
+	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
+	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
+	0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
+	0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
+	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
+	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
+};
+
+#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
+
+static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off,
+		      u8 tw_off)
+{
+	if (is_tw286x(solo_dev, chip_id))
+		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					 TW_CHIP_OFFSET_ADDR(chip_id),
+					 tw6x_off);
+	else
+		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					 TW_CHIP_OFFSET_ADDR(chip_id),
+					 tw_off);
+}
+
+static void tw_writebyte(struct solo_dev *solo_dev, int chip_id,
+			 u8 tw6x_off, u8 tw_off, u8 val)
+{
+	if (is_tw286x(solo_dev, chip_id))
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+				   TW_CHIP_OFFSET_ADDR(chip_id),
+				   tw6x_off, val);
+	else
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+				   TW_CHIP_OFFSET_ADDR(chip_id),
+				   tw_off, val);
+}
+
+static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
+				u8 val)
+{
+	int i;
+
+	for (i = 0; i < 5; i++) {
+		u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
+
+		if (rval == val)
+			return;
+
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val);
+		msleep_interruptible(1);
+	}
+
+/*	printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */
+/*		addr, off, val); */
+}
+
+static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_tw2865_common[256];
+	int i;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
+		memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
+		       sizeof(tbl_tw2865_common));
+	else
+		memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
+		       sizeof(tbl_tw2865_common));
+
+	/* ALINK Mode */
+	if (solo_dev->nr_chans == 4) {
+		tbl_tw2865_common[0xd2] = 0x01;
+		tbl_tw2865_common[0xcf] = 0x00;
+	} else if (solo_dev->nr_chans == 8) {
+		tbl_tw2865_common[0xd2] = 0x02;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2865_common[0xcf] = 0x80;
+	} else if (solo_dev->nr_chans == 16) {
+		tbl_tw2865_common[0xd2] = 0x03;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2865_common[0xcf] = 0x83;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+			tbl_tw2865_common[0xcf] = 0x83;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+			tbl_tw2865_common[0xcf] = 0x80;
+	}
+
+	for (i = 0; i < 0xff; i++) {
+		/* Skip read only registers */
+		switch (i) {
+		case 0xb8 ... 0xc1:
+		case 0xc4 ... 0xc7:
+		case 0xfd:
+			continue;
+		}
+		switch (i & ~0x30) {
+		case 0x00:
+		case 0x0c ... 0x0d:
+			continue;
+		}
+
+		tw_write_and_verify(solo_dev, dev_addr, i,
+				    tbl_tw2865_common[i]);
+	}
+
+	return 0;
+}
+
+static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_tw2864_common[256];
+	int i;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
+		memcpy(tbl_tw2864_common, tbl_tw2864_pal_template,
+		       sizeof(tbl_tw2864_common));
+	else
+		memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template,
+		       sizeof(tbl_tw2864_common));
+
+	if (solo_dev->tw2865 == 0) {
+		/* IRQ Mode */
+		if (solo_dev->nr_chans == 4) {
+			tbl_tw2864_common[0xd2] = 0x01;
+			tbl_tw2864_common[0xcf] = 0x00;
+		} else if (solo_dev->nr_chans == 8) {
+			tbl_tw2864_common[0xd2] = 0x02;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x40;
+		} else if (solo_dev->nr_chans == 16) {
+			tbl_tw2864_common[0xd2] = 0x03;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+				tbl_tw2864_common[0xcf] = 0x40;
+		}
+	} else {
+		/* ALINK Mode. Assumes that the first tw28xx is a
+		 * 2865 and these are in cascade. */
+		for (i = 0; i <= 4; i++)
+			tbl_tw2864_common[0x08 | i << 4] = 0x12;
+
+		if (solo_dev->nr_chans == 8) {
+			tbl_tw2864_common[0xd2] = 0x02;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x80;
+		} else if (solo_dev->nr_chans == 16) {
+			tbl_tw2864_common[0xd2] = 0x03;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x83;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+				tbl_tw2864_common[0xcf] = 0x83;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+				tbl_tw2864_common[0xcf] = 0x80;
+		}
+	}
+
+	for (i = 0; i < 0xff; i++) {
+		/* Skip read only registers */
+		switch (i) {
+		case 0xb8 ... 0xc1:
+		case 0xfd:
+			continue;
+		}
+		switch (i & ~0x30) {
+		case 0x00:
+		case 0x0c:
+		case 0x0d:
+			continue;
+		}
+
+		tw_write_and_verify(solo_dev, dev_addr, i,
+				    tbl_tw2864_common[i]);
+	}
+
+	return 0;
+}
+
+static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_ntsc_tw2815_common[] = {
+		0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
+		0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
+	};
+
+	u8 tbl_pal_tw2815_common[] = {
+		0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
+		0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
+	};
+
+	u8 tbl_tw2815_sfr[] = {
+		0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f, /* 0x00 */
+		0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
+		0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00, /* 0x10 */
+		0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
+		0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec, /* 0x20 */
+		0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
+		0x88, 0x11, 0x00, 0x88, 0x88, 0x00,		/* 0x30 */
+	};
+	u8 *tbl_tw2815_common;
+	int i;
+	int ch;
+
+	tbl_ntsc_tw2815_common[0x06] = 0;
+
+	/* Horizontal Delay Control */
+	tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8);
+
+	/* Horizontal Active Control */
+	tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2);
+
+	/* Vertical Delay Control */
+	tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4);
+
+	/* Vertical Active Control */
+	tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5);
+
+	tbl_pal_tw2815_common[0x06] = 0;
+
+	/* Horizontal Delay Control */
+	tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8);
+
+	/* Horizontal Active Control */
+	tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2);
+
+	/* Vertical Delay Control */
+	tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4);
+
+	/* Vertical Active Control */
+	tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5);
+
+	tbl_tw2815_common =
+	    (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ?
+	     tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
+
+	/* Dual ITU-R BT.656 format */
+	tbl_tw2815_common[0x0d] |= 0x04;
+
+	/* Audio configuration */
+	tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
+
+	if (solo_dev->nr_chans == 4) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 1;
+		tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
+	} else if (solo_dev->nr_chans == 8) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 2;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
+	} else if (solo_dev->nr_chans == 16) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 3;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
+	}
+
+	/* Output mode of R_ADATM pin (0 mixing, 1 record) */
+	/* tbl_tw2815_sfr[0x63 - 0x40] |= 0 << 2; */
+
+	/* 8KHz, used to be 16KHz, but changed for remote client compat */
+	tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
+	tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
+
+	/* Playback of right channel */
+	tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
+
+	/* Reserved value (XXX ??) */
+	tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
+
+	/* Analog output gain and mix ratio playback on full */
+	tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
+	/* Select playback audio and mute all except */
+	tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
+	tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
+
+	/* End of audio configuration */
+
+	for (ch = 0; ch < 4; ch++) {
+		tbl_tw2815_common[0x0d] &= ~3;
+		switch (ch) {
+		case 0:
+			tbl_tw2815_common[0x0d] |= 0x21;
+			break;
+		case 1:
+			tbl_tw2815_common[0x0d] |= 0x20;
+			break;
+		case 2:
+			tbl_tw2815_common[0x0d] |= 0x23;
+			break;
+		case 3:
+			tbl_tw2815_common[0x0d] |= 0x22;
+			break;
+		}
+
+		for (i = 0; i < 0x0f; i++) {
+			if (i == 0x00)
+				continue;	/* read-only */
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   dev_addr, (ch * 0x10) + i,
+					   tbl_tw2815_common[i]);
+		}
+	}
+
+	for (i = 0x40; i < 0x76; i++) {
+		/* Skip read-only and nop registers */
+		if (i == 0x40 || i == 0x59 || i == 0x5a ||
+		    i == 0x5d || i == 0x5e || i == 0x5f)
+			continue;
+
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i,
+				       tbl_tw2815_sfr[i - 0x40]);
+	}
+
+	return 0;
+}
+
+#define FIRST_ACTIVE_LINE	0x0008
+#define LAST_ACTIVE_LINE	0x0102
+
+static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals,
+		int start, int n)
+{
+	for (; start < n; start++, vals++) {
+		/* Skip read-only registers */
+		switch (start) {
+		/* case 0x00 ... 0x25: */
+		case 0x2e ... 0x37:
+		case 0x60:
+		case 0x7d:
+			continue;
+		}
+		solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals);
+	}
+}
+
+#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \
+		| ((FIRST_ACTIVE_LINE & 0x100) >> 4))
+
+static void saa712x_setup(struct solo_dev *dev)
+{
+	const int reg_start = 0x26;
+	const uint8_t saa7128_regs_ntsc[] = {
+	/* :0x26 */
+		0x0d, 0x00,
+	/* :0x28 */
+		0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
+	/* :0x2e XXX: read-only */
+		0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* :0x38 */
+		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* :0x40 */
+		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
+		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
+	/* :0x50 */
+		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
+		0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
+	/* :0x60 */
+		0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
+		0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00,
+	/* :0x70 */
+		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
+		0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff,
+		SAA712x_reg7c, 0x00, 0xff, 0xff,
+	}, saa7128_regs_pal[] = {
+	/* :0x26 */
+		0x0d, 0x00,
+	/* :0x28 */
+		0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
+	/* :0x2e XXX: read-only */
+		0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* :0x38 */
+		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* :0x40 */
+		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
+		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
+	/* :0x50 */
+		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
+		0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e,
+	/* :0x60 */
+		0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77,
+		0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00,
+	/* :0x70 */
+		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
+		0x00, 0x00, 0x12, 0x30,
+		SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff,
+	};
+
+	if (dev->video_type == SOLO_VO_FMT_TYPE_PAL)
+		saa712x_write_regs(dev, saa7128_regs_pal, reg_start,
+				sizeof(saa7128_regs_pal));
+	else
+		saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start,
+				sizeof(saa7128_regs_ntsc));
+}
+
+int solo_tw28_init(struct solo_dev *solo_dev)
+{
+	int i;
+	u8 value;
+
+	solo_dev->tw28_cnt = 0;
+
+	/* Detect techwell chip type(s) */
+	for (i = 0; i < solo_dev->nr_chans / 4; i++) {
+		value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					  TW_CHIP_OFFSET_ADDR(i), 0xFF);
+
+		switch (value >> 3) {
+		case 0x18:
+			solo_dev->tw2865 |= 1 << i;
+			solo_dev->tw28_cnt++;
+			break;
+		case 0x0c:
+			solo_dev->tw2864 |= 1 << i;
+			solo_dev->tw28_cnt++;
+			break;
+		default:
+			value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						  TW_CHIP_OFFSET_ADDR(i),
+						  0x59);
+			if ((value >> 3) == 0x04) {
+				solo_dev->tw2815 |= 1 << i;
+				solo_dev->tw28_cnt++;
+			}
+		}
+	}
+
+	if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) {
+		dev_err(&solo_dev->pdev->dev,
+			"Could not initialize any techwell chips\n");
+		return -EINVAL;
+	}
+
+	saa712x_setup(solo_dev);
+
+	for (i = 0; i < solo_dev->tw28_cnt; i++) {
+		if ((solo_dev->tw2865 & (1 << i)))
+			tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+		else if ((solo_dev->tw2864 & (1 << i)))
+			tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+		else
+			tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+	}
+
+	return 0;
+}
+
+/*
+ * We accessed the video status signal in the Techwell chip through
+ * iic/i2c because the video status reported by register REG_VI_STATUS1
+ * (address 0x012C) of the SOLO6010 chip doesn't give the correct video
+ * status signal values.
+ */
+int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
+{
+	u8 val, chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR,
+			  TW_AV_STAT_ADDR) & 0x0f;
+
+	return val & (1 << ch) ? 1 : 0;
+}
+
+#if 0
+/* Status of audio from up to 4 techwell chips are combined into 1 variable.
+ * See techwell datasheet for details. */
+u16 tw28_get_audio_status(struct solo_dev *solo_dev)
+{
+	u8 val;
+	u16 status = 0;
+	int i;
+
+	for (i = 0; i < solo_dev->tw28_cnt; i++) {
+		val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR,
+				   TW_AV_STAT_ADDR) & 0xf0) >> 4;
+		status |= val << (i * 4);
+	}
+
+	return status;
+}
+#endif
+
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch)
+{
+	return is_tw286x(solo_dev, ch / 4);
+}
+
+int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
+		      s32 val)
+{
+	char sval;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	if (val > 255 || val < 0)
+		return -ERANGE;
+
+	switch (ctrl) {
+	case V4L2_CID_SHARPNESS:
+		/* Only 286x has sharpness */
+		if (is_tw286x(solo_dev, chip_num)) {
+			u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						 TW_CHIP_OFFSET_ADDR(chip_num),
+						 TW286x_SHARPNESS(chip_num));
+			v &= 0xf0;
+			v |= val;
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   TW_CHIP_OFFSET_ADDR(chip_num),
+					   TW286x_SHARPNESS(chip_num), v);
+		} else {
+			return -EINVAL;
+		}
+		break;
+
+	case V4L2_CID_HUE:
+		if (is_tw286x(solo_dev, chip_num))
+			sval = val - 128;
+		else
+			sval = (char)val;
+		tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
+			     TW_HUE_ADDR(ch), sval);
+
+		break;
+
+	case V4L2_CID_SATURATION:
+		/* 286x chips have a U and V component for saturation */
+		if (is_tw286x(solo_dev, chip_num)) {
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   TW_CHIP_OFFSET_ADDR(chip_num),
+					   TW286x_SATURATIONU_ADDR(ch), val);
+		}
+		tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch),
+			     TW_SATURATION_ADDR(ch), val);
+
+		break;
+
+	case V4L2_CID_CONTRAST:
+		tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch),
+			     TW_CONTRAST_ADDR(ch), val);
+		break;
+
+	case V4L2_CID_BRIGHTNESS:
+		if (is_tw286x(solo_dev, chip_num))
+			sval = val - 128;
+		else
+			sval = (char)val;
+		tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch),
+			     TW_BRIGHTNESS_ADDR(ch), sval);
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
+		      s32 *val)
+{
+	u8 rval, chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	switch (ctrl) {
+	case V4L2_CID_SHARPNESS:
+		/* Only 286x has sharpness */
+		if (is_tw286x(solo_dev, chip_num)) {
+			rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						 TW_CHIP_OFFSET_ADDR(chip_num),
+						 TW286x_SHARPNESS(chip_num));
+			*val = rval & 0x0f;
+		} else
+			*val = 0;
+		break;
+	case V4L2_CID_HUE:
+		rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
+				   TW_HUE_ADDR(ch));
+		if (is_tw286x(solo_dev, chip_num))
+			*val = (s32)((char)rval) + 128;
+		else
+			*val = rval;
+		break;
+	case V4L2_CID_SATURATION:
+		*val = tw_readbyte(solo_dev, chip_num,
+				   TW286x_SATURATIONU_ADDR(ch),
+				   TW_SATURATION_ADDR(ch));
+		break;
+	case V4L2_CID_CONTRAST:
+		*val = tw_readbyte(solo_dev, chip_num,
+				   TW286x_CONTRAST_ADDR(ch),
+				   TW_CONTRAST_ADDR(ch));
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		rval = tw_readbyte(solo_dev, chip_num,
+				   TW286x_BRIGHTNESS_ADDR(ch),
+				   TW_BRIGHTNESS_ADDR(ch));
+		if (is_tw286x(solo_dev, chip_num))
+			*val = (s32)((char)rval) + 128;
+		else
+			*val = rval;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if 0
+/*
+ * For audio output volume, the output channel is only 1. In this case we
+ * don't need to offset TW_CHIP_OFFSET_ADDR. The TW_CHIP_OFFSET_ADDR used
+ * is the base address of the techwell chip.
+ */
+void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val)
+{
+	unsigned int val;
+	unsigned int chip_num;
+
+	chip_num = (solo_dev->nr_chans - 1) / 4;
+
+	val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
+			  TW_AUDIO_OUTPUT_VOL_ADDR);
+
+	u_val = (val & 0x0f) | (u_val << 4);
+
+	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
+		     TW_AUDIO_OUTPUT_VOL_ADDR, u_val);
+}
+#endif
+
+u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch)
+{
+	u8 val;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	val = tw_readbyte(solo_dev, chip_num,
+			  TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+			  TW_AUDIO_INPUT_GAIN_ADDR(ch));
+
+	return (ch % 2) ? (val >> 4) : (val & 0x0f);
+}
+
+void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val)
+{
+	u8 old_val;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	old_val = tw_readbyte(solo_dev, chip_num,
+			      TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+			      TW_AUDIO_INPUT_GAIN_ADDR(ch));
+
+	val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
+		((ch % 2) ? (val << 4) : val);
+
+	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+		     TW_AUDIO_INPUT_GAIN_ADDR(ch), val);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.h linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.h
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-tw28.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOLO6X10_TW28_H
+#define __SOLO6X10_TW28_H
+
+#include "solo6x10.h"
+
+#define TW_NUM_CHIP				4
+#define TW_BASE_ADDR				0x28
+#define TW_CHIP_OFFSET_ADDR(n)			(TW_BASE_ADDR + (n))
+
+/* tw2815 */
+#define TW_AV_STAT_ADDR				0x5a
+#define TW_HUE_ADDR(n)				(0x07 | ((n) << 4))
+#define TW_SATURATION_ADDR(n)			(0x08 | ((n) << 4))
+#define TW_CONTRAST_ADDR(n)			(0x09 | ((n) << 4))
+#define TW_BRIGHTNESS_ADDR(n)			(0x0a | ((n) << 4))
+#define TW_AUDIO_OUTPUT_VOL_ADDR		0x70
+#define TW_AUDIO_INPUT_GAIN_ADDR(n)		(0x60 + ((n > 1) ? 1 : 0))
+
+/* tw286x */
+#define TW286x_AV_STAT_ADDR			0xfd
+#define TW286x_HUE_ADDR(n)			(0x06 | ((n) << 4))
+#define TW286x_SATURATIONU_ADDR(n)		(0x04 | ((n) << 4))
+#define TW286x_SATURATIONV_ADDR(n)		(0x05 | ((n) << 4))
+#define TW286x_CONTRAST_ADDR(n)			(0x02 | ((n) << 4))
+#define TW286x_BRIGHTNESS_ADDR(n)		(0x01 | ((n) << 4))
+#define TW286x_SHARPNESS(n)			(0x03 | ((n) << 4))
+#define TW286x_AUDIO_OUTPUT_VOL_ADDR		0xdf
+#define TW286x_AUDIO_INPUT_GAIN_ADDR(n)		(0xD0 + ((n > 1) ? 1 : 0))
+
+int solo_tw28_init(struct solo_dev *solo_dev);
+
+int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val);
+int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val);
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch);
+
+u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch);
+void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val);
+int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch);
+
+#if 0
+unsigned int tw2815_get_audio_status(struct SOLO *solo);
+void tw2815_Set_AudioOutVol(struct SOLO *solo, unsigned int u_val);
+#endif
+
+#endif /* __SOLO6X10_TW28_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,733 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+/* Image size is two fields, SOLO_HW_BPL is one horizontal line in hardware */
+#define SOLO_HW_BPL		2048
+#define solo_vlines(__solo)	(__solo->video_vsize * 2)
+#define solo_image_size(__solo) (solo_bytesperline(__solo) * \
+				 solo_vlines(__solo))
+#define solo_bytesperline(__solo) (__solo->video_hsize * 2)
+
+#define MIN_VID_BUFFERS		2
+
+static inline void erase_on(struct solo_dev *solo_dev)
+{
+	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
+	solo_dev->erasing = 1;
+	solo_dev->frame_blank = 0;
+}
+
+static inline int erase_off(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->erasing)
+		return 0;
+
+	/* First time around, assert erase off */
+	if (!solo_dev->frame_blank)
+		solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0);
+	/* Keep the erasing flag on for 8 frames minimum */
+	if (solo_dev->frame_blank++ >= 8)
+		solo_dev->erasing = 0;
+
+	return 1;
+}
+
+void solo_video_in_isr(struct solo_dev *solo_dev)
+{
+	wake_up_interruptible_all(&solo_dev->disp_thread_wait);
+}
+
+static void solo_win_setup(struct solo_dev *solo_dev, u8 ch,
+			   int sx, int sy, int ex, int ey, int scale)
+{
+	if (ch >= solo_dev->nr_chans)
+		return;
+
+	/* Here, we just keep window/channel the same */
+	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch),
+		       SOLO_VI_WIN_CHANNEL(ch) |
+		       SOLO_VI_WIN_SX(sx) |
+		       SOLO_VI_WIN_EX(ex) |
+		       SOLO_VI_WIN_SCALE(scale));
+
+	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch),
+		       SOLO_VI_WIN_SY(sy) |
+		       SOLO_VI_WIN_EY(ey));
+}
+
+static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
+{
+	u8 ch = idx * 4;
+
+	if (ch >= solo_dev->nr_chans)
+		return -EINVAL;
+
+	if (!on) {
+		u8 i;
+
+		for (i = ch; i < ch + 4; i++)
+			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
+				       solo_vlines(solo_dev),
+				       solo_dev->video_hsize,
+				       solo_vlines(solo_dev), 0);
+		return 0;
+	}
+
+	/* Row 1 */
+	solo_win_setup(solo_dev, ch, 0, 0, solo_dev->video_hsize / 2,
+		       solo_vlines(solo_dev) / 2, 3);
+	solo_win_setup(solo_dev, ch + 1, solo_dev->video_hsize / 2, 0,
+		       solo_dev->video_hsize, solo_vlines(solo_dev) / 2, 3);
+	/* Row 2 */
+	solo_win_setup(solo_dev, ch + 2, 0, solo_vlines(solo_dev) / 2,
+		       solo_dev->video_hsize / 2, solo_vlines(solo_dev), 3);
+	solo_win_setup(solo_dev, ch + 3, solo_dev->video_hsize / 2,
+		       solo_vlines(solo_dev) / 2, solo_dev->video_hsize,
+		       solo_vlines(solo_dev), 3);
+
+	return 0;
+}
+
+static int solo_v4l2_ch_ext_16up(struct solo_dev *solo_dev, int on)
+{
+	int sy, ysize, hsize, i;
+
+	if (!on) {
+		for (i = 0; i < 16; i++)
+			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
+				       solo_vlines(solo_dev),
+				       solo_dev->video_hsize,
+				       solo_vlines(solo_dev), 0);
+		return 0;
+	}
+
+	ysize = solo_vlines(solo_dev) / 4;
+	hsize = solo_dev->video_hsize / 4;
+
+	for (sy = 0, i = 0; i < 4; i++, sy += ysize) {
+		solo_win_setup(solo_dev, i * 4, 0, sy, hsize,
+			       sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 1, hsize, sy,
+			       hsize * 2, sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 2, hsize * 2, sy,
+			       hsize * 3, sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 3, hsize * 3, sy,
+			       solo_dev->video_hsize, sy + ysize, 5);
+	}
+
+	return 0;
+}
+
+static int solo_v4l2_ch(struct solo_dev *solo_dev, u8 ch, int on)
+{
+	u8 ext_ch;
+
+	if (ch < solo_dev->nr_chans) {
+		solo_win_setup(solo_dev, ch, on ? 0 : solo_dev->video_hsize,
+			       on ? 0 : solo_vlines(solo_dev),
+			       solo_dev->video_hsize, solo_vlines(solo_dev),
+			       on ? 1 : 0);
+		return 0;
+	}
+
+	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
+		return -EINVAL;
+
+	ext_ch = ch - solo_dev->nr_chans;
+
+	/* 4up's first */
+	if (ext_ch < 4)
+		return solo_v4l2_ch_ext_4up(solo_dev, ext_ch, on);
+
+	/* Remaining case is 16up for 16-port */
+	return solo_v4l2_ch_ext_16up(solo_dev, on);
+}
+
+static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
+{
+	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
+		return -EINVAL;
+
+	erase_on(solo_dev);
+
+	solo_v4l2_ch(solo_dev, solo_dev->cur_disp_ch, 0);
+	solo_v4l2_ch(solo_dev, ch, 1);
+
+	solo_dev->cur_disp_ch = ch;
+
+	return 0;
+}
+
+static void solo_fillbuf(struct solo_dev *solo_dev,
+			 struct vb2_buffer *vb)
+{
+	dma_addr_t vbuf;
+	unsigned int fdma_addr;
+	int error = -1;
+	int i;
+
+	vbuf = vb2_dma_contig_plane_dma_addr(vb, 0);
+	if (!vbuf)
+		goto finish_buf;
+
+	if (erase_off(solo_dev)) {
+		void *p = vb2_plane_vaddr(vb, 0);
+		int image_size = solo_image_size(solo_dev);
+
+		for (i = 0; i < image_size; i += 2) {
+			((u8 *)p)[i] = 0x80;
+			((u8 *)p)[i + 1] = 0x00;
+		}
+		error = 0;
+	} else {
+		fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
+				(SOLO_HW_BPL * solo_vlines(solo_dev)));
+
+		error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
+				       solo_bytesperline(solo_dev),
+				       solo_vlines(solo_dev), SOLO_HW_BPL);
+	}
+
+finish_buf:
+	if (!error) {
+		vb2_set_plane_payload(vb, 0,
+			solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
+		vb->v4l2_buf.sequence = solo_dev->sequence++;
+		v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+	}
+
+	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+}
+
+static void solo_thread_try(struct solo_dev *solo_dev)
+{
+	struct solo_vb2_buf *vb;
+
+	/* Only "break" from this loop if slock is held, otherwise
+	 * just return. */
+	for (;;) {
+		unsigned int cur_write;
+
+		cur_write = SOLO_VI_STATUS0_PAGE(
+			solo_reg_read(solo_dev, SOLO_VI_STATUS0));
+		if (cur_write == solo_dev->old_write)
+			return;
+
+		spin_lock(&solo_dev->slock);
+
+		if (list_empty(&solo_dev->vidq_active))
+			break;
+
+		vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf,
+				      list);
+
+		solo_dev->old_write = cur_write;
+		list_del(&vb->list);
+
+		spin_unlock(&solo_dev->slock);
+
+		solo_fillbuf(solo_dev, &vb->vb);
+	}
+
+	assert_spin_locked(&solo_dev->slock);
+	spin_unlock(&solo_dev->slock);
+}
+
+static int solo_thread(void *data)
+{
+	struct solo_dev *solo_dev = data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	set_freezable();
+	add_wait_queue(&solo_dev->disp_thread_wait, &wait);
+
+	for (;;) {
+		long timeout = schedule_timeout_interruptible(HZ);
+
+		if (timeout == -ERESTARTSYS || kthread_should_stop())
+			break;
+		solo_thread_try(solo_dev);
+		try_to_freeze();
+	}
+
+	remove_wait_queue(&solo_dev->disp_thread_wait, &wait);
+
+	return 0;
+}
+
+static int solo_start_thread(struct solo_dev *solo_dev)
+{
+	int ret = 0;
+
+	solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp");
+
+	if (IS_ERR(solo_dev->kthread)) {
+		ret = PTR_ERR(solo_dev->kthread);
+		solo_dev->kthread = NULL;
+		return ret;
+	}
+	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
+
+	return ret;
+}
+
+static void solo_stop_thread(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->kthread)
+		return;
+
+	solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN);
+	kthread_stop(solo_dev->kthread);
+	solo_dev->kthread = NULL;
+}
+
+static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	sizes[0] = solo_image_size(solo_dev);
+	alloc_ctxs[0] = solo_dev->alloc_ctx;
+	*num_planes = 1;
+
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
+
+	return 0;
+}
+
+static int solo_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	solo_dev->sequence = 0;
+	return solo_start_thread(solo_dev);
+}
+
+static void solo_stop_streaming(struct vb2_queue *q)
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	solo_stop_thread(solo_dev);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
+}
+
+static void solo_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
+
+	spin_lock(&solo_dev->slock);
+	list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
+	spin_unlock(&solo_dev->slock);
+	wake_up_interruptible(&solo_dev->disp_thread_wait);
+}
+
+static const struct vb2_ops solo_video_qops = {
+	.queue_setup	= solo_queue_setup,
+	.buf_queue	= solo_buf_queue,
+	.start_streaming = solo_start_streaming,
+	.stop_streaming = solo_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+};
+
+static int solo_querycap(struct file *file, void  *priv,
+			 struct v4l2_capability *cap)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	strcpy(cap->driver, SOLO6X10_NAME);
+	strcpy(cap->card, "Softlogic 6x10");
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(solo_dev->pdev));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int solo_enum_ext_input(struct solo_dev *solo_dev,
+			       struct v4l2_input *input)
+{
+	static const char * const dispnames_1[] = { "4UP" };
+	static const char * const dispnames_2[] = { "4UP-1", "4UP-2" };
+	static const char * const dispnames_5[] = {
+		"4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
+	};
+	const char * const *dispnames;
+
+	if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
+		return -EINVAL;
+
+	if (solo_dev->nr_ext == 5)
+		dispnames = dispnames_5;
+	else if (solo_dev->nr_ext == 2)
+		dispnames = dispnames_2;
+	else
+		dispnames = dispnames_1;
+
+	snprintf(input->name, sizeof(input->name), "Multi %s",
+		 dispnames[input->index - solo_dev->nr_chans]);
+
+	return 0;
+}
+
+static int solo_enum_input(struct file *file, void *priv,
+			   struct v4l2_input *input)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (input->index >= solo_dev->nr_chans) {
+		int ret = solo_enum_ext_input(solo_dev, input);
+
+		if (ret < 0)
+			return ret;
+	} else {
+		snprintf(input->name, sizeof(input->name), "Camera %d",
+			 input->index + 1);
+
+		/* We can only check this for normal inputs */
+		if (!tw28_get_video_status(solo_dev, input->index))
+			input->status = V4L2_IN_ST_NO_SIGNAL;
+	}
+
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+	input->std = solo_dev->vfd->tvnorms;
+	return 0;
+}
+
+static int solo_set_input(struct file *file, void *priv, unsigned int index)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	int ret = solo_v4l2_set_ch(solo_dev, index);
+
+	if (!ret) {
+		while (erase_off(solo_dev))
+			/* Do nothing */;
+	}
+
+	return ret;
+}
+
+static int solo_get_input(struct file *file, void *priv, unsigned int *index)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	*index = solo_dev->cur_disp_ch;
+
+	return 0;
+}
+
+static int solo_enum_fmt_cap(struct file *file, void *priv,
+			     struct v4l2_fmtdesc *f)
+{
+	if (f->index)
+		return -EINVAL;
+
+	f->pixelformat = V4L2_PIX_FMT_UYVY;
+	strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
+
+	return 0;
+}
+
+static int solo_try_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int image_size = solo_image_size(solo_dev);
+
+	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
+		return -EINVAL;
+
+	pix->width = solo_dev->video_hsize;
+	pix->height = solo_vlines(solo_dev);
+	pix->sizeimage = image_size;
+	pix->field = V4L2_FIELD_INTERLACED;
+	pix->pixelformat = V4L2_PIX_FMT_UYVY;
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
+	return 0;
+}
+
+static int solo_set_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (vb2_is_busy(&solo_dev->vidq))
+		return -EBUSY;
+
+	/* For right now, if it doesn't match our running config,
+	 * then fail */
+	return solo_try_fmt_cap(file, priv, f);
+}
+
+static int solo_get_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	pix->width = solo_dev->video_hsize;
+	pix->height = solo_vlines(solo_dev);
+	pix->pixelformat = V4L2_PIX_FMT_UYVY;
+	pix->field = V4L2_FIELD_INTERLACED;
+	pix->sizeimage = solo_image_size(solo_dev);
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->bytesperline = solo_bytesperline(solo_dev);
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_g_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
+	return 0;
+}
+
+int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz)
+{
+	int i;
+
+	/* Make sure all video nodes are idle */
+	if (vb2_is_busy(&solo_dev->vidq))
+		return -EBUSY;
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		if (vb2_is_busy(&solo_dev->v4l2_enc[i]->vidq))
+			return -EBUSY;
+	solo_dev->video_type = is_50hz ? SOLO_VO_FMT_TYPE_PAL :
+					 SOLO_VO_FMT_TYPE_NTSC;
+	/* Reconfigure for the new standard */
+	solo_disp_init(solo_dev);
+	solo_enc_init(solo_dev);
+	solo_tw28_init(solo_dev);
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_update_mode(solo_dev->v4l2_enc[i]);
+	return solo_v4l2_set_ch(solo_dev, solo_dev->cur_disp_ch);
+}
+
+static int solo_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	return solo_set_video_type(solo_dev, std & V4L2_STD_625_50);
+}
+
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct solo_dev *solo_dev =
+		container_of(ctrl->handler, struct solo_dev, disp_hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MOTION_TRACE:
+		if (ctrl->val) {
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
+					SOLO_VI_MOTION_Y_ADD |
+					SOLO_VI_MOTION_Y_VALUE(0x20) |
+					SOLO_VI_MOTION_CB_VALUE(0x10) |
+					SOLO_VI_MOTION_CR_VALUE(0x10));
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
+					SOLO_VI_MOTION_CR_ADD |
+					SOLO_VI_MOTION_Y_VALUE(0x10) |
+					SOLO_VI_MOTION_CB_VALUE(0x80) |
+					SOLO_VI_MOTION_CR_VALUE(0x10));
+		} else {
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
+		}
+		return 0;
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static const struct v4l2_file_operations solo_v4l2_fops = {
+	.owner			= THIS_MODULE,
+	.open			= v4l2_fh_open,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
+	.vidioc_querycap		= solo_querycap,
+	.vidioc_s_std			= solo_s_std,
+	.vidioc_g_std			= solo_g_std,
+	/* Input callbacks */
+	.vidioc_enum_input		= solo_enum_input,
+	.vidioc_s_input			= solo_set_input,
+	.vidioc_g_input			= solo_get_input,
+	/* Video capture format callbacks */
+	.vidioc_enum_fmt_vid_cap	= solo_enum_fmt_cap,
+	.vidioc_try_fmt_vid_cap		= solo_try_fmt_cap,
+	.vidioc_s_fmt_vid_cap		= solo_set_fmt_cap,
+	.vidioc_g_fmt_vid_cap		= solo_get_fmt_cap,
+	/* Streaming I/O */
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
+static struct video_device solo_v4l2_template = {
+	.name			= SOLO6X10_NAME,
+	.fops			= &solo_v4l2_fops,
+	.ioctl_ops		= &solo_v4l2_ioctl_ops,
+	.minor			= -1,
+	.release		= video_device_release,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
+};
+
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_motion_trace_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_TRACE,
+	.name = "Motion Detection Trace",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.step = 1,
+};
+
+int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
+{
+	int ret;
+	int i;
+
+	init_waitqueue_head(&solo_dev->disp_thread_wait);
+	spin_lock_init(&solo_dev->slock);
+	mutex_init(&solo_dev->lock);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
+
+	solo_dev->vfd = video_device_alloc();
+	if (!solo_dev->vfd)
+		return -ENOMEM;
+
+	*solo_dev->vfd = solo_v4l2_template;
+	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_dev->vfd->queue = &solo_dev->vidq;
+	solo_dev->vfd->lock = &solo_dev->lock;
+	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
+	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
+	if (solo_dev->disp_hdl.error) {
+		ret = solo_dev->disp_hdl.error;
+		goto fail;
+	}
+	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
+
+	video_set_drvdata(solo_dev->vfd, solo_dev);
+
+	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_dev->vidq.ops = &solo_video_qops;
+	solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
+	solo_dev->vidq.drv_priv = solo_dev;
+	solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	solo_dev->vidq.gfp_flags = __GFP_DMA32;
+	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_dev->vidq.lock = &solo_dev->lock;
+	ret = vb2_queue_init(&solo_dev->vidq);
+	if (ret < 0)
+		goto fail;
+
+	solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
+	if (IS_ERR(solo_dev->alloc_ctx)) {
+		dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
+		return PTR_ERR(solo_dev->alloc_ctx);
+	}
+
+	/* Cycle all the channels and clear */
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_v4l2_set_ch(solo_dev, i);
+		while (erase_off(solo_dev))
+			/* Do nothing */;
+	}
+
+	/* Set the default display channel */
+	solo_v4l2_set_ch(solo_dev, 0);
+	while (erase_off(solo_dev))
+		/* Do nothing */;
+
+	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
+	if (ret < 0)
+		goto fail;
+
+	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,
+		 solo_dev->nr_chans, solo_dev->nr_ext);
+
+	return 0;
+
+fail:
+	video_device_release(solo_dev->vfd);
+	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
+	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
+	solo_dev->vfd = NULL;
+	return ret;
+}
+
+void solo_v4l2_exit(struct solo_dev *solo_dev)
+{
+	if (solo_dev->vfd == NULL)
+		return;
+
+	video_unregister_device(solo_dev->vfd);
+	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
+	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
+	solo_dev->vfd = NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
--- linux-libre-3.16-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1435 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+#include "solo6x10-jpeg.h"
+
+#define MIN_VID_BUFFERS		2
+#define FRAME_BUF_SIZE		(196 * 1024)
+#define MP4_QS			16
+#define DMA_ALIGN		4096
+
+/* 6010 M4V */
+static unsigned char vop_6010_ntsc_d1[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_ntsc_cif[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_pal_d1[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_pal_cif[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
+};
+
+/* 6110 h.264 */
+static unsigned char vop_6110_ntsc_d1[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
+	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_ntsc_cif[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
+	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_pal_d1[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
+	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_pal_cif[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
+	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
+};
+
+typedef __le32 vop_header[16];
+
+struct solo_enc_buf {
+	enum solo_enc_types	type;
+	const vop_header	*vh;
+	int			motion;
+};
+
+static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	return (solo_dev->motion_mask >> solo_enc->ch) & 1;
+}
+
+static int solo_motion_detected(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	unsigned long flags;
+	u32 ch_mask = 1 << solo_enc->ch;
+	int ret = 0;
+
+	spin_lock_irqsave(&solo_enc->motion_lock, flags);
+	if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
+		solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
+
+	return ret;
+}
+
+static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	u32 mask = 1 << solo_enc->ch;
+	unsigned long flags;
+
+	spin_lock_irqsave(&solo_enc->motion_lock, flags);
+
+	if (on)
+		solo_dev->motion_mask |= mask;
+	else
+		solo_dev->motion_mask &= ~mask;
+
+	solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
+
+	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
+		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
+		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
+
+	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
+}
+
+void solo_update_mode(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	int vop_len;
+	unsigned char *vop;
+
+	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
+	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
+
+	if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
+		solo_enc->width = solo_dev->video_hsize >> 1;
+		solo_enc->height = solo_dev->video_vsize;
+		if (solo_dev->type == SOLO_DEV_6110) {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6110_ntsc_cif;
+				vop_len = sizeof(vop_6110_ntsc_cif);
+			} else {
+				vop = vop_6110_pal_cif;
+				vop_len = sizeof(vop_6110_pal_cif);
+			}
+		} else {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6010_ntsc_cif;
+				vop_len = sizeof(vop_6010_ntsc_cif);
+			} else {
+				vop = vop_6010_pal_cif;
+				vop_len = sizeof(vop_6010_pal_cif);
+			}
+		}
+	} else {
+		solo_enc->width = solo_dev->video_hsize;
+		solo_enc->height = solo_dev->video_vsize << 1;
+		solo_enc->bw_weight <<= 2;
+		if (solo_dev->type == SOLO_DEV_6110) {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6110_ntsc_d1;
+				vop_len = sizeof(vop_6110_ntsc_d1);
+			} else {
+				vop = vop_6110_pal_d1;
+				vop_len = sizeof(vop_6110_pal_d1);
+			}
+		} else {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6010_ntsc_d1;
+				vop_len = sizeof(vop_6010_ntsc_d1);
+			} else {
+				vop = vop_6010_pal_d1;
+				vop_len = sizeof(vop_6010_pal_d1);
+			}
+		}
+	}
+
+	memcpy(solo_enc->vop, vop, vop_len);
+
+	/* Some fixups for 6010/M4V */
+	if (solo_dev->type == SOLO_DEV_6010) {
+		u16 fps = solo_dev->fps * 1000;
+		u16 interval = solo_enc->interval * 1000;
+
+		vop = solo_enc->vop;
+
+		/* Frame rate and interval */
+		vop[22] = fps >> 4;
+		vop[23] = ((fps << 4) & 0xf0) | 0x0c
+			| ((interval >> 13) & 0x3);
+		vop[24] = (interval >> 5) & 0xff;
+		vop[25] = ((interval << 3) & 0xf8) | 0x04;
+	}
+
+	solo_enc->vop_len = vop_len;
+
+	/* Now handle the jpeg header */
+	vop = solo_enc->jpeg_header;
+	vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
+	vop[SOF0_START + 6] = 0xff & solo_enc->height;
+	vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
+	vop[SOF0_START + 8] = 0xff & solo_enc->width;
+
+	memcpy(vop + DQT_START,
+	       jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
+}
+
+static int solo_enc_on(struct solo_enc_dev *solo_enc)
+{
+	u8 ch = solo_enc->ch;
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	u8 interval;
+
+	solo_update_mode(solo_enc);
+
+	/* Make sure to do a bandwidth check */
+	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
+		return -EBUSY;
+	solo_enc->sequence = 0;
+	solo_enc->motion_last_state = false;
+	solo_enc->frames_since_last_motion = 0;
+	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
+
+	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
+
+	/* Disable all encoding for this channel */
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
+
+	/* Common for both std and ext encoding */
+	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
+		       solo_enc->interlaced ? 1 : 0);
+
+	if (solo_enc->interlaced)
+		interval = solo_enc->interval - 1;
+	else
+		interval = solo_enc->interval;
+
+	/* Standard encoding only */
+	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
+	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
+
+	/* Extended encoding only */
+	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
+	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
+
+	/* Enables the standard encoder */
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
+
+	return 0;
+}
+
+static void solo_enc_off(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	solo_dev->enc_bw_remain += solo_enc->bw_weight;
+
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
+}
+
+static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
+			      unsigned int off, unsigned int size)
+{
+	int ret;
+
+	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
+		return -EINVAL;
+
+	/* Single shot */
+	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
+		return solo_p2m_dma_t(solo_dev, 0, dma,
+				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
+				      0, 0);
+	}
+
+	/* Buffer wrap */
+	ret = solo_p2m_dma_t(solo_dev, 0, dma,
+			     SOLO_MP4E_EXT_ADDR(solo_dev) + off,
+			     SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
+
+	if (!ret) {
+		ret = solo_p2m_dma_t(solo_dev, 0,
+			     dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
+			     SOLO_MP4E_EXT_ADDR(solo_dev),
+			     size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
+	}
+
+	return ret;
+}
+
+/* Build a descriptor queue out of an SG list and send it to the P2M for
+ * processing. */
+static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
+			  struct sg_table *vbuf, int off, int size,
+			  unsigned int base, unsigned int base_size)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct scatterlist *sg;
+	int i;
+	int ret;
+
+	if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
+		return -EINVAL;
+
+	solo_enc->desc_count = 1;
+
+	for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
+		struct solo_p2m_desc *desc;
+		dma_addr_t dma;
+		int len;
+		int left = base_size - off;
+
+		desc = &solo_enc->desc_items[solo_enc->desc_count++];
+		dma = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+
+		/* We assume this is smaller than the scatter size */
+		BUG_ON(skip >= len);
+		if (skip) {
+			len -= skip;
+			dma += skip;
+			size -= skip;
+			skip = 0;
+		}
+
+		len = min(len, size);
+
+		if (len <= left) {
+			/* Single descriptor */
+			solo_p2m_fill_desc(desc, 0, dma, base + off,
+					   len, 0, 0);
+		} else {
+			/* Buffer wrap */
+			/* XXX: Do these as separate DMA requests, to avoid
+			   timeout errors triggered by awkwardly sized
+			   descriptors. See
+			   <https://github.com/bluecherrydvr/solo6x10/issues/8>
+			 */
+			ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
+					     left, 0, 0);
+			if (ret)
+				return ret;
+
+			ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
+					     len - left, 0, 0);
+			if (ret)
+				return ret;
+
+			solo_enc->desc_count--;
+		}
+
+		size -= len;
+		if (size <= 0)
+			break;
+
+		off += len;
+		if (off >= base_size)
+			off -= base_size;
+
+		/* Because we may use two descriptors per loop */
+		if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
+			ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
+						solo_enc->desc_dma,
+						solo_enc->desc_count - 1);
+			if (ret)
+				return ret;
+			solo_enc->desc_count = 1;
+		}
+	}
+
+	if (solo_enc->desc_count <= 1)
+		return 0;
+
+	return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
+			solo_enc->desc_dma, solo_enc->desc_count - 1);
+}
+
+/* Extract values from VOP header - VE_STATUSxx */
+static inline int vop_interlaced(const vop_header *vh)
+{
+	return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
+}
+
+static inline u8 vop_channel(const vop_header *vh)
+{
+	return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
+}
+
+static inline u8 vop_type(const vop_header *vh)
+{
+	return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
+}
+
+static inline u32 vop_mpeg_size(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
+}
+
+static inline u8 vop_hsize(const vop_header *vh)
+{
+	return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
+}
+
+static inline u8 vop_vsize(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[1]) & 0xFF;
+}
+
+static inline u32 vop_mpeg_offset(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[2]);
+}
+
+static inline u32 vop_jpeg_offset(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[3]);
+}
+
+static inline u32 vop_jpeg_size(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
+}
+
+static inline u32 vop_sec(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[5]);
+}
+
+static inline u32 vop_usec(const vop_header *vh)
+{
+	return __le32_to_cpu((*vh)[6]);
+}
+
+static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
+			  struct vb2_buffer *vb, const vop_header *vh)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+	int frame_size;
+	int ret;
+
+	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+
+	if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
+		return -EIO;
+
+	frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
+	vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
+
+	/* may discard all previous data in vbuf->sgl */
+	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE))
+		return -ENOMEM;
+	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+			     vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
+			     frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
+			     SOLO_JPEG_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE);
+
+	/* add the header only after dma_unmap_sg() */
+	sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+			    solo_enc->jpeg_header, solo_enc->jpeg_len);
+
+	return ret;
+}
+
+static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
+		struct vb2_buffer *vb, const vop_header *vh)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+	int frame_off, frame_size;
+	int skip = 0;
+	int ret;
+
+	if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
+		return -EIO;
+
+	/* If this is a key frame, add extra header */
+	vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
+		V4L2_BUF_FLAG_BFRAME);
+	if (!vop_type(vh)) {
+		skip = solo_enc->vop_len;
+		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
+			solo_enc->vop_len);
+	} else {
+		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
+	}
+
+	/* Now get the actual mpeg payload */
+	frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
+		sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
+	frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
+
+	/* may discard all previous data in vbuf->sgl */
+	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE))
+		return -ENOMEM;
+	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+			SOLO_MP4E_EXT_ADDR(solo_dev),
+			SOLO_MP4E_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE);
+
+	/* add the header only after dma_unmap_sg() */
+	if (!vop_type(vh))
+		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+				    solo_enc->vop, solo_enc->vop_len);
+	return ret;
+}
+
+static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
+			    struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
+{
+	const vop_header *vh = enc_buf->vh;
+	int ret;
+
+	switch (solo_enc->fmt) {
+	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_H264:
+		ret = solo_fill_mpeg(solo_enc, vb, vh);
+		break;
+	default: /* V4L2_PIX_FMT_MJPEG */
+		ret = solo_fill_jpeg(solo_enc, vb, vh);
+		break;
+	}
+
+	if (!ret) {
+		bool send_event = false;
+
+		vb->v4l2_buf.sequence = solo_enc->sequence++;
+		vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
+		vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
+
+		/* Check for motion flags */
+		if (solo_is_motion_on(solo_enc)) {
+			/* It takes a few frames for the hardware to detect
+			 * motion. Once it does it clears the motion detection
+			 * register and it takes again a few frames before
+			 * motion is seen. This means in practice that when the
+			 * motion field is 1, it will go back to 0 for the next
+			 * frame. This leads to motion detection event being
+			 * sent all the time, which is not what we want.
+			 * Instead wait a few frames before deciding that the
+			 * motion has halted. After some experimentation it
+			 * turns out that waiting for 5 frames works well.
+			 */
+			if (enc_buf->motion == 0 &&
+			    solo_enc->motion_last_state &&
+			    solo_enc->frames_since_last_motion++ > 5)
+				send_event = true;
+			else if (enc_buf->motion) {
+				solo_enc->frames_since_last_motion = 0;
+				send_event = !solo_enc->motion_last_state;
+			}
+		}
+
+		if (send_event) {
+			struct v4l2_event ev = {
+				.type = V4L2_EVENT_MOTION_DET,
+				.u.motion_det = {
+					.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+					.frame_sequence = vb->v4l2_buf.sequence,
+					.region_mask = enc_buf->motion ? 1 : 0,
+				},
+			};
+
+			solo_enc->motion_last_state = enc_buf->motion;
+			solo_enc->frames_since_last_motion = 0;
+			v4l2_event_queue(solo_enc->vfd, &ev);
+		}
+	}
+
+	vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+
+	return ret;
+}
+
+static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
+				struct solo_enc_buf *enc_buf)
+{
+	struct solo_vb2_buf *vb;
+	unsigned long flags;
+
+	mutex_lock(&solo_enc->lock);
+	if (solo_enc->type != enc_buf->type)
+		goto unlock;
+
+	spin_lock_irqsave(&solo_enc->av_lock, flags);
+	if (list_empty(&solo_enc->vidq_active)) {
+		spin_unlock_irqrestore(&solo_enc->av_lock, flags);
+		goto unlock;
+	}
+	vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
+		list);
+	list_del(&vb->list);
+	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
+
+	solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
+unlock:
+	mutex_unlock(&solo_enc->lock);
+}
+
+void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
+{
+	wake_up_interruptible_all(&solo_dev->ring_thread_wait);
+}
+
+static void solo_handle_ring(struct solo_dev *solo_dev)
+{
+	for (;;) {
+		struct solo_enc_dev *solo_enc;
+		struct solo_enc_buf enc_buf;
+		u32 mpeg_current, off;
+		u8 ch;
+		u8 cur_q;
+
+		/* Check if the hardware has any new ones in the queue */
+		cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
+		if (cur_q == solo_dev->enc_idx)
+			break;
+
+		mpeg_current = solo_reg_read(solo_dev,
+					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
+		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
+
+		ch = (mpeg_current >> 24) & 0x1f;
+		off = mpeg_current & 0x00ffffff;
+
+		if (ch >= SOLO_MAX_CHANNELS) {
+			ch -= SOLO_MAX_CHANNELS;
+			enc_buf.type = SOLO_ENC_TYPE_EXT;
+		} else
+			enc_buf.type = SOLO_ENC_TYPE_STD;
+
+		solo_enc = solo_dev->v4l2_enc[ch];
+		if (solo_enc == NULL) {
+			dev_err(&solo_dev->pdev->dev,
+				"Got spurious packet for channel %d\n", ch);
+			continue;
+		}
+
+		/* FAIL... */
+		if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
+				     sizeof(vop_header)))
+			continue;
+
+		enc_buf.vh = solo_dev->vh_buf;
+
+		/* Sanity check */
+		if (vop_mpeg_offset(enc_buf.vh) !=
+			SOLO_MP4E_EXT_ADDR(solo_dev) + off)
+			continue;
+
+		if (solo_motion_detected(solo_enc))
+			enc_buf.motion = 1;
+		else
+			enc_buf.motion = 0;
+
+		solo_enc_handle_one(solo_enc, &enc_buf);
+	}
+}
+
+static int solo_ring_thread(void *data)
+{
+	struct solo_dev *solo_dev = data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	set_freezable();
+	add_wait_queue(&solo_dev->ring_thread_wait, &wait);
+
+	for (;;) {
+		long timeout = schedule_timeout_interruptible(HZ);
+
+		if (timeout == -ERESTARTSYS || kthread_should_stop())
+			break;
+		solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
+		solo_handle_ring(solo_dev);
+		solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
+		try_to_freeze();
+	}
+
+	remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
+
+	return 0;
+}
+
+static int solo_enc_queue_setup(struct vb2_queue *q,
+				const struct v4l2_format *fmt,
+				unsigned int *num_buffers,
+				unsigned int *num_planes, unsigned int sizes[],
+				void *alloc_ctxs[])
+{
+	sizes[0] = FRAME_BUF_SIZE;
+	*num_planes = 1;
+
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
+
+	return 0;
+}
+
+static void solo_enc_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
+
+	spin_lock(&solo_enc->av_lock);
+	list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
+	spin_unlock(&solo_enc->av_lock);
+}
+
+static int solo_ring_start(struct solo_dev *solo_dev)
+{
+	solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
+					    SOLO6X10_NAME "_ring");
+	if (IS_ERR(solo_dev->ring_thread)) {
+		int err = PTR_ERR(solo_dev->ring_thread);
+
+		solo_dev->ring_thread = NULL;
+		return err;
+	}
+
+	solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
+
+	return 0;
+}
+
+static void solo_ring_stop(struct solo_dev *solo_dev)
+{
+	if (solo_dev->ring_thread) {
+		kthread_stop(solo_dev->ring_thread);
+		solo_dev->ring_thread = NULL;
+	}
+
+	solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
+}
+
+static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+	int ret;
+
+	ret = solo_enc_on(solo_enc);
+	if (ret)
+		return ret;
+	return solo_ring_start(solo_enc->solo_dev);
+}
+
+static void solo_enc_stop_streaming(struct vb2_queue *q)
+{
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+
+	solo_enc_off(solo_enc);
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_ring_stop(solo_enc->solo_dev);
+}
+
+static struct vb2_ops solo_enc_video_qops = {
+	.queue_setup	= solo_enc_queue_setup,
+	.buf_queue	= solo_enc_buf_queue,
+	.start_streaming = solo_enc_start_streaming,
+	.stop_streaming = solo_enc_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+};
+
+static int solo_enc_querycap(struct file *file, void  *priv,
+			     struct v4l2_capability *cap)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	strcpy(cap->driver, SOLO6X10_NAME);
+	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
+		 solo_enc->ch);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(solo_dev->pdev));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int solo_enc_enum_input(struct file *file, void *priv,
+			       struct v4l2_input *input)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (input->index)
+		return -EINVAL;
+
+	snprintf(input->name, sizeof(input->name), "Encoder %d",
+		 solo_enc->ch + 1);
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+	input->std = solo_enc->vfd->tvnorms;
+
+	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
+		input->status = V4L2_IN_ST_NO_SIGNAL;
+
+	return 0;
+}
+
+static int solo_enc_set_input(struct file *file, void *priv,
+			      unsigned int index)
+{
+	if (index)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int solo_enc_get_input(struct file *file, void *priv,
+			      unsigned int *index)
+{
+	*index = 0;
+
+	return 0;
+}
+
+static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
+				 struct v4l2_fmtdesc *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	int dev_type = solo_enc->solo_dev->type;
+
+	switch (f->index) {
+	case 0:
+		switch (dev_type) {
+		case SOLO_DEV_6010:
+			f->pixelformat = V4L2_PIX_FMT_MPEG4;
+			strcpy(f->description, "MPEG-4 part 2");
+			break;
+		case SOLO_DEV_6110:
+			f->pixelformat = V4L2_PIX_FMT_H264;
+			strcpy(f->description, "H.264");
+			break;
+		}
+		break;
+	case 1:
+		f->pixelformat = V4L2_PIX_FMT_MJPEG;
+		strcpy(f->description, "MJPEG");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+
+	return 0;
+}
+
+static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
+{
+	return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
+		|| (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
+		|| pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
+}
+
+static int solo_enc_try_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
+		return -EINVAL;
+
+	if (pix->width < solo_dev->video_hsize ||
+	    pix->height < solo_dev->video_vsize << 1) {
+		/* Default to CIF 1/2 size */
+		pix->width = solo_dev->video_hsize >> 1;
+		pix->height = solo_dev->video_vsize;
+	} else {
+		/* Full frame */
+		pix->width = solo_dev->video_hsize;
+		pix->height = solo_dev->video_vsize << 1;
+	}
+
+	switch (pix->field) {
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_ANY:
+	default:
+		pix->field = V4L2_FIELD_INTERLACED;
+		break;
+	}
+
+	/* Just set these */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->bytesperline = 0;
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_enc_set_fmt_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int ret;
+
+	if (vb2_is_busy(&solo_enc->vidq))
+		return -EBUSY;
+
+	ret = solo_enc_try_fmt_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	if (pix->width == solo_dev->video_hsize)
+		solo_enc->mode = SOLO_ENC_MODE_D1;
+	else
+		solo_enc->mode = SOLO_ENC_MODE_CIF;
+
+	/* This does not change the encoder at all */
+	solo_enc->fmt = pix->pixelformat;
+
+	/*
+	 * More information is needed about these 'extended' types. As far
+	 * as I can tell these are basically additional video streams with
+	 * different MPEG encoding attributes that can run in parallel with
+	 * the main stream. If so, then this should be implemented as a
+	 * second video node. Abusing priv like this is certainly not the
+	 * right approach.
+	if (pix->priv)
+		solo_enc->type = SOLO_ENC_TYPE_EXT;
+	 */
+	solo_update_mode(solo_enc);
+	return 0;
+}
+
+static int solo_enc_get_fmt_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	pix->width = solo_enc->width;
+	pix->height = solo_enc->height;
+	pix->pixelformat = solo_enc->fmt;
+	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
+		     V4L2_FIELD_NONE;
+	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
+	return 0;
+}
+
+static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+
+	return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
+}
+
+static int solo_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
+		return -EINVAL;
+
+	switch (fsize->index) {
+	case 0:
+		fsize->discrete.width = solo_dev->video_hsize >> 1;
+		fsize->discrete.height = solo_dev->video_vsize;
+		break;
+	case 1:
+		fsize->discrete.width = solo_dev->video_hsize;
+		fsize->discrete.height = solo_dev->video_vsize << 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+	return 0;
+}
+
+static int solo_enum_frameintervals(struct file *file, void *priv,
+				    struct v4l2_frmivalenum *fintv)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
+		return -EINVAL;
+	if (fintv->index)
+		return -EINVAL;
+	if ((fintv->width != solo_dev->video_hsize >> 1 ||
+	     fintv->height != solo_dev->video_vsize) &&
+	    (fintv->width != solo_dev->video_hsize ||
+	     fintv->height != solo_dev->video_vsize << 1))
+		return -EINVAL;
+
+	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+
+	fintv->stepwise.min.numerator = 1;
+	fintv->stepwise.min.denominator = solo_dev->fps;
+
+	fintv->stepwise.max.numerator = 15;
+	fintv->stepwise.max.denominator = solo_dev->fps;
+
+	fintv->stepwise.step.numerator = 1;
+	fintv->stepwise.step.denominator = solo_dev->fps;
+
+	return 0;
+}
+
+static int solo_g_parm(struct file *file, void *priv,
+		       struct v4l2_streamparm *sp)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = solo_enc->interval;
+	cp->timeperframe.denominator = solo_enc->solo_dev->fps;
+	cp->capturemode = 0;
+	/* XXX: Shouldn't we be able to get/set this from videobuf? */
+	cp->readbuffers = 2;
+
+	return 0;
+}
+
+static inline int calc_interval(u8 fps, u32 n, u32 d)
+{
+	if (!n || !d)
+		return 1;
+	if (d == fps)
+		return n;
+	n *= fps;
+	return min(15U, n / d + (n % d >= (fps >> 1)));
+}
+
+static int solo_s_parm(struct file *file, void *priv,
+		       struct v4l2_streamparm *sp)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct v4l2_fract *t = &sp->parm.capture.timeperframe;
+	u8 fps = solo_enc->solo_dev->fps;
+
+	if (vb2_is_streaming(&solo_enc->vidq))
+		return -EBUSY;
+
+	solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
+	solo_update_mode(solo_enc);
+	return solo_g_parm(file, priv, sp);
+}
+
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct solo_enc_dev *solo_enc =
+		container_of(ctrl->handler, struct solo_enc_dev, hdl);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	int err;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+	case V4L2_CID_SHARPNESS:
+		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
+					 ctrl->val);
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		solo_enc->gop = ctrl->val;
+		solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
+		solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
+		return 0;
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		solo_enc->qp = ctrl->val;
+		solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
+		solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
+		return 0;
+	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
+		solo_enc->motion_thresh = ctrl->val << 8;
+		if (!solo_enc->motion_global || !solo_enc->motion_enabled)
+			return 0;
+		return solo_set_motion_threshold(solo_dev, solo_enc->ch,
+				solo_enc->motion_thresh);
+	case V4L2_CID_DETECT_MD_MODE:
+		solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
+		solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
+		if (ctrl->val) {
+			if (solo_enc->motion_global)
+				err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
+					solo_enc->motion_thresh);
+			else
+				err = solo_set_motion_block(solo_dev, solo_enc->ch,
+					solo_enc->md_thresholds->p_cur.p_u16);
+			if (err)
+				return err;
+		}
+		solo_motion_toggle(solo_enc, ctrl->val);
+		return 0;
+	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+		if (solo_enc->motion_enabled && !solo_enc->motion_global)
+			return solo_set_motion_block(solo_dev, solo_enc->ch,
+					solo_enc->md_thresholds->p_new.p_u16);
+		break;
+	case V4L2_CID_OSD_TEXT:
+		strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
+		return solo_osd_print(solo_enc);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int solo_subscribe_event(struct v4l2_fh *fh,
+				const struct v4l2_event_subscription *sub)
+{
+
+	switch (sub->type) {
+	case V4L2_EVENT_CTRL:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	case V4L2_EVENT_MOTION_DET:
+		/* Allow for up to 30 events (1 second for NTSC) to be
+		 * stored. */
+		return v4l2_event_subscribe(fh, sub, 30, NULL);
+	}
+	return -EINVAL;
+}
+
+static const struct v4l2_file_operations solo_enc_fops = {
+	.owner			= THIS_MODULE,
+	.open			= v4l2_fh_open,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
+	.vidioc_querycap		= solo_enc_querycap,
+	.vidioc_s_std			= solo_enc_s_std,
+	.vidioc_g_std			= solo_enc_g_std,
+	/* Input callbacks */
+	.vidioc_enum_input		= solo_enc_enum_input,
+	.vidioc_s_input			= solo_enc_set_input,
+	.vidioc_g_input			= solo_enc_get_input,
+	/* Video capture format callbacks */
+	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
+	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
+	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
+	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
+	/* Streaming I/O */
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	/* Frame size and interval */
+	.vidioc_enum_framesizes		= solo_enum_framesizes,
+	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
+	/* Video capture parameters */
+	.vidioc_s_parm			= solo_s_parm,
+	.vidioc_g_parm			= solo_g_parm,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= solo_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
+static const struct video_device solo_enc_template = {
+	.name			= SOLO6X10_NAME,
+	.fops			= &solo_enc_fops,
+	.ioctl_ops		= &solo_enc_ioctl_ops,
+	.minor			= -1,
+	.release		= video_device_release,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
+};
+
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_OSD_TEXT,
+	.name = "OSD Text",
+	.type = V4L2_CTRL_TYPE_STRING,
+	.max = OSD_TEXT_MAX,
+	.step = 1,
+};
+
+/* Motion Detection Threshold matrix */
+static const struct v4l2_ctrl_config solo_md_thresholds = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
+	.dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
+	.def = SOLO_DEF_MOT_THRESH,
+	.max = 65535,
+	.step = 1,
+};
+
+static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
+					   u8 ch, unsigned nr)
+{
+	struct solo_enc_dev *solo_enc;
+	struct v4l2_ctrl_handler *hdl;
+	int ret;
+
+	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
+	if (!solo_enc)
+		return ERR_PTR(-ENOMEM);
+
+	hdl = &solo_enc->hdl;
+	v4l2_ctrl_handler_init(hdl, 10);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_HUE, 0, 255, 1, 128);
+	if (tw28_has_sharpness(solo_dev, ch))
+		v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0, 15, 1, 0);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
+	v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
+			V4L2_CID_DETECT_MD_MODE,
+			V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
+			V4L2_DETECT_MD_MODE_DISABLED);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
+			SOLO_DEF_MOT_THRESH >> 8);
+	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+	solo_enc->md_thresholds =
+		v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
+	if (hdl->error) {
+		ret = hdl->error;
+		goto hdl_free;
+	}
+
+	solo_enc->solo_dev = solo_dev;
+	solo_enc->ch = ch;
+	mutex_init(&solo_enc->lock);
+	spin_lock_init(&solo_enc->av_lock);
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
+		V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
+	solo_enc->type = SOLO_ENC_TYPE_STD;
+
+	solo_enc->qp = SOLO_DEFAULT_QP;
+	solo_enc->gop = solo_dev->fps;
+	solo_enc->interval = 1;
+	solo_enc->mode = SOLO_ENC_MODE_CIF;
+	solo_enc->motion_global = true;
+	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
+	solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_enc->vidq.ops = &solo_enc_video_qops;
+	solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
+	solo_enc->vidq.drv_priv = solo_enc;
+	solo_enc->vidq.gfp_flags = __GFP_DMA32;
+	solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_enc->vidq.lock = &solo_enc->lock;
+	ret = vb2_queue_init(&solo_enc->vidq);
+	if (ret)
+		goto hdl_free;
+	solo_update_mode(solo_enc);
+
+	spin_lock_init(&solo_enc->motion_lock);
+
+	/* Initialize this per encoder */
+	solo_enc->jpeg_len = sizeof(jpeg_header);
+	memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
+
+	solo_enc->desc_nelts = 32;
+	solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
+				      sizeof(struct solo_p2m_desc) *
+				      solo_enc->desc_nelts,
+				      &solo_enc->desc_dma);
+	ret = -ENOMEM;
+	if (solo_enc->desc_items == NULL)
+		goto hdl_free;
+
+	solo_enc->vfd = video_device_alloc();
+	if (!solo_enc->vfd)
+		goto pci_free;
+
+	*solo_enc->vfd = solo_enc_template;
+	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_enc->vfd->ctrl_handler = hdl;
+	solo_enc->vfd->queue = &solo_enc->vidq;
+	solo_enc->vfd->lock = &solo_enc->lock;
+	video_set_drvdata(solo_enc->vfd, solo_enc);
+	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
+	if (ret < 0)
+		goto vdev_release;
+
+	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
+		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
+		 solo_enc->vfd->num);
+
+	return solo_enc;
+
+vdev_release:
+	video_device_release(solo_enc->vfd);
+pci_free:
+	pci_free_consistent(solo_enc->solo_dev->pdev,
+			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
+			solo_enc->desc_items, solo_enc->desc_dma);
+hdl_free:
+	v4l2_ctrl_handler_free(hdl);
+	kfree(solo_enc);
+	return ERR_PTR(ret);
+}
+
+static void solo_enc_free(struct solo_enc_dev *solo_enc)
+{
+	if (solo_enc == NULL)
+		return;
+
+	video_unregister_device(solo_enc->vfd);
+	v4l2_ctrl_handler_free(&solo_enc->hdl);
+	kfree(solo_enc);
+}
+
+int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
+{
+	int i;
+
+	init_waitqueue_head(&solo_dev->ring_thread_wait);
+
+	solo_dev->vh_size = sizeof(vop_header);
+	solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
+						solo_dev->vh_size,
+						&solo_dev->vh_dma);
+	if (solo_dev->vh_buf == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
+		if (IS_ERR(solo_dev->v4l2_enc[i]))
+			break;
+	}
+
+	if (i != solo_dev->nr_chans) {
+		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
+
+		while (i--)
+			solo_enc_free(solo_dev->v4l2_enc[i]);
+		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
+				    solo_dev->vh_buf, solo_dev->vh_dma);
+		solo_dev->vh_buf = NULL;
+		return ret;
+	}
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
+	else
+		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
+
+	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
+		 solo_dev->v4l2_enc[0]->vfd->num,
+		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
+
+	return 0;
+}
+
+void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_enc_free(solo_dev->v4l2_enc[i]);
+
+	if (solo_dev->vh_buf)
+		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
+			    solo_dev->vh_buf, solo_dev->vh_dma);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/sta2x11/sta2x11_vip.c linux-libre-3.17-rc7-gnu/drivers/media/pci/sta2x11/sta2x11_vip.c
--- linux-libre-3.16-gnu/drivers/media/pci/sta2x11/sta2x11_vip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/sta2x11/sta2x11_vip.c	2014-09-28 17:29:07.000000000 -0400
@@ -640,7 +640,6 @@ static int vidioc_try_fmt_vid_cap(struct
 	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 	f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1093,7 +1092,6 @@ static int sta2x11_vip_init_one(struct p
 	vip->video_dev = &video_dev_template;
 	vip->video_dev->v4l2_dev = &vip->v4l2_dev;
 	vip->video_dev->queue = &vip->vb_vidq;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vip->video_dev->flags);
 	video_set_drvdata(vip->video_dev, vip);
 
 	ret = video_register_device(vip->video_dev, VFL_TYPE_GRABBER, -1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/ttpci/budget-ci.c linux-libre-3.17-rc7-gnu/drivers/media/pci/ttpci/budget-ci.c
--- linux-libre-3.16-gnu/drivers/media/pci/ttpci/budget-ci.c	2014-08-07 04:49:22.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/ttpci/budget-ci.c	2014-09-28 21:30:30.000000000 -0400
@@ -161,14 +161,14 @@ static void msp430_ir_interrupt(unsigned
 		return;
 
 	if (budget_ci->ir.full_rc5) {
-		rc_keydown(dev,
-			   budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
-			   (command & 0x20) ? 1 : 0);
+		rc_keydown(dev, RC_TYPE_RC5,
+			   RC_SCANCODE_RC5(budget_ci->ir.rc5_device, budget_ci->ir.ir_key),
+			   !!(command & 0x20));
 		return;
 	}
 
 	/* FIXME: We should generate complete scancodes for all devices */
-	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
+	rc_keydown(dev, RC_TYPE_UNKNOWN, budget_ci->ir.ir_key, !!(command & 0x20));
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
@@ -234,7 +234,7 @@ static int msp430_ir_init(struct budget_
 		break;
 	}
 	if (!budget_ci->ir.full_rc5)
-		dev->scanmask = 0xff;
+		dev->scancode_mask = 0xff;
 
 	error = rc_register_device(dev);
 	if (error) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/pci/zoran/zr36050.h linux-libre-3.17-rc7-gnu/drivers/media/pci/zoran/zr36050.h
--- linux-libre-3.16-gnu/drivers/media/pci/zoran/zr36050.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/pci/zoran/zr36050.h	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,6 @@ struct zr36050 {
 /* zr36050 mode register bits */
 
 #define ZR050_MO_COMP                0x80
-#define ZR050_MO_COMP                0x80
 #define ZR050_MO_ATP                 0x40
 #define ZR050_MO_PASS2               0x20
 #define ZR050_MO_TLM                 0x10
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/arv.c linux-libre-3.17-rc7-gnu/drivers/media/platform/arv.c
--- linux-libre-3.16-gnu/drivers/media/platform/arv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/arv.c	2014-09-28 17:29:07.000000000 -0400
@@ -773,7 +773,6 @@ static int __init ar_init(void)
 	ar->vdev.fops = &ar_fops;
 	ar->vdev.ioctl_ops = &ar_ioctl_ops;
 	ar->vdev.release = video_device_release_empty;
-	set_bit(V4L2_FL_USE_FH_PRIO, &ar->vdev.flags);
 	video_set_drvdata(&ar->vdev, ar);
 
 	if (vga) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/blackfin/bfin_capture.c linux-libre-3.17-rc7-gnu/drivers/media/platform/blackfin/bfin_capture.c
--- linux-libre-3.16-gnu/drivers/media/platform/blackfin/bfin_capture.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/blackfin/bfin_capture.c	2014-09-28 17:29:07.000000000 -0400
@@ -446,7 +446,7 @@ static void bcap_stop_streaming(struct v
 	while (!list_empty(&bcap_dev->dma_queue)) {
 		bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
 						struct bcap_buffer, list);
-		list_del(&bcap_dev->cur_frm->list);
+		list_del_init(&bcap_dev->cur_frm->list);
 		vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
 	}
 }
@@ -533,7 +533,7 @@ static irqreturn_t bcap_isr(int irq, voi
 		}
 		bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
 				struct bcap_buffer, list);
-		list_del(&bcap_dev->cur_frm->list);
+		list_del_init(&bcap_dev->cur_frm->list);
 	} else {
 		/* clear error flag, we will get a new frame */
 		if (ppi->err)
@@ -583,7 +583,7 @@ static int bcap_streamon(struct file *fi
 	bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
 					struct bcap_buffer, list);
 	/* remove buffer from the dma queue */
-	list_del(&bcap_dev->cur_frm->list);
+	list_del_init(&bcap_dev->cur_frm->list);
 	addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
 	/* update DMA address */
 	ppi->ops->update_addr(ppi, (unsigned long)addr);
@@ -939,7 +939,7 @@ static int bcap_probe(struct platform_de
 
 	bcap_dev->cfg = config;
 
-	bcap_dev->ppi = ppi_create_instance(config->ppi_info);
+	bcap_dev->ppi = ppi_create_instance(pdev, config->ppi_info);
 	if (!bcap_dev->ppi) {
 		v4l2_err(pdev->dev.driver, "Unable to create ppi\n");
 		ret = -ENODEV;
@@ -966,7 +966,6 @@ static int bcap_probe(struct platform_de
 	vfd->ioctl_ops          = &bcap_ioctl_ops;
 	vfd->tvnorms            = 0;
 	vfd->v4l2_dev           = &bcap_dev->v4l2_dev;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name));
 	bcap_dev->video_dev     = vfd;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/blackfin/ppi.c linux-libre-3.17-rc7-gnu/drivers/media/platform/blackfin/ppi.c
--- linux-libre-3.16-gnu/drivers/media/platform/blackfin/ppi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/blackfin/ppi.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/platform_device.h>
 
 #include <asm/bfin_ppi.h>
 #include <asm/blackfin.h>
@@ -205,6 +206,20 @@ static int ppi_set_params(struct ppi_if
 	int dma_config, bytes_per_line;
 	int hcount, hdelay, samples_per_line;
 
+#ifdef CONFIG_PINCTRL
+	static const char * const pin_state[] = {"8bit", "16bit", "24bit"};
+	struct pinctrl *pctrl;
+	struct pinctrl_state *pstate;
+
+	if (params->dlen > 24 || params->dlen <= 0)
+		return -EINVAL;
+	pctrl = devm_pinctrl_get(ppi->dev);
+	pstate = pinctrl_lookup_state(pctrl,
+				      pin_state[(params->dlen + 7) / 8 - 1]);
+	if (pinctrl_select_state(pctrl, pstate))
+		return -EINVAL;
+#endif
+
 	bytes_per_line = params->width * params->bpp / 8;
 	/* convert parameters unit from pixels to samples */
 	hcount = params->width * params->bpp / params->dlen;
@@ -307,26 +322,30 @@ static void ppi_update_addr(struct ppi_i
 	set_dma_start_addr(ppi->info->dma_ch, addr);
 }
 
-struct ppi_if *ppi_create_instance(const struct ppi_info *info)
+struct ppi_if *ppi_create_instance(struct platform_device *pdev,
+			const struct ppi_info *info)
 {
 	struct ppi_if *ppi;
 
 	if (!info || !info->pin_req)
 		return NULL;
 
+#ifndef CONFIG_PINCTRL
 	if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) {
-		pr_err("request peripheral failed\n");
+		dev_err(&pdev->dev, "request peripheral failed\n");
 		return NULL;
 	}
+#endif
 
 	ppi = kzalloc(sizeof(*ppi), GFP_KERNEL);
 	if (!ppi) {
 		peripheral_free_list(info->pin_req);
-		pr_err("unable to allocate memory for ppi handle\n");
+		dev_err(&pdev->dev, "unable to allocate memory for ppi handle\n");
 		return NULL;
 	}
 	ppi->ops = &ppi_ops;
 	ppi->info = info;
+	ppi->dev = &pdev->dev;
 
 	pr_info("ppi probe success\n");
 	return ppi;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/coda.c linux-libre-3.17-rc7-gnu/drivers/media/platform/coda.c
--- linux-libre-3.16-gnu/drivers/media/platform/coda.c	2014-08-07 04:49:53.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/coda.c	2014-09-28 21:31:06.000000000 -0400
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/genalloc.h>
@@ -22,10 +23,12 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/of.h>
 #include <linux/platform_data/coda.h>
+#include <linux/reset.h>
 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -41,22 +44,18 @@
 
 #define CODADX6_MAX_INSTANCES	4
 
-#define CODA_FMO_BUF_SIZE	32
-#define CODADX6_WORK_BUF_SIZE	(288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
-#define CODA7_WORK_BUF_SIZE	(128 * 1024)
-#define CODA7_TEMP_BUF_SIZE	(304 * 1024)
 #define CODA_PARA_BUF_SIZE	(10 * 1024)
 #define CODA_ISRAM_SIZE	(2048 * 2)
-#define CODADX6_IRAM_SIZE	0xb000
-#define CODA7_IRAM_SIZE		0x14000
 
 #define CODA7_PS_BUF_SIZE	0x28000
+#define CODA9_PS_SAVE_SIZE	(512 * 1024)
 
 #define CODA_MAX_FRAMEBUFFERS	8
 
 #define CODA_MAX_FRAME_SIZE	0x100000
 #define FMO_SLICE_SAVE_BUF_SIZE         (32)
 #define CODA_DEFAULT_GAMMA		4096
+#define CODA9_DEFAULT_GAMMA		24576	/* 0.75 * 32768 */
 
 #define MIN_W 176
 #define MIN_H 144
@@ -84,6 +83,7 @@ enum coda_inst_type {
 enum coda_product {
 	CODA_DX6 = 0xf001,
 	CODA_7541 = 0xf012,
+	CODA_960 = 0xf020,
 };
 
 struct coda_fmt {
@@ -105,20 +105,26 @@ struct coda_devtype {
 	struct coda_codec	*codecs;
 	unsigned int		num_codecs;
 	size_t			workbuf_size;
+	size_t			tempbuf_size;
+	size_t			iram_size;
 };
 
 /* Per-queue, driver-specific private data */
 struct coda_q_data {
 	unsigned int		width;
 	unsigned int		height;
+	unsigned int		bytesperline;
 	unsigned int		sizeimage;
 	unsigned int		fourcc;
+	struct v4l2_rect	rect;
 };
 
 struct coda_aux_buf {
 	void			*vaddr;
 	dma_addr_t		paddr;
 	u32			size;
+	struct debugfs_blob_wrapper blob;
+	struct dentry		*dentry;
 };
 
 struct coda_dev {
@@ -130,32 +136,38 @@ struct coda_dev {
 	void __iomem		*regs_base;
 	struct clk		*clk_per;
 	struct clk		*clk_ahb;
+	struct reset_control	*rstc;
 
 	struct coda_aux_buf	codebuf;
 	struct coda_aux_buf	tempbuf;
 	struct coda_aux_buf	workbuf;
 	struct gen_pool		*iram_pool;
-	long unsigned int	iram_vaddr;
-	long unsigned int	iram_paddr;
-	unsigned long		iram_size;
+	struct coda_aux_buf	iram;
 
 	spinlock_t		irqlock;
 	struct mutex		dev_mutex;
 	struct mutex		coda_mutex;
+	struct workqueue_struct	*workqueue;
 	struct v4l2_m2m_dev	*m2m_dev;
 	struct vb2_alloc_ctx	*alloc_ctx;
 	struct list_head	instances;
 	unsigned long		instance_mask;
-	struct delayed_work	timeout;
+	struct dentry		*debugfs_root;
 };
 
 struct coda_params {
 	u8			rot_mode;
 	u8			h264_intra_qp;
 	u8			h264_inter_qp;
+	u8			h264_min_qp;
+	u8			h264_max_qp;
+	u8			h264_deblk_enabled;
+	u8			h264_deblk_alpha;
+	u8			h264_deblk_beta;
 	u8			mpeg4_intra_qp;
 	u8			mpeg4_inter_qp;
 	u8			gop_size;
+	int			intra_refresh;
 	int			codec_mode;
 	int			codec_mode_aux;
 	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
@@ -175,13 +187,34 @@ struct coda_iram_info {
 	phys_addr_t	buf_btp_use;
 	phys_addr_t	search_ram_paddr;
 	int		search_ram_size;
+	int		remaining;
+	phys_addr_t	next_paddr;
+};
+
+struct gdi_tiled_map {
+	int xy2ca_map[16];
+	int xy2ba_map[16];
+	int xy2ra_map[16];
+	int rbc2axi_map[32];
+	int xy2rbc_config;
+	int map_type;
+#define GDI_LINEAR_FRAME_MAP 0
+};
+
+struct coda_timestamp {
+	struct list_head	list;
+	u32			sequence;
+	struct v4l2_timecode	timecode;
+	struct timeval		timestamp;
 };
 
 struct coda_ctx {
 	struct coda_dev			*dev;
 	struct mutex			buffer_mutex;
 	struct list_head		list;
-	struct work_struct		skip_run;
+	struct work_struct		pic_run_work;
+	struct work_struct		seq_end_work;
+	struct completion		completion;
 	int				aborting;
 	int				initialized;
 	int				streamon_out;
@@ -189,12 +222,12 @@ struct coda_ctx {
 	u32				isequence;
 	u32				qsequence;
 	u32				osequence;
+	u32				sequence_offset;
 	struct coda_q_data		q_data[2];
 	enum coda_inst_type		inst_type;
 	struct coda_codec		*codec;
 	enum v4l2_colorspace		colorspace;
 	struct coda_params		params;
-	struct v4l2_m2m_ctx		*m2m_ctx;
 	struct v4l2_ctrl_handler	ctrls;
 	struct v4l2_fh			fh;
 	int				gopcounter;
@@ -204,19 +237,26 @@ struct coda_ctx {
 	struct kfifo			bitstream_fifo;
 	struct mutex			bitstream_mutex;
 	struct coda_aux_buf		bitstream;
-	bool				prescan_failed;
+	bool				hold;
 	struct coda_aux_buf		parabuf;
 	struct coda_aux_buf		psbuf;
 	struct coda_aux_buf		slicebuf;
 	struct coda_aux_buf		internal_frames[CODA_MAX_FRAMEBUFFERS];
+	u32				frame_types[CODA_MAX_FRAMEBUFFERS];
+	struct coda_timestamp		frame_timestamps[CODA_MAX_FRAMEBUFFERS];
+	u32				frame_errors[CODA_MAX_FRAMEBUFFERS];
+	struct list_head		timestamp_list;
 	struct coda_aux_buf		workbuf;
 	int				num_internal_frames;
 	int				idx;
 	int				reg_idx;
 	struct coda_iram_info		iram_info;
+	struct gdi_tiled_map		tiled_map;
 	u32				bit_stream_param;
 	u32				frm_dis_flg;
+	u32				frame_mem_ctrl;
 	int				display_idx;
+	struct dentry			*debugfs_entry;
 };
 
 static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
@@ -264,15 +304,23 @@ static void coda_command_async(struct co
 {
 	struct coda_dev *dev = ctx->dev;
 
-	if (dev->devtype->product == CODA_7541) {
+	if (dev->devtype->product == CODA_960 ||
+	    dev->devtype->product == CODA_7541) {
 		/* Restore context related registers to CODA */
 		coda_write(dev, ctx->bit_stream_param,
 				CODA_REG_BIT_BIT_STREAM_PARAM);
 		coda_write(dev, ctx->frm_dis_flg,
 				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+		coda_write(dev, ctx->frame_mem_ctrl,
+				CODA_REG_BIT_FRAME_MEM_CTRL);
 		coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR);
 	}
 
+	if (dev->devtype->product == CODA_960) {
+		coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
+		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+	}
+
 	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
 
 	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
@@ -290,6 +338,39 @@ static int coda_command_sync(struct coda
 	return coda_wait_timeout(dev);
 }
 
+static int coda_hw_reset(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	unsigned long timeout;
+	unsigned int idx;
+	int ret;
+
+	if (!dev->rstc)
+		return -ENOENT;
+
+	idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
+	while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
+		if (time_after(jiffies, timeout))
+			return -ETIME;
+		cpu_relax();
+	}
+
+	ret = reset_control_reset(dev->rstc);
+	if (ret < 0)
+		return ret;
+
+	coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
+	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
+	ret = coda_wait_timeout(dev);
+	coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
+
+	return ret;
+}
+
 static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
 					 enum v4l2_buf_type type)
 {
@@ -299,9 +380,8 @@ static struct coda_q_data *get_q_data(st
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		return &(ctx->q_data[V4L2_M2M_DST]);
 	default:
-		BUG();
+		return NULL;
 	}
-	return NULL;
 }
 
 /*
@@ -348,6 +428,13 @@ static struct coda_codec coda7_codecs[]
 	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1080),
 };
 
+static struct coda_codec coda9_codecs[] = {
+	CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1920, 1080),
+	CODA_CODEC(CODA9_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1920, 1080),
+	CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1080),
+	CODA_CODEC(CODA9_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1080),
+};
+
 static bool coda_format_is_yuv(u32 fourcc)
 {
 	switch (fourcc) {
@@ -426,6 +513,8 @@ static char *coda_product_name(int produ
 		return "CodaDx6";
 	case CODA_7541:
 		return "CODA7541";
+	case CODA_960:
+		return "CODA960";
 	default:
 		snprintf(buf, sizeof(buf), "(0x%04x)", product);
 		return buf;
@@ -515,7 +604,7 @@ static int coda_enum_fmt_vid_cap(struct
 	struct coda_q_data *q_data_src;
 
 	/* If the source format is already fixed, only list matching formats */
-	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	if (vb2_is_streaming(src_vq)) {
 		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 
@@ -535,24 +624,18 @@ static int coda_enum_fmt_vid_out(struct
 static int coda_g_fmt(struct file *file, void *priv,
 		      struct v4l2_format *f)
 {
-	struct vb2_queue *vq;
 	struct coda_q_data *q_data;
 	struct coda_ctx *ctx = fh_to_ctx(priv);
 
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
-	if (!vq)
-		return -EINVAL;
-
 	q_data = get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
 
 	f->fmt.pix.field	= V4L2_FIELD_NONE;
 	f->fmt.pix.pixelformat	= q_data->fourcc;
 	f->fmt.pix.width	= q_data->width;
 	f->fmt.pix.height	= q_data->height;
-	if (coda_format_is_yuv(f->fmt.pix.pixelformat))
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2);
-	else /* encoded formats h.264/mpeg4 */
-		f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.bytesperline = q_data->bytesperline;
 
 	f->fmt.pix.sizeimage	= q_data->sizeimage;
 	f->fmt.pix.colorspace	= ctx->colorspace;
@@ -592,14 +675,16 @@ static int coda_try_fmt(struct coda_ctx
 		break;
 	default:
 		q_data = get_q_data(ctx, f->type);
+		if (!q_data)
+			return -EINVAL;
 		f->fmt.pix.pixelformat = q_data->fourcc;
 	}
 
 	switch (f->fmt.pix.pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YVU420:
-		/* Frame stride must be multiple of 8 */
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8);
+		/* Frame stride must be multiple of 8, but 16 for h.264 */
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
 					f->fmt.pix.height * 3 / 2;
 		break;
@@ -613,8 +698,6 @@ static int coda_try_fmt(struct coda_ctx
 		BUG();
 	}
 
-	f->fmt.pix.priv = 0;
-
 	return 0;
 }
 
@@ -630,7 +713,7 @@ static int coda_try_fmt_vid_cap(struct f
 	 * If the source format is already fixed, try to find a codec that
 	 * converts to the given destination format
 	 */
-	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	if (vb2_is_streaming(src_vq)) {
 		struct coda_q_data *q_data_src;
 
@@ -653,9 +736,9 @@ static int coda_try_fmt_vid_cap(struct f
 
 	/* The h.264 decoder only returns complete 16x16 macroblocks */
 	if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) {
-		f->fmt.pix.width = round_up(f->fmt.pix.width, 16);
+		f->fmt.pix.width = f->fmt.pix.width;
 		f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
-		f->fmt.pix.bytesperline = f->fmt.pix.width;
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
 				       f->fmt.pix.height * 3 / 2;
 	}
@@ -684,7 +767,7 @@ static int coda_s_fmt(struct coda_ctx *c
 	struct coda_q_data *q_data;
 	struct vb2_queue *vq;
 
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 	if (!vq)
 		return -EINVAL;
 
@@ -700,7 +783,12 @@ static int coda_s_fmt(struct coda_ctx *c
 	q_data->fourcc = f->fmt.pix.pixelformat;
 	q_data->width = f->fmt.pix.width;
 	q_data->height = f->fmt.pix.height;
+	q_data->bytesperline = f->fmt.pix.bytesperline;
 	q_data->sizeimage = f->fmt.pix.sizeimage;
+	q_data->rect.left = 0;
+	q_data->rect.top = 0;
+	q_data->rect.width = f->fmt.pix.width;
+	q_data->rect.height = f->fmt.pix.height;
 
 	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
@@ -739,36 +827,12 @@ static int coda_s_fmt_vid_out(struct fil
 	return ret;
 }
 
-static int coda_reqbufs(struct file *file, void *priv,
-			struct v4l2_requestbuffers *reqbufs)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int coda_querybuf(struct file *file, void *priv,
-			 struct v4l2_buffer *buf)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
 static int coda_qbuf(struct file *file, void *priv,
 		     struct v4l2_buffer *buf)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
 
-	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int coda_expbuf(struct file *file, void *priv,
-		       struct v4l2_exportbuffer *eb)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
+	return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf);
 }
 
 static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
@@ -776,7 +840,7 @@ static bool coda_buf_is_end_of_stream(st
 {
 	struct vb2_queue *src_vq;
 
-	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 
 	return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) &&
 		(buf->sequence == (ctx->qsequence - 1)));
@@ -788,7 +852,7 @@ static int coda_dqbuf(struct file *file,
 	struct coda_ctx *ctx = fh_to_ctx(priv);
 	int ret;
 
-	ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+	ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf);
 
 	/* If this is the last capture buffer, emit an end-of-stream event */
 	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
@@ -803,38 +867,48 @@ static int coda_dqbuf(struct file *file,
 	return ret;
 }
 
-static int coda_create_bufs(struct file *file, void *priv,
-			    struct v4l2_create_buffers *create)
+static int coda_g_selection(struct file *file, void *fh,
+			    struct v4l2_selection *s)
 {
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	return v4l2_m2m_create_bufs(file, ctx->m2m_ctx, create);
-}
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_q_data *q_data;
+	struct v4l2_rect r, *rsel;
 
-static int coda_streamon(struct file *file, void *priv,
-			 enum v4l2_buf_type type)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
+	q_data = get_q_data(ctx, s->type);
+	if (!q_data)
+		return -EINVAL;
 
-	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
+	r.left = 0;
+	r.top = 0;
+	r.width = q_data->width;
+	r.height = q_data->height;
+	rsel = &q_data->rect;
 
-static int coda_streamoff(struct file *file, void *priv,
-			  enum v4l2_buf_type type)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	int ret;
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		rsel = &r;
+		/* fallthrough */
+	case V4L2_SEL_TGT_CROP:
+		if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+		break;
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_PADDED:
+		rsel = &r;
+		/* fallthrough */
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	/*
-	 * This indirectly calls __vb2_queue_cancel, which dequeues all buffers.
-	 * We therefore have to lock it against running hardware in this context,
-	 * which still needs the buffers.
-	 */
-	mutex_lock(&ctx->buffer_mutex);
-	ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-	mutex_unlock(&ctx->buffer_mutex);
+	s->r = *rsel;
 
-	return ret;
+	return 0;
 }
 
 static int coda_try_decoder_cmd(struct file *file, void *fh,
@@ -856,6 +930,7 @@ static int coda_decoder_cmd(struct file
 			    struct v4l2_decoder_cmd *dc)
 {
 	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_dev *dev = ctx->dev;
 	int ret;
 
 	ret = coda_try_decoder_cmd(file, fh, dc);
@@ -869,6 +944,15 @@ static int coda_decoder_cmd(struct file
 	/* Set the strem-end flag on this context */
 	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
 
+	if ((dev->devtype->product == CODA_960) &&
+	    coda_isbusy(dev) &&
+	    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
+		/* If this context is currently running, update the hardware flag */
+		coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+	}
+	ctx->hold = false;
+	v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
+
 	return 0;
 }
 
@@ -896,16 +980,18 @@ static const struct v4l2_ioctl_ops coda_
 	.vidioc_try_fmt_vid_out	= coda_try_fmt_vid_out,
 	.vidioc_s_fmt_vid_out	= coda_s_fmt_vid_out,
 
-	.vidioc_reqbufs		= coda_reqbufs,
-	.vidioc_querybuf	= coda_querybuf,
+	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
 
 	.vidioc_qbuf		= coda_qbuf,
-	.vidioc_expbuf		= coda_expbuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
 	.vidioc_dqbuf		= coda_dqbuf,
-	.vidioc_create_bufs	= coda_create_bufs,
+	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
 
-	.vidioc_streamon	= coda_streamon,
-	.vidioc_streamoff	= coda_streamoff,
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_g_selection	= coda_g_selection,
 
 	.vidioc_try_decoder_cmd	= coda_try_decoder_cmd,
 	.vidioc_decoder_cmd	= coda_decoder_cmd,
@@ -916,13 +1002,6 @@ static const struct v4l2_ioctl_ops coda_
 
 static int coda_start_decoding(struct coda_ctx *ctx);
 
-static void coda_skip_run(struct work_struct *work)
-{
-	struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run);
-
-	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
-}
-
 static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
 {
 	return kfifo_len(&ctx->bitstream_fifo);
@@ -975,7 +1054,7 @@ static int coda_bitstream_queue(struct c
 	dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr,
 				   ctx->bitstream.size, DMA_TO_DEVICE);
 
-	ctx->qsequence++;
+	src_buf->v4l2_buf.sequence = ctx->qsequence++;
 
 	return 0;
 }
@@ -1003,7 +1082,7 @@ static bool coda_bitstream_try_queue(str
 	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
 		coda_kfifo_sync_to_device_write(ctx);
 
-	ctx->prescan_failed = false;
+	ctx->hold = false;
 
 	return true;
 }
@@ -1011,12 +1090,26 @@ static bool coda_bitstream_try_queue(str
 static void coda_fill_bitstream(struct coda_ctx *ctx)
 {
 	struct vb2_buffer *src_buf;
+	struct coda_timestamp *ts;
 
-	while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) {
-		src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 
 		if (coda_bitstream_try_queue(ctx, src_buf)) {
-			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			/*
+			 * Source buffer is queued in the bitstream ringbuffer;
+			 * queue the timestamp and mark source buffer as done
+			 */
+			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+
+			ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+			if (ts) {
+				ts->sequence = src_buf->v4l2_buf.sequence;
+				ts->timecode = src_buf->v4l2_buf.timecode;
+				ts->timestamp = src_buf->v4l2_buf.timestamp;
+				list_add_tail(&ts->list, &ctx->timestamp_list);
+			}
+
 			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
 		} else {
 			break;
@@ -1024,6 +1117,27 @@ static void coda_fill_bitstream(struct c
 	}
 }
 
+static void coda_set_gdi_regs(struct coda_ctx *ctx)
+{
+	struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
+	struct coda_dev *dev = ctx->dev;
+	int i;
+
+	for (i = 0; i < 16; i++)
+		coda_write(dev, tiled_map->xy2ca_map[i],
+				CODA9_GDI_XY2_CAS_0 + 4 * i);
+	for (i = 0; i < 4; i++)
+		coda_write(dev, tiled_map->xy2ba_map[i],
+				CODA9_GDI_XY2_BA_0 + 4 * i);
+	for (i = 0; i < 16; i++)
+		coda_write(dev, tiled_map->xy2ra_map[i],
+				CODA9_GDI_XY2_RAS_0 + 4 * i);
+	coda_write(dev, tiled_map->xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
+	for (i = 0; i < 32; i++)
+		coda_write(dev, tiled_map->rbc2axi_map[i],
+				CODA9_GDI_RBC2_AXI_0 + 4 * i);
+}
+
 /*
  * Mem-to-mem operations.
  */
@@ -1035,7 +1149,7 @@ static int coda_prepare_decode(struct co
 	u32 stridey, height;
 	u32 picture_y, picture_cb, picture_cr;
 
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
 	if (ctx->params.rot_mode & CODA_ROT_90) {
@@ -1056,7 +1170,7 @@ static int coda_prepare_decode(struct co
 		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 			 "bitstream payload: %d, skipping\n",
 			 coda_get_bitstream_payload(ctx));
-		schedule_work(&ctx->skip_run);
+		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 		return -EAGAIN;
 	}
 
@@ -1065,13 +1179,16 @@ static int coda_prepare_decode(struct co
 		int ret = coda_start_decoding(ctx);
 		if (ret < 0) {
 			v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
-			schedule_work(&ctx->skip_run);
+			v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 			return -EAGAIN;
 		} else {
 			ctx->initialized = 1;
 		}
 	}
 
+	if (dev->devtype->product == CODA_960)
+		coda_set_gdi_regs(ctx);
+
 	/* Set rotator output */
 	picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 	if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
@@ -1082,10 +1199,26 @@ static int coda_prepare_decode(struct co
 		picture_cb = picture_y + stridey * height;
 		picture_cr = picture_cb + stridey / 2 * height / 2;
 	}
-	coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
-	coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
-	coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
-	coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
+
+	if (dev->devtype->product == CODA_960) {
+		/*
+		 * The CODA960 seems to have an internal list of buffers with
+		 * 64 entries that includes the registered frame buffers as
+		 * well as the rotator buffer output.
+		 * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames.
+		 */
+		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index,
+				CODA9_CMD_DEC_PIC_ROT_INDEX);
+		coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
+		coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
+		coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
+		coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
+	} else {
+		coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
+		coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
+		coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
+		coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
+	}
 	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
 			CODA_CMD_DEC_PIC_ROT_MODE);
 
@@ -1095,6 +1228,9 @@ static int coda_prepare_decode(struct co
 	case CODA_7541:
 		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
 		break;
+	case CODA_960:
+		coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /* 'hardcode to use interrupt disable mode'? */
+		break;
 	}
 
 	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
@@ -1116,8 +1252,8 @@ static void coda_prepare_encode(struct c
 	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
 	u32 dst_fourcc;
 
-	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	dst_fourcc = q_data_dst->fourcc;
@@ -1139,6 +1275,9 @@ static void coda_prepare_encode(struct c
 		src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
 	}
 
+	if (dev->devtype->product == CODA_960)
+		coda_set_gdi_regs(ctx);
+
 	/*
 	 * Copy headers at the beginning of the first frame for H.264 only.
 	 * In MPEG4 they are already copied by the coda.
@@ -1205,51 +1344,93 @@ static void coda_prepare_encode(struct c
 	switch (q_data_src->fourcc) {
 	case V4L2_PIX_FMT_YVU420:
 		/* Switch Cb and Cr for YVU420 format */
-		picture_cr = picture_y + q_data_src->width * q_data_src->height;
-		picture_cb = picture_cr + q_data_src->width / 2 *
+		picture_cr = picture_y + q_data_src->bytesperline *
+				q_data_src->height;
+		picture_cb = picture_cr + q_data_src->bytesperline / 2 *
 				q_data_src->height / 2;
 		break;
 	case V4L2_PIX_FMT_YUV420:
 	default:
-		picture_cb = picture_y + q_data_src->width * q_data_src->height;
-		picture_cr = picture_cb + q_data_src->width / 2 *
+		picture_cb = picture_y + q_data_src->bytesperline *
+				q_data_src->height;
+		picture_cr = picture_cb + q_data_src->bytesperline / 2 *
 				q_data_src->height / 2;
 		break;
 	}
 
-	coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
-	coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
-	coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
+	if (dev->devtype->product == CODA_960) {
+		coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
+		coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE);
+		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
+
+		coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
+		coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
+		coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
+	} else {
+		coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
+		coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
+		coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
+	}
 	coda_write(dev, force_ipicture << 1 & 0x2,
 		   CODA_CMD_ENC_PIC_OPTION);
 
 	coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
 	coda_write(dev, pic_stream_buffer_size / 1024,
 		   CODA_CMD_ENC_PIC_BB_SIZE);
+
+	if (!ctx->streamon_out) {
+		/* After streamoff on the output side, set the stream end flag */
+		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+		coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+	}
 }
 
 static void coda_device_run(void *m2m_priv)
 {
 	struct coda_ctx *ctx = m2m_priv;
 	struct coda_dev *dev = ctx->dev;
-	int ret;
+
+	queue_work(dev->workqueue, &ctx->pic_run_work);
+}
+
+static void coda_free_framebuffers(struct coda_ctx *ctx);
+static void coda_free_context_buffers(struct coda_ctx *ctx);
+
+static void coda_seq_end_work(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work);
+	struct coda_dev *dev = ctx->dev;
 
 	mutex_lock(&ctx->buffer_mutex);
+	mutex_lock(&dev->coda_mutex);
 
-	/*
-	 * If streamoff dequeued all buffers before we could get the lock,
-	 * just bail out immediately.
-	 */
-	if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
-	    ctx->inst_type != CODA_INST_DECODER) ||
-		!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
-		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-			"%d: device_run without buffers\n", ctx->idx);
-		mutex_unlock(&ctx->buffer_mutex);
-		schedule_work(&ctx->skip_run);
-		return;
+	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+		 "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx, __func__);
+	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+		v4l2_err(&dev->v4l2_dev,
+			 "CODA_COMMAND_SEQ_END failed\n");
 	}
 
+	kfifo_init(&ctx->bitstream_fifo,
+		ctx->bitstream.vaddr, ctx->bitstream.size);
+
+	coda_free_framebuffers(ctx);
+	coda_free_context_buffers(ctx);
+
+	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
+}
+
+static void coda_finish_decode(struct coda_ctx *ctx);
+static void coda_finish_encode(struct coda_ctx *ctx);
+
+static void coda_pic_run_work(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work);
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	mutex_lock(&ctx->buffer_mutex);
 	mutex_lock(&dev->coda_mutex);
 
 	if (ctx->inst_type == CODA_INST_DECODER) {
@@ -1268,12 +1449,30 @@ static void coda_device_run(void *m2m_pr
 		coda_write(dev, ctx->iram_info.axi_sram_use,
 				CODA7_REG_BIT_AXI_SRAM_USE);
 
-	/* 1 second timeout in case CODA locks up */
-	schedule_delayed_work(&dev->timeout, HZ);
-
 	if (ctx->inst_type == CODA_INST_DECODER)
 		coda_kfifo_sync_to_device_full(ctx);
 	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
+
+	if (!wait_for_completion_timeout(&ctx->completion, msecs_to_jiffies(1000))) {
+		dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n");
+
+		ctx->hold = true;
+
+		coda_hw_reset(ctx);
+	} else if (!ctx->aborting) {
+		if (ctx->inst_type == CODA_INST_DECODER)
+			coda_finish_decode(ctx);
+		else
+			coda_finish_encode(ctx);
+	}
+
+	if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
+		queue_work(dev->workqueue, &ctx->seq_end_work);
+
+	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 }
 
 static int coda_job_ready(void *m2m_priv)
@@ -1285,20 +1484,20 @@ static int coda_job_ready(void *m2m_priv
 	 * and 1 frame are needed. In the decoder case,
 	 * the compressed frame can be in the bitstream.
 	 */
-	if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
+	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
 	    ctx->inst_type != CODA_INST_DECODER) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "not ready: not enough video buffers.\n");
 		return 0;
 	}
 
-	if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "not ready: not enough video capture buffers.\n");
 		return 0;
 	}
 
-	if (ctx->prescan_failed ||
+	if (ctx->hold ||
 	    ((ctx->inst_type == CODA_INST_DECODER) &&
 	     (coda_get_bitstream_payload(ctx) < 512) &&
 	     !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
@@ -1351,6 +1550,32 @@ static struct v4l2_m2m_ops coda_m2m_ops
 	.unlock		= coda_unlock,
 };
 
+static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
+{
+	struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
+	int luma_map, chro_map, i;
+
+	memset(tiled_map, 0, sizeof(*tiled_map));
+
+	luma_map = 64;
+	chro_map = 64;
+	tiled_map->map_type = tiled_map_type;
+	for (i = 0; i < 16; i++)
+		tiled_map->xy2ca_map[i] = luma_map << 8 | chro_map;
+	for (i = 0; i < 4; i++)
+		tiled_map->xy2ba_map[i] = luma_map << 8 | chro_map;
+	for (i = 0; i < 16; i++)
+		tiled_map->xy2ra_map[i] = luma_map << 8 | chro_map;
+
+	if (tiled_map_type == GDI_LINEAR_FRAME_MAP) {
+		tiled_map->xy2rbc_config = 0;
+	} else {
+		dev_err(&ctx->dev->plat_dev->dev, "invalid map type: %d\n",
+			tiled_map_type);
+		return;
+	}
+}
+
 static void set_default_params(struct coda_ctx *ctx)
 {
 	int max_w;
@@ -1370,10 +1595,19 @@ static void set_default_params(struct co
 	ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc;
 	ctx->q_data[V4L2_M2M_SRC].width = max_w;
 	ctx->q_data[V4L2_M2M_SRC].height = max_h;
+	ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
 	ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2;
 	ctx->q_data[V4L2_M2M_DST].width = max_w;
 	ctx->q_data[V4L2_M2M_DST].height = max_h;
+	ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
 	ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE;
+	ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
+	ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
+	ctx->q_data[V4L2_M2M_DST].rect.width = max_w;
+	ctx->q_data[V4L2_M2M_DST].rect.height = max_h;
+
+	if (ctx->dev->devtype->product == CODA_960)
+		coda_set_tiled_map_type(ctx, GDI_LINEAR_FRAME_MAP);
 }
 
 /*
@@ -1423,6 +1657,7 @@ static int coda_buf_prepare(struct vb2_b
 static void coda_buf_queue(struct vb2_buffer *vb)
 {
 	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct coda_dev *dev = ctx->dev;
 	struct coda_q_data *q_data;
 
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
@@ -1437,29 +1672,24 @@ static void coda_buf_queue(struct vb2_bu
 		 * For backwards compatibility, queuing an empty buffer marks
 		 * the stream end
 		 */
-		if (vb2_get_plane_payload(vb, 0) == 0)
+		if (vb2_get_plane_payload(vb, 0) == 0) {
 			ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+			if ((dev->devtype->product == CODA_960) &&
+			    coda_isbusy(dev) &&
+			    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
+				/* if this decoder instance is running, set the stream end flag */
+				coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+			}
+		}
 		mutex_lock(&ctx->bitstream_mutex);
-		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 		coda_fill_bitstream(ctx);
 		mutex_unlock(&ctx->bitstream_mutex);
 	} else {
-		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 	}
 }
 
-static void coda_wait_prepare(struct vb2_queue *q)
-{
-	struct coda_ctx *ctx = vb2_get_drv_priv(q);
-	coda_unlock(ctx);
-}
-
-static void coda_wait_finish(struct vb2_queue *q)
-{
-	struct coda_ctx *ctx = vb2_get_drv_priv(q);
-	coda_lock(ctx);
-}
-
 static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
 {
 	struct coda_dev *dev = ctx->dev;
@@ -1472,7 +1702,8 @@ static void coda_parabuf_write(struct co
 }
 
 static int coda_alloc_aux_buf(struct coda_dev *dev,
-			      struct coda_aux_buf *buf, size_t size)
+			      struct coda_aux_buf *buf, size_t size,
+			      const char *name, struct dentry *parent)
 {
 	buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr,
 					GFP_KERNEL);
@@ -1481,13 +1712,23 @@ static int coda_alloc_aux_buf(struct cod
 
 	buf->size = size;
 
+	if (name && parent) {
+		buf->blob.data = buf->vaddr;
+		buf->blob.size = size;
+		buf->dentry = debugfs_create_blob(name, 0644, parent, &buf->blob);
+		if (!buf->dentry)
+			dev_warn(&dev->plat_dev->dev,
+				 "failed to create debugfs entry %s\n", name);
+	}
+
 	return 0;
 }
 
 static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
-					 struct coda_aux_buf *buf, size_t size)
+					 struct coda_aux_buf *buf, size_t size,
+					 const char *name)
 {
-	return coda_alloc_aux_buf(ctx->dev, buf, size);
+	return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
 }
 
 static void coda_free_aux_buf(struct coda_dev *dev,
@@ -1499,6 +1740,7 @@ static void coda_free_aux_buf(struct cod
 		buf->vaddr = NULL;
 		buf->size = 0;
 	}
+	debugfs_remove(buf->dentry);
 }
 
 static void coda_free_framebuffers(struct coda_ctx *ctx)
@@ -1512,25 +1754,35 @@ static void coda_free_framebuffers(struc
 static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc)
 {
 	struct coda_dev *dev = ctx->dev;
-	int height = q_data->height;
+	int width, height;
 	dma_addr_t paddr;
 	int ysize;
 	int ret;
 	int i;
 
-	if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
-		height = round_up(height, 16);
-	ysize = round_up(q_data->width, 8) * height;
+	if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
+	     ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) {
+		width = round_up(q_data->width, 16);
+		height = round_up(q_data->height, 16);
+	} else {
+		width = round_up(q_data->width, 8);
+		height = q_data->height;
+	}
+	ysize = width * height;
 
 	/* Allocate frame buffers */
 	for (i = 0; i < ctx->num_internal_frames; i++) {
 		size_t size;
+		char *name;
 
-		size = q_data->sizeimage;
+		size = ysize + ysize / 2;
 		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
 		    dev->devtype->product != CODA_DX6)
-			ctx->internal_frames[i].size += ysize/4;
-		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size);
+			size += ysize / 4;
+		name = kasprintf(GFP_KERNEL, "fb%d", i);
+		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i],
+					     size, name);
+		kfree(name);
 		if (ret < 0) {
 			coda_free_framebuffers(ctx);
 			return ret;
@@ -1579,23 +1831,48 @@ static int coda_h264_padding(int size, c
 	return nal_size;
 }
 
+static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
+{
+	phys_addr_t ret;
+
+	size = round_up(size, 1024);
+	if (size > iram->remaining)
+		return 0;
+	iram->remaining -= size;
+
+	ret = iram->next_paddr;
+	iram->next_paddr += size;
+
+	return ret;
+}
+
 static void coda_setup_iram(struct coda_ctx *ctx)
 {
 	struct coda_iram_info *iram_info = &ctx->iram_info;
 	struct coda_dev *dev = ctx->dev;
-	int ipacdc_size;
-	int bitram_size;
-	int dbk_size;
-	int ovl_size;
 	int mb_width;
-	int me_size;
-	int size;
+	int dbk_bits;
+	int bit_bits;
+	int ip_bits;
 
 	memset(iram_info, 0, sizeof(*iram_info));
-	size = dev->iram_size;
+	iram_info->next_paddr = dev->iram.paddr;
+	iram_info->remaining = dev->iram.size;
 
-	if (dev->devtype->product == CODA_DX6)
+	switch (dev->devtype->product) {
+	case CODA_7541:
+		dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE;
+		bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+		ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+		break;
+	case CODA_960:
+		dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE;
+		bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+		ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+		break;
+	default: /* CODA_DX6 */
 		return;
+	}
 
 	if (ctx->inst_type == CODA_INST_ENCODER) {
 		struct coda_q_data *q_data_src;
@@ -1604,111 +1881,63 @@ static void coda_setup_iram(struct coda_
 		mb_width = DIV_ROUND_UP(q_data_src->width, 16);
 
 		/* Prioritize in case IRAM is too small for everything */
-		me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048,
-				   1024);
-		iram_info->search_ram_size = me_size;
-		if (size >= iram_info->search_ram_size) {
-			if (dev->devtype->product == CODA_7541)
-				iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE;
-			iram_info->search_ram_paddr = dev->iram_paddr;
-			size -= iram_info->search_ram_size;
-		} else {
-			pr_err("IRAM is smaller than the search ram size\n");
-			goto out;
+		if (dev->devtype->product == CODA_7541) {
+			iram_info->search_ram_size = round_up(mb_width * 16 *
+							      36 + 2048, 1024);
+			iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
+							iram_info->search_ram_size);
+			if (!iram_info->search_ram_paddr) {
+				pr_err("IRAM is smaller than the search ram size\n");
+				goto out;
+			}
+			iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE |
+						   CODA7_USE_ME_ENABLE;
 		}
 
 		/* Only H.264BP and H.263P3 are considered */
-		dbk_size = round_up(128 * mb_width, 1024);
-		if (size >= dbk_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
-			iram_info->buf_dbk_y_use = dev->iram_paddr +
-						   iram_info->search_ram_size;
-			iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use +
-						   dbk_size / 2;
-			size -= dbk_size;
-		} else {
+		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * mb_width);
+		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * mb_width);
+		if (!iram_info->buf_dbk_c_use)
 			goto out;
-		}
+		iram_info->axi_sram_use |= dbk_bits;
 
-		bitram_size = round_up(128 * mb_width, 1024);
-		if (size >= bitram_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
-			iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
-						 dbk_size / 2;
-			size -= bitram_size;
-		} else {
+		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		if (!iram_info->buf_bit_use)
 			goto out;
-		}
+		iram_info->axi_sram_use |= bit_bits;
 
-		ipacdc_size = round_up(128 * mb_width, 1024);
-		if (size >= ipacdc_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
-			iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
-						      bitram_size;
-			size -= ipacdc_size;
-		}
+		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		if (!iram_info->buf_ip_ac_dc_use)
+			goto out;
+		iram_info->axi_sram_use |= ip_bits;
 
 		/* OVL and BTP disabled for encoder */
 	} else if (ctx->inst_type == CODA_INST_DECODER) {
 		struct coda_q_data *q_data_dst;
-		int mb_height;
 
 		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
-		mb_height = DIV_ROUND_UP(q_data_dst->height, 16);
 
-		dbk_size = round_up(256 * mb_width, 1024);
-		if (size >= dbk_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
-			iram_info->buf_dbk_y_use = dev->iram_paddr;
-			iram_info->buf_dbk_c_use = dev->iram_paddr +
-						   dbk_size / 2;
-			size -= dbk_size;
-		} else {
+		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		if (!iram_info->buf_dbk_c_use)
 			goto out;
-		}
+		iram_info->axi_sram_use |= dbk_bits;
 
-		bitram_size = round_up(128 * mb_width, 1024);
-		if (size >= bitram_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
-			iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
-						 dbk_size / 2;
-			size -= bitram_size;
-		} else {
+		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		if (!iram_info->buf_bit_use)
 			goto out;
-		}
+		iram_info->axi_sram_use |= bit_bits;
 
-		ipacdc_size = round_up(128 * mb_width, 1024);
-		if (size >= ipacdc_size) {
-			iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
-			iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
-						      bitram_size;
-			size -= ipacdc_size;
-		} else {
+		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+		if (!iram_info->buf_ip_ac_dc_use)
 			goto out;
-		}
+		iram_info->axi_sram_use |= ip_bits;
 
-		ovl_size = round_up(80 * mb_width, 1024);
+		/* OVL and BTP unused as there is no VC1 support yet */
 	}
 
 out:
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		break;
-	case CODA_7541:
-		/* i.MX53 uses secondary AXI for IRAM access */
-		if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE)
-			iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE;
-		if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)
-			iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE;
-		if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE)
-			iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE;
-		if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE)
-			iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE;
-		if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE)
-			iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE;
-	}
-
 	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "IRAM smaller than needed\n");
@@ -1746,13 +1975,8 @@ static int coda_alloc_context_buffers(st
 	size_t size;
 	int ret;
 
-	switch (dev->devtype->product) {
-	case CODA_7541:
-		size = CODA7_WORK_BUF_SIZE;
-		break;
-	default:
+	if (dev->devtype->product == CODA_DX6)
 		return 0;
-	}
 
 	if (ctx->psbuf.vaddr) {
 		v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
@@ -1772,7 +1996,7 @@ static int coda_alloc_context_buffers(st
 		/* worst case slice size */
 		size = (DIV_ROUND_UP(q_data->width, 16) *
 			DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
-		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size);
+		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, "slicebuf");
 		if (ret < 0) {
 			v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer",
 				 ctx->slicebuf.size);
@@ -1781,14 +2005,18 @@ static int coda_alloc_context_buffers(st
 	}
 
 	if (dev->devtype->product == CODA_7541) {
-		ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE);
+		ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE, "psbuf");
 		if (ret < 0) {
 			v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer");
 			goto err;
 		}
 	}
 
-	ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size);
+	size = dev->devtype->workbuf_size;
+	if (dev->devtype->product == CODA_960 &&
+	    q_data->fourcc == V4L2_PIX_FMT_H264)
+		size += CODA9_PS_SAVE_SIZE;
+	ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, "workbuf");
 	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer",
 			 ctx->workbuf.size);
@@ -1834,12 +2062,17 @@ static int coda_start_decoding(struct co
 	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
 	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
 	val = 0;
-	if (dev->devtype->product == CODA_7541)
+	if ((dev->devtype->product == CODA_7541) ||
+	    (dev->devtype->product == CODA_960))
 		val |= CODA_REORDER_ENABLE;
 	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
 
 	ctx->params.codec_mode = ctx->codec->mode;
-	ctx->params.codec_mode_aux = 0;
+	if (dev->devtype->product == CODA_960 &&
+	    src_fourcc == V4L2_PIX_FMT_MPEG4)
+		ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
+	else
+		ctx->params.codec_mode_aux = 0;
 	if (src_fourcc == V4L2_PIX_FMT_H264) {
 		if (dev->devtype->product == CODA_7541) {
 			coda_write(dev, ctx->psbuf.paddr,
@@ -1847,6 +2080,13 @@ static int coda_start_decoding(struct co
 			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
 					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
 		}
+		if (dev->devtype->product == CODA_960) {
+			coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
+			coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
+		}
+	}
+	if (dev->devtype->product != CODA_960) {
+		coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
 	}
 
 	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
@@ -1888,7 +2128,7 @@ static int coda_start_decoding(struct co
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n",
 		 __func__, ctx->idx, width, height);
 
-	ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1;
+	ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED);
 	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
 		v4l2_err(&dev->v4l2_dev,
 			 "not enough framebuffers to decode (%d < %d)\n",
@@ -1896,6 +2136,21 @@ static int coda_start_decoding(struct co
 		return -EINVAL;
 	}
 
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		u32 left_right;
+		u32 top_bottom;
+
+		left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
+		top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
+
+		q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
+		q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
+		q_data_dst->rect.width = width - q_data_dst->rect.left -
+					 (left_right & 0x3ff);
+		q_data_dst->rect.height = height - q_data_dst->rect.top -
+					  (top_bottom & 0x3ff);
+	}
+
 	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
 	if (ret < 0)
 		return ret;
@@ -1918,6 +2173,20 @@ static int coda_start_decoding(struct co
 				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
 		coda_write(dev, ctx->iram_info.buf_ovl_use,
 				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+		if (dev->devtype->product == CODA_960)
+			coda_write(dev, ctx->iram_info.buf_btp_use,
+					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+	}
+
+	if (dev->devtype->product == CODA_960) {
+		coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
+
+		coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
+		coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
+				32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
+				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
+				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
+				CODA9_CMD_SET_FRAME_CACHE_CONFIG);
 	}
 
 	if (src_fourcc == V4L2_PIX_FMT_H264) {
@@ -1931,8 +2200,16 @@ static int coda_start_decoding(struct co
 		int max_mb_x = 1920 / 16;
 		int max_mb_y = 1088 / 16;
 		int max_mb_num = max_mb_x * max_mb_y;
+
 		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
 				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
+	} else if (dev->devtype->product == CODA_960) {
+		int max_mb_x = 1920 / 16;
+		int max_mb_y = 1088 / 16;
+		int max_mb_num = max_mb_x * max_mb_y;
+
+		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
+				CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
 	}
 
 	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
@@ -1948,34 +2225,49 @@ static int coda_encode_header(struct cod
 			      int header_code, u8 *header, int *size)
 {
 	struct coda_dev *dev = ctx->dev;
+	size_t bufsize;
 	int ret;
+	int i;
+
+	if (dev->devtype->product == CODA_960)
+		memset(vb2_plane_vaddr(buf, 0), 0, 64);
 
 	coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0),
 		   CODA_CMD_ENC_HEADER_BB_START);
-	coda_write(dev, vb2_plane_size(buf, 0), CODA_CMD_ENC_HEADER_BB_SIZE);
+	bufsize = vb2_plane_size(buf, 0);
+	if (dev->devtype->product == CODA_960)
+		bufsize /= 1024;
+	coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
 	coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
 	ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
 	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
 		return ret;
 	}
-	*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
-		coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+
+	if (dev->devtype->product == CODA_960) {
+		for (i = 63; i > 0; i--)
+			if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0)
+				break;
+		*size = i + 1;
+	} else {
+		*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
+			coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+	}
 	memcpy(header, vb2_plane_vaddr(buf, 0), *size);
 
 	return 0;
 }
 
+static int coda_start_encoding(struct coda_ctx *ctx);
+
 static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct coda_ctx *ctx = vb2_get_drv_priv(q);
 	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
-	u32 bitstream_buf, bitstream_size;
 	struct coda_dev *dev = ctx->dev;
 	struct coda_q_data *q_data_src, *q_data_dst;
-	struct vb2_buffer *buf;
 	u32 dst_fourcc;
-	u32 value;
 	int ret = 0;
 
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
@@ -2007,13 +2299,10 @@ static int coda_start_streaming(struct v
 
 	/* Allow decoder device_run with no new buffers queued */
 	if (ctx->inst_type == CODA_INST_DECODER)
-		v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true);
+		v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
 
 	ctx->gopcounter = ctx->params.gop_size - 1;
-	buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
-	bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	bitstream_size = q_data_dst->sizeimage;
 	dst_fourcc = q_data_dst->fourcc;
 
 	ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
@@ -2032,16 +2321,36 @@ static int coda_start_streaming(struct v
 		mutex_lock(&dev->coda_mutex);
 		ret = coda_start_decoding(ctx);
 		mutex_unlock(&dev->coda_mutex);
-		if (ret == -EAGAIN) {
+		if (ret == -EAGAIN)
 			return 0;
-		} else if (ret < 0) {
+		else if (ret < 0)
 			return ret;
-		} else {
-			ctx->initialized = 1;
-			return 0;
-		}
+	} else {
+		ret = coda_start_encoding(ctx);
 	}
 
+	ctx->initialized = 1;
+	return ret;
+}
+
+static int coda_start_encoding(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	struct coda_q_data *q_data_src, *q_data_dst;
+	u32 bitstream_buf, bitstream_size;
+	struct vb2_buffer *buf;
+	int gamma, ret, value;
+	u32 dst_fourcc;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_fourcc = q_data_dst->fourcc;
+
+	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
+	bitstream_size = q_data_dst->sizeimage;
+
 	if (!coda_is_initialized(dev)) {
 		v4l2_err(v4l2_dev, "coda is not initialized.\n");
 		return -EFAULT;
@@ -2057,14 +2366,23 @@ static int coda_start_streaming(struct v
 		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
 			CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
 		break;
-	default:
+	case CODA_960:
+		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+		/* fallthrough */
+	case CODA_7541:
 		coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
 			CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+		break;
 	}
 
+	value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
+	value &= ~(1 << 2 | 0x7 << 9);
+	ctx->frame_mem_ctrl = value;
+	coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
+
 	if (dev->devtype->product == CODA_DX6) {
 		/* Configure the coda */
-		coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
+		coda_write(dev, dev->iram.paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
 	}
 
 	/* Could set rotation here if needed */
@@ -2073,7 +2391,16 @@ static int coda_start_streaming(struct v
 		value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET;
 		value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
 		break;
-	default:
+	case CODA_7541:
+		if (dst_fourcc == V4L2_PIX_FMT_H264) {
+			value = (round_up(q_data_src->width, 16) &
+				 CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
+			value |= (round_up(q_data_src->height, 16) &
+				  CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
+			break;
+		}
+		/* fallthrough */
+	case CODA_960:
 		value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
 		value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
 	}
@@ -2084,12 +2411,28 @@ static int coda_start_streaming(struct v
 	ctx->params.codec_mode = ctx->codec->mode;
 	switch (dst_fourcc) {
 	case V4L2_PIX_FMT_MPEG4:
-		coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
+		if (dev->devtype->product == CODA_960)
+			coda_write(dev, CODA9_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
+		else
+			coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
 		coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
 		break;
 	case V4L2_PIX_FMT_H264:
-		coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA);
+		if (dev->devtype->product == CODA_960)
+			coda_write(dev, CODA9_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
+		else
+			coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
+		if (ctx->params.h264_deblk_enabled) {
+			value = ((ctx->params.h264_deblk_alpha &
+				  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
+				 CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
+				((ctx->params.h264_deblk_beta &
+				  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
+				 CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
+		} else {
+			value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET;
+		}
+		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
 		break;
 	default:
 		v4l2_err(v4l2_dev,
@@ -2121,42 +2464,75 @@ static int coda_start_streaming(struct v
 		/* Rate control enabled */
 		value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET;
 		value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
+		if (dev->devtype->product == CODA_960)
+			value |= BIT(31); /* disable autoskip */
 	} else {
 		value = 0;
 	}
 	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
 
 	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
-	coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH);
+	coda_write(dev, ctx->params.intra_refresh,
+		   CODA_CMD_ENC_SEQ_INTRA_REFRESH);
 
 	coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
 	coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
 
-	/* set default gamma */
-	value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET;
-	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA);
 
-	if (CODA_DEFAULT_GAMMA > 0) {
-		if (dev->devtype->product == CODA_DX6)
-			value  = 1 << CODADX6_OPTION_GAMMA_OFFSET;
-		else
-			value  = 1 << CODA7_OPTION_GAMMA_OFFSET;
+	value = 0;
+	if (dev->devtype->product == CODA_960)
+		gamma = CODA9_DEFAULT_GAMMA;
+	else
+		gamma = CODA_DEFAULT_GAMMA;
+	if (gamma > 0) {
+		coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET,
+			   CODA_CMD_ENC_SEQ_RC_GAMMA);
+	}
+
+	if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
+		coda_write(dev,
+			   ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
+			   ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
+			   CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
+	}
+	if (dev->devtype->product == CODA_960) {
+		if (ctx->params.h264_max_qp)
+			value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
+		if (CODA_DEFAULT_GAMMA > 0)
+			value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
 	} else {
-		value = 0;
+		if (CODA_DEFAULT_GAMMA > 0) {
+			if (dev->devtype->product == CODA_DX6)
+				value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
+			else
+				value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
+		}
+		if (ctx->params.h264_min_qp)
+			value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
+		if (ctx->params.h264_max_qp)
+			value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
 	}
 	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
 
+	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
+
 	coda_setup_iram(ctx);
 
 	if (dst_fourcc == V4L2_PIX_FMT_H264) {
-		if (dev->devtype->product == CODA_DX6) {
+		switch (dev->devtype->product) {
+		case CODA_DX6:
 			value = FMO_SLICE_SAVE_BUF_SIZE << 7;
 			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
-		} else {
+			break;
+		case CODA_7541:
 			coda_write(dev, ctx->iram_info.search_ram_paddr,
 					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
 			coda_write(dev, ctx->iram_info.search_ram_size,
 					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
+			break;
+		case CODA_960:
+			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
+			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
 		}
 	}
 
@@ -2172,7 +2548,10 @@ static int coda_start_streaming(struct v
 		goto out;
 	}
 
-	ctx->num_internal_frames = 2;
+	if (dev->devtype->product == CODA_960)
+		ctx->num_internal_frames = 4;
+	else
+		ctx->num_internal_frames = 2;
 	ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
 	if (ret < 0) {
 		v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
@@ -2180,10 +2559,12 @@ static int coda_start_streaming(struct v
 	}
 
 	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
-	coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE);
-	if (dev->devtype->product == CODA_7541)
-		coda_write(dev, round_up(q_data_src->width, 8),
+	coda_write(dev, q_data_src->bytesperline,
+			CODA_CMD_SET_FRAME_BUF_STRIDE);
+	if (dev->devtype->product == CODA_7541) {
+		coda_write(dev, q_data_src->bytesperline,
 				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
+	}
 	if (dev->devtype->product != CODA_DX6) {
 		coda_write(dev, ctx->iram_info.buf_bit_use,
 				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
@@ -2195,7 +2576,16 @@ static int coda_start_streaming(struct v
 				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
 		coda_write(dev, ctx->iram_info.buf_ovl_use,
 				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+		if (dev->devtype->product == CODA_960) {
+			coda_write(dev, ctx->iram_info.buf_btp_use,
+					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+
+			/* FIXME */
+			coda_write(dev, ctx->internal_frames[2].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_A);
+			coda_write(dev, ctx->internal_frames[3].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_B);
+		}
 	}
+
 	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
 	if (ret < 0) {
 		v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
@@ -2203,7 +2593,7 @@ static int coda_start_streaming(struct v
 	}
 
 	/* Save stream headers */
-	buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	switch (dst_fourcc) {
 	case V4L2_PIX_FMT_H264:
 		/*
@@ -2279,6 +2669,17 @@ static void coda_stop_streaming(struct v
 			 "%s: output\n", __func__);
 		ctx->streamon_out = 0;
 
+		if (ctx->inst_type == CODA_INST_DECODER &&
+		    coda_isbusy(dev) && ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX)) {
+			/* if this decoder instance is running, set the stream end flag */
+			if (dev->devtype->product == CODA_960) {
+				u32 val = coda_read(dev, CODA_REG_BIT_BIT_STREAM_PARAM);
+
+				val |= CODA_BIT_STREAM_END_FLAG;
+				coda_write(dev, val, CODA_REG_BIT_BIT_STREAM_PARAM);
+				ctx->bit_stream_param = val;
+			}
+		}
 		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
 
 		ctx->isequence = 0;
@@ -2288,9 +2689,18 @@ static void coda_stop_streaming(struct v
 		ctx->streamon_cap = 0;
 
 		ctx->osequence = 0;
+		ctx->sequence_offset = 0;
 	}
 
 	if (!ctx->streamon_out && !ctx->streamon_cap) {
+		struct coda_timestamp *ts;
+
+		while (!list_empty(&ctx->timestamp_list)) {
+			ts = list_first_entry(&ctx->timestamp_list,
+					      struct coda_timestamp, list);
+			list_del(&ts->list);
+			kfree(ts);
+		}
 		kfifo_init(&ctx->bitstream_fifo,
 			ctx->bitstream.vaddr, ctx->bitstream.size);
 		ctx->runcounter = 0;
@@ -2301,10 +2711,10 @@ static struct vb2_ops coda_qops = {
 	.queue_setup		= coda_queue_setup,
 	.buf_prepare		= coda_buf_prepare,
 	.buf_queue		= coda_buf_queue,
-	.wait_prepare		= coda_wait_prepare,
-	.wait_finish		= coda_wait_finish,
 	.start_streaming	= coda_start_streaming,
 	.stop_streaming		= coda_stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
 };
 
 static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -2340,6 +2750,22 @@ static int coda_s_ctrl(struct v4l2_ctrl
 	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
 		ctx->params.h264_inter_qp = ctrl->val;
 		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		ctx->params.h264_min_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		ctx->params.h264_max_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+		ctx->params.h264_deblk_alpha = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+		ctx->params.h264_deblk_beta = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+		ctx->params.h264_deblk_enabled = (ctrl->val ==
+				V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+		break;
 	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
 		ctx->params.mpeg4_intra_qp = ctrl->val;
 		break;
@@ -2357,6 +2783,9 @@ static int coda_s_ctrl(struct v4l2_ctrl
 		break;
 	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
 		break;
+	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+		ctx->params.intra_refresh = ctrl->val;
+		break;
 	default:
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			"Invalid control, id=%d, val=%d\n",
@@ -2384,9 +2813,23 @@ static int coda_ctrls_setup(struct coda_
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25);
+		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25);
+		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25);
+	if (ctx->dev->devtype->product != CODA_960) {
+		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12);
+	}
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, 0, 15, 1, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, 0, 15, 1, 0);
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0,
+		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -2404,6 +2847,8 @@ static int coda_ctrls_setup(struct coda_
 		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
 		(1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE),
 		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, 1920 * 1088 / 256, 1, 0);
 
 	if (ctx->ctrls.error) {
 		v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)",
@@ -2427,6 +2872,7 @@ static int coda_queue_init(void *priv, s
 	src_vq->ops = &coda_qops;
 	src_vq->mem_ops = &vb2_dma_contig_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &ctx->dev->dev_mutex;
 
 	ret = vb2_queue_init(src_vq);
 	if (ret)
@@ -2439,6 +2885,7 @@ static int coda_queue_init(void *priv, s
 	dst_vq->ops = &coda_qops;
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &ctx->dev->dev_mutex;
 
 	return vb2_queue_init(dst_vq);
 }
@@ -2458,6 +2905,7 @@ static int coda_open(struct file *file)
 {
 	struct coda_dev *dev = video_drvdata(file);
 	struct coda_ctx *ctx = NULL;
+	char *name;
 	int ret;
 	int idx;
 
@@ -2472,7 +2920,13 @@ static int coda_open(struct file *file)
 	}
 	set_bit(idx, &dev->instance_mask);
 
-	INIT_WORK(&ctx->skip_run, coda_skip_run);
+	name = kasprintf(GFP_KERNEL, "context%d", idx);
+	ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
+	kfree(name);
+
+	init_completion(&ctx->completion);
+	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
+	INIT_WORK(&ctx->seq_end_work, coda_seq_end_work);
 	v4l2_fh_init(&ctx->fh, video_devdata(file));
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
@@ -2480,12 +2934,20 @@ static int coda_open(struct file *file)
 	ctx->idx = idx;
 	switch (dev->devtype->product) {
 	case CODA_7541:
+	case CODA_960:
 		ctx->reg_idx = 0;
 		break;
 	default:
 		ctx->reg_idx = idx;
 	}
 
+	/* Power up and upload firmware if necessary */
+	ret = pm_runtime_get_sync(&dev->plat_dev->dev);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret);
+		goto err_pm_get;
+	}
+
 	ret = clk_prepare_enable(dev->clk_per);
 	if (ret)
 		goto err_clk_per;
@@ -2495,15 +2957,16 @@ static int coda_open(struct file *file)
 		goto err_clk_ahb;
 
 	set_default_params(ctx);
-	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
 					 &coda_queue_init);
-	if (IS_ERR(ctx->m2m_ctx)) {
-		ret = PTR_ERR(ctx->m2m_ctx);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
 
 		v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n",
 			 __func__, ret);
 		goto err_ctx_init;
 	}
+
 	ret = coda_ctrls_setup(ctx);
 	if (ret) {
 		v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n");
@@ -2512,7 +2975,8 @@ static int coda_open(struct file *file)
 
 	ctx->fh.ctrl_handler = &ctx->ctrls;
 
-	ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE);
+	ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE,
+				     "parabuf");
 	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
 		goto err_dma_alloc;
@@ -2530,6 +2994,7 @@ static int coda_open(struct file *file)
 		ctx->bitstream.vaddr, ctx->bitstream.size);
 	mutex_init(&ctx->bitstream_mutex);
 	mutex_init(&ctx->buffer_mutex);
+	INIT_LIST_HEAD(&ctx->timestamp_list);
 
 	coda_lock(ctx);
 	list_add(&ctx->list, &dev->instances);
@@ -2548,12 +3013,14 @@ err_dma_writecombine:
 err_dma_alloc:
 	v4l2_ctrl_handler_free(&ctx->ctrls);
 err_ctrls_setup:
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 err_ctx_init:
 	clk_disable_unprepare(dev->clk_ahb);
 err_clk_ahb:
 	clk_disable_unprepare(dev->clk_per);
 err_clk_per:
+	pm_runtime_put_sync(&dev->plat_dev->dev);
+err_pm_get:
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	clear_bit(ctx->idx, &dev->instance_mask);
@@ -2570,20 +3037,16 @@ static int coda_release(struct file *fil
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
 		 ctx);
 
+	debugfs_remove_recursive(ctx->debugfs_entry);
+
 	/* If this instance is running, call .job_abort and wait for it to end */
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
 	/* In case the instance was not running, we still need to call SEQ_END */
-	mutex_lock(&dev->coda_mutex);
-	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-		 "%s: sent command 'SEQ_END' to coda\n", __func__);
-	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
-		v4l2_err(&dev->v4l2_dev,
-			 "CODA_COMMAND_SEQ_END failed\n");
-		mutex_unlock(&dev->coda_mutex);
-		return -ETIMEDOUT;
+	if (ctx->initialized) {
+		queue_work(dev->workqueue, &ctx->seq_end_work);
+		flush_work(&ctx->seq_end_work);
 	}
-	mutex_unlock(&dev->coda_mutex);
 
 	coda_free_framebuffers(ctx);
 
@@ -2601,6 +3064,7 @@ static int coda_release(struct file *fil
 	v4l2_ctrl_handler_free(&ctx->ctrls);
 	clk_disable_unprepare(dev->clk_ahb);
 	clk_disable_unprepare(dev->clk_per);
+	pm_runtime_put_sync(&dev->plat_dev->dev);
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	clear_bit(ctx->idx, &dev->instance_mask);
@@ -2609,32 +3073,13 @@ static int coda_release(struct file *fil
 	return 0;
 }
 
-static unsigned int coda_poll(struct file *file,
-				 struct poll_table_struct *wait)
-{
-	struct coda_ctx *ctx = fh_to_ctx(file->private_data);
-	int ret;
-
-	coda_lock(ctx);
-	ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-	coda_unlock(ctx);
-	return ret;
-}
-
-static int coda_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct coda_ctx *ctx = fh_to_ctx(file->private_data);
-
-	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-}
-
 static const struct v4l2_file_operations coda_fops = {
 	.owner		= THIS_MODULE,
 	.open		= coda_open,
 	.release	= coda_release,
-	.poll		= coda_poll,
+	.poll		= v4l2_m2m_fop_poll,
 	.unlocked_ioctl	= video_ioctl2,
-	.mmap		= coda_mmap,
+	.mmap		= v4l2_m2m_fop_mmap,
 };
 
 static void coda_finish_decode(struct coda_ctx *ctx)
@@ -2643,14 +3088,16 @@ static void coda_finish_decode(struct co
 	struct coda_q_data *q_data_src;
 	struct coda_q_data *q_data_dst;
 	struct vb2_buffer *dst_buf;
+	struct coda_timestamp *ts;
 	int width, height;
 	int decoded_idx;
 	int display_idx;
 	u32 src_fourcc;
 	int success;
+	u32 err_mb;
 	u32 val;
 
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
 	/* Update kfifo out pointer from coda bitstream read pointer */
 	coda_kfifo_sync_from_device(ctx);
@@ -2693,19 +3140,34 @@ static void coda_finish_decode(struct co
 
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
-	val = coda_read(dev, CODA_RET_DEC_PIC_TYPE);
-	if ((val & 0x7) == 0) {
-		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
-		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+	/* frame crop information */
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		u32 left_right;
+		u32 top_bottom;
+
+		left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
+		top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
+
+		if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
+			/* Keep current crop information */
+		} else {
+			struct v4l2_rect *rect = &q_data_dst->rect;
+
+			rect->left = left_right >> 16 & 0xffff;
+			rect->top = top_bottom >> 16 & 0xffff;
+			rect->width = width - rect->left -
+				      (left_right & 0xffff);
+			rect->height = height - rect->top -
+				       (top_bottom & 0xffff);
+		}
 	} else {
-		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
-		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+		/* no cropping */
 	}
 
-	val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
-	if (val > 0)
+	err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
+	if (err_mb > 0)
 		v4l2_err(&dev->v4l2_dev,
-			 "errors in %d macroblocks\n", val);
+			 "errors in %d macroblocks\n", err_mb);
 
 	if (dev->devtype->product == CODA_7541) {
 		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
@@ -2713,7 +3175,7 @@ static void coda_finish_decode(struct co
 			/* not enough bitstream data */
 			v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 				 "prescan failed: %d\n", val);
-			ctx->prescan_failed = true;
+			ctx->hold = true;
 			return;
 		}
 	}
@@ -2741,13 +3203,38 @@ static void coda_finish_decode(struct co
 
 	if (decoded_idx == -1) {
 		/* no frame was decoded, but we might have a display frame */
-		if (display_idx < 0 && ctx->display_idx < 0)
-			ctx->prescan_failed = true;
+		if (display_idx >= 0 && display_idx < ctx->num_internal_frames)
+			ctx->sequence_offset++;
+		else if (ctx->display_idx < 0)
+			ctx->hold = true;
 	} else if (decoded_idx == -2) {
 		/* no frame was decoded, we still return the remaining buffers */
 	} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
 		v4l2_err(&dev->v4l2_dev,
 			 "decoded frame index out of range: %d\n", decoded_idx);
+	} else {
+		ts = list_first_entry(&ctx->timestamp_list,
+				      struct coda_timestamp, list);
+		list_del(&ts->list);
+		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
+		val -= ctx->sequence_offset;
+		if (val != (ts->sequence & 0xffff)) {
+			v4l2_err(&dev->v4l2_dev,
+				 "sequence number mismatch (%d(%d) != %d)\n",
+				 val, ctx->sequence_offset, ts->sequence);
+		}
+		ctx->frame_timestamps[decoded_idx] = *ts;
+		kfree(ts);
+
+		val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
+		if (val == 0)
+			ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME;
+		else if (val == 1)
+			ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME;
+		else
+			ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME;
+
+		ctx->frame_errors[decoded_idx] = err_mb;
 	}
 
 	if (display_idx == -1) {
@@ -2755,7 +3242,7 @@ static void coda_finish_decode(struct co
 		 * no more frames to be decoded, but there could still
 		 * be rotator output to dequeue
 		 */
-		ctx->prescan_failed = true;
+		ctx->hold = true;
 	} else if (display_idx == -3) {
 		/* possibly prescan failure */
 	} else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
@@ -2767,13 +3254,21 @@ static void coda_finish_decode(struct co
 	/* If a frame was copied out, return it */
 	if (ctx->display_idx >= 0 &&
 	    ctx->display_idx < ctx->num_internal_frames) {
-		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 		dst_buf->v4l2_buf.sequence = ctx->osequence++;
 
+		dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+					     V4L2_BUF_FLAG_PFRAME |
+					     V4L2_BUF_FLAG_BFRAME);
+		dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
+		ts = &ctx->frame_timestamps[ctx->display_idx];
+		dst_buf->v4l2_buf.timecode = ts->timecode;
+		dst_buf->v4l2_buf.timestamp = ts->timestamp;
+
 		vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
 
-		v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE :
-						     VB2_BUF_STATE_ERROR);
+		v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
+				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 
 		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 			"job finished: decoding frame (%d) (%s)\n",
@@ -2795,8 +3290,8 @@ static void coda_finish_encode(struct co
 	struct coda_dev *dev = ctx->dev;
 	u32 wr_ptr, start_ptr;
 
-	src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
 	/* Get results from the coda */
 	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
@@ -2833,6 +3328,8 @@ static void coda_finish_encode(struct co
 	dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
 
 	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
 
 	ctx->gopcounter--;
@@ -2851,8 +3348,6 @@ static irqreturn_t coda_irq_handler(int
 	struct coda_dev *dev = data;
 	struct coda_ctx *ctx;
 
-	cancel_delayed_work(&dev->timeout);
-
 	/* read status register to attend the IRQ */
 	coda_read(dev, CODA_REG_BIT_INT_STATUS);
 	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
@@ -2868,7 +3363,6 @@ static irqreturn_t coda_irq_handler(int
 	if (ctx->aborting) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			 "task has been aborted\n");
-		goto out;
 	}
 
 	if (coda_isbusy(ctx->dev)) {
@@ -2877,60 +3371,15 @@ static irqreturn_t coda_irq_handler(int
 		return IRQ_NONE;
 	}
 
-	if (ctx->inst_type == CODA_INST_DECODER)
-		coda_finish_decode(ctx);
-	else
-		coda_finish_encode(ctx);
-
-out:
-	if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) {
-		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-			 "%s: sent command 'SEQ_END' to coda\n", __func__);
-		if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
-			v4l2_err(&dev->v4l2_dev,
-				 "CODA_COMMAND_SEQ_END failed\n");
-		}
-
-		kfifo_init(&ctx->bitstream_fifo,
-			ctx->bitstream.vaddr, ctx->bitstream.size);
-
-		coda_free_framebuffers(ctx);
-		coda_free_context_buffers(ctx);
-	}
-
-	mutex_unlock(&dev->coda_mutex);
-	mutex_unlock(&ctx->buffer_mutex);
-
-	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
+	complete(&ctx->completion);
 
 	return IRQ_HANDLED;
 }
 
-static void coda_timeout(struct work_struct *work)
-{
-	struct coda_ctx *ctx;
-	struct coda_dev *dev = container_of(to_delayed_work(work),
-					    struct coda_dev, timeout);
-
-	dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n");
-
-	mutex_lock(&dev->dev_mutex);
-	list_for_each_entry(ctx, &dev->instances, list) {
-		if (mutex_is_locked(&ctx->buffer_mutex))
-			mutex_unlock(&ctx->buffer_mutex);
-		v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	}
-	mutex_unlock(&dev->dev_mutex);
-
-	mutex_unlock(&dev->coda_mutex);
-	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
-	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
-}
-
 static u32 coda_supported_firmwares[] = {
 	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
 	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
+	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
 };
 
 static bool coda_firmware_supported(u32 vernum)
@@ -2945,19 +3394,21 @@ static bool coda_firmware_supported(u32
 
 static int coda_hw_init(struct coda_dev *dev)
 {
-	u16 product, major, minor, release;
 	u32 data;
 	u16 *p;
 	int i, ret;
 
 	ret = clk_prepare_enable(dev->clk_per);
 	if (ret)
-		return ret;
+		goto err_clk_per;
 
 	ret = clk_prepare_enable(dev->clk_ahb);
 	if (ret)
 		goto err_clk_ahb;
 
+	if (dev->rstc)
+		reset_control_reset(dev->rstc);
+
 	/*
 	 * Copy the first CODA_ISRAM_SIZE in the internal SRAM.
 	 * The 16-bit chars in the code buffer are in memory access
@@ -2985,7 +3436,8 @@ static int coda_hw_init(struct coda_dev
 		coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
 
 	/* Tell the BIT where to find everything it needs */
-	if (dev->devtype->product == CODA_7541) {
+	if (dev->devtype->product == CODA_960 ||
+	    dev->devtype->product == CODA_7541) {
 		coda_write(dev, dev->tempbuf.paddr,
 				CODA_REG_BIT_TEMP_BUF_ADDR);
 		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
@@ -3005,7 +3457,10 @@ static int coda_hw_init(struct coda_dev
 	default:
 		coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL);
 	}
-	coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
+	if (dev->devtype->product == CODA_960)
+		coda_write(dev, 1 << 12, CODA_REG_BIT_FRAME_MEM_CTRL);
+	else
+		coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
 
 	if (dev->devtype->product != CODA_DX6)
 		coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
@@ -3022,17 +3477,46 @@ static int coda_hw_init(struct coda_dev
 	coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
 	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
 
-	/* Load firmware */
+	clk_disable_unprepare(dev->clk_ahb);
+	clk_disable_unprepare(dev->clk_per);
+
+	return 0;
+
+err_clk_ahb:
+	clk_disable_unprepare(dev->clk_per);
+err_clk_per:
+	return ret;
+}
+
+static int coda_check_firmware(struct coda_dev *dev)
+{
+	u16 product, major, minor, release;
+	u32 data;
+	int ret;
+
+	ret = clk_prepare_enable(dev->clk_per);
+	if (ret)
+		goto err_clk_per;
+
+	ret = clk_prepare_enable(dev->clk_ahb);
+	if (ret)
+		goto err_clk_ahb;
+
 	coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
 	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
 	coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
 	coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
 	coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND);
 	if (coda_wait_timeout(dev)) {
-		clk_disable_unprepare(dev->clk_per);
-		clk_disable_unprepare(dev->clk_ahb);
 		v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
-		return -EIO;
+		ret = -EIO;
+		goto err_run_cmd;
+	}
+
+	if (dev->devtype->product == CODA_960) {
+		data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
+		v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
+			  data);
 	}
 
 	/* Check we are compatible with the loaded firmware */
@@ -3066,8 +3550,11 @@ static int coda_hw_init(struct coda_dev
 
 	return 0;
 
+err_run_cmd:
+	clk_disable_unprepare(dev->clk_ahb);
 err_clk_ahb:
 	clk_disable_unprepare(dev->clk_per);
+err_clk_per:
 	return ret;
 }
 
@@ -3083,7 +3570,8 @@ static void coda_fw_callback(const struc
 	}
 
 	/* allocate auxiliary per-device code buffer for the BIT processor */
-	ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size);
+	ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
+				 dev->debugfs_root);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to allocate code buffer\n");
 		return;
@@ -3093,10 +3581,37 @@ static void coda_fw_callback(const struc
 	memcpy(dev->codebuf.vaddr, fw->data, fw->size);
 	release_firmware(fw);
 
-	ret = coda_hw_init(dev);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
-		return;
+	if (pm_runtime_enabled(&pdev->dev) && pdev->dev.pm_domain) {
+		/*
+		 * Enabling power temporarily will cause coda_hw_init to be
+		 * called via coda_runtime_resume by the pm domain.
+		 */
+		ret = pm_runtime_get_sync(&dev->plat_dev->dev);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to power on: %d\n",
+				 ret);
+			return;
+		}
+
+		ret = coda_check_firmware(dev);
+		if (ret < 0)
+			return;
+
+		pm_runtime_put_sync(&dev->plat_dev->dev);
+	} else {
+		/*
+		 * If runtime pm is disabled or pm_domain is not set,
+		 * initialize once manually.
+		 */
+		ret = coda_hw_init(dev);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
+			return;
+		}
+
+		ret = coda_check_firmware(dev);
+		if (ret < 0)
+			return;
 	}
 
 	dev->vfd.fops	= &coda_fops,
@@ -3150,20 +3665,45 @@ static int coda_firmware_request(struct
 enum coda_platform {
 	CODA_IMX27,
 	CODA_IMX53,
+	CODA_IMX6Q,
+	CODA_IMX6DL,
 };
 
 static const struct coda_devtype coda_devdata[] = {
 	[CODA_IMX27] = {
-		/*(DEBLOBBED)*/"/*(DEBLOBBED)*/",
-		.product    = CODA_DX6,
-		.codecs     = codadx6_codecs,
-		.num_codecs = ARRAY_SIZE(codadx6_codecs),
+		.firmware     = "/*(DEBLOBBED)*/",
+		.product      = CODA_DX6,
+		.codecs       = codadx6_codecs,
+		.num_codecs   = ARRAY_SIZE(codadx6_codecs),
+		.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
+		.iram_size    = 0xb000,
 	},
 	[CODA_IMX53] = {
-		/*(DEBLOBBED)*/"/*(DEBLOBBED)*/",
-		.product    = CODA_7541,
-		.codecs     = coda7_codecs,
-		.num_codecs = ARRAY_SIZE(coda7_codecs),
+		.firmware     = "/*(DEBLOBBED)*/",
+		.product      = CODA_7541,
+		.codecs       = coda7_codecs,
+		.num_codecs   = ARRAY_SIZE(coda7_codecs),
+		.workbuf_size = 128 * 1024,
+		.tempbuf_size = 304 * 1024,
+		.iram_size    = 0x14000,
+	},
+	[CODA_IMX6Q] = {
+		.firmware     = "/*(DEBLOBBED)*/",
+		.product      = CODA_960,
+		.codecs       = coda9_codecs,
+		.num_codecs   = ARRAY_SIZE(coda9_codecs),
+		.workbuf_size = 80 * 1024,
+		.tempbuf_size = 204 * 1024,
+		.iram_size    = 0x21000,
+	},
+	[CODA_IMX6DL] = {
+		.firmware     = "/*(DEBLOBBED)*/",
+		.product      = CODA_960,
+		.codecs       = coda9_codecs,
+		.num_codecs   = ARRAY_SIZE(coda9_codecs),
+		.workbuf_size = 80 * 1024,
+		.tempbuf_size = 204 * 1024,
+		.iram_size    = 0x20000,
 	},
 };
 
@@ -3178,6 +3718,8 @@ MODULE_DEVICE_TABLE(platform, coda_platf
 static const struct of_device_id coda_dt_ids[] = {
 	{ .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
 	{ .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
+	{ .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] },
+	{ .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, coda_dt_ids);
@@ -3204,7 +3746,6 @@ static int coda_probe(struct platform_de
 
 	spin_lock_init(&dev->irqlock);
 	INIT_LIST_HEAD(&dev->instances);
-	INIT_DELAYED_WORK(&dev->timeout, coda_timeout);
 
 	dev->plat_dev = pdev;
 	dev->clk_per = devm_clk_get(&pdev->dev, "per");
@@ -3229,13 +3770,25 @@ static int coda_probe(struct platform_de
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "failed to get irq resource\n");
-		return -ENOENT;
+		return irq;
 	}
 
-	if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler,
-		IRQF_ONESHOT, dev_name(&pdev->dev), dev) < 0) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		return -ENOENT;
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler,
+			IRQF_ONESHOT, dev_name(&pdev->dev), dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+		return ret;
+	}
+
+	dev->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(dev->rstc)) {
+		ret = PTR_ERR(dev->rstc);
+		if (ret == -ENOENT || ret == -ENOSYS) {
+			dev->rstc = NULL;
+		} else {
+			dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
+			return ret;
+		}
 	}
 
 	/* Get IRAM pool from device tree or platform data */
@@ -3266,24 +3819,26 @@ static int coda_probe(struct platform_de
 		return -EINVAL;
 	}
 
+	dev->debugfs_root = debugfs_create_dir("coda", NULL);
+	if (!dev->debugfs_root)
+		dev_warn(&pdev->dev, "failed to create debugfs root\n");
+
 	/* allocate auxiliary per-device buffers for the BIT processor */
-	switch (dev->devtype->product) {
-	case CODA_DX6:
+	if (dev->devtype->product == CODA_DX6) {
 		ret = coda_alloc_aux_buf(dev, &dev->workbuf,
-					 CODADX6_WORK_BUF_SIZE);
+					 dev->devtype->workbuf_size, "workbuf",
+					 dev->debugfs_root);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to allocate work buffer\n");
 			v4l2_device_unregister(&dev->v4l2_dev);
 			return ret;
 		}
-		break;
-	case CODA_7541:
-		dev->tempbuf.size = CODA7_TEMP_BUF_SIZE;
-		break;
 	}
-	if (dev->tempbuf.size) {
+
+	if (dev->devtype->tempbuf_size) {
 		ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
-					 dev->tempbuf.size);
+					 dev->devtype->tempbuf_size, "tempbuf",
+					 dev->debugfs_root);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to allocate temp buffer\n");
 			v4l2_device_unregister(&dev->v4l2_dev);
@@ -3291,23 +3846,29 @@ static int coda_probe(struct platform_de
 		}
 	}
 
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		dev->iram_size = CODADX6_IRAM_SIZE;
-		break;
-	case CODA_7541:
-		dev->iram_size = CODA7_IRAM_SIZE;
-		break;
-	}
-	dev->iram_vaddr = (unsigned long)gen_pool_dma_alloc(dev->iram_pool,
-			dev->iram_size, (dma_addr_t *)&dev->iram_paddr);
-	if (!dev->iram_vaddr) {
+	dev->iram.size = dev->devtype->iram_size;
+	dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size,
+					     &dev->iram.paddr);
+	if (!dev->iram.vaddr) {
 		dev_err(&pdev->dev, "unable to alloc iram\n");
 		return -ENOMEM;
 	}
 
+	dev->iram.blob.data = dev->iram.vaddr;
+	dev->iram.blob.size = dev->iram.size;
+	dev->iram.dentry = debugfs_create_blob("iram", 0644, dev->debugfs_root,
+					       &dev->iram.blob);
+
+	dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	if (!dev->workqueue) {
+		dev_err(&pdev->dev, "unable to alloc workqueue\n");
+		return -ENOMEM;
+	}
+
 	platform_set_drvdata(pdev, dev);
 
+	pm_runtime_enable(&pdev->dev);
+
 	return coda_firmware_request(dev);
 }
 
@@ -3318,17 +3879,41 @@ static int coda_remove(struct platform_d
 	video_unregister_device(&dev->vfd);
 	if (dev->m2m_dev)
 		v4l2_m2m_release(dev->m2m_dev);
+	pm_runtime_disable(&pdev->dev);
 	if (dev->alloc_ctx)
 		vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
 	v4l2_device_unregister(&dev->v4l2_dev);
-	if (dev->iram_vaddr)
-		gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size);
+	destroy_workqueue(dev->workqueue);
+	if (dev->iram.vaddr)
+		gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr,
+			      dev->iram.size);
 	coda_free_aux_buf(dev, &dev->codebuf);
 	coda_free_aux_buf(dev, &dev->tempbuf);
 	coda_free_aux_buf(dev, &dev->workbuf);
+	debugfs_remove_recursive(dev->debugfs_root);
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int coda_runtime_resume(struct device *dev)
+{
+	struct coda_dev *cdev = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (dev->pm_domain) {
+		ret = coda_hw_init(cdev);
+		if (ret)
+			v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n");
+	}
+
+	return ret;
+}
+#endif
+
+static const struct dev_pm_ops coda_pm_ops = {
+	SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL)
+};
+
 static struct platform_driver coda_driver = {
 	.probe	= coda_probe,
 	.remove	= coda_remove,
@@ -3336,6 +3921,7 @@ static struct platform_driver coda_drive
 		.name	= CODA_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(coda_dt_ids),
+		.pm	= &coda_pm_ops,
 	},
 	.id_table = coda_platform_ids,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/coda.h linux-libre-3.17-rc7-gnu/drivers/media/platform/coda.h
--- linux-libre-3.16-gnu/drivers/media/platform/coda.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/coda.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,14 @@
 #define CODA_REG_BIT_CODE_RESET		0x014
 #define		CODA_REG_RESET_ENABLE		(1 << 0)
 #define CODA_REG_BIT_CUR_PC			0x018
+#define CODA9_REG_BIT_SW_RESET			0x024
+#define		CODA9_SW_RESET_BPU_CORE   0x008
+#define		CODA9_SW_RESET_BPU_BUS    0x010
+#define		CODA9_SW_RESET_VCE_CORE   0x020
+#define		CODA9_SW_RESET_VCE_BUS    0x040
+#define		CODA9_SW_RESET_GDI_CORE   0x080
+#define		CODA9_SW_RESET_GDI_BUS    0x100
+#define CODA9_REG_BIT_SW_RESET_STATUS		0x034
 
 /* Static SW registers */
 #define CODA_REG_BIT_CODE_BUF_ADDR		0x100
@@ -39,9 +47,11 @@
 #define		CODADX6_STREAM_BUF_PIC_FLUSH	(1 << 2)
 #define		CODA7_STREAM_BUF_DYNALLOC_EN	(1 << 5)
 #define		CODADX6_STREAM_BUF_DYNALLOC_EN	(1 << 4)
-#define 	CODA_STREAM_CHKDIS_OFFSET	(1 << 1)
+#define		CODADX6_STREAM_CHKDIS_OFFSET	(1 << 1)
+#define		CODA7_STREAM_SEL_64BITS_ENDIAN	(1 << 1)
 #define		CODA_STREAM_ENDIAN_SELECT	(1 << 0)
 #define CODA_REG_BIT_FRAME_MEM_CTRL		0x110
+#define		CODA_FRAME_CHROMA_INTERLEAVE	(1 << 2)
 #define		CODA_IMAGE_ENDIAN_SELECT	(1 << 0)
 #define CODA_REG_BIT_BIT_STREAM_PARAM		0x114
 #define		CODA_BIT_STREAM_END_FLAG	(1 << 2)
@@ -52,13 +62,21 @@
 #define CODA_REG_BIT_FRM_DIS_FLG(x)		(0x150 + 4 * (x))
 #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR	0x140
 #define CODA7_REG_BIT_AXI_SRAM_USE		0x140
+#define		CODA9_USE_HOST_BTP_ENABLE	(1 << 13)
+#define		CODA9_USE_HOST_OVL_ENABLE	(1 << 12)
 #define		CODA7_USE_HOST_ME_ENABLE	(1 << 11)
+#define		CODA9_USE_HOST_DBK_ENABLE	(3 << 10)
 #define		CODA7_USE_HOST_OVL_ENABLE	(1 << 10)
 #define		CODA7_USE_HOST_DBK_ENABLE	(1 << 9)
+#define		CODA9_USE_HOST_IP_ENABLE	(1 << 9)
 #define		CODA7_USE_HOST_IP_ENABLE	(1 << 8)
+#define		CODA9_USE_HOST_BIT_ENABLE	(1 << 8)
 #define		CODA7_USE_HOST_BIT_ENABLE	(1 << 7)
+#define		CODA9_USE_BTP_ENABLE		(1 << 5)
 #define		CODA7_USE_ME_ENABLE		(1 << 4)
+#define		CODA9_USE_OVL_ENABLE		(1 << 4)
 #define		CODA7_USE_OVL_ENABLE		(1 << 3)
+#define		CODA9_USE_DBK_ENABLE		(3 << 2)
 #define		CODA7_USE_DBK_ENABLE		(1 << 2)
 #define		CODA7_USE_IP_ENABLE		(1 << 1)
 #define		CODA7_USE_BIT_ENABLE		(1 << 0)
@@ -93,6 +111,18 @@
 #define		CODA7_MODE_ENCODE_H264		8
 #define		CODA7_MODE_ENCODE_MP4		11
 #define		CODA7_MODE_ENCODE_MJPG		13
+#define		CODA9_MODE_DECODE_H264		0
+#define		CODA9_MODE_DECODE_VC1		1
+#define		CODA9_MODE_DECODE_MP2		2
+#define		CODA9_MODE_DECODE_MP4		3
+#define		CODA9_MODE_DECODE_DV3		3
+#define		CODA9_MODE_DECODE_RV		4
+#define		CODA9_MODE_DECODE_AVS		5
+#define		CODA9_MODE_DECODE_MJPG		6
+#define		CODA9_MODE_DECODE_VPX		7
+#define		CODA9_MODE_ENCODE_H264		8
+#define		CODA9_MODE_ENCODE_MP4		11
+#define		CODA9_MODE_ENCODE_MJPG		13
 #define 	CODA_MODE_INVALID		0xffff
 #define CODA_REG_BIT_INT_ENABLE		0x170
 #define		CODA_INT_INTERRUPT_ENABLE	(1 << 3)
@@ -129,6 +159,7 @@
 #define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE		0x1a0
 
 #define CODA7_RET_DEC_SEQ_ASPECT		0x1b0
+#define CODA9_RET_DEC_SEQ_BITRATE		0x1b4
 #define CODA_RET_DEC_SEQ_SUCCESS		0x1c0
 #define CODA_RET_DEC_SEQ_SRC_FMT		0x1c4 /* SRC_SIZE on CODA7 */
 #define CODA_RET_DEC_SEQ_SRC_SIZE		0x1c4
@@ -145,13 +176,19 @@
 #define CODA_RET_DEC_SEQ_FRATE_DR		0x1e8
 #define CODA_RET_DEC_SEQ_JPG_PARA		0x1e4
 #define CODA_RET_DEC_SEQ_JPG_THUMB_IND		0x1e8
+#define CODA9_RET_DEC_SEQ_HEADER_REPORT		0x1ec
 
 /* Decoder Picture Run */
 #define CODA_CMD_DEC_PIC_ROT_MODE		0x180
 #define CODA_CMD_DEC_PIC_ROT_ADDR_Y		0x184
+#define CODA9_CMD_DEC_PIC_ROT_INDEX		0x184
 #define CODA_CMD_DEC_PIC_ROT_ADDR_CB		0x188
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y		0x188
 #define CODA_CMD_DEC_PIC_ROT_ADDR_CR		0x18c
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB		0x18c
 #define CODA_CMD_DEC_PIC_ROT_STRIDE		0x190
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR		0x190
+#define CODA9_CMD_DEC_PIC_ROT_STRIDE		0x1b8
 
 #define CODA_CMD_DEC_PIC_OPTION			0x194
 #define		CODA_PRE_SCAN_EN			(1 << 0)
@@ -183,25 +220,39 @@
 #define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM	0x1e4
 #define CODA_RET_DEC_PIC_FRAME_NEED		0x1ec
 
+#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT	0x1e8
+#define CODA9_RET_DEC_PIC_ASPECT		0x1f0
+#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO	0x1f0
+#define CODA9_RET_DEC_PIC_FRATE_NR		0x1f4
+#define CODA9_RET_DEC_PIC_FRATE_DR		0x1f8
+
 /* Encoder Sequence Initialization */
 #define CODA_CMD_ENC_SEQ_BB_START				0x180
 #define CODA_CMD_ENC_SEQ_BB_SIZE				0x184
 #define CODA_CMD_ENC_SEQ_OPTION				0x188
 #define		CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET		9
+#define		CODA9_OPTION_MVC_PREFIX_NAL_OFFSET		9
 #define		CODA7_OPTION_GAMMA_OFFSET			8
+#define		CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET		8
 #define		CODA7_OPTION_RCQPMAX_OFFSET			7
+#define		CODA9_OPTION_GAMMA_OFFSET			7
 #define		CODADX6_OPTION_GAMMA_OFFSET			7
 #define		CODA7_OPTION_RCQPMIN_OFFSET			6
+#define		CODA9_OPTION_RCQPMAX_OFFSET			6
 #define		CODA_OPTION_LIMITQP_OFFSET			6
 #define		CODA_OPTION_RCINTRAQP_OFFSET			5
 #define		CODA_OPTION_FMO_OFFSET				4
+#define		CODA9_OPTION_MVC_INTERVIEW_OFFSET		4
 #define		CODA_OPTION_AVC_AUD_OFFSET			2
 #define		CODA_OPTION_SLICEREPORT_OFFSET			1
 #define CODA_CMD_ENC_SEQ_COD_STD				0x18c
 #define		CODA_STD_MPEG4					0
+#define		CODA9_STD_H264					0
 #define		CODA_STD_H263					1
 #define		CODA_STD_H264					2
 #define		CODA_STD_MJPG					3
+#define		CODA9_STD_MPEG4					3
+
 #define CODA_CMD_ENC_SEQ_SRC_SIZE				0x190
 #define		CODA7_PICWIDTH_OFFSET				16
 #define		CODA7_PICWIDTH_MASK				0xffff
@@ -268,15 +319,26 @@
 #define CODA7_CMD_ENC_SEQ_SEARCH_BASE				0x1b8
 #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE				0x1bc
 #define CODA7_CMD_ENC_SEQ_INTRA_QP				0x1c4
-#define CODA_CMD_ENC_SEQ_RC_QP_MAX				0x1c8
+#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX				0x1c8
+#define		CODA_QPMIN_OFFSET				8
+#define		CODA_QPMIN_MASK					0x3f
 #define		CODA_QPMAX_OFFSET				0
 #define		CODA_QPMAX_MASK					0x3f
 #define CODA_CMD_ENC_SEQ_RC_GAMMA				0x1cc
 #define		CODA_GAMMA_OFFSET				0
 #define		CODA_GAMMA_MASK					0xffff
+#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE			0x1d0
+#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT				0x1d4
+#define CODA9_CMD_ENC_SEQ_ME_OPTION				0x1d8
 #define CODA_RET_ENC_SEQ_SUCCESS				0x1c0
 
 /* Encoder Picture Run */
+#define CODA9_CMD_ENC_PIC_SRC_INDEX		0x180
+#define CODA9_CMD_ENC_PIC_SRC_STRIDE		0x184
+#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC	0x1a4
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y		0x1a8
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB		0x1ac
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR		0x1b0
 #define CODA_CMD_ENC_PIC_SRC_ADDR_Y	0x180
 #define CODA_CMD_ENC_PIC_SRC_ADDR_CB	0x184
 #define CODA_CMD_ENC_PIC_SRC_ADDR_CR	0x188
@@ -291,7 +353,11 @@
 #define		CODA_MIR_VER					(0x1 << 2)
 #define		CODA_MIR_HOR					(0x2 << 2)
 #define		CODA_MIR_VER_HOR				(0x3 << 2)
-#define CODA_CMD_ENC_PIC_OPTION	0x194
+#define CODA_CMD_ENC_PIC_OPTION		0x194
+#define		CODA_FORCE_IPICTURE				BIT(1)
+#define		CODA_REPORT_MB_INFO				BIT(3)
+#define		CODA_REPORT_MV_INFO				BIT(4)
+#define		CODA_REPORT_SLICE_INFO				BIT(5)
 #define CODA_CMD_ENC_PIC_BB_START	0x198
 #define CODA_CMD_ENC_PIC_BB_SIZE	0x19c
 #define CODA_RET_ENC_FRAME_NUM		0x1c0
@@ -306,13 +372,30 @@
 #define CODA_CMD_SET_FRAME_BUF_STRIDE		0x184
 #define CODA_CMD_SET_FRAME_SLICE_BB_START	0x188
 #define CODA_CMD_SET_FRAME_SLICE_BB_SIZE	0x18c
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A		0x188
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B		0x18c
 #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR	0x190
 #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR	0x194
 #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR	0x198
 #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR	0x19c
 #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR	0x1a0
 #define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE	0x1a4
+#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR	0x1a4
 #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE	0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_SIZE		0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_CONFIG	0x1ac
+#define		CODA9_CACHE_BYPASS_OFFSET		28
+#define		CODA9_CACHE_DUALCONF_OFFSET		26
+#define		CODA9_CACHE_PAGEMERGE_OFFSET		24
+#define		CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET	16
+#define		CODA9_CACHE_CB_BUFFER_SIZE_OFFSET	8
+#define		CODA9_CACHE_CR_BUFFER_SIZE_OFFSET	0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC	0x1b0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC	0x1b4
+#define CODA9_CMD_SET_FRAME_DP_BUF_BASE		0x1b0
+#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE		0x1b4
+#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE	0x1b8
+#define CODA9_CMD_SET_FRAME_DELAY		0x1bc
 
 /* Encoder Header */
 #define CODA_CMD_ENC_HEADER_CODE	0x180
@@ -322,8 +405,11 @@
 #define		CODA_HEADER_MP4V_VOL	0
 #define		CODA_HEADER_MP4V_VOS	1
 #define		CODA_HEADER_MP4V_VIS	2
+#define		CODA9_HEADER_FRAME_CROP	(1 << 3)
 #define CODA_CMD_ENC_HEADER_BB_START	0x184
 #define CODA_CMD_ENC_HEADER_BB_SIZE	0x188
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H	0x18c
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V	0x190
 
 /* Get Version */
 #define CODA_CMD_FIRMWARE_VERNUM		0x1c0
@@ -334,5 +420,28 @@
 #define		CODA_FIRMWARE_VERNUM(product, major, minor, release)	\
 			((product) << 16 | ((major) << 12) |		\
 			((minor) << 8) | (release))
+#define CODA9_CMD_FIRMWARE_CODE_REV		0x1c4
+
+#define CODA9_GDMA_BASE				0x1000
+#define CODA9_GDI_WPROT_ERR_CLR			(CODA9_GDMA_BASE + 0x0a0)
+#define CODA9_GDI_WPROT_RGN_EN			(CODA9_GDMA_BASE + 0x0ac)
+
+#define CODA9_GDI_BUS_CTRL			(CODA9_GDMA_BASE + 0x0f0)
+#define CODA9_GDI_BUS_STATUS			(CODA9_GDMA_BASE + 0x0f4)
+
+#define CODA9_GDI_XY2_CAS_0			(CODA9_GDMA_BASE + 0x800)
+#define CODA9_GDI_XY2_CAS_F			(CODA9_GDMA_BASE + 0x83c)
+
+#define CODA9_GDI_XY2_BA_0			(CODA9_GDMA_BASE + 0x840)
+#define CODA9_GDI_XY2_BA_1			(CODA9_GDMA_BASE + 0x844)
+#define CODA9_GDI_XY2_BA_2			(CODA9_GDMA_BASE + 0x848)
+#define CODA9_GDI_XY2_BA_3			(CODA9_GDMA_BASE + 0x84c)
+
+#define CODA9_GDI_XY2_RAS_0			(CODA9_GDMA_BASE + 0x850)
+#define CODA9_GDI_XY2_RAS_F			(CODA9_GDMA_BASE + 0x88c)
+
+#define CODA9_GDI_XY2_RBC_CONFIG		(CODA9_GDMA_BASE + 0x890)
+#define CODA9_GDI_RBC2_AXI_0			(CODA9_GDMA_BASE + 0x8a0)
+#define CODA9_GDI_RBC2_AXI_1F			(CODA9_GDMA_BASE + 0x91c)
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/dm644x_ccdc.c linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/dm644x_ccdc.c
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/dm644x_ccdc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/dm644x_ccdc.c	2014-09-28 17:29:07.000000000 -0400
@@ -581,13 +581,8 @@ void ccdc_config_raw(void)
 	     config_params->alaw.enable)
 		syn_mode |= CCDC_DATA_PACK_ENABLE;
 
-#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
-	/* enable video port */
-	val = CCDC_ENABLE_VIDEO_PORT;
-#else
 	/* disable video port */
 	val = CCDC_DISABLE_VIDEO_PORT;
-#endif
 
 	if (config_params->data_sz == CCDC_DATA_8BITS)
 		val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/vpbe_display.c linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpbe_display.c
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/vpbe_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpbe_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -1709,7 +1709,6 @@ static int register_device(struct vpbe_l
 	vpbe_display_layer->disp_dev = disp_dev;
 	/* set the driver data in platform device */
 	platform_set_drvdata(pdev, disp_dev);
-	set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags);
 	video_set_drvdata(&vpbe_display_layer->video_dev,
 			  vpbe_display_layer);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/vpfe_capture.c linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpfe_capture.c
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/vpfe_capture.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpfe_capture.c	2014-09-28 17:29:07.000000000 -0400
@@ -1916,7 +1916,6 @@ static int vpfe_probe(struct platform_de
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
 		"video_dev=%x\n", (int)&vpfe_dev->video_dev);
 	vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags);
 	ret = video_register_device(vpfe_dev->video_dev,
 				    VFL_TYPE_GRABBER, -1);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_capture.c linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_capture.c
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_capture.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_capture.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,32 +39,10 @@ MODULE_VERSION(VPIF_CAPTURE_VERSION);
 		v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
 
 static int debug = 1;
-static u32 ch0_numbuffers = 3;
-static u32 ch1_numbuffers = 3;
-static u32 ch0_bufsize = 1920 * 1080 * 2;
-static u32 ch1_bufsize = 720 * 576 * 2;
 
 module_param(debug, int, 0644);
-module_param(ch0_numbuffers, uint, S_IRUGO);
-module_param(ch1_numbuffers, uint, S_IRUGO);
-module_param(ch0_bufsize, uint, S_IRUGO);
-module_param(ch1_bufsize, uint, S_IRUGO);
 
 MODULE_PARM_DESC(debug, "Debug level 0-1");
-MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)");
-MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)");
-MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)");
-MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)");
-
-static struct vpif_config_params config_params = {
-	.min_numbuffers = 3,
-	.numbuffers[0] = 3,
-	.numbuffers[1] = 3,
-	.min_bufsize[0] = 720 * 480 * 2,
-	.min_bufsize[1] = 720 * 480 * 2,
-	.channel_bufsize[0] = 1920 * 1080 * 2,
-	.channel_bufsize[1] = 720 * 576 * 2,
-};
 
 #define VPIF_DRIVER_NAME	"vpif_capture"
 
@@ -521,10 +499,28 @@ static int vpif_update_std_info(struct c
 	common->width = std_info->width;
 	common->fmt.fmt.pix.height = std_info->height;
 	common->height = std_info->height;
+	common->fmt.fmt.pix.sizeimage = common->height * common->width * 2;
 	common->fmt.fmt.pix.bytesperline = std_info->width;
 	vpifparams->video_params.hpitch = std_info->width;
 	vpifparams->video_params.storage_mode = std_info->frm_fmt;
 
+	if (vid_ch->stdid)
+		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	else
+		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+	if (ch->vpifparams.std_info.frm_fmt)
+		common->fmt.fmt.pix.field = V4L2_FIELD_NONE;
+	else
+		common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+	if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
+		common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+	else
+		common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
+
+	common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
 	return 0;
 }
 
@@ -601,27 +597,6 @@ static void vpif_calculate_offsets(struc
 }
 
 /**
- * vpif_config_format: configure default frame format in the device
- * ch : ptr to channel object
- */
-static void vpif_config_format(struct channel_obj *ch)
-{
-	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-
-	vpif_dbg(2, debug, "vpif_config_format\n");
-
-	common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
-	common->fmt.fmt.pix.sizeimage
-	    = config_params.channel_bufsize[ch->channel_id];
-
-	if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
-		common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
-	else
-		common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
-	common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-}
-
-/**
  * vpif_get_default_field() - Get default field type based on interface
  * @vpif_params - ptr to vpif params
  */
@@ -633,112 +608,6 @@ static inline enum v4l2_field vpif_get_d
 }
 
 /**
- * vpif_check_format()  - check given pixel format for compatibility
- * @ch - channel  ptr
- * @pixfmt - Given pixel format
- * @update - update the values as per hardware requirement
- *
- * Check the application pixel format for S_FMT and update the input
- * values as per hardware limits for TRY_FMT. The default pixel and
- * field format is selected based on interface type.
- */
-static int vpif_check_format(struct channel_obj *ch,
-			     struct v4l2_pix_format *pixfmt,
-			     int update)
-{
-	struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
-	struct vpif_params *vpif_params = &ch->vpifparams;
-	enum v4l2_field field = pixfmt->field;
-	u32 sizeimage, hpitch, vpitch;
-	int ret = -EINVAL;
-
-	vpif_dbg(2, debug, "vpif_check_format\n");
-	/**
-	 * first check for the pixel format. If if_type is Raw bayer,
-	 * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only
-	 * V4L2_PIX_FMT_YUV422P is supported
-	 */
-	if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
-		if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) {
-			if (!update) {
-				vpif_dbg(2, debug, "invalid pix format\n");
-				goto exit;
-			}
-			pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
-		}
-	} else {
-		if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) {
-			if (!update) {
-				vpif_dbg(2, debug, "invalid pixel format\n");
-				goto exit;
-			}
-			pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
-		}
-	}
-
-	if (!(VPIF_VALID_FIELD(field))) {
-		if (!update) {
-			vpif_dbg(2, debug, "invalid field format\n");
-			goto exit;
-		}
-		/**
-		 * By default use FIELD_NONE for RAW Bayer capture
-		 * and FIELD_INTERLACED for other interfaces
-		 */
-		field = vpif_get_default_field(&vpif_params->iface);
-	} else if (field == V4L2_FIELD_ANY)
-		/* unsupported field. Use default */
-		field = vpif_get_default_field(&vpif_params->iface);
-
-	/* validate the hpitch */
-	hpitch = pixfmt->bytesperline;
-	if (hpitch < vpif_params->std_info.width) {
-		if (!update) {
-			vpif_dbg(2, debug, "invalid hpitch\n");
-			goto exit;
-		}
-		hpitch = vpif_params->std_info.width;
-	}
-
-	sizeimage = pixfmt->sizeimage;
-
-	vpitch = sizeimage / (hpitch * 2);
-
-	/* validate the vpitch */
-	if (vpitch < vpif_params->std_info.height) {
-		if (!update) {
-			vpif_dbg(2, debug, "Invalid vpitch\n");
-			goto exit;
-		}
-		vpitch = vpif_params->std_info.height;
-	}
-
-	/* Check for 8 byte alignment */
-	if (!ALIGN(hpitch, 8)) {
-		if (!update) {
-			vpif_dbg(2, debug, "invalid pitch alignment\n");
-			goto exit;
-		}
-		/* adjust to next 8 byte boundary */
-		hpitch = (((hpitch + 7) / 8) * 8);
-	}
-	/* if update is set, modify the bytesperline and sizeimage */
-	if (update) {
-		pixfmt->bytesperline = hpitch;
-		pixfmt->sizeimage = hpitch * vpitch * 2;
-	}
-	/**
-	 * Image width and height is always based on current standard width and
-	 * height
-	 */
-	pixfmt->width = common->fmt.fmt.pix.width;
-	pixfmt->height = common->fmt.fmt.pix.height;
-	return 0;
-exit:
-	return ret;
-}
-
-/**
  * vpif_config_addr() - function to configure buffer address in vpif
  * @ch - channel ptr
  * @muxmode - channel mux mode
@@ -948,9 +817,6 @@ static int vpif_s_std(struct file *file,
 		return -EINVAL;
 	}
 
-	/* Configure the default format information */
-	vpif_config_format(ch);
-
 	/* set standard in the sub device */
 	ret = v4l2_subdev_call(ch->sd, video, s_std, std_id);
 	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
@@ -977,10 +843,8 @@ static int vpif_enum_input(struct file *
 
 	chan_cfg = &config->chan_config[ch->channel_id];
 
-	if (input->index >= chan_cfg->input_count) {
-		vpif_dbg(1, debug, "Invalid input index\n");
+	if (input->index >= chan_cfg->input_count)
 		return -EINVAL;
-	}
 
 	memcpy(input, &chan_cfg->inputs[input->index].input,
 		sizeof(*input));
@@ -1069,8 +933,34 @@ static int vpif_try_fmt_vid_cap(struct f
 	struct video_device *vdev = video_devdata(file);
 	struct channel_obj *ch = video_get_drvdata(vdev);
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+	struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+	struct vpif_params *vpif_params = &ch->vpifparams;
 
-	return vpif_check_format(ch, pixfmt, 1);
+	/*
+	 * to supress v4l-compliance warnings silently correct
+	 * the pixelformat
+	 */
+	if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
+		if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8)
+			pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
+	} else {
+		if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P)
+			pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
+	}
+
+	common->fmt.fmt.pix.pixelformat = pixfmt->pixelformat;
+
+	vpif_update_std_info(ch);
+
+	pixfmt->field = common->fmt.fmt.pix.field;
+	pixfmt->colorspace = common->fmt.fmt.pix.colorspace;
+	pixfmt->bytesperline = common->fmt.fmt.pix.width;
+	pixfmt->width = common->fmt.fmt.pix.width;
+	pixfmt->height = common->fmt.fmt.pix.height;
+	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
+	pixfmt->priv = 0;
+
+	return 0;
 }
 
 
@@ -1108,20 +998,17 @@ static int vpif_s_fmt_vid_cap(struct fil
 	struct video_device *vdev = video_devdata(file);
 	struct channel_obj *ch = video_get_drvdata(vdev);
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-	struct v4l2_pix_format *pixfmt;
-	int ret = 0;
+	int ret;
 
 	vpif_dbg(2, debug, "%s\n", __func__);
 
 	if (vb2_is_busy(&common->buffer_queue))
 		return -EBUSY;
 
-	pixfmt = &fmt->fmt.pix;
-	/* Check for valid field format */
-	ret = vpif_check_format(ch, pixfmt, 0);
-
+	ret = vpif_try_fmt_vid_cap(file, priv, fmt);
 	if (ret)
 		return ret;
+
 	/* store the format in the channel object */
 	common->fmt = *fmt;
 	return 0;
@@ -1411,36 +1298,9 @@ static struct v4l2_file_operations vpif_
  */
 static int initialize_vpif(void)
 {
-	int err = 0, i, j;
+	int err, i, j;
 	int free_channel_objects_index;
 
-	/* Default number of buffers should be 3 */
-	if ((ch0_numbuffers > 0) &&
-	    (ch0_numbuffers < config_params.min_numbuffers))
-		ch0_numbuffers = config_params.min_numbuffers;
-	if ((ch1_numbuffers > 0) &&
-	    (ch1_numbuffers < config_params.min_numbuffers))
-		ch1_numbuffers = config_params.min_numbuffers;
-
-	/* Set buffer size to min buffers size if it is invalid */
-	if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
-		ch0_bufsize =
-		    config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
-	if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
-		ch1_bufsize =
-		    config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
-
-	config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers;
-	config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers;
-	if (ch0_numbuffers) {
-		config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
-		    = ch0_bufsize;
-	}
-	if (ch1_numbuffers) {
-		config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
-		    = ch1_bufsize;
-	}
-
 	/* Allocate memory for six channel objects */
 	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
 		vpif_obj.dev[i] =
@@ -1496,6 +1356,11 @@ static int vpif_probe_complete(void)
 		if (err)
 			goto probe_out;
 
+		/* set initial format */
+		ch->video.stdid = V4L2_STD_525_60;
+		memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
+		vpif_update_std_info(ch);
+
 		/* Initialize vb2 queue */
 		q = &common->buffer_queue;
 		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1533,7 +1398,6 @@ static int vpif_probe_complete(void)
 		vdev->vfl_dir = VFL_DIR_RX;
 		vdev->queue = q;
 		vdev->lock = &common->lock;
-		set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
 		video_set_drvdata(ch->video_dev, ch);
 		err = video_register_device(vdev,
 					    VFL_TYPE_GRABBER, (j ? 1 : 0));
@@ -1714,7 +1578,7 @@ static int vpif_remove(struct platform_d
 	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
 		/* Get the pointer to the channel object */
 		ch = vpif_obj.dev[i];
-		common = &ch->common[i];
+		common = &ch->common[VPIF_VIDEO_INDEX];
 		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
 		/* Unregister video device */
 		video_unregister_device(ch->video_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_capture.h linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_capture.h
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_capture.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_capture.h	2014-09-28 17:29:07.000000000 -0400
@@ -119,15 +119,4 @@ struct vpif_device {
 	struct vpif_capture_config *config;
 };
 
-struct vpif_config_params {
-	u8 min_numbuffers;
-	u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS];
-	s8 device_type;
-	u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
-	u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
-	u8 default_device[VPIF_CAPTURE_NUM_CHANNELS];
-	u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
-	u8 max_device_type;
-};
-
 #endif				/* VPIF_CAPTURE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_display.c linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_display.c
--- linux-libre-3.16-gnu/drivers/media/platform/davinci/vpif_display.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/davinci/vpif_display.c	2014-09-28 17:29:07.000000000 -0400
@@ -649,7 +649,6 @@ static int vpif_try_fmt_vid_out(struct f
 	pixfmt->width = common->fmt.fmt.pix.width;
 	pixfmt->height = common->fmt.fmt.pix.height;
 	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
-	pixfmt->priv = 0;
 
 	return 0;
 }
@@ -1224,7 +1223,6 @@ static int vpif_probe_complete(void)
 		vdev->vfl_dir = VFL_DIR_TX;
 		vdev->queue = q;
 		vdev->lock = &common->lock;
-		set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
 		video_set_drvdata(ch->video_dev, ch);
 		err = video_register_device(vdev, VFL_TYPE_GRABBER,
 					    (j ? 3 : 2));
@@ -1388,7 +1386,7 @@ static int vpif_remove(struct platform_d
 	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
 		/* Get the pointer to the channel object */
 		ch = vpif_obj.dev[i];
-		common = &ch->common[i];
+		common = &ch->common[VPIF_VIDEO_INDEX];
 		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
 		/* Unregister video device */
 		video_unregister_device(ch->video_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/platform/Kconfig
--- linux-libre-3.16-gnu/drivers/media/platform/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -96,6 +96,7 @@ config VIDEO_OMAP3
 	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
 	select ARM_DMA_USE_IOMMU
 	select OMAP_IOMMU
+	select VIDEOBUF2_DMA_CONTIG
 	---help---
 	  Driver for an OMAP 3 camera controller.
 
@@ -142,6 +143,7 @@ config VIDEO_CODA
 	select SRAM
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
+	select GENERIC_ALLOCATOR
 	---help---
 	   Coda is a range of video codec IPs that supports
 	   H.264, MPEG-4, and other video formats.
@@ -165,12 +167,13 @@ config VIDEO_SAMSUNG_S5P_G2D
 	  2d graphics accelerator.
 
 config VIDEO_SAMSUNG_S5P_JPEG
-	tristate "Samsung S5P/Exynos4 JPEG codec driver"
+	tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
 	depends on VIDEO_DEV && VIDEO_V4L2 && (PLAT_S5P || ARCH_EXYNOS)
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	---help---
-	  This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
+	  This is a v4l2 driver for Samsung S5P, EXYNOS3250
+	  and EXYNOS4 JPEG codec
 
 config VIDEO_SAMSUNG_S5P_MFC
 	tristate "Samsung S5P MFC Video Codec"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/m2m-deinterlace.c linux-libre-3.17-rc7-gnu/drivers/media/platform/m2m-deinterlace.c
--- linux-libre-3.16-gnu/drivers/media/platform/m2m-deinterlace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/m2m-deinterlace.c	2014-09-28 17:29:07.000000000 -0400
@@ -1002,7 +1002,7 @@ static int deinterlace_probe(struct plat
 	dma_cap_mask_t mask;
 	int ret = 0;
 
-	pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+	pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
 	if (!pcdev)
 		return -ENOMEM;
 
@@ -1012,7 +1012,7 @@ static int deinterlace_probe(struct plat
 	dma_cap_set(DMA_INTERLEAVE, mask);
 	pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
 	if (!pcdev->dma_chan)
-		goto free_dev;
+		return -ENODEV;
 
 	if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
 		v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
@@ -1078,8 +1078,6 @@ unreg_dev:
 	v4l2_device_unregister(&pcdev->v4l2_dev);
 rel_dma:
 	dma_release_channel(pcdev->dma_chan);
-free_dev:
-	kfree(pcdev);
 
 	return ret;
 }
@@ -1094,7 +1092,6 @@ static int deinterlace_remove(struct pla
 	v4l2_device_unregister(&pcdev->v4l2_dev);
 	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 	dma_release_channel(pcdev->dma_chan);
-	kfree(pcdev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/mem2mem_testdev.c linux-libre-3.17-rc7-gnu/drivers/media/platform/mem2mem_testdev.c
--- linux-libre-3.16-gnu/drivers/media/platform/mem2mem_testdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/mem2mem_testdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -532,7 +532,6 @@ static int vidioc_try_fmt(struct v4l2_fo
 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.field = V4L2_FIELD_NONE;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/omap/omap_vout.c linux-libre-3.17-rc7-gnu/drivers/media/platform/omap/omap_vout.c
--- linux-libre-3.16-gnu/drivers/media/platform/omap/omap_vout.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/omap/omap_vout.c	2014-09-28 17:29:07.000000000 -0400
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v
 
 	pix->pixelformat = omap_formats[ifmt].pixelformat;
 	pix->field = V4L2_FIELD_ANY;
-	pix->priv = 0;
 
 	switch (pix->pixelformat) {
 	case V4L2_PIX_FMT_YUYV:
@@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_
 	pix->field = V4L2_FIELD_ANY;
 	pix->bytesperline = pix->width * 2;
 	pix->sizeimage = pix->bytesperline * pix->height;
-	pix->priv = 0;
 	pix->colorspace = V4L2_COLORSPACE_JPEG;
 
 	vout->bpp = RGB565_BPP;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s3c-camif/camif-capture.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s3c-camif/camif-capture.c
--- linux-libre-3.16-gnu/drivers/media/platform/s3c-camif/camif-capture.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s3c-camif/camif-capture.c	2014-09-28 17:29:07.000000000 -0400
@@ -1172,7 +1172,6 @@ int s3c_camif_register_video_node(struct
 		goto err_vd_rel;
 
 	video_set_drvdata(vfd, vp);
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
 	v4l2_ctrl_handler_init(&vp->ctrl_handler, 1);
 	ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops,
@@ -1271,6 +1270,7 @@ static int s3c_camif_subdev_get_fmt(stru
 	}
 
 	mutex_unlock(&camif->lock);
+	mf->field = V4L2_FIELD_NONE;
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
 	return 0;
 }
@@ -1319,6 +1319,7 @@ static int s3c_camif_subdev_set_fmt(stru
 	v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n",
 		 fmt->pad, mf->code, mf->width, mf->height);
 
+	mf->field = V4L2_FIELD_NONE;
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
 	mutex_lock(&camif->lock);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
  *
- * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
@@ -32,6 +32,7 @@
 #include "jpeg-core.h"
 #include "jpeg-hw-s5p.h"
 #include "jpeg-hw-exynos4.h"
+#include "jpeg-hw-exynos3250.h"
 #include "jpeg-regs.h"
 
 static struct s5p_jpeg_fmt sjpeg_formats[] = {
@@ -41,6 +42,7 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.flags		= SJPEG_FMT_FLAG_ENC_CAPTURE |
 				  SJPEG_FMT_FLAG_DEC_OUTPUT |
 				  SJPEG_FMT_FLAG_S5P |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
 				  SJPEG_FMT_FLAG_EXYNOS4,
 	},
 	{
@@ -70,6 +72,19 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
 	},
 	{
+		.name		= "YUV 4:2:2 packed, YCbYCr",
+		.fourcc		= V4L2_PIX_FMT_YUYV,
+		.depth		= 16,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+	},
+	{
 		.name		= "YUV 4:2:2 packed, YCrYCb",
 		.fourcc		= V4L2_PIX_FMT_YVYU,
 		.depth		= 16,
@@ -83,6 +98,45 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
 	},
 	{
+		.name		= "YUV 4:2:2 packed, YCrYCb",
+		.fourcc		= V4L2_PIX_FMT_YVYU,
+		.depth		= 16,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+	},
+	{
+		.name		= "YUV 4:2:2 packed, YCrYCb",
+		.fourcc		= V4L2_PIX_FMT_UYVY,
+		.depth		= 16,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+	},
+	{
+		.name		= "YUV 4:2:2 packed, YCrYCb",
+		.fourcc		= V4L2_PIX_FMT_VYUY,
+		.depth		= 16,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+	},
+	{
 		.name		= "RGB565",
 		.fourcc		= V4L2_PIX_FMT_RGB565,
 		.depth		= 16,
@@ -100,6 +154,32 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.fourcc		= V4L2_PIX_FMT_RGB565,
 		.depth		= 16,
 		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+	},
+	{
+		.name		= "RGB565X",
+		.fourcc		= V4L2_PIX_FMT_RGB565X,
+		.depth		= 16,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+	},
+	{
+		.name		= "RGB565",
+		.fourcc		= V4L2_PIX_FMT_RGB565,
+		.depth		= 16,
+		.colplanes	= 1,
 		.h_align	= 0,
 		.v_align	= 0,
 		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
@@ -121,6 +201,19 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,
 	},
 	{
+		.name		= "ARGB8888, 32 bpp",
+		.fourcc		= V4L2_PIX_FMT_RGB32,
+		.depth		= 32,
+		.colplanes	= 1,
+		.h_align	= 2,
+		.v_align	= 0,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+	},
+	{
 		.name		= "YUV 4:4:4 planar, Y/CbCr",
 		.fourcc		= V4L2_PIX_FMT_NV24,
 		.depth		= 24,
@@ -190,9 +283,23 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.fourcc		= V4L2_PIX_FMT_NV12,
 		.depth		= 12,
 		.colplanes	= 2,
+		.h_align	= 3,
+		.v_align	= 3,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+	},
+	{
+		.name		= "YUV 4:2:0 planar, Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV12,
+		.depth		= 12,
+		.colplanes	= 2,
 		.h_align	= 4,
 		.v_align	= 4,
-		.flags		= SJPEG_FMT_FLAG_DEC_CAPTURE |
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
 				  SJPEG_FMT_FLAG_S5P |
 				  SJPEG_FMT_NON_RGB,
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
@@ -202,10 +309,24 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.fourcc		= V4L2_PIX_FMT_NV21,
 		.depth		= 12,
 		.colplanes	= 2,
+		.h_align	= 3,
+		.v_align	= 3,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+	},
+	{
+		.name		= "YUV 4:2:0 planar, Y/CrCb",
+		.fourcc		= V4L2_PIX_FMT_NV21,
+		.depth		= 12,
+		.colplanes	= 2,
 		.h_align	= 1,
 		.v_align	= 1,
 		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
 				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
 				  SJPEG_FMT_FLAG_EXYNOS4 |
 				  SJPEG_FMT_NON_RGB,
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
@@ -224,6 +345,19 @@ static struct s5p_jpeg_fmt sjpeg_formats
 		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
 	},
 	{
+		.name		= "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr",
+		.fourcc		= V4L2_PIX_FMT_YUV420,
+		.depth		= 12,
+		.colplanes	= 3,
+		.h_align	= 4,
+		.v_align	= 4,
+		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |
+				  SJPEG_FMT_FLAG_DEC_CAPTURE |
+				  SJPEG_FMT_FLAG_EXYNOS3250 |
+				  SJPEG_FMT_NON_RGB,
+		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+	},
+	{
 		.name		= "Gray",
 		.fourcc		= V4L2_PIX_FMT_GREY,
 		.depth		= 8,
@@ -457,6 +591,16 @@ static int exynos4x12_decoded_subsamplin
 	V4L2_JPEG_CHROMA_SUBSAMPLING_420,
 };
 
+static int exynos3250_decoded_subsampling[] = {
+	V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+	V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+	V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+	V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+	-1,
+	-1,
+	V4L2_JPEG_CHROMA_SUBSAMPLING_411,
+};
+
 static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
 {
 	return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
@@ -471,14 +615,21 @@ static int s5p_jpeg_to_user_subsampling(
 {
 	WARN_ON(ctx->subsampling > 3);
 
-	if (ctx->jpeg->variant->version == SJPEG_S5P) {
+	switch (ctx->jpeg->variant->version) {
+	case SJPEG_S5P:
 		if (ctx->subsampling > 2)
 			return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
 		return ctx->subsampling;
-	} else {
+	case SJPEG_EXYNOS3250:
+		if (ctx->subsampling > 3)
+			return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
+		return exynos3250_decoded_subsampling[ctx->subsampling];
+	case SJPEG_EXYNOS4:
 		if (ctx->subsampling > 2)
 			return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
 		return exynos4x12_decoded_subsampling[ctx->subsampling];
+	default:
+		return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
 	}
 }
 
@@ -646,6 +797,7 @@ static int s5p_jpeg_open(struct file *fi
 							FMT_TYPE_OUTPUT);
 		cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
 							FMT_TYPE_CAPTURE);
+		ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
 	}
 
 	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
@@ -754,14 +906,14 @@ static bool s5p_jpeg_parse_hdr(struct s5
 	while (notfound) {
 		c = get_byte(&jpeg_buffer);
 		if (c == -1)
-			break;
+			return false;
 		if (c != 0xff)
 			continue;
 		do
 			c = get_byte(&jpeg_buffer);
 		while (c == 0xff);
 		if (c == -1)
-			break;
+			return false;
 		if (c == 0)
 			continue;
 		length = 0;
@@ -981,7 +1133,8 @@ static struct s5p_jpeg_fmt *s5p_jpeg_fin
 	return NULL;
 }
 
-static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
+				   u32 *w, unsigned int wmin, unsigned int wmax,
 				   unsigned int walign,
 				   u32 *h, unsigned int hmin, unsigned int hmax,
 				   unsigned int halign)
@@ -993,13 +1146,27 @@ static void jpeg_bound_align_image(u32 *
 
 	w_step = 1 << walign;
 	h_step = 1 << halign;
+
+	if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) {
+		/*
+		 * Rightmost and bottommost pixels are cropped by the
+		 * Exynos3250 JPEG IP for RGB formats, for the specific
+		 * width and height values respectively. This assignment
+		 * will result in v4l_bound_align_image returning dimensions
+		 * reduced by 1 for the aforementioned cases.
+		 */
+		if (w_step == 4 && ((width & 3) == 1)) {
+			wmax = width;
+			hmax = height;
+		}
+	}
+
 	v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
 
 	if (*w < width && (*w + w_step) < wmax)
 		*w += w_step;
 	if (*h < height && (*h + h_step) < hmax)
 		*h += h_step;
-
 }
 
 static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
@@ -1015,12 +1182,12 @@ static int vidioc_try_fmt(struct v4l2_fo
 	/* V4L2 specification suggests the driver corrects the format struct
 	 * if any of the dimensions is unsupported */
 	if (q_type == FMT_TYPE_OUTPUT)
-		jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+		jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
 				       S5P_JPEG_MAX_WIDTH, 0,
 				       &pix->height, S5P_JPEG_MIN_HEIGHT,
 				       S5P_JPEG_MAX_HEIGHT, 0);
 	else
-		jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+		jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
 				       S5P_JPEG_MAX_WIDTH, fmt->h_align,
 				       &pix->height, S5P_JPEG_MIN_HEIGHT,
 				       S5P_JPEG_MAX_HEIGHT, fmt->v_align);
@@ -1142,7 +1309,7 @@ static int exynos4_jpeg_get_output_buffe
 	else
 		wh_align = 1;
 
-	jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH,
+	jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
 			       S5P_JPEG_MAX_WIDTH, wh_align,
 			       &h, S5P_JPEG_MIN_HEIGHT,
 			       S5P_JPEG_MAX_HEIGHT, wh_align);
@@ -1150,12 +1317,16 @@ static int exynos4_jpeg_get_output_buffe
 	return w * h * fmt_depth >> 3;
 }
 
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+				   struct v4l2_rect *r);
+
 static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
 {
 	struct vb2_queue *vq;
 	struct s5p_jpeg_q_data *q_data = NULL;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct v4l2_ctrl *ctrl_subs;
+	struct v4l2_rect scale_rect;
 	unsigned int f_type;
 
 	vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
@@ -1200,6 +1371,35 @@ static int s5p_jpeg_s_fmt(struct s5p_jpe
 					V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
 		if (ctrl_subs)
 			v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
+		ct->crop_altered = false;
+	}
+
+	/*
+	 * For decoding init crop_rect with capture buffer dimmensions which
+	 * contain aligned dimensions of the input JPEG image and do it only
+	 * if crop rectangle hasn't been altered by the user space e.g. with
+	 * S_SELECTION ioctl. For encoding assign output buffer dimensions.
+	 */
+	if (!ct->crop_altered &&
+	    ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
+	     (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
+		ct->crop_rect.width = pix->width;
+		ct->crop_rect.height = pix->height;
+	}
+
+	/*
+	 * Prevent downscaling to YUV420 format by more than 2
+	 * for Exynos3250 SoC as it produces broken raw image
+	 * in such cases.
+	 */
+	if (ct->mode == S5P_JPEG_DECODE &&
+	    f_type == FMT_TYPE_CAPTURE &&
+	    ct->jpeg->variant->version == SJPEG_EXYNOS3250 &&
+	    pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
+	    ct->scale_factor > 2) {
+		scale_rect.width = ct->out_q.w / 2;
+		scale_rect.height = ct->out_q.h / 2;
+		exynos3250_jpeg_try_downscale(ct, &scale_rect);
 	}
 
 	return 0;
@@ -1229,6 +1429,101 @@ static int s5p_jpeg_s_fmt_vid_out(struct
 	return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
 }
 
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+				   struct v4l2_rect *r)
+{
+	int w_ratio, h_ratio, scale_factor, cur_ratio, i;
+
+	w_ratio = ctx->out_q.w / r->width;
+	h_ratio = ctx->out_q.h / r->height;
+
+	scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
+	scale_factor = clamp_val(scale_factor, 1, 8);
+
+	/* Align scale ratio to the nearest power of 2 */
+	for (i = 0; i <= 3; ++i) {
+		cur_ratio = 1 << i;
+		if (scale_factor <= cur_ratio) {
+			ctx->scale_factor = cur_ratio;
+			break;
+		}
+	}
+
+	r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
+	r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
+
+	ctx->crop_rect.width = r->width;
+	ctx->crop_rect.height = r->height;
+	ctx->crop_rect.left = 0;
+	ctx->crop_rect.top = 0;
+
+	ctx->crop_altered = true;
+
+	return 0;
+}
+
+/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
+static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+	if (a->left < b->left || a->top < b->top)
+		return 0;
+	if (a->left + a->width > b->left + b->width)
+		return 0;
+	if (a->top + a->height > b->top + b->height)
+		return 0;
+
+	return 1;
+}
+
+static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
+				   struct v4l2_rect *r)
+{
+	struct v4l2_rect base_rect;
+	int w_step, h_step;
+
+	switch (ctx->cap_q.fmt->fourcc) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		w_step = 1;
+		h_step = 2;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		w_step = 2;
+		h_step = 2;
+		break;
+	default:
+		w_step = 1;
+		h_step = 1;
+		break;
+	}
+
+	base_rect.top = 0;
+	base_rect.left = 0;
+	base_rect.width = ctx->out_q.w;
+	base_rect.height = ctx->out_q.h;
+
+	r->width = round_down(r->width, w_step);
+	r->height = round_down(r->height, h_step);
+	r->left = round_down(r->left, 2);
+	r->top = round_down(r->top, 2);
+
+	if (!enclosed_rectangle(r, &base_rect))
+		return -EINVAL;
+
+	ctx->crop_rect.left = r->left;
+	ctx->crop_rect.top = r->top;
+	ctx->crop_rect.width = r->width;
+	ctx->crop_rect.height = r->height;
+
+	ctx->crop_altered = true;
+
+	return 0;
+}
+
+/*
+ * V4L2 controls
+ */
+
 static int s5p_jpeg_g_selection(struct file *file, void *priv,
 			 struct v4l2_selection *s)
 {
@@ -1243,27 +1538,53 @@ static int s5p_jpeg_g_selection(struct f
 	case V4L2_SEL_TGT_CROP:
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 	case V4L2_SEL_TGT_CROP_DEFAULT:
-	case V4L2_SEL_TGT_COMPOSE:
 	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
 		s->r.width = ctx->out_q.w;
 		s->r.height = ctx->out_q.h;
+		s->r.left = 0;
+		s->r.top = 0;
 		break;
+	case V4L2_SEL_TGT_COMPOSE:
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 	case V4L2_SEL_TGT_COMPOSE_PADDED:
-		s->r.width = ctx->cap_q.w;
-		s->r.height = ctx->cap_q.h;
+		s->r.width = ctx->crop_rect.width;
+		s->r.height =  ctx->crop_rect.height;
+		s->r.left = ctx->crop_rect.left;
+		s->r.top = ctx->crop_rect.top;
 		break;
 	default:
 		return -EINVAL;
 	}
-	s->r.left = 0;
-	s->r.top = 0;
 	return 0;
 }
 
 /*
  * V4L2 controls
  */
+static int s5p_jpeg_s_selection(struct file *file, void *fh,
+				  struct v4l2_selection *s)
+{
+	struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+	struct v4l2_rect *rect = &s->r;
+	int ret = -EINVAL;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (s->target == V4L2_SEL_TGT_COMPOSE) {
+		if (ctx->mode != S5P_JPEG_DECODE)
+			return -EINVAL;
+		if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+			ret = exynos3250_jpeg_try_downscale(ctx, rect);
+	} else if (s->target == V4L2_SEL_TGT_CROP) {
+		if (ctx->mode != S5P_JPEG_ENCODE)
+			return -EINVAL;
+		if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+			ret = exynos3250_jpeg_try_crop(ctx, rect);
+	}
+
+	return ret;
+}
 
 static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -1282,36 +1603,53 @@ static int s5p_jpeg_g_volatile_ctrl(stru
 	return 0;
 }
 
-static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
+static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
 {
-	struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
-	if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) {
-		if (ctx->jpeg->variant->version == SJPEG_S5P)
-			goto error_free;
+	switch (ctx->jpeg->variant->version) {
+	case SJPEG_S5P:
+		return 0;
+	case SJPEG_EXYNOS3250:
+		/*
+		 * The exynos3250 device can produce JPEG image only
+		 * of 4:4:4 subsampling when given RGB32 source image.
+		 */
+		if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+			*ctrl_val = 0;
+		break;
+	case SJPEG_EXYNOS4:
 		/*
 		 * The exynos4x12 device requires input raw image fourcc
 		 * to be V4L2_PIX_FMT_GREY if gray jpeg format
 		 * is to be set.
 		 */
 		if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
-		    ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
-			ret = -EINVAL;
-			goto error_free;
-		}
-		/*
-		 * The exynos4x12 device requires resulting jpeg subsampling
-		 * not to be lower than the input raw image subsampling.
-		 */
-		if (ctx->out_q.fmt->subsampling > ctrl->val)
-			ctrl->val = ctx->out_q.fmt->subsampling;
+		    *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
+			return -EINVAL;
+		break;
 	}
 
-error_free:
+	/*
+	 * The exynos4x12 and exynos3250 devices require resulting
+	 * jpeg subsampling not to be lower than the input raw image
+	 * subsampling.
+	 */
+	if (ctx->out_q.fmt->subsampling > *ctrl_val)
+		*ctrl_val = ctx->out_q.fmt->subsampling;
+
+	return 0;
+}
+
+static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+	if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
+		ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
+
 	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
 	return ret;
 }
@@ -1414,6 +1752,7 @@ static const struct v4l2_ioctl_ops s5p_j
 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
 
 	.vidioc_g_selection		= s5p_jpeg_g_selection,
+	.vidioc_s_selection		= s5p_jpeg_s_selection,
 };
 
 /*
@@ -1604,6 +1943,135 @@ static void exynos4_jpeg_device_run(void
 	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
 }
 
+static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
+{
+	struct s5p_jpeg *jpeg = ctx->jpeg;
+	struct s5p_jpeg_fmt *fmt;
+	struct vb2_buffer *vb;
+	struct s5p_jpeg_addr jpeg_addr;
+	u32 pix_size;
+
+	pix_size = ctx->cap_q.w * ctx->cap_q.h;
+
+	if (ctx->mode == S5P_JPEG_ENCODE) {
+		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+		fmt = ctx->out_q.fmt;
+	} else {
+		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+		fmt = ctx->cap_q.fmt;
+	}
+
+	jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+	if (fmt->colplanes == 2) {
+		jpeg_addr.cb = jpeg_addr.y + pix_size;
+	} else if (fmt->colplanes == 3) {
+		jpeg_addr.cb = jpeg_addr.y + pix_size;
+		if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
+			jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
+		else
+			jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
+	}
+
+	exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
+}
+
+static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
+{
+	struct s5p_jpeg *jpeg = ctx->jpeg;
+	struct vb2_buffer *vb;
+	unsigned int jpeg_addr = 0;
+
+	if (ctx->mode == S5P_JPEG_ENCODE)
+		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	else
+		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+
+	jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+	exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
+}
+
+static void exynos3250_jpeg_device_run(void *priv)
+{
+	struct s5p_jpeg_ctx *ctx = priv;
+	struct s5p_jpeg *jpeg = ctx->jpeg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+	exynos3250_jpeg_reset(jpeg->regs);
+	exynos3250_jpeg_set_dma_num(jpeg->regs);
+	exynos3250_jpeg_poweron(jpeg->regs);
+	exynos3250_jpeg_clk_set(jpeg->regs);
+	exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
+
+	if (ctx->mode == S5P_JPEG_ENCODE) {
+		exynos3250_jpeg_input_raw_fmt(jpeg->regs,
+					      ctx->out_q.fmt->fourcc);
+		exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
+
+		/*
+		 * JPEG IP allows storing 4 quantization tables
+		 * We fill table 0 for luma and table 1 for chroma
+		 */
+		s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+		s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+		/* use table 0 for Y */
+		exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
+		/* use table 1 for Cb and Cr*/
+		exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
+		exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
+
+		/* Y, Cb, Cr use Huffman table 0 */
+		exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
+		exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
+		exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
+		exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
+		exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
+		exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
+
+		exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
+		exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
+		exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
+								ctx->out_q.w);
+		exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
+							ctx->crop_rect.top);
+		exynos3250_jpeg_set_img_addr(ctx);
+		exynos3250_jpeg_set_jpeg_addr(ctx);
+		exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
+
+		/* ultimately comes from sizeimage from userspace */
+		exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
+
+		if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
+		    ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
+		    ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+			exynos3250_jpeg_set_y16(jpeg->regs, true);
+	} else {
+		exynos3250_jpeg_set_img_addr(ctx);
+		exynos3250_jpeg_set_jpeg_addr(ctx);
+		exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
+								ctx->cap_q.w);
+		exynos3250_jpeg_offset(jpeg->regs, 0, 0);
+		exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
+							ctx->scale_factor);
+		exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
+		exynos3250_jpeg_output_raw_fmt(jpeg->regs,
+						ctx->cap_q.fmt->fourcc);
+	}
+
+	exynos3250_jpeg_interrupts_enable(jpeg->regs);
+
+	/* JPEG RGB to YCbCr conversion matrix */
+	exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
+
+	exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
+	jpeg->irq_status = 0;
+	exynos3250_jpeg_start(jpeg->regs);
+
+	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+}
+
 static int s5p_jpeg_job_ready(void *priv)
 {
 	struct s5p_jpeg_ctx *ctx = priv;
@@ -1621,8 +2089,14 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_
 	.device_run	= s5p_jpeg_device_run,
 	.job_ready	= s5p_jpeg_job_ready,
 	.job_abort	= s5p_jpeg_job_abort,
-}
-;
+};
+
+static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
+	.device_run	= exynos3250_jpeg_device_run,
+	.job_ready	= s5p_jpeg_job_ready,
+	.job_abort	= s5p_jpeg_job_abort,
+};
+
 static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
 	.device_run	= exynos4_jpeg_device_run,
 	.job_ready	= s5p_jpeg_job_ready,
@@ -1895,6 +2369,70 @@ static irqreturn_t exynos4_jpeg_irq(int
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
+{
+	struct s5p_jpeg *jpeg = dev_id;
+	struct s5p_jpeg_ctx *curr_ctx;
+	struct vb2_buffer *src_buf, *dst_buf;
+	unsigned long payload_size = 0;
+	enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+	bool interrupt_timeout = false;
+	u32 irq_status;
+
+	spin_lock(&jpeg->slock);
+
+	irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
+	if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
+		exynos3250_jpeg_clear_timer_status(jpeg->regs);
+		interrupt_timeout = true;
+		dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
+	}
+
+	irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
+	exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
+
+	jpeg->irq_status |= irq_status;
+
+	curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+	if (!curr_ctx)
+		goto exit_unlock;
+
+	if ((irq_status & EXYNOS3250_HEADER_STAT) &&
+	    (curr_ctx->mode == S5P_JPEG_DECODE)) {
+		exynos3250_jpeg_rstart(jpeg->regs);
+		goto exit_unlock;
+	}
+
+	if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
+				EXYNOS3250_WDMA_DONE |
+				EXYNOS3250_RDMA_DONE |
+				EXYNOS3250_RESULT_STAT))
+		payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
+	else if (interrupt_timeout)
+		state = VB2_BUF_STATE_ERROR;
+	else
+		goto exit_unlock;
+
+	src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+	dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
+	dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
+
+	v4l2_m2m_buf_done(src_buf, state);
+	if (curr_ctx->mode == S5P_JPEG_ENCODE)
+		vb2_set_plane_payload(dst_buf, 0, payload_size);
+	v4l2_m2m_buf_done(dst_buf, state);
+	v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
+
+	curr_ctx->subsampling =
+			exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
+exit_unlock:
+	spin_unlock(&jpeg->slock);
+	return IRQ_HANDLED;
+}
+
 static void *jpeg_get_drv_data(struct device *dev);
 
 /*
@@ -1950,6 +2488,10 @@ static int s5p_jpeg_probe(struct platfor
 	}
 	dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
 
+	jpeg->sclk = clk_get(&pdev->dev, "sclk");
+	if (IS_ERR(jpeg->sclk))
+		dev_info(&pdev->dev, "sclk clock not available\n");
+
 	/* v4l2 device */
 	ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
 	if (ret) {
@@ -2057,6 +2599,8 @@ device_register_rollback:
 
 clk_get_rollback:
 	clk_put(jpeg->clk);
+	if (!IS_ERR(jpeg->sclk))
+		clk_put(jpeg->sclk);
 
 	return ret;
 }
@@ -2075,10 +2619,15 @@ static int s5p_jpeg_remove(struct platfo
 	v4l2_m2m_release(jpeg->m2m_dev);
 	v4l2_device_unregister(&jpeg->v4l2_dev);
 
-	if (!pm_runtime_status_suspended(&pdev->dev))
+	if (!pm_runtime_status_suspended(&pdev->dev)) {
 		clk_disable_unprepare(jpeg->clk);
+		if (!IS_ERR(jpeg->sclk))
+			clk_disable_unprepare(jpeg->sclk);
+	}
 
 	clk_put(jpeg->clk);
+	if (!IS_ERR(jpeg->sclk))
+		clk_put(jpeg->sclk);
 
 	return 0;
 }
@@ -2088,6 +2637,8 @@ static int s5p_jpeg_runtime_suspend(stru
 	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
 
 	clk_disable_unprepare(jpeg->clk);
+	if (!IS_ERR(jpeg->sclk))
+		clk_disable_unprepare(jpeg->sclk);
 
 	return 0;
 }
@@ -2102,15 +2653,24 @@ static int s5p_jpeg_runtime_resume(struc
 	if (ret < 0)
 		return ret;
 
+	if (!IS_ERR(jpeg->sclk)) {
+		ret = clk_prepare_enable(jpeg->sclk);
+		if (ret < 0)
+			return ret;
+	}
+
 	spin_lock_irqsave(&jpeg->slock, flags);
 
 	/*
-	 * JPEG IP allows storing two Huffman tables for each component
+	 * JPEG IP allows storing two Huffman tables for each component.
 	 * We fill table 0 for each component and do this here only
-	 * for S5PC210 device as Exynos4x12 requires programming its
-	 * Huffman tables each time the encoding process is initialized.
+	 * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires
+	 * programming its Huffman tables each time the encoding process
+	 * is initialized, and thus it is accomplished in the device_run
+	 * callback of m2m_ops.
 	 */
-	if (jpeg->variant->version == SJPEG_S5P) {
+	if (jpeg->variant->version == SJPEG_S5P ||
+	    jpeg->variant->version == SJPEG_EXYNOS3250) {
 		s5p_jpeg_set_hdctbl(jpeg->regs);
 		s5p_jpeg_set_hdctblg(jpeg->regs);
 		s5p_jpeg_set_hactbl(jpeg->regs);
@@ -2150,6 +2710,13 @@ static struct s5p_jpeg_variant s5p_jpeg_
 	.fmt_ver_flag	= SJPEG_FMT_FLAG_S5P,
 };
 
+static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
+	.version	= SJPEG_EXYNOS3250,
+	.jpeg_irq	= exynos3250_jpeg_irq,
+	.m2m_ops	= &exynos3250_jpeg_m2m_ops,
+	.fmt_ver_flag	= SJPEG_FMT_FLAG_EXYNOS3250,
+};
+
 static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
 	.version	= SJPEG_EXYNOS4,
 	.jpeg_irq	= exynos4_jpeg_irq,
@@ -2162,8 +2729,11 @@ static const struct of_device_id samsung
 		.compatible = "samsung,s5pv210-jpeg",
 		.data = &s5p_jpeg_drvdata,
 	}, {
+		.compatible = "samsung,exynos3250-jpeg",
+		.data = &exynos3250_jpeg_drvdata,
+	}, {
 		.compatible = "samsung,exynos4210-jpeg",
-		.data = &s5p_jpeg_drvdata,
+		.data = &exynos4_jpeg_drvdata,
 	}, {
 		.compatible = "samsung,exynos4212-jpeg",
 		.data = &exynos4_jpeg_drvdata,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.h linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.h
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-core.h	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,8 @@
 #define S5P_JPEG_COEF32			0x6e
 #define S5P_JPEG_COEF33			0x13
 
+#define EXYNOS3250_IRQ_TIMEOUT		0x10000000
+
 /* a selection of JPEG markers */
 #define TEM				0x01
 #define SOF0				0xc0
@@ -49,9 +51,10 @@
 #define SJPEG_FMT_FLAG_DEC_CAPTURE	(1 << 2)
 #define SJPEG_FMT_FLAG_DEC_OUTPUT	(1 << 3)
 #define SJPEG_FMT_FLAG_S5P		(1 << 4)
-#define SJPEG_FMT_FLAG_EXYNOS4		(1 << 5)
-#define SJPEG_FMT_RGB			(1 << 6)
-#define SJPEG_FMT_NON_RGB		(1 << 7)
+#define SJPEG_FMT_FLAG_EXYNOS3250	(1 << 5)
+#define SJPEG_FMT_FLAG_EXYNOS4		(1 << 6)
+#define SJPEG_FMT_RGB			(1 << 7)
+#define SJPEG_FMT_NON_RGB		(1 << 8)
 
 #define S5P_JPEG_ENCODE		0
 #define S5P_JPEG_DECODE		1
@@ -65,8 +68,9 @@
 
 /* Version numbers */
 
-#define SJPEG_S5P	1
-#define SJPEG_EXYNOS4	2
+#define SJPEG_S5P		1
+#define SJPEG_EXYNOS3250	2
+#define SJPEG_EXYNOS4		3
 
 enum exynos4_jpeg_result {
 	OK_ENC_OR_DEC,
@@ -95,8 +99,13 @@ enum  exynos4_jpeg_img_quality_level {
  * @regs:		JPEG IP registers mapping
  * @irq:		JPEG IP irq
  * @clk:		JPEG IP clock
+ * @sclk:		Exynos3250 JPEG IP special clock
  * @dev:		JPEG IP struct device
  * @alloc_ctx:		videobuf2 memory allocator's context
+ * @variant:		driver variant to be used
+ * @irq_status		interrupt flags set during single encode/decode
+			operation
+
  */
 struct s5p_jpeg {
 	struct mutex		lock;
@@ -111,9 +120,11 @@ struct s5p_jpeg {
 	unsigned int		irq;
 	enum exynos4_jpeg_result irq_ret;
 	struct clk		*clk;
+	struct clk		*sclk;
 	struct device		*dev;
 	void			*alloc_ctx;
 	struct s5p_jpeg_variant *variant;
+	u32			irq_status;
 };
 
 struct s5p_jpeg_variant {
@@ -164,9 +175,15 @@ struct s5p_jpeg_q_data {
  * @jpeg:		JPEG IP device for this context
  * @mode:		compression (encode) operation or decompression (decode)
  * @compr_quality:	destination image quality in compression (encode) mode
+ * @restart_interval:	JPEG restart interval for JPEG encoding
+ * @subsampling:	subsampling of a raw format or a JPEG
  * @out_q:		source (output) queue information
- * @cap_fmt:		destination (capture) queue queue information
+ * @cap_q:		destination (capture) queue queue information
+ * @scale_factor:	scale factor for JPEG decoding
+ * @crop_rect:		a rectangle representing crop area of the output buffer
+ * @fh:			V4L2 file handle
  * @hdr_parsed:		set if header has been parsed during decompression
+ * @crop_altered:	set if crop rectangle has been altered by the user space
  * @ctrl_handler:	controls handler
  */
 struct s5p_jpeg_ctx {
@@ -177,8 +194,11 @@ struct s5p_jpeg_ctx {
 	unsigned short		subsampling;
 	struct s5p_jpeg_q_data	out_q;
 	struct s5p_jpeg_q_data	cap_q;
+	unsigned int		scale_factor;
+	struct v4l2_rect	crop_rect;
 	struct v4l2_fh		fh;
 	bool			hdr_parsed;
+	bool			crop_altered;
 	struct v4l2_ctrl_handler ctrl_handler;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,487 @@
+/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+
+#include "jpeg-core.h"
+#include "jpeg-regs.h"
+#include "jpeg-hw-exynos3250.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs)
+{
+	u32 reg = 0;
+	int count = 1000;
+
+	writel(1, regs + EXYNOS3250_SW_RESET);
+	/* no other way but polling for when JPEG IP becomes operational */
+	while (reg != 0 && --count > 0) {
+		udelay(1);
+		cpu_relax();
+		reg = readl(regs + EXYNOS3250_SW_RESET);
+	}
+
+	reg = 0;
+	count = 1000;
+
+	while (reg != 1 && --count > 0) {
+		writel(1, regs + EXYNOS3250_JPGDRI);
+		udelay(1);
+		cpu_relax();
+		reg = readl(regs + EXYNOS3250_JPGDRI);
+	}
+
+	writel(0, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_poweron(void __iomem *regs)
+{
+	writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
+}
+
+void exynos3250_jpeg_set_dma_num(void __iomem *regs)
+{
+	writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &
+			EXYNOS3250_WDMA_ISSUE_NUM_MASK) |
+	       ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &
+			EXYNOS3250_RDMA_ISSUE_NUM_MASK) |
+	       ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &
+			EXYNOS3250_ISSUE_GATHER_NUM_MASK),
+		regs + EXYNOS3250_DMA_ISSUE_NUM);
+}
+
+void exynos3250_jpeg_clk_set(void __iomem *base)
+{
+	u32 reg;
+
+	reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;
+
+	writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS3250_JPGCMOD) &
+			EXYNOS3250_MODE_Y16_MASK;
+
+	switch (fmt) {
+	case V4L2_PIX_FMT_RGB32:
+		reg |= EXYNOS3250_MODE_SEL_ARGB8888;
+		break;
+	case V4L2_PIX_FMT_BGR32:
+		reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		reg |= EXYNOS3250_MODE_SEL_RGB565;
+		break;
+	case V4L2_PIX_FMT_RGB565X:
+		reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
+			EXYNOS3250_SRC_SWAP_UV;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
+			EXYNOS3250_SRC_SWAP_UV;
+		break;
+	case V4L2_PIX_FMT_NV12:
+		reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;
+		break;
+	case V4L2_PIX_FMT_NV21:
+		reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		reg |= EXYNOS3250_MODE_SEL_420_3P;
+		break;
+	default:
+		break;
+
+	}
+
+	writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS3250_JPGCMOD);
+	if (y16)
+		reg |= EXYNOS3250_MODE_Y16;
+	else
+		reg &= ~EXYNOS3250_MODE_Y16_MASK;
+	writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)
+{
+	u32 reg, m;
+
+	if (mode == S5P_JPEG_ENCODE)
+		m = EXYNOS3250_PROC_MODE_COMPR;
+	else
+		m = EXYNOS3250_PROC_MODE_DECOMPR;
+	reg = readl(regs + EXYNOS3250_JPGMOD);
+	reg &= ~EXYNOS3250_PROC_MODE_MASK;
+	reg |= m;
+	writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
+{
+	u32 reg, m = 0;
+
+	switch (mode) {
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+		m = EXYNOS3250_SUBSAMPLING_MODE_444;
+		break;
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+		m = EXYNOS3250_SUBSAMPLING_MODE_422;
+		break;
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+		m = EXYNOS3250_SUBSAMPLING_MODE_420;
+		break;
+	}
+
+	reg = readl(regs + EXYNOS3250_JPGMOD);
+	reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;
+	reg |= m;
+	writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_JPGMOD) &
+				EXYNOS3250_SUBSAMPLING_MODE_MASK;
+}
+
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+	u32 reg;
+
+	reg = dri & EXYNOS3250_JPGDRI_MASK;
+	writel(reg, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+	unsigned long reg;
+
+	reg = readl(regs + EXYNOS3250_QHTBL);
+	reg &= ~EXYNOS3250_QT_NUM_MASK(t);
+	reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &
+					EXYNOS3250_QT_NUM_MASK(t);
+	writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+	unsigned long reg;
+
+	reg = readl(regs + EXYNOS3250_QHTBL);
+	reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);
+	/* this driver uses table 0 for all color components */
+	reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &
+					EXYNOS3250_HT_NUM_AC_MASK(t);
+	writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+	unsigned long reg;
+
+	reg = readl(regs + EXYNOS3250_QHTBL);
+	reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);
+	/* this driver uses table 0 for all color components */
+	reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &
+					EXYNOS3250_HT_NUM_DC_MASK(t);
+	writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)
+{
+	u32 reg;
+
+	reg = y & EXYNOS3250_JPGY_MASK;
+	writel(reg, regs + EXYNOS3250_JPGY);
+}
+
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)
+{
+	u32 reg;
+
+	reg = x & EXYNOS3250_JPGX_MASK;
+	writel(reg, regs + EXYNOS3250_JPGX);
+}
+
+unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_JPGY);
+}
+
+unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_JPGX);
+}
+
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS3250_JPGINTSE);
+	reg |= (EXYNOS3250_JPEG_DONE_EN |
+		EXYNOS3250_WDMA_DONE_EN |
+		EXYNOS3250_RDMA_DONE_EN |
+		EXYNOS3250_ENC_STREAM_INT_EN |
+		EXYNOS3250_CORE_DONE_EN |
+		EXYNOS3250_ERR_INT_EN |
+		EXYNOS3250_HEAD_INT_EN);
+	writel(reg, regs + EXYNOS3250_JPGINTSE);
+}
+
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)
+{
+	u32 reg;
+
+	reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;
+	writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);
+}
+
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+	u32 reg;
+
+	switch (fmt) {
+	case V4L2_PIX_FMT_RGB32:
+		reg = EXYNOS3250_OUT_FMT_ARGB8888;
+		break;
+	case V4L2_PIX_FMT_BGR32:
+		reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		reg = EXYNOS3250_OUT_FMT_RGB565;
+		break;
+	case V4L2_PIX_FMT_RGB565X:
+		reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
+			EXYNOS3250_OUT_SWAP_UV;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
+			EXYNOS3250_OUT_SWAP_UV;
+		break;
+	case V4L2_PIX_FMT_NV12:
+		reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;
+		break;
+	case V4L2_PIX_FMT_NV21:
+		reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		reg = EXYNOS3250_OUT_FMT_420_3P;
+		break;
+	default:
+		reg = 0;
+		break;
+	}
+
+	writel(reg, regs + EXYNOS3250_OUTFORM);
+}
+
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
+{
+	writel(addr, regs + EXYNOS3250_JPG_JPGADR);
+}
+
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)
+{
+	writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);
+	writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);
+	writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);
+}
+
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+			    unsigned int width)
+{
+	u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;
+
+	switch (img_fmt) {
+	case V4L2_PIX_FMT_RGB32:
+		reg_luma = 4 * width;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB565X:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_VYUY:
+		reg_luma = 2 * width;
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		reg_luma = width;
+		reg_cb = reg_luma;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		reg_luma = width;
+		reg_cb = reg_cr = reg_luma / 2;
+		break;
+	default:
+		break;
+	}
+
+	writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);
+	writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);
+	writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);
+}
+
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+				unsigned int y_offset)
+{
+	u32 reg;
+
+	reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &
+			EXYNOS3250_LUMA_YY_OFFSET_MASK;
+	reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &
+			EXYNOS3250_LUMA_YX_OFFSET_MASK;
+
+	writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);
+
+	reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &
+			EXYNOS3250_CHROMA_YY_OFFSET_MASK;
+	reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &
+			EXYNOS3250_CHROMA_YX_OFFSET_MASK;
+
+	writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);
+
+	reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &
+			EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;
+	reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &
+			EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;
+
+	writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);
+}
+
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)
+{
+	if (mode == S5P_JPEG_ENCODE) {
+		writel(EXYNOS3250_JPEG_ENC_COEF1,
+					base + EXYNOS3250_JPG_COEF(1));
+		writel(EXYNOS3250_JPEG_ENC_COEF2,
+					base + EXYNOS3250_JPG_COEF(2));
+		writel(EXYNOS3250_JPEG_ENC_COEF3,
+					base + EXYNOS3250_JPG_COEF(3));
+	} else {
+		writel(EXYNOS3250_JPEG_DEC_COEF1,
+					base + EXYNOS3250_JPG_COEF(1));
+		writel(EXYNOS3250_JPEG_DEC_COEF2,
+					base + EXYNOS3250_JPG_COEF(2));
+		writel(EXYNOS3250_JPEG_DEC_COEF3,
+					base + EXYNOS3250_JPG_COEF(3));
+	}
+}
+
+void exynos3250_jpeg_start(void __iomem *regs)
+{
+	writel(1, regs + EXYNOS3250_JSTART);
+}
+
+void exynos3250_jpeg_rstart(void __iomem *regs)
+{
+	writel(1, regs + EXYNOS3250_JRSTART);
+}
+
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_JPGINTST);
+}
+
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+						unsigned int value)
+{
+	return writel(value, regs + EXYNOS3250_JPGINTST);
+}
+
+unsigned int exynos3250_jpeg_operating(void __iomem *regs)
+{
+	return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
+}
+
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
+}
+
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs,
+						unsigned int size)
+{
+	writel(size & EXYNOS3250_DEC_STREAM_MASK,
+				regs + EXYNOS3250_DEC_STREAM_SIZE);
+}
+
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,
+						unsigned int sratio)
+{
+	switch (sratio) {
+	case 1:
+	default:
+		sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
+		break;
+	case 2:
+		sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;
+		break;
+	case 4:
+		sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;
+		break;
+	case 8:
+		sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;
+		break;
+	}
+
+	writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,
+				regs + EXYNOS3250_DEC_SCALING_RATIO);
+}
+
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)
+{
+	time_value &= EXYNOS3250_TIMER_INIT_MASK;
+
+	writel(EXYNOS3250_TIMER_INT_STAT | time_value,
+					regs + EXYNOS3250_TIMER_SE);
+}
+
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
+{
+	return readl(regs + EXYNOS3250_TIMER_ST);
+}
+
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
+{
+	writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,60 @@
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef JPEG_HW_EXYNOS3250_H_
+#define JPEG_HW_EXYNOS3250_H_
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+
+#include "jpeg-regs.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs);
+void exynos3250_jpeg_poweron(void __iomem *regs);
+void exynos3250_jpeg_set_dma_num(void __iomem *regs);
+void exynos3250_jpeg_clk_set(void __iomem *base);
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16);
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode);
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs);
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri);
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y);
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x);
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs);
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_outform_raw(void __iomem *regs, unsigned long format);
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr);
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr);
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+			    unsigned int width);
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+				unsigned int y_offset);
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode);
+void exynos3250_jpeg_start(void __iomem *regs);
+void exynos3250_jpeg_rstart(void __iomem *regs);
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs);
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+						unsigned int value);
+unsigned int exynos3250_jpeg_operating(void __iomem *regs);
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs);
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio);
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value);
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs);
+void exynos3250_jpeg_set_timer_status(void __iomem *regs);
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs);
+
+#endif /* JPEG_HW_EXYNOS3250_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-regs.h linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-regs.h
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/jpeg-regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/jpeg-regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
  *
  * Register definition file for Samsung JPEG codec driver
  *
- * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
@@ -373,5 +373,250 @@
 /* JPEG AC chrominance (values) Huffman table register */
 #define EXYNOS4_HUFF_TBL_HACCV	0x310
 
+/* Register and bit definitions for Exynos 3250 */
+
+/* JPEG mode register */
+#define EXYNOS3250_JPGMOD			0x00
+#define EXYNOS3250_PROC_MODE_MASK		(0x1 << 3)
+#define EXYNOS3250_PROC_MODE_DECOMPR		(0x1 << 3)
+#define EXYNOS3250_PROC_MODE_COMPR		(0x0 << 3)
+#define EXYNOS3250_SUBSAMPLING_MODE_MASK	(0x7 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_444		(0x0 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_422		(0x1 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_420		(0x2 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_411		(0x6 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_GRAY	(0x3 << 0)
+
+/* JPEG operation status register */
+#define EXYNOS3250_JPGOPR			0x04
+#define EXYNOS3250_JPGOPR_MASK			0x01
+
+/* Quantization and Huffman tables register */
+#define EXYNOS3250_QHTBL			0x08
+#define EXYNOS3250_QT_NUM_SHIFT(t)		((((t) - 1) << 1) + 8)
+#define EXYNOS3250_QT_NUM_MASK(t)		(0x3 << EXYNOS3250_QT_NUM_SHIFT(t))
+
+/* Huffman tables */
+#define EXYNOS3250_HT_NUM_AC_SHIFT(t)		(((t) << 1) - 1)
+#define EXYNOS3250_HT_NUM_AC_MASK(t)		(0x1 << EXYNOS3250_HT_NUM_AC_SHIFT(t))
+
+#define EXYNOS3250_HT_NUM_DC_SHIFT(t)		(((t) - 1) << 1)
+#define EXYNOS3250_HT_NUM_DC_MASK(t)		(0x1 << EXYNOS3250_HT_NUM_DC_SHIFT(t))
+
+/* JPEG restart interval register */
+#define EXYNOS3250_JPGDRI			0x0c
+#define EXYNOS3250_JPGDRI_MASK			0xffff
+
+/* JPEG vertical resolution register */
+#define EXYNOS3250_JPGY				0x10
+#define EXYNOS3250_JPGY_MASK			0xffff
+
+/* JPEG horizontal resolution register */
+#define EXYNOS3250_JPGX				0x14
+#define EXYNOS3250_JPGX_MASK			0xffff
+
+/* JPEG byte count register */
+#define EXYNOS3250_JPGCNT			0x18
+#define EXYNOS3250_JPGCNT_MASK			0xffffff
+
+/* JPEG interrupt mask register */
+#define EXYNOS3250_JPGINTSE			0x1c
+#define EXYNOS3250_JPEG_DONE_EN			(1 << 11)
+#define EXYNOS3250_WDMA_DONE_EN			(1 << 10)
+#define EXYNOS3250_RDMA_DONE_EN			(1 << 9)
+#define EXYNOS3250_ENC_STREAM_INT_EN		(1 << 8)
+#define EXYNOS3250_CORE_DONE_EN			(1 << 5)
+#define EXYNOS3250_ERR_INT_EN			(1 << 4)
+#define EXYNOS3250_HEAD_INT_EN			(1 << 3)
+
+/* JPEG interrupt status register */
+#define EXYNOS3250_JPGINTST			0x20
+#define EXYNOS3250_JPEG_DONE			(1 << 11)
+#define EXYNOS3250_WDMA_DONE			(1 << 10)
+#define EXYNOS3250_RDMA_DONE			(1 << 9)
+#define EXYNOS3250_ENC_STREAM_STAT		(1 << 8)
+#define EXYNOS3250_RESULT_STAT			(1 << 5)
+#define EXYNOS3250_STREAM_STAT			(1 << 4)
+#define EXYNOS3250_HEADER_STAT			(1 << 3)
+
+/*
+ * Base address of the luma component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_LUMA_BASE			0x100
+#define EXYNOS3250_SRC_TILE_EN_MASK		0x100
+
+/* Stride of source or destination luma raw image buffer */
+#define EXYNOS3250_LUMA_STRIDE			0x104
+
+/* Horizontal/vertical offset of active region in luma raw image buffer */
+#define EXYNOS3250_LUMA_XY_OFFSET		0x108
+#define EXYNOS3250_LUMA_YY_OFFSET_SHIFT		18
+#define EXYNOS3250_LUMA_YY_OFFSET_MASK		(0x1fff << EXYNOS3250_LUMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_LUMA_YX_OFFSET_SHIFT		2
+#define EXYNOS3250_LUMA_YX_OFFSET_MASK		(0x1fff << EXYNOS3250_LUMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cb) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_BASE			0x10c
+
+/* Stride of source or destination chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_STRIDE		0x110
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_XY_OFFSET		0x114
+#define EXYNOS3250_CHROMA_YY_OFFSET_SHIFT	18
+#define EXYNOS3250_CHROMA_YY_OFFSET_MASK	(0x1fff << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_YX_OFFSET_SHIFT	2
+#define EXYNOS3250_CHROMA_YX_OFFSET_MASK	(0x1fff << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cr) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_CR_BASE		0x118
+
+/* Stride of source or destination chroma(Cr) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_STRIDE		0x11c
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_XY_OFFSET		0x120
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT	18
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK	(0x1fff << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT	2
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK	(0x1fff << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT)
+
+/* Raw image data r/w address register */
+#define EXYNOS3250_JPG_IMGADR			0x50
+
+/* Source or destination JPEG file DMA buffer address */
+#define EXYNOS3250_JPG_JPGADR			0x124
+
+/* Coefficients for RGB-to-YCbCr converter register */
+#define EXYNOS3250_JPG_COEF(n)			(0x128 + (((n) - 1) << 2))
+#define EXYNOS3250_COEF_SHIFT(j)		((3 - (j)) << 3)
+#define EXYNOS3250_COEF_MASK(j)			(0xff << EXYNOS3250_COEF_SHIFT(j))
+
+/* Raw input format setting */
+#define EXYNOS3250_JPGCMOD			0x134
+#define EXYNOS3250_SRC_TILE_EN			(0x1 << 10)
+#define EXYNOS3250_SRC_NV_MASK			(0x1 << 9)
+#define EXYNOS3250_SRC_NV12			(0x0 << 9)
+#define EXYNOS3250_SRC_NV21			(0x1 << 9)
+#define EXYNOS3250_SRC_BIG_ENDIAN_MASK		(0x1 << 8)
+#define EXYNOS3250_SRC_BIG_ENDIAN		(0x1 << 8)
+#define EXYNOS3250_MODE_SEL_MASK		(0x7 << 5)
+#define EXYNOS3250_MODE_SEL_420_2P		(0x0 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_LUM_CHR	(0x1 << 5)
+#define EXYNOS3250_MODE_SEL_RGB565		(0x2 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_CHR_LUM	(0x3 << 5)
+#define EXYNOS3250_MODE_SEL_ARGB8888		(0x4 << 5)
+#define EXYNOS3250_MODE_SEL_420_3P		(0x5 << 5)
+#define EXYNOS3250_SRC_SWAP_RGB			(0x1 << 3)
+#define EXYNOS3250_SRC_SWAP_UV			(0x1 << 2)
+#define EXYNOS3250_MODE_Y16_MASK		(0x1 << 1)
+#define EXYNOS3250_MODE_Y16			(0x1 << 1)
+#define EXYNOS3250_HALF_EN_MASK			(0x1 << 0)
+#define EXYNOS3250_HALF_EN			(0x1 << 0)
+
+/* Power on/off and clock down control */
+#define EXYNOS3250_JPGCLKCON			0x138
+#define EXYNOS3250_CLK_DOWN_READY		(0x1 << 1)
+#define EXYNOS3250_POWER_ON			(0x1 << 0)
+
+/* Start compression or decompression */
+#define EXYNOS3250_JSTART			0x13c
+
+/* Restart decompression after header analysis */
+#define EXYNOS3250_JRSTART			0x140
+
+/* JPEG SW reset register */
+#define EXYNOS3250_SW_RESET			0x144
+
+/* JPEG timer setting register */
+#define EXYNOS3250_TIMER_SE			0x148
+#define EXYNOS3250_TIMER_INT_EN_SHIFT		31
+#define EXYNOS3250_TIMER_INT_EN			(1 << EXYNOS3250_TIMER_INT_EN_SHIFT)
+#define EXYNOS3250_TIMER_INIT_MASK		0x7fffffff
+
+/* JPEG timer status register */
+#define EXYNOS3250_TIMER_ST			0x14c
+#define EXYNOS3250_TIMER_INT_STAT_SHIFT		31
+#define EXYNOS3250_TIMER_INT_STAT		(1 << EXYNOS3250_TIMER_INT_STAT_SHIFT)
+#define EXYNOS3250_TIMER_CNT_SHIFT		0
+#define EXYNOS3250_TIMER_CNT_MASK		0x7fffffff
+
+/* Command status register */
+#define EXYNOS3250_COMSTAT			0x150
+#define EXYNOS3250_CUR_PROC_MODE		(0x1 << 1)
+#define EXYNOS3250_CUR_COM_MODE			(0x1 << 0)
+
+/* JPEG decompression output format register */
+#define EXYNOS3250_OUTFORM			0x154
+#define EXYNOS3250_OUT_ALPHA_MASK		(0xff << 24)
+#define EXYNOS3250_OUT_TILE_EN			(0x1 << 10)
+#define EXYNOS3250_OUT_NV_MASK			(0x1 << 9)
+#define EXYNOS3250_OUT_NV12			(0x0 << 9)
+#define EXYNOS3250_OUT_NV21			(0x1 << 9)
+#define EXYNOS3250_OUT_BIG_ENDIAN_MASK		(0x1 << 8)
+#define EXYNOS3250_OUT_BIG_ENDIAN		(0x1 << 8)
+#define EXYNOS3250_OUT_SWAP_RGB			(0x1 << 7)
+#define EXYNOS3250_OUT_SWAP_UV			(0x1 << 6)
+#define EXYNOS3250_OUT_FMT_MASK			(0x7 << 0)
+#define EXYNOS3250_OUT_FMT_420_2P		(0x0 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_LUM_CHR	(0x1 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_CHR_LUM	(0x3 << 0)
+#define EXYNOS3250_OUT_FMT_420_3P		(0x4 << 0)
+#define EXYNOS3250_OUT_FMT_RGB565		(0x5 << 0)
+#define EXYNOS3250_OUT_FMT_ARGB8888		(0x6 << 0)
+
+/* Input JPEG stream byte size for decompression */
+#define EXYNOS3250_DEC_STREAM_SIZE		0x158
+#define EXYNOS3250_DEC_STREAM_MASK		0x1fffffff
+
+/* The upper bound of the byte size of output compressed stream */
+#define EXYNOS3250_ENC_STREAM_BOUND		0x15c
+#define EXYNOS3250_ENC_STREAM_BOUND_MASK	0xffffc0
+
+/* Scale-down ratio when decoding */
+#define EXYNOS3250_DEC_SCALING_RATIO		0x160
+#define EXYNOS3250_DEC_SCALE_FACTOR_MASK	0x3
+#define EXYNOS3250_DEC_SCALE_FACTOR_8_8		0x0
+#define EXYNOS3250_DEC_SCALE_FACTOR_4_8		0x1
+#define EXYNOS3250_DEC_SCALE_FACTOR_2_8		0x2
+#define EXYNOS3250_DEC_SCALE_FACTOR_1_8		0x3
+
+/* Error check */
+#define EXYNOS3250_CRC_RESULT			0x164
+
+/* RDMA and WDMA operation status register */
+#define EXYNOS3250_DMA_OPER_STATUS		0x168
+#define EXYNOS3250_WDMA_OPER_STATUS		(0x1 << 1)
+#define EXYNOS3250_RDMA_OPER_STATUS		(0x1 << 0)
+
+/* DMA issue gathering number and issue number settings */
+#define EXYNOS3250_DMA_ISSUE_NUM		0x16c
+#define EXYNOS3250_WDMA_ISSUE_NUM_SHIFT		16
+#define EXYNOS3250_WDMA_ISSUE_NUM_MASK		(0x7 << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_RDMA_ISSUE_NUM_SHIFT		8
+#define EXYNOS3250_RDMA_ISSUE_NUM_MASK		(0x7 << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_ISSUE_GATHER_NUM_SHIFT	0
+#define EXYNOS3250_ISSUE_GATHER_NUM_MASK	(0x7 << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT)
+#define EXYNOS3250_DMA_MO_COUNT			0x7
+
+/* Version register */
+#define EXYNOS3250_VERSION			0x1fc
+
+/* RGB <-> YUV conversion coefficients */
+#define EXYNOS3250_JPEG_ENC_COEF1		0x01352e1e
+#define EXYNOS3250_JPEG_ENC_COEF2		0x00b0ae83
+#define EXYNOS3250_JPEG_ENC_COEF3		0x020cdc13
+
+#define EXYNOS3250_JPEG_DEC_COEF1		0x04a80199
+#define EXYNOS3250_JPEG_DEC_COEF2		0x04a9a064
+#define EXYNOS3250_JPEG_DEC_COEF3		0x04a80102
+
 #endif /* JPEG_REGS_H_ */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/Makefile linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/Makefile
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-jpeg/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-jpeg/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,2 +1,2 @@
-s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
+s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos3250.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c	2014-08-07 04:50:56.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c	2014-09-28 21:32:14.000000000 -0400
@@ -162,7 +162,7 @@ static void s5p_mfc_watchdog_worker(stru
 	/* Double check if there is at least one instance running.
 	 * If no instance is in memory than no firmware should be present */
 	if (dev->num_inst > 0) {
-		ret = s5p_mfc_reload_firmware(dev);
+		ret = s5p_mfc_load_firmware(dev);
 		if (ret) {
 			mfc_err("Failed to reload FW\n");
 			goto unlock;
@@ -724,7 +724,7 @@ static int s5p_mfc_open(struct file *fil
 		ret = -ENOMEM;
 		goto err_alloc;
 	}
-	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	v4l2_fh_init(&ctx->fh, vdev);
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
 	ctx->dev = dev;
@@ -1351,7 +1351,7 @@ static struct s5p_mfc_variant mfc_drvdat
 	.port_num	= MFC_NUM_PORTS,
 	.buf_size	= &buf_size_v5,
 	.buf_align	= &mfc_buf_align_v5,
-	.fw_name	= "/*(DEBLOBBED)*/",
+	.fw_name[0]	= "/*(DEBLOBBED)*/",
 };
 
 struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
@@ -1378,7 +1378,12 @@ static struct s5p_mfc_variant mfc_drvdat
 	.port_num	= MFC_NUM_PORTS_V6,
 	.buf_size	= &buf_size_v6,
 	.buf_align	= &mfc_buf_align_v6,
-	.fw_name        = "/*(DEBLOBBED)*/",
+	.fw_name[0]     = "/*(DEBLOBBED)*/",
+	/*
+	 * v6-v2 firmware contains bug fixes and interface change
+	 * for init buffer command
+	 */
+	.fw_name[1]     = "/*(DEBLOBBED)*/",
 };
 
 struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
@@ -1405,7 +1410,7 @@ static struct s5p_mfc_variant mfc_drvdat
 	.port_num	= MFC_NUM_PORTS_V7,
 	.buf_size	= &buf_size_v7,
 	.buf_align	= &mfc_buf_align_v7,
-	.fw_name        = "/*(DEBLOBBED)*/",
+	.fw_name[0]     = "/*(DEBLOBBED)*/",
 };
 
 struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
@@ -1432,7 +1437,7 @@ static struct s5p_mfc_variant mfc_drvdat
 	.port_num	= MFC_NUM_PORTS_V8,
 	.buf_size	= &buf_size_v8,
 	.buf_align	= &mfc_buf_align_v8,
-	.fw_name        = "/*(DEBLOBBED)*/",
+	.fw_name[0]     = "/*(DEBLOBBED)*/",
 };
 
 static struct platform_device_id mfc_driver_ids[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,8 @@
 #define MFC_BANK2_ALIGN_ORDER	13
 #define MFC_BASE_ALIGN_ORDER	17
 
+#define MFC_FW_MAX_VERSIONS	2
+
 #include <media/videobuf2-dma-contig.h>
 
 static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
@@ -163,6 +165,11 @@ enum s5p_mfc_decode_arg {
 	MFC_DEC_RES_CHANGE,
 };
 
+enum s5p_mfc_fw_ver {
+	MFC_FW_V1,
+	MFC_FW_V2,
+};
+
 #define MFC_BUF_FLAG_USED	(1 << 0)
 #define MFC_BUF_FLAG_EOS	(1 << 1)
 
@@ -225,7 +232,7 @@ struct s5p_mfc_variant {
 	u32 version_bit;
 	struct s5p_mfc_buf_size *buf_size;
 	struct s5p_mfc_buf_align *buf_align;
-	char	*fw_name;
+	char	*fw_name[MFC_FW_MAX_VERSIONS];
 };
 
 /**
@@ -287,6 +294,7 @@ struct s5p_mfc_priv_buf {
  * @warn_start:		hardware error code from which warnings start
  * @mfc_ops:		ops structure holding HW operation function pointers
  * @mfc_cmds:		cmd structure holding HW commands function pointers
+ * @fw_ver:		loaded firmware sub-version
  *
  */
 struct s5p_mfc_dev {
@@ -331,6 +339,7 @@ struct s5p_mfc_dev {
 	struct s5p_mfc_hw_ops *mfc_ops;
 	struct s5p_mfc_hw_cmds *mfc_cmds;
 	const struct s5p_mfc_regs *mfc_regs;
+	enum s5p_mfc_fw_ver fw_ver;
 };
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c	2014-08-07 04:50:54.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c	2014-09-28 21:32:11.000000000 -0400
@@ -38,8 +38,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mf
 	dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size,
 					&dev->bank1, GFP_KERNEL);
 
-	if (IS_ERR_OR_NULL(dev->fw_virt_addr)) {
-		dev->fw_virt_addr = NULL;
+	if (!dev->fw_virt_addr) {
 		mfc_err("Allocating bitprocessor buffer failed\n");
 		return -ENOMEM;
 	}
@@ -48,7 +47,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mf
 		bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
 					&bank2_dma_addr, GFP_KERNEL);
 
-		if (IS_ERR(dev->fw_virt_addr)) {
+		if (!bank2_virt) {
 			mfc_err("Allocating bank2 base failed\n");
 			dma_free_coherent(dev->mem_dev_l, dev->fw_size,
 				dev->fw_virt_addr, dev->bank1);
@@ -78,47 +77,23 @@ int s5p_mfc_alloc_firmware(struct s5p_mf
 int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
 {
 	struct firmware *fw_blob;
-	int err;
+	int i, err = -EINVAL;
 
 	/* Firmare has to be present as a separate file or compiled
 	 * into kernel. */
 	mfc_debug_enter();
 
-	err = reject_firmware((const struct firmware **)&fw_blob,
-				     dev->variant->fw_name, dev->v4l2_dev.dev);
-	if (err != 0) {
-		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
-		return -EINVAL;
-	}
-	if (fw_blob->size > dev->fw_size) {
-		mfc_err("MFC firmware is too big to be loaded\n");
-		release_firmware(fw_blob);
-		return -ENOMEM;
-	}
-	if (!dev->fw_virt_addr) {
-		mfc_err("MFC firmware is not allocated\n");
-		release_firmware(fw_blob);
-		return -EINVAL;
+	for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
+		if (!dev->variant->fw_name[i])
+			continue;
+		err = reject_firmware((const struct firmware **)&fw_blob,
+				dev->variant->fw_name[i], dev->v4l2_dev.dev);
+		if (!err) {
+			dev->fw_ver = (enum s5p_mfc_fw_ver) i;
+			break;
+		}
 	}
-	memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
-	wmb();
-	release_firmware(fw_blob);
-	mfc_debug_leave();
-	return 0;
-}
 
-/* Reload firmware to MFC */
-int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
-{
-	struct firmware *fw_blob;
-	int err;
-
-	/* Firmare has to be present as a separate file or compiled
-	 * into kernel. */
-	mfc_debug_enter();
-
-	err = reject_firmware((const struct firmware **)&fw_blob,
-				     dev->variant->fw_name, dev->v4l2_dev.dev);
 	if (err != 0) {
 		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c	2014-09-28 17:29:07.000000000 -0400
@@ -436,6 +436,7 @@ static int vidioc_s_fmt(struct file *fil
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
 	int ret = 0;
 	struct v4l2_pix_format_mplane *pix_mp;
+	struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
 
 	mfc_debug_enter();
 	ret = vidioc_try_fmt(file, priv, f);
@@ -459,11 +460,13 @@ static int vidioc_s_fmt(struct file *fil
 		mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
 		pix_mp->height = 0;
 		pix_mp->width = 0;
-		if (pix_mp->plane_fmt[0].sizeimage)
-			ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
-		else
+		if (pix_mp->plane_fmt[0].sizeimage == 0)
 			pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
 								DEF_CPB_SIZE;
+		else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)
+			ctx->dec_src_buf_size = buf_size->cpb;
+		else
+			ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
 		pix_mp->plane_fmt[0].bytesperline = 0;
 		ctx->state = MFCINST_INIT;
 		ret = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,8 @@
 #define WRITEL(data, reg) \
 	(WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg)))
 
+#define IS_MFCV6_V2(dev) (!IS_MFCV7_PLUS(dev) && dev->fw_ver == MFC_FW_V2)
+
 /* Allocate temporary buffers for decoding */
 static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
 {
@@ -1352,7 +1354,7 @@ static int s5p_mfc_init_decode_v6(struct
 		WRITEL(ctx->display_delay, mfc_regs->d_display_delay);
 	}
 
-	if (IS_MFCV7_PLUS(dev)) {
+	if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) {
 		WRITEL(reg, mfc_regs->d_dec_options);
 		reg = 0;
 	}
@@ -1367,7 +1369,7 @@ static int s5p_mfc_init_decode_v6(struct
 	if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
 		reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
 
-	if (IS_MFCV7_PLUS(dev))
+	if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev))
 		WRITEL(reg, mfc_regs->d_init_buffer_options);
 	else
 		WRITEL(reg, mfc_regs->d_dec_options);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,8 @@
 #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
 
@@ -50,6 +52,20 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *
 		goto err_p_ip_clk;
 	}
 
+	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");
+		} 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;
+			}
+		}
+	}
+
 	atomic_set(&pm->power, 0);
 #ifdef CONFIG_PM_RUNTIME
 	pm->device = &dev->plat_dev->dev;
@@ -59,6 +75,9 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *
 	atomic_set(&clk_ref, 0);
 #endif
 	return 0;
+
+err_s_clk:
+	clk_put(pm->clock);
 err_p_ip_clk:
 	clk_put(pm->clock_gate);
 err_g_ip_clk:
@@ -67,6 +86,11 @@ err_g_ip_clk:
 
 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);
+	}
 	clk_unprepare(pm->clock_gate);
 	clk_put(pm->clock_gate);
 #ifdef CONFIG_PM_RUNTIME
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/s5p-tv/mixer_video.c linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-tv/mixer_video.c
--- linux-libre-3.16-gnu/drivers/media/platform/s5p-tv/mixer_video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/s5p-tv/mixer_video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1109,8 +1109,6 @@ struct mxr_layer *mxr_base_layer_create(
 		.ioctl_ops = &mxr_ioctl_ops,
 	};
 	strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
-	/* let framework control PRIORITY */
-	set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
 
 	video_set_drvdata(&layer->vfd, layer);
 	layer->vfd.lock = &layer->mutex;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/sh_veu.c linux-libre-3.17-rc7-gnu/drivers/media/platform/sh_veu.c
--- linux-libre-3.16-gnu/drivers/media/platform/sh_veu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/sh_veu.c	2014-09-28 17:29:07.000000000 -0400
@@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_fi
 	pix->bytesperline	= vfmt->bytesperline;
 	pix->sizeimage		= vfmt->bytesperline * pix->height *
 		vfmt->fmt->depth / vfmt->fmt->ydepth;
-	pix->priv		= 0;
 	dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
 		f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
 
@@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_fo
 
 	pix->pixelformat	= fmt->fourcc;
 	pix->colorspace		= sh_veu_4cc2cspace(pix->pixelformat);
-	pix->priv		= 0;
 
 	pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/atmel-isi.c linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/atmel-isi.c
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/atmel-isi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/atmel-isi.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
 #include <media/atmel-isi.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
+#include <media/v4l2-of.h>
 #include <media/videobuf2-dma-contig.h>
 
 #define MAX_BUFFER_NUM			32
@@ -33,6 +34,7 @@
 #define VID_LIMIT_BYTES			(16 * 1024 * 1024)
 #define MIN_FRAME_RATE			15
 #define FRAME_INTERVAL_MILLI_SEC	(1000 / MIN_FRAME_RATE)
+#define ISI_DEFAULT_MCLK_FREQ		25000000
 
 /* Frame buffer descriptor */
 struct fbd {
@@ -84,7 +86,7 @@ struct atmel_isi {
 	struct clk			*mck;
 	unsigned int			irq;
 
-	struct isi_platform_data	*pdata;
+	struct isi_platform_data	pdata;
 	u16				width_flags;	/* max 12 bits */
 
 	struct list_head		video_buffer_list;
@@ -350,7 +352,7 @@ static void start_dma(struct atmel_isi *
 
 	cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK;
 	/* Enable linked list */
-	cfg1 |= isi->pdata->frate | ISI_CFG1_DISCR;
+	cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR;
 
 	/* Enable codec path and ISI */
 	ctrl = ISI_CTRL_CDC | ISI_CTRL_EN;
@@ -795,7 +797,7 @@ static int isi_camera_set_bus_param(stru
 	/* Make choises, based on platform preferences */
 	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
 	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
-		if (isi->pdata->hsync_act_low)
+		if (isi->pdata.hsync_act_low)
 			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
 			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
@@ -803,7 +805,7 @@ static int isi_camera_set_bus_param(stru
 
 	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
 	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
-		if (isi->pdata->vsync_act_low)
+		if (isi->pdata.vsync_act_low)
 			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
 			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
@@ -811,7 +813,7 @@ static int isi_camera_set_bus_param(stru
 
 	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
 	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
-		if (isi->pdata->pclk_act_falling)
+		if (isi->pdata.pclk_act_falling)
 			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 		else
 			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
@@ -833,9 +835,9 @@ static int isi_camera_set_bus_param(stru
 	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
 
-	if (isi->pdata->has_emb_sync)
+	if (isi->pdata.has_emb_sync)
 		cfg1 |= ISI_CFG1_EMB_SYNC;
-	if (isi->pdata->full_mode)
+	if (isi->pdata.full_mode)
 		cfg1 |= ISI_CFG1_FULL_MODE;
 
 	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -876,6 +878,51 @@ static int atmel_isi_remove(struct platf
 	return 0;
 }
 
+static int atmel_isi_probe_dt(struct atmel_isi *isi,
+			struct platform_device *pdev)
+{
+	struct device_node *np= pdev->dev.of_node;
+	struct v4l2_of_endpoint ep;
+	int err;
+
+	/* Default settings for ISI */
+	isi->pdata.full_mode = 1;
+	isi->pdata.mck_hz = ISI_DEFAULT_MCLK_FREQ;
+	isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL;
+
+	np = of_graph_get_next_endpoint(np, NULL);
+	if (!np) {
+		dev_err(&pdev->dev, "Could not find the endpoint\n");
+		return -EINVAL;
+	}
+
+	err = v4l2_of_parse_endpoint(np, &ep);
+	if (err) {
+		dev_err(&pdev->dev, "Could not parse the endpoint\n");
+		goto err_probe_dt;
+	}
+
+	switch (ep.bus.parallel.bus_width) {
+	case 8:
+		isi->pdata.data_width_flags = ISI_DATAWIDTH_8;
+		break;
+	case 10:
+		isi->pdata.data_width_flags =
+				ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10;
+		break;
+	default:
+		dev_err(&pdev->dev, "Unsupported bus width: %d\n",
+				ep.bus.parallel.bus_width);
+		err = -EINVAL;
+		goto err_probe_dt;
+	}
+
+err_probe_dt:
+	of_node_put(np);
+
+	return err;
+}
+
 static int atmel_isi_probe(struct platform_device *pdev)
 {
 	unsigned int irq;
@@ -887,7 +934,7 @@ static int atmel_isi_probe(struct platfo
 	struct isi_platform_data *pdata;
 
 	pdata = dev->platform_data;
-	if (!pdata || !pdata->data_width_flags) {
+	if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) {
 		dev_err(&pdev->dev,
 			"No config available for Atmel ISI\n");
 		return -EINVAL;
@@ -903,7 +950,14 @@ static int atmel_isi_probe(struct platfo
 	if (IS_ERR(isi->pclk))
 		return PTR_ERR(isi->pclk);
 
-	isi->pdata = pdata;
+	if (pdata) {
+		memcpy(&isi->pdata, pdata, sizeof(isi->pdata));
+	} else {
+		ret = atmel_isi_probe_dt(isi, pdev);
+		if (ret)
+			return ret;
+	}
+
 	isi->active = NULL;
 	spin_lock_init(&isi->lock);
 	INIT_LIST_HEAD(&isi->video_buffer_list);
@@ -919,7 +973,7 @@ static int atmel_isi_probe(struct platfo
 		/* Set ISI_MCK's frequency, it should be faster than pixel
 		 * clock.
 		 */
-		ret = clk_set_rate(isi->mck, pdata->mck_hz);
+		ret = clk_set_rate(isi->mck, isi->pdata.mck_hz);
 		if (ret < 0)
 			return ret;
 	}
@@ -953,9 +1007,9 @@ static int atmel_isi_probe(struct platfo
 		goto err_ioremap;
 	}
 
-	if (pdata->data_width_flags & ISI_DATAWIDTH_8)
+	if (isi->pdata.data_width_flags & ISI_DATAWIDTH_8)
 		isi->width_flags = 1 << 7;
-	if (pdata->data_width_flags & ISI_DATAWIDTH_10)
+	if (isi->pdata.data_width_flags & ISI_DATAWIDTH_10)
 		isi->width_flags |= 1 << 9;
 
 	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -980,6 +1034,11 @@ static int atmel_isi_probe(struct platfo
 	soc_host->v4l2_dev.dev	= &pdev->dev;
 	soc_host->nr		= pdev->id;
 
+	if (isi->pdata.asd_sizes) {
+		soc_host->asd = isi->pdata.asd;
+		soc_host->asd_sizes = isi->pdata.asd_sizes;
+	}
+
 	ret = soc_camera_host_register(soc_host);
 	if (ret) {
 		dev_err(&pdev->dev, "Unable to register soc camera host\n");
@@ -1000,11 +1059,18 @@ err_alloc_ctx:
 	return ret;
 }
 
+static const struct of_device_id atmel_isi_of_match[] = {
+	{ .compatible = "atmel,at91sam9g45-isi" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, atmel_isi_of_match);
+
 static struct platform_driver atmel_isi_driver = {
 	.remove		= atmel_isi_remove,
 	.driver		= {
 		.name = "atmel_isi",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(atmel_isi_of_match),
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/Kconfig
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -17,19 +17,6 @@ config SOC_CAMERA_PLATFORM
 	help
 	  This is a generic SoC camera platform driver, useful for testing
 
-config MX1_VIDEO
-	bool
-
-config VIDEO_MX1
-	tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
-	depends on BROKEN
-	depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA
-	select FIQ
-	select VIDEOBUF_DMA_CONTIG
-	select MX1_VIDEO
-	---help---
-	  This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface
-
 config VIDEO_MX3
 	tristate "i.MX3x Camera Sensor Interface driver"
 	depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
@@ -47,6 +34,7 @@ config VIDEO_PXA27x
 config VIDEO_RCAR_VIN
 	tristate "R-Car Video Input (VIN) support"
 	depends on VIDEO_DEV && SOC_CAMERA
+	depends on ARCH_SHMOBILE || COMPILE_TEST
 	select VIDEOBUF2_DMA_CONTIG
 	select SOC_CAMERA_SCALE_CROP
 	---help---
@@ -55,12 +43,14 @@ config VIDEO_RCAR_VIN
 config VIDEO_SH_MOBILE_CSI2
 	tristate "SuperH Mobile MIPI CSI-2 Interface driver"
 	depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+	depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
 	---help---
 	  This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
 
 config VIDEO_SH_MOBILE_CEU
 	tristate "SuperH Mobile CEU Interface driver"
 	depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
+	depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
 	select VIDEOBUF2_DMA_CONTIG
 	select SOC_CAMERA_SCALE_CROP
 	---help---
@@ -76,7 +66,7 @@ config VIDEO_OMAP1
 
 config VIDEO_MX2
 	tristate "i.MX27 Camera Sensor Interface driver"
-	depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27
+	depends on VIDEO_DEV && SOC_CAMERA && SOC_IMX27
 	select VIDEOBUF2_DMA_CONTIG
 	---help---
 	  This is a v4l2 driver for the i.MX27 Camera Sensor Interface
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/Makefile linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/Makefile
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc
 
 # soc-camera host drivers have to be linked after camera drivers
 obj-$(CONFIG_VIDEO_ATMEL_ISI)		+= atmel-isi.o
-obj-$(CONFIG_VIDEO_MX1)			+= mx1_camera.o
 obj-$(CONFIG_VIDEO_MX2)			+= mx2_camera.o
 obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o
 obj-$(CONFIG_VIDEO_OMAP1)		+= omap1_camera.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/mx1_camera.c linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/mx1_camera.c
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/mx1_camera.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/mx1_camera.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,866 +0,0 @@
-/*
- * V4L2 Driver for i.MXL/i.MXL camera (CSI) host
- *
- * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com>
- *
- * Based on PXA SoC camera driver
- * Copyright (C) 2006, Sascha Hauer, Pengutronix
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/videodev2.h>
-
-#include <media/soc_camera.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf-dma-contig.h>
-#include <media/soc_mediabus.h>
-
-#include <asm/dma.h>
-#include <asm/fiq.h>
-#include <mach/dma-mx1-mx2.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <linux/platform_data/camera-mx1.h>
-
-/*
- * CSI registers
- */
-#define CSICR1		0x00			/* CSI Control Register 1 */
-#define CSISR		0x08			/* CSI Status Register */
-#define CSIRXR		0x10			/* CSI RxFIFO Register */
-
-#define CSICR1_RXFF_LEVEL(x)	(((x) & 0x3) << 19)
-#define CSICR1_SOF_POL		(1 << 17)
-#define CSICR1_SOF_INTEN	(1 << 16)
-#define CSICR1_MCLKDIV(x)	(((x) & 0xf) << 12)
-#define CSICR1_MCLKEN		(1 << 9)
-#define CSICR1_FCC		(1 << 8)
-#define CSICR1_BIG_ENDIAN	(1 << 7)
-#define CSICR1_CLR_RXFIFO	(1 << 5)
-#define CSICR1_GCLK_MODE	(1 << 4)
-#define CSICR1_DATA_POL		(1 << 2)
-#define CSICR1_REDGE		(1 << 1)
-#define CSICR1_EN		(1 << 0)
-
-#define CSISR_SFF_OR_INT	(1 << 25)
-#define CSISR_RFF_OR_INT	(1 << 24)
-#define CSISR_STATFF_INT	(1 << 21)
-#define CSISR_RXFF_INT		(1 << 18)
-#define CSISR_SOF_INT		(1 << 16)
-#define CSISR_DRDY		(1 << 0)
-
-#define DRIVER_VERSION "0.0.2"
-#define DRIVER_NAME "mx1-camera"
-
-#define CSI_IRQ_MASK	(CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
-			CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT)
-
-#define CSI_BUS_FLAGS	(V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
-			V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \
-			V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
-			V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW)
-
-#define MAX_VIDEO_MEM 16	/* Video memory limit in megabytes */
-
-/*
- * Structures
- */
-
-/* buffer for one video frame */
-struct mx1_buffer {
-	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer		vb;
-	enum v4l2_mbus_pixelcode	code;
-	int				inwork;
-};
-
-/*
- * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor
- * Interface. If anyone ever builds hardware to enable more than
- * one camera, they will have to modify this driver too
- */
-struct mx1_camera_dev {
-	struct soc_camera_host		soc_host;
-	struct mx1_camera_pdata		*pdata;
-	struct mx1_buffer		*active;
-	struct resource			*res;
-	struct clk			*clk;
-	struct list_head		capture;
-
-	void __iomem			*base;
-	int				dma_chan;
-	unsigned int			irq;
-	unsigned long			mclk;
-
-	spinlock_t			lock;
-};
-
-/*
- *  Videobuf operations
- */
-static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
-			      unsigned int *size)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-
-	*size = icd->sizeimage;
-
-	if (!*count)
-		*count = 32;
-
-	if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
-		*count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
-
-	dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
-
-	return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-	struct videobuf_buffer *vb = &buf->vb;
-
-	BUG_ON(in_interrupt());
-
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	/*
-	 * This waits until this buffer is out of danger, i.e., until it is no
-	 * longer in STATE_QUEUED or STATE_ACTIVE
-	 */
-	videobuf_waiton(vq, vb, 0, 0);
-	videobuf_dma_contig_free(vq, vb);
-
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int mx1_videobuf_prepare(struct videobuf_queue *vq,
-		struct videobuf_buffer *vb, enum v4l2_field field)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-	struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-	int ret;
-
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	/* Added list head initialization on alloc */
-	WARN_ON(!list_empty(&vb->queue));
-
-	BUG_ON(NULL == icd->current_fmt);
-
-	/*
-	 * I think, in buf_prepare you only have to protect global data,
-	 * the actual buffer is yours
-	 */
-	buf->inwork = 1;
-
-	if (buf->code	!= icd->current_fmt->code ||
-	    vb->width	!= icd->user_width ||
-	    vb->height	!= icd->user_height ||
-	    vb->field	!= field) {
-		buf->code	= icd->current_fmt->code;
-		vb->width	= icd->user_width;
-		vb->height	= icd->user_height;
-		vb->field	= field;
-		vb->state	= VIDEOBUF_NEEDS_INIT;
-	}
-
-	vb->size = icd->sizeimage;
-	if (0 != vb->baddr && vb->bsize < vb->size) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		ret = videobuf_iolock(vq, vb, NULL);
-		if (ret)
-			goto fail;
-
-		vb->state = VIDEOBUF_PREPARED;
-	}
-
-	buf->inwork = 0;
-
-	return 0;
-
-fail:
-	free_buffer(vq, buf);
-out:
-	buf->inwork = 0;
-	return ret;
-}
-
-static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
-{
-	struct videobuf_buffer *vbuf = &pcdev->active->vb;
-	struct device *dev = pcdev->soc_host.icd->parent;
-	int ret;
-
-	if (unlikely(!pcdev->active)) {
-		dev_err(dev, "DMA End IRQ with no active buffer\n");
-		return -EFAULT;
-	}
-
-	/* setup sg list for future DMA */
-	ret = imx_dma_setup_single(pcdev->dma_chan,
-		videobuf_to_dma_contig(vbuf),
-		vbuf->size, pcdev->res->start +
-		CSIRXR, DMA_MODE_READ);
-	if (unlikely(ret))
-		dev_err(dev, "Failed to setup DMA sg list\n");
-
-	return ret;
-}
-
-/* Called under spinlock_irqsave(&pcdev->lock, ...) */
-static void mx1_videobuf_queue(struct videobuf_queue *vq,
-						struct videobuf_buffer *vb)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct mx1_camera_dev *pcdev = ici->priv;
-	struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	list_add_tail(&vb->queue, &pcdev->capture);
-
-	vb->state = VIDEOBUF_ACTIVE;
-
-	if (!pcdev->active) {
-		pcdev->active = buf;
-
-		/* setup sg list for future DMA */
-		if (!mx1_camera_setup_dma(pcdev)) {
-			unsigned int temp;
-			/* enable SOF irq */
-			temp = __raw_readl(pcdev->base + CSICR1) |
-							CSICR1_SOF_INTEN;
-			__raw_writel(temp, pcdev->base + CSICR1);
-		}
-	}
-}
-
-static void mx1_videobuf_release(struct videobuf_queue *vq,
-				 struct videobuf_buffer *vb)
-{
-	struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-#ifdef DEBUG
-	struct soc_camera_device *icd = vq->priv_data;
-	struct device *dev = icd->parent;
-
-	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	switch (vb->state) {
-	case VIDEOBUF_ACTIVE:
-		dev_dbg(dev, "%s (active)\n", __func__);
-		break;
-	case VIDEOBUF_QUEUED:
-		dev_dbg(dev, "%s (queued)\n", __func__);
-		break;
-	case VIDEOBUF_PREPARED:
-		dev_dbg(dev, "%s (prepared)\n", __func__);
-		break;
-	default:
-		dev_dbg(dev, "%s (unknown)\n", __func__);
-		break;
-	}
-#endif
-
-	free_buffer(vq, buf);
-}
-
-static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev,
-			      struct videobuf_buffer *vb,
-			      struct mx1_buffer *buf)
-{
-	/* _init is used to debug races, see comment in mx1_camera_reqbufs() */
-	list_del_init(&vb->queue);
-	vb->state = VIDEOBUF_DONE;
-	v4l2_get_timestamp(&vb->ts);
-	vb->field_count++;
-	wake_up(&vb->done);
-
-	if (list_empty(&pcdev->capture)) {
-		pcdev->active = NULL;
-		return;
-	}
-
-	pcdev->active = list_entry(pcdev->capture.next,
-				   struct mx1_buffer, vb.queue);
-
-	/* setup sg list for future DMA */
-	if (likely(!mx1_camera_setup_dma(pcdev))) {
-		unsigned int temp;
-
-		/* enable SOF irq */
-		temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN;
-		__raw_writel(temp, pcdev->base + CSICR1);
-	}
-}
-
-static void mx1_camera_dma_irq(int channel, void *data)
-{
-	struct mx1_camera_dev *pcdev = data;
-	struct device *dev = pcdev->soc_host.icd->parent;
-	struct mx1_buffer *buf;
-	struct videobuf_buffer *vb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pcdev->lock, flags);
-
-	imx_dma_disable(channel);
-
-	if (unlikely(!pcdev->active)) {
-		dev_err(dev, "DMA End IRQ with no active buffer\n");
-		goto out;
-	}
-
-	vb = &pcdev->active->vb;
-	buf = container_of(vb, struct mx1_buffer, vb);
-	WARN_ON(buf->inwork || list_empty(&vb->queue));
-	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	mx1_camera_wakeup(pcdev, vb, buf);
-out:
-	spin_unlock_irqrestore(&pcdev->lock, flags);
-}
-
-static struct videobuf_queue_ops mx1_videobuf_ops = {
-	.buf_setup	= mx1_videobuf_setup,
-	.buf_prepare	= mx1_videobuf_prepare,
-	.buf_queue	= mx1_videobuf_queue,
-	.buf_release	= mx1_videobuf_release,
-};
-
-static void mx1_camera_init_videobuf(struct videobuf_queue *q,
-				     struct soc_camera_device *icd)
-{
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct mx1_camera_dev *pcdev = ici->priv;
-
-	videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent,
-				&pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				V4L2_FIELD_NONE,
-				sizeof(struct mx1_buffer), icd, &ici->host_lock);
-}
-
-static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
-{
-	unsigned int mclk = pcdev->mclk;
-	unsigned long div;
-	unsigned long lcdclk;
-
-	lcdclk = clk_get_rate(pcdev->clk);
-
-	/*
-	 * We verify platform_mclk_10khz != 0, so if anyone breaks it, here
-	 * they get a nice Oops
-	 */
-	div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
-
-	dev_dbg(pcdev->soc_host.icd->parent,
-		"System clock %lukHz, target freq %dkHz, divisor %lu\n",
-		lcdclk / 1000, mclk / 1000, div);
-
-	return div;
-}
-
-static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
-{
-	unsigned int csicr1 = CSICR1_EN;
-
-	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n");
-
-	clk_prepare_enable(pcdev->clk);
-
-	/* enable CSI before doing anything else */
-	__raw_writel(csicr1, pcdev->base + CSICR1);
-
-	csicr1 |= CSICR1_MCLKEN | CSICR1_FCC | CSICR1_GCLK_MODE;
-	csicr1 |= CSICR1_MCLKDIV(mclk_get_divisor(pcdev));
-	csicr1 |= CSICR1_RXFF_LEVEL(2); /* 16 words */
-
-	__raw_writel(csicr1, pcdev->base + CSICR1);
-}
-
-static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
-{
-	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n");
-
-	/* Disable all CSI interface */
-	__raw_writel(0x00, pcdev->base + CSICR1);
-
-	clk_disable_unprepare(pcdev->clk);
-}
-
-static int mx1_camera_add_device(struct soc_camera_device *icd)
-{
-	dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n",
-		 icd->devnum);
-
-	return 0;
-}
-
-static void mx1_camera_remove_device(struct soc_camera_device *icd)
-{
-	dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n",
-		 icd->devnum);
-}
-
-/*
- * The following two functions absolutely depend on the fact, that
- * there can be only one camera on i.MX1/i.MXL camera sensor interface
- */
-static int mx1_camera_clock_start(struct soc_camera_host *ici)
-{
-	struct mx1_camera_dev *pcdev = ici->priv;
-
-	mx1_camera_activate(pcdev);
-
-	return 0;
-}
-
-static void mx1_camera_clock_stop(struct soc_camera_host *ici)
-{
-	struct mx1_camera_dev *pcdev = ici->priv;
-	unsigned int csicr1;
-
-	/* disable interrupts */
-	csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK;
-	__raw_writel(csicr1, pcdev->base + CSICR1);
-
-	/* Stop DMA engine */
-	imx_dma_disable(pcdev->dma_chan);
-
-	mx1_camera_deactivate(pcdev);
-}
-
-static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
-{
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct mx1_camera_dev *pcdev = ici->priv;
-	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
-	unsigned long common_flags;
-	unsigned int csicr1;
-	int ret;
-
-	/* MX1 supports only 8bit buswidth */
-	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
-	if (!ret) {
-		common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS);
-		if (!common_flags) {
-			dev_warn(icd->parent,
-				 "Flags incompatible: camera 0x%x, host 0x%x\n",
-				 cfg.flags, CSI_BUS_FLAGS);
-			return -EINVAL;
-		}
-	} else if (ret != -ENOIOCTLCMD) {
-		return ret;
-	} else {
-		common_flags = CSI_BUS_FLAGS;
-	}
-
-	/* Make choises, based on platform choice */
-	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
-		(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
-			if (!pcdev->pdata ||
-			     pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
-				common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
-			else
-				common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
-	}
-
-	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
-		(common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
-			if (!pcdev->pdata ||
-			     pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
-				common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
-			else
-				common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
-	}
-
-	if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
-		(common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
-			if (!pcdev->pdata ||
-			     pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
-				common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
-			else
-				common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
-	}
-
-	cfg.flags = common_flags;
-	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
-	if (ret < 0 && ret != -ENOIOCTLCMD) {
-		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
-			common_flags, ret);
-		return ret;
-	}
-
-	csicr1 = __raw_readl(pcdev->base + CSICR1);
-
-	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
-		csicr1 |= CSICR1_REDGE;
-	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
-		csicr1 |= CSICR1_SOF_POL;
-	if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
-		csicr1 |= CSICR1_DATA_POL;
-
-	__raw_writel(csicr1, pcdev->base + CSICR1);
-
-	return 0;
-}
-
-static int mx1_camera_set_fmt(struct soc_camera_device *icd,
-			      struct v4l2_format *f)
-{
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	const struct soc_camera_format_xlate *xlate;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	struct v4l2_mbus_framefmt mf;
-	int ret, buswidth;
-
-	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
-	if (!xlate) {
-		dev_warn(icd->parent, "Format %x not found\n",
-			 pix->pixelformat);
-		return -EINVAL;
-	}
-
-	buswidth = xlate->host_fmt->bits_per_sample;
-	if (buswidth > 8) {
-		dev_warn(icd->parent,
-			 "bits-per-sample %d for format %x unsupported\n",
-			 buswidth, pix->pixelformat);
-		return -EINVAL;
-	}
-
-	mf.width	= pix->width;
-	mf.height	= pix->height;
-	mf.field	= pix->field;
-	mf.colorspace	= pix->colorspace;
-	mf.code		= xlate->code;
-
-	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
-	if (ret < 0)
-		return ret;
-
-	if (mf.code != xlate->code)
-		return -EINVAL;
-
-	pix->width		= mf.width;
-	pix->height		= mf.height;
-	pix->field		= mf.field;
-	pix->colorspace		= mf.colorspace;
-	icd->current_fmt	= xlate;
-
-	return ret;
-}
-
-static int mx1_camera_try_fmt(struct soc_camera_device *icd,
-			      struct v4l2_format *f)
-{
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	const struct soc_camera_format_xlate *xlate;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	struct v4l2_mbus_framefmt mf;
-	int ret;
-	/* TODO: limit to mx1 hardware capabilities */
-
-	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
-	if (!xlate) {
-		dev_warn(icd->parent, "Format %x not found\n",
-			 pix->pixelformat);
-		return -EINVAL;
-	}
-
-	mf.width	= pix->width;
-	mf.height	= pix->height;
-	mf.field	= pix->field;
-	mf.colorspace	= pix->colorspace;
-	mf.code		= xlate->code;
-
-	/* limit to sensor capabilities */
-	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
-	if (ret < 0)
-		return ret;
-
-	pix->width	= mf.width;
-	pix->height	= mf.height;
-	pix->field	= mf.field;
-	pix->colorspace	= mf.colorspace;
-
-	return 0;
-}
-
-static int mx1_camera_reqbufs(struct soc_camera_device *icd,
-			      struct v4l2_requestbuffers *p)
-{
-	int i;
-
-	/*
-	 * This is for locking debugging only. I removed spinlocks and now I
-	 * check whether .prepare is ever called on a linked buffer, or whether
-	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-	 * it hadn't triggered
-	 */
-	for (i = 0; i < p->count; i++) {
-		struct mx1_buffer *buf = container_of(icd->vb_vidq.bufs[i],
-						      struct mx1_buffer, vb);
-		buf->inwork = 0;
-		INIT_LIST_HEAD(&buf->vb.queue);
-	}
-
-	return 0;
-}
-
-static unsigned int mx1_camera_poll(struct file *file, poll_table *pt)
-{
-	struct soc_camera_device *icd = file->private_data;
-	struct mx1_buffer *buf;
-
-	buf = list_entry(icd->vb_vidq.stream.next, struct mx1_buffer,
-			 vb.stream);
-
-	poll_wait(file, &buf->vb.done, pt);
-
-	if (buf->vb.state == VIDEOBUF_DONE ||
-	    buf->vb.state == VIDEOBUF_ERROR)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
-
-static int mx1_camera_querycap(struct soc_camera_host *ici,
-			       struct v4l2_capability *cap)
-{
-	/* cap->name is set by the friendly caller:-> */
-	strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card));
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-
-	return 0;
-}
-
-static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
-	.owner		= THIS_MODULE,
-	.add		= mx1_camera_add_device,
-	.remove		= mx1_camera_remove_device,
-	.clock_start	= mx1_camera_clock_start,
-	.clock_stop	= mx1_camera_clock_stop,
-	.set_bus_param	= mx1_camera_set_bus_param,
-	.set_fmt	= mx1_camera_set_fmt,
-	.try_fmt	= mx1_camera_try_fmt,
-	.init_videobuf	= mx1_camera_init_videobuf,
-	.reqbufs	= mx1_camera_reqbufs,
-	.poll		= mx1_camera_poll,
-	.querycap	= mx1_camera_querycap,
-};
-
-static struct fiq_handler fh = {
-	.name		= "csi_sof"
-};
-
-static int __init mx1_camera_probe(struct platform_device *pdev)
-{
-	struct mx1_camera_dev *pcdev;
-	struct resource *res;
-	struct pt_regs regs;
-	struct clk *clk;
-	void __iomem *base;
-	unsigned int irq;
-	int err = 0;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!res || (int)irq <= 0) {
-		err = -ENODEV;
-		goto exit;
-	}
-
-	clk = clk_get(&pdev->dev, "csi_clk");
-	if (IS_ERR(clk)) {
-		err = PTR_ERR(clk);
-		goto exit;
-	}
-
-	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
-	if (!pcdev) {
-		dev_err(&pdev->dev, "Could not allocate pcdev\n");
-		err = -ENOMEM;
-		goto exit_put_clk;
-	}
-
-	pcdev->res = res;
-	pcdev->clk = clk;
-
-	pcdev->pdata = pdev->dev.platform_data;
-
-	if (pcdev->pdata)
-		pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
-
-	if (!pcdev->mclk) {
-		dev_warn(&pdev->dev,
-			 "mclk_10khz == 0! Please, fix your platform data. "
-			 "Using default 20MHz\n");
-		pcdev->mclk = 20000000;
-	}
-
-	INIT_LIST_HEAD(&pcdev->capture);
-	spin_lock_init(&pcdev->lock);
-
-	/*
-	 * Request the regions.
-	 */
-	if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) {
-		err = -EBUSY;
-		goto exit_kfree;
-	}
-
-	base = ioremap(res->start, resource_size(res));
-	if (!base) {
-		err = -ENOMEM;
-		goto exit_release;
-	}
-	pcdev->irq = irq;
-	pcdev->base = base;
-
-	/* request dma */
-	pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
-	if (pcdev->dma_chan < 0) {
-		dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
-		err = -EBUSY;
-		goto exit_iounmap;
-	}
-	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
-
-	imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
-			       pcdev);
-
-	imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO,
-			       IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0);
-	/* burst length : 16 words = 64 bytes */
-	imx_dma_config_burstlen(pcdev->dma_chan, 0);
-
-	/* request irq */
-	err = claim_fiq(&fh);
-	if (err) {
-		dev_err(&pdev->dev, "Camera interrupt register failed\n");
-		goto exit_free_dma;
-	}
-
-	set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end -
-						   &mx1_camera_sof_fiq_start);
-
-	regs.ARM_r8 = (long)MX1_DMA_DIMR;
-	regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan);
-	regs.ARM_r10 = (long)pcdev->base + CSICR1;
-	regs.ARM_fp = (long)pcdev->base + CSISR;
-	regs.ARM_sp = 1 << pcdev->dma_chan;
-	set_fiq_regs(&regs);
-
-	mxc_set_irq_fiq(irq, 1);
-	enable_fiq(irq);
-
-	pcdev->soc_host.drv_name	= DRIVER_NAME;
-	pcdev->soc_host.ops		= &mx1_soc_camera_host_ops;
-	pcdev->soc_host.priv		= pcdev;
-	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev;
-	pcdev->soc_host.nr		= pdev->id;
-	err = soc_camera_host_register(&pcdev->soc_host);
-	if (err)
-		goto exit_free_irq;
-
-	dev_info(&pdev->dev, "MX1 Camera driver loaded\n");
-
-	return 0;
-
-exit_free_irq:
-	disable_fiq(irq);
-	mxc_set_irq_fiq(irq, 0);
-	release_fiq(&fh);
-exit_free_dma:
-	imx_dma_free(pcdev->dma_chan);
-exit_iounmap:
-	iounmap(base);
-exit_release:
-	release_mem_region(res->start, resource_size(res));
-exit_kfree:
-	kfree(pcdev);
-exit_put_clk:
-	clk_put(clk);
-exit:
-	return err;
-}
-
-static int __exit mx1_camera_remove(struct platform_device *pdev)
-{
-	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
-	struct mx1_camera_dev *pcdev = container_of(soc_host,
-					struct mx1_camera_dev, soc_host);
-	struct resource *res;
-
-	imx_dma_free(pcdev->dma_chan);
-	disable_fiq(pcdev->irq);
-	mxc_set_irq_fiq(pcdev->irq, 0);
-	release_fiq(&fh);
-
-	clk_put(pcdev->clk);
-
-	soc_camera_host_unregister(soc_host);
-
-	iounmap(pcdev->base);
-
-	res = pcdev->res;
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(pcdev);
-
-	dev_info(&pdev->dev, "MX1 Camera driver unloaded\n");
-
-	return 0;
-}
-
-static struct platform_driver mx1_camera_driver = {
-	.driver		= {
-		.name	= DRIVER_NAME,
-	},
-	.remove		= __exit_p(mx1_camera_remove),
-};
-
-module_platform_driver_probe(mx1_camera_driver, mx1_camera_probe);
-
-MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver");
-MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/pxa_camera.c linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/pxa_camera.c
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/pxa_camera.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/pxa_camera.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 #include <media/videobuf-dma-sg.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
+#include <media/v4l2-of.h>
 
 #include <linux/videodev2.h>
 
@@ -1650,6 +1651,68 @@ static struct soc_camera_host_ops pxa_so
 	.set_bus_param	= pxa_camera_set_bus_param,
 };
 
+static int pxa_camera_pdata_from_dt(struct device *dev,
+				    struct pxa_camera_dev *pcdev)
+{
+	u32 mclk_rate;
+	struct device_node *np = dev->of_node;
+	struct v4l2_of_endpoint ep;
+	int err = of_property_read_u32(np, "clock-frequency",
+				       &mclk_rate);
+	if (!err) {
+		pcdev->platform_flags |= PXA_CAMERA_MCLK_EN;
+		pcdev->mclk = mclk_rate;
+	}
+
+	np = of_graph_get_next_endpoint(np, NULL);
+	if (!np) {
+		dev_err(dev, "could not find endpoint\n");
+		return -EINVAL;
+	}
+
+	err = v4l2_of_parse_endpoint(np, &ep);
+	if (err) {
+		dev_err(dev, "could not parse endpoint\n");
+		goto out;
+	}
+
+	switch (ep.bus.parallel.bus_width) {
+	case 4:
+		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_4;
+		break;
+	case 5:
+		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_5;
+		break;
+	case 8:
+		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_8;
+		break;
+	case 9:
+		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_9;
+		break;
+	case 10:
+		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
+		break;
+	default:
+		break;
+	};
+
+	if (ep.bus.parallel.flags & V4L2_MBUS_MASTER)
+		pcdev->platform_flags |= PXA_CAMERA_MASTER;
+	if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+		pcdev->platform_flags |= PXA_CAMERA_HSP;
+	if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+		pcdev->platform_flags |= PXA_CAMERA_VSP;
+	if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		pcdev->platform_flags |= PXA_CAMERA_PCLK_EN | PXA_CAMERA_PCP;
+	if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+		pcdev->platform_flags |= PXA_CAMERA_PCLK_EN;
+
+out:
+	of_node_put(np);
+
+	return err;
+}
+
 static int pxa_camera_probe(struct platform_device *pdev)
 {
 	struct pxa_camera_dev *pcdev;
@@ -1676,7 +1739,15 @@ static int pxa_camera_probe(struct platf
 	pcdev->res = res;
 
 	pcdev->pdata = pdev->dev.platform_data;
-	pcdev->platform_flags = pcdev->pdata->flags;
+	if (&pdev->dev.of_node && !pcdev->pdata) {
+		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
+	} else {
+		pcdev->platform_flags = pcdev->pdata->flags;
+		pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
+	}
+	if (err < 0)
+		return err;
+
 	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
 			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
 		/*
@@ -1693,7 +1764,6 @@ static int pxa_camera_probe(struct platf
 		pcdev->width_flags |= 1 << 8;
 	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)
 		pcdev->width_flags |= 1 << 9;
-	pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
 	if (!pcdev->mclk) {
 		dev_warn(&pdev->dev,
 			 "mclk == 0! Please, fix your platform data. "
@@ -1799,10 +1869,17 @@ static const struct dev_pm_ops pxa_camer
 	.resume		= pxa_camera_resume,
 };
 
+static const struct of_device_id pxa_camera_of_match[] = {
+	{ .compatible = "marvell,pxa270-qci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pxa_camera_of_match);
+
 static struct platform_driver pxa_camera_driver = {
 	.driver		= {
 		.name	= PXA_CAM_DRV_NAME,
 		.pm	= &pxa_camera_pm,
+		.of_match_table = of_match_ptr(pxa_camera_of_match),
 	},
 	.probe		= pxa_camera_probe,
 	.remove		= pxa_camera_remove,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/rcar_vin.c linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/rcar_vin.c
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/rcar_vin.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/rcar_vin.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_data/camera-rcar.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -31,6 +33,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mediabus.h>
+#include <media/v4l2-of.h>
 #include <media/v4l2-subdev.h>
 #include <media/videobuf2-dma-contig.h>
 
@@ -126,13 +129,13 @@ struct rcar_vin_priv {
 	int				sequence;
 	/* State of the VIN module in capturing mode */
 	enum rcar_vin_state		state;
-	struct rcar_vin_platform_data	*pdata;
 	struct soc_camera_host		ici;
 	struct list_head		capture;
 #define MAX_BUFFER_NUM			3
 	struct vb2_buffer		*queue_buf[MAX_BUFFER_NUM];
 	struct vb2_alloc_ctx		*alloc_ctx;
 	enum v4l2_field			field;
+	unsigned int			pdata_flags;
 	unsigned int			vb_count;
 	unsigned int			nr_hw_slots;
 	bool				request_to_stop;
@@ -275,12 +278,12 @@ static int rcar_vin_setup(struct rcar_vi
 		break;
 	case V4L2_MBUS_FMT_YUYV8_2X8:
 		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
-		vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+		vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
 			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
 		break;
 	case V4L2_MBUS_FMT_YUYV10_2X10:
 		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
-		vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+		vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
 			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
 		break;
 	default:
@@ -797,7 +800,7 @@ static int rcar_vin_set_bus_param(struct
 	/* Make choises, based on platform preferences */
 	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
 	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
-		if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
+		if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
 			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
 			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
@@ -805,7 +808,7 @@ static int rcar_vin_set_bus_param(struct
 
 	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
 	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
-		if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
+		if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
 			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
 			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
@@ -1390,6 +1393,17 @@ static struct soc_camera_host_ops rcar_v
 	.init_videobuf2	= rcar_vin_init_videobuf2,
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id rcar_vin_of_table[] = {
+	{ .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
+	{ .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
+	{ .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
+	{ .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
+#endif
+
 static struct platform_device_id rcar_vin_id_table[] = {
 	{ "r8a7791-vin",  RCAR_GEN2 },
 	{ "r8a7790-vin",  RCAR_GEN2 },
@@ -1402,15 +1416,52 @@ MODULE_DEVICE_TABLE(platform, rcar_vin_i
 
 static int rcar_vin_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match = NULL;
 	struct rcar_vin_priv *priv;
 	struct resource *mem;
 	struct rcar_vin_platform_data *pdata;
+	unsigned int pdata_flags;
 	int irq, ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata || !pdata->flags) {
-		dev_err(&pdev->dev, "platform data not set\n");
-		return -EINVAL;
+	if (pdev->dev.of_node) {
+		struct v4l2_of_endpoint ep;
+		struct device_node *np;
+
+		match = of_match_device(of_match_ptr(rcar_vin_of_table),
+					&pdev->dev);
+
+		np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
+		if (!np) {
+			dev_err(&pdev->dev, "could not find endpoint\n");
+			return -EINVAL;
+		}
+
+		ret = v4l2_of_parse_endpoint(np, &ep);
+		if (ret) {
+			dev_err(&pdev->dev, "could not parse endpoint\n");
+			return ret;
+		}
+
+		if (ep.bus_type == V4L2_MBUS_BT656)
+			pdata_flags = RCAR_VIN_BT656;
+		else {
+			pdata_flags = 0;
+			if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+				pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
+			if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+				pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
+		}
+
+		of_node_put(np);
+
+		dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
+	} else {
+		pdata = pdev->dev.platform_data;
+		if (!pdata || !pdata->flags) {
+			dev_err(&pdev->dev, "platform data not set\n");
+			return -EINVAL;
+		}
+		pdata_flags = pdata->flags;
 	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1441,12 +1492,18 @@ static int rcar_vin_probe(struct platfor
 
 	priv->ici.priv = priv;
 	priv->ici.v4l2_dev.dev = &pdev->dev;
-	priv->ici.nr = pdev->id;
 	priv->ici.drv_name = dev_name(&pdev->dev);
 	priv->ici.ops = &rcar_vin_host_ops;
 
-	priv->pdata = pdata;
-	priv->chip = pdev->id_entry->driver_data;
+	priv->pdata_flags = pdata_flags;
+	if (!match) {
+		priv->ici.nr = pdev->id;
+		priv->chip = pdev->id_entry->driver_data;
+	} else {
+		priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
+		priv->chip = (enum chip_id)match->data;
+	};
+
 	spin_lock_init(&priv->lock);
 	INIT_LIST_HEAD(&priv->capture);
 
@@ -1487,6 +1544,7 @@ static struct platform_driver rcar_vin_d
 	.driver		= {
 		.name		= DRV_NAME,
 		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(rcar_vin_of_table),
 	},
 	.id_table	= rcar_vin_id_table,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/soc_camera/soc_camera.c linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/soc_camera.c
--- linux-libre-3.16-gnu/drivers/media/platform/soc_camera/soc_camera.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/soc_camera/soc_camera.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-of.h>
 #include <media/videobuf-core.h>
 #include <media/videobuf2-core.h>
 
@@ -1524,14 +1525,14 @@ static int scan_async_group(struct soc_c
 
 	ret = soc_camera_dyn_pdev(&sdesc, sasc);
 	if (ret < 0)
-		return ret;
+		goto eallocpdev;
 
 	sasc->sensor = &sasd->asd;
 
 	icd = soc_camera_add_pdev(sasc);
 	if (!icd) {
-		platform_device_put(sasc->pdev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto eaddpdev;
 	}
 
 	sasc->notifier.subdevs = asd;
@@ -1559,7 +1560,11 @@ static int scan_async_group(struct soc_c
 	v4l2_clk_unregister(icd->clk);
 eclkreg:
 	icd->clk = NULL;
-	platform_device_unregister(sasc->pdev);
+	platform_device_del(sasc->pdev);
+eaddpdev:
+	platform_device_put(sasc->pdev);
+eallocpdev:
+	devm_kfree(ici->v4l2_dev.dev, sasc);
 	dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
 
 	return ret;
@@ -1581,6 +1586,130 @@ static void scan_async_host(struct soc_c
 #define scan_async_host(ici)		do {} while (0)
 #endif
 
+#ifdef CONFIG_OF
+
+struct soc_of_info {
+	struct soc_camera_async_subdev	sasd;
+	struct soc_camera_async_client	sasc;
+	struct v4l2_async_subdev	*subdev;
+};
+
+static int soc_of_bind(struct soc_camera_host *ici,
+		       struct device_node *ep,
+		       struct device_node *remote)
+{
+	struct soc_camera_device *icd;
+	struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,};
+	struct soc_camera_async_client *sasc;
+	struct soc_of_info *info;
+	struct i2c_client *client;
+	char clk_name[V4L2_SUBDEV_NAME_SIZE];
+	int ret;
+
+	/* allocate a new subdev and add match info to it */
+	info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info),
+			    GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->sasd.asd.match.of.node = remote;
+	info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF;
+	info->subdev = &info->sasd.asd;
+
+	/* Or shall this be managed by the soc-camera device? */
+	sasc = &info->sasc;
+
+	/* HACK: just need a != NULL */
+	sdesc.host_desc.board_info = ERR_PTR(-ENODATA);
+
+	ret = soc_camera_dyn_pdev(&sdesc, sasc);
+	if (ret < 0)
+		goto eallocpdev;
+
+	sasc->sensor = &info->sasd.asd;
+
+	icd = soc_camera_add_pdev(sasc);
+	if (!icd) {
+		ret = -ENOMEM;
+		goto eaddpdev;
+	}
+
+	sasc->notifier.subdevs = &info->subdev;
+	sasc->notifier.num_subdevs = 1;
+	sasc->notifier.bound = soc_camera_async_bound;
+	sasc->notifier.unbind = soc_camera_async_unbind;
+	sasc->notifier.complete = soc_camera_async_complete;
+
+	icd->sasc = sasc;
+	icd->parent = ici->v4l2_dev.dev;
+
+	client = of_find_i2c_device_by_node(remote);
+
+	if (client)
+		snprintf(clk_name, sizeof(clk_name), "%d-%04x",
+			 client->adapter->nr, client->addr);
+	else
+		snprintf(clk_name, sizeof(clk_name), "of-%s",
+			 of_node_full_name(remote));
+
+	icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd);
+	if (IS_ERR(icd->clk)) {
+		ret = PTR_ERR(icd->clk);
+		goto eclkreg;
+	}
+
+	ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier);
+	if (!ret)
+		return 0;
+eclkreg:
+	icd->clk = NULL;
+	platform_device_del(sasc->pdev);
+eaddpdev:
+	platform_device_put(sasc->pdev);
+eallocpdev:
+	devm_kfree(ici->v4l2_dev.dev, sasc);
+	dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
+
+	return ret;
+}
+
+static void scan_of_host(struct soc_camera_host *ici)
+{
+	struct device *dev = ici->v4l2_dev.dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *epn = NULL, *ren;
+	unsigned int i;
+
+	for (i = 0; ; i++) {
+		epn = of_graph_get_next_endpoint(np, epn);
+		if (!epn)
+			break;
+
+		ren = of_graph_get_remote_port(epn);
+		if (!ren) {
+			dev_notice(dev, "no remote for %s\n",
+				   of_node_full_name(epn));
+			continue;
+		}
+
+		/* so we now have a remote node to connect */
+		if (!i)
+			soc_of_bind(ici, epn, ren->parent);
+
+		of_node_put(epn);
+		of_node_put(ren);
+
+		if (i) {
+			dev_err(dev, "multiple subdevices aren't supported yet!\n");
+			break;
+		}
+	}
+}
+
+#else
+static inline void scan_of_host(struct soc_camera_host *ici) { }
+#endif
+
 /* Called during host-driver probe */
 static int soc_camera_probe(struct soc_camera_host *ici,
 			    struct soc_camera_device *icd)
@@ -1832,7 +1961,9 @@ int soc_camera_host_register(struct soc_
 	mutex_init(&ici->host_lock);
 	mutex_init(&ici->clk_lock);
 
-	if (ici->asd_sizes)
+	if (ici->v4l2_dev.dev->of_node)
+		scan_of_host(ici);
+	else if (ici->asd_sizes)
 		/*
 		 * No OF, host with a list of subdevices. Don't try to mix
 		 * modes by initialising some groups statically and some
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vino.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vino.c
--- linux-libre-3.16-gnu/drivers/media/platform/vino.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vino.c	2014-09-28 17:29:07.000000000 -0400
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct f
 	pf->colorspace =
 		vino_data_formats[tempvcs.data_format].colorspace;
 
-	pf->priv = 0;
 	return 0;
 }
 
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct fil
 	pf->colorspace =
 		vino_data_formats[vcs->data_format].colorspace;
 
-	pf->priv = 0;
-
 	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 	return 0;
 }
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct fil
 	pf->colorspace =
 		vino_data_formats[vcs->data_format].colorspace;
 
-	pf->priv = 0;
-
 	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vivi.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vivi.c
--- linux-libre-3.16-gnu/drivers/media/platform/vivi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vivi.c	2014-09-28 17:29:07.000000000 -0400
@@ -648,13 +648,13 @@ static void vivi_fillbuff(struct vivi_de
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
 			dev->int32->cur.val,
-			dev->int64->cur.val64,
+			*dev->int64->p_cur.p_s64,
 			dev->bitmask->cur.val);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
 			dev->boolean->cur.val,
 			dev->menu->qmenu[dev->menu->cur.val],
-			dev->string->cur.string);
+			dev->string->p_cur.p_char);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 	snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
 			dev->int_menu->qmenu_int[dev->int_menu->cur.val],
@@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct
 		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	else
 		f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
-	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1236,7 +1235,7 @@ static const struct v4l2_ctrl_config viv
 	.id = VIVI_CID_CUSTOM_BASE + 2,
 	.name = "Integer 32 Bits",
 	.type = V4L2_CTRL_TYPE_INTEGER,
-	.min = 0x80000000,
+	.min = -0x80000000LL,
 	.max = 0x7fffffff,
 	.step = 1,
 };
@@ -1246,6 +1245,9 @@ static const struct v4l2_ctrl_config viv
 	.id = VIVI_CID_CUSTOM_BASE + 3,
 	.name = "Integer 64 Bits",
 	.type = V4L2_CTRL_TYPE_INTEGER64,
+	.min = LLONG_MIN,
+	.max = LLONG_MAX,
+	.step = 1,
 };
 
 static const char * const vivi_ctrl_menu_strings[] = {
@@ -1459,7 +1461,6 @@ static int __init vivi_create_instance(i
 	vfd->debug = debug;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->queue = q;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
 	/*
 	 * Provide a mutex to v4l2 core. It will be used to protect
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_bru.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_bru.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_bru.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_bru.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 
 #include "vsp1.h"
 #include "vsp1_bru.h"
+#include "vsp1_rwpf.h"
 
 #define BRU_MIN_SIZE				4U
 #define BRU_MAX_SIZE				8190U
@@ -37,19 +38,47 @@ static inline void vsp1_bru_write(struct
 }
 
 /* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
+ * Controls
  */
 
-static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input)
+static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	return media_entity_remote_pad(&bru->entity.pads[input]) != NULL;
+	struct vsp1_bru *bru =
+		container_of(ctrl->handler, struct vsp1_bru, ctrls);
+
+	if (!vsp1_entity_is_streaming(&bru->entity))
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BG_COLOR:
+		vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val |
+			       (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
+		break;
+	}
+
+	return 0;
 }
 
+static const struct v4l2_ctrl_ops bru_ctrl_ops = {
+	.s_ctrl = bru_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
 static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
 {
+	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
 	struct vsp1_bru *bru = to_bru(subdev);
 	struct v4l2_mbus_framefmt *format;
+	unsigned int flags;
 	unsigned int i;
+	int ret;
+
+	ret = vsp1_entity_set_streaming(&bru->entity, enable);
+	if (ret < 0)
+		return ret;
 
 	if (!enable)
 		return 0;
@@ -62,18 +91,19 @@ static int bru_s_stream(struct v4l2_subd
 	 * to sane default values for now.
 	 */
 
-	/* Disable both color data normalization and dithering. */
-	vsp1_bru_write(bru, VI6_BRU_INCTRL, 0);
-
-	/* Set the background position to cover the whole output image and
-	 * set its color to opaque black.
+	/* Disable dithering and enable color data normalization unless the
+	 * format at the pipeline output is premultiplied.
 	 */
+	flags = pipe->output ? pipe->output->video.format.flags : 0;
+	vsp1_bru_write(bru, VI6_BRU_INCTRL,
+		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
+		       0 : VI6_BRU_INCTRL_NRM);
+
+	/* Set the background position to cover the whole output image. */
 	vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE,
 		       (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
 		       (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
 	vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0);
-	vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL,
-		       0xff << VI6_BRU_VIRRPF_COL_A_SHIFT);
 
 	/* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
 	 * unit with a NOP operation to make BRU input 1 available as the
@@ -84,6 +114,7 @@ static int bru_s_stream(struct v4l2_subd
 		       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
 
 	for (i = 0; i < 4; ++i) {
+		bool premultiplied = false;
 		u32 ctrl = 0;
 
 		/* Configure all Blend/ROP units corresponding to an enabled BRU
@@ -91,11 +122,15 @@ static int bru_s_stream(struct v4l2_subd
 		 * disabled BRU inputs are used in ROP NOP mode to ignore the
 		 * SRC input.
 		 */
-		if (bru_is_input_enabled(bru, i))
+		if (bru->inputs[i].rpf) {
 			ctrl |= VI6_BRU_CTRL_RBC;
-		else
+
+			premultiplied = bru->inputs[i].rpf->video.format.flags
+				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
+		} else {
 			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
 			     |  VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
+		}
 
 		/* Select the virtual RPF as the Blend/ROP unit A DST input to
 		 * serve as a background color.
@@ -117,10 +152,18 @@ static int bru_s_stream(struct v4l2_subd
 		 *
 		 *	DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
 		 *	DSTa = DSTa * (1 - SRCa) + SRCa
+		 *
+		 * when the SRC input isn't premultiplied, and to
+		 *
+		 *	DSTc = DSTc * (1 - SRCa) + SRCc
+		 *	DSTa = DSTa * (1 - SRCa) + SRCa
+		 *
+		 * otherwise.
 		 */
 		vsp1_bru_write(bru, VI6_BRU_BLD(i),
 			       VI6_BRU_BLD_CCMDX_255_SRC_A |
-			       VI6_BRU_BLD_CCMDY_SRC_A |
+			       (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
+						VI6_BRU_BLD_CCMDY_SRC_A) |
 			       VI6_BRU_BLD_ACMDX_255_SRC_A |
 			       VI6_BRU_BLD_ACMDY_COEFY |
 			       (0xff << VI6_BRU_BLD_COEFY_SHIFT));
@@ -192,7 +235,7 @@ static struct v4l2_rect *bru_get_compose
 	case V4L2_SUBDEV_FORMAT_TRY:
 		return v4l2_subdev_get_try_crop(fh, pad);
 	case V4L2_SUBDEV_FORMAT_ACTIVE:
-		return &bru->compose[pad];
+		return &bru->inputs[pad].compose;
 	default:
 		return NULL;
 	}
@@ -391,5 +434,19 @@ struct vsp1_bru *vsp1_bru_create(struct
 
 	vsp1_entity_init_formats(subdev, NULL);
 
+	/* Initialize the control handler. */
+	v4l2_ctrl_handler_init(&bru->ctrls, 1);
+	v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+			  0, 0xffffff, 1, 0);
+
+	bru->entity.subdev.ctrl_handler = &bru->ctrls;
+
+	if (bru->ctrls.error) {
+		dev_err(vsp1->dev, "bru: failed to initialize controls\n");
+		ret = bru->ctrls.error;
+		vsp1_entity_destroy(&bru->entity);
+		return ERR_PTR(ret);
+	}
+
 	return bru;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_bru.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_bru.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_bru.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_bru.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,11 +14,13 @@
 #define __VSP1_BRU_H__
 
 #include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
 
 #include "vsp1_entity.h"
 
 struct vsp1_device;
+struct vsp1_rwpf;
 
 #define BRU_PAD_SINK(n)				(n)
 #define BRU_PAD_SOURCE				4
@@ -26,7 +28,12 @@ struct vsp1_device;
 struct vsp1_bru {
 	struct vsp1_entity entity;
 
-	struct v4l2_rect compose[4];
+	struct v4l2_ctrl_handler ctrls;
+
+	struct {
+		struct vsp1_rwpf *rpf;
+		struct v4l2_rect compose;
+	} inputs[4];
 };
 
 static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_drv.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_drv.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -345,36 +345,32 @@ static int vsp1_device_init(struct vsp1_
  * Increment the VSP1 reference count and initialize the device if the first
  * reference is taken.
  *
- * Return a pointer to the VSP1 device or NULL if an error occurred.
+ * Return 0 on success or a negative error code otherwise.
  */
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
+int vsp1_device_get(struct vsp1_device *vsp1)
 {
-	struct vsp1_device *__vsp1 = vsp1;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&vsp1->lock);
 	if (vsp1->ref_count > 0)
 		goto done;
 
 	ret = clk_prepare_enable(vsp1->clock);
-	if (ret < 0) {
-		__vsp1 = NULL;
+	if (ret < 0)
 		goto done;
-	}
 
 	ret = vsp1_device_init(vsp1);
 	if (ret < 0) {
 		clk_disable_unprepare(vsp1->clock);
-		__vsp1 = NULL;
 		goto done;
 	}
 
 done:
-	if (__vsp1)
+	if (!ret)
 		vsp1->ref_count++;
 
 	mutex_unlock(&vsp1->lock);
-	return __vsp1;
+	return ret;
 }
 
 /*
@@ -440,19 +436,19 @@ static int vsp1_validate_platform_data(s
 		return -EINVAL;
 	}
 
-	if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) {
+	if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) {
 		dev_err(&pdev->dev, "invalid number of RPF (%u)\n",
 			pdata->rpf_count);
 		return -EINVAL;
 	}
 
-	if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) {
+	if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) {
 		dev_err(&pdev->dev, "invalid number of UDS (%u)\n",
 			pdata->uds_count);
 		return -EINVAL;
 	}
 
-	if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) {
+	if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) {
 		dev_err(&pdev->dev, "invalid number of WPF (%u)\n",
 			pdata->wpf_count);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_entity.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_entity.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_entity.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_entity.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,42 @@
 
 #include "vsp1.h"
 #include "vsp1_entity.h"
+#include "vsp1_video.h"
+
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity)
+{
+	bool streaming;
+
+	mutex_lock(&entity->lock);
+	streaming = entity->streaming;
+	mutex_unlock(&entity->lock);
+
+	return streaming;
+}
+
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
+{
+	int ret;
+
+	mutex_lock(&entity->lock);
+	entity->streaming = streaming;
+	mutex_unlock(&entity->lock);
+
+	if (!streaming)
+		return 0;
+
+	if (!entity->subdev.ctrl_handler)
+		return 0;
+
+	ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
+	if (ret < 0) {
+		mutex_lock(&entity->lock);
+		entity->streaming = false;
+		mutex_unlock(&entity->lock);
+	}
+
+	return ret;
+}
 
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Operations
@@ -157,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device
 	if (i == ARRAY_SIZE(vsp1_routes))
 		return -EINVAL;
 
+	mutex_init(&entity->lock);
+
 	entity->vsp1 = vsp1;
 	entity->source_pad = num_pads - 1;
 
@@ -185,7 +223,11 @@ int vsp1_entity_init(struct vsp1_device
 
 void vsp1_entity_destroy(struct vsp1_entity *entity)
 {
+	if (entity->video)
+		vsp1_video_cleanup(entity->video);
 	if (entity->subdev.ctrl_handler)
 		v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
 	media_entity_cleanup(&entity->subdev.entity);
+
+	mutex_destroy(&entity->lock);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_entity.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_entity.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_entity.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_entity.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,10 +14,12 @@
 #define __VSP1_ENTITY_H__
 
 #include <linux/list.h>
+#include <linux/mutex.h>
 
 #include <media/v4l2-subdev.h>
 
 struct vsp1_device;
+struct vsp1_video;
 
 enum vsp1_entity_type {
 	VSP1_ENTITY_BRU,
@@ -68,6 +70,11 @@ struct vsp1_entity {
 
 	struct v4l2_subdev subdev;
 	struct v4l2_mbus_framefmt *formats;
+
+	struct vsp1_video *video;
+
+	struct mutex lock;		/* Protects the streaming field */
+	bool streaming;
 };
 
 static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
@@ -89,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_e
 void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_fh *fh);
 
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity);
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming);
+
 #endif /* __VSP1_ENTITY_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,9 +36,9 @@ struct vsp1_rwpf;
 struct vsp1_sru;
 struct vsp1_uds;
 
-#define VPS1_MAX_RPF		5
-#define VPS1_MAX_UDS		3
-#define VPS1_MAX_WPF		4
+#define VSP1_MAX_RPF		5
+#define VSP1_MAX_UDS		3
+#define VSP1_MAX_WPF		4
 
 struct vsp1_device {
 	struct device *dev;
@@ -55,10 +55,10 @@ struct vsp1_device {
 	struct vsp1_hsit *hst;
 	struct vsp1_lif *lif;
 	struct vsp1_lut *lut;
-	struct vsp1_rwpf *rpf[VPS1_MAX_RPF];
+	struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
 	struct vsp1_sru *sru;
-	struct vsp1_uds *uds[VPS1_MAX_UDS];
-	struct vsp1_rwpf *wpf[VPS1_MAX_WPF];
+	struct vsp1_uds *uds[VSP1_MAX_UDS];
+	struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
 
 	struct list_head entities;
 
@@ -66,7 +66,7 @@ struct vsp1_device {
 	struct media_device media_dev;
 };
 
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1);
+int vsp1_device_get(struct vsp1_device *vsp1);
 void vsp1_device_put(struct vsp1_device *vsp1);
 
 static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_regs.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_regs.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -336,7 +336,9 @@
  */
 
 #define VI6_SRU_CTRL0			0x2200
+#define VI6_SRU_CTRL0_PARAM0_MASK	(0x1ff << 16)
 #define VI6_SRU_CTRL0_PARAM0_SHIFT	16
+#define VI6_SRU_CTRL0_PARAM1_MASK	(0x1f << 8)
 #define VI6_SRU_CTRL0_PARAM1_SHIFT	8
 #define VI6_SRU_CTRL0_MODE_UPSCALE	(4 << 4)
 #define VI6_SRU_CTRL0_PARAM2		(1 << 3)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_rpf.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_rpf.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_rpf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_rpf.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,36 @@ static inline void vsp1_rpf_write(struct
 }
 
 /* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int rpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vsp1_rwpf *rpf =
+		container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+	struct vsp1_pipeline *pipe;
+
+	if (!vsp1_entity_is_streaming(&rpf->entity))
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_ALPHA_COMPONENT:
+		vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
+			       ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+
+		pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity);
+		vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
+	.s_ctrl = rpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
  * V4L2 Subdevice Core Operations
  */
 
@@ -50,6 +80,11 @@ static int rpf_s_stream(struct v4l2_subd
 	const struct v4l2_rect *crop = &rpf->crop;
 	u32 pstride;
 	u32 infmt;
+	int ret;
+
+	ret = vsp1_entity_set_streaming(&rpf->entity, enable);
+	if (ret < 0)
+		return ret;
 
 	if (!enable)
 		return 0;
@@ -101,12 +136,13 @@ static int rpf_s_stream(struct v4l2_subd
 		       (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) |
 		       (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT));
 
-	/* Disable alpha, mask and color key. Set the alpha channel to a fixed
-	 * value of 255.
+	/* Use the alpha channel (extended to 8 bits) when available or an
+	 * alpha value set through the V4L2_CID_ALPHA_COMPONENT control
+	 * otherwise. Disable color keying.
 	 */
-	vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED);
-	vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
-		       255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+	vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
+		       (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
+				       : VI6_RPF_ALPH_SEL_ASEL_FIXED));
 	vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);
 	vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0);
 
@@ -196,6 +232,20 @@ struct vsp1_rwpf *vsp1_rpf_create(struct
 
 	vsp1_entity_init_formats(subdev, NULL);
 
+	/* Initialize the control handler. */
+	v4l2_ctrl_handler_init(&rpf->ctrls, 1);
+	v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+			  0, 255, 1, 255);
+
+	rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
+
+	if (rpf->ctrls.error) {
+		dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
+			index);
+		ret = rpf->ctrls.error;
+		goto error;
+	}
+
 	/* Initialize the video device. */
 	video = &rpf->video;
 
@@ -205,7 +255,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct
 
 	ret = vsp1_video_init(video, &rpf->entity);
 	if (ret < 0)
-		goto error_video;
+		goto error;
+
+	rpf->entity.video = video;
 
 	/* Connect the video device to the RPF. */
 	ret = media_entity_create_link(&rpf->video.video.entity, 0,
@@ -214,13 +266,11 @@ struct vsp1_rwpf *vsp1_rpf_create(struct
 				       MEDIA_LNK_FL_ENABLED |
 				       MEDIA_LNK_FL_IMMUTABLE);
 	if (ret < 0)
-		goto error_link;
+		goto error;
 
 	return rpf;
 
-error_link:
-	vsp1_video_cleanup(video);
-error_video:
-	media_entity_cleanup(&rpf->entity.subdev.entity);
+error:
+	vsp1_entity_destroy(&rpf->entity);
 	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_rwpf.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_rwpf.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_rwpf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_rwpf.h	2014-09-28 17:29:07.000000000 -0400
@@ -14,6 +14,7 @@
 #define __VSP1_RWPF_H__
 
 #include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
@@ -26,6 +27,7 @@
 struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct vsp1_video video;
+	struct v4l2_ctrl_handler ctrls;
 
 	unsigned int max_width;
 	unsigned int max_height;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_sru.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_sru.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_sru.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_sru.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,38 +42,6 @@ static inline void vsp1_sru_write(struct
 
 #define V4L2_CID_VSP1_SRU_INTENSITY		(V4L2_CID_USER_BASE + 1)
 
-static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct vsp1_sru *sru =
-		container_of(ctrl->handler, struct vsp1_sru, ctrls);
-
-	switch (ctrl->id) {
-	case V4L2_CID_VSP1_SRU_INTENSITY:
-		sru->intensity = ctrl->val;
-		break;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_ctrl_ops sru_ctrl_ops = {
-	.s_ctrl = sru_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config sru_intensity_control = {
-	.ops = &sru_ctrl_ops,
-	.id = V4L2_CID_VSP1_SRU_INTENSITY,
-	.name = "Intensity",
-	.type = V4L2_CTRL_TYPE_INTEGER,
-	.min = 1,
-	.max = 6,
-	.step = 1,
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
- */
-
 struct vsp1_sru_param {
 	u32 ctrl0;
 	u32 ctrl2;
@@ -110,22 +78,66 @@ static const struct vsp1_sru_param vsp1_
 	},
 };
 
+static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vsp1_sru *sru =
+		container_of(ctrl->handler, struct vsp1_sru, ctrls);
+	const struct vsp1_sru_param *param;
+	u32 value;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VSP1_SRU_INTENSITY:
+		param = &vsp1_sru_params[ctrl->val - 1];
+
+		value = vsp1_sru_read(sru, VI6_SRU_CTRL0);
+		value &= ~(VI6_SRU_CTRL0_PARAM0_MASK |
+			   VI6_SRU_CTRL0_PARAM1_MASK);
+		value |= param->ctrl0;
+		vsp1_sru_write(sru, VI6_SRU_CTRL0, value);
+
+		vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops sru_ctrl_ops = {
+	.s_ctrl = sru_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config sru_intensity_control = {
+	.ops = &sru_ctrl_ops,
+	.id = V4L2_CID_VSP1_SRU_INTENSITY,
+	.name = "Intensity",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 1,
+	.max = 6,
+	.def = 1,
+	.step = 1,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
 static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
 {
 	struct vsp1_sru *sru = to_sru(subdev);
-	const struct vsp1_sru_param *param;
 	struct v4l2_mbus_framefmt *input;
 	struct v4l2_mbus_framefmt *output;
-	bool upscale;
 	u32 ctrl0;
+	int ret;
+
+	ret = vsp1_entity_set_streaming(&sru->entity, enable);
+	if (ret < 0)
+		return ret;
 
 	if (!enable)
 		return 0;
 
 	input = &sru->entity.formats[SRU_PAD_SINK];
 	output = &sru->entity.formats[SRU_PAD_SOURCE];
-	upscale = input->width != output->width;
-	param = &vsp1_sru_params[sru->intensity];
 
 	if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32)
 		ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
@@ -133,10 +145,18 @@ static int sru_s_stream(struct v4l2_subd
 	else
 		ctrl0 = VI6_SRU_CTRL0_PARAM3;
 
-	vsp1_sru_write(sru, VI6_SRU_CTRL0, param->ctrl0 | ctrl0 |
-		       (upscale ? VI6_SRU_CTRL0_MODE_UPSCALE : 0));
+	if (input->width != output->width)
+		ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE;
+
+	/* Take the control handler lock to ensure that the CTRL0 value won't be
+	 * changed behind our back by a set control operation.
+	 */
+	mutex_lock(sru->ctrls.lock);
+	ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
+	       & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
+	mutex_unlock(sru->ctrls.lock);
+
 	vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
-	vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
 
 	return 0;
 }
@@ -348,8 +368,15 @@ struct vsp1_sru *vsp1_sru_create(struct
 	/* Initialize the control handler. */
 	v4l2_ctrl_handler_init(&sru->ctrls, 1);
 	v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL);
-	v4l2_ctrl_handler_setup(&sru->ctrls);
+
 	sru->entity.subdev.ctrl_handler = &sru->ctrls;
 
+	if (sru->ctrls.error) {
+		dev_err(vsp1->dev, "sru: failed to initialize controls\n");
+		ret = sru->ctrls.error;
+		vsp1_entity_destroy(&sru->entity);
+		return ERR_PTR(ret);
+	}
+
 	return sru;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_sru.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_sru.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_sru.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_sru.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,6 @@ struct vsp1_sru {
 	struct vsp1_entity entity;
 
 	struct v4l2_ctrl_handler ctrls;
-	unsigned int intensity;
 };
 
 static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_uds.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_uds.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_uds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_uds.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,6 +45,11 @@ static inline void vsp1_uds_write(struct
  * Scaling Computation
  */
 
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha)
+{
+	vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
+}
+
 /*
  * uds_output_size - Return the output size for an input size and scaling ratio
  * @input: input size in pixels
@@ -105,49 +110,56 @@ static unsigned int uds_compute_ratio(un
 	return (input - 1) * 4096 / (output - 1);
 }
 
-static void uds_compute_ratios(struct vsp1_uds *uds)
-{
-	struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK];
-	struct v4l2_mbus_framefmt *output =
-		&uds->entity.formats[UDS_PAD_SOURCE];
-
-	uds->hscale = uds_compute_ratio(input->width, output->width);
-	uds->vscale = uds_compute_ratio(input->height, output->height);
-
-	dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n",
-		uds->hscale, uds->vscale);
-}
-
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Core Operations
  */
 
 static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
 {
-	const struct v4l2_mbus_framefmt *format;
 	struct vsp1_uds *uds = to_uds(subdev);
+	const struct v4l2_mbus_framefmt *output;
+	const struct v4l2_mbus_framefmt *input;
+	unsigned int hscale;
+	unsigned int vscale;
+	bool multitap;
 
 	if (!enable)
 		return 0;
 
-	/* Enable multi-tap scaling. */
-	vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_AON | VI6_UDS_CTRL_BC);
+	input = &uds->entity.formats[UDS_PAD_SINK];
+	output = &uds->entity.formats[UDS_PAD_SOURCE];
+
+	hscale = uds_compute_ratio(input->width, output->width);
+	vscale = uds_compute_ratio(input->height, output->height);
+
+	dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
+
+	/* Multi-tap scaling can't be enabled along with alpha scaling when
+	 * scaling down with a factor lower than or equal to 1/2 in either
+	 * direction.
+	 */
+	if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
+		multitap = false;
+	else
+		multitap = true;
+
+	vsp1_uds_write(uds, VI6_UDS_CTRL,
+		       (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
+		       (multitap ? VI6_UDS_CTRL_BC : 0));
 
 	vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
-		       (uds_passband_width(uds->hscale)
+		       (uds_passband_width(hscale)
 				<< VI6_UDS_PASS_BWIDTH_H_SHIFT) |
-		       (uds_passband_width(uds->vscale)
+		       (uds_passband_width(vscale)
 				<< VI6_UDS_PASS_BWIDTH_V_SHIFT));
 
 	/* Set the scaling ratios and the output size. */
-	format = &uds->entity.formats[UDS_PAD_SOURCE];
-
 	vsp1_uds_write(uds, VI6_UDS_SCALE,
-		       (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
-		       (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
+		       (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
+		       (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
 	vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
-		       (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
-		       (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
+		       (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
+		       (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
 
 	return 0;
 }
@@ -280,9 +292,6 @@ static int uds_set_format(struct v4l2_su
 		uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which);
 	}
 
-	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-		uds_compute_ratios(uds);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_uds.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_uds.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_uds.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_uds.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,9 +25,7 @@ struct vsp1_device;
 
 struct vsp1_uds {
 	struct vsp1_entity entity;
-
-	unsigned int hscale;
-	unsigned int vscale;
+	bool scale_alpha;
 };
 
 static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
@@ -37,4 +35,6 @@ static inline struct vsp1_uds *to_uds(st
 
 struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index);
 
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha);
+
 #endif /* __VSP1_UDS_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_video.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_video.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_video.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@
 #include "vsp1_bru.h"
 #include "vsp1_entity.h"
 #include "vsp1_rwpf.h"
+#include "vsp1_uds.h"
 #include "vsp1_video.h"
 
 #define VSP1_VIDEO_DEF_FORMAT		V4L2_PIX_FMT_YUYV
@@ -50,70 +51,85 @@ static const struct vsp1_format_info vsp
 	{ V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 8, 0, 0 }, false, false, 1, 1 },
-	{ V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  1, { 8, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1 },
-	{ V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1 },
+	  1, { 16, 0, 0 }, false, false, 1, 1, false },
 	{ V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1 },
+	  1, { 16, 0, 0 }, false, false, 1, 1, false },
 	{ V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_BGR_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 },
+	  1, { 24, 0, 0 }, false, false, 1, 1, false },
 	{ V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_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 },
-	{ V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  1, { 24, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
-	  1, { 32, 0, 0 }, false, false, 1, 1 },
-	{ V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  1, { 32, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_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 },
+	  1, { 32, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_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, V4L2_MBUS_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,
-	  1, { 16, 0, 0 }, false, false, 2, 1 },
+	  1, { 16, 0, 0 }, false, false, 2, 1, false },
 	{ V4L2_PIX_FMT_VYUY, V4L2_MBUS_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,
-	  1, { 16, 0, 0 }, false, true, 2, 1 },
+	  1, { 16, 0, 0 }, false, true, 2, 1, false },
 	{ V4L2_PIX_FMT_YUYV, V4L2_MBUS_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,
-	  1, { 16, 0, 0 }, true, false, 2, 1 },
+	  1, { 16, 0, 0 }, true, false, 2, 1, false },
 	{ V4L2_PIX_FMT_YVYU, V4L2_MBUS_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,
-	  1, { 16, 0, 0 }, true, true, 2, 1 },
+	  1, { 16, 0, 0 }, true, true, 2, 1, false },
 	{ V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, false, 2, 2 },
+	  2, { 8, 16, 0 }, false, false, 2, 2, false },
 	{ V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, true, 2, 2 },
+	  2, { 8, 16, 0 }, false, true, 2, 2, false },
 	{ V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, false, 2, 1 },
+	  2, { 8, 16, 0 }, false, false, 2, 1, false },
 	{ V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, true, 2, 1 },
+	  2, { 8, 16, 0 }, false, true, 2, 1, false },
 	{ V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  3, { 8, 8, 8 }, false, false, 2, 2 },
+	  3, { 8, 8, 8 }, false, false, 2, 2, false },
 };
 
 /*
@@ -181,11 +197,29 @@ static int __vsp1_video_try_format(struc
 				   struct v4l2_pix_format_mplane *pix,
 				   const struct vsp1_format_info **fmtinfo)
 {
+	static const u32 xrgb_formats[][2] = {
+		{ V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_XRGB444 },
+		{ V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_XRGB555 },
+		{ V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_XBGR32 },
+		{ V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_XRGB32 },
+	};
+
 	const struct vsp1_format_info *info;
 	unsigned int width = pix->width;
 	unsigned int height = pix->height;
 	unsigned int i;
 
+	/* Backward compatibility: replace deprecated RGB formats by their XRGB
+	 * equivalent. This selects the format older userspace applications want
+	 * while still exposing the new format.
+	 */
+	for (i = 0; i < ARRAY_SIZE(xrgb_formats); ++i) {
+		if (xrgb_formats[i][0] == pix->pixelformat) {
+			pix->pixelformat = xrgb_formats[i][1];
+			break;
+		}
+	}
+
 	/* Retrieve format information and select the default format if the
 	 * requested format isn't supported.
 	 */
@@ -273,13 +307,14 @@ vsp1_video_format_adjust(struct vsp1_vid
  * Pipeline Management
  */
 
-static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
+static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
+					 struct vsp1_rwpf *input,
 					 struct vsp1_rwpf *output)
 {
 	struct vsp1_entity *entity;
 	unsigned int entities = 0;
 	struct media_pad *pad;
-	bool uds_found = false;
+	bool bru_found = false;
 
 	input->location.left = 0;
 	input->location.top = 0;
@@ -301,10 +336,15 @@ static int vsp1_pipeline_validate_branch
 		 */
 		if (entity->type == VSP1_ENTITY_BRU) {
 			struct vsp1_bru *bru = to_bru(&entity->subdev);
-			struct v4l2_rect *rect = &bru->compose[pad->index];
+			struct v4l2_rect *rect =
+				&bru->inputs[pad->index].compose;
+
+			bru->inputs[pad->index].rpf = input;
 
 			input->location.left = rect->left;
 			input->location.top = rect->top;
+
+			bru_found = true;
 		}
 
 		/* We've reached the WPF, we're done. */
@@ -319,9 +359,12 @@ static int vsp1_pipeline_validate_branch
 
 		/* UDS can't be chained. */
 		if (entity->type == VSP1_ENTITY_UDS) {
-			if (uds_found)
+			if (pipe->uds)
 				return -EPIPE;
-			uds_found = true;
+
+			pipe->uds = entity;
+			pipe->uds_input = bru_found ? pipe->bru
+					: &input->entity;
 		}
 
 		/* Follow the source link. The link setup operations ensure
@@ -340,6 +383,27 @@ static int vsp1_pipeline_validate_branch
 	return 0;
 }
 
+static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
+{
+	if (pipe->bru) {
+		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+		unsigned int i;
+
+		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
+			bru->inputs[i].rpf = NULL;
+	}
+
+	INIT_LIST_HEAD(&pipe->entities);
+	pipe->state = VSP1_PIPELINE_STOPPED;
+	pipe->buffers_ready = 0;
+	pipe->num_video = 0;
+	pipe->num_inputs = 0;
+	pipe->output = NULL;
+	pipe->bru = NULL;
+	pipe->lif = NULL;
+	pipe->uds = NULL;
+}
+
 static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 				  struct vsp1_video *video)
 {
@@ -395,7 +459,7 @@ static int vsp1_pipeline_validate(struct
 	 * contains no loop and that all branches end at the output WPF.
 	 */
 	for (i = 0; i < pipe->num_inputs; ++i) {
-		ret = vsp1_pipeline_validate_branch(pipe->inputs[i],
+		ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i],
 						    pipe->output);
 		if (ret < 0)
 			goto error;
@@ -404,13 +468,7 @@ static int vsp1_pipeline_validate(struct
 	return 0;
 
 error:
-	INIT_LIST_HEAD(&pipe->entities);
-	pipe->buffers_ready = 0;
-	pipe->num_video = 0;
-	pipe->num_inputs = 0;
-	pipe->output = NULL;
-	pipe->bru = NULL;
-	pipe->lif = NULL;
+	__vsp1_pipeline_cleanup(pipe);
 	return ret;
 }
 
@@ -441,16 +499,8 @@ static void vsp1_pipeline_cleanup(struct
 	mutex_lock(&pipe->lock);
 
 	/* If we're the last user clean up the pipeline. */
-	if (--pipe->use_count == 0) {
-		INIT_LIST_HEAD(&pipe->entities);
-		pipe->state = VSP1_PIPELINE_STOPPED;
-		pipe->buffers_ready = 0;
-		pipe->num_video = 0;
-		pipe->num_inputs = 0;
-		pipe->output = NULL;
-		pipe->bru = NULL;
-		pipe->lif = NULL;
-	}
+	if (--pipe->use_count == 0)
+		__vsp1_pipeline_cleanup(pipe);
 
 	mutex_unlock(&pipe->lock);
 }
@@ -471,7 +521,8 @@ static int vsp1_pipeline_stop(struct vsp
 	int ret;
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
-	pipe->state = VSP1_PIPELINE_STOPPING;
+	if (pipe->state == VSP1_PIPELINE_RUNNING)
+		pipe->state = VSP1_PIPELINE_STOPPING;
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 
 	ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED,
@@ -479,7 +530,7 @@ static int vsp1_pipeline_stop(struct vsp
 	ret = ret == 0 ? -ETIMEDOUT : 0;
 
 	list_for_each_entry(entity, &pipe->entities, list_pipe) {
-		if (entity->route)
+		if (entity->route && entity->route->reg)
 			vsp1_write(entity->vsp1, entity->route->reg,
 				   VI6_DPR_NODE_UNUSED);
 
@@ -576,6 +627,7 @@ static void vsp1_video_frame_end(struct
 
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
+	enum vsp1_pipeline_state state;
 	unsigned long flags;
 	unsigned int i;
 
@@ -591,11 +643,13 @@ void vsp1_pipeline_frame_end(struct vsp1
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
+	state = pipe->state;
+	pipe->state = VSP1_PIPELINE_STOPPED;
+
 	/* If a stop has been requested, mark the pipeline as stopped and
 	 * return.
 	 */
-	if (pipe->state == VSP1_PIPELINE_STOPPING) {
-		pipe->state = VSP1_PIPELINE_STOPPED;
+	if (state == VSP1_PIPELINE_STOPPING) {
 		wake_up(&pipe->wq);
 		goto done;
 	}
@@ -608,6 +662,47 @@ done:
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 }
 
+/*
+ * Propagate the alpha value through the pipeline.
+ *
+ * As the UDS has restricted scaling capabilities when the alpha component needs
+ * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
+ * value. The UDS then outputs a fixed alpha value which needs to be programmed
+ * from the input RPF alpha.
+ */
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+				   struct vsp1_entity *input,
+				   unsigned int alpha)
+{
+	struct vsp1_entity *entity;
+	struct media_pad *pad;
+
+	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
+
+	while (pad) {
+		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
+
+		/* The BRU background color has a fixed alpha value set to 255,
+		 * the output alpha value is thus always equal to 255.
+		 */
+		if (entity->type == VSP1_ENTITY_BRU)
+			alpha = 255;
+
+		if (entity->type == VSP1_ENTITY_UDS) {
+			struct vsp1_uds *uds = to_uds(&entity->subdev);
+
+			vsp1_uds_set_alpha(uds, alpha);
+			break;
+		}
+
+		pad = &entity->pads[entity->source_pad];
+		pad = media_entity_remote_pad(pad);
+	}
+}
+
 /* -----------------------------------------------------------------------------
  * videobuf2 Queue Operations
  */
@@ -654,8 +749,6 @@ static int vsp1_video_buffer_prepare(str
 	if (vb->num_planes < format->num_planes)
 		return -EINVAL;
 
-	buf->video = video;
-
 	for (i = 0; i < vb->num_planes; ++i) {
 		buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
 		buf->length[i] = vb2_plane_size(vb, i);
@@ -717,6 +810,25 @@ static int vsp1_video_start_streaming(st
 
 	mutex_lock(&pipe->lock);
 	if (pipe->stream_count == pipe->num_video - 1) {
+		if (pipe->uds) {
+			struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
+
+			/* If a BRU is present in the pipeline before the UDS,
+			 * the alpha component doesn't need to be scaled as the
+			 * BRU output alpha value is fixed to 255. Otherwise we
+			 * need to scale the alpha component only when available
+			 * at the input RPF.
+			 */
+			if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
+				uds->scale_alpha = false;
+			} else {
+				struct vsp1_rwpf *rpf =
+					to_rwpf(&pipe->uds_input->subdev);
+
+				uds->scale_alpha = rpf->video.fmtinfo->alpha;
+			}
+		}
+
 		list_for_each_entry(entity, &pipe->entities, list_pipe) {
 			vsp1_entity_route_setup(entity);
 
@@ -744,6 +856,7 @@ static void vsp1_video_stop_streaming(st
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
 	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
+	struct vsp1_video_buffer *buffer;
 	unsigned long flags;
 	int ret;
 
@@ -761,6 +874,8 @@ static void vsp1_video_stop_streaming(st
 
 	/* Remove all buffers from the IRQ queue. */
 	spin_lock_irqsave(&video->irqlock, flags);
+	list_for_each_entry(buffer, &video->irqqueue, queue)
+		vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR);
 	INIT_LIST_HEAD(&video->irqqueue);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 }
@@ -950,8 +1065,8 @@ static int vsp1_video_open(struct file *
 
 	file->private_data = vfh;
 
-	if (!vsp1_device_get(video->vsp1)) {
-		ret = -EBUSY;
+	ret = vsp1_device_get(video->vsp1);
+	if (ret < 0) {
 		v4l2_fh_del(vfh);
 		kfree(vfh);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_video.h linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_video.h
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_video.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_video.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@ struct vsp1_video;
  * @swap_uv: the U and V components are swapped (V comes before U)
  * @hsub: horizontal subsampling factor
  * @vsub: vertical subsampling factor
+ * @alpha: has an alpha channel
  */
 struct vsp1_format_info {
 	u32 fourcc;
@@ -45,6 +46,7 @@ struct vsp1_format_info {
 	bool swap_uv;
 	unsigned int hsub;
 	unsigned int vsub;
+	bool alpha;
 };
 
 enum vsp1_pipeline_state {
@@ -73,10 +75,12 @@ struct vsp1_pipeline {
 
 	unsigned int num_video;
 	unsigned int num_inputs;
-	struct vsp1_rwpf *inputs[VPS1_MAX_RPF];
+	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
 	struct vsp1_rwpf *output;
 	struct vsp1_entity *bru;
 	struct vsp1_entity *lif;
+	struct vsp1_entity *uds;
+	struct vsp1_entity *uds_input;
 
 	struct list_head entities;
 };
@@ -90,7 +94,6 @@ static inline struct vsp1_pipeline *to_v
 }
 
 struct vsp1_video_buffer {
-	struct vsp1_video *video;
 	struct vb2_buffer buf;
 	struct list_head queue;
 
@@ -142,4 +145,8 @@ void vsp1_video_cleanup(struct vsp1_vide
 
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
 
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+				   struct vsp1_entity *input,
+				   unsigned int alpha);
+
 #endif /* __VSP1_VIDEO_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_wpf.c linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_wpf.c
--- linux-libre-3.16-gnu/drivers/media/platform/vsp1/vsp1_wpf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/platform/vsp1/vsp1_wpf.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,22 +39,56 @@ static inline void vsp1_wpf_write(struct
 }
 
 /* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int wpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vsp1_rwpf *wpf =
+		container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+	u32 value;
+
+	if (!vsp1_entity_is_streaming(&wpf->entity))
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_ALPHA_COMPONENT:
+		value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT);
+		value &= ~VI6_WPF_OUTFMT_PDV_MASK;
+		value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT;
+		vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops wpf_ctrl_ops = {
+	.s_ctrl = wpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
  * V4L2 Subdevice Core Operations
  */
 
 static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 {
+	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
 	struct vsp1_rwpf *wpf = to_rwpf(subdev);
-	struct vsp1_pipeline *pipe =
-		to_vsp1_pipeline(&wpf->entity.subdev.entity);
 	struct vsp1_device *vsp1 = wpf->entity.vsp1;
 	const struct v4l2_rect *crop = &wpf->crop;
 	unsigned int i;
 	u32 srcrpf = 0;
 	u32 outfmt = 0;
+	int ret;
+
+	ret = vsp1_entity_set_streaming(&wpf->entity, enable);
+	if (ret < 0)
+		return ret;
 
 	if (!enable) {
 		vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
+		vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0);
 		return 0;
 	}
 
@@ -99,6 +133,8 @@ static int wpf_s_stream(struct v4l2_subd
 
 		outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
 
+		if (fmtinfo->alpha)
+			outfmt |= VI6_WPF_OUTFMT_PXA;
 		if (fmtinfo->swap_yc)
 			outfmt |= VI6_WPF_OUTFMT_SPYCS;
 		if (fmtinfo->swap_uv)
@@ -111,7 +147,13 @@ static int wpf_s_stream(struct v4l2_subd
 	    wpf->entity.formats[RWPF_PAD_SOURCE].code)
 		outfmt |= VI6_WPF_OUTFMT_CSC;
 
+	/* Take the control handler lock to ensure that the PDV value won't be
+	 * changed behind our back by a set control operation.
+	 */
+	mutex_lock(wpf->ctrls.lock);
+	outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK;
 	vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
+	mutex_unlock(wpf->ctrls.lock);
 
 	vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index),
 		   VI6_DPR_WPF_FPORCH_FP_WPFN);
@@ -207,6 +249,20 @@ struct vsp1_rwpf *vsp1_wpf_create(struct
 
 	vsp1_entity_init_formats(subdev, NULL);
 
+	/* Initialize the control handler. */
+	v4l2_ctrl_handler_init(&wpf->ctrls, 1);
+	v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+			  0, 255, 1, 255);
+
+	wpf->entity.subdev.ctrl_handler = &wpf->ctrls;
+
+	if (wpf->ctrls.error) {
+		dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
+			index);
+		ret = wpf->ctrls.error;
+		goto error;
+	}
+
 	/* Initialize the video device. */
 	video = &wpf->video;
 
@@ -216,7 +272,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct
 
 	ret = vsp1_video_init(video, &wpf->entity);
 	if (ret < 0)
-		goto error_video;
+		goto error;
+
+	wpf->entity.video = video;
 
 	/* Connect the video device to the WPF. All connections are immutable
 	 * except for the WPF0 source link if a LIF is present.
@@ -229,15 +287,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct
 				       RWPF_PAD_SOURCE,
 				       &wpf->video.video.entity, 0, flags);
 	if (ret < 0)
-		goto error_link;
+		goto error;
 
 	wpf->entity.sink = &wpf->video.video.entity;
 
 	return wpf;
 
-error_link:
-	vsp1_video_cleanup(video);
-error_video:
-	media_entity_cleanup(&wpf->entity.subdev.entity);
+error:
+	vsp1_entity_destroy(&wpf->entity);
 	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/dsbr100.c linux-libre-3.17-rc7-gnu/drivers/media/radio/dsbr100.c
--- linux-libre-3.16-gnu/drivers/media/radio/dsbr100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/dsbr100.c	2014-09-28 17:29:07.000000000 -0400
@@ -390,7 +390,6 @@ static int usb_dsbr100_probe(struct usb_
 	radio->videodev.release = video_device_release_empty;
 	radio->videodev.lock = &radio->v4l2_lock;
 	radio->videodev.ctrl_handler = &radio->hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
 
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->curfreq = FREQ_MIN * FREQ_MUL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-cadet.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-cadet.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-cadet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-cadet.c	2014-09-28 17:29:07.000000000 -0400
@@ -650,7 +650,6 @@ static int __init cadet_init(void)
 	dev->vdev.ioctl_ops = &cadet_ioctl_ops;
 	dev->vdev.release = video_device_release_empty;
 	dev->vdev.lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 	video_set_drvdata(&dev->vdev, dev);
 
 	res = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-isa.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-isa.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-isa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-isa.c	2014-09-28 17:29:07.000000000 -0400
@@ -253,7 +253,6 @@ static int radio_isa_common_probe(struct
 	isa->vdev.fops = &radio_isa_fops;
 	isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
 	isa->vdev.release = video_device_release_empty;
-	set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags);
 	video_set_drvdata(&isa->vdev, isa);
 	isa->freq = FREQ_LOW;
 	isa->stereo = drv->has_stereo;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-keene.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-keene.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-keene.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-keene.c	2014-09-28 17:29:07.000000000 -0400
@@ -265,7 +265,7 @@ static int keene_s_ctrl(struct v4l2_ctrl
 		return keene_cmd_set(radio);
 
 	case V4L2_CID_AUDIO_COMPRESSION_GAIN:
-		radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step];
+		radio->tx = db2tx[(ctrl->val - (s32)ctrl->minimum) / (s32)ctrl->step];
 		return keene_cmd_set(radio);
 	}
 	return -EINVAL;
@@ -380,7 +380,6 @@ static int usb_keene_probe(struct usb_in
 	usb_set_intfdata(intf, &radio->v4l2_dev);
 
 	video_set_drvdata(&radio->vdev, radio);
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	/* at least 11ms is needed in order to settle hardware */
 	msleep(20);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-ma901.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-ma901.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-ma901.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-ma901.c	2014-09-28 17:29:07.000000000 -0400
@@ -411,7 +411,6 @@ static int usb_ma901radio_probe(struct u
 	radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
 	radio->vdev.release = video_device_release_empty;
 	radio->vdev.lock = &radio->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->intf = intf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-miropcm20.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-miropcm20.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-miropcm20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-miropcm20.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,20 +1,36 @@
-/* Miro PCM20 radio driver for Linux radio support
+/*
+ * Miro PCM20 radio driver for Linux radio support
  * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
  * Thanks to Norberto Pellici for the ACI device interface specification
  * The API part is based on the radiotrack driver by M. Kirkwood
  * This driver relies on the aci mixer provided by the snd-miro
  * ALSA driver.
  * Look there for further info...
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions...                Robert
+ *
+ * From the original miro RDS sources:
+ *
+ *  (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
+ *
+ *  Many thanks to Fred Seidel <seidel@metabox.de>, the
+ *  designer of the RDS decoder hardware. With his help
+ *  I was able to code this driver.
+ *  Thanks also to Norberto Pellicci, Dominic Mounteney
+ *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
+ *  for good hints on finding Fred. It was somewhat hard
+ *  to locate him here in Germany... [:
+ *
+ * This code has been reintroduced and converted to use
+ * the new V4L2 RDS API by:
+ *
+ * Hans Verkuil <hans.verkuil@cisco.com>
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
 #include <linux/videodev2.h>
+#include <linux/kthread.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
@@ -22,6 +38,22 @@
 #include <media/v4l2-event.h>
 #include <sound/aci.h>
 
+#define RDS_DATASHIFT          2   /* Bit 2 */
+#define RDS_DATAMASK        (1 << RDS_DATASHIFT)
+#define RDS_BUSYMASK        0x10   /* Bit 4 */
+#define RDS_CLOCKMASK       0x08   /* Bit 3 */
+#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1)
+
+#define RDS_STATUS      0x01
+#define RDS_STATIONNAME 0x02
+#define RDS_TEXT        0x03
+#define RDS_ALTFREQ     0x04
+#define RDS_TIMEDATE    0x05
+#define RDS_PI_CODE     0x06
+#define RDS_PTYTATP     0x07
+#define RDS_RESET       0x08
+#define RDS_RXVALUE     0x09
+
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
 MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
@@ -30,6 +62,14 @@ struct pcm20 {
 	struct v4l2_device v4l2_dev;
 	struct video_device vdev;
 	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl *rds_pty;
+	struct v4l2_ctrl *rds_ps_name;
+	struct v4l2_ctrl *rds_radio_test;
+	struct v4l2_ctrl *rds_ta;
+	struct v4l2_ctrl *rds_tp;
+	struct v4l2_ctrl *rds_ms;
+	/* thread for periodic RDS status checking */
+	struct task_struct *kthread;
 	unsigned long freq;
 	u32 audmode;
 	struct snd_miro_aci *aci;
@@ -41,6 +81,103 @@ static struct pcm20 pcm20_card = {
 	.audmode = V4L2_TUNER_MODE_STEREO,
 };
 
+
+static int rds_waitread(struct snd_miro_aci *aci)
+{
+	u8 byte;
+	int i = 2000;
+
+	do {
+		byte = inb(aci->aci_port + ACI_REG_RDS);
+		i--;
+	} while ((byte & RDS_BUSYMASK) && i);
+
+	/*
+	 * It's magic, but without this the data that you read later on
+	 * is unreliable and full of bit errors. With this 1 usec delay
+	 * everything is fine.
+	 */
+	udelay(1);
+	return i ? byte : -1;
+}
+
+static int rds_rawwrite(struct snd_miro_aci *aci, u8 byte)
+{
+	if (rds_waitread(aci) >= 0) {
+		outb(byte, aci->aci_port + ACI_REG_RDS);
+		return 0;
+	}
+	return -1;
+}
+
+static int rds_write(struct snd_miro_aci *aci, u8 byte)
+{
+	u8 sendbuffer[8];
+	int i;
+
+	for (i = 7; i >= 0; i--)
+		sendbuffer[7 - i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
+	sendbuffer[0] |= RDS_CLOCKMASK;
+
+	for (i = 0; i < 8; i++)
+		rds_rawwrite(aci, sendbuffer[i]);
+	return 0;
+}
+
+static int rds_readcycle_nowait(struct snd_miro_aci *aci)
+{
+	outb(0, aci->aci_port + ACI_REG_RDS);
+	return rds_waitread(aci);
+}
+
+static int rds_readcycle(struct snd_miro_aci *aci)
+{
+	if (rds_rawwrite(aci, 0) < 0)
+		return -1;
+	return rds_waitread(aci);
+}
+
+static int rds_ack(struct snd_miro_aci *aci)
+{
+	int i = rds_readcycle(aci);
+
+	if (i < 0)
+		return -1;
+	if (i & RDS_DATAMASK)
+		return 0;  /* ACK  */
+	return 1;  /* NACK */
+}
+
+static int rds_cmd(struct snd_miro_aci *aci, u8 cmd, u8 databuffer[], u8 datasize)
+{
+	int i, j;
+
+	rds_write(aci, cmd);
+
+	/* RDS_RESET doesn't need further processing */
+	if (cmd == RDS_RESET)
+		return 0;
+	if (rds_ack(aci))
+		return -EIO;
+	if (datasize == 0)
+		return 0;
+
+	/* to be able to use rds_readcycle_nowait()
+	   I have to waitread() here */
+	if (rds_waitread(aci) < 0)
+		return -1;
+
+	memset(databuffer, 0, datasize);
+
+	for (i = 0; i < 8 * datasize; i++) {
+		j = rds_readcycle_nowait(aci);
+		if (j < 0)
+			return -EIO;
+		databuffer[i / 8] |= RDS_DATA(j) << (7 - (i % 8));
+	}
+	return 0;
+}
+
 static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
 {
 	unsigned char freql;
@@ -54,17 +191,10 @@ static int pcm20_setfreq(struct pcm20 *d
 	freql = freq & 0xff;
 	freqh = freq >> 8;
 
+	rds_cmd(aci, RDS_RESET, NULL, 0);
 	return snd_aci_cmd(aci, ACI_WRITE_TUNE, freql, freqh);
 }
 
-static const struct v4l2_file_operations pcm20_fops = {
-	.owner		= THIS_MODULE,
-	.open		= v4l2_fh_open,
-	.poll		= v4l2_ctrl_poll,
-	.release	= v4l2_fh_release,
-	.unlocked_ioctl	= video_ioctl2,
-};
-
 static int vidioc_querycap(struct file *file, void *priv,
 				struct v4l2_capability *v)
 {
@@ -73,16 +203,31 @@ static int vidioc_querycap(struct file *
 	strlcpy(v->driver, "Miro PCM20", sizeof(v->driver));
 	strlcpy(v->card, "Miro PCM20", sizeof(v->card));
 	snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev->v4l2_dev.name);
-	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
 	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
+static bool sanitize(char *p, int size)
+{
+	int i;
+	bool ret = true;
+
+	for (i = 0; i < size; i++) {
+		if (p[i] < 32) {
+			p[i] = ' ';
+			ret = false;
+		}
+	}
+	return ret;
+}
+
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
 	struct pcm20 *dev = video_drvdata(file);
 	int res;
+	u8 buf;
 
 	if (v->index)
 		return -EINVAL;
@@ -97,8 +242,12 @@ static int vidioc_g_tuner(struct file *f
 	res = snd_aci_cmd(dev->aci, ACI_READ_TUNERSTEREO, -1, -1);
 	v->rxsubchans = (res & 0x40) ? V4L2_TUNER_SUB_MONO :
 					V4L2_TUNER_SUB_STEREO;
-	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+			V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
 	v->audmode = dev->audmode;
+	res = rds_cmd(dev->aci, RDS_RXVALUE, &buf, 1);
+	if (res >= 0 && buf)
+		v->rxsubchans |= V4L2_TUNER_SUB_RDS;
 	return 0;
 }
 
@@ -157,6 +306,115 @@ static int pcm20_s_ctrl(struct v4l2_ctrl
 	return -EINVAL;
 }
 
+static int pcm20_thread(void *data)
+{
+	struct pcm20 *dev = data;
+	const unsigned no_rds_start_counter = 5;
+	const unsigned sleep_msecs = 2000;
+	unsigned no_rds_counter = no_rds_start_counter;
+
+	for (;;) {
+		char text_buffer[66];
+		u8 buf;
+		int res;
+
+		msleep_interruptible(sleep_msecs);
+
+		if (kthread_should_stop())
+			break;
+
+		res = rds_cmd(dev->aci, RDS_RXVALUE, &buf, 1);
+		if (res)
+			continue;
+		if (buf == 0) {
+			if (no_rds_counter == 0)
+				continue;
+			no_rds_counter--;
+			if (no_rds_counter)
+				continue;
+
+			/*
+			 * No RDS seen for no_rds_start_counter * sleep_msecs
+			 * milliseconds, clear all RDS controls to their
+			 * default values.
+			 */
+			v4l2_ctrl_s_ctrl_string(dev->rds_ps_name, "");
+			v4l2_ctrl_s_ctrl(dev->rds_ms, 1);
+			v4l2_ctrl_s_ctrl(dev->rds_ta, 0);
+			v4l2_ctrl_s_ctrl(dev->rds_tp, 0);
+			v4l2_ctrl_s_ctrl(dev->rds_pty, 0);
+			v4l2_ctrl_s_ctrl_string(dev->rds_radio_test, "");
+			continue;
+		}
+		no_rds_counter = no_rds_start_counter;
+
+		res = rds_cmd(dev->aci, RDS_STATUS, &buf, 1);
+		if (res)
+			continue;
+		if ((buf >> 3) & 1) {
+			res = rds_cmd(dev->aci, RDS_STATIONNAME, text_buffer, 8);
+			text_buffer[8] = 0;
+			if (!res && sanitize(text_buffer, 8))
+				v4l2_ctrl_s_ctrl_string(dev->rds_ps_name, text_buffer);
+		}
+		if ((buf >> 6) & 1) {
+			u8 pty;
+
+			res = rds_cmd(dev->aci, RDS_PTYTATP, &pty, 1);
+			if (!res) {
+				v4l2_ctrl_s_ctrl(dev->rds_ms, !!(pty & 0x01));
+				v4l2_ctrl_s_ctrl(dev->rds_ta, !!(pty & 0x02));
+				v4l2_ctrl_s_ctrl(dev->rds_tp, !!(pty & 0x80));
+				v4l2_ctrl_s_ctrl(dev->rds_pty, (pty >> 2) & 0x1f);
+			}
+		}
+		if ((buf >> 4) & 1) {
+			res = rds_cmd(dev->aci, RDS_TEXT, text_buffer, 65);
+			text_buffer[65] = 0;
+			if (!res && sanitize(text_buffer + 1, 64))
+				v4l2_ctrl_s_ctrl_string(dev->rds_radio_test, text_buffer + 1);
+		}
+	}
+	return 0;
+}
+
+static int pcm20_open(struct file *file)
+{
+	struct pcm20 *dev = video_drvdata(file);
+	int res = v4l2_fh_open(file);
+
+	if (!res && v4l2_fh_is_singular_file(file) &&
+	    IS_ERR_OR_NULL(dev->kthread)) {
+		dev->kthread = kthread_run(pcm20_thread, dev, "%s",
+					   dev->v4l2_dev.name);
+		if (IS_ERR(dev->kthread)) {
+			v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
+			v4l2_fh_release(file);
+			return PTR_ERR(dev->kthread);
+		}
+	}
+	return res;
+}
+
+static int pcm20_release(struct file *file)
+{
+	struct pcm20 *dev = video_drvdata(file);
+
+	if (v4l2_fh_is_singular_file(file) && !IS_ERR_OR_NULL(dev->kthread)) {
+		kthread_stop(dev->kthread);
+		dev->kthread = NULL;
+	}
+	return v4l2_fh_release(file);
+}
+
+static const struct v4l2_file_operations pcm20_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pcm20_open,
+	.poll		= v4l2_ctrl_poll,
+	.release	= pcm20_release,
+	.unlocked_ioctl	= video_ioctl2,
+};
+
 static const struct v4l2_ioctl_ops pcm20_ioctl_ops = {
 	.vidioc_querycap    = vidioc_querycap,
 	.vidioc_g_tuner     = vidioc_g_tuner,
@@ -195,9 +453,21 @@ static int __init pcm20_init(void)
 	}
 
 	hdl = &dev->ctrl_handler;
-	v4l2_ctrl_handler_init(hdl, 1);
+	v4l2_ctrl_handler_init(hdl, 7);
 	v4l2_ctrl_new_std(hdl, &pcm20_ctrl_ops,
 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+	dev->rds_pty = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_PTY, 0, 0x1f, 1, 0);
+	dev->rds_ps_name = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
+	dev->rds_radio_test = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
+	dev->rds_ta = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
+	dev->rds_tp = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
+	dev->rds_ms = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
 	v4l2_dev->ctrl_handler = hdl;
 	if (hdl->error) {
 		res = hdl->error;
@@ -210,7 +480,6 @@ static int __init pcm20_init(void)
 	dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
 	dev->vdev.release = video_device_release_empty;
 	dev->vdev.lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 	video_set_drvdata(&dev->vdev, dev);
 	snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO,
 			dev->audmode == V4L2_TUNER_MODE_MONO, -1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-mr800.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-mr800.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-mr800.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-mr800.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@
  * achievements (specifications given).
  * Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
  * in 2007. He allowed to use his driver to improve current mr800 radio driver.
- * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
+ * http://www.spinics.net/lists/linux-usb-devel/msg10109.html
  *
  * Version 0.01:	First working version.
  * 			It's required to blacklist AverMedia USB Radio
@@ -558,7 +558,6 @@ static int usb_amradio_probe(struct usb_
 	radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
 	radio->vdev.release = video_device_release_empty;
 	radio->vdev.lock = &radio->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->intf = intf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-raremono.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-raremono.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-raremono.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-raremono.c	2014-09-28 17:29:07.000000000 -0400
@@ -361,7 +361,6 @@ static int usb_raremono_probe(struct usb
 	usb_set_intfdata(intf, &radio->v4l2_dev);
 
 	video_set_drvdata(&radio->vdev, radio);
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	raremono_cmd_main(radio, BAND_FM, 95160);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-sf16fmi.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-sf16fmi.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-sf16fmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-sf16fmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -344,7 +344,6 @@ static int __init fmi_init(void)
 	fmi->vdev.fops = &fmi_fops;
 	fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
 	fmi->vdev.release = video_device_release_empty;
-	set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags);
 	video_set_drvdata(&fmi->vdev, fmi);
 
 	mutex_init(&fmi->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-si476x.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-si476x.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-si476x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-si476x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1470,7 +1470,6 @@ static int si476x_radio_probe(struct pla
 	video_set_drvdata(&radio->videodev, radio);
 	platform_set_drvdata(pdev, radio);
 
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
 
 	radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
 	v4l2_ctrl_handler_init(&radio->ctrl_handler,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-tea5764.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-tea5764.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-tea5764.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-tea5764.c	2014-09-28 17:29:07.000000000 -0400
@@ -478,7 +478,6 @@ static int tea5764_i2c_probe(struct i2c_
 	video_set_drvdata(&radio->vdev, radio);
 	radio->vdev.lock = &radio->mutex;
 	radio->vdev.v4l2_dev = v4l2_dev;
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	/* initialize and power off the chip */
 	tea5764_i2c_read(radio);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-tea5777.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-tea5777.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-tea5777.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-tea5777.c	2014-09-28 17:29:07.000000000 -0400
@@ -570,7 +570,6 @@ int radio_tea5777_init(struct radio_tea5
 	tea->fops = tea575x_fops;
 	tea->fops.owner = owner;
 	tea->vd.fops = &tea->fops;
-	set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
 
 	tea->vd.ctrl_handler = &tea->ctrl_handler;
 	v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/radio-timb.c linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-timb.c
--- linux-libre-3.16-gnu/drivers/media/radio/radio-timb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/radio-timb.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,6 @@ static int timbradio_probe(struct platfo
 	tr->video_dev.release = video_device_release_empty;
 	tr->video_dev.minor = -1;
 	tr->video_dev.lock = &tr->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags);
 
 	strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
 	err = v4l2_device_register(NULL, &tr->v4l2_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/si470x/radio-si470x-usb.c linux-libre-3.17-rc7-gnu/drivers/media/radio/si470x/radio-si470x-usb.c
--- linux-libre-3.16-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -680,7 +680,6 @@ static int si470x_usb_driver_probe(struc
 	radio->videodev.lock = &radio->lock;
 	radio->videodev.v4l2_dev = &radio->v4l2_dev;
 	radio->videodev.release = video_device_release_empty;
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
 	video_set_drvdata(&radio->videodev, radio);
 
 	/* get device and chip versions */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/si4713/radio-platform-si4713.c linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/radio-platform-si4713.c
--- linux-libre-3.16-gnu/drivers/media/radio/si4713/radio-platform-si4713.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/radio-platform-si4713.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,7 +196,6 @@ static int radio_si4713_pdriver_probe(st
 	rsdev->radio_dev = radio_si4713_vdev_template;
 	rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
 	rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
-	set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
 	/* Serialize all access to the si4713 */
 	rsdev->radio_dev.lock = &rsdev->lock;
 	video_set_drvdata(&rsdev->radio_dev, rsdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/si4713/radio-usb-si4713.c linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/radio-usb-si4713.c
--- linux-libre-3.16-gnu/drivers/media/radio/si4713/radio-usb-si4713.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/radio-usb-si4713.c	2014-09-28 17:29:07.000000000 -0400
@@ -492,7 +492,6 @@ static int usb_si4713_probe(struct usb_i
 	radio->vdev.vfl_dir = VFL_DIR_TX;
 
 	video_set_drvdata(&radio->vdev, radio);
-	set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
 
 	retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
 	if (retval < 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/si4713/si4713.c linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/si4713.c
--- linux-libre-3.16-gnu/drivers/media/radio/si4713/si4713.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/si4713.c	2014-09-28 17:29:07.000000000 -0400
@@ -957,6 +957,41 @@ static int si4713_choose_econtrol_action
 		*bit = 5;
 		*mask = 0x1F << 5;
 		break;
+	case V4L2_CID_RDS_TX_DYNAMIC_PTY:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 15;
+		*mask = 1 << 15;
+		break;
+	case V4L2_CID_RDS_TX_COMPRESSED:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 14;
+		*mask = 1 << 14;
+		break;
+	case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 13;
+		*mask = 1 << 13;
+		break;
+	case V4L2_CID_RDS_TX_MONO_STEREO:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 12;
+		*mask = 1 << 12;
+		break;
+	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 10;
+		*mask = 1 << 10;
+		break;
+	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 4;
+		*mask = 1 << 4;
+		break;
+	case V4L2_CID_RDS_TX_MUSIC_SPEECH:
+		*property = SI4713_TX_RDS_PS_MISC;
+		*bit = 3;
+		*mask = 1 << 3;
+		break;
 	case V4L2_CID_AUDIO_LIMITER_ENABLED:
 		*property = SI4713_TX_ACOMP_ENABLE;
 		*bit = 1;
@@ -1098,11 +1133,11 @@ static int si4713_s_ctrl(struct v4l2_ctr
 
 		switch (ctrl->id) {
 		case V4L2_CID_RDS_TX_PS_NAME:
-			ret = si4713_set_rds_ps_name(sdev, ctrl->string);
+			ret = si4713_set_rds_ps_name(sdev, ctrl->p_new.p_char);
 			break;
 
 		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			ret = si4713_set_rds_radio_text(sdev, ctrl->string);
+			ret = si4713_set_rds_radio_text(sdev, ctrl->p_new.p_char);
 			break;
 
 		case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
@@ -1122,6 +1157,17 @@ static int si4713_s_ctrl(struct v4l2_ctr
 			}
 			break;
 
+		case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
+		case V4L2_CID_RDS_TX_ALT_FREQS:
+			if (sdev->rds_alt_freqs_enable->val) {
+				val = sdev->rds_alt_freqs->p_new.p_u32[0];
+				val = val / 100 - 876 + 0xe101;
+			} else {
+				val = 0xe0e0;
+			}
+			ret = si4713_write_property(sdev, SI4713_TX_RDS_PS_AF, val);
+			break;
+
 		default:
 			ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
 					&mask, &property, &mul, &table, &size);
@@ -1355,6 +1401,17 @@ static const struct v4l2_subdev_ops si47
 	.tuner		= &si4713_subdev_tuner_ops,
 };
 
+static const struct v4l2_ctrl_config si4713_alt_freqs_ctrl = {
+	.id = V4L2_CID_RDS_TX_ALT_FREQS,
+	.type = V4L2_CTRL_TYPE_U32,
+	.min = 87600,
+	.max = 107900,
+	.step = 100,
+	.def = 87600,
+	.dims = { 1 },
+	.elem_size = sizeof(u32),
+};
+
 /*
  * I2C driver interface
  */
@@ -1410,6 +1467,23 @@ static int si4713_probe(struct i2c_clien
 			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
 	sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
 			V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
+	sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
+	sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
+	sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
+	sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
+	sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
+	sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
+	sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
+	sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+			V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
+	sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
 	sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
 			V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
 			10, DEFAULT_RDS_DEVIATION);
@@ -1476,7 +1550,7 @@ static int si4713_probe(struct i2c_clien
 		rval = hdl->error;
 		goto free_ctrls;
 	}
-	v4l2_ctrl_cluster(20, &sdev->mute);
+	v4l2_ctrl_cluster(29, &sdev->mute);
 	sdev->sd.ctrl_handler = hdl;
 
 	if (client->irq) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/si4713/si4713.h linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/si4713.h
--- linux-libre-3.16-gnu/drivers/media/radio/si4713/si4713.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/si4713/si4713.h	2014-09-28 17:29:07.000000000 -0400
@@ -211,6 +211,15 @@ struct si4713_device {
 		struct v4l2_ctrl *rds_pi;
 		struct v4l2_ctrl *rds_deviation;
 		struct v4l2_ctrl *rds_pty;
+		struct v4l2_ctrl *rds_compressed;
+		struct v4l2_ctrl *rds_art_head;
+		struct v4l2_ctrl *rds_stereo;
+		struct v4l2_ctrl *rds_ta;
+		struct v4l2_ctrl *rds_tp;
+		struct v4l2_ctrl *rds_ms;
+		struct v4l2_ctrl *rds_dyn_pty;
+		struct v4l2_ctrl *rds_alt_freqs_enable;
+		struct v4l2_ctrl *rds_alt_freqs;
 		struct v4l2_ctrl *compression_enabled;
 		struct v4l2_ctrl *compression_threshold;
 		struct v4l2_ctrl *compression_gain;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/radio/tea575x.c linux-libre-3.17-rc7-gnu/drivers/media/radio/tea575x.c
--- linux-libre-3.16-gnu/drivers/media/radio/tea575x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/radio/tea575x.c	2014-09-28 17:29:07.000000000 -0400
@@ -523,7 +523,6 @@ int snd_tea575x_init(struct snd_tea575x
 	tea->fops = tea575x_fops;
 	tea->fops.owner = owner;
 	tea->vd.fops = &tea->fops;
-	set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
 	/* disable hw_freq_seek if we can't use it */
 	if (tea->cannot_read_data)
 		v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ati_remote.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ati_remote.c
--- linux-libre-3.16-gnu/drivers/media/rc/ati_remote.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ati_remote.c	2014-09-28 17:29:07.000000000 -0400
@@ -279,46 +279,42 @@ struct ati_remote {
 
 /* "Kinds" of messages sent from the hardware to the driver. */
 #define KIND_END        0
-#define KIND_LITERAL    1   /* Simply pass to input system */
+#define KIND_LITERAL    1   /* Simply pass to input system as EV_KEY */
 #define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
-#define KIND_LU         3   /* Directional keypad diagonals - left up, */
-#define KIND_RU         4   /*   right up,  */
-#define KIND_LD         5   /*   left down, */
-#define KIND_RD         6   /*   right down */
-#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
+#define KIND_ACCEL      3   /* Translate to EV_REL mouse-move events */
 
 /* Translation table from hardware messages to input events. */
 static const struct {
-	short kind;
-	unsigned char data;
-	int type;
-	unsigned int code;
-	int value;
+	unsigned char kind;
+	unsigned char data;	/* Raw key code from remote */
+	unsigned short code;	/* Input layer translation */
 }  ati_remote_tbl[] = {
-	/* Directional control pad axes */
-	{KIND_ACCEL,   0x70, EV_REL, REL_X, -1},   /* left */
-	{KIND_ACCEL,   0x71, EV_REL, REL_X, 1},    /* right */
-	{KIND_ACCEL,   0x72, EV_REL, REL_Y, -1},   /* up */
-	{KIND_ACCEL,   0x73, EV_REL, REL_Y, 1},    /* down */
+	/* Directional control pad axes.  Code is xxyy */
+	{KIND_ACCEL,    0x70, 0xff00},	/* left */
+	{KIND_ACCEL,    0x71, 0x0100},	/* right */
+	{KIND_ACCEL,    0x72, 0x00ff},	/* up */
+	{KIND_ACCEL,    0x73, 0x0001},	/* down */
+
 	/* Directional control pad diagonals */
-	{KIND_LU,      0x74, EV_REL, 0, 0},        /* left up */
-	{KIND_RU,      0x75, EV_REL, 0, 0},        /* right up */
-	{KIND_LD,      0x77, EV_REL, 0, 0},        /* left down */
-	{KIND_RD,      0x76, EV_REL, 0, 0},        /* right down */
+	{KIND_ACCEL,    0x74, 0xffff},	/* left up */
+	{KIND_ACCEL,    0x75, 0x01ff},	/* right up */
+	{KIND_ACCEL,    0x77, 0xff01},	/* left down */
+	{KIND_ACCEL,    0x76, 0x0101},	/* right down */
 
-	/* "Mouse button" buttons */
-	{KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
-	{KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
-	{KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
-	{KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+	/* "Mouse button" buttons.  The code below uses the fact that the
+	 * lsbit of the raw code is a down/up indicator. */
+	{KIND_LITERAL,  0x78, BTN_LEFT}, /* left btn down */
+	{KIND_LITERAL,  0x79, BTN_LEFT}, /* left btn up */
+	{KIND_LITERAL,  0x7c, BTN_RIGHT},/* right btn down */
+	{KIND_LITERAL,  0x7d, BTN_RIGHT},/* right btn up */
 
 	/* Artificial "doubleclick" events are generated by the hardware.
 	 * They are mapped to the "side" and "extra" mouse buttons here. */
-	{KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
-	{KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+	{KIND_FILTERED, 0x7a, BTN_SIDE}, /* left dblclick */
+	{KIND_FILTERED, 0x7e, BTN_EXTRA},/* right dblclick */
 
 	/* Non-mouse events are handled by rc-core */
-	{KIND_END, 0x00, EV_MAX + 1, 0, 0}
+	{KIND_END, 0x00, 0}
 };
 
 /*
@@ -493,7 +489,6 @@ static void ati_remote_input_report(stru
 	unsigned char *data= ati_remote->inbuf;
 	struct input_dev *dev = ati_remote->idev;
 	int index = -1;
-	int acc;
 	int remote_num;
 	unsigned char scancode;
 	u32 wheel_keycode = KEY_RESERVED;
@@ -507,8 +502,9 @@ static void ati_remote_input_report(stru
 	 */
 
 	/* Deal with strange looking inputs */
-	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
-		((data[3] & 0x0f) != 0x00) ) {
+	if ( urb->actual_length != 4 || data[0] != 0x14 ||
+	     data[1] != (unsigned char)(data[2] + data[3] + 0xD5) ||
+	     (data[3] & 0x0f) != 0x00) {
 		ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
 		return;
 	}
@@ -524,9 +520,9 @@ 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,%02x, "
+			"Masked input from channel 0x%02x: data %02x, "
 			"mask= 0x%02lx\n",
-			remote_num, data[1], data[2], channel_mask);
+			remote_num, data[2], channel_mask);
 		return;
 	}
 
@@ -566,16 +562,16 @@ static void ati_remote_input_report(stru
 	}
 
 	if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code,
-			ati_remote_tbl[index].value);
-		input_sync(dev);
+		/*
+		 * The lsbit of the raw key code is a down/up flag.
+		 * Invert it to match the input layer's conventions.
+		 */
+		input_event(dev, EV_KEY, ati_remote_tbl[index].code,
+			!(data[2] & 1));
 
 		ati_remote->old_jiffies = jiffies;
-		return;
-	}
 
-	if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
+	} else if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
 		unsigned long now = jiffies;
 
 		/* Filter duplicate events which happen "too close" together. */
@@ -588,12 +584,11 @@ static void ati_remote_input_report(stru
 			ati_remote->first_jiffies = now;
 		}
 
-		ati_remote->old_data = data[2];
 		ati_remote->old_jiffies = now;
 
-		/* Ensure we skip at least the 4 first duplicate events (generated
-		 * by a single keypress), and continue skipping until repeat_delay
-		 * msecs have passed
+		/* Ensure we skip at least the 4 first duplicate events
+		 * (generated by a single keypress), and continue skipping
+		 * until repeat_delay msecs have passed.
 		 */
 		if (ati_remote->repeat_count > 0 &&
 		    (ati_remote->repeat_count < 5 ||
@@ -601,7 +596,10 @@ static void ati_remote_input_report(stru
 				      msecs_to_jiffies(repeat_delay))))
 			return;
 
-		if (index < 0) {
+		if (index >= 0) {
+			input_event(dev, EV_KEY, ati_remote_tbl[index].code, 1);
+			input_event(dev, EV_KEY, ati_remote_tbl[index].code, 0);
+		} else {
 			/* Not a mouse event, hand it to rc-core. */
 			int count = 1;
 
@@ -622,61 +620,37 @@ static void ati_remote_input_report(stru
 				* it would cause ghost repeats which would be a
 				* regression for this driver.
 				*/
-				rc_keydown_notimeout(ati_remote->rdev, scancode,
-						     data[2]);
+				rc_keydown_notimeout(ati_remote->rdev, RC_TYPE_OTHER,
+						     scancode, data[2]);
 				rc_keyup(ati_remote->rdev);
 			}
-			return;
+			goto nosync;
 		}
 
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 1);
-		input_sync(dev);
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 0);
-		input_sync(dev);
-
-	} else {
+	} else if (ati_remote_tbl[index].kind == KIND_ACCEL) {
+		signed char dx = ati_remote_tbl[index].code >> 8;
+		signed char dy = ati_remote_tbl[index].code & 255;
 
 		/*
 		 * Other event kinds are from the directional control pad, and
 		 * have an acceleration factor applied to them.  Without this
 		 * acceleration, the control pad is mostly unusable.
 		 */
-		acc = ati_remote_compute_accel(ati_remote);
-
-		switch (ati_remote_tbl[index].kind) {
-		case KIND_ACCEL:
-			input_event(dev, ati_remote_tbl[index].type,
-				ati_remote_tbl[index].code,
-				ati_remote_tbl[index].value * acc);
-			break;
-		case KIND_LU:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_RU:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_LD:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		case KIND_RD:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		default:
-			dev_dbg(&ati_remote->interface->dev,
-				"ati_remote kind=%d\n",
-				ati_remote_tbl[index].kind);
-		}
-		input_sync(dev);
-
+		int acc = ati_remote_compute_accel(ati_remote);
+		if (dx)
+			input_report_rel(dev, REL_X, dx * acc);
+		if (dy)
+			input_report_rel(dev, REL_Y, dy * acc);
 		ati_remote->old_jiffies = jiffies;
-		ati_remote->old_data = data[2];
+
+	} else {
+		dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+			ati_remote_tbl[index].kind);
+		return;
 	}
+	input_sync(dev);
+nosync:
+	ati_remote->old_data = data[2];
 }
 
 /*
@@ -763,8 +737,9 @@ static void ati_remote_input_init(struct
 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
 	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
 	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
-		if (ati_remote_tbl[i].type == EV_KEY)
-			set_bit(ati_remote_tbl[i].code, idev->keybit);
+		if (ati_remote_tbl[i].kind == KIND_LITERAL ||
+		    ati_remote_tbl[i].kind == KIND_FILTERED)
+			__set_bit(ati_remote_tbl[i].code, idev->keybit);
 
 	input_set_drvdata(idev, ati_remote);
 
@@ -784,7 +759,7 @@ static void ati_remote_rc_init(struct at
 
 	rdev->priv = ati_remote;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-	rc_set_allowed_protocols(rdev, RC_BIT_OTHER);
+	rdev->allowed_protocols = RC_BIT_OTHER;
 	rdev->driver_name = "ati_remote";
 
 	rdev->open = ati_remote_rc_open;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ene_ir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ene_ir.c
--- linux-libre-3.16-gnu/drivers/media/rc/ene_ir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ene_ir.c	2014-09-28 17:29:07.000000000 -0400
@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp
 		learning_mode_force = false;
 
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->priv = dev;
 	rdev->open = ene_open;
 	rdev->close = ene_close;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/fintek-cir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/fintek-cir.c
--- linux-libre-3.16-gnu/drivers/media/rc/fintek-cir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/fintek-cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *
 	/* Set up the rc device */
 	rdev->priv = fintek;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->open = fintek_open;
 	rdev->close = fintek_close;
 	rdev->input_name = FINTEK_DESCRIPTION;
@@ -686,12 +686,12 @@ static struct pnp_driver fintek_driver =
 	.shutdown	= fintek_shutdown,
 };
 
-static int fintek_init(void)
+static int __init fintek_init(void)
 {
 	return pnp_register_driver(&fintek_driver);
 }
 
-static void fintek_exit(void)
+static void __exit fintek_exit(void)
 {
 	pnp_unregister_driver(&fintek_driver);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/gpio-ir-recv.c linux-libre-3.17-rc7-gnu/drivers/media/rc/gpio-ir-recv.c
--- linux-libre-3.16-gnu/drivers/media/rc/gpio-ir-recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/gpio-ir-recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct pla
 	rcdev->dev.parent = &pdev->dev;
 	rcdev->driver_name = GPIO_IR_DRIVER_NAME;
 	if (pdata->allowed_protos)
-		rc_set_allowed_protocols(rcdev, pdata->allowed_protos);
+		rcdev->allowed_protocols = pdata->allowed_protos;
 	else
-		rc_set_allowed_protocols(rcdev, RC_BIT_ALL);
+		rcdev->allowed_protocols = RC_BIT_ALL;
 	rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
 
 	gpio_dev->rcdev = rcdev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/iguanair.c linux-libre-3.17-rc7-gnu/drivers/media/rc/iguanair.c
--- linux-libre-3.16-gnu/drivers/media/rc/iguanair.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/iguanair.c	2014-09-28 17:29:07.000000000 -0400
@@ -495,7 +495,7 @@ static int iguanair_probe(struct usb_int
 	usb_to_input_id(ir->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rc, RC_BIT_ALL);
+	rc->allowed_protocols = RC_BIT_ALL;
 	rc->priv = ir;
 	rc->open = iguanair_open;
 	rc->close = iguanair_close;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-core.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-core.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,11 @@
  *
  * Copyright 2010-2014 Imagination Technologies 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 contains core img-ir code for setting up the driver. The two interfaces
  * (raw and hardware decode) are handled separately.
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir.h linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir.h
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,11 @@
  * ImgTec IR Decoder found in PowerDown Controller.
  *
  * Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #ifndef _IMG_IR_H_
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-hw.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-hw.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,11 @@
  *
  * Copyright 2010-2014 Imagination Technologies 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 ties into the input subsystem using the RC-core. Protocol support is
  * provided in separate modules which provide the parameters and scancode
  * translation functions to set up the hardware decoder and interpret the
@@ -507,7 +512,7 @@ unlock:
 static int img_ir_set_normal_filter(struct rc_dev *dev,
 				    struct rc_scancode_filter *sc_filter)
 {
-	return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter); 
+	return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter);
 }
 
 static int img_ir_set_wakeup_filter(struct rc_dev *dev,
@@ -551,8 +556,8 @@ static void img_ir_set_decoder(struct im
 	hw->mode = IMG_IR_M_NORMAL;
 
 	/* clear the wakeup scancode filter */
-	rdev->scancode_filters[RC_FILTER_WAKEUP].data = 0;
-	rdev->scancode_filters[RC_FILTER_WAKEUP].mask = 0;
+	rdev->scancode_wakeup_filter.data = 0;
+	rdev->scancode_wakeup_filter.mask = 0;
 
 	/* clear raw filters */
 	_img_ir_set_filter(priv, NULL);
@@ -656,8 +661,8 @@ success:
 	wakeup_protocols = *ir_type;
 	if (!hw->decoder || !hw->decoder->filter)
 		wakeup_protocols = 0;
-	rc_set_allowed_wakeup_protocols(rdev, wakeup_protocols);
-	rc_set_enabled_wakeup_protocols(rdev, wakeup_protocols);
+	rdev->allowed_wakeup_protocols = wakeup_protocols;
+	rdev->enabled_wakeup_protocols = wakeup_protocols;
 	return 0;
 }
 
@@ -671,9 +676,9 @@ static void img_ir_set_protocol(struct i
 	spin_unlock_irq(&rdev->rc_map.lock);
 
 	mutex_lock(&rdev->lock);
-	rc_set_enabled_protocols(rdev, proto);
-	rc_set_allowed_wakeup_protocols(rdev, proto);
-	rc_set_enabled_wakeup_protocols(rdev, proto);
+	rdev->enabled_protocols = proto;
+	rdev->allowed_wakeup_protocols = proto;
+	rdev->enabled_wakeup_protocols = proto;
 	mutex_unlock(&rdev->lock);
 }
 
@@ -790,9 +795,11 @@ static void img_ir_handle_data(struct im
 	struct img_ir_priv_hw *hw = &priv->hw;
 	const struct img_ir_decoder *dec = hw->decoder;
 	int ret = IMG_IR_SCANCODE;
-	int scancode;
+	u32 scancode;
+	enum rc_type protocol = RC_TYPE_UNKNOWN;
+
 	if (dec->scancode)
-		ret = dec->scancode(len, raw, &scancode, hw->enabled_protocols);
+		ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols);
 	else if (len >= 32)
 		scancode = (u32)raw;
 	else if (len < 32)
@@ -801,7 +808,7 @@ static void img_ir_handle_data(struct im
 		len, (unsigned long long)raw);
 	if (ret == IMG_IR_SCANCODE) {
 		dev_dbg(priv->dev, "decoded scan code %#x\n", scancode);
-		rc_keydown(hw->rdev, scancode, 0);
+		rc_keydown(hw->rdev, protocol, scancode, 0);
 		img_ir_end_repeat(priv);
 	} else if (ret == IMG_IR_REPEATCODE) {
 		if (hw->mode == IMG_IR_M_REPEATING) {
@@ -996,7 +1003,7 @@ int img_ir_probe_hw(struct img_ir_priv *
 	}
 	rdev->priv = priv;
 	rdev->map_name = RC_MAP_EMPTY;
-	rc_set_allowed_protocols(rdev, img_ir_allowed_protos(priv));
+	rdev->allowed_protocols = img_ir_allowed_protos(priv);
 	rdev->input_name = "IMG Infrared Decoder";
 	rdev->s_filter = img_ir_set_normal_filter;
 	rdev->s_wakeup_filter = img_ir_set_wakeup_filter;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-hw.h linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-hw.h
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,11 @@
  * ImgTec IR Hardware Decoder found in PowerDown Controller.
  *
  * Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #ifndef _IMG_IR_HW_H_
@@ -157,7 +162,8 @@ struct img_ir_decoder {
 	struct img_ir_control		control;
 
 	/* scancode logic */
-	int (*scancode)(int len, u64 raw, int *scancode, u64 protocols);
+	int (*scancode)(int len, u64 raw, enum rc_type *protocol,
+			u32 *scancode, u64 enabled_protocols);
 	int (*filter)(const struct rc_scancode_filter *in,
 		      struct img_ir_filter *out, u64 protocols);
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-jvc.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-jvc.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-jvc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-jvc.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,12 +2,18 @@
  * ImgTec IR Decoder setup for JVC protocol.
  *
  * Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #include "img-ir-hw.h"
 
 /* Convert JVC data to a scancode */
-static int img_ir_jvc_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
+			       u32 *scancode, u64 enabled_protocols)
 {
 	unsigned int cust, data;
 
@@ -17,6 +23,7 @@ static int img_ir_jvc_scancode(int len,
 	cust = (raw >> 0) & 0xff;
 	data = (raw >> 8) & 0xff;
 
+	*protocol = RC_TYPE_JVC;
 	*scancode = cust << 8 | data;
 	return IMG_IR_SCANCODE;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-nec.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-nec.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-nec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-nec.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,13 +2,19 @@
  * ImgTec IR Decoder setup for NEC protocol.
  *
  * Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #include "img-ir-hw.h"
 #include <linux/bitrev.h>
 
 /* Convert NEC data to a scancode */
-static int img_ir_nec_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
+			       u32 *scancode, u64 enabled_protocols)
 {
 	unsigned int addr, addr_inv, data, data_inv;
 	/* a repeat code has no data */
@@ -40,6 +46,7 @@ static int img_ir_nec_scancode(int len,
 		*scancode = addr << 8 |
 			    data;
 	}
+	*protocol = RC_TYPE_NEC;
 	return IMG_IR_SCANCODE;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-raw.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-raw.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-raw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-raw.c	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,11 @@
  *
  * Copyright 2010-2014 Imagination Technologies 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 ties into the input subsystem using the RC-core in raw mode. Raw IR
  * signal edges are reported and decoded by generic software decoders.
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-raw.h linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-raw.h
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-raw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-raw.h	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,11 @@
  * ImgTec IR Raw Decoder found in PowerDown Controller.
  *
  * Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #ifndef _IMG_IR_RAW_H_
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sanyo.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sanyo.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sanyo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sanyo.c	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,11 @@
  *
  * Copyright 2012-2014 Imagination Technologies 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.
+ *
  * From ir-sanyo-decoder.c:
  *
  * This protocol uses the NEC protocol timings. However, data is formatted as:
@@ -18,7 +23,8 @@
 #include "img-ir-hw.h"
 
 /* Convert Sanyo data to a scancode */
-static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
+				 u32 *scancode, u64 enabled_protocols)
 {
 	unsigned int addr, addr_inv, data, data_inv;
 	/* a repeat code has no data */
@@ -38,6 +44,7 @@ static int img_ir_sanyo_scancode(int len
 		return -EINVAL;
 
 	/* Normal Sanyo */
+	*protocol = RC_TYPE_SANYO;
 	*scancode = addr << 8 | data;
 	return IMG_IR_SCANCODE;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sharp.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sharp.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sharp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sharp.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,12 +2,18 @@
  * ImgTec IR Decoder setup for Sharp protocol.
  *
  * Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #include "img-ir-hw.h"
 
 /* Convert Sharp data to a scancode */
-static int img_ir_sharp_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
+				 u32 *scancode, u64 enabled_protocols)
 {
 	unsigned int addr, cmd, exp, chk;
 
@@ -26,6 +32,7 @@ static int img_ir_sharp_scancode(int len
 		/* probably the second half of the message */
 		return -EINVAL;
 
+	*protocol = RC_TYPE_SHARP;
 	*scancode = addr << 8 | cmd;
 	return IMG_IR_SCANCODE;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sony.c linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sony.c
--- linux-libre-3.16-gnu/drivers/media/rc/img-ir/img-ir-sony.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/img-ir/img-ir-sony.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,40 +2,49 @@
  * ImgTec IR Decoder setup for Sony (SIRC) protocol.
  *
  * Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
  */
 
 #include "img-ir-hw.h"
 
 /* Convert Sony data to a scancode */
-static int img_ir_sony_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
+				u32 *scancode, u64 enabled_protocols)
 {
 	unsigned int dev, subdev, func;
 
 	switch (len) {
 	case 12:
-		if (!(protocols & RC_BIT_SONY12))
+		if (!(enabled_protocols & RC_BIT_SONY12))
 			return -EINVAL;
 		func   = raw & 0x7f;	/* first 7 bits */
 		raw    >>= 7;
 		dev    = raw & 0x1f;	/* next 5 bits */
 		subdev = 0;
+		*protocol = RC_TYPE_SONY12;
 		break;
 	case 15:
-		if (!(protocols & RC_BIT_SONY15))
+		if (!(enabled_protocols & RC_BIT_SONY15))
 			return -EINVAL;
 		func   = raw & 0x7f;	/* first 7 bits */
 		raw    >>= 7;
 		dev    = raw & 0xff;	/* next 8 bits */
 		subdev = 0;
+		*protocol = RC_TYPE_SONY15;
 		break;
 	case 20:
-		if (!(protocols & RC_BIT_SONY20))
+		if (!(enabled_protocols & RC_BIT_SONY20))
 			return -EINVAL;
 		func   = raw & 0x7f;	/* first 7 bits */
 		raw    >>= 7;
 		dev    = raw & 0x1f;	/* next 5 bits */
 		raw    >>= 5;
 		subdev = raw & 0xff;	/* next 8 bits */
+		*protocol = RC_TYPE_SONY20;
 		break;
 	default:
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/imon.c linux-libre-3.17-rc7-gnu/drivers/media/rc/imon.c
--- linux-libre-3.16-gnu/drivers/media/rc/imon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/imon.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,11 +78,11 @@ static int display_open(struct inode *in
 static int display_close(struct inode *inode, struct file *file);
 
 /* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
 			 size_t n_bytes, loff_t *pos);
 
 /* LCD file_operations override function prototypes */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
 			 size_t n_bytes, loff_t *pos);
 
 /*** G L O B A L S ***/
@@ -825,7 +825,7 @@ static struct attribute_group imon_rf_at
  * than 32 bytes are provided spaces will be appended to
  * generate a full screen.
  */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
 			 size_t n_bytes, loff_t *pos)
 {
 	int i;
@@ -912,7 +912,7 @@ exit:
  * display whatever diacritics you need, and so on), but it's also
  * a lot more complicated than most LCDs...
  */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
 			 size_t n_bytes, loff_t *pos)
 {
 	int retval = 0;
@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struc
 	unsigned char ir_proto_packet[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
-	if (*rc_type && !rc_protocols_allowed(rc, *rc_type))
+	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");
 
@@ -1579,7 +1579,10 @@ static void imon_incoming_packet(struct
 		if (press_type == 0)
 			rc_keyup(ictx->rdev);
 		else {
-			rc_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle);
+			if (ictx->rc_type == RC_BIT_RC6_MCE)
+				rc_keydown(ictx->rdev,
+					   ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
+					   ictx->rc_scancode, ictx->rc_toggle);
 			spin_lock_irqsave(&ictx->kc_lock, flags);
 			ictx->last_keycode = ictx->kc;
 			spin_unlock_irqrestore(&ictx->kc_lock, flags);
@@ -1867,8 +1870,7 @@ static struct rc_dev *imon_init_rdev(str
 
 	rdev->priv = ictx;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-					/* iMON PAD or MCE */
-	rc_set_allowed_protocols(rdev, RC_BIT_OTHER | RC_BIT_RC6_MCE);
+	rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
 	rdev->change_protocol = imon_ir_change_protocol;
 	rdev->driver_name = MOD_NAME;
 
@@ -1881,7 +1883,7 @@ static struct rc_dev *imon_init_rdev(str
 
 	if (ictx->product == 0xffdc) {
 		imon_get_ffdc_type(ictx);
-		rc_set_allowed_protocols(rdev, ictx->rc_type);
+		rdev->allowed_protocols = ictx->rc_type;
 	}
 
 	imon_set_display_type(ictx);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-jvc-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-jvc-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-jvc-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-jvc-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *
 {
 	struct jvc_dec *data = &dev->raw->jvc;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_JVC))
+	if (!(dev->enabled_protocols & RC_BIT_JVC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -140,7 +140,7 @@ again:
 			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
 				   (bitrev8((data->bits >> 0) & 0xff) << 0);
 			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
-			rc_keydown(dev, scancode, data->toggle);
+			rc_keydown(dev, RC_TYPE_JVC, scancode, data->toggle);
 			data->first = false;
 			data->old_bits = data->bits;
 		} else if (data->bits == data->old_bits) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-lirc-codec.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-lirc-codec.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-lirc-codec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-lirc-codec.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev
 	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_LIRC))
+	if (!(dev->enabled_protocols & RC_BIT_LIRC))
 		return 0;
 
 	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-mce_kbd-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-mce_kbd-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-mce_kbd-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-mce_kbd-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_d
 	u32 scancode;
 	unsigned long delay;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_MCE_KBD))
+	if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-nec-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-nec-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-nec-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-nec-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *
 	u8 address, not_address, command, not_command;
 	bool send_32bits = false;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_NEC))
+	if (!(dev->enabled_protocols & RC_BIT_NEC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -189,7 +189,7 @@ static int ir_nec_decode(struct rc_dev *
 		if (data->is_nec_x)
 			data->necx_repeat = true;
 
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, RC_TYPE_NEC, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-raw.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-raw.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-raw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-raw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,362 +0,0 @@
-/* ir-raw.c - handle IR pulse/space events
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab
- *
- * This program is free software; 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/export.h>
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-#include <linux/kmod.h>
-#include <linux/sched.h>
-#include <linux/freezer.h>
-#include "rc-core-priv.h"
-
-/* Define the max number of pulse/space transitions to buffer */
-#define MAX_IR_EVENT_SIZE      512
-
-/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
-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 u64 available_protocols;
-
-static int ir_raw_event_thread(void *data)
-{
-	struct ir_raw_event ev;
-	struct ir_raw_handler *handler;
-	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
-	int retval;
-
-	while (!kthread_should_stop()) {
-
-		spin_lock_irq(&raw->lock);
-		retval = kfifo_len(&raw->kfifo);
-
-		if (retval < sizeof(ev)) {
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			if (kthread_should_stop())
-				set_current_state(TASK_RUNNING);
-
-			spin_unlock_irq(&raw->lock);
-			schedule();
-			continue;
-		}
-
-		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
-		spin_unlock_irq(&raw->lock);
-
-		mutex_lock(&ir_raw_handler_lock);
-		list_for_each_entry(handler, &ir_raw_handler_list, list)
-			handler->decode(raw->dev, ev);
-		raw->prev_ev = ev;
-		mutex_unlock(&ir_raw_handler_lock);
-	}
-
-	return 0;
-}
-
-/**
- * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
- * @dev:	the struct rc_dev device descriptor
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This routine (which may be called from an interrupt context) stores a
- * pulse/space duration for the raw ir decoding state machines. Pulses are
- * signalled as positive values and spaces as negative values. A zero value
- * will reset the decoding state machines.
- */
-int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
-{
-	if (!dev->raw)
-		return -EINVAL;
-
-	IR_dprintk(2, "sample: (%05dus %s)\n",
-		   TO_US(ev->duration), TO_STR(ev->pulse));
-
-	if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
-		return -ENOMEM;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store);
-
-/**
- * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
- * @dev:	the struct rc_dev device descriptor
- * @type:	the type of the event that has occurred
- *
- * This routine (which may be called from an interrupt context) is used to
- * store the beginning of an ir pulse or space (or the start/end of ir
- * reception) for the raw ir decoding state machines. This is used by
- * hardware which does not provide durations directly but only interrupts
- * (or similar events) on state change.
- */
-int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
-{
-	ktime_t			now;
-	s64			delta; /* ns */
-	DEFINE_IR_RAW_EVENT(ev);
-	int			rc = 0;
-	int			delay;
-
-	if (!dev->raw)
-		return -EINVAL;
-
-	now = ktime_get();
-	delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
-	delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
-
-	/* Check for a long duration since last event or if we're
-	 * being called for the first time, note that delta can't
-	 * possibly be negative.
-	 */
-	if (delta > delay || !dev->raw->last_type)
-		type |= IR_START_EVENT;
-	else
-		ev.duration = delta;
-
-	if (type & IR_START_EVENT)
-		ir_raw_event_reset(dev);
-	else if (dev->raw->last_type & IR_SPACE) {
-		ev.pulse = false;
-		rc = ir_raw_event_store(dev, &ev);
-	} else if (dev->raw->last_type & IR_PULSE) {
-		ev.pulse = true;
-		rc = ir_raw_event_store(dev, &ev);
-	} else
-		return 0;
-
-	dev->raw->last_event = now;
-	dev->raw->last_type = type;
-	return rc;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
-
-/**
- * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
- * @dev:	the struct rc_dev device descriptor
- * @type:	the type of the event that has occurred
- *
- * This routine (which may be called from an interrupt context) works
- * in similar manner to ir_raw_event_store_edge.
- * This routine is intended for devices with limited internal buffer
- * It automerges samples of same type, and handles timeouts. Returns non-zero
- * if the event was added, and zero if the event was ignored due to idle
- * processing.
- */
-int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
-{
-	if (!dev->raw)
-		return -EINVAL;
-
-	/* Ignore spaces in idle mode */
-	if (dev->idle && !ev->pulse)
-		return 0;
-	else if (dev->idle)
-		ir_raw_event_set_idle(dev, false);
-
-	if (!dev->raw->this_ev.duration)
-		dev->raw->this_ev = *ev;
-	else if (ev->pulse == dev->raw->this_ev.pulse)
-		dev->raw->this_ev.duration += ev->duration;
-	else {
-		ir_raw_event_store(dev, &dev->raw->this_ev);
-		dev->raw->this_ev = *ev;
-	}
-
-	/* Enter idle mode if nessesary */
-	if (!ev->pulse && dev->timeout &&
-	    dev->raw->this_ev.duration >= dev->timeout)
-		ir_raw_event_set_idle(dev, true);
-
-	return 1;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
-
-/**
- * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not
- * @dev:	the struct rc_dev device descriptor
- * @idle:	whether the device is idle or not
- */
-void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
-{
-	if (!dev->raw)
-		return;
-
-	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
-
-	if (idle) {
-		dev->raw->this_ev.timeout = true;
-		ir_raw_event_store(dev, &dev->raw->this_ev);
-		init_ir_raw_event(&dev->raw->this_ev);
-	}
-
-	if (dev->s_idle)
-		dev->s_idle(dev, idle);
-
-	dev->idle = idle;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
-
-/**
- * ir_raw_event_handle() - schedules the decoding of stored ir data
- * @dev:	the struct rc_dev device descriptor
- *
- * This routine will tell rc-core to start decoding stored ir data.
- */
-void ir_raw_event_handle(struct rc_dev *dev)
-{
-	unsigned long flags;
-
-	if (!dev->raw)
-		return;
-
-	spin_lock_irqsave(&dev->raw->lock, flags);
-	wake_up_process(dev->raw->thread);
-	spin_unlock_irqrestore(&dev->raw->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_handle);
-
-/* used internally by the sysfs interface */
-u64
-ir_raw_get_allowed_protocols(void)
-{
-	u64 protocols;
-	mutex_lock(&ir_raw_handler_lock);
-	protocols = available_protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-	return protocols;
-}
-
-/*
- * Used to (un)register raw event clients
- */
-int ir_raw_event_register(struct rc_dev *dev)
-{
-	int rc;
-	struct ir_raw_handler *handler;
-
-	if (!dev)
-		return -EINVAL;
-
-	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
-	if (!dev->raw)
-		return -ENOMEM;
-
-	dev->raw->dev = dev;
-	rc_set_enabled_protocols(dev, ~0);
-	rc = kfifo_alloc(&dev->raw->kfifo,
-			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
-			 GFP_KERNEL);
-	if (rc < 0)
-		goto out;
-
-	spin_lock_init(&dev->raw->lock);
-	dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
-				       "rc%ld", dev->devno);
-
-	if (IS_ERR(dev->raw->thread)) {
-		rc = PTR_ERR(dev->raw->thread);
-		goto out;
-	}
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_add_tail(&dev->raw->list, &ir_raw_client_list);
-	list_for_each_entry(handler, &ir_raw_handler_list, list)
-		if (handler->raw_register)
-			handler->raw_register(dev);
-	mutex_unlock(&ir_raw_handler_lock);
-
-	return 0;
-
-out:
-	kfree(dev->raw);
-	dev->raw = NULL;
-	return rc;
-}
-
-void ir_raw_event_unregister(struct rc_dev *dev)
-{
-	struct ir_raw_handler *handler;
-
-	if (!dev || !dev->raw)
-		return;
-
-	kthread_stop(dev->raw->thread);
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_del(&dev->raw->list);
-	list_for_each_entry(handler, &ir_raw_handler_list, list)
-		if (handler->raw_unregister)
-			handler->raw_unregister(dev);
-	mutex_unlock(&ir_raw_handler_lock);
-
-	kfifo_free(&dev->raw->kfifo);
-	kfree(dev->raw);
-	dev->raw = NULL;
-}
-
-/*
- * Extension interface - used to register the IR decoders
- */
-
-int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
-{
-	struct ir_raw_event_ctrl *raw;
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
-	if (ir_raw_handler->raw_register)
-		list_for_each_entry(raw, &ir_raw_client_list, list)
-			ir_raw_handler->raw_register(raw->dev);
-	available_protocols |= ir_raw_handler->protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(ir_raw_handler_register);
-
-void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
-{
-	struct ir_raw_event_ctrl *raw;
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_del(&ir_raw_handler->list);
-	if (ir_raw_handler->raw_unregister)
-		list_for_each_entry(raw, &ir_raw_client_list, list)
-			ir_raw_handler->raw_unregister(raw->dev);
-	available_protocols &= ~ir_raw_handler->protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-}
-EXPORT_SYMBOL(ir_raw_handler_unregister);
-
-void ir_raw_init(void)
-{
-	/* Load the decoder modules */
-
-	load_nec_decode();
-	load_rc5_decode();
-	load_rc6_decode();
-	load_jvc_decode();
-	load_sony_decode();
-	load_sanyo_decode();
-	load_sharp_decode();
-	load_mce_kbd_decode();
-	load_lirc_codec();
-
-	/* If needed, we may later add some init code. In this case,
-	   it is needed to change the CONFIG_MODULE test at rc-core.h
-	 */
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-rc5-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc5-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-rc5-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc5-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
  *
  * Copyright (C) 2010 by Mauro Carvalho Chehab
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
  *
  * This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -13,23 +14,22 @@
  */
 
 /*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
+ * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
+ * and 20 bit RC5x protocol.
  */
 
 #include "rc-core-priv.h"
 #include <linux/module.h>
 
 #define RC5_NBITS		14
+#define RC5_SZ_NBITS		15
 #define RC5X_NBITS		20
 #define CHECK_RC5X_NBITS	8
 #define RC5_UNIT		888888 /* ns */
 #define RC5_BIT_START		(1 * RC5_UNIT)
 #define RC5_BIT_END		(1 * RC5_UNIT)
 #define RC5X_SPACE		(4 * RC5_UNIT)
+#define RC5_TRAILER		(10 * RC5_UNIT) /* In reality, approx 100 */
 
 enum rc5_state {
 	STATE_INACTIVE,
@@ -51,8 +51,9 @@ static int ir_rc5_decode(struct rc_dev *
 	struct rc5_dec *data = &dev->raw->rc5;
 	u8 toggle;
 	u32 scancode;
+	enum rc_type protocol;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_RC5 | RC_BIT_RC5X))
+	if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -65,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *
 		goto out;
 
 again:
-	IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+	IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
 		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 
 	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
@@ -79,12 +80,15 @@ again:
 
 		data->state = STATE_BIT_START;
 		data->count = 1;
-		/* We just need enough bits to get to STATE_CHECK_RC5X */
-		data->wanted_bits = RC5X_NBITS;
 		decrease_duration(&ev, RC5_BIT_START);
 		goto again;
 
 	case STATE_BIT_START:
+		if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
+			data->state = STATE_FINISHED;
+			goto again;
+		}
+
 		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
 			break;
 
@@ -99,9 +103,7 @@ again:
 		if (!is_transition(&ev, &dev->raw->prev_ev))
 			break;
 
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else if (data->count == CHECK_RC5X_NBITS)
+		if (data->count == CHECK_RC5X_NBITS)
 			data->state = STATE_CHECK_RC5X;
 		else
 			data->state = STATE_BIT_START;
@@ -111,13 +113,10 @@ again:
 
 	case STATE_CHECK_RC5X:
 		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
-			/* RC5X */
-			data->wanted_bits = RC5X_NBITS;
+			data->is_rc5x = true;
 			decrease_duration(&ev, RC5X_SPACE);
-		} else {
-			/* RC5 */
-			data->wanted_bits = RC5_NBITS;
-		}
+		} else
+			data->is_rc5x = false;
 		data->state = STATE_BIT_START;
 		goto again;
 
@@ -125,10 +124,10 @@ again:
 		if (ev.pulse)
 			break;
 
-		if (data->wanted_bits == RC5X_NBITS) {
+		if (data->is_rc5x && data->count == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
-			if (!rc_protocols_enabled(dev, RC_BIT_RC5X)) {
+			if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
@@ -138,14 +137,12 @@ again:
 			toggle   = (data->bits & 0x20000) ? 1 : 0;
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 16 | command << 8 | xdata;
+			protocol = RC_TYPE_RC5X;
 
-			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
-				   scancode, toggle);
-
-		} else {
+		} else if (!data->is_rc5x && data->count == RC5_NBITS) {
 			/* RC5 */
 			u8 command, system;
-			if (!rc_protocols_enabled(dev, RC_BIT_RC5)) {
+			if (!(dev->enabled_protocols & RC_BIT_RC5)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
@@ -154,25 +151,41 @@ again:
 			toggle   = (data->bits & 0x00800) ? 1 : 0;
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 8 | command;
+			protocol = RC_TYPE_RC5;
 
-			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
-				   scancode, toggle);
-		}
+		} else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
+			/* RC5 StreamZap */
+			u8 command, system;
+			if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
+			command  = (data->bits & 0x0003F) >> 0;
+			system   = (data->bits & 0x02FC0) >> 6;
+			toggle   = (data->bits & 0x01000) ? 1 : 0;
+			scancode = system << 6 | command;
+			protocol = RC_TYPE_RC5_SZ;
 
-		rc_keydown(dev, scancode, toggle);
+		} else
+			break;
+
+		IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
+			   scancode, protocol, toggle);
+
+		rc_keydown(dev, protocol, scancode, toggle);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
 
 out:
-	IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	IR_dprintk(1, "RC5(x/sz) decode failed at state %i count %d (%uus %s)\n",
+		   data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
 	data->state = STATE_INACTIVE;
 	return -EINVAL;
 }
 
 static struct ir_raw_handler rc5_handler = {
-	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X,
+	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
 	.decode		= ir_rc5_decode,
 };
 
@@ -180,7 +193,7 @@ static int __init ir_rc5_decode_init(voi
 {
 	ir_raw_handler_register(&rc5_handler);
 
-	printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
+	printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
 	return 0;
 }
 
@@ -193,6 +206,6 @@ module_init(ir_rc5_decode_init);
 module_exit(ir_rc5_decode_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
+MODULE_DESCRIPTION("RC5(x/sz) IR protocol decoder");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-rc5-sz-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc5-sz-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-rc5-sz-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc5-sz-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab
- * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2 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.
- */
-
-/*
- * This code handles the 15 bit RC5-ish protocol used by the Streamzap
- * PC Remote.
- * It considers a carrier of 36 kHz, with a total of 15 bits, where
- * the first two bits are start bits, and a third one is a filing bit
- */
-
-#include "rc-core-priv.h"
-#include <linux/module.h>
-
-#define RC5_SZ_NBITS		15
-#define RC5_UNIT		888888 /* ns */
-#define RC5_BIT_START		(1 * RC5_UNIT)
-#define RC5_BIT_END		(1 * RC5_UNIT)
-
-enum rc5_sz_state {
-	STATE_INACTIVE,
-	STATE_BIT_START,
-	STATE_BIT_END,
-	STATE_FINISHED,
-};
-
-/**
- * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
- * @dev:	the struct rc_dev descriptor of the device
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
-{
-	struct rc5_sz_dec *data = &dev->raw->rc5_sz;
-	u8 toggle, command, system;
-	u32 scancode;
-
-	if (!rc_protocols_enabled(dev, RC_BIT_RC5_SZ))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		goto out;
-
-again:
-	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		return 0;
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		data->state = STATE_BIT_START;
-		data->count = 1;
-		data->wanted_bits = RC5_SZ_NBITS;
-		decrease_duration(&ev, RC5_BIT_START);
-		goto again;
-
-	case STATE_BIT_START:
-		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
-			break;
-
-		data->bits <<= 1;
-		if (!ev.pulse)
-			data->bits |= 1;
-		data->count++;
-		data->state = STATE_BIT_END;
-		return 0;
-
-	case STATE_BIT_END:
-		if (!is_transition(&ev, &dev->raw->prev_ev))
-			break;
-
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else
-			data->state = STATE_BIT_START;
-
-		decrease_duration(&ev, RC5_BIT_END);
-		goto again;
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		/* RC5-sz */
-		command  = (data->bits & 0x0003F) >> 0;
-		system   = (data->bits & 0x02FC0) >> 6;
-		toggle   = (data->bits & 0x01000) ? 1 : 0;
-		scancode = system << 6 | command;
-
-		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
-			   scancode, toggle);
-
-		rc_keydown(dev, scancode, toggle);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler rc5_sz_handler = {
-	.protocols	= RC_BIT_RC5_SZ,
-	.decode		= ir_rc5_sz_decode,
-};
-
-static int __init ir_rc5_sz_decode_init(void)
-{
-	ir_raw_handler_register(&rc5_sz_handler);
-
-	printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_rc5_sz_decode_exit(void)
-{
-	ir_raw_handler_unregister(&rc5_sz_handler);
-}
-
-module_init(ir_rc5_sz_decode_init);
-module_exit(ir_rc5_sz_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-rc6-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc6-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-rc6-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-rc6-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,10 +88,11 @@ static int ir_rc6_decode(struct rc_dev *
 	struct rc6_dec *data = &dev->raw->rc6;
 	u32 scancode;
 	u8 toggle;
+	enum rc_type protocol;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
-				  RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
-				  RC_BIT_RC6_MCE))
+	if (!(dev->enabled_protocols &
+	      (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
+	       RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -233,9 +234,11 @@ again:
 		case RC6_MODE_0:
 			scancode = data->body;
 			toggle = data->toggle;
+			protocol = RC_TYPE_RC6_0;
 			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
 				   scancode, toggle);
 			break;
+
 		case RC6_MODE_6A:
 			if (data->count > CHAR_BIT * sizeof data->body) {
 				IR_dprintk(1, "RC6 too many (%u) data bits\n",
@@ -244,23 +247,39 @@ again:
 			}
 
 			scancode = data->body;
-			if (data->count == RC6_6A_32_NBITS &&
-					(scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
-				/* MCE RC */
-				toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
-				scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
-			} else {
+			switch (data->count) {
+			case 20:
+				protocol = RC_TYPE_RC6_6A_20;
+				toggle = 0;
+				break;
+			case 24:
+				protocol = RC_BIT_RC6_6A_24;
 				toggle = 0;
+				break;
+			case 32:
+				if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+					protocol = RC_TYPE_RC6_MCE;
+					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
+				} else {
+					protocol = RC_BIT_RC6_6A_32;
+					toggle = 0;
+				}
+				break;
+			default:
+				IR_dprintk(1, "RC6(6A) unsupported length\n");
+				goto out;
 			}
-			IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
-				   scancode, toggle);
+
+			IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
+				   protocol, scancode, toggle);
 			break;
 		default:
 			IR_dprintk(1, "RC6 unknown mode\n");
 			goto out;
 		}
 
-		rc_keydown(dev, scancode, toggle);
+		rc_keydown(dev, protocol, scancode, toggle);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-sanyo-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sanyo-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-sanyo-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sanyo-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev
 	u32 scancode;
 	u8 address, command, not_command;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_SANYO))
+	if (!(dev->enabled_protocols & RC_BIT_SANYO))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -167,7 +167,7 @@ static int ir_sanyo_decode(struct rc_dev
 
 		scancode = address << 8 | command;
 		IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, RC_TYPE_SANYO, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-sharp-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sharp-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-sharp-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sharp-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@ static int ir_sharp_decode(struct rc_dev
 	struct sharp_dec *data = &dev->raw->sharp;
 	u32 msg, echo, address, command, scancode;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_SHARP))
+	if (!(dev->enabled_protocols & RC_BIT_SHARP))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -162,7 +162,7 @@ static int ir_sharp_decode(struct rc_dev
 		scancode = address << 8 | command;
 		IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode);
 
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, RC_TYPE_SHARP, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-sony-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sony-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-sony-decoder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-sony-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,11 +42,12 @@ enum sony_state {
 static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct sony_dec *data = &dev->raw->sony;
+	enum rc_type protocol;
 	u32 scancode;
 	u8 device, subdevice, function;
 
-	if (!rc_protocols_enabled(dev, RC_BIT_SONY12 | RC_BIT_SONY15 |
-				  RC_BIT_SONY20))
+	if (!(dev->enabled_protocols &
+	      (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -124,31 +125,34 @@ static int ir_sony_decode(struct rc_dev
 
 		switch (data->count) {
 		case 12:
-			if (!rc_protocols_enabled(dev, RC_BIT_SONY12)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY12)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
 			device    = bitrev8((data->bits <<  3) & 0xF8);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  4) & 0xFE);
+			protocol = RC_TYPE_SONY12;
 			break;
 		case 15:
-			if (!rc_protocols_enabled(dev, RC_BIT_SONY15)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY15)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
 			device    = bitrev8((data->bits >>  0) & 0xFF);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  7) & 0xFE);
+			protocol = RC_TYPE_SONY15;
 			break;
 		case 20:
-			if (!rc_protocols_enabled(dev, RC_BIT_SONY20)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY20)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
 			device    = bitrev8((data->bits >>  5) & 0xF8);
 			subdevice = bitrev8((data->bits >>  0) & 0xFF);
 			function  = bitrev8((data->bits >> 12) & 0xFE);
+			protocol = RC_TYPE_SONY20;
 			break;
 		default:
 			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
@@ -157,7 +161,7 @@ static int ir_sony_decode(struct rc_dev
 
 		scancode = device << 16 | subdevice << 8 | function;
 		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, protocol, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ir-xmp-decoder.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-xmp-decoder.c
--- linux-libre-3.16-gnu/drivers/media/rc/ir-xmp-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ir-xmp-decoder.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,225 @@
+/* ir-xmp-decoder.c - handle XMP IR Pulse/Space protocol
+ *
+ * Copyright (C) 2014 by Marcel Mol
+ *
+ * This program is free software; 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.
+ *
+ * - Based on info from http://www.hifi-remote.com
+ * - Ignore Toggle=9 frames
+ * - Ignore XMP-1 XMP-2 difference, always store 16 bit OBC
+ */
+
+#include <linux/bitrev.h>
+#include <linux/module.h>
+#include "rc-core-priv.h"
+
+#define XMP_UNIT		  136000 /* ns */
+#define XMP_LEADER		  210000 /* ns */
+#define XMP_NIBBLE_PREFIX	  760000 /* ns */
+#define	XMP_HALFFRAME_SPACE	13800000 /* ns */
+#define	XMP_TRAILER_SPACE	20000000 /* should be 80ms but not all dureation supliers can go that high */
+
+enum xmp_state {
+	STATE_INACTIVE,
+	STATE_LEADER_PULSE,
+	STATE_NIBBLE_SPACE,
+};
+
+/**
+ * ir_xmp_decode() - Decode one XMP pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @duration:	the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct xmp_dec *data = &dev->raw->xmp;
+
+	if (!(dev->enabled_protocols & RC_BIT_XMP))
+		return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	IR_dprintk(2, "XMP decode started at state %d %d (%uus %s)\n",
+		   data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2)) {
+			data->count = 0;
+			data->state = STATE_NIBBLE_SPACE;
+		}
+
+		return 0;
+
+	case STATE_LEADER_PULSE:
+		if (!ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2))
+			data->state = STATE_NIBBLE_SPACE;
+
+		return 0;
+
+	case STATE_NIBBLE_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (geq_margin(ev.duration, XMP_TRAILER_SPACE, XMP_NIBBLE_PREFIX)) {
+			int divider, i;
+			u8 addr, subaddr, subaddr2, toggle, oem, obc1, obc2, sum1, sum2;
+			u32 *n;
+			u32 scancode;
+
+			if (data->count != 16) {
+				IR_dprintk(2, "received TRAILER period at index %d: %u\n",
+					data->count, ev.duration);
+				data->state = STATE_INACTIVE;
+				return -EINVAL;
+			}
+
+			n = data->durations;
+			/*
+			 * the 4th nibble should be 15 so base the divider on this
+			 * to transform durations into nibbles. Substract 2000 from
+			 * the divider to compensate for fluctuations in the signal
+			 */
+			divider = (n[3] - XMP_NIBBLE_PREFIX) / 15 - 2000;
+			if (divider < 50) {
+				IR_dprintk(2, "divider to small %d.\n", divider);
+				data->state = STATE_INACTIVE;
+				return -EINVAL;
+			}
+
+			/* convert to nibbles and do some sanity checks */
+			for (i = 0; i < 16; i++)
+				n[i] = (n[i] - XMP_NIBBLE_PREFIX) / divider;
+			sum1 = (15 + n[0] + n[1] + n[2] + n[3] +
+				n[4] + n[5] + n[6] + n[7]) % 16;
+			sum2 = (15 + n[8] + n[9] + n[10] + n[11] +
+				n[12] + n[13] + n[14] + n[15]) % 16;
+
+			if (sum1 != 15 || sum2 != 15) {
+				IR_dprintk(2, "checksum errors sum1=0x%X sum2=0x%X\n",
+					sum1, sum2);
+				data->state = STATE_INACTIVE;
+				return -EINVAL;
+			}
+
+			subaddr  = n[0] << 4 | n[2];
+			subaddr2 = n[8] << 4 | n[11];
+			oem      = n[4] << 4 | n[5];
+			addr     = n[6] << 4 | n[7];
+			toggle   = n[10];
+			obc1 = n[12] << 4 | n[13];
+			obc2 = n[14] << 4 | n[15];
+			if (subaddr != subaddr2) {
+				IR_dprintk(2, "subaddress nibbles mismatch 0x%02X != 0x%02X\n",
+					subaddr, subaddr2);
+				data->state = STATE_INACTIVE;
+				return -EINVAL;
+			}
+			if (oem != 0x44)
+				IR_dprintk(1, "Warning: OEM nibbles 0x%02X. Expected 0x44\n",
+					oem);
+
+			scancode = addr << 24 | subaddr << 16 |
+				   obc1 << 8 | obc2;
+			IR_dprintk(1, "XMP scancode 0x%06x\n", scancode);
+
+			if (toggle == 0) {
+				rc_keydown(dev, RC_TYPE_XMP, scancode, 0);
+			} else {
+				rc_repeat(dev);
+				IR_dprintk(1, "Repeat last key\n");
+			}
+			data->state = STATE_INACTIVE;
+
+			return 0;
+
+		} else if (geq_margin(ev.duration, XMP_HALFFRAME_SPACE, XMP_NIBBLE_PREFIX)) {
+			/* Expect 8 or 16 nibble pulses. 16 in case of 'final' frame */
+			if (data->count == 16) {
+				IR_dprintk(2, "received half frame pulse at index %d. Probably a final frame key-up event: %u\n",
+					data->count, ev.duration);
+				/*
+				 * TODO: for now go back to half frame position
+				 *	 so trailer can be found and key press
+				 *	 can be handled.
+				 */
+				data->count = 8;
+			}
+
+			else if (data->count != 8)
+				IR_dprintk(2, "received half frame pulse at index %d: %u\n",
+					data->count, ev.duration);
+			data->state = STATE_LEADER_PULSE;
+
+			return 0;
+
+		} else if (geq_margin(ev.duration, XMP_NIBBLE_PREFIX, XMP_UNIT)) {
+			/* store nibble raw data, decode after trailer */
+			if (data->count == 16) {
+				IR_dprintk(2, "to many pulses (%d) ignoring: %u\n",
+					data->count, ev.duration);
+				data->state = STATE_INACTIVE;
+				return -EINVAL;
+			}
+			data->durations[data->count] = ev.duration;
+			data->count++;
+			data->state = STATE_LEADER_PULSE;
+
+			return 0;
+
+		}
+
+		break;
+	}
+
+	IR_dprintk(1, "XMP decode failed at count %d state %d (%uus %s)\n",
+		   data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler xmp_handler = {
+	.protocols	= RC_BIT_XMP,
+	.decode		= ir_xmp_decode,
+};
+
+static int __init ir_xmp_decode_init(void)
+{
+	ir_raw_handler_register(&xmp_handler);
+
+	printk(KERN_INFO "IR XMP protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_xmp_decode_exit(void)
+{
+	ir_raw_handler_unregister(&xmp_handler);
+}
+
+module_init(ir_xmp_decode_init);
+module_exit(ir_xmp_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marcel Mol <marcel@mesa.nl>");
+MODULE_AUTHOR("MESA Consulting (http://www.mesa.nl)");
+MODULE_DESCRIPTION("XMP IR protocol decoder");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ite-cir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ite-cir.c
--- linux-libre-3.16-gnu/drivers/media/rc/ite-cir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ite-cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pde
 	/* set up ir-core props */
 	rdev->priv = itdev;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->open = ite_open;
 	rdev->close = ite_close;
 	rdev->s_idle = ite_s_idle;
@@ -1709,12 +1709,12 @@ static struct pnp_driver ite_driver = {
 	.shutdown	= ite_shutdown,
 };
 
-static int ite_init(void)
+static int __init ite_init(void)
 {
 	return pnp_register_driver(&ite_driver);
 }
 
-static void ite_exit(void)
+static void __exit ite_exit(void)
 {
 	pnp_unregister_driver(&ite_driver);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/rc/Kconfig
--- linux-libre-3.16-gnu/drivers/media/rc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -84,18 +84,6 @@ config IR_SONY_DECODER
 	   Enable this option if you have an infrared remote control which
 	   uses the Sony protocol, and you need software decoding support.
 
-config IR_RC5_SZ_DECODER
-	tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
-	depends on RC_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have IR with RC-5 (streamzap) protocol,
-	   and if the IR is decoded in software. (The Streamzap PC Remote
-	   uses an IR protocol that is almost standard RC-5, but not quite,
-	   as it uses an additional bit).
-
 config IR_SANYO_DECODER
 	tristate "Enable IR raw decoder for the Sanyo protocol"
 	depends on RC_CORE
@@ -125,6 +113,16 @@ config IR_MCE_KBD_DECODER
 	   Enable this option if you have a Microsoft Remote Keyboard for
 	   Windows Media Center Edition, which you would like to use with
 	   a raw IR receiver in your system.
+
+config IR_XMP_DECODER
+	tristate "Enable IR raw decoder for the XMP protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have IR with XMP protocol, and
+	   if the IR is decoded in software
 endif #RC_DECODERS
 
 menuconfig RC_DEVICES
@@ -343,4 +341,14 @@ config RC_ST
 
 	 If you're not sure, select N here.
 
+config IR_SUNXI
+    tristate "SUNXI IR remote control"
+    depends on RC_CORE
+    depends on ARCH_SUNXI
+    ---help---
+      Say Y if you want to use sunXi internal IR Controller
+
+      To compile this driver as a module, choose M here: the module will
+      be called sunxi-ir.
+
 endif #RC_DEVICES
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-ati-x10.c linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-ati-x10.c
--- linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-ati-x10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-ati-x10.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,42 @@
 #include <linux/module.h>
 #include <media/rc-map.h>
 
+/*
+ * Intended usage comments below are from vendor-supplied
+ * Source: ATI REMOTE WONDERâ„¢ Installation Guide
+ * http://www2.ati.com/manuals/remctrl.pdf
+ *
+ * Scancodes were in strict left-right, top-bottom order on the
+ * original ATI Remote Wonder, but were moved on later models.
+ *
+ * Keys A-F are intended to be user-programmable.
+ */
+
 static struct rc_map_table ati_x10[] = {
+	/* keyboard - Above the cursor pad */
+	{ 0x00, KEY_A },
+	{ 0x01, KEY_B },
+	{ 0x02, KEY_POWER },      /* Power */
+
+	{ 0x03, KEY_TV },         /* TV */
+	{ 0x04, KEY_DVD },        /* DVD */
+	{ 0x05, KEY_WWW },        /* WEB */
+	{ 0x06, KEY_BOOKMARKS },  /* "book": Open Media Library */
+	{ 0x07, KEY_EDIT },       /* "hand": Toggle left mouse button (grab) */
+
+	/* Mouse emulation pad goes here, handled by driver separately */
+
+	{ 0x09, KEY_VOLUMEDOWN }, /* VOL + */
+	{ 0x08, KEY_VOLUMEUP },   /* VOL - */
+	{ 0x0a, KEY_MUTE },       /* MUTE  */
+	{ 0x0b, KEY_CHANNELUP },  /* CH + */
+	{ 0x0c, KEY_CHANNELDOWN },/* CH - */
+
+	/*
+	 * We could use KEY_NUMERIC_x for these, but the X11 protocol
+	 * has problems with keycodes greater than 255, so avoid those high
+	 * keycodes in default maps.
+	 */
 	{ 0x0d, KEY_1 },
 	{ 0x0e, KEY_2 },
 	{ 0x0f, KEY_3 },
@@ -36,46 +71,45 @@ static struct rc_map_table ati_x10[] = {
 	{ 0x13, KEY_7 },
 	{ 0x14, KEY_8 },
 	{ 0x15, KEY_9 },
+	{ 0x16, KEY_MENU },       /* "menu": DVD root menu */
+				  /* KEY_NUMERIC_STAR? */
 	{ 0x17, KEY_0 },
-	{ 0x00, KEY_A },
-	{ 0x01, KEY_B },
+	{ 0x18, KEY_SETUP },      /* "check": DVD setup menu */
+				  /* KEY_NUMERIC_POUND? */
+
+	/* DVD navigation buttons */
 	{ 0x19, KEY_C },
+	{ 0x1a, KEY_UP },         /* up */
 	{ 0x1b, KEY_D },
-	{ 0x21, KEY_E },
-	{ 0x23, KEY_F },
 
-	{ 0x18, KEY_KPENTER },    /* "check" */
-	{ 0x16, KEY_MENU },       /* "menu" */
-	{ 0x02, KEY_POWER },      /* Power */
-	{ 0x03, KEY_TV },         /* TV */
-	{ 0x04, KEY_DVD },        /* DVD */
-	{ 0x05, KEY_WWW },        /* WEB */
-	{ 0x06, KEY_BOOKMARKS },  /* "book" */
-	{ 0x07, KEY_EDIT },       /* "hand" */
-	{ 0x1c, KEY_COFFEE },     /* "timer" */
-	{ 0x20, KEY_FRONT },      /* "max" */
+	{ 0x1c, KEY_PROPS },      /* "timer" Should be Data On Screen */
+				  /* Symbol is "circle nailed to box" */
 	{ 0x1d, KEY_LEFT },       /* left */
+	{ 0x1e, KEY_OK },         /* "OK" */
 	{ 0x1f, KEY_RIGHT },      /* right */
+	{ 0x20, KEY_SCREEN },     /* "max" (X11 warning: 0x177) */
+				  /* Should be AC View Toggle, but
+				     that's not in <input/input.h>.
+				     KEY_ZOOM (0x174)? */
+	{ 0x21, KEY_E },
 	{ 0x22, KEY_DOWN },       /* down */
-	{ 0x1a, KEY_UP },         /* up */
-	{ 0x1e, KEY_OK },         /* "OK" */
-	{ 0x09, KEY_VOLUMEDOWN }, /* VOL + */
-	{ 0x08, KEY_VOLUMEUP },   /* VOL - */
-	{ 0x0a, KEY_MUTE },       /* MUTE  */
-	{ 0x0b, KEY_CHANNELUP },  /* CH + */
-	{ 0x0c, KEY_CHANNELDOWN },/* CH - */
+	{ 0x23, KEY_F },
+	/* Play/stop/pause buttons */
+	{ 0x24, KEY_REWIND },     /* (<<) Rewind */
+	{ 0x25, KEY_PLAY },       /* ( >) Play (KEY_PLAYCD?) */
+	{ 0x26, KEY_FASTFORWARD }, /* (>>) Fast forward */
+
 	{ 0x27, KEY_RECORD },     /* ( o) red */
-	{ 0x25, KEY_PLAY },       /* ( >) */
-	{ 0x24, KEY_REWIND },     /* (<<) */
-	{ 0x26, KEY_FORWARD },    /* (>>) */
-	{ 0x28, KEY_STOP },       /* ([]) */
-	{ 0x29, KEY_PAUSE },      /* ('') */
-	{ 0x2b, KEY_PREVIOUS },   /* (<-) */
+	{ 0x28, KEY_STOPCD },     /* ([]) Stop  (KEY_STOP is something else!) */
+	{ 0x29, KEY_PAUSE },      /* ('') Pause (KEY_PAUSECD?) */
+
+	/* Extra keys, not on the original ATI remote */
 	{ 0x2a, KEY_NEXT },       /* (>+) */
-	{ 0x2d, KEY_INFO },       /* PLAYING */
+	{ 0x2b, KEY_PREVIOUS },   /* (<-) */
+	{ 0x2d, KEY_INFO },       /* PLAYING  (X11 warning: 0x166) */
 	{ 0x2e, KEY_HOME },       /* TOP */
 	{ 0x2f, KEY_END },        /* END */
-	{ 0x30, KEY_SELECT },     /* SELECT */
+	{ 0x30, KEY_SELECT },     /* SELECT  (X11 warning: 0x161) */
 };
 
 static struct rc_map_list ati_x10_map = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-behold.c linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-behold.c
--- linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-behold.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-behold.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,8 +30,8 @@ static struct rc_map_table behold[] = {
 	/*  0x1c            0x12  *
 	 *  TV/FM          POWER  *
 	 *                        */
-	{ 0x6b861c, KEY_TUNER },	/* XXX KEY_TV / KEY_RADIO */
-	{ 0x6b8612, KEY_POWER },
+	{ 0x866b1c, KEY_TUNER },	/* XXX KEY_TV / KEY_RADIO */
+	{ 0x866b12, KEY_POWER },
 
 	/*  0x01    0x02    0x03  *
 	 *   1       2       3    *
@@ -42,28 +42,28 @@ static struct rc_map_table behold[] = {
 	 *  0x07    0x08    0x09  *
 	 *   7       8       9    *
 	 *                        */
-	{ 0x6b8601, KEY_1 },
-	{ 0x6b8602, KEY_2 },
-	{ 0x6b8603, KEY_3 },
-	{ 0x6b8604, KEY_4 },
-	{ 0x6b8605, KEY_5 },
-	{ 0x6b8606, KEY_6 },
-	{ 0x6b8607, KEY_7 },
-	{ 0x6b8608, KEY_8 },
-	{ 0x6b8609, KEY_9 },
+	{ 0x866b01, KEY_1 },
+	{ 0x866b02, KEY_2 },
+	{ 0x866b03, KEY_3 },
+	{ 0x866b04, KEY_4 },
+	{ 0x866b05, KEY_5 },
+	{ 0x866b06, KEY_6 },
+	{ 0x866b07, KEY_7 },
+	{ 0x866b08, KEY_8 },
+	{ 0x866b09, KEY_9 },
 
 	/*  0x0a    0x00    0x17  *
 	 * RECALL    0      MODE  *
 	 *                        */
-	{ 0x6b860a, KEY_AGAIN },
-	{ 0x6b8600, KEY_0 },
-	{ 0x6b8617, KEY_MODE },
+	{ 0x866b0a, KEY_AGAIN },
+	{ 0x866b00, KEY_0 },
+	{ 0x866b17, KEY_MODE },
 
 	/*  0x14          0x10    *
 	 * ASPECT      FULLSCREEN *
 	 *                        */
-	{ 0x6b8614, KEY_SCREEN },
-	{ 0x6b8610, KEY_ZOOM },
+	{ 0x866b14, KEY_SCREEN },
+	{ 0x866b10, KEY_ZOOM },
 
 	/*          0x0b          *
 	 *           Up           *
@@ -74,17 +74,17 @@ static struct rc_map_table behold[] = {
 	 *         0x015          *
 	 *         Down           *
 	 *                        */
-	{ 0x6b860b, KEY_CHANNELUP },
-	{ 0x6b8618, KEY_VOLUMEDOWN },
-	{ 0x6b8616, KEY_OK },		/* XXX KEY_ENTER */
-	{ 0x6b860c, KEY_VOLUMEUP },
-	{ 0x6b8615, KEY_CHANNELDOWN },
+	{ 0x866b0b, KEY_CHANNELUP },
+	{ 0x866b18, KEY_VOLUMEDOWN },
+	{ 0x866b16, KEY_OK },		/* XXX KEY_ENTER */
+	{ 0x866b0c, KEY_VOLUMEUP },
+	{ 0x866b15, KEY_CHANNELDOWN },
 
 	/*  0x11            0x0d  *
 	 *  MUTE            INFO  *
 	 *                        */
-	{ 0x6b8611, KEY_MUTE },
-	{ 0x6b860d, KEY_INFO },
+	{ 0x866b11, KEY_MUTE },
+	{ 0x866b0d, KEY_INFO },
 
 	/*  0x0f    0x1b    0x1a  *
 	 * RECORD PLAY/PAUSE STOP *
@@ -93,26 +93,26 @@ static struct rc_map_table behold[] = {
 	 *TELETEXT  AUDIO  SOURCE *
 	 *           RED   YELLOW *
 	 *                        */
-	{ 0x6b860f, KEY_RECORD },
-	{ 0x6b861b, KEY_PLAYPAUSE },
-	{ 0x6b861a, KEY_STOP },
-	{ 0x6b860e, KEY_TEXT },
-	{ 0x6b861f, KEY_RED },	/*XXX KEY_AUDIO	*/
-	{ 0x6b861e, KEY_VIDEO },
+	{ 0x866b0f, KEY_RECORD },
+	{ 0x866b1b, KEY_PLAYPAUSE },
+	{ 0x866b1a, KEY_STOP },
+	{ 0x866b0e, KEY_TEXT },
+	{ 0x866b1f, KEY_RED },	/*XXX KEY_AUDIO	*/
+	{ 0x866b1e, KEY_VIDEO },
 
 	/*  0x1d   0x13     0x19  *
 	 * SLEEP  PREVIEW   DVB   *
 	 *         GREEN    BLUE  *
 	 *                        */
-	{ 0x6b861d, KEY_SLEEP },
-	{ 0x6b8613, KEY_GREEN },
-	{ 0x6b8619, KEY_BLUE },	/* XXX KEY_SAT	*/
+	{ 0x866b1d, KEY_SLEEP },
+	{ 0x866b13, KEY_GREEN },
+	{ 0x866b19, KEY_BLUE },	/* XXX KEY_SAT	*/
 
 	/*  0x58           0x5c   *
 	 * FREEZE        SNAPSHOT *
 	 *                        */
-	{ 0x6b8658, KEY_SLOW },
-	{ 0x6b865c, KEY_CAMERA },
+	{ 0x866b58, KEY_SLOW },
+	{ 0x866b5c, KEY_CAMERA },
 
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-nebula.c linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-nebula.c
--- linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-nebula.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-nebula.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,68 +14,68 @@
 #include <linux/module.h>
 
 static struct rc_map_table nebula[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x0a, KEY_TV },
-	{ 0x0b, KEY_AUX },
-	{ 0x0c, KEY_DVD },
-	{ 0x0d, KEY_POWER },
-	{ 0x0e, KEY_CAMERA },	/* labelled 'Picture' */
-	{ 0x0f, KEY_AUDIO },
-	{ 0x10, KEY_INFO },
-	{ 0x11, KEY_F13 },	/* 16:9 */
-	{ 0x12, KEY_F14 },	/* 14:9 */
-	{ 0x13, KEY_EPG },
-	{ 0x14, KEY_EXIT },
-	{ 0x15, KEY_MENU },
-	{ 0x16, KEY_UP },
-	{ 0x17, KEY_DOWN },
-	{ 0x18, KEY_LEFT },
-	{ 0x19, KEY_RIGHT },
-	{ 0x1a, KEY_ENTER },
-	{ 0x1b, KEY_CHANNELUP },
-	{ 0x1c, KEY_CHANNELDOWN },
-	{ 0x1d, KEY_VOLUMEUP },
-	{ 0x1e, KEY_VOLUMEDOWN },
-	{ 0x1f, KEY_RED },
-	{ 0x20, KEY_GREEN },
-	{ 0x21, KEY_YELLOW },
-	{ 0x22, KEY_BLUE },
-	{ 0x23, KEY_SUBTITLE },
-	{ 0x24, KEY_F15 },	/* AD */
-	{ 0x25, KEY_TEXT },
-	{ 0x26, KEY_MUTE },
-	{ 0x27, KEY_REWIND },
-	{ 0x28, KEY_STOP },
-	{ 0x29, KEY_PLAY },
-	{ 0x2a, KEY_FASTFORWARD },
-	{ 0x2b, KEY_F16 },	/* chapter */
-	{ 0x2c, KEY_PAUSE },
-	{ 0x2d, KEY_PLAY },
-	{ 0x2e, KEY_RECORD },
-	{ 0x2f, KEY_F17 },	/* picture in picture */
-	{ 0x30, KEY_KPPLUS },	/* zoom in */
-	{ 0x31, KEY_KPMINUS },	/* zoom out */
-	{ 0x32, KEY_F18 },	/* capture */
-	{ 0x33, KEY_F19 },	/* web */
-	{ 0x34, KEY_EMAIL },
-	{ 0x35, KEY_PHONE },
-	{ 0x36, KEY_PC },
+	{ 0x0000, KEY_0 },
+	{ 0x0001, KEY_1 },
+	{ 0x0002, KEY_2 },
+	{ 0x0003, KEY_3 },
+	{ 0x0004, KEY_4 },
+	{ 0x0005, KEY_5 },
+	{ 0x0006, KEY_6 },
+	{ 0x0007, KEY_7 },
+	{ 0x0008, KEY_8 },
+	{ 0x0009, KEY_9 },
+	{ 0x000a, KEY_TV },
+	{ 0x000b, KEY_AUX },
+	{ 0x000c, KEY_DVD },
+	{ 0x000d, KEY_POWER },
+	{ 0x000e, KEY_CAMERA },	/* labelled 'Picture' */
+	{ 0x000f, KEY_AUDIO },
+	{ 0x0010, KEY_INFO },
+	{ 0x0011, KEY_F13 },	/* 16:9 */
+	{ 0x0012, KEY_F14 },	/* 14:9 */
+	{ 0x0013, KEY_EPG },
+	{ 0x0014, KEY_EXIT },
+	{ 0x0015, KEY_MENU },
+	{ 0x0016, KEY_UP },
+	{ 0x0017, KEY_DOWN },
+	{ 0x0018, KEY_LEFT },
+	{ 0x0019, KEY_RIGHT },
+	{ 0x001a, KEY_ENTER },
+	{ 0x001b, KEY_CHANNELUP },
+	{ 0x001c, KEY_CHANNELDOWN },
+	{ 0x001d, KEY_VOLUMEUP },
+	{ 0x001e, KEY_VOLUMEDOWN },
+	{ 0x001f, KEY_RED },
+	{ 0x0020, KEY_GREEN },
+	{ 0x0021, KEY_YELLOW },
+	{ 0x0022, KEY_BLUE },
+	{ 0x0023, KEY_SUBTITLE },
+	{ 0x0024, KEY_F15 },	/* AD */
+	{ 0x0025, KEY_TEXT },
+	{ 0x0026, KEY_MUTE },
+	{ 0x0027, KEY_REWIND },
+	{ 0x0028, KEY_STOP },
+	{ 0x0029, KEY_PLAY },
+	{ 0x002a, KEY_FASTFORWARD },
+	{ 0x002b, KEY_F16 },	/* chapter */
+	{ 0x002c, KEY_PAUSE },
+	{ 0x002d, KEY_PLAY },
+	{ 0x002e, KEY_RECORD },
+	{ 0x002f, KEY_F17 },	/* picture in picture */
+	{ 0x0030, KEY_KPPLUS },	/* zoom in */
+	{ 0x0031, KEY_KPMINUS },	/* zoom out */
+	{ 0x0032, KEY_F18 },	/* capture */
+	{ 0x0033, KEY_F19 },	/* web */
+	{ 0x0034, KEY_EMAIL },
+	{ 0x0035, KEY_PHONE },
+	{ 0x0036, KEY_PC },
 };
 
 static struct rc_map_list nebula_map = {
 	.map = {
 		.scan    = nebula,
 		.size    = ARRAY_SIZE(nebula),
-		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.rc_type = RC_TYPE_RC5,
 		.name    = RC_MAP_NEBULA,
 	}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-streamzap.c linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-streamzap.c
--- linux-libre-3.16-gnu/drivers/media/rc/keymaps/rc-streamzap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/keymaps/rc-streamzap.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,9 +15,7 @@
 static struct rc_map_table streamzap[] = {
 /*
  * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
- * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
- * an additional RC-5-sz decoder is being deployed to support it, but it
- * may be possible to merge it back with the standard RC-5 decoder.
+ * bit in it.
  */
 	{ 0x28c0, KEY_NUMERIC_0 },
 	{ 0x28c1, KEY_NUMERIC_1 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/Makefile linux-libre-3.17-rc7-gnu/drivers/media/rc/Makefile
--- linux-libre-3.16-gnu/drivers/media/rc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,4 @@
-rc-core-objs	:= rc-main.o ir-raw.o
+rc-core-objs	:= rc-main.o rc-ir-raw.o
 
 obj-y += keymaps/
 
@@ -9,11 +9,11 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-d
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
-obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
 obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
 obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
 obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
+obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
 
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
@@ -32,4 +32,5 @@ obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-rec
 obj-$(CONFIG_IR_IGUANA) += iguanair.o
 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/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/mceusb.c linux-libre-3.17-rc7-gnu/drivers/media/rc/mceusb.c
--- linux-libre-3.16-gnu/drivers/media/rc/mceusb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/mceusb.c	2014-09-28 17:29:07.000000000 -0400
@@ -187,6 +187,7 @@
 #define VENDOR_CONEXANT		0x0572
 #define VENDOR_TWISTEDMELON	0x2596
 #define VENDOR_HAUPPAUGE	0x2040
+#define VENDOR_PCTV		0x2013
 
 enum mceusb_model_type {
 	MCE_GEN2 = 0,		/* Most boards */
@@ -240,7 +241,6 @@ static const struct mceusb_model mceusb_
 		 * remotes, but we should have something handy,
 		 * to allow testing it
 		 */
-		.rc_map = RC_MAP_HAUPPAUGE,
 		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
 	},
 	[CX_HYBRID_TV] = {
@@ -248,7 +248,6 @@ static const struct mceusb_model mceusb_
 		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
 	},
 	[HAUPPAUGE_CX_HYBRID_TV] = {
-		.rc_map = RC_MAP_HAUPPAUGE,
 		.no_tx = 1, /* eeprom says it has no tx */
 		.name = "Conexant Hybrid TV (cx231xx) MCE IR no TX",
 	},
@@ -396,6 +395,13 @@ static struct usb_device_id mceusb_dev_t
 	/* Hauppauge WINTV-HVR-HVR 930C-HD - based on cx231xx */
 	{ USB_DEVICE(VENDOR_HAUPPAUGE, 0xb130),
 	  .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+	{ USB_DEVICE(VENDOR_HAUPPAUGE, 0xb131),
+	  .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+	{ USB_DEVICE(VENDOR_PCTV, 0x0259),
+	  .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+	{ USB_DEVICE(VENDOR_PCTV, 0x025e),
+	  .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+
 	/* Terminating entry */
 	{ }
 };
@@ -1192,8 +1198,10 @@ static void mceusb_flash_led(struct mceu
 	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
 }
 
-static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
+static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir,
+					 struct usb_interface *intf)
 {
+	struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
 	struct device *dev = ir->dev;
 	struct rc_dev *rc;
 	int ret;
@@ -1219,7 +1227,7 @@ static struct rc_dev *mceusb_init_rc_dev
 	rc->dev.parent = dev;
 	rc->priv = ir;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rc, RC_BIT_ALL);
+	rc->allowed_protocols = RC_BIT_ALL;
 	rc->timeout = MS_TO_NS(100);
 	if (!ir->flags.no_tx) {
 		rc->s_tx_mask = mceusb_set_tx_mask;
@@ -1227,8 +1235,19 @@ static struct rc_dev *mceusb_init_rc_dev
 		rc->tx_ir = mceusb_tx_ir;
 	}
 	rc->driver_name = DRIVER_NAME;
-	rc->map_name = mceusb_model[ir->model].rc_map ?
-			mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE;
+
+	switch (le16_to_cpu(udev->descriptor.idVendor)) {
+	case VENDOR_HAUPPAUGE:
+		rc->map_name = RC_MAP_HAUPPAUGE;
+		break;
+	case VENDOR_PCTV:
+		rc->map_name = RC_MAP_PINNACLE_PCTV_HD;
+		break;
+	default:
+		rc->map_name = RC_MAP_RC6_MCE;
+	}
+	if (mceusb_model[ir->model].rc_map)
+		rc->map_name = mceusb_model[ir->model].rc_map;
 
 	ret = rc_register_device(rc);
 	if (ret < 0) {
@@ -1343,7 +1362,7 @@ static int mceusb_dev_probe(struct usb_i
 		snprintf(name + strlen(name), sizeof(name) - strlen(name),
 			 " %s", buf);
 
-	ir->rc = mceusb_init_rc_dev(ir);
+	ir->rc = mceusb_init_rc_dev(ir, intf);
 	if (!ir->rc)
 		goto rc_dev_fail;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/nuvoton-cir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/nuvoton-cir.c
--- linux-libre-3.16-gnu/drivers/media/rc/nuvoton-cir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/nuvoton-cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -1044,7 +1044,7 @@ static int nvt_probe(struct pnp_dev *pde
 	/* Set up the rc device */
 	rdev->priv = nvt;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->open = nvt_open;
 	rdev->close = nvt_close;
 	rdev->tx_ir = nvt_tx_ir;
@@ -1221,12 +1221,12 @@ static struct pnp_driver nvt_driver = {
 	.shutdown	= nvt_shutdown,
 };
 
-static int nvt_init(void)
+static int __init nvt_init(void)
 {
 	return pnp_register_driver(&nvt_driver);
 }
 
-static void nvt_exit(void)
+static void __exit nvt_exit(void)
 {
 	pnp_unregister_driver(&nvt_driver);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/rc-core-priv.h linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-core-priv.h
--- linux-libre-3.16-gnu/drivers/media/rc/rc-core-priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-core-priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ struct ir_raw_event_ctrl {
 		int state;
 		u32 bits;
 		unsigned count;
-		unsigned wanted_bits;
+		bool is_rc5x;
 	} rc5;
 	struct rc6_dec {
 		int state;
@@ -77,12 +77,6 @@ struct ir_raw_event_ctrl {
 		bool first;
 		bool toggle;
 	} jvc;
-	struct rc5_sz_dec {
-		int state;
-		u32 bits;
-		unsigned count;
-		unsigned wanted_bits;
-	} rc5_sz;
 	struct sanyo_dec {
 		int state;
 		unsigned count;
@@ -116,6 +110,11 @@ struct ir_raw_event_ctrl {
 		bool send_timeout_reports;
 
 	} lirc;
+	struct xmp_dec {
+		int state;
+		unsigned count;
+		u32 durations[16];
+	} xmp;
 };
 
 /* macros for IR decoders */
@@ -231,5 +230,12 @@ static inline void load_mce_kbd_decode(v
 static inline void load_lirc_codec(void) { }
 #endif
 
+/* from ir-xmp-decoder.c */
+#ifdef CONFIG_IR_XMP_DECODER_MODULE
+#define load_xmp_decode()      request_module_nowait("ir-xmp-decoder")
+#else
+static inline void load_xmp_decode(void) { }
+#endif
+
 
 #endif /* _RC_CORE_PRIV */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/rc-ir-raw.c linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-ir-raw.c
--- linux-libre-3.16-gnu/drivers/media/rc/rc-ir-raw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-ir-raw.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,370 @@
+/* rc-ir-raw.c - handle IR pulse/space events
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab
+ *
+ * This program is free software; 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/export.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/freezer.h>
+#include "rc-core-priv.h"
+
+/* Define the max number of pulse/space transitions to buffer */
+#define MAX_IR_EVENT_SIZE      512
+
+/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
+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 u64 available_protocols;
+
+static int ir_raw_event_thread(void *data)
+{
+	struct ir_raw_event ev;
+	struct ir_raw_handler *handler;
+	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
+	int retval;
+
+	while (!kthread_should_stop()) {
+
+		spin_lock_irq(&raw->lock);
+		retval = kfifo_len(&raw->kfifo);
+
+		if (retval < sizeof(ev)) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
+			spin_unlock_irq(&raw->lock);
+			schedule();
+			continue;
+		}
+
+		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
+		spin_unlock_irq(&raw->lock);
+
+		mutex_lock(&ir_raw_handler_lock);
+		list_for_each_entry(handler, &ir_raw_handler_list, list)
+			handler->decode(raw->dev, ev);
+		raw->prev_ev = ev;
+		mutex_unlock(&ir_raw_handler_lock);
+	}
+
+	return 0;
+}
+
+/**
+ * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
+ * @dev:	the struct rc_dev device descriptor
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This routine (which may be called from an interrupt context) stores a
+ * pulse/space duration for the raw ir decoding state machines. Pulses are
+ * signalled as positive values and spaces as negative values. A zero value
+ * will reset the decoding state machines.
+ */
+int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
+{
+	if (!dev->raw)
+		return -EINVAL;
+
+	IR_dprintk(2, "sample: (%05dus %s)\n",
+		   TO_US(ev->duration), TO_STR(ev->pulse));
+
+	if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store);
+
+/**
+ * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
+ * @dev:	the struct rc_dev device descriptor
+ * @type:	the type of the event that has occurred
+ *
+ * This routine (which may be called from an interrupt context) is used to
+ * store the beginning of an ir pulse or space (or the start/end of ir
+ * reception) for the raw ir decoding state machines. This is used by
+ * hardware which does not provide durations directly but only interrupts
+ * (or similar events) on state change.
+ */
+int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
+{
+	ktime_t			now;
+	s64			delta; /* ns */
+	DEFINE_IR_RAW_EVENT(ev);
+	int			rc = 0;
+	int			delay;
+
+	if (!dev->raw)
+		return -EINVAL;
+
+	now = ktime_get();
+	delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
+	delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
+
+	/* Check for a long duration since last event or if we're
+	 * being called for the first time, note that delta can't
+	 * possibly be negative.
+	 */
+	if (delta > delay || !dev->raw->last_type)
+		type |= IR_START_EVENT;
+	else
+		ev.duration = delta;
+
+	if (type & IR_START_EVENT)
+		ir_raw_event_reset(dev);
+	else if (dev->raw->last_type & IR_SPACE) {
+		ev.pulse = false;
+		rc = ir_raw_event_store(dev, &ev);
+	} else if (dev->raw->last_type & IR_PULSE) {
+		ev.pulse = true;
+		rc = ir_raw_event_store(dev, &ev);
+	} else
+		return 0;
+
+	dev->raw->last_event = now;
+	dev->raw->last_type = type;
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
+
+/**
+ * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
+ * @dev:	the struct rc_dev device descriptor
+ * @type:	the type of the event that has occurred
+ *
+ * This routine (which may be called from an interrupt context) works
+ * in similar manner to ir_raw_event_store_edge.
+ * This routine is intended for devices with limited internal buffer
+ * It automerges samples of same type, and handles timeouts. Returns non-zero
+ * if the event was added, and zero if the event was ignored due to idle
+ * processing.
+ */
+int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
+{
+	if (!dev->raw)
+		return -EINVAL;
+
+	/* Ignore spaces in idle mode */
+	if (dev->idle && !ev->pulse)
+		return 0;
+	else if (dev->idle)
+		ir_raw_event_set_idle(dev, false);
+
+	if (!dev->raw->this_ev.duration)
+		dev->raw->this_ev = *ev;
+	else if (ev->pulse == dev->raw->this_ev.pulse)
+		dev->raw->this_ev.duration += ev->duration;
+	else {
+		ir_raw_event_store(dev, &dev->raw->this_ev);
+		dev->raw->this_ev = *ev;
+	}
+
+	/* Enter idle mode if nessesary */
+	if (!ev->pulse && dev->timeout &&
+	    dev->raw->this_ev.duration >= dev->timeout)
+		ir_raw_event_set_idle(dev, true);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
+
+/**
+ * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not
+ * @dev:	the struct rc_dev device descriptor
+ * @idle:	whether the device is idle or not
+ */
+void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
+{
+	if (!dev->raw)
+		return;
+
+	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
+
+	if (idle) {
+		dev->raw->this_ev.timeout = true;
+		ir_raw_event_store(dev, &dev->raw->this_ev);
+		init_ir_raw_event(&dev->raw->this_ev);
+	}
+
+	if (dev->s_idle)
+		dev->s_idle(dev, idle);
+
+	dev->idle = idle;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
+
+/**
+ * ir_raw_event_handle() - schedules the decoding of stored ir data
+ * @dev:	the struct rc_dev device descriptor
+ *
+ * This routine will tell rc-core to start decoding stored ir data.
+ */
+void ir_raw_event_handle(struct rc_dev *dev)
+{
+	unsigned long flags;
+
+	if (!dev->raw)
+		return;
+
+	spin_lock_irqsave(&dev->raw->lock, flags);
+	wake_up_process(dev->raw->thread);
+	spin_unlock_irqrestore(&dev->raw->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_handle);
+
+/* used internally by the sysfs interface */
+u64
+ir_raw_get_allowed_protocols(void)
+{
+	u64 protocols;
+	mutex_lock(&ir_raw_handler_lock);
+	protocols = available_protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+	return protocols;
+}
+
+static int change_protocol(struct rc_dev *dev, u64 *rc_type)
+{
+	/* the caller will update dev->enabled_protocols */
+	return 0;
+}
+
+/*
+ * Used to (un)register raw event clients
+ */
+int ir_raw_event_register(struct rc_dev *dev)
+{
+	int rc;
+	struct ir_raw_handler *handler;
+
+	if (!dev)
+		return -EINVAL;
+
+	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
+	if (!dev->raw)
+		return -ENOMEM;
+
+	dev->raw->dev = dev;
+	dev->enabled_protocols = ~0;
+	dev->change_protocol = change_protocol;
+	rc = kfifo_alloc(&dev->raw->kfifo,
+			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
+			 GFP_KERNEL);
+	if (rc < 0)
+		goto out;
+
+	spin_lock_init(&dev->raw->lock);
+	dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
+				       "rc%ld", dev->devno);
+
+	if (IS_ERR(dev->raw->thread)) {
+		rc = PTR_ERR(dev->raw->thread);
+		goto out;
+	}
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_add_tail(&dev->raw->list, &ir_raw_client_list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_register)
+			handler->raw_register(dev);
+	mutex_unlock(&ir_raw_handler_lock);
+
+	return 0;
+
+out:
+	kfree(dev->raw);
+	dev->raw = NULL;
+	return rc;
+}
+
+void ir_raw_event_unregister(struct rc_dev *dev)
+{
+	struct ir_raw_handler *handler;
+
+	if (!dev || !dev->raw)
+		return;
+
+	kthread_stop(dev->raw->thread);
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_del(&dev->raw->list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_unregister)
+			handler->raw_unregister(dev);
+	mutex_unlock(&ir_raw_handler_lock);
+
+	kfifo_free(&dev->raw->kfifo);
+	kfree(dev->raw);
+	dev->raw = NULL;
+}
+
+/*
+ * Extension interface - used to register the IR decoders
+ */
+
+int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
+{
+	struct ir_raw_event_ctrl *raw;
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
+	if (ir_raw_handler->raw_register)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_register(raw->dev);
+	available_protocols |= ir_raw_handler->protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ir_raw_handler_register);
+
+void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
+{
+	struct ir_raw_event_ctrl *raw;
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_del(&ir_raw_handler->list);
+	if (ir_raw_handler->raw_unregister)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_unregister(raw->dev);
+	available_protocols &= ~ir_raw_handler->protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+}
+EXPORT_SYMBOL(ir_raw_handler_unregister);
+
+void ir_raw_init(void)
+{
+	/* Load the decoder modules */
+
+	load_nec_decode();
+	load_rc5_decode();
+	load_rc6_decode();
+	load_jvc_decode();
+	load_sony_decode();
+	load_sanyo_decode();
+	load_sharp_decode();
+	load_mce_kbd_decode();
+	load_lirc_codec();
+	load_xmp_decode();
+
+	/* If needed, we may later add some init code. In this case,
+	   it is needed to change the CONFIG_MODULE test at rc-core.h
+	 */
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/rc-loopback.c linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-loopback.c
--- linux-libre-3.16-gnu/drivers/media/rc/rc-loopback.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-loopback.c	2014-09-28 17:29:07.000000000 -0400
@@ -195,7 +195,7 @@ static int __init loop_init(void)
 	rc->map_name		= RC_MAP_EMPTY;
 	rc->priv		= &loopdev;
 	rc->driver_type		= RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rc, RC_BIT_ALL);
+	rc->allowed_protocols	= RC_BIT_ALL;
 	rc->timeout		= 100 * 1000 * 1000; /* 100 ms */
 	rc->min_timeout		= 1;
 	rc->max_timeout		= UINT_MAX;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/rc-main.c linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-main.c
--- linux-libre-3.16-gnu/drivers/media/rc/rc-main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/rc-main.c	2014-09-28 17:29:07.000000000 -0400
@@ -285,8 +285,8 @@ static unsigned int ir_establish_scancod
 	 * IR tables from other remotes. So, we support specifying a mask to
 	 * indicate the valid bits of the scancodes.
 	 */
-	if (dev->scanmask)
-		scancode &= dev->scanmask;
+	if (dev->scancode_mask)
+		scancode &= dev->scancode_mask;
 
 	/* First check if we already have a mapping for this ir command */
 	for (i = 0; i < rc_map->len; i++) {
@@ -623,6 +623,7 @@ EXPORT_SYMBOL_GPL(rc_repeat);
 /**
  * ir_do_keydown() - internal function to process a keypress
  * @dev:	the struct rc_dev descriptor of the device
+ * @protocol:	the protocol of the keypress
  * @scancode:   the scancode of the keypress
  * @keycode:    the keycode of the keypress
  * @toggle:     the toggle value of the keypress
@@ -630,12 +631,13 @@ EXPORT_SYMBOL_GPL(rc_repeat);
  * This function is used internally to register a keypress, it must be
  * called with keylock held.
  */
-static void ir_do_keydown(struct rc_dev *dev, int scancode,
-			  u32 keycode, u8 toggle)
+static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
+			  u32 scancode, u32 keycode, u8 toggle)
 {
 	bool new_event = (!dev->keypressed		 ||
+			  dev->last_protocol != protocol ||
 			  dev->last_scancode != scancode ||
-			  dev->last_toggle != toggle);
+			  dev->last_toggle   != toggle);
 
 	if (new_event && dev->keypressed)
 		ir_do_keyup(dev, false);
@@ -645,13 +647,14 @@ static void ir_do_keydown(struct rc_dev
 	if (new_event && keycode != KEY_RESERVED) {
 		/* Register a keypress */
 		dev->keypressed = true;
+		dev->last_protocol = protocol;
 		dev->last_scancode = scancode;
 		dev->last_toggle = toggle;
 		dev->last_keycode = keycode;
 
 		IR_dprintk(1, "%s: key down event, "
-			   "key 0x%04x, scancode 0x%04x\n",
-			   dev->input_name, keycode, scancode);
+			   "key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
+			   dev->input_name, keycode, protocol, scancode);
 		input_report_key(dev->input_dev, keycode, 1);
 
 		led_trigger_event(led_feedback, LED_FULL);
@@ -663,20 +666,21 @@ static void ir_do_keydown(struct rc_dev
 /**
  * rc_keydown() - generates input event for a key press
  * @dev:	the struct rc_dev descriptor of the device
- * @scancode:   the scancode that we're seeking
+ * @protocol:	the protocol for the keypress
+ * @scancode:	the scancode for the keypress
  * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
  *              support toggle values, this should be set to zero)
  *
  * This routine is used to signal that a key has been pressed on the
  * remote control.
  */
-void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown(struct rc_dev *dev, enum rc_type protocol, u32 scancode, u8 toggle)
 {
 	unsigned long flags;
 	u32 keycode = rc_g_keycode_from_table(dev, scancode);
 
 	spin_lock_irqsave(&dev->keylock, flags);
-	ir_do_keydown(dev, scancode, keycode, toggle);
+	ir_do_keydown(dev, protocol, scancode, keycode, toggle);
 
 	if (dev->keypressed) {
 		dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
@@ -690,20 +694,22 @@ EXPORT_SYMBOL_GPL(rc_keydown);
  * rc_keydown_notimeout() - generates input event for a key press without
  *                          an automatic keyup event at a later time
  * @dev:	the struct rc_dev descriptor of the device
- * @scancode:   the scancode that we're seeking
+ * @protocol:	the protocol for the keypress
+ * @scancode:	the scancode for the keypress
  * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
  *              support toggle values, this should be set to zero)
  *
  * This routine is used to signal that a key has been pressed on the
  * remote control. The driver must manually call rc_keyup() at a later stage.
  */
-void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol,
+			  u32 scancode, u8 toggle)
 {
 	unsigned long flags;
 	u32 keycode = rc_g_keycode_from_table(dev, scancode);
 
 	spin_lock_irqsave(&dev->keylock, flags);
-	ir_do_keydown(dev, scancode, keycode, toggle);
+	ir_do_keydown(dev, protocol, scancode, keycode, toggle);
 	spin_unlock_irqrestore(&dev->keylock, flags);
 }
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
@@ -794,6 +800,7 @@ static struct {
 	{ RC_BIT_SHARP,		"sharp"		},
 	{ RC_BIT_MCE_KBD,	"mce_kbd"	},
 	{ RC_BIT_LIRC,		"lirc"		},
+	{ RC_BIT_XMP,		"xmp"		},
 };
 
 /**
@@ -824,7 +831,7 @@ struct rc_filter_attribute {
 /**
  * show_protocols() - shows the current/wakeup IR protocol(s)
  * @device:	the device descriptor
- * @mattr:	the device attribute struct (unused)
+ * @mattr:	the device attribute struct
  * @buf:	a pointer to the output buffer
  *
  * This routine is a callback routine for input read the IR protocol type(s).
@@ -850,20 +857,20 @@ static ssize_t show_protocols(struct dev
 
 	mutex_lock(&dev->lock);
 
-	enabled = dev->enabled_protocols[fattr->type];
-	if (dev->driver_type == RC_DRIVER_SCANCODE ||
-	    fattr->type == RC_FILTER_WAKEUP)
-		allowed = dev->allowed_protocols[fattr->type];
-	else if (dev->raw)
-		allowed = ir_raw_get_allowed_protocols();
-	else {
-		mutex_unlock(&dev->lock);
-		return -ENODEV;
+	if (fattr->type == RC_FILTER_NORMAL) {
+		enabled = dev->enabled_protocols;
+		allowed = dev->allowed_protocols;
+		if (dev->raw && !allowed)
+			allowed = ir_raw_get_allowed_protocols();
+	} else {
+		enabled = dev->enabled_wakeup_protocols;
+		allowed = dev->allowed_wakeup_protocols;
 	}
 
-	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
-		   (long long)allowed,
-		   (long long)enabled);
+	mutex_unlock(&dev->lock);
+
+	IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
+		   __func__, (long long)allowed, (long long)enabled);
 
 	for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
 		if (allowed & enabled & proto_names[i].type)
@@ -879,62 +886,29 @@ static ssize_t show_protocols(struct dev
 		tmp--;
 	*tmp = '\n';
 
-	mutex_unlock(&dev->lock);
-
 	return tmp + 1 - buf;
 }
 
 /**
- * store_protocols() - changes the current/wakeup IR protocol(s)
- * @device:	the device descriptor
- * @mattr:	the device attribute struct (unused)
- * @buf:	a pointer to the input buffer
- * @len:	length of the input buffer
+ * parse_protocol_change() - parses a protocol change request
+ * @protocols:	pointer to the bitmask of current protocols
+ * @buf:	pointer to the buffer with a list of changes
  *
- * This routine is for changing the IR protocol type.
- * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
- * Writing "+proto" will add a protocol to the list of enabled protocols.
- * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "+proto" will add a protocol to the protocol mask.
+ * Writing "-proto" will remove a protocol from protocol mask.
  * Writing "proto" will enable only "proto".
  * Writing "none" will disable all protocols.
- * Returns -EINVAL if an invalid protocol combination or unknown protocol name
- * is used, otherwise @len.
- *
- * dev->lock is taken to guard against races between device
- * registration, store_protocols and show_protocols.
+ * Returns the number of changes performed or a negative error code.
  */
-static ssize_t store_protocols(struct device *device,
-			       struct device_attribute *mattr,
-			       const char *data,
-			       size_t len)
+static int parse_protocol_change(u64 *protocols, const char *buf)
 {
-	struct rc_dev *dev = to_rc_dev(device);
-	struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
-	bool enable, disable;
 	const char *tmp;
-	u64 old_type, type;
+	unsigned count = 0;
+	bool enable, disable;
 	u64 mask;
-	int rc, i, count = 0;
-	ssize_t ret;
-	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
-	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
-	struct rc_scancode_filter local_filter, *filter;
-
-	/* Device is being removed */
-	if (!dev)
-		return -EINVAL;
-
-	mutex_lock(&dev->lock);
-
-	if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
-		IR_dprintk(1, "Protocol switching not supported\n");
-		ret = -EINVAL;
-		goto out;
-	}
-	old_type = dev->enabled_protocols[fattr->type];
-	type = old_type;
+	int i;
 
-	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
+	while ((tmp = strsep((char **)&buf, " \n")) != NULL) {
 		if (!*tmp)
 			break;
 
@@ -960,76 +934,124 @@ static ssize_t store_protocols(struct de
 
 		if (i == ARRAY_SIZE(proto_names)) {
 			IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 
 		count++;
 
 		if (enable)
-			type |= mask;
+			*protocols |= mask;
 		else if (disable)
-			type &= ~mask;
+			*protocols &= ~mask;
 		else
-			type = mask;
+			*protocols = mask;
 	}
 
 	if (!count) {
 		IR_dprintk(1, "Protocol not specified\n");
-		ret = -EINVAL;
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+/**
+ * store_protocols() - changes the current/wakeup IR protocol(s)
+ * @device:	the device descriptor
+ * @mattr:	the device attribute struct
+ * @buf:	a pointer to the input buffer
+ * @len:	length of the input buffer
+ *
+ * This routine is for changing the IR protocol type.
+ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
+ * See parse_protocol_change() for the valid commands.
+ * Returns @len on success or a negative error code.
+ *
+ * dev->lock is taken to guard against races between device
+ * registration, store_protocols and show_protocols.
+ */
+static ssize_t store_protocols(struct device *device,
+			       struct device_attribute *mattr,
+			       const char *buf, size_t len)
+{
+	struct rc_dev *dev = to_rc_dev(device);
+	struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
+	u64 *current_protocols;
+	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
+	struct rc_scancode_filter *filter;
+	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+	u64 old_protocols, new_protocols;
+	ssize_t rc;
+
+	/* Device is being removed */
+	if (!dev)
+		return -EINVAL;
+
+	if (fattr->type == RC_FILTER_NORMAL) {
+		IR_dprintk(1, "Normal protocol change requested\n");
+		current_protocols = &dev->enabled_protocols;
+		change_protocol = dev->change_protocol;
+		filter = &dev->scancode_filter;
+		set_filter = dev->s_filter;
+	} else {
+		IR_dprintk(1, "Wakeup protocol change requested\n");
+		current_protocols = &dev->enabled_wakeup_protocols;
+		change_protocol = dev->change_wakeup_protocol;
+		filter = &dev->scancode_wakeup_filter;
+		set_filter = dev->s_wakeup_filter;
+	}
+
+	if (!change_protocol) {
+		IR_dprintk(1, "Protocol switching not supported\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->lock);
+
+	old_protocols = *current_protocols;
+	new_protocols = old_protocols;
+	rc = parse_protocol_change(&new_protocols, buf);
+	if (rc < 0)
+		goto out;
+
+	rc = change_protocol(dev, &new_protocols);
+	if (rc < 0) {
+		IR_dprintk(1, "Error setting protocols to 0x%llx\n",
+			   (long long)new_protocols);
 		goto out;
 	}
 
-	change_protocol = (fattr->type == RC_FILTER_NORMAL)
-		? dev->change_protocol : dev->change_wakeup_protocol;
-	if (change_protocol) {
-		rc = change_protocol(dev, &type);
-		if (rc < 0) {
-			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
-				   (long long)type);
-			ret = -EINVAL;
-			goto out;
-		}
+	if (new_protocols == old_protocols) {
+		rc = len;
+		goto out;
 	}
 
-	dev->enabled_protocols[fattr->type] = type;
-	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
-		   (long long)type);
+	*current_protocols = new_protocols;
+	IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);
 
 	/*
 	 * If the protocol is changed the filter needs updating.
 	 * Try setting the same filter with the new protocol (if any).
 	 * Fall back to clearing the filter.
 	 */
-	filter = &dev->scancode_filters[fattr->type];
-	set_filter = (fattr->type == RC_FILTER_NORMAL)
-		? dev->s_filter : dev->s_wakeup_filter;
+	if (set_filter && filter->mask) {
+		if (new_protocols)
+			rc = set_filter(dev, filter);
+		else
+			rc = -1;
 
-	if (set_filter && old_type != type && filter->mask) {
-		local_filter = *filter;
-		if (!type) {
-			/* no protocol => clear filter */
-			ret = -1;
-		} else {
-			/* hardware filtering => try setting, otherwise clear */
-			ret = set_filter(dev, &local_filter);
-		}
-		if (ret < 0) {
-			/* clear the filter */
-			local_filter.data = 0;
-			local_filter.mask = 0;
-			set_filter(dev, &local_filter);
+		if (rc < 0) {
+			filter->data = 0;
+			filter->mask = 0;
+			set_filter(dev, filter);
 		}
-
-		/* commit the new filter */
-		*filter = local_filter;
 	}
 
-	ret = len;
+	rc = len;
 
 out:
 	mutex_unlock(&dev->lock);
-	return ret;
+	return rc;
 }
 
 /**
@@ -1055,20 +1077,23 @@ static ssize_t show_filter(struct device
 {
 	struct rc_dev *dev = to_rc_dev(device);
 	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
+	struct rc_scancode_filter *filter;
 	u32 val;
 
 	/* Device is being removed */
 	if (!dev)
 		return -EINVAL;
 
+	if (fattr->type == RC_FILTER_NORMAL)
+		filter = &dev->scancode_filter;
+	else
+		filter = &dev->scancode_wakeup_filter;
+
 	mutex_lock(&dev->lock);
-	if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
-	    (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
-		val = 0;
-	else if (fattr->mask)
-		val = dev->scancode_filters[fattr->type].mask;
+	if (fattr->mask)
+		val = filter->mask;
 	else
-		val = dev->scancode_filters[fattr->type].data;
+		val = filter->data;
 	mutex_unlock(&dev->lock);
 
 	return sprintf(buf, "%#x\n", val);
@@ -1095,15 +1120,15 @@ static ssize_t show_filter(struct device
  */
 static ssize_t store_filter(struct device *device,
 			    struct device_attribute *attr,
-			    const char *buf,
-			    size_t count)
+			    const char *buf, size_t len)
 {
 	struct rc_dev *dev = to_rc_dev(device);
 	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
-	struct rc_scancode_filter local_filter, *filter;
+	struct rc_scancode_filter new_filter, *filter;
 	int ret;
 	unsigned long val;
 	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+	u64 *enabled_protocols;
 
 	/* Device is being removed */
 	if (!dev)
@@ -1113,38 +1138,42 @@ static ssize_t store_filter(struct devic
 	if (ret < 0)
 		return ret;
 
-	/* Can the scancode filter be set? */
-	set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter :
-							 dev->s_wakeup_filter;
+	if (fattr->type == RC_FILTER_NORMAL) {
+		set_filter = dev->s_filter;
+		enabled_protocols = &dev->enabled_protocols;
+		filter = &dev->scancode_filter;
+	} else {
+		set_filter = dev->s_wakeup_filter;
+		enabled_protocols = &dev->enabled_wakeup_protocols;
+		filter = &dev->scancode_wakeup_filter;
+	}
+
 	if (!set_filter)
 		return -EINVAL;
 
 	mutex_lock(&dev->lock);
 
-	/* Tell the driver about the new filter */
-	filter = &dev->scancode_filters[fattr->type];
-	local_filter = *filter;
+	new_filter = *filter;
 	if (fattr->mask)
-		local_filter.mask = val;
+		new_filter.mask = val;
 	else
-		local_filter.data = val;
+		new_filter.data = val;
 
-	if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
+	if (!*enabled_protocols && val) {
 		/* refuse to set a filter unless a protocol is enabled */
 		ret = -EINVAL;
 		goto unlock;
 	}
 
-	ret = set_filter(dev, &local_filter);
+	ret = set_filter(dev, &new_filter);
 	if (ret < 0)
 		goto unlock;
 
-	/* Success, commit the new filter */
-	*filter = local_filter;
+	*filter = new_filter;
 
 unlock:
 	mutex_unlock(&dev->lock);
-	return (ret < 0) ? ret : count;
+	return (ret < 0) ? ret : len;
 }
 
 static void rc_dev_release(struct device *device)
@@ -1315,7 +1344,7 @@ int rc_register_device(struct rc_dev *de
 	dev->dev.groups = dev->sysfs_groups;
 	dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp;
 	if (dev->s_filter)
-		dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;	
+		dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
 	if (dev->s_wakeup_filter)
 		dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
 	if (dev->change_wakeup_protocol)
@@ -1395,7 +1424,7 @@ int rc_register_device(struct rc_dev *de
 		rc = dev->change_protocol(dev, &rc_type);
 		if (rc < 0)
 			goto out_raw;
-		dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type;
+		dev->enabled_protocols = rc_type;
 	}
 
 	mutex_unlock(&dev->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/redrat3.c linux-libre-3.17-rc7-gnu/drivers/media/rc/redrat3.c
--- linux-libre-3.16-gnu/drivers/media/rc/redrat3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/redrat3.c	2014-09-28 17:29:07.000000000 -0400
@@ -878,7 +878,7 @@ static struct rc_dev *redrat3_init_rc_de
 	rc->dev.parent = dev;
 	rc->priv = rr3;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rc, RC_BIT_ALL);
+	rc->allowed_protocols = RC_BIT_ALL;
 	rc->timeout = US_TO_NS(2750);
 	rc->tx_ir = redrat3_transmit_ir;
 	rc->s_tx_carrier = redrat3_set_tx_carrier;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/st_rc.c linux-libre-3.17-rc7-gnu/drivers/media/rc/st_rc.c
--- linux-libre-3.16-gnu/drivers/media/rc/st_rc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/st_rc.c	2014-09-28 17:29:07.000000000 -0400
@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_d
 	st_rc_hardware_init(rc_dev);
 
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	/* rx sampling rate is 10Mhz */
 	rdev->rx_resolution = 100;
 	rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/streamzap.c linux-libre-3.17-rc7-gnu/drivers/media/rc/streamzap.c
--- linux-libre-3.16-gnu/drivers/media/rc/streamzap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/streamzap.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,13 +63,6 @@ MODULE_DEVICE_TABLE(usb, streamzap_table
 /* number of samples buffered */
 #define SZ_BUF_LEN 128
 
-/* from ir-rc5-sz-decoder.c */
-#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
-#define load_rc5_sz_decode()    request_module("ir-rc5-sz-decoder")
-#else
-#define load_rc5_sz_decode()    {}
-#endif
-
 enum StreamzapDecoderState {
 	PulseSpace,
 	FullPulse,
@@ -316,7 +309,7 @@ static struct rc_dev *streamzap_init_rc_
 	rdev->dev.parent = dev;
 	rdev->priv = sz;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+	rdev->allowed_protocols = RC_BIT_ALL;
 	rdev->driver_name = DRIVER_NAME;
 	rdev->map_name = RC_MAP_STREAMZAP;
 
@@ -452,9 +445,6 @@ static int streamzap_probe(struct usb_in
 	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
 		 usbdev->bus->busnum, usbdev->devnum);
 
-	/* Load the streamzap not-quite-rc5 decoder too */
-	load_rc5_sz_decode();
-
 	return 0;
 
 rc_dev_fail:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/sunxi-cir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/sunxi-cir.c
--- linux-libre-3.16-gnu/drivers/media/rc/sunxi-cir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/sunxi-cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,318 @@
+/*
+ * Driver for Allwinner sunXi IR controller
+ *
+ * Copyright (C) 2014 Alexsey Shestacov <wingrime@linux-sunxi.org>
+ * Copyright (C) 2014 Alexander Bersenev <bay@hackerdom.ru>
+ *
+ * Based on sun5i-ir.c:
+ * Copyright (C) 2007-2012 Daniel Wang
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <media/rc-core.h>
+
+#define SUNXI_IR_DEV "sunxi-ir"
+
+/* Registers */
+/* IR Control */
+#define SUNXI_IR_CTL_REG      0x00
+/* Global Enable */
+#define REG_CTL_GEN			BIT(0)
+/* RX block enable */
+#define REG_CTL_RXEN			BIT(1)
+/* CIR mode */
+#define REG_CTL_MD			(BIT(4) | BIT(5))
+
+/* Rx Config */
+#define SUNXI_IR_RXCTL_REG    0x10
+/* Pulse Polarity Invert flag */
+#define REG_RXCTL_RPPI			BIT(2)
+
+/* Rx Data */
+#define SUNXI_IR_RXFIFO_REG   0x20
+
+/* Rx Interrupt Enable */
+#define SUNXI_IR_RXINT_REG    0x2C
+/* Rx FIFO Overflow */
+#define REG_RXINT_ROI_EN		BIT(0)
+/* Rx Packet End */
+#define REG_RXINT_RPEI_EN		BIT(1)
+/* Rx FIFO Data Available */
+#define REG_RXINT_RAI_EN		BIT(4)
+
+/* Rx FIFO available byte level */
+#define REG_RXINT_RAL(val)    (((val) << 8) & (GENMASK(11, 8)))
+
+/* Rx Interrupt Status */
+#define SUNXI_IR_RXSTA_REG    0x30
+/* RX FIFO Get Available Counter */
+#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0)))
+/* Clear all interrupt status value */
+#define REG_RXSTA_CLEARALL    0xff
+
+/* IR Sample Config */
+#define SUNXI_IR_CIR_REG      0x34
+/* CIR_REG register noise threshold */
+#define REG_CIR_NTHR(val)    (((val) << 2) & (GENMASK(7, 2)))
+/* CIR_REG register idle threshold */
+#define REG_CIR_ITHR(val)    (((val) << 8) & (GENMASK(15, 8)))
+
+/* Hardware supported fifo size */
+#define SUNXI_IR_FIFO_SIZE    16
+/* How many messages in FIFO trigger IRQ */
+#define TRIGGER_LEVEL         8
+/* Required frequency for IR0 or IR1 clock in CIR mode */
+#define SUNXI_IR_BASE_CLK     8000000
+/* Frequency after IR internal divider  */
+#define SUNXI_IR_CLK          (SUNXI_IR_BASE_CLK / 64)
+/* Sample period in ns */
+#define SUNXI_IR_SAMPLE       (1000000000ul / SUNXI_IR_CLK)
+/* Noise threshold in samples  */
+#define SUNXI_IR_RXNOISE      1
+/* Idle Threshold in samples */
+#define SUNXI_IR_RXIDLE       20
+/* Time after which device stops sending data in ms */
+#define SUNXI_IR_TIMEOUT      120
+
+struct sunxi_ir {
+	spinlock_t      ir_lock;
+	struct rc_dev   *rc;
+	void __iomem    *base;
+	int             irq;
+	struct clk      *clk;
+	struct clk      *apb_clk;
+	const char      *map_name;
+};
+
+static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
+{
+	unsigned long status;
+	unsigned char dt;
+	unsigned int cnt, rc;
+	struct sunxi_ir *ir = dev_id;
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	spin_lock(&ir->ir_lock);
+
+	status = readl(ir->base + SUNXI_IR_RXSTA_REG);
+
+	/* clean all pending statuses */
+	writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+	if (status & REG_RXINT_RAI_EN) {
+		/* How many messages in fifo */
+		rc  = REG_RXSTA_GET_AC(status);
+		/* Sanity check */
+		rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc;
+		/* If we have data */
+		for (cnt = 0; cnt < rc; cnt++) {
+			/* for each bit in fifo */
+			dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
+			rawir.pulse = (dt & 0x80) != 0;
+			rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
+			ir_raw_event_store_with_filter(ir->rc, &rawir);
+		}
+	}
+
+	if (status & REG_RXINT_ROI_EN) {
+		ir_raw_event_reset(ir->rc);
+	} else if (status & REG_RXINT_RPEI_EN) {
+		ir_raw_event_set_idle(ir->rc, true);
+		ir_raw_event_handle(ir->rc);
+	}
+
+	spin_unlock(&ir->ir_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int sunxi_ir_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	unsigned long tmp = 0;
+
+	struct device *dev = &pdev->dev;
+	struct device_node *dn = dev->of_node;
+	struct resource *res;
+	struct sunxi_ir *ir;
+
+	ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL);
+	if (!ir)
+		return -ENOMEM;
+
+	/* Clock */
+	ir->apb_clk = devm_clk_get(dev, "apb");
+	if (IS_ERR(ir->apb_clk)) {
+		dev_err(dev, "failed to get a apb clock.\n");
+		return PTR_ERR(ir->apb_clk);
+	}
+	ir->clk = devm_clk_get(dev, "ir");
+	if (IS_ERR(ir->clk)) {
+		dev_err(dev, "failed to get a ir clock.\n");
+		return PTR_ERR(ir->clk);
+	}
+
+	ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
+	if (ret) {
+		dev_err(dev, "set ir base clock failed!\n");
+		return ret;
+	}
+
+	if (clk_prepare_enable(ir->apb_clk)) {
+		dev_err(dev, "try to enable apb_ir_clk failed\n");
+		return -EINVAL;
+	}
+
+	if (clk_prepare_enable(ir->clk)) {
+		dev_err(dev, "try to enable ir_clk failed\n");
+		ret = -EINVAL;
+		goto exit_clkdisable_apb_clk;
+	}
+
+	/* IO */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ir->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(ir->base)) {
+		dev_err(dev, "failed to map registers\n");
+		ret = PTR_ERR(ir->base);
+		goto exit_clkdisable_clk;
+	}
+
+	ir->rc = rc_allocate_device();
+	if (!ir->rc) {
+		dev_err(dev, "failed to allocate device\n");
+		ret = -ENOMEM;
+		goto exit_clkdisable_clk;
+	}
+
+	ir->rc->priv = ir;
+	ir->rc->input_name = SUNXI_IR_DEV;
+	ir->rc->input_phys = "sunxi-ir/input0";
+	ir->rc->input_id.bustype = BUS_HOST;
+	ir->rc->input_id.vendor = 0x0001;
+	ir->rc->input_id.product = 0x0001;
+	ir->rc->input_id.version = 0x0100;
+	ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);
+	ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
+	ir->rc->dev.parent = dev;
+	ir->rc->driver_type = RC_DRIVER_IR_RAW;
+	ir->rc->allowed_protocols = RC_BIT_ALL;
+	ir->rc->rx_resolution = SUNXI_IR_SAMPLE;
+	ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
+	ir->rc->driver_name = SUNXI_IR_DEV;
+
+	ret = rc_register_device(ir->rc);
+	if (ret) {
+		dev_err(dev, "failed to register rc device\n");
+		goto exit_free_dev;
+	}
+
+	platform_set_drvdata(pdev, ir);
+
+	/* IRQ */
+	ir->irq = platform_get_irq(pdev, 0);
+	if (ir->irq < 0) {
+		dev_err(dev, "no irq resource\n");
+		ret = ir->irq;
+		goto exit_free_dev;
+	}
+
+	ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir);
+	if (ret) {
+		dev_err(dev, "failed request irq\n");
+		goto exit_free_dev;
+	}
+
+	/* Enable CIR Mode */
+	writel(REG_CTL_MD, ir->base+SUNXI_IR_CTL_REG);
+
+	/* Set noise threshold and idle threshold */
+	writel(REG_CIR_NTHR(SUNXI_IR_RXNOISE)|REG_CIR_ITHR(SUNXI_IR_RXIDLE),
+	       ir->base + SUNXI_IR_CIR_REG);
+
+	/* Invert Input Signal */
+	writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG);
+
+	/* Clear All Rx Interrupt Status */
+	writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+	/*
+	 * Enable IRQ on overflow, packet end, FIFO available with trigger
+	 * level
+	 */
+	writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN |
+	       REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1),
+	       ir->base + SUNXI_IR_RXINT_REG);
+
+	/* Enable IR Module */
+	tmp = readl(ir->base + SUNXI_IR_CTL_REG);
+	writel(tmp | REG_CTL_GEN | REG_CTL_RXEN, ir->base + SUNXI_IR_CTL_REG);
+
+	dev_info(dev, "initialized sunXi IR driver\n");
+	return 0;
+
+exit_free_dev:
+	rc_free_device(ir->rc);
+exit_clkdisable_clk:
+	clk_disable_unprepare(ir->clk);
+exit_clkdisable_apb_clk:
+	clk_disable_unprepare(ir->apb_clk);
+
+	return ret;
+}
+
+static int sunxi_ir_remove(struct platform_device *pdev)
+{
+	unsigned long flags;
+	struct sunxi_ir *ir = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(ir->clk);
+	clk_disable_unprepare(ir->apb_clk);
+
+	spin_lock_irqsave(&ir->ir_lock, flags);
+	/* disable IR IRQ */
+	writel(0, ir->base + SUNXI_IR_RXINT_REG);
+	/* clear All Rx Interrupt Status */
+	writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+	/* disable IR */
+	writel(0, ir->base + SUNXI_IR_CTL_REG);
+	spin_unlock_irqrestore(&ir->ir_lock, flags);
+
+	rc_unregister_device(ir->rc);
+	return 0;
+}
+
+static const struct of_device_id sunxi_ir_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-ir", },
+	{},
+};
+
+static struct platform_driver sunxi_ir_driver = {
+	.probe          = sunxi_ir_probe,
+	.remove         = sunxi_ir_remove,
+	.driver = {
+		.name = SUNXI_IR_DEV,
+		.owner = THIS_MODULE,
+		.of_match_table = sunxi_ir_match,
+	},
+};
+
+module_platform_driver(sunxi_ir_driver);
+
+MODULE_DESCRIPTION("Allwinner sunXi IR controller driver");
+MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/ttusbir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/ttusbir.c
--- linux-libre-3.16-gnu/drivers/media/rc/ttusbir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/ttusbir.c	2014-09-28 17:29:07.000000000 -0400
@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_inte
 	usb_to_input_id(tt->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc_set_allowed_protocols(rc, RC_BIT_ALL);
+	rc->allowed_protocols = RC_BIT_ALL;
 	rc->priv = tt;
 	rc->driver_name = DRIVER_NAME;
 	rc->map_name = RC_MAP_TT_1500;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/rc/winbond-cir.c linux-libre-3.17-rc7-gnu/drivers/media/rc/winbond-cir.c
--- linux-libre-3.16-gnu/drivers/media/rc/winbond-cir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/rc/winbond-cir.c	2014-09-28 17:29:07.000000000 -0400
@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, cons
 	data->dev->dev.parent = &device->dev;
 	data->dev->timeout = MS_TO_NS(100);
 	data->dev->rx_resolution = US_TO_NS(2);
-	rc_set_allowed_protocols(data->dev, RC_BIT_ALL);
+	data->dev->allowed_protocols = RC_BIT_ALL;
 
 	err = rc_register_device(data->dev);
 	if (err)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/tuners/Kconfig
--- linux-libre-3.16-gnu/drivers/media/tuners/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 # Analog TV tuners, auto-loaded via tuner.ko
 config MEDIA_TUNER
 	tristate
-	depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
+	depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT) && I2C
 	default y
 	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
@@ -16,7 +16,7 @@ config MEDIA_TUNER
 
 menu "Customize TV tuners"
 	visible if !MEDIA_SUBDRV_AUTOSELECT
-	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
+	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
 
 config MEDIA_TUNER_SIMPLE
 	tristate "Simple tuner support"
@@ -71,6 +71,13 @@ config MEDIA_TUNER_TEA5767
 	help
 	  Say Y here to include support for the Philips TEA5767 radio tuner.
 
+config MEDIA_TUNER_MSI001
+	tristate "Mirics MSi001"
+	depends on MEDIA_SUPPORT && SPI && VIDEO_V4L2
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Mirics MSi001 silicon tuner driver.
+
 config MEDIA_TUNER_MT20XX
 	tristate "Microtune 2032 / 2050 tuners"
 	depends on MEDIA_SUPPORT && I2C
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/Makefile linux-libre-3.17-rc7-gnu/drivers/media/tuners/Makefile
--- linux-libre-3.16-gnu/drivers/media/tuners/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda
 obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
+obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
 obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
 obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/msi001.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/msi001.c
--- linux-libre-3.16-gnu/drivers/media/tuners/msi001.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/msi001.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,500 @@
+/*
+ * Mirics MSi001 silicon tuner driver
+ *
+ * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/gcd.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   49000000,
+		.rangehigh  =  263000000,
+	}, {
+		.type = V4L2_TUNER_RF,
+		.index = 1,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  390000000,
+		.rangehigh  =  960000000,
+	},
+};
+
+struct msi001 {
+	struct spi_device *spi;
+	struct v4l2_subdev sd;
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *bandwidth_auto;
+	struct v4l2_ctrl *bandwidth;
+	struct v4l2_ctrl *lna_gain;
+	struct v4l2_ctrl *mixer_gain;
+	struct v4l2_ctrl *if_gain;
+
+	unsigned int f_tuner;
+};
+
+static inline struct msi001 *sd_to_msi001(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct msi001, sd);
+}
+
+static int msi001_wreg(struct msi001 *s, u32 data)
+{
+	/* Register format: 4 bits addr + 20 bits value */
+	return spi_write(s->spi, &data, 3);
+};
+
+static int msi001_set_gain(struct msi001 *s, int lna_gain, int mixer_gain,
+		int if_gain)
+{
+	int ret;
+	u32 reg;
+	dev_dbg(&s->spi->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
+			lna_gain, mixer_gain, if_gain);
+
+	reg = 1 << 0;
+	reg |= (59 - if_gain) << 4;
+	reg |= 0 << 10;
+	reg |= (1 - mixer_gain) << 12;
+	reg |= (1 - lna_gain) << 13;
+	reg |= 4 << 14;
+	reg |= 0 << 17;
+	ret = msi001_wreg(s, reg);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
+	return ret;
+};
+
+static int msi001_set_tuner(struct msi001 *s)
+{
+	int ret, i;
+	unsigned int n, m, thresh, frac, vco_step, tmp, f_if1;
+	u32 reg;
+	u64 f_vco, tmp64;
+	u8 mode, filter_mode, lo_div;
+	static const struct {
+		u32 rf;
+		u8 mode;
+		u8 lo_div;
+	} band_lut[] = {
+		{ 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */
+		{108000000, 0x42, 32}, /* VHF_MODE */
+		{330000000, 0x44, 16}, /* B3_MODE */
+		{960000000, 0x48,  4}, /* B45_MODE */
+		{      ~0U, 0x50,  2}, /* BL_MODE */
+	};
+	static const struct {
+		u32 freq;
+		u8 filter_mode;
+	} if_freq_lut[] = {
+		{      0, 0x03}, /* Zero IF */
+		{ 450000, 0x02}, /* 450 kHz IF */
+		{1620000, 0x01}, /* 1.62 MHz IF */
+		{2048000, 0x00}, /* 2.048 MHz IF */
+	};
+	static const struct {
+		u32 freq;
+		u8 val;
+	} bandwidth_lut[] = {
+		{ 200000, 0x00}, /* 200 kHz */
+		{ 300000, 0x01}, /* 300 kHz */
+		{ 600000, 0x02}, /* 600 kHz */
+		{1536000, 0x03}, /* 1.536 MHz */
+		{5000000, 0x04}, /* 5 MHz */
+		{6000000, 0x05}, /* 6 MHz */
+		{7000000, 0x06}, /* 7 MHz */
+		{8000000, 0x07}, /* 8 MHz */
+	};
+
+	unsigned int f_rf = s->f_tuner;
+
+	/*
+	 * bandwidth (Hz)
+	 * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
+	 */
+	unsigned int bandwidth;
+
+	/*
+	 * intermediate frequency (Hz)
+	 * 0, 450000, 1620000, 2048000
+	 */
+	unsigned int f_if = 0;
+	#define F_REF 24000000
+	#define R_REF 4
+	#define F_OUT_STEP 1
+
+	dev_dbg(&s->spi->dev,
+			"%s: f_rf=%d f_if=%d\n",
+			__func__, f_rf, f_if);
+
+	for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
+		if (f_rf <= band_lut[i].rf) {
+			mode = band_lut[i].mode;
+			lo_div = band_lut[i].lo_div;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(band_lut)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* AM_MODE is upconverted */
+	if ((mode >> 0) & 0x1)
+		f_if1 =  5 * F_REF;
+	else
+		f_if1 =  0;
+
+	for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
+		if (f_if == if_freq_lut[i].freq) {
+			filter_mode = if_freq_lut[i].filter_mode;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(if_freq_lut)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* filters */
+	bandwidth = s->bandwidth->val;
+	bandwidth = clamp(bandwidth, 200000U, 8000000U);
+
+	for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+		if (bandwidth <= bandwidth_lut[i].freq) {
+			bandwidth = bandwidth_lut[i].val;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(bandwidth_lut)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	s->bandwidth->val = bandwidth_lut[i].freq;
+
+	dev_dbg(&s->spi->dev, "%s: bandwidth selected=%d\n",
+			__func__, bandwidth_lut[i].freq);
+
+	f_vco = (u64) (f_rf + f_if + f_if1) * lo_div;
+	tmp64 = f_vco;
+	m = do_div(tmp64, F_REF * R_REF);
+	n = (unsigned int) tmp64;
+
+	vco_step = F_OUT_STEP * lo_div;
+	thresh = (F_REF * R_REF) / vco_step;
+	frac = 1ul * thresh * m / (F_REF * R_REF);
+
+	/* Find out greatest common divisor and divide to smaller. */
+	tmp = gcd(thresh, frac);
+	thresh /= tmp;
+	frac /= tmp;
+
+	/* Force divide to reg max. Resolution will be reduced. */
+	tmp = DIV_ROUND_UP(thresh, 4095);
+	thresh = DIV_ROUND_CLOSEST(thresh, tmp);
+	frac = DIV_ROUND_CLOSEST(frac, tmp);
+
+	/* calc real RF set */
+	tmp = 1ul * F_REF * R_REF * n;
+	tmp += 1ul * F_REF * R_REF * frac / thresh;
+	tmp /= lo_div;
+
+	dev_dbg(&s->spi->dev,
+			"%s: rf=%u:%u n=%d thresh=%d frac=%d\n",
+				__func__, f_rf, tmp, n, thresh, frac);
+
+	ret = msi001_wreg(s, 0x00000e);
+	if (ret)
+		goto err;
+
+	ret = msi001_wreg(s, 0x000003);
+	if (ret)
+		goto err;
+
+	reg = 0 << 0;
+	reg |= mode << 4;
+	reg |= filter_mode << 12;
+	reg |= bandwidth << 14;
+	reg |= 0x02 << 17;
+	reg |= 0x00 << 20;
+	ret = msi001_wreg(s, reg);
+	if (ret)
+		goto err;
+
+	reg = 5 << 0;
+	reg |= thresh << 4;
+	reg |= 1 << 19;
+	reg |= 1 << 21;
+	ret = msi001_wreg(s, reg);
+	if (ret)
+		goto err;
+
+	reg = 2 << 0;
+	reg |= frac << 4;
+	reg |= n << 16;
+	ret = msi001_wreg(s, reg);
+	if (ret)
+		goto err;
+
+	ret = msi001_set_gain(s, s->lna_gain->cur.val, s->mixer_gain->cur.val,
+			s->if_gain->cur.val);
+	if (ret)
+		goto err;
+
+	reg = 6 << 0;
+	reg |= 63 << 4;
+	reg |= 4095 << 10;
+	ret = msi001_wreg(s, reg);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
+	return ret;
+};
+
+static int msi001_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	int ret;
+	dev_dbg(&s->spi->dev, "%s: on=%d\n", __func__, on);
+
+	if (on)
+		ret = 0;
+	else
+		ret = msi001_wreg(s, 0x000000);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_core_ops msi001_core_ops = {
+	.s_power                  = msi001_s_power,
+};
+
+static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
+
+	strlcpy(v->name, "Mirics MSi001", sizeof(v->name));
+	v->type = V4L2_TUNER_RF;
+	v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+	v->rangelow =    49000000;
+	v->rangehigh =  960000000;
+
+	return 0;
+}
+
+static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
+	return 0;
+}
+
+static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	dev_dbg(&s->spi->dev, "%s: tuner=%d\n", __func__, f->tuner);
+	f->frequency = s->f_tuner;
+	return 0;
+}
+
+static int msi001_s_frequency(struct v4l2_subdev *sd,
+		const struct v4l2_frequency *f)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	unsigned int band;
+	dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2))
+		band = 0;
+	else
+		band = 1;
+	s->f_tuner = clamp_t(unsigned int, f->frequency,
+			bands[band].rangelow, bands[band].rangehigh);
+
+	return msi001_set_tuner(s);
+}
+
+static int msi001_enum_freq_bands(struct v4l2_subdev *sd,
+		struct v4l2_frequency_band *band)
+{
+	struct msi001 *s = sd_to_msi001(sd);
+	dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->index >= ARRAY_SIZE(bands))
+		return -EINVAL;
+
+	band->capability = bands[band->index].capability;
+	band->rangelow = bands[band->index].rangelow;
+	band->rangehigh = bands[band->index].rangehigh;
+
+	return 0;
+}
+
+static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
+	.g_tuner                  = msi001_g_tuner,
+	.s_tuner                  = msi001_s_tuner,
+	.g_frequency              = msi001_g_frequency,
+	.s_frequency              = msi001_s_frequency,
+	.enum_freq_bands          = msi001_enum_freq_bands,
+};
+
+static const struct v4l2_subdev_ops msi001_ops = {
+	.core                     = &msi001_core_ops,
+	.tuner                    = &msi001_tuner_ops,
+};
+
+static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct msi001 *s = container_of(ctrl->handler, struct msi001, hdl);
+
+	int ret;
+	dev_dbg(&s->spi->dev,
+			"%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
+			__func__, ctrl->id, ctrl->name, ctrl->val,
+			ctrl->minimum, ctrl->maximum, ctrl->step);
+
+	switch (ctrl->id) {
+	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
+	case V4L2_CID_RF_TUNER_BANDWIDTH:
+		ret = msi001_set_tuner(s);
+		break;
+	case  V4L2_CID_RF_TUNER_LNA_GAIN:
+		ret = msi001_set_gain(s, s->lna_gain->val,
+				s->mixer_gain->cur.val, s->if_gain->cur.val);
+		break;
+	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
+		ret = msi001_set_gain(s, s->lna_gain->cur.val,
+				s->mixer_gain->val, s->if_gain->cur.val);
+		break;
+	case  V4L2_CID_RF_TUNER_IF_GAIN:
+		ret = msi001_set_gain(s, s->lna_gain->cur.val,
+				s->mixer_gain->cur.val, s->if_gain->val);
+		break;
+	default:
+		dev_dbg(&s->spi->dev, "%s: unkown control %d\n",
+				__func__, ctrl->id);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops msi001_ctrl_ops = {
+	.s_ctrl                   = msi001_s_ctrl,
+};
+
+static int msi001_probe(struct spi_device *spi)
+{
+	struct msi001 *s;
+	int ret;
+	dev_dbg(&spi->dev, "%s:\n", __func__);
+
+	s = kzalloc(sizeof(struct msi001), GFP_KERNEL);
+	if (s == NULL) {
+		ret = -ENOMEM;
+		dev_dbg(&spi->dev, "Could not allocate memory for msi001\n");
+		goto err_kfree;
+	}
+
+	s->spi = spi;
+	s->f_tuner = bands[0].rangelow;
+	v4l2_spi_subdev_init(&s->sd, spi, &msi001_ops);
+
+	/* Register controls */
+	v4l2_ctrl_handler_init(&s->hdl, 5);
+	s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+			V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
+	s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+			V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000);
+	v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1);
+	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 1, 1, 1);
+	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
+			V4L2_CID_RF_TUNER_IF_GAIN, 0, 59, 1, 0);
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->spi->dev, "Could not initialize controls\n");
+		/* control init failed, free handler */
+		goto err_ctrl_handler_free;
+	}
+
+	s->sd.ctrl_handler = &s->hdl;
+	return 0;
+
+err_ctrl_handler_free:
+	v4l2_ctrl_handler_free(&s->hdl);
+err_kfree:
+	kfree(s);
+	return ret;
+}
+
+static int msi001_remove(struct spi_device *spi)
+{
+	struct v4l2_subdev *sd = spi_get_drvdata(spi);
+	struct msi001 *s = sd_to_msi001(sd);
+	dev_dbg(&spi->dev, "%s:\n", __func__);
+
+	/*
+	 * Registered by v4l2_spi_new_subdev() from master driver, but we must
+	 * unregister it from here. Weird.
+	 */
+	v4l2_device_unregister_subdev(&s->sd);
+	v4l2_ctrl_handler_free(&s->hdl);
+	kfree(s);
+	return 0;
+}
+
+static const struct spi_device_id msi001_id[] = {
+	{"msi001", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, msi001_id);
+
+static struct spi_driver msi001_driver = {
+	.driver = {
+		.name	= "msi001",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= msi001_probe,
+	.remove		= msi001_remove,
+	.id_table	= msi001_id,
+};
+module_spi_driver(msi001_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Mirics MSi001");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/r820t.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/r820t.c
--- linux-libre-3.16-gnu/drivers/media/tuners/r820t.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/r820t.c	2014-09-28 17:29:07.000000000 -0400
@@ -1545,7 +1545,7 @@ static int r820t_imr_cross(struct r820t_
 		cross[i].value = rc;
 
 		if (cross[i].value < tmp.value)
-			memcpy(&tmp, &cross[i], sizeof(tmp));
+			tmp = cross[i];
 	}
 
 	if ((tmp.phase_y & 0x1f) == 1) {	/* y-direction */
@@ -2300,7 +2300,6 @@ struct dvb_frontend *r820t_attach(struct
 	case 0:
 		/* memory allocation failure */
 		goto err_no_gate;
-		break;
 	case 1:
 		/* new tuner instance */
 		priv->cfg = cfg;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/si2157.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157.c
--- linux-libre-3.16-gnu/drivers/media/tuners/si2157.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157.c	2014-09-28 21:27:53.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
@@ -16,54 +16,58 @@
 
 #include "si2157_priv.h"
 
+static const struct dvb_tuner_ops si2157_ops;
+
 /* execute firmware command */
 static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
 {
 	int ret;
-	u8 buf[1];
 	unsigned long timeout;
 
 	mutex_lock(&s->i2c_mutex);
 
-	if (cmd->len) {
+	if (cmd->wlen) {
 		/* write cmd and args for firmware */
-		ret = i2c_master_send(s->client, cmd->args, cmd->len);
+		ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
 		if (ret < 0) {
 			goto err_mutex_unlock;
-		} else if (ret != cmd->len) {
+		} else if (ret != cmd->wlen) {
 			ret = -EREMOTEIO;
 			goto err_mutex_unlock;
 		}
 	}
 
-	/* wait cmd execution terminate */
-	#define TIMEOUT 80
-	timeout = jiffies + msecs_to_jiffies(TIMEOUT);
-	while (!time_after(jiffies, timeout)) {
-		ret = i2c_master_recv(s->client, buf, 1);
-		if (ret < 0) {
-			goto err_mutex_unlock;
-		} else if (ret != 1) {
-			ret = -EREMOTEIO;
-			goto err_mutex_unlock;
-		}
+	if (cmd->rlen) {
+		/* wait cmd execution terminate */
+		#define TIMEOUT 80
+		timeout = jiffies + msecs_to_jiffies(TIMEOUT);
+		while (!time_after(jiffies, timeout)) {
+			ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
+			if (ret < 0) {
+				goto err_mutex_unlock;
+			} else if (ret != cmd->rlen) {
+				ret = -EREMOTEIO;
+				goto err_mutex_unlock;
+			}
 
-		/* firmware ready? */
-		if ((buf[0] >> 7) & 0x01)
-			break;
-	}
+			/* firmware ready? */
+			if ((cmd->args[0] >> 7) & 0x01)
+				break;
+		}
 
-	dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", __func__,
-			jiffies_to_msecs(jiffies) -
-			(jiffies_to_msecs(timeout) - TIMEOUT));
+		dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n",
+				__func__,
+				jiffies_to_msecs(jiffies) -
+				(jiffies_to_msecs(timeout) - TIMEOUT));
 
-	if (!((buf[0] >> 7) & 0x01)) {
-		ret = -ETIMEDOUT;
-		goto err_mutex_unlock;
-	} else {
-		ret = 0;
+		if (!((cmd->args[0] >> 7) & 0x01)) {
+			ret = -ETIMEDOUT;
+			goto err_mutex_unlock;
+		}
 	}
 
+	ret = 0;
+
 err_mutex_unlock:
 	mutex_unlock(&s->i2c_mutex);
 	if (ret)
@@ -78,23 +82,133 @@ err:
 static int si2157_init(struct dvb_frontend *fe)
 {
 	struct si2157 *s = fe->tuner_priv;
+	int ret, len, remaining;
+	struct si2157_cmd cmd;
+	const struct firmware *fw = NULL;
+	u8 *fw_file;
+	unsigned int chip_id;
 
 	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
+	/* configure? */
+	memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
+	cmd.wlen = 15;
+	cmd.rlen = 1;
+	ret = si2157_cmd_execute(s, &cmd);
+	if (ret)
+		goto err;
+
+	/* query chip revision */
+	memcpy(cmd.args, "\x02", 1);
+	cmd.wlen = 1;
+	cmd.rlen = 13;
+	ret = si2157_cmd_execute(s, &cmd);
+	if (ret)
+		goto err;
+
+	chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+			cmd.args[4] << 0;
+
+	#define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
+	#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
+
+	switch (chip_id) {
+	case SI2158_A20:
+		fw_file = SI2158_A20_FIRMWARE;
+		break;
+	case SI2157_A30:
+		goto skip_fw_download;
+		break;
+	default:
+		dev_err(&s->client->dev,
+				"%s: unkown chip version Si21%d-%c%c%c\n",
+				KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+				cmd.args[3], cmd.args[4]);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* cold state - try to download firmware */
+	dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
+			KBUILD_MODNAME, si2157_ops.info.name);
+
+	/* request the firmware, this will block and timeout */
+	ret = reject_firmware(&fw, fw_file, &s->client->dev);
+	if (ret) {
+		dev_err(&s->client->dev, "%s: firmware file '%s' not found\n",
+				KBUILD_MODNAME, fw_file);
+		goto err;
+	}
+
+	/* firmware should be n chunks of 17 bytes */
+	if (fw->size % 17 != 0) {
+		dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n",
+				KBUILD_MODNAME, fw_file);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
+			KBUILD_MODNAME, fw_file);
+
+	for (remaining = fw->size; remaining > 0; remaining -= 17) {
+		len = fw->data[fw->size - remaining];
+		memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
+		cmd.wlen = len;
+		cmd.rlen = 1;
+		ret = si2157_cmd_execute(s, &cmd);
+		if (ret) {
+			dev_err(&s->client->dev,
+					"%s: firmware download failed=%d\n",
+					KBUILD_MODNAME, ret);
+			goto err;
+		}
+	}
+
+	release_firmware(fw);
+	fw = NULL;
+
+skip_fw_download:
+	/* reboot the tuner with new firmware? */
+	memcpy(cmd.args, "\x01\x01", 2);
+	cmd.wlen = 2;
+	cmd.rlen = 1;
+	ret = si2157_cmd_execute(s, &cmd);
+	if (ret)
+		goto err;
+
 	s->active = true;
 
 	return 0;
+err:
+	if (fw)
+		release_firmware(fw);
+
+	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
 }
 
 static int si2157_sleep(struct dvb_frontend *fe)
 {
 	struct si2157 *s = fe->tuner_priv;
+	int ret;
+	struct si2157_cmd cmd;
 
 	dev_dbg(&s->client->dev, "%s:\n", __func__);
 
 	s->active = false;
 
+	memcpy(cmd.args, "\x13", 1);
+	cmd.wlen = 1;
+	cmd.rlen = 0;
+	ret = si2157_cmd_execute(s, &cmd);
+	if (ret)
+		goto err;
+
 	return 0;
+err:
+	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
 }
 
 static int si2157_set_params(struct dvb_frontend *fe)
@@ -103,6 +217,7 @@ static int si2157_set_params(struct dvb_
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	struct si2157_cmd cmd;
+	u8 bandwidth, delivery_system;
 
 	dev_dbg(&s->client->dev,
 			"%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
@@ -114,50 +229,46 @@ static int si2157_set_params(struct dvb_
 		goto err;
 	}
 
-	/* configure? */
-	cmd.args[0] = 0xc0;
-	cmd.args[1] = 0x00;
-	cmd.args[2] = 0x0c;
-	cmd.args[3] = 0x00;
-	cmd.args[4] = 0x00;
-	cmd.args[5] = 0x01;
-	cmd.args[6] = 0x01;
-	cmd.args[7] = 0x01;
-	cmd.args[8] = 0x01;
-	cmd.args[9] = 0x01;
-	cmd.args[10] = 0x01;
-	cmd.args[11] = 0x02;
-	cmd.args[12] = 0x00;
-	cmd.args[13] = 0x00;
-	cmd.args[14] = 0x01;
-	cmd.len = 15;
-	ret = si2157_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
+	if (c->bandwidth_hz <= 6000000)
+		bandwidth = 0x06;
+	else if (c->bandwidth_hz <= 7000000)
+		bandwidth = 0x07;
+	else if (c->bandwidth_hz <= 8000000)
+		bandwidth = 0x08;
+	else
+		bandwidth = 0x0f;
 
-	cmd.args[0] = 0x02;
-	cmd.len = 1;
-	ret = si2157_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
+	switch (c->delivery_system) {
+	case SYS_DVBT:
+	case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
+			delivery_system = 0x20;
+			break;
+	case SYS_DVBC_ANNEX_A:
+			delivery_system = 0x30;
+			break;
+	default:
+			ret = -EINVAL;
+			goto err;
+	}
 
-	cmd.args[0] = 0x01;
-	cmd.args[1] = 0x01;
-	cmd.len = 2;
+	memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
+	cmd.args[4] = delivery_system | bandwidth;
+	if (s->inversion)
+		cmd.args[5] = 0x01;
+	cmd.wlen = 6;
+	cmd.rlen = 1;
 	ret = si2157_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	/* set frequency */
-	cmd.args[0] = 0x41;
-	cmd.args[1] = 0x00;
-	cmd.args[2] = 0x00;
-	cmd.args[3] = 0x00;
+	memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
 	cmd.args[4] = (c->frequency >>  0) & 0xff;
 	cmd.args[5] = (c->frequency >>  8) & 0xff;
 	cmd.args[6] = (c->frequency >> 16) & 0xff;
 	cmd.args[7] = (c->frequency >> 24) & 0xff;
-	cmd.len = 8;
+	cmd.wlen = 8;
+	cmd.rlen = 1;
 	ret = si2157_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
@@ -168,9 +279,15 @@ err:
 	return ret;
 }
 
-static const struct dvb_tuner_ops si2157_tuner_ops = {
+static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	*frequency = 5000000; /* default value of property 0x0706 */
+	return 0;
+}
+
+static const struct dvb_tuner_ops si2157_ops = {
 	.info = {
-		.name           = "Silicon Labs Si2157",
+		.name           = "Silicon Labs Si2157/Si2158",
 		.frequency_min  = 110000000,
 		.frequency_max  = 862000000,
 	},
@@ -178,6 +295,7 @@ static const struct dvb_tuner_ops si2157
 	.init = si2157_init,
 	.sleep = si2157_sleep,
 	.set_params = si2157_set_params,
+	.get_if_frequency = si2157_get_if_frequency,
 };
 
 static int si2157_probe(struct i2c_client *client,
@@ -198,22 +316,24 @@ static int si2157_probe(struct i2c_clien
 
 	s->client = client;
 	s->fe = cfg->fe;
+	s->inversion = cfg->inversion;
 	mutex_init(&s->i2c_mutex);
 
 	/* check if the tuner is there */
-	cmd.len = 0;
+	cmd.wlen = 0;
+	cmd.rlen = 1;
 	ret = si2157_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
 	fe->tuner_priv = s;
-	memcpy(&fe->ops.tuner_ops, &si2157_tuner_ops,
+	memcpy(&fe->ops.tuner_ops, &si2157_ops,
 			sizeof(struct dvb_tuner_ops));
 
 	i2c_set_clientdata(client, s);
 
 	dev_info(&s->client->dev,
-			"%s: Silicon Labs Si2157 successfully attached\n",
+			"%s: Silicon Labs Si2157/Si2158 successfully attached\n",
 			KBUILD_MODNAME);
 	return 0;
 err:
@@ -255,6 +375,7 @@ static struct i2c_driver si2157_driver =
 
 module_i2c_driver(si2157_driver);
 
-MODULE_DESCRIPTION("Silicon Labs Si2157 silicon tuner driver");
+MODULE_DESCRIPTION("Silicon Labs Si2157/Si2158 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_LICENSE("GPL");
+/*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/si2157.h linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157.h
--- linux-libre-3.16-gnu/drivers/media/tuners/si2157.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
@@ -29,6 +29,11 @@ struct si2157_config {
 	 * frontend
 	 */
 	struct dvb_frontend *fe;
+
+	/*
+	 * Spectral Inversion
+	 */
+	bool inversion;
 };
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/si2157_priv.h linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157_priv.h
--- linux-libre-3.16-gnu/drivers/media/tuners/si2157_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/si2157_priv.h	2014-09-28 21:27:55.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
@@ -17,6 +17,7 @@
 #ifndef SI2157_PRIV_H
 #define SI2157_PRIV_H
 
+#include <linux/firmware.h>
 #include "si2157.h"
 
 /* state struct */
@@ -25,13 +26,17 @@ struct si2157 {
 	struct i2c_client *client;
 	struct dvb_frontend *fe;
 	bool active;
+	bool inversion;
 };
 
 /* firmare command struct */
 #define SI2157_ARGLEN      30
 struct si2157_cmd {
 	u8 args[SI2157_ARGLEN];
-	unsigned len;
+	unsigned wlen;
+	unsigned rlen;
 };
 
+#define SI2158_A20_FIRMWARE "/*(DEBLOBBED)*/"
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/tuner_it913x.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/tuner_it913x.c
--- linux-libre-3.16-gnu/drivers/media/tuners/tuner_it913x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/tuner_it913x.c	2014-09-28 17:29:07.000000000 -0400
@@ -396,6 +396,7 @@ struct dvb_frontend *it913x_attach(struc
 		struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 config)
 {
 	struct it913x_state *state = NULL;
+	int ret;
 
 	/* allocate memory for the internal state */
 	state = kzalloc(sizeof(struct it913x_state), GFP_KERNEL);
@@ -425,6 +426,11 @@ struct dvb_frontend *it913x_attach(struc
 	state->tuner_type = config;
 	state->firmware_ver = 1;
 
+	/* tuner RF initial */
+	ret = it913x_wr_reg(state, PRO_DMOD, 0xec4c, 0x68);
+	if (ret < 0)
+		goto error;
+
 	fe->tuner_priv = state;
 	memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,
 			sizeof(struct dvb_tuner_ops));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/tuner-xc2028.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/tuner-xc2028.c
--- linux-libre-3.16-gnu/drivers/media/tuners/tuner-xc2028.c	2014-08-07 04:47:13.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/tuner-xc2028.c	2014-09-28 21:27:58.000000000 -0400
@@ -1489,7 +1489,6 @@ struct dvb_frontend *xc2028_attach(struc
 	case 0:
 		/* memory allocation failure */
 		goto fail;
-		break;
 	case 1:
 		/* new tuner instance */
 		priv->ctrl.max_len = 13;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/xc4000.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/xc4000.c
--- linux-libre-3.16-gnu/drivers/media/tuners/xc4000.c	2014-08-07 04:47:16.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/xc4000.c	2014-09-28 21:28:04.000000000 -0400
@@ -93,7 +93,7 @@ struct xc4000_priv {
 	struct firmware_description *firm;
 	int	firm_size;
 	u32	if_khz;
-	u32	freq_hz;
+	u32	freq_hz, freq_offset;
 	u32	bandwidth;
 	u8	video_standard;
 	u8	rf_mode;
@@ -116,6 +116,7 @@ struct xc4000_priv {
 #define XC4000_AUDIO_STD_MONO		32
 
 /*(DEBLOBBED)*/
+/*(DEBLOBBED)*/
 
 /* Misc Defines */
 #define MAX_TV_STANDARD			24
@@ -730,13 +731,25 @@ static int xc4000_fwupload(struct dvb_fr
 	char		      name[33];
 	const char	      *fname;
 
-	if (firmware_name[0] != '\0')
+	if (firmware_name[0] != '\0') {
 		fname = firmware_name;
-	else
+
+		dprintk(1, "Reading custom firmware %s\n", fname);
+		rc = maybe_reject_firmware(&fw, fname,
+				      priv->i2c_props.adap->dev.parent);
+	} else {
 		fname = "/*(DEBLOBBED)*/";
+		dprintk(1, "Trying to read firmware %s\n", fname);
+		rc = maybe_reject_firmware(&fw, fname,
+				      priv->i2c_props.adap->dev.parent);
+		if (rc == -ENOENT) {
+			fname = "/*(DEBLOBBED)*/";
+			dprintk(1, "Trying to read firmware %s\n", fname);
+			rc = maybe_reject_firmware(&fw, fname,
+					      priv->i2c_props.adap->dev.parent);
+		}
+	}
 
-	dprintk(1, "Reading firmware %s\n", fname);
-	rc = maybe_reject_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
 	if (rc < 0) {
 		if (rc == -ENOENT)
 			printk(KERN_ERR "Error: firmware %s not found.\n", fname);
@@ -746,6 +759,8 @@ static int xc4000_fwupload(struct dvb_fr
 
 		return rc;
 	}
+	dprintk(1, "Loading Firmware: %s\n", fname);
+
 	p = fw->data;
 	endp = p + fw->size;
 
@@ -1157,14 +1172,14 @@ static int xc4000_set_params(struct dvb_
 	case SYS_ATSC:
 		dprintk(1, "%s() VSB modulation\n", __func__);
 		priv->rf_mode = XC_RF_MODE_AIR;
-		priv->freq_hz = c->frequency - 1750000;
+		priv->freq_offset = 1750000;
 		priv->video_standard = XC4000_DTV6;
 		type = DTV6;
 		break;
 	case SYS_DVBC_ANNEX_B:
 		dprintk(1, "%s() QAM modulation\n", __func__);
 		priv->rf_mode = XC_RF_MODE_CABLE;
-		priv->freq_hz = c->frequency - 1750000;
+		priv->freq_offset = 1750000;
 		priv->video_standard = XC4000_DTV6;
 		type = DTV6;
 		break;
@@ -1173,23 +1188,23 @@ static int xc4000_set_params(struct dvb_
 		dprintk(1, "%s() OFDM\n", __func__);
 		if (bw == 0) {
 			if (c->frequency < 400000000) {
-				priv->freq_hz = c->frequency - 2250000;
+				priv->freq_offset = 2250000;
 			} else {
-				priv->freq_hz = c->frequency - 2750000;
+				priv->freq_offset = 2750000;
 			}
 			priv->video_standard = XC4000_DTV7_8;
 			type = DTV78;
 		} else if (bw <= 6000000) {
 			priv->video_standard = XC4000_DTV6;
-			priv->freq_hz = c->frequency - 1750000;
+			priv->freq_offset = 1750000;
 			type = DTV6;
 		} else if (bw <= 7000000) {
 			priv->video_standard = XC4000_DTV7;
-			priv->freq_hz = c->frequency - 2250000;
+			priv->freq_offset = 2250000;
 			type = DTV7;
 		} else {
 			priv->video_standard = XC4000_DTV8;
-			priv->freq_hz = c->frequency - 2750000;
+			priv->freq_offset = 2750000;
 			type = DTV8;
 		}
 		priv->rf_mode = XC_RF_MODE_AIR;
@@ -1200,6 +1215,8 @@ static int xc4000_set_params(struct dvb_
 		goto fail;
 	}
 
+	priv->freq_hz = c->frequency - priv->freq_offset;
+
 	dprintk(1, "%s() frequency=%d (compensated)\n",
 		__func__, priv->freq_hz);
 
@@ -1520,7 +1537,7 @@ static int xc4000_get_frequency(struct d
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 
-	*freq = priv->freq_hz;
+	*freq = priv->freq_hz + priv->freq_offset;
 
 	if (debug) {
 		mutex_lock(&priv->lock);
@@ -1668,7 +1685,6 @@ struct dvb_frontend *xc4000_attach(struc
 	switch (instance) {
 	case 0:
 		goto fail;
-		break;
 	case 1:
 		/* new tuner instance */
 		priv->bandwidth = 6000000;
@@ -1755,3 +1771,4 @@ EXPORT_SYMBOL(xc4000_attach);
 MODULE_AUTHOR("Steven Toth, Davide Ferri");
 MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
 MODULE_LICENSE("GPL");
+/*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/tuners/xc5000.c linux-libre-3.17-rc7-gnu/drivers/media/tuners/xc5000.c
--- linux-libre-3.16-gnu/drivers/media/tuners/xc5000.c	2014-08-07 04:47:19.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/tuners/xc5000.c	2014-09-28 21:28:08.000000000 -0400
@@ -56,7 +56,7 @@ struct xc5000_priv {
 
 	u32 if_khz;
 	u16 xtal_khz;
-	u32 freq_hz;
+	u32 freq_hz, freq_offset;
 	u32 bandwidth;
 	u8  video_standard;
 	u8  rf_mode;
@@ -625,48 +625,30 @@ static int xc_set_xtal(struct dvb_fronte
 	return ret;
 }
 
-static int xc5000_fwupload(struct dvb_frontend *fe)
+static int xc5000_fwupload(struct dvb_frontend *fe,
+			   const struct xc5000_fw_cfg *desired_fw,
+			   const struct firmware *fw)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
-	const struct firmware *fw;
 	int ret;
-	const struct xc5000_fw_cfg *desired_fw =
-		xc5000_assign_firmware(priv->chip_id);
-	priv->pll_register_no = desired_fw->pll_reg;
-	priv->init_status_supported = desired_fw->init_status_supported;
-	priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
 
 	/* request the firmware, this will block and timeout */
-	printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
+	dprintk(1, "waiting for firmware upload (%s)...\n",
 		desired_fw->name);
 
-	ret = reject_firmware(&fw, desired_fw->name,
-		priv->i2c_props.adap->dev.parent);
-	if (ret) {
-		printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
-		goto out;
-	} else {
-		printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
-		       fw->size);
-		ret = 0;
-	}
+	priv->pll_register_no = desired_fw->pll_reg;
+	priv->init_status_supported = desired_fw->init_status_supported;
+	priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
 
-	if (fw->size != desired_fw->size) {
-		printk(KERN_ERR "xc5000: firmware incorrect size\n");
-		ret = -EINVAL;
-	} else {
-		printk(KERN_INFO "xc5000: firmware uploading...\n");
-		ret = xc_load_i2c_sequence(fe,  fw->data);
-		if (0 == ret)
-			ret = xc_set_xtal(fe);
-		if (0 == ret)
-			printk(KERN_INFO "xc5000: firmware upload complete...\n");
-		else
-			printk(KERN_ERR "xc5000: firmware upload failed...\n");
-	}
 
-out:
-	release_firmware(fw);
+	dprintk(1, "firmware uploading...\n");
+	ret = xc_load_i2c_sequence(fe,  fw->data);
+	if (!ret) {
+		ret = xc_set_xtal(fe);
+		dprintk(1, "Firmware upload complete...\n");
+	} else
+		printk(KERN_ERR "xc5000: firmware upload failed...\n");
+
 	return ret;
 }
 
@@ -749,13 +731,13 @@ static int xc5000_set_params(struct dvb_
 	case SYS_ATSC:
 		dprintk(1, "%s() VSB modulation\n", __func__);
 		priv->rf_mode = XC_RF_MODE_AIR;
-		priv->freq_hz = freq - 1750000;
+		priv->freq_offset = 1750000;
 		priv->video_standard = DTV6;
 		break;
 	case SYS_DVBC_ANNEX_B:
 		dprintk(1, "%s() QAM modulation\n", __func__);
 		priv->rf_mode = XC_RF_MODE_CABLE;
-		priv->freq_hz = freq - 1750000;
+		priv->freq_offset = 1750000;
 		priv->video_standard = DTV6;
 		break;
 	case SYS_ISDBT:
@@ -770,15 +752,15 @@ static int xc5000_set_params(struct dvb_
 		switch (bw) {
 		case 6000000:
 			priv->video_standard = DTV6;
-			priv->freq_hz = freq - 1750000;
+			priv->freq_offset = 1750000;
 			break;
 		case 7000000:
 			priv->video_standard = DTV7;
-			priv->freq_hz = freq - 2250000;
+			priv->freq_offset = 2250000;
 			break;
 		case 8000000:
 			priv->video_standard = DTV8;
-			priv->freq_hz = freq - 2750000;
+			priv->freq_offset = 2750000;
 			break;
 		default:
 			printk(KERN_ERR "xc5000 bandwidth not set!\n");
@@ -792,15 +774,15 @@ static int xc5000_set_params(struct dvb_
 		priv->rf_mode = XC_RF_MODE_CABLE;
 		if (bw <= 6000000) {
 			priv->video_standard = DTV6;
-			priv->freq_hz = freq - 1750000;
+			priv->freq_offset = 1750000;
 			b = 6;
 		} else if (bw <= 7000000) {
 			priv->video_standard = DTV7;
-			priv->freq_hz = freq - 2250000;
+			priv->freq_offset = 2250000;
 			b = 7;
 		} else {
 			priv->video_standard = DTV7_8;
-			priv->freq_hz = freq - 2750000;
+			priv->freq_offset = 2750000;
 			b = 8;
 		}
 		dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
@@ -811,6 +793,8 @@ static int xc5000_set_params(struct dvb_
 		return -EINVAL;
 	}
 
+	priv->freq_hz = freq - priv->freq_offset;
+
 	dprintk(1, "%s() frequency=%d (compensated to %d)\n",
 		__func__, freq, priv->freq_hz);
 
@@ -1061,7 +1045,7 @@ static int xc5000_get_frequency(struct d
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	dprintk(1, "%s()\n", __func__);
-	*freq = priv->freq_hz;
+	*freq = priv->freq_hz + priv->freq_offset;
 	return 0;
 }
 
@@ -1099,42 +1083,65 @@ static int xc5000_get_status(struct dvb_
 static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret = 0;
+	const struct xc5000_fw_cfg *desired_fw = xc5000_assign_firmware(priv->chip_id);
+	const struct firmware *fw;
+	int ret, i;
 	u16 pll_lock_status;
 	u16 fw_ck;
 
 	cancel_delayed_work(&priv->timer_sleep);
 
-	if (force || xc5000_is_firmware_loaded(fe) != 0) {
+	if (!force && xc5000_is_firmware_loaded(fe) == 0)
+		return 0;
 
-fw_retry:
+	ret = reject_firmware(&fw, desired_fw->name,
+			       priv->i2c_props.adap->dev.parent);
+	if (ret) {
+		printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
+		return ret;
+	}
 
-		ret = xc5000_fwupload(fe);
+	dprintk(1, "firmware read %Zu bytes.\n", fw->size);
+
+	if (fw->size != desired_fw->size) {
+		printk(KERN_ERR "xc5000: Firmware file with incorrect size\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* Try up to 5 times to load firmware */
+	for (i = 0; i < 5; i++) {
+		if (i)
+			printk(KERN_CONT " - retrying to upload firmware.\n");
+
+		ret = xc5000_fwupload(fe, desired_fw, fw);
 		if (ret != 0)
-			return ret;
+			goto err;
 
 		msleep(20);
 
 		if (priv->fw_checksum_supported) {
-			if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
-			    != 0) {
-				dprintk(1, "%s() FW checksum reading failed.\n",
-					__func__);
-				goto fw_retry;
+			if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)) {
+				printk(KERN_ERR
+				       "xc5000: FW checksum reading failed.");
+				continue;
 			}
 
-			if (fw_ck == 0) {
-				dprintk(1, "%s() FW checksum failed = 0x%04x\n",
-					__func__, fw_ck);
-				goto fw_retry;
+			if (!fw_ck) {
+				printk(KERN_ERR
+				       "xc5000: FW checksum failed = 0x%04x.",
+				       fw_ck);
+				continue;
 			}
 		}
 
 		/* Start the tuner self-calibration process */
-		ret |= xc_initialize(priv);
-
-		if (ret != 0)
-			goto fw_retry;
+		ret = xc_initialize(priv);
+		if (ret) {
+			printk(KERN_ERR
+			       "xc5000: Can't request Self-callibration.");
+			continue;
+		}
 
 		/* Wait for calibration to complete.
 		 * We could continue but XC5000 will clock stretch subsequent
@@ -1144,15 +1151,17 @@ fw_retry:
 		msleep(100);
 
 		if (priv->init_status_supported) {
-			if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) {
-				dprintk(1, "%s() FW failed reading init status.\n",
-					__func__);
-				goto fw_retry;
+			if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck)) {
+				printk(KERN_ERR
+				       "xc5000: FW failed reading init status.");
+				continue;
 			}
 
-			if (fw_ck == 0) {
-				dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
-				goto fw_retry;
+			if (!fw_ck) {
+				printk(KERN_ERR
+				       "xc5000: FW init status failed = 0x%04x.",
+				       fw_ck);
+				continue;
 			}
 		}
 
@@ -1161,15 +1170,27 @@ fw_retry:
 				       &pll_lock_status);
 			if (pll_lock_status > 63) {
 				/* PLL is unlocked, force reload of the firmware */
-				printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
-				goto fw_retry;
+				printk(KERN_ERR
+				       "xc5000: PLL not running after fwload.");
+				continue;
 			}
 		}
 
 		/* Default to "CABLE" mode */
-		ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+		ret = xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+		if (!ret)
+			break;
+		printk(KERN_ERR "xc5000: can't set to cable mode.");
 	}
 
+err:
+	if (!ret)
+		printk(KERN_INFO "xc5000: Firmware %s loaded and running.\n",
+		       desired_fw->name);
+	else
+		printk(KERN_CONT " - too many retries. Giving up\n");
+
+	release_firmware(fw);
 	return ret;
 }
 
@@ -1302,7 +1323,6 @@ struct dvb_frontend *xc5000_attach(struc
 	switch (instance) {
 	case 0:
 		goto fail;
-		break;
 	case 1:
 		/* new tuner instance */
 		priv->bandwidth = 6000000;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/airspy/airspy.c linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/airspy.c
--- linux-libre-3.16-gnu/drivers/media/usb/airspy/airspy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/airspy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1132 @@
+/*
+ * AirSpy SDR driver
+ *
+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* AirSpy USB API commands (from AirSpy Library) */
+enum {
+	CMD_INVALID                       = 0x00,
+	CMD_RECEIVER_MODE                 = 0x01,
+	CMD_SI5351C_WRITE                 = 0x02,
+	CMD_SI5351C_READ                  = 0x03,
+	CMD_R820T_WRITE                   = 0x04,
+	CMD_R820T_READ                    = 0x05,
+	CMD_SPIFLASH_ERASE                = 0x06,
+	CMD_SPIFLASH_WRITE                = 0x07,
+	CMD_SPIFLASH_READ                 = 0x08,
+	CMD_BOARD_ID_READ                 = 0x09,
+	CMD_VERSION_STRING_READ           = 0x0a,
+	CMD_BOARD_PARTID_SERIALNO_READ    = 0x0b,
+	CMD_SET_SAMPLE_RATE               = 0x0c,
+	CMD_SET_FREQ                      = 0x0d,
+	CMD_SET_LNA_GAIN                  = 0x0e,
+	CMD_SET_MIXER_GAIN                = 0x0f,
+	CMD_SET_VGA_GAIN                  = 0x10,
+	CMD_SET_LNA_AGC                   = 0x11,
+	CMD_SET_MIXER_AGC                 = 0x12,
+	CMD_SET_PACKING                   = 0x13,
+};
+
+/*
+ *       bEndpointAddress     0x81  EP 1 IN
+ *         Transfer Type            Bulk
+ *       wMaxPacketSize     0x0200  1x 512 bytes
+ */
+#define MAX_BULK_BUFS            (6)
+#define BULK_BUFFER_SIZE         (128 * 512)
+
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   = 20000000,
+		.rangehigh  = 20000000,
+	},
+};
+
+static const struct v4l2_frequency_band bands_rf[] = {
+	{
+		.tuner = 1,
+		.type = V4L2_TUNER_RF,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =   24000000,
+		.rangehigh  = 1750000000,
+	},
+};
+
+/* stream formats */
+struct airspy_format {
+	char	*name;
+	u32	pixelformat;
+	u32	buffersize;
+};
+
+/* format descriptions for capture and preview */
+static struct airspy_format formats[] = {
+	{
+		.name		= "Real U12LE",
+		.pixelformat	= V4L2_SDR_FMT_RU12LE,
+		.buffersize	= BULK_BUFFER_SIZE,
+	},
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct airspy_frame_buf {
+	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct list_head list;
+};
+
+struct airspy {
+#define POWER_ON           (1 << 1)
+#define URB_BUF            (1 << 2)
+#define USB_STATE_URB_BUF  (1 << 3)
+	unsigned long flags;
+
+	struct usb_device *udev;
+	struct video_device vdev;
+	struct v4l2_device v4l2_dev;
+
+	/* videobuf2 queue and queued buffers list */
+	struct vb2_queue vb_queue;
+	struct list_head queued_bufs;
+	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+	unsigned sequence;	     /* Buffer sequence counter */
+	unsigned int vb_full;        /* vb is full and packets dropped */
+
+	/* Note if taking both locks v4l2_lock must always be locked first! */
+	struct mutex v4l2_lock;      /* Protects everything else */
+	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
+
+	struct urb     *urb_list[MAX_BULK_BUFS];
+	int            buf_num;
+	unsigned long  buf_size;
+	u8             *buf_list[MAX_BULK_BUFS];
+	dma_addr_t     dma_addr[MAX_BULK_BUFS];
+	int            urbs_initialized;
+	int            urbs_submitted;
+
+	/* USB control message buffer */
+	#define BUF_SIZE 24
+	u8 buf[BUF_SIZE];
+
+	/* Current configuration */
+	unsigned int f_adc;
+	unsigned int f_rf;
+	u32 pixelformat;
+	u32 buffersize;
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *lna_gain_auto;
+	struct v4l2_ctrl *lna_gain;
+	struct v4l2_ctrl *mixer_gain_auto;
+	struct v4l2_ctrl *mixer_gain;
+	struct v4l2_ctrl *if_gain;
+
+	/* Sample rate calc */
+	unsigned long jiffies_next;
+	unsigned int sample;
+	unsigned int sample_measured;
+};
+
+#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+	char *_direction; \
+	if (_t & USB_DIR_IN) \
+		_direction = "<<<"; \
+	else \
+		_direction = ">>>"; \
+	dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+			"%s %*ph\n",  __func__, _t, _r, _v & 0xff, _v >> 8, \
+			_i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+			_l, _b); \
+}
+
+/* execute firmware command */
+static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
+		u8 *data, u16 size)
+{
+	int ret;
+	unsigned int pipe;
+	u8 requesttype;
+
+	switch (request) {
+	case CMD_RECEIVER_MODE:
+	case CMD_SET_FREQ:
+		pipe = usb_sndctrlpipe(s->udev, 0);
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
+		break;
+	case CMD_BOARD_ID_READ:
+	case CMD_VERSION_STRING_READ:
+	case CMD_BOARD_PARTID_SERIALNO_READ:
+	case CMD_SET_LNA_GAIN:
+	case CMD_SET_MIXER_GAIN:
+	case CMD_SET_VGA_GAIN:
+	case CMD_SET_LNA_AGC:
+	case CMD_SET_MIXER_AGC:
+		pipe = usb_rcvctrlpipe(s->udev, 0);
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
+		break;
+	default:
+		dev_err(&s->udev->dev, "Unknown command %02x\n", request);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* write request */
+	if (!(requesttype & USB_DIR_IN))
+		memcpy(s->buf, data, size);
+
+	ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
+			index, s->buf, size, 1000);
+	airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
+			index, s->buf, size);
+	if (ret < 0) {
+		dev_err(&s->udev->dev,
+				"usb_control_msg() failed %d request %02x\n",
+				ret, request);
+		goto err;
+	}
+
+	/* read request */
+	if (requesttype & USB_DIR_IN)
+		memcpy(data, s->buf, size);
+
+	return 0;
+err:
+	return ret;
+}
+
+/* Private functions */
+static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
+{
+	unsigned long flags = 0;
+	struct airspy_frame_buf *buf = NULL;
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	if (list_empty(&s->queued_bufs))
+		goto leave;
+
+	buf = list_entry(s->queued_bufs.next,
+			struct airspy_frame_buf, list);
+	list_del(&buf->list);
+leave:
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	return buf;
+}
+
+static unsigned int airspy_convert_stream(struct airspy *s,
+		void *dst, void *src, unsigned int src_len)
+{
+	unsigned int dst_len;
+
+	if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
+		memcpy(dst, src, src_len);
+		dst_len = src_len;
+	} else {
+		dst_len = 0;
+	}
+
+	/* calculate samping rate and output it in 10 seconds intervals */
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+		#define MSECS 10000UL
+		unsigned int samples = s->sample - s->sample_measured;
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample_measured = s->sample;
+		dev_dbg(&s->udev->dev,
+				"slen=%d samples=%u msecs=%lu sample rate=%lu\n",
+				src_len, samples, MSECS,
+				samples * 1000UL / MSECS);
+	}
+
+	/* total number of samples */
+	s->sample += src_len / 2;
+
+	return dst_len;
+}
+
+/*
+ * This gets called for the bulk stream pipe. This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void airspy_urb_complete(struct urb *urb)
+{
+	struct airspy *s = urb->context;
+	struct airspy_frame_buf *fbuf;
+
+	dev_dbg_ratelimited(&s->udev->dev,
+			"%s: status=%d length=%d/%d errors=%d\n",
+			__func__, urb->status, urb->actual_length,
+			urb->transfer_buffer_length, urb->error_count);
+
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:            /* error */
+		dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
+				urb->status);
+		break;
+	}
+
+	if (likely(urb->actual_length > 0)) {
+		void *ptr;
+		unsigned int len;
+		/* get free framebuffer */
+		fbuf = airspy_get_next_fill_buf(s);
+		if (unlikely(fbuf == NULL)) {
+			s->vb_full++;
+			dev_notice_ratelimited(&s->udev->dev,
+					"videobuf is full, %d packets dropped\n",
+					s->vb_full);
+			goto skip;
+		}
+
+		/* fill framebuffer */
+		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+		len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
+				urb->actual_length);
+		vb2_set_plane_payload(&fbuf->vb, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
+		fbuf->vb.v4l2_buf.sequence = s->sequence++;
+		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+	}
+skip:
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int airspy_kill_urbs(struct airspy *s)
+{
+	int i;
+
+	for (i = s->urbs_submitted - 1; i >= 0; i--) {
+		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
+		/* stop the URB */
+		usb_kill_urb(s->urb_list[i]);
+	}
+	s->urbs_submitted = 0;
+
+	return 0;
+}
+
+static int airspy_submit_urbs(struct airspy *s)
+{
+	int i, ret;
+
+	for (i = 0; i < s->urbs_initialized; i++) {
+		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
+		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+		if (ret) {
+			dev_err(&s->udev->dev,
+					"Could not submit URB no. %d - get them all back\n",
+					i);
+			airspy_kill_urbs(s);
+			return ret;
+		}
+		s->urbs_submitted++;
+	}
+
+	return 0;
+}
+
+static int airspy_free_stream_bufs(struct airspy *s)
+{
+	if (s->flags & USB_STATE_URB_BUF) {
+		while (s->buf_num) {
+			s->buf_num--;
+			dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
+					__func__, s->buf_num);
+			usb_free_coherent(s->udev, s->buf_size,
+					  s->buf_list[s->buf_num],
+					  s->dma_addr[s->buf_num]);
+		}
+	}
+	s->flags &= ~USB_STATE_URB_BUF;
+
+	return 0;
+}
+
+static int airspy_alloc_stream_bufs(struct airspy *s)
+{
+	s->buf_num = 0;
+	s->buf_size = BULK_BUFFER_SIZE;
+
+	dev_dbg(&s->udev->dev,
+			"%s: all in all I will use %u bytes for streaming\n",
+			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
+		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+				BULK_BUFFER_SIZE, GFP_ATOMIC,
+				&s->dma_addr[s->buf_num]);
+		if (!s->buf_list[s->buf_num]) {
+			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
+					__func__, s->buf_num);
+			airspy_free_stream_bufs(s);
+			return -ENOMEM;
+		}
+
+		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+				__func__, s->buf_num,
+				s->buf_list[s->buf_num],
+				(long long)s->dma_addr[s->buf_num]);
+		s->flags |= USB_STATE_URB_BUF;
+	}
+
+	return 0;
+}
+
+static int airspy_free_urbs(struct airspy *s)
+{
+	int i;
+
+	airspy_kill_urbs(s);
+
+	for (i = s->urbs_initialized - 1; i >= 0; i--) {
+		if (s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
+					__func__, i);
+			/* free the URBs */
+			usb_free_urb(s->urb_list[i]);
+		}
+	}
+	s->urbs_initialized = 0;
+
+	return 0;
+}
+
+static int airspy_alloc_urbs(struct airspy *s)
+{
+	int i, j;
+
+	/* allocate the URBs */
+	for (i = 0; i < MAX_BULK_BUFS; i++) {
+		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!s->urb_list[i]) {
+			dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
+			for (j = 0; j < i; j++)
+				usb_free_urb(s->urb_list[j]);
+			return -ENOMEM;
+		}
+		usb_fill_bulk_urb(s->urb_list[i],
+				s->udev,
+				usb_rcvbulkpipe(s->udev, 0x81),
+				s->buf_list[i],
+				BULK_BUFFER_SIZE,
+				airspy_urb_complete, s);
+
+		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+		s->urb_list[i]->transfer_dma = s->dma_addr[i];
+		s->urbs_initialized++;
+	}
+
+	return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void airspy_cleanup_queued_bufs(struct airspy *s)
+{
+	unsigned long flags = 0;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	while (!list_empty(&s->queued_bufs)) {
+		struct airspy_frame_buf *buf;
+		buf = list_entry(s->queued_bufs.next,
+				struct airspy_frame_buf, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void airspy_disconnect(struct usb_interface *intf)
+{
+	struct v4l2_device *v = usb_get_intfdata(intf);
+	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->vb_queue_lock);
+	mutex_lock(&s->v4l2_lock);
+	/* No need to keep the urbs around after disconnection */
+	s->udev = NULL;
+	v4l2_device_disconnect(&s->v4l2_dev);
+	video_unregister_device(&s->vdev);
+	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&s->vb_queue_lock);
+
+	v4l2_device_put(&s->v4l2_dev);
+}
+
+/* Videobuf2 operations */
+static int airspy_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+	/* Need at least 8 buffers */
+	if (vq->num_buffers + *nbuffers < 8)
+		*nbuffers = 8 - vq->num_buffers;
+	*nplanes = 1;
+	sizes[0] = PAGE_ALIGN(s->buffersize);
+
+	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+			__func__, *nbuffers, sizes[0]);
+	return 0;
+}
+
+static void airspy_buf_queue(struct vb2_buffer *vb)
+{
+	struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct airspy_frame_buf *buf =
+			container_of(vb, struct airspy_frame_buf, vb);
+	unsigned long flags = 0;
+
+	/* Check the device has not disconnected between prep and queuing */
+	if (unlikely(!s->udev)) {
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	list_add_tail(&buf->list, &s->queued_bufs);
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (!s->udev)
+		return -ENODEV;
+
+	mutex_lock(&s->v4l2_lock);
+
+	set_bit(POWER_ON, &s->flags);
+
+	s->sequence = 0;
+
+	ret = airspy_alloc_stream_bufs(s);
+	if (ret)
+		goto err;
+
+	ret = airspy_alloc_urbs(s);
+	if (ret)
+		goto err;
+
+	ret = airspy_submit_urbs(s);
+	if (ret)
+		goto err;
+
+	/* start hardware streaming */
+	ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
+	if (ret)
+		goto err;
+err:
+	mutex_unlock(&s->v4l2_lock);
+
+	return ret;
+}
+
+static void airspy_stop_streaming(struct vb2_queue *vq)
+{
+	struct airspy *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->v4l2_lock);
+
+	/* stop hardware streaming */
+	airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
+
+	airspy_kill_urbs(s);
+	airspy_free_urbs(s);
+	airspy_free_stream_bufs(s);
+
+	airspy_cleanup_queued_bufs(s);
+
+	clear_bit(POWER_ON, &s->flags);
+
+	mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops airspy_vb2_ops = {
+	.queue_setup            = airspy_queue_setup,
+	.buf_queue              = airspy_buf_queue,
+	.start_streaming        = airspy_start_streaming,
+	.stop_streaming         = airspy_stop_streaming,
+	.wait_prepare           = vb2_ops_wait_prepare,
+	.wait_finish            = vb2_ops_wait_finish,
+};
+
+static int airspy_querycap(struct file *file, void *fh,
+		struct v4l2_capability *cap)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_fmtdesc *f)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
+
+	if (f->index >= NUM_FORMATS)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
+
+	return 0;
+}
+
+static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&s->pixelformat);
+
+	f->fmt.sdr.pixelformat = s->pixelformat;
+	f->fmt.sdr.buffersize = s->buffersize;
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+
+	return 0;
+}
+
+static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *s = video_drvdata(file);
+	struct vb2_queue *q = &s->vb_queue;
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			s->pixelformat = formats[i].pixelformat;
+			s->buffersize = formats[i].buffersize;
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static int airspy_try_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct airspy *s = video_drvdata(file);
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static int airspy_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *v)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0)
+		ret = 0;
+	else if (v->index == 1)
+		ret = 0;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0) {
+		strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow  = bands[0].rangelow;
+		v->rangehigh = bands[0].rangehigh;
+		ret = 0;
+	} else if (v->index == 1) {
+		strlcpy(v->name, "AirSpy RF", sizeof(v->name));
+		v->type = V4L2_TUNER_RF;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow  = bands_rf[0].rangelow;
+		v->rangehigh = bands_rf[0].rangehigh;
+		ret = 0;
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret  = 0;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+			__func__, f->tuner, f->type);
+
+	if (f->tuner == 0) {
+		f->type = V4L2_TUNER_ADC;
+		f->frequency = s->f_adc;
+		ret = 0;
+	} else if (f->tuner == 1) {
+		f->type = V4L2_TUNER_RF;
+		f->frequency = s->f_rf;
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_s_frequency(struct file *file, void *priv,
+		const struct v4l2_frequency *f)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+	u8 buf[4];
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->tuner == 0) {
+		s->f_adc = clamp_t(unsigned int, f->frequency,
+				bands[0].rangelow,
+				bands[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = 0;
+	} else if (f->tuner == 1) {
+		s->f_rf = clamp_t(unsigned int, f->frequency,
+				bands_rf[0].rangelow,
+				bands_rf[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+				__func__, s->f_rf);
+		buf[0] = (s->f_rf >>  0) & 0xff;
+		buf[1] = (s->f_rf >>  8) & 0xff;
+		buf[2] = (s->f_rf >> 16) & 0xff;
+		buf[3] = (s->f_rf >> 24) & 0xff;
+		ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int airspy_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
+{
+	struct airspy *s = video_drvdata(file);
+	int ret;
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->tuner == 0) {
+		if (band->index >= ARRAY_SIZE(bands)) {
+			ret = -EINVAL;
+		} else {
+			*band = bands[band->index];
+			ret = 0;
+		}
+	} else if (band->tuner == 1) {
+		if (band->index >= ARRAY_SIZE(bands_rf)) {
+			ret = -EINVAL;
+		} else {
+			*band = bands_rf[band->index];
+			ret = 0;
+		}
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
+	.vidioc_querycap          = airspy_querycap,
+
+	.vidioc_enum_fmt_sdr_cap  = airspy_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = airspy_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = airspy_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = airspy_try_fmt_sdr_cap,
+
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
+
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
+
+	.vidioc_g_tuner           = airspy_g_tuner,
+	.vidioc_s_tuner           = airspy_s_tuner,
+
+	.vidioc_g_frequency       = airspy_g_frequency,
+	.vidioc_s_frequency       = airspy_s_frequency,
+	.vidioc_enum_freq_bands   = airspy_enum_freq_bands,
+
+	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_log_status        = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations airspy_fops = {
+	.owner                    = THIS_MODULE,
+	.open                     = v4l2_fh_open,
+	.release                  = vb2_fop_release,
+	.read                     = vb2_fop_read,
+	.poll                     = vb2_fop_poll,
+	.mmap                     = vb2_fop_mmap,
+	.unlocked_ioctl           = video_ioctl2,
+};
+
+static struct video_device airspy_template = {
+	.name                     = "AirSpy SDR",
+	.release                  = video_device_release_empty,
+	.fops                     = &airspy_fops,
+	.ioctl_ops                = &airspy_ioctl_ops,
+};
+
+static void airspy_video_release(struct v4l2_device *v)
+{
+	struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+	v4l2_ctrl_handler_free(&s->hdl);
+	v4l2_device_unregister(&s->v4l2_dev);
+	kfree(s);
+}
+
+static int airspy_set_lna_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+			__func__, s->lna_gain_auto->cur.val,
+			s->lna_gain_auto->val, s->lna_gain->cur.val,
+			s->lna_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+
+	if (s->lna_gain_auto->val == false) {
+		ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
+				&u8tmp, 1);
+		if (ret)
+			goto err;
+	}
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_set_mixer_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+			__func__, s->mixer_gain_auto->cur.val,
+			s->mixer_gain_auto->val, s->mixer_gain->cur.val,
+			s->mixer_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+
+	if (s->mixer_gain_auto->val == false) {
+		ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
+				s->mixer_gain->val, &u8tmp, 1);
+		if (ret)
+			goto err;
+	}
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_set_if_gain(struct airspy *s)
+{
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
+			__func__, s->if_gain->cur.val, s->if_gain->val);
+
+	ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
+			&u8tmp, 1);
+	if (ret)
+		goto err;
+err:
+	if (ret)
+		dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
+	int ret;
+
+	switch (ctrl->id) {
+	case  V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
+	case  V4L2_CID_RF_TUNER_LNA_GAIN:
+		ret = airspy_set_lna_gain(s);
+		break;
+	case  V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
+	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
+		ret = airspy_set_mixer_gain(s);
+		break;
+	case  V4L2_CID_RF_TUNER_IF_GAIN:
+		ret = airspy_set_if_gain(s);
+		break;
+	default:
+		dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
+				__func__, ctrl->id, ctrl->name);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
+	.s_ctrl = airspy_s_ctrl,
+};
+
+static int airspy_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct airspy *s = NULL;
+	int ret;
+	u8 u8tmp, buf[BUF_SIZE];
+
+	s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
+	if (s == NULL) {
+		dev_err(&udev->dev,
+				"Could not allocate memory for airspy state\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&s->v4l2_lock);
+	mutex_init(&s->vb_queue_lock);
+	spin_lock_init(&s->queued_bufs_lock);
+	INIT_LIST_HEAD(&s->queued_bufs);
+	s->udev = udev;
+	s->f_adc = bands[0].rangelow;
+	s->f_rf = bands_rf[0].rangelow;
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+
+	/* Detect device */
+	ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
+	if (ret == 0)
+		ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
+				buf, BUF_SIZE);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not detect board\n");
+		goto err_free_mem;
+	}
+
+	buf[BUF_SIZE - 1] = '\0';
+
+	dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
+	dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
+
+	/* Init videobuf2 queue structure */
+	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	s->vb_queue.drv_priv = s;
+	s->vb_queue.buf_struct_size = sizeof(struct airspy_frame_buf);
+	s->vb_queue.ops = &airspy_vb2_ops;
+	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	ret = vb2_queue_init(&s->vb_queue);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+		goto err_free_mem;
+	}
+
+	/* Init video_device structure */
+	s->vdev = airspy_template;
+	s->vdev.queue = &s->vb_queue;
+	s->vdev.queue->lock = &s->vb_queue_lock;
+	video_set_drvdata(&s->vdev, s);
+
+	/* Register the v4l2_device structure */
+	s->v4l2_dev.release = airspy_video_release;
+	ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register v4l2-device (%d)\n", ret);
+		goto err_free_mem;
+	}
+
+	/* Register controls */
+	v4l2_ctrl_handler_init(&s->hdl, 5);
+	s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
+	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
+	v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+	s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
+	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
+	v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+			V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->udev->dev, "Could not initialize controls\n");
+		goto err_free_controls;
+	}
+
+	v4l2_ctrl_handler_setup(&s->hdl);
+
+	s->v4l2_dev.ctrl_handler = &s->hdl;
+	s->vdev.v4l2_dev = &s->v4l2_dev;
+	s->vdev.lock = &s->v4l2_lock;
+
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register as video device (%d)\n",
+				ret);
+		goto err_unregister_v4l2_dev;
+	}
+	dev_info(&s->udev->dev, "Registered as %s\n",
+			video_device_node_name(&s->vdev));
+	dev_notice(&s->udev->dev,
+			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
+			KBUILD_MODNAME);
+	return 0;
+
+err_free_controls:
+	v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_v4l2_dev:
+	v4l2_device_unregister(&s->v4l2_dev);
+err_free_mem:
+	kfree(s);
+	return ret;
+}
+
+/* USB device ID list */
+static struct usb_device_id airspy_id_table[] = {
+	{ USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, airspy_id_table);
+
+/* USB subsystem interface */
+static struct usb_driver airspy_driver = {
+	.name                     = KBUILD_MODNAME,
+	.probe                    = airspy_probe,
+	.disconnect               = airspy_disconnect,
+	.id_table                 = airspy_id_table,
+};
+
+module_usb_driver(airspy_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("AirSpy SDR");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/airspy/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/airspy/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,10 @@
+config USB_AIRSPY
+	tristate "AirSpy"
+	depends on VIDEO_V4L2
+	select VIDEOBUF2_VMALLOC
+	---help---
+	  This is a video4linux2 driver for AirSpy SDR device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called airspy
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/airspy/Makefile linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/Makefile
--- linux-libre-3.16-gnu/drivers/media/usb/airspy/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/airspy/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_AIRSPY)              += airspy.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-cards.c linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-cards.c
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-cards.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-cards.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = {
 		.name	= "Hauppauge HVR850",
 		.tuner_type = TUNER_XC5000,
 		.tuner_addr = 0x61,
-		.i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
 		.input = {
 			{
 				.type = AU0828_VMUX_TELEVISION,
@@ -71,13 +71,14 @@ struct au0828_board au0828_boards[] = {
 		.name	= "Hauppauge HVR950Q",
 		.tuner_type = TUNER_XC5000,
 		.tuner_addr = 0x61,
+		.has_ir_i2c = 1,
 		/* The au0828 hardware i2c implementation does not properly
 		   support the xc5000's i2c clock stretching.  So we need to
 		   lower the clock frequency enough where the 15us clock
 		   stretch fits inside of a normal clock cycle, or else the
 		   au0828 fails to set the STOP bit.  A 30 KHz clock puts the
 		   clock pulse width at 18us */
-		.i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
 		.input = {
 			{
 				.type = AU0828_VMUX_TELEVISION,
@@ -108,7 +109,7 @@ struct au0828_board au0828_boards[] = {
 		.name	= "DViCO FusionHDTV USB",
 		.tuner_type = UNSET,
 		.tuner_addr = ADDR_UNSET,
-		.i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+		.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
 	},
 	[AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
 		.name = "Hauppauge Woodbury",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-core.c
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,12 @@
  * 2 = USB handling
  * 4 = I2C related
  * 8 = Bridge related
+ * 16 = IR related
  */
 int au0828_debug;
 module_param_named(debug, au0828_debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
+MODULE_PARM_DESC(debug,
+		 "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");
 
 static unsigned int disable_usb_speed_check;
 module_param(disable_usb_speed_check, int, 0444);
@@ -151,6 +153,9 @@ static void au0828_usb_disconnect(struct
 
 	dprintk(1, "%s()\n", __func__);
 
+#ifdef CONFIG_VIDEO_AU0828_RC
+	au0828_rc_unregister(dev);
+#endif
 	/* Digital TV */
 	au0828_dvb_unregister(dev);
 
@@ -261,9 +266,15 @@ static int au0828_usb_probe(struct usb_i
 		pr_err("%s() au0282_dev_register failed\n",
 		       __func__);
 
+#ifdef CONFIG_VIDEO_AU0828_RC
+	/* Remote controller */
+	au0828_rc_register(dev);
+#endif
 
-	/* Store the pointer to the au0828_dev so it can be accessed in
-	   au0828_usb_disconnect */
+	/*
+	 * Store the pointer to the au0828_dev so it can be accessed in
+	 * au0828_usb_disconnect
+	 */
 	usb_set_intfdata(interface, dev);
 
 	printk(KERN_INFO "Registered device AU0828 [%s]\n",
@@ -279,6 +290,8 @@ static struct usb_driver au0828_usb_driv
 	.probe		= au0828_usb_probe,
 	.disconnect	= au0828_usb_disconnect,
 	.id_table	= au0828_usb_id_table,
+
+	/* FIXME: Add suspend and resume functions */
 };
 
 static int __init au0828_init(void)
@@ -298,6 +311,10 @@ static int __init au0828_init(void)
 		printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
 		       __func__);
 
+	if (au0828_debug & 16)
+		printk(KERN_INFO "%s() IR Debugging is enabled\n",
+		       __func__);
+
 	printk(KERN_INFO "au0828 driver loaded\n");
 
 	ret = usb_register(&au0828_usb_driver);
@@ -318,4 +335,4 @@ module_exit(au0828_exit);
 MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.2");
+MODULE_VERSION("0.0.3");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828.h linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828.h
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828.h	2014-09-28 17:29:07.000000000 -0400
@@ -88,6 +88,7 @@ struct au0828_board {
 	unsigned int tuner_type;
 	unsigned char tuner_addr;
 	unsigned char i2c_clk_divider;
+	unsigned char has_ir_i2c:1;
 	struct au0828_input input[AU0828_MAX_INPUT];
 
 };
@@ -213,6 +214,10 @@ struct au0828_dev {
 	struct v4l2_device v4l2_dev;
 	struct v4l2_ctrl_handler v4l2_ctrl_hdl;
 #endif
+#ifdef CONFIG_VIDEO_AU0828_RC
+	struct au0828_rc *ir;
+#endif
+
 	int users;
 	unsigned int resources;	/* resources in use */
 	struct video_device *vdev;
@@ -319,3 +324,9 @@ extern struct videobuf_queue_ops au0828_
 	do { if (au0828_debug & level)\
 		printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
 	} while (0)
+
+/* au0828-input.c */
+int au0828_rc_register(struct au0828_dev *dev);
+void au0828_rc_unregister(struct au0828_dev *dev);
+int au0828_rc_suspend(struct au0828_dev *dev);
+int au0828_rc_resume(struct au0828_dev *dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-i2c.c
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,25 +141,27 @@ static int i2c_sendbytes(struct i2c_adap
 {
 	int i, strobe = 0;
 	struct au0828_dev *dev = i2c_adap->algo_data;
+	u8 i2c_speed = dev->board.i2c_clk_divider;
 
 	dprintk(4, "%s()\n", __func__);
 
 	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 
-	/* Set the I2C clock */
 	if (((dev->board.tuner_type == TUNER_XC5000) ||
 	     (dev->board.tuner_type == TUNER_XC5000C)) &&
-	    (dev->board.tuner_addr == msg->addr) &&
-	    (msg->len == 64)) {
-		/* Hack to speed up firmware load.  The xc5000 lets us do up
-		   to 400 KHz when in firmware download mode */
-		au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-			     AU0828_I2C_CLK_250KHZ);
-	} else {
-		/* Use the i2c clock speed in the board configuration */
-		au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-			     dev->board.i2c_clk_divider);
+	    (dev->board.tuner_addr == msg->addr)) {
+		/*
+		 * Due to I2C clock stretch, we need to use a lower speed
+		 * on xc5000 for commands. However, firmware transfer can
+		 * speed up to 400 KHz.
+		 */
+		if (msg->len == 64)
+			i2c_speed = AU0828_I2C_CLK_250KHZ;
+		else
+			i2c_speed = AU0828_I2C_CLK_20KHZ;
 	}
+	/* Set the I2C clock */
+	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
 
 	/* Hardware needs 8 bit addresses */
 	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
@@ -228,15 +230,24 @@ static int i2c_readbytes(struct i2c_adap
 	const struct i2c_msg *msg, int joined)
 {
 	struct au0828_dev *dev = i2c_adap->algo_data;
+	u8 i2c_speed = dev->board.i2c_clk_divider;
 	int i;
 
 	dprintk(4, "%s()\n", __func__);
 
 	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 
+	/*
+	 * Due to xc5000c clock stretch, we cannot use full speed at
+	 * readings from xc5000, as otherwise they'll fail.
+	 */
+	if (((dev->board.tuner_type == TUNER_XC5000) ||
+	     (dev->board.tuner_type == TUNER_XC5000C)) &&
+	    (dev->board.tuner_addr == msg->addr))
+		i2c_speed = AU0828_I2C_CLK_20KHZ;
+
 	/* Set the I2C clock */
-	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-		     dev->board.i2c_clk_divider);
+	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
 
 	/* Hardware needs 8 bit addresses */
 	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-input.c linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-input.c
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-input.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,386 @@
+/*
+  handle au0828 IR remotes via linux kernel input layer.
+
+   Copyright (C) 2014 Mauro Carvalho Chehab <mchehab@samsung.com>
+   Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+  Based on em28xx-input.c.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+
+#include "au0828.h"
+
+struct au0828_rc {
+	struct au0828_dev *dev;
+	struct rc_dev *rc;
+	char name[32];
+	char phys[32];
+
+	/* poll decoder */
+	int polling;
+	struct delayed_work work;
+
+	/* i2c slave address of external device (if used) */
+	u16 i2c_dev_addr;
+
+	int  (*get_key_i2c)(struct au0828_rc *ir);
+};
+
+/*
+ * AU8522 has a builtin IR receiver. Add functions to get IR from it
+ */
+
+static int au8522_rc_write(struct au0828_rc *ir, u16 reg, u8 data)
+{
+	int rc;
+	char buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
+	struct i2c_msg msg = { .addr = ir->i2c_dev_addr, .flags = 0,
+			       .buf = buf, .len = sizeof(buf) };
+
+	rc = i2c_transfer(ir->dev->i2c_client.adapter, &msg, 1);
+
+	if (rc < 0)
+		return rc;
+
+	return (rc == 1) ? 0 : -EIO;
+}
+
+static int au8522_rc_read(struct au0828_rc *ir, u16 reg, int val,
+				 char *buf, int size)
+{
+	int rc;
+	char obuf[3];
+	struct i2c_msg msg[2] = { { .addr = ir->i2c_dev_addr, .flags = 0,
+				    .buf = obuf, .len = 2 },
+				  { .addr = ir->i2c_dev_addr, .flags = I2C_M_RD,
+				    .buf = buf, .len = size } };
+
+	obuf[0] = 0x40 | reg >> 8;
+	obuf[1] = reg & 0xff;
+	if (val >= 0) {
+		obuf[2] = val;
+		msg[0].len++;
+	}
+
+	rc = i2c_transfer(ir->dev->i2c_client.adapter, msg, 2);
+
+	if (rc < 0)
+		return rc;
+
+	return (rc == 2) ? 0 : -EIO;
+}
+
+static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value)
+{
+	int rc;
+	char buf;
+
+	rc = au8522_rc_read(ir, reg, -1, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	buf = (buf & ~mask) | (value & mask);
+
+	return au8522_rc_write(ir, reg, buf);
+}
+
+#define au8522_rc_set(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), (bit))
+#define au8522_rc_clear(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), 0)
+
+/* Remote Controller time units */
+
+#define AU8522_UNIT		200000 /* ns */
+#define NEC_START_SPACE		(4500000 / AU8522_UNIT)
+#define NEC_START_PULSE		(562500 * 16)
+#define RC5_START_SPACE		(4 * AU8522_UNIT)
+#define RC5_START_PULSE		888888
+
+static int au0828_get_key_au8522(struct au0828_rc *ir)
+{
+	unsigned char buf[40];
+	DEFINE_IR_RAW_EVENT(rawir);
+	int i, j, rc;
+	int prv_bit, bit, width;
+	bool first = true;
+
+	/* Check IR int */
+	rc = au8522_rc_read(ir, 0xe1, -1, buf, 1);
+	if (rc < 0 || !(buf[0] & (1 << 4)))
+		return 0;
+
+	/* Something arrived. Get the data */
+	rc = au8522_rc_read(ir, 0xe3, 0x11, buf, sizeof(buf));
+
+
+	if (rc < 0)
+		return rc;
+
+	/* Disable IR */
+	au8522_rc_clear(ir, 0xe0, 1 << 4);
+
+	usleep_range(45000, 46000);
+
+	/* Enable IR */
+	au8522_rc_set(ir, 0xe0, 1 << 4);
+
+	dprintk(16, "RC data received: %*ph\n", 40, buf);
+
+	prv_bit = (buf[0] >> 7) & 0x01;
+	width = 0;
+	for (i = 0; i < sizeof(buf); i++) {
+		for (j = 7; j >= 0; j--) {
+			bit = (buf[i] >> j) & 0x01;
+			if (bit == prv_bit) {
+				width++;
+				continue;
+			}
+
+			/*
+			 * Fix an au8522 bug: the first pulse event
+			 * is lost. So, we need to fake it, based on the
+			 * protocol. That means that not all raw decoders
+			 * will work, as we need to add a hack for each
+			 * protocol, based on the first space.
+			 * So, we only support RC5 and NEC.
+			 */
+
+			if (first) {
+				first = false;
+
+				init_ir_raw_event(&rawir);
+				rawir.pulse = true;
+				if (width > NEC_START_SPACE - 2 &&
+				    width < NEC_START_SPACE + 2) {
+					/* NEC protocol */
+					rawir.duration = NEC_START_PULSE;
+					dprintk(16, "Storing NEC start %s with duration %d",
+						rawir.pulse ? "pulse" : "space",
+						rawir.duration);
+				} else {
+					/* RC5 protocol */
+					rawir.duration = RC5_START_PULSE;
+					dprintk(16, "Storing RC5 start %s with duration %d",
+						rawir.pulse ? "pulse" : "space",
+						rawir.duration);
+				}
+				ir_raw_event_store(ir->rc, &rawir);
+			}
+
+			init_ir_raw_event(&rawir);
+			rawir.pulse = prv_bit ? false : true;
+			rawir.duration = AU8522_UNIT * width;
+			dprintk(16, "Storing %s with duration %d",
+				rawir.pulse ? "pulse" : "space",
+				rawir.duration);
+			ir_raw_event_store(ir->rc, &rawir);
+
+			width = 1;
+			prv_bit = bit;
+		}
+	}
+
+	init_ir_raw_event(&rawir);
+	rawir.pulse = prv_bit ? false : true;
+	rawir.duration = AU8522_UNIT * width;
+	dprintk(16, "Storing end %s with duration %d",
+		rawir.pulse ? "pulse" : "space",
+		rawir.duration);
+	ir_raw_event_store(ir->rc, &rawir);
+
+	ir_raw_event_handle(ir->rc);
+
+	return 1;
+}
+
+/*
+ * Generic IR code
+ */
+
+static void au0828_rc_work(struct work_struct *work)
+{
+	struct au0828_rc *ir = container_of(work, struct au0828_rc, work.work);
+	int rc;
+
+	rc = ir->get_key_i2c(ir);
+	if (rc < 0)
+		pr_info("Error while getting RC scancode\n");
+
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static int au0828_rc_start(struct rc_dev *rc)
+{
+	struct au0828_rc *ir = rc->priv;
+
+	INIT_DELAYED_WORK(&ir->work, au0828_rc_work);
+
+	/* Enable IR */
+	au8522_rc_set(ir, 0xe0, 1 << 4);
+
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+
+	return 0;
+}
+
+static void au0828_rc_stop(struct rc_dev *rc)
+{
+	struct au0828_rc *ir = rc->priv;
+
+	/* Disable IR */
+	au8522_rc_clear(ir, 0xe0, 1 << 4);
+
+	cancel_delayed_work_sync(&ir->work);
+}
+
+static int au0828_probe_i2c_ir(struct au0828_dev *dev)
+{
+	int i = 0;
+	const unsigned short addr_list[] = {
+		 0x47, I2C_CLIENT_END
+	};
+
+	while (addr_list[i] != I2C_CLIENT_END) {
+		if (i2c_probe_func_quick_read(dev->i2c_client.adapter,
+					      addr_list[i]) == 1)
+			return addr_list[i];
+		i++;
+	}
+
+	return -ENODEV;
+}
+
+int au0828_rc_register(struct au0828_dev *dev)
+{
+	struct au0828_rc *ir;
+	struct rc_dev *rc;
+	int err = -ENOMEM;
+	u16 i2c_rc_dev_addr = 0;
+
+	if (!dev->board.has_ir_i2c)
+		return 0;
+
+	i2c_rc_dev_addr = au0828_probe_i2c_ir(dev);
+	if (!i2c_rc_dev_addr)
+		return -ENODEV;
+
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	rc = rc_allocate_device();
+	if (!ir || !rc)
+		goto error;
+
+	/* record handles to ourself */
+	ir->dev = dev;
+	dev->ir = ir;
+	ir->rc = rc;
+
+	rc->priv = ir;
+	rc->open = au0828_rc_start;
+	rc->close = au0828_rc_stop;
+
+	if (dev->board.has_ir_i2c) {	/* external i2c device */
+		switch (dev->boardnr) {
+		case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+			rc->map_name = RC_MAP_HAUPPAUGE;
+			ir->get_key_i2c = au0828_get_key_au8522;
+			break;
+		default:
+			err = -ENODEV;
+			goto error;
+		}
+
+		ir->i2c_dev_addr = i2c_rc_dev_addr;
+	}
+
+	/* This is how often we ask the chip for IR information */
+	ir->polling = 100; /* ms */
+
+	/* init input device */
+	snprintf(ir->name, sizeof(ir->name), "au0828 IR (%s)",
+		 dev->board.name);
+
+	usb_make_path(dev->usbdev, 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->usbdev->descriptor.idVendor);
+	rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct);
+	rc->dev.parent = &dev->usbdev->dev;
+	rc->driver_name = "au0828-input";
+	rc->driver_type = RC_DRIVER_IR_RAW;
+	rc->allowed_protocols = RC_BIT_NEC | RC_BIT_RC5;
+
+	/* all done */
+	err = rc_register_device(rc);
+	if (err)
+		goto error;
+
+	pr_info("Remote controller %s initalized\n", ir->name);
+
+	return 0;
+
+error:
+	dev->ir = NULL;
+	rc_free_device(rc);
+	kfree(ir);
+	return err;
+}
+
+void au0828_rc_unregister(struct au0828_dev *dev)
+{
+	struct au0828_rc *ir = dev->ir;
+
+	/* skip detach on non attached boards */
+	if (!ir)
+		return;
+
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
+
+	/* done */
+	kfree(ir);
+	dev->ir = NULL;
+}
+
+int au0828_rc_suspend(struct au0828_dev *dev)
+{
+	struct au0828_rc *ir = dev->ir;
+
+	if (!ir)
+		return 0;
+
+	cancel_delayed_work_sync(&ir->work);
+
+	return 0;
+}
+
+int au0828_rc_resume(struct au0828_dev *dev)
+{
+	struct au0828_rc *ir = dev->ir;
+
+	if (!ir)
+		return 0;
+
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/au0828-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/au0828-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -787,23 +787,40 @@ static int au0828_i2s_init(struct au0828
 
 /*
  * Auvitek au0828 analog stream enable
- * Please set interface0 to AS5 before enable the stream
  */
 static int au0828_analog_stream_enable(struct au0828_dev *d)
 {
+	struct usb_interface *iface;
+	int ret, h, w;
+
 	dprintk(1, "au0828_analog_stream_enable called\n");
+
+	iface = usb_ifnum_to_if(d->usbdev, 0);
+	if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) {
+		dprintk(1, "Changing intf#0 to alt 5\n");
+		/* set au0828 interface0 to AS5 here again */
+		ret = usb_set_interface(d->usbdev, 0, 5);
+		if (ret < 0) {
+			printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
+			return -EBUSY;
+		}
+	}
+
+	h = d->height / 2 + 2;
+	w = d->width * 2;
+
 	au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
 	au0828_writereg(d, 0x106, 0x00);
 	/* set x position */
 	au0828_writereg(d, 0x110, 0x00);
 	au0828_writereg(d, 0x111, 0x00);
-	au0828_writereg(d, 0x114, 0xa0);
-	au0828_writereg(d, 0x115, 0x05);
+	au0828_writereg(d, 0x114, w & 0xff);
+	au0828_writereg(d, 0x115, w >> 8);
 	/* set y position */
 	au0828_writereg(d, 0x112, 0x00);
 	au0828_writereg(d, 0x113, 0x00);
-	au0828_writereg(d, 0x116, 0xf2);
-	au0828_writereg(d, 0x117, 0x00);
+	au0828_writereg(d, 0x116, h & 0xff);
+	au0828_writereg(d, 0x117, h >> 8);
 	au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
 
 	return 0;
@@ -1002,15 +1019,6 @@ static int au0828_v4l2_open(struct file
 		return -ERESTARTSYS;
 	}
 	if (dev->users == 0) {
-		/* set au0828 interface0 to AS5 here again */
-		ret = usb_set_interface(dev->usbdev, 0, 5);
-		if (ret < 0) {
-			mutex_unlock(&dev->lock);
-			printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
-			kfree(fh);
-			return -EBUSY;
-		}
-
 		au0828_analog_stream_enable(dev);
 		au0828_analog_stream_reset(dev);
 
@@ -1252,13 +1260,6 @@ static int au0828_set_format(struct au08
 		}
 	}
 
-	/* set au0828 interface0 to AS5 here again */
-	ret = usb_set_interface(dev->usbdev, 0, 5);
-	if (ret < 0) {
-		printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
-		return -EBUSY;
-	}
-
 	au0828_analog_stream_enable(dev);
 
 	return 0;
@@ -1364,9 +1365,11 @@ static int vidioc_s_std(struct file *fil
 
 	i2c_gate_ctrl(dev, 1);
 
-	/* FIXME: when we support something other than NTSC, we are going to
-	   have to make the au0828 bridge adjust the size of its capture
-	   buffer, which is currently hardcoded at 720x480 */
+	/*
+	 * FIXME: when we support something other than 60Hz standards,
+	 * we are going to have to make the au0828 bridge adjust the size
+	 * of its capture buffer, which is currently hardcoded at 720x480
+	 */
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm);
 
@@ -1723,6 +1726,7 @@ static int vidioc_streamoff(struct file
 		dev->vid_timeout_running = 0;
 		del_timer_sync(&dev->vid_timeout);
 
+		au0828_analog_stream_disable(dev);
 		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
 		rc = au0828_stream_interrupt(dev);
 		if (rc != 0)
@@ -1915,7 +1919,7 @@ static const struct video_device au0828_
 	.fops                       = &au0828_v4l_fops,
 	.release                    = video_device_release,
 	.ioctl_ops 		    = &video_ioctl_ops,
-	.tvnorms                    = V4L2_STD_NTSC_M,
+	.tvnorms                    = V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
 };
 
 /**************************************************************************/
@@ -1928,7 +1932,8 @@ int au0828_analog_register(struct au0828
 	struct usb_endpoint_descriptor *endpoint;
 	int i, ret;
 
-	dprintk(1, "au0828_analog_register called!\n");
+	dprintk(1, "au0828_analog_register called for intf#%d!\n",
+		interface->cur_altsetting->desc.bInterfaceNumber);
 
 	/* set au0828 usb interface0 to as5 */
 	retval = usb_set_interface(dev->usbdev,
@@ -1952,6 +1957,9 @@ int au0828_analog_register(struct au0828
 			dev->max_pkt_size = (tmp & 0x07ff) *
 				(((tmp & 0x1800) >> 11) + 1);
 			dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
+			dprintk(1,
+				"Found isoc endpoint 0x%02x, max size = %d\n",
+				dev->isoc_in_endpointaddr, dev->max_pkt_size);
 		}
 	}
 	if (!(dev->isoc_in_endpointaddr)) {
@@ -2008,14 +2016,12 @@ int au0828_analog_register(struct au0828
 	*dev->vdev = au0828_video_template;
 	dev->vdev->v4l2_dev = &dev->v4l2_dev;
 	dev->vdev->lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags);
 	strcpy(dev->vdev->name, "au0828a video");
 
 	/* Setup the VBI device */
 	*dev->vbi_dev = au0828_video_template;
 	dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
 	dev->vbi_dev->lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags);
 	strcpy(dev->vbi_dev->name, "au0828a vbi");
 
 	/* Register the v4l2 device */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,9 +20,17 @@ config VIDEO_AU0828_V4L2
 	bool "Auvitek AU0828 v4l2 analog video support"
 	depends on VIDEO_AU0828 && VIDEO_V4L2
 	select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TUNER
 	default y
 	---help---
 	  This is a video4linux driver for Auvitek's USB device.
 
 	  Choose Y here to include support for v4l2 analog video
 	  capture within the au0828 driver.
+
+config VIDEO_AU0828_RC
+	bool "AU0828 Remote Controller support"
+	depends on RC_CORE
+	depends on VIDEO_AU0828
+	---help---
+	   Enables Remote Controller support on au0828 driver.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/au0828/Makefile linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/Makefile
--- linux-libre-3.16-gnu/drivers/media/usb/au0828/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/au0828/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,10 @@ ifeq ($(CONFIG_VIDEO_AU0828_V4L2),y)
   au0828-objs   += au0828-video.o au0828-vbi.o
 endif
 
+ifeq ($(CONFIG_VIDEO_AU0828_RC),y)
+  au0828-objs   += au0828-input.o
+endif
+
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
 ccflags-y += -Idrivers/media/tuners
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cpia2/cpia2_v4l.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cpia2/cpia2_v4l.c
--- linux-libre-3.16-gnu/drivers/media/usb/cpia2/cpia2_v4l.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cpia2/cpia2_v4l.c	2014-09-28 17:29:07.000000000 -0400
@@ -1169,7 +1169,6 @@ int cpia2_register_camera(struct camera_
 	cam->vdev.lock = &cam->v4l2_lock;
 	cam->vdev.ctrl_handler = hdl;
 	cam->vdev.v4l2_dev = &cam->v4l2_dev;
-	set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
 
 	reset_camera_struct_v4l(cam);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-417.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-417.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-417.c	2014-08-07 04:50:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-417.c	2014-09-28 21:31:26.000000000 -0400
@@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct f
 	f->fmt.pix.width = dev->ts1.width;
 	f->fmt.pix.height = dev->ts1.height;
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-	f->fmt.pix.priv = 0;
 	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
 		dev->ts1.width, dev->ts1.height);
 	dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
@@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct
 	f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.priv = 0;
 	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
 		dev->ts1.width, dev->ts1.height);
 	dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
@@ -1923,7 +1921,6 @@ static struct video_device *cx231xx_vide
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->lock = &dev->lock;
 	vfd->release = video_device_release;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
 	video_set_drvdata(vfd, dev);
 	if (dev->tuner_type == TUNER_ABSENT) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-avcore.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-avcore.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-avcore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-avcore.c	2014-09-28 17:29:07.000000000 -0400
@@ -352,6 +352,7 @@ int cx231xx_afe_update_power_control(str
 	case CX231XX_BOARD_CNXT_RDU_253S:
 	case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
 	case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
 	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-cards.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-cards.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-cards.c	2014-08-07 04:47:16.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-cards.c	2014-09-28 21:28:05.000000000 -0400
@@ -704,6 +704,84 @@ struct cx231xx_board cx231xx_boards[] =
 			}
 		},
 	},
+	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx] = {
+		.name = "Hauppauge WinTV 930C-HD (1113xx) / PCTV QuatroStick 521e",
+		.tuner_type = TUNER_NXP_TDA18271,
+		.tuner_addr = 0x60,
+		.tuner_gpio = RDE250_XCV_TUNER,
+		.tuner_sif_gpio = 0x05,
+		.tuner_scl_gpio = 0x1a,
+		.tuner_sda_gpio = 0x1b,
+		.decoder = CX231XX_AVDECODER,
+		.output_mode = OUT_MODE_VIP11,
+		.demod_xfer_mode = 0,
+		.ctl_pin_status_mask = 0xFFFFFFC4,
+		.agc_analog_digital_select_gpio = 0x0c,
+		.gpio_pin_status_mask = 0x4001000,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
+		.has_dvb = 1,
+		.demod_addr = 0x0e,
+		.norm = V4L2_STD_PAL,
+
+		.input = {{
+			.type = CX231XX_VMUX_TELEVISION,
+			.vmux = CX231XX_VIN_3_1,
+			.amux = CX231XX_AMUX_VIDEO,
+			.gpio = NULL,
+		}, {
+			.type = CX231XX_VMUX_COMPOSITE1,
+			.vmux = CX231XX_VIN_2_1,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = NULL,
+		}, {
+			.type = CX231XX_VMUX_SVIDEO,
+			.vmux = CX231XX_VIN_1_1 |
+				(CX231XX_VIN_1_2 << 8) |
+				CX25840_SVIDEO_ON,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = NULL,
+		} },
+	},
+	[CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx] = {
+		.name = "Hauppauge WinTV 930C-HD (1114xx) / PCTV QuatroStick 522e",
+		.tuner_type = TUNER_ABSENT,
+		.tuner_addr = 0x60,
+		.tuner_gpio = RDE250_XCV_TUNER,
+		.tuner_sif_gpio = 0x05,
+		.tuner_scl_gpio = 0x1a,
+		.tuner_sda_gpio = 0x1b,
+		.decoder = CX231XX_AVDECODER,
+		.output_mode = OUT_MODE_VIP11,
+		.demod_xfer_mode = 0,
+		.ctl_pin_status_mask = 0xFFFFFFC4,
+		.agc_analog_digital_select_gpio = 0x0c,
+		.gpio_pin_status_mask = 0x4001000,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
+		.has_dvb = 1,
+		.demod_addr = 0x0e,
+		.norm = V4L2_STD_PAL,
+
+		.input = {{
+			.type = CX231XX_VMUX_TELEVISION,
+			.vmux = CX231XX_VIN_3_1,
+			.amux = CX231XX_AMUX_VIDEO,
+			.gpio = NULL,
+		}, {
+			.type = CX231XX_VMUX_COMPOSITE1,
+			.vmux = CX231XX_VIN_2_1,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = NULL,
+		}, {
+			.type = CX231XX_VMUX_SVIDEO,
+			.vmux = CX231XX_VIN_1_1 |
+				(CX231XX_VIN_1_2 << 8) |
+				CX25840_SVIDEO_ON,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = NULL,
+		} },
+	},
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -733,10 +811,20 @@ struct usb_device_id cx231xx_id_table[]
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
 	{USB_DEVICE(0x2040, 0xb120),
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
+	{USB_DEVICE(0x2040, 0xb130),
+	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
+	{USB_DEVICE(0x2040, 0xb131),
+	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
 	{USB_DEVICE(0x2040, 0xb140),
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
 	{USB_DEVICE(0x2040, 0xc200),
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
+	/* PCTV QuatroStick 521e */
+	{USB_DEVICE(0x2013, 0x0259),
+	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
+	/* PCTV QuatroStick 522e */
+	{USB_DEVICE(0x2013, 0x025e),
+	 .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
 	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
 	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
 	{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
@@ -886,6 +974,50 @@ static void cx231xx_config_tuner(struct
 
 }
 
+static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
+{
+	int ret = 0;
+	u8 addr = 0xa0 >> 1;
+	u8 start_offset = 0;
+	int len_todo = len;
+	u8 *eedata_cur = eedata;
+	int i;
+	struct i2c_msg msg_write = { .addr = addr, .flags = 0,
+		.buf = &start_offset, .len = 1 };
+	struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
+
+	/* mutex_lock(&dev->i2c_lock); */
+	cx231xx_enable_i2c_port_3(dev, false);
+
+	/* start reading at offset 0 */
+	ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
+	if (ret < 0) {
+		cx231xx_err("Can't read eeprom\n");
+		return ret;
+	}
+
+	while (len_todo > 0) {
+		msg_read.len = (len_todo > 64) ? 64 : len_todo;
+		msg_read.buf = eedata_cur;
+
+		ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
+		if (ret < 0) {
+			cx231xx_err("Can't read eeprom\n");
+			return ret;
+		}
+		eedata_cur += msg_read.len;
+		len_todo -= msg_read.len;
+	}
+
+	cx231xx_enable_i2c_port_3(dev, true);
+	/* mutex_unlock(&dev->i2c_lock); */
+
+	for (i = 0; i + 15 < len; i += 16)
+		cx231xx_info("i2c eeprom %02x: %*ph\n", i, 16, &eedata[i]);
+
+	return 0;
+}
+
 void cx231xx_card_setup(struct cx231xx *dev)
 {
 
@@ -917,6 +1049,21 @@ void cx231xx_card_setup(struct cx231xx *
 		else
 			cx231xx_config_tuner(dev);
 	}
+
+	switch (dev->model) {
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+		{
+			struct tveeprom tvee;
+			static u8 eeprom[256];
+
+			read_eeprom(dev, eeprom, sizeof(eeprom));
+			tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
+						&tvee, eeprom + 0xc0);
+			break;
+		}
+	}
+
 }
 
 /*
@@ -964,12 +1111,6 @@ void cx231xx_release_resources(struct cx
 
 	/* Mark device as unused */
 	clear_bit(dev->devno, &cx231xx_devused);
-
-	kfree(dev->video_mode.alt_max_pkt_size);
-	kfree(dev->vbi_mode.alt_max_pkt_size);
-	kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-	kfree(dev->ts1_mode.alt_max_pkt_size);
-	kfree(dev);
 }
 
 /*
@@ -1003,7 +1144,11 @@ static int cx231xx_init_dev(struct cx231
 	dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
 
 	/* Query cx231xx to find what pcb config it is related to */
-	initialize_cx231xx(dev);
+	retval = initialize_cx231xx(dev);
+	if (retval < 0) {
+		cx231xx_errdev("Failed to read PCB config\n");
+		return retval;
+	}
 
 	/*To workaround error number=-71 on EP0 for VideoGrabber,
 		 need set alt here.*/
@@ -1121,6 +1266,117 @@ static void flush_request_modules(struct
 #define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
+static int cx231xx_init_v4l2(struct cx231xx *dev,
+			     struct usb_device *udev,
+			     struct usb_interface *interface,
+			     int isoc_pipe)
+{
+	struct usb_interface *uif;
+	int i, idx;
+
+	/* Video Init */
+
+	/* compute alternate max packet sizes for video */
+	idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
+	if (idx >= dev->max_iad_interface_count) {
+		cx231xx_errdev("Video PCB interface #%d doesn't exist\n", idx);
+		return -ENODEV;
+	}
+
+	uif = udev->actconfig->interface[idx];
+
+	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
+	dev->video_mode.num_alt = uif->num_altsetting;
+
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->video_mode.end_point_addr,
+		     dev->video_mode.num_alt);
+
+	dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
+	if (dev->video_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dev->video_mode.num_alt; i++) {
+		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+		dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->video_mode.alt_max_pkt_size[i]);
+	}
+
+	/* VBI Init */
+
+	idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
+	if (idx >= dev->max_iad_interface_count) {
+		cx231xx_errdev("VBI PCB interface #%d doesn't exist\n", idx);
+		return -ENODEV;
+	}
+	uif = udev->actconfig->interface[idx];
+
+	dev->vbi_mode.end_point_addr =
+	    uif->altsetting[0].endpoint[isoc_pipe].desc.
+			bEndpointAddress;
+
+	dev->vbi_mode.num_alt = uif->num_altsetting;
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->vbi_mode.end_point_addr,
+		     dev->vbi_mode.num_alt);
+
+	/* compute alternate max packet sizes for vbi */
+	dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
+	if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
+		u16 tmp =
+		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+				desc.wMaxPacketSize);
+		dev->vbi_mode.alt_max_pkt_size[i] =
+		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->vbi_mode.alt_max_pkt_size[i]);
+	}
+
+	/* Sliced CC VBI init */
+
+	/* compute alternate max packet sizes for sliced CC */
+	idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
+	if (idx >= dev->max_iad_interface_count) {
+		cx231xx_errdev("Sliced CC PCB interface #%d doesn't exist\n", idx);
+		return -ENODEV;
+	}
+	uif = udev->actconfig->interface[idx];
+
+	dev->sliced_cc_mode.end_point_addr =
+	    uif->altsetting[0].endpoint[isoc_pipe].desc.
+			bEndpointAddress;
+
+	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->sliced_cc_mode.end_point_addr,
+		     dev->sliced_cc_mode.num_alt);
+	dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
+
+	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
+		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+				desc.wMaxPacketSize);
+		dev->sliced_cc_mode.alt_max_pkt_size[i] =
+		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->sliced_cc_mode.alt_max_pkt_size[i]);
+	}
+
+	return 0;
+}
+
 /*
  * cx231xx_usb_probe()
  * checks for supported devices
@@ -1135,6 +1391,7 @@ static int cx231xx_usb_probe(struct usb_
 	int nr = 0, ifnum;
 	int i, isoc_pipe = 0;
 	char *speed;
+	u8 idx;
 	struct usb_interface_assoc_descriptor *assoc_desc;
 
 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
@@ -1157,16 +1414,16 @@ static int cx231xx_usb_probe(struct usb_
 		}
 	} while (test_and_set_bit(nr, &cx231xx_devused));
 
+	udev = usb_get_dev(interface_to_usbdev(interface));
+
 	/* allocate memory for our device state and initialize it */
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		cx231xx_err(DRIVER_NAME ": out of memory!\n");
 		clear_bit(nr, &cx231xx_devused);
 		return -ENOMEM;
 	}
 
-	udev = usb_get_dev(interface_to_usbdev(interface));
-
 	snprintf(dev->name, 29, "cx231xx #%d", nr);
 	dev->devno = nr;
 	dev->model = id->driver_info;
@@ -1185,8 +1442,7 @@ static int cx231xx_usb_probe(struct usb_
 	dev->vbi_or_sliced_cc_mode = 0;
 
 	/* get maximum no.of IAD interfaces */
-	assoc_desc = udev->actconfig->intf_assoc[0];
-	dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
+	dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
 
 	/* init CIR module TBD */
 
@@ -1238,120 +1494,31 @@ static int cx231xx_usb_probe(struct usb_
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, dev);
 
-	/*
-	 * AV device initialization - only done at the last interface
-	 */
-
 	/* Create v4l2 device */
 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
 	if (retval) {
 		cx231xx_errdev("v4l2_device_register failed\n");
-		retval = -EIO;
 		goto err_v4l2;
 	}
+
 	/* allocate device struct */
 	retval = cx231xx_init_dev(dev, udev, nr);
 	if (retval)
 		goto err_init;
 
-	/* compute alternate max packet sizes for video */
-	uif = udev->actconfig->interface[dev->current_pcb_config.
-		       hs_config_info[0].interface_info.video_index + 1];
-
-	dev->video_mode.end_point_addr = uif->altsetting[0].
-			endpoint[isoc_pipe].desc.bEndpointAddress;
-
-	dev->video_mode.num_alt = uif->num_altsetting;
-	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-		     dev->video_mode.end_point_addr,
-		     dev->video_mode.num_alt);
-	dev->video_mode.alt_max_pkt_size =
-		kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL);
-
-	if (dev->video_mode.alt_max_pkt_size == NULL) {
-		cx231xx_errdev("out of memory!\n");
-		retval = -ENOMEM;
-		goto err_video_alt;
-	}
-
-	for (i = 0; i < dev->video_mode.num_alt; i++) {
-		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-				desc.wMaxPacketSize);
-		dev->video_mode.alt_max_pkt_size[i] =
-		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		cx231xx_info("Alternate setting %i, max size= %i\n", i,
-			     dev->video_mode.alt_max_pkt_size[i]);
-	}
-
-	/* compute alternate max packet sizes for vbi */
-	uif = udev->actconfig->interface[dev->current_pcb_config.
-				       hs_config_info[0].interface_info.
-				       vanc_index + 1];
-
-	dev->vbi_mode.end_point_addr =
-	    uif->altsetting[0].endpoint[isoc_pipe].desc.
-			bEndpointAddress;
-
-	dev->vbi_mode.num_alt = uif->num_altsetting;
-	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-		     dev->vbi_mode.end_point_addr,
-		     dev->vbi_mode.num_alt);
-	dev->vbi_mode.alt_max_pkt_size =
-	    kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL);
-
-	if (dev->vbi_mode.alt_max_pkt_size == NULL) {
-		cx231xx_errdev("out of memory!\n");
-		retval = -ENOMEM;
-		goto err_vbi_alt;
-	}
-
-	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
-		u16 tmp =
-		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-				desc.wMaxPacketSize);
-		dev->vbi_mode.alt_max_pkt_size[i] =
-		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		cx231xx_info("Alternate setting %i, max size= %i\n", i,
-			     dev->vbi_mode.alt_max_pkt_size[i]);
-	}
-
-	/* compute alternate max packet sizes for sliced CC */
-	uif = udev->actconfig->interface[dev->current_pcb_config.
-				       hs_config_info[0].interface_info.
-				       hanc_index + 1];
-
-	dev->sliced_cc_mode.end_point_addr =
-	    uif->altsetting[0].endpoint[isoc_pipe].desc.
-			bEndpointAddress;
-
-	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
-	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-		     dev->sliced_cc_mode.end_point_addr,
-		     dev->sliced_cc_mode.num_alt);
-	dev->sliced_cc_mode.alt_max_pkt_size =
-		kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL);
-
-	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
-		cx231xx_errdev("out of memory!\n");
-		retval = -ENOMEM;
-		goto err_sliced_cc_alt;
-	}
-
-	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
-		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-				desc.wMaxPacketSize);
-		dev->sliced_cc_mode.alt_max_pkt_size[i] =
-		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		cx231xx_info("Alternate setting %i, max size= %i\n", i,
-			     dev->sliced_cc_mode.alt_max_pkt_size[i]);
-	}
+	retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
+	if (retval)
+		goto err_init;
 
 	if (dev->current_pcb_config.ts1_source != 0xff) {
 		/* compute alternate max packet sizes for TS1 */
-		uif = udev->actconfig->interface[dev->current_pcb_config.
-					       hs_config_info[0].
-					       interface_info.
-					       ts1_index + 1];
+		idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
+		if (idx >= dev->max_iad_interface_count) {
+			cx231xx_errdev("TS1 PCB interface #%d doesn't exist\n", idx);
+			retval = -ENODEV;
+			goto err_video_alt;
+		}
+		uif = udev->actconfig->interface[idx];
 
 		dev->ts1_mode.end_point_addr =
 		    uif->altsetting[0].endpoint[isoc_pipe].
@@ -1361,13 +1528,12 @@ static int cx231xx_usb_probe(struct usb_
 		cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
 			     dev->ts1_mode.end_point_addr,
 			     dev->ts1_mode.num_alt);
-		dev->ts1_mode.alt_max_pkt_size =
-			kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL);
 
+		dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
 			cx231xx_errdev("out of memory!\n");
 			retval = -ENOMEM;
-			goto err_ts1_alt;
+			goto err_video_alt;
 		}
 
 		for (i = 0; i < dev->ts1_mode.num_alt; i++) {
@@ -1394,12 +1560,6 @@ static int cx231xx_usb_probe(struct usb_
 	request_modules(dev);
 
 	return 0;
-err_ts1_alt:
-	kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-err_sliced_cc_alt:
-	kfree(dev->vbi_mode.alt_max_pkt_size);
-err_vbi_alt:
-	kfree(dev->video_mode.alt_max_pkt_size);
 err_video_alt:
 	/* cx231xx_uninit_dev: */
 	cx231xx_close_extension(dev);
@@ -1415,7 +1575,6 @@ err_v4l2:
 err_if:
 	usb_put_dev(udev);
 	clear_bit(dev->devno, &cx231xx_devused);
-	kfree(dev);
 	return retval;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-core.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -726,6 +726,7 @@ int cx231xx_set_mode(struct cx231xx *dev
 			errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
 			break;
 		case CX231XX_BOARD_HAUPPAUGE_EXETER:
+		case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
 			errCode = cx231xx_set_power_mode(dev,
 						POLARIS_AVMODE_DIGITAL);
 			break;
@@ -744,6 +745,7 @@ int cx231xx_set_mode(struct cx231xx *dev
 		case CX231XX_BOARD_CNXT_RDE_253S:
 		case CX231XX_BOARD_CNXT_RDU_253S:
 		case CX231XX_BOARD_HAUPPAUGE_EXETER:
+		case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
 		case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 		case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
 		case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
@@ -1379,6 +1381,7 @@ int cx231xx_dev_init(struct cx231xx *dev
 	case CX231XX_BOARD_CNXT_RDE_253S:
 	case CX231XX_BOARD_CNXT_RDU_253S:
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
 	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
 	case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,9 @@
 #include "tda18271.h"
 #include "s5h1411.h"
 #include "lgdt3305.h"
+#include "si2165.h"
 #include "mb86a20s.h"
+#include "si2157.h"
 
 MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
 MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
@@ -67,6 +69,7 @@ struct cx231xx_dvb {
 	struct dmx_frontend fe_hw;
 	struct dmx_frontend fe_mem;
 	struct dvb_net net;
+	struct i2c_client *i2c_client_tuner;
 };
 
 static struct s5h1432_config dvico_s5h1432_config = {
@@ -151,6 +154,18 @@ static struct tda18271_config pv_tda1827
 	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
 };
 
+static const struct si2165_config hauppauge_930C_HD_1113xx_si2165_config = {
+	.i2c_addr	= 0x64,
+	.chip_mode	= SI2165_MODE_PLL_XTAL,
+	.ref_freq_Hz	= 16000000,
+};
+
+static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = {
+	.i2c_addr	= 0x64,
+	.chip_mode	= SI2165_MODE_PLL_EXT,
+	.ref_freq_Hz	= 24000000,
+};
+
 static inline void print_err_status(struct cx231xx *dev, int packet, int status)
 {
 	char *errmsg = "Unknown";
@@ -549,11 +564,18 @@ fail_adapter:
 
 static void unregister_dvb(struct cx231xx_dvb *dvb)
 {
+	struct i2c_client *client;
 	dvb_net_release(&dvb->net);
 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	dvb_dmxdev_release(&dvb->dmxdev);
 	dvb_dmx_release(&dvb->demux);
+	client = dvb->i2c_client_tuner;
+	/* remove I2C tuner */
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
 	dvb_unregister_frontend(dvb->frontend);
 	dvb_frontend_detach(dvb->frontend);
 	dvb_unregister_adapter(&dvb->adapter);
@@ -704,6 +726,89 @@ static int dvb_init(struct cx231xx *dev)
 			   &hcw_tda18271_config);
 		break;
 
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
+
+		dev->dvb->frontend = dvb_attach(si2165_attach,
+			&hauppauge_930C_HD_1113xx_si2165_config,
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
+			);
+
+		if (dev->dvb->frontend == NULL) {
+			printk(DRIVER_NAME
+			       ": Failed to attach SI2165 front end\n");
+			result = -EINVAL;
+			goto out_free;
+		}
+
+		dev->dvb->frontend->ops.i2c_gate_ctrl = 0;
+
+		/* define general-purpose callback pointer */
+		dvb->frontend->callback = cx231xx_tuner_callback;
+
+		dvb_attach(tda18271_attach, dev->dvb->frontend,
+			0x60,
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+			&hcw_tda18271_config);
+
+		dev->cx231xx_reset_analog_tuner = NULL;
+		break;
+
+	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+	{
+		struct i2c_client *client;
+		struct i2c_board_info info;
+		struct si2157_config si2157_config;
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+
+		dev->dvb->frontend = dvb_attach(si2165_attach,
+			&pctv_quatro_stick_1114xx_si2165_config,
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
+			);
+
+		if (dev->dvb->frontend == NULL) {
+			printk(DRIVER_NAME
+			       ": Failed to attach SI2165 front end\n");
+			result = -EINVAL;
+			goto out_free;
+		}
+
+		dev->dvb->frontend->ops.i2c_gate_ctrl = 0;
+
+		/* define general-purpose callback pointer */
+		dvb->frontend->callback = cx231xx_tuner_callback;
+
+		/* attach tuner */
+		memset(&si2157_config, 0, sizeof(si2157_config));
+		si2157_config.fe = dev->dvb->frontend;
+		si2157_config.inversion = true;
+		strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+		info.addr = 0x60;
+		info.platform_data = &si2157_config;
+		request_module("si2157");
+
+		client = i2c_new_device(
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+			&info);
+		if (client == NULL || client->dev.driver == NULL) {
+			dvb_frontend_detach(dev->dvb->frontend);
+			result = -ENODEV;
+			goto out_free;
+		}
+
+		if (!try_module_get(client->dev.driver->owner)) {
+			i2c_unregister_device(client);
+			dvb_frontend_detach(dev->dvb->frontend);
+			result = -ENODEV;
+			goto out_free;
+		}
+
+		dev->cx231xx_reset_analog_tuner = NULL;
+
+		dev->dvb->i2c_client_tuner = client;
+		break;
+	}
+
 	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx.h linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx.h
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -73,6 +73,8 @@
 #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16
 #define CX231XX_BOARD_OTG102 17
 #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18
+#define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19
+#define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-input.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-input.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,11 +21,12 @@
 #include "cx231xx.h"
 #include <linux/usb.h>
 #include <linux/slab.h>
+#include <linux/bitrev.h>
 
 #define MODULE_NAME "cx231xx-input"
 
-static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
-			 u32 *ir_raw)
+static int get_key_isdbt(struct IR_i2c *ir, enum rc_type *protocol,
+			 u32 *pscancode, u8 *toggle)
 {
 	int	rc;
 	u8	cmd, scancode;
@@ -46,21 +47,14 @@ static int get_key_isdbt(struct IR_i2c *
 	if (cmd == 0xff)
 		return 0;
 
-	scancode =
-		 ((cmd & 0x01) ? 0x80 : 0) |
-		 ((cmd & 0x02) ? 0x40 : 0) |
-		 ((cmd & 0x04) ? 0x20 : 0) |
-		 ((cmd & 0x08) ? 0x10 : 0) |
-		 ((cmd & 0x10) ? 0x08 : 0) |
-		 ((cmd & 0x20) ? 0x04 : 0) |
-		 ((cmd & 0x40) ? 0x02 : 0) |
-		 ((cmd & 0x80) ? 0x01 : 0);
+	scancode = bitrev8(cmd);
 
 	dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n",
 		cmd, scancode);
 
-	*ir_key = scancode;
-	*ir_raw = scancode;
+	*protocol = RC_TYPE_OTHER;
+	*pscancode = scancode;
+	*toggle = 0;
 	return 1;
 }
 
@@ -97,7 +91,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
 	dev->init_data.get_key = get_key_isdbt;
 	dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
 	/* The i2c micro-controller only outputs the cmd part of NEC protocol */
-	dev->init_data.rc_dev->scanmask = 0xff;
+	dev->init_data.rc_dev->scancode_mask = 0xff;
 	dev->init_data.rc_dev->driver_name = "cx231xx";
 	dev->init_data.type = RC_BIT_NEC;
 	info.addr = 0x30;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c	2014-09-28 17:29:07.000000000 -0400
@@ -654,8 +654,9 @@ static struct pcb_config cx231xx_Scenari
 
 /*****************************************************************/
 
-u32 initialize_cx231xx(struct cx231xx *dev)
+int initialize_cx231xx(struct cx231xx *dev)
 {
+	int retval;
 	u32 config_info = 0;
 	struct pcb_config *p_pcb_info;
 	u8 usb_speed = 1;	/* from register,1--HS, 0--FS  */
@@ -670,7 +671,10 @@ u32 initialize_cx231xx(struct cx231xx *d
 
 	/* read board config register to find out which
 	pcb config it is related to */
-	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
+	retval = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
+				       data, 4);
+	if (retval < 0)
+		return retval;
 
 	config_info = le32_to_cpu(*((__le32 *)data));
 	usb_speed = (u8) (config_info & 0x1);
@@ -767,7 +771,7 @@ u32 initialize_cx231xx(struct cx231xx *d
 			cx231xx_info("bad senario!!!!!\n");
 			cx231xx_info("config_info=%x\n",
 				     (config_info & SELFPOWER_MASK));
-			return 1;
+			return -ENODEV;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -221,6 +221,6 @@ enum INDEX_PCB_CONFIG{
 /***************************************************************************/
 struct cx231xx;
 
-u32 initialize_cx231xx(struct cx231xx *p_dev);
+int initialize_cx231xx(struct cx231xx *p_dev);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/cx231xx-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/cx231xx-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,7 +208,7 @@ static inline void get_next_buf(struct c
 static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
 {
 	struct cx231xx_dmaqueue *dma_q = urb->context;
-	int i, rc = 1;
+	int i;
 	unsigned char *p_buffer;
 	u32 bytes_parsed = 0, buffer_size = 0;
 	u8 sav_eav = 0;
@@ -299,13 +299,12 @@ static inline int cx231xx_isoc_copy(stru
 		bytes_parsed = 0;
 
 	}
-	return rc;
+	return 1;
 }
 
 static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
 {
 	struct cx231xx_dmaqueue *dma_q = urb->context;
-	int rc = 1;
 	unsigned char *p_buffer;
 	u32 bytes_parsed = 0, buffer_size = 0;
 	u8 sav_eav = 0;
@@ -379,7 +378,7 @@ static inline int cx231xx_bulk_copy(stru
 		bytes_parsed = 0;
 
 	}
-	return rc;
+	return 1;
 }
 
 
@@ -886,7 +885,6 @@ static int vidioc_g_fmt_vid_cap(struct f
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -931,7 +929,6 @@ static int vidioc_try_fmt_vid_cap(struct
 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1620,7 +1617,7 @@ static int radio_s_tuner(struct file *fi
  */
 static int cx231xx_v4l2_open(struct file *filp)
 {
-	int errCode = 0, radio = 0;
+	int radio = 0;
 	struct video_device *vdev = video_devdata(filp);
 	struct cx231xx *dev = video_drvdata(filp);
 	struct cx231xx_fh *fh;
@@ -1718,7 +1715,7 @@ static int cx231xx_v4l2_open(struct file
 	mutex_unlock(&dev->lock);
 	v4l2_fh_add(&fh->fh);
 
-	return errCode;
+	return 0;
 }
 
 /*
@@ -2066,7 +2063,6 @@ static struct video_device *cx231xx_vdev
 	vfd->release = video_device_release;
 	vfd->debug = video_debug;
 	vfd->lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/cx231xx/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/cx231xx/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/cx231xx/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -47,6 +47,8 @@ config VIDEO_CX231XX_DVB
 	select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
 
 	---help---
 	  This adds support for DVB cards based on the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/cxusb.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/cxusb.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/cxusb.c	2014-08-07 04:47:43.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/cxusb.c	2014-09-28 21:28:33.000000000 -0400
@@ -42,9 +42,11 @@
 #include "dib0070.h"
 #include "lgs8gxx.h"
 #include "atbm8830.h"
+#include "si2168.h"
+#include "si2157.h"
 
 /* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
+#define MAX_XFER_SIZE  80
 
 /* debug */
 static int dvb_usb_cxusb_debug;
@@ -144,6 +146,22 @@ static int cxusb_d680_dmb_gpio_tuner(str
 	}
 }
 
+static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff)
+{
+	u8 o[2], i;
+	int rc;
+
+	o[0] = 0x83;
+	o[1] = onoff;
+	rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+	if (rc) {
+		deb_info("gpio_write failed.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
 /* I2C */
 static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 			  int num)
@@ -505,6 +523,30 @@ static int cxusb_d680_dmb_rc_query(struc
 	return 0;
 }
 
+static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d)
+{
+	u8 i[2];
+	int ret;
+	u32 cmd, keycode;
+	u8 rc5_cmd, rc5_addr, rc5_toggle;
+
+	ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2);
+	if (ret)
+		return ret;
+
+	cmd = (i[0] << 8) | i[1];
+
+	if (cmd != 0xffff) {
+		rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */
+		rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */
+		rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */
+		keycode = (rc5_addr << 8) | rc5_cmd;
+		rc_keydown(d->rc_dev, RC_BIT_RC5, keycode, rc5_toggle);
+	}
+
+	return 0;
+}
+
 static struct rc_map_table rc_map_dvico_mce_table[] = {
 	{ 0xfe02, KEY_TV },
 	{ 0xfe0e, KEY_MP3 },
@@ -1070,8 +1112,15 @@ static struct dib7000p_config cxusb_dual
 	.hostbus_diversity = 1,
 };
 
+struct dib0700_adapter_state {
+	int (*set_param_save)(struct dvb_frontend *);
+	struct dib7000p_ops dib7000p_ops;
+};
+
 static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
 	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
 		err("set interface failed");
 
@@ -1079,14 +1128,17 @@ static int cxusb_dualdig4_rev2_frontend_
 
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-				     &cxusb_dualdig4_rev2_config) < 0) {
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+				       &cxusb_dualdig4_rev2_config) < 0) {
 		printk(KERN_WARNING "Unable to enumerate dib7000p\n");
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
-			      &cxusb_dualdig4_rev2_config);
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
+					      &cxusb_dualdig4_rev2_config);
 	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
@@ -1095,7 +1147,10 @@ static int cxusb_dualdig4_rev2_frontend_
 
 static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
 {
-	return dib7000p_set_gpio(fe, 8, 0, !onoff);
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
 }
 
 static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
@@ -1110,10 +1165,6 @@ static struct dib0070_config dib7070p_di
 	.clock_khz = 12000,
 };
 
-struct dib0700_adapter_state {
-	int (*set_param_save) (struct dvb_frontend *);
-};
-
 static int dib7070_set_param_override(struct dvb_frontend *fe)
 {
 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -1128,7 +1179,7 @@ static int dib7070_set_param_override(st
 	case BAND_UHF: offset = 550; break;
 	}
 
-	dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+	state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
 
 	return state->set_param_save(fe);
 }
@@ -1136,8 +1187,14 @@ static int dib7070_set_param_override(st
 static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c =
-		dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+	struct i2c_adapter *tun_i2c;
+
+	/*
+	 * No need to call dvb7000p_attach here, as it was called
+	 * already, as frontend_attach method is called first, and
+	 * tuner_attach is only called on sucess.
+	 */
+	tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
 					DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
@@ -1286,6 +1343,74 @@ static int cxusb_mygica_d689_frontend_at
 	return 0;
 }
 
+static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct cxusb_state *st = d->priv;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client_demod;
+	struct i2c_client *client_tuner;
+	struct i2c_board_info info;
+	struct si2168_config si2168_config;
+	struct si2157_config si2157_config;
+
+	/* reset the tuner */
+	if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) {
+		err("clear tuner gpio failed");
+		return -EIO;
+	}
+	msleep(100);
+	if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) {
+		err("set tuner gpio failed");
+		return -EIO;
+	}
+	msleep(100);
+
+	/* attach frontend */
+	si2168_config.i2c_adapter = &adapter;
+	si2168_config.fe = &adap->fe_adap[0].fe;
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+	info.addr = 0x64;
+	info.platform_data = &si2168_config;
+	request_module(info.type);
+	client_demod = i2c_new_device(&d->i2c_adap, &info);
+	if (client_demod == NULL || client_demod->dev.driver == NULL)
+		return -ENODEV;
+
+	if (!try_module_get(client_demod->dev.driver->owner)) {
+		i2c_unregister_device(client_demod);
+		return -ENODEV;
+	}
+
+	st->i2c_client_demod = client_demod;
+
+	/* attach tuner */
+	memset(&si2157_config, 0, sizeof(si2157_config));
+	si2157_config.fe = adap->fe_adap[0].fe;
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+	info.addr = 0x60;
+	info.platform_data = &si2157_config;
+	request_module(info.type);
+	client_tuner = i2c_new_device(adapter, &info);
+	if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
+		module_put(client_demod->dev.driver->owner);
+		i2c_unregister_device(client_demod);
+		return -ENODEV;
+	}
+	if (!try_module_get(client_tuner->dev.driver->owner)) {
+		i2c_unregister_device(client_tuner);
+		module_put(client_demod->dev.driver->owner);
+		i2c_unregister_device(client_demod);
+		return -ENODEV;
+	}
+
+	st->i2c_client_tuner = client_tuner;
+
+	return 0;
+}
+
 /*
  * DViCO has shipped two devices with the same USB ID, but only one of them
  * needs a firmware download.  Check the device class details to see if they
@@ -1367,6 +1492,7 @@ static struct dvb_usb_device_properties
 static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
 static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
 static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
@@ -1397,12 +1523,37 @@ static int cxusb_probe(struct usb_interf
 				     THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
 				     THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
+				     THIS_MODULE, NULL, adapter_nr) ||
 	    0)
 		return 0;
 
 	return -EINVAL;
 }
 
+static void cxusb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+	struct cxusb_state *st = d->priv;
+	struct i2c_client *client;
+
+	/* remove I2C client for tuner */
+	client = st->i2c_client_tuner;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
+	/* remove I2C client for demodulator */
+	client = st->i2c_client_demod;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
+	dvb_usb_device_exit(intf);
+}
+
 static struct usb_device_id cxusb_table [] = {
 	{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
@@ -1424,6 +1575,7 @@ static struct usb_device_id cxusb_table
 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
 	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
 	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
+	{ USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
 	{}		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2070,10 +2222,63 @@ static struct dvb_usb_device_properties
 	}
 };
 
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl         = CYPRESS_FX2,
+
+	.size_of_priv     = sizeof(struct cxusb_state),
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.num_frontends = 1,
+		.fe = {{
+			.streaming_ctrl   = cxusb_streaming_ctrl,
+			/* both frontend and tuner attached in the
+			   same function */
+			.frontend_attach  = cxusb_tt_ct2_4400_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			},
+		} },
+		},
+	},
+
+	.i2c_algo = &cxusb_i2c_algo,
+	.generic_bulk_ctrl_endpoint = 0x01,
+	.generic_bulk_ctrl_endpoint_response = 0x81,
+
+	.rc.core = {
+		.rc_codes       = RC_MAP_TT_1500,
+		.allowed_protos = RC_BIT_RC5,
+		.rc_query       = cxusb_tt_ct2_4400_rc_query,
+		.rc_interval    = 150,
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{
+			"TechnoTrend TVStick CT2-4400",
+			{ NULL },
+			{ &cxusb_table[20], NULL },
+		},
+	}
+};
+
 static struct usb_driver cxusb_driver = {
 	.name		= "dvb_usb_cxusb",
 	.probe		= cxusb_probe,
-	.disconnect     = dvb_usb_device_exit,
+	.disconnect     = cxusb_disconnect,
 	.id_table	= cxusb_table,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/cxusb.h linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/cxusb.h
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/cxusb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/cxusb.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,8 @@
 
 struct cxusb_state {
 	u8 gpio_write_state[3];
+	struct i2c_client *i2c_client_demod;
+	struct i2c_client *i2c_client_tuner;
 };
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dib0700_core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dib0700_core.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dib0700_core.c	2014-08-07 04:47:50.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dib0700_core.c	2014-09-28 21:28:41.000000000 -0400
@@ -658,13 +658,8 @@ out:
 struct dib0700_rc_response {
 	u8 report_id;
 	u8 data_state;
-	union {
-		u16 system16;
-		struct {
-			u8 not_system;
-			u8 system;
-		};
-	};
+	u8 system;
+	u8 not_system;
 	u8 data;
 	u8 not_data;
 };
@@ -674,6 +669,7 @@ static void dib0700_rc_urb_completion(st
 {
 	struct dvb_usb_device *d = purb->context;
 	struct dib0700_rc_response *poll_reply;
+	enum rc_type protocol;
 	u32 uninitialized_var(keycode);
 	u8 toggle;
 
@@ -707,44 +703,55 @@ static void dib0700_rc_urb_completion(st
 
 	switch (d->props.rc.core.protocol) {
 	case RC_BIT_NEC:
+		protocol = RC_TYPE_NEC;
 		toggle = 0;
 
 		/* NEC protocol sends repeat code as 0 0 0 FF */
-		if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
-		    && (poll_reply->not_data == 0xff)) {
+		if (poll_reply->system     == 0x00 &&
+		    poll_reply->not_system == 0x00 &&
+		    poll_reply->data       == 0x00 &&
+		    poll_reply->not_data   == 0xff) {
 			poll_reply->data_state = 2;
 			break;
 		}
 
-		if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
+		if ((poll_reply->data ^ poll_reply->not_data) != 0xff) {
+			deb_data("NEC32 protocol\n");
+			keycode = RC_SCANCODE_NEC32(poll_reply->system     << 24 |
+						     poll_reply->not_system << 16 |
+						     poll_reply->data       << 8  |
+						     poll_reply->not_data);
+		} else if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
 			deb_data("NEC extended protocol\n");
-			/* NEC extended code - 24 bits */
-			keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data;
+			keycode = RC_SCANCODE_NECX(poll_reply->system << 8 |
+						    poll_reply->not_system,
+						    poll_reply->data);
+
 		} else {
 			deb_data("NEC normal protocol\n");
-			/* normal NEC code - 16 bits */
-			keycode = poll_reply->system << 8 | poll_reply->data;
+			keycode = RC_SCANCODE_NEC(poll_reply->system,
+						   poll_reply->data);
 		}
 
 		break;
 	default:
 		deb_data("RC5 protocol\n");
-		/* RC5 Protocol */
+		protocol = RC_TYPE_RC5;
 		toggle = poll_reply->report_id;
-		keycode = poll_reply->system << 8 | poll_reply->data;
+		keycode = RC_SCANCODE_RC5(poll_reply->system, poll_reply->data);
 
 		break;
 	}
 
 	if ((poll_reply->data + poll_reply->not_data) != 0xff) {
 		/* Key failed integrity check */
-		err("key failed integrity check: %04x %02x %02x",
-		    poll_reply->system,
+		err("key failed integrity check: %02x %02x %02x %02x",
+		    poll_reply->system,  poll_reply->not_system,
 		    poll_reply->data, poll_reply->not_data);
 		goto resubmit;
 	}
 
-	rc_keydown(d->rc_dev, keycode, toggle);
+	rc_keydown(d->rc_dev, protocol, keycode, toggle);
 
 resubmit:
 	/* Clean the buffer before we requeue */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c	2014-08-07 04:47:48.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c	2014-09-28 21:28:38.000000000 -0400
@@ -32,6 +32,8 @@ MODULE_PARM_DESC(force_lna_activation, "
 struct dib0700_adapter_state {
 	int (*set_param_save) (struct dvb_frontend *);
 	const struct firmware *frontend_firmware;
+	struct dib7000p_ops dib7000p_ops;
+	struct dib8000_ops dib8000_ops;
 };
 
 /* Hauppauge Nova-T 500 (aka Bristol)
@@ -262,6 +264,11 @@ static struct mt2266_config stk7700d_mt2
 
 static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	if (adap->id == 0) {
 		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 		msleep(10);
@@ -272,16 +279,16 @@ static int stk7700P2_frontend_attach(str
 		msleep(10);
 		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 		msleep(10);
-		if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+		if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 					     stk7700d_dib7000p_mt2266_config)
 		    != 0) {
-			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__);
+			dvb_detach(&state->dib7000p_ops);
 			return -ENODEV;
 		}
 	}
 
-	adap->fe_adap[0].fe =
-		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
 			   0x80 + (adap->id << 1),
 			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
@@ -290,6 +297,11 @@ static int stk7700P2_frontend_attach(str
 
 static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	if (adap->id == 0) {
 		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 		msleep(10);
@@ -301,16 +313,16 @@ static int stk7700d_frontend_attach(stru
 		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 		msleep(10);
 		dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-		if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+		if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
 					     stk7700d_dib7000p_mt2266_config)
 		    != 0) {
-			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__);
+			dvb_detach(&state->dib7000p_ops);
 			return -ENODEV;
 		}
 	}
 
-	adap->fe_adap[0].fe =
-		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
 			   0x80 + (adap->id << 1),
 			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
@@ -320,7 +332,10 @@ static int stk7700d_frontend_attach(stru
 static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct dib0700_adapter_state *state = adap->priv;
+
+	tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
+					    DIBX000_I2C_INTERFACE_TUNER, 1);
 	return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
 		&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
 }
@@ -397,12 +412,14 @@ static int stk7700ph_xc3028_callback(voi
 				     int command, int arg)
 {
 	struct dvb_usb_adapter *adap = ptr;
+	struct dib0700_adapter_state *state = adap->priv;
 
 	switch (command) {
 	case XC2028_TUNER_RESET:
 		/* Send the tuner in then out of reset */
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+		msleep(10);
+		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 		break;
 	case XC2028_RESET_CLK:
 		break;
@@ -428,12 +445,16 @@ static struct xc2028_config stk7700ph_xc
 static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
 
 	if (desc->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
 	    desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
 	else
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
 	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
@@ -445,14 +466,15 @@ static int stk7700ph_frontend_attach(str
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 	msleep(10);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				     &stk7700ph_dib7700_xc3028_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 		    __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
 		&stk7700ph_dib7700_xc3028_config);
 
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -461,8 +483,9 @@ static int stk7700ph_frontend_attach(str
 static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
+	struct dib0700_adapter_state *state = adap->priv;
 
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+	tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
 		DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	stk7700ph_xc3028_config.i2c_adap = tun_i2c;
@@ -489,7 +512,8 @@ static u8 rc_request[] = { REQUEST_POLL_
 static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 {
 	u8 key[4];
-	u32 keycode;
+	enum rc_type protocol;
+	u32 scancode;
 	u8 toggle;
 	int i;
 	struct dib0700_state *st = d->priv;
@@ -516,28 +540,29 @@ static int dib0700_rc_query_old_firmware
 
 	dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */
 
-	d->last_event = 0;
 	switch (d->props.rc.core.protocol) {
 	case RC_BIT_NEC:
 		/* NEC protocol sends repeat code as 0 0 0 FF */
 		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
-		    (key[3] == 0xff))
-			keycode = d->last_event;
-		else {
-			keycode = key[3-2] << 8 | key[3-3];
-			d->last_event = keycode;
+		    (key[3] == 0xff)) {
+			rc_repeat(d->rc_dev);
+			return 0;
 		}
 
-		rc_keydown(d->rc_dev, keycode, 0);
+		protocol = RC_TYPE_NEC;
+		scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]);
+		toggle = 0;
 		break;
+
 	default:
 		/* RC-5 protocol changes toggle bit on new keypress */
-		keycode = key[3-2] << 8 | key[3-3];
+		protocol = RC_TYPE_RC5;
+		scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]);
 		toggle = key[3-1];
-		rc_keydown(d->rc_dev, keycode, toggle);
-
 		break;
 	}
+
+	rc_keydown(d->rc_dev, protocol, scancode, toggle);
 	return 0;
 }
 
@@ -673,6 +698,11 @@ static struct dib7000p_config stk7700p_d
 static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_state *st = adap->dev->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	/* unless there is no real power management in DVB - we leave the device on GPIO6 */
 
 	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
@@ -689,11 +719,13 @@ static int stk7700p_frontend_attach(stru
 
 	st->mt2060_if1[0] = 1220;
 
-	if (dib7000pc_detection(&adap->dev->i2c_adap)) {
-		adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+	if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap)) {
+		adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
 		st->is_dib7000pc = 1;
-	} else
+	} else {
+		memset(&state->dib7000p_ops, 0, sizeof(state->dib7000p_ops));
 		adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+	}
 
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
@@ -707,14 +739,16 @@ static int stk7700p_tuner_attach(struct
 	struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
 	struct dib0700_state *st = adap->dev->priv;
 	struct i2c_adapter *tun_i2c;
+	struct dib0700_adapter_state *state = adap->priv;
 	s8 a;
 	int if1=1220;
+
 	if (adap->dev->udev->descriptor.idVendor  == cpu_to_le16(USB_VID_HAUPPAUGE) &&
 		adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
 		if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
 	}
 	if (st->is_dib7000pc)
-		tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 	else
 		tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
@@ -767,14 +801,20 @@ static struct dibx000_agc_config dib7070
 
 static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
 {
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
 	deb_info("reset: %d", onoff);
-	return dib7000p_set_gpio(fe, 8, 0, !onoff);
+	return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
 }
 
 static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
 	deb_info("sleep: %d", onoff);
-	return dib7000p_set_gpio(fe, 9, 0, onoff);
+	return state->dib7000p_ops.set_gpio(fe, 9, 0, onoff);
 }
 
 static struct dib0070_config dib7070p_dib0070_config[2] = {
@@ -818,7 +858,7 @@ static int dib7070_set_param_override(st
 		default: offset = 550; break;
 	}
 	deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
-	dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+	state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
 	return state->set_param_save(fe);
 }
 
@@ -832,39 +872,39 @@ static int dib7770_set_param_override(st
 	 u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
 	 switch (band) {
 	 case BAND_VHF:
-		  dib7000p_set_gpio(fe, 0, 0, 1);
+		  state->dib7000p_ops.set_gpio(fe, 0, 0, 1);
 		  offset = 850;
 		  break;
 	 case BAND_UHF:
 	 default:
-		  dib7000p_set_gpio(fe, 0, 0, 0);
+		  state->dib7000p_ops.set_gpio(fe, 0, 0, 0);
 		  offset = 250;
 		  break;
 	 }
 	 deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
-	 dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+	 state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
 	 return state->set_param_save(fe);
 }
 
 static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	 struct dib0700_adapter_state *st = adap->priv;
-	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
 			 DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	 if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
-			&dib7770p_dib0070_config) == NULL)
-		 return -ENODEV;
+	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+		       &dib7770p_dib0070_config) == NULL)
+		return -ENODEV;
 
-	 st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	 adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
-	 return 0;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+	return 0;
 }
 
 static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
 		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
@@ -882,28 +922,33 @@ static int dib7070p_tuner_attach(struct
 static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
 		u16 pid, int onoff)
 {
+	struct dib0700_adapter_state *state = adapter->priv;
 	struct dib0700_state *st = adapter->dev->priv;
+
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+		return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 	return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
 	struct dib0700_state *st = adapter->dev->priv;
+	struct dib0700_adapter_state *state = adapter->priv;
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+		return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 	return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
 {
-	return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+	struct dib0700_adapter_state *state = adapter->priv;
+	return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
-	return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+	struct dib0700_adapter_state *state = adapter->priv;
+	return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -936,6 +981,11 @@ static struct dib7000p_config dib7070p_d
 static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
 	    p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
 		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -954,14 +1004,15 @@ static int stk7070p_frontend_attach(stru
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				     &dib7070p_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 		    __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
 		&dib7070p_dib7000p_config);
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
@@ -988,6 +1039,11 @@ static struct dib7000p_config dib7770p_d
 static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
 	    p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
 		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -1006,14 +1062,15 @@ static int stk7770p_frontend_attach(stru
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				     &dib7770p_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 		    __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
 		&dib7770p_dib7000p_config);
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
@@ -1161,12 +1218,18 @@ static struct dib8000_config dib807x_dib
 
 static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
 {
-	return dib8000_set_gpio(fe, 5, 0, !onoff);
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	return state->dib8000_ops.set_gpio(fe, 5, 0, !onoff);
 }
 
 static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
-	return dib8000_set_gpio(fe, 0, 0, onoff);
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	return state->dib8000_ops.set_gpio(fe, 0, 0, onoff);
 }
 
 static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
@@ -1223,7 +1286,7 @@ static int dib807x_set_param_override(st
 		offset += 250; break;
 	}
 	deb_info("WBD for DiB8000: %d\n", offset);
-	dib8000_set_wbd_ref(fe, offset);
+	state->dib8000_ops.set_wbd_ref(fe, offset);
 
 	return state->set_param_save(fe);
 }
@@ -1231,7 +1294,7 @@ static int dib807x_set_param_override(st
 static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
+	struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe,
 			DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
@@ -1252,18 +1315,27 @@ static int dib807x_tuner_attach(struct d
 static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
 	u16 pid, int onoff)
 {
-	return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+	struct dib0700_adapter_state *state = adapter->priv;
+
+	return state->dib8000_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
 		int onoff)
 {
-	return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+	struct dib0700_adapter_state *state = adapter->priv;
+
+	return state->dib8000_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 /* STK807x */
 static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
+
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1279,10 +1351,10 @@ static int stk807x_frontend_attach(struc
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				0x80, 0);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
 	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
@@ -1291,6 +1363,11 @@ static int stk807x_frontend_attach(struc
 /* STK807xPVR */
 static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
+
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
 	msleep(30);
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -1309,9 +1386,9 @@ static int stk807xpvr_frontend_attach0(s
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
 	/* initialize IC 0 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1319,10 +1396,15 @@ static int stk807xpvr_frontend_attach0(s
 
 static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
+
 	/* initialize IC 1 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82,
 			      &dib807x_dib8000_config[1]);
 
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1331,104 +1413,121 @@ static int stk807xpvr_frontend_attach1(s
 /* STK8096GP */
 static struct dibx000_agc_config dib8090_agc_config[2] = {
 	{
-	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+	.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
 	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
 	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
 	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
-	787,
-	10,
+	.inv_gain = 787,
+	.time_stabiliz = 10,
 
-	0,
-	118,
+	.alpha_level = 0,
+	.thlock = 118,
 
-	0,
-	3530,
-	1,
-	5,
+	.wbd_inv = 0,
+	.wbd_ref = 3530,
+	.wbd_sel = 1,
+	.wbd_alpha = 5,
 
-	65535,
-	0,
+	.agc1_max = 65535,
+	.agc1_min = 0,
 
-	65535,
-	0,
+	.agc2_max = 65535,
+	.agc2_min = 0,
 
-	0,
-	32,
-	114,
-	143,
-	144,
-	114,
-	227,
-	116,
-	117,
+	.agc1_pt1 = 0,
+	.agc1_pt2 = 32,
+	.agc1_pt3 = 114,
+	.agc1_slope1 = 143,
+	.agc1_slope2 = 144,
+	.agc2_pt1 = 114,
+	.agc2_pt2 = 227,
+	.agc2_slope1 = 116,
+	.agc2_slope2 = 117,
 
-	28,
-	26,
-	31,
-	51,
+	.alpha_mant = 28,
+	.alpha_exp = 26,
+	.beta_mant = 31,
+	.beta_exp = 51,
 
-	0,
+	.perform_agc_softsplit = 0,
 	},
 	{
-	BAND_CBAND,
+	.band_caps = BAND_CBAND,
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
 	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
 	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
 	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
-	787,
-	10,
+	.inv_gain = 787,
+	.time_stabiliz = 10,
 
-	0,
-	118,
+	.alpha_level = 0,
+	.thlock = 118,
 
-	0,
-	3530,
-	1,
-	5,
+	.wbd_inv = 0,
+	.wbd_ref = 3530,
+	.wbd_sel = 1,
+	.wbd_alpha = 5,
 
-	0,
-	0,
+	.agc1_max = 0,
+	.agc1_min = 0,
 
-	65535,
-	0,
+	.agc2_max = 65535,
+	.agc2_min = 0,
 
-	0,
-	32,
-	114,
-	143,
-	144,
-	114,
-	227,
-	116,
-	117,
+	.agc1_pt1 = 0,
+	.agc1_pt2 = 32,
+	.agc1_pt3 = 114,
+	.agc1_slope1 = 143,
+	.agc1_slope2 = 144,
+	.agc2_pt1 = 114,
+	.agc2_pt2 = 227,
+	.agc2_slope1 = 116,
+	.agc2_slope2 = 117,
 
-	28,
-	26,
-	31,
-	51,
+	.alpha_mant = 28,
+	.alpha_exp = 26,
+	.beta_mant = 31,
+	.beta_exp = 51,
 
-	0,
+	.perform_agc_softsplit = 0,
 	}
 };
 
 static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
-	54000, 13500,
-	1, 18, 3, 1, 0,
-	0, 0, 1, 1, 2,
-	(3 << 14) | (1 << 12) | (599 << 0),
-	(0 << 25) | 0,
-	20199727,
-	12000000,
+	.internal = 54000,
+	.sampling = 13500,
+
+	.pll_prediv = 1,
+	.pll_ratio = 18,
+	.pll_range = 3,
+	.pll_reset = 1,
+	.pll_bypass = 0,
+
+	.enable_refdiv = 0,
+	.bypclk_div = 0,
+	.IO_CLK_en_core = 1,
+	.ADClkSrc = 1,
+	.modulo = 2,
+
+	.sad_cfg = (3 << 14) | (1 << 12) | (599 << 0),
+
+	.ifreq = (0 << 25) | 0,
+	.timf = 20199727,
+
+	.xtal_hz = 12000000,
 };
 
 static int dib8090_get_adc_power(struct dvb_frontend *fe)
 {
-	return dib8000_get_adc_power(fe, 1);
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	return state->dib8000_ops.get_adc_power(fe, 1);
 }
 
 static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart)
@@ -1551,10 +1650,10 @@ static int dib8096_set_param_override(st
 	default:
 			deb_info("Warning : Rf frequency  (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency);
 	case BAND_VHF:
-			dib8000_set_gpio(fe, 3, 0, 1);
+			state->dib8000_ops.set_gpio(fe, 3, 0, 1);
 			break;
 	case BAND_UHF:
-			dib8000_set_gpio(fe, 3, 0, 0);
+			state->dib8000_ops.set_gpio(fe, 3, 0, 0);
 			break;
 	}
 
@@ -1568,7 +1667,7 @@ static int dib8096_set_param_override(st
 	}
 
 	/** Update PLL if needed ratio **/
-	dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+	state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
 
 	/** Get optimize PLL ratio to remove spurious **/
 	pll_ratio = dib8090_compute_pll_parameters(fe);
@@ -1582,14 +1681,14 @@ static int dib8096_set_param_override(st
 		timf = 18179756;
 
 	/** Update ratio **/
-	dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
+	state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
 
-	dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, timf);
+	state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, timf);
 
 	if (band != BAND_CBAND) {
 		/* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */
 		target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
-		dib8000_set_wbd_ref(fe, target);
+		state->dib8000_ops.set_wbd_ref(fe, target);
 	}
 
 	if (band == BAND_CBAND) {
@@ -1601,18 +1700,18 @@ static int dib8096_set_param_override(st
 			msleep(ret);
 			tune_state = dib0090_get_tune_state(fe);
 			if (tune_state == CT_AGC_STEP_0)
-				dib8000_set_gpio(fe, 6, 0, 1);
+				state->dib8000_ops.set_gpio(fe, 6, 0, 1);
 			else if (tune_state == CT_AGC_STEP_1) {
 				dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
 				if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */
-					dib8000_set_gpio(fe, 6, 0, 0);
+					state->dib8000_ops.set_gpio(fe, 6, 0, 0);
 			}
 		} while (tune_state < CT_AGC_STOP);
 
 		deb_info("switching to PWM AGC\n");
 		dib0090_pwm_gain_reset(fe);
-		dib8000_pwm_agc_reset(fe);
-		dib8000_set_tune_state(fe, CT_DEMOD_START);
+		state->dib8000_ops.pwm_agc_reset(fe);
+		state->dib8000_ops.set_tune_state(fe, CT_DEMOD_START);
 	} else {
 		/* for everything else than CBAND we are using standard AGC */
 		deb_info("not tuning in CBAND - standard AGC startup\n");
@@ -1625,7 +1724,7 @@ static int dib8096_set_param_override(st
 static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
 		return -ENODEV;
@@ -1637,6 +1736,11 @@ static int dib809x_tuner_attach(struct d
 
 static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
+
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1652,9 +1756,9 @@ static int stk809x_frontend_attach(struc
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
 
 	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
@@ -1663,16 +1767,16 @@ static int nim8096md_tuner_attach(struct
 {
 	struct dib0700_adapter_state *st = adap->priv;
 	struct i2c_adapter *tun_i2c;
-	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
+	struct dvb_frontend *fe_slave  = st->dib8000_ops.get_slave_frontend(adap->fe_adap[0].fe, 1);
 
 	if (fe_slave) {
-		tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = st->dib8000_ops.get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
 		if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
 			return -ENODEV;
 		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
 		fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
 	}
-	tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
 		return -ENODEV;
 
@@ -1685,6 +1789,10 @@ static int nim8096md_tuner_attach(struct
 static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_frontend *fe_slave;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
 
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
 	msleep(20);
@@ -1703,14 +1811,18 @@ static int nim8096md_frontend_attach(str
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
 	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
-	dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
+	/* Needed to increment refcount */
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
+
+	fe_slave = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
+	state->dib8000_ops.set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
 	return fe_slave == NULL ?  -ENODEV : 0;
 }
@@ -1845,7 +1957,7 @@ static struct dib0090_wbd_slope dib8096p
 	{ 0xFFFF, 0, 0, 0, 0, 0},
 };
 
-static const struct dib0090_config tfe8096p_dib0090_config = {
+static struct dib0090_config tfe8096p_dib0090_config = {
 	.io.clock_khz			= 12000,
 	.io.pll_bypass			= 0,
 	.io.pll_range			= 0,
@@ -1853,8 +1965,6 @@ static const struct dib0090_config tfe80
 	.io.pll_loopdiv			= 6,
 	.io.adc_clock_ratio		= 0,
 	.io.pll_int_loop_filt	= 0,
-	.reset					= dib8096p_tuner_sleep,
-	.sleep					= dib8096p_tuner_sleep,
 
 	.freq_offset_khz_uhf	= -143,
 	.freq_offset_khz_vhf	= -143,
@@ -1871,8 +1981,6 @@ static const struct dib0090_config tfe80
 
 	.fref_clock_ratio		= 1,
 
-	.wbd					= dib8096p_wbd_table,
-
 	.ls_cfg_pad_drv			= 0,
 	.data_tx_drv			= 0,
 	.low_if					= NULL,
@@ -1983,15 +2091,15 @@ static int dib8096p_agc_startup(struct d
 	/* dib0090_get_wbd_target is returning any possible
 	   temperature compensated wbd-target */
 	target = (dib0090_get_wbd_target(fe) * 8  + 1) / 2;
-	dib8000_set_wbd_ref(fe, target);
+	state->dib8000_ops.set_wbd_ref(fe, target);
 
 	if (dib8096p_get_best_sampling(fe, &adc) == 0) {
 		pll.pll_ratio  = adc.pll_loopdiv;
 		pll.pll_prediv = adc.pll_prediv;
 
 		dib0700_set_i2c_speed(adap->dev, 200);
-		dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
-		dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+		state->dib8000_ops.update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+		state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
 		dib0700_set_i2c_speed(adap->dev, 1000);
 	}
 	return 0;
@@ -2001,6 +2109,10 @@ static int tfe8096p_frontend_attach(stru
 {
 	struct dib0700_state *st = adap->dev->priv;
 	u32 fw_version;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+		return -ENODEV;
 
 	dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
 	if (fw_version >= 0x10200)
@@ -2021,10 +2133,10 @@ static int tfe8096p_frontend_attach(stru
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
+	state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
 
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
-			&adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
+	adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap,
+					     0x80, &tfe8096p_dib8000_config);
 
 	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
@@ -2032,13 +2144,17 @@ static int tfe8096p_frontend_attach(stru
 static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
+	struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+	tfe8096p_dib0090_config.reset = st->dib8000_ops.tuner_sleep;
+	tfe8096p_dib0090_config.sleep = st->dib8000_ops.tuner_sleep;
+	tfe8096p_dib0090_config.wbd = dib8096p_wbd_table;
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
 				&tfe8096p_dib0090_config) == NULL)
 		return -ENODEV;
 
-	dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+	st->dib8000_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
 	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
 	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
@@ -2479,14 +2595,14 @@ static int dib7090_agc_startup(struct dv
 	memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
 	dib0090_pwm_gain_reset(fe);
 	target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
-	dib7000p_set_wbd_ref(fe, target);
+	state->dib7000p_ops.set_wbd_ref(fe, target);
 
 	if (dib7090p_get_best_sampling(fe, &adc) == 0) {
 		pll.pll_ratio  = adc.pll_loopdiv;
 		pll.pll_prediv = adc.pll_prediv;
 
-		dib7000p_update_pll(fe, &pll);
-		dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+		state->dib7000p_ops.update_pll(fe, &pll);
+		state->dib7000p_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
 	}
 	return 0;
 }
@@ -2501,14 +2617,17 @@ static int dib7090_agc_restart(struct dv
 
 static int tfe7790p_update_lna(struct dvb_frontend *fe, u16 agc_global)
 {
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
 	deb_info("update LNA: agc global=%i", agc_global);
 
 	if (agc_global < 25000) {
-		dib7000p_set_gpio(fe, 8, 0, 0);
-		dib7000p_set_agc1_min(fe, 0);
+		state->dib7000p_ops.set_gpio(fe, 8, 0, 0);
+		state->dib7000p_ops.set_agc1_min(fe, 0);
 	} else {
-		dib7000p_set_gpio(fe, 8, 0, 1);
-		dib7000p_set_agc1_min(fe, 32768);
+		state->dib7000p_ops.set_gpio(fe, 8, 0, 1);
+		state->dib7000p_ops.set_agc1_min(fe, 32768);
 	}
 
 	return 0;
@@ -2644,13 +2763,16 @@ static struct dib7000p_config nim7090_di
 
 static int tfe7090p_pvr_update_lna(struct dvb_frontend *fe, u16 agc_global)
 {
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
 	deb_info("TFE7090P-PVR update LNA: agc global=%i", agc_global);
 	if (agc_global < 25000) {
-		dib7000p_set_gpio(fe, 5, 0, 0);
-		dib7000p_set_agc1_min(fe, 0);
+		state->dib7000p_ops.set_gpio(fe, 5, 0, 0);
+		state->dib7000p_ops.set_agc1_min(fe, 0);
 	} else {
-		dib7000p_set_gpio(fe, 5, 0, 1);
-		dib7000p_set_agc1_min(fe, 32768);
+		state->dib7000p_ops.set_gpio(fe, 5, 0, 1);
+		state->dib7000p_ops.set_agc1_min(fe, 32768);
 	}
 
 	return 0;
@@ -2714,7 +2836,7 @@ static struct dib7000p_config tfe7090pvr
 	}
 };
 
-static const struct dib0090_config nim7090_dib0090_config = {
+static struct dib0090_config nim7090_dib0090_config = {
 	.io.clock_khz = 12000,
 	.io.pll_bypass = 0,
 	.io.pll_range = 0,
@@ -2722,14 +2844,10 @@ static const struct dib0090_config nim70
 	.io.pll_loopdiv = 6,
 	.io.adc_clock_ratio = 0,
 	.io.pll_int_loop_filt = 0,
-	.reset = dib7090_tuner_sleep,
-	.sleep = dib7090_tuner_sleep,
 
 	.freq_offset_khz_uhf = 0,
 	.freq_offset_khz_vhf = 0,
 
-	.get_adc_power = dib7090_get_adc_power,
-
 	.clkouttobamse = 1,
 	.analog_output = 0,
 
@@ -2776,7 +2894,7 @@ static struct dib7000p_config tfe7790p_d
 	.enMpegOutput				= 1,
 };
 
-static const struct dib0090_config tfe7790p_dib0090_config = {
+static struct dib0090_config tfe7790p_dib0090_config = {
 	.io.clock_khz = 12000,
 	.io.pll_bypass = 0,
 	.io.pll_range = 0,
@@ -2784,14 +2902,10 @@ static const struct dib0090_config tfe77
 	.io.pll_loopdiv = 6,
 	.io.adc_clock_ratio = 0,
 	.io.pll_int_loop_filt = 0,
-	.reset = dib7090_tuner_sleep,
-	.sleep = dib7090_tuner_sleep,
 
 	.freq_offset_khz_uhf = 0,
 	.freq_offset_khz_vhf = 0,
 
-	.get_adc_power = dib7090_get_adc_power,
-
 	.clkouttobamse = 1,
 	.analog_output = 0,
 
@@ -2813,7 +2927,7 @@ static const struct dib0090_config tfe77
 	.force_crystal_mode = 1,
 };
 
-static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
+static struct dib0090_config tfe7090pvr_dib0090_config[2] = {
 	{
 		.io.clock_khz = 12000,
 		.io.pll_bypass = 0,
@@ -2822,14 +2936,10 @@ static const struct dib0090_config tfe70
 		.io.pll_loopdiv = 6,
 		.io.adc_clock_ratio = 0,
 		.io.pll_int_loop_filt = 0,
-		.reset = dib7090_tuner_sleep,
-		.sleep = dib7090_tuner_sleep,
 
 		.freq_offset_khz_uhf = 50,
 		.freq_offset_khz_vhf = 70,
 
-		.get_adc_power = dib7090_get_adc_power,
-
 		.clkouttobamse = 1,
 		.analog_output = 0,
 
@@ -2854,14 +2964,10 @@ static const struct dib0090_config tfe70
 		.io.pll_loopdiv = 6,
 		.io.adc_clock_ratio = 0,
 		.io.pll_int_loop_filt = 0,
-		.reset = dib7090_tuner_sleep,
-		.sleep = dib7090_tuner_sleep,
 
 		.freq_offset_khz_uhf = -50,
 		.freq_offset_khz_vhf = -70,
 
-		.get_adc_power = dib7090_get_adc_power,
-
 		.clkouttobamse = 1,
 		.analog_output = 0,
 
@@ -2883,6 +2989,11 @@ static const struct dib0090_config tfe70
 
 static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -2895,11 +3006,12 @@ static int nim7090_frontend_attach(struc
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
 
 	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
@@ -2907,12 +3019,16 @@ static int nim7090_frontend_attach(struc
 static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+	struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+	nim7090_dib0090_config.reset = st->dib7000p_ops.tuner_sleep,
+	nim7090_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep,
+	nim7090_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+	st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
 	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
 	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2922,6 +3038,10 @@ static int nim7090_tuner_attach(struct d
 static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_state *st = adap->dev->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
 
 	/* The TFE7090 requires the dib0700 to not be in master mode */
 	st->disable_streaming_master_mode = 1;
@@ -2939,17 +3059,18 @@ static int tfe7090pvr_frontend0_attach(s
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
 	/* initialize IC 0 */
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
 	dib0700_set_i2c_speed(adap->dev, 340);
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
 	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	dib7090_slave_reset(adap->fe_adap[0].fe);
+	state->dib7000p_ops.slave_reset(adap->fe_adap[0].fe);
 
 	return 0;
 }
@@ -2957,19 +3078,24 @@ static int tfe7090pvr_frontend0_attach(s
 static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *i2c;
+	struct dib0700_adapter_state *state = adap->priv;
 
 	if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
 		err("the master dib7090 has to be initialized first");
 		return -ENODEV; /* the master device has not been initialized */
 	}
 
-	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
-	if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
+	i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+	if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
 	dib0700_set_i2c_speed(adap->dev, 200);
 
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -2978,12 +3104,16 @@ static int tfe7090pvr_frontend1_attach(s
 static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+	struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+	tfe7090pvr_dib0090_config[0].reset = st->dib7000p_ops.tuner_sleep;
+	tfe7090pvr_dib0090_config[0].sleep = st->dib7000p_ops.tuner_sleep;
+	tfe7090pvr_dib0090_config[0].get_adc_power = st->dib7000p_ops.get_adc_power;
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+	st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
 	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
 	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2993,12 +3123,16 @@ static int tfe7090pvr_tuner0_attach(stru
 static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+	struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+	tfe7090pvr_dib0090_config[1].reset = st->dib7000p_ops.tuner_sleep;
+	tfe7090pvr_dib0090_config[1].sleep = st->dib7000p_ops.tuner_sleep;
+	tfe7090pvr_dib0090_config[1].get_adc_power = st->dib7000p_ops.get_adc_power;
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+	st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
 	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
 	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3008,6 +3142,10 @@ static int tfe7090pvr_tuner1_attach(stru
 static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_state *st = adap->dev->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
 
 	/* The TFE7790P requires the dib0700 to not be in master mode */
 	st->disable_streaming_master_mode = 1;
@@ -3024,13 +3162,14 @@ static int tfe7790p_frontend_attach(stru
 	msleep(20);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap,
 				1, 0x10, &tfe7790p_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 				__func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
 			0x80, &tfe7790p_dib7000p_config);
 
 	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
@@ -3040,13 +3179,18 @@ static int tfe7790p_tuner_attach(struct
 {
 	struct dib0700_adapter_state *st = adap->priv;
 	struct i2c_adapter *tun_i2c =
-		dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+		st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+
+	tfe7790p_dib0090_config.reset = st->dib7000p_ops.tuner_sleep;
+	tfe7790p_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep;
+	tfe7790p_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
 
 	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
 				&tfe7790p_dib0090_config) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+	st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 
 	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
 	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3103,25 +3247,36 @@ static void stk7070pd_init(struct dvb_us
 
 static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
 {
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
 	stk7070pd_init(adap->dev);
 
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
 				     stk7070pd_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 		    __func__);
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
 {
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
+
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
 	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
@@ -3164,6 +3319,10 @@ static int novatd_frontend_attach(struct
 {
 	struct dvb_usb_device *dev = adap->dev;
 	struct dib0700_state *st = dev->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
 
 	if (adap->id == 0) {
 		stk7070pd_init(dev);
@@ -3173,15 +3332,16 @@ static int novatd_frontend_attach(struct
 		dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
 		dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
 
-		if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+		if (state->dib7000p_ops.i2c_enumeration(&dev->i2c_adap, 2, 18,
 					     stk7070pd_dib7000p_config) != 0) {
-			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n",
 			    __func__);
+			dvb_detach(&state->dib7000p_ops);
 			return -ENODEV;
 		}
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&dev->i2c_adap,
 			adap->id == 0 ? 0x80 : 0x82,
 			&stk7070pd_dib7000p_config[adap->id]);
 
@@ -3291,12 +3451,13 @@ static int dib0700_xc4000_tuner_callback
 					 int command, int arg)
 {
 	struct dvb_usb_adapter *adap = priv;
+	struct dib0700_adapter_state *state = adap->priv;
 
 	if (command == XC4000_TUNER_RESET) {
 		/* Reset the tuner */
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
 		msleep(10);
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 	} else {
 		err("xc4000: unknown tuner callback command: %d\n", command);
 		return -EINVAL;
@@ -3374,6 +3535,10 @@ static struct dib7000p_config pctv_340e_
 static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_state *st = adap->dev->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+
+	if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+		return -ENODEV;
 
 	/* Power Supply on */
 	dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0);
@@ -3397,12 +3562,13 @@ static int pctv340e_frontend_attach(stru
 
 	msleep(500);
 
-	if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
+	if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
 		/* Demodulator not found for some reason? */
+		dvb_detach(&state->dib7000p_ops);
 		return -ENODEV;
 	}
 
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x12,
 			      &pctv_340e_config);
 	st->is_dib7000pc = 1;
 
@@ -3420,9 +3586,10 @@ static struct xc4000_config dib7000p_xc4
 static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
+	struct dib0700_adapter_state *state = adap->priv;
 
 	/* The xc4000 is not on the main i2c bus */
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+	tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
 					  DIBX000_I2C_INTERFACE_TUNER, 1);
 	if (tun_i2c == NULL) {
 		printk(KERN_ERR "Could not reach tuner i2c bus\n");
@@ -3636,6 +3803,7 @@ struct dvb_usb_device_properties dib0700
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
 			}},
+				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			},
 		},
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dibusb.h linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dibusb.h
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dibusb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dibusb.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@
 
 /*
  * i2c read
- * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
+ * bulk write: 0x02 ((7bit i2c_addr << 1) | 0x01) register_bytes length_word
  * bulk read:  byte_buffer (length_word bytes)
  */
 #define DIBUSB_REQ_I2C_READ			0x02
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dvb-usb-remote.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dvb-usb-remote.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dvb-usb-remote.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dvb-usb-remote.c	2014-09-28 17:29:07.000000000 -0400
@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(s
 	dev->driver_name = d->props.rc.core.module_name;
 	dev->map_name = d->props.rc.core.rc_codes;
 	dev->change_protocol = d->props.rc.core.change_protocol;
-	rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos);
+	dev->allowed_protocols = d->props.rc.core.allowed_protos;
 	dev->driver_type = d->props.rc.core.driver_type;
 	usb_to_input_id(d->udev, &dev->input_id);
 	dev->input_name = "IR-receiver inside an USB DVB receiver";
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dw2102.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dw2102.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/dw2102.c	2014-08-07 04:48:01.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/dw2102.c	2014-09-28 21:28:53.000000000 -0400
@@ -1109,6 +1109,7 @@ static struct ds3000_config su3000_ds300
 static struct cxd2820r_config cxd2820r_config = {
 	.i2c_address = 0x6c, /* (0xd8 >> 1) */
 	.ts_mode = 0x38,
+	.ts_clock_inv = 1,
 };
 
 static struct tda18271_config tda18271_config = {
@@ -1387,20 +1388,27 @@ static int su3000_frontend_attach(struct
 
 static int t220_frontend_attach(struct dvb_usb_adapter *d)
 {
-	u8 obuf[3] = { 0xe, 0x80, 0 };
+	u8 obuf[3] = { 0xe, 0x87, 0 };
 	u8 ibuf[] = { 0 };
 
 	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
 		err("command 0x0e transfer failed.");
 
 	obuf[0] = 0xe;
-	obuf[1] = 0x83;
+	obuf[1] = 0x86;
+	obuf[2] = 1;
+
+	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+		err("command 0x0e transfer failed.");
+
+	obuf[0] = 0xe;
+	obuf[1] = 0x80;
 	obuf[2] = 0;
 
 	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
 		err("command 0x0e transfer failed.");
 
-	msleep(100);
+	msleep(50);
 
 	obuf[0] = 0xe;
 	obuf[1] = 0x80;
@@ -1482,7 +1490,7 @@ static int dw2102_rc_query(struct dvb_us
 		if (msg.buf[0] != 0xff) {
 			deb_rc("%s: rc code: %x, %x\n",
 					__func__, key[0], key[1]);
-			rc_keydown(d->rc_dev, key[0], 1);
+			rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0], 0);
 		}
 	}
 
@@ -1503,7 +1511,7 @@ static int prof_rc_query(struct dvb_usb_
 		if (msg.buf[0] != 0xff) {
 			deb_rc("%s: rc code: %x, %x\n",
 					__func__, key[0], key[1]);
-			rc_keydown(d->rc_dev, key[0]^0xff, 1);
+			rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0]^0xff, 0);
 		}
 	}
 
@@ -1524,7 +1532,8 @@ static int su3000_rc_query(struct dvb_us
 		if (msg.buf[0] != 0xff) {
 			deb_rc("%s: rc code: %x, %x\n",
 					__func__, key[0], key[1]);
-			rc_keydown(d->rc_dev, key[1] << 8 | key[0], 1);
+			rc_keydown(d->rc_dev, RC_TYPE_RC5,
+				   RC_SCANCODE_RC5(key[1], key[0]), 0);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -117,10 +117,12 @@ config DVB_USB_CXUSB
 	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
 	  Currently, only DVB and ATSC modes are supported, analog mode
@@ -128,6 +130,7 @@ config DVB_USB_CXUSB
 
 	  Medion MD95700 hybrid USB2.0 device.
 	  DViCO FusionHDTV (Bluebird) USB2.0 devices
+	  TechnoTrend TVStick CT2-4400
 
 config DVB_USB_M920X
 	tristate "Uli m920x DVB-T USB2.0 support"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/m920x.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/m920x.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/m920x.c	2014-08-07 04:48:13.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/m920x.c	2014-09-28 21:29:06.000000000 -0400
@@ -245,7 +245,7 @@ static int m920x_rc_core_query(struct dv
 	else if (state == REMOTE_KEY_REPEAT)
 		rc_repeat(d->rc_dev);
 	else
-		rc_keydown(d->rc_dev, rc_state[1], 0);
+		rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, rc_state[1], 0);
 
 out:
 	kfree(rc_state);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/pctv452e.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/pctv452e.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/pctv452e.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/pctv452e.c	2014-09-28 17:29:07.000000000 -0400
@@ -565,12 +565,12 @@ static int pctv452e_rc_query(struct dvb_
 
 	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
 		/* got a "press" event */
-		state->last_rc_key = (rx[7] << 8) | rx[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__, rx[6], rx[7]);
 
-		rc_keydown(d->rc_dev, state->last_rc_key, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
 	} else if (state->last_rc_key) {
 		rc_keyup(d->rc_dev);
 		state->last_rc_key = 0;
@@ -927,7 +927,7 @@ static struct dvb_usb_device_properties
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
-		.allowed_protos	= RC_BIT_UNKNOWN,
+		.allowed_protos	= RC_BIT_RC5,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
@@ -980,7 +980,7 @@ static struct dvb_usb_device_properties
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_TT_1500,
-		.allowed_protos	= RC_BIT_UNKNOWN,
+		.allowed_protos	= RC_BIT_RC5,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c	2014-08-07 04:48:20.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c	2014-09-28 21:29:13.000000000 -0400
@@ -710,7 +710,7 @@ static struct dvb_usb_device_properties
 					.isoc = {
 						.framesperurb = 32,
 						.framesize = 2048,
-						.interval = 3,
+						.interval = 1,
 					}
 				}
 			},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/ttusb2.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/ttusb2.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb/ttusb2.c	2014-08-07 04:48:22.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb/ttusb2.c	2014-09-28 21:29:15.000000000 -0400
@@ -438,9 +438,9 @@ static int tt3650_rc_query(struct dvb_us
 
 	if (rx[8] & 0x01) {
 		/* got a "press" event */
-		st->last_rc_key = (rx[3] << 8) | rx[2];
+		st->last_rc_key = RC_SCANCODE_RC5(rx[3], rx[2]);
 		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
-		rc_keydown(d->rc_dev, st->last_rc_key, rx[1]);
+		rc_keydown(d->rc_dev, RC_TYPE_RC5, st->last_rc_key, rx[1]);
 	} else if (st->last_rc_key) {
 		rc_keyup(d->rc_dev);
 		st->last_rc_key = 0;
@@ -747,7 +747,7 @@ static struct dvb_usb_device_properties
 		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
 		.rc_codes         = RC_MAP_TT_1500,
 		.rc_query         = tt3650_rc_query,
-		.allowed_protos   = RC_BIT_UNKNOWN,
+		.allowed_protos   = RC_BIT_RC5,
 	},
 
 	.num_adapters = 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/af9015.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/af9015.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/af9015.c	2014-08-07 04:47:31.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/af9015.c	2014-09-28 21:28:20.000000000 -0400
@@ -1213,7 +1213,7 @@ static int af9015_rc_query(struct dvb_us
 	if ((state->rc_repeat != buf[6] || buf[0]) &&
 			!memcmp(&buf[12], state->rc_last, 4)) {
 		dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__);
-		rc_keydown(d->rc_dev, state->rc_keycode, 0);
+		rc_repeat(d->rc_dev);
 		state->rc_repeat = buf[6];
 		return ret;
 	}
@@ -1233,18 +1233,22 @@ static int af9015_rc_query(struct dvb_us
 		if (buf[14] == (u8) ~buf[15]) {
 			if (buf[12] == (u8) ~buf[13]) {
 				/* NEC */
-				state->rc_keycode = buf[12] << 8 | buf[14];
+				state->rc_keycode = RC_SCANCODE_NEC(buf[12],
+								    buf[14]);
 			} else {
 				/* NEC extended*/
-				state->rc_keycode = buf[12] << 16 |
-					buf[13] << 8 | buf[14];
+				state->rc_keycode = RC_SCANCODE_NECX(buf[12] << 8 |
+								     buf[13],
+								     buf[14]);
 			}
 		} else {
 			/* 32 bit NEC */
-			state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
-					buf[14] << 8 | buf[15];
+			state->rc_keycode = RC_SCANCODE_NEC32(buf[12] << 24 |
+							      buf[13] << 16 |
+							      buf[14] << 8  |
+							      buf[15]);
 		}
-		rc_keydown(d->rc_dev, state->rc_keycode, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0);
 	} else {
 		dev_dbg(&d->udev->dev, "%s: no key press\n", __func__);
 		/* Invalidate last keypress */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/af9035.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/af9035.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/af9035.c	2014-08-07 04:47:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/af9035.c	2014-09-28 21:28:25.000000000 -0400
@@ -799,6 +799,25 @@ static int af9035_read_config(struct dvb
 		addr += 0x10; /* shift for the 2nd tuner params */
 	}
 
+	/*
+	 * These AVerMedia devices has a bad EEPROM content :-(
+	 * Override some wrong values here.
+	 */
+	if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) {
+		switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
+		case USB_PID_AVERMEDIA_A835B_1835:
+		case USB_PID_AVERMEDIA_A835B_2835:
+		case USB_PID_AVERMEDIA_A835B_3835:
+			dev_info(&d->udev->dev,
+				 "%s: overriding tuner from %02x to %02x\n",
+				 KBUILD_MODNAME, state->af9033_config[0].tuner,
+				 AF9033_TUNER_IT9135_60);
+
+			state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60;
+			break;
+		}
+	}
+
 skip_eeprom:
 	/* get demod clock */
 	ret = af9035_rd_reg(d, 0x00d800, &tmp);
@@ -1313,19 +1332,20 @@ static int af9035_rc_query(struct dvb_us
 	if ((buf[2] + buf[3]) == 0xff) {
 		if ((buf[0] + buf[1]) == 0xff) {
 			/* NEC standard 16bit */
-			key = buf[0] << 8 | buf[2];
+			key = RC_SCANCODE_NEC(buf[0], buf[2]);
 		} else {
 			/* NEC extended 24bit */
-			key = buf[0] << 16 | buf[1] << 8 | buf[2];
+			key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]);
 		}
 	} else {
 		/* NEC full code 32bit */
-		key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+		key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
+					buf[2] << 8  | buf[3]);
 	}
 
 	dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf);
 
-	rc_keydown(d->rc_dev, key, 0);
+	rc_keydown(d->rc_dev, RC_TYPE_NEC, key, 0);
 
 	return 0;
 
@@ -1555,6 +1575,10 @@ static const struct usb_device_id af9035
 		&af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900,
 		&af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E,
+		&af9035_props, "PCTV 78e", RC_MAP_IT913X_V1) },
+	{ DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E,
+		&af9035_props, "PCTV 79e", RC_MAP_IT913X_V2) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/anysee.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/anysee.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/anysee.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/anysee.c	2014-09-28 17:29:07.000000000 -0400
@@ -1038,7 +1038,8 @@ static int anysee_rc_query(struct dvb_us
 	if (ircode[0]) {
 		dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__,
 				ircode[1]);
-		rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC,
+			   RC_SCANCODE_NEC(0x08, ircode[1]), 0);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/az6007.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/az6007.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/az6007.c	2014-08-07 04:47:38.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/az6007.c	2014-09-28 21:28:27.000000000 -0400
@@ -207,24 +207,27 @@ static int az6007_streaming_ctrl(struct
 static int az6007_rc_query(struct dvb_usb_device *d)
 {
 	struct az6007_device_state *st = d_to_priv(d);
-	unsigned code = 0;
+	unsigned code;
 
 	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
 
 	if (st->data[1] == 0x44)
 		return 0;
 
-	if ((st->data[1] ^ st->data[2]) == 0xff)
-		code = st->data[1];
-	else
-		code = st->data[1] << 8 | st->data[2];
-
-	if ((st->data[3] ^ st->data[4]) == 0xff)
-		code = code << 8 | st->data[3];
-	else
-		code = code << 16 | st->data[3] << 8 | st->data[4];
+	if ((st->data[3] ^ st->data[4]) == 0xff) {
+		if ((st->data[1] ^ st->data[2]) == 0xff)
+			code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
+		else
+			code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
+						st->data[3]);
+	} else {
+		code = RC_SCANCODE_NEC32(st->data[1] << 24 |
+					 st->data[2] << 16 |
+					 st->data[3] << 8  |
+					 st->data[4]);
+	}
 
-	rc_keydown(d->rc_dev, code, st->data[5]);
+	rc_keydown(d->rc_dev, RC_TYPE_NEC, code, st->data[5]);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c	2014-08-07 04:47:19.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c	2014-09-28 21:28:08.000000000 -0400
@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct
 	dev->driver_name = (char *) d->props->driver_name;
 	dev->map_name = d->rc.map_name;
 	dev->driver_type = d->rc.driver_type;
-	rc_set_allowed_protocols(dev, d->rc.allowed_protos);
+	dev->allowed_protocols = d->rc.allowed_protos;
 	dev->change_protocol = d->rc.change_protocol;
 	dev->priv = d;
 
@@ -253,13 +253,6 @@ static int dvb_usbv2_adapter_stream_exit
 	return usb_urb_exitv2(&adap->stream);
 }
 
-static int wait_schedule(void *ptr)
-{
-	schedule();
-
-	return 0;
-}
-
 static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
@@ -273,8 +266,7 @@ static int dvb_usb_start_feed(struct dvb
 			dvbdmxfeed->pid, dvbdmxfeed->index);
 
 	/* wait init is done */
-	wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
-			TASK_UNINTERRUPTIBLE);
+	wait_on_bit(&adap->state_bits, ADAP_INIT, TASK_UNINTERRUPTIBLE);
 
 	if (adap->active_fe == -1)
 		return -EINVAL;
@@ -568,7 +560,7 @@ static int dvb_usb_fe_sleep(struct dvb_f
 
 	if (!adap->suspend_resume_active) {
 		set_bit(ADAP_SLEEP, &adap->state_bits);
-		wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule,
+		wait_on_bit(&adap->state_bits, ADAP_STREAMING,
 				TASK_UNINTERRUPTIBLE);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -129,6 +129,7 @@ config DVB_USB_RTL28XXU
 	depends on DVB_USB_V2 && I2C_MUX
 	select DVB_RTL2830
 	select DVB_RTL2832
+	select DVB_RTL2832_SDR if (MEDIA_SUBDRV_AUTOSELECT && MEDIA_SDR_SUPPORT)
 	select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c	2014-08-07 04:48:10.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c	2014-09-28 21:29:03.000000000 -0400
@@ -125,14 +125,13 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
 #define TUNER_RS2000	0x4
 
 struct lme2510_state {
+	unsigned long int_urb_due;
 	u8 id;
 	u8 tuner_config;
 	u8 signal_lock;
 	u8 signal_level;
 	u8 signal_sn;
 	u8 time_key;
-	u8 last_key;
-	u8 key_timeout;
 	u8 i2c_talk_onoff;
 	u8 i2c_gate;
 	u8 i2c_tuner_gate_w;
@@ -287,14 +286,13 @@ static void lme2510_int_response(struct
 		case 0xaa:
 			debug_data_snipet(1, "INT Remote data snipet", ibuf);
 			if ((ibuf[4] + ibuf[5]) == 0xff) {
-				key = ibuf[5];
-				key += (ibuf[3] > 0)
-					? (ibuf[3] ^ 0xff) << 8 : 0;
-				key += (ibuf[2] ^ 0xff) << 16;
+				key = RC_SCANCODE_NECX((ibuf[2] ^ 0xff) << 8 |
+						       (ibuf[3] > 0) ? (ibuf[3] ^ 0xff) : 0,
+						       ibuf[5]);
 				deb_info(1, "INT Key =%08x", key);
 				if (adap_to_d(adap)->rc_dev != NULL)
 					rc_keydown(adap_to_d(adap)->rc_dev,
-						key, 0);
+						   RC_TYPE_NEC, key, 0);
 			}
 			break;
 		case 0xbb:
@@ -323,7 +321,7 @@ static void lme2510_int_response(struct
 				}
 				break;
 			case TUNER_RS2000:
-				if (ibuf[1] == 0x3 &&  ibuf[6] == 0xff)
+				if (ibuf[2] & 0x1)
 					st->signal_lock = 0xff;
 				else
 					st->signal_lock = 0x00;
@@ -343,7 +341,12 @@ static void lme2510_int_response(struct
 		break;
 		}
 	}
+
 	usb_submit_urb(lme_urb, GFP_ATOMIC);
+
+	/* interrupt urb is due every 48 msecs while streaming
+	 *	add 12msecs for system lag */
+	st->int_urb_due = jiffies + msecs_to_jiffies(60);
 }
 
 static int lme2510_int_read(struct dvb_usb_adapter *adap)
@@ -584,14 +587,13 @@ static int lme2510_msg(struct dvb_usb_de
 			switch (wbuf[3]) {
 			case 0x8c:
 				rbuf[0] = 0x55;
-				rbuf[1] = 0xff;
-				if (st->last_key == st->time_key) {
-					st->key_timeout++;
-					if (st->key_timeout > 5)
-						rbuf[1] = 0;
-				} else
-					st->key_timeout = 0;
-				st->last_key = st->time_key;
+				rbuf[1] = st->signal_lock;
+
+				/* If int_urb_due overdue
+				 *  set rbuf[1] to 0 to clear lock */
+				if (time_after(jiffies,	st->int_urb_due))
+					rbuf[1] = 0;
+
 				break;
 			default:
 				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,7 +129,7 @@ int mxl111sf_write_reg_mask(struct mxl11
 				   u8 addr, u8 mask, u8 data)
 {
 	int ret;
-	u8 val;
+	u8 val = 0;
 
 	if (mask != 0xff) {
 		ret = mxl111sf_read_reg(state, addr, &val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
--- linux-libre-3.16-gnu/drivers/media/usb/dvb-usb-v2/rtl28xxu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/dvb-usb-v2/rtl28xxu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1287,19 +1287,19 @@ static int rtl2831u_rc_query(struct dvb_
 		if (buf[2] == (u8) ~buf[3]) {
 			if (buf[0] == (u8) ~buf[1]) {
 				/* NEC standard (16 bit) */
-				rc_code = buf[0] << 8 | buf[2];
+				rc_code = RC_SCANCODE_NEC(buf[0], buf[2]);
 			} else {
 				/* NEC extended (24 bit) */
-				rc_code = buf[0] << 16 |
-						buf[1] << 8 | buf[2];
+				rc_code = RC_SCANCODE_NECX(buf[0] << 8 | buf[1],
+							   buf[2]);
 			}
 		} else {
 			/* NEC full (32 bit) */
-			rc_code = buf[0] << 24 | buf[1] << 16 |
-					buf[2] << 8 | buf[3];
+			rc_code = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
+						    buf[2] << 8  | buf[3]);
 		}
 
-		rc_keydown(d->rc_dev, rc_code, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
 
 		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
 		if (ret)
@@ -1541,6 +1541,8 @@ static const struct usb_device_id rtl28x
 		&rtl2832u_props, "Peak DVB-T USB", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U,
 		&rtl2832u_props, "Sveon STV20", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21,
+		&rtl2832u_props, "Sveon STV21", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27,
 		&rtl2832u_props, "Sveon STV27", NULL) },
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-camera.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-camera.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-camera.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-camera.c	2014-09-28 17:29:07.000000000 -0400
@@ -366,7 +366,7 @@ int em28xx_init_camera(struct em28xx *de
 		v4l2->sensor_xtal = 4300000;
 		pdata.xtal = v4l2->sensor_xtal;
 		if (NULL ==
-		    v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
+		    v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
 					      &mt9v011_info, NULL)) {
 			ret = -ENODEV;
 			break;
@@ -423,7 +423,7 @@ int em28xx_init_camera(struct em28xx *de
 		v4l2->sensor_yres = 480;
 
 		subdev =
-		     v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
+		     v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
 					       &ov2640_info, NULL);
 		if (NULL == subdev) {
 			ret = -ENODEV;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-cards.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-cards.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-cards.c	2014-08-07 04:47:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-cards.c	2014-09-28 21:27:55.000000000 -0400
@@ -2280,6 +2280,8 @@ struct usb_device_id em28xx_id_table[] =
 			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2875),
 			.driver_info = EM2820_BOARD_UNKNOWN },
+	{ USB_DEVICE(0xeb1a, 0x2885), /* MSI Digivox Trio */
+			.driver_info = EM2884_BOARD_TERRATEC_H5 },
 	{ USB_DEVICE(0xeb1a, 0xe300),
 			.driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
 	{ USB_DEVICE(0xeb1a, 0xe303),
@@ -3522,7 +3524,6 @@ static struct usb_driver em28xx_usb_driv
 	.disconnect = em28xx_usb_disconnect,
 	.suspend = em28xx_usb_suspend,
 	.resume = em28xx_usb_resume,
-	.reset_resume = em28xx_usb_resume,
 	.id_table = em28xx_id_table,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-dvb.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-dvb.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-dvb.c	2014-08-07 04:50:25.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-dvb.c	2014-09-28 21:31:39.000000000 -0400
@@ -1213,9 +1213,17 @@ static int em28xx_dvb_init(struct em28xx
 		dvb->fe[0] = dvb_attach(lgdt3305_attach,
 					   &em2870_lgdt3304_dev,
 					   &dev->i2c_adap[dev->def_i2c_bus]);
-		if (dvb->fe[0] != NULL)
-			dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				   &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config);
+		if (!dvb->fe[0]) {
+			result = -EINVAL;
+			goto out_free;
+		}
+		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+			&dev->i2c_adap[dev->def_i2c_bus],
+			&kworld_a340_config)) {
+				dvb_frontend_detach(dvb->fe[0]);
+				result = -EINVAL;
+				goto out_free;
+		}
 		break;
 	case EM28174_BOARD_PCTV_290E:
 		/* set default GPIO0 for LNA, used if GPIOLIB is undefined */
@@ -1545,6 +1553,7 @@ static int em28xx_dvb_init(struct em28xx
 			dvb->i2c_client_demod = client;
 
 			/* attach tuner */
+			memset(&si2157_config, 0, sizeof(si2157_config));
 			si2157_config.fe = dvb->fe[0];
 			memset(&info, 0, sizeof(struct i2c_board_info));
 			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
@@ -1645,10 +1654,14 @@ static int em28xx_dvb_fini(struct em28xx
 	if (dev->disconnected) {
 		/* We cannot tell the device to sleep
 		 * once it has been unplugged. */
-		if (dvb->fe[0])
+		if (dvb->fe[0]) {
 			prevent_sleep(&dvb->fe[0]->ops);
-		if (dvb->fe[1])
+			dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED;
+		}
+		if (dvb->fe[1]) {
 			prevent_sleep(&dvb->fe[1]->ops);
+			dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED;
+		}
 	}
 
 	/* remove I2C tuner */
@@ -1712,7 +1725,6 @@ static int em28xx_dvb_resume(struct em28
 	em28xx_info("Resuming DVB extension");
 	if (dev->dvb) {
 		struct em28xx_dvb *dvb = dev->dvb;
-		struct i2c_client *client = dvb->i2c_client_tuner;
 
 		if (dvb->fe[0]) {
 			ret = dvb_frontend_resume(dvb->fe[0]);
@@ -1723,22 +1735,6 @@ static int em28xx_dvb_resume(struct em28
 			ret = dvb_frontend_resume(dvb->fe[1]);
 			em28xx_info("fe1 resume %d", ret);
 		}
-		/* remove I2C tuner */
-		if (client) {
-			module_put(client->dev.driver->owner);
-			i2c_unregister_device(client);
-		}
-
-		/* remove I2C demod */
-		client = dvb->i2c_client_demod;
-		if (client) {
-			module_put(client->dev.driver->owner);
-			i2c_unregister_device(client);
-		}
-
-		em28xx_unregister_dvb(dvb);
-		kfree(dvb);
-		dev->dvb = NULL;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx.h linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx.h
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -576,13 +576,6 @@ struct em28xx_audio {
 
 struct em28xx;
 
-struct em28xx_fh {
-	struct v4l2_fh fh;
-	struct em28xx *dev;
-
-	enum v4l2_buf_type           type;
-};
-
 enum em28xx_i2c_algo_type {
 	EM28XX_I2C_ALGO_EM28XX = 0,
 	EM28XX_I2C_ALGO_EM2800,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-i2c.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -501,6 +501,12 @@ static int em28xx_i2c_xfer(struct i2c_ad
 	int addr, rc, i;
 	u8 reg;
 
+	/* prevent i2c xfer attempts after device is disconnected
+	   some fe's try to do i2c writes/reads from their release
+	   interfaces when called in disconnect path */
+	if (dev->disconnected)
+		return -ENODEV;
+
 	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
 	if (rc < 0)
 		return rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-input.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-input.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/slab.h>
+#include <linux/bitrev.h>
 
 #include "em28xx.h"
 
@@ -53,6 +54,7 @@ struct em28xx_ir_poll_result {
 	unsigned int toggle_bit:1;
 	unsigned int read_count:7;
 
+	enum rc_type protocol;
 	u32 scancode;
 };
 
@@ -72,7 +74,7 @@ struct em28xx_IR {
 	/* i2c slave address of external device (if used) */
 	u16 i2c_dev_addr;
 
-	int  (*get_key_i2c)(struct i2c_client *, u32 *);
+	int  (*get_key_i2c)(struct i2c_client *ir, enum rc_type *protocol, u32 *scancode);
 	int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
 };
 
@@ -80,7 +82,8 @@ struct em28xx_IR {
  I2C IR based get keycodes - should be used with ir-kbd-i2c
  **********************************************************/
 
-static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, u32 *ir_key)
+static int em28xx_get_key_terratec(struct i2c_client *i2c_dev,
+				   enum rc_type *protocol, u32 *scancode)
 {
 	unsigned char b;
 
@@ -98,14 +101,15 @@ static int em28xx_get_key_terratec(struc
 		/* keep old data */
 		return 1;
 
-	*ir_key = b;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = b;
 	return 1;
 }
 
-static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, u32 *ir_key)
+static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev,
+				  enum rc_type *protocol, u32 *scancode)
 {
 	unsigned char buf[2];
-	u16 code;
 	int size;
 
 	/* poll IR chip */
@@ -127,26 +131,13 @@ static int em28xx_get_key_em_haup(struct
 	 * So, the code translation is not complete. Yet, it is enough to
 	 * work with the provided RC5 IR.
 	 */
-	code =
-		 ((buf[0] & 0x01) ? 0x0020 : 0) | /* 		0010 0000 */
-		 ((buf[0] & 0x02) ? 0x0010 : 0) | /* 		0001 0000 */
-		 ((buf[0] & 0x04) ? 0x0008 : 0) | /* 		0000 1000 */
-		 ((buf[0] & 0x08) ? 0x0004 : 0) | /* 		0000 0100 */
-		 ((buf[0] & 0x10) ? 0x0002 : 0) | /* 		0000 0010 */
-		 ((buf[0] & 0x20) ? 0x0001 : 0) | /* 		0000 0001 */
-		 ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000		  */
-		 ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000		  */
-		 ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100		  */
-		 ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010		  */
-		 ((buf[1] & 0x80) ? 0x0100 : 0);  /* 0000 0001		  */
-
-	/* return key */
-	*ir_key = code;
+	*protocol = RC_TYPE_RC5;
+	*scancode = (bitrev8(buf[1]) & 0x1f) << 8 | bitrev8(buf[0]) >> 2;
 	return 1;
 }
 
 static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev,
-					    u32 *ir_key)
+					    enum rc_type *protocol, u32 *scancode)
 {
 	unsigned char buf[3];
 
@@ -158,13 +149,13 @@ static int em28xx_get_key_pinnacle_usb_g
 	if (buf[0] != 0x00)
 		return 0;
 
-	*ir_key = buf[2]&0x3f;
-
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = buf[2] & 0x3f;
 	return 1;
 }
 
 static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev,
-					       u32 *ir_key)
+					       enum rc_type *protocol, u32 *scancode)
 {
 	unsigned char subaddr, keydetect, key;
 
@@ -184,7 +175,8 @@ static int em28xx_get_key_winfast_usbii_
 	if (key == 0x00)
 		return 0;
 
-	*ir_key = key;
+	*protocol = RC_TYPE_UNKNOWN;
+	*scancode = key;
 	return 1;
 }
 
@@ -215,7 +207,22 @@ static int default_polling_getkey(struct
 	poll_result->read_count = (msg[0] & 0x7f);
 
 	/* Remote Control Address/Data (Regs 0x46/0x47) */
-	poll_result->scancode = msg[1] << 8 | msg[2];
+	switch (ir->rc_type) {
+	case RC_BIT_RC5:
+		poll_result->protocol = RC_TYPE_RC5;
+		poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]);
+		break;
+
+	case RC_BIT_NEC:
+		poll_result->protocol = RC_TYPE_NEC;
+		poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[2]);
+		break;
+
+	default:
+		poll_result->protocol = RC_TYPE_UNKNOWN;
+		poll_result->scancode = msg[1] << 8 | msg[2];
+		break;
+	}
 
 	return 0;
 }
@@ -247,25 +254,32 @@ static int em2874_polling_getkey(struct
 	 */
 	switch (ir->rc_type) {
 	case RC_BIT_RC5:
-		poll_result->scancode = msg[1] << 8 | msg[2];
+		poll_result->protocol = RC_TYPE_RC5;
+		poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]);
 		break;
+
 	case RC_BIT_NEC:
+		poll_result->protocol = RC_TYPE_RC5;
+		poll_result->scancode = msg[1] << 8 | msg[2];
 		if ((msg[3] ^ msg[4]) != 0xff)		/* 32 bits NEC */
-			poll_result->scancode = (msg[1] << 24) |
-						(msg[2] << 16) |
-						(msg[3] << 8)  |
-						 msg[4];
+			poll_result->scancode = RC_SCANCODE_NEC32((msg[1] << 24) |
+								  (msg[2] << 16) |
+								  (msg[3] << 8)  |
+								  (msg[4]));
 		else if ((msg[1] ^ msg[2]) != 0xff)	/* 24 bits NEC */
-			poll_result->scancode = (msg[1] << 16) |
-						(msg[2] << 8)  |
-						 msg[3];
+			poll_result->scancode = RC_SCANCODE_NECX(msg[1] << 8 |
+								 msg[2], msg[3]);
 		else					/* Normal NEC */
-			poll_result->scancode = msg[1] << 8 | msg[3];
+			poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[3]);
 		break;
+
 	case RC_BIT_RC6_0:
-		poll_result->scancode = msg[1] << 8 | msg[2];
+		poll_result->protocol = RC_TYPE_RC6_0;
+		poll_result->scancode = RC_SCANCODE_RC6_0(msg[1], msg[2]);
 		break;
+
 	default:
+		poll_result->protocol = RC_TYPE_UNKNOWN;
 		poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) |
 					(msg[3] << 8)  | msg[4];
 		break;
@@ -281,22 +295,24 @@ static int em2874_polling_getkey(struct
 static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir)
 {
 	struct em28xx *dev = ir->dev;
-	static u32 ir_key;
+	static u32 scancode;
+	enum rc_type protocol;
 	int rc;
 	struct i2c_client client;
 
 	client.adapter = &ir->dev->i2c_adap[dev->def_i2c_bus];
 	client.addr = ir->i2c_dev_addr;
 
-	rc = ir->get_key_i2c(&client, &ir_key);
+	rc = ir->get_key_i2c(&client, &protocol, &scancode);
 	if (rc < 0) {
 		dprintk("ir->get_key_i2c() failed: %d\n", rc);
 		return rc;
 	}
 
 	if (rc) {
-		dprintk("%s: keycode = 0x%04x\n", __func__, ir_key);
-		rc_keydown(ir->rc, ir_key, 0);
+		dprintk("%s: proto = 0x%04x, scancode = 0x%04x\n",
+			__func__, protocol, scancode);
+		rc_keydown(ir->rc, protocol, scancode, 0);
 	}
 	return 0;
 }
@@ -319,10 +335,12 @@ static void em28xx_ir_handle_key(struct
 			poll_result.scancode);
 		if (ir->full_code)
 			rc_keydown(ir->rc,
+				   poll_result.protocol,
 				   poll_result.scancode,
 				   poll_result.toggle_bit);
 		else
 			rc_keydown(ir->rc,
+				   RC_TYPE_UNKNOWN,
 				   poll_result.scancode & 0xff,
 				   poll_result.toggle_bit);
 
@@ -727,7 +745,7 @@ static int em28xx_ir_init(struct em28xx
 		case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
 			rc->map_name = RC_MAP_HAUPPAUGE;
 			ir->get_key_i2c = em28xx_get_key_em_haup;
-			rc_set_allowed_protocols(rc, RC_BIT_RC5);
+			rc->allowed_protocols = RC_BIT_RC5;
 			break;
 		case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
 			rc->map_name = RC_MAP_WINFAST_USBII_DELUXE;
@@ -743,7 +761,7 @@ static int em28xx_ir_init(struct em28xx
 		switch (dev->chip_id) {
 		case CHIP_ID_EM2860:
 		case CHIP_ID_EM2883:
-			rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+			rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC;
 			ir->get_key = default_polling_getkey;
 			break;
 		case CHIP_ID_EM2884:
@@ -751,8 +769,8 @@ static int em28xx_ir_init(struct em28xx
 		case CHIP_ID_EM28174:
 		case CHIP_ID_EM28178:
 			ir->get_key = em2874_polling_getkey;
-			rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC |
-						 RC_BIT_RC6_0);
+			rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC |
+					     RC_BIT_RC6_0;
 			break;
 		default:
 			err = -ENODEV;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/em28xx/em28xx-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/em28xx/em28xx-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1227,8 +1227,7 @@ static void scale_to_size(struct em28xx
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx         *dev = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
 
 	f->fmt.pix.width = v4l2->width;
@@ -1261,8 +1260,7 @@ static struct em28xx_fmt *format_by_four
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 			struct v4l2_format *f)
 {
-	struct em28xx_fh      *fh    = priv;
-	struct em28xx         *dev   = fh->dev;
+	struct em28xx         *dev   = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2  = dev->v4l2;
 	unsigned int          width  = f->fmt.pix.width;
 	unsigned int          height = f->fmt.pix.height;
@@ -1344,7 +1342,7 @@ static int vidioc_s_fmt_vid_cap(struct f
 	struct em28xx *dev = video_drvdata(file);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 
-	if (v4l2->streaming_users > 0)
+	if (vb2_is_busy(&v4l2->vb_vidq))
 		return -EBUSY;
 
 	vidioc_try_fmt_vid_cap(file, priv, f);
@@ -1355,8 +1353,7 @@ static int vidioc_s_fmt_vid_cap(struct f
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	*norm = dev->v4l2->norm;
 
@@ -1365,8 +1362,7 @@ static int vidioc_g_std(struct file *fil
 
 static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
 
@@ -1375,8 +1371,7 @@ static int vidioc_querystd(struct file *
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
 {
-	struct em28xx_fh   *fh   = priv;
-	struct em28xx      *dev  = fh->dev;
+	struct em28xx      *dev  = video_drvdata(file);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 	struct v4l2_format f;
 
@@ -1408,8 +1403,7 @@ static int vidioc_s_std(struct file *fil
 static int vidioc_g_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *p)
 {
-	struct em28xx_fh   *fh   = priv;
-	struct em28xx      *dev  = fh->dev;
+	struct em28xx      *dev  = video_drvdata(file);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 	int rc = 0;
 
@@ -1427,8 +1421,7 @@ static int vidioc_g_parm(struct file *fi
 static int vidioc_s_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *p)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	p->parm.capture.readbuffers = EM28XX_MIN_BUF;
 	return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
@@ -1450,8 +1443,7 @@ static const char *iname[] = {
 static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *i)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 	unsigned int       n;
 
 	n = i->index;
@@ -1479,8 +1471,7 @@ static int vidioc_enum_input(struct file
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	*i = dev->ctl_input;
 
@@ -1489,8 +1480,7 @@ static int vidioc_g_input(struct file *f
 
 static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (i >= MAX_EM28XX_INPUT)
 		return -EINVAL;
@@ -1503,8 +1493,7 @@ static int vidioc_s_input(struct file *f
 
 static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
-	struct em28xx_fh   *fh    = priv;
-	struct em28xx      *dev   = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	switch (a->index) {
 	case EM28XX_AMUX_VIDEO:
@@ -1543,8 +1532,7 @@ static int vidioc_g_audio(struct file *f
 
 static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
-	struct em28xx_fh   *fh  = priv;
-	struct em28xx      *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (a->index >= MAX_EM28XX_INPUT)
 		return -EINVAL;
@@ -1563,8 +1551,7 @@ static int vidioc_s_audio(struct file *f
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *t)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1578,8 +1565,7 @@ static int vidioc_g_tuner(struct file *f
 static int vidioc_s_tuner(struct file *file, void *priv,
 				const struct v4l2_tuner *t)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1591,8 +1577,7 @@ static int vidioc_s_tuner(struct file *f
 static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx         *dev = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
 
 	if (0 != f->tuner)
@@ -1606,8 +1591,7 @@ static int vidioc_s_frequency(struct fil
 				const struct v4l2_frequency *f)
 {
 	struct v4l2_frequency  new_freq = *f;
-	struct em28xx_fh          *fh   = priv;
-	struct em28xx             *dev  = fh->dev;
+	struct em28xx             *dev  = video_drvdata(file);
 	struct em28xx_v4l2        *v4l2 = dev->v4l2;
 
 	if (0 != f->tuner)
@@ -1624,8 +1608,7 @@ static int vidioc_s_frequency(struct fil
 static int vidioc_g_chip_info(struct file *file, void *priv,
 	       struct v4l2_dbg_chip_info *chip)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (chip->match.addr > 1)
 		return -EINVAL;
@@ -1652,8 +1635,7 @@ static int em28xx_reg_len(int reg)
 static int vidioc_g_register(struct file *file, void *priv,
 			     struct v4l2_dbg_register *reg)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 	int ret;
 
 	if (reg->match.addr > 1)
@@ -1693,8 +1675,7 @@ static int vidioc_g_register(struct file
 static int vidioc_s_register(struct file *file, void *priv,
 			     const struct v4l2_dbg_register *reg)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx *dev = video_drvdata(file);
 	__le16 buf;
 
 	if (reg->match.addr > 1)
@@ -1715,8 +1696,7 @@ static int vidioc_querycap(struct file *
 					struct v4l2_capability *cap)
 {
 	struct video_device   *vdev = video_devdata(file);
-	struct em28xx_fh      *fh   = priv;
-	struct em28xx         *dev  = fh->dev;
+	struct em28xx         *dev  = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
 
 	strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
@@ -1761,8 +1741,7 @@ static int vidioc_enum_fmt_vid_cap(struc
 static int vidioc_enum_framesizes(struct file *file, void *priv,
 				  struct v4l2_frmsizeenum *fsize)
 {
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
+	struct em28xx         *dev = video_drvdata(file);
 	struct em28xx_fmt     *fmt;
 	unsigned int	      maxw = norm_maxw(dev);
 	unsigned int	      maxh = norm_maxh(dev);
@@ -1806,8 +1785,7 @@ static int vidioc_enum_framesizes(struct
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 				struct v4l2_format *format)
 {
-	struct em28xx_fh      *fh   = priv;
-	struct em28xx         *dev  = fh->dev;
+	struct em28xx         *dev  = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
 
 	format->fmt.vbi.samples_per_line = v4l2->vbi_width;
@@ -1840,7 +1818,7 @@ static int vidioc_g_fmt_vbi_cap(struct f
 static int radio_g_tuner(struct file *file, void *priv,
 			 struct v4l2_tuner *t)
 {
-	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (unlikely(t->index > 0))
 		return -EINVAL;
@@ -1855,7 +1833,7 @@ static int radio_g_tuner(struct file *fi
 static int radio_s_tuner(struct file *file, void *priv,
 			 const struct v4l2_tuner *t)
 {
-	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+	struct em28xx *dev = video_drvdata(file);
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1890,7 +1868,7 @@ static int em28xx_v4l2_open(struct file
 	struct em28xx *dev = video_drvdata(filp);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 	enum v4l2_buf_type fh_type = 0;
-	struct em28xx_fh *fh;
+	int ret;
 
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_GRABBER:
@@ -1911,16 +1889,14 @@ static int em28xx_v4l2_open(struct file
 
 	if (mutex_lock_interruptible(&dev->lock))
 		return -ERESTARTSYS;
-	fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
-	if (!fh) {
-		em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+
+	ret = v4l2_fh_open(filp);
+	if (ret) {
+		em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
+			      __func__, ret);
 		mutex_unlock(&dev->lock);
-		return -ENOMEM;
+		return ret;
 	}
-	v4l2_fh_init(&fh->fh, vdev);
-	fh->dev = dev;
-	fh->type = fh_type;
-	filp->private_data = fh;
 
 	if (v4l2->users == 0) {
 		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
@@ -1945,7 +1921,6 @@ static int em28xx_v4l2_open(struct file
 	v4l2->users++;
 
 	mutex_unlock(&dev->lock);
-	v4l2_fh_add(&fh->fh);
 
 	return 0;
 }
@@ -2046,8 +2021,7 @@ static int em28xx_v4l2_resume(struct em2
  */
 static int em28xx_v4l2_close(struct file *filp)
 {
-	struct em28xx_fh      *fh   = filp->private_data;
-	struct em28xx         *dev  = fh->dev;
+	struct em28xx         *dev  = video_drvdata(filp);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
 	int              errCode;
 
@@ -2208,7 +2182,6 @@ static struct video_device *em28xx_vdev_
 	vfd->v4l2_dev	= &dev->v4l2->v4l2_dev;
 	vfd->debug	= video_debug;
 	vfd->lock	= &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	if (dev->board.is_webcam)
 		vfd->tvnorms = 0;
 
@@ -2552,7 +2525,7 @@ static int em28xx_v4l2_init(struct em28x
 		v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
 
 		/* disable inapplicable ioctls */
-		v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
+		v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM);
 		if (dev->tuner_type == TUNER_ABSENT) {
 			v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
 			v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-driver.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-driver.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-driver.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-driver.c	2014-09-28 21:31:54.000000000 -0400
@@ -0,0 +1,766 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+
+#include "go7007-priv.h"
+
+/*
+ * Wait for an interrupt to be delivered from the GO7007SB and return
+ * the associated value and data.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
+{
+	go->interrupt_available = 0;
+	go->hpi_ops->read_interrupt(go);
+	if (wait_event_timeout(go->interrupt_waitq,
+				go->interrupt_available, 5*HZ) < 0) {
+		v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n");
+		return -1;
+	}
+	if (!go->interrupt_available)
+		return -1;
+	go->interrupt_available = 0;
+	*value = go->interrupt_value & 0xfffe;
+	*data = go->interrupt_data;
+	return 0;
+}
+EXPORT_SYMBOL(go7007_read_interrupt);
+
+/*
+ * Read a register/address on the GO7007SB.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data)
+{
+	int count = 100;
+	u16 value;
+
+	if (go7007_write_interrupt(go, 0x0010, addr) < 0)
+		return -EIO;
+	while (count-- > 0) {
+		if (go7007_read_interrupt(go, &value, data) == 0 &&
+				value == 0xa000)
+			return 0;
+	}
+	return -EIO;
+}
+EXPORT_SYMBOL(go7007_read_addr);
+
+/*
+ * Send the boot firmware to the encoder, which just wakes it up and lets
+ * us talk to the GPIO pins and on-board I2C adapter.
+ *
+ * Must be called with the hw_lock held.
+ */
+static int go7007_load_encoder(struct go7007 *go)
+{
+	const struct firmware *fw_entry;
+	char fw_name[] = "/*(DEBLOBBED)*/";
+	void *bounce;
+	int fw_len, rv = 0;
+	u16 intr_val, intr_data;
+
+	if (go->boot_fw == NULL) {
+		if (reject_firmware(&fw_entry, fw_name, go->dev)) {
+			v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
+			return -1;
+		}
+		if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
+			v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
+			release_firmware(fw_entry);
+			return -1;
+		}
+		fw_len = fw_entry->size - 16;
+		bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
+		if (bounce == NULL) {
+			v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
+			release_firmware(fw_entry);
+			return -1;
+		}
+		release_firmware(fw_entry);
+		go->boot_fw_len = fw_len;
+		go->boot_fw = bounce;
+	}
+	if (go7007_interface_reset(go) < 0 ||
+	    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
+	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+			(intr_val & ~0x1) != 0x5a5a) {
+		v4l2_err(go, "error transferring firmware\n");
+		rv = -1;
+	}
+	return rv;
+}
+
+/*(DEBLOBBED)*/
+
+/*
+ * Boot the encoder and register the I2C adapter if requested.  Do the
+ * minimum initialization necessary, since the board-specific code may
+ * still need to probe the board ID.
+ *
+ * Must NOT be called with the hw_lock held.
+ */
+int go7007_boot_encoder(struct go7007 *go, int init_i2c)
+{
+	int ret;
+
+	mutex_lock(&go->hw_lock);
+	ret = go7007_load_encoder(go);
+	mutex_unlock(&go->hw_lock);
+	if (ret < 0)
+		return -1;
+	if (!init_i2c)
+		return 0;
+	if (go7007_i2c_init(go) < 0)
+		return -1;
+	go->i2c_adapter_online = 1;
+	return 0;
+}
+EXPORT_SYMBOL(go7007_boot_encoder);
+
+/*
+ * Configure any hardware-related registers in the GO7007, such as GPIO
+ * pins and bus parameters, which are board-specific.  This assumes
+ * the boot firmware has already been downloaded.
+ *
+ * Must be called with the hw_lock held.
+ */
+static int go7007_init_encoder(struct go7007 *go)
+{
+	if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
+		go7007_write_addr(go, 0x1000, 0x0811);
+		go7007_write_addr(go, 0x1000, 0x0c11);
+	}
+	switch (go->board_id) {
+	case GO7007_BOARDID_MATRIX_REV:
+		/* Set GPIO pin 0 to be an output (audio clock control) */
+		go7007_write_addr(go, 0x3c82, 0x0001);
+		go7007_write_addr(go, 0x3c80, 0x00fe);
+		break;
+	case GO7007_BOARDID_ADLINK_MPG24:
+		/* set GPIO5 to be an output, currently low */
+		go7007_write_addr(go, 0x3c82, 0x0000);
+		go7007_write_addr(go, 0x3c80, 0x00df);
+		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		/* GPIO pin 0: audio clock control */
+		/*      pin 2: TW9906 reset */
+		/*      pin 3: capture LED */
+		go7007_write_addr(go, 0x3c82, 0x000d);
+		go7007_write_addr(go, 0x3c80, 0x00f2);
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Send the boot firmware to the GO7007 and configure the registers.  This
+ * is the only way to stop the encoder once it has started streaming video.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_reset_encoder(struct go7007 *go)
+{
+	if (go7007_load_encoder(go) < 0)
+		return -1;
+	return go7007_init_encoder(go);
+}
+
+/*
+ * Attempt to instantiate an I2C client by ID, probably loading a module.
+ */
+static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c)
+{
+	struct go7007 *go = i2c_get_adapdata(adapter);
+	struct v4l2_device *v4l2_dev = &go->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct i2c_board_info info;
+
+	memset(&info, 0, sizeof(info));
+	strlcpy(info.type, i2c->type, sizeof(info.type));
+	info.addr = i2c->addr;
+	info.flags = i2c->flags;
+
+	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL);
+	if (sd) {
+		if (i2c->is_video)
+			go->sd_video = sd;
+		if (i2c->is_audio)
+			go->sd_audio = sd;
+		return 0;
+	}
+
+	pr_info("go7007: probing for module i2c:%s failed\n", i2c->type);
+	return -EINVAL;
+}
+
+/*
+ * Detach and unregister the encoder.  The go7007 struct won't be freed
+ * until v4l2 finishes releasing its resources and all associated fds are
+ * closed by applications.
+ */
+static void go7007_remove(struct v4l2_device *v4l2_dev)
+{
+	struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev);
+
+	v4l2_device_unregister(v4l2_dev);
+	if (go->hpi_ops->release)
+		go->hpi_ops->release(go);
+	if (go->i2c_adapter_online) {
+		i2c_del_adapter(&go->i2c_adapter);
+		go->i2c_adapter_online = 0;
+	}
+
+	kfree(go->boot_fw);
+	go7007_v4l2_remove(go);
+	kfree(go);
+}
+
+/*
+ * Finalize the GO7007 hardware setup, register the on-board I2C adapter
+ * (if used on this board), load the I2C client driver for the sensor
+ * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2
+ * interfaces.
+ *
+ * Must NOT be called with the hw_lock held.
+ */
+int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
+{
+	int i, ret;
+
+	dev_info(go->dev, "go7007: registering new %s\n", go->name);
+
+	go->v4l2_dev.release = go7007_remove;
+	ret = v4l2_device_register(go->dev, &go->v4l2_dev);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&go->hw_lock);
+	ret = go7007_init_encoder(go);
+	mutex_unlock(&go->hw_lock);
+	if (ret < 0)
+		return ret;
+
+	ret = go7007_v4l2_ctrl_init(go);
+	if (ret < 0)
+		return ret;
+
+	if (!go->i2c_adapter_online &&
+			go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
+		ret = go7007_i2c_init(go);
+		if (ret < 0)
+			return ret;
+		go->i2c_adapter_online = 1;
+	}
+	if (go->i2c_adapter_online) {
+		if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
+			/* Reset the TW9906 */
+			go7007_write_addr(go, 0x3c82, 0x0009);
+			msleep(50);
+			go7007_write_addr(go, 0x3c82, 0x000d);
+		}
+		for (i = 0; i < num_i2c_devs; ++i)
+			init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]);
+
+		if (go->tuner_type >= 0) {
+			struct tuner_setup setup = {
+				.addr = ADDR_UNSET,
+				.type = go->tuner_type,
+				.mode_mask = T_ANALOG_TV,
+			};
+
+			v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
+				s_type_addr, &setup);
+		}
+		if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
+			v4l2_subdev_call(go->sd_video, video, s_routing,
+					0, 0, go->channel_number + 1);
+	}
+
+	ret = go7007_v4l2_init(go);
+	if (ret < 0)
+		return ret;
+
+	if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
+		go->audio_enabled = 1;
+		go7007_snd_init(go);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(go7007_register_encoder);
+
+/*
+ * Send the encode firmware to the encoder, which will cause it
+ * to immediately start delivering the video and audio streams.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_start_encoder(struct go7007 *go)
+{
+	u8 *fw;
+	int fw_len, rv = 0, i, x, y;
+	u16 intr_val, intr_data;
+
+	go->modet_enable = 0;
+	for (i = 0; i < 4; i++)
+		go->modet[i].enable = 0;
+
+	switch (v4l2_ctrl_g_ctrl(go->modet_mode)) {
+	case V4L2_DETECT_MD_MODE_GLOBAL:
+		memset(go->modet_map, 0, sizeof(go->modet_map));
+		go->modet[0].enable = 1;
+		go->modet_enable = 1;
+		break;
+	case V4L2_DETECT_MD_MODE_REGION_GRID:
+		for (y = 0; y < go->height / 16; y++) {
+			for (x = 0; x < go->width / 16; x++) {
+				int idx = y * go->width / 16 + x;
+
+				go->modet[go->modet_map[idx]].enable = 1;
+			}
+		}
+		go->modet_enable = 1;
+		break;
+	}
+
+	if (go->dvd_mode)
+		go->modet_enable = 0;
+
+	if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
+		return -1;
+
+	if (go7007_send_firmware(go, fw, fw_len) < 0 ||
+			go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
+		v4l2_err(&go->v4l2_dev, "error transferring firmware\n");
+		rv = -1;
+		goto start_error;
+	}
+
+	go->state = STATE_DATA;
+	go->parse_length = 0;
+	go->seen_frame = 0;
+	if (go7007_stream_start(go) < 0) {
+		v4l2_err(&go->v4l2_dev, "error starting stream transfer\n");
+		rv = -1;
+		goto start_error;
+	}
+
+start_error:
+	kfree(fw);
+	return rv;
+}
+
+/*
+ * Store a byte in the current video buffer, if there is one.
+ */
+static inline void store_byte(struct go7007_buffer *vb, u8 byte)
+{
+	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
+		u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+
+		ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
+	}
+}
+
+static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb,
+		u32 motion_regions)
+{
+	if (motion_regions != go->modet_event_status) {
+		struct v4l2_event ev = {
+			.type = V4L2_EVENT_MOTION_DET,
+			.u.motion_det = {
+				.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+				.frame_sequence = vb->vb.v4l2_buf.sequence,
+				.region_mask = motion_regions,
+			},
+		};
+
+		v4l2_event_queue(&go->vdev, &ev);
+		go->modet_event_status = motion_regions;
+	}
+}
+
+/*
+ * Determine regions with motion and send a motion detection event
+ * in case of changes.
+ */
+static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
+{
+	u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+	unsigned motion[4] = { 0, 0, 0, 0 };
+	u32 motion_regions = 0;
+	unsigned stride = (go->width + 7) >> 3;
+	unsigned x, y;
+	int i;
+
+	for (i = 0; i < 216; ++i)
+		store_byte(vb, go->active_map[i]);
+	for (y = 0; y < go->height / 16; y++) {
+		for (x = 0; x < go->width / 16; x++) {
+			if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7))))
+				continue;
+			motion[go->modet_map[y * (go->width / 16) + x]]++;
+		}
+	}
+	motion_regions = ((motion[0] > 0) << 0) |
+			 ((motion[1] > 0) << 1) |
+			 ((motion[2] > 0) << 2) |
+			 ((motion[3] > 0) << 3);
+	*bytesused -= 216;
+	go7007_set_motion_regions(go, vb, motion_regions);
+}
+
+/*
+ * Deliver the last video buffer and get a new one to start writing to.
+ */
+static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
+{
+	u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+	struct go7007_buffer *vb_tmp = NULL;
+
+	if (vb == NULL) {
+		spin_lock(&go->spinlock);
+		if (!list_empty(&go->vidq_active))
+			vb = go->active_buf =
+				list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+		spin_unlock(&go->spinlock);
+		go->next_seq++;
+		return vb;
+	}
+
+	vb->vb.v4l2_buf.sequence = go->next_seq++;
+	if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
+		go7007_motion_regions(go, vb);
+	else
+		go7007_set_motion_regions(go, vb, 0);
+
+	v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+	vb_tmp = vb;
+	spin_lock(&go->spinlock);
+	list_del(&vb->list);
+	if (list_empty(&go->vidq_active))
+		vb = NULL;
+	else
+		vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+	go->active_buf = vb;
+	spin_unlock(&go->spinlock);
+	vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+	return vb;
+}
+
+static void write_bitmap_word(struct go7007 *go)
+{
+	int x, y, i, stride = ((go->width >> 4) + 7) >> 3;
+
+	for (i = 0; i < 16; ++i) {
+		y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4);
+		x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4);
+		if (stride * y + (x >> 3) < sizeof(go->active_map))
+			go->active_map[stride * y + (x >> 3)] |=
+					(go->modet_word & 1) << (x & 0x7);
+		go->modet_word >>= 1;
+	}
+}
+
+/*
+ * Parse a chunk of the video stream into frames.  The frames are not
+ * delimited by the hardware, so we have to parse the frame boundaries
+ * based on the type of video stream we're receiving.
+ */
+void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
+{
+	struct go7007_buffer *vb = go->active_buf;
+	int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1;
+
+	switch (go->format) {
+	case V4L2_PIX_FMT_MPEG4:
+		seq_start_code = 0xB0;
+		gop_start_code = 0xB3;
+		frame_start_code = 0xB6;
+		break;
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+		seq_start_code = 0xB3;
+		gop_start_code = 0xB8;
+		frame_start_code = 0x00;
+		break;
+	}
+
+	for (i = 0; i < length; ++i) {
+		if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
+			v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
+			vb->vb.v4l2_planes[0].bytesused = 0;
+			vb->frame_offset = 0;
+			vb->modet_active = 0;
+			vb = go->active_buf = NULL;
+		}
+
+		switch (go->state) {
+		case STATE_DATA:
+			switch (buf[i]) {
+			case 0x00:
+				go->state = STATE_00;
+				break;
+			case 0xFF:
+				go->state = STATE_FF;
+				break;
+			default:
+				store_byte(vb, buf[i]);
+				break;
+			}
+			break;
+		case STATE_00:
+			switch (buf[i]) {
+			case 0x00:
+				go->state = STATE_00_00;
+				break;
+			case 0xFF:
+				store_byte(vb, 0x00);
+				go->state = STATE_FF;
+				break;
+			default:
+				store_byte(vb, 0x00);
+				store_byte(vb, buf[i]);
+				go->state = STATE_DATA;
+				break;
+			}
+			break;
+		case STATE_00_00:
+			switch (buf[i]) {
+			case 0x00:
+				store_byte(vb, 0x00);
+				/* go->state remains STATE_00_00 */
+				break;
+			case 0x01:
+				go->state = STATE_00_00_01;
+				break;
+			case 0xFF:
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				go->state = STATE_FF;
+				break;
+			default:
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, buf[i]);
+				go->state = STATE_DATA;
+				break;
+			}
+			break;
+		case STATE_00_00_01:
+			if (buf[i] == 0xF8 && go->modet_enable == 0) {
+				/* MODET start code, but MODET not enabled */
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
+				store_byte(vb, 0xF8);
+				go->state = STATE_DATA;
+				break;
+			}
+			/* If this is the start of a new MPEG frame,
+			 * get a new buffer */
+			if ((go->format == V4L2_PIX_FMT_MPEG1 ||
+			     go->format == V4L2_PIX_FMT_MPEG2 ||
+			     go->format == V4L2_PIX_FMT_MPEG4) &&
+			    (buf[i] == seq_start_code ||
+			     buf[i] == gop_start_code ||
+			     buf[i] == frame_start_code)) {
+				if (vb == NULL || go->seen_frame)
+					vb = frame_boundary(go, vb);
+				go->seen_frame = buf[i] == frame_start_code;
+				if (vb && go->seen_frame)
+					vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
+			}
+			/* Handle any special chunk types, or just write the
+			 * start code to the (potentially new) buffer */
+			switch (buf[i]) {
+			case 0xF5: /* timestamp */
+				go->parse_length = 12;
+				go->state = STATE_UNPARSED;
+				break;
+			case 0xF6: /* vbi */
+				go->state = STATE_VBI_LEN_A;
+				break;
+			case 0xF8: /* MD map */
+				go->parse_length = 0;
+				memset(go->active_map, 0,
+						sizeof(go->active_map));
+				go->state = STATE_MODET_MAP;
+				break;
+			case 0xFF: /* Potential JPEG start code */
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
+				go->state = STATE_FF;
+				break;
+			default:
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
+				store_byte(vb, buf[i]);
+				go->state = STATE_DATA;
+				break;
+			}
+			break;
+		case STATE_FF:
+			switch (buf[i]) {
+			case 0x00:
+				store_byte(vb, 0xFF);
+				go->state = STATE_00;
+				break;
+			case 0xFF:
+				store_byte(vb, 0xFF);
+				/* go->state remains STATE_FF */
+				break;
+			case 0xD8:
+				if (go->format == V4L2_PIX_FMT_MJPEG)
+					vb = frame_boundary(go, vb);
+				/* fall through */
+			default:
+				store_byte(vb, 0xFF);
+				store_byte(vb, buf[i]);
+				go->state = STATE_DATA;
+				break;
+			}
+			break;
+		case STATE_VBI_LEN_A:
+			go->parse_length = buf[i] << 8;
+			go->state = STATE_VBI_LEN_B;
+			break;
+		case STATE_VBI_LEN_B:
+			go->parse_length |= buf[i];
+			if (go->parse_length > 0)
+				go->state = STATE_UNPARSED;
+			else
+				go->state = STATE_DATA;
+			break;
+		case STATE_MODET_MAP:
+			if (go->parse_length < 204) {
+				if (go->parse_length & 1) {
+					go->modet_word |= buf[i];
+					write_bitmap_word(go);
+				} else
+					go->modet_word = buf[i] << 8;
+			} else if (go->parse_length == 207 && vb) {
+				vb->modet_active = buf[i];
+			}
+			if (++go->parse_length == 208)
+				go->state = STATE_DATA;
+			break;
+		case STATE_UNPARSED:
+			if (--go->parse_length == 0)
+				go->state = STATE_DATA;
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL(go7007_parse_video_stream);
+
+/*
+ * Allocate a new go7007 struct.  Used by the hardware-specific probe.
+ */
+struct go7007 *go7007_alloc(const struct go7007_board_info *board,
+						struct device *dev)
+{
+	struct go7007 *go;
+	int i;
+
+	go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
+	if (go == NULL)
+		return NULL;
+	go->dev = dev;
+	go->board_info = board;
+	go->board_id = 0;
+	go->tuner_type = -1;
+	go->channel_number = 0;
+	go->name[0] = 0;
+	mutex_init(&go->hw_lock);
+	init_waitqueue_head(&go->frame_waitq);
+	spin_lock_init(&go->spinlock);
+	go->status = STATUS_INIT;
+	memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
+	go->i2c_adapter_online = 0;
+	go->interrupt_available = 0;
+	init_waitqueue_head(&go->interrupt_waitq);
+	go->input = 0;
+	go7007_update_board(go);
+	go->encoder_h_halve = 0;
+	go->encoder_v_halve = 0;
+	go->encoder_subsample = 0;
+	go->format = V4L2_PIX_FMT_MJPEG;
+	go->bitrate = 1500000;
+	go->fps_scale = 1;
+	go->pali = 0;
+	go->aspect_ratio = GO7007_RATIO_1_1;
+	go->gop_size = 0;
+	go->ipb = 0;
+	go->closed_gop = 0;
+	go->repeat_seqhead = 0;
+	go->seq_header_enable = 0;
+	go->gop_header_enable = 0;
+	go->dvd_mode = 0;
+	go->interlace_coding = 0;
+	for (i = 0; i < 4; ++i)
+		go->modet[i].enable = 0;
+	for (i = 0; i < 1624; ++i)
+		go->modet_map[i] = 0;
+	go->audio_deliver = NULL;
+	go->audio_enabled = 0;
+
+	return go;
+}
+EXPORT_SYMBOL(go7007_alloc);
+
+void go7007_update_board(struct go7007 *go)
+{
+	const struct go7007_board_info *board = go->board_info;
+
+	if (board->sensor_flags & GO7007_SENSOR_TV) {
+		go->standard = GO7007_STD_NTSC;
+		go->std = V4L2_STD_NTSC_M;
+		go->width = 720;
+		go->height = 480;
+		go->sensor_framerate = 30000;
+	} else {
+		go->standard = GO7007_STD_OTHER;
+		go->width = board->sensor_width;
+		go->height = board->sensor_height;
+		go->sensor_framerate = board->sensor_framerate;
+	}
+	go->encoder_v_offset = board->sensor_v_offset;
+	go->encoder_h_offset = board->sensor_h_offset;
+}
+EXPORT_SYMBOL(go7007_update_board);
+
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-fw.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-fw.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-fw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-fw.c	2014-09-28 21:31:57.000000000 -0400
@@ -0,0 +1,1628 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+/*
+ * This file contains code to generate a firmware image for the GO7007SB
+ * encoder.  Much of the firmware is read verbatim from a file, but some of
+ * it concerning bitrate control and other things that can be configured at
+ * run-time are generated dynamically.  Note that the format headers
+ * generated here do not affect the functioning of the encoder; they are
+ * merely parroted back to the host at the start of each frame.
+ */
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include "go7007-priv.h"
+
+#define GO7007_FW_NAME "/*(DEBLOBBED)*/"
+
+/* Constants used in the source firmware image to describe code segments */
+
+#define	FLAG_MODE_MJPEG		(1)
+#define	FLAG_MODE_MPEG1		(1<<1)
+#define	FLAG_MODE_MPEG2		(1<<2)
+#define	FLAG_MODE_MPEG4		(1<<3)
+#define	FLAG_MODE_H263		(1<<4)
+#define FLAG_MODE_ALL		(FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \
+					FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \
+					FLAG_MODE_H263)
+#define FLAG_SPECIAL		(1<<8)
+
+#define SPECIAL_FRM_HEAD	0
+#define SPECIAL_BRC_CTRL	1
+#define SPECIAL_CONFIG		2
+#define SPECIAL_SEQHEAD		3
+#define SPECIAL_AV_SYNC		4
+#define SPECIAL_FINAL		5
+#define SPECIAL_AUDIO		6
+#define SPECIAL_MODET		7
+
+/* Little data class for creating MPEG headers bit-by-bit */
+
+struct code_gen {
+	unsigned char *p; /* destination */
+	u32 a; /* collects bits at the top of the variable */
+	int b; /* bit position of most recently-written bit */
+	int len; /* written out so far */
+};
+
+#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 }
+
+#define CODE_ADD(name, val, length) do { \
+	name.b -= (length); \
+	name.a |= (val) << name.b; \
+	while (name.b <= 24) { \
+		*name.p = name.a >> 24; \
+		++name.p; \
+		name.a <<= 8; \
+		name.b += 8; \
+		name.len += 8; \
+	} \
+} while (0)
+
+#define CODE_LENGTH(name) (name.len + (32 - name.b))
+
+/* Tables for creating the bitrate control data */
+
+static const s16 converge_speed_ip[101] = {
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+	5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
+	9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
+	19, 20, 22, 23, 25, 27, 30, 32, 35, 38,
+	41, 45, 49, 53, 58, 63, 69, 76, 83, 91,
+	100
+};
+
+static const s16 converge_speed_ipb[101] = {
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
+	6, 6, 6, 7, 7, 7, 7, 8, 8, 9,
+	9, 9, 10, 10, 11, 12, 12, 13, 14, 14,
+	15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
+	28, 30, 32, 34, 37, 40, 42, 46, 49, 53,
+	57, 61, 66, 71, 77, 83, 90, 97, 106, 115,
+	125, 135, 147, 161, 175, 191, 209, 228, 249, 273,
+	300
+};
+
+static const s16 LAMBDA_table[4][101] = {
+	{	16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
+		19, 19, 19, 20, 20, 20, 21, 21, 22, 22,
+		22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
+		27, 27, 28, 28, 29, 29, 30, 31, 31, 32,
+		32, 33, 33, 34, 35, 35, 36, 37, 37, 38,
+		39, 39, 40, 41, 42, 42, 43, 44, 45, 46,
+		46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+		67, 68, 69, 70, 72, 73, 74, 76, 77, 78,
+		80, 81, 83, 84, 86, 87, 89, 90, 92, 94,
+		96
+	},
+	{
+		20, 20, 20, 21, 21, 21, 22, 22, 23, 23,
+		23, 24, 24, 25, 25, 26, 26, 27, 27, 28,
+		28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
+		34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
+		40, 41, 42, 43, 43, 44, 45, 46, 47, 48,
+		48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+		58, 59, 60, 61, 62, 64, 65, 66, 67, 68,
+		70, 71, 72, 73, 75, 76, 78, 79, 80, 82,
+		83, 85, 86, 88, 90, 91, 93, 95, 96, 98,
+		100, 102, 103, 105, 107, 109, 111, 113, 115, 117,
+		120
+	},
+	{
+		24, 24, 24, 25, 25, 26, 26, 27, 27, 28,
+		28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
+		34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
+		41, 41, 42, 43, 44, 44, 45, 46, 47, 48,
+		49, 50, 50, 51, 52, 53, 54, 55, 56, 57,
+		58, 59, 60, 62, 63, 64, 65, 66, 67, 69,
+		70, 71, 72, 74, 75, 76, 78, 79, 81, 82,
+		84, 85, 87, 88, 90, 92, 93, 95, 97, 98,
+		100, 102, 104, 106, 108, 110, 112, 114, 116, 118,
+		120, 122, 124, 127, 129, 131, 134, 136, 138, 141,
+		144
+	},
+	{
+		32, 32, 33, 33, 34, 34, 35, 36, 36, 37,
+		38, 38, 39, 40, 41, 41, 42, 43, 44, 44,
+		45, 46, 47, 48, 49, 50, 50, 51, 52, 53,
+		54, 55, 56, 57, 58, 59, 60, 62, 63, 64,
+		65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
+		78, 79, 81, 82, 84, 85, 87, 88, 90, 92,
+		93, 95, 97, 98, 100, 102, 104, 106, 108, 110,
+		112, 114, 116, 118, 120, 122, 124, 127, 129, 131,
+		134, 136, 139, 141, 144, 146, 149, 152, 154, 157,
+		160, 163, 166, 169, 172, 175, 178, 181, 185, 188,
+		192
+	}
+};
+
+/* MPEG blank frame generation tables */
+
+enum mpeg_frame_type {
+	PFRAME,
+	BFRAME_PRE,
+	BFRAME_POST,
+	BFRAME_BIDIR,
+	BFRAME_EMPTY
+};
+
+static const u32 addrinctab[33][2] = {
+	{ 0x01, 1 },	{ 0x03, 3 },	{ 0x02, 3 },	{ 0x03, 4 },
+	{ 0x02, 4 },	{ 0x03, 5 },	{ 0x02, 5 },	{ 0x07, 7 },
+	{ 0x06, 7 },	{ 0x0b, 8 },	{ 0x0a, 8 },	{ 0x09, 8 },
+	{ 0x08, 8 },	{ 0x07, 8 },	{ 0x06, 8 },	{ 0x17, 10 },
+	{ 0x16, 10 },	{ 0x15, 10 },	{ 0x14, 10 },	{ 0x13, 10 },
+	{ 0x12, 10 },	{ 0x23, 11 },	{ 0x22, 11 },	{ 0x21, 11 },
+	{ 0x20, 11 },	{ 0x1f, 11 },	{ 0x1e, 11 },	{ 0x1d, 11 },
+	{ 0x1c, 11 },	{ 0x1b, 11 },	{ 0x1a, 11 },	{ 0x19, 11 },
+	{ 0x18, 11 }
+};
+
+/* Standard JPEG tables */
+
+static const u8 default_intra_quant_table[] = {
+	 8, 16, 19, 22, 26, 27, 29, 34,
+	16, 16, 22, 24, 27, 29, 34, 37,
+	19, 22, 26, 27, 29, 34, 34, 38,
+	22, 22, 26, 27, 29, 34, 37, 40,
+	22, 26, 27, 29, 32, 35, 40, 48,
+	26, 27, 29, 32, 35, 40, 48, 58,
+	26, 27, 29, 34, 38, 46, 56, 69,
+	27, 29, 35, 38, 46, 56, 69, 83
+};
+
+static const u8 bits_dc_luminance[] = {
+	0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 val_dc_luminance[] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 bits_dc_chrominance[] = {
+	0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+};
+
+static const u8 val_dc_chrominance[] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 bits_ac_luminance[] = {
+	0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+static const u8 val_ac_luminance[] = {
+	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xf9, 0xfa
+};
+
+static const u8 bits_ac_chrominance[] = {
+	0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+};
+
+static const u8 val_ac_chrominance[] = {
+	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xf9, 0xfa
+};
+
+/* Zig-zag mapping for quant table
+ *
+ * OK, let's do this mapping on the actual table above so it doesn't have
+ * to be done on the fly.
+ */
+static const int zz[64] = {
+	0,   1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5,
+	12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28,
+	35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+	58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space)
+{
+	int i, cnt = pkg_cnt * 32;
+
+	if (space < cnt)
+		return -1;
+
+	for (i = 0; i < cnt; ++i)
+		dest[i] = cpu_to_le16p(src + i);
+
+	return cnt;
+}
+
+static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q)
+{
+	int i, p = 0;
+
+	buf[p++] = 0xff;
+	buf[p++] = 0xd8;
+	buf[p++] = 0xff;
+	buf[p++] = 0xdb;
+	buf[p++] = 0;
+	buf[p++] = 2 + 65;
+	buf[p++] = 0;
+	buf[p++] = default_intra_quant_table[0];
+	for (i = 1; i < 64; ++i)
+		/* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */
+		buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3;
+	buf[p++] = 0xff;
+	buf[p++] = 0xc0;
+	buf[p++] = 0;
+	buf[p++] = 17;
+	buf[p++] = 8;
+	buf[p++] = go->height >> 8;
+	buf[p++] = go->height & 0xff;
+	buf[p++] = go->width >> 8;
+	buf[p++] = go->width & 0xff;
+	buf[p++] = 3;
+	buf[p++] = 1;
+	buf[p++] = 0x22;
+	buf[p++] = 0;
+	buf[p++] = 2;
+	buf[p++] = 0x11;
+	buf[p++] = 0;
+	buf[p++] = 3;
+	buf[p++] = 0x11;
+	buf[p++] = 0;
+	buf[p++] = 0xff;
+	buf[p++] = 0xc4;
+	buf[p++] = 418 >> 8;
+	buf[p++] = 418 & 0xff;
+	buf[p++] = 0x00;
+	memcpy(buf + p, bits_dc_luminance + 1, 16);
+	p += 16;
+	memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance));
+	p += sizeof(val_dc_luminance);
+	buf[p++] = 0x01;
+	memcpy(buf + p, bits_dc_chrominance + 1, 16);
+	p += 16;
+	memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance));
+	p += sizeof(val_dc_chrominance);
+	buf[p++] = 0x10;
+	memcpy(buf + p, bits_ac_luminance + 1, 16);
+	p += 16;
+	memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance));
+	p += sizeof(val_ac_luminance);
+	buf[p++] = 0x11;
+	memcpy(buf + p, bits_ac_chrominance + 1, 16);
+	p += 16;
+	memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance));
+	p += sizeof(val_ac_chrominance);
+	buf[p++] = 0xff;
+	buf[p++] = 0xda;
+	buf[p++] = 0;
+	buf[p++] = 12;
+	buf[p++] = 3;
+	buf[p++] = 1;
+	buf[p++] = 0x00;
+	buf[p++] = 2;
+	buf[p++] = 0x11;
+	buf[p++] = 3;
+	buf[p++] = 0x11;
+	buf[p++] = 0;
+	buf[p++] = 63;
+	buf[p++] = 0;
+	return p;
+}
+
+static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
+{
+	u8 *buf;
+	u16 mem = 0x3e00;
+	unsigned int addr = 0x19;
+	int size = 0, i, off = 0, chunk;
+
+	buf = kzalloc(4096, GFP_KERNEL);
+	if (buf == NULL)
+		return -1;
+
+	for (i = 1; i < 32; ++i) {
+		mjpeg_frame_header(go, buf + size, i);
+		size += 80;
+	}
+	chunk = mjpeg_frame_header(go, buf + size, 1);
+	memmove(buf + size, buf + size + 80, chunk - 80);
+	size += chunk - 80;
+
+	for (i = 0; i < size; i += chunk * 2) {
+		if (space - off < 32) {
+			off = -1;
+			goto done;
+		}
+
+		code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+		chunk = 28;
+		if (mem + chunk > 0x4000)
+			chunk = 0x4000 - mem;
+		if (i + 2 * chunk > size)
+			chunk = (size - i) / 2;
+
+		if (chunk < 28) {
+			code[off] = __cpu_to_le16(0x4000 | chunk);
+			code[off + 31] = __cpu_to_le16(addr++);
+			mem = 0x3e00;
+		} else {
+			code[off] = __cpu_to_le16(0x1000 | 28);
+			code[off + 31] = 0;
+			mem += 28;
+		}
+
+		memcpy(&code[off + 2], buf + i, chunk * 2);
+		off += 32;
+	}
+done:
+	kfree(buf);
+	return off;
+}
+
+static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
+		int modulo, int pict_struct, enum mpeg_frame_type frame)
+{
+	int i, j, mb_code, mb_len;
+	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+	CODE_GEN(c, buf + 6);
+
+	switch (frame) {
+	case PFRAME:
+		mb_code = 0x1;
+		mb_len = 3;
+		break;
+	case BFRAME_PRE:
+		mb_code = 0x2;
+		mb_len = 4;
+		break;
+	case BFRAME_POST:
+		mb_code = 0x2;
+		mb_len = 3;
+		break;
+	case BFRAME_BIDIR:
+		mb_code = 0x2;
+		mb_len = 2;
+		break;
+	default: /* keep the compiler happy */
+		mb_code = mb_len = 0;
+		break;
+	}
+
+	CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13);
+	CODE_ADD(c, 0xffff, 16);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
+	if (frame != PFRAME)
+		CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
+	else
+		CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */
+	CODE_ADD(c, 0, 3); /* What is this?? */
+	/* Byte-align with zeros */
+	j = 8 - (CODE_LENGTH(c) % 8);
+	if (j != 8)
+		CODE_ADD(c, 0, j);
+
+	if (go->format == V4L2_PIX_FMT_MPEG2) {
+		CODE_ADD(c, 0x1, 24);
+		CODE_ADD(c, 0xb5, 8);
+		CODE_ADD(c, 0x844, 12);
+		CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8);
+		if (go->interlace_coding) {
+			CODE_ADD(c, pict_struct, 4);
+			if (go->dvd_mode)
+				CODE_ADD(c, 0x000, 11);
+			else
+				CODE_ADD(c, 0x200, 11);
+		} else {
+			CODE_ADD(c, 0x3, 4);
+			CODE_ADD(c, 0x20c, 11);
+		}
+		/* Byte-align with zeros */
+		j = 8 - (CODE_LENGTH(c) % 8);
+		if (j != 8)
+			CODE_ADD(c, 0, j);
+	}
+
+	for (i = 0; i < rows; ++i) {
+		CODE_ADD(c, 1, 24);
+		CODE_ADD(c, i + 1, 8);
+		CODE_ADD(c, 0x2, 6);
+		CODE_ADD(c, 0x1, 1);
+		CODE_ADD(c, mb_code, mb_len);
+		if (go->interlace_coding) {
+			CODE_ADD(c, 0x1, 2);
+			CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+		}
+		if (frame == BFRAME_BIDIR) {
+			CODE_ADD(c, 0x3, 2);
+			if (go->interlace_coding)
+				CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+		}
+		CODE_ADD(c, 0x3, 2);
+		for (j = (go->width >> 4) - 2; j >= 33; j -= 33)
+			CODE_ADD(c, 0x8, 11);
+		CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]);
+		CODE_ADD(c, mb_code, mb_len);
+		if (go->interlace_coding) {
+			CODE_ADD(c, 0x1, 2);
+			CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+		}
+		if (frame == BFRAME_BIDIR) {
+			CODE_ADD(c, 0x3, 2);
+			if (go->interlace_coding)
+				CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+		}
+		CODE_ADD(c, 0x3, 2);
+
+		/* Byte-align with zeros */
+		j = 8 - (CODE_LENGTH(c) % 8);
+		if (j != 8)
+			CODE_ADD(c, 0, j);
+	}
+
+	i = CODE_LENGTH(c) + 4 * 8;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+	buf[4] = 0x01;
+	buf[5] = 0x00;
+	return i;
+}
+
+static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
+{
+	int i, aspect_ratio, picture_rate;
+	CODE_GEN(c, buf + 6);
+
+	if (go->format == V4L2_PIX_FMT_MPEG1) {
+		switch (go->aspect_ratio) {
+		case GO7007_RATIO_4_3:
+			aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
+			break;
+		case GO7007_RATIO_16_9:
+			aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
+			break;
+		default:
+			aspect_ratio = 1;
+			break;
+		}
+	} else {
+		switch (go->aspect_ratio) {
+		case GO7007_RATIO_4_3:
+			aspect_ratio = 2;
+			break;
+		case GO7007_RATIO_16_9:
+			aspect_ratio = 3;
+			break;
+		default:
+			aspect_ratio = 1;
+			break;
+		}
+	}
+	switch (go->sensor_framerate) {
+	case 24000:
+		picture_rate = 1;
+		break;
+	case 24024:
+		picture_rate = 2;
+		break;
+	case 25025:
+		picture_rate = go->interlace_coding ? 6 : 3;
+		break;
+	case 30000:
+		picture_rate = go->interlace_coding ? 7 : 4;
+		break;
+	case 30030:
+		picture_rate = go->interlace_coding ? 8 : 5;
+		break;
+	default:
+		picture_rate = 5; /* 30 fps seems like a reasonable default */
+		break;
+	}
+
+	CODE_ADD(c, go->width, 12);
+	CODE_ADD(c, go->height, 12);
+	CODE_ADD(c, aspect_ratio, 4);
+	CODE_ADD(c, picture_rate, 4);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18);
+	CODE_ADD(c, 1, 1);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10);
+	CODE_ADD(c, 0, 3);
+
+	/* Byte-align with zeros */
+	i = 8 - (CODE_LENGTH(c) % 8);
+	if (i != 8)
+		CODE_ADD(c, 0, i);
+
+	if (go->format == V4L2_PIX_FMT_MPEG2) {
+		CODE_ADD(c, 0x1, 24);
+		CODE_ADD(c, 0xb5, 8);
+		CODE_ADD(c, 0x148, 12);
+		if (go->interlace_coding)
+			CODE_ADD(c, 0x20001, 20);
+		else
+			CODE_ADD(c, 0xa0001, 20);
+		CODE_ADD(c, 0, 16);
+
+		/* Byte-align with zeros */
+		i = 8 - (CODE_LENGTH(c) % 8);
+		if (i != 8)
+			CODE_ADD(c, 0, i);
+
+		if (ext) {
+			CODE_ADD(c, 0x1, 24);
+			CODE_ADD(c, 0xb52, 12);
+			CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3);
+			CODE_ADD(c, 0x105, 9);
+			CODE_ADD(c, 0x505, 16);
+			CODE_ADD(c, go->width, 14);
+			CODE_ADD(c, 1, 1);
+			CODE_ADD(c, go->height, 14);
+
+			/* Byte-align with zeros */
+			i = 8 - (CODE_LENGTH(c) % 8);
+			if (i != 8)
+				CODE_ADD(c, 0, i);
+		}
+	}
+
+	i = CODE_LENGTH(c) + 4 * 8;
+	buf[0] = i & 0xff;
+	buf[1] = i >> 8;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+	buf[4] = 0x01;
+	buf[5] = 0xb3;
+	return i;
+}
+
+static int gen_mpeg1hdr_to_package(struct go7007 *go,
+					__le16 *code, int space, int *framelen)
+{
+	u8 *buf;
+	u16 mem = 0x3e00;
+	unsigned int addr = 0x19;
+	int i, off = 0, chunk;
+
+	buf = kzalloc(5120, GFP_KERNEL);
+	if (buf == NULL)
+		return -1;
+
+	framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
+	if (go->interlace_coding)
+		framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8,
+							0, 2, PFRAME);
+	buf[0] = framelen[0] & 0xff;
+	buf[1] = framelen[0] >> 8;
+	i = 368;
+	framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE);
+	if (go->interlace_coding)
+		framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8,
+							0, 2, BFRAME_PRE);
+	buf[i] = framelen[1] & 0xff;
+	buf[i + 1] = framelen[1] >> 8;
+	i += 1632;
+	framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST);
+	if (go->interlace_coding)
+		framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8,
+							0, 2, BFRAME_POST);
+	buf[i] = framelen[2] & 0xff;
+	buf[i + 1] = framelen[2] >> 8;
+	i += 1432;
+	framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR);
+	if (go->interlace_coding)
+		framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8,
+							0, 2, BFRAME_BIDIR);
+	buf[i] = framelen[3] & 0xff;
+	buf[i + 1] = framelen[3] >> 8;
+	i += 1632 + 16;
+	mpeg1_sequence_header(go, buf + i, 0);
+	i += 40;
+	for (i = 0; i < 5120; i += chunk * 2) {
+		if (space - off < 32) {
+			off = -1;
+			goto done;
+		}
+
+		code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+		chunk = 28;
+		if (mem + chunk > 0x4000)
+			chunk = 0x4000 - mem;
+		if (i + 2 * chunk > 5120)
+			chunk = (5120 - i) / 2;
+
+		if (chunk < 28) {
+			code[off] = __cpu_to_le16(0x4000 | chunk);
+			code[off + 31] = __cpu_to_le16(addr);
+			if (mem + chunk == 0x4000) {
+				mem = 0x3e00;
+				++addr;
+			}
+		} else {
+			code[off] = __cpu_to_le16(0x1000 | 28);
+			code[off + 31] = 0;
+			mem += 28;
+		}
+
+		memcpy(&code[off + 2], buf + i, chunk * 2);
+		off += 32;
+	}
+done:
+	kfree(buf);
+	return off;
+}
+
+static int vti_bitlen(struct go7007 *go)
+{
+	unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale;
+
+	for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i)
+		;
+	return i + 1;
+}
+
+static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf,
+		int modulo, enum mpeg_frame_type frame)
+{
+	int i;
+	CODE_GEN(c, buf + 6);
+	int mb_count = (go->width >> 4) * (go->height >> 4);
+
+	CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2);
+	if (modulo)
+		CODE_ADD(c, 0x1, 1);
+	CODE_ADD(c, 0x1, 2);
+	CODE_ADD(c, 0, vti_bitlen(go));
+	CODE_ADD(c, 0x3, 2);
+	if (frame == PFRAME)
+		CODE_ADD(c, 0, 1);
+	CODE_ADD(c, 0xc, 11);
+	if (frame != PFRAME)
+		CODE_ADD(c, 0x4, 3);
+	if (frame != BFRAME_EMPTY) {
+		for (i = 0; i < mb_count; ++i) {
+			switch (frame) {
+			case PFRAME:
+				CODE_ADD(c, 0x1, 1);
+				break;
+			case BFRAME_PRE:
+				CODE_ADD(c, 0x47, 8);
+				break;
+			case BFRAME_POST:
+				CODE_ADD(c, 0x27, 7);
+				break;
+			case BFRAME_BIDIR:
+				CODE_ADD(c, 0x5f, 8);
+				break;
+			case BFRAME_EMPTY: /* keep compiler quiet */
+				break;
+			}
+		}
+	}
+
+	/* Byte-align with a zero followed by ones */
+	i = 8 - (CODE_LENGTH(c) % 8);
+	CODE_ADD(c, 0, 1);
+	CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
+
+	i = CODE_LENGTH(c) + 4 * 8;
+	buf[0] = i & 0xff;
+	buf[1] = i >> 8;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+	buf[4] = 0x01;
+	buf[5] = 0xb6;
+	return i;
+}
+
+static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
+{
+	const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali,
+		0x00, 0x00, 0x01, 0xb5, 0x09,
+		0x00, 0x00, 0x01, 0x00,
+		0x00, 0x00, 0x01, 0x20, };
+	int i, aspect_ratio;
+	int fps = go->sensor_framerate / go->fps_scale;
+	CODE_GEN(c, buf + 2 + sizeof(head));
+
+	switch (go->aspect_ratio) {
+	case GO7007_RATIO_4_3:
+		aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
+		break;
+	case GO7007_RATIO_16_9:
+		aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
+		break;
+	default:
+		aspect_ratio = 1;
+		break;
+	}
+
+	memcpy(buf + 2, head, sizeof(head));
+	CODE_ADD(c, 0x191, 17);
+	CODE_ADD(c, aspect_ratio, 4);
+	CODE_ADD(c, 0x1, 4);
+	CODE_ADD(c, fps, 16);
+	CODE_ADD(c, 0x3, 2);
+	CODE_ADD(c, 1001, vti_bitlen(go));
+	CODE_ADD(c, 1, 1);
+	CODE_ADD(c, go->width, 13);
+	CODE_ADD(c, 1, 1);
+	CODE_ADD(c, go->height, 13);
+	CODE_ADD(c, 0x2830, 14);
+
+	/* Byte-align */
+	i = 8 - (CODE_LENGTH(c) % 8);
+	CODE_ADD(c, 0, 1);
+	CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
+
+	i = CODE_LENGTH(c) + sizeof(head) * 8;
+	buf[0] = i & 0xff;
+	buf[1] = i >> 8;
+	return i;
+}
+
+static int gen_mpeg4hdr_to_package(struct go7007 *go,
+					__le16 *code, int space, int *framelen)
+{
+	u8 *buf;
+	u16 mem = 0x3e00;
+	unsigned int addr = 0x19;
+	int i, off = 0, chunk;
+
+	buf = kzalloc(5120, GFP_KERNEL);
+	if (buf == NULL)
+		return -1;
+
+	framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
+	i = 368;
+	framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE);
+	i += 1632;
+	framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST);
+	i += 1432;
+	framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR);
+	i += 1632;
+	mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY);
+	i += 16;
+	mpeg4_sequence_header(go, buf + i, 0);
+	i += 40;
+	for (i = 0; i < 5120; i += chunk * 2) {
+		if (space - off < 32) {
+			off = -1;
+			goto done;
+		}
+
+		code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+		chunk = 28;
+		if (mem + chunk > 0x4000)
+			chunk = 0x4000 - mem;
+		if (i + 2 * chunk > 5120)
+			chunk = (5120 - i) / 2;
+
+		if (chunk < 28) {
+			code[off] = __cpu_to_le16(0x4000 | chunk);
+			code[off + 31] = __cpu_to_le16(addr);
+			if (mem + chunk == 0x4000) {
+				mem = 0x3e00;
+				++addr;
+			}
+		} else {
+			code[off] = __cpu_to_le16(0x1000 | 28);
+			code[off + 31] = 0;
+			mem += 28;
+		}
+
+		memcpy(&code[off + 2], buf + i, chunk * 2);
+		off += 32;
+	}
+	mem = 0x3e00;
+	addr = go->ipb ? 0x14f9 : 0x0af9;
+	memset(buf, 0, 5120);
+	framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME);
+	i = 368;
+	framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE);
+	i += 1632;
+	framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST);
+	i += 1432;
+	framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR);
+	i += 1632;
+	mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY);
+	i += 16;
+	for (i = 0; i < 5120; i += chunk * 2) {
+		if (space - off < 32) {
+			off = -1;
+			goto done;
+		}
+
+		code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+		chunk = 28;
+		if (mem + chunk > 0x4000)
+			chunk = 0x4000 - mem;
+		if (i + 2 * chunk > 5120)
+			chunk = (5120 - i) / 2;
+
+		if (chunk < 28) {
+			code[off] = __cpu_to_le16(0x4000 | chunk);
+			code[off + 31] = __cpu_to_le16(addr);
+			if (mem + chunk == 0x4000) {
+				mem = 0x3e00;
+				++addr;
+			}
+		} else {
+			code[off] = __cpu_to_le16(0x1000 | 28);
+			code[off + 31] = 0;
+			mem += 28;
+		}
+
+		memcpy(&code[off + 2], buf + i, chunk * 2);
+		off += 32;
+	}
+done:
+	kfree(buf);
+	return off;
+}
+
+static int brctrl_to_package(struct go7007 *go,
+					__le16 *code, int space, int *framelen)
+{
+	int converge_speed = 0;
+	int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ?
+				100 : 0;
+	int peak_rate = 6 * go->bitrate / 5;
+	int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ?
+				go->bitrate :
+				(go->dvd_mode ? 900000 : peak_rate);
+	int fps = go->sensor_framerate / go->fps_scale;
+	int q = 0;
+	/* Bizarre math below depends on rounding errors in division */
+	u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps;
+	u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps;
+	u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000);
+	u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32);
+	u32 cplx[] = {
+		q > 0 ? sgop_expt_addr * q :
+			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+		q > 0 ? sgop_expt_addr * q :
+			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+		q > 0 ? sgop_expt_addr * q :
+			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+		q > 0 ? sgop_expt_addr * q :
+			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+	};
+	u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr;
+	u16 pack[] = {
+		0x200e,		0x0000,
+		0xBF20,		go->ipb ? converge_speed_ipb[converge_speed]
+					: converge_speed_ip[converge_speed],
+		0xBF21,		go->ipb ? 2 : 0,
+		0xBF22,		go->ipb ? LAMBDA_table[0][lambda / 2 + 50]
+					: 32767,
+		0xBF23,		go->ipb ? LAMBDA_table[1][lambda] : 32767,
+		0xBF24,		32767,
+		0xBF25,		lambda > 99 ? 32767 : LAMBDA_table[3][lambda],
+		0xBF26,		sgop_expt_addr & 0x0000FFFF,
+		0xBF27,		sgop_expt_addr >> 16,
+		0xBF28,		sgop_peak_addr & 0x0000FFFF,
+		0xBF29,		sgop_peak_addr >> 16,
+		0xBF2A,		vbv_alert_addr & 0x0000FFFF,
+		0xBF2B,		vbv_alert_addr >> 16,
+		0xBF2C,		0,
+		0xBF2D,		0,
+		0,		0,
+
+		0x200e,		0x0000,
+		0xBF2E,		vbv_alert_addr & 0x0000FFFF,
+		0xBF2F,		vbv_alert_addr >> 16,
+		0xBF30,		cplx[0] & 0x0000FFFF,
+		0xBF31,		cplx[0] >> 16,
+		0xBF32,		cplx[1] & 0x0000FFFF,
+		0xBF33,		cplx[1] >> 16,
+		0xBF34,		cplx[2] & 0x0000FFFF,
+		0xBF35,		cplx[2] >> 16,
+		0xBF36,		cplx[3] & 0x0000FFFF,
+		0xBF37,		cplx[3] >> 16,
+		0xBF38,		0,
+		0xBF39,		0,
+		0xBF3A,		total_expt_addr & 0x0000FFFF,
+		0xBF3B,		total_expt_addr >> 16,
+		0,		0,
+
+		0x200e,		0x0000,
+		0xBF3C,		total_expt_addr & 0x0000FFFF,
+		0xBF3D,		total_expt_addr >> 16,
+		0xBF3E,		0,
+		0xBF3F,		0,
+		0xBF48,		0,
+		0xBF49,		0,
+		0xBF4A,		calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q),
+		0xBF4B,		4,
+		0xBF4C,		0,
+		0xBF4D,		0,
+		0xBF4E,		0,
+		0xBF4F,		0,
+		0xBF50,		0,
+		0xBF51,		0,
+		0,		0,
+
+		0x200e,		0x0000,
+		0xBF40,		sgop_expt_addr & 0x0000FFFF,
+		0xBF41,		sgop_expt_addr >> 16,
+		0xBF42,		0,
+		0xBF43,		0,
+		0xBF44,		0,
+		0xBF45,		0,
+		0xBF46,		(go->width >> 4) * (go->height >> 4),
+		0xBF47,		0,
+		0xBF64,		0,
+		0xBF65,		0,
+		0xBF18,		framelen[4],
+		0xBF19,		framelen[5],
+		0xBF1A,		framelen[6],
+		0xBF1B,		framelen[7],
+		0,		0,
+
+#if 0
+		/* Remove once we don't care about matching */
+		0x200e,		0x0000,
+		0xBF56,		4,
+		0xBF57,		0,
+		0xBF58,		5,
+		0xBF59,		0,
+		0xBF5A,		6,
+		0xBF5B,		0,
+		0xBF5C,		8,
+		0xBF5D,		0,
+		0xBF5E,		1,
+		0xBF5F,		0,
+		0xBF60,		1,
+		0xBF61,		0,
+		0xBF62,		0,
+		0xBF63,		0,
+		0,		0,
+#else
+		0x2008,		0x0000,
+		0xBF56,		4,
+		0xBF57,		0,
+		0xBF58,		5,
+		0xBF59,		0,
+		0xBF5A,		6,
+		0xBF5B,		0,
+		0xBF5C,		8,
+		0xBF5D,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+#endif
+
+		0x200e,		0x0000,
+		0xBF10,		0,
+		0xBF11,		0,
+		0xBF12,		0,
+		0xBF13,		0,
+		0xBF14,		0,
+		0xBF15,		0,
+		0xBF16,		0,
+		0xBF17,		0,
+		0xBF7E,		0,
+		0xBF7F,		1,
+		0xBF52,		framelen[0],
+		0xBF53,		framelen[1],
+		0xBF54,		framelen[2],
+		0xBF55,		framelen[3],
+		0,		0,
+	};
+
+	return copy_packages(code, pack, 6, space);
+}
+
+static int config_package(struct go7007 *go, __le16 *code, int space)
+{
+	int fps = go->sensor_framerate / go->fps_scale / 1000;
+	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+	int brc_window_size = fps;
+	int q_min = 2, q_max = 31;
+	int THACCoeffSet0 = 0;
+	u16 pack[] = {
+		0x200e,		0x0000,
+		0xc002,		0x14b4,
+		0xc003,		0x28b4,
+		0xc004,		0x3c5a,
+		0xdc05,		0x2a77,
+		0xc6c3,		go->format == V4L2_PIX_FMT_MPEG4 ? 0 :
+				(go->format == V4L2_PIX_FMT_H263 ? 0 : 1),
+		0xc680,		go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 :
+				(go->format == V4L2_PIX_FMT_H263 ? 0x61 :
+									0xd3),
+		0xc780,		0x0140,
+		0xe009,		0x0001,
+		0xc60f,		0x0008,
+		0xd4ff,		0x0002,
+		0xe403,		2340,
+		0xe406,		75,
+		0xd411,		0x0001,
+		0xd410,		0xa1d6,
+		0x0001,		0x2801,
+
+		0x200d,		0x0000,
+		0xe402,		0x018b,
+		0xe401,		0x8b01,
+		0xd472,		(go->board_info->sensor_flags &
+							GO7007_SENSOR_TV) &&
+						(!go->interlace_coding) ?
+					0x01b0 : 0x0170,
+		0xd475,		(go->board_info->sensor_flags &
+							GO7007_SENSOR_TV) &&
+						(!go->interlace_coding) ?
+					0x0008 : 0x0009,
+		0xc404,		go->interlace_coding ? 0x44 :
+				(go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 :
+				(go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 :
+				(go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 :
+				(go->format == V4L2_PIX_FMT_H263  ? 0x08 :
+								     0x20)))),
+		0xbf0a,		(go->format == V4L2_PIX_FMT_MPEG4 ? 8 :
+				(go->format == V4L2_PIX_FMT_MPEG1 ? 1 :
+				(go->format == V4L2_PIX_FMT_MPEG2 ? 2 :
+				(go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) |
+				((go->repeat_seqhead ? 1 : 0) << 6) |
+				((go->dvd_mode ? 1 : 0) << 9) |
+				((go->gop_header_enable ? 1 : 0) << 10),
+		0xbf0b,		0,
+		0xdd5a,		go->ipb ? 0x14 : 0x0a,
+		0xbf0c,		0,
+		0xbf0d,		0,
+		0xc683,		THACCoeffSet0,
+		0xc40a,		(go->width << 4) | rows,
+		0xe01a,		go->board_info->hpi_buffer_cap,
+		0,		0,
+		0,		0,
+
+		0x2008,		0,
+		0xe402,		0x88,
+		0xe401,		0x8f01,
+		0xbf6a,		0,
+		0xbf6b,		0,
+		0xbf6c,		0,
+		0xbf6d,		0,
+		0xbf6e,		0,
+		0xbf6f,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+
+		0x200e,		0,
+		0xbf66,		brc_window_size,
+		0xbf67,		0,
+		0xbf68,		q_min,
+		0xbf69,		q_max,
+		0xbfe0,		0,
+		0xbfe1,		0,
+		0xbfe2,		0,
+		0xbfe3,		go->ipb ? 3 : 1,
+		0xc031,		go->board_info->sensor_flags &
+					GO7007_SENSOR_VBI ? 1 : 0,
+		0xc01c,		0x1f,
+		0xdd8c,		0x15,
+		0xdd94,		0x15,
+		0xdd88,		go->ipb ? 0x1401 : 0x0a01,
+		0xdd90,		go->ipb ? 0x1401 : 0x0a01,
+		0,		0,
+
+		0x200e,		0,
+		0xbfe4,		0,
+		0xbfe5,		0,
+		0xbfe6,		0,
+		0xbfe7,		fps << 8,
+		0xbfe8,		0x3a00,
+		0xbfe9,		0,
+		0xbfea,		0,
+		0xbfeb,		0,
+		0xbfec,		(go->interlace_coding ? 1 << 15 : 0) |
+					(go->modet_enable ? 0xa : 0) |
+					(go->board_info->sensor_flags &
+						GO7007_SENSOR_VBI ? 1 : 0),
+		0xbfed,		0,
+		0xbfee,		0,
+		0xbfef,		0,
+		0xbff0,		go->board_info->sensor_flags &
+					GO7007_SENSOR_TV ? 0xf060 : 0xb060,
+		0xbff1,		0,
+		0,		0,
+	};
+
+	return copy_packages(code, pack, 5, space);
+}
+
+static int seqhead_to_package(struct go7007 *go, __le16 *code, int space,
+	int (*sequence_header_func)(struct go7007 *go,
+		unsigned char *buf, int ext))
+{
+	int vop_time_increment_bitlength = vti_bitlen(go);
+	int fps = go->sensor_framerate / go->fps_scale *
+					(go->interlace_coding ? 2 : 1);
+	unsigned char buf[40] = { };
+	int len = sequence_header_func(go, buf, 1);
+	u16 pack[] = {
+		0x2006,		0,
+		0xbf08,		fps,
+		0xbf09,		0,
+		0xbff2,		vop_time_increment_bitlength,
+		0xbff3,		(1 << vop_time_increment_bitlength) - 1,
+		0xbfe6,		0,
+		0xbfe7,		(fps / 1000) << 8,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+
+		0x2007,		0,
+		0xc800,		buf[2] << 8 | buf[3],
+		0xc801,		buf[4] << 8 | buf[5],
+		0xc802,		buf[6] << 8 | buf[7],
+		0xc803,		buf[8] << 8 | buf[9],
+		0xc406,		64,
+		0xc407,		len - 64,
+		0xc61b,		1,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+
+		0x200e,		0,
+		0xc808,		buf[10] << 8 | buf[11],
+		0xc809,		buf[12] << 8 | buf[13],
+		0xc80a,		buf[14] << 8 | buf[15],
+		0xc80b,		buf[16] << 8 | buf[17],
+		0xc80c,		buf[18] << 8 | buf[19],
+		0xc80d,		buf[20] << 8 | buf[21],
+		0xc80e,		buf[22] << 8 | buf[23],
+		0xc80f,		buf[24] << 8 | buf[25],
+		0xc810,		buf[26] << 8 | buf[27],
+		0xc811,		buf[28] << 8 | buf[29],
+		0xc812,		buf[30] << 8 | buf[31],
+		0xc813,		buf[32] << 8 | buf[33],
+		0xc814,		buf[34] << 8 | buf[35],
+		0xc815,		buf[36] << 8 | buf[37],
+		0,		0,
+		0,		0,
+		0,		0,
+	};
+
+	return copy_packages(code, pack, 3, space);
+}
+
+static int relative_prime(int big, int little)
+{
+	int remainder;
+
+	while (little != 0) {
+		remainder = big % little;
+		big = little;
+		little = remainder;
+	}
+	return big;
+}
+
+static int avsync_to_package(struct go7007 *go, __le16 *code, int space)
+{
+	int arate = go->board_info->audio_rate * 1001 * go->fps_scale;
+	int ratio = arate / go->sensor_framerate;
+	int adjratio = ratio * 215 / 100;
+	int rprime = relative_prime(go->sensor_framerate,
+					arate % go->sensor_framerate);
+	int f1 = (arate % go->sensor_framerate) / rprime;
+	int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime;
+	u16 pack[] = {
+		0x200e,		0,
+		0xbf98,		(u16)((-adjratio) & 0xffff),
+		0xbf99,		(u16)((-adjratio) >> 16),
+		0xbf92,		0,
+		0xbf93,		0,
+		0xbff4,		f1 > f2 ? f1 : f2,
+		0xbff5,		f1 < f2 ? f1 : f2,
+		0xbff6,		f1 < f2 ? ratio : ratio + 1,
+		0xbff7,		f1 > f2 ? ratio : ratio + 1,
+		0xbff8,		0,
+		0xbff9,		0,
+		0xbffa,		adjratio & 0xffff,
+		0xbffb,		adjratio >> 16,
+		0xbf94,		0,
+		0xbf95,		0,
+		0,		0,
+	};
+
+	return copy_packages(code, pack, 1, space);
+}
+
+static int final_package(struct go7007 *go, __le16 *code, int space)
+{
+	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+	u16 pack[] = {
+		0x8000,
+		0,
+		0,
+		0,
+		0,
+		0,
+		0,
+		2,
+		((go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
+						(!go->interlace_coding) ?
+					(1 << 14) | (1 << 9) : 0) |
+			((go->encoder_subsample ? 1 : 0) << 8) |
+			(go->board_info->sensor_flags &
+				GO7007_SENSOR_CONFIG_MASK),
+		((go->encoder_v_halve ? 1 : 0) << 14) |
+			(go->encoder_v_halve ? rows << 9 : rows << 8) |
+			(go->encoder_h_halve ? 1 << 6 : 0) |
+			(go->encoder_h_halve ? go->width >> 3 : go->width >> 4),
+		(1 << 15) | (go->encoder_v_offset << 6) |
+			(1 << 7) | (go->encoder_h_offset >> 2),
+		(1 << 6),
+		0,
+		0,
+		((go->fps_scale - 1) << 8) |
+			(go->board_info->sensor_flags & GO7007_SENSOR_TV ?
+						(1 << 7) : 0) |
+			0x41,
+		go->ipb ? 0xd4c : 0x36b,
+		(rows << 8) | (go->width >> 4),
+		go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0,
+		(1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) |
+			((go->closed_gop ? 1 : 0) << 12) |
+			((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) |
+		/*	(1 << 9) |   */
+			((go->ipb ? 3 : 0) << 7) |
+			((go->modet_enable ? 1 : 0) << 2) |
+			((go->dvd_mode ? 1 : 0) << 1) | 1,
+		(go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 :
+			(go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))),
+		go->ipb ? 0x1f15 : 0x1f0b,
+		go->ipb ? 0x0015 : 0x000b,
+		go->ipb ? 0xa800 : 0x5800,
+		0xffff,
+		0x0020 + 0x034b * 0,
+		0x0020 + 0x034b * 1,
+		0x0020 + 0x034b * 2,
+		0x0020 + 0x034b * 3,
+		0x0020 + 0x034b * 4,
+		0x0020 + 0x034b * 5,
+		go->ipb ? (go->gop_size / 3) : go->gop_size,
+		(go->height >> 4) * (go->width >> 4) * 110 / 100,
+	};
+
+	return copy_packages(code, pack, 1, space);
+}
+
+static int audio_to_package(struct go7007 *go, __le16 *code, int space)
+{
+	int clock_config = ((go->board_info->audio_flags &
+				GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) |
+			((go->board_info->audio_flags &
+				GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) |
+			(((go->board_info->audio_bclk_div / 4) - 1) << 4) |
+			(go->board_info->audio_main_div - 1);
+	u16 pack[] = {
+		0x200d,		0,
+		0x9002,		0,
+		0x9002,		0,
+		0x9031,		0,
+		0x9032,		0,
+		0x9033,		0,
+		0x9034,		0,
+		0x9035,		0,
+		0x9036,		0,
+		0x9037,		0,
+		0x9040,		0,
+		0x9000,		clock_config,
+		0x9001,		(go->board_info->audio_flags & 0xffff) |
+					(1 << 9),
+		0x9000,		((go->board_info->audio_flags &
+						GO7007_AUDIO_I2S_MASTER ?
+						1 : 0) << 10) |
+					clock_config,
+		0,		0,
+		0,		0,
+		0x2005,		0,
+		0x9041,		0,
+		0x9042,		256,
+		0x9043,		0,
+		0x9044,		16,
+		0x9045,		16,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+		0,		0,
+	};
+
+	return copy_packages(code, pack, 2, space);
+}
+
+static int modet_to_package(struct go7007 *go, __le16 *code, int space)
+{
+	bool has_modet0 = go->modet[0].enable;
+	bool has_modet1 = go->modet[1].enable;
+	bool has_modet2 = go->modet[2].enable;
+	bool has_modet3 = go->modet[3].enable;
+	int ret, mb, i, addr, cnt = 0;
+	u16 pack[32];
+	u16 thresholds[] = {
+		0x200e,		0,
+		0xbf82,		has_modet0 ? go->modet[0].pixel_threshold : 32767,
+		0xbf83,		has_modet1 ? go->modet[1].pixel_threshold : 32767,
+		0xbf84,		has_modet2 ? go->modet[2].pixel_threshold : 32767,
+		0xbf85,		has_modet3 ? go->modet[3].pixel_threshold : 32767,
+		0xbf86,		has_modet0 ? go->modet[0].motion_threshold : 32767,
+		0xbf87,		has_modet1 ? go->modet[1].motion_threshold : 32767,
+		0xbf88,		has_modet2 ? go->modet[2].motion_threshold : 32767,
+		0xbf89,		has_modet3 ? go->modet[3].motion_threshold : 32767,
+		0xbf8a,		has_modet0 ? go->modet[0].mb_threshold : 32767,
+		0xbf8b,		has_modet1 ? go->modet[1].mb_threshold : 32767,
+		0xbf8c,		has_modet2 ? go->modet[2].mb_threshold : 32767,
+		0xbf8d,		has_modet3 ? go->modet[3].mb_threshold : 32767,
+		0xbf8e,		0,
+		0xbf8f,		0,
+		0,		0,
+	};
+
+	ret = copy_packages(code, thresholds, 1, space);
+	if (ret < 0)
+		return -1;
+	cnt += ret;
+
+	addr = 0xbac0;
+	memset(pack, 0, 64);
+	i = 0;
+	for (mb = 0; mb < 1624; ++mb) {
+		pack[i * 2 + 3] <<= 2;
+		pack[i * 2 + 3] |= go->modet_map[mb];
+		if (mb % 8 != 7)
+			continue;
+		pack[i * 2 + 2] = addr++;
+		++i;
+		if (i == 10 || mb == 1623) {
+			pack[0] = 0x2000 | i;
+			ret = copy_packages(code + cnt, pack, 1, space - cnt);
+			if (ret < 0)
+				return -1;
+			cnt += ret;
+			i = 0;
+			memset(pack, 0, 64);
+		}
+		pack[i * 2 + 3] = 0;
+	}
+
+	memset(pack, 0, 64);
+	i = 0;
+	for (addr = 0xbb90; addr < 0xbbfa; ++addr) {
+		pack[i * 2 + 2] = addr;
+		pack[i * 2 + 3] = 0;
+		++i;
+		if (i == 10 || addr == 0xbbf9) {
+			pack[0] = 0x2000 | i;
+			ret = copy_packages(code + cnt, pack, 1, space - cnt);
+			if (ret < 0)
+				return -1;
+			cnt += ret;
+			i = 0;
+			memset(pack, 0, 64);
+		}
+	}
+	return cnt;
+}
+
+static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
+			int *framelen)
+{
+	switch (type) {
+	case SPECIAL_FRM_HEAD:
+		switch (go->format) {
+		case V4L2_PIX_FMT_MJPEG:
+			return gen_mjpeghdr_to_package(go, code, space);
+		case V4L2_PIX_FMT_MPEG1:
+		case V4L2_PIX_FMT_MPEG2:
+			return gen_mpeg1hdr_to_package(go, code, space,
+								framelen);
+		case V4L2_PIX_FMT_MPEG4:
+			return gen_mpeg4hdr_to_package(go, code, space,
+								framelen);
+		}
+	case SPECIAL_BRC_CTRL:
+		return brctrl_to_package(go, code, space, framelen);
+	case SPECIAL_CONFIG:
+		return config_package(go, code, space);
+	case SPECIAL_SEQHEAD:
+		switch (go->format) {
+		case V4L2_PIX_FMT_MPEG1:
+		case V4L2_PIX_FMT_MPEG2:
+			return seqhead_to_package(go, code, space,
+					mpeg1_sequence_header);
+		case V4L2_PIX_FMT_MPEG4:
+			return seqhead_to_package(go, code, space,
+					mpeg4_sequence_header);
+		default:
+			return 0;
+		}
+	case SPECIAL_AV_SYNC:
+		return avsync_to_package(go, code, space);
+	case SPECIAL_FINAL:
+		return final_package(go, code, space);
+	case SPECIAL_AUDIO:
+		return audio_to_package(go, code, space);
+	case SPECIAL_MODET:
+		return modet_to_package(go, code, space);
+	}
+	dev_err(go->dev,
+		"firmware file contains unsupported feature %04x\n", type);
+	return -1;
+}
+
+int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
+{
+	const struct firmware *fw_entry;
+	__le16 *code, *src;
+	int framelen[8] = { }; /* holds the lengths of empty frame templates */
+	int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags;
+	int mode_flag;
+	int ret;
+
+	switch (go->format) {
+	case V4L2_PIX_FMT_MJPEG:
+		mode_flag = FLAG_MODE_MJPEG;
+		break;
+	case V4L2_PIX_FMT_MPEG1:
+		mode_flag = FLAG_MODE_MPEG1;
+		break;
+	case V4L2_PIX_FMT_MPEG2:
+		mode_flag = FLAG_MODE_MPEG2;
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		mode_flag = FLAG_MODE_MPEG4;
+		break;
+	default:
+		return -1;
+	}
+	if (reject_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) {
+		dev_err(go->dev,
+			"unable to load firmware from file \"%s\"\n",
+			GO7007_FW_NAME);
+		return -1;
+	}
+	code = kzalloc(codespace * 2, GFP_KERNEL);
+	if (code == NULL)
+		goto fw_failed;
+
+	src = (__le16 *)fw_entry->data;
+	srclen = fw_entry->size / 2;
+	while (srclen >= 2) {
+		chunk_flags = __le16_to_cpu(src[0]);
+		chunk_len = __le16_to_cpu(src[1]);
+		if (chunk_len + 2 > srclen) {
+			dev_err(go->dev,
+				"firmware file \"%s\" appears to be corrupted\n",
+				GO7007_FW_NAME);
+			goto fw_failed;
+		}
+		if (chunk_flags & mode_flag) {
+			if (chunk_flags & FLAG_SPECIAL) {
+				ret = do_special(go, __le16_to_cpu(src[2]),
+					&code[i], codespace - i, framelen);
+				if (ret < 0) {
+					dev_err(go->dev,
+						"insufficient memory for firmware construction\n");
+					goto fw_failed;
+				}
+				i += ret;
+			} else {
+				if (codespace - i < chunk_len) {
+					dev_err(go->dev,
+						"insufficient memory for firmware construction\n");
+					goto fw_failed;
+				}
+				memcpy(&code[i], &src[2], chunk_len * 2);
+				i += chunk_len;
+			}
+		}
+		srclen -= chunk_len + 2;
+		src += chunk_len + 2;
+	}
+	release_firmware(fw_entry);
+	*fw = (u8 *)code;
+	*fwlen = i * 2;
+	return 0;
+
+fw_failed:
+	kfree(code);
+	release_firmware(fw_entry);
+	return -1;
+}
+
+/*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-i2c.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-i2c.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+
+#include "go7007-priv.h"
+
+/********************* Driver for on-board I2C adapter *********************/
+
+/* #define GO7007_I2C_DEBUG */
+
+#define SPI_I2C_ADDR_BASE		0x1400
+#define STATUS_REG_ADDR			(SPI_I2C_ADDR_BASE + 0x2)
+#define I2C_CTRL_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x6)
+#define I2C_DEV_UP_ADDR_REG_ADDR	(SPI_I2C_ADDR_BASE + 0x7)
+#define I2C_LO_ADDR_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x8)
+#define I2C_DATA_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x9)
+#define I2C_CLKFREQ_REG_ADDR		(SPI_I2C_ADDR_BASE + 0xa)
+
+#define I2C_STATE_MASK			0x0007
+#define I2C_READ_READY_MASK		0x0008
+
+/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs
+ * on the Adlink PCI-MPG24, so access is shared between all of them. */
+static DEFINE_MUTEX(adlink_mpg24_i2c_lock);
+
+static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
+		u16 command, int flags, u8 *data)
+{
+	int i, ret = -EIO;
+	u16 val;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -ENODEV;
+
+#ifdef GO7007_I2C_DEBUG
+	if (read)
+		dev_dbg(go->dev, "go7007-i2c: reading 0x%02x on 0x%02x\n",
+			command, addr);
+	else
+		dev_dbg(go->dev,
+			"go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n",
+			*data, command, addr);
+#endif
+
+	mutex_lock(&go->hw_lock);
+
+	if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
+		/* Bridge the I2C port on this GO7007 to the shared bus */
+		mutex_lock(&adlink_mpg24_i2c_lock);
+		go7007_write_addr(go, 0x3c82, 0x0020);
+	}
+
+	/* Wait for I2C adapter to be ready */
+	for (i = 0; i < 10; ++i) {
+		if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
+			goto i2c_done;
+		if (!(val & I2C_STATE_MASK))
+			break;
+		msleep(100);
+	}
+	if (i == 10) {
+		dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
+		goto i2c_done;
+	}
+
+	/* Set target register (command) */
+	go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags);
+	go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command);
+
+	/* If we're writing, send the data and target address and we're done */
+	if (!read) {
+		go7007_write_addr(go, I2C_DATA_REG_ADDR, *data);
+		go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
+					(addr << 9) | (command >> 8));
+		ret = 0;
+		goto i2c_done;
+	}
+
+	/* Otherwise, we're reading.  First clear i2c_rx_data_rdy. */
+	if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
+		goto i2c_done;
+
+	/* Send the target address plus read flag */
+	go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
+			(addr << 9) | 0x0100 | (command >> 8));
+
+	/* Wait for i2c_rx_data_rdy */
+	for (i = 0; i < 10; ++i) {
+		if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
+			goto i2c_done;
+		if (val & I2C_READ_READY_MASK)
+			break;
+		msleep(100);
+	}
+	if (i == 10) {
+		dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
+		goto i2c_done;
+	}
+
+	/* Retrieve the read byte */
+	if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
+		goto i2c_done;
+	*data = val;
+	ret = 0;
+
+i2c_done:
+	if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
+		/* Isolate the I2C port on this GO7007 from the shared bus */
+		go7007_write_addr(go, 0x3c82, 0x0000);
+		mutex_unlock(&adlink_mpg24_i2c_lock);
+	}
+	mutex_unlock(&go->hw_lock);
+	return ret;
+}
+
+static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+		unsigned short flags, char read_write,
+		u8 command, int size, union i2c_smbus_data *data)
+{
+	struct go7007 *go = i2c_get_adapdata(adapter);
+
+	if (size != I2C_SMBUS_BYTE_DATA)
+		return -EIO;
+	return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command,
+			flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte);
+}
+
+/* VERY LIMITED I2C master xfer function -- only needed because the
+ * SMBus functions only support 8-bit commands and the SAA7135 uses
+ * 16-bit commands.  The I2C interface on the GO7007, as limited as
+ * it is, does support this mode. */
+
+static int go7007_i2c_master_xfer(struct i2c_adapter *adapter,
+					struct i2c_msg msgs[], int num)
+{
+	struct go7007 *go = i2c_get_adapdata(adapter);
+	int i;
+
+	for (i = 0; i < num; ++i) {
+		/* We can only do two things here -- write three bytes, or
+		 * write two bytes and read one byte. */
+		if (msgs[i].len == 2) {
+			if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr ||
+					(msgs[i].flags & I2C_M_RD) ||
+					!(msgs[i + 1].flags & I2C_M_RD) ||
+					msgs[i + 1].len != 1)
+				return -EIO;
+			if (go7007_i2c_xfer(go, msgs[i].addr, 1,
+					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
+					0x01, &msgs[i + 1].buf[0]) < 0)
+				return -EIO;
+			++i;
+		} else if (msgs[i].len == 3) {
+			if (msgs[i].flags & I2C_M_RD)
+				return -EIO;
+			if (msgs[i].len != 3)
+				return -EIO;
+			if (go7007_i2c_xfer(go, msgs[i].addr, 0,
+					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
+					0x01, &msgs[i].buf[2]) < 0)
+				return -EIO;
+		} else
+			return -EIO;
+	}
+
+	return num;
+}
+
+static u32 go7007_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static struct i2c_algorithm go7007_algo = {
+	.smbus_xfer	= go7007_smbus_xfer,
+	.master_xfer	= go7007_i2c_master_xfer,
+	.functionality	= go7007_functionality,
+};
+
+static struct i2c_adapter go7007_adap_templ = {
+	.owner			= THIS_MODULE,
+	.name			= "WIS GO7007SB",
+	.algo			= &go7007_algo,
+};
+
+int go7007_i2c_init(struct go7007 *go)
+{
+	memcpy(&go->i2c_adapter, &go7007_adap_templ,
+			sizeof(go7007_adap_templ));
+	go->i2c_adapter.dev.parent = go->dev;
+	i2c_set_adapdata(&go->i2c_adapter, go);
+	if (i2c_add_adapter(&go->i2c_adapter) < 0) {
+		dev_err(go->dev,
+			"go7007-i2c: error: i2c_add_adapter failed\n");
+		return -1;
+	}
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-loader.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-loader.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-loader.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-loader.c	2014-09-28 21:31:59.000000000 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 Sensoray Company 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.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <cypress_firmware.h>
+
+struct fw_config {
+	u16 vendor;
+	u16 product;
+	const char * const fw_name1;
+	const char * const fw_name2;
+};
+
+static struct fw_config fw_configs[] = {
+	{ 0x1943, 0xa250, "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/" },
+	{ 0x093b, 0xa002, "/*(DEBLOBBED)*/", NULL },
+	{ 0x093b, 0xa004, "/*(DEBLOBBED)*/", NULL },
+	{ 0x0eb1, 0x6666, "/*(DEBLOBBED)*/", NULL },
+	{ 0x0eb1, 0x6668, "/*(DEBLOBBED)*/", NULL },
+	{ 0, 0, NULL, NULL }
+};
+/*(DEBLOBBED)*/
+
+static int go7007_loader_probe(struct usb_interface *interface,
+				const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	const struct firmware *fw;
+	u16 vendor, product;
+	const char *fw1, *fw2;
+	int ret;
+	int i;
+
+	usbdev = usb_get_dev(interface_to_usbdev(interface));
+	if (!usbdev)
+		goto failed2;
+
+	if (usbdev->descriptor.bNumConfigurations != 1) {
+		dev_err(&interface->dev, "can't handle multiple config\n");
+		goto failed2;
+	}
+
+	vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+	product = le16_to_cpu(usbdev->descriptor.idProduct);
+
+	for (i = 0; fw_configs[i].fw_name1; i++)
+		if (fw_configs[i].vendor == vendor &&
+		    fw_configs[i].product == product)
+			break;
+
+	/* Should never happen */
+	if (fw_configs[i].fw_name1 == NULL)
+		goto failed2;
+
+	fw1 = fw_configs[i].fw_name1;
+	fw2 = fw_configs[i].fw_name2;
+
+	dev_info(&interface->dev, "loading firmware %s\n", fw1);
+
+	if (reject_firmware(&fw, fw1, &usbdev->dev)) {
+		dev_err(&interface->dev,
+			"unable to load firmware from file \"%s\"\n", fw1);
+		goto failed2;
+	}
+	ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+	release_firmware(fw);
+	if (0 != ret) {
+		dev_err(&interface->dev, "loader download failed\n");
+		goto failed2;
+	}
+
+	if (fw2 == NULL)
+		return 0;
+
+	if (reject_firmware(&fw, fw2, &usbdev->dev)) {
+		dev_err(&interface->dev,
+			"unable to load firmware from file \"%s\"\n", fw2);
+		goto failed2;
+	}
+	ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+	release_firmware(fw);
+	if (0 != ret) {
+		dev_err(&interface->dev, "firmware download failed\n");
+		goto failed2;
+	}
+	return 0;
+
+failed2:
+	usb_put_dev(usbdev);
+	dev_err(&interface->dev, "probe failed\n");
+	return -ENODEV;
+}
+
+static void go7007_loader_disconnect(struct usb_interface *interface)
+{
+	dev_info(&interface->dev, "disconnect\n");
+	usb_put_dev(interface_to_usbdev(interface));
+	usb_set_intfdata(interface, NULL);
+}
+
+static const struct usb_device_id go7007_loader_ids[] = {
+	{ USB_DEVICE(0x1943, 0xa250) },
+	{ USB_DEVICE(0x093b, 0xa002) },
+	{ USB_DEVICE(0x093b, 0xa004) },
+	{ USB_DEVICE(0x0eb1, 0x6666) },
+	{ USB_DEVICE(0x0eb1, 0x6668) },
+	{}                          /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, go7007_loader_ids);
+
+static struct usb_driver go7007_loader_driver = {
+	.name		= "go7007-loader",
+	.probe		= go7007_loader_probe,
+	.disconnect	= go7007_loader_disconnect,
+	.id_table	= go7007_loader_ids,
+};
+
+module_usb_driver(go7007_loader_driver);
+
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("firmware loader for go7007-usb");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-priv.h linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-priv.h
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+/*
+ * This is the private include file for the go7007 driver.  It should not
+ * be included by anybody but the driver itself, and especially not by
+ * user-space applications.
+ */
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-core.h>
+
+struct go7007;
+
+/* IDs to activate board-specific support code */
+#define GO7007_BOARDID_MATRIX_II	0
+#define GO7007_BOARDID_MATRIX_RELOAD	1
+#define GO7007_BOARDID_STAR_TREK	2
+#define GO7007_BOARDID_PCI_VOYAGER	3
+#define GO7007_BOARDID_XMEN		4
+#define GO7007_BOARDID_XMEN_II		5
+#define GO7007_BOARDID_XMEN_III		6
+#define GO7007_BOARDID_MATRIX_REV	7
+#define GO7007_BOARDID_PX_M402U		8
+#define GO7007_BOARDID_PX_TV402U	9
+#define GO7007_BOARDID_LIFEVIEW_LR192	10 /* TV Walker Ultra */
+#define GO7007_BOARDID_ENDURA		11
+#define GO7007_BOARDID_ADLINK_MPG24	12
+#define GO7007_BOARDID_SENSORAY_2250	13 /* Sensoray 2250/2251 */
+#define GO7007_BOARDID_ADS_USBAV_709    14
+
+/* Various characteristics of each board */
+#define GO7007_BOARD_HAS_AUDIO		(1<<0)
+#define GO7007_BOARD_USE_ONBOARD_I2C	(1<<1)
+#define GO7007_BOARD_HAS_TUNER		(1<<2)
+
+/* Characteristics of sensor devices */
+#define GO7007_SENSOR_VALID_POLAR	(1<<0)
+#define GO7007_SENSOR_HREF_POLAR	(1<<1)
+#define GO7007_SENSOR_VREF_POLAR	(1<<2)
+#define GO7007_SENSOR_FIELD_ID_POLAR	(1<<3)
+#define GO7007_SENSOR_BIT_WIDTH		(1<<4)
+#define GO7007_SENSOR_VALID_ENABLE	(1<<5)
+#define GO7007_SENSOR_656		(1<<6)
+#define GO7007_SENSOR_CONFIG_MASK	0x7f
+#define GO7007_SENSOR_TV		(1<<7)
+#define GO7007_SENSOR_VBI		(1<<8)
+#define GO7007_SENSOR_SCALING		(1<<9)
+#define GO7007_SENSOR_SAA7115		(1<<10)
+
+/* Characteristics of audio sensor devices */
+#define GO7007_AUDIO_I2S_MODE_1		(1)
+#define GO7007_AUDIO_I2S_MODE_2		(2)
+#define GO7007_AUDIO_I2S_MODE_3		(3)
+#define GO7007_AUDIO_BCLK_POLAR		(1<<2)
+#define GO7007_AUDIO_WORD_14		(14<<4)
+#define GO7007_AUDIO_WORD_16		(16<<4)
+#define GO7007_AUDIO_ONE_CHANNEL	(1<<11)
+#define GO7007_AUDIO_I2S_MASTER		(1<<16)
+#define GO7007_AUDIO_OKI_MODE		(1<<17)
+
+#define GO7007_CID_CUSTOM_BASE		(V4L2_CID_DETECT_CLASS_BASE + 0x1000)
+#define V4L2_CID_PIXEL_THRESHOLD0	(GO7007_CID_CUSTOM_BASE+1)
+#define V4L2_CID_MOTION_THRESHOLD0	(GO7007_CID_CUSTOM_BASE+2)
+#define V4L2_CID_MB_THRESHOLD0		(GO7007_CID_CUSTOM_BASE+3)
+#define V4L2_CID_PIXEL_THRESHOLD1	(GO7007_CID_CUSTOM_BASE+4)
+#define V4L2_CID_MOTION_THRESHOLD1	(GO7007_CID_CUSTOM_BASE+5)
+#define V4L2_CID_MB_THRESHOLD1		(GO7007_CID_CUSTOM_BASE+6)
+#define V4L2_CID_PIXEL_THRESHOLD2	(GO7007_CID_CUSTOM_BASE+7)
+#define V4L2_CID_MOTION_THRESHOLD2	(GO7007_CID_CUSTOM_BASE+8)
+#define V4L2_CID_MB_THRESHOLD2		(GO7007_CID_CUSTOM_BASE+9)
+#define V4L2_CID_PIXEL_THRESHOLD3	(GO7007_CID_CUSTOM_BASE+10)
+#define V4L2_CID_MOTION_THRESHOLD3	(GO7007_CID_CUSTOM_BASE+11)
+#define V4L2_CID_MB_THRESHOLD3		(GO7007_CID_CUSTOM_BASE+12)
+
+struct go7007_board_info {
+	unsigned int flags;
+	int hpi_buffer_cap;
+	unsigned int sensor_flags;
+	int sensor_width;
+	int sensor_height;
+	int sensor_framerate;
+	int sensor_h_offset;
+	int sensor_v_offset;
+	unsigned int audio_flags;
+	int audio_rate;
+	int audio_bclk_div;
+	int audio_main_div;
+	int num_i2c_devs;
+	struct go_i2c {
+		const char *type;
+		unsigned int is_video:1;
+		unsigned int is_audio:1;
+		int addr;
+		u32 flags;
+	} i2c_devs[5];
+	int num_inputs;
+	struct {
+		int video_input;
+		int audio_index;
+		char *name;
+	} inputs[4];
+	int video_config;
+	int num_aud_inputs;
+	struct {
+		int audio_input;
+		char *name;
+	} aud_inputs[3];
+};
+
+struct go7007_hpi_ops {
+	int (*interface_reset)(struct go7007 *go);
+	int (*write_interrupt)(struct go7007 *go, int addr, int data);
+	int (*read_interrupt)(struct go7007 *go);
+	int (*stream_start)(struct go7007 *go);
+	int (*stream_stop)(struct go7007 *go);
+	int (*send_firmware)(struct go7007 *go, u8 *data, int len);
+	int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg);
+	void (*release)(struct go7007 *go);
+};
+
+/* The video buffer size must be a multiple of PAGE_SIZE */
+#define	GO7007_BUF_PAGES	(128 * 1024 / PAGE_SIZE)
+#define	GO7007_BUF_SIZE		(GO7007_BUF_PAGES << PAGE_SHIFT)
+
+struct go7007_buffer {
+	struct vb2_buffer vb;
+	struct list_head list;
+	unsigned int frame_offset;
+	u32 modet_active;
+};
+
+#define GO7007_RATIO_1_1	0
+#define GO7007_RATIO_4_3	1
+#define GO7007_RATIO_16_9	2
+
+enum go7007_parser_state {
+	STATE_DATA,
+	STATE_00,
+	STATE_00_00,
+	STATE_00_00_01,
+	STATE_FF,
+	STATE_VBI_LEN_A,
+	STATE_VBI_LEN_B,
+	STATE_MODET_MAP,
+	STATE_UNPARSED,
+};
+
+struct go7007 {
+	struct device *dev;
+	u8 bus_info[32];
+	const struct go7007_board_info *board_info;
+	unsigned int board_id;
+	int tuner_type;
+	int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */
+	char name[64];
+	struct video_device vdev;
+	void *boot_fw;
+	unsigned boot_fw_len;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *mpeg_video_encoding;
+	struct v4l2_ctrl *mpeg_video_gop_size;
+	struct v4l2_ctrl *mpeg_video_gop_closure;
+	struct v4l2_ctrl *mpeg_video_bitrate;
+	struct v4l2_ctrl *mpeg_video_aspect_ratio;
+	struct v4l2_ctrl *mpeg_video_b_frames;
+	struct v4l2_ctrl *mpeg_video_rep_seqheader;
+	struct v4l2_ctrl *modet_mode;
+	enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
+	spinlock_t spinlock;
+	struct mutex hw_lock;
+	struct mutex serialize_lock;
+	int audio_enabled;
+	struct v4l2_subdev *sd_video;
+	struct v4l2_subdev *sd_audio;
+	u8 usb_buf[16];
+
+	/* Video input */
+	int input;
+	int aud_input;
+	enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard;
+	v4l2_std_id std;
+	int sensor_framerate;
+	int width;
+	int height;
+	int encoder_h_offset;
+	int encoder_v_offset;
+	unsigned int encoder_h_halve:1;
+	unsigned int encoder_v_halve:1;
+	unsigned int encoder_subsample:1;
+
+	/* Encoder config */
+	u32 format;
+	int bitrate;
+	int fps_scale;
+	int pali;
+	int aspect_ratio;
+	int gop_size;
+	unsigned int ipb:1;
+	unsigned int closed_gop:1;
+	unsigned int repeat_seqhead:1;
+	unsigned int seq_header_enable:1;
+	unsigned int gop_header_enable:1;
+	unsigned int dvd_mode:1;
+	unsigned int interlace_coding:1;
+
+	/* Motion detection */
+	unsigned int modet_enable:1;
+	struct {
+		unsigned int enable:1;
+		int pixel_threshold;
+		int motion_threshold;
+		int mb_threshold;
+	} modet[4];
+	unsigned char modet_map[1624];
+	unsigned char active_map[216];
+	u32 modet_event_status;
+
+	/* Video streaming */
+	struct mutex queue_lock;
+	struct vb2_queue vidq;
+	enum go7007_parser_state state;
+	int parse_length;
+	u16 modet_word;
+	int seen_frame;
+	u32 next_seq;
+	struct list_head vidq_active;
+	wait_queue_head_t frame_waitq;
+	struct go7007_buffer *active_buf;
+
+	/* Audio streaming */
+	void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
+	void *snd_context;
+
+	/* I2C */
+	int i2c_adapter_online;
+	struct i2c_adapter i2c_adapter;
+
+	/* HPI driver */
+	struct go7007_hpi_ops *hpi_ops;
+	void *hpi_context;
+	int interrupt_available;
+	wait_queue_head_t interrupt_waitq;
+	unsigned short interrupt_value;
+	unsigned short interrupt_data;
+};
+
+static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct go7007, v4l2_dev);
+}
+
+/* All of these must be called with the hpi_lock mutex held! */
+#define go7007_interface_reset(go) \
+			((go)->hpi_ops->interface_reset(go))
+#define	go7007_write_interrupt(go, x, y) \
+			((go)->hpi_ops->write_interrupt)((go), (x), (y))
+#define go7007_stream_start(go) \
+			((go)->hpi_ops->stream_start(go))
+#define go7007_stream_stop(go) \
+			((go)->hpi_ops->stream_stop(go))
+#define	go7007_send_firmware(go, x, y) \
+			((go)->hpi_ops->send_firmware)((go), (x), (y))
+#define go7007_write_addr(go, x, y) \
+			((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y))
+
+/* go7007-driver.c */
+int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data);
+int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data);
+int go7007_boot_encoder(struct go7007 *go, int init_i2c);
+int go7007_reset_encoder(struct go7007 *go);
+int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs);
+int go7007_start_encoder(struct go7007 *go);
+void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length);
+struct go7007 *go7007_alloc(const struct go7007_board_info *board,
+					struct device *dev);
+void go7007_update_board(struct go7007 *go);
+
+/* go7007-fw.c */
+int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen);
+
+/* go7007-i2c.c */
+int go7007_i2c_init(struct go7007 *go);
+int go7007_i2c_remove(struct go7007 *go);
+
+/* go7007-v4l2.c */
+int go7007_v4l2_init(struct go7007 *go);
+int go7007_v4l2_ctrl_init(struct go7007 *go);
+void go7007_v4l2_remove(struct go7007 *go);
+
+/* snd-go7007.c */
+int go7007_snd_init(struct go7007 *go);
+int go7007_snd_remove(struct go7007 *go);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-usb.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-usb.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1345 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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/module.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <asm/byteorder.h>
+#include <media/saa7115.h>
+#include <media/tuner.h>
+#include <media/uda1342.h>
+
+#include "go7007-priv.h"
+
+static unsigned int assume_endura;
+module_param(assume_endura, int, 0644);
+MODULE_PARM_DESC(assume_endura,
+			"when probing fails, hardware is a Pelco Endura");
+
+/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
+
+#define	HPI_STATUS_ADDR	0xFFF4
+#define	INT_PARAM_ADDR	0xFFF6
+#define	INT_INDEX_ADDR	0xFFF8
+
+/*
+ * Pipes on EZ-USB interface:
+ *	0 snd - Control
+ *	0 rcv - Control
+ *	2 snd - Download firmware (control)
+ *	4 rcv - Read Interrupt (interrupt)
+ *	6 rcv - Read Video (bulk)
+ *	8 rcv - Read Audio (bulk)
+ */
+
+#define GO7007_USB_EZUSB		(1<<0)
+#define GO7007_USB_EZUSB_I2C		(1<<1)
+
+struct go7007_usb_board {
+	unsigned int flags;
+	struct go7007_board_info main_info;
+};
+
+struct go7007_usb {
+	const struct go7007_usb_board *board;
+	struct mutex i2c_lock;
+	struct usb_device *usbdev;
+	struct urb *video_urbs[8];
+	struct urb *audio_urbs[8];
+	struct urb *intr_urb;
+};
+
+/*********************** Product specification data ***********************/
+
+static const struct go7007_usb_board board_matrix_ii = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_VALID_ENABLE |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
+					GO7007_SENSOR_VBI |
+					GO7007_SENSOR_SCALING,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "saa7115",
+				.addr	= 0x20,
+				.is_video = 1,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 9,
+				.name		= "S-Video",
+			},
+		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
+	},
+};
+
+static const struct go7007_usb_board board_matrix_reload = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "saa7113",
+				.addr	= 0x25,
+				.is_video = 1,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 9,
+				.name		= "S-Video",
+			},
+		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
+	},
+};
+
+static const struct go7007_usb_board board_star_trek = {
+	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO, /* |
+					GO7007_BOARD_HAS_TUNER, */
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_VALID_ENABLE |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
+					GO7007_SENSOR_VBI |
+					GO7007_SENSOR_SCALING,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_WORD_16,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "saa7115",
+				.addr	= 0x20,
+				.is_video = 1,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+		/*	{
+		 *		.video_input	= 3,
+		 *		.audio_index	= AUDIO_TUNER,
+		 *		.name		= "Tuner",
+		 *	},
+		 */
+			{
+				.video_input	= 1,
+			/*	.audio_index	= AUDIO_EXTERN, */
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 8,
+			/*	.audio_index	= AUDIO_EXTERN, */
+				.name		= "S-Video",
+			},
+		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
+	},
+};
+
+static const struct go7007_usb_board board_px_tv402u = {
+	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_HAS_TUNER,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_VALID_ENABLE |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
+					GO7007_SENSOR_VBI |
+					GO7007_SENSOR_SCALING,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_WORD_16,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.num_i2c_devs	 = 5,
+		.i2c_devs	 = {
+			{
+				.type	= "saa7115",
+				.addr	= 0x20,
+				.is_video = 1,
+			},
+			{
+				.type	= "uda1342",
+				.addr	= 0x1a,
+				.is_audio = 1,
+			},
+			{
+				.type	= "tuner",
+				.addr	= 0x60,
+			},
+			{
+				.type	= "tuner",
+				.addr	= 0x43,
+			},
+			{
+				.type	= "sony-btf-mpx",
+				.addr	= 0x44,
+			},
+		},
+		.num_inputs	 = 3,
+		.inputs		 = {
+			{
+				.video_input	= 3,
+				.audio_index	= 0,
+				.name		= "Tuner",
+			},
+			{
+				.video_input	= 1,
+				.audio_index	= 1,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 8,
+				.audio_index	= 1,
+				.name		= "S-Video",
+			},
+		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
+		.num_aud_inputs	 = 2,
+		.aud_inputs	 = {
+			{
+				.audio_input	= UDA1342_IN2,
+				.name		= "Tuner",
+			},
+			{
+				.audio_input	= UDA1342_IN1,
+				.name		= "Line In",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_xmen = {
+	.flags		= 0,
+	.main_info	= {
+		.flags		  = GO7007_BOARD_USE_ONBOARD_I2C,
+		.hpi_buffer_cap   = 0,
+		.sensor_flags	  = GO7007_SENSOR_VREF_POLAR,
+		.sensor_width	  = 320,
+		.sensor_height	  = 240,
+		.sensor_framerate = 30030,
+		.audio_flags	  = GO7007_AUDIO_ONE_CHANNEL |
+					GO7007_AUDIO_I2S_MODE_3 |
+					GO7007_AUDIO_WORD_14 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_BCLK_POLAR |
+					GO7007_AUDIO_OKI_MODE,
+		.audio_rate	  = 8000,
+		.audio_bclk_div	  = 48,
+		.audio_main_div	  = 1,
+		.num_i2c_devs	  = 1,
+		.i2c_devs	  = {
+			{
+				.type	= "ov7640",
+				.addr	= 0x21,
+			},
+		},
+		.num_inputs	  = 1,
+		.inputs		  = {
+			{
+				.name		= "Camera",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_matrix_revolution = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "tw9903",
+				.is_video = 1,
+				.addr	= 0x44,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 2,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 8,
+				.name		= "S-Video",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_lifeview_lr192 = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_VALID_ENABLE |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI |
+					GO7007_SENSOR_SCALING,
+		.num_i2c_devs	 = 0,
+		.num_inputs	 = 1,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_endura = {
+	.flags		= 0,
+	.main_info	= {
+		.flags		 = 0,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 8000,
+		.audio_bclk_div	 = 48,
+		.audio_main_div	 = 8,
+		.hpi_buffer_cap  = 0,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV,
+		.sensor_h_offset = 8,
+		.num_i2c_devs	 = 0,
+		.num_inputs	 = 1,
+		.inputs		 = {
+			{
+				.name		= "Camera",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_adlink_mpg24 = {
+	.flags		= 0,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 0,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "tw2804",
+				.addr	= 0x00, /* yes, really */
+				.flags  = I2C_CLIENT_TEN,
+				.is_video = 1,
+			},
+		},
+		.num_inputs	 = 1,
+		.inputs		 = {
+			{
+				.name		= "Composite",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_sensoray_2250 = {
+	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+	.main_info	= {
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.flags		 = GO7007_BOARD_HAS_AUDIO,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "s2250",
+				.addr	= 0x43,
+				.is_video = 1,
+				.is_audio = 1,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 1,
+				.name		= "S-Video",
+			},
+		},
+		.num_aud_inputs	 = 3,
+		.aud_inputs	 = {
+			{
+				.audio_input	= 0,
+				.name		= "Line In",
+			},
+			{
+				.audio_input	= 1,
+				.name		= "Mic",
+			},
+			{
+				.audio_input	= 2,
+				.name		= "Mic Boost",
+			},
+		},
+	},
+};
+
+static const struct go7007_usb_board board_ads_usbav_709 = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "tw9906",
+				.is_video = 1,
+				.addr	= 0x44,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 10,
+				.name		= "S-Video",
+			},
+		},
+	},
+};
+
+static const struct usb_device_id go7007_usb_id_table[] = {
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+					USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x200,   /* Revision number of XMen */
+		.bcdDevice_hi	= 0x200,
+		.bInterfaceClass	= 255,
+		.bInterfaceSubClass	= 0,
+		.bInterfaceProtocol	= 255,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x202,   /* Revision number of Matrix II */
+		.bcdDevice_hi	= 0x202,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x204,   /* Revision number of Matrix */
+		.bcdDevice_hi	= 0x204,   /*     Reloaded */
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+					USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x205,   /* Revision number of XMen-II */
+		.bcdDevice_hi	= 0x205,
+		.bInterfaceClass	= 255,
+		.bInterfaceSubClass	= 0,
+		.bInterfaceProtocol	= 255,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_II,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x208,   /* Revision number of Star Trek */
+		.bcdDevice_hi	= 0x208,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_STAR_TREK,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+					USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x209,   /* Revision number of XMen-III */
+		.bcdDevice_hi	= 0x209,
+		.bInterfaceClass	= 255,
+		.bInterfaceSubClass	= 0,
+		.bInterfaceProtocol	= 255,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_III,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
+		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
+		.bcdDevice_lo	= 0x210,   /* Revision number of Matrix */
+		.bcdDevice_hi	= 0x210,   /*     Revolution */
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x093b,  /* Vendor ID of Plextor */
+		.idProduct	= 0xa102,  /* Product ID of M402U */
+		.bcdDevice_lo	= 0x1,	   /* revision number of Blueberry */
+		.bcdDevice_hi	= 0x1,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_M402U,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x093b,  /* Vendor ID of Plextor */
+		.idProduct	= 0xa104,  /* Product ID of TV402U */
+		.bcdDevice_lo	= 0x1,
+		.bcdDevice_hi	= 0x1,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x10fd,  /* Vendor ID of Anubis Electronics */
+		.idProduct	= 0xde00,  /* Product ID of Lifeview LR192 */
+		.bcdDevice_lo	= 0x1,
+		.bcdDevice_hi	= 0x1,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x1943,  /* Vendor ID Sensoray */
+		.idProduct	= 0x2250,  /* Product ID of 2250/2251 */
+		.bcdDevice_lo	= 0x1,
+		.bcdDevice_hi	= 0x1,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
+	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x06e1,  /* Vendor ID of ADS Technologies */
+		.idProduct	= 0x0709,  /* Product ID of DVD Xpress DX2 */
+		.bcdDevice_lo	= 0x204,
+		.bcdDevice_hi	= 0x204,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709,
+	},
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, go7007_usb_id_table);
+
+/********************* Driver for EZ-USB HPI interface *********************/
+
+static int go7007_usb_vendor_request(struct go7007 *go, int request,
+		int value, int index, void *transfer_buffer, int length, int in)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int timeout = 5000;
+
+	if (in) {
+		return usb_control_msg(usb->usbdev,
+				usb_rcvctrlpipe(usb->usbdev, 0), request,
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+				value, index, transfer_buffer, length, timeout);
+	} else {
+		return usb_control_msg(usb->usbdev,
+				usb_sndctrlpipe(usb->usbdev, 0), request,
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				value, index, transfer_buffer, length, timeout);
+	}
+}
+
+static int go7007_usb_interface_reset(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	u16 intr_val, intr_data;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -1;
+	/* Reset encoder */
+	if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
+		return -1;
+	msleep(100);
+
+	if (usb->board->flags & GO7007_USB_EZUSB) {
+		/* Reset buffer in EZ-USB */
+		pr_debug("resetting EZ-USB buffers\n");
+		if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
+		    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
+			return -1;
+
+		/* Reset encoder again */
+		if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
+			return -1;
+		msleep(100);
+	}
+
+	/* Wait for an interrupt to indicate successful hardware reset */
+	if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+			(intr_val & ~0x1) != 0x55aa) {
+		dev_err(go->dev, "unable to reset the USB interface\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
+						int addr, int data)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int i, r;
+	u16 status_reg = 0;
+	int timeout = 500;
+
+	pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
+
+	for (i = 0; i < 100; ++i) {
+		r = usb_control_msg(usb->usbdev,
+				usb_rcvctrlpipe(usb->usbdev, 0), 0x14,
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+				0, HPI_STATUS_ADDR, go->usb_buf,
+				sizeof(status_reg), timeout);
+		if (r < 0)
+			break;
+		status_reg = le16_to_cpu(*((u16 *)go->usb_buf));
+		if (!(status_reg & 0x0010))
+			break;
+		msleep(10);
+	}
+	if (r < 0)
+		goto write_int_error;
+	if (i == 100) {
+		dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg);
+		return -1;
+	}
+	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12,
+			USB_TYPE_VENDOR | USB_RECIP_DEVICE, data,
+			INT_PARAM_ADDR, NULL, 0, timeout);
+	if (r < 0)
+		goto write_int_error;
+	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0),
+			0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr,
+			INT_INDEX_ADDR, NULL, 0, timeout);
+	if (r < 0)
+		goto write_int_error;
+	return 0;
+
+write_int_error:
+	dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
+	return r;
+}
+
+static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
+						int addr, int data)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int r;
+	int timeout = 500;
+
+	pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
+
+	go->usb_buf[0] = data & 0xff;
+	go->usb_buf[1] = data >> 8;
+	go->usb_buf[2] = addr & 0xff;
+	go->usb_buf[3] = addr >> 8;
+	go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0;
+	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00,
+			USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
+			0xf0f0, go->usb_buf, 8, timeout);
+	if (r < 0) {
+		dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
+		return r;
+	}
+	return 0;
+}
+
+static void go7007_usb_readinterrupt_complete(struct urb *urb)
+{
+	struct go7007 *go = (struct go7007 *)urb->context;
+	u16 *regs = (u16 *)urb->transfer_buffer;
+	int status = urb->status;
+
+	if (status) {
+		if (status != -ESHUTDOWN &&
+				go->status != STATUS_SHUTDOWN) {
+			dev_err(go->dev, "error in read interrupt: %d\n", urb->status);
+		} else {
+			wake_up(&go->interrupt_waitq);
+			return;
+		}
+	} else if (urb->actual_length != urb->transfer_buffer_length) {
+		dev_err(go->dev, "short read in interrupt pipe!\n");
+	} else {
+		go->interrupt_available = 1;
+		go->interrupt_data = __le16_to_cpu(regs[0]);
+		go->interrupt_value = __le16_to_cpu(regs[1]);
+		pr_debug("ReadInterrupt: %04x %04x\n",
+				go->interrupt_value, go->interrupt_data);
+	}
+
+	wake_up(&go->interrupt_waitq);
+}
+
+static int go7007_usb_read_interrupt(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int r;
+
+	r = usb_submit_urb(usb->intr_urb, GFP_KERNEL);
+	if (r < 0) {
+		dev_err(go->dev, "unable to submit interrupt urb: %d\n", r);
+		return r;
+	}
+	return 0;
+}
+
+static void go7007_usb_read_video_pipe_complete(struct urb *urb)
+{
+	struct go7007 *go = (struct go7007 *)urb->context;
+	int r, status = urb->status;
+
+	if (!vb2_is_streaming(&go->vidq)) {
+		wake_up_interruptible(&go->frame_waitq);
+		return;
+	}
+	if (status) {
+		dev_err(go->dev, "error in video pipe: %d\n", status);
+		return;
+	}
+	if (urb->actual_length != urb->transfer_buffer_length) {
+		dev_err(go->dev, "short read in video pipe!\n");
+		return;
+	}
+	go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length);
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r < 0)
+		dev_err(go->dev, "error in video pipe: %d\n", r);
+}
+
+static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
+{
+	struct go7007 *go = (struct go7007 *)urb->context;
+	int r, status = urb->status;
+
+	if (!vb2_is_streaming(&go->vidq))
+		return;
+	if (status) {
+		dev_err(go->dev, "error in audio pipe: %d\n",
+			status);
+		return;
+	}
+	if (urb->actual_length != urb->transfer_buffer_length) {
+		dev_err(go->dev, "short read in audio pipe!\n");
+		return;
+	}
+	if (go->audio_deliver != NULL)
+		go->audio_deliver(go, urb->transfer_buffer, urb->actual_length);
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r < 0)
+		dev_err(go->dev, "error in audio pipe: %d\n", r);
+}
+
+static int go7007_usb_stream_start(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int i, r;
+
+	for (i = 0; i < 8; ++i) {
+		r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL);
+		if (r < 0) {
+			dev_err(go->dev, "error submitting video urb %d: %d\n", i, r);
+			goto video_submit_failed;
+		}
+	}
+	if (!go->audio_enabled)
+		return 0;
+
+	for (i = 0; i < 8; ++i) {
+		r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL);
+		if (r < 0) {
+			dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r);
+			goto audio_submit_failed;
+		}
+	}
+	return 0;
+
+audio_submit_failed:
+	for (i = 0; i < 7; ++i)
+		usb_kill_urb(usb->audio_urbs[i]);
+video_submit_failed:
+	for (i = 0; i < 8; ++i)
+		usb_kill_urb(usb->video_urbs[i]);
+	return -1;
+}
+
+static int go7007_usb_stream_stop(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int i;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return 0;
+	for (i = 0; i < 8; ++i)
+		usb_kill_urb(usb->video_urbs[i]);
+	if (go->audio_enabled)
+		for (i = 0; i < 8; ++i)
+			usb_kill_urb(usb->audio_urbs[i]);
+	return 0;
+}
+
+static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int transferred, pipe;
+	int timeout = 500;
+
+	pr_debug("DownloadBuffer sending %d bytes\n", len);
+
+	if (usb->board->flags & GO7007_USB_EZUSB)
+		pipe = usb_sndbulkpipe(usb->usbdev, 2);
+	else
+		pipe = usb_sndbulkpipe(usb->usbdev, 3);
+
+	return usb_bulk_msg(usb->usbdev, pipe, data, len,
+					&transferred, timeout);
+}
+
+static void go7007_usb_release(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	struct urb *vurb, *aurb;
+	int i;
+
+	if (usb->intr_urb) {
+		usb_kill_urb(usb->intr_urb);
+		kfree(usb->intr_urb->transfer_buffer);
+		usb_free_urb(usb->intr_urb);
+	}
+
+	/* Free USB-related structs */
+	for (i = 0; i < 8; ++i) {
+		vurb = usb->video_urbs[i];
+		if (vurb) {
+			usb_kill_urb(vurb);
+			kfree(vurb->transfer_buffer);
+			usb_free_urb(vurb);
+		}
+		aurb = usb->audio_urbs[i];
+		if (aurb) {
+			usb_kill_urb(aurb);
+			kfree(aurb->transfer_buffer);
+			usb_free_urb(aurb);
+		}
+	}
+
+	kfree(go->hpi_context);
+}
+
+static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
+	.interface_reset	= go7007_usb_interface_reset,
+	.write_interrupt	= go7007_usb_ezusb_write_interrupt,
+	.read_interrupt		= go7007_usb_read_interrupt,
+	.stream_start		= go7007_usb_stream_start,
+	.stream_stop		= go7007_usb_stream_stop,
+	.send_firmware		= go7007_usb_send_firmware,
+	.release		= go7007_usb_release,
+};
+
+static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
+	.interface_reset	= go7007_usb_interface_reset,
+	.write_interrupt	= go7007_usb_onboard_write_interrupt,
+	.read_interrupt		= go7007_usb_read_interrupt,
+	.stream_start		= go7007_usb_stream_start,
+	.stream_stop		= go7007_usb_stream_stop,
+	.send_firmware		= go7007_usb_send_firmware,
+	.release		= go7007_usb_release,
+};
+
+/********************* Driver for EZ-USB I2C adapter *********************/
+
+static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
+					struct i2c_msg msgs[], int num)
+{
+	struct go7007 *go = i2c_get_adapdata(adapter);
+	struct go7007_usb *usb = go->hpi_context;
+	u8 *buf = go->usb_buf;
+	int buf_len, i;
+	int ret = -EIO;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -ENODEV;
+
+	mutex_lock(&usb->i2c_lock);
+
+	for (i = 0; i < num; ++i) {
+		/* The hardware command is "write some bytes then read some
+		 * bytes", so we try to coalesce a write followed by a read
+		 * into a single USB transaction */
+		if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr &&
+				!(msgs[i].flags & I2C_M_RD) &&
+				(msgs[i + 1].flags & I2C_M_RD)) {
+#ifdef GO7007_I2C_DEBUG
+			pr_debug("i2c write/read %d/%d bytes on %02x\n",
+				msgs[i].len, msgs[i + 1].len, msgs[i].addr);
+#endif
+			buf[0] = 0x01;
+			buf[1] = msgs[i].len + 1;
+			buf[2] = msgs[i].addr << 1;
+			memcpy(&buf[3], msgs[i].buf, msgs[i].len);
+			buf_len = msgs[i].len + 3;
+			buf[buf_len++] = msgs[++i].len;
+		} else if (msgs[i].flags & I2C_M_RD) {
+#ifdef GO7007_I2C_DEBUG
+			pr_debug("i2c read %d bytes on %02x\n",
+					msgs[i].len, msgs[i].addr);
+#endif
+			buf[0] = 0x01;
+			buf[1] = 1;
+			buf[2] = msgs[i].addr << 1;
+			buf[3] = msgs[i].len;
+			buf_len = 4;
+		} else {
+#ifdef GO7007_I2C_DEBUG
+			pr_debug("i2c write %d bytes on %02x\n",
+					msgs[i].len, msgs[i].addr);
+#endif
+			buf[0] = 0x00;
+			buf[1] = msgs[i].len + 1;
+			buf[2] = msgs[i].addr << 1;
+			memcpy(&buf[3], msgs[i].buf, msgs[i].len);
+			buf_len = msgs[i].len + 3;
+			buf[buf_len++] = 0;
+		}
+		if (go7007_usb_vendor_request(go, 0x24, 0, 0,
+						buf, buf_len, 0) < 0)
+			goto i2c_done;
+		if (msgs[i].flags & I2C_M_RD) {
+			memset(buf, 0, msgs[i].len + 1);
+			if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
+						msgs[i].len + 1, 1) < 0)
+				goto i2c_done;
+			memcpy(msgs[i].buf, buf + 1, msgs[i].len);
+		}
+	}
+	ret = num;
+
+i2c_done:
+	mutex_unlock(&usb->i2c_lock);
+	return ret;
+}
+
+static u32 go7007_usb_functionality(struct i2c_adapter *adapter)
+{
+	/* No errors are reported by the hardware, so we don't bother
+	 * supporting quick writes to avoid confusing probing */
+	return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK;
+}
+
+static struct i2c_algorithm go7007_usb_algo = {
+	.master_xfer	= go7007_usb_i2c_master_xfer,
+	.functionality	= go7007_usb_functionality,
+};
+
+static struct i2c_adapter go7007_usb_adap_templ = {
+	.owner			= THIS_MODULE,
+	.name			= "WIS GO7007SB EZ-USB",
+	.algo			= &go7007_usb_algo,
+};
+
+/********************* USB add/remove functions *********************/
+
+static int go7007_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct go7007 *go;
+	struct go7007_usb *usb;
+	const struct go7007_usb_board *board;
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	unsigned num_i2c_devs;
+	char *name;
+	int video_pipe, i, v_urb_len;
+
+	pr_debug("probing new GO7007 USB board\n");
+
+	switch (id->driver_info) {
+	case GO7007_BOARDID_MATRIX_II:
+		name = "WIS Matrix II or compatible";
+		board = &board_matrix_ii;
+		break;
+	case GO7007_BOARDID_MATRIX_RELOAD:
+		name = "WIS Matrix Reloaded or compatible";
+		board = &board_matrix_reload;
+		break;
+	case GO7007_BOARDID_MATRIX_REV:
+		name = "WIS Matrix Revolution or compatible";
+		board = &board_matrix_revolution;
+		break;
+	case GO7007_BOARDID_STAR_TREK:
+		name = "WIS Star Trek or compatible";
+		board = &board_star_trek;
+		break;
+	case GO7007_BOARDID_XMEN:
+		name = "WIS XMen or compatible";
+		board = &board_xmen;
+		break;
+	case GO7007_BOARDID_XMEN_II:
+		name = "WIS XMen II or compatible";
+		board = &board_xmen;
+		break;
+	case GO7007_BOARDID_XMEN_III:
+		name = "WIS XMen III or compatible";
+		board = &board_xmen;
+		break;
+	case GO7007_BOARDID_PX_M402U:
+		name = "Plextor PX-M402U";
+		board = &board_matrix_ii;
+		break;
+	case GO7007_BOARDID_PX_TV402U:
+		name = "Plextor PX-TV402U (unknown tuner)";
+		board = &board_px_tv402u;
+		break;
+	case GO7007_BOARDID_LIFEVIEW_LR192:
+		dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
+		return -ENODEV;
+		name = "Lifeview TV Walker Ultra";
+		board = &board_lifeview_lr192;
+		break;
+	case GO7007_BOARDID_SENSORAY_2250:
+		dev_info(&intf->dev, "Sensoray 2250 found\n");
+		name = "Sensoray 2250/2251";
+		board = &board_sensoray_2250;
+		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		name = "ADS Tech DVD Xpress DX2";
+		board = &board_ads_usbav_709;
+		break;
+	default:
+		dev_err(&intf->dev, "unknown board ID %d!\n",
+				(unsigned int)id->driver_info);
+		return -ENODEV;
+	}
+
+	go = go7007_alloc(&board->main_info, &intf->dev);
+	if (go == NULL)
+		return -ENOMEM;
+
+	usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL);
+	if (usb == NULL) {
+		kfree(go);
+		return -ENOMEM;
+	}
+
+	usb->board = board;
+	usb->usbdev = usbdev;
+	usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info));
+	go->board_id = id->driver_info;
+	strncpy(go->name, name, sizeof(go->name));
+	if (board->flags & GO7007_USB_EZUSB)
+		go->hpi_ops = &go7007_usb_ezusb_hpi_ops;
+	else
+		go->hpi_ops = &go7007_usb_onboard_hpi_ops;
+	go->hpi_context = usb;
+
+	/* Allocate the URB and buffer for receiving incoming interrupts */
+	usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (usb->intr_urb == NULL)
+		goto allocfail;
+	usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
+	if (usb->intr_urb->transfer_buffer == NULL)
+		goto allocfail;
+
+	if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
+		usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
+			usb_rcvbulkpipe(usb->usbdev, 4),
+			usb->intr_urb->transfer_buffer, 2*sizeof(u16),
+			go7007_usb_readinterrupt_complete, go);
+	else
+		usb_fill_int_urb(usb->intr_urb, usb->usbdev,
+			usb_rcvintpipe(usb->usbdev, 4),
+			usb->intr_urb->transfer_buffer, 2*sizeof(u16),
+			go7007_usb_readinterrupt_complete, go, 8);
+	usb_set_intfdata(intf, &go->v4l2_dev);
+
+	/* Boot the GO7007 */
+	if (go7007_boot_encoder(go, go->board_info->flags &
+					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
+		goto allocfail;
+
+	/* Register the EZ-USB I2C adapter, if we're using it */
+	if (board->flags & GO7007_USB_EZUSB_I2C) {
+		memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
+				sizeof(go7007_usb_adap_templ));
+		mutex_init(&usb->i2c_lock);
+		go->i2c_adapter.dev.parent = go->dev;
+		i2c_set_adapdata(&go->i2c_adapter, go);
+		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
+			dev_err(go->dev, "error: i2c_add_adapter failed\n");
+			goto allocfail;
+		}
+		go->i2c_adapter_online = 1;
+	}
+
+	/* Pelco and Adlink reused the XMen and XMen-III vendor and product
+	 * IDs for their own incompatible designs.  We can detect XMen boards
+	 * by probing the sensor, but there is no way to probe the sensors on
+	 * the Pelco and Adlink designs so we default to the Adlink.  If it
+	 * is actually a Pelco, the user must set the assume_endura module
+	 * parameter. */
+	if ((go->board_id == GO7007_BOARDID_XMEN ||
+				go->board_id == GO7007_BOARDID_XMEN_III) &&
+			go->i2c_adapter_online) {
+		union i2c_smbus_data data;
+
+		/* Check to see if register 0x0A is 0x76 */
+		i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
+			I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
+		if (data.byte != 0x76) {
+			if (assume_endura) {
+				go->board_id = GO7007_BOARDID_ENDURA;
+				usb->board = board = &board_endura;
+				go->board_info = &board->main_info;
+				strncpy(go->name, "Pelco Endura",
+					sizeof(go->name));
+			} else {
+				u16 channel;
+
+				/* read channel number from GPIO[1:0] */
+				go7007_read_addr(go, 0x3c81, &channel);
+				channel &= 0x3;
+				go->board_id = GO7007_BOARDID_ADLINK_MPG24;
+				usb->board = board = &board_adlink_mpg24;
+				go->board_info = &board->main_info;
+				go->channel_number = channel;
+				snprintf(go->name, sizeof(go->name),
+					"Adlink PCI-MPG24, channel #%d",
+					channel);
+			}
+			go7007_update_board(go);
+		}
+	}
+
+	num_i2c_devs = go->board_info->num_i2c_devs;
+
+	/* Probe the tuner model on the TV402U */
+	if (go->board_id == GO7007_BOARDID_PX_TV402U) {
+		/* Board strapping indicates tuner model */
+		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
+					1) < 0) {
+			dev_err(go->dev, "GPIO read failed!\n");
+			goto allocfail;
+		}
+		switch (go->usb_buf[0] >> 6) {
+		case 1:
+			go->tuner_type = TUNER_SONY_BTF_PG472Z;
+			go->std = V4L2_STD_PAL;
+			strncpy(go->name, "Plextor PX-TV402U-EU",
+					sizeof(go->name));
+			break;
+		case 2:
+			go->tuner_type = TUNER_SONY_BTF_PK467Z;
+			go->std = V4L2_STD_NTSC_M_JP;
+			num_i2c_devs -= 2;
+			strncpy(go->name, "Plextor PX-TV402U-JP",
+					sizeof(go->name));
+			break;
+		case 3:
+			go->tuner_type = TUNER_SONY_BTF_PB463Z;
+			num_i2c_devs -= 2;
+			strncpy(go->name, "Plextor PX-TV402U-NA",
+					sizeof(go->name));
+			break;
+		default:
+			pr_debug("unable to detect tuner type!\n");
+			break;
+		}
+		/* Configure tuner mode selection inputs connected
+		 * to the EZ-USB GPIO output pins */
+		if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
+					NULL, 0, 0) < 0) {
+			dev_err(go->dev, "GPIO write failed!\n");
+			goto allocfail;
+		}
+	}
+
+	/* Print a nasty message if the user attempts to use a USB2.0 device in
+	 * a USB1.1 port.  There will be silent corruption of the stream. */
+	if ((board->flags & GO7007_USB_EZUSB) &&
+			usbdev->speed != USB_SPEED_HIGH)
+		dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
+
+	/* Allocate the URBs and buffers for receiving the video stream */
+	if (board->flags & GO7007_USB_EZUSB) {
+		v_urb_len = 1024;
+		video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
+	} else {
+		v_urb_len = 512;
+		video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
+	}
+	for (i = 0; i < 8; ++i) {
+		usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (usb->video_urbs[i] == NULL)
+			goto allocfail;
+		usb->video_urbs[i]->transfer_buffer =
+						kmalloc(v_urb_len, GFP_KERNEL);
+		if (usb->video_urbs[i]->transfer_buffer == NULL)
+			goto allocfail;
+		usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
+				usb->video_urbs[i]->transfer_buffer, v_urb_len,
+				go7007_usb_read_video_pipe_complete, go);
+	}
+
+	/* Allocate the URBs and buffers for receiving the audio stream */
+	if ((board->flags & GO7007_USB_EZUSB) &&
+	    (board->flags & GO7007_BOARD_HAS_AUDIO)) {
+		for (i = 0; i < 8; ++i) {
+			usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+			if (usb->audio_urbs[i] == NULL)
+				goto allocfail;
+			usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
+								GFP_KERNEL);
+			if (usb->audio_urbs[i]->transfer_buffer == NULL)
+				goto allocfail;
+			usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
+				usb_rcvbulkpipe(usb->usbdev, 8),
+				usb->audio_urbs[i]->transfer_buffer, 4096,
+				go7007_usb_read_audio_pipe_complete, go);
+		}
+	}
+
+	/* Do any final GO7007 initialization, then register the
+	 * V4L2 and ALSA interfaces */
+	if (go7007_register_encoder(go, num_i2c_devs) < 0)
+		goto allocfail;
+
+	go->status = STATUS_ONLINE;
+	return 0;
+
+allocfail:
+	go7007_usb_release(go);
+	kfree(go);
+	return -ENOMEM;
+}
+
+static void go7007_usb_disconnect(struct usb_interface *intf)
+{
+	struct go7007 *go = to_go7007(usb_get_intfdata(intf));
+
+	mutex_lock(&go->queue_lock);
+	mutex_lock(&go->serialize_lock);
+
+	if (go->audio_enabled)
+		go7007_snd_remove(go);
+
+	go->status = STATUS_SHUTDOWN;
+	v4l2_device_disconnect(&go->v4l2_dev);
+	video_unregister_device(&go->vdev);
+	mutex_unlock(&go->serialize_lock);
+	mutex_unlock(&go->queue_lock);
+
+	v4l2_device_put(&go->v4l2_dev);
+}
+
+static struct usb_driver go7007_usb_driver = {
+	.name		= "go7007",
+	.probe		= go7007_usb_probe,
+	.disconnect	= go7007_usb_disconnect,
+	.id_table	= go7007_usb_id_table,
+};
+
+module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-v4l2.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-v4l2.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/go7007-v4l2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/go7007-v4l2.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+#include <media/saa7115.h>
+
+#include "go7007-priv.h"
+
+#define call_all(dev, o, f, args...) \
+	v4l2_device_call_until_err(dev, 0, o, f, ##args)
+
+static bool valid_pixelformat(u32 pixelformat)
+{
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_MJPEG:
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+	case V4L2_PIX_FMT_MPEG4:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
+{
+	u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+
+	switch (format) {
+	case V4L2_PIX_FMT_MJPEG:
+		return V4L2_BUF_FLAG_KEYFRAME;
+	case V4L2_PIX_FMT_MPEG4:
+		switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
+		case 0:
+			return V4L2_BUF_FLAG_KEYFRAME;
+		case 1:
+			return V4L2_BUF_FLAG_PFRAME;
+		case 2:
+			return V4L2_BUF_FLAG_BFRAME;
+		default:
+			return 0;
+		}
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+		switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
+		case 1:
+			return V4L2_BUF_FLAG_KEYFRAME;
+		case 2:
+			return V4L2_BUF_FLAG_PFRAME;
+		case 3:
+			return V4L2_BUF_FLAG_BFRAME;
+		default:
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static void get_resolution(struct go7007 *go, int *width, int *height)
+{
+	switch (go->standard) {
+	case GO7007_STD_NTSC:
+		*width = 720;
+		*height = 480;
+		break;
+	case GO7007_STD_PAL:
+		*width = 720;
+		*height = 576;
+		break;
+	case GO7007_STD_OTHER:
+	default:
+		*width = go->board_info->sensor_width;
+		*height = go->board_info->sensor_height;
+		break;
+	}
+}
+
+static void set_formatting(struct go7007 *go)
+{
+	if (go->format == V4L2_PIX_FMT_MJPEG) {
+		go->pali = 0;
+		go->aspect_ratio = GO7007_RATIO_1_1;
+		go->gop_size = 0;
+		go->ipb = 0;
+		go->closed_gop = 0;
+		go->repeat_seqhead = 0;
+		go->seq_header_enable = 0;
+		go->gop_header_enable = 0;
+		go->dvd_mode = 0;
+		return;
+	}
+
+	switch (go->format) {
+	case V4L2_PIX_FMT_MPEG1:
+		go->pali = 0;
+		break;
+	default:
+	case V4L2_PIX_FMT_MPEG2:
+		go->pali = 0x48;
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		/* For future reference: this is the list of MPEG4
+		 * profiles that are available, although they are
+		 * untested:
+		 *
+		 * Profile		pali
+		 * --------------	----
+		 * PROFILE_S_L0		0x08
+		 * PROFILE_S_L1		0x01
+		 * PROFILE_S_L2		0x02
+		 * PROFILE_S_L3		0x03
+		 * PROFILE_ARTS_L1	0x91
+		 * PROFILE_ARTS_L2	0x92
+		 * PROFILE_ARTS_L3	0x93
+		 * PROFILE_ARTS_L4	0x94
+		 * PROFILE_AS_L0	0xf0
+		 * PROFILE_AS_L1	0xf1
+		 * PROFILE_AS_L2	0xf2
+		 * PROFILE_AS_L3	0xf3
+		 * PROFILE_AS_L4	0xf4
+		 * PROFILE_AS_L5	0xf5
+		 */
+		go->pali = 0xf5;
+		break;
+	}
+	go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size);
+	go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure);
+	go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0;
+	go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate);
+	go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader);
+	go->gop_header_enable = 1;
+	go->dvd_mode = 0;
+	if (go->format == V4L2_PIX_FMT_MPEG2)
+		go->dvd_mode =
+			go->bitrate == 9800000 &&
+			go->gop_size == 15 &&
+			go->ipb == 0 &&
+			go->repeat_seqhead == 1 &&
+			go->closed_gop;
+
+	switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) {
+	default:
+	case V4L2_MPEG_VIDEO_ASPECT_1x1:
+		go->aspect_ratio = GO7007_RATIO_1_1;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_4x3:
+		go->aspect_ratio = GO7007_RATIO_4_3;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_16x9:
+		go->aspect_ratio = GO7007_RATIO_16_9;
+		break;
+	}
+}
+
+static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
+{
+	int sensor_height = 0, sensor_width = 0;
+	int width, height;
+
+	if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
+		return -EINVAL;
+
+	get_resolution(go, &sensor_width, &sensor_height);
+
+	if (fmt == NULL) {
+		width = sensor_width;
+		height = sensor_height;
+	} else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
+		if (fmt->fmt.pix.width > sensor_width)
+			width = sensor_width;
+		else if (fmt->fmt.pix.width < 144)
+			width = 144;
+		else
+			width = fmt->fmt.pix.width & ~0x0f;
+
+		if (fmt->fmt.pix.height > sensor_height)
+			height = sensor_height;
+		else if (fmt->fmt.pix.height < 96)
+			height = 96;
+		else
+			height = fmt->fmt.pix.height & ~0x0f;
+	} else {
+		width = fmt->fmt.pix.width;
+
+		if (width <= sensor_width / 4) {
+			width = sensor_width / 4;
+			height = sensor_height / 4;
+		} else if (width <= sensor_width / 2) {
+			width = sensor_width / 2;
+			height = sensor_height / 2;
+		} else {
+			width = sensor_width;
+			height = sensor_height;
+		}
+		width &= ~0xf;
+		height &= ~0xf;
+	}
+
+	if (fmt != NULL) {
+		u32 pixelformat = fmt->fmt.pix.pixelformat;
+
+		memset(fmt, 0, sizeof(*fmt));
+		fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		fmt->fmt.pix.width = width;
+		fmt->fmt.pix.height = height;
+		fmt->fmt.pix.pixelformat = pixelformat;
+		fmt->fmt.pix.field = V4L2_FIELD_NONE;
+		fmt->fmt.pix.bytesperline = 0;
+		fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
+		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	}
+
+	if (try)
+		return 0;
+
+	if (fmt)
+		go->format = fmt->fmt.pix.pixelformat;
+	go->width = width;
+	go->height = height;
+	go->encoder_h_offset = go->board_info->sensor_h_offset;
+	go->encoder_v_offset = go->board_info->sensor_v_offset;
+
+	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
+		struct v4l2_mbus_framefmt mbus_fmt;
+
+		mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+		mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
+		mbus_fmt.height = height;
+		go->encoder_h_halve = 0;
+		go->encoder_v_halve = 0;
+		go->encoder_subsample = 0;
+		call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt);
+	} else {
+		if (width <= sensor_width / 4) {
+			go->encoder_h_halve = 1;
+			go->encoder_v_halve = 1;
+			go->encoder_subsample = 1;
+		} else if (width <= sensor_width / 2) {
+			go->encoder_h_halve = 1;
+			go->encoder_v_halve = 1;
+			go->encoder_subsample = 0;
+		} else {
+			go->encoder_h_halve = 0;
+			go->encoder_v_halve = 0;
+			go->encoder_subsample = 0;
+		}
+	}
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	strlcpy(cap->driver, "go7007", sizeof(cap->driver));
+	strlcpy(cap->card, go->name, sizeof(cap->card));
+	strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
+
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+				V4L2_CAP_STREAMING;
+
+	if (go->board_info->num_aud_inputs)
+		cap->device_caps |= V4L2_CAP_AUDIO;
+	if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
+		cap->device_caps |= V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *fmt)
+{
+	char *desc = NULL;
+
+	switch (fmt->index) {
+	case 0:
+		fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
+		desc = "Motion JPEG";
+		break;
+	case 1:
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
+		desc = "MPEG-1 ES";
+		break;
+	case 2:
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
+		desc = "MPEG-2 ES";
+		break;
+	case 3:
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
+		desc = "MPEG-4 ES";
+		break;
+	default:
+		return -EINVAL;
+	}
+	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
+
+	strncpy(fmt->description, desc, sizeof(fmt->description));
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *fmt)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	fmt->fmt.pix.width = go->width;
+	fmt->fmt.pix.height = go->height;
+	fmt->fmt.pix.pixelformat = go->format;
+	fmt->fmt.pix.field = V4L2_FIELD_NONE;
+	fmt->fmt.pix.bytesperline = 0;
+	fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+			struct v4l2_format *fmt)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	return set_capture_size(go, fmt, 1);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+			struct v4l2_format *fmt)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (vb2_is_busy(&go->vidq))
+		return -EBUSY;
+
+	return set_capture_size(go, fmt, 0);
+}
+
+static int go7007_queue_setup(struct vb2_queue *q,
+		const struct v4l2_format *fmt,
+		unsigned int *num_buffers, unsigned int *num_planes,
+		unsigned int sizes[], void *alloc_ctxs[])
+{
+	sizes[0] = GO7007_BUF_SIZE;
+	*num_planes = 1;
+
+	if (*num_buffers < 2)
+		*num_buffers = 2;
+
+	return 0;
+}
+
+static void go7007_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
+	unsigned long flags;
+
+	spin_lock_irqsave(&go->spinlock, flags);
+	list_add_tail(&go7007_vb->list, &go->vidq_active);
+	spin_unlock_irqrestore(&go->spinlock, flags);
+}
+
+static int go7007_buf_prepare(struct vb2_buffer *vb)
+{
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
+
+	go7007_vb->modet_active = 0;
+	go7007_vb->frame_offset = 0;
+	vb->v4l2_planes[0].bytesused = 0;
+	return 0;
+}
+
+static void go7007_buf_finish(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
+	u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
+	struct v4l2_buffer *buf = &vb->v4l2_buf;
+
+	buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
+			V4L2_BUF_FLAG_PFRAME);
+	buf->flags |= frame_type_flag;
+	buf->field = V4L2_FIELD_NONE;
+}
+
+static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct go7007 *go = vb2_get_drv_priv(q);
+	int ret;
+
+	set_formatting(go);
+	mutex_lock(&go->hw_lock);
+	go->next_seq = 0;
+	go->active_buf = NULL;
+	go->modet_event_status = 0;
+	q->streaming = 1;
+	if (go7007_start_encoder(go) < 0)
+		ret = -EIO;
+	else
+		ret = 0;
+	mutex_unlock(&go->hw_lock);
+	if (ret) {
+		q->streaming = 0;
+		return ret;
+	}
+	call_all(&go->v4l2_dev, video, s_stream, 1);
+	v4l2_ctrl_grab(go->mpeg_video_gop_size, true);
+	v4l2_ctrl_grab(go->mpeg_video_gop_closure, true);
+	v4l2_ctrl_grab(go->mpeg_video_bitrate, true);
+	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true);
+	/* Turn on Capture LED */
+	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
+		go7007_write_addr(go, 0x3c82, 0x0005);
+	return ret;
+}
+
+static void go7007_stop_streaming(struct vb2_queue *q)
+{
+	struct go7007 *go = vb2_get_drv_priv(q);
+	unsigned long flags;
+
+	q->streaming = 0;
+	go7007_stream_stop(go);
+	mutex_lock(&go->hw_lock);
+	go7007_reset_encoder(go);
+	mutex_unlock(&go->hw_lock);
+	call_all(&go->v4l2_dev, video, s_stream, 0);
+
+	spin_lock_irqsave(&go->spinlock, flags);
+	INIT_LIST_HEAD(&go->vidq_active);
+	spin_unlock_irqrestore(&go->spinlock, flags);
+	v4l2_ctrl_grab(go->mpeg_video_gop_size, false);
+	v4l2_ctrl_grab(go->mpeg_video_gop_closure, false);
+	v4l2_ctrl_grab(go->mpeg_video_bitrate, false);
+	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false);
+	/* Turn on Capture LED */
+	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
+		go7007_write_addr(go, 0x3c82, 0x000d);
+}
+
+static struct vb2_ops go7007_video_qops = {
+	.queue_setup    = go7007_queue_setup,
+	.buf_queue      = go7007_buf_queue,
+	.buf_prepare    = go7007_buf_prepare,
+	.buf_finish     = go7007_buf_finish,
+	.start_streaming = go7007_start_streaming,
+	.stop_streaming = go7007_stop_streaming,
+	.wait_prepare   = vb2_ops_wait_prepare,
+	.wait_finish    = vb2_ops_wait_finish,
+};
+
+static int vidioc_g_parm(struct file *filp, void *priv,
+		struct v4l2_streamparm *parm)
+{
+	struct go7007 *go = video_drvdata(filp);
+	struct v4l2_fract timeperframe = {
+		.numerator = 1001 *  go->fps_scale,
+		.denominator = go->sensor_framerate,
+	};
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	parm->parm.capture.readbuffers = 2;
+	parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+	parm->parm.capture.timeperframe = timeperframe;
+
+	return 0;
+}
+
+static int vidioc_s_parm(struct file *filp, void *priv,
+		struct v4l2_streamparm *parm)
+{
+	struct go7007 *go = video_drvdata(filp);
+	unsigned int n, d;
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	n = go->sensor_framerate *
+		parm->parm.capture.timeperframe.numerator;
+	d = 1001 * parm->parm.capture.timeperframe.denominator;
+	if (n != 0 && d != 0 && n > d)
+		go->fps_scale = (n + d/2) / d;
+	else
+		go->fps_scale = 1;
+
+	return vidioc_g_parm(filp, priv, parm);
+}
+
+/* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
+   its resolution, when the device is not connected to TV.
+   This is were an API abuse, probably used by the lack of specific IOCTL's to
+   enumerate it, by the time the driver was written.
+
+   However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
+   and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
+
+   The two functions below implement the newer ioctls
+*/
+static int vidioc_enum_framesizes(struct file *filp, void *priv,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct go7007 *go = video_drvdata(filp);
+	int width, height;
+
+	if (fsize->index > 2)
+		return -EINVAL;
+
+	if (!valid_pixelformat(fsize->pixel_format))
+		return -EINVAL;
+
+	get_resolution(go, &width, &height);
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = (width >> fsize->index) & ~0xf;
+	fsize->discrete.height = (height >> fsize->index) & ~0xf;
+	return 0;
+}
+
+static int vidioc_enum_frameintervals(struct file *filp, void *priv,
+				      struct v4l2_frmivalenum *fival)
+{
+	struct go7007 *go = video_drvdata(filp);
+	int width, height;
+	int i;
+
+	if (fival->index > 4)
+		return -EINVAL;
+
+	if (!valid_pixelformat(fival->pixel_format))
+		return -EINVAL;
+
+	if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
+		get_resolution(go, &width, &height);
+		for (i = 0; i <= 2; i++)
+			if (fival->width == ((width >> i) & ~0xf) &&
+			    fival->height == ((height >> i) & ~0xf))
+				break;
+		if (i > 2)
+			return -EINVAL;
+	}
+	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+	fival->discrete.numerator = 1001 * (fival->index + 1);
+	fival->discrete.denominator = go->sensor_framerate;
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	*std = go->std;
+	return 0;
+}
+
+static int go7007_s_std(struct go7007 *go)
+{
+	if (go->std & V4L2_STD_625_50) {
+		go->standard = GO7007_STD_PAL;
+		go->sensor_framerate = 25025;
+	} else {
+		go->standard = GO7007_STD_NTSC;
+		go->sensor_framerate = 30000;
+	}
+
+	call_all(&go->v4l2_dev, video, s_std, go->std);
+	set_capture_size(go, NULL, 0);
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (vb2_is_busy(&go->vidq))
+		return -EBUSY;
+
+	go->std = std;
+
+	return go7007_s_std(go);
+}
+
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	return call_all(&go->v4l2_dev, video, querystd, std);
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *inp)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (inp->index >= go->board_info->num_inputs)
+		return -EINVAL;
+
+	strncpy(inp->name, go->board_info->inputs[inp->index].name,
+			sizeof(inp->name));
+
+	/* If this board has a tuner, it will be the first input */
+	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+			inp->index == 0)
+		inp->type = V4L2_INPUT_TYPE_TUNER;
+	else
+		inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+	if (go->board_info->num_aud_inputs)
+		inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
+	else
+		inp->audioset = 0;
+	inp->tuner = 0;
+	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+		inp->std = video_devdata(file)->tvnorms;
+	else
+		inp->std = 0;
+
+	return 0;
+}
+
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	*input = go->input;
+
+	return 0;
+}
+
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (a->index >= go->board_info->num_aud_inputs)
+		return -EINVAL;
+	strlcpy(a->name, go->board_info->aud_inputs[a->index].name,
+		sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	a->index = go->aud_input;
+	strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
+		sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh,
+	const struct v4l2_audio *a)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (a->index >= go->board_info->num_aud_inputs)
+		return -EINVAL;
+	go->aud_input = a->index;
+	v4l2_subdev_call(go->sd_audio, audio, s_routing,
+		go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
+	return 0;
+}
+
+static void go7007_s_input(struct go7007 *go)
+{
+	unsigned int input = go->input;
+
+	v4l2_subdev_call(go->sd_video, video, s_routing,
+			go->board_info->inputs[input].video_input, 0,
+			go->board_info->video_config);
+	if (go->board_info->num_aud_inputs) {
+		int aud_input = go->board_info->inputs[input].audio_index;
+
+		v4l2_subdev_call(go->sd_audio, audio, s_routing,
+			go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
+		go->aud_input = aud_input;
+	}
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (input >= go->board_info->num_inputs)
+		return -EINVAL;
+	if (vb2_is_busy(&go->vidq))
+		return -EBUSY;
+
+	go->input = input;
+	go7007_s_input(go);
+
+	return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (t->index != 0)
+		return -EINVAL;
+
+	strlcpy(t->name, "Tuner", sizeof(t->name));
+	return call_all(&go->v4l2_dev, tuner, g_tuner, t);
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+				const struct v4l2_tuner *t)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (t->index != 0)
+		return -EINVAL;
+
+	return call_all(&go->v4l2_dev, tuner, s_tuner, t);
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (f->tuner)
+		return -EINVAL;
+
+	return call_all(&go->v4l2_dev, tuner, g_frequency, f);
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+				const struct v4l2_frequency *f)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	if (f->tuner)
+		return -EINVAL;
+
+	return call_all(&go->v4l2_dev, tuner, s_frequency, f);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct go7007 *go = video_drvdata(file);
+
+	v4l2_ctrl_log_status(file, priv);
+	return call_all(&go->v4l2_dev, core, log_status);
+}
+
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+				const struct v4l2_event_subscription *sub)
+{
+
+	switch (sub->type) {
+	case V4L2_EVENT_CTRL:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	case V4L2_EVENT_MOTION_DET:
+		/* Allow for up to 30 events (1 second for NTSC) to be
+		 * stored. */
+		return v4l2_event_subscribe(fh, sub, 30, NULL);
+	}
+	return -EINVAL;
+}
+
+
+static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct go7007 *go =
+		container_of(ctrl->handler, struct go7007, hdl);
+	unsigned y;
+	u8 *mt;
+
+	switch (ctrl->id) {
+	case V4L2_CID_PIXEL_THRESHOLD0:
+		go->modet[0].pixel_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MOTION_THRESHOLD0:
+		go->modet[0].motion_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MB_THRESHOLD0:
+		go->modet[0].mb_threshold = ctrl->val;
+		break;
+	case V4L2_CID_PIXEL_THRESHOLD1:
+		go->modet[1].pixel_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MOTION_THRESHOLD1:
+		go->modet[1].motion_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MB_THRESHOLD1:
+		go->modet[1].mb_threshold = ctrl->val;
+		break;
+	case V4L2_CID_PIXEL_THRESHOLD2:
+		go->modet[2].pixel_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MOTION_THRESHOLD2:
+		go->modet[2].motion_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MB_THRESHOLD2:
+		go->modet[2].mb_threshold = ctrl->val;
+		break;
+	case V4L2_CID_PIXEL_THRESHOLD3:
+		go->modet[3].pixel_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MOTION_THRESHOLD3:
+		go->modet[3].motion_threshold = ctrl->val;
+		break;
+	case V4L2_CID_MB_THRESHOLD3:
+		go->modet[3].mb_threshold = ctrl->val;
+		break;
+	case V4L2_CID_DETECT_MD_REGION_GRID:
+		mt = go->modet_map;
+		for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
+			memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct v4l2_file_operations go7007_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= vb2_fop_release,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= vb2_fop_read,
+	.mmap		= vb2_fop_mmap,
+	.poll		= vb2_fop_poll,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap          = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
+	.vidioc_g_std             = vidioc_g_std,
+	.vidioc_s_std             = vidioc_s_std,
+	.vidioc_querystd          = vidioc_querystd,
+	.vidioc_enum_input        = vidioc_enum_input,
+	.vidioc_g_input           = vidioc_g_input,
+	.vidioc_s_input           = vidioc_s_input,
+	.vidioc_enumaudio         = vidioc_enumaudio,
+	.vidioc_g_audio           = vidioc_g_audio,
+	.vidioc_s_audio           = vidioc_s_audio,
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
+	.vidioc_g_tuner           = vidioc_g_tuner,
+	.vidioc_s_tuner           = vidioc_s_tuner,
+	.vidioc_g_frequency       = vidioc_g_frequency,
+	.vidioc_s_frequency       = vidioc_s_frequency,
+	.vidioc_g_parm            = vidioc_g_parm,
+	.vidioc_s_parm            = vidioc_s_parm,
+	.vidioc_enum_framesizes   = vidioc_enum_framesizes,
+	.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+	.vidioc_log_status        = vidioc_log_status,
+	.vidioc_subscribe_event   = vidioc_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static struct video_device go7007_template = {
+	.name		= "go7007",
+	.fops		= &go7007_fops,
+	.release	= video_device_release_empty,
+	.ioctl_ops	= &video_ioctl_ops,
+	.tvnorms	= V4L2_STD_ALL,
+};
+
+static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
+	.s_ctrl = go7007_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_PIXEL_THRESHOLD0,
+	.name = "Pixel Threshold Region 0",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 20,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD0,
+	.name = "Motion Threshold Region 0",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 80,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MB_THRESHOLD0,
+	.name = "MB Threshold Region 0",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 200,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_PIXEL_THRESHOLD1,
+	.name = "Pixel Threshold Region 1",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 20,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD1,
+	.name = "Motion Threshold Region 1",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 80,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MB_THRESHOLD1,
+	.name = "MB Threshold Region 1",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 200,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_PIXEL_THRESHOLD2,
+	.name = "Pixel Threshold Region 2",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 20,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD2,
+	.name = "Motion Threshold Region 2",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 80,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MB_THRESHOLD2,
+	.name = "MB Threshold Region 2",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 200,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_PIXEL_THRESHOLD3,
+	.name = "Pixel Threshold Region 3",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 20,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD3,
+	.name = "Motion Threshold Region 3",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 80,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_MB_THRESHOLD3,
+	.name = "MB Threshold Region 3",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 200,
+	.max = 32767,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = {
+	.ops = &go7007_ctrl_ops,
+	.id = V4L2_CID_DETECT_MD_REGION_GRID,
+	.dims = { 576 / 16, 720 / 16 },
+	.max = 3,
+	.step = 1,
+};
+
+int go7007_v4l2_ctrl_init(struct go7007 *go)
+{
+	struct v4l2_ctrl_handler *hdl = &go->hdl;
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(hdl, 22);
+	go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
+	go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
+	go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_BITRATE,
+			64000, 10000000, 1, 9800000);
+	go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0);
+	go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1);
+
+	go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_ASPECT,
+			V4L2_MPEG_VIDEO_ASPECT_16x9, 0,
+			V4L2_MPEG_VIDEO_ASPECT_1x1);
+	ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_JPEG_ACTIVE_MARKER, 0,
+			V4L2_JPEG_ACTIVE_MARKER_DQT |
+			V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
+			V4L2_JPEG_ACTIVE_MARKER_DQT |
+			V4L2_JPEG_ACTIVE_MARKER_DHT);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL);
+	go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
+			V4L2_CID_DETECT_MD_MODE,
+			V4L2_DETECT_MD_MODE_REGION_GRID,
+			1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
+			V4L2_DETECT_MD_MODE_DISABLED);
+	if (hdl->error) {
+		int rv = hdl->error;
+
+		v4l2_err(&go->v4l2_dev, "Could not register controls\n");
+		return rv;
+	}
+	go->v4l2_dev.ctrl_handler = hdl;
+	return 0;
+}
+
+int go7007_v4l2_init(struct go7007 *go)
+{
+	struct video_device *vdev = &go->vdev;
+	int rv;
+
+	mutex_init(&go->serialize_lock);
+	mutex_init(&go->queue_lock);
+
+	INIT_LIST_HEAD(&go->vidq_active);
+	go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	go->vidq.ops = &go7007_video_qops;
+	go->vidq.mem_ops = &vb2_vmalloc_memops;
+	go->vidq.drv_priv = go;
+	go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
+	go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	go->vidq.lock = &go->queue_lock;
+	rv = vb2_queue_init(&go->vidq);
+	if (rv)
+		return rv;
+	*vdev = go7007_template;
+	vdev->lock = &go->serialize_lock;
+	vdev->queue = &go->vidq;
+	video_set_drvdata(vdev, go);
+	vdev->v4l2_dev = &go->v4l2_dev;
+	if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
+		v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
+	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
+		v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
+		v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
+	} else {
+		struct v4l2_frequency f = {
+			.type = V4L2_TUNER_ANALOG_TV,
+			.frequency = 980,
+		};
+
+		call_all(&go->v4l2_dev, tuner, s_frequency, &f);
+	}
+	if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
+		v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
+		vdev->tvnorms = 0;
+	}
+	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
+		v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
+	if (go->board_info->num_aud_inputs == 0) {
+		v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
+		v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
+	}
+	/* Setup correct crystal frequency on this board */
+	if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
+		v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
+				SAA7115_FREQ_24_576_MHZ,
+				SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
+				SAA7115_FREQ_FL_DOUBLE_ASCLK);
+	go7007_s_input(go);
+	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+		go7007_s_std(go);
+	rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (rv < 0)
+		return rv;
+	dev_info(go->dev, "registered device %s [v4l2]\n",
+		 video_device_node_name(vdev));
+
+	return 0;
+}
+
+void go7007_v4l2_remove(struct go7007 *go)
+{
+	v4l2_ctrl_handler_free(&go->hdl);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,51 @@
+config VIDEO_GO7007
+	tristate "WIS GO7007 MPEG encoder support"
+	depends on VIDEO_DEV && I2C
+	depends on SND && USB
+	select VIDEOBUF2_VMALLOC
+	select VIDEO_TUNER
+	select CYPRESS_FIRMWARE
+	select SND_PCM
+	select VIDEO_SONY_BTF_MPX if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+	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_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This is a video4linux driver for the WIS GO7007 MPEG
+	  encoder chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called go7007.
+
+config VIDEO_GO7007_USB
+	tristate "WIS GO7007 USB support"
+	depends on VIDEO_GO7007 && USB
+	---help---
+	  This is a video4linux driver for the WIS GO7007 MPEG
+	  encoder chip over USB.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called go7007-usb.
+
+config VIDEO_GO7007_LOADER
+	tristate "WIS GO7007 Loader support"
+	depends on VIDEO_GO7007
+	default y
+	---help---
+	  This is a go7007 firmware loader driver for the WIS GO7007
+	  MPEG encoder chip over USB.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called go7007-loader.
+
+config VIDEO_GO7007_USB_S2250_BOARD
+	tristate "Sensoray 2250/2251 support"
+	depends on VIDEO_GO7007_USB && USB
+	---help---
+	  This is a video4linux driver for the Sensoray 2250/2251 device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called s2250.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/Makefile linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/Makefile
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,11 @@
+obj-$(CONFIG_VIDEO_GO7007) += go7007.o
+obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
+obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o
+obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
+
+go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
+		snd-go7007.o
+
+s2250-y := s2250-board.o
+
+ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/s2250-board.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/s2250-board.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/s2250-board.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/s2250-board.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2008 Sensoray Company 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.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-subdev.h>
+#include "go7007-priv.h"
+
+MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver");
+MODULE_LICENSE("GPL v2");
+
+/*
+ * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b.
+ * Due to the unusual way these are accessed on this device we do not
+ * reuse the i2c drivers, but instead they are implemented in this
+ * driver. It would be nice to improve on this, though.
+ */
+
+#define TLV320_ADDRESS      0x34
+#define VPX322_ADDR_ANALOGCONTROL1	0x02
+#define VPX322_ADDR_BRIGHTNESS0		0x0127
+#define VPX322_ADDR_BRIGHTNESS1		0x0131
+#define VPX322_ADDR_CONTRAST0		0x0128
+#define VPX322_ADDR_CONTRAST1		0x0132
+#define VPX322_ADDR_HUE			0x00dc
+#define VPX322_ADDR_SAT			0x0030
+
+struct go7007_usb_board {
+	unsigned int flags;
+	struct go7007_board_info main_info;
+};
+
+struct go7007_usb {
+	struct go7007_usb_board *board;
+	struct mutex i2c_lock;
+	struct usb_device *usbdev;
+	struct urb *video_urbs[8];
+	struct urb *audio_urbs[8];
+	struct urb *intr_urb;
+};
+
+static unsigned char aud_regs[] = {
+	0x1e, 0x00,
+	0x00, 0x17,
+	0x02, 0x17,
+	0x04, 0xf9,
+	0x06, 0xf9,
+	0x08, 0x02,
+	0x0a, 0x00,
+	0x0c, 0x00,
+	0x0a, 0x00,
+	0x0c, 0x00,
+	0x0e, 0x02,
+	0x10, 0x00,
+	0x12, 0x01,
+	0x00, 0x00,
+};
+
+
+static unsigned char vid_regs[] = {
+	0xF2, 0x0f,
+	0xAA, 0x00,
+	0xF8, 0xff,
+	0x00, 0x00,
+};
+
+static u16 vid_regs_fp[] = {
+	0x028, 0x067,
+	0x120, 0x016,
+	0x121, 0xcF2,
+	0x122, 0x0F2,
+	0x123, 0x00c,
+	0x124, 0x2d0,
+	0x125, 0x2e0,
+	0x126, 0x004,
+	0x128, 0x1E0,
+	0x12A, 0x016,
+	0x12B, 0x0F2,
+	0x12C, 0x0F2,
+	0x12D, 0x00c,
+	0x12E, 0x2d0,
+	0x12F, 0x2e0,
+	0x130, 0x004,
+	0x132, 0x1E0,
+	0x140, 0x060,
+	0x153, 0x00C,
+	0x154, 0x200,
+	0x150, 0x801,
+	0x000, 0x000
+};
+
+/* PAL specific values */
+static u16 vid_regs_fp_pal[] = {
+	0x120, 0x017,
+	0x121, 0xd22,
+	0x122, 0x122,
+	0x12A, 0x017,
+	0x12B, 0x122,
+	0x12C, 0x122,
+	0x140, 0x060,
+	0x000, 0x000,
+};
+
+struct s2250 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	v4l2_std_id std;
+	int input;
+	int brightness;
+	int contrast;
+	int saturation;
+	int hue;
+	int reg12b_val;
+	int audio_input;
+	struct i2c_client *audio;
+};
+
+static inline struct s2250 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct s2250, sd);
+}
+
+/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
+static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
+	u16 value, u16 index, void *transfer_buffer, int length, int in)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	int timeout = 5000;
+
+	if (in) {
+		return usb_control_msg(usb->usbdev,
+				usb_rcvctrlpipe(usb->usbdev, 0), request,
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+				value, index, transfer_buffer, length, timeout);
+	} else {
+		return usb_control_msg(usb->usbdev,
+				usb_sndctrlpipe(usb->usbdev, 0), request,
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				value, index, transfer_buffer, length, timeout);
+	}
+}
+/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+	struct go7007 *go = i2c_get_adapdata(client->adapter);
+	struct go7007_usb *usb;
+	int rc;
+	int dev_addr = client->addr << 1;  /* firmware wants 8-bit address */
+	u8 *buf;
+
+	if (go == NULL)
+		return -ENODEV;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -EBUSY;
+
+	buf = kzalloc(16, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	usb = go->hpi_context;
+	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
+		dev_info(&client->dev, "i2c lock failed\n");
+		kfree(buf);
+		return -EINTR;
+	}
+	rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
+				       (reg<<8 | value),
+				       buf,
+				       16, 1);
+
+	mutex_unlock(&usb->i2c_lock);
+	kfree(buf);
+	return rc;
+}
+
+static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
+{
+	struct go7007 *go = i2c_get_adapdata(client->adapter);
+	struct go7007_usb *usb;
+	int rc;
+	u8 *buf;
+	struct s2250 *dec = i2c_get_clientdata(client);
+
+	if (go == NULL)
+		return -ENODEV;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -EBUSY;
+
+	buf = kzalloc(16, GFP_KERNEL);
+
+	if (buf == NULL)
+		return -ENOMEM;
+
+
+
+	memset(buf, 0xcd, 6);
+
+	usb = go->hpi_context;
+	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
+		dev_info(&client->dev, "i2c lock failed\n");
+		kfree(buf);
+		return -EINTR;
+	}
+	rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1);
+	mutex_unlock(&usb->i2c_lock);
+	if (rc < 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	if (buf[0] == 0) {
+		unsigned int subaddr, val_read;
+
+		subaddr = (buf[4] << 8) + buf[5];
+		val_read = (buf[2] << 8) + buf[3];
+		kfree(buf);
+		if (val_read != val) {
+			dev_info(&client->dev, "invalid fp write %x %x\n",
+				 val_read, val);
+			return -EFAULT;
+		}
+		if (subaddr != addr) {
+			dev_info(&client->dev, "invalid fp write addr %x %x\n",
+				 subaddr, addr);
+			return -EFAULT;
+		}
+	} else {
+		kfree(buf);
+		return -EFAULT;
+	}
+
+	/* save last 12b value */
+	if (addr == 0x12b)
+		dec->reg12b_val = val;
+
+	return 0;
+}
+
+static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
+{
+	struct go7007 *go = i2c_get_adapdata(client->adapter);
+	struct go7007_usb *usb;
+	int rc;
+	u8 *buf;
+
+	if (go == NULL)
+		return -ENODEV;
+
+	if (go->status == STATUS_SHUTDOWN)
+		return -EBUSY;
+
+	buf = kzalloc(16, GFP_KERNEL);
+
+	if (buf == NULL)
+		return -ENOMEM;
+
+
+
+	memset(buf, 0xcd, 6);
+	usb = go->hpi_context;
+	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
+		dev_info(&client->dev, "i2c lock failed\n");
+		kfree(buf);
+		return -EINTR;
+	}
+	rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1);
+	mutex_unlock(&usb->i2c_lock);
+	if (rc < 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	*val = (buf[0] << 8) | buf[1];
+	kfree(buf);
+
+	return 0;
+}
+
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+	int i;
+
+	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
+		if (write_reg(client, regs[i], regs[i+1]) < 0) {
+			dev_info(&client->dev, "failed\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int write_regs_fp(struct i2c_client *client, u16 *regs)
+{
+	int i;
+
+	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
+		if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
+			dev_info(&client->dev, "failed fp\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+				 u32 config)
+{
+	struct s2250 *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int vidsys;
+
+	vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
+	if (input == 0) {
+		/* composite */
+		write_reg_fp(client, 0x20, 0x020 | vidsys);
+		write_reg_fp(client, 0x21, 0x662);
+		write_reg_fp(client, 0x140, 0x060);
+	} else if (input == 1) {
+		/* S-Video */
+		write_reg_fp(client, 0x20, 0x040 | vidsys);
+		write_reg_fp(client, 0x21, 0x666);
+		write_reg_fp(client, 0x140, 0x060);
+	} else {
+		return -EINVAL;
+	}
+	state->input = input;
+	return 0;
+}
+
+static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct s2250 *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u16 vidsource;
+
+	vidsource = (state->input == 1) ? 0x040 : 0x020;
+	if (norm & V4L2_STD_625_50) {
+		write_regs_fp(client, vid_regs_fp);
+		write_regs_fp(client, vid_regs_fp_pal);
+		write_reg_fp(client, 0x20, vidsource);
+	} else {
+		write_regs_fp(client, vid_regs_fp);
+		write_reg_fp(client, 0x20, vidsource | 1);
+	}
+	state->std = norm;
+	return 0;
+}
+
+static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
+	u16 oldvalue;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
+		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
+			     ctrl->val | (oldvalue & ~0xff));
+		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
+		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
+			     ctrl->val | (oldvalue & ~0xff));
+		write_reg_fp(client, 0x140, 0x60);
+		break;
+	case V4L2_CID_CONTRAST:
+		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
+		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
+			     ctrl->val | (oldvalue & ~0x3f));
+		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
+		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
+			     ctrl->val | (oldvalue & ~0x3f));
+		write_reg_fp(client, 0x140, 0x60);
+		break;
+	case V4L2_CID_SATURATION:
+		write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int s2250_s_mbus_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *fmt)
+{
+	struct s2250 *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (fmt->height < 640) {
+		write_reg_fp(client, 0x12b, state->reg12b_val | 0x400);
+		write_reg_fp(client, 0x140, 0x060);
+	} else {
+		write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400);
+		write_reg_fp(client, 0x140, 0x060);
+	}
+	return 0;
+}
+
+static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+				 u32 config)
+{
+	struct s2250 *state = to_state(sd);
+
+	switch (input) {
+	case 0:
+		write_reg(state->audio, 0x08, 0x02); /* Line In */
+		break;
+	case 1:
+		write_reg(state->audio, 0x08, 0x04); /* Mic */
+		break;
+	case 2:
+		write_reg(state->audio, 0x08, 0x05); /* Mic Boost */
+		break;
+	default:
+		return -EINVAL;
+	}
+	state->audio_input = input;
+	return 0;
+}
+
+
+static int s2250_log_status(struct v4l2_subdev *sd)
+{
+	struct s2250 *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" :
+					state->std == V4L2_STD_PAL ? "PAL" :
+					state->std == V4L2_STD_SECAM ? "SECAM" :
+					"unknown");
+	v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" :
+					state->input == 1 ? "S-video" :
+					"error");
+	v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" :
+					state->audio_input == 1 ? "Mic" :
+					state->audio_input == 2 ? "Mic Boost" :
+					"error");
+	return v4l2_ctrl_subdev_log_status(sd);
+}
+
+/* --------------------------------------------------------------------------*/
+
+static const struct v4l2_ctrl_ops s2250_ctrl_ops = {
+	.s_ctrl = s2250_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops s2250_core_ops = {
+	.log_status = s2250_log_status,
+};
+
+static const struct v4l2_subdev_audio_ops s2250_audio_ops = {
+	.s_routing = s2250_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops s2250_video_ops = {
+	.s_std = s2250_s_std,
+	.s_routing = s2250_s_video_routing,
+	.s_mbus_fmt = s2250_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_ops s2250_ops = {
+	.core = &s2250_core_ops,
+	.audio = &s2250_audio_ops,
+	.video = &s2250_video_ops,
+};
+
+/* --------------------------------------------------------------------------*/
+
+static int s2250_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct i2c_client *audio;
+	struct i2c_adapter *adapter = client->adapter;
+	struct s2250 *state;
+	struct v4l2_subdev *sd;
+	u8 *data;
+	struct go7007 *go = i2c_get_adapdata(adapter);
+	struct go7007_usb *usb = go->hpi_context;
+
+	audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
+	if (audio == NULL)
+		return -ENOMEM;
+
+	state = kzalloc(sizeof(struct s2250), GFP_KERNEL);
+	if (state == NULL) {
+		i2c_unregister_device(audio);
+		return -ENOMEM;
+	}
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &s2250_ops);
+
+	v4l2_info(sd, "initializing %s at address 0x%x on %s\n",
+	       "Sensoray 2250/2251", client->addr, client->adapter->name);
+
+	v4l2_ctrl_handler_init(&state->hdl, 4);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 4094, 1, 2070);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_HUE, -512, 511, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+
+	state->std = V4L2_STD_NTSC;
+	state->brightness = 50;
+	state->contrast = 50;
+	state->saturation = 50;
+	state->hue = 0;
+	state->audio = audio;
+
+	/* initialize the audio */
+	if (write_regs(audio, aud_regs) < 0) {
+		dev_err(&client->dev, "error initializing audio\n");
+		goto fail;
+	}
+
+	if (write_regs(client, vid_regs) < 0) {
+		dev_err(&client->dev, "error initializing decoder\n");
+		goto fail;
+	}
+	if (write_regs_fp(client, vid_regs_fp) < 0) {
+		dev_err(&client->dev, "error initializing decoder\n");
+		goto fail;
+	}
+	/* set default channel */
+	/* composite */
+	write_reg_fp(client, 0x20, 0x020 | 1);
+	write_reg_fp(client, 0x21, 0x662);
+	write_reg_fp(client, 0x140, 0x060);
+
+	/* set default audio input */
+	state->audio_input = 0;
+	write_reg(client, 0x08, 0x02); /* Line In */
+
+	if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
+		data = kzalloc(16, GFP_KERNEL);
+		if (data != NULL) {
+			int rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
+						       data, 16, 1);
+
+			if (rc > 0) {
+				u8 mask;
+
+				data[0] = 0;
+				mask = 1<<5;
+				data[0] &= ~mask;
+				data[1] |= mask;
+				go7007_usb_vendor_request(go, 0x40, 0,
+							  (data[1]<<8)
+							  + data[1],
+							  data, 16, 0);
+			}
+			kfree(data);
+		}
+		mutex_unlock(&usb->i2c_lock);
+	}
+
+	v4l2_info(sd, "initialized successfully\n");
+	return 0;
+
+fail:
+	i2c_unregister_device(audio);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return -EIO;
+}
+
+static int s2250_remove(struct i2c_client *client)
+{
+	struct s2250 *state = to_state(i2c_get_clientdata(client));
+
+	v4l2_device_unregister_subdev(&state->sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+static const struct i2c_device_id s2250_id[] = {
+	{ "s2250", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, s2250_id);
+
+static struct i2c_driver s2250_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "s2250",
+	},
+	.probe		= s2250_probe,
+	.remove		= s2250_remove,
+	.id_table	= s2250_id,
+};
+
+module_i2c_driver(s2250_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/go7007/snd-go7007.c linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/snd-go7007.c
--- linux-libre-3.16-gnu/drivers/media/usb/go7007/snd-go7007.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/go7007/snd-go7007.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+#include "go7007-priv.h"
+
+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;
+
+module_param_array(index, int, NULL, 0444);
+module_param_array(id, charp, NULL, 0444);
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the go7007 audio driver");
+MODULE_PARM_DESC(id, "ID string for the go7007 audio driver");
+MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver");
+
+struct go7007_snd {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *substream;
+	spinlock_t lock;
+	int w_idx;
+	int hw_ptr;
+	int avail;
+	int capturing;
+};
+
+static struct snd_pcm_hardware go7007_snd_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_48000,
+	.rate_min		= 48000,
+	.rate_max		= 48000,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.buffer_bytes_max	= (128*1024),
+	.period_bytes_min	= 4096,
+	.period_bytes_max	= (128*1024),
+	.periods_min		= 1,
+	.periods_max		= 32,
+};
+
+static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length)
+{
+	struct go7007_snd *gosnd = go->snd_context;
+	struct snd_pcm_runtime *runtime = gosnd->substream->runtime;
+	int frames = bytes_to_frames(runtime, length);
+
+	spin_lock(&gosnd->lock);
+	gosnd->hw_ptr += frames;
+	if (gosnd->hw_ptr >= runtime->buffer_size)
+		gosnd->hw_ptr -= runtime->buffer_size;
+	gosnd->avail += frames;
+	spin_unlock(&gosnd->lock);
+	if (gosnd->w_idx + length > runtime->dma_bytes) {
+		int cpy = runtime->dma_bytes - gosnd->w_idx;
+
+		memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy);
+		length -= cpy;
+		buf += cpy;
+		gosnd->w_idx = 0;
+	}
+	memcpy(runtime->dma_area + gosnd->w_idx, buf, length);
+	gosnd->w_idx += length;
+	spin_lock(&gosnd->lock);
+	if (gosnd->avail < runtime->period_size) {
+		spin_unlock(&gosnd->lock);
+		return;
+	}
+	gosnd->avail -= runtime->period_size;
+	spin_unlock(&gosnd->lock);
+	if (gosnd->capturing)
+		snd_pcm_period_elapsed(gosnd->substream);
+}
+
+static int go7007_snd_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *hw_params)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+	unsigned int bytes;
+
+	bytes = params_buffer_bytes(hw_params);
+	if (substream->runtime->dma_bytes > 0)
+		vfree(substream->runtime->dma_area);
+	substream->runtime->dma_bytes = 0;
+	substream->runtime->dma_area = vmalloc(bytes);
+	if (substream->runtime->dma_area == NULL)
+		return -ENOMEM;
+	substream->runtime->dma_bytes = bytes;
+	go->audio_deliver = parse_audio_stream_data;
+	return 0;
+}
+
+static int go7007_snd_hw_free(struct snd_pcm_substream *substream)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+
+	go->audio_deliver = NULL;
+	if (substream->runtime->dma_bytes > 0)
+		vfree(substream->runtime->dma_area);
+	substream->runtime->dma_bytes = 0;
+	return 0;
+}
+
+static int go7007_snd_capture_open(struct snd_pcm_substream *substream)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+	struct go7007_snd *gosnd = go->snd_context;
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&gosnd->lock, flags);
+	if (gosnd->substream == NULL) {
+		gosnd->substream = substream;
+		substream->runtime->hw = go7007_snd_capture_hw;
+		r = 0;
+	} else
+		r = -EBUSY;
+	spin_unlock_irqrestore(&gosnd->lock, flags);
+	return r;
+}
+
+static int go7007_snd_capture_close(struct snd_pcm_substream *substream)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+	struct go7007_snd *gosnd = go->snd_context;
+
+	gosnd->substream = NULL;
+	return 0;
+}
+
+static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+	struct go7007_snd *gosnd = go->snd_context;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* Just set a flag to indicate we should signal ALSA when
+		 * sound comes in */
+		gosnd->capturing = 1;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+		gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
+		gosnd->capturing = 0;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct go7007 *go = snd_pcm_substream_chip(substream);
+	struct go7007_snd *gosnd = go->snd_context;
+
+	return gosnd->hw_ptr;
+}
+
+static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream,
+					unsigned long offset)
+{
+	return vmalloc_to_page(substream->runtime->dma_area + offset);
+}
+
+static struct snd_pcm_ops go7007_snd_capture_ops = {
+	.open		= go7007_snd_capture_open,
+	.close		= go7007_snd_capture_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= go7007_snd_hw_params,
+	.hw_free	= go7007_snd_hw_free,
+	.prepare	= go7007_snd_pcm_prepare,
+	.trigger	= go7007_snd_pcm_trigger,
+	.pointer	= go7007_snd_pcm_pointer,
+	.page		= go7007_snd_pcm_page,
+};
+
+static int go7007_snd_free(struct snd_device *device)
+{
+	struct go7007 *go = device->device_data;
+
+	kfree(go->snd_context);
+	go->snd_context = NULL;
+	return 0;
+}
+
+static struct snd_device_ops go7007_snd_device_ops = {
+	.dev_free	= go7007_snd_free,
+};
+
+int go7007_snd_init(struct go7007 *go)
+{
+	static int dev;
+	struct go7007_snd *gosnd;
+	int ret = 0;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+	gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL);
+	if (gosnd == NULL)
+		return -ENOMEM;
+	spin_lock_init(&gosnd->lock);
+	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
+	gosnd->capturing = 0;
+	ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0,
+			   &gosnd->card);
+	if (ret < 0) {
+		kfree(gosnd);
+		return ret;
+	}
+	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
+			&go7007_snd_device_ops);
+	if (ret < 0) {
+		kfree(gosnd);
+		return ret;
+	}
+	ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
+	if (ret < 0) {
+		snd_card_free(gosnd->card);
+		kfree(gosnd);
+		return ret;
+	}
+	strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
+	strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
+	strlcpy(gosnd->card->longname, gosnd->card->shortname,
+			sizeof(gosnd->card->longname));
+
+	gosnd->pcm->private_data = go;
+	snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&go7007_snd_capture_ops);
+
+	ret = snd_card_register(gosnd->card);
+	if (ret < 0) {
+		snd_card_free(gosnd->card);
+		kfree(gosnd);
+		return ret;
+	}
+
+	gosnd->substream = NULL;
+	go->snd_context = gosnd;
+	v4l2_device_get(&go->v4l2_dev);
+	++dev;
+
+	return 0;
+}
+EXPORT_SYMBOL(go7007_snd_init);
+
+int go7007_snd_remove(struct go7007 *go)
+{
+	struct go7007_snd *gosnd = go->snd_context;
+
+	snd_card_disconnect(gosnd->card);
+	snd_card_free_when_closed(gosnd->card);
+	v4l2_device_put(&go->v4l2_dev);
+	return 0;
+}
+EXPORT_SYMBOL(go7007_snd_remove);
+
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/autogain_functions.c linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/autogain_functions.c
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/autogain_functions.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/autogain_functions.c	2014-09-28 17:29:07.000000000 -0400
@@ -121,9 +121,9 @@ int gspca_coarse_grained_expo_autogain(
 	orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
 	orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
 
-	gain_low  = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+	gain_low  = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
 		    5 * 2 + gspca_dev->gain->minimum;
-	gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+	gain_high = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
 		    5 * 4 + gspca_dev->gain->minimum;
 
 	/* If we are of a multiple of deadzone, do multiple steps to reach the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/gspca.c linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/gspca.c
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/gspca.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/gspca.c	2014-09-28 17:29:07.000000000 -0400
@@ -603,10 +603,13 @@ static void gspca_stream_off(struct gspc
 }
 
 /*
- * look for an input transfer endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting.
+ *
+ * If xfer_ep is invalid, return the first valid ep found, otherwise
+ * look for exactly the ep with address equal to xfer_ep.
  */
 static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
-					  int xfer)
+					  int xfer, int xfer_ep)
 {
 	struct usb_host_endpoint *ep;
 	int i, attr;
@@ -616,7 +619,8 @@ static struct usb_host_endpoint *alt_xfe
 		attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 		if (attr == xfer
 		    && ep->desc.wMaxPacketSize != 0
-		    && usb_endpoint_dir_in(&ep->desc))
+		    && usb_endpoint_dir_in(&ep->desc)
+		    && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep))
 			return ep;
 	}
 	return NULL;
@@ -689,7 +693,8 @@ static int build_isoc_ep_tb(struct gspca
 		found = 0;
 		for (j = 0; j < nbalt; j++) {
 			ep = alt_xfer(&intf->altsetting[j],
-				      USB_ENDPOINT_XFER_ISOC);
+				      USB_ENDPOINT_XFER_ISOC,
+				      gspca_dev->xfer_ep);
 			if (ep == NULL)
 				continue;
 			if (ep->desc.bInterval == 0) {
@@ -862,7 +867,8 @@ static int gspca_init_transfer(struct gs
 	/* if bulk or the subdriver forced an altsetting, get the endpoint */
 	if (gspca_dev->alt != 0) {
 		gspca_dev->alt--;	/* (previous version compatibility) */
-		ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+		ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer,
+			      gspca_dev->xfer_ep);
 		if (ep == NULL) {
 			pr_err("bad altsetting %d\n", gspca_dev->alt);
 			return -EIO;
@@ -904,7 +910,8 @@ static int gspca_init_transfer(struct gs
 		if (!gspca_dev->cam.no_urb_create) {
 			PDEBUG(D_STREAM, "init transfer alt %d", alt);
 			ret = create_urbs(gspca_dev,
-				alt_xfer(&intf->altsetting[alt], xfer));
+				alt_xfer(&intf->altsetting[alt], xfer,
+					 gspca_dev->xfer_ep));
 			if (ret < 0) {
 				destroy_urbs(gspca_dev);
 				goto out;
@@ -1102,8 +1109,8 @@ static int vidioc_g_fmt_vid_cap(struct f
 	struct gspca_dev *gspca_dev = video_drvdata(file);
 
 	fmt->fmt.pix = gspca_dev->pixfmt;
-	/* some drivers use priv internally, zero it before giving it to
-	   userspace */
+	/* some drivers use priv internally, zero it before giving it back to
+	   the core */
 	fmt->fmt.pix.priv = 0;
 	return 0;
 }
@@ -1139,8 +1146,8 @@ static int try_fmt_vid_cap(struct gspca_
 		fmt->fmt.pix.height = h;
 		gspca_dev->sd_desc->try_fmt(gspca_dev, fmt);
 	}
-	/* some drivers use priv internally, zero it before giving it to
-	   userspace */
+	/* some drivers use priv internally, zero it before giving it back to
+	   the core */
 	fmt->fmt.pix.priv = 0;
 	return mode;			/* used when s_fmt */
 }
@@ -2030,6 +2037,7 @@ int gspca_dev_probe2(struct usb_interfac
 	}
 	gspca_dev->dev = dev;
 	gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
+	gspca_dev->xfer_ep = -1;
 
 	/* check if any audio device */
 	if (dev->actconfig->desc.bNumInterfaces != 1) {
@@ -2058,7 +2066,6 @@ int gspca_dev_probe2(struct usb_interfac
 	gspca_dev->vdev = gspca_template;
 	gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
 	video_set_drvdata(&gspca_dev->vdev, gspca_dev);
-	set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
 	gspca_dev->module = module;
 	gspca_dev->present = 1;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/gspca.h linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/gspca.h
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/gspca.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/gspca.h	2014-09-28 17:29:07.000000000 -0400
@@ -205,6 +205,7 @@ struct gspca_dev {
 	char memory;			/* memory type (V4L2_MEMORY_xxx) */
 	__u8 iface;			/* USB interface number */
 	__u8 alt;			/* USB alternate setting */
+	int xfer_ep;			/* USB transfer endpoint address */
 	u8 audio;			/* presence of audio device */
 
 	/* (*) These variables are proteced by both usb_lock and queue_lock,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/kinect.c linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/kinect.c
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/kinect.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/kinect.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,8 @@ MODULE_AUTHOR("Antonio Ospite <ospite@st
 MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+static bool depth_mode;
+
 struct pkt_hdr {
 	uint8_t magic[2];
 	uint8_t pad;
@@ -73,6 +75,14 @@ struct sd {
 
 #define FPS_HIGH       0x0100
 
+static const struct v4l2_pix_format depth_camera_mode[] = {
+	{640, 480, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
+	 .bytesperline = 640 * 10 / 8,
+	 .sizeimage =  640 * 480 * 10 / 8,
+	 .colorspace = V4L2_COLORSPACE_SRGB,
+	 .priv = MODE_640x488 | FORMAT_Y10B},
+};
+
 static const struct v4l2_pix_format video_camera_mode[] = {
 	{640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
 	 .bytesperline = 640,
@@ -219,7 +229,7 @@ static int write_register(struct gspca_d
 }
 
 /* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
+static int sd_config_video(struct gspca_dev *gspca_dev,
 		     const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -227,8 +237,6 @@ static int sd_config(struct gspca_dev *g
 
 	sd->cam_tag = 0;
 
-	/* Only video stream is supported for now,
-	 * which has stream flag = 0x80 */
 	sd->stream_flag = 0x80;
 
 	cam = &gspca_dev->cam;
@@ -236,6 +244,8 @@ static int sd_config(struct gspca_dev *g
 	cam->cam_mode = video_camera_mode;
 	cam->nmodes = ARRAY_SIZE(video_camera_mode);
 
+	gspca_dev->xfer_ep = 0x81;
+
 #if 0
 	/* Setting those values is not needed for video stream */
 	cam->npkt = 15;
@@ -245,6 +255,26 @@ static int sd_config(struct gspca_dev *g
 	return 0;
 }
 
+static int sd_config_depth(struct gspca_dev *gspca_dev,
+		     const struct usb_device_id *id)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct cam *cam;
+
+	sd->cam_tag = 0;
+
+	sd->stream_flag = 0x70;
+
+	cam = &gspca_dev->cam;
+
+	cam->cam_mode = depth_camera_mode;
+	cam->nmodes = ARRAY_SIZE(depth_camera_mode);
+
+	gspca_dev->xfer_ep = 0x82;
+
+	return 0;
+}
+
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
@@ -253,7 +283,7 @@ static int sd_init(struct gspca_dev *gsp
 	return 0;
 }
 
-static int sd_start(struct gspca_dev *gspca_dev)
+static int sd_start_video(struct gspca_dev *gspca_dev)
 {
 	int mode;
 	uint8_t fmt_reg, fmt_val;
@@ -325,12 +355,39 @@ static int sd_start(struct gspca_dev *gs
 	return 0;
 }
 
-static void sd_stopN(struct gspca_dev *gspca_dev)
+static int sd_start_depth(struct gspca_dev *gspca_dev)
+{
+	/* turn off IR-reset function */
+	write_register(gspca_dev, 0x105, 0x00);
+
+	/* reset depth stream */
+	write_register(gspca_dev, 0x06, 0x00);
+	/* Depth Stream Format 0x03: 11 bit stream | 0x02: 10 bit */
+	write_register(gspca_dev, 0x12, 0x02);
+	/* Depth Stream Resolution 1: standard (640x480) */
+	write_register(gspca_dev, 0x13, 0x01);
+	/* Depth Framerate / 0x1e (30): 30 fps */
+	write_register(gspca_dev, 0x14, 0x1e);
+	/* Depth Stream Control  / 2: Open Depth Stream */
+	write_register(gspca_dev, 0x06, 0x02);
+	/* disable depth hflip / LSB = 0: Smoothing Disabled */
+	write_register(gspca_dev, 0x17, 0x00);
+
+	return 0;
+}
+
+static void sd_stopN_video(struct gspca_dev *gspca_dev)
 {
 	/* reset video stream */
 	write_register(gspca_dev, 0x05, 0x00);
 }
 
+static void sd_stopN_depth(struct gspca_dev *gspca_dev)
+{
+	/* reset depth stream */
+	write_register(gspca_dev, 0x06, 0x00);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -366,12 +423,24 @@ static void sd_pkt_scan(struct gspca_dev
 }
 
 /* sub-driver description */
-static const struct sd_desc sd_desc = {
+static const struct sd_desc sd_desc_video = {
 	.name      = MODULE_NAME,
-	.config    = sd_config,
+	.config    = sd_config_video,
 	.init      = sd_init,
-	.start     = sd_start,
-	.stopN     = sd_stopN,
+	.start     = sd_start_video,
+	.stopN     = sd_stopN_video,
+	.pkt_scan  = sd_pkt_scan,
+	/*
+	.get_streamparm = sd_get_streamparm,
+	.set_streamparm = sd_set_streamparm,
+	*/
+};
+static const struct sd_desc sd_desc_depth = {
+	.name      = MODULE_NAME,
+	.config    = sd_config_depth,
+	.init      = sd_init,
+	.start     = sd_start_depth,
+	.stopN     = sd_stopN_depth,
 	.pkt_scan  = sd_pkt_scan,
 	/*
 	.get_streamparm = sd_get_streamparm,
@@ -391,8 +460,12 @@ MODULE_DEVICE_TABLE(usb, device_table);
 /* -- device connect -- */
 static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
-				THIS_MODULE);
+	if (depth_mode)
+		return gspca_dev_probe(intf, id, &sd_desc_depth,
+				       sizeof(struct sd), THIS_MODULE);
+	else
+		return gspca_dev_probe(intf, id, &sd_desc_video,
+				       sizeof(struct sd), THIS_MODULE);
 }
 
 static struct usb_driver sd_driver = {
@@ -408,3 +481,6 @@ static struct usb_driver sd_driver = {
 };
 
 module_usb_driver(sd_driver);
+
+module_param(depth_mode, bool, 0644);
+MODULE_PARM_DESC(depth_mode, "0=video 1=depth");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/pac7302.c linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/pac7302.c
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/pac7302.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/pac7302.c	2014-09-28 17:29:07.000000000 -0400
@@ -394,9 +394,9 @@ static void setbrightcont(struct gspca_d
 	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
 	for (i = 0; i < 10; i++) {
 		v = max[i];
-		v += (sd->brightness->val - sd->brightness->maximum)
-			* 150 / sd->brightness->maximum; /* 200 ? */
-		v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
+		v += (sd->brightness->val - (s32)sd->brightness->maximum)
+			* 150 / (s32)sd->brightness->maximum; /* 200 ? */
+		v -= delta[i] * sd->contrast->val / (s32)sd->contrast->maximum;
 		if (v < 0)
 			v = 0;
 		else if (v > 0xff)
@@ -419,7 +419,7 @@ static void setcolors(struct gspca_dev *
 	reg_w(gspca_dev, 0x11, 0x01);
 	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
 	for (i = 0; i < 9; i++) {
-		v = a[i] * sd->saturation->val / sd->saturation->maximum;
+		v = a[i] * sd->saturation->val / (s32)sd->saturation->maximum;
 		v += b[i];
 		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
 		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/gspca/sonixb.c linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/sonixb.c
--- linux-libre-3.16-gnu/drivers/media/usb/gspca/sonixb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/gspca/sonixb.c	2014-09-28 17:29:07.000000000 -0400
@@ -913,7 +913,7 @@ static void do_autogain(struct gspca_dev
 				desired_avg_lum, deadzone))
 			sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
 	} else {
-		int gain_knee = gspca_dev->gain->maximum * 9 / 10;
+		int gain_knee = (s32)gspca_dev->gain->maximum * 9 / 10;
 		if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
 				deadzone, gain_knee, sd->exposure_knee))
 			sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/hdpvr/hdpvr-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/hdpvr/hdpvr-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/hdpvr/hdpvr-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/hdpvr/hdpvr-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1022,14 +1022,13 @@ static int vidioc_g_fmt_vid_cap(struct f
 	f->fmt.pix.pixelformat	= V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage	= dev->bulk_in_size;
 	f->fmt.pix.bytesperline	= 0;
-	f->fmt.pix.priv		= 0;
 	if (f->fmt.pix.width == 720) {
 		/* SDTV formats */
 		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 		f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 	} else {
 		/* HDTV formats */
-		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE240M;
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
 		f->fmt.pix.field = V4L2_FIELD_NONE;
 	}
 	return 0;
@@ -1240,7 +1239,6 @@ int hdpvr_register_videodev(struct hdpvr
 	strcpy(dev->video_dev->name, "Hauppauge HD PVR");
 	dev->video_dev->v4l2_dev = &dev->v4l2_dev;
 	video_set_drvdata(dev->video_dev, dev);
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->video_dev->flags);
 
 	res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
 	if (res < 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ source "drivers/media/usb/hdpvr/Kconfig"
 source "drivers/media/usb/tlg2300/Kconfig"
 source "drivers/media/usb/usbvision/Kconfig"
 source "drivers/media/usb/stk1160/Kconfig"
+source "drivers/media/usb/go7007/Kconfig"
 endif
 
 if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
@@ -52,5 +53,11 @@ if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG
 source "drivers/media/usb/em28xx/Kconfig"
 endif
 
+if MEDIA_SDR_SUPPORT
+	comment "Software defined radio USB devices"
+source "drivers/media/usb/msi2500/Kconfig"
+source "drivers/media/usb/airspy/Kconfig"
+endif
+
 endif #MEDIA_USB_SUPPORT
 endif #USB
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/Makefile linux-libre-3.17-rc7-gnu/drivers/media/usb/Makefile
--- linux-libre-3.16-gnu/drivers/media/usb/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,8 @@ obj-y += zr364xx/ stkwebcam/ s2255/
 obj-$(CONFIG_USB_VIDEO_CLASS)	+= uvc/
 obj-$(CONFIG_USB_GSPCA)         += gspca/
 obj-$(CONFIG_USB_PWC)           += pwc/
+obj-$(CONFIG_USB_MSI2500)       += msi2500/
+obj-$(CONFIG_USB_AIRSPY)        += airspy/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
 obj-$(CONFIG_VIDEO_HDPVR)	+= hdpvr/
@@ -20,3 +22,4 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_TM6000) += tm6000/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_USBTV) += usbtv/
+obj-$(CONFIG_VIDEO_GO7007) += go7007/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/msi2500/Kconfig linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/Kconfig
--- linux-libre-3.16-gnu/drivers/media/usb/msi2500/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,5 @@
+config USB_MSI2500
+	tristate "Mirics MSi2500"
+	depends on VIDEO_V4L2 && SPI
+	select VIDEOBUF2_VMALLOC
+	select MEDIA_TUNER_MSI001
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/msi2500/Makefile linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/Makefile
--- linux-libre-3.16-gnu/drivers/media/usb/msi2500/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_MSI2500)             += msi2500.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/msi2500/msi2500.c linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/msi2500.c
--- linux-libre-3.16-gnu/drivers/media/usb/msi2500/msi2500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/msi2500/msi2500.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1336 @@
+/*
+ * Mirics MSi3101 SDR Dongle driver
+ *
+ * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * That driver is somehow based of pwc driver:
+ *  (C) 1999-2004 Nemosoft Unv.
+ *  (C) 2004-2006 Luc Saillard (luc@saillard.org)
+ *  (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <linux/usb.h>
+#include <media/videobuf2-vmalloc.h>
+#include <linux/spi/spi.h>
+
+static bool msi2500_emulated_fmt;
+module_param_named(emulated_formats, msi2500_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
+/*
+ *   iConfiguration          0
+ *     bInterfaceNumber        0
+ *     bAlternateSetting       1
+ *     bNumEndpoints           1
+ *       bEndpointAddress     0x81  EP 1 IN
+ *       bmAttributes            1
+ *         Transfer Type            Isochronous
+ *       wMaxPacketSize     0x1400  3x 1024 bytes
+ *       bInterval               1
+ */
+#define MAX_ISO_BUFS            (8)
+#define ISO_FRAMES_PER_DESC     (8)
+#define ISO_MAX_FRAME_SIZE      (3 * 1024)
+#define ISO_BUFFER_SIZE         (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+#define MAX_ISOC_ERRORS         20
+
+/*
+ * TODO: These formats should be moved to V4L2 API. Formats are currently
+ * disabled from formats[] table, not visible to userspace.
+ */
+ /* signed 12-bit */
+#define MSI2500_PIX_FMT_SDR_S12         v4l2_fourcc('D', 'S', '1', '2')
+/* Mirics MSi2500 format 384 */
+#define MSI2500_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4')
+
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.tuner = 0,
+		.type = V4L2_TUNER_ADC,
+		.index = 0,
+		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow   =  1200000,
+		.rangehigh  = 15000000,
+	},
+};
+
+/* stream formats */
+struct msi2500_format {
+	char	*name;
+	u32	pixelformat;
+	u32	buffersize;
+};
+
+/* format descriptions for capture and preview */
+static struct msi2500_format formats[] = {
+	{
+		.name		= "Complex S8",
+		.pixelformat	= V4L2_SDR_FMT_CS8,
+		.buffersize	= 3 * 1008,
+#if 0
+	}, {
+		.name		= "10+2-bit signed",
+		.pixelformat	= MSI2500_PIX_FMT_SDR_MSI2500_384,
+	}, {
+		.name		= "12-bit signed",
+		.pixelformat	= MSI2500_PIX_FMT_SDR_S12,
+#endif
+	}, {
+		.name		= "Complex S14LE",
+		.pixelformat	= V4L2_SDR_FMT_CS14LE,
+		.buffersize	= 3 * 1008,
+	}, {
+		.name		= "Complex U8 (emulated)",
+		.pixelformat	= V4L2_SDR_FMT_CU8,
+		.buffersize	= 3 * 1008,
+	}, {
+		.name		= "Complex U16LE (emulated)",
+		.pixelformat	=  V4L2_SDR_FMT_CU16LE,
+		.buffersize	= 3 * 1008,
+	},
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct msi2500_frame_buf {
+	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct list_head list;
+};
+
+struct msi2500_state {
+	struct video_device vdev;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_subdev *v4l2_subdev;
+	struct spi_master *master;
+
+	/* videobuf2 queue and queued buffers list */
+	struct vb2_queue vb_queue;
+	struct list_head queued_bufs;
+	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+
+	/* Note if taking both locks v4l2_lock must always be locked first! */
+	struct mutex v4l2_lock;      /* Protects everything else */
+	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
+
+	/* Pointer to our usb_device, will be NULL after unplug */
+	struct usb_device *udev; /* Both mutexes most be hold when setting! */
+
+	unsigned int f_adc;
+	u32 pixelformat;
+	u32 buffersize;
+	unsigned int num_formats;
+
+	unsigned int isoc_errors; /* number of contiguous ISOC errors */
+	unsigned int vb_full; /* vb is full and packets dropped */
+
+	struct urb *urbs[MAX_ISO_BUFS];
+
+	/* Controls */
+	struct v4l2_ctrl_handler hdl;
+
+	u32 next_sample; /* for track lost packets */
+	u32 sample; /* for sample rate calc */
+	unsigned long jiffies_next;
+	unsigned int sample_ctrl_bit[4];
+};
+
+/* Private functions */
+static struct msi2500_frame_buf *msi2500_get_next_fill_buf(
+		struct msi2500_state *s)
+{
+	unsigned long flags = 0;
+	struct msi2500_frame_buf *buf = NULL;
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	if (list_empty(&s->queued_bufs))
+		goto leave;
+
+	buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf, list);
+	list_del(&buf->list);
+leave:
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	return buf;
+}
+
+/*
+ * +===========================================================================
+ * |   00-1023 | USB packet type '504'
+ * +===========================================================================
+ * |   00-  03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * |   04-  15 | garbage
+ * +---------------------------------------------------------------------------
+ * |   16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 8-bit sample
+ * 504 * 2 = 1008 samples
+ *
+ *
+ * +===========================================================================
+ * |   00-1023 | USB packet type '384'
+ * +===========================================================================
+ * |   00-  03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * |   04-  15 | garbage
+ * +---------------------------------------------------------------------------
+ * |   16- 175 | samples
+ * +---------------------------------------------------------------------------
+ * |  176- 179 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * |  180- 339 | samples
+ * +---------------------------------------------------------------------------
+ * |  340- 343 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * |  344- 503 | samples
+ * +---------------------------------------------------------------------------
+ * |  504- 507 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * |  508- 667 | samples
+ * +---------------------------------------------------------------------------
+ * |  668- 671 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * |  672- 831 | samples
+ * +---------------------------------------------------------------------------
+ * |  832- 835 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * |  836- 995 | samples
+ * +---------------------------------------------------------------------------
+ * |  996- 999 | control bits for previous samples
+ * +---------------------------------------------------------------------------
+ * | 1000-1023 | garbage
+ * +---------------------------------------------------------------------------
+ *
+ * Bytes 4 - 7 could have some meaning?
+ *
+ * Control bits for previous samples is 32-bit field, containing 16 x 2-bit
+ * numbers. This results one 2-bit number for 8 samples. It is likely used for
+ * for bit shifting sample by given bits, increasing actual sampling resolution.
+ * Number 2 (0b10) was never seen.
+ *
+ * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes
+ *
+ *
+ * +===========================================================================
+ * |   00-1023 | USB packet type '336'
+ * +===========================================================================
+ * |   00-  03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * |   04-  15 | garbage
+ * +---------------------------------------------------------------------------
+ * |   16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 12-bit sample
+ *
+ *
+ * +===========================================================================
+ * |   00-1023 | USB packet type '252'
+ * +===========================================================================
+ * |   00-  03 | sequence number of first sample in that USB packet
+ * +---------------------------------------------------------------------------
+ * |   04-  15 | garbage
+ * +---------------------------------------------------------------------------
+ * |   16-1023 | samples
+ * +---------------------------------------------------------------------------
+ * signed 14-bit sample
+ */
+
+static int msi2500_convert_stream(struct msi2500_state *s, u8 *dst, u8 *src,
+		unsigned int src_len)
+{
+	unsigned int i, j, transactions, dst_len = 0;
+	u32 sample[3];
+
+	/* There could be 1-3 1024 byte transactions per packet */
+	transactions = src_len / 1024;
+
+	for (i = 0; i < transactions; i++) {
+		sample[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 |
+				src[0] << 0;
+		if (i == 0 && s->next_sample != sample[0]) {
+			dev_dbg_ratelimited(&s->udev->dev,
+					"%d samples lost, %d %08x:%08x\n",
+					sample[0] - s->next_sample,
+					src_len, s->next_sample, sample[0]);
+		}
+
+		/*
+		 * Dump all unknown 'garbage' data - maybe we will discover
+		 * someday if there is something rational...
+		 */
+		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
+
+		src += 16; /* skip header */
+
+		switch (s->pixelformat) {
+		case V4L2_SDR_FMT_CU8: /* 504 x IQ samples */
+		{
+			s8 *s8src = (s8 *) src;
+			u8 *u8dst = (u8 *) dst;
+
+			for (j = 0; j < 1008; j++)
+				*u8dst++ = *s8src++ + 128;
+
+			src += 1008;
+			dst += 1008;
+			dst_len += 1008;
+			s->next_sample = sample[i] + 504;
+			break;
+		}
+		case  V4L2_SDR_FMT_CU16LE: /* 252 x IQ samples */
+		{
+			s16 *s16src = (s16 *) src;
+			u16 *u16dst = (u16 *) dst;
+			struct {signed int x:14; } se; /* sign extension */
+			unsigned int utmp;
+
+			for (j = 0; j < 1008; j += 2) {
+				/* sign extension from 14-bit to signed int */
+				se.x = *s16src++;
+				/* from signed int to unsigned int */
+				utmp = se.x + 8192;
+				/* from 14-bit to 16-bit */
+				*u16dst++ = utmp << 2 | utmp >> 12;
+			}
+
+			src += 1008;
+			dst += 1008;
+			dst_len += 1008;
+			s->next_sample = sample[i] + 252;
+			break;
+		}
+		case MSI2500_PIX_FMT_SDR_MSI2500_384: /* 384 x IQ samples */
+			/* Dump unknown 'garbage' data */
+			dev_dbg_ratelimited(&s->udev->dev,
+					"%*ph\n", 24, &src[1000]);
+			memcpy(dst, src, 984);
+			src += 984 + 24;
+			dst += 984;
+			dst_len += 984;
+			s->next_sample = sample[i] + 384;
+			break;
+		case V4L2_SDR_FMT_CS8:         /* 504 x IQ samples */
+			memcpy(dst, src, 1008);
+			src += 1008;
+			dst += 1008;
+			dst_len += 1008;
+			s->next_sample = sample[i] + 504;
+			break;
+		case MSI2500_PIX_FMT_SDR_S12:  /* 336 x IQ samples */
+			memcpy(dst, src, 1008);
+			src += 1008;
+			dst += 1008;
+			dst_len += 1008;
+			s->next_sample = sample[i] + 336;
+			break;
+		case V4L2_SDR_FMT_CS14LE:      /* 252 x IQ samples */
+			memcpy(dst, src, 1008);
+			src += 1008;
+			dst += 1008;
+			dst_len += 1008;
+			s->next_sample = sample[i] + 252;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* calculate sample rate and output it in 10 seconds intervals */
+	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+		#define MSECS 10000UL
+		unsigned int msecs = jiffies_to_msecs(jiffies -
+				s->jiffies_next + msecs_to_jiffies(MSECS));
+		unsigned int samples = s->next_sample - s->sample;
+
+		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		s->sample = s->next_sample;
+		dev_dbg(&s->udev->dev,
+				"size=%u samples=%u msecs=%u sample rate=%lu\n",
+				src_len, samples, msecs,
+				samples * 1000UL / msecs);
+	}
+
+	return dst_len;
+}
+
+/*
+ * This gets called for the Isochronous pipe (stream). This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void msi2500_isoc_handler(struct urb *urb)
+{
+	struct msi2500_state *s = (struct msi2500_state *)urb->context;
+	int i, flen, fstatus;
+	unsigned char *iso_buf = NULL;
+	struct msi2500_frame_buf *fbuf;
+
+	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
+			urb->status == -ESHUTDOWN)) {
+		dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n",
+				urb, urb->status == -ENOENT ? "" : "a");
+		return;
+	}
+
+	if (unlikely(urb->status != 0)) {
+		dev_dbg(&s->udev->dev,
+				"msi2500_isoc_handler() called with status %d\n",
+				urb->status);
+		/* Give up after a number of contiguous errors */
+		if (++s->isoc_errors > MAX_ISOC_ERRORS)
+			dev_dbg(&s->udev->dev,
+					"Too many ISOC errors, bailing out\n");
+		goto handler_end;
+	} else {
+		/* Reset ISOC error counter. We did get here, after all. */
+		s->isoc_errors = 0;
+	}
+
+	/* Compact data */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		void *ptr;
+
+		/* Check frame error */
+		fstatus = urb->iso_frame_desc[i].status;
+		if (unlikely(fstatus)) {
+			dev_dbg_ratelimited(&s->udev->dev,
+					"frame=%d/%d has error %d skipping\n",
+					i, urb->number_of_packets, fstatus);
+			continue;
+		}
+
+		/* Check if that frame contains data */
+		flen = urb->iso_frame_desc[i].actual_length;
+		if (unlikely(flen == 0))
+			continue;
+
+		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+		/* Get free framebuffer */
+		fbuf = msi2500_get_next_fill_buf(s);
+		if (unlikely(fbuf == NULL)) {
+			s->vb_full++;
+			dev_dbg_ratelimited(&s->udev->dev,
+					"videobuf is full, %d packets dropped\n",
+					s->vb_full);
+			continue;
+		}
+
+		/* fill framebuffer */
+		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+		flen = msi2500_convert_stream(s, ptr, iso_buf, flen);
+		vb2_set_plane_payload(&fbuf->vb, 0, flen);
+		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+	}
+
+handler_end:
+	i = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(i != 0))
+		dev_dbg(&s->udev->dev,
+				"Error (%d) re-submitting urb in msi2500_isoc_handler\n",
+				i);
+}
+
+static void msi2500_iso_stop(struct msi2500_state *s)
+{
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	/* Unlinking ISOC buffers one by one */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		if (s->urbs[i]) {
+			dev_dbg(&s->udev->dev, "Unlinking URB %p\n",
+					s->urbs[i]);
+			usb_kill_urb(s->urbs[i]);
+		}
+	}
+}
+
+static void msi2500_iso_free(struct msi2500_state *s)
+{
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	/* Freeing ISOC buffers one by one */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		if (s->urbs[i]) {
+			dev_dbg(&s->udev->dev, "Freeing URB\n");
+			if (s->urbs[i]->transfer_buffer) {
+				usb_free_coherent(s->udev,
+					s->urbs[i]->transfer_buffer_length,
+					s->urbs[i]->transfer_buffer,
+					s->urbs[i]->transfer_dma);
+			}
+			usb_free_urb(s->urbs[i]);
+			s->urbs[i] = NULL;
+		}
+	}
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static void msi2500_isoc_cleanup(struct msi2500_state *s)
+{
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	msi2500_iso_stop(s);
+	msi2500_iso_free(s);
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static int msi2500_isoc_init(struct msi2500_state *s)
+{
+	struct usb_device *udev;
+	struct urb *urb;
+	int i, j, ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	s->isoc_errors = 0;
+	udev = s->udev;
+
+	ret = usb_set_interface(s->udev, 0, 1);
+	if (ret)
+		return ret;
+
+	/* Allocate and init Isochronuous urbs */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+		if (urb == NULL) {
+			dev_err(&s->udev->dev,
+					"Failed to allocate urb %d\n", i);
+			msi2500_isoc_cleanup(s);
+			return -ENOMEM;
+		}
+		s->urbs[i] = urb;
+		dev_dbg(&s->udev->dev, "Allocated URB at 0x%p\n", urb);
+
+		urb->interval = 1;
+		urb->dev = udev;
+		urb->pipe = usb_rcvisocpipe(udev, 0x81);
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		urb->transfer_buffer = usb_alloc_coherent(udev, ISO_BUFFER_SIZE,
+				GFP_KERNEL, &urb->transfer_dma);
+		if (urb->transfer_buffer == NULL) {
+			dev_err(&s->udev->dev,
+					"Failed to allocate urb buffer %d\n",
+					i);
+			msi2500_isoc_cleanup(s);
+			return -ENOMEM;
+		}
+		urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+		urb->complete = msi2500_isoc_handler;
+		urb->context = s;
+		urb->start_frame = 0;
+		urb->number_of_packets = ISO_FRAMES_PER_DESC;
+		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
+		}
+	}
+
+	/* link */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		ret = usb_submit_urb(s->urbs[i], GFP_KERNEL);
+		if (ret) {
+			dev_err(&s->udev->dev,
+					"isoc_init() submit_urb %d failed with error %d\n",
+					i, ret);
+			msi2500_isoc_cleanup(s);
+			return ret;
+		}
+		dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]);
+	}
+
+	/* All is done... */
+	return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void msi2500_cleanup_queued_bufs(struct msi2500_state *s)
+{
+	unsigned long flags = 0;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	while (!list_empty(&s->queued_bufs)) {
+		struct msi2500_frame_buf *buf;
+
+		buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf,
+				 list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void msi2500_disconnect(struct usb_interface *intf)
+{
+	struct v4l2_device *v = usb_get_intfdata(intf);
+	struct msi2500_state *s =
+			container_of(v, struct msi2500_state, v4l2_dev);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->vb_queue_lock);
+	mutex_lock(&s->v4l2_lock);
+	/* No need to keep the urbs around after disconnection */
+	s->udev = NULL;
+	v4l2_device_disconnect(&s->v4l2_dev);
+	video_unregister_device(&s->vdev);
+	spi_unregister_master(s->master);
+	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&s->vb_queue_lock);
+
+	v4l2_device_put(&s->v4l2_dev);
+}
+
+static int msi2500_querycap(struct file *file, void *fh,
+		struct v4l2_capability *cap)
+{
+	struct msi2500_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+/* Videobuf2 operations */
+static int msi2500_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct msi2500_state *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+	/* Absolute min and max number of buffers available for mmap() */
+	*nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32);
+	*nplanes = 1;
+	sizes[0] = PAGE_ALIGN(s->buffersize);
+	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+			__func__, *nbuffers, sizes[0]);
+	return 0;
+}
+
+static void msi2500_buf_queue(struct vb2_buffer *vb)
+{
+	struct msi2500_state *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct msi2500_frame_buf *buf =
+			container_of(vb, struct msi2500_frame_buf, vb);
+	unsigned long flags = 0;
+
+	/* Check the device has not disconnected between prep and queuing */
+	if (unlikely(!s->udev)) {
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	spin_lock_irqsave(&s->queued_bufs_lock, flags);
+	list_add_tail(&buf->list, &s->queued_bufs);
+	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+#define CMD_WREG               0x41
+#define CMD_START_STREAMING    0x43
+#define CMD_STOP_STREAMING     0x45
+#define CMD_READ_UNKNOW        0x48
+
+#define msi2500_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+	char *_direction; \
+	if (_t & USB_DIR_IN) \
+		_direction = "<<<"; \
+	else \
+		_direction = ">>>"; \
+	dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+			"%s %*ph\n",  __func__, _t, _r, _v & 0xff, _v >> 8, \
+			_i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+			_l, _b); \
+}
+
+static int msi2500_ctrl_msg(struct msi2500_state *s, u8 cmd, u32 data)
+{
+	int ret;
+	u8 request = cmd;
+	u8 requesttype = USB_DIR_OUT | USB_TYPE_VENDOR;
+	u16 value = (data >> 0) & 0xffff;
+	u16 index = (data >> 16) & 0xffff;
+
+	msi2500_dbg_usb_control_msg(s->udev,
+			request, requesttype, value, index, NULL, 0);
+
+	ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0),
+			request, requesttype, value, index, NULL, 0, 2000);
+
+	if (ret)
+		dev_err(&s->udev->dev, "%s: failed %d, cmd %02x, data %04x\n",
+				__func__, ret, cmd, data);
+
+	return ret;
+};
+
+#define F_REF 24000000
+#define DIV_R_IN 2
+static int msi2500_set_usb_adc(struct msi2500_state *s)
+{
+	int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract;
+	u32 reg3, reg4, reg7;
+	struct v4l2_ctrl *bandwidth_auto;
+	struct v4l2_ctrl *bandwidth;
+
+	f_sr = s->f_adc;
+
+	/* set tuner, subdev, filters according to sampling rate */
+	bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+			V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
+	if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
+		bandwidth = v4l2_ctrl_find(&s->hdl,
+				V4L2_CID_RF_TUNER_BANDWIDTH);
+		v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
+	}
+
+	/* select stream format */
+	switch (s->pixelformat) {
+	case V4L2_SDR_FMT_CU8:
+		reg7 = 0x000c9407; /* 504 */
+		break;
+	case  V4L2_SDR_FMT_CU16LE:
+		reg7 = 0x00009407; /* 252 */
+		break;
+	case V4L2_SDR_FMT_CS8:
+		reg7 = 0x000c9407; /* 504 */
+		break;
+	case MSI2500_PIX_FMT_SDR_MSI2500_384:
+		reg7 = 0x0000a507; /* 384 */
+		break;
+	case MSI2500_PIX_FMT_SDR_S12:
+		reg7 = 0x00008507; /* 336 */
+		break;
+	case V4L2_SDR_FMT_CS14LE:
+		reg7 = 0x00009407; /* 252 */
+		break;
+	default:
+		reg7 = 0x000c9407; /* 504 */
+		break;
+	}
+
+	/*
+	 * Synthesizer config is just a educated guess...
+	 *
+	 * [7:0]   0x03, register address
+	 * [8]     1, power control
+	 * [9]     ?, power control
+	 * [12:10] output divider
+	 * [13]    0 ?
+	 * [14]    0 ?
+	 * [15]    fractional MSB, bit 20
+	 * [16:19] N
+	 * [23:20] ?
+	 * [24:31] 0x01
+	 *
+	 * output divider
+	 * val   div
+	 *   0     - (invalid)
+	 *   1     4
+	 *   2     6
+	 *   3     8
+	 *   4    10
+	 *   5    12
+	 *   6    14
+	 *   7    16
+	 *
+	 * VCO 202000000 - 720000000++
+	 */
+	reg3 = 0x01000303;
+	reg4 = 0x00000004;
+
+	/* XXX: Filters? AGC? */
+	if (f_sr < 6000000)
+		reg3 |= 0x1 << 20;
+	else if (f_sr < 7000000)
+		reg3 |= 0x5 << 20;
+	else if (f_sr < 8500000)
+		reg3 |= 0x9 << 20;
+	else
+		reg3 |= 0xd << 20;
+
+	for (div_r_out = 4; div_r_out < 16; div_r_out += 2) {
+		f_vco = f_sr * div_r_out * 12;
+		dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n",
+				__func__, div_r_out, f_vco);
+		if (f_vco >= 202000000)
+			break;
+	}
+
+	div_n = f_vco / (F_REF * DIV_R_IN);
+	div_m = f_vco % (F_REF * DIV_R_IN);
+	fract = 0x200000ul * div_m / (F_REF * DIV_R_IN);
+
+	reg3 |= div_n << 16;
+	reg3 |= (div_r_out / 2 - 1) << 10;
+	reg3 |= ((fract >> 20) & 0x000001) << 15; /* [20] */
+	reg4 |= ((fract >>  0) & 0x0fffff) <<  8; /* [19:0] */
+
+	dev_dbg(&s->udev->dev,
+			"%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n",
+			__func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3,
+			reg4);
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00608008);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00000c05);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00020000);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00480102);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00f38008);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, reg7);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, reg4);
+	if (ret)
+		goto err;
+
+	ret = msi2500_ctrl_msg(s, CMD_WREG, reg3);
+	if (ret)
+		goto err;
+err:
+	return ret;
+};
+
+static int msi2500_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct msi2500_state *s = vb2_get_drv_priv(vq);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	if (!s->udev)
+		return -ENODEV;
+
+	if (mutex_lock_interruptible(&s->v4l2_lock))
+		return -ERESTARTSYS;
+
+	/* wake-up tuner */
+	v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1);
+
+	ret = msi2500_set_usb_adc(s);
+
+	ret = msi2500_isoc_init(s);
+	if (ret)
+		msi2500_cleanup_queued_bufs(s);
+
+	ret = msi2500_ctrl_msg(s, CMD_START_STREAMING, 0);
+
+	mutex_unlock(&s->v4l2_lock);
+
+	return ret;
+}
+
+static void msi2500_stop_streaming(struct vb2_queue *vq)
+{
+	struct msi2500_state *s = vb2_get_drv_priv(vq);
+
+	dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+	mutex_lock(&s->v4l2_lock);
+
+	if (s->udev)
+		msi2500_isoc_cleanup(s);
+
+	msi2500_cleanup_queued_bufs(s);
+
+	/* according to tests, at least 700us delay is required  */
+	msleep(20);
+	if (!msi2500_ctrl_msg(s, CMD_STOP_STREAMING, 0)) {
+		/* sleep USB IF / ADC */
+		msi2500_ctrl_msg(s, CMD_WREG, 0x01000003);
+	}
+
+	/* sleep tuner */
+	v4l2_subdev_call(s->v4l2_subdev, core, s_power, 0);
+
+	mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops msi2500_vb2_ops = {
+	.queue_setup            = msi2500_queue_setup,
+	.buf_queue              = msi2500_buf_queue,
+	.start_streaming        = msi2500_start_streaming,
+	.stop_streaming         = msi2500_stop_streaming,
+	.wait_prepare           = vb2_ops_wait_prepare,
+	.wait_finish            = vb2_ops_wait_finish,
+};
+
+static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_fmtdesc *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
+
+	if (f->index >= s->num_formats)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
+
+	return 0;
+}
+
+static int msi2500_g_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&s->pixelformat);
+
+	f->fmt.sdr.pixelformat = s->pixelformat;
+	f->fmt.sdr.buffersize = s->buffersize;
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+
+	return 0;
+}
+
+static int msi2500_s_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	struct vb2_queue *q = &s->vb_queue;
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < s->num_formats; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			s->pixelformat = formats[i].pixelformat;
+			s->buffersize = formats[i].buffersize;
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static int msi2500_try_fmt_sdr_cap(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int i;
+
+	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+			(char *)&f->fmt.sdr.pixelformat);
+
+	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+	for (i = 0; i < s->num_formats; i++) {
+		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+			f->fmt.sdr.buffersize = formats[i].buffersize;
+			return 0;
+		}
+	}
+
+	f->fmt.sdr.pixelformat = formats[0].pixelformat;
+	f->fmt.sdr.buffersize = formats[0].buffersize;
+
+	return 0;
+}
+
+static int msi2500_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *v)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0)
+		ret = 0;
+	else if (v->index == 1)
+		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_tuner, v);
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int msi2500_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+	if (v->index == 0) {
+		strlcpy(v->name, "Mirics MSi2500", sizeof(v->name));
+		v->type = V4L2_TUNER_ADC;
+		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+		v->rangelow =   1200000;
+		v->rangehigh = 15000000;
+		ret = 0;
+	} else if (v->index == 1) {
+		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_tuner, v);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msi2500_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int ret  = 0;
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+			__func__, f->tuner, f->type);
+
+	if (f->tuner == 0) {
+		f->frequency = s->f_adc;
+		ret = 0;
+	} else if (f->tuner == 1) {
+		f->type = V4L2_TUNER_RF;
+		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_frequency, f);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msi2500_s_frequency(struct file *file, void *priv,
+		const struct v4l2_frequency *f)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+			__func__, f->tuner, f->type, f->frequency);
+
+	if (f->tuner == 0) {
+		s->f_adc = clamp_t(unsigned int, f->frequency,
+				bands[0].rangelow,
+				bands[0].rangehigh);
+		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+				__func__, s->f_adc);
+		ret = msi2500_set_usb_adc(s);
+	} else if (f->tuner == 1) {
+		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msi2500_enum_freq_bands(struct file *file, void *priv,
+		struct v4l2_frequency_band *band)
+{
+	struct msi2500_state *s = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+			__func__, band->tuner, band->type, band->index);
+
+	if (band->tuner == 0) {
+		if (band->index >= ARRAY_SIZE(bands)) {
+			ret = -EINVAL;
+		} else {
+			*band = bands[band->index];
+			ret = 0;
+		}
+	} else if (band->tuner == 1) {
+		ret = v4l2_subdev_call(s->v4l2_subdev, tuner,
+				enum_freq_bands, band);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops msi2500_ioctl_ops = {
+	.vidioc_querycap          = msi2500_querycap,
+
+	.vidioc_enum_fmt_sdr_cap  = msi2500_enum_fmt_sdr_cap,
+	.vidioc_g_fmt_sdr_cap     = msi2500_g_fmt_sdr_cap,
+	.vidioc_s_fmt_sdr_cap     = msi2500_s_fmt_sdr_cap,
+	.vidioc_try_fmt_sdr_cap   = msi2500_try_fmt_sdr_cap,
+
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
+
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
+
+	.vidioc_g_tuner           = msi2500_g_tuner,
+	.vidioc_s_tuner           = msi2500_s_tuner,
+
+	.vidioc_g_frequency       = msi2500_g_frequency,
+	.vidioc_s_frequency       = msi2500_s_frequency,
+	.vidioc_enum_freq_bands   = msi2500_enum_freq_bands,
+
+	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_log_status        = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations msi2500_fops = {
+	.owner                    = THIS_MODULE,
+	.open                     = v4l2_fh_open,
+	.release                  = vb2_fop_release,
+	.read                     = vb2_fop_read,
+	.poll                     = vb2_fop_poll,
+	.mmap                     = vb2_fop_mmap,
+	.unlocked_ioctl           = video_ioctl2,
+};
+
+static struct video_device msi2500_template = {
+	.name                     = "Mirics MSi3101 SDR Dongle",
+	.release                  = video_device_release_empty,
+	.fops                     = &msi2500_fops,
+	.ioctl_ops                = &msi2500_ioctl_ops,
+};
+
+static void msi2500_video_release(struct v4l2_device *v)
+{
+	struct msi2500_state *s =
+			container_of(v, struct msi2500_state, v4l2_dev);
+
+	v4l2_ctrl_handler_free(&s->hdl);
+	v4l2_device_unregister(&s->v4l2_dev);
+	kfree(s);
+}
+
+static int msi2500_transfer_one_message(struct spi_master *master,
+		struct spi_message *m)
+{
+	struct msi2500_state *s = spi_master_get_devdata(master);
+	struct spi_transfer *t;
+	int ret = 0;
+	u32 data;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		dev_dbg(&s->udev->dev, "%s: msg=%*ph\n",
+				__func__, t->len, t->tx_buf);
+		data = 0x09; /* reg 9 is SPI adapter */
+		data |= ((u8 *)t->tx_buf)[0] << 8;
+		data |= ((u8 *)t->tx_buf)[1] << 16;
+		data |= ((u8 *)t->tx_buf)[2] << 24;
+		ret = msi2500_ctrl_msg(s, CMD_WREG, data);
+	}
+
+	m->status = ret;
+	spi_finalize_current_message(master);
+	return ret;
+}
+
+static int msi2500_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct msi2500_state *s = NULL;
+	struct v4l2_subdev *sd;
+	struct spi_master *master;
+	int ret;
+	static struct spi_board_info board_info = {
+		.modalias		= "msi001",
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.max_speed_hz		= 12000000,
+	};
+
+	s = kzalloc(sizeof(struct msi2500_state), GFP_KERNEL);
+	if (s == NULL) {
+		pr_err("Could not allocate memory for msi2500_state\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&s->v4l2_lock);
+	mutex_init(&s->vb_queue_lock);
+	spin_lock_init(&s->queued_bufs_lock);
+	INIT_LIST_HEAD(&s->queued_bufs);
+	s->udev = udev;
+	s->f_adc = bands[0].rangelow;
+	s->pixelformat = formats[0].pixelformat;
+	s->buffersize = formats[0].buffersize;
+	s->num_formats = NUM_FORMATS;
+	if (msi2500_emulated_fmt == false)
+		s->num_formats -= 2;
+
+	/* Init videobuf2 queue structure */
+	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	s->vb_queue.drv_priv = s;
+	s->vb_queue.buf_struct_size = sizeof(struct msi2500_frame_buf);
+	s->vb_queue.ops = &msi2500_vb2_ops;
+	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	ret = vb2_queue_init(&s->vb_queue);
+	if (ret) {
+		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+		goto err_free_mem;
+	}
+
+	/* Init video_device structure */
+	s->vdev = msi2500_template;
+	s->vdev.queue = &s->vb_queue;
+	s->vdev.queue->lock = &s->vb_queue_lock;
+	video_set_drvdata(&s->vdev, s);
+
+	/* Register the v4l2_device structure */
+	s->v4l2_dev.release = msi2500_video_release;
+	ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register v4l2-device (%d)\n", ret);
+		goto err_free_mem;
+	}
+
+	/* SPI master adapter */
+	master = spi_alloc_master(&s->udev->dev, 0);
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err_unregister_v4l2_dev;
+	}
+
+	s->master = master;
+	master->bus_num = 0;
+	master->num_chipselect = 1;
+	master->transfer_one_message = msi2500_transfer_one_message;
+	spi_master_set_devdata(master, s);
+	ret = spi_register_master(master);
+	if (ret) {
+		spi_master_put(master);
+		goto err_unregister_v4l2_dev;
+	}
+
+	/* load v4l2 subdevice */
+	sd = v4l2_spi_new_subdev(&s->v4l2_dev, master, &board_info);
+	s->v4l2_subdev = sd;
+	if (sd == NULL) {
+		dev_err(&s->udev->dev, "cannot get v4l2 subdevice\n");
+		ret = -ENODEV;
+		goto err_unregister_master;
+	}
+
+	/* Register controls */
+	v4l2_ctrl_handler_init(&s->hdl, 0);
+	if (s->hdl.error) {
+		ret = s->hdl.error;
+		dev_err(&s->udev->dev, "Could not initialize controls\n");
+		goto err_free_controls;
+	}
+
+	/* currently all controls are from subdev */
+	v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
+
+	s->v4l2_dev.ctrl_handler = &s->hdl;
+	s->vdev.v4l2_dev = &s->v4l2_dev;
+	s->vdev.lock = &s->v4l2_lock;
+
+	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+	if (ret) {
+		dev_err(&s->udev->dev,
+				"Failed to register as video device (%d)\n",
+				ret);
+		goto err_unregister_v4l2_dev;
+	}
+	dev_info(&s->udev->dev, "Registered as %s\n",
+			video_device_node_name(&s->vdev));
+	dev_notice(&s->udev->dev,
+			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
+			KBUILD_MODNAME);
+
+	return 0;
+
+err_free_controls:
+	v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_master:
+	spi_unregister_master(s->master);
+err_unregister_v4l2_dev:
+	v4l2_device_unregister(&s->v4l2_dev);
+err_free_mem:
+	kfree(s);
+	return ret;
+}
+
+/* USB device ID list */
+static struct usb_device_id msi2500_id_table[] = {
+	{ USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */
+	{ USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, msi2500_id_table);
+
+/* USB subsystem interface */
+static struct usb_driver msi2500_driver = {
+	.name                     = KBUILD_MODNAME,
+	.probe                    = msi2500_probe,
+	.disconnect               = msi2500_disconnect,
+	.id_table                 = msi2500_id_table,
+};
+
+module_usb_driver(msi2500_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c linux-libre-3.17-rc7-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-3.16-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c	2014-09-28 17:29:07.000000000 -0400
@@ -951,15 +951,9 @@ 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", ret);
-		} else {
-			if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
-				pvr2_trace(PVR2_TRACE_V4LIOCTL,
-					   "pvr2_v4l2_do_ioctl failure, ret=%ld"
-					   " command was:", ret);
-				v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
-						cmd);
-			}
+				   "pvr2_v4l2_do_ioctl failure, ret=%ld"
+				   " command was:", ret);
+			v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
 		}
 	} else {
 		pvr2_trace(PVR2_TRACE_V4LIOCTL,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/pwc/pwc-if.c linux-libre-3.17-rc7-gnu/drivers/media/usb/pwc/pwc-if.c
--- linux-libre-3.16-gnu/drivers/media/usb/pwc/pwc-if.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/pwc/pwc-if.c	2014-09-28 17:29:07.000000000 -0400
@@ -1013,7 +1013,6 @@ static int usb_pwc_probe(struct usb_inte
 	strcpy(pdev->vdev.name, name);
 	pdev->vdev.queue = &pdev->vb_queue;
 	pdev->vdev.queue->lock = &pdev->vb_queue_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
 	video_set_drvdata(&pdev->vdev, pdev);
 
 	pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/s2255/s2255drv.c linux-libre-3.17-rc7-gnu/drivers/media/usb/s2255/s2255drv.c
--- linux-libre-3.16-gnu/drivers/media/usb/s2255/s2255drv.c	2014-08-07 04:51:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/s2255/s2255drv.c	2014-09-28 21:32:20.000000000 -0400
@@ -1676,7 +1676,6 @@ static int s2255_probe_v4l(struct s2255_
 		vc->vdev.ctrl_handler = &vc->hdl;
 		vc->vdev.lock = &dev->lock;
 		vc->vdev.v4l2_dev = &dev->v4l2_dev;
-		set_bit(V4L2_FL_USE_FH_PRIO, &vc->vdev.flags);
 		video_set_drvdata(&vc->vdev, vc);
 		if (video_nr == -1)
 			ret = video_register_device(&vc->vdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/stk1160/stk1160-v4l.c linux-libre-3.17-rc7-gnu/drivers/media/usb/stk1160/stk1160-v4l.c
--- linux-libre-3.16-gnu/drivers/media/usb/stk1160/stk1160-v4l.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/stk1160/stk1160-v4l.c	2014-09-28 17:29:07.000000000 -0400
@@ -671,7 +671,6 @@ int stk1160_video_register(struct stk116
 
 	/* This will be used to set video_device parent */
 	dev->vdev.v4l2_dev = &dev->v4l2_dev;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 
 	/* NTSC is default */
 	dev->norm = V4L2_STD_NTSC_M;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/stkwebcam/stk-webcam.c linux-libre-3.17-rc7-gnu/drivers/media/usb/stkwebcam/stk-webcam.c
--- linux-libre-3.16-gnu/drivers/media/usb/stkwebcam/stk-webcam.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/stkwebcam/stk-webcam.c	2014-09-28 17:29:07.000000000 -0400
@@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(stru
 		pix_format->bytesperline = 2 * pix_format->width;
 	pix_format->sizeimage = pix_format->bytesperline
 				* pix_format->height;
-	pix_format->priv = 0;
 	return 0;
 }
 
@@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct fi
 		fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
 	fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
 		* fmtd->fmt.pix.height;
-	fmtd->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1266,7 +1264,6 @@ static int stk_register_video_device(str
 	dev->vdev.lock = &dev->lock;
 	dev->vdev.debug = debug;
 	dev->vdev.v4l2_dev = &dev->v4l2_dev;
-	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 	video_set_drvdata(&dev->vdev, dev);
 	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
 	if (err)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-main.c linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-main.c
--- linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-main.c	2014-08-07 04:50:58.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-main.c	2014-09-28 21:32:16.000000000 -0400
@@ -476,6 +476,8 @@ err_audio:
 err_video:
 	v4l2_device_unregister(&pd->v4l2_dev);
 err_v4l2:
+	usb_put_intf(pd->interface);
+	usb_put_dev(pd->udev);
 	kfree(pd);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-radio.c linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-radio.c
--- linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-radio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-radio.c	2014-09-28 17:29:07.000000000 -0400
@@ -327,7 +327,6 @@ int poseidon_fm_init(struct poseidon *p)
 	}
 	vfd->v4l2_dev = &p->v4l2_dev;
 	vfd->ctrl_handler = hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	video_set_drvdata(vfd, p);
 	return video_register_device(vfd, VFL_TYPE_RADIO, -1);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/tlg2300/pd-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/tlg2300/pd-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1321,7 +1321,6 @@ static void init_video_context(struct ru
 				.bytesperline	= 720 * 2,
 				.sizeimage	= 720 * 576 * 2,
 				.colorspace	= V4L2_COLORSPACE_SMPTE170M,
-				.priv		= 0
 			};
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/tm6000/tm6000-input.c linux-libre-3.17-rc7-gnu/drivers/media/usb/tm6000/tm6000-input.c
--- linux-libre-3.16-gnu/drivers/media/usb/tm6000/tm6000-input.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/tm6000/tm6000-input.c	2014-09-28 17:29:07.000000000 -0400
@@ -162,11 +162,42 @@ static int tm6000_ir_config(struct tm600
 	return 0;
 }
 
+static void tm6000_ir_keydown(struct tm6000_IR *ir,
+			      const char *buf, unsigned int len)
+{
+	u8 device, command;
+	u32 scancode;
+	enum rc_type protocol;
+
+	if (len < 1)
+		return;
+
+	command = buf[0];
+	device = (len > 1 ? buf[1] : 0x0);
+	switch (ir->rc_type) {
+	case RC_BIT_RC5:
+		protocol = RC_TYPE_RC5;
+		scancode = RC_SCANCODE_RC5(device, command);
+		break;
+	case RC_BIT_NEC:
+		protocol = RC_TYPE_NEC;
+		scancode = RC_SCANCODE_NEC(device, command);
+		break;
+	default:
+		protocol = RC_TYPE_OTHER;
+		scancode = RC_SCANCODE_OTHER(device << 8 | command);
+		break;
+	}
+
+	dprintk(1, "%s, protocol: 0x%04x, scancode: 0x%08x\n",
+		__func__, protocol, scancode);
+	rc_keydown(ir->rc, protocol, scancode, 0);
+}
+
 static void tm6000_ir_urb_received(struct urb *urb)
 {
 	struct tm6000_core *dev = urb->context;
 	struct tm6000_IR *ir = dev->ir;
-	struct tm6000_ir_poll_result poll_result;
 	char *buf;
 
 	dprintk(2, "%s\n",__func__);
@@ -184,12 +215,7 @@ static void tm6000_ir_urb_received(struc
 			       DUMP_PREFIX_OFFSET,16, 1,
 			       buf, urb->actual_length, false);
 
-	poll_result.rc_data = buf[0];
-	if (urb->actual_length > 1)
-		poll_result.rc_data |= buf[1] << 8;
-
-	dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-	rc_keydown(ir->rc, poll_result.rc_data, 0);
+	tm6000_ir_keydown(ir, urb->transfer_buffer, urb->actual_length);
 
 	usb_submit_urb(urb, GFP_ATOMIC);
 	/*
@@ -204,7 +230,6 @@ static void tm6000_ir_handle_key(struct
 {
 	struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
 	struct tm6000_core *dev = ir->dev;
-	struct tm6000_ir_poll_result poll_result;
 	int rc;
 	u8 buf[2];
 
@@ -219,13 +244,8 @@ static void tm6000_ir_handle_key(struct
 	if (rc < 0)
 		return;
 
-	if (rc > 1)
-		poll_result.rc_data = buf[0] | buf[1] << 8;
-	else
-		poll_result.rc_data = buf[0];
-
 	/* Check if something was read */
-	if ((poll_result.rc_data & 0xff) == 0xff) {
+	if ((buf[0] & 0xff) == 0xff) {
 		if (!ir->pwled) {
 			tm6000_flash_led(dev, 1);
 			ir->pwled = 1;
@@ -233,8 +253,7 @@ static void tm6000_ir_handle_key(struct
 		return;
 	}
 
-	dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-	rc_keydown(ir->rc, poll_result.rc_data, 0);
+	tm6000_ir_keydown(ir, buf, rc);
 	tm6000_flash_led(dev, 0);
 	ir->pwled = 0;
 
@@ -422,9 +441,9 @@ int tm6000_ir_init(struct tm6000_core *d
 	ir->rc = rc;
 
 	/* input setup */
-	rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+	rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC;
 	/* Neded, in order to support NEC remotes with 24 or 32 bits */
-	rc->scanmask = 0xffff;
+	rc->scancode_mask = 0xffff;
 	rc->priv = ir;
 	rc->change_protocol = tm6000_ir_change_protocol;
 	if (dev->int_in.endp) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/tm6000/tm6000-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/tm6000/tm6000-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/tm6000/tm6000-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/tm6000/tm6000-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct f
 		(f->fmt.pix.width * fh->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct
 	f->fmt.pix.width &= ~0x01;
 
 	f->fmt.pix.field = field;
-	f->fmt.pix.priv = 0;
 
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
@@ -1626,7 +1624,6 @@ static struct video_device *vdev_init(st
 	vfd->release = video_device_release;
 	vfd->debug = tm6000_debug;
 	vfd->lock = &dev->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c linux-libre-3.17-rc7-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
--- linux-libre-3.16-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c	2014-08-07 04:49:39.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c	2014-09-28 21:30:49.000000000 -0400
@@ -791,8 +791,7 @@ static void ttusb_free_iso_urbs(struct t
 	int i;
 
 	for (i = 0; i < ISO_BUF_COUNT; i++)
-		if (ttusb->iso_urb[i])
-			usb_free_urb(ttusb->iso_urb[i]);
+		usb_free_urb(ttusb->iso_urb[i]);
 
 	pci_free_consistent(NULL,
 			    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *
@@ -804,11 +803,9 @@ static int ttusb_alloc_iso_urbs(struct t
 {
 	int i;
 
-	ttusb->iso_buffer = pci_alloc_consistent(NULL,
-						 ISO_FRAME_SIZE *
-						 FRAMES_PER_ISO_BUF *
-						 ISO_BUF_COUNT,
-						 &ttusb->iso_dma_handle);
+	ttusb->iso_buffer = pci_zalloc_consistent(NULL,
+						  ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT,
+						  &ttusb->iso_dma_handle);
 
 	if (!ttusb->iso_buffer) {
 		dprintk("%s: pci_alloc_consistent - not enough memory\n",
@@ -816,9 +813,6 @@ static int ttusb_alloc_iso_urbs(struct t
 		return -ENOMEM;
 	}
 
-	memset(ttusb->iso_buffer, 0,
-	       ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
-
 	for (i = 0; i < ISO_BUF_COUNT; i++) {
 		struct urb *urb;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c linux-libre-3.17-rc7-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c
--- linux-libre-3.16-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c	2014-08-07 04:49:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c	2014-09-28 21:30:53.000000000 -0400
@@ -1151,11 +1151,9 @@ static int ttusb_dec_alloc_iso_urbs(stru
 
 	dprintk("%s\n", __func__);
 
-	dec->iso_buffer = pci_alloc_consistent(NULL,
-					       ISO_FRAME_SIZE *
-					       (FRAMES_PER_ISO_BUF *
-						ISO_BUF_COUNT),
-					       &dec->iso_dma_handle);
+	dec->iso_buffer = pci_zalloc_consistent(NULL,
+						ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT),
+						&dec->iso_dma_handle);
 
 	if (!dec->iso_buffer) {
 		dprintk("%s: pci_alloc_consistent - not enough memory\n",
@@ -1163,9 +1161,6 @@ static int ttusb_dec_alloc_iso_urbs(stru
 		return -ENOMEM;
 	}
 
-	memset(dec->iso_buffer, 0,
-	       ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
-
 	for (i = 0; i < ISO_BUF_COUNT; i++) {
 		struct urb *urb;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/usbtv/usbtv-core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/usbtv/usbtv-core.c
--- linux-libre-3.16-gnu/drivers/media/usb/usbtv/usbtv-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/usbtv/usbtv-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -91,6 +91,8 @@ static int usbtv_probe(struct usb_interf
 	return 0;
 
 usbtv_video_fail:
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(usbtv->udev);
 	kfree(usbtv);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/usbtv/usbtv-video.c linux-libre-3.17-rc7-gnu/drivers/media/usb/usbtv/usbtv-video.c
--- linux-libre-3.16-gnu/drivers/media/usb/usbtv/usbtv-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/usbtv/usbtv-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -701,7 +701,6 @@ int usbtv_video_init(struct usbtv *usbtv
 	usbtv->vdev.tvnorms = USBTV_TV_STD;
 	usbtv->vdev.queue = &usbtv->vb2q;
 	usbtv->vdev.lock = &usbtv->v4l2_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
 	video_set_drvdata(&usbtv->vdev, usbtv);
 	ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret < 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/usbvision/usbvision-core.c linux-libre-3.17-rc7-gnu/drivers/media/usb/usbvision/usbvision-core.c
--- linux-libre-3.16-gnu/drivers/media/usb/usbvision/usbvision-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/usbvision/usbvision-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -1463,8 +1463,6 @@ static int usbvision_write_reg_irq(struc
 
 static int usbvision_init_compression(struct usb_usbvision *usbvision)
 {
-	int err_code = 0;
-
 	usbvision->last_isoc_frame_num = -1;
 	usbvision->isoc_data_count = 0;
 	usbvision->isoc_packet_count = 0;
@@ -1475,7 +1473,7 @@ static int usbvision_init_compression(st
 	usbvision->request_intra = 1;
 	usbvision->isoc_measure_bandwidth_count = 0;
 
-	return err_code;
+	return 0;
 }
 
 /* this function measures the used bandwidth since last call
@@ -1484,11 +1482,9 @@ static int usbvision_init_compression(st
  */
 static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
 {
-	int err_code = 0;
-
 	if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
 		usbvision->isoc_measure_bandwidth_count++;
-		return err_code;
+		return 0;
 	}
 	if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
 		usbvision->used_bandwidth = usbvision->isoc_data_count /
@@ -1499,7 +1495,7 @@ static int usbvision_measure_bandwidth(s
 	usbvision->isoc_data_count = 0;
 	usbvision->isoc_packet_count = 0;
 	usbvision->isoc_skip_count = 0;
-	return err_code;
+	return 0;
 }
 
 static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
@@ -1546,26 +1542,24 @@ static int usbvision_adjust_compression(
 
 static int usbvision_request_intra(struct usb_usbvision *usbvision)
 {
-	int err_code = 0;
 	unsigned char buffer[1];
 
 	PDEBUG(DBG_IRQ, "");
 	usbvision->request_intra = 1;
 	buffer[0] = 1;
 	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-	return err_code;
+	return 0;
 }
 
 static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
 {
-	int err_code = 0;
 	unsigned char buffer[1];
 
 	PDEBUG(DBG_IRQ, "");
 	usbvision->request_intra = 0;
 	buffer[0] = 0;
 	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-	return err_code;
+	return 0;
 }
 
 /*******************************
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/uvc/uvc_driver.c linux-libre-3.17-rc7-gnu/drivers/media/usb/uvc/uvc_driver.c
--- linux-libre-3.16-gnu/drivers/media/usb/uvc/uvc_driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/uvc/uvc_driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -1746,7 +1746,6 @@ static int uvc_register_video(struct uvc
 	vdev->fops = &uvc_fops;
 	vdev->release = uvc_release;
 	vdev->prio = &stream->chain->prio;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
 	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
 		vdev->vfl_dir = VFL_DIR_TX;
 	strlcpy(vdev->name, dev->name, sizeof vdev->name);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/usb/zr364xx/zr364xx.c linux-libre-3.17-rc7-gnu/drivers/media/usb/zr364xx/zr364xx.c
--- linux-libre-3.16-gnu/drivers/media/usb/zr364xx/zr364xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/usb/zr364xx/zr364xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_ca
 	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-	f->fmt.pix.priv = 0;
 	DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
 	    decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
 	    f->fmt.pix.field);
@@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(
 	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(
 	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-	f->fmt.pix.priv = 0;
 	cam->vb_vidq.field = f->fmt.pix.field;
 
 	if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
@@ -1456,7 +1453,6 @@ static int zr364xx_probe(struct usb_inte
 	cam->vdev.lock = &cam->lock;
 	cam->vdev.v4l2_dev = &cam->v4l2_dev;
 	cam->vdev.ctrl_handler = &cam->ctrl_handler;
-	set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
 	video_set_drvdata(&cam->vdev, cam);
 	if (debug)
 		cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-common.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-common.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-common.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,9 +111,13 @@ int v4l2_ctrl_check(struct v4l2_ext_cont
 EXPORT_SYMBOL(v4l2_ctrl_check);
 
 /* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
 {
 	const char *name;
+	s64 min = _min;
+	s64 max = _max;
+	u64 step = _step;
+	s64 def = _def;
 
 	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
 		       &min, &max, &step, &def, &qctrl->flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c	2014-09-28 17:29:07.000000000 -0400
@@ -540,7 +540,16 @@ struct v4l2_framebuffer32 {
 	__u32			capability;
 	__u32			flags;
 	compat_caddr_t 		base;
-	struct v4l2_pix_format	fmt;
+	struct {
+		__u32		width;
+		__u32		height;
+		__u32		pixelformat;
+		__u32		field;
+		__u32		bytesperline;
+		__u32		sizeimage;
+		__u32		colorspace;
+		__u32		priv;
+	} fmt;
 };
 
 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
@@ -550,10 +559,10 @@ static int get_v4l2_framebuffer32(struct
 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
 		get_user(tmp, &up->base) ||
 		get_user(kp->capability, &up->capability) ||
-		get_user(kp->flags, &up->flags))
+		get_user(kp->flags, &up->flags) ||
+		copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
 			return -EFAULT;
 	kp->base = compat_ptr(tmp);
-	get_v4l2_pix_format(&kp->fmt, &up->fmt);
 	return 0;
 }
 
@@ -564,9 +573,9 @@ static int put_v4l2_framebuffer32(struct
 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
 		put_user(tmp, &up->base) ||
 		put_user(kp->capability, &up->capability) ||
-		put_user(kp->flags, &up->flags))
+		put_user(kp->flags, &up->flags) ||
+		copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
 			return -EFAULT;
-	put_v4l2_pix_format(&kp->fmt, &up->fmt);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-ctrls.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-ctrls.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-ctrls.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-ctrls.c	2014-09-28 17:29:07.000000000 -0400
@@ -462,6 +462,13 @@ const char * const *v4l2_ctrl_get_menu(u
 		"RGB full range (0-255)",
 		NULL,
 	};
+	static const char * const detect_md_mode[] = {
+		"Disabled",
+		"Global",
+		"Threshold Grid",
+		"Region Grid",
+		NULL,
+	};
 
 
 	switch (id) {
@@ -553,6 +560,8 @@ const char * const *v4l2_ctrl_get_menu(u
 	case V4L2_CID_DV_TX_RGB_RANGE:
 	case V4L2_CID_DV_RX_RGB_RANGE:
 		return dv_rgb_range;
+	case V4L2_CID_DETECT_MD_MODE:
+		return detect_md_mode;
 
 	default:
 		return NULL;
@@ -592,7 +601,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 {
 	switch (id) {
 	/* USER controls */
-	/* Keep the order of the 'case's the same as in videodev2.h! */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_USER_CLASS:		return "User Controls";
 	case V4L2_CID_BRIGHTNESS:		return "Brightness";
 	case V4L2_CID_CONTRAST:			return "Contrast";
@@ -754,7 +763,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:			return "VPX Profile";
 
 	/* CAMERA controls */
-	/* Keep the order of the 'case's the same as in videodev2.h! */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_CAMERA_CLASS:		return "Camera Controls";
 	case V4L2_CID_EXPOSURE_AUTO:		return "Auto Exposure";
 	case V4L2_CID_EXPOSURE_ABSOLUTE:	return "Exposure Time, Absolute";
@@ -788,14 +797,23 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_AUTO_FOCUS_STATUS:	return "Auto Focus, Status";
 	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range";
 
-	/* FM Radio Modulator control */
-	/* Keep the order of the 'case's the same as in videodev2.h! */
+	/* FM Radio Modulator controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_FM_TX_CLASS:		return "FM Radio Modulator Controls";
 	case V4L2_CID_RDS_TX_DEVIATION:		return "RDS Signal Deviation";
 	case V4L2_CID_RDS_TX_PI:		return "RDS Program ID";
 	case V4L2_CID_RDS_TX_PTY:		return "RDS Program Type";
 	case V4L2_CID_RDS_TX_PS_NAME:		return "RDS PS Name";
 	case V4L2_CID_RDS_TX_RADIO_TEXT:	return "RDS Radio Text";
+	case V4L2_CID_RDS_TX_MONO_STEREO:	return "RDS Stereo";
+	case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:	return "RDS Artificial Head";
+	case V4L2_CID_RDS_TX_COMPRESSED:	return "RDS Compressed";
+	case V4L2_CID_RDS_TX_DYNAMIC_PTY:	return "RDS Dynamic PTY";
+	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
+	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:	return "RDS Traffic Program";
+	case V4L2_CID_RDS_TX_MUSIC_SPEECH:	return "RDS Music";
+	case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:	return "RDS Enable Alt Frequencies";
+	case V4L2_CID_RDS_TX_ALT_FREQS:		return "RDS Alternate Frequencies";
 	case V4L2_CID_AUDIO_LIMITER_ENABLED:	return "Audio Limiter Feature Enabled";
 	case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
 	case V4L2_CID_AUDIO_LIMITER_DEVIATION:	return "Audio Limiter Deviation";
@@ -812,6 +830,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TUNE_ANTENNA_CAPACITOR:	return "Tune Antenna Capacitor";
 
 	/* Flash controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_FLASH_CLASS:		return "Flash Controls";
 	case V4L2_CID_FLASH_LED_MODE:		return "LED Mode";
 	case V4L2_CID_FLASH_STROBE_SOURCE:	return "Strobe Source";
@@ -827,7 +846,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_FLASH_READY:		return "Ready to Strobe";
 
 	/* JPEG encoder controls */
-	/* Keep the order of the 'case's the same as in videodev2.h! */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_JPEG_CLASS:		return "JPEG Compression Controls";
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:	return "Chroma Subsampling";
 	case V4L2_CID_JPEG_RESTART_INTERVAL:	return "Restart Interval";
@@ -835,18 +854,21 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_JPEG_ACTIVE_MARKER:	return "Active Markers";
 
 	/* Image source controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_IMAGE_SOURCE_CLASS:	return "Image Source Controls";
 	case V4L2_CID_VBLANK:			return "Vertical Blanking";
 	case V4L2_CID_HBLANK:			return "Horizontal Blanking";
 	case V4L2_CID_ANALOGUE_GAIN:		return "Analogue Gain";
 
 	/* Image processing controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_IMAGE_PROC_CLASS:		return "Image Processing Controls";
 	case V4L2_CID_LINK_FREQ:		return "Link Frequency";
 	case V4L2_CID_PIXEL_RATE:		return "Pixel Rate";
 	case V4L2_CID_TEST_PATTERN:		return "Test Pattern";
 
 	/* DV controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
 	case V4L2_CID_DV_CLASS:			return "Digital Video Controls";
 	case V4L2_CID_DV_TX_HOTPLUG:		return "Hotplug Present";
 	case V4L2_CID_DV_TX_RXSENSE:		return "RxSense Present";
@@ -859,7 +881,6 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_FM_RX_CLASS:		return "FM Radio Receiver Controls";
 	case V4L2_CID_TUNE_DEEMPHASIS:		return "De-Emphasis";
 	case V4L2_CID_RDS_RECEPTION:		return "RDS Reception";
-
 	case V4L2_CID_RF_TUNER_CLASS:		return "RF Tuner Controls";
 	case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:	return "LNA Gain, Auto";
 	case V4L2_CID_RF_TUNER_LNA_GAIN:	return "LNA Gain";
@@ -870,6 +891,20 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:	return "Bandwidth, Auto";
 	case V4L2_CID_RF_TUNER_BANDWIDTH:	return "Bandwidth";
 	case V4L2_CID_RF_TUNER_PLL_LOCK:	return "PLL Lock";
+	case V4L2_CID_RDS_RX_PTY:		return "RDS Program Type";
+	case V4L2_CID_RDS_RX_PS_NAME:		return "RDS PS Name";
+	case V4L2_CID_RDS_RX_RADIO_TEXT:	return "RDS Radio Text";
+	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
+	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:	return "RDS Traffic Program";
+	case V4L2_CID_RDS_RX_MUSIC_SPEECH:	return "RDS Music";
+
+	/* Detection controls */
+	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
+	case V4L2_CID_DETECT_CLASS:		return "Detection Controls";
+	case V4L2_CID_DETECT_MD_MODE:		return "Motion Detection Mode";
+	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold";
+	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:	return "MD Threshold Grid";
+	case V4L2_CID_DETECT_MD_REGION_GRID:	return "MD Region Grid";
 	default:
 		return NULL;
 	}
@@ -877,7 +912,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 EXPORT_SYMBOL(v4l2_ctrl_get_name);
 
 void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
-		    s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
+		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
 {
 	*name = v4l2_ctrl_get_name(id);
 	*flags = 0;
@@ -924,6 +959,17 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_RF_TUNER_IF_GAIN_AUTO:
 	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
 	case V4L2_CID_RF_TUNER_PLL_LOCK:
+	case V4L2_CID_RDS_TX_MONO_STEREO:
+	case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
+	case V4L2_CID_RDS_TX_COMPRESSED:
+	case V4L2_CID_RDS_TX_DYNAMIC_PTY:
+	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
+	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
+	case V4L2_CID_RDS_TX_MUSIC_SPEECH:
+	case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
+	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
+	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
+	case V4L2_CID_RDS_RX_MUSIC_SPEECH:
 		*type = V4L2_CTRL_TYPE_BOOLEAN;
 		*min = 0;
 		*max = *step = 1;
@@ -988,6 +1034,7 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_TEST_PATTERN:
 	case V4L2_CID_TUNE_DEEMPHASIS:
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
+	case V4L2_CID_DETECT_MD_MODE:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_LINK_FREQ:
@@ -995,6 +1042,8 @@ void v4l2_ctrl_fill(u32 id, const char *
 		break;
 	case V4L2_CID_RDS_TX_PS_NAME:
 	case V4L2_CID_RDS_TX_RADIO_TEXT:
+	case V4L2_CID_RDS_RX_PS_NAME:
+	case V4L2_CID_RDS_RX_RADIO_TEXT:
 		*type = V4L2_CTRL_TYPE_STRING;
 		break;
 	case V4L2_CID_ISO_SENSITIVITY:
@@ -1014,6 +1063,7 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_DV_CLASS:
 	case V4L2_CID_FM_RX_CLASS:
 	case V4L2_CID_RF_TUNER_CLASS:
+	case V4L2_CID_DETECT_CLASS:
 		*type = V4L2_CTRL_TYPE_CTRL_CLASS;
 		/* You can neither read not write these */
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1041,14 +1091,32 @@ void v4l2_ctrl_fill(u32 id, const char *
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		break;
-	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
 	case V4L2_CID_MPEG_VIDEO_DEC_PTS:
-		*flags |= V4L2_CTRL_FLAG_VOLATILE;
-		/* Fall through */
+		*type = V4L2_CTRL_TYPE_INTEGER64;
+		*flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+		*min = *def = 0;
+		*max = 0x1ffffffffLL;
+		*step = 1;
+		break;
+	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
+		*type = V4L2_CTRL_TYPE_INTEGER64;
+		*flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+		*min = *def = 0;
+		*max = 0x7fffffffffffffffLL;
+		*step = 1;
+		break;
 	case V4L2_CID_PIXEL_RATE:
 		*type = V4L2_CTRL_TYPE_INTEGER64;
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
-		*min = *max = *step = *def = 0;
+		break;
+	case V4L2_CID_DETECT_MD_REGION_GRID:
+		*type = V4L2_CTRL_TYPE_U8;
+		break;
+	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+		*type = V4L2_CTRL_TYPE_U16;
+		break;
+	case V4L2_CID_RDS_TX_ALT_FREQS:
+		*type = V4L2_CTRL_TYPE_U32;
 		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
@@ -1090,6 +1158,7 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_RF_TUNER_MIXER_GAIN:
 	case V4L2_CID_RF_TUNER_IF_GAIN:
 	case V4L2_CID_RF_TUNER_BANDWIDTH:
+	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
 		*flags |= V4L2_CTRL_FLAG_SLIDER;
 		break;
 	case V4L2_CID_PAN_RELATIVE:
@@ -1106,6 +1175,12 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_DV_TX_RXSENSE:
 	case V4L2_CID_DV_TX_EDID_PRESENT:
 	case V4L2_CID_DV_RX_POWER_PRESENT:
+	case V4L2_CID_RDS_RX_PTY:
+	case V4L2_CID_RDS_RX_PS_NAME:
+	case V4L2_CID_RDS_RX_RADIO_TEXT:
+	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
+	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
+	case V4L2_CID_RDS_RX_MUSIC_SPEECH:
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		break;
 	case V4L2_CID_RF_TUNER_PLL_LOCK:
@@ -1115,20 +1190,6 @@ void v4l2_ctrl_fill(u32 id, const char *
 }
 EXPORT_SYMBOL(v4l2_ctrl_fill);
 
-/* Helper function to determine whether the control type is compatible with
-   VIDIOC_G/S_CTRL. */
-static bool type_is_int(const struct v4l2_ctrl *ctrl)
-{
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER64:
-	case V4L2_CTRL_TYPE_STRING:
-		/* Nope, these need v4l2_ext_control */
-		return false;
-	default:
-		return true;
-	}
-}
-
 static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
 {
 	memset(ev->reserved, 0, sizeof(ev->reserved));
@@ -1137,10 +1198,10 @@ static void fill_event(struct v4l2_event
 	ev->u.ctrl.changes = changes;
 	ev->u.ctrl.type = ctrl->type;
 	ev->u.ctrl.flags = ctrl->flags;
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+	if (ctrl->is_ptr)
 		ev->u.ctrl.value64 = 0;
 	else
-		ev->u.ctrl.value64 = ctrl->cur.val64;
+		ev->u.ctrl.value64 = *ctrl->p_cur.p_s64;
 	ev->u.ctrl.minimum = ctrl->minimum;
 	ev->u.ctrl.maximum = ctrl->maximum;
 	if (ctrl->type == V4L2_CTRL_TYPE_MENU
@@ -1166,42 +1227,283 @@ static void send_event(struct v4l2_fh *f
 			v4l2_event_queue_fh(sev->fh, &ev);
 }
 
-/* Helper function: copy the current control value back to the caller */
-static int cur_to_user(struct v4l2_ext_control *c,
-		       struct v4l2_ctrl *ctrl)
+static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
+		      union v4l2_ctrl_ptr ptr1,
+		      union v4l2_ctrl_ptr ptr2)
+{
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BUTTON:
+		return false;
+	case V4L2_CTRL_TYPE_STRING:
+		idx *= ctrl->elem_size;
+		/* strings are always 0-terminated */
+		return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
+	case V4L2_CTRL_TYPE_INTEGER64:
+		return ptr1.p_s64[idx] == ptr2.p_s64[idx];
+	case V4L2_CTRL_TYPE_U8:
+		return ptr1.p_u8[idx] == ptr2.p_u8[idx];
+	case V4L2_CTRL_TYPE_U16:
+		return ptr1.p_u16[idx] == ptr2.p_u16[idx];
+	case V4L2_CTRL_TYPE_U32:
+		return ptr1.p_u32[idx] == ptr2.p_u32[idx];
+	default:
+		if (ctrl->is_int)
+			return ptr1.p_s32[idx] == ptr2.p_s32[idx];
+		idx *= ctrl->elem_size;
+		return !memcmp(ptr1.p + idx, ptr2.p + idx, ctrl->elem_size);
+	}
+}
+
+static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
+		     union v4l2_ctrl_ptr ptr)
+{
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_STRING:
+		idx *= ctrl->elem_size;
+		memset(ptr.p_char + idx, ' ', ctrl->minimum);
+		ptr.p_char[idx + ctrl->minimum] = '\0';
+		break;
+	case V4L2_CTRL_TYPE_INTEGER64:
+		ptr.p_s64[idx] = ctrl->default_value;
+		break;
+	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_BITMASK:
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		ptr.p_s32[idx] = ctrl->default_value;
+		break;
+	case V4L2_CTRL_TYPE_U8:
+		ptr.p_u8[idx] = ctrl->default_value;
+		break;
+	case V4L2_CTRL_TYPE_U16:
+		ptr.p_u16[idx] = ctrl->default_value;
+		break;
+	case V4L2_CTRL_TYPE_U32:
+		ptr.p_u32[idx] = ctrl->default_value;
+		break;
+	default:
+		idx *= ctrl->elem_size;
+		memset(ptr.p + idx, 0, ctrl->elem_size);
+		break;
+	}
+}
+
+static void std_log(const struct v4l2_ctrl *ctrl)
+{
+	union v4l2_ctrl_ptr ptr = ctrl->p_cur;
+
+	if (ctrl->is_array) {
+		unsigned i;
+
+		for (i = 0; i < ctrl->nr_of_dims; i++)
+			pr_cont("[%u]", ctrl->dims[i]);
+		pr_cont(" ");
+	}
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+		pr_cont("%d", *ptr.p_s32);
+		break;
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		pr_cont("%s", *ptr.p_s32 ? "true" : "false");
+		break;
+	case V4L2_CTRL_TYPE_MENU:
+		pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
+		break;
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+		pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
+		break;
+	case V4L2_CTRL_TYPE_BITMASK:
+		pr_cont("0x%08x", *ptr.p_s32);
+		break;
+	case V4L2_CTRL_TYPE_INTEGER64:
+		pr_cont("%lld", *ptr.p_s64);
+		break;
+	case V4L2_CTRL_TYPE_STRING:
+		pr_cont("%s", ptr.p_char);
+		break;
+	case V4L2_CTRL_TYPE_U8:
+		pr_cont("%u", (unsigned)*ptr.p_u8);
+		break;
+	case V4L2_CTRL_TYPE_U16:
+		pr_cont("%u", (unsigned)*ptr.p_u16);
+		break;
+	case V4L2_CTRL_TYPE_U32:
+		pr_cont("%u", (unsigned)*ptr.p_u32);
+		break;
+	default:
+		pr_cont("unknown type %d", ctrl->type);
+		break;
+	}
+}
+
+/*
+ * Round towards the closest legal value. Be careful when we are
+ * close to the maximum range of the control type to prevent
+ * wrap-arounds.
+ */
+#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
+({								\
+	offset_type offset;					\
+	if ((ctrl)->maximum >= 0 &&				\
+	    val >= (ctrl)->maximum - (s32)((ctrl)->step / 2))	\
+		val = (ctrl)->maximum;				\
+	else							\
+		val += (s32)((ctrl)->step / 2);			\
+	val = clamp_t(typeof(val), val,				\
+		      (ctrl)->minimum, (ctrl)->maximum);	\
+	offset = (val) - (ctrl)->minimum;			\
+	offset = (ctrl)->step * (offset / (u32)(ctrl)->step);	\
+	val = (ctrl)->minimum + offset;				\
+	0;							\
+})
+
+/* Validate a new control */
+static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
+			union v4l2_ctrl_ptr ptr)
+{
+	size_t len;
+	u64 offset;
+	s64 val;
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+		return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
+	case V4L2_CTRL_TYPE_INTEGER64:
+		/*
+		 * We can't use the ROUND_TO_RANGE define here due to
+		 * the u64 divide that needs special care.
+		 */
+		val = ptr.p_s64[idx];
+		if (ctrl->maximum >= 0 && val >= ctrl->maximum - (s64)(ctrl->step / 2))
+			val = ctrl->maximum;
+		else
+			val += (s64)(ctrl->step / 2);
+		val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
+		offset = val - ctrl->minimum;
+		do_div(offset, ctrl->step);
+		ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step;
+		return 0;
+	case V4L2_CTRL_TYPE_U8:
+		return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
+	case V4L2_CTRL_TYPE_U16:
+		return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl);
+	case V4L2_CTRL_TYPE_U32:
+		return ROUND_TO_RANGE(ptr.p_u32[idx], u32, ctrl);
+
+	case V4L2_CTRL_TYPE_BOOLEAN:
+		ptr.p_s32[idx] = !!ptr.p_s32[idx];
+		return 0;
+
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+		if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
+			return -ERANGE;
+		if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx]))
+			return -EINVAL;
+		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
+		    ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
+			return -EINVAL;
+		return 0;
+
+	case V4L2_CTRL_TYPE_BITMASK:
+		ptr.p_s32[idx] &= ctrl->maximum;
+		return 0;
+
+	case V4L2_CTRL_TYPE_BUTTON:
+	case V4L2_CTRL_TYPE_CTRL_CLASS:
+		ptr.p_s32[idx] = 0;
+		return 0;
+
+	case V4L2_CTRL_TYPE_STRING:
+		idx *= ctrl->elem_size;
+		len = strlen(ptr.p_char + idx);
+		if (len < ctrl->minimum)
+			return -ERANGE;
+		if ((len - (u32)ctrl->minimum) % (u32)ctrl->step)
+			return -ERANGE;
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ctrl_type_ops std_type_ops = {
+	.equal = std_equal,
+	.init = std_init,
+	.log = std_log,
+	.validate = std_validate,
+};
+
+/* Helper function: copy the given control value back to the caller */
+static int ptr_to_user(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr ptr)
 {
 	u32 len;
 
+	if (ctrl->is_ptr && !ctrl->is_string)
+		return copy_to_user(c->ptr, ptr.p, c->size) ?
+		       -EFAULT : 0;
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(ctrl->cur.string);
+		len = strlen(ptr.p_char);
 		if (c->size < len + 1) {
-			c->size = len + 1;
+			c->size = ctrl->elem_size;
 			return -ENOSPC;
 		}
-		return copy_to_user(c->string, ctrl->cur.string,
-						len + 1) ? -EFAULT : 0;
+		return copy_to_user(c->string, ptr.p_char, len + 1) ?
+		       -EFAULT : 0;
 	case V4L2_CTRL_TYPE_INTEGER64:
-		c->value64 = ctrl->cur.val64;
+		c->value64 = *ptr.p_s64;
 		break;
 	default:
-		c->value = ctrl->cur.val;
+		c->value = *ptr.p_s32;
 		break;
 	}
 	return 0;
 }
 
-/* Helper function: copy the caller-provider value as the new control value */
-static int user_to_new(struct v4l2_ext_control *c,
+/* Helper function: copy the current control value back to the caller */
+static int cur_to_user(struct v4l2_ext_control *c,
 		       struct v4l2_ctrl *ctrl)
 {
+	return ptr_to_user(c, ctrl, ctrl->p_cur);
+}
+
+/* Helper function: copy the new control value back to the caller */
+static int new_to_user(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl)
+{
+	return ptr_to_user(c, ctrl, ctrl->p_new);
+}
+
+/* Helper function: copy the caller-provider value to the given control value */
+static int user_to_ptr(struct v4l2_ext_control *c,
+		       struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr ptr)
+{
 	int ret;
 	u32 size;
 
 	ctrl->is_new = 1;
+	if (ctrl->is_ptr && !ctrl->is_string) {
+		unsigned idx;
+
+		ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
+		if (ret || !ctrl->is_array)
+			return ret;
+		for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
+			ctrl->type_ops->init(ctrl, idx, ptr);
+		return 0;
+	}
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER64:
-		ctrl->val64 = c->value64;
+		*ptr.p_s64 = c->value64;
 		break;
 	case V4L2_CTRL_TYPE_STRING:
 		size = c->size;
@@ -1209,74 +1511,53 @@ static int user_to_new(struct v4l2_ext_c
 			return -ERANGE;
 		if (size > ctrl->maximum + 1)
 			size = ctrl->maximum + 1;
-		ret = copy_from_user(ctrl->string, c->string, size);
+		ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
 		if (!ret) {
-			char last = ctrl->string[size - 1];
+			char last = ptr.p_char[size - 1];
 
-			ctrl->string[size - 1] = 0;
+			ptr.p_char[size - 1] = 0;
 			/* If the string was longer than ctrl->maximum,
 			   then return an error. */
-			if (strlen(ctrl->string) == ctrl->maximum && last)
+			if (strlen(ptr.p_char) == ctrl->maximum && last)
 				return -ERANGE;
 		}
-		return ret ? -EFAULT : 0;
+		return ret;
 	default:
-		ctrl->val = c->value;
+		*ptr.p_s32 = c->value;
 		break;
 	}
 	return 0;
 }
 
-/* Helper function: copy the new control value back to the caller */
-static int new_to_user(struct v4l2_ext_control *c,
+/* Helper function: copy the caller-provider value as the new control value */
+static int user_to_new(struct v4l2_ext_control *c,
 		       struct v4l2_ctrl *ctrl)
 {
-	u32 len;
+	return user_to_ptr(c, ctrl, ctrl->p_new);
+}
 
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(ctrl->string);
-		if (c->size < len + 1) {
-			c->size = ctrl->maximum + 1;
-			return -ENOSPC;
-		}
-		return copy_to_user(c->string, ctrl->string,
-						len + 1) ? -EFAULT : 0;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		c->value64 = ctrl->val64;
-		break;
-	default:
-		c->value = ctrl->val;
-		break;
-	}
-	return 0;
+/* Copy the one value to another. */
+static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
+		       union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
+{
+	if (ctrl == NULL)
+		return;
+	memcpy(to.p, from.p, ctrl->elems * ctrl->elem_size);
 }
 
 /* Copy the new value to the current value. */
 static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
 {
-	bool changed = false;
+	bool changed;
 
 	if (ctrl == NULL)
 		return;
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_BUTTON:
-		changed = true;
-		break;
-	case V4L2_CTRL_TYPE_STRING:
-		/* strings are always 0-terminated */
-		changed = strcmp(ctrl->string, ctrl->cur.string);
-		strcpy(ctrl->cur.string, ctrl->string);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		changed = ctrl->val64 != ctrl->cur.val64;
-		ctrl->cur.val64 = ctrl->val64;
-		break;
-	default:
-		changed = ctrl->val != ctrl->cur.val;
-		ctrl->cur.val = ctrl->val;
-		break;
-	}
+
+	/* has_changed is set by cluster_changed */
+	changed = ctrl->has_changed;
+	if (changed)
+		ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
+
 	if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
 		/* Note: CH_FLAGS is only set for auto clusters. */
 		ctrl->flags &=
@@ -1305,62 +1586,47 @@ static void cur_to_new(struct v4l2_ctrl
 {
 	if (ctrl == NULL)
 		return;
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_STRING:
-		/* strings are always 0-terminated */
-		strcpy(ctrl->string, ctrl->cur.string);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		ctrl->val64 = ctrl->cur.val64;
-		break;
-	default:
-		ctrl->val = ctrl->cur.val;
-		break;
-	}
+	ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
 }
 
 /* Return non-zero if one or more of the controls in the cluster has a new
    value that differs from the current value. */
 static int cluster_changed(struct v4l2_ctrl *master)
 {
-	int diff = 0;
+	bool changed = false;
+	unsigned idx;
 	int i;
 
-	for (i = 0; !diff && i < master->ncontrols; i++) {
+	for (i = 0; i < master->ncontrols; i++) {
 		struct v4l2_ctrl *ctrl = master->cluster[i];
+		bool ctrl_changed = false;
 
 		if (ctrl == NULL)
 			continue;
-		switch (ctrl->type) {
-		case V4L2_CTRL_TYPE_BUTTON:
-			/* Button controls are always 'different' */
-			return 1;
-		case V4L2_CTRL_TYPE_STRING:
-			/* strings are always 0-terminated */
-			diff = strcmp(ctrl->string, ctrl->cur.string);
-			break;
-		case V4L2_CTRL_TYPE_INTEGER64:
-			diff = ctrl->val64 != ctrl->cur.val64;
-			break;
-		default:
-			diff = ctrl->val != ctrl->cur.val;
-			break;
-		}
+		for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
+			ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
+				ctrl->p_cur, ctrl->p_new);
+		ctrl->has_changed = ctrl_changed;
+		changed |= ctrl->has_changed;
 	}
-	return diff;
+	return changed;
 }
 
 /* Control range checking */
 static int check_range(enum v4l2_ctrl_type type,
-		s32 min, s32 max, u32 step, s32 def)
+		s64 min, s64 max, u64 step, s64 def)
 {
 	switch (type) {
 	case V4L2_CTRL_TYPE_BOOLEAN:
 		if (step != 1 || max > 1 || min < 0)
 			return -ERANGE;
 		/* fall through */
+	case V4L2_CTRL_TYPE_U8:
+	case V4L2_CTRL_TYPE_U16:
+	case V4L2_CTRL_TYPE_U32:
 	case V4L2_CTRL_TYPE_INTEGER:
-		if (step <= 0 || min > max || def < min || def > max)
+	case V4L2_CTRL_TYPE_INTEGER64:
+		if (step == 0 || min > max || def < min || def > max)
 			return -ERANGE;
 		return 0;
 	case V4L2_CTRL_TYPE_BITMASK:
@@ -1389,58 +1655,33 @@ static int check_range(enum v4l2_ctrl_ty
 static int validate_new(const struct v4l2_ctrl *ctrl,
 			struct v4l2_ext_control *c)
 {
-	size_t len;
-	u32 offset;
-	s32 val;
-
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER:
-		/* Round towards the closest legal value */
-		val = c->value + ctrl->step / 2;
-		val = clamp(val, ctrl->minimum, ctrl->maximum);
-		offset = val - ctrl->minimum;
-		offset = ctrl->step * (offset / ctrl->step);
-		c->value = ctrl->minimum + offset;
-		return 0;
-
-	case V4L2_CTRL_TYPE_BOOLEAN:
-		c->value = !!c->value;
-		return 0;
-
-	case V4L2_CTRL_TYPE_MENU:
-	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		if (c->value < ctrl->minimum || c->value > ctrl->maximum)
-			return -ERANGE;
-		if (ctrl->menu_skip_mask & (1 << c->value))
-			return -EINVAL;
-		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
-		    ctrl->qmenu[c->value][0] == '\0')
-			return -EINVAL;
-		return 0;
-
-	case V4L2_CTRL_TYPE_BITMASK:
-		c->value &= ctrl->maximum;
-		return 0;
-
-	case V4L2_CTRL_TYPE_BUTTON:
-	case V4L2_CTRL_TYPE_CTRL_CLASS:
-		c->value = 0;
-		return 0;
-
-	case V4L2_CTRL_TYPE_INTEGER64:
-		return 0;
+	union v4l2_ctrl_ptr ptr;
+	unsigned idx;
+	int err = 0;
 
-	case V4L2_CTRL_TYPE_STRING:
-		len = strlen(c->string);
-		if (len < ctrl->minimum)
-			return -ERANGE;
-		if ((len - ctrl->minimum) % ctrl->step)
-			return -ERANGE;
-		return 0;
+	if (!ctrl->is_ptr) {
+		switch (ctrl->type) {
+		case V4L2_CTRL_TYPE_INTEGER:
+		case V4L2_CTRL_TYPE_INTEGER_MENU:
+		case V4L2_CTRL_TYPE_MENU:
+		case V4L2_CTRL_TYPE_BITMASK:
+		case V4L2_CTRL_TYPE_BOOLEAN:
+		case V4L2_CTRL_TYPE_BUTTON:
+		case V4L2_CTRL_TYPE_CTRL_CLASS:
+			ptr.p_s32 = &c->value;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
 
-	default:
-		return -EINVAL;
+		case V4L2_CTRL_TYPE_INTEGER64:
+			ptr.p_s64 = &c->value64;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
+		default:
+			break;
+		}
 	}
+	ptr.p = c->ptr;
+	for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+		err = ctrl->type_ops->validate(ctrl, idx, ptr);
+	return err;
 }
 
 static inline u32 node2id(struct list_head *node)
@@ -1522,7 +1763,7 @@ static struct v4l2_ctrl_ref *find_privat
 		   VIDIOC_G/S_CTRL. */
 		if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
 		    V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
-			if (!type_is_int(ref->ctrl))
+			if (!ref->ctrl->is_int)
 				continue;
 			if (id == 0)
 				return ref;
@@ -1592,8 +1833,12 @@ static int handler_new_ref(struct v4l2_c
 	u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
 	int bucket = id % hdl->nr_of_buckets;	/* which bucket to use */
 
-	/* Automatically add the control class if it is not yet present. */
-	if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
+	/*
+	 * Automatically add the control class if it is not yet present and
+	 * the new control is not a compound control.
+	 */
+	if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES &&
+	    id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
 		if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
 			return hdl->error;
 
@@ -1652,20 +1897,61 @@ unlock:
 /* Add a new control */
 static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
+			const struct v4l2_ctrl_type_ops *type_ops,
 			u32 id, const char *name, enum v4l2_ctrl_type type,
-			s32 min, s32 max, u32 step, s32 def,
+			s64 min, s64 max, u64 step, s64 def,
+			const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
 			u32 flags, const char * const *qmenu,
 			const s64 *qmenu_int, void *priv)
 {
 	struct v4l2_ctrl *ctrl;
-	unsigned sz_extra = 0;
+	unsigned sz_extra;
+	unsigned nr_of_dims = 0;
+	unsigned elems = 1;
+	bool is_array;
+	unsigned tot_ctrl_size;
+	unsigned idx;
+	void *data;
 	int err;
 
 	if (hdl->error)
 		return NULL;
 
+	while (dims && dims[nr_of_dims]) {
+		elems *= dims[nr_of_dims];
+		nr_of_dims++;
+		if (nr_of_dims == V4L2_CTRL_MAX_DIMS)
+			break;
+	}
+	is_array = nr_of_dims > 0;
+
+	/* Prefill elem_size for all types handled by std_type_ops */
+	switch (type) {
+	case V4L2_CTRL_TYPE_INTEGER64:
+		elem_size = sizeof(s64);
+		break;
+	case V4L2_CTRL_TYPE_STRING:
+		elem_size = max + 1;
+		break;
+	case V4L2_CTRL_TYPE_U8:
+		elem_size = sizeof(u8);
+		break;
+	case V4L2_CTRL_TYPE_U16:
+		elem_size = sizeof(u16);
+		break;
+	case V4L2_CTRL_TYPE_U32:
+		elem_size = sizeof(u32);
+		break;
+	default:
+		if (type < V4L2_CTRL_COMPOUND_TYPES)
+			elem_size = sizeof(s32);
+		break;
+	}
+	tot_ctrl_size = elem_size * elems;
+
 	/* Sanity checks */
-	if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
+	if (id == 0 || name == NULL || !elem_size ||
+	    id >= V4L2_CID_PRIVATE_BASE ||
 	    (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
 	    (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
 		handler_set_err(hdl, -ERANGE);
@@ -1680,13 +1966,23 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
 		handler_set_err(hdl, -ERANGE);
 		return NULL;
 	}
+	if (is_array &&
+	    (type == V4L2_CTRL_TYPE_BUTTON ||
+	     type == V4L2_CTRL_TYPE_CTRL_CLASS)) {
+		handler_set_err(hdl, -EINVAL);
+		return NULL;
+	}
 
+	sz_extra = 0;
 	if (type == V4L2_CTRL_TYPE_BUTTON)
 		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		flags |= V4L2_CTRL_FLAG_READ_ONLY;
-	else if (type == V4L2_CTRL_TYPE_STRING)
-		sz_extra += 2 * (max + 1);
+	else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
+		 type == V4L2_CTRL_TYPE_STRING ||
+		 type >= V4L2_CTRL_COMPOUND_TYPES ||
+		 is_array)
+		sz_extra += 2 * tot_ctrl_size;
 
 	ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
 	if (ctrl == NULL) {
@@ -1698,6 +1994,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
 	INIT_LIST_HEAD(&ctrl->ev_subs);
 	ctrl->handler = hdl;
 	ctrl->ops = ops;
+	ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
 	ctrl->id = id;
 	ctrl->name = name;
 	ctrl->type = type;
@@ -1705,19 +2002,36 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
 	ctrl->minimum = min;
 	ctrl->maximum = max;
 	ctrl->step = step;
+	ctrl->default_value = def;
+	ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING;
+	ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string;
+	ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+	ctrl->is_array = is_array;
+	ctrl->elems = elems;
+	ctrl->nr_of_dims = nr_of_dims;
+	if (nr_of_dims)
+		memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0]));
+	ctrl->elem_size = elem_size;
 	if (type == V4L2_CTRL_TYPE_MENU)
 		ctrl->qmenu = qmenu;
 	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
 		ctrl->qmenu_int = qmenu_int;
 	ctrl->priv = priv;
-	ctrl->cur.val = ctrl->val = ctrl->default_value = def;
+	ctrl->cur.val = ctrl->val = def;
+	data = &ctrl[1];
 
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
-		ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1);
-		ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1);
-		if (ctrl->minimum)
-			memset(ctrl->cur.string, ' ', ctrl->minimum);
+	if (!ctrl->is_int) {
+		ctrl->p_new.p = data;
+		ctrl->p_cur.p = data + tot_ctrl_size;
+	} else {
+		ctrl->p_new.p = &ctrl->val;
+		ctrl->p_cur.p = &ctrl->cur.val;
 	}
+	for (idx = 0; idx < elems; idx++) {
+		ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
+		ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
+	}
+
 	if (handler_new_ref(hdl, ctrl)) {
 		kfree(ctrl);
 		return NULL;
@@ -1738,10 +2052,10 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(s
 	const s64 *qmenu_int = cfg->qmenu_int;
 	enum v4l2_ctrl_type type = cfg->type;
 	u32 flags = cfg->flags;
-	s32 min = cfg->min;
-	s32 max = cfg->max;
-	u32 step = cfg->step;
-	s32 def = cfg->def;
+	s64 min = cfg->min;
+	s64 max = cfg->max;
+	u64 step = cfg->step;
+	s64 def = cfg->def;
 
 	if (name == NULL)
 		v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
@@ -1761,10 +2075,11 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(s
 		return NULL;
 	}
 
-	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
+	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name,
 			type, min, max,
-			is_menu ? cfg->menu_skip_mask : step,
-			def, flags, qmenu, qmenu_int, priv);
+			is_menu ? cfg->menu_skip_mask : step, def,
+			cfg->dims, cfg->elem_size,
+			flags, qmenu, qmenu_int, priv);
 	if (ctrl)
 		ctrl->is_private = cfg->is_private;
 	return ctrl;
@@ -1774,35 +2089,39 @@ EXPORT_SYMBOL(v4l2_ctrl_new_custom);
 /* Helper function for standard non-menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 min, s32 max, u32 step, s32 def)
+			u32 id, s64 min, s64 max, u64 step, s64 def)
 {
 	const char *name;
 	enum v4l2_ctrl_type type;
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
-	if (type == V4L2_CTRL_TYPE_MENU
-	    || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
+	if (type == V4L2_CTRL_TYPE_MENU ||
+	    type == V4L2_CTRL_TYPE_INTEGER_MENU ||
+	    type >= V4L2_CTRL_COMPOUND_TYPES) {
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
-			     min, max, step, def, flags, NULL, NULL, NULL);
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+			     min, max, step, def, NULL, 0,
+			     flags, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std);
 
 /* Helper function for standard menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 max, s32 mask, s32 def)
+			u32 id, u8 _max, u64 mask, u8 _def)
 {
 	const char * const *qmenu = NULL;
 	const s64 *qmenu_int = NULL;
 	unsigned int qmenu_int_len = 0;
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 min;
-	s32 step;
+	s64 min;
+	s64 max = _max;
+	s64 def = _def;
+	u64 step;
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1816,21 +2135,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
-			     0, max, mask, def, flags, qmenu, qmenu_int, NULL);
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+			     0, max, mask, def, NULL, 0,
+			     flags, qmenu, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
 /* Helper function for standard menu controls with driver defined menu */
 struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
-			const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
-			s32 mask, s32 def, const char * const *qmenu)
+			const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
+			u64 mask, u8 _def, const char * const *qmenu)
 {
 	enum v4l2_ctrl_type type;
 	const char *name;
 	u32 flags;
-	s32 step;
-	s32 min;
+	u64 step;
+	s64 min;
+	s64 max = _max;
+	s64 def = _def;
 
 	/* v4l2_ctrl_new_std_menu_items() should only be called for
 	 * standard controls without a standard menu.
@@ -1845,7 +2167,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+			     0, max, mask, def, NULL, 0,
 			     flags, qmenu, NULL, NULL);
 
 }
@@ -1854,12 +2177,14 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_ite
 /* Helper function for standard integer menu controls */
 struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
-			u32 id, s32 max, s32 def, const s64 *qmenu_int)
+			u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
 {
 	const char *name;
 	enum v4l2_ctrl_type type;
-	s32 min;
-	s32 step;
+	s64 min;
+	u64 step;
+	s64 max = _max;
+	s64 def = _def;
 	u32 flags;
 
 	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1867,8 +2192,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu
 		handler_set_err(hdl, -EINVAL);
 		return NULL;
 	}
-	return v4l2_ctrl_new(hdl, ops, id, name, type,
-			     0, max, 0, def, flags, NULL, qmenu_int, NULL);
+	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+			     0, max, 0, def, NULL, 0,
+			     flags, NULL, qmenu_int, NULL);
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
 
@@ -2048,45 +2374,21 @@ static void log_ctrl(const struct v4l2_c
 	if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
 		return;
 
-	printk(KERN_INFO "%s%s%s: ", prefix, colon, ctrl->name);
+	pr_info("%s%s%s: ", prefix, colon, ctrl->name);
+
+	ctrl->type_ops->log(ctrl);
 
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_INTEGER:
-		printk(KERN_CONT "%d", ctrl->cur.val);
-		break;
-	case V4L2_CTRL_TYPE_BOOLEAN:
-		printk(KERN_CONT "%s", ctrl->cur.val ? "true" : "false");
-		break;
-	case V4L2_CTRL_TYPE_MENU:
-		printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER_MENU:
-		printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
-		break;
-	case V4L2_CTRL_TYPE_BITMASK:
-		printk(KERN_CONT "0x%08x", ctrl->cur.val);
-		break;
-	case V4L2_CTRL_TYPE_INTEGER64:
-		printk(KERN_CONT "%lld", ctrl->cur.val64);
-		break;
-	case V4L2_CTRL_TYPE_STRING:
-		printk(KERN_CONT "%s", ctrl->cur.string);
-		break;
-	default:
-		printk(KERN_CONT "unknown type %d", ctrl->type);
-		break;
-	}
 	if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
 			   V4L2_CTRL_FLAG_GRABBED |
 			   V4L2_CTRL_FLAG_VOLATILE)) {
 		if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
-			printk(KERN_CONT " inactive");
+			pr_cont(" inactive");
 		if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
-			printk(KERN_CONT " grabbed");
+			pr_cont(" grabbed");
 		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
-			printk(KERN_CONT " volatile");
+			pr_cont(" volatile");
 	}
-	printk(KERN_CONT "\n");
+	pr_cont("\n");
 }
 
 /* Log all controls owned by the handler */
@@ -2157,9 +2459,10 @@ int v4l2_ctrl_handler_setup(struct v4l2_
 }
 EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
 
-/* Implement VIDIOC_QUERYCTRL */
-int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+/* Implement VIDIOC_QUERY_EXT_CTRL */
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
 {
+	const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
 	u32 id = qc->id & V4L2_CTRL_ID_MASK;
 	struct v4l2_ctrl_ref *ref;
 	struct v4l2_ctrl *ctrl;
@@ -2172,7 +2475,20 @@ int v4l2_queryctrl(struct v4l2_ctrl_hand
 	/* Try to find it */
 	ref = find_ref(hdl, id);
 
-	if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
+	if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
+		bool is_compound;
+		/* Match any control that is not hidden */
+		unsigned mask = 1;
+		bool match = false;
+
+		if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
+			/* Match any hidden control */
+			match = true;
+		} else if ((qc->id & next_flags) == next_flags) {
+			/* Match any control, compound or not */
+			mask = 0;
+		}
+
 		/* Find the next control with ID > qc->id */
 
 		/* Did we reach the end of the control list? */
@@ -2180,19 +2496,34 @@ int v4l2_queryctrl(struct v4l2_ctrl_hand
 			ref = NULL; /* Yes, so there is no next control */
 		} else if (ref) {
 			/* We found a control with the given ID, so just get
-			   the next one in the list. */
-			ref = list_entry(ref->node.next, typeof(*ref), node);
+			   the next valid one in the list. */
+			list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
+				is_compound =
+					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+				if (id < ref->ctrl->id &&
+				    (is_compound & mask) == match)
+					break;
+			}
+			if (&ref->node == &hdl->ctrl_refs)
+				ref = NULL;
 		} else {
 			/* No control with the given ID exists, so start
 			   searching for the next largest ID. We know there
 			   is one, otherwise the first 'if' above would have
 			   been true. */
-			list_for_each_entry(ref, &hdl->ctrl_refs, node)
-				if (id < ref->ctrl->id)
+			list_for_each_entry(ref, &hdl->ctrl_refs, node) {
+				is_compound =
+					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+				if (id < ref->ctrl->id &&
+				    (is_compound & mask) == match)
 					break;
+			}
+			if (&ref->node == &hdl->ctrl_refs)
+				ref = NULL;
 		}
 	}
 	mutex_unlock(hdl->lock);
+
 	if (!ref)
 		return -EINVAL;
 
@@ -2203,6 +2534,14 @@ int v4l2_queryctrl(struct v4l2_ctrl_hand
 	else
 		qc->id = ctrl->id;
 	strlcpy(qc->name, ctrl->name, sizeof(qc->name));
+	qc->flags = ctrl->flags;
+	qc->type = ctrl->type;
+	if (ctrl->is_ptr)
+		qc->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD;
+	qc->elem_size = ctrl->elem_size;
+	qc->elems = ctrl->elems;
+	qc->nr_of_dims = ctrl->nr_of_dims;
+	memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
 	qc->minimum = ctrl->minimum;
 	qc->maximum = ctrl->maximum;
 	qc->default_value = ctrl->default_value;
@@ -2211,15 +2550,50 @@ int v4l2_queryctrl(struct v4l2_ctrl_hand
 		qc->step = 1;
 	else
 		qc->step = ctrl->step;
-	qc->flags = ctrl->flags;
-	qc->type = ctrl->type;
+	return 0;
+}
+EXPORT_SYMBOL(v4l2_query_ext_ctrl);
+
+/* Implement VIDIOC_QUERYCTRL */
+int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+{
+	struct v4l2_query_ext_ctrl qec = { qc->id };
+	int rc;
+
+	rc = v4l2_query_ext_ctrl(hdl, &qec);
+	if (rc)
+		return rc;
+
+	qc->id = qec.id;
+	qc->type = qec.type;
+	qc->flags = qec.flags;
+	strlcpy(qc->name, qec.name, sizeof(qc->name));
+	switch (qc->type) {
+	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER_MENU:
+	case V4L2_CTRL_TYPE_STRING:
+	case V4L2_CTRL_TYPE_BITMASK:
+		qc->minimum = qec.minimum;
+		qc->maximum = qec.maximum;
+		qc->step = qec.step;
+		qc->default_value = qec.default_value;
+		break;
+	default:
+		qc->minimum = 0;
+		qc->maximum = 0;
+		qc->step = 0;
+		qc->default_value = 0;
+		break;
+	}
 	return 0;
 }
 EXPORT_SYMBOL(v4l2_queryctrl);
 
 int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 {
-	if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+	if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND))
 		return -EINVAL;
 	return v4l2_queryctrl(sd->ctrl_handler, qc);
 }
@@ -2319,7 +2693,8 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
    Find the controls in the control array and do some basic checks. */
 static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
 			     struct v4l2_ext_controls *cs,
-			     struct v4l2_ctrl_helper *helpers)
+			     struct v4l2_ctrl_helper *helpers,
+			     bool get)
 {
 	struct v4l2_ctrl_helper *h;
 	bool have_clusters = false;
@@ -2351,6 +2726,18 @@ static int prepare_ext_ctrls(struct v4l2
 			have_clusters = true;
 		if (ctrl->cluster[0] != ctrl)
 			ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
+		if (ctrl->is_ptr && !ctrl->is_string) {
+			unsigned tot_size = ctrl->elems * ctrl->elem_size;
+
+			if (c->size < tot_size) {
+				if (get) {
+					c->size = tot_size;
+					return -ENOSPC;
+				}
+				return -EFAULT;
+			}
+			c->size = tot_size;
+		}
 		/* Store the ref to the master control of the cluster */
 		h->mref = ref;
 		h->ctrl = ctrl;
@@ -2431,7 +2818,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_ha
 			return -ENOMEM;
 	}
 
-	ret = prepare_ext_ctrls(hdl, cs, helpers);
+	ret = prepare_ext_ctrls(hdl, cs, helpers, true);
 	cs->error_idx = cs->count;
 
 	for (i = 0; !ret && i < cs->count; i++)
@@ -2493,11 +2880,11 @@ static int get_ctrl(struct v4l2_ctrl *ct
 	int ret = 0;
 	int i;
 
-	/* String controls are not supported. The new_to_user() and
+	/* Compound controls are not supported. The new_to_user() and
 	 * cur_to_user() calls below would need to be modified not to access
 	 * userspace memory when called from get_ctrl().
 	 */
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+	if (!ctrl->is_int)
 		return -EINVAL;
 
 	if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
@@ -2523,7 +2910,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler
 	struct v4l2_ext_control c;
 	int ret;
 
-	if (ctrl == NULL || !type_is_int(ctrl))
+	if (ctrl == NULL || !ctrl->is_int)
 		return -EINVAL;
 	ret = get_ctrl(ctrl, &c);
 	control->value = c.value;
@@ -2542,7 +2929,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *c
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(!type_is_int(ctrl));
+	WARN_ON(!ctrl->is_int);
 	c.value = 0;
 	get_ctrl(ctrl, &c);
 	return c.value;
@@ -2554,7 +2941,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_c
 	struct v4l2_ext_control c;
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+	WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
 	c.value = 0;
 	get_ctrl(ctrl, &c);
 	return c.value;
@@ -2678,7 +3065,7 @@ static int try_set_ext_ctrls(struct v4l2
 		if (!helpers)
 			return -ENOMEM;
 	}
-	ret = prepare_ext_ctrls(hdl, cs, helpers);
+	ret = prepare_ext_ctrls(hdl, cs, helpers, false);
 	if (!ret)
 		ret = validate_ctrls(cs, helpers, set);
 	if (ret && set)
@@ -2783,26 +3170,22 @@ static int set_ctrl(struct v4l2_fh *fh,
 	struct v4l2_ctrl *master = ctrl->cluster[0];
 	int i;
 
-	/* String controls are not supported. The user_to_new() and
-	 * cur_to_user() calls below would need to be modified not to access
-	 * userspace memory when called from set_ctrl().
-	 */
-	if (ctrl->type == V4L2_CTRL_TYPE_STRING)
-		return -EINVAL;
-
 	/* Reset the 'is_new' flags of the cluster */
 	for (i = 0; i < master->ncontrols; i++)
 		if (master->cluster[i])
 			master->cluster[i]->is_new = 0;
 
+	if (c)
+		user_to_new(c, ctrl);
+
 	/* For autoclusters with volatiles that are switched from auto to
 	   manual mode we have to update the current volatile values since
 	   those will become the initial manual values after such a switch. */
 	if (master->is_auto && master->has_volatiles && ctrl == master &&
-	    !is_cur_manual(master) && c->value == master->manual_mode_value)
+	    !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
 		update_from_auto_cluster(master);
 
-	user_to_new(c, ctrl);
+	ctrl->is_new = 1;
 	return try_or_set_cluster(fh, master, true, ch_flags);
 }
 
@@ -2829,7 +3212,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, stru
 	struct v4l2_ext_control c;
 	int ret;
 
-	if (ctrl == NULL || !type_is_int(ctrl))
+	if (ctrl == NULL || !ctrl->is_int)
 		return -EINVAL;
 
 	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
@@ -2848,27 +3231,38 @@ int v4l2_subdev_s_ctrl(struct v4l2_subde
 }
 EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
 
-int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
+int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
 {
-	struct v4l2_ext_control c;
+	lockdep_assert_held(ctrl->handler->lock);
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(!type_is_int(ctrl));
-	c.value = val;
-	return set_ctrl_lock(NULL, ctrl, &c);
+	WARN_ON(!ctrl->is_int);
+	ctrl->val = val;
+	return set_ctrl(NULL, ctrl, NULL, 0);
 }
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
 
-int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
+int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
 {
-	struct v4l2_ext_control c;
+	lockdep_assert_held(ctrl->handler->lock);
 
 	/* It's a driver bug if this happens. */
-	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
-	c.value64 = val;
-	return set_ctrl_lock(NULL, ctrl, &c);
+	WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+	*ctrl->p_new.p_s64 = val;
+	return set_ctrl(NULL, ctrl, NULL, 0);
 }
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
+
+int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
+{
+	lockdep_assert_held(ctrl->handler->lock);
+
+	/* It's a driver bug if this happens. */
+	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
+	strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
+	return set_ctrl(NULL, ctrl, NULL, 0);
+}
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
 
 void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
 {
@@ -2886,40 +3280,47 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *
 }
 EXPORT_SYMBOL(v4l2_ctrl_notify);
 
-int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
-			s32 min, s32 max, u32 step, s32 def)
+int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
+			s64 min, s64 max, u64 step, s64 def)
 {
-	int ret = check_range(ctrl->type, min, max, step, def);
+	int ret;
 	struct v4l2_ext_control c;
 
+	lockdep_assert_held(ctrl->handler->lock);
+
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER:
+	case V4L2_CTRL_TYPE_INTEGER64:
 	case V4L2_CTRL_TYPE_BOOLEAN:
 	case V4L2_CTRL_TYPE_MENU:
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
 	case V4L2_CTRL_TYPE_BITMASK:
+	case V4L2_CTRL_TYPE_U8:
+	case V4L2_CTRL_TYPE_U16:
+	case V4L2_CTRL_TYPE_U32:
+		if (ctrl->is_array)
+			return -EINVAL;
+		ret = check_range(ctrl->type, min, max, step, def);
 		if (ret)
 			return ret;
 		break;
 	default:
 		return -EINVAL;
 	}
-	v4l2_ctrl_lock(ctrl);
 	ctrl->minimum = min;
 	ctrl->maximum = max;
 	ctrl->step = step;
 	ctrl->default_value = def;
-	c.value = ctrl->cur.val;
+	c.value = *ctrl->p_cur.p_s32;
 	if (validate_new(ctrl, &c))
 		c.value = def;
-	if (c.value != ctrl->cur.val)
+	if (c.value != *ctrl->p_cur.p_s32)
 		ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
 	else
 		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
-	v4l2_ctrl_unlock(ctrl);
 	return ret;
 }
-EXPORT_SYMBOL(v4l2_ctrl_modify_range);
+EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
 
 static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-dev.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-dev.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -335,7 +335,7 @@ static unsigned int v4l2_poll(struct fil
 		return DEFAULT_POLLMASK;
 	if (video_is_registered(vdev))
 		res = vdev->fops->poll(filp, poll);
-	if (vdev->debug)
+	if (vdev->debug > 2)
 		printk(KERN_DEBUG "%s: poll: %08x\n",
 			video_device_node_name(vdev), res);
 	return res;
@@ -563,20 +563,18 @@ static void determine_valid_ioctls(struc
 	/* vfl_type and vfl_dir independent ioctls */
 
 	SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
-	if (ops->vidioc_g_priority ||
-			test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+	if (ops->vidioc_g_priority)
 		set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
-	if (ops->vidioc_s_priority ||
-			test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+	if (ops->vidioc_s_priority)
 		set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
-	SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
-	SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
 	/* Note: the control handler can also be passed through the filehandle,
 	   and that can't be tested here. If the bit for these control ioctls
 	   is set, then the ioctl is valid. But if it is 0, then it can still
 	   be valid if the filehandle passed the control handler. */
 	if (vdev->ctrl_handler || ops->vidioc_queryctrl)
 		set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
+	if (vdev->ctrl_handler || ops->vidioc_query_ext_ctrl)
+		set_bit(_IOC_NR(VIDIOC_QUERY_EXT_CTRL), valid_ioctls);
 	if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
 		set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
 	if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
@@ -684,6 +682,8 @@ static void determine_valid_ioctls(struc
 		SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
 		SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
 		SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
+		SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
+		SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
 	}
 
 	if (is_vid || is_vbi) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-fh.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-fh.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-fh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-fh.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,13 @@ void v4l2_fh_init(struct v4l2_fh *fh, st
 	fh->ctrl_handler = vdev->ctrl_handler;
 	INIT_LIST_HEAD(&fh->list);
 	set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
+	/*
+	 * determine_valid_ioctls() does not know if struct v4l2_fh
+	 * is used by this driver, but here we do. So enable the
+	 * prio ioctls here.
+	 */
+	set_bit(_IOC_NR(VIDIOC_G_PRIORITY), vdev->valid_ioctls);
+	set_bit(_IOC_NR(VIDIOC_S_PRIORITY), vdev->valid_ioctls);
 	fh->prio = V4L2_PRIORITY_UNSET;
 	init_waitqueue_head(&fh->wait);
 	INIT_LIST_HEAD(&fh->available);
@@ -49,8 +56,7 @@ void v4l2_fh_add(struct v4l2_fh *fh)
 {
 	unsigned long flags;
 
-	if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
-		v4l2_prio_open(fh->vdev->prio, &fh->prio);
+	v4l2_prio_open(fh->vdev->prio, &fh->prio);
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 	list_add(&fh->list, &fh->vdev->fh_list);
 	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
@@ -78,8 +84,7 @@ void v4l2_fh_del(struct v4l2_fh *fh)
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 	list_del_init(&fh->list);
 	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-	if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
-		v4l2_prio_close(fh->vdev->prio, fh->prio);
+	v4l2_prio_close(fh->vdev->prio, fh->prio);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_del);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-ioctl.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-ioctl.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -256,7 +256,8 @@ static void v4l_print_format(const void
 		pix = &p->fmt.pix;
 		pr_cont(", width=%u, height=%u, "
 			"pixelformat=%c%c%c%c, field=%s, "
-			"bytesperline=%u, sizeimage=%u, colorspace=%d\n",
+			"bytesperline=%u, sizeimage=%u, colorspace=%d, "
+			"flags %u\n",
 			pix->width, pix->height,
 			(pix->pixelformat & 0xff),
 			(pix->pixelformat >>  8) & 0xff,
@@ -264,7 +265,7 @@ static void v4l_print_format(const void
 			(pix->pixelformat >> 24) & 0xff,
 			prt_names(pix->field, v4l2_field_names),
 			pix->bytesperline, pix->sizeimage,
-			pix->colorspace);
+			pix->colorspace, pix->flags);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
@@ -525,6 +526,20 @@ static void v4l_print_queryctrl(const vo
 			p->step, p->default_value, p->flags);
 }
 
+static void v4l_print_query_ext_ctrl(const void *arg, bool write_only)
+{
+	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",
+			p->id, p->type, (int)sizeof(p->name), p->name,
+			p->minimum, p->maximum,
+			p->step, p->default_value, p->flags,
+			p->elem_size, p->elems, p->nr_of_dims,
+			p->dims[0], p->dims[1], p->dims[2], p->dims[3]);
+}
+
 static void v4l_print_querymenu(const void *arg, bool write_only)
 {
 	const struct v4l2_querymenu *p = arg;
@@ -959,13 +974,49 @@ static int check_fmt(struct file *file,
 	return -EINVAL;
 }
 
+static void v4l_sanitize_format(struct v4l2_format *fmt)
+{
+	unsigned int offset;
+
+	/*
+	 * The v4l2_pix_format structure has been extended with fields that were
+	 * not previously required to be set to zero by applications. The priv
+	 * field, when set to a magic value, indicates the the extended fields
+	 * are valid. Otherwise they will contain undefined values. To simplify
+	 * the API towards drivers zero the extended fields and set the priv
+	 * field to the magic value when the extended pixel format structure
+	 * isn't used by applications.
+	 */
+
+	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return;
+
+	if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
+		return;
+
+	fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+	offset = offsetof(struct v4l2_pix_format, priv)
+	       + sizeof(fmt->fmt.pix.priv);
+	memset(((void *)&fmt->fmt.pix) + offset, 0,
+	       sizeof(fmt->fmt.pix) - offset);
+}
+
 static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 	struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+	int ret;
 
 	cap->version = LINUX_VERSION_CODE;
-	return ops->vidioc_querycap(file, fh, cap);
+
+	ret = ops->vidioc_querycap(file, fh, cap);
+
+	cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
+	cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
+
+	return ret;
 }
 
 static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1048,32 +1099,34 @@ static int v4l_enum_fmt(const struct v4l
 {
 	struct v4l2_fmtdesc *p = arg;
 	struct video_device *vfd = video_devdata(file);
+	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap))
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap))
 			break;
 		return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane))
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane))
 			break;
 		return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay))
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay))
 			break;
 		return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out))
+		if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out))
 			break;
 		return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
+		if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane))
 			break;
 		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
-		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
+		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap))
 			break;
 		return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
 	}
@@ -1089,12 +1142,41 @@ static int v4l_g_fmt(const struct v4l2_i
 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+	int ret;
+
+	/*
+	 * fmt can't be cleared for these overlay types due to the 'clips'
+	 * 'clipcount' and 'bitmap' pointers in struct v4l2_window.
+	 * Those are provided by the user. So handle these two overlay types
+	 * first, and then just do a simple memset for the other types.
+	 */
+	switch (p->type) {
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+		struct v4l2_clip *clips = p->fmt.win.clips;
+		u32 clipcount = p->fmt.win.clipcount;
+		void *bitmap = p->fmt.win.bitmap;
+
+		memset(&p->fmt, 0, sizeof(p->fmt));
+		p->fmt.win.clips = clips;
+		p->fmt.win.clipcount = clipcount;
+		p->fmt.win.bitmap = bitmap;
+		break;
+	}
+	default:
+		memset(&p->fmt, 0, sizeof(p->fmt));
+		break;
+	}
 
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
 			break;
-		return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
 			break;
@@ -1114,7 +1196,11 @@ static int v4l_g_fmt(const struct v4l2_i
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
 			break;
-		return ops->vidioc_g_fmt_vid_out(file, fh, arg);
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
 			break;
@@ -1148,13 +1234,19 @@ static int v4l_s_fmt(const struct v4l2_i
 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+	int ret;
+
+	v4l_sanitize_format(p);
 
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.pix);
-		return ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+		ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
 			break;
@@ -1179,7 +1271,10 @@ static int v4l_s_fmt(const struct v4l2_i
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.pix);
-		return ops->vidioc_s_fmt_vid_out(file, fh, arg);
+		ret = ops->vidioc_s_fmt_vid_out(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
 			break;
@@ -1218,13 +1313,19 @@ static int v4l_try_fmt(const struct v4l2
 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+	int ret;
+
+	v4l_sanitize_format(p);
 
 	switch (p->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.pix);
-		return ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+		ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
 			break;
@@ -1249,7 +1350,10 @@ static int v4l_try_fmt(const struct v4l2
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.pix);
-		return ops->vidioc_try_fmt_vid_out(file, fh, arg);
+		ret = ops->vidioc_try_fmt_vid_out(file, fh, arg);
+		/* just in case the driver zeroed it again */
+		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		return ret;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
 			break;
@@ -1502,7 +1606,18 @@ static int v4l_create_bufs(const struct
 	struct v4l2_create_buffers *create = arg;
 	int ret = check_fmt(file, create->format.type);
 
-	return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
+	if (ret)
+		return ret;
+
+	v4l_sanitize_format(&create->format);
+
+	ret = ops->vidioc_create_bufs(file, fh, create);
+
+	if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+	return ret;
 }
 
 static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
@@ -1561,6 +1676,23 @@ static int v4l_queryctrl(const struct v4
 	return -ENOTTY;
 }
 
+static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops,
+				struct file *file, void *fh, void *arg)
+{
+	struct video_device *vfd = video_devdata(file);
+	struct v4l2_query_ext_ctrl *p = arg;
+	struct v4l2_fh *vfh =
+		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
+
+	if (vfh && vfh->ctrl_handler)
+		return v4l2_query_ext_ctrl(vfh->ctrl_handler, p);
+	if (vfd->ctrl_handler)
+		return v4l2_query_ext_ctrl(vfd->ctrl_handler, p);
+	if (ops->vidioc_query_ext_ctrl)
+		return ops->vidioc_query_ext_ctrl(file, fh, p);
+	return -ENOTTY;
+}
+
 static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -1751,37 +1883,41 @@ static int v4l_cropcap(const struct v4l2
 				struct file *file, void *fh, void *arg)
 {
 	struct v4l2_cropcap *p = arg;
-	struct v4l2_selection s = { .type = p->type };
-	int ret;
 
-	if (ops->vidioc_cropcap)
-		return ops->vidioc_cropcap(file, fh, p);
+	if (ops->vidioc_g_selection) {
+		struct v4l2_selection s = { .type = p->type };
+		int ret;
 
-	/* obtaining bounds */
-	if (V4L2_TYPE_IS_OUTPUT(p->type))
-		s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
-	else
-		s.target = V4L2_SEL_TGT_CROP_BOUNDS;
+		/* obtaining bounds */
+		if (V4L2_TYPE_IS_OUTPUT(p->type))
+			s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+		else
+			s.target = V4L2_SEL_TGT_CROP_BOUNDS;
 
-	ret = ops->vidioc_g_selection(file, fh, &s);
-	if (ret)
-		return ret;
-	p->bounds = s.r;
+		ret = ops->vidioc_g_selection(file, fh, &s);
+		if (ret)
+			return ret;
+		p->bounds = s.r;
 
-	/* obtaining defrect */
-	if (V4L2_TYPE_IS_OUTPUT(p->type))
-		s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
-	else
-		s.target = V4L2_SEL_TGT_CROP_DEFAULT;
+		/* obtaining defrect */
+		if (V4L2_TYPE_IS_OUTPUT(p->type))
+			s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+		else
+			s.target = V4L2_SEL_TGT_CROP_DEFAULT;
 
-	ret = ops->vidioc_g_selection(file, fh, &s);
-	if (ret)
-		return ret;
-	p->defrect = s.r;
+		ret = ops->vidioc_g_selection(file, fh, &s);
+		if (ret)
+			return ret;
+		p->defrect = s.r;
+	}
 
 	/* setting trivial pixelaspect */
 	p->pixelaspect.numerator = 1;
 	p->pixelaspect.denominator = 1;
+
+	if (ops->vidioc_cropcap)
+		return ops->vidioc_cropcap(file, fh, p);
+
 	return 0;
 }
 
@@ -1951,8 +2087,11 @@ static int v4l_enum_freq_bands(const str
 		if (type != p->type)
 			return -EINVAL;
 	}
-	if (ops->vidioc_enum_freq_bands)
-		return ops->vidioc_enum_freq_bands(file, fh, p);
+	if (ops->vidioc_enum_freq_bands) {
+		err = ops->vidioc_enum_freq_bands(file, fh, p);
+		if (err != -ENOTTY)
+			return err;
+	}
 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
 		struct v4l2_tuner t = {
 			.index = p->tuner,
@@ -2042,7 +2181,7 @@ struct v4l2_ioctl_info {
 static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
 	IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
-	IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)),
+	IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0),
 	IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
 	IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
@@ -2070,8 +2209,8 @@ static struct v4l2_ioctl_info v4l2_ioctl
 	IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
 	IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
 	IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
-	IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)),
-	IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)),
+	IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0),
+	IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO),
 	IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
 	IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
@@ -2084,8 +2223,8 @@ static struct v4l2_ioctl_info v4l2_ioctl
 	IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
 	IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
 	IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
-	IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0),
-	IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO),
+	IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)),
+	IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)),
 	IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
 	IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
@@ -2121,6 +2260,7 @@ static struct v4l2_ioctl_info v4l2_ioctl
 	IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
+	IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -2190,7 +2330,6 @@ static long __video_do_ioctl(struct file
 	const struct v4l2_ioctl_info *info;
 	void *fh = file->private_data;
 	struct v4l2_fh *vfh = NULL;
-	int use_fh_prio = 0;
 	int debug = vfd->debug;
 	long ret = -ENOTTY;
 
@@ -2200,10 +2339,8 @@ static long __video_do_ioctl(struct file
 		return ret;
 	}
 
-	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
 		vfh = file->private_data;
-		use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
-	}
 
 	if (v4l2_is_known_ioctl(cmd)) {
 		info = &v4l2_ioctls[_IOC_NR(cmd)];
@@ -2212,7 +2349,7 @@ static long __video_do_ioctl(struct file
 		    !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
 			goto done;
 
-		if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
+		if (vfh && (info->flags & INFO_FL_PRIO)) {
 			ret = v4l2_prio_check(vfd->prio, vfh->prio);
 			if (ret)
 				goto done;
@@ -2237,7 +2374,7 @@ static long __video_do_ioctl(struct file
 		ret = -ENOTTY;
 	} else {
 		ret = ops->vidioc_default(file, fh,
-			use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
+			vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
 			cmd, arg);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-mem2mem.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-mem2mem.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-mem2mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-mem2mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,7 +208,7 @@ static void v4l2_m2m_try_run(struct v4l2
  * An example of the above could be an instance that requires more than one
  * src/dst buffer per transaction.
  */
-static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
+void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 {
 	struct v4l2_m2m_dev *m2m_dev;
 	unsigned long flags_job, flags_out, flags_cap;
@@ -274,6 +274,7 @@ static void v4l2_m2m_try_schedule(struct
 
 	v4l2_m2m_try_run(m2m_dev);
 }
+EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule);
 
 /**
  * v4l2_m2m_cancel_job() - cancel pending jobs for the context
@@ -568,8 +569,12 @@ unsigned int v4l2_m2m_poll(struct file *
 
 	if (m2m_ctx->m2m_dev->m2m_ops->lock)
 		m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
-	else if (m2m_ctx->q_lock)
-		mutex_lock(m2m_ctx->q_lock);
+	else if (m2m_ctx->q_lock) {
+		if (mutex_lock_interruptible(m2m_ctx->q_lock)) {
+			rc |= POLLERR;
+			goto end;
+		}
+	}
 
 	spin_lock_irqsave(&src_q->done_lock, flags);
 	if (!list_empty(&src_q->done_list))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-subdev.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-subdev.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/v4l2-subdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/v4l2-subdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,6 +126,57 @@ static int subdev_close(struct file *fil
 	return 0;
 }
 
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+static int check_format(struct v4l2_subdev *sd,
+			struct v4l2_subdev_format *format)
+{
+	if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+	    format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+		return -EINVAL;
+
+	if (format->pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop)
+{
+	if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
+	    crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+		return -EINVAL;
+
+	if (crop->pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int check_selection(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_selection *sel)
+{
+	if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
+	    sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+		return -EINVAL;
+
+	if (sel->pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+	if (edid->pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	if (edid->blocks && edid->edid == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+#endif
+
 static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *vdev = video_devdata(file);
@@ -133,12 +184,16 @@ static long subdev_do_ioctl(struct file
 	struct v4l2_fh *vfh = file->private_data;
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 	struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+	int rval;
 #endif
 
 	switch (cmd) {
 	case VIDIOC_QUERYCTRL:
 		return v4l2_queryctrl(vfh->ctrl_handler, arg);
 
+	case VIDIOC_QUERY_EXT_CTRL:
+		return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg);
+
 	case VIDIOC_QUERYMENU:
 		return v4l2_querymenu(vfh->ctrl_handler, arg);
 
@@ -203,12 +258,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_G_FMT: {
 		struct v4l2_subdev_format *format = arg;
 
-		if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
-
-		if (format->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_format(sd, format);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
 	}
@@ -216,12 +268,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_S_FMT: {
 		struct v4l2_subdev_format *format = arg;
 
-		if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
-
-		if (format->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_format(sd, format);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
 	}
@@ -229,14 +278,10 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_G_CROP: {
 		struct v4l2_subdev_crop *crop = arg;
 		struct v4l2_subdev_selection sel;
-		int rval;
-
-		if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
 
-		if (crop->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_crop(sd, crop);
+		if (rval)
+			return rval;
 
 		rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
 		if (rval != -ENOIOCTLCMD)
@@ -258,14 +303,10 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_S_CROP: {
 		struct v4l2_subdev_crop *crop = arg;
 		struct v4l2_subdev_selection sel;
-		int rval;
 
-		if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
-
-		if (crop->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_crop(sd, crop);
+		if (rval)
+			return rval;
 
 		rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
 		if (rval != -ENOIOCTLCMD)
@@ -336,12 +377,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_G_SELECTION: {
 		struct v4l2_subdev_selection *sel = arg;
 
-		if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
-
-		if (sel->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_selection(sd, sel);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(
 			sd, pad, get_selection, subdev_fh, sel);
@@ -350,12 +388,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_SUBDEV_S_SELECTION: {
 		struct v4l2_subdev_selection *sel = arg;
 
-		if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
-		    sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-			return -EINVAL;
-
-		if (sel->pad >= sd->entity.num_pads)
-			return -EINVAL;
+		rval = check_selection(sd, sel);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(
 			sd, pad, set_selection, subdev_fh, sel);
@@ -364,10 +399,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_G_EDID: {
 		struct v4l2_subdev_edid *edid = arg;
 
-		if (edid->pad >= sd->entity.num_pads)
-			return -EINVAL;
-		if (edid->blocks && edid->edid == NULL)
-			return -EINVAL;
+		rval = check_edid(sd, edid);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(sd, pad, get_edid, edid);
 	}
@@ -375,10 +409,9 @@ static long subdev_do_ioctl(struct file
 	case VIDIOC_S_EDID: {
 		struct v4l2_subdev_edid *edid = arg;
 
-		if (edid->pad >= sd->entity.num_pads)
-			return -EINVAL;
-		if (edid->blocks && edid->edid == NULL)
-			return -EINVAL;
+		rval = check_edid(sd, edid);
+		if (rval)
+			return rval;
 
 		return v4l2_subdev_call(sd, pad, set_edid, edid);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-core.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-core.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -576,6 +576,7 @@ static int __verify_planes_array(struct
 static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
 	unsigned int length;
+	unsigned int bytesused;
 	unsigned int plane;
 
 	if (!V4L2_TYPE_IS_OUTPUT(b->type))
@@ -583,21 +584,24 @@ static int __verify_length(struct vb2_bu
 
 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
 		for (plane = 0; plane < vb->num_planes; ++plane) {
-			length = (b->memory == V4L2_MEMORY_USERPTR)
+			length = (b->memory == V4L2_MEMORY_USERPTR ||
+				  b->memory == V4L2_MEMORY_DMABUF)
 			       ? b->m.planes[plane].length
 			       : vb->v4l2_planes[plane].length;
+			bytesused = b->m.planes[plane].bytesused
+				  ? b->m.planes[plane].bytesused : length;
 
 			if (b->m.planes[plane].bytesused > length)
 				return -EINVAL;
 
 			if (b->m.planes[plane].data_offset > 0 &&
-			    b->m.planes[plane].data_offset >=
-			    b->m.planes[plane].bytesused)
+			    b->m.planes[plane].data_offset >= bytesused)
 				return -EINVAL;
 		}
 	} else {
 		length = (b->memory == V4L2_MEMORY_USERPTR)
 		       ? b->length : vb->v4l2_planes[0].length;
+		bytesused = b->bytesused ? b->bytesused : length;
 
 		if (b->bytesused > length)
 			return -EINVAL;
@@ -967,6 +971,7 @@ static int __reqbufs(struct vb2_queue *q
 	 * to the userspace.
 	 */
 	req->count = allocated_buffers;
+	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
 
 	return 0;
 }
@@ -1014,6 +1019,7 @@ static int __create_bufs(struct vb2_queu
 		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
 		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
 		q->memory = create->memory;
+		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
 	}
 
 	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
@@ -1126,7 +1132,7 @@ EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
  */
 void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
 {
-	if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+	if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
 		return NULL;
 
 	return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv);
@@ -1161,13 +1167,10 @@ void vb2_buffer_done(struct vb2_buffer *
 	if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
 		return;
 
-	if (!q->start_streaming_called) {
-		if (WARN_ON(state != VB2_BUF_STATE_QUEUED))
-			state = VB2_BUF_STATE_QUEUED;
-	} else if (WARN_ON(state != VB2_BUF_STATE_DONE &&
-			   state != VB2_BUF_STATE_ERROR)) {
-			state = VB2_BUF_STATE_ERROR;
-	}
+	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
+		    state != VB2_BUF_STATE_ERROR &&
+		    state != VB2_BUF_STATE_QUEUED))
+		state = VB2_BUF_STATE_ERROR;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/*
@@ -1234,35 +1237,6 @@ static void __fill_vb2_buffer(struct vb2
 	unsigned int plane;
 
 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-		/* Fill in driver-provided information for OUTPUT types */
-		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-			bool bytesused_is_used;
-
-			/* Check if bytesused == 0 for all planes */
-			for (plane = 0; plane < vb->num_planes; ++plane)
-				if (b->m.planes[plane].bytesused)
-					break;
-			bytesused_is_used = plane < vb->num_planes;
-
-			/*
-			 * Will have to go up to b->length when API starts
-			 * accepting variable number of planes.
-			 *
-			 * If bytesused_is_used is false, then fall back to the
-			 * full buffer size. In that case userspace clearly
-			 * never bothered to set it and it's a safe assumption
-			 * that they really meant to use the full plane sizes.
-			 */
-			for (plane = 0; plane < vb->num_planes; ++plane) {
-				struct v4l2_plane *pdst = &v4l2_planes[plane];
-				struct v4l2_plane *psrc = &b->m.planes[plane];
-
-				pdst->bytesused = bytesused_is_used ?
-					psrc->bytesused : psrc->length;
-				pdst->data_offset = psrc->data_offset;
-			}
-		}
-
 		if (b->memory == V4L2_MEMORY_USERPTR) {
 			for (plane = 0; plane < vb->num_planes; ++plane) {
 				v4l2_planes[plane].m.userptr =
@@ -1279,6 +1253,28 @@ static void __fill_vb2_buffer(struct vb2
 					b->m.planes[plane].length;
 			}
 		}
+
+		/* Fill in driver-provided information for OUTPUT types */
+		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+			/*
+			 * Will have to go up to b->length when API starts
+			 * accepting variable number of planes.
+			 *
+			 * If bytesused == 0 for the output buffer, then fall
+			 * back to the full buffer size. In that case
+			 * userspace clearly never bothered to set it and
+			 * it's a safe assumption that they really meant to
+			 * use the full plane sizes.
+			 */
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				struct v4l2_plane *pdst = &v4l2_planes[plane];
+				struct v4l2_plane *psrc = &b->m.planes[plane];
+
+				pdst->bytesused = psrc->bytesused ?
+					psrc->bytesused : pdst->length;
+				pdst->data_offset = psrc->data_offset;
+			}
+		}
 	} else {
 		/*
 		 * Single-planar buffers do not use planes array,
@@ -1286,15 +1282,9 @@ static void __fill_vb2_buffer(struct vb2
 		 * In videobuf we use our internal V4l2_planes struct for
 		 * single-planar buffers as well, for simplicity.
 		 *
-		 * If bytesused == 0, then fall back to the full buffer size
-		 * as that's a sensible default.
+		 * If bytesused == 0 for the output buffer, then fall back
+		 * to the full buffer size as that's a sensible default.
 		 */
-		if (V4L2_TYPE_IS_OUTPUT(b->type))
-			v4l2_planes[0].bytesused =
-				b->bytesused ? b->bytesused : b->length;
-		else
-			v4l2_planes[0].bytesused = 0;
-
 		if (b->memory == V4L2_MEMORY_USERPTR) {
 			v4l2_planes[0].m.userptr = b->m.userptr;
 			v4l2_planes[0].length = b->length;
@@ -1304,6 +1294,13 @@ static void __fill_vb2_buffer(struct vb2
 			v4l2_planes[0].m.fd = b->m.fd;
 			v4l2_planes[0].length = b->length;
 		}
+
+		if (V4L2_TYPE_IS_OUTPUT(b->type))
+			v4l2_planes[0].bytesused = b->bytesused ?
+				b->bytesused : v4l2_planes[0].length;
+		else
+			v4l2_planes[0].bytesused = 0;
+
 	}
 
 	/* Zero flags that the vb2 core handles */
@@ -1606,6 +1603,11 @@ static int __buf_prepare(struct vb2_buff
 		return -EINVAL;
 	}
 
+	if (q->error) {
+		dprintk(1, "fatal error occurred on queue\n");
+		return -EIO;
+	}
+
 	vb->state = VB2_BUF_STATE_PREPARING;
 	vb->v4l2_buf.timestamp.tv_sec = 0;
 	vb->v4l2_buf.timestamp.tv_usec = 0;
@@ -1750,13 +1752,21 @@ static int vb2_start_streaming(struct vb
 		__enqueue_in_driver(vb);
 
 	/* Tell the driver to start streaming */
+	q->start_streaming_called = 1;
 	ret = call_qop(q, start_streaming, q,
 		       atomic_read(&q->owned_by_drv_count));
-	q->start_streaming_called = ret == 0;
 	if (!ret)
 		return 0;
 
+	q->start_streaming_called = 0;
+
 	dprintk(1, "driver refused to start streaming\n");
+	/*
+	 * If you see this warning, then the driver isn't cleaning up properly
+	 * after a failed start_streaming(). See the start_streaming()
+	 * documentation in videobuf2-core.h for more information how buffers
+	 * should be returned to vb2 in start_streaming().
+	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
 		unsigned i;
 
@@ -1772,6 +1782,12 @@ static int vb2_start_streaming(struct vb
 		/* Must be zero now */
 		WARN_ON(atomic_read(&q->owned_by_drv_count));
 	}
+	/*
+	 * If done_list is not empty, then start_streaming() didn't call
+	 * vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED) but STATE_ERROR or
+	 * STATE_DONE.
+	 */
+	WARN_ON(!list_empty(&q->done_list));
 	return ret;
 }
 
@@ -1807,6 +1823,7 @@ static int vb2_internal_qbuf(struct vb2_
 	 */
 	list_add_tail(&vb->queued_entry, &q->queued_list);
 	q->queued_count++;
+	q->waiting_for_buffers = false;
 	vb->state = VB2_BUF_STATE_QUEUED;
 	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
 		/*
@@ -1901,6 +1918,11 @@ static int __vb2_wait_for_done_vb(struct
 			return -EINVAL;
 		}
 
+		if (q->error) {
+			dprintk(1, "Queue in error state, will not wait for buffers\n");
+			return -EIO;
+		}
+
 		if (!list_empty(&q->done_list)) {
 			/*
 			 * Found a buffer that we were waiting for.
@@ -1926,7 +1948,8 @@ static int __vb2_wait_for_done_vb(struct
 		 */
 		dprintk(3, "will sleep waiting for buffers\n");
 		ret = wait_event_interruptible(q->done_wq,
-				!list_empty(&q->done_list) || !q->streaming);
+				!list_empty(&q->done_list) || !q->streaming ||
+				q->error);
 
 		/*
 		 * We need to reevaluate both conditions again after reacquiring
@@ -2112,6 +2135,12 @@ static void __vb2_queue_cancel(struct vb
 	if (q->start_streaming_called)
 		call_void_qop(q, stop_streaming, q);
 
+	/*
+	 * If you see this warning, then the driver isn't cleaning up properly
+	 * in stop_streaming(). See the stop_streaming() documentation in
+	 * videobuf2-core.h for more information how buffers should be returned
+	 * to vb2 in stop_streaming().
+	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
 		for (i = 0; i < q->num_buffers; ++i)
 			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE)
@@ -2123,6 +2152,7 @@ static void __vb2_queue_cancel(struct vb
 	q->streaming = 0;
 	q->start_streaming_called = 0;
 	q->queued_count = 0;
+	q->error = 0;
 
 	/*
 	 * Remove all buffers from videobuf's list...
@@ -2200,6 +2230,27 @@ static int vb2_internal_streamon(struct
 }
 
 /**
+ * vb2_queue_error() - signal a fatal error on the queue
+ * @q:		videobuf2 queue
+ *
+ * Flag that a fatal unrecoverable error has occurred and wake up all processes
+ * waiting on the queue. Polling will now set POLLERR and queuing and dequeuing
+ * buffers will return -EIO.
+ *
+ * The error flag will be cleared when cancelling the queue, either from
+ * vb2_streamoff or vb2_queue_release. Drivers should thus not call this
+ * function before starting the stream, otherwise the error flag will remain set
+ * until the queue is released when closing the device node.
+ */
+void vb2_queue_error(struct vb2_queue *q)
+{
+	q->error = 1;
+
+	wake_up_all(&q->done_wq);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_error);
+
+/**
  * vb2_streamon - start streaming
  * @q:		videobuf2 queue
  * @type:	type argument passed from userspace to vidioc_streamon handler
@@ -2239,6 +2290,7 @@ static int vb2_internal_streamoff(struct
 	 * their normal dequeued state.
 	 */
 	__vb2_queue_cancel(q);
+	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
 
 	dprintk(3, "successful\n");
 	return 0;
@@ -2557,10 +2609,25 @@ unsigned int vb2_poll(struct vb2_queue *
 	}
 
 	/*
-	 * There is nothing to wait for if no buffers have already been queued.
+	 * There is nothing to wait for if the queue isn't streaming, or if the
+	 * error flag is set.
 	 */
-	if (list_empty(&q->queued_list))
+	if (!vb2_is_streaming(q) || q->error)
 		return res | POLLERR;
+	/*
+	 * For compatibility with vb1: if QBUF hasn't been called yet, then
+	 * return POLLERR as well. This only affects capture queues, output
+	 * queues will always initialize waiting_for_buffers to false.
+	 */
+	if (q->waiting_for_buffers)
+		return res | POLLERR;
+
+	/*
+	 * For output streams you can write as long as there are fewer buffers
+	 * queued than there are buffers available.
+	 */
+	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
+		return res | POLLOUT | POLLWRNORM;
 
 	if (list_empty(&q->done_list))
 		poll_wait(file, &q->done_wq, wait);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-dma-contig.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-dma-contig.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-dma-contig.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-dma-contig.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,6 +98,9 @@ static void *vb2_dc_vaddr(void *buf_priv
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
+	if (!buf->vaddr && buf->db_attach)
+		buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+
 	return buf->vaddr;
 }
 
@@ -404,7 +407,7 @@ static struct dma_buf *vb2_dc_get_dmabuf
 	if (WARN_ON(!buf->sgt_base))
 		return NULL;
 
-	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags);
+	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags, NULL);
 	if (IS_ERR(dbuf))
 		return NULL;
 
@@ -735,6 +738,7 @@ static int vb2_dc_map_dmabuf(void *mem_p
 
 	buf->dma_addr = sg_dma_address(sgt->sgl);
 	buf->dma_sgt = sgt;
+	buf->vaddr = NULL;
 
 	return 0;
 }
@@ -754,6 +758,10 @@ static void vb2_dc_unmap_dmabuf(void *me
 		return;
 	}
 
+	if (buf->vaddr) {
+		dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+		buf->vaddr = NULL;
+	}
 	dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
 
 	buf->dma_addr = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-dma-sg.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-dma-sg.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf2-dma-sg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf2-dma-sg.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,7 +113,7 @@ static void *vb2_dma_sg_alloc(void *allo
 		goto fail_pages_alloc;
 
 	ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
-			buf->num_pages, 0, size, gfp_flags);
+			buf->num_pages, 0, size, GFP_KERNEL);
 	if (ret)
 		goto fail_table_alloc;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c
--- linux-libre-3.16-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c	2014-09-28 17:29:07.000000000 -0400
@@ -211,13 +211,36 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init_user
 int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
 			     int nr_pages)
 {
+	int i;
+
 	dprintk(1, "init kernel [%d pages]\n", nr_pages);
 
 	dma->direction = direction;
-	dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+	dma->vaddr_pages = kcalloc(nr_pages, sizeof(*dma->vaddr_pages),
+				   GFP_KERNEL);
+	if (!dma->vaddr_pages)
+		return -ENOMEM;
+
+	dma->dma_addr = kcalloc(nr_pages, sizeof(*dma->dma_addr), GFP_KERNEL);
+	if (!dma->dma_addr) {
+		kfree(dma->vaddr_pages);
+		return -ENOMEM;
+	}
+	for (i = 0; i < nr_pages; i++) {
+		void *addr;
+
+		addr = dma_alloc_coherent(dma->dev, PAGE_SIZE,
+					  &(dma->dma_addr[i]), GFP_KERNEL);
+		if (addr == NULL)
+			goto out_free_pages;
+
+		dma->vaddr_pages[i] = virt_to_page(addr);
+	}
+	dma->vaddr = vmap(dma->vaddr_pages, nr_pages, VM_MAP | VM_IOREMAP,
+			  PAGE_KERNEL);
 	if (NULL == dma->vaddr) {
 		dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
-		return -ENOMEM;
+		goto out_free_pages;
 	}
 
 	dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
@@ -228,6 +251,19 @@ int videobuf_dma_init_kernel(struct vide
 	dma->nr_pages = nr_pages;
 
 	return 0;
+out_free_pages:
+	while (i > 0) {
+		void *addr = page_address(dma->vaddr_pages[i]);
+		dma_free_coherent(dma->dev, PAGE_SIZE, addr, dma->dma_addr[i]);
+		i--;
+	}
+	kfree(dma->dma_addr);
+	dma->dma_addr = NULL;
+	kfree(dma->vaddr_pages);
+	dma->vaddr_pages = NULL;
+
+	return -ENOMEM;
+
 }
 EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
 
@@ -322,8 +358,21 @@ int videobuf_dma_free(struct videobuf_dm
 		dma->pages = NULL;
 	}
 
-	vfree(dma->vaddr);
-	dma->vaddr = NULL;
+	if (dma->dma_addr) {
+		for (i = 0; i < dma->nr_pages; i++) {
+			void *addr;
+
+			addr = page_address(dma->vaddr_pages[i]);
+			dma_free_coherent(dma->dev, PAGE_SIZE, addr,
+					  dma->dma_addr[i]);
+		}
+		kfree(dma->dma_addr);
+		dma->dma_addr = NULL;
+		kfree(dma->vaddr_pages);
+		dma->vaddr_pages = NULL;
+		vunmap(dma->vaddr);
+		dma->vaddr = NULL;
+	}
 
 	if (dma->bus_addr)
 		dma->bus_addr = 0;
@@ -461,6 +510,11 @@ static int __videobuf_iolock(struct vide
 
 	MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
+	if (!mem->dma.dev)
+		mem->dma.dev = q->dev;
+	else
+		WARN_ON(mem->dma.dev != q->dev);
+
 	switch (vb->memory) {
 	case V4L2_MEMORY_MMAP:
 	case V4L2_MEMORY_USERPTR:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/memory/fsl-corenet-cf.c linux-libre-3.17-rc7-gnu/drivers/memory/fsl-corenet-cf.c
--- linux-libre-3.16-gnu/drivers/memory/fsl-corenet-cf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/memory/fsl-corenet-cf.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,251 @@
+/*
+ * CoreNet Coherency Fabric error reporting
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+enum ccf_version {
+	CCF1,
+	CCF2,
+};
+
+struct ccf_info {
+	enum ccf_version version;
+	int err_reg_offs;
+};
+
+static const struct ccf_info ccf1_info = {
+	.version = CCF1,
+	.err_reg_offs = 0xa00,
+};
+
+static const struct ccf_info ccf2_info = {
+	.version = CCF2,
+	.err_reg_offs = 0xe40,
+};
+
+static const struct of_device_id ccf_matches[] = {
+	{
+		.compatible = "fsl,corenet1-cf",
+		.data = &ccf1_info,
+	},
+	{
+		.compatible = "fsl,corenet2-cf",
+		.data = &ccf2_info,
+	},
+	{}
+};
+
+struct ccf_err_regs {
+	u32 errdet;		/* 0x00 Error Detect Register */
+	/* 0x04 Error Enable (ccf1)/Disable (ccf2) Register */
+	u32 errdis;
+	/* 0x08 Error Interrupt Enable Register (ccf2 only) */
+	u32 errinten;
+	u32 cecar;		/* 0x0c Error Capture Attribute Register */
+	u32 cecaddrh;		/* 0x10 Error Capture Address High */
+	u32 cecaddrl;		/* 0x14 Error Capture Address Low */
+	u32 cecar2;		/* 0x18 Error Capture Attribute Register 2 */
+};
+
+/* LAE/CV also valid for errdis and errinten */
+#define ERRDET_LAE		(1 << 0)  /* Local Access Error */
+#define ERRDET_CV		(1 << 1)  /* Coherency Violation */
+#define ERRDET_CTYPE_SHIFT	26	  /* Capture Type (ccf2 only) */
+#define ERRDET_CTYPE_MASK	(0x1f << ERRDET_CTYPE_SHIFT)
+#define ERRDET_CAP		(1 << 31) /* Capture Valid (ccf2 only) */
+
+#define CECAR_VAL		(1 << 0)  /* Valid (ccf1 only) */
+#define CECAR_UVT		(1 << 15) /* Unavailable target ID (ccf1) */
+#define CECAR_SRCID_SHIFT_CCF1	24
+#define CECAR_SRCID_MASK_CCF1	(0xff << CECAR_SRCID_SHIFT_CCF1)
+#define CECAR_SRCID_SHIFT_CCF2	18
+#define CECAR_SRCID_MASK_CCF2	(0xff << CECAR_SRCID_SHIFT_CCF2)
+
+#define CECADDRH_ADDRH		0xff
+
+struct ccf_private {
+	const struct ccf_info *info;
+	struct device *dev;
+	void __iomem *regs;
+	struct ccf_err_regs __iomem *err_regs;
+};
+
+static irqreturn_t ccf_irq(int irq, void *dev_id)
+{
+	struct ccf_private *ccf = dev_id;
+	static DEFINE_RATELIMIT_STATE(ratelimit, DEFAULT_RATELIMIT_INTERVAL,
+				      DEFAULT_RATELIMIT_BURST);
+	u32 errdet, cecar, cecar2;
+	u64 addr;
+	u32 src_id;
+	bool uvt = false;
+	bool cap_valid = false;
+
+	errdet = ioread32be(&ccf->err_regs->errdet);
+	cecar = ioread32be(&ccf->err_regs->cecar);
+	cecar2 = ioread32be(&ccf->err_regs->cecar2);
+	addr = ioread32be(&ccf->err_regs->cecaddrl);
+	addr |= ((u64)(ioread32be(&ccf->err_regs->cecaddrh) &
+		       CECADDRH_ADDRH)) << 32;
+
+	if (!__ratelimit(&ratelimit))
+		goto out;
+
+	switch (ccf->info->version) {
+	case CCF1:
+		if (cecar & CECAR_VAL) {
+			if (cecar & CECAR_UVT)
+				uvt = true;
+
+			src_id = (cecar & CECAR_SRCID_MASK_CCF1) >>
+				 CECAR_SRCID_SHIFT_CCF1;
+			cap_valid = true;
+		}
+
+		break;
+	case CCF2:
+		if (errdet & ERRDET_CAP) {
+			src_id = (cecar & CECAR_SRCID_MASK_CCF2) >>
+				 CECAR_SRCID_SHIFT_CCF2;
+			cap_valid = true;
+		}
+
+		break;
+	}
+
+	dev_crit(ccf->dev, "errdet 0x%08x cecar 0x%08x cecar2 0x%08x\n",
+		 errdet, cecar, cecar2);
+
+	if (errdet & ERRDET_LAE) {
+		if (uvt)
+			dev_crit(ccf->dev, "LAW Unavailable Target ID\n");
+		else
+			dev_crit(ccf->dev, "Local Access Window Error\n");
+	}
+
+	if (errdet & ERRDET_CV)
+		dev_crit(ccf->dev, "Coherency Violation\n");
+
+	if (cap_valid) {
+		dev_crit(ccf->dev, "address 0x%09llx, src id 0x%x\n",
+			 addr, src_id);
+	}
+
+out:
+	iowrite32be(errdet, &ccf->err_regs->errdet);
+	return errdet ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int ccf_probe(struct platform_device *pdev)
+{
+	struct ccf_private *ccf;
+	struct resource *r;
+	const struct of_device_id *match;
+	int ret, irq;
+
+	match = of_match_device(ccf_matches, &pdev->dev);
+	if (WARN_ON(!match))
+		return -ENODEV;
+
+	ccf = devm_kzalloc(&pdev->dev, sizeof(*ccf), GFP_KERNEL);
+	if (!ccf)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+		return -ENXIO;
+	}
+
+	ccf->regs = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(ccf->regs)) {
+		dev_err(&pdev->dev, "%s: can't map mem resource\n", __func__);
+		return PTR_ERR(ccf->regs);
+	}
+
+	ccf->dev = &pdev->dev;
+	ccf->info = match->data;
+	ccf->err_regs = ccf->regs + ccf->info->err_reg_offs;
+
+	dev_set_drvdata(&pdev->dev, ccf);
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "%s: no irq\n", __func__);
+		return -ENXIO;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: can't request irq\n", __func__);
+		return ret;
+	}
+
+	switch (ccf->info->version) {
+	case CCF1:
+		/* On CCF1 this register enables rather than disables. */
+		iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errdis);
+		break;
+
+	case CCF2:
+		iowrite32be(0, &ccf->err_regs->errdis);
+		iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errinten);
+		break;
+	}
+
+	return 0;
+}
+
+static int ccf_remove(struct platform_device *pdev)
+{
+	struct ccf_private *ccf = dev_get_drvdata(&pdev->dev);
+
+	switch (ccf->info->version) {
+	case CCF1:
+		iowrite32be(0, &ccf->err_regs->errdis);
+		break;
+
+	case CCF2:
+		/*
+		 * We clear errdis on ccf1 because that's the only way to
+		 * disable interrupts, but on ccf2 there's no need to disable
+		 * detection.
+		 */
+		iowrite32be(0, &ccf->err_regs->errinten);
+		break;
+	}
+
+	return 0;
+}
+
+static struct platform_driver ccf_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = ccf_matches,
+	},
+	.probe = ccf_probe,
+	.remove = ccf_remove,
+};
+
+module_platform_driver(ccf_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale CoreNet Coherency Fabric error reporting");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/memory/Kconfig linux-libre-3.17-rc7-gnu/drivers/memory/Kconfig
--- linux-libre-3.16-gnu/drivers/memory/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/memory/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,16 @@ config TEGRA30_MC
 	  analysis, especially for IOMMU/SMMU(System Memory Management
 	  Unit) module.
 
+config FSL_CORENET_CF
+	tristate "Freescale CoreNet Error Reporting"
+	depends on FSL_SOC_BOOKE
+	help
+	  Say Y for reporting of errors from the Freescale CoreNet
+	  Coherency Fabric.  Errors reported include accesses to
+	  physical addresses that mapped by no local access window
+	  (LAW) or an invalid LAW, as well as bad cache state that
+	  represents a coherency violation.
+
 config FSL_IFC
 	bool
 	depends on FSL_SOC
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/memory/Makefile linux-libre-3.17-rc7-gnu/drivers/memory/Makefile
--- linux-libre-3.16-gnu/drivers/memory/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/memory/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
+obj-$(CONFIG_FSL_CORENET_CF)	+= fsl-corenet-cf.o
 obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_MVEBU_DEVBUS)	+= mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/Kconfig linux-libre-3.17-rc7-gnu/drivers/message/fusion/Kconfig
--- linux-libre-3.16-gnu/drivers/message/fusion/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,7 @@ config FUSION_SPI
 config FUSION_FC
 	tristate "Fusion MPT ScsiHost drivers for FC"
 	depends on PCI && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	---help---
 	  SCSI HOST support for a Fiber Channel host adapters.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptbase.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptbase.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptbase.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptbase.c	2014-09-28 17:29:07.000000000 -0400
@@ -649,12 +649,10 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAM
 	case MPI_FUNCTION_CONFIG:
 	case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
 		ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
-		if (reply) {
-			ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
-			memcpy(ioc->mptbase_cmds.reply, reply,
-			    min(MPT_DEFAULT_FRAME_SIZE,
-				4 * reply->u.reply.MsgLength));
-		}
+		ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+		memcpy(ioc->mptbase_cmds.reply, reply,
+		    min(MPT_DEFAULT_FRAME_SIZE,
+			4 * reply->u.reply.MsgLength));
 		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
 			ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
 			complete(&ioc->mptbase_cmds.done);
@@ -1408,8 +1406,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTE
  *	in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
  *
  **/
-static void
-mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
+static const char*
+mpt_get_product_name(u16 vendor, u16 device, u8 revision)
 {
 	char *product_str = NULL;
 
@@ -1635,8 +1633,7 @@ mpt_get_product_name(u16 vendor, u16 dev
 	}
 
  out:
-	if (product_str)
-		sprintf(prod_name, "%s", product_str);
+	return product_str;
 }
 
 /**
@@ -1887,8 +1884,8 @@ mpt_attach(struct pci_dev *pdev, const s
 	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
 	    ioc->name, &ioc->facts, &ioc->pfacts[0]));
 
-	mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision,
-			     ioc->prod_name);
+	ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device,
+					      pdev->revision);
 
 	switch (pdev->device)
 	{
@@ -7007,7 +7004,7 @@ EXPORT_SYMBOL(mpt_halt_firmware);
  *	IOC doesn't reply to any outstanding request. This will transfer IOC
  *	to READY state.
  **/
-int
+static int
 mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 {
 	int		 rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptbase.h linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptbase.h
--- linux-libre-3.16-gnu/drivers/message/fusion/mptbase.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptbase.h	2014-09-28 17:29:07.000000000 -0400
@@ -405,7 +405,7 @@ typedef struct _VirtTarget {
 typedef struct _VirtDevice {
 	VirtTarget		*vtarget;
 	u8			 configured_lun;
-	int			 lun;
+	u64			 lun;
 } VirtDevice;
 
 /*
@@ -605,7 +605,7 @@ typedef struct _MPT_ADAPTER
 	int			 id;		/* Unique adapter id N {0,1,2,...} */
 	int			 pci_irq;	/* This irq           */
 	char			 name[MPT_NAME_LENGTH];	/* "iocN"             */
-	char			 prod_name[MPT_NAME_LENGTH];	/* "LSIFC9x9"         */
+	const char		 *prod_name;	/* "LSIFC9x9"         */
 #ifdef CONFIG_FUSION_LOGGING
 	/* used in mpt_display_event_info */
 	char			 evStr[EVENT_DESCR_STR_SZ];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptctl.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptctl.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -1261,19 +1261,11 @@ mptctl_getiocinfo (unsigned long arg, un
 	else
 		return -EFAULT;
 
-	karg = kmalloc(data_size, GFP_KERNEL);
-	if (karg == NULL) {
-		printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
-				__FILE__, __LINE__);
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(karg, uarg, data_size)) {
-		printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - "
-			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
-				__FILE__, __LINE__, uarg);
-		kfree(karg);
-		return -EFAULT;
+	karg = memdup_user(uarg, data_size);
+	if (IS_ERR(karg)) {
+		printk(KERN_ERR MYNAM "%s@%d::mpt_ioctl_iocinfo() - memdup_user returned error [%ld]\n",
+				__FILE__, __LINE__, PTR_ERR(karg));
+		return PTR_ERR(karg);
 	}
 
 	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptfc.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptfc.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptfc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptfc.c	2014-09-28 17:29:07.000000000 -0400
@@ -204,7 +204,7 @@ mptfc_block_error_handler(struct scsi_cm
 	 || (loops > 0 && ioc->active == 0)) {
 		spin_unlock_irqrestore(shost->host_lock, flags);
 		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
-			"mptfc_block_error_handler.%d: %d:%d, port status is "
+			"mptfc_block_error_handler.%d: %d:%llu, port status is "
 			"%x, active flag %d, deferring %s recovery.\n",
 			ioc->name, ioc->sh->host_no,
 			SCpnt->device->id, SCpnt->device->lun,
@@ -218,7 +218,7 @@ mptfc_block_error_handler(struct scsi_cm
 	if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
 	 || ioc->active == 0) {
 		dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
-			"%s.%d: %d:%d, failing recovery, "
+			"%s.%d: %d:%llu, failing recovery, "
 			"port state %x, active %d, vdevice %p.\n", caller,
 			ioc->name, ioc->sh->host_no,
 			SCpnt->device->id, SCpnt->device->lun, ready,
@@ -226,7 +226,7 @@ mptfc_block_error_handler(struct scsi_cm
 		return FAILED;
 	}
 	dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
-		"%s.%d: %d:%d, executing recovery.\n", caller,
+		"%s.%d: %d:%llu, executing recovery.\n", caller,
 		ioc->name, ioc->sh->host_no,
 		SCpnt->device->id, SCpnt->device->lun));
 	return (*func)(SCpnt);
@@ -525,8 +525,7 @@ mptfc_target_destroy(struct scsi_target
 		if (ri)	/* better be! */
 			ri->starget = NULL;
 	}
-	if (starget->hostdata)
-		kfree(starget->hostdata);
+	kfree(starget->hostdata);
 	starget->hostdata = NULL;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptsas.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptsas.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptsas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptsas.c	2014-09-28 17:29:07.000000000 -0400
@@ -990,11 +990,10 @@ mptsas_queue_device_delete(MPT_ADAPTER *
 	MpiEventDataSasDeviceStatusChange_t *sas_event_data)
 {
 	struct fw_event_work *fw_event;
-	int sz;
 
-	sz = offsetof(struct fw_event_work, event_data) +
-	    sizeof(MpiEventDataSasDeviceStatusChange_t);
-	fw_event = kzalloc(sz, GFP_ATOMIC);
+	fw_event = kzalloc(sizeof(*fw_event) +
+			   sizeof(MpiEventDataSasDeviceStatusChange_t),
+			   GFP_ATOMIC);
 	if (!fw_event) {
 		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
 		    ioc->name, __func__, __LINE__);
@@ -1011,10 +1010,8 @@ static void
 mptsas_queue_rescan(MPT_ADAPTER *ioc)
 {
 	struct fw_event_work *fw_event;
-	int sz;
 
-	sz = offsetof(struct fw_event_work, event_data);
-	fw_event = kzalloc(sz, GFP_ATOMIC);
+	fw_event = kzalloc(sizeof(*fw_event), GFP_ATOMIC);
 	if (!fw_event) {
 		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
 		    ioc->name, __func__, __LINE__);
@@ -1206,27 +1203,28 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *io
 	    "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
 
 	pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
-	if (pScsiTmReply) {
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-		    "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
-		    "\ttask_type = 0x%02X, iocstatus = 0x%04X "
-		    "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
-		    "term_cmnds = %d\n", ioc->name,
-		    pScsiTmReply->Bus, pScsiTmReply->TargetID,
-		    pScsiTmReply->TaskType,
-		    le16_to_cpu(pScsiTmReply->IOCStatus),
-		    le32_to_cpu(pScsiTmReply->IOCLogInfo),
-		    pScsiTmReply->ResponseCode,
-		    le32_to_cpu(pScsiTmReply->TerminationCount)));
+	if (!pScsiTmReply)
+		return 0;
 
-		if (pScsiTmReply->ResponseCode)
-			mptscsih_taskmgmt_response_code(ioc,
-			pScsiTmReply->ResponseCode);
-	}
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
+	    "\ttask_type = 0x%02X, iocstatus = 0x%04X "
+	    "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
+	    "term_cmnds = %d\n", ioc->name,
+	    pScsiTmReply->Bus, pScsiTmReply->TargetID,
+	    pScsiTmReply->TaskType,
+	    le16_to_cpu(pScsiTmReply->IOCStatus),
+	    le32_to_cpu(pScsiTmReply->IOCLogInfo),
+	    pScsiTmReply->ResponseCode,
+	    le32_to_cpu(pScsiTmReply->TerminationCount)));
 
-	if (pScsiTmReply && (pScsiTmReply->TaskType ==
+	if (pScsiTmReply->ResponseCode)
+		mptscsih_taskmgmt_response_code(ioc,
+		pScsiTmReply->ResponseCode);
+
+	if (pScsiTmReply->TaskType ==
 	    MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
-	     MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
+	     MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {
 		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
 		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
 		memcpy(ioc->taskmgmt_cmds.reply, mr,
@@ -1575,7 +1573,7 @@ mptsas_del_end_device(MPT_ADAPTER *ioc,
 	mptsas_port_delete(ioc, phy_info->port_details);
 }
 
-struct mptsas_phyinfo *
+static struct mptsas_phyinfo *
 mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
 	struct mptsas_devinfo *sas_device)
 {
@@ -3648,7 +3646,7 @@ mptsas_send_expander_event(struct fw_eve
  * @handle:
  *
  */
-struct mptsas_portinfo *
+static struct mptsas_portinfo *
 mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
 {
 	struct mptsas_portinfo buffer, *port_info;
@@ -3763,7 +3761,7 @@ mptsas_send_link_status_event(struct fw_
 						printk(MYIOC_s_DEBUG_FMT
 						"SDEV OUTSTANDING CMDS"
 						"%d\n", ioc->name,
-						sdev->device_busy));
+						atomic_read(&sdev->device_busy)));
 				}
 
 			}
@@ -3856,10 +3854,8 @@ retry_page:
 			phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
 					sas_info->sas_address);
 
-			if (phy_info) {
-				mptsas_del_end_device(ioc, phy_info);
-				goto redo_device_scan;
-			}
+			mptsas_del_end_device(ioc, phy_info);
+			goto redo_device_scan;
 		} else
 			mptsas_volume_delete(ioc, sas_info->fw.id);
 	}
@@ -3870,9 +3866,8 @@ retry_page:
  redo_expander_scan:
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 
-		if (port_info->phy_info &&
-		    (!(port_info->phy_info[0].identify.device_info &
-		    MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+		if (!(port_info->phy_info[0].identify.device_info &
+		    MPI_SAS_DEVICE_INFO_SMP_TARGET))
 			continue;
 		found_expander = 0;
 		handle = 0xFFFF;
@@ -4983,7 +4978,7 @@ static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 {
 	u32 event = le32_to_cpu(reply->Event);
-	int sz, event_data_sz;
+	int event_data_sz;
 	struct fw_event_work *fw_event;
 	unsigned long delay;
 
@@ -5093,8 +5088,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
 
 	event_data_sz = ((reply->MsgLength * 4) -
 	    offsetof(EventNotificationReply_t, Data));
-	sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
-	fw_event = kzalloc(sz, GFP_ATOMIC);
+	fw_event = kzalloc(sizeof(*fw_event) + event_data_sz, GFP_ATOMIC);
 	if (!fw_event) {
 		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
 		 __func__, __LINE__);
@@ -5321,7 +5315,7 @@ mptsas_probe(struct pci_dev *pdev, const
 	return error;
 }
 
-void
+static void
 mptsas_shutdown(struct pci_dev *pdev)
 {
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptsas.h linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptsas.h
--- linux-libre-3.16-gnu/drivers/message/fusion/mptsas.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptsas.h	2014-09-28 17:29:07.000000000 -0400
@@ -110,7 +110,7 @@ struct fw_event_work {
 	MPT_ADAPTER	*ioc;
 	u32			event;
 	u8			retries;
-	u8			__attribute__((aligned(4))) event_data[1];
+	char			event_data[0] __aligned(4);
 };
 
 struct mptsas_discovery_event {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptscsih.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptscsih.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptscsih.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptscsih.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,7 @@ static void	mptscsih_freeChainBuffers(MP
 static void	mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 
 int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id,
-		int lun, int ctx2abort, ulong timeout);
+		u64 lun, int ctx2abort, ulong timeout);
 
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
@@ -536,7 +536,7 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, s
 	}
 
 	scsi_print_command(sc);
-	printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n",
+	printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %llu\n",
 	    ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun);
 	printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
 	    "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
@@ -692,7 +692,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 		 */
 		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
 		    pScsiReply->ResponseInfo) {
-			printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
+			printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%llu] "
 			"FCP_ResponseInfo=%08xh\n", ioc->name,
 			sc->device->host->host_no, sc->device->channel,
 			sc->device->id, sc->device->lun,
@@ -1155,7 +1155,7 @@ mptscsih_report_queue_full(struct scsi_c
 		return;
 	ioc = hd->ioc;
 	if (time - hd->last_queue_full > 10 * HZ) {
-		dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
+		dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%llu) reported QUEUE_FULL!\n",
 				ioc->name, 0, sc->device->id, sc->device->lun));
 		hd->last_queue_full = time;
 	}
@@ -1271,15 +1271,13 @@ mptscsih_info(struct Scsi_Host *SChost)
 
 	h = shost_priv(SChost);
 
-	if (h) {
-		if (h->info_kbuf == NULL)
-			if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
-				return h->info_kbuf;
-		h->info_kbuf[0] = '\0';
+	if (h->info_kbuf == NULL)
+		if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+			return h->info_kbuf;
+	h->info_kbuf[0] = '\0';
 
-		mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
-		h->info_kbuf[size-1] = '\0';
-	}
+	mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+	h->info_kbuf[size-1] = '\0';
 
 	return h->info_kbuf;
 }
@@ -1368,8 +1366,7 @@ 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
-	    && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+	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) {
@@ -1518,7 +1515,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
  *
  **/
 int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u64 lun,
 	int ctx2abort, ulong timeout)
 {
 	MPT_FRAME_HDR	*mf;
@@ -2380,7 +2377,7 @@ mptscsih_slave_configure(struct scsi_dev
 	vdevice = sdev->hostdata;
 
 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-		"device @ %p, channel=%d, id=%d, lun=%d\n",
+		"device @ %p, channel=%d, id=%d, lun=%llu\n",
 		ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
 	if (ioc->bus_type == SPI)
 		dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
@@ -2971,7 +2968,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
 	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-	    "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
+	    "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%llu\n",
 	    ioc->name, __func__, cmd, io->channel, io->id, io->lun));
 
 	if (dir == MPI_SCSIIO_CONTROL_READ)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptscsih.h linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptscsih.h
--- linux-libre-3.16-gnu/drivers/message/fusion/mptscsih.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptscsih.h	2014-09-28 17:29:07.000000000 -0400
@@ -98,7 +98,7 @@ typedef struct _internal_cmd {
 	u8		cmd;		/* SCSI Op Code */
 	u8		channel;	/* bus number */
 	u8		id;		/* SCSI ID (virtual) */
-	int		lun;
+	u64		lun;
 	u8		flags;		/* Bit Field - See above */
 	u8		physDiskNum;	/* Phys disk number, -1 else */
 	u8		rsvd2;
@@ -115,7 +115,7 @@ extern int mptscsih_show_info(struct seq
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt);
 extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
-	u8 id, int lun, int ctx2abort, ulong timeout);
+	u8 id, u64 lun, int ctx2abort, ulong timeout);
 extern void mptscsih_slave_destroy(struct scsi_device *device);
 extern int mptscsih_slave_configure(struct scsi_device *device);
 extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/fusion/mptspi.c linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptspi.c
--- linux-libre-3.16-gnu/drivers/message/fusion/mptspi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/fusion/mptspi.c	2014-09-28 17:29:07.000000000 -0400
@@ -461,8 +461,7 @@ static int mptspi_target_alloc(struct sc
 static void
 mptspi_target_destroy(struct scsi_target *starget)
 {
-	if (starget->hostdata)
-		kfree(starget->hostdata);
+	kfree(starget->hostdata);
 	starget->hostdata = NULL;
 }
 
@@ -620,7 +619,7 @@ static void mptspi_read_parameters(struc
 	spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
 }
 
-int
+static int
 mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
 	MPT_ADAPTER	*ioc = hd->ioc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/message/i2o/i2o_scsi.c linux-libre-3.17-rc7-gnu/drivers/message/i2o/i2o_scsi.c
--- linux-libre-3.16-gnu/drivers/message/i2o/i2o_scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/message/i2o/i2o_scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,7 @@ static unsigned int i2o_scsi_max_lun = 2
 struct i2o_scsi_host {
 	struct Scsi_Host *scsi_host;	/* pointer to the SCSI host */
 	struct i2o_controller *iop;	/* pointer to the I2O controller */
-	unsigned int lun;	/* lun's used for block devices */
+	u64 lun;	/* lun's used for block devices */
 	struct i2o_device *channel[0];	/* channel->i2o_dev mapping table */
 };
 
@@ -287,9 +287,8 @@ static int i2o_scsi_probe(struct device
 	}
 
 	if (le64_to_cpu(lun) >= scsi_host->max_lun) {
-		osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)",
-			 (long unsigned int)le64_to_cpu(lun),
-			 scsi_host->max_lun);
+		osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)",
+			 le64_to_cpu(lun), scsi_host->max_lun);
 		return -EFAULT;
 	}
 
@@ -308,9 +307,9 @@ static int i2o_scsi_probe(struct device
 	if (rc)
 		goto err;
 
-	osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
+	osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n",
 		 i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
-		 (long unsigned int)le64_to_cpu(lun));
+		 le64_to_cpu(lun));
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/88pm805.c linux-libre-3.17-rc7-gnu/drivers/mfd/88pm805.c
--- linux-libre-3.16-gnu/drivers/mfd/88pm805.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/88pm805.c	2014-09-28 17:29:07.000000000 -0400
@@ -158,7 +158,7 @@ static int device_irq_init_805(struct pm
 	 * PM805_INT_STATUS is under 32K clock domain, so need to
 	 * add proper delay before the next I2C register access.
 	 */
-	msleep(1);
+	usleep_range(1000, 3000);
 
 	if (ret < 0)
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/88pm860x-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/88pm860x-core.c
--- linux-libre-3.16-gnu/drivers/mfd/88pm860x-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/88pm860x-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,8 @@
  * Base driver for Marvell 88PM8607
  *
  * Copyright (C) 2009 Marvell International Ltd.
- * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -140,7 +141,8 @@ static struct resource codec_resources[]
 	/* Headset insertion or removal */
 	{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
 	/* Audio short */
-	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
+	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short",
+	 IORESOURCE_IRQ,},
 };
 
 static struct resource battery_resources[] = {
@@ -150,10 +152,14 @@ static struct resource battery_resources
 
 static struct resource charger_resources[] = {
 	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
-	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
-	{PM8607_IRQ_CHG_FAIL,  PM8607_IRQ_CHG_FAIL,  "charging timeout",    IORESOURCE_IRQ,},
-	{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",	    IORESOURCE_IRQ,},
-	{PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature", IORESOURCE_IRQ,},
+	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",
+	 IORESOURCE_IRQ,},
+	{PM8607_IRQ_CHG_FAIL,  PM8607_IRQ_CHG_FAIL,  "charging timeout",
+	 IORESOURCE_IRQ,},
+	{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",
+	 IORESOURCE_IRQ,},
+	{PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature",
+	 IORESOURCE_IRQ,},
 	{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
@@ -568,8 +574,8 @@ static struct irq_domain_ops pm860x_irq_
 static int device_irq_init(struct pm860x_chip *chip,
 				     struct pm860x_platform_data *pdata)
 {
-	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
-				: chip->companion;
+	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ?
+		chip->client : chip->companion;
 	unsigned char status_buf[INT_STATUS_NUM];
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
 	int data, mask, ret = -EINVAL;
@@ -631,8 +637,8 @@ static int device_irq_init(struct pm860x
 	if (!chip->core_irq)
 		goto out;
 
-	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
-				   "88pm860x", chip);
+	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq,
+				   flags | IRQF_ONESHOT, "88pm860x", chip);
 	if (ret) {
 		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
 		chip->core_irq = 0;
@@ -871,7 +877,7 @@ static void device_rtc_init(struct pm860
 {
 	int ret;
 
-	if ((pdata == NULL))
+	if (!pdata)
 		return;
 
 	rtc_devs[0].platform_data = pdata->rtc;
@@ -997,8 +1003,9 @@ static void device_8607_init(struct pm86
 			 ret);
 		break;
 	default:
-		dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
-			"Chip ID: %02x\n", ret);
+		dev_err(chip->dev,
+			"Failed to detect Marvell 88PM8607. Chip ID: %02x\n",
+			ret);
 		goto out;
 	}
 
@@ -1120,8 +1127,8 @@ static int pm860x_dt_init(struct device_
 	ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
 				   &pdata->companion_addr);
 	if (ret) {
-		dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
-			"property\n");
+		dev_err(dev,
+			"Not found \"marvell,88pm860x-slave-addr\" property\n");
 		pdata->companion_addr = 0;
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/88pm860x-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/88pm860x-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/88pm860x-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/88pm860x-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,8 @@
  * I2C driver for Marvell 88PM860x
  *
  * Copyright (C) 2009 Marvell International Ltd.
- * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/aat2870-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/aat2870-core.c
--- linux-libre-3.16-gnu/drivers/mfd/aat2870-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/aat2870-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -303,7 +303,10 @@ static ssize_t aat2870_reg_write_file(st
 	while (*start == ' ')
 		start++;
 
-	addr = simple_strtoul(start, &start, 16);
+	ret = kstrtoul(start, 16, &addr);
+	if (ret)
+		return ret;
+
 	if (addr >= AAT2870_REG_NUM) {
 		dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/ab3100-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-3.16-gnu/drivers/mfd/ab3100-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/ab3100-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -91,8 +91,8 @@ static int ab3100_set_register_interrupt
 			err);
 	} else if (err != 2) {
 		dev_err(ab3100->dev,
-			"write error (write register) "
-			"%d bytes transferred (expected 2)\n",
+			"write error (write register)\n"
+			"  %d bytes transferred (expected 2)\n",
 			err);
 		err = -EIO;
 	} else {
@@ -135,8 +135,8 @@ static int ab3100_set_test_register_inte
 			err);
 	} else if (err != 2) {
 		dev_err(ab3100->dev,
-			"write error (write test register) "
-			"%d bytes transferred (expected 2)\n",
+			"write error (write test register)\n"
+			"  %d bytes transferred (expected 2)\n",
 			err);
 		err = -EIO;
 	} else {
@@ -171,8 +171,8 @@ static int ab3100_get_register_interrupt
 		goto get_reg_out_unlock;
 	} else if (err != 1) {
 		dev_err(ab3100->dev,
-			"write error (send register address) "
-			"%d bytes transferred (expected 1)\n",
+			"write error (send register address)\n"
+			"  %d bytes transferred (expected 1)\n",
 			err);
 		err = -EIO;
 		goto get_reg_out_unlock;
@@ -189,8 +189,8 @@ static int ab3100_get_register_interrupt
 		goto get_reg_out_unlock;
 	} else if (err != 1) {
 		dev_err(ab3100->dev,
-			"write error (read register) "
-			"%d bytes transferred (expected 1)\n",
+			"write error (read register)\n"
+			"  %d bytes transferred (expected 1)\n",
 			err);
 		err = -EIO;
 		goto get_reg_out_unlock;
@@ -237,8 +237,8 @@ static int ab3100_get_register_page_inte
 		goto get_reg_page_out_unlock;
 	} else if (err != 1) {
 		dev_err(ab3100->dev,
-			"write error (send first register address) "
-			"%d bytes transferred (expected 1)\n",
+			"write error (send first register address)\n"
+			"  %d bytes transferred (expected 1)\n",
 			err);
 		err = -EIO;
 		goto get_reg_page_out_unlock;
@@ -252,8 +252,8 @@ static int ab3100_get_register_page_inte
 		goto get_reg_page_out_unlock;
 	} else if (err != numregs) {
 		dev_err(ab3100->dev,
-			"write error (read register page) "
-			"%d bytes transferred (expected %d)\n",
+			"write error (read register page)\n"
+			"  %d bytes transferred (expected %d)\n",
 			err, numregs);
 		err = -EIO;
 		goto get_reg_page_out_unlock;
@@ -295,8 +295,8 @@ static int ab3100_mask_and_set_register_
 		goto get_maskset_unlock;
 	} else if (err != 1) {
 		dev_err(ab3100->dev,
-			"write error (maskset send address) "
-			"%d bytes transferred (expected 1)\n",
+			"write error (maskset send address)\n"
+			"  %d bytes transferred (expected 1)\n",
 			err);
 		err = -EIO;
 		goto get_maskset_unlock;
@@ -310,8 +310,8 @@ static int ab3100_mask_and_set_register_
 		goto get_maskset_unlock;
 	} else if (err != 1) {
 		dev_err(ab3100->dev,
-			"write error (maskset read register) "
-			"%d bytes transferred (expected 1)\n",
+			"write error (maskset read register)\n"
+			"  %d bytes transferred (expected 1)\n",
 			err);
 		err = -EIO;
 		goto get_maskset_unlock;
@@ -330,8 +330,8 @@ static int ab3100_mask_and_set_register_
 		goto get_maskset_unlock;
 	} else if (err != 2) {
 		dev_err(ab3100->dev,
-			"write error (write register) "
-			"%d bytes transferred (expected 2)\n",
+			"write error (write register)\n"
+			"  %d bytes transferred (expected 2)\n",
 			err);
 		err = -EIO;
 		goto get_maskset_unlock;
@@ -371,7 +371,7 @@ EXPORT_SYMBOL(ab3100_event_register);
 int ab3100_event_unregister(struct ab3100 *ab3100,
 			    struct notifier_block *nb)
 {
-  return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
+	return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
 					    nb);
 }
 EXPORT_SYMBOL(ab3100_event_unregister);
@@ -455,7 +455,7 @@ static int ab3100_registers_print(struct
 	u8 value;
 	u8 reg;
 
-	seq_printf(s, "AB3100 registers:\n");
+	seq_puts(s, "AB3100 registers:\n");
 
 	for (reg = 0; reg < 0xff; reg++) {
 		ab3100_get_register_interruptible(ab3100, reg, &value);
@@ -560,8 +560,8 @@ static ssize_t ab3100_get_set_reg(struct
 		ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
 
 		dev_info(ab3100->dev,
-			 "debug write reg[0x%02x] with 0x%02x, "
-			 "after readback: 0x%02x\n",
+			 "debug write reg[0x%02x]\n"
+			 "  with 0x%02x, after readback: 0x%02x\n",
 			 user_reg, user_value, regvalue);
 	}
 	return buf_size;
@@ -719,8 +719,7 @@ static int ab3100_setup(struct ab3100 *a
 	 */
 	if (ab3100->chip_id == 0xc4) {
 		dev_warn(ab3100->dev,
-			 "AB3100 P1E variant detected, "
-			 "forcing chip to 32KHz\n");
+			 "AB3100 P1E variant detected forcing chip to 32KHz\n");
 		err = ab3100_set_test_register_interruptible(ab3100,
 			0x02, 0x08);
 	}
@@ -878,8 +877,7 @@ static int ab3100_probe(struct i2c_clien
 						&ab3100->chip_id);
 	if (err) {
 		dev_err(&client->dev,
-			"could not communicate with the AB3100 analog "
-			"baseband chip\n");
+			"failed to communicate with AB3100 chip\n");
 		goto exit_no_detect;
 	}
 
@@ -902,8 +900,8 @@ static int ab3100_probe(struct i2c_clien
 	if (ids[i].id == 0x0) {
 		dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
 			ab3100->chip_id);
-		dev_err(&client->dev, "accepting it anyway. Please update "
-			"the driver.\n");
+		dev_err(&client->dev,
+			"accepting it anyway. Please update the driver.\n");
 		goto exit_no_detect;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/ab8500-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/ab8500-core.c
--- linux-libre-3.16-gnu/drivers/mfd/ab8500-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/ab8500-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,8 +148,8 @@ static const int ab9540_irq_regoffset[AB
 
 /* AB8540 support */
 static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
-	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
-	25, 26, 27, 28, 29, 30, 31,
+	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
+	23, 25, 26, 27, 28, 29, 30, 31,
 };
 
 static const char ab8500_version_str[][7] = {
@@ -322,7 +322,7 @@ static int ab8500_mask_and_set_register(
 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
 
 	atomic_inc(&ab8500->transfer_ongoing);
-	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
+	ret = mask_and_set_register_interruptible(ab8500, bank, reg,
 						 bitmask, bitvalues);
 	atomic_dec(&ab8500->transfer_ongoing);
 	return ret;
@@ -415,9 +415,11 @@ static void ab8500_irq_unmask(struct irq
 	if (type & IRQ_TYPE_EDGE_FALLING) {
 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
 			ab8500->mask[index + 2] &= ~mask;
-		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
+		else if (offset >= AB9540_INT_GPIO50R &&
+			 offset <= AB9540_INT_GPIO54R)
 			ab8500->mask[index + 1] &= ~mask;
-		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
+		else if (offset == AB8540_INT_GPIO43R ||
+			 offset == AB8540_INT_GPIO44R)
 			/* Here the falling IRQ is one bit lower */
 			ab8500->mask[index] &= ~(mask << 1);
 		else
@@ -451,7 +453,7 @@ static void update_latch_offset(u8 *offs
 	/* Fix inconsistent ab8540 bit mapping... */
 	if (unlikely(*offset == 16))
 			*offset = 25;
-	if ((i==3) && (*offset >= 24))
+	if ((i == 3) && (*offset >= 24))
 			*offset += 2;
 }
 
@@ -573,8 +575,8 @@ static int ab8500_irq_map(struct irq_dom
 }
 
 static struct irq_domain_ops ab8500_irq_ops = {
-        .map    = ab8500_irq_map,
-        .xlate  = irq_domain_xlate_twocell,
+	.map    = ab8500_irq_map,
+	.xlate  = irq_domain_xlate_twocell,
 };
 
 static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
@@ -607,8 +609,8 @@ int ab8500_suspend(struct ab8500 *ab8500
 {
 	if (atomic_read(&ab8500->transfer_ongoing))
 		return -EINVAL;
-	else
-		return 0;
+
+	return 0;
 }
 
 static struct resource ab8500_gpadc_resources[] = {
@@ -1551,7 +1553,7 @@ static struct attribute_group ab9540_att
 
 static int ab8500_probe(struct platform_device *pdev)
 {
-	static char *switch_off_status[] = {
+	static const char *switch_off_status[] = {
 		"Swoff bit programming",
 		"Thermal protection activation",
 		"Vbat lower then BattOk falling threshold",
@@ -1560,7 +1562,7 @@ static int ab8500_probe(struct platform_
 		"Battery level lower than power on reset threshold",
 		"Power on key 1 pressed longer than 10 seconds",
 		"DB8500 thermal shutdown"};
-	static char *turn_on_status[] = {
+	static const char *turn_on_status[] = {
 		"Battery rising (Vbat)",
 		"Power On Key 1 dbF",
 		"Power On Key 2 dbF",
@@ -1579,7 +1581,7 @@ static int ab8500_probe(struct platform_
 	int i;
 	u8 value;
 
-	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
+	ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
 	if (!ab8500)
 		return -ENOMEM;
 
@@ -1636,7 +1638,7 @@ static int ab8500_probe(struct platform_
 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
-	}/* Configure AB8500 or AB9540 IRQ */
+	} /* Configure AB8500 or AB9540 IRQ */
 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
@@ -1646,10 +1648,12 @@ static int ab8500_probe(struct platform_
 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
 	}
-	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+				    GFP_KERNEL);
 	if (!ab8500->mask)
 		return -ENOMEM;
-	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+				       GFP_KERNEL);
 	if (!ab8500->oldmask)
 		return -ENOMEM;
 
@@ -1674,14 +1678,13 @@ static int ab8500_probe(struct platform_
 	if (value) {
 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
 			if (value & 1)
-				printk(KERN_CONT " \"%s\"",
-				       switch_off_status[i]);
+				pr_cont(" \"%s\"", switch_off_status[i]);
 			value = value >> 1;
 
 		}
-		printk(KERN_CONT "\n");
+		pr_cont("\n");
 	} else {
-		printk(KERN_CONT " None\n");
+		pr_cont(" None\n");
 	}
 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
 		AB8500_TURN_ON_STATUS, &value);
@@ -1692,12 +1695,12 @@ static int ab8500_probe(struct platform_
 	if (value) {
 		for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
 			if (value & 1)
-				printk("\"%s\" ", turn_on_status[i]);
+				pr_cont("\"%s\" ", turn_on_status[i]);
 			value = value >> 1;
 		}
-		printk("\n");
+		pr_cont("\n");
 	} else {
-		printk("None\n");
+		pr_cont("None\n");
 	}
 
 	if (plat && plat->init)
@@ -1751,7 +1754,7 @@ static int ab8500_probe(struct platform_
 	if (ret)
 		return ret;
 
-#if CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
 	/* Pass to debugfs */
 	ab8500_debug_resources[0].start = ab8500->irq;
 	ab8500_debug_resources[0].end = ab8500->irq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/ab8500-debugfs.c linux-libre-3.17-rc7-gnu/drivers/mfd/ab8500-debugfs.c
--- linux-libre-3.16-gnu/drivers/mfd/ab8500-debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/ab8500-debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,10 +135,10 @@ struct ab8500_prcmu_ranges {
 /* hwreg- "mask" and "shift" entries ressources */
 struct hwreg_cfg {
 	u32  bank;      /* target bank */
-	u32  addr;      /* target address */
+	unsigned long addr;      /* target address */
 	uint fmt;       /* format */
-	uint mask;      /* read/write mask, applied before any bit shift */
-	int  shift;     /* bit shift (read:right shift, write:left shift */
+	unsigned long mask; /* read/write mask, applied before any bit shift */
+	long shift;     /* bit shift (read:right shift, write:left shift */
 };
 /* fmt bit #0: 0=hexa, 1=dec */
 #define REG_FMT_DEC(c) ((c)->fmt & 0x1)
@@ -1304,16 +1304,17 @@ static int ab8500_registers_print(struct
 			}
 
 			if (s) {
-				err = seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n",
-					bank, reg, value);
+				err = seq_printf(s,
+						 "  [0x%02X/0x%02X]: 0x%02X\n",
+						 bank, reg, value);
 				if (err < 0) {
 					/* Error is not returned here since
 					 * the output is wanted in any case */
 					return 0;
 				}
 			} else {
-				printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
-					bank, reg, value);
+				dev_info(dev, " [0x%02X/0x%02X]: 0x%02X\n",
+					 bank, reg, value);
 			}
 		}
 	}
@@ -1325,7 +1326,7 @@ static int ab8500_print_bank_registers(s
 	struct device *dev = s->private;
 	u32 bank = debug_bank;
 
-	seq_printf(s, AB8500_NAME_STRING " register values:\n");
+	seq_puts(s, AB8500_NAME_STRING " register values:\n");
 
 	seq_printf(s, " bank 0x%02X:\n", bank);
 
@@ -1350,12 +1351,11 @@ static int ab8500_print_all_banks(struct
 {
 	struct device *dev = s->private;
 	unsigned int i;
-	int err;
 
-	seq_printf(s, AB8500_NAME_STRING " register values:\n");
+	seq_puts(s, AB8500_NAME_STRING " register values:\n");
 
 	for (i = 0; i < AB8500_NUM_BANKS; i++) {
-		err = seq_printf(s, " bank 0x%02X:\n", i);
+		seq_printf(s, " bank 0x%02X:\n", i);
 
 		ab8500_registers_print(dev, i, s);
 	}
@@ -1367,10 +1367,10 @@ void ab8500_dump_all_banks(struct device
 {
 	unsigned int i;
 
-	printk(KERN_INFO"ab8500 register values:\n");
+	dev_info(dev, "ab8500 register values:\n");
 
 	for (i = 1; i < AB8500_NUM_BANKS; i++) {
-		printk(KERN_INFO" bank 0x%02X:\n", i);
+		dev_info(dev, " bank 0x%02X:\n", i);
 		ab8500_registers_print(dev, i, NULL);
 	}
 }
@@ -1384,8 +1384,6 @@ static struct ab8500_register_dump
 	u8 value;
 } ab8500_complete_register_dump[DUMP_MAX_REGS];
 
-extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-
 /* This shall only be called upon kernel panic! */
 void ab8500_dump_all_banks_to_mem(void)
 {
@@ -1393,8 +1391,7 @@ void ab8500_dump_all_banks_to_mem(void)
 	u8 bank;
 	int err = 0;
 
-	pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
-		"for crash analyze.\n");
+	pr_info("Saving all ABB registers for crash analysis.\n");
 
 	for (bank = 0; bank < AB8500_NUM_BANKS; bank++) {
 		for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
@@ -1564,7 +1561,7 @@ static ssize_t ab8500_val_write(struct f
 	err = abx500_set_register_interruptible(dev,
 		(u8)debug_bank, debug_address, (u8)user_val);
 	if (err < 0) {
-		printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
+		pr_err("abx500_set_reg failed %d, %d", err, __LINE__);
 		return -EINVAL;
 	}
 
@@ -1596,7 +1593,7 @@ static int ab8500_interrupts_print(struc
 {
 	int line;
 
-	seq_printf(s, "name: number:  number of: wake:\n");
+	seq_puts(s, "name: number:  number of: wake:\n");
 
 	for (line = 0; line < num_interrupt_lines; line++) {
 		struct irq_desc *desc = irq_to_desc(line + irq_first);
@@ -1722,7 +1719,8 @@ static int ab8500_print_modem_registers(
 
 static int ab8500_modem_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_print_modem_registers, inode->i_private);
+	return single_open(file, ab8500_print_modem_registers,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_modem_fops = {
@@ -1751,7 +1749,8 @@ static int ab8500_gpadc_bat_ctrl_print(s
 
 static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_bat_ctrl_print,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
@@ -1781,7 +1780,8 @@ static int ab8500_gpadc_btemp_ball_print
 static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
 					struct file *file)
 {
-	return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_btemp_ball_print,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
@@ -1962,7 +1962,8 @@ static int ab8500_gpadc_main_bat_v_print
 static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
 					struct file *file)
 {
-	return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_main_bat_v_print,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
@@ -2082,7 +2083,8 @@ static int ab8500_gpadc_bk_bat_v_print(s
 
 static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_bk_bat_v_print,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
@@ -2111,7 +2113,8 @@ static int ab8500_gpadc_die_temp_print(s
 
 static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_die_temp_print,
+			   inode->i_private);
 }
 
 static const struct file_operations ab8500_gpadc_die_temp_fops = {
@@ -2190,8 +2193,9 @@ static int ab8540_gpadc_vbat_true_meas_p
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 	vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
 		avg_sample, trig_edge, trig_timer, conv_type);
-	vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
-		vbat_true_meas_raw);
+	vbat_true_meas_convert =
+		ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
+					   vbat_true_meas_raw);
 
 	return seq_printf(s, "%d,0x%X\n",
 		vbat_true_meas_convert, vbat_true_meas_raw);
@@ -2285,7 +2289,8 @@ static const struct file_operations ab85
 	.owner = THIS_MODULE,
 };
 
-static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
+						      void *p)
 {
 	int vbat_true_meas_raw;
 	int vbat_true_meas_convert;
@@ -2314,7 +2319,8 @@ static int ab8540_gpadc_vbat_true_meas_a
 		inode->i_private);
 }
 
-static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
+static const struct file_operations
+ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
 	.open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -2368,14 +2374,15 @@ static int ab8540_gpadc_otp_cal_print(st
 	ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
 			&vbat_l, &vbat_h, &ibat_l, &ibat_h);
 	return seq_printf(s, "VMAIN_L:0x%X\n"
-		"VMAIN_H:0x%X\n"
-		"BTEMP_L:0x%X\n"
-		"BTEMP_H:0x%X\n"
-		"VBAT_L:0x%X\n"
-		"VBAT_H:0x%X\n"
-		"IBAT_L:0x%X\n"
-		"IBAT_H:0x%X\n",
-		vmain_l, vmain_h, btemp_l, btemp_h, vbat_l, vbat_h, ibat_l, ibat_h);
+			  "VMAIN_H:0x%X\n"
+			  "BTEMP_L:0x%X\n"
+			  "BTEMP_H:0x%X\n"
+			  "VBAT_L:0x%X\n"
+			  "VBAT_H:0x%X\n"
+			  "IBAT_L:0x%X\n"
+			  "IBAT_H:0x%X\n",
+			  vmain_l, vmain_h, btemp_l, btemp_h,
+			  vbat_l, vbat_h, ibat_l, ibat_h);
 }
 
 static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
@@ -2419,8 +2426,8 @@ static ssize_t ab8500_gpadc_avg_sample_w
 			|| (user_avg_sample == SAMPLE_16)) {
 		avg_sample = (u8) user_avg_sample;
 	} else {
-		dev_err(dev, "debugfs error input: "
-			"should be egal to 1, 4, 8 or 16\n");
+		dev_err(dev,
+			"debugfs err input: should be egal to 1, 4, 8 or 16\n");
 		return -EINVAL;
 	}
 
@@ -2504,14 +2511,14 @@ static ssize_t ab8500_gpadc_trig_timer_w
 	if (err)
 		return err;
 
-	if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
-		trig_timer = (u8) user_trig_timer;
-	} else {
-		dev_err(dev, "debugfs error input: "
-			"should be beetween 0 to 255\n");
+	if (user_trig_timer & ~0xFF) {
+		dev_err(dev,
+			"debugfs error input: should be beetween 0 to 255\n");
 		return -EINVAL;
 	}
 
+	trig_timer = (u8) user_trig_timer;
+
 	return count;
 }
 
@@ -2579,6 +2586,7 @@ static const struct file_operations ab85
 static int strval_len(char *b)
 {
 	char *s = b;
+
 	if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
 		s += 2;
 		for (; *s && (*s != ' ') && (*s != '\n'); s++) {
@@ -2643,13 +2651,17 @@ static ssize_t hwreg_common_write(char *
 			b += (*(b+2) == ' ') ? 3 : 6;
 			if (strval_len(b) == 0)
 				return -EINVAL;
-			loc.mask = simple_strtoul(b, &b, 0);
+			ret = kstrtoul(b, 0, &loc.mask);
+			if (ret)
+				return ret;
 		} else if ((!strncmp(b, "-s ", 3)) ||
 				(!strncmp(b, "-shift ", 7))) {
 			b += (*(b+2) == ' ') ? 3 : 7;
 			if (strval_len(b) == 0)
 				return -EINVAL;
-			loc.shift = simple_strtol(b, &b, 0);
+			ret = kstrtol(b, 0, &loc.shift);
+			if (ret)
+				return ret;
 		} else {
 			return -EINVAL;
 		}
@@ -2657,29 +2669,36 @@ static ssize_t hwreg_common_write(char *
 	/* get arg BANK and ADDRESS */
 	if (strval_len(b) == 0)
 		return -EINVAL;
-	loc.bank = simple_strtoul(b, &b, 0);
+	ret = kstrtouint(b, 0, &loc.bank);
+	if (ret)
+		return ret;
 	while (*b == ' ')
 		b++;
 	if (strval_len(b) == 0)
 		return -EINVAL;
-	loc.addr = simple_strtoul(b, &b, 0);
+	ret = kstrtoul(b, 0, &loc.addr);
+	if (ret)
+		return ret;
 
 	if (write) {
 		while (*b == ' ')
 			b++;
 		if (strval_len(b) == 0)
 			return -EINVAL;
-		val = simple_strtoul(b, &b, 0);
+		ret = kstrtouint(b, 0, &val);
+		if (ret)
+			return ret;
 	}
 
 	/* args are ok, update target cfg (mainly for read) */
 	*cfg = loc;
 
 #ifdef ABB_HWREG_DEBUG
-	pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
-			"value=0x%X\n", (write) ? "write" : "read",
-			REG_FMT_DEC(cfg) ? "decimal" : "hexa",
-			cfg->addr, cfg->mask, cfg->shift, val);
+	pr_warn("HWREG request: %s, %s,\n"
+		"  addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n",
+		(write) ? "write" : "read",
+		REG_FMT_DEC(cfg) ? "decimal" : "hexa",
+		cfg->addr, cfg->mask, cfg->shift, val);
 #endif
 
 	if (!write)
@@ -2765,8 +2784,8 @@ static ssize_t show_irq(struct device *d
 	irq_index = name - irq_first;
 	if (irq_index >= num_irqs)
 		return -EINVAL;
-	else
-		return sprintf(buf, "%u\n", irq_count[irq_index]);
+
+	return sprintf(buf, "%u\n", irq_count[irq_index]);
 }
 
 static ssize_t ab8500_subscribe_write(struct file *file,
@@ -2815,7 +2834,7 @@ static ssize_t ab8500_subscribe_write(st
 	dev_attr[irq_index]->attr.mode = S_IRUGO;
 	err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
 	if (err < 0) {
-		printk(KERN_ERR "sysfs_create_file failed %d\n", err);
+		pr_info("sysfs_create_file failed %d\n", err);
 		return err;
 	}
 
@@ -2823,8 +2842,8 @@ static ssize_t ab8500_subscribe_write(st
 				   IRQF_SHARED | IRQF_NO_SUSPEND,
 				   "ab8500-debug", &dev->kobj);
 	if (err < 0) {
-		printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
-                       err, user_val);
+		pr_info("request_threaded_irq failed %d, %lu\n",
+			err, user_val);
 		sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
 		return err;
 	}
@@ -2946,6 +2965,7 @@ static int ab8500_debug_probe(struct pla
 	struct dentry *file;
 	struct ab8500 *ab8500;
 	struct resource *res;
+
 	debug_bank = AB8500_MISC;
 	debug_address = AB8500_REV_REG & 0x00FF;
 
@@ -2958,7 +2978,7 @@ static int ab8500_debug_probe(struct pla
 		return -ENOMEM;
 
 	dev_attr = devm_kzalloc(&plf->dev,
-				sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
+				sizeof(*dev_attr)*num_irqs, GFP_KERNEL);
 	if (!dev_attr)
 		return -ENOMEM;
 
@@ -2969,23 +2989,20 @@ static int ab8500_debug_probe(struct pla
 
 	res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
 	if (!res) {
-		dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
-			irq_first);
-		return ENXIO;
+		dev_err(&plf->dev, "AB8500 irq not found, err %d\n", irq_first);
+		return -ENXIO;
 	}
 	irq_ab8500 = res->start;
 
 	irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
 	if (irq_first < 0) {
-		dev_err(&plf->dev, "First irq not found, err %d\n",
-			irq_first);
+		dev_err(&plf->dev, "First irq not found, err %d\n", irq_first);
 		return irq_first;
 	}
 
 	irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
 	if (irq_last < 0) {
-		dev_err(&plf->dev, "Last irq not found, err %d\n",
-			irq_last);
+		dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last);
 		return irq_last;
 	}
 
@@ -2994,37 +3011,41 @@ static int ab8500_debug_probe(struct pla
 		goto err;
 
 	ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
-		ab8500_dir);
+					      ab8500_dir);
 	if (!ab8500_gpadc_dir)
 		goto err;
 
-	file = debugfs_create_file("all-bank-registers", S_IRUGO,
-		ab8500_dir, &plf->dev, &ab8500_registers_fops);
+	file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir,
+				   &plf->dev, &ab8500_registers_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("all-banks", S_IRUGO,
-		ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
+	file = debugfs_create_file("all-banks", S_IRUGO, ab8500_dir,
+				   &plf->dev, &ab8500_all_banks_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_bank_fops);
+	file = debugfs_create_file("register-bank",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_dir, &plf->dev, &ab8500_bank_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_address_fops);
+	file = debugfs_create_file("register-address",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_dir, &plf->dev, &ab8500_address_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_val_fops);
+	file = debugfs_create_file("register-value",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_dir, &plf->dev, &ab8500_val_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
+	file = debugfs_create_file("irq-subscribe",
+				   (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+				   &plf->dev, &ab8500_subscribe_fops);
 	if (!file)
 		goto err;
 
@@ -3042,158 +3063,191 @@ static int ab8500_debug_probe(struct pla
 		num_interrupt_lines = AB8540_NR_IRQS;
 	}
 
-	file = debugfs_create_file("interrupts", (S_IRUGO),
-		ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
+	file = debugfs_create_file("interrupts", (S_IRUGO), ab8500_dir,
+				   &plf->dev, &ab8500_interrupts_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
+	file = debugfs_create_file("irq-unsubscribe",
+				   (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+				   &plf->dev, &ab8500_unsubscribe_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
+				   ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_dir, &plf->dev, &ab8500_modem_fops);
+	file = debugfs_create_file("all-modem-registers",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_dir, &plf->dev, &ab8500_modem_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_bat_ctrl_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
+				   ab8500_gpadc_dir,
+				   &plf->dev, &ab8500_gpadc_btemp_ball_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
+	file = debugfs_create_file("main_charger_v",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_main_charger_v_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
+	file = debugfs_create_file("acc_detect1",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_acc_detect1_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
+	file = debugfs_create_file("acc_detect2",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_acc_detect2_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_aux1_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_aux2_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_main_bat_v_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_vbus_v_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
+	file = debugfs_create_file("main_charger_c",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_main_charger_c_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
+	file = debugfs_create_file("usb_charger_c",
+				   (S_IRUGO | S_IWUSR | S_IWGRP),
+				   ab8500_gpadc_dir,
+				   &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_bk_bat_v_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_die_temp_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_id_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_usb_id_fops);
 	if (!file)
 		goto err;
 
 	if (is_ab8540(ab8500)) {
-		file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
-			ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops);
+		file = debugfs_create_file("xtal_temp",
+					   (S_IRUGO | S_IWUSR | S_IWGRP),
+					   ab8500_gpadc_dir, &plf->dev,
+					   &ab8540_gpadc_xtal_temp_fops);
 		if (!file)
 			goto err;
-		file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP),
-			ab8500_gpadc_dir, &plf->dev,
-			&ab8540_gpadc_vbat_true_meas_fops);
+		file = debugfs_create_file("vbattruemeas",
+					   (S_IRUGO | S_IWUSR | S_IWGRP),
+					   ab8500_gpadc_dir, &plf->dev,
+					   &ab8540_gpadc_vbat_true_meas_fops);
 		if (!file)
 			goto err;
 		file = debugfs_create_file("batctrl_and_ibat",
-			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
-			&plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops);
+					(S_IRUGO | S_IWUGO),
+					ab8500_gpadc_dir,
+					&plf->dev,
+					&ab8540_gpadc_bat_ctrl_and_ibat_fops);
 		if (!file)
 			goto err;
 		file = debugfs_create_file("vbatmeas_and_ibat",
-			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
-			&plf->dev,
-			&ab8540_gpadc_vbat_meas_and_ibat_fops);
+					(S_IRUGO | S_IWUGO),
+					ab8500_gpadc_dir, &plf->dev,
+					&ab8540_gpadc_vbat_meas_and_ibat_fops);
 		if (!file)
 			goto err;
 		file = debugfs_create_file("vbattruemeas_and_ibat",
-			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
-			&plf->dev,
-			&ab8540_gpadc_vbat_true_meas_and_ibat_fops);
+				(S_IRUGO | S_IWUGO),
+				ab8500_gpadc_dir,
+				&plf->dev,
+				&ab8540_gpadc_vbat_true_meas_and_ibat_fops);
 		if (!file)
 			goto err;
 		file = debugfs_create_file("battemp_and_ibat",
-			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+			(S_IRUGO | S_IWUGO),
+			ab8500_gpadc_dir,
 			&plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops);
 		if (!file)
 			goto err;
-		file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP),
-			ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops);
+		file = debugfs_create_file("otp_calib",
+				(S_IRUGO | S_IWUSR | S_IWGRP),
+				ab8500_gpadc_dir,
+				&plf->dev, &ab8540_gpadc_otp_calib_fops);
 		if (!file)
 			goto err;
 	}
 	file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_avg_sample_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_trig_edge_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_trig_timer_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP),
-		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
+				   ab8500_gpadc_dir, &plf->dev,
+				   &ab8500_gpadc_conv_type_fops);
 	if (!file)
 		goto err;
 
 	return 0;
 
 err:
-	if (ab8500_dir)
-		debugfs_remove_recursive(ab8500_dir);
+	debugfs_remove_recursive(ab8500_dir);
 	dev_err(&plf->dev, "failed to create debugfs entries.\n");
 
 	return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/arizona-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-core.c
--- linux-libre-3.16-gnu/drivers/mfd/arizona-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,6 +123,8 @@ static irqreturn_t arizona_underclocked(
 		dev_err(arizona->dev, "AIF2 underclocked\n");
 	if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
 		dev_err(arizona->dev, "AIF1 underclocked\n");
+	if (val & ARIZONA_ISRC3_UNDERCLOCKED_STS)
+		dev_err(arizona->dev, "ISRC3 underclocked\n");
 	if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
 		dev_err(arizona->dev, "ISRC2 underclocked\n");
 	if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS)
@@ -192,6 +194,8 @@ static irqreturn_t arizona_overclocked(i
 		dev_err(arizona->dev, "ASRC sync WARP overclocked\n");
 	if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS)
 		dev_err(arizona->dev, "DSP1 overclocked\n");
+	if (val[1] & ARIZONA_ISRC3_OVERCLOCKED_STS)
+		dev_err(arizona->dev, "ISRC3 overclocked\n");
 	if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS)
 		dev_err(arizona->dev, "ISRC2 overclocked\n");
 	if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
@@ -497,12 +501,12 @@ const struct dev_pm_ops arizona_pm_ops =
 EXPORT_SYMBOL_GPL(arizona_pm_ops);
 
 #ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev)
+unsigned long arizona_of_get_type(struct device *dev)
 {
 	const struct of_device_id *id = of_match_device(arizona_of_match, dev);
 
 	if (id)
-		return (int)id->data;
+		return (unsigned long)id->data;
 	else
 		return 0;
 }
@@ -578,17 +582,21 @@ static const struct mfd_cell early_devs[
 };
 
 static const char *wm5102_supplies[] = {
+	"MICVDD",
 	"DBVDD2",
 	"DBVDD3",
 	"CPVDD",
 	"SPKVDDL",
 	"SPKVDDR",
-	"MICVDD",
 };
 
 static const struct mfd_cell wm5102_devs[] = {
 	{ .name = "arizona-micsupp" },
-	{ .name = "arizona-extcon" },
+	{
+		.name = "arizona-extcon",
+		.parent_supplies = wm5102_supplies,
+		.num_parent_supplies = 1, /* We only need MICVDD */
+	},
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
@@ -601,7 +609,11 @@ static const struct mfd_cell wm5102_devs
 
 static const struct mfd_cell wm5110_devs[] = {
 	{ .name = "arizona-micsupp" },
-	{ .name = "arizona-extcon" },
+	{
+		.name = "arizona-extcon",
+		.parent_supplies = wm5102_supplies,
+		.num_parent_supplies = 1, /* We only need MICVDD */
+	},
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
@@ -613,6 +625,7 @@ static const struct mfd_cell wm5110_devs
 };
 
 static const char *wm8997_supplies[] = {
+	"MICVDD",
 	"DBVDD2",
 	"CPVDD",
 	"SPKVDD",
@@ -620,7 +633,11 @@ static const char *wm8997_supplies[] = {
 
 static const struct mfd_cell wm8997_devs[] = {
 	{ .name = "arizona-micsupp" },
-	{ .name = "arizona-extcon" },
+	{
+		.name = "arizona-extcon",
+		.parent_supplies = wm8997_supplies,
+		.num_parent_supplies = 1, /* We only need MICVDD */
+	},
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
@@ -683,7 +700,13 @@ int arizona_dev_init(struct arizona *ari
 		goto err_early;
 	}
 
-	arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
+	/**
+	 * Don't use devres here because the only device we have to get
+	 * against is the MFD device and DCVDD will likely be supplied by
+	 * one of its children. Meaning that the regulator will be
+	 * destroyed by the time devres calls regulator put.
+	 */
+	arizona->dcvdd = regulator_get(arizona->dev, "DCVDD");
 	if (IS_ERR(arizona->dcvdd)) {
 		ret = PTR_ERR(arizona->dcvdd);
 		dev_err(dev, "Failed to request DCVDD: %d\n", ret);
@@ -697,7 +720,7 @@ int arizona_dev_init(struct arizona *ari
 				       "arizona /RESET");
 		if (ret != 0) {
 			dev_err(dev, "Failed to request /RESET: %d\n", ret);
-			goto err_early;
+			goto err_dcvdd;
 		}
 	}
 
@@ -706,7 +729,7 @@ int arizona_dev_init(struct arizona *ari
 	if (ret != 0) {
 		dev_err(dev, "Failed to enable core supplies: %d\n",
 			ret);
-		goto err_early;
+		goto err_dcvdd;
 	}
 
 	ret = regulator_enable(arizona->dcvdd);
@@ -1015,6 +1038,8 @@ err_reset:
 err_enable:
 	regulator_bulk_disable(arizona->num_core_supplies,
 			       arizona->core_supplies);
+err_dcvdd:
+	regulator_put(arizona->dcvdd);
 err_early:
 	mfd_remove_devices(dev);
 	return ret;
@@ -1023,16 +1048,20 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
 
 int arizona_dev_exit(struct arizona *arizona)
 {
+	pm_runtime_disable(arizona->dev);
+
+	regulator_disable(arizona->dcvdd);
+	regulator_put(arizona->dcvdd);
+
 	mfd_remove_devices(arizona->dev);
 	arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
 	arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
 	arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
-	pm_runtime_disable(arizona->dev);
 	arizona_irq_exit(arizona);
 	if (arizona->pdata.reset)
 		gpio_set_value_cansleep(arizona->pdata.reset, 0);
-	regulator_disable(arizona->dcvdd);
-	regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies),
+
+	regulator_bulk_disable(arizona->num_core_supplies,
 			       arizona->core_supplies);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/arizona.h linux-libre-3.17-rc7-gnu/drivers/mfd/arizona.h
--- linux-libre-3.16-gnu/drivers/mfd/arizona.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/arizona.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@ extern const struct regmap_irq_chip wm51
 
 extern const struct regmap_irq_chip wm5110_aod;
 extern const struct regmap_irq_chip wm5110_irq;
+extern const struct regmap_irq_chip wm5110_revd_irq;
 
 extern const struct regmap_irq_chip wm8997_aod;
 extern const struct regmap_irq_chip wm8997_irq;
@@ -46,9 +47,9 @@ int arizona_irq_init(struct arizona *ari
 int arizona_irq_exit(struct arizona *arizona);
 
 #ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev);
+unsigned long arizona_of_get_type(struct device *dev);
 #else
-static inline int arizona_of_get_type(struct device *dev)
+static inline unsigned long arizona_of_get_type(struct device *dev)
 {
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/arizona-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/arizona-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,11 +24,12 @@
 #include "arizona.h"
 
 static int arizona_i2c_probe(struct i2c_client *i2c,
-					  const struct i2c_device_id *id)
+			     const struct i2c_device_id *id)
 {
 	struct arizona *arizona;
 	const struct regmap_config *regmap_config;
-	int ret, type;
+	unsigned long type;
+	int ret;
 
 	if (i2c->dev.of_node)
 		type = arizona_of_get_type(&i2c->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/arizona-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/arizona-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -188,24 +188,33 @@ int arizona_irq_init(struct arizona *ari
 	int flags = IRQF_ONESHOT;
 	int ret, i;
 	const struct regmap_irq_chip *aod, *irq;
-	bool ctrlif_error = true;
 	struct irq_data *irq_data;
 
+	arizona->ctrlif_error = true;
+
 	switch (arizona->type) {
 #ifdef CONFIG_MFD_WM5102
 	case WM5102:
 		aod = &wm5102_aod;
 		irq = &wm5102_irq;
 
-		ctrlif_error = false;
+		arizona->ctrlif_error = false;
 		break;
 #endif
 #ifdef CONFIG_MFD_WM5110
 	case WM5110:
 		aod = &wm5110_aod;
-		irq = &wm5110_irq;
 
-		ctrlif_error = false;
+		switch (arizona->rev) {
+		case 0 ... 2:
+			irq = &wm5110_irq;
+			break;
+		default:
+			irq = &wm5110_revd_irq;
+			break;
+		}
+
+		arizona->ctrlif_error = false;
 		break;
 #endif
 #ifdef CONFIG_MFD_WM8997
@@ -213,7 +222,7 @@ int arizona_irq_init(struct arizona *ari
 		aod = &wm8997_aod;
 		irq = &wm8997_irq;
 
-		ctrlif_error = false;
+		arizona->ctrlif_error = false;
 		break;
 #endif
 	default:
@@ -300,7 +309,7 @@ int arizona_irq_init(struct arizona *ari
 	}
 
 	/* Handle control interface errors in the core */
-	if (ctrlif_error) {
+	if (arizona->ctrlif_error) {
 		i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
 		ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
 					   IRQF_ONESHOT,
@@ -345,7 +354,9 @@ int arizona_irq_init(struct arizona *ari
 	return 0;
 
 err_main_irq:
-	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+	if (arizona->ctrlif_error)
+		free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
+			 arizona);
 err_ctrlif:
 	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
 err_boot_done:
@@ -361,7 +372,9 @@ err:
 
 int arizona_irq_exit(struct arizona *arizona)
 {
-	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+	if (arizona->ctrlif_error)
+		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),
 			    arizona->irq_chip);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/arizona-spi.c linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-spi.c
--- linux-libre-3.16-gnu/drivers/mfd/arizona-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/arizona-spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,8 @@ static int arizona_spi_probe(struct spi_
 	const struct spi_device_id *id = spi_get_device_id(spi);
 	struct arizona *arizona;
 	const struct regmap_config *regmap_config;
-	int ret, type;
+	unsigned long type;
+	int ret;
 
 	if (spi->dev.of_node)
 		type = arizona_of_get_type(&spi->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/asic3.c linux-libre-3.17-rc7-gnu/drivers/mfd/asic3.c
--- linux-libre-3.16-gnu/drivers/mfd/asic3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/asic3.c	2014-09-28 17:29:07.000000000 -0400
@@ -899,13 +899,15 @@ static int __init asic3_mfd_probe(struct
 	ds1wm_resources[0].end   >>= asic->bus_shift;
 
 	/* MMC */
-	asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
+	if (mem_sdio) {
+		asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
 				 mem_sdio->start,
 				 ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
-	if (!asic->tmio_cnf) {
-		ret = -ENOMEM;
-		dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
-		goto out;
+		if (!asic->tmio_cnf) {
+			ret = -ENOMEM;
+			dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
+			goto out;
+		}
 	}
 	asic3_mmc_resources[0].start >>= asic->bus_shift;
 	asic3_mmc_resources[0].end   >>= asic->bus_shift;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/cros_ec.c linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec.c
--- linux-libre-3.16-gnu/drivers/mfd/cros_ec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,64 +25,42 @@
 #include <linux/mfd/cros_ec_commands.h>
 
 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
-		       struct cros_ec_msg *msg)
+		       struct cros_ec_command *msg)
 {
 	uint8_t *out;
 	int csum, i;
 
-	BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
+	BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
 	out = ec_dev->dout;
 	out[0] = EC_CMD_VERSION0 + msg->version;
-	out[1] = msg->cmd;
-	out[2] = msg->out_len;
+	out[1] = msg->command;
+	out[2] = msg->outsize;
 	csum = out[0] + out[1] + out[2];
-	for (i = 0; i < msg->out_len; i++)
-		csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
-	out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
+	for (i = 0; i < msg->outsize; i++)
+		csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
+	out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
 
-	return EC_MSG_TX_PROTO_BYTES + msg->out_len;
+	return EC_MSG_TX_PROTO_BYTES + msg->outsize;
 }
 EXPORT_SYMBOL(cros_ec_prepare_tx);
 
-static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
-		uint16_t cmd, void *out_buf, int out_len,
-		void *in_buf, int in_len)
-{
-	struct cros_ec_msg msg;
-
-	msg.version = cmd >> 8;
-	msg.cmd = cmd & 0xff;
-	msg.out_buf = out_buf;
-	msg.out_len = out_len;
-	msg.in_buf = in_buf;
-	msg.in_len = in_len;
-
-	return ec_dev->command_xfer(ec_dev, &msg);
-}
-
-static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
-		uint16_t cmd, void *buf, int buf_len)
-{
-	return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
-}
-
-static int cros_ec_command_send(struct cros_ec_device *ec_dev,
-		uint16_t cmd, void *buf, int buf_len)
-{
-	return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
-}
-
-static irqreturn_t ec_irq_thread(int irq, void *data)
+int cros_ec_check_result(struct cros_ec_device *ec_dev,
+			 struct cros_ec_command *msg)
 {
-	struct cros_ec_device *ec_dev = data;
-
-	if (device_may_wakeup(ec_dev->dev))
-		pm_wakeup_event(ec_dev->dev, 0);
-
-	blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
-
-	return IRQ_HANDLED;
+	switch (msg->result) {
+	case EC_RES_SUCCESS:
+		return 0;
+	case EC_RES_IN_PROGRESS:
+		dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+			msg->command);
+		return -EAGAIN;
+	default:
+		dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
+			msg->command, msg->result);
+		return 0;
+	}
 }
+EXPORT_SYMBOL(cros_ec_check_result);
 
 static const struct mfd_cell cros_devs[] = {
 	{
@@ -102,12 +80,6 @@ int cros_ec_register(struct cros_ec_devi
 	struct device *dev = ec_dev->dev;
 	int err = 0;
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
-
-	ec_dev->command_send = cros_ec_command_send;
-	ec_dev->command_recv = cros_ec_command_recv;
-	ec_dev->command_sendrecv = cros_ec_command_sendrecv;
-
 	if (ec_dev->din_size) {
 		ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
 		if (!ec_dev->din)
@@ -119,42 +91,23 @@ int cros_ec_register(struct cros_ec_devi
 			return -ENOMEM;
 	}
 
-	if (!ec_dev->irq) {
-		dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
-		return err;
-	}
-
-	err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
-				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				   "chromeos-ec", ec_dev);
-	if (err) {
-		dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
-		return err;
-	}
-
 	err = mfd_add_devices(dev, 0, cros_devs,
 			      ARRAY_SIZE(cros_devs),
 			      NULL, ec_dev->irq, NULL);
 	if (err) {
 		dev_err(dev, "failed to add mfd devices\n");
-		goto fail_mfd;
+		return err;
 	}
 
-	dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
+	dev_info(dev, "Chrome EC device registered\n");
 
 	return 0;
-
-fail_mfd:
-	free_irq(ec_dev->irq, ec_dev);
-
-	return err;
 }
 EXPORT_SYMBOL(cros_ec_register);
 
 int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
 	mfd_remove_devices(ec_dev->dev);
-	free_irq(ec_dev->irq, ec_dev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/cros_ec_i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec_i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/cros_ec_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,12 +29,13 @@ static inline struct cros_ec_device *to_
 	return i2c_get_clientdata(client);
 }
 
-static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
-				struct cros_ec_msg *msg)
+static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
+				struct cros_ec_command *msg)
 {
 	struct i2c_client *client = ec_dev->priv;
 	int ret = -ENOMEM;
 	int i;
+	int len;
 	int packet_len;
 	u8 *out_buf = NULL;
 	u8 *in_buf = NULL;
@@ -50,7 +51,7 @@ static int cros_ec_command_xfer(struct c
 	 * allocate larger packet (one byte for checksum, one byte for
 	 * length, and one for result code)
 	 */
-	packet_len = msg->in_len + 3;
+	packet_len = msg->insize + 3;
 	in_buf = kzalloc(packet_len, GFP_KERNEL);
 	if (!in_buf)
 		goto done;
@@ -61,7 +62,7 @@ static int cros_ec_command_xfer(struct c
 	 * allocate larger packet (one byte for checksum, one for
 	 * command code, one for length, and one for command version)
 	 */
-	packet_len = msg->out_len + 4;
+	packet_len = msg->outsize + 4;
 	out_buf = kzalloc(packet_len, GFP_KERNEL);
 	if (!out_buf)
 		goto done;
@@ -69,16 +70,16 @@ static int cros_ec_command_xfer(struct c
 	i2c_msg[0].buf = (char *)out_buf;
 
 	out_buf[0] = EC_CMD_VERSION0 + msg->version;
-	out_buf[1] = msg->cmd;
-	out_buf[2] = msg->out_len;
+	out_buf[1] = msg->command;
+	out_buf[2] = msg->outsize;
 
 	/* copy message payload and compute checksum */
 	sum = out_buf[0] + out_buf[1] + out_buf[2];
-	for (i = 0; i < msg->out_len; i++) {
-		out_buf[3 + i] = msg->out_buf[i];
+	for (i = 0; i < msg->outsize; i++) {
+		out_buf[3 + i] = msg->outdata[i];
 		sum += out_buf[3 + i];
 	}
-	out_buf[3 + msg->out_len] = sum;
+	out_buf[3 + msg->outsize] = sum;
 
 	/* send command to EC and read answer */
 	ret = i2c_transfer(client->adapter, i2c_msg, 2);
@@ -92,28 +93,34 @@ static int cros_ec_command_xfer(struct c
 	}
 
 	/* check response error code */
-	if (i2c_msg[1].buf[0]) {
-		dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
-			 msg->cmd, i2c_msg[1].buf[0]);
-		ret = -EINVAL;
+	msg->result = i2c_msg[1].buf[0];
+	ret = cros_ec_check_result(ec_dev, msg);
+	if (ret)
+		goto done;
+
+	len = in_buf[1];
+	if (len > msg->insize) {
+		dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
+			len, msg->insize);
+		ret = -ENOSPC;
 		goto done;
 	}
 
 	/* copy response packet payload and compute checksum */
 	sum = in_buf[0] + in_buf[1];
-	for (i = 0; i < msg->in_len; i++) {
-		msg->in_buf[i] = in_buf[2 + i];
+	for (i = 0; i < len; i++) {
+		msg->indata[i] = in_buf[2 + i];
 		sum += in_buf[2 + i];
 	}
 	dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
 		i2c_msg[1].len, in_buf, sum);
-	if (sum != in_buf[2 + msg->in_len]) {
+	if (sum != in_buf[2 + len]) {
 		dev_err(ec_dev->dev, "bad packet checksum\n");
 		ret = -EBADMSG;
 		goto done;
 	}
 
-	ret = 0;
+	ret = len;
  done:
 	kfree(in_buf);
 	kfree(out_buf);
@@ -132,11 +139,10 @@ static int cros_ec_i2c_probe(struct i2c_
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, ec_dev);
-	ec_dev->name = "I2C";
 	ec_dev->dev = dev;
 	ec_dev->priv = client;
 	ec_dev->irq = client->irq;
-	ec_dev->command_xfer = cros_ec_command_xfer;
+	ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
 	ec_dev->ec_name = client->name;
 	ec_dev->phys_name = client->adapter->name;
 	ec_dev->parent = &client->dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/cros_ec_spi.c linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec_spi.c
--- linux-libre-3.16-gnu/drivers/mfd/cros_ec_spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/cros_ec_spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@
  *	if no record
  * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
  *      is sent when we want to turn off CS at the end of a transaction.
- * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
+ * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
  */
 struct cros_ec_spi {
 	struct spi_device *spi;
@@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(
 }
 
 /**
- * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
+ * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
  *
  * @ec_dev: ChromeOS EC device
  * @ec_msg: Message to transfer
  */
-static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
-				    struct cros_ec_msg *ec_msg)
+static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
+				struct cros_ec_command *ec_msg)
 {
 	struct cros_ec_spi *ec_spi = ec_dev->priv;
 	struct spi_transfer trans;
@@ -225,7 +225,6 @@ static int cros_ec_command_spi_xfer(stru
 	u8 *ptr;
 	int sum;
 	int ret = 0, final_ret;
-	struct timespec ts;
 
 	/*
 	 * We have the shared ec_dev buffer plus we do lots of separate spi_sync
@@ -239,11 +238,9 @@ static int cros_ec_command_spi_xfer(stru
 
 	/* If it's too soon to do another transaction, wait */
 	if (ec_spi->last_transfer_ns) {
-		struct timespec ts;
 		unsigned long delay;	/* The delay completed so far */
 
-		ktime_get_ts(&ts);
-		delay = timespec_to_ns(&ts) - ec_spi->last_transfer_ns;
+		delay = ktime_get_ns() - ec_spi->last_transfer_ns;
 		if (delay < EC_SPI_RECOVERY_TIME_NS)
 			ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
 	}
@@ -261,27 +258,22 @@ static int cros_ec_command_spi_xfer(stru
 	/* Get the response */
 	if (!ret) {
 		ret = cros_ec_spi_receive_response(ec_dev,
-				ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
+				ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
 	} else {
 		dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
 	}
 
-	/* turn off CS */
+	/*
+	 * Turn off CS, possibly adding a delay to ensure the rising edge
+	 * doesn't come too soon after the end of the data.
+	 */
 	spi_message_init(&msg);
-
-	if (ec_spi->end_of_msg_delay) {
-		/*
-		 * Add delay for last transaction, to ensure the rising edge
-		 * doesn't come too soon after the end of the data.
-		 */
-		memset(&trans, 0, sizeof(trans));
-		trans.delay_usecs = ec_spi->end_of_msg_delay;
-		spi_message_add_tail(&trans, &msg);
-	}
+	memset(&trans, 0, sizeof(trans));
+	trans.delay_usecs = ec_spi->end_of_msg_delay;
+	spi_message_add_tail(&trans, &msg);
 
 	final_ret = spi_sync(ec_spi->spi, &msg);
-	ktime_get_ts(&ts);
-	ec_spi->last_transfer_ns = timespec_to_ns(&ts);
+	ec_spi->last_transfer_ns = ktime_get_ns();
 	if (!ret)
 		ret = final_ret;
 	if (ret < 0) {
@@ -289,20 +281,19 @@ static int cros_ec_command_spi_xfer(stru
 		goto exit;
 	}
 
-	/* check response error code */
 	ptr = ec_dev->din;
-	if (ptr[0]) {
-		dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
-			 ec_msg->cmd, ptr[0]);
-		debug_packet(ec_dev->dev, "in_err", ptr, len);
-		ret = -EINVAL;
+
+	/* check response error code */
+	ec_msg->result = ptr[0];
+	ret = cros_ec_check_result(ec_dev, ec_msg);
+	if (ret)
 		goto exit;
-	}
+
 	len = ptr[1];
 	sum = ptr[0] + ptr[1];
-	if (len > ec_msg->in_len) {
+	if (len > ec_msg->insize) {
 		dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
-			len, ec_msg->in_len);
+			len, ec_msg->insize);
 		ret = -ENOSPC;
 		goto exit;
 	}
@@ -310,8 +301,8 @@ static int cros_ec_command_spi_xfer(stru
 	/* copy response packet payload and compute checksum */
 	for (i = 0; i < len; i++) {
 		sum += ptr[i + 2];
-		if (ec_msg->in_len)
-			ec_msg->in_buf[i] = ptr[i + 2];
+		if (ec_msg->insize)
+			ec_msg->indata[i] = ptr[i + 2];
 	}
 	sum &= 0xff;
 
@@ -325,7 +316,7 @@ static int cros_ec_command_spi_xfer(stru
 		goto exit;
 	}
 
-	ret = 0;
+	ret = len;
 exit:
 	mutex_unlock(&ec_spi->lock);
 	return ret;
@@ -368,11 +359,10 @@ static int cros_ec_spi_probe(struct spi_
 	cros_ec_spi_dt_probe(ec_spi, dev);
 
 	spi_set_drvdata(spi, ec_dev);
-	ec_dev->name = "SPI";
 	ec_dev->dev = dev;
 	ec_dev->priv = ec_spi;
 	ec_dev->irq = spi->irq;
-	ec_dev->command_xfer = cros_ec_command_spi_xfer;
+	ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
 	ec_dev->ec_name = ec_spi->spi->modalias;
 	ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
 	ec_dev->parent = &ec_spi->spi->dev;
@@ -385,6 +375,8 @@ static int cros_ec_spi_probe(struct spi_
 		return err;
 	}
 
+	device_init_wakeup(&spi->dev, true);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/da9063-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/da9063-core.c
--- linux-libre-3.16-gnu/drivers/mfd/da9063-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/da9063-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -153,9 +153,9 @@ int da9063_device_init(struct da9063 *da
 		 "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
 		 model, variant_id);
 
-	if (variant_code != PMIC_DA9063_BB) {
-		dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
-				variant_code);
+	if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
+		dev_err(da9063->dev,
+			"Cannot support variant code: 0x%02X\n", variant_code);
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/da9063-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/da9063-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/da9063-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/da9063-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,10 +25,10 @@
 #include <linux/mfd/da9063/pdata.h>
 #include <linux/mfd/da9063/registers.h>
 
-static const struct regmap_range da9063_readable_ranges[] = {
+static const struct regmap_range da9063_ad_readable_ranges[] = {
 	{
 		.range_min = DA9063_REG_PAGE_CON,
-		.range_max = DA9063_REG_SECOND_D,
+		.range_max = DA9063_AD_REG_SECOND_D,
 	}, {
 		.range_min = DA9063_REG_SEQ,
 		.range_max = DA9063_REG_ID_32_31,
@@ -37,14 +37,14 @@ static const struct regmap_range da9063_
 		.range_max = DA9063_REG_AUTO3_LOW,
 	}, {
 		.range_min = DA9063_REG_T_OFFSET,
-		.range_max = DA9063_REG_GP_ID_19,
+		.range_max = DA9063_AD_REG_GP_ID_19,
 	}, {
 		.range_min = DA9063_REG_CHIP_ID,
 		.range_max = DA9063_REG_CHIP_VARIANT,
 	},
 };
 
-static const struct regmap_range da9063_writeable_ranges[] = {
+static const struct regmap_range da9063_ad_writeable_ranges[] = {
 	{
 		.range_min = DA9063_REG_PAGE_CON,
 		.range_max = DA9063_REG_PAGE_CON,
@@ -53,7 +53,7 @@ static const struct regmap_range da9063_
 		.range_max = DA9063_REG_VSYS_MON,
 	}, {
 		.range_min = DA9063_REG_COUNT_S,
-		.range_max = DA9063_REG_ALARM_Y,
+		.range_max = DA9063_AD_REG_ALARM_Y,
 	}, {
 		.range_min = DA9063_REG_SEQ,
 		.range_max = DA9063_REG_ID_32_31,
@@ -62,14 +62,14 @@ static const struct regmap_range da9063_
 		.range_max = DA9063_REG_AUTO3_LOW,
 	}, {
 		.range_min = DA9063_REG_CONFIG_I,
-		.range_max = DA9063_REG_MON_REG_4,
+		.range_max = DA9063_AD_REG_MON_REG_4,
 	}, {
-		.range_min = DA9063_REG_GP_ID_0,
-		.range_max = DA9063_REG_GP_ID_19,
+		.range_min = DA9063_AD_REG_GP_ID_0,
+		.range_max = DA9063_AD_REG_GP_ID_19,
 	},
 };
 
-static const struct regmap_range da9063_volatile_ranges[] = {
+static const struct regmap_range da9063_ad_volatile_ranges[] = {
 	{
 		.range_min = DA9063_REG_STATUS_A,
 		.range_max = DA9063_REG_EVENT_D,
@@ -81,26 +81,104 @@ static const struct regmap_range da9063_
 		.range_max = DA9063_REG_ADC_MAN,
 	}, {
 		.range_min = DA9063_REG_ADC_RES_L,
-		.range_max = DA9063_REG_SECOND_D,
+		.range_max = DA9063_AD_REG_SECOND_D,
 	}, {
-		.range_min = DA9063_REG_MON_REG_5,
-		.range_max = DA9063_REG_MON_REG_6,
+		.range_min = DA9063_AD_REG_MON_REG_5,
+		.range_max = DA9063_AD_REG_MON_REG_6,
 	},
 };
 
-static const struct regmap_access_table da9063_readable_table = {
-	.yes_ranges = da9063_readable_ranges,
-	.n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
+static const struct regmap_access_table da9063_ad_readable_table = {
+	.yes_ranges = da9063_ad_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
 };
 
-static const struct regmap_access_table da9063_writeable_table = {
-	.yes_ranges = da9063_writeable_ranges,
-	.n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
+static const struct regmap_access_table da9063_ad_writeable_table = {
+	.yes_ranges = da9063_ad_writeable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
 };
 
-static const struct regmap_access_table da9063_volatile_table = {
-	.yes_ranges = da9063_volatile_ranges,
-	.n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
+static const struct regmap_access_table da9063_ad_volatile_table = {
+	.yes_ranges = da9063_ad_volatile_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
+};
+
+static const struct regmap_range da9063_bb_readable_ranges[] = {
+	{
+		.range_min = DA9063_REG_PAGE_CON,
+		.range_max = DA9063_BB_REG_SECOND_D,
+	}, {
+		.range_min = DA9063_REG_SEQ,
+		.range_max = DA9063_REG_ID_32_31,
+	}, {
+		.range_min = DA9063_REG_SEQ_A,
+		.range_max = DA9063_REG_AUTO3_LOW,
+	}, {
+		.range_min = DA9063_REG_T_OFFSET,
+		.range_max = DA9063_BB_REG_GP_ID_19,
+	}, {
+		.range_min = DA9063_REG_CHIP_ID,
+		.range_max = DA9063_REG_CHIP_VARIANT,
+	},
+};
+
+static const struct regmap_range da9063_bb_writeable_ranges[] = {
+	{
+		.range_min = DA9063_REG_PAGE_CON,
+		.range_max = DA9063_REG_PAGE_CON,
+	}, {
+		.range_min = DA9063_REG_FAULT_LOG,
+		.range_max = DA9063_REG_VSYS_MON,
+	}, {
+		.range_min = DA9063_REG_COUNT_S,
+		.range_max = DA9063_BB_REG_ALARM_Y,
+	}, {
+		.range_min = DA9063_REG_SEQ,
+		.range_max = DA9063_REG_ID_32_31,
+	}, {
+		.range_min = DA9063_REG_SEQ_A,
+		.range_max = DA9063_REG_AUTO3_LOW,
+	}, {
+		.range_min = DA9063_REG_CONFIG_I,
+		.range_max = DA9063_BB_REG_MON_REG_4,
+	}, {
+		.range_min = DA9063_BB_REG_GP_ID_0,
+		.range_max = DA9063_BB_REG_GP_ID_19,
+	},
+};
+
+static const struct regmap_range da9063_bb_volatile_ranges[] = {
+	{
+		.range_min = DA9063_REG_STATUS_A,
+		.range_max = DA9063_REG_EVENT_D,
+	}, {
+		.range_min = DA9063_REG_CONTROL_F,
+		.range_max = DA9063_REG_CONTROL_F,
+	}, {
+		.range_min = DA9063_REG_ADC_MAN,
+		.range_max = DA9063_REG_ADC_MAN,
+	}, {
+		.range_min = DA9063_REG_ADC_RES_L,
+		.range_max = DA9063_BB_REG_SECOND_D,
+	}, {
+		.range_min = DA9063_BB_REG_MON_REG_5,
+		.range_max = DA9063_BB_REG_MON_REG_6,
+	},
+};
+
+static const struct regmap_access_table da9063_bb_readable_table = {
+	.yes_ranges = da9063_bb_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_writeable_table = {
+	.yes_ranges = da9063_bb_writeable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_volatile_table = {
+	.yes_ranges = da9063_bb_volatile_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
 };
 
 static const struct regmap_range_cfg da9063_range_cfg[] = {
@@ -123,10 +201,6 @@ static struct regmap_config da9063_regma
 	.max_register = DA9063_REG_CHIP_VARIANT,
 
 	.cache_type = REGCACHE_RBTREE,
-
-	.rd_table = &da9063_readable_table,
-	.wr_table = &da9063_writeable_table,
-	.volatile_table = &da9063_volatile_table,
 };
 
 static int da9063_i2c_probe(struct i2c_client *i2c,
@@ -143,6 +217,16 @@ static int da9063_i2c_probe(struct i2c_c
 	da9063->dev = &i2c->dev;
 	da9063->chip_irq = i2c->irq;
 
+	if (da9063->variant_code == PMIC_DA9063_AD) {
+		da9063_regmap_config.rd_table = &da9063_ad_readable_table;
+		da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
+		da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
+	} else {
+		da9063_regmap_config.rd_table = &da9063_bb_readable_table;
+		da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
+		da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
+	}
+
 	da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
 	if (IS_ERR(da9063->regmap)) {
 		ret = PTR_ERR(da9063->regmap);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/dm355evm_msp.c linux-libre-3.17-rc7-gnu/drivers/mfd/dm355evm_msp.c
--- linux-libre-3.16-gnu/drivers/mfd/dm355evm_msp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/dm355evm_msp.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(dm355evm_msp_read);
  * Many of the msp430 pins are just used as fixed-direction GPIOs.
  * We could export a few more of them this way, if we wanted.
  */
-#define MSP_GPIO(bit,reg)	((DM355EVM_MSP_ ## reg) << 3 | (bit))
+#define MSP_GPIO(bit, reg)	((DM355EVM_MSP_ ## reg) << 3 | (bit))
 
 static const u8 msp_gpios[] = {
 	/* eight leds */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/ezx-pcap.c linux-libre-3.17-rc7-gnu/drivers/mfd/ezx-pcap.c
--- linux-libre-3.16-gnu/drivers/mfd/ezx-pcap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/ezx-pcap.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@ static int ezx_pcap_putget(struct pcap_c
 	struct spi_message m;
 	int status;
 
-	memset(&t, 0, sizeof t);
+	memset(&t, 0, sizeof(t));
 	spi_message_init(&m);
 	t.len = sizeof(u32);
 	spi_message_add_tail(&t, &m);
@@ -211,7 +211,6 @@ static void pcap_irq_handler(unsigned in
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	queue_work(pcap->workqueue, &pcap->isr_work);
-	return;
 }
 
 /* ADC */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/htc-i2cpld.c linux-libre-3.17-rc7-gnu/drivers/mfd/htc-i2cpld.c
--- linux-libre-3.16-gnu/drivers/mfd/htc-i2cpld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/htc-i2cpld.c	2014-09-28 17:29:07.000000000 -0400
@@ -332,18 +332,13 @@ static int htcpld_setup_chip_irq(
 		int chip_index)
 {
 	struct htcpld_data *htcpld;
-	struct device *dev = &pdev->dev;
-	struct htcpld_core_platform_data *pdata;
 	struct htcpld_chip *chip;
-	struct htcpld_chip_platform_data *plat_chip_data;
 	unsigned int irq, irq_end;
 	int ret = 0;
 
 	/* Get the platform and driver data */
-	pdata = dev_get_platdata(dev);
 	htcpld = platform_get_drvdata(pdev);
 	chip = &htcpld->chip[chip_index];
-	plat_chip_data = &pdata->chip[chip_index];
 
 	/* Setup irq handlers */
 	irq_end = chip->irq_start + chip->nirqs;
@@ -409,7 +404,7 @@ static int htcpld_register_chip_i2c(
 	}
 
 	i2c_set_clientdata(client, chip);
-	snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
+	snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%x", client->addr);
 	chip->client = client;
 
 	/* Reset the chip */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/intel_msic.c linux-libre-3.17-rc7-gnu/drivers/mfd/intel_msic.c
--- linux-libre-3.16-gnu/drivers/mfd/intel_msic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/intel_msic.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,7 +27,7 @@
 
 /*
  * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
- * Since IRQ block starts from address 0x002 we need to substract that from
+ * Since IRQ block starts from address 0x002 we need to subtract that from
  * the actual IRQ status register address.
  */
 #define MSIC_IRQ_STATUS(x)	(INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_core.c linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_core.c
--- linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ * intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+/*
+ * On some boards the PMIC interrupt may come from a GPIO line.
+ * Try to lookup the ACPI table and see if such connection exists. If not,
+ * return -ENOENT and use the IRQ provided by I2C.
+ */
+static int intel_soc_pmic_find_gpio_irq(struct device *dev)
+{
+	struct gpio_desc *desc;
+	int irq;
+
+	desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
+	if (IS_ERR(desc))
+		return -ENOENT;
+
+	irq = gpiod_to_irq(desc);
+	if (irq < 0)
+		dev_warn(dev, "Can't get irq: %d\n", irq);
+
+	return irq;
+}
+
+static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+				    const struct i2c_device_id *i2c_id)
+{
+	struct device *dev = &i2c->dev;
+	const struct acpi_device_id *id;
+	struct intel_soc_pmic_config *config;
+	struct intel_soc_pmic *pmic;
+	int ret;
+	int irq;
+
+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
+	if (!id || !id->driver_data)
+		return -ENODEV;
+
+	config = (struct intel_soc_pmic_config *)id->driver_data;
+
+	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+	dev_set_drvdata(dev, pmic);
+
+	pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
+
+	irq = intel_soc_pmic_find_gpio_irq(dev);
+	pmic->irq = (irq < 0) ? i2c->irq : irq;
+
+	ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+				  config->irq_flags | IRQF_ONESHOT,
+				  0, config->irq_chip,
+				  &pmic->irq_chip_data);
+	if (ret)
+		return ret;
+
+	ret = enable_irq_wake(pmic->irq);
+	if (ret)
+		dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
+
+	ret = mfd_add_devices(dev, -1, config->cell_dev,
+			      config->n_cell_devs, NULL, 0,
+			      regmap_irq_get_domain(pmic->irq_chip_data));
+	if (ret)
+		goto err_del_irq_chip;
+
+	return 0;
+
+err_del_irq_chip:
+	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+	return ret;
+}
+
+static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+
+	mfd_remove_devices(&i2c->dev);
+
+	return 0;
+}
+
+static void intel_soc_pmic_shutdown(struct i2c_client *i2c)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+	disable_irq(pmic->irq);
+
+	return;
+}
+
+static int intel_soc_pmic_suspend(struct device *dev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+	disable_irq(pmic->irq);
+
+	return 0;
+}
+
+static int intel_soc_pmic_resume(struct device *dev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+	enable_irq(pmic->irq);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
+			 intel_soc_pmic_resume);
+
+static const struct i2c_device_id intel_soc_pmic_i2c_id[] = {
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
+
+#if defined(CONFIG_ACPI)
+static struct acpi_device_id intel_soc_pmic_acpi_match[] = {
+	{"INT33FD", (kernel_ulong_t)&intel_soc_pmic_config_crc},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
+#endif
+
+static struct i2c_driver intel_soc_pmic_i2c_driver = {
+	.driver = {
+		.name = "intel_soc_pmic_i2c",
+		.owner = THIS_MODULE,
+		.pm = &intel_soc_pmic_pm_ops,
+		.acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match),
+	},
+	.probe = intel_soc_pmic_i2c_probe,
+	.remove = intel_soc_pmic_i2c_remove,
+	.id_table = intel_soc_pmic_i2c_id,
+	.shutdown = intel_soc_pmic_shutdown,
+};
+
+module_i2c_driver(intel_soc_pmic_i2c_driver);
+
+MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_core.h linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_core.h
--- linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_core.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * intel_soc_pmic_core.h - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#ifndef __INTEL_SOC_PMIC_CORE_H__
+#define __INTEL_SOC_PMIC_CORE_H__
+
+struct intel_soc_pmic_config {
+	unsigned long irq_flags;
+	struct mfd_cell *cell_dev;
+	int n_cell_devs;
+	struct regmap_config *regmap_config;
+	struct regmap_irq_chip *irq_chip;
+};
+
+extern struct intel_soc_pmic_config intel_soc_pmic_config_crc;
+
+#endif	/* __INTEL_SOC_PMIC_CORE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_crc.c linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_crc.c
--- linux-libre-3.16-gnu/drivers/mfd/intel_soc_pmic_crc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/intel_soc_pmic_crc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * intel_soc_pmic_crc.c - Device access for Crystal Cove PMIC
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+#define CRYSTAL_COVE_MAX_REGISTER	0xC6
+
+#define CRYSTAL_COVE_REG_IRQLVL1	0x02
+#define CRYSTAL_COVE_REG_MIRQLVL1	0x0E
+
+#define CRYSTAL_COVE_IRQ_PWRSRC		0
+#define CRYSTAL_COVE_IRQ_THRM		1
+#define CRYSTAL_COVE_IRQ_BCU		2
+#define CRYSTAL_COVE_IRQ_ADC		3
+#define CRYSTAL_COVE_IRQ_CHGR		4
+#define CRYSTAL_COVE_IRQ_GPIO		5
+#define CRYSTAL_COVE_IRQ_VHDMIOCP	6
+
+static struct resource gpio_resources[] = {
+	{
+		.name	= "GPIO",
+		.start	= CRYSTAL_COVE_IRQ_GPIO,
+		.end	= CRYSTAL_COVE_IRQ_GPIO,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource pwrsrc_resources[] = {
+	{
+		.name  = "PWRSRC",
+		.start = CRYSTAL_COVE_IRQ_PWRSRC,
+		.end   = CRYSTAL_COVE_IRQ_PWRSRC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource adc_resources[] = {
+	{
+		.name  = "ADC",
+		.start = CRYSTAL_COVE_IRQ_ADC,
+		.end   = CRYSTAL_COVE_IRQ_ADC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource thermal_resources[] = {
+	{
+		.name  = "THERMAL",
+		.start = CRYSTAL_COVE_IRQ_THRM,
+		.end   = CRYSTAL_COVE_IRQ_THRM,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource bcu_resources[] = {
+	{
+		.name  = "BCU",
+		.start = CRYSTAL_COVE_IRQ_BCU,
+		.end   = CRYSTAL_COVE_IRQ_BCU,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell crystal_cove_dev[] = {
+	{
+		.name = "crystal_cove_pwrsrc",
+		.num_resources = ARRAY_SIZE(pwrsrc_resources),
+		.resources = pwrsrc_resources,
+	},
+	{
+		.name = "crystal_cove_adc",
+		.num_resources = ARRAY_SIZE(adc_resources),
+		.resources = adc_resources,
+	},
+	{
+		.name = "crystal_cove_thermal",
+		.num_resources = ARRAY_SIZE(thermal_resources),
+		.resources = thermal_resources,
+	},
+	{
+		.name = "crystal_cove_bcu",
+		.num_resources = ARRAY_SIZE(bcu_resources),
+		.resources = bcu_resources,
+	},
+	{
+		.name = "crystal_cove_gpio",
+		.num_resources = ARRAY_SIZE(gpio_resources),
+		.resources = gpio_resources,
+	},
+};
+
+static struct regmap_config crystal_cove_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CRYSTAL_COVE_MAX_REGISTER,
+	.cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_irq crystal_cove_irqs[] = {
+	[CRYSTAL_COVE_IRQ_PWRSRC] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_PWRSRC),
+	},
+	[CRYSTAL_COVE_IRQ_THRM] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_THRM),
+	},
+	[CRYSTAL_COVE_IRQ_BCU] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_BCU),
+	},
+	[CRYSTAL_COVE_IRQ_ADC] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_ADC),
+	},
+	[CRYSTAL_COVE_IRQ_CHGR] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_CHGR),
+	},
+	[CRYSTAL_COVE_IRQ_GPIO] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_GPIO),
+	},
+	[CRYSTAL_COVE_IRQ_VHDMIOCP] = {
+		.mask = BIT(CRYSTAL_COVE_IRQ_VHDMIOCP),
+	},
+};
+
+static struct regmap_irq_chip crystal_cove_irq_chip = {
+	.name = "Crystal Cove",
+	.irqs = crystal_cove_irqs,
+	.num_irqs = ARRAY_SIZE(crystal_cove_irqs),
+	.num_regs = 1,
+	.status_base = CRYSTAL_COVE_REG_IRQLVL1,
+	.mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
+};
+
+struct intel_soc_pmic_config intel_soc_pmic_config_crc = {
+	.irq_flags = IRQF_TRIGGER_RISING,
+	.cell_dev = crystal_cove_dev,
+	.n_cell_devs = ARRAY_SIZE(crystal_cove_dev),
+	.regmap_config = &crystal_cove_regmap_config,
+	.irq_chip = &crystal_cove_irq_chip,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/ipaq-micro.c linux-libre-3.17-rc7-gnu/drivers/mfd/ipaq-micro.c
--- linux-libre-3.16-gnu/drivers/mfd/ipaq-micro.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/ipaq-micro.c	2014-09-28 17:29:07.000000000 -0400
@@ -115,7 +115,7 @@ static void micro_rx_msg(struct ipaq_mic
 		} else {
 			dev_err(micro->dev,
 				"out of band RX message 0x%02x\n", id);
-			if(!micro->msg)
+			if (!micro->msg)
 				dev_info(micro->dev, "no message queued\n");
 			else
 				dev_info(micro->dev, "expected message %02x\n",
@@ -126,13 +126,13 @@ static void micro_rx_msg(struct ipaq_mic
 		if (micro->key)
 			micro->key(micro->key_data, len, data);
 		else
-			dev_dbg(micro->dev, "key message ignored, no handle \n");
+			dev_dbg(micro->dev, "key message ignored, no handle\n");
 		break;
 	case MSG_TOUCHSCREEN:
 		if (micro->ts)
 			micro->ts(micro->ts_data, len, data);
 		else
-			dev_dbg(micro->dev, "touchscreen message ignored, no handle \n");
+			dev_dbg(micro->dev, "touchscreen message ignored, no handle\n");
 		break;
 	default:
 		dev_err(micro->dev,
@@ -154,7 +154,7 @@ static void micro_process_char(struct ip
 			rx->state = STATE_ID; /* Next byte is the id and len */
 		break;
 	case STATE_ID: /* Looking for id and len byte */
-		rx->id = (ch & 0xf0) >> 4 ;
+		rx->id = (ch & 0xf0) >> 4;
 		rx->len = (ch & 0x0f);
 		rx->index = 0;
 		rx->chksum = ch;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/Kconfig linux-libre-3.17-rc7-gnu/drivers/mfd/Kconfig
--- linux-libre-3.16-gnu/drivers/mfd/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,7 @@ config MFD_CORE
 config MFD_CS5535
 	tristate "AMD CS5535 and CS5536 southbridge core functions"
 	select MFD_CORE
-	depends on PCI && X86
+	depends on PCI && (X86_32 || (X86 && COMPILE_TEST))
 	---help---
 	  This is the core driver for CS5535/CS5536 MFD functions.  This is
           necessary for using the board's GPIO and MFGPT functionality.
@@ -187,6 +187,7 @@ config MFD_MC13XXX
 	tristate
 	depends on (SPI_MASTER || I2C)
 	select MFD_CORE
+	select REGMAP_IRQ
 	help
 	  Enable support for the Freescale MC13783 and MC13892 PMICs.
 	  This driver provides common support for accessing the device,
@@ -253,6 +254,18 @@ config LPC_SCH
 	  LPC bridge function of the Intel SCH provides support for
 	  System Management Bus and General Purpose I/O.
 
+config INTEL_SOC_PMIC
+	bool "Support for Intel Atom SoC PMIC"
+	depends on I2C=y
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  Select this option to enable support for the PMIC device
+	  on some Intel SoC systems. The PMIC provides ADC, GPIO,
+	  thermal, charger and related power management functions
+	  on these systems.
+
 config MFD_INTEL_MSIC
 	bool "Intel MSIC"
 	depends on INTEL_SCU_IPC
@@ -367,14 +380,15 @@ config MFD_MAX14577
 	  of the device.
 
 config MFD_MAX77686
-	bool "Maxim Semiconductor MAX77686 PMIC Support"
+	bool "Maxim Semiconductor MAX77686/802 PMIC Support"
 	depends on I2C=y
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	select IRQ_DOMAIN
 	help
-	  Say yes here to add support for Maxim Semiconductor MAX77686.
-	  This is a Power Management IC with RTC on chip.
+	  Say yes here to add support for Maxim Semiconductor MAX77686 and
+	  MAX77802 which are Power Management IC with an RTC on chip.
 	  This driver provides common support for accessing the device;
 	  additional drivers must be enabled in order to use the functionality
 	  of the device.
@@ -384,6 +398,7 @@ config MFD_MAX77693
 	depends on I2C=y
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	help
 	  Say yes here to add support for Maxim Semiconductor MAX77693.
 	  This is a companion Power Management IC with Flash, Haptic, Charger,
@@ -573,6 +588,7 @@ config MFD_SEC_CORE
 	select MFD_CORE
 	select REGMAP_I2C
 	select REGMAP_IRQ
+	select REGULATOR
 	help
 	 Support for the Samsung Electronics MFD series.
 	 This driver provides common support for accessing the device,
@@ -1056,7 +1072,7 @@ config MFD_LM3533
 config MFD_TIMBERDALE
 	tristate "Timberdale FPGA"
 	select MFD_CORE
-	depends on PCI && GPIOLIB
+	depends on PCI && GPIOLIB && (X86_32 || COMPILE_TEST)
 	---help---
 	This is the core driver for the timberdale FPGA. This device is a
 	multifunction device which exposes numerous platform devices.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/kempld-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/kempld-core.c
--- linux-libre-3.16-gnu/drivers/mfd/kempld-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/kempld-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,8 @@
 
 #define MAX_ID_LEN 4
 static char force_device_id[MAX_ID_LEN + 1] = "";
-module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
+module_param_string(force_device_id, force_device_id,
+		    sizeof(force_device_id), 0);
 MODULE_PARM_DESC(force_device_id, "Override detected product");
 
 /*
@@ -36,7 +37,7 @@ static void kempld_get_hardware_mutex(st
 {
 	/* The mutex bit will read 1 until access has been granted */
 	while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
-		msleep(1);
+		usleep_range(1000, 3000);
 }
 
 static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
@@ -499,7 +500,7 @@ static struct platform_driver kempld_dri
 	.remove		= kempld_remove,
 };
 
-static struct dmi_system_id __initdata kempld_dmi_table[] = {
+static struct dmi_system_id kempld_dmi_table[] __initdata = {
 	{
 		.ident = "BHL6",
 		.matches = {
@@ -736,7 +737,8 @@ static int __init kempld_init(void)
 	int ret;
 
 	if (force_device_id[0]) {
-		for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
+		for (id = kempld_dmi_table;
+		     id->matches[0].slot != DMI_NONE; id++)
 			if (strstr(id->ident, force_device_id))
 				if (id->callback && id->callback(id))
 					break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/lp8788-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/lp8788-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/lp8788-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/lp8788-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,12 +66,14 @@ static inline u8 _irq_to_val(enum lp8788
 static void lp8788_irq_enable(struct irq_data *data)
 {
 	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
 	irqd->enabled[data->hwirq] = 1;
 }
 
 static void lp8788_irq_disable(struct irq_data *data)
 {
 	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
 	irqd->enabled[data->hwirq] = 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/Makefile linux-libre-3.17-rc7-gnu/drivers/mfd/Makefile
--- linux-libre-3.16-gnu/drivers/mfd/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -115,8 +115,8 @@ da9063-objs			:= da9063-core.o da9063-ir
 obj-$(CONFIG_MFD_DA9063)	+= da9063.o
 
 obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
-obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
-obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
+obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
+obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
 obj-$(CONFIG_MFD_MAX8907)	+= max8907.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
@@ -169,3 +169,6 @@ obj-$(CONFIG_MFD_AS3711)	+= as3711.o
 obj-$(CONFIG_MFD_AS3722)	+= as3722.o
 obj-$(CONFIG_MFD_STW481X)	+= stw481x.o
 obj-$(CONFIG_MFD_IPAQ_MICRO)	+= ipaq-micro.o
+
+intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
+obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max77686.c linux-libre-3.17-rc7-gnu/drivers/mfd/max77686.c
--- linux-libre-3.16-gnu/drivers/mfd/max77686.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max77686.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * max77686.c - mfd core driver for the Maxim 77686
+ * max77686.c - mfd core driver for the Maxim 77686/802
  *
  * Copyright (C) 2012 Samsung Electronics
  * Chiwoong Byun <woong.byun@smasung.com>
@@ -25,6 +25,8 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
 #include <linux/mfd/core.h>
@@ -41,15 +43,166 @@ static const struct mfd_cell max77686_de
 	{ .name = "max77686-clk", },
 };
 
+static const struct mfd_cell max77802_devs[] = {
+	{ .name = "max77802-pmic", },
+	{ .name = "max77802-clk", },
+	{ .name = "max77802-rtc", },
+};
+
+static bool max77802_pmic_is_accessible_reg(struct device *dev,
+					    unsigned int reg)
+{
+	return (reg >= MAX77802_REG_DEVICE_ID && reg < MAX77802_REG_PMIC_END);
+}
+
+static bool max77802_rtc_is_accessible_reg(struct device *dev,
+					   unsigned int reg)
+{
+	return (reg >= MAX77802_RTC_INT && reg < MAX77802_RTC_END);
+}
+
+static bool max77802_is_accessible_reg(struct device *dev, unsigned int reg)
+{
+	return (max77802_pmic_is_accessible_reg(dev, reg) ||
+		max77802_rtc_is_accessible_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	return (reg == MAX77802_REG_INTSRC || reg == MAX77802_REG_INT1 ||
+		reg == MAX77802_REG_INT2);
+}
+
+static bool max77802_rtc_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	return (reg == MAX77802_RTC_INT ||
+		reg == MAX77802_RTC_UPDATE0 ||
+		reg == MAX77802_RTC_UPDATE1);
+}
+
+static bool max77802_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	return (max77802_pmic_is_precious_reg(dev, reg) ||
+		max77802_rtc_is_precious_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return (max77802_is_precious_reg(dev, reg) ||
+		reg == MAX77802_REG_STATUS1 || reg == MAX77802_REG_STATUS2 ||
+		reg == MAX77802_REG_PWRON);
+}
+
+static bool max77802_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return (max77802_rtc_is_precious_reg(dev, reg) ||
+		reg == MAX77802_RTC_SEC ||
+		reg == MAX77802_RTC_MIN ||
+		reg == MAX77802_RTC_HOUR ||
+		reg == MAX77802_RTC_WEEKDAY ||
+		reg == MAX77802_RTC_MONTH ||
+		reg == MAX77802_RTC_YEAR ||
+		reg == MAX77802_RTC_DATE);
+}
+
+static bool max77802_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return (max77802_pmic_is_volatile_reg(dev, reg) ||
+		max77802_rtc_is_volatile_reg(dev, reg));
+}
+
 static struct regmap_config max77686_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 };
 
-#ifdef CONFIG_OF
+static struct regmap_config max77686_rtc_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static struct regmap_config max77802_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.writeable_reg = max77802_is_accessible_reg,
+	.readable_reg = max77802_is_accessible_reg,
+	.precious_reg = max77802_is_precious_reg,
+	.volatile_reg = max77802_is_volatile_reg,
+	.name = "max77802-pmic",
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq max77686_irqs[] = {
+	/* INT1 interrupts */
+	{ .reg_offset = 0, .mask = MAX77686_INT1_PWRONF_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_PWRONR_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_JIGONBF_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_JIGONBR_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_ACOKBF_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_ACOKBR_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_ONKEY1S_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_INT1_MRSTB_MSK, },
+	/* INT2 interrupts */
+	{ .reg_offset = 1, .mask = MAX77686_INT2_140C_MSK, },
+	{ .reg_offset = 1, .mask = MAX77686_INT2_120C_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_irq_chip = {
+	.name			= "max77686-pmic",
+	.status_base		= MAX77686_REG_INT1,
+	.mask_base		= MAX77686_REG_INT1MSK,
+	.num_regs		= 2,
+	.irqs			= max77686_irqs,
+	.num_irqs		= ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq max77686_rtc_irqs[] = {
+	/* RTC interrupts */
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
+	{ .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_rtc_irq_chip = {
+	.name			= "max77686-rtc",
+	.status_base		= MAX77686_RTC_INT,
+	.mask_base		= MAX77686_RTC_INTM,
+	.num_regs		= 1,
+	.irqs			= max77686_rtc_irqs,
+	.num_irqs		= ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct regmap_irq_chip max77802_irq_chip = {
+	.name			= "max77802-pmic",
+	.status_base		= MAX77802_REG_INT1,
+	.mask_base		= MAX77802_REG_INT1MSK,
+	.num_regs		= 2,
+	.irqs			= max77686_irqs, /* same masks as 77686 */
+	.num_irqs		= ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq_chip max77802_rtc_irq_chip = {
+	.name			= "max77802-rtc",
+	.status_base		= MAX77802_RTC_INT,
+	.mask_base		= MAX77802_RTC_INTM,
+	.num_regs		= 1,
+	.irqs			= max77686_rtc_irqs, /* same masks as 77686 */
+	.num_irqs		= ARRAY_SIZE(max77686_rtc_irqs),
+};
+
 static const struct of_device_id max77686_pmic_dt_match[] = {
-	{.compatible = "maxim,max77686", .data = NULL},
-	{},
+	{
+		.compatible = "maxim,max77686",
+		.data = (void *)TYPE_MAX77686,
+	},
+	{
+		.compatible = "maxim,max77802",
+		.data = (void *)TYPE_MAX77802,
+	},
+	{ },
 };
 
 static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
@@ -58,53 +211,74 @@ static struct max77686_platform_data *ma
 	struct max77686_platform_data *pd;
 
 	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		dev_err(dev, "could not allocate memory for pdata\n");
+	if (!pd)
 		return NULL;
-	}
 
 	dev->platform_data = pd;
 	return pd;
 }
-#else
-static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
-								  *dev)
-{
-	return 0;
-}
-#endif
 
 static int max77686_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct max77686_dev *max77686 = NULL;
 	struct max77686_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	const struct of_device_id *match;
 	unsigned int data;
 	int ret = 0;
+	const struct regmap_config *config;
+	const struct regmap_irq_chip *irq_chip;
+	const struct regmap_irq_chip *rtc_irq_chip;
+	struct regmap **rtc_regmap;
+	const struct mfd_cell *cells;
+	int n_devs;
 
-	if (i2c->dev.of_node)
+	if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node && !pdata)
 		pdata = max77686_i2c_parse_dt_pdata(&i2c->dev);
 
 	if (!pdata) {
 		dev_err(&i2c->dev, "No platform data found.\n");
-		return -EIO;
+		return -EINVAL;
 	}
 
 	max77686 = devm_kzalloc(&i2c->dev,
 				sizeof(struct max77686_dev), GFP_KERNEL);
-	if (max77686 == NULL)
+	if (!max77686)
 		return -ENOMEM;
 
+	if (i2c->dev.of_node) {
+		match = of_match_node(max77686_pmic_dt_match, i2c->dev.of_node);
+		if (!match)
+			return -EINVAL;
+
+		max77686->type = (unsigned long)match->data;
+	} else
+		max77686->type = id->driver_data;
+
 	i2c_set_clientdata(i2c, max77686);
 	max77686->dev = &i2c->dev;
 	max77686->i2c = i2c;
-	max77686->type = id->driver_data;
 
 	max77686->wakeup = pdata->wakeup;
-	max77686->irq_gpio = pdata->irq_gpio;
 	max77686->irq = i2c->irq;
 
-	max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config);
+	if (max77686->type == TYPE_MAX77686) {
+		config = &max77686_regmap_config;
+		irq_chip = &max77686_irq_chip;
+		rtc_irq_chip = &max77686_rtc_irq_chip;
+		rtc_regmap = &max77686->rtc_regmap;
+		cells =  max77686_devs;
+		n_devs = ARRAY_SIZE(max77686_devs);
+	} else {
+		config = &max77802_regmap_config;
+		irq_chip = &max77802_irq_chip;
+		rtc_irq_chip = &max77802_rtc_irq_chip;
+		rtc_regmap = &max77686->regmap;
+		cells =  max77802_devs;
+		n_devs = ARRAY_SIZE(max77802_devs);
+	}
+
+	max77686->regmap = devm_regmap_init_i2c(i2c, config);
 	if (IS_ERR(max77686->regmap)) {
 		ret = PTR_ERR(max77686->regmap);
 		dev_err(max77686->dev, "Failed to allocate register map: %d\n",
@@ -112,30 +286,68 @@ static int max77686_i2c_probe(struct i2c
 		return ret;
 	}
 
-	if (regmap_read(max77686->regmap,
-			 MAX77686_REG_DEVICE_ID, &data) < 0) {
+	ret = regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data);
+	if (ret < 0) {
 		dev_err(max77686->dev,
 			"device not found on this channel (this is not an error)\n");
 		return -ENODEV;
-	} else
-		dev_info(max77686->dev, "device found\n");
+	}
 
-	max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
-	if (!max77686->rtc) {
-		dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n");
-		return -ENODEV;
+	if (max77686->type == TYPE_MAX77686) {
+		max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+		if (!max77686->rtc) {
+			dev_err(max77686->dev,
+				"Failed to allocate I2C device for RTC\n");
+			return -ENODEV;
+		}
+		i2c_set_clientdata(max77686->rtc, max77686);
+
+		max77686->rtc_regmap =
+			devm_regmap_init_i2c(max77686->rtc,
+					     &max77686_rtc_regmap_config);
+		if (IS_ERR(max77686->rtc_regmap)) {
+			ret = PTR_ERR(max77686->rtc_regmap);
+			dev_err(max77686->dev,
+				"failed to allocate RTC regmap: %d\n",
+				ret);
+			goto err_unregister_i2c;
+		}
 	}
-	i2c_set_clientdata(max77686->rtc, max77686);
 
-	max77686_irq_init(max77686);
+	ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
+				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+				  IRQF_SHARED, 0, irq_chip,
+				  &max77686->irq_data);
+	if (ret) {
+		dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
+		goto err_unregister_i2c;
+	}
 
-	ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
-			      ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
+	ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
+				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+				  IRQF_SHARED, 0, rtc_irq_chip,
+				  &max77686->rtc_irq_data);
+	if (ret) {
+		dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
+		goto err_del_irqc;
+	}
+
+	ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
 	if (ret < 0) {
-		mfd_remove_devices(max77686->dev);
-		i2c_unregister_device(max77686->rtc);
+		dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
+		goto err_del_rtc_irqc;
 	}
 
+	return 0;
+
+err_del_rtc_irqc:
+	regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+err_del_irqc:
+	regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+err_unregister_i2c:
+	if (max77686->type == TYPE_MAX77686)
+		i2c_unregister_device(max77686->rtc);
+
 	return ret;
 }
 
@@ -144,7 +356,12 @@ static int max77686_i2c_remove(struct i2
 	struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
 
 	mfd_remove_devices(max77686->dev);
-	i2c_unregister_device(max77686->rtc);
+
+	regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+	regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+
+	if (max77686->type == TYPE_MAX77686)
+		i2c_unregister_device(max77686->rtc);
 
 	return 0;
 }
@@ -155,10 +372,50 @@ static const struct i2c_device_id max776
 };
 MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
 
+#ifdef CONFIG_PM_SLEEP
+static int max77686_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(max77686->irq);
+
+	/*
+	 * IRQ must be disabled during suspend because if it happens
+	 * while suspended it will be handled before resuming I2C.
+	 *
+	 * When device is woken up from suspend (e.g. by RTC wake alarm),
+	 * an interrupt occurs before resuming I2C bus controller.
+	 * Interrupt handler tries to read registers but this read
+	 * will fail because I2C is still suspended.
+	 */
+	disable_irq(max77686->irq);
+
+	return 0;
+}
+
+static int max77686_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(max77686->irq);
+
+	enable_irq(max77686->irq);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(max77686_pm, max77686_suspend, max77686_resume);
+
 static struct i2c_driver max77686_i2c_driver = {
 	.driver = {
 		   .name = "max77686",
 		   .owner = THIS_MODULE,
+		   .pm = &max77686_pm,
 		   .of_match_table = of_match_ptr(max77686_pmic_dt_match),
 	},
 	.probe = max77686_i2c_probe,
@@ -179,6 +436,6 @@ static void __exit max77686_i2c_exit(voi
 }
 module_exit(max77686_i2c_exit);
 
-MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver");
+MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver");
 MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max77686-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/max77686-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/max77686-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max77686-irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-/*
- * max77686-irq.c - Interrupt controller support for MAX77686
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Chiwoong Byun <woong.byun@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mfd/max77686.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-enum {
-	MAX77686_DEBUG_IRQ_INFO = 1 << 0,
-	MAX77686_DEBUG_IRQ_MASK = 1 << 1,
-	MAX77686_DEBUG_IRQ_INT = 1 << 2,
-};
-
-static int debug_mask = 0;
-module_param(debug_mask, int, 0);
-MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO  0x2=IRQ_MASK 0x4=IRQ_INI)");
-
-static const u8 max77686_mask_reg[] = {
-	[PMIC_INT1] = MAX77686_REG_INT1MSK,
-	[PMIC_INT2] = MAX77686_REG_INT2MSK,
-	[RTC_INT] = MAX77686_RTC_INTM,
-};
-
-static struct regmap *max77686_get_regmap(struct max77686_dev *max77686,
-				enum max77686_irq_source src)
-{
-	switch (src) {
-	case PMIC_INT1 ... PMIC_INT2:
-		return max77686->regmap;
-	case RTC_INT:
-		return max77686->rtc_regmap;
-	default:
-		return ERR_PTR(-EINVAL);
-	}
-}
-
-struct max77686_irq_data {
-	int mask;
-	enum max77686_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask)		\
-	[(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77686_irq_data max77686_irqs[] = {
-	DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF,	PMIC_INT1, 1 << 0),
-	DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR,	PMIC_INT1, 1 << 1),
-	DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF,	PMIC_INT1, 1 << 2),
-	DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR,	PMIC_INT1, 1 << 3),
-	DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF,	PMIC_INT1, 1 << 4),
-	DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR,	PMIC_INT1, 1 << 5),
-	DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S,	PMIC_INT1, 1 << 6),
-	DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB,		PMIC_INT1, 1 << 7),
-	DECLARE_IRQ(MAX77686_PMICIRQ_140C,		PMIC_INT2, 1 << 0),
-	DECLARE_IRQ(MAX77686_PMICIRQ_120C,		PMIC_INT2, 1 << 1),
-	DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S,		RTC_INT, 1 << 0),
-	DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1,		RTC_INT, 1 << 1),
-	DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2,		RTC_INT, 1 << 2),
-	DECLARE_IRQ(MAX77686_RTCIRQ_SMPL,		RTC_INT, 1 << 3),
-	DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S,		RTC_INT, 1 << 4),
-	DECLARE_IRQ(MAX77686_RTCIRQ_WTSR,		RTC_INT, 1 << 5),
-};
-
-static void max77686_irq_lock(struct irq_data *data)
-{
-	struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-
-	if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
-		pr_info("%s\n", __func__);
-
-	mutex_lock(&max77686->irqlock);
-}
-
-static void max77686_irq_sync_unlock(struct irq_data *data)
-{
-	struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-	int i;
-
-	for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
-		u8 mask_reg = max77686_mask_reg[i];
-		struct regmap *map = max77686_get_regmap(max77686, i);
-
-		if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
-			pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n",
-			__func__, i, mask_reg, max77686->irq_masks_cur[i]);
-
-		if (mask_reg == MAX77686_REG_INVALID ||
-				IS_ERR_OR_NULL(map))
-			continue;
-
-		max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i];
-
-		regmap_write(map, max77686_mask_reg[i],
-				max77686->irq_masks_cur[i]);
-	}
-
-	mutex_unlock(&max77686->irqlock);
-}
-
-static const inline struct max77686_irq_data *to_max77686_irq(int irq)
-{
-	struct irq_data *data = irq_get_irq_data(irq);
-	return &max77686_irqs[data->hwirq];
-}
-
-static void max77686_irq_mask(struct irq_data *data)
-{
-	struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-	const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
-	max77686->irq_masks_cur[irq_data->group] |= irq_data->mask;
-
-	if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
-		pr_info("%s: group=%d, cur=0x%x\n",
-			__func__, irq_data->group,
-			max77686->irq_masks_cur[irq_data->group]);
-}
-
-static void max77686_irq_unmask(struct irq_data *data)
-{
-	struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-	const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
-	max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-
-	if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
-		pr_info("%s: group=%d, cur=0x%x\n",
-			__func__, irq_data->group,
-			max77686->irq_masks_cur[irq_data->group]);
-}
-
-static struct irq_chip max77686_irq_chip = {
-	.name			= "max77686",
-	.irq_bus_lock		= max77686_irq_lock,
-	.irq_bus_sync_unlock	= max77686_irq_sync_unlock,
-	.irq_mask		= max77686_irq_mask,
-	.irq_unmask		= max77686_irq_unmask,
-};
-
-static irqreturn_t max77686_irq_thread(int irq, void *data)
-{
-	struct max77686_dev *max77686 = data;
-	unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {};
-	unsigned int irq_src;
-	int ret;
-	int i, cur_irq;
-
-	ret = regmap_read(max77686->regmap,  MAX77686_REG_INTSRC, &irq_src);
-	if (ret < 0) {
-		dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
-				ret);
-		return IRQ_NONE;
-	}
-
-	if (debug_mask & MAX77686_DEBUG_IRQ_INT)
-		pr_info("%s: irq_src=0x%x\n", __func__, irq_src);
-
-	if (irq_src == MAX77686_IRQSRC_PMIC) {
-		ret = regmap_bulk_read(max77686->regmap,
-					 MAX77686_REG_INT1, irq_reg, 2);
-		if (ret < 0) {
-			dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
-					ret);
-			return IRQ_NONE;
-		}
-
-		if (debug_mask & MAX77686_DEBUG_IRQ_INT)
-			pr_info("%s: int1=0x%x, int2=0x%x\n", __func__,
-				 irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]);
-	}
-
-	if (irq_src & MAX77686_IRQSRC_RTC) {
-		ret = regmap_read(max77686->rtc_regmap,
-					MAX77686_RTC_INT, &irq_reg[RTC_INT]);
-		if (ret < 0) {
-			dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
-					ret);
-			return IRQ_NONE;
-		}
-
-		if (debug_mask & MAX77686_DEBUG_IRQ_INT)
-			pr_info("%s: rtc int=0x%x\n", __func__,
-							 irq_reg[RTC_INT]);
-
-	}
-
-	for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++)
-		irq_reg[i] &= ~max77686->irq_masks_cur[i];
-
-	for (i = 0; i < MAX77686_IRQ_NR; i++) {
-		if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) {
-			cur_irq = irq_find_mapping(max77686->irq_domain, i);
-			if (cur_irq)
-				handle_nested_irq(cur_irq);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq,
-					irq_hw_number_t hw)
-{
-	struct max77686_dev *max77686 = d->host_data;
-
-	irq_set_chip_data(irq, max77686);
-	irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-	return 0;
-}
-
-static struct irq_domain_ops max77686_irq_domain_ops = {
-	.map = max77686_irq_domain_map,
-};
-
-int max77686_irq_init(struct max77686_dev *max77686)
-{
-	struct irq_domain *domain;
-	int i;
-	int ret;
-	int val;
-	struct regmap *map;
-
-	mutex_init(&max77686->irqlock);
-
-	if (max77686->irq_gpio && !max77686->irq) {
-		max77686->irq = gpio_to_irq(max77686->irq_gpio);
-
-		if (debug_mask & MAX77686_DEBUG_IRQ_INT) {
-			ret = gpio_request(max77686->irq_gpio, "pmic_irq");
-			if (ret < 0) {
-				dev_err(max77686->dev,
-					"Failed to request gpio %d with ret:"
-					"%d\n",	max77686->irq_gpio, ret);
-				return IRQ_NONE;
-			}
-
-			gpio_direction_input(max77686->irq_gpio);
-			val = gpio_get_value(max77686->irq_gpio);
-			gpio_free(max77686->irq_gpio);
-			pr_info("%s: gpio_irq=%x\n", __func__, val);
-		}
-	}
-
-	if (!max77686->irq) {
-		dev_err(max77686->dev, "irq is not specified\n");
-		return -ENODEV;
-	}
-
-	/* Mask individual interrupt sources */
-	for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
-		max77686->irq_masks_cur[i] = 0xff;
-		max77686->irq_masks_cache[i] = 0xff;
-		map = max77686_get_regmap(max77686, i);
-
-		if (IS_ERR_OR_NULL(map))
-			continue;
-		if (max77686_mask_reg[i] == MAX77686_REG_INVALID)
-			continue;
-
-		regmap_write(map, max77686_mask_reg[i], 0xff);
-	}
-	domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR,
-					&max77686_irq_domain_ops, max77686);
-	if (!domain) {
-		dev_err(max77686->dev, "could not create irq domain\n");
-		return -ENODEV;
-	}
-	max77686->irq_domain = domain;
-
-	ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread,
-				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				   "max77686-irq", max77686);
-
-	if (ret)
-		dev_err(max77686->dev, "Failed to request IRQ %d: %d\n",
-			max77686->irq, ret);
-
-
-	if (debug_mask & MAX77686_DEBUG_IRQ_INFO)
-		pr_info("%s-\n", __func__);
-
-	return 0;
-}
-
-void max77686_irq_exit(struct max77686_dev *max77686)
-{
-	if (max77686->irq)
-		free_irq(max77686->irq, max77686);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max77693.c linux-libre-3.17-rc7-gnu/drivers/mfd/max77693.c
--- linux-libre-3.16-gnu/drivers/mfd/max77693.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max77693.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,62 +49,62 @@ static const struct mfd_cell max77693_de
 	{ .name = "max77693-haptic", },
 };
 
-int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest)
-{
-	unsigned int val;
-	int ret;
-
-	ret = regmap_read(map, reg, &val);
-	*dest = val;
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_read_reg);
-
-int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf)
-{
-	int ret;
-
-	ret = regmap_bulk_read(map, reg, buf, count);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_bulk_read);
-
-int max77693_write_reg(struct regmap *map, u8 reg, u8 value)
-{
-	int ret;
-
-	ret = regmap_write(map, reg, value);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_write_reg);
-
-int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf)
-{
-	int ret;
+static const struct regmap_config max77693_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX77693_PMIC_REG_END,
+};
 
-	ret = regmap_bulk_write(map, reg, buf, count);
+static const struct regmap_irq max77693_led_irqs[] = {
+	{ .mask = LED_IRQ_FLED2_OPEN,  },
+	{ .mask = LED_IRQ_FLED2_SHORT, },
+	{ .mask = LED_IRQ_FLED1_OPEN,  },
+	{ .mask = LED_IRQ_FLED1_SHORT, },
+	{ .mask = LED_IRQ_MAX_FLASH,   },
+};
 
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_bulk_write);
+static const struct regmap_irq_chip max77693_led_irq_chip = {
+	.name			= "max77693-led",
+	.status_base		= MAX77693_LED_REG_FLASH_INT,
+	.mask_base		= MAX77693_LED_REG_FLASH_INT_MASK,
+	.mask_invert		= false,
+	.num_regs		= 1,
+	.irqs			= max77693_led_irqs,
+	.num_irqs		= ARRAY_SIZE(max77693_led_irqs),
+};
 
-int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask)
-{
-	int ret;
+static const struct regmap_irq max77693_topsys_irqs[] = {
+	{ .mask = TOPSYS_IRQ_T120C_INT,  },
+	{ .mask = TOPSYS_IRQ_T140C_INT,  },
+	{ .mask = TOPSYS_IRQ_LOWSYS_INT, },
+};
 
-	ret = regmap_update_bits(map, reg, mask, val);
+static const struct regmap_irq_chip max77693_topsys_irq_chip = {
+	.name			= "max77693-topsys",
+	.status_base		= MAX77693_PMIC_REG_TOPSYS_INT,
+	.mask_base		= MAX77693_PMIC_REG_TOPSYS_INT_MASK,
+	.mask_invert		= false,
+	.num_regs		= 1,
+	.irqs			= max77693_topsys_irqs,
+	.num_irqs		= ARRAY_SIZE(max77693_topsys_irqs),
+};
 
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_update_reg);
+static const struct regmap_irq max77693_charger_irqs[] = {
+	{ .mask = CHG_IRQ_BYP_I,   },
+	{ .mask = CHG_IRQ_THM_I,   },
+	{ .mask = CHG_IRQ_BAT_I,   },
+	{ .mask = CHG_IRQ_CHG_I,   },
+	{ .mask = CHG_IRQ_CHGIN_I, },
+};
 
-static const struct regmap_config max77693_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = MAX77693_PMIC_REG_END,
+static const struct regmap_irq_chip max77693_charger_irq_chip = {
+	.name			= "max77693-charger",
+	.status_base		= MAX77693_CHG_REG_CHG_INT,
+	.mask_base		= MAX77693_CHG_REG_CHG_INT_MASK,
+	.mask_invert		= false,
+	.num_regs		= 1,
+	.irqs			= max77693_charger_irqs,
+	.num_irqs		= ARRAY_SIZE(max77693_charger_irqs),
 };
 
 static const struct regmap_config max77693_regmap_muic_config = {
@@ -113,11 +113,42 @@ static const struct regmap_config max776
 	.max_register = MAX77693_MUIC_REG_END,
 };
 
+static const struct regmap_irq max77693_muic_irqs[] = {
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC,		},
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW,	},
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR,	},
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K,		},
+
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP,	},
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN,	},
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR,	},
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP,		},
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT,	},
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM,		},
+
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC,		},
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC,		},
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP,		},
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR,	},
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED,	},
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET,	},
+};
+
+static const struct regmap_irq_chip max77693_muic_irq_chip = {
+	.name			= "max77693-muic",
+	.status_base		= MAX77693_MUIC_REG_INT1,
+	.mask_base		= MAX77693_MUIC_REG_INTMASK1,
+	.mask_invert		= true,
+	.num_regs		= 3,
+	.irqs			= max77693_muic_irqs,
+	.num_irqs		= ARRAY_SIZE(max77693_muic_irqs),
+};
+
 static int max77693_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct max77693_dev *max77693;
-	u8 reg_data;
+	unsigned int reg_data;
 	int ret = 0;
 
 	max77693 = devm_kzalloc(&i2c->dev,
@@ -139,7 +170,7 @@ static int max77693_i2c_probe(struct i2c
 		return ret;
 	}
 
-	ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
+	ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
 				&reg_data);
 	if (ret < 0) {
 		dev_err(max77693->dev, "device not found on this channel\n");
@@ -176,9 +207,45 @@ static int max77693_i2c_probe(struct i2c
 		goto err_regmap_muic;
 	}
 
-	ret = max77693_irq_init(max77693);
-	if (ret < 0)
-		goto err_irq;
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_led_irq_chip,
+				&max77693->irq_data_led);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_regmap_muic;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_topsys_irq_chip,
+				&max77693->irq_data_topsys);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_topsys;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_charger_irq_chip,
+				&max77693->irq_data_charger);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_charger;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_muic_irq_chip,
+				&max77693->irq_data_muic);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_muic;
+	}
 
 	pm_runtime_set_active(max77693->dev);
 
@@ -190,8 +257,14 @@ static int max77693_i2c_probe(struct i2c
 	return ret;
 
 err_mfd:
-	max77693_irq_exit(max77693);
-err_irq:
+	mfd_remove_devices(max77693->dev);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+err_irq_muic:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+err_irq_charger:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+err_irq_topsys:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
 err_regmap_muic:
 	i2c_unregister_device(max77693->haptic);
 err_i2c_haptic:
@@ -204,7 +277,12 @@ static int max77693_i2c_remove(struct i2
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
 	mfd_remove_devices(max77693->dev);
-	max77693_irq_exit(max77693);
+
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
+
 	i2c_unregister_device(max77693->muic);
 	i2c_unregister_device(max77693->haptic);
 
@@ -222,8 +300,11 @@ static int max77693_suspend(struct devic
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max77693->irq, 1);
+	if (device_may_wakeup(dev)) {
+		enable_irq_wake(max77693->irq);
+		disable_irq(max77693->irq);
+	}
+
 	return 0;
 }
 
@@ -232,9 +313,12 @@ static int max77693_resume(struct device
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max77693->irq, 0);
-	return max77693_irq_resume(max77693);
+	if (device_may_wakeup(dev)) {
+		disable_irq_wake(max77693->irq);
+		enable_irq(max77693->irq);
+	}
+
+	return 0;
 }
 
 static const struct dev_pm_ops max77693_pm = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max77693-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/max77693-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/max77693-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max77693-irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,336 +0,0 @@
-/*
- * max77693-irq.c - Interrupt controller support for MAX77693
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * SangYoung Son <hello.son@samsung.com>
- *
- * This program is not provided / owned by Maxim Integrated Products.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/irqdomain.h>
-#include <linux/mfd/max77693.h>
-#include <linux/mfd/max77693-private.h>
-
-static const u8 max77693_mask_reg[] = {
-	[LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK,
-	[TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
-	[CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK,
-	[MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1,
-	[MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2,
-	[MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3,
-};
-
-static struct regmap *max77693_get_regmap(struct max77693_dev *max77693,
-				enum max77693_irq_source src)
-{
-	switch (src) {
-	case LED_INT ... CHG_INT:
-		return max77693->regmap;
-	case MUIC_INT1 ... MUIC_INT3:
-		return max77693->regmap_muic;
-	default:
-		return ERR_PTR(-EINVAL);
-	}
-}
-
-struct max77693_irq_data {
-	int mask;
-	enum max77693_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask)		\
-	[(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77693_irq_data max77693_irqs[] = {
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN,	LED_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT,	LED_INT, 1 << 1),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN,	LED_INT, 1 << 2),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT,	LED_INT, 1 << 3),
-	DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH,		LED_INT, 1 << 4),
-
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT,	TOPSYS_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT,	TOPSYS_INT, 1 << 1),
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT,	TOPSYS_INT, 1 << 3),
-
-	DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I,		CHG_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I,		CHG_INT, 1 << 2),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I,		CHG_INT, 1 << 3),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I,		CHG_INT, 1 << 4),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I,		CHG_INT, 1 << 6),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC,		MUIC_INT1, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW,	MUIC_INT1, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR,	MUIC_INT1, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K,	MUIC_INT1, 1 << 3),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP,	MUIC_INT2, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN,	MUIC_INT2, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR,	MUIC_INT2, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP,	MUIC_INT2, 1 << 3),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT,	MUIC_INT2, 1 << 4),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM,	MUIC_INT2, 1 << 5),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC,		MUIC_INT3, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC,	MUIC_INT3, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP,		MUIC_INT3, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR,	MUIC_INT3, 1 << 3),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED,	MUIC_INT3, 1 << 4),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET,	MUIC_INT3, 1 << 5),
-};
-
-static void max77693_irq_lock(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-
-	mutex_lock(&max77693->irqlock);
-}
-
-static void max77693_irq_sync_unlock(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	int i;
-
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		u8 mask_reg = max77693_mask_reg[i];
-		struct regmap *map = max77693_get_regmap(max77693, i);
-
-		if (mask_reg == MAX77693_REG_INVALID ||
-				IS_ERR_OR_NULL(map))
-			continue;
-		max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i];
-
-		max77693_write_reg(map, max77693_mask_reg[i],
-				max77693->irq_masks_cur[i]);
-	}
-
-	mutex_unlock(&max77693->irqlock);
-}
-
-static const inline struct max77693_irq_data *
-irq_to_max77693_irq(struct max77693_dev *max77693, int irq)
-{
-	struct irq_data *data = irq_get_irq_data(irq);
-	return &max77693_irqs[data->hwirq];
-}
-
-static void max77693_irq_mask(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	const struct max77693_irq_data *irq_data =
-				irq_to_max77693_irq(max77693, data->irq);
-
-	if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
-		return;
-
-	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
-		max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-	else
-		max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
-}
-
-static void max77693_irq_unmask(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	const struct max77693_irq_data *irq_data =
-	    irq_to_max77693_irq(max77693, data->irq);
-
-	if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
-		return;
-
-	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
-		max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
-	else
-		max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-}
-
-static struct irq_chip max77693_irq_chip = {
-	.name			= "max77693",
-	.irq_bus_lock		= max77693_irq_lock,
-	.irq_bus_sync_unlock	= max77693_irq_sync_unlock,
-	.irq_mask		= max77693_irq_mask,
-	.irq_unmask		= max77693_irq_unmask,
-};
-
-#define MAX77693_IRQSRC_CHG		(1 << 0)
-#define MAX77693_IRQSRC_TOP		(1 << 1)
-#define MAX77693_IRQSRC_FLASH		(1 << 2)
-#define MAX77693_IRQSRC_MUIC		(1 << 3)
-static irqreturn_t max77693_irq_thread(int irq, void *data)
-{
-	struct max77693_dev *max77693 = data;
-	u8 irq_reg[MAX77693_IRQ_GROUP_NR] = {};
-	u8 irq_src;
-	int ret;
-	int i, cur_irq;
-
-	ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_INTSRC,
-				&irq_src);
-	if (ret < 0) {
-		dev_err(max77693->dev, "Failed to read interrupt source: %d\n",
-				ret);
-		return IRQ_NONE;
-	}
-
-	if (irq_src & MAX77693_IRQSRC_CHG)
-		/* CHG_INT */
-		ret = max77693_read_reg(max77693->regmap, MAX77693_CHG_REG_CHG_INT,
-				&irq_reg[CHG_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_TOP)
-		/* TOPSYS_INT */
-		ret = max77693_read_reg(max77693->regmap,
-			MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_FLASH)
-		/* LED_INT */
-		ret = max77693_read_reg(max77693->regmap,
-			MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_MUIC)
-		/* MUIC INT1 ~ INT3 */
-		max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
-			MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);
-
-	/* Apply masking */
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		if (i >= MUIC_INT1 && i <= MUIC_INT3)
-			irq_reg[i] &= max77693->irq_masks_cur[i];
-		else
-			irq_reg[i] &= ~max77693->irq_masks_cur[i];
-	}
-
-	/* Report */
-	for (i = 0; i < MAX77693_IRQ_NR; i++) {
-		if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) {
-			cur_irq = irq_find_mapping(max77693->irq_domain, i);
-			if (cur_irq)
-				handle_nested_irq(cur_irq);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-int max77693_irq_resume(struct max77693_dev *max77693)
-{
-	if (max77693->irq)
-		max77693_irq_thread(0, max77693);
-
-	return 0;
-}
-
-static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq,
-				irq_hw_number_t hw)
-{
-	struct max77693_dev *max77693 = d->host_data;
-
-	irq_set_chip_data(irq, max77693);
-	irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-	return 0;
-}
-
-static struct irq_domain_ops max77693_irq_domain_ops = {
-	.map = max77693_irq_domain_map,
-};
-
-int max77693_irq_init(struct max77693_dev *max77693)
-{
-	struct irq_domain *domain;
-	int i;
-	int ret = 0;
-	u8 intsrc_mask;
-
-	mutex_init(&max77693->irqlock);
-
-	/* Mask individual interrupt sources */
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		struct regmap *map;
-		/* MUIC IRQ  0:MASK 1:NOT MASK */
-		/* Other IRQ 1:MASK 0:NOT MASK */
-		if (i >= MUIC_INT1 && i <= MUIC_INT3) {
-			max77693->irq_masks_cur[i] = 0x00;
-			max77693->irq_masks_cache[i] = 0x00;
-		} else {
-			max77693->irq_masks_cur[i] = 0xff;
-			max77693->irq_masks_cache[i] = 0xff;
-		}
-		map = max77693_get_regmap(max77693, i);
-
-		if (IS_ERR_OR_NULL(map))
-			continue;
-		if (max77693_mask_reg[i] == MAX77693_REG_INVALID)
-			continue;
-		if (i >= MUIC_INT1 && i <= MUIC_INT3)
-			max77693_write_reg(map, max77693_mask_reg[i], 0x00);
-		else
-			max77693_write_reg(map, max77693_mask_reg[i], 0xff);
-	}
-
-	domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR,
-					&max77693_irq_domain_ops, max77693);
-	if (!domain) {
-		dev_err(max77693->dev, "could not create irq domain\n");
-		ret = -ENODEV;
-		goto err_irq;
-	}
-	max77693->irq_domain = domain;
-
-	/* Unmask max77693 interrupt */
-	ret = max77693_read_reg(max77693->regmap,
-			MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
-	if (ret < 0) {
-		dev_err(max77693->dev, "fail to read PMIC register\n");
-		goto err_irq;
-	}
-
-	intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
-	intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
-	intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
-	ret = max77693_write_reg(max77693->regmap,
-			MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
-	if (ret < 0) {
-		dev_err(max77693->dev, "fail to write PMIC register\n");
-		goto err_irq;
-	}
-
-	ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
-				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				   "max77693-irq", max77693);
-	if (ret)
-		dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
-			max77693->irq, ret);
-
-err_irq:
-	return ret;
-}
-
-void max77693_irq_exit(struct max77693_dev *max77693)
-{
-	if (max77693->irq)
-		free_irq(max77693->irq, max77693);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max8925-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/max8925-core.c
--- linux-libre-3.16-gnu/drivers/mfd/max8925-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max8925-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -624,6 +624,7 @@ static void max8925_irq_sync_unlock(stru
 static void max8925_irq_enable(struct irq_data *data)
 {
 	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
 	max8925_irqs[data->irq - chip->irq_base].enable
 		= max8925_irqs[data->irq - chip->irq_base].offs;
 }
@@ -631,6 +632,7 @@ static void max8925_irq_enable(struct ir
 static void max8925_irq_disable(struct irq_data *data)
 {
 	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
 	max8925_irqs[data->irq - chip->irq_base].enable = 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/max8925-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/max8925-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/max8925-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/max8925-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -257,9 +257,11 @@ static struct i2c_driver max8925_driver
 static int __init max8925_i2c_init(void)
 {
 	int ret;
+
 	ret = i2c_add_driver(&max8925_driver);
 	if (ret != 0)
 		pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
+
 	return ret;
 }
 subsys_initcall(max8925_i2c_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/mc13xxx-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/mc13xxx-core.c
--- linux-libre-3.16-gnu/drivers/mfd/mc13xxx-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/mc13xxx-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,106 +10,18 @@
  * Free Software Foundation.
  */
 
-#include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/mc13xxx.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 
 #include "mc13xxx.h"
 
 #define MC13XXX_IRQSTAT0	0
-#define MC13XXX_IRQSTAT0_ADCDONEI	(1 << 0)
-#define MC13XXX_IRQSTAT0_ADCBISDONEI	(1 << 1)
-#define MC13XXX_IRQSTAT0_TSI		(1 << 2)
-#define MC13783_IRQSTAT0_WHIGHI		(1 << 3)
-#define MC13783_IRQSTAT0_WLOWI		(1 << 4)
-#define MC13XXX_IRQSTAT0_CHGDETI	(1 << 6)
-#define MC13783_IRQSTAT0_CHGOVI		(1 << 7)
-#define MC13XXX_IRQSTAT0_CHGREVI	(1 << 8)
-#define MC13XXX_IRQSTAT0_CHGSHORTI	(1 << 9)
-#define MC13XXX_IRQSTAT0_CCCVI		(1 << 10)
-#define MC13XXX_IRQSTAT0_CHGCURRI	(1 << 11)
-#define MC13XXX_IRQSTAT0_BPONI		(1 << 12)
-#define MC13XXX_IRQSTAT0_LOBATLI	(1 << 13)
-#define MC13XXX_IRQSTAT0_LOBATHI	(1 << 14)
-#define MC13783_IRQSTAT0_UDPI		(1 << 15)
-#define MC13783_IRQSTAT0_USBI		(1 << 16)
-#define MC13783_IRQSTAT0_IDI		(1 << 19)
-#define MC13783_IRQSTAT0_SE1I		(1 << 21)
-#define MC13783_IRQSTAT0_CKDETI		(1 << 22)
-#define MC13783_IRQSTAT0_UDMI		(1 << 23)
-
 #define MC13XXX_IRQMASK0	1
-#define MC13XXX_IRQMASK0_ADCDONEM	MC13XXX_IRQSTAT0_ADCDONEI
-#define MC13XXX_IRQMASK0_ADCBISDONEM	MC13XXX_IRQSTAT0_ADCBISDONEI
-#define MC13XXX_IRQMASK0_TSM		MC13XXX_IRQSTAT0_TSI
-#define MC13783_IRQMASK0_WHIGHM		MC13783_IRQSTAT0_WHIGHI
-#define MC13783_IRQMASK0_WLOWM		MC13783_IRQSTAT0_WLOWI
-#define MC13XXX_IRQMASK0_CHGDETM	MC13XXX_IRQSTAT0_CHGDETI
-#define MC13783_IRQMASK0_CHGOVM		MC13783_IRQSTAT0_CHGOVI
-#define MC13XXX_IRQMASK0_CHGREVM	MC13XXX_IRQSTAT0_CHGREVI
-#define MC13XXX_IRQMASK0_CHGSHORTM	MC13XXX_IRQSTAT0_CHGSHORTI
-#define MC13XXX_IRQMASK0_CCCVM		MC13XXX_IRQSTAT0_CCCVI
-#define MC13XXX_IRQMASK0_CHGCURRM	MC13XXX_IRQSTAT0_CHGCURRI
-#define MC13XXX_IRQMASK0_BPONM		MC13XXX_IRQSTAT0_BPONI
-#define MC13XXX_IRQMASK0_LOBATLM	MC13XXX_IRQSTAT0_LOBATLI
-#define MC13XXX_IRQMASK0_LOBATHM	MC13XXX_IRQSTAT0_LOBATHI
-#define MC13783_IRQMASK0_UDPM		MC13783_IRQSTAT0_UDPI
-#define MC13783_IRQMASK0_USBM		MC13783_IRQSTAT0_USBI
-#define MC13783_IRQMASK0_IDM		MC13783_IRQSTAT0_IDI
-#define MC13783_IRQMASK0_SE1M		MC13783_IRQSTAT0_SE1I
-#define MC13783_IRQMASK0_CKDETM		MC13783_IRQSTAT0_CKDETI
-#define MC13783_IRQMASK0_UDMM		MC13783_IRQSTAT0_UDMI
-
 #define MC13XXX_IRQSTAT1	3
-#define MC13XXX_IRQSTAT1_1HZI		(1 << 0)
-#define MC13XXX_IRQSTAT1_TODAI		(1 << 1)
-#define MC13783_IRQSTAT1_ONOFD1I	(1 << 3)
-#define MC13783_IRQSTAT1_ONOFD2I	(1 << 4)
-#define MC13783_IRQSTAT1_ONOFD3I	(1 << 5)
-#define MC13XXX_IRQSTAT1_SYSRSTI	(1 << 6)
-#define MC13XXX_IRQSTAT1_RTCRSTI	(1 << 7)
-#define MC13XXX_IRQSTAT1_PCI		(1 << 8)
-#define MC13XXX_IRQSTAT1_WARMI		(1 << 9)
-#define MC13XXX_IRQSTAT1_MEMHLDI	(1 << 10)
-#define MC13783_IRQSTAT1_PWRRDYI	(1 << 11)
-#define MC13XXX_IRQSTAT1_THWARNLI	(1 << 12)
-#define MC13XXX_IRQSTAT1_THWARNHI	(1 << 13)
-#define MC13XXX_IRQSTAT1_CLKI		(1 << 14)
-#define MC13783_IRQSTAT1_SEMAFI		(1 << 15)
-#define MC13783_IRQSTAT1_MC2BI		(1 << 17)
-#define MC13783_IRQSTAT1_HSDETI		(1 << 18)
-#define MC13783_IRQSTAT1_HSLI		(1 << 19)
-#define MC13783_IRQSTAT1_ALSPTHI	(1 << 20)
-#define MC13783_IRQSTAT1_AHSSHORTI	(1 << 21)
-
 #define MC13XXX_IRQMASK1	4
-#define MC13XXX_IRQMASK1_1HZM		MC13XXX_IRQSTAT1_1HZI
-#define MC13XXX_IRQMASK1_TODAM		MC13XXX_IRQSTAT1_TODAI
-#define MC13783_IRQMASK1_ONOFD1M	MC13783_IRQSTAT1_ONOFD1I
-#define MC13783_IRQMASK1_ONOFD2M	MC13783_IRQSTAT1_ONOFD2I
-#define MC13783_IRQMASK1_ONOFD3M	MC13783_IRQSTAT1_ONOFD3I
-#define MC13XXX_IRQMASK1_SYSRSTM	MC13XXX_IRQSTAT1_SYSRSTI
-#define MC13XXX_IRQMASK1_RTCRSTM	MC13XXX_IRQSTAT1_RTCRSTI
-#define MC13XXX_IRQMASK1_PCM		MC13XXX_IRQSTAT1_PCI
-#define MC13XXX_IRQMASK1_WARMM		MC13XXX_IRQSTAT1_WARMI
-#define MC13XXX_IRQMASK1_MEMHLDM	MC13XXX_IRQSTAT1_MEMHLDI
-#define MC13783_IRQMASK1_PWRRDYM	MC13783_IRQSTAT1_PWRRDYI
-#define MC13XXX_IRQMASK1_THWARNLM	MC13XXX_IRQSTAT1_THWARNLI
-#define MC13XXX_IRQMASK1_THWARNHM	MC13XXX_IRQSTAT1_THWARNHI
-#define MC13XXX_IRQMASK1_CLKM		MC13XXX_IRQSTAT1_CLKI
-#define MC13783_IRQMASK1_SEMAFM		MC13783_IRQSTAT1_SEMAFI
-#define MC13783_IRQMASK1_MC2BM		MC13783_IRQSTAT1_MC2BI
-#define MC13783_IRQMASK1_HSDETM		MC13783_IRQSTAT1_HSDETI
-#define MC13783_IRQMASK1_HSLM		MC13783_IRQSTAT1_HSLI
-#define MC13783_IRQMASK1_ALSPTHM	MC13783_IRQSTAT1_ALSPTHI
-#define MC13783_IRQMASK1_AHSSHORTM	MC13783_IRQSTAT1_AHSSHORTI
 
 #define MC13XXX_REVISION	7
 #define MC13XXX_REVISION_REVMETAL	(0x07 <<  0)
@@ -189,45 +101,21 @@ EXPORT_SYMBOL(mc13xxx_reg_rmw);
 
 int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq)
 {
-	int ret;
-	unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
-	u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
-	u32 mask;
-
-	if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
-		return -EINVAL;
-
-	ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
-	if (ret)
-		return ret;
+	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
 
-	if (mask & irqbit)
-		/* already masked */
-		return 0;
+	disable_irq_nosync(virq);
 
-	return mc13xxx_reg_write(mc13xxx, offmask, mask | irqbit);
+	return 0;
 }
 EXPORT_SYMBOL(mc13xxx_irq_mask);
 
 int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq)
 {
-	int ret;
-	unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
-	u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
-	u32 mask;
-
-	if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
-		return -EINVAL;
-
-	ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
-	if (ret)
-		return ret;
+	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
 
-	if (!(mask & irqbit))
-		/* already unmasked */
-		return 0;
+	enable_irq(virq);
 
-	return mc13xxx_reg_write(mc13xxx, offmask, mask & ~irqbit);
+	return 0;
 }
 EXPORT_SYMBOL(mc13xxx_irq_unmask);
 
@@ -239,7 +127,7 @@ int mc13xxx_irq_status(struct mc13xxx *m
 	unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
 	u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
 
-	if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
+	if (irq < 0 || irq >= ARRAY_SIZE(mc13xxx->irqs))
 		return -EINVAL;
 
 	if (enabled) {
@@ -266,147 +154,26 @@ int mc13xxx_irq_status(struct mc13xxx *m
 }
 EXPORT_SYMBOL(mc13xxx_irq_status);
 
-int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq)
-{
-	unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
-	unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
-
-	BUG_ON(irq < 0 || irq >= MC13XXX_NUM_IRQ);
-
-	return mc13xxx_reg_write(mc13xxx, offstat, val);
-}
-EXPORT_SYMBOL(mc13xxx_irq_ack);
-
-int mc13xxx_irq_request_nounmask(struct mc13xxx *mc13xxx, int irq,
-		irq_handler_t handler, const char *name, void *dev)
-{
-	BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-	BUG_ON(!handler);
-
-	if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
-		return -EINVAL;
-
-	if (mc13xxx->irqhandler[irq])
-		return -EBUSY;
-
-	mc13xxx->irqhandler[irq] = handler;
-	mc13xxx->irqdata[irq] = dev;
-
-	return 0;
-}
-EXPORT_SYMBOL(mc13xxx_irq_request_nounmask);
-
 int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq,
 		irq_handler_t handler, const char *name, void *dev)
 {
-	int ret;
-
-	ret = mc13xxx_irq_request_nounmask(mc13xxx, irq, handler, name, dev);
-	if (ret)
-		return ret;
-
-	ret = mc13xxx_irq_unmask(mc13xxx, irq);
-	if (ret) {
-		mc13xxx->irqhandler[irq] = NULL;
-		mc13xxx->irqdata[irq] = NULL;
-		return ret;
-	}
+	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
 
-	return 0;
+	return devm_request_threaded_irq(mc13xxx->dev, virq, NULL, handler,
+					 0, name, dev);
 }
 EXPORT_SYMBOL(mc13xxx_irq_request);
 
 int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev)
 {
-	int ret;
-	BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-
-	if (irq < 0 || irq >= MC13XXX_NUM_IRQ || !mc13xxx->irqhandler[irq] ||
-			mc13xxx->irqdata[irq] != dev)
-		return -EINVAL;
-
-	ret = mc13xxx_irq_mask(mc13xxx, irq);
-	if (ret)
-		return ret;
+	int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
 
-	mc13xxx->irqhandler[irq] = NULL;
-	mc13xxx->irqdata[irq] = NULL;
+	devm_free_irq(mc13xxx->dev, virq, dev);
 
 	return 0;
 }
 EXPORT_SYMBOL(mc13xxx_irq_free);
 
-static inline irqreturn_t mc13xxx_irqhandler(struct mc13xxx *mc13xxx, int irq)
-{
-	return mc13xxx->irqhandler[irq](irq, mc13xxx->irqdata[irq]);
-}
-
-/*
- * returns: number of handled irqs or negative error
- * locking: holds mc13xxx->lock
- */
-static int mc13xxx_irq_handle(struct mc13xxx *mc13xxx,
-		unsigned int offstat, unsigned int offmask, int baseirq)
-{
-	u32 stat, mask;
-	int ret = mc13xxx_reg_read(mc13xxx, offstat, &stat);
-	int num_handled = 0;
-
-	if (ret)
-		return ret;
-
-	ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
-	if (ret)
-		return ret;
-
-	while (stat & ~mask) {
-		int irq = __ffs(stat & ~mask);
-
-		stat &= ~(1 << irq);
-
-		if (likely(mc13xxx->irqhandler[baseirq + irq])) {
-			irqreturn_t handled;
-
-			handled = mc13xxx_irqhandler(mc13xxx, baseirq + irq);
-			if (handled == IRQ_HANDLED)
-				num_handled++;
-		} else {
-			dev_err(mc13xxx->dev,
-					"BUG: irq %u but no handler\n",
-					baseirq + irq);
-
-			mask |= 1 << irq;
-
-			ret = mc13xxx_reg_write(mc13xxx, offmask, mask);
-		}
-	}
-
-	return num_handled;
-}
-
-static irqreturn_t mc13xxx_irq_thread(int irq, void *data)
-{
-	struct mc13xxx *mc13xxx = data;
-	irqreturn_t ret;
-	int handled = 0;
-
-	mc13xxx_lock(mc13xxx);
-
-	ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT0,
-			MC13XXX_IRQMASK0, 0);
-	if (ret > 0)
-		handled = 1;
-
-	ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT1,
-			MC13XXX_IRQMASK1, 24);
-	if (ret > 0)
-		handled = 1;
-
-	mc13xxx_unlock(mc13xxx);
-
-	return IRQ_RETVAL(handled);
-}
-
 #define maskval(reg, mask)	(((reg) & (mask)) >> __ffs(mask))
 static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision)
 {
@@ -475,8 +242,6 @@ static irqreturn_t mc13xxx_handler_adcdo
 {
 	struct mc13xxx_adcdone_data *adcdone_data = data;
 
-	mc13xxx_irq_ack(adcdone_data->mc13xxx, irq);
-
 	complete_all(&adcdone_data->done);
 
 	return IRQ_HANDLED;
@@ -544,7 +309,6 @@ int mc13xxx_adc_do_conversion(struct mc1
 	dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
 	mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
 			mc13xxx_handler_adcdone, __func__, &adcdone_data);
-	mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE);
 
 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
@@ -599,7 +363,8 @@ static int mc13xxx_add_subdevice_pdata(s
 	if (!cell.name)
 		return -ENOMEM;
 
-	return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);
+	return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0,
+			       regmap_irq_get_domain(mc13xxx->irq_data));
 }
 
 static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
@@ -640,8 +405,8 @@ int mc13xxx_common_init(struct device *d
 {
 	struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
 	struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
-	int ret;
 	u32 revision;
+	int i, ret;
 
 	mc13xxx->dev = dev;
 
@@ -651,31 +416,32 @@ int mc13xxx_common_init(struct device *d
 
 	mc13xxx->variant->print_revision(mc13xxx, revision);
 
-	/* mask all irqs */
-	ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
-	if (ret)
-		return ret;
+	for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) {
+		mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG;
+		mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG);
+	}
 
-	ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff);
+	mc13xxx->irq_chip.name = dev_name(dev);
+	mc13xxx->irq_chip.status_base = MC13XXX_IRQSTAT0;
+	mc13xxx->irq_chip.mask_base = MC13XXX_IRQMASK0;
+	mc13xxx->irq_chip.ack_base = MC13XXX_IRQSTAT0;
+	mc13xxx->irq_chip.irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0;
+	mc13xxx->irq_chip.init_ack_masked = true;
+	mc13xxx->irq_chip.use_ack = true;
+	mc13xxx->irq_chip.num_regs = MC13XXX_IRQ_REG_CNT;
+	mc13xxx->irq_chip.irqs = mc13xxx->irqs;
+	mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);
+
+	ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
+				  0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
 	if (ret)
 		return ret;
 
 	mutex_init(&mc13xxx->lock);
 
-	ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
-			IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
-	if (ret)
-		return ret;
-
 	if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
 		mc13xxx->flags = pdata->flags;
 
-	if (mc13xxx->flags & MC13XXX_USE_ADC)
-		mc13xxx_add_subdevice(mc13xxx, "%s-adc");
-
-	if (mc13xxx->flags & MC13XXX_USE_RTC)
-		mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
-
 	if (pdata) {
 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
 			&pdata->regulators, sizeof(pdata->regulators));
@@ -699,6 +465,12 @@ int mc13xxx_common_init(struct device *d
 			mc13xxx_add_subdevice(mc13xxx, "%s-ts");
 	}
 
+	if (mc13xxx->flags & MC13XXX_USE_ADC)
+		mc13xxx_add_subdevice(mc13xxx, "%s-adc");
+
+	if (mc13xxx->flags & MC13XXX_USE_RTC)
+		mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mc13xxx_common_init);
@@ -707,8 +479,8 @@ int mc13xxx_common_exit(struct device *d
 {
 	struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
 
-	free_irq(mc13xxx->irq, mc13xxx);
 	mfd_remove_devices(dev);
+	regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data);
 	mutex_destroy(&mc13xxx->lock);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/mc13xxx.h linux-libre-3.17-rc7-gnu/drivers/mfd/mc13xxx.h
--- linux-libre-3.16-gnu/drivers/mfd/mc13xxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/mc13xxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,9 @@
 #include <linux/regmap.h>
 #include <linux/mfd/mc13xxx.h>
 
-#define MC13XXX_NUMREGS 0x3f
+#define MC13XXX_NUMREGS		0x3f
+#define MC13XXX_IRQ_REG_CNT	2
+#define MC13XXX_IRQ_PER_REG	24
 
 struct mc13xxx;
 
@@ -33,13 +35,14 @@ struct mc13xxx {
 	struct device *dev;
 	const struct mc13xxx_variant *variant;
 
+	struct regmap_irq irqs[MC13XXX_IRQ_PER_REG * MC13XXX_IRQ_REG_CNT];
+	struct regmap_irq_chip irq_chip;
+	struct regmap_irq_chip_data *irq_data;
+
 	struct mutex lock;
 	int irq;
 	int flags;
 
-	irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
-	void *irqdata[MC13XXX_NUM_IRQ];
-
 	int adcflags;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/mcp-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/mcp-core.c
--- linux-libre-3.16-gnu/drivers/mfd/mcp-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/mcp-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,6 +137,7 @@ EXPORT_SYMBOL(mcp_reg_read);
 void mcp_enable(struct mcp *mcp)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&mcp->lock, flags);
 	if (mcp->use_count++ == 0)
 		mcp->ops->enable(mcp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/omap-usb-host.c linux-libre-3.17-rc7-gnu/drivers/mfd/omap-usb-host.c
--- linux-libre-3.16-gnu/drivers/mfd/omap-usb-host.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/omap-usb-host.c	2014-09-28 17:29:07.000000000 -0400
@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconf
 
 		for (i = 0; i < omap->nports; i++) {
 			if (is_ehci_phy_mode(pdata->port_mode[i])) {
-				reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
 				break;
 			}
 		}
@@ -647,7 +647,7 @@ static int usbhs_omap_probe(struct platf
 		default:
 			omap->nports = OMAP3_HS_USB_PORTS;
 			dev_dbg(dev,
-			 "USB HOST Rev:0x%d not recognized, assuming %d ports\n",
+			 "USB HOST Rev:0x%x not recognized, assuming %d ports\n",
 			 omap->usbhs_rev, omap->nports);
 			break;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/palmas.c linux-libre-3.17-rc7-gnu/drivers/mfd/palmas.c
--- linux-libre-3.16-gnu/drivers/mfd/palmas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/palmas.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,52 +25,6 @@
 #include <linux/mfd/palmas.h>
 #include <linux/of_device.h>
 
-#define PALMAS_EXT_REQ (PALMAS_EXT_CONTROL_ENABLE1 |	\
-			PALMAS_EXT_CONTROL_ENABLE2 |	\
-			PALMAS_EXT_CONTROL_NSLEEP)
-
-struct palmas_sleep_requestor_info {
-	int id;
-	int reg_offset;
-	int bit_pos;
-};
-
-#define EXTERNAL_REQUESTOR(_id, _offset, _pos)		\
-	[PALMAS_EXTERNAL_REQSTR_ID_##_id] = {		\
-		.id = PALMAS_EXTERNAL_REQSTR_ID_##_id,	\
-		.reg_offset = _offset,			\
-		.bit_pos = _pos,			\
-	}
-
-static struct palmas_sleep_requestor_info sleep_req_info[] = {
-	EXTERNAL_REQUESTOR(REGEN1, 0, 0),
-	EXTERNAL_REQUESTOR(REGEN2, 0, 1),
-	EXTERNAL_REQUESTOR(SYSEN1, 0, 2),
-	EXTERNAL_REQUESTOR(SYSEN2, 0, 3),
-	EXTERNAL_REQUESTOR(CLK32KG, 0, 4),
-	EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5),
-	EXTERNAL_REQUESTOR(REGEN3, 0, 6),
-	EXTERNAL_REQUESTOR(SMPS12, 1, 0),
-	EXTERNAL_REQUESTOR(SMPS3, 1, 1),
-	EXTERNAL_REQUESTOR(SMPS45, 1, 2),
-	EXTERNAL_REQUESTOR(SMPS6, 1, 3),
-	EXTERNAL_REQUESTOR(SMPS7, 1, 4),
-	EXTERNAL_REQUESTOR(SMPS8, 1, 5),
-	EXTERNAL_REQUESTOR(SMPS9, 1, 6),
-	EXTERNAL_REQUESTOR(SMPS10, 1, 7),
-	EXTERNAL_REQUESTOR(LDO1, 2, 0),
-	EXTERNAL_REQUESTOR(LDO2, 2, 1),
-	EXTERNAL_REQUESTOR(LDO3, 2, 2),
-	EXTERNAL_REQUESTOR(LDO4, 2, 3),
-	EXTERNAL_REQUESTOR(LDO5, 2, 4),
-	EXTERNAL_REQUESTOR(LDO6, 2, 5),
-	EXTERNAL_REQUESTOR(LDO7, 2, 6),
-	EXTERNAL_REQUESTOR(LDO8, 2, 7),
-	EXTERNAL_REQUESTOR(LDO9, 3, 0),
-	EXTERNAL_REQUESTOR(LDOLN, 3, 1),
-	EXTERNAL_REQUESTOR(LDOUSB, 3, 2),
-};
-
 static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
 	{
 		.reg_bits = 8,
@@ -92,6 +46,133 @@ static const struct regmap_config palmas
 	},
 };
 
+static const struct regmap_irq tps65917_irqs[] = {
+	/* INT1 IRQs */
+	[TPS65917_RESERVED1] = {
+		.mask = TPS65917_RESERVED,
+	},
+	[TPS65917_PWRON_IRQ] = {
+		.mask = TPS65917_INT1_STATUS_PWRON,
+	},
+	[TPS65917_LONG_PRESS_KEY_IRQ] = {
+		.mask = TPS65917_INT1_STATUS_LONG_PRESS_KEY,
+	},
+	[TPS65917_RESERVED2] = {
+		.mask = TPS65917_RESERVED,
+	},
+	[TPS65917_PWRDOWN_IRQ] = {
+		.mask = TPS65917_INT1_STATUS_PWRDOWN,
+	},
+	[TPS65917_HOTDIE_IRQ] = {
+		.mask = TPS65917_INT1_STATUS_HOTDIE,
+	},
+	[TPS65917_VSYS_MON_IRQ] = {
+		.mask = TPS65917_INT1_STATUS_VSYS_MON,
+	},
+	[TPS65917_RESERVED3] = {
+		.mask = TPS65917_RESERVED,
+	},
+	/* INT2 IRQs*/
+	[TPS65917_RESERVED4] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 1,
+	},
+	[TPS65917_OTP_ERROR_IRQ] = {
+		.mask = TPS65917_INT2_STATUS_OTP_ERROR,
+		.reg_offset = 1,
+	},
+	[TPS65917_WDT_IRQ] = {
+		.mask = TPS65917_INT2_STATUS_WDT,
+		.reg_offset = 1,
+	},
+	[TPS65917_RESERVED5] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 1,
+	},
+	[TPS65917_RESET_IN_IRQ] = {
+		.mask = TPS65917_INT2_STATUS_RESET_IN,
+		.reg_offset = 1,
+	},
+	[TPS65917_FSD_IRQ] = {
+		.mask = TPS65917_INT2_STATUS_FSD,
+		.reg_offset = 1,
+	},
+	[TPS65917_SHORT_IRQ] = {
+		.mask = TPS65917_INT2_STATUS_SHORT,
+		.reg_offset = 1,
+	},
+	[TPS65917_RESERVED6] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 1,
+	},
+	/* INT3 IRQs */
+	[TPS65917_GPADC_AUTO_0_IRQ] = {
+		.mask = TPS65917_INT3_STATUS_GPADC_AUTO_0,
+		.reg_offset = 2,
+	},
+	[TPS65917_GPADC_AUTO_1_IRQ] = {
+		.mask = TPS65917_INT3_STATUS_GPADC_AUTO_1,
+		.reg_offset = 2,
+	},
+	[TPS65917_GPADC_EOC_SW_IRQ] = {
+		.mask = TPS65917_INT3_STATUS_GPADC_EOC_SW,
+		.reg_offset = 2,
+	},
+	[TPS65917_RESREVED6] = {
+		.mask = TPS65917_RESERVED6,
+		.reg_offset = 2,
+	},
+	[TPS65917_RESERVED7] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 2,
+	},
+	[TPS65917_RESERVED8] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 2,
+	},
+	[TPS65917_RESERVED9] = {
+		.mask = TPS65917_RESERVED,
+		.reg_offset = 2,
+	},
+	[TPS65917_VBUS_IRQ] = {
+		.mask = TPS65917_INT3_STATUS_VBUS,
+		.reg_offset = 2,
+	},
+	/* INT4 IRQs */
+	[TPS65917_GPIO_0_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_0,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_1_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_1,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_2_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_2,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_3_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_3,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_4_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_4,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_5_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_5,
+		.reg_offset = 3,
+	},
+	[TPS65917_GPIO_6_IRQ] = {
+		.mask = TPS65917_INT4_STATUS_GPIO_6,
+		.reg_offset = 3,
+	},
+	[TPS65917_RESERVED10] = {
+		.mask = TPS65917_RESERVED10,
+		.reg_offset = 3,
+	},
+};
+
 static const struct regmap_irq palmas_irqs[] = {
 	/* INT1 IRQs */
 	[PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = {
@@ -232,13 +313,26 @@ static struct regmap_irq_chip palmas_irq
 			PALMAS_INT1_MASK),
 };
 
+static struct regmap_irq_chip tps65917_irq_chip = {
+	.name = "tps65917",
+	.irqs = tps65917_irqs,
+	.num_irqs = ARRAY_SIZE(tps65917_irqs),
+
+	.num_regs = 4,
+	.irq_reg_stride = 5,
+	.status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+			PALMAS_INT1_STATUS),
+	.mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+			PALMAS_INT1_MASK),
+};
+
 int palmas_ext_control_req_config(struct palmas *palmas,
 	enum palmas_external_requestor_id id,  int ext_ctrl, bool enable)
 {
+	struct palmas_pmic_driver_data *pmic_ddata = palmas->pmic_ddata;
 	int preq_mask_bit = 0;
 	int reg_add = 0;
-	int bit_pos;
-	int ret;
+	int bit_pos, ret;
 
 	if (!(ext_ctrl & PALMAS_EXT_REQ))
 		return 0;
@@ -257,8 +351,8 @@ int palmas_ext_control_req_config(struct
 		preq_mask_bit = 2;
 	}
 
-	bit_pos = sleep_req_info[id].bit_pos;
-	reg_add += sleep_req_info[id].reg_offset;
+	bit_pos = pmic_ddata->sleep_req_info[id].bit_pos;
+	reg_add += pmic_ddata->sleep_req_info[id].reg_offset;
 	if (enable)
 		ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
 				reg_add, BIT(bit_pos), BIT(bit_pos));
@@ -357,14 +451,38 @@ static void palmas_power_off(void)
 static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
 static unsigned int tps659038_features;
 
+struct palmas_driver_data {
+	unsigned int *features;
+	struct regmap_irq_chip *irq_chip;
+};
+
+static struct palmas_driver_data palmas_data = {
+	.features = &palmas_features,
+	.irq_chip = &palmas_irq_chip,
+};
+
+static struct palmas_driver_data tps659038_data = {
+	.features = &tps659038_features,
+	.irq_chip = &palmas_irq_chip,
+};
+
+static struct palmas_driver_data tps65917_data = {
+	.features = &tps659038_features,
+	.irq_chip = &tps65917_irq_chip,
+};
+
 static const struct of_device_id of_palmas_match_tbl[] = {
 	{
 		.compatible = "ti,palmas",
-		.data = &palmas_features,
+		.data = &palmas_data,
 	},
 	{
 		.compatible = "ti,tps659038",
-		.data = &tps659038_features,
+		.data = &tps659038_data,
+	},
+	{
+		.compatible = "ti,tps65917",
+		.data = &tps65917_data,
 	},
 	{ },
 };
@@ -375,9 +493,10 @@ static int palmas_i2c_probe(struct i2c_c
 {
 	struct palmas *palmas;
 	struct palmas_platform_data *pdata;
+	struct palmas_driver_data *driver_data;
 	struct device_node *node = i2c->dev.of_node;
 	int ret = 0, i;
-	unsigned int reg, addr, *features;
+	unsigned int reg, addr;
 	int slave;
 	const struct of_device_id *match;
 
@@ -408,8 +527,8 @@ static int palmas_i2c_probe(struct i2c_c
 	if (!match)
 		return -ENODATA;
 
-	features = (unsigned int *)match->data;
-	palmas->features = *features;
+	driver_data = (struct palmas_driver_data *)match->data;
+	palmas->features = *driver_data->features;
 
 	for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
 		if (i == 0)
@@ -463,8 +582,8 @@ static int palmas_i2c_probe(struct i2c_c
 	regmap_write(palmas->regmap[slave], addr, reg);
 
 	ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
-			IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip,
-			&palmas->irq_data);
+				  IRQF_ONESHOT | pdata->irq_flags, 0,
+				  driver_data->irq_chip, &palmas->irq_data);
 	if (ret < 0)
 		goto err_i2c;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/pcf50633-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/pcf50633-core.c
--- linux-libre-3.16-gnu/drivers/mfd/pcf50633-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/pcf50633-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -244,20 +244,20 @@ static int pcf50633_probe(struct i2c_cli
 
 	for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
 		struct platform_device *pdev;
+		int j;
 
 		pdev = platform_device_alloc("pcf50633-regulator", i);
-		if (!pdev) {
-			dev_err(pcf->dev, "Cannot create regulator %d\n", i);
-			continue;
-		}
+		if (!pdev)
+			return -ENOMEM;
 
 		pdev->dev.parent = pcf->dev;
-		if (platform_device_add_data(pdev, &pdata->reg_init_data[i],
-					sizeof(pdata->reg_init_data[i])) < 0) {
+		ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
+					       sizeof(pdata->reg_init_data[i]));
+		if (ret) {
 			platform_device_put(pdev);
-			dev_err(pcf->dev, "Out of memory for regulator parameters %d\n",
-									i);
-			continue;
+			for (j = 0; j < i; j++)
+				platform_device_put(pcf->regulator_pdev[j]);
+			return ret;
 		}
 		pcf->regulator_pdev[i] = pdev;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/pm8921-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/pm8921-core.c
--- linux-libre-3.16-gnu/drivers/mfd/pm8921-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/pm8921-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -186,11 +186,9 @@ static void pm8xxx_irq_mask_ack(struct i
 {
 	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;
 
 	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
 	pm8xxx_config_irq(chip, block, config);
@@ -200,11 +198,9 @@ static void pm8xxx_irq_unmask(struct irq
 {
 	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;
 
 	config = chip->config[pmirq];
 	pm8xxx_config_irq(chip, block, config);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/rtsx_pcr.c linux-libre-3.17-rc7-gnu/drivers/mfd/rtsx_pcr.c
--- linux-libre-3.16-gnu/drivers/mfd/rtsx_pcr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/rtsx_pcr.c	2014-09-28 17:29:07.000000000 -0400
@@ -337,40 +337,64 @@ static void rtsx_pci_add_sg_tbl(struct r
 int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
 		int num_sg, bool read, int timeout)
 {
-	struct completion trans_done;
-	u8 dir;
-	int err = 0, i, count;
-	long timeleft;
-	unsigned long flags;
-	struct scatterlist *sg;
-	enum dma_data_direction dma_dir;
-	u32 val;
-	dma_addr_t addr;
-	unsigned int len;
+	int err = 0, count;
 
 	dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+	count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
+	if (count < 1)
+		return -EINVAL;
+	dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+
+	err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
+
+	rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read)
+{
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
-	/* don't transfer data during abort processing */
 	if (pcr->remove_pci)
 		return -EINVAL;
 
 	if ((sglist == NULL) || (num_sg <= 0))
 		return -EINVAL;
 
-	if (read) {
-		dir = DEVICE_TO_HOST;
-		dma_dir = DMA_FROM_DEVICE;
-	} else {
-		dir = HOST_TO_DEVICE;
-		dma_dir = DMA_TO_DEVICE;
-	}
+	return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
 
-	count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
-	if (count < 1) {
-		dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
+void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read)
+{
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
+
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int count, bool read, int timeout)
+{
+	struct completion trans_done;
+	struct scatterlist *sg;
+	dma_addr_t addr;
+	long timeleft;
+	unsigned long flags;
+	unsigned int len;
+	int i, err = 0;
+	u32 val;
+	u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
+
+	if (pcr->remove_pci)
+		return -ENODEV;
+
+	if ((sglist == NULL) || (count < 1))
 		return -EINVAL;
-	}
-	dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
 
 	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
 	pcr->sgi = 0;
@@ -400,12 +424,10 @@ int rtsx_pci_transfer_data(struct rtsx_p
 	}
 
 	spin_lock_irqsave(&pcr->lock, flags);
-
 	if (pcr->trans_result == TRANS_RESULT_FAIL)
 		err = -EINVAL;
 	else if (pcr->trans_result == TRANS_NO_DEVICE)
 		err = -ENODEV;
-
 	spin_unlock_irqrestore(&pcr->lock, flags);
 
 out:
@@ -413,8 +435,6 @@ out:
 	pcr->done = NULL;
 	spin_unlock_irqrestore(&pcr->lock, flags);
 
-	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
-
 	if ((err < 0) && (err != -ENODEV))
 		rtsx_pci_stop_cmd(pcr);
 
@@ -423,7 +443,7 @@ out:
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
 
 int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/rtsx_usb.c linux-libre-3.17-rc7-gnu/drivers/mfd/rtsx_usb.c
--- linux-libre-3.16-gnu/drivers/mfd/rtsx_usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/rtsx_usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -744,6 +744,7 @@ static struct usb_device_id rtsx_usb_usb
 	{ USB_DEVICE(0x0BDA, 0x0140) },
 	{ }
 };
+MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
 
 static struct usb_driver rtsx_usb_driver = {
 	.name			= "rtsx_usb",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/sec-core.c linux-libre-3.17-rc7-gnu/drivers/mfd/sec-core.c
--- linux-libre-3.16-gnu/drivers/mfd/sec-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/sec-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,8 +28,10 @@
 #include <linux/mfd/samsung/s2mpa01.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8763.h>
 #include <linux/mfd/samsung/s5m8767.h>
+#include <linux/regulator/machine.h>
 #include <linux/regmap.h>
 
 static const struct mfd_cell s5m8751_devs[] = {
@@ -89,6 +91,15 @@ static const struct mfd_cell s2mpa01_dev
 	},
 };
 
+static const struct mfd_cell s2mpu02_devs[] = {
+	{ .name = "s2mpu02-pmic", },
+	{ .name = "s2mpu02-rtc", },
+	{
+		.name = "s2mpu02-clk",
+		.of_compatible = "samsung,s2mpu02-clk",
+	}
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id sec_dt_match[] = {
 	{	.compatible = "samsung,s5m8767-pmic",
@@ -103,6 +114,9 @@ static const struct of_device_id sec_dt_
 		.compatible = "samsung,s2mpa01-pmic",
 		.data = (void *)S2MPA01,
 	}, {
+		.compatible = "samsung,s2mpu02-pmic",
+		.data = (void *)S2MPU02,
+	}, {
 		/* Sentinel */
 	},
 };
@@ -132,6 +146,18 @@ static bool s2mps11_volatile(struct devi
 	}
 }
 
+static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPU02_REG_INT1M:
+	case S2MPU02_REG_INT2M:
+	case S2MPU02_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
 static bool s5m8763_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -177,6 +203,15 @@ static const struct regmap_config s2mps1
 	.cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config s2mpu02_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPU02_REG_DVSDATA,
+	.volatile_reg = s2mpu02_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
 static const struct regmap_config s5m8763_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -238,6 +273,7 @@ static inline unsigned long sec_i2c_get_
 #ifdef CONFIG_OF
 	if (i2c->dev.of_node) {
 		const struct of_device_id *match;
+
 		match = of_match_node(sec_dt_match, i2c->dev.of_node);
 		return (unsigned long)match->data;
 	}
@@ -250,9 +286,10 @@ static int sec_pmic_probe(struct i2c_cli
 {
 	struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	const struct regmap_config *regmap;
+	const struct mfd_cell *sec_devs;
 	struct sec_pmic_dev *sec_pmic;
 	unsigned long device_type;
-	int ret;
+	int ret, num_sec_devs;
 
 	sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
 				GFP_KERNEL);
@@ -297,6 +334,9 @@ static int sec_pmic_probe(struct i2c_cli
 	case S5M8767X:
 		regmap = &s5m8767_regmap_config;
 		break;
+	case S2MPU02:
+		regmap = &s2mpu02_regmap_config;
+		break;
 	default:
 		regmap = &sec_regmap_config;
 		break;
@@ -319,34 +359,39 @@ static int sec_pmic_probe(struct i2c_cli
 
 	switch (sec_pmic->device_type) {
 	case S5M8751X:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
-				      ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
+		sec_devs = s5m8751_devs;
+		num_sec_devs = ARRAY_SIZE(s5m8751_devs);
 		break;
 	case S5M8763X:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
-				      ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
+		sec_devs = s5m8763_devs;
+		num_sec_devs = ARRAY_SIZE(s5m8763_devs);
 		break;
 	case S5M8767X:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
-				      ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
+		sec_devs = s5m8767_devs;
+		num_sec_devs = ARRAY_SIZE(s5m8767_devs);
 		break;
 	case S2MPA01:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
-				      ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
+		sec_devs = s2mpa01_devs;
+		num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
 		break;
 	case S2MPS11X:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
-				      ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
+		sec_devs = s2mps11_devs;
+		num_sec_devs = ARRAY_SIZE(s2mps11_devs);
 		break;
 	case S2MPS14X:
-		ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
-				      ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
+		sec_devs = s2mps14_devs;
+		num_sec_devs = ARRAY_SIZE(s2mps14_devs);
+		break;
+	case S2MPU02:
+		sec_devs = s2mpu02_devs;
+		num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
 		break;
 	default:
 		/* If this happens the probe function is problem */
 		BUG();
 	}
-
+	ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
+			      0, NULL);
 	if (ret)
 		goto err_mfd;
 
@@ -387,6 +432,15 @@ static int sec_pmic_suspend(struct devic
 	 */
 	disable_irq(sec_pmic->irq);
 
+	switch (sec_pmic->device_type) {
+	case S2MPS14X:
+	case S2MPU02:
+		regulator_suspend_prepare(PM_SUSPEND_MEM);
+		break;
+	default:
+		break;
+	}
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/sec-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/sec-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/sec-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/sec-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8763.h>
 #include <linux/mfd/samsung/s5m8767.h>
 
@@ -161,6 +162,77 @@ static const struct regmap_irq s2mps14_i
 	},
 };
 
+static const struct regmap_irq s2mpu02_irqs[] = {
+	[S2MPU02_IRQ_PWRONF] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_PWRONF_MASK,
+	},
+	[S2MPU02_IRQ_PWRONR] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_PWRONR_MASK,
+	},
+	[S2MPU02_IRQ_JIGONBF] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_JIGONBF_MASK,
+	},
+	[S2MPU02_IRQ_JIGONBR] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_JIGONBR_MASK,
+	},
+	[S2MPU02_IRQ_ACOKBF] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_ACOKBF_MASK,
+	},
+	[S2MPU02_IRQ_ACOKBR] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_ACOKBR_MASK,
+	},
+	[S2MPU02_IRQ_PWRON1S] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_PWRON1S_MASK,
+	},
+	[S2MPU02_IRQ_MRB] = {
+		.reg_offset = 0,
+		.mask = S2MPS11_IRQ_MRB_MASK,
+	},
+	[S2MPU02_IRQ_RTC60S] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_RTC60S_MASK,
+	},
+	[S2MPU02_IRQ_RTCA1] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_RTCA1_MASK,
+	},
+	[S2MPU02_IRQ_RTCA0] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_RTCA0_MASK,
+	},
+	[S2MPU02_IRQ_SMPL] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_SMPL_MASK,
+	},
+	[S2MPU02_IRQ_RTC1S] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_RTC1S_MASK,
+	},
+	[S2MPU02_IRQ_WTSR] = {
+		.reg_offset = 1,
+		.mask = S2MPS11_IRQ_WTSR_MASK,
+	},
+	[S2MPU02_IRQ_INT120C] = {
+		.reg_offset = 2,
+		.mask = S2MPS11_IRQ_INT120C_MASK,
+	},
+	[S2MPU02_IRQ_INT140C] = {
+		.reg_offset = 2,
+		.mask = S2MPS11_IRQ_INT140C_MASK,
+	},
+	[S2MPU02_IRQ_TSD] = {
+		.reg_offset = 2,
+		.mask = S2MPS14_IRQ_TSD_MASK,
+	},
+};
+
 static const struct regmap_irq s5m8767_irqs[] = {
 	[S5M8767_IRQ_PWRR] = {
 		.reg_offset = 0,
@@ -327,6 +399,16 @@ static const struct regmap_irq_chip s2mp
 	.ack_base = S2MPS14_REG_INT1,
 };
 
+static const struct regmap_irq_chip s2mpu02_irq_chip = {
+	.name = "s2mpu02",
+	.irqs = s2mpu02_irqs,
+	.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
+	.num_regs = 3,
+	.status_base = S2MPU02_REG_INT1,
+	.mask_base = S2MPU02_REG_INT1M,
+	.ack_base = S2MPU02_REG_INT1,
+};
+
 static const struct regmap_irq_chip s5m8767_irq_chip = {
 	.name = "s5m8767",
 	.irqs = s5m8767_irqs,
@@ -351,6 +433,7 @@ int sec_irq_init(struct sec_pmic_dev *se
 {
 	int ret = 0;
 	int type = sec_pmic->device_type;
+	const struct regmap_irq_chip *sec_irq_chip;
 
 	if (!sec_pmic->irq) {
 		dev_warn(sec_pmic->dev,
@@ -361,28 +444,19 @@ int sec_irq_init(struct sec_pmic_dev *se
 
 	switch (type) {
 	case S5M8763X:
-		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				  sec_pmic->irq_base, &s5m8763_irq_chip,
-				  &sec_pmic->irq_data);
+		sec_irq_chip = &s5m8763_irq_chip;
 		break;
 	case S5M8767X:
-		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				  sec_pmic->irq_base, &s5m8767_irq_chip,
-				  &sec_pmic->irq_data);
+		sec_irq_chip = &s5m8767_irq_chip;
 		break;
 	case S2MPS11X:
-		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				  sec_pmic->irq_base, &s2mps11_irq_chip,
-				  &sec_pmic->irq_data);
+		sec_irq_chip = &s2mps11_irq_chip;
 		break;
 	case S2MPS14X:
-		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				  sec_pmic->irq_base, &s2mps14_irq_chip,
-				  &sec_pmic->irq_data);
+		sec_irq_chip = &s2mps14_irq_chip;
+		break;
+	case S2MPU02:
+		sec_irq_chip = &s2mpu02_irq_chip;
 		break;
 	default:
 		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
@@ -390,6 +464,10 @@ int sec_irq_init(struct sec_pmic_dev *se
 		return -EINVAL;
 	}
 
+	ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
+			  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			  sec_pmic->irq_base, sec_irq_chip,
+			  &sec_pmic->irq_data);
 	if (ret != 0) {
 		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
 		return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/si476x-cmd.c linux-libre-3.17-rc7-gnu/drivers/mfd/si476x-cmd.c
--- linux-libre-3.16-gnu/drivers/mfd/si476x-cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/si476x-cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1228,8 +1228,8 @@ static int si476x_core_cmd_fm_rsq_status
 }
 
 static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
-					     struct si476x_rsq_status_args *rsqargs,
-					     struct si476x_rsq_status_report *report)
+				     struct si476x_rsq_status_args *rsqargs,
+				     struct si476x_rsq_status_report *report)
 {
 	int err;
 	u8       resp[CMD_FM_RSQ_STATUS_A10_NRESP];
@@ -1434,10 +1434,10 @@ typedef int (*tune_freq_func_t) (struct
 				 struct si476x_tune_freq_args *tuneargs);
 
 static struct {
-	int (*power_up) (struct si476x_core *,
-			 struct si476x_power_up_args *);
-	int (*power_down) (struct si476x_core *,
-			   struct si476x_power_down_args *);
+	int (*power_up)(struct si476x_core *,
+			struct si476x_power_up_args *);
+	int (*power_down)(struct si476x_core *,
+			  struct si476x_power_down_args *);
 
 	tune_freq_func_t fm_tune_freq;
 	tune_freq_func_t am_tune_freq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/stmpe.c linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe.c
--- linux-libre-3.16-gnu/drivers/mfd/stmpe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1147,7 +1147,7 @@ static void stmpe_of_probe(struct stmpe_
 }
 
 /* Called from client specific probe routines */
-int stmpe_probe(struct stmpe_client_info *ci, int partnum)
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
 {
 	struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
 	struct device_node *np = ci->dev->of_node;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/stmpe.h linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe.h
--- linux-libre-3.16-gnu/drivers/mfd/stmpe.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ struct stmpe_client_info {
 	void (*init)(struct stmpe *stmpe);
 };
 
-int stmpe_probe(struct stmpe_client_info *ci, int partnum);
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum);
 int stmpe_remove(struct stmpe *stmpe);
 
 #define STMPE_ICR_LSB_HIGH	(1 << 2)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/stmpe-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/stmpe-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/stmpe-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(of, stmpe_of_match);
 static int
 stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
-	int partnum;
+	enum stmpe_partnum partnum;
 	const struct of_device_id *of_id;
 
 	i2c_ci.data = (void *)id;
@@ -85,7 +85,7 @@ stmpe_i2c_probe(struct i2c_client *i2c,
 		dev_info(&i2c->dev, "matching on node name, compatible is preferred\n");
 		partnum = id->driver_data;
 	} else
-		partnum = (int)of_id->data;
+		partnum = (enum stmpe_partnum)of_id->data;
 
 	return stmpe_probe(&i2c_ci, partnum);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/sun6i-prcm.c linux-libre-3.17-rc7-gnu/drivers/mfd/sun6i-prcm.c
--- linux-libre-3.16-gnu/drivers/mfd/sun6i-prcm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/sun6i-prcm.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,16 +76,46 @@ static const struct mfd_cell sun6i_a31_p
 	},
 };
 
+static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
+	{
+		.name = "sun8i-a23-apb0-clk",
+		.of_compatible = "allwinner,sun8i-a23-apb0-clk",
+		.num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
+		.resources = sun6i_a31_apb0_clk_res,
+	},
+	{
+		.name = "sun6i-a31-apb0-gates-clk",
+		.of_compatible = "allwinner,sun8i-a23-apb0-gates-clk",
+		.num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
+		.resources = sun6i_a31_apb0_gates_clk_res,
+	},
+	{
+		.name = "sun6i-a31-apb0-clock-reset",
+		.of_compatible = "allwinner,sun6i-a31-clock-reset",
+		.num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
+		.resources = sun6i_a31_apb0_rstc_res,
+	},
+};
+
 static const struct prcm_data sun6i_a31_prcm_data = {
 	.nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
 	.subdevs = sun6i_a31_prcm_subdevs,
 };
 
+static const struct prcm_data sun8i_a23_prcm_data = {
+	.nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs),
+	.subdevs = sun8i_a23_prcm_subdevs,
+};
+
 static const struct of_device_id sun6i_prcm_dt_ids[] = {
 	{
 		.compatible = "allwinner,sun6i-a31-prcm",
 		.data = &sun6i_a31_prcm_data,
 	},
+	{
+		.compatible = "allwinner,sun8i-a23-prcm",
+		.data = &sun8i_a23_prcm_data,
+	},
 	{ /* sentinel */ },
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/tc3589x.c linux-libre-3.17-rc7-gnu/drivers/mfd/tc3589x.c
--- linux-libre-3.16-gnu/drivers/mfd/tc3589x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/tc3589x.c	2014-09-28 17:29:07.000000000 -0400
@@ -236,7 +236,7 @@ static void tc3589x_irq_unmap(struct irq
 static struct irq_domain_ops tc3589x_irq_ops = {
 	.map    = tc3589x_irq_map,
 	.unmap  = tc3589x_irq_unmap,
-	.xlate  = irq_domain_xlate_twocell,
+	.xlate  = irq_domain_xlate_onecell,
 };
 
 static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/tc6387xb.c linux-libre-3.17-rc7-gnu/drivers/mfd/tc6387xb.c
--- linux-libre-3.16-gnu/drivers/mfd/tc6387xb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/tc6387xb.c	2014-09-28 17:29:07.000000000 -0400
@@ -147,11 +147,10 @@ static int tc6387xb_probe(struct platfor
 	int irq, ret;
 
 	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!iomem) {
+	if (!iomem)
 		return -EINVAL;
-	}
 
-	tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
+	tc6387xb = kzalloc(sizeof(*tc6387xb), GFP_KERNEL);
 	if (!tc6387xb)
 		return -ENOMEM;
 
@@ -189,7 +188,7 @@ static int tc6387xb_probe(struct platfor
 	if (pdata && pdata->enable)
 		pdata->enable(dev);
 
-	printk(KERN_INFO "Toshiba tc6387xb initialised\n");
+	dev_info(&dev->dev, "Toshiba tc6387xb initialised\n");
 
 	ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
 			      ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/tps6105x.c linux-libre-3.17-rc7-gnu/drivers/mfd/tps6105x.c
--- linux-libre-3.16-gnu/drivers/mfd/tps6105x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/tps6105x.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,7 +141,7 @@ static int tps6105x_probe(struct i2c_cli
 	int ret;
 	int i;
 
-	tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
+	tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
 	if (!tps6105x)
 		return -ENOMEM;
 
@@ -154,7 +154,7 @@ static int tps6105x_probe(struct i2c_cli
 	ret = tps6105x_startup(tps6105x);
 	if (ret) {
 		dev_err(&client->dev, "chip initialization failed\n");
-		goto fail;
+		return ret;
 	}
 
 	/* Remove warning texts when you implement new cell drivers */
@@ -187,16 +187,8 @@ static int tps6105x_probe(struct i2c_cli
 		tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
 	}
 
-	ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
-			      ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
-	if (ret)
-		goto fail;
-
-	return 0;
-
-fail:
-	kfree(tps6105x);
-	return ret;
+	return mfd_add_devices(&client->dev, 0, tps6105x_cells,
+			       ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
 }
 
 static int tps6105x_remove(struct i2c_client *client)
@@ -210,7 +202,6 @@ static int tps6105x_remove(struct i2c_cl
 		TPS6105X_REG0_MODE_MASK,
 		TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
 
-	kfree(tps6105x);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/tps65910.c linux-libre-3.17-rc7-gnu/drivers/mfd/tps65910.c
--- linux-libre-3.16-gnu/drivers/mfd/tps65910.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/tps65910.c	2014-09-28 17:29:07.000000000 -0400
@@ -387,7 +387,7 @@ static const struct of_device_id tps6591
 MODULE_DEVICE_TABLE(of, tps65910_of_match);
 
 static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
-						int *chip_id)
+						unsigned long *chip_id)
 {
 	struct device_node *np = client->dev.of_node;
 	struct tps65910_board *board_info;
@@ -401,7 +401,7 @@ static struct tps65910_board *tps65910_p
 		return NULL;
 	}
 
-	*chip_id  = (int)match->data;
+	*chip_id  = (unsigned long)match->data;
 
 	board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
 			GFP_KERNEL);
@@ -431,7 +431,7 @@ static struct tps65910_board *tps65910_p
 #else
 static inline
 struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
-					 int *chip_id)
+					 unsigned long *chip_id)
 {
 	return NULL;
 }
@@ -453,14 +453,14 @@ static void tps65910_power_off(void)
 }
 
 static int tps65910_i2c_probe(struct i2c_client *i2c,
-					const struct i2c_device_id *id)
+			      const struct i2c_device_id *id)
 {
 	struct tps65910 *tps65910;
 	struct tps65910_board *pmic_plat_data;
 	struct tps65910_board *of_pmic_plat_data = NULL;
 	struct tps65910_platform_data *init_data;
+	unsigned long chip_id = id->driver_data;
 	int ret = 0;
-	int chip_id = id->driver_data;
 
 	pmic_plat_data = dev_get_platdata(&i2c->dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/tps65912-spi.c linux-libre-3.17-rc7-gnu/drivers/mfd/tps65912-spi.c
--- linux-libre-3.16-gnu/drivers/mfd/tps65912-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/tps65912-spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,9 @@ static int tps65912_spi_write(struct tps
 	unsigned long spi_data = 1 << 23 | addr << 15 | *data;
 	struct spi_transfer xfer;
 	struct spi_message msg;
-	u32 tx_buf, rx_buf;
+	u32 tx_buf;
 
 	tx_buf = spi_data;
-	rx_buf = 0;
 
 	xfer.tx_buf	= &tx_buf;
 	xfer.rx_buf	= NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/twl4030-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/twl4030-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/twl4030-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/twl4030-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -297,7 +297,7 @@ static irqreturn_t handle_twl4030_pih(in
 	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
 			      REG_PIH_ISR_P1);
 	if (ret) {
-		pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
+		pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret);
 		return IRQ_NONE;
 	}
 
@@ -338,7 +338,7 @@ static int twl4030_init_sih_modules(unsi
 	irq_line = line;
 
 	/* disable all interrupts on our line */
-	memset(buf, 0xff, sizeof buf);
+	memset(buf, 0xff, sizeof(buf));
 	sih = sih_modules;
 	for (i = 0; i < nr_sih_modules; i++, sih++) {
 		/* skip USB -- it's funky */
@@ -646,7 +646,7 @@ int twl4030_sih_setup(struct device *dev
 	if (status < 0)
 		return status;
 
-	agent = kzalloc(sizeof *agent, GFP_KERNEL);
+	agent = kzalloc(sizeof(*agent), GFP_KERNEL);
 	if (!agent)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/twl4030-power.c linux-libre-3.17-rc7-gnu/drivers/mfd/twl4030-power.c
--- linux-libre-3.16-gnu/drivers/mfd/twl4030-power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/twl4030-power.c	2014-09-28 17:29:07.000000000 -0400
@@ -724,24 +724,24 @@ static struct twl4030_script *omap3_idle
  * above.
  */
 static struct twl4030_resconfig omap3_idle_rconfig[] = {
-	TWL_REMAP_SLEEP(RES_VAUX1, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VAUX2, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VAUX3, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VAUX4, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VMMC1, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VMMC2, DEV_GRP_NULL, 0, 0),
+	TWL_REMAP_SLEEP(RES_VAUX1, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VAUX2, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VAUX3, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VAUX4, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VMMC1, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VMMC2, TWL4030_RESCONFIG_UNDEF, 0, 0),
 	TWL_REMAP_OFF(RES_VPLL1, DEV_GRP_P1, 3, 1),
 	TWL_REMAP_SLEEP(RES_VPLL2, DEV_GRP_P1, 0, 0),
-	TWL_REMAP_SLEEP(RES_VSIM, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VDAC, DEV_GRP_NULL, 0, 0),
+	TWL_REMAP_SLEEP(RES_VSIM, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VDAC, TWL4030_RESCONFIG_UNDEF, 0, 0),
 	TWL_REMAP_SLEEP(RES_VINTANA1, TWL_DEV_GRP_P123, 1, 2),
 	TWL_REMAP_SLEEP(RES_VINTANA2, TWL_DEV_GRP_P123, 0, 2),
 	TWL_REMAP_SLEEP(RES_VINTDIG, TWL_DEV_GRP_P123, 1, 2),
 	TWL_REMAP_SLEEP(RES_VIO, TWL_DEV_GRP_P123, 2, 2),
 	TWL_REMAP_OFF(RES_VDD1, DEV_GRP_P1, 4, 1),
 	TWL_REMAP_OFF(RES_VDD2, DEV_GRP_P1, 3, 1),
-	TWL_REMAP_SLEEP(RES_VUSB_1V5, DEV_GRP_NULL, 0, 0),
-	TWL_REMAP_SLEEP(RES_VUSB_1V8, DEV_GRP_NULL, 0, 0),
+	TWL_REMAP_SLEEP(RES_VUSB_1V5, TWL4030_RESCONFIG_UNDEF, 0, 0),
+	TWL_REMAP_SLEEP(RES_VUSB_1V8, TWL4030_RESCONFIG_UNDEF, 0, 0),
 	TWL_REMAP_SLEEP(RES_VUSB_3V1, TWL_DEV_GRP_P123, 0, 0),
 	/* Resource #20 USB charge pump skipped */
 	TWL_REMAP_SLEEP(RES_REGEN, TWL_DEV_GRP_P123, 2, 1),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/twl6030-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/twl6030-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/twl6030-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/twl6030-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ static int twl6030_interrupt_mapping[24]
 	BATDETECT_INTR_OFFSET,	/* Bit 9	BAT			*/
 	SIMDETECT_INTR_OFFSET,	/* Bit 10	SIM			*/
 	MMCDETECT_INTR_OFFSET,	/* Bit 11	MMC			*/
-	RSV_INTR_OFFSET,  	/* Bit 12	Reserved		*/
+	RSV_INTR_OFFSET,	/* Bit 12	Reserved		*/
 	MADC_INTR_OFFSET,	/* Bit 13	GPADC_RT_EOC		*/
 	MADC_INTR_OFFSET,	/* Bit 14	GPADC_SW_EOC		*/
 	GASGAUGE_INTR_OFFSET,	/* Bit 15	CC_AUTOCAL		*/
@@ -245,6 +245,7 @@ int twl6030_interrupt_unmask(u8 bit_mask
 {
 	int ret;
 	u8 unmask_value;
+
 	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value,
 			REG_INT_STS_A + offset);
 	unmask_value &= (~(bit_mask));
@@ -258,6 +259,7 @@ int twl6030_interrupt_mask(u8 bit_mask,
 {
 	int ret;
 	u8 mask_value;
+
 	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value,
 			REG_INT_STS_A + offset);
 	mask_value |= (bit_mask);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/twl6040.c linux-libre-3.17-rc7-gnu/drivers/mfd/twl6040.c
--- linux-libre-3.16-gnu/drivers/mfd/twl6040.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/twl6040.c	2014-09-28 17:29:07.000000000 -0400
@@ -700,7 +700,7 @@ static int twl6040_probe(struct i2c_clie
 	}
 
 	ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
-				  0, &twl6040_irq_chip,&twl6040->irq_data);
+				  0, &twl6040_irq_chip, &twl6040->irq_data);
 	if (ret < 0)
 		goto gpio_err;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm5102-tables.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm5102-tables.c
--- linux-libre-3.16-gnu/drivers/mfd/wm5102-tables.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm5102-tables.c	2014-09-28 17:29:07.000000000 -0400
@@ -138,11 +138,11 @@ static const struct regmap_irq wm5102_ir
 		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
 	},
 
-	[ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
 	},
-	[ARIZONA_IRQ_SPK_SHUTDOWN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
 	},
 	[ARIZONA_IRQ_HPDET] = {
 		.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm5110-tables.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm5110-tables.c
--- linux-libre-3.16-gnu/drivers/mfd/wm5110-tables.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm5110-tables.c	2014-09-28 17:29:07.000000000 -0400
@@ -340,11 +340,11 @@ static const struct regmap_irq wm5110_ir
 		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
 	},
 
-	[ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
 	},
-	[ARIZONA_IRQ_SPK_SHUTDOWN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
 	},
 	[ARIZONA_IRQ_HPDET] = {
 		.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -416,16 +416,28 @@ static const struct regmap_irq wm5110_ir
 	[ARIZONA_IRQ_ISRC2_CFG_ERR] = {
 		.reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1
 	},
+	[ARIZONA_IRQ_HP3R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP3L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP2R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP2L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP1R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP1L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+	},
 
 	[ARIZONA_IRQ_BOOT_DONE] = {
 		.reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
 	},
-	[ARIZONA_IRQ_DCS_DAC_DONE] = {
-		.reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1
-	},
-	[ARIZONA_IRQ_DCS_HP_DONE] = {
-		.reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1
-	},
 	[ARIZONA_IRQ_FLL2_CLOCK_OK] = {
 		.reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
 	},
@@ -445,6 +457,209 @@ const struct regmap_irq_chip wm5110_irq
 };
 EXPORT_SYMBOL_GPL(wm5110_irq);
 
+static const struct regmap_irq wm5110_revd_irqs[ARIZONA_NUM_IRQ] = {
+	[ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 },
+	[ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 },
+	[ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
+	[ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
+
+	[ARIZONA_IRQ_DSP4_RAM_RDY] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP4_RAM_RDY_EINT1
+	},
+	[ARIZONA_IRQ_DSP3_RAM_RDY] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP3_RAM_RDY_EINT1
+	},
+	[ARIZONA_IRQ_DSP2_RAM_RDY] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP2_RAM_RDY_EINT1
+	},
+	[ARIZONA_IRQ_DSP1_RAM_RDY] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP1_RAM_RDY_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ8] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ8_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ7] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ7_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ6] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ6_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ5] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ5_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ4] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ4_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ3] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ3_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ2] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1
+	},
+	[ARIZONA_IRQ_DSP_IRQ1] = {
+		.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
+	},
+
+	[ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
+	},
+	[ARIZONA_IRQ_SPK_OVERHEAT] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
+	},
+	[ARIZONA_IRQ_HPDET] = {
+		.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
+	},
+	[ARIZONA_IRQ_MICDET] = {
+		.reg_offset = 2, .mask = ARIZONA_MICDET_EINT1
+	},
+	[ARIZONA_IRQ_WSEQ_DONE] = {
+		.reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1
+	},
+	[ARIZONA_IRQ_DRC2_SIG_DET] = {
+		.reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1
+	},
+	[ARIZONA_IRQ_DRC1_SIG_DET] = {
+		.reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1
+	},
+	[ARIZONA_IRQ_ASRC2_LOCK] = {
+		.reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1
+	},
+	[ARIZONA_IRQ_ASRC1_LOCK] = {
+		.reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1
+	},
+	[ARIZONA_IRQ_UNDERCLOCKED] = {
+		.reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1
+	},
+	[ARIZONA_IRQ_OVERCLOCKED] = {
+		.reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1
+	},
+	[ARIZONA_IRQ_FLL2_LOCK] = {
+		.reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1
+	},
+	[ARIZONA_IRQ_FLL1_LOCK] = {
+		.reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1
+	},
+	[ARIZONA_IRQ_CLKGEN_ERR] = {
+		.reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1
+	},
+	[ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = {
+		.reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1
+	},
+
+	[ARIZONA_IRQ_CTRLIF_ERR] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_CTRLIF_ERR_EINT1
+	},
+	[ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_MIXER_DROPPED_SAMPLE_EINT1
+	},
+	[ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_ASYNC_CLK_ENA_LOW_EINT1
+	},
+	[ARIZONA_IRQ_SYSCLK_ENA_LOW] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_SYSCLK_ENA_LOW_EINT1
+	},
+	[ARIZONA_IRQ_ISRC1_CFG_ERR] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_ISRC1_CFG_ERR_EINT1
+	},
+	[ARIZONA_IRQ_ISRC2_CFG_ERR] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_ISRC2_CFG_ERR_EINT1
+	},
+	[ARIZONA_IRQ_ISRC3_CFG_ERR] = {
+		.reg_offset = 3, .mask = ARIZONA_V2_ISRC3_CFG_ERR_EINT1
+	},
+	[ARIZONA_IRQ_HP3R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP3L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP2R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP2L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP1R_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+	},
+	[ARIZONA_IRQ_HP1L_DONE] = {
+		.reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+	},
+
+	[ARIZONA_IRQ_BOOT_DONE] = {
+		.reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
+	},
+	[ARIZONA_IRQ_ASRC_CFG_ERR] = {
+		.reg_offset = 4, .mask = ARIZONA_V2_ASRC_CFG_ERR_EINT1
+	},
+	[ARIZONA_IRQ_FLL2_CLOCK_OK] = {
+		.reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
+	},
+	[ARIZONA_IRQ_FLL1_CLOCK_OK] = {
+		.reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1
+	},
+
+	[ARIZONA_IRQ_DSP_SHARED_WR_COLL] = {
+		.reg_offset = 5, .mask = ARIZONA_DSP_SHARED_WR_COLL_EINT1
+	},
+	[ARIZONA_IRQ_SPK_SHUTDOWN] = {
+		.reg_offset = 5, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+	},
+	[ARIZONA_IRQ_SPK1R_SHORT] = {
+		.reg_offset = 5, .mask = ARIZONA_SPK1R_SHORT_EINT1
+	},
+	[ARIZONA_IRQ_SPK1L_SHORT] = {
+		.reg_offset = 5, .mask = ARIZONA_SPK1L_SHORT_EINT1
+	},
+	[ARIZONA_IRQ_HP3R_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP3R_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP3R_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP3R_SC_POS_EINT1
+	},
+	[ARIZONA_IRQ_HP3L_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP3L_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP3L_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP3L_SC_POS_EINT1
+	},
+	[ARIZONA_IRQ_HP2R_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP2R_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP2R_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP2R_SC_POS_EINT1
+	},
+	[ARIZONA_IRQ_HP2L_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP2L_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP2L_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP2L_SC_POS_EINT1
+	},
+	[ARIZONA_IRQ_HP1R_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP1R_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP1R_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP1R_SC_POS_EINT1
+	},
+	[ARIZONA_IRQ_HP1L_SC_NEG] = {
+		.reg_offset = 5, .mask = ARIZONA_HP1L_SC_NEG_EINT1
+	},
+	[ARIZONA_IRQ_HP1L_SC_POS] = {
+		.reg_offset = 5, .mask = ARIZONA_HP1L_SC_POS_EINT1
+	},
+};
+
+const struct regmap_irq_chip wm5110_revd_irq = {
+	.name = "wm5110 IRQ",
+	.status_base = ARIZONA_INTERRUPT_STATUS_1,
+	.mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK,
+	.ack_base = ARIZONA_INTERRUPT_STATUS_1,
+	.num_regs = 6,
+	.irqs = wm5110_revd_irqs,
+	.num_irqs = ARRAY_SIZE(wm5110_revd_irqs),
+};
+EXPORT_SYMBOL_GPL(wm5110_revd_irq);
+
 static const struct reg_default wm5110_reg_default[] = {
 	{ 0x00000008, 0x0019 },    /* R8     - Ctrl IF SPI CFG 1 */
 	{ 0x00000009, 0x0001 },    /* R9     - Ctrl IF I2C1 CFG 1 */
@@ -1274,12 +1489,14 @@ static const struct reg_default wm5110_r
 	{ 0x00000D0A, 0xFFFF },    /* R3338  - Interrupt Status 3 Mask */
 	{ 0x00000D0B, 0xFFFF },    /* R3339  - Interrupt Status 4 Mask */
 	{ 0x00000D0C, 0xFEFF },    /* R3340  - Interrupt Status 5 Mask */
+	{ 0x00000D0D, 0xFFFF },    /* R3341  - Interrupt Status 6 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 */
+	{ 0x00000D1D, 0xFFFF },    /* R3357  - IRQ2 Status 6 Mask */
 	{ 0x00000D1F, 0x0000 },    /* R3359  - IRQ2 Control */
 	{ 0x00000D53, 0xFFFF },    /* R3411  - AOD IRQ Mask IRQ1 */
 	{ 0x00000D54, 0xFFFF },    /* R3412  - AOD IRQ Mask IRQ2 */
@@ -2311,22 +2528,26 @@ static bool wm5110_readable_register(str
 	case ARIZONA_INTERRUPT_STATUS_3:
 	case ARIZONA_INTERRUPT_STATUS_4:
 	case ARIZONA_INTERRUPT_STATUS_5:
+	case ARIZONA_INTERRUPT_STATUS_6:
 	case ARIZONA_INTERRUPT_STATUS_1_MASK:
 	case ARIZONA_INTERRUPT_STATUS_2_MASK:
 	case ARIZONA_INTERRUPT_STATUS_3_MASK:
 	case ARIZONA_INTERRUPT_STATUS_4_MASK:
 	case ARIZONA_INTERRUPT_STATUS_5_MASK:
+	case ARIZONA_INTERRUPT_STATUS_6_MASK:
 	case ARIZONA_INTERRUPT_CONTROL:
 	case ARIZONA_IRQ2_STATUS_1:
 	case ARIZONA_IRQ2_STATUS_2:
 	case ARIZONA_IRQ2_STATUS_3:
 	case ARIZONA_IRQ2_STATUS_4:
 	case ARIZONA_IRQ2_STATUS_5:
+	case ARIZONA_IRQ2_STATUS_6:
 	case ARIZONA_IRQ2_STATUS_1_MASK:
 	case ARIZONA_IRQ2_STATUS_2_MASK:
 	case ARIZONA_IRQ2_STATUS_3_MASK:
 	case ARIZONA_IRQ2_STATUS_4_MASK:
 	case ARIZONA_IRQ2_STATUS_5_MASK:
+	case ARIZONA_IRQ2_STATUS_6_MASK:
 	case ARIZONA_IRQ2_CONTROL:
 	case ARIZONA_INTERRUPT_RAW_STATUS_2:
 	case ARIZONA_INTERRUPT_RAW_STATUS_3:
@@ -2335,6 +2556,7 @@ static bool wm5110_readable_register(str
 	case ARIZONA_INTERRUPT_RAW_STATUS_6:
 	case ARIZONA_INTERRUPT_RAW_STATUS_7:
 	case ARIZONA_INTERRUPT_RAW_STATUS_8:
+	case ARIZONA_INTERRUPT_RAW_STATUS_9:
 	case ARIZONA_IRQ_PIN_STATUS:
 	case ARIZONA_AOD_WKUP_AND_TRIG:
 	case ARIZONA_AOD_IRQ1:
@@ -2610,11 +2832,13 @@ static bool wm5110_volatile_register(str
 	case ARIZONA_INTERRUPT_STATUS_3:
 	case ARIZONA_INTERRUPT_STATUS_4:
 	case ARIZONA_INTERRUPT_STATUS_5:
+	case ARIZONA_INTERRUPT_STATUS_6:
 	case ARIZONA_IRQ2_STATUS_1:
 	case ARIZONA_IRQ2_STATUS_2:
 	case ARIZONA_IRQ2_STATUS_3:
 	case ARIZONA_IRQ2_STATUS_4:
 	case ARIZONA_IRQ2_STATUS_5:
+	case ARIZONA_IRQ2_STATUS_6:
 	case ARIZONA_INTERRUPT_RAW_STATUS_2:
 	case ARIZONA_INTERRUPT_RAW_STATUS_3:
 	case ARIZONA_INTERRUPT_RAW_STATUS_4:
@@ -2622,6 +2846,7 @@ static bool wm5110_volatile_register(str
 	case ARIZONA_INTERRUPT_RAW_STATUS_6:
 	case ARIZONA_INTERRUPT_RAW_STATUS_7:
 	case ARIZONA_INTERRUPT_RAW_STATUS_8:
+	case ARIZONA_INTERRUPT_RAW_STATUS_9:
 	case ARIZONA_IRQ_PIN_STATUS:
 	case ARIZONA_AOD_WKUP_AND_TRIG:
 	case ARIZONA_AOD_IRQ1:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm8350-i2c.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm8350-i2c.c
--- linux-libre-3.16-gnu/drivers/mfd/wm8350-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm8350-i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,10 +58,10 @@ static int wm8350_i2c_remove(struct i2c_
 }
 
 static const struct i2c_device_id wm8350_i2c_id[] = {
-       { "wm8350", 0 },
-       { "wm8351", 0 },
-       { "wm8352", 0 },
-       { }
+	{ "wm8350", 0 },
+	{ "wm8351", 0 },
+	{ "wm8352", 0 },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm8350-irq.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm8350-irq.c
--- linux-libre-3.16-gnu/drivers/mfd/wm8350-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm8350-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -497,7 +497,8 @@ int wm8350_irq_init(struct wm8350 *wm835
 	if (pdata && pdata->irq_base > 0)
 		irq_base = pdata->irq_base;
 
-	wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
+	wm8350->irq_base =
+		irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
 	if (wm8350->irq_base < 0) {
 		dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
 			wm8350->irq_base);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm8994-regmap.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm8994-regmap.c
--- linux-libre-3.16-gnu/drivers/mfd/wm8994-regmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm8994-regmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,14 +123,23 @@ static struct reg_default wm1811_default
 	{ 0x0402, 0x00C0 },    /* R1026 - AIF1 DAC1 Left Volume */
 	{ 0x0403, 0x00C0 },    /* R1027 - AIF1 DAC1 Right Volume */
 	{ 0x0410, 0x0000 },    /* R1040 - AIF1 ADC1 Filters */
+	{ 0x0411, 0x0000 },    /* R1041 - AIF1 ADC2 Filters */
 	{ 0x0420, 0x0200 },    /* R1056 - AIF1 DAC1 Filters (1) */
 	{ 0x0421, 0x0010 },    /* R1057 - AIF1 DAC1 Filters (2) */
+	{ 0x0422, 0x0200 },    /* R1058 - AIF1 DAC2 Filters (1) */
+	{ 0x0423, 0x0010 },    /* R1059 - AIF1 DAC2 Filters (2) */
 	{ 0x0430, 0x0068 },    /* R1072 - AIF1 DAC1 Noise Gate */
+	{ 0x0431, 0x0068 },    /* R1073 - AIF1 DAC2 Noise Gate */
 	{ 0x0440, 0x0098 },    /* R1088 - AIF1 DRC1 (1) */
 	{ 0x0441, 0x0845 },    /* R1089 - AIF1 DRC1 (2) */
 	{ 0x0442, 0x0000 },    /* R1090 - AIF1 DRC1 (3) */
 	{ 0x0443, 0x0000 },    /* R1091 - AIF1 DRC1 (4) */
 	{ 0x0444, 0x0000 },    /* R1092 - AIF1 DRC1 (5) */
+	{ 0x0450, 0x0098 },    /* R1104 - AIF1 DRC2 (1) */
+	{ 0x0451, 0x0845 },    /* R1105 - AIF1 DRC2 (2) */
+	{ 0x0452, 0x0000 },    /* R1106 - AIF1 DRC2 (3) */
+	{ 0x0453, 0x0000 },    /* R1107 - AIF1 DRC2 (4) */
+	{ 0x0454, 0x0000 },    /* R1108 - AIF1 DRC2 (5) */
 	{ 0x0480, 0x6318 },    /* R1152 - AIF1 DAC1 EQ Gains (1) */
 	{ 0x0481, 0x6300 },    /* R1153 - AIF1 DAC1 EQ Gains (2) */
 	{ 0x0482, 0x0FCA },    /* R1154 - AIF1 DAC1 EQ Band 1 A */
@@ -152,6 +161,27 @@ static struct reg_default wm1811_default
 	{ 0x0492, 0x0559 },    /* R1170 - AIF1 DAC1 EQ Band 5 B */
 	{ 0x0493, 0x4000 },    /* R1171 - AIF1 DAC1 EQ Band 5 PG */
 	{ 0x0494, 0x0000 },    /* R1172 - AIF1 DAC1 EQ Band 1 C */
+	{ 0x04A0, 0x6318 },    /* R1184 - AIF1 DAC2 EQ Gains (1) */
+	{ 0x04A1, 0x6300 },    /* R1185 - AIF1 DAC2 EQ Gains (2) */
+	{ 0x04A2, 0x0FCA },    /* R1186 - AIF1 DAC2 EQ Band 1 A */
+	{ 0x04A3, 0x0400 },    /* R1187 - AIF1 DAC2 EQ Band 1 B */
+	{ 0x04A4, 0x00D8 },    /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+	{ 0x04A5, 0x1EB5 },    /* R1189 - AIF1 DAC2 EQ Band 2 A */
+	{ 0x04A6, 0xF145 },    /* R1190 - AIF1 DAC2 EQ Band 2 B */
+	{ 0x04A7, 0x0B75 },    /* R1191 - AIF1 DAC2 EQ Band 2 C */
+	{ 0x04A8, 0x01C5 },    /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+	{ 0x04A9, 0x1C58 },    /* R1193 - AIF1 DAC2 EQ Band 3 A */
+	{ 0x04AA, 0xF373 },    /* R1194 - AIF1 DAC2 EQ Band 3 B */
+	{ 0x04AB, 0x0A54 },    /* R1195 - AIF1 DAC2 EQ Band 3 C */
+	{ 0x04AC, 0x0558 },    /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+	{ 0x04AD, 0x168E },    /* R1197 - AIF1 DAC2 EQ Band 4 A */
+	{ 0x04AE, 0xF829 },    /* R1198 - AIF1 DAC2 EQ Band 4 B */
+	{ 0x04AF, 0x07AD },    /* R1199 - AIF1 DAC2 EQ Band 4 C */
+	{ 0x04B0, 0x1103 },    /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+	{ 0x04B1, 0x0564 },    /* R1201 - AIF1 DAC2 EQ Band 5 A */
+	{ 0x04B2, 0x0559 },    /* R1202 - AIF1 DAC2 EQ Band 5 B */
+	{ 0x04B3, 0x4000 },    /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+	{ 0x04B4, 0x0000 },    /* R1204 - AIF1 DAC2 EQ Band 1 C */
 	{ 0x0500, 0x00C0 },    /* R1280 - AIF2 ADC Left Volume */
 	{ 0x0501, 0x00C0 },    /* R1281 - AIF2 ADC Right Volume */
 	{ 0x0502, 0x00C0 },    /* R1282 - AIF2 DAC Left Volume */
@@ -194,6 +224,8 @@ static struct reg_default wm1811_default
 	{ 0x0605, 0x0000 },    /* R1541 - AIF2ADC Right Mixer Routing */
 	{ 0x0606, 0x0000 },    /* R1542 - AIF1 ADC1 Left Mixer Routing */
 	{ 0x0607, 0x0000 },    /* R1543 - AIF1 ADC1 Right Mixer Routing */
+	{ 0x0608, 0x0000 },    /* R1544 - AIF1 ADC2 Left Mixer Routing */
+	{ 0x0609, 0x0000 },    /* R1545 - AIF1 ADC2 Right Mixer Routing */
 	{ 0x0610, 0x02C0 },    /* R1552 - DAC1 Left Volume */
 	{ 0x0611, 0x02C0 },    /* R1553 - DAC1 Right Volume */
 	{ 0x0612, 0x02C0 },    /* R1554 - AIF2TX Left Volume */
@@ -846,14 +878,23 @@ static bool wm1811_readable_register(str
 	case WM8994_AIF1_DAC1_LEFT_VOLUME:
 	case WM8994_AIF1_DAC1_RIGHT_VOLUME:
 	case WM8994_AIF1_ADC1_FILTERS:
+	case WM8994_AIF1_ADC2_FILTERS:
 	case WM8994_AIF1_DAC1_FILTERS_1:
 	case WM8994_AIF1_DAC1_FILTERS_2:
+	case WM8994_AIF1_DAC2_FILTERS_1:
+	case WM8994_AIF1_DAC2_FILTERS_2:
 	case WM8958_AIF1_DAC1_NOISE_GATE:
+	case WM8958_AIF1_DAC2_NOISE_GATE:
 	case WM8994_AIF1_DRC1_1:
 	case WM8994_AIF1_DRC1_2:
 	case WM8994_AIF1_DRC1_3:
 	case WM8994_AIF1_DRC1_4:
 	case WM8994_AIF1_DRC1_5:
+	case WM8994_AIF1_DRC2_1:
+	case WM8994_AIF1_DRC2_2:
+	case WM8994_AIF1_DRC2_3:
+	case WM8994_AIF1_DRC2_4:
+	case WM8994_AIF1_DRC2_5:
 	case WM8994_AIF1_DAC1_EQ_GAINS_1:
 	case WM8994_AIF1_DAC1_EQ_GAINS_2:
 	case WM8994_AIF1_DAC1_EQ_BAND_1_A:
@@ -875,6 +916,27 @@ static bool wm1811_readable_register(str
 	case WM8994_AIF1_DAC1_EQ_BAND_5_B:
 	case WM8994_AIF1_DAC1_EQ_BAND_5_PG:
 	case WM8994_AIF1_DAC1_EQ_BAND_1_C:
+	case WM8994_AIF1_DAC2_EQ_GAINS_1:
+	case WM8994_AIF1_DAC2_EQ_GAINS_2:
+	case WM8994_AIF1_DAC2_EQ_BAND_1_A:
+	case WM8994_AIF1_DAC2_EQ_BAND_1_B:
+	case WM8994_AIF1_DAC2_EQ_BAND_1_PG:
+	case WM8994_AIF1_DAC2_EQ_BAND_2_A:
+	case WM8994_AIF1_DAC2_EQ_BAND_2_B:
+	case WM8994_AIF1_DAC2_EQ_BAND_2_C:
+	case WM8994_AIF1_DAC2_EQ_BAND_2_PG:
+	case WM8994_AIF1_DAC2_EQ_BAND_3_A:
+	case WM8994_AIF1_DAC2_EQ_BAND_3_B:
+	case WM8994_AIF1_DAC2_EQ_BAND_3_C:
+	case WM8994_AIF1_DAC2_EQ_BAND_3_PG:
+	case WM8994_AIF1_DAC2_EQ_BAND_4_A:
+	case WM8994_AIF1_DAC2_EQ_BAND_4_B:
+	case WM8994_AIF1_DAC2_EQ_BAND_4_C:
+	case WM8994_AIF1_DAC2_EQ_BAND_4_PG:
+	case WM8994_AIF1_DAC2_EQ_BAND_5_A:
+	case WM8994_AIF1_DAC2_EQ_BAND_5_B:
+	case WM8994_AIF1_DAC2_EQ_BAND_5_PG:
+	case WM8994_AIF1_DAC2_EQ_BAND_1_C:
 	case WM8994_AIF2_ADC_LEFT_VOLUME:
 	case WM8994_AIF2_ADC_RIGHT_VOLUME:
 	case WM8994_AIF2_DAC_LEFT_VOLUME:
@@ -917,6 +979,8 @@ static bool wm1811_readable_register(str
 	case WM8994_DAC2_RIGHT_MIXER_ROUTING:
 	case WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING:
 	case WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+	case WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING:
+	case WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING:
 	case WM8994_DAC1_LEFT_VOLUME:
 	case WM8994_DAC1_RIGHT_VOLUME:
 	case WM8994_DAC2_LEFT_VOLUME:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mfd/wm8997-tables.c linux-libre-3.17-rc7-gnu/drivers/mfd/wm8997-tables.c
--- linux-libre-3.16-gnu/drivers/mfd/wm8997-tables.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mfd/wm8997-tables.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,11 +65,11 @@ static const struct regmap_irq wm8997_ir
 	[ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
 	[ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
 
-	[ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
 	},
-	[ARIZONA_IRQ_SPK_SHUTDOWN] = {
-		.reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+	[ARIZONA_IRQ_SPK_OVERHEAT] = {
+		.reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
 	},
 	[ARIZONA_IRQ_HPDET] = {
 		.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -174,10 +174,10 @@ static const struct reg_default wm8997_r
 	{ 0x00000062, 0x01FF },    /* R98    - Sample Rate Sequence Select 2 */
 	{ 0x00000063, 0x01FF },    /* R99    - Sample Rate Sequence Select 3 */
 	{ 0x00000064, 0x01FF },    /* R100   - Sample Rate Sequence Select 4 */
-	{ 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 */
+	{ 0x00000068, 0x01FF },    /* R104   - AlwaysOn Triggers Seq Select 3 */
+	{ 0x00000069, 0x01FF },    /* R105   - AlwaysOn Triggers Seq Select 4 */
+	{ 0x0000006A, 0x01FF },    /* R106   - AlwaysOn Triggers Seq Select 5 */
+	{ 0x0000006B, 0x01FF },    /* R107   - AlwaysOn Triggers Seq Select 6 */
 	{ 0x00000070, 0x0000 },    /* R112   - Comfort Noise Generator */
 	{ 0x00000090, 0x0000 },    /* R144   - Haptics Control 1 */
 	{ 0x00000091, 0x7FFF },    /* R145   - Haptics Control 2 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/atmel_pwm.c linux-libre-3.17-rc7-gnu/drivers/misc/atmel_pwm.c
--- linux-libre-3.16-gnu/drivers/misc/atmel_pwm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/atmel_pwm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,402 +0,0 @@
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/atmel_pwm.h>
-
-
-/*
- * This is a simple driver for the PWM controller found in various newer
- * Atmel SOCs, including the AVR32 series and the AT91sam9263.
- *
- * Chips with current Linux ports have only 4 PWM channels, out of max 32.
- * AT32UC3A and AT32UC3B chips have 7 channels (but currently no Linux).
- * Docs are inconsistent about the width of the channel counter registers;
- * it's at least 16 bits, but several places say 20 bits.
- */
-#define	PWM_NCHAN	4		/* max 32 */
-
-struct pwm {
-	spinlock_t		lock;
-	struct platform_device	*pdev;
-	u32			mask;
-	int			irq;
-	void __iomem		*base;
-	struct clk		*clk;
-	struct pwm_channel	*channel[PWM_NCHAN];
-	void			(*handler[PWM_NCHAN])(struct pwm_channel *);
-};
-
-
-/* global PWM controller registers */
-#define PWM_MR		0x00
-#define PWM_ENA		0x04
-#define PWM_DIS		0x08
-#define PWM_SR		0x0c
-#define PWM_IER		0x10
-#define PWM_IDR		0x14
-#define PWM_IMR		0x18
-#define PWM_ISR		0x1c
-
-static inline void pwm_writel(const struct pwm *p, unsigned offset, u32 val)
-{
-	__raw_writel(val, p->base + offset);
-}
-
-static inline u32 pwm_readl(const struct pwm *p, unsigned offset)
-{
-	return __raw_readl(p->base + offset);
-}
-
-static inline void __iomem *pwmc_regs(const struct pwm *p, int index)
-{
-	return p->base + 0x200 + index * 0x20;
-}
-
-static struct pwm *pwm;
-
-static void pwm_dumpregs(struct pwm_channel *ch, char *tag)
-{
-	struct device	*dev = &pwm->pdev->dev;
-
-	dev_dbg(dev, "%s: mr %08x, sr %08x, imr %08x\n",
-		tag,
-		pwm_readl(pwm, PWM_MR),
-		pwm_readl(pwm, PWM_SR),
-		pwm_readl(pwm, PWM_IMR));
-	dev_dbg(dev,
-		"pwm ch%d - mr %08x, dty %u, prd %u, cnt %u\n",
-		ch->index,
-		pwm_channel_readl(ch, PWM_CMR),
-		pwm_channel_readl(ch, PWM_CDTY),
-		pwm_channel_readl(ch, PWM_CPRD),
-		pwm_channel_readl(ch, PWM_CCNT));
-}
-
-
-/**
- * pwm_channel_alloc - allocate an unused PWM channel
- * @index: identifies the channel
- * @ch: structure to be initialized
- *
- * Drivers allocate PWM channels according to the board's wiring, and
- * matching board-specific setup code.  Returns zero or negative errno.
- */
-int pwm_channel_alloc(int index, struct pwm_channel *ch)
-{
-	unsigned long	flags;
-	int		status = 0;
-
-	if (!pwm)
-		return -EPROBE_DEFER;
-
-	if (!(pwm->mask & 1 << index))
-		return -ENODEV;
-
-	if (index < 0 || index >= PWM_NCHAN || !ch)
-		return -EINVAL;
-	memset(ch, 0, sizeof *ch);
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	if (pwm->channel[index])
-		status = -EBUSY;
-	else {
-		clk_enable(pwm->clk);
-
-		ch->regs = pwmc_regs(pwm, index);
-		ch->index = index;
-
-		/* REVISIT: ap7000 seems to go 2x as fast as we expect!! */
-		ch->mck = clk_get_rate(pwm->clk);
-
-		pwm->channel[index] = ch;
-		pwm->handler[index] = NULL;
-
-		/* channel and irq are always disabled when we return */
-		pwm_writel(pwm, PWM_DIS, 1 << index);
-		pwm_writel(pwm, PWM_IDR, 1 << index);
-	}
-	spin_unlock_irqrestore(&pwm->lock, flags);
-	return status;
-}
-EXPORT_SYMBOL(pwm_channel_alloc);
-
-static int pwmcheck(struct pwm_channel *ch)
-{
-	int		index;
-
-	if (!pwm)
-		return -ENODEV;
-	if (!ch)
-		return -EINVAL;
-	index = ch->index;
-	if (index < 0 || index >= PWM_NCHAN || pwm->channel[index] != ch)
-		return -EINVAL;
-
-	return index;
-}
-
-/**
- * pwm_channel_free - release a previously allocated channel
- * @ch: the channel being released
- *
- * The channel is completely shut down (counter and IRQ disabled),
- * and made available for re-use.  Returns zero, or negative errno.
- */
-int pwm_channel_free(struct pwm_channel *ch)
-{
-	unsigned long	flags;
-	int		t;
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	t = pwmcheck(ch);
-	if (t >= 0) {
-		pwm->channel[t] = NULL;
-		pwm->handler[t] = NULL;
-
-		/* channel and irq are always disabled when we return */
-		pwm_writel(pwm, PWM_DIS, 1 << t);
-		pwm_writel(pwm, PWM_IDR, 1 << t);
-
-		clk_disable(pwm->clk);
-		t = 0;
-	}
-	spin_unlock_irqrestore(&pwm->lock, flags);
-	return t;
-}
-EXPORT_SYMBOL(pwm_channel_free);
-
-int __pwm_channel_onoff(struct pwm_channel *ch, int enabled)
-{
-	unsigned long	flags;
-	int		t;
-
-	/* OMITTED FUNCTIONALITY:  starting several channels in synch */
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	t = pwmcheck(ch);
-	if (t >= 0) {
-		pwm_writel(pwm, enabled ? PWM_ENA : PWM_DIS, 1 << t);
-		t = 0;
-		pwm_dumpregs(ch, enabled ? "enable" : "disable");
-	}
-	spin_unlock_irqrestore(&pwm->lock, flags);
-
-	return t;
-}
-EXPORT_SYMBOL(__pwm_channel_onoff);
-
-/**
- * pwm_clk_alloc - allocate and configure CLKA or CLKB
- * @prescale: from 0..10, the power of two used to divide MCK
- * @div: from 1..255, the linear divisor to use
- *
- * Returns PWM_CPR_CLKA, PWM_CPR_CLKB, or negative errno.  The allocated
- * clock will run with a period of (2^prescale * div) / MCK, or twice as
- * long if center aligned PWM output is used.  The clock must later be
- * deconfigured using pwm_clk_free().
- */
-int pwm_clk_alloc(unsigned prescale, unsigned div)
-{
-	unsigned long	flags;
-	u32		mr;
-	u32		val = (prescale << 8) | div;
-	int		ret = -EBUSY;
-
-	if (prescale >= 10 || div == 0 || div > 255)
-		return -EINVAL;
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	mr = pwm_readl(pwm, PWM_MR);
-	if ((mr & 0xffff) == 0) {
-		mr |= val;
-		ret = PWM_CPR_CLKA;
-	} else if ((mr & (0xffff << 16)) == 0) {
-		mr |= val << 16;
-		ret = PWM_CPR_CLKB;
-	}
-	if (ret > 0)
-		pwm_writel(pwm, PWM_MR, mr);
-	spin_unlock_irqrestore(&pwm->lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(pwm_clk_alloc);
-
-/**
- * pwm_clk_free - deconfigure and release CLKA or CLKB
- *
- * Reverses the effect of pwm_clk_alloc().
- */
-void pwm_clk_free(unsigned clk)
-{
-	unsigned long	flags;
-	u32		mr;
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	mr = pwm_readl(pwm, PWM_MR);
-	if (clk == PWM_CPR_CLKA)
-		pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 0));
-	if (clk == PWM_CPR_CLKB)
-		pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 16));
-	spin_unlock_irqrestore(&pwm->lock, flags);
-}
-EXPORT_SYMBOL(pwm_clk_free);
-
-/**
- * pwm_channel_handler - manage channel's IRQ handler
- * @ch: the channel
- * @handler: the handler to use, possibly NULL
- *
- * If the handler is non-null, the handler will be called after every
- * period of this PWM channel.  If the handler is null, this channel
- * won't generate an IRQ.
- */
-int pwm_channel_handler(struct pwm_channel *ch,
-		void (*handler)(struct pwm_channel *ch))
-{
-	unsigned long	flags;
-	int		t;
-
-	spin_lock_irqsave(&pwm->lock, flags);
-	t = pwmcheck(ch);
-	if (t >= 0) {
-		pwm->handler[t] = handler;
-		pwm_writel(pwm, handler ? PWM_IER : PWM_IDR, 1 << t);
-		t = 0;
-	}
-	spin_unlock_irqrestore(&pwm->lock, flags);
-
-	return t;
-}
-EXPORT_SYMBOL(pwm_channel_handler);
-
-static irqreturn_t pwm_irq(int id, void *_pwm)
-{
-	struct pwm	*p = _pwm;
-	irqreturn_t	handled = IRQ_NONE;
-	u32		irqstat;
-	int		index;
-
-	spin_lock(&p->lock);
-
-	/* ack irqs, then handle them */
-	irqstat = pwm_readl(pwm, PWM_ISR);
-
-	while (irqstat) {
-		struct pwm_channel *ch;
-		void (*handler)(struct pwm_channel *ch);
-
-		index = ffs(irqstat) - 1;
-		irqstat &= ~(1 << index);
-		ch = pwm->channel[index];
-		handler = pwm->handler[index];
-		if (handler && ch) {
-			spin_unlock(&p->lock);
-			handler(ch);
-			spin_lock(&p->lock);
-			handled = IRQ_HANDLED;
-		}
-	}
-
-	spin_unlock(&p->lock);
-	return handled;
-}
-
-static int __init pwm_probe(struct platform_device *pdev)
-{
-	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int irq = platform_get_irq(pdev, 0);
-	u32 *mp = pdev->dev.platform_data;
-	struct pwm *p;
-	int status = -EIO;
-
-	if (pwm)
-		return -EBUSY;
-	if (!r || irq < 0 || !mp || !*mp)
-		return -ENODEV;
-	if (*mp & ~((1<<PWM_NCHAN)-1)) {
-		dev_warn(&pdev->dev, "mask 0x%x ... more than %d channels\n",
-			*mp, PWM_NCHAN);
-		return -EINVAL;
-	}
-
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-
-	spin_lock_init(&p->lock);
-	p->pdev = pdev;
-	p->mask = *mp;
-	p->irq = irq;
-	p->base = ioremap(r->start, resource_size(r));
-	if (!p->base)
-		goto fail;
-	p->clk = clk_get(&pdev->dev, "pwm_clk");
-	if (IS_ERR(p->clk)) {
-		status = PTR_ERR(p->clk);
-		p->clk = NULL;
-		goto fail;
-	}
-
-	status = request_irq(irq, pwm_irq, 0, pdev->name, p);
-	if (status < 0)
-		goto fail;
-
-	pwm = p;
-	platform_set_drvdata(pdev, p);
-
-	return 0;
-
-fail:
-	if (p->clk)
-		clk_put(p->clk);
-	if (p->base)
-		iounmap(p->base);
-
-	kfree(p);
-	return status;
-}
-
-static int __exit pwm_remove(struct platform_device *pdev)
-{
-	struct pwm *p = platform_get_drvdata(pdev);
-
-	if (p != pwm)
-		return -EINVAL;
-
-	clk_enable(pwm->clk);
-	pwm_writel(pwm, PWM_DIS, (1 << PWM_NCHAN) - 1);
-	pwm_writel(pwm, PWM_IDR, (1 << PWM_NCHAN) - 1);
-	clk_disable(pwm->clk);
-
-	pwm = NULL;
-
-	free_irq(p->irq, p);
-	clk_put(p->clk);
-	iounmap(p->base);
-	kfree(p);
-
-	return 0;
-}
-
-static struct platform_driver atmel_pwm_driver = {
-	.driver = {
-		.name = "atmel_pwm",
-		.owner = THIS_MODULE,
-	},
-	.remove = __exit_p(pwm_remove),
-
-	/* NOTE: PWM can keep running in AVR32 "idle" and "frozen" states;
-	 * and all AT91sam9263 states, albeit at reduced clock rate if
-	 * MCK becomes the slow clock (i.e. what Linux labels STR).
-	 */
-};
-
-module_platform_driver_probe(atmel_pwm_driver, pwm_probe);
-
-MODULE_DESCRIPTION("Driver for AT32/AT91 PWM module");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_pwm");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/atmel-ssc.c linux-libre-3.17-rc7-gnu/drivers/misc/atmel-ssc.c
--- linux-libre-3.16-gnu/drivers/misc/atmel-ssc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/atmel-ssc.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,10 +83,17 @@ EXPORT_SYMBOL(ssc_free);
 
 static struct atmel_ssc_platform_data at91rm9200_config = {
 	.use_dma = 0,
+	.has_fslen_ext = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9rl_config = {
+	.use_dma = 0,
+	.has_fslen_ext = 1,
 };
 
 static struct atmel_ssc_platform_data at91sam9g45_config = {
 	.use_dma = 1,
+	.has_fslen_ext = 1,
 };
 
 static const struct platform_device_id atmel_ssc_devtypes[] = {
@@ -94,6 +101,9 @@ static const struct platform_device_id a
 		.name = "at91rm9200_ssc",
 		.driver_data = (unsigned long) &at91rm9200_config,
 	}, {
+		.name = "at91sam9rl_ssc",
+		.driver_data = (unsigned long) &at91sam9rl_config,
+	}, {
 		.name = "at91sam9g45_ssc",
 		.driver_data = (unsigned long) &at91sam9g45_config,
 	}, {
@@ -107,6 +117,9 @@ static const struct of_device_id atmel_s
 		.compatible = "atmel,at91rm9200-ssc",
 		.data = &at91rm9200_config,
 	}, {
+		.compatible = "atmel,at91sam9rl-ssc",
+		.data = &at91sam9rl_config,
+	}, {
 		.compatible = "atmel,at91sam9g45-ssc",
 		.data = &at91sam9g45_config,
 	}, {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/bh1770glc.c linux-libre-3.17-rc7-gnu/drivers/misc/bh1770glc.c
--- linux-libre-3.16-gnu/drivers/misc/bh1770glc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/bh1770glc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1185,7 +1185,7 @@ static int bh1770_probe(struct i2c_clien
 	struct bh1770_chip *chip;
 	int err;
 
-	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	chip = devm_kzalloc(&client->dev, sizeof *chip, GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
@@ -1198,8 +1198,7 @@ static int bh1770_probe(struct i2c_clien
 
 	if (client->dev.platform_data == NULL) {
 		dev_err(&client->dev, "platform data is mandatory\n");
-		err = -EINVAL;
-		goto fail1;
+		return -EINVAL;
 	}
 
 	chip->pdata		= client->dev.platform_data;
@@ -1224,24 +1223,24 @@ static int bh1770_probe(struct i2c_clien
 	chip->regs[0].supply = reg_vcc;
 	chip->regs[1].supply = reg_vleds;
 
-	err = regulator_bulk_get(&client->dev,
-				 ARRAY_SIZE(chip->regs), chip->regs);
+	err = devm_regulator_bulk_get(&client->dev,
+				      ARRAY_SIZE(chip->regs), chip->regs);
 	if (err < 0) {
 		dev_err(&client->dev, "Cannot get regulators\n");
-		goto fail1;
+		return err;
 	}
 
 	err = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
 				chip->regs);
 	if (err < 0) {
 		dev_err(&client->dev, "Cannot enable regulators\n");
-		goto fail2;
+		return err;
 	}
 
 	usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
 	err = bh1770_detect(chip);
 	if (err < 0)
-		goto fail3;
+		goto fail0;
 
 	/* Start chip */
 	bh1770_chip_on(chip);
@@ -1252,14 +1251,14 @@ static int bh1770_probe(struct i2c_clien
 	if (chip->lux_corr == 0) {
 		dev_err(&client->dev, "Improper correction values\n");
 		err = -EINVAL;
-		goto fail3;
+		goto fail0;
 	}
 
 	if (chip->pdata->setup_resources) {
 		err = chip->pdata->setup_resources();
 		if (err) {
 			err = -EINVAL;
-			goto fail3;
+			goto fail0;
 		}
 	}
 
@@ -1267,7 +1266,7 @@ static int bh1770_probe(struct i2c_clien
 				&bh1770_attribute_group);
 	if (err < 0) {
 		dev_err(&chip->client->dev, "Sysfs registration failed\n");
-		goto fail4;
+		goto fail1;
 	}
 
 	/*
@@ -1283,22 +1282,18 @@ static int bh1770_probe(struct i2c_clien
 	if (err) {
 		dev_err(&client->dev, "could not get IRQ %d\n",
 			client->irq);
-		goto fail5;
+		goto fail2;
 	}
 	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
 	return err;
-fail5:
+fail2:
 	sysfs_remove_group(&chip->client->dev.kobj,
 			&bh1770_attribute_group);
-fail4:
+fail1:
 	if (chip->pdata->release_resources)
 		chip->pdata->release_resources();
-fail3:
+fail0:
 	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
-fail2:
-	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
-fail1:
-	kfree(chip);
 	return err;
 }
 
@@ -1322,8 +1317,6 @@ static int bh1770_remove(struct i2c_clie
 	pm_runtime_disable(&client->dev);
 	pm_runtime_set_suspended(&client->dev);
 
-	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
-	kfree(chip);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/bh1780gli.c linux-libre-3.17-rc7-gnu/drivers/misc/bh1780gli.c
--- linux-libre-3.16-gnu/drivers/misc/bh1780gli.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/bh1780gli.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,50 +149,35 @@ static int bh1780_probe(struct i2c_clien
 						const struct i2c_device_id *id)
 {
 	int ret;
-	struct bh1780_data *ddata = NULL;
+	struct bh1780_data *ddata;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
-		ret = -EIO;
-		goto err_op_failed;
-	}
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+		return -EIO;
 
-	ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL);
-	if (ddata == NULL) {
-		ret = -ENOMEM;
-		goto err_op_failed;
-	}
+	ddata = devm_kzalloc(&client->dev, sizeof(struct bh1780_data),
+			     GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
 
 	ddata->client = client;
 	i2c_set_clientdata(client, ddata);
 
 	ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID");
 	if (ret < 0)
-		goto err_op_failed;
+		return ret;
 
 	dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n",
 			(ret & BH1780_REVMASK));
 
 	mutex_init(&ddata->lock);
 
-	ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
-	if (ret)
-		goto err_op_failed;
-
-	return 0;
-
-err_op_failed:
-	kfree(ddata);
-	return ret;
+	return sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
 }
 
 static int bh1780_remove(struct i2c_client *client)
 {
-	struct bh1780_data *ddata;
-
-	ddata = i2c_get_clientdata(client);
 	sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
-	kfree(ddata);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/carma/carma-fpga.c linux-libre-3.17-rc7-gnu/drivers/misc/carma/carma-fpga.c
--- linux-libre-3.16-gnu/drivers/misc/carma/carma-fpga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/carma/carma-fpga.c	2014-09-28 17:29:07.000000000 -0400
@@ -954,10 +954,7 @@ static int data_debugfs_init(struct fpga
 {
 	priv->dbg_entry = debugfs_create_file(drv_name, S_IRUGO, NULL, priv,
 					      &data_debug_fops);
-	if (IS_ERR(priv->dbg_entry))
-		return PTR_ERR(priv->dbg_entry);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(priv->dbg_entry);
 }
 
 static void data_debugfs_exit(struct fpga_device *priv)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/dummy-irq.c linux-libre-3.17-rc7-gnu/drivers/misc/dummy-irq.c
--- linux-libre-3.16-gnu/drivers/misc/dummy-irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/dummy-irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,3 +61,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jiri Kosina");
 module_param(irq, uint, 0444);
 MODULE_PARM_DESC(irq, "The IRQ to register for");
+MODULE_DESCRIPTION("Dummy IRQ handler driver");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/fuse/Makefile linux-libre-3.17-rc7-gnu/drivers/misc/fuse/Makefile
--- linux-libre-3.16-gnu/drivers/misc/fuse/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/misc/fuse/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_base.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_base.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,6 @@
 #include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/log2.h>
-#include <linux/genwqe/genwqe_card.h>
 
 #include "card_base.h"
 #include "card_ddcb.h"
@@ -58,7 +57,7 @@ static struct dentry *debugfs_genwqe;
 static struct genwqe_dev *genwqe_devices[GENWQE_CARD_NO_MAX];
 
 /* PCI structure for identifying device by PCI vendor and device ID */
-static DEFINE_PCI_DEVICE_TABLE(genwqe_device_table) = {
+static const struct pci_device_id genwqe_device_table[] = {
 	{ .vendor      = PCI_VENDOR_ID_IBM,
 	  .device      = PCI_DEVICE_GENWQE,
 	  .subvendor   = PCI_SUBVENDOR_ID_IBM,
@@ -140,6 +139,12 @@ static struct genwqe_dev *genwqe_dev_all
 	cd->class_genwqe = class_genwqe;
 	cd->debugfs_genwqe = debugfs_genwqe;
 
+	/*
+	 * This comes from kernel config option and can be overritten via
+	 * debugfs.
+	 */
+	cd->use_platform_recovery = CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY;
+
 	init_waitqueue_head(&cd->queue_waitq);
 
 	spin_lock_init(&cd->file_lock);
@@ -761,6 +766,124 @@ static u64 genwqe_fir_checking(struct ge
 }
 
 /**
+ * genwqe_pci_fundamental_reset() - trigger a PCIe fundamental reset on the slot
+ *
+ * Note: pci_set_pcie_reset_state() is not implemented on all archs, so this
+ * reset method will not work in all cases.
+ *
+ * Return: 0 on success or error code from pci_set_pcie_reset_state()
+ */
+static int genwqe_pci_fundamental_reset(struct pci_dev *pci_dev)
+{
+	int rc;
+
+	/*
+	 * lock pci config space access from userspace,
+	 * save state and issue PCIe fundamental reset
+	 */
+	pci_cfg_access_lock(pci_dev);
+	pci_save_state(pci_dev);
+	rc = pci_set_pcie_reset_state(pci_dev, pcie_warm_reset);
+	if (!rc) {
+		/* keep PCIe reset asserted for 250ms */
+		msleep(250);
+		pci_set_pcie_reset_state(pci_dev, pcie_deassert_reset);
+		/* Wait for 2s to reload flash and train the link */
+		msleep(2000);
+	}
+	pci_restore_state(pci_dev);
+	pci_cfg_access_unlock(pci_dev);
+	return rc;
+}
+
+
+static int genwqe_platform_recovery(struct genwqe_dev *cd)
+{
+	struct pci_dev *pci_dev = cd->pci_dev;
+	int rc;
+
+	dev_info(&pci_dev->dev,
+		 "[%s] resetting card for error recovery\n", __func__);
+
+	/* Clear out error injection flags */
+	cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE |
+			    GENWQE_INJECT_GFIR_FATAL |
+			    GENWQE_INJECT_GFIR_INFO);
+
+	genwqe_stop(cd);
+
+	/* Try recoverying the card with fundamental reset */
+	rc = genwqe_pci_fundamental_reset(pci_dev);
+	if (!rc) {
+		rc = genwqe_start(cd);
+		if (!rc)
+			dev_info(&pci_dev->dev,
+				 "[%s] card recovered\n", __func__);
+		else
+			dev_err(&pci_dev->dev,
+				"[%s] err: cannot start card services! (err=%d)\n",
+				__func__, rc);
+	} else {
+		dev_err(&pci_dev->dev,
+			"[%s] card reset failed\n", __func__);
+	}
+
+	return rc;
+}
+
+/*
+ * genwqe_reload_bistream() - reload card bitstream
+ *
+ * Set the appropriate register and call fundamental reset to reaload the card
+ * bitstream.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int genwqe_reload_bistream(struct genwqe_dev *cd)
+{
+	struct pci_dev *pci_dev = cd->pci_dev;
+	int rc;
+
+	dev_info(&pci_dev->dev,
+		 "[%s] resetting card for bitstream reload\n",
+		 __func__);
+
+	genwqe_stop(cd);
+
+	/*
+	 * Cause a CPLD reprogram with the 'next_bitstream'
+	 * partition on PCIe hot or fundamental reset
+	 */
+	__genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET,
+			(cd->softreset & 0xcull) | 0x70ull);
+
+	rc = genwqe_pci_fundamental_reset(pci_dev);
+	if (rc) {
+		/*
+		 * A fundamental reset failure can be caused
+		 * by lack of support on the arch, so we just
+		 * log the error and try to start the card
+		 * again.
+		 */
+		dev_err(&pci_dev->dev,
+			"[%s] err: failed to reset card for bitstream reload\n",
+			__func__);
+	}
+
+	rc = genwqe_start(cd);
+	if (rc) {
+		dev_err(&pci_dev->dev,
+			"[%s] err: cannot start card services! (err=%d)\n",
+			__func__, rc);
+		return rc;
+	}
+	dev_info(&pci_dev->dev,
+		 "[%s] card reloaded\n", __func__);
+	return 0;
+}
+
+
+/**
  * genwqe_health_thread() - Health checking thread
  *
  * This thread is only started for the PF of the card.
@@ -786,6 +909,7 @@ static int genwqe_health_thread(void *da
 	struct pci_dev *pci_dev = cd->pci_dev;
 	u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg;
 
+ health_thread_begin:
 	while (!kthread_should_stop()) {
 		rc = wait_event_interruptible_timeout(cd->health_waitq,
 			 (genwqe_health_check_cond(cd, &gfir) ||
@@ -846,6 +970,13 @@ static int genwqe_health_thread(void *da
 			}
 		}
 
+		if (cd->card_state == GENWQE_CARD_RELOAD_BITSTREAM) {
+			/* Userspace requested card bitstream reload */
+			rc = genwqe_reload_bistream(cd);
+			if (rc)
+				goto fatal_error;
+		}
+
 		cd->last_gfir = gfir;
 		cond_resched();
 	}
@@ -853,6 +984,28 @@ static int genwqe_health_thread(void *da
 	return 0;
 
  fatal_error:
+	if (cd->use_platform_recovery) {
+		/*
+		 * Since we use raw accessors, EEH errors won't be detected
+		 * by the platform until we do a non-raw MMIO or config space
+		 * read
+		 */
+		readq(cd->mmio + IO_SLC_CFGREG_GFIR);
+
+		/* We do nothing if the card is going over PCI recovery */
+		if (pci_channel_offline(pci_dev))
+			return -EIO;
+
+		/*
+		 * If it's supported by the platform, we try a fundamental reset
+		 * to recover from a fatal error. Otherwise, we continue to wait
+		 * for an external recovery procedure to take care of it.
+		 */
+		rc = genwqe_platform_recovery(cd);
+		if (!rc)
+			goto health_thread_begin;
+	}
+
 	dev_err(&pci_dev->dev,
 		"[%s] card unusable. Please trigger unbind!\n", __func__);
 
@@ -958,6 +1111,9 @@ static int genwqe_pci_setup(struct genwq
 	pci_set_master(pci_dev);
 	pci_enable_pcie_error_reporting(pci_dev);
 
+	/* EEH recovery requires PCIe fundamental reset */
+	pci_dev->needs_freset = 1;
+
 	/* request complete BAR-0 space (length = 0) */
 	cd->mmio_len = pci_resource_len(pci_dev, 0);
 	cd->mmio = pci_iomap(pci_dev, 0, 0);
@@ -1096,23 +1252,40 @@ static pci_ers_result_t genwqe_err_error
 
 	dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state);
 
-	if (pci_dev == NULL)
-		return PCI_ERS_RESULT_NEED_RESET;
-
 	cd = dev_get_drvdata(&pci_dev->dev);
 	if (cd == NULL)
-		return PCI_ERS_RESULT_NEED_RESET;
+		return PCI_ERS_RESULT_DISCONNECT;
 
-	switch (state) {
-	case pci_channel_io_normal:
-		return PCI_ERS_RESULT_CAN_RECOVER;
-	case pci_channel_io_frozen:
-		return PCI_ERS_RESULT_NEED_RESET;
-	case pci_channel_io_perm_failure:
+	/* Stop the card */
+	genwqe_health_check_stop(cd);
+	genwqe_stop(cd);
+
+	/*
+	 * On permanent failure, the PCI code will call device remove
+	 * after the return of this function.
+	 * genwqe_stop() can be called twice.
+	 */
+	if (state == pci_channel_io_perm_failure) {
 		return PCI_ERS_RESULT_DISCONNECT;
+	} else {
+		genwqe_pci_remove(cd);
+		return PCI_ERS_RESULT_NEED_RESET;
 	}
+}
 
-	return PCI_ERS_RESULT_NEED_RESET;
+static pci_ers_result_t genwqe_err_slot_reset(struct pci_dev *pci_dev)
+{
+	int rc;
+	struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev);
+
+	rc = genwqe_pci_setup(cd);
+	if (!rc) {
+		return PCI_ERS_RESULT_RECOVERED;
+	} else {
+		dev_err(&pci_dev->dev,
+			"err: problems with PCI setup (err=%d)\n", rc);
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
 }
 
 static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev)
@@ -1120,8 +1293,22 @@ static pci_ers_result_t genwqe_err_resul
 	return PCI_ERS_RESULT_NONE;
 }
 
-static void genwqe_err_resume(struct pci_dev *dev)
+static void genwqe_err_resume(struct pci_dev *pci_dev)
 {
+	int rc;
+	struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev);
+
+	rc = genwqe_start(cd);
+	if (!rc) {
+		rc = genwqe_health_check_start(cd);
+		if (rc)
+			dev_err(&pci_dev->dev,
+				"err: cannot start health checking! (err=%d)\n",
+				rc);
+	} else {
+		dev_err(&pci_dev->dev,
+			"err: cannot start card services! (err=%d)\n", rc);
+	}
 }
 
 static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs)
@@ -1144,7 +1331,7 @@ static struct pci_error_handlers genwqe_
 	.error_detected = genwqe_err_error_detected,
 	.mmio_enabled	= genwqe_err_result_none,
 	.link_reset	= genwqe_err_result_none,
-	.slot_reset	= genwqe_err_result_none,
+	.slot_reset	= genwqe_err_slot_reset,
 	.resume		= genwqe_err_resume,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_base.h linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_base.h
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_base.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_base.h	2014-09-28 17:29:07.000000000 -0400
@@ -291,6 +291,8 @@ struct genwqe_dev {
 	struct task_struct *health_thread;
 	wait_queue_head_t health_waitq;
 
+	int use_platform_recovery;	/* use platform recovery mechanisms */
+
 	/* char device */
 	dev_t  devnum_genwqe;		/* major/minor num card */
 	struct class *class_genwqe;	/* reference to class object */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_ddcb.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_ddcb.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_ddcb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_ddcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -1118,7 +1118,21 @@ static irqreturn_t genwqe_pf_isr(int irq
 	 * safer, but slower for the good-case ... See above.
 	 */
 	gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR);
-	if ((gfir & GFIR_ERR_TRIGGER) != 0x0) {
+	if (((gfir & GFIR_ERR_TRIGGER) != 0x0) &&
+	    !pci_channel_offline(pci_dev)) {
+
+		if (cd->use_platform_recovery) {
+			/*
+			 * Since we use raw accessors, EEH errors won't be
+			 * detected by the platform until we do a non-raw
+			 * MMIO or config space read
+			 */
+			readq(cd->mmio + IO_SLC_CFGREG_GFIR);
+
+			/* Don't do anything if the PCI channel is frozen */
+			if (pci_channel_offline(pci_dev))
+				goto exit;
+		}
 
 		wake_up_interruptible(&cd->health_waitq);
 
@@ -1126,12 +1140,12 @@ static irqreturn_t genwqe_pf_isr(int irq
 		 * By default GFIRs causes recovery actions. This
 		 * count is just for debug when recovery is masked.
 		 */
-		printk_ratelimited(KERN_ERR
-				   "%s %s: [%s] GFIR=%016llx\n",
-				   GENWQE_DEVNAME, dev_name(&pci_dev->dev),
-				   __func__, gfir);
+		dev_err_ratelimited(&pci_dev->dev,
+				    "[%s] GFIR=%016llx\n",
+				    __func__, gfir);
 	}
 
+ exit:
 	return IRQ_HANDLED;
 }
 
@@ -1237,9 +1251,7 @@ int genwqe_setup_service_layer(struct ge
 	}
 
 	rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS);
-	if (rc > 0)
-		rc = genwqe_set_interrupt_capability(cd, rc);
-	if (rc != 0) {
+	if (rc) {
 		rc = -ENODEV;
 		goto stop_kthread;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_debugfs.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_debugfs.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -485,6 +485,13 @@ int genwqe_init_debugfs(struct genwqe_de
 		goto err1;
 	}
 
+	file = debugfs_create_u32("use_platform_recovery", 0666, root,
+				  &cd->use_platform_recovery);
+	if (!file) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
 	cd->debugfs_root = root;
 	return 0;
 err1:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_dev.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_dev.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -1048,10 +1048,15 @@ static long genwqe_ioctl(struct file *fi
 	int rc = 0;
 	struct genwqe_file *cfile = (struct genwqe_file *)filp->private_data;
 	struct genwqe_dev *cd = cfile->cd;
+	struct pci_dev *pci_dev = cd->pci_dev;
 	struct genwqe_reg_io __user *io;
 	u64 val;
 	u32 reg_offs;
 
+	/* Return -EIO if card hit EEH */
+	if (pci_channel_offline(pci_dev))
+		return -EIO;
+
 	if (_IOC_TYPE(cmd) != GENWQE_IOC_CODE)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_sysfs.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_sysfs.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -223,6 +223,30 @@ static ssize_t next_bitstream_store(stru
 }
 static DEVICE_ATTR_RW(next_bitstream);
 
+static ssize_t reload_bitstream_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int reload;
+	struct genwqe_dev *cd = dev_get_drvdata(dev);
+
+	if (kstrtoint(buf, 0, &reload) < 0)
+		return -EINVAL;
+
+	if (reload == 0x1) {
+		if (cd->card_state == GENWQE_CARD_UNUSED ||
+		    cd->card_state == GENWQE_CARD_USED)
+			cd->card_state = GENWQE_CARD_RELOAD_BITSTREAM;
+		else
+			return -EIO;
+	} else {
+		return -EINVAL;
+	}
+
+	return count;
+}
+static DEVICE_ATTR_WO(reload_bitstream);
+
 /*
  * Create device_attribute structures / params: name, mode, show, store
  * additional flag if valid in VF
@@ -239,6 +263,7 @@ static struct attribute *genwqe_attribut
 	&dev_attr_status.attr,
 	&dev_attr_freerunning_timer.attr,
 	&dev_attr_queue_working_time.attr,
+	&dev_attr_reload_bitstream.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/card_utils.c linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_utils.c
--- linux-libre-3.16-gnu/drivers/misc/genwqe/card_utils.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/card_utils.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,12 +53,17 @@
  */
 int __genwqe_writeq(struct genwqe_dev *cd, u64 byte_offs, u64 val)
 {
+	struct pci_dev *pci_dev = cd->pci_dev;
+
 	if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE)
 		return -EIO;
 
 	if (cd->mmio == NULL)
 		return -EIO;
 
+	if (pci_channel_offline(pci_dev))
+		return -EIO;
+
 	__raw_writeq((__force u64)cpu_to_be64(val), cd->mmio + byte_offs);
 	return 0;
 }
@@ -99,12 +104,17 @@ u64 __genwqe_readq(struct genwqe_dev *cd
  */
 int __genwqe_writel(struct genwqe_dev *cd, u64 byte_offs, u32 val)
 {
+	struct pci_dev *pci_dev = cd->pci_dev;
+
 	if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE)
 		return -EIO;
 
 	if (cd->mmio == NULL)
 		return -EIO;
 
+	if (pci_channel_offline(pci_dev))
+		return -EIO;
+
 	__raw_writel((__force u32)cpu_to_be32(val), cd->mmio + byte_offs);
 	return 0;
 }
@@ -718,10 +728,12 @@ int genwqe_set_interrupt_capability(stru
 	int rc;
 	struct pci_dev *pci_dev = cd->pci_dev;
 
-	rc = pci_enable_msi_exact(pci_dev, count);
-	if (rc == 0)
-		cd->flags |= GENWQE_FLAG_MSI_ENABLED;
-	return rc;
+	rc = pci_enable_msi_range(pci_dev, 1, count);
+	if (rc < 0)
+		return rc;
+
+	cd->flags |= GENWQE_FLAG_MSI_ENABLED;
+	return 0;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/genwqe_driver.h linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/genwqe_driver.h
--- linux-libre-3.16-gnu/drivers/misc/genwqe/genwqe_driver.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/genwqe_driver.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@
 #include <asm/byteorder.h>
 #include <linux/genwqe/genwqe_card.h>
 
-#define DRV_VERS_STRING		"2.0.15"
+#define DRV_VERS_STRING		"2.0.21"
 
 /*
  * Static minor number assignement, until we decide/implement
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/genwqe/Kconfig linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/Kconfig
--- linux-libre-3.16-gnu/drivers/misc/genwqe/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/genwqe/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,3 +11,9 @@ menuconfig GENWQE
 	  Enables PCIe card driver for IBM GenWQE accelerators.
 	  The user-space interface is described in
 	  include/linux/genwqe/genwqe_card.h.
+
+config GENWQE_PLATFORM_ERROR_RECOVERY
+	int "Use platform recovery procedures (0=off, 1=on)"
+	depends on GENWQE
+	default 1 if PPC64
+	default 0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/ioc4.c linux-libre-3.17-rc7-gnu/drivers/misc/ioc4.c
--- linux-libre-3.16-gnu/drivers/misc/ioc4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/ioc4.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,6 @@ ioc4_clock_calibrate(struct ioc4_driver_
 	union ioc4_int_out int_out;
 	union ioc4_gpcr gpcr;
 	unsigned int state, last_state = 1;
-	struct timespec start_ts, end_ts;
 	uint64_t start, end, period;
 	unsigned int count = 0;
 
@@ -174,10 +173,10 @@ ioc4_clock_calibrate(struct ioc4_driver_
 		if (!last_state && state) {
 			count++;
 			if (count == IOC4_CALIBRATE_END) {
-				ktime_get_ts(&end_ts);
+				end = ktime_get_ns();
 				break;
 			} else if (count == IOC4_CALIBRATE_DISCARD)
-				ktime_get_ts(&start_ts);
+				start = ktime_get_ns();
 		}
 		last_state = state;
 	} while (1);
@@ -192,8 +191,6 @@ ioc4_clock_calibrate(struct ioc4_driver_
 	 *    by which the IOC4 generates the square wave, to get the
 	 *    period of an IOC4 INT_OUT count.
 	 */
-	end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec;
-	start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec;
 	period = (end - start) /
 		(IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/Kconfig linux-libre-3.17-rc7-gnu/drivers/misc/Kconfig
--- linux-libre-3.16-gnu/drivers/misc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -51,16 +51,6 @@ config AD525X_DPOT_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
-config ATMEL_PWM
-	tristate "Atmel AT32/AT91 PWM support"
-	depends on HAVE_CLK
-	depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
-	help
-	  This option enables device driver support for the PWM channels
-	  on certain Atmel processors.  Pulse Width Modulation is used for
-	  purposes including software controlled power-efficient backlights
-	  on LCD displays, motor control, and waveform generation.
-
 config ATMEL_TCLIB
 	bool "Atmel AT32/AT91 Timer/Counter Library"
 	depends on (AVR32 || ARCH_AT91)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/lattice-ecp3-config.c linux-libre-3.17-rc7-gnu/drivers/misc/lattice-ecp3-config.c
--- linux-libre-3.16-gnu/drivers/misc/lattice-ecp3-config.c	2014-08-07 05:00:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/lattice-ecp3-config.c	2014-09-28 21:43:36.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/spi/spi.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <asm/unaligned.h>
 
 #define FIRMWARE_NAME	"/*(DEBLOBBED)*/"
 
@@ -78,6 +79,11 @@ static void firmware_load(const struct f
 	u32 jedec_id;
 	u32 status;
 
+	if (fw == NULL) {
+		dev_err(&spi->dev, "Cannot load firmware, aborting\n");
+		return;
+	}
+
 	if (fw->size == 0) {
 		dev_err(&spi->dev, "Error: Firmware size is 0!\n");
 		return;
@@ -91,8 +97,8 @@ static void firmware_load(const struct f
 	/* Trying to speak with the FPGA via SPI... */
 	txbuf[0] = FPGA_CMD_READ_ID;
 	ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
-	dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", *(u32 *)&rxbuf[4]);
-	jedec_id = *(u32 *)&rxbuf[4];
+	jedec_id = get_unaligned_be32(&rxbuf[4]);
+	dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", jedec_id);
 
 	for (i = 0; i < ARRAY_SIZE(ecp3_dev); i++) {
 		if (jedec_id == ecp3_dev[i].jedec_id)
@@ -109,7 +115,8 @@ static void firmware_load(const struct f
 
 	txbuf[0] = FPGA_CMD_READ_STATUS;
 	ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
-	dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]);
+	status = get_unaligned_be32(&rxbuf[4]);
+	dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);
 
 	buffer = kzalloc(fw->size + 8, GFP_KERNEL);
 	if (!buffer) {
@@ -141,7 +148,7 @@ static void firmware_load(const struct f
 	for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) {
 		txbuf[0] = FPGA_CMD_READ_STATUS;
 		ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
-		status = *(u32 *)&rxbuf[4];
+		status = get_unaligned_be32(&rxbuf[4]);
 		if (status == FPGA_STATUS_CLEARED)
 			break;
 
@@ -164,8 +171,8 @@ static void firmware_load(const struct f
 
 	txbuf[0] = FPGA_CMD_READ_STATUS;
 	ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
-	dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]);
-	status = *(u32 *)&rxbuf[4];
+	status = get_unaligned_be32(&rxbuf[4]);
+	dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);
 
 	/* Check result */
 	if (status & FPGA_STATUS_DONE)
@@ -196,7 +203,7 @@ static int lattice_ecp3_probe(struct spi
 	spi_set_drvdata(spi, data);
 
 	init_completion(&data->fw_loaded);
-	err = reject_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+	err = reject_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
 				      FIRMWARE_NAME, &spi->dev,
 				      GFP_KERNEL, spi, firmware_load);
 	if (err) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/lkdtm.c linux-libre-3.17-rc7-gnu/drivers/misc/lkdtm.c
--- linux-libre-3.16-gnu/drivers/misc/lkdtm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/lkdtm.c	2014-09-28 17:29:07.000000000 -0400
@@ -870,3 +870,4 @@ module_init(lkdtm_module_init);
 module_exit(lkdtm_module_exit);
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Kprobe module for testing crash dumps");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/Makefile linux-libre-3.17-rc7-gnu/drivers/misc/Makefile
--- linux-libre-3.16-gnu/drivers/misc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,6 @@ obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
 obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
-obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_BMP085)		+= bmp085.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/client.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/client.c
--- linux-libre-3.16-gnu/drivers/misc/mei/client.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/client.c	2014-09-28 17:29:07.000000000 -0400
@@ -459,7 +459,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
 {
 	struct mei_device *dev;
 	struct mei_cl_cb *cb;
-	int rets, err;
+	int rets;
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
@@ -491,6 +491,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
 			cl_err(dev, cl, "failed to disconnect.\n");
 			goto free;
 		}
+		cl->timer_count = MEI_CONNECT_TIMEOUT;
 		mdelay(10); /* Wait for hardware disconnection ready */
 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
 	} else {
@@ -500,23 +501,18 @@ int mei_cl_disconnect(struct mei_cl *cl)
 	}
 	mutex_unlock(&dev->device_lock);
 
-	err = wait_event_timeout(dev->wait_recvd_msg,
+	wait_event_timeout(dev->wait_recvd_msg,
 			MEI_FILE_DISCONNECTED == cl->state,
 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 
 	mutex_lock(&dev->device_lock);
+
 	if (MEI_FILE_DISCONNECTED == cl->state) {
 		rets = 0;
 		cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
 	} else {
-		rets = -ENODEV;
-		if (MEI_FILE_DISCONNECTED != cl->state)
-			cl_err(dev, cl, "wrong status client disconnect.\n");
-
-		if (err)
-			cl_dbg(dev, cl, "wait failed disconnect err=%d\n", err);
-
-		cl_err(dev, cl, "failed to disconnect from FW client.\n");
+		cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");
+		rets = -ETIME;
 	}
 
 	mei_io_list_flush(&dev->ctrl_rd_list, cl);
@@ -605,6 +601,7 @@ int mei_cl_connect(struct mei_cl *cl, st
 		cl->timer_count = MEI_CONNECT_TIMEOUT;
 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
 	} else {
+		cl->state = MEI_FILE_INITIALIZING;
 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 
@@ -616,6 +613,7 @@ int mei_cl_connect(struct mei_cl *cl, st
 	mutex_lock(&dev->device_lock);
 
 	if (cl->state != MEI_FILE_CONNECTED) {
+		cl->state = MEI_FILE_DISCONNECTED;
 		/* something went really wrong */
 		if (!cl->status)
 			cl->status = -EFAULT;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/hw-me.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-me.c
--- linux-libre-3.16-gnu/drivers/misc/mei/hw-me.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-me.c	2014-09-28 17:29:07.000000000 -0400
@@ -710,64 +710,10 @@ end:
 	return IRQ_HANDLED;
 }
 
-/**
- * mei_me_fw_status - retrieve fw status from the pci config space
- *
- * @dev: the device structure
- * @fw_status: fw status registers storage
- *
- * returns 0 on success an error code otherwise
- */
-static int mei_me_fw_status(struct mei_device *dev,
-			    struct mei_fw_status *fw_status)
-{
-	const u32 pci_cfg_reg[] = {PCI_CFG_HFS_1, PCI_CFG_HFS_2};
-	int i;
-
-	if (!fw_status)
-		return -EINVAL;
-
-	switch (dev->pdev->device) {
-	case MEI_DEV_ID_IBXPK_1:
-	case MEI_DEV_ID_IBXPK_2:
-	case MEI_DEV_ID_CPT_1:
-	case MEI_DEV_ID_PBG_1:
-	case MEI_DEV_ID_PPT_1:
-	case MEI_DEV_ID_PPT_2:
-	case MEI_DEV_ID_PPT_3:
-	case MEI_DEV_ID_LPT_H:
-	case MEI_DEV_ID_LPT_W:
-	case MEI_DEV_ID_LPT_LP:
-	case MEI_DEV_ID_LPT_HR:
-	case MEI_DEV_ID_WPT_LP:
-		fw_status->count = 2;
-		break;
-	case MEI_DEV_ID_ICH10_1:
-	case MEI_DEV_ID_ICH10_2:
-	case MEI_DEV_ID_ICH10_3:
-	case MEI_DEV_ID_ICH10_4:
-		fw_status->count = 1;
-		break;
-	default:
-		fw_status->count = 0;
-		break;
-	}
-
-	for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) {
-		int ret;
-		ret = pci_read_config_dword(dev->pdev,
-				pci_cfg_reg[i], &fw_status->status[i]);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
 static const struct mei_hw_ops mei_me_hw_ops = {
 
 	.pg_state  = mei_me_pg_state,
 
-	.fw_status = mei_me_fw_status,
 	.host_is_ready = mei_me_host_is_ready,
 
 	.hw_is_ready = mei_me_hw_is_ready,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/hw-me-regs.h linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-me-regs.h
--- linux-libre-3.16-gnu/drivers/misc/mei/hw-me-regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-me-regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -115,6 +115,7 @@
 #define MEI_DEV_ID_LPT_HR     0x8CBA  /* Lynx Point H Refresh */
 
 #define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
+#define MEI_DEV_ID_WPT_LP_2   0x9CBB  /* Wildcat Point LP 2 */
 
 /* Host Firmware Status Registers in PCI Config Space */
 #define PCI_CFG_HFS_1         0x40
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/hw-txe.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-txe.c
--- linux-libre-3.16-gnu/drivers/misc/mei/hw-txe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/hw-txe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1042,40 +1042,8 @@ end:
 	return IRQ_HANDLED;
 }
 
-
-/**
- * mei_txe_fw_status - retrieve fw status from the pci config space
- *
- * @dev: the device structure
- * @fw_status: fw status registers storage
- *
- * returns: 0 on success an error code otherwise
- */
-static int mei_txe_fw_status(struct mei_device *dev,
-			     struct mei_fw_status *fw_status)
-{
-	const u32 pci_cfg_reg[] = {PCI_CFG_TXE_FW_STS0, PCI_CFG_TXE_FW_STS1};
-	int i;
-
-	if (!fw_status)
-		return -EINVAL;
-
-	fw_status->count = 2;
-
-	for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) {
-		int ret;
-		ret = pci_read_config_dword(dev->pdev,
-				pci_cfg_reg[i], &fw_status->status[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 static const struct mei_hw_ops mei_txe_hw_ops = {
 
-	.fw_status = mei_txe_fw_status,
 	.host_is_ready = mei_txe_host_is_ready,
 
 	.pg_state = mei_txe_pg_state,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/main.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/main.c
--- linux-libre-3.16-gnu/drivers/misc/mei/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,6 @@
 #include <linux/compat.h>
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
-#include <linux/miscdevice.h>
 
 #include <linux/mei.h>
 
@@ -49,19 +48,12 @@
  */
 static int mei_open(struct inode *inode, struct file *file)
 {
-	struct miscdevice *misc = file->private_data;
-	struct pci_dev *pdev;
-	struct mei_cl *cl;
 	struct mei_device *dev;
+	struct mei_cl *cl;
 
 	int err;
 
-	if (!misc->parent)
-		return -ENODEV;
-
-	pdev = container_of(misc->parent, struct pci_dev, dev);
-
-	dev = pci_get_drvdata(pdev);
+	dev = container_of(inode->i_cdev, struct mei_device, cdev);
 	if (!dev)
 		return -ENODEV;
 
@@ -667,46 +659,148 @@ static const struct file_operations mei_
 	.llseek = no_llseek
 };
 
-/*
- * Misc Device Struct
+static struct class *mei_class;
+static dev_t mei_devt;
+#define MEI_MAX_DEVS  MINORMASK
+static DEFINE_MUTEX(mei_minor_lock);
+static DEFINE_IDR(mei_idr);
+
+/**
+ * mei_minor_get - obtain next free device minor number
+ *
+ * @dev:  device pointer
+ *
+ * returns allocated minor, or -ENOSPC if no free minor left
  */
-static struct miscdevice  mei_misc_device = {
-		.name = "mei",
-		.fops = &mei_fops,
-		.minor = MISC_DYNAMIC_MINOR,
-};
+static int mei_minor_get(struct mei_device *dev)
+{
+	int ret;
+
+	mutex_lock(&mei_minor_lock);
+	ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL);
+	if (ret >= 0)
+		dev->minor = ret;
+	else if (ret == -ENOSPC)
+		dev_err(&dev->pdev->dev, "too many mei devices\n");
 
+	mutex_unlock(&mei_minor_lock);
+	return ret;
+}
 
-int mei_register(struct mei_device *dev)
+/**
+ * mei_minor_free - mark device minor number as free
+ *
+ * @dev:  device pointer
+ */
+static void mei_minor_free(struct mei_device *dev)
 {
-	int ret;
-	mei_misc_device.parent = &dev->pdev->dev;
-	ret = misc_register(&mei_misc_device);
-	if (ret)
+	mutex_lock(&mei_minor_lock);
+	idr_remove(&mei_idr, dev->minor);
+	mutex_unlock(&mei_minor_lock);
+}
+
+int mei_register(struct mei_device *dev, struct device *parent)
+{
+	struct device *clsdev; /* class device */
+	int ret, devno;
+
+	ret = mei_minor_get(dev);
+	if (ret < 0)
 		return ret;
 
-	if (mei_dbgfs_register(dev, mei_misc_device.name))
-		dev_err(&dev->pdev->dev, "cannot register debugfs\n");
+	/* Fill in the data structures */
+	devno = MKDEV(MAJOR(mei_devt), dev->minor);
+	cdev_init(&dev->cdev, &mei_fops);
+	dev->cdev.owner = mei_fops.owner;
+
+	/* Add the device */
+	ret = cdev_add(&dev->cdev, devno, 1);
+	if (ret) {
+		dev_err(parent, "unable to add device %d:%d\n",
+			MAJOR(mei_devt), dev->minor);
+		goto err_dev_add;
+	}
+
+	clsdev = device_create(mei_class, parent, devno,
+			 NULL, "mei%d", dev->minor);
+
+	if (IS_ERR(clsdev)) {
+		dev_err(parent, "unable to create device %d:%d\n",
+			MAJOR(mei_devt), dev->minor);
+		ret = PTR_ERR(clsdev);
+		goto err_dev_create;
+	}
+
+	ret = mei_dbgfs_register(dev, dev_name(clsdev));
+	if (ret) {
+		dev_err(clsdev, "cannot register debugfs ret = %d\n", ret);
+		goto err_dev_dbgfs;
+	}
 
 	return 0;
+
+err_dev_dbgfs:
+	device_destroy(mei_class, devno);
+err_dev_create:
+	cdev_del(&dev->cdev);
+err_dev_add:
+	mei_minor_free(dev);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mei_register);
 
 void mei_deregister(struct mei_device *dev)
 {
+	int devno;
+
+	devno = dev->cdev.dev;
+	cdev_del(&dev->cdev);
+
 	mei_dbgfs_deregister(dev);
-	misc_deregister(&mei_misc_device);
-	mei_misc_device.parent = NULL;
+
+	device_destroy(mei_class, devno);
+
+	mei_minor_free(dev);
 }
 EXPORT_SYMBOL_GPL(mei_deregister);
 
 static int __init mei_init(void)
 {
-	return mei_cl_bus_init();
+	int ret;
+
+	mei_class = class_create(THIS_MODULE, "mei");
+	if (IS_ERR(mei_class)) {
+		pr_err("couldn't create class\n");
+		ret = PTR_ERR(mei_class);
+		goto err;
+	}
+
+	ret = alloc_chrdev_region(&mei_devt, 0, MEI_MAX_DEVS, "mei");
+	if (ret < 0) {
+		pr_err("unable to allocate char dev region\n");
+		goto err_class;
+	}
+
+	ret = mei_cl_bus_init();
+	if (ret < 0) {
+		pr_err("unable to initialize bus\n");
+		goto err_chrdev;
+	}
+
+	return 0;
+
+err_chrdev:
+	unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
+err_class:
+	class_destroy(mei_class);
+err:
+	return ret;
 }
 
 static void __exit mei_exit(void)
 {
+	unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
+	class_destroy(mei_class);
 	mei_cl_bus_exit();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/mei_dev.h linux-libre-3.17-rc7-gnu/drivers/misc/mei/mei_dev.h
--- linux-libre-3.16-gnu/drivers/misc/mei/mei_dev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/mei_dev.h	2014-09-28 17:29:07.000000000 -0400
@@ -227,7 +227,6 @@ struct mei_cl {
 
 /** struct mei_hw_ops
  *
- * @fw_status        - read FW status from PCI config space
  * @host_is_ready    - query for host readiness
 
  * @hw_is_ready      - query if hw is ready
@@ -255,8 +254,6 @@ struct mei_cl {
  */
 struct mei_hw_ops {
 
-	int (*fw_status)(struct mei_device *dev,
-		struct mei_fw_status *fw_status);
 	bool (*host_is_ready)(struct mei_device *dev);
 
 	bool (*hw_is_ready)(struct mei_device *dev);
@@ -400,6 +397,10 @@ struct mei_cfg {
 /**
  * struct mei_device -  MEI private device struct
 
+ * @pdev - pointer to pci device struct
+ * @cdev - character device
+ * @minor - minor number allocated for device
+ *
  * @reset_count - limits the number of consecutive resets
  * @hbm_state - state of host bus message protocol
  * @pg_event - power gating event
@@ -412,6 +413,9 @@ struct mei_cfg {
  */
 struct mei_device {
 	struct pci_dev *pdev;	/* pointer to pci device struct */
+	struct cdev cdev;
+	int minor;
+
 	/*
 	 * lists of queues
 	 */
@@ -741,7 +745,7 @@ static inline int mei_dbgfs_register(str
 static inline void mei_dbgfs_deregister(struct mei_device *dev) {}
 #endif /* CONFIG_DEBUG_FS */
 
-int mei_register(struct mei_device *dev);
+int mei_register(struct mei_device *dev, struct device *parent);
 void mei_deregister(struct mei_device *dev);
 
 #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/nfc.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/nfc.c
--- linux-libre-3.16-gnu/drivers/misc/mei/nfc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/nfc.c	2014-09-28 17:29:07.000000000 -0400
@@ -342,9 +342,10 @@ static int mei_nfc_send(struct mei_cl_de
 	ndev = (struct mei_nfc_dev *) cldev->priv_data;
 	dev = ndev->cl->dev;
 
+	err = -ENOMEM;
 	mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
 	if (!mei_buf)
-		return -ENOMEM;
+		goto out;
 
 	hdr = (struct mei_nfc_hci_hdr *) mei_buf;
 	hdr->cmd = MEI_NFC_CMD_HCI_SEND;
@@ -354,12 +355,9 @@ static int mei_nfc_send(struct mei_cl_de
 	hdr->data_size = length;
 
 	memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
-
 	err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE);
 	if (err < 0)
-		return err;
-
-	kfree(mei_buf);
+		goto out;
 
 	if (!wait_event_interruptible_timeout(ndev->send_wq,
 				ndev->recv_req_id == ndev->req_id, HZ)) {
@@ -368,7 +366,8 @@ static int mei_nfc_send(struct mei_cl_de
 	} else {
 		ndev->req_id++;
 	}
-
+out:
+	kfree(mei_buf);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/pci-me.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/pci-me.c
--- linux-libre-3.16-gnu/drivers/misc/mei/pci-me.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/pci-me.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/compat.h>
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
-#include <linux/miscdevice.h>
 
 #include <linux/pm_runtime.h>
 
@@ -82,6 +81,7 @@ static const struct pci_device_id mei_me
 	{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch_cfg)},
 
 	/* required last entry */
 	{0, }
@@ -207,7 +207,7 @@ static int mei_me_probe(struct pci_dev *
 	pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
 
-	err = mei_register(dev);
+	err = mei_register(dev, &pdev->dev);
 	if (err)
 		goto release_irq;
 
@@ -369,7 +369,7 @@ static int mei_me_pm_runtime_idle(struct
 	if (!dev)
 		return -ENODEV;
 	if (mei_write_is_idle(dev))
-		pm_schedule_suspend(device, MEI_ME_RPM_TIMEOUT * 2);
+		pm_runtime_autosuspend(device);
 
 	return -EBUSY;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mei/pci-txe.c linux-libre-3.17-rc7-gnu/drivers/misc/mei/pci-txe.c
--- linux-libre-3.16-gnu/drivers/misc/mei/pci-txe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mei/pci-txe.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,7 +149,7 @@ static int mei_txe_probe(struct pci_dev
 	pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
 
-	err = mei_register(dev);
+	err = mei_register(dev, &pdev->dev);
 	if (err)
 		goto release_irq;
 
@@ -306,7 +306,7 @@ static int mei_txe_pm_runtime_idle(struc
 	if (!dev)
 		return -ENODEV;
 	if (mei_write_is_idle(dev))
-		pm_schedule_suspend(device, MEI_TXI_RPM_TIMEOUT * 2);
+		pm_runtime_autosuspend(device);
 
 	return -EBUSY;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/bus/Makefile linux-libre-3.17-rc7-gnu/drivers/misc/mic/bus/Makefile
--- linux-libre-3.16-gnu/drivers/misc/mic/bus/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/bus/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2014, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/bus/mic_bus.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/bus/mic_bus.c
--- linux-libre-3.16-gnu/drivers/misc/mic/bus/mic_bus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/bus/mic_bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,218 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Bus driver.
+ *
+ * This implementation is very similar to the the virtio bus driver
+ * implementation @ drivers/virtio/virtio.c
+ */
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/idr.h>
+#include <linux/mic_bus.h>
+
+/* Unique numbering for mbus devices. */
+static DEFINE_IDA(mbus_index_ida);
+
+static ssize_t device_show(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	struct mbus_device *dev = dev_to_mbus(d);
+	return sprintf(buf, "0x%04x\n", dev->id.device);
+}
+static DEVICE_ATTR_RO(device);
+
+static ssize_t vendor_show(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	struct mbus_device *dev = dev_to_mbus(d);
+	return sprintf(buf, "0x%04x\n", dev->id.vendor);
+}
+static DEVICE_ATTR_RO(vendor);
+
+static ssize_t modalias_show(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	struct mbus_device *dev = dev_to_mbus(d);
+	return sprintf(buf, "mbus:d%08Xv%08X\n",
+		       dev->id.device, dev->id.vendor);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *mbus_dev_attrs[] = {
+	&dev_attr_device.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_modalias.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(mbus_dev);
+
+static inline int mbus_id_match(const struct mbus_device *dev,
+				const struct mbus_device_id *id)
+{
+	if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID)
+		return 0;
+
+	return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev->id.vendor;
+}
+
+/*
+ * This looks through all the IDs a driver claims to support.  If any of them
+ * match, we return 1 and the kernel will call mbus_dev_probe().
+ */
+static int mbus_dev_match(struct device *dv, struct device_driver *dr)
+{
+	unsigned int i;
+	struct mbus_device *dev = dev_to_mbus(dv);
+	const struct mbus_device_id *ids;
+
+	ids = drv_to_mbus(dr)->id_table;
+	for (i = 0; ids[i].device; i++)
+		if (mbus_id_match(dev, &ids[i]))
+			return 1;
+	return 0;
+}
+
+static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env)
+{
+	struct mbus_device *dev = dev_to_mbus(dv);
+
+	return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X",
+			      dev->id.device, dev->id.vendor);
+}
+
+static int mbus_dev_probe(struct device *d)
+{
+	int err;
+	struct mbus_device *dev = dev_to_mbus(d);
+	struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
+
+	err = drv->probe(dev);
+	if (!err)
+		if (drv->scan)
+			drv->scan(dev);
+	return err;
+}
+
+static int mbus_dev_remove(struct device *d)
+{
+	struct mbus_device *dev = dev_to_mbus(d);
+	struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
+
+	drv->remove(dev);
+	return 0;
+}
+
+static struct bus_type mic_bus = {
+	.name  = "mic_bus",
+	.match = mbus_dev_match,
+	.dev_groups = mbus_dev_groups,
+	.uevent = mbus_uevent,
+	.probe = mbus_dev_probe,
+	.remove = mbus_dev_remove,
+};
+
+int mbus_register_driver(struct mbus_driver *driver)
+{
+	driver->driver.bus = &mic_bus;
+	return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(mbus_register_driver);
+
+void mbus_unregister_driver(struct mbus_driver *driver)
+{
+	driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(mbus_unregister_driver);
+
+static void mbus_release_dev(struct device *d)
+{
+	struct mbus_device *mbdev = dev_to_mbus(d);
+	kfree(mbdev);
+}
+
+struct mbus_device *
+mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
+		     struct mbus_hw_ops *hw_ops, void __iomem *mmio_va)
+{
+	int ret;
+	struct mbus_device *mbdev;
+
+	mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL);
+	if (!mbdev)
+		return ERR_PTR(-ENOMEM);
+
+	mbdev->mmio_va = mmio_va;
+	mbdev->dev.parent = pdev;
+	mbdev->id.device = id;
+	mbdev->id.vendor = MBUS_DEV_ANY_ID;
+	mbdev->dev.archdata.dma_ops = dma_ops;
+	mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask;
+	dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64));
+	mbdev->dev.release = mbus_release_dev;
+	mbdev->hw_ops = hw_ops;
+	mbdev->dev.bus = &mic_bus;
+
+	/* Assign a unique device index and hence name. */
+	ret = ida_simple_get(&mbus_index_ida, 0, 0, GFP_KERNEL);
+	if (ret < 0)
+		goto free_mbdev;
+
+	mbdev->index = ret;
+	dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index);
+	/*
+	 * device_register() causes the bus infrastructure to look for a
+	 * matching driver.
+	 */
+	ret = device_register(&mbdev->dev);
+	if (ret)
+		goto ida_remove;
+	return mbdev;
+ida_remove:
+	ida_simple_remove(&mbus_index_ida, mbdev->index);
+free_mbdev:
+	kfree(mbdev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(mbus_register_device);
+
+void mbus_unregister_device(struct mbus_device *mbdev)
+{
+	int index = mbdev->index; /* save for after device release */
+
+	device_unregister(&mbdev->dev);
+	ida_simple_remove(&mbus_index_ida, index);
+}
+EXPORT_SYMBOL_GPL(mbus_unregister_device);
+
+static int __init mbus_init(void)
+{
+	return bus_register(&mic_bus);
+}
+
+static void __exit mbus_exit(void)
+{
+	bus_unregister(&mic_bus);
+	ida_destroy(&mbus_index_ida);
+}
+
+core_initcall(mbus_init);
+module_exit(mbus_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC Bus driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/card/mic_device.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_device.c
--- linux-libre-3.16-gnu/drivers/misc/mic/card/mic_device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_device.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,8 +83,8 @@ static int mic_shutdown_init(void)
 	int shutdown_db;
 
 	shutdown_db = mic_next_card_db();
-	shutdown_cookie = mic_request_card_irq(mic_shutdown_isr,
-			"Shutdown", mdrv, shutdown_db);
+	shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, NULL,
+					       "Shutdown", mdrv, shutdown_db);
 	if (IS_ERR(shutdown_cookie))
 		rc = PTR_ERR(shutdown_cookie);
 	else
@@ -136,7 +136,8 @@ static void mic_dp_uninit(void)
 /**
  * mic_request_card_irq - request an irq.
  *
- * @func: The callback function that handles the interrupt.
+ * @handler: interrupt handler passed to request_threaded_irq.
+ * @thread_fn: thread fn. passed to request_threaded_irq.
  * @name: The ASCII name of the callee requesting the irq.
  * @data: private data that is returned back when calling the
  * function handler.
@@ -149,17 +150,19 @@ static void mic_dp_uninit(void)
  * error code.
  *
  */
-struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
-	const char *name, void *data, int index)
+struct mic_irq *
+mic_request_card_irq(irq_handler_t handler,
+		     irq_handler_t thread_fn, const char *name,
+		     void *data, int index)
 {
 	int rc = 0;
 	unsigned long cookie;
 	struct mic_driver *mdrv = g_drv;
 
-	rc  = request_irq(mic_db_to_irq(mdrv, index), func,
-		0, name, data);
+	rc  = request_threaded_irq(mic_db_to_irq(mdrv, index), handler,
+				   thread_fn, 0, name, data);
 	if (rc) {
-		dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc);
+		dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n", rc);
 		goto err;
 	}
 	mdrv->irq_info.irq_usage_count[index]++;
@@ -172,9 +175,9 @@ err:
 /**
  * mic_free_card_irq - free irq.
  *
- * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
  * @data: private data specified by the calling function during the
- * mic_request_irq
+ * mic_request_threaded_irq
  *
  * returns: none.
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/card/mic_device.h linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_device.h
--- linux-libre-3.16-gnu/drivers/misc/mic/card/mic_device.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_device.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,8 @@
 #include <linux/workqueue.h>
 #include <linux/io.h>
 #include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#include <linux/mic_bus.h>
 
 /**
  * struct mic_intr_info - Contains h/w specific interrupt sources info
@@ -70,6 +72,7 @@ struct mic_device {
  * @hotplug_work: Hot plug work for adding/removing virtio devices.
  * @irq_info: The OS specific irq information
  * @intr_info: H/W specific interrupt information.
+ * @dma_mbdev: dma device on the MIC virtual bus.
  */
 struct mic_driver {
 	char name[20];
@@ -80,6 +83,7 @@ struct mic_driver {
 	struct work_struct hotplug_work;
 	struct mic_irq_info irq_info;
 	struct mic_intr_info intr_info;
+	struct mbus_device *dma_mbdev;
 };
 
 /**
@@ -116,8 +120,9 @@ mic_mmio_write(struct mic_mw *mw, u32 va
 int mic_driver_init(struct mic_driver *mdrv);
 void mic_driver_uninit(struct mic_driver *mdrv);
 int mic_next_card_db(void);
-struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
-	const char *name, void *data, int intr_src);
+struct mic_irq *
+mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn,
+		     const char *name, void *data, int intr_src);
 void mic_free_card_irq(struct mic_irq *cookie, void *data);
 u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
 void mic_send_intr(struct mic_device *mdev, int doorbell);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/card/mic_virtio.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_virtio.c
--- linux-libre-3.16-gnu/drivers/misc/mic/card/mic_virtio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_virtio.c	2014-09-28 17:29:07.000000000 -0400
@@ -417,7 +417,7 @@ static int mic_add_device(struct mic_dev
 
 	virtio_db = mic_next_card_db();
 	mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler,
-			"virtio intr", mvdev, virtio_db);
+			NULL, "virtio intr", mvdev, virtio_db);
 	if (IS_ERR(mvdev->virtio_cookie)) {
 		ret = PTR_ERR(mvdev->virtio_cookie);
 		goto kfree;
@@ -606,8 +606,9 @@ int mic_devices_init(struct mic_driver *
 	mic_scan_devices(mdrv, !REMOVE_DEVICES);
 
 	config_db = mic_next_card_db();
-	virtio_config_cookie = mic_request_card_irq(mic_extint_handler,
-			"virtio_config_intr", mdrv, config_db);
+	virtio_config_cookie = mic_request_card_irq(mic_extint_handler, NULL,
+						    "virtio_config_intr", mdrv,
+						    config_db);
 	if (IS_ERR(virtio_config_cookie)) {
 		rc = PTR_ERR(virtio_config_cookie);
 		goto exit;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/card/mic_x100.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_x100.c
--- linux-libre-3.16-gnu/drivers/misc/mic/card/mic_x100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/card/mic_x100.c	2014-09-28 17:29:07.000000000 -0400
@@ -148,6 +148,47 @@ void mic_card_unmap(struct mic_device *m
 	iounmap(addr);
 }
 
+static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev)
+{
+	return dev_get_drvdata(mbdev->dev.parent);
+}
+
+static struct mic_irq *
+_mic_request_threaded_irq(struct mbus_device *mbdev,
+			  irq_handler_t handler, irq_handler_t thread_fn,
+			  const char *name, void *data, int intr_src)
+{
+	int rc = 0;
+	unsigned int irq = intr_src;
+	unsigned long cookie = irq;
+
+	rc  = request_threaded_irq(irq, handler, thread_fn, 0, name, data);
+	if (rc) {
+		dev_err(mbdev_to_mdrv(mbdev)->dev,
+			"request_threaded_irq failed rc = %d\n", rc);
+		return ERR_PTR(rc);
+	}
+	return (struct mic_irq *)cookie;
+}
+
+static void _mic_free_irq(struct mbus_device *mbdev,
+			  struct mic_irq *cookie, void *data)
+{
+	unsigned long irq = (unsigned long)cookie;
+	free_irq(irq, data);
+}
+
+static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
+{
+	mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev);
+}
+
+static struct mbus_hw_ops mbus_hw_ops = {
+	.request_threaded_irq = _mic_request_threaded_irq,
+	.free_irq = _mic_free_irq,
+	.ack_interrupt = _mic_ack_interrupt,
+};
+
 static int __init mic_probe(struct platform_device *pdev)
 {
 	struct mic_driver *mdrv = &g_drv;
@@ -159,32 +200,41 @@ static int __init mic_probe(struct platf
 
 	mdev->mmio.pa = MIC_X100_MMIO_BASE;
 	mdev->mmio.len = MIC_X100_MMIO_LEN;
-	mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN);
+	mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE,
+				     MIC_X100_MMIO_LEN);
 	if (!mdev->mmio.va) {
 		dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
 		rc = -EIO;
 		goto done;
 	}
 	mic_hw_intr_init(mdrv);
+	platform_set_drvdata(pdev, mdrv);
+	mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC,
+					       NULL, &mbus_hw_ops,
+					       mdrv->mdev.mmio.va);
+	if (IS_ERR(mdrv->dma_mbdev)) {
+		rc = PTR_ERR(mdrv->dma_mbdev);
+		dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc);
+		goto done;
+	}
 	rc = mic_driver_init(mdrv);
 	if (rc) {
 		dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
-		goto iounmap;
+		goto remove_dma;
 	}
 done:
 	return rc;
-iounmap:
-	iounmap(mdev->mmio.va);
+remove_dma:
+	mbus_unregister_device(mdrv->dma_mbdev);
 	return rc;
 }
 
 static int mic_remove(struct platform_device *pdev)
 {
 	struct mic_driver *mdrv = &g_drv;
-	struct mic_device *mdev = &mdrv->mdev;
 
 	mic_driver_uninit(mdrv);
-	iounmap(mdev->mmio.va);
+	mbus_unregister_device(mdrv->dma_mbdev);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_boot.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_boot.c
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_boot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_boot.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,11 +23,70 @@
 #include <linux/pci.h>
 
 #include <linux/mic_common.h>
+#include <linux/mic_bus.h>
 #include "../common/mic_dev.h"
 #include "mic_device.h"
 #include "mic_smpt.h"
 #include "mic_virtio.h"
 
+static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
+{
+	return dev_get_drvdata(mbdev->dev.parent);
+}
+
+static dma_addr_t
+mic_dma_map_page(struct device *dev, struct page *page,
+		 unsigned long offset, size_t size, enum dma_data_direction dir,
+		 struct dma_attrs *attrs)
+{
+	void *va = phys_to_virt(page_to_phys(page)) + offset;
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	return mic_map_single(mdev, va, size);
+}
+
+static void
+mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
+		   size_t size, enum dma_data_direction dir,
+		   struct dma_attrs *attrs)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	mic_unmap_single(mdev, dma_addr, size);
+}
+
+static struct dma_map_ops mic_dma_ops = {
+	.map_page = mic_dma_map_page,
+	.unmap_page = mic_dma_unmap_page,
+};
+
+static struct mic_irq *
+_mic_request_threaded_irq(struct mbus_device *mbdev,
+			  irq_handler_t handler, irq_handler_t thread_fn,
+			  const char *name, void *data, int intr_src)
+{
+	return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
+					thread_fn, name, data,
+					intr_src, MIC_INTR_DMA);
+}
+
+static void _mic_free_irq(struct mbus_device *mbdev,
+			  struct mic_irq *cookie, void *data)
+{
+	return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
+}
+
+static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
+{
+	struct mic_device *mdev = mbdev_to_mdev(mbdev);
+	mdev->ops->intr_workarounds(mdev);
+}
+
+static struct mbus_hw_ops mbus_hw_ops = {
+	.request_threaded_irq = _mic_request_threaded_irq,
+	.free_irq = _mic_free_irq,
+	.ack_interrupt = _mic_ack_interrupt,
+};
+
 /**
  * mic_reset - Reset the MIC device.
  * @mdev: pointer to mic_device instance
@@ -95,9 +154,21 @@ retry:
 		 */
 		goto retry;
 	}
+	mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
+					       MBUS_DEV_DMA_HOST, &mic_dma_ops,
+					       &mbus_hw_ops, mdev->mmio.va);
+	if (IS_ERR(mdev->dma_mbdev)) {
+		rc = PTR_ERR(mdev->dma_mbdev);
+		goto unlock_ret;
+	}
+	mdev->dma_ch = mic_request_dma_chan(mdev);
+	if (!mdev->dma_ch) {
+		rc = -ENXIO;
+		goto dma_remove;
+	}
 	rc = mdev->ops->load_mic_fw(mdev, buf);
 	if (rc)
-		goto unlock_ret;
+		goto dma_release;
 	mic_smpt_restore(mdev);
 	mic_intr_restore(mdev);
 	mdev->intr_ops->enable_interrupts(mdev);
@@ -105,6 +176,11 @@ retry:
 	mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
 	mdev->ops->send_firmware_intr(mdev);
 	mic_set_state(mdev, MIC_ONLINE);
+	goto unlock_ret;
+dma_release:
+	dma_release_channel(mdev->dma_ch);
+dma_remove:
+	mbus_unregister_device(mdev->dma_mbdev);
 unlock_ret:
 	mutex_unlock(&mdev->mic_mutex);
 	return rc;
@@ -122,6 +198,11 @@ void mic_stop(struct mic_device *mdev, b
 	mutex_lock(&mdev->mic_mutex);
 	if (MIC_OFFLINE != mdev->state || force) {
 		mic_virtio_reset_devices(mdev);
+		if (mdev->dma_ch) {
+			dma_release_channel(mdev->dma_ch);
+			mdev->dma_ch = NULL;
+		}
+		mbus_unregister_device(mdev->dma_mbdev);
 		mic_bootparam_init(mdev);
 		mic_reset(mdev);
 		if (MIC_RESET_FAILED == mdev->state)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_device.h linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_device.h
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_device.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_device.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,8 @@
 #include <linux/idr.h>
 #include <linux/notifier.h>
 #include <linux/irqreturn.h>
+#include <linux/dmaengine.h>
+#include <linux/mic_bus.h>
 
 #include "mic_intr.h"
 
@@ -87,6 +89,8 @@ enum mic_stepping {
  * @cdev: Character device for MIC.
  * @vdev_list: list of virtio devices.
  * @pm_notifier: Handles PM notifications from the OS.
+ * @dma_mbdev: MIC BUS DMA device.
+ * @dma_ch: DMA channel reserved by this driver for use by virtio devices.
  */
 struct mic_device {
 	struct mic_mw mmio;
@@ -124,6 +128,8 @@ struct mic_device {
 	struct cdev cdev;
 	struct list_head vdev_list;
 	struct notifier_block pm_notifier;
+	struct mbus_device *dma_mbdev;
+	struct dma_chan *dma_ch;
 };
 
 /**
@@ -144,6 +150,7 @@ struct mic_device {
  * @load_mic_fw: Load firmware segments required to boot the card
  * into card memory. This includes the kernel, command line, ramdisk etc.
  * @get_postcode: Get post code status from firmware.
+ * @dma_filter: DMA filter function to be used.
  */
 struct mic_hw_ops {
 	u8 aper_bar;
@@ -159,6 +166,7 @@ struct mic_hw_ops {
 	void (*send_firmware_intr)(struct mic_device *mdev);
 	int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
 	u32 (*get_postcode)(struct mic_device *mdev);
+	bool (*dma_filter)(struct dma_chan *chan, void *param);
 };
 
 /**
@@ -187,6 +195,22 @@ mic_mmio_write(struct mic_mw *mw, u32 va
 	iowrite32(val, mw->va + offset);
 }
 
+static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_MEMCPY, mask);
+	chan = dma_request_channel(mask, mdev->ops->dma_filter,
+				   mdev->sdev->parent);
+	if (chan)
+		return chan;
+	dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n",
+		__func__, __LINE__);
+	return NULL;
+}
+
 void mic_sysfs_init(struct mic_device *mdev);
 int mic_start(struct mic_device *mdev, const char *buf);
 void mic_stop(struct mic_device *mdev, bool force);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_intr.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_intr.c
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_intr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_intr.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,28 +24,29 @@
 #include "../common/mic_dev.h"
 #include "mic_device.h"
 
-/*
- * mic_invoke_callback - Invoke callback functions registered for
- * the corresponding source id.
- *
- * @mdev: pointer to the mic_device instance
- * @idx: The interrupt source id.
- *
- * Returns none.
- */
-static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
+static irqreturn_t mic_thread_fn(int irq, void *dev)
 {
+	struct mic_device *mdev = dev;
+	struct mic_intr_info *intr_info = mdev->intr_info;
+	struct mic_irq_info *irq_info = &mdev->irq_info;
 	struct mic_intr_cb *intr_cb;
 	struct pci_dev *pdev = container_of(mdev->sdev->parent,
-		struct pci_dev, dev);
+					    struct pci_dev, dev);
+	int i;
 
-	spin_lock(&mdev->irq_info.mic_intr_lock);
-	list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
-		if (intr_cb->func)
-			intr_cb->func(pdev->irq, intr_cb->data);
-	spin_unlock(&mdev->irq_info.mic_intr_lock);
+	spin_lock(&irq_info->mic_thread_lock);
+	for (i = intr_info->intr_start_idx[MIC_INTR_DB];
+			i < intr_info->intr_len[MIC_INTR_DB]; i++)
+		if (test_and_clear_bit(i, &irq_info->mask)) {
+			list_for_each_entry(intr_cb, &irq_info->cb_list[i],
+					    list)
+				if (intr_cb->thread_fn)
+					intr_cb->thread_fn(pdev->irq,
+							 intr_cb->data);
+		}
+	spin_unlock(&irq_info->mic_thread_lock);
+	return IRQ_HANDLED;
 }
-
 /**
  * mic_interrupt - Generic interrupt handler for
  * MSI and INTx based interrupts.
@@ -53,7 +54,11 @@ static inline void mic_invoke_callback(s
 static irqreturn_t mic_interrupt(int irq, void *dev)
 {
 	struct mic_device *mdev = dev;
-	struct mic_intr_info *info = mdev->intr_info;
+	struct mic_intr_info *intr_info = mdev->intr_info;
+	struct mic_irq_info *irq_info = &mdev->irq_info;
+	struct mic_intr_cb *intr_cb;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+					    struct pci_dev, dev);
 	u32 mask;
 	int i;
 
@@ -61,12 +66,19 @@ static irqreturn_t mic_interrupt(int irq
 	if (!mask)
 		return IRQ_NONE;
 
-	for (i = info->intr_start_idx[MIC_INTR_DB];
-			i < info->intr_len[MIC_INTR_DB]; i++)
-		if (mask & BIT(i))
-			mic_invoke_callback(mdev, i);
-
-	return IRQ_HANDLED;
+	spin_lock(&irq_info->mic_intr_lock);
+	for (i = intr_info->intr_start_idx[MIC_INTR_DB];
+			i < intr_info->intr_len[MIC_INTR_DB]; i++)
+		if (mask & BIT(i)) {
+			list_for_each_entry(intr_cb, &irq_info->cb_list[i],
+					    list)
+				if (intr_cb->handler)
+					intr_cb->handler(pdev->irq,
+							 intr_cb->data);
+			set_bit(i, &irq_info->mask);
+		}
+	spin_unlock(&irq_info->mic_intr_lock);
+	return IRQ_WAKE_THREAD;
 }
 
 /* Return the interrupt offset from the index. Index is 0 based. */
@@ -99,14 +111,15 @@ static struct msix_entry *mic_get_availa
  *
  * @mdev: pointer to the mic_device instance
  * @idx: The source id to be registered.
- * @func: The function to be called when the source id receives
+ * @handler: The function to be called when the source id receives
  * the interrupt.
+ * @thread_fn: thread fn. corresponding to the handler
  * @data: Private data of the requester.
  * Return the callback structure that was registered or an
  * appropriate error on failure.
  */
 static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
-			u8 idx, irqreturn_t (*func) (int irq, void *dev),
+			u8 idx, irq_handler_t handler, irq_handler_t thread_fn,
 			void *data)
 {
 	struct mic_intr_cb *intr_cb;
@@ -117,7 +130,8 @@ static struct mic_intr_cb *mic_register_
 	if (!intr_cb)
 		return ERR_PTR(-ENOMEM);
 
-	intr_cb->func = func;
+	intr_cb->handler = handler;
+	intr_cb->thread_fn = thread_fn;
 	intr_cb->data = data;
 	intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
 		0, 0, GFP_KERNEL);
@@ -126,9 +140,11 @@ static struct mic_intr_cb *mic_register_
 		goto ida_fail;
 	}
 
+	spin_lock(&mdev->irq_info.mic_thread_lock);
 	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
 	list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
 	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+	spin_unlock(&mdev->irq_info.mic_thread_lock);
 
 	return intr_cb;
 ida_fail:
@@ -152,8 +168,9 @@ static u8 mic_unregister_intr_callback(s
 	unsigned long flags;
 	int i;
 
+	spin_lock(&mdev->irq_info.mic_thread_lock);
+	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
 	for (i = 0;  i < MIC_NUM_OFFSETS; i++) {
-		spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
 		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
 			intr_cb = list_entry(pos, struct mic_intr_cb, list);
 			if (intr_cb->cb_id == idx) {
@@ -163,11 +180,13 @@ static u8 mic_unregister_intr_callback(s
 				kfree(intr_cb);
 				spin_unlock_irqrestore(
 					&mdev->irq_info.mic_intr_lock, flags);
+				spin_unlock(&mdev->irq_info.mic_thread_lock);
 				return i;
 			}
 		}
-		spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
 	}
+	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+	spin_unlock(&mdev->irq_info.mic_thread_lock);
 	return MIC_NUM_OFFSETS;
 }
 
@@ -242,6 +261,7 @@ static int mic_setup_callbacks(struct mi
 		INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
 	ida_init(&mdev->irq_info.cb_ida);
 	spin_lock_init(&mdev->irq_info.mic_intr_lock);
+	spin_lock_init(&mdev->irq_info.mic_thread_lock);
 	return 0;
 }
 
@@ -258,14 +278,12 @@ static void mic_release_callbacks(struct
 	struct mic_intr_cb *intr_cb;
 	int i;
 
+	spin_lock(&mdev->irq_info.mic_thread_lock);
+	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
 	for (i = 0; i < MIC_NUM_OFFSETS; i++) {
-		spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
 
-		if (list_empty(&mdev->irq_info.cb_list[i])) {
-			spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
-					       flags);
+		if (list_empty(&mdev->irq_info.cb_list[i]))
 			break;
-		}
 
 		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
 			intr_cb = list_entry(pos, struct mic_intr_cb, list);
@@ -274,8 +292,9 @@ static void mic_release_callbacks(struct
 					  intr_cb->cb_id);
 			kfree(intr_cb);
 		}
-		spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
 	}
+	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+	spin_unlock(&mdev->irq_info.mic_thread_lock);
 	ida_destroy(&mdev->irq_info.cb_ida);
 	kfree(mdev->irq_info.cb_list);
 }
@@ -313,7 +332,8 @@ static int mic_setup_msi(struct mic_devi
 		goto err_nomem2;
 	}
 
-	rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
+	rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
+				  0, "mic-msi", mdev);
 	if (rc) {
 		dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
 		goto err_irq_req_fail;
@@ -353,8 +373,8 @@ static int mic_setup_intx(struct mic_dev
 		goto err_nomem;
 	}
 
-	rc = request_irq(pdev->irq, mic_interrupt,
-		IRQF_SHARED, "mic-intx", mdev);
+	rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
+				  IRQF_SHARED, "mic-intx", mdev);
 	if (rc)
 		goto err;
 
@@ -391,13 +411,14 @@ int mic_next_db(struct mic_device *mdev)
 #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
 
 /**
- * mic_request_irq - request an irq. mic_mutex needs
+ * mic_request_threaded_irq - request an irq. mic_mutex needs
  * to be held before calling this function.
  *
  * @mdev: pointer to mic_device instance
- * @func: The callback function that handles the interrupt.
+ * @handler: The callback function that handles the interrupt.
  * The function needs to call ack_interrupts
  * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
+ * @thread_fn: thread fn required by request_threaded_irq.
  * @name: The ASCII name of the callee requesting the irq.
  * @data: private data that is returned back when calling the
  * function handler.
@@ -412,10 +433,11 @@ int mic_next_db(struct mic_device *mdev)
  * error code.
  *
  */
-struct mic_irq *mic_request_irq(struct mic_device *mdev,
-	irqreturn_t (*func)(int irq, void *dev),
-	const char *name, void *data, int intr_src,
-	enum mic_intr_type type)
+struct mic_irq *
+mic_request_threaded_irq(struct mic_device *mdev,
+			 irq_handler_t handler, irq_handler_t thread_fn,
+			 const char *name, void *data, int intr_src,
+			 enum mic_intr_type type)
 {
 	u16 offset;
 	int rc = 0;
@@ -444,7 +466,8 @@ struct mic_irq *mic_request_irq(struct m
 			goto err;
 		}
 
-		rc = request_irq(msix->vector, func, 0, name, data);
+		rc = request_threaded_irq(msix->vector, handler, thread_fn,
+					  0, name, data);
 		if (rc) {
 			dev_dbg(mdev->sdev->parent,
 				"request irq failed rc = %d\n", rc);
@@ -458,8 +481,8 @@ struct mic_irq *mic_request_irq(struct m
 		dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
 			msix->vector, intr_src);
 	} else {
-		intr_cb = mic_register_intr_callback(mdev,
-				offset, func, data);
+		intr_cb = mic_register_intr_callback(mdev, offset, handler,
+						     thread_fn, data);
 		if (IS_ERR(intr_cb)) {
 			dev_err(mdev->sdev->parent,
 				"No available callback entries for use\n");
@@ -487,9 +510,9 @@ err:
  *  needs to be held before calling this function.
  *
  * @mdev: pointer to mic_device instance
- * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
  * @data: private data specified by the calling function during the
- * mic_request_irq
+ * mic_request_threaded_irq
  *
  * returns: none.
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_intr.h linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_intr.h
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_intr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_intr.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,12 +21,15 @@
 #ifndef _MIC_INTR_H_
 #define _MIC_INTR_H_
 
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
 /*
  * The minimum number of msix vectors required for normal operation.
  * 3 for virtio network, console and block devices.
  * 1 for card shutdown notifications.
+ * 4 for host owned DMA channels.
  */
-#define MIC_MIN_MSIX 4
+#define MIC_MIN_MSIX 8
 #define MIC_NUM_OFFSETS 32
 
 /**
@@ -68,7 +71,11 @@ struct mic_intr_info {
  * @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
  * @cb_ida: callback ID allocator to track the callbacks registered.
  * @mic_intr_lock: spinlock to protect the interrupt callback list.
+ * @mic_thread_lock: spinlock to protect the thread callback list.
+ *		   This lock is used to protect against thread_fn while
+ *		   mic_intr_lock is used to protect against interrupt handler.
  * @cb_list: Array of callback lists one for each source.
+ * @mask: Mask used by the main thread fn to call the underlying thread fns.
  */
 struct mic_irq_info {
 	int next_avail_src;
@@ -77,19 +84,23 @@ struct mic_irq_info {
 	u16 num_vectors;
 	struct ida cb_ida;
 	spinlock_t mic_intr_lock;
+	spinlock_t mic_thread_lock;
 	struct list_head *cb_list;
+	unsigned long mask;
 };
 
 /**
  * struct mic_intr_cb - Interrupt callback structure.
  *
- * @func: The callback function
+ * @handler: The callback function
+ * @thread_fn: The thread_fn.
  * @data: Private data of the requester.
  * @cb_id: The callback id. Identifies this callback.
  * @list: list head pointing to the next callback structure.
  */
 struct mic_intr_cb {
-	irqreturn_t (*func) (int irq, void *data);
+	irq_handler_t handler;
+	irq_handler_t thread_fn;
 	void *data;
 	int cb_id;
 	struct list_head list;
@@ -124,11 +135,11 @@ struct mic_hw_intr_ops {
 };
 
 int mic_next_db(struct mic_device *mdev);
-struct mic_irq *mic_request_irq(struct mic_device *mdev,
-	irqreturn_t (*func)(int irq, void *data),
-	const char *name, void *data, int intr_src,
-	enum mic_intr_type type);
-
+struct mic_irq *
+mic_request_threaded_irq(struct mic_device *mdev,
+			 irq_handler_t handler, irq_handler_t thread_fn,
+			 const char *name, void *data, int intr_src,
+			 enum mic_intr_type type);
 void mic_free_irq(struct mic_device *mdev,
 		struct mic_irq *cookie, void *data);
 int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_main.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_main.c
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
 
 static const char mic_driver_name[] = "mic";
 
-static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = {
+static const struct pci_device_id mic_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
@@ -389,8 +389,9 @@ static int mic_probe(struct pci_dev *pde
 	mutex_lock(&mdev->mic_mutex);
 
 	mdev->shutdown_db = mic_next_db(mdev);
-	mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db,
-		"shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB);
+	mdev->shutdown_cookie = mic_request_threaded_irq(mdev, mic_shutdown_db,
+					NULL, "shutdown-interrupt", mdev,
+					mdev->shutdown_db, MIC_INTR_DB);
 	if (IS_ERR(mdev->shutdown_cookie)) {
 		rc = PTR_ERR(mdev->shutdown_cookie);
 		mutex_unlock(&mdev->mic_mutex);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_virtio.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_virtio.c
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_virtio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_virtio.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,60 +21,157 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
-
+#include <linux/dmaengine.h>
 #include <linux/mic_common.h>
+
 #include "../common/mic_dev.h"
 #include "mic_device.h"
 #include "mic_smpt.h"
 #include "mic_virtio.h"
 
 /*
- * Initiates the copies across the PCIe bus from card memory to
- * a user space buffer.
+ * Size of the internal buffer used during DMA's as an intermediate buffer
+ * for copy to/from user.
  */
-static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
-		void __user *ubuf, size_t len, u64 addr)
+#define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
+
+static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
+			dma_addr_t src, size_t len)
 {
-	int err;
-	void __iomem *dbuf = mvdev->mdev->aper.va + addr;
-	/*
-	 * We are copying from IO below an should ideally use something
-	 * like copy_to_user_fromio(..) if it existed.
-	 */
-	if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
-		err = -EFAULT;
-		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+	int err = 0;
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *mic_ch = mdev->dma_ch;
+
+	if (!mic_ch) {
+		err = -EBUSY;
+		goto error;
+	}
+
+	tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len,
+						    DMA_PREP_FENCE);
+	if (!tx) {
+		err = -ENOMEM;
+		goto error;
+	} else {
+		dma_cookie_t cookie = tx->tx_submit(tx);
+
+		err = dma_submit_error(cookie);
+		if (err)
+			goto error;
+		err = dma_sync_wait(mic_ch, cookie);
+	}
+error:
+	if (err)
+		dev_err(mdev->sdev->parent, "%s %d err %d\n",
 			__func__, __LINE__, err);
-		goto err;
+	return err;
+}
+
+/*
+ * Initiates the copies across the PCIe bus from card memory to a user
+ * space buffer. When transfers are done using DMA, source/destination
+ * addresses and transfer length must follow the alignment requirements of
+ * the MIC DMA engine.
+ */
+static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf,
+				   size_t len, u64 daddr, size_t dlen,
+				   int vr_idx)
+{
+	struct mic_device *mdev = mvdev->mdev;
+	void __iomem *dbuf = mdev->aper.va + daddr;
+	struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
+	size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
+	size_t dma_offset;
+	size_t partlen;
+	int err;
+
+	dma_offset = daddr - round_down(daddr, dma_alignment);
+	daddr -= dma_offset;
+	len += dma_offset;
+
+	while (len) {
+		partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
+
+		err = mic_sync_dma(mdev, mvr->buf_da, daddr,
+				   ALIGN(partlen, dma_alignment));
+		if (err)
+			goto err;
+
+		if (copy_to_user(ubuf, mvr->buf + dma_offset,
+				 partlen - dma_offset)) {
+			err = -EFAULT;
+			goto err;
+		}
+		daddr += partlen;
+		ubuf += partlen;
+		dbuf += partlen;
+		mvdev->in_bytes_dma += partlen;
+		mvdev->in_bytes += partlen;
+		len -= partlen;
+		dma_offset = 0;
 	}
-	mvdev->in_bytes += len;
-	err = 0;
+	return 0;
 err:
+	dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
 	return err;
 }
 
 /*
- * Initiates copies across the PCIe bus from a user space
- * buffer to card memory.
+ * Initiates copies across the PCIe bus from a user space buffer to card
+ * memory. When transfers are done using DMA, source/destination addresses
+ * and transfer length must follow the alignment requirements of the MIC
+ * DMA engine.
  */
-static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
-		void __user *ubuf, size_t len, u64 addr)
+static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf,
+				     size_t len, u64 daddr, size_t dlen,
+				     int vr_idx)
 {
+	struct mic_device *mdev = mvdev->mdev;
+	void __iomem *dbuf = mdev->aper.va + daddr;
+	struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
+	size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
+	size_t partlen;
 	int err;
-	void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+
+	if (daddr & (dma_alignment - 1)) {
+		mvdev->tx_dst_unaligned += len;
+		goto memcpy;
+	} else if (ALIGN(len, dma_alignment) > dlen) {
+		mvdev->tx_len_unaligned += len;
+		goto memcpy;
+	}
+
+	while (len) {
+		partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
+
+		if (copy_from_user(mvr->buf, ubuf, partlen)) {
+			err = -EFAULT;
+			goto err;
+		}
+		err = mic_sync_dma(mdev, daddr, mvr->buf_da,
+				   ALIGN(partlen, dma_alignment));
+		if (err)
+			goto err;
+		daddr += partlen;
+		ubuf += partlen;
+		dbuf += partlen;
+		mvdev->out_bytes_dma += partlen;
+		mvdev->out_bytes += partlen;
+		len -= partlen;
+	}
+memcpy:
 	/*
 	 * We are copying to IO below and should ideally use something
 	 * like copy_from_user_toio(..) if it existed.
 	 */
 	if (copy_from_user((void __force *)dbuf, ubuf, len)) {
 		err = -EFAULT;
-		dev_err(mic_dev(mvdev), "%s %d err %d\n",
-			__func__, __LINE__, err);
 		goto err;
 	}
 	mvdev->out_bytes += len;
-	err = 0;
+	return 0;
 err:
+	dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
 	return err;
 }
 
@@ -110,7 +207,8 @@ static inline u32 mic_vringh_iov_consume
  * way to override the VRINGH xfer(..) routines as of v3.10.
  */
 static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
-	void __user *ubuf, size_t len, bool read, size_t *out_len)
+			void __user *ubuf, size_t len, bool read, int vr_idx,
+			size_t *out_len)
 {
 	int ret = 0;
 	size_t partlen, tot_len = 0;
@@ -118,13 +216,15 @@ static int mic_vringh_copy(struct mic_vd
 	while (len && iov->i < iov->used) {
 		partlen = min(iov->iov[iov->i].iov_len, len);
 		if (read)
-			ret = mic_virtio_copy_to_user(mvdev,
-				ubuf, partlen,
-				(u64)iov->iov[iov->i].iov_base);
+			ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen,
+						(u64)iov->iov[iov->i].iov_base,
+						iov->iov[iov->i].iov_len,
+						vr_idx);
 		else
-			ret = mic_virtio_copy_from_user(mvdev,
-				ubuf, partlen,
-				(u64)iov->iov[iov->i].iov_base);
+			ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen,
+						(u64)iov->iov[iov->i].iov_base,
+						iov->iov[iov->i].iov_len,
+						vr_idx);
 		if (ret) {
 			dev_err(mic_dev(mvdev), "%s %d err %d\n",
 				__func__, __LINE__, ret);
@@ -192,8 +292,8 @@ static int _mic_virtio_copy(struct mic_v
 			ubuf = iov.iov_base;
 		}
 		/* Issue all the read descriptors first */
-		ret = mic_vringh_copy(mvdev, riov, ubuf, len,
-			MIC_VRINGH_READ, &out_len);
+		ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ,
+				      copy->vr_idx, &out_len);
 		if (ret) {
 			dev_err(mic_dev(mvdev), "%s %d err %d\n",
 				__func__, __LINE__, ret);
@@ -203,8 +303,8 @@ static int _mic_virtio_copy(struct mic_v
 		ubuf += out_len;
 		copy->out_len += out_len;
 		/* Issue the write descriptors next */
-		ret = mic_vringh_copy(mvdev, wiov, ubuf, len,
-			!MIC_VRINGH_READ, &out_len);
+		ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ,
+				      copy->vr_idx, &out_len);
 		if (ret) {
 			dev_err(mic_dev(mvdev), "%s %d err %d\n",
 				__func__, __LINE__, ret);
@@ -589,13 +689,19 @@ int mic_virtio_add_device(struct mic_vde
 		dev_dbg(mdev->sdev->parent,
 			"%s %d index %d va %p info %p vr_size 0x%x\n",
 			__func__, __LINE__, i, vr->va, vr->info, vr_size);
+		mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
+					get_order(MIC_INT_DMA_BUF_SIZE));
+		mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf,
+					  MIC_INT_DMA_BUF_SIZE);
 	}
 
 	snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
 		 mvdev->virtio_id);
 	mvdev->virtio_db = mic_next_db(mdev);
-	mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler,
-			irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB);
+	mvdev->virtio_cookie = mic_request_threaded_irq(mdev,
+					       mic_virtio_intr_handler,
+					       NULL, irqname, mvdev,
+					       mvdev->virtio_db, MIC_INTR_DB);
 	if (IS_ERR(mvdev->virtio_cookie)) {
 		ret = PTR_ERR(mvdev->virtio_cookie);
 		dev_dbg(mdev->sdev->parent, "request irq failed\n");
@@ -671,6 +777,11 @@ skip_hot_remove:
 	vqconfig = mic_vq_config(mvdev->dd);
 	for (i = 0; i < mvdev->dd->num_vq; i++) {
 		struct mic_vringh *mvr = &mvdev->mvr[i];
+
+		mic_unmap_single(mvdev->mdev, mvr->buf_da,
+				 MIC_INT_DMA_BUF_SIZE);
+		free_pages((unsigned long)mvr->buf,
+			   get_order(MIC_INT_DMA_BUF_SIZE));
 		vringh_kiov_cleanup(&mvr->riov);
 		vringh_kiov_cleanup(&mvr->wiov);
 		mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_virtio.h linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_virtio.h
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_virtio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_virtio.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,18 +46,23 @@
  * @vrh: The host VRINGH used for accessing the card vrings.
  * @riov: The VRINGH read kernel IOV.
  * @wiov: The VRINGH write kernel IOV.
- * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
  * @vr_mutex: Mutex for synchronizing access to the VRING.
+ * @buf: Temporary kernel buffer used to copy in/out data
+ * from/to the card via DMA.
+ * @buf_da: dma address of buf.
  * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
+ * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
  */
 struct mic_vringh {
 	struct mic_vring vring;
 	struct vringh vrh;
 	struct vringh_kiov riov;
 	struct vringh_kiov wiov;
-	u16 head;
 	struct mutex vr_mutex;
+	void *buf;
+	dma_addr_t buf_da;
 	struct mic_vdev *mvdev;
+	u16 head;
 };
 
 /**
@@ -69,6 +74,14 @@ struct mic_vringh {
  * @poll_wake - Used for waking up threads blocked in poll.
  * @out_bytes - Debug stats for number of bytes copied from host to card.
  * @in_bytes - Debug stats for number of bytes copied from card to host.
+ * @out_bytes_dma - Debug stats for number of bytes copied from host to card
+ * using DMA.
+ * @in_bytes_dma - Debug stats for number of bytes copied from card to host
+ * using DMA.
+ * @tx_len_unaligned - Debug stats for number of bytes copied to the card where
+ * the transfer length did not have the required DMA alignment.
+ * @tx_dst_unaligned - Debug stats for number of bytes copied where the
+ * destination address on the card did not have the required DMA alignment.
  * @mvr - Store per VRING data structures.
  * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
  * @dd - Virtio device descriptor.
@@ -84,6 +97,10 @@ struct mic_vdev {
 	int poll_wake;
 	unsigned long out_bytes;
 	unsigned long in_bytes;
+	unsigned long out_bytes_dma;
+	unsigned long in_bytes_dma;
+	unsigned long tx_len_unaligned;
+	unsigned long tx_dst_unaligned;
 	struct mic_vringh mvr[MIC_MAX_VRINGS];
 	struct work_struct virtio_bh_work;
 	struct mic_device_desc *dd;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/host/mic_x100.c linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_x100.c
--- linux-libre-3.16-gnu/drivers/misc/mic/host/mic_x100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/host/mic_x100.c	2014-09-28 17:29:07.000000000 -0400
@@ -549,6 +549,13 @@ struct mic_smpt_ops mic_x100_smpt_ops =
 	.set = mic_x100_smpt_set,
 };
 
+static bool mic_x100_dma_filter(struct dma_chan *chan, void *param)
+{
+	if (chan->device->dev->parent == (struct device *)param)
+		return true;
+	return false;
+}
+
 struct mic_hw_ops mic_x100_ops = {
 	.aper_bar = MIC_X100_APER_BAR,
 	.mmio_bar = MIC_X100_MMIO_BAR,
@@ -563,6 +570,7 @@ struct mic_hw_ops mic_x100_ops = {
 	.send_firmware_intr = mic_x100_send_firmware_intr,
 	.load_mic_fw = mic_x100_load_firmware,
 	.get_postcode = mic_x100_get_postcode,
+	.dma_filter = mic_x100_dma_filter,
 };
 
 struct mic_hw_intr_ops mic_x100_intr_ops = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/Kconfig linux-libre-3.17-rc7-gnu/drivers/misc/mic/Kconfig
--- linux-libre-3.16-gnu/drivers/misc/mic/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,25 @@
+comment "Intel MIC Bus Driver"
+
+config INTEL_MIC_BUS
+	tristate "Intel MIC Bus Driver"
+	depends on 64BIT && PCI && X86 && X86_DEV_DMA_OPS
+	help
+	  This option is selected by any driver which registers a
+	  device or driver on the MIC Bus, such as CONFIG_INTEL_MIC_HOST,
+	  CONFIG_INTEL_MIC_CARD, CONFIG_INTEL_MIC_X100_DMA etc.
+
+	  If you are building a host/card kernel with an Intel MIC device
+	  then say M (recommended) or Y, else say N. If unsure say N.
+
+	  More information about the Intel MIC family as well as the Linux
+	  OS and tools for MIC to use with this driver are available from
+	  <http://software.intel.com/en-us/mic-developer>.
+
 comment "Intel MIC Host Driver"
 
 config INTEL_MIC_HOST
 	tristate "Intel MIC Host Driver"
-	depends on 64BIT && PCI && X86
+	depends on 64BIT && PCI && X86 && INTEL_MIC_BUS
 	select VHOST_RING
 	help
 	  This enables Host Driver support for the Intel Many Integrated
@@ -22,7 +39,7 @@ comment "Intel MIC Card Driver"
 
 config INTEL_MIC_CARD
 	tristate "Intel MIC Card Driver"
-	depends on 64BIT && X86
+	depends on 64BIT && X86 && INTEL_MIC_BUS
 	select VIRTIO
 	help
 	  This enables card driver support for the Intel Many Integrated
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/mic/Makefile linux-libre-3.17-rc7-gnu/drivers/misc/mic/Makefile
--- linux-libre-3.16-gnu/drivers/misc/mic/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/mic/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,3 +4,4 @@
 #
 obj-$(CONFIG_INTEL_MIC_HOST) += host/
 obj-$(CONFIG_INTEL_MIC_CARD) += card/
+obj-$(CONFIG_INTEL_MIC_BUS) += bus/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/sgi-xp/xpnet.c linux-libre-3.17-rc7-gnu/drivers/misc/sgi-xp/xpnet.c
--- linux-libre-3.16-gnu/drivers/misc/sgi-xp/xpnet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/sgi-xp/xpnet.c	2014-09-28 17:29:07.000000000 -0400
@@ -544,7 +544,8 @@ xpnet_init(void)
 	 * use ether_setup() to init the majority of our device
 	 * structure and then override the necessary pieces.
 	 */
-	xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, ether_setup);
+	xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, NET_NAME_UNKNOWN,
+				    ether_setup);
 	if (xpnet_device == NULL) {
 		kfree(xpnet_broadcast_partitions);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/ti-st/st_kim.c linux-libre-3.17-rc7-gnu/drivers/misc/ti-st/st_kim.c
--- linux-libre-3.16-gnu/drivers/misc/ti-st/st_kim.c	2014-08-07 04:58:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/ti-st/st_kim.c	2014-09-28 21:40:35.000000000 -0400
@@ -244,7 +244,8 @@ static long read_local_version(struct ki
 	if (version & 0x8000)
 		maj_ver |= 0x0008;
 
-	sprintf(bts_scr_name, "/*(DEBLOBBED)*/", chip, maj_ver, min_ver);
+	sprintf(bts_scr_name, "/*(DEBLOBBED)*/",
+		chip, maj_ver, min_ver);
 
 	/* to be accessed later via sysfs entry */
 	kim_gdata->version.full = version;
@@ -287,7 +288,7 @@ static long download_firmware(struct kim
 	long len = 0;
 	unsigned char *ptr = NULL;
 	unsigned char *action_ptr = NULL;
-	unsigned char bts_scr_name[30] = { 0 };	/* 30 char long bts scr name? */
+	unsigned char bts_scr_name[40] = { 0 };	/* 40 char long bts scr name? */
 	int wr_room_space;
 	int cmd_size;
 	unsigned long timeout;
@@ -778,7 +779,7 @@ static int kim_probe(struct platform_dev
 	pr_info("sysfs entries created\n");
 
 	kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
-	if (IS_ERR(kim_debugfs_dir)) {
+	if (!kim_debugfs_dir) {
 		pr_err(" debugfs entries creation failed ");
 		err = -EIO;
 		goto err_debugfs_dir;
@@ -788,7 +789,6 @@ static int kim_probe(struct platform_dev
 				kim_gdata, &version_debugfs_fops);
 	debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir,
 				kim_gdata, &list_debugfs_fops);
-	pr_info(" debugfs entries created ");
 	return 0;
 
 err_debugfs_dir:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/vexpress-syscfg.c linux-libre-3.17-rc7-gnu/drivers/misc/vexpress-syscfg.c
--- linux-libre-3.16-gnu/drivers/misc/vexpress-syscfg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/vexpress-syscfg.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,7 +130,7 @@ static int vexpress_syscfg_write(void *c
 	return vexpress_syscfg_exec(func, index, true, &val);
 }
 
-struct regmap_config vexpress_syscfg_regmap_config = {
+static struct regmap_config vexpress_syscfg_regmap_config = {
 	.lock = vexpress_config_lock,
 	.unlock = vexpress_config_unlock,
 	.reg_bits = 32,
@@ -276,7 +276,7 @@ int vexpress_syscfg_device_register(stru
 }
 
 
-int vexpress_syscfg_probe(struct platform_device *pdev)
+static int vexpress_syscfg_probe(struct platform_device *pdev)
 {
 	struct vexpress_syscfg *syscfg;
 	struct resource *res;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/misc/vmw_vmci/vmci_guest.c linux-libre-3.17-rc7-gnu/drivers/misc/vmw_vmci/vmci_guest.c
--- linux-libre-3.16-gnu/drivers/misc/vmw_vmci/vmci_guest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/misc/vmw_vmci/vmci_guest.c	2014-09-28 17:29:07.000000000 -0400
@@ -748,7 +748,7 @@ static void vmci_guest_remove_device(str
 	/* The rest are managed resources and will be freed by PCI core */
 }
 
-static DEFINE_PCI_DEVICE_TABLE(vmci_ids) = {
+static const struct pci_device_id vmci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_VMCI), },
 	{ 0 },
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/card/block.c linux-libre-3.17-rc7-gnu/drivers/mmc/card/block.c
--- linux-libre-3.16-gnu/drivers/mmc/card/block.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/card/block.c	2014-09-28 17:29:07.000000000 -0400
@@ -2028,8 +2028,7 @@ static int mmc_blk_issue_rq(struct mmc_q
 		/* complete ongoing async transfer before issuing discard */
 		if (card->host->areq)
 			mmc_blk_issue_rw_rq(mq, NULL);
-		if (req->cmd_flags & REQ_SECURE &&
-			!(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
+		if (req->cmd_flags & REQ_SECURE)
 			ret = mmc_blk_issue_secdiscard_rq(mq, req);
 		else
 			ret = mmc_blk_issue_discard_rq(mq, req);
@@ -2432,6 +2431,8 @@ static int mmc_blk_probe(struct mmc_card
 	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);
@@ -2446,7 +2447,6 @@ static int mmc_blk_probe(struct mmc_card
 		goto out;
 
 	mmc_set_drvdata(card, md);
-	mmc_fixup_device(card, blk_fixups);
 
 	if (mmc_add_disk(md))
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/core/bus.c linux-libre-3.17-rc7-gnu/drivers/mmc/core/bus.c
--- linux-libre-3.16-gnu/drivers/mmc/core/bus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/core/bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -180,7 +180,6 @@ static int mmc_bus_resume(struct device
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
-
 static int mmc_runtime_suspend(struct device *dev)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
@@ -196,17 +195,10 @@ static int mmc_runtime_resume(struct dev
 
 	return host->bus_ops->runtime_resume(host);
 }
-
-static int mmc_runtime_idle(struct device *dev)
-{
-	return 0;
-}
-
 #endif /* !CONFIG_PM_RUNTIME */
 
 static const struct dev_pm_ops mmc_bus_pm_ops = {
-	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
-			mmc_runtime_idle)
+	SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, NULL)
 	SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/core/core.c linux-libre-3.17-rc7-gnu/drivers/mmc/core/core.c
--- linux-libre-3.16-gnu/drivers/mmc/core/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/core/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -2102,7 +2102,8 @@ EXPORT_SYMBOL(mmc_can_sanitize);
 
 int mmc_can_secure_erase_trim(struct mmc_card *card)
 {
-	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)
+	if ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) &&
+	    !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
 		return 1;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/core/mmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/core/mmc.c
--- linux-libre-3.16-gnu/drivers/mmc/core/mmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/core/mmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -324,13 +324,12 @@ static int mmc_read_ext_csd(struct mmc_c
 		}
 	}
 
+	/*
+	 * The EXT_CSD format is meant to be forward compatible. As long
+	 * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
+	 * are authorized, see JEDEC JESD84-B50 section B.8.
+	 */
 	card->ext_csd.rev = ext_csd[EXT_CSD_REV];
-	if (card->ext_csd.rev > 7) {
-		pr_err("%s: unrecognised EXT_CSD revision %d\n",
-			mmc_hostname(card->host), card->ext_csd.rev);
-		err = -EINVAL;
-		goto out;
-	}
 
 	card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
 	card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/core/quirks.c linux-libre-3.17-rc7-gnu/drivers/mmc/core/quirks.c
--- linux-libre-3.16-gnu/drivers/mmc/core/quirks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/core/quirks.c	2014-09-28 17:29:07.000000000 -0400
@@ -91,7 +91,7 @@ void mmc_fixup_device(struct mmc_card *c
 		    (f->cis_device == card->cis.device ||
 		     f->cis_device == (u16) SDIO_ANY_ID) &&
 		    rev >= f->rev_start && rev <= f->rev_end) {
-			dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
+			dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup);
 			f->vendor_fixup(card, f->data);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/core/sd_ops.c linux-libre-3.17-rc7-gnu/drivers/mmc/core/sd_ops.c
--- linux-libre-3.16-gnu/drivers/mmc/core/sd_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/core/sd_ops.c	2014-09-28 17:29:07.000000000 -0400
@@ -184,6 +184,9 @@ int mmc_send_app_op_cond(struct mmc_host
 		mmc_delay(10);
 	}
 
+	if (!i)
+		pr_err("%s: card never left busy state\n", mmc_hostname(host));
+
 	if (rocr && !mmc_host_is_spi(host))
 		*rocr = cmd.resp[0];
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/au1xmmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/au1xmmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/au1xmmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/au1xmmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,7 @@
  * (the low to high transition will not occur).
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -90,7 +91,7 @@ struct au1xmmc_host {
 	struct mmc_request *mrq;
 
 	u32 flags;
-	u32 iobase;
+	void __iomem *iobase;
 	u32 clock;
 	u32 bus_width;
 	u32 power_mode;
@@ -118,6 +119,7 @@ struct au1xmmc_host {
 	struct au1xmmc_platform_data *platdata;
 	struct platform_device *pdev;
 	struct resource *ioarea;
+	struct clk *clk;
 };
 
 /* Status flags used by the host structure */
@@ -162,32 +164,33 @@ static inline int has_dbdma(void)
 
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
-	u32 val = au_readl(HOST_CONFIG(host));
+	u32 val = __raw_readl(HOST_CONFIG(host));
 	val |= mask;
-	au_writel(val, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void FLUSH_FIFO(struct au1xmmc_host *host)
 {
-	u32 val = au_readl(HOST_CONFIG2(host));
+	u32 val = __raw_readl(HOST_CONFIG2(host));
 
-	au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
-	au_sync_delay(1);
+	__raw_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
 	/* SEND_STOP will turn off clock control - this re-enables it */
 	val &= ~SD_CONFIG2_DF;
 
-	au_writel(val, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
 {
-	u32 val = au_readl(HOST_CONFIG(host));
+	u32 val = __raw_readl(HOST_CONFIG(host));
 	val &= ~mask;
-	au_writel(val, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void SEND_STOP(struct au1xmmc_host *host)
@@ -197,12 +200,13 @@ static inline void SEND_STOP(struct au1x
 	WARN_ON(host->status != HOST_S_DATA);
 	host->status = HOST_S_STOP;
 
-	config2 = au_readl(HOST_CONFIG2(host));
-	au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
-	au_sync();
+	config2 = __raw_readl(HOST_CONFIG2(host));
+	__raw_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	/* Send the stop command */
-	au_writel(STOP_CMD, HOST_CMD(host));
+	__raw_writel(STOP_CMD, HOST_CMD(host));
+	wmb(); /* drain writebuffer */
 }
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
@@ -296,28 +300,28 @@ static int au1xmmc_send_command(struct a
 		}
 	}
 
-	au_writel(cmd->arg, HOST_CMDARG(host));
-	au_sync();
+	__raw_writel(cmd->arg, HOST_CMDARG(host));
+	wmb(); /* drain writebuffer */
 
 	if (wait)
 		IRQ_OFF(host, SD_CONFIG_CR);
 
-	au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
-	au_sync();
+	__raw_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+	wmb(); /* drain writebuffer */
 
 	/* Wait for the command to go on the line */
-	while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
+	while (__raw_readl(HOST_CMD(host)) & SD_CMD_GO)
 		/* nop */;
 
 	/* Wait for the command to come back */
 	if (wait) {
-		u32 status = au_readl(HOST_STATUS(host));
+		u32 status = __raw_readl(HOST_STATUS(host));
 
 		while (!(status & SD_STATUS_CR))
-			status = au_readl(HOST_STATUS(host));
+			status = __raw_readl(HOST_STATUS(host));
 
 		/* Clear the CR status */
-		au_writel(SD_STATUS_CR, HOST_STATUS(host));
+		__raw_writel(SD_STATUS_CR, HOST_STATUS(host));
 
 		IRQ_ON(host, SD_CONFIG_CR);
 	}
@@ -339,11 +343,11 @@ static void au1xmmc_data_complete(struct
 	data = mrq->cmd->data;
 
 	if (status == 0)
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 	/* The transaction is really over when the SD_STATUS_DB bit is clear */
 	while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 	data->error = 0;
 	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
@@ -357,7 +361,7 @@ static void au1xmmc_data_complete(struct
 		data->error = -EILSEQ;
 
 	/* Clear the CRC bits */
-	au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+	__raw_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
 
 	data->bytes_xfered = 0;
 
@@ -380,7 +384,7 @@ static void au1xmmc_tasklet_data(unsigne
 {
 	struct au1xmmc_host *host = (struct au1xmmc_host *)param;
 
-	u32 status = au_readl(HOST_STATUS(host));
+	u32 status = __raw_readl(HOST_STATUS(host));
 	au1xmmc_data_complete(host, status);
 }
 
@@ -412,15 +416,15 @@ static void au1xmmc_send_pio(struct au1x
 		max = AU1XMMC_MAX_TRANSFER;
 
 	for (count = 0; count < max; count++) {
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_TH))
 			break;
 
 		val = *sg_ptr++;
 
-		au_writel((unsigned long)val, HOST_TXPORT(host));
-		au_sync();
+		__raw_writel((unsigned long)val, HOST_TXPORT(host));
+		wmb(); /* drain writebuffer */
 	}
 
 	host->pio.len -= count;
@@ -472,7 +476,7 @@ static void au1xmmc_receive_pio(struct a
 		max = AU1XMMC_MAX_TRANSFER;
 
 	for (count = 0; count < max; count++) {
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_NE))
 			break;
@@ -494,7 +498,7 @@ static void au1xmmc_receive_pio(struct a
 			break;
 		}
 
-		val = au_readl(HOST_RXPORT(host));
+		val = __raw_readl(HOST_RXPORT(host));
 
 		if (sg_ptr)
 			*sg_ptr++ = (unsigned char)(val & 0xFF);
@@ -537,10 +541,10 @@ static void au1xmmc_cmd_complete(struct
 
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136) {
-			r[0] = au_readl(host->iobase + SD_RESP3);
-			r[1] = au_readl(host->iobase + SD_RESP2);
-			r[2] = au_readl(host->iobase + SD_RESP1);
-			r[3] = au_readl(host->iobase + SD_RESP0);
+			r[0] = __raw_readl(host->iobase + SD_RESP3);
+			r[1] = __raw_readl(host->iobase + SD_RESP2);
+			r[2] = __raw_readl(host->iobase + SD_RESP1);
+			r[3] = __raw_readl(host->iobase + SD_RESP0);
 
 			/* The CRC is omitted from the response, so really
 			 * we only got 120 bytes, but the engine expects
@@ -559,7 +563,7 @@ static void au1xmmc_cmd_complete(struct
 			 * that means that the OSR data starts at bit 31,
 			 * so we can just read RESP0 and return that.
 			 */
-			cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+			cmd->resp[0] = __raw_readl(host->iobase + SD_RESP0);
 		}
 	}
 
@@ -586,7 +590,7 @@ static void au1xmmc_cmd_complete(struct
 			u32 mask = SD_STATUS_DB | SD_STATUS_NE;
 
 			while((status & mask) != mask)
-				status = au_readl(HOST_STATUS(host));
+				status = __raw_readl(HOST_STATUS(host));
 		}
 
 		au1xxx_dbdma_start(channel);
@@ -595,24 +599,17 @@ static void au1xmmc_cmd_complete(struct
 
 static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 {
-	unsigned int pbus = get_au1x00_speed();
-	unsigned int divisor;
+	unsigned int pbus = clk_get_rate(host->clk);
+	unsigned int divisor = ((pbus / rate) / 2) - 1;
 	u32 config;
 
-	/* From databook:
-	 * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
-	 */
-	pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
-	pbus /= 2;
-	divisor = ((pbus / rate) / 2) - 1;
-
-	config = au_readl(HOST_CONFIG(host));
+	config = __raw_readl(HOST_CONFIG(host));
 
 	config &= ~(SD_CONFIG_DIV);
 	config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
 
-	au_writel(config, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(config, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static int au1xmmc_prepare_data(struct au1xmmc_host *host,
@@ -636,7 +633,7 @@ static int au1xmmc_prepare_data(struct a
 	if (host->dma.len == 0)
 		return -ETIMEDOUT;
 
-	au_writel(data->blksz - 1, HOST_BLKSIZE(host));
+	__raw_writel(data->blksz - 1, HOST_BLKSIZE(host));
 
 	if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
 		int i;
@@ -723,31 +720,34 @@ static void au1xmmc_request(struct mmc_h
 static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 {
 	/* Apply the clock */
-	au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
-        au_sync_delay(1);
+	__raw_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
-	au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
-	au_sync_delay(5);
+	__raw_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
+	mdelay(5);
 
-	au_writel(~0, HOST_STATUS(host));
-	au_sync();
+	__raw_writel(~0, HOST_STATUS(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(0, HOST_BLKSIZE(host));
-	au_writel(0x001fffff, HOST_TIMEOUT(host));
-	au_sync();
+	__raw_writel(0, HOST_BLKSIZE(host));
+	__raw_writel(0x001fffff, HOST_TIMEOUT(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-        au_sync();
+	__raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
-	au_sync_delay(1);
+	__raw_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
-	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	/* Configure interrupts */
-	au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 
@@ -767,7 +767,7 @@ static void au1xmmc_set_ios(struct mmc_h
 		host->clock = ios->clock;
 	}
 
-	config2 = au_readl(HOST_CONFIG2(host));
+	config2 = __raw_readl(HOST_CONFIG2(host));
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_8:
 		config2 |= SD_CONFIG2_BB;
@@ -780,8 +780,8 @@ static void au1xmmc_set_ios(struct mmc_h
 		config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
 		break;
 	}
-	au_writel(config2, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(config2, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 }
 
 #define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
@@ -793,7 +793,7 @@ static irqreturn_t au1xmmc_irq(int irq,
 	struct au1xmmc_host *host = dev_id;
 	u32 status;
 
-	status = au_readl(HOST_STATUS(host));
+	status = __raw_readl(HOST_STATUS(host));
 
 	if (!(status & SD_STATUS_I))
 		return IRQ_NONE;	/* not ours */
@@ -839,8 +839,8 @@ static irqreturn_t au1xmmc_irq(int irq,
 				status);
 	}
 
-	au_writel(status, HOST_STATUS(host));
-	au_sync();
+	__raw_writel(status, HOST_STATUS(host));
+	wmb(); /* drain writebuffer */
 
 	return IRQ_HANDLED;
 }
@@ -976,7 +976,7 @@ static int au1xmmc_probe(struct platform
 		goto out1;
 	}
 
-	host->iobase = (unsigned long)ioremap(r->start, 0x3c);
+	host->iobase = ioremap(r->start, 0x3c);
 	if (!host->iobase) {
 		dev_err(&pdev->dev, "cannot remap mmio\n");
 		goto out2;
@@ -1025,6 +1025,16 @@ static int au1xmmc_probe(struct platform
 		goto out3;
 	}
 
+	host->clk = clk_get(&pdev->dev, ALCHEMY_PERIPH_CLK);
+	if (IS_ERR(host->clk)) {
+		dev_err(&pdev->dev, "cannot find clock\n");
+		goto out_irq;
+	}
+	if (clk_prepare_enable(host->clk)) {
+		dev_err(&pdev->dev, "cannot enable clock\n");
+		goto out_clk;
+	}
+
 	host->status = HOST_S_IDLE;
 
 	/* board-specific carddetect setup, if any */
@@ -1075,7 +1085,7 @@ static int au1xmmc_probe(struct platform
 
 	platform_set_drvdata(pdev, host);
 
-	pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+	pr_info(DRIVER_NAME ": MMC Controller %d set up at %p"
 		" (mode=%s)\n", pdev->id, host->iobase,
 		host->flags & HOST_F_DMA ? "dma" : "pio");
 
@@ -1087,10 +1097,10 @@ out6:
 		led_classdev_unregister(host->platdata->led);
 out5:
 #endif
-	au_writel(0, HOST_ENABLE(host));
-	au_writel(0, HOST_CONFIG(host));
-	au_writel(0, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(0, HOST_ENABLE(host));
+	__raw_writel(0, HOST_CONFIG(host));
+	__raw_writel(0, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	if (host->flags & HOST_F_DBDMA)
 		au1xmmc_dbdma_shutdown(host);
@@ -1101,7 +1111,10 @@ out5:
 	if (host->platdata && host->platdata->cd_setup &&
 	    !(mmc->caps & MMC_CAP_NEEDS_POLL))
 		host->platdata->cd_setup(mmc, 0);
-
+out_clk:
+	clk_disable_unprepare(host->clk);
+	clk_put(host->clk);
+out_irq:
 	free_irq(host->irq, host);
 out3:
 	iounmap((void *)host->iobase);
@@ -1130,10 +1143,10 @@ static int au1xmmc_remove(struct platfor
 		    !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
 			host->platdata->cd_setup(host->mmc, 0);
 
-		au_writel(0, HOST_ENABLE(host));
-		au_writel(0, HOST_CONFIG(host));
-		au_writel(0, HOST_CONFIG2(host));
-		au_sync();
+		__raw_writel(0, HOST_ENABLE(host));
+		__raw_writel(0, HOST_CONFIG(host));
+		__raw_writel(0, HOST_CONFIG2(host));
+		wmb(); /* drain writebuffer */
 
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
@@ -1143,6 +1156,9 @@ static int au1xmmc_remove(struct platfor
 
 		au1xmmc_set_power(host, 0);
 
+		clk_disable_unprepare(host->clk);
+		clk_put(host->clk);
+
 		free_irq(host->irq, host);
 		iounmap((void *)host->iobase);
 		release_resource(host->ioarea);
@@ -1158,11 +1174,11 @@ static int au1xmmc_suspend(struct platfo
 {
 	struct au1xmmc_host *host = platform_get_drvdata(pdev);
 
-	au_writel(0, HOST_CONFIG2(host));
-	au_writel(0, HOST_CONFIG(host));
-	au_writel(0xffffffff, HOST_STATUS(host));
-	au_writel(0, HOST_ENABLE(host));
-	au_sync();
+	__raw_writel(0, HOST_CONFIG2(host));
+	__raw_writel(0, HOST_CONFIG(host));
+	__raw_writel(0xffffffff, HOST_STATUS(host));
+	__raw_writel(0, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[
 	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host);
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
+static bool dw_mci_reset(struct dw_mci *host);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -997,7 +996,8 @@ static int dw_mci_get_ro(struct mmc_host
 	int gpio_ro = mmc_gpio_get_ro(mmc);
 
 	/* Use platform get_ro function, else try on board write protect */
-	if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
+	if ((slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) ||
+			(slot->host->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT))
 		read_only = 0;
 	else if (!IS_ERR_VALUE(gpio_ro))
 		read_only = gpio_ro;
@@ -1235,7 +1235,7 @@ static int dw_mci_data_complete(struct d
 		 * After an error, there may be data lingering
 		 * in the FIFO
 		 */
-		dw_mci_fifo_reset(host);
+		dw_mci_reset(host);
 	} else {
 		data->bytes_xfered = data->blocks * data->blksz;
 		data->error = 0;
@@ -1352,7 +1352,7 @@ static void dw_mci_tasklet_func(unsigned
 
 			/* CMD error in data command */
 			if (mrq->cmd->error && mrq->data)
-				dw_mci_fifo_reset(host);
+				dw_mci_reset(host);
 
 			host->cmd = NULL;
 			host->data = NULL;
@@ -1963,14 +1963,8 @@ static void dw_mci_work_routine_card(str
 			}
 
 			/* Power down slot */
-			if (present == 0) {
-				/* Clear down the FIFO */
-				dw_mci_fifo_reset(host);
-#ifdef CONFIG_MMC_DW_IDMAC
-				dw_mci_idmac_reset(host);
-#endif
-
-			}
+			if (present == 0)
+				dw_mci_reset(host);
 
 			spin_unlock_bh(&host->lock);
 
@@ -2021,8 +2015,11 @@ static int dw_mci_of_get_slot_quirks(str
 
 	/* get quirks */
 	for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++)
-		if (of_get_property(np, of_slot_quirks[idx].quirk, NULL))
+		if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) {
+			dev_warn(dev, "Slot quirk %s is deprecated\n",
+					of_slot_quirks[idx].quirk);
 			quirks |= of_slot_quirks[idx].id;
+		}
 
 	return quirks;
 }
@@ -2208,8 +2205,11 @@ static bool dw_mci_ctrl_reset(struct dw_
 	return false;
 }
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host)
+static bool dw_mci_reset(struct dw_mci *host)
 {
+	u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
+	bool ret = false;
+
 	/*
 	 * Reseting generates a block interrupt, hence setting
 	 * the scatter-gather pointer to NULL.
@@ -2219,15 +2219,60 @@ static inline bool dw_mci_fifo_reset(str
 		host->sg = NULL;
 	}
 
-	return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
-}
+	if (host->use_dma)
+		flags |= SDMMC_CTRL_DMA_RESET;
 
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
-{
-	return dw_mci_ctrl_reset(host,
-				 SDMMC_CTRL_FIFO_RESET |
-				 SDMMC_CTRL_RESET |
-				 SDMMC_CTRL_DMA_RESET);
+	if (dw_mci_ctrl_reset(host, flags)) {
+		/*
+		 * In all cases we clear the RAWINTS register to clear any
+		 * interrupts.
+		 */
+		mci_writel(host, RINTSTS, 0xFFFFFFFF);
+
+		/* if using dma we wait for dma_req to clear */
+		if (host->use_dma) {
+			unsigned long timeout = jiffies + msecs_to_jiffies(500);
+			u32 status;
+			do {
+				status = mci_readl(host, STATUS);
+				if (!(status & SDMMC_STATUS_DMA_REQ))
+					break;
+				cpu_relax();
+			} while (time_before(jiffies, timeout));
+
+			if (status & SDMMC_STATUS_DMA_REQ) {
+				dev_err(host->dev,
+					"%s: Timeout waiting for dma_req to "
+					"clear during reset\n", __func__);
+				goto ciu_out;
+			}
+
+			/* when using DMA next we reset the fifo again */
+			if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
+				goto ciu_out;
+		}
+	} else {
+		/* if the controller reset bit did clear, then set clock regs */
+		if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) {
+			dev_err(host->dev, "%s: fifo/dma reset bits didn't "
+				"clear but ciu was reset, doing clock update\n",
+				__func__);
+			goto ciu_out;
+		}
+	}
+
+#if IS_ENABLED(CONFIG_MMC_DW_IDMAC)
+	/* It is also recommended that we reset and reprogram idmac */
+	dw_mci_idmac_reset(host);
+#endif
+
+	ret = true;
+
+ciu_out:
+	/* After a CTRL reset we need to have CIU set clock registers  */
+	mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
+
+	return ret;
 }
 
 #ifdef CONFIG_OF
@@ -2238,6 +2283,9 @@ static struct dw_mci_of_quirks {
 	{
 		.quirk	= "broken-cd",
 		.id	= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+	}, {
+		.quirk	= "disable-wp",
+		.id	= DW_MCI_QUIRK_NO_WRITE_PROTECT,
 	},
 };
 
@@ -2425,7 +2473,7 @@ int dw_mci_probe(struct dw_mci *host)
 	}
 
 	/* Reset all blocks */
-	if (!dw_mci_ctrl_all_reset(host))
+	if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
 		return -ENODEV;
 
 	host->dma_ops = host->pdata->dma_ops;
@@ -2612,7 +2660,7 @@ int dw_mci_resume(struct dw_mci *host)
 		}
 	}
 
-	if (!dw_mci_ctrl_all_reset(host)) {
+	if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
 		ret = -ENODEV;
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc.h linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc.h
--- linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -129,6 +129,7 @@
 #define SDMMC_CMD_INDX(n)		((n) & 0x1F)
 /* Status register defines */
 #define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FFF)
+#define SDMMC_STATUS_DMA_REQ		BIT(31)
 /* FIFOTH register defines */
 #define SDMMC_SET_FIFOTH(m, r, t)	(((m) & 0x7) << 28 | \
 					 ((r) & 0xFFF) << 16 | \
@@ -150,6 +151,10 @@
 /* Card read threshold */
 #define SDMMC_SET_RD_THLD(v, x)		(((v) & 0x1FFF) << 16 | (x))
 
+/* All ctrl reset bits */
+#define SDMMC_CTRL_ALL_RESET_FLAGS \
+	(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
+
 /* Register access macros */
 #define mci_readl(dev, reg)			\
 	__raw_readl((dev)->regs + SDMMC_##reg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc-pci.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc-pci.c
--- linux-libre-3.16-gnu/drivers/mmc/host/dw_mmc-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/dw_mmc-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,7 +102,7 @@ static int dw_mci_pci_resume(struct devi
 
 static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
 
-static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = {
+static const struct pci_device_id dw_mci_pci_id[] = {
 	{ PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
 	{}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/Kconfig linux-libre-3.17-rc7-gnu/drivers/mmc/host/Kconfig
--- linux-libre-3.16-gnu/drivers/mmc/host/Kconfig	2014-08-07 04:59:10.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/Kconfig	2014-09-28 21:41:47.000000000 -0400
@@ -290,6 +290,18 @@ config MMC_MOXART
 	  be found on some embedded hardware such as UC-7112-LX.
 	  If you have a controller with this interface, say Y here.
 
+config MMC_SDHCI_ST
+	tristate "SDHCI support on STMicroelectronics SoC"
+	depends on ARCH_STI
+	depends on MMC_SDHCI_PLTFM
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the Secure Digital Host Controller Interface in
+	  STMicroelectronics SoCs.
+
+	  If you have a controller with this interface, say Y or M here.
+	  If unsure, say N.
+
 config MMC_OMAP
 	tristate "TI OMAP Multimedia Card Interface support"
 	depends on ARCH_OMAP
@@ -303,6 +315,7 @@ config MMC_OMAP
 
 config MMC_OMAP_HS
 	tristate "TI OMAP High Speed Multimedia Card Interface support"
+	depends on HAS_DMA
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
 	help
 	  This selects the TI OMAP High Speed Multimedia card Interface.
@@ -343,7 +356,7 @@ config MMC_ATMELMCI
 
 config MMC_SDHCI_MSM
 	tristate "Qualcomm SDHCI Controller Support"
-	depends on ARCH_QCOM
+	depends on ARCH_QCOM || (ARM && COMPILE_TEST)
 	depends on MMC_SDHCI_PLTFM
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
@@ -440,6 +453,7 @@ config MMC_SPI
 config MMC_S3C
 	tristate "Samsung S3C SD/MMC Card Interface support"
 	depends on ARCH_S3C24XX
+	depends on S3C24XX_DMAC
 	help
 	  This selects a driver for the MCI interface found in
           Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@@ -477,15 +491,6 @@ config MMC_S3C_DMA
 	  working properly and needs to be debugged before this
 	  option is useful.
 
-config MMC_S3C_PIODMA
-	bool "Support for both PIO and DMA"
-	help
-	  Compile both the PIO and DMA transfer routines into the
-	  driver and let the platform select at run-time which one
-	  is best.
-
-	  See notes for the DMA option.
-
 endchoice
 
 config MMC_SDRICOH_CS
@@ -623,7 +628,7 @@ config MMC_DW_PCI
 
 config MMC_SH_MMCIF
 	tristate "SuperH Internal MMCIF support"
-	depends on MMC_BLOCK
+	depends on MMC_BLOCK && HAS_DMA
 	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
 	help
 	  This selects the MMC Host Interface controller (MMCIF).
@@ -691,6 +696,7 @@ config MMC_WMT
 
 config MMC_USDHI6ROL0
 	tristate "Renesas USDHI6ROL0 SD/SDIO Host Controller support"
+	depends on HAS_DMA
 	help
 	  This selects support for the Renesas USDHI6ROL0 SD/SDIO
 	  Host Controller
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/Makefile linux-libre-3.17-rc7-gnu/drivers/mmc/host/Makefile
--- linux-libre-3.16-gnu/drivers/mmc/host/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -68,6 +68,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhc
 obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= sdhci-msm.o
+obj-$(CONFIG_MMC_SDHCI_ST)		+= sdhci-st.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/mmci.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/mmci.c
--- linux-libre-3.16-gnu/drivers/mmc/host/mmci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/mmci.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,34 +52,53 @@ static unsigned int fmax = 515633;
  * struct variant_data - MMCI variant-specific quirks
  * @clkreg: default value for MCICLOCK register
  * @clkreg_enable: enable value for MMCICLOCK register
+ * @clkreg_8bit_bus_enable: enable value for 8 bit bus
+ * @clkreg_neg_edge_enable: enable value for inverted data/cmd output
  * @datalength_bits: number of bits in the MMCIDATALENGTH register
  * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
  *	      is asserted (likewise for RX)
  * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
  *		  is asserted (likewise for RX)
+ * @data_cmd_enable: enable value for data commands.
  * @sdio: variant supports SDIO
  * @st_clkdiv: true if using a ST-specific clock divider algorithm
+ * @datactrl_mask_ddrmode: ddr mode mask in datactrl register.
  * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
+ * @blksz_datactrl4: true if Block size is at b4..b16 position in datactrl
+ *		     register
  * @pwrreg_powerup: power up value for MMCIPOWER register
+ * @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
  * @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.
+ * @reversed_irq_handling: handle data irq before cmd irq.
  */
 struct variant_data {
 	unsigned int		clkreg;
 	unsigned int		clkreg_enable;
+	unsigned int		clkreg_8bit_bus_enable;
+	unsigned int		clkreg_neg_edge_enable;
 	unsigned int		datalength_bits;
 	unsigned int		fifosize;
 	unsigned int		fifohalfsize;
+	unsigned int		data_cmd_enable;
+	unsigned int		datactrl_mask_ddrmode;
 	bool			sdio;
 	bool			st_clkdiv;
 	bool			blksz_datactrl16;
+	bool			blksz_datactrl4;
 	u32			pwrreg_powerup;
+	u32			f_max;
 	bool			signal_direction;
 	bool			pwrreg_clkgate;
 	bool			busy_detect;
 	bool			pwrreg_nopower;
+	bool			explicit_mclk_control;
+	bool			qcom_fifo;
+	bool			reversed_irq_handling;
 };
 
 static struct variant_data variant_arm = {
@@ -87,6 +106,8 @@ static struct variant_data variant_arm =
 	.fifohalfsize		= 8 * 4,
 	.datalength_bits	= 16,
 	.pwrreg_powerup		= MCI_PWR_UP,
+	.f_max			= 100000000,
+	.reversed_irq_handling	= true,
 };
 
 static struct variant_data variant_arm_extended_fifo = {
@@ -94,6 +115,7 @@ static struct variant_data variant_arm_e
 	.fifohalfsize		= 64 * 4,
 	.datalength_bits	= 16,
 	.pwrreg_powerup		= MCI_PWR_UP,
+	.f_max			= 100000000,
 };
 
 static struct variant_data variant_arm_extended_fifo_hwfc = {
@@ -102,15 +124,18 @@ static struct variant_data variant_arm_e
 	.clkreg_enable		= MCI_ARM_HWFCEN,
 	.datalength_bits	= 16,
 	.pwrreg_powerup		= MCI_PWR_UP,
+	.f_max			= 100000000,
 };
 
 static struct variant_data variant_u300 = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg_enable		= MCI_ST_U300_HWFCEN,
+	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
 	.datalength_bits	= 16,
 	.sdio			= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.f_max			= 100000000,
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
@@ -124,6 +149,7 @@ static struct variant_data variant_nomad
 	.sdio			= true,
 	.st_clkdiv		= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.f_max			= 100000000,
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
@@ -134,10 +160,13 @@ static struct variant_data variant_ux500
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= MCI_ST_UX500_HWFCEN,
+	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
+	.clkreg_neg_edge_enable	= MCI_ST_UX500_NEG_EDGE,
 	.datalength_bits	= 24,
 	.sdio			= true,
 	.st_clkdiv		= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.f_max			= 100000000,
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
@@ -149,17 +178,38 @@ static struct variant_data variant_ux500
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
 	.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,
 	.datalength_bits	= 24,
 	.sdio			= true,
 	.st_clkdiv		= true,
 	.blksz_datactrl16	= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.f_max			= 100000000,
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
 	.pwrreg_nopower		= true,
 };
 
+static struct variant_data variant_qcom = {
+	.fifosize		= 16 * 4,
+	.fifohalfsize		= 8 * 4,
+	.clkreg			= MCI_CLK_ENABLE,
+	.clkreg_enable		= MCI_QCOM_CLK_FLOWENA |
+				  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,
+	.blksz_datactrl4	= true,
+	.datalength_bits	= 24,
+	.pwrreg_powerup		= MCI_PWR_UP,
+	.f_max			= 208000000,
+	.explicit_mclk_control	= true,
+	.qcom_fifo		= true,
+};
+
 static int mmci_card_busy(struct mmc_host *mmc)
 {
 	struct mmci_host *host = mmc_priv(mmc);
@@ -260,7 +310,9 @@ static void mmci_set_clkreg(struct mmci_
 	host->cclk = 0;
 
 	if (desired) {
-		if (desired >= host->mclk) {
+		if (variant->explicit_mclk_control) {
+			host->cclk = host->mclk;
+		} else if (desired >= host->mclk) {
 			clk = MCI_CLK_BYPASS;
 			if (variant->st_clkdiv)
 				clk |= MCI_ST_UX500_NEG_EDGE;
@@ -299,11 +351,11 @@ static void mmci_set_clkreg(struct mmci_
 	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4)
 		clk |= MCI_4BIT_BUS;
 	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8)
-		clk |= MCI_ST_8BIT_BUS;
+		clk |= variant->clkreg_8bit_bus_enable;
 
 	if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
 	    host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
-		clk |= MCI_ST_UX500_NEG_EDGE;
+		clk |= variant->clkreg_neg_edge_enable;
 
 	mmci_write_clkreg(host, clk);
 }
@@ -719,7 +771,7 @@ static void mmci_start_data(struct mmci_
 	data->bytes_xfered = 0;
 
 	clks = (unsigned long long)data->timeout_ns * host->cclk;
-	do_div(clks, 1000000000UL);
+	do_div(clks, NSEC_PER_SEC);
 
 	timeout = data->timeout_clks + (unsigned int)clks;
 
@@ -732,6 +784,8 @@ static void mmci_start_data(struct mmci_
 
 	if (variant->blksz_datactrl16)
 		datactrl = MCI_DPSM_ENABLE | (data->blksz << 16);
+	else if (variant->blksz_datactrl4)
+		datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
 	else
 		datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
 
@@ -767,7 +821,7 @@ static void mmci_start_data(struct mmci_
 
 	if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
 	    host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
-		datactrl |= MCI_ST_DPSM_DDRMODE;
+		datactrl |= variant->datactrl_mask_ddrmode;
 
 	/*
 	 * Attempt to use DMA operation mode, if this
@@ -812,7 +866,7 @@ mmci_start_command(struct mmci_host *hos
 
 	if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
 		writel(0, base + MMCICOMMAND);
-		udelay(1);
+		mmci_reg_delay(host);
 	}
 
 	c |= cmd->opcode | MCI_CPSM_ENABLE;
@@ -824,6 +878,9 @@ mmci_start_command(struct mmci_host *hos
 	if (/*interrupt*/0)
 		c |= MCI_CPSM_INTERRUPT;
 
+	if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
+		c |= host->variant->data_cmd_enable;
+
 	host->cmd = cmd;
 
 	writel(cmd->arg, base + MMCIARGUMENT);
@@ -834,6 +891,10 @@ static void
 mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 	      unsigned int status)
 {
+	/* Make sure we have data to handle */
+	if (!data)
+		return;
+
 	/* First check for errors */
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
 		      MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
@@ -902,9 +963,17 @@ mmci_cmd_irq(struct mmci_host *host, str
 	     unsigned int status)
 {
 	void __iomem *base = host->base;
-	bool sbc = (cmd == host->mrq->sbc);
-	bool busy_resp = host->variant->busy_detect &&
-			(cmd->flags & MMC_RSP_BUSY);
+	bool sbc, busy_resp;
+
+	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)))
+		return;
 
 	/* Check if we need to wait for busy completion. */
 	if (host->busy_status && (status & MCI_ST_CARDBUSY))
@@ -957,15 +1026,34 @@ mmci_cmd_irq(struct mmci_host *host, str
 	}
 }
 
+static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain)
+{
+	return remain - (readl(host->base + MMCIFIFOCNT) << 2);
+}
+
+static int mmci_qcom_get_rx_fifocnt(struct mmci_host *host, u32 status, int r)
+{
+	/*
+	 * on qcom SDCC4 only 8 words are used in each burst so only 8 addresses
+	 * from the fifo range should be used
+	 */
+	if (status & MCI_RXFIFOHALFFULL)
+		return host->variant->fifohalfsize;
+	else if (status & MCI_RXDATAAVLBL)
+		return 4;
+
+	return 0;
+}
+
 static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
 {
 	void __iomem *base = host->base;
 	char *ptr = buffer;
-	u32 status;
+	u32 status = readl(host->base + MMCISTATUS);
 	int host_remain = host->size;
 
 	do {
-		int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
+		int count = host->get_rx_fifocnt(host, status, host_remain);
 
 		if (count > remain)
 			count = remain;
@@ -1132,9 +1220,6 @@ static irqreturn_t mmci_irq(int irq, voi
 	spin_lock(&host->lock);
 
 	do {
-		struct mmc_command *cmd;
-		struct mmc_data *data;
-
 		status = readl(host->base + MMCISTATUS);
 
 		if (host->singleirq) {
@@ -1154,16 +1239,13 @@ static irqreturn_t mmci_irq(int irq, voi
 
 		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
 
-		cmd = host->cmd;
-		if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
-			MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
-			mmci_cmd_irq(host, cmd, status);
-
-		data = host->data;
-		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
-			      MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
-			      MCI_DATABLOCKEND) && data)
-			mmci_data_irq(host, data, status);
+		if (host->variant->reversed_irq_handling) {
+			mmci_data_irq(host, host->data, status);
+			mmci_cmd_irq(host, host->cmd, status);
+		} else {
+			mmci_cmd_irq(host, host->cmd, status);
+			mmci_data_irq(host, host->data, status);
+		}
 
 		/* Don't poll for busy completion in irq context. */
 		if (host->busy_status)
@@ -1296,6 +1378,17 @@ static void mmci_set_ios(struct mmc_host
 	if (!ios->clock && variant->pwrreg_clkgate)
 		pwr &= ~MCI_PWR_ON;
 
+	if (host->variant->explicit_mclk_control &&
+	    ios->clock != host->clock_cache) {
+		ret = clk_set_rate(host->clk, ios->clock);
+		if (ret < 0)
+			dev_err(mmc_dev(host->mmc),
+				"Error setting clock rate (%d)\n", ret);
+		else
+			host->mclk = clk_get_rate(host->clk);
+	}
+	host->clock_cache = ios->clock;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	mmci_set_clkreg(host, ios->clock);
@@ -1443,6 +1536,11 @@ static int mmci_probe(struct amba_device
 	if (ret)
 		goto host_free;
 
+	if (variant->qcom_fifo)
+		host->get_rx_fifocnt = mmci_qcom_get_rx_fifocnt;
+	else
+		host->get_rx_fifocnt = mmci_get_rx_fifocnt;
+
 	host->plat = plat;
 	host->variant = variant;
 	host->mclk = clk_get_rate(host->clk);
@@ -1451,8 +1549,8 @@ static int mmci_probe(struct amba_device
 	 * so we try to adjust the clock down to this,
 	 * (if possible).
 	 */
-	if (host->mclk > 100000000) {
-		ret = clk_set_rate(host->clk, 100000000);
+	if (host->mclk > variant->f_max) {
+		ret = clk_set_rate(host->clk, variant->f_max);
 		if (ret < 0)
 			goto clk_disable;
 		host->mclk = clk_get_rate(host->clk);
@@ -1471,9 +1569,12 @@ static int mmci_probe(struct amba_device
 	 * The ARM and ST versions of the block have slightly different
 	 * clock divider equations which means that the minimum divider
 	 * differs too.
+	 * on Qualcomm like controllers get the nearest minimum clock to 100Khz
 	 */
 	if (variant->st_clkdiv)
 		mmc->f_min = DIV_ROUND_UP(host->mclk, 257);
+	else if (variant->explicit_mclk_control)
+		mmc->f_min = clk_round_rate(host->clk, 100000);
 	else
 		mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
 	/*
@@ -1483,9 +1584,14 @@ static int mmci_probe(struct amba_device
 	 * the block, of course.
 	 */
 	if (mmc->f_max)
-		mmc->f_max = min(host->mclk, mmc->f_max);
+		mmc->f_max = variant->explicit_mclk_control ?
+				min(variant->f_max, mmc->f_max) :
+				min(host->mclk, mmc->f_max);
 	else
-		mmc->f_max = min(host->mclk, fmax);
+		mmc->f_max = variant->explicit_mclk_control ?
+				fmax : min(host->mclk, fmax);
+
+
 	dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
 
 	/* Get regulators and the supported OCR mask */
@@ -1752,6 +1858,12 @@ static struct amba_id mmci_ids[] = {
 		.mask   = 0xf0ffffff,
 		.data	= &variant_ux500v2,
 	},
+	/* Qualcomm variants */
+	{
+		.id     = 0x00051180,
+		.mask	= 0x000fffff,
+		.data	= &variant_qcom,
+	},
 	{ 0, 0 },
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/mmci.h linux-libre-3.17-rc7-gnu/drivers/mmc/host/mmci.h
--- linux-libre-3.16-gnu/drivers/mmc/host/mmci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/mmci.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,6 +41,15 @@
 /* Modified PL180 on Versatile Express platform */
 #define MCI_ARM_HWFCEN		(1 << 12)
 
+/* Modified on Qualcomm Integrations */
+#define MCI_QCOM_CLK_WIDEBUS_8	(BIT(10) | BIT(11))
+#define MCI_QCOM_CLK_FLOWENA	BIT(12)
+#define MCI_QCOM_CLK_INVERTOUT	BIT(13)
+
+/* select in latch data and command in */
+#define MCI_QCOM_CLK_SELECT_IN_FBCLK	BIT(15)
+#define MCI_QCOM_CLK_SELECT_IN_DDR_MODE	(BIT(14) | BIT(15))
+
 #define MMCIARGUMENT		0x008
 #define MMCICOMMAND		0x00c
 #define MCI_CPSM_RESPONSE	(1 << 6)
@@ -54,6 +63,14 @@
 #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)
+
 #define MMCIRESPCMD		0x010
 #define MMCIRESPONSE0		0x014
 #define MMCIRESPONSE1		0x018
@@ -191,6 +208,8 @@ struct mmci_host {
 	spinlock_t		lock;
 
 	unsigned int		mclk;
+	/* cached value of requested clk in set_ios */
+	unsigned int		clock_cache;
 	unsigned int		cclk;
 	u32			pwr_reg;
 	u32			pwr_reg_add;
@@ -210,6 +229,7 @@ struct mmci_host {
 	/* pio stuff */
 	struct sg_mapping_iter	sg_miter;
 	unsigned int		size;
+	int (*get_rx_fifocnt)(struct mmci_host *h, u32 status, int remain);
 
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/moxart-mmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/moxart-mmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/moxart-mmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/moxart-mmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -13,7 +13,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/mxs-mmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/mxs-mmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/mxs-mmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/mxs-mmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,8 @@ static int mxs_mmc_get_cd(struct mmc_hos
 	if (ret >= 0)
 		return ret;
 
-	present = !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
+	present = mmc->caps & MMC_CAP_NEEDS_POLL ||
+		!(readl(ssp->base + HW_SSP_STATUS(ssp)) &
 			BM_SSP_STATUS_CARD_DETECT);
 
 	if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/omap_hsmmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/omap_hsmmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 #include <linux/clk.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/omap-dmaengine.h>
@@ -36,6 +37,7 @@
 #include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pinctrl/consumer.h>
@@ -54,6 +56,7 @@
 #define OMAP_HSMMC_RSP54	0x0118
 #define OMAP_HSMMC_RSP76	0x011C
 #define OMAP_HSMMC_DATA		0x0120
+#define OMAP_HSMMC_PSTATE	0x0124
 #define OMAP_HSMMC_HCTL		0x0128
 #define OMAP_HSMMC_SYSCTL	0x012C
 #define OMAP_HSMMC_STAT		0x0130
@@ -91,7 +94,10 @@
 #define BCE			(1 << 1)
 #define FOUR_BIT		(1 << 1)
 #define HSPE			(1 << 2)
+#define IWE			(1 << 24)
 #define DDR			(1 << 19)
+#define CLKEXTFREE		(1 << 16)
+#define CTPL			(1 << 11)
 #define DW8			(1 << 5)
 #define OD			0x1
 #define STAT_CLEAR		0xFFFFFFFF
@@ -101,11 +107,15 @@
 #define SRD			(1 << 26)
 #define SOFTRESET		(1 << 1)
 
+/* PSTATE */
+#define DLEV_DAT(x)		(1 << (20 + (x)))
+
 /* Interrupt masks for IE and ISE register */
 #define CC_EN			(1 << 0)
 #define TC_EN			(1 << 1)
 #define BWR_EN			(1 << 4)
 #define BRR_EN			(1 << 5)
+#define CIRQ_EN			(1 << 8)
 #define ERR_EN			(1 << 15)
 #define CTO_EN			(1 << 16)
 #define CCRC_EN			(1 << 17)
@@ -140,7 +150,6 @@
 #define VDD_3V0			3000000		/* 300000 uV */
 #define VDD_165_195		(ffs(MMC_VDD_165_195) - 1)
 
-#define AUTO_CMD23		(1 << 1)	/* Auto CMD23 support */
 /*
  * One controller can have multiple slots, like on some omap boards using
  * omap.c controller driver. Luckily this is not currently done on any known
@@ -194,6 +203,7 @@ struct omap_hsmmc_host {
 	u32			sysctl;
 	u32			capa;
 	int			irq;
+	int			wake_irq;
 	int			use_dma, dma_ch;
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
@@ -206,6 +216,9 @@ struct omap_hsmmc_host {
 	int			req_in_progress;
 	unsigned long		clk_rate;
 	unsigned int		flags;
+#define AUTO_CMD23		(1 << 0)        /* Auto CMD23 support */
+#define HSMMC_SDIO_IRQ_ENABLED	(1 << 1)        /* SDIO irq enabled */
+#define HSMMC_WAKE_IRQ_ENABLED	(1 << 2)
 	struct omap_hsmmc_next	next_data;
 	struct	omap_mmc_platform_data	*pdata;
 };
@@ -510,27 +523,40 @@ static void omap_hsmmc_stop_clock(struct
 static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 				  struct mmc_command *cmd)
 {
-	unsigned int irq_mask;
+	u32 irq_mask = INT_EN_MASK;
+	unsigned long flags;
 
 	if (host->use_dma)
-		irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
-	else
-		irq_mask = INT_EN_MASK;
+		irq_mask &= ~(BRR_EN | BWR_EN);
 
 	/* Disable timeout for erases */
 	if (cmd->opcode == MMC_ERASE)
 		irq_mask &= ~DTO_EN;
 
+	spin_lock_irqsave(&host->irq_lock, flags);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* latch pending CIRQ, but don't signal MMC core */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
 	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 {
-	OMAP_HSMMC_WRITE(host->base, ISE, 0);
-	OMAP_HSMMC_WRITE(host->base, IE, 0);
+	u32 irq_mask = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+	/* no transfer running but need to keep cirq if enabled */
+	if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+		irq_mask |= CIRQ_EN;
+	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 }
 
 /* Calculate divisor for the given clock frequency */
@@ -667,6 +693,9 @@ static int omap_hsmmc_context_restore(st
 		capa = VS18;
 	}
 
+	if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
+		hctl |= IWE;
+
 	OMAP_HSMMC_WRITE(host->base, HCTL,
 			OMAP_HSMMC_READ(host->base, HCTL) | hctl);
 
@@ -681,7 +710,9 @@ static int omap_hsmmc_context_restore(st
 		&& time_before(jiffies, timeout))
 		;
 
-	omap_hsmmc_disable_irq(host);
+	OMAP_HSMMC_WRITE(host->base, ISE, 0);
+	OMAP_HSMMC_WRITE(host->base, IE, 0);
+	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 
 	/* Do not initialize card-specific things if the power is off */
 	if (host->power_mode == MMC_POWER_OFF)
@@ -1118,8 +1149,12 @@ static irqreturn_t omap_hsmmc_irq(int ir
 	int status;
 
 	status = OMAP_HSMMC_READ(host->base, STAT);
-	while (status & INT_EN_MASK && host->req_in_progress) {
-		omap_hsmmc_do_irq(host, status);
+	while (status & (INT_EN_MASK | CIRQ_EN)) {
+		if (host->req_in_progress)
+			omap_hsmmc_do_irq(host, status);
+
+		if (status & CIRQ_EN)
+			mmc_signal_sdio_irq(host->mmc);
 
 		/* Flush posted write */
 		status = OMAP_HSMMC_READ(host->base, STAT);
@@ -1128,6 +1163,22 @@ static irqreturn_t omap_hsmmc_irq(int ir
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t omap_hsmmc_wake_irq(int irq, void *dev_id)
+{
+	struct omap_hsmmc_host *host = dev_id;
+
+	/* cirq is level triggered, disable to avoid infinite loop */
+	spin_lock(&host->irq_lock);
+	if (host->flags & HSMMC_WAKE_IRQ_ENABLED) {
+		disable_irq_nosync(host->wake_irq);
+		host->flags &= ~HSMMC_WAKE_IRQ_ENABLED;
+	}
+	spin_unlock(&host->irq_lock);
+	pm_request_resume(host->dev); /* no use counter */
+
+	return IRQ_HANDLED;
+}
+
 static void set_sd_bus_power(struct omap_hsmmc_host *host)
 {
 	unsigned long i;
@@ -1639,6 +1690,103 @@ static void omap_hsmmc_init_card(struct
 		mmc_slot(host).init_card(card);
 }
 
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	u32 irq_mask, con;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->irq_lock, flags);
+
+	con = OMAP_HSMMC_READ(host->base, CON);
+	irq_mask = OMAP_HSMMC_READ(host->base, ISE);
+	if (enable) {
+		host->flags |= HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask |= CIRQ_EN;
+		con |= CTPL | CLKEXTFREE;
+	} else {
+		host->flags &= ~HSMMC_SDIO_IRQ_ENABLED;
+		irq_mask &= ~CIRQ_EN;
+		con &= ~(CTPL | CLKEXTFREE);
+	}
+	OMAP_HSMMC_WRITE(host->base, CON, con);
+	OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+
+	/*
+	 * if enable, piggy back detection on current request
+	 * but always disable immediately
+	 */
+	if (!host->req_in_progress || !enable)
+		OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+	/* flush posted write */
+	OMAP_HSMMC_READ(host->base, IE);
+
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
+static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	int ret;
+
+	/*
+	 * For omaps with wake-up path, wakeirq will be irq from pinctrl and
+	 * for other omaps, wakeirq will be from GPIO (dat line remuxed to
+	 * gpio). wakeirq is needed to detect sdio irq in runtime suspend state
+	 * with functional clock disabled.
+	 */
+	if (!host->dev->of_node || !host->wake_irq)
+		return -ENODEV;
+
+	/* Prevent auto-enabling of IRQ */
+	irq_set_status_flags(host->wake_irq, IRQ_NOAUTOEN);
+	ret = devm_request_irq(host->dev, host->wake_irq, omap_hsmmc_wake_irq,
+			       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+			       mmc_hostname(mmc), host);
+	if (ret) {
+		dev_err(mmc_dev(host->mmc), "Unable to request wake IRQ\n");
+		goto err;
+	}
+
+	/*
+	 * Some omaps don't have wake-up path from deeper idle states
+	 * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
+	 */
+	if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
+		struct pinctrl *p = devm_pinctrl_get(host->dev);
+		if (!p) {
+			ret = -ENODEV;
+			goto err_free_irq;
+		}
+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
+			dev_info(host->dev, "missing default pinctrl state\n");
+			devm_pinctrl_put(p);
+			ret = -EINVAL;
+			goto err_free_irq;
+		}
+
+		if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
+			dev_info(host->dev, "missing idle pinctrl state\n");
+			devm_pinctrl_put(p);
+			ret = -EINVAL;
+			goto err_free_irq;
+		}
+		devm_pinctrl_put(p);
+	}
+
+	OMAP_HSMMC_WRITE(host->base, HCTL,
+			 OMAP_HSMMC_READ(host->base, HCTL) | IWE);
+	return 0;
+
+err_free_irq:
+	devm_free_irq(host->dev, host->wake_irq, host);
+err:
+	dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
+	host->wake_irq = 0;
+	return ret;
+}
+
 static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 {
 	u32 hctl, capa, value;
@@ -1691,7 +1839,7 @@ static const struct mmc_host_ops omap_hs
 	.get_cd = omap_hsmmc_get_cd,
 	.get_ro = omap_hsmmc_get_ro,
 	.init_card = omap_hsmmc_init_card,
-	/* NYET -- enable_sdio_irq */
+	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1701,13 +1849,23 @@ static int omap_hsmmc_regs_show(struct s
 	struct mmc_host *mmc = s->private;
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-	seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n",
-			mmc->index, host->context_loss);
+	seq_printf(s, "mmc%d:\n", mmc->index);
+	seq_printf(s, "sdio irq mode\t%s\n",
+		   (mmc->caps & MMC_CAP_SDIO_IRQ) ? "interrupt" : "polling");
 
-	pm_runtime_get_sync(host->dev);
+	if (mmc->caps & MMC_CAP_SDIO_IRQ) {
+		seq_printf(s, "sdio irq \t%s\n",
+			   (host->flags & HSMMC_SDIO_IRQ_ENABLED) ?  "enabled"
+			   : "disabled");
+	}
+	seq_printf(s, "ctx_loss:\t%d\n", host->context_loss);
 
+	pm_runtime_get_sync(host->dev);
+	seq_puts(s, "\nregs:\n");
 	seq_printf(s, "CON:\t\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, CON));
+	seq_printf(s, "PSTATE:\t\t0x%08x\n",
+		   OMAP_HSMMC_READ(host->base, PSTATE));
 	seq_printf(s, "HCTL:\t\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, HCTL));
 	seq_printf(s, "SYSCTL:\t\t0x%08x\n",
@@ -1761,6 +1919,10 @@ static const struct omap_mmc_of_data oma
 static const struct omap_mmc_of_data omap4_mmc_of_data = {
 	.reg_offset = 0x100,
 };
+static const struct omap_mmc_of_data am33xx_mmc_of_data = {
+	.reg_offset = 0x100,
+	.controller_flags = OMAP_HSMMC_SWAKEUP_MISSING,
+};
 
 static const struct of_device_id omap_mmc_of_match[] = {
 	{
@@ -1777,6 +1939,10 @@ static const struct of_device_id omap_mm
 		.compatible = "ti,omap4-hsmmc",
 		.data = &omap4_mmc_of_data,
 	},
+	{
+		.compatible = "ti,am33xx-hsmmc",
+		.data = &am33xx_mmc_of_data,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
@@ -1850,7 +2016,6 @@ static int omap_hsmmc_probe(struct platf
 	const struct of_device_id *match;
 	dma_cap_mask_t mask;
 	unsigned tx_req, rx_req;
-	struct pinctrl *pinctrl;
 	const struct omap_mmc_of_data *data;
 	void __iomem *base;
 
@@ -1913,6 +2078,9 @@ static int omap_hsmmc_probe(struct platf
 
 	platform_set_drvdata(pdev, host);
 
+	if (pdev->dev.of_node)
+		host->wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
 	mmc->ops	= &omap_hsmmc_ops;
 
 	mmc->f_min = OMAP_MMC_MIN_CLOCK;
@@ -2061,10 +2229,17 @@ static int omap_hsmmc_probe(struct platf
 
 	omap_hsmmc_disable_irq(host);
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl))
-		dev_warn(&pdev->dev,
-			"pins are not configured from the driver\n");
+	/*
+	 * For now, only support SDIO interrupt if we have a separate
+	 * wake-up interrupt configured from device tree. This is because
+	 * the wake-up interrupt is needed for idle state and some
+	 * platforms need special quirks. And we don't want to add new
+	 * legacy mux platform init code callbacks any longer as we
+	 * are moving to DT based booting anyways.
+	 */
+	ret = omap_hsmmc_configure_wake_irq(host);
+	if (!ret)
+		mmc->caps |= MMC_CAP_SDIO_IRQ;
 
 	omap_hsmmc_protect_card(host);
 
@@ -2170,11 +2345,18 @@ static int omap_hsmmc_suspend(struct dev
 	pm_runtime_get_sync(host->dev);
 
 	if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
-		omap_hsmmc_disable_irq(host);
+		OMAP_HSMMC_WRITE(host->base, ISE, 0);
+		OMAP_HSMMC_WRITE(host->base, IE, 0);
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 		OMAP_HSMMC_WRITE(host->base, HCTL,
 				OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 	}
 
+	/* do not wake up due to sdio irq */
+	if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+	    !(host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
+		disable_irq(host->wake_irq);
+
 	if (host->dbclk)
 		clk_disable_unprepare(host->dbclk);
 
@@ -2200,6 +2382,10 @@ static int omap_hsmmc_resume(struct devi
 
 	omap_hsmmc_protect_card(host);
 
+	if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+	    !(host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
+		enable_irq(host->wake_irq);
+
 	pm_runtime_mark_last_busy(host->dev);
 	pm_runtime_put_autosuspend(host->dev);
 	return 0;
@@ -2215,22 +2401,77 @@ static int omap_hsmmc_resume(struct devi
 static int omap_hsmmc_runtime_suspend(struct device *dev)
 {
 	struct omap_hsmmc_host *host;
+	unsigned long flags;
+	int ret = 0;
 
 	host = platform_get_drvdata(to_platform_device(dev));
 	omap_hsmmc_context_save(host);
 	dev_dbg(dev, "disabled\n");
 
-	return 0;
+	spin_lock_irqsave(&host->irq_lock, flags);
+	if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+	    (host->flags & HSMMC_SDIO_IRQ_ENABLED)) {
+		/* disable sdio irq handling to prevent race */
+		OMAP_HSMMC_WRITE(host->base, ISE, 0);
+		OMAP_HSMMC_WRITE(host->base, IE, 0);
+
+		if (!(OMAP_HSMMC_READ(host->base, PSTATE) & DLEV_DAT(1))) {
+			/*
+			 * dat1 line low, pending sdio irq
+			 * race condition: possible irq handler running on
+			 * multi-core, abort
+			 */
+			dev_dbg(dev, "pending sdio irq, abort suspend\n");
+			OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+			OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+			OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+			pm_runtime_mark_last_busy(dev);
+			ret = -EBUSY;
+			goto abort;
+		}
+
+		pinctrl_pm_select_idle_state(dev);
+
+		WARN_ON(host->flags & HSMMC_WAKE_IRQ_ENABLED);
+		enable_irq(host->wake_irq);
+		host->flags |= HSMMC_WAKE_IRQ_ENABLED;
+	} else {
+		pinctrl_pm_select_idle_state(dev);
+	}
+
+abort:
+	spin_unlock_irqrestore(&host->irq_lock, flags);
+	return ret;
 }
 
 static int omap_hsmmc_runtime_resume(struct device *dev)
 {
 	struct omap_hsmmc_host *host;
+	unsigned long flags;
 
 	host = platform_get_drvdata(to_platform_device(dev));
 	omap_hsmmc_context_restore(host);
 	dev_dbg(dev, "enabled\n");
 
+	spin_lock_irqsave(&host->irq_lock, flags);
+	if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+	    (host->flags & HSMMC_SDIO_IRQ_ENABLED)) {
+		/* sdio irq flag can't change while in runtime suspend */
+		if (host->flags & HSMMC_WAKE_IRQ_ENABLED) {
+			disable_irq_nosync(host->wake_irq);
+			host->flags &= ~HSMMC_WAKE_IRQ_ENABLED;
+		}
+
+		pinctrl_pm_select_default_state(host->dev);
+
+		/* irq lost, if pinmux incorrect */
+		OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+		OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+		OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+	} else {
+		pinctrl_pm_select_default_state(host->dev);
+	}
+	spin_unlock_irqrestore(&host->irq_lock, flags);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/highmem.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/workqueue.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
@@ -36,7 +37,10 @@ struct realtek_pci_sdmmc {
 	struct rtsx_pcr		*pcr;
 	struct mmc_host		*mmc;
 	struct mmc_request	*mrq;
+	struct workqueue_struct *workq;
+#define SDMMC_WORKQ_NAME	"rtsx_pci_sdmmc_workq"
 
+	struct work_struct	work;
 	struct mutex		host_mutex;
 
 	u8			ssc_depth;
@@ -48,6 +52,11 @@ struct realtek_pci_sdmmc {
 	int			power_state;
 #define SDMMC_POWER_ON		1
 #define SDMMC_POWER_OFF		0
+
+	unsigned int		sg_count;
+	s32			cookie;
+	unsigned int		cookie_sg_count;
+	bool			using_cookie;
 };
 
 static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
@@ -86,6 +95,77 @@ static void sd_print_debug_regs(struct r
 #define sd_print_debug_regs(host)
 #endif /* DEBUG */
 
+/*
+ * sd_pre_dma_transfer - do dma_map_sg() or using cookie
+ *
+ * @pre: if called in pre_req()
+ * return:
+ *	0 - do dma_map_sg()
+ *	1 - using cookie
+ */
+static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
+		struct mmc_data *data, bool pre)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int read = data->flags & MMC_DATA_READ;
+	int count = 0;
+	int using_cookie = 0;
+
+	if (!pre && data->host_cookie && data->host_cookie != host->cookie) {
+		dev_err(sdmmc_dev(host),
+			"error: data->host_cookie = %d, host->cookie = %d\n",
+			data->host_cookie, host->cookie);
+		data->host_cookie = 0;
+	}
+
+	if (pre || data->host_cookie != host->cookie) {
+		count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read);
+	} else {
+		count = host->cookie_sg_count;
+		using_cookie = 1;
+	}
+
+	if (pre) {
+		host->cookie_sg_count = count;
+		if (++host->cookie < 0)
+			host->cookie = 1;
+		data->host_cookie = host->cookie;
+	} else {
+		host->sg_count = count;
+	}
+
+	return using_cookie;
+}
+
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		bool is_first_req)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (data->host_cookie) {
+		dev_err(sdmmc_dev(host),
+			"error: reset data->host_cookie = %d\n",
+			data->host_cookie);
+		data->host_cookie = 0;
+	}
+
+	sd_pre_dma_transfer(host, data, true);
+	dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count);
+}
+
+static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		int err)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_data *data = mrq->data;
+	int read = data->flags & MMC_DATA_READ;
+
+	rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
+	data->host_cookie = 0;
+}
+
 static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
 		u8 *buf, int buf_len, int timeout)
 {
@@ -415,7 +495,7 @@ static int sd_rw_multi(struct realtek_pc
 
 	rtsx_pci_send_cmd_no_wait(pcr);
 
-	err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+	err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000);
 	if (err < 0) {
 		sd_clear_error(host);
 		return err;
@@ -640,12 +720,24 @@ static int sd_tuning_rx(struct realtek_p
 	return 0;
 }
 
-static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+static inline int sd_rw_cmd(struct mmc_command *cmd)
 {
-	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	return mmc_op_multi(cmd->opcode) ||
+		(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+		(cmd->opcode == MMC_WRITE_BLOCK);
+}
+
+static void sd_request(struct work_struct *work)
+{
+	struct realtek_pci_sdmmc *host = container_of(work,
+			struct realtek_pci_sdmmc, work);
 	struct rtsx_pcr *pcr = host->pcr;
+
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_request *mrq = host->mrq;
 	struct mmc_command *cmd = mrq->cmd;
 	struct mmc_data *data = mrq->data;
+
 	unsigned int data_size = 0;
 	int err;
 
@@ -677,13 +769,13 @@ static void sdmmc_request(struct mmc_hos
 	if (mrq->data)
 		data_size = data->blocks * data->blksz;
 
-	if (!data_size || mmc_op_multi(cmd->opcode) ||
-			(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
-			(cmd->opcode == MMC_WRITE_BLOCK)) {
+	if (!data_size || sd_rw_cmd(cmd)) {
 		sd_send_cmd_get_rsp(host, cmd);
 
 		if (!cmd->error && data_size) {
 			sd_rw_multi(host, mrq);
+			if (!host->using_cookie)
+				sdmmc_post_req(host->mmc, host->mrq, 0);
 
 			if (mmc_op_multi(cmd->opcode) && mrq->stop)
 				sd_send_cmd_get_rsp(host, mrq->stop);
@@ -712,6 +804,21 @@ finish:
 	mmc_request_done(mmc, mrq);
 }
 
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	mutex_lock(&host->host_mutex);
+	host->mrq = mrq;
+	mutex_unlock(&host->host_mutex);
+
+	if (sd_rw_cmd(mrq->cmd))
+		host->using_cookie = sd_pre_dma_transfer(host, data, false);
+
+	queue_work(host->workq, &host->work);
+}
+
 static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
 		unsigned char bus_width)
 {
@@ -1146,6 +1253,8 @@ out:
 }
 
 static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+	.pre_req = sdmmc_pre_req,
+	.post_req = sdmmc_post_req,
 	.request = sdmmc_request,
 	.set_ios = sdmmc_set_ios,
 	.get_ro = sdmmc_get_ro,
@@ -1224,10 +1333,16 @@ static int rtsx_pci_sdmmc_drv_probe(stru
 		return -ENOMEM;
 
 	host = mmc_priv(mmc);
+	host->workq = create_singlethread_workqueue(SDMMC_WORKQ_NAME);
+	if (!host->workq) {
+		mmc_free_host(mmc);
+		return -ENOMEM;
+	}
 	host->pcr = pcr;
 	host->mmc = mmc;
 	host->pdev = pdev;
 	host->power_state = SDMMC_POWER_OFF;
+	INIT_WORK(&host->work, sd_request);
 	platform_set_drvdata(pdev, host);
 	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
 	pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
@@ -1255,6 +1370,8 @@ static int rtsx_pci_sdmmc_drv_remove(str
 	pcr->slots[RTSX_SD_CARD].card_event = NULL;
 	mmc = host->mmc;
 
+	cancel_work_sync(&host->work);
+
 	mutex_lock(&host->host_mutex);
 	if (host->mrq) {
 		dev_dbg(&(pdev->dev),
@@ -1273,6 +1390,10 @@ static int rtsx_pci_sdmmc_drv_remove(str
 	mmc_remove_host(mmc);
 	host->eject = true;
 
+	flush_workqueue(host->workq);
+	destroy_workqueue(host->workq);
+	host->workq = NULL;
+
 	mmc_free_host(mmc);
 
 	dev_dbg(&(pdev->dev),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/s3cmci.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/s3cmci.c
--- linux-libre-3.16-gnu/drivers/mmc/host/s3cmci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/s3cmci.c	2014-09-28 17:29:07.000000000 -0400
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/mmc/host.h>
@@ -27,6 +28,7 @@
 #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"
@@ -140,10 +142,6 @@ static const int dbgmap_debug = dbg_err
 		dev_dbg(&host->pdev->dev, args);  \
 	} while (0)
 
-static struct s3c2410_dma_client s3cmci_dma_client = {
-	.name		= "s3c-mci",
-};
-
 static void finalize_request(struct s3cmci_host *host);
 static void s3cmci_send_request(struct mmc_host *mmc);
 static void s3cmci_reset(struct s3cmci_host *host);
@@ -256,25 +254,8 @@ static inline bool s3cmci_host_usedma(st
 {
 #ifdef CONFIG_MMC_S3C_PIO
 	return false;
-#elif defined(CONFIG_MMC_S3C_DMA)
+#else /* CONFIG_MMC_S3C_DMA */
 	return true;
-#else
-	return host->dodma;
-#endif
-}
-
-/**
- * s3cmci_host_canpio - return true if host has pio code available
- *
- * Return true if the driver has been compiled with the PIO support code
- * available.
- */
-static inline bool s3cmci_host_canpio(void)
-{
-#ifdef CONFIG_MMC_S3C_PIO
-	return true;
-#else
-	return false;
 #endif
 }
 
@@ -841,60 +822,24 @@ static irqreturn_t s3cmci_irq_cd(int irq
 	return IRQ_HANDLED;
 }
 
-static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
-				     void *buf_id, int size,
-				     enum s3c2410_dma_buffresult result)
+static void s3cmci_dma_done_callback(void *arg)
 {
-	struct s3cmci_host *host = buf_id;
+	struct s3cmci_host *host = arg;
 	unsigned long iflags;
-	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
-
-	mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
-	mci_dsta = readl(host->base + S3C2410_SDIDSTA);
-	mci_fsta = readl(host->base + S3C2410_SDIFSTA);
-	mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
 
 	BUG_ON(!host->mrq);
 	BUG_ON(!host->mrq->data);
-	BUG_ON(!host->dmatogo);
 
 	spin_lock_irqsave(&host->complete_lock, iflags);
 
-	if (result != S3C2410_RES_OK) {
-		dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
-			"fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
-			mci_csta, mci_dsta, mci_fsta,
-			mci_dcnt, result, host->dmatogo);
-
-		goto fail_request;
-	}
-
-	host->dmatogo--;
-	if (host->dmatogo) {
-		dbg(host, dbg_dma, "DMA DONE  Size:%i DSTA:[%08x] "
-			"DCNT:[%08x] toGo:%u\n",
-			size, mci_dsta, mci_dcnt, host->dmatogo);
-
-		goto out;
-	}
-
-	dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
-		size, mci_dsta, mci_dcnt);
+	dbg(host, dbg_dma, "DMA FINISHED\n");
 
 	host->dma_complete = 1;
 	host->complete_what = COMPLETION_FINALIZE;
 
-out:
 	tasklet_schedule(&host->pio_tasklet);
 	spin_unlock_irqrestore(&host->complete_lock, iflags);
-	return;
 
-fail_request:
-	host->mrq->data->error = -EINVAL;
-	host->complete_what = COMPLETION_FINALIZE;
-	clear_imask(host);
-
-	goto out;
 }
 
 static void finalize_request(struct s3cmci_host *host)
@@ -966,7 +911,7 @@ static void finalize_request(struct s3cm
 	 * DMA channel and the fifo to clear out any garbage. */
 	if (mrq->data->error != 0) {
 		if (s3cmci_host_usedma(host))
-			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+			dmaengine_terminate_all(host->dma);
 
 		if (host->is2440) {
 			/* Clear failure register and reset fifo. */
@@ -992,29 +937,6 @@ request_done:
 	mmc_request_done(host->mmc, mrq);
 }
 
-static void s3cmci_dma_setup(struct s3cmci_host *host,
-			     enum dma_data_direction source)
-{
-	static enum dma_data_direction last_source = -1;
-	static int setup_ok;
-
-	if (last_source == source)
-		return;
-
-	last_source = source;
-
-	s3c2410_dma_devconfig(host->dma, source,
-			      host->mem->start + host->sdidata);
-
-	if (!setup_ok) {
-		s3c2410_dma_config(host->dma, 4);
-		s3c2410_dma_set_buffdone_fn(host->dma,
-					    s3cmci_dma_done_callback);
-		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
-		setup_ok = 1;
-	}
-}
-
 static void s3cmci_send_command(struct s3cmci_host *host,
 					struct mmc_command *cmd)
 {
@@ -1162,43 +1084,45 @@ static int s3cmci_prepare_pio(struct s3c
 
 static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 {
-	int dma_len, i;
 	int rw = data->flags & MMC_DATA_WRITE;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_slave_config conf = {
+		.src_addr = host->mem->start + host->sdidata,
+		.dst_addr = host->mem->start + host->sdidata,
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+		.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+	};
 
 	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
-
-	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-			     rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-	if (dma_len == 0)
-		return -ENOMEM;
-
-	host->dma_complete = 0;
-	host->dmatogo = dma_len;
-
-	for (i = 0; i < dma_len; i++) {
-		int res;
-
-		dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
-		    sg_dma_address(&data->sg[i]),
-		    sg_dma_len(&data->sg[i]));
+	/* Restore prescaler value */
+	writel(host->prescaler, host->base + S3C2410_SDIPRE);
 
-		res = s3c2410_dma_enqueue(host->dma, host,
-					  sg_dma_address(&data->sg[i]),
-					  sg_dma_len(&data->sg[i]));
+	if (!rw)
+		conf.direction = DMA_DEV_TO_MEM;
+	else
+		conf.direction = DMA_MEM_TO_DEV;
 
-		if (res) {
-			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
-			return -EBUSY;
-		}
-	}
+	dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
-	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
+	dmaengine_slave_config(host->dma, &conf);
+	desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len,
+		conf.direction,
+		DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	if (!desc)
+		goto unmap_exit;
+	desc->callback = s3cmci_dma_done_callback;
+	desc->callback_param = host;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(host->dma);
 
 	return 0;
+
+unmap_exit:
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	return -ENOMEM;
 }
 
 static void s3cmci_send_request(struct mmc_host *mmc)
@@ -1676,10 +1600,6 @@ static int s3cmci_probe(struct platform_
 	host->complete_what 	= COMPLETION_NONE;
 	host->pio_active 	= XFER_NONE;
 
-#ifdef CONFIG_MMC_S3C_PIODMA
-	host->dodma		= host->pdata->use_dma;
-#endif
-
 	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!host->mem) {
 		dev_err(&pdev->dev,
@@ -1765,17 +1685,17 @@ static int s3cmci_probe(struct platform_
 	/* depending on the dma state, get a dma channel to use. */
 
 	if (s3cmci_host_usedma(host)) {
-		host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
-						host);
-		if (host->dma < 0) {
+		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) {
 			dev_err(&pdev->dev, "cannot get DMA channel.\n");
-			if (!s3cmci_host_canpio()) {
-				ret = -EBUSY;
-				goto probe_free_gpio_wp;
-			} else {
-				dev_warn(&pdev->dev, "falling back to PIO.\n");
-				host->dodma = 0;
-			}
+			ret = -EBUSY;
+			goto probe_free_gpio_wp;
 		}
 	}
 
@@ -1787,7 +1707,7 @@ static int s3cmci_probe(struct platform_
 		goto probe_free_dma;
 	}
 
-	ret = clk_enable(host->clk);
+	ret = clk_prepare_enable(host->clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock source.\n");
 		goto clk_free;
@@ -1816,7 +1736,7 @@ static int s3cmci_probe(struct platform_
 	mmc->max_segs		= 128;
 
 	dbg(host, dbg_debug,
-	    "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
+	    "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
 	    (host->is2440?"2440":""),
 	    host->base, host->irq, host->irq_cd, host->dma);
 
@@ -1845,14 +1765,14 @@ static int s3cmci_probe(struct platform_
 	s3cmci_cpufreq_deregister(host);
 
  free_dmabuf:
-	clk_disable(host->clk);
+	clk_disable_unprepare(host->clk);
 
  clk_free:
 	clk_put(host->clk);
 
  probe_free_dma:
 	if (s3cmci_host_usedma(host))
-		s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+		dma_release_channel(host->dma);
 
  probe_free_gpio_wp:
 	if (!host->pdata->no_wprotect)
@@ -1897,7 +1817,7 @@ static void s3cmci_shutdown(struct platf
 	s3cmci_debugfs_remove(host);
 	s3cmci_cpufreq_deregister(host);
 	mmc_remove_host(mmc);
-	clk_disable(host->clk);
+	clk_disable_unprepare(host->clk);
 }
 
 static int s3cmci_remove(struct platform_device *pdev)
@@ -1914,7 +1834,7 @@ static int s3cmci_remove(struct platform
 	tasklet_disable(&host->pio_tasklet);
 
 	if (s3cmci_host_usedma(host))
-		s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+		dma_release_channel(host->dma);
 
 	free_irq(host->irq, host);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/s3cmci.h linux-libre-3.17-rc7-gnu/drivers/mmc/host/s3cmci.h
--- linux-libre-3.16-gnu/drivers/mmc/host/s3cmci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/s3cmci.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@ struct s3cmci_host {
 	void __iomem		*base;
 	int			irq;
 	int			irq_cd;
-	int			dma;
+	struct dma_chan		*dma;
 
 	unsigned long		clk_rate;
 	unsigned long		clk_div;
@@ -36,8 +36,6 @@ struct s3cmci_host {
 	int			is2440;
 	unsigned		sdiimsk;
 	unsigned		sdidata;
-	int			dodma;
-	int			dmatogo;
 
 	bool			irq_disabled;
 	bool			irq_enabled;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-acpi.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-acpi.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,9 +124,11 @@ static const struct sdhci_acpi_chip sdhc
 
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
 	.chip    = &sdhci_acpi_chip_int,
-	.caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET,
+	.caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
+		   MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR,
 	.caps2   = MMC_CAP2_HC_ERASE_SZ,
 	.flags   = SDHCI_ACPI_RUNTIME_PM,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci.c	2014-09-28 17:29:07.000000000 -0400
@@ -1223,8 +1223,16 @@ EXPORT_SYMBOL_GPL(sdhci_set_clock);
 static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
 			    unsigned short vdd)
 {
+	struct mmc_host *mmc = host->mmc;
 	u8 pwr = 0;
 
+	if (!IS_ERR(mmc->supply.vmmc)) {
+		spin_unlock_irq(&host->lock);
+		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+		spin_lock_irq(&host->lock);
+		return;
+	}
+
 	if (mode != MMC_POWER_OFF) {
 		switch (1 << vdd) {
 		case MMC_VDD_165_195:
@@ -1283,12 +1291,6 @@ static void sdhci_set_power(struct sdhci
 		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
 			mdelay(10);
 	}
-
-	if (host->vmmc) {
-		spin_unlock_irq(&host->lock);
-		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
-		spin_lock_irq(&host->lock);
-	}
 }
 
 /*****************************************************************************\
@@ -1440,13 +1442,15 @@ static void sdhci_do_set_ios(struct sdhc
 {
 	unsigned long flags;
 	u8 ctrl;
+	struct mmc_host *mmc = host->mmc;
 
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->flags & SDHCI_DEVICE_DEAD) {
 		spin_unlock_irqrestore(&host->lock, flags);
-		if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
-			mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+		if (!IS_ERR(mmc->supply.vmmc) &&
+		    ios->power_mode == MMC_POWER_OFF)
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
 		return;
 	}
 
@@ -1530,7 +1534,6 @@ static void sdhci_do_set_ios(struct sdhc
 			host->ops->set_clock(host, host->clock);
 		}
 
-
 		/* Reset SD Clock Enable */
 		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
 		clk &= ~SDHCI_CLOCK_CARD_EN;
@@ -1707,6 +1710,7 @@ static void sdhci_enable_sdio_irq(struct
 static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
 						struct mmc_ios *ios)
 {
+	struct mmc_host *mmc = host->mmc;
 	u16 ctrl;
 	int ret;
 
@@ -1725,11 +1729,12 @@ static int sdhci_do_start_signal_voltage
 		ctrl &= ~SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		if (host->vqmmc) {
-			ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
+		if (!IS_ERR(mmc->supply.vqmmc)) {
+			ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
+						    3600000);
 			if (ret) {
 				pr_warning("%s: Switching to 3.3V signalling voltage "
-						" failed\n", mmc_hostname(host->mmc));
+						" failed\n", mmc_hostname(mmc));
 				return -EIO;
 			}
 		}
@@ -1742,16 +1747,16 @@ static int sdhci_do_start_signal_voltage
 			return 0;
 
 		pr_warning("%s: 3.3V regulator output did not became stable\n",
-				mmc_hostname(host->mmc));
+				mmc_hostname(mmc));
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_180:
-		if (host->vqmmc) {
-			ret = regulator_set_voltage(host->vqmmc,
+		if (!IS_ERR(mmc->supply.vqmmc)) {
+			ret = regulator_set_voltage(mmc->supply.vqmmc,
 					1700000, 1950000);
 			if (ret) {
 				pr_warning("%s: Switching to 1.8V signalling voltage "
-						" failed\n", mmc_hostname(host->mmc));
+						" failed\n", mmc_hostname(mmc));
 				return -EIO;
 			}
 		}
@@ -1763,24 +1768,22 @@ static int sdhci_do_start_signal_voltage
 		ctrl |= SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		/* Wait for 5ms */
-		usleep_range(5000, 5500);
-
 		/* 1.8V regulator output should be stable within 5 ms */
 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 		if (ctrl & SDHCI_CTRL_VDD_180)
 			return 0;
 
 		pr_warning("%s: 1.8V regulator output did not became stable\n",
-				mmc_hostname(host->mmc));
+				mmc_hostname(mmc));
 
 		return -EAGAIN;
 	case MMC_SIGNAL_VOLTAGE_120:
-		if (host->vqmmc) {
-			ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000);
+		if (!IS_ERR(mmc->supply.vqmmc)) {
+			ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
+						    1300000);
 			if (ret) {
 				pr_warning("%s: Switching to 1.2V signalling voltage "
-						" failed\n", mmc_hostname(host->mmc));
+						" failed\n", mmc_hostname(mmc));
 				return -EIO;
 			}
 		}
@@ -2643,7 +2646,6 @@ static void sdhci_runtime_pm_bus_off(str
 int sdhci_runtime_suspend_host(struct sdhci_host *host)
 {
 	unsigned long flags;
-	int ret = 0;
 
 	/* Disable tuning since we are suspending */
 	if (host->flags & SDHCI_USING_RETUNING_TIMER) {
@@ -2663,14 +2665,14 @@ int sdhci_runtime_suspend_host(struct sd
 	host->runtime_suspended = true;
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
 
 int sdhci_runtime_resume_host(struct sdhci_host *host)
 {
 	unsigned long flags;
-	int ret = 0, host_flags = host->flags;
+	int host_flags = host->flags;
 
 	if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
 		if (host->ops->enable_dma)
@@ -2709,7 +2711,7 @@ int sdhci_runtime_resume_host(struct sdh
 
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
 
@@ -2820,12 +2822,12 @@ int sdhci_add_host(struct sdhci_host *ho
 		 * (128) and potentially one alignment transfer for
 		 * each of those entries.
 		 */
-		host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
+		host->adma_desc = dma_alloc_coherent(mmc_dev(mmc),
 						     ADMA_SIZE, &host->adma_addr,
 						     GFP_KERNEL);
 		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
 		if (!host->adma_desc || !host->align_buffer) {
-			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+			dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
 					  host->adma_desc, host->adma_addr);
 			kfree(host->align_buffer);
 			pr_warning("%s: Unable to allocate ADMA "
@@ -2838,7 +2840,7 @@ int sdhci_add_host(struct sdhci_host *ho
 			pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
 				   mmc_hostname(mmc));
 			host->flags &= ~SDHCI_USE_ADMA;
-			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+			dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
 					  host->adma_desc, host->adma_addr);
 			kfree(host->align_buffer);
 			host->adma_desc = NULL;
@@ -2853,7 +2855,7 @@ int sdhci_add_host(struct sdhci_host *ho
 	 */
 	if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
 		host->dma_mask = DMA_BIT_MASK(64);
-		mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+		mmc_dev(mmc)->dma_mask = &host->dma_mask;
 	}
 
 	if (host->version >= SDHCI_SPEC_300)
@@ -2959,28 +2961,25 @@ int sdhci_add_host(struct sdhci_host *ho
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
-	    !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
+	    !(mmc->caps & MMC_CAP_NONREMOVABLE))
 		mmc->caps |= MMC_CAP_NEEDS_POLL;
 
+	/* If there are external regulators, get them */
+	if (mmc_regulator_get_supply(mmc) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
 	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
-	host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc");
-	if (IS_ERR_OR_NULL(host->vqmmc)) {
-		if (PTR_ERR(host->vqmmc) < 0) {
-			pr_info("%s: no vqmmc regulator found\n",
-				mmc_hostname(mmc));
-			host->vqmmc = NULL;
-		}
-	} else {
-		ret = regulator_enable(host->vqmmc);
-		if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
-			1950000))
+	if (!IS_ERR(mmc->supply.vqmmc)) {
+		ret = regulator_enable(mmc->supply.vqmmc);
+		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
+						    1950000))
 			caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
 					SDHCI_SUPPORT_SDR50 |
 					SDHCI_SUPPORT_DDR50);
 		if (ret) {
 			pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
 				mmc_hostname(mmc), ret);
-			host->vqmmc = NULL;
+			mmc->supply.vqmmc = NULL;
 		}
 	}
 
@@ -3041,34 +3040,6 @@ int sdhci_add_host(struct sdhci_host *ho
 
 	ocr_avail = 0;
 
-	host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc");
-	if (IS_ERR_OR_NULL(host->vmmc)) {
-		if (PTR_ERR(host->vmmc) < 0) {
-			pr_info("%s: no vmmc regulator found\n",
-				mmc_hostname(mmc));
-			host->vmmc = NULL;
-		}
-	}
-
-#ifdef CONFIG_REGULATOR
-	/*
-	 * Voltage range check makes sense only if regulator reports
-	 * any voltage value.
-	 */
-	if (host->vmmc && regulator_get_voltage(host->vmmc) > 0) {
-		ret = regulator_is_supported_voltage(host->vmmc, 2700000,
-			3600000);
-		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
-			caps[0] &= ~SDHCI_CAN_VDD_330;
-		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
-			caps[0] &= ~SDHCI_CAN_VDD_300;
-		ret = regulator_is_supported_voltage(host->vmmc, 1700000,
-			1950000);
-		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
-			caps[0] &= ~SDHCI_CAN_VDD_180;
-	}
-#endif /* CONFIG_REGULATOR */
-
 	/*
 	 * According to SD Host Controller spec v3.00, if the Host System
 	 * can afford more than 150mA, Host Driver should set XPC to 1. Also
@@ -3077,8 +3048,8 @@ int sdhci_add_host(struct sdhci_host *ho
 	 * value.
 	 */
 	max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
-	if (!max_current_caps && host->vmmc) {
-		u32 curr = regulator_get_current_limit(host->vmmc);
+	if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
+		u32 curr = regulator_get_current_limit(mmc->supply.vmmc);
 		if (curr > 0) {
 
 			/* convert to SDHCI_MAX_CURRENT format */
@@ -3118,8 +3089,12 @@ int sdhci_add_host(struct sdhci_host *ho
 				   SDHCI_MAX_CURRENT_MULTIPLIER;
 	}
 
+	/* If OCR set by external regulators, use it instead */
+	if (mmc->ocr_avail)
+		ocr_avail = mmc->ocr_avail;
+
 	if (host->ocr_mask)
-		ocr_avail = host->ocr_mask;
+		ocr_avail &= host->ocr_mask;
 
 	mmc->ocr_avail = ocr_avail;
 	mmc->ocr_avail_sdio = ocr_avail;
@@ -3273,6 +3248,7 @@ EXPORT_SYMBOL_GPL(sdhci_add_host);
 
 void sdhci_remove_host(struct sdhci_host *host, int dead)
 {
+	struct mmc_host *mmc = host->mmc;
 	unsigned long flags;
 
 	if (dead) {
@@ -3282,7 +3258,7 @@ void sdhci_remove_host(struct sdhci_host
 
 		if (host->mrq) {
 			pr_err("%s: Controller removed during "
-				" transfer!\n", mmc_hostname(host->mmc));
+				" transfer!\n", mmc_hostname(mmc));
 
 			host->mrq->cmd->error = -ENOMEDIUM;
 			tasklet_schedule(&host->finish_tasklet);
@@ -3293,7 +3269,7 @@ void sdhci_remove_host(struct sdhci_host
 
 	sdhci_disable_card_detection(host);
 
-	mmc_remove_host(host->mmc);
+	mmc_remove_host(mmc);
 
 #ifdef SDHCI_USE_LEDS_CLASS
 	led_classdev_unregister(&host->led);
@@ -3310,18 +3286,14 @@ void sdhci_remove_host(struct sdhci_host
 
 	tasklet_kill(&host->finish_tasklet);
 
-	if (host->vmmc) {
-		regulator_disable(host->vmmc);
-		regulator_put(host->vmmc);
-	}
+	if (!IS_ERR(mmc->supply.vmmc))
+		regulator_disable(mmc->supply.vmmc);
 
-	if (host->vqmmc) {
-		regulator_disable(host->vqmmc);
-		regulator_put(host->vqmmc);
-	}
+	if (!IS_ERR(mmc->supply.vqmmc))
+		regulator_disable(mmc->supply.vqmmc);
 
 	if (host->adma_desc)
-		dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+		dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
 				  host->adma_desc, host->adma_addr);
 	kfree(host->align_buffer);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-msm.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-msm.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-msm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-msm.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,6 @@
 
 #include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/regulator/consumer.h>
 #include <linux/delay.h>
 #include <linux/mmc/mmc.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pci.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pci.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,6 +103,10 @@ static const struct sdhci_pci_fixes sdhc
 			  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
+static const struct sdhci_pci_fixes sdhci_intel_qrk = {
+	.quirks		= SDHCI_QUIRK_NO_HISPD_BIT,
+};
+
 static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -264,7 +268,7 @@ static void sdhci_pci_int_hw_reset(struc
 static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
-				 MMC_CAP_HW_RESET;
+				 MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
 	slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
 	slot->hw_reset = sdhci_pci_int_hw_reset;
 	return 0;
@@ -279,6 +283,7 @@ static int byt_sdio_probe_slot(struct sd
 static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
 	.allow_runtime_pm = true,
 	.probe_slot	= byt_emmc_probe_slot,
+	.quirks2	= SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
@@ -753,6 +758,14 @@ static const struct pci_device_id pci_id
 
 	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_QRK_SD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_qrk,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_MRST_SD0,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
@@ -1130,18 +1143,13 @@ static int sdhci_pci_suspend(struct devi
 			goto err_pci_suspend;
 	}
 
-	pci_save_state(pdev);
 	if (pm_flags & MMC_PM_KEEP_POWER) {
-		if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
-			pci_pme_active(pdev, true);
-			pci_enable_wake(pdev, PCI_D3hot, 1);
-		}
-		pci_set_power_state(pdev, PCI_D3hot);
-	} else {
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_disable_device(pdev);
-		pci_set_power_state(pdev, PCI_D3hot);
-	}
+		if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+			device_init_wakeup(dev, true);
+		else
+			device_init_wakeup(dev, false);
+	} else
+		device_init_wakeup(dev, false);
 
 	return 0;
 
@@ -1162,12 +1170,6 @@ static int sdhci_pci_resume(struct devic
 	if (!chip)
 		return 0;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-
 	if (chip->fixes && chip->fixes->resume) {
 		ret = chip->fixes->resume(chip);
 		if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pci.h linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pci.h
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pci.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 #define PCI_DEVICE_ID_INTEL_CLV_SDIO2	0x08fb
 #define PCI_DEVICE_ID_INTEL_CLV_EMMC0	0x08e5
 #define PCI_DEVICE_ID_INTEL_CLV_EMMC1	0x08e6
+#define PCI_DEVICE_ID_INTEL_QRK_SD	0x08A7
 
 /*
  * PCI registers
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pxav3.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pxav3.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-pxav3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-pxav3.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,15 +288,13 @@ static int sdhci_pxav3_probe(struct plat
 	int ret;
 	struct clk *clk;
 
-	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+	pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL);
 	if (!pxa)
 		return -ENOMEM;
 
 	host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0);
-	if (IS_ERR(host)) {
-		kfree(pxa);
+	if (IS_ERR(host))
 		return PTR_ERR(host);
-	}
 
 	if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
 		ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
@@ -308,7 +306,7 @@ static int sdhci_pxav3_probe(struct plat
 	pltfm_host = sdhci_priv(host);
 	pltfm_host->priv = pxa;
 
-	clk = clk_get(dev, NULL);
+	clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(dev, "failed to get io clock\n");
 		ret = PTR_ERR(clk);
@@ -389,11 +387,9 @@ err_add_host:
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	clk_disable_unprepare(clk);
-	clk_put(clk);
 err_clk_get:
 err_mbus_win:
 	sdhci_pltfm_free(pdev);
-	kfree(pxa);
 	return ret;
 }
 
@@ -401,17 +397,14 @@ static int sdhci_pxav3_remove(struct pla
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct sdhci_pxa *pxa = pltfm_host->priv;
 
 	pm_runtime_get_sync(&pdev->dev);
 	sdhci_remove_host(host, 1);
 	pm_runtime_disable(&pdev->dev);
 
 	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
 
 	sdhci_pltfm_free(pdev);
-	kfree(pxa);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-st.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-st.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-st.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-st.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * Support for SDHCI on STMicroelectronics SoCs
+ *
+ * Copyright (C) 2014 STMicroelectronics Ltd
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ * Contributors: Peter Griffin <peter.griffin@linaro.org>
+ *
+ * Based on sdhci-cns3xxx.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci-pltfm.h"
+
+static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
+{
+	u32 ret;
+
+	switch (reg) {
+	case SDHCI_CAPABILITIES:
+		ret = readl_relaxed(host->ioaddr + reg);
+		/* Support 3.3V and 1.8V */
+		ret &= ~SDHCI_CAN_VDD_300;
+		break;
+	default:
+		ret = readl_relaxed(host->ioaddr + reg);
+	}
+	return ret;
+}
+
+static const struct sdhci_ops sdhci_st_ops = {
+	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.set_clock = sdhci_set_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.read_l = sdhci_st_readl,
+	.reset = sdhci_reset,
+};
+
+static const struct sdhci_pltfm_data sdhci_st_pdata = {
+	.ops = &sdhci_st_ops,
+	.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+	    SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+};
+
+
+static int sdhci_st_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct clk *clk;
+	int ret = 0;
+	u16 host_version;
+
+	clk =  devm_clk_get(&pdev->dev, "mmc");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Peripheral clk not found\n");
+		return PTR_ERR(clk);
+	}
+
+	host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
+	if (IS_ERR(host)) {
+		dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
+		return PTR_ERR(host);
+	}
+
+	ret = mmc_of_parse(host->mmc);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed mmc_of_parse\n");
+		return ret;
+	}
+
+	clk_prepare_enable(clk);
+
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->clk = clk;
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed sdhci_add_host\n");
+		goto err_out;
+	}
+
+	platform_set_drvdata(pdev, host);
+
+	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
+
+	dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
+		((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
+		((host_version & SDHCI_VENDOR_VER_MASK) >>
+		SDHCI_VENDOR_VER_SHIFT));
+
+	return 0;
+
+err_out:
+	clk_disable_unprepare(clk);
+	sdhci_pltfm_free(pdev);
+
+	return ret;
+}
+
+static int sdhci_st_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	clk_disable_unprepare(pltfm_host->clk);
+
+	return sdhci_pltfm_unregister(pdev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_st_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	int ret = sdhci_suspend_host(host);
+
+	if (ret)
+		goto out;
+
+	clk_disable_unprepare(pltfm_host->clk);
+out:
+	return ret;
+}
+
+static int sdhci_st_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	clk_prepare_enable(pltfm_host->clk);
+
+	return sdhci_resume_host(host);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
+
+static const struct of_device_id st_sdhci_match[] = {
+	{ .compatible = "st,sdhci" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, st_sdhci_match);
+
+static struct platform_driver sdhci_st_driver = {
+	.probe = sdhci_st_probe,
+	.remove = sdhci_st_remove,
+	.driver = {
+		   .name = "sdhci-st",
+		   .pm = &sdhci_st_pmops,
+		   .of_match_table = of_match_ptr(st_sdhci_match),
+		  },
+};
+
+module_platform_driver(sdhci_st_driver);
+
+MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:st-sdhci");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sdhci-tegra.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-tegra.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sdhci-tegra.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sdhci-tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,8 +26,6 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/slot-gpio.h>
 
-#include <asm/gpio.h>
-
 #include "sdhci-pltfm.h"
 
 /* Tegra SDHOST controller vendor register definitions */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/sh_mmcif.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/sh_mmcif.c
--- linux-libre-3.16-gnu/drivers/mmc/host/sh_mmcif.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/sh_mmcif.c	2014-09-28 17:29:07.000000000 -0400
@@ -386,7 +386,7 @@ sh_mmcif_request_dma_one(struct sh_mmcif
 			 struct sh_mmcif_plat_data *pdata,
 			 enum dma_transfer_direction direction)
 {
-	struct dma_slave_config cfg;
+	struct dma_slave_config cfg = { 0, };
 	struct dma_chan *chan;
 	unsigned int slave_id;
 	struct resource *res;
@@ -417,8 +417,15 @@ sh_mmcif_request_dma_one(struct sh_mmcif
 	/* In the OF case the driver will get the slave ID from the DT */
 	cfg.slave_id = slave_id;
 	cfg.direction = direction;
-	cfg.dst_addr = res->start + MMCIF_CE_DATA;
-	cfg.src_addr = 0;
+
+	if (direction == DMA_DEV_TO_MEM) {
+		cfg.src_addr = res->start + MMCIF_CE_DATA;
+		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	} else {
+		cfg.dst_addr = res->start + MMCIF_CE_DATA;
+		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	}
+
 	ret = dmaengine_slave_config(chan, &cfg);
 	if (ret < 0) {
 		dma_release_channel(chan);
@@ -1378,26 +1385,19 @@ static int sh_mmcif_probe(struct platfor
 		dev_err(&pdev->dev, "Get irq error\n");
 		return -ENXIO;
 	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "platform_get_resource error.\n");
-		return -ENXIO;
-	}
-	reg = ioremap(res->start, resource_size(res));
-	if (!reg) {
-		dev_err(&pdev->dev, "ioremap error.\n");
-		return -ENOMEM;
-	}
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
 
 	mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
-	if (!mmc) {
-		ret = -ENOMEM;
-		goto ealloch;
-	}
+	if (!mmc)
+		return -ENOMEM;
 
 	ret = mmc_of_parse(mmc);
 	if (ret < 0)
-		goto eofparse;
+		goto err_host;
 
 	host		= mmc_priv(mmc);
 	host->mmc	= mmc;
@@ -1427,19 +1427,19 @@ static int sh_mmcif_probe(struct platfor
 	pm_runtime_enable(&pdev->dev);
 	host->power = false;
 
-	host->hclk = clk_get(&pdev->dev, NULL);
+	host->hclk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(host->hclk)) {
 		ret = PTR_ERR(host->hclk);
 		dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
-		goto eclkget;
+		goto err_pm;
 	}
 	ret = sh_mmcif_clk_update(host);
 	if (ret < 0)
-		goto eclkupdate;
+		goto err_pm;
 
 	ret = pm_runtime_resume(&pdev->dev);
 	if (ret < 0)
-		goto eresume;
+		goto err_clk;
 
 	INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
 
@@ -1447,65 +1447,55 @@ static int sh_mmcif_probe(struct platfor
 	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
 	name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error";
-	ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host);
+	ret = devm_request_threaded_irq(&pdev->dev, irq[0], sh_mmcif_intr,
+					sh_mmcif_irqt, 0, name, host);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq error (%s)\n", name);
-		goto ereqirq0;
+		goto err_clk;
 	}
 	if (irq[1] >= 0) {
-		ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt,
-					   0, "sh_mmc:int", host);
+		ret = devm_request_threaded_irq(&pdev->dev, irq[1],
+						sh_mmcif_intr, sh_mmcif_irqt,
+						0, "sh_mmc:int", host);
 		if (ret) {
 			dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
-			goto ereqirq1;
+			goto err_clk;
 		}
 	}
 
 	if (pd && pd->use_cd_gpio) {
 		ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
 		if (ret < 0)
-			goto erqcd;
+			goto err_clk;
 	}
 
 	mutex_init(&host->thread_lock);
 
-	clk_disable_unprepare(host->hclk);
 	ret = mmc_add_host(mmc);
 	if (ret < 0)
-		goto emmcaddh;
+		goto err_clk;
 
 	dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
-	dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
-	dev_dbg(&pdev->dev, "chip ver H'%04x\n",
-		sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
+	dev_info(&pdev->dev, "Chip version 0x%04x, clock rate %luMHz\n",
+		 sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0xffff,
+		 clk_get_rate(host->hclk) / 1000000UL);
+
+	clk_disable_unprepare(host->hclk);
 	return ret;
 
-emmcaddh:
-erqcd:
-	if (irq[1] >= 0)
-		free_irq(irq[1], host);
-ereqirq1:
-	free_irq(irq[0], host);
-ereqirq0:
-	pm_runtime_suspend(&pdev->dev);
-eresume:
+err_clk:
 	clk_disable_unprepare(host->hclk);
-eclkupdate:
-	clk_put(host->hclk);
-eclkget:
+err_pm:
 	pm_runtime_disable(&pdev->dev);
-eofparse:
+err_host:
 	mmc_free_host(mmc);
-ealloch:
-	iounmap(reg);
 	return ret;
 }
 
 static int sh_mmcif_remove(struct platform_device *pdev)
 {
 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
-	int irq[2];
 
 	host->dying = true;
 	clk_prepare_enable(host->hclk);
@@ -1523,16 +1513,6 @@ static int sh_mmcif_remove(struct platfo
 	 */
 	cancel_delayed_work_sync(&host->timeout_work);
 
-	if (host->addr)
-		iounmap(host->addr);
-
-	irq[0] = platform_get_irq(pdev, 0);
-	irq[1] = platform_get_irq(pdev, 1);
-
-	free_irq(irq[0], host);
-	if (irq[1] >= 0)
-		free_irq(irq[1], host);
-
 	clk_disable_unprepare(host->hclk);
 	mmc_free_host(host->mmc);
 	pm_runtime_put_sync(&pdev->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/tmio_mmc_dma.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/tmio_mmc_dma.c
--- linux-libre-3.16-gnu/drivers/mmc/host/tmio_mmc_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/tmio_mmc_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -294,6 +294,7 @@ void tmio_mmc_request_dma(struct tmio_mm
 			cfg.slave_id = pdata->dma->slave_id_tx;
 		cfg.direction = DMA_MEM_TO_DEV;
 		cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift);
+		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		cfg.src_addr = 0;
 		ret = dmaengine_slave_config(host->chan_tx, &cfg);
 		if (ret < 0)
@@ -312,6 +313,7 @@ void tmio_mmc_request_dma(struct tmio_mm
 			cfg.slave_id = pdata->dma->slave_id_rx;
 		cfg.direction = DMA_DEV_TO_MEM;
 		cfg.src_addr = cfg.dst_addr;
+		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		cfg.dst_addr = 0;
 		ret = dmaengine_slave_config(host->chan_rx, &cfg);
 		if (ret < 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mmc/host/wmt-sdmmc.c linux-libre-3.17-rc7-gnu/drivers/mmc/host/wmt-sdmmc.c
--- linux-libre-3.16-gnu/drivers/mmc/host/wmt-sdmmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mmc/host/wmt-sdmmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,6 @@
 #define BM_SPI_CS			0x20
 #define BM_SD_POWER			0x40
 #define BM_SOFT_RESET			0x80
-#define BM_ONEBIT_MASK			0xFD
 
 /* SDMMC_BLKLEN bit fields */
 #define BLKL_CRCERR_ABORT		0x0800
@@ -120,6 +119,8 @@
 #define STS2_DATARSP_BUSY		0x20
 #define STS2_DIS_FORCECLK		0x80
 
+/* SDMMC_EXTCTRL bit fields */
+#define EXT_EIGHTBIT			0x04
 
 /* MMC/SD DMA Controller Registers */
 #define SDDMA_GCR			0x100
@@ -672,7 +673,7 @@ static void wmt_mci_request(struct mmc_h
 static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct wmt_mci_priv *priv;
-	u32 reg_tmp;
+	u32 busmode, extctrl;
 
 	priv = mmc_priv(mmc);
 
@@ -687,28 +688,26 @@ static void wmt_mci_set_ios(struct mmc_h
 	if (ios->clock != 0)
 		clk_set_rate(priv->clk_sdmmc, ios->clock);
 
+	busmode = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+	extctrl = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+
+	busmode &= ~(BM_EIGHTBIT_MODE | BM_FOURBIT_MODE);
+	extctrl &= ~EXT_EIGHTBIT;
+
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_8:
-		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
-		writeb(reg_tmp | 0x04, priv->sdmmc_base + SDMMC_EXTCTRL);
+		busmode |= BM_EIGHTBIT_MODE;
+		extctrl |= EXT_EIGHTBIT;
 		break;
 	case MMC_BUS_WIDTH_4:
-		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
-		writeb(reg_tmp | BM_FOURBIT_MODE, priv->sdmmc_base +
-		       SDMMC_BUSMODE);
-
-		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
-		writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+		busmode |= BM_FOURBIT_MODE;
 		break;
 	case MMC_BUS_WIDTH_1:
-		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
-		writeb(reg_tmp & BM_ONEBIT_MASK, priv->sdmmc_base +
-		       SDMMC_BUSMODE);
-
-		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
-		writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
 		break;
 	}
+
+	writeb(busmode, priv->sdmmc_base + SDMMC_BUSMODE);
+	writeb(extctrl, priv->sdmmc_base + SDMMC_EXTCTRL);
 }
 
 static int wmt_mci_get_ro(struct mmc_host *mmc)
@@ -830,7 +829,7 @@ static int wmt_mci_probe(struct platform
 		goto fail3;
 	}
 
-	ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv);
+	ret = request_irq(dma_irq, wmt_mci_dma_isr, 0, "sdmmc", priv);
 	if (ret) {
 		dev_err(&pdev->dev, "Register DMA IRQ fail\n");
 		goto fail4;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/chips/cfi_cmdset_0002.c linux-libre-3.17-rc7-gnu/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-libre-3.16-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,18 @@ static void cfi_amdstd_sync (struct mtd_
 static int cfi_amdstd_suspend (struct mtd_info *);
 static void cfi_amdstd_resume (struct mtd_info *);
 static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
+static int cfi_amdstd_get_fact_prot_info(struct mtd_info *, size_t,
+					 size_t *, struct otp_info *);
+static int cfi_amdstd_get_user_prot_info(struct mtd_info *, size_t,
+					 size_t *, struct otp_info *);
 static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *, loff_t, size_t,
+					 size_t *, u_char *);
+static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t,
+					 size_t *, u_char *);
+static int cfi_amdstd_write_user_prot_reg(struct mtd_info *, loff_t, size_t,
+					  size_t *, u_char *);
+static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *, loff_t, size_t);
 
 static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
 				  size_t *retlen, const u_char *buf);
@@ -518,6 +529,12 @@ struct mtd_info *cfi_cmdset_0002(struct
 	mtd->_sync    = cfi_amdstd_sync;
 	mtd->_suspend = cfi_amdstd_suspend;
 	mtd->_resume  = cfi_amdstd_resume;
+	mtd->_read_user_prot_reg = cfi_amdstd_read_user_prot_reg;
+	mtd->_read_fact_prot_reg = cfi_amdstd_read_fact_prot_reg;
+	mtd->_get_fact_prot_info = cfi_amdstd_get_fact_prot_info;
+	mtd->_get_user_prot_info = cfi_amdstd_get_user_prot_info;
+	mtd->_write_user_prot_reg = cfi_amdstd_write_user_prot_reg;
+	mtd->_lock_user_prot_reg = cfi_amdstd_lock_user_prot_reg;
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
 	mtd->writesize = 1;
@@ -628,6 +645,23 @@ struct mtd_info *cfi_cmdset_0002(struct
 		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
 		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
 		cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+		/*
+		 * First calculate the timeout max according to timeout field
+		 * of struct cfi_ident that probed from chip's CFI aera, if
+		 * available. Specify a minimum of 2000us, in case the CFI data
+		 * is wrong.
+		 */
+		if (cfi->cfiq->BufWriteTimeoutTyp &&
+		    cfi->cfiq->BufWriteTimeoutMax)
+			cfi->chips[i].buffer_write_time_max =
+				1 << (cfi->cfiq->BufWriteTimeoutTyp +
+				      cfi->cfiq->BufWriteTimeoutMax);
+		else
+			cfi->chips[i].buffer_write_time_max = 0;
+
+		cfi->chips[i].buffer_write_time_max =
+			max(cfi->chips[i].buffer_write_time_max, 2000);
+
 		cfi->chips[i].ref_point_counter = 0;
 		init_waitqueue_head(&(cfi->chips[i].wq));
 	}
@@ -1137,12 +1171,48 @@ static int cfi_amdstd_read (struct mtd_i
 	return ret;
 }
 
+typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
+			loff_t adr, size_t len, u_char *buf, size_t grouplen);
 
-static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
+static inline void otp_enter(struct map_info *map, struct flchip *chip,
+			     loff_t adr, size_t len)
+{
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+
+	INVALIDATE_CACHED_RANGE(map, chip->start + adr, len);
+}
+
+static inline void otp_exit(struct map_info *map, struct flchip *chip,
+			    loff_t adr, size_t len)
+{
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+
+	INVALIDATE_CACHED_RANGE(map, chip->start + adr, len);
+}
+
+static inline int do_read_secsi_onechip(struct map_info *map,
+					struct flchip *chip, loff_t adr,
+					size_t len, u_char *buf,
+					size_t grouplen)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long timeo = jiffies + HZ;
-	struct cfi_private *cfi = map->fldrv_priv;
 
  retry:
 	mutex_lock(&chip->mutex);
@@ -1164,16 +1234,9 @@ static inline int do_read_secsi_onechip(
 
 	chip->state = FL_READY;
 
-	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-
+	otp_enter(map, chip, adr, len);
 	map_copy_from(map, buf, adr, len);
-
-	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-	cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	otp_exit(map, chip, adr, len);
 
 	wake_up(&chip->wq);
 	mutex_unlock(&chip->mutex);
@@ -1205,7 +1268,8 @@ static int cfi_amdstd_secsi_read (struct
 		else
 			thislen = len;
 
-		ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+		ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs,
+					    thislen, buf, 0);
 		if (ret)
 			break;
 
@@ -1219,8 +1283,271 @@ static int cfi_amdstd_secsi_read (struct
 	return ret;
 }
 
+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
+				     unsigned long adr, map_word datum,
+				     int mode);
 
-static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
+static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr,
+			size_t len, u_char *buf, size_t grouplen)
+{
+	int ret;
+	while (len) {
+		unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1);
+		int gap = adr - bus_ofs;
+		int n = min_t(int, len, map_bankwidth(map) - gap);
+		map_word datum;
+
+		if (n != map_bankwidth(map)) {
+			/* partial write of a word, load old contents */
+			otp_enter(map, chip, bus_ofs, map_bankwidth(map));
+			datum = map_read(map, bus_ofs);
+			otp_exit(map, chip, bus_ofs, map_bankwidth(map));
+		}
+
+		datum = map_word_load_partial(map, datum, buf, gap, n);
+		ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
+		if (ret)
+			return ret;
+
+		adr += n;
+		buf += n;
+		len -= n;
+	}
+
+	return 0;
+}
+
+static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr,
+		       size_t len, u_char *buf, size_t grouplen)
+{
+	struct cfi_private *cfi = map->fldrv_priv;
+	uint8_t lockreg;
+	unsigned long timeo;
+	int ret;
+
+	/* make sure area matches group boundaries */
+	if ((adr != 0) || (len != grouplen))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	ret = get_chip(map, chip, chip->start, FL_LOCKING);
+	if (ret) {
+		mutex_unlock(&chip->mutex);
+		return ret;
+	}
+	chip->state = FL_LOCKING;
+
+	/* Enter lock register command */
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x40, cfi->addr_unlock1, chip->start, map, cfi,
+			 cfi->device_type, NULL);
+
+	/* read lock register */
+	lockreg = cfi_read_query(map, 0);
+
+	/* set bit 0 to protect extended memory block */
+	lockreg &= ~0x01;
+
+	/* set bit 0 to protect extended memory block */
+	/* write lock register */
+	map_write(map, CMD(0xA0), chip->start);
+	map_write(map, CMD(lockreg), chip->start);
+
+	/* wait for chip to become ready */
+	timeo = jiffies + msecs_to_jiffies(2);
+	for (;;) {
+		if (chip_ready(map, adr))
+			break;
+
+		if (time_after(jiffies, timeo)) {
+			pr_err("Waiting for chip to be ready timed out.\n");
+			ret = -EIO;
+			break;
+		}
+		UDELAY(map, chip, 0, 1);
+	}
+
+	/* exit protection commands */
+	map_write(map, CMD(0x90), chip->start);
+	map_write(map, CMD(0x00), chip->start);
+
+	chip->state = FL_READY;
+	put_chip(map, chip, chip->start);
+	mutex_unlock(&chip->mutex);
+
+	return ret;
+}
+
+static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
+			       size_t *retlen, u_char *buf,
+			       otp_op_t action, int user_regs)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	int ofs_factor = cfi->interleave * cfi->device_type;
+	unsigned long base;
+	int chipnum;
+	struct flchip *chip;
+	uint8_t otp, lockreg;
+	int ret;
+
+	size_t user_size, factory_size, otpsize;
+	loff_t user_offset, factory_offset, otpoffset;
+	int user_locked = 0, otplocked;
+
+	*retlen = 0;
+
+	for (chipnum = 0; chipnum < cfi->numchips; chipnum++) {
+		chip = &cfi->chips[chipnum];
+		factory_size = 0;
+		user_size = 0;
+
+		/* Micron M29EW family */
+		if (is_m29ew(cfi)) {
+			base = chip->start;
+
+			/* check whether secsi area is factory locked
+			   or user lockable */
+			mutex_lock(&chip->mutex);
+			ret = get_chip(map, chip, base, FL_CFI_QUERY);
+			if (ret) {
+				mutex_unlock(&chip->mutex);
+				return ret;
+			}
+			cfi_qry_mode_on(base, map, cfi);
+			otp = cfi_read_query(map, base + 0x3 * ofs_factor);
+			cfi_qry_mode_off(base, map, cfi);
+			put_chip(map, chip, base);
+			mutex_unlock(&chip->mutex);
+
+			if (otp & 0x80) {
+				/* factory locked */
+				factory_offset = 0;
+				factory_size = 0x100;
+			} else {
+				/* customer lockable */
+				user_offset = 0;
+				user_size = 0x100;
+
+				mutex_lock(&chip->mutex);
+				ret = get_chip(map, chip, base, FL_LOCKING);
+				if (ret) {
+					mutex_unlock(&chip->mutex);
+					return ret;
+				}
+
+				/* Enter lock register command */
+				cfi_send_gen_cmd(0xAA, cfi->addr_unlock1,
+						 chip->start, map, cfi,
+						 cfi->device_type, NULL);
+				cfi_send_gen_cmd(0x55, cfi->addr_unlock2,
+						 chip->start, map, cfi,
+						 cfi->device_type, NULL);
+				cfi_send_gen_cmd(0x40, cfi->addr_unlock1,
+						 chip->start, map, cfi,
+						 cfi->device_type, NULL);
+				/* read lock register */
+				lockreg = cfi_read_query(map, 0);
+				/* exit protection commands */
+				map_write(map, CMD(0x90), chip->start);
+				map_write(map, CMD(0x00), chip->start);
+				put_chip(map, chip, chip->start);
+				mutex_unlock(&chip->mutex);
+
+				user_locked = ((lockreg & 0x01) == 0x00);
+			}
+		}
+
+		otpsize = user_regs ? user_size : factory_size;
+		if (!otpsize)
+			continue;
+		otpoffset = user_regs ? user_offset : factory_offset;
+		otplocked = user_regs ? user_locked : 1;
+
+		if (!action) {
+			/* return otpinfo */
+			struct otp_info *otpinfo;
+			len -= sizeof(*otpinfo);
+			if (len <= 0)
+				return -ENOSPC;
+			otpinfo = (struct otp_info *)buf;
+			otpinfo->start = from;
+			otpinfo->length = otpsize;
+			otpinfo->locked = otplocked;
+			buf += sizeof(*otpinfo);
+			*retlen += sizeof(*otpinfo);
+			from += otpsize;
+		} else if ((from < otpsize) && (len > 0)) {
+			size_t size;
+			size = (len < otpsize - from) ? len : otpsize - from;
+			ret = action(map, chip, otpoffset + from, size, buf,
+				     otpsize);
+			if (ret < 0)
+				return ret;
+
+			buf += size;
+			len -= size;
+			*retlen += size;
+			from = 0;
+		} else {
+			from -= otpsize;
+		}
+	}
+	return 0;
+}
+
+static int cfi_amdstd_get_fact_prot_info(struct mtd_info *mtd, size_t len,
+					 size_t *retlen, struct otp_info *buf)
+{
+	return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
+				   NULL, 0);
+}
+
+static int cfi_amdstd_get_user_prot_info(struct mtd_info *mtd, size_t len,
+					 size_t *retlen, struct otp_info *buf)
+{
+	return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
+				   NULL, 1);
+}
+
+static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+					 size_t len, size_t *retlen,
+					 u_char *buf)
+{
+	return cfi_amdstd_otp_walk(mtd, from, len, retlen,
+				   buf, do_read_secsi_onechip, 0);
+}
+
+static int cfi_amdstd_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+					 size_t len, size_t *retlen,
+					 u_char *buf)
+{
+	return cfi_amdstd_otp_walk(mtd, from, len, retlen,
+				   buf, do_read_secsi_onechip, 1);
+}
+
+static int cfi_amdstd_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+					  size_t len, size_t *retlen,
+					  u_char *buf)
+{
+	return cfi_amdstd_otp_walk(mtd, from, len, retlen, buf,
+				   do_otp_write, 1);
+}
+
+static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+					 size_t len)
+{
+	size_t retlen;
+	return cfi_amdstd_otp_walk(mtd, from, len, &retlen, NULL,
+				   do_otp_lock, 1);
+}
+
+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
+				     unsigned long adr, map_word datum,
+				     int mode)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	unsigned long timeo = jiffies + HZ;
@@ -1241,7 +1568,7 @@ static int __xipram do_write_oneword(str
 	adr += chip->start;
 
 	mutex_lock(&chip->mutex);
-	ret = get_chip(map, chip, adr, FL_WRITING);
+	ret = get_chip(map, chip, adr, mode);
 	if (ret) {
 		mutex_unlock(&chip->mutex);
 		return ret;
@@ -1250,6 +1577,9 @@ static int __xipram do_write_oneword(str
 	pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
 	       __func__, adr, datum.x[0] );
 
+	if (mode == FL_OTP_WRITE)
+		otp_enter(map, chip, adr, map_bankwidth(map));
+
 	/*
 	 * Check for a NOP for the case when the datum to write is already
 	 * present - it saves time and works around buggy chips that corrupt
@@ -1266,12 +1596,13 @@ static int __xipram do_write_oneword(str
 	XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
 	ENABLE_VPP(map);
 	xip_disable(map, chip, adr);
+
  retry:
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	map_write(map, datum, adr);
-	chip->state = FL_WRITING;
+	chip->state = mode;
 
 	INVALIDATE_CACHE_UDELAY(map, chip,
 				adr, map_bankwidth(map),
@@ -1280,7 +1611,7 @@ static int __xipram do_write_oneword(str
 	/* See comment above for timeout value. */
 	timeo = jiffies + uWriteTimeout;
 	for (;;) {
-		if (chip->state != FL_WRITING) {
+		if (chip->state != mode) {
 			/* Someone's suspended the write. Sleep */
 			DECLARE_WAITQUEUE(wait, current);
 
@@ -1320,6 +1651,8 @@ static int __xipram do_write_oneword(str
 	}
 	xip_enable(map, chip, adr);
  op_done:
+	if (mode == FL_OTP_WRITE)
+		otp_exit(map, chip, adr, map_bankwidth(map));
 	chip->state = FL_READY;
 	DISABLE_VPP(map);
 	put_chip(map, chip, adr);
@@ -1375,7 +1708,7 @@ static int cfi_amdstd_write_words(struct
 		tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
 
 		ret = do_write_oneword(map, &cfi->chips[chipnum],
-				       bus_ofs, tmp_buf);
+				       bus_ofs, tmp_buf, FL_WRITING);
 		if (ret)
 			return ret;
 
@@ -1399,7 +1732,7 @@ static int cfi_amdstd_write_words(struct
 		datum = map_word_load(map, buf);
 
 		ret = do_write_oneword(map, &cfi->chips[chipnum],
-				       ofs, datum);
+				       ofs, datum, FL_WRITING);
 		if (ret)
 			return ret;
 
@@ -1442,7 +1775,7 @@ static int cfi_amdstd_write_words(struct
 		tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
 
 		ret = do_write_oneword(map, &cfi->chips[chipnum],
-				ofs, tmp_buf);
+				       ofs, tmp_buf, FL_WRITING);
 		if (ret)
 			return ret;
 
@@ -1462,8 +1795,12 @@ static int __xipram do_write_buffer(stru
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	unsigned long timeo = jiffies + HZ;
-	/* see comments in do_write_oneword() regarding uWriteTimeo. */
-	unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
+	/*
+	 * Timeout is calculated according to CFI data, if available.
+	 * See more comments in cfi_cmdset_0002().
+	 */
+	unsigned long uWriteTimeout =
+				usecs_to_jiffies(chip->buffer_write_time_max);
 	int ret = -EIO;
 	unsigned long cmd_adr;
 	int z, words;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/cmdlinepart.c linux-libre-3.17-rc7-gnu/drivers/mtd/cmdlinepart.c
--- linux-libre-3.16-gnu/drivers/mtd/cmdlinepart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/cmdlinepart.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
  * <mtd-id>  := unique name used in mapping driver/device (mtd->name)
  * <size>    := standard linux memsize OR "-" to denote all remaining space
  *              size is automatically truncated at end of device
- *              if specified or trucated size is 0 the part is skipped
+ *              if specified or truncated size is 0 the part is skipped
  * <offset>  := standard linux memsize
  *              if omitted the part will immediately follow the previous part
  *              or 0 if the first part
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/devices/phram.c linux-libre-3.17-rc7-gnu/drivers/mtd/devices/phram.c
--- linux-libre-3.16-gnu/drivers/mtd/devices/phram.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/devices/phram.c	2014-09-28 17:29:07.000000000 -0400
@@ -181,12 +181,10 @@ static int parse_name(char **pname, cons
 	if (len > 64)
 		return -ENOSPC;
 
-	name = kmalloc(len, GFP_KERNEL);
+	name = kstrdup(token, GFP_KERNEL);
 	if (!name)
 		return -ENOMEM;
 
-	strcpy(name, token);
-
 	*pname = name;
 	return 0;
 }
@@ -195,6 +193,7 @@ static int parse_name(char **pname, cons
 static inline void kill_final_newline(char *str)
 {
 	char *newline = strrchr(str, '\n');
+
 	if (newline && !newline[1])
 		*newline = 0;
 }
@@ -233,7 +232,7 @@ static int phram_setup(const char *val)
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i=0; i<3; i++)
+	for (i = 0; i < 3; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/ftl.c linux-libre-3.17-rc7-gnu/drivers/mtd/ftl.c
--- linux-libre-3.16-gnu/drivers/mtd/ftl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/ftl.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,7 +111,6 @@ typedef struct partition_t {
     struct mtd_blktrans_dev mbd;
     uint32_t		state;
     uint32_t		*VirtualBlockMap;
-    uint32_t		*VirtualPageMap;
     uint32_t		FreeTotal;
     struct eun_info_t {
 	uint32_t		Offset;
@@ -1035,8 +1034,6 @@ static void ftl_freepart(partition_t *pa
 {
 	vfree(part->VirtualBlockMap);
 	part->VirtualBlockMap = NULL;
-	kfree(part->VirtualPageMap);
-	part->VirtualPageMap = NULL;
 	kfree(part->EUNInfo);
 	part->EUNInfo = NULL;
 	kfree(part->XferInfo);
@@ -1075,7 +1072,6 @@ static void ftl_add_mtd(struct mtd_blktr
 			return;
 	}
 
-	ftl_freepart(partition);
 	kfree(partition);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/maps/rbtx4939-flash.c linux-libre-3.17-rc7-gnu/drivers/mtd/maps/rbtx4939-flash.c
--- linux-libre-3.16-gnu/drivers/mtd/maps/rbtx4939-flash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/maps/rbtx4939-flash.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,6 @@ static int rbtx4939_flash_remove(struct
 		return 0;
 
 	if (info->mtd) {
-		struct rbtx4939_flash_data *pdata = dev_get_platdata(&dev->dev);
-
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/mtdcore.c linux-libre-3.17-rc7-gnu/drivers/mtd/mtdcore.c
--- linux-libre-3.16-gnu/drivers/mtd/mtdcore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/mtdcore.c	2014-09-28 17:29:07.000000000 -0400
@@ -298,6 +298,47 @@ static ssize_t mtd_ecc_step_size_show(st
 }
 static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL);
 
+static ssize_t mtd_ecc_stats_corrected_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->corrected);
+}
+static DEVICE_ATTR(corrected_bits, S_IRUGO,
+		   mtd_ecc_stats_corrected_show, NULL);
+
+static ssize_t mtd_ecc_stats_errors_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->failed);
+}
+static DEVICE_ATTR(ecc_failures, S_IRUGO, mtd_ecc_stats_errors_show, NULL);
+
+static ssize_t mtd_badblocks_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->badblocks);
+}
+static DEVICE_ATTR(bad_blocks, S_IRUGO, mtd_badblocks_show, NULL);
+
+static ssize_t mtd_bbtblocks_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->bbtblocks);
+}
+static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL);
+
 static struct attribute *mtd_attrs[] = {
 	&dev_attr_type.attr,
 	&dev_attr_flags.attr,
@@ -310,6 +351,10 @@ static struct attribute *mtd_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_ecc_strength.attr,
 	&dev_attr_ecc_step_size.attr,
+	&dev_attr_corrected_bits.attr,
+	&dev_attr_ecc_failures.attr,
+	&dev_attr_bad_blocks.attr,
+	&dev_attr_bbt_blocks.attr,
 	&dev_attr_bitflip_threshold.attr,
 	NULL,
 };
@@ -998,12 +1043,22 @@ int mtd_is_locked(struct mtd_info *mtd,
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
 
-int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
+int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
-	if (!mtd->_block_isbad)
+	if (ofs < 0 || ofs > mtd->size)
+		return -EINVAL;
+	if (!mtd->_block_isreserved)
 		return 0;
+	return mtd->_block_isreserved(mtd, ofs);
+}
+EXPORT_SYMBOL_GPL(mtd_block_isreserved);
+
+int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
 	if (ofs < 0 || ofs > mtd->size)
 		return -EINVAL;
+	if (!mtd->_block_isbad)
+		return 0;
 	return mtd->_block_isbad(mtd, ofs);
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/mtdpart.c linux-libre-3.17-rc7-gnu/drivers/mtd/mtdpart.c
--- linux-libre-3.16-gnu/drivers/mtd/mtdpart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/mtdpart.c	2014-09-28 17:29:07.000000000 -0400
@@ -290,6 +290,13 @@ static void part_resume(struct mtd_info
 	part->master->_resume(part->master);
 }
 
+static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
+{
+	struct mtd_part *part = PART(mtd);
+	ofs += part->offset;
+	return part->master->_block_isreserved(part->master, ofs);
+}
+
 static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_part *part = PART(mtd);
@@ -422,6 +429,8 @@ static struct mtd_part *allocate_partiti
 		slave->mtd._unlock = part_unlock;
 	if (master->_is_locked)
 		slave->mtd._is_locked = part_is_locked;
+	if (master->_block_isreserved)
+		slave->mtd._block_isreserved = part_block_isreserved;
 	if (master->_block_isbad)
 		slave->mtd._block_isbad = part_block_isbad;
 	if (master->_block_markbad)
@@ -526,7 +535,9 @@ static struct mtd_part *allocate_partiti
 		uint64_t offs = 0;
 
 		while (offs < slave->mtd.size) {
-			if (mtd_block_isbad(master, offs + slave->offset))
+			if (mtd_block_isreserved(master, offs + slave->offset))
+				slave->mtd.ecc_stats.bbtblocks++;
+			else if (mtd_block_isbad(master, offs + slave->offset))
 				slave->mtd.ecc_stats.badblocks++;
 			offs += slave->mtd.erasesize;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/atmel_nand.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/atmel_nand.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/atmel_nand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/atmel_nand.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,9 @@ struct atmel_nfc {
 	bool			write_by_sram;
 
 	bool			is_initialized;
-	struct completion	comp_nfc;
+	struct completion	comp_ready;
+	struct completion	comp_cmd_done;
+	struct completion	comp_xfer_done;
 
 	/* Point to the sram bank which include readed data via NFC */
 	void __iomem		*data_in_sram;
@@ -861,12 +863,11 @@ static int pmecc_correction(struct mtd_i
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct atmel_nand_host *host = nand_chip->priv;
-	int i, err_nbr, eccbytes;
+	int i, err_nbr;
 	uint8_t *buf_pos;
 	int total_err = 0;
 
-	eccbytes = nand_chip->ecc.bytes;
-	for (i = 0; i < eccbytes; i++)
+	for (i = 0; i < nand_chip->ecc.total; i++)
 		if (ecc[i] != 0xff)
 			goto normal_check;
 	/* Erased page, return OK */
@@ -928,7 +929,7 @@ static int atmel_nand_pmecc_read_page(st
 	struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
 {
 	struct atmel_nand_host *host = chip->priv;
-	int eccsize = chip->ecc.size;
+	int eccsize = chip->ecc.size * chip->ecc.steps;
 	uint8_t *oob = chip->oob_poi;
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
 	uint32_t stat;
@@ -1169,8 +1170,7 @@ static int atmel_pmecc_nand_init_params(
 		goto err;
 	}
 
-	/* ECC is calculated for the whole page (1 step) */
-	nand_chip->ecc.size = mtd->writesize;
+	nand_chip->ecc.size = sector_size;
 
 	/* set ECC page size and oob layout */
 	switch (mtd->writesize) {
@@ -1185,18 +1185,20 @@ static int atmel_pmecc_nand_init_params(
 		host->pmecc_index_of = host->pmecc_rom_base +
 			host->pmecc_lookup_table_offset;
 
-		nand_chip->ecc.steps = 1;
+		nand_chip->ecc.steps = host->pmecc_sector_number;
 		nand_chip->ecc.strength = cap;
-		nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
+		nand_chip->ecc.bytes = host->pmecc_bytes_per_sector;
+		nand_chip->ecc.total = host->pmecc_bytes_per_sector *
 				       host->pmecc_sector_number;
-		if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
+		if (nand_chip->ecc.total > mtd->oobsize - 2) {
 			dev_err(host->dev, "No room for ECC bytes\n");
 			err_no = -EINVAL;
 			goto err;
 		}
 		pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
 					mtd->oobsize,
-					nand_chip->ecc.bytes);
+					nand_chip->ecc.total);
+
 		nand_chip->ecc.layout = &atmel_pmecc_oobinfo;
 		break;
 	case 512:
@@ -1572,49 +1574,104 @@ static int atmel_hw_nand_init_params(str
 	return 0;
 }
 
+static inline u32 nfc_read_status(struct atmel_nand_host *host)
+{
+	u32 err_flags = NFC_SR_DTOE | NFC_SR_UNDEF | NFC_SR_AWB | NFC_SR_ASE;
+	u32 nfc_status = nfc_readl(host->nfc->hsmc_regs, SR);
+
+	if (unlikely(nfc_status & err_flags)) {
+		if (nfc_status & NFC_SR_DTOE)
+			dev_err(host->dev, "NFC: Waiting Nand R/B Timeout Error\n");
+		else if (nfc_status & NFC_SR_UNDEF)
+			dev_err(host->dev, "NFC: Access Undefined Area Error\n");
+		else if (nfc_status & NFC_SR_AWB)
+			dev_err(host->dev, "NFC: Access memory While NFC is busy\n");
+		else if (nfc_status & NFC_SR_ASE)
+			dev_err(host->dev, "NFC: Access memory Size Error\n");
+	}
+
+	return nfc_status;
+}
+
 /* SMC interrupt service routine */
 static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
 {
 	struct atmel_nand_host *host = dev_id;
 	u32 status, mask, pending;
-	irqreturn_t ret = IRQ_HANDLED;
+	irqreturn_t ret = IRQ_NONE;
 
-	status = nfc_readl(host->nfc->hsmc_regs, SR);
+	status = nfc_read_status(host);
 	mask = nfc_readl(host->nfc->hsmc_regs, IMR);
 	pending = status & mask;
 
 	if (pending & NFC_SR_XFR_DONE) {
-		complete(&host->nfc->comp_nfc);
+		complete(&host->nfc->comp_xfer_done);
 		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
-	} else if (pending & NFC_SR_RB_EDGE) {
-		complete(&host->nfc->comp_nfc);
+		ret = IRQ_HANDLED;
+	}
+	if (pending & NFC_SR_RB_EDGE) {
+		complete(&host->nfc->comp_ready);
 		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
-	} else if (pending & NFC_SR_CMD_DONE) {
-		complete(&host->nfc->comp_nfc);
+		ret = IRQ_HANDLED;
+	}
+	if (pending & NFC_SR_CMD_DONE) {
+		complete(&host->nfc->comp_cmd_done);
 		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE);
-	} else {
-		ret = IRQ_NONE;
+		ret = IRQ_HANDLED;
 	}
 
 	return ret;
 }
 
 /* NFC(Nand Flash Controller) related functions */
-static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
+static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
 {
-	unsigned long timeout;
-	init_completion(&host->nfc->comp_nfc);
+	if (flag & NFC_SR_XFR_DONE)
+		init_completion(&host->nfc->comp_xfer_done);
+
+	if (flag & NFC_SR_RB_EDGE)
+		init_completion(&host->nfc->comp_ready);
+
+	if (flag & NFC_SR_CMD_DONE)
+		init_completion(&host->nfc->comp_cmd_done);
 
 	/* Enable interrupt that need to wait for */
 	nfc_writel(host->nfc->hsmc_regs, IER, flag);
+}
 
-	timeout = wait_for_completion_timeout(&host->nfc->comp_nfc,
-			msecs_to_jiffies(NFC_TIME_OUT_MS));
-	if (timeout)
-		return 0;
+static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
+{
+	int i, index = 0;
+	struct completion *comp[3];	/* Support 3 interrupt completion */
 
-	/* Time out to wait for the interrupt */
+	if (flag & NFC_SR_XFR_DONE)
+		comp[index++] = &host->nfc->comp_xfer_done;
+
+	if (flag & NFC_SR_RB_EDGE)
+		comp[index++] = &host->nfc->comp_ready;
+
+	if (flag & NFC_SR_CMD_DONE)
+		comp[index++] = &host->nfc->comp_cmd_done;
+
+	if (index == 0) {
+		dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < index; i++) {
+		if (wait_for_completion_timeout(comp[i],
+				msecs_to_jiffies(NFC_TIME_OUT_MS)))
+			continue;	/* wait for next completion */
+		else
+			goto err_timeout;
+	}
+
+	return 0;
+
+err_timeout:
 	dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag);
+	/* Disable the interrupt as it is not handled by interrupt handler */
+	nfc_writel(host->nfc->hsmc_regs, IDR, flag);
 	return -ETIMEDOUT;
 }
 
@@ -1622,6 +1679,9 @@ static int nfc_send_command(struct atmel
 	unsigned int cmd, unsigned int addr, unsigned char cycle0)
 {
 	unsigned long timeout;
+	u32 flag = NFC_SR_CMD_DONE;
+	flag |= cmd & NFCADDR_CMD_DATAEN ? NFC_SR_XFR_DONE : 0;
+
 	dev_dbg(host->dev,
 		"nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n",
 		cmd, addr, cycle0);
@@ -1635,18 +1695,28 @@ static int nfc_send_command(struct atmel
 			return -ETIMEDOUT;
 		}
 	}
+
+	nfc_prepare_interrupt(host, flag);
 	nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0);
 	nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs);
-	return nfc_wait_interrupt(host, NFC_SR_CMD_DONE);
+	return nfc_wait_interrupt(host, flag);
 }
 
 static int nfc_device_ready(struct mtd_info *mtd)
 {
+	u32 status, mask;
 	struct nand_chip *nand_chip = mtd->priv;
 	struct atmel_nand_host *host = nand_chip->priv;
-	if (!nfc_wait_interrupt(host, NFC_SR_RB_EDGE))
-		return 1;
-	return 0;
+
+	status = nfc_read_status(host);
+	mask = nfc_readl(host->nfc->hsmc_regs, IMR);
+
+	/* The mask should be 0. If not we may lost interrupts */
+	if (unlikely(mask & status))
+		dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
+				mask & status);
+
+	return status & NFC_SR_RB_EDGE;
 }
 
 static void nfc_select_chip(struct mtd_info *mtd, int chip)
@@ -1795,10 +1865,6 @@ static void nfc_nand_command(struct mtd_
 	nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
 	nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
 
-	if (dataen == NFCADDR_CMD_DATAEN)
-		if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE))
-			dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n");
-
 	/*
 	 * Program and erase have their own busy handlers status, sequential
 	 * in, and deplete1 need no delay.
@@ -1823,6 +1889,7 @@ static void nfc_nand_command(struct mtd_
 		}
 		/* fall through */
 	default:
+		nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
 		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
 	}
 }
@@ -2209,6 +2276,9 @@ static int atmel_nand_nfc_probe(struct p
 		}
 	}
 
+	nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
+	nfc_readl(nfc->hsmc_regs, SR);	/* clear the NFC_SR */
+
 	nfc->is_initialized = true;
 	dev_info(&pdev->dev, "NFC is probed.\n");
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/atmel_nand_nfc.h linux-libre-3.17-rc7-gnu/drivers/mtd/nand/atmel_nand_nfc.h
--- linux-libre-3.16-gnu/drivers/mtd/nand/atmel_nand_nfc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/atmel_nand_nfc.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,10 @@
 #define ATMEL_HSMC_NFC_SR	0x08		/* NFC Status Register */
 #define		NFC_SR_XFR_DONE		(1 << 16)
 #define		NFC_SR_CMD_DONE		(1 << 17)
+#define		NFC_SR_DTOE		(1 << 20)
+#define		NFC_SR_UNDEF		(1 << 21)
+#define		NFC_SR_AWB		(1 << 22)
+#define		NFC_SR_ASE		(1 << 23)
 #define		NFC_SR_RB_EDGE		(1 << 24)
 
 #define ATMEL_HSMC_NFC_IER	0x0c
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/au1550nd.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/au1550nd.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/au1550nd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/au1550nd.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ static u_char au_read_byte(struct mtd_in
 {
 	struct nand_chip *this = mtd->priv;
 	u_char ret = readb(this->IO_ADDR_R);
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -56,7 +56,7 @@ static void au_write_byte(struct mtd_inf
 {
 	struct nand_chip *this = mtd->priv;
 	writeb(byte, this->IO_ADDR_W);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 /**
@@ -69,7 +69,7 @@ static u_char au_read_byte16(struct mtd_
 {
 	struct nand_chip *this = mtd->priv;
 	u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -84,7 +84,7 @@ static void au_write_byte16(struct mtd_i
 {
 	struct nand_chip *this = mtd->priv;
 	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 /**
@@ -97,7 +97,7 @@ static u16 au_read_word(struct mtd_info
 {
 	struct nand_chip *this = mtd->priv;
 	u16 ret = readw(this->IO_ADDR_R);
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -116,7 +116,7 @@ static void au_write_buf(struct mtd_info
 
 	for (i = 0; i < len; i++) {
 		writeb(buf[i], this->IO_ADDR_W);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -135,7 +135,7 @@ static void au_read_buf(struct mtd_info
 
 	for (i = 0; i < len; i++) {
 		buf[i] = readb(this->IO_ADDR_R);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -156,7 +156,7 @@ static void au_write_buf16(struct mtd_in
 
 	for (i = 0; i < len; i++) {
 		writew(p[i], this->IO_ADDR_W);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 
 }
@@ -178,7 +178,7 @@ static void au_read_buf16(struct mtd_inf
 
 	for (i = 0; i < len; i++) {
 		p[i] = readw(this->IO_ADDR_R);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -223,26 +223,23 @@ static void au1550_hwcontrol(struct mtd_
 
 	case NAND_CTL_SETNCE:
 		/* assert (force assert) chip enable */
-		au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
+		alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
 		break;
 
 	case NAND_CTL_CLRNCE:
 		/* deassert chip enable */
-		au_writel(0, MEM_STNDCTL);
+		alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
 		break;
 	}
 
 	this->IO_ADDR_R = this->IO_ADDR_W;
 
-	/* Drain the writebuffer */
-	au_sync();
+	wmb(); /* Drain the writebuffer */
 }
 
 int au1550_device_ready(struct mtd_info *mtd)
 {
-	int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
-	au_sync();
-	return ret;
+	return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/bf5xx_nand.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/bf5xx_nand.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/bf5xx_nand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/bf5xx_nand.c	2014-09-28 17:29:07.000000000 -0400
@@ -830,34 +830,10 @@ out_err:
 	return err;
 }
 
-/* PM Support */
-#ifdef CONFIG_PM
-
-static int bf5xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
-{
-	struct bf5xx_nand_info *info = platform_get_drvdata(dev);
-
-	return 0;
-}
-
-static int bf5xx_nand_resume(struct platform_device *dev)
-{
-	struct bf5xx_nand_info *info = platform_get_drvdata(dev);
-
-	return 0;
-}
-
-#else
-#define bf5xx_nand_suspend NULL
-#define bf5xx_nand_resume NULL
-#endif
-
 /* driver device registration */
 static struct platform_driver bf5xx_nand_driver = {
 	.probe		= bf5xx_nand_probe,
 	.remove		= bf5xx_nand_remove,
-	.suspend	= bf5xx_nand_suspend,
-	.resume		= bf5xx_nand_resume,
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/denali.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/denali.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/denali.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/denali.c	2014-09-28 17:29:07.000000000 -0400
@@ -473,7 +473,7 @@ static void detect_partition_feature(str
 static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 {
 	uint16_t status = PASS;
-	uint32_t id_bytes[5], addr;
+	uint32_t id_bytes[8], addr;
 	uint8_t i, maf_id, device_id;
 
 	dev_dbg(denali->dev,
@@ -488,7 +488,7 @@ static uint16_t denali_nand_timing_set(s
 	addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
 	index_addr(denali, (uint32_t)addr | 0, 0x90);
 	index_addr(denali, (uint32_t)addr | 1, 0);
-	for (i = 0; i < 5; i++)
+	for (i = 0; i < 8; i++)
 		index_addr_read_data(denali, addr | 2, &id_bytes[i]);
 	maf_id = id_bytes[0];
 	device_id = id_bytes[1];
@@ -1276,7 +1276,7 @@ static void denali_cmdfunc(struct mtd_in
 		addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
 		index_addr(denali, (uint32_t)addr | 0, 0x90);
 		index_addr(denali, (uint32_t)addr | 1, 0);
-		for (i = 0; i < 5; i++) {
+		for (i = 0; i < 8; i++) {
 			index_addr_read_data(denali,
 						(uint32_t)addr | 2,
 						&id);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	2014-09-28 17:29:07.000000000 -0400
@@ -285,9 +285,8 @@ static int legacy_set_geometry(struct gp
 	geo->ecc_strength = get_ecc_strength(this);
 	if (!gpmi_check_ecc(this)) {
 		dev_err(this->dev,
-			"We can not support this nand chip."
-			" Its required ecc strength(%d) is beyond our"
-			" capability(%d).\n", geo->ecc_strength,
+			"required ecc strength of the NAND chip: %d is not supported by the GPMI controller (%d)\n",
+			geo->ecc_strength,
 			this->devdata->bch_max_ecc_strength);
 		return -EINVAL;
 	}
@@ -1082,6 +1081,7 @@ static int gpmi_ecc_read_subpage(struct
 	int first, last, marker_pos;
 	int ecc_parity_size;
 	int col = 0;
+	int old_swap_block_mark = this->swap_block_mark;
 
 	/* The size of ECC parity */
 	ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
@@ -1090,17 +1090,21 @@ static int gpmi_ecc_read_subpage(struct
 	first = offs / size;
 	last = (offs + len - 1) / size;
 
-	/*
-	 * Find the chunk which contains the Block Marker. If this chunk is
-	 * in the range of [first, last], we have to read out the whole page.
-	 * Why? since we had swapped the data at the position of Block Marker
-	 * to the metadata which is bound with the chunk 0.
-	 */
-	marker_pos = geo->block_mark_byte_offset / size;
-	if (last >= marker_pos && first <= marker_pos) {
-		dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n",
+	if (this->swap_block_mark) {
+		/*
+		 * Find the chunk which contains the Block Marker.
+		 * If this chunk is in the range of [first, last],
+		 * we have to read out the whole page.
+		 * Why? since we had swapped the data at the position of Block
+		 * Marker to the metadata which is bound with the chunk 0.
+		 */
+		marker_pos = geo->block_mark_byte_offset / size;
+		if (last >= marker_pos && first <= marker_pos) {
+			dev_dbg(this->dev,
+				"page:%d, first:%d, last:%d, marker at:%d\n",
 				page, first, last, marker_pos);
-		return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
+			return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
+		}
 	}
 
 	meta = geo->metadata_size;
@@ -1146,7 +1150,7 @@ static int gpmi_ecc_read_subpage(struct
 	writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0);
 	writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1);
 	this->bch_geometry = old_geo;
-	this->swap_block_mark = true;
+	this->swap_block_mark = old_swap_block_mark;
 
 	return max_bitflips;
 }
@@ -1180,7 +1184,7 @@ static int gpmi_ecc_write_page(struct mt
 
 		/* Handle block mark swapping. */
 		block_mark_swapping(this,
-				(void *) payload_virt, (void *) auxiliary_virt);
+				(void *)payload_virt, (void *)auxiliary_virt);
 	} else {
 		/*
 		 * If control arrives here, we're not doing block mark swapping,
@@ -1310,10 +1314,10 @@ static int gpmi_ecc_read_oob(struct mtd_
 
 	/*
 	 * Now, we want to make sure the block mark is correct. In the
-	 * Swapping/Raw case, we already have it. Otherwise, we need to
-	 * explicitly read it.
+	 * non-transcribing case (!GPMI_IS_MX23()), we already have it.
+	 * Otherwise, we need to explicitly read it.
 	 */
-	if (!this->swap_block_mark) {
+	if (GPMI_IS_MX23(this)) {
 		/* Read the block mark into the first byte of the OOB buffer. */
 		chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
 		chip->oob_poi[0] = chip->read_byte(mtd);
@@ -1354,7 +1358,7 @@ static int gpmi_block_markbad(struct mtd
 	chipnr = (int)(ofs >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
 
-	column = this->swap_block_mark ? mtd->writesize : 0;
+	column = !GPMI_IS_MX23(this) ? mtd->writesize : 0;
 
 	/* Write the block mark. */
 	block_mark = this->data_buffer_dma;
@@ -1597,8 +1601,9 @@ static int mx23_boot_init(struct gpmi_na
 			dev_dbg(dev, "Transcribing mark in block %u\n", block);
 			ret = chip->block_markbad(mtd, byte);
 			if (ret)
-				dev_err(dev, "Failed to mark block bad with "
-							"ret %d\n", ret);
+				dev_err(dev,
+					"Failed to mark block bad with ret %d\n",
+					ret);
 		}
 	}
 
@@ -1649,9 +1654,6 @@ static int gpmi_init_last(struct gpmi_na
 	struct bch_geometry *bch_geo = &this->bch_geometry;
 	int ret;
 
-	/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
-	this->swap_block_mark = !GPMI_IS_MX23(this);
-
 	/* Set up the medium geometry */
 	ret = gpmi_set_geometry(this);
 	if (ret)
@@ -1715,9 +1717,20 @@ static int gpmi_nand_init(struct gpmi_na
 	chip->badblock_pattern	= &gpmi_bbt_descr;
 	chip->block_markbad	= gpmi_block_markbad;
 	chip->options		|= NAND_NO_SUBPAGE_WRITE;
-	if (of_get_nand_on_flash_bbt(this->dev->of_node))
+
+	/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+	this->swap_block_mark = !GPMI_IS_MX23(this);
+
+	if (of_get_nand_on_flash_bbt(this->dev->of_node)) {
 		chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
 
+		if (of_property_read_bool(this->dev->of_node,
+						"fsl,no-blockmark-swap"))
+			this->swap_block_mark = false;
+	}
+	dev_dbg(this->dev, "Blockmark swapping %sabled\n",
+		this->swap_block_mark ? "en" : "dis");
+
 	/*
 	 * Allocate a temporary DMA buffer for reading ID in the
 	 * nand_scan_ident().
@@ -1760,16 +1773,16 @@ err_out:
 static const struct of_device_id gpmi_nand_id_table[] = {
 	{
 		.compatible = "fsl,imx23-gpmi-nand",
-		.data = (void *)&gpmi_devdata_imx23,
+		.data = &gpmi_devdata_imx23,
 	}, {
 		.compatible = "fsl,imx28-gpmi-nand",
-		.data = (void *)&gpmi_devdata_imx28,
+		.data = &gpmi_devdata_imx28,
 	}, {
 		.compatible = "fsl,imx6q-gpmi-nand",
-		.data = (void *)&gpmi_devdata_imx6q,
+		.data = &gpmi_devdata_imx6q,
 	}, {
 		.compatible = "fsl,imx6sx-gpmi-nand",
-		.data = (void *)&gpmi_devdata_imx6sx,
+		.data = &gpmi_devdata_imx6sx,
 	}, {}
 };
 MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/lpc32xx_mlc.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/lpc32xx_mlc.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/lpc32xx_mlc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/lpc32xx_mlc.c	2014-09-28 17:29:07.000000000 -0400
@@ -721,12 +721,6 @@ static int lpc32xx_nand_probe(struct pla
 	nand_chip->bbt_td = &lpc32xx_nand_bbt;
 	nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror;
 
-	/* bitflip_threshold's default is defined as ecc_strength anyway.
-	 * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
-	 * being 0, it causes bad block table scanning errors in
-	 * nand_scan_tail(), so preparing it here. */
-	mtd->bitflip_threshold = nand_chip->ecc.strength;
-
 	if (use_dma) {
 		res = lpc32xx_dma_setup(host);
 		if (res) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/lpc32xx_slc.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/lpc32xx_slc.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/lpc32xx_slc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/lpc32xx_slc.c	2014-09-28 17:29:07.000000000 -0400
@@ -840,12 +840,6 @@ static int lpc32xx_nand_probe(struct pla
 	chip->ecc.strength = 1;
 	chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
 
-	/* bitflip_threshold's default is defined as ecc_strength anyway.
-	 * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
-	 * being 0, it causes bad block table scanning errors in
-	 * nand_scan_tail(), so preparing it here already. */
-	mtd->bitflip_threshold = chip->ecc.strength;
-
 	/*
 	 * Allocate a large enough buffer for a single huge page plus
 	 * extra space for the spare area and ECC storage area
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/Makefile linux-libre-3.17-rc7-gnu/drivers/mtd/nand/Makefile
--- linux-libre-3.16-gnu/drivers/mtd/nand/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -50,4 +50,4 @@ obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi
 obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
 obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
 
-nand-objs := nand_base.o nand_bbt.o
+nand-objs := nand_base.o nand_bbt.o nand_timings.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/nand_base.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/nand_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -488,6 +488,23 @@ static int nand_check_wp(struct mtd_info
  * nand_block_checkbad - [GENERIC] Check if a block is marked bad
  * @mtd: MTD device structure
  * @ofs: offset from device start
+ *
+ * Check if the block is mark as reserved.
+ */
+static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	if (!chip->bbt)
+		return 0;
+	/* Return info from the table */
+	return nand_isreserved_bbt(mtd, ofs);
+}
+
+/**
+ * nand_block_checkbad - [GENERIC] Check if a block is marked bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
  * @getchip: 0, if the chip is already selected
  * @allowbbt: 1, if its allowed to access the bbt area
  *
@@ -4113,6 +4130,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->_unlock = NULL;
 	mtd->_suspend = nand_suspend;
 	mtd->_resume = nand_resume;
+	mtd->_block_isreserved = nand_block_isreserved;
 	mtd->_block_isbad = nand_block_isbad;
 	mtd->_block_markbad = nand_block_markbad;
 	mtd->writebufsize = mtd->writesize;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/nand_bbt.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_bbt.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/nand_bbt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_bbt.c	2014-09-28 17:29:07.000000000 -0400
@@ -1311,6 +1311,20 @@ int nand_default_bbt(struct mtd_info *mt
 }
 
 /**
+ * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
+ * @mtd: MTD device structure
+ * @offs: offset in the device
+ */
+int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
+{
+	struct nand_chip *this = mtd->priv;
+	int block;
+
+	block = (int)(offs >> this->bbt_erase_shift);
+	return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED;
+}
+
+/**
  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
  * @mtd: MTD device structure
  * @offs: offset in the device
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/nand_timings.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_timings.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/nand_timings.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/nand_timings.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,253 @@
+/*
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@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/kernel.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/mtd/nand.h>
+
+static const struct nand_sdr_timings onfi_sdr_timings[] = {
+	/* Mode 0 */
+	{
+		.tADL_min = 200000,
+		.tALH_min = 20000,
+		.tALS_min = 50000,
+		.tAR_min = 25000,
+		.tCEA_max = 100000,
+		.tCEH_min = 20000,
+		.tCH_min = 20000,
+		.tCHZ_max = 100000,
+		.tCLH_min = 20000,
+		.tCLR_min = 20000,
+		.tCLS_min = 50000,
+		.tCOH_min = 0,
+		.tCS_min = 70000,
+		.tDH_min = 20000,
+		.tDS_min = 40000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 10000,
+		.tITC_max = 1000000,
+		.tRC_min = 100000,
+		.tREA_max = 40000,
+		.tREH_min = 30000,
+		.tRHOH_min = 0,
+		.tRHW_min = 200000,
+		.tRHZ_max = 200000,
+		.tRLOH_min = 0,
+		.tRP_min = 50000,
+		.tRST_max = 250000000000,
+		.tWB_max = 200000,
+		.tRR_min = 40000,
+		.tWC_min = 100000,
+		.tWH_min = 30000,
+		.tWHR_min = 120000,
+		.tWP_min = 50000,
+		.tWW_min = 100000,
+	},
+	/* Mode 1 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 10000,
+		.tALS_min = 25000,
+		.tAR_min = 10000,
+		.tCEA_max = 45000,
+		.tCEH_min = 20000,
+		.tCH_min = 10000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 10000,
+		.tCLR_min = 10000,
+		.tCLS_min = 25000,
+		.tCOH_min = 15000,
+		.tCS_min = 35000,
+		.tDH_min = 10000,
+		.tDS_min = 20000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 50000,
+		.tREA_max = 30000,
+		.tREH_min = 15000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRP_min = 25000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 45000,
+		.tWH_min = 15000,
+		.tWHR_min = 80000,
+		.tWP_min = 25000,
+		.tWW_min = 100000,
+	},
+	/* Mode 2 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 10000,
+		.tALS_min = 15000,
+		.tAR_min = 10000,
+		.tCEA_max = 30000,
+		.tCEH_min = 20000,
+		.tCH_min = 10000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 10000,
+		.tCLR_min = 10000,
+		.tCLS_min = 15000,
+		.tCOH_min = 15000,
+		.tCS_min = 25000,
+		.tDH_min = 5000,
+		.tDS_min = 15000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 35000,
+		.tREA_max = 25000,
+		.tREH_min = 15000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tRP_min = 17000,
+		.tWC_min = 35000,
+		.tWH_min = 15000,
+		.tWHR_min = 80000,
+		.tWP_min = 17000,
+		.tWW_min = 100000,
+	},
+	/* Mode 3 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 25000,
+		.tDH_min = 5000,
+		.tDS_min = 10000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 30000,
+		.tREA_max = 20000,
+		.tREH_min = 10000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRP_min = 15000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 30000,
+		.tWH_min = 10000,
+		.tWHR_min = 80000,
+		.tWP_min = 15000,
+		.tWW_min = 100000,
+	},
+	/* Mode 4 */
+	{
+		.tADL_min = 70000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 30000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 20000,
+		.tDH_min = 5000,
+		.tDS_min = 10000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 25000,
+		.tREA_max = 20000,
+		.tREH_min = 10000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 5000,
+		.tRP_min = 12000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 25000,
+		.tWH_min = 10000,
+		.tWHR_min = 80000,
+		.tWP_min = 12000,
+		.tWW_min = 100000,
+	},
+	/* Mode 5 */
+	{
+		.tADL_min = 70000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 30000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 15000,
+		.tDH_min = 5000,
+		.tDS_min = 7000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 20000,
+		.tREA_max = 16000,
+		.tREH_min = 7000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 5000,
+		.tRP_min = 10000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 20000,
+		.tWH_min = 7000,
+		.tWHR_min = 80000,
+		.tWP_min = 10000,
+		.tWW_min = 100000,
+	},
+};
+
+/**
+ * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
+ * timings according to the given ONFI timing mode
+ * @mode: ONFI timing mode
+ */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
+{
+	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
+		return ERR_PTR(-EINVAL);
+
+	return &onfi_sdr_timings[mode];
+}
+EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/omap2.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/omap2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/omap2.c	2014-09-28 17:29:07.000000000 -0400
@@ -931,7 +931,7 @@ static int omap_calculate_ecc(struct mtd
 	u32 val;
 
 	val = readl(info->reg.gpmc_ecc_config);
-	if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+	if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs)
 		return -EINVAL;
 
 	/* read ecc result */
@@ -1794,9 +1794,12 @@ static int omap_nand_probe(struct platfo
 	}
 
 	/* populate MTD interface based on ECC scheme */
-	nand_chip->ecc.layout	= &omap_oobinfo;
 	ecclayout		= &omap_oobinfo;
 	switch (info->ecc_opt) {
+	case OMAP_ECC_HAM1_CODE_SW:
+		nand_chip->ecc.mode = NAND_ECC_SOFT;
+		break;
+
 	case OMAP_ECC_HAM1_CODE_HW:
 		pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
 		nand_chip->ecc.mode             = NAND_ECC_HW;
@@ -1848,7 +1851,7 @@ static int omap_nand_probe(struct platfo
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
 							nand_chip->ecc.bytes,
-							&nand_chip->ecc.layout);
+							&ecclayout);
 		if (!nand_chip->ecc.priv) {
 			pr_err("nand: error: unable to use s/w BCH library\n");
 			err = -EINVAL;
@@ -1923,7 +1926,7 @@ static int omap_nand_probe(struct platfo
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
 							nand_chip->ecc.bytes,
-							&nand_chip->ecc.layout);
+							&ecclayout);
 		if (!nand_chip->ecc.priv) {
 			pr_err("nand: error: unable to use s/w BCH library\n");
 			err = -EINVAL;
@@ -2012,6 +2015,9 @@ static int omap_nand_probe(struct platfo
 		goto return_error;
 	}
 
+	if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW)
+		goto scan_tail;
+
 	/* all OOB bytes from oobfree->offset till end off OOB are free */
 	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
 	/* check if NAND device's OOB is enough to store ECC signatures */
@@ -2021,7 +2027,9 @@ static int omap_nand_probe(struct platfo
 		err = -EINVAL;
 		goto return_error;
 	}
+	nand_chip->ecc.layout = ecclayout;
 
+scan_tail:
 	/* second phase scan */
 	if (nand_scan_tail(mtd)) {
 		err = -ENXIO;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/nand/s3c2410.c linux-libre-3.17-rc7-gnu/drivers/mtd/nand/s3c2410.c
--- linux-libre-3.16-gnu/drivers/mtd/nand/s3c2410.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/nand/s3c2410.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,10 +208,10 @@ static void s3c2410_nand_clk_set_state(s
 
 	if (info->clk_state == CLOCK_ENABLE) {
 		if (new_state != CLOCK_ENABLE)
-			clk_disable(info->clk);
+			clk_disable_unprepare(info->clk);
 	} else {
 		if (new_state == CLOCK_ENABLE)
-			clk_enable(info->clk);
+			clk_prepare_enable(info->clk);
 	}
 
 	info->clk_state = new_state;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/onenand/Kconfig linux-libre-3.17-rc7-gnu/drivers/mtd/onenand/Kconfig
--- linux-libre-3.16-gnu/drivers/mtd/onenand/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/onenand/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,10 @@ config MTD_ONENAND_OMAP2
 
 config MTD_ONENAND_SAMSUNG
         tristate "OneNAND on Samsung SOC controller support"
-        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4
+        depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4
         help
           Support for a OneNAND flash device connected to an Samsung SOC.
-          S3C64XX/S5PC100 use command mapping method.
+          S3C64XX uses command mapping method.
           S5PC110/S5PC210 use generic OneNAND method.
 
 config MTD_ONENAND_OTP
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/onenand/samsung.c linux-libre-3.17-rc7-gnu/drivers/mtd/onenand/samsung.c
--- linux-libre-3.16-gnu/drivers/mtd/onenand/samsung.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/onenand/samsung.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Implementation:
- *	S3C64XX and S5PC100: emulate the pseudo BufferRAM
+ *	S3C64XX: emulate the pseudo BufferRAM
  *	S5PC110: use DMA
  */
 
@@ -32,7 +32,6 @@
 enum soc_type {
 	TYPE_S3C6400,
 	TYPE_S3C6410,
-	TYPE_S5PC100,
 	TYPE_S5PC110,
 };
 
@@ -59,7 +58,6 @@ enum soc_type {
 #define MAP_11				(0x3)
 
 #define S3C64XX_CMD_MAP_SHIFT		24
-#define S5PC100_CMD_MAP_SHIFT		26
 
 #define S3C6400_FBA_SHIFT		10
 #define S3C6400_FPA_SHIFT		4
@@ -69,10 +67,6 @@ enum soc_type {
 #define S3C6410_FPA_SHIFT		6
 #define S3C6410_FSA_SHIFT		4
 
-#define S5PC100_FBA_SHIFT		13
-#define S5PC100_FPA_SHIFT		7
-#define S5PC100_FSA_SHIFT		5
-
 /* S5PC110 specific definitions */
 #define S5PC110_DMA_SRC_ADDR		0x400
 #define S5PC110_DMA_SRC_CFG		0x404
@@ -195,11 +189,6 @@ static unsigned int s3c64xx_cmd_map(unsi
 	return (type << S3C64XX_CMD_MAP_SHIFT) | val;
 }
 
-static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val)
-{
-	return (type << S5PC100_CMD_MAP_SHIFT) | val;
-}
-
 static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
 {
 	return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
@@ -212,12 +201,6 @@ static unsigned int s3c6410_mem_addr(int
 		(fsa << S3C6410_FSA_SHIFT);
 }
 
-static unsigned int s5pc100_mem_addr(int fba, int fpa, int fsa)
-{
-	return (fba << S5PC100_FBA_SHIFT) | (fpa << S5PC100_FPA_SHIFT) |
-		(fsa << S5PC100_FSA_SHIFT);
-}
-
 static void s3c_onenand_reset(void)
 {
 	unsigned long timeout = 0x10000;
@@ -835,9 +818,6 @@ static void s3c_onenand_setup(struct mtd
 	} else if (onenand->type == TYPE_S3C6410) {
 		onenand->mem_addr = s3c6410_mem_addr;
 		onenand->cmd_map = s3c64xx_cmd_map;
-	} else if (onenand->type == TYPE_S5PC100) {
-		onenand->mem_addr = s5pc100_mem_addr;
-		onenand->cmd_map = s5pc1xx_cmd_map;
 	} else if (onenand->type == TYPE_S5PC110) {
 		/* Use generic onenand functions */
 		this->read_bufferram = s5pc110_read_bufferram;
@@ -1111,9 +1091,6 @@ static struct platform_device_id s3c_one
 		.name		= "s3c6410-onenand",
 		.driver_data	= TYPE_S3C6410,
 	}, {
-		.name		= "s5pc100-onenand",
-		.driver_data	= TYPE_S5PC100,
-	}, {
 		.name		= "s5pc110-onenand",
 		.driver_data	= TYPE_S5PC110,
 	}, { },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/spi-nor/spi-nor.c linux-libre-3.17-rc7-gnu/drivers/mtd/spi-nor/spi-nor.c
--- linux-libre-3.16-gnu/drivers/mtd/spi-nor/spi-nor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/spi-nor/spi-nor.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,25 @@ static int read_sr(struct spi_nor *nor)
 }
 
 /*
+ * Read the flag status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_fsr(struct spi_nor *nor)
+{
+	int ret;
+	u8 val;
+
+	ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
+	if (ret < 0) {
+		pr_err("error %d reading FSR\n", ret);
+		return ret;
+	}
+
+	return val;
+}
+
+/*
  * Read configuration register, returning its value in the
  * location. Return the configuration register value.
  * Returns negative if error occured.
@@ -165,6 +184,32 @@ static int spi_nor_wait_till_ready(struc
 	return -ETIMEDOUT;
 }
 
+static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor)
+{
+	unsigned long deadline;
+	int sr;
+	int fsr;
+
+	deadline = jiffies + MAX_READY_WAIT_JIFFIES;
+
+	do {
+		cond_resched();
+
+		sr = read_sr(nor);
+		if (sr < 0) {
+			break;
+		} else if (!(sr & SR_WIP)) {
+			fsr = read_fsr(nor);
+			if (fsr < 0)
+				break;
+			if (fsr & FSR_READY)
+				return 0;
+		}
+	} while (!time_after_eq(jiffies, deadline));
+
+	return -ETIMEDOUT;
+}
+
 /*
  * Service routine to read status register until ready, or timeout occurs.
  * Returns non-zero if error.
@@ -402,6 +447,7 @@ struct flash_info {
 #define	SECT_4K_PMC		0x10	/* SPINOR_OP_BE_4K_PMC works uniformly */
 #define	SPI_NOR_DUAL_READ	0x20    /* Flash supports Dual Read */
 #define	SPI_NOR_QUAD_READ	0x40    /* Flash supports Quad Read */
+#define	USE_FSR			0x80	/* use flag status register */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
@@ -449,6 +495,7 @@ const struct spi_device_id spi_nor_ids[]
 	{ "en25q32b",   INFO(0x1c3016, 0, 64 * 1024,   64, 0) },
 	{ "en25p64",    INFO(0x1c2017, 0, 64 * 1024,  128, 0) },
 	{ "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, SECT_4K) },
+	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
 	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
 
 	/* ESMT */
@@ -488,6 +535,8 @@ const struct spi_device_id spi_nor_ids[]
 	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, 0) },
 	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K) },
 	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) },
 
 	/* PMC */
 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
@@ -965,6 +1014,10 @@ int spi_nor_scan(struct spi_nor *nor, co
 	else
 		mtd->_write = spi_nor_write;
 
+	if ((info->flags & USE_FSR) &&
+	    nor->wait_till_ready == spi_nor_wait_till_ready)
+		nor->wait_till_ready = spi_nor_wait_till_fsr_ready;
+
 	/* prefer "small sector" erase if possible */
 	if (info->flags & SECT_4K) {
 		nor->erase_opcode = SPINOR_OP_BE_4K;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/ubi/block.c linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/block.c
--- linux-libre-3.16-gnu/drivers/mtd/ubi/block.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/block.c	2014-09-28 17:29:07.000000000 -0400
@@ -378,9 +378,11 @@ int ubiblock_create(struct ubi_volume_in
 {
 	struct ubiblock *dev;
 	struct gendisk *gd;
-	int disk_capacity;
+	u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
 	int ret;
 
+	if ((sector_t)disk_capacity != disk_capacity)
+		return -EFBIG;
 	/* Check that the volume isn't already handled */
 	mutex_lock(&devices_mutex);
 	if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
@@ -412,7 +414,6 @@ int ubiblock_create(struct ubi_volume_in
 	gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
 	gd->private_data = dev;
 	sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
-	disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
 	set_capacity(gd, disk_capacity);
 	dev->gd = gd;
 
@@ -498,11 +499,16 @@ int ubiblock_remove(struct ubi_volume_in
 	return 0;
 }
 
-static void ubiblock_resize(struct ubi_volume_info *vi)
+static int ubiblock_resize(struct ubi_volume_info *vi)
 {
 	struct ubiblock *dev;
-	int disk_capacity;
+	u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
 
+	if ((sector_t)disk_capacity != disk_capacity) {
+		ubi_warn("%s: the volume is too big, cannot resize (%d LEBs)",
+			 dev->gd->disk_name, vi->size);
+		return -EFBIG;
+	}
 	/*
 	 * Need to lock the device list until we stop using the device,
 	 * otherwise the device struct might get released in
@@ -512,15 +518,15 @@ static void ubiblock_resize(struct ubi_v
 	dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
 	if (!dev) {
 		mutex_unlock(&devices_mutex);
-		return;
+		return -ENODEV;
 	}
 
 	mutex_lock(&dev->dev_mutex);
-	disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
 	set_capacity(dev->gd, disk_capacity);
 	ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
 	mutex_unlock(&dev->dev_mutex);
 	mutex_unlock(&devices_mutex);
+	return 0;
 }
 
 static int ubiblock_notify(struct notifier_block *nb,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/ubi/vtbl.c linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/vtbl.c
--- linux-libre-3.16-gnu/drivers/mtd/ubi/vtbl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/vtbl.c	2014-09-28 17:29:07.000000000 -0400
@@ -591,7 +591,7 @@ static int init_volumes(struct ubi_devic
 
 		/* Static volumes only */
 		av = ubi_find_av(ai, i);
-		if (!av) {
+		if (!av || !av->leb_count) {
 			/*
 			 * No eraseblocks belonging to this volume found. We
 			 * don't actually know whether this static volume is
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/mtd/ubi/wl.c linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/wl.c
--- linux-libre-3.16-gnu/drivers/mtd/ubi/wl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/mtd/ubi/wl.c	2014-09-28 17:29:07.000000000 -0400
@@ -1718,12 +1718,12 @@ int ubi_wl_flush(struct ubi_device *ubi,
 	       vol_id, lnum, ubi->works_count);
 
 	while (found) {
-		struct ubi_work *wrk;
+		struct ubi_work *wrk, *tmp;
 		found = 0;
 
 		down_read(&ubi->work_sem);
 		spin_lock(&ubi->wl_lock);
-		list_for_each_entry(wrk, &ubi->works, list) {
+		list_for_each_entry_safe(wrk, tmp, &ubi->works, list) {
 			if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
 			    (lnum == UBI_ALL || wrk->lnum == lnum)) {
 				list_del(&wrk->list);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/arcnet/arcnet.c linux-libre-3.17-rc7-gnu/drivers/net/arcnet/arcnet.c
--- linux-libre-3.16-gnu/drivers/net/arcnet/arcnet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/arcnet/arcnet.c	2014-09-28 17:29:07.000000000 -0400
@@ -346,7 +346,8 @@ struct net_device *alloc_arcdev(const ch
 	struct net_device *dev;
 
 	dev = alloc_netdev(sizeof(struct arcnet_local),
-			   name && *name ? name : "arc%d", arcdev_setup);
+			   name && *name ? name : "arc%d", NET_NAME_UNKNOWN,
+			   arcdev_setup);
 	if(dev) {
 		struct arcnet_local *lp = netdev_priv(dev);
 		spin_lock_init(&lp->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/arcnet/com20020_cs.c linux-libre-3.17-rc7-gnu/drivers/net/arcnet/com20020_cs.c
--- linux-libre-3.16-gnu/drivers/net/arcnet/com20020_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/arcnet/com20020_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,20 +112,20 @@ static void com20020_detach(struct pcmci
 
 /*====================================================================*/
 
-typedef struct com20020_dev_t {
+struct com20020_dev {
     struct net_device       *dev;
-} com20020_dev_t;
+};
 
 static int com20020_probe(struct pcmcia_device *p_dev)
 {
-    com20020_dev_t *info;
+    struct com20020_dev *info;
     struct net_device *dev;
     struct arcnet_local *lp;
 
     dev_dbg(&p_dev->dev, "com20020_attach()\n");
 
     /* Create new network device */
-    info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
+    info = kzalloc(sizeof(*info), GFP_KERNEL);
     if (!info)
 	goto fail_alloc_info;
 
@@ -160,7 +160,7 @@ fail_alloc_info:
 
 static void com20020_detach(struct pcmcia_device *link)
 {
-    struct com20020_dev_t *info = link->priv;
+    struct com20020_dev *info = link->priv;
     struct net_device *dev = info->dev;
 
     dev_dbg(&link->dev, "detach...\n");
@@ -199,7 +199,7 @@ static void com20020_detach(struct pcmci
 static int com20020_config(struct pcmcia_device *link)
 {
     struct arcnet_local *lp;
-    com20020_dev_t *info;
+    struct com20020_dev *info;
     struct net_device *dev;
     int i, ret;
     int ioaddr;
@@ -291,7 +291,7 @@ static void com20020_release(struct pcmc
 
 static int com20020_suspend(struct pcmcia_device *link)
 {
-	com20020_dev_t *info = link->priv;
+	struct com20020_dev *info = link->priv;
 	struct net_device *dev = info->dev;
 
 	if (link->open)
@@ -302,7 +302,7 @@ static int com20020_suspend(struct pcmci
 
 static int com20020_resume(struct pcmcia_device *link)
 {
-	com20020_dev_t *info = link->priv;
+	struct com20020_dev *info = link->priv;
 	struct net_device *dev = info->dev;
 
 	if (link->open) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/arcnet/com20020-pci.c linux-libre-3.17-rc7-gnu/drivers/net/arcnet/com20020-pci.c
--- linux-libre-3.16-gnu/drivers/net/arcnet/com20020-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/arcnet/com20020-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -144,7 +144,7 @@ static void com20020pci_remove(struct pc
 	free_netdev(dev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = {
+static const struct pci_device_id com20020pci_id_table[] = {
 	{ 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_3ad.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_3ad.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_3ad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_3ad.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,8 +20,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -301,8 +299,8 @@ static u16 __get_link_speed(struct port
 		}
 	}
 
-	pr_debug("Port %d Received link speed %d update from adapter\n",
-		 port->actor_port_number, speed);
+	netdev_dbg(slave->bond->dev, "Port %d Received link speed %d update from adapter\n",
+		   port->actor_port_number, speed);
 	return speed;
 }
 
@@ -329,14 +327,14 @@ static u8 __get_duplex(struct port *port
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
 			retval = 0x1;
-			pr_debug("Port %d Received status full duplex update from adapter\n",
-				 port->actor_port_number);
+			netdev_dbg(slave->bond->dev, "Port %d Received status full duplex update from adapter\n",
+				   port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
 			retval = 0x0;
-			pr_debug("Port %d Received status NOT full duplex update from adapter\n",
-				 port->actor_port_number);
+			netdev_dbg(slave->bond->dev, "Port %d Received status NOT full duplex update from adapter\n",
+				   port->actor_port_number);
 			break;
 		}
 	}
@@ -1079,9 +1077,8 @@ static void ad_rx_machine(struct lacpdu
 			/* detect loopback situation */
 			if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
 					      &(port->actor_system))) {
-				pr_err("%s: An illegal loopback occurred on adapter (%s)\n"
+				netdev_err(port->slave->bond->dev, "An illegal loopback occurred on adapter (%s)\n"
 				       "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
-				       port->slave->bond->dev->name,
 				       port->slave->dev->name);
 				return;
 			}
@@ -1269,9 +1266,9 @@ static void ad_port_selection_logic(stru
 				port->next_port_in_aggregator = NULL;
 				port->actor_port_aggregator_identifier = 0;
 
-				pr_debug("Port %d left LAG %d\n",
-					 port->actor_port_number,
-					 temp_aggregator->aggregator_identifier);
+				netdev_dbg(bond->dev, "Port %d left LAG %d\n",
+					   port->actor_port_number,
+					   temp_aggregator->aggregator_identifier);
 				/* if the aggregator is empty, clear its
 				 * parameters, and set it ready to be attached
 				 */
@@ -1284,11 +1281,11 @@ static void ad_port_selection_logic(stru
 			/* meaning: the port was related to an aggregator
 			 * but was not on the aggregator port list
 			 */
-			pr_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
-					    port->slave->bond->dev->name,
-					    port->actor_port_number,
-					    port->slave->dev->name,
-					    port->aggregator->aggregator_identifier);
+			net_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
+					     port->slave->bond->dev->name,
+					     port->actor_port_number,
+					     port->slave->dev->name,
+					     port->aggregator->aggregator_identifier);
 		}
 	}
 	/* search on all aggregators for a suitable aggregator for this port */
@@ -1318,9 +1315,9 @@ static void ad_port_selection_logic(stru
 			port->next_port_in_aggregator = aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
 			aggregator->lag_ports = port;
-			pr_debug("Port %d joined LAG %d(existing LAG)\n",
-				 port->actor_port_number,
-				 port->aggregator->aggregator_identifier);
+			netdev_dbg(bond->dev, "Port %d joined LAG %d(existing LAG)\n",
+				   port->actor_port_number,
+				   port->aggregator->aggregator_identifier);
 
 			/* mark this port as selected */
 			port->sm_vars |= AD_PORT_SELECTED;
@@ -1363,12 +1360,11 @@ static void ad_port_selection_logic(stru
 			/* mark this port as selected */
 			port->sm_vars |= AD_PORT_SELECTED;
 
-			pr_debug("Port %d joined LAG %d(new LAG)\n",
-				 port->actor_port_number,
-				 port->aggregator->aggregator_identifier);
+			netdev_dbg(bond->dev, "Port %d joined LAG %d(new LAG)\n",
+				   port->actor_port_number,
+				   port->aggregator->aggregator_identifier);
 		} else {
-			pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n",
-			       port->slave->bond->dev->name,
+			netdev_err(bond->dev, "Port %d (on %s) did not find a suitable aggregator\n",
 			       port->actor_port_number, port->slave->dev->name);
 		}
 	}
@@ -1445,9 +1441,9 @@ static struct aggregator *ad_agg_selecti
 		break;
 
 	default:
-		pr_warn_ratelimited("%s: Impossible agg select mode %d\n",
-				    curr->slave->bond->dev->name,
-				    __get_agg_selection_mode(curr->lag_ports));
+		net_warn_ratelimited("%s: Impossible agg select mode %d\n",
+				     curr->slave->bond->dev->name,
+				     __get_agg_selection_mode(curr->lag_ports));
 		break;
 	}
 
@@ -1539,40 +1535,40 @@ static void ad_agg_selection_logic(struc
 
 	/* if there is new best aggregator, activate it */
 	if (best) {
-		pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-			 best->aggregator_identifier, best->num_of_ports,
-			 best->actor_oper_aggregator_key,
-			 best->partner_oper_aggregator_key,
-			 best->is_individual, best->is_active);
-		pr_debug("best ports %p slave %p %s\n",
-			 best->lag_ports, best->slave,
-			 best->slave ? best->slave->dev->name : "NULL");
+		netdev_dbg(bond->dev, "best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+			   best->aggregator_identifier, best->num_of_ports,
+			   best->actor_oper_aggregator_key,
+			   best->partner_oper_aggregator_key,
+			   best->is_individual, best->is_active);
+		netdev_dbg(bond->dev, "best ports %p slave %p %s\n",
+			   best->lag_ports, best->slave,
+			   best->slave ? best->slave->dev->name : "NULL");
 
 		bond_for_each_slave_rcu(bond, slave, iter) {
 			agg = &(SLAVE_AD_INFO(slave)->aggregator);
 
-			pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-				 agg->aggregator_identifier, agg->num_of_ports,
-				 agg->actor_oper_aggregator_key,
-				 agg->partner_oper_aggregator_key,
-				 agg->is_individual, agg->is_active);
+			netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+				   agg->aggregator_identifier, agg->num_of_ports,
+				   agg->actor_oper_aggregator_key,
+				   agg->partner_oper_aggregator_key,
+				   agg->is_individual, agg->is_active);
 		}
 
 		/* check if any partner replys */
 		if (best->is_individual) {
-			pr_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
-					    best->slave ?
-					    best->slave->bond->dev->name : "NULL");
+			net_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
+					     best->slave ?
+					     best->slave->bond->dev->name : "NULL");
 		}
 
 		best->is_active = 1;
-		pr_debug("LAG %d chosen as the active LAG\n",
-			 best->aggregator_identifier);
-		pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-			 best->aggregator_identifier, best->num_of_ports,
-			 best->actor_oper_aggregator_key,
-			 best->partner_oper_aggregator_key,
-			 best->is_individual, best->is_active);
+		netdev_dbg(bond->dev, "LAG %d chosen as the active LAG\n",
+			   best->aggregator_identifier);
+		netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+			   best->aggregator_identifier, best->num_of_ports,
+			   best->actor_oper_aggregator_key,
+			   best->partner_oper_aggregator_key,
+			   best->is_individual, best->is_active);
 
 		/* disable the ports that were related to the former
 		 * active_aggregator
@@ -1908,13 +1904,13 @@ void bond_3ad_unbind_slave(struct slave
 
 	/* if slave is null, the whole port is not initialized */
 	if (!port->slave) {
-		pr_warn("Warning: %s: Trying to unbind an uninitialized port on %s\n",
-			slave->bond->dev->name, slave->dev->name);
+		netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n",
+			    slave->dev->name);
 		return;
 	}
 
-	pr_debug("Unbinding Link Aggregation Group %d\n",
-		 aggregator->aggregator_identifier);
+	netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n",
+		   aggregator->aggregator_identifier);
 
 	/* Tell the partner that this port is not suitable for aggregation */
 	port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -1949,14 +1945,13 @@ void bond_3ad_unbind_slave(struct slave
 			 * new aggregator
 			 */
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n",
-					 aggregator->aggregator_identifier,
-					 new_aggregator->aggregator_identifier);
+				netdev_dbg(bond->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n",
+					   aggregator->aggregator_identifier,
+					   new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) &&
 				    new_aggregator->is_active) {
-					pr_info("%s: Removing an active aggregator\n",
-						aggregator->slave->bond->dev->name);
+					netdev_info(bond->dev, "Removing an active aggregator\n");
 					 select_new_active_agg = 1;
 				}
 
@@ -1986,8 +1981,7 @@ void bond_3ad_unbind_slave(struct slave
 				if (select_new_active_agg)
 					ad_agg_selection_logic(__get_first_agg(port));
 			} else {
-				pr_warn("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
-					slave->bond->dev->name);
+				netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
 			}
 		} else {
 			/* in case that the only port related to this
@@ -1996,8 +1990,7 @@ void bond_3ad_unbind_slave(struct slave
 			select_new_active_agg = aggregator->is_active;
 			ad_clear_agg(aggregator);
 			if (select_new_active_agg) {
-				pr_info("%s: Removing an active aggregator\n",
-					slave->bond->dev->name);
+				netdev_info(bond->dev, "Removing an active aggregator\n");
 				/* select new active aggregator */
 				temp_aggregator = __get_first_agg(port);
 				if (temp_aggregator)
@@ -2006,7 +1999,7 @@ void bond_3ad_unbind_slave(struct slave
 		}
 	}
 
-	pr_debug("Unbinding port %d\n", port->actor_port_number);
+	netdev_dbg(bond->dev, "Unbinding port %d\n", port->actor_port_number);
 
 	/* find the aggregator that this port is connected to */
 	bond_for_each_slave(bond, slave_iter, iter) {
@@ -2029,8 +2022,7 @@ void bond_3ad_unbind_slave(struct slave
 					select_new_active_agg = temp_aggregator->is_active;
 					ad_clear_agg(temp_aggregator);
 					if (select_new_active_agg) {
-						pr_info("%s: Removing an active aggregator\n",
-							slave->bond->dev->name);
+						netdev_info(bond->dev, "Removing an active aggregator\n");
 						/* select new active aggregator */
 						ad_agg_selection_logic(__get_first_agg(port));
 					}
@@ -2081,8 +2073,8 @@ void bond_3ad_state_machine_handler(stru
 		/* select the active aggregator for the bond */
 		if (port) {
 			if (!port->slave) {
-				pr_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n",
-						    bond->dev->name);
+				net_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n",
+						     bond->dev->name);
 				goto re_arm;
 			}
 
@@ -2096,7 +2088,7 @@ void bond_3ad_state_machine_handler(stru
 	bond_for_each_slave_rcu(bond, slave, iter) {
 		port = &(SLAVE_AD_INFO(slave)->port);
 		if (!port->slave) {
-			pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
+			net_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
 					    bond->dev->name);
 			goto re_arm;
 		}
@@ -2158,16 +2150,16 @@ static int bond_3ad_rx_indication(struct
 		port = &(SLAVE_AD_INFO(slave)->port);
 
 		if (!port->slave) {
-			pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
-					    slave->dev->name, slave->bond->dev->name);
+			net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
+					     slave->dev->name, slave->bond->dev->name);
 			return ret;
 		}
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
 			ret = RX_HANDLER_CONSUMED;
-			pr_debug("Received LACPDU on port %d\n",
-				 port->actor_port_number);
+			netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n",
+				   port->actor_port_number);
 			/* Protect against concurrent state machines */
 			__get_state_machine_lock(port);
 			ad_rx_machine(lacpdu, port);
@@ -2182,20 +2174,20 @@ static int bond_3ad_rx_indication(struct
 
 			switch (((struct bond_marker *)lacpdu)->tlv_type) {
 			case AD_MARKER_INFORMATION_SUBTYPE:
-				pr_debug("Received Marker Information on port %d\n",
-					 port->actor_port_number);
+				netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
+					   port->actor_port_number);
 				ad_marker_info_received((struct bond_marker *)lacpdu, port);
 				break;
 
 			case AD_MARKER_RESPONSE_SUBTYPE:
-				pr_debug("Received Marker Response on port %d\n",
-					 port->actor_port_number);
+				netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
+					   port->actor_port_number);
 				ad_marker_response_received((struct bond_marker *)lacpdu, port);
 				break;
 
 			default:
-				pr_debug("Received an unknown Marker subtype on slot %d\n",
-					 port->actor_port_number);
+				netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
+					   port->actor_port_number);
 			}
 		}
 	}
@@ -2216,8 +2208,8 @@ void bond_3ad_adapter_speed_changed(stru
 
 	/* if slave is null, the whole port is not initialized */
 	if (!port->slave) {
-		pr_warn("Warning: %s: speed changed for uninitialized port on %s\n",
-			slave->bond->dev->name, slave->dev->name);
+		netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n",
+			    slave->dev->name);
 		return;
 	}
 
@@ -2226,7 +2218,7 @@ void bond_3ad_adapter_speed_changed(stru
 	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
 	port->actor_oper_port_key = port->actor_admin_port_key |=
 		(__get_link_speed(port) << 1);
-	pr_debug("Port %d changed speed\n", port->actor_port_number);
+	netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
 	/* there is no need to reselect a new aggregator, just signal the
 	 * state machines to reinitialize
 	 */
@@ -2249,8 +2241,8 @@ void bond_3ad_adapter_duplex_changed(str
 
 	/* if slave is null, the whole port is not initialized */
 	if (!port->slave) {
-		pr_warn("%s: Warning: duplex changed for uninitialized port on %s\n",
-			slave->bond->dev->name, slave->dev->name);
+		netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n",
+			    slave->dev->name);
 		return;
 	}
 
@@ -2259,7 +2251,7 @@ void bond_3ad_adapter_duplex_changed(str
 	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
 	port->actor_oper_port_key = port->actor_admin_port_key |=
 		__get_duplex(port);
-	pr_debug("Port %d changed duplex\n", port->actor_port_number);
+	netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number);
 	/* there is no need to reselect a new aggregator, just signal the
 	 * state machines to reinitialize
 	 */
@@ -2283,8 +2275,8 @@ void bond_3ad_handle_link_change(struct
 
 	/* if slave is null, the whole port is not initialized */
 	if (!port->slave) {
-		pr_warn("Warning: %s: link status changed for uninitialized port on %s\n",
-			slave->bond->dev->name, slave->dev->name);
+		netdev_warn(slave->bond->dev, "link status changed for uninitialized port on %s\n",
+			    slave->dev->name);
 		return;
 	}
 
@@ -2311,9 +2303,9 @@ void bond_3ad_handle_link_change(struct
 		port->actor_oper_port_key = (port->actor_admin_port_key &=
 					     ~AD_SPEED_KEY_BITS);
 	}
-	pr_debug("Port %d changed link status to %s\n",
-		 port->actor_port_number,
-		 link == BOND_LINK_UP ? "UP" : "DOWN");
+	netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
+		   port->actor_port_number,
+		   link == BOND_LINK_UP ? "UP" : "DOWN");
 	/* there is no need to reselect a new aggregator, just signal the
 	 * state machines to reinitialize
 	 */
@@ -2427,8 +2419,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	int agg_id;
 
 	if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
-		pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
-			 dev->name);
+		netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n");
 		goto err_free;
 	}
 
@@ -2436,7 +2427,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	agg_id = ad_info.aggregator_id;
 
 	if (slaves_in_agg == 0) {
-		pr_debug("%s: Error: active aggregator is empty\n", dev->name);
+		netdev_dbg(dev, "active aggregator is empty\n");
 		goto err_free;
 	}
 
@@ -2462,8 +2453,8 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	}
 
 	if (slave_agg_no >= 0) {
-		pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
-		       dev->name, agg_id);
+		netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n",
+			   agg_id);
 		goto err_free;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_alb.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_alb.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_alb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_alb.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -202,6 +200,7 @@ static int tlb_initialize(struct bonding
 static void tlb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct tlb_up_slave *arr;
 
 	_lock_tx_hashtbl_bh(bond);
 
@@ -209,6 +208,10 @@ static void tlb_deinitialize(struct bond
 	bond_info->tx_hashtbl = NULL;
 
 	_unlock_tx_hashtbl_bh(bond);
+
+	arr = rtnl_dereference(bond_info->slave_arr);
+	if (arr)
+		kfree_rcu(arr, rcu);
 }
 
 static long long compute_gap(struct slave *slave)
@@ -369,7 +372,7 @@ static int rlb_arp_recv(const struct sk_
 	if (arp->op_code == htons(ARPOP_REPLY)) {
 		/* update rx hash table for this ARP */
 		rlb_update_entry_from_arp(bond, arp);
-		pr_debug("Server received an ARP Reply from client\n");
+		netdev_dbg(bond->dev, "Server received an ARP Reply from client\n");
 	}
 out:
 	return RX_HANDLER_ANOTHER;
@@ -448,11 +451,13 @@ static struct slave *__rlb_next_rx_slave
  */
 static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
 {
-	if (!bond->curr_active_slave)
+	struct slave *curr_active = bond_deref_active_protected(bond);
+
+	if (!curr_active)
 		return;
 
 	if (!bond->alb_info.primary_is_promisc) {
-		if (!dev_set_promiscuity(bond->curr_active_slave->dev, 1))
+		if (!dev_set_promiscuity(curr_active->dev, 1))
 			bond->alb_info.primary_is_promisc = 1;
 		else
 			bond->alb_info.primary_is_promisc = 0;
@@ -460,7 +465,7 @@ static void rlb_teach_disabled_mac_on_pr
 
 	bond->alb_info.rlb_promisc_timeout_counter = 0;
 
-	alb_send_learning_packets(bond->curr_active_slave, addr, true);
+	alb_send_learning_packets(curr_active, addr, true);
 }
 
 /* slave being removed should not be active at this point
@@ -509,7 +514,7 @@ static void rlb_clear_slave(struct bondi
 
 	write_lock_bh(&bond->curr_slave_lock);
 
-	if (slave != bond->curr_active_slave)
+	if (slave != bond_deref_active_protected(bond))
 		rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
 
 	write_unlock_bh(&bond->curr_slave_lock);
@@ -533,8 +538,8 @@ static void rlb_update_client(struct rlb
 				 client_info->slave->dev->dev_addr,
 				 client_info->mac_dst);
 		if (!skb) {
-			pr_err("%s: Error: failed to create an ARP packet\n",
-			       client_info->slave->bond->dev->name);
+			netdev_err(client_info->slave->bond->dev,
+				   "failed to create an ARP packet\n");
 			continue;
 		}
 
@@ -543,8 +548,8 @@ static void rlb_update_client(struct rlb
 		if (client_info->vlan_id) {
 			skb = vlan_put_tag(skb, htons(ETH_P_8021Q), client_info->vlan_id);
 			if (!skb) {
-				pr_err("%s: Error: failed to insert VLAN tag\n",
-				       client_info->slave->bond->dev->name);
+				netdev_err(client_info->slave->bond->dev,
+					   "failed to insert VLAN tag\n");
 				continue;
 			}
 		}
@@ -628,8 +633,7 @@ static void rlb_req_update_subnet_client
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 		if (!client_info->slave) {
-			pr_err("%s: Error: found a client with no channel in the client's hash table\n",
-			       bond->dev->name);
+			netdev_err(bond->dev, "found a client with no channel in the client's hash table\n");
 			continue;
 		}
 		/*update all clients using this src_ip, that are not assigned
@@ -684,7 +688,7 @@ static struct slave *rlb_choose_channel(
 			 * move the old client to primary (curr_active_slave) so
 			 * that the new client can be assigned to this entry.
 			 */
-			if (bond->curr_active_slave &&
+			if (curr_active_slave &&
 			    client_info->slave != curr_active_slave) {
 				client_info->slave = curr_active_slave;
 				rlb_update_client(client_info);
@@ -765,7 +769,7 @@ static struct slave *rlb_arp_xmit(struct
 		tx_slave = rlb_choose_channel(skb, bond);
 		if (tx_slave)
 			ether_addr_copy(arp->mac_src, tx_slave->dev->dev_addr);
-		pr_debug("Server sent ARP Reply packet\n");
+		netdev_dbg(bond->dev, "Server sent ARP Reply packet\n");
 	} else if (arp->op_code == htons(ARPOP_REQUEST)) {
 		/* Create an entry in the rx_hashtbl for this client as a
 		 * place holder.
@@ -785,7 +789,7 @@ static struct slave *rlb_arp_xmit(struct
 		 * updated with their assigned mac.
 		 */
 		rlb_req_update_subnet_clients(bond, arp->ip_src);
-		pr_debug("Server sent ARP Request packet\n");
+		netdev_dbg(bond->dev, "Server sent ARP Request packet\n");
 	}
 
 	return tx_slave;
@@ -1024,8 +1028,7 @@ static void alb_send_lp_vid(struct slave
 	if (vid) {
 		skb = vlan_put_tag(skb, vlan_proto, vid);
 		if (!skb) {
-			pr_err("%s: Error: failed to insert VLAN tag\n",
-			       slave->bond->dev->name);
+			netdev_err(slave->bond->dev, "failed to insert VLAN tag\n");
 			return;
 		}
 	}
@@ -1039,7 +1042,7 @@ static void alb_send_learning_packets(st
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 	struct net_device *upper;
 	struct list_head *iter;
-	struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
+	struct bond_vlan_tag *tags;
 
 	/* send untagged */
 	alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -1067,10 +1070,12 @@ static void alb_send_learning_packets(st
 		 * when strict_match is turned off.
 		 */
 		if (netif_is_macvlan(upper) && !strict_match) {
-			memset(tags, 0, sizeof(tags));
-			bond_verify_device_path(bond->dev, upper, tags);
+			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);
 		}
 	}
 	rcu_read_unlock();
@@ -1091,9 +1096,8 @@ static int alb_set_slave_mac_addr(struct
 	memcpy(s_addr.sa_data, addr, dev->addr_len);
 	s_addr.sa_family = dev->type;
 	if (dev_set_mac_address(dev, &s_addr)) {
-		pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n"
-		       "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
-		       slave->bond->dev->name, dev->name);
+		netdev_err(slave->bond->dev, "dev_set_mac_address of dev %s failed! ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
+			   dev->name);
 		return -EOPNOTSUPP;
 	}
 	return 0;
@@ -1221,7 +1225,7 @@ static void alb_change_hw_addr_on_detach
  */
 static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *has_bond_addr = bond->curr_active_slave;
+	struct slave *has_bond_addr = rcu_access_pointer(bond->curr_active_slave);
 	struct slave *tmp_slave1, *free_mac_slave = NULL;
 	struct list_head *iter;
 
@@ -1267,13 +1271,12 @@ static int alb_handle_addr_collision_on_
 	if (free_mac_slave) {
 		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
 
-		pr_warn("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
-			bond->dev->name, slave->dev->name,
-			free_mac_slave->dev->name);
+		netdev_warn(bond->dev, "the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
+			    slave->dev->name, free_mac_slave->dev->name);
 
 	} else if (has_bond_addr) {
-		pr_err("%s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
-		       bond->dev->name, slave->dev->name);
+		netdev_err(bond->dev, "the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
+			   slave->dev->name);
 		return -EFAULT;
 	}
 
@@ -1406,9 +1409,39 @@ out:
 	return NETDEV_TX_OK;
 }
 
+static int bond_tlb_update_slave_arr(struct bonding *bond,
+				     struct slave *skipslave)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *tx_slave;
+	struct list_head *iter;
+	struct tlb_up_slave *new_arr, *old_arr;
+
+	new_arr = kzalloc(offsetof(struct tlb_up_slave, arr[bond->slave_cnt]),
+			  GFP_ATOMIC);
+	if (!new_arr)
+		return -ENOMEM;
+
+	bond_for_each_slave(bond, tx_slave, iter) {
+		if (!bond_slave_can_tx(tx_slave))
+			continue;
+		if (skipslave == tx_slave)
+			continue;
+		new_arr->arr[new_arr->count++] = tx_slave;
+	}
+
+	old_arr = rtnl_dereference(bond_info->slave_arr);
+	rcu_assign_pointer(bond_info->slave_arr, new_arr);
+	if (old_arr)
+		kfree_rcu(old_arr, rcu);
+
+	return 0;
+}
+
 int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct ethhdr *eth_data;
 	struct slave *tx_slave = NULL;
 	u32 hash_index;
@@ -1429,12 +1462,12 @@ int bond_tlb_xmit(struct sk_buff *skb, s
 							      hash_index & 0xFF,
 							      skb->len);
 			} else {
-				struct list_head *iter;
-				int idx = hash_index % bond->slave_cnt;
+				struct tlb_up_slave *slaves;
 
-				bond_for_each_slave_rcu(bond, tx_slave, iter)
-					if (--idx < 0)
-						break;
+				slaves = rcu_dereference(bond_info->slave_arr);
+				if (slaves && slaves->count)
+					tx_slave = slaves->arr[hash_index %
+							       slaves->count];
 			}
 			break;
 		}
@@ -1575,7 +1608,7 @@ void bond_alb_monitor(struct work_struct
 			 * use mac of the slave device.
 			 * In RLB mode, we always use strict matches.
 			 */
-			strict_match = (slave != bond->curr_active_slave ||
+			strict_match = (slave != rcu_access_pointer(bond->curr_active_slave) ||
 					bond_info->rlb_enabled);
 			alb_send_learning_packets(slave, slave->dev->dev_addr,
 						  strict_match);
@@ -1593,7 +1626,7 @@ void bond_alb_monitor(struct work_struct
 
 		bond_for_each_slave_rcu(bond, slave, iter) {
 			tlb_clear_slave(bond, slave, 1);
-			if (slave == bond->curr_active_slave) {
+			if (slave == rcu_access_pointer(bond->curr_active_slave)) {
 				SLAVE_TLB_INFO(slave).load =
 					bond_info->unbalanced_load /
 						BOND_TLB_REBALANCE_INTERVAL;
@@ -1625,7 +1658,8 @@ void bond_alb_monitor(struct work_struct
 			 * because a slave was disabled then
 			 * it can now leave promiscuous mode.
 			 */
-			dev_set_promiscuity(bond->curr_active_slave->dev, -1);
+			dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+					    -1);
 			bond_info->primary_is_promisc = 0;
 
 			rtnl_unlock();
@@ -1698,6 +1732,11 @@ void bond_alb_deinit_slave(struct bondin
 		bond->alb_info.rx_slave = NULL;
 		rlb_clear_slave(bond, slave);
 	}
+
+	if (bond_is_nondyn_tlb(bond))
+		if (bond_tlb_update_slave_arr(bond, slave))
+			pr_err("Failed to build slave-array for TLB mode.\n");
+
 }
 
 /* Caller must hold bond lock for read */
@@ -1721,6 +1760,11 @@ void bond_alb_handle_link_change(struct
 			 */
 		}
 	}
+
+	if (bond_is_nondyn_tlb(bond)) {
+		if (bond_tlb_update_slave_arr(bond, NULL))
+			pr_err("Failed to build slave-array for TLB mode.\n");
+	}
 }
 
 /**
@@ -1742,17 +1786,21 @@ void bond_alb_handle_active_change(struc
 	__acquires(&bond->curr_slave_lock)
 {
 	struct slave *swap_slave;
+	struct slave *curr_active;
 
-	if (bond->curr_active_slave == new_slave)
+	curr_active = rcu_dereference_protected(bond->curr_active_slave,
+						!new_slave ||
+						lockdep_is_held(&bond->curr_slave_lock));
+	if (curr_active == new_slave)
 		return;
 
-	if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
-		dev_set_promiscuity(bond->curr_active_slave->dev, -1);
+	if (curr_active && bond->alb_info.primary_is_promisc) {
+		dev_set_promiscuity(curr_active->dev, -1);
 		bond->alb_info.primary_is_promisc = 0;
 		bond->alb_info.rlb_promisc_timeout_counter = 0;
 	}
 
-	swap_slave = bond->curr_active_slave;
+	swap_slave = curr_active;
 	rcu_assign_pointer(bond->curr_active_slave, new_slave);
 
 	if (!new_slave || !bond_has_slaves(bond))
@@ -1818,6 +1866,7 @@ int bond_alb_set_mac_address(struct net_
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct sockaddr *sa = addr;
+	struct slave *curr_active;
 	struct slave *swap_slave;
 	int res;
 
@@ -1834,23 +1883,24 @@ int bond_alb_set_mac_address(struct net_
 	 * Otherwise we'll need to pass the new address to it and handle
 	 * duplications.
 	 */
-	if (!bond->curr_active_slave)
+	curr_active = rtnl_dereference(bond->curr_active_slave);
+	if (!curr_active)
 		return 0;
 
 	swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr);
 
 	if (swap_slave) {
-		alb_swap_mac_addr(swap_slave, bond->curr_active_slave);
-		alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
+		alb_swap_mac_addr(swap_slave, curr_active);
+		alb_fasten_mac_swap(bond, swap_slave, curr_active);
 	} else {
-		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
+		alb_set_slave_mac_addr(curr_active, bond_dev->dev_addr);
 
 		read_lock(&bond->lock);
-		alb_send_learning_packets(bond->curr_active_slave,
+		alb_send_learning_packets(curr_active,
 					  bond_dev->dev_addr, false);
 		if (bond->alb_info.rlb_enabled) {
 			/* inform clients mac address has changed */
-			rlb_req_update_slave_clients(bond, bond->curr_active_slave);
+			rlb_req_update_slave_clients(bond, curr_active);
 		}
 		read_unlock(&bond->lock);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_alb.h linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_alb.h
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_alb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_alb.h	2014-09-28 17:29:07.000000000 -0400
@@ -139,12 +139,20 @@ struct tlb_slave_info {
 			 */
 };
 
+struct tlb_up_slave {
+	unsigned int	count;
+	struct rcu_head rcu;
+	struct slave	*arr[0];
+};
+
 struct alb_bond_info {
 	struct tlb_client_info	*tx_hashtbl; /* Dynamically allocated */
 	spinlock_t		tx_hashtbl_lock;
 	u32			unbalanced_load;
 	int			tx_rebalance_counter;
 	int			lp_counter;
+	/* -------- non-dynamic tlb mode only ---------*/
+	struct tlb_up_slave __rcu *slave_arr;	  /* Up slaves */
 	/* -------- rlb parameters -------- */
 	int rlb_enabled;
 	struct rlb_client_info	*rx_hashtbl;	/* Receive hash table */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_debugfs.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,8 +69,7 @@ void bond_debug_register(struct bonding
 		debugfs_create_dir(bond->dev->name, bonding_debug_root);
 
 	if (!bond->debug_dir) {
-		pr_warn("%s: Warning: failed to register to debugfs\n",
-			bond->dev->name);
+		netdev_warn(bond->dev, "failed to register to debugfs\n");
 		return;
 	}
 
@@ -98,8 +97,7 @@ void bond_debug_reregister(struct bondin
 	if (d) {
 		bond->debug_dir = d;
 	} else {
-		pr_warn("%s: Warning: failed to reregister, so just unregister old one\n",
-			bond->dev->name);
+		netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n");
 		bond_debug_unregister(bond);
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bonding.h linux-libre-3.17-rc7-gnu/drivers/net/bonding/bonding.h
--- linux-libre-3.16-gnu/drivers/net/bonding/bonding.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bonding.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,6 @@
 
 #define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
 
-#define BOND_MAX_VLAN_ENCAP	2
 #define BOND_MAX_ARP_TARGETS	16
 
 #define BOND_DEFAULT_MIIMON	100
@@ -194,8 +193,8 @@ struct slave {
  */
 struct bonding {
 	struct   net_device *dev; /* first - useful for panic debug */
-	struct   slave *curr_active_slave;
-	struct   slave *current_arp_slave;
+	struct   slave __rcu *curr_active_slave;
+	struct   slave __rcu *current_arp_slave;
 	struct   slave *primary_slave;
 	bool     force_primary;
 	s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
@@ -232,6 +231,10 @@ struct bonding {
 #define bond_slave_get_rtnl(dev) \
 	((struct slave *) rtnl_dereference(dev->rx_handler_data))
 
+#define bond_deref_active_protected(bond)				   \
+	rcu_dereference_protected(bond->curr_active_slave,		   \
+				  lockdep_is_held(&bond->curr_slave_lock))
+
 struct bond_vlan_tag {
 	__be16		vlan_proto;
 	unsigned short	vlan_id;
@@ -265,6 +268,12 @@ static inline bool bond_is_lb(const stru
 	       BOND_MODE(bond) == BOND_MODE_ALB;
 }
 
+static inline bool bond_is_nondyn_tlb(const struct bonding *bond)
+{
+	return (BOND_MODE(bond) == BOND_MODE_TLB)  &&
+	       (bond->params.tlb_dynamic_lb == 0);
+}
+
 static inline bool bond_mode_uses_arp(int mode)
 {
 	return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB &&
@@ -514,11 +523,10 @@ unsigned int bond_get_num_tx_queues(void
 int bond_netlink_init(void);
 void bond_netlink_fini(void);
 struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
-struct net_device *bond_option_active_slave_get(struct bonding *bond);
 const char *bond_slave_link_status(s8 link);
-bool bond_verify_device_path(struct net_device *start_dev,
-			     struct net_device *end_dev,
-			     struct bond_vlan_tag *tags);
+struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
+					      struct net_device *end_dev,
+					      int level);
 
 #ifdef CONFIG_PROC_FS
 void bond_create_proc_entry(struct bonding *bond);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_main.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,8 +31,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -177,7 +175,7 @@ MODULE_PARM_DESC(fail_over_mac, "For act
 				"the same MAC; 0 for none (default), "
 				"1 for active, 2 for follow");
 module_param(all_slaves_active, int, 0);
-MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface"
+MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface "
 				     "by setting active flag for all slaves; "
 				     "0 for never (default), 1 for always.");
 module_param(resend_igmp, int, 0);
@@ -498,11 +496,10 @@ static int bond_set_promiscuity(struct b
 	int err = 0;
 
 	if (bond_uses_primary(bond)) {
-		/* write lock already acquired */
-		if (bond->curr_active_slave) {
-			err = dev_set_promiscuity(bond->curr_active_slave->dev,
-						  inc);
-		}
+		struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
+
+		if (curr_active)
+			err = dev_set_promiscuity(curr_active->dev, inc);
 	} else {
 		struct slave *slave;
 
@@ -524,11 +521,10 @@ static int bond_set_allmulti(struct bond
 	int err = 0;
 
 	if (bond_uses_primary(bond)) {
-		/* write lock already acquired */
-		if (bond->curr_active_slave) {
-			err = dev_set_allmulti(bond->curr_active_slave->dev,
-					       inc);
-		}
+		struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
+
+		if (curr_active)
+			err = dev_set_allmulti(curr_active->dev, inc);
 	} else {
 		struct slave *slave;
 
@@ -629,8 +625,8 @@ static void bond_hw_addr_swap(struct bon
 static void bond_set_dev_addr(struct net_device *bond_dev,
 			      struct net_device *slave_dev)
 {
-	pr_debug("bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n",
-		 bond_dev, slave_dev, slave_dev->addr_len);
+	netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n",
+		   bond_dev, slave_dev, slave_dev->addr_len);
 	memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
 	bond_dev->addr_assign_type = NET_ADDR_STOLEN;
 	call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev);
@@ -684,8 +680,8 @@ static void bond_do_fail_over_mac(struct
 
 		rv = dev_set_mac_address(new_active->dev, &saddr);
 		if (rv) {
-			pr_err("%s: Error %d setting MAC of slave %s\n",
-			       bond->dev->name, -rv, new_active->dev->name);
+			netdev_err(bond->dev, "Error %d setting MAC of slave %s\n",
+				   -rv, new_active->dev->name);
 			goto out;
 		}
 
@@ -697,14 +693,14 @@ static void bond_do_fail_over_mac(struct
 
 		rv = dev_set_mac_address(old_active->dev, &saddr);
 		if (rv)
-			pr_err("%s: Error %d setting MAC of slave %s\n",
-			       bond->dev->name, -rv, new_active->dev->name);
+			netdev_err(bond->dev, "Error %d setting MAC of slave %s\n",
+				   -rv, new_active->dev->name);
 out:
 		write_lock_bh(&bond->curr_slave_lock);
 		break;
 	default:
-		pr_err("%s: bond_do_fail_over_mac impossible: bad policy %d\n",
-		       bond->dev->name, bond->params.fail_over_mac);
+		netdev_err(bond->dev, "bond_do_fail_over_mac impossible: bad policy %d\n",
+			   bond->params.fail_over_mac);
 		break;
 	}
 
@@ -713,7 +709,7 @@ out:
 static bool bond_should_change_active(struct bonding *bond)
 {
 	struct slave *prim = bond->primary_slave;
-	struct slave *curr = bond->curr_active_slave;
+	struct slave *curr = bond_deref_active_protected(bond);
 
 	if (!prim || !curr || curr->link != BOND_LINK_UP)
 		return true;
@@ -765,8 +761,8 @@ static bool bond_should_notify_peers(str
 	slave = rcu_dereference(bond->curr_active_slave);
 	rcu_read_unlock();
 
-	pr_debug("bond_should_notify_peers: bond %s slave %s\n",
-		 bond->dev->name, slave ? slave->dev->name : "NULL");
+	netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n",
+		   slave ? slave->dev->name : "NULL");
 
 	if (!slave || !bond->send_peer_notif ||
 	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
@@ -792,7 +788,11 @@ static bool bond_should_notify_peers(str
  */
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 {
-	struct slave *old_active = bond->curr_active_slave;
+	struct slave *old_active;
+
+	old_active = rcu_dereference_protected(bond->curr_active_slave,
+					       !new_active ||
+					       lockdep_is_held(&bond->curr_slave_lock));
 
 	if (old_active == new_active)
 		return;
@@ -802,9 +802,9 @@ void bond_change_active_slave(struct bon
 
 		if (new_active->link == BOND_LINK_BACK) {
 			if (bond_uses_primary(bond)) {
-				pr_info("%s: making interface %s the new active one %d ms earlier\n",
-					bond->dev->name, new_active->dev->name,
-					(bond->params.updelay - new_active->delay) * bond->params.miimon);
+				netdev_info(bond->dev, "making interface %s the new active one %d ms earlier\n",
+					    new_active->dev->name,
+					    (bond->params.updelay - new_active->delay) * bond->params.miimon);
 			}
 
 			new_active->delay = 0;
@@ -817,8 +817,8 @@ void bond_change_active_slave(struct bon
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 		} else {
 			if (bond_uses_primary(bond)) {
-				pr_info("%s: making interface %s the new active one\n",
-					bond->dev->name, new_active->dev->name);
+				netdev_info(bond->dev, "making interface %s the new active one\n",
+					    new_active->dev->name);
 			}
 		}
 	}
@@ -900,18 +900,16 @@ void bond_select_active_slave(struct bon
 	int rv;
 
 	best_slave = bond_find_best_slave(bond);
-	if (best_slave != bond->curr_active_slave) {
+	if (best_slave != bond_deref_active_protected(bond)) {
 		bond_change_active_slave(bond, best_slave);
 		rv = bond_set_carrier(bond);
 		if (!rv)
 			return;
 
 		if (netif_carrier_ok(bond->dev)) {
-			pr_info("%s: first active interface up!\n",
-				bond->dev->name);
+			netdev_info(bond->dev, "first active interface up!\n");
 		} else {
-			pr_info("%s: now running without any active interface!\n",
-				bond->dev->name);
+			netdev_info(bond->dev, "now running without any active interface!\n");
 		}
 	}
 }
@@ -1001,12 +999,6 @@ static netdev_features_t bond_fix_featur
 	netdev_features_t mask;
 	struct slave *slave;
 
-	if (!bond_has_slaves(bond)) {
-		/* Disable adding VLANs to empty bond. But why? --mq */
-		features |= NETIF_F_VLAN_CHALLENGED;
-		return features;
-	}
-
 	mask = features;
 	features &= ~NETIF_F_ONE_FOR_ALL;
 	features |= NETIF_F_ALL_FOR_ALL;
@@ -1214,36 +1206,38 @@ int bond_enslave(struct net_device *bond
 	if (!bond->params.use_carrier &&
 	    slave_dev->ethtool_ops->get_link == NULL &&
 	    slave_ops->ndo_do_ioctl == NULL) {
-		pr_warn("%s: Warning: no link monitoring support for %s\n",
-			bond_dev->name, slave_dev->name);
+		netdev_warn(bond_dev, "no link monitoring support for %s\n",
+			    slave_dev->name);
 	}
 
 	/* already enslaved */
 	if (slave_dev->flags & IFF_SLAVE) {
-		pr_debug("Error: Device was already enslaved\n");
+		netdev_dbg(bond_dev, "Error: Device was already enslaved\n");
 		return -EBUSY;
 	}
 
 	if (bond_dev == slave_dev) {
-		pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name);
+		netdev_err(bond_dev, "cannot enslave bond to itself.\n");
 		return -EPERM;
 	}
 
 	/* vlan challenged mutual exclusion */
 	/* no need to lock since we're protected by rtnl_lock */
 	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
-		pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n",
+			   slave_dev->name);
 		if (vlan_uses_dev(bond_dev)) {
-			pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
-			       bond_dev->name, slave_dev->name, bond_dev->name);
+			netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
+				   slave_dev->name, bond_dev->name);
 			return -EPERM;
 		} else {
-			pr_warn("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
-				bond_dev->name, slave_dev->name,
-				slave_dev->name, bond_dev->name);
+			netdev_warn(bond_dev, "enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
+				    slave_dev->name, slave_dev->name,
+				    bond_dev->name);
 		}
 	} else {
-		pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		netdev_dbg(bond_dev, "%s is !NETIF_F_VLAN_CHALLENGED\n",
+			   slave_dev->name);
 	}
 
 	/*
@@ -1253,8 +1247,8 @@ int bond_enslave(struct net_device *bond
 	 * enslaving it; the old ifenslave will not.
 	 */
 	if ((slave_dev->flags & IFF_UP)) {
-		pr_err("%s is up - this may be due to an out of date ifenslave\n",
-		       slave_dev->name);
+		netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n",
+			   slave_dev->name);
 		res = -EPERM;
 		goto err_undo_flags;
 	}
@@ -1268,16 +1262,14 @@ int bond_enslave(struct net_device *bond
 	 */
 	if (!bond_has_slaves(bond)) {
 		if (bond_dev->type != slave_dev->type) {
-			pr_debug("%s: change device type from %d to %d\n",
-				 bond_dev->name,
-				 bond_dev->type, slave_dev->type);
+			netdev_dbg(bond_dev, "change device type from %d to %d\n",
+				   bond_dev->type, slave_dev->type);
 
 			res = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE,
 						       bond_dev);
 			res = notifier_to_errno(res);
 			if (res) {
-				pr_err("%s: refused to change device type\n",
-				       bond_dev->name);
+				netdev_err(bond_dev, "refused to change device type\n");
 				res = -EBUSY;
 				goto err_undo_flags;
 			}
@@ -1297,26 +1289,24 @@ int bond_enslave(struct net_device *bond
 						 bond_dev);
 		}
 	} else if (bond_dev->type != slave_dev->type) {
-		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
-		       slave_dev->name, slave_dev->type, bond_dev->type);
+		netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
+			   slave_dev->name, slave_dev->type, bond_dev->type);
 		res = -EINVAL;
 		goto err_undo_flags;
 	}
 
 	if (slave_ops->ndo_set_mac_address == NULL) {
-		if (!bond_has_slaves(bond)) {
-			pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n",
-				bond_dev->name);
-			if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) {
+		netdev_warn(bond_dev, "The slave device specified does not support setting the MAC address\n");
+		if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP &&
+		    bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
+			if (!bond_has_slaves(bond)) {
 				bond->params.fail_over_mac = BOND_FOM_ACTIVE;
-				pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n",
-					bond_dev->name);
+				netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n");
+			} else {
+				netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n");
+				res = -EOPNOTSUPP;
+				goto err_undo_flags;
 			}
-		} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
-			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n",
-			       bond_dev->name);
-			res = -EOPNOTSUPP;
-			goto err_undo_flags;
 		}
 	}
 
@@ -1346,7 +1336,7 @@ int bond_enslave(struct net_device *bond
 	new_slave->original_mtu = slave_dev->mtu;
 	res = dev_set_mtu(slave_dev, bond->dev->mtu);
 	if (res) {
-		pr_debug("Error %d calling dev_set_mtu\n", res);
+		netdev_dbg(bond_dev, "Error %d calling dev_set_mtu\n", res);
 		goto err_free;
 	}
 
@@ -1367,7 +1357,7 @@ int bond_enslave(struct net_device *bond
 		addr.sa_family = slave_dev->type;
 		res = dev_set_mac_address(slave_dev, &addr);
 		if (res) {
-			pr_debug("Error %d calling set_mac_address\n", res);
+			netdev_dbg(bond_dev, "Error %d calling set_mac_address\n", res);
 			goto err_restore_mtu;
 		}
 	}
@@ -1375,7 +1365,7 @@ int bond_enslave(struct net_device *bond
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
-		pr_debug("Opening slave %s failed\n", slave_dev->name);
+		netdev_dbg(bond_dev, "Opening slave %s failed\n", slave_dev->name);
 		goto err_restore_mac;
 	}
 
@@ -1425,8 +1415,8 @@ int bond_enslave(struct net_device *bond
 
 	res = vlan_vids_add_by_dev(slave_dev, bond_dev);
 	if (res) {
-		pr_err("%s: Error: Couldn't add bond vlan ids to %s\n",
-		       bond_dev->name, slave_dev->name);
+		netdev_err(bond_dev, "Couldn't add bond vlan ids to %s\n",
+			   slave_dev->name);
 		goto err_close;
 	}
 
@@ -1455,12 +1445,12 @@ int bond_enslave(struct net_device *bond
 			 * supported); thus, we don't need to change
 			 * the messages for netif_carrier.
 			 */
-			pr_warn("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
-				bond_dev->name, slave_dev->name);
+			netdev_warn(bond_dev, "MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
+				    slave_dev->name);
 		} else if (link_reporting == -1) {
 			/* unable get link status using mii/ethtool */
-			pr_warn("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
-				bond_dev->name, slave_dev->name);
+			netdev_warn(bond_dev, "can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
+				    slave_dev->name);
 		}
 	}
 
@@ -1485,9 +1475,9 @@ int bond_enslave(struct net_device *bond
 
 	if (new_slave->link != BOND_LINK_DOWN)
 		new_slave->last_link_up = jiffies;
-	pr_debug("Initial state of slave_dev is BOND_LINK_%s\n",
-		 new_slave->link == BOND_LINK_DOWN ? "DOWN" :
-		 (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
+	netdev_dbg(bond_dev, "Initial state of slave_dev is BOND_LINK_%s\n",
+		   new_slave->link == BOND_LINK_DOWN ? "DOWN" :
+		   (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
 
 	if (bond_uses_primary(bond) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
@@ -1528,7 +1518,7 @@ int bond_enslave(struct net_device *bond
 		bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
 		break;
 	default:
-		pr_debug("This slave is always active in trunk mode\n");
+		netdev_dbg(bond_dev, "This slave is always active in trunk mode\n");
 
 		/* always active in trunk mode */
 		bond_set_active_slave(new_slave);
@@ -1537,7 +1527,8 @@ int bond_enslave(struct net_device *bond
 		 * anyway (it holds no special properties of the bond device),
 		 * so we can change it without calling change_active_interface()
 		 */
-		if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
+		if (!rcu_access_pointer(bond->curr_active_slave) &&
+		    new_slave->link == BOND_LINK_UP)
 			rcu_assign_pointer(bond->curr_active_slave, new_slave);
 
 		break;
@@ -1547,8 +1538,7 @@ int bond_enslave(struct net_device *bond
 	slave_dev->npinfo = bond->dev->npinfo;
 	if (slave_dev->npinfo) {
 		if (slave_enable_netpoll(new_slave)) {
-			pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n",
-				bond_dev->name);
+			netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n");
 			res = -EBUSY;
 			goto err_detach;
 		}
@@ -1558,19 +1548,19 @@ int bond_enslave(struct net_device *bond
 	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
 					 new_slave);
 	if (res) {
-		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
+		netdev_dbg(bond_dev, "Error %d calling netdev_rx_handler_register\n", res);
 		goto err_detach;
 	}
 
 	res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
 	if (res) {
-		pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
+		netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res);
 		goto err_unregister;
 	}
 
 	res = bond_sysfs_slave_add(new_slave);
 	if (res) {
-		pr_debug("Error %d calling bond_sysfs_slave_add\n", res);
+		netdev_dbg(bond_dev, "Error %d calling bond_sysfs_slave_add\n", res);
 		goto err_upper_unlink;
 	}
 
@@ -1586,10 +1576,10 @@ int bond_enslave(struct net_device *bond
 		unblock_netpoll_tx();
 	}
 
-	pr_info("%s: Enslaving %s as %s interface with %s link\n",
-		bond_dev->name, slave_dev->name,
-		bond_is_active_slave(new_slave) ? "an active" : "a backup",
-		new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
+	netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
+		    slave_dev->name,
+		    bond_is_active_slave(new_slave) ? "an active" : "a backup",
+		    new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
 
 	/* enslave is successful */
 	return 0;
@@ -1608,7 +1598,7 @@ err_detach:
 	vlan_vids_del_by_dev(slave_dev, bond_dev);
 	if (bond->primary_slave == new_slave)
 		bond->primary_slave = NULL;
-	if (bond->curr_active_slave == new_slave) {
+	if (rcu_access_pointer(bond->curr_active_slave) == new_slave) {
 		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_change_active_slave(bond, NULL);
@@ -1674,8 +1664,8 @@ static int __bond_release_one(struct net
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    !netdev_has_upper_dev(slave_dev, bond_dev)) {
-		pr_err("%s: Error: cannot release %s\n",
-		       bond_dev->name, slave_dev->name);
+		netdev_err(bond_dev, "cannot release %s\n",
+			   slave_dev->name);
 		return -EINVAL;
 	}
 
@@ -1684,8 +1674,8 @@ static int __bond_release_one(struct net
 	slave = bond_get_slave_by_dev(bond, slave_dev);
 	if (!slave) {
 		/* not a slave of this bond */
-		pr_info("%s: %s not enslaved\n",
-			bond_dev->name, slave_dev->name);
+		netdev_info(bond_dev, "%s not enslaved\n",
+			    slave_dev->name);
 		unblock_netpoll_tx();
 		return -EINVAL;
 	}
@@ -1705,23 +1695,21 @@ static int __bond_release_one(struct net
 
 	write_unlock_bh(&bond->lock);
 
-	pr_info("%s: Releasing %s interface %s\n",
-		bond_dev->name,
-		bond_is_active_slave(slave) ? "active" : "backup",
-		slave_dev->name);
+	netdev_info(bond_dev, "Releasing %s interface %s\n",
+		    bond_is_active_slave(slave) ? "active" : "backup",
+		    slave_dev->name);
 
-	oldcurrent = bond->curr_active_slave;
+	oldcurrent = rcu_access_pointer(bond->curr_active_slave);
 
-	bond->current_arp_slave = NULL;
+	RCU_INIT_POINTER(bond->current_arp_slave, NULL);
 
 	if (!all && (!bond->params.fail_over_mac ||
 		     BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) {
 		if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
 		    bond_has_slaves(bond))
-			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
-				bond_dev->name, slave_dev->name,
-				slave->perm_hwaddr,
-				bond_dev->name, slave_dev->name);
+			netdev_warn(bond_dev, "the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
+				    slave_dev->name, slave->perm_hwaddr,
+				    bond_dev->name, slave_dev->name);
 	}
 
 	if (bond->primary_slave == slave)
@@ -1760,13 +1748,6 @@ static int __bond_release_one(struct net
 	if (!bond_has_slaves(bond)) {
 		bond_set_carrier(bond);
 		eth_hw_addr_random(bond_dev);
-
-		if (vlan_uses_dev(bond_dev)) {
-			pr_warn("%s: Warning: clearing HW address of %s while it still has VLANs\n",
-				bond_dev->name, bond_dev->name);
-			pr_warn("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs\n",
-				bond_dev->name);
-		}
 	}
 
 	unblock_netpoll_tx();
@@ -1781,8 +1762,8 @@ static int __bond_release_one(struct net
 	bond_compute_features(bond);
 	if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
 	    (old_features & NETIF_F_VLAN_CHALLENGED))
-		pr_info("%s: last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
-			bond_dev->name, slave_dev->name, bond_dev->name);
+		netdev_info(bond_dev, "last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
+			    slave_dev->name, bond_dev->name);
 
 	/* must do this from outside any spinlocks */
 	vlan_vids_del_by_dev(slave_dev, bond_dev);
@@ -1849,8 +1830,8 @@ static int  bond_release_and_destroy(str
 	ret = bond_release(bond_dev, slave_dev);
 	if (ret == 0 && !bond_has_slaves(bond)) {
 		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
-		pr_info("%s: Destroying bond %s\n",
-			bond_dev->name, bond_dev->name);
+		netdev_info(bond_dev, "Destroying bond %s\n",
+			    bond_dev->name);
 		unregister_netdevice(bond_dev);
 	}
 	return ret;
@@ -1891,7 +1872,7 @@ static int bond_slave_info_query(struct
 
 /*-------------------------------- Monitoring -------------------------------*/
 
-
+/* called with rcu_read_lock() */
 static int bond_miimon_inspect(struct bonding *bond)
 {
 	int link_state, commit = 0;
@@ -1899,7 +1880,7 @@ static int bond_miimon_inspect(struct bo
 	struct slave *slave;
 	bool ignore_updelay;
 
-	ignore_updelay = !bond->curr_active_slave ? true : false;
+	ignore_updelay = !rcu_dereference(bond->curr_active_slave);
 
 	bond_for_each_slave_rcu(bond, slave, iter) {
 		slave->new_link = BOND_LINK_NOCHANGE;
@@ -1914,14 +1895,13 @@ static int bond_miimon_inspect(struct bo
 			slave->link = BOND_LINK_FAIL;
 			slave->delay = bond->params.downdelay;
 			if (slave->delay) {
-				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n",
-					bond->dev->name,
-					(BOND_MODE(bond) ==
-					 BOND_MODE_ACTIVEBACKUP) ?
-					(bond_is_active_slave(slave) ?
-					 "active " : "backup ") : "",
-					slave->dev->name,
-					bond->params.downdelay * bond->params.miimon);
+				netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n",
+					    (BOND_MODE(bond) ==
+					     BOND_MODE_ACTIVEBACKUP) ?
+					     (bond_is_active_slave(slave) ?
+					      "active " : "backup ") : "",
+					    slave->dev->name,
+					    bond->params.downdelay * bond->params.miimon);
 			}
 			/*FALLTHRU*/
 		case BOND_LINK_FAIL:
@@ -1931,11 +1911,10 @@ static int bond_miimon_inspect(struct bo
 				 */
 				slave->link = BOND_LINK_UP;
 				slave->last_link_up = jiffies;
-				pr_info("%s: link status up again after %d ms for interface %s\n",
-					bond->dev->name,
-					(bond->params.downdelay - slave->delay) *
-					bond->params.miimon,
-					slave->dev->name);
+				netdev_info(bond->dev, "link status up again after %d ms for interface %s\n",
+					    (bond->params.downdelay - slave->delay) *
+					    bond->params.miimon,
+					    slave->dev->name);
 				continue;
 			}
 
@@ -1956,21 +1935,20 @@ static int bond_miimon_inspect(struct bo
 			slave->delay = bond->params.updelay;
 
 			if (slave->delay) {
-				pr_info("%s: link status up for interface %s, enabling it in %d ms\n",
-					bond->dev->name, slave->dev->name,
-					ignore_updelay ? 0 :
-					bond->params.updelay *
-					bond->params.miimon);
+				netdev_info(bond->dev, "link status up for interface %s, enabling it in %d ms\n",
+					    slave->dev->name,
+					    ignore_updelay ? 0 :
+					    bond->params.updelay *
+					    bond->params.miimon);
 			}
 			/*FALLTHRU*/
 		case BOND_LINK_BACK:
 			if (!link_state) {
 				slave->link = BOND_LINK_DOWN;
-				pr_info("%s: link status down again after %d ms for interface %s\n",
-					bond->dev->name,
-					(bond->params.updelay - slave->delay) *
-					bond->params.miimon,
-					slave->dev->name);
+				netdev_info(bond->dev, "link status down again after %d ms for interface %s\n",
+					    (bond->params.updelay - slave->delay) *
+					    bond->params.miimon,
+					    slave->dev->name);
 
 				continue;
 			}
@@ -2018,10 +1996,10 @@ static void bond_miimon_commit(struct bo
 				bond_set_backup_slave(slave);
 			}
 
-			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex\n",
-				bond->dev->name, slave->dev->name,
-				slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
-				slave->duplex ? "full" : "half");
+			netdev_info(bond->dev, "link status definitely up for interface %s, %u Mbps %s duplex\n",
+				    slave->dev->name,
+				    slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
+				    slave->duplex ? "full" : "half");
 
 			/* notify ad that the link status has changed */
 			if (BOND_MODE(bond) == BOND_MODE_8023AD)
@@ -2048,8 +2026,8 @@ static void bond_miimon_commit(struct bo
 				bond_set_slave_inactive_flags(slave,
 							      BOND_SLAVE_NOTIFY_NOW);
 
-			pr_info("%s: link status definitely down for interface %s, disabling it\n",
-				bond->dev->name, slave->dev->name);
+			netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n",
+				    slave->dev->name);
 
 			if (BOND_MODE(bond) == BOND_MODE_8023AD)
 				bond_3ad_handle_link_change(slave,
@@ -2059,15 +2037,14 @@ static void bond_miimon_commit(struct bo
 				bond_alb_handle_link_change(bond, slave,
 							    BOND_LINK_DOWN);
 
-			if (slave == bond->curr_active_slave)
+			if (slave == rcu_access_pointer(bond->curr_active_slave))
 				goto do_failover;
 
 			continue;
 
 		default:
-			pr_err("%s: invalid new link %d on slave %s\n",
-			       bond->dev->name, slave->new_link,
-			       slave->dev->name);
+			netdev_err(bond->dev, "invalid new link %d on slave %s\n",
+				   slave->new_link, slave->dev->name);
 			slave->new_link = BOND_LINK_NOCHANGE;
 
 			continue;
@@ -2168,10 +2145,10 @@ static void bond_arp_send(struct net_dev
 			  struct bond_vlan_tag *tags)
 {
 	struct sk_buff *skb;
-	int i;
+	struct bond_vlan_tag *outer_tag = tags;
 
-	pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n",
-		 arp_op, slave_dev->name, &dest_ip, &src_ip);
+	netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n",
+		   arp_op, slave_dev->name, &dest_ip, &src_ip);
 
 	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
 			 NULL, slave_dev->dev_addr, NULL);
@@ -2181,30 +2158,42 @@ static void bond_arp_send(struct net_dev
 		return;
 	}
 
+	if (!tags || tags->vlan_proto == VLAN_N_VID)
+		goto xmit;
+
+	tags++;
+
 	/* Go through all the tags backwards and add them to the packet */
-	for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) {
-		if (!tags[i].vlan_id)
+	while (tags->vlan_proto != VLAN_N_VID) {
+		if (!tags->vlan_id) {
+			tags++;
 			continue;
+		}
 
-		pr_debug("inner tag: proto %X vid %X\n",
-			 ntohs(tags[i].vlan_proto), tags[i].vlan_id);
-		skb = __vlan_put_tag(skb, tags[i].vlan_proto,
-				     tags[i].vlan_id);
+		netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n",
+			   ntohs(outer_tag->vlan_proto), tags->vlan_id);
+		skb = __vlan_put_tag(skb, tags->vlan_proto,
+				     tags->vlan_id);
 		if (!skb) {
 			net_err_ratelimited("failed to insert inner VLAN tag\n");
 			return;
 		}
+
+		tags++;
 	}
 	/* Set the outer tag */
-	if (tags[0].vlan_id) {
-		pr_debug("outer tag: proto %X vid %X\n",
-			 ntohs(tags[0].vlan_proto), tags[0].vlan_id);
-		skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id);
+	if (outer_tag->vlan_id) {
+		netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n",
+			   ntohs(outer_tag->vlan_proto), outer_tag->vlan_id);
+		skb = vlan_put_tag(skb, outer_tag->vlan_proto,
+				   outer_tag->vlan_id);
 		if (!skb) {
 			net_err_ratelimited("failed to insert outer VLAN tag\n");
 			return;
 		}
 	}
+
+xmit:
 	arp_xmit(skb);
 }
 
@@ -2214,46 +2203,50 @@ static void bond_arp_send(struct net_dev
  * When the path is validated, collect any vlan information in the
  * path.
  */
-bool bond_verify_device_path(struct net_device *start_dev,
-			     struct net_device *end_dev,
-			     struct bond_vlan_tag *tags)
+struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
+					      struct net_device *end_dev,
+					      int level)
 {
+	struct bond_vlan_tag *tags;
 	struct net_device *upper;
 	struct list_head  *iter;
-	int  idx;
 
-	if (start_dev == end_dev)
-		return true;
+	if (start_dev == end_dev) {
+		tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC);
+		if (!tags)
+			return ERR_PTR(-ENOMEM);
+		tags[level].vlan_proto = VLAN_N_VID;
+		return tags;
+	}
 
 	netdev_for_each_upper_dev_rcu(start_dev, upper, iter) {
-		if (bond_verify_device_path(upper, end_dev, tags)) {
-			if (is_vlan_dev(upper)) {
-				idx = vlan_get_encap_level(upper);
-				if (idx >= BOND_MAX_VLAN_ENCAP)
-					return false;
-
-				tags[idx].vlan_proto =
-						    vlan_dev_vlan_proto(upper);
-				tags[idx].vlan_id = vlan_dev_vlan_id(upper);
-			}
-			return true;
+		tags = bond_verify_device_path(upper, end_dev, level + 1);
+		if (IS_ERR_OR_NULL(tags)) {
+			if (IS_ERR(tags))
+				return tags;
+			continue;
 		}
+		if (is_vlan_dev(upper)) {
+			tags[level].vlan_proto = vlan_dev_vlan_proto(upper);
+			tags[level].vlan_id = vlan_dev_vlan_id(upper);
+		}
+
+		return tags;
 	}
 
-	return false;
+	return NULL;
 }
 
 static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
 	struct rtable *rt;
-	struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
+	struct bond_vlan_tag *tags;
 	__be32 *targets = bond->params.arp_targets, addr;
 	int i;
-	bool ret;
 
 	for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
-		pr_debug("basa: target %pI4\n", &targets[i]);
-		memset(tags, 0, sizeof(tags));
+		netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]);
+		tags = NULL;
 
 		/* Find out through which dev should the packet go */
 		rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
@@ -2276,16 +2269,15 @@ static void bond_arp_send_all(struct bon
 			goto found;
 
 		rcu_read_lock();
-		ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags);
+		tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0);
 		rcu_read_unlock();
 
-		if (ret)
+		if (!IS_ERR_OR_NULL(tags))
 			goto found;
 
 		/* Not our device - skip */
-		pr_debug("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
-			 bond->dev->name, &targets[i],
-			 rt->dst.dev ? rt->dst.dev->name : "NULL");
+		netdev_dbg(bond->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n",
+			   &targets[i], rt->dst.dev ? rt->dst.dev->name : "NULL");
 
 		ip_rt_put(rt);
 		continue;
@@ -2295,6 +2287,7 @@ found:
 		ip_rt_put(rt);
 		bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
 			      addr, tags);
+		kfree(tags);
 	}
 }
 
@@ -2303,13 +2296,15 @@ static void bond_validate_arp(struct bon
 	int i;
 
 	if (!sip || !bond_has_this_ip(bond, tip)) {
-		pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip);
+		netdev_dbg(bond->dev, "bva: sip %pI4 tip %pI4 not found\n",
+			   &sip, &tip);
 		return;
 	}
 
 	i = bond_get_targets_ip(bond->params.arp_targets, sip);
 	if (i == -1) {
-		pr_debug("bva: sip %pI4 not found in targets\n", &sip);
+		netdev_dbg(bond->dev, "bva: sip %pI4 not found in targets\n",
+			   &sip);
 		return;
 	}
 	slave->last_rx = jiffies;
@@ -2336,8 +2331,8 @@ int bond_arp_rcv(const struct sk_buff *s
 
 	alen = arp_hdr_len(bond->dev);
 
-	pr_debug("bond_arp_rcv: bond %s skb->dev %s\n",
-		 bond->dev->name, skb->dev->name);
+	netdev_dbg(bond->dev, "bond_arp_rcv: skb->dev %s\n",
+		   skb->dev->name);
 
 	if (alen > skb_headlen(skb)) {
 		arp = kmalloc(alen, GFP_ATOMIC);
@@ -2361,10 +2356,10 @@ int bond_arp_rcv(const struct sk_buff *s
 	arp_ptr += 4 + bond->dev->addr_len;
 	memcpy(&tip, arp_ptr, 4);
 
-	pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
-		 bond->dev->name, slave->dev->name, bond_slave_state(slave),
-		 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
-		 &sip, &tip);
+	netdev_dbg(bond->dev, "bond_arp_rcv: %s/%d av %d sv %d sip %pI4 tip %pI4\n",
+		   slave->dev->name, bond_slave_state(slave),
+		     bond->params.arp_validate, slave_do_arp_validate(bond, slave),
+		     &sip, &tip);
 
 	curr_active_slave = rcu_dereference(bond->curr_active_slave);
 
@@ -2429,7 +2424,7 @@ static void bond_loadbalance_arp_mon(str
 
 	rcu_read_lock();
 
-	oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
+	oldcurrent = rcu_dereference(bond->curr_active_slave);
 	/* see if any of the previous devices are up now (i.e. they have
 	 * xmt and rcv traffic). the curr_active_slave does not come into
 	 * the picture unless it is null. also, slave->last_link_up is not
@@ -2454,14 +2449,12 @@ static void bond_loadbalance_arp_mon(str
 				 * is closed.
 				 */
 				if (!oldcurrent) {
-					pr_info("%s: link status definitely up for interface %s\n",
-						bond->dev->name,
-						slave->dev->name);
+					netdev_info(bond->dev, "link status definitely up for interface %s\n",
+						    slave->dev->name);
 					do_failover = 1;
 				} else {
-					pr_info("%s: interface %s is now up\n",
-						bond->dev->name,
-						slave->dev->name);
+					netdev_info(bond->dev, "interface %s is now up\n",
+						    slave->dev->name);
 				}
 			}
 		} else {
@@ -2480,8 +2473,8 @@ static void bond_loadbalance_arp_mon(str
 				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
 
-				pr_info("%s: interface %s is now down\n",
-					bond->dev->name, slave->dev->name);
+				netdev_info(bond->dev, "interface %s is now down\n",
+					    slave->dev->name);
 
 				if (slave == oldcurrent)
 					do_failover = 1;
@@ -2577,7 +2570,7 @@ static int bond_ab_arp_inspect(struct bo
 		 * before being taken out
 		 */
 		if (!bond_is_active_slave(slave) &&
-		    !bond->current_arp_slave &&
+		    !rcu_access_pointer(bond->current_arp_slave) &&
 		    !bond_time_in_interval(bond, last_rx, 3)) {
 			slave->new_link = BOND_LINK_DOWN;
 			commit++;
@@ -2620,21 +2613,24 @@ static void bond_ab_arp_commit(struct bo
 
 		case BOND_LINK_UP:
 			trans_start = dev_trans_start(slave->dev);
-			if (bond->curr_active_slave != slave ||
-			    (!bond->curr_active_slave &&
+			if (rtnl_dereference(bond->curr_active_slave) != slave ||
+			    (!rtnl_dereference(bond->curr_active_slave) &&
 			     bond_time_in_interval(bond, trans_start, 1))) {
+				struct slave *current_arp_slave;
+
+				current_arp_slave = rtnl_dereference(bond->current_arp_slave);
 				slave->link = BOND_LINK_UP;
-				if (bond->current_arp_slave) {
+				if (current_arp_slave) {
 					bond_set_slave_inactive_flags(
-						bond->current_arp_slave,
+						current_arp_slave,
 						BOND_SLAVE_NOTIFY_NOW);
-					bond->current_arp_slave = NULL;
+					RCU_INIT_POINTER(bond->current_arp_slave, NULL);
 				}
 
-				pr_info("%s: link status definitely up for interface %s\n",
-					bond->dev->name, slave->dev->name);
+				netdev_info(bond->dev, "link status definitely up for interface %s\n",
+					    slave->dev->name);
 
-				if (!bond->curr_active_slave ||
+				if (!rtnl_dereference(bond->curr_active_slave) ||
 				    (slave == bond->primary_slave))
 					goto do_failover;
 
@@ -2650,20 +2646,19 @@ static void bond_ab_arp_commit(struct bo
 			bond_set_slave_inactive_flags(slave,
 						      BOND_SLAVE_NOTIFY_NOW);
 
-			pr_info("%s: link status definitely down for interface %s, disabling it\n",
-				bond->dev->name, slave->dev->name);
+			netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n",
+				    slave->dev->name);
 
-			if (slave == bond->curr_active_slave) {
-				bond->current_arp_slave = NULL;
+			if (slave == rtnl_dereference(bond->curr_active_slave)) {
+				RCU_INIT_POINTER(bond->current_arp_slave, NULL);
 				goto do_failover;
 			}
 
 			continue;
 
 		default:
-			pr_err("%s: impossible: new_link %d on slave %s\n",
-			       bond->dev->name, slave->new_link,
-			       slave->dev->name);
+			netdev_err(bond->dev, "impossible: new_link %d on slave %s\n",
+				   slave->new_link, slave->dev->name);
 			continue;
 		}
 
@@ -2694,9 +2689,9 @@ static bool bond_ab_arp_probe(struct bon
 	bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
 
 	if (curr_arp_slave && curr_active_slave)
-		pr_info("PROBE: c_arp %s && cas %s BAD\n",
-			curr_arp_slave->dev->name,
-			curr_active_slave->dev->name);
+		netdev_info(bond->dev, "PROBE: c_arp %s && cas %s BAD\n",
+			    curr_arp_slave->dev->name,
+			    curr_active_slave->dev->name);
 
 	if (curr_active_slave) {
 		bond_arp_send_all(bond, curr_active_slave);
@@ -2737,8 +2732,8 @@ static bool bond_ab_arp_probe(struct bon
 			bond_set_slave_inactive_flags(slave,
 						      BOND_SLAVE_NOTIFY_LATER);
 
-			pr_info("%s: backup interface %s is now down\n",
-				bond->dev->name, slave->dev->name);
+			netdev_info(bond->dev, "backup interface %s is now down\n",
+				    slave->dev->name);
 		}
 		if (slave == curr_arp_slave)
 			found = true;
@@ -2934,9 +2929,8 @@ static int bond_slave_netdev_event(unsig
 			break;
 		}
 
-		pr_info("%s: Primary slave changed to %s, reselecting active slave\n",
-			bond->dev->name,
-			bond->primary_slave ? slave_dev->name : "none");
+		netdev_info(bond->dev, "Primary slave changed to %s, reselecting active slave\n",
+			    bond->primary_slave ? slave_dev->name : "none");
 
 		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
@@ -2971,19 +2965,18 @@ static int bond_netdev_event(struct noti
 {
 	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
 
-	pr_debug("event_dev: %s, event: %lx\n",
-		 event_dev ? event_dev->name : "None", event);
+	netdev_dbg(event_dev, "event: %lx\n", event);
 
 	if (!(event_dev->priv_flags & IFF_BONDING))
 		return NOTIFY_DONE;
 
 	if (event_dev->flags & IFF_MASTER) {
-		pr_debug("IFF_MASTER\n");
+		netdev_dbg(event_dev, "IFF_MASTER\n");
 		return bond_master_netdev_event(event, event_dev);
 	}
 
 	if (event_dev->flags & IFF_SLAVE) {
-		pr_debug("IFF_SLAVE\n");
+		netdev_dbg(event_dev, "IFF_SLAVE\n");
 		return bond_slave_netdev_event(event, event_dev);
 	}
 
@@ -2999,11 +2992,11 @@ static struct notifier_block bond_netdev
 /* L2 hash helper */
 static inline u32 bond_eth_hash(struct sk_buff *skb)
 {
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-
-	if (skb_headlen(skb) >= offsetof(struct ethhdr, h_proto))
-		return data->h_dest[5] ^ data->h_source[5];
+	struct ethhdr *ep, hdr_tmp;
 
+	ep = skb_header_pointer(skb, 0, sizeof(hdr_tmp), &hdr_tmp);
+	if (ep)
+		return ep->h_dest[5] ^ ep->h_source[5] ^ ep->h_proto;
 	return 0;
 }
 
@@ -3110,8 +3103,8 @@ static int bond_open(struct net_device *
 	if (bond_has_slaves(bond)) {
 		read_lock(&bond->curr_slave_lock);
 		bond_for_each_slave(bond, slave, iter) {
-			if (bond_uses_primary(bond)
-				&& (slave != bond->curr_active_slave)) {
+			if (bond_uses_primary(bond) &&
+			    slave != rcu_access_pointer(bond->curr_active_slave)) {
 				bond_set_slave_inactive_flags(slave,
 							      BOND_SLAVE_NOTIFY_NOW);
 			} else {
@@ -3225,7 +3218,7 @@ static int bond_do_ioctl(struct net_devi
 	struct net *net;
 	int res = 0;
 
-	pr_debug("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd);
+	netdev_dbg(bond_dev, "bond_ioctl: cmd=%d\n", cmd);
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
@@ -3295,12 +3288,12 @@ static int bond_do_ioctl(struct net_devi
 
 	slave_dev = __dev_get_by_name(net, ifr->ifr_slave);
 
-	pr_debug("slave_dev=%p:\n", slave_dev);
+	netdev_dbg(bond_dev, "slave_dev=%p:\n", slave_dev);
 
 	if (!slave_dev)
 		return -ENODEV;
 
-	pr_debug("slave_dev->name=%s:\n", slave_dev->name);
+	netdev_dbg(bond_dev, "slave_dev->name=%s:\n", slave_dev->name);
 	switch (cmd) {
 	case BOND_ENSLAVE_OLD:
 	case SIOCBONDENSLAVE:
@@ -3427,8 +3420,7 @@ static int bond_change_mtu(struct net_de
 	struct list_head *iter;
 	int res = 0;
 
-	pr_debug("bond=%p, name=%s, new_mtu=%d\n",
-		 bond, bond_dev ? bond_dev->name : "None", new_mtu);
+	netdev_dbg(bond_dev, "bond=%p, new_mtu=%d\n", bond, new_mtu);
 
 	/* Can't hold bond->lock with bh disabled here since
 	 * some base drivers panic. On the other hand we can't
@@ -3446,8 +3438,8 @@ static int bond_change_mtu(struct net_de
 	 */
 
 	bond_for_each_slave(bond, slave, iter) {
-		pr_debug("s %p c_m %p\n",
-			 slave, slave->dev->netdev_ops->ndo_change_mtu);
+		netdev_dbg(bond_dev, "s %p c_m %p\n",
+			   slave, slave->dev->netdev_ops->ndo_change_mtu);
 
 		res = dev_set_mtu(slave->dev, new_mtu);
 
@@ -3460,7 +3452,8 @@ static int bond_change_mtu(struct net_de
 			 * means changing their mtu from timer context, which
 			 * is probably not a good idea.
 			 */
-			pr_debug("err %d %s\n", res, slave->dev->name);
+			netdev_dbg(bond_dev, "err %d %s\n", res,
+				   slave->dev->name);
 			goto unwind;
 		}
 	}
@@ -3479,8 +3472,8 @@ unwind:
 
 		tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu);
 		if (tmp_res) {
-			pr_debug("unwind err %d dev %s\n",
-				 tmp_res, rollback_slave->dev->name);
+			netdev_dbg(bond_dev, "unwind err %d dev %s\n",
+				   tmp_res, rollback_slave->dev->name);
 		}
 	}
 
@@ -3506,8 +3499,7 @@ static int bond_set_mac_address(struct n
 		return bond_alb_set_mac_address(bond_dev, addr);
 
 
-	pr_debug("bond=%p, name=%s\n",
-		 bond, bond_dev ? bond_dev->name : "None");
+	netdev_dbg(bond_dev, "bond=%p\n", bond);
 
 	/* If fail_over_mac is enabled, do nothing and return success.
 	 * Returning an error causes ifenslave to fail.
@@ -3535,7 +3527,7 @@ static int bond_set_mac_address(struct n
 	 */
 
 	bond_for_each_slave(bond, slave, iter) {
-		pr_debug("slave %p %s\n", slave, slave->dev->name);
+		netdev_dbg(bond_dev, "slave %p %s\n", slave, slave->dev->name);
 		res = dev_set_mac_address(slave->dev, addr);
 		if (res) {
 			/* TODO: consider downing the slave
@@ -3544,7 +3536,7 @@ static int bond_set_mac_address(struct n
 			 * breakage anyway until ARP finish
 			 * updating, so...
 			 */
-			pr_debug("err %d %s\n", res, slave->dev->name);
+			netdev_dbg(bond_dev, "err %d %s\n", res, slave->dev->name);
 			goto unwind;
 		}
 	}
@@ -3566,8 +3558,8 @@ unwind:
 
 		tmp_res = dev_set_mac_address(rollback_slave->dev, &tmp_sa);
 		if (tmp_res) {
-			pr_debug("unwind err %d dev %s\n",
-				 tmp_res, rollback_slave->dev->name);
+			netdev_dbg(bond_dev, "unwind err %d dev %s\n",
+				   tmp_res, rollback_slave->dev->name);
 		}
 	}
 
@@ -3667,8 +3659,14 @@ static int bond_xmit_roundrobin(struct s
 		else
 			bond_xmit_slave_id(bond, skb, 0);
 	} else {
-		slave_id = bond_rr_gen_slave_id(bond);
-		bond_xmit_slave_id(bond, skb, slave_id % bond->slave_cnt);
+		int slave_cnt = ACCESS_ONCE(bond->slave_cnt);
+
+		if (likely(slave_cnt)) {
+			slave_id = bond_rr_gen_slave_id(bond);
+			bond_xmit_slave_id(bond, skb, slave_id % slave_cnt);
+		} else {
+			dev_kfree_skb_any(skb);
+		}
 	}
 
 	return NETDEV_TX_OK;
@@ -3699,8 +3697,13 @@ static int bond_xmit_activebackup(struct
 static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	int slave_cnt = ACCESS_ONCE(bond->slave_cnt);
 
-	bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb) % bond->slave_cnt);
+	if (likely(slave_cnt))
+		bond_xmit_slave_id(bond, skb,
+				   bond_xmit_hash(bond, skb) % slave_cnt);
+	else
+		dev_kfree_skb_any(skb);
 
 	return NETDEV_TX_OK;
 }
@@ -3814,8 +3817,7 @@ static netdev_tx_t __bond_start_xmit(str
 		return bond_tlb_xmit(skb, dev);
 	default:
 		/* Should never happen, mode already checked */
-		pr_err("%s: Error: Unknown bonding mode %d\n",
-		       dev->name, BOND_MODE(bond));
+		netdev_err(dev, "Unknown bonding mode %d\n", BOND_MODE(bond));
 		WARN_ON_ONCE(1);
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
@@ -3956,13 +3958,6 @@ void bond_setup(struct net_device *bond_
 	bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT;
 	bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 
-	/* At first, we block adding VLANs. That's the only way to
-	 * prevent problems that occur when adding VLANs over an
-	 * empty bond. The block will be removed once non-challenged
-	 * slaves are enslaved.
-	 */
-	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
-
 	/* don't acquire bond device's netif_tx_lock when
 	 * transmitting */
 	bond_dev->features |= NETIF_F_LLTX;
@@ -4002,7 +3997,7 @@ static void bond_uninit(struct net_devic
 	/* Release the bonded slaves */
 	bond_for_each_slave(bond, slave, iter)
 		__bond_release_one(bond_dev, slave->dev, true);
-	pr_info("%s: Released all slaves\n", bond_dev->name);
+	netdev_info(bond_dev, "Released all slaves\n");
 
 	list_del(&bond->bond_list);
 
@@ -4391,7 +4386,7 @@ static int bond_init(struct net_device *
 	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
-	pr_debug("Begin bond_init for %s\n", bond_dev->name);
+	netdev_dbg(bond_dev, "Begin bond_init\n");
 
 	/*
 	 * Initialize locks that may be required during
@@ -4440,7 +4435,7 @@ int bond_create(struct net *net, const c
 	rtnl_lock();
 
 	bond_dev = alloc_netdev_mq(sizeof(struct bonding),
-				   name ? name : "bond%d",
+				   name ? name : "bond%d", NET_NAME_UNKNOWN,
 				   bond_setup, tx_queues);
 	if (!bond_dev) {
 		pr_err("%s: eek! can't alloc netdev!\n", name);
@@ -4481,7 +4476,6 @@ static void __net_exit bond_net_exit(str
 	LIST_HEAD(list);
 
 	bond_destroy_sysfs(bn);
-	bond_destroy_proc_dir(bn);
 
 	/* Kill off any bonds created after unregistering bond rtnl ops */
 	rtnl_lock();
@@ -4489,6 +4483,8 @@ static void __net_exit bond_net_exit(str
 		unregister_netdevice_queue(bond->dev, &list);
 	unregister_netdevice_many(&list);
 	rtnl_unlock();
+
+	bond_destroy_proc_dir(bn);
 }
 
 static struct pernet_operations bond_net_ops = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_netlink.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_netlink.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_netlink.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_netlink.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,8 +9,6 @@
  * (at your option) any later version.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
@@ -181,8 +179,7 @@ static int bond_changelink(struct net_de
 		int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
 
 		if (arp_interval && miimon) {
-			pr_err("%s: ARP monitoring cannot be used with MII monitoring\n",
-			       bond->dev->name);
+			netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n");
 			return -EINVAL;
 		}
 
@@ -207,8 +204,7 @@ static int bond_changelink(struct net_de
 			i++;
 		}
 		if (i == 0 && bond->params.arp_interval)
-			pr_warn("%s: Removing last arp target with arp_interval on\n",
-				bond->dev->name);
+			netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
 		if (err)
 			return err;
 	}
@@ -216,8 +212,7 @@ static int bond_changelink(struct net_de
 		int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
 
 		if (arp_validate && miimon) {
-			pr_err("%s: ARP validating cannot be used with MII monitoring\n",
-			       bond->dev->name);
+			netdev_err(bond->dev, "ARP validating cannot be used with MII monitoring\n");
 			return -EINVAL;
 		}
 
@@ -398,20 +393,31 @@ static size_t bond_get_size(const struct
 		0;
 }
 
+static int bond_option_active_slave_get_ifindex(struct bonding *bond)
+{
+	const struct net_device *slave;
+	int ifindex;
+
+	rcu_read_lock();
+	slave = bond_option_active_slave_get_rcu(bond);
+	ifindex = slave ? slave->ifindex : 0;
+	rcu_read_unlock();
+	return ifindex;
+}
+
 static int bond_fill_info(struct sk_buff *skb,
 			  const struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct net_device *slave_dev = bond_option_active_slave_get(bond);
-	struct nlattr *targets;
 	unsigned int packets_per_slave;
-	int i, targets_added;
+	int ifindex, i, targets_added;
+	struct nlattr *targets;
 
 	if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
 		goto nla_put_failure;
 
-	if (slave_dev &&
-	    nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
+	ifindex = bond_option_active_slave_get_ifindex(bond);
+	if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex))
 		goto nla_put_failure;
 
 	if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_options.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_options.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_options.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_options.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,8 +9,6 @@
  * (at your option) any later version.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/errno.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
@@ -544,9 +542,8 @@ static void bond_opt_dep_print(struct bo
 	params = &bond->params;
 	modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode);
 	if (test_bit(params->mode, &opt->unsuppmodes))
-		pr_err("%s: option %s: mode dependency failed, not supported in mode %s(%llu)\n",
-		       bond->dev->name, opt->name,
-		       modeval->string, modeval->value);
+		netdev_err(bond->dev, "option %s: mode dependency failed, not supported in mode %s(%llu)\n",
+			   opt->name, modeval->string, modeval->value);
 }
 
 static void bond_opt_error_interpret(struct bonding *bond,
@@ -564,31 +561,30 @@ static void bond_opt_error_interpret(str
 				p = strchr(val->string, '\n');
 				if (p)
 					*p = '\0';
-				pr_err("%s: option %s: invalid value (%s)\n",
-				       bond->dev->name, opt->name, val->string);
+				netdev_err(bond->dev, "option %s: invalid value (%s)\n",
+					   opt->name, val->string);
 			} else {
-				pr_err("%s: option %s: invalid value (%llu)\n",
-				       bond->dev->name, opt->name, val->value);
+				netdev_err(bond->dev, "option %s: invalid value (%llu)\n",
+					   opt->name, val->value);
 			}
 		}
 		minval = bond_opt_get_flags(opt, BOND_VALFLAG_MIN);
 		maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX);
 		if (!maxval)
 			break;
-		pr_err("%s: option %s: allowed values %llu - %llu\n",
-		       bond->dev->name, opt->name, minval ? minval->value : 0,
-		       maxval->value);
+		netdev_err(bond->dev, "option %s: allowed values %llu - %llu\n",
+			   opt->name, minval ? minval->value : 0, maxval->value);
 		break;
 	case -EACCES:
 		bond_opt_dep_print(bond, opt);
 		break;
 	case -ENOTEMPTY:
-		pr_err("%s: option %s: unable to set because the bond device has slaves\n",
-		       bond->dev->name, opt->name);
+		netdev_err(bond->dev, "option %s: unable to set because the bond device has slaves\n",
+			   opt->name);
 		break;
 	case -EBUSY:
-		pr_err("%s: option %s: unable to set because the bond device is up\n",
-		       bond->dev->name, opt->name);
+		netdev_err(bond->dev, "option %s: unable to set because the bond device is up\n",
+			   opt->name);
 		break;
 	default:
 		break;
@@ -671,17 +667,18 @@ const struct bond_option *bond_opt_get(u
 	return &bond_opts[option];
 }
 
-int bond_option_mode_set(struct bonding *bond, const struct bond_opt_value *newval)
+static int bond_option_mode_set(struct bonding *bond,
+				const struct bond_opt_value *newval)
 {
 	if (!bond_mode_uses_arp(newval->value) && bond->params.arp_interval) {
-		pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
-			bond->dev->name, newval->string);
+		netdev_info(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n",
+			    newval->string);
 		/* disable arp monitoring */
 		bond->params.arp_interval = 0;
 		/* set miimon to default value */
 		bond->params.miimon = BOND_DEFAULT_MIIMON;
-		pr_info("%s: Setting MII monitoring interval to %d\n",
-			bond->dev->name, bond->params.miimon);
+		netdev_info(bond->dev, "Setting MII monitoring interval to %d\n",
+			    bond->params.miimon);
 	}
 
 	/* don't cache arp_validate between modes */
@@ -704,11 +701,6 @@ struct net_device *bond_option_active_sl
 	return __bond_option_active_slave_get(bond, slave);
 }
 
-struct net_device *bond_option_active_slave_get(struct bonding *bond)
-{
-	return __bond_option_active_slave_get(bond, bond->curr_active_slave);
-}
-
 static int bond_option_active_slave_set(struct bonding *bond,
 					const struct bond_opt_value *newval)
 {
@@ -727,14 +719,14 @@ static int bond_option_active_slave_set(
 
 	if (slave_dev) {
 		if (!netif_is_bond_slave(slave_dev)) {
-			pr_err("Device %s is not bonding slave\n",
-			       slave_dev->name);
+			netdev_err(bond->dev, "Device %s is not bonding slave\n",
+				   slave_dev->name);
 			return -EINVAL;
 		}
 
 		if (bond->dev != netdev_master_upper_dev_get(slave_dev)) {
-			pr_err("%s: Device %s is not our slave\n",
-			       bond->dev->name, slave_dev->name);
+			netdev_err(bond->dev, "Device %s is not our slave\n",
+				   slave_dev->name);
 			return -EINVAL;
 		}
 	}
@@ -744,29 +736,29 @@ static int bond_option_active_slave_set(
 
 	/* check to see if we are clearing active */
 	if (!slave_dev) {
-		pr_info("%s: Clearing current active slave\n", bond->dev->name);
+		netdev_info(bond->dev, "Clearing current active slave\n");
 		RCU_INIT_POINTER(bond->curr_active_slave, NULL);
 		bond_select_active_slave(bond);
 	} else {
-		struct slave *old_active = bond->curr_active_slave;
+		struct slave *old_active = bond_deref_active_protected(bond);
 		struct slave *new_active = bond_slave_get_rtnl(slave_dev);
 
 		BUG_ON(!new_active);
 
 		if (new_active == old_active) {
 			/* do nothing */
-			pr_info("%s: %s is already the current active slave\n",
-				bond->dev->name, new_active->dev->name);
+			netdev_info(bond->dev, "%s is already the current active slave\n",
+				    new_active->dev->name);
 		} else {
 			if (old_active && (new_active->link == BOND_LINK_UP) &&
 			    bond_slave_is_up(new_active)) {
-				pr_info("%s: Setting %s as active slave\n",
-					bond->dev->name, new_active->dev->name);
+				netdev_info(bond->dev, "Setting %s as active slave\n",
+					    new_active->dev->name);
 				bond_change_active_slave(bond, new_active);
 			} else {
-				pr_err("%s: Could not set %s as active slave; either %s is down or the link is down\n",
-				       bond->dev->name, new_active->dev->name,
-				       new_active->dev->name);
+				netdev_err(bond->dev, "Could not set %s as active slave; either %s is down or the link is down\n",
+					   new_active->dev->name,
+					   new_active->dev->name);
 				ret = -EINVAL;
 			}
 		}
@@ -785,20 +777,17 @@ static int bond_option_active_slave_set(
 static int bond_option_miimon_set(struct bonding *bond,
 				  const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting MII monitoring interval to %llu\n",
-		bond->dev->name, newval->value);
+	netdev_info(bond->dev, "Setting MII monitoring interval to %llu\n",
+		    newval->value);
 	bond->params.miimon = newval->value;
 	if (bond->params.updelay)
-		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
-			bond->dev->name,
+		netdev_info(bond->dev, "Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
 			bond->params.updelay * bond->params.miimon);
 	if (bond->params.downdelay)
-		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
-			bond->dev->name,
-			bond->params.downdelay * bond->params.miimon);
+		netdev_info(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
+			    bond->params.downdelay * bond->params.miimon);
 	if (newval->value && bond->params.arp_interval) {
-		pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n",
-			bond->dev->name);
+		netdev_info(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n");
 		bond->params.arp_interval = 0;
 		if (bond->params.arp_validate)
 			bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
@@ -830,20 +819,18 @@ static int bond_option_updelay_set(struc
 	int value = newval->value;
 
 	if (!bond->params.miimon) {
-		pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
-		       bond->dev->name);
+		netdev_err(bond->dev, "Unable to set up delay as MII monitoring is disabled\n");
 		return -EPERM;
 	}
 	if ((value % bond->params.miimon) != 0) {
-		pr_warn("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
-			bond->dev->name, value,
-			bond->params.miimon,
-			(value / bond->params.miimon) *
-			bond->params.miimon);
+		netdev_warn(bond->dev, "up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
+			    value, bond->params.miimon,
+			    (value / bond->params.miimon) *
+			    bond->params.miimon);
 	}
 	bond->params.updelay = value / bond->params.miimon;
-	pr_info("%s: Setting up delay to %d\n",
-		bond->dev->name, bond->params.updelay * bond->params.miimon);
+	netdev_info(bond->dev, "Setting up delay to %d\n",
+		    bond->params.updelay * bond->params.miimon);
 
 	return 0;
 }
@@ -854,20 +841,18 @@ static int bond_option_downdelay_set(str
 	int value = newval->value;
 
 	if (!bond->params.miimon) {
-		pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
-		       bond->dev->name);
+		netdev_err(bond->dev, "Unable to set down delay as MII monitoring is disabled\n");
 		return -EPERM;
 	}
 	if ((value % bond->params.miimon) != 0) {
-		pr_warn("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
-			bond->dev->name, value,
-			bond->params.miimon,
-			(value / bond->params.miimon) *
-			bond->params.miimon);
+		netdev_warn(bond->dev, "down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
+			    value, bond->params.miimon,
+			    (value / bond->params.miimon) *
+			    bond->params.miimon);
 	}
 	bond->params.downdelay = value / bond->params.miimon;
-	pr_info("%s: Setting down delay to %d\n",
-		bond->dev->name, bond->params.downdelay * bond->params.miimon);
+	netdev_info(bond->dev, "Setting down delay to %d\n",
+		    bond->params.downdelay * bond->params.miimon);
 
 	return 0;
 }
@@ -875,8 +860,8 @@ static int bond_option_downdelay_set(str
 static int bond_option_use_carrier_set(struct bonding *bond,
 				       const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting use_carrier to %llu\n",
-		bond->dev->name, newval->value);
+	netdev_info(bond->dev, "Setting use_carrier to %llu\n",
+		    newval->value);
 	bond->params.use_carrier = newval->value;
 
 	return 0;
@@ -889,18 +874,16 @@ static int bond_option_use_carrier_set(s
 static int bond_option_arp_interval_set(struct bonding *bond,
 					const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting ARP monitoring interval to %llu\n",
-		bond->dev->name, newval->value);
+	netdev_info(bond->dev, "Setting ARP monitoring interval to %llu\n",
+		    newval->value);
 	bond->params.arp_interval = newval->value;
 	if (newval->value) {
 		if (bond->params.miimon) {
-			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n",
-				bond->dev->name, bond->dev->name);
+			netdev_info(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n");
 			bond->params.miimon = 0;
 		}
 		if (!bond->params.arp_targets[0])
-			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n",
-				bond->dev->name);
+			netdev_info(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n");
 	}
 	if (bond->dev->flags & IFF_UP) {
 		/* If the interface is up, we may need to fire off
@@ -944,24 +927,24 @@ static int _bond_option_arp_ip_target_ad
 	int ind;
 
 	if (!bond_is_ip_target_ok(target)) {
-		pr_err("%s: invalid ARP target %pI4 specified for addition\n",
-		       bond->dev->name, &target);
+		netdev_err(bond->dev, "invalid ARP target %pI4 specified for addition\n",
+			   &target);
 		return -EINVAL;
 	}
 
 	if (bond_get_targets_ip(targets, target) != -1) { /* dup */
-		pr_err("%s: ARP target %pI4 is already present\n",
-		       bond->dev->name, &target);
+		netdev_err(bond->dev, "ARP target %pI4 is already present\n",
+			   &target);
 		return -EINVAL;
 	}
 
 	ind = bond_get_targets_ip(targets, 0); /* first free slot */
 	if (ind == -1) {
-		pr_err("%s: ARP target table is full!\n", bond->dev->name);
+		netdev_err(bond->dev, "ARP target table is full!\n");
 		return -EINVAL;
 	}
 
-	pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target);
+	netdev_info(bond->dev, "Adding ARP target %pI4\n", &target);
 
 	_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
 
@@ -989,23 +972,22 @@ static int bond_option_arp_ip_target_rem
 	int ind, i;
 
 	if (!bond_is_ip_target_ok(target)) {
-		pr_err("%s: invalid ARP target %pI4 specified for removal\n",
-		       bond->dev->name, &target);
+		netdev_err(bond->dev, "invalid ARP target %pI4 specified for removal\n",
+			   &target);
 		return -EINVAL;
 	}
 
 	ind = bond_get_targets_ip(targets, target);
 	if (ind == -1) {
-		pr_err("%s: unable to remove nonexistent ARP target %pI4\n",
-		       bond->dev->name, &target);
+		netdev_err(bond->dev, "unable to remove nonexistent ARP target %pI4\n",
+			   &target);
 		return -EINVAL;
 	}
 
 	if (ind == 0 && !targets[1] && bond->params.arp_interval)
-		pr_warn("%s: Removing last arp target with arp_interval on\n",
-			bond->dev->name);
+		netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
 
-	pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);
+	netdev_info(bond->dev, "Removing ARP target %pI4\n", &target);
 
 	/* not to race with bond_arp_rcv */
 	write_lock_bh(&bond->lock);
@@ -1044,8 +1026,8 @@ static int bond_option_arp_ip_targets_se
 
 	if (newval->string) {
 		if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
-			pr_err("%s: invalid ARP target %pI4 specified\n",
-			       bond->dev->name, &target);
+			netdev_err(bond->dev, "invalid ARP target %pI4 specified\n",
+				   &target);
 			return ret;
 		}
 		if (newval->string[0] == '+')
@@ -1053,8 +1035,7 @@ static int bond_option_arp_ip_targets_se
 		else if (newval->string[0] == '-')
 			ret = bond_option_arp_ip_target_rem(bond, target);
 		else
-			pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n",
-			       bond->dev->name);
+			netdev_err(bond->dev, "no command found in arp_ip_targets file - use +<addr> or -<addr>\n");
 	} else {
 		target = newval->value;
 		ret = bond_option_arp_ip_target_add(bond, target);
@@ -1066,8 +1047,8 @@ static int bond_option_arp_ip_targets_se
 static int bond_option_arp_validate_set(struct bonding *bond,
 					const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting arp_validate to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting arp_validate to %s (%llu)\n",
+		    newval->string, newval->value);
 
 	if (bond->dev->flags & IFF_UP) {
 		if (!newval->value)
@@ -1083,8 +1064,8 @@ static int bond_option_arp_validate_set(
 static int bond_option_arp_all_targets_set(struct bonding *bond,
 					   const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting arp_all_targets to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting arp_all_targets to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.arp_all_targets = newval->value;
 
 	return 0;
@@ -1106,7 +1087,7 @@ static int bond_option_primary_set(struc
 		*p = '\0';
 	/* check to see if we are clearing primary */
 	if (!strlen(primary)) {
-		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
+		netdev_info(bond->dev, "Setting primary slave to None\n");
 		bond->primary_slave = NULL;
 		memset(bond->params.primary, 0, sizeof(bond->params.primary));
 		bond_select_active_slave(bond);
@@ -1115,8 +1096,8 @@ static int bond_option_primary_set(struc
 
 	bond_for_each_slave(bond, slave, iter) {
 		if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) {
-			pr_info("%s: Setting %s as primary slave\n",
-				bond->dev->name, slave->dev->name);
+			netdev_info(bond->dev, "Setting %s as primary slave\n",
+				    slave->dev->name);
 			bond->primary_slave = slave;
 			strcpy(bond->params.primary, slave->dev->name);
 			bond_select_active_slave(bond);
@@ -1125,15 +1106,15 @@ static int bond_option_primary_set(struc
 	}
 
 	if (bond->primary_slave) {
-		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
+		netdev_info(bond->dev, "Setting primary slave to None\n");
 		bond->primary_slave = NULL;
 		bond_select_active_slave(bond);
 	}
 	strncpy(bond->params.primary, primary, IFNAMSIZ);
 	bond->params.primary[IFNAMSIZ - 1] = 0;
 
-	pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n",
-		bond->dev->name, primary, bond->dev->name);
+	netdev_info(bond->dev, "Recording %s as primary, but it has not been enslaved to %s yet\n",
+		    primary, bond->dev->name);
 
 out:
 	write_unlock_bh(&bond->curr_slave_lock);
@@ -1146,8 +1127,8 @@ out:
 static int bond_option_primary_reselect_set(struct bonding *bond,
 					    const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting primary_reselect to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting primary_reselect to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.primary_reselect = newval->value;
 
 	block_netpoll_tx();
@@ -1162,8 +1143,8 @@ static int bond_option_primary_reselect_
 static int bond_option_fail_over_mac_set(struct bonding *bond,
 					 const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting fail_over_mac to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting fail_over_mac to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.fail_over_mac = newval->value;
 
 	return 0;
@@ -1172,8 +1153,8 @@ static int bond_option_fail_over_mac_set
 static int bond_option_xmit_hash_policy_set(struct bonding *bond,
 					    const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting xmit hash policy to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting xmit hash policy to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.xmit_policy = newval->value;
 
 	return 0;
@@ -1182,8 +1163,8 @@ static int bond_option_xmit_hash_policy_
 static int bond_option_resend_igmp_set(struct bonding *bond,
 				       const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting resend_igmp to %llu\n",
-		bond->dev->name, newval->value);
+	netdev_info(bond->dev, "Setting resend_igmp to %llu\n",
+		    newval->value);
 	bond->params.resend_igmp = newval->value;
 
 	return 0;
@@ -1221,8 +1202,8 @@ static int bond_option_all_slaves_active
 static int bond_option_min_links_set(struct bonding *bond,
 				     const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting min links value to %llu\n",
-		bond->dev->name, newval->value);
+	netdev_info(bond->dev, "Setting min links value to %llu\n",
+		    newval->value);
 	bond->params.min_links = newval->value;
 
 	return 0;
@@ -1257,8 +1238,8 @@ static int bond_option_pps_set(struct bo
 static int bond_option_lacp_rate_set(struct bonding *bond,
 				     const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting LACP rate to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting LACP rate to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.lacp_fast = newval->value;
 	bond_3ad_update_lacp_rate(bond);
 
@@ -1268,8 +1249,8 @@ static int bond_option_lacp_rate_set(str
 static int bond_option_ad_select_set(struct bonding *bond,
 				     const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting ad_select to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting ad_select to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.ad_select = newval->value;
 
 	return 0;
@@ -1330,7 +1311,7 @@ out:
 	return ret;
 
 err_no_cmd:
-	pr_info("invalid input for queue_id set for %s\n", bond->dev->name);
+	netdev_info(bond->dev, "invalid input for queue_id set\n");
 	ret = -EPERM;
 	goto out;
 
@@ -1352,20 +1333,20 @@ static int bond_option_slaves_set(struct
 
 	dev = __dev_get_by_name(dev_net(bond->dev), ifname);
 	if (!dev) {
-		pr_info("%s: interface %s does not exist!\n",
-			bond->dev->name, ifname);
+		netdev_info(bond->dev, "interface %s does not exist!\n",
+			    ifname);
 		ret = -ENODEV;
 		goto out;
 	}
 
 	switch (command[0]) {
 	case '+':
-		pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name);
+		netdev_info(bond->dev, "Adding slave %s\n", dev->name);
 		ret = bond_enslave(bond->dev, dev);
 		break;
 
 	case '-':
-		pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name);
+		netdev_info(bond->dev, "Removing slave %s\n", dev->name);
 		ret = bond_release(bond->dev, dev);
 		break;
 
@@ -1377,8 +1358,7 @@ out:
 	return ret;
 
 err_no_cmd:
-	pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n",
-	       bond->dev->name);
+	netdev_err(bond->dev, "no command found in slaves file - use +ifname or -ifname\n");
 	ret = -EPERM;
 	goto out;
 }
@@ -1386,8 +1366,8 @@ err_no_cmd:
 static int bond_option_tlb_dynamic_lb_set(struct bonding *bond,
 					  const struct bond_opt_value *newval)
 {
-	pr_info("%s: Setting dynamic-lb to %s (%llu)\n",
-		bond->dev->name, newval->string, newval->value);
+	netdev_info(bond->dev, "Setting dynamic-lb to %s (%llu)\n",
+		    newval->string, newval->value);
 	bond->params.tlb_dynamic_lb = newval->value;
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_procfs.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_procfs.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_procfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_procfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -252,8 +252,8 @@ void bond_create_proc_entry(struct bondi
 						    S_IRUGO, bn->proc_dir,
 						    &bond_info_fops, bond);
 		if (bond->proc_entry == NULL)
-			pr_warn("Warning: Cannot create /proc/net/%s/%s\n",
-				DRV_NAME, bond_dev->name);
+			netdev_warn(bond_dev, "Cannot create /proc/net/%s/%s\n",
+				    DRV_NAME, bond_dev->name);
 		else
 			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -492,8 +492,9 @@ static ssize_t bonding_show_mii_status(s
 				       char *buf)
 {
 	struct bonding *bond = to_bond(d);
+	bool active = !!rcu_access_pointer(bond->curr_active_slave);
 
-	return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down");
+	return sprintf(buf, "%s\n", active ? "up" : "down");
 }
 static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/bonding/bond_sysfs_slave.c linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_sysfs_slave.c
--- linux-libre-3.16-gnu/drivers/net/bonding/bond_sysfs_slave.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/bonding/bond_sysfs_slave.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,7 @@ int bond_sysfs_slave_add(struct slave *s
 	for (a = slave_attrs; *a; ++a) {
 		err = sysfs_create_file(&slave->kobj, &((*a)->attr));
 		if (err) {
-			kobject_del(&slave->kobj);
+			kobject_put(&slave->kobj);
 			return err;
 		}
 	}
@@ -140,5 +140,5 @@ void bond_sysfs_slave_del(struct slave *
 	for (a = slave_attrs; *a; ++a)
 		sysfs_remove_file(&slave->kobj, &((*a)->attr));
 
-	kobject_del(&slave->kobj);
+	kobject_put(&slave->kobj);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/caif/caif_serial.c linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_serial.c
--- linux-libre-3.16-gnu/drivers/net/caif/caif_serial.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_serial.c	2014-09-28 17:29:07.000000000 -0400
@@ -349,7 +349,8 @@ static int ldisc_open(struct tty_struct
 	result = snprintf(name, sizeof(name), "cf%s", tty->name);
 	if (result >= IFNAMSIZ)
 		return -EINVAL;
-	dev = alloc_netdev(sizeof(*ser), name, caifdev_setup);
+	dev = alloc_netdev(sizeof(*ser), name, NET_NAME_UNKNOWN,
+			   caifdev_setup);
 	if (!dev)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/caif/caif_spi.c linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_spi.c
--- linux-libre-3.16-gnu/drivers/net/caif/caif_spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -730,8 +730,8 @@ int cfspi_spi_probe(struct platform_devi
 	int res;
 	dev = (struct cfspi_dev *)pdev->dev.platform_data;
 
-	ndev = alloc_netdev(sizeof(struct cfspi),
-			"cfspi%d", cfspi_setup);
+	ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
+			    NET_NAME_UNKNOWN, cfspi_setup);
 	if (!dev)
 		return -ENODEV;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/caif/caif_virtio.c linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_virtio.c
--- linux-libre-3.16-gnu/drivers/net/caif/caif_virtio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/caif/caif_virtio.c	2014-09-28 17:29:07.000000000 -0400
@@ -661,7 +661,7 @@ static int cfv_probe(struct virtio_devic
 	int err = -EINVAL;
 
 	netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name,
-			      cfv_netdev_setup);
+			      NET_NAME_UNKNOWN, cfv_netdev_setup);
 	if (!netdev)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/at91_can.c linux-libre-3.17-rc7-gnu/drivers/net/can/at91_can.c
--- linux-libre-3.16-gnu/drivers/net/can/at91_can.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/at91_can.c	2014-09-28 17:29:07.000000000 -0400
@@ -1123,7 +1123,9 @@ static int at91_open(struct net_device *
 	struct at91_priv *priv = netdev_priv(dev);
 	int err;
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
 
 	/* check or determine and set bittime */
 	err = open_candev(dev);
@@ -1149,7 +1151,7 @@ static int at91_open(struct net_device *
  out_close:
 	close_candev(dev);
  out:
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return err;
 }
@@ -1166,7 +1168,7 @@ static int at91_close(struct net_device
 	at91_chip_stop(dev, CAN_STATE_STOPPED);
 
 	free_irq(dev->irq, dev);
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	close_candev(dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/c_can/c_can_pci.c linux-libre-3.17-rc7-gnu/drivers/net/can/c_can/c_can_pci.c
--- linux-libre-3.16-gnu/drivers/net/can/c_can/c_can_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/c_can/c_can_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -270,7 +270,8 @@ static struct c_can_pci_data c_can_pch =
 	PCI_DEVICE(_vend, _dev),			\
 	.driver_data = (unsigned long)&_driverdata,	\
 }
-static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
+
+static const struct pci_device_id c_can_pci_tbl[] = {
 	C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
 		 c_can_sta2x11),
 	C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/c_can/c_can_platform.c linux-libre-3.17-rc7-gnu/drivers/net/can/c_can/c_can_platform.c
--- linux-libre-3.16-gnu/drivers/net/can/c_can/c_can_platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/c_can/c_can_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,14 +97,14 @@ static void c_can_hw_raminit_ti(const st
 	ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
 	writel(ctrl, priv->raminit_ctrlreg);
 	ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
-	c_can_hw_raminit_wait_ti(priv, ctrl, mask);
+	c_can_hw_raminit_wait_ti(priv, mask, ctrl);
 
 	if (enable) {
 		/* Set start bit and wait for the done bit. */
 		ctrl |= CAN_RAMINIT_START_MASK(priv->instance);
 		writel(ctrl, priv->raminit_ctrlreg);
 		ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
-		c_can_hw_raminit_wait_ti(priv, ctrl, mask);
+		c_can_hw_raminit_wait_ti(priv, mask, ctrl);
 	}
 	spin_unlock(&raminit_lock);
 }
@@ -208,40 +208,31 @@ static int c_can_plat_probe(struct platf
 	}
 
 	/* get the appropriate clk */
-	clk = clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "no clock defined\n");
-		ret = -ENODEV;
+		ret = PTR_ERR(clk);
 		goto exit;
 	}
 
 	/* get the platform data */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!mem || irq <= 0) {
-		ret = -ENODEV;
-		goto exit_free_clk;
-	}
-
-	if (!request_mem_region(mem->start, resource_size(mem),
-				KBUILD_MODNAME)) {
-		dev_err(&pdev->dev, "resource unavailable\n");
+	if (irq <= 0) {
 		ret = -ENODEV;
-		goto exit_free_clk;
+		goto exit;
 	}
 
-	addr = ioremap(mem->start, resource_size(mem));
-	if (!addr) {
-		dev_err(&pdev->dev, "failed to map can port\n");
-		ret = -ENOMEM;
-		goto exit_release_mem;
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	addr = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(addr)) {
+		ret =  PTR_ERR(addr);
+		goto exit;
 	}
 
 	/* allocate the c_can device */
 	dev = alloc_c_can_dev();
 	if (!dev) {
 		ret = -ENOMEM;
-		goto exit_iounmap;
+		goto exit;
 	}
 
 	priv = netdev_priv(dev);
@@ -289,7 +280,7 @@ static int c_can_plat_probe(struct platf
 
 		priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start,
 						     resource_size(res));
-		if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
+		if (!priv->raminit_ctrlreg || priv->instance < 0)
 			dev_info(&pdev->dev, "control memory is not used for raminit\n");
 		else
 			priv->raminit = c_can_hw_raminit_ti;
@@ -322,12 +313,6 @@ static int c_can_plat_probe(struct platf
 
 exit_free_device:
 	free_c_can_dev(dev);
-exit_iounmap:
-	iounmap(addr);
-exit_release_mem:
-	release_mem_region(mem->start, resource_size(mem));
-exit_free_clk:
-	clk_put(clk);
 exit:
 	dev_err(&pdev->dev, "probe failed\n");
 
@@ -337,18 +322,10 @@ exit:
 static int c_can_plat_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
-	struct c_can_priv *priv = netdev_priv(dev);
-	struct resource *mem;
 
 	unregister_c_can_dev(dev);
 
 	free_c_can_dev(dev);
-	iounmap(priv->base);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-
-	clk_put(priv->priv);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/dev.c linux-libre-3.17-rc7-gnu/drivers/net/can/dev.c
--- linux-libre-3.16-gnu/drivers/net/can/dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -565,7 +565,7 @@ struct net_device *alloc_candev(int size
 	else
 		size = sizeof_priv;
 
-	dev = alloc_netdev(size, "can%d", can_setup);
+	dev = alloc_netdev(size, "can%d", NET_NAME_UNKNOWN, can_setup);
 	if (!dev)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/flexcan.c linux-libre-3.17-rc7-gnu/drivers/net/can/flexcan.c
--- linux-libre-3.16-gnu/drivers/net/can/flexcan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/flexcan.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,7 @@
 #define FLEXCAN_MCR_BCC			BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
-#define FLEXCAN_MCR_MAXMB(x)		((x) & 0x1f)
+#define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
 #define FLEXCAN_MCR_IDAM_A		(0 << 8)
 #define FLEXCAN_MCR_IDAM_B		(1 << 8)
 #define FLEXCAN_MCR_IDAM_C		(2 << 8)
@@ -125,7 +125,9 @@
 	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
-#define FLEXCAN_TX_BUF_ID		8
+/* Errata ERR005829 step7: Reserve first valid MB */
+#define FLEXCAN_TX_BUF_RESERVED		8
+#define FLEXCAN_TX_BUF_ID		9
 #define FLEXCAN_IFLAG_BUF(x)		BIT(x)
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)
@@ -136,6 +138,17 @@
 
 /* FLEXCAN message buffers */
 #define FLEXCAN_MB_CNT_CODE(x)		(((x) & 0xf) << 24)
+#define FLEXCAN_MB_CODE_RX_INACTIVE	(0x0 << 24)
+#define FLEXCAN_MB_CODE_RX_EMPTY	(0x4 << 24)
+#define FLEXCAN_MB_CODE_RX_FULL		(0x2 << 24)
+#define FLEXCAN_MB_CODE_RX_OVERRRUN	(0x6 << 24)
+#define FLEXCAN_MB_CODE_RX_RANSWER	(0xa << 24)
+
+#define FLEXCAN_MB_CODE_TX_INACTIVE	(0x8 << 24)
+#define FLEXCAN_MB_CODE_TX_ABORT	(0x9 << 24)
+#define FLEXCAN_MB_CODE_TX_DATA		(0xc << 24)
+#define FLEXCAN_MB_CODE_TX_TANSWER	(0xe << 24)
+
 #define FLEXCAN_MB_CNT_SRR		BIT(22)
 #define FLEXCAN_MB_CNT_IDE		BIT(21)
 #define FLEXCAN_MB_CNT_RTR		BIT(20)
@@ -298,7 +311,7 @@ static int flexcan_chip_enable(struct fl
 	flexcan_write(reg, &regs->mcr);
 
 	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-		usleep_range(10, 20);
+		udelay(10);
 
 	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
 		return -ETIMEDOUT;
@@ -317,7 +330,7 @@ static int flexcan_chip_disable(struct f
 	flexcan_write(reg, &regs->mcr);
 
 	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-		usleep_range(10, 20);
+		udelay(10);
 
 	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
 		return -ETIMEDOUT;
@@ -336,7 +349,7 @@ static int flexcan_chip_freeze(struct fl
 	flexcan_write(reg, &regs->mcr);
 
 	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-		usleep_range(100, 200);
+		udelay(100);
 
 	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
 		return -ETIMEDOUT;
@@ -355,7 +368,7 @@ static int flexcan_chip_unfreeze(struct
 	flexcan_write(reg, &regs->mcr);
 
 	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-		usleep_range(10, 20);
+		udelay(10);
 
 	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
 		return -ETIMEDOUT;
@@ -370,7 +383,7 @@ static int flexcan_chip_softreset(struct
 
 	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
 	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
-		usleep_range(10, 20);
+		udelay(10);
 
 	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
 		return -ETIMEDOUT;
@@ -428,6 +441,14 @@ static int flexcan_start_xmit(struct sk_
 	flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
 	flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 
+	/* Errata ERR005829 step8:
+	 * Write twice INACTIVE(0x8) code to first MB.
+	 */
+	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+
 	return NETDEV_TX_OK;
 }
 
@@ -549,6 +570,13 @@ static void do_state(struct net_device *
 
 	/* process state changes depending on the new state */
 	switch (new_state) {
+	case CAN_STATE_ERROR_WARNING:
+		netdev_dbg(dev, "Error Warning\n");
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = (bec.txerr > bec.rxerr) ?
+			CAN_ERR_CRTL_TX_WARNING :
+			CAN_ERR_CRTL_RX_WARNING;
+		break;
 	case CAN_STATE_ERROR_ACTIVE:
 		netdev_dbg(dev, "Error Active\n");
 		cf->can_id |= CAN_ERR_PROT;
@@ -737,6 +765,9 @@ static irqreturn_t flexcan_irq(int irq,
 		stats->tx_bytes += can_get_echo_skb(dev, 0);
 		stats->tx_packets++;
 		can_led_event(dev, CAN_LED_EVENT_TX);
+		/* after sending a RTR frame mailbox is in RX mode */
+		flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+			      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 		flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
 		netif_wake_queue(dev);
 	}
@@ -794,6 +825,7 @@ static int flexcan_chip_start(struct net
 	struct flexcan_regs __iomem *regs = priv->base;
 	int err;
 	u32 reg_mcr, reg_ctrl;
+	int i;
 
 	/* enable module */
 	err = flexcan_chip_enable(priv);
@@ -852,14 +884,26 @@ static int flexcan_chip_start(struct net
 	if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
 	    priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
 		reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
+	else
+		reg_ctrl &= ~FLEXCAN_CTRL_ERR_MSK;
 
 	/* save for later use */
 	priv->reg_ctrl_default = reg_ctrl;
 	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
-	/* Abort any pending TX, mark Mailbox as INACTIVE */
-	flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+	/* clear and invalidate all mailboxes first */
+	for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) {
+		flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
+			      &regs->cantxfg[i].can_ctrl);
+	}
+
+	/* Errata ERR005829: mark first TX mailbox as INACTIVE */
+	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
+		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+
+	/* mark TX mailbox as INACTIVE */
+	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
 		      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 
 	/* acceptance mask/acceptance code (accept everything) */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/pch_can.c linux-libre-3.17-rc7-gnu/drivers/net/can/pch_can.c
--- linux-libre-3.16-gnu/drivers/net/can/pch_can.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/pch_can.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,7 +194,7 @@ static const struct can_bittiming_const
 	.brp_inc = 1,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = {
+static const struct pci_device_id pch_pci_tbl[] = {
 	{PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,}
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/sja1000/ems_pci.c linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/ems_pci.c
--- linux-libre-3.16-gnu/drivers/net/can/sja1000/ems_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/ems_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ struct ems_pci_card {
 
 #define EMS_PCI_BASE_SIZE  4096 /* size of controller area */
 
-static DEFINE_PCI_DEVICE_TABLE(ems_pci_tbl) = {
+static const struct pci_device_id ems_pci_tbl[] = {
 	/* CPC-PCI v1 */
 	{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
 	/* CPC-PCI v2 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/sja1000/kvaser_pci.c linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/kvaser_pci.c
--- linux-libre-3.16-gnu/drivers/net/can/sja1000/kvaser_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/kvaser_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@ struct kvaser_pci {
 #define KVASER_PCI_VENDOR_ID2     0x1a07    /* the PCI device and vendor IDs */
 #define KVASER_PCI_DEVICE_ID2     0x0008
 
-static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = {
+static const struct pci_device_id kvaser_pci_tbl[] = {
 	{KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,},
 	{KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,},
 	{ 0,}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/sja1000/peak_pci.c linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/peak_pci.c
--- linux-libre-3.16-gnu/drivers/net/can/sja1000/peak_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/peak_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,6 +70,8 @@ struct peak_pci_chan {
 #define PEAK_PC_104P_DEVICE_ID	0x0006	/* PCAN-PC/104+ cards */
 #define PEAK_PCI_104E_DEVICE_ID	0x0007	/* PCAN-PCI/104 Express cards */
 #define PEAK_MPCIE_DEVICE_ID	0x0008	/* The miniPCIe slot cards */
+#define PEAK_PCIE_OEM_ID	0x0009	/* PCAN-PCI Express OEM */
+#define PEAK_PCIEC34_DEVICE_ID	0x000A	/* PCAN-PCI Express 34 (one channel) */
 
 #define PEAK_PCI_CHAN_MAX	4
 
@@ -77,7 +79,7 @@ static const u16 peak_pci_icr_masks[PEAK
 	0x02, 0x01, 0x40, 0x80
 };
 
-static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
+static const struct pci_device_id peak_pci_tbl[] = {
 	{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 	{PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 	{PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
@@ -87,6 +89,7 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_
 	{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
 	{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #endif
 	{0,}
 };
@@ -653,7 +656,8 @@ static int peak_pci_probe(struct pci_dev
 		 * This must be done *before* register_sja1000dev() but
 		 * *after* devices linkage
 		 */
-		if (pdev->device == PEAK_PCIEC_DEVICE_ID) {
+		if (pdev->device == PEAK_PCIEC_DEVICE_ID ||
+		    pdev->device == PEAK_PCIEC34_DEVICE_ID) {
 			err = peak_pciec_probe(pdev, dev);
 			if (err) {
 				dev_err(&pdev->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/sja1000/plx_pci.c linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/plx_pci.c
--- linux-libre-3.16-gnu/drivers/net/can/sja1000/plx_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/plx_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,7 +247,7 @@ static struct plx_pci_card_info plx_pci_
 	/* based on PLX9030 */
 };
 
-static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
+static const struct pci_device_id plx_pci_tbl[] = {
 	{
 		/* Adlink PCI-7841/cPCI-7841 */
 		ADLINK_PCI_VENDOR_ID, ADLINK_PCI_DEVICE_ID,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/sja1000/sja1000.c linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/sja1000.c
--- linux-libre-3.16-gnu/drivers/net/can/sja1000/sja1000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/sja1000/sja1000.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,6 +141,7 @@ static void set_normal_mode(struct net_d
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
 	unsigned char status = priv->read_reg(priv, SJA1000_MOD);
+	u8 mod_reg_val = 0x00;
 	int i;
 
 	for (i = 0; i < 100; i++) {
@@ -158,9 +159,10 @@ static void set_normal_mode(struct net_d
 
 		/* set chip to normal mode */
 		if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
-			priv->write_reg(priv, SJA1000_MOD, MOD_LOM);
-		else
-			priv->write_reg(priv, SJA1000_MOD, 0x00);
+			mod_reg_val |= MOD_LOM;
+		if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+			mod_reg_val |= MOD_STM;
+		priv->write_reg(priv, SJA1000_MOD, mod_reg_val);
 
 		udelay(10);
 
@@ -170,6 +172,35 @@ static void set_normal_mode(struct net_d
 	netdev_err(dev, "setting SJA1000 into normal mode failed!\n");
 }
 
+/*
+ * initialize SJA1000 chip:
+ *   - reset chip
+ *   - set output mode
+ *   - set baudrate
+ *   - enable interrupts
+ *   - start operating mode
+ */
+static void chipset_init(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	/* set clock divider and output control register */
+	priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
+
+	/* set acceptance filter (accept all) */
+	priv->write_reg(priv, SJA1000_ACCC0, 0x00);
+	priv->write_reg(priv, SJA1000_ACCC1, 0x00);
+	priv->write_reg(priv, SJA1000_ACCC2, 0x00);
+	priv->write_reg(priv, SJA1000_ACCC3, 0x00);
+
+	priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
+	priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
+	priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
+	priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
+
+	priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
+}
+
 static void sja1000_start(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
@@ -178,6 +209,10 @@ static void sja1000_start(struct net_dev
 	if (priv->can.state != CAN_STATE_STOPPED)
 		set_reset_mode(dev);
 
+	/* Initialize chip if uninitialized at this stage */
+	if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN))
+		chipset_init(dev);
+
 	/* Clear error counters and error code capture */
 	priv->write_reg(priv, SJA1000_TXERR, 0x0);
 	priv->write_reg(priv, SJA1000_RXERR, 0x0);
@@ -235,35 +270,6 @@ static int sja1000_get_berr_counter(cons
 }
 
 /*
- * initialize SJA1000 chip:
- *   - reset chip
- *   - set output mode
- *   - set baudrate
- *   - enable interrupts
- *   - start operating mode
- */
-static void chipset_init(struct net_device *dev)
-{
-	struct sja1000_priv *priv = netdev_priv(dev);
-
-	/* set clock divider and output control register */
-	priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
-
-	/* set acceptance filter (accept all) */
-	priv->write_reg(priv, SJA1000_ACCC0, 0x00);
-	priv->write_reg(priv, SJA1000_ACCC1, 0x00);
-	priv->write_reg(priv, SJA1000_ACCC2, 0x00);
-	priv->write_reg(priv, SJA1000_ACCC3, 0x00);
-
-	priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
-	priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
-	priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
-	priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
-
-	priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
-}
-
-/*
  * transmit a CAN message
  * message layout in the sk_buff should be like this:
  * xx xx xx xx	 ff	 ll   00 11 22 33 44 55 66 77
@@ -278,6 +284,7 @@ static netdev_tx_t sja1000_start_xmit(st
 	uint8_t dlc;
 	canid_t id;
 	uint8_t dreg;
+	u8 cmd_reg_val = 0x00;
 	int i;
 
 	if (can_dropped_invalid_skb(dev, skb))
@@ -312,9 +319,14 @@ static netdev_tx_t sja1000_start_xmit(st
 	can_put_echo_skb(skb, dev, 0);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
-		sja1000_write_cmdreg(priv, CMD_TR | CMD_AT);
+		cmd_reg_val |= CMD_AT;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+		cmd_reg_val |= CMD_SRR;
 	else
-		sja1000_write_cmdreg(priv, CMD_TR);
+		cmd_reg_val |= CMD_TR;
+
+	sja1000_write_cmdreg(priv, cmd_reg_val);
 
 	return NETDEV_TX_OK;
 }
@@ -622,9 +634,12 @@ struct net_device *alloc_sja1000dev(int
 	priv->can.do_set_bittiming = sja1000_set_bittiming;
 	priv->can.do_set_mode = sja1000_set_mode;
 	priv->can.do_get_berr_counter = sja1000_get_berr_counter;
-	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
-		CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY |
-		CAN_CTRLMODE_ONE_SHOT;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
+				       CAN_CTRLMODE_LISTENONLY |
+				       CAN_CTRLMODE_3_SAMPLES |
+				       CAN_CTRLMODE_ONE_SHOT |
+				       CAN_CTRLMODE_BERR_REPORTING |
+				       CAN_CTRLMODE_PRESUME_ACK;
 
 	spin_lock_init(&priv->cmdreg_lock);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/can/slcan.c linux-libre-3.17-rc7-gnu/drivers/net/can/slcan.c
--- linux-libre-3.16-gnu/drivers/net/can/slcan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/can/slcan.c	2014-09-28 17:29:07.000000000 -0400
@@ -529,7 +529,7 @@ static struct slcan *slc_alloc(dev_t lin
 		return NULL;
 
 	sprintf(name, "slcan%d", i);
-	dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+	dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, slc_setup);
 	if (!dev)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/cris/eth_v10.c linux-libre-3.17-rc7-gnu/drivers/net/cris/eth_v10.c
--- linux-libre-3.16-gnu/drivers/net/cris/eth_v10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/cris/eth_v10.c	2014-09-28 17:29:07.000000000 -0400
@@ -1496,7 +1496,6 @@ e100_set_config(struct net_device *dev,
 		case IF_PORT_AUI:
 			spin_unlock(&np->lock);
 			return -EOPNOTSUPP;
-			break;
 		default:
 			printk(KERN_ERR "%s: Invalid media selected", dev->name);
 			spin_unlock(&np->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/dummy.c linux-libre-3.17-rc7-gnu/drivers/net/dummy.c
--- linux-libre-3.16-gnu/drivers/net/dummy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/dummy.c	2014-09-28 17:29:07.000000000 -0400
@@ -164,7 +164,7 @@ static int __init dummy_init_one(void)
 	struct net_device *dev_dummy;
 	int err;
 
-	dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
+	dev_dummy = alloc_netdev(0, "dummy%d", NET_NAME_UNKNOWN, dummy_setup);
 	if (!dev_dummy)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/eql.c linux-libre-3.17-rc7-gnu/drivers/net/eql.c
--- linux-libre-3.16-gnu/drivers/net/eql.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/eql.c	2014-09-28 17:29:07.000000000 -0400
@@ -585,7 +585,8 @@ static int __init eql_init_module(void)
 
 	pr_info("%s\n", version);
 
-	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
+	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", NET_NAME_UNKNOWN,
+			       eql_setup);
 	if (!dev_eql)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/3com/3c59x.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/3com/3c59x.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/3com/3c59x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/3com/3c59x.c	2014-09-28 17:29:07.000000000 -0400
@@ -375,7 +375,7 @@ static struct vortex_chip_info {
 };
 
 
-static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = {
+static const struct pci_device_id vortex_pci_tbl[] = {
 	{ 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 },
 	{ 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 },
 	{ 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 },
@@ -2129,6 +2129,7 @@ boomerang_start_xmit(struct sk_buff *skb
 	int entry = vp->cur_tx % TX_RING_SIZE;
 	struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
 	unsigned long flags;
+	dma_addr_t dma_addr;
 
 	if (vortex_debug > 6) {
 		pr_debug("boomerang_start_xmit()\n");
@@ -2163,24 +2164,48 @@ boomerang_start_xmit(struct sk_buff *skb
 			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
 
 	if (!skb_shinfo(skb)->nr_frags) {
-		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
-										skb->len, PCI_DMA_TODEVICE));
+		dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, skb->len,
+					  PCI_DMA_TODEVICE);
+		if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr))
+			goto out_dma_err;
+
+		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr);
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG);
 	} else {
 		int i;
 
-		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
-										skb_headlen(skb), PCI_DMA_TODEVICE));
+		dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data,
+					  skb_headlen(skb), PCI_DMA_TODEVICE);
+		if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr))
+			goto out_dma_err;
+
+		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr);
 		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb));
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
+			dma_addr = skb_frag_dma_map(&VORTEX_PCI(vp)->dev, frag,
+						    0,
+						    frag->size,
+						    DMA_TO_DEVICE);
+			if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) {
+				for(i = i-1; i >= 0; i--)
+					dma_unmap_page(&VORTEX_PCI(vp)->dev,
+						       le32_to_cpu(vp->tx_ring[entry].frag[i+1].addr),
+						       le32_to_cpu(vp->tx_ring[entry].frag[i+1].length),
+						       DMA_TO_DEVICE);
+
+				pci_unmap_single(VORTEX_PCI(vp),
+						 le32_to_cpu(vp->tx_ring[entry].frag[0].addr),
+						 le32_to_cpu(vp->tx_ring[entry].frag[0].length),
+						 PCI_DMA_TODEVICE);
+
+				goto out_dma_err;
+			}
+
 			vp->tx_ring[entry].frag[i+1].addr =
-					cpu_to_le32(pci_map_single(
-						VORTEX_PCI(vp),
-						(void *)skb_frag_address(frag),
-						skb_frag_size(frag), PCI_DMA_TODEVICE));
+						cpu_to_le32(dma_addr);
 
 			if (i == skb_shinfo(skb)->nr_frags-1)
 					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
@@ -2189,7 +2214,10 @@ boomerang_start_xmit(struct sk_buff *skb
 		}
 	}
 #else
-	vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
+	dma_addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
+	if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr))
+		goto out_dma_err;
+	vp->tx_ring[entry].addr = cpu_to_le32(dma_addr);
 	vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
 	vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 #endif
@@ -2217,7 +2245,11 @@ boomerang_start_xmit(struct sk_buff *skb
 	skb_tx_timestamp(skb);
 	iowrite16(DownUnstall, ioaddr + EL3_CMD);
 	spin_unlock_irqrestore(&vp->lock, flags);
+out:
 	return NETDEV_TX_OK;
+out_dma_err:
+	dev_err(&VORTEX_PCI(vp)->dev, "Error mapping dma buffer\n");
+	goto out;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/3com/typhoon.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/3com/typhoon.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/3com/typhoon.c	2014-08-07 04:53:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/3com/typhoon.c	2014-09-28 21:34:43.000000000 -0400
@@ -203,7 +203,7 @@ static struct typhoon_card_info typhoon_
  * bit 8 indicates if this is a (0) copper or (1) fiber card
  * bits 12-16 indicate card type: (0) client and (1) server
  */
-static DEFINE_PCI_DEVICE_TABLE(typhoon_pci_tbl) = {
+static const struct pci_device_id typhoon_pci_tbl[] = {
 	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0,TYPHOON_TX },
 	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_95,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/axnet_cs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/axnet_cs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/axnet_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/axnet_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,7 +108,7 @@ static u32 axnet_msg_enable;
 
 /*====================================================================*/
 
-typedef struct axnet_dev_t {
+struct axnet_dev {
 	struct pcmcia_device	*p_dev;
 	caddr_t	base;
 	struct timer_list	watchdog;
@@ -118,9 +118,9 @@ typedef struct axnet_dev_t {
 	int	phy_id;
 	int	flags;
 	int	active_low;
-} axnet_dev_t;
+};
 
-static inline axnet_dev_t *PRIV(struct net_device *dev)
+static inline struct axnet_dev *PRIV(struct net_device *dev)
 {
 	void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
 	return p;
@@ -141,13 +141,13 @@ static const struct net_device_ops axnet
 
 static int axnet_probe(struct pcmcia_device *link)
 {
-    axnet_dev_t *info;
+    struct axnet_dev *info;
     struct net_device *dev;
     struct ei_device *ei_local;
 
     dev_dbg(&link->dev, "axnet_attach()\n");
 
-    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
+    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(struct axnet_dev));
     if (!dev)
 	return -ENOMEM;
 
@@ -274,7 +274,7 @@ static int axnet_configcheck(struct pcmc
 static int axnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    axnet_dev_t *info = PRIV(dev);
+    struct axnet_dev *info = PRIV(dev);
     int i, j, j2, ret;
 
     dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
@@ -389,7 +389,7 @@ static int axnet_suspend(struct pcmcia_d
 static int axnet_resume(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
-	axnet_dev_t *info = PRIV(dev);
+	struct axnet_dev *info = PRIV(dev);
 
 	if (link->open) {
 		if (info->active_low == 1)
@@ -467,7 +467,7 @@ static void mdio_write(unsigned int addr
 static int axnet_open(struct net_device *dev)
 {
     int ret;
-    axnet_dev_t *info = PRIV(dev);
+    struct axnet_dev *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
     unsigned int nic_base = dev->base_addr;
     
@@ -497,7 +497,7 @@ static int axnet_open(struct net_device
 
 static int axnet_close(struct net_device *dev)
 {
-    axnet_dev_t *info = PRIV(dev);
+    struct axnet_dev *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
 
     dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
@@ -554,7 +554,7 @@ static irqreturn_t ei_irq_wrapper(int ir
 static void ei_watchdog(u_long arg)
 {
     struct net_device *dev = (struct net_device *)(arg);
-    axnet_dev_t *info = PRIV(dev);
+    struct axnet_dev *info = PRIV(dev);
     unsigned int nic_base = dev->base_addr;
     unsigned int mii_addr = nic_base + AXNET_MII_EEP;
     u_short link;
@@ -610,7 +610,7 @@ reschedule:
 
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    axnet_dev_t *info = PRIV(dev);
+    struct axnet_dev *info = PRIV(dev);
     struct mii_ioctl_data *data = if_mii(rq);
     unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
     switch (cmd) {
@@ -1452,7 +1452,7 @@ static void ei_receive(struct net_device
 
 static void ei_rx_overrun(struct net_device *dev)
 {
-	axnet_dev_t *info = PRIV(dev);
+	struct axnet_dev *info = PRIV(dev);
 	long e8390_base = dev->base_addr;
 	unsigned char was_txing, must_resend = 0;
 	struct ei_device *ei_local = netdev_priv(dev);
@@ -1624,7 +1624,7 @@ static void set_multicast_list(struct ne
 
 static void AX88190_init(struct net_device *dev, int startp)
 {
-	axnet_dev_t *info = PRIV(dev);
+	struct axnet_dev *info = PRIV(dev);
 	long e8390_base = dev->base_addr;
 	struct ei_device *ei_local = netdev_priv(dev);
 	int i;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -91,7 +91,8 @@ config MCF8390
 
 config NE2000
 	tristate "NE2000/NE1000 support"
-	depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+	depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX || \
+		    ATARI_ETHERNEC)
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/lib8390.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/lib8390.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/lib8390.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/lib8390.c	2014-09-28 17:29:07.000000000 -0400
@@ -986,7 +986,7 @@ static void ethdev_setup(struct net_devi
 static struct net_device *____alloc_ei_netdev(int size)
 {
 	return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
-				ethdev_setup);
+			    NET_NAME_UNKNOWN, ethdev_setup);
 }
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/mac8390.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/mac8390.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/mac8390.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/mac8390.c	2014-09-28 17:29:07.000000000 -0400
@@ -178,10 +178,8 @@ static enum mac8390_type __init mac8390_
 		case NUBUS_DRHW_APPLE_SONIC_LC:
 		case NUBUS_DRHW_SONNET:
 			return MAC8390_NONE;
-			break;
 		default:
 			return MAC8390_APPLE;
-			break;
 		}
 		break;
 
@@ -189,13 +187,10 @@ static enum mac8390_type __init mac8390_
 		switch (dev->dr_hw) {
 		case NUBUS_DRHW_ASANTE_LC:
 			return MAC8390_NONE;
-			break;
 		case NUBUS_DRHW_CABLETRON:
 			return MAC8390_CABLETRON;
-			break;
 		default:
 			return MAC8390_APPLE;
-			break;
 		}
 		break;
 
@@ -220,10 +215,8 @@ static enum mac8390_type __init mac8390_
 		switch (dev->dr_hw) {
 		case NUBUS_DRHW_INTERLAN:
 			return MAC8390_INTERLAN;
-			break;
 		default:
 			return MAC8390_KINETICS;
-			break;
 		}
 		break;
 
@@ -563,7 +556,6 @@ static int __init mac8390_initdev(struct
 		case ACCESS_UNKNOWN:
 			pr_err("Don't know how to access card memory!\n");
 			return -ENODEV;
-			break;
 
 		case ACCESS_16:
 			/* 16 bit card, register map is reversed */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/ne2k-pci.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/ne2k-pci.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/ne2k-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/ne2k-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,7 +135,7 @@ static struct {
 };
 
 
-static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = {
+static const struct pci_device_id ne2k_pci_tbl[] = {
 	{ 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 },
 	{ 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 },
 	{ 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/ne.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/ne.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/ne.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/ne.c	2014-09-28 17:29:07.000000000 -0400
@@ -169,6 +169,8 @@ bad_clone_list[] __initdata = {
 #elif defined(CONFIG_PLAT_OAKS32R)  || \
    defined(CONFIG_MACH_TX49XX)
 #  define DCR_VAL 0x48		/* 8-bit mode */
+#elif defined(CONFIG_ATARI)	/* 8-bit mode on Atari, normal on Q40 */
+#  define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49)
 #else
 #  define DCR_VAL 0x49
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/8390/pcnet_cs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/pcnet_cs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/8390/pcnet_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/8390/pcnet_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,11 +111,11 @@ static void pcnet_detach(struct pcmcia_d
 
 /*====================================================================*/
 
-typedef struct hw_info_t {
+struct hw_info {
     u_int	offset;
     u_char	a0, a1, a2;
     u_int	flags;
-} hw_info_t;
+};
 
 #define DELAY_OUTPUT	0x01
 #define HAS_MISC_REG	0x02
@@ -132,7 +132,7 @@ typedef struct hw_info_t {
 #define MII_PHYID_REG1		0x02
 #define MII_PHYID_REG2		0x03
 
-static hw_info_t hw_info[] = {
+static struct hw_info hw_info[] = {
     { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
     { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
     { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
@@ -196,11 +196,11 @@ static hw_info_t hw_info[] = {
 
 #define NR_INFO		ARRAY_SIZE(hw_info)
 
-static hw_info_t default_info = { 0, 0, 0, 0, 0 };
-static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
-static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
+static struct hw_info default_info = { 0, 0, 0, 0, 0 };
+static struct hw_info dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
+static struct hw_info dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
 
-typedef struct pcnet_dev_t {
+struct pcnet_dev {
 	struct pcmcia_device	*p_dev;
     u_int		flags;
     void		__iomem *base;
@@ -210,12 +210,12 @@ typedef struct pcnet_dev_t {
     u_char		eth_phy, pna_phy;
     u_short		link_status;
     u_long		mii_reset;
-} pcnet_dev_t;
+};
 
-static inline pcnet_dev_t *PRIV(struct net_device *dev)
+static inline struct pcnet_dev *PRIV(struct net_device *dev)
 {
 	char *p = netdev_priv(dev);
-	return (pcnet_dev_t *)(p + sizeof(struct ei_device));
+	return (struct pcnet_dev *)(p + sizeof(struct ei_device));
 }
 
 static const struct net_device_ops pcnet_netdev_ops = {
@@ -237,13 +237,13 @@ static const struct net_device_ops pcnet
 
 static int pcnet_probe(struct pcmcia_device *link)
 {
-    pcnet_dev_t *info;
+    struct pcnet_dev *info;
     struct net_device *dev;
 
     dev_dbg(&link->dev, "pcnet_attach()\n");
 
     /* Create new ethernet device */
-    dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
+    dev = __alloc_ei_netdev(sizeof(struct pcnet_dev));
     if (!dev) return -ENOMEM;
     info = PRIV(dev);
     info->p_dev = link;
@@ -276,7 +276,7 @@ static void pcnet_detach(struct pcmcia_d
 
 ======================================================================*/
 
-static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+static struct hw_info *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     u_char __iomem *base, *virt;
@@ -317,7 +317,7 @@ static hw_info_t *get_hwinfo(struct pcmc
 
 ======================================================================*/
 
-static hw_info_t *get_prom(struct pcmcia_device *link)
+static struct hw_info *get_prom(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     unsigned int ioaddr = dev->base_addr;
@@ -371,7 +371,7 @@ static hw_info_t *get_prom(struct pcmcia
 
 ======================================================================*/
 
-static hw_info_t *get_dl10019(struct pcmcia_device *link)
+static struct hw_info *get_dl10019(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -393,7 +393,7 @@ static hw_info_t *get_dl10019(struct pcm
 
 ======================================================================*/
 
-static hw_info_t *get_ax88190(struct pcmcia_device *link)
+static struct hw_info *get_ax88190(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     unsigned int ioaddr = dev->base_addr;
@@ -424,7 +424,7 @@ static hw_info_t *get_ax88190(struct pcm
 
 ======================================================================*/
 
-static hw_info_t *get_hwired(struct pcmcia_device *link)
+static struct hw_info *get_hwired(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -489,12 +489,12 @@ static int pcnet_confcheck(struct pcmcia
 	return try_io_port(p_dev);
 }
 
-static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
-				   int *has_shmem, int try)
+static struct hw_info *pcnet_try_config(struct pcmcia_device *link,
+					int *has_shmem, int try)
 {
 	struct net_device *dev = link->priv;
-	hw_info_t *local_hw_info;
-	pcnet_dev_t *info = PRIV(dev);
+	struct hw_info *local_hw_info;
+	struct pcnet_dev *info = PRIV(dev);
 	int priv = try;
 	int ret;
 
@@ -553,10 +553,10 @@ static hw_info_t *pcnet_try_config(struc
 static int pcnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     int start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
-    hw_info_t *local_hw_info;
+    struct hw_info *local_hw_info;
     struct ei_device *ei_local;
 
     dev_dbg(&link->dev, "pcnet_config\n");
@@ -639,7 +639,7 @@ failed:
 
 static void pcnet_release(struct pcmcia_device *link)
 {
-	pcnet_dev_t *info = PRIV(link->priv);
+	struct pcnet_dev *info = PRIV(link->priv);
 
 	dev_dbg(&link->dev, "pcnet_release\n");
 
@@ -836,7 +836,7 @@ static void write_asic(unsigned int ioad
 static void set_misc_reg(struct net_device *dev)
 {
     unsigned int nic_base = dev->base_addr;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     u_char tmp;
 
     if (info->flags & HAS_MISC_REG) {
@@ -873,7 +873,7 @@ static void set_misc_reg(struct net_devi
 
 static void mii_phy_probe(struct net_device *dev)
 {
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
     int i;
     u_int tmp, phyid;
@@ -898,7 +898,7 @@ static void mii_phy_probe(struct net_dev
 static int pcnet_open(struct net_device *dev)
 {
     int ret;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
     unsigned int nic_base = dev->base_addr;
 
@@ -931,7 +931,7 @@ static int pcnet_open(struct net_device
 
 static int pcnet_close(struct net_device *dev)
 {
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
 
     dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
@@ -982,7 +982,7 @@ static void pcnet_reset_8390(struct net_
 
 static int set_config(struct net_device *dev, struct ifmap *map)
 {
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
 	if (!(info->flags & HAS_MISC_REG))
 	    return -EOPNOTSUPP;
@@ -1000,7 +1000,7 @@ static int set_config(struct net_device
 static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
 {
     struct net_device *dev = dev_id;
-    pcnet_dev_t *info;
+    struct pcnet_dev *info;
     irqreturn_t ret = ei_interrupt(irq, dev_id);
 
     if (ret == IRQ_HANDLED) {
@@ -1013,7 +1013,7 @@ static irqreturn_t ei_irq_wrapper(int ir
 static void ei_watchdog(u_long arg)
 {
     struct net_device *dev = (struct net_device *)arg;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     unsigned int nic_base = dev->base_addr;
     unsigned int mii_addr = nic_base + DLINK_GPIO;
     u_short link;
@@ -1101,7 +1101,7 @@ reschedule:
 
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     struct mii_ioctl_data *data = if_mii(rq);
     unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
 
@@ -1214,7 +1214,7 @@ static void dma_block_output(struct net_
 			     const u_char *buf, const int start_page)
 {
     unsigned int nic_base = dev->base_addr;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
 #ifdef PCMCIA_DEBUG
     int retries = 0;
     struct ei_device *ei_local = netdev_priv(dev);
@@ -1403,7 +1403,7 @@ static int setup_shmem_window(struct pcm
 			      int stop_pg, int cm_offset)
 {
     struct net_device *dev = link->priv;
-    pcnet_dev_t *info = PRIV(dev);
+    struct pcnet_dev *info = PRIV(dev);
     int i, window_size, offset, ret;
 
     window_size = (stop_pg - start_pg) << 8;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/adaptec/starfire.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adaptec/starfire.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/adaptec/starfire.c	2014-08-07 04:51:25.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adaptec/starfire.c	2014-09-28 21:32:49.000000000 -0400
@@ -284,7 +284,7 @@ enum chipset {
 	CH_6915 = 0,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = {
+static const struct pci_device_id starfire_pci_tbl[] = {
 	{ PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/adi/bfin_mac.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/bfin_mac.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/adi/bfin_mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/bfin_mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -1218,11 +1218,11 @@ out:
 #define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \
 	RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE)
 
-static void bfin_mac_rx(struct net_device *dev)
+static void bfin_mac_rx(struct bfin_mac_local *lp)
 {
+	struct net_device *dev = lp->ndev;
 	struct sk_buff *skb, *new_skb;
 	unsigned short len;
-	struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev);
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
 	unsigned int i;
 	unsigned char fcs[ETH_FCS_LEN + 1];
@@ -1256,7 +1256,7 @@ static void bfin_mac_rx(struct net_devic
 	current_rx_ptr->skb = new_skb;
 	current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
 
-	len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN);
+	len = (unsigned short)(current_rx_ptr->status.status_word & RX_FRLEN);
 	/* Deduce Ethernet FCS length from Ethernet payload length */
 	len -= ETH_FCS_LEN;
 	skb_put(skb, len);
@@ -1294,7 +1294,8 @@ static void bfin_mac_rx(struct net_devic
 	}
 #endif
 
-	netif_rx(skb);
+	napi_gro_receive(&lp->napi, skb);
+
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += len;
 out:
@@ -1302,41 +1303,52 @@ out:
 	current_rx_ptr = current_rx_ptr->next;
 }
 
+static int bfin_mac_poll(struct napi_struct *napi, int budget)
+{
+	int i = 0;
+	struct bfin_mac_local *lp = container_of(napi,
+						 struct bfin_mac_local,
+						 napi);
+
+	while (current_rx_ptr->status.status_word != 0 && i < budget) {
+		bfin_mac_rx(lp);
+		i++;
+	}
+
+	if (i < budget) {
+		napi_complete(napi);
+		if (test_and_clear_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags))
+			enable_irq(IRQ_MAC_RX);
+	}
+
+	return i;
+}
+
 /* interrupt routine to handle rx and error signal */
 static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = dev_id;
-	int number = 0;
+	struct bfin_mac_local *lp = netdev_priv(dev_id);
+	u32 status;
 
-get_one_packet:
-	if (current_rx_ptr->status.status_word == 0) {
-		/* no more new packet received */
-		if (number == 0) {
-			if (current_rx_ptr->next->status.status_word != 0) {
-				current_rx_ptr = current_rx_ptr->next;
-				goto real_rx;
-			}
-		}
-		bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() |
-					   DMA_DONE | DMA_ERR);
-		return IRQ_HANDLED;
+	status = bfin_read_DMA1_IRQ_STATUS();
+
+	bfin_write_DMA1_IRQ_STATUS(status | DMA_DONE | DMA_ERR);
+	if (status & DMA_DONE) {
+		disable_irq_nosync(IRQ_MAC_RX);
+		set_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags);
+		napi_schedule(&lp->napi);
 	}
 
-real_rx:
-	bfin_mac_rx(dev);
-	number++;
-	goto get_one_packet;
+	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static void bfin_mac_poll(struct net_device *dev)
+static void bfin_mac_poll_controller(struct net_device *dev)
 {
 	struct bfin_mac_local *lp = netdev_priv(dev);
 
-	disable_irq(IRQ_MAC_RX);
 	bfin_mac_interrupt(IRQ_MAC_RX, dev);
 	tx_reclaim_skb(lp);
-	enable_irq(IRQ_MAC_RX);
 }
 #endif				/* CONFIG_NET_POLL_CONTROLLER */
 
@@ -1428,14 +1440,13 @@ static void bfin_mac_timeout(struct net_
 		tx_list_head = tx_list_head->next;
 	}
 
-	if (netif_queue_stopped(lp->ndev))
-		netif_wake_queue(lp->ndev);
+	if (netif_queue_stopped(dev))
+		netif_wake_queue(dev);
 
 	bfin_mac_enable(lp->phydev);
 
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
 }
 
 static void bfin_mac_multicast_hash(struct net_device *dev)
@@ -1562,6 +1573,7 @@ static int bfin_mac_open(struct net_devi
 		return ret;
 	pr_debug("hardware init finished\n");
 
+	napi_enable(&lp->napi);
 	netif_start_queue(dev);
 	netif_carrier_on(dev);
 
@@ -1579,6 +1591,7 @@ static int bfin_mac_close(struct net_dev
 	pr_debug("%s: %s\n", dev->name, __func__);
 
 	netif_stop_queue(dev);
+	napi_disable(&lp->napi);
 	netif_carrier_off(dev);
 
 	phy_stop(lp->phydev);
@@ -1604,7 +1617,7 @@ static const struct net_device_ops bfin_
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= bfin_mac_poll,
+	.ndo_poll_controller	= bfin_mac_poll_controller,
 #endif
 };
 
@@ -1689,6 +1702,9 @@ static int bfin_mac_probe(struct platfor
 	lp->tx_reclaim_timer.data = (unsigned long)lp;
 	lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout;
 
+	lp->flags = 0;
+	netif_napi_add(ndev, &lp->napi, bfin_mac_poll, CONFIG_BFIN_RX_DESC_NUM);
+
 	spin_lock_init(&lp->lock);
 
 	/* now, enable interrupts */
@@ -1723,6 +1739,7 @@ out_err_phc:
 out_err_reg_ndev:
 	free_irq(IRQ_MAC_RX, ndev);
 out_err_request_irq:
+	netif_napi_del(&lp->napi);
 out_err_mii_probe:
 	mdiobus_unregister(lp->mii_bus);
 	mdiobus_free(lp->mii_bus);
@@ -1743,6 +1760,8 @@ static int bfin_mac_remove(struct platfo
 
 	unregister_netdev(ndev);
 
+	netif_napi_del(&lp->napi);
+
 	free_irq(IRQ_MAC_RX, ndev);
 
 	free_netdev(ndev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/adi/bfin_mac.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/bfin_mac.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/adi/bfin_mac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/bfin_mac.h	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,7 @@
 #endif
 
 #define TX_RECLAIM_JIFFIES (HZ / 5)
+#define BFIN_MAC_RX_IRQ_DISABLED	1
 
 struct dma_descriptor {
 	struct dma_descriptor *next_dma_desc;
@@ -80,6 +81,8 @@ struct bfin_mac_local {
 	int irq_wake_requested;
 	struct timer_list tx_reclaim_timer;
 	struct net_device *ndev;
+	struct napi_struct napi;
+	unsigned long flags;
 
 	/* Data for EMAC_VLAN1 regs */
 	u16 vlan1_mask, vlan2_mask;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/adi/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/adi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/adi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -52,8 +52,7 @@ config BFIN_TX_DESC_NUM
 config BFIN_RX_DESC_NUM
 	int "Number of receive buffer packets"
 	depends on BFIN_MAC
-	range 20 100 if BFIN_MAC_USE_L1
-	range 20 800
+	range 20 64
 	default "20"
 	---help---
 	  Set the number of buffer packets used in driver.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/aeroflex/greth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/aeroflex/greth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/aeroflex/greth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/aeroflex/greth.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,6 +123,12 @@ static inline void greth_enable_tx(struc
 	GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
 }
 
+static inline void greth_enable_tx_and_irq(struct greth_private *greth)
+{
+	wmb(); /* BDs must been written to memory before enabling TX */
+	GRETH_REGORIN(greth->regs->control, GRETH_TXEN | GRETH_TXI);
+}
+
 static inline void greth_disable_tx(struct greth_private *greth)
 {
 	GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
@@ -447,29 +453,30 @@ out:
 	return err;
 }
 
+static inline u16 greth_num_free_bds(u16 tx_last, u16 tx_next)
+{
+	if (tx_next < tx_last)
+		return (tx_last - tx_next) - 1;
+	else
+		return GRETH_TXBD_NUM - (tx_next - tx_last) - 1;
+}
 
 static netdev_tx_t
 greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct greth_private *greth = netdev_priv(dev);
 	struct greth_bd *bdp;
-	u32 status = 0, dma_addr, ctrl;
+	u32 status, dma_addr;
 	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
 	unsigned long flags;
+	u16 tx_last;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
+	tx_last = greth->tx_last;
+	rmb(); /* tx_last is updated by the poll task */
 
-	/* Clean TX Ring */
-	greth_clean_tx_gbit(dev);
-
-	if (greth->tx_free < nr_frags + 1) {
-		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
-		ctrl = GRETH_REGLOAD(greth->regs->control);
-		/* Enable TX IRQ only if not already in poll() routine */
-		if (ctrl & GRETH_RXI)
-			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
+	if (greth_num_free_bds(tx_last, greth->tx_next) < nr_frags + 1) {
 		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&greth->devlock, flags);
 		err = NETDEV_TX_BUSY;
 		goto out;
 	}
@@ -488,6 +495,8 @@ greth_start_xmit_gbit(struct sk_buff *sk
 	/* Linear buf */
 	if (nr_frags != 0)
 		status = GRETH_TXBD_MORE;
+	else
+		status = GRETH_BD_IE;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		status |= GRETH_TXBD_CSALL;
@@ -545,14 +554,12 @@ greth_start_xmit_gbit(struct sk_buff *sk
 
 	/* Enable the descriptor chain by enabling the first descriptor */
 	bdp = greth->tx_bd_base + greth->tx_next;
-	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
-	greth->tx_next = curr_tx;
-	greth->tx_free -= nr_frags + 1;
-
-	wmb();
+	greth_write_bd(&bdp->stat,
+		       greth_read_bd(&bdp->stat) | GRETH_BD_EN);
 
 	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
-	greth_enable_tx(greth);
+	greth->tx_next = curr_tx;
+	greth_enable_tx_and_irq(greth);
 	spin_unlock_irqrestore(&greth->devlock, flags);
 
 	return NETDEV_TX_OK;
@@ -648,7 +655,6 @@ static void greth_clean_tx(struct net_de
 	if (greth->tx_free > 0) {
 		netif_wake_queue(dev);
 	}
-
 }
 
 static inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
@@ -670,20 +676,22 @@ static void greth_clean_tx_gbit(struct n
 {
 	struct greth_private *greth;
 	struct greth_bd *bdp, *bdp_last_frag;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	u32 stat;
 	int nr_frags, i;
+	u16 tx_last;
 
 	greth = netdev_priv(dev);
+	tx_last = greth->tx_last;
 
-	while (greth->tx_free < GRETH_TXBD_NUM) {
+	while (tx_last != greth->tx_next) {
 
-		skb = greth->tx_skbuff[greth->tx_last];
+		skb = greth->tx_skbuff[tx_last];
 
 		nr_frags = skb_shinfo(skb)->nr_frags;
 
 		/* We only clean fully completed SKBs */
-		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
+		bdp_last_frag = greth->tx_bd_base + SKIP_TX(tx_last, nr_frags);
 
 		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
 		mb();
@@ -692,14 +700,14 @@ static void greth_clean_tx_gbit(struct n
 		if (stat & GRETH_BD_EN)
 			break;
 
-		greth->tx_skbuff[greth->tx_last] = NULL;
+		greth->tx_skbuff[tx_last] = NULL;
 
 		greth_update_tx_stats(dev, stat);
 		dev->stats.tx_bytes += skb->len;
 
-		bdp = greth->tx_bd_base + greth->tx_last;
+		bdp = greth->tx_bd_base + tx_last;
 
-		greth->tx_last = NEXT_TX(greth->tx_last);
+		tx_last = NEXT_TX(tx_last);
 
 		dma_unmap_single(greth->dev,
 				 greth_read_bd(&bdp->addr),
@@ -708,21 +716,26 @@ static void greth_clean_tx_gbit(struct n
 
 		for (i = 0; i < nr_frags; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			bdp = greth->tx_bd_base + greth->tx_last;
+			bdp = greth->tx_bd_base + tx_last;
 
 			dma_unmap_page(greth->dev,
 				       greth_read_bd(&bdp->addr),
 				       skb_frag_size(frag),
 				       DMA_TO_DEVICE);
 
-			greth->tx_last = NEXT_TX(greth->tx_last);
+			tx_last = NEXT_TX(tx_last);
 		}
-		greth->tx_free += nr_frags+1;
 		dev_kfree_skb(skb);
 	}
+	if (skb) { /* skb is set only if the above while loop was entered */
+		wmb();
+		greth->tx_last = tx_last;
 
-	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
-		netif_wake_queue(dev);
+		if (netif_queue_stopped(dev) &&
+		    (greth_num_free_bds(tx_last, greth->tx_next) >
+		    (MAX_SKB_FRAGS+1)))
+			netif_wake_queue(dev);
+	}
 }
 
 static int greth_rx(struct net_device *dev, int limit)
@@ -965,16 +978,12 @@ static int greth_poll(struct napi_struct
 	greth = container_of(napi, struct greth_private, napi);
 
 restart_txrx_poll:
-	if (netif_queue_stopped(greth->netdev)) {
-		if (greth->gbit_mac)
-			greth_clean_tx_gbit(greth->netdev);
-		else
-			greth_clean_tx(greth->netdev);
-	}
-
 	if (greth->gbit_mac) {
+		greth_clean_tx_gbit(greth->netdev);
 		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
 	} else {
+		if (netif_queue_stopped(greth->netdev))
+			greth_clean_tx(greth->netdev);
 		work_done += greth_rx(greth->netdev, budget - work_done);
 	}
 
@@ -983,7 +992,8 @@ restart_txrx_poll:
 		spin_lock_irqsave(&greth->devlock, flags);
 
 		ctrl = GRETH_REGLOAD(greth->regs->control);
-		if (netif_queue_stopped(greth->netdev)) {
+		if ((greth->gbit_mac && (greth->tx_last != greth->tx_next)) ||
+		    (!greth->gbit_mac && netif_queue_stopped(greth->netdev))) {
 			GRETH_REGSAVE(greth->regs->control,
 					ctrl | GRETH_TXI | GRETH_RXI);
 			mask = GRETH_INT_RX | GRETH_INT_RE |
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/aeroflex/greth.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/aeroflex/greth.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/aeroflex/greth.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/aeroflex/greth.h	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@ struct greth_private {
 
 	u16 tx_next;
 	u16 tx_last;
-	u16 tx_free;
+	u16 tx_free; /* only used on 10/100Mbit */
 	u16 rx_cur;
 
 	struct greth_regs *regs;	/* Address of controller registers. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c	2014-09-28 17:29:07.000000000 -0400
@@ -633,8 +633,10 @@ static void emac_rx(struct net_device *d
 		}
 
 		/* Move data from EMAC */
-		skb = dev_alloc_skb(rxlen + 4);
-		if (good_packet && skb) {
+		if (good_packet) {
+			skb = netdev_alloc_skb(dev, rxlen + 4);
+			if (!skb)
+				continue;
 			skb_reserve(skb, 2);
 			rdptr = (u8 *) skb_put(skb, rxlen - 4);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/alteon/acenic.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/alteon/acenic.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/alteon/acenic.c	2014-08-07 04:51:18.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/alteon/acenic.c	2014-09-28 21:32:42.000000000 -0400
@@ -131,7 +131,7 @@
 #define PCI_DEVICE_ID_SGI_ACENIC	0x0009
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = {
+static const struct pci_device_id acenic_pci_tbl[] = {
 	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE,
 	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
 	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/amd8111e.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/amd8111e.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/amd8111e.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/amd8111e.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,6 @@ Revision History:
 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
 MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS);
 MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
 module_param_array(speed_duplex, int, NULL, 0);
 MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
 module_param_array(coalesce, bool, NULL, 0);
@@ -109,17 +108,9 @@ MODULE_PARM_DESC(coalesce, "Enable or Di
 module_param_array(dynamic_ipg, bool, NULL, 0);
 MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable");
 
-static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = {
-
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-	{ 0, }
-
-};
-/*
-This function will read the PHY registers.
-*/
-static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val)
+/* This function will read the PHY registers. */
+static int amd8111e_read_phy(struct amd8111e_priv *lp,
+			     int phy_id, int reg, u32 *val)
 {
 	void __iomem *mmio = lp->mmio;
 	unsigned int reg_val;
@@ -146,10 +137,9 @@ err_phy_read:
 
 }
 
-/*
-This function will write into PHY registers.
-*/
-static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
+/* This function will write into PHY registers. */
+static int amd8111e_write_phy(struct amd8111e_priv *lp,
+			      int phy_id, int reg, u32 val)
 {
 	unsigned int repeat = REPEAT_CNT;
 	void __iomem *mmio = lp->mmio;
@@ -176,12 +166,11 @@ err_phy_write:
 	return -EINVAL;
 
 }
-/*
-This is the mii register read function provided to the mii interface.
-*/
-static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
+
+/* This is the mii register read function provided to the mii interface. */
+static int amd8111e_mdio_read(struct net_device *dev, int phy_id, int reg_num)
 {
-	struct amd8111e_priv* lp = netdev_priv(dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
 	unsigned int reg_val;
 
 	amd8111e_read_phy(lp,phy_id,reg_num,&reg_val);
@@ -189,19 +178,18 @@ static int amd8111e_mdio_read(struct net
 
 }
 
-/*
-This is the mii register write function provided to the mii interface.
-*/
-static void amd8111e_mdio_write(struct net_device * dev, int phy_id, int reg_num, int val)
+/* This is the mii register write function provided to the mii interface. */
+static void amd8111e_mdio_write(struct net_device *dev,
+				int phy_id, int reg_num, int val)
 {
-	struct amd8111e_priv* lp = netdev_priv(dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
 
 	amd8111e_write_phy(lp, phy_id, reg_num, val);
 }
 
-/*
-This function will set PHY speed. During initialization sets the original speed to 100 full.
-*/
+/* This function will set PHY speed. During initialization sets
+ * the original speed to 100 full
+ */
 static void amd8111e_set_ext_phy(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
@@ -240,14 +228,13 @@ static void amd8111e_set_ext_phy(struct
 
 }
 
-/*
-This function will unmap skb->data space and will free
-all transmit and receive skbuffs.
-*/
+/* This function will unmap skb->data space and will free
+ * all transmit and receive skbuffs.
+ */
 static int amd8111e_free_skbs(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct sk_buff* rx_skbuff;
+	struct sk_buff *rx_skbuff;
 	int i;
 
 	/* Freeing transmit skbs */
@@ -274,18 +261,18 @@ static int amd8111e_free_skbs(struct net
 	return 0;
 }
 
-/*
-This will set the receive buffer length corresponding to the mtu size of networkinterface.
-*/
-static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
+/* This will set the receive buffer length corresponding
+ * to the mtu size of networkinterface.
+ */
+static inline void amd8111e_set_rx_buff_len(struct net_device *dev)
 {
-	struct amd8111e_priv* lp = netdev_priv(dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
 	unsigned int mtu = dev->mtu;
 
 	if (mtu > ETH_DATA_LEN){
 		/* MTU + ethernet header + FCS
-		+ optional VLAN tag + skb reserve space 2 */
-
+		 * + optional VLAN tag + skb reserve space 2
+		 */
 		lp->rx_buff_len = mtu + ETH_HLEN + 10;
 		lp->options |= OPTION_JUMBO_ENABLE;
 	} else{
@@ -294,8 +281,10 @@ static inline void amd8111e_set_rx_buff_
 	}
 }
 
-/*
-This function will free all the previously allocated buffers, determine new receive buffer length  and will allocate new receive buffers. This function also allocates and initializes both the transmitter and receive hardware descriptors.
+/* This function will free all the previously allocated buffers,
+ * determine new receive buffer length  and will allocate new receive buffers.
+ * This function also allocates and initializes both the transmitter
+ * and receive hardware descriptors.
  */
 static int amd8111e_init_ring(struct net_device *dev)
 {
@@ -376,15 +365,18 @@ err_free_tx_ring:
 err_no_mem:
 	return -ENOMEM;
 }
-/* This function will set the interrupt coalescing according to the input arguments */
-static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
+
+/* This function will set the interrupt coalescing according
+ * to the input arguments
+ */
+static int amd8111e_set_coalesce(struct net_device *dev, enum coal_mode cmod)
 {
 	unsigned int timeout;
 	unsigned int event_count;
 
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	void __iomem *mmio = lp->mmio;
-	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+	struct amd8111e_coalesce_conf *coal_conf = &lp->coal_conf;
 
 
 	switch(cmod)
@@ -435,9 +427,7 @@ static int amd8111e_set_coalesce(struct
 
 }
 
-/*
-This function initializes the device registers  and starts the device.
-*/
+/* This function initializes the device registers  and starts the device. */
 static int amd8111e_restart(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
@@ -501,8 +491,7 @@ static int amd8111e_restart(struct net_d
 
 	/* Enable interrupt coalesce */
 	if(lp->options & OPTION_INTR_COAL_ENABLE){
-		printk(KERN_INFO "%s: Interrupt Coalescing Enabled.\n",
-								dev->name);
+		netdev_info(dev, "Interrupt Coalescing Enabled.\n");
 		amd8111e_set_coalesce(dev,ENABLE_COAL);
 	}
 
@@ -514,10 +503,9 @@ static int amd8111e_restart(struct net_d
 	readl(mmio+CMD0);
 	return 0;
 }
-/*
-This function clears necessary the device registers.
-*/
-static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
+
+/* This function clears necessary the device registers. */
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
 {
 	unsigned int reg_val;
 	unsigned int logic_filter[2] ={0,};
@@ -587,7 +575,7 @@ static void amd8111e_init_hw_default( st
 	writew(MIB_CLEAR, mmio + MIB_ADDR);
 
 	/* Clear LARF */
-	amd8111e_writeq(*(u64*)logic_filter,mmio+LADRF);
+	amd8111e_writeq(*(u64 *)logic_filter, mmio + LADRF);
 
 	/* SRAM_SIZE register */
 	reg_val = readl(mmio + SRAM_SIZE);
@@ -605,11 +593,10 @@ static void amd8111e_init_hw_default( st
 
 }
 
-/*
-This function disables the interrupt and clears all the pending
-interrupts in INT0
+/* This function disables the interrupt and clears all the pending
+ * interrupts in INT0
  */
-static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
 {
 	u32 intr0;
 
@@ -625,10 +612,8 @@ static void amd8111e_disable_interrupt(s
 
 }
 
-/*
-This function stops the chip.
-*/
-static void amd8111e_stop_chip(struct amd8111e_priv* lp)
+/* This function stops the chip. */
+static void amd8111e_stop_chip(struct amd8111e_priv *lp)
 {
 	writel(RUN, lp->mmio + CMD0);
 
@@ -636,10 +621,8 @@ static void amd8111e_stop_chip(struct am
 	readl(lp->mmio + CMD0);
 }
 
-/*
-This function frees the  transmiter and receiver descriptor rings.
-*/
-static void amd8111e_free_ring(struct amd8111e_priv* lp)
+/* This function frees the  transmiter and receiver descriptor rings. */
+static void amd8111e_free_ring(struct amd8111e_priv *lp)
 {
 	/* Free transmit and receive descriptor rings */
 	if(lp->rx_ring){
@@ -659,12 +642,13 @@ static void amd8111e_free_ring(struct am
 
 }
 
-/*
-This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
-*/
+/* This function will free all the transmit skbs that are actually
+ * transmitted by the device. It will check the ownership of the
+ * skb before freeing the skb.
+ */
 static int amd8111e_tx(struct net_device *dev)
 {
-	struct amd8111e_priv* lp = netdev_priv(dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
 	int tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
 	int status;
 	/* Complete all the transmit packet */
@@ -724,21 +708,20 @@ static int amd8111e_rx_poll(struct napi_
 		goto rx_not_empty;
 
 	do{
-		/* process receive packets until we use the quota*/
-		/* If we own the next entry, it's a new packet. Send it up. */
+		/* process receive packets until we use the quota.
+		 * If we own the next entry, it's a new packet. Send it up.
+		 */
 		while(1) {
 			status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
 			if (status & OWN_BIT)
 				break;
 
-			/*
-			 * There is a tricky error noted by John Murphy,
+			/* There is a tricky error noted by John Murphy,
 			 * <murf@perftech.com> to Russ Nelson: Even with
 			 * full-sized * buffers it's possible for a
 			 * jabber packet to use two buffers, with only
 			 * the last correctly noting the error.
 			 */
-
 			if(status & ERR_BIT) {
 				/* reseting flags */
 				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
@@ -771,7 +754,8 @@ static int amd8111e_rx_poll(struct napi_
 			new_skb = netdev_alloc_skb(dev, lp->rx_buff_len);
 			if (!new_skb) {
 				/* if allocation fail,
-				   ignore that pkt and go to next one */
+				 * ignore that pkt and go to next one
+				 */
 				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
 				lp->drv_rx_errors++;
 				goto err_next_pkt;
@@ -812,8 +796,8 @@ static int amd8111e_rx_poll(struct napi_
 			rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
 		}
 		/* Check the interrupt status register for more packets in the
-		   mean time. Process them since we have not used up our quota.*/
-
+		 * mean time. Process them since we have not used up our quota.
+		 */
 		intr0 = readl(mmio + INT0);
 		/*Ack receive packets */
 		writel(intr0 & RINT0,mmio + INT0);
@@ -833,10 +817,8 @@ rx_not_empty:
 	return num_rx_pkt;
 }
 
-/*
-This function will indicate the link status to the kernel.
-*/
-static int amd8111e_link_change(struct net_device* dev)
+/* This function will indicate the link status to the kernel. */
+static int amd8111e_link_change(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	int status0,speed;
@@ -860,24 +842,26 @@ static int amd8111e_link_change(struct n
 		else if(speed == PHY_SPEED_100)
 			lp->link_config.speed = SPEED_100;
 
-		printk(KERN_INFO "%s: Link is Up. Speed is %s Mbps %s Duplex\n",			dev->name,
-		       (lp->link_config.speed == SPEED_100) ? "100": "10",
-		       (lp->link_config.duplex == DUPLEX_FULL)? "Full": "Half");
+		netdev_info(dev, "Link is Up. Speed is %s Mbps %s Duplex\n",
+			    (lp->link_config.speed == SPEED_100) ?
+							"100" : "10",
+			    (lp->link_config.duplex == DUPLEX_FULL) ?
+							"Full" : "Half");
+
 		netif_carrier_on(dev);
 	}
 	else{
 		lp->link_config.speed = SPEED_INVALID;
 		lp->link_config.duplex = DUPLEX_INVALID;
 		lp->link_config.autoneg = AUTONEG_INVALID;
-		printk(KERN_INFO "%s: Link is Down.\n",dev->name);
+		netdev_info(dev, "Link is Down.\n");
 		netif_carrier_off(dev);
 	}
 
 	return 0;
 }
-/*
-This function reads the mib counters.
-*/
+
+/* This function reads the mib counters. */
 static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
 {
 	unsigned int  status;
@@ -895,8 +879,7 @@ static int amd8111e_read_mib(void __iome
 	return data;
 }
 
-/*
- * This function reads the mib registers and returns the hardware statistics.
+/* This function reads the mib registers and returns the hardware statistics.
  * It updates previous internal driver statistics with new values.
  */
 static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
@@ -992,13 +975,14 @@ static struct net_device_stats *amd8111e
 
 	return new_stats;
 }
+
 /* This function recalculate the interrupt coalescing  mode on every interrupt
-according to the datarate and the packet rate.
-*/
+ * according to the datarate and the packet rate.
+ */
 static int amd8111e_calc_coalesce(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+	struct amd8111e_coalesce_conf *coal_conf = &lp->coal_conf;
 	int tx_pkt_rate;
 	int rx_pkt_rate;
 	int tx_data_rate;
@@ -1126,13 +1110,14 @@ static int amd8111e_calc_coalesce(struct
 	return 0;
 
 }
-/*
-This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
-*/
+
+/* This is device interrupt function. It handles transmit,
+ * receive,link change and hardware timer interrupts.
+ */
 static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
 {
 
-	struct net_device * dev = (struct net_device *) dev_id;
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	void __iomem *mmio = lp->mmio;
 	unsigned int intr0, intren0;
@@ -1168,7 +1153,7 @@ static irqreturn_t amd8111e_interrupt(in
 			/* Schedule a polling routine */
 			__napi_schedule(&lp->napi);
 		} else if (intren0 & RINTEN0) {
-			printk("************Driver bug! interrupt while in poll\n");
+			netdev_dbg(dev, "************Driver bug! interrupt while in poll\n");
 			/* Fix by disable receive interrupts */
 			writel(RINTEN0, mmio + INTEN0);
 		}
@@ -1205,10 +1190,11 @@ static void amd8111e_poll(struct net_dev
 #endif
 
 
-/*
-This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
-*/
-static int amd8111e_close(struct net_device * dev)
+/* This function closes the network interface and updates
+ * the statistics so that most recent statistics will be
+ * available after the interface is down.
+ */
+static int amd8111e_close(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	netif_stop_queue(dev);
@@ -1238,9 +1224,11 @@ static int amd8111e_close(struct net_dev
 	lp->opened = 0;
 	return 0;
 }
-/* This function opens new interface.It requests irq for the device, initializes the device,buffers and descriptors, and starts the device.
-*/
-static int amd8111e_open(struct net_device * dev )
+
+/* This function opens new interface.It requests irq for the device,
+ * initializes the device,buffers and descriptors, and starts the device.
+ */
+static int amd8111e_open(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 
@@ -1264,7 +1252,7 @@ static int amd8111e_open(struct net_devi
 	/* Start ipg timer */
 	if(lp->options & OPTION_DYN_IPG_ENABLE){
 		add_timer(&lp->ipg_data.ipg_timer);
-		printk(KERN_INFO "%s: Dynamic IPG Enabled.\n",dev->name);
+		netdev_info(dev, "Dynamic IPG Enabled\n");
 	}
 
 	lp->opened = 1;
@@ -1275,10 +1263,11 @@ static int amd8111e_open(struct net_devi
 
 	return 0;
 }
-/*
-This function checks if there is any transmit  descriptors available to queue more packet.
-*/
-static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
+
+/* This function checks if there is any transmit  descriptors
+ * available to queue more packet.
+ */
+static int amd8111e_tx_queue_avail(struct amd8111e_priv *lp)
 {
 	int tx_index = lp->tx_idx & TX_BUFF_MOD_MASK;
 	if (lp->tx_skbuff[tx_index])
@@ -1287,12 +1276,14 @@ static int amd8111e_tx_queue_avail(struc
 		return 0;
 
 }
-/*
-This function will queue the transmit packets to the descriptors and will trigger the send operation. It also initializes the transmit descriptors with buffer physical address, byte count, ownership to hardware etc.
-*/
 
+/* This function will queue the transmit packets to the
+ * descriptors and will trigger the send operation. It also
+ * initializes the transmit descriptors with buffer physical address,
+ * byte count, ownership to hardware etc.
+ */
 static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
-				       struct net_device * dev)
+				       struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	int tx_index;
@@ -1338,9 +1329,7 @@ static netdev_tx_t amd8111e_start_xmit(s
 	spin_unlock_irqrestore(&lp->lock, flags);
 	return NETDEV_TX_OK;
 }
-/*
-This function returns all the memory mapped registers of the device.
-*/
+/* This function returns all the memory mapped registers of the device. */
 static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
 {
 	void __iomem *mmio = lp->mmio;
@@ -1361,10 +1350,9 @@ static void amd8111e_read_regs(struct am
 }
 
 
-/*
-This function sets promiscuos mode, all-multi mode or the multicast address
-list to the device.
-*/
+/* This function sets promiscuos mode, all-multi mode or the multicast address
+ * list to the device.
+ */
 static void amd8111e_set_multicast_list(struct net_device *dev)
 {
 	struct netdev_hw_addr *ha;
@@ -1383,14 +1371,14 @@ static void amd8111e_set_multicast_list(
 		/* get all multicast packet */
 		mc_filter[1] = mc_filter[0] = 0xffffffff;
 		lp->options |= OPTION_MULTICAST_ENABLE;
-		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+		amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
 		return;
 	}
 	if (netdev_mc_empty(dev)) {
 		/* get only own packets */
 		mc_filter[1] = mc_filter[0] = 0;
 		lp->options &= ~OPTION_MULTICAST_ENABLE;
-		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+		amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
 		/* disable promiscuous mode */
 		writel(PROM, lp->mmio + CMD2);
 		return;
@@ -1402,14 +1390,15 @@ static void amd8111e_set_multicast_list(
 		bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f;
 		mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
 	}
-	amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
+	amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
 
 	/* To eliminate PCI posting bug */
 	readl(lp->mmio + CMD2);
 
 }
 
-static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
+static void amd8111e_get_drvinfo(struct net_device *dev,
+				 struct ethtool_drvinfo *info)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	struct pci_dev *pci_dev = lp->pci_dev;
@@ -1501,11 +1490,11 @@ static const struct ethtool_ops ops = {
 	.set_wol = amd8111e_set_wol,
 };
 
-/*
-This function handles all the  ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application.
-*/
-
-static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
+/* This function handles all the  ethtool ioctls. It gives driver info,
+ * gets/sets driver speed, gets memory mapped register values, forces
+ * auto negotiation, sets/gets WOL options for ethtool application.
+ */
+static int amd8111e_ioctl(struct net_device *dev , struct ifreq *ifr, int cmd)
 {
 	struct mii_ioctl_data *data = if_mii(ifr);
 	struct amd8111e_priv *lp = netdev_priv(dev);
@@ -1559,9 +1548,9 @@ static int amd8111e_set_mac_address(stru
 	return 0;
 }
 
-/*
-This function changes the mtu of the device. It restarts the device  to initialize the descriptor with new receive buffers.
-*/
+/* This function changes the mtu of the device. It restarts the device  to
+ * initialize the descriptor with new receive buffers.
+ */
 static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
@@ -1572,7 +1561,8 @@ static int amd8111e_change_mtu(struct ne
 
 	if (!netif_running(dev)) {
 		/* new_mtu will be used
-		   when device starts netxt time */
+		 * when device starts netxt time
+		 */
 		dev->mtu = new_mtu;
 		return 0;
 	}
@@ -1591,7 +1581,7 @@ static int amd8111e_change_mtu(struct ne
 	return err;
 }
 
-static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
+static int amd8111e_enable_magicpkt(struct amd8111e_priv *lp)
 {
 	writel( VAL1|MPPLBA, lp->mmio + CMD3);
 	writel( VAL0|MPEN_SW, lp->mmio + CMD7);
@@ -1601,7 +1591,7 @@ static int amd8111e_enable_magicpkt(stru
 	return 0;
 }
 
-static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
+static int amd8111e_enable_link_change(struct amd8111e_priv *lp)
 {
 
 	/* Adapter is already stoped/suspended/interrupt-disabled */
@@ -1612,19 +1602,18 @@ static int amd8111e_enable_link_change(s
 	return 0;
 }
 
-/*
- * This function is called when a packet transmission fails to complete
+/* This function is called when a packet transmission fails to complete
  * within a reasonable period, on the assumption that an interrupt have
  * failed or the interface is locked up. This function will reinitialize
  * the hardware.
  */
 static void amd8111e_tx_timeout(struct net_device *dev)
 {
-	struct amd8111e_priv* lp = netdev_priv(dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
 	int err;
 
-	printk(KERN_ERR "%s: transmit timed out, resetting\n",
-	 					      dev->name);
+	netdev_err(dev, "transmit timed out, resetting\n");
+
 	spin_lock_irq(&lp->lock);
 	err = amd8111e_restart(dev);
 	spin_unlock_irq(&lp->lock);
@@ -1701,22 +1690,10 @@ static int amd8111e_resume(struct pci_de
 	return 0;
 }
 
-
-static void amd8111e_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	if (dev) {
-		unregister_netdev(dev);
-		iounmap(((struct amd8111e_priv *)netdev_priv(dev))->mmio);
-		free_netdev(dev);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-	}
-}
-static void amd8111e_config_ipg(struct net_device* dev)
+static void amd8111e_config_ipg(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct ipg_info* ipg_data = &lp->ipg_data;
+	struct ipg_info *ipg_data = &lp->ipg_data;
 	void __iomem *mmio = lp->mmio;
 	unsigned int prev_col_cnt = ipg_data->col_cnt;
 	unsigned int total_col_cnt;
@@ -1814,27 +1791,24 @@ static int amd8111e_probe_one(struct pci
 {
 	int err, i;
 	unsigned long reg_addr,reg_len;
-	struct amd8111e_priv* lp;
-	struct net_device* dev;
+	struct amd8111e_priv *lp;
+	struct net_device *dev;
 
 	err = pci_enable_device(pdev);
 	if(err){
-		printk(KERN_ERR "amd8111e: Cannot enable new PCI device, "
-			"exiting.\n");
+		dev_err(&pdev->dev, "Cannot enable new PCI device\n");
 		return err;
 	}
 
 	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
-		printk(KERN_ERR "amd8111e: Cannot find PCI base address, "
-		       "exiting.\n");
+		dev_err(&pdev->dev, "Cannot find PCI base address\n");
 		err = -ENODEV;
 		goto err_disable_pdev;
 	}
 
 	err = pci_request_regions(pdev, MODULE_NAME);
 	if(err){
-		printk(KERN_ERR "amd8111e: Cannot obtain PCI resources, "
-		       "exiting.\n");
+		dev_err(&pdev->dev, "Cannot obtain PCI resources\n");
 		goto err_disable_pdev;
 	}
 
@@ -1842,16 +1816,14 @@ static int amd8111e_probe_one(struct pci
 
 	/* Find power-management capability. */
 	if (!pdev->pm_cap) {
-		printk(KERN_ERR "amd8111e: No Power Management capability, "
-		       "exiting.\n");
+		dev_err(&pdev->dev, "No Power Management capability\n");
 		err = -ENODEV;
 		goto err_free_reg;
 	}
 
 	/* Initialize DMA */
 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
-		printk(KERN_ERR "amd8111e: DMA not supported,"
-			"exiting.\n");
+		dev_err(&pdev->dev, "DMA not supported\n");
 		err = -ENODEV;
 		goto err_free_reg;
 	}
@@ -1878,10 +1850,9 @@ static int amd8111e_probe_one(struct pci
 
 	spin_lock_init(&lp->lock);
 
-	lp->mmio = ioremap(reg_addr, reg_len);
+	lp->mmio = devm_ioremap(&pdev->dev, reg_addr, reg_len);
 	if (!lp->mmio) {
-		printk(KERN_ERR "amd8111e: Cannot map device registers, "
-		       "exiting\n");
+		dev_err(&pdev->dev, "Cannot map device registers\n");
 		err = -ENOMEM;
 		goto err_free_dev;
 	}
@@ -1923,9 +1894,8 @@ static int amd8111e_probe_one(struct pci
 
 	err = register_netdev(dev);
 	if (err) {
-		printk(KERN_ERR "amd8111e: Cannot register net device, "
-		       "exiting.\n");
-		goto err_iounmap;
+		dev_err(&pdev->dev, "Cannot register net device\n");
+		goto err_free_dev;
 	}
 
 	pci_set_drvdata(pdev, dev);
@@ -1942,21 +1912,17 @@ static int amd8111e_probe_one(struct pci
 	}
 
 	/*  display driver and device information */
-
     	chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
-	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
-	       dev->name,MODULE_VERS);
-	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
-	       dev->name, chip_version, dev->dev_addr);
+	dev_info(&pdev->dev, "AMD-8111e Driver Version: %s\n", MODULE_VERS);
+	dev_info(&pdev->dev, "[ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
+		 chip_version, dev->dev_addr);
 	if (lp->ext_phy_id)
-		printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
-		       dev->name, lp->ext_phy_id, lp->ext_phy_addr);
+		dev_info(&pdev->dev, "Found MII PHY ID 0x%08x at address 0x%02x\n",
+			 lp->ext_phy_id, lp->ext_phy_addr);
 	else
-		printk(KERN_INFO "%s: Couldn't detect MII PHY, assuming address 0x01\n",
-		       dev->name);
+		dev_info(&pdev->dev, "Couldn't detect MII PHY, assuming address 0x01\n");
+
     	return 0;
-err_iounmap:
-	iounmap(lp->mmio);
 
 err_free_dev:
 	free_netdev(dev);
@@ -1970,6 +1936,29 @@ err_disable_pdev:
 
 }
 
+static void amd8111e_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (dev) {
+		unregister_netdev(dev);
+		free_netdev(dev);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+	}
+}
+
+static const struct pci_device_id amd8111e_pci_tbl[] = {
+	{
+	 .vendor = PCI_VENDOR_ID_AMD,
+	 .device = PCI_DEVICE_ID_AMD8111E_7462,
+	},
+	{
+	 .vendor = 0,
+	}
+};
+MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
+
 static struct pci_driver amd8111e_driver = {
 	.name   	= MODULE_NAME,
 	.id_table	= amd8111e_pci_tbl,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/au1000_eth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/au1000_eth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/au1000_eth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/au1000_eth.c	2014-09-28 17:29:07.000000000 -0400
@@ -89,6 +89,124 @@ MODULE_DESCRIPTION(DRV_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+/* AU1000 MAC registers and bits */
+#define MAC_CONTROL		0x0
+#  define MAC_RX_ENABLE		(1 << 2)
+#  define MAC_TX_ENABLE		(1 << 3)
+#  define MAC_DEF_CHECK		(1 << 5)
+#  define MAC_SET_BL(X)		(((X) & 0x3) << 6)
+#  define MAC_AUTO_PAD		(1 << 8)
+#  define MAC_DISABLE_RETRY	(1 << 10)
+#  define MAC_DISABLE_BCAST	(1 << 11)
+#  define MAC_LATE_COL		(1 << 12)
+#  define MAC_HASH_MODE		(1 << 13)
+#  define MAC_HASH_ONLY		(1 << 15)
+#  define MAC_PASS_ALL		(1 << 16)
+#  define MAC_INVERSE_FILTER	(1 << 17)
+#  define MAC_PROMISCUOUS	(1 << 18)
+#  define MAC_PASS_ALL_MULTI	(1 << 19)
+#  define MAC_FULL_DUPLEX	(1 << 20)
+#  define MAC_NORMAL_MODE	0
+#  define MAC_INT_LOOPBACK	(1 << 21)
+#  define MAC_EXT_LOOPBACK	(1 << 22)
+#  define MAC_DISABLE_RX_OWN	(1 << 23)
+#  define MAC_BIG_ENDIAN	(1 << 30)
+#  define MAC_RX_ALL		(1 << 31)
+#define MAC_ADDRESS_HIGH	0x4
+#define MAC_ADDRESS_LOW		0x8
+#define MAC_MCAST_HIGH		0xC
+#define MAC_MCAST_LOW		0x10
+#define MAC_MII_CNTRL		0x14
+#  define MAC_MII_BUSY		(1 << 0)
+#  define MAC_MII_READ		0
+#  define MAC_MII_WRITE		(1 << 1)
+#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
+#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
+#define MAC_MII_DATA		0x18
+#define MAC_FLOW_CNTRL		0x1C
+#  define MAC_FLOW_CNTRL_BUSY	(1 << 0)
+#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
+#  define MAC_PASS_CONTROL	(1 << 2)
+#  define MAC_SET_PAUSE(X)	(((X) & 0xffff) << 16)
+#define MAC_VLAN1_TAG		0x20
+#define MAC_VLAN2_TAG		0x24
+
+/* Ethernet Controller Enable */
+#  define MAC_EN_CLOCK_ENABLE	(1 << 0)
+#  define MAC_EN_RESET0		(1 << 1)
+#  define MAC_EN_TOSS		(0 << 2)
+#  define MAC_EN_CACHEABLE	(1 << 3)
+#  define MAC_EN_RESET1		(1 << 4)
+#  define MAC_EN_RESET2		(1 << 5)
+#  define MAC_DMA_RESET		(1 << 6)
+
+/* Ethernet Controller DMA Channels */
+/* offsets from MAC_TX_RING_ADDR address */
+#define MAC_TX_BUFF0_STATUS	0x0
+#  define TX_FRAME_ABORTED	(1 << 0)
+#  define TX_JAB_TIMEOUT	(1 << 1)
+#  define TX_NO_CARRIER		(1 << 2)
+#  define TX_LOSS_CARRIER	(1 << 3)
+#  define TX_EXC_DEF		(1 << 4)
+#  define TX_LATE_COLL_ABORT	(1 << 5)
+#  define TX_EXC_COLL		(1 << 6)
+#  define TX_UNDERRUN		(1 << 7)
+#  define TX_DEFERRED		(1 << 8)
+#  define TX_LATE_COLL		(1 << 9)
+#  define TX_COLL_CNT_MASK	(0xF << 10)
+#  define TX_PKT_RETRY		(1 << 31)
+#define MAC_TX_BUFF0_ADDR	0x4
+#  define TX_DMA_ENABLE		(1 << 0)
+#  define TX_T_DONE		(1 << 1)
+#  define TX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
+#define MAC_TX_BUFF0_LEN	0x8
+#define MAC_TX_BUFF1_STATUS	0x10
+#define MAC_TX_BUFF1_ADDR	0x14
+#define MAC_TX_BUFF1_LEN	0x18
+#define MAC_TX_BUFF2_STATUS	0x20
+#define MAC_TX_BUFF2_ADDR	0x24
+#define MAC_TX_BUFF2_LEN	0x28
+#define MAC_TX_BUFF3_STATUS	0x30
+#define MAC_TX_BUFF3_ADDR	0x34
+#define MAC_TX_BUFF3_LEN	0x38
+
+/* offsets from MAC_RX_RING_ADDR */
+#define MAC_RX_BUFF0_STATUS	0x0
+#  define RX_FRAME_LEN_MASK	0x3fff
+#  define RX_WDOG_TIMER		(1 << 14)
+#  define RX_RUNT		(1 << 15)
+#  define RX_OVERLEN		(1 << 16)
+#  define RX_COLL		(1 << 17)
+#  define RX_ETHER		(1 << 18)
+#  define RX_MII_ERROR		(1 << 19)
+#  define RX_DRIBBLING		(1 << 20)
+#  define RX_CRC_ERROR		(1 << 21)
+#  define RX_VLAN1		(1 << 22)
+#  define RX_VLAN2		(1 << 23)
+#  define RX_LEN_ERROR		(1 << 24)
+#  define RX_CNTRL_FRAME	(1 << 25)
+#  define RX_U_CNTRL_FRAME	(1 << 26)
+#  define RX_MCAST_FRAME	(1 << 27)
+#  define RX_BCAST_FRAME	(1 << 28)
+#  define RX_FILTER_FAIL	(1 << 29)
+#  define RX_PACKET_FILTER	(1 << 30)
+#  define RX_MISSED_FRAME	(1 << 31)
+
+#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
+		    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
+		    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
+#define MAC_RX_BUFF0_ADDR	0x4
+#  define RX_DMA_ENABLE		(1 << 0)
+#  define RX_T_DONE		(1 << 1)
+#  define RX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
+#  define RX_SET_BUFF_ADDR(X)	((X) & 0xffffffc0)
+#define MAC_RX_BUFF1_STATUS	0x10
+#define MAC_RX_BUFF1_ADDR	0x14
+#define MAC_RX_BUFF2_STATUS	0x20
+#define MAC_RX_BUFF2_ADDR	0x24
+#define MAC_RX_BUFF3_STATUS	0x30
+#define MAC_RX_BUFF3_ADDR	0x34
+
 /*
  * Theory of operation
  *
@@ -152,10 +270,12 @@ static void au1000_enable_mac(struct net
 
 	if (force_reset || (!aup->mac_enabled)) {
 		writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-		au_sync_delay(2);
+		wmb(); /* drain writebuffer */
+		mdelay(2);
 		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
 				| MAC_EN_CLOCK_ENABLE), aup->enable);
-		au_sync_delay(2);
+		wmb(); /* drain writebuffer */
+		mdelay(2);
 
 		aup->mac_enabled = 1;
 	}
@@ -273,7 +393,8 @@ static void au1000_hard_stop(struct net_
 	reg = readl(&aup->mac->control);
 	reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
 	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
+	wmb(); /* drain writebuffer */
+	mdelay(10);
 }
 
 static void au1000_enable_rx_tx(struct net_device *dev)
@@ -286,7 +407,8 @@ static void au1000_enable_rx_tx(struct n
 	reg = readl(&aup->mac->control);
 	reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
 	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
+	wmb(); /* drain writebuffer */
+	mdelay(10);
 }
 
 static void
@@ -336,7 +458,8 @@ au1000_adjust_link(struct net_device *de
 			reg |= MAC_DISABLE_RX_OWN;
 		}
 		writel(reg, &aup->mac->control);
-		au_sync_delay(1);
+		wmb(); /* drain writebuffer */
+		mdelay(1);
 
 		au1000_enable_rx_tx(dev);
 		aup->old_duplex = phydev->duplex;
@@ -500,9 +623,11 @@ static void au1000_reset_mac_unlocked(st
 	au1000_hard_stop(dev);
 
 	writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-	au_sync_delay(2);
+	wmb(); /* drain writebuffer */
+	mdelay(2);
 	writel(0, aup->enable);
-	au_sync_delay(2);
+	wmb(); /* drain writebuffer */
+	mdelay(2);
 
 	aup->tx_full = 0;
 	for (i = 0; i < NUM_RX_DMA; i++) {
@@ -652,7 +777,7 @@ static int au1000_init(struct net_device
 	for (i = 0; i < NUM_RX_DMA; i++)
 		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
 
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
@@ -669,7 +794,7 @@ static int au1000_init(struct net_device
 
 	writel(control, &aup->mac->control);
 	writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	spin_unlock_irqrestore(&aup->lock, flags);
 	return 0;
@@ -760,7 +885,7 @@ static int au1000_rx(struct net_device *
 		}
 		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
 		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/* next descriptor */
 		prxd = aup->rx_dma_ring[aup->rx_head];
@@ -808,7 +933,7 @@ static void au1000_tx_ack(struct net_dev
 		au1000_update_tx_stats(dev, ptxd->status);
 		ptxd->buff_stat &= ~TX_T_DONE;
 		ptxd->len = 0;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
 		ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -939,7 +1064,7 @@ static netdev_tx_t au1000_tx(struct sk_b
 	ps->tx_bytes += ptxd->len;
 
 	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dev_kfree_skb(skb);
 	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
 	return NETDEV_TX_OK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/declance.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/declance.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/declance.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/declance.c	2014-09-28 17:29:07.000000000 -0400
@@ -475,7 +475,7 @@ static void lance_init_ring(struct net_d
 	*lib_ptr(ib, rx_ptr, lp->type) = leptr;
 	if (ZERO)
 		printk("RX ptr: %8.8x(%8.8x)\n",
-		       leptr, lib_off(brx_ring, lp->type));
+		       leptr, (uint)lib_off(brx_ring, lp->type));
 
 	/* Setup tx descriptor pointer */
 	leptr = offsetof(struct lance_init_block, btx_ring);
@@ -484,7 +484,7 @@ static void lance_init_ring(struct net_d
 	*lib_ptr(ib, tx_ptr, lp->type) = leptr;
 	if (ZERO)
 		printk("TX ptr: %8.8x(%8.8x)\n",
-		       leptr, lib_off(btx_ring, lp->type));
+		       leptr, (uint)lib_off(btx_ring, lp->type));
 
 	if (ZERO)
 		printk("TX rings:\n");
@@ -499,8 +499,8 @@ static void lance_init_ring(struct net_d
 						/* The ones required by tmd2 */
 		*lib_ptr(ib, btx_ring[i].misc, lp->type) = 0;
 		if (i < 3 && ZERO)
-			printk("%d: 0x%8.8x(0x%8.8x)\n",
-			       i, leptr, (uint)lp->tx_buf_ptr_cpu[i]);
+			printk("%d: %8.8x(%p)\n",
+			       i, leptr, lp->tx_buf_ptr_cpu[i]);
 	}
 
 	/* Setup the Rx ring entries */
@@ -516,8 +516,8 @@ static void lance_init_ring(struct net_d
 							     0xf000;
 		*lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0;
 		if (i < 3 && ZERO)
-			printk("%d: 0x%8.8x(0x%8.8x)\n",
-			       i, leptr, (uint)lp->rx_buf_ptr_cpu[i]);
+			printk("%d: %8.8x(%p)\n",
+			       i, leptr, lp->rx_buf_ptr_cpu[i]);
 	}
 	iob();
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -182,6 +182,9 @@ config AMD_XGBE
 	depends on OF_NET
 	select PHYLIB
 	select AMD_XGBE_PHY
+	select BITREVERSE
+	select CRC32
+	select PTP_1588_CLOCK
 	---help---
 	  This driver supports the AMD 10GbE Ethernet device found on an
 	  AMD SoC.
@@ -189,4 +192,14 @@ config AMD_XGBE
 	  To compile this driver as a module, choose M here: the module
 	  will be called amd-xgbe.
 
+config AMD_XGBE_DCB
+	bool "Data Center Bridging (DCB) support"
+	default n
+	depends on AMD_XGBE && DCB
+	---help---
+	  Say Y here to enable Data Center Bridging (DCB) support in the
+	  driver.
+
+	  If unsure, say N.
+
 endif # NET_VENDOR_AMD
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/pcnet32.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/pcnet32.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/pcnet32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/pcnet32.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ static const char *const version =
 /*
  * PCI device identifiers for "new style" Linux PCI Device Drivers
  */
-static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = {
+static const struct pci_device_id pcnet32_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
 
@@ -481,37 +481,32 @@ static void pcnet32_realloc_tx_ring(stru
 	dma_addr_t *new_dma_addr_list;
 	struct pcnet32_tx_head *new_tx_ring;
 	struct sk_buff **new_skb_list;
+	unsigned int entries = BIT(size);
 
 	pcnet32_purge_tx_ring(dev);
 
-	new_tx_ring = pci_alloc_consistent(lp->pci_dev,
-					   sizeof(struct pcnet32_tx_head) *
-					   (1 << size),
-					   &new_ring_dma_addr);
-	if (new_tx_ring == NULL) {
-		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+	new_tx_ring =
+		pci_zalloc_consistent(lp->pci_dev,
+				      sizeof(struct pcnet32_tx_head) * entries,
+				      &new_ring_dma_addr);
+	if (new_tx_ring == NULL)
 		return;
-	}
-	memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
 
-	new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t),
-				    GFP_ATOMIC);
+	new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
 	if (!new_dma_addr_list)
 		goto free_new_tx_ring;
 
-	new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *),
-			       GFP_ATOMIC);
+	new_skb_list = kcalloc(entries, sizeof(struct sk_buff *), GFP_ATOMIC);
 	if (!new_skb_list)
 		goto free_new_lists;
 
 	kfree(lp->tx_skbuff);
 	kfree(lp->tx_dma_addr);
 	pci_free_consistent(lp->pci_dev,
-			    sizeof(struct pcnet32_tx_head) *
-			    lp->tx_ring_size, lp->tx_ring,
-			    lp->tx_ring_dma_addr);
+			    sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+			    lp->tx_ring, lp->tx_ring_dma_addr);
 
-	lp->tx_ring_size = (1 << size);
+	lp->tx_ring_size = entries;
 	lp->tx_mod_mask = lp->tx_ring_size - 1;
 	lp->tx_len_bits = (size << 12);
 	lp->tx_ring = new_tx_ring;
@@ -524,8 +519,7 @@ free_new_lists:
 	kfree(new_dma_addr_list);
 free_new_tx_ring:
 	pci_free_consistent(lp->pci_dev,
-			    sizeof(struct pcnet32_tx_head) *
-			    (1 << size),
+			    sizeof(struct pcnet32_tx_head) * entries,
 			    new_tx_ring,
 			    new_ring_dma_addr);
 }
@@ -549,17 +543,14 @@ static void pcnet32_realloc_rx_ring(stru
 	struct pcnet32_rx_head *new_rx_ring;
 	struct sk_buff **new_skb_list;
 	int new, overlap;
-	unsigned int entries = 1 << size;
+	unsigned int entries = BIT(size);
 
-	new_rx_ring = pci_alloc_consistent(lp->pci_dev,
-					   sizeof(struct pcnet32_rx_head) *
-					   entries,
-					   &new_ring_dma_addr);
-	if (new_rx_ring == NULL) {
-		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+	new_rx_ring =
+		pci_zalloc_consistent(lp->pci_dev,
+				      sizeof(struct pcnet32_rx_head) * entries,
+				      &new_ring_dma_addr);
+	if (new_rx_ring == NULL)
 		return;
-	}
-	memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * entries);
 
 	new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
 	if (!new_dma_addr_list)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,8 @@
 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-desc.o xgbe-ethtool.o xgbe-mdio.o \
+		 xgbe-ptp.o
 
+amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
 amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h	2014-09-28 17:29:07.000000000 -0400
@@ -170,6 +170,8 @@
 #define DMA_MR_SWR_WIDTH		1
 #define DMA_SBMR_EAME_INDEX		11
 #define DMA_SBMR_EAME_WIDTH		1
+#define DMA_SBMR_BLEN_256_INDEX		7
+#define DMA_SBMR_BLEN_256_WIDTH		1
 #define DMA_SBMR_UNDEF_INDEX		0
 #define DMA_SBMR_UNDEF_WIDTH		1
 
@@ -276,13 +278,6 @@
 #define MAC_PFR				0x0008
 #define MAC_WTR				0x000c
 #define MAC_HTR0			0x0010
-#define MAC_HTR1			0x0014
-#define MAC_HTR2			0x0018
-#define MAC_HTR3			0x001c
-#define MAC_HTR4			0x0020
-#define MAC_HTR5			0x0024
-#define MAC_HTR6			0x0028
-#define MAC_HTR7			0x002c
 #define MAC_VLANTR			0x0050
 #define MAC_VLANHTR			0x0058
 #define MAC_VLANIR			0x0060
@@ -312,9 +307,23 @@
 #define MAC_MACA0LR			0x0304
 #define MAC_MACA1HR			0x0308
 #define MAC_MACA1LR			0x030c
+#define MAC_TSCR			0x0d00
+#define MAC_SSIR			0x0d04
+#define MAC_STSR			0x0d08
+#define MAC_STNR			0x0d0c
+#define MAC_STSUR			0x0d10
+#define MAC_STNUR			0x0d14
+#define MAC_TSAR			0x0d18
+#define MAC_TSSR			0x0d20
+#define MAC_TXSNR			0x0d30
+#define MAC_TXSSR			0x0d34
 
 #define MAC_QTFCR_INC			4
 #define MAC_MACA_INC			4
+#define MAC_HTR_INC			4
+
+#define MAC_RQC2_INC			4
+#define MAC_RQC2_Q_PER_REG		4
 
 /* MAC register entry bit positions and sizes */
 #define MAC_HWF0R_ADDMACADRSEL_INDEX	18
@@ -355,6 +364,8 @@
 #define MAC_HWF1R_HASHTBLSZ_WIDTH	3
 #define MAC_HWF1R_L3L4FNUM_INDEX	27
 #define MAC_HWF1R_L3L4FNUM_WIDTH	4
+#define MAC_HWF1R_NUMTC_INDEX		21
+#define MAC_HWF1R_NUMTC_WIDTH		3
 #define MAC_HWF1R_RSSEN_INDEX		20
 #define MAC_HWF1R_RSSEN_WIDTH		1
 #define MAC_HWF1R_RXFIFOSIZE_INDEX	0
@@ -377,22 +388,30 @@
 #define MAC_HWF2R_TXCHCNT_WIDTH		4
 #define MAC_HWF2R_TXQCNT_INDEX		6
 #define MAC_HWF2R_TXQCNT_WIDTH		4
+#define MAC_IER_TSIE_INDEX		12
+#define MAC_IER_TSIE_WIDTH		1
 #define MAC_ISR_MMCRXIS_INDEX		9
 #define MAC_ISR_MMCRXIS_WIDTH		1
 #define MAC_ISR_MMCTXIS_INDEX		10
 #define MAC_ISR_MMCTXIS_WIDTH		1
 #define MAC_ISR_PMTIS_INDEX		4
 #define MAC_ISR_PMTIS_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_PFR_HMC_INDEX		2
 #define MAC_PFR_HMC_WIDTH		1
+#define MAC_PFR_HPF_INDEX		10
+#define MAC_PFR_HPF_WIDTH		1
 #define MAC_PFR_HUC_INDEX		1
 #define MAC_PFR_HUC_WIDTH		1
 #define MAC_PFR_PM_INDEX		4
 #define MAC_PFR_PM_WIDTH		1
 #define MAC_PFR_PR_INDEX		0
 #define MAC_PFR_PR_WIDTH		1
+#define MAC_PFR_VTFE_INDEX		16
+#define MAC_PFR_VTFE_WIDTH		1
 #define MAC_PMTCSR_MGKPKTEN_INDEX	1
 #define MAC_PMTCSR_MGKPKTEN_WIDTH	1
 #define MAC_PMTCSR_PWRDWN_INDEX		0
@@ -419,24 +438,80 @@
 #define MAC_RCR_LM_WIDTH		1
 #define MAC_RCR_RE_INDEX		0
 #define MAC_RCR_RE_WIDTH		1
+#define MAC_RFCR_PFCE_INDEX		8
+#define MAC_RFCR_PFCE_WIDTH		1
 #define MAC_RFCR_RFE_INDEX		0
 #define MAC_RFCR_RFE_WIDTH		1
+#define MAC_RFCR_UP_INDEX		1
+#define MAC_RFCR_UP_WIDTH		1
 #define MAC_RQC0R_RXQ0EN_INDEX		0
 #define MAC_RQC0R_RXQ0EN_WIDTH		2
+#define MAC_SSIR_SNSINC_INDEX		8
+#define MAC_SSIR_SNSINC_WIDTH		8
+#define MAC_SSIR_SSINC_INDEX		16
+#define MAC_SSIR_SSINC_WIDTH		8
 #define MAC_TCR_SS_INDEX		29
 #define MAC_TCR_SS_WIDTH		2
 #define MAC_TCR_TE_INDEX		0
 #define MAC_TCR_TE_WIDTH		1
+#define MAC_TSCR_AV8021ASMEN_INDEX	28
+#define MAC_TSCR_AV8021ASMEN_WIDTH	1
+#define MAC_TSCR_SNAPTYPSEL_INDEX	16
+#define MAC_TSCR_SNAPTYPSEL_WIDTH	2
+#define MAC_TSCR_TSADDREG_INDEX		5
+#define MAC_TSCR_TSADDREG_WIDTH		1
+#define MAC_TSCR_TSCFUPDT_INDEX		1
+#define MAC_TSCR_TSCFUPDT_WIDTH		1
+#define MAC_TSCR_TSCTRLSSR_INDEX	9
+#define MAC_TSCR_TSCTRLSSR_WIDTH	1
+#define MAC_TSCR_TSENA_INDEX		0
+#define MAC_TSCR_TSENA_WIDTH		1
+#define MAC_TSCR_TSENALL_INDEX		8
+#define MAC_TSCR_TSENALL_WIDTH		1
+#define MAC_TSCR_TSEVNTENA_INDEX	14
+#define MAC_TSCR_TSEVNTENA_WIDTH	1
+#define MAC_TSCR_TSINIT_INDEX		2
+#define MAC_TSCR_TSINIT_WIDTH		1
+#define MAC_TSCR_TSIPENA_INDEX		11
+#define MAC_TSCR_TSIPENA_WIDTH		1
+#define MAC_TSCR_TSIPV4ENA_INDEX	13
+#define MAC_TSCR_TSIPV4ENA_WIDTH	1
+#define MAC_TSCR_TSIPV6ENA_INDEX	12
+#define MAC_TSCR_TSIPV6ENA_WIDTH	1
+#define MAC_TSCR_TSMSTRENA_INDEX	15
+#define MAC_TSCR_TSMSTRENA_WIDTH	1
+#define MAC_TSCR_TSVER2ENA_INDEX	10
+#define MAC_TSCR_TSVER2ENA_WIDTH	1
+#define MAC_TSCR_TXTSSTSM_INDEX		24
+#define MAC_TSCR_TXTSSTSM_WIDTH		1
+#define MAC_TSSR_TXTSC_INDEX		15
+#define MAC_TSSR_TXTSC_WIDTH		1
+#define MAC_TXSNR_TXTSSTSMIS_INDEX	31
+#define MAC_TXSNR_TXTSSTSMIS_WIDTH	1
+#define MAC_VLANHTR_VLHT_INDEX		0
+#define MAC_VLANHTR_VLHT_WIDTH		16
+#define MAC_VLANIR_VLTI_INDEX		20
+#define MAC_VLANIR_VLTI_WIDTH		1
+#define MAC_VLANIR_CSVL_INDEX		19
+#define MAC_VLANIR_CSVL_WIDTH		1
 #define MAC_VLANTR_DOVLTC_INDEX		20
 #define MAC_VLANTR_DOVLTC_WIDTH		1
 #define MAC_VLANTR_ERSVLM_INDEX		19
 #define MAC_VLANTR_ERSVLM_WIDTH		1
 #define MAC_VLANTR_ESVL_INDEX		18
 #define MAC_VLANTR_ESVL_WIDTH		1
+#define MAC_VLANTR_ETV_INDEX		16
+#define MAC_VLANTR_ETV_WIDTH		1
 #define MAC_VLANTR_EVLS_INDEX		21
 #define MAC_VLANTR_EVLS_WIDTH		2
 #define MAC_VLANTR_EVLRXS_INDEX		24
 #define MAC_VLANTR_EVLRXS_WIDTH		1
+#define MAC_VLANTR_VL_INDEX		0
+#define MAC_VLANTR_VL_WIDTH		16
+#define MAC_VLANTR_VTHM_INDEX		25
+#define MAC_VLANTR_VTHM_WIDTH		1
+#define MAC_VLANTR_VTIM_INDEX		17
+#define MAC_VLANTR_VTIM_WIDTH		1
 #define MAC_VR_DEVID_INDEX		8
 #define MAC_VR_DEVID_WIDTH		8
 #define MAC_VR_SNPSVER_INDEX		0
@@ -638,6 +713,8 @@
 
 #define MTL_RQDCM_INC			4
 #define MTL_RQDCM_Q_PER_REG		4
+#define MTL_TCPM_INC			4
+#define MTL_TCPM_TC_PER_REG		4
 
 /* MTL register entry bit positions and sizes */
 #define MTL_OMR_ETSALG_INDEX		5
@@ -656,9 +733,6 @@
 #define MTL_Q_TQOMR			0x00
 #define MTL_Q_TQUR			0x04
 #define MTL_Q_TQDR			0x08
-#define MTL_Q_TCECR			0x10
-#define MTL_Q_TCESR			0x14
-#define MTL_Q_TCQWR			0x18
 #define MTL_Q_RQOMR			0x40
 #define MTL_Q_RQMPOCR			0x44
 #define MTL_Q_RQDR			0x4c
@@ -666,8 +740,6 @@
 #define MTL_Q_ISR			0x74
 
 /* MTL queue register entry bit positions and sizes */
-#define MTL_Q_TCQWR_QW_INDEX		0
-#define MTL_Q_TCQWR_QW_WIDTH		21
 #define MTL_Q_RQOMR_EHFC_INDEX		7
 #define MTL_Q_RQOMR_EHFC_WIDTH		1
 #define MTL_Q_RQOMR_RFA_INDEX		8
@@ -682,6 +754,8 @@
 #define MTL_Q_RQOMR_RTC_WIDTH		2
 #define MTL_Q_TQOMR_FTQ_INDEX		0
 #define MTL_Q_TQOMR_FTQ_WIDTH		1
+#define MTL_Q_TQOMR_Q2TCMAP_INDEX	8
+#define MTL_Q_TQOMR_Q2TCMAP_WIDTH	3
 #define MTL_Q_TQOMR_TQS_INDEX		16
 #define MTL_Q_TQOMR_TQS_WIDTH		10
 #define MTL_Q_TQOMR_TSF_INDEX		1
@@ -728,10 +802,14 @@
 #define MTL_TC_INC			MTL_Q_INC
 
 #define MTL_TC_ETSCR			0x10
+#define MTL_TC_ETSSR			0x14
+#define MTL_TC_QWR			0x18
 
 /* MTL traffic class register entry bit positions and sizes */
 #define MTL_TC_ETSCR_TSA_INDEX		0
 #define MTL_TC_ETSCR_TSA_WIDTH		2
+#define MTL_TC_QWR_QW_INDEX		0
+#define MTL_TC_QWR_QW_WIDTH		21
 
 /* MTL traffic class register value */
 #define MTL_TSA_SP			0x00
@@ -764,9 +842,19 @@
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH	1
 #define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX	2
 #define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH	1
+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX	3
+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH	1
+#define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX	4
+#define RX_PACKET_ATTRIBUTES_CONTEXT_WIDTH	1
+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_INDEX	5
+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH	1
 
 #define RX_NORMAL_DESC0_OVT_INDEX		0
 #define RX_NORMAL_DESC0_OVT_WIDTH		16
+#define RX_NORMAL_DESC3_CDA_INDEX		27
+#define RX_NORMAL_DESC3_CDA_WIDTH		1
+#define RX_NORMAL_DESC3_CTXT_INDEX		30
+#define RX_NORMAL_DESC3_CTXT_WIDTH		1
 #define RX_NORMAL_DESC3_ES_INDEX		15
 #define RX_NORMAL_DESC3_ES_WIDTH		1
 #define RX_NORMAL_DESC3_ETLT_INDEX		16
@@ -780,12 +868,19 @@
 #define RX_NORMAL_DESC3_PL_INDEX		0
 #define RX_NORMAL_DESC3_PL_WIDTH		14
 
+#define RX_CONTEXT_DESC3_TSA_INDEX		4
+#define RX_CONTEXT_DESC3_TSA_WIDTH		1
+#define RX_CONTEXT_DESC3_TSD_INDEX		6
+#define RX_CONTEXT_DESC3_TSD_WIDTH		1
+
 #define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_INDEX	0
 #define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_WIDTH	1
 #define TX_PACKET_ATTRIBUTES_TSO_ENABLE_INDEX	1
 #define TX_PACKET_ATTRIBUTES_TSO_ENABLE_WIDTH	1
 #define TX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX	2
 #define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH	1
+#define TX_PACKET_ATTRIBUTES_PTP_INDEX		3
+#define TX_PACKET_ATTRIBUTES_PTP_WIDTH		1
 
 #define TX_CONTEXT_DESC2_MSS_INDEX		0
 #define TX_CONTEXT_DESC2_MSS_WIDTH		15
@@ -802,6 +897,8 @@
 #define TX_NORMAL_DESC2_HL_B1L_WIDTH		14
 #define TX_NORMAL_DESC2_IC_INDEX		31
 #define TX_NORMAL_DESC2_IC_WIDTH		1
+#define TX_NORMAL_DESC2_TTSE_INDEX		30
+#define TX_NORMAL_DESC2_TTSE_WIDTH		1
 #define TX_NORMAL_DESC2_VTIR_INDEX		14
 #define TX_NORMAL_DESC2_VTIR_WIDTH		2
 #define TX_NORMAL_DESC3_CIC_INDEX		16
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,270 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014 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 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/netdevice.h>
+#include <net/dcbnl.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+
+static int xgbe_dcb_ieee_getets(struct net_device *netdev,
+				struct ieee_ets *ets)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+	/* Set number of supported traffic classes */
+	ets->ets_cap = pdata->hw_feat.tc_cnt;
+
+	if (pdata->ets) {
+		ets->cbs = pdata->ets->cbs;
+		memcpy(ets->tc_tx_bw, pdata->ets->tc_tx_bw,
+		       sizeof(ets->tc_tx_bw));
+		memcpy(ets->tc_tsa, pdata->ets->tc_tsa,
+		       sizeof(ets->tc_tsa));
+		memcpy(ets->prio_tc, pdata->ets->prio_tc,
+		       sizeof(ets->prio_tc));
+	}
+
+	return 0;
+}
+
+static int xgbe_dcb_ieee_setets(struct net_device *netdev,
+				struct ieee_ets *ets)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	unsigned int i, tc_ets, tc_ets_weight;
+
+	tc_ets = 0;
+	tc_ets_weight = 0;
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		DBGPR("  TC%u: tx_bw=%hhu, rx_bw=%hhu, tsa=%hhu\n", i,
+		      ets->tc_tx_bw[i], ets->tc_rx_bw[i], ets->tc_tsa[i]);
+		DBGPR("  PRIO%u: TC=%hhu\n", i, ets->prio_tc[i]);
+
+		if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) &&
+		    (i >= pdata->hw_feat.tc_cnt))
+				return -EINVAL;
+
+		if (ets->prio_tc[i] >= pdata->hw_feat.tc_cnt)
+			return -EINVAL;
+
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			break;
+		case IEEE_8021QAZ_TSA_ETS:
+			tc_ets = 1;
+			tc_ets_weight += ets->tc_tx_bw[i];
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/* Weights must add up to 100% */
+	if (tc_ets && (tc_ets_weight != 100))
+		return -EINVAL;
+
+	if (!pdata->ets) {
+		pdata->ets = devm_kzalloc(pdata->dev, sizeof(*pdata->ets),
+					  GFP_KERNEL);
+		if (!pdata->ets)
+			return -ENOMEM;
+	}
+
+	memcpy(pdata->ets, ets, sizeof(*pdata->ets));
+
+	pdata->hw_if.config_dcb_tc(pdata);
+
+	return 0;
+}
+
+static int xgbe_dcb_ieee_getpfc(struct net_device *netdev,
+				struct ieee_pfc *pfc)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+	/* Set number of supported PFC traffic classes */
+	pfc->pfc_cap = pdata->hw_feat.tc_cnt;
+
+	if (pdata->pfc) {
+		pfc->pfc_en = pdata->pfc->pfc_en;
+		pfc->mbc = pdata->pfc->mbc;
+		pfc->delay = pdata->pfc->delay;
+	}
+
+	return 0;
+}
+
+static int xgbe_dcb_ieee_setpfc(struct net_device *netdev,
+				struct ieee_pfc *pfc)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+	DBGPR("  cap=%hhu, en=%hhx, mbc=%hhu, delay=%hhu\n",
+	      pfc->pfc_cap, pfc->pfc_en, pfc->mbc, pfc->delay);
+
+	if (!pdata->pfc) {
+		pdata->pfc = devm_kzalloc(pdata->dev, sizeof(*pdata->pfc),
+					  GFP_KERNEL);
+		if (!pdata->pfc)
+			return -ENOMEM;
+	}
+
+	memcpy(pdata->pfc, pfc, sizeof(*pdata->pfc));
+
+	pdata->hw_if.config_dcb_pfc(pdata);
+
+	return 0;
+}
+
+static u8 xgbe_dcb_getdcbx(struct net_device *netdev)
+{
+	return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+}
+
+static u8 xgbe_dcb_setdcbx(struct net_device *netdev, u8 dcbx)
+{
+	u8 support = xgbe_dcb_getdcbx(netdev);
+
+	DBGPR("  DCBX=%#hhx\n", dcbx);
+
+	if (dcbx & ~support)
+		return 1;
+
+	if ((dcbx & support) != support)
+		return 1;
+
+	return 0;
+}
+
+static const struct dcbnl_rtnl_ops xgbe_dcbnl_ops = {
+	/* IEEE 802.1Qaz std */
+	.ieee_getets = xgbe_dcb_ieee_getets,
+	.ieee_setets = xgbe_dcb_ieee_setets,
+	.ieee_getpfc = xgbe_dcb_ieee_getpfc,
+	.ieee_setpfc = xgbe_dcb_ieee_setpfc,
+
+	/* DCBX configuration */
+	.getdcbx     = xgbe_dcb_getdcbx,
+	.setdcbx     = xgbe_dcb_setdcbx,
+};
+
+const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void)
+{
+	return &xgbe_dcbnl_ops;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -151,7 +151,7 @@ static ssize_t xgbe_common_write(const c
 {
 	char workarea[32];
 	ssize_t len;
-	unsigned int scan_value;
+	int ret;
 
 	if (*ppos != 0)
 		return 0;
@@ -165,9 +165,8 @@ static ssize_t xgbe_common_write(const c
 		return len;
 
 	workarea[len] = '\0';
-	if (sscanf(workarea, "%x", &scan_value) == 1)
-		*value = scan_value;
-	else
+	ret = kstrtouint(workarea, 16, value);
+	if (ret)
 		return -EIO;
 
 	return len;
@@ -273,8 +272,8 @@ static ssize_t xpcs_reg_value_read(struc
 	struct xgbe_prv_data *pdata = filp->private_data;
 	unsigned int value;
 
-	value = pdata->hw_if.read_mmd_regs(pdata, pdata->debugfs_xpcs_mmd,
-					   pdata->debugfs_xpcs_reg);
+	value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd,
+			   pdata->debugfs_xpcs_reg);
 
 	return xgbe_common_read(buffer, count, ppos, value);
 }
@@ -291,8 +290,8 @@ static ssize_t xpcs_reg_value_write(stru
 	if (len < 0)
 		return len;
 
-	pdata->hw_if.write_mmd_regs(pdata, pdata->debugfs_xpcs_mmd,
-				    pdata->debugfs_xpcs_reg, value);
+	XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg,
+		    value);
 
 	return len;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-desc.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-desc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-desc.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,7 +131,7 @@ static void xgbe_free_ring(struct xgbe_p
 
 	if (ring->rdata) {
 		for (i = 0; i < ring->rdesc_count; i++) {
-			rdata = GET_DESC_DATA(ring, i);
+			rdata = XGBE_GET_DESC_DATA(ring, i);
 			xgbe_unmap_skb(pdata, rdata);
 		}
 
@@ -256,7 +256,7 @@ static void xgbe_wrapper_tx_descriptor_i
 		rdesc_dma = ring->rdesc_dma;
 
 		for (j = 0; j < ring->rdesc_count; j++) {
-			rdata = GET_DESC_DATA(ring, j);
+			rdata = XGBE_GET_DESC_DATA(ring, j);
 
 			rdata->rdesc = rdesc;
 			rdata->rdesc_dma = rdesc_dma;
@@ -298,7 +298,7 @@ static void xgbe_wrapper_rx_descriptor_i
 		rdesc_dma = ring->rdesc_dma;
 
 		for (j = 0; j < ring->rdesc_count; j++) {
-			rdata = GET_DESC_DATA(ring, j);
+			rdata = XGBE_GET_DESC_DATA(ring, j);
 
 			rdata->rdesc = rdesc;
 			rdata->rdesc_dma = rdesc_dma;
@@ -359,6 +359,15 @@ static void xgbe_unmap_skb(struct xgbe_p
 	rdata->len = 0;
 	rdata->interrupt = 0;
 	rdata->mapped_as_page = 0;
+
+	if (rdata->state_saved) {
+		rdata->state_saved = 0;
+		rdata->state.incomplete = 0;
+		rdata->state.context_next = 0;
+		rdata->state.skb = NULL;
+		rdata->state.len = 0;
+		rdata->state.error = 0;
+	}
 }
 
 static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
@@ -392,7 +401,7 @@ static int xgbe_map_tx_skb(struct xgbe_c
 	if ((tso && (packet->mss != ring->tx.cur_mss)) ||
 	    (vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag)))
 		cur_index++;
-	rdata = GET_DESC_DATA(ring, cur_index);
+	rdata = XGBE_GET_DESC_DATA(ring, cur_index);
 
 	if (tso) {
 		DBGPR("  TSO packet\n");
@@ -413,12 +422,12 @@ static int xgbe_map_tx_skb(struct xgbe_c
 		packet->length += packet->header_len;
 
 		cur_index++;
-		rdata = GET_DESC_DATA(ring, cur_index);
+		rdata = XGBE_GET_DESC_DATA(ring, cur_index);
 	}
 
 	/* Map the (remainder of the) packet */
 	for (datalen = skb_headlen(skb) - offset; datalen; ) {
-		len = min_t(unsigned int, datalen, TX_MAX_BUF_SIZE);
+		len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE);
 
 		skb_dma = dma_map_single(pdata->dev, skb->data + offset, len,
 					 DMA_TO_DEVICE);
@@ -437,7 +446,7 @@ static int xgbe_map_tx_skb(struct xgbe_c
 		packet->length += len;
 
 		cur_index++;
-		rdata = GET_DESC_DATA(ring, cur_index);
+		rdata = XGBE_GET_DESC_DATA(ring, cur_index);
 	}
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -447,7 +456,8 @@ static int xgbe_map_tx_skb(struct xgbe_c
 		offset = 0;
 
 		for (datalen = skb_frag_size(frag); datalen; ) {
-			len = min_t(unsigned int, datalen, TX_MAX_BUF_SIZE);
+			len = min_t(unsigned int, datalen,
+				    XGBE_TX_MAX_BUF_SIZE);
 
 			skb_dma = skb_frag_dma_map(pdata->dev, frag, offset,
 						   len, DMA_TO_DEVICE);
@@ -468,7 +478,7 @@ static int xgbe_map_tx_skb(struct xgbe_c
 			packet->length += len;
 
 			cur_index++;
-			rdata = GET_DESC_DATA(ring, cur_index);
+			rdata = XGBE_GET_DESC_DATA(ring, cur_index);
 		}
 	}
 
@@ -484,7 +494,7 @@ static int xgbe_map_tx_skb(struct xgbe_c
 
 err_out:
 	while (start_index < cur_index) {
-		rdata = GET_DESC_DATA(ring, start_index++);
+		rdata = XGBE_GET_DESC_DATA(ring, start_index++);
 		xgbe_unmap_skb(pdata, rdata);
 	}
 
@@ -507,7 +517,7 @@ static void xgbe_realloc_skb(struct xgbe
 	      ring->rx.realloc_index);
 
 	for (i = 0; i < ring->dirty; i++) {
-		rdata = GET_DESC_DATA(ring, ring->rx.realloc_index);
+		rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index);
 
 		/* Reset rdata values */
 		xgbe_unmap_skb(pdata, rdata);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -116,6 +116,8 @@
 
 #include <linux/phy.h>
 #include <linux/clk.h>
+#include <linux/bitrev.h>
+#include <linux/crc32.h>
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -129,7 +131,7 @@ static unsigned int xgbe_usec_to_riwt(st
 
 	DBGPR("-->xgbe_usec_to_riwt\n");
 
-	rate = clk_get_rate(pdata->sysclock);
+	rate = clk_get_rate(pdata->sysclk);
 
 	/*
 	 * Convert the input usec value to the watchdog timer value. Each
@@ -152,7 +154,7 @@ static unsigned int xgbe_riwt_to_usec(st
 
 	DBGPR("-->xgbe_riwt_to_usec\n");
 
-	rate = clk_get_rate(pdata->sysclock);
+	rate = clk_get_rate(pdata->sysclk);
 
 	/*
 	 * Convert the input watchdog timer value to the usec value. Each
@@ -245,7 +247,7 @@ static int xgbe_config_rsf_mode(struct x
 {
 	unsigned int i;
 
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RSF, val);
 
 	return 0;
@@ -255,7 +257,7 @@ static int xgbe_config_tsf_mode(struct x
 {
 	unsigned int i;
 
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TSF, val);
 
 	return 0;
@@ -266,7 +268,7 @@ static int xgbe_config_rx_threshold(stru
 {
 	unsigned int i;
 
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RTC, val);
 
 	return 0;
@@ -277,7 +279,7 @@ static int xgbe_config_tx_threshold(stru
 {
 	unsigned int i;
 
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TTC, val);
 
 	return 0;
@@ -341,12 +343,12 @@ static int xgbe_disable_tx_flow_control(
 	unsigned int i;
 
 	/* Clear MTL flow control */
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
 
 	/* Clear MAC flow control */
 	max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-	q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt, max_q_count);
+	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
 	reg = MAC_Q0TFCR;
 	for (i = 0; i < q_count; i++) {
 		reg_val = XGMAC_IOREAD(pdata, reg);
@@ -366,12 +368,12 @@ static int xgbe_enable_tx_flow_control(s
 	unsigned int i;
 
 	/* Set MTL flow control */
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 1);
 
 	/* Set MAC flow control */
 	max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-	q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt, max_q_count);
+	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
 	reg = MAC_Q0TFCR;
 	for (i = 0; i < q_count; i++) {
 		reg_val = XGMAC_IOREAD(pdata, reg);
@@ -405,7 +407,9 @@ static int xgbe_enable_rx_flow_control(s
 
 static int xgbe_config_tx_flow_control(struct xgbe_prv_data *pdata)
 {
-	if (pdata->tx_pause)
+	struct ieee_pfc *pfc = pdata->pfc;
+
+	if (pdata->tx_pause || (pfc && pfc->pfc_en))
 		xgbe_enable_tx_flow_control(pdata);
 	else
 		xgbe_disable_tx_flow_control(pdata);
@@ -415,7 +419,9 @@ static int xgbe_config_tx_flow_control(s
 
 static int xgbe_config_rx_flow_control(struct xgbe_prv_data *pdata)
 {
-	if (pdata->rx_pause)
+	struct ieee_pfc *pfc = pdata->pfc;
+
+	if (pdata->rx_pause || (pfc && pfc->pfc_en))
 		xgbe_enable_rx_flow_control(pdata);
 	else
 		xgbe_disable_rx_flow_control(pdata);
@@ -425,8 +431,13 @@ static int xgbe_config_rx_flow_control(s
 
 static void xgbe_config_flow_control(struct xgbe_prv_data *pdata)
 {
+	struct ieee_pfc *pfc = pdata->pfc;
+
 	xgbe_config_tx_flow_control(pdata);
 	xgbe_config_rx_flow_control(pdata);
+
+	XGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE,
+			   (pfc && pfc->pfc_en) ? 1 : 0);
 }
 
 static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
@@ -484,18 +495,22 @@ static void xgbe_enable_mtl_interrupts(s
 		XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, mtl_q_isr);
 
 		/* No MTL interrupts to be enabled */
-		XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, 0);
+		XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_IER, 0);
 	}
 }
 
 static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
 {
-	/* No MAC interrupts to be enabled */
-	XGMAC_IOWRITE(pdata, MAC_IER, 0);
+	unsigned int mac_ier = 0;
+
+	/* Enable Timestamp interrupt */
+	XGMAC_SET_BITS(mac_ier, MAC_IER, TSIE, 1);
+
+	XGMAC_IOWRITE(pdata, MAC_IER, mac_ier);
 
 	/* Enable all counter interrupts */
-	XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xff);
-	XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xff);
+	XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff);
+	XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
 }
 
 static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
@@ -547,24 +562,16 @@ static int xgbe_set_all_multicast_mode(s
 	return 0;
 }
 
-static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata,
-				   unsigned int am_mode)
+static void xgbe_set_mac_reg(struct xgbe_prv_data *pdata,
+			     struct netdev_hw_addr *ha, unsigned int *mac_reg)
 {
-	struct netdev_hw_addr *ha;
-	unsigned int mac_reg;
 	unsigned int mac_addr_hi, mac_addr_lo;
 	u8 *mac_addr;
-	unsigned int i;
-
-	XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 0);
-	XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 0);
 
-	i = 0;
-	mac_reg = MAC_MACA1HR;
+	mac_addr_lo = 0;
+	mac_addr_hi = 0;
 
-	netdev_for_each_uc_addr(ha, pdata->netdev) {
-		mac_addr_lo = 0;
-		mac_addr_hi = 0;
+	if (ha) {
 		mac_addr = (u8 *)&mac_addr_lo;
 		mac_addr[0] = ha->addr[0];
 		mac_addr[1] = ha->addr[1];
@@ -574,54 +581,93 @@ static int xgbe_set_addn_mac_addrs(struc
 		mac_addr[0] = ha->addr[4];
 		mac_addr[1] = ha->addr[5];
 
-		DBGPR("  adding unicast address %pM at 0x%04x\n",
-		      ha->addr, mac_reg);
+		DBGPR("  adding mac address %pM at 0x%04x\n", ha->addr,
+		      *mac_reg);
 
 		XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
-
-		XGMAC_IOWRITE(pdata, mac_reg, mac_addr_hi);
-		mac_reg += MAC_MACA_INC;
-		XGMAC_IOWRITE(pdata, mac_reg, mac_addr_lo);
-		mac_reg += MAC_MACA_INC;
-
-		i++;
 	}
 
-	if (!am_mode) {
-		netdev_for_each_mc_addr(ha, pdata->netdev) {
-			mac_addr_lo = 0;
-			mac_addr_hi = 0;
-			mac_addr = (u8 *)&mac_addr_lo;
-			mac_addr[0] = ha->addr[0];
-			mac_addr[1] = ha->addr[1];
-			mac_addr[2] = ha->addr[2];
-			mac_addr[3] = ha->addr[3];
-			mac_addr = (u8 *)&mac_addr_hi;
-			mac_addr[0] = ha->addr[4];
-			mac_addr[1] = ha->addr[5];
+	XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_hi);
+	*mac_reg += MAC_MACA_INC;
+	XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_lo);
+	*mac_reg += MAC_MACA_INC;
+}
 
-			DBGPR("  adding multicast address %pM at 0x%04x\n",
-			      ha->addr, mac_reg);
+static void xgbe_set_mac_addn_addrs(struct xgbe_prv_data *pdata)
+{
+	struct net_device *netdev = pdata->netdev;
+	struct netdev_hw_addr *ha;
+	unsigned int mac_reg;
+	unsigned int addn_macs;
 
-			XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
+	mac_reg = MAC_MACA1HR;
+	addn_macs = pdata->hw_feat.addn_mac;
 
-			XGMAC_IOWRITE(pdata, mac_reg, mac_addr_hi);
-			mac_reg += MAC_MACA_INC;
-			XGMAC_IOWRITE(pdata, mac_reg, mac_addr_lo);
-			mac_reg += MAC_MACA_INC;
+	if (netdev_uc_count(netdev) > addn_macs) {
+		xgbe_set_promiscuous_mode(pdata, 1);
+	} else {
+		netdev_for_each_uc_addr(ha, netdev) {
+			xgbe_set_mac_reg(pdata, ha, &mac_reg);
+			addn_macs--;
+		}
 
-			i++;
+		if (netdev_mc_count(netdev) > addn_macs) {
+			xgbe_set_all_multicast_mode(pdata, 1);
+		} else {
+			netdev_for_each_mc_addr(ha, netdev) {
+				xgbe_set_mac_reg(pdata, ha, &mac_reg);
+				addn_macs--;
+			}
 		}
 	}
 
 	/* Clear remaining additional MAC address entries */
-	for (; i < pdata->hw_feat.addn_mac; i++) {
-		XGMAC_IOWRITE(pdata, mac_reg, 0);
-		mac_reg += MAC_MACA_INC;
-		XGMAC_IOWRITE(pdata, mac_reg, 0);
-		mac_reg += MAC_MACA_INC;
+	while (addn_macs--)
+		xgbe_set_mac_reg(pdata, NULL, &mac_reg);
+}
+
+static void xgbe_set_mac_hash_table(struct xgbe_prv_data *pdata)
+{
+	struct net_device *netdev = pdata->netdev;
+	struct netdev_hw_addr *ha;
+	unsigned int hash_reg;
+	unsigned int hash_table_shift, hash_table_count;
+	u32 hash_table[XGBE_MAC_HASH_TABLE_SIZE];
+	u32 crc;
+	unsigned int i;
+
+	hash_table_shift = 26 - (pdata->hw_feat.hash_table_size >> 7);
+	hash_table_count = pdata->hw_feat.hash_table_size / 32;
+	memset(hash_table, 0, sizeof(hash_table));
+
+	/* Build the MAC Hash Table register values */
+	netdev_for_each_uc_addr(ha, netdev) {
+		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
+		crc >>= hash_table_shift;
+		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
 	}
 
+	netdev_for_each_mc_addr(ha, netdev) {
+		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
+		crc >>= hash_table_shift;
+		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
+	}
+
+	/* Set the MAC Hash Table registers */
+	hash_reg = MAC_HTR0;
+	for (i = 0; i < hash_table_count; i++) {
+		XGMAC_IOWRITE(pdata, hash_reg, hash_table[i]);
+		hash_reg += MAC_HTR_INC;
+	}
+}
+
+static int xgbe_add_mac_addresses(struct xgbe_prv_data *pdata)
+{
+	if (pdata->hw_feat.hash_table_size)
+		xgbe_set_mac_hash_table(pdata);
+	else
+		xgbe_set_mac_addn_addrs(pdata);
+
 	return 0;
 }
 
@@ -738,6 +784,89 @@ static int xgbe_disable_rx_vlan_strippin
 	return 0;
 }
 
+static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+{
+	/* Enable VLAN filtering */
+	XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1);
+
+	/* Enable VLAN Hash Table filtering */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1);
+
+	/* Disable VLAN tag inverse matching */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0);
+
+	/* Only filter on the lower 12-bits of the VLAN tag */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1);
+
+	/* In order for the VLAN Hash Table filtering to be effective,
+	 * the VLAN tag identifier in the VLAN Tag Register must not
+	 * be zero.  Set the VLAN tag identifier to "1" to enable the
+	 * VLAN Hash Table filtering.  This implies that a VLAN tag of
+	 * 1 will always pass filtering.
+	 */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1);
+
+	return 0;
+}
+
+static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+{
+	/* Disable VLAN filtering */
+	XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0);
+
+	return 0;
+}
+
+#ifndef CRCPOLY_LE
+#define CRCPOLY_LE 0xedb88320
+#endif
+static u32 xgbe_vid_crc32_le(__le16 vid_le)
+{
+	u32 poly = CRCPOLY_LE;
+	u32 crc = ~0;
+	u32 temp = 0;
+	unsigned char *data = (unsigned char *)&vid_le;
+	unsigned char data_byte = 0;
+	int i, bits;
+
+	bits = get_bitmask_order(VLAN_VID_MASK);
+	for (i = 0; i < bits; i++) {
+		if ((i % 8) == 0)
+			data_byte = data[i / 8];
+
+		temp = ((crc & 1) ^ data_byte) & 1;
+		crc >>= 1;
+		data_byte >>= 1;
+
+		if (temp)
+			crc ^= poly;
+	}
+
+	return crc;
+}
+
+static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata)
+{
+	u32 crc;
+	u16 vid;
+	__le16 vid_le;
+	u16 vlan_hash_table = 0;
+
+	/* Generate the VLAN Hash Table value */
+	for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) {
+		/* Get the CRC32 value of the VLAN ID */
+		vid_le = cpu_to_le16(vid);
+		crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28;
+
+		vlan_hash_table |= (1 << crc);
+	}
+
+	/* Set the VLAN Hash Table filtering register */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table);
+
+	return 0;
+}
+
 static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata)
 {
 	struct xgbe_ring_desc *rdesc = rdata->rdesc;
@@ -766,7 +895,7 @@ static void xgbe_tx_desc_init(struct xgb
 
 	/* Initialze all descriptors */
 	for (i = 0; i < ring->rdesc_count; i++) {
-		rdata = GET_DESC_DATA(ring, i);
+		rdata = XGBE_GET_DESC_DATA(ring, i);
 		rdesc = rdata->rdesc;
 
 		/* Initialize Tx descriptor
@@ -791,7 +920,7 @@ static void xgbe_tx_desc_init(struct xgb
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_TDRLR, ring->rdesc_count - 1);
 
 	/* Update the starting address of descriptor ring */
-	rdata = GET_DESC_DATA(ring, start_index);
+	rdata = XGBE_GET_DESC_DATA(ring, start_index);
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_HI,
 			  upper_32_bits(rdata->rdesc_dma));
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_LO,
@@ -848,7 +977,7 @@ static void xgbe_rx_desc_init(struct xgb
 
 	/* Initialize all descriptors */
 	for (i = 0; i < ring->rdesc_count; i++) {
-		rdata = GET_DESC_DATA(ring, i);
+		rdata = XGBE_GET_DESC_DATA(ring, i);
 		rdesc = rdata->rdesc;
 
 		/* Initialize Rx descriptor
@@ -882,20 +1011,194 @@ static void xgbe_rx_desc_init(struct xgb
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_RDRLR, ring->rdesc_count - 1);
 
 	/* Update the starting address of descriptor ring */
-	rdata = GET_DESC_DATA(ring, start_index);
+	rdata = XGBE_GET_DESC_DATA(ring, start_index);
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_HI,
 			  upper_32_bits(rdata->rdesc_dma));
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_LO,
 			  lower_32_bits(rdata->rdesc_dma));
 
 	/* Update the Rx Descriptor Tail Pointer */
-	rdata = GET_DESC_DATA(ring, start_index + ring->rdesc_count - 1);
+	rdata = XGBE_GET_DESC_DATA(ring, start_index + ring->rdesc_count - 1);
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
 			  lower_32_bits(rdata->rdesc_dma));
 
 	DBGPR("<--rx_desc_init\n");
 }
 
+static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
+				      unsigned int addend)
+{
+	/* Set the addend register value and tell the device */
+	XGMAC_IOWRITE(pdata, MAC_TSAR, addend);
+	XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1);
+
+	/* Wait for addend update to complete */
+	while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
+		udelay(5);
+}
+
+static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
+				 unsigned int nsec)
+{
+	/* Set the time values and tell the device */
+	XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
+	XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
+	XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1);
+
+	/* Wait for time update to complete */
+	while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
+		udelay(5);
+}
+
+static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)
+{
+	u64 nsec;
+
+	nsec = XGMAC_IOREAD(pdata, MAC_STSR);
+	nsec *= NSEC_PER_SEC;
+	nsec += XGMAC_IOREAD(pdata, MAC_STNR);
+
+	return nsec;
+}
+
+static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
+{
+	unsigned int tx_snr;
+	u64 nsec;
+
+	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 *= NSEC_PER_SEC;
+	nsec += tx_snr;
+
+	return nsec;
+}
+
+static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
+			       struct xgbe_ring_desc *rdesc)
+{
+	u64 nsec;
+
+	if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
+	    !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
+		nsec = le32_to_cpu(rdesc->desc1);
+		nsec <<= 32;
+		nsec |= le32_to_cpu(rdesc->desc0);
+		if (nsec != 0xffffffffffffffffULL) {
+			packet->rx_tstamp = nsec;
+			XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+				       RX_TSTAMP, 1);
+		}
+	}
+}
+
+static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
+			      unsigned int mac_tscr)
+{
+	/* Set one nano-second accuracy */
+	XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
+
+	/* Set fine timestamp update */
+	XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
+
+	/* Overwrite earlier timestamps */
+	XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
+
+	XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
+
+	/* Exit if timestamping is not enabled */
+	if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
+		return 0;
+
+	/* Initialize time registers */
+	XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
+	XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
+	xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
+	xgbe_set_tstamp_time(pdata, 0, 0);
+
+	/* Initialize the timecounter */
+	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+			 ktime_to_ns(ktime_get_real()));
+
+	return 0;
+}
+
+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 i;
+
+	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++) {
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			DBGPR("  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);
+
+			DBGPR("  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;
+		}
+	}
+}
+
+static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
+{
+	struct ieee_pfc *pfc = pdata->pfc;
+	struct ieee_ets *ets = pdata->ets;
+	unsigned int mask, reg, reg_val;
+	unsigned int tc, prio;
+
+	if (!pfc || !ets)
+		return;
+
+	for (tc = 0; tc < pdata->hw_feat.tc_cnt; tc++) {
+		mask = 0;
+		for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+			if ((pfc->pfc_en & (1 << prio)) &&
+			    (ets->prio_tc[prio] == tc))
+				mask |= (1 << prio);
+		}
+		mask &= 0xff;
+
+		DBGPR("  TC%u PFC mask=%#x\n", tc, mask);
+		reg = MTL_TCPM0R + (MTL_TCPM_INC * (tc / MTL_TCPM_TC_PER_REG));
+		reg_val = XGMAC_IOREAD(pdata, reg);
+
+		reg_val &= ~(0xff << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+		reg_val |= (mask << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+
+		XGMAC_IOWRITE(pdata, reg, reg_val);
+	}
+
+	xgbe_config_flow_control(pdata);
+}
+
 static void xgbe_pre_xmit(struct xgbe_channel *channel)
 {
 	struct xgbe_prv_data *pdata = channel->pdata;
@@ -933,7 +1236,7 @@ static void xgbe_pre_xmit(struct xgbe_ch
 	if (tx_coalesce && !channel->tx_timer_active)
 		ring->coalesce_count = 0;
 
-	rdata = GET_DESC_DATA(ring, ring->cur);
+	rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 	rdesc = rdata->rdesc;
 
 	/* Create a context descriptor if this is a TSO packet */
@@ -977,7 +1280,7 @@ static void xgbe_pre_xmit(struct xgbe_ch
 		}
 
 		ring->cur++;
-		rdata = GET_DESC_DATA(ring, ring->cur);
+		rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 		rdesc = rdata->rdesc;
 	}
 
@@ -994,6 +1297,10 @@ static void xgbe_pre_xmit(struct xgbe_ch
 		XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, VTIR,
 				  TX_NORMAL_DESC2_VLAN_INSERT);
 
+	/* Timestamp enablement check */
+	if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
+		XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
+
 	/* Set IC bit based on Tx coalescing settings */
 	XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
 	if (tx_coalesce && (!tx_frames ||
@@ -1034,7 +1341,7 @@ static void xgbe_pre_xmit(struct xgbe_ch
 
 	for (i = ring->cur - start_index + 1; i < packet->rdesc_count; i++) {
 		ring->cur++;
-		rdata = GET_DESC_DATA(ring, ring->cur);
+		rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 		rdesc = rdata->rdesc;
 
 		/* Update buffer address */
@@ -1074,7 +1381,7 @@ static void xgbe_pre_xmit(struct xgbe_ch
 	wmb();
 
 	/* Set OWN bit for the first descriptor */
-	rdata = GET_DESC_DATA(ring, start_index);
+	rdata = XGBE_GET_DESC_DATA(ring, start_index);
 	rdesc = rdata->rdesc;
 	XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
 
@@ -1088,7 +1395,7 @@ static void xgbe_pre_xmit(struct xgbe_ch
 	/* Issue a poll command to Tx DMA by writing address
 	 * of next immediate free descriptor */
 	ring->cur++;
-	rdata = GET_DESC_DATA(ring, ring->cur);
+	rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 	XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
 			  lower_32_bits(rdata->rdesc_dma));
 
@@ -1113,11 +1420,12 @@ static int xgbe_dev_read(struct xgbe_cha
 	struct xgbe_ring_data *rdata;
 	struct xgbe_ring_desc *rdesc;
 	struct xgbe_packet_data *packet = &ring->packet_data;
+	struct net_device *netdev = channel->pdata->netdev;
 	unsigned int err, etlt;
 
 	DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur);
 
-	rdata = GET_DESC_DATA(ring, ring->cur);
+	rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 	rdesc = rdata->rdesc;
 
 	/* Check for data availability */
@@ -1128,6 +1436,25 @@ static int xgbe_dev_read(struct xgbe_cha
 	xgbe_dump_rx_desc(ring, rdesc, ring->cur);
 #endif
 
+	if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CTXT)) {
+		/* Timestamp Context Descriptor */
+		xgbe_get_rx_tstamp(packet, rdesc);
+
+		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+			       CONTEXT, 1);
+		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+			       CONTEXT_NEXT, 0);
+		return 0;
+	}
+
+	/* Normal Descriptor, be sure Context Descriptor bit is off */
+	XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT, 0);
+
+	/* Indicate if a Context Descriptor is next */
+	if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CDA))
+		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+			       CONTEXT_NEXT, 1);
+
 	/* Get the packet length */
 	rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
 
@@ -1153,7 +1480,8 @@ static int xgbe_dev_read(struct xgbe_cha
 	DBGPR("  err=%u, etlt=%#x\n", err, etlt);
 
 	if (!err || (err && !etlt)) {
-		if (etlt == 0x09) {
+		if ((etlt == 0x09) &&
+		    (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
 			XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
 				       VLAN_CTAG, 1);
 			packet->vlan_ctag = XGMAC_GET_BITS_LE(rdesc->desc0,
@@ -1188,56 +1516,48 @@ static int xgbe_is_last_desc(struct xgbe
 	return XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD);
 }
 
-static void xgbe_save_interrupt_status(struct xgbe_channel *channel,
-				       enum xgbe_int_state int_state)
+static int xgbe_enable_int(struct xgbe_channel *channel,
+			   enum xgbe_int int_id)
 {
 	unsigned int dma_ch_ier;
 
-	if (int_state == XGMAC_INT_STATE_SAVE) {
-		channel->saved_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-		channel->saved_ier &= DMA_INTERRUPT_MASK;
-	} else {
-		dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-		dma_ch_ier |= channel->saved_ier;
-		XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
-	}
-}
+	dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
 
-static int xgbe_enable_int(struct xgbe_channel *channel,
-			   enum xgbe_int int_id)
-{
 	switch (int_id) {
-	case XGMAC_INT_DMA_ISR_DC0IS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 1);
-		break;
 	case XGMAC_INT_DMA_CH_SR_TI:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_TPS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TXSE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_TBU:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TBUE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RI:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RIE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RBU:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RBUE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RPS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RSE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 1);
+		break;
+	case XGMAC_INT_DMA_CH_SR_TI_RI:
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
 		break;
 	case XGMAC_INT_DMA_CH_SR_FBE:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, FBEE, 1);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1);
 		break;
 	case XGMAC_INT_DMA_ALL:
-		xgbe_save_interrupt_status(channel, XGMAC_INT_STATE_RESTORE);
+		dma_ch_ier |= channel->saved_ier;
 		break;
 	default:
 		return -1;
 	}
 
+	XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+
 	return 0;
 }
 
@@ -1246,42 +1566,44 @@ static int xgbe_disable_int(struct xgbe_
 {
 	unsigned int dma_ch_ier;
 
+	dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
+
 	switch (int_id) {
-	case XGMAC_INT_DMA_ISR_DC0IS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 0);
-		break;
 	case XGMAC_INT_DMA_CH_SR_TI:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_TPS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TXSE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_TBU:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TBUE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RI:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RIE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RBU:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RBUE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_RPS:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RSE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 0);
+		break;
+	case XGMAC_INT_DMA_CH_SR_TI_RI:
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0);
 		break;
 	case XGMAC_INT_DMA_CH_SR_FBE:
-		XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, FBEE, 0);
+		XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 0);
 		break;
 	case XGMAC_INT_DMA_ALL:
-		xgbe_save_interrupt_status(channel, XGMAC_INT_STATE_SAVE);
-
-		dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-		dma_ch_ier &= ~DMA_INTERRUPT_MASK;
-		XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+		channel->saved_ier = dma_ch_ier & XGBE_DMA_INTERRUPT_MASK;
+		dma_ch_ier &= ~XGBE_DMA_INTERRUPT_MASK;
 		break;
 	default:
 		return -1;
 	}
 
+	XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+
 	return 0;
 }
 
@@ -1311,11 +1633,14 @@ static int xgbe_flush_tx_queues(struct x
 {
 	unsigned int i, count;
 
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) < 0x21)
+		return 0;
+
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, FTQ, 1);
 
 	/* Poll Until Poll Condition */
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++) {
+	for (i = 0; i < pdata->tx_q_count; i++) {
 		count = 2000;
 		while (count-- && XGMAC_MTL_IOREAD_BITS(pdata, i,
 							MTL_Q_TQOMR, FTQ))
@@ -1335,6 +1660,7 @@ static void xgbe_config_dma_bus(struct x
 
 	/* Set the System Bus mode */
 	XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1);
+	XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1);
 }
 
 static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
@@ -1342,23 +1668,23 @@ static void xgbe_config_dma_cache(struct
 	unsigned int arcache, awcache;
 
 	arcache = 0;
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, DMA_ARCACHE_SETTING);
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, DMA_ARDOMAIN_SETTING);
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, DMA_ARCACHE_SETTING);
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, DMA_ARDOMAIN_SETTING);
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, DMA_ARCACHE_SETTING);
-	XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, DMA_ARDOMAIN_SETTING);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache);
+	XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain);
 	XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache);
 
 	awcache = 0;
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, DMA_AWCACHE_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, DMA_AWDOMAIN_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, DMA_AWCACHE_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, DMA_AWDOMAIN_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, DMA_AWCACHE_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, DMA_AWDOMAIN_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, DMA_AWCACHE_SETTING);
-	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, DMA_AWDOMAIN_SETTING);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache);
+	XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain);
 	XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache);
 }
 
@@ -1366,21 +1692,22 @@ static void xgbe_config_mtl_mode(struct
 {
 	unsigned int i;
 
-	/* Set Tx to weighted round robin scheduling algorithm (when
-	 * traffic class is using ETS algorithm)
-	 */
+	/* Set Tx to weighted round robin scheduling algorithm */
 	XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_WRR);
 
-	/* Set Tx traffic classes to strict priority algorithm */
-	for (i = 0; i < XGBE_TC_CNT; i++)
-		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, MTL_TSA_SP);
+	/* Set Tx traffic classes to use WRR algorithm with equal weights */
+	for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+				       MTL_TSA_ETS);
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, 1);
+	}
 
 	/* Set Rx to strict priority algorithm */
 	XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
 }
 
-static unsigned int xgbe_calculate_per_queue_fifo(unsigned long fifo_size,
-						  unsigned char queue_count)
+static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
+						  unsigned int queue_count)
 {
 	unsigned int q_fifo_size = 0;
 	enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256;
@@ -1388,66 +1715,70 @@ static unsigned int xgbe_calculate_per_q
 	/* Calculate Tx/Rx fifo share per queue */
 	switch (fifo_size) {
 	case 0:
-		q_fifo_size = FIFO_SIZE_B(128);
+		q_fifo_size = XGBE_FIFO_SIZE_B(128);
 		break;
 	case 1:
-		q_fifo_size = FIFO_SIZE_B(256);
+		q_fifo_size = XGBE_FIFO_SIZE_B(256);
 		break;
 	case 2:
-		q_fifo_size = FIFO_SIZE_B(512);
+		q_fifo_size = XGBE_FIFO_SIZE_B(512);
 		break;
 	case 3:
-		q_fifo_size = FIFO_SIZE_KB(1);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(1);
 		break;
 	case 4:
-		q_fifo_size = FIFO_SIZE_KB(2);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(2);
 		break;
 	case 5:
-		q_fifo_size = FIFO_SIZE_KB(4);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(4);
 		break;
 	case 6:
-		q_fifo_size = FIFO_SIZE_KB(8);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(8);
 		break;
 	case 7:
-		q_fifo_size = FIFO_SIZE_KB(16);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(16);
 		break;
 	case 8:
-		q_fifo_size = FIFO_SIZE_KB(32);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(32);
 		break;
 	case 9:
-		q_fifo_size = FIFO_SIZE_KB(64);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(64);
 		break;
 	case 10:
-		q_fifo_size = FIFO_SIZE_KB(128);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(128);
 		break;
 	case 11:
-		q_fifo_size = FIFO_SIZE_KB(256);
+		q_fifo_size = XGBE_FIFO_SIZE_KB(256);
 		break;
 	}
+
+	/* The configured value is not the actual amount of fifo RAM */
+	q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size);
+
 	q_fifo_size = q_fifo_size / queue_count;
 
 	/* Set the queue fifo size programmable value */
-	if (q_fifo_size >= FIFO_SIZE_KB(256))
+	if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_256K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(128))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_128K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(64))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_64K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(32))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_32K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(16))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_16K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(8))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_8K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(4))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_4K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(2))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_2K;
-	else if (q_fifo_size >= FIFO_SIZE_KB(1))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_1K;
-	else if (q_fifo_size >= FIFO_SIZE_B(512))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_512;
-	else if (q_fifo_size >= FIFO_SIZE_B(256))
+	else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256))
 		p_fifo = XGMAC_MTL_FIFO_SIZE_256;
 
 	return p_fifo;
@@ -1459,13 +1790,13 @@ static void xgbe_config_tx_fifo_size(str
 	unsigned int i;
 
 	fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
-						  pdata->hw_feat.tx_q_cnt);
+						  pdata->tx_q_count);
 
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size);
 
 	netdev_notice(pdata->netdev, "%d Tx queues, %d byte fifo per queue\n",
-		      pdata->hw_feat.tx_q_cnt, ((fifo_size + 1) * 256));
+		      pdata->tx_q_count, ((fifo_size + 1) * 256));
 }
 
 static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
@@ -1474,27 +1805,84 @@ static void xgbe_config_rx_fifo_size(str
 	unsigned int i;
 
 	fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
-						  pdata->hw_feat.rx_q_cnt);
+						  pdata->rx_q_count);
 
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size);
 
 	netdev_notice(pdata->netdev, "%d Rx queues, %d byte fifo per queue\n",
-		      pdata->hw_feat.rx_q_cnt, ((fifo_size + 1) * 256));
+		      pdata->rx_q_count, ((fifo_size + 1) * 256));
 }
 
-static void xgbe_config_rx_queue_mapping(struct xgbe_prv_data *pdata)
+static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
 {
-	unsigned int i, reg, reg_val;
-	unsigned int q_count = pdata->hw_feat.rx_q_cnt;
+	unsigned int qptc, qptc_extra, queue;
+	unsigned int prio_queues;
+	unsigned int ppq, ppq_extra, prio;
+	unsigned int mask;
+	unsigned int i, j, reg, reg_val;
+
+	/* Map the MTL Tx Queues to Traffic Classes
+	 *   Note: Tx Queues >= Traffic Classes
+	 */
+	qptc = pdata->tx_q_count / pdata->hw_feat.tc_cnt;
+	qptc_extra = pdata->tx_q_count % pdata->hw_feat.tc_cnt;
+
+	for (i = 0, queue = 0; i < pdata->hw_feat.tc_cnt; i++) {
+		for (j = 0; j < qptc; j++) {
+			DBGPR("  TXq%u mapped to TC%u\n", queue, i);
+			XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
+					       Q2TCMAP, i);
+			pdata->q2tc_map[queue++] = i;
+		}
+
+		if (i < qptc_extra) {
+			DBGPR("  TXq%u mapped to TC%u\n", queue, i);
+			XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
+					       Q2TCMAP, i);
+			pdata->q2tc_map[queue++] = i;
+		}
+	}
+
+	/* 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);
+	ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
+	ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;
+
+	reg = MAC_RQC2R;
+	reg_val = 0;
+	for (i = 0, prio = 0; i < prio_queues;) {
+		mask = 0;
+		for (j = 0; j < ppq; j++) {
+			DBGPR("  PRIO%u mapped to RXq%u\n", prio, i);
+			mask |= (1 << prio);
+			pdata->prio2q_map[prio++] = i;
+		}
+
+		if (i < ppq_extra) {
+			DBGPR("  PRIO%u mapped to RXq%u\n", prio, i);
+			mask |= (1 << prio);
+			pdata->prio2q_map[prio++] = i;
+		}
+
+		reg_val |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3));
+
+		if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues))
+			continue;
+
+		XGMAC_IOWRITE(pdata, reg, reg_val);
+		reg += MAC_RQC2_INC;
+		reg_val = 0;
+	}
 
 	/* Select dynamic mapping of MTL Rx queue to DMA Rx channel */
 	reg = MTL_RQDCM0R;
 	reg_val = 0;
-	for (i = 0; i < q_count;) {
+	for (i = 0; i < pdata->rx_q_count;) {
 		reg_val |= (0x80 << ((i++ % MTL_RQDCM_Q_PER_REG) << 3));
 
-		if ((i % MTL_RQDCM_Q_PER_REG) && (i != q_count))
+		if ((i % MTL_RQDCM_Q_PER_REG) && (i != pdata->rx_q_count))
 			continue;
 
 		XGMAC_IOWRITE(pdata, reg, reg_val);
@@ -1508,7 +1896,7 @@ static void xgbe_config_flow_control_thr
 {
 	unsigned int i;
 
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; 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_RQOMR, RFA, 2);
 
@@ -1520,6 +1908,13 @@ static void xgbe_config_flow_control_thr
 static void xgbe_config_mac_address(struct xgbe_prv_data *pdata)
 {
 	xgbe_set_mac_address(pdata, pdata->netdev->dev_addr);
+
+	/* Filtering is done using perfect filtering and hash filtering */
+	if (pdata->hw_feat.hash_table_size) {
+		XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1);
+		XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 1);
+		XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 1);
+	}
 }
 
 static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata)
@@ -1541,12 +1936,50 @@ static void xgbe_config_checksum_offload
 
 static void xgbe_config_vlan_support(struct xgbe_prv_data *pdata)
 {
+	/* Indicate that VLAN Tx CTAGs come from context descriptors */
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, CSVL, 0);
+	XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, VLTI, 1);
+
+	/* Set the current VLAN Hash Table register value */
+	xgbe_update_vlan_hash_table(pdata);
+
+	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+		xgbe_enable_rx_vlan_filtering(pdata);
+	else
+		xgbe_disable_rx_vlan_filtering(pdata);
+
 	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
 		xgbe_enable_rx_vlan_stripping(pdata);
 	else
 		xgbe_disable_rx_vlan_stripping(pdata);
 }
 
+static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo)
+{
+	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;
+
+	default:
+		read_hi = false;
+	};
+
+	val = XGMAC_IOREAD(pdata, reg_lo);
+
+	if (read_hi)
+		val |= ((u64)XGMAC_IOREAD(pdata, reg_lo + 4) << 32);
+
+	return val;
+}
+
 static void xgbe_tx_mmc_int(struct xgbe_prv_data *pdata)
 {
 	struct xgbe_mmc_stats *stats = &pdata->mmc_stats;
@@ -1554,75 +1987,75 @@ static void xgbe_tx_mmc_int(struct xgbe_
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_GB))
 		stats->txoctetcount_gb +=
-			XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_GB))
 		stats->txframecount_gb +=
-			XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_G))
 		stats->txbroadcastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_G))
 		stats->txmulticastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX64OCTETS_GB))
 		stats->tx64octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX64OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX65TO127OCTETS_GB))
 		stats->tx65to127octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX65TO127OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX128TO255OCTETS_GB))
 		stats->tx128to255octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX128TO255OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX256TO511OCTETS_GB))
 		stats->tx256to511octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX256TO511OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX512TO1023OCTETS_GB))
 		stats->tx512to1023octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX512TO1023OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX1024TOMAXOCTETS_GB))
 		stats->tx1024tomaxoctets_gb +=
-			XGMAC_IOREAD(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNICASTFRAMES_GB))
 		stats->txunicastframes_gb +=
-			XGMAC_IOREAD(pdata, MMC_TXUNICASTFRAMES_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_GB))
 		stats->txmulticastframes_gb +=
-			XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_GB))
 		stats->txbroadcastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
+			xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNDERFLOWERROR))
 		stats->txunderflowerror +=
-			XGMAC_IOREAD(pdata, MMC_TXUNDERFLOWERROR_LO);
+			xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_G))
 		stats->txoctetcount_g +=
-			XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_G_LO);
+			xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_G))
 		stats->txframecount_g +=
-			XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_G_LO);
+			xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXPAUSEFRAMES))
 		stats->txpauseframes +=
-			XGMAC_IOREAD(pdata, MMC_TXPAUSEFRAMES_LO);
+			xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXVLANFRAMES_G))
 		stats->txvlanframes_g +=
-			XGMAC_IOREAD(pdata, MMC_TXVLANFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
 }
 
 static void xgbe_rx_mmc_int(struct xgbe_prv_data *pdata)
@@ -1632,95 +2065,95 @@ static void xgbe_rx_mmc_int(struct xgbe_
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFRAMECOUNT_GB))
 		stats->rxframecount_gb +=
-			XGMAC_IOREAD(pdata, MMC_RXFRAMECOUNT_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_GB))
 		stats->rxoctetcount_gb +=
-			XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_G))
 		stats->rxoctetcount_g +=
-			XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_G_LO);
+			xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXBROADCASTFRAMES_G))
 		stats->rxbroadcastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_RXBROADCASTFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXMULTICASTFRAMES_G))
 		stats->rxmulticastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_RXMULTICASTFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXCRCERROR))
 		stats->rxcrcerror +=
-			XGMAC_IOREAD(pdata, MMC_RXCRCERROR_LO);
+			xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXRUNTERROR))
 		stats->rxrunterror +=
-			XGMAC_IOREAD(pdata, MMC_RXRUNTERROR);
+			xgbe_mmc_read(pdata, MMC_RXRUNTERROR);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXJABBERERROR))
 		stats->rxjabbererror +=
-			XGMAC_IOREAD(pdata, MMC_RXJABBERERROR);
+			xgbe_mmc_read(pdata, MMC_RXJABBERERROR);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNDERSIZE_G))
 		stats->rxundersize_g +=
-			XGMAC_IOREAD(pdata, MMC_RXUNDERSIZE_G);
+			xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOVERSIZE_G))
 		stats->rxoversize_g +=
-			XGMAC_IOREAD(pdata, MMC_RXOVERSIZE_G);
+			xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX64OCTETS_GB))
 		stats->rx64octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX64OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX65TO127OCTETS_GB))
 		stats->rx65to127octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX65TO127OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX128TO255OCTETS_GB))
 		stats->rx128to255octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX128TO255OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX256TO511OCTETS_GB))
 		stats->rx256to511octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX256TO511OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX512TO1023OCTETS_GB))
 		stats->rx512to1023octets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX512TO1023OCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX1024TOMAXOCTETS_GB))
 		stats->rx1024tomaxoctets_gb +=
-			XGMAC_IOREAD(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNICASTFRAMES_G))
 		stats->rxunicastframes_g +=
-			XGMAC_IOREAD(pdata, MMC_RXUNICASTFRAMES_G_LO);
+			xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXLENGTHERROR))
 		stats->rxlengtherror +=
-			XGMAC_IOREAD(pdata, MMC_RXLENGTHERROR_LO);
+			xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOUTOFRANGETYPE))
 		stats->rxoutofrangetype +=
-			XGMAC_IOREAD(pdata, MMC_RXOUTOFRANGETYPE_LO);
+			xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXPAUSEFRAMES))
 		stats->rxpauseframes +=
-			XGMAC_IOREAD(pdata, MMC_RXPAUSEFRAMES_LO);
+			xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFIFOOVERFLOW))
 		stats->rxfifooverflow +=
-			XGMAC_IOREAD(pdata, MMC_RXFIFOOVERFLOW_LO);
+			xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXVLANFRAMES_GB))
 		stats->rxvlanframes_gb +=
-			XGMAC_IOREAD(pdata, MMC_RXVLANFRAMES_GB_LO);
+			xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
 
 	if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXWATCHDOGERROR))
 		stats->rxwatchdogerror +=
-			XGMAC_IOREAD(pdata, MMC_RXWATCHDOGERROR);
+			xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR);
 }
 
 static void xgbe_read_mmc_stats(struct xgbe_prv_data *pdata)
@@ -1731,127 +2164,127 @@ static void xgbe_read_mmc_stats(struct x
 	XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 1);
 
 	stats->txoctetcount_gb +=
-		XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
 
 	stats->txframecount_gb +=
-		XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
 
 	stats->txbroadcastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
 
 	stats->txmulticastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
 
 	stats->tx64octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX64OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
 
 	stats->tx65to127octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX65TO127OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
 
 	stats->tx128to255octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX128TO255OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
 
 	stats->tx256to511octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX256TO511OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
 
 	stats->tx512to1023octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX512TO1023OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
 
 	stats->tx1024tomaxoctets_gb +=
-		XGMAC_IOREAD(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
 
 	stats->txunicastframes_gb +=
-		XGMAC_IOREAD(pdata, MMC_TXUNICASTFRAMES_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
 
 	stats->txmulticastframes_gb +=
-		XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
 
 	stats->txbroadcastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
+		xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
 
 	stats->txunderflowerror +=
-		XGMAC_IOREAD(pdata, MMC_TXUNDERFLOWERROR_LO);
+		xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
 
 	stats->txoctetcount_g +=
-		XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_G_LO);
+		xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
 
 	stats->txframecount_g +=
-		XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_G_LO);
+		xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
 
 	stats->txpauseframes +=
-		XGMAC_IOREAD(pdata, MMC_TXPAUSEFRAMES_LO);
+		xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
 
 	stats->txvlanframes_g +=
-		XGMAC_IOREAD(pdata, MMC_TXVLANFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
 
 	stats->rxframecount_gb +=
-		XGMAC_IOREAD(pdata, MMC_RXFRAMECOUNT_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
 
 	stats->rxoctetcount_gb +=
-		XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
 
 	stats->rxoctetcount_g +=
-		XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_G_LO);
+		xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
 
 	stats->rxbroadcastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_RXBROADCASTFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
 
 	stats->rxmulticastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_RXMULTICASTFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
 
 	stats->rxcrcerror +=
-		XGMAC_IOREAD(pdata, MMC_RXCRCERROR_LO);
+		xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO);
 
 	stats->rxrunterror +=
-		XGMAC_IOREAD(pdata, MMC_RXRUNTERROR);
+		xgbe_mmc_read(pdata, MMC_RXRUNTERROR);
 
 	stats->rxjabbererror +=
-		XGMAC_IOREAD(pdata, MMC_RXJABBERERROR);
+		xgbe_mmc_read(pdata, MMC_RXJABBERERROR);
 
 	stats->rxundersize_g +=
-		XGMAC_IOREAD(pdata, MMC_RXUNDERSIZE_G);
+		xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G);
 
 	stats->rxoversize_g +=
-		XGMAC_IOREAD(pdata, MMC_RXOVERSIZE_G);
+		xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G);
 
 	stats->rx64octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX64OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
 
 	stats->rx65to127octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX65TO127OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
 
 	stats->rx128to255octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX128TO255OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
 
 	stats->rx256to511octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX256TO511OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
 
 	stats->rx512to1023octets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX512TO1023OCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
 
 	stats->rx1024tomaxoctets_gb +=
-		XGMAC_IOREAD(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
 
 	stats->rxunicastframes_g +=
-		XGMAC_IOREAD(pdata, MMC_RXUNICASTFRAMES_G_LO);
+		xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
 
 	stats->rxlengtherror +=
-		XGMAC_IOREAD(pdata, MMC_RXLENGTHERROR_LO);
+		xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
 
 	stats->rxoutofrangetype +=
-		XGMAC_IOREAD(pdata, MMC_RXOUTOFRANGETYPE_LO);
+		xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
 
 	stats->rxpauseframes +=
-		XGMAC_IOREAD(pdata, MMC_RXPAUSEFRAMES_LO);
+		xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
 
 	stats->rxfifooverflow +=
-		XGMAC_IOREAD(pdata, MMC_RXFIFOOVERFLOW_LO);
+		xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
 
 	stats->rxvlanframes_gb +=
-		XGMAC_IOREAD(pdata, MMC_RXVLANFRAMES_GB_LO);
+		xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
 
 	stats->rxwatchdogerror +=
-		XGMAC_IOREAD(pdata, MMC_RXWATCHDOGERROR);
+		xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR);
 
 	/* Un-freeze counters */
 	XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 0);
@@ -1881,7 +2314,7 @@ static void xgbe_enable_tx(struct xgbe_p
 	}
 
 	/* Enable each Tx queue */
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
 				       MTL_Q_ENABLED);
 
@@ -1898,7 +2331,7 @@ static void xgbe_disable_tx(struct xgbe_
 	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
 
 	/* Disable each Tx queue */
-	for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+	for (i = 0; i < pdata->tx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, 0);
 
 	/* Disable each Tx DMA channel */
@@ -1927,7 +2360,7 @@ static void xgbe_enable_rx(struct xgbe_p
 
 	/* Enable each Rx queue */
 	reg_val = 0;
-	for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+	for (i = 0; i < pdata->rx_q_count; i++)
 		reg_val |= (0x02 << (i << 1));
 	XGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val);
 
@@ -2061,9 +2494,7 @@ static int xgbe_init(struct xgbe_prv_dat
 	 * Initialize MTL related features
 	 */
 	xgbe_config_mtl_mode(pdata);
-	xgbe_config_rx_queue_mapping(pdata);
-	/*TODO: Program the priorities mapped to the Selected Traffic Classes
-		in MTL_TC_Prty_Map0-3 registers */
+	xgbe_config_queue_mapping(pdata);
 	xgbe_config_tsf_mode(pdata, pdata->tx_sf_mode);
 	xgbe_config_rsf_mode(pdata, pdata->rx_sf_mode);
 	xgbe_config_tx_threshold(pdata, pdata->tx_threshold);
@@ -2071,15 +2502,13 @@ static int xgbe_init(struct xgbe_prv_dat
 	xgbe_config_tx_fifo_size(pdata);
 	xgbe_config_rx_fifo_size(pdata);
 	xgbe_config_flow_control_threshold(pdata);
-	/*TODO: Queue to Traffic Class Mapping (Q2TCMAP) */
 	/*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);
 
-	/* Transmit Class Weight */
-	XGMAC_IOWRITE_BITS(pdata, MTL_Q_TCQWR, QW, 0x10);
-
 	/*
 	 * Initialize MAC related features
 	 */
@@ -2104,7 +2533,7 @@ void xgbe_init_function_ptrs_dev(struct
 
 	hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode;
 	hw_if->set_all_multicast_mode = xgbe_set_all_multicast_mode;
-	hw_if->set_addn_mac_addrs = xgbe_set_addn_mac_addrs;
+	hw_if->add_mac_addresses = xgbe_add_mac_addresses;
 	hw_if->set_mac_address = xgbe_set_mac_address;
 
 	hw_if->enable_rx_csum = xgbe_enable_rx_csum;
@@ -2112,6 +2541,9 @@ void xgbe_init_function_ptrs_dev(struct
 
 	hw_if->enable_rx_vlan_stripping = xgbe_enable_rx_vlan_stripping;
 	hw_if->disable_rx_vlan_stripping = xgbe_disable_rx_vlan_stripping;
+	hw_if->enable_rx_vlan_filtering = xgbe_enable_rx_vlan_filtering;
+	hw_if->disable_rx_vlan_filtering = xgbe_disable_rx_vlan_filtering;
+	hw_if->update_vlan_hash_table = xgbe_update_vlan_hash_table;
 
 	hw_if->read_mmd_regs = xgbe_read_mmd_regs;
 	hw_if->write_mmd_regs = xgbe_write_mmd_regs;
@@ -2178,5 +2610,16 @@ void xgbe_init_function_ptrs_dev(struct
 	hw_if->rx_mmc_int = xgbe_rx_mmc_int;
 	hw_if->read_mmc_stats = xgbe_read_mmc_stats;
 
+	/* For PTP config */
+	hw_if->config_tstamp = xgbe_config_tstamp;
+	hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
+	hw_if->set_tstamp_time = xgbe_set_tstamp_time;
+	hw_if->get_tstamp_time = xgbe_get_tstamp_time;
+	hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
+
+	/* For Data Center Bridging config */
+	hw_if->config_dcb_tc = xgbe_config_dcb_tc;
+	hw_if->config_dcb_pfc = xgbe_config_dcb_pfc;
+
 	DBGPR("<--xgbe_init_function_ptrs\n");
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,10 +117,11 @@
 #include <linux/spinlock.h>
 #include <linux/tcp.h>
 #include <linux/if_vlan.h>
-#include <linux/phy.h>
 #include <net/busy_poll.h>
 #include <linux/clk.h>
 #include <linux/if_ether.h>
+#include <linux/net_tstamp.h>
+#include <linux/phy.h>
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -144,9 +145,10 @@ static int xgbe_calc_rx_buf_size(struct
 	}
 
 	rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-	if (rx_buf_size < RX_MIN_BUF_SIZE)
-		rx_buf_size = RX_MIN_BUF_SIZE;
-	rx_buf_size = (rx_buf_size + RX_BUF_ALIGN - 1) & ~(RX_BUF_ALIGN - 1);
+	if (rx_buf_size < XGBE_RX_MIN_BUF_SIZE)
+		rx_buf_size = XGBE_RX_MIN_BUF_SIZE;
+	rx_buf_size = (rx_buf_size + XGBE_RX_BUF_ALIGN - 1) &
+		      ~(XGBE_RX_BUF_ALIGN - 1);
 
 	return rx_buf_size;
 }
@@ -155,16 +157,21 @@ static void xgbe_enable_rx_tx_ints(struc
 {
 	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)
-			hw_if->enable_int(channel,
-					  XGMAC_INT_DMA_CH_SR_TI);
-		if (channel->rx_ring)
-			hw_if->enable_int(channel,
-					  XGMAC_INT_DMA_CH_SR_RI);
+		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;
+
+		hw_if->enable_int(channel, int_id);
 	}
 }
 
@@ -172,16 +179,21 @@ static void xgbe_disable_rx_tx_ints(stru
 {
 	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)
-			hw_if->disable_int(channel,
-					   XGMAC_INT_DMA_CH_SR_TI);
-		if (channel->rx_ring)
-			hw_if->disable_int(channel,
-					   XGMAC_INT_DMA_CH_SR_RI);
+		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;
+
+		hw_if->disable_int(channel, int_id);
 	}
 }
 
@@ -191,7 +203,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;
+	unsigned int mac_isr, mac_tssr;
 	unsigned int i;
 
 	/* The DMA interrupt status register also reports MAC and MTL
@@ -244,6 +256,17 @@ static irqreturn_t xgbe_isr(int irq, voi
 
 		if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCRXIS))
 			hw_if->rx_mmc_int(pdata);
+
+		if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) {
+			mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR);
+
+			if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
+				/* Read Tx Timestamp to clear interrupt */
+				pdata->tx_tstamp =
+					hw_if->get_tx_tstamp(pdata);
+				schedule_work(&pdata->tx_tstamp_work);
+			}
+		}
 	}
 
 	DBGPR("  DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR));
@@ -338,6 +361,8 @@ void xgbe_get_all_hw_features(struct xgb
 
 	memset(hw_feat, 0, sizeof(*hw_feat));
 
+	hw_feat->version = XGMAC_IOREAD(pdata, MAC_VR);
+
 	/* Hardware feature register 0 */
 	hw_feat->gmii        = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, GMIISEL);
 	hw_feat->vlhash      = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, VLHASH);
@@ -364,6 +389,7 @@ void xgbe_get_all_hw_features(struct xgb
 	hw_feat->sph           = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN);
 	hw_feat->tso           = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN);
 	hw_feat->dma_debug     = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DBGMEMA);
+	hw_feat->tc_cnt	       = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, NUMTC);
 	hw_feat->hash_table_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
 						  HASHTBLSZ);
 	hw_feat->l3l4_filter_num = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
@@ -377,6 +403,21 @@ void xgbe_get_all_hw_features(struct xgb
 	hw_feat->pps_out_num  = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM);
 	hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM);
 
+	/* Translate the Hash Table size into actual number */
+	switch (hw_feat->hash_table_size) {
+	case 0:
+		break;
+	case 1:
+		hw_feat->hash_table_size = 64;
+		break;
+	case 2:
+		hw_feat->hash_table_size = 128;
+		break;
+	case 3:
+		hw_feat->hash_table_size = 256;
+		break;
+	}
+
 	/* The Queue and Channel counts are zero based so increment them
 	 * to get the actual number
 	 */
@@ -396,9 +437,12 @@ static void xgbe_napi_enable(struct xgbe
 	napi_enable(&pdata->napi);
 }
 
-static void xgbe_napi_disable(struct xgbe_prv_data *pdata)
+static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del)
 {
 	napi_disable(&pdata->napi);
+
+	if (del)
+		netif_napi_del(&pdata->napi);
 }
 
 void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata)
@@ -446,7 +490,7 @@ static void xgbe_free_tx_skbuff(struct x
 			break;
 
 		for (j = 0; j < ring->rdesc_count; j++) {
-			rdata = GET_DESC_DATA(ring, j);
+			rdata = XGBE_GET_DESC_DATA(ring, j);
 			desc_if->unmap_skb(pdata, rdata);
 		}
 	}
@@ -471,7 +515,7 @@ static void xgbe_free_rx_skbuff(struct x
 			break;
 
 		for (j = 0; j < ring->rdesc_count; j++) {
-			rdata = GET_DESC_DATA(ring, j);
+			rdata = XGBE_GET_DESC_DATA(ring, j);
 			desc_if->unmap_skb(pdata, rdata);
 		}
 	}
@@ -479,6 +523,114 @@ static void xgbe_free_rx_skbuff(struct x
 	DBGPR("<--xgbe_free_rx_skbuff\n");
 }
 
+static void xgbe_adjust_link(struct net_device *netdev)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	struct xgbe_hw_if *hw_if = &pdata->hw_if;
+	struct phy_device *phydev = pdata->phydev;
+	int new_state = 0;
+
+	if (phydev == NULL)
+		return;
+
+	if (phydev->link) {
+		/* Flow control support */
+		if (pdata->pause_autoneg) {
+			if (phydev->pause || phydev->asym_pause) {
+				pdata->tx_pause = 1;
+				pdata->rx_pause = 1;
+			} else {
+				pdata->tx_pause = 0;
+				pdata->rx_pause = 0;
+			}
+		}
+
+		if (pdata->tx_pause != pdata->phy_tx_pause) {
+			hw_if->config_tx_flow_control(pdata);
+			pdata->phy_tx_pause = pdata->tx_pause;
+		}
+
+		if (pdata->rx_pause != pdata->phy_rx_pause) {
+			hw_if->config_rx_flow_control(pdata);
+			pdata->phy_rx_pause = pdata->rx_pause;
+		}
+
+		/* Speed support */
+		if (phydev->speed != pdata->phy_speed) {
+			new_state = 1;
+
+			switch (phydev->speed) {
+			case SPEED_10000:
+				hw_if->set_xgmii_speed(pdata);
+				break;
+
+			case SPEED_2500:
+				hw_if->set_gmii_2500_speed(pdata);
+				break;
+
+			case SPEED_1000:
+				hw_if->set_gmii_speed(pdata);
+				break;
+			}
+			pdata->phy_speed = phydev->speed;
+		}
+
+		if (phydev->link != pdata->phy_link) {
+			new_state = 1;
+			pdata->phy_link = 1;
+		}
+	} else if (pdata->phy_link) {
+		new_state = 1;
+		pdata->phy_link = 0;
+		pdata->phy_speed = SPEED_UNKNOWN;
+	}
+
+	if (new_state)
+		phy_print_status(phydev);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+	struct net_device *netdev = pdata->netdev;
+	struct phy_device *phydev = pdata->phydev;
+	int ret;
+
+	pdata->phy_link = -1;
+	pdata->phy_speed = SPEED_UNKNOWN;
+	pdata->phy_tx_pause = pdata->tx_pause;
+	pdata->phy_rx_pause = pdata->rx_pause;
+
+	ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
+				 pdata->phy_mode);
+	if (ret) {
+		netdev_err(netdev, "phy_connect_direct failed\n");
+		return ret;
+	}
+
+	if (!phydev->drv || (phydev->drv->phy_id == 0)) {
+		netdev_err(netdev, "phy_id not valid\n");
+		ret = -ENODEV;
+		goto err_phy_connect;
+	}
+	DBGPR("  phy_connect_direct succeeded for PHY %s, link=%d\n",
+	      dev_name(&phydev->dev), phydev->link);
+
+	return 0;
+
+err_phy_connect:
+	phy_disconnect(phydev);
+
+	return ret;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+	if (!pdata->phydev)
+		return;
+
+	phy_disconnect(pdata->phydev);
+}
+
 int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
@@ -502,7 +654,7 @@ int xgbe_powerdown(struct net_device *ne
 		netif_device_detach(netdev);
 
 	netif_tx_stop_all_queues(netdev);
-	xgbe_napi_disable(pdata);
+	xgbe_napi_disable(pdata, 0);
 
 	/* Powerdown Tx/Rx */
 	hw_if->powerdown_tx(pdata);
@@ -591,7 +743,7 @@ static void xgbe_stop(struct xgbe_prv_da
 	phy_stop(pdata->phydev);
 
 	netif_tx_stop_all_queues(netdev);
-	xgbe_napi_disable(pdata);
+	xgbe_napi_disable(pdata, 1);
 
 	xgbe_stop_tx_timers(pdata);
 
@@ -639,6 +791,197 @@ static void xgbe_restart(struct work_str
 	rtnl_unlock();
 }
 
+static void xgbe_tx_tstamp(struct work_struct *work)
+{
+	struct xgbe_prv_data *pdata = container_of(work,
+						   struct xgbe_prv_data,
+						   tx_tstamp_work);
+	struct skb_shared_hwtstamps hwtstamps;
+	u64 nsec;
+	unsigned long flags;
+
+	if (pdata->tx_tstamp) {
+		nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+					    pdata->tx_tstamp);
+
+		memset(&hwtstamps, 0, sizeof(hwtstamps));
+		hwtstamps.hwtstamp = ns_to_ktime(nsec);
+		skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
+	}
+
+	dev_kfree_skb_any(pdata->tx_tstamp_skb);
+
+	spin_lock_irqsave(&pdata->tstamp_lock, flags);
+	pdata->tx_tstamp_skb = NULL;
+	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+}
+
+static int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata,
+				      struct ifreq *ifreq)
+{
+	if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config,
+			 sizeof(pdata->tstamp_config)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata,
+				      struct ifreq *ifreq)
+{
+	struct hwtstamp_config config;
+	unsigned int mac_tscr;
+
+	if (copy_from_user(&config, ifreq->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	if (config.flags)
+		return -EINVAL;
+
+	mac_tscr = 0;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		break;
+
+	case HWTSTAMP_TX_ON:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+
+	case HWTSTAMP_FILTER_ALL:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2, UDP, any kind of event packet */
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+	/* PTP v1, UDP, any kind of event packet */
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2, UDP, Sync packet */
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+	/* PTP v1, UDP, Sync packet */
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2, UDP, Delay_req packet */
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+	/* PTP v1, UDP, Delay_req packet */
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* 802.AS1, Ethernet, any kind of event packet */
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* 802.AS1, Ethernet, Sync packet */
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* 802.AS1, Ethernet, Delay_req packet */
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2/802.AS1, any layer, any kind of event packet */
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2/802.AS1, any layer, Sync packet */
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	/* PTP v2/802.AS1, any layer, Delay_req packet */
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+		XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+		break;
+
+	default:
+		return -ERANGE;
+	}
+
+	pdata->hw_if.config_tstamp(pdata, mac_tscr);
+
+	memcpy(&pdata->tstamp_config, &config, sizeof(config));
+
+	return 0;
+}
+
+static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata,
+				struct sk_buff *skb,
+				struct xgbe_packet_data *packet)
+{
+	unsigned long flags;
+
+	if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) {
+		spin_lock_irqsave(&pdata->tstamp_lock, flags);
+		if (pdata->tx_tstamp_skb) {
+			/* Another timestamp in progress, ignore this one */
+			XGMAC_SET_BITS(packet->attributes,
+				       TX_PACKET_ATTRIBUTES, PTP, 0);
+		} else {
+			pdata->tx_tstamp_skb = skb_get(skb);
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		}
+		spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+	}
+
+	if (!XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
+		skb_tx_timestamp(skb);
+}
+
 static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet)
 {
 	if (vlan_tx_tag_present(skb))
@@ -682,7 +1025,8 @@ static int xgbe_is_tso(struct sk_buff *s
 	return 1;
 }
 
-static void xgbe_packet_info(struct xgbe_ring *ring, struct sk_buff *skb,
+static void xgbe_packet_info(struct xgbe_prv_data *pdata,
+			     struct xgbe_ring *ring, struct sk_buff *skb,
 			     struct xgbe_packet_data *packet)
 {
 	struct skb_frag_struct *frag;
@@ -724,16 +1068,21 @@ static void xgbe_packet_info(struct xgbe
 			       VLAN_CTAG, 1);
 	}
 
+	if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+	    (pdata->tstamp_config.tx_type == HWTSTAMP_TX_ON))
+		XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
+			       PTP, 1);
+
 	for (len = skb_headlen(skb); len;) {
 		packet->rdesc_count++;
-		len -= min_t(unsigned int, len, TX_MAX_BUF_SIZE);
+		len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE);
 	}
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		frag = &skb_shinfo(skb)->frags[i];
 		for (len = skb_frag_size(frag); len; ) {
 			packet->rdesc_count++;
-			len -= min_t(unsigned int, len, TX_MAX_BUF_SIZE);
+			len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE);
 		}
 	}
 }
@@ -747,26 +1096,38 @@ static int xgbe_open(struct net_device *
 
 	DBGPR("-->xgbe_open\n");
 
-	/* Enable the clock */
-	ret = clk_prepare_enable(pdata->sysclock);
-	if (ret) {
-		netdev_alert(netdev, "clk_prepare_enable failed\n");
+	/* Initialize the phy */
+	ret = xgbe_phy_init(pdata);
+	if (ret)
 		return ret;
+
+	/* Enable the clocks */
+	ret = clk_prepare_enable(pdata->sysclk);
+	if (ret) {
+		netdev_alert(netdev, "dma clk_prepare_enable failed\n");
+		goto err_phy_init;
+	}
+
+	ret = clk_prepare_enable(pdata->ptpclk);
+	if (ret) {
+		netdev_alert(netdev, "ptp clk_prepare_enable failed\n");
+		goto err_sysclk;
 	}
 
 	/* Calculate the Rx buffer size before allocating rings */
 	ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
 	if (ret < 0)
-		goto err_clk;
+		goto err_ptpclk;
 	pdata->rx_buf_size = ret;
 
 	/* Allocate the ring descriptors and buffers */
 	ret = desc_if->alloc_ring_resources(pdata);
 	if (ret)
-		goto err_clk;
+		goto err_ptpclk;
 
-	/* Initialize the device restart work struct */
+	/* Initialize the device restart and Tx timestamp work struct */
 	INIT_WORK(&pdata->restart_work, xgbe_restart);
+	INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
 
 	/* Request interrupts */
 	ret = devm_request_irq(pdata->dev, netdev->irq, xgbe_isr, 0,
@@ -795,8 +1156,14 @@ err_start:
 err_irq:
 	desc_if->free_ring_resources(pdata);
 
-err_clk:
-	clk_disable_unprepare(pdata->sysclock);
+err_ptpclk:
+	clk_disable_unprepare(pdata->ptpclk);
+
+err_sysclk:
+	clk_disable_unprepare(pdata->sysclk);
+
+err_phy_init:
+	xgbe_phy_exit(pdata);
 
 	return ret;
 }
@@ -824,8 +1191,12 @@ static int xgbe_close(struct net_device
 		pdata->irq_number = 0;
 	}
 
-	/* Disable the clock */
-	clk_disable_unprepare(pdata->sysclock);
+	/* Disable the clocks */
+	clk_disable_unprepare(pdata->ptpclk);
+	clk_disable_unprepare(pdata->sysclk);
+
+	/* Release the phy */
+	xgbe_phy_exit(pdata);
 
 	DBGPR("<--xgbe_close\n");
 
@@ -861,7 +1232,7 @@ static int xgbe_xmit(struct sk_buff *skb
 
 	/* Calculate preliminary packet info */
 	memset(packet, 0, sizeof(*packet));
-	xgbe_packet_info(ring, skb, packet);
+	xgbe_packet_info(pdata, ring, skb, packet);
 
 	/* Check that there are enough descriptors available */
 	if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) {
@@ -885,6 +1256,8 @@ static int xgbe_xmit(struct sk_buff *skb
 		goto tx_netdev_return;
 	}
 
+	xgbe_prep_tx_tstamp(pdata, skb, packet);
+
 	/* Configure required descriptor fields for transmission */
 	hw_if->pre_xmit(channel);
 
@@ -911,18 +1284,10 @@ static void xgbe_set_rx_mode(struct net_
 	pr_mode = ((netdev->flags & IFF_PROMISC) != 0);
 	am_mode = ((netdev->flags & IFF_ALLMULTI) != 0);
 
-	if (netdev_uc_count(netdev) > pdata->hw_feat.addn_mac)
-		pr_mode = 1;
-	if (netdev_mc_count(netdev) > pdata->hw_feat.addn_mac)
-		am_mode = 1;
-	if ((netdev_uc_count(netdev) + netdev_mc_count(netdev)) >
-	     pdata->hw_feat.addn_mac)
-		pr_mode = 1;
-
 	hw_if->set_promiscuous_mode(pdata, pr_mode);
 	hw_if->set_all_multicast_mode(pdata, am_mode);
-	if (!pr_mode)
-		hw_if->set_addn_mac_addrs(pdata, am_mode);
+
+	hw_if->add_mac_addresses(pdata);
 
 	DBGPR("<--xgbe_set_rx_mode\n");
 }
@@ -947,6 +1312,27 @@ static int xgbe_set_mac_address(struct n
 	return 0;
 }
 
+static int xgbe_ioctl(struct net_device *netdev, struct ifreq *ifreq, int cmd)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	int ret;
+
+	switch (cmd) {
+	case SIOCGHWTSTAMP:
+		ret = xgbe_get_hwtstamp_settings(pdata, ifreq);
+		break;
+
+	case SIOCSHWTSTAMP:
+		ret = xgbe_set_hwtstamp_settings(pdata, ifreq);
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
 static int xgbe_change_mtu(struct net_device *netdev, int mtu)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
@@ -999,6 +1385,38 @@ static struct rtnl_link_stats64 *xgbe_ge
 	return s;
 }
 
+static int xgbe_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
+				u16 vid)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	struct xgbe_hw_if *hw_if = &pdata->hw_if;
+
+	DBGPR("-->%s\n", __func__);
+
+	set_bit(vid, pdata->active_vlans);
+	hw_if->update_vlan_hash_table(pdata);
+
+	DBGPR("<--%s\n", __func__);
+
+	return 0;
+}
+
+static int xgbe_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
+				 u16 vid)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	struct xgbe_hw_if *hw_if = &pdata->hw_if;
+
+	DBGPR("-->%s\n", __func__);
+
+	clear_bit(vid, pdata->active_vlans);
+	hw_if->update_vlan_hash_table(pdata);
+
+	DBGPR("<--%s\n", __func__);
+
+	return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void xgbe_poll_controller(struct net_device *netdev)
 {
@@ -1016,31 +1434,58 @@ static void xgbe_poll_controller(struct
 }
 #endif /* End CONFIG_NET_POLL_CONTROLLER */
 
+static int xgbe_setup_tc(struct net_device *netdev, u8 tc)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	unsigned int offset, queue;
+	u8 i;
+
+	if (tc && (tc != pdata->hw_feat.tc_cnt))
+		return -EINVAL;
+
+	if (tc) {
+		netdev_set_num_tc(netdev, tc);
+		for (i = 0, queue = 0, offset = 0; i < tc; i++) {
+			while ((queue < pdata->tx_q_count) &&
+			       (pdata->q2tc_map[queue] == i))
+				queue++;
+
+			DBGPR("  TC%u using TXq%u-%u\n", i, offset, queue - 1);
+			netdev_set_tc_queue(netdev, i, queue - offset, offset);
+			offset = queue;
+		}
+	} else {
+		netdev_reset_tc(netdev);
+	}
+
+	return 0;
+}
+
 static int xgbe_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
-	unsigned int rxcsum_enabled, rxvlan_enabled;
+	unsigned int rxcsum, rxvlan, rxvlan_filter;
 
-	rxcsum_enabled = !!(pdata->netdev_features & NETIF_F_RXCSUM);
-	rxvlan_enabled = !!(pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX);
+	rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
+	rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
+	rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER;
 
-	if ((features & NETIF_F_RXCSUM) && !rxcsum_enabled) {
+	if ((features & NETIF_F_RXCSUM) && !rxcsum)
 		hw_if->enable_rx_csum(pdata);
-		netdev_alert(netdev, "state change - rxcsum enabled\n");
-	} else if (!(features & NETIF_F_RXCSUM) && rxcsum_enabled) {
+	else if (!(features & NETIF_F_RXCSUM) && rxcsum)
 		hw_if->disable_rx_csum(pdata);
-		netdev_alert(netdev, "state change - rxcsum disabled\n");
-	}
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan_enabled) {
+	if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan)
 		hw_if->enable_rx_vlan_stripping(pdata);
-		netdev_alert(netdev, "state change - rxvlan enabled\n");
-	} else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan_enabled) {
+	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan)
 		hw_if->disable_rx_vlan_stripping(pdata);
-		netdev_alert(netdev, "state change - rxvlan disabled\n");
-	}
+
+	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter)
+		hw_if->enable_rx_vlan_filtering(pdata);
+	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter)
+		hw_if->disable_rx_vlan_filtering(pdata);
 
 	pdata->netdev_features = features;
 
@@ -1056,11 +1501,15 @@ static const struct net_device_ops xgbe_
 	.ndo_set_rx_mode	= xgbe_set_rx_mode,
 	.ndo_set_mac_address	= xgbe_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= xgbe_ioctl,
 	.ndo_change_mtu		= xgbe_change_mtu,
 	.ndo_get_stats64	= xgbe_get_stats64,
+	.ndo_vlan_rx_add_vid	= xgbe_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= xgbe_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= xgbe_poll_controller,
 #endif
+	.ndo_setup_tc		= xgbe_setup_tc,
 	.ndo_set_features	= xgbe_set_features,
 };
 
@@ -1069,6 +1518,22 @@ struct net_device_ops *xgbe_get_netdev_o
 	return (struct net_device_ops *)&xgbe_netdev_ops;
 }
 
+static void xgbe_rx_refresh(struct xgbe_channel *channel)
+{
+	struct xgbe_prv_data *pdata = channel->pdata;
+	struct xgbe_desc_if *desc_if = &pdata->desc_if;
+	struct xgbe_ring *ring = channel->rx_ring;
+	struct xgbe_ring_data *rdata;
+
+	desc_if->realloc_skb(channel);
+
+	/* Update the Rx Tail Pointer Register with address of
+	 * the last cleaned entry */
+	rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
+	XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
+			  lower_32_bits(rdata->rdesc_dma));
+}
+
 static int xgbe_tx_poll(struct xgbe_channel *channel)
 {
 	struct xgbe_prv_data *pdata = channel->pdata;
@@ -1089,8 +1554,9 @@ static int xgbe_tx_poll(struct xgbe_chan
 
 	spin_lock_irqsave(&ring->lock, flags);
 
-	while ((processed < TX_DESC_MAX_PROC) && (ring->dirty < ring->cur)) {
-		rdata = GET_DESC_DATA(ring, ring->dirty);
+	while ((processed < XGBE_TX_DESC_MAX_PROC) &&
+	       (ring->dirty < ring->cur)) {
+		rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
 		rdesc = rdata->rdesc;
 
 		if (!hw_if->tx_complete(rdesc))
@@ -1109,7 +1575,7 @@ static int xgbe_tx_poll(struct xgbe_chan
 	}
 
 	if ((ring->tx.queue_stopped == 1) &&
-	    (xgbe_tx_avail_desc(ring) > TX_DESC_MIN_FREE)) {
+	    (xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
 		ring->tx.queue_stopped = 0;
 		netif_wake_subqueue(netdev, channel->queue_index);
 	}
@@ -1125,14 +1591,14 @@ static int xgbe_rx_poll(struct xgbe_chan
 {
 	struct xgbe_prv_data *pdata = channel->pdata;
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
-	struct xgbe_desc_if *desc_if = &pdata->desc_if;
 	struct xgbe_ring *ring = channel->rx_ring;
 	struct xgbe_ring_data *rdata;
 	struct xgbe_packet_data *packet;
 	struct net_device *netdev = pdata->netdev;
 	struct sk_buff *skb;
-	unsigned int incomplete, error;
-	unsigned int cur_len, put_len, max_len;
+	struct skb_shared_hwtstamps *hwtstamps;
+	unsigned int incomplete, error, context_next, context;
+	unsigned int len, put_len, max_len;
 	int received = 0;
 
 	DBGPR("-->xgbe_rx_poll: budget=%d\n", budget);
@@ -1141,18 +1607,32 @@ static int xgbe_rx_poll(struct xgbe_chan
 	if (!ring)
 		return 0;
 
+	rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 	packet = &ring->packet_data;
 	while (received < budget) {
 		DBGPR("  cur = %d\n", ring->cur);
 
-		/* Clear the packet data information */
-		memset(packet, 0, sizeof(*packet));
-		skb = NULL;
-		error = 0;
-		cur_len = 0;
+		/* First time in loop see if we need to restore state */
+		if (!received && rdata->state_saved) {
+			incomplete = rdata->state.incomplete;
+			context_next = rdata->state.context_next;
+			skb = rdata->state.skb;
+			error = rdata->state.error;
+			len = rdata->state.len;
+		} else {
+			memset(packet, 0, sizeof(*packet));
+			incomplete = 0;
+			context_next = 0;
+			skb = NULL;
+			error = 0;
+			len = 0;
+		}
 
 read_again:
-		rdata = GET_DESC_DATA(ring, ring->cur);
+		rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
+
+		if (ring->dirty > (XGBE_RX_DESC_CNT >> 3))
+			xgbe_rx_refresh(channel);
 
 		if (hw_if->dev_read(channel))
 			break;
@@ -1168,9 +1648,15 @@ read_again:
 		incomplete = XGMAC_GET_BITS(packet->attributes,
 					    RX_PACKET_ATTRIBUTES,
 					    INCOMPLETE);
+		context_next = XGMAC_GET_BITS(packet->attributes,
+					      RX_PACKET_ATTRIBUTES,
+					      CONTEXT_NEXT);
+		context = XGMAC_GET_BITS(packet->attributes,
+					 RX_PACKET_ATTRIBUTES,
+					 CONTEXT);
 
 		/* Earlier error, just drain the remaining data */
-		if (incomplete && error)
+		if ((incomplete || context_next) && error)
 			goto read_again;
 
 		if (error || packet->errors) {
@@ -1180,30 +1666,37 @@ read_again:
 			continue;
 		}
 
-		put_len = rdata->len - cur_len;
-		if (skb) {
-			if (pskb_expand_head(skb, 0, put_len, GFP_ATOMIC)) {
-				DBGPR("pskb_expand_head error\n");
-				if (incomplete) {
-					error = 1;
-					goto read_again;
-				}
+		if (!context) {
+			put_len = rdata->len - len;
+			if (skb) {
+				if (pskb_expand_head(skb, 0, put_len,
+						     GFP_ATOMIC)) {
+					DBGPR("pskb_expand_head error\n");
+					if (incomplete) {
+						error = 1;
+						goto read_again;
+					}
 
-				dev_kfree_skb(skb);
-				continue;
+					dev_kfree_skb(skb);
+					continue;
+				}
+				memcpy(skb_tail_pointer(skb), rdata->skb->data,
+				       put_len);
+			} else {
+				skb = rdata->skb;
+				rdata->skb = NULL;
 			}
-			memcpy(skb_tail_pointer(skb), rdata->skb->data,
-			       put_len);
-		} else {
-			skb = rdata->skb;
-			rdata->skb = NULL;
+			skb_put(skb, put_len);
+			len += put_len;
 		}
-		skb_put(skb, put_len);
-		cur_len += put_len;
 
-		if (incomplete)
+		if (incomplete || context_next)
 			goto read_again;
 
+		/* Stray Context Descriptor? */
+		if (!skb)
+			continue;
+
 		/* Be sure we don't exceed the configured MTU */
 		max_len = netdev->mtu + ETH_HLEN;
 		if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
@@ -1230,6 +1723,16 @@ read_again:
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 					       packet->vlan_ctag);
 
+		if (XGMAC_GET_BITS(packet->attributes,
+				   RX_PACKET_ATTRIBUTES, RX_TSTAMP)) {
+			u64 nsec;
+
+			nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+						    packet->rx_tstamp);
+			hwtstamps = skb_hwtstamps(skb);
+			hwtstamps->hwtstamp = ns_to_ktime(nsec);
+		}
+
 		skb->dev = netdev;
 		skb->protocol = eth_type_trans(skb, netdev);
 		skb_record_rx_queue(skb, channel->queue_index);
@@ -1239,14 +1742,15 @@ read_again:
 		napi_gro_receive(&pdata->napi, skb);
 	}
 
-	if (received) {
-		desc_if->realloc_skb(channel);
-
-		/* Update the Rx Tail Pointer Register with address of
-		 * the last cleaned entry */
-		rdata = GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
-		XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
-				  lower_32_bits(rdata->rdesc_dma));
+	/* Check if we need to save state before leaving */
+	if (received && (incomplete || context_next)) {
+		rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
+		rdata->state_saved = 1;
+		rdata->state.incomplete = incomplete;
+		rdata->state.context_next = context_next;
+		rdata->state.skb = skb;
+		rdata->state.len = len;
+		rdata->state.error = error;
 	}
 
 	DBGPR("<--xgbe_rx_poll: received = %d\n", received);
@@ -1259,21 +1763,28 @@ static int xgbe_poll(struct napi_struct
 	struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data,
 						   napi);
 	struct xgbe_channel *channel;
-	int processed;
+	int ring_budget;
+	int processed, last_processed;
 	unsigned int i;
 
 	DBGPR("-->xgbe_poll: budget=%d\n", budget);
 
-	/* Cleanup Tx ring first */
-	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++)
-		xgbe_tx_poll(channel);
-
-	/* Process Rx ring next */
 	processed = 0;
-	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++)
-		processed += xgbe_rx_poll(channel, budget - processed);
+	ring_budget = budget / pdata->rx_ring_count;
+	do {
+		last_processed = processed;
+
+		channel = pdata->channel;
+		for (i = 0; i < pdata->channel_count; i++, channel++) {
+			/* Cleanup Tx ring first */
+			xgbe_tx_poll(channel);
+
+			/* Process Rx ring next */
+			if (ring_budget > (budget - processed))
+				ring_budget = budget - processed;
+			processed += xgbe_rx_poll(channel, ring_budget);
+		}
+	} while ((processed < budget) && (processed != last_processed));
 
 	/* If we processed everything, we are done */
 	if (processed < budget) {
@@ -1296,7 +1807,7 @@ void xgbe_dump_tx_desc(struct xgbe_ring
 	struct xgbe_ring_desc *rdesc;
 
 	while (count--) {
-		rdata = GET_DESC_DATA(ring, idx);
+		rdata = XGBE_GET_DESC_DATA(ring, idx);
 		rdesc = rdata->rdesc;
 		DBGPR("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx,
 		      (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -116,6 +116,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/phy.h>
+#include <linux/net_tstamp.h>
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -289,13 +290,9 @@ static int xgbe_get_settings(struct net_
 	if (!pdata->phydev)
 		return -ENODEV;
 
-	spin_lock_irq(&pdata->lock);
-
 	ret = phy_ethtool_gset(pdata->phydev, cmd);
 	cmd->transceiver = XCVR_EXTERNAL;
 
-	spin_unlock_irq(&pdata->lock);
-
 	DBGPR("<--xgbe_get_settings\n");
 
 	return ret;
@@ -314,36 +311,32 @@ static int xgbe_set_settings(struct net_
 	if (!pdata->phydev)
 		return -ENODEV;
 
-	spin_lock_irq(&pdata->lock);
-
 	speed = ethtool_cmd_speed(cmd);
 
-	ret = -EINVAL;
 	if (cmd->phy_address != phydev->addr)
-		goto unlock;
+		return -EINVAL;
 
 	if ((cmd->autoneg != AUTONEG_ENABLE) &&
 	    (cmd->autoneg != AUTONEG_DISABLE))
-		goto unlock;
+		return -EINVAL;
 
-	if ((cmd->autoneg == AUTONEG_DISABLE) &&
-	    (((speed != SPEED_10000) && (speed != SPEED_1000)) ||
-	     (cmd->duplex != DUPLEX_FULL)))
-		goto unlock;
+	if (cmd->autoneg == AUTONEG_DISABLE) {
+		switch (speed) {
+		case SPEED_10000:
+		case SPEED_2500:
+		case SPEED_1000:
+			break;
+		default:
+			return -EINVAL;
+		}
 
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		/* Clear settings needed to force speeds */
-		phydev->supported &= ~SUPPORTED_1000baseT_Full;
-		phydev->supported &= ~SUPPORTED_10000baseT_Full;
-	} else {
-		/* Add settings needed to force speed */
-		phydev->supported |= SUPPORTED_1000baseT_Full;
-		phydev->supported |= SUPPORTED_10000baseT_Full;
+		if (cmd->duplex != DUPLEX_FULL)
+			return -EINVAL;
 	}
 
 	cmd->advertising &= phydev->supported;
 	if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
-		goto unlock;
+		return -EINVAL;
 
 	ret = 0;
 	phydev->autoneg = cmd->autoneg;
@@ -359,9 +352,6 @@ static int xgbe_set_settings(struct net_
 	if (netif_running(netdev))
 		ret = phy_start_aneg(phydev);
 
-unlock:
-	spin_unlock_irq(&pdata->lock);
-
 	DBGPR("<--xgbe_set_settings\n");
 
 	return ret;
@@ -371,15 +361,16 @@ static void xgbe_get_drvinfo(struct net_
 			     struct ethtool_drvinfo *drvinfo)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	struct xgbe_hw_features *hw_feat = &pdata->hw_feat;
 
 	strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver));
 	strlcpy(drvinfo->version, XGBE_DRV_VERSION, sizeof(drvinfo->version));
 	strlcpy(drvinfo->bus_info, dev_name(pdata->dev),
 		sizeof(drvinfo->bus_info));
 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d",
-		 XGMAC_IOREAD_BITS(pdata, MAC_VR, USERVER),
-		 XGMAC_IOREAD_BITS(pdata, MAC_VR, DEVID),
-		 XGMAC_IOREAD_BITS(pdata, MAC_VR, SNPSVER));
+		 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
+		 XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
+		 XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
 	drvinfo->n_stats = XGBE_STATS_COUNT;
 }
 
@@ -490,6 +481,39 @@ static int xgbe_set_coalesce(struct net_
 	return 0;
 }
 
+static int xgbe_get_ts_info(struct net_device *netdev,
+			    struct ethtool_ts_info *ts_info)
+{
+	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+				   SOF_TIMESTAMPING_RX_SOFTWARE |
+				   SOF_TIMESTAMPING_SOFTWARE |
+				   SOF_TIMESTAMPING_TX_HARDWARE |
+				   SOF_TIMESTAMPING_RX_HARDWARE |
+				   SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	if (pdata->ptp_clock)
+		ts_info->phc_index = ptp_clock_index(pdata->ptp_clock);
+	else
+		ts_info->phc_index = -1;
+
+	ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+	ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+			      (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+			      (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+			      (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+			      (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+			      (1 << HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 static const struct ethtool_ops xgbe_ethtool_ops = {
 	.get_settings = xgbe_get_settings,
 	.set_settings = xgbe_set_settings,
@@ -502,6 +526,7 @@ static const struct ethtool_ops xgbe_eth
 	.get_strings = xgbe_get_strings,
 	.get_ethtool_stats = xgbe_get_ethtool_stats,
 	.get_sset_count = xgbe_get_sset_count,
+	.get_ts_info = xgbe_get_ts_info,
 };
 
 struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h	2014-09-28 17:29:07.000000000 -0400
@@ -121,6 +121,12 @@
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
 #include <linux/phy.h>
+#include <linux/if_vlan.h>
+#include <linux/bitops.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <net/dcbnl.h>
 
 
 #define XGBE_DRV_NAME		"amd-xgbe"
@@ -128,22 +134,30 @@
 #define XGBE_DRV_DESC		"AMD 10 Gigabit Ethernet Driver"
 
 /* Descriptor related defines */
-#define TX_DESC_CNT		512
-#define TX_DESC_MIN_FREE	(TX_DESC_CNT >> 3)
-#define TX_DESC_MAX_PROC	(TX_DESC_CNT >> 1)
-#define RX_DESC_CNT		512
+#define XGBE_TX_DESC_CNT	512
+#define XGBE_TX_DESC_MIN_FREE	(XGBE_TX_DESC_CNT >> 3)
+#define XGBE_TX_DESC_MAX_PROC	(XGBE_TX_DESC_CNT >> 1)
+#define XGBE_RX_DESC_CNT	512
 
-#define TX_MAX_BUF_SIZE		(0x3fff & ~(64 - 1))
+#define XGBE_TX_MAX_BUF_SIZE	(0x3fff & ~(64 - 1))
 
-#define RX_MIN_BUF_SIZE		(ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
-#define RX_BUF_ALIGN		64
+#define XGBE_RX_MIN_BUF_SIZE	(ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
+#define XGBE_RX_BUF_ALIGN	64
 
 #define XGBE_MAX_DMA_CHANNELS	16
-#define DMA_ARDOMAIN_SETTING	0x2
-#define DMA_ARCACHE_SETTING	0xb
-#define DMA_AWDOMAIN_SETTING	0x2
-#define DMA_AWCACHE_SETTING	0x7
-#define DMA_INTERRUPT_MASK	0x31c7
+#define XGBE_MAX_QUEUES		16
+
+/* DMA cache settings - Outer sharable, write-back, write-allocate */
+#define XGBE_DMA_OS_AXDOMAIN	0x2
+#define XGBE_DMA_OS_ARCACHE	0xb
+#define XGBE_DMA_OS_AWCACHE	0xf
+
+/* DMA cache settings - System, no caches used */
+#define XGBE_DMA_SYS_AXDOMAIN	0x3
+#define XGBE_DMA_SYS_ARCACHE	0x0
+#define XGBE_DMA_SYS_AWCACHE	0x0
+
+#define XGBE_DMA_INTERRUPT_MASK	0x31c7
 
 #define XGMAC_MIN_PACKET	60
 #define XGMAC_STD_PACKET_MTU	1500
@@ -151,45 +165,54 @@
 #define XGMAC_JUMBO_PACKET_MTU	9000
 #define XGMAC_MAX_JUMBO_PACKET	9018
 
-#define MAX_MULTICAST_LIST	14
-#define TX_FLAGS_IP_PKT		0x00000001
-#define TX_FLAGS_TCP_PKT	0x00000002
-
 /* MDIO bus phy name */
 #define XGBE_PHY_NAME		"amd_xgbe_phy"
 #define XGBE_PRTAD		0
 
+/* Device-tree clock names */
+#define XGBE_DMA_CLOCK		"dma_clk"
+#define XGBE_PTP_CLOCK		"ptp_clk"
+
+/* Timestamp support - values based on 50MHz PTP clock
+ *   50MHz => 20 nsec
+ */
+#define XGBE_TSTAMP_SSINC	20
+#define XGBE_TSTAMP_SNSINC	0
+
 /* Driver PMT macros */
 #define XGMAC_DRIVER_CONTEXT	1
 #define XGMAC_IOCTL_CONTEXT	2
 
-#define FIFO_SIZE_B(x)		(x)
-#define FIFO_SIZE_KB(x)		(x * 1024)
+#define XGBE_FIFO_MAX		81920
+#define XGBE_FIFO_SIZE_B(x)	(x)
+#define XGBE_FIFO_SIZE_KB(x)	(x * 1024)
 
-#define XGBE_TC_CNT		2
+#define XGBE_TC_MIN_QUANTUM	10
 
 /* Helper macro for descriptor handling
- *  Always use GET_DESC_DATA to access the descriptor data
+ *  Always use XGBE_GET_DESC_DATA to access the descriptor data
  *  since the index is free-running and needs to be and-ed
  *  with the descriptor count value of the ring to index to
  *  the proper descriptor data.
  */
-#define GET_DESC_DATA(_ring, _idx)				\
+#define XGBE_GET_DESC_DATA(_ring, _idx)				\
 	((_ring)->rdata +					\
 	 ((_idx) & ((_ring)->rdesc_count - 1)))
 
 
 /* Default coalescing parameters */
-#define XGMAC_INIT_DMA_TX_USECS		100
-#define XGMAC_INIT_DMA_TX_FRAMES	16
+#define XGMAC_INIT_DMA_TX_USECS		50
+#define XGMAC_INIT_DMA_TX_FRAMES	25
 
 #define XGMAC_MAX_DMA_RIWT		0xff
-#define XGMAC_INIT_DMA_RX_USECS		100
-#define XGMAC_INIT_DMA_RX_FRAMES	16
+#define XGMAC_INIT_DMA_RX_USECS		30
+#define XGMAC_INIT_DMA_RX_FRAMES	25
 
 /* Flow control queue count */
 #define XGMAC_MAX_FLOW_CONTROL_QUEUES	8
 
+/* Maximum MAC address hash table size (256 bits = 8 bytes) */
+#define XGBE_MAC_HASH_TABLE_SIZE	8
 
 struct xgbe_prv_data;
 
@@ -207,6 +230,8 @@ struct xgbe_packet_data {
 	unsigned short mss;
 
 	unsigned short vlan_ctag;
+
+	u64 rx_tstamp;
 };
 
 /* Common Rx and Tx descriptor mapping */
@@ -219,7 +244,7 @@ struct xgbe_ring_desc {
 
 /* Structure used to hold information related to the descriptor
  * and the packet associated with the descriptor (always use
- * use the GET_DESC_DATA macro to access this data from the ring)
+ * use the XGBE_GET_DESC_DATA macro to access this data from the ring)
  */
 struct xgbe_ring_data {
 	struct xgbe_ring_desc *rdesc;	/* Virtual address of descriptor */
@@ -235,6 +260,20 @@ struct xgbe_ring_data {
 	unsigned int interrupt;		/* Interrupt indicator */
 
 	unsigned int mapped_as_page;
+
+	/* Incomplete receive save location.  If the budget is exhausted
+	 * or the last descriptor (last normal descriptor or a following
+	 * context descriptor) has not been DMA'd yet the current state
+	 * of the receive processing needs to be saved.
+	 */
+	unsigned int state_saved;
+	struct {
+		unsigned int incomplete;
+		unsigned int context_next;
+		struct sk_buff *skb;
+		unsigned int len;
+		unsigned int error;
+	} state;
 };
 
 struct xgbe_ring {
@@ -250,7 +289,7 @@ struct xgbe_ring {
 	unsigned int rdesc_count;
 
 	/* Array of descriptor data corresponding the descriptor memory
-	 * (always use the GET_DESC_DATA macro to access this data)
+	 * (always use the XGBE_GET_DESC_DATA macro to access this data)
 	 */
 	struct xgbe_ring_data *rdata;
 
@@ -304,13 +343,13 @@ struct xgbe_channel {
 } ____cacheline_aligned;
 
 enum xgbe_int {
-	XGMAC_INT_DMA_ISR_DC0IS,
 	XGMAC_INT_DMA_CH_SR_TI,
 	XGMAC_INT_DMA_CH_SR_TPS,
 	XGMAC_INT_DMA_CH_SR_TBU,
 	XGMAC_INT_DMA_CH_SR_RI,
 	XGMAC_INT_DMA_CH_SR_RBU,
 	XGMAC_INT_DMA_CH_SR_RPS,
+	XGMAC_INT_DMA_CH_SR_TI_RI,
 	XGMAC_INT_DMA_CH_SR_FBE,
 	XGMAC_INT_DMA_ALL,
 };
@@ -386,7 +425,7 @@ struct xgbe_hw_if {
 
 	int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int);
 	int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int);
-	int (*set_addn_mac_addrs)(struct xgbe_prv_data *, unsigned int);
+	int (*add_mac_addresses)(struct xgbe_prv_data *);
 	int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr);
 
 	int (*enable_rx_csum)(struct xgbe_prv_data *);
@@ -394,6 +433,9 @@ struct xgbe_hw_if {
 
 	int (*enable_rx_vlan_stripping)(struct xgbe_prv_data *);
 	int (*disable_rx_vlan_stripping)(struct xgbe_prv_data *);
+	int (*enable_rx_vlan_filtering)(struct xgbe_prv_data *);
+	int (*disable_rx_vlan_filtering)(struct xgbe_prv_data *);
+	int (*update_vlan_hash_table)(struct xgbe_prv_data *);
 
 	int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
 	void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
@@ -457,6 +499,18 @@ struct xgbe_hw_if {
 	void (*rx_mmc_int)(struct xgbe_prv_data *);
 	void (*tx_mmc_int)(struct xgbe_prv_data *);
 	void (*read_mmc_stats)(struct xgbe_prv_data *);
+
+	/* For Timestamp config */
+	int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
+	void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
+	void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
+				unsigned int nsec);
+	u64 (*get_tstamp_time)(struct xgbe_prv_data *);
+	u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
+
+	/* For Data Center Bridging config */
+	void (*config_dcb_tc)(struct xgbe_prv_data *);
+	void (*config_dcb_pfc)(struct xgbe_prv_data *);
 };
 
 struct xgbe_desc_if {
@@ -473,6 +527,9 @@ struct xgbe_desc_if {
  * or configurations are present in the device.
  */
 struct xgbe_hw_features {
+	/* HW Version */
+	unsigned int version;
+
 	/* HW Feature Register0 */
 	unsigned int gmii;		/* 1000 Mbps support */
 	unsigned int vlhash;		/* VLAN Hash Filter */
@@ -498,6 +555,7 @@ struct xgbe_hw_features {
 	unsigned int tso;		/* TCP Segmentation Offload */
 	unsigned int dma_debug;		/* DMA Debug Registers */
 	unsigned int rss;		/* Receive Side Scaling */
+	unsigned int tc_cnt;		/* Number of Traffic Classes */
 	unsigned int hash_table_size;	/* Hash Table Size */
 	unsigned int l3l4_filter_num;	/* Number of L3-L4 Filters */
 
@@ -530,6 +588,11 @@ struct xgbe_prv_data {
 	struct xgbe_hw_if hw_if;
 	struct xgbe_desc_if desc_if;
 
+	/* AXI DMA settings */
+	unsigned int axdomain;
+	unsigned int arcache;
+	unsigned int awcache;
+
 	/* Rings for Tx/Rx on a DMA channel */
 	struct xgbe_channel *channel;
 	unsigned int channel_count;
@@ -538,6 +601,9 @@ struct xgbe_prv_data {
 	unsigned int rx_ring_count;
 	unsigned int rx_desc_count;
 
+	unsigned int tx_q_count;
+	unsigned int rx_q_count;
+
 	/* Tx/Rx common settings */
 	unsigned int pblx8;
 
@@ -589,8 +655,30 @@ struct xgbe_prv_data {
 	struct napi_struct napi;
 	struct xgbe_mmc_stats mmc_stats;
 
-	/* System clock value used for Rx watchdog */
-	struct clk *sysclock;
+	/* Filtering support */
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+
+	/* Device clocks */
+	struct clk *sysclk;
+	struct clk *ptpclk;
+
+	/* Timestamp support */
+	spinlock_t tstamp_lock;
+	struct ptp_clock_info ptp_clock_info;
+	struct ptp_clock *ptp_clock;
+	struct hwtstamp_config tstamp_config;
+	struct cyclecounter tstamp_cc;
+	struct timecounter tstamp_tc;
+	unsigned int tstamp_addend;
+	struct work_struct tx_tstamp_work;
+	struct sk_buff *tx_tstamp_skb;
+	u64 tx_tstamp;
+
+	/* DCB support */
+	struct ieee_ets *ets;
+	struct ieee_pfc *pfc;
+	unsigned int q2tc_map[XGBE_MAX_QUEUES];
+	unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS];
 
 	/* Hardware features of the device */
 	struct xgbe_hw_features hw_feat;
@@ -617,10 +705,15 @@ void xgbe_init_function_ptrs_dev(struct
 void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
 struct net_device_ops *xgbe_get_netdev_ops(void);
 struct ethtool_ops *xgbe_get_ethtool_ops(void);
+#ifdef CONFIG_AMD_XGBE_DCB
+const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void);
+#endif
 
 int xgbe_mdio_register(struct xgbe_prv_data *);
 void xgbe_mdio_unregister(struct xgbe_prv_data *);
 void xgbe_dump_phy_registers(struct xgbe_prv_data *);
+void xgbe_ptp_register(struct xgbe_prv_data *);
+void xgbe_ptp_unregister(struct xgbe_prv_data *);
 void xgbe_dump_tx_desc(struct xgbe_ring *, unsigned int, unsigned int,
 		       unsigned int);
 void xgbe_dump_rx_desc(struct xgbe_ring *, struct xgbe_ring_desc *,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c	2014-09-28 17:29:07.000000000 -0400
@@ -172,7 +172,7 @@ static struct xgbe_channel *xgbe_alloc_r
 		}
 
 		if (i < pdata->rx_ring_count) {
-			spin_lock_init(&tx_ring->lock);
+			spin_lock_init(&rx_ring->lock);
 			channel->rx_ring = rx_ring++;
 		}
 
@@ -245,18 +245,19 @@ static int xgbe_probe(struct platform_de
 
 	spin_lock_init(&pdata->lock);
 	mutex_init(&pdata->xpcs_mutex);
+	spin_lock_init(&pdata->tstamp_lock);
 
 	/* Set and validate the number of descriptors for a ring */
-	BUILD_BUG_ON_NOT_POWER_OF_2(TX_DESC_CNT);
-	pdata->tx_desc_count = TX_DESC_CNT;
+	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(RX_DESC_CNT);
-	pdata->rx_desc_count = RX_DESC_CNT;
+	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);
@@ -265,10 +266,18 @@ static int xgbe_probe(struct platform_de
 	}
 
 	/* Obtain the system clock setting */
-	pdata->sysclock = devm_clk_get(dev, NULL);
-	if (IS_ERR(pdata->sysclock)) {
-		dev_err(dev, "devm_clk_get failed\n");
-		ret = PTR_ERR(pdata->sysclock);
+	pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
+	if (IS_ERR(pdata->sysclk)) {
+		dev_err(dev, "dma devm_clk_get failed\n");
+		ret = PTR_ERR(pdata->sysclk);
+		goto err_io;
+	}
+
+	/* 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");
+		ret = PTR_ERR(pdata->ptpclk);
 		goto err_io;
 	}
 
@@ -294,8 +303,21 @@ static int xgbe_probe(struct platform_de
 	/* Set the DMA mask */
 	if (!dev->dma_mask)
 		dev->dma_mask = &dev->coherent_dma_mask;
-	*(dev->dma_mask) = DMA_BIT_MASK(40);
-	dev->coherent_dma_mask = DMA_BIT_MASK(40);
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+	if (ret) {
+		dev_err(dev, "dma_set_mask_and_coherent failed\n");
+		goto err_io;
+	}
+
+	if (of_property_read_bool(dev->of_node, "dma-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;
+	}
 
 	ret = platform_get_irq(pdev, 0);
 	if (ret < 0) {
@@ -336,9 +358,16 @@ static int xgbe_probe(struct platform_de
 	/* Set default configuration data */
 	xgbe_default_config(pdata);
 
-	/* Calculate the number of Tx and Rx rings to be created */
+	/* 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;
 	ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
 	if (ret) {
 		dev_err(dev, "error setting real tx queue count\n");
@@ -348,6 +377,7 @@ static int xgbe_probe(struct platform_de
 	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");
@@ -373,9 +403,12 @@ static int xgbe_probe(struct platform_de
 	if (ret)
 		goto err_bus_id;
 
-	/* Set network and ethtool operations */
+	/* Set device operations */
 	netdev->netdev_ops = xgbe_get_netdev_ops();
 	netdev->ethtool_ops = xgbe_get_ethtool_ops();
+#ifdef CONFIG_AMD_XGBE_DCB
+	netdev->dcbnl_ops = xgbe_get_dcbnl_ops();
+#endif
 
 	/* Set device features */
 	netdev->hw_features = NETIF_F_SG |
@@ -386,7 +419,8 @@ static int xgbe_probe(struct platform_de
 			      NETIF_F_TSO6 |
 			      NETIF_F_GRO |
 			      NETIF_F_HW_VLAN_CTAG_RX |
-			      NETIF_F_HW_VLAN_CTAG_TX;
+			      NETIF_F_HW_VLAN_CTAG_TX |
+			      NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	netdev->vlan_features |= NETIF_F_SG |
 				 NETIF_F_IP_CSUM |
@@ -397,6 +431,8 @@ static int xgbe_probe(struct platform_de
 	netdev->features |= netdev->hw_features;
 	pdata->netdev_features = netdev->features;
 
+	netdev->priv_flags |= IFF_UNICAST_FLT;
+
 	xgbe_init_rx_coalesce(pdata);
 	xgbe_init_tx_coalesce(pdata);
 
@@ -407,6 +443,8 @@ static int xgbe_probe(struct platform_de
 		goto err_reg_netdev;
 	}
 
+	xgbe_ptp_register(pdata);
+
 	xgbe_debugfs_init(pdata);
 
 	netdev_notice(netdev, "net device enabled\n");
@@ -439,6 +477,8 @@ static int xgbe_remove(struct platform_d
 
 	xgbe_debugfs_exit(pdata);
 
+	xgbe_ptp_unregister(pdata);
+
 	unregister_netdev(netdev);
 
 	xgbe_mdio_unregister(pdata);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -116,7 +116,6 @@
 
 #include <linux/module.h>
 #include <linux/kmod.h>
-#include <linux/spinlock.h>
 #include <linux/mdio.h>
 #include <linux/phy.h>
 #include <linux/of.h>
@@ -158,82 +157,6 @@ static int xgbe_mdio_write(struct mii_bu
 	return 0;
 }
 
-static void xgbe_adjust_link(struct net_device *netdev)
-{
-	struct xgbe_prv_data *pdata = netdev_priv(netdev);
-	struct xgbe_hw_if *hw_if = &pdata->hw_if;
-	struct phy_device *phydev = pdata->phydev;
-	unsigned long flags;
-	int new_state = 0;
-
-	if (phydev == NULL)
-		return;
-
-	DBGPR_MDIO("-->xgbe_adjust_link: address=%d, newlink=%d, curlink=%d\n",
-		   phydev->addr, phydev->link, pdata->phy_link);
-
-	spin_lock_irqsave(&pdata->lock, flags);
-
-	if (phydev->link) {
-		/* Flow control support */
-		if (pdata->pause_autoneg) {
-			if (phydev->pause || phydev->asym_pause) {
-				pdata->tx_pause = 1;
-				pdata->rx_pause = 1;
-			} else {
-				pdata->tx_pause = 0;
-				pdata->rx_pause = 0;
-			}
-		}
-
-		if (pdata->tx_pause != pdata->phy_tx_pause) {
-			hw_if->config_tx_flow_control(pdata);
-			pdata->phy_tx_pause = pdata->tx_pause;
-		}
-
-		if (pdata->rx_pause != pdata->phy_rx_pause) {
-			hw_if->config_rx_flow_control(pdata);
-			pdata->phy_rx_pause = pdata->rx_pause;
-		}
-
-		/* Speed support */
-		if (phydev->speed != pdata->phy_speed) {
-			new_state = 1;
-
-			switch (phydev->speed) {
-			case SPEED_10000:
-				hw_if->set_xgmii_speed(pdata);
-				break;
-
-			case SPEED_2500:
-				hw_if->set_gmii_2500_speed(pdata);
-				break;
-
-			case SPEED_1000:
-				hw_if->set_gmii_speed(pdata);
-				break;
-			}
-			pdata->phy_speed = phydev->speed;
-		}
-
-		if (phydev->link != pdata->phy_link) {
-			new_state = 1;
-			pdata->phy_link = 1;
-		}
-	} else if (pdata->phy_link) {
-		new_state = 1;
-		pdata->phy_link = 0;
-		pdata->phy_speed = SPEED_UNKNOWN;
-	}
-
-	if (new_state)
-		phy_print_status(phydev);
-
-	spin_unlock_irqrestore(&pdata->lock, flags);
-
-	DBGPR_MDIO("<--xgbe_adjust_link\n");
-}
-
 void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
 {
 	struct device *dev = pdata->dev;
@@ -283,7 +206,6 @@ void xgbe_dump_phy_registers(struct xgbe
 
 int xgbe_mdio_register(struct xgbe_prv_data *pdata)
 {
-	struct net_device *netdev = pdata->netdev;
 	struct device_node *phy_node;
 	struct mii_bus *mii;
 	struct phy_device *phydev;
@@ -298,7 +220,6 @@ int xgbe_mdio_register(struct xgbe_prv_d
 		return -EINVAL;
 	}
 
-	/* Register with the MDIO bus */
 	mii = mdiobus_alloc();
 	if (mii == NULL) {
 		dev_err(pdata->dev, "mdiobus_alloc failed\n");
@@ -353,32 +274,8 @@ int xgbe_mdio_register(struct xgbe_prv_d
 	pdata->mii = mii;
 	pdata->mdio_mmd = MDIO_MMD_PCS;
 
-	pdata->phy_link = -1;
-	pdata->phy_speed = SPEED_UNKNOWN;
-	pdata->phy_tx_pause = pdata->tx_pause;
-	pdata->phy_rx_pause = pdata->rx_pause;
-
-	ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
-				 pdata->phy_mode);
-	if (ret) {
-		netdev_err(netdev, "phy_connect_direct failed\n");
-		goto err_phy_device;
-	}
-
-	if (!phydev->drv || (phydev->drv->phy_id == 0)) {
-		netdev_err(netdev, "phy_id not valid\n");
-		ret = -ENODEV;
-		goto err_phy_connect;
-	}
-	DBGPR("  phy_connect_direct succeeded for PHY %s, link=%d\n",
-	      dev_name(&phydev->dev), phydev->link);
-
 	phydev->autoneg = pdata->default_autoneg;
 	if (phydev->autoneg == AUTONEG_DISABLE) {
-		/* Add settings needed to force speed */
-		phydev->supported |= SUPPORTED_1000baseT_Full;
-		phydev->supported |= SUPPORTED_10000baseT_Full;
-
 		phydev->speed = pdata->default_speed;
 		phydev->duplex = DUPLEX_FULL;
 
@@ -395,9 +292,6 @@ int xgbe_mdio_register(struct xgbe_prv_d
 
 	return 0;
 
-err_phy_connect:
-	phy_disconnect(phydev);
-
 err_phy_device:
 	phy_device_free(phydev);
 
@@ -417,7 +311,6 @@ void xgbe_mdio_unregister(struct xgbe_pr
 {
 	DBGPR("-->xgbe_mdio_unregister\n");
 
-	phy_disconnect(pdata->phydev);
 	pdata->phydev = NULL;
 
 	module_put(pdata->phy_module);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,285 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014 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 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/clk.h>
+#include <linux/clocksource.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/net_tstamp.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+
+static cycle_t xgbe_cc_read(const struct cyclecounter *cc)
+{
+	struct xgbe_prv_data *pdata = container_of(cc,
+						   struct xgbe_prv_data,
+						   tstamp_cc);
+	u64 nsec;
+
+	nsec = pdata->hw_if.get_tstamp_time(pdata);
+
+	return nsec;
+}
+
+static int xgbe_adjfreq(struct ptp_clock_info *info, s32 delta)
+{
+	struct xgbe_prv_data *pdata = container_of(info,
+						   struct xgbe_prv_data,
+						   ptp_clock_info);
+	unsigned long flags;
+	u64 adjust;
+	u32 addend, diff;
+	unsigned int neg_adjust = 0;
+
+	if (delta < 0) {
+		neg_adjust = 1;
+		delta = -delta;
+	}
+
+	adjust = pdata->tstamp_addend;
+	adjust *= delta;
+	diff = div_u64(adjust, 1000000000UL);
+
+	addend = (neg_adjust) ? pdata->tstamp_addend - diff :
+				pdata->tstamp_addend + diff;
+
+	spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+	pdata->hw_if.update_tstamp_addend(pdata, addend);
+
+	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+	return 0;
+}
+
+static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
+{
+	struct xgbe_prv_data *pdata = container_of(info,
+						   struct xgbe_prv_data,
+						   ptp_clock_info);
+	unsigned long flags;
+	u64 nsec;
+
+	spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+	nsec = timecounter_read(&pdata->tstamp_tc);
+
+	nsec += delta;
+	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+
+	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+	return 0;
+}
+
+static int xgbe_gettime(struct ptp_clock_info *info, struct timespec *ts)
+{
+	struct xgbe_prv_data *pdata = container_of(info,
+						   struct xgbe_prv_data,
+						   ptp_clock_info);
+	unsigned long flags;
+	u64 nsec;
+
+	spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+	nsec = timecounter_read(&pdata->tstamp_tc);
+
+	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+	*ts = ns_to_timespec(nsec);
+
+	return 0;
+}
+
+static int xgbe_settime(struct ptp_clock_info *info, const struct timespec *ts)
+{
+	struct xgbe_prv_data *pdata = container_of(info,
+						   struct xgbe_prv_data,
+						   ptp_clock_info);
+	unsigned long flags;
+	u64 nsec;
+
+	nsec = timespec_to_ns(ts);
+
+	spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+
+	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+	return 0;
+}
+
+static int xgbe_enable(struct ptp_clock_info *info,
+		       struct ptp_clock_request *request, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+void xgbe_ptp_register(struct xgbe_prv_data *pdata)
+{
+	struct ptp_clock_info *info = &pdata->ptp_clock_info;
+	struct ptp_clock *clock;
+	struct cyclecounter *cc = &pdata->tstamp_cc;
+	u64 dividend;
+
+	snprintf(info->name, sizeof(info->name), "%s",
+		 netdev_name(pdata->netdev));
+	info->owner = THIS_MODULE;
+	info->max_adj = clk_get_rate(pdata->ptpclk);
+	info->adjfreq = xgbe_adjfreq;
+	info->adjtime = xgbe_adjtime;
+	info->gettime = xgbe_gettime;
+	info->settime = xgbe_settime;
+	info->enable = xgbe_enable;
+
+	clock = ptp_clock_register(info, pdata->dev);
+	if (IS_ERR(clock)) {
+		dev_err(pdata->dev, "ptp_clock_register failed\n");
+		return;
+	}
+
+	pdata->ptp_clock = clock;
+
+	/* Calculate the addend:
+	 *   addend = 2^32 / (PTP ref clock / 50Mhz)
+	 *          = (2^32 * 50Mhz) / PTP ref clock
+	 */
+	dividend = 50000000;
+	dividend <<= 32;
+	pdata->tstamp_addend = div_u64(dividend, clk_get_rate(pdata->ptpclk));
+
+	/* Setup the timecounter */
+	cc->read = xgbe_cc_read;
+	cc->mask = CLOCKSOURCE_MASK(64);
+	cc->mult = 1;
+	cc->shift = 0;
+
+	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+			 ktime_to_ns(ktime_get_real()));
+
+	/* Disable all timestamping to start */
+	XGMAC_IOWRITE(pdata, MAC_TCR, 0);
+	pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+	pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+}
+
+void xgbe_ptp_unregister(struct xgbe_prv_data *pdata)
+{
+	if (pdata->ptp_clock)
+		ptp_clock_unregister(pdata->ptp_clock);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+source "drivers/net/ethernet/apm/xgene/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# Makefile for APM X-GENE Ethernet driver.
+#
+
+obj-$(CONFIG_NET_XGENE) += xgene/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,10 @@
+config NET_XGENE
+	tristate "APM X-Gene SoC Ethernet Driver"
+	depends on HAS_DMA
+	select PHYLIB
+	help
+	  This is the Ethernet driver for the on-chip ethernet interface on the
+	  APM X-Gene SoC.
+
+	  To compile this driver as a module, choose M here. This module will
+	  be called xgene_enet.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet Driver.
+#
+
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
+obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,125 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/ethtool.h>
+#include "xgene_enet_main.h"
+
+struct xgene_gstrings_stats {
+	char name[ETH_GSTRING_LEN];
+	int offset;
+};
+
+#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
+
+static const struct xgene_gstrings_stats gstrings_stats[] = {
+	XGENE_STAT(rx_packets),
+	XGENE_STAT(tx_packets),
+	XGENE_STAT(rx_bytes),
+	XGENE_STAT(tx_bytes),
+	XGENE_STAT(rx_errors),
+	XGENE_STAT(tx_errors),
+	XGENE_STAT(rx_length_errors),
+	XGENE_STAT(rx_crc_errors),
+	XGENE_STAT(rx_frame_errors),
+	XGENE_STAT(rx_fifo_errors)
+};
+
+#define XGENE_STATS_LEN		ARRAY_SIZE(gstrings_stats)
+
+static void xgene_get_drvinfo(struct net_device *ndev,
+			      struct ethtool_drvinfo *info)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct platform_device *pdev = pdata->pdev;
+
+	strcpy(info->driver, "xgene_enet");
+	strcpy(info->version, XGENE_DRV_VERSION);
+	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
+	sprintf(info->bus_info, "%s", pdev->name);
+}
+
+static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct phy_device *phydev = pdata->phy_dev;
+
+	if (phydev == NULL)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct phy_device *phydev = pdata->phy_dev;
+
+	if (phydev == NULL)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
+}
+
+static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	int i;
+	u8 *p = data;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	for (i = 0; i < XGENE_STATS_LEN; i++) {
+		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
+		p += ETH_GSTRING_LEN;
+	}
+}
+
+static int xgene_get_sset_count(struct net_device *ndev, int sset)
+{
+	if (sset != ETH_SS_STATS)
+		return -EINVAL;
+
+	return XGENE_STATS_LEN;
+}
+
+static void xgene_get_ethtool_stats(struct net_device *ndev,
+				    struct ethtool_stats *dummy,
+				    u64 *data)
+{
+	void *pdata = netdev_priv(ndev);
+	int i;
+
+	for (i = 0; i < XGENE_STATS_LEN; i++)
+		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+}
+
+static const struct ethtool_ops xgene_ethtool_ops = {
+	.get_drvinfo = xgene_get_drvinfo,
+	.get_settings = xgene_get_settings,
+	.set_settings = xgene_set_settings,
+	.get_link = ethtool_op_get_link,
+	.get_strings = xgene_get_strings,
+	.get_sset_count = xgene_get_sset_count,
+	.get_ethtool_stats = xgene_get_ethtool_stats
+};
+
+void xgene_enet_set_ethtool_ops(struct net_device *ndev)
+{
+	ndev->ethtool_ops = &xgene_ethtool_ops;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,728 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *	    Ravi Patel <rapatel@apm.com>
+ *	    Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
+{
+	u32 *ring_cfg = ring->state;
+	u64 addr = ring->dma;
+	enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize;
+
+	ring_cfg[4] |= (1 << SELTHRSH_POS) &
+			CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN);
+	ring_cfg[3] |= ACCEPTLERR;
+	ring_cfg[2] |= QCOHERENT;
+
+	addr >>= 8;
+	ring_cfg[2] |= (addr << RINGADDRL_POS) &
+			CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN);
+	addr >>= RINGADDRL_LEN;
+	ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN);
+	ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) &
+			CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN);
+}
+
+static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring)
+{
+	u32 *ring_cfg = ring->state;
+	bool is_bufpool;
+	u32 val;
+
+	is_bufpool = xgene_enet_is_bufpool(ring->id);
+	val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR;
+	ring_cfg[4] |= (val << RINGTYPE_POS) &
+			CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN);
+
+	if (is_bufpool) {
+		ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) &
+				CREATE_MASK(RINGMODE_POS, RINGMODE_LEN);
+	}
+}
+
+static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring)
+{
+	u32 *ring_cfg = ring->state;
+
+	ring_cfg[3] |= RECOMBBUF;
+	ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) &
+			CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN);
+	ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN);
+}
+
+static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring,
+				 u32 offset, u32 data)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+	iowrite32(data, pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
+				 u32 offset, u32 *data)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+	*data = ioread32(pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
+{
+	int i;
+
+	xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
+	for (i = 0; i < NUM_RING_CONFIG; i++) {
+		xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
+				     ring->state[i]);
+	}
+}
+
+static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
+{
+	memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG);
+	xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
+{
+	xgene_enet_ring_set_type(ring);
+
+	if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
+		xgene_enet_ring_set_recombbuf(ring);
+
+	xgene_enet_ring_init(ring);
+	xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
+{
+	u32 ring_id_val, ring_id_buf;
+	bool is_bufpool;
+
+	is_bufpool = xgene_enet_is_bufpool(ring->id);
+
+	ring_id_val = ring->id & GENMASK(9, 0);
+	ring_id_val |= OVERWRITE;
+
+	ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
+	ring_id_buf |= PREFETCH_BUF_EN;
+	if (is_bufpool)
+		ring_id_buf |= IS_BUFFER_POOL;
+
+	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val);
+	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf);
+}
+
+static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
+{
+	u32 ring_id;
+
+	ring_id = ring->id | OVERWRITE;
+	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id);
+	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+					struct xgene_enet_desc_ring *ring)
+{
+	u32 size = ring->size;
+	u32 i, data;
+	bool is_bufpool;
+
+	xgene_enet_clr_ring_state(ring);
+	xgene_enet_set_ring_state(ring);
+	xgene_enet_set_ring_id(ring);
+
+	ring->slots = xgene_enet_get_numslots(ring->id, size);
+
+	is_bufpool = xgene_enet_is_bufpool(ring->id);
+	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+		return ring;
+
+	for (i = 0; i < ring->slots; i++)
+		xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]);
+
+	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+	data |= BIT(31 - xgene_enet_ring_bufnum(ring->id));
+	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+	return ring;
+}
+
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
+{
+	u32 data;
+	bool is_bufpool;
+
+	is_bufpool = xgene_enet_is_bufpool(ring->id);
+	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+		goto out;
+
+	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+	data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id));
+	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+out:
+	xgene_enet_clr_desc_ring_id(ring);
+	xgene_enet_clr_ring_state(ring);
+}
+
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+			    struct xgene_enet_pdata *pdata,
+			    enum xgene_enet_err_code status)
+{
+	struct rtnl_link_stats64 *stats = &pdata->stats;
+
+	switch (status) {
+	case INGRESS_CRC:
+		stats->rx_crc_errors++;
+		break;
+	case INGRESS_CHECKSUM:
+	case INGRESS_CHECKSUM_COMPUTE:
+		stats->rx_errors++;
+		break;
+	case INGRESS_TRUNC_FRAME:
+		stats->rx_frame_errors++;
+		break;
+	case INGRESS_PKT_LEN:
+		stats->rx_length_errors++;
+		break;
+	case INGRESS_PKT_UNDER:
+		stats->rx_frame_errors++;
+		break;
+	case INGRESS_FIFO_OVERRUN:
+		stats->rx_fifo_errors++;
+		break;
+	default:
+		break;
+	}
+}
+
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
+			      u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->eth_csr_addr + offset;
+
+	iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
+				  u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->eth_ring_if_addr + offset;
+
+	iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
+				   u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+	iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
+				  u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+	iowrite32(val, addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 wr_addr, u32 wr_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(wr_addr, addr);
+	iowrite32(wr_data, wr);
+	iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+	/* wait for write command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
+				  u32 wr_addr, u32 wr_data)
+{
+	void __iomem *addr, *wr, *cmd, *cmd_done;
+
+	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+	wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
+	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+		netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
+			   wr_addr);
+}
+
+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
+			      u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->eth_csr_addr + offset;
+
+	*val = ioread32(addr);
+}
+
+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
+				   u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+	*val = ioread32(addr);
+}
+
+static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
+				  u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+	*val = ioread32(addr);
+}
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 rd_addr, u32 *rd_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(rd_addr, addr);
+	iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+	/* wait for read command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	*rd_data = ioread32(rd);
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
+				  u32 rd_addr, u32 *rd_data)
+{
+	void __iomem *addr, *rd, *cmd, *cmd_done;
+
+	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+	rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
+	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+		netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
+			   rd_addr);
+}
+
+static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id,
+			       u32 reg, u16 data)
+{
+	u32 addr = 0, wr_data = 0;
+	u32 done;
+	u8 wait = 10;
+
+	PHY_ADDR_SET(&addr, phy_id);
+	REG_ADDR_SET(&addr, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+
+	PHY_CONTROL_SET(&wr_data, data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		netdev_err(pdata->ndev, "MII_MGMT write failed\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
+			      u8 phy_id, u32 reg)
+{
+	u32 addr = 0;
+	u32 data, done;
+	u8 wait = 10;
+
+	PHY_ADDR_SET(&addr, phy_id);
+	REG_ADDR_SET(&addr, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		netdev_err(pdata->ndev, "MII_MGMT read failed\n");
+		return -EBUSY;
+	}
+
+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
+
+	return data;
+}
+
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+{
+	u32 addr0, addr1;
+	u8 *dev_addr = pdata->ndev->dev_addr;
+
+	addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+		(dev_addr[1] << 8) | dev_addr[0];
+	addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+	addr1 |= pdata->phy_addr & 0xFFFF;
+
+	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
+	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
+{
+	struct net_device *ndev = pdata->ndev;
+	u32 data;
+	u8 wait = 10;
+
+	xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+	do {
+		usleep_range(100, 110);
+		xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
+	} while ((data != 0xffffffff) && wait--);
+
+	if (data != 0xffffffff) {
+		netdev_err(ndev, "Failed to release memory from shutdown\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
+{
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
+}
+
+void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
+{
+	u32 value, mc2;
+	u32 intf_ctl, rgmii;
+	u32 icm0, icm2;
+
+	xgene_gmac_reset(pdata);
+
+	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
+	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
+	xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
+	xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
+
+	switch (speed) {
+	case SPEED_10:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		CFG_MACMODE_SET(&icm0, 0);
+		CFG_WAITASYNCRD_SET(&icm2, 500);
+		rgmii &= ~CFG_SPEED_1250;
+		break;
+	case SPEED_100:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		intf_ctl |= ENET_LHD_MODE;
+		CFG_MACMODE_SET(&icm0, 1);
+		CFG_WAITASYNCRD_SET(&icm2, 80);
+		rgmii &= ~CFG_SPEED_1250;
+		break;
+	default:
+		ENET_INTERFACE_MODE2_SET(&mc2, 2);
+		intf_ctl |= ENET_GHD_MODE;
+		CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
+		xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
+		value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+		xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
+		break;
+	}
+
+	mc2 |= FULL_DUPLEX2;
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
+	xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
+
+	xgene_gmac_set_mac_addr(pdata);
+
+	/* Adjust MDC clock frequency */
+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
+	MGMT_CLOCK_SEL_SET(&value, 7);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
+
+	/* Enable drop if bufpool not available */
+	xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
+	value |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+	xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value);
+
+	/* Rtype should be copied from FP */
+	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
+	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+
+	/* Rx-Tx traffic resume */
+	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
+
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
+
+	xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
+	value &= ~TX_DV_GATE_EN0;
+	value &= ~RX_DV_GATE_EN0;
+	value |= RESUME_RX0;
+	xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value);
+
+	xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
+}
+
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
+{
+	u32 val = 0xffffffff;
+
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val);
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val);
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val);
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
+}
+
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+			   u32 dst_ring_num, u16 bufpool_id)
+{
+	u32 cb;
+	u32 fpsel;
+
+	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+
+	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
+	cb |= CFG_CLE_BYPASS_EN0;
+	CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
+	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
+
+	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);
+	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
+}
+
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
+}
+
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
+}
+
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
+}
+
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
+}
+
+void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+{
+	u32 val;
+
+	clk_prepare_enable(pdata->clk);
+	clk_disable_unprepare(pdata->clk);
+	clk_prepare_enable(pdata->clk);
+	xgene_enet_ecc_init(pdata);
+	xgene_enet_config_ring_if_assoc(pdata);
+
+	/* Enable auto-incr for scanning */
+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
+	val |= SCAN_AUTO_INCR;
+	MGMT_CLOCK_SEL_SET(&val, 1);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
+}
+
+void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
+{
+	clk_disable_unprepare(pdata->clk);
+}
+
+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_enet_pdata *pdata = bus->priv;
+	u32 val;
+
+	val = xgene_mii_phy_read(pdata, mii_id, regnum);
+	netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n",
+		   mii_id, regnum, val);
+
+	return val;
+}
+
+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+				 u16 val)
+{
+	struct xgene_enet_pdata *pdata = bus->priv;
+
+	netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n",
+		   mii_id, regnum, val);
+	return xgene_mii_phy_write(pdata, mii_id, regnum, val);
+}
+
+static void xgene_enet_adjust_link(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct phy_device *phydev = pdata->phy_dev;
+
+	if (phydev->link) {
+		if (pdata->phy_speed != phydev->speed) {
+			xgene_gmac_init(pdata, phydev->speed);
+			xgene_gmac_rx_enable(pdata);
+			xgene_gmac_tx_enable(pdata);
+			pdata->phy_speed = phydev->speed;
+			phy_print_status(phydev);
+		}
+	} else {
+		xgene_gmac_rx_disable(pdata);
+		xgene_gmac_tx_disable(pdata);
+		pdata->phy_speed = SPEED_UNKNOWN;
+		phy_print_status(phydev);
+	}
+}
+
+static int xgene_enet_phy_connect(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct device_node *phy_np;
+	struct phy_device *phy_dev;
+	struct device *dev = &pdata->pdev->dev;
+
+	phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
+	if (!phy_np) {
+		netdev_dbg(ndev, "No phy-handle found\n");
+		return -ENODEV;
+	}
+
+	phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+				 0, pdata->phy_mode);
+	if (!phy_dev) {
+		netdev_err(ndev, "Could not connect to PHY\n");
+		return  -ENODEV;
+	}
+
+	pdata->phy_speed = SPEED_UNKNOWN;
+	phy_dev->supported &= ~SUPPORTED_10baseT_Half &
+			      ~SUPPORTED_100baseT_Half &
+			      ~SUPPORTED_1000baseT_Half;
+	phy_dev->advertising = phy_dev->supported;
+	pdata->phy_dev = phy_dev;
+
+	return 0;
+}
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+{
+	struct net_device *ndev = pdata->ndev;
+	struct device *dev = &pdata->pdev->dev;
+	struct device_node *child_np;
+	struct device_node *mdio_np = NULL;
+	struct mii_bus *mdio_bus;
+	int ret;
+
+	for_each_child_of_node(dev->of_node, child_np) {
+		if (of_device_is_compatible(child_np, "apm,xgene-mdio")) {
+			mdio_np = child_np;
+			break;
+		}
+	}
+
+	if (!mdio_np) {
+		netdev_dbg(ndev, "No mdio node in the dts\n");
+		return -ENXIO;
+	}
+
+	mdio_bus = mdiobus_alloc();
+	if (!mdio_bus)
+		return -ENOMEM;
+
+	mdio_bus->name = "APM X-Gene MDIO bus";
+	mdio_bus->read = xgene_enet_mdio_read;
+	mdio_bus->write = xgene_enet_mdio_write;
+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii",
+		 ndev->name);
+
+	mdio_bus->priv = pdata;
+	mdio_bus->parent = &ndev->dev;
+
+	ret = of_mdiobus_register(mdio_bus, mdio_np);
+	if (ret) {
+		netdev_err(ndev, "Failed to register MDIO bus\n");
+		mdiobus_free(mdio_bus);
+		return ret;
+	}
+	pdata->mdio_bus = mdio_bus;
+
+	ret = xgene_enet_phy_connect(ndev);
+	if (ret)
+		xgene_enet_mdio_remove(pdata);
+
+	return ret;
+}
+
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
+{
+	mdiobus_unregister(pdata->mdio_bus);
+	mdiobus_free(pdata->mdio_bus);
+	pdata->mdio_bus = NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,337 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *	    Ravi Patel <rapatel@apm.com>
+ *	    Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_HW_H__
+#define __XGENE_ENET_HW_H__
+
+#include "xgene_enet_main.h"
+
+struct xgene_enet_pdata;
+struct xgene_enet_stats;
+
+/* clears and then set bits */
+static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len)
+{
+	u32 end = start + len - 1;
+	u32 mask = GENMASK(end, start);
+
+	*dst &= ~mask;
+	*dst |= (val << start) & mask;
+}
+
+static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
+{
+	return (val & GENMASK(end, start)) >> start;
+}
+
+#define CSR_RING_ID		0x0008
+#define OVERWRITE		BIT(31)
+#define IS_BUFFER_POOL		BIT(20)
+#define PREFETCH_BUF_EN		BIT(21)
+#define CSR_RING_ID_BUF		0x000c
+#define CSR_RING_NE_INT_MODE	0x017c
+#define CSR_RING_CONFIG		0x006c
+#define CSR_RING_WR_BASE	0x0070
+#define NUM_RING_CONFIG		5
+#define BUFPOOL_MODE		3
+#define RM3			3
+#define INC_DEC_CMD_ADDR	0x002c
+#define UDP_HDR_SIZE		2
+#define BUF_LEN_CODE_2K		0x5000
+
+#define CREATE_MASK(pos, len)		GENMASK((pos)+(len)-1, (pos))
+#define CREATE_MASK_ULL(pos, len)	GENMASK_ULL((pos)+(len)-1, (pos))
+
+/* Empty slot soft signature */
+#define EMPTY_SLOT_INDEX	1
+#define EMPTY_SLOT		~0ULL
+
+#define WORK_DESC_SIZE		32
+#define BUFPOOL_DESC_SIZE	16
+
+#define RING_OWNER_MASK		GENMASK(9, 6)
+#define RING_BUFNUM_MASK	GENMASK(5, 0)
+
+#define SELTHRSH_POS		3
+#define SELTHRSH_LEN		3
+#define RINGADDRL_POS		5
+#define RINGADDRL_LEN		27
+#define RINGADDRH_POS		0
+#define RINGADDRH_LEN		6
+#define RINGSIZE_POS		23
+#define RINGSIZE_LEN		3
+#define RINGTYPE_POS		19
+#define RINGTYPE_LEN		2
+#define RINGMODE_POS		20
+#define RINGMODE_LEN		3
+#define RECOMTIMEOUTL_POS	28
+#define RECOMTIMEOUTL_LEN	3
+#define RECOMTIMEOUTH_POS	0
+#define RECOMTIMEOUTH_LEN	2
+#define NUMMSGSINQ_POS		1
+#define NUMMSGSINQ_LEN		16
+#define ACCEPTLERR		BIT(19)
+#define QCOHERENT		BIT(4)
+#define RECOMBBUF		BIT(27)
+
+#define BLOCK_ETH_CSR_OFFSET		0x2000
+#define BLOCK_ETH_RING_IF_OFFSET	0x9000
+#define BLOCK_ETH_CLKRST_CSR_OFFSET	0xC000
+#define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000
+
+#define BLOCK_ETH_MAC_OFFSET		0x0000
+#define BLOCK_ETH_STATS_OFFSET		0x0014
+#define BLOCK_ETH_MAC_CSR_OFFSET	0x2800
+
+#define MAC_ADDR_REG_OFFSET		0x00
+#define MAC_COMMAND_REG_OFFSET		0x04
+#define MAC_WRITE_REG_OFFSET		0x08
+#define MAC_READ_REG_OFFSET		0x0c
+#define MAC_COMMAND_DONE_REG_OFFSET	0x10
+
+#define STAT_ADDR_REG_OFFSET		0x00
+#define STAT_COMMAND_REG_OFFSET		0x04
+#define STAT_WRITE_REG_OFFSET		0x08
+#define STAT_READ_REG_OFFSET		0x0c
+#define STAT_COMMAND_DONE_REG_OFFSET	0x10
+
+#define MII_MGMT_CONFIG_ADDR		0x20
+#define MII_MGMT_COMMAND_ADDR		0x24
+#define MII_MGMT_ADDRESS_ADDR		0x28
+#define MII_MGMT_CONTROL_ADDR		0x2c
+#define MII_MGMT_STATUS_ADDR		0x30
+#define MII_MGMT_INDICATORS_ADDR	0x34
+
+#define BUSY_MASK			BIT(0)
+#define READ_CYCLE_MASK			BIT(0)
+#define PHY_CONTROL_SET(dst, val)	xgene_set_bits(dst, val, 0, 16)
+
+#define ENET_SPARE_CFG_REG_ADDR		0x0750
+#define RSIF_CONFIG_REG_ADDR		0x0010
+#define RSIF_RAM_DBG_REG0_ADDR		0x0048
+#define RGMII_REG_0_ADDR		0x07e0
+#define CFG_LINK_AGGR_RESUME_0_ADDR	0x07c8
+#define DEBUG_REG_ADDR			0x0700
+#define CFG_BYPASS_ADDR			0x0294
+#define CLE_BYPASS_REG0_0_ADDR		0x0490
+#define CLE_BYPASS_REG1_0_ADDR		0x0494
+#define CFG_RSIF_FPBUFF_TIMEOUT_EN	BIT(31)
+#define RESUME_TX			BIT(0)
+#define CFG_SPEED_1250			BIT(24)
+#define TX_PORT0			BIT(0)
+#define CFG_BYPASS_UNISEC_TX		BIT(2)
+#define CFG_BYPASS_UNISEC_RX		BIT(1)
+#define CFG_CLE_BYPASS_EN0		BIT(31)
+#define CFG_TXCLK_MUXSEL0_SET(dst, val)	xgene_set_bits(dst, val, 29, 3)
+
+#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_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 ICM_CONFIG0_REG_0_ADDR		0x0400
+#define ICM_CONFIG2_REG_0_ADDR		0x0410
+#define RX_DV_GATE_REG_0_ADDR		0x05fc
+#define TX_DV_GATE_EN0			BIT(2)
+#define RX_DV_GATE_EN0			BIT(1)
+#define RESUME_RX0			BIT(0)
+#define ENET_CFGSSQMIWQASSOC_ADDR		0xe0
+#define ENET_CFGSSQMIFPQASSOC_ADDR		0xdc
+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR	0xf0
+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR		0xf4
+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR		0x70
+#define ENET_BLOCK_MEM_RDY_ADDR			0x74
+#define MAC_CONFIG_1_ADDR			0x00
+#define MAC_CONFIG_2_ADDR			0x04
+#define MAX_FRAME_LEN_ADDR			0x10
+#define INTERFACE_CONTROL_ADDR			0x38
+#define STATION_ADDR0_ADDR			0x40
+#define STATION_ADDR1_ADDR			0x44
+#define PHY_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 8, 5)
+#define REG_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 0, 5)
+#define ENET_INTERFACE_MODE2_SET(dst, val)	xgene_set_bits(dst, val, 8, 2)
+#define MGMT_CLOCK_SEL_SET(dst, val)		xgene_set_bits(dst, val, 0, 3)
+#define SOFT_RESET1			BIT(31)
+#define TX_EN				BIT(0)
+#define RX_EN				BIT(2)
+#define ENET_LHD_MODE			BIT(25)
+#define ENET_GHD_MODE			BIT(26)
+#define FULL_DUPLEX2			BIT(0)
+#define SCAN_AUTO_INCR			BIT(5)
+#define TBYT_ADDR			0x38
+#define TPKT_ADDR			0x39
+#define TDRP_ADDR			0x45
+#define TFCS_ADDR			0x47
+#define TUND_ADDR			0x4a
+
+#define TSO_IPPROTO_TCP			1
+#define	FULL_DUPLEX			2
+
+#define USERINFO_POS			0
+#define USERINFO_LEN			32
+#define FPQNUM_POS			32
+#define FPQNUM_LEN			12
+#define LERR_POS			60
+#define LERR_LEN			3
+#define STASH_POS			52
+#define STASH_LEN			2
+#define BUFDATALEN_POS			48
+#define BUFDATALEN_LEN			12
+#define DATAADDR_POS			0
+#define DATAADDR_LEN			42
+#define COHERENT_POS			63
+#define HENQNUM_POS			48
+#define HENQNUM_LEN			12
+#define TYPESEL_POS			44
+#define TYPESEL_LEN			4
+#define ETHHDR_POS			12
+#define ETHHDR_LEN			8
+#define IC_POS				35	/* Insert CRC */
+#define TCPHDR_POS			0
+#define TCPHDR_LEN			6
+#define IPHDR_POS			6
+#define IPHDR_LEN			6
+#define EC_POS				22	/* Enable checksum */
+#define EC_LEN				1
+#define IS_POS				24	/* IP protocol select */
+#define IS_LEN				1
+#define TYPE_ETH_WORK_MESSAGE_POS	44
+
+struct xgene_enet_raw_desc {
+	__le64 m0;
+	__le64 m1;
+	__le64 m2;
+	__le64 m3;
+};
+
+struct xgene_enet_raw_desc16 {
+	__le64 m0;
+	__le64 m1;
+};
+
+static inline void xgene_enet_mark_desc_slot_empty(void *desc_slot_ptr)
+{
+	__le64 *desc_slot = desc_slot_ptr;
+
+	desc_slot[EMPTY_SLOT_INDEX] = cpu_to_le64(EMPTY_SLOT);
+}
+
+static inline bool xgene_enet_is_desc_slot_empty(void *desc_slot_ptr)
+{
+	__le64 *desc_slot = desc_slot_ptr;
+
+	return (desc_slot[EMPTY_SLOT_INDEX] == cpu_to_le64(EMPTY_SLOT));
+}
+
+enum xgene_enet_ring_cfgsize {
+	RING_CFGSIZE_512B,
+	RING_CFGSIZE_2KB,
+	RING_CFGSIZE_16KB,
+	RING_CFGSIZE_64KB,
+	RING_CFGSIZE_512KB,
+	RING_CFGSIZE_INVALID
+};
+
+enum xgene_enet_ring_type {
+	RING_DISABLED,
+	RING_REGULAR,
+	RING_BUFPOOL
+};
+
+enum xgene_ring_owner {
+	RING_OWNER_ETH0,
+	RING_OWNER_CPU = 15,
+	RING_OWNER_INVALID
+};
+
+enum xgene_enet_ring_bufnum {
+	RING_BUFNUM_REGULAR = 0x0,
+	RING_BUFNUM_BUFPOOL = 0x20,
+	RING_BUFNUM_INVALID
+};
+
+enum xgene_enet_cmd {
+	XGENE_ENET_WR_CMD = BIT(31),
+	XGENE_ENET_RD_CMD = BIT(30)
+};
+
+enum xgene_enet_err_code {
+	HBF_READ_DATA = 3,
+	HBF_LL_READ = 4,
+	BAD_WORK_MSG = 6,
+	BUFPOOL_TIMEOUT = 15,
+	INGRESS_CRC = 16,
+	INGRESS_CHECKSUM = 17,
+	INGRESS_TRUNC_FRAME = 18,
+	INGRESS_PKT_LEN = 19,
+	INGRESS_PKT_UNDER = 20,
+	INGRESS_FIFO_OVERRUN = 21,
+	INGRESS_CHECKSUM_COMPUTE = 26,
+	ERR_CODE_INVALID
+};
+
+static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id)
+{
+	return (id & RING_OWNER_MASK) >> 6;
+}
+
+static inline u8 xgene_enet_ring_bufnum(u16 id)
+{
+	return id & RING_BUFNUM_MASK;
+}
+
+static inline bool xgene_enet_is_bufpool(u16 id)
+{
+	return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
+}
+
+static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
+{
+	bool is_bufpool = xgene_enet_is_bufpool(id);
+
+	return (is_bufpool) ? size / BUFPOOL_DESC_SIZE :
+		      size / WORK_DESC_SIZE;
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+		struct xgene_enet_desc_ring *ring);
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring);
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+			    struct xgene_enet_pdata *pdata,
+			    enum xgene_enet_err_code status);
+
+void xgene_enet_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+			   u32 dst_ring_num, u16 bufpool_id);
+void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
+void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+
+#endif /* __XGENE_ENET_HW_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,960 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *	    Ravi Patel <rapatel@apm.com>
+ *	    Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+	struct xgene_enet_raw_desc16 *raw_desc;
+	int i;
+
+	for (i = 0; i < buf_pool->slots; i++) {
+		raw_desc = &buf_pool->raw_desc16[i];
+
+		/* Hardware expects descriptor in little endian format */
+		raw_desc->m0 = cpu_to_le64(i |
+				SET_VAL(FPQNUM, buf_pool->dst_ring_num) |
+				SET_VAL(STASH, 3));
+	}
+}
+
+static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
+				     u32 nbuf)
+{
+	struct sk_buff *skb;
+	struct xgene_enet_raw_desc16 *raw_desc;
+	struct net_device *ndev;
+	struct device *dev;
+	dma_addr_t dma_addr;
+	u32 tail = buf_pool->tail;
+	u32 slots = buf_pool->slots - 1;
+	u16 bufdatalen, len;
+	int i;
+
+	ndev = buf_pool->ndev;
+	dev = ndev_to_dev(buf_pool->ndev);
+	bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
+	len = XGENE_ENET_MAX_MTU;
+
+	for (i = 0; i < nbuf; i++) {
+		raw_desc = &buf_pool->raw_desc16[tail];
+
+		skb = netdev_alloc_skb_ip_align(ndev, len);
+		if (unlikely(!skb))
+			return -ENOMEM;
+		buf_pool->rx_skb[tail] = skb;
+
+		dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, dma_addr)) {
+			netdev_err(ndev, "DMA mapping error\n");
+			dev_kfree_skb_any(skb);
+			return -EINVAL;
+		}
+
+		raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+					   SET_VAL(BUFDATALEN, bufdatalen) |
+					   SET_BIT(COHERENT));
+		tail = (tail + 1) & slots;
+	}
+
+	iowrite32(nbuf, buf_pool->cmd);
+	buf_pool->tail = tail;
+
+	return 0;
+}
+
+static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+	return ((u16)pdata->rm << 10) | ring->num;
+}
+
+static u8 xgene_enet_hdr_len(const void *data)
+{
+	const struct ethhdr *eth = data;
+
+	return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+{
+	u32 __iomem *cmd_base = ring->cmd_base;
+	u32 ring_state, num_msgs;
+
+	ring_state = ioread32(&cmd_base[1]);
+	num_msgs = ring_state & CREATE_MASK(NUMMSGSINQ_POS, NUMMSGSINQ_LEN);
+
+	return num_msgs >> NUMMSGSINQ_POS;
+}
+
+static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+	struct xgene_enet_raw_desc16 *raw_desc;
+	u32 slots = buf_pool->slots - 1;
+	u32 tail = buf_pool->tail;
+	u32 userinfo;
+	int i, len;
+
+	len = xgene_enet_ring_len(buf_pool);
+	for (i = 0; i < len; i++) {
+		tail = (tail - 1) & slots;
+		raw_desc = &buf_pool->raw_desc16[tail];
+
+		/* Hardware stores descriptor in little endian format */
+		userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+		dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
+	}
+
+	iowrite32(-len, buf_pool->cmd);
+	buf_pool->tail = tail;
+}
+
+static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
+{
+	struct xgene_enet_desc_ring *rx_ring = data;
+
+	if (napi_schedule_prep(&rx_ring->napi)) {
+		disable_irq_nosync(irq);
+		__napi_schedule(&rx_ring->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+				    struct xgene_enet_raw_desc *raw_desc)
+{
+	struct sk_buff *skb;
+	struct device *dev;
+	u16 skb_index;
+	u8 status;
+	int ret = 0;
+
+	skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+	skb = cp_ring->cp_skb[skb_index];
+
+	dev = ndev_to_dev(cp_ring->ndev);
+	dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+			 GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)),
+			 DMA_TO_DEVICE);
+
+	/* Checking for error */
+	status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+	if (unlikely(status > 2)) {
+		xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
+				       status);
+		ret = -EIO;
+	}
+
+	if (likely(skb)) {
+		dev_kfree_skb_any(skb);
+	} else {
+		netdev_err(cp_ring->ndev, "completion skb is NULL\n");
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+static u64 xgene_enet_work_msg(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	u8 l3hlen, l4hlen = 0;
+	u8 csum_enable = 0;
+	u8 proto = 0;
+	u8 ethhdr;
+	u64 hopinfo;
+
+	if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
+	    unlikely(skb->protocol != htons(ETH_P_8021Q)))
+		goto out;
+
+	if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM)))
+		goto out;
+
+	iph = ip_hdr(skb);
+	if (unlikely(ip_is_fragment(iph)))
+		goto out;
+
+	if (likely(iph->protocol == IPPROTO_TCP)) {
+		l4hlen = tcp_hdrlen(skb) >> 2;
+		csum_enable = 1;
+		proto = TSO_IPPROTO_TCP;
+	} else if (iph->protocol == IPPROTO_UDP) {
+		l4hlen = UDP_HDR_SIZE;
+		csum_enable = 1;
+	}
+out:
+	l3hlen = ip_hdrlen(skb) >> 2;
+	ethhdr = xgene_enet_hdr_len(skb->data);
+	hopinfo = SET_VAL(TCPHDR, l4hlen) |
+		  SET_VAL(IPHDR, l3hlen) |
+		  SET_VAL(ETHHDR, ethhdr) |
+		  SET_VAL(EC, csum_enable) |
+		  SET_VAL(IS, proto) |
+		  SET_BIT(IC) |
+		  SET_BIT(TYPE_ETH_WORK_MESSAGE);
+
+	return hopinfo;
+}
+
+static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
+				    struct sk_buff *skb)
+{
+	struct device *dev = ndev_to_dev(tx_ring->ndev);
+	struct xgene_enet_raw_desc *raw_desc;
+	dma_addr_t dma_addr;
+	u16 tail = tx_ring->tail;
+	u64 hopinfo;
+
+	raw_desc = &tx_ring->raw_desc[tail];
+	memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
+
+	dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, dma_addr)) {
+		netdev_err(tx_ring->ndev, "DMA mapping error\n");
+		return -EINVAL;
+	}
+
+	/* Hardware expects descriptor in little endian format */
+	raw_desc->m0 = cpu_to_le64(tail);
+	raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+				   SET_VAL(BUFDATALEN, skb->len) |
+				   SET_BIT(COHERENT));
+	hopinfo = xgene_enet_work_msg(skb);
+	raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
+				   hopinfo);
+	tx_ring->cp_ring->cp_skb[tail] = skb;
+
+	return 0;
+}
+
+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+					 struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
+	struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
+	u32 tx_level, cq_level;
+
+	tx_level = xgene_enet_ring_len(tx_ring);
+	cq_level = xgene_enet_ring_len(cp_ring);
+	if (unlikely(tx_level > pdata->tx_qcnt_hi ||
+		     cq_level > pdata->cp_qcnt_hi)) {
+		netif_stop_queue(ndev);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (xgene_enet_setup_tx_desc(tx_ring, skb)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	iowrite32(1, tx_ring->cmd);
+	skb_tx_timestamp(skb);
+	tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1);
+
+	pdata->stats.tx_packets++;
+	pdata->stats.tx_bytes += skb->len;
+
+	return NETDEV_TX_OK;
+}
+
+static void xgene_enet_skip_csum(struct sk_buff *skb)
+{
+	struct iphdr *iph = ip_hdr(skb);
+
+	if (!ip_is_fragment(iph) ||
+	    (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+}
+
+static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
+			       struct xgene_enet_raw_desc *raw_desc)
+{
+	struct net_device *ndev;
+	struct xgene_enet_pdata *pdata;
+	struct device *dev;
+	struct xgene_enet_desc_ring *buf_pool;
+	u32 datalen, skb_index;
+	struct sk_buff *skb;
+	u8 status;
+	int ret = 0;
+
+	ndev = rx_ring->ndev;
+	pdata = netdev_priv(ndev);
+	dev = ndev_to_dev(rx_ring->ndev);
+	buf_pool = rx_ring->buf_pool;
+
+	dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+			 XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+	skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+	skb = buf_pool->rx_skb[skb_index];
+
+	/* checking for error */
+	status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+	if (unlikely(status > 2)) {
+		dev_kfree_skb_any(skb);
+		xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
+				       status);
+		pdata->stats.rx_dropped++;
+		ret = -EIO;
+		goto out;
+	}
+
+	/* strip off CRC as HW isn't doing this */
+	datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
+	datalen -= 4;
+	prefetch(skb->data - NET_IP_ALIGN);
+	skb_put(skb, datalen);
+
+	skb_checksum_none_assert(skb);
+	skb->protocol = eth_type_trans(skb, ndev);
+	if (likely((ndev->features & NETIF_F_IP_CSUM) &&
+		   skb->protocol == htons(ETH_P_IP))) {
+		xgene_enet_skip_csum(skb);
+	}
+
+	pdata->stats.rx_packets++;
+	pdata->stats.rx_bytes += datalen;
+	napi_gro_receive(&rx_ring->napi, skb);
+out:
+	if (--rx_ring->nbufpool == 0) {
+		ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
+		rx_ring->nbufpool = NUM_BUFPOOL;
+	}
+
+	return ret;
+}
+
+static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc)
+{
+	return GET_VAL(FPQNUM, le64_to_cpu(raw_desc->m0)) ? true : false;
+}
+
+static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+				   int budget)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+	struct xgene_enet_raw_desc *raw_desc;
+	u16 head = ring->head;
+	u16 slots = ring->slots - 1;
+	int ret, count = 0;
+
+	do {
+		raw_desc = &ring->raw_desc[head];
+		if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
+			break;
+
+		if (is_rx_desc(raw_desc))
+			ret = xgene_enet_rx_frame(ring, raw_desc);
+		else
+			ret = xgene_enet_tx_completion(ring, raw_desc);
+		xgene_enet_mark_desc_slot_empty(raw_desc);
+
+		head = (head + 1) & slots;
+		count++;
+
+		if (ret)
+			break;
+	} while (--budget);
+
+	if (likely(count)) {
+		iowrite32(-count, ring->cmd);
+		ring->head = head;
+
+		if (netif_queue_stopped(ring->ndev)) {
+			if (xgene_enet_ring_len(ring) < pdata->cp_qcnt_low)
+				netif_wake_queue(ring->ndev);
+		}
+	}
+
+	return budget;
+}
+
+static int xgene_enet_napi(struct napi_struct *napi, const int budget)
+{
+	struct xgene_enet_desc_ring *ring;
+	int processed;
+
+	ring = container_of(napi, struct xgene_enet_desc_ring, napi);
+	processed = xgene_enet_process_ring(ring, budget);
+
+	if (processed != budget) {
+		napi_complete(napi);
+		enable_irq(ring->irq);
+	}
+
+	return processed;
+}
+
+static void xgene_enet_timeout(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+	xgene_gmac_reset(pdata);
+}
+
+static int xgene_enet_register_irq(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct device *dev = ndev_to_dev(ndev);
+	int ret;
+
+	ret = devm_request_irq(dev, pdata->rx_ring->irq, xgene_enet_rx_irq,
+			       IRQF_SHARED, ndev->name, pdata->rx_ring);
+	if (ret) {
+		netdev_err(ndev, "rx%d interrupt request failed\n",
+			   pdata->rx_ring->irq);
+	}
+
+	return ret;
+}
+
+static void xgene_enet_free_irq(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata;
+	struct device *dev;
+
+	pdata = netdev_priv(ndev);
+	dev = ndev_to_dev(ndev);
+	devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
+}
+
+static int xgene_enet_open(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	int ret;
+
+	xgene_gmac_tx_enable(pdata);
+	xgene_gmac_rx_enable(pdata);
+
+	ret = xgene_enet_register_irq(ndev);
+	if (ret)
+		return ret;
+	napi_enable(&pdata->rx_ring->napi);
+
+	if (pdata->phy_dev)
+		phy_start(pdata->phy_dev);
+
+	netif_start_queue(ndev);
+
+	return ret;
+}
+
+static int xgene_enet_close(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+	netif_stop_queue(ndev);
+
+	if (pdata->phy_dev)
+		phy_stop(pdata->phy_dev);
+
+	napi_disable(&pdata->rx_ring->napi);
+	xgene_enet_free_irq(ndev);
+	xgene_enet_process_ring(pdata->rx_ring, -1);
+
+	xgene_gmac_tx_disable(pdata);
+	xgene_gmac_rx_disable(pdata);
+
+	return 0;
+}
+
+static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
+{
+	struct xgene_enet_pdata *pdata;
+	struct device *dev;
+
+	pdata = netdev_priv(ring->ndev);
+	dev = ndev_to_dev(ring->ndev);
+
+	xgene_enet_clear_ring(ring);
+	dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+}
+
+static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
+{
+	struct xgene_enet_desc_ring *buf_pool;
+
+	if (pdata->tx_ring) {
+		xgene_enet_delete_ring(pdata->tx_ring);
+		pdata->tx_ring = NULL;
+	}
+
+	if (pdata->rx_ring) {
+		buf_pool = pdata->rx_ring->buf_pool;
+		xgene_enet_delete_bufpool(buf_pool);
+		xgene_enet_delete_ring(buf_pool);
+		xgene_enet_delete_ring(pdata->rx_ring);
+		pdata->rx_ring = NULL;
+	}
+}
+
+static int xgene_enet_get_ring_size(struct device *dev,
+				    enum xgene_enet_ring_cfgsize cfgsize)
+{
+	int size = -EINVAL;
+
+	switch (cfgsize) {
+	case RING_CFGSIZE_512B:
+		size = 0x200;
+		break;
+	case RING_CFGSIZE_2KB:
+		size = 0x800;
+		break;
+	case RING_CFGSIZE_16KB:
+		size = 0x4000;
+		break;
+	case RING_CFGSIZE_64KB:
+		size = 0x10000;
+		break;
+	case RING_CFGSIZE_512KB:
+		size = 0x80000;
+		break;
+	default:
+		dev_err(dev, "Unsupported cfg ring size %d\n", cfgsize);
+		break;
+	}
+
+	return size;
+}
+
+static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
+{
+	struct device *dev;
+
+	if (!ring)
+		return;
+
+	dev = ndev_to_dev(ring->ndev);
+
+	if (ring->desc_addr) {
+		xgene_enet_clear_ring(ring);
+		dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+	}
+	devm_kfree(dev, ring);
+}
+
+static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+	struct xgene_enet_desc_ring *ring;
+
+	ring = pdata->tx_ring;
+	if (ring) {
+		if (ring->cp_ring && ring->cp_ring->cp_skb)
+			devm_kfree(dev, ring->cp_ring->cp_skb);
+		xgene_enet_free_desc_ring(ring);
+	}
+
+	ring = pdata->rx_ring;
+	if (ring) {
+		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);
+		}
+		xgene_enet_free_desc_ring(ring);
+	}
+}
+
+static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
+			struct net_device *ndev, u32 ring_num,
+			enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
+{
+	struct xgene_enet_desc_ring *ring;
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct device *dev = ndev_to_dev(ndev);
+	int size;
+
+	size = xgene_enet_get_ring_size(dev, cfgsize);
+	if (size < 0)
+		return NULL;
+
+	ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring),
+			    GFP_KERNEL);
+	if (!ring)
+		return NULL;
+
+	ring->ndev = ndev;
+	ring->num = ring_num;
+	ring->cfgsize = cfgsize;
+	ring->id = ring_id;
+
+	ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
+					      GFP_KERNEL);
+	if (!ring->desc_addr) {
+		devm_kfree(dev, ring);
+		return NULL;
+	}
+	ring->size = size;
+
+	ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
+	ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
+	pdata->rm = RM3;
+	ring = xgene_enet_setup_ring(ring);
+	netdev_dbg(ndev, "ring info: num=%d  size=%d  id=%d  slots=%d\n",
+		   ring->num, ring->size, ring->id, ring->slots);
+
+	return ring;
+}
+
+static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum)
+{
+	return (owner << 6) | (bufnum & GENMASK(5, 0));
+}
+
+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_desc_ring *buf_pool = NULL;
+	u8 cpu_bufnum = 0, eth_bufnum = 0;
+	u8 bp_bufnum = 0x20;
+	u16 ring_id, ring_num = 0;
+	int ret;
+
+	/* allocate rx descriptor ring */
+	ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
+	rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+					      RING_CFGSIZE_16KB, ring_id);
+	if (!rx_ring) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* allocate buffer pool for receiving packets */
+	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++);
+	buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+					       RING_CFGSIZE_2KB, ring_id);
+	if (!buf_pool) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	rx_ring->nbufpool = NUM_BUFPOOL;
+	rx_ring->buf_pool = buf_pool;
+	rx_ring->irq = pdata->rx_irq;
+	buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
+					sizeof(struct sk_buff *), GFP_KERNEL);
+	if (!buf_pool->rx_skb) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
+	rx_ring->buf_pool = buf_pool;
+	pdata->rx_ring = rx_ring;
+
+	/* allocate tx descriptor ring */
+	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++);
+	tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+					      RING_CFGSIZE_16KB, ring_id);
+	if (!tx_ring) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	pdata->tx_ring = tx_ring;
+
+	cp_ring = pdata->rx_ring;
+	cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
+				       sizeof(struct sk_buff *), GFP_KERNEL);
+	if (!cp_ring->cp_skb) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	pdata->tx_ring->cp_ring = cp_ring;
+	pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
+
+	pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
+	pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
+	pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
+
+	return 0;
+
+err:
+	xgene_enet_free_desc_rings(pdata);
+	return ret;
+}
+
+static struct rtnl_link_stats64 *xgene_enet_get_stats64(
+			struct net_device *ndev,
+			struct rtnl_link_stats64 *storage)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct rtnl_link_stats64 *stats = &pdata->stats;
+
+	stats->rx_errors += stats->rx_length_errors +
+			    stats->rx_crc_errors +
+			    stats->rx_frame_errors +
+			    stats->rx_fifo_errors;
+	memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
+
+	return storage;
+}
+
+static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	int ret;
+
+	ret = eth_mac_addr(ndev, addr);
+	if (ret)
+		return ret;
+	xgene_gmac_set_mac_addr(pdata);
+
+	return ret;
+}
+
+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_set_mac_address = xgene_enet_set_mac_address,
+};
+
+static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+{
+	struct platform_device *pdev;
+	struct net_device *ndev;
+	struct device *dev;
+	struct resource *res;
+	void __iomem *base_addr;
+	const char *mac;
+	int ret;
+
+	pdev = pdata->pdev;
+	dev = &pdev->dev;
+	ndev = pdata->ndev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
+	if (!res) {
+		dev_err(dev, "Resource enet_csr not defined\n");
+		return -ENODEV;
+	}
+	pdata->base_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->base_addr)) {
+		dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+		return PTR_ERR(pdata->base_addr);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
+	if (!res) {
+		dev_err(dev, "Resource ring_csr not defined\n");
+		return -ENODEV;
+	}
+	pdata->ring_csr_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->ring_csr_addr)) {
+		dev_err(dev, "Unable to retrieve ENET Ring CSR region\n");
+		return PTR_ERR(pdata->ring_csr_addr);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
+	if (!res) {
+		dev_err(dev, "Resource ring_cmd not defined\n");
+		return -ENODEV;
+	}
+	pdata->ring_cmd_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->ring_cmd_addr)) {
+		dev_err(dev, "Unable to retrieve ENET Ring command region\n");
+		return PTR_ERR(pdata->ring_cmd_addr);
+	}
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret <= 0) {
+		dev_err(dev, "Unable to get ENET Rx IRQ\n");
+		ret = ret ? : -ENXIO;
+		return ret;
+	}
+	pdata->rx_irq = ret;
+
+	mac = of_get_mac_address(dev->of_node);
+	if (mac)
+		memcpy(ndev->dev_addr, mac, ndev->addr_len);
+	else
+		eth_hw_addr_random(ndev);
+	memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+	pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+	if (pdata->phy_mode < 0) {
+		dev_err(dev, "Incorrect phy-connection-type in DTS\n");
+		return -EINVAL;
+	}
+
+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+	ret = IS_ERR(pdata->clk);
+	if (IS_ERR(pdata->clk)) {
+		dev_err(&pdev->dev, "can't get clock\n");
+		ret = PTR_ERR(pdata->clk);
+		return ret;
+	}
+
+	base_addr = pdata->base_addr;
+	pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
+	pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
+	pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
+	pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
+	pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
+	pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
+	pdata->rx_buff_cnt = NUM_PKT_BUF;
+
+	return ret;
+}
+
+static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+{
+	struct net_device *ndev = pdata->ndev;
+	struct xgene_enet_desc_ring *buf_pool;
+	u16 dst_ring_num;
+	int ret;
+
+	xgene_gmac_tx_disable(pdata);
+	xgene_gmac_rx_disable(pdata);
+
+	ret = xgene_enet_create_desc_rings(ndev);
+	if (ret) {
+		netdev_err(ndev, "Error in ring configuration\n");
+		return ret;
+	}
+
+	/* setup buffer pool */
+	buf_pool = pdata->rx_ring->buf_pool;
+	xgene_enet_init_bufpool(buf_pool);
+	ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+	if (ret) {
+		xgene_enet_delete_desc_rings(pdata);
+		return ret;
+	}
+
+	dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
+	xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
+
+	return ret;
+}
+
+static int xgene_enet_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev;
+	struct xgene_enet_pdata *pdata;
+	struct device *dev = &pdev->dev;
+	struct napi_struct *napi;
+	int ret;
+
+	ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
+	if (!ndev)
+		return -ENOMEM;
+
+	pdata = netdev_priv(ndev);
+
+	pdata->pdev = pdev;
+	pdata->ndev = ndev;
+	SET_NETDEV_DEV(ndev, dev);
+	platform_set_drvdata(pdev, pdata);
+	ndev->netdev_ops = &xgene_ndev_ops;
+	xgene_enet_set_ethtool_ops(ndev);
+	ndev->features |= NETIF_F_IP_CSUM |
+			  NETIF_F_GSO |
+			  NETIF_F_GRO;
+
+	ret = xgene_enet_get_resources(pdata);
+	if (ret)
+		goto err;
+
+	xgene_enet_reset(pdata);
+	xgene_gmac_init(pdata, SPEED_1000);
+
+	ret = register_netdev(ndev);
+	if (ret) {
+		netdev_err(ndev, "Failed to register netdev\n");
+		goto err;
+	}
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+	if (ret) {
+		netdev_err(ndev, "No usable DMA configuration\n");
+		goto err;
+	}
+
+	ret = xgene_enet_init_hw(pdata);
+	if (ret)
+		goto err;
+
+	napi = &pdata->rx_ring->napi;
+	netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
+	ret = xgene_enet_mdio_config(pdata);
+
+	return ret;
+err:
+	free_netdev(ndev);
+	return ret;
+}
+
+static int xgene_enet_remove(struct platform_device *pdev)
+{
+	struct xgene_enet_pdata *pdata;
+	struct net_device *ndev;
+
+	pdata = platform_get_drvdata(pdev);
+	ndev = pdata->ndev;
+
+	xgene_gmac_rx_disable(pdata);
+	xgene_gmac_tx_disable(pdata);
+
+	netif_napi_del(&pdata->rx_ring->napi);
+	xgene_enet_mdio_remove(pdata);
+	xgene_enet_delete_desc_rings(pdata);
+	unregister_netdev(ndev);
+	xgene_gport_shutdown(pdata);
+	free_netdev(ndev);
+
+	return 0;
+}
+
+static struct of_device_id xgene_enet_match[] = {
+	{.compatible = "apm,xgene-enet",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_enet_match);
+
+static struct platform_driver xgene_enet_driver = {
+	.driver = {
+		   .name = "xgene-enet",
+		   .of_match_table = xgene_enet_match,
+	},
+	.probe = xgene_enet_probe,
+	.remove = xgene_enet_remove,
+};
+
+module_platform_driver(xgene_enet_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
+MODULE_VERSION(XGENE_DRV_VERSION);
+MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,135 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *	    Ravi Patel <rapatel@apm.com>
+ *	    Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_MAIN_H__
+#define __XGENE_ENET_MAIN_H__
+
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/prefetch.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include "xgene_enet_hw.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 NUM_PKT_BUF	64
+#define NUM_BUFPOOL	32
+
+/* software context of a descriptor ring */
+struct xgene_enet_desc_ring {
+	struct net_device *ndev;
+	u16 id;
+	u16 num;
+	u16 head;
+	u16 tail;
+	u16 slots;
+	u16 irq;
+	u32 size;
+	u32 state[NUM_RING_CONFIG];
+	void __iomem *cmd_base;
+	void __iomem *cmd;
+	dma_addr_t dma;
+	u16 dst_ring_num;
+	u8 nbufpool;
+	struct sk_buff *(*rx_skb);
+	struct sk_buff *(*cp_skb);
+	enum xgene_enet_ring_cfgsize cfgsize;
+	struct xgene_enet_desc_ring *cp_ring;
+	struct xgene_enet_desc_ring *buf_pool;
+	struct napi_struct napi;
+	union {
+		void *desc_addr;
+		struct xgene_enet_raw_desc *raw_desc;
+		struct xgene_enet_raw_desc16 *raw_desc16;
+	};
+};
+
+/* ethernet private data */
+struct xgene_enet_pdata {
+	struct net_device *ndev;
+	struct mii_bus *mdio_bus;
+	struct phy_device *phy_dev;
+	int phy_speed;
+	struct clk *clk;
+	struct platform_device *pdev;
+	struct xgene_enet_desc_ring *tx_ring;
+	struct xgene_enet_desc_ring *rx_ring;
+	char *dev_name;
+	u32 rx_buff_cnt;
+	u32 tx_qcnt_hi;
+	u32 cp_qcnt_hi;
+	u32 cp_qcnt_low;
+	u32 rx_irq;
+	void __iomem *eth_csr_addr;
+	void __iomem *eth_ring_if_addr;
+	void __iomem *eth_diag_csr_addr;
+	void __iomem *mcx_mac_addr;
+	void __iomem *mcx_stats_addr;
+	void __iomem *mcx_mac_csr_addr;
+	void __iomem *base_addr;
+	void __iomem *ring_csr_addr;
+	void __iomem *ring_cmd_addr;
+	u32 phy_addr;
+	int phy_mode;
+	u32 speed;
+	u16 rm;
+	struct rtnl_link_stats64 stats;
+};
+
+/* Set the specified value into a bit-field defined by its starting position
+ * and length within a single u64.
+ */
+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
+{
+	return (val & ((1ULL << len) - 1)) << pos;
+}
+
+#define SET_VAL(field, val) \
+		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
+
+#define SET_BIT(field) \
+		xgene_enet_set_field_value(field ## _POS, 1, 1)
+
+/* Get the value from a bit-field defined by its starting position
+ * and length within the specified u64.
+ */
+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
+{
+	return (src >> pos) & ((1ULL << len) - 1);
+}
+
+#define GET_VAL(field, src) \
+		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
+
+static inline struct device *ndev_to_dev(struct net_device *ndev)
+{
+	return ndev->dev.parent;
+}
+
+void xgene_enet_set_ethtool_ops(struct net_device *netdev);
+
+#endif /* __XGENE_ENET_MAIN_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/arc/emac.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/arc/emac.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/arc/emac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/arc/emac.h	2014-09-28 17:29:07.000000000 -0400
@@ -105,12 +105,10 @@ struct buffer_state {
 /**
  * struct arc_emac_priv - Storage of EMAC's private information.
  * @dev:	Pointer to the current device.
- * @ndev:	Pointer to the current network device.
  * @phy_dev:	Pointer to attached PHY device.
  * @bus:	Pointer to the current MII bus.
  * @regs:	Base address of EMAC memory-mapped control registers.
  * @napi:	Structure for NAPI.
- * @stats:	Network device statistics.
  * @rxbd:	Pointer to Rx BD ring.
  * @txbd:	Pointer to Tx BD ring.
  * @rxbd_dma:	DMA handle for Rx BD ring.
@@ -127,7 +125,6 @@ struct buffer_state {
 struct arc_emac_priv {
 	/* Devices */
 	struct device *dev;
-	struct net_device *ndev;
 	struct phy_device *phy_dev;
 	struct mii_bus *bus;
 
@@ -135,7 +132,6 @@ struct arc_emac_priv {
 	struct clk *clk;
 
 	struct napi_struct napi;
-	struct net_device_stats stats;
 
 	struct arc_emac_bd *rxbd;
 	struct arc_emac_bd *txbd;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/arc/emac_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/arc/emac_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/arc/emac_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/arc/emac_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,17 @@
 #define DRV_VERSION	"1.0"
 
 /**
+ * arc_emac_tx_avail - Return the number of available slots in the tx ring.
+ * @priv: Pointer to ARC EMAC private data structure.
+ *
+ * returns: the number of slots available for transmission in tx the ring.
+ */
+static inline int arc_emac_tx_avail(struct arc_emac_priv *priv)
+{
+	return (priv->txbd_dirty + TX_BD_NUM - priv->txbd_curr - 1) % TX_BD_NUM;
+}
+
+/**
  * arc_emac_adjust_link - Adjust the PHY link duplex.
  * @ndev:	Pointer to the net_device structure.
  *
@@ -140,7 +151,7 @@ static const struct ethtool_ops arc_emac
 static void arc_emac_tx_clean(struct net_device *ndev)
 {
 	struct arc_emac_priv *priv = netdev_priv(ndev);
-	struct net_device_stats *stats = &priv->stats;
+	struct net_device_stats *stats = &ndev->stats;
 	unsigned int i;
 
 	for (i = 0; i < TX_BD_NUM; i++) {
@@ -180,10 +191,15 @@ static void arc_emac_tx_clean(struct net
 		txbd->info = 0;
 
 		*txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM;
-
-		if (netif_queue_stopped(ndev))
-			netif_wake_queue(ndev);
 	}
+
+	/* Ensure that txbd_dirty is visible to tx() before checking
+	 * for queue stopped.
+	 */
+	smp_mb();
+
+	if (netif_queue_stopped(ndev) && arc_emac_tx_avail(priv))
+		netif_wake_queue(ndev);
 }
 
 /**
@@ -202,7 +218,7 @@ static int arc_emac_rx(struct net_device
 
 	for (work_done = 0; work_done < budget; work_done++) {
 		unsigned int *last_rx_bd = &priv->last_rx_bd;
-		struct net_device_stats *stats = &priv->stats;
+		struct net_device_stats *stats = &ndev->stats;
 		struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd];
 		struct arc_emac_bd *rxbd = &priv->rxbd[*last_rx_bd];
 		unsigned int pktlen, info = le32_to_cpu(rxbd->info);
@@ -298,7 +314,7 @@ static int arc_emac_poll(struct napi_str
 	work_done = arc_emac_rx(ndev, budget);
 	if (work_done < budget) {
 		napi_complete(napi);
-		arc_reg_or(priv, R_ENABLE, RXINT_MASK);
+		arc_reg_or(priv, R_ENABLE, RXINT_MASK | TXINT_MASK);
 	}
 
 	return work_done;
@@ -318,7 +334,7 @@ static irqreturn_t arc_emac_intr(int irq
 {
 	struct net_device *ndev = dev_instance;
 	struct arc_emac_priv *priv = netdev_priv(ndev);
-	struct net_device_stats *stats = &priv->stats;
+	struct net_device_stats *stats = &ndev->stats;
 	unsigned int status;
 
 	status = arc_reg_get(priv, R_STATUS);
@@ -327,9 +343,9 @@ static irqreturn_t arc_emac_intr(int irq
 	/* Reset all flags except "MDIO complete" */
 	arc_reg_set(priv, R_STATUS, status);
 
-	if (status & RXINT_MASK) {
+	if (status & (RXINT_MASK | TXINT_MASK)) {
 		if (likely(napi_schedule_prep(&priv->napi))) {
-			arc_reg_clr(priv, R_ENABLE, RXINT_MASK);
+			arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK);
 			__napi_schedule(&priv->napi);
 		}
 	}
@@ -440,7 +456,7 @@ static int arc_emac_open(struct net_devi
 	arc_reg_set(priv, R_TX_RING, (unsigned int)priv->txbd_dma);
 
 	/* Enable interrupts */
-	arc_reg_set(priv, R_ENABLE, RXINT_MASK | ERR_MASK);
+	arc_reg_set(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK);
 
 	/* Set CONTROL */
 	arc_reg_set(priv, R_CTRL,
@@ -511,7 +527,7 @@ static int arc_emac_stop(struct net_devi
 	netif_stop_queue(ndev);
 
 	/* Disable interrupts */
-	arc_reg_clr(priv, R_ENABLE, RXINT_MASK | ERR_MASK);
+	arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK);
 
 	/* Disable EMAC */
 	arc_reg_clr(priv, R_CTRL, EN_MASK);
@@ -529,7 +545,7 @@ static int arc_emac_stop(struct net_devi
 static struct net_device_stats *arc_emac_stats(struct net_device *ndev)
 {
 	struct arc_emac_priv *priv = netdev_priv(ndev);
-	struct net_device_stats *stats = &priv->stats;
+	struct net_device_stats *stats = &ndev->stats;
 	unsigned long miss, rxerr;
 	u8 rxcrc, rxfram, rxoflow;
 
@@ -565,7 +581,7 @@ static int arc_emac_tx(struct sk_buff *s
 {
 	struct arc_emac_priv *priv = netdev_priv(ndev);
 	unsigned int len, *txbd_curr = &priv->txbd_curr;
-	struct net_device_stats *stats = &priv->stats;
+	struct net_device_stats *stats = &ndev->stats;
 	__le32 *info = &priv->txbd[*txbd_curr].info;
 	dma_addr_t addr;
 
@@ -574,11 +590,9 @@ static int arc_emac_tx(struct sk_buff *s
 
 	len = max_t(unsigned int, ETH_ZLEN, skb->len);
 
-	/* EMAC still holds this buffer in its possession.
-	 * CPU must not modify this buffer descriptor
-	 */
-	if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC)) {
+	if (unlikely(!arc_emac_tx_avail(priv))) {
 		netif_stop_queue(ndev);
+		netdev_err(ndev, "BUG! Tx Ring full when queue awake!\n");
 		return NETDEV_TX_BUSY;
 	}
 
@@ -607,12 +621,19 @@ static int arc_emac_tx(struct sk_buff *s
 	/* Increment index to point to the next BD */
 	*txbd_curr = (*txbd_curr + 1) % TX_BD_NUM;
 
-	/* Get "info" of the next BD */
-	info = &priv->txbd[*txbd_curr].info;
+	/* Ensure that tx_clean() sees the new txbd_curr before
+	 * checking the queue status. This prevents an unneeded wake
+	 * of the queue in tx_clean().
+	 */
+	smp_mb();
 
-	/* Check if if Tx BD ring is full - next BD is still owned by EMAC */
-	if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC))
+	if (!arc_emac_tx_avail(priv)) {
 		netif_stop_queue(ndev);
+		/* Refresh tx_dirty */
+		smp_mb();
+		if (arc_emac_tx_avail(priv))
+			netif_start_queue(ndev);
+	}
 
 	arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
@@ -720,7 +741,6 @@ static int arc_emac_probe(struct platfor
 
 	priv = netdev_priv(ndev);
 	priv->dev = &pdev->dev;
-	priv->ndev = ndev;
 
 	priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs);
 	if (IS_ERR(priv->regs)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/alx/main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/alx/main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/alx/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/alx/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -1527,7 +1527,7 @@ static const struct pci_error_handlers a
 	.resume         = alx_pci_error_resume,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(alx_pci_tbl) = {
+static const struct pci_device_id alx_pci_tbl[] = {
 	{ PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_AR8161),
 	  .driver_data = ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG },
 	{ PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_E2200),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -639,7 +639,6 @@ int atl1c_phy_init(struct atl1c_hw *hw)
 			dev_err(&pdev->dev, "Wrong Media type %d\n",
 				hw->media_type);
 		return -1;
-		break;
 	}
 
 	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
@@ -682,7 +681,6 @@ int atl1c_get_speed_and_duplex(struct at
 		break;
 	default:
 		return -1;
-		break;
 	}
 
 	if (phy_data & GIGA_PSSR_DPLX)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@ char atl1c_driver_version[] = ATL1C_DRV_
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
+static const struct pci_device_id atl1c_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -618,7 +618,6 @@ int atl1e_get_speed_and_duplex(struct at
 		break;
 	default:
 		return AT_ERR_PHY_SPEED;
-		break;
 	}
 
 	if (phy_data & MII_AT001_PSSR_DPLX)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@ char atl1e_driver_version[] = DRV_VERSIO
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = {
+static const struct pci_device_id atl1e_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)},
 	/* required last entry */
@@ -831,17 +831,14 @@ static int atl1e_setup_ring_resources(st
 	/* real ring DMA buffer */
 
 	size = adapter->ring_size;
-	adapter->ring_vir_addr = pci_alloc_consistent(pdev,
-			adapter->ring_size, &adapter->ring_dma);
-
+	adapter->ring_vir_addr = pci_zalloc_consistent(pdev, adapter->ring_size,
+						       &adapter->ring_dma);
 	if (adapter->ring_vir_addr == NULL) {
 		netdev_err(adapter->netdev,
 			   "pci_alloc_consistent failed, size = D%d\n", size);
 		return -ENOMEM;
 	}
 
-	memset(adapter->ring_vir_addr, 0, adapter->ring_size);
-
 	rx_page_desc = rx_ring->rx_page_desc;
 
 	/* Init TPD Ring */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atlx/atl1.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atlx/atl1.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atlx/atl1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atlx/atl1.c	2014-09-28 17:29:07.000000000 -0400
@@ -235,7 +235,7 @@ static void atl1_check_options(struct at
 /*
  * atl1_pci_tbl - PCI Device ID Table
  */
-static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = {
+static const struct pci_device_id atl1_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
 	/* required last entry */
 	{0,}
@@ -910,7 +910,6 @@ static s32 atl1_get_speed_and_duplex(str
 		if (netif_msg_hw(adapter))
 			dev_dbg(&pdev->dev, "error getting speed\n");
 		return ATLX_ERR_PHY_SPEED;
-		break;
 	}
 	if (phy_data & MII_ATLX_PSSR_DPLX)
 		*duplex = FULL_DUPLEX;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atlx/atl2.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atlx/atl2.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/atheros/atlx/atl2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/atheros/atlx/atl2.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@ MODULE_VERSION(ATL2_DRV_VERSION);
 /*
  * atl2_pci_tbl - PCI Device ID Table
  */
-static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = {
+static const struct pci_device_id atl2_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)},
 	/* required last entry */
 	{0,}
@@ -2493,7 +2493,6 @@ static s32 atl2_get_speed_and_duplex(str
 		break;
 	default:
 		return ATLX_ERR_PHY_SPEED;
-		break;
 	}
 
 	if (phy_data & MII_ATLX_PSSR_DPLX)
@@ -2933,11 +2932,9 @@ static int atl2_validate_option(int *val
 		case OPTION_ENABLED:
 			printk(KERN_INFO "%s Enabled\n", opt->name);
 			return 0;
-			break;
 		case OPTION_DISABLED:
 			printk(KERN_INFO "%s Disabled\n", opt->name);
 			return 0;
-			break;
 		}
 		break;
 	case range_option:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/b44.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/b44.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/b44.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/b44.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,7 +105,7 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapp
 
 
 #ifdef CONFIG_B44_PCI
-static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = {
+static const struct pci_device_id b44_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) },
@@ -1697,7 +1697,7 @@ static struct rtnl_link_stats64 *b44_get
 				     hwstat->tx_underruns +
 				     hwstat->tx_excessive_cols +
 				     hwstat->tx_late_cols);
-		nstat->multicast  = hwstat->tx_multicast_pkts;
+		nstat->multicast  = hwstat->rx_multicast_pkts;
 		nstat->collisions = hwstat->tx_total_cols;
 
 		nstat->rx_length_errors = (hwstat->rx_oversize_pkts +
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bcmsysport.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bcmsysport.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bcmsysport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bcmsysport.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,14 +81,14 @@ static inline void dma_desc_set_addr(str
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 	__raw_writel(upper_32_bits(addr) & DESC_ADDR_HI_MASK,
-			d + DESC_ADDR_HI_STATUS_LEN);
+		     d + DESC_ADDR_HI_STATUS_LEN);
 #endif
 	__raw_writel(lower_32_bits(addr), d + DESC_ADDR_LO);
 }
 
 static inline void tdma_port_write_desc_addr(struct bcm_sysport_priv *priv,
-						struct dma_desc *desc,
-						unsigned int port)
+					     struct dma_desc *desc,
+					     unsigned int port)
 {
 	/* Ports are latched, so write upper address first */
 	tdma_writel(priv, desc->addr_status_len, TDMA_WRITE_PORT_HI(port));
@@ -108,7 +108,7 @@ static int bcm_sysport_set_settings(stru
 }
 
 static int bcm_sysport_get_settings(struct net_device *dev,
-					struct ethtool_cmd *cmd)
+				    struct ethtool_cmd *cmd)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 
@@ -119,14 +119,14 @@ static int bcm_sysport_get_settings(stru
 }
 
 static int bcm_sysport_set_rx_csum(struct net_device *dev,
-					netdev_features_t wanted)
+				   netdev_features_t wanted)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	u32 reg;
 
-	priv->rx_csum_en = !!(wanted & NETIF_F_RXCSUM);
+	priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
 	reg = rxchk_readl(priv, RXCHK_CONTROL);
-	if (priv->rx_csum_en)
+	if (priv->rx_chk_en)
 		reg |= RXCHK_EN;
 	else
 		reg &= ~RXCHK_EN;
@@ -134,7 +134,7 @@ static int bcm_sysport_set_rx_csum(struc
 	/* If UniMAC forwards CRC, we need to skip over it to get
 	 * a valid CHK bit to be set in the per-packet status word
 	 */
-	if (priv->rx_csum_en && priv->crc_fwd)
+	if (priv->rx_chk_en && priv->crc_fwd)
 		reg |= RXCHK_SKIP_FCS;
 	else
 		reg &= ~RXCHK_SKIP_FCS;
@@ -145,7 +145,7 @@ static int bcm_sysport_set_rx_csum(struc
 }
 
 static int bcm_sysport_set_tx_csum(struct net_device *dev,
-					netdev_features_t wanted)
+				   netdev_features_t wanted)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	u32 reg;
@@ -165,7 +165,7 @@ static int bcm_sysport_set_tx_csum(struc
 }
 
 static int bcm_sysport_set_features(struct net_device *dev,
-					netdev_features_t features)
+				    netdev_features_t features)
 {
 	netdev_features_t changed = features ^ dev->features;
 	netdev_features_t wanted = dev->wanted_features;
@@ -261,7 +261,7 @@ static const struct bcm_sysport_stats bc
 	/* RXCHK misc statistics */
 	STAT_RXCHK("rxchk_bad_csum", mib.rxchk_bad_csum, RXCHK_BAD_CSUM_CNTR),
 	STAT_RXCHK("rxchk_other_pkt_disc", mib.rxchk_other_pkt_disc,
-			RXCHK_OTHER_DISC_CNTR),
+		   RXCHK_OTHER_DISC_CNTR),
 	/* RBUF misc statistics */
 	STAT_RBUF("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, RBUF_OVFL_DISC_CNTR),
 	STAT_RBUF("rbuf_err_cnt", mib.rbuf_err_cnt, RBUF_ERR_PKT_CNTR),
@@ -270,7 +270,7 @@ static const struct bcm_sysport_stats bc
 #define BCM_SYSPORT_STATS_LEN	ARRAY_SIZE(bcm_sysport_gstrings_stats)
 
 static void bcm_sysport_get_drvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *info)
+				    struct ethtool_drvinfo *info)
 {
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 	strlcpy(info->version, "0.1", sizeof(info->version));
@@ -303,7 +303,7 @@ static int bcm_sysport_get_sset_count(st
 }
 
 static void bcm_sysport_get_strings(struct net_device *dev,
-					u32 stringset, u8 *data)
+				    u32 stringset, u8 *data)
 {
 	int i;
 
@@ -311,8 +311,8 @@ static void bcm_sysport_get_strings(stru
 	case ETH_SS_STATS:
 		for (i = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
 			memcpy(data + i * ETH_GSTRING_LEN,
-				bcm_sysport_gstrings_stats[i].stat_string,
-				ETH_GSTRING_LEN);
+			       bcm_sysport_gstrings_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
 		}
 		break;
 	default:
@@ -362,7 +362,7 @@ static void bcm_sysport_update_mib_count
 }
 
 static void bcm_sysport_get_stats(struct net_device *dev,
-					struct ethtool_stats *stats, u64 *data)
+				  struct ethtool_stats *stats, u64 *data)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	int i;
@@ -384,6 +384,64 @@ static void bcm_sysport_get_stats(struct
 	}
 }
 
+static void bcm_sysport_get_wol(struct net_device *dev,
+				struct ethtool_wolinfo *wol)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	u32 reg;
+
+	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+	wol->wolopts = priv->wolopts;
+
+	if (!(priv->wolopts & WAKE_MAGICSECURE))
+		return;
+
+	/* Return the programmed SecureOn password */
+	reg = umac_readl(priv, UMAC_PSW_MS);
+	put_unaligned_be16(reg, &wol->sopass[0]);
+	reg = umac_readl(priv, UMAC_PSW_LS);
+	put_unaligned_be32(reg, &wol->sopass[2]);
+}
+
+static int bcm_sysport_set_wol(struct net_device *dev,
+			       struct ethtool_wolinfo *wol)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
+	u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+
+	if (!device_can_wakeup(kdev))
+		return -ENOTSUPP;
+
+	if (wol->wolopts & ~supported)
+		return -EINVAL;
+
+	/* Program the SecureOn password */
+	if (wol->wolopts & WAKE_MAGICSECURE) {
+		umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
+			    UMAC_PSW_MS);
+		umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
+			    UMAC_PSW_LS);
+	}
+
+	/* Flag the device and relevant IRQ as wakeup capable */
+	if (wol->wolopts) {
+		device_set_wakeup_enable(kdev, 1);
+		enable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = 0;
+	} else {
+		device_set_wakeup_enable(kdev, 0);
+		/* Avoid unbalanced disable_irq_wake calls */
+		if (!priv->wol_irq_disabled)
+			disable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = 1;
+	}
+
+	priv->wolopts = wol->wolopts;
+
+	return 0;
+}
+
 static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb)
 {
 	dev_kfree_skb_any(cb->skb);
@@ -406,7 +464,7 @@ static int bcm_sysport_rx_refill(struct
 	}
 
 	mapping = dma_map_single(kdev, cb->skb->data,
-				RX_BUF_LENGTH, DMA_FROM_DEVICE);
+				 RX_BUF_LENGTH, DMA_FROM_DEVICE);
 	ret = dma_mapping_error(kdev, mapping);
 	if (ret) {
 		bcm_sysport_free_cb(cb);
@@ -470,33 +528,24 @@ static unsigned int bcm_sysport_desc_rx(
 		to_process = p_index - priv->rx_c_index;
 
 	netif_dbg(priv, rx_status, ndev,
-			"p_index=%d rx_c_index=%d to_process=%d\n",
-			p_index, priv->rx_c_index, to_process);
-
-	while ((processed < to_process) &&
-		(processed < budget)) {
+		  "p_index=%d rx_c_index=%d to_process=%d\n",
+		  p_index, priv->rx_c_index, to_process);
 
+	while ((processed < to_process) && (processed < budget)) {
 		cb = &priv->rx_cbs[priv->rx_read_ptr];
 		skb = cb->skb;
-		dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
-				RX_BUF_LENGTH, DMA_FROM_DEVICE);
-
-		/* Extract the Receive Status Block prepended */
-		rsb = (struct bcm_rsb *)skb->data;
-		len = (rsb->rx_status_len >> DESC_LEN_SHIFT) & DESC_LEN_MASK;
-		status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) &
-			DESC_STATUS_MASK;
 
 		processed++;
 		priv->rx_read_ptr++;
+
 		if (priv->rx_read_ptr == priv->num_rx_bds)
 			priv->rx_read_ptr = 0;
 
-		netif_dbg(priv, rx_status, ndev,
-				"p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
-				p_index, priv->rx_c_index, priv->rx_read_ptr,
-				len, status);
-
+		/* We do not have a backing SKB, so we do not a corresponding
+		 * DMA mapping for this incoming packet since
+		 * bcm_sysport_rx_refill always either has both skb and mapping
+		 * or none.
+		 */
 		if (unlikely(!skb)) {
 			netif_err(priv, rx_err, ndev, "out of memory!\n");
 			ndev->stats.rx_dropped++;
@@ -504,6 +553,20 @@ static unsigned int bcm_sysport_desc_rx(
 			goto refill;
 		}
 
+		dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
+				 RX_BUF_LENGTH, DMA_FROM_DEVICE);
+
+		/* Extract the Receive Status Block prepended */
+		rsb = (struct bcm_rsb *)skb->data;
+		len = (rsb->rx_status_len >> DESC_LEN_SHIFT) & DESC_LEN_MASK;
+		status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) &
+			  DESC_STATUS_MASK;
+
+		netif_dbg(priv, rx_status, ndev,
+			  "p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
+			  p_index, priv->rx_c_index, priv->rx_read_ptr,
+			  len, status);
+
 		if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) {
 			netif_err(priv, rx_status, ndev, "fragmented packet!\n");
 			ndev->stats.rx_dropped++;
@@ -554,9 +617,9 @@ refill:
 }
 
 static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_priv *priv,
-					struct bcm_sysport_cb *cb,
-					unsigned int *bytes_compl,
-					unsigned int *pkts_compl)
+				       struct bcm_sysport_cb *cb,
+				       unsigned int *bytes_compl,
+				       unsigned int *pkts_compl)
 {
 	struct device *kdev = &priv->pdev->dev;
 	struct net_device *ndev = priv->netdev;
@@ -565,8 +628,8 @@ static void bcm_sysport_tx_reclaim_one(s
 		ndev->stats.tx_bytes += cb->skb->len;
 		*bytes_compl += cb->skb->len;
 		dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
-				dma_unmap_len(cb, dma_len),
-				DMA_TO_DEVICE);
+				 dma_unmap_len(cb, dma_len),
+				 DMA_TO_DEVICE);
 		ndev->stats.tx_packets++;
 		(*pkts_compl)++;
 		bcm_sysport_free_cb(cb);
@@ -574,7 +637,7 @@ static void bcm_sysport_tx_reclaim_one(s
 	} else if (dma_unmap_addr(cb, dma_addr)) {
 		ndev->stats.tx_bytes += dma_unmap_len(cb, dma_len);
 		dma_unmap_page(kdev, dma_unmap_addr(cb, dma_addr),
-				dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
+			       dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
 		dma_unmap_addr_set(cb, dma_addr, 0);
 	}
 }
@@ -608,8 +671,8 @@ static unsigned int __bcm_sysport_tx_rec
 		last_tx_cn = num_tx_cbs - last_c_index + c_index;
 
 	netif_dbg(priv, tx_done, ndev,
-			"ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n",
-			ring->index, c_index, last_tx_cn, last_c_index);
+		  "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n",
+		  ring->index, c_index, last_tx_cn, last_c_index);
 
 	while (last_tx_cn-- > 0) {
 		cb = ring->cbs + last_c_index;
@@ -626,8 +689,8 @@ static unsigned int __bcm_sysport_tx_rec
 		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);
+		  "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
+		  ring->index, ring->c_index, pkts_compl, bytes_compl);
 
 	return pkts_compl;
 }
@@ -692,6 +755,20 @@ static int bcm_sysport_poll(struct napi_
 	return work_done;
 }
 
+static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
+{
+	u32 reg;
+
+	/* Stop monitoring MPD interrupt */
+	intrl2_0_mask_set(priv, INTRL2_0_MPD);
+
+	/* Clear the MagicPacket detection logic */
+	reg = umac_readl(priv, UMAC_MPD_CTRL);
+	reg &= ~MPD_EN;
+	umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+	netif_dbg(priv, wol, priv->netdev, "resumed from WOL\n");
+}
 
 /* RX and misc interrupt routine */
 static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
@@ -722,6 +799,11 @@ static irqreturn_t bcm_sysport_rx_isr(in
 	if (priv->irq0_stat & INTRL2_0_TX_RING_FULL)
 		bcm_sysport_tx_reclaim_all(priv);
 
+	if (priv->irq0_stat & INTRL2_0_MPD) {
+		netdev_info(priv->netdev, "Wake-on-LAN interrupt!\n");
+		bcm_sysport_resume_from_wol(priv);
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -757,6 +839,15 @@ static irqreturn_t bcm_sysport_tx_isr(in
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
+{
+	struct bcm_sysport_priv *priv = dev_id;
+
+	pm_wakeup_event(&priv->pdev->dev, 0);
+
+	return IRQ_HANDLED;
+}
+
 static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sk_buff *nskb;
@@ -804,8 +895,9 @@ static int bcm_sysport_insert_tsb(struct
 			csum_info |= L4_LENGTH_VALID;
 			if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP)
 				csum_info |= L4_UDP;
-		} else
+		} else {
 			csum_info = 0;
+		}
 
 		tsb->l4_ptr_dest_map = csum_info;
 	}
@@ -869,7 +961,7 @@ static netdev_tx_t bcm_sysport_xmit(stru
 	mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
 	if (dma_mapping_error(kdev, mapping)) {
 		netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
-				skb->data, skb_len);
+			  skb->data, skb_len);
 		ret = NETDEV_TX_OK;
 		goto out;
 	}
@@ -887,7 +979,7 @@ static netdev_tx_t bcm_sysport_xmit(stru
 	len_status = upper_32_bits(mapping) & DESC_ADDR_HI_MASK;
 	len_status |= (skb_len << DESC_LEN_SHIFT);
 	len_status |= (DESC_SOP | DESC_EOP | TX_STATUS_APP_CRC) <<
-			DESC_STATUS_SHIFT;
+		       DESC_STATUS_SHIFT;
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		len_status |= (DESC_L4_CSUM << DESC_STATUS_SHIFT);
 
@@ -912,7 +1004,7 @@ static netdev_tx_t bcm_sysport_xmit(stru
 		netif_tx_stop_queue(txq);
 
 	netif_dbg(priv, tx_queued, dev, "ring=%d desc_count=%d, curr_desc=%d\n",
-			ring->index, ring->desc_count, ring->curr_desc);
+		  ring->index, ring->desc_count, ring->curr_desc);
 
 	ret = NETDEV_TX_OK;
 out:
@@ -1010,7 +1102,7 @@ static int bcm_sysport_init_tx_ring(stru
 		return -ENOMEM;
 	}
 
-	ring->cbs = kzalloc(sizeof(struct bcm_sysport_cb) * size, GFP_KERNEL);
+	ring->cbs = kcalloc(size, sizeof(struct bcm_sysport_cb), GFP_KERNEL);
 	if (!ring->cbs) {
 		netif_err(priv, hw, priv->netdev, "CB allocation failed\n");
 		return -ENOMEM;
@@ -1050,14 +1142,14 @@ static int bcm_sysport_init_tx_ring(stru
 	napi_enable(&ring->napi);
 
 	netif_dbg(priv, hw, priv->netdev,
-			"TDMA cfg, size=%d, desc_cpu=%p\n",
-			ring->size, ring->desc_cpu);
+		  "TDMA cfg, size=%d, desc_cpu=%p\n",
+		  ring->size, ring->desc_cpu);
 
 	return 0;
 }
 
 static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
-					unsigned int index)
+				     unsigned int index)
 {
 	struct bcm_sysport_tx_ring *ring = &priv->tx_rings[index];
 	struct device *kdev = &priv->pdev->dev;
@@ -1088,7 +1180,7 @@ static void bcm_sysport_fini_tx_ring(str
 
 /* RDMA helper */
 static inline int rdma_enable_set(struct bcm_sysport_priv *priv,
-					unsigned int enable)
+				  unsigned int enable)
 {
 	unsigned int timeout = 1000;
 	u32 reg;
@@ -1115,7 +1207,7 @@ static inline int rdma_enable_set(struct
 
 /* TDMA helper */
 static inline int tdma_enable_set(struct bcm_sysport_priv *priv,
-					unsigned int enable)
+				  unsigned int enable)
 {
 	unsigned int timeout = 1000;
 	u32 reg;
@@ -1153,8 +1245,8 @@ static int bcm_sysport_init_rx_ring(stru
 	priv->rx_bd_assign_index = 0;
 	priv->rx_c_index = 0;
 	priv->rx_read_ptr = 0;
-	priv->rx_cbs = kzalloc(priv->num_rx_bds *
-				sizeof(struct bcm_sysport_cb), GFP_KERNEL);
+	priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct bcm_sysport_cb),
+				GFP_KERNEL);
 	if (!priv->rx_cbs) {
 		netif_err(priv, hw, priv->netdev, "CB allocation failed\n");
 		return -ENOMEM;
@@ -1186,8 +1278,8 @@ static int bcm_sysport_init_rx_ring(stru
 	rdma_writel(priv, 1, RDMA_MBDONE_INTR);
 
 	netif_dbg(priv, hw, priv->netdev,
-			"RDMA cfg, num_rx_bds=%d, rx_bds=%p\n",
-			priv->num_rx_bds, priv->rx_bds);
+		  "RDMA cfg, num_rx_bds=%d, rx_bds=%p\n",
+		  priv->num_rx_bds, priv->rx_bds);
 
 	return 0;
 }
@@ -1207,8 +1299,8 @@ static void bcm_sysport_fini_rx_ring(str
 		cb = &priv->rx_cbs[i];
 		if (dma_unmap_addr(cb, dma_addr))
 			dma_unmap_single(&priv->pdev->dev,
-					dma_unmap_addr(cb, dma_addr),
-					RX_BUF_LENGTH, DMA_FROM_DEVICE);
+					 dma_unmap_addr(cb, dma_addr),
+					 RX_BUF_LENGTH, DMA_FROM_DEVICE);
 		bcm_sysport_free_cb(cb);
 	}
 
@@ -1236,15 +1328,15 @@ static void bcm_sysport_set_rx_mode(stru
 }
 
 static inline void umac_enable_set(struct bcm_sysport_priv *priv,
-					unsigned int enable)
+				   u32 mask, unsigned int enable)
 {
 	u32 reg;
 
 	reg = umac_readl(priv, UMAC_CMD);
 	if (enable)
-		reg |= CMD_RX_EN | CMD_TX_EN;
+		reg |= mask;
 	else
-		reg &= ~(CMD_RX_EN | CMD_TX_EN);
+		reg &= ~mask;
 	umac_writel(priv, reg, UMAC_CMD);
 
 	/* UniMAC stops on a packet boundary, wait for a full-sized packet
@@ -1268,7 +1360,7 @@ static inline void umac_reset(struct bcm
 }
 
 static void umac_set_hw_addr(struct bcm_sysport_priv *priv,
-				unsigned char *addr)
+			     unsigned char *addr)
 {
 	umac_writel(priv, (addr[0] << 24) | (addr[1] << 16) |
 			(addr[2] << 8) | addr[3], UMAC_MAC0);
@@ -1284,11 +1376,35 @@ static void topctrl_flush(struct bcm_sys
 	topctrl_writel(priv, 0, TX_FLUSH_CNTL);
 }
 
+static void bcm_sysport_netif_start(struct net_device *dev)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+
+	/* Enable NAPI */
+	napi_enable(&priv->napi);
+
+	phy_start(priv->phydev);
+
+	/* Enable TX interrupts for the 32 TXQs */
+	intrl2_1_mask_clear(priv, 0xffffffff);
+
+	/* Last call before we start the real business */
+	netif_tx_start_all_queues(dev);
+}
+
+static void rbuf_init(struct bcm_sysport_priv *priv)
+{
+	u32 reg;
+
+	reg = rbuf_readl(priv, RBUF_CONTROL);
+	reg |= RBUF_4B_ALGN | RBUF_RSB_EN;
+	rbuf_writel(priv, reg, RBUF_CONTROL);
+}
+
 static int bcm_sysport_open(struct net_device *dev)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	unsigned int i;
-	u32 reg;
 	int ret;
 
 	/* Reset UniMAC */
@@ -1298,12 +1414,10 @@ static int bcm_sysport_open(struct net_d
 	topctrl_flush(priv);
 
 	/* Disable the UniMAC RX/TX */
-	umac_enable_set(priv, 0);
+	umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 0);
 
 	/* Enable RBUF 2bytes alignment and Receive Status Block */
-	reg = rbuf_readl(priv, RBUF_CONTROL);
-	reg |= RBUF_4B_ALGN | RBUF_RSB_EN;
-	rbuf_writel(priv, reg, RBUF_CONTROL);
+	rbuf_init(priv);
 
 	/* Set maximum frame length */
 	umac_writel(priv, UMAC_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
@@ -1351,7 +1465,7 @@ static int bcm_sysport_open(struct net_d
 		ret = bcm_sysport_init_tx_ring(priv, i);
 		if (ret) {
 			netdev_err(dev, "failed to initialize TX ring %d\n",
-					i);
+				   i);
 			goto out_free_tx_ring;
 		}
 	}
@@ -1379,19 +1493,10 @@ static int bcm_sysport_open(struct net_d
 	if (ret)
 		goto out_clear_rx_int;
 
-	/* Enable NAPI */
-	napi_enable(&priv->napi);
-
 	/* Turn on UniMAC TX/RX */
-	umac_enable_set(priv, 1);
-
-	phy_start(priv->phydev);
-
-	/* Enable TX interrupts for the 32 TXQs */
-	intrl2_1_mask_clear(priv, 0xffffffff);
+	umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 1);
 
-	/* Last call before we start the real business */
-	netif_tx_start_all_queues(dev);
+	bcm_sysport_netif_start(dev);
 
 	return 0;
 
@@ -1410,12 +1515,9 @@ out_phy_disconnect:
 	return ret;
 }
 
-static int bcm_sysport_stop(struct net_device *dev)
+static void bcm_sysport_netif_stop(struct net_device *dev)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
-	unsigned int i;
-	u32 reg;
-	int ret;
 
 	/* stop all software from updating hardware */
 	netif_tx_stop_all_queues(dev);
@@ -1427,11 +1529,18 @@ static int bcm_sysport_stop(struct net_d
 	intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
 	intrl2_1_mask_set(priv, 0xffffffff);
 	intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
+}
+
+static int bcm_sysport_stop(struct net_device *dev)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	unsigned int i;
+	int ret;
+
+	bcm_sysport_netif_stop(dev);
 
 	/* Disable UniMAC RX */
-	reg = umac_readl(priv, UMAC_CMD);
-	reg &= ~CMD_RX_EN;
-	umac_writel(priv, reg, UMAC_CMD);
+	umac_enable_set(priv, CMD_RX_EN, 0);
 
 	ret = tdma_enable_set(priv, 0);
 	if (ret) {
@@ -1449,9 +1558,7 @@ static int bcm_sysport_stop(struct net_d
 	}
 
 	/* Disable UniMAC TX */
-	reg = umac_readl(priv, UMAC_CMD);
-	reg &= ~CMD_TX_EN;
-	umac_writel(priv, reg, UMAC_CMD);
+	umac_enable_set(priv, CMD_TX_EN, 0);
 
 	/* Free RX/TX rings SW structures */
 	for (i = 0; i < dev->num_tx_queues; i++)
@@ -1477,6 +1584,8 @@ static struct ethtool_ops bcm_sysport_et
 	.get_strings		= bcm_sysport_get_strings,
 	.get_ethtool_stats	= bcm_sysport_get_stats,
 	.get_sset_count		= bcm_sysport_get_sset_count,
+	.get_wol		= bcm_sysport_get_wol,
+	.set_wol		= bcm_sysport_set_wol,
 };
 
 static const struct net_device_ops bcm_sysport_netdev_ops = {
@@ -1518,6 +1627,7 @@ static int bcm_sysport_probe(struct plat
 
 	priv->irq0 = platform_get_irq(pdev, 0);
 	priv->irq1 = platform_get_irq(pdev, 1);
+	priv->wol_irq = platform_get_irq(pdev, 2);
 	if (priv->irq0 <= 0 || priv->irq1 <= 0) {
 		dev_err(&pdev->dev, "invalid interrupts\n");
 		ret = -EINVAL;
@@ -1570,6 +1680,13 @@ static int bcm_sysport_probe(struct plat
 	dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA |
 				NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 
+	/* Request the WOL interrupt and advertise suspend if available */
+	priv->wol_irq_disabled = 1;
+	ret = devm_request_irq(&pdev->dev, priv->wol_irq,
+			       bcm_sysport_wol_isr, 0, dev->name, priv);
+	if (!ret)
+		device_set_wakeup_capable(&pdev->dev, 1);
+
 	/* Set the needed headroom once and for all */
 	BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8);
 	dev->needed_headroom += sizeof(struct bcm_tsb);
@@ -1585,10 +1702,10 @@ static int bcm_sysport_probe(struct plat
 
 	priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
 	dev_info(&pdev->dev,
-		"Broadcom SYSTEMPORT" REV_FMT
-		" at 0x%p (irqs: %d, %d, TXQs: %d, RXQs: %d)\n",
-		(priv->rev >> 8) & 0xff, priv->rev & 0xff,
-		priv->base, priv->irq0, priv->irq1, txq, rxq);
+		 "Broadcom SYSTEMPORT" REV_FMT
+		 " at 0x%p (irqs: %d, %d, TXQs: %d, RXQs: %d)\n",
+		 (priv->rev >> 8) & 0xff, priv->rev & 0xff,
+		 priv->base, priv->irq0, priv->irq1, txq, rxq);
 
 	return 0;
 err:
@@ -1610,6 +1727,208 @@ static int bcm_sysport_remove(struct pla
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
+{
+	struct net_device *ndev = priv->netdev;
+	unsigned int timeout = 1000;
+	u32 reg;
+
+	/* Password has already been programmed */
+	reg = umac_readl(priv, UMAC_MPD_CTRL);
+	reg |= MPD_EN;
+	reg &= ~PSW_EN;
+	if (priv->wolopts & WAKE_MAGICSECURE)
+		reg |= PSW_EN;
+	umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+	/* Make sure RBUF entered WoL mode as result */
+	do {
+		reg = rbuf_readl(priv, RBUF_STATUS);
+		if (reg & RBUF_WOL_MODE)
+			break;
+
+		udelay(10);
+	} while (timeout-- > 0);
+
+	/* Do not leave the UniMAC RBUF matching only MPD packets */
+	if (!timeout) {
+		reg = umac_readl(priv, UMAC_MPD_CTRL);
+		reg &= ~MPD_EN;
+		umac_writel(priv, reg, UMAC_MPD_CTRL);
+		netif_err(priv, wol, ndev, "failed to enter WOL mode\n");
+		return -ETIMEDOUT;
+	}
+
+	/* UniMAC receive needs to be turned on */
+	umac_enable_set(priv, CMD_RX_EN, 1);
+
+	/* Enable the interrupt wake-up source */
+	intrl2_0_mask_clear(priv, INTRL2_0_MPD);
+
+	netif_dbg(priv, wol, ndev, "entered WOL mode\n");
+
+	return 0;
+}
+
+static int bcm_sysport_suspend(struct device *d)
+{
+	struct net_device *dev = dev_get_drvdata(d);
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	unsigned int i;
+	int ret = 0;
+	u32 reg;
+
+	if (!netif_running(dev))
+		return 0;
+
+	bcm_sysport_netif_stop(dev);
+
+	phy_suspend(priv->phydev);
+
+	netif_device_detach(dev);
+
+	/* Disable UniMAC RX */
+	umac_enable_set(priv, CMD_RX_EN, 0);
+
+	ret = rdma_enable_set(priv, 0);
+	if (ret) {
+		netdev_err(dev, "RDMA timeout!\n");
+		return ret;
+	}
+
+	/* Disable RXCHK if enabled */
+	if (priv->rx_chk_en) {
+		reg = rxchk_readl(priv, RXCHK_CONTROL);
+		reg &= ~RXCHK_EN;
+		rxchk_writel(priv, reg, RXCHK_CONTROL);
+	}
+
+	/* Flush RX pipe */
+	if (!priv->wolopts)
+		topctrl_writel(priv, RX_FLUSH, RX_FLUSH_CNTL);
+
+	ret = tdma_enable_set(priv, 0);
+	if (ret) {
+		netdev_err(dev, "TDMA timeout!\n");
+		return ret;
+	}
+
+	/* Wait for a packet boundary */
+	usleep_range(2000, 3000);
+
+	umac_enable_set(priv, CMD_TX_EN, 0);
+
+	topctrl_writel(priv, TX_FLUSH, TX_FLUSH_CNTL);
+
+	/* Free RX/TX rings SW structures */
+	for (i = 0; i < dev->num_tx_queues; i++)
+		bcm_sysport_fini_tx_ring(priv, i);
+	bcm_sysport_fini_rx_ring(priv);
+
+	/* Get prepared for Wake-on-LAN */
+	if (device_may_wakeup(d) && priv->wolopts)
+		ret = bcm_sysport_suspend_to_wol(priv);
+
+	return ret;
+}
+
+static int bcm_sysport_resume(struct device *d)
+{
+	struct net_device *dev = dev_get_drvdata(d);
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	unsigned int i;
+	u32 reg;
+	int ret;
+
+	if (!netif_running(dev))
+		return 0;
+
+	/* We may have been suspended and never received a WOL event that
+	 * would turn off MPD detection, take care of that now
+	 */
+	bcm_sysport_resume_from_wol(priv);
+
+	/* Initialize both hardware and software ring */
+	for (i = 0; i < dev->num_tx_queues; i++) {
+		ret = bcm_sysport_init_tx_ring(priv, i);
+		if (ret) {
+			netdev_err(dev, "failed to initialize TX ring %d\n",
+				   i);
+			goto out_free_tx_rings;
+		}
+	}
+
+	/* Initialize linked-list */
+	tdma_writel(priv, TDMA_LL_RAM_INIT_BUSY, TDMA_STATUS);
+
+	/* Initialize RX ring */
+	ret = bcm_sysport_init_rx_ring(priv);
+	if (ret) {
+		netdev_err(dev, "failed to initialize RX ring\n");
+		goto out_free_rx_ring;
+	}
+
+	netif_device_attach(dev);
+
+	/* Enable RX interrupt and TX ring full interrupt */
+	intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE | INTRL2_0_TX_RING_FULL);
+
+	/* RX pipe enable */
+	topctrl_writel(priv, 0, RX_FLUSH_CNTL);
+
+	ret = rdma_enable_set(priv, 1);
+	if (ret) {
+		netdev_err(dev, "failed to enable RDMA\n");
+		goto out_free_rx_ring;
+	}
+
+	/* Enable rxhck */
+	if (priv->rx_chk_en) {
+		reg = rxchk_readl(priv, RXCHK_CONTROL);
+		reg |= RXCHK_EN;
+		rxchk_writel(priv, reg, RXCHK_CONTROL);
+	}
+
+	rbuf_init(priv);
+
+	/* Set maximum frame length */
+	umac_writel(priv, UMAC_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
+
+	/* Set MAC address */
+	umac_set_hw_addr(priv, dev->dev_addr);
+
+	umac_enable_set(priv, CMD_RX_EN, 1);
+
+	/* TX pipe enable */
+	topctrl_writel(priv, 0, TX_FLUSH_CNTL);
+
+	umac_enable_set(priv, CMD_TX_EN, 1);
+
+	ret = tdma_enable_set(priv, 1);
+	if (ret) {
+		netdev_err(dev, "TDMA timeout!\n");
+		goto out_free_rx_ring;
+	}
+
+	phy_resume(priv->phydev);
+
+	bcm_sysport_netif_start(dev);
+
+	return 0;
+
+out_free_rx_ring:
+	bcm_sysport_fini_rx_ring(priv);
+out_free_tx_rings:
+	for (i = 0; i < dev->num_tx_queues; i++)
+		bcm_sysport_fini_tx_ring(priv, i);
+	return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bcm_sysport_pm_ops,
+		bcm_sysport_suspend, bcm_sysport_resume);
+
 static const struct of_device_id bcm_sysport_of_match[] = {
 	{ .compatible = "brcm,systemport-v1.00" },
 	{ .compatible = "brcm,systemport" },
@@ -1623,6 +1942,7 @@ static struct platform_driver bcm_syspor
 		.name = "brcm-systemport",
 		.owner = THIS_MODULE,
 		.of_match_table = bcm_sysport_of_match,
+		.pm = &bcm_sysport_pm_ops,
 	},
 };
 module_platform_driver(bcm_sysport_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bcmsysport.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bcmsysport.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bcmsysport.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bcmsysport.h	2014-09-28 17:29:07.000000000 -0400
@@ -246,6 +246,15 @@ struct bcm_rsb {
 #define  MIB_RX_CNT_RST			(1 << 0)
 #define  MIB_RUNT_CNT_RST		(1 << 1)
 #define  MIB_TX_CNT_RST			(1 << 2)
+
+#define UMAC_MPD_CTRL			0x620
+#define  MPD_EN				(1 << 0)
+#define  MSEQ_LEN_SHIFT			16
+#define  MSEQ_LEN_MASK			0xff
+#define  PSW_EN				(1 << 27)
+
+#define UMAC_PSW_MS			0x624
+#define UMAC_PSW_LS			0x628
 #define UMAC_MDF_CTRL			0x650
 #define UMAC_MDF_ADDR			0x654
 
@@ -642,6 +651,7 @@ struct bcm_sysport_priv {
 	struct platform_device	*pdev;
 	int			irq0;
 	int			irq1;
+	int			wol_irq;
 
 	/* Transmit rings */
 	struct bcm_sysport_tx_ring tx_rings[TDMA_NUM_RINGS];
@@ -664,10 +674,12 @@ struct bcm_sysport_priv {
 	int			old_duplex;
 
 	/* Misc fields */
-	unsigned int		rx_csum_en:1;
+	unsigned int		rx_chk_en:1;
 	unsigned int		tsb_en:1;
 	unsigned int		crc_fwd:1;
 	u16			rev;
+	u32			wolopts;
+	unsigned int		wol_irq_disabled:1;
 
 	/* MIB related fields */
 	struct bcm_sysport_mib	mib;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2.c	2014-08-07 04:51:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2.c	2014-09-28 21:33:01.000000000 -0400
@@ -1,6 +1,7 @@
-/* bnx2.c: Broadcom NX2 network driver.
+/* bnx2.c: QLogic NX2 network driver.
  *
- * Copyright (c) 2004-2013 Broadcom Corporation
+ * Copyright (c) 2004-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
@@ -71,10 +72,10 @@
 #define TX_TIMEOUT  (5*HZ)
 
 static char version[] =
-	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+	"QLogic NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/5716 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 /*(DEBLOBBED)*/
@@ -115,7 +116,7 @@ static struct {
 	{ "Broadcom NetXtreme II BCM5716 1000Base-SX" },
 	};
 
-static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
+static const struct pci_device_id bnx2_pci_tbl[] = {
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
 	  PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2_fw.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2_fw.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2_fw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2_fw.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
-/* bnx2_fw.h: Broadcom NX2 network driver.
+/* bnx2_fw.h: QLogic NX2 network driver.
  *
  * Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
-/* bnx2.h: Broadcom NX2 network driver.
+/* bnx2.h: QLogic NX2 network driver.
  *
- * Copyright (c) 2004-2013 Broadcom Corporation
+ * Copyright (c) 2004-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2014-08-07 04:51:45.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2014-09-28 21:33:11.000000000 -0400
@@ -483,11 +483,7 @@ static void bnx2x_tpa_start(struct bnx2x
 
 #ifdef BNX2X_STOP_ON_ERROR
 	fp->tpa_queue_used |= (1 << queue);
-#ifdef _ASM_GENERIC_INT_L64_H
-	DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
-#else
 	DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n",
-#endif
 	   fp->tpa_queue_used);
 #endif
 }
@@ -1192,29 +1188,38 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp)
 static void bnx2x_fill_report_data(struct bnx2x *bp,
 				   struct bnx2x_link_report_data *data)
 {
-	u16 line_speed = bnx2x_get_mf_speed(bp);
-
 	memset(data, 0, sizeof(*data));
 
-	/* Fill the report data: effective line speed */
-	data->line_speed = line_speed;
+	if (IS_PF(bp)) {
+		/* Fill the report data: effective line speed */
+		data->line_speed = bnx2x_get_mf_speed(bp);
 
-	/* Link is down */
-	if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
-		__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-			  &data->link_report_flags);
+		/* Link is down */
+		if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &data->link_report_flags);
 
-	/* Full DUPLEX */
-	if (bp->link_vars.duplex == DUPLEX_FULL)
-		__set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags);
+		if (!BNX2X_NUM_ETH_QUEUES(bp))
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &data->link_report_flags);
 
-	/* Rx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
-		__set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags);
+		/* Full DUPLEX */
+		if (bp->link_vars.duplex == DUPLEX_FULL)
+			__set_bit(BNX2X_LINK_REPORT_FD,
+				  &data->link_report_flags);
 
-	/* Tx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-		__set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags);
+		/* Rx Flow Control is ON */
+		if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
+			__set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+				  &data->link_report_flags);
+
+		/* Tx Flow Control is ON */
+		if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+			__set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+				  &data->link_report_flags);
+	} else { /* VF */
+		*data = bp->vf_link_vars;
+	}
 }
 
 /**
@@ -1268,6 +1273,10 @@ void __bnx2x_link_report(struct bnx2x *b
 	 */
 	memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data));
 
+	/* propagate status to VFs */
+	if (IS_PF(bp))
+		bnx2x_iov_link_update(bp);
+
 	if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
 		     &cur_data.link_report_flags)) {
 		netif_carrier_off(bp->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -2303,8 +2303,8 @@ static int bnx2x_set_admin_app_up(struct
 	return 0;
 }
 
-static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
-				 u16 idval, u8 up)
+static int bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
+				  u16 idval, u8 up)
 {
 	struct bnx2x *bp = netdev_priv(netdev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,6 +216,43 @@ static int bnx2x_get_port_type(struct bn
 	return port_type;
 }
 
+static int bnx2x_get_vf_settings(struct net_device *dev,
+				 struct ethtool_cmd *cmd)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	if (bp->state == BNX2X_STATE_OPEN) {
+		if (test_bit(BNX2X_LINK_REPORT_FD,
+			     &bp->vf_link_vars.link_report_flags))
+			cmd->duplex = DUPLEX_FULL;
+		else
+			cmd->duplex = DUPLEX_HALF;
+
+		ethtool_cmd_speed_set(cmd, bp->vf_link_vars.line_speed);
+	} else {
+		cmd->duplex = DUPLEX_UNKNOWN;
+		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+	}
+
+	cmd->port		= PORT_OTHER;
+	cmd->phy_address	= 0;
+	cmd->transceiver	= XCVR_INTERNAL;
+	cmd->autoneg		= AUTONEG_DISABLE;
+	cmd->maxtxpkt		= 0;
+	cmd->maxrxpkt		= 0;
+
+	DP(BNX2X_MSG_ETHTOOL, "ethtool_cmd: cmd %d\n"
+	   "  supported 0x%x  advertising 0x%x  speed %u\n"
+	   "  duplex %d  port %d  phy_address %d  transceiver %d\n"
+	   "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
+	   cmd->cmd, cmd->supported, cmd->advertising,
+	   ethtool_cmd_speed(cmd),
+	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
+	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
+
+	return 0;
+}
+
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -1111,6 +1148,10 @@ static u32 bnx2x_get_link(struct net_dev
 	if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
 		return 0;
 
+	if (IS_VF(bp))
+		return !test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				 &bp->vf_link_vars.link_report_flags);
+
 	return bp->link_vars.link_up;
 }
 
@@ -3485,8 +3526,7 @@ static const struct ethtool_ops bnx2x_et
 };
 
 static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
-	.get_settings		= bnx2x_get_settings,
-	.set_settings		= bnx2x_set_settings,
+	.get_settings		= bnx2x_get_vf_settings,
 	.get_drvinfo		= bnx2x_get_drvinfo,
 	.get_msglevel		= bnx2x_get_msglevel,
 	.set_msglevel		= bnx2x_set_msglevel,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h	2014-09-28 17:29:07.000000000 -0400
@@ -1483,6 +1483,7 @@ struct bnx2x {
 	union pf_vf_bulletin   *pf2vf_bulletin;
 	dma_addr_t		pf2vf_bulletin_mapping;
 
+	union pf_vf_bulletin		shadow_bulletin;
 	struct pf_vf_bulletin_content	old_bulletin;
 
 	u16 requested_nr_virtfn;
@@ -1508,8 +1509,10 @@ struct bnx2x {
 /* TCP with Timestamp Option (32) + IPv6 (40) */
 #define ETH_MAX_TPA_HEADER_SIZE		72
 
-	/* Max supported alignment is 256 (8 shift) */
-#define BNX2X_RX_ALIGN_SHIFT		min(8, L1_CACHE_SHIFT)
+	/* Max supported alignment is 256 (8 shift)
+	 * minimal alignment shift 6 is optimal for 57xxx HW performance
+	 */
+#define BNX2X_RX_ALIGN_SHIFT		max(6, min(8, L1_CACHE_SHIFT))
 
 	/* FW uses 2 Cache lines Alignment for start packet and size
 	 *
@@ -1929,6 +1932,8 @@ struct bnx2x {
 	struct semaphore			stats_sema;
 
 	u8					phys_port_id[ETH_ALEN];
+
+	struct bnx2x_link_report_data		vf_link_vars;
 };
 
 /* Tx queues may be less or equal to Rx queues */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h	2014-08-07 04:51:49.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h	2014-09-28 21:33:16.000000000 -0400
@@ -2233,7 +2233,12 @@ struct shmem2_region {
 	u32 reserved3;				/* Offset 0x14C */
 	u32 reserved4;				/* Offset 0x150 */
 	u32 link_attr_sync[PORT_MAX];		/* Offset 0x154 */
-	#define LINK_ATTR_SYNC_KR2_ENABLE	(1<<0)
+	#define LINK_ATTR_SYNC_KR2_ENABLE	0x00000001
+	#define LINK_SFP_EEPROM_COMP_CODE_MASK	0x0000ff00
+	#define LINK_SFP_EEPROM_COMP_CODE_SHIFT		 8
+	#define LINK_SFP_EEPROM_COMP_CODE_SR	0x00001000
+	#define LINK_SFP_EEPROM_COMP_CODE_LR	0x00002000
+	#define LINK_SFP_EEPROM_COMP_CODE_LRM	0x00004000
 
 	u32 reserved5[2];
 	u32 reserved6[PORT_MAX];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c	2014-09-28 17:29:07.000000000 -0400
@@ -154,15 +154,22 @@ typedef int (*read_sfp_module_eeprom_fun
 			 LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR		0x2
+	#define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN	0x0
 	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
 	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
 	#define SFP_EEPROM_CON_TYPE_VAL_RJ45	0x22
 
 
-#define SFP_EEPROM_COMP_CODE_ADDR		0x3
-	#define SFP_EEPROM_COMP_CODE_SR_MASK	(1<<4)
-	#define SFP_EEPROM_COMP_CODE_LR_MASK	(1<<5)
-	#define SFP_EEPROM_COMP_CODE_LRM_MASK	(1<<6)
+#define SFP_EEPROM_10G_COMP_CODE_ADDR		0x3
+	#define SFP_EEPROM_10G_COMP_CODE_SR_MASK	(1<<4)
+	#define SFP_EEPROM_10G_COMP_CODE_LR_MASK	(1<<5)
+	#define SFP_EEPROM_10G_COMP_CODE_LRM_MASK	(1<<6)
+
+#define SFP_EEPROM_1G_COMP_CODE_ADDR		0x6
+	#define SFP_EEPROM_1G_COMP_CODE_SX	(1<<0)
+	#define SFP_EEPROM_1G_COMP_CODE_LX	(1<<1)
+	#define SFP_EEPROM_1G_COMP_CODE_CX	(1<<2)
+	#define SFP_EEPROM_1G_COMP_CODE_BASE_T	(1<<3)
 
 #define SFP_EEPROM_FC_TX_TECH_ADDR		0x8
 	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
@@ -3633,8 +3640,8 @@ static void bnx2x_warpcore_enable_AN_KR2
 				 reg_set[i].val);
 
 	/* Start KR2 work-around timer which handles BCM8073 link-parner */
-	vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
-	bnx2x_update_link_attr(params, vars->link_attr_sync);
+	params->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
+	bnx2x_update_link_attr(params, params->link_attr_sync);
 }
 
 static void bnx2x_disable_kr2(struct link_params *params,
@@ -3666,8 +3673,8 @@ static void bnx2x_disable_kr2(struct lin
 	for (i = 0; i < ARRAY_SIZE(reg_set); i++)
 		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
 				 reg_set[i].val);
-	vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
-	bnx2x_update_link_attr(params, vars->link_attr_sync);
+	params->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+	bnx2x_update_link_attr(params, params->link_attr_sync);
 
 	vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
 }
@@ -4810,7 +4817,7 @@ void bnx2x_link_status_update(struct lin
 					~FEATURE_CONFIG_PFC_ENABLED;
 
 	if (SHMEM2_HAS(bp, link_attr_sync))
-		vars->link_attr_sync = SHMEM2_RD(bp,
+		params->link_attr_sync = SHMEM2_RD(bp,
 						 link_attr_sync[params->port]);
 
 	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
@@ -8057,21 +8064,24 @@ static int bnx2x_get_edc_mode(struct bnx
 {
 	struct bnx2x *bp = params->bp;
 	u32 sync_offset = 0, phy_idx, media_types;
-	u8 gport, val[2], check_limiting_mode = 0;
+	u8 val[SFP_EEPROM_FC_TX_TECH_ADDR + 1], check_limiting_mode = 0;
 	*edc_mode = EDC_MODE_LIMITING;
 	phy->media_type = ETH_PHY_UNSPECIFIED;
 	/* First check for copper cable */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
 					 I2C_DEV_ADDR_A0,
-					 SFP_EEPROM_CON_TYPE_ADDR,
-					 2,
+					 0,
+					 SFP_EEPROM_FC_TX_TECH_ADDR + 1,
 					 (u8 *)val) != 0) {
 		DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
 		return -EINVAL;
 	}
-
-	switch (val[0]) {
+	params->link_attr_sync &= ~LINK_SFP_EEPROM_COMP_CODE_MASK;
+	params->link_attr_sync |= val[SFP_EEPROM_10G_COMP_CODE_ADDR] <<
+		LINK_SFP_EEPROM_COMP_CODE_SHIFT;
+	bnx2x_update_link_attr(params, params->link_attr_sync);
+	switch (val[SFP_EEPROM_CON_TYPE_ADDR]) {
 	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
 	{
 		u8 copper_module_type;
@@ -8079,17 +8089,7 @@ static int bnx2x_get_edc_mode(struct bnx
 		/* Check if its active cable (includes SFP+ module)
 		 * of passive cable
 		 */
-		if (bnx2x_read_sfp_module_eeprom(phy,
-					       params,
-					       I2C_DEV_ADDR_A0,
-					       SFP_EEPROM_FC_TX_TECH_ADDR,
-					       1,
-					       &copper_module_type) != 0) {
-			DP(NETIF_MSG_LINK,
-				"Failed to read copper-cable-type"
-				" from SFP+ EEPROM\n");
-			return -EINVAL;
-		}
+		copper_module_type = val[SFP_EEPROM_FC_TX_TECH_ADDR];
 
 		if (copper_module_type &
 		    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
@@ -8115,16 +8115,18 @@ static int bnx2x_get_edc_mode(struct bnx
 		}
 		break;
 	}
+	case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN:
 	case SFP_EEPROM_CON_TYPE_VAL_LC:
 	case SFP_EEPROM_CON_TYPE_VAL_RJ45:
 		check_limiting_mode = 1;
-		if ((val[1] & (SFP_EEPROM_COMP_CODE_SR_MASK |
-			       SFP_EEPROM_COMP_CODE_LR_MASK |
-			       SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
+		if ((val[SFP_EEPROM_10G_COMP_CODE_ADDR] &
+		     (SFP_EEPROM_10G_COMP_CODE_SR_MASK |
+		      SFP_EEPROM_10G_COMP_CODE_LR_MASK |
+		      SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) {
 			DP(NETIF_MSG_LINK, "1G SFP module detected\n");
-			gport = params->port;
 			phy->media_type = ETH_PHY_SFP_1G_FIBER;
 			if (phy->req_line_speed != SPEED_1000) {
+				u8 gport = params->port;
 				phy->req_line_speed = SPEED_1000;
 				if (!CHIP_IS_E1x(bp)) {
 					gport = BP_PATH(bp) +
@@ -8134,6 +8136,12 @@ static int bnx2x_get_edc_mode(struct bnx
 					   "Warning: Link speed was forced to 1000Mbps. Current SFP module in port %d is not compliant with 10G Ethernet\n",
 					   gport);
 			}
+			if (val[SFP_EEPROM_1G_COMP_CODE_ADDR] &
+			    SFP_EEPROM_1G_COMP_CODE_BASE_T) {
+				bnx2x_sfp_set_transmitter(params, phy, 0);
+				msleep(40);
+				bnx2x_sfp_set_transmitter(params, phy, 1);
+			}
 		} else {
 			int idx, cfg_idx = 0;
 			DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -8149,7 +8157,7 @@ static int bnx2x_get_edc_mode(struct bnx
 		break;
 	default:
 		DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
-			 val[0]);
+			 val[SFP_EEPROM_CON_TYPE_ADDR]);
 		return -EINVAL;
 	}
 	sync_offset = params->shmem_base +
@@ -13507,7 +13515,7 @@ static void bnx2x_check_kr2_wa(struct li
 
 	sigdet = bnx2x_warpcore_get_sigdet(phy, params);
 	if (!sigdet) {
-		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+		if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
 			bnx2x_kr2_recovery(params, vars, phy);
 			DP(NETIF_MSG_LINK, "No sigdet\n");
 		}
@@ -13525,7 +13533,7 @@ static void bnx2x_check_kr2_wa(struct li
 
 	/* CL73 has not begun yet */
 	if (base_page == 0) {
-		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+		if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
 			bnx2x_kr2_recovery(params, vars, phy);
 			DP(NETIF_MSG_LINK, "No BP\n");
 		}
@@ -13541,7 +13549,7 @@ static void bnx2x_check_kr2_wa(struct li
 			    ((next_page & 0xe0) == 0x20))));
 
 	/* In case KR2 is already disabled, check if we need to re-enable it */
-	if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+	if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
 		if (!not_kr2_device) {
 			DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
 			   next_page);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h	2014-09-28 17:29:07.000000000 -0400
@@ -323,6 +323,9 @@ struct link_params {
 #define LINK_FLAGS_INT_DISABLED		(1<<0)
 #define PHY_INITIALIZED		(1<<1)
 	u32 lfa_base;
+
+	/* The same definitions as the shmem2 parameter */
+	u32 link_attr_sync;
 };
 
 /* Output parameters */
@@ -364,8 +367,6 @@ struct link_vars {
 	u8 rx_tx_asic_rst;
 	u8 turn_to_run_wc_rt;
 	u16 rsrv2;
-	/* The same definitions as the shmem2 parameter */
-	u32 link_attr_sync;
 };
 
 /***********************************************************/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2014-08-07 04:51:45.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2014-09-28 21:33:11.000000000 -0400
@@ -246,7 +246,7 @@ static struct {
 #define PCI_DEVICE_ID_NX2_57811_VF	CHIP_NUM_57811_VF
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
+static const struct pci_device_id bnx2x_pci_tbl[] = {
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
@@ -2695,6 +2695,14 @@ void bnx2x__link_status_update(struct bn
 		bp->link_vars.duplex = DUPLEX_FULL;
 		bp->link_vars.flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 		__bnx2x_link_report(bp);
+
+		bnx2x_sample_bulletin(bp);
+
+		/* if bulletin board did not have an update for link status
+		 * __bnx2x_link_report will report current status
+		 * but it will NOT duplicate report in case of already reported
+		 * during sampling bulletin board.
+		 */
 		bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
 	}
 }
@@ -6838,6 +6846,37 @@ static void bnx2x__common_init_phy(struc
 	bnx2x_release_phy_lock(bp);
 }
 
+static void bnx2x_config_endianity(struct bnx2x *bp, u32 val)
+{
+	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, val);
+
+	/* make sure this value is 0 */
+	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
+
+	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, val);
+}
+
+static void bnx2x_set_endianity(struct bnx2x *bp)
+{
+#ifdef __BIG_ENDIAN
+	bnx2x_config_endianity(bp, 1);
+#else
+	bnx2x_config_endianity(bp, 0);
+#endif
+}
+
+static void bnx2x_reset_endianity(struct bnx2x *bp)
+{
+	bnx2x_config_endianity(bp, 0);
+}
+
 /**
  * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
  *
@@ -6904,23 +6943,7 @@ static int bnx2x_init_hw_common(struct b
 
 	bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
 	bnx2x_init_pxp(bp);
-
-#ifdef __BIG_ENDIAN
-	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
-	/* make sure this value is 0 */
-	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
-
-/*	REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
-	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
-#endif
-
+	bnx2x_set_endianity(bp);
 	bnx2x_ilt_init_page_size(bp, INITOP_SET);
 
 	if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
@@ -10041,6 +10064,8 @@ static void bnx2x_prev_unload_close_mac(
 }
 
 #define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
+#define BNX2X_PREV_UNDI_PROD_ADDR_H(f) (BAR_TSTRORM_INTMEM + \
+					0x1848 + ((f) << 4))
 #define BNX2X_PREV_UNDI_RCQ(val)	((val) & 0xffff)
 #define BNX2X_PREV_UNDI_BD(val)		((val) >> 16 & 0xffff)
 #define BNX2X_PREV_UNDI_PROD(rcq, bd)	((bd) << 16 | (rcq))
@@ -10048,8 +10073,6 @@ static void bnx2x_prev_unload_close_mac(
 #define BCM_5710_UNDI_FW_MF_MAJOR	(0x07)
 #define BCM_5710_UNDI_FW_MF_MINOR	(0x08)
 #define BCM_5710_UNDI_FW_MF_VERS	(0x05)
-#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4))
-#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4))
 
 static bool bnx2x_prev_is_after_undi(struct bnx2x *bp)
 {
@@ -10068,72 +10091,25 @@ static bool bnx2x_prev_is_after_undi(str
 	return false;
 }
 
-static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp)
-{
-	u8 major, minor, version;
-	u32 fw;
-
-	/* Must check that FW is loaded */
-	if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
-	     MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
-		BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
-		return false;
-	}
-
-	/* Read Currently loaded FW version */
-	fw = REG_RD(bp, XSEM_REG_PRAM);
-	major = fw & 0xff;
-	minor = (fw >> 0x8) & 0xff;
-	version = (fw >> 0x10) & 0xff;
-	BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
-		       fw, major, minor, version);
-
-	if (major > BCM_5710_UNDI_FW_MF_MAJOR)
-		return true;
-
-	if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
-	    (minor > BCM_5710_UNDI_FW_MF_MINOR))
-		return true;
-
-	if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
-	    (minor == BCM_5710_UNDI_FW_MF_MINOR) &&
-	    (version >= BCM_5710_UNDI_FW_MF_VERS))
-		return true;
-
-	return false;
-}
-
-static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
-{
-	int i;
-
-	/* Due to legacy (FW) code, the first function on each engine has a
-	 * different offset macro from the rest of the functions.
-	 * Setting this for all 8 functions is harmless regardless of whether
-	 * this is actually a multi-function device.
-	 */
-	for (i = 0; i < 2; i++)
-		REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
-
-	for (i = 2; i < 8; i++)
-		REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
-
-	BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
-}
-
-static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
+static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 inc)
 {
 	u16 rcq, bd;
-	u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
+	u32 addr, tmp_reg;
 
+	if (BP_FUNC(bp) < 2)
+		addr = BNX2X_PREV_UNDI_PROD_ADDR(BP_PORT(bp));
+	else
+		addr = BNX2X_PREV_UNDI_PROD_ADDR_H(BP_FUNC(bp) - 2);
+
+	tmp_reg = REG_RD(bp, addr);
 	rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
 	bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
 
 	tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
-	REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg);
+	REG_WR(bp, addr, tmp_reg);
 
-	BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n",
-		       port, bd, rcq);
+	BNX2X_DEV_INFO("UNDI producer [%d/%d][%08x] rings bd -> 0x%04x, rcq -> 0x%04x\n",
+		       BP_PORT(bp), BP_FUNC(bp), addr, bd, rcq);
 }
 
 static int bnx2x_prev_mcp_done(struct bnx2x *bp)
@@ -10372,7 +10348,6 @@ static int bnx2x_prev_unload_common(stru
 	/* Reset should be performed after BRB is emptied */
 	if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
 		u32 timer_count = 1000;
-		bool need_write = true;
 
 		/* Close the MAC Rx to prevent BRB from filling up */
 		bnx2x_prev_unload_close_mac(bp, &mac_vals);
@@ -10409,20 +10384,10 @@ static int bnx2x_prev_unload_common(stru
 			else
 				timer_count--;
 
-			/* New UNDI FW supports MF and contains better
-			 * cleaning methods - might be redundant but harmless.
-			 */
-			if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
-				if (need_write) {
-					bnx2x_prev_unload_undi_mf(bp);
-					need_write = false;
-				}
-			} else if (prev_undi) {
-				/* If UNDI resides in memory,
-				 * manually increment it
-				 */
-				bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
-			}
+			/* If UNDI resides in memory, manually increment it */
+			if (prev_undi)
+				bnx2x_prev_unload_undi_inc(bp, 1);
+
 			udelay(10);
 		}
 
@@ -12421,6 +12386,7 @@ static const struct net_device_ops bnx2x
 	.ndo_busy_poll		= bnx2x_low_latency_recv,
 #endif
 	.ndo_get_phys_port_id	= bnx2x_get_phys_port_id,
+	.ndo_set_vf_link_state	= bnx2x_set_vf_link_state,
 };
 
 static int bnx2x_set_coherency_mask(struct bnx2x *bp)
@@ -13157,9 +13123,15 @@ static void __bnx2x_remove(struct pci_de
 	bnx2x_iov_remove_one(bp);
 
 	/* Power on: we can't let PCI layer write to us while we are in D3 */
-	if (IS_PF(bp))
+	if (IS_PF(bp)) {
 		bnx2x_set_power_state(bp, PCI_D0);
 
+		/* Set endianity registers to reset values in case next driver
+		 * boots in different endianty environment.
+		 */
+		bnx2x_reset_endianity(bp);
+	}
+
 	/* Disable MSI/MSI-X */
 	bnx2x_disable_msi(bp);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,11 @@
 #include <linux/crc32.h>
 #include <linux/if_vlan.h>
 
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+			    struct bnx2x_virtf **vf,
+			    struct pf_vf_bulletin_content **bulletin,
+			    bool test_queue);
+
 /* General service functions */
 static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
 					 u16 pf_id)
@@ -597,8 +602,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, str
 	rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_DEL);
 	if (rc) {
 		BNX2X_ERR("Failed to remove multicasts\n");
-		if (mc)
-			kfree(mc);
+		kfree(mc);
 		return rc;
 	}
 
@@ -1328,6 +1332,8 @@ int bnx2x_iov_init_one(struct bnx2x *bp,
 	/* Prepare the VFs event synchronization mechanism */
 	mutex_init(&bp->vfdb->event_mutex);
 
+	mutex_init(&bp->vfdb->bulletin_mutex);
+
 	return 0;
 failed:
 	DP(BNX2X_MSG_IOV, "Failed err=%d\n", err);
@@ -1473,6 +1479,107 @@ static void bnx2x_vfq_init(struct bnx2x
 	   vf->abs_vfid, q->sp_obj.func_id, q->cid);
 }
 
+static int bnx2x_max_speed_cap(struct bnx2x *bp)
+{
+	u32 supported = bp->port.supported[bnx2x_get_link_cfg_idx(bp)];
+
+	if (supported &
+	    (SUPPORTED_20000baseMLD2_Full | SUPPORTED_20000baseKR2_Full))
+		return 20000;
+
+	return 10000; /* assume lowest supported speed is 10G */
+}
+
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx)
+{
+	struct bnx2x_link_report_data *state = &bp->last_reported_link;
+	struct pf_vf_bulletin_content *bulletin;
+	struct bnx2x_virtf *vf;
+	bool update = true;
+	int rc = 0;
+
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, idx, &vf, &bulletin, false);
+	if (rc)
+		return rc;
+
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
+	if (vf->link_cfg == IFLA_VF_LINK_STATE_AUTO) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+
+		bulletin->link_speed = state->line_speed;
+		bulletin->link_flags = 0;
+		if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+		if (test_bit(BNX2X_LINK_REPORT_FD,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_FULL_DUPLEX;
+		if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_RX_FC_ON;
+		if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_TX_FC_ON;
+	} else if (vf->link_cfg == IFLA_VF_LINK_STATE_DISABLE &&
+		   !(bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+		bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+	} else if (vf->link_cfg == IFLA_VF_LINK_STATE_ENABLE &&
+		   (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+		bulletin->link_speed = bnx2x_max_speed_cap(bp);
+		bulletin->link_flags &= ~VFPF_LINK_REPORT_LINK_DOWN;
+	} else {
+		update = false;
+	}
+
+	if (update) {
+		DP(NETIF_MSG_LINK | BNX2X_MSG_IOV,
+		   "vf %d mode %u speed %d flags %x\n", idx,
+		   vf->link_cfg, bulletin->link_speed, bulletin->link_flags);
+
+		/* Post update on VF's bulletin board */
+		rc = bnx2x_post_vf_bulletin(bp, idx);
+		if (rc) {
+			BNX2X_ERR("failed to update VF[%d] bulletin\n", idx);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+	return rc;
+}
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int idx, int link_state)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	struct bnx2x_virtf *vf = BP_VF(bp, idx);
+
+	if (!vf)
+		return -EINVAL;
+
+	if (vf->link_cfg == link_state)
+		return 0; /* nothing todo */
+
+	vf->link_cfg = link_state;
+
+	return bnx2x_iov_link_update_vf(bp, idx);
+}
+
+void bnx2x_iov_link_update(struct bnx2x *bp)
+{
+	int vfid;
+
+	if (!IS_SRIOV(bp))
+		return;
+
+	for_each_vf(bp, vfid)
+		bnx2x_iov_link_update_vf(bp, vfid);
+}
+
 /* called by bnx2x_nic_load */
 int bnx2x_iov_nic_init(struct bnx2x *bp)
 {
@@ -2510,22 +2617,23 @@ void bnx2x_disable_sriov(struct bnx2x *b
 	pci_disable_sriov(bp->pdev);
 }
 
-static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
-			     struct bnx2x_virtf **vf,
-			     struct pf_vf_bulletin_content **bulletin)
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+			    struct bnx2x_virtf **vf,
+			    struct pf_vf_bulletin_content **bulletin,
+			    bool test_queue)
 {
 	if (bp->state != BNX2X_STATE_OPEN) {
-		BNX2X_ERR("vf ndo called though PF is down\n");
+		BNX2X_ERR("PF is down - can't utilize iov-related functionality\n");
 		return -EINVAL;
 	}
 
 	if (!IS_SRIOV(bp)) {
-		BNX2X_ERR("vf ndo called though sriov is disabled\n");
+		BNX2X_ERR("sriov is disabled - can't utilize iov-realted functionality\n");
 		return -EINVAL;
 	}
 
 	if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
-		BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+		BNX2X_ERR("VF is uninitialized - can't utilize iov-related functionality. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
 			  vfidx, BNX2X_NR_VIRTFN(bp));
 		return -EINVAL;
 	}
@@ -2535,19 +2643,18 @@ static int bnx2x_vf_ndo_prep(struct bnx2
 	*bulletin = BP_VF_BULLETIN(bp, vfidx);
 
 	if (!*vf) {
-		BNX2X_ERR("vf ndo called but vf struct is null. vfidx was %d\n",
-			  vfidx);
+		BNX2X_ERR("Unable to get VF structure for vfidx %d\n", vfidx);
 		return -EINVAL;
 	}
 
-	if (!(*vf)->vfqs) {
-		BNX2X_ERR("vf ndo called but vfqs struct is null. Was ndo invoked before dynamically enabling SR-IOV? vfidx was %d\n",
+	if (test_queue && !(*vf)->vfqs) {
+		BNX2X_ERR("vfqs struct is null. Was this invoked before dynamically enabling SR-IOV? vfidx was %d\n",
 			  vfidx);
 		return -EINVAL;
 	}
 
 	if (!*bulletin) {
-		BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+		BNX2X_ERR("Bulletin Board struct is null for vfidx %d\n",
 			  vfidx);
 		return -EINVAL;
 	}
@@ -2566,9 +2673,10 @@ int bnx2x_get_vf_config(struct net_devic
 	int rc;
 
 	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
 	if (rc)
 		return rc;
+
 	mac_obj = &bnx2x_leading_vfq(vf, mac_obj);
 	vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
 	if (!mac_obj || !vlan_obj) {
@@ -2591,6 +2699,7 @@ int bnx2x_get_vf_config(struct net_devic
 						 VLAN_HLEN);
 		}
 	} else {
+		mutex_lock(&bp->vfdb->bulletin_mutex);
 		/* mac */
 		if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
 			/* mac configured by ndo so its in bulletin board */
@@ -2606,6 +2715,8 @@ int bnx2x_get_vf_config(struct net_devic
 		else
 			/* function has not been loaded yet. Show vlans as 0s */
 			memset(&ivi->vlan, 0, VLAN_HLEN);
+
+		mutex_unlock(&bp->vfdb->bulletin_mutex);
 	}
 
 	return 0;
@@ -2635,15 +2746,18 @@ int bnx2x_set_vf_mac(struct net_device *
 	struct bnx2x_virtf *vf = NULL;
 	struct pf_vf_bulletin_content *bulletin = NULL;
 
-	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
-	if (rc)
-		return rc;
 	if (!is_valid_ether_addr(mac)) {
 		BNX2X_ERR("mac address invalid\n");
 		return -EINVAL;
 	}
 
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+	if (rc)
+		return rc;
+
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
 	/* update PF's copy of the VF's bulletin. Will no longer accept mac
 	 * configuration requests from vf unless match this mac
 	 */
@@ -2652,6 +2766,10 @@ int bnx2x_set_vf_mac(struct net_device *
 
 	/* Post update on VF's bulletin board */
 	rc = bnx2x_post_vf_bulletin(bp, vfidx);
+
+	/* release lock before checking return code */
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+
 	if (rc) {
 		BNX2X_ERR("failed to update VF[%d] bulletin\n", vfidx);
 		return rc;
@@ -2716,11 +2834,6 @@ int bnx2x_set_vf_vlan(struct net_device
 	unsigned long accept_flags;
 	int rc;
 
-	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
-	if (rc)
-		return rc;
-
 	if (vlan > 4095) {
 		BNX2X_ERR("illegal vlan value %d\n", vlan);
 		return -EINVAL;
@@ -2729,18 +2842,27 @@ int bnx2x_set_vf_vlan(struct net_device
 	DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
 	   vfidx, vlan, 0);
 
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+	if (rc)
+		return rc;
+
 	/* update PF's copy of the VF's bulletin. No point in posting the vlan
 	 * to the VF since it doesn't have anything to do with it. But it useful
 	 * to store it here in case the VF is not up yet and we can only
 	 * configure the vlan later when it does. Treat vlan id 0 as remove the
 	 * Host tag.
 	 */
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
 	if (vlan > 0)
 		bulletin->valid_bitmap |= 1 << VLAN_VALID;
 	else
 		bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
 	bulletin->vlan = vlan;
 
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+
 	/* is vf initialized and queue set up? */
 	if (vf->state != VF_ENABLED ||
 	    bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
@@ -2850,10 +2972,9 @@ out:
  * entire bulletin board excluding the crc field itself. Use the length field
  * as the Bulletin Board was posted by a PF with possibly a different version
  * from the vf which will sample it. Therefore, the length is computed by the
- * PF and the used blindly by the VF.
+ * PF and then used blindly by the VF.
  */
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
-			  struct pf_vf_bulletin_content *bulletin)
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin)
 {
 	return crc32(BULLETIN_CRC_SEED,
 		 ((u8 *)bulletin) + sizeof(bulletin->crc),
@@ -2863,47 +2984,74 @@ u32 bnx2x_crc_vf_bulletin(struct bnx2x *
 /* Check for new posts on the bulletin board */
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
 {
-	struct pf_vf_bulletin_content bulletin = bp->pf2vf_bulletin->content;
+	struct pf_vf_bulletin_content *bulletin;
 	int attempts;
 
-	/* bulletin board hasn't changed since last sample */
-	if (bp->old_bulletin.version == bulletin.version)
-		return PFVF_BULLETIN_UNCHANGED;
+	/* sampling structure in mid post may result with corrupted data
+	 * validate crc to ensure coherency.
+	 */
+	for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
+		u32 crc;
 
-	/* validate crc of new bulletin board */
-	if (bp->old_bulletin.version != bp->pf2vf_bulletin->content.version) {
-		/* sampling structure in mid post may result with corrupted data
-		 * validate crc to ensure coherency.
-		 */
-		for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
-			bulletin = bp->pf2vf_bulletin->content;
-			if (bulletin.crc == bnx2x_crc_vf_bulletin(bp,
-								  &bulletin))
-				break;
-			BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
-				  bulletin.crc,
-				  bnx2x_crc_vf_bulletin(bp, &bulletin));
-		}
-		if (attempts >= BULLETIN_ATTEMPTS) {
-			BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
-				  attempts);
-			return PFVF_BULLETIN_CRC_ERR;
-		}
+		/* sample the bulletin board */
+		memcpy(&bp->shadow_bulletin, bp->pf2vf_bulletin,
+		       sizeof(union pf_vf_bulletin));
+
+		crc = bnx2x_crc_vf_bulletin(&bp->shadow_bulletin.content);
+
+		if (bp->shadow_bulletin.content.crc == crc)
+			break;
+
+		BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
+			  bp->shadow_bulletin.content.crc, crc);
 	}
 
+	if (attempts >= BULLETIN_ATTEMPTS) {
+		BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
+			  attempts);
+		return PFVF_BULLETIN_CRC_ERR;
+	}
+	bulletin = &bp->shadow_bulletin.content;
+
+	/* bulletin board hasn't changed since last sample */
+	if (bp->old_bulletin.version == bulletin->version)
+		return PFVF_BULLETIN_UNCHANGED;
+
 	/* the mac address in bulletin board is valid and is new */
-	if (bulletin.valid_bitmap & 1 << MAC_ADDR_VALID &&
-	    !ether_addr_equal(bulletin.mac, bp->old_bulletin.mac)) {
+	if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID &&
+	    !ether_addr_equal(bulletin->mac, bp->old_bulletin.mac)) {
 		/* update new mac to net device */
-		memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
+		memcpy(bp->dev->dev_addr, bulletin->mac, ETH_ALEN);
 	}
 
-	/* the vlan in bulletin board is valid and is new */
-	if (bulletin.valid_bitmap & 1 << VLAN_VALID)
-		memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
+	if (bulletin->valid_bitmap & (1 << LINK_VALID)) {
+		DP(BNX2X_MSG_IOV, "link update speed %d flags %x\n",
+		   bulletin->link_speed, bulletin->link_flags);
+
+		bp->vf_link_vars.line_speed = bulletin->link_speed;
+		bp->vf_link_vars.link_report_flags = 0;
+		/* Link is down */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Full DUPLEX */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_FULL_DUPLEX)
+			__set_bit(BNX2X_LINK_REPORT_FD,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Rx Flow Control is ON */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_RX_FC_ON)
+			__set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Tx Flow Control is ON */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_TX_FC_ON)
+			__set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+				  &bp->vf_link_vars.link_report_flags);
+		__bnx2x_link_report(bp);
+	}
 
 	/* copy new bulletin board to bp */
-	bp->old_bulletin = bulletin;
+	memcpy(&bp->old_bulletin, bulletin,
+	       sizeof(struct pf_vf_bulletin_content));
 
 	return PFVF_BULLETIN_UPDATED;
 }
@@ -2948,6 +3096,8 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 	if (!bp->pf2vf_bulletin)
 		goto alloc_mem_err;
 
+	bnx2x_vf_bulletin_finalize(&bp->pf2vf_bulletin->content, true);
+
 	return 0;
 
 alloc_mem_err:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,11 @@ struct bnx2x_virtf {
 #define VF_CACHE_LINE		0x0010
 #define VF_CFG_VLAN		0x0020
 #define VF_CFG_STATS_COALESCE	0x0040
-
+#define VF_CFG_EXT_BULLETIN	0x0080
+	u8 link_cfg;		/* IFLA_VF_LINK_STATE_AUTO
+				 * IFLA_VF_LINK_STATE_ENABLE
+				 * IFLA_VF_LINK_STATE_DISABLE
+				 */
 	u8 state;
 #define VF_FREE		0	/* VF ready to be acquired holds no resc */
 #define VF_ACQUIRED	1	/* VF acquired, but not initialized */
@@ -295,22 +299,22 @@ struct bnx2x_vfdb {
 #define BP_VFDB(bp)		((bp)->vfdb)
 	/* vf array */
 	struct bnx2x_virtf	*vfs;
-#define BP_VF(bp, idx)		(&((bp)->vfdb->vfs[(idx)]))
-#define bnx2x_vf(bp, idx, var)	((bp)->vfdb->vfs[(idx)].var)
+#define BP_VF(bp, idx)		(&((bp)->vfdb->vfs[idx]))
+#define bnx2x_vf(bp, idx, var)	((bp)->vfdb->vfs[idx].var)
 
 	/* queue array - for all vfs */
 	struct bnx2x_vf_queue *vfqs;
 
 	/* vf HW contexts */
 	struct hw_dma		context[BNX2X_VF_CIDS/ILT_PAGE_CIDS];
-#define	BP_VF_CXT_PAGE(bp, i)	(&(bp)->vfdb->context[(i)])
+#define	BP_VF_CXT_PAGE(bp, i)	(&(bp)->vfdb->context[i])
 
 	/* SR-IOV information */
 	struct bnx2x_sriov	sriov;
 	struct hw_dma		mbx_dma;
 #define BP_VF_MBX_DMA(bp)	(&((bp)->vfdb->mbx_dma))
 	struct bnx2x_vf_mbx	mbxs[BNX2X_MAX_NUM_OF_VFS];
-#define BP_VF_MBX(bp, vfid)	(&((bp)->vfdb->mbxs[(vfid)]))
+#define BP_VF_MBX(bp, vfid)	(&((bp)->vfdb->mbxs[vfid]))
 
 	struct hw_dma		bulletin_dma;
 #define BP_VF_BULLETIN_DMA(bp)	(&((bp)->vfdb->bulletin_dma))
@@ -336,6 +340,9 @@ struct bnx2x_vfdb {
 	/* sp_rtnl synchronization */
 	struct mutex			event_mutex;
 	u64				event_occur;
+
+	/* bulletin board update synchronization */
+	struct mutex			bulletin_mutex;
 };
 
 /* queue access */
@@ -467,9 +474,10 @@ void bnx2x_vf_handle_flr_event(struct bn
 
 bool bnx2x_tlv_supported(u16 tlvtype);
 
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
-			  struct pf_vf_bulletin_content *bulletin);
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin);
 int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf);
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+				bool support_long);
 
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
 
@@ -520,6 +528,11 @@ void bnx2x_iov_task(struct work_struct *
 
 void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag);
 
+void bnx2x_iov_link_update(struct bnx2x *bp);
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx);
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state);
+
 #else /* CONFIG_BNX2X_SRIOV */
 
 static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
@@ -579,6 +592,14 @@ static inline void bnx2x_iov_channel_dow
 
 static inline void bnx2x_iov_task(struct work_struct *work) {}
 static inline void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag) {}
+static inline void bnx2x_iov_link_update(struct bnx2x *bp) {}
+static inline int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx) {return 0; }
+
+static inline int bnx2x_set_vf_link_state(struct net_device *dev, int vf,
+					  int link_state) {return 0; }
+struct pf_vf_bulletin_content;
+static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+					      bool support_long) {}
 
 #endif /* CONFIG_BNX2X_SRIOV */
 #endif /* bnx2x_sriov.h */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c	2014-09-28 17:29:07.000000000 -0400
@@ -251,6 +251,9 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp,
 	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
 		      CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));
 
+	/* Bulletin support for bulletin board with length > legacy length */
+	req->vfdev_info.caps |= VF_CAP_SUPPORT_EXT_BULLETIN;
+
 	/* add list termination tlv */
 	bnx2x_add_tlv(bp, req,
 		      req->first_tlv.tl.length + sizeof(struct channel_tlv),
@@ -1232,6 +1235,41 @@ static void bnx2x_vf_mbx_acquire_resp(st
 	bnx2x_vf_mbx_resp_send_msg(bp, vf, vfop_status);
 }
 
+static bool bnx2x_vf_mbx_is_windows_vm(struct bnx2x *bp,
+				       struct vfpf_acquire_tlv *acquire)
+{
+	/* Windows driver does one of three things:
+	 * 1. Old driver doesn't have bulletin board address set.
+	 * 2. 'Middle' driver sends mc_num == 32.
+	 * 3. New driver sets the OS field.
+	 */
+	if (!acquire->bulletin_addr ||
+	    acquire->resc_request.num_mc_filters == 32 ||
+	    ((acquire->vfdev_info.vf_os & VF_OS_MASK) ==
+	     VF_OS_WINDOWS))
+		return true;
+
+	return false;
+}
+
+static int bnx2x_vf_mbx_acquire_chk_dorq(struct bnx2x *bp,
+					 struct bnx2x_virtf *vf,
+					 struct bnx2x_vf_mbx *mbx)
+{
+	/* Linux drivers which correctly set the doorbell size also
+	 * send a physical port request
+	 */
+	if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
+				  CHANNEL_TLV_PHYS_PORT_ID))
+		return 0;
+
+	/* Issue does not exist in windows VMs */
+	if (bnx2x_vf_mbx_is_windows_vm(bp, &mbx->msg->req.acquire))
+		return 0;
+
+	return -EOPNOTSUPP;
+}
+
 static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
 				 struct bnx2x_vf_mbx *mbx)
 {
@@ -1247,12 +1285,32 @@ static void bnx2x_vf_mbx_acquire(struct
 	   acquire->resc_request.num_vlan_filters,
 	   acquire->resc_request.num_mc_filters);
 
+	/* Prevent VFs with old drivers from loading, since they calculate
+	 * CIDs incorrectly requiring a VF-flr [VM reboot] in order to recover
+	 * while being upgraded.
+	 */
+	rc = bnx2x_vf_mbx_acquire_chk_dorq(bp, vf, mbx);
+	if (rc) {
+		DP(BNX2X_MSG_IOV,
+		   "VF [%d] - Can't support acquire request due to doorbell mismatch. Please update VM driver\n",
+		   vf->abs_vfid);
+		goto out;
+	}
+
 	/* acquire the resources */
 	rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
 
 	/* store address of vf's bulletin board */
 	vf->bulletin_map = acquire->bulletin_addr;
+	if (acquire->vfdev_info.caps & VF_CAP_SUPPORT_EXT_BULLETIN) {
+		DP(BNX2X_MSG_IOV, "VF[%d] supports long bulletin boards\n",
+		   vf->abs_vfid);
+		vf->cfg_flags |= VF_CFG_EXT_BULLETIN;
+	} else {
+		vf->cfg_flags &= ~VF_CFG_EXT_BULLETIN;
+	}
 
+out:
 	/* response */
 	bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
 }
@@ -1273,6 +1331,10 @@ static void bnx2x_vf_mbx_init_vf(struct
 	if (init->flags & VFPF_INIT_FLG_STATS_COALESCE)
 		vf->cfg_flags |= VF_CFG_STATS_COALESCE;
 
+	/* Update VF's view of link state */
+	if (vf->cfg_flags & VF_CFG_EXT_BULLETIN)
+		bnx2x_iov_link_update_vf(bp, vf->index);
+
 	/* response */
 	bnx2x_vf_mbx_resp(bp, vf, rc);
 }
@@ -2007,6 +2069,17 @@ void bnx2x_vf_mbx(struct bnx2x *bp)
 	}
 }
 
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+				bool support_long)
+{
+	/* Older VFs contain a bug where they can't check CRC for bulletin
+	 * boards of length greater than legacy size.
+	 */
+	bulletin->length = support_long ? BULLETIN_CONTENT_SIZE :
+					  BULLETIN_CONTENT_LEGACY_SIZE;
+	bulletin->crc = bnx2x_crc_vf_bulletin(bulletin);
+}
+
 /* propagate local bulletin board to vf */
 int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
 {
@@ -2023,8 +2096,9 @@ int bnx2x_post_vf_bulletin(struct bnx2x
 
 	/* increment bulletin board version and compute crc */
 	bulletin->version++;
-	bulletin->length = BULLETIN_CONTENT_SIZE;
-	bulletin->crc = bnx2x_crc_vf_bulletin(bp, bulletin);
+	bnx2x_vf_bulletin_finalize(bulletin,
+				   (bnx2x_vf(bp, vf, cfg_flags) &
+				    VF_CFG_EXT_BULLETIN) ? true : false);
 
 	/* propagate bulletin board via dmae to vm memory */
 	rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h	2014-09-28 17:29:07.000000000 -0400
@@ -65,6 +65,7 @@ struct hw_sb_info {
 #define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST	0x00000008
 #define VFPF_RX_MASK_ACCEPT_BROADCAST		0x00000010
 #define BULLETIN_CONTENT_SIZE		(sizeof(struct pf_vf_bulletin_content))
+#define BULLETIN_CONTENT_LEGACY_SIZE	(32)
 #define BULLETIN_ATTEMPTS	5 /* crc failures before throwing towel */
 #define BULLETIN_CRC_SEED	0
 
@@ -117,7 +118,15 @@ struct vfpf_acquire_tlv {
 		/* the following fields are for debug purposes */
 		u8  vf_id;		/* ME register value */
 		u8  vf_os;		/* e.g. Linux, W2K8 */
-		u8 padding[2];
+#define VF_OS_SUBVERSION_MASK	(0x1f)
+#define VF_OS_MASK		(0xe0)
+#define VF_OS_SHIFT		(5)
+#define VF_OS_UNDEFINED		(0 << VF_OS_SHIFT)
+#define VF_OS_WINDOWS		(1 << VF_OS_SHIFT)
+
+		u8 padding;
+		u8 caps;
+#define VF_CAP_SUPPORT_EXT_BULLETIN	(1 << 0)
 	} vfdev_info;
 
 	struct vf_pf_resc_request resc_request;
@@ -393,11 +402,23 @@ struct pf_vf_bulletin_content {
 					 * to attempt to send messages on the
 					 * channel after this bit is set
 					 */
+#define LINK_VALID		3	/* alert the VF thet a new link status
+					 * update is available for it
+					 */
 	u8 mac[ETH_ALEN];
 	u8 mac_padding[2];
 
 	u16 vlan;
 	u8 vlan_padding[6];
+
+	u16 link_speed;			 /* Effective line speed */
+	u8 link_speed_padding[6];
+	u32 link_flags;			 /* VFPF_LINK_REPORT_XXX flags */
+#define VFPF_LINK_REPORT_LINK_DOWN	 (1 << 0)
+#define VFPF_LINK_REPORT_FULL_DUPLEX	 (1 << 1)
+#define VFPF_LINK_REPORT_RX_FC_ON	 (1 << 2)
+#define VFPF_LINK_REPORT_TX_FC_ON	 (1 << 3)
+	u8 link_flags_padding[4];
 };
 
 union pf_vf_bulletin {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,15 @@
-/* cnic.c: Broadcom CNIC core network driver.
+/* cnic.c: QLogic CNIC core network driver.
  *
  * Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Original skeleton written by: John(Zongxi) Chen (zongxi@broadcom.com)
- * Modified and maintained by: Michael Chan <mchan@broadcom.com>
+ * Previously modified and maintained by: Michael Chan <mchan@broadcom.com>
+ * Maintained By: Dept-HSGLinuxNICDev@qlogic.com
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -29,7 +31,7 @@
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
 #include <linux/random.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#if IS_ENABLED(CONFIG_VLAN_8021Q)
 #define BCM_VLAN 1
 #endif
 #include <net/ip.h>
@@ -56,11 +58,11 @@
 #define CNIC_MODULE_NAME	"cnic"
 
 static char version[] =
-	"Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+	"QLogic NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
 	      "Chen (zongxi@broadcom.com");
-MODULE_DESCRIPTION("Broadcom NetXtreme II CNIC Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II CNIC Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CNIC_MODULE_VERSION);
 
@@ -3683,7 +3685,7 @@ static int cnic_get_v4_route(struct sock
 static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr,
 			     struct dst_entry **dst)
 {
-#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_IPV6)
 	struct flowi6 fl6;
 
 	memset(&fl6, 0, sizeof(fl6));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic_defs.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic_defs.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic_defs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic_defs.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,8 @@
 
-/* cnic.c: Broadcom CNIC core network driver.
+/* cnic.c: QLogic CNIC core network driver.
  *
  * Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
-/* cnic.h: Broadcom CNIC core network driver.
+/* cnic.h: QLogic CNIC core network driver.
  *
  * Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic_if.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic_if.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/cnic_if.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/cnic_if.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
-/* cnic_if.h: Broadcom CNIC core network driver.
+/* cnic_if.h: QLogic CNIC core network driver.
  *
  * Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,15 +6,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
 #define pr_fmt(fmt)				"bcmgenet: " fmt
@@ -79,13 +70,13 @@
 				TOTAL_DESC * DMA_DESC_SIZE)
 
 static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
-						void __iomem *d, u32 value)
+					     void __iomem *d, u32 value)
 {
 	__raw_writel(value, d + DMA_DESC_LENGTH_STATUS);
 }
 
 static inline u32 dmadesc_get_length_status(struct bcmgenet_priv *priv,
-						void __iomem *d)
+					    void __iomem *d)
 {
 	return __raw_readl(d + DMA_DESC_LENGTH_STATUS);
 }
@@ -98,7 +89,7 @@ static inline void dmadesc_set_addr(stru
 
 	/* Register writes to GISB bus can take couple hundred nanoseconds
 	 * and are done for each packet, save these expensive writes unless
-	 * the platform is explicitely configured for 64-bits/LPAE.
+	 * the platform is explicitly configured for 64-bits/LPAE.
 	 */
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 	if (priv->hw_params->flags & GENET_HAS_40BITS)
@@ -108,7 +99,7 @@ static inline void dmadesc_set_addr(stru
 
 /* Combined address + length/status setter */
 static inline void dmadesc_set(struct bcmgenet_priv *priv,
-				void __iomem *d, dma_addr_t addr, u32 val)
+			       void __iomem *d, dma_addr_t addr, u32 val)
 {
 	dmadesc_set_length_status(priv, d, val);
 	dmadesc_set_addr(priv, d, addr);
@@ -123,7 +114,7 @@ static inline dma_addr_t dmadesc_get_add
 
 	/* Register writes to GISB bus can take couple hundred nanoseconds
 	 * and are done for each packet, save these expensive writes unless
-	 * the platform is explicitely configured for 64-bits/LPAE.
+	 * the platform is explicitly configured for 64-bits/LPAE.
 	 */
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 	if (priv->hw_params->flags & GENET_HAS_40BITS)
@@ -242,7 +233,7 @@ static inline struct bcmgenet_priv *dev_
 }
 
 static inline u32 bcmgenet_tdma_readl(struct bcmgenet_priv *priv,
-					enum dma_reg r)
+				      enum dma_reg r)
 {
 	return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
 			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
@@ -256,7 +247,7 @@ static inline void bcmgenet_tdma_writel(
 }
 
 static inline u32 bcmgenet_rdma_readl(struct bcmgenet_priv *priv,
-					enum dma_reg r)
+				      enum dma_reg r)
 {
 	return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
 			DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
@@ -333,8 +324,8 @@ static const u8 genet_dma_ring_regs_v123
 static const u8 *genet_dma_ring_regs;
 
 static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,
-						unsigned int ring,
-						enum dma_ring_reg r)
+					   unsigned int ring,
+					   enum dma_ring_reg r)
 {
 	return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
 			(DMA_RING_SIZE * ring) +
@@ -342,9 +333,8 @@ static inline u32 bcmgenet_tdma_ring_rea
 }
 
 static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,
-						unsigned int ring,
-						u32 val,
-						enum dma_ring_reg r)
+					     unsigned int ring, u32 val,
+					     enum dma_ring_reg r)
 {
 	__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
 			(DMA_RING_SIZE * ring) +
@@ -352,8 +342,8 @@ static inline void bcmgenet_tdma_ring_wr
 }
 
 static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,
-						unsigned int ring,
-						enum dma_ring_reg r)
+					   unsigned int ring,
+					   enum dma_ring_reg r)
 {
 	return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
 			(DMA_RING_SIZE * ring) +
@@ -361,9 +351,8 @@ static inline u32 bcmgenet_rdma_ring_rea
 }
 
 static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
-						unsigned int ring,
-						u32 val,
-						enum dma_ring_reg r)
+					     unsigned int ring, u32 val,
+					     enum dma_ring_reg r)
 {
 	__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
 			(DMA_RING_SIZE * ring) +
@@ -371,7 +360,7 @@ static inline void bcmgenet_rdma_ring_wr
 }
 
 static int bcmgenet_get_settings(struct net_device *dev,
-		struct ethtool_cmd *cmd)
+				 struct ethtool_cmd *cmd)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 
@@ -385,7 +374,7 @@ static int bcmgenet_get_settings(struct
 }
 
 static int bcmgenet_set_settings(struct net_device *dev,
-		struct ethtool_cmd *cmd)
+				 struct ethtool_cmd *cmd)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 
@@ -458,7 +447,7 @@ static int bcmgenet_set_tx_csum(struct n
 }
 
 static int bcmgenet_set_features(struct net_device *dev,
-		netdev_features_t features)
+				 netdev_features_t features)
 {
 	netdev_features_t changed = features ^ dev->features;
 	netdev_features_t wanted = dev->wanted_features;
@@ -625,12 +614,11 @@ static const struct bcmgenet_stats bcmge
 #define BCMGENET_STATS_LEN	ARRAY_SIZE(bcmgenet_gstrings_stats)
 
 static void bcmgenet_get_drvinfo(struct net_device *dev,
-		struct ethtool_drvinfo *info)
+				 struct ethtool_drvinfo *info)
 {
 	strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
 	strlcpy(info->version, "v2.0", sizeof(info->version));
 	info->n_stats = BCMGENET_STATS_LEN;
-
 }
 
 static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
@@ -643,8 +631,8 @@ static int bcmgenet_get_sset_count(struc
 	}
 }
 
-static void bcmgenet_get_strings(struct net_device *dev,
-				u32 stringset, u8 *data)
+static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,
+				 u8 *data)
 {
 	int i;
 
@@ -652,8 +640,8 @@ static void bcmgenet_get_strings(struct
 	case ETH_SS_STATS:
 		for (i = 0; i < BCMGENET_STATS_LEN; i++) {
 			memcpy(data + i * ETH_GSTRING_LEN,
-				bcmgenet_gstrings_stats[i].stat_string,
-				ETH_GSTRING_LEN);
+			       bcmgenet_gstrings_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
 		}
 		break;
 	}
@@ -678,8 +666,8 @@ static void bcmgenet_update_mib_counters
 		case BCMGENET_STAT_RUNT:
 			if (s->type != BCMGENET_STAT_MIB_RX)
 				offset = BCMGENET_STAT_OFFSET;
-			val = bcmgenet_umac_readl(priv, UMAC_MIB_START +
-								j + offset);
+			val = bcmgenet_umac_readl(priv,
+						  UMAC_MIB_START + j + offset);
 			break;
 		case BCMGENET_STAT_MISC:
 			val = bcmgenet_umac_readl(priv, s->reg_offset);
@@ -696,8 +684,8 @@ static void bcmgenet_update_mib_counters
 }
 
 static void bcmgenet_get_ethtool_stats(struct net_device *dev,
-					struct ethtool_stats *stats,
-					u64 *data)
+				       struct ethtool_stats *stats,
+				       u64 *data)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	int i;
@@ -730,6 +718,8 @@ static struct ethtool_ops bcmgenet_ethto
 	.get_link		= ethtool_op_get_link,
 	.get_msglevel		= bcmgenet_get_msglevel,
 	.set_msglevel		= bcmgenet_set_msglevel,
+	.get_wol		= bcmgenet_get_wol,
+	.set_wol		= bcmgenet_set_wol,
 };
 
 /* Power down the unimac, based on mode. */
@@ -743,9 +733,12 @@ static void bcmgenet_power_down(struct b
 		phy_detach(priv->phydev);
 		break;
 
+	case GENET_POWER_WOL_MAGIC:
+		bcmgenet_wol_power_down_cfg(priv, mode);
+		break;
+
 	case GENET_POWER_PASSIVE:
 		/* Power down LED */
-		bcmgenet_mii_reset(priv->dev);
 		if (priv->hw_params->flags & GENET_HAS_EXT) {
 			reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
 			reg |= (EXT_PWR_DOWN_PHY |
@@ -759,7 +752,7 @@ static void bcmgenet_power_down(struct b
 }
 
 static void bcmgenet_power_up(struct bcmgenet_priv *priv,
-				enum bcmgenet_power_mode mode)
+			      enum bcmgenet_power_mode mode)
 {
 	u32 reg;
 
@@ -777,12 +770,17 @@ static void bcmgenet_power_up(struct bcm
 		/* enable APD */
 		reg |= EXT_PWR_DN_EN_LD;
 		break;
+	case GENET_POWER_WOL_MAGIC:
+		bcmgenet_wol_power_up_cfg(priv, mode);
+		return;
 	default:
 		break;
 	}
 
 	bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-	bcmgenet_mii_reset(priv->dev);
+
+	if (mode == GENET_POWER_PASSIVE)
+		bcmgenet_mii_reset(priv->dev);
 }
 
 /* ioctl handle special commands that are not present in ethtool. */
@@ -841,45 +839,46 @@ static inline void bcmgenet_tx_ring16_in
 						  struct bcmgenet_tx_ring *ring)
 {
 	bcmgenet_intrl2_0_writel(priv,
-			UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
-			INTRL2_CPU_MASK_SET);
+				 UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+				 INTRL2_CPU_MASK_SET);
 }
 
 static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_priv *priv,
 						 struct bcmgenet_tx_ring *ring)
 {
 	bcmgenet_intrl2_0_writel(priv,
-			UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
-			INTRL2_CPU_MASK_CLEAR);
+				 UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+				 INTRL2_CPU_MASK_CLEAR);
 }
 
 static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_priv *priv,
-						struct bcmgenet_tx_ring *ring)
+					       struct bcmgenet_tx_ring *ring)
 {
-	bcmgenet_intrl2_1_writel(priv,
-			(1 << ring->index), INTRL2_CPU_MASK_CLEAR);
+	bcmgenet_intrl2_1_writel(priv, (1 << ring->index),
+				 INTRL2_CPU_MASK_CLEAR);
 	priv->int1_mask &= ~(1 << ring->index);
 }
 
 static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv,
 						struct bcmgenet_tx_ring *ring)
 {
-	bcmgenet_intrl2_1_writel(priv,
-			(1 << ring->index), INTRL2_CPU_MASK_SET);
+	bcmgenet_intrl2_1_writel(priv, (1 << ring->index),
+				 INTRL2_CPU_MASK_SET);
 	priv->int1_mask |= (1 << ring->index);
 }
 
 /* Unlocked version of the reclaim routine */
 static void __bcmgenet_tx_reclaim(struct net_device *dev,
-				struct bcmgenet_tx_ring *ring)
+				  struct bcmgenet_tx_ring *ring)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	int last_tx_cn, last_c_index, num_tx_bds;
 	struct enet_cb *tx_cb_ptr;
 	struct netdev_queue *txq;
+	unsigned int bds_compl;
 	unsigned int c_index;
 
-	/* Compute how many buffers are transmited since last xmit call */
+	/* Compute how many buffers are transmitted since last xmit call */
 	c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX);
 	txq = netdev_get_tx_queue(dev, ring->queue);
 
@@ -894,31 +893,33 @@ static void __bcmgenet_tx_reclaim(struct
 		last_tx_cn = num_tx_bds - last_c_index + c_index;
 
 	netif_dbg(priv, tx_done, dev,
-			"%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
-			__func__, ring->index,
-			c_index, last_tx_cn, last_c_index);
+		  "%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
+		  __func__, ring->index,
+		  c_index, last_tx_cn, last_c_index);
 
 	/* Reclaim transmitted buffers */
 	while (last_tx_cn-- > 0) {
 		tx_cb_ptr = ring->cbs + last_c_index;
+		bds_compl = 0;
 		if (tx_cb_ptr->skb) {
+			bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1;
 			dev->stats.tx_bytes += tx_cb_ptr->skb->len;
 			dma_unmap_single(&dev->dev,
-					dma_unmap_addr(tx_cb_ptr, dma_addr),
-					tx_cb_ptr->skb->len,
-					DMA_TO_DEVICE);
+					 dma_unmap_addr(tx_cb_ptr, dma_addr),
+					 tx_cb_ptr->skb->len,
+					 DMA_TO_DEVICE);
 			bcmgenet_free_cb(tx_cb_ptr);
 		} else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
 			dev->stats.tx_bytes +=
 				dma_unmap_len(tx_cb_ptr, dma_len);
 			dma_unmap_page(&dev->dev,
-					dma_unmap_addr(tx_cb_ptr, dma_addr),
-					dma_unmap_len(tx_cb_ptr, dma_len),
-					DMA_TO_DEVICE);
+				       dma_unmap_addr(tx_cb_ptr, dma_addr),
+				       dma_unmap_len(tx_cb_ptr, dma_len),
+				       DMA_TO_DEVICE);
 			dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0);
 		}
 		dev->stats.tx_packets++;
-		ring->free_bds += 1;
+		ring->free_bds += bds_compl;
 
 		last_c_index++;
 		last_c_index &= (num_tx_bds - 1);
@@ -934,7 +935,7 @@ static void __bcmgenet_tx_reclaim(struct
 }
 
 static void bcmgenet_tx_reclaim(struct net_device *dev,
-		struct bcmgenet_tx_ring *ring)
+				struct bcmgenet_tx_ring *ring)
 {
 	unsigned long flags;
 
@@ -1008,11 +1009,11 @@ static int bcmgenet_xmit_single(struct n
 	return 0;
 }
 
-/* Transmit a SKB fragement */
+/* Transmit a SKB fragment */
 static int bcmgenet_xmit_frag(struct net_device *dev,
-				skb_frag_t *frag,
-				u16 dma_desc_flags,
-				struct bcmgenet_tx_ring *ring)
+			      skb_frag_t *frag,
+			      u16 dma_desc_flags,
+			      struct bcmgenet_tx_ring *ring)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	struct device *kdev = &priv->pdev->dev;
@@ -1027,11 +1028,11 @@ static int bcmgenet_xmit_frag(struct net
 	tx_cb_ptr->skb = NULL;
 
 	mapping = skb_frag_dma_map(kdev, frag, 0,
-		skb_frag_size(frag), DMA_TO_DEVICE);
+				   skb_frag_size(frag), DMA_TO_DEVICE);
 	ret = dma_mapping_error(kdev, mapping);
 	if (ret) {
 		netif_err(priv, tx_err, dev, "%s: Tx DMA map failed\n",
-				__func__);
+			  __func__);
 		return ret;
 	}
 
@@ -1039,8 +1040,8 @@ static int bcmgenet_xmit_frag(struct net
 	dma_unmap_len_set(tx_cb_ptr, dma_len, frag->size);
 
 	dmadesc_set(priv, tx_cb_ptr->bd_addr, mapping,
-			(frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
-			(priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT));
+		    (frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
+		    (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT));
 
 
 	ring->free_bds -= 1;
@@ -1103,8 +1104,9 @@ static int bcmgenet_put_tx_csum(struct n
 			tx_csum_info |= STATUS_TX_CSUM_LV;
 			if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP)
 				tx_csum_info |= STATUS_TX_CSUM_PROTO_UDP;
-		} else
+		} else {
 			tx_csum_info = 0;
+		}
 
 		status->tx_csum_info = tx_csum_info;
 	}
@@ -1144,7 +1146,7 @@ static netdev_tx_t bcmgenet_xmit(struct
 	if (ring->free_bds <= nr_frags + 1) {
 		netif_tx_stop_queue(txq);
 		netdev_err(dev, "%s: tx ring %d full when queue %d awake\n",
-				__func__, index, ring->queue);
+			   __func__, index, ring->queue);
 		ret = NETDEV_TX_BUSY;
 		goto out;
 	}
@@ -1177,8 +1179,9 @@ static netdev_tx_t bcmgenet_xmit(struct
 	/* xmit fragment */
 	for (i = 0; i < nr_frags; i++) {
 		ret = bcmgenet_xmit_frag(dev,
-				&skb_shinfo(skb)->frags[i],
-				(i == nr_frags - 1) ? DMA_EOP : 0, ring);
+					 &skb_shinfo(skb)->frags[i],
+					 (i == nr_frags - 1) ? DMA_EOP : 0,
+					 ring);
 		if (ret) {
 			ret = NETDEV_TX_OK;
 			goto out;
@@ -1191,7 +1194,7 @@ static netdev_tx_t bcmgenet_xmit(struct
 	 * producer index, now write it down to the hardware
 	 */
 	bcmgenet_tdma_ring_writel(priv, ring->index,
-			ring->prod_index, TDMA_PROD_INDEX);
+				  ring->prod_index, TDMA_PROD_INDEX);
 
 	if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) {
 		netif_tx_stop_queue(txq);
@@ -1205,16 +1208,14 @@ out:
 }
 
 
-static int bcmgenet_rx_refill(struct bcmgenet_priv *priv,
-				struct enet_cb *cb)
+static int bcmgenet_rx_refill(struct bcmgenet_priv *priv, struct enet_cb *cb)
 {
 	struct device *kdev = &priv->pdev->dev;
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 	int ret;
 
-	skb = netdev_alloc_skb(priv->dev,
-				priv->rx_buf_len + SKB_ALIGNMENT);
+	skb = netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT);
 	if (!skb)
 		return -ENOMEM;
 
@@ -1222,12 +1223,12 @@ static int bcmgenet_rx_refill(struct bcm
 	WARN_ON(cb->skb != NULL);
 	cb->skb = skb;
 	mapping = dma_map_single(kdev, skb->data,
-			priv->rx_buf_len, DMA_FROM_DEVICE);
+				 priv->rx_buf_len, DMA_FROM_DEVICE);
 	ret = dma_mapping_error(kdev, mapping);
 	if (ret) {
 		bcmgenet_free_cb(cb);
 		netif_err(priv, rx_err, priv->dev,
-				"%s DMA map failed\n", __func__);
+			  "%s DMA map failed\n", __func__);
 		return ret;
 	}
 
@@ -1262,8 +1263,7 @@ static unsigned int bcmgenet_desc_rx(str
 	unsigned int p_index;
 	unsigned int chksum_ok = 0;
 
-	p_index = bcmgenet_rdma_ring_readl(priv,
-			DESC_INDEX, RDMA_PROD_INDEX);
+	p_index = bcmgenet_rdma_ring_readl(priv, DESC_INDEX, RDMA_PROD_INDEX);
 	p_index &= DMA_P_INDEX_MASK;
 
 	if (p_index < priv->rx_c_index)
@@ -1273,27 +1273,45 @@ static unsigned int bcmgenet_desc_rx(str
 		rxpkttoprocess = p_index - priv->rx_c_index;
 
 	netif_dbg(priv, rx_status, dev,
-		"RDMA: rxpkttoprocess=%d\n", rxpkttoprocess);
+		  "RDMA: rxpkttoprocess=%d\n", rxpkttoprocess);
 
 	while ((rxpktprocessed < rxpkttoprocess) &&
-			(rxpktprocessed < budget)) {
+	       (rxpktprocessed < budget)) {
+		cb = &priv->rx_cbs[priv->rx_read_ptr];
+		skb = cb->skb;
+
+		rxpktprocessed++;
+
+		priv->rx_read_ptr++;
+		priv->rx_read_ptr &= (priv->num_rx_bds - 1);
+
+		/* We do not have a backing SKB, so we do not have a
+		 * corresponding DMA mapping for this incoming packet since
+		 * bcmgenet_rx_refill always either has both skb and mapping or
+		 * none.
+		 */
+		if (unlikely(!skb)) {
+			dev->stats.rx_dropped++;
+			dev->stats.rx_errors++;
+			goto refill;
+		}
 
 		/* Unmap the packet contents such that we can use the
 		 * RSV from the 64 bytes descriptor when enabled and save
 		 * a 32-bits register read
 		 */
-		cb = &priv->rx_cbs[priv->rx_read_ptr];
-		skb = cb->skb;
 		dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr),
-				priv->rx_buf_len, DMA_FROM_DEVICE);
+				 priv->rx_buf_len, DMA_FROM_DEVICE);
 
 		if (!priv->desc_64b_en) {
-			dma_length_status = dmadesc_get_length_status(priv,
-							priv->rx_bds +
-							(priv->rx_read_ptr *
-							 DMA_DESC_SIZE));
+			dma_length_status =
+				dmadesc_get_length_status(priv,
+							  priv->rx_bds +
+							  (priv->rx_read_ptr *
+							   DMA_DESC_SIZE));
 		} else {
 			struct status_64 *status;
+
 			status = (struct status_64 *)skb->data;
 			dma_length_status = status->length_status;
 		}
@@ -1305,25 +1323,13 @@ static unsigned int bcmgenet_desc_rx(str
 		len = dma_length_status >> DMA_BUFLENGTH_SHIFT;
 
 		netif_dbg(priv, rx_status, dev,
-			"%s: p_ind=%d c_ind=%d read_ptr=%d len_stat=0x%08x\n",
-			__func__, p_index, priv->rx_c_index, priv->rx_read_ptr,
-			dma_length_status);
-
-		rxpktprocessed++;
-
-		priv->rx_read_ptr++;
-		priv->rx_read_ptr &= (priv->num_rx_bds - 1);
-
-		/* out of memory, just drop packets at the hardware level */
-		if (unlikely(!skb)) {
-			dev->stats.rx_dropped++;
-			dev->stats.rx_errors++;
-			goto refill;
-		}
+			  "%s:p_ind=%d c_ind=%d read_ptr=%d len_stat=0x%08x\n",
+			  __func__, p_index, priv->rx_c_index,
+			  priv->rx_read_ptr, dma_length_status);
 
 		if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
 			netif_err(priv, rx_status, dev,
-					"Droping fragmented packet!\n");
+				  "dropping fragmented packet!\n");
 			dev->stats.rx_dropped++;
 			dev->stats.rx_errors++;
 			dev_kfree_skb_any(cb->skb);
@@ -1337,7 +1343,7 @@ static unsigned int bcmgenet_desc_rx(str
 						DMA_RX_LG |
 						DMA_RX_RXER))) {
 			netif_err(priv, rx_status, dev, "dma_flag=0x%x\n",
-						(unsigned int)dma_flag);
+				  (unsigned int)dma_flag);
 			if (dma_flag & DMA_RX_CRC_ERROR)
 				dev->stats.rx_crc_errors++;
 			if (dma_flag & DMA_RX_OV)
@@ -1356,7 +1362,7 @@ static unsigned int bcmgenet_desc_rx(str
 		} /* error packet */
 
 		chksum_ok = (dma_flag & priv->dma_rx_chk_bit) &&
-				priv->desc_rxchk_en;
+			     priv->desc_rxchk_en;
 
 		skb_put(skb, len);
 		if (priv->desc_64b_en) {
@@ -1416,7 +1422,6 @@ static int bcmgenet_alloc_rx_buffers(str
 		ret = bcmgenet_rx_refill(priv, cb);
 		if (ret)
 			break;
-
 	}
 
 	return ret;
@@ -1432,8 +1437,8 @@ static void bcmgenet_free_rx_buffers(str
 
 		if (dma_unmap_addr(cb, dma_addr)) {
 			dma_unmap_single(&priv->dev->dev,
-					dma_unmap_addr(cb, dma_addr),
-					priv->rx_buf_len, DMA_FROM_DEVICE);
+					 dma_unmap_addr(cb, dma_addr),
+					 priv->rx_buf_len, DMA_FROM_DEVICE);
 			dma_unmap_addr_set(cb, dma_addr, 0);
 		}
 
@@ -1442,6 +1447,24 @@ static void bcmgenet_free_rx_buffers(str
 	}
 }
 
+static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
+{
+	u32 reg;
+
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	if (enable)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	/* UniMAC stops on a packet boundary, wait for a full-size packet
+	 * to be processed
+	 */
+	if (enable == 0)
+		usleep_range(1000, 2000);
+}
+
 static int reset_umac(struct bcmgenet_priv *priv)
 {
 	struct device *kdev = &priv->pdev->dev;
@@ -1467,13 +1490,24 @@ static int reset_umac(struct bcmgenet_pr
 
 	if (timeout == 1000) {
 		dev_err(kdev,
-			"timeout waiting for MAC to come out of resetn\n");
+			"timeout waiting for MAC to come out of reset\n");
 		return -ETIMEDOUT;
 	}
 
 	return 0;
 }
 
+static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
+{
+	/* Mask all interrupts.*/
+	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
+	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
+	bcmgenet_intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+	bcmgenet_intrl2_1_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
+	bcmgenet_intrl2_1_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
+	bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+}
+
 static int init_umac(struct bcmgenet_priv *priv)
 {
 	struct device *kdev = &priv->pdev->dev;
@@ -1489,7 +1523,8 @@ static int init_umac(struct bcmgenet_pri
 	bcmgenet_umac_writel(priv, 0, UMAC_CMD);
 	/* clear tx/rx counter */
 	bcmgenet_umac_writel(priv,
-		MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT, UMAC_MIB_CTRL);
+			     MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT,
+			     UMAC_MIB_CTRL);
 	bcmgenet_umac_writel(priv, 0, UMAC_MIB_CTRL);
 
 	bcmgenet_umac_writel(priv, ENET_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
@@ -1502,21 +1537,18 @@ static int init_umac(struct bcmgenet_pri
 	if (!GENET_IS_V1(priv) && !GENET_IS_V2(priv))
 		bcmgenet_rbuf_writel(priv, 1, RBUF_TBUF_SIZE_CTRL);
 
-	/* Mask all interrupts.*/
-	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
-	bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
-	bcmgenet_intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+	bcmgenet_intr_disable(priv);
 
 	cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE;
 
 	dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__);
 
-	/* Monitor cable plug/unpluged event for internal PHY */
-	if (phy_is_internal(priv->phydev))
+	/* Monitor cable plug/unplugged event for internal PHY */
+	if (phy_is_internal(priv->phydev)) {
 		cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
-	else if (priv->ext_phy)
+	} else if (priv->ext_phy) {
 		cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
-	else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+	} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
 		reg = bcmgenet_bp_mc_get(priv);
 		reg |= BIT(priv->hw_params->bp_in_en_shift);
 
@@ -1532,8 +1564,7 @@ static int init_umac(struct bcmgenet_pri
 	if (priv->hw_params->flags & GENET_HAS_MDIO_INTR)
 		cpu_mask_clear |= UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR;
 
-	bcmgenet_intrl2_0_writel(priv, cpu_mask_clear,
-		INTRL2_CPU_MASK_CLEAR);
+	bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR);
 
 	/* Enable rx/tx engine.*/
 	dev_dbg(kdev, "done init umac\n");
@@ -1582,28 +1613,28 @@ static void bcmgenet_init_tx_ring(struct
 	bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
 	/* Disable rate control for now */
 	bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
-			TDMA_FLOW_PERIOD);
+				  TDMA_FLOW_PERIOD);
 	/* Unclassified traffic goes to ring 16 */
 	bcmgenet_tdma_ring_writel(priv, index,
-			((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
-			DMA_RING_BUF_SIZE);
+				  ((size << DMA_RING_SIZE_SHIFT) |
+				   RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
 
 	first_bd = write_ptr;
 
 	/* Set start and end address, read and write pointers */
 	bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
-			DMA_START_ADDR);
+				  DMA_START_ADDR);
 	bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
-			TDMA_READ_PTR);
+				  TDMA_READ_PTR);
 	bcmgenet_tdma_ring_writel(priv, index, first_bd,
-			TDMA_WRITE_PTR);
+				  TDMA_WRITE_PTR);
 	bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
-			DMA_END_ADDR);
+				  DMA_END_ADDR);
 }
 
 /* Initialize a RDMA ring */
 static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
-				  unsigned int index, unsigned int size)
+				 unsigned int index, unsigned int size)
 {
 	u32 words_per_bd = WORDS_PER_BD(priv);
 	int ret;
@@ -1614,8 +1645,8 @@ static int bcmgenet_init_rx_ring(struct
 	priv->rx_bd_assign_index = 0;
 	priv->rx_c_index = 0;
 	priv->rx_read_ptr = 0;
-	priv->rx_cbs = kzalloc(priv->num_rx_bds * sizeof(struct enet_cb),
-				GFP_KERNEL);
+	priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct enet_cb),
+			       GFP_KERNEL);
 	if (!priv->rx_cbs)
 		return -ENOMEM;
 
@@ -1629,14 +1660,15 @@ static int bcmgenet_init_rx_ring(struct
 	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
 	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
 	bcmgenet_rdma_ring_writel(priv, index,
-		((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
-		DMA_RING_BUF_SIZE);
+				  ((size << DMA_RING_SIZE_SHIFT) |
+				   RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
 	bcmgenet_rdma_ring_writel(priv, index, 0, DMA_START_ADDR);
 	bcmgenet_rdma_ring_writel(priv, index,
-		words_per_bd * size - 1, DMA_END_ADDR);
+				  words_per_bd * size - 1, DMA_END_ADDR);
 	bcmgenet_rdma_ring_writel(priv, index,
-			(DMA_FC_THRESH_LO << DMA_XOFF_THRESHOLD_SHIFT) |
-			DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
+				  (DMA_FC_THRESH_LO <<
+				   DMA_XOFF_THRESHOLD_SHIFT) |
+				   DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
 	bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_READ_PTR);
 
 	return ret;
@@ -1683,10 +1715,10 @@ static void bcmgenet_init_multiq(struct
 		 * (ring 16)
 		 */
 		bcmgenet_init_tx_ring(priv, i, priv->hw_params->bds_cnt,
-					i * priv->hw_params->bds_cnt,
-					(i + 1) * priv->hw_params->bds_cnt);
+				      i * priv->hw_params->bds_cnt,
+				      (i + 1) * priv->hw_params->bds_cnt);
 
-		/* Configure ring as decriptor ring and setup priority */
+		/* Configure ring as descriptor ring and setup priority */
 		ring_cfg |= 1 << i;
 		dma_priority |= ((GENET_Q0_PRIORITY + i) <<
 				(GENET_MAX_MQ_CNT + 1) * i);
@@ -1712,13 +1744,63 @@ static void bcmgenet_init_multiq(struct
 	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
 }
 
+static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
+{
+	int ret = 0;
+	int timeout = 0;
+	u32 reg;
+
+	/* Disable TDMA to stop add more frames in TX DMA */
+	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+	reg &= ~DMA_EN;
+	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+
+	/* Check TDMA status register to confirm TDMA is disabled */
+	while (timeout++ < DMA_TIMEOUT_VAL) {
+		reg = bcmgenet_tdma_readl(priv, DMA_STATUS);
+		if (reg & DMA_DISABLED)
+			break;
+
+		udelay(1);
+	}
+
+	if (timeout == DMA_TIMEOUT_VAL) {
+		netdev_warn(priv->dev, "Timed out while disabling TX DMA\n");
+		ret = -ETIMEDOUT;
+	}
+
+	/* Wait 10ms for packet drain in both tx and rx dma */
+	usleep_range(10000, 20000);
+
+	/* Disable RDMA */
+	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+	reg &= ~DMA_EN;
+	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+	timeout = 0;
+	/* Check RDMA status register to confirm RDMA is disabled */
+	while (timeout++ < DMA_TIMEOUT_VAL) {
+		reg = bcmgenet_rdma_readl(priv, DMA_STATUS);
+		if (reg & DMA_DISABLED)
+			break;
+
+		udelay(1);
+	}
+
+	if (timeout == DMA_TIMEOUT_VAL) {
+		netdev_warn(priv->dev, "Timed out while disabling RX DMA\n");
+		ret = -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
 static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
 {
 	int i;
 
 	/* disable DMA */
-	bcmgenet_rdma_writel(priv, 0, DMA_CTRL);
-	bcmgenet_tdma_writel(priv, 0, DMA_CTRL);
+	bcmgenet_dma_teardown(priv);
 
 	for (i = 0; i < priv->num_tx_bds; i++) {
 		if (priv->tx_cbs[i].skb != NULL) {
@@ -1752,11 +1834,11 @@ static int bcmgenet_init_dma(struct bcmg
 	/* Init tDma */
 	bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
 
-	/* Initialize commont TX ring structures */
+	/* Initialize common TX ring structures */
 	priv->tx_bds = priv->base + priv->hw_params->tdma_offset;
 	priv->num_tx_bds = TOTAL_DESC;
-	priv->tx_cbs = kzalloc(priv->num_tx_bds * sizeof(struct enet_cb),
-				GFP_KERNEL);
+	priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb),
+			       GFP_KERNEL);
 	if (!priv->tx_cbs) {
 		bcmgenet_fini_dma(priv);
 		return -ENOMEM;
@@ -1767,8 +1849,9 @@ static int bcmgenet_init_dma(struct bcmg
 
 	/* initialize special ring 16 */
 	bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_DEFAULT_BD_CNT,
-			priv->hw_params->tx_queues * priv->hw_params->bds_cnt,
-			TOTAL_DESC);
+			      priv->hw_params->tx_queues *
+			      priv->hw_params->bds_cnt,
+			      TOTAL_DESC);
 
 	return 0;
 }
@@ -1789,11 +1872,11 @@ static int bcmgenet_poll(struct napi_str
 	priv->rx_c_index += work_done;
 	priv->rx_c_index &= DMA_C_INDEX_MASK;
 	bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
-				priv->rx_c_index, RDMA_CONS_INDEX);
+				  priv->rx_c_index, RDMA_CONS_INDEX);
 	if (work_done < budget) {
 		napi_complete(napi);
-		bcmgenet_intrl2_0_writel(priv,
-			UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_CLEAR);
+		bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
+					 INTRL2_CPU_MASK_CLEAR);
 	}
 
 	return work_done;
@@ -1807,11 +1890,18 @@ static void bcmgenet_irq_task(struct wor
 
 	netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
 
+	if (priv->irq0_stat & UMAC_IRQ_MPD_R) {
+		priv->irq0_stat &= ~UMAC_IRQ_MPD_R;
+		netif_dbg(priv, wol, priv->dev,
+			  "magic packet detected, waking up\n");
+		bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+	}
+
 	/* Link UP/DOWN event */
 	if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
-		(priv->irq0_stat & (UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN))) {
+	    (priv->irq0_stat & (UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN))) {
 		phy_mac_interrupt(priv->phydev,
-			priv->irq0_stat & UMAC_IRQ_LINK_UP);
+				  priv->irq0_stat & UMAC_IRQ_LINK_UP);
 		priv->irq0_stat &= ~(UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN);
 	}
 }
@@ -1826,11 +1916,11 @@ static irqreturn_t bcmgenet_isr1(int irq
 	priv->irq1_stat =
 		bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
 		~priv->int1_mask;
-	/* clear inerrupts*/
+	/* clear interrupts */
 	bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
 
 	netif_dbg(priv, intr, priv->dev,
-		"%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
+		  "%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
 	/* Check the MBDONE interrupts.
 	 * packet is done, reclaim descriptors
 	 */
@@ -1839,7 +1929,7 @@ static irqreturn_t bcmgenet_isr1(int irq
 		for (index = 0; index < 16; index++) {
 			if (priv->irq1_stat & (1 << index))
 				bcmgenet_tx_reclaim(priv->dev,
-						&priv->tx_rings[index]);
+						    &priv->tx_rings[index]);
 		}
 	}
 	return IRQ_HANDLED;
@@ -1854,11 +1944,11 @@ static irqreturn_t bcmgenet_isr0(int irq
 	priv->irq0_stat =
 		bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
 		~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
-	/* clear inerrupts*/
+	/* clear interrupts */
 	bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
 
 	netif_dbg(priv, intr, priv->dev,
-		"IRQ=0x%x\n", priv->irq0_stat);
+		  "IRQ=0x%x\n", priv->irq0_stat);
 
 	if (priv->irq0_stat & (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE)) {
 		/* We use NAPI(software interrupt throttling, if
@@ -1866,8 +1956,8 @@ static irqreturn_t bcmgenet_isr0(int irq
 		 * Disable interrupt, will be enabled in the poll method.
 		 */
 		if (likely(napi_schedule_prep(&priv->napi))) {
-			bcmgenet_intrl2_0_writel(priv,
-				UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_SET);
+			bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
+						 INTRL2_CPU_MASK_SET);
 			__napi_schedule(&priv->napi);
 		}
 	}
@@ -1888,7 +1978,7 @@ static irqreturn_t bcmgenet_isr0(int irq
 	}
 
 	if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
-		priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
+	    priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
 		priv->irq0_stat &= ~(UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
 		wake_up(&priv->wq);
 	}
@@ -1896,6 +1986,15 @@ static irqreturn_t bcmgenet_isr0(int irq
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t bcmgenet_wol_isr(int irq, void *dev_id)
+{
+	struct bcmgenet_priv *priv = dev_id;
+
+	pm_wakeup_event(&priv->pdev->dev, 0);
+
+	return IRQ_HANDLED;
+}
+
 static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
 {
 	u32 reg;
@@ -1911,7 +2010,7 @@ static void bcmgenet_umac_reset(struct b
 }
 
 static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
-				  unsigned char *addr)
+				 unsigned char *addr)
 {
 	bcmgenet_umac_writel(priv, (addr[0] << 24) | (addr[1] << 16) |
 			(addr[2] << 8) | addr[3], UMAC_MAC0);
@@ -1920,14 +2019,9 @@ static void bcmgenet_set_hw_addr(struct
 
 static int bcmgenet_wol_resume(struct bcmgenet_priv *priv)
 {
-	int ret;
-
 	/* From WOL-enabled suspend, switch to regular clock */
-	clk_disable(priv->clk_wol);
-	/* init umac registers to synchronize s/w with h/w */
-	ret = init_umac(priv);
-	if (ret)
-		return ret;
+	if (priv->wolopts)
+		clk_disable_unprepare(priv->clk_wol);
 
 	phy_init_hw(priv->phydev);
 	/* Speed settings must be restored */
@@ -1972,6 +2066,23 @@ static void bcmgenet_enable_dma(struct b
 	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
 }
 
+static void bcmgenet_netif_start(struct net_device *dev)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+
+	/* Start the network engine */
+	napi_enable(&priv->napi);
+
+	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
+
+	if (phy_is_internal(priv->phydev))
+		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
+
+	netif_tx_start_all_queues(dev);
+
+	phy_start(priv->phydev);
+}
+
 static int bcmgenet_open(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -1993,18 +2104,14 @@ static int bcmgenet_open(struct net_devi
 		goto err_clk_disable;
 
 	/* disable ethernet MAC while updating its registers */
+	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
+
+	/* Make sure we reflect the value of CRC_CMD_FWD */
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-	reg &= ~(CMD_TX_EN | CMD_RX_EN);
-	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
-	if (priv->wol_enabled) {
-		ret = bcmgenet_wol_resume(priv);
-		if (ret)
-			return ret;
-	}
-
 	if (phy_is_internal(priv->phydev)) {
 		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
 		reg |= EXT_ENERGY_DET_MASK;
@@ -2025,37 +2132,20 @@ static int bcmgenet_open(struct net_devi
 	bcmgenet_enable_dma(priv, dma_ctrl);
 
 	ret = request_irq(priv->irq0, bcmgenet_isr0, IRQF_SHARED,
-			dev->name, priv);
+			  dev->name, priv);
 	if (ret < 0) {
 		netdev_err(dev, "can't request IRQ %d\n", priv->irq0);
 		goto err_fini_dma;
 	}
 
 	ret = request_irq(priv->irq1, bcmgenet_isr1, IRQF_SHARED,
-				dev->name, priv);
+			  dev->name, priv);
 	if (ret < 0) {
 		netdev_err(dev, "can't request IRQ %d\n", priv->irq1);
 		goto err_irq0;
 	}
 
-	/* Start the network engine */
-	napi_enable(&priv->napi);
-
-	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-	reg |= (CMD_TX_EN | CMD_RX_EN);
-	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
-	/* Make sure we reflect the value of CRC_CMD_FWD */
-	priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
-
-	device_set_wakeup_capable(&dev->dev, 1);
-
-	if (phy_is_internal(priv->phydev))
-		bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
-
-	netif_tx_start_all_queues(dev);
-
-	phy_start(priv->phydev);
+	bcmgenet_netif_start(dev);
 
 	return 0;
 
@@ -2069,86 +2159,44 @@ err_clk_disable:
 	return ret;
 }
 
-static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
+static void bcmgenet_netif_stop(struct net_device *dev)
 {
-	int ret = 0;
-	int timeout = 0;
-	u32 reg;
-
-	/* Disable TDMA to stop add more frames in TX DMA */
-	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
-	reg &= ~DMA_EN;
-	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
-
-	/* Check TDMA status register to confirm TDMA is disabled */
-	while (timeout++ < DMA_TIMEOUT_VAL) {
-		reg = bcmgenet_tdma_readl(priv, DMA_STATUS);
-		if (reg & DMA_DISABLED)
-			break;
-
-		udelay(1);
-	}
-
-	if (timeout == DMA_TIMEOUT_VAL) {
-		netdev_warn(priv->dev,
-			"Timed out while disabling TX DMA\n");
-		ret = -ETIMEDOUT;
-	}
-
-	/* Wait 10ms for packet drain in both tx and rx dma */
-	usleep_range(10000, 20000);
-
-	/* Disable RDMA */
-	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
-	reg &= ~DMA_EN;
-	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+	struct bcmgenet_priv *priv = netdev_priv(dev);
 
-	timeout = 0;
-	/* Check RDMA status register to confirm RDMA is disabled */
-	while (timeout++ < DMA_TIMEOUT_VAL) {
-		reg = bcmgenet_rdma_readl(priv, DMA_STATUS);
-		if (reg & DMA_DISABLED)
-			break;
+	netif_tx_stop_all_queues(dev);
+	napi_disable(&priv->napi);
+	phy_stop(priv->phydev);
 
-		udelay(1);
-	}
+	bcmgenet_intr_disable(priv);
 
-	if (timeout == DMA_TIMEOUT_VAL) {
-		netdev_warn(priv->dev,
-			"Timed out while disabling RX DMA\n");
-			ret = -ETIMEDOUT;
-	}
+	/* Wait for pending work items to complete. Since interrupts are
+	 * disabled no new work will be scheduled.
+	 */
+	cancel_work_sync(&priv->bcmgenet_irq_work);
 
-	return ret;
+	priv->old_pause = -1;
+	priv->old_link = -1;
+	priv->old_duplex = -1;
 }
 
 static int bcmgenet_close(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	int ret;
-	u32 reg;
 
 	netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
 
-	phy_stop(priv->phydev);
+	bcmgenet_netif_stop(dev);
 
 	/* Disable MAC receive */
-	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-	reg &= ~CMD_RX_EN;
-	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
-	netif_tx_stop_all_queues(dev);
+	umac_enable_set(priv, CMD_RX_EN, false);
 
 	ret = bcmgenet_dma_teardown(priv);
 	if (ret)
 		return ret;
 
 	/* Disable MAC transmit. TX DMA disabled have to done before this */
-	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-	reg &= ~CMD_TX_EN;
-	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
-	napi_disable(&priv->napi);
+	umac_enable_set(priv, CMD_TX_EN, false);
 
 	/* tx reclaim */
 	bcmgenet_tx_reclaim_all(dev);
@@ -2157,18 +2205,9 @@ static int bcmgenet_close(struct net_dev
 	free_irq(priv->irq0, priv);
 	free_irq(priv->irq1, priv);
 
-	/* Wait for pending work items to complete - we are stopping
-	 * the clock now. Since interrupts are disabled, no new work
-	 * will be scheduled.
-	 */
-	cancel_work_sync(&priv->bcmgenet_irq_work);
-
 	if (phy_is_internal(priv->phydev))
 		bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
 
-	if (priv->wol_enabled)
-		clk_enable(priv->clk_wol);
-
 	if (!IS_ERR(priv->clk))
 		clk_disable_unprepare(priv->clk);
 
@@ -2197,12 +2236,11 @@ static inline void bcmgenet_set_mdf_addr
 {
 	u32 reg;
 
-	bcmgenet_umac_writel(priv,
-			addr[0] << 8 | addr[1], UMAC_MDF_ADDR + (*i * 4));
-	bcmgenet_umac_writel(priv,
-			addr[2] << 24 | addr[3] << 16 |
-			addr[4] << 8 | addr[5],
-			UMAC_MDF_ADDR + ((*i + 1) * 4));
+	bcmgenet_umac_writel(priv, addr[0] << 8 | addr[1],
+			     UMAC_MDF_ADDR + (*i * 4));
+	bcmgenet_umac_writel(priv, addr[2] << 24 | addr[3] << 16 |
+			     addr[4] << 8 | addr[5],
+			     UMAC_MDF_ADDR + ((*i + 1) * 4));
 	reg = bcmgenet_umac_readl(priv, UMAC_MDF_CTRL);
 	reg |= (1 << (MAX_MC_COUNT - *mc));
 	bcmgenet_umac_writel(priv, reg, UMAC_MDF_CTRL);
@@ -2219,7 +2257,7 @@ static void bcmgenet_set_rx_mode(struct
 
 	netif_dbg(priv, hw, dev, "%s: %08X\n", __func__, dev->flags);
 
-	/* Promiscous mode */
+	/* Promiscuous mode */
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 	if (dev->flags & IFF_PROMISC) {
 		reg |= CMD_PROMISC;
@@ -2399,7 +2437,7 @@ static void bcmgenet_set_hw_params(struc
 
 	/* Print the GENET core version */
 	dev_info(&priv->pdev->dev, "GENET " GENET_VER_FMT,
-		major, (reg >> 16) & 0x0f, reg & 0xffff);
+		 major, (reg >> 16) & 0x0f, reg & 0xffff);
 
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 	if (!(params->flags & GENET_HAS_40BITS))
@@ -2455,6 +2493,7 @@ static int bcmgenet_probe(struct platfor
 	priv = netdev_priv(dev);
 	priv->irq0 = platform_get_irq(pdev, 0);
 	priv->irq1 = platform_get_irq(pdev, 1);
+	priv->wol_irq = platform_get_irq(pdev, 2);
 	if (!priv->irq0 || !priv->irq1) {
 		dev_err(&pdev->dev, "can't find IRQs\n");
 		err = -EINVAL;
@@ -2489,6 +2528,13 @@ static int bcmgenet_probe(struct platfor
 	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
 		NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
 
+	/* Request the WOL interrupt and advertise suspend if available */
+	priv->wol_irq_disabled = true;
+	err = devm_request_irq(&pdev->dev, priv->wol_irq, bcmgenet_wol_isr, 0,
+			       dev->name, priv);
+	if (!err)
+		device_set_wakeup_capable(&pdev->dev, 1);
+
 	/* Set the needed headroom to account for any possible
 	 * features enabling/disabling at runtime
 	 */
@@ -2500,6 +2546,13 @@ static int bcmgenet_probe(struct platfor
 	priv->pdev = pdev;
 	priv->version = (enum bcmgenet_version)of_id->data;
 
+	priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
+	if (IS_ERR(priv->clk))
+		dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
+
+	if (!IS_ERR(priv->clk))
+		clk_prepare_enable(priv->clk);
+
 	bcmgenet_set_hw_params(priv);
 
 	/* Mii wait queue */
@@ -2508,17 +2561,10 @@ static int bcmgenet_probe(struct platfor
 	priv->rx_buf_len = RX_BUF_LENGTH;
 	INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
 
-	priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
-	if (IS_ERR(priv->clk))
-		dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
-
 	priv->clk_wol = devm_clk_get(&priv->pdev->dev, "enet-wol");
 	if (IS_ERR(priv->clk_wol))
 		dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
 
-	if (!IS_ERR(priv->clk))
-		clk_prepare_enable(priv->clk);
-
 	err = reset_umac(priv);
 	if (err)
 		goto err_clk_disable;
@@ -2566,6 +2612,116 @@ static int bcmgenet_remove(struct platfo
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int bcmgenet_suspend(struct device *d)
+{
+	struct net_device *dev = dev_get_drvdata(d);
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	int ret;
+
+	if (!netif_running(dev))
+		return 0;
+
+	bcmgenet_netif_stop(dev);
+
+	phy_suspend(priv->phydev);
+
+	netif_device_detach(dev);
+
+	/* Disable MAC receive */
+	umac_enable_set(priv, CMD_RX_EN, false);
+
+	ret = bcmgenet_dma_teardown(priv);
+	if (ret)
+		return ret;
+
+	/* Disable MAC transmit. TX DMA disabled have to done before this */
+	umac_enable_set(priv, CMD_TX_EN, false);
+
+	/* tx reclaim */
+	bcmgenet_tx_reclaim_all(dev);
+	bcmgenet_fini_dma(priv);
+
+	/* Prepare the device for Wake-on-LAN and switch to the slow clock */
+	if (device_may_wakeup(d) && priv->wolopts) {
+		bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
+		clk_prepare_enable(priv->clk_wol);
+	}
+
+	/* Turn off the clocks */
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static int bcmgenet_resume(struct device *d)
+{
+	struct net_device *dev = dev_get_drvdata(d);
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	unsigned long dma_ctrl;
+	int ret;
+	u32 reg;
+
+	if (!netif_running(dev))
+		return 0;
+
+	/* Turn on the clock */
+	ret = clk_prepare_enable(priv->clk);
+	if (ret)
+		return ret;
+
+	bcmgenet_umac_reset(priv);
+
+	ret = init_umac(priv);
+	if (ret)
+		goto out_clk_disable;
+
+	ret = bcmgenet_wol_resume(priv);
+	if (ret)
+		goto out_clk_disable;
+
+	/* disable ethernet MAC while updating its registers */
+	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
+
+	bcmgenet_set_hw_addr(priv, dev->dev_addr);
+
+	if (phy_is_internal(priv->phydev)) {
+		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+		reg |= EXT_ENERGY_DET_MASK;
+		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+	}
+
+	if (priv->wolopts)
+		bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+
+	/* Disable RX/TX DMA and flush TX queues */
+	dma_ctrl = bcmgenet_dma_disable(priv);
+
+	/* Reinitialize TDMA and RDMA and SW housekeeping */
+	ret = bcmgenet_init_dma(priv);
+	if (ret) {
+		netdev_err(dev, "failed to initialize DMA\n");
+		goto out_clk_disable;
+	}
+
+	/* Always enable ring 16 - descriptor ring */
+	bcmgenet_enable_dma(priv, dma_ctrl);
+
+	netif_device_attach(dev);
+
+	phy_resume(priv->phydev);
+
+	bcmgenet_netif_start(dev);
+
+	return 0;
+
+out_clk_disable:
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(bcmgenet_pm_ops, bcmgenet_suspend, bcmgenet_resume);
 
 static struct platform_driver bcmgenet_driver = {
 	.probe	= bcmgenet_probe,
@@ -2574,6 +2730,7 @@ static struct platform_driver bcmgenet_d
 		.name	= "bcmgenet",
 		.owner	= THIS_MODULE,
 		.of_match_table = bcmgenet_match,
+		.pm	= &bcmgenet_pm_ops,
 	},
 };
 module_platform_driver(bcmgenet_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.h	2014-09-28 17:29:07.000000000 -0400
@@ -4,18 +4,8 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
-*/
+ */
+
 #ifndef __BCMGENET_H__
 #define __BCMGENET_H__
 
@@ -456,6 +446,7 @@ struct enet_cb {
 enum bcmgenet_power_mode {
 	GENET_POWER_CABLE_SENSE = 0,
 	GENET_POWER_PASSIVE,
+	GENET_POWER_WOL_MAGIC,
 };
 
 struct bcmgenet_priv;
@@ -513,9 +504,9 @@ struct bcmgenet_tx_ring {
 	unsigned int	cb_ptr;		/* Tx ring initial CB ptr */
 	unsigned int	end_ptr;	/* Tx ring end CB ptr */
 	void (*int_enable)(struct bcmgenet_priv *priv,
-				struct bcmgenet_tx_ring *);
+			   struct bcmgenet_tx_ring *);
 	void (*int_disable)(struct bcmgenet_priv *priv,
-				struct bcmgenet_tx_ring *);
+			    struct bcmgenet_tx_ring *);
 };
 
 /* device context */
@@ -569,6 +560,8 @@ struct bcmgenet_priv {
 	int irq1;
 	unsigned int irq0_stat;
 	unsigned int irq1_stat;
+	int wol_irq;
+	bool wol_irq_disabled;
 
 	/* HW descriptors/checksum variables */
 	bool desc_64b_en;
@@ -583,7 +576,6 @@ struct bcmgenet_priv {
 	struct platform_device *pdev;
 
 	/* WOL */
-	unsigned long wol_enabled;
 	struct clk *clk_wol;
 	u32 wolopts;
 
@@ -625,4 +617,12 @@ int bcmgenet_mii_config(struct net_devic
 void bcmgenet_mii_exit(struct net_device *dev);
 void bcmgenet_mii_reset(struct net_device *dev);
 
+/* Wake-on-LAN routines */
+void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
+int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
+int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+				enum bcmgenet_power_mode mode);
+void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
+			       enum bcmgenet_power_mode mode);
+
 #endif /* __BCMGENET_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
+ *
+ * Copyright (c) 2014 Broadcom 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.
+ */
+
+#define pr_fmt(fmt)				"bcmgenet_wol: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <net/arp.h>
+
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/phy.h>
+
+#include "bcmgenet.h"
+
+/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
+ * Detection is supported through ethtool
+ */
+void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	u32 reg;
+
+	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+	wol->wolopts = priv->wolopts;
+	memset(wol->sopass, 0, sizeof(wol->sopass));
+
+	if (wol->wolopts & WAKE_MAGICSECURE) {
+		reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_MS);
+		put_unaligned_be16(reg, &wol->sopass[0]);
+		reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_LS);
+		put_unaligned_be32(reg, &wol->sopass[2]);
+	}
+}
+
+/* ethtool function - set WOL (Wake on LAN) settings.
+ * Only for magic packet detection mode.
+ */
+int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
+	u32 reg;
+
+	if (!device_can_wakeup(kdev))
+		return -ENOTSUPP;
+
+	if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE))
+		return -EINVAL;
+
+	if (wol->wolopts & WAKE_MAGICSECURE) {
+		bcmgenet_umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
+				     UMAC_MPD_PW_MS);
+		bcmgenet_umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
+				     UMAC_MPD_PW_LS);
+		reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+		reg |= MPD_PW_EN;
+		bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+	}
+
+	/* Flag the device and relevant IRQ as wakeup capable */
+	if (wol->wolopts) {
+		device_set_wakeup_enable(kdev, 1);
+		enable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = false;
+	} else {
+		device_set_wakeup_enable(kdev, 0);
+		/* Avoid unbalanced disable_irq_wake calls */
+		if (!priv->wol_irq_disabled)
+			disable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = true;
+	}
+
+	priv->wolopts = wol->wolopts;
+
+	return 0;
+}
+
+static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
+{
+	struct net_device *dev = priv->dev;
+	int retries = 0;
+
+	while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
+		& RBUF_STATUS_WOL)) {
+		retries++;
+		if (retries > 5) {
+			netdev_crit(dev, "polling wol mode timeout\n");
+			return -ETIMEDOUT;
+		}
+		mdelay(1);
+	}
+
+	return retries;
+}
+
+int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+				enum bcmgenet_power_mode mode)
+{
+	struct net_device *dev = priv->dev;
+	u32 cpu_mask_clear;
+	int retries = 0;
+	u32 reg;
+
+	if (mode != GENET_POWER_WOL_MAGIC) {
+		netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
+		return -EINVAL;
+	}
+
+	/* disable RX */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg &= ~CMD_RX_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	mdelay(10);
+
+	reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+	reg |= MPD_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+	/* Do not leave UniMAC in MPD mode only */
+	retries = bcmgenet_poll_wol_status(priv);
+	if (retries < 0) {
+		reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+		reg &= ~MPD_EN;
+		bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+		return retries;
+	}
+
+	netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
+		  retries);
+
+	/* Enable CRC forward */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	priv->crc_fwd_en = 1;
+	reg |= CMD_CRC_FWD;
+
+	/* Receiver must be enabled for WOL MP detection */
+	reg |= CMD_RX_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+	if (priv->hw_params->flags & GENET_HAS_EXT) {
+		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+		reg &= ~EXT_ENERGY_DET_MASK;
+		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+	}
+
+	/* Enable the MPD interrupt */
+	cpu_mask_clear = UMAC_IRQ_MPD_R;
+
+	bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR);
+
+	return 0;
+}
+
+void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
+			       enum bcmgenet_power_mode mode)
+{
+	u32 cpu_mask_set;
+	u32 reg;
+
+	if (mode != GENET_POWER_WOL_MAGIC) {
+		netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
+		return;
+	}
+
+	reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+	reg &= ~MPD_EN;
+	bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+	/* Disable CRC Forward */
+	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	reg &= ~CMD_CRC_FWD;
+	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	priv->crc_fwd_en = 0;
+
+	/* Stop monitoring magic packet IRQ */
+	cpu_mask_set = UMAC_IRQ_MPD_R;
+
+	/* Stop monitoring magic packet IRQ */
+	bcmgenet_intrl2_0_writel(priv, cpu_mask_set, INTRL2_CPU_MASK_SET);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmmii.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmmii.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/bcmmii.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/bcmmii.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,15 +6,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
 
@@ -44,15 +35,15 @@ static int bcmgenet_mii_read(struct mii_
 	u32 reg;
 
 	bcmgenet_umac_writel(priv, (MDIO_RD | (phy_id << MDIO_PMD_SHIFT) |
-			(location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
+			     (location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
 	/* Start MDIO transaction*/
 	reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
 	reg |= MDIO_START_BUSY;
 	bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
 	wait_event_timeout(priv->wq,
-			!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
-				& MDIO_START_BUSY),
-			HZ / 100);
+			   !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
+			   & MDIO_START_BUSY),
+			   HZ / 100);
 	ret = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
 
 	if (ret & MDIO_READ_FAIL)
@@ -63,22 +54,22 @@ static int bcmgenet_mii_read(struct mii_
 
 /* write a value to the MII */
 static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
-			int location, u16 val)
+			      int location, u16 val)
 {
 	struct net_device *dev = bus->priv;
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	u32 reg;
 
 	bcmgenet_umac_writel(priv, (MDIO_WR | (phy_id << MDIO_PMD_SHIFT) |
-			(location << MDIO_REG_SHIFT) | (0xffff & val)),
-			UMAC_MDIO_CMD);
+			     (location << MDIO_REG_SHIFT) | (0xffff & val)),
+			     UMAC_MDIO_CMD);
 	reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
 	reg |= MDIO_START_BUSY;
 	bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
 	wait_event_timeout(priv->wq,
-			!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
-				MDIO_START_BUSY),
-			HZ / 100);
+			   !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
+			   MDIO_START_BUSY),
+			   HZ / 100);
 
 	return 0;
 }
@@ -136,17 +127,22 @@ static void bcmgenet_mii_setup(struct ne
 		/* pause capability */
 		if (!phydev->pause)
 			cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
+	}
 
+	if (!status_changed)
+		return;
+
+	if (phydev->link) {
 		reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 		reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
 			       CMD_HD_EN |
 			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
 		reg |= cmd_bits;
 		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
 	}
 
-	if (status_changed)
-		phy_print_status(phydev);
+	phy_print_status(phydev);
 }
 
 void bcmgenet_mii_reset(struct net_device *dev)
@@ -247,7 +243,7 @@ int bcmgenet_mii_config(struct net_devic
 		phy_name = "external MII";
 		phydev->supported &= PHY_BASIC_FEATURES;
 		bcmgenet_sys_writel(priv,
-				PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
+				    PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
 		break;
 
 	case PHY_INTERFACE_MODE_REVMII:
@@ -283,7 +279,7 @@ int bcmgenet_mii_config(struct net_devic
 		reg |= RGMII_MODE_EN | id_mode_dis;
 		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
 		bcmgenet_sys_writel(priv,
-				PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
+				    PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
 		break;
 	default:
 		dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
@@ -311,12 +307,12 @@ static int bcmgenet_mii_probe(struct net
 	/* In the case of a fixed PHY, the DT node associated
 	 * to the PHY is the Ethernet MAC DT node.
 	 */
-	if (of_phy_is_fixed_link(dn)) {
+	if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
 		ret = of_phy_register_fixed_link(dn);
 		if (ret)
 			return ret;
 
-		priv->phy_dn = dn;
+		priv->phy_dn = of_node_get(dn);
 	}
 
 	phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0,
@@ -362,7 +358,7 @@ static int bcmgenet_mii_probe(struct net
 		priv->mii_bus->irq[phydev->addr] = PHY_POLL;
 
 	pr_info("attached PHY at address %d [%s]\n",
-			phydev->addr, phydev->drv->name);
+		phydev->addr, phydev->drv->name);
 
 	return 0;
 }
@@ -387,9 +383,9 @@ static int bcmgenet_mii_alloc(struct bcm
 	bus->read = bcmgenet_mii_read;
 	bus->write = bcmgenet_mii_write;
 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
-			priv->pdev->name, priv->pdev->id);
+		 priv->pdev->name, priv->pdev->id);
 
-	bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
 	if (!bus->irq) {
 		mdiobus_free(priv->mii_bus);
 		return -ENOMEM;
@@ -452,6 +448,7 @@ int bcmgenet_mii_init(struct net_device
 	return 0;
 
 out:
+	of_node_put(priv->phy_dn);
 	mdiobus_unregister(priv->mii_bus);
 out_free:
 	kfree(priv->mii_bus->irq);
@@ -463,6 +460,7 @@ void bcmgenet_mii_exit(struct net_device
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 
+	of_node_put(priv->phy_dn);
 	mdiobus_unregister(priv->mii_bus);
 	kfree(priv->mii_bus->irq);
 	mdiobus_free(priv->mii_bus);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/genet/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/genet/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,2 +1,2 @@
 obj-$(CONFIG_BCMGENET) += genet.o
-genet-objs := bcmgenet.o bcmmii.o
+genet-objs := bcmgenet.o bcmmii.o bcmgenet_wol.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -72,23 +72,23 @@ config BCMGENET
 	  Broadcom BCM7xxx Set Top Box family chipset.
 
 config BNX2
-	tristate "Broadcom NetXtremeII support"
+	tristate "QLogic NetXtremeII support"
 	depends on PCI
 	select CRC32
 	select FW_LOADER
 	---help---
-	  This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
+	  This driver supports QLogic NetXtremeII gigabit Ethernet cards.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called bnx2.  This is recommended.
 
 config CNIC
-	tristate "Broadcom CNIC support"
-	depends on PCI
+	tristate "QLogic CNIC support"
+	depends on PCI && (IPV6 || IPV6=n)
 	select BNX2
 	select UIO
 	---help---
-	  This driver supports offload features of Broadcom NetXtremeII
+	  This driver supports offload features of QLogic NetXtremeII
 	  gigabit Ethernet cards.
 
 	  To compile this driver as a module, choose M here: the module
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/tg3.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/tg3.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/tg3.c	2014-08-07 04:53:01.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/tg3.c	2014-09-28 21:34:39.000000000 -0400
@@ -228,7 +228,7 @@ MODULE_PARM_DESC(tg3_debug, "Tigon3 bitm
 #define TG3_DRV_DATA_FLAG_10_100_ONLY	0x0001
 #define TG3_DRV_DATA_FLAG_5705_10_100	0x0002
 
-static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
+static const struct pci_device_id tg3_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
@@ -7821,17 +7821,18 @@ static int tigon3_dma_hwbug_workaround(s
 
 static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
 
-/* Use GSO to workaround a rare TSO bug that may be triggered when the
- * TSO header is greater than 80 bytes.
+/* Use GSO to workaround all TSO packets that meet HW bug conditions
+ * indicated in tg3_tx_frag_set()
  */
-static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
+static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
+		       struct netdev_queue *txq, struct sk_buff *skb)
 {
 	struct sk_buff *segs, *nskb;
 	u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
 
 	/* Estimate the number of fragments in the worst case */
-	if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) {
-		netif_stop_queue(tp->dev);
+	if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
+		netif_tx_stop_queue(txq);
 
 		/* netif_tx_stop_queue() must be done before checking
 		 * checking tx index in tg3_tx_avail() below, because in
@@ -7839,13 +7840,14 @@ static int tg3_tso_bug(struct tg3 *tp, s
 		 * netif_tx_queue_stopped().
 		 */
 		smp_mb();
-		if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)
+		if (tg3_tx_avail(tnapi) <= frag_cnt_est)
 			return NETDEV_TX_BUSY;
 
-		netif_wake_queue(tp->dev);
+		netif_tx_wake_queue(txq);
 	}
 
-	segs = skb_gso_segment(skb, tp->dev->features & ~(NETIF_F_TSO | NETIF_F_TSO6));
+	segs = skb_gso_segment(skb, tp->dev->features &
+				    ~(NETIF_F_TSO | NETIF_F_TSO6));
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
 
@@ -7903,8 +7905,6 @@ static netdev_tx_t tg3_start_xmit(struct
 
 	entry = tnapi->tx_prod;
 	base_flags = 0;
-	if (skb->ip_summed == CHECKSUM_PARTIAL)
-		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss) {
@@ -7918,10 +7918,17 @@ static netdev_tx_t tg3_start_xmit(struct
 
 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
 
+		/* HW/FW can not correctly segment packets that have been
+		 * vlan encapsulated.
+		 */
+		if (skb->protocol == htons(ETH_P_8021Q) ||
+		    skb->protocol == htons(ETH_P_8021AD))
+			return tg3_tso_bug(tp, tnapi, txq, skb);
+
 		if (!skb_is_gso_v6(skb)) {
 			if (unlikely((ETH_HLEN + hdr_len) > 80) &&
 			    tg3_flag(tp, TSO_BUG))
-				return tg3_tso_bug(tp, skb);
+				return tg3_tso_bug(tp, tnapi, txq, skb);
 
 			ip_csum = iph->check;
 			ip_tot_len = iph->tot_len;
@@ -7968,6 +7975,17 @@ static netdev_tx_t tg3_start_xmit(struct
 				base_flags |= tsflags << 12;
 			}
 		}
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		/* HW/FW can not correctly checksum packets that have been
+		 * vlan encapsulated.
+		 */
+		if (skb->protocol == htons(ETH_P_8021Q) ||
+		    skb->protocol == htons(ETH_P_8021AD)) {
+			if (skb_checksum_help(skb))
+				goto drop;
+		} else  {
+			base_flags |= TXD_FLAG_TCPUDP_CSUM;
+		}
 	}
 
 	if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
@@ -8052,7 +8070,7 @@ static netdev_tx_t tg3_start_xmit(struct
 				iph->tot_len = ip_tot_len;
 			}
 			tcph->check = tcp_csum;
-			return tg3_tso_bug(tp, skb);
+			return tg3_tso_bug(tp, tnapi, txq, skb);
 		}
 
 		/* If the workaround fails due to memory/mapping
@@ -11606,6 +11624,12 @@ static int tg3_open(struct net_device *d
 	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
+	if (tp->pcierr_recovery) {
+		netdev_err(dev, "Failed to open device. PCI error recovery "
+			   "in progress\n");
+		return -EAGAIN;
+	}
+
 	if (tp->fw_needed) {
 		err = tg3_reject_firmware(tp);
 		if (tg3_asic_rev(tp) == ASIC_REV_57766) {
@@ -11663,6 +11687,12 @@ static int tg3_close(struct net_device *
 {
 	struct tg3 *tp = netdev_priv(dev);
 
+	if (tp->pcierr_recovery) {
+		netdev_err(dev, "Failed to close device. PCI error recovery "
+			   "in progress\n");
+		return -EAGAIN;
+	}
+
 	tg3_ptp_fini(tp);
 
 	tg3_stop(tp);
@@ -14082,8 +14112,9 @@ static struct rtnl_link_stats64 *tg3_get
 
 	spin_lock_bh(&tp->lock);
 	if (!tp->hw_stats) {
+		*stats = tp->net_stats_prev;
 		spin_unlock_bh(&tp->lock);
-		return &tp->net_stats_prev;
+		return stats;
 	}
 
 	tg3_get_nstats(tp, stats);
@@ -15915,7 +15946,7 @@ static inline u32 tg3_rx_ret_ring_size(s
 		return TG3_RX_RET_MAX_SIZE_5705;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
+static const struct pci_device_id tg3_write_reorder_chipsets[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) },
@@ -17174,7 +17205,7 @@ static int tg3_do_test_dma(struct tg3 *t
 
 #define TEST_BUFFER_SIZE	0x2000
 
-static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
+static const struct pci_device_id tg3_dma_wait_state_chipsets[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
 	{ },
 };
@@ -17549,6 +17580,7 @@ static int tg3_init_one(struct pci_dev *
 	tp->rx_mode = TG3_DEF_RX_MODE;
 	tp->tx_mode = TG3_DEF_TX_MODE;
 	tp->irq_sync = 1;
+	tp->pcierr_recovery = false;
 
 	if (tg3_debug > 0)
 		tp->msg_enable = tg3_debug;
@@ -18059,6 +18091,8 @@ static pci_ers_result_t tg3_io_error_det
 
 	rtnl_lock();
 
+	tp->pcierr_recovery = true;
+
 	/* We probably don't have netdev yet */
 	if (!netdev || !netif_running(netdev))
 		goto done;
@@ -18183,6 +18217,7 @@ static void tg3_io_resume(struct pci_dev
 	tg3_phy_start(tp);
 
 done:
+	tp->pcierr_recovery = false;
 	rtnl_unlock();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/tg3.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/tg3.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/broadcom/tg3.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/broadcom/tg3.h	2014-09-28 17:29:07.000000000 -0400
@@ -3407,6 +3407,7 @@ struct tg3 {
 
 	struct device			*hwmon_dev;
 	bool				link_up;
+	bool				pcierr_recovery;
 };
 
 /* Accessor macros for chip and asic attributes
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/bnad.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/bnad.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/bnad.c	2014-08-07 04:51:29.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/bnad.c	2014-09-28 21:32:53.000000000 -0400
@@ -600,9 +600,9 @@ bnad_cq_process(struct bnad *bnad, struc
 	prefetch(bnad->netdev);
 
 	cq = ccb->sw_q;
-	cmpl = &cq[ccb->producer_index];
 
 	while (packets < budget) {
+		cmpl = &cq[ccb->producer_index];
 		if (!cmpl->valid)
 			break;
 		/* The 'valid' field is set by the adapter, only after writing
@@ -2506,7 +2506,7 @@ bnad_tso_prepare(struct bnad *bnad, stru
 	 * For TSO, the TCP checksum field is seeded with pseudo-header sum
 	 * excluding the length field.
 	 */
-	if (skb->protocol == htons(ETH_P_IP)) {
+	if (vlan_get_protocol(skb) == htons(ETH_P_IP)) {
 		struct iphdr *iph = ip_hdr(skb);
 
 		/* Do we really need these? */
@@ -2870,12 +2870,13 @@ bnad_txq_wi_prepare(struct bnad *bnad, s
 		}
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			__be16 net_proto = vlan_get_protocol(skb);
 			u8 proto = 0;
 
-			if (skb->protocol == htons(ETH_P_IP))
+			if (net_proto == htons(ETH_P_IP))
 				proto = ip_hdr(skb)->protocol;
 #ifdef NETIF_F_IPV6_CSUM
-			else if (skb->protocol == htons(ETH_P_IPV6)) {
+			else if (net_proto == htons(ETH_P_IPV6)) {
 				/* nexthdr may not be TCP immediately. */
 				proto = ipv6_hdr(skb)->nexthdr;
 			}
@@ -3836,7 +3837,7 @@ bnad_pci_remove(struct pci_dev *pdev)
 	free_netdev(netdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
+static const struct pci_device_id bnad_pci_id_table[] = {
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
 			PCI_DEVICE_ID_BROCADE_CT),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c	2014-08-07 04:51:31.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c	2014-09-28 21:32:55.000000000 -0400
@@ -997,10 +997,8 @@ bnad_get_eeprom(struct net_device *netde
 	unsigned long flags = 0;
 	int ret = 0;
 
-	/* Check if the flash read request is valid */
-	if (eeprom->magic != (bnad->pcidev->vendor |
-			     (bnad->pcidev->device << 16)))
-		return -EFAULT;
+	/* Fill the magic value */
+	eeprom->magic = bnad->pcidev->vendor | (bnad->pcidev->device << 16);
 
 	/* Query the flash partition based on the offset */
 	flash_part = bnad_get_flash_partition_by_offset(bnad,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/cna_fwimg.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/cna_fwimg.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/brocade/bna/cna_fwimg.c	2014-08-07 04:51:31.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/brocade/bna/cna_fwimg.c	2014-09-28 21:32:55.000000000 -0400
@@ -68,10 +68,8 @@ bfa_cb_image_get_chunk(enum bfi_asic_gen
 	switch (asic_gen) {
 	case BFI_ASIC_GEN_CT:
 		return (bfi_image_ct_cna + off);
-		break;
 	case BFI_ASIC_GEN_CT2:
 		return (bfi_image_ct2_cna + off);
-		break;
 	default:
 		return NULL;
 	}
@@ -83,10 +81,8 @@ bfa_cb_image_get_size(enum bfi_asic_gen
 	switch (asic_gen) {
 	case BFI_ASIC_GEN_CT:
 		return bfi_image_ct_cna_size;
-		break;
 	case BFI_ASIC_GEN_CT2:
 		return bfi_image_ct2_cna_size;
-		break;
 	default:
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cadence/macb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cadence/macb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cadence/macb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cadence/macb.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,6 +52,9 @@
 					| 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))
+
 /*
  * Graceful stop timeouts in us. We should allow up to
  * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
@@ -264,7 +267,8 @@ static void macb_handle_link_change(stru
 				reg |= MACB_BIT(FD);
 			if (phydev->speed == SPEED_100)
 				reg |= MACB_BIT(SPD);
-			if (phydev->speed == SPEED_1000)
+			if (phydev->speed == SPEED_1000 &&
+			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
 				reg |= GEM_BIT(GBE);
 
 			macb_or_gem_writel(bp, NCFGR, reg);
@@ -337,7 +341,7 @@ static int macb_mii_probe(struct net_dev
 	}
 
 	/* mask with MAC supported features */
-	if (macb_is_gem(bp))
+	if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
 		phydev->supported &= PHY_GBIT_FEATURES;
 	else
 		phydev->supported &= PHY_BASIC_FEATURES;
@@ -467,6 +471,24 @@ static int macb_halt_tx(struct macb *bp)
 	return -ETIMEDOUT;
 }
 
+static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
+{
+	if (tx_skb->mapping) {
+		if (tx_skb->mapped_as_page)
+			dma_unmap_page(&bp->pdev->dev, tx_skb->mapping,
+				       tx_skb->size, DMA_TO_DEVICE);
+		else
+			dma_unmap_single(&bp->pdev->dev, tx_skb->mapping,
+					 tx_skb->size, DMA_TO_DEVICE);
+		tx_skb->mapping = 0;
+	}
+
+	if (tx_skb->skb) {
+		dev_kfree_skb_any(tx_skb->skb);
+		tx_skb->skb = NULL;
+	}
+}
+
 static void macb_tx_error_task(struct work_struct *work)
 {
 	struct macb	*bp = container_of(work, struct macb, tx_error_task);
@@ -504,10 +526,23 @@ static void macb_tx_error_task(struct wo
 		skb = tx_skb->skb;
 
 		if (ctrl & MACB_BIT(TX_USED)) {
-			netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
-				    macb_tx_ring_wrap(tail), skb->data);
-			bp->stats.tx_packets++;
-			bp->stats.tx_bytes += skb->len;
+			/* skb is set for the last buffer of the frame */
+			while (!skb) {
+				macb_tx_unmap(bp, tx_skb);
+				tail++;
+				tx_skb = macb_tx_skb(bp, tail);
+				skb = tx_skb->skb;
+			}
+
+			/* ctrl still refers to the first buffer descriptor
+			 * since it's the only one written back by the hardware
+			 */
+			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);
+				bp->stats.tx_packets++;
+				bp->stats.tx_bytes += skb->len;
+			}
 		} else {
 			/*
 			 * "Buffers exhausted mid-frame" errors may only happen
@@ -521,10 +556,7 @@ static void macb_tx_error_task(struct wo
 			desc->ctrl = ctrl | MACB_BIT(TX_USED);
 		}
 
-		dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
-				 DMA_TO_DEVICE);
-		tx_skb->skb = NULL;
-		dev_kfree_skb(skb);
+		macb_tx_unmap(bp, tx_skb);
 	}
 
 	/* Make descriptor updates visible to hardware */
@@ -572,20 +604,35 @@ static void macb_tx_interrupt(struct mac
 
 		ctrl = desc->ctrl;
 
+		/* TX_USED bit is only set by hardware on the very first buffer
+		 * descriptor of the transmitted frame.
+		 */
 		if (!(ctrl & MACB_BIT(TX_USED)))
 			break;
 
-		tx_skb = macb_tx_skb(bp, tail);
-		skb = tx_skb->skb;
+		/* Process all buffers of the current transmitted frame */
+		for (;; tail++) {
+			tx_skb = macb_tx_skb(bp, tail);
+			skb = tx_skb->skb;
 
-		netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
-			macb_tx_ring_wrap(tail), skb->data);
-		dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
-				 DMA_TO_DEVICE);
-		bp->stats.tx_packets++;
-		bp->stats.tx_bytes += skb->len;
-		tx_skb->skb = NULL;
-		dev_kfree_skb_irq(skb);
+			/* 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);
+				bp->stats.tx_packets++;
+				bp->stats.tx_bytes += skb->len;
+			}
+
+			/* Now we can safely release resources */
+			macb_tx_unmap(bp, tx_skb);
+
+			/* skb is set only for the last buffer of the frame.
+			 * WARNING: at this point skb has been freed by
+			 * macb_tx_unmap().
+			 */
+			if (skb)
+				break;
+		}
 	}
 
 	bp->tx_tail = tail;
@@ -718,6 +765,10 @@ static int gem_rx(struct macb *bp, int b
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		skb_checksum_none_assert(skb);
+		if (bp->dev->features & NETIF_F_RXCSUM &&
+		    !(bp->dev->flags & IFF_PROMISC) &&
+		    GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		bp->stats.rx_packets++;
 		bp->stats.rx_bytes += skb->len;
@@ -1001,15 +1052,145 @@ static void macb_poll_controller(struct
 }
 #endif
 
-static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static inline unsigned int macb_count_tx_descriptors(struct macb *bp,
+						     unsigned int len)
+{
+	return (len + bp->max_tx_length - 1) / bp->max_tx_length;
+}
+
+static unsigned int macb_tx_map(struct macb *bp,
+				struct sk_buff *skb)
 {
-	struct macb *bp = netdev_priv(dev);
 	dma_addr_t mapping;
-	unsigned int len, entry;
+	unsigned int len, entry, i, tx_head = bp->tx_head;
+	struct macb_tx_skb *tx_skb = NULL;
 	struct macb_dma_desc *desc;
-	struct macb_tx_skb *tx_skb;
+	unsigned int offset, size, count = 0;
+	unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
+	unsigned int eof = 1;
 	u32 ctrl;
+
+	/* First, map non-paged data */
+	len = skb_headlen(skb);
+	offset = 0;
+	while (len) {
+		size = min(len, bp->max_tx_length);
+		entry = macb_tx_ring_wrap(tx_head);
+		tx_skb = &bp->tx_skb[entry];
+
+		mapping = dma_map_single(&bp->pdev->dev,
+					 skb->data + offset,
+					 size, DMA_TO_DEVICE);
+		if (dma_mapping_error(&bp->pdev->dev, mapping))
+			goto dma_error;
+
+		/* Save info to properly release resources */
+		tx_skb->skb = NULL;
+		tx_skb->mapping = mapping;
+		tx_skb->size = size;
+		tx_skb->mapped_as_page = false;
+
+		len -= size;
+		offset += size;
+		count++;
+		tx_head++;
+	}
+
+	/* Then, map paged data from fragments */
+	for (f = 0; f < nr_frags; f++) {
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+		len = skb_frag_size(frag);
+		offset = 0;
+		while (len) {
+			size = min(len, bp->max_tx_length);
+			entry = macb_tx_ring_wrap(tx_head);
+			tx_skb = &bp->tx_skb[entry];
+
+			mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
+						   offset, size, DMA_TO_DEVICE);
+			if (dma_mapping_error(&bp->pdev->dev, mapping))
+				goto dma_error;
+
+			/* Save info to properly release resources */
+			tx_skb->skb = NULL;
+			tx_skb->mapping = mapping;
+			tx_skb->size = size;
+			tx_skb->mapped_as_page = true;
+
+			len -= size;
+			offset += size;
+			count++;
+			tx_head++;
+		}
+	}
+
+	/* Should never happen */
+	if (unlikely(tx_skb == NULL)) {
+		netdev_err(bp->dev, "BUG! empty skb!\n");
+		return 0;
+	}
+
+	/* This is the last buffer of the frame: save socket buffer */
+	tx_skb->skb = skb;
+
+	/* Update TX ring: update buffer descriptors in reverse order
+	 * to avoid race condition
+	 */
+
+	/* Set 'TX_USED' bit in buffer descriptor at tx_head position
+	 * to set the end of TX queue
+	 */
+	i = tx_head;
+	entry = macb_tx_ring_wrap(i);
+	ctrl = MACB_BIT(TX_USED);
+	desc = &bp->tx_ring[entry];
+	desc->ctrl = ctrl;
+
+	do {
+		i--;
+		entry = macb_tx_ring_wrap(i);
+		tx_skb = &bp->tx_skb[entry];
+		desc = &bp->tx_ring[entry];
+
+		ctrl = (u32)tx_skb->size;
+		if (eof) {
+			ctrl |= MACB_BIT(TX_LAST);
+			eof = 0;
+		}
+		if (unlikely(entry == (TX_RING_SIZE - 1)))
+			ctrl |= MACB_BIT(TX_WRAP);
+
+		/* Set TX buffer descriptor */
+		desc->addr = tx_skb->mapping;
+		/* desc->addr must be visible to hardware before clearing
+		 * 'TX_USED' bit in desc->ctrl.
+		 */
+		wmb();
+		desc->ctrl = ctrl;
+	} while (i != bp->tx_head);
+
+	bp->tx_head = tx_head;
+
+	return count;
+
+dma_error:
+	netdev_err(bp->dev, "TX DMA map failed\n");
+
+	for (i = bp->tx_head; i != tx_head; i++) {
+		tx_skb = macb_tx_skb(bp, i);
+
+		macb_tx_unmap(bp, tx_skb);
+	}
+
+	return 0;
+}
+
+static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct macb *bp = netdev_priv(dev);
 	unsigned long flags;
+	unsigned int count, nr_frags, frag_size, f;
 
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
 	netdev_vdbg(bp->dev,
@@ -1020,44 +1201,34 @@ static int macb_start_xmit(struct sk_buf
 		       skb->data, 16, true);
 #endif
 
-	len = skb->len;
+	/* Count how many TX buffer descriptors are needed to send this
+	 * socket buffer: skb fragments of jumbo frames may need to be
+	 * splitted into many buffer descriptors.
+	 */
+	count = macb_count_tx_descriptors(bp, skb_headlen(skb));
+	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 += macb_count_tx_descriptors(bp, frag_size);
+	}
+
 	spin_lock_irqsave(&bp->lock, flags);
 
 	/* This is a hard error, log it. */
-	if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
+	if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < count) {
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&bp->lock, flags);
-		netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
 		netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
 			   bp->tx_head, bp->tx_tail);
 		return NETDEV_TX_BUSY;
 	}
 
-	entry = macb_tx_ring_wrap(bp->tx_head);
-	netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
-	mapping = dma_map_single(&bp->pdev->dev, skb->data,
-				 len, DMA_TO_DEVICE);
-	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
+	/* Map socket buffer for DMA transfer */
+	if (!macb_tx_map(bp, skb)) {
 		dev_kfree_skb_any(skb);
 		goto unlock;
 	}
 
-	bp->tx_head++;
-	tx_skb = &bp->tx_skb[entry];
-	tx_skb->skb = skb;
-	tx_skb->mapping = mapping;
-	netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
-		   skb->data, (unsigned long)mapping);
-
-	ctrl = MACB_BF(TX_FRMLEN, len);
-	ctrl |= MACB_BIT(TX_LAST);
-	if (entry == (TX_RING_SIZE - 1))
-		ctrl |= MACB_BIT(TX_WRAP);
-
-	desc = &bp->tx_ring[entry];
-	desc->addr = mapping;
-	desc->ctrl = ctrl;
-
 	/* Make newly initialized descriptor visible to hardware */
 	wmb();
 
@@ -1342,7 +1513,7 @@ static u32 macb_dbw(struct macb *bp)
 /*
  * Configure the receive DMA engine
  * - use the correct receive buffer size
- * - set the possibility to use INCR16 bursts
+ * - set best burst length for DMA operations
  *   (if not supported by FIFO, it will fallback to default)
  * - set both rx/tx packet buffers to full memory size
  * These are configurable parameters for GEM.
@@ -1354,24 +1525,20 @@ static void macb_configure_dma(struct ma
 	if (macb_is_gem(bp)) {
 		dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
 		dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
-		dmacfg |= GEM_BF(FBLDO, 16);
+		if (bp->dma_burst_length)
+			dmacfg = GEM_BFINS(FBLDO, bp->dma_burst_length, dmacfg);
 		dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
 		dmacfg &= ~GEM_BIT(ENDIA);
+		if (bp->dev->features & NETIF_F_HW_CSUM)
+			dmacfg |= GEM_BIT(TXCOEN);
+		else
+			dmacfg &= ~GEM_BIT(TXCOEN);
+		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
+			   dmacfg);
 		gem_writel(bp, DMACFG, dmacfg);
 	}
 }
 
-/*
- * Configure peripheral capacities according to integration options used
- */
-static void macb_configure_caps(struct macb *bp)
-{
-	if (macb_is_gem(bp)) {
-		if (GEM_BFEXT(IRQCOR, gem_readl(bp, DCFG1)) == 0)
-			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
-	}
-}
-
 static void macb_init_hw(struct macb *bp)
 {
 	u32 config;
@@ -1386,6 +1553,8 @@ static void macb_init_hw(struct macb *bp
 	config |= MACB_BIT(BIG);		/* Receive oversized frames */
 	if (bp->dev->flags & IFF_PROMISC)
 		config |= MACB_BIT(CAF);	/* Copy All Frames */
+	else if (macb_is_gem(bp) && bp->dev->features & NETIF_F_RXCSUM)
+		config |= GEM_BIT(RXCOEN);
 	if (!(bp->dev->flags & IFF_BROADCAST))
 		config |= MACB_BIT(NBC);	/* No BroadCast */
 	config |= macb_dbw(bp);
@@ -1394,7 +1563,6 @@ static void macb_init_hw(struct macb *bp
 	bp->duplex = DUPLEX_HALF;
 
 	macb_configure_dma(bp);
-	macb_configure_caps(bp);
 
 	/* Initialize TX and RX buffers */
 	macb_writel(bp, RBQP, bp->rx_ring_dma);
@@ -1500,13 +1668,22 @@ void macb_set_rx_mode(struct net_device
 
 	cfg = macb_readl(bp, NCFGR);
 
-	if (dev->flags & IFF_PROMISC)
+	if (dev->flags & IFF_PROMISC) {
 		/* Enable promiscuous mode */
 		cfg |= MACB_BIT(CAF);
-	else if (dev->flags & (~IFF_PROMISC))
-		 /* Disable promiscuous mode */
+
+		/* Disable RX checksum offload */
+		if (macb_is_gem(bp))
+			cfg &= ~GEM_BIT(RXCOEN);
+	} else {
+		/* Disable promiscuous mode */
 		cfg &= ~MACB_BIT(CAF);
 
+		/* Enable RX checksum offload only if requested */
+		if (macb_is_gem(bp) && dev->features & NETIF_F_RXCSUM)
+			cfg |= GEM_BIT(RXCOEN);
+	}
+
 	if (dev->flags & IFF_ALLMULTI) {
 		/* Enable all multicast mode */
 		macb_or_gem_writel(bp, HRB, -1);
@@ -1767,6 +1944,40 @@ int macb_ioctl(struct net_device *dev, s
 }
 EXPORT_SYMBOL_GPL(macb_ioctl);
 
+static int macb_set_features(struct net_device *netdev,
+			     netdev_features_t features)
+{
+	struct macb *bp = netdev_priv(netdev);
+	netdev_features_t changed = features ^ netdev->features;
+
+	/* TX checksum offload */
+	if ((changed & NETIF_F_HW_CSUM) && macb_is_gem(bp)) {
+		u32 dmacfg;
+
+		dmacfg = gem_readl(bp, DMACFG);
+		if (features & NETIF_F_HW_CSUM)
+			dmacfg |= GEM_BIT(TXCOEN);
+		else
+			dmacfg &= ~GEM_BIT(TXCOEN);
+		gem_writel(bp, DMACFG, dmacfg);
+	}
+
+	/* RX checksum offload */
+	if ((changed & NETIF_F_RXCSUM) && macb_is_gem(bp)) {
+		u32 netcfg;
+
+		netcfg = gem_readl(bp, NCFGR);
+		if (features & NETIF_F_RXCSUM &&
+		    !(netdev->flags & IFF_PROMISC))
+			netcfg |= GEM_BIT(RXCOEN);
+		else
+			netcfg &= ~GEM_BIT(RXCOEN);
+		gem_writel(bp, NCFGR, netcfg);
+	}
+
+	return 0;
+}
+
 static const struct net_device_ops macb_netdev_ops = {
 	.ndo_open		= macb_open,
 	.ndo_stop		= macb_close,
@@ -1780,20 +1991,77 @@ static const struct net_device_ops macb_
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= macb_poll_controller,
 #endif
+	.ndo_set_features	= macb_set_features,
 };
 
 #if defined(CONFIG_OF)
+static struct macb_config pc302gem_config = {
+	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+	.dma_burst_length = 16,
+};
+
+static struct macb_config sama5d3_config = {
+	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+	.dma_burst_length = 16,
+};
+
+static struct macb_config sama5d4_config = {
+	.caps = 0,
+	.dma_burst_length = 4,
+};
+
 static const struct of_device_id macb_dt_ids[] = {
 	{ .compatible = "cdns,at32ap7000-macb" },
 	{ .compatible = "cdns,at91sam9260-macb" },
 	{ .compatible = "cdns,macb" },
-	{ .compatible = "cdns,pc302-gem" },
-	{ .compatible = "cdns,gem" },
+	{ .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
+	{ .compatible = "cdns,gem", .data = &pc302gem_config },
+	{ .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config },
+	{ .compatible = "atmel,sama5d4-gem", .data = &sama5d4_config },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
 #endif
 
+/*
+ * Configure peripheral capacities according to device tree
+ * and integration options used
+ */
+static void macb_configure_caps(struct macb *bp)
+{
+	u32 dcfg;
+	const struct of_device_id *match;
+	const struct macb_config *config;
+
+	if (bp->pdev->dev.of_node) {
+		match = of_match_node(macb_dt_ids, bp->pdev->dev.of_node);
+		if (match && match->data) {
+			config = (const struct macb_config *)match->data;
+
+			bp->caps = config->caps;
+			/*
+			 * As we have access to the matching node, configure
+			 * DMA burst length as well
+			 */
+			bp->dma_burst_length = config->dma_burst_length;
+		}
+	}
+
+	if (MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2)
+		bp->caps |= MACB_CAPS_MACB_IS_GEM;
+
+	if (macb_is_gem(bp)) {
+		dcfg = gem_readl(bp, DCFG1);
+		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
+			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+		dcfg = gem_readl(bp, DCFG2);
+		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
+			bp->caps |= MACB_CAPS_FIFO_MODE;
+	}
+
+	netdev_dbg(bp->dev, "Cadence caps 0x%08x\n", bp->caps);
+}
+
 static int __init macb_probe(struct platform_device *pdev)
 {
 	struct macb_platform_data *pdata;
@@ -1828,9 +2096,6 @@ static int __init macb_probe(struct plat
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	/* TODO: Actually, we have some interesting features... */
-	dev->features |= 0;
-
 	bp = netdev_priv(dev);
 	bp->pdev = pdev;
 	bp->dev = dev;
@@ -1897,19 +2162,33 @@ static int __init macb_probe(struct plat
 
 	dev->base_addr = regs->start;
 
+	/* setup capacities */
+	macb_configure_caps(bp);
+
 	/* setup appropriated routines according to adapter type */
 	if (macb_is_gem(bp)) {
+		bp->max_tx_length = GEM_MAX_TX_LEN;
 		bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
 		bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
 		bp->macbgem_ops.mog_init_rings = gem_init_rings;
 		bp->macbgem_ops.mog_rx = gem_rx;
 	} else {
+		bp->max_tx_length = MACB_MAX_TX_LEN;
 		bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
 		bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
 		bp->macbgem_ops.mog_init_rings = macb_init_rings;
 		bp->macbgem_ops.mog_rx = macb_rx;
 	}
 
+	/* Set features */
+	dev->hw_features = NETIF_F_SG;
+	/* 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;
+	if (bp->caps & MACB_CAPS_SG_DISABLED)
+		dev->hw_features &= ~NETIF_F_SG;
+	dev->features = dev->hw_features;
+
 	/* Set MII management clock divider */
 	config = macb_mdc_clk_div(bp);
 	config |= macb_dbw(bp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cadence/macb.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cadence/macb.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cadence/macb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cadence/macb.h	2014-09-28 17:29:07.000000000 -0400
@@ -164,6 +164,8 @@
 #define GEM_CLK_SIZE				3
 #define GEM_DBW_OFFSET				21
 #define GEM_DBW_SIZE				2
+#define GEM_RXCOEN_OFFSET			24
+#define GEM_RXCOEN_SIZE				1
 
 /* Constants for data bus width. */
 #define GEM_DBW32				0
@@ -305,6 +307,12 @@
 #define GEM_DBWDEF_OFFSET			25
 #define GEM_DBWDEF_SIZE				3
 
+/* Bitfields in DCFG2. */
+#define GEM_RX_PKT_BUFF_OFFSET			20
+#define GEM_RX_PKT_BUFF_SIZE			1
+#define GEM_TX_PKT_BUFF_OFFSET			21
+#define GEM_TX_PKT_BUFF_SIZE			1
+
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
@@ -326,7 +334,11 @@
 #define MACB_MAN_CODE				2
 
 /* Capability mask bits */
-#define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x1
+#define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x00000001
+#define MACB_CAPS_FIFO_MODE			0x10000000
+#define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
+#define MACB_CAPS_SG_DISABLED			0x40000000
+#define MACB_CAPS_MACB_IS_GEM			0x80000000
 
 /* Bit manipulation macros */
 #define MACB_BIT(name)					\
@@ -442,6 +454,14 @@ struct macb_dma_desc {
 #define MACB_RX_BROADCAST_OFFSET		31
 #define MACB_RX_BROADCAST_SIZE			1
 
+/* RX checksum offload disabled: bit 24 clear in NCFGR */
+#define GEM_RX_TYPEID_MATCH_OFFSET		22
+#define GEM_RX_TYPEID_MATCH_SIZE		2
+
+/* RX checksum offload enabled: bit 24 set in NCFGR */
+#define GEM_RX_CSUM_OFFSET			22
+#define GEM_RX_CSUM_SIZE			2
+
 #define MACB_TX_FRMLEN_OFFSET			0
 #define MACB_TX_FRMLEN_SIZE			11
 #define MACB_TX_LAST_OFFSET			15
@@ -459,14 +479,32 @@ struct macb_dma_desc {
 #define MACB_TX_USED_OFFSET			31
 #define MACB_TX_USED_SIZE			1
 
+#define GEM_TX_FRMLEN_OFFSET			0
+#define GEM_TX_FRMLEN_SIZE			14
+
+/* Buffer descriptor constants */
+#define GEM_RX_CSUM_NONE			0
+#define GEM_RX_CSUM_IP_ONLY			1
+#define GEM_RX_CSUM_IP_TCP			2
+#define GEM_RX_CSUM_IP_UDP			3
+
+/* limit RX checksum offload to TCP and UDP packets */
+#define GEM_RX_CSUM_CHECKED_MASK		2
+
 /**
  * struct macb_tx_skb - data about an skb which is being transmitted
- * @skb: skb currently being transmitted
- * @mapping: DMA address of the skb's data buffer
+ * @skb: skb currently being transmitted, only set for the last buffer
+ *       of the frame
+ * @mapping: DMA address of the skb's fragment buffer
+ * @size: size of the DMA mapped buffer
+ * @mapped_as_page: true when buffer was mapped with skb_frag_dma_map(),
+ *                  false when buffer was mapped with dma_map_single()
  */
 struct macb_tx_skb {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
+	size_t			size;
+	bool			mapped_as_page;
 };
 
 /*
@@ -554,6 +592,11 @@ struct macb_or_gem_ops {
 	int	(*mog_rx)(struct macb *bp, int budget);
 };
 
+struct macb_config {
+	u32			caps;
+	unsigned int		dma_burst_length;
+};
+
 struct macb {
 	void __iomem		*regs;
 
@@ -595,6 +638,7 @@ struct macb {
 	unsigned int 		duplex;
 
 	u32			caps;
+	unsigned int		dma_burst_length;
 
 	phy_interface_t		phy_interface;
 
@@ -602,6 +646,7 @@ struct macb {
 	struct sk_buff *skb;			/* holds skb until xmit interrupt completes */
 	dma_addr_t skb_physaddr;		/* phys addr from pci_map_single */
 	int skb_length;				/* saved skb length for pci_unmap_single */
+	unsigned int		max_tx_length;
 };
 
 extern const struct ethtool_ops macb_ethtool_ops;
@@ -615,7 +660,7 @@ void macb_get_hwaddr(struct macb *bp);
 
 static inline bool macb_is_gem(struct macb *bp)
 {
-	return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
+	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
 }
 
 #endif /* _MACB_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/calxeda/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/calxeda/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/calxeda/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/calxeda/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
 config NET_CALXEDA_XGMAC
 	tristate "Calxeda 1G/10G XGMAC Ethernet driver"
 	depends on HAS_IOMEM && HAS_DMA
+	depends on ARCH_HIGHBANK || COMPILE_TEST
 	select CRC32
 	help
 	  This is the driver for the XGMAC Ethernet IP block found on Calxeda
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb/subr.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb/subr.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb/subr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb/subr.c	2014-09-28 17:29:07.000000000 -0400
@@ -522,7 +522,7 @@ static const struct board_info t1_board[
 
 };
 
-DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = {
+const struct pci_device_id t1_pci_tbl[] = {
 	CH_DEVICE(8, 0, CH_BRD_T110_1CU),
 	CH_DEVICE(8, 1, CH_BRD_T110_1CU),
 	CH_DEVICE(7, 0, CH_BRD_N110_1F),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c	2014-08-07 04:52:00.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c	2014-09-28 21:33:28.000000000 -0400
@@ -85,7 +85,7 @@ enum {
 #define CH_DEVICE(devid, idx) \
 	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
 
-static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = {
+static const struct pci_device_id cxgb3_pci_tbl[] = {
 	CH_DEVICE(0x20, 0),	/* PE9000 */
 	CH_DEVICE(0x21, 1),	/* T302E */
 	CH_DEVICE(0x22, 2),	/* T310E */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1091 @@
+/*
+ *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
+ *
+ *  Written by Anish Bhatt (anish@chelsio.com)
+ *	       Casey Leedom (leedom@chelsio.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.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ *
+ */
+
+#include "cxgb4.h"
+
+/* DCBx version control
+ */
+char *dcb_ver_array[] = {
+	"Unknown",
+	"DCBx-CIN",
+	"DCBx-CEE 1.01",
+	"DCBx-IEEE",
+	"", "", "",
+	"Auto Negotiated"
+};
+
+/* Initialize a port's Data Center Bridging state.  Typically used after a
+ * Link Down event.
+ */
+void cxgb4_dcb_state_init(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+	int version_temp = dcb->dcb_version;
+
+	memset(dcb, 0, sizeof(struct port_dcb_info));
+	dcb->state = CXGB4_DCB_STATE_START;
+	if (version_temp)
+		dcb->dcb_version = version_temp;
+
+	netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
+		    __func__, pi->port_id);
+}
+
+void cxgb4_dcb_version_init(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+
+	/* Any writes here are only done on kernels that exlicitly need
+	 * a specific version, say < 2.6.38 which only support CEE
+	 */
+	dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
+}
+
+/* Finite State machine for Data Center Bridging.
+ */
+void cxgb4_dcb_state_fsm(struct net_device *dev,
+			 enum cxgb4_dcb_state_input transition_to)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+	struct adapter *adap = pi->adapter;
+	enum cxgb4_dcb_state current_state = dcb->state;
+
+	netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
+		    __func__, dcb->state, transition_to, dev->name);
+
+	switch (current_state) {
+	case CXGB4_DCB_STATE_START: {
+		switch (transition_to) {
+		case CXGB4_DCB_INPUT_FW_DISABLED: {
+			/* we're going to use Host DCB */
+			dcb->state = CXGB4_DCB_STATE_HOST;
+			dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
+			dcb->enabled = 1;
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_ENABLED: {
+			/* we're going to use Firmware DCB */
+			dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
+			dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+			/* expected transition */
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+			dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+			break;
+		}
+
+		default:
+			goto bad_state_input;
+		}
+		break;
+	}
+
+	case CXGB4_DCB_STATE_FW_INCOMPLETE: {
+		switch (transition_to) {
+		case CXGB4_DCB_INPUT_FW_ENABLED: {
+			/* we're alreaady in firmware DCB mode */
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+			/* we're already incomplete */
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+			dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+			dcb->enabled = 1;
+			linkwatch_fire_event(dev);
+			break;
+		}
+
+		default:
+			goto bad_state_input;
+		}
+		break;
+	}
+
+	case CXGB4_DCB_STATE_FW_ALLSYNCED: {
+		switch (transition_to) {
+		case CXGB4_DCB_INPUT_FW_ENABLED: {
+			/* we're alreaady in firmware DCB mode */
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+			/* We were successfully running with firmware DCB but
+			 * now it's telling us that it's in an "incomplete
+			 * state.  We need to reset back to a ground state
+			 * of incomplete.
+			 */
+			cxgb4_dcb_state_init(dev);
+			dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
+			dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+			linkwatch_fire_event(dev);
+			break;
+		}
+
+		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+			/* we're already all sync'ed
+			 * this is only applicable for IEEE or
+			 * when another VI already completed negotiaton
+			 */
+			dcb->enabled = 1;
+			linkwatch_fire_event(dev);
+			break;
+		}
+
+		default:
+			goto bad_state_input;
+		}
+		break;
+	}
+
+	case CXGB4_DCB_STATE_HOST: {
+		switch (transition_to) {
+		case CXGB4_DCB_INPUT_FW_DISABLED: {
+			/* we're alreaady in Host DCB mode */
+			break;
+		}
+
+		default:
+			goto bad_state_input;
+		}
+		break;
+	}
+
+	default:
+		goto bad_state_transition;
+	}
+	return;
+
+bad_state_input:
+	dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
+		transition_to);
+	return;
+
+bad_state_transition:
+	dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
+		current_state, transition_to);
+}
+
+/* Handle a DCB/DCBX update message from the firmware.
+ */
+void cxgb4_dcb_handle_fw_update(struct adapter *adap,
+				const struct fw_port_cmd *pcmd)
+{
+	const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
+	int port = FW_PORT_CMD_PORTID_GET(be32_to_cpu(pcmd->op_to_portid));
+	struct net_device *dev = adap->port[port];
+	struct port_info *pi = netdev_priv(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+	int dcb_type = pcmd->u.dcb.pgid.type;
+	int dcb_running_version;
+
+	/* Handle Firmware DCB Control messages separately since they drive
+	 * our state machine.
+	 */
+	if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
+		enum cxgb4_dcb_state_input input =
+			((pcmd->u.dcb.control.all_syncd_pkd &
+			  FW_PORT_CMD_ALL_SYNCD)
+			 ? CXGB4_DCB_STATE_FW_ALLSYNCED
+			 : CXGB4_DCB_STATE_FW_INCOMPLETE);
+
+		if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
+			dcb_running_version = FW_PORT_CMD_DCB_VERSION_GET(
+				be16_to_cpu(
+				pcmd->u.dcb.control.dcb_version_to_app_state));
+			if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
+			    dcb_running_version == FW_PORT_DCB_VER_IEEE) {
+				dcb->dcb_version = dcb_running_version;
+				dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
+					 dev->name,
+					 dcb_ver_array[dcb->dcb_version]);
+			} else {
+				dev_warn(adap->pdev_dev,
+					 "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
+					 dcb_ver_array[dcb->dcb_version],
+					 dcb_ver_array[dcb_running_version]);
+				dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
+			}
+		}
+
+		cxgb4_dcb_state_fsm(dev, input);
+		return;
+	}
+
+	/* It's weird, and almost certainly an error, to get Firmware DCB
+	 * messages when we either haven't been told whether we're going to be
+	 * doing Host or Firmware DCB; and even worse when we've been told
+	 * that we're doing Host DCB!
+	 */
+	if (dcb->state == CXGB4_DCB_STATE_START ||
+	    dcb->state == CXGB4_DCB_STATE_HOST) {
+		dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
+			dcb->state);
+		return;
+	}
+
+	/* Now handle the general Firmware DCB update messages ...
+	 */
+	switch (dcb_type) {
+	case FW_PORT_DCB_TYPE_PGID:
+		dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
+		dcb->msgs |= CXGB4_DCB_FW_PGID;
+		break;
+
+	case FW_PORT_DCB_TYPE_PGRATE:
+		dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
+		memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
+		       sizeof(dcb->pgrate));
+		memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
+		       sizeof(dcb->tsa));
+		dcb->msgs |= CXGB4_DCB_FW_PGRATE;
+		if (dcb->msgs & CXGB4_DCB_FW_PGID)
+			IEEE_FAUX_SYNC(dev, dcb);
+		break;
+
+	case FW_PORT_DCB_TYPE_PRIORATE:
+		memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
+		       sizeof(dcb->priorate));
+		dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
+		break;
+
+	case FW_PORT_DCB_TYPE_PFC:
+		dcb->pfcen = fwdcb->pfc.pfcen;
+		dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
+		dcb->msgs |= CXGB4_DCB_FW_PFC;
+		IEEE_FAUX_SYNC(dev, dcb);
+		break;
+
+	case FW_PORT_DCB_TYPE_APP_ID: {
+		const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
+		int idx = fwap->idx;
+		struct app_priority *ap = &dcb->app_priority[idx];
+
+		struct dcb_app app = {
+			.protocol = be16_to_cpu(fwap->protocolid),
+		};
+		int err;
+
+		/* Convert from firmware format to relevant format
+		 * when using app selector
+		 */
+		if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
+			app.selector = (fwap->sel_field + 1);
+			app.priority = ffs(fwap->user_prio_map) - 1;
+			err = dcb_ieee_setapp(dev, &app);
+			IEEE_FAUX_SYNC(dev, dcb);
+		} else {
+			/* Default is CEE */
+			app.selector = !!(fwap->sel_field);
+			app.priority = fwap->user_prio_map;
+			err = dcb_setapp(dev, &app);
+		}
+
+		if (err)
+			dev_err(adap->pdev_dev,
+				"Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
+				app.selector, app.protocol, app.priority, -err);
+
+		ap->user_prio_map = fwap->user_prio_map;
+		ap->sel_field = fwap->sel_field;
+		ap->protocolid = be16_to_cpu(fwap->protocolid);
+		dcb->msgs |= CXGB4_DCB_FW_APP_ID;
+		break;
+	}
+
+	default:
+		dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
+			dcb_type);
+		break;
+	}
+}
+
+/* Data Center Bridging netlink operations.
+ */
+
+
+/* Get current DCB enabled/disabled state.
+ */
+static u8 cxgb4_getstate(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	return pi->dcb.enabled;
+}
+
+/* Set DCB enabled/disabled.
+ */
+static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	/* Firmware doesn't provide any mechanism to control the DCB state.
+	 */
+	if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
+		return 1;
+
+	return 0;
+}
+
+static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
+			     u8 *prio_type, u8 *pgid, u8 *bw_per,
+			     u8 *up_tc_map, int local)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int err;
+
+	*prio_type = *pgid = *bw_per = *up_tc_map = 0;
+
+	if (local)
+		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+	else
+		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+
+	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+		return;
+	}
+	*pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
+
+	INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+			-err);
+		return;
+	}
+
+	*bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
+	*up_tc_map = (1 << tc);
+
+	/* prio_type is link strict */
+	*prio_type = 0x2;
+}
+
+static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
+				u8 *prio_type, u8 *pgid, u8 *bw_per,
+				u8 *up_tc_map)
+{
+	return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 1);
+}
+
+
+static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
+				u8 *prio_type, u8 *pgid, u8 *bw_per,
+				u8 *up_tc_map)
+{
+	return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 0);
+}
+
+static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
+				u8 prio_type, u8 pgid, u8 bw_per,
+				u8 up_tc_map)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	u32 _pgid;
+	int err;
+
+	if (pgid == DCB_ATTR_VALUE_UNDEFINED)
+		return;
+	if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
+		return;
+
+	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+		return;
+	}
+
+	_pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
+	_pgid &= ~(0xF << (tc * 4));
+	_pgid |= pgid << (tc * 4);
+	pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
+
+	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
+			-err);
+		return;
+	}
+
+	memset(&pcmd, 0, sizeof(struct fw_port_cmd));
+
+	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+			-err);
+		return;
+	}
+
+	pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
+
+	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS)
+		dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
+			-err);
+}
+
+static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
+			      int local)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int err;
+
+	if (local)
+		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+	else
+		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+
+	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+			-err);
+		return;
+	}
+
+	*bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
+}
+
+static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
+{
+	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
+}
+
+static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
+{
+	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
+}
+
+static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
+				 u8 bw_per)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int err;
+
+	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+			-err);
+		return;
+	}
+
+	pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
+
+	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+	if (err != FW_PORT_DCB_CFG_SUCCESS)
+		dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
+			-err);
+}
+
+/* Return whether the specified Traffic Class Priority has Priority Pause
+ * Frames enabled.
+ */
+static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+
+	if (dcb->state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
+	    priority >= CXGB4_MAX_PRIORITY)
+		*pfccfg = 0;
+	else
+		*pfccfg = (pi->dcb.pfcen >> priority) & 1;
+}
+
+/* Enable/disable Priority Pause Frames for the specified Traffic Class
+ * Priority.
+ */
+static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int err;
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
+	    priority >= CXGB4_MAX_PRIORITY)
+		return;
+
+	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+	pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
+	pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
+
+	if (pfccfg)
+		pcmd.u.dcb.pfc.pfcen |= (1 << priority);
+	else
+		pcmd.u.dcb.pfc.pfcen &= (~(1 << priority));
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
+		return;
+	}
+
+	pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
+}
+
+static u8 cxgb4_setall(struct net_device *dev)
+{
+	return 0;
+}
+
+/* Return DCB capabilities.
+ */
+static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	switch (cap_id) {
+	case DCB_CAP_ATTR_PG:
+	case DCB_CAP_ATTR_PFC:
+		*caps = true;
+		break;
+
+	case DCB_CAP_ATTR_PG_TCS:
+		/* 8 priorities for PG represented by bitmap */
+		*caps = 0x80;
+		break;
+
+	case DCB_CAP_ATTR_PFC_TCS:
+		/* 8 priorities for PFC represented by bitmap */
+		*caps = 0x80;
+		break;
+
+	case DCB_CAP_ATTR_GSP:
+		*caps = true;
+		break;
+
+	case DCB_CAP_ATTR_UP2TC:
+	case DCB_CAP_ATTR_BCN:
+		*caps = false;
+		break;
+
+	case DCB_CAP_ATTR_DCBX:
+		*caps = pi->dcb.supported;
+		break;
+
+	default:
+		*caps = false;
+	}
+
+	return 0;
+}
+
+/* Return the number of Traffic Classes for the indicated Traffic Class ID.
+ */
+static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	switch (tcs_id) {
+	case DCB_NUMTCS_ATTR_PG:
+		if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
+			*num = pi->dcb.pg_num_tcs_supported;
+		else
+			*num = 0x8;
+		break;
+
+	case DCB_NUMTCS_ATTR_PFC:
+		*num = 0x8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Set the number of Traffic Classes supported for the indicated Traffic Class
+ * ID.
+ */
+static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
+{
+	/* Setting the number of Traffic Classes isn't supported.
+	 */
+	return -ENOSYS;
+}
+
+/* Return whether Priority Flow Control is enabled.  */
+static u8 cxgb4_getpfcstate(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return false;
+
+	return pi->dcb.pfcen != 0;
+}
+
+/* Enable/disable Priority Flow Control. */
+static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
+{
+	/* We can't enable/disable Priority Flow Control but we also can't
+	 * return an error ...
+	 */
+}
+
+/* Return the Application User Priority Map associated with the specified
+ * Application ID.
+ */
+static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+			  int peer)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int i;
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return 0;
+
+	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+		struct fw_port_cmd pcmd;
+		int err;
+
+		if (peer)
+			INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+		else
+			INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+
+		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+		pcmd.u.dcb.app_priority.idx = i;
+
+		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+		if (err != FW_PORT_DCB_CFG_SUCCESS) {
+			dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
+				-err);
+			return err;
+		}
+		if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
+			if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
+				return pcmd.u.dcb.app_priority.user_prio_map;
+
+		/* exhausted app list */
+		if (!pcmd.u.dcb.app_priority.protocolid)
+			break;
+	}
+
+	return -EEXIST;
+}
+
+/* Return the Application User Priority Map associated with the specified
+ * Application ID.
+ */
+static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
+{
+	return __cxgb4_getapp(dev, app_idtype, app_id, 0);
+}
+
+/* Write a new Application User Priority Map for the specified Application ID
+ */
+static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+			  u8 app_prio)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int i, err;
+
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return -EINVAL;
+
+	/* DCB info gets thrown away on link up */
+	if (!netif_carrier_ok(dev))
+		return -ENOLINK;
+
+	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+		pcmd.u.dcb.app_priority.idx = i;
+		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+		if (err != FW_PORT_DCB_CFG_SUCCESS) {
+			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+				-err);
+			return err;
+		}
+		if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
+			/* overwrite existing app table */
+			pcmd.u.dcb.app_priority.protocolid = 0;
+			break;
+		}
+		/* find first empty slot */
+		if (!pcmd.u.dcb.app_priority.protocolid)
+			break;
+	}
+
+	if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
+		/* no empty slots available */
+		dev_err(adap->pdev_dev, "DCB app table full\n");
+		return -EBUSY;
+	}
+
+	/* write out new app table entry */
+	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+	pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+	pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
+	pcmd.u.dcb.app_priority.sel_field = app_idtype;
+	pcmd.u.dcb.app_priority.user_prio_map = app_prio;
+	pcmd.u.dcb.app_priority.idx = i;
+
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
+			-err);
+		return err;
+	}
+
+	return 0;
+}
+
+/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
+static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+			u8 app_prio)
+{
+	int ret;
+	struct dcb_app app = {
+		.selector = app_idtype,
+		.protocol = app_id,
+		.priority = app_prio,
+	};
+
+	if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
+	    app_idtype != DCB_APP_IDTYPE_PORTNUM)
+		return -EINVAL;
+
+	/* Convert app_idtype to a format that firmware understands */
+	ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
+			      app_idtype : 3, app_id, app_prio);
+	if (ret)
+		return ret;
+
+	return dcb_setapp(dev, &app);
+}
+
+/* Return whether IEEE Data Center Bridging has been negotiated.
+ */
+static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+	struct port_dcb_info *dcb = &pi->dcb;
+
+	return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
+		(dcb->supported & DCB_CAP_DCBX_VER_IEEE));
+}
+
+/* Fill in the Application User Priority Map associated with the
+ * specified Application.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
+ */
+static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
+{
+	int prio;
+
+	if (!cxgb4_ieee_negotiation_complete(dev))
+		return -EINVAL;
+	if (!(app->selector && app->protocol))
+		return -EINVAL;
+
+	/* Try querying firmware first, use firmware format */
+	prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
+
+	if (prio < 0)
+		prio = dcb_ieee_getapp_mask(dev, app);
+
+	app->priority = ffs(prio) - 1;
+	return 0;
+}
+
+/* Write a new Application User Priority Map for the specified Application ID.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
+ */
+static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+	int ret;
+
+	if (!cxgb4_ieee_negotiation_complete(dev))
+		return -EINVAL;
+	if (!(app->selector && app->protocol))
+		return -EINVAL;
+
+	if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE  &&
+	      app->selector < IEEE_8021QAZ_APP_SEL_ANY))
+		return -EINVAL;
+
+	/* change selector to a format that firmware understands */
+	ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
+			     (1 << app->priority));
+	if (ret)
+		return ret;
+
+	return dcb_ieee_setapp(dev, app);
+}
+
+/* Return our DCBX parameters.
+ */
+static u8 cxgb4_getdcbx(struct net_device *dev)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	/* This is already set by cxgb4_set_dcb_caps, so just return it */
+	return pi->dcb.supported;
+}
+
+/* Set our DCBX parameters.
+ */
+static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	/* Filter out requests which exceed our capabilities.
+	 */
+	if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
+	    != dcb_request)
+		return 1;
+
+	/* Can't enable DCB if we haven't successfully negotiated it.
+	 */
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return 1;
+
+	/* There's currently no mechanism to allow for the firmware DCBX
+	 * negotiation to be changed from the Host Driver.  If the caller
+	 * requests exactly the same parameters that we already have then
+	 * we'll allow them to be successfully "set" ...
+	 */
+	if (dcb_request != pi->dcb.supported)
+		return 1;
+
+	pi->dcb.supported = dcb_request;
+	return 0;
+}
+
+static int cxgb4_getpeer_app(struct net_device *dev,
+			     struct dcb_peer_app_info *info, u16 *app_count)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int i, err = 0;
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return 1;
+
+	info->willing = 0;
+	info->error = 0;
+
+	*app_count = 0;
+	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+		pcmd.u.dcb.app_priority.idx = *app_count;
+		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+		if (err != FW_PORT_DCB_CFG_SUCCESS) {
+			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+				-err);
+			return err;
+		}
+
+		/* find first empty slot */
+		if (!pcmd.u.dcb.app_priority.protocolid)
+			break;
+	}
+	*app_count = i;
+	return err;
+}
+
+static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	int i, err = 0;
+
+	if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+		return 1;
+
+	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+		pcmd.u.dcb.app_priority.idx = i;
+		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+		if (err != FW_PORT_DCB_CFG_SUCCESS) {
+			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+				-err);
+			return err;
+		}
+
+		/* find first empty slot */
+		if (!pcmd.u.dcb.app_priority.protocolid)
+			break;
+
+		table[i].selector = pcmd.u.dcb.app_priority.sel_field;
+		table[i].protocol =
+			be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
+		table[i].priority =
+			ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
+	}
+	return err;
+}
+
+/* Return Priority Group information.
+ */
+static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
+{
+	struct fw_port_cmd pcmd;
+	struct port_info *pi = netdev2pinfo(dev);
+	struct adapter *adap = pi->adapter;
+	u32 pgid;
+	int i, err;
+
+	/* We're always "willing" -- the Switch Fabric always dictates the
+	 * DCBX parameters to us.
+	 */
+	pg->willing = true;
+
+	INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+		return err;
+	}
+	pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
+
+	for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
+		pg->prio_pg[i] = (pgid >> (i * 4)) & 0xF;
+
+	INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+	if (err != FW_PORT_DCB_CFG_SUCCESS) {
+		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+			-err);
+		return err;
+	}
+
+	for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
+		pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
+
+	return 0;
+}
+
+/* Return Priority Flow Control information.
+ */
+static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
+{
+	struct port_info *pi = netdev2pinfo(dev);
+
+	cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
+	pfc->pfc_en = pi->dcb.pfcen;
+
+	return 0;
+}
+
+const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
+	.ieee_getapp		= cxgb4_ieee_getapp,
+	.ieee_setapp		= cxgb4_ieee_setapp,
+
+	/* CEE std */
+	.getstate		= cxgb4_getstate,
+	.setstate		= cxgb4_setstate,
+	.getpgtccfgtx		= cxgb4_getpgtccfg_tx,
+	.getpgbwgcfgtx		= cxgb4_getpgbwgcfg_tx,
+	.getpgtccfgrx		= cxgb4_getpgtccfg_rx,
+	.getpgbwgcfgrx		= cxgb4_getpgbwgcfg_rx,
+	.setpgtccfgtx		= cxgb4_setpgtccfg_tx,
+	.setpgbwgcfgtx		= cxgb4_setpgbwgcfg_tx,
+	.setpfccfg		= cxgb4_setpfccfg,
+	.getpfccfg		= cxgb4_getpfccfg,
+	.setall			= cxgb4_setall,
+	.getcap			= cxgb4_getcap,
+	.getnumtcs		= cxgb4_getnumtcs,
+	.setnumtcs		= cxgb4_setnumtcs,
+	.getpfcstate		= cxgb4_getpfcstate,
+	.setpfcstate		= cxgb4_setpfcstate,
+	.getapp			= cxgb4_getapp,
+	.setapp			= cxgb4_setapp,
+
+	/* DCBX configuration */
+	.getdcbx		= cxgb4_getdcbx,
+	.setdcbx		= cxgb4_setdcbx,
+
+	/* peer apps */
+	.peer_getappinfo	= cxgb4_getpeer_app,
+	.peer_getapptable	= cxgb4_getpeerapp_tbl,
+
+	/* CEE peer */
+	.cee_peer_getpg		= cxgb4_cee_peer_getpg,
+	.cee_peer_getpfc	= cxgb4_cee_peer_getpfc,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
+ *
+ *  Written by Anish Bhatt (anish@chelsio.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.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ *
+ */
+
+#ifndef __CXGB4_DCB_H
+#define __CXGB4_DCB_H
+
+#include <linux/netdevice.h>
+#include <linux/dcbnl.h>
+#include <net/dcbnl.h>
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+
+#define CXGB4_DCBX_FW_SUPPORT \
+	(DCB_CAP_DCBX_VER_CEE | \
+	 DCB_CAP_DCBX_VER_IEEE | \
+	 DCB_CAP_DCBX_LLD_MANAGED)
+#define CXGB4_DCBX_HOST_SUPPORT \
+	(DCB_CAP_DCBX_VER_CEE | \
+	 DCB_CAP_DCBX_VER_IEEE | \
+	 DCB_CAP_DCBX_HOST)
+
+#define CXGB4_MAX_PRIORITY      CXGB4_MAX_DCBX_APP_SUPPORTED
+#define CXGB4_MAX_TCS           CXGB4_MAX_DCBX_APP_SUPPORTED
+
+#define INIT_PORT_DCB_CMD(__pcmd, __port, __op, __action) \
+	do { \
+		memset(&(__pcmd), 0, sizeof(__pcmd)); \
+		(__pcmd).op_to_portid = \
+			cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) | \
+				    FW_CMD_REQUEST | \
+				    FW_CMD_##__op | \
+				    FW_PORT_CMD_PORTID(__port)); \
+		(__pcmd).action_to_len16 = \
+			cpu_to_be32(FW_PORT_CMD_ACTION(__action) | \
+				    FW_LEN16(pcmd)); \
+	} while (0)
+
+#define INIT_PORT_DCB_READ_PEER_CMD(__pcmd, __port) \
+	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_RECV)
+
+#define INIT_PORT_DCB_READ_LOCAL_CMD(__pcmd, __port) \
+	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_TRANS)
+
+#define INIT_PORT_DCB_READ_SYNC_CMD(__pcmd, __port) \
+	INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_DET)
+
+#define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \
+	INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG)
+
+#define IEEE_FAUX_SYNC(__dev, __dcb) \
+	do { \
+		if ((__dcb)->dcb_version == FW_PORT_DCB_VER_IEEE) \
+			cxgb4_dcb_state_fsm((__dev), \
+					    CXGB4_DCB_STATE_FW_ALLSYNCED); \
+	} while (0)
+
+/* States we can be in for a port's Data Center Bridging.
+ */
+enum cxgb4_dcb_state {
+	CXGB4_DCB_STATE_START,		/* initial unknown state */
+	CXGB4_DCB_STATE_HOST,		/* we're using Host DCB (if at all) */
+	CXGB4_DCB_STATE_FW_INCOMPLETE,	/* using firmware DCB, incomplete */
+	CXGB4_DCB_STATE_FW_ALLSYNCED,	/* using firmware DCB, all sync'ed */
+};
+
+/* Data Center Bridging state input for the Finite State Machine.
+ */
+enum cxgb4_dcb_state_input {
+	/* Input from the firmware.
+	 */
+	CXGB4_DCB_INPUT_FW_DISABLED,	/* firmware DCB disabled */
+	CXGB4_DCB_INPUT_FW_ENABLED,	/* firmware DCB enabled */
+	CXGB4_DCB_INPUT_FW_INCOMPLETE,	/* firmware reports incomplete DCB */
+	CXGB4_DCB_INPUT_FW_ALLSYNCED,	/* firmware reports all sync'ed */
+
+};
+
+/* Firmware DCB messages that we've received so far ...
+ */
+enum cxgb4_dcb_fw_msgs {
+	CXGB4_DCB_FW_PGID	= 0x01,
+	CXGB4_DCB_FW_PGRATE	= 0x02,
+	CXGB4_DCB_FW_PRIORATE	= 0x04,
+	CXGB4_DCB_FW_PFC	= 0x08,
+	CXGB4_DCB_FW_APP_ID	= 0x10,
+};
+
+#define CXGB4_MAX_DCBX_APP_SUPPORTED 8
+
+/* Data Center Bridging support;
+ */
+struct port_dcb_info {
+	enum cxgb4_dcb_state state;	/* DCB State Machine */
+	enum cxgb4_dcb_fw_msgs msgs;	/* DCB Firmware messages received */
+	unsigned int supported;		/* OS DCB capabilities supported */
+	bool enabled;			/* OS Enabled state */
+
+	/* Cached copies of DCB information sent by the firmware (in Host
+	 * Native Endian format).
+	 */
+	u32	pgid;			/* Priority Group[0..7] */
+	u8	dcb_version;		/* Running DCBx version */
+	u8	pfcen;			/* Priority Flow Control[0..7] */
+	u8	pg_num_tcs_supported;	/* max PG Traffic Classes */
+	u8	pfc_num_tcs_supported;	/* max PFC Traffic Classes */
+	u8	pgrate[8];		/* Priority Group Rate[0..7] */
+	u8	priorate[8];		/* Priority Rate[0..7] */
+	u8	tsa[8];			/* TSA Algorithm[0..7] */
+	struct app_priority { /* Application Information */
+		u8	user_prio_map;	/* Priority Map bitfield */
+		u8	sel_field;	/* Protocol ID interpretation */
+		u16	protocolid;	/* Protocol ID */
+	} app_priority[CXGB4_MAX_DCBX_APP_SUPPORTED];
+};
+
+void cxgb4_dcb_state_init(struct net_device *);
+void cxgb4_dcb_version_init(struct net_device *);
+void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input);
+void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *);
+void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *);
+extern const struct dcbnl_rtnl_ops cxgb4_dcb_ops;
+
+#define CXGB4_DCB_ENABLED true
+
+#else /* !CONFIG_CHELSIO_T4_DCB */
+
+static inline void cxgb4_dcb_state_init(struct net_device *dev)
+{
+}
+
+#define CXGB4_DCB_ENABLED false
+
+#endif /* !CONFIG_CHELSIO_T4_DCB */
+
+#endif /* __CXGB4_DCB_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -50,13 +50,13 @@
 #include "cxgb4_uld.h"
 
 #define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x09
-#define T4FW_VERSION_MICRO 0x17
+#define T4FW_VERSION_MINOR 0x0B
+#define T4FW_VERSION_MICRO 0x1B
 #define T4FW_VERSION_BUILD 0x00
 
 #define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x09
-#define T5FW_VERSION_MICRO 0x17
+#define T5FW_VERSION_MINOR 0x0B
+#define T5FW_VERSION_MICRO 0x1B
 #define T5FW_VERSION_BUILD 0x00
 
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@ -85,7 +85,8 @@ enum {
 	MEMWIN1_BASE_T5  = 0x52000,
 	MEMWIN2_APERTURE = 65536,
 	MEMWIN2_BASE     = 0x30000,
-	MEMWIN2_BASE_T5  = 0x54000,
+	MEMWIN2_APERTURE_T5 = 131072,
+	MEMWIN2_BASE_T5  = 0x60000,
 };
 
 enum dev_master {
@@ -309,6 +310,9 @@ struct adapter_params {
 
 	unsigned int ofldq_wr_cred;
 	bool ulptx_memwrite_dsgl;          /* use of T5 DSGL allowed */
+
+	unsigned int max_ordird_qp;       /* Max read depth per RDMA QP */
+	unsigned int max_ird_adapter;     /* Max read depth per adapter */
 };
 
 #include "t4fw_api.h"
@@ -373,6 +377,8 @@ enum {
 struct adapter;
 struct sge_rspq;
 
+#include "cxgb4_dcb.h"
+
 struct port_info {
 	struct adapter *adapter;
 	u16    viid;
@@ -389,6 +395,9 @@ struct port_info {
 	u8     rss_mode;
 	struct link_config link_cfg;
 	u16   *rss;
+#ifdef CONFIG_CHELSIO_T4_DCB
+	struct port_dcb_info dcb;     /* Data Center Bridging support */
+#endif
 };
 
 struct dentry;
@@ -513,6 +522,9 @@ struct sge_txq {
 struct sge_eth_txq {                /* state for an SGE Ethernet Tx queue */
 	struct sge_txq q;
 	struct netdev_queue *txq;   /* associated netdev TX queue */
+#ifdef CONFIG_CHELSIO_T4_DCB
+	u8 dcb_prio;		    /* DCB Priority bound to queue */
+#endif
 	unsigned long tso;          /* # of TSO requests */
 	unsigned long tx_cso;       /* # of Tx checksum offloads */
 	unsigned long vlan_ins;     /* # of Tx VLAN insertions */
@@ -603,6 +615,7 @@ struct l2t_data;
 struct adapter {
 	void __iomem *regs;
 	void __iomem *bar2;
+	u32 t4_bar0;
 	struct pci_dev *pdev;
 	struct device *pdev_dev;
 	unsigned int mbox;
@@ -639,6 +652,7 @@ struct adapter {
 	struct tid_info tids;
 	void **tid_release_head;
 	spinlock_t tid_release_lock;
+	struct workqueue_struct *workq;
 	struct work_struct tid_release_task;
 	struct work_struct db_full_task;
 	struct work_struct db_drop_task;
@@ -647,6 +661,7 @@ struct adapter {
 	struct dentry *debugfs_root;
 
 	spinlock_t stats_lock;
+	spinlock_t win0_lock ____cacheline_aligned_in_smp;
 };
 
 /* Defined bit width of user definable filter tuples
@@ -855,6 +870,7 @@ void t4_os_link_changed(struct adapter *
 void *t4_alloc_mem(size_t size);
 
 void t4_free_sge_resources(struct adapter *adap);
+void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q);
 irq_handler_t t4_intr_handler(struct adapter *adap);
 netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev);
 int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
@@ -941,6 +957,7 @@ void t4_write_indirect(struct adapter *a
 void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
 		      unsigned int data_reg, u32 *vals, unsigned int nregs,
 		      unsigned int start_idx);
+void t4_hw_pci_read_cfg4(struct adapter *adapter, int reg, u32 *val);
 
 struct fw_filter_wr;
 
@@ -952,8 +969,17 @@ int t4_wait_dev_ready(struct adapter *ad
 int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
 		  struct link_config *lc);
 int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
-int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
-		    __be32 *buf);
+
+#define T4_MEMORY_WRITE	0
+#define T4_MEMORY_READ	1
+int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr, u32 len,
+		 __be32 *buf, int dir);
+static inline int t4_memory_write(struct adapter *adap, int mtype, u32 addr,
+				  u32 len, __be32 *buf)
+{
+	return t4_memory_rw(adap, 0, mtype, addr, len, buf, 0);
+}
+
 int t4_seeprom_wp(struct adapter *adapter, bool enable);
 int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
@@ -1007,6 +1033,10 @@ int t4_query_params(struct adapter *adap
 int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
 		  unsigned int vf, unsigned int nparams, const u32 *params,
 		  const u32 *val);
+int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
+			  unsigned int pf, unsigned int vf,
+			  unsigned int nparams, const u32 *params,
+			  const u32 *val);
 int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
 		unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
 		unsigned int rxqi, unsigned int rxq, unsigned int tc,
@@ -1025,6 +1055,8 @@ int t4_change_mac(struct adapter *adap,
 		  int idx, const u8 *addr, bool persist, bool add_smt);
 int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		     bool ucast, u64 vec, bool sleep_ok);
+int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
+			unsigned int viid, bool rx_en, bool tx_en, bool dcb_en);
 int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		 bool rx_en, bool tx_en);
 int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
@@ -1045,7 +1077,6 @@ int t4_ofld_eq_free(struct adapter *adap
 int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
 void t4_db_full(struct adapter *adapter);
 void t4_db_dropped(struct adapter *adapter);
-int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
 int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
 			 u32 addr, u32 val);
 void t4_sge_decode_idma_state(struct adapter *adapter, int state);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2014-08-07 04:52:04.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2014-09-28 21:33:33.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -67,6 +67,7 @@
 #include "t4_regs.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "cxgb4_dcb.h"
 #include "l2t.h"
 
 #include <../drivers/net/bonding/bonding.h>
@@ -211,7 +212,7 @@ struct filter_entry {
 
 #define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) }
 
-static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
+static const struct pci_device_id cxgb4_pci_tbl[] = {
 	CH_DEVICE(0xa000, 0),  /* PE10K */
 	CH_DEVICE(0x4001, -1),
 	CH_DEVICE(0x4002, -1),
@@ -223,6 +224,17 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci
 	CH_DEVICE(0x4008, -1),
 	CH_DEVICE(0x4009, -1),
 	CH_DEVICE(0x400a, -1),
+	CH_DEVICE(0x400d, -1),
+	CH_DEVICE(0x400e, -1),
+	CH_DEVICE(0x4080, -1),
+	CH_DEVICE(0x4081, -1),
+	CH_DEVICE(0x4082, -1),
+	CH_DEVICE(0x4083, -1),
+	CH_DEVICE(0x4084, -1),
+	CH_DEVICE(0x4085, -1),
+	CH_DEVICE(0x4086, -1),
+	CH_DEVICE(0x4087, -1),
+	CH_DEVICE(0x4088, -1),
 	CH_DEVICE(0x4401, 4),
 	CH_DEVICE(0x4402, 4),
 	CH_DEVICE(0x4403, 4),
@@ -235,6 +247,15 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci
 	CH_DEVICE(0x440a, 4),
 	CH_DEVICE(0x440d, 4),
 	CH_DEVICE(0x440e, 4),
+	CH_DEVICE(0x4480, 4),
+	CH_DEVICE(0x4481, 4),
+	CH_DEVICE(0x4482, 4),
+	CH_DEVICE(0x4483, 4),
+	CH_DEVICE(0x4484, 4),
+	CH_DEVICE(0x4485, 4),
+	CH_DEVICE(0x4486, 4),
+	CH_DEVICE(0x4487, 4),
+	CH_DEVICE(0x4488, 4),
 	CH_DEVICE(0x5001, 4),
 	CH_DEVICE(0x5002, 4),
 	CH_DEVICE(0x5003, 4),
@@ -390,6 +411,17 @@ module_param_array(num_vf, uint, NULL, 0
 MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
 #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)
+ *
+ * Default: select_queue=0
+ */
+static int select_queue;
+module_param(select_queue, int, 0644);
+MODULE_PARM_DESC(select_queue,
+		 "Select between kernel provided method of selecting or driver method of selecting TX queue. Default is kernel method.");
+
 /*
  * The filter TCAM has a fixed portion and a variable portion.  The fixed
  * portion can match on source/destination IP IPv4/IPv6 addresses and TCP/UDP
@@ -457,6 +489,44 @@ static void link_report(struct net_devic
 	}
 }
 
+#ifdef CONFIG_CHELSIO_T4_DCB
+/* Set up/tear down Data Center Bridging Priority mapping for a net device. */
+static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
+{
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adap = pi->adapter;
+	struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset];
+	int i;
+
+	/* We use a simple mapping of Port TX Queue Index to DCB
+	 * Priority when we're enabling DCB.
+	 */
+	for (i = 0; i < pi->nqsets; i++, txq++) {
+		u32 name, value;
+		int err;
+
+		name = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
+			FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) |
+			FW_PARAMS_PARAM_YZ(txq->q.cntxt_id));
+		value = enable ? i : 0xffffffff;
+
+		/* Since we can be called while atomic (from "interrupt
+		 * level") we need to issue the Set Parameters Commannd
+		 * without sleeping (timeout < 0).
+		 */
+		err = t4_set_params_nosleep(adap, adap->mbox, adap->fn, 0, 1,
+					    &name, &value);
+
+		if (err)
+			dev_err(adap->pdev_dev,
+				"Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n",
+				enable ? "set" : "unset", pi->port_id, i, -err);
+		else
+			txq->dcb_prio = value;
+	}
+}
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
 void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
 {
 	struct net_device *dev = adapter->port[port_id];
@@ -465,8 +535,13 @@ void t4_os_link_changed(struct adapter *
 	if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) {
 		if (link_stat)
 			netif_carrier_on(dev);
-		else
+		else {
+#ifdef CONFIG_CHELSIO_T4_DCB
+			cxgb4_dcb_state_init(dev);
+			dcb_tx_queue_prio_enable(dev, false);
+#endif /* CONFIG_CHELSIO_T4_DCB */
 			netif_carrier_off(dev);
+		}
 
 		link_report(dev);
 	}
@@ -567,8 +642,6 @@ static int set_rxmode(struct net_device
 	return ret;
 }
 
-static struct workqueue_struct *workq;
-
 /**
  *	link_start - enable a port
  *	@dev: the port to enable
@@ -599,11 +672,49 @@ static int link_start(struct net_device
 	if (ret == 0)
 		ret = t4_link_start(pi->adapter, mb, pi->tx_chan,
 				    &pi->link_cfg);
-	if (ret == 0)
-		ret = t4_enable_vi(pi->adapter, mb, pi->viid, true, true);
+	if (ret == 0) {
+		local_bh_disable();
+		ret = t4_enable_vi_params(pi->adapter, mb, pi->viid, true,
+					  true, CXGB4_DCB_ENABLED);
+		local_bh_enable();
+	}
+
 	return ret;
 }
 
+int cxgb4_dcb_enabled(const struct net_device *dev)
+{
+#ifdef CONFIG_CHELSIO_T4_DCB
+	struct port_info *pi = netdev_priv(dev);
+
+	return pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED;
+#else
+	return 0;
+#endif
+}
+EXPORT_SYMBOL(cxgb4_dcb_enabled);
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+/* Handle a Data Center Bridging update message from the firmware. */
+static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd)
+{
+	int port = FW_PORT_CMD_PORTID_GET(ntohl(pcmd->op_to_portid));
+	struct net_device *dev = adap->port[port];
+	int old_dcb_enabled = cxgb4_dcb_enabled(dev);
+	int new_dcb_enabled;
+
+	cxgb4_dcb_handle_fw_update(adap, pcmd);
+	new_dcb_enabled = cxgb4_dcb_enabled(dev);
+
+	/* If the DCB has become enabled or disabled on the port then we're
+	 * going to need to set up/tear down DCB Priority parameters for the
+	 * TX Queues associated with the port.
+	 */
+	if (new_dcb_enabled != old_dcb_enabled)
+		dcb_tx_queue_prio_enable(dev, new_dcb_enabled);
+}
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
 /* Clear a filter and release any of its resources that we own.  This also
  * clears the filter's "pending" status.
  */
@@ -708,8 +819,32 @@ static int fwevtq_handler(struct sge_rsp
 	} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
 		const struct cpl_fw6_msg *p = (void *)rsp;
 
-		if (p->type == 0)
-			t4_handle_fw_rpl(q->adap, p->data);
+#ifdef CONFIG_CHELSIO_T4_DCB
+		const struct fw_port_cmd *pcmd = (const void *)p->data;
+		unsigned int cmd = FW_CMD_OP_GET(ntohl(pcmd->op_to_portid));
+		unsigned int action =
+			FW_PORT_CMD_ACTION_GET(ntohl(pcmd->action_to_len16));
+
+		if (cmd == FW_PORT_CMD &&
+		    action == FW_PORT_ACTION_GET_PORT_INFO) {
+			int port = FW_PORT_CMD_PORTID_GET(
+					be32_to_cpu(pcmd->op_to_portid));
+			struct net_device *dev = q->adap->port[port];
+			int state_input = ((pcmd->u.info.dcbxdis_pkd &
+					    FW_PORT_CMD_DCBXDIS)
+					   ? CXGB4_DCB_INPUT_FW_DISABLED
+					   : CXGB4_DCB_INPUT_FW_ENABLED);
+
+			cxgb4_dcb_state_fsm(dev, state_input);
+		}
+
+		if (cmd == FW_PORT_CMD &&
+		    action == FW_PORT_ACTION_L2_DCB_CFG)
+			dcb_rpl(q->adap, pcmd);
+		else
+#endif
+			if (p->type == 0)
+				t4_handle_fw_rpl(q->adap, p->data);
 	} else if (opcode == CPL_L2T_WRITE_RPL) {
 		const struct cpl_l2t_write_rpl *p = (void *)rsp;
 
@@ -1117,7 +1252,9 @@ freeout:	t4_free_sge_resources(adap);
 			goto freeout;
 	}
 
-	t4_write_reg(adap, MPS_TRC_RSS_CONTROL,
+	t4_write_reg(adap, is_t4(adap->params.chip) ?
+				MPS_TRC_RSS_CONTROL :
+				MPS_T5_TRC_RSS_CONTROL,
 		     RSSCONTROL(netdev2pinfo(adap->port[0])->tx_chan) |
 		     QUEUENUMBER(s->ethrxq[0].rspq.abs_id));
 	return 0;
@@ -1289,6 +1426,48 @@ static int del_filter_wr(struct adapter
 	return 0;
 }
 
+static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
+			     void *accel_priv, select_queue_fallback_t fallback)
+{
+	int txq;
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+	/* If a Data Center Bridging has been successfully negotiated on this
+	 * link then we'll use the skb's priority to map it to a TX Queue.
+	 * The skb's priority is determined via the VLAN Tag Priority Code
+	 * Point field.
+	 */
+	if (cxgb4_dcb_enabled(dev)) {
+		u16 vlan_tci;
+		int err;
+
+		err = vlan_get_tag(skb, &vlan_tci);
+		if (unlikely(err)) {
+			if (net_ratelimit())
+				netdev_warn(dev,
+					    "TX Packet without VLAN Tag on DCB Link\n");
+			txq = 0;
+		} else {
+			txq = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		}
+		return txq;
+	}
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
+	if (select_queue) {
+		txq = (skb_rx_queue_recorded(skb)
+			? skb_get_rx_queue(skb)
+			: smp_processor_id());
+
+		while (unlikely(txq >= dev->real_num_tx_queues))
+			txq -= dev->real_num_tx_queues;
+
+		return txq;
+	}
+
+	return fallback(dev, skb) % dev->real_num_tx_queues;
+}
+
 static inline int is_offload(const struct adapter *adap)
 {
 	return adap->params.offload;
@@ -1583,7 +1762,8 @@ static void get_regs(struct net_device *
 		0xd004, 0xd03c,
 		0xdfc0, 0xdfe0,
 		0xe000, 0xea7c,
-		0xf000, 0x11190,
+		0xf000, 0x11110,
+		0x11118, 0x11190,
 		0x19040, 0x1906c,
 		0x19078, 0x19080,
 		0x1908c, 0x19124,
@@ -1790,7 +1970,8 @@ static void get_regs(struct net_device *
 		0xd004, 0xd03c,
 		0xdfc0, 0xdfe0,
 		0xe000, 0x11088,
-		0x1109c, 0x1117c,
+		0x1109c, 0x11110,
+		0x11118, 0x1117c,
 		0x11190, 0x11204,
 		0x19040, 0x1906c,
 		0x19078, 0x19080,
@@ -2911,6 +3092,8 @@ static ssize_t mem_read(struct file *fil
 	loff_t avail = file_inode(file)->i_size;
 	unsigned int mem = (uintptr_t)file->private_data & 3;
 	struct adapter *adap = file->private_data - mem;
+	__be32 *data;
+	int ret;
 
 	if (pos < 0)
 		return -EINVAL;
@@ -2919,29 +3102,24 @@ static ssize_t mem_read(struct file *fil
 	if (count > avail - pos)
 		count = avail - pos;
 
-	while (count) {
-		size_t len;
-		int ret, ofst;
-		__be32 data[16];
+	data = t4_alloc_mem(count);
+	if (!data)
+		return -ENOMEM;
 
-		if ((mem == MEM_MC) || (mem == MEM_MC1))
-			ret = t4_mc_read(adap, mem % MEM_MC, pos, data, NULL);
-		else
-			ret = t4_edc_read(adap, mem, pos, data, NULL);
-		if (ret)
-			return ret;
+	spin_lock(&adap->win0_lock);
+	ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ);
+	spin_unlock(&adap->win0_lock);
+	if (ret) {
+		t4_free_mem(data);
+		return ret;
+	}
+	ret = copy_to_user(buf, data, count);
 
-		ofst = pos % sizeof(data);
-		len = min(count, sizeof(data) - ofst);
-		if (copy_to_user(buf, (u8 *)data + ofst, len))
-			return -EFAULT;
+	t4_free_mem(data);
+	if (ret)
+		return -EFAULT;
 
-		buf += len;
-		pos += len;
-		count -= len;
-	}
-	count = pos - *ppos;
-	*ppos = pos;
+	*ppos = pos + count;
 	return count;
 }
 
@@ -3163,7 +3341,7 @@ static void cxgb4_queue_tid_release(stru
 	adap->tid_release_head = (void **)((uintptr_t)p | chan);
 	if (!adap->tid_release_task_busy) {
 		adap->tid_release_task_busy = true;
-		queue_work(workq, &adap->tid_release_task);
+		queue_work(adap->workq, &adap->tid_release_task);
 	}
 	spin_unlock_bh(&adap->tid_release_lock);
 }
@@ -3273,8 +3451,8 @@ static int tid_init(struct tid_info *t)
 	return 0;
 }
 
-static int cxgb4_clip_get(const struct net_device *dev,
-			  const struct in6_addr *lip)
+int cxgb4_clip_get(const struct net_device *dev,
+		   const struct in6_addr *lip)
 {
 	struct adapter *adap;
 	struct fw_clip_cmd c;
@@ -3288,9 +3466,10 @@ static int cxgb4_clip_get(const struct n
 	c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
 }
+EXPORT_SYMBOL(cxgb4_clip_get);
 
-static int cxgb4_clip_release(const struct net_device *dev,
-			      const struct in6_addr *lip)
+int cxgb4_clip_release(const struct net_device *dev,
+		       const struct in6_addr *lip)
 {
 	struct adapter *adap;
 	struct fw_clip_cmd c;
@@ -3304,6 +3483,7 @@ static int cxgb4_clip_release(const stru
 	c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
 }
+EXPORT_SYMBOL(cxgb4_clip_release);
 
 /**
  *	cxgb4_create_server - create an IP server
@@ -3602,7 +3782,11 @@ static int read_eq_indices(struct adapte
 	__be64 indices;
 	int ret;
 
-	ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
+	spin_lock(&adap->win0_lock);
+	ret = t4_memory_rw(adap, 0, MEM_EDC0, addr,
+			   sizeof(indices), (__be32 *)&indices,
+			   T4_MEMORY_READ);
+	spin_unlock(&adap->win0_lock);
 	if (!ret) {
 		*cidx = (be64_to_cpu(indices) >> 25) & 0xffff;
 		*pidx = (be64_to_cpu(indices) >> 9) & 0xffff;
@@ -3656,6 +3840,85 @@ void cxgb4_enable_db_coalescing(struct n
 }
 EXPORT_SYMBOL(cxgb4_enable_db_coalescing);
 
+int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte)
+{
+	struct adapter *adap;
+	u32 offset, memtype, memaddr;
+	u32 edc0_size, edc1_size, mc0_size, mc1_size;
+	u32 edc0_end, edc1_end, mc0_end, mc1_end;
+	int ret;
+
+	adap = netdev2adap(dev);
+
+	offset = ((stag >> 8) * 32) + adap->vres.stag.start;
+
+	/* Figure out where the offset lands in the Memory Type/Address scheme.
+	 * This code assumes that the memory is laid out starting at offset 0
+	 * with no breaks as: EDC0, EDC1, MC0, MC1. All cards have both EDC0
+	 * and EDC1.  Some cards will have neither MC0 nor MC1, most cards have
+	 * MC0, and some have both MC0 and MC1.
+	 */
+	edc0_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)) << 20;
+	edc1_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM1_BAR)) << 20;
+	mc0_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)) << 20;
+
+	edc0_end = edc0_size;
+	edc1_end = edc0_end + edc1_size;
+	mc0_end = edc1_end + mc0_size;
+
+	if (offset < edc0_end) {
+		memtype = MEM_EDC0;
+		memaddr = offset;
+	} else if (offset < edc1_end) {
+		memtype = MEM_EDC1;
+		memaddr = offset - edc0_end;
+	} else {
+		if (offset < mc0_end) {
+			memtype = MEM_MC0;
+			memaddr = offset - edc1_end;
+		} else if (is_t4(adap->params.chip)) {
+			/* T4 only has a single memory channel */
+			goto err;
+		} else {
+			mc1_size = EXT_MEM_SIZE_GET(
+					t4_read_reg(adap,
+						    MA_EXT_MEMORY1_BAR)) << 20;
+			mc1_end = mc0_end + mc1_size;
+			if (offset < mc1_end) {
+				memtype = MEM_MC1;
+				memaddr = offset - mc0_end;
+			} else {
+				/* offset beyond the end of any memory */
+				goto err;
+			}
+		}
+	}
+
+	spin_lock(&adap->win0_lock);
+	ret = t4_memory_rw(adap, 0, memtype, memaddr, 32, tpte, T4_MEMORY_READ);
+	spin_unlock(&adap->win0_lock);
+	return ret;
+
+err:
+	dev_err(adap->pdev_dev, "stag %#x, offset %#x out of range\n",
+		stag, offset);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(cxgb4_read_tpte);
+
+u64 cxgb4_read_sge_timestamp(struct net_device *dev)
+{
+	u32 hi, lo;
+	struct adapter *adap;
+
+	adap = netdev2adap(dev);
+	lo = t4_read_reg(adap, SGE_TIMESTAMP_LO);
+	hi = GET_TSVAL(t4_read_reg(adap, SGE_TIMESTAMP_HI));
+
+	return ((u64)hi << 32) | (u64)lo;
+}
+EXPORT_SYMBOL(cxgb4_read_sge_timestamp);
+
 static struct pci_driver cxgb4_driver;
 
 static void check_neigh_update(struct neighbour *neigh)
@@ -3878,7 +4141,7 @@ void t4_db_full(struct adapter *adap)
 		notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
 		t4_set_reg_field(adap, SGE_INT_ENABLE3,
 				 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
-		queue_work(workq, &adap->db_full_task);
+		queue_work(adap->workq, &adap->db_full_task);
 	}
 }
 
@@ -3888,7 +4151,7 @@ void t4_db_dropped(struct adapter *adap)
 		disable_dbs(adap);
 		notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
 	}
-	queue_work(workq, &adap->db_drop_task);
+	queue_work(adap->workq, &adap->db_drop_task);
 }
 
 static void uld_attach(struct adapter *adap, unsigned int uld)
@@ -3898,6 +4161,7 @@ static void uld_attach(struct adapter *a
 	unsigned short i;
 
 	lli.pdev = adap->pdev;
+	lli.pf = adap->fn;
 	lli.l2t = adap->l2t;
 	lli.tids = &adap->tids;
 	lli.ports = adap->port;
@@ -3918,6 +4182,7 @@ static void uld_attach(struct adapter *a
 	lli.wr_cred = adap->params.ofldq_wr_cred;
 	lli.adapter_type = adap->params.chip;
 	lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
+	lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
 	lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
 			t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
 			(adap->fn * 4));
@@ -3932,8 +4197,12 @@ static void uld_attach(struct adapter *a
 	lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
 	lli.fw_vers = adap->params.fw_vers;
 	lli.dbfifo_int_thresh = dbfifo_int_thresh;
+	lli.sge_ingpadboundary = adap->sge.fl_align;
+	lli.sge_egrstatuspagesize = adap->sge.stat_len;
 	lli.sge_pktshift = adap->sge.pktshift;
 	lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
+	lli.max_ordird_qp = adap->params.max_ordird_qp;
+	lli.max_ird_adapter = adap->params.max_ird_adapter;
 	lli.ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl;
 
 	handle = ulds[uld].add(&lli);
@@ -4597,6 +4866,7 @@ static const struct net_device_ops cxgb4
 	.ndo_open             = cxgb_open,
 	.ndo_stop             = cxgb_close,
 	.ndo_start_xmit       = t4_eth_xmit,
+	.ndo_select_queue     =	cxgb_select_queue,
 	.ndo_get_stats64      = cxgb_get_stats,
 	.ndo_set_rx_mode      = cxgb_set_rxmode,
 	.ndo_set_mac_address  = cxgb_set_mac_addr,
@@ -4616,20 +4886,75 @@ void t4_fatal_err(struct adapter *adap)
 	dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
 }
 
+/* Return the specified PCI-E Configuration Space register from our Physical
+ * Function.  We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static u32 t4_read_pcie_cfg4(struct adapter *adap, int reg)
+{
+	struct fw_ldst_cmd ldst_cmd;
+	u32 val;
+	int ret;
+
+	/* Construct and send the Firmware LDST Command to retrieve the
+	 * specified PCI-E Configuration Space register.
+	 */
+	memset(&ldst_cmd, 0, sizeof(ldst_cmd));
+	ldst_cmd.op_to_addrspace =
+		htonl(FW_CMD_OP(FW_LDST_CMD) |
+		      FW_CMD_REQUEST |
+		      FW_CMD_READ |
+		      FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+	ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
+	ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
+	ldst_cmd.u.pcie.ctrl_to_fn =
+		(FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn));
+	ldst_cmd.u.pcie.r = reg;
+	ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
+			 &ldst_cmd);
+
+	/* If the LDST Command suucceeded, exctract the returned register
+	 * value.  Otherwise read it directly ourself.
+	 */
+	if (ret == 0)
+		val = ntohl(ldst_cmd.u.pcie.data[0]);
+	else
+		t4_hw_pci_read_cfg4(adap, reg, &val);
+
+	return val;
+}
+
 static void setup_memwin(struct adapter *adap)
 {
-	u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
+	u32 mem_win0_base, mem_win1_base, mem_win2_base, mem_win2_aperture;
 
-	bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
 	if (is_t4(adap->params.chip)) {
+		u32 bar0;
+
+		/* Truncation intentional: we only read the bottom 32-bits of
+		 * the 64-bit BAR0/BAR1 ...  We use the hardware backdoor
+		 * mechanism to read BAR0 instead of using
+		 * pci_resource_start() because we could be operating from
+		 * within a Virtual Machine which is trapping our accesses to
+		 * our Configuration Space and we need to set up the PCI-E
+		 * Memory Window decoders with the actual addresses which will
+		 * be coming across the PCI-E link.
+		 */
+		bar0 = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_0);
+		bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+		adap->t4_bar0 = bar0;
+
 		mem_win0_base = bar0 + MEMWIN0_BASE;
 		mem_win1_base = bar0 + MEMWIN1_BASE;
 		mem_win2_base = bar0 + MEMWIN2_BASE;
+		mem_win2_aperture = MEMWIN2_APERTURE;
 	} else {
 		/* For T5, only relative offset inside the PCIe BAR is passed */
 		mem_win0_base = MEMWIN0_BASE;
-		mem_win1_base = MEMWIN1_BASE_T5;
+		mem_win1_base = MEMWIN1_BASE;
 		mem_win2_base = MEMWIN2_BASE_T5;
+		mem_win2_aperture = MEMWIN2_APERTURE_T5;
 	}
 	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
 		     mem_win0_base | BIR(0) |
@@ -4639,16 +4964,19 @@ static void setup_memwin(struct adapter
 		     WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
 	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
 		     mem_win2_base | BIR(0) |
-		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
+		     WINDOW(ilog2(mem_win2_aperture) - 10));
+	t4_read_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
 }
 
 static void setup_memwin_rdma(struct adapter *adap)
 {
 	if (adap->vres.ocq.size) {
-		unsigned int start, sz_kb;
+		u32 start;
+		unsigned int sz_kb;
 
-		start = pci_resource_start(adap->pdev, 2) +
-			OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
+		start = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_2);
+		start &= PCI_BASE_ADDRESS_MEM_MASK;
+		start += OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
 		sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
 		t4_write_reg(adap,
 			     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
@@ -4861,7 +5189,7 @@ static int adap_init0_config(struct adap
 					      adapter->fn, 0, 1, params, val);
 			if (ret == 0) {
 				/*
-				 * For t4_memory_write() below addresses and
+				 * For t4_memory_rw() below addresses and
 				 * sizes have to be in terms of multiples of 4
 				 * bytes.  So, if the Configuration File isn't
 				 * a multiple of 4 bytes in length we'll have
@@ -4877,8 +5205,9 @@ static int adap_init0_config(struct adap
 				mtype = FW_PARAMS_PARAM_Y_GET(val[0]);
 				maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16;
 
-				ret = t4_memory_write(adapter, mtype, maddr,
-						      size, data);
+				spin_lock(&adapter->win0_lock);
+				ret = t4_memory_rw(adapter, 0, mtype, maddr,
+						   size, data, T4_MEMORY_WRITE);
 				if (ret == 0 && resid != 0) {
 					union {
 						__be32 word;
@@ -4889,10 +5218,12 @@ static int adap_init0_config(struct adap
 					last.word = data[size >> 2];
 					for (i = resid; i < 4; i++)
 						last.buf[i] = 0;
-					ret = t4_memory_write(adapter, mtype,
-							      maddr + size,
-							      4, &last.word);
+					ret = t4_memory_rw(adapter, 0, mtype,
+							   maddr + size,
+							   4, &last.word,
+							   T4_MEMORY_WRITE);
 				}
+				spin_unlock(&adapter->win0_lock);
 			}
 		}
 
@@ -5627,7 +5958,8 @@ static int adap_init0(struct adapter *ad
 		params[3] = FW_PARAM_PFVF(CQ_END);
 		params[4] = FW_PARAM_PFVF(OCQ_START);
 		params[5] = FW_PARAM_PFVF(OCQ_END);
-		ret = t4_query_params(adap, 0, 0, 0, 6, params, val);
+		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, params,
+				      val);
 		if (ret < 0)
 			goto bye;
 		adap->vres.qp.start = val[0];
@@ -5636,6 +5968,23 @@ static int adap_init0(struct adapter *ad
 		adap->vres.cq.size = val[3] - val[2] + 1;
 		adap->vres.ocq.start = val[4];
 		adap->vres.ocq.size = val[5] - val[4] + 1;
+
+		params[0] = FW_PARAM_DEV(MAXORDIRD_QP);
+		params[1] = FW_PARAM_DEV(MAXIRD_ADAPTER);
+		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params,
+				      val);
+		if (ret < 0) {
+			adap->params.max_ordird_qp = 8;
+			adap->params.max_ird_adapter = 32 * adap->tids.ntids;
+			ret = 0;
+		} else {
+			adap->params.max_ordird_qp = val[0];
+			adap->params.max_ird_adapter = val[1];
+		}
+		dev_info(adap->pdev_dev,
+			 "max_ordird_qp %d max_ird_adapter %d\n",
+			 adap->params.max_ordird_qp,
+			 adap->params.max_ird_adapter);
 	}
 	if (caps_cmd.iscsicaps) {
 		params[0] = FW_PARAM_PFVF(ISCSI_START);
@@ -5837,12 +6186,33 @@ static inline void init_rspq(struct adap
 static void cfg_queues(struct adapter *adap)
 {
 	struct sge *s = &adap->sge;
-	int i, q10g = 0, n10g = 0, qidx = 0;
+	int i, n10g = 0, qidx = 0;
+#ifndef CONFIG_CHELSIO_T4_DCB
+	int q10g = 0;
+#endif
 	int ciq_size;
 
 	for_each_port(adap, i)
 		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
+	 * own TX Queue in order to prevent Head-Of-Line Blocking.
+	 */
+	if (adap->params.nports * 8 > MAX_ETH_QSETS) {
+		dev_err(adap->pdev_dev, "MAX_ETH_QSETS=%d < %d!\n",
+			MAX_ETH_QSETS, adap->params.nports * 8);
+		BUG_ON(1);
+	}
 
+	for_each_port(adap, i) {
+		struct port_info *pi = adap2pinfo(adap, i);
+
+		pi->first_qset = qidx;
+		pi->nqsets = 8;
+		qidx += pi->nqsets;
+	}
+#else /* !CONFIG_CHELSIO_T4_DCB */
 	/*
 	 * We default to 1 queue per non-10G port and up to # of cores queues
 	 * per 10G port.
@@ -5859,6 +6229,7 @@ static void cfg_queues(struct adapter *a
 		pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
 		qidx += pi->nqsets;
 	}
+#endif /* !CONFIG_CHELSIO_T4_DCB */
 
 	s->ethqsets = qidx;
 	s->max_ethqsets = qidx;   /* MSI-X may lower it later */
@@ -5977,8 +6348,14 @@ static int enable_msix(struct adapter *a
 		/* need nchan for each possible ULD */
 		ofld_need = 3 * nchan;
 	}
+#ifdef CONFIG_CHELSIO_T4_DCB
+	/* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
+	 * each port.
+	 */
+	need = 8 * adap->params.nports + EXTRA_VECS + ofld_need;
+#else
 	need = adap->params.nports + EXTRA_VECS + ofld_need;
-
+#endif
 	want = pci_enable_msix_range(adap->pdev, entries, need, want);
 	if (want < 0)
 		return want;
@@ -6100,6 +6477,7 @@ static int init_one(struct pci_dev *pdev
 	struct port_info *pi;
 	bool highdma = false;
 	struct adapter *adapter = NULL;
+	void __iomem *regs;
 
 	printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
 
@@ -6110,32 +6488,41 @@ static int init_one(struct pci_dev *pdev
 		return err;
 	}
 
-	/* We control everything through one PF */
-	func = PCI_FUNC(pdev->devfn);
-	if (func != ent->driver_data) {
-		pci_save_state(pdev);        /* to restore SR-IOV later */
-		goto sriov;
-	}
-
 	err = pci_enable_device(pdev);
 	if (err) {
 		dev_err(&pdev->dev, "cannot enable PCI device\n");
 		goto out_release_regions;
 	}
 
+	regs = pci_ioremap_bar(pdev, 0);
+	if (!regs) {
+		dev_err(&pdev->dev, "cannot map device registers\n");
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+
+	/* We control everything through one PF */
+	func = SOURCEPF_GET(readl(regs + PL_WHOAMI));
+	if (func != ent->driver_data) {
+		iounmap(regs);
+		pci_disable_device(pdev);
+		pci_save_state(pdev);        /* to restore SR-IOV later */
+		goto sriov;
+	}
+
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
 		highdma = true;
 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 		if (err) {
 			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for "
 				"coherent allocations\n");
-			goto out_disable_device;
+			goto out_unmap_bar0;
 		}
 	} else {
 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (err) {
 			dev_err(&pdev->dev, "no usable DMA configuration\n");
-			goto out_disable_device;
+			goto out_unmap_bar0;
 		}
 	}
 
@@ -6147,19 +6534,19 @@ static int init_one(struct pci_dev *pdev
 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
 	if (!adapter) {
 		err = -ENOMEM;
-		goto out_disable_device;
+		goto out_unmap_bar0;
 	}
 
-	/* PCI device has been enabled */
-	adapter->flags |= DEV_ENABLED;
-
-	adapter->regs = pci_ioremap_bar(pdev, 0);
-	if (!adapter->regs) {
-		dev_err(&pdev->dev, "cannot map device registers\n");
+	adapter->workq = create_singlethread_workqueue("cxgb4");
+	if (!adapter->workq) {
 		err = -ENOMEM;
 		goto out_free_adapter;
 	}
 
+	/* PCI device has been enabled */
+	adapter->flags |= DEV_ENABLED;
+
+	adapter->regs = regs;
 	adapter->pdev = pdev;
 	adapter->pdev_dev = &pdev->dev;
 	adapter->mbox = func;
@@ -6176,7 +6563,8 @@ static int init_one(struct pci_dev *pdev
 
 	err = t4_prep_adapter(adapter);
 	if (err)
-		goto out_unmap_bar0;
+		goto out_free_adapter;
+
 
 	if (!is_t4(adapter->params.chip)) {
 		s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
@@ -6193,14 +6581,14 @@ static int init_one(struct pci_dev *pdev
 			dev_err(&pdev->dev,
 				"Incorrect number of egress queues per page\n");
 			err = -EINVAL;
-			goto out_unmap_bar0;
+			goto out_free_adapter;
 		}
 		adapter->bar2 = ioremap_wc(pci_resource_start(pdev, 2),
 		pci_resource_len(pdev, 2));
 		if (!adapter->bar2) {
 			dev_err(&pdev->dev, "cannot map device bar2 region\n");
 			err = -ENOMEM;
-			goto out_unmap_bar0;
+			goto out_free_adapter;
 		}
 	}
 
@@ -6241,6 +6629,10 @@ static int init_one(struct pci_dev *pdev
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
 		netdev->netdev_ops = &cxgb4_netdev_ops;
+#ifdef CONFIG_CHELSIO_T4_DCB
+		netdev->dcbnl_ops = &cxgb4_dcb_ops;
+		cxgb4_dcb_state_init(netdev);
+#endif
 		netdev->ethtool_ops = &cxgb_ethtool_ops;
 	}
 
@@ -6334,10 +6726,13 @@ sriov:
  out_unmap_bar:
 	if (!is_t4(adapter->params.chip))
 		iounmap(adapter->bar2);
- out_unmap_bar0:
-	iounmap(adapter->regs);
  out_free_adapter:
+	if (adapter->workq)
+		destroy_workqueue(adapter->workq);
+
 	kfree(adapter);
+ out_unmap_bar0:
+	iounmap(regs);
  out_disable_device:
 	pci_disable_pcie_error_reporting(pdev);
 	pci_disable_device(pdev);
@@ -6358,6 +6753,11 @@ static void remove_one(struct pci_dev *p
 	if (adapter) {
 		int i;
 
+		/* Tear down per-adapter Work Queue first since it can contain
+		 * references to our adapter data structure.
+		 */
+		destroy_workqueue(adapter->workq);
+
 		if (is_offload(adapter))
 			detach_ulds(adapter);
 
@@ -6365,8 +6765,7 @@ static void remove_one(struct pci_dev *p
 			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
 				unregister_netdev(adapter->port[i]);
 
-		if (adapter->debugfs_root)
-			debugfs_remove_recursive(adapter->debugfs_root);
+		debugfs_remove_recursive(adapter->debugfs_root);
 
 		/* If we allocated filters, free up state associated with any
 		 * valid filters ...
@@ -6411,20 +6810,14 @@ static int __init cxgb4_init_module(void
 {
 	int ret;
 
-	workq = create_singlethread_workqueue("cxgb4");
-	if (!workq)
-		return -ENOMEM;
-
 	/* Debugfs support is optional, just warn if this fails */
 	cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
 	if (!cxgb4_debugfs_root)
 		pr_warn("could not create debugfs entry, continuing\n");
 
 	ret = pci_register_driver(&cxgb4_driver);
-	if (ret < 0) {
+	if (ret < 0)
 		debugfs_remove(cxgb4_debugfs_root);
-		destroy_workqueue(workq);
-	}
 
 	register_inet6addr_notifier(&cxgb4_inet6addr_notifier);
 
@@ -6436,8 +6829,6 @@ static void __exit cxgb4_cleanup_module(
 	unregister_inet6addr_notifier(&cxgb4_inet6addr_notifier);
 	pci_unregister_driver(&cxgb4_driver);
 	debugfs_remove(cxgb4_debugfs_root);  /* NULL ok */
-	flush_workqueue(workq);
-	destroy_workqueue(workq);
 }
 
 module_init(cxgb4_init_module);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -172,6 +172,10 @@ int cxgb4_create_server_filter(const str
 			       unsigned char port, unsigned char mask);
 int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
 			       unsigned int queue, bool ipv6);
+int cxgb4_clip_get(const struct net_device *dev, const struct in6_addr *lip);
+int cxgb4_clip_release(const struct net_device *dev,
+		       const struct in6_addr *lip);
+
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
 	skb_set_queue_mapping(skb, (queue << 1) | prio);
@@ -243,6 +247,7 @@ struct cxgb4_lld_info {
 	unsigned char fw_api_ver;            /* FW API version */
 	unsigned int fw_vers;                /* FW version */
 	unsigned int iscsi_iolen;            /* iSCSI max I/O length */
+	unsigned int cclk_ps;                /* Core clock period in psec */
 	unsigned short udb_density;          /* # of user DB/page */
 	unsigned short ucq_density;          /* # of user CQs/page */
 	unsigned short filt_mode;            /* filter optional components */
@@ -251,10 +256,15 @@ struct cxgb4_lld_info {
 	void __iomem *gts_reg;               /* address of GTS register */
 	void __iomem *db_reg;                /* address of kernel doorbell */
 	int dbfifo_int_thresh;		     /* doorbell fifo int threshold */
+	unsigned int sge_ingpadboundary;     /* SGE ingress padding boundary */
+	unsigned int sge_egrstatuspagesize;  /* SGE egress status page size */
 	unsigned int sge_pktshift;           /* Padding between CPL and */
 					     /*	packet data */
+	unsigned int pf;		     /* Physical Function we're using */
 	bool enable_fw_ofld_conn;            /* Enable connection through fw */
 					     /* WR */
+	unsigned int max_ordird_qp;          /* Max ORD/IRD depth per RDMA QP */
+	unsigned int max_ird_adapter;        /* Max IRD memory per adapter */
 	bool ulptx_memwrite_dsgl;            /* use of T5 DSGL allowed */
 };
 
@@ -291,5 +301,7 @@ int cxgb4_sync_txq_pidx(struct net_devic
 int cxgb4_flush_eq_cache(struct net_device *dev);
 void cxgb4_disable_db_coalescing(struct net_device *dev);
 void cxgb4_enable_db_coalescing(struct net_device *dev);
+int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte);
+u64 cxgb4_read_sge_timestamp(struct net_device *dev);
 
 #endif  /* !__CXGB4_OFLD_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/l2t.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,3 +5,4 @@
 obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
 
 cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o
+cxgb4-$(CONFIG_CHELSIO_T4_DCB) +=  cxgb4_dcb.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -2303,7 +2303,8 @@ int t4_sge_alloc_eth_txq(struct adapter
 			    FW_EQ_ETH_CMD_PFN(adap->fn) | FW_EQ_ETH_CMD_VFN(0));
 	c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC |
 				 FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c));
-	c.viid_pkd = htonl(FW_EQ_ETH_CMD_VIID(pi->viid));
+	c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE |
+			   FW_EQ_ETH_CMD_VIID(pi->viid));
 	c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) |
 				   FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) |
 				   FW_EQ_ETH_CMD_FETCHRO(1) |
@@ -2480,6 +2481,22 @@ static void free_rspq_fl(struct adapter
 }
 
 /**
+ *      t4_free_ofld_rxqs - free a block of consecutive Rx queues
+ *      @adap: the adapter
+ *      @n: number of queues
+ *      @q: pointer to first queue
+ *
+ *      Release the resources of a consecutive block of offload Rx queues.
+ */
+void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q)
+{
+	for ( ; n; n--, q++)
+		if (q->rspq.desc)
+			free_rspq_fl(adap, &q->rspq,
+				     q->fl.size ? &q->fl : NULL);
+}
+
+/**
  *	t4_free_sge_resources - free SGE resources
  *	@adap: the adapter
  *
@@ -2490,12 +2507,12 @@ void t4_free_sge_resources(struct adapte
 	int i;
 	struct sge_eth_rxq *eq = adap->sge.ethrxq;
 	struct sge_eth_txq *etq = adap->sge.ethtxq;
-	struct sge_ofld_rxq *oq = adap->sge.ofldrxq;
 
 	/* clean up Ethernet Tx/Rx queues */
 	for (i = 0; i < adap->sge.ethqsets; i++, eq++, etq++) {
 		if (eq->rspq.desc)
-			free_rspq_fl(adap, &eq->rspq, &eq->fl);
+			free_rspq_fl(adap, &eq->rspq,
+				     eq->fl.size ? &eq->fl : NULL);
 		if (etq->q.desc) {
 			t4_eth_eq_free(adap, adap->fn, adap->fn, 0,
 				       etq->q.cntxt_id);
@@ -2506,18 +2523,9 @@ void t4_free_sge_resources(struct adapte
 	}
 
 	/* clean up RDMA and iSCSI Rx queues */
-	for (i = 0; i < adap->sge.ofldqsets; i++, oq++) {
-		if (oq->rspq.desc)
-			free_rspq_fl(adap, &oq->rspq, &oq->fl);
-	}
-	for (i = 0, oq = adap->sge.rdmarxq; i < adap->sge.rdmaqs; i++, oq++) {
-		if (oq->rspq.desc)
-			free_rspq_fl(adap, &oq->rspq, &oq->fl);
-	}
-	for (i = 0, oq = adap->sge.rdmaciq; i < adap->sge.rdmaciqs; i++, oq++) {
-		if (oq->rspq.desc)
-			free_rspq_fl(adap, &oq->rspq, &oq->fl);
-	}
+	t4_free_ofld_rxqs(adap, adap->sge.ofldqsets, adap->sge.ofldrxq);
+	t4_free_ofld_rxqs(adap, adap->sge.rdmaqs, adap->sge.rdmarxq);
+	t4_free_ofld_rxqs(adap, adap->sge.rdmaciqs, adap->sge.rdmaciq);
 
 	/* clean up offload Tx queues */
 	for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2009-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -46,9 +46,11 @@ enum fw_retval {
 	FW_EFAULT		= 14,	/* bad address; fw bad */
 	FW_EBUSY		= 16,	/* resource busy */
 	FW_EEXIST		= 17,	/* file exists */
+	FW_ENODEV		= 19,	/* no such device */
 	FW_EINVAL		= 22,	/* invalid argument */
 	FW_ENOSPC		= 28,	/* no space left on device */
 	FW_ENOSYS		= 38,	/* functionality not implemented */
+	FW_ENODATA		= 61,	/* no data available */
 	FW_EPROTO		= 71,	/* protocol error */
 	FW_EADDRINUSE		= 98,	/* address already in use */
 	FW_EADDRNOTAVAIL	= 99,	/* cannot assigned requested address */
@@ -932,6 +934,8 @@ enum fw_params_param_dev {
 	FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
 	FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
 	FW_PARAMS_PARAM_DEV_CF = 0x0D,
+	FW_PARAMS_PARAM_DEV_MAXORDIRD_QP = 0x13, /* max supported QP IRD/ORD */
+	FW_PARAMS_PARAM_DEV_MAXIRD_ADAPTER = 0x14, /* max supported adap IRD */
 	FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
 };
 
@@ -989,6 +993,7 @@ enum fw_params_param_dmaq {
 	FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10,
 	FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11,
 	FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12,
+	FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13,
 };
 
 #define FW_PARAMS_MNEM(x)      ((x) << 24)
@@ -1222,6 +1227,7 @@ struct fw_eq_eth_cmd {
 #define FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << 16)
 #define FW_EQ_ETH_CMD_EQSIZE(x) ((x) << 0)
 
+#define FW_EQ_ETH_CMD_AUTOEQUEQE (1U << 30)
 #define FW_EQ_ETH_CMD_VIID(x) ((x) << 16)
 
 struct fw_eq_ctrl_cmd {
@@ -1422,6 +1428,7 @@ struct fw_vi_enable_cmd {
 #define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0)
 #define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31)
 #define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30)
+#define FW_VI_ENABLE_CMD_DCB_INFO(x) ((x) << 28)
 #define FW_VI_ENABLE_CMD_LED (1U << 29)
 
 /* VI VF stats offset definitions */
@@ -1594,6 +1601,9 @@ enum fw_port_action {
 	FW_PORT_ACTION_GET_PORT_INFO	= 0x0003,
 	FW_PORT_ACTION_L2_PPP_CFG	= 0x0004,
 	FW_PORT_ACTION_L2_DCB_CFG	= 0x0005,
+	FW_PORT_ACTION_DCB_READ_TRANS	= 0x0006,
+	FW_PORT_ACTION_DCB_READ_RECV	= 0x0007,
+	FW_PORT_ACTION_DCB_READ_DET	= 0x0008,
 	FW_PORT_ACTION_LOW_PWR_TO_NORMAL = 0x0010,
 	FW_PORT_ACTION_L1_LOW_PWR_EN	= 0x0011,
 	FW_PORT_ACTION_L2_WOL_MODE_EN	= 0x0012,
@@ -1620,6 +1630,14 @@ enum fw_port_l2cfg_ctlbf {
 	FW_PORT_L2_CTLBF_TXIPG	= 0x20
 };
 
+enum fw_port_dcb_versions {
+	FW_PORT_DCB_VER_UNKNOWN,
+	FW_PORT_DCB_VER_CEE1D0,
+	FW_PORT_DCB_VER_CEE1D01,
+	FW_PORT_DCB_VER_IEEE,
+	FW_PORT_DCB_VER_AUTO = 7
+};
+
 enum fw_port_dcb_cfg {
 	FW_PORT_DCB_CFG_PG	= 0x01,
 	FW_PORT_DCB_CFG_PFC	= 0x02,
@@ -1637,6 +1655,14 @@ enum fw_port_dcb_type {
 	FW_PORT_DCB_TYPE_PRIORATE	= 0x02,
 	FW_PORT_DCB_TYPE_PFC		= 0x03,
 	FW_PORT_DCB_TYPE_APP_ID		= 0x04,
+	FW_PORT_DCB_TYPE_CONTROL	= 0x05,
+};
+
+enum fw_port_dcb_feature_state {
+	FW_PORT_DCB_FEATURE_STATE_PENDING = 0x0,
+	FW_PORT_DCB_FEATURE_STATE_SUCCESS = 0x1,
+	FW_PORT_DCB_FEATURE_STATE_ERROR	= 0x2,
+	FW_PORT_DCB_FEATURE_STATE_TIMEOUT = 0x3,
 };
 
 struct fw_port_cmd {
@@ -1648,9 +1674,11 @@ struct fw_port_cmd {
 			__be32 r;
 		} l1cfg;
 		struct fw_port_l2cfg {
-			__be16 ctlbf_to_ivlan0;
+			__u8   ctlbf;
+			__u8   ovlan3_to_ivlan0;
 			__be16 ivlantype;
-			__be32 txipg_pkd;
+			__be16 txipg_force_pinfo;
+			__be16 mtu;
 			__be16 ovlan0mask;
 			__be16 ovlan0type;
 			__be16 ovlan1mask;
@@ -1666,24 +1694,61 @@ struct fw_port_cmd {
 			__be16 acap;
 			__be16 mtu;
 			__u8   cbllen;
-			__u8   r9;
-			__be32 r10;
-			__be64 r11;
+			__u8   auxlinfo;
+			__u8   dcbxdis_pkd;
+			__u8   r8_lo[3];
+			__be64 r9;
 		} info;
-		struct fw_port_ppp {
-			__be32 pppen_to_ncsich;
-			__be32 r11;
-		} ppp;
-		struct fw_port_dcb {
-			__be16 cfg;
-			u8 up_map;
-			u8 sf_cfgrc;
-			__be16 prot_ix;
-			u8 pe7_to_pe0;
-			u8 numTCPFCs;
-			__be32 pgid0_to_pgid7;
-			__be32 numTCs_oui;
-			u8 pgpc[8];
+		struct fw_port_diags {
+			__u8   diagop;
+			__u8   r[3];
+			__be32 diagval;
+		} diags;
+		union fw_port_dcb {
+			struct fw_port_dcb_pgid {
+				__u8   type;
+				__u8   apply_pkd;
+				__u8   r10_lo[2];
+				__be32 pgid;
+				__be64 r11;
+			} pgid;
+			struct fw_port_dcb_pgrate {
+				__u8   type;
+				__u8   apply_pkd;
+				__u8   r10_lo[5];
+				__u8   num_tcs_supported;
+				__u8   pgrate[8];
+				__u8   tsa[8];
+			} pgrate;
+			struct fw_port_dcb_priorate {
+				__u8   type;
+				__u8   apply_pkd;
+				__u8   r10_lo[6];
+				__u8   strict_priorate[8];
+			} priorate;
+			struct fw_port_dcb_pfc {
+				__u8   type;
+				__u8   pfcen;
+				__u8   r10[5];
+				__u8   max_pfc_tcs;
+				__be64 r11;
+			} pfc;
+			struct fw_port_app_priority {
+				__u8   type;
+				__u8   r10[2];
+				__u8   idx;
+				__u8   user_prio_map;
+				__u8   sel_field;
+				__be16 protocolid;
+				__be64 r12;
+			} app_priority;
+			struct fw_port_dcb_control {
+				__u8   type;
+				__u8   all_syncd_pkd;
+				__be16 dcb_version_to_app_state;
+				__be32 r11;
+				__be64 r12;
+			} control;
 		} dcb;
 	} u;
 };
@@ -1720,6 +1785,11 @@ struct fw_port_cmd {
 #define FW_PORT_CMD_MODTYPE_MASK 0x1f
 #define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK)
 
+#define FW_PORT_CMD_DCBXDIS (1U << 7)
+#define FW_PORT_CMD_APPLY (1U <<  7)
+#define FW_PORT_CMD_ALL_SYNCD (1U << 7)
+#define FW_PORT_CMD_DCB_VERSION_GET(x) (((x) >> 8) & 0xf)
+
 #define FW_PORT_CMD_PPPEN(x) ((x) << 31)
 #define FW_PORT_CMD_TPSRC(x) ((x) << 28)
 #define FW_PORT_CMD_NCSISRC(x) ((x) << 24)
@@ -2158,6 +2228,10 @@ struct fw_debug_cmd {
 #define FW_PCIE_FW_MASTER(x)     ((x) << FW_PCIE_FW_MASTER_SHIFT)
 #define FW_PCIE_FW_MASTER_GET(x) (((x) >> FW_PCIE_FW_MASTER_SHIFT) & \
 				 FW_PCIE_FW_MASTER_MASK)
+#define FW_PCIE_FW_EVAL_MASK   0x7
+#define FW_PCIE_FW_EVAL_SHIFT  24
+#define FW_PCIE_FW_EVAL_GET(x) (((x) >> FW_PCIE_FW_EVAL_SHIFT) & \
+				 FW_PCIE_FW_EVAL_MASK)
 
 struct fw_hdr {
 	u8 ver;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -144,6 +144,58 @@ void t4_write_indirect(struct adapter *a
 }
 
 /*
+ * Read a 32-bit PCI Configuration Space register via the PCI-E backdoor
+ * mechanism.  This guarantees that we get the real value even if we're
+ * operating within a Virtual Machine and the Hypervisor is trapping our
+ * Configuration Space accesses.
+ */
+void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
+{
+	u32 req = ENABLE | FUNCTION(adap->fn) | reg;
+
+	if (is_t4(adap->params.chip))
+		req |= F_LOCALCFG;
+
+	t4_write_reg(adap, PCIE_CFG_SPACE_REQ, req);
+	*val = t4_read_reg(adap, PCIE_CFG_SPACE_DATA);
+
+	/* Reset ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
+	 * Configuration Space read.  (None of the other fields matter when
+	 * ENABLE is 0 so a simple register write is easier than a
+	 * read-modify-write via t4_set_reg_field().)
+	 */
+	t4_write_reg(adap, PCIE_CFG_SPACE_REQ, 0);
+}
+
+/*
+ * t4_report_fw_error - report firmware error
+ * @adap: the adapter
+ *
+ * The adapter firmware can indicate error conditions to the host.
+ * If the firmware has indicated an error, print out the reason for
+ * the firmware error.
+ */
+static void t4_report_fw_error(struct adapter *adap)
+{
+	static const char *const reason[] = {
+		"Crash",                        /* PCIE_FW_EVAL_CRASH */
+		"During Device Preparation",    /* PCIE_FW_EVAL_PREP */
+		"During Device Configuration",  /* PCIE_FW_EVAL_CONF */
+		"During Device Initialization", /* PCIE_FW_EVAL_INIT */
+		"Unexpected Event",             /* PCIE_FW_EVAL_UNEXPECTEDEVENT */
+		"Insufficient Airflow",         /* PCIE_FW_EVAL_OVERHEAT */
+		"Device Shutdown",              /* PCIE_FW_EVAL_DEVICESHUTDOWN */
+		"Reserved",                     /* reserved */
+	};
+	u32 pcie_fw;
+
+	pcie_fw = t4_read_reg(adap, MA_PCIE_FW);
+	if (pcie_fw & FW_PCIE_FW_ERR)
+		dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n",
+			reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]);
+}
+
+/*
  * Get the reply to a mailbox command and store it in @rpl in big-endian order.
  */
 static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
@@ -276,6 +328,7 @@ int t4_wr_mbox_meat(struct adapter *adap
 	dump_mbox(adap, mbox, data_reg);
 	dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
 		*(const u8 *)cmd, mbox);
+	t4_report_fw_error(adap);
 	return -ETIMEDOUT;
 }
 
@@ -389,78 +442,41 @@ int t4_edc_read(struct adapter *adap, in
 	return 0;
 }
 
-/*
- *	t4_mem_win_rw - read/write memory through PCIE memory window
- *	@adap: the adapter
- *	@addr: address of first byte requested
- *	@data: MEMWIN0_APERTURE bytes of data containing the requested address
- *	@dir: direction of transfer 1 => read, 0 => write
- *
- *	Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
- *	MEMWIN0_APERTURE-byte-aligned address that covers the requested
- *	address @addr.
- */
-static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
-{
-	int i;
-	u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
-
-	/*
-	 * Setup offset into PCIE memory window.  Address must be a
-	 * MEMWIN0_APERTURE-byte-aligned address.  (Read back MA register to
-	 * ensure that changes propagate before we attempt to use the new
-	 * values.)
-	 */
-	t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
-		     (addr & ~(MEMWIN0_APERTURE - 1)) | win_pf);
-	t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
-
-	/* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
-	for (i = 0; i < MEMWIN0_APERTURE; i = i+0x4) {
-		if (dir)
-			*data++ = (__force __be32) t4_read_reg(adap,
-							(MEMWIN0_BASE + i));
-		else
-			t4_write_reg(adap, (MEMWIN0_BASE + i),
-				     (__force u32) *data++);
-	}
-
-	return 0;
-}
-
 /**
  *	t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
  *	@adap: the adapter
+ *	@win: PCI-E Memory Window to use
  *	@mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
  *	@addr: address within indicated memory type
  *	@len: amount of memory to transfer
  *	@buf: host memory buffer
- *	@dir: direction of transfer 1 => read, 0 => write
+ *	@dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)
  *
  *	Reads/writes an [almost] arbitrary memory region in the firmware: the
- *	firmware memory address, length and host buffer must be aligned on
- *	32-bit boudaries.  The memory is transferred as a raw byte sequence
- *	from/to the firmware's memory.  If this memory contains data
- *	structures which contain multi-byte integers, it's the callers
- *	responsibility to perform appropriate byte order conversions.
+ *	firmware memory address and host buffer must be aligned on 32-bit
+ *	boudaries; the length may be arbitrary.  The memory is transferred as
+ *	a raw byte sequence from/to the firmware's memory.  If this memory
+ *	contains data structures which contain multi-byte integers, it's the
+ *	caller's responsibility to perform appropriate byte order conversions.
  */
-static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
-			__be32 *buf, int dir)
+int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
+		 u32 len, __be32 *buf, int dir)
 {
-	u32 pos, start, end, offset, memoffset;
-	u32 edc_size, mc_size;
-	int ret = 0;
-	__be32 *data;
+	u32 pos, offset, resid, memoffset;
+	u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base;
 
-	/*
-	 * Argument sanity checks ...
+	/* Argument sanity checks ...
 	 */
-	if ((addr & 0x3) || (len & 0x3))
+	if (addr & 0x3)
 		return -EINVAL;
 
-	data = vmalloc(MEMWIN0_APERTURE);
-	if (!data)
-		return -ENOMEM;
+	/* It's convenient to be able to handle lengths which aren't a
+	 * multiple of 32-bits because we often end up transferring files to
+	 * the firmware.  So we'll handle that by normalizing the length here
+	 * and then handling any residual transfer at the end.
+	 */
+	resid = len & 0x3;
+	len -= resid;
 
 	/* Offset into the region of memory which is being accessed
 	 * MEM_EDC0 = 0
@@ -481,72 +497,105 @@ static int t4_memory_rw(struct adapter *
 	/* Determine the PCIE_MEM_ACCESS_OFFSET */
 	addr = addr + memoffset;
 
-	/*
-	 * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
-	 * at a time so we need to round down the start and round up the end.
-	 * We'll start copying out of the first line at (addr - start) a word
-	 * at a time.
+	/* Each PCI-E Memory Window is programmed with a window size -- or
+	 * "aperture" -- which controls the granularity of its mapping onto
+	 * adapter memory.  We need to grab that aperture in order to know
+	 * how to use the specified window.  The window is also programmed
+	 * with the base address of the Memory Window in BAR0's address
+	 * space.  For T4 this is an absolute PCI-E Bus Address.  For T5
+	 * the address is relative to BAR0.
 	 */
-	start = addr & ~(MEMWIN0_APERTURE-1);
-	end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
-	offset = (addr - start)/sizeof(__be32);
+	mem_reg = t4_read_reg(adap,
+			      PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN,
+						  win));
+	mem_aperture = 1 << (GET_WINDOW(mem_reg) + 10);
+	mem_base = GET_PCIEOFST(mem_reg) << 10;
+	if (is_t4(adap->params.chip))
+		mem_base -= adap->t4_bar0;
+	win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
-	for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
+	/* Calculate our initial PCI-E Memory Window Position and Offset into
+	 * that Window.
+	 */
+	pos = addr & ~(mem_aperture-1);
+	offset = addr - pos;
 
-		/*
-		 * If we're writing, copy the data from the caller's memory
-		 * buffer
-		 */
-		if (!dir) {
-			/*
-			 * If we're doing a partial write, then we need to do
-			 * a read-modify-write ...
-			 */
-			if (offset || len < MEMWIN0_APERTURE) {
-				ret = t4_mem_win_rw(adap, pos, data, 1);
-				if (ret)
-					break;
-			}
-			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
-			       len > 0) {
-				data[offset++] = *buf++;
-				len -= sizeof(__be32);
-			}
-		}
+	/* Set up initial PCI-E Memory Window to cover the start of our
+	 * transfer.  (Read it back to ensure that changes propagate before we
+	 * attempt to use the new value.)
+	 */
+	t4_write_reg(adap,
+		     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win),
+		     pos | win_pf);
+	t4_read_reg(adap,
+		    PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
 
-		/*
-		 * Transfer a block of memory and bail if there's an error.
-		 */
-		ret = t4_mem_win_rw(adap, pos, data, dir);
-		if (ret)
-			break;
+	/* Transfer data to/from the adapter as long as there's an integral
+	 * number of 32-bit transfers to complete.
+	 */
+	while (len > 0) {
+		if (dir == T4_MEMORY_READ)
+			*buf++ = (__force __be32) t4_read_reg(adap,
+							mem_base + offset);
+		else
+			t4_write_reg(adap, mem_base + offset,
+				     (__force u32) *buf++);
+		offset += sizeof(__be32);
+		len -= sizeof(__be32);
 
-		/*
-		 * If we're reading, copy the data into the caller's memory
-		 * buffer.
+		/* If we've reached the end of our current window aperture,
+		 * move the PCI-E Memory Window on to the next.  Note that
+		 * doing this here after "len" may be 0 allows us to set up
+		 * the PCI-E Memory Window for a possible final residual
+		 * transfer below ...
 		 */
-		if (dir)
-			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
-			       len > 0) {
-				*buf++ = data[offset++];
-				len -= sizeof(__be32);
-			}
+		if (offset == mem_aperture) {
+			pos += mem_aperture;
+			offset = 0;
+			t4_write_reg(adap,
+				     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET,
+							 win), pos | win_pf);
+			t4_read_reg(adap,
+				    PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET,
+							win));
+		}
 	}
 
-	vfree(data);
-	return ret;
-}
+	/* If the original transfer had a length which wasn't a multiple of
+	 * 32-bits, now's where we need to finish off the transfer of the
+	 * residual amount.  The PCI-E Memory Window has already been moved
+	 * above (if necessary) to cover this final transfer.
+	 */
+	if (resid) {
+		union {
+			__be32 word;
+			char byte[4];
+		} last;
+		unsigned char *bp;
+		int i;
 
-int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
-		    __be32 *buf)
-{
-	return t4_memory_rw(adap, mtype, addr, len, buf, 0);
+		if (dir == T4_MEMORY_READ) {
+			last.word = (__force __be32) t4_read_reg(adap,
+							mem_base + offset);
+			for (bp = (unsigned char *)buf, i = resid; i < 4; i++)
+				bp[i] = last.byte[i];
+		} else {
+			last.word = *buf;
+			for (i = resid; i < 4; i++)
+				last.byte[i] = 0;
+			t4_write_reg(adap, mem_base + offset,
+				     (__force u32) last.word);
+		}
+	}
+
+	return 0;
 }
 
 #define EEPROM_STAT_ADDR   0x7bfc
 #define VPD_BASE           0x400
 #define VPD_BASE_OLD       0
 #define VPD_LEN            1024
+#define CHELSIO_VPD_UNIQUE_ID 0x82
 
 /**
  *	t4_seeprom_wp - enable/disable EEPROM write protection
@@ -584,7 +633,14 @@ int get_vpd_params(struct adapter *adapt
 	ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd);
 	if (ret < 0)
 		goto out;
-	addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
+
+	/* The VPD shall have a unique identifier specified by the PCI SIG.
+	 * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
+	 * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
+	 * is expected to automatically put this entry at the
+	 * beginning of the VPD.
+	 */
+	addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
 
 	ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd);
 	if (ret < 0)
@@ -648,6 +704,7 @@ int get_vpd_params(struct adapter *adapt
 	i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
 	memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
 	strim(p->sn);
+	i = pci_vpd_info_field_size(vpd + pn - PCI_VPD_INFO_FLD_HDR_SIZE);
 	memcpy(p->pn, vpd + pn, min(i, PN_LEN));
 	strim(p->pn);
 
@@ -1375,15 +1432,18 @@ static void pcie_intr_handler(struct ada
 
 	int fat;
 
-	fat = t4_handle_intr_status(adapter,
-				    PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-				    sysbus_intr_info) +
-	      t4_handle_intr_status(adapter,
-				    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-				    pcie_port_intr_info) +
-	      t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
-				    is_t4(adapter->params.chip) ?
-				    pcie_intr_info : t5_pcie_intr_info);
+	if (is_t4(adapter->params.chip))
+		fat = t4_handle_intr_status(adapter,
+					    PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+					    sysbus_intr_info) +
+			t4_handle_intr_status(adapter,
+					      PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+					      pcie_port_intr_info) +
+			t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+					      pcie_intr_info);
+	else
+		fat = t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+					    t5_pcie_intr_info);
 
 	if (fat)
 		t4_fatal_err(adapter);
@@ -1502,6 +1562,9 @@ static void cim_intr_handler(struct adap
 
 	int fat;
 
+	if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR)
+		t4_report_fw_error(adapter);
+
 	fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE,
 				    cim_intr_info) +
 	      t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE,
@@ -1700,16 +1763,24 @@ static void mps_intr_handler(struct adap
  */
 static void mem_intr_handler(struct adapter *adapter, int idx)
 {
-	static const char name[3][5] = { "EDC0", "EDC1", "MC" };
+	static const char name[4][7] = { "EDC0", "EDC1", "MC/MC0", "MC1" };
 
 	unsigned int addr, cnt_addr, v;
 
 	if (idx <= MEM_EDC1) {
 		addr = EDC_REG(EDC_INT_CAUSE, idx);
 		cnt_addr = EDC_REG(EDC_ECC_STATUS, idx);
+	} else if (idx == MEM_MC) {
+		if (is_t4(adapter->params.chip)) {
+			addr = MC_INT_CAUSE;
+			cnt_addr = MC_ECC_STATUS;
+		} else {
+			addr = MC_P_INT_CAUSE;
+			cnt_addr = MC_P_ECC_STATUS;
+		}
 	} else {
-		addr = MC_INT_CAUSE;
-		cnt_addr = MC_ECC_STATUS;
+		addr = MC_REG(MC_P_INT_CAUSE, 1);
+		cnt_addr = MC_REG(MC_P_ECC_STATUS, 1);
 	}
 
 	v = t4_read_reg(adapter, addr) & MEM_INT_MASK;
@@ -1741,10 +1812,16 @@ static void ma_intr_handler(struct adapt
 {
 	u32 v, status = t4_read_reg(adap, MA_INT_CAUSE);
 
-	if (status & MEM_PERR_INT_CAUSE)
+	if (status & MEM_PERR_INT_CAUSE) {
 		dev_alert(adap->pdev_dev,
 			  "MA parity error, parity status %#x\n",
 			  t4_read_reg(adap, MA_PARITY_ERROR_STATUS));
+		if (is_t5(adap->params.chip))
+			dev_alert(adap->pdev_dev,
+				  "MA parity error, parity status %#x\n",
+				  t4_read_reg(adap,
+					      MA_PARITY_ERROR_STATUS2));
+	}
 	if (status & MEM_WRAP_INT_CAUSE) {
 		v = t4_read_reg(adap, MA_INT_WRAP_STATUS);
 		dev_alert(adap->pdev_dev, "MA address wrap-around error by "
@@ -1873,6 +1950,8 @@ int t4_slow_intr_handler(struct adapter
 		pcie_intr_handler(adapter);
 	if (cause & MC)
 		mem_intr_handler(adapter, MEM_MC);
+	if (!is_t4(adapter->params.chip) && (cause & MC1))
+		mem_intr_handler(adapter, MEM_MC1);
 	if (cause & EDC0)
 		mem_intr_handler(adapter, MEM_EDC0);
 	if (cause & EDC1)
@@ -2505,39 +2584,6 @@ int t4_fwaddrspace_write(struct adapter
 }
 
 /**
- *     t4_mem_win_read_len - read memory through PCIE memory window
- *     @adap: the adapter
- *     @addr: address of first byte requested aligned on 32b.
- *     @data: len bytes to hold the data read
- *     @len: amount of data to read from window.  Must be <=
- *            MEMWIN0_APERATURE after adjusting for 16B for T4 and
- *            128B for T5 alignment requirements of the the memory window.
- *
- *     Read len bytes of data from MC starting at @addr.
- */
-int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
-{
-	int i, off;
-	u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
-
-	/* Align on a 2KB boundary.
-	 */
-	off = addr & MEMWIN0_APERTURE;
-	if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
-		return -EINVAL;
-
-	t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
-		     (addr & ~MEMWIN0_APERTURE) | win_pf);
-	t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
-
-	for (i = 0; i < len; i += 4)
-		*data++ = (__force __be32) t4_read_reg(adap,
-						(MEMWIN0_BASE + off + i));
-
-	return 0;
-}
-
-/**
  *	t4_mdio_rd - read a PHY register through MDIO
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
@@ -2737,12 +2783,16 @@ retry:
 	/*
 	 * Issue the HELLO command to the firmware.  If it's not successful
 	 * but indicates that we got a "busy" or "timeout" condition, retry
-	 * the HELLO until we exhaust our retry limit.
+	 * the HELLO until we exhaust our retry limit.  If we do exceed our
+	 * retry limit, check to see if the firmware left us any error
+	 * information and report that if so.
 	 */
 	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
 	if (ret < 0) {
 		if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
 			goto retry;
+		if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR)
+			t4_report_fw_error(adap);
 		return ret;
 	}
 
@@ -3175,6 +3225,46 @@ int t4_query_params(struct adapter *adap
 }
 
 /**
+ *      t4_set_params_nosleep - sets FW or device parameters
+ *      @adap: the adapter
+ *      @mbox: mailbox to use for the FW command
+ *      @pf: the PF
+ *      @vf: the VF
+ *      @nparams: the number of parameters
+ *      @params: the parameter names
+ *      @val: the parameter values
+ *
+ *	 Does not ever sleep
+ *      Sets the value of FW or device parameters.  Up to 7 parameters can be
+ *      specified at once.
+ */
+int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
+			  unsigned int pf, unsigned int vf,
+			  unsigned int nparams, const u32 *params,
+			  const u32 *val)
+{
+	struct fw_params_cmd c;
+	__be32 *p = &c.param[0].mnem;
+
+	if (nparams > 7)
+		return -EINVAL;
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
+				FW_CMD_REQUEST | FW_CMD_WRITE |
+				FW_PARAMS_CMD_PFN(pf) |
+				FW_PARAMS_CMD_VFN(vf));
+	c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+
+	while (nparams--) {
+		*p++ = cpu_to_be32(*params++);
+		*p++ = cpu_to_be32(*val++);
+	}
+
+	return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/**
  *	t4_set_params - sets FW or device parameters
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
@@ -3499,6 +3589,33 @@ int t4_set_addr_hash(struct adapter *ada
 }
 
 /**
+ *      t4_enable_vi_params - enable/disable a virtual interface
+ *      @adap: the adapter
+ *      @mbox: mailbox to use for the FW command
+ *      @viid: the VI id
+ *      @rx_en: 1=enable Rx, 0=disable Rx
+ *      @tx_en: 1=enable Tx, 0=disable Tx
+ *      @dcb_en: 1=enable delivery of Data Center Bridging messages.
+ *
+ *      Enables/disables a virtual interface.  Note that setting DCB Enable
+ *      only makes sense when enabling a Virtual Interface ...
+ */
+int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
+			unsigned int viid, bool rx_en, bool tx_en, bool dcb_en)
+{
+	struct fw_vi_enable_cmd c;
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
+			     FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
+
+	c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
+			       FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c) |
+			       FW_VI_ENABLE_CMD_DCB_INFO(dcb_en));
+	return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/**
  *	t4_enable_vi - enable/disable a virtual interface
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
@@ -3511,14 +3628,7 @@ int t4_set_addr_hash(struct adapter *ada
 int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		 bool rx_en, bool tx_en)
 {
-	struct fw_vi_enable_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
-	c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
-			       FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+	return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0);
 }
 
 /**
@@ -3686,6 +3796,7 @@ int t4_handle_fw_rpl(struct adapter *ada
 			lc->link_ok = link_ok;
 			lc->speed = speed;
 			lc->fc = fc;
+			lc->supported = be16_to_cpu(p->u.info.pcap);
 			t4_os_link_changed(adap, port, link_ok);
 		}
 		if (mod != pi->mod_type) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -75,6 +75,7 @@ enum {
 	CPL_RX_DATA_DDP       = 0x42,
 	CPL_PASS_ACCEPT_REQ   = 0x44,
 	CPL_TRACE_PKT_T5      = 0x48,
+	CPL_RX_ISCSI_DDP      = 0x49,
 
 	CPL_RDMA_READ_REQ     = 0x60,
 
@@ -86,6 +87,7 @@ enum {
 	CPL_SGE_EGR_UPDATE    = 0xA5,
 
 	CPL_TRACE_PKT         = 0xB0,
+	CPL_ISCSI_DATA	      = 0xB2,
 
 	CPL_FW4_MSG           = 0xC0,
 	CPL_FW4_PLD           = 0xC1,
@@ -270,12 +272,15 @@ struct cpl_pass_accept_rpl {
 #define RX_COALESCE_VALID(x) ((x) << 11)
 #define RX_COALESCE(x)       ((x) << 12)
 #define PACE(x)	      ((x) << 16)
+#define RX_FC_VALID	     ((1U) << 19)
+#define RX_FC_DISABLE	     ((1U) << 20)
 #define TX_QUEUE(x)          ((x) << 23)
 #define RX_CHANNEL(x)        ((x) << 26)
 #define CCTRL_ECN(x)         ((x) << 27)
 #define WND_SCALE_EN(x)      ((x) << 28)
 #define TSTAMPS_EN(x)        ((x) << 29)
 #define SACK_EN(x)           ((x) << 30)
+#define T5_OPT_2_VALID	     ((1U) << 31)
 	__be64 opt0;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Chelsio T4 Ethernet driver for Linux.
  *
- * Copyright (c) 2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -251,6 +251,12 @@
 #define V_NOCOALESCE(x) ((x) << S_NOCOALESCE)
 #define F_NOCOALESCE    V_NOCOALESCE(1U)
 
+#define SGE_TIMESTAMP_LO 0x1098
+#define SGE_TIMESTAMP_HI 0x109c
+#define S_TSVAL    0
+#define M_TSVAL    0xfffffffU
+#define GET_TSVAL(x) (((x) >> S_TSVAL) & M_TSVAL)
+
 #define SGE_TIMER_VALUE_0_AND_1 0x10b8
 #define  TIMERVALUE0_MASK   0xffff0000U
 #define  TIMERVALUE0_SHIFT  16
@@ -387,6 +393,8 @@
 #define  MSTGRPPERR      0x00000001U
 
 #define PCIE_NONFAT_ERR 0x3010
+#define PCIE_CFG_SPACE_REQ 0x3060
+#define PCIE_CFG_SPACE_DATA 0x3064
 #define PCIE_MEM_ACCESS_BASE_WIN 0x3068
 #define S_PCIEOFST       10
 #define M_PCIEOFST       0x3fffffU
@@ -398,7 +406,11 @@
 #define  WINDOW_MASK     0x000000ffU
 #define  WINDOW_SHIFT    0
 #define  WINDOW(x)       ((x) << WINDOW_SHIFT)
+#define  GET_WINDOW(x)	 (((x) >> WINDOW_SHIFT) & WINDOW_MASK)
 #define PCIE_MEM_ACCESS_OFFSET 0x306c
+#define ENABLE	(1U << 30)
+#define FUNCTION(x) ((x) << 12)
+#define F_LOCALCFG    (1U << 28)
 
 #define S_PFNUM    0
 #define V_PFNUM(x) ((x) << S_PFNUM)
@@ -436,11 +448,13 @@
 #define  TDUE 0x00010000U
 
 #define MC_INT_CAUSE 0x7518
+#define MC_P_INT_CAUSE 0x41318
 #define  ECC_UE_INT_CAUSE 0x00000004U
 #define  ECC_CE_INT_CAUSE 0x00000002U
 #define  PERR_INT_CAUSE   0x00000001U
 
 #define MC_ECC_STATUS 0x751c
+#define MC_P_ECC_STATUS 0x4131c
 #define  ECC_CECNT_MASK   0xffff0000U
 #define  ECC_CECNT_SHIFT  16
 #define  ECC_CECNT(x)     ((x) << ECC_CECNT_SHIFT)
@@ -497,6 +511,7 @@
 #define  MEM_WRAP_CLIENT_NUM_GET(x) (((x) & MEM_WRAP_CLIENT_NUM_MASK) >> MEM_WRAP_CLIENT_NUM_SHIFT)
 #define MA_PCIE_FW 0x30b8
 #define MA_PARITY_ERROR_STATUS 0x77f4
+#define MA_PARITY_ERROR_STATUS2 0x7804
 
 #define MA_EXT_MEMORY1_BAR 0x7808
 #define EDC_0_BASE_ADDR 0x7900
@@ -945,6 +960,7 @@
 #define  TRCMULTIFILTER     0x00000001U
 
 #define MPS_TRC_RSS_CONTROL 0x9808
+#define MPS_T5_TRC_RSS_CONTROL 0xa00c
 #define  RSSCONTROL_MASK    0x00ff0000U
 #define  RSSCONTROL_SHIFT   16
 #define  RSSCONTROL(x)      ((x) << RSSCONTROL_SHIFT)
@@ -1089,6 +1105,7 @@
 #define  I2CM       0x00000002U
 #define  CIM        0x00000001U
 
+#define MC1 0x31
 #define PL_INT_ENABLE 0x19410
 #define PL_INT_MAP0 0x19414
 #define PL_RST 0x19428
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -2876,24 +2876,24 @@ static void cxgb4vf_pci_shutdown(struct
 	if (!adapter)
 		return;
 
-	/*
-	 * Disable all Virtual Interfaces.  This will shut down the
+	/* Disable all Virtual Interfaces.  This will shut down the
 	 * delivery of all ingress packets into the chip for these
 	 * Virtual Interfaces.
 	 */
-	for_each_port(adapter, pidx) {
-		struct net_device *netdev;
-		struct port_info *pi;
-
-		if (!test_bit(pidx, &adapter->registered_device_map))
-			continue;
-
-		netdev = adapter->port[pidx];
-		if (!netdev)
-			continue;
+	for_each_port(adapter, pidx)
+		if (test_bit(pidx, &adapter->registered_device_map))
+			unregister_netdev(adapter->port[pidx]);
 
-		pi = netdev_priv(netdev);
-		t4vf_enable_vi(adapter, pi->viid, false, false);
+	/* Free up all Queues which will prevent further DMA and
+	 * Interrupts allowing various internal pathways to drain.
+	 */
+	t4vf_sge_stop(adapter);
+	if (adapter->flags & USING_MSIX) {
+		pci_disable_msix(adapter->pdev);
+		adapter->flags &= ~USING_MSIX;
+	} else if (adapter->flags & USING_MSI) {
+		pci_disable_msi(adapter->pdev);
+		adapter->flags &= ~USING_MSI;
 	}
 
 	/*
@@ -2901,6 +2901,7 @@ static void cxgb4vf_pci_shutdown(struct
 	 * Interrupts allowing various internal pathways to drain.
 	 */
 	t4vf_free_sge_resources(adapter);
+	pci_set_drvdata(pdev, NULL);
 }
 
 /*
@@ -2909,7 +2910,7 @@ static void cxgb4vf_pci_shutdown(struct
 #define CH_DEVICE(devid, idx) \
 	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
 
-static DEFINE_PCI_DEVICE_TABLE(cxgb4vf_pci_tbl) = {
+static const struct pci_device_id cxgb4vf_pci_tbl[] = {
 	CH_DEVICE(0xb000, 0),	/* PE10K FPGA */
 	CH_DEVICE(0x4800, 0),	/* T440-dbg */
 	CH_DEVICE(0x4801, 0),	/* T420-cr */
@@ -2924,6 +2925,15 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4vf_p
 	CH_DEVICE(0x480a, 0),   /* T404-bt */
 	CH_DEVICE(0x480d, 0),   /* T480-cr */
 	CH_DEVICE(0x480e, 0),   /* T440-lp-cr */
+	CH_DEVICE(0x4880, 0),
+	CH_DEVICE(0x4880, 1),
+	CH_DEVICE(0x4880, 2),
+	CH_DEVICE(0x4880, 3),
+	CH_DEVICE(0x4880, 4),
+	CH_DEVICE(0x4880, 5),
+	CH_DEVICE(0x4880, 6),
+	CH_DEVICE(0x4880, 7),
+	CH_DEVICE(0x4880, 8),
 	CH_DEVICE(0x5800, 0),	/* T580-dbg */
 	CH_DEVICE(0x5801, 0),	/* T520-cr */
 	CH_DEVICE(0x5802, 0),	/* T522-cr */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4vf/sge.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/cxgb4vf/sge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/cxgb4vf/sge.c	2014-09-28 17:29:07.000000000 -0400
@@ -2250,7 +2250,8 @@ int t4vf_sge_alloc_eth_txq(struct adapte
 	cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC |
 					 FW_EQ_ETH_CMD_EQSTART |
 					 FW_LEN16(cmd));
-	cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_VIID(pi->viid));
+	cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE |
+				   FW_EQ_ETH_CMD_VIID(pi->viid));
 	cmd.fetchszm_to_iqid =
 		cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE(SGE_HOSTFCMODE_STPG) |
 			    FW_EQ_ETH_CMD_PCIECHN(pi->port_id) |
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/chelsio/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/chelsio/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -86,6 +86,17 @@ config CHELSIO_T4
 	  To compile this driver as a module choose M here; the module
 	  will be called cxgb4.
 
+config CHELSIO_T4_DCB
+	bool "Data Center Bridging (DCB) Support for Chelsio T4/T5 cards"
+	default n
+	depends on CHELSIO_T4 && DCB
+	---help---
+	  Enable DCB support through rtNetlink interface.
+	  Say Y here if you want to enable Data Center Bridging (DCB) support
+	  in the driver.
+
+	  If unsure, say N.
+
 config CHELSIO_T4VF
 	tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support"
 	depends on PCI
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cirrus/cs89x0.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cirrus/cs89x0.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cirrus/cs89x0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cirrus/cs89x0.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,6 @@ struct net_local {
 	int force;		/* force various values; see FORCE* above. */
 	spinlock_t lock;
 	void __iomem *virt_addr;/* CS89x0 virtual address. */
-	unsigned long size;	/* Length of CS89x0 memory region. */
 #if ALLOW_DMA
 	int use_dma;		/* Flag: we're using dma */
 	int dma;		/* DMA channel */
@@ -1854,41 +1853,29 @@ static int __init cs89x0_platform_probe(
 
 	lp = netdev_priv(dev);
 
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dev->irq = platform_get_irq(pdev, 0);
-	if (mem_res == NULL || dev->irq <= 0) {
-		dev_warn(&dev->dev, "memory/interrupt resource missing\n");
+	if (dev->irq <= 0) {
+		dev_warn(&dev->dev, "interrupt resource missing\n");
 		err = -ENXIO;
 		goto free;
 	}
 
-	lp->size = resource_size(mem_res);
-	if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
-		dev_warn(&dev->dev, "request_mem_region() failed\n");
-		err = -EBUSY;
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	virt_addr = devm_ioremap_resource(&pdev->dev, mem_res);
+	if (IS_ERR(virt_addr)) {
+		err = PTR_ERR(virt_addr);
 		goto free;
 	}
 
-	virt_addr = ioremap(mem_res->start, lp->size);
-	if (!virt_addr) {
-		dev_warn(&dev->dev, "ioremap() failed\n");
-		err = -ENOMEM;
-		goto release;
-	}
-
 	err = cs89x0_probe1(dev, virt_addr, 0);
 	if (err) {
 		dev_warn(&dev->dev, "no cs8900 or cs8920 detected\n");
-		goto unmap;
+		goto free;
 	}
 
 	platform_set_drvdata(pdev, dev);
 	return 0;
 
-unmap:
-	iounmap(virt_addr);
-release:
-	release_mem_region(mem_res->start, lp->size);
 free:
 	free_netdev(dev);
 	return err;
@@ -1897,17 +1884,12 @@ free:
 static int cs89x0_platform_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
-	struct net_local *lp = netdev_priv(dev);
-	struct resource *mem_res;
 
 	/* This platform_get_resource() call will not return NULL, because
 	 * the same call in cs89x0_platform_probe() has returned a non NULL
 	 * value.
 	 */
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	unregister_netdev(dev);
-	iounmap(lp->virt_addr);
-	release_mem_region(mem_res->start, lp->size);
 	free_netdev(dev);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_api.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_api.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_api.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_api.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,13 +34,13 @@ int enic_api_devcmd_proxy_by_index(struc
 	struct vnic_dev *vdev = enic->vdev;
 
 	spin_lock(&enic->enic_api_lock);
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 
 	vnic_dev_cmd_proxy_by_index_start(vdev, vf);
 	err = vnic_dev_cmd(vdev, cmd, a0, a1, wait);
 	vnic_dev_cmd_proxy_end(vdev);
 
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 	spin_unlock(&enic->enic_api_lock);
 
 	return err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,284 @@
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_link.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <net/flow_keys.h>
+#include "enic_res.h"
+#include "enic_clsf.h"
+
+/* enic_addfltr_5t - Add ipv4 5tuple filter
+ *	@enic: enic struct of vnic
+ *	@keys: flow_keys of ipv4 5tuple
+ *	@rq: rq number to steer to
+ *
+ * This function returns filter_id(hardware_id) of the filter
+ * added. In case of error it returns an negative number.
+ */
+int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
+{
+	int res;
+	struct filter data;
+
+	switch (keys->ip_proto) {
+	case IPPROTO_TCP:
+		data.u.ipv4.protocol = PROTO_TCP;
+		break;
+	case IPPROTO_UDP:
+		data.u.ipv4.protocol = PROTO_UDP;
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	};
+	data.type = FILTER_IPV4_5TUPLE;
+	data.u.ipv4.src_addr = ntohl(keys->src);
+	data.u.ipv4.dst_addr = ntohl(keys->dst);
+	data.u.ipv4.src_port = ntohs(keys->port16[0]);
+	data.u.ipv4.dst_port = ntohs(keys->port16[1]);
+	data.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
+
+	spin_lock_bh(&enic->devcmd_lock);
+	res = vnic_dev_classifier(enic->vdev, CLSF_ADD, &rq, &data);
+	spin_unlock_bh(&enic->devcmd_lock);
+	res = (res == 0) ? rq : res;
+
+	return res;
+}
+
+/* enic_delfltr - Delete clsf filter
+ *	@enic: enic struct of vnic
+ *	@filter_id: filter_is(hardware_id) of filter to be deleted
+ *
+ * This function returns zero in case of success, negative number incase of
+ * error.
+ */
+int enic_delfltr(struct enic *enic, u16 filter_id)
+{
+	int ret;
+
+	spin_lock_bh(&enic->devcmd_lock);
+	ret = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL);
+	spin_unlock_bh(&enic->devcmd_lock);
+
+	return ret;
+}
+
+/* enic_rfs_flw_tbl_init - initialize enic->rfs_h members
+ *	@enic: enic data
+ */
+void enic_rfs_flw_tbl_init(struct enic *enic)
+{
+	int i;
+
+	spin_lock_init(&enic->rfs_h.lock);
+	for (i = 0; i <= ENIC_RFS_FLW_MASK; i++)
+		INIT_HLIST_HEAD(&enic->rfs_h.ht_head[i]);
+	enic->rfs_h.max = enic->config.num_arfs;
+	enic->rfs_h.free = enic->rfs_h.max;
+	enic->rfs_h.toclean = 0;
+	enic_rfs_timer_start(enic);
+}
+
+void enic_rfs_flw_tbl_free(struct enic *enic)
+{
+	int i;
+
+	enic_rfs_timer_stop(enic);
+	spin_lock(&enic->rfs_h.lock);
+	enic->rfs_h.free = 0;
+	for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
+		struct hlist_head *hhead;
+		struct hlist_node *tmp;
+		struct enic_rfs_fltr_node *n;
+
+		hhead = &enic->rfs_h.ht_head[i];
+		hlist_for_each_entry_safe(n, tmp, hhead, node) {
+			enic_delfltr(enic, n->fltr_id);
+			hlist_del(&n->node);
+			kfree(n);
+		}
+	}
+	spin_unlock(&enic->rfs_h.lock);
+}
+
+struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id)
+{
+	int i;
+
+	for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
+		struct hlist_head *hhead;
+		struct hlist_node *tmp;
+		struct enic_rfs_fltr_node *n;
+
+		hhead = &enic->rfs_h.ht_head[i];
+		hlist_for_each_entry_safe(n, tmp, hhead, node)
+			if (n->fltr_id == fltr_id)
+				return n;
+	}
+
+	return NULL;
+}
+
+#ifdef CONFIG_RFS_ACCEL
+void enic_flow_may_expire(unsigned long data)
+{
+	struct enic *enic = (struct enic *)data;
+	bool res;
+	int j;
+
+	spin_lock(&enic->rfs_h.lock);
+	for (j = 0; j < ENIC_CLSF_EXPIRE_COUNT; j++) {
+		struct hlist_head *hhead;
+		struct hlist_node *tmp;
+		struct enic_rfs_fltr_node *n;
+
+		hhead = &enic->rfs_h.ht_head[enic->rfs_h.toclean++];
+		hlist_for_each_entry_safe(n, tmp, hhead, node) {
+			res = rps_may_expire_flow(enic->netdev, n->rq_id,
+						  n->flow_id, n->fltr_id);
+			if (res) {
+				res = enic_delfltr(enic, n->fltr_id);
+				if (unlikely(res))
+					continue;
+				hlist_del(&n->node);
+				kfree(n);
+				enic->rfs_h.free++;
+			}
+		}
+	}
+	spin_unlock(&enic->rfs_h.lock);
+	mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
+}
+
+static struct enic_rfs_fltr_node *htbl_key_search(struct hlist_head *h,
+						  struct flow_keys *k)
+{
+	struct enic_rfs_fltr_node *tpos;
+
+	hlist_for_each_entry(tpos, h, node)
+		if (tpos->keys.src == k->src &&
+		    tpos->keys.dst == k->dst &&
+		    tpos->keys.ports == k->ports &&
+		    tpos->keys.ip_proto == k->ip_proto &&
+		    tpos->keys.n_proto == k->n_proto)
+			return tpos;
+	return NULL;
+}
+
+int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+		       u16 rxq_index, u32 flow_id)
+{
+	struct flow_keys keys;
+	struct enic_rfs_fltr_node *n;
+	struct enic *enic;
+	u16 tbl_idx;
+	int res, i;
+
+	enic = netdev_priv(dev);
+	res = skb_flow_dissect(skb, &keys);
+	if (!res || keys.n_proto != htons(ETH_P_IP) ||
+	    (keys.ip_proto != IPPROTO_TCP && keys.ip_proto != IPPROTO_UDP))
+		return -EPROTONOSUPPORT;
+
+	tbl_idx = skb_get_hash_raw(skb) & ENIC_RFS_FLW_MASK;
+	spin_lock(&enic->rfs_h.lock);
+	n = htbl_key_search(&enic->rfs_h.ht_head[tbl_idx], &keys);
+
+	if (n) { /* entry already present  */
+		if (rxq_index == n->rq_id) {
+			res = -EEXIST;
+			goto ret_unlock;
+		}
+
+		/* desired rq changed for the flow, we need to delete
+		 * old fltr and add new one
+		 *
+		 * The moment we delete the fltr, the upcoming pkts
+		 * are put it default rq based on rss. When we add
+		 * new filter, upcoming pkts are put in desired queue.
+		 * This could cause ooo pkts.
+		 *
+		 * Lets 1st try adding new fltr and then del old one.
+		 */
+		i = --enic->rfs_h.free;
+		/* clsf tbl is full, we have to del old fltr first*/
+		if (unlikely(i < 0)) {
+			enic->rfs_h.free++;
+			res = enic_delfltr(enic, n->fltr_id);
+			if (unlikely(res < 0))
+				goto ret_unlock;
+			res = enic_addfltr_5t(enic, &keys, rxq_index);
+			if (res < 0) {
+				hlist_del(&n->node);
+				enic->rfs_h.free++;
+				goto ret_unlock;
+			}
+		/* add new fltr 1st then del old fltr */
+		} else {
+			int ret;
+
+			res = enic_addfltr_5t(enic, &keys, rxq_index);
+			if (res < 0) {
+				enic->rfs_h.free++;
+				goto ret_unlock;
+			}
+			ret = enic_delfltr(enic, n->fltr_id);
+			/* deleting old fltr failed. Add old fltr to list.
+			 * enic_flow_may_expire() will try to delete it later.
+			 */
+			if (unlikely(ret < 0)) {
+				struct enic_rfs_fltr_node *d;
+				struct hlist_head *head;
+
+				head = &enic->rfs_h.ht_head[tbl_idx];
+				d = kmalloc(sizeof(*d), GFP_ATOMIC);
+				if (d) {
+					d->fltr_id = n->fltr_id;
+					INIT_HLIST_NODE(&d->node);
+					hlist_add_head(&d->node, head);
+				}
+			} else {
+				enic->rfs_h.free++;
+			}
+		}
+		n->rq_id = rxq_index;
+		n->fltr_id = res;
+		n->flow_id = flow_id;
+	/* entry not present */
+	} else {
+		i = --enic->rfs_h.free;
+		if (i <= 0) {
+			enic->rfs_h.free++;
+			res = -EBUSY;
+			goto ret_unlock;
+		}
+
+		n = kmalloc(sizeof(*n), GFP_ATOMIC);
+		if (!n) {
+			res = -ENOMEM;
+			enic->rfs_h.free++;
+			goto ret_unlock;
+		}
+
+		res = enic_addfltr_5t(enic, &keys, rxq_index);
+		if (res < 0) {
+			kfree(n);
+			enic->rfs_h.free++;
+			goto ret_unlock;
+		}
+		n->rq_id = rxq_index;
+		n->fltr_id = res;
+		n->flow_id = flow_id;
+		n->keys = keys;
+		INIT_HLIST_NODE(&n->node);
+		hlist_add_head(&n->node, &enic->rfs_h.ht_head[tbl_idx]);
+	}
+
+ret_unlock:
+	spin_unlock(&enic->rfs_h.lock);
+	return res;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_clsf.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,37 @@
+#ifndef _ENIC_CLSF_H_
+#define _ENIC_CLSF_H_
+
+#include "vnic_dev.h"
+#include "enic.h"
+
+#define ENIC_CLSF_EXPIRE_COUNT 128
+
+int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq);
+int enic_delfltr(struct enic *enic, u16 filter_id);
+void enic_rfs_flw_tbl_init(struct enic *enic);
+void enic_rfs_flw_tbl_free(struct enic *enic);
+struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id);
+
+#ifdef CONFIG_RFS_ACCEL
+int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+		       u16 rxq_index, u32 flow_id);
+void enic_flow_may_expire(unsigned long data);
+
+static inline void enic_rfs_timer_start(struct enic *enic)
+{
+	init_timer(&enic->rfs_h.rfs_may_expire);
+	enic->rfs_h.rfs_may_expire.function = enic_flow_may_expire;
+	enic->rfs_h.rfs_may_expire.data = (unsigned long)enic;
+	mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
+}
+
+static inline void enic_rfs_timer_stop(struct enic *enic)
+{
+	del_timer_sync(&enic->rfs_h.rfs_may_expire);
+}
+#else
+static inline void enic_rfs_timer_start(struct enic *enic) {}
+static inline void enic_rfs_timer_stop(struct enic *enic) {}
+#endif /* CONFIG_RFS_ACCEL */
+
+#endif /* _ENIC_CLSF_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_dev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_dev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,9 +29,9 @@ int enic_dev_fw_info(struct enic *enic,
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_fw_info(enic->vdev, fw_info);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -40,9 +40,9 @@ int enic_dev_stats_dump(struct enic *eni
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_stats_dump(enic->vdev, vstats);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -54,9 +54,9 @@ int enic_dev_add_station_addr(struct eni
 	if (!is_valid_ether_addr(enic->netdev->dev_addr))
 		return -EADDRNOTAVAIL;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -68,9 +68,9 @@ int enic_dev_del_station_addr(struct eni
 	if (!is_valid_ether_addr(enic->netdev->dev_addr))
 		return -EADDRNOTAVAIL;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -80,10 +80,10 @@ int enic_dev_packet_filter(struct enic *
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_packet_filter(enic->vdev, directed,
 		multicast, broadcast, promisc, allmulti);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -92,9 +92,9 @@ int enic_dev_add_addr(struct enic *enic,
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_add_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -103,9 +103,9 @@ int enic_dev_del_addr(struct enic *enic,
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_del_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -114,9 +114,9 @@ int enic_dev_notify_unset(struct enic *e
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_notify_unset(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -125,9 +125,9 @@ int enic_dev_hang_notify(struct enic *en
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_hang_notify(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -136,10 +136,10 @@ int enic_dev_set_ig_vlan_rewrite_mode(st
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
 		IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -148,9 +148,9 @@ int enic_dev_enable(struct enic *enic)
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_enable_wait(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -159,9 +159,9 @@ int enic_dev_disable(struct enic *enic)
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_disable(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -170,9 +170,9 @@ int enic_dev_intr_coal_timer_info(struct
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_intr_coal_timer_info(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -181,9 +181,9 @@ int enic_vnic_dev_deinit(struct enic *en
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_deinit(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -192,10 +192,10 @@ int enic_dev_init_prov2(struct enic *eni
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_init_prov2(enic->vdev,
 		(u8 *)vp, vic_provinfo_size(vp));
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -204,9 +204,9 @@ int enic_dev_deinit_done(struct enic *en
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_deinit_done(enic->vdev, status);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -217,9 +217,9 @@ int enic_vlan_rx_add_vid(struct net_devi
 	struct enic *enic = netdev_priv(netdev);
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = enic_add_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -230,9 +230,9 @@ int enic_vlan_rx_kill_vid(struct net_dev
 	struct enic *enic = netdev_priv(netdev);
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = enic_del_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -241,9 +241,9 @@ int enic_dev_enable2(struct enic *enic,
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_enable2(enic->vdev, active);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -252,9 +252,9 @@ int enic_dev_enable2_done(struct enic *e
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = vnic_dev_enable2_done(enic->vdev, status);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_dev.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_dev.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_dev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_dev.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
  */
 #define ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnicdevcmdfn, ...) \
 	do { \
-		spin_lock(&enic->devcmd_lock); \
+		spin_lock_bh(&enic->devcmd_lock); \
 		if (enic_is_valid_vf(enic, vf)) { \
 			vnic_dev_cmd_proxy_by_index_start(enic->vdev, vf); \
 			err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
@@ -36,7 +36,7 @@
 		} else { \
 			err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
 		} \
-		spin_unlock(&enic->devcmd_lock); \
+		spin_unlock_bh(&enic->devcmd_lock); \
 	} while (0)
 
 int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include "enic_res.h"
 #include "enic.h"
 #include "enic_dev.h"
+#include "enic_clsf.h"
 
 struct enic_stat {
 	char name[ETH_GSTRING_LEN];
@@ -231,7 +232,7 @@ static int enic_set_coalesce(struct net_
 		if (ecmd->use_adaptive_rx_coalesce	||
 		    ecmd->rx_coalesce_usecs_low		||
 		    ecmd->rx_coalesce_usecs_high)
-			return -EOPNOTSUPP;
+			return -EINVAL;
 
 		intr = enic_legacy_io_intr();
 		vnic_intr_coalescing_timer_set(&enic->intr[intr],
@@ -243,34 +244,29 @@ static int enic_set_coalesce(struct net_
 		if (ecmd->use_adaptive_rx_coalesce	||
 		    ecmd->rx_coalesce_usecs_low		||
 		    ecmd->rx_coalesce_usecs_high)
-			return -EOPNOTSUPP;
+			return -EINVAL;
 
 		vnic_intr_coalescing_timer_set(&enic->intr[0],
 			tx_coalesce_usecs);
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
+		if (ecmd->rx_coalesce_usecs_high &&
+		    (rx_coalesce_usecs_high <
+		     rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
+				return -EINVAL;
+
 		for (i = 0; i < enic->wq_count; i++) {
 			intr = enic_msix_wq_intr(enic, i);
 			vnic_intr_coalescing_timer_set(&enic->intr[intr],
 				tx_coalesce_usecs);
 		}
 
-		if (rxcoal->use_adaptive_rx_coalesce) {
-			if (!ecmd->use_adaptive_rx_coalesce) {
-				rxcoal->use_adaptive_rx_coalesce = 0;
-				enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
-			}
-		} else {
-			if (ecmd->use_adaptive_rx_coalesce)
-				rxcoal->use_adaptive_rx_coalesce = 1;
-			else
-				enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
-		}
+		rxcoal->use_adaptive_rx_coalesce =
+					!!ecmd->use_adaptive_rx_coalesce;
+		if (!rxcoal->use_adaptive_rx_coalesce)
+			enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
 
 		if (ecmd->rx_coalesce_usecs_high) {
-			if (rx_coalesce_usecs_high <
-			    (rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
-				return -EINVAL;
 			rxcoal->range_end = rx_coalesce_usecs_high;
 			rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
 			rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
@@ -287,6 +283,102 @@ static int enic_set_coalesce(struct net_
 	return 0;
 }
 
+static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd,
+			    u32 *rule_locs)
+{
+	int j, ret = 0, cnt = 0;
+
+	cmd->data = enic->rfs_h.max - enic->rfs_h.free;
+	for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) {
+		struct hlist_head *hhead;
+		struct hlist_node *tmp;
+		struct enic_rfs_fltr_node *n;
+
+		hhead = &enic->rfs_h.ht_head[j];
+		hlist_for_each_entry_safe(n, tmp, hhead, node) {
+			if (cnt == cmd->rule_cnt)
+				return -EMSGSIZE;
+			rule_locs[cnt] = n->fltr_id;
+			cnt++;
+		}
+	}
+	cmd->rule_cnt = cnt;
+
+	return ret;
+}
+
+static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
+{
+	struct ethtool_rx_flow_spec *fsp =
+				(struct ethtool_rx_flow_spec *)&cmd->fs;
+	struct enic_rfs_fltr_node *n;
+
+	n = htbl_fltr_search(enic, (u16)fsp->location);
+	if (!n)
+		return -EINVAL;
+	switch (n->keys.ip_proto) {
+	case IPPROTO_TCP:
+		fsp->flow_type = TCP_V4_FLOW;
+		break;
+	case IPPROTO_UDP:
+		fsp->flow_type = UDP_V4_FLOW;
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src;
+	fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
+
+	fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst;
+	fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
+
+	fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0];
+	fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
+
+	fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1];
+	fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
+
+	fsp->ring_cookie = n->rq_id;
+
+	return 0;
+}
+
+static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+			  u32 *rule_locs)
+{
+	struct enic *enic = netdev_priv(dev);
+	int ret = 0;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = enic->rq_count;
+		break;
+	case ETHTOOL_GRXCLSRLCNT:
+		spin_lock_bh(&enic->rfs_h.lock);
+		cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free;
+		cmd->data = enic->rfs_h.max;
+		spin_unlock_bh(&enic->rfs_h.lock);
+		break;
+	case ETHTOOL_GRXCLSRLALL:
+		spin_lock_bh(&enic->rfs_h.lock);
+		ret = enic_grxclsrlall(enic, cmd, rule_locs);
+		spin_unlock_bh(&enic->rfs_h.lock);
+		break;
+	case ETHTOOL_GRXCLSRULE:
+		spin_lock_bh(&enic->rfs_h.lock);
+		ret = enic_grxclsrule(enic, cmd);
+		spin_unlock_bh(&enic->rfs_h.lock);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
 static const struct ethtool_ops enic_ethtool_ops = {
 	.get_settings = enic_get_settings,
 	.get_drvinfo = enic_get_drvinfo,
@@ -298,6 +390,7 @@ static const struct ethtool_ops enic_eth
 	.get_ethtool_stats = enic_get_ethtool_stats,
 	.get_coalesce = enic_get_coalesce,
 	.set_coalesce = enic_set_coalesce,
+	.get_rxnfc = enic_get_rxnfc,
 };
 
 void enic_set_ethtool_ops(struct net_device *netdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.1.1.50"
+#define DRV_VERSION		"2.1.1.67"
 #define DRV_COPYRIGHT		"Copyright 2008-2013 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
@@ -99,6 +99,41 @@ struct enic_port_profile {
 	u8 mac_addr[ETH_ALEN];
 };
 
+/* enic_rfs_fltr_node - rfs filter node in hash table
+ *	@@keys: IPv4 5 tuple
+ *	@flow_id: flow_id of clsf filter provided by kernel
+ *	@fltr_id: filter id of clsf filter returned by adaptor
+ *	@rq_id: desired rq index
+ *	@node: hlist_node
+ */
+struct enic_rfs_fltr_node {
+	struct flow_keys keys;
+	u32 flow_id;
+	u16 fltr_id;
+	u16 rq_id;
+	struct hlist_node node;
+};
+
+/* enic_rfs_flw_tbl - rfs flow table
+ *	@max: Maximum number of filters vNIC supports
+ *	@free: Number of free filters available
+ *	@toclean: hash table index to clean next
+ *	@ht_head: hash table list head
+ *	@lock: spin lock
+ *	@rfs_may_expire: timer function for enic_rps_may_expire_flow
+ */
+struct enic_rfs_flw_tbl {
+	u16 max;
+	int free;
+
+#define ENIC_RFS_FLW_BITSHIFT	(10)
+#define ENIC_RFS_FLW_MASK	((1 << ENIC_RFS_FLW_BITSHIFT) - 1)
+	u16 toclean:ENIC_RFS_FLW_BITSHIFT;
+	struct hlist_head ht_head[1 << ENIC_RFS_FLW_BITSHIFT];
+	spinlock_t lock;
+	struct timer_list rfs_may_expire;
+};
+
 /* Per-instance private data structure */
 struct enic {
 	struct net_device *netdev;
@@ -140,7 +175,7 @@ struct enic {
 	unsigned int rq_count;
 	u64 rq_truncated_pkts;
 	u64 rq_bad_fcs;
-	struct napi_struct napi[ENIC_RQ_MAX];
+	struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX];
 
 	/* interrupt resource cache line section */
 	____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
@@ -150,6 +185,7 @@ struct enic {
 	/* completion queue cache line section */
 	____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
 	unsigned int cq_count;
+	struct enic_rfs_flw_tbl rfs_h;
 };
 
 static inline struct device *enic_get_dev(struct enic *enic)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,12 @@
 #include <linux/prefetch.h>
 #include <net/ip6_checksum.h>
 #include <linux/ktime.h>
+#ifdef CONFIG_RFS_ACCEL
+#include <linux/cpu_rmap.h>
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#include <net/busy_poll.h>
+#endif
 
 #include "cq_enet_desc.h"
 #include "vnic_dev.h"
@@ -49,6 +55,7 @@
 #include "enic.h"
 #include "enic_dev.h"
 #include "enic_pp.h"
+#include "enic_clsf.h"
 
 #define ENIC_NOTIFY_TIMER_PERIOD	(2 * HZ)
 #define WQ_ENET_MAX_DESC_LEN		(1 << WQ_ENET_LEN_BITS)
@@ -60,7 +67,7 @@
 #define PCI_DEVICE_ID_CISCO_VIC_ENET_VF      0x0071  /* enet SRIOV VF */
 
 /* Supported devices */
-static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
+static const struct pci_device_id enic_id_table[] = {
 	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
 	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
 	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
@@ -309,40 +316,15 @@ static irqreturn_t enic_isr_msi(int irq,
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t enic_isr_msix_rq(int irq, void *data)
+static irqreturn_t enic_isr_msix(int irq, void *data)
 {
 	struct napi_struct *napi = data;
 
-	/* schedule NAPI polling for RQ cleanup */
 	napi_schedule(napi);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t enic_isr_msix_wq(int irq, void *data)
-{
-	struct enic *enic = data;
-	unsigned int cq;
-	unsigned int intr;
-	unsigned int wq_work_to_do = -1; /* no limit */
-	unsigned int wq_work_done;
-	unsigned int wq_irq;
-
-	wq_irq = (u32)irq - enic->msix_entry[enic_msix_wq_intr(enic, 0)].vector;
-	cq = enic_cq_wq(enic, wq_irq);
-	intr = enic_msix_wq_intr(enic, wq_irq);
-
-	wq_work_done = vnic_cq_service(&enic->cq[cq],
-		wq_work_to_do, enic_wq_service, NULL);
-
-	vnic_intr_return_credits(&enic->intr[intr],
-		wq_work_done,
-		1 /* unmask intr */,
-		1 /* reset intr timer */);
-
-	return IRQ_HANDLED;
-}
-
 static irqreturn_t enic_isr_msix_err(int irq, void *data)
 {
 	struct enic *enic = data;
@@ -1049,10 +1031,12 @@ static void enic_rq_indicate_buf(struct
 		if (vlan_stripped)
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
 
-		if (netdev->features & NETIF_F_GRO)
-			napi_gro_receive(&enic->napi[q_number], skb);
-		else
+		skb_mark_napi_id(skb, &enic->napi[rq->index]);
+		if (enic_poll_busy_polling(rq) ||
+		    !(netdev->features & NETIF_F_GRO))
 			netif_receive_skb(skb);
+		else
+			napi_gro_receive(&enic->napi[q_number], skb);
 		if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
 			enic_intr_update_pkt_size(&cq->pkt_size_counter,
 						  bytes_written);
@@ -1089,16 +1073,22 @@ static int enic_poll(struct napi_struct
 	unsigned int  work_done, rq_work_done = 0, wq_work_done;
 	int err;
 
-	/* Service RQ (first) and WQ
-	 */
+	wq_work_done = vnic_cq_service(&enic->cq[cq_wq], wq_work_to_do,
+				       enic_wq_service, NULL);
+
+	if (!enic_poll_lock_napi(&enic->rq[cq_rq])) {
+		if (wq_work_done > 0)
+			vnic_intr_return_credits(&enic->intr[intr],
+						 wq_work_done,
+						 0 /* dont unmask intr */,
+						 0 /* dont reset intr timer */);
+		return rq_work_done;
+	}
 
 	if (budget > 0)
 		rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
 			rq_work_to_do, enic_rq_service, NULL);
 
-	wq_work_done = vnic_cq_service(&enic->cq[cq_wq],
-		wq_work_to_do, enic_wq_service, NULL);
-
 	/* Accumulate intr event credits for this polling
 	 * cycle.  An intr event is the completion of a
 	 * a WQ or RQ packet.
@@ -1130,6 +1120,7 @@ static int enic_poll(struct napi_struct
 		napi_complete(napi);
 		vnic_intr_unmask(&enic->intr[intr]);
 	}
+	enic_poll_unlock_napi(&enic->rq[cq_rq]);
 
 	return rq_work_done;
 }
@@ -1192,7 +1183,102 @@ static void enic_calc_int_moderation(str
 	pkt_size_counter->small_pkt_bytes_cnt = 0;
 }
 
-static int enic_poll_msix(struct napi_struct *napi, int budget)
+#ifdef CONFIG_RFS_ACCEL
+static void enic_free_rx_cpu_rmap(struct enic *enic)
+{
+	free_irq_cpu_rmap(enic->netdev->rx_cpu_rmap);
+	enic->netdev->rx_cpu_rmap = NULL;
+}
+
+static void enic_set_rx_cpu_rmap(struct enic *enic)
+{
+	int i, res;
+
+	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) {
+		enic->netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(enic->rq_count);
+		if (unlikely(!enic->netdev->rx_cpu_rmap))
+			return;
+		for (i = 0; i < enic->rq_count; i++) {
+			res = irq_cpu_rmap_add(enic->netdev->rx_cpu_rmap,
+					       enic->msix_entry[i].vector);
+			if (unlikely(res)) {
+				enic_free_rx_cpu_rmap(enic);
+				return;
+			}
+		}
+	}
+}
+
+#else
+
+static void enic_free_rx_cpu_rmap(struct enic *enic)
+{
+}
+
+static void enic_set_rx_cpu_rmap(struct enic *enic)
+{
+}
+
+#endif /* CONFIG_RFS_ACCEL */
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+int enic_busy_poll(struct napi_struct *napi)
+{
+	struct net_device *netdev = napi->dev;
+	struct enic *enic = netdev_priv(netdev);
+	unsigned int rq = (napi - &enic->napi[0]);
+	unsigned int cq = enic_cq_rq(enic, rq);
+	unsigned int intr = enic_msix_rq_intr(enic, rq);
+	unsigned int work_to_do = -1; /* clean all pkts possible */
+	unsigned int work_done;
+
+	if (!enic_poll_lock_poll(&enic->rq[rq]))
+		return LL_FLUSH_BUSY;
+	work_done = vnic_cq_service(&enic->cq[cq], work_to_do,
+				    enic_rq_service, NULL);
+
+	if (work_done > 0)
+		vnic_intr_return_credits(&enic->intr[intr],
+					 work_done, 0, 0);
+	vnic_rq_fill(&enic->rq[rq], enic_rq_alloc_buf);
+	if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
+		enic_calc_int_moderation(enic, &enic->rq[rq]);
+	enic_poll_unlock_poll(&enic->rq[rq]);
+
+	return work_done;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
+{
+	struct net_device *netdev = napi->dev;
+	struct enic *enic = netdev_priv(netdev);
+	unsigned int wq_index = (napi - &enic->napi[0]) - enic->rq_count;
+	struct vnic_wq *wq = &enic->wq[wq_index];
+	unsigned int cq;
+	unsigned int intr;
+	unsigned int wq_work_to_do = -1; /* clean all desc possible */
+	unsigned int wq_work_done;
+	unsigned int wq_irq;
+
+	wq_irq = wq->index;
+	cq = enic_cq_wq(enic, wq_irq);
+	intr = enic_msix_wq_intr(enic, wq_irq);
+	wq_work_done = vnic_cq_service(&enic->cq[cq], wq_work_to_do,
+				       enic_wq_service, NULL);
+
+	vnic_intr_return_credits(&enic->intr[intr], wq_work_done,
+				 0 /* don't unmask intr */,
+				 1 /* reset intr timer */);
+	if (!wq_work_done) {
+		napi_complete(napi);
+		vnic_intr_unmask(&enic->intr[intr]);
+	}
+
+	return 0;
+}
+
+static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
 {
 	struct net_device *netdev = napi->dev;
 	struct enic *enic = netdev_priv(netdev);
@@ -1203,6 +1289,8 @@ static int enic_poll_msix(struct napi_st
 	unsigned int work_done = 0;
 	int err;
 
+	if (!enic_poll_lock_napi(&enic->rq[rq]))
+		return work_done;
 	/* Service RQ
 	 */
 
@@ -1248,6 +1336,7 @@ static int enic_poll_msix(struct napi_st
 			enic_set_int_moderation(enic, &enic->rq[rq]);
 		vnic_intr_unmask(&enic->intr[intr]);
 	}
+	enic_poll_unlock_napi(&enic->rq[rq]);
 
 	return work_done;
 }
@@ -1267,6 +1356,7 @@ static void enic_free_intr(struct enic *
 	struct net_device *netdev = enic->netdev;
 	unsigned int i;
 
+	enic_free_rx_cpu_rmap(enic);
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	case VNIC_DEV_INTR_MODE_INTX:
 		free_irq(enic->pdev->irq, netdev);
@@ -1291,6 +1381,7 @@ static int enic_request_intr(struct enic
 	unsigned int i, intr;
 	int err = 0;
 
+	enic_set_rx_cpu_rmap(enic);
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 
 	case VNIC_DEV_INTR_MODE_INTX:
@@ -1312,17 +1403,19 @@ static int enic_request_intr(struct enic
 			snprintf(enic->msix[intr].devname,
 				sizeof(enic->msix[intr].devname),
 				"%.11s-rx-%d", netdev->name, i);
-			enic->msix[intr].isr = enic_isr_msix_rq;
+			enic->msix[intr].isr = enic_isr_msix;
 			enic->msix[intr].devid = &enic->napi[i];
 		}
 
 		for (i = 0; i < enic->wq_count; i++) {
+			int wq = enic_cq_wq(enic, i);
+
 			intr = enic_msix_wq_intr(enic, i);
 			snprintf(enic->msix[intr].devname,
 				sizeof(enic->msix[intr].devname),
 				"%.11s-tx-%d", netdev->name, i);
-			enic->msix[intr].isr = enic_isr_msix_wq;
-			enic->msix[intr].devid = enic;
+			enic->msix[intr].isr = enic_isr_msix;
+			enic->msix[intr].devid = &enic->napi[wq];
 		}
 
 		intr = enic_msix_err_intr(enic);
@@ -1421,7 +1514,7 @@ static int enic_dev_notify_set(struct en
 {
 	int err;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	case VNIC_DEV_INTR_MODE_INTX:
 		err = vnic_dev_notify_set(enic->vdev,
@@ -1435,7 +1528,7 @@ static int enic_dev_notify_set(struct en
 		err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
 		break;
 	}
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -1494,15 +1587,20 @@ static int enic_open(struct net_device *
 
 	netif_tx_wake_all_queues(netdev);
 
-	for (i = 0; i < enic->rq_count; i++)
+	for (i = 0; i < enic->rq_count; i++) {
+		enic_busy_poll_init_lock(&enic->rq[i]);
 		napi_enable(&enic->napi[i]);
-
+	}
+	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+		for (i = 0; i < enic->wq_count; i++)
+			napi_enable(&enic->napi[enic_cq_wq(enic, i)]);
 	enic_dev_enable(enic);
 
 	for (i = 0; i < enic->intr_count; i++)
 		vnic_intr_unmask(&enic->intr[i]);
 
 	enic_notify_timer_start(enic);
+	enic_rfs_flw_tbl_init(enic);
 
 	return 0;
 
@@ -1529,14 +1627,23 @@ static int enic_stop(struct net_device *
 	enic_synchronize_irqs(enic);
 
 	del_timer_sync(&enic->notify_timer);
+	enic_rfs_flw_tbl_free(enic);
 
 	enic_dev_disable(enic);
 
-	for (i = 0; i < enic->rq_count; i++)
+	local_bh_disable();
+	for (i = 0; i < enic->rq_count; i++) {
 		napi_disable(&enic->napi[i]);
+		while (!enic_poll_lock_napi(&enic->rq[i]))
+			mdelay(1);
+	}
+	local_bh_enable();
 
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
+	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+		for (i = 0; i < enic->wq_count; i++)
+			napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
 
 	if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
 		enic_dev_del_station_addr(enic);
@@ -1656,13 +1763,14 @@ static void enic_poll_controller(struct
 	case VNIC_DEV_INTR_MODE_MSIX:
 		for (i = 0; i < enic->rq_count; i++) {
 			intr = enic_msix_rq_intr(enic, i);
-			enic_isr_msix_rq(enic->msix_entry[intr].vector,
-				&enic->napi[i]);
+			enic_isr_msix(enic->msix_entry[intr].vector,
+				      &enic->napi[i]);
 		}
 
 		for (i = 0; i < enic->wq_count; i++) {
 			intr = enic_msix_wq_intr(enic, i);
-			enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+			enic_isr_msix(enic->msix_entry[intr].vector,
+				      &enic->napi[enic_cq_wq(enic, i)]);
 		}
 
 		break;
@@ -1758,11 +1866,11 @@ static int enic_set_rsskey(struct enic *
 
 	memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = enic_set_rss_key(enic,
 		rss_key_buf_pa,
 		sizeof(union vnic_rss_key));
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
 		rss_key_buf_va, rss_key_buf_pa);
@@ -1785,11 +1893,11 @@ static int enic_set_rsscpu(struct enic *
 	for (i = 0; i < (1 << rss_hash_bits); i++)
 		(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = enic_set_rss_cpu(enic,
 		rss_cpu_buf_pa,
 		sizeof(union vnic_rss_cpu));
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
 		rss_cpu_buf_va, rss_cpu_buf_pa);
@@ -1807,13 +1915,13 @@ static int enic_set_niccfg(struct enic *
 	/* Enable VLAN tag stripping.
 	*/
 
-	spin_lock(&enic->devcmd_lock);
+	spin_lock_bh(&enic->devcmd_lock);
 	err = enic_set_nic_cfg(enic,
 		rss_default_cpu, rss_hash_type,
 		rss_hash_bits, rss_base_cpu,
 		rss_enable, tso_ipid_split_en,
 		ig_vlan_strip_en);
-	spin_unlock(&enic->devcmd_lock);
+	spin_unlock_bh(&enic->devcmd_lock);
 
 	return err;
 }
@@ -2021,6 +2129,12 @@ static const struct net_device_ops enic_
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= enic_poll_controller,
 #endif
+#ifdef CONFIG_RFS_ACCEL
+	.ndo_rx_flow_steer	= enic_rx_flow_steer,
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= enic_busy_poll,
+#endif
 };
 
 static const struct net_device_ops enic_netdev_ops = {
@@ -2041,14 +2155,25 @@ static const struct net_device_ops enic_
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= enic_poll_controller,
 #endif
+#ifdef CONFIG_RFS_ACCEL
+	.ndo_rx_flow_steer	= enic_rx_flow_steer,
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= enic_busy_poll,
+#endif
 };
 
 static void enic_dev_deinit(struct enic *enic)
 {
 	unsigned int i;
 
-	for (i = 0; i < enic->rq_count; i++)
+	for (i = 0; i < enic->rq_count; i++) {
+		napi_hash_del(&enic->napi[i]);
 		netif_napi_del(&enic->napi[i]);
+	}
+	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+		for (i = 0; i < enic->wq_count; i++)
+			netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);
 
 	enic_free_vnic_resources(enic);
 	enic_clear_intr_mode(enic);
@@ -2114,11 +2239,17 @@ static int enic_dev_init(struct enic *en
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	default:
 		netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
+		napi_hash_add(&enic->napi[0]);
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->rq_count; i++)
+		for (i = 0; i < enic->rq_count; i++) {
 			netif_napi_add(netdev, &enic->napi[i],
-				enic_poll_msix, 64);
+				enic_poll_msix_rq, NAPI_POLL_WEIGHT);
+			napi_hash_add(&enic->napi[i]);
+		}
+		for (i = 0; i < enic->wq_count; i++)
+			netif_napi_add(netdev, &enic->napi[enic_cq_wq(enic, i)],
+				       enic_poll_msix_wq, NAPI_POLL_WEIGHT);
 		break;
 	}
 
@@ -2386,6 +2517,10 @@ static int enic_probe(struct pci_dev *pd
 
 	netdev->features |= netdev->hw_features;
 
+#ifdef CONFIG_RFS_ACCEL
+	netdev->hw_features |= NETIF_F_NTUPLE;
+#endif
+
 	if (using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_res.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_res.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/enic_res.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/enic_res.c	2014-09-28 17:29:07.000000000 -0400
@@ -71,6 +71,7 @@ int enic_get_vnic_config(struct enic *en
 	GET_CONFIG(intr_mode);
 	GET_CONFIG(intr_timer_usec);
 	GET_CONFIG(loop_tag);
+	GET_CONFIG(num_arfs);
 
 	c->wq_desc_count =
 		min_t(u32, ENIC_MAX_WQ_DESCS,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,5 +2,5 @@ obj-$(CONFIG_ENIC) := enic.o
 
 enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
 	enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
-	enic_ethtool.o enic_api.o
+	enic_ethtool.o enic_api.o enic_clsf.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -312,12 +312,12 @@ static int _vnic_dev_cmd(struct vnic_dev
 				err = (int)readq(&devcmd->args[0]);
 				if (err == ERR_EINVAL &&
 				    cmd == CMD_CAPABILITY)
-					return err;
+					return -err;
 				if (err != ERR_ECMDUNKNOWN ||
 				    cmd != CMD_CAPABILITY)
 					pr_err("Error %d devcmd %d\n",
 						err, _CMD_N(cmd));
-				return err;
+				return -err;
 			}
 
 			if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
@@ -432,14 +432,12 @@ int vnic_dev_fw_info(struct vnic_dev *vd
 	int err = 0;
 
 	if (!vdev->fw_info) {
-		vdev->fw_info = pci_alloc_consistent(vdev->pdev,
-			sizeof(struct vnic_devcmd_fw_info),
-			&vdev->fw_info_pa);
+		vdev->fw_info = pci_zalloc_consistent(vdev->pdev,
+						      sizeof(struct vnic_devcmd_fw_info),
+						      &vdev->fw_info_pa);
 		if (!vdev->fw_info)
 			return -ENOMEM;
 
-		memset(vdev->fw_info, 0, sizeof(struct vnic_devcmd_fw_info));
-
 		a0 = vdev->fw_info_pa;
 		a1 = sizeof(struct vnic_devcmd_fw_info);
 
@@ -1048,3 +1046,64 @@ int vnic_dev_set_mac_addr(struct vnic_de
 
 	return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait);
 }
+
+/* vnic_dev_classifier: Add/Delete classifier entries
+ * @vdev: vdev of the device
+ * @cmd: CLSF_ADD for Add filter
+ *	 CLSF_DEL for Delete filter
+ * @entry: In case of ADD filter, the caller passes the RQ number in this
+ *	   variable.
+ *
+ *	   This function stores the filter_id returned by the firmware in the
+ *	   same variable before return;
+ *
+ *	   In case of DEL filter, the caller passes the RQ number. Return
+ *	   value is irrelevant.
+ * @data: filter data
+ */
+int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
+			struct filter *data)
+{
+	u64 a0, a1;
+	int wait = 1000;
+	dma_addr_t tlv_pa;
+	int ret = -EINVAL;
+	struct filter_tlv *tlv, *tlv_va;
+	struct filter_action *action;
+	u64 tlv_size;
+
+	if (cmd == CLSF_ADD) {
+		tlv_size = sizeof(struct filter) +
+			   sizeof(struct filter_action) +
+			   2 * sizeof(struct filter_tlv);
+		tlv_va = pci_alloc_consistent(vdev->pdev, tlv_size, &tlv_pa);
+		if (!tlv_va)
+			return -ENOMEM;
+		tlv = tlv_va;
+		a0 = tlv_pa;
+		a1 = tlv_size;
+		memset(tlv, 0, tlv_size);
+		tlv->type = CLSF_TLV_FILTER;
+		tlv->length = sizeof(struct filter);
+		*(struct filter *)&tlv->val = *data;
+
+		tlv = (struct filter_tlv *)((char *)tlv +
+					    sizeof(struct filter_tlv) +
+					    sizeof(struct filter));
+
+		tlv->type = CLSF_TLV_ACTION;
+		tlv->length = sizeof(struct filter_action);
+		action = (struct filter_action *)&tlv->val;
+		action->type = FILTER_ACTION_RQ_STEERING;
+		action->u.rq_idx = *entry;
+
+		ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait);
+		*entry = (u16)a0;
+		pci_free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa);
+	} else if (cmd == CLSF_DEL) {
+		a0 = *entry;
+		ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait);
+	}
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_devcmd.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_devcmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_devcmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -603,6 +603,11 @@ struct filter_tlv {
 	u_int32_t val[0];
 };
 
+enum {
+	CLSF_ADD = 0,
+	CLSF_DEL = 1,
+};
+
 /*
  * Writing cmd register causes STAT_BUSY to get set in status register.
  * When cmd completes, STAT_BUSY will be cleared.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.h	2014-09-28 17:29:07.000000000 -0400
@@ -133,5 +133,7 @@ int vnic_dev_enable2(struct vnic_dev *vd
 int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
 int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status);
 int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
+int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
+			struct filter *data);
 
 #endif /* _VNIC_DEV_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_enet.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_enet.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_enet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_enet.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,8 @@ struct vnic_enet_config {
 	char devname[16];
 	u32 intr_timer_usec;
 	u16 loop_tag;
+	u16 vf_rq_count;
+	u16 num_arfs;
 };
 
 #define VENETF_TSO		0x1	/* TSO enabled */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_rq.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_rq.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/cisco/enic/vnic_rq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/cisco/enic/vnic_rq.h	2014-09-28 17:29:07.000000000 -0400
@@ -85,6 +85,21 @@ struct vnic_rq {
 	struct vnic_rq_buf *to_clean;
 	void *os_buf_head;
 	unsigned int pkts_outstanding;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#define ENIC_POLL_STATE_IDLE		0
+#define ENIC_POLL_STATE_NAPI		(1 << 0) /* NAPI owns this poll */
+#define ENIC_POLL_STATE_POLL		(1 << 1) /* poll owns this poll */
+#define ENIC_POLL_STATE_NAPI_YIELD	(1 << 2) /* NAPI yielded this poll */
+#define ENIC_POLL_STATE_POLL_YIELD	(1 << 3) /* poll yielded this poll */
+#define ENIC_POLL_YIELD			(ENIC_POLL_STATE_NAPI_YIELD |	\
+					 ENIC_POLL_STATE_POLL_YIELD)
+#define ENIC_POLL_LOCKED		(ENIC_POLL_STATE_NAPI |		\
+					 ENIC_POLL_STATE_POLL)
+#define ENIC_POLL_USER_PEND		(ENIC_POLL_STATE_POLL |		\
+					 ENIC_POLL_STATE_POLL_YIELD)
+	unsigned int bpoll_state;
+	spinlock_t bpoll_lock;
+#endif /* CONFIG_NET_RX_BUSY_POLL */
 };
 
 static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
@@ -197,6 +212,113 @@ static inline int vnic_rq_fill(struct vn
 	return 0;
 }
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void enic_busy_poll_init_lock(struct vnic_rq *rq)
+{
+	spin_lock_init(&rq->bpoll_lock);
+	rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+}
+
+static inline bool enic_poll_lock_napi(struct vnic_rq *rq)
+{
+	bool rc = true;
+
+	spin_lock(&rq->bpoll_lock);
+	if (rq->bpoll_state & ENIC_POLL_LOCKED) {
+		WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI);
+		rq->bpoll_state |= ENIC_POLL_STATE_NAPI_YIELD;
+		rc = false;
+	} else {
+		rq->bpoll_state = ENIC_POLL_STATE_NAPI;
+	}
+	spin_unlock(&rq->bpoll_lock);
+
+	return rc;
+}
+
+static inline bool enic_poll_unlock_napi(struct vnic_rq *rq)
+{
+	bool rc = false;
+
+	spin_lock(&rq->bpoll_lock);
+	WARN_ON(rq->bpoll_state &
+		(ENIC_POLL_STATE_POLL | ENIC_POLL_STATE_NAPI_YIELD));
+	if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD)
+		rc = true;
+	rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+	spin_unlock(&rq->bpoll_lock);
+
+	return rc;
+}
+
+static inline bool enic_poll_lock_poll(struct vnic_rq *rq)
+{
+	bool rc = true;
+
+	spin_lock_bh(&rq->bpoll_lock);
+	if (rq->bpoll_state & ENIC_POLL_LOCKED) {
+		rq->bpoll_state |= ENIC_POLL_STATE_POLL_YIELD;
+		rc = false;
+	} else {
+		rq->bpoll_state |= ENIC_POLL_STATE_POLL;
+	}
+	spin_unlock_bh(&rq->bpoll_lock);
+
+	return rc;
+}
+
+static inline bool enic_poll_unlock_poll(struct vnic_rq *rq)
+{
+	bool rc = false;
+
+	spin_lock_bh(&rq->bpoll_lock);
+	WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI);
+	if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD)
+		rc = true;
+	rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+	spin_unlock_bh(&rq->bpoll_lock);
+
+	return rc;
+}
+
+static inline bool enic_poll_busy_polling(struct vnic_rq *rq)
+{
+	WARN_ON(!(rq->bpoll_state & ENIC_POLL_LOCKED));
+	return rq->bpoll_state & ENIC_POLL_USER_PEND;
+}
+
+#else
+
+static inline void enic_busy_poll_init_lock(struct vnic_rq *rq)
+{
+}
+
+static inline bool enic_poll_lock_napi(struct vnic_rq *rq)
+{
+	return true;
+}
+
+static inline bool enic_poll_unlock_napi(struct vnic_rq *rq)
+{
+	return false;
+}
+
+static inline bool enic_poll_lock_poll(struct vnic_rq *rq)
+{
+	return false;
+}
+
+static inline bool enic_poll_unlock_poll(struct vnic_rq *rq)
+{
+	return false;
+}
+
+static inline bool enic_poll_ll_polling(struct vnic_rq *rq)
+{
+	return false;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 void vnic_rq_free(struct vnic_rq *rq);
 int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
 	unsigned int desc_count, unsigned int desc_size);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/davicom/dm9000.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/davicom/dm9000.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/davicom/dm9000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/davicom/dm9000.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,7 +93,7 @@ enum dm9000_type {
 };
 
 /* Structure/enum declaration ------------------------------- */
-typedef struct board_info {
+struct board_info {
 
 	void __iomem	*io_addr;	/* Register I/O base address */
 	void __iomem	*io_data;	/* Data I/O address */
@@ -141,7 +141,7 @@ typedef struct board_info {
 	u32		wake_state;
 
 	int		ip_summed;
-} board_info_t;
+};
 
 /* debug code */
 
@@ -151,7 +151,7 @@ typedef struct board_info {
 	}						\
 } while (0)
 
-static inline board_info_t *to_dm9000_board(struct net_device *dev)
+static inline struct board_info *to_dm9000_board(struct net_device *dev)
 {
 	return netdev_priv(dev);
 }
@@ -162,7 +162,7 @@ static inline board_info_t *to_dm9000_bo
  *   Read a byte from I/O port
  */
 static u8
-ior(board_info_t *db, int reg)
+ior(struct board_info *db, int reg)
 {
 	writeb(reg, db->io_addr);
 	return readb(db->io_data);
@@ -173,14 +173,14 @@ ior(board_info_t *db, int reg)
  */
 
 static void
-iow(board_info_t *db, int reg, int value)
+iow(struct board_info *db, int reg, int value)
 {
 	writeb(reg, db->io_addr);
 	writeb(value, db->io_data);
 }
 
 static void
-dm9000_reset(board_info_t *db)
+dm9000_reset(struct board_info *db)
 {
 	dev_dbg(db->dev, "resetting device\n");
 
@@ -272,7 +272,7 @@ static void dm9000_dumpblk_32bit(void __
  * Sleep, either by using msleep() or if we are suspending, then
  * use mdelay() to sleep.
  */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
+static void dm9000_msleep(struct board_info *db, unsigned int ms)
 {
 	if (db->in_suspend || db->in_timeout)
 		mdelay(ms);
@@ -284,7 +284,7 @@ static void dm9000_msleep(board_info_t *
 static int
 dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned long flags;
 	unsigned int reg_save;
 	int ret;
@@ -330,7 +330,7 @@ static void
 dm9000_phy_write(struct net_device *dev,
 		 int phyaddr_unused, int reg, int value)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned long flags;
 	unsigned long reg_save;
 
@@ -408,7 +408,7 @@ static void dm9000_set_io(struct board_i
 	}
 }
 
-static void dm9000_schedule_poll(board_info_t *db)
+static void dm9000_schedule_poll(struct board_info *db)
 {
 	if (db->type == TYPE_DM9000E)
 		schedule_delayed_work(&db->phy_poll, HZ * 2);
@@ -416,7 +416,7 @@ static void dm9000_schedule_poll(board_i
 
 static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	if (!netif_running(dev))
 		return -EINVAL;
@@ -425,7 +425,7 @@ static int dm9000_ioctl(struct net_devic
 }
 
 static unsigned int
-dm9000_read_locked(board_info_t *db, int reg)
+dm9000_read_locked(struct board_info *db, int reg)
 {
 	unsigned long flags;
 	unsigned int ret;
@@ -437,7 +437,7 @@ dm9000_read_locked(board_info_t *db, int
 	return ret;
 }
 
-static int dm9000_wait_eeprom(board_info_t *db)
+static int dm9000_wait_eeprom(struct board_info *db)
 {
 	unsigned int status;
 	int timeout = 8;	/* wait max 8msec */
@@ -474,7 +474,7 @@ static int dm9000_wait_eeprom(board_info
  *  Read a word data from EEPROM
  */
 static void
-dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
+dm9000_read_eeprom(struct board_info *db, int offset, u8 *to)
 {
 	unsigned long flags;
 
@@ -514,7 +514,7 @@ dm9000_read_eeprom(board_info_t *db, int
  * Write a word data to SROM
  */
 static void
-dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
+dm9000_write_eeprom(struct board_info *db, int offset, u8 *data)
 {
 	unsigned long flags;
 
@@ -546,7 +546,7 @@ dm9000_write_eeprom(board_info_t *db, in
 static void dm9000_get_drvinfo(struct net_device *dev,
 			       struct ethtool_drvinfo *info)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	strlcpy(info->driver, CARDNAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
@@ -556,21 +556,21 @@ static void dm9000_get_drvinfo(struct ne
 
 static u32 dm9000_get_msglevel(struct net_device *dev)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	return dm->msg_enable;
 }
 
 static void dm9000_set_msglevel(struct net_device *dev, u32 value)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	dm->msg_enable = value;
 }
 
 static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	mii_ethtool_gset(&dm->mii, cmd);
 	return 0;
@@ -578,21 +578,21 @@ static int dm9000_get_settings(struct ne
 
 static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	return mii_ethtool_sset(&dm->mii, cmd);
 }
 
 static int dm9000_nway_reset(struct net_device *dev)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	return mii_nway_restart(&dm->mii);
 }
 
 static int dm9000_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	netdev_features_t changed = dev->features ^ features;
 	unsigned long flags;
 
@@ -608,7 +608,7 @@ static int dm9000_set_features(struct ne
 
 static u32 dm9000_get_link(struct net_device *dev)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	u32 ret;
 
 	if (dm->flags & DM9000_PLATF_EXT_PHY)
@@ -629,7 +629,7 @@ static int dm9000_get_eeprom_len(struct
 static int dm9000_get_eeprom(struct net_device *dev,
 			     struct ethtool_eeprom *ee, u8 *data)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	int offset = ee->offset;
 	int len = ee->len;
 	int i;
@@ -653,7 +653,7 @@ static int dm9000_get_eeprom(struct net_
 static int dm9000_set_eeprom(struct net_device *dev,
 			     struct ethtool_eeprom *ee, u8 *data)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	int offset = ee->offset;
 	int len = ee->len;
 	int done;
@@ -691,7 +691,7 @@ static int dm9000_set_eeprom(struct net_
 
 static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	memset(w, 0, sizeof(struct ethtool_wolinfo));
 
@@ -702,7 +702,7 @@ static void dm9000_get_wol(struct net_de
 
 static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 	unsigned long flags;
 	u32 opts = w->wolopts;
 	u32 wcr = 0;
@@ -752,7 +752,7 @@ static const struct ethtool_ops dm9000_e
 	.set_eeprom		= dm9000_set_eeprom,
 };
 
-static void dm9000_show_carrier(board_info_t *db,
+static void dm9000_show_carrier(struct board_info *db,
 				unsigned carrier, unsigned nsr)
 {
 	int lpa;
@@ -775,7 +775,7 @@ static void
 dm9000_poll_work(struct work_struct *w)
 {
 	struct delayed_work *dw = to_delayed_work(w);
-	board_info_t *db = container_of(dw, board_info_t, phy_poll);
+	struct board_info *db = container_of(dw, struct board_info, phy_poll);
 	struct net_device *ndev = db->ndev;
 
 	if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
@@ -817,10 +817,12 @@ dm9000_release_board(struct platform_dev
 
 	/* release the resources */
 
-	release_resource(db->data_req);
+	if (db->data_req)
+		release_resource(db->data_req);
 	kfree(db->data_req);
 
-	release_resource(db->addr_req);
+	if (db->addr_req)
+		release_resource(db->addr_req);
 	kfree(db->addr_req);
 }
 
@@ -841,7 +843,7 @@ static unsigned char dm9000_type_to_char
 static void
 dm9000_hash_table_unlocked(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
 	int i, oft;
 	u32 hash_val;
@@ -877,7 +879,7 @@ dm9000_hash_table_unlocked(struct net_de
 static void
 dm9000_hash_table(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned long flags;
 
 	spin_lock_irqsave(&db->lock, flags);
@@ -886,13 +888,13 @@ dm9000_hash_table(struct net_device *dev
 }
 
 static void
-dm9000_mask_interrupts(board_info_t *db)
+dm9000_mask_interrupts(struct board_info *db)
 {
 	iow(db, DM9000_IMR, IMR_PAR);
 }
 
 static void
-dm9000_unmask_interrupts(board_info_t *db)
+dm9000_unmask_interrupts(struct board_info *db)
 {
 	iow(db, DM9000_IMR, db->imr_all);
 }
@@ -903,7 +905,7 @@ dm9000_unmask_interrupts(board_info_t *d
 static void
 dm9000_init_dm9000(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned int imr;
 	unsigned int ncr;
 
@@ -968,7 +970,7 @@ dm9000_init_dm9000(struct net_device *de
 /* Our watchdog timed out. Called by the networking layer */
 static void dm9000_timeout(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	u8 reg_save;
 	unsigned long flags;
 
@@ -994,7 +996,7 @@ static void dm9000_send_packet(struct ne
 			       int ip_summed,
 			       u16 pkt_len)
 {
-	board_info_t *dm = to_dm9000_board(dev);
+	struct board_info *dm = to_dm9000_board(dev);
 
 	/* The DM9000 is not smart enough to leave fragmented packets alone. */
 	if (dm->ip_summed != ip_summed) {
@@ -1021,7 +1023,7 @@ static int
 dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	unsigned long flags;
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 
 	dm9000_dbg(db, 3, "%s:\n", __func__);
 
@@ -1060,7 +1062,7 @@ dm9000_start_xmit(struct sk_buff *skb, s
  * receive the packet to upper layer, free the transmitted packet
  */
 
-static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
+static void dm9000_tx_done(struct net_device *dev, struct board_info *db)
 {
 	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
 
@@ -1092,7 +1094,7 @@ struct dm9000_rxhdr {
 static void
 dm9000_rx(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	struct dm9000_rxhdr rxhdr;
 	struct sk_buff *skb;
 	u8 rxbyte, *rdptr;
@@ -1194,7 +1196,7 @@ dm9000_rx(struct net_device *dev)
 static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	int int_status;
 	unsigned long flags;
 	u8 reg_save;
@@ -1244,7 +1246,7 @@ static irqreturn_t dm9000_interrupt(int
 static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned long flags;
 	unsigned nsr, wcr;
 
@@ -1294,7 +1296,7 @@ static void dm9000_poll_controller(struc
 static int
 dm9000_open(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 	unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
 
 	if (netif_msg_ifup(db))
@@ -1340,7 +1342,7 @@ dm9000_open(struct net_device *dev)
 static void
 dm9000_shutdown(struct net_device *dev)
 {
-	board_info_t *db = netdev_priv(dev);
+	struct board_info *db = netdev_priv(dev);
 
 	/* RESET device */
 	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */
@@ -1356,7 +1358,7 @@ dm9000_shutdown(struct net_device *dev)
 static int
 dm9000_stop(struct net_device *ndev)
 {
-	board_info_t *db = netdev_priv(ndev);
+	struct board_info *db = netdev_priv(ndev);
 
 	if (netif_msg_ifdown(db))
 		dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -1397,7 +1399,7 @@ static struct dm9000_plat_data *dm9000_p
 	const void *mac_addr;
 
 	if (!IS_ENABLED(CONFIG_OF) || !np)
-		return NULL;
+		return ERR_PTR(-ENXIO);
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -1679,7 +1681,7 @@ dm9000_drv_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct net_device *ndev = platform_get_drvdata(pdev);
-	board_info_t *db;
+	struct board_info *db;
 
 	if (ndev) {
 		db = netdev_priv(ndev);
@@ -1702,7 +1704,7 @@ dm9000_drv_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct net_device *ndev = platform_get_drvdata(pdev);
-	board_info_t *db = netdev_priv(ndev);
+	struct board_info *db = netdev_priv(ndev);
 
 	if (ndev) {
 		if (netif_running(ndev)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/de2104x.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/de2104x.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/de2104x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/de2104x.c	2014-09-28 17:29:07.000000000 -0400
@@ -340,7 +340,7 @@ static void de21041_media_timer (unsigne
 static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media);
 
 
-static DEFINE_PCI_DEVICE_TABLE(de_pci_tbl) = {
+static const struct pci_device_id de_pci_tbl[] = {
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/de4x5.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/de4x5.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/de4x5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/de4x5.c	2014-09-28 17:29:07.000000000 -0400
@@ -2328,7 +2328,7 @@ static void de4x5_pci_remove(struct pci_
 	pci_disable_device (pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(de4x5_pci_tbl) = {
+static const struct pci_device_id de4x5_pci_tbl[] = {
         { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
           PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
         { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
@@ -3250,7 +3250,6 @@ srom_map_media(struct net_device *dev)
 	printk("%s: Bad media code [%d] detected in SROM!\n", dev->name,
 	                                                  lp->infoblock_media);
 	return -1;
-	break;
     }
 
     return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/dmfe.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/dmfe.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/dmfe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/dmfe.c	2014-09-28 17:29:07.000000000 -0400
@@ -2096,7 +2096,7 @@ static void dmfe_HPNA_remote_cmd_chk(str
 
 
 
-static DEFINE_PCI_DEVICE_TABLE(dmfe_pci_tbl) = {
+static const struct pci_device_id dmfe_pci_tbl[] = {
 	{ 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID },
 	{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID },
 	{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -207,7 +207,7 @@ struct tulip_chip_table tulip_tbl[] = {
 };
 
 
-static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = {
+static const struct pci_device_id tulip_pci_tbl[] = {
 	{ 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
 	{ 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 },
 	{ 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 },
@@ -1294,7 +1294,7 @@ static const struct net_device_ops tulip
 #endif
 };
 
-DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
+const struct pci_device_id early_486_chipsets[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
 	{ },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/uli526x.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/uli526x.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/uli526x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/uli526x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1768,7 +1768,7 @@ static u16 phy_read_1bit(struct uli526x_
 }
 
 
-static DEFINE_PCI_DEVICE_TABLE(uli526x_pci_tbl) = {
+static const struct pci_device_id uli526x_pci_tbl[] = {
 	{ 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
 	{ 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
 	{ 0, }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,7 @@ enum chip_capability_flags {
 	CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(w840_pci_tbl) = {
+static const struct pci_device_id w840_pci_tbl[] = {
 	{ 0x1050, 0x0840, PCI_ANY_ID, 0x8153,     0, 0, 0 },
 	{ 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c	2014-09-28 17:29:07.000000000 -0400
@@ -137,7 +137,7 @@ static int link_status(struct xircom_pri
 
 
 
-static DEFINE_PCI_DEVICE_TABLE(xircom_pci_table) = {
+static const struct pci_device_id xircom_pci_table[] = {
 	{ PCI_VDEVICE(XIRCOM, 0x0003), },
 	{0,},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dlink/dl2k.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dlink/dl2k.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/dlink/dl2k.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dlink/dl2k.h	2014-09-28 17:29:07.000000000 -0400
@@ -408,7 +408,7 @@ struct netdev_private {
         driver_data             Data private to the driver.
 */
 
-static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = {
+static const struct pci_device_id rio_pci_tbl[] = {
 	{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
 	{0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dlink/sundance.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dlink/sundance.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dlink/sundance.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dlink/sundance.c	2014-09-28 17:29:07.000000000 -0400
@@ -199,7 +199,7 @@ IVc. Errata
 #define USE_IO_OPS 1
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(sundance_pci_tbl) = {
+static const struct pci_device_id sundance_pci_tbl[] = {
 	{ 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
 	{ 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
 	{ 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/dnet.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dnet.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/dnet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/dnet.c	2014-09-28 17:29:07.000000000 -0400
@@ -323,7 +323,8 @@ static int dnet_mii_init(struct dnet *bp
 
 	bp->mii_bus->priv = bp;
 
-	bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	bp->mii_bus->irq = devm_kmalloc(&bp->pdev->dev,
+					sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
 	if (!bp->mii_bus->irq) {
 		err = -ENOMEM;
 		goto err_out;
@@ -334,7 +335,7 @@ static int dnet_mii_init(struct dnet *bp
 
 	if (mdiobus_register(bp->mii_bus)) {
 		err = -ENXIO;
-		goto err_out_free_mdio_irq;
+		goto err_out;
 	}
 
 	if (dnet_mii_probe(bp->dev) != 0) {
@@ -346,8 +347,6 @@ static int dnet_mii_init(struct dnet *bp
 
 err_out_unregister_bus:
 	mdiobus_unregister(bp->mii_bus);
-err_out_free_mdio_irq:
-	kfree(bp->mii_bus->irq);
 err_out:
 	mdiobus_free(bp->mii_bus);
 	return err;
@@ -825,28 +824,14 @@ static int dnet_probe(struct platform_de
 	struct net_device *dev;
 	struct dnet *bp;
 	struct phy_device *phydev;
-	int err = -ENXIO;
-	unsigned int mem_base, mem_size, irq;
+	int err;
+	unsigned int irq;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no mmio resource defined\n");
-		goto err_out;
-	}
-	mem_base = res->start;
-	mem_size = resource_size(res);
 	irq = platform_get_irq(pdev, 0);
 
-	if (!request_mem_region(mem_base, mem_size, DRV_NAME)) {
-		dev_err(&pdev->dev, "no memory region available\n");
-		err = -EBUSY;
-		goto err_out;
-	}
-
-	err = -ENOMEM;
 	dev = alloc_etherdev(sizeof(*bp));
 	if (!dev)
-		goto err_out_release_mem;
+		return -ENOMEM;
 
 	/* TODO: Actually, we have some interesting features... */
 	dev->features |= 0;
@@ -859,10 +844,10 @@ static int dnet_probe(struct platform_de
 
 	spin_lock_init(&bp->lock);
 
-	bp->regs = ioremap(mem_base, mem_size);
-	if (!bp->regs) {
-		dev_err(&pdev->dev, "failed to map registers, aborting.\n");
-		err = -ENOMEM;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	bp->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(bp->regs)) {
+		err = PTR_ERR(bp->regs);
 		goto err_out_free_dev;
 	}
 
@@ -871,7 +856,7 @@ static int dnet_probe(struct platform_de
 	if (err) {
 		dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
 		       irq, err);
-		goto err_out_iounmap;
+		goto err_out_free_dev;
 	}
 
 	dev->netdev_ops = &dnet_netdev_ops;
@@ -908,7 +893,7 @@ static int dnet_probe(struct platform_de
 		goto err_out_unregister_netdev;
 
 	dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n",
-	       bp->regs, mem_base, dev->irq, dev->dev_addr);
+	       bp->regs, (unsigned int)res->start, dev->irq, dev->dev_addr);
 	dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma\n",
 	       (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ",
 	       (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ",
@@ -925,13 +910,8 @@ err_out_unregister_netdev:
 	unregister_netdev(dev);
 err_out_free_irq:
 	free_irq(dev->irq, dev);
-err_out_iounmap:
-	iounmap(bp->regs);
 err_out_free_dev:
 	free_netdev(dev);
-err_out_release_mem:
-	release_mem_region(mem_base, mem_size);
-err_out:
 	return err;
 }
 
@@ -948,11 +928,9 @@ static int dnet_remove(struct platform_d
 		if (bp->phy_dev)
 			phy_disconnect(bp->phy_dev);
 		mdiobus_unregister(bp->mii_bus);
-		kfree(bp->mii_bus->irq);
 		mdiobus_free(bp->mii_bus);
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
-		iounmap(bp->regs);
 		free_netdev(dev);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2014-09-28 17:29:07.000000000 -0400
@@ -1749,8 +1749,7 @@ err:
 }
 
 /* Uses synchronous mcc */
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
-		      char *fw_on_flash)
+int be_cmd_get_fw_ver(struct be_adapter *adapter)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_fw_version *req;
@@ -1772,9 +1771,8 @@ int be_cmd_get_fw_ver(struct be_adapter
 	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
-		strcpy(fw_ver, resp->firmware_version_string);
-		if (fw_on_flash)
-			strcpy(fw_on_flash, resp->fw_on_flash_version_string);
+		strcpy(adapter->fw_ver, resp->firmware_version_string);
+		strcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string);
 	}
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
@@ -1997,8 +1995,7 @@ err:
 }
 
 /* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
-			u32 *mode, u32 *caps, u16 *asic_rev)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_query_fw_cfg *req;
@@ -2017,10 +2014,10 @@ int be_cmd_query_fw_cfg(struct be_adapte
 	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
-		*port_num = le32_to_cpu(resp->phys_port);
-		*mode = le32_to_cpu(resp->function_mode);
-		*caps = le32_to_cpu(resp->function_caps);
-		*asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
+		adapter->port_num = le32_to_cpu(resp->phys_port);
+		adapter->function_mode = le32_to_cpu(resp->function_mode);
+		adapter->function_caps = le32_to_cpu(resp->function_caps);
+		adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
 	}
 
 	mutex_unlock(&adapter->mbox_lock);
@@ -2224,7 +2221,7 @@ int lancer_cmd_write_object(struct be_ad
 
 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
 					 msecs_to_jiffies(60000)))
-		status = -1;
+		status = -ETIMEDOUT;
 	else
 		status = adapter->flash_status;
 
@@ -2243,6 +2240,34 @@ err_unlock:
 	return status;
 }
 
+int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
+{
+	struct lancer_cmd_req_delete_object *req;
+	struct be_mcc_wrb *wrb;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_DELETE_OBJECT,
+			       sizeof(*req), wrb, NULL);
+
+	strcpy(req->object_name, obj_name);
+
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
 int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
 			   u32 data_size, u32 data_offset, const char *obj_name,
 			   u32 *data_read, u32 *eof, u8 *addn_status)
@@ -2320,7 +2345,7 @@ int be_cmd_write_flashrom(struct be_adap
 
 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
 					 msecs_to_jiffies(40000)))
-		status = -1;
+		status = -ETIMEDOUT;
 	else
 		status = adapter->flash_status;
 
@@ -3313,15 +3338,28 @@ err:
 	return status;
 }
 
-static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count)
+/* Descriptor type */
+enum {
+	FUNC_DESC = 1,
+	VFT_DESC = 2
+};
+
+static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+					       int desc_type)
 {
 	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+	struct be_nic_res_desc *nic;
 	int i;
 
 	for (i = 0; i < desc_count; i++) {
 		if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
-		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1)
-			return (struct be_nic_res_desc *)hdr;
+		    hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
+			nic = (struct be_nic_res_desc *)hdr;
+			if (desc_type == FUNC_DESC ||
+			    (desc_type == VFT_DESC &&
+			     nic->flags & (1 << VFT_SHIFT)))
+				return nic;
+		}
 
 		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
 		hdr = (void *)hdr + hdr->desc_len;
@@ -3329,6 +3367,16 @@ static struct be_nic_res_desc *be_get_ni
 	return NULL;
 }
 
+static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count)
+{
+	return be_get_nic_desc(buf, desc_count, VFT_DESC);
+}
+
+static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count)
+{
+	return be_get_nic_desc(buf, desc_count, FUNC_DESC);
+}
+
 static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
 						 u32 desc_count)
 {
@@ -3424,7 +3472,7 @@ int be_cmd_get_func_config(struct be_ada
 		u32 desc_count = le32_to_cpu(resp->desc_count);
 		struct be_nic_res_desc *desc;
 
-		desc = be_get_nic_desc(resp->func_param, desc_count);
+		desc = be_get_func_nic_desc(resp->func_param, desc_count);
 		if (!desc) {
 			status = -EINVAL;
 			goto err;
@@ -3440,76 +3488,17 @@ err:
 	return status;
 }
 
-/* Uses mbox */
-static int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
-					  u8 domain, struct be_dma_mem *cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_profile_config *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-	wrb = wrb_from_mbox(adapter);
-
-	req = cmd->va;
-	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			       OPCODE_COMMON_GET_PROFILE_CONFIG,
-			       cmd->size, wrb, cmd);
-
-	req->type = ACTIVE_PROFILE_TYPE;
-	req->hdr.domain = domain;
-	if (!lancer_chip(adapter))
-		req->hdr.version = 1;
-
-	status = be_mbox_notify_wait(adapter);
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses sync mcc */
-static int be_cmd_get_profile_config_mccq(struct be_adapter *adapter,
-					  u8 domain, struct be_dma_mem *cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_profile_config *req;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-
-	req = cmd->va;
-	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			       OPCODE_COMMON_GET_PROFILE_CONFIG,
-			       cmd->size, wrb, cmd);
-
-	req->type = ACTIVE_PROFILE_TYPE;
-	req->hdr.domain = domain;
-	if (!lancer_chip(adapter))
-		req->hdr.version = 1;
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses sync mcc, if MCCQ is already created otherwise mbox */
+/* Will use MBOX only if MCCQ has not been created */
 int be_cmd_get_profile_config(struct be_adapter *adapter,
 			      struct be_resources *res, u8 domain)
 {
 	struct be_cmd_resp_get_profile_config *resp;
+	struct be_cmd_req_get_profile_config *req;
+	struct be_nic_res_desc *vf_res;
 	struct be_pcie_res_desc *pcie;
 	struct be_port_res_desc *port;
 	struct be_nic_res_desc *nic;
-	struct be_queue_info *mccq = &adapter->mcc_obj.q;
+	struct be_mcc_wrb wrb = {0};
 	struct be_dma_mem cmd;
 	u32 desc_count;
 	int status;
@@ -3520,10 +3509,17 @@ int be_cmd_get_profile_config(struct be_
 	if (!cmd.va)
 		return -ENOMEM;
 
-	if (!mccq->created)
-		status = be_cmd_get_profile_config_mbox(adapter, domain, &cmd);
-	else
-		status = be_cmd_get_profile_config_mccq(adapter, domain, &cmd);
+	req = cmd.va;
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_GET_PROFILE_CONFIG,
+			       cmd.size, &wrb, &cmd);
+
+	req->hdr.domain = domain;
+	if (!lancer_chip(adapter))
+		req->hdr.version = 1;
+	req->type = ACTIVE_PROFILE_TYPE;
+
+	status = be_cmd_notify_wait(adapter, &wrb);
 	if (status)
 		goto err;
 
@@ -3539,48 +3535,52 @@ int be_cmd_get_profile_config(struct be_
 	if (port)
 		adapter->mc_type = port->mc_type;
 
-	nic = be_get_nic_desc(resp->func_param, desc_count);
+	nic = be_get_func_nic_desc(resp->func_param, desc_count);
 	if (nic)
 		be_copy_nic_desc(res, nic);
 
+	vf_res = be_get_vft_desc(resp->func_param, desc_count);
+	if (vf_res)
+		res->vf_if_cap_flags = vf_res->cap_flags;
 err:
 	if (cmd.va)
 		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
 	return status;
 }
 
-int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
-			      int size, u8 version, u8 domain)
+/* Will use MBOX only if MCCQ has not been created */
+static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
+				     int size, int count, u8 version, u8 domain)
 {
 	struct be_cmd_req_set_profile_config *req;
-	struct be_mcc_wrb *wrb;
+	struct be_mcc_wrb wrb = {0};
+	struct be_dma_mem cmd;
 	int status;
 
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
+	memset(&cmd, 0, sizeof(struct be_dma_mem));
+	cmd.size = sizeof(struct be_cmd_req_set_profile_config);
+	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+	if (!cmd.va)
+		return -ENOMEM;
 
-	req = embedded_payload(wrb);
+	req = cmd.va;
 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			       OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
-			       wrb, NULL);
+			       OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
+			       &wrb, &cmd);
 	req->hdr.version = version;
 	req->hdr.domain = domain;
-	req->desc_count = cpu_to_le32(1);
+	req->desc_count = cpu_to_le32(count);
 	memcpy(req->desc, desc, size);
 
-	status = be_mcc_notify_wait(adapter);
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
+	status = be_cmd_notify_wait(adapter, &wrb);
+
+	if (cmd.va)
+		pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
 	return status;
 }
 
 /* Mark all fields invalid */
-void be_reset_nic_desc(struct be_nic_res_desc *nic)
+static void be_reset_nic_desc(struct be_nic_res_desc *nic)
 {
 	memset(nic, 0, sizeof(*nic));
 	nic->unicast_mac_count = 0xFFFF;
@@ -3601,9 +3601,20 @@ void be_reset_nic_desc(struct be_nic_res
 	nic->wol_param = 0x0F;
 	nic->tunnel_iface_count = 0xFFFF;
 	nic->direct_tenant_iface_count = 0xFFFF;
+	nic->bw_min = 0xFFFFFFFF;
 	nic->bw_max = 0xFFFFFFFF;
 }
 
+/* Mark all fields invalid */
+static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
+{
+	memset(pcie, 0, sizeof(*pcie));
+	pcie->sriov_state = 0xFF;
+	pcie->pf_state = 0xFF;
+	pcie->pf_type = 0xFF;
+	pcie->num_vfs = 0xFFFF;
+}
+
 int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
 		      u8 domain)
 {
@@ -3634,7 +3645,63 @@ int be_cmd_config_qos(struct be_adapter
 
 	return be_cmd_set_profile_config(adapter, &nic_desc,
 					 nic_desc.hdr.desc_len,
-					 version, domain);
+					 1, version, domain);
+}
+
+int be_cmd_set_sriov_config(struct be_adapter *adapter,
+			    struct be_resources res, u16 num_vfs)
+{
+	struct {
+		struct be_pcie_res_desc pcie;
+		struct be_nic_res_desc nic_vft;
+	} __packed desc;
+	u16 vf_q_count;
+
+	if (BEx_chip(adapter) || lancer_chip(adapter))
+		return 0;
+
+	/* PF PCIE descriptor */
+	be_reset_pcie_desc(&desc.pcie);
+	desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
+	desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+	desc.pcie.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+	desc.pcie.pf_num = adapter->pdev->devfn;
+	desc.pcie.sriov_state = num_vfs ? 1 : 0;
+	desc.pcie.num_vfs = cpu_to_le16(num_vfs);
+
+	/* VF NIC Template descriptor */
+	be_reset_nic_desc(&desc.nic_vft);
+	desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
+	desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+	desc.nic_vft.flags = (1 << VFT_SHIFT) | (1 << IMM_SHIFT) |
+				(1 << NOSV_SHIFT);
+	desc.nic_vft.pf_num = adapter->pdev->devfn;
+	desc.nic_vft.vf_num = 0;
+
+	if (num_vfs && res.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
+		/* If number of VFs requested is 8 less than max supported,
+		 * assign 8 queue pairs to the PF and divide the remaining
+		 * resources evenly among the VFs
+		 */
+		if (num_vfs < (be_max_vfs(adapter) - 8))
+			vf_q_count = (res.max_rss_qs - 8) / num_vfs;
+		else
+			vf_q_count = res.max_rss_qs / num_vfs;
+
+		desc.nic_vft.rq_count = cpu_to_le16(vf_q_count);
+		desc.nic_vft.txq_count = cpu_to_le16(vf_q_count);
+		desc.nic_vft.rssq_count = cpu_to_le16(vf_q_count - 1);
+		desc.nic_vft.cq_count = cpu_to_le16(3 * vf_q_count);
+	} else {
+		desc.nic_vft.txq_count = cpu_to_le16(1);
+		desc.nic_vft.rq_count = cpu_to_le16(1);
+		desc.nic_vft.rssq_count = cpu_to_le16(0);
+		/* One CQ for each TX, RX and MCCQ */
+		desc.nic_vft.cq_count = cpu_to_le16(3);
+	}
+
+	return be_cmd_set_profile_config(adapter, &desc,
+					 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
 }
 
 int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
@@ -3686,7 +3753,7 @@ int be_cmd_set_vxlan_port(struct be_adap
 	}
 
 	return be_cmd_set_profile_config(adapter, &port_desc,
-					 RESOURCE_DESC_SIZE_V1, 1, 0);
+					 RESOURCE_DESC_SIZE_V1, 1, 1, 0);
 }
 
 int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
@@ -3766,13 +3833,19 @@ bool dump_present(struct be_adapter *ada
 
 int lancer_initiate_dump(struct be_adapter *adapter)
 {
+	struct device *dev = &adapter->pdev->dev;
 	int status;
 
+	if (dump_present(adapter)) {
+		dev_info(dev, "Previous dump not cleared, not forcing dump\n");
+		return -EEXIST;
+	}
+
 	/* give firmware reset and diagnostic dump */
 	status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
 				     PHYSDEV_CONTROL_DD_MASK);
 	if (status < 0) {
-		dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
+		dev_err(dev, "FW reset failed\n");
 		return status;
 	}
 
@@ -3781,13 +3854,21 @@ int lancer_initiate_dump(struct be_adapt
 		return status;
 
 	if (!dump_present(adapter)) {
-		dev_err(&adapter->pdev->dev, "Dump image not present\n");
-		return -1;
+		dev_err(dev, "FW dump not generated\n");
+		return -EIO;
 	}
 
 	return 0;
 }
 
+int lancer_delete_dump(struct be_adapter *adapter)
+{
+	int status;
+
+	status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
+	return be_cmd_status(status);
+}
+
 /* Uses sync mcc */
 int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_cmds.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_cmds.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_cmds.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_cmds.h	2014-09-28 17:29:07.000000000 -0400
@@ -231,6 +231,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_FN_PRIVILEGES			170
 #define OPCODE_COMMON_READ_OBJECT			171
 #define OPCODE_COMMON_WRITE_OBJECT			172
+#define OPCODE_COMMON_DELETE_OBJECT			174
 #define OPCODE_COMMON_MANAGE_IFACE_FILTERS		193
 #define OPCODE_COMMON_GET_IFACE_LIST			194
 #define OPCODE_COMMON_ENABLE_DISABLE_VF			196
@@ -1081,11 +1082,6 @@ struct be_cmd_req_modify_eq_delay {
 	struct be_set_eqd set_eqd[MAX_EVT_QS];
 } __packed;
 
-struct be_cmd_resp_modify_eq_delay {
-	struct be_cmd_resp_hdr hdr;
-	u32 rsvd0;
-} __packed;
-
 /******************** Get FW Config *******************/
 /* The HW can come up in either of the following multi-channel modes
  * based on the skew/IPL.
@@ -1156,11 +1152,6 @@ struct be_cmd_req_enable_disable_beacon
 	u8  status_duration;
 } __packed;
 
-struct be_cmd_resp_enable_disable_beacon {
-	struct be_cmd_resp_hdr resp_hdr;
-	u32 rsvd0;
-} __packed;
-
 struct be_cmd_req_get_beacon_state {
 	struct be_cmd_req_hdr hdr;
 	u8  port_num;
@@ -1263,6 +1254,13 @@ struct lancer_cmd_resp_read_object {
 	u32 eof;
 };
 
+struct lancer_cmd_req_delete_object {
+	struct be_cmd_req_hdr hdr;
+	u32 rsvd1;
+	u32 rsvd2;
+	u8 object_name[104];
+};
+
 /************************ WOL *******************************/
 struct be_cmd_req_acpi_wol_magic_config{
 	struct be_cmd_req_hdr hdr;
@@ -1326,11 +1324,6 @@ struct be_cmd_req_set_lmode {
 	u8 loopback_state;
 };
 
-struct be_cmd_resp_set_lmode {
-	struct be_cmd_resp_hdr resp_hdr;
-	u8 rsvd0[4];
-};
-
 /********************** DDR DMA test *********************/
 struct be_cmd_req_ddrdma_test {
 	struct be_cmd_req_hdr hdr;
@@ -1434,11 +1427,6 @@ struct be_cmd_req_set_qos {
 	u32 rsvd[7];
 };
 
-struct be_cmd_resp_set_qos {
-	struct be_cmd_resp_hdr hdr;
-	u32 rsvd;
-};
-
 /*********************** Controller Attributes ***********************/
 struct be_cmd_req_cntl_attribs {
 	struct be_cmd_req_hdr hdr;
@@ -1572,11 +1560,6 @@ struct be_cmd_req_set_hsw_config {
 	u8 context[sizeof(struct amap_set_hsw_context) / 8];
 } __packed;
 
-struct be_cmd_resp_set_hsw_config {
-	struct be_cmd_resp_hdr hdr;
-	u32 rsvd;
-};
-
 struct amap_get_hsw_req_context {
 	u8 interface_id[16];
 	u8 rsvd0[14];
@@ -1835,6 +1818,7 @@ struct be_cmd_req_set_ext_fat_caps {
 #define PORT_RESOURCE_DESC_TYPE_V1		0x55
 #define MAX_RESOURCE_DESC			264
 
+#define VFT_SHIFT				3	/* VF template */
 #define IMM_SHIFT				6	/* Immediate */
 #define NOSV_SHIFT				7	/* No save */
 
@@ -1962,12 +1946,8 @@ struct be_cmd_req_set_profile_config {
 	struct be_cmd_req_hdr hdr;
 	u32 rsvd;
 	u32 desc_count;
-	u8 desc[RESOURCE_DESC_SIZE_V1];
-};
-
-struct be_cmd_resp_set_profile_config {
-	struct be_cmd_resp_hdr hdr;
-};
+	u8 desc[2 * RESOURCE_DESC_SIZE_V1];
+} __packed;
 
 struct be_cmd_req_get_active_profile {
 	struct be_cmd_req_hdr hdr;
@@ -2070,16 +2050,14 @@ int be_cmd_reset(struct be_adapter *adap
 int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd);
 int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
 			       struct be_dma_mem *nonemb_cmd);
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
-		      char *fw_on_flash);
+int be_cmd_get_fw_ver(struct be_adapter *adapter);
 int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num);
 int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
 		       u32 num);
 int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
 int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc);
 int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc);
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
-			u32 *function_mode, u32 *function_caps, u16 *asic_rev);
+int be_cmd_query_fw_cfg(struct be_adapter *adapter);
 int be_cmd_reset_function(struct be_adapter *adapter);
 int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
 		      u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey);
@@ -2097,6 +2075,7 @@ int lancer_cmd_write_object(struct be_ad
 int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
 			   u32 data_size, u32 data_offset, const char *obj_name,
 			   u32 *data_read, u32 *eof, u8 *addn_status);
+int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
 int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 			  u16 optype, int offset);
 int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
@@ -2150,6 +2129,7 @@ int be_cmd_set_ext_fat_capabilites(struc
 				   struct be_fat_conf_params *cfgs);
 int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
 int lancer_initiate_dump(struct be_adapter *adapter);
+int lancer_delete_dump(struct be_adapter *adapter);
 bool dump_present(struct be_adapter *adapter);
 int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
@@ -2157,8 +2137,6 @@ int be_cmd_get_func_config(struct be_ada
 			   struct be_resources *res);
 int be_cmd_get_profile_config(struct be_adapter *adapter,
 			      struct be_resources *res, u8 domain);
-int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
-			      int size, u8 version, u8 domain);
 int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile);
 int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
 		     int vf_num);
@@ -2168,3 +2146,5 @@ int be_cmd_set_logical_link_config(struc
 					  int link_state, u8 domain);
 int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port);
 int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op);
+int be_cmd_set_sriov_config(struct be_adapter *adapter,
+			    struct be_resources res, u16 num_vfs);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -643,7 +643,7 @@ be_set_pauseparam(struct net_device *net
 	if (status)
 		dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
 
-	return status;
+	return be_cmd_status(status);
 }
 
 static int be_set_phys_id(struct net_device *netdev,
@@ -681,22 +681,21 @@ static int be_set_dump(struct net_device
 	struct device *dev = &adapter->pdev->dev;
 	int status;
 
-	if (!lancer_chip(adapter)) {
-		dev_err(dev, "FW dump not supported\n");
+	if (!lancer_chip(adapter) ||
+	    !check_privilege(adapter, MAX_PRIVILEGES))
 		return -EOPNOTSUPP;
-	}
-
-	if (dump_present(adapter)) {
-		dev_err(dev, "Previous dump not cleared, not forcing dump\n");
-		return 0;
-	}
 
 	switch (dump->flag) {
 	case LANCER_INITIATE_FW_DUMP:
 		status = lancer_initiate_dump(adapter);
 		if (!status)
-			dev_info(dev, "F/w dump initiated successfully\n");
+			dev_info(dev, "FW dump initiated successfully\n");
 		break;
+	case LANCER_DELETE_FW_DUMP:
+		status = lancer_delete_dump(adapter);
+		if (!status)
+			dev_info(dev, "FW dump deleted successfully\n");
+	break;
 	default:
 		dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);
 		return -EINVAL;
@@ -762,7 +761,7 @@ static int be_test_ddr_dma(struct be_ada
 err:
 	dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
 			  ddrdma_cmd.dma);
-	return ret;
+	return be_cmd_status(ret);
 }
 
 static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
@@ -885,7 +884,7 @@ static int be_read_eeprom(struct net_dev
 	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
 			  eeprom_cmd.dma);
 
-	return status;
+	return be_cmd_status(status);
 }
 
 static u32 be_get_msg_level(struct net_device *netdev)
@@ -1042,7 +1041,7 @@ static int be_set_rss_hash_opts(struct b
 	if (!status)
 		adapter->rss_info.rss_flags = rss_flags;
 
-	return status;
+	return be_cmd_status(status);
 }
 
 static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
@@ -1080,6 +1079,7 @@ static int be_set_channels(struct net_de
 			   struct ethtool_channels *ch)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
+	int status;
 
 	if (ch->rx_count || ch->tx_count || ch->other_count ||
 	    !ch->combined_count || ch->combined_count > be_max_qs(adapter))
@@ -1087,7 +1087,8 @@ static int be_set_channels(struct net_de
 
 	adapter->cfg_num_qs = ch->combined_count;
 
-	return be_update_queues(adapter);
+	status = be_update_queues(adapter);
+	return be_cmd_status(status);
 }
 
 static u32 be_get_rxfh_indir_size(struct net_device *netdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER			"10.2u"
+#define DRV_VER			"10.4u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"Emulex BladeEngine2"
 #define BE3_NAME		"Emulex BladeEngine3"
@@ -372,6 +372,7 @@ enum vf_state {
 };
 
 #define BE_FLAGS_LINK_STATUS_INIT		1
+#define BE_FLAGS_SRIOV_ENABLED			(1 << 2)
 #define BE_FLAGS_WORKER_SCHEDULED		(1 << 3)
 #define BE_FLAGS_VLAN_PROMISC			(1 << 4)
 #define BE_FLAGS_MCAST_PROMISC			(1 << 5)
@@ -382,8 +383,10 @@ enum vf_state {
 
 #define BE_UC_PMAC_COUNT			30
 #define BE_VF_UC_PMAC_COUNT			2
+
 /* Ethtool set_dump flags */
 #define LANCER_INITIATE_FW_DUMP			0x1
+#define LANCER_DELETE_FW_DUMP			0x2
 
 struct phy_info {
 	u8 transceiver;
@@ -411,6 +414,7 @@ struct be_resources {
 	u16 max_vlans;		/* Number of vlans supported */
 	u16 max_evt_qs;
 	u32 if_cap_flags;
+	u32 vf_if_cap_flags;	/* VF if capability flags */
 };
 
 struct rss_info {
@@ -500,6 +504,7 @@ struct be_adapter {
 	u32 flash_status;
 	struct completion et_cmd_compl;
 
+	struct be_resources pool_res;	/* resources available for the port */
 	struct be_resources res;	/* resources available for the func */
 	u16 num_vfs;			/* Number of VFs provisioned by PF */
 	u8 virtfn;
@@ -523,9 +528,9 @@ struct be_adapter {
 
 #define be_physfn(adapter)		(!adapter->virtfn)
 #define be_virtfn(adapter)		(adapter->virtfn)
-#define	sriov_enabled(adapter)		(adapter->num_vfs > 0)
-#define sriov_want(adapter)             (be_physfn(adapter) &&	\
-					 (num_vfs || pci_num_vf(adapter->pdev)))
+#define sriov_enabled(adapter)		(adapter->flags &	\
+					 BE_FLAGS_SRIOV_ENABLED)
+
 #define for_all_vfs(adapter, vf_cfg, i)					\
 	for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs;	\
 		i++, vf_cfg++)
@@ -536,7 +541,7 @@ struct be_adapter {
 #define be_max_vlans(adapter)		(adapter->res.max_vlans)
 #define be_max_uc(adapter)		(adapter->res.max_uc_mac)
 #define be_max_mc(adapter)		(adapter->res.max_mcast_mac)
-#define be_max_vfs(adapter)		(adapter->res.max_vfs)
+#define be_max_vfs(adapter)		(adapter->pool_res.max_vfs)
 #define be_max_rss(adapter)		(adapter->res.max_rss_qs)
 #define be_max_txqs(adapter)		(adapter->res.max_tx_qs)
 #define be_max_prio_txqs(adapter)	(adapter->res.max_prio_tx_qs)
@@ -671,6 +676,8 @@ static inline void swap_dws(void *wrb, i
 #endif				/* __BIG_ENDIAN */
 }
 
+#define be_cmd_status(status)		(status > 0 ? -EIO : status)
+
 static inline u8 is_tcp_pkt(struct sk_buff *skb)
 {
 	u8 val = 0;
@@ -890,5 +897,6 @@ void be_roce_dev_remove(struct be_adapte
  */
 void be_roce_dev_open(struct be_adapter *);
 void be_roce_dev_close(struct be_adapter *);
+void be_roce_dev_shutdown(struct be_adapter *);
 
 #endif				/* BE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@ static ushort rx_frag_size = 2048;
 module_param(rx_frag_size, ushort, S_IRUGO);
 MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 
-static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
+static const struct pci_device_id be_dev_ids[] = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
@@ -81,10 +81,10 @@ static const char * const ue_status_low_
 	"P1_OB_LINK ",
 	"HOST_GPIO ",
 	"MBOX ",
-	"AXGMAC0",
-	"AXGMAC1",
-	"JTAG",
-	"MPU_INTPEND"
+	"ERX2 ",
+	"SPARE ",
+	"JTAG ",
+	"MPU_INTPEND "
 };
 /* UE Status High CSR */
 static const char * const ue_status_hi_desc[] = {
@@ -109,16 +109,16 @@ static const char * const ue_status_hi_d
 	"HOST5",
 	"HOST6",
 	"HOST7",
-	"HOST8",
-	"HOST9",
+	"ECRC",
+	"Poison TLP",
 	"NETC",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
+	"PERIPH",
+	"LLTXULP",
+	"D2P",
+	"RCON",
+	"LDMA",
+	"LLTXP",
+	"LLTXPB",
 	"Unknown"
 };
 
@@ -1172,20 +1172,15 @@ static int be_vlan_add_vid(struct net_de
 static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	int status = 0;
 
 	/* Packets with VID 0 are always received by Lancer by default */
 	if (lancer_chip(adapter) && vid == 0)
-		goto ret;
+		return 0;
 
 	clear_bit(vid, adapter->vids);
-	status = be_vid_config(adapter);
-	if (!status)
-		adapter->vlans_added--;
-	else
-		set_bit(vid, adapter->vids);
-ret:
-	return status;
+	adapter->vlans_added--;
+
+	return be_vid_config(adapter);
 }
 
 static void be_clear_promisc(struct be_adapter *adapter)
@@ -1275,6 +1270,12 @@ static int be_set_vf_mac(struct net_devi
 	if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
 		return -EINVAL;
 
+	/* Proceed further only if user provided MAC is different
+	 * from active MAC
+	 */
+	if (ether_addr_equal(mac, vf_cfg->mac_addr))
+		return 0;
+
 	if (BEx_chip(adapter)) {
 		be_cmd_pmac_del(adapter, vf_cfg->if_handle, vf_cfg->pmac_id,
 				vf + 1);
@@ -1286,13 +1287,15 @@ static int be_set_vf_mac(struct net_devi
 					vf + 1);
 	}
 
-	if (status)
-		dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
-			mac, vf);
-	else
-		memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
+	if (status) {
+		dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed: %#x",
+			mac, vf, status);
+		return be_cmd_status(status);
+	}
 
-	return status;
+	ether_addr_copy(vf_cfg->mac_addr, mac);
+
+	return 0;
 }
 
 static int be_get_vf_config(struct net_device *netdev, int vf,
@@ -1341,12 +1344,16 @@ static int be_set_vf_vlan(struct net_dev
 					       vf + 1, vf_cfg->if_handle, 0);
 	}
 
-	if (!status)
-		vf_cfg->vlan_tag = vlan;
-	else
-		dev_info(&adapter->pdev->dev,
-			 "VLAN %d config on VF %d failed\n", vlan, vf);
-	return status;
+	if (status) {
+		dev_err(&adapter->pdev->dev,
+			"VLAN %d config on VF %d failed : %#x\n", vlan,
+			vf, status);
+		return be_cmd_status(status);
+	}
+
+	vf_cfg->vlan_tag = vlan;
+
+	return 0;
 }
 
 static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
@@ -1377,7 +1384,7 @@ static int be_set_vf_tx_rate(struct net_
 
 	if (!link_status) {
 		dev_err(dev, "TX-rate setting not allowed when link is down\n");
-		status = -EPERM;
+		status = -ENETDOWN;
 		goto err;
 	}
 
@@ -1408,7 +1415,7 @@ config_qos:
 err:
 	dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n",
 		max_tx_rate, vf);
-	return status;
+	return be_cmd_status(status);
 }
 static int be_set_vf_link_state(struct net_device *netdev, int vf,
 				int link_state)
@@ -1423,10 +1430,15 @@ static int be_set_vf_link_state(struct n
 		return -EINVAL;
 
 	status = be_cmd_set_logical_link_config(adapter, link_state, vf+1);
-	if (!status)
-		adapter->vf_cfg[vf].plink_tracking = link_state;
+	if (status) {
+		dev_err(&adapter->pdev->dev,
+			"Link state change on VF %d failed: %#x\n", vf, status);
+		return be_cmd_status(status);
+	}
 
-	return status;
+	adapter->vf_cfg[vf].plink_tracking = link_state;
+
+	return 0;
 }
 
 static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
@@ -2028,7 +2040,7 @@ static void be_rx_cq_clean(struct be_rx_
 	 */
 	for (;;) {
 		rxcp = be_rx_compl_get(rxo);
-		if (rxcp == NULL) {
+		if (!rxcp) {
 			if (lancer_chip(adapter))
 				break;
 
@@ -2935,8 +2947,8 @@ static int be_setup_wol(struct be_adapte
 	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
 				     GFP_KERNEL);
-	if (cmd.va == NULL)
-		return -1;
+	if (!cmd.va)
+		return -ENOMEM;
 
 	if (enable) {
 		status = pci_write_config_dword(adapter->pdev,
@@ -3043,6 +3055,7 @@ static void be_vf_clear(struct be_adapte
 done:
 	kfree(adapter->vf_cfg);
 	adapter->num_vfs = 0;
+	adapter->flags &= ~BE_FLAGS_SRIOV_ENABLED;
 }
 
 static void be_clear_queues(struct be_adapter *adapter)
@@ -3098,6 +3111,13 @@ static int be_clear(struct be_adapter *a
 	if (sriov_enabled(adapter))
 		be_vf_clear(adapter);
 
+	/* Re-configure FW to distribute resources evenly across max-supported
+	 * number of VFs, only when VFs are not already enabled.
+	 */
+	if (be_physfn(adapter) && !pci_vfs_assigned(adapter->pdev))
+		be_cmd_set_sriov_config(adapter, adapter->pool_res,
+					pci_sriov_get_totalvfs(adapter->pdev));
+
 #ifdef CONFIG_BE2NET_VXLAN
 	be_disable_vxlan_offloads(adapter);
 #endif
@@ -3170,19 +3190,6 @@ static int be_vf_setup(struct be_adapter
 	u32 privileges;
 
 	old_vfs = pci_num_vf(adapter->pdev);
-	if (old_vfs) {
-		dev_info(dev, "%d VFs are already enabled\n", old_vfs);
-		if (old_vfs != num_vfs)
-			dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
-		adapter->num_vfs = old_vfs;
-	} else {
-		if (num_vfs > be_max_vfs(adapter))
-			dev_info(dev, "Device supports %d VFs and not %d\n",
-				 be_max_vfs(adapter), num_vfs);
-		adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter));
-		if (!adapter->num_vfs)
-			return 0;
-	}
 
 	status = be_vf_setup_init(adapter);
 	if (status)
@@ -3194,17 +3201,15 @@ static int be_vf_setup(struct be_adapter
 			if (status)
 				goto err;
 		}
-	} else {
-		status = be_vfs_if_create(adapter);
-		if (status)
-			goto err;
-	}
 
-	if (old_vfs) {
 		status = be_vfs_mac_query(adapter);
 		if (status)
 			goto err;
 	} else {
+		status = be_vfs_if_create(adapter);
+		if (status)
+			goto err;
+
 		status = be_vf_eth_addr_config(adapter);
 		if (status)
 			goto err;
@@ -3243,6 +3248,8 @@ static int be_vf_setup(struct be_adapter
 			goto err;
 		}
 	}
+
+	adapter->flags |= BE_FLAGS_SRIOV_ENABLED;
 	return 0;
 err:
 	dev_err(dev, "VF setup failed\n");
@@ -3270,19 +3277,7 @@ static u8 be_convert_mc_type(u32 functio
 static void BEx_get_resources(struct be_adapter *adapter,
 			      struct be_resources *res)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	bool use_sriov = false;
-	int max_vfs = 0;
-
-	if (be_physfn(adapter) && BE3_chip(adapter)) {
-		be_cmd_get_profile_config(adapter, res, 0);
-		/* Some old versions of BE3 FW don't report max_vfs value */
-		if (res->max_vfs == 0) {
-			max_vfs = pci_sriov_get_totalvfs(pdev);
-			res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
-		}
-		use_sriov = res->max_vfs && sriov_want(adapter);
-	}
+	bool use_sriov = adapter->num_vfs ? 1 : 0;
 
 	if (be_physfn(adapter))
 		res->max_uc_mac = BE_UC_PMAC_COUNT;
@@ -3326,7 +3321,7 @@ static void BEx_get_resources(struct be_
 	res->max_rx_qs = res->max_rss_qs + 1;
 
 	if (be_physfn(adapter))
-		res->max_evt_qs = (res->max_vfs > 0) ?
+		res->max_evt_qs = (be_max_vfs(adapter) > 0) ?
 					BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
 	else
 		res->max_evt_qs = 1;
@@ -3349,6 +3344,51 @@ static void be_setup_init(struct be_adap
 		adapter->cmd_privileges = MIN_PRIVILEGES;
 }
 
+static int be_get_sriov_config(struct be_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	struct be_resources res = {0};
+	int max_vfs, old_vfs;
+
+	/* Some old versions of BE3 FW don't report max_vfs value */
+	be_cmd_get_profile_config(adapter, &res, 0);
+
+	if (BE3_chip(adapter) && !res.max_vfs) {
+		max_vfs = pci_sriov_get_totalvfs(adapter->pdev);
+		res.max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
+	}
+
+	adapter->pool_res = res;
+
+	if (!be_max_vfs(adapter)) {
+		if (num_vfs)
+			dev_warn(dev, "device doesn't support SRIOV\n");
+		adapter->num_vfs = 0;
+		return 0;
+	}
+
+	pci_sriov_set_totalvfs(adapter->pdev, be_max_vfs(adapter));
+
+	/* validate num_vfs module param */
+	old_vfs = pci_num_vf(adapter->pdev);
+	if (old_vfs) {
+		dev_info(dev, "%d VFs are already enabled\n", old_vfs);
+		if (old_vfs != num_vfs)
+			dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
+		adapter->num_vfs = old_vfs;
+	} else {
+		if (num_vfs > be_max_vfs(adapter)) {
+			dev_info(dev, "Resources unavailable to init %d VFs\n",
+				 num_vfs);
+			dev_info(dev, "Limiting to %d VFs\n",
+				 be_max_vfs(adapter));
+		}
+		adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter));
+	}
+
+	return 0;
+}
+
 static int be_get_resources(struct be_adapter *adapter)
 {
 	struct device *dev = &adapter->pdev->dev;
@@ -3374,13 +3414,6 @@ static int be_get_resources(struct be_ad
 			res.max_evt_qs /= 2;
 		adapter->res = res;
 
-		if (be_physfn(adapter)) {
-			status = be_cmd_get_profile_config(adapter, &res, 0);
-			if (status)
-				return status;
-			adapter->res.max_vfs = res.max_vfs;
-		}
-
 		dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n",
 			 be_max_txqs(adapter), be_max_rxqs(adapter),
 			 be_max_rss(adapter), be_max_eqs(adapter),
@@ -3393,16 +3426,41 @@ static int be_get_resources(struct be_ad
 	return 0;
 }
 
-/* Routine to query per function resource limits */
+static void be_sriov_config(struct be_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	int status;
+
+	status = be_get_sriov_config(adapter);
+	if (status) {
+		dev_err(dev, "Failed to query SR-IOV configuration\n");
+		dev_err(dev, "SR-IOV cannot be enabled\n");
+		return;
+	}
+
+	/* When the HW is in SRIOV capable configuration, the PF-pool
+	 * resources are equally distributed across the max-number of
+	 * VFs. The user may request only a subset of the max-vfs to be
+	 * enabled. Based on num_vfs, redistribute the resources across
+	 * num_vfs so that each VF will have access to more number of
+	 * resources. This facility is not available in BE3 FW.
+	 * Also, this is done by FW in Lancer chip.
+	 */
+	if (be_max_vfs(adapter) && !pci_num_vf(adapter->pdev)) {
+		status = be_cmd_set_sriov_config(adapter,
+						 adapter->pool_res,
+						 adapter->num_vfs);
+		if (status)
+			dev_err(dev, "Failed to optimize SR-IOV resources\n");
+	}
+}
+
 static int be_get_config(struct be_adapter *adapter)
 {
 	u16 profile_id;
 	int status;
 
-	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
-				     &adapter->function_mode,
-				     &adapter->function_caps,
-				     &adapter->asic_rev);
+	status = be_cmd_query_fw_cfg(adapter);
 	if (status)
 		return status;
 
@@ -3413,6 +3471,9 @@ static int be_get_config(struct be_adapt
 				 "Using profile 0x%x\n", profile_id);
 	}
 
+	if (!BE2_chip(adapter) && be_physfn(adapter))
+		be_sriov_config(adapter);
+
 	status = be_get_resources(adapter);
 	if (status)
 		return status;
@@ -3571,7 +3632,7 @@ static int be_setup(struct be_adapter *a
 	if (status)
 		goto err;
 
-	be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash);
+	be_cmd_get_fw_ver(adapter);
 
 	if (BE2_chip(adapter) && fw_major_num(adapter->fw_ver) < 4) {
 		dev_err(dev, "Firmware on card is old(%s), IRQs may not work.",
@@ -3596,12 +3657,8 @@ static int be_setup(struct be_adapter *a
 		be_cmd_set_logical_link_config(adapter,
 					       IFLA_VF_LINK_STATE_AUTO, 0);
 
-	if (sriov_want(adapter)) {
-		if (be_max_vfs(adapter))
-			be_vf_setup(adapter);
-		else
-			dev_warn(dev, "device doesn't support SRIOV\n");
-	}
+	if (adapter->num_vfs)
+		be_vf_setup(adapter);
 
 	status = be_cmd_get_phy_info(adapter);
 	if (!status && be_pause_supported(adapter))
@@ -3925,7 +3982,7 @@ static int be_flash_skyhawk(struct be_ad
 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
 	if (!fsec) {
 		dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
-		return -1;
+		return -EINVAL;
 	}
 
 	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
@@ -4094,7 +4151,7 @@ lancer_fw_exit:
 static int be_get_ufi_type(struct be_adapter *adapter,
 			   struct flash_file_hdr_g3 *fhdr)
 {
-	if (fhdr == NULL)
+	if (!fhdr)
 		goto be_get_ufi_exit;
 
 	if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
@@ -4156,7 +4213,7 @@ static int be_fw_download(struct be_adap
 							      &flash_cmd,
 							      num_imgs);
 				else {
-					status = -1;
+					status = -EINVAL;
 					dev_err(&adapter->pdev->dev,
 						"Can't load BE3 UFI on BE3R\n");
 				}
@@ -4167,7 +4224,7 @@ static int be_fw_download(struct be_adap
 	if (ufi_type == UFI_TYPE2)
 		status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
 	else if (ufi_type == -1)
-		status = -1;
+		status = -EINVAL;
 
 	dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
 			  flash_cmd.dma);
@@ -4190,7 +4247,7 @@ int be_load_fw(struct be_adapter *adapte
 	if (!netif_running(adapter->netdev)) {
 		dev_err(&adapter->pdev->dev,
 			"Firmware load not allowed (interface is down)\n");
-		return -1;
+		return -ENETDOWN;
 	}
 
 	status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
@@ -4205,8 +4262,7 @@ int be_load_fw(struct be_adapter *adapte
 		status = be_fw_download(adapter, fw);
 
 	if (!status)
-		be_cmd_get_fw_ver(adapter, adapter->fw_ver,
-				  adapter->fw_on_flash);
+		be_cmd_get_fw_ver(adapter);
 
 fw_exit:
 	release_firmware(fw);
@@ -4437,12 +4493,12 @@ static int be_map_pci_bars(struct be_ada
 
 	if (BEx_chip(adapter) && be_physfn(adapter)) {
 		adapter->csr = pci_iomap(adapter->pdev, 2, 0);
-		if (adapter->csr == NULL)
+		if (!adapter->csr)
 			return -ENOMEM;
 	}
 
 	addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
-	if (addr == NULL)
+	if (!addr)
 		goto pci_map_err;
 	adapter->db = addr;
 
@@ -4505,7 +4561,7 @@ static int be_ctrl_init(struct be_adapte
 	rx_filter->va = dma_zalloc_coherent(&adapter->pdev->dev,
 					    rx_filter->size, &rx_filter->dma,
 					    GFP_KERNEL);
-	if (rx_filter->va == NULL) {
+	if (!rx_filter->va) {
 		status = -ENOMEM;
 		goto free_mbox;
 	}
@@ -4554,8 +4610,8 @@ static int be_stats_init(struct be_adapt
 
 	cmd->va = dma_zalloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
 				      GFP_KERNEL);
-	if (cmd->va == NULL)
-		return -1;
+	if (!cmd->va)
+		return -ENOMEM;
 	return 0;
 }
 
@@ -4776,7 +4832,7 @@ static int be_probe(struct pci_dev *pdev
 	pci_set_master(pdev);
 
 	netdev = alloc_etherdev_mqs(sizeof(*adapter), MAX_TX_QS, MAX_RX_QS);
-	if (netdev == NULL) {
+	if (!netdev) {
 		status = -ENOMEM;
 		goto rel_reg;
 	}
@@ -4958,6 +5014,7 @@ static void be_shutdown(struct pci_dev *
 	if (!adapter)
 		return;
 
+	be_roce_dev_shutdown(adapter);
 	cancel_delayed_work_sync(&adapter->work);
 	cancel_delayed_work_sync(&adapter->func_recovery_work);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_roce.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_roce.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_roce.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_roce.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,7 +120,8 @@ static void _be_roce_dev_open(struct be_
 {
 	if (ocrdma_drv && adapter->ocrdma_dev &&
 	    ocrdma_drv->state_change_handler)
-		ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+		ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+						 BE_DEV_UP);
 }
 
 void be_roce_dev_open(struct be_adapter *adapter)
@@ -136,7 +137,8 @@ static void _be_roce_dev_close(struct be
 {
 	if (ocrdma_drv && adapter->ocrdma_dev &&
 	    ocrdma_drv->state_change_handler)
-		ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+		ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+						 BE_DEV_DOWN);
 }
 
 void be_roce_dev_close(struct be_adapter *adapter)
@@ -147,6 +149,18 @@ void be_roce_dev_close(struct be_adapter
 		mutex_unlock(&be_adapter_list_lock);
 	}
 }
+
+void be_roce_dev_shutdown(struct be_adapter *adapter)
+{
+	if (be_roce_supported(adapter)) {
+		mutex_lock(&be_adapter_list_lock);
+		if (ocrdma_drv && adapter->ocrdma_dev &&
+		    ocrdma_drv->state_change_handler)
+			ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+							 BE_DEV_SHUTDOWN);
+		mutex_unlock(&be_adapter_list_lock);
+	}
+}
 
 int be_roce_register_driver(struct ocrdma_driver *drv)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_roce.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_roce.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/emulex/benet/be_roce.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/emulex/benet/be_roce.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,7 +62,8 @@ struct ocrdma_driver {
 
 enum {
 	BE_DEV_UP	= 0,
-	BE_DEV_DOWN	= 1
+	BE_DEV_DOWN	= 1,
+	BE_DEV_SHUTDOWN = 2
 };
 
 /* APIs for RoCE driver to register callback handlers,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/fealnx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/fealnx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/fealnx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/fealnx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1936,7 +1936,7 @@ static int netdev_close(struct net_devic
 	return 0;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(fealnx_pci_tbl) = {
+static const struct pci_device_id fealnx_pci_tbl[] = {
 	{0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec.h	2014-09-28 17:29:07.000000000 -0400
@@ -256,12 +256,6 @@ struct bufdesc_ex {
 #define FLAG_RX_CSUM_ENABLED	(BD_ENET_RX_ICE | BD_ENET_RX_PCR)
 #define FLAG_RX_CSUM_ERROR	(BD_ENET_RX_ICE | BD_ENET_RX_PCR)
 
-struct fec_enet_delayed_work {
-	struct delayed_work delay_work;
-	bool timeout;
-	bool trig_tx;
-};
-
 /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
  * tx_bd_base always point to the base of the buffer descriptors.  The
  * cur_rx and cur_tx point to the currently available buffer.
@@ -281,6 +275,9 @@ struct fec_enet_private {
 	struct clk *clk_enet_out;
 	struct clk *clk_ptp;
 
+	bool ptp_clk_on;
+	struct mutex ptp_clk_mutex;
+
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	unsigned char *tx_bounce[TX_RING_SIZE];
 	struct	sk_buff *tx_skbuff[TX_RING_SIZE];
@@ -308,7 +305,6 @@ struct fec_enet_private {
 
 	struct	platform_device *pdev;
 
-	int	opened;
 	int	dev_id;
 
 	/* Phylib and MDIO interface */
@@ -317,6 +313,7 @@ struct fec_enet_private {
 	int	mii_timeout;
 	uint	phy_speed;
 	phy_interface_t	phy_interface;
+	struct device_node *phy_node;
 	int	link;
 	int	full_duplex;
 	int	speed;
@@ -328,6 +325,8 @@ struct fec_enet_private {
 	struct	napi_struct napi;
 	int	csum_flags;
 
+	struct work_struct tx_timeout_work;
+
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_caps;
 	unsigned long last_overflow_check;
@@ -339,8 +338,7 @@ struct fec_enet_private {
 	u32 cycle_speed;
 	int hwts_rx_en;
 	int hwts_tx_en;
-	struct timer_list time_keep;
-	struct fec_enet_delayed_work delay_work;
+	struct delayed_work time_keep;
 	struct regulator *reg_phy;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,6 +52,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/regulator/consumer.h>
 #include <linux/if_vlan.h>
@@ -320,6 +321,27 @@ static void *swap_buffer(void *bufaddr,
 	return bufaddr;
 }
 
+static void fec_dump(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct bufdesc *bdp = fep->tx_bd_base;
+	unsigned int index = 0;
+
+	netdev_info(ndev, "TX ring dump\n");
+	pr_info("Nr     SC     addr       len  SKB\n");
+
+	do {
+		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
+			index,
+			bdp == fep->cur_tx ? 'S' : ' ',
+			bdp == fep->dirty_tx ? 'H' : ' ',
+			bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
+			fep->tx_skbuff[index]);
+		bdp = fec_enet_get_nextdesc(bdp, fep);
+		index++;
+	} while (bdp != fep->tx_bd_base);
+}
+
 static inline bool is_ipv4_pkt(struct sk_buff *skb)
 {
 	return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
@@ -342,22 +364,6 @@ fec_enet_clear_csum(struct sk_buff *skb,
 	return 0;
 }
 
-static void
-fec_enet_submit_work(struct bufdesc *bdp, struct fec_enet_private *fep)
-{
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	struct bufdesc *bdp_pre;
-
-	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
-	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
-	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
-		fep->delay_work.trig_tx = true;
-		schedule_delayed_work(&(fep->delay_work.delay_work),
-					msecs_to_jiffies(1));
-	}
-}
-
 static int
 fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)
 {
@@ -373,6 +379,7 @@ fec_enet_txq_submit_frag_skb(struct sk_b
 	skb_frag_t *this_frag;
 	unsigned int index;
 	void *bufaddr;
+	dma_addr_t addr;
 	int i;
 
 	for (frag = 0; frag < nr_frags; frag++) {
@@ -415,15 +422,16 @@ fec_enet_txq_submit_frag_skb(struct sk_b
 				swap_buffer(bufaddr, frag_len);
 		}
 
-		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-						frag_len, DMA_TO_DEVICE);
-		if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+		addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
+				      DMA_TO_DEVICE);
+		if (dma_mapping_error(&fep->pdev->dev, addr)) {
 			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
 			goto dma_mapping_error;
 		}
 
+		bdp->cbd_bufaddr = addr;
 		bdp->cbd_datlen = frag_len;
 		bdp->cbd_sc = status;
 	}
@@ -450,6 +458,7 @@ static int fec_enet_txq_submit_skb(struc
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	struct bufdesc *bdp, *last_bdp;
 	void *bufaddr;
+	dma_addr_t addr;
 	unsigned short status;
 	unsigned short buflen;
 	unsigned int estatus = 0;
@@ -490,12 +499,9 @@ static int fec_enet_txq_submit_skb(struc
 			swap_buffer(bufaddr, buflen);
 	}
 
-	/* Push the data cache so the CPM does not get stale memory
-	 * data.
-	 */
-	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-					buflen, DMA_TO_DEVICE);
-	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+	/* Push the data cache so the CPM does not get stale memory data. */
+	addr = dma_map_single(&fep->pdev->dev, bufaddr, buflen, DMA_TO_DEVICE);
+	if (dma_mapping_error(&fep->pdev->dev, addr)) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "Tx DMA memory map failed\n");
@@ -537,6 +543,7 @@ static int fec_enet_txq_submit_skb(struc
 	fep->tx_skbuff[index] = skb;
 
 	bdp->cbd_datlen = buflen;
+	bdp->cbd_bufaddr = addr;
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
@@ -544,8 +551,6 @@ static int fec_enet_txq_submit_skb(struc
 	status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
 
-	fec_enet_submit_work(bdp, fep);
-
 	/* If this was the last BD in the ring, start at the beginning again. */
 	bdp = fec_enet_get_nextdesc(last_bdp, fep);
 
@@ -570,12 +575,12 @@ fec_enet_txq_put_data_tso(struct sk_buff
 	struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 	unsigned short status;
 	unsigned int estatus = 0;
+	dma_addr_t addr;
 
 	status = bdp->cbd_sc;
 	status &= ~BD_ENET_TX_STATS;
 
 	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
-	bdp->cbd_datlen = size;
 
 	if (((unsigned long) data) & FEC_ALIGNMENT ||
 		id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
@@ -586,15 +591,17 @@ fec_enet_txq_put_data_tso(struct sk_buff
 			swap_buffer(data, size);
 	}
 
-	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
-					size, DMA_TO_DEVICE);
-	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+	addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
+	if (dma_mapping_error(&fep->pdev->dev, addr)) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "Tx DMA memory map failed\n");
 		return NETDEV_TX_BUSY;
 	}
 
+	bdp->cbd_datlen = size;
+	bdp->cbd_bufaddr = addr;
+
 	if (fep->bufdesc_ex) {
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
@@ -732,8 +739,6 @@ static int fec_enet_txq_submit_tso(struc
 	/* Save skb pointer */
 	fep->tx_skbuff[index] = skb;
 
-	fec_enet_submit_work(bdp, fep);
-
 	skb_tx_timestamp(skb);
 	fep->cur_tx = bdp;
 
@@ -801,7 +806,7 @@ static void fec_enet_bd_init(struct net_
 
 		/* Initialize the BD for every fragment in the page. */
 		bdp->cbd_sc = 0;
-		if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+		if (fep->tx_skbuff[i]) {
 			dev_kfree_skb_any(fep->tx_skbuff[i]);
 			fep->tx_skbuff[i] = NULL;
 		}
@@ -815,12 +820,13 @@ static void fec_enet_bd_init(struct net_
 	fep->dirty_tx = bdp;
 }
 
-/* This function is called to start or restart the FEC during a link
- * change.  This only happens when switching between half and full
- * duplex.
+/*
+ * This function is called to start or restart the FEC during a link
+ * change, transmit timeout, or to reconfigure the FEC.  The network
+ * packet processing for this device must be stopped before this call.
  */
 static void
-fec_restart(struct net_device *ndev, int duplex)
+fec_restart(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
@@ -831,13 +837,6 @@ fec_restart(struct net_device *ndev, int
 	u32 rcntl = OPT_FRAME_SIZE | 0x04;
 	u32 ecntl = 0x2; /* ETHEREN */
 
-	if (netif_running(ndev)) {
-		netif_device_detach(ndev);
-		napi_disable(&fep->napi);
-		netif_stop_queue(ndev);
-		netif_tx_lock_bh(ndev);
-	}
-
 	/* Whack a reset.  We should wait for this. */
 	writel(1, fep->hwp + FEC_ECNTRL);
 	udelay(10);
@@ -878,7 +877,7 @@ fec_restart(struct net_device *ndev, int
 	}
 
 	/* Enable MII mode */
-	if (duplex) {
+	if (fep->full_duplex == DUPLEX_FULL) {
 		/* FD enable */
 		writel(0x04, fep->hwp + FEC_X_CNTRL);
 	} else {
@@ -887,8 +886,6 @@ fec_restart(struct net_device *ndev, int
 		writel(0x0, fep->hwp + FEC_X_CNTRL);
 	}
 
-	fep->full_duplex = duplex;
-
 	/* Set MII speed */
 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
@@ -1006,13 +1003,6 @@ fec_restart(struct net_device *ndev, int
 
 	/* Enable interrupts we wish to service */
 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-
-	if (netif_running(ndev)) {
-		netif_tx_unlock_bh(ndev);
-		netif_wake_queue(ndev);
-		napi_enable(&fep->napi);
-		netif_device_attach(ndev);
-	}
 }
 
 static void
@@ -1050,29 +1040,44 @@ fec_timeout(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	fec_dump(ndev);
+
 	ndev->stats.tx_errors++;
 
-	fep->delay_work.timeout = true;
-	schedule_delayed_work(&(fep->delay_work.delay_work), 0);
+	schedule_work(&fep->tx_timeout_work);
 }
 
-static void fec_enet_work(struct work_struct *work)
+static void fec_enet_timeout_work(struct work_struct *work)
 {
 	struct fec_enet_private *fep =
-		container_of(work,
-			     struct fec_enet_private,
-			     delay_work.delay_work.work);
+		container_of(work, struct fec_enet_private, tx_timeout_work);
+	struct net_device *ndev = fep->netdev;
 
-	if (fep->delay_work.timeout) {
-		fep->delay_work.timeout = false;
-		fec_restart(fep->netdev, fep->full_duplex);
-		netif_wake_queue(fep->netdev);
+	rtnl_lock();
+	if (netif_device_present(ndev) || netif_running(ndev)) {
+		napi_disable(&fep->napi);
+		netif_tx_lock_bh(ndev);
+		fec_restart(ndev);
+		netif_wake_queue(ndev);
+		netif_tx_unlock_bh(ndev);
+		napi_enable(&fep->napi);
 	}
+	rtnl_unlock();
+}
 
-	if (fep->delay_work.trig_tx) {
-		fep->delay_work.trig_tx = false;
-		writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-	}
+static void
+fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
+	struct skb_shared_hwtstamps *hwtstamps)
+{
+	unsigned long flags;
+	u64 ns;
+
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+	ns = timecounter_cyc2time(&fep->tc, ts);
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+	memset(hwtstamps, 0, sizeof(*hwtstamps));
+	hwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
 static void
@@ -1100,6 +1105,7 @@ fec_enet_tx(struct net_device *ndev)
 		index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
 
 		skb = fep->tx_skbuff[index];
+		fep->tx_skbuff[index] = NULL;
 		if (!IS_TSO_HEADER(fep, bdp->cbd_bufaddr))
 			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 					bdp->cbd_datlen, DMA_TO_DEVICE);
@@ -1132,20 +1138,12 @@ fec_enet_tx(struct net_device *ndev)
 		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
 			fep->bufdesc_ex) {
 			struct skb_shared_hwtstamps shhwtstamps;
-			unsigned long flags;
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
-			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-			spin_lock_irqsave(&fep->tmreg_lock, flags);
-			shhwtstamps.hwtstamp = ns_to_ktime(
-				timecounter_cyc2time(&fep->tc, ebdp->ts));
-			spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+			fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps);
 			skb_tstamp_tx(skb, &shhwtstamps);
 		}
 
-		if (status & BD_ENET_TX_READY)
-			netdev_err(ndev, "HEY! Enet xmit interrupt and TX_READY\n");
-
 		/* Deferred means some collisions occurred during transmit,
 		 * but we eventually sent the packet OK.
 		 */
@@ -1154,7 +1152,6 @@ fec_enet_tx(struct net_device *ndev)
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
-		fep->tx_skbuff[index] = NULL;
 
 		fep->dirty_tx = bdp;
 
@@ -1169,7 +1166,10 @@ fec_enet_tx(struct net_device *ndev)
 				netif_wake_queue(ndev);
 		}
 	}
-	return;
+
+	/* ERR006538: Keep the transmitter going */
+	if (bdp != fep->cur_tx && readl(fep->hwp + FEC_X_DES_ACTIVE) == 0)
+		writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 }
 
 /* During a receive, the cur_rx points to the current incoming buffer.
@@ -1215,8 +1215,7 @@ fec_enet_rx(struct net_device *ndev, int
 		if ((status & BD_ENET_RX_LAST) == 0)
 			netdev_err(ndev, "rcv is not +last\n");
 
-		if (!fep->opened)
-			goto rx_processing_done;
+		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
 
 		/* Check for errors. */
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
@@ -1300,18 +1299,9 @@ fec_enet_rx(struct net_device *ndev, int
 			skb->protocol = eth_type_trans(skb, ndev);
 
 			/* Get receive timestamp from the skb */
-			if (fep->hwts_rx_en && fep->bufdesc_ex) {
-				struct skb_shared_hwtstamps *shhwtstamps =
-							    skb_hwtstamps(skb);
-				unsigned long flags;
-
-				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-
-				spin_lock_irqsave(&fep->tmreg_lock, flags);
-				shhwtstamps->hwtstamp = ns_to_ktime(
-				    timecounter_cyc2time(&fep->tc, ebdp->ts));
-				spin_unlock_irqrestore(&fep->tmreg_lock, flags);
-			}
+			if (fep->hwts_rx_en && fep->bufdesc_ex)
+				fec_enet_hwtstamp(fep, ebdp->ts,
+						  skb_hwtstamps(skb));
 
 			if (fep->bufdesc_ex &&
 			    (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
@@ -1369,29 +1359,25 @@ fec_enet_interrupt(int irq, void *dev_id
 {
 	struct net_device *ndev = dev_id;
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	const unsigned napi_mask = FEC_ENET_RXF | FEC_ENET_TXF;
 	uint int_events;
 	irqreturn_t ret = IRQ_NONE;
 
-	do {
-		int_events = readl(fep->hwp + FEC_IEVENT);
-		writel(int_events, fep->hwp + FEC_IEVENT);
+	int_events = readl(fep->hwp + FEC_IEVENT);
+	writel(int_events & ~napi_mask, fep->hwp + FEC_IEVENT);
 
-		if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
-			ret = IRQ_HANDLED;
+	if (int_events & napi_mask) {
+		ret = IRQ_HANDLED;
 
-			/* Disable the RX interrupt */
-			if (napi_schedule_prep(&fep->napi)) {
-				writel(FEC_RX_DISABLED_IMASK,
-					fep->hwp + FEC_IMASK);
-				__napi_schedule(&fep->napi);
-			}
-		}
+		/* Disable the NAPI interrupts */
+		writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+		napi_schedule(&fep->napi);
+	}
 
-		if (int_events & FEC_ENET_MII) {
-			ret = IRQ_HANDLED;
-			complete(&fep->mdio_done);
-		}
-	} while (int_events);
+	if (int_events & FEC_ENET_MII) {
+		ret = IRQ_HANDLED;
+		complete(&fep->mdio_done);
+	}
 
 	return ret;
 }
@@ -1399,8 +1385,16 @@ fec_enet_interrupt(int irq, void *dev_id
 static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 {
 	struct net_device *ndev = napi->dev;
-	int pkts = fec_enet_rx(ndev, budget);
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	int pkts;
+
+	/*
+	 * Clear any pending transmit or receive interrupts before
+	 * processing the rings to avoid racing with the hardware.
+	 */
+	writel(FEC_ENET_RXF | FEC_ENET_TXF, fep->hwp + FEC_IEVENT);
+
+	pkts = fec_enet_rx(ndev, budget);
 
 	fec_enet_tx(ndev);
 
@@ -1498,14 +1492,23 @@ static void fec_enet_adjust_link(struct
 		return;
 	}
 
-	if (phy_dev->link) {
+	/*
+	 * If the netdev is down, or is going down, we're not interested
+	 * in link state events, so just mark our idea of the link as down
+	 * and ignore the event.
+	 */
+	if (!netif_running(ndev) || !netif_device_present(ndev)) {
+		fep->link = 0;
+	} else if (phy_dev->link) {
 		if (!fep->link) {
 			fep->link = phy_dev->link;
 			status_change = 1;
 		}
 
-		if (fep->full_duplex != phy_dev->duplex)
+		if (fep->full_duplex != phy_dev->duplex) {
+			fep->full_duplex = phy_dev->duplex;
 			status_change = 1;
+		}
 
 		if (phy_dev->speed != fep->speed) {
 			fep->speed = phy_dev->speed;
@@ -1513,11 +1516,21 @@ static void fec_enet_adjust_link(struct
 		}
 
 		/* if any of the above changed restart the FEC */
-		if (status_change)
-			fec_restart(ndev, phy_dev->duplex);
+		if (status_change) {
+			napi_disable(&fep->napi);
+			netif_tx_lock_bh(ndev);
+			fec_restart(ndev);
+			netif_wake_queue(ndev);
+			netif_tx_unlock_bh(ndev);
+			napi_enable(&fep->napi);
+		}
 	} else {
 		if (fep->link) {
+			napi_disable(&fep->napi);
+			netif_tx_lock_bh(ndev);
 			fec_stop(ndev);
+			netif_tx_unlock_bh(ndev);
+			napi_enable(&fep->napi);
 			fep->link = phy_dev->link;
 			status_change = 1;
 		}
@@ -1598,17 +1611,27 @@ static int fec_enet_clk_enable(struct ne
 				goto failed_clk_enet_out;
 		}
 		if (fep->clk_ptp) {
+			mutex_lock(&fep->ptp_clk_mutex);
 			ret = clk_prepare_enable(fep->clk_ptp);
-			if (ret)
+			if (ret) {
+				mutex_unlock(&fep->ptp_clk_mutex);
 				goto failed_clk_ptp;
+			} else {
+				fep->ptp_clk_on = true;
+			}
+			mutex_unlock(&fep->ptp_clk_mutex);
 		}
 	} else {
 		clk_disable_unprepare(fep->clk_ahb);
 		clk_disable_unprepare(fep->clk_ipg);
 		if (fep->clk_enet_out)
 			clk_disable_unprepare(fep->clk_enet_out);
-		if (fep->clk_ptp)
+		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);
+		}
 	}
 
 	return 0;
@@ -1636,29 +1659,37 @@ static int fec_enet_mii_probe(struct net
 
 	fep->phy_dev = NULL;
 
-	/* check for attached phy */
-	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
-		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
-			continue;
-		if (fep->mii_bus->phy_map[phy_id] == NULL)
-			continue;
-		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
-			continue;
-		if (dev_id--)
-			continue;
-		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
-		break;
-	}
+	if (fep->phy_node) {
+		phy_dev = of_phy_connect(ndev, fep->phy_node,
+					 &fec_enet_adjust_link, 0,
+					 fep->phy_interface);
+	} else {
+		/* check for attached phy */
+		for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+			if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+				continue;
+			if (fep->mii_bus->phy_map[phy_id] == NULL)
+				continue;
+			if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+				continue;
+			if (dev_id--)
+				continue;
+			strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+			break;
+		}
 
-	if (phy_id >= PHY_MAX_ADDR) {
-		netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
-		strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
-		phy_id = 0;
+		if (phy_id >= PHY_MAX_ADDR) {
+			netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
+			strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+			phy_id = 0;
+		}
+
+		snprintf(phy_name, sizeof(phy_name),
+			 PHY_ID_FMT, mdio_bus_id, phy_id);
+		phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
+				      fep->phy_interface);
 	}
 
-	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
-			      fep->phy_interface);
 	if (IS_ERR(phy_dev)) {
 		netdev_err(ndev, "could not attach to PHY\n");
 		return PTR_ERR(phy_dev);
@@ -1667,6 +1698,7 @@ static int fec_enet_mii_probe(struct net
 	/* mask with MAC supported features */
 	if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
 		phy_dev->supported &= PHY_GBIT_FEATURES;
+		phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
 #if !defined(CONFIG_M5272)
 		phy_dev->supported |= SUPPORTED_Pause;
 #endif
@@ -1694,6 +1726,7 @@ static int fec_enet_mii_init(struct plat
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
+	struct device_node *node;
 	int err = -ENXIO, i;
 
 	/*
@@ -1761,7 +1794,15 @@ static int fec_enet_mii_init(struct plat
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		fep->mii_bus->irq[i] = PHY_POLL;
 
-	if (mdiobus_register(fep->mii_bus))
+	node = of_get_child_by_name(pdev->dev.of_node, "mdio");
+	if (node) {
+		err = of_mdiobus_register(fep->mii_bus, node);
+		of_node_put(node);
+	} else {
+		err = mdiobus_register(fep->mii_bus);
+	}
+
+	if (err)
 		goto err_out_free_mdio_irq;
 
 	mii_cnt++;
@@ -1870,6 +1911,9 @@ static int fec_enet_set_pauseparam(struc
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	if (!fep->phy_dev)
+		return -ENODEV;
+
 	if (pause->tx_pause != pause->rx_pause) {
 		netdev_info(ndev,
 			"hardware only support enable/disable both tx and rx");
@@ -1895,8 +1939,14 @@ static int fec_enet_set_pauseparam(struc
 			fec_stop(ndev);
 		phy_start_aneg(fep->phy_dev);
 	}
-	if (netif_running(ndev))
-		fec_restart(ndev, 0);
+	if (netif_running(ndev)) {
+		napi_disable(&fep->napi);
+		netif_tx_lock_bh(ndev);
+		fec_restart(ndev);
+		netif_wake_queue(ndev);
+		netif_tx_unlock_bh(ndev);
+		napi_enable(&fep->napi);
+	}
 
 	return 0;
 }
@@ -2013,21 +2063,19 @@ static int fec_enet_nway_reset(struct ne
 }
 
 static const struct ethtool_ops fec_enet_ethtool_ops = {
-#if !defined(CONFIG_M5272)
-	.get_pauseparam		= fec_enet_get_pauseparam,
-	.set_pauseparam		= fec_enet_set_pauseparam,
-#endif
 	.get_settings		= fec_enet_get_settings,
 	.set_settings		= fec_enet_set_settings,
 	.get_drvinfo		= fec_enet_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
-	.get_ts_info		= fec_enet_get_ts_info,
 	.nway_reset		= fec_enet_nway_reset,
+	.get_link		= ethtool_op_get_link,
 #ifndef CONFIG_M5272
-	.get_ethtool_stats	= fec_enet_get_ethtool_stats,
+	.get_pauseparam		= fec_enet_get_pauseparam,
+	.set_pauseparam		= fec_enet_set_pauseparam,
 	.get_strings		= fec_enet_get_strings,
+	.get_ethtool_stats	= fec_enet_get_ethtool_stats,
 	.get_sset_count		= fec_enet_get_sset_count,
 #endif
+	.get_ts_info		= fec_enet_get_ts_info,
 };
 
 static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
@@ -2061,18 +2109,23 @@ static void fec_enet_free_buffers(struct
 	bdp = fep->rx_bd_base;
 	for (i = 0; i < fep->rx_ring_size; i++) {
 		skb = fep->rx_skbuff[i];
-
-		if (bdp->cbd_bufaddr)
+		fep->rx_skbuff[i] = NULL;
+		if (skb) {
 			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-		if (skb)
 			dev_kfree_skb(skb);
+		}
 		bdp = fec_enet_get_nextdesc(bdp, fep);
 	}
 
 	bdp = fep->tx_bd_base;
-	for (i = 0; i < fep->tx_ring_size; i++)
+	for (i = 0; i < fep->tx_ring_size; i++) {
 		kfree(fep->tx_bounce[i]);
+		fep->tx_bounce[i] = NULL;
+		skb = fep->tx_skbuff[i];
+		fep->tx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
 }
 
 static int fec_enet_alloc_buffers(struct net_device *ndev)
@@ -2084,21 +2137,23 @@ static int fec_enet_alloc_buffers(struct
 
 	bdp = fep->rx_bd_base;
 	for (i = 0; i < fep->rx_ring_size; i++) {
+		dma_addr_t addr;
+
 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
-		if (!skb) {
-			fec_enet_free_buffers(ndev);
-			return -ENOMEM;
-		}
-		fep->rx_skbuff[i] = skb;
+		if (!skb)
+			goto err_alloc;
 
-		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
+		addr = dma_map_single(&fep->pdev->dev, skb->data,
 				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-		if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
-			fec_enet_free_buffers(ndev);
+		if (dma_mapping_error(&fep->pdev->dev, addr)) {
+			dev_kfree_skb(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Rx DMA memory map failed\n");
-			return -ENOMEM;
+			goto err_alloc;
 		}
+
+		fep->rx_skbuff[i] = skb;
+		bdp->cbd_bufaddr = addr;
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 
 		if (fep->bufdesc_ex) {
@@ -2116,6 +2171,8 @@ static int fec_enet_alloc_buffers(struct
 	bdp = fep->tx_bd_base;
 	for (i = 0; i < fep->tx_ring_size; i++) {
 		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+		if (!fep->tx_bounce[i])
+			goto err_alloc;
 
 		bdp->cbd_sc = 0;
 		bdp->cbd_bufaddr = 0;
@@ -2133,6 +2190,10 @@ static int fec_enet_alloc_buffers(struct
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	return 0;
+
+ err_alloc:
+	fec_enet_free_buffers(ndev);
+	return -ENOMEM;
 }
 
 static int
@@ -2161,10 +2222,10 @@ fec_enet_open(struct net_device *ndev)
 		return ret;
 	}
 
+	fec_restart(ndev);
 	napi_enable(&fep->napi);
 	phy_start(fep->phy_dev);
 	netif_start_queue(ndev);
-	fep->opened = 1;
 	return 0;
 }
 
@@ -2173,17 +2234,17 @@ fec_enet_close(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	/* Don't know what to do yet. */
-	napi_disable(&fep->napi);
-	fep->opened = 0;
-	netif_stop_queue(ndev);
-	fec_stop(ndev);
+	phy_stop(fep->phy_dev);
 
-	if (fep->phy_dev) {
-		phy_stop(fep->phy_dev);
-		phy_disconnect(fep->phy_dev);
+	if (netif_device_present(ndev)) {
+		napi_disable(&fep->napi);
+		netif_tx_disable(ndev);
+		fec_stop(ndev);
 	}
 
+	phy_disconnect(fep->phy_dev);
+	fep->phy_dev = NULL;
+
 	fec_enet_clk_enable(ndev, false);
 	pinctrl_pm_select_sleep_state(&fep->pdev->dev);
 	fec_enet_free_buffers(ndev);
@@ -2310,12 +2371,21 @@ static void fec_poll_controller(struct n
 }
 #endif
 
+#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM
+
 static int fec_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct fec_enet_private *fep = netdev_priv(netdev);
 	netdev_features_t changed = features ^ netdev->features;
 
+	/* Quiesce the device if necessary */
+	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+		napi_disable(&fep->napi);
+		netif_tx_lock_bh(netdev);
+		fec_stop(netdev);
+	}
+
 	netdev->features = features;
 
 	/* Receive checksum has been changed */
@@ -2324,14 +2394,14 @@ static int fec_set_features(struct net_d
 			fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
 		else
 			fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
+	}
 
-		if (netif_running(netdev)) {
-			fec_stop(netdev);
-			fec_restart(netdev, fep->phy_dev->duplex);
-			netif_wake_queue(netdev);
-		} else {
-			fec_restart(netdev, fep->phy_dev->duplex);
-		}
+	/* Resume the device after updates */
+	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+		fec_restart(netdev);
+		netif_wake_queue(netdev);
+		netif_tx_unlock_bh(netdev);
+		napi_enable(&fep->napi);
 	}
 
 	return 0;
@@ -2432,7 +2502,7 @@ static int fec_enet_init(struct net_devi
 
 	ndev->hw_features = ndev->features;
 
-	fec_restart(ndev, 0);
+	fec_restart(ndev);
 
 	return 0;
 }
@@ -2485,6 +2555,7 @@ fec_probe(struct platform_device *pdev)
 	struct resource *r;
 	const struct of_device_id *of_id;
 	static int dev_id;
+	struct device_node *np = pdev->dev.of_node, *phy_node;
 
 	of_id = of_match_device(fec_dt_ids, &pdev->dev);
 	if (of_id)
@@ -2524,6 +2595,18 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
+	phy_node = of_parse_phandle(np, "phy-handle", 0);
+	if (!phy_node && of_phy_is_fixed_link(np)) {
+		ret = of_phy_register_fixed_link(np);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"broken fixed-link specification\n");
+			goto failed_phy;
+		}
+		phy_node = of_node_get(np);
+	}
+	fep->phy_node = phy_node;
+
 	ret = of_get_phy_mode(pdev->dev.of_node);
 	if (ret < 0) {
 		pdata = dev_get_platdata(&pdev->dev);
@@ -2552,6 +2635,8 @@ fec_probe(struct platform_device *pdev)
 	if (IS_ERR(fep->clk_enet_out))
 		fep->clk_enet_out = NULL;
 
+	fep->ptp_clk_on = false;
+	mutex_init(&fep->ptp_clk_mutex);
 	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
 	fep->bufdesc_ex =
 		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
@@ -2615,7 +2700,7 @@ fec_probe(struct platform_device *pdev)
 	if (fep->bufdesc_ex && fep->ptp_clock)
 		netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
 
-	INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
+	INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
 	return 0;
 
 failed_register:
@@ -2628,6 +2713,8 @@ failed_init:
 failed_regulator:
 	fec_enet_clk_enable(ndev, false);
 failed_clk:
+failed_phy:
+	of_node_put(phy_node);
 failed_ioremap:
 	free_netdev(ndev);
 
@@ -2640,31 +2727,37 @@ fec_drv_remove(struct platform_device *p
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	cancel_delayed_work_sync(&(fep->delay_work.delay_work));
+	cancel_delayed_work_sync(&fep->time_keep);
+	cancel_work_sync(&fep->tx_timeout_work);
 	unregister_netdev(ndev);
 	fec_enet_mii_remove(fep);
-	del_timer_sync(&fep->time_keep);
 	if (fep->reg_phy)
 		regulator_disable(fep->reg_phy);
 	if (fep->ptp_clock)
 		ptp_clock_unregister(fep->ptp_clock);
 	fec_enet_clk_enable(ndev, false);
+	of_node_put(fep->phy_node);
 	free_netdev(ndev);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int
-fec_suspend(struct device *dev)
+static int __maybe_unused fec_suspend(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	rtnl_lock();
 	if (netif_running(ndev)) {
-		fec_stop(ndev);
+		phy_stop(fep->phy_dev);
+		napi_disable(&fep->napi);
+		netif_tx_lock_bh(ndev);
 		netif_device_detach(ndev);
+		netif_tx_unlock_bh(ndev);
+		fec_stop(ndev);
 	}
+	rtnl_unlock();
+
 	fec_enet_clk_enable(ndev, false);
 	pinctrl_pm_select_sleep_state(&fep->pdev->dev);
 
@@ -2674,8 +2767,7 @@ fec_suspend(struct device *dev)
 	return 0;
 }
 
-static int
-fec_resume(struct device *dev)
+static int __maybe_unused fec_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -2692,10 +2784,16 @@ fec_resume(struct device *dev)
 	if (ret)
 		goto failed_clk;
 
+	rtnl_lock();
 	if (netif_running(ndev)) {
-		fec_restart(ndev, fep->full_duplex);
+		fec_restart(ndev);
+		netif_tx_lock_bh(ndev);
 		netif_device_attach(ndev);
+		netif_tx_unlock_bh(ndev);
+		napi_enable(&fep->napi);
+		phy_start(fep->phy_dev);
 	}
+	rtnl_unlock();
 
 	return 0;
 
@@ -2704,7 +2802,6 @@ failed_clk:
 		regulator_disable(fep->reg_phy);
 	return ret;
 }
-#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1015,8 +1015,7 @@ mpc52xx_fec_remove(struct platform_devic
 
 	unregister_netdev(ndev);
 
-	if (priv->phy_node)
-		of_node_put(priv->phy_node);
+	of_node_put(priv->phy_node);
 	priv->phy_node = NULL;
 
 	irq_dispose_mapping(ndev->irq);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_ptp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_ptp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fec_ptp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fec_ptp.c	2014-09-28 17:29:07.000000000 -0400
@@ -245,12 +245,20 @@ static int fec_ptp_settime(struct ptp_cl
 	u64 ns;
 	unsigned long flags;
 
+	mutex_lock(&fep->ptp_clk_mutex);
+	/* Check the ptp clock */
+	if (!fep->ptp_clk_on) {
+		mutex_unlock(&fep->ptp_clk_mutex);
+		return -EINVAL;
+	}
+
 	ns = ts->tv_sec * 1000000000ULL;
 	ns += ts->tv_nsec;
 
 	spin_lock_irqsave(&fep->tmreg_lock, flags);
 	timecounter_init(&fep->tc, &fep->cc, ns);
 	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+	mutex_unlock(&fep->ptp_clk_mutex);
 	return 0;
 }
 
@@ -338,17 +346,22 @@ int fec_ptp_get(struct net_device *ndev,
  * fec_time_keep - call timecounter_read every second to avoid timer overrun
  *                 because ENET just support 32bit counter, will timeout in 4s
  */
-static void fec_time_keep(unsigned long _data)
+static void fec_time_keep(struct work_struct *work)
 {
-	struct fec_enet_private *fep = (struct fec_enet_private *)_data;
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct fec_enet_private *fep = container_of(dwork, struct fec_enet_private, time_keep);
 	u64 ns;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fep->tmreg_lock, flags);
-	ns = timecounter_read(&fep->tc);
-	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+	mutex_lock(&fep->ptp_clk_mutex);
+	if (fep->ptp_clk_on) {
+		spin_lock_irqsave(&fep->tmreg_lock, flags);
+		ns = timecounter_read(&fep->tc);
+		spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+	}
+	mutex_unlock(&fep->ptp_clk_mutex);
 
-	mod_timer(&fep->time_keep, jiffies + HZ);
+	schedule_delayed_work(&fep->time_keep, HZ);
 }
 
 /**
@@ -386,15 +399,13 @@ void fec_ptp_init(struct platform_device
 
 	fec_ptp_start_cyclecounter(ndev);
 
-	init_timer(&fep->time_keep);
-	fep->time_keep.data = (unsigned long)fep;
-	fep->time_keep.function = fec_time_keep;
-	fep->time_keep.expires = jiffies + HZ;
-	add_timer(&fep->time_keep);
+	INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep);
 
 	fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
 	if (IS_ERR(fep->ptp_clock)) {
 		fep->ptp_clock = NULL;
 		pr_err("ptp_clock_register failed\n");
 	}
+
+	schedule_delayed_work(&fep->time_keep, HZ);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2014-09-28 17:29:07.000000000 -0400
@@ -1033,7 +1033,7 @@ static int fs_enet_probe(struct platform
 		/* In the case of a fixed PHY, the DT node associated
 		 * to the PHY is the Ethernet MAC DT node.
 		 */
-		fpi->phy_node = ofdev->dev.of_node;
+		fpi->phy_node = of_node_get(ofdev->dev.of_node);
 	}
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,6 @@
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
-#include <asm/mpc8xx.h>
 #include <asm/cpm1.h>
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,6 @@
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
-#include <asm/mpc8xx.h>
 #include <asm/cpm1.h>
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/gianfar.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/gianfar.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/gianfar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/gianfar.c	2014-09-28 17:29:07.000000000 -0400
@@ -892,12 +892,12 @@ static int gfar_of_init(struct platform_
 	/* In the case of a fixed PHY, the DT node associated
 	 * to the PHY is the Ethernet MAC DT node.
 	 */
-	if (of_phy_is_fixed_link(np)) {
+	if (!priv->phy_node && of_phy_is_fixed_link(np)) {
 		err = of_phy_register_fixed_link(np);
 		if (err)
 			goto err_grp_init;
 
-		priv->phy_node = np;
+		priv->phy_node = of_node_get(np);
 	}
 
 	/* Find the TBI PHY.  If it's not there, we don't support SGMII */
@@ -1435,10 +1435,8 @@ register_fail:
 	unmap_group_regs(priv);
 	gfar_free_rx_queues(priv);
 	gfar_free_tx_queues(priv);
-	if (priv->phy_node)
-		of_node_put(priv->phy_node);
-	if (priv->tbi_node)
-		of_node_put(priv->tbi_node);
+	of_node_put(priv->phy_node);
+	of_node_put(priv->tbi_node);
 	free_gfar_dev(priv);
 	return err;
 }
@@ -1447,10 +1445,8 @@ static int gfar_remove(struct platform_d
 {
 	struct gfar_private *priv = platform_get_drvdata(ofdev);
 
-	if (priv->phy_node)
-		of_node_put(priv->phy_node);
-	if (priv->tbi_node)
-		of_node_put(priv->tbi_node);
+	of_node_put(priv->phy_node);
+	of_node_put(priv->tbi_node);
 
 	unregister_netdev(priv->ndev);
 	unmap_group_regs(priv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/ucc_geth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/ucc_geth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/ucc_geth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/ucc_geth.c	2014-09-28 17:29:07.000000000 -0400
@@ -2396,7 +2396,6 @@ static int ucc_geth_startup(struct ucc_g
 		if (netif_msg_ifup(ugeth))
 			pr_err("Bad number of Rx threads value\n");
 		return -EINVAL;
-		break;
 	}
 
 	switch (ug_info->numThreadsTx) {
@@ -2419,7 +2418,6 @@ static int ucc_geth_startup(struct ucc_g
 		if (netif_msg_ifup(ugeth))
 			pr_err("Bad number of Tx threads value\n");
 		return -EINVAL;
-		break;
 	}
 
 	/* Calculate rx_extended_features */
@@ -3787,16 +3785,15 @@ static int ucc_geth_probe(struct platfor
 	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
 
 	ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
-	if (!ug_info->phy_node) {
-		/* In the case of a fixed PHY, the DT node associated
+	if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
+		/*
+		 * In the case of a fixed PHY, the DT node associated
 		 * to the PHY is the Ethernet MAC DT node.
 		 */
-		if (of_phy_is_fixed_link(np)) {
-			err = of_phy_register_fixed_link(np);
-			if (err)
-				return err;
-		}
-		ug_info->phy_node = np;
+		err = of_phy_register_fixed_link(np);
+		if (err)
+			return err;
+		ug_info->phy_node = of_node_get(np);
 	}
 
 	/* Find the TBI PHY node.  If it's not there, we don't support SGMII */
@@ -3864,8 +3861,11 @@ static int ucc_geth_probe(struct platfor
 	/* Create an ethernet device instance */
 	dev = alloc_etherdev(sizeof(*ugeth));
 
-	if (dev == NULL)
+	if (dev == NULL) {
+		of_node_put(ug_info->tbi_node);
+		of_node_put(ug_info->phy_node);
 		return -ENOMEM;
+	}
 
 	ugeth = netdev_priv(dev);
 	spin_lock_init(&ugeth->lock);
@@ -3899,6 +3899,8 @@ static int ucc_geth_probe(struct platfor
 			pr_err("%s: Cannot register net device, aborting\n",
 			       dev->name);
 		free_netdev(dev);
+		of_node_put(ug_info->tbi_node);
+		of_node_put(ug_info->phy_node);
 		return err;
 	}
 
@@ -3922,6 +3924,8 @@ static int ucc_geth_remove(struct platfo
 	unregister_netdev(dev);
 	free_netdev(dev);
 	ucc_geth_memclean(ugeth);
+	of_node_put(ugeth->ug_info->tbi_node);
+	of_node_put(ugeth->ug_info->phy_node);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/freescale/xgmac_mdio.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/xgmac_mdio.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/freescale/xgmac_mdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/freescale/xgmac_mdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ struct tgec_mdio_controller {
 #define MDIO_DATA_BSY		(1 << 31)
 
 /*
- * Wait untill the MDIO bus is free
+ * Wait until the MDIO bus is free
  */
 static int xgmac_wait_until_free(struct device *dev,
 				 struct tgec_mdio_controller __iomem *regs)
@@ -163,7 +163,7 @@ static int xgmac_mdio_read(struct mii_bu
 	/* Return all Fs if nothing was there */
 	if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER) {
 		dev_err(&bus->dev,
-			"Error while reading PHY%d reg at %d.%d\n",
+			"Error while reading PHY%d reg at %d.%hhu\n",
 			phy_id, dev_addr, regnum);
 		return 0xffff;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,23 +99,23 @@ static const struct ethtool_ops netdev_e
 /*
     card type
  */
-typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
+enum cardtype { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
 	       XXX10304, NEC, KME
-} cardtype_t;
+};
 
 /*
     driver specific data structure
 */
-typedef struct local_info_t {
+struct local_info {
 	struct pcmcia_device	*p_dev;
     long open_time;
     uint tx_started:1;
     uint tx_queue;
     u_short tx_queue_len;
-    cardtype_t cardtype;
+    enum cardtype cardtype;
     u_short sent;
     u_char __iomem *base;
-} local_info_t;
+};
 
 #define MC_FILTERBREAK 64
 
@@ -232,13 +232,13 @@ static const struct net_device_ops fjn_n
 
 static int fmvj18x_probe(struct pcmcia_device *link)
 {
-    local_info_t *lp;
+    struct local_info *lp;
     struct net_device *dev;
 
     dev_dbg(&link->dev, "fmvj18x_attach()\n");
 
     /* Make up a FMVJ18x specific data structure */
-    dev = alloc_etherdev(sizeof(local_info_t));
+    dev = alloc_etherdev(sizeof(struct local_info));
     if (!dev)
 	return -ENOMEM;
     lp = netdev_priv(dev);
@@ -327,10 +327,10 @@ static int fmvj18x_ioprobe(struct pcmcia
 static int fmvj18x_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     int i, ret;
     unsigned int ioaddr;
-    cardtype_t cardtype;
+    enum cardtype cardtype;
     char *card_name = "unknown";
     u8 *buf;
     size_t len;
@@ -584,7 +584,7 @@ static int fmvj18x_setup_mfc(struct pcmc
     int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
     link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,7 +626,7 @@ static void fmvj18x_release(struct pcmci
 {
 
     struct net_device *dev = link->priv;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     u_char __iomem *tmp;
 
     dev_dbg(&link->dev, "fmvj18x_release\n");
@@ -711,7 +711,7 @@ module_pcmcia_driver(fmvj18x_cs_driver);
 static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
 {
     struct net_device *dev = dev_id;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr;
     unsigned short tx_stat, rx_stat;
 
@@ -772,7 +772,7 @@ static irqreturn_t fjn_interrupt(int dum
 
 static void fjn_tx_timeout(struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
 
     netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
@@ -802,7 +802,7 @@ static void fjn_tx_timeout(struct net_de
 static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
 					struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     short length = skb->len;
     
@@ -874,7 +874,7 @@ static netdev_tx_t fjn_start_xmit(struct
 
 static void fjn_reset(struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     int i;
 
@@ -1058,7 +1058,7 @@ static int fjn_config(struct net_device
 
 static int fjn_open(struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     struct pcmcia_device *link = lp->p_dev;
 
     pr_debug("fjn_open('%s').\n", dev->name);
@@ -1083,7 +1083,7 @@ static int fjn_open(struct net_device *d
 
 static int fjn_close(struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     struct pcmcia_device *link = lp->p_dev;
     unsigned int ioaddr = dev->base_addr;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/hp/hp100.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/hp/hp100.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/hp/hp100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/hp/hp100.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl
 #endif
 
 #ifdef CONFIG_PCI
-static DEFINE_PCI_DEVICE_TABLE(hp100_pci_tbl) = {
+static const struct pci_device_id hp100_pci_tbl[] = {
 	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,},
 	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,},
 	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -1994,7 +1994,7 @@ static void xmit_common(struct sk_buff *
 {
 	swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
 
-	if (skb->protocol != htons(ETH_P_IP))
+	if (vlan_get_protocol(skb) != htons(ETH_P_IP))
 		return;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ehea/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ehea/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ehea/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ehea/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 #
 # Makefile for the eHEA ethernet device driver for IBM eServer System p
 #
-ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o ehea_phyp.o
+ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o
 obj-$(CONFIG_EHEA) += ehea.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ibmveth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ibmveth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ibm/ibmveth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ibm/ibmveth.c	2014-09-28 17:29:07.000000000 -0400
@@ -292,6 +292,18 @@ failure:
 	atomic_add(buffers_added, &(pool->available));
 }
 
+/*
+ * The final 8 bytes of the buffer list is a counter of frames dropped
+ * because there was not a buffer in the buffer list capable of holding
+ * the frame.
+ */
+static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter)
+{
+	__be64 *p = adapter->buffer_list_addr + 4096 - 8;
+
+	adapter->rx_no_buffer = be64_to_cpup(p);
+}
+
 /* replenish routine */
 static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 {
@@ -307,8 +319,7 @@ static void ibmveth_replenish_task(struc
 			ibmveth_replenish_buffer_pool(adapter, pool);
 	}
 
-	adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) +
-						4096 - 8);
+	ibmveth_update_rx_no_buffer(adapter);
 }
 
 /* empty and free ana buffer pool - also used to do cleanup in error paths */
@@ -698,8 +709,7 @@ static int ibmveth_close(struct net_devi
 
 	free_irq(netdev->irq, netdev);
 
-	adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) +
-						4096 - 8);
+	ibmveth_update_rx_no_buffer(adapter);
 
 	ibmveth_cleanup(adapter);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/icplus/ipg.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/icplus/ipg.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/icplus/ipg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/icplus/ipg.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,7 @@ static const char * const ipg_brand_name
 	"D-Link NIC IP1000A"
 };
 
-static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = {
+static const struct pci_device_id ipg_pci_tbl[] = {
 	{ PCI_VDEVICE(SUNDANCE,	0x1023), 0 },
 	{ PCI_VDEVICE(SUNDANCE,	0x2021), 1 },
 	{ PCI_VDEVICE(DLINK,	0x9021), 2 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -1316,7 +1316,6 @@ static int e1000_set_phy_loopback(struct
 	case e1000_82547:
 	case e1000_82547_rev_2:
 		return e1000_integrated_phy_loopback(adapter);
-		break;
 	default:
 		/* Default PHY loopback work is to read the MII
 		 * control register and assert bit 14 (loopback mode).
@@ -1325,7 +1324,6 @@ static int e1000_set_phy_loopback(struct
 		phy_reg |= MII_CR_LOOPBACK;
 		e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
 		return 0;
-		break;
 	}
 
 	return 8;
@@ -1344,7 +1342,6 @@ static int e1000_setup_loopback_test(str
 		case e1000_82545_rev_3:
 		case e1000_82546_rev_3:
 			return e1000_set_phy_loopback(adapter);
-			break;
 		default:
 			rctl = er32(RCTL);
 			rctl |= E1000_RCTL_LBM_TCVR;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -902,7 +902,6 @@ static s32 e1000_setup_fiber_serdes_link
 	default:
 		e_dbg("Flow control param set incorrectly\n");
 		return -E1000_ERR_CONFIG;
-		break;
 	}
 
 	/* Since auto-negotiation is enabled, take the link out of reset (the
@@ -5041,7 +5040,6 @@ static s32 e1000_get_cable_length(struct
 			break;
 		default:
 			return -E1000_ERR_PHY;
-			break;
 		}
 	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
 		u16 cur_agc_value;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@ static const char e1000_copyright[] = "C
  * Macro expands to...
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
-static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
+static const struct pci_device_id e1000_pci_tbl[] = {
 	INTEL_E1000_ETHERNET_DEVICE(0x1000),
 	INTEL_E1000_ETHERNET_DEVICE(0x1001),
 	INTEL_E1000_ETHERNET_DEVICE(0x1004),
@@ -2674,7 +2674,8 @@ set_itr_now:
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
 static int e1000_tso(struct e1000_adapter *adapter,
-		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
+		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
+		     __be16 protocol)
 {
 	struct e1000_context_desc *context_desc;
 	struct e1000_buffer *buffer_info;
@@ -2692,7 +2693,7 @@ static int e1000_tso(struct e1000_adapte
 
 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 		mss = skb_shinfo(skb)->gso_size;
-		if (skb->protocol == htons(ETH_P_IP)) {
+		if (protocol == htons(ETH_P_IP)) {
 			struct iphdr *iph = ip_hdr(skb);
 			iph->tot_len = 0;
 			iph->check = 0;
@@ -2702,7 +2703,7 @@ static int e1000_tso(struct e1000_adapte
 								 0);
 			cmd_length = E1000_TXD_CMD_IP;
 			ipcse = skb_transport_offset(skb) - 1;
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		} else if (skb_is_gso_v6(skb)) {
 			ipv6_hdr(skb)->payload_len = 0;
 			tcp_hdr(skb)->check =
 				~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
@@ -2745,7 +2746,8 @@ static int e1000_tso(struct e1000_adapte
 }
 
 static bool e1000_tx_csum(struct e1000_adapter *adapter,
-			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
+			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
+			  __be16 protocol)
 {
 	struct e1000_context_desc *context_desc;
 	struct e1000_buffer *buffer_info;
@@ -2756,7 +2758,7 @@ static bool e1000_tx_csum(struct e1000_a
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
 		return false;
 
-	switch (skb->protocol) {
+	switch (protocol) {
 	case cpu_to_be16(ETH_P_IP):
 		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
 			cmd_len |= E1000_TXD_CMD_TCP;
@@ -3097,6 +3099,7 @@ static netdev_tx_t e1000_xmit_frame(stru
 	int count = 0;
 	int tso;
 	unsigned int f;
+	__be16 protocol = vlan_get_protocol(skb);
 
 	/* This goes back to the question of how to logically map a Tx queue
 	 * to a flow.  Right now, performance is impacted slightly negatively
@@ -3210,7 +3213,7 @@ static netdev_tx_t e1000_xmit_frame(stru
 
 	first = tx_ring->next_to_use;
 
-	tso = e1000_tso(adapter, tx_ring, skb);
+	tso = e1000_tso(adapter, tx_ring, skb, protocol);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
@@ -3220,10 +3223,10 @@ static netdev_tx_t e1000_xmit_frame(stru
 		if (likely(hw->mac_type != e1000_82544))
 			tx_ring->last_tx_tso = true;
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb, protocol)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
-	if (likely(skb->protocol == htons(ETH_P_IP)))
+	if (protocol == htons(ETH_P_IP))
 		tx_flags |= E1000_TX_FLAGS_IPV4;
 
 	if (unlikely(skb->no_fcs))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/82571.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/82571.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/82571.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/82571.c	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,6 @@ static s32 e1000_init_phy_params_82571(s
 		break;
 	default:
 		return -E1000_ERR_PHY;
-		break;
 	}
 
 	/* This can only be done after all function pointers are setup. */
@@ -422,7 +421,6 @@ static s32 e1000_get_phy_id_82571(struct
 		break;
 	case e1000_82573:
 		return e1000e_get_phy_id(hw);
-		break;
 	case e1000_82574:
 	case e1000_82583:
 		ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id);
@@ -440,7 +438,6 @@ static s32 e1000_get_phy_id_82571(struct
 		break;
 	default:
 		return -E1000_ERR_PHY;
-		break;
 	}
 
 	return 0;
@@ -1458,7 +1455,6 @@ static s32 e1000_setup_copper_link_82571
 		break;
 	default:
 		return -E1000_ERR_PHY;
-		break;
 	}
 
 	if (ret_val)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/defines.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/defines.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/defines.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/defines.h	2014-09-28 17:29:07.000000000 -0400
@@ -342,6 +342,7 @@
 #define E1000_TIPG_IPGR2_SHIFT  20
 
 #define MAX_JUMBO_FRAME_SIZE    0x3F00
+#define E1000_TX_PTR_GAP		0x1F
 
 /* Extended Configuration Control and Size */
 #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -1521,11 +1521,9 @@ static int e1000_setup_loopback_test(str
 		switch (hw->mac.type) {
 		case e1000_80003es2lan:
 			return e1000_set_es2lan_mac_loopback(adapter);
-			break;
 		case e1000_82571:
 		case e1000_82572:
 			return e1000_set_82571_fiber_loopback(adapter);
-			break;
 		default:
 			rctl = er32(RCTL);
 			rctl |= E1000_RCTL_LBM_TCVR;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.c	2014-09-28 17:29:07.000000000 -0400
@@ -572,7 +572,6 @@ static s32 e1000_init_phy_params_ich8lan
 		break;
 	default:
 		return -E1000_ERR_PHY;
-		break;
 	}
 
 	return 0;
@@ -2445,7 +2444,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(st
 			return ret_val;
 		e1e_rphy(hw, PHY_REG(776, 20), &data);
 		data &= ~(0x3FF << 2);
-		data |= (0x1A << 2);
+		data |= (E1000_TX_PTR_GAP << 2);
 		ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
 		if (ret_val)
 			return ret_val;
@@ -4606,14 +4605,23 @@ void e1000_suspend_workarounds_ich8lan(s
 
 			/* Disable LPLU if both link partners support 100BaseT
 			 * EEE and 100Full is advertised on both ends of the
-			 * link.
+			 * link, and enable Auto Enable LPI since there will
+			 * be no driver to enable LPI while in Sx.
 			 */
 			if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
 			    (dev_spec->eee_lp_ability &
 			     I82579_EEE_100_SUPPORTED) &&
-			    (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+			    (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
 				phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
 					      E1000_PHY_CTRL_NOND0A_LPLU);
+
+				/* Set Auto Enable LPI after link up */
+				e1e_rphy_locked(hw,
+						I217_LPI_GPIO_CTRL, &phy_reg);
+				phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
+				e1e_wphy_locked(hw,
+						I217_LPI_GPIO_CTRL, phy_reg);
+			}
 		}
 
 		/* For i217 Intel Rapid Start Technology support,
@@ -4710,6 +4718,11 @@ void e1000_resume_workarounds_pchlan(str
 			return;
 		}
 
+		/* Clear Auto Enable LPI after link up */
+		e1e_rphy_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg);
+		phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
+		e1e_wphy_locked(hw, I217_LPI_GPIO_CTRL, phy_reg);
+
 		if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
 			/* Restore clear on SMB if no manageability engine
 			 * is present
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/ich8lan.h	2014-09-28 17:29:07.000000000 -0400
@@ -217,6 +217,10 @@
 #define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK	0x3F00
 #define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT	8
 
+/* Low Power Idle GPIO Control */
+#define I217_LPI_GPIO_CTRL			PHY_REG(772, 18)
+#define I217_LPI_GPIO_CTRL_AUTO_EN_LPI		0x0800
+
 /* PHY Low Power Idle Control */
 #define I82579_LPI_CTRL				PHY_REG(772, 20)
 #define I82579_LPI_CTRL_100_ENABLE		0x2000
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/mac.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/mac.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -787,7 +787,6 @@ static s32 e1000_commit_fc_settings_gene
 	default:
 		e_dbg("Flow control param set incorrectly\n");
 		return -E1000_ERR_CONFIG;
-		break;
 	}
 
 	ew32(TXCW, txcw);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/manage.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/manage.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/manage.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/manage.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,7 @@ static u8 e1000_calculate_checksum(u8 *b
  *  e1000_mng_enable_host_if - Checks host interface is enabled
  *  @hw: pointer to the HW structure
  *
- *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
+ *  Returns 0 upon success, else -E1000_ERR_HOST_INTERFACE_COMMAND
  *
  *  This function checks whether the HOST IF is enabled for command operation
  *  and also checks whether the previous command is completed.  It busy waits
@@ -78,7 +78,7 @@ static s32 e1000_mng_enable_host_if(stru
 	}
 
 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
-		e_dbg("Previous command timeout failed .\n");
+		e_dbg("Previous command timeout failed.\n");
 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
 	}
 
@@ -327,9 +327,12 @@ bool e1000e_enable_mng_pass_thru(struct
 	} else if ((hw->mac.type == e1000_82574) ||
 		   (hw->mac.type == e1000_82583)) {
 		u16 data;
+		s32 ret_val;
 
 		factps = er32(FACTPS);
-		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+		ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+		if (ret_val)
+			return false;
 
 		if (!(factps & E1000_FACTPS_MNGCG) &&
 		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/netdev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/netdev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -5164,7 +5164,8 @@ link_up:
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
-static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
+static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb,
+		     __be16 protocol)
 {
 	struct e1000_context_desc *context_desc;
 	struct e1000_buffer *buffer_info;
@@ -5183,7 +5184,7 @@ static int e1000_tso(struct e1000_ring *
 
 	hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	mss = skb_shinfo(skb)->gso_size;
-	if (skb->protocol == htons(ETH_P_IP)) {
+	if (protocol == htons(ETH_P_IP)) {
 		struct iphdr *iph = ip_hdr(skb);
 		iph->tot_len = 0;
 		iph->check = 0;
@@ -5231,7 +5232,8 @@ static int e1000_tso(struct e1000_ring *
 	return 1;
 }
 
-static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb,
+			  __be16 protocol)
 {
 	struct e1000_adapter *adapter = tx_ring->adapter;
 	struct e1000_context_desc *context_desc;
@@ -5239,16 +5241,10 @@ static bool e1000_tx_csum(struct e1000_r
 	unsigned int i;
 	u8 css;
 	u32 cmd_len = E1000_TXD_CMD_DEXT;
-	__be16 protocol;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
 		return false;
 
-	if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
-		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-	else
-		protocol = skb->protocol;
-
 	switch (protocol) {
 	case cpu_to_be16(ETH_P_IP):
 		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
@@ -5546,6 +5542,7 @@ static netdev_tx_t e1000_xmit_frame(stru
 	int count = 0;
 	int tso;
 	unsigned int f;
+	__be16 protocol = vlan_get_protocol(skb);
 
 	if (test_bit(__E1000_DOWN, &adapter->state)) {
 		dev_kfree_skb_any(skb);
@@ -5620,7 +5617,7 @@ static netdev_tx_t e1000_xmit_frame(stru
 
 	first = tx_ring->next_to_use;
 
-	tso = e1000_tso(tx_ring, skb);
+	tso = e1000_tso(tx_ring, skb, protocol);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
@@ -5628,14 +5625,14 @@ static netdev_tx_t e1000_xmit_frame(stru
 
 	if (tso)
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if (e1000_tx_csum(tx_ring, skb))
+	else if (e1000_tx_csum(tx_ring, skb, protocol))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
 	/* Old method was to assume IPv4 packet by default if TSO was enabled.
 	 * 82571 hardware supports TSO capabilities for IPv6 as well...
 	 * no longer assume, we must.
 	 */
-	if (skb->protocol == htons(ETH_P_IP))
+	if (protocol == htons(ETH_P_IP))
 		tx_flags |= E1000_TX_FLAGS_IPV4;
 
 	if (unlikely(skb->no_fcs))
@@ -6033,6 +6030,28 @@ release:
 	return retval;
 }
 
+static void e1000e_flush_lpic(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	u32 ret_val;
+
+	pm_runtime_get_sync(netdev->dev.parent);
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto fl_out;
+
+	pr_info("EEE TX LPI TIMER: %08X\n",
+		er32(LPIC) >> E1000_LPIC_LPIET_SHIFT);
+
+	hw->phy.ops.release(hw);
+
+fl_out:
+	pm_runtime_put_sync(netdev->dev.parent);
+}
+
 static int e1000e_pm_freeze(struct device *dev)
 {
 	struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
@@ -6333,6 +6352,8 @@ static int e1000e_pm_suspend(struct devi
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 
+	e1000e_flush_lpic(pdev);
+
 	e1000e_pm_freeze(dev);
 
 	return __e1000_shutdown(pdev, false);
@@ -6357,9 +6378,14 @@ static int e1000e_pm_runtime_idle(struct
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	u16 eee_lp;
 
-	if (!e1000e_has_link(adapter))
+	eee_lp = adapter->hw.dev_spec.ich8lan.eee_lp_ability;
+
+	if (!e1000e_has_link(adapter)) {
+		adapter->hw.dev_spec.ich8lan.eee_lp_ability = eee_lp;
 		pm_schedule_suspend(dev, 5 * MSEC_PER_SEC);
+	}
 
 	return -EBUSY;
 }
@@ -6411,6 +6437,8 @@ static int e1000e_pm_runtime_suspend(str
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
+	e1000e_flush_lpic(pdev);
+
 	e1000e_pm_freeze(&pdev->dev);
 
 	__e1000_shutdown(pdev, false);
@@ -6708,6 +6736,7 @@ static int e1000_probe(struct pci_dev *p
 	int bars, i, err, pci_using_dac;
 	u16 eeprom_data = 0;
 	u16 eeprom_apme_mask = E1000_EEPROM_APME;
+	s32 rval = 0;
 
 	if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S)
 		aspm_disable_flag = PCIE_LINK_STATE_L0S;
@@ -6940,15 +6969,19 @@ static int e1000_probe(struct pci_dev *p
 	} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
 		if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
 		    (adapter->hw.bus.func == 1))
-			e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_B,
-				       1, &eeprom_data);
+			rval = e1000_read_nvm(&adapter->hw,
+					      NVM_INIT_CONTROL3_PORT_B,
+					      1, &eeprom_data);
 		else
-			e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_A,
-				       1, &eeprom_data);
+			rval = e1000_read_nvm(&adapter->hw,
+					      NVM_INIT_CONTROL3_PORT_A,
+					      1, &eeprom_data);
 	}
 
 	/* fetch WoL from EEPROM */
-	if (eeprom_data & eeprom_apme_mask)
+	if (rval)
+		e_dbg("NVM read error getting WoL initial values: %d\n", rval);
+	else if (eeprom_data & eeprom_apme_mask)
 		adapter->eeprom_wol |= E1000_WUFC_MAG;
 
 	/* now that we have the eeprom settings, apply the special cases
@@ -6967,7 +7000,12 @@ static int e1000_probe(struct pci_dev *p
 		device_wakeup_enable(&pdev->dev);
 
 	/* save off EEPROM version number */
-	e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
+	rval = e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
+
+	if (rval) {
+		e_dbg("NVM read error getting EEPROM version: %d\n", rval);
+		adapter->eeprom_vers = 0;
+	}
 
 	/* reset the hardware with the new settings */
 	e1000e_reset(adapter);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/nvm.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/nvm.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e1000e/nvm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e1000e/nvm.c	2014-09-28 17:29:07.000000000 -0400
@@ -327,8 +327,10 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw
 
 		ew32(EERD, eerd);
 		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
-		if (ret_val)
+		if (ret_val) {
+			e_dbg("NVM read error: %d\n", ret_val);
 			break;
+		}
 
 		data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/e100.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e100.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/e100.c	2014-08-07 04:52:08.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/e100.c	2014-09-28 21:33:37.000000000 -0400
@@ -206,7 +206,7 @@ MODULE_PARM_DESC(use_io, "Force use of i
 #define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
 	PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
 	PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
-static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = {
+static const struct pci_device_id e100_id_table[] = {
 	INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
 	INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
 	INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,8 +38,8 @@ static void i40e_resume_aq(struct i40e_h
  **/
 static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
 {
-	return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
-	       (desc->opcode == i40e_aqc_opc_nvm_update);
+	return (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_erase)) ||
+		(desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_update));
 }
 
 /**
@@ -55,16 +55,24 @@ static void i40e_adminq_init_regs(struct
 		hw->aq.asq.tail = I40E_VF_ATQT1;
 		hw->aq.asq.head = I40E_VF_ATQH1;
 		hw->aq.asq.len  = I40E_VF_ATQLEN1;
+		hw->aq.asq.bal  = I40E_VF_ATQBAL1;
+		hw->aq.asq.bah  = I40E_VF_ATQBAH1;
 		hw->aq.arq.tail = I40E_VF_ARQT1;
 		hw->aq.arq.head = I40E_VF_ARQH1;
 		hw->aq.arq.len  = I40E_VF_ARQLEN1;
+		hw->aq.arq.bal  = I40E_VF_ARQBAL1;
+		hw->aq.arq.bah  = I40E_VF_ARQBAH1;
 	} else {
 		hw->aq.asq.tail = I40E_PF_ATQT;
 		hw->aq.asq.head = I40E_PF_ATQH;
 		hw->aq.asq.len  = I40E_PF_ATQLEN;
+		hw->aq.asq.bal  = I40E_PF_ATQBAL;
+		hw->aq.asq.bah  = I40E_PF_ATQBAH;
 		hw->aq.arq.tail = I40E_PF_ARQT;
 		hw->aq.arq.head = I40E_PF_ARQH;
 		hw->aq.arq.len  = I40E_PF_ARQLEN;
+		hw->aq.arq.bal  = I40E_PF_ARQBAL;
+		hw->aq.arq.bah  = I40E_PF_ARQBAH;
 	}
 }
 
@@ -296,27 +304,18 @@ static i40e_status i40e_config_asq_regs(
 	i40e_status ret_code = 0;
 	u32 reg = 0;
 
-	if (hw->mac.type == I40E_MAC_VF) {
-		/* configure the transmit queue */
-		wr32(hw, I40E_VF_ATQBAH1,
-		    upper_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_VF_ATQBAL1,
-		    lower_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
-					  I40E_VF_ATQLEN1_ATQENABLE_MASK));
-		reg = rd32(hw, I40E_VF_ATQBAL1);
-	} else {
-		/* configure the transmit queue */
-		wr32(hw, I40E_PF_ATQBAH,
-		    upper_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_PF_ATQBAL,
-		    lower_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
-					  I40E_PF_ATQLEN_ATQENABLE_MASK));
-		reg = rd32(hw, I40E_PF_ATQBAL);
-	}
+	/* Clear Head and Tail */
+	wr32(hw, hw->aq.asq.head, 0);
+	wr32(hw, hw->aq.asq.tail, 0);
+
+	/* set starting point */
+	wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
+				  I40E_PF_ATQLEN_ATQENABLE_MASK));
+	wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
+	wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
 
 	/* Check one register to verify that config was applied */
+	reg = rd32(hw, hw->aq.asq.bal);
 	if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
 
@@ -334,30 +333,21 @@ static i40e_status i40e_config_arq_regs(
 	i40e_status ret_code = 0;
 	u32 reg = 0;
 
-	if (hw->mac.type == I40E_MAC_VF) {
-		/* configure the receive queue */
-		wr32(hw, I40E_VF_ARQBAH1,
-		    upper_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_VF_ARQBAL1,
-		    lower_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
-					  I40E_VF_ARQLEN1_ARQENABLE_MASK));
-		reg = rd32(hw, I40E_VF_ARQBAL1);
-	} else {
-		/* configure the receive queue */
-		wr32(hw, I40E_PF_ARQBAH,
-		    upper_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_PF_ARQBAL,
-		    lower_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
-					  I40E_PF_ARQLEN_ARQENABLE_MASK));
-		reg = rd32(hw, I40E_PF_ARQBAL);
-	}
+	/* Clear Head and Tail */
+	wr32(hw, hw->aq.arq.head, 0);
+	wr32(hw, hw->aq.arq.tail, 0);
+
+	/* set starting point */
+	wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
+				  I40E_PF_ARQLEN_ARQENABLE_MASK));
+	wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
+	wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
 
 	/* Update tail in the HW to post pre-allocated buffers */
 	wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
 
 	/* Check one register to verify that config was applied */
+	reg = rd32(hw, hw->aq.arq.bal);
 	if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
 
@@ -499,6 +489,8 @@ static i40e_status i40e_shutdown_asq(str
 	wr32(hw, hw->aq.asq.head, 0);
 	wr32(hw, hw->aq.asq.tail, 0);
 	wr32(hw, hw->aq.asq.len, 0);
+	wr32(hw, hw->aq.asq.bal, 0);
+	wr32(hw, hw->aq.asq.bah, 0);
 
 	/* make sure lock is available */
 	mutex_lock(&hw->aq.asq_mutex);
@@ -530,6 +522,8 @@ static i40e_status i40e_shutdown_arq(str
 	wr32(hw, hw->aq.arq.head, 0);
 	wr32(hw, hw->aq.arq.tail, 0);
 	wr32(hw, hw->aq.arq.len, 0);
+	wr32(hw, hw->aq.arq.bal, 0);
+	wr32(hw, hw->aq.arq.bah, 0);
 
 	/* make sure lock is available */
 	mutex_lock(&hw->aq.arq_mutex);
@@ -577,6 +571,9 @@ i40e_status i40e_init_adminq(struct i40e
 	/* Set up register offsets */
 	i40e_adminq_init_regs(hw);
 
+	/* setup ASQ command write back timeout */
+	hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
+
 	/* allocate the ASQ */
 	ret_code = i40e_init_asq(hw);
 	if (ret_code)
@@ -677,6 +674,10 @@ static u16 i40e_clean_asq(struct i40e_hw
 	desc = I40E_ADMINQ_DESC(*asq, ntc);
 	details = I40E_ADMINQ_DETAILS(*asq, ntc);
 	while (rd32(hw, hw->aq.asq.head) != ntc) {
+		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+			   "%s: ntc %d head %d.\n", __func__, ntc,
+			   rd32(hw, hw->aq.asq.head));
+
 		if (details->callback) {
 			I40E_ADMINQ_CALLBACK cb_func =
 					(I40E_ADMINQ_CALLBACK)details->callback;
@@ -736,6 +737,15 @@ i40e_status i40e_asq_send_command(struct
 	struct i40e_aq_desc *desc_on_ring;
 	bool cmd_completed = false;
 	u16  retval = 0;
+	u32  val = 0;
+
+	val = rd32(hw, hw->aq.asq.head);
+	if (val >= hw->aq.num_asq_entries) {
+		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+			   "AQTX: head overrun at %d\n", val);
+		status = I40E_ERR_QUEUE_EMPTY;
+		goto asq_send_command_exit;
+	}
 
 	if (hw->aq.asq.count == 0) {
 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
@@ -829,6 +839,7 @@ i40e_status i40e_asq_send_command(struct
 	}
 
 	/* bump the tail */
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
 	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff);
 	(hw->aq.asq.next_to_use)++;
 	if (hw->aq.asq.next_to_use == hw->aq.asq.count)
@@ -852,7 +863,7 @@ i40e_status i40e_asq_send_command(struct
 			/* ugh! delay while spin_lock */
 			udelay(delay_len);
 			total_delay += delay_len;
-		} while (total_delay <  I40E_ASQ_CMD_TIMEOUT);
+		} while (total_delay < hw->aq.asq_cmd_timeout);
 	}
 
 	/* if ready, copy the desc back to temp */
@@ -866,6 +877,7 @@ i40e_status i40e_asq_send_command(struct
 				   I40E_DEBUG_AQ_MESSAGE,
 				   "AQTX: Command completed with error 0x%X.\n",
 				   retval);
+
 			/* strip off FW internal code */
 			retval &= 0xff;
 		}
@@ -877,8 +889,9 @@ i40e_status i40e_asq_send_command(struct
 		hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
 	}
 
-	if (i40e_is_nvm_update_op(desc))
-		hw->aq.nvm_busy = true;
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+		   "AQTX: desc and buffer writeback:\n");
+	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
 
 	/* update the error if time out occurred */
 	if ((!cmd_completed) &&
@@ -889,6 +902,9 @@ i40e_status i40e_asq_send_command(struct
 		status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
 	}
 
+	if (!status && i40e_is_nvm_update_op(desc))
+		hw->aq.nvm_busy = true;
+
 asq_send_command_error:
 	mutex_unlock(&hw->aq.asq_mutex);
 asq_send_command_exit:
@@ -951,10 +967,6 @@ i40e_status i40e_clean_arq_element(struc
 	/* now clean the next descriptor */
 	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
 	desc_idx = ntc;
-	i40e_debug_aq(hw,
-		      I40E_DEBUG_AQ_COMMAND,
-		      (void *)desc,
-		      hw->aq.arq.r.arq_bi[desc_idx].va);
 
 	flags = le16_to_cpu(desc->flags);
 	if (flags & I40E_AQ_FLAG_ERR) {
@@ -965,17 +977,17 @@ i40e_status i40e_clean_arq_element(struc
 			   I40E_DEBUG_AQ_MESSAGE,
 			   "AQRX: Event received with error 0x%X.\n",
 			   hw->aq.arq_last_status);
-	} else {
-		e->desc = *desc;
-		datalen = le16_to_cpu(desc->datalen);
-		e->msg_size = min(datalen, e->msg_size);
-		if (e->msg_buf != NULL && (e->msg_size != 0))
-			memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
-			       e->msg_size);
 	}
 
-	if (i40e_is_nvm_update_op(&e->desc))
-		hw->aq.nvm_busy = false;
+	e->desc = *desc;
+	datalen = le16_to_cpu(desc->datalen);
+	e->msg_size = min(datalen, e->msg_size);
+	if (e->msg_buf != NULL && (e->msg_size != 0))
+		memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+		       e->msg_size);
+
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
+	i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
 
 	/* Restore the original datalen and buffer address in the desc,
 	 * FW updates datalen to indicate the event message
@@ -1006,6 +1018,14 @@ clean_arq_element_out:
 		*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
 	mutex_unlock(&hw->aq.arq_mutex);
 
+	if (i40e_is_nvm_update_op(&e->desc)) {
+		hw->aq.nvm_busy = false;
+		if (hw->aq.nvm_release_on_done) {
+			i40e_release_nvm(hw);
+			hw->aq.nvm_release_on_done = false;
+		}
+	}
+
 	return ret_code;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,8 @@ struct i40e_adminq_ring {
 	u32 head;
 	u32 tail;
 	u32 len;
+	u32 bah;
+	u32 bal;
 };
 
 /* ASQ transaction details */
@@ -82,6 +84,7 @@ struct i40e_arq_event_info {
 struct i40e_adminq_info {
 	struct i40e_adminq_ring arq;    /* receive queue */
 	struct i40e_adminq_ring asq;    /* send queue */
+	u32 asq_cmd_timeout;            /* send queue cmd write back timeout*/
 	u16 num_arq_entries;            /* receive queue depth */
 	u16 num_asq_entries;            /* send queue depth */
 	u16 arq_buf_size;               /* receive queue buffer size */
@@ -91,6 +94,7 @@ struct i40e_adminq_info {
 	u16 api_maj_ver;                /* api major version */
 	u16 api_min_ver;                /* api minor version */
 	bool nvm_busy;
+	bool nvm_release_on_done;
 
 	struct mutex asq_mutex; /* Send queue lock */
 	struct mutex arq_mutex; /* Receive queue lock */
@@ -100,6 +104,41 @@ struct i40e_adminq_info {
 	enum i40e_admin_queue_err arq_last_status;
 };
 
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_rc: AdminQ error code to convert
+ **/
+static inline int i40e_aq_rc_to_posix(u16 aq_rc)
+{
+	int aq_to_posix[] = {
+		0,           /* I40E_AQ_RC_OK */
+		-EPERM,      /* I40E_AQ_RC_EPERM */
+		-ENOENT,     /* I40E_AQ_RC_ENOENT */
+		-ESRCH,      /* I40E_AQ_RC_ESRCH */
+		-EINTR,      /* I40E_AQ_RC_EINTR */
+		-EIO,        /* I40E_AQ_RC_EIO */
+		-ENXIO,      /* I40E_AQ_RC_ENXIO */
+		-E2BIG,      /* I40E_AQ_RC_E2BIG */
+		-EAGAIN,     /* I40E_AQ_RC_EAGAIN */
+		-ENOMEM,     /* I40E_AQ_RC_ENOMEM */
+		-EACCES,     /* I40E_AQ_RC_EACCES */
+		-EFAULT,     /* I40E_AQ_RC_EFAULT */
+		-EBUSY,      /* I40E_AQ_RC_EBUSY */
+		-EEXIST,     /* I40E_AQ_RC_EEXIST */
+		-EINVAL,     /* I40E_AQ_RC_EINVAL */
+		-ENOTTY,     /* I40E_AQ_RC_ENOTTY */
+		-ENOSPC,     /* I40E_AQ_RC_ENOSPC */
+		-ENOSYS,     /* I40E_AQ_RC_ENOSYS */
+		-ERANGE,     /* I40E_AQ_RC_ERANGE */
+		-EPIPE,      /* I40E_AQ_RC_EFLUSHED */
+		-ESPIPE,     /* I40E_AQ_RC_BAD_ADDR */
+		-EROFS,      /* I40E_AQ_RC_EMODE */
+		-EFBIG,      /* I40E_AQ_RC_EFBIG */
+	};
+
+	return aq_to_posix[aq_rc];
+}
+
 /* general information */
 #define I40E_AQ_LARGE_BUF	512
 #define I40E_ASQ_CMD_TIMEOUT	100000  /* usecs */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -554,7 +554,6 @@ i40e_status i40e_init_shared_code(struct
 		break;
 	default:
 		return I40E_ERR_DEVICE_NOT_SUPPORTED;
-		break;
 	}
 
 	hw->phy.get_link_info = true;
@@ -655,6 +654,31 @@ i40e_status i40e_get_mac_addr(struct i40
 }
 
 /**
+ * i40e_get_port_mac_addr - get Port MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: pointer to Port MAC address
+ *
+ * Reads the adapter's Port MAC address
+ **/
+i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
+{
+	struct i40e_aqc_mac_address_read_data addrs;
+	i40e_status status;
+	u16 flags = 0;
+
+	status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
+	if (status)
+		return status;
+
+	if (flags & I40E_AQC_PORT_ADDR_VALID)
+		memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac));
+	else
+		status = I40E_ERR_INVALID_MAC_ADDR;
+
+	return status;
+}
+
+/**
  * i40e_pre_tx_queue_cfg - pre tx queue configure
  * @hw: pointer to the HW structure
  * @queue: target pf queue index
@@ -669,8 +693,10 @@ void i40e_pre_tx_queue_cfg(struct i40e_h
 	u32 reg_block = 0;
 	u32 reg_val;
 
-	if (abs_queue_idx >= 128)
+	if (abs_queue_idx >= 128) {
 		reg_block = abs_queue_idx / 128;
+		abs_queue_idx %= 128;
+	}
 
 	reg_val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block));
 	reg_val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK;
@@ -683,6 +709,33 @@ void i40e_pre_tx_queue_cfg(struct i40e_h
 
 	wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val);
 }
+#ifdef I40E_FCOE
+
+/**
+ * i40e_get_san_mac_addr - get SAN MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: pointer to SAN MAC address
+ *
+ * Reads the adapter's SAN MAC address from NVM
+ **/
+i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
+{
+	struct i40e_aqc_mac_address_read_data addrs;
+	i40e_status status;
+	u16 flags = 0;
+
+	status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
+	if (status)
+		return status;
+
+	if (flags & I40E_AQC_SAN_ADDR_VALID)
+		memcpy(mac_addr, &addrs.pf_san_mac, sizeof(addrs.pf_san_mac));
+	else
+		status = I40E_ERR_INVALID_MAC_ADDR;
+
+	return status;
+}
+#endif
 
 /**
  * i40e_get_media_type - Gets media type
@@ -811,6 +864,99 @@ i40e_status i40e_pf_reset(struct i40e_hw
 }
 
 /**
+ * i40e_clear_hw - clear out any left over hw state
+ * @hw: pointer to the hw struct
+ *
+ * Clear queues and interrupts, typically called at init time,
+ * but after the capabilities have been found so we know how many
+ * queues and msix vectors have been allocated.
+ **/
+void i40e_clear_hw(struct i40e_hw *hw)
+{
+	u32 num_queues, base_queue;
+	u32 num_pf_int;
+	u32 num_vf_int;
+	u32 num_vfs;
+	u32 i, j;
+	u32 val;
+	u32 eol = 0x7ff;
+
+	/* get number of interrupts, queues, and vfs */
+	val = rd32(hw, I40E_GLPCI_CNF2);
+	num_pf_int = (val & I40E_GLPCI_CNF2_MSI_X_PF_N_MASK) >>
+		     I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT;
+	num_vf_int = (val & I40E_GLPCI_CNF2_MSI_X_VF_N_MASK) >>
+		     I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT;
+
+	val = rd32(hw, I40E_PFLAN_QALLOC);
+	base_queue = (val & I40E_PFLAN_QALLOC_FIRSTQ_MASK) >>
+		     I40E_PFLAN_QALLOC_FIRSTQ_SHIFT;
+	j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >>
+	    I40E_PFLAN_QALLOC_LASTQ_SHIFT;
+	if (val & I40E_PFLAN_QALLOC_VALID_MASK)
+		num_queues = (j - base_queue) + 1;
+	else
+		num_queues = 0;
+
+	val = rd32(hw, I40E_PF_VT_PFALLOC);
+	i = (val & I40E_PF_VT_PFALLOC_FIRSTVF_MASK) >>
+	    I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT;
+	j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >>
+	    I40E_PF_VT_PFALLOC_LASTVF_SHIFT;
+	if (val & I40E_PF_VT_PFALLOC_VALID_MASK)
+		num_vfs = (j - i) + 1;
+	else
+		num_vfs = 0;
+
+	/* stop all the interrupts */
+	wr32(hw, I40E_PFINT_ICR0_ENA, 0);
+	val = 0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
+	for (i = 0; i < num_pf_int - 2; i++)
+		wr32(hw, I40E_PFINT_DYN_CTLN(i), val);
+
+	/* Set the FIRSTQ_INDX field to 0x7FF in PFINT_LNKLSTx */
+	val = eol << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT;
+	wr32(hw, I40E_PFINT_LNKLST0, val);
+	for (i = 0; i < num_pf_int - 2; i++)
+		wr32(hw, I40E_PFINT_LNKLSTN(i), val);
+	val = eol << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT;
+	for (i = 0; i < num_vfs; i++)
+		wr32(hw, I40E_VPINT_LNKLST0(i), val);
+	for (i = 0; i < num_vf_int - 2; i++)
+		wr32(hw, I40E_VPINT_LNKLSTN(i), val);
+
+	/* warn the HW of the coming Tx disables */
+	for (i = 0; i < num_queues; i++) {
+		u32 abs_queue_idx = base_queue + i;
+		u32 reg_block = 0;
+
+		if (abs_queue_idx >= 128) {
+			reg_block = abs_queue_idx / 128;
+			abs_queue_idx %= 128;
+		}
+
+		val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block));
+		val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK;
+		val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT);
+		val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK;
+
+		wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), val);
+	}
+	udelay(400);
+
+	/* stop all the queues */
+	for (i = 0; i < num_queues; i++) {
+		wr32(hw, I40E_QINT_TQCTL(i), 0);
+		wr32(hw, I40E_QTX_ENA(i), 0);
+		wr32(hw, I40E_QINT_RQCTL(i), 0);
+		wr32(hw, I40E_QRX_ENA(i), 0);
+	}
+
+	/* short wait for all queue disables to settle */
+	udelay(50);
+}
+
+/**
  * i40e_clear_pxe_mode - clear pxe operations mode
  * @hw: pointer to the hw struct
  *
@@ -942,6 +1088,164 @@ void i40e_led_set(struct i40e_hw *hw, u3
 /* Admin command wrappers */
 
 /**
+ * i40e_aq_get_phy_capabilities
+ * @hw: pointer to the hw struct
+ * @abilities: structure for PHY capabilities to be filled
+ * @qualified_modules: report Qualified Modules
+ * @report_init: report init capabilities (active are default)
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Returns the various PHY abilities supported on the Port.
+ **/
+i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
+			bool qualified_modules, bool report_init,
+			struct i40e_aq_get_phy_abilities_resp *abilities,
+			struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	i40e_status status;
+	u16 abilities_size = sizeof(struct i40e_aq_get_phy_abilities_resp);
+
+	if (!abilities)
+		return I40E_ERR_PARAM;
+
+	i40e_fill_default_direct_cmd_desc(&desc,
+					  i40e_aqc_opc_get_phy_abilities);
+
+	desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+	if (abilities_size > I40E_AQ_LARGE_BUF)
+		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+
+	if (qualified_modules)
+		desc.params.external.param0 |=
+			cpu_to_le32(I40E_AQ_PHY_REPORT_QUALIFIED_MODULES);
+
+	if (report_init)
+		desc.params.external.param0 |=
+			cpu_to_le32(I40E_AQ_PHY_REPORT_INITIAL_VALUES);
+
+	status = i40e_asq_send_command(hw, &desc, abilities, abilities_size,
+				       cmd_details);
+
+	if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
+		status = I40E_ERR_UNKNOWN_PHY;
+
+	return status;
+}
+
+/**
+ * i40e_aq_set_phy_config
+ * @hw: pointer to the hw struct
+ * @config: structure with PHY configuration to be set
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Set the various PHY configuration parameters
+ * supported on the Port.One or more of the Set PHY config parameters may be
+ * ignored in an MFP mode as the PF may not have the privilege to set some
+ * of the PHY Config parameters. This status will be indicated by the
+ * command response.
+ **/
+enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
+				struct i40e_aq_set_phy_config *config,
+				struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	struct i40e_aq_set_phy_config *cmd =
+			(struct i40e_aq_set_phy_config *)&desc.params.raw;
+	enum i40e_status_code status;
+
+	if (!config)
+		return I40E_ERR_PARAM;
+
+	i40e_fill_default_direct_cmd_desc(&desc,
+					  i40e_aqc_opc_set_phy_config);
+
+	*cmd = *config;
+
+	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+	return status;
+}
+
+/**
+ * i40e_set_fc
+ * @hw: pointer to the hw struct
+ *
+ * Set the requested flow control mode using set_phy_config.
+ **/
+enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
+				  bool atomic_restart)
+{
+	enum i40e_fc_mode fc_mode = hw->fc.requested_mode;
+	struct i40e_aq_get_phy_abilities_resp abilities;
+	struct i40e_aq_set_phy_config config;
+	enum i40e_status_code status;
+	u8 pause_mask = 0x0;
+
+	*aq_failures = 0x0;
+
+	switch (fc_mode) {
+	case I40E_FC_FULL:
+		pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX;
+		pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX;
+		break;
+	case I40E_FC_RX_PAUSE:
+		pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX;
+		break;
+	case I40E_FC_TX_PAUSE:
+		pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX;
+		break;
+	default:
+		break;
+	}
+
+	/* Get the current phy config */
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+					      NULL);
+	if (status) {
+		*aq_failures |= I40E_SET_FC_AQ_FAIL_GET;
+		return status;
+	}
+
+	memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
+	/* clear the old pause settings */
+	config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) &
+			   ~(I40E_AQ_PHY_FLAG_PAUSE_RX);
+	/* set the new abilities */
+	config.abilities |= pause_mask;
+	/* If the abilities have changed, then set the new config */
+	if (config.abilities != abilities.abilities) {
+		/* Auto restart link so settings take effect */
+		if (atomic_restart)
+			config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+		/* Copy over all the old settings */
+		config.phy_type = abilities.phy_type;
+		config.link_speed = abilities.link_speed;
+		config.eee_capability = abilities.eee_capability;
+		config.eeer = abilities.eeer_val;
+		config.low_power_ctrl = abilities.d3_lpan;
+		status = i40e_aq_set_phy_config(hw, &config, NULL);
+
+		if (status)
+			*aq_failures |= I40E_SET_FC_AQ_FAIL_SET;
+	}
+	/* Update the link info */
+	status = i40e_update_link_info(hw, true);
+	if (status) {
+		/* Wait a little bit (on 40G cards it sometimes takes a really
+		 * long time for link to come back from the atomic reset)
+		 * and try once more
+		 */
+		msleep(1000);
+		status = i40e_update_link_info(hw, true);
+	}
+	if (status)
+		*aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE;
+
+	return status;
+}
+
+/**
  * i40e_aq_clear_pxe_mode
  * @hw: pointer to the hw struct
  * @cmd_details: pointer to command details structure or NULL
@@ -971,12 +1275,14 @@ i40e_status i40e_aq_clear_pxe_mode(struc
 /**
  * i40e_aq_set_link_restart_an
  * @hw: pointer to the hw struct
+ * @enable_link: if true: enable link, if false: disable link
  * @cmd_details: pointer to command details structure or NULL
  *
  * Sets up the link and restarts the Auto-Negotiation over the link.
  **/
 i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
-				struct i40e_asq_cmd_details *cmd_details)
+					bool enable_link,
+					struct i40e_asq_cmd_details *cmd_details)
 {
 	struct i40e_aq_desc desc;
 	struct i40e_aqc_set_link_restart_an *cmd =
@@ -987,6 +1293,10 @@ i40e_status i40e_aq_set_link_restart_an(
 					  i40e_aqc_opc_set_link_restart_an);
 
 	cmd->command = I40E_AQ_PHY_RESTART_AN;
+	if (enable_link)
+		cmd->command |= I40E_AQ_PHY_LINK_ENABLE;
+	else
+		cmd->command &= ~I40E_AQ_PHY_LINK_ENABLE;
 
 	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
@@ -1011,6 +1321,7 @@ i40e_status i40e_aq_get_link_info(struct
 		(struct i40e_aqc_get_link_status *)&desc.params.raw;
 	struct i40e_link_status *hw_link_info = &hw->phy.link_info;
 	i40e_status status;
+	bool tx_pause, rx_pause;
 	u16 command_flags;
 
 	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_link_status);
@@ -1040,6 +1351,18 @@ i40e_status i40e_aq_get_link_info(struct
 	hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size);
 	hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
 
+	/* update fc info */
+	tx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_TX);
+	rx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_RX);
+	if (tx_pause & rx_pause)
+		hw->fc.current_mode = I40E_FC_FULL;
+	else if (tx_pause)
+		hw->fc.current_mode = I40E_FC_TX_PAUSE;
+	else if (rx_pause)
+		hw->fc.current_mode = I40E_FC_RX_PAUSE;
+	else
+		hw->fc.current_mode = I40E_FC_NONE;
+
 	if (resp->config & I40E_AQ_CONFIG_CRC_ENA)
 		hw_link_info->crc_enable = true;
 	else
@@ -1062,6 +1385,35 @@ aq_get_link_info_exit:
 }
 
 /**
+ * i40e_update_link_info
+ * @hw: pointer to the hw struct
+ * @enable_lse: enable/disable LinkStatusEvent reporting
+ *
+ * Returns the link status of the adapter
+ **/
+i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse)
+{
+	struct i40e_aq_get_phy_abilities_resp abilities;
+	i40e_status status;
+
+	status = i40e_aq_get_link_info(hw, enable_lse, NULL, NULL);
+	if (status)
+		return status;
+
+	status = i40e_aq_get_phy_capabilities(hw, false, false,
+					      &abilities, NULL);
+	if (status)
+		return status;
+
+	if (abilities.abilities & I40E_AQ_PHY_AN_ENABLED)
+		hw->phy.link_info.an_enabled = true;
+	else
+		hw->phy.link_info.an_enabled = false;
+
+	return status;
+}
+
+/**
  * i40e_aq_add_vsi
  * @hw: pointer to the hw struct
  * @vsi_ctx: pointer to a vsi context struct
@@ -1650,6 +2002,35 @@ i40e_status i40e_aq_send_msg_to_vf(struc
 }
 
 /**
+ * i40e_aq_debug_write_register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Write to a register using the admin queue commands
+ **/
+i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
+					u32 reg_addr, u64 reg_val,
+					struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	struct i40e_aqc_debug_reg_read_write *cmd =
+		(struct i40e_aqc_debug_reg_read_write *)&desc.params.raw;
+	i40e_status status;
+
+	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_write_reg);
+
+	cmd->address = cpu_to_le32(reg_addr);
+	cmd->value_high = cpu_to_le32((u32)(reg_val >> 32));
+	cmd->value_low = cpu_to_le32((u32)(reg_val & 0xFFFFFFFF));
+
+	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+	return status;
+}
+
+/**
  * i40e_aq_set_hmc_resource_profile
  * @hw: pointer to the hw struct
  * @profile: type of profile the HMC is to be set as
@@ -1796,6 +2177,47 @@ i40e_aq_read_nvm_exit:
 	return status;
 }
 
+/**
+ * i40e_aq_erase_nvm
+ * @hw: pointer to the hw struct
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: offset in the module (expressed in 4 KB from module's beginning)
+ * @length: length of the section to be erased (expressed in 4 KB)
+ * @last_command: tells if this is the last command in a series
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Erase the NVM sector using the admin queue commands
+ **/
+i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
+			      u32 offset, u16 length, bool last_command,
+			      struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	struct i40e_aqc_nvm_update *cmd =
+		(struct i40e_aqc_nvm_update *)&desc.params.raw;
+	i40e_status status;
+
+	/* In offset the highest byte must be zeroed. */
+	if (offset & 0xFF000000) {
+		status = I40E_ERR_PARAM;
+		goto i40e_aq_erase_nvm_exit;
+	}
+
+	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_erase);
+
+	/* If this is the last command in a series, set the proper flag. */
+	if (last_command)
+		cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
+	cmd->module_pointer = module_pointer;
+	cmd->offset = cpu_to_le32(offset);
+	cmd->length = cpu_to_le16(length);
+
+	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+i40e_aq_erase_nvm_exit:
+	return status;
+}
+
 #define I40E_DEV_FUNC_CAP_SWITCH_MODE	0x01
 #define I40E_DEV_FUNC_CAP_MGMT_MODE	0x02
 #define I40E_DEV_FUNC_CAP_NPAR		0x03
@@ -1839,7 +2261,6 @@ static void i40e_parse_discover_capabili
 	struct i40e_aqc_list_capabilities_element_resp *cap;
 	u32 number, logical_id, phys_id;
 	struct i40e_hw_capabilities *p;
-	u32 reg_val;
 	u32 i = 0;
 	u16 id;
 
@@ -1910,11 +2331,7 @@ static void i40e_parse_discover_capabili
 			break;
 		case I40E_DEV_FUNC_CAP_RSS:
 			p->rss = true;
-			reg_val = rd32(hw, I40E_PFQF_CTL_0);
-			if (reg_val & I40E_PFQF_CTL_0_HASHLUTSIZE_MASK)
-				p->rss_table_size = number;
-			else
-				p->rss_table_size = 128;
+			p->rss_table_size = number;
 			p->rss_table_entry_width = logical_id;
 			break;
 		case I40E_DEV_FUNC_CAP_RX_QUEUES:
@@ -2030,6 +2447,53 @@ exit:
 	return status;
 }
 
+/**
+ * i40e_aq_update_nvm
+ * @hw: pointer to the hw struct
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: byte offset from the module beginning
+ * @length: length of the section to be written (in bytes from the offset)
+ * @data: command buffer (size [bytes] = length)
+ * @last_command: tells if this is the last command in a series
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Update the NVM using the admin queue commands
+ **/
+i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
+			       u32 offset, u16 length, void *data,
+			       bool last_command,
+			       struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	struct i40e_aqc_nvm_update *cmd =
+		(struct i40e_aqc_nvm_update *)&desc.params.raw;
+	i40e_status status;
+
+	/* In offset the highest byte must be zeroed. */
+	if (offset & 0xFF000000) {
+		status = I40E_ERR_PARAM;
+		goto i40e_aq_update_nvm_exit;
+	}
+
+	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
+
+	/* If this is the last command in a series, set the proper flag. */
+	if (last_command)
+		cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
+	cmd->module_pointer = module_pointer;
+	cmd->offset = cpu_to_le32(offset);
+	cmd->length = cpu_to_le16(length);
+
+	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
+	if (length > I40E_AQ_LARGE_BUF)
+		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+
+	status = i40e_asq_send_command(hw, &desc, data, length, cmd_details);
+
+i40e_aq_update_nvm_exit:
+	return status;
+}
+
 /**
  * i40e_aq_get_lldp_mib
  * @hw: pointer to the hw struct
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -697,6 +697,25 @@ static void i40e_dbg_dump_vsi_seid(struc
 			 vsi->bw_ets_limit_credits[i],
 			 vsi->bw_ets_max_quanta[i]);
 	}
+#ifdef I40E_FCOE
+	if (vsi->type == I40E_VSI_FCOE) {
+		dev_info(&pf->pdev->dev,
+			 "    fcoe_stats: rx_packets = %llu, rx_dwords = %llu, rx_dropped = %llu\n",
+			 vsi->fcoe_stats.rx_fcoe_packets,
+			 vsi->fcoe_stats.rx_fcoe_dwords,
+			 vsi->fcoe_stats.rx_fcoe_dropped);
+		dev_info(&pf->pdev->dev,
+			 "    fcoe_stats: tx_packets = %llu, tx_dwords = %llu\n",
+			 vsi->fcoe_stats.tx_fcoe_packets,
+			 vsi->fcoe_stats.tx_fcoe_dwords);
+		dev_info(&pf->pdev->dev,
+			 "    fcoe_stats: bad_crc = %llu, last_error = %llu\n",
+			 vsi->fcoe_stats.fcoe_bad_fccrc,
+			 vsi->fcoe_stats.fcoe_last_error);
+		dev_info(&pf->pdev->dev, "    fcoe_stats: ddp_count = %llu\n",
+			 vsi->fcoe_stats.fcoe_ddp_count);
+	}
+#endif
 }
 
 /**
@@ -1238,7 +1257,7 @@ static ssize_t i40e_dbg_command_write(st
 	} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {
 		i40e_status ret;
 		u16 vid;
-		int v;
+		unsigned int v;
 
 		cnt = sscanf(&cmd_buf[8], "%i %u", &vsi_seid, &v);
 		if (cnt != 2) {
@@ -1254,7 +1273,7 @@ static ssize_t i40e_dbg_command_write(st
 			goto command_write_done;
 		}
 
-		vid = (unsigned)v;
+		vid = v;
 		ret = i40e_vsi_add_pvid(vsi, vid);
 		if (!ret)
 			dev_info(&pf->pdev->dev,
@@ -1743,6 +1762,9 @@ static ssize_t i40e_dbg_command_write(st
 		i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false);
 	} else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) {
 		i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true);
+	} else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) {
+		dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n",
+			 i40e_get_current_fd_count(pf));
 	} else if (strncmp(cmd_buf, "lldp", 4) == 0) {
 		if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
 			int ret;
@@ -1830,7 +1852,7 @@ static ssize_t i40e_dbg_command_write(st
 
 			ret = i40e_aq_get_lldp_mib(&pf->hw,
 					I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
-					I40E_AQ_LLDP_MIB_LOCAL,
+					I40E_AQ_LLDP_MIB_REMOTE,
 					buff, I40E_LLDPDU_SIZE,
 					&llen, &rlen, NULL);
 			if (ret) {
@@ -1962,6 +1984,7 @@ static ssize_t i40e_dbg_command_write(st
 		dev_info(&pf->pdev->dev, "  rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
 		dev_info(&pf->pdev->dev, "  fd-atr off\n");
 		dev_info(&pf->pdev->dev, "  fd-atr on\n");
+		dev_info(&pf->pdev->dev, "  fd current cnt");
 		dev_info(&pf->pdev->dev, "  lldp start\n");
 		dev_info(&pf->pdev->dev, "  lldp stop\n");
 		dev_info(&pf->pdev->dev, "  lldp get local\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -155,6 +155,19 @@ static struct i40e_stats i40e_gstrings_s
 	I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count),
 };
 
+#ifdef I40E_FCOE
+static const struct i40e_stats i40e_gstrings_fcoe_stats[] = {
+	I40E_VSI_STAT("fcoe_bad_fccrc", fcoe_stats.fcoe_bad_fccrc),
+	I40E_VSI_STAT("rx_fcoe_dropped", fcoe_stats.rx_fcoe_dropped),
+	I40E_VSI_STAT("rx_fcoe_packets", fcoe_stats.rx_fcoe_packets),
+	I40E_VSI_STAT("rx_fcoe_dwords", fcoe_stats.rx_fcoe_dwords),
+	I40E_VSI_STAT("fcoe_ddp_count", fcoe_stats.fcoe_ddp_count),
+	I40E_VSI_STAT("fcoe_last_error", fcoe_stats.fcoe_last_error),
+	I40E_VSI_STAT("tx_fcoe_packets", fcoe_stats.tx_fcoe_packets),
+	I40E_VSI_STAT("tx_fcoe_dwords", fcoe_stats.tx_fcoe_dwords),
+};
+
+#endif /* I40E_FCOE */
 #define I40E_QUEUE_STATS_LEN(n) \
 	(((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \
 	    * 2 /* Tx and Rx together */                                     \
@@ -162,9 +175,17 @@ static struct i40e_stats i40e_gstrings_s
 #define I40E_GLOBAL_STATS_LEN	ARRAY_SIZE(i40e_gstrings_stats)
 #define I40E_NETDEV_STATS_LEN   ARRAY_SIZE(i40e_gstrings_net_stats)
 #define I40E_MISC_STATS_LEN	ARRAY_SIZE(i40e_gstrings_misc_stats)
+#ifdef I40E_FCOE
+#define I40E_FCOE_STATS_LEN	ARRAY_SIZE(i40e_gstrings_fcoe_stats)
+#define I40E_VSI_STATS_LEN(n)	(I40E_NETDEV_STATS_LEN + \
+				 I40E_FCOE_STATS_LEN + \
+				 I40E_MISC_STATS_LEN + \
+				 I40E_QUEUE_STATS_LEN((n)))
+#else
 #define I40E_VSI_STATS_LEN(n)   (I40E_NETDEV_STATS_LEN + \
 				 I40E_MISC_STATS_LEN + \
 				 I40E_QUEUE_STATS_LEN((n)))
+#endif /* I40E_FCOE */
 #define I40E_PFC_STATS_LEN ( \
 		(FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \
 		 FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_rx) + \
@@ -215,52 +236,135 @@ static int i40e_get_settings(struct net_
 	/* hardware is either in 40G mode or 10G mode
 	 * NOTE: this section initializes supported and advertising
 	 */
+	if (!link_up) {
+		/* link is down and the driver needs to fall back on
+		 * device ID to determine what kinds of info to display,
+		 * it's mostly a guess that may change when link is up
+		 */
+		switch (hw->device_id) {
+		case I40E_DEV_ID_QSFP_A:
+		case I40E_DEV_ID_QSFP_B:
+		case I40E_DEV_ID_QSFP_C:
+			/* pluggable QSFP */
+			ecmd->supported = SUPPORTED_40000baseSR4_Full |
+					  SUPPORTED_40000baseCR4_Full |
+					  SUPPORTED_40000baseLR4_Full;
+			ecmd->advertising = ADVERTISED_40000baseSR4_Full |
+					    ADVERTISED_40000baseCR4_Full |
+					    ADVERTISED_40000baseLR4_Full;
+			break;
+		case I40E_DEV_ID_KX_B:
+			/* backplane 40G */
+			ecmd->supported = SUPPORTED_40000baseKR4_Full;
+			ecmd->advertising = ADVERTISED_40000baseKR4_Full;
+			break;
+		case I40E_DEV_ID_KX_C:
+			/* backplane 10G */
+			ecmd->supported = SUPPORTED_10000baseKR_Full;
+			ecmd->advertising = ADVERTISED_10000baseKR_Full;
+			break;
+		default:
+			/* all the rest are 10G/1G */
+			ecmd->supported = SUPPORTED_10000baseT_Full |
+					  SUPPORTED_1000baseT_Full;
+			ecmd->advertising = ADVERTISED_10000baseT_Full |
+					    ADVERTISED_1000baseT_Full;
+			break;
+		}
+
+		/* skip phy_type use as it is zero when link is down */
+		goto no_valid_phy_type;
+	}
+
 	switch (hw_link_info->phy_type) {
 	case I40E_PHY_TYPE_40GBASE_CR4:
 	case I40E_PHY_TYPE_40GBASE_CR4_CU:
-		ecmd->supported = SUPPORTED_40000baseCR4_Full;
-		ecmd->advertising = ADVERTISED_40000baseCR4_Full;
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_40000baseCR4_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_40000baseCR4_Full;
 		break;
 	case I40E_PHY_TYPE_40GBASE_KR4:
-		ecmd->supported = SUPPORTED_40000baseKR4_Full;
-		ecmd->advertising = ADVERTISED_40000baseKR4_Full;
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_40000baseKR4_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_40000baseKR4_Full;
 		break;
 	case I40E_PHY_TYPE_40GBASE_SR4:
+	case I40E_PHY_TYPE_XLPPI:
+	case I40E_PHY_TYPE_XLAUI:
 		ecmd->supported = SUPPORTED_40000baseSR4_Full;
-		ecmd->advertising = ADVERTISED_40000baseSR4_Full;
 		break;
 	case I40E_PHY_TYPE_40GBASE_LR4:
 		ecmd->supported = SUPPORTED_40000baseLR4_Full;
-		ecmd->advertising = ADVERTISED_40000baseLR4_Full;
 		break;
 	case I40E_PHY_TYPE_10GBASE_KX4:
-		ecmd->supported = SUPPORTED_10000baseKX4_Full;
-		ecmd->advertising = ADVERTISED_10000baseKX4_Full;
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_10000baseKX4_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_10000baseKX4_Full;
 		break;
 	case I40E_PHY_TYPE_10GBASE_KR:
-		ecmd->supported = SUPPORTED_10000baseKR_Full;
-		ecmd->advertising = ADVERTISED_10000baseKR_Full;
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_10000baseKR_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_10000baseKR_Full;
 		break;
-	default:
-		if (i40e_is_40G_device(hw->device_id)) {
-			ecmd->supported = SUPPORTED_40000baseSR4_Full;
-			ecmd->advertising = ADVERTISED_40000baseSR4_Full;
-		} else {
-			ecmd->supported = SUPPORTED_10000baseT_Full;
-			ecmd->advertising = ADVERTISED_10000baseT_Full;
-		}
+	case I40E_PHY_TYPE_10GBASE_SR:
+	case I40E_PHY_TYPE_10GBASE_LR:
+		ecmd->supported = SUPPORTED_10000baseT_Full;
 		break;
+	case I40E_PHY_TYPE_10GBASE_CR1_CU:
+	case I40E_PHY_TYPE_10GBASE_CR1:
+	case I40E_PHY_TYPE_10GBASE_T:
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_10000baseT_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_10000baseT_Full;
+		break;
+	case I40E_PHY_TYPE_XAUI:
+	case I40E_PHY_TYPE_XFI:
+	case I40E_PHY_TYPE_SFI:
+	case I40E_PHY_TYPE_10GBASE_SFPP_CU:
+		ecmd->supported = SUPPORTED_10000baseT_Full;
+		break;
+	case I40E_PHY_TYPE_1000BASE_KX:
+	case I40E_PHY_TYPE_1000BASE_T:
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_1000baseT_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_1000baseT_Full;
+		break;
+	case I40E_PHY_TYPE_100BASE_TX:
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_100baseT_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_100baseT_Full;
+		break;
+	case I40E_PHY_TYPE_SGMII:
+		ecmd->supported = SUPPORTED_Autoneg |
+				  SUPPORTED_1000baseT_Full |
+				  SUPPORTED_100baseT_Full;
+		ecmd->advertising = ADVERTISED_Autoneg |
+				    ADVERTISED_1000baseT_Full |
+				    ADVERTISED_100baseT_Full;
+		break;
+	default:
+		/* if we got here and link is up something bad is afoot */
+		WARN_ON(link_up);
 	}
 
-	ecmd->supported |= SUPPORTED_Autoneg;
-	ecmd->advertising |= ADVERTISED_Autoneg;
+no_valid_phy_type:
+	/* this is if autoneg is enabled or disabled */
 	ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
 			  AUTONEG_ENABLE : AUTONEG_DISABLE);
 
 	switch (hw->phy.media_type) {
 	case I40E_MEDIA_TYPE_BACKPLANE:
-		ecmd->supported |= SUPPORTED_Backplane;
-		ecmd->advertising |= ADVERTISED_Backplane;
+		ecmd->supported |= SUPPORTED_Autoneg |
+				   SUPPORTED_Backplane;
+		ecmd->advertising |= ADVERTISED_Autoneg |
+				     ADVERTISED_Backplane;
 		ecmd->port = PORT_NONE;
 		break;
 	case I40E_MEDIA_TYPE_BASET:
@@ -276,7 +380,6 @@ static int i40e_get_settings(struct net_
 		break;
 	case I40E_MEDIA_TYPE_FIBER:
 		ecmd->supported |= SUPPORTED_FIBRE;
-		ecmd->advertising |= ADVERTISED_FIBRE;
 		ecmd->port = PORT_FIBRE;
 		break;
 	case I40E_MEDIA_TYPE_UNKNOWN:
@@ -287,6 +390,25 @@ static int i40e_get_settings(struct net_
 
 	ecmd->transceiver = XCVR_EXTERNAL;
 
+	ecmd->supported |= SUPPORTED_Pause;
+
+	switch (hw->fc.current_mode) {
+	case I40E_FC_FULL:
+		ecmd->advertising |= ADVERTISED_Pause;
+		break;
+	case I40E_FC_TX_PAUSE:
+		ecmd->advertising |= ADVERTISED_Asym_Pause;
+		break;
+	case I40E_FC_RX_PAUSE:
+		ecmd->advertising |= (ADVERTISED_Pause |
+				      ADVERTISED_Asym_Pause);
+		break;
+	default:
+		ecmd->advertising &= ~(ADVERTISED_Pause |
+				       ADVERTISED_Asym_Pause);
+		break;
+	}
+
 	if (link_up) {
 		switch (link_speed) {
 		case I40E_LINK_SPEED_40GB:
@@ -296,6 +418,9 @@ static int i40e_get_settings(struct net_
 		case I40E_LINK_SPEED_10GB:
 			ethtool_cmd_speed_set(ecmd, SPEED_10000);
 			break;
+		case I40E_LINK_SPEED_1GB:
+			ethtool_cmd_speed_set(ecmd, SPEED_1000);
+			break;
 		default:
 			break;
 		}
@@ -309,6 +434,182 @@ static int i40e_get_settings(struct net_
 }
 
 /**
+ * i40e_set_settings - Set Speed and Duplex
+ * @netdev: network interface device structure
+ * @ecmd: ethtool command
+ *
+ * Set speed/duplex per media_types advertised/forced
+ **/
+static int i40e_set_settings(struct net_device *netdev,
+			     struct ethtool_cmd *ecmd)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_aq_get_phy_abilities_resp abilities;
+	struct i40e_aq_set_phy_config config;
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_hw *hw = &pf->hw;
+	struct ethtool_cmd safe_ecmd;
+	i40e_status status = 0;
+	bool change = false;
+	int err = 0;
+	u8 autoneg;
+	u32 advertise;
+
+	if (vsi != pf->vsi[pf->lan_vsi])
+		return -EOPNOTSUPP;
+
+	if (hw->phy.media_type != I40E_MEDIA_TYPE_BASET &&
+	    hw->phy.media_type != I40E_MEDIA_TYPE_FIBER &&
+	    hw->phy.media_type != I40E_MEDIA_TYPE_BACKPLANE)
+		return -EOPNOTSUPP;
+
+	/* get our own copy of the bits to check against */
+	memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd));
+	i40e_get_settings(netdev, &safe_ecmd);
+
+	/* save autoneg and speed out of ecmd */
+	autoneg = ecmd->autoneg;
+	advertise = ecmd->advertising;
+
+	/* set autoneg and speed back to what they currently are */
+	ecmd->autoneg = safe_ecmd.autoneg;
+	ecmd->advertising = safe_ecmd.advertising;
+
+	ecmd->cmd = safe_ecmd.cmd;
+	/* If ecmd and safe_ecmd are not the same now, then they are
+	 * trying to set something that we do not support
+	 */
+	if (memcmp(ecmd, &safe_ecmd, sizeof(struct ethtool_cmd)))
+		return -EOPNOTSUPP;
+
+	while (test_bit(__I40E_CONFIG_BUSY, &vsi->state))
+		usleep_range(1000, 2000);
+
+	/* Get the current phy config */
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+					      NULL);
+	if (status)
+		return -EAGAIN;
+
+	/* Copy link_speed and abilities to config in case they are not
+	 * set below
+	 */
+	memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
+	config.link_speed = abilities.link_speed;
+	config.abilities = abilities.abilities;
+
+	/* Check autoneg */
+	if (autoneg == AUTONEG_ENABLE) {
+		/* If autoneg is not supported, return error */
+		if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) {
+			netdev_info(netdev, "Autoneg not supported on this phy\n");
+			return -EINVAL;
+		}
+		/* If autoneg was not already enabled */
+		if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) {
+			config.abilities = abilities.abilities |
+					   I40E_AQ_PHY_ENABLE_AN;
+			change = true;
+		}
+	} else {
+		/* If autoneg is supported 10GBASE_T is the only phy that
+		 * can disable it, so otherwise return error
+		 */
+		if (safe_ecmd.supported & SUPPORTED_Autoneg &&
+		    hw->phy.link_info.phy_type != I40E_PHY_TYPE_10GBASE_T) {
+			netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
+			return -EINVAL;
+		}
+		/* If autoneg is currently enabled */
+		if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) {
+			config.abilities = abilities.abilities |
+					   ~I40E_AQ_PHY_ENABLE_AN;
+			change = true;
+		}
+	}
+
+	if (advertise & ~safe_ecmd.supported)
+		return -EINVAL;
+
+	if (advertise & ADVERTISED_100baseT_Full)
+		if (!(abilities.link_speed & I40E_LINK_SPEED_100MB)) {
+			config.link_speed |= I40E_LINK_SPEED_100MB;
+			change = true;
+		}
+	if (advertise & ADVERTISED_1000baseT_Full ||
+	    advertise & ADVERTISED_1000baseKX_Full)
+		if (!(abilities.link_speed & I40E_LINK_SPEED_1GB)) {
+			config.link_speed |= I40E_LINK_SPEED_1GB;
+			change = true;
+		}
+	if (advertise & ADVERTISED_10000baseT_Full ||
+	    advertise & ADVERTISED_10000baseKX4_Full ||
+	    advertise & ADVERTISED_10000baseKR_Full)
+		if (!(abilities.link_speed & I40E_LINK_SPEED_10GB)) {
+			config.link_speed |= I40E_LINK_SPEED_10GB;
+			change = true;
+		}
+	if (advertise & ADVERTISED_40000baseKR4_Full ||
+	    advertise & ADVERTISED_40000baseCR4_Full ||
+	    advertise & ADVERTISED_40000baseSR4_Full ||
+	    advertise & ADVERTISED_40000baseLR4_Full)
+		if (!(abilities.link_speed & I40E_LINK_SPEED_40GB)) {
+			config.link_speed |= I40E_LINK_SPEED_40GB;
+			change = true;
+		}
+
+	if (change) {
+		/* copy over the rest of the abilities */
+		config.phy_type = abilities.phy_type;
+		config.eee_capability = abilities.eee_capability;
+		config.eeer = abilities.eeer_val;
+		config.low_power_ctrl = abilities.d3_lpan;
+
+		/* If link is up set link and an so changes take effect */
+		if (hw->phy.link_info.link_info & I40E_AQ_LINK_UP)
+			config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+
+		/* make the aq call */
+		status = i40e_aq_set_phy_config(hw, &config, NULL);
+		if (status) {
+			netdev_info(netdev, "Set phy config failed with error %d.\n",
+				    status);
+			return -EAGAIN;
+		}
+
+		status = i40e_update_link_info(hw, true);
+		if (status)
+			netdev_info(netdev, "Updating link info failed with error %d\n",
+				    status);
+
+	} else {
+		netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
+	}
+
+	return err;
+}
+
+static int i40e_nway_reset(struct net_device *netdev)
+{
+	/* restart autonegotiation */
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_hw *hw = &pf->hw;
+	bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
+	i40e_status ret = 0;
+
+	ret = i40e_aq_set_link_restart_an(hw, link_up, NULL);
+	if (ret) {
+		netdev_info(netdev, "link restart failed, aq_err=%d\n",
+			    pf->hw.aq.asq_last_status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
  * i40e_get_pauseparam -  Get Flow Control status
  * Return tx/rx-pause status
  **/
@@ -334,6 +635,85 @@ static void i40e_get_pauseparam(struct n
 	}
 }
 
+/**
+ * i40e_set_pauseparam - Set Flow Control parameter
+ * @netdev: network interface device structure
+ * @pause: return tx/rx flow control status
+ **/
+static int i40e_set_pauseparam(struct net_device *netdev,
+			       struct ethtool_pauseparam *pause)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_hw *hw = &pf->hw;
+	struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+	bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
+	i40e_status status;
+	u8 aq_failures;
+	int err = 0;
+
+	if (vsi != pf->vsi[pf->lan_vsi])
+		return -EOPNOTSUPP;
+
+	if (pause->autoneg != ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
+	    AUTONEG_ENABLE : AUTONEG_DISABLE)) {
+		netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
+		return -EOPNOTSUPP;
+	}
+
+	/* If we have link and don't have autoneg */
+	if (!test_bit(__I40E_DOWN, &pf->state) &&
+	    !(hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
+		/* Send message that it might not necessarily work*/
+		netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n");
+	}
+
+	if (hw->fc.current_mode == I40E_FC_PFC) {
+		netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (pause->rx_pause && pause->tx_pause)
+		hw->fc.requested_mode = I40E_FC_FULL;
+	else if (pause->rx_pause && !pause->tx_pause)
+		hw->fc.requested_mode = I40E_FC_RX_PAUSE;
+	else if (!pause->rx_pause && pause->tx_pause)
+		hw->fc.requested_mode = I40E_FC_TX_PAUSE;
+	else if (!pause->rx_pause && !pause->tx_pause)
+		hw->fc.requested_mode = I40E_FC_NONE;
+	else
+		 return -EINVAL;
+
+	/* Set the fc mode and only restart an if link is up*/
+	status = i40e_set_fc(hw, &aq_failures, link_up);
+
+	if (aq_failures & I40E_SET_FC_AQ_FAIL_GET) {
+		netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with error %d and status %d\n",
+			    status, hw->aq.asq_last_status);
+		err = -EAGAIN;
+	}
+	if (aq_failures & I40E_SET_FC_AQ_FAIL_SET) {
+		netdev_info(netdev, "Set fc failed on the set_phy_config call with error %d and status %d\n",
+			    status, hw->aq.asq_last_status);
+		err = -EAGAIN;
+	}
+	if (aq_failures & I40E_SET_FC_AQ_FAIL_UPDATE) {
+		netdev_info(netdev, "Set fc failed on the update_link_info call with error %d and status %d\n",
+			    status, hw->aq.asq_last_status);
+		err = -EAGAIN;
+	}
+
+	if (!test_bit(__I40E_DOWN, &pf->state)) {
+		/* Give it a little more time to try to come back */
+		msleep(75);
+		if (!test_bit(__I40E_DOWN, &pf->state))
+			return i40e_nway_reset(netdev);
+	}
+
+	return err;
+}
+
 static u32 i40e_get_msglevel(struct net_device *netdev)
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
@@ -404,10 +784,33 @@ static int i40e_get_eeprom(struct net_de
 	u8 *eeprom_buff;
 	u16 i, sectors;
 	bool last;
+	u32 magic;
+
 #define I40E_NVM_SECTOR_SIZE  4096
 	if (eeprom->len == 0)
 		return -EINVAL;
 
+	/* check for NVMUpdate access method */
+	magic = hw->vendor_id | (hw->device_id << 16);
+	if (eeprom->magic && eeprom->magic != magic) {
+		int errno;
+
+		/* make sure it is the right magic for NVMUpdate */
+		if ((eeprom->magic >> 16) != hw->device_id)
+			return -EINVAL;
+
+		ret_val = i40e_nvmupd_command(hw,
+					      (struct i40e_nvm_access *)eeprom,
+					      bytes, &errno);
+		if (ret_val)
+			dev_info(&pf->pdev->dev,
+				 "NVMUpdate read failed err=%d status=0x%x\n",
+				 ret_val, hw->aq.asq_last_status);
+
+		return errno;
+	}
+
+	/* normal ethtool get_eeprom support */
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
 	eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL);
@@ -434,7 +837,7 @@ static int i40e_get_eeprom(struct net_de
 		ret_val = i40e_aq_read_nvm(hw, 0x0,
 				eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
 				len,
-				eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
+				(u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
 				last, NULL);
 		if (ret_val) {
 			dev_info(&pf->pdev->dev,
@@ -446,7 +849,7 @@ static int i40e_get_eeprom(struct net_de
 
 release_nvm:
 	i40e_release_nvm(hw);
-	memcpy(bytes, eeprom_buff, eeprom->len);
+	memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
 free_buff:
 	kfree(eeprom_buff);
 	return ret_val;
@@ -466,6 +869,39 @@ static int i40e_get_eeprom_len(struct ne
 	return val;
 }
 
+static int i40e_set_eeprom(struct net_device *netdev,
+			   struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_hw *hw = &np->vsi->back->hw;
+	struct i40e_pf *pf = np->vsi->back;
+	int ret_val = 0;
+	int errno;
+	u32 magic;
+
+	/* normal ethtool set_eeprom is not supported */
+	magic = hw->vendor_id | (hw->device_id << 16);
+	if (eeprom->magic == magic)
+		return -EOPNOTSUPP;
+
+	/* check for NVMUpdate access method */
+	if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id)
+		return -EINVAL;
+
+	if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
+	    test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
+		return -EBUSY;
+
+	ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom,
+				      bytes, &errno);
+	if (ret_val)
+		dev_info(&pf->pdev->dev,
+			 "NVMUpdate write failed err=%d status=0x%x\n",
+			 ret_val, hw->aq.asq_last_status);
+
+	return errno;
+}
+
 static void i40e_get_drvinfo(struct net_device *netdev,
 			     struct ethtool_drvinfo *drvinfo)
 {
@@ -697,6 +1133,13 @@ static void i40e_get_ethtool_stats(struc
 		data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat ==
 			    sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
+#ifdef I40E_FCOE
+	for (j = 0; j < I40E_FCOE_STATS_LEN; j++) {
+		p = (char *)vsi + i40e_gstrings_fcoe_stats[j].stat_offset;
+		data[i++] = (i40e_gstrings_fcoe_stats[j].sizeof_stat ==
+			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	}
+#endif
 	rcu_read_lock();
 	for (j = 0; j < vsi->num_queue_pairs; j++) {
 		tx_ring = ACCESS_ONCE(vsi->tx_rings[j]);
@@ -778,6 +1221,13 @@ static void i40e_get_strings(struct net_
 				 i40e_gstrings_misc_stats[i].stat_string);
 			p += ETH_GSTRING_LEN;
 		}
+#ifdef I40E_FCOE
+		for (i = 0; i < I40E_FCOE_STATS_LEN; i++) {
+			snprintf(p, ETH_GSTRING_LEN, "%s",
+				 i40e_gstrings_fcoe_stats[i].stat_string);
+			p += ETH_GSTRING_LEN;
+		}
+#endif
 		for (i = 0; i < vsi->num_queue_pairs; i++) {
 			snprintf(p, ETH_GSTRING_LEN, "tx-%u.tx_packets", i);
 			p += ETH_GSTRING_LEN;
@@ -1021,24 +1471,6 @@ static int i40e_set_wol(struct net_devic
 	return 0;
 }
 
-static int i40e_nway_reset(struct net_device *netdev)
-{
-	/* restart autonegotiation */
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_pf *pf = np->vsi->back;
-	struct i40e_hw *hw = &pf->hw;
-	i40e_status ret = 0;
-
-	ret = i40e_aq_set_link_restart_an(hw, NULL);
-	if (ret) {
-		netdev_info(netdev, "link restart failed, aq_err=%d\n",
-			    pf->hw.aq.asq_last_status);
-		return -EIO;
-	}
-
-	return 0;
-}
-
 static int i40e_set_phys_id(struct net_device *netdev,
 			    enum ethtool_phys_id_state state)
 {
@@ -1105,17 +1537,36 @@ static int i40e_set_coalesce(struct net_
 	if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
 		vsi->work_limit = ec->tx_max_coalesced_frames_irq;
 
+	vector = vsi->base_vector;
 	if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
-	    (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
+	    (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
 		vsi->rx_itr_setting = ec->rx_coalesce_usecs;
-	else
+	} else if (ec->rx_coalesce_usecs == 0) {
+		vsi->rx_itr_setting = ec->rx_coalesce_usecs;
+		i40e_irq_dynamic_disable(vsi, vector);
+		if (ec->use_adaptive_rx_coalesce)
+			netif_info(pf, drv, netdev,
+				   "Rx-secs=0, need to disable adaptive-Rx for a complete disable\n");
+	} else {
+		netif_info(pf, drv, netdev,
+			   "Invalid value, Rx-usecs range is 0, 8-8160\n");
 		return -EINVAL;
+	}
 
 	if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
-	    (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
+	    (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
 		vsi->tx_itr_setting = ec->tx_coalesce_usecs;
-	else
+	} else if (ec->tx_coalesce_usecs == 0) {
+		vsi->tx_itr_setting = ec->tx_coalesce_usecs;
+		i40e_irq_dynamic_disable(vsi, vector);
+		if (ec->use_adaptive_tx_coalesce)
+			netif_info(pf, drv, netdev,
+				   "Tx-secs=0, need to disable adaptive-Tx for a complete disable\n");
+	} else {
+		netif_info(pf, drv, netdev,
+			   "Invalid value, Tx-usecs range is 0, 8-8160\n");
 		return -EINVAL;
+	}
 
 	if (ec->use_adaptive_rx_coalesce)
 		vsi->rx_itr_setting |= I40E_ITR_DYNAMIC;
@@ -1127,7 +1578,6 @@ static int i40e_set_coalesce(struct net_
 	else
 		vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
 
-	vector = vsi->base_vector;
 	for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
 		q_vector = vsi->q_vectors[i];
 		q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
@@ -1498,7 +1948,7 @@ static int i40e_update_ethtool_fdir_entr
 
 	/* add filter to the list */
 	if (parent)
-		hlist_add_after(&parent->fdir_node, &input->fdir_node);
+		hlist_add_behind(&input->fdir_node, &parent->fdir_node);
 	else
 		hlist_add_head(&input->fdir_node,
 			       &pf->fdir_filter_list);
@@ -1731,6 +2181,7 @@ static int i40e_set_channels(struct net_
 
 static const struct ethtool_ops i40e_ethtool_ops = {
 	.get_settings		= i40e_get_settings,
+	.set_settings		= i40e_set_settings,
 	.get_drvinfo		= i40e_get_drvinfo,
 	.get_regs_len		= i40e_get_regs_len,
 	.get_regs		= i40e_get_regs,
@@ -1738,11 +2189,13 @@ static const struct ethtool_ops i40e_eth
 	.get_link		= ethtool_op_get_link,
 	.get_wol		= i40e_get_wol,
 	.set_wol		= i40e_set_wol,
+	.set_eeprom		= i40e_set_eeprom,
 	.get_eeprom_len		= i40e_get_eeprom_len,
 	.get_eeprom		= i40e_get_eeprom,
 	.get_ringparam		= i40e_get_ringparam,
 	.set_ringparam		= i40e_set_ringparam,
 	.get_pauseparam		= i40e_get_pauseparam,
+	.set_pauseparam		= i40e_set_pauseparam,
 	.get_msglevel		= i40e_get_msglevel,
 	.set_msglevel		= i40e_set_msglevel,
 	.get_rxnfc		= i40e_get_rxnfc,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1562 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+
+#include <linux/if_ether.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+#include <uapi/linux/dcbnl.h>
+
+#include "i40e.h"
+#include "i40e_fcoe.h"
+
+/**
+ * i40e_rx_is_fip - returns true if the rx packet type is FIP
+ * @ptype: the packet type field from rx descriptor write-back
+ **/
+static inline bool i40e_rx_is_fip(u16 ptype)
+{
+	return ptype == I40E_RX_PTYPE_L2_FIP_PAY2;
+}
+
+/**
+ * i40e_rx_is_fcoe - returns true if the rx packet type is FCoE
+ * @ptype: the packet type field from rx descriptor write-back
+ **/
+static inline bool i40e_rx_is_fcoe(u16 ptype)
+{
+	return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) &&
+	       (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER);
+}
+
+/**
+ * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF
+ * @sof: the FCoE start of frame delimiter
+ **/
+static inline bool i40e_fcoe_sof_is_class2(u8 sof)
+{
+	return (sof == FC_SOF_I2) || (sof == FC_SOF_N2);
+}
+
+/**
+ * i40e_fcoe_sof_is_class3 - returns true if this is a FC Class 3 SOF
+ * @sof: the FCoE start of frame delimiter
+ **/
+static inline bool i40e_fcoe_sof_is_class3(u8 sof)
+{
+	return (sof == FC_SOF_I3) || (sof == FC_SOF_N3);
+}
+
+/**
+ * i40e_fcoe_sof_is_supported - returns true if the FC SOF is supported by HW
+ * @sof: the input SOF value from the frame
+ **/
+static inline bool i40e_fcoe_sof_is_supported(u8 sof)
+{
+	return i40e_fcoe_sof_is_class2(sof) ||
+	       i40e_fcoe_sof_is_class3(sof);
+}
+
+/**
+ * i40e_fcoe_fc_sof - pull the SOF from FCoE header in the frame
+ * @skb: the frame whose EOF is to be pulled from
+ **/
+static inline int i40e_fcoe_fc_sof(struct sk_buff *skb, u8 *sof)
+{
+	*sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
+
+	if (!i40e_fcoe_sof_is_supported(*sof))
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ * i40e_fcoe_eof_is_supported - returns true if the EOF is supported by HW
+ * @eof:     the input EOF value from the frame
+ **/
+static inline bool i40e_fcoe_eof_is_supported(u8 eof)
+{
+	return (eof == FC_EOF_N) || (eof == FC_EOF_T) ||
+	       (eof == FC_EOF_NI) || (eof == FC_EOF_A);
+}
+
+/**
+ * i40e_fcoe_fc_eof - pull EOF from FCoE trailer in the frame
+ * @skb: the frame whose EOF is to be pulled from
+ **/
+static inline int i40e_fcoe_fc_eof(struct sk_buff *skb, u8 *eof)
+{
+	/* the first byte of the last dword is EOF */
+	skb_copy_bits(skb, skb->len - 4, eof, 1);
+
+	if (!i40e_fcoe_eof_is_supported(*eof))
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ * i40e_fcoe_ctxt_eof - convert input FC EOF for descriptor programming
+ * @eof: the input eof value from the frame
+ *
+ * The FC EOF is converted to the value understood by HW for descriptor
+ * programming. Never call this w/o calling i40e_fcoe_eof_is_supported()
+ * first.
+ **/
+static inline u32 i40e_fcoe_ctxt_eof(u8 eof)
+{
+	switch (eof) {
+	case FC_EOF_N:
+		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_N;
+	case FC_EOF_T:
+		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_T;
+	case FC_EOF_NI:
+		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI;
+	case FC_EOF_A:
+		return I40E_TX_DESC_CMD_L4T_EOFT_EOF_A;
+	default:
+		/* FIXME: still returns 0 */
+		pr_err("Unrecognized EOF %x\n", eof);
+		return 0;
+	}
+}
+
+/**
+ * i40e_fcoe_xid_is_valid - returns true if the exchange id is valid
+ * @xid: the exchange id
+ **/
+static inline bool i40e_fcoe_xid_is_valid(u16 xid)
+{
+	return (xid != FC_XID_UNKNOWN) && (xid < I40E_FCOE_DDP_MAX);
+}
+
+/**
+ * i40e_fcoe_ddp_unmap - unmap the mapped sglist associated
+ * @pf: pointer to pf
+ * @ddp: sw DDP context
+ *
+ * Unmap the scatter-gather list associated with the given SW DDP context
+ *
+ * Returns: data length already ddp-ed in bytes
+ *
+ **/
+static inline void i40e_fcoe_ddp_unmap(struct i40e_pf *pf,
+				       struct i40e_fcoe_ddp *ddp)
+{
+	if (test_and_set_bit(__I40E_FCOE_DDP_UNMAPPED, &ddp->flags))
+		return;
+
+	if (ddp->sgl) {
+		dma_unmap_sg(&pf->pdev->dev, ddp->sgl, ddp->sgc,
+			     DMA_FROM_DEVICE);
+		ddp->sgl = NULL;
+		ddp->sgc = 0;
+	}
+
+	if (ddp->pool) {
+		dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
+		ddp->pool = NULL;
+	}
+}
+
+/**
+ * i40e_fcoe_ddp_clear - clear the given SW DDP context
+ * @ddp - SW DDP context
+ **/
+static inline void i40e_fcoe_ddp_clear(struct i40e_fcoe_ddp *ddp)
+{
+	memset(ddp, 0, sizeof(struct i40e_fcoe_ddp));
+	ddp->xid = FC_XID_UNKNOWN;
+	ddp->flags = __I40E_FCOE_DDP_NONE;
+}
+
+/**
+ * i40e_fcoe_progid_is_fcoe - check if the prog_id is for FCoE
+ * @id: the prog id for the programming status Rx descriptor write-back
+ **/
+static inline bool i40e_fcoe_progid_is_fcoe(u8 id)
+{
+	return (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
+	       (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS);
+}
+
+/**
+ * i40e_fcoe_fc_get_xid - get xid from the frame header
+ * @fh: the fc frame header
+ *
+ * In case the incoming frame's exchange is originated from
+ * the initiator, then received frame's exchange id is ANDed
+ * with fc_cpu_mask bits to get the same cpu on which exchange
+ * was originated, otherwise just use the current cpu.
+ *
+ * Returns ox_id if exchange originator, rx_id if responder
+ **/
+static inline u16 i40e_fcoe_fc_get_xid(struct fc_frame_header *fh)
+{
+	u32 f_ctl = ntoh24(fh->fh_f_ctl);
+
+	return (f_ctl & FC_FC_EX_CTX) ?
+		be16_to_cpu(fh->fh_ox_id) :
+		be16_to_cpu(fh->fh_rx_id);
+}
+
+/**
+ * i40e_fcoe_fc_frame_header - get fc frame header from skb
+ * @skb: packet
+ *
+ * This checks if there is a VLAN header and returns the data
+ * pointer to the start of the fc_frame_header.
+ *
+ * Returns pointer to the fc_frame_header
+ **/
+static inline struct fc_frame_header *i40e_fcoe_fc_frame_header(
+	struct sk_buff *skb)
+{
+	void *fh = skb->data + sizeof(struct fcoe_hdr);
+
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
+		fh += sizeof(struct vlan_hdr);
+
+	return (struct fc_frame_header *)fh;
+}
+
+/**
+ * i40e_fcoe_ddp_put - release the DDP context for a given exchange id
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id that corresponding DDP context will be released
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
+ * and it is expected to be called by ULD, i.e., FCP layer of libfc
+ * to release the corresponding ddp context when the I/O is done.
+ *
+ * Returns : data length already ddp-ed in bytes
+ **/
+static int i40e_fcoe_ddp_put(struct net_device *netdev, u16 xid)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	int len = 0;
+	struct i40e_fcoe_ddp *ddp = &fcoe->ddp[xid];
+
+	if (!fcoe || !ddp)
+		goto out;
+
+	if (test_bit(__I40E_FCOE_DDP_DONE, &ddp->flags))
+		len = ddp->len;
+	i40e_fcoe_ddp_unmap(pf, ddp);
+out:
+	return len;
+}
+
+/**
+ * i40e_fcoe_sw_init - sets up the HW for FCoE
+ * @pf: pointer to pf
+ *
+ * Returns 0 if FCoE is supported otherwise the error code
+ **/
+int i40e_init_pf_fcoe(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = &pf->hw;
+	u32 val;
+
+	pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+	pf->num_fcoe_qps = 0;
+	pf->fcoe_hmc_cntx_num = 0;
+	pf->fcoe_hmc_filt_num = 0;
+
+	if (!pf->hw.func_caps.fcoe) {
+		dev_info(&pf->pdev->dev, "FCoE capability is disabled\n");
+		return 0;
+	}
+
+	if (!pf->hw.func_caps.dcb) {
+		dev_warn(&pf->pdev->dev,
+			 "Hardware is not DCB capable not enabling FCoE.\n");
+		return 0;
+	}
+
+	/* enable FCoE hash filter */
+	val = rd32(hw, I40E_PFQF_HENA(1));
+	val |= 1 << (I40E_FILTER_PCTYPE_FCOE_OX - 32);
+	val |= 1 << (I40E_FILTER_PCTYPE_FCOE_RX - 32);
+	val &= I40E_PFQF_HENA_PTYPE_ENA_MASK;
+	wr32(hw, I40E_PFQF_HENA(1), val);
+
+	/* enable flag */
+	pf->flags |= I40E_FLAG_FCOE_ENABLED;
+	pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
+
+	/* Reserve 4K DDP contexts and 20K filter size for FCoE */
+	pf->fcoe_hmc_cntx_num = (1 << I40E_DMA_CNTX_SIZE_4K) *
+				 I40E_DMA_CNTX_BASE_SIZE;
+	pf->fcoe_hmc_filt_num = pf->fcoe_hmc_cntx_num +
+				(1 << I40E_HASH_FILTER_SIZE_16K) *
+				I40E_HASH_FILTER_BASE_SIZE;
+
+	/* FCoE object: max 16K filter buckets and 4K DMA contexts */
+	pf->filter_settings.fcoe_filt_num = I40E_HASH_FILTER_SIZE_16K;
+	pf->filter_settings.fcoe_cntx_num = I40E_DMA_CNTX_SIZE_4K;
+
+	/* Setup max frame with FCoE_MTU plus L2 overheads */
+	val = rd32(hw, I40E_GLFCOE_RCTL);
+	val &= ~I40E_GLFCOE_RCTL_MAX_SIZE_MASK;
+	val |= ((FCOE_MTU + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
+		 << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT);
+	wr32(hw, I40E_GLFCOE_RCTL, val);
+
+	dev_info(&pf->pdev->dev, "FCoE is supported.\n");
+	return 0;
+}
+
+/**
+ * i40e_get_fcoe_tc_map - Return TC map for FCoE APP
+ * @pf: pointer to pf
+ *
+ **/
+u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf)
+{
+	struct i40e_ieee_app_priority_table app;
+	struct i40e_hw *hw = &pf->hw;
+	u8 enabled_tc = 0;
+	u8 tc, i;
+	/* Get the FCoE APP TLV */
+	struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
+
+	for (i = 0; i < dcbcfg->numapps; i++) {
+		app = dcbcfg->app[i];
+		if (app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+		    app.protocolid == ETH_P_FCOE) {
+			tc = dcbcfg->etscfg.prioritytable[app.priority];
+			enabled_tc |= (1 << tc);
+			break;
+		}
+	}
+
+	/* TC0 if there is no TC defined for FCoE APP TLV */
+	enabled_tc = enabled_tc ? enabled_tc : 0x1;
+
+	return enabled_tc;
+}
+
+/**
+ * i40e_fcoe_vsi_init - prepares the VSI context for creating a FCoE VSI
+ * @vsi: pointer to the associated VSI struct
+ * @ctxt: pointer to the associated VSI context to be passed to HW
+ *
+ * Returns 0 on success or < 0 on error
+ **/
+int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt)
+{
+	struct i40e_aqc_vsi_properties_data *info = &ctxt->info;
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_hw *hw = &pf->hw;
+	u8 enabled_tc = 0;
+
+	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+		dev_err(&pf->pdev->dev,
+			"FCoE is not enabled for this device\n");
+		return -EPERM;
+	}
+
+	/* initialize the hardware for FCoE */
+	ctxt->pf_num = hw->pf_id;
+	ctxt->vf_num = 0;
+	ctxt->uplink_seid = vsi->uplink_seid;
+	ctxt->connection_type = 0x1;
+	ctxt->flags = I40E_AQ_VSI_TYPE_PF;
+
+	/* FCoE VSI would need the following sections */
+	info->valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID |
+					    I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+
+	/* FCoE VSI does not need these sections */
+	info->valid_sections &= cpu_to_le16(~(I40E_AQ_VSI_PROP_SECURITY_VALID |
+					    I40E_AQ_VSI_PROP_VLAN_VALID |
+					    I40E_AQ_VSI_PROP_CAS_PV_VALID |
+					    I40E_AQ_VSI_PROP_INGRESS_UP_VALID |
+					    I40E_AQ_VSI_PROP_EGRESS_UP_VALID));
+
+	enabled_tc = i40e_get_fcoe_tc_map(pf);
+	i40e_vsi_setup_queue_map(vsi, ctxt, enabled_tc, true);
+
+	/* set up queue option section: only enable FCoE */
+	info->queueing_opt_flags = I40E_AQ_VSI_QUE_OPT_FCOE_ENA;
+
+	return 0;
+}
+
+/**
+ * i40e_fcoe_enable - this is the implementation of ndo_fcoe_enable,
+ * indicating the upper FCoE protocol stack is ready to use FCoE
+ * offload features.
+ *
+ * @netdev: pointer to the netdev that FCoE is created on
+ *
+ * Returns 0 on success
+ *
+ * in RTNL
+ *
+ **/
+int i40e_fcoe_enable(struct net_device *netdev)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+
+	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+		netdev_err(netdev, "HW does not support FCoE.\n");
+		return -ENODEV;
+	}
+
+	if (vsi->type != I40E_VSI_FCOE) {
+		netdev_err(netdev, "interface does not support FCoE.\n");
+		return -EBUSY;
+	}
+
+	atomic_inc(&fcoe->refcnt);
+
+	return 0;
+}
+
+/**
+ * i40e_fcoe_disable- disables FCoE for upper FCoE protocol stack.
+ * @dev: pointer to the netdev that FCoE is created on
+ *
+ * Returns 0 on success
+ *
+ **/
+int i40e_fcoe_disable(struct net_device *netdev)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+
+	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+		netdev_err(netdev, "device does not support FCoE\n");
+		return -ENODEV;
+	}
+	if (vsi->type != I40E_VSI_FCOE)
+		return -EBUSY;
+
+	if (!atomic_dec_and_test(&fcoe->refcnt))
+		return -EINVAL;
+
+	netdev_info(netdev, "FCoE disabled\n");
+
+	return 0;
+}
+
+/**
+ * i40e_fcoe_dma_pool_free - free the per cpu pool for FCoE DDP
+ * @fcoe: the FCoE sw object
+ * @dev: the device that the pool is associated with
+ * @cpu: the cpu for this pool
+ *
+ **/
+static void i40e_fcoe_dma_pool_free(struct i40e_fcoe *fcoe,
+				    struct device *dev,
+				    unsigned int cpu)
+{
+	struct i40e_fcoe_ddp_pool *ddp_pool;
+
+	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
+	if (!ddp_pool->pool) {
+		dev_warn(dev, "DDP pool already freed for cpu %d\n", cpu);
+		return;
+	}
+	dma_pool_destroy(ddp_pool->pool);
+	ddp_pool->pool = NULL;
+}
+
+/**
+ * i40e_fcoe_dma_pool_create - per cpu pool for FCoE DDP
+ * @fcoe: the FCoE sw object
+ * @dev: the device that the pool is associated with
+ * @cpu: the cpu for this pool
+ *
+ * Returns 0 on successful or non zero on failure
+ *
+ **/
+static int i40e_fcoe_dma_pool_create(struct i40e_fcoe *fcoe,
+				     struct device *dev,
+				     unsigned int cpu)
+{
+	struct i40e_fcoe_ddp_pool *ddp_pool;
+	struct dma_pool *pool;
+	char pool_name[32];
+
+	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
+	if (ddp_pool && ddp_pool->pool) {
+		dev_warn(dev, "DDP pool already allocated for cpu %d\n", cpu);
+		return 0;
+	}
+	snprintf(pool_name, sizeof(pool_name), "i40e_fcoe_ddp_%d", cpu);
+	pool = dma_pool_create(pool_name, dev, I40E_FCOE_DDP_PTR_MAX,
+			       I40E_FCOE_DDP_PTR_ALIGN, PAGE_SIZE);
+	if (!pool) {
+		dev_err(dev, "dma_pool_create %s failed\n", pool_name);
+		return -ENOMEM;
+	}
+	ddp_pool->pool = pool;
+	return 0;
+}
+
+/**
+ * i40e_fcoe_free_ddp_resources - release FCoE DDP resources
+ * @vsi: the vsi FCoE is associated with
+ *
+ **/
+void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi)
+{
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	int cpu, i;
+
+	/* do nothing if not FCoE VSI */
+	if (vsi->type != I40E_VSI_FCOE)
+		return;
+
+	/* do nothing if no DDP pools were allocated */
+	if (!fcoe->ddp_pool)
+		return;
+
+	for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
+		i40e_fcoe_ddp_put(vsi->netdev, i);
+
+	for_each_possible_cpu(cpu)
+		i40e_fcoe_dma_pool_free(fcoe, &pf->pdev->dev, cpu);
+
+	free_percpu(fcoe->ddp_pool);
+	fcoe->ddp_pool = NULL;
+
+	netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources released\n",
+		    vsi->id, vsi->seid);
+}
+
+/**
+ * i40e_fcoe_setup_ddp_resources - allocate per cpu DDP resources
+ * @vsi: the VSI FCoE is associated with
+ *
+ * Returns 0 on successful or non zero on failure
+ *
+ **/
+int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi)
+{
+	struct i40e_pf *pf = vsi->back;
+	struct device *dev = &pf->pdev->dev;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	unsigned int cpu;
+	int i;
+
+	if (vsi->type != I40E_VSI_FCOE)
+		return -ENODEV;
+
+	/* do nothing if no DDP pools were allocated */
+	if (fcoe->ddp_pool)
+		return -EEXIST;
+
+	/* allocate per CPU memory to track DDP pools */
+	fcoe->ddp_pool = alloc_percpu(struct i40e_fcoe_ddp_pool);
+	if (!fcoe->ddp_pool) {
+		dev_err(&pf->pdev->dev, "failed to allocate percpu DDP\n");
+		return -ENOMEM;
+	}
+
+	/* allocate pci pool for each cpu */
+	for_each_possible_cpu(cpu) {
+		if (!i40e_fcoe_dma_pool_create(fcoe, dev, cpu))
+			continue;
+
+		dev_err(dev, "failed to alloc DDP pool on cpu:%d\n", cpu);
+		i40e_fcoe_free_ddp_resources(vsi);
+		return -ENOMEM;
+	}
+
+	/* initialize the sw context */
+	for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
+		i40e_fcoe_ddp_clear(&fcoe->ddp[i]);
+
+	netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources allocated\n",
+		    vsi->id, vsi->seid);
+
+	return 0;
+}
+
+/**
+ * i40e_fcoe_handle_status - check the Programming Status for FCoE
+ * @rx_ring: the Rx ring for this descriptor
+ * @rx_desc: the Rx descriptor for Programming Status, not a packet descriptor.
+ *
+ * Check if this is the Rx Programming Status descriptor write-back for FCoE.
+ * This is used to verify if the context/filter programming or invalidation
+ * requested by SW to the HW is successful or not and take actions accordingly.
+ **/
+void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
+			     union i40e_rx_desc *rx_desc, u8 prog_id)
+{
+	struct i40e_pf *pf = rx_ring->vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	struct i40e_fcoe_ddp *ddp;
+	u32 error;
+	u16 xid;
+	u64 qw;
+
+	/* we only care for FCoE here */
+	if (!i40e_fcoe_progid_is_fcoe(prog_id))
+		return;
+
+	xid = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param) &
+	      (I40E_FCOE_DDP_MAX - 1);
+
+	if (!i40e_fcoe_xid_is_valid(xid))
+		return;
+
+	ddp = &fcoe->ddp[xid];
+	WARN_ON(xid != ddp->xid);
+
+	qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+	error = (qw & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
+		I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
+
+	/* DDP context programming status: failure or success */
+	if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) {
+		if (I40E_RX_PROG_FCOE_ERROR_TBL_FULL(error)) {
+			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x TABLE FULL\n",
+				xid, ddp->xid);
+			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT;
+		}
+		if (I40E_RX_PROG_FCOE_ERROR_CONFLICT(error)) {
+			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x CONFLICT\n",
+				xid, ddp->xid);
+			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT;
+		}
+	}
+
+	/* DDP context invalidation status: failure or success */
+	if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS) {
+		if (I40E_RX_PROG_FCOE_ERROR_INVLFAIL(error)) {
+			dev_err(&pf->pdev->dev, "xid %x ddp->xid %x INVALIDATION FAILURE\n",
+				xid, ddp->xid);
+			ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT;
+		}
+		/* clear the flag so we can retry invalidation */
+		clear_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags);
+	}
+
+	/* unmap DMA */
+	i40e_fcoe_ddp_unmap(pf, ddp);
+	i40e_fcoe_ddp_clear(ddp);
+}
+
+/**
+ * i40e_fcoe_handle_offload - check ddp status and mark it done
+ * @adapter: i40e adapter
+ * @rx_desc: advanced rx descriptor
+ * @skb: the skb holding the received data
+ *
+ * This checks ddp status.
+ *
+ * Returns : < 0 indicates an error or not a FCOE ddp, 0 indicates
+ * not passing the skb to ULD, > 0 indicates is the length of data
+ * being ddped.
+ *
+ **/
+int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
+			     union i40e_rx_desc *rx_desc,
+			     struct sk_buff *skb)
+{
+	struct i40e_pf *pf = rx_ring->vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	struct fc_frame_header *fh = NULL;
+	struct i40e_fcoe_ddp *ddp = NULL;
+	u32 status, fltstat;
+	u32 error, fcerr;
+	int rc = -EINVAL;
+	u16 ptype;
+	u16 xid;
+	u64 qw;
+
+	/* check this rxd is for programming status */
+	qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+	/* packet descriptor, check packet type */
+	ptype = (qw & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
+	if (!i40e_rx_is_fcoe(ptype))
+		goto out_no_ddp;
+
+	error = (qw & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT;
+	fcerr = (error >> I40E_RX_DESC_ERROR_L3L4E_SHIFT) &
+		 I40E_RX_DESC_FCOE_ERROR_MASK;
+
+	/* check stateless offload error */
+	if (unlikely(fcerr == I40E_RX_DESC_ERROR_L3L4E_PROT)) {
+		dev_err(&pf->pdev->dev, "Protocol Error\n");
+		skb->ip_summed = CHECKSUM_NONE;
+	} else {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+
+	/* check hw status on ddp */
+	status = (qw & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT;
+	fltstat = (status >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) &
+		   I40E_RX_DESC_FLTSTAT_FCMASK;
+
+	/* now we are ready to check DDP */
+	fh = i40e_fcoe_fc_frame_header(skb);
+	xid = i40e_fcoe_fc_get_xid(fh);
+	if (!i40e_fcoe_xid_is_valid(xid))
+		goto out_no_ddp;
+
+	/* non DDP normal receive, return to the protocol stack */
+	if (fltstat == I40E_RX_DESC_FLTSTAT_NOMTCH)
+		goto out_no_ddp;
+
+	/* do we have a sw ddp context setup ? */
+	ddp = &fcoe->ddp[xid];
+	if (!ddp->sgl)
+		goto out_no_ddp;
+
+	/* fetch xid from hw rxd wb, which should match up the sw ctxt */
+	xid = le16_to_cpu(rx_desc->wb.qword0.lo_dword.mirr_fcoe.fcoe_ctx_id);
+	if (ddp->xid != xid) {
+		dev_err(&pf->pdev->dev, "xid 0x%x does not match ctx_xid 0x%x\n",
+			ddp->xid, xid);
+		goto out_put_ddp;
+	}
+
+	/* the same exchange has already errored out */
+	if (ddp->fcerr) {
+		dev_err(&pf->pdev->dev, "xid 0x%x fcerr 0x%x reported fcer 0x%x\n",
+			xid, ddp->fcerr, fcerr);
+		goto out_put_ddp;
+	}
+
+	/* fcoe param is valid by now with correct DDPed length */
+	ddp->len = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param);
+	ddp->fcerr = fcerr;
+	/* header posting only, useful only for target mode and debugging */
+	if (fltstat == I40E_RX_DESC_FLTSTAT_DDP) {
+		/* For target mode, we get header of the last packet but it
+		 * does not have the FCoE trailer field, i.e., CRC and EOF
+		 * Ordered Set since they are offloaded by the HW, so fill
+		 * it up correspondingly to allow the packet to pass through
+		 * to the upper protocol stack.
+		 */
+		u32 f_ctl = ntoh24(fh->fh_f_ctl);
+
+		if ((f_ctl & FC_FC_END_SEQ) &&
+		    (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA)) {
+			struct fcoe_crc_eof *crc = NULL;
+
+			crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
+			crc->fcoe_eof = FC_EOF_T;
+		} else {
+			/* otherwise, drop the header only frame */
+			rc = 0;
+			goto out_no_ddp;
+		}
+	}
+
+out_put_ddp:
+	/* either we got RSP or we have an error, unmap DMA in both cases */
+	i40e_fcoe_ddp_unmap(pf, ddp);
+	if (ddp->len && !ddp->fcerr) {
+		int pkts;
+
+		rc = ddp->len;
+		i40e_fcoe_ddp_clear(ddp);
+		ddp->len = rc;
+		pkts = DIV_ROUND_UP(rc, 2048);
+		rx_ring->stats.bytes += rc;
+		rx_ring->stats.packets += pkts;
+		rx_ring->q_vector->rx.total_bytes += rc;
+		rx_ring->q_vector->rx.total_packets += pkts;
+		set_bit(__I40E_FCOE_DDP_DONE, &ddp->flags);
+	}
+
+out_no_ddp:
+	return rc;
+}
+
+/**
+ * i40e_fcoe_ddp_setup - called to set up ddp context
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ * @target_mode: indicates this is a DDP request for target
+ *
+ * Returns : 1 for success and 0 for no DDP on this I/O
+ **/
+static int i40e_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
+			       struct scatterlist *sgl, unsigned int sgc,
+			       int target_mode)
+{
+	static const unsigned int bufflen = I40E_FCOE_DDP_BUF_MIN;
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_fcoe_ddp_pool *ddp_pool;
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	unsigned int i, j, dmacount;
+	struct i40e_fcoe_ddp *ddp;
+	unsigned int firstoff = 0;
+	unsigned int thisoff = 0;
+	unsigned int thislen = 0;
+	struct scatterlist *sg;
+	dma_addr_t addr = 0;
+	unsigned int len;
+
+	if (xid >= I40E_FCOE_DDP_MAX) {
+		dev_warn(&pf->pdev->dev, "xid=0x%x out-of-range\n", xid);
+		return 0;
+	}
+
+	/* no DDP if we are already down or resetting */
+	if (test_bit(__I40E_DOWN, &pf->state) ||
+	    test_bit(__I40E_NEEDS_RESTART, &pf->state)) {
+		dev_info(&pf->pdev->dev, "xid=0x%x device in reset/down\n",
+			 xid);
+		return 0;
+	}
+
+	ddp = &fcoe->ddp[xid];
+	if (ddp->sgl) {
+		dev_info(&pf->pdev->dev, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
+			 xid, ddp->sgl, ddp->sgc);
+		return 0;
+	}
+	i40e_fcoe_ddp_clear(ddp);
+
+	if (!fcoe->ddp_pool) {
+		dev_info(&pf->pdev->dev, "No DDP pool, xid 0x%x\n", xid);
+		return 0;
+	}
+
+	ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu());
+	if (!ddp_pool->pool) {
+		dev_info(&pf->pdev->dev, "No percpu ddp pool, xid 0x%x\n", xid);
+		goto out_noddp;
+	}
+
+	/* setup dma from scsi command sgl */
+	dmacount = dma_map_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
+	if (dmacount == 0) {
+		dev_info(&pf->pdev->dev, "dma_map_sg for sgl %p, sgc %d failed\n",
+			 sgl, sgc);
+		goto out_noddp_unmap;
+	}
+
+	/* alloc the udl from our ddp pool */
+	ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp);
+	if (!ddp->udl) {
+		dev_info(&pf->pdev->dev,
+			 "Failed allocated ddp context, xid 0x%x\n", xid);
+		goto out_noddp_unmap;
+	}
+
+	j = 0;
+	ddp->len = 0;
+	for_each_sg(sgl, sg, dmacount, i) {
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		ddp->len += len;
+		while (len) {
+			/* max number of buffers allowed in one DDP context */
+			if (j >= I40E_FCOE_DDP_BUFFCNT_MAX) {
+				dev_info(&pf->pdev->dev,
+					 "xid=%x:%d,%d,%d:addr=%llx not enough descriptors\n",
+					 xid, i, j, dmacount, (u64)addr);
+				goto out_noddp_free;
+			}
+
+			/* get the offset of length of current buffer */
+			thisoff = addr & ((dma_addr_t)bufflen - 1);
+			thislen = min_t(unsigned int, (bufflen - thisoff), len);
+			/* all but the 1st buffer (j == 0)
+			 * must be aligned on bufflen
+			 */
+			if ((j != 0) && (thisoff))
+				goto out_noddp_free;
+
+			/* all but the last buffer
+			 * ((i == (dmacount - 1)) && (thislen == len))
+			 * must end at bufflen
+			 */
+			if (((i != (dmacount - 1)) || (thislen != len)) &&
+			    ((thislen + thisoff) != bufflen))
+				goto out_noddp_free;
+
+			ddp->udl[j] = (u64)(addr - thisoff);
+			/* only the first buffer may have none-zero offset */
+			if (j == 0)
+				firstoff = thisoff;
+			len -= thislen;
+			addr += thislen;
+			j++;
+		}
+	}
+	/* only the last buffer may have non-full bufflen */
+	ddp->lastsize = thisoff + thislen;
+	ddp->firstoff = firstoff;
+	ddp->list_len = j;
+	ddp->pool = ddp_pool->pool;
+	ddp->sgl = sgl;
+	ddp->sgc = sgc;
+	ddp->xid = xid;
+	if (target_mode)
+		set_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
+	set_bit(__I40E_FCOE_DDP_INITALIZED, &ddp->flags);
+
+	put_cpu();
+	return 1; /* Success */
+
+out_noddp_free:
+	dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
+	i40e_fcoe_ddp_clear(ddp);
+
+out_noddp_unmap:
+	dma_unmap_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
+out_noddp:
+	put_cpu();
+	return 0;
+}
+
+/**
+ * i40e_fcoe_ddp_get - called to set up ddp context in initiator mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ **/
+static int i40e_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+			     struct scatterlist *sgl, unsigned int sgc)
+{
+	return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
+}
+
+/**
+ * i40e_fcoe_ddp_target - called to set up ddp context in target mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O. The DDP in target mode is a write I/O request
+ * from the initiator.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ **/
+static int i40e_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+				struct scatterlist *sgl, unsigned int sgc)
+{
+	return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
+}
+
+/**
+ * i40e_fcoe_program_ddp - programs the HW DDP related descriptors
+ * @tx_ring: transmit ring for this packet
+ * @skb:     the packet to be sent out
+ * @sof: the SOF to indicate class of service
+ *
+ * Determine if it is READ/WRITE command, and finds out if there is
+ * a matching SW DDP context for this command. DDP is applicable
+ * only in case of READ if initiator or WRITE in case of
+ * responder (via checking XFER_RDY).
+ *
+ * Note: caller checks sof and ddp sw context
+ *
+ * Returns : none
+ *
+ **/
+static void i40e_fcoe_program_ddp(struct i40e_ring *tx_ring,
+				  struct sk_buff *skb,
+				  struct i40e_fcoe_ddp *ddp, u8 sof)
+{
+	struct i40e_fcoe_filter_context_desc *filter_desc = NULL;
+	struct i40e_fcoe_queue_context_desc *queue_desc = NULL;
+	struct i40e_fcoe_ddp_context_desc *ddp_desc = NULL;
+	struct i40e_pf *pf = tx_ring->vsi->back;
+	u16 i = tx_ring->next_to_use;
+	struct fc_frame_header *fh;
+	u64 flags_rsvd_lanq = 0;
+	bool target_mode;
+
+	/* check if abort is still pending */
+	if (test_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) {
+		dev_warn(&pf->pdev->dev,
+			 "DDP abort is still pending xid:%hx and ddp->flags:%lx:\n",
+			 ddp->xid, ddp->flags);
+		return;
+	}
+
+	/* set the flag to indicate this is programmed */
+	if (test_and_set_bit(__I40E_FCOE_DDP_PROGRAMMED, &ddp->flags)) {
+		dev_warn(&pf->pdev->dev,
+			 "DDP is already programmed for xid:%hx and ddp->flags:%lx:\n",
+			 ddp->xid, ddp->flags);
+		return;
+	}
+
+	/* Prepare the DDP context descriptor */
+	ddp_desc = I40E_DDP_CONTEXT_DESC(tx_ring, i);
+	i++;
+	if (i == tx_ring->count)
+		i = 0;
+
+	ddp_desc->type_cmd_foff_lsize =
+				cpu_to_le64(I40E_TX_DESC_DTYPE_DDP_CTX	|
+				((u64)I40E_FCOE_DDP_CTX_DESC_BSIZE_4K  <<
+				I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)	|
+				((u64)ddp->firstoff		       <<
+				I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)	|
+				((u64)ddp->lastsize		       <<
+				I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT));
+	ddp_desc->rsvd = cpu_to_le64(0);
+
+	/* target mode needs last packet in the sequence  */
+	target_mode = test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
+	if (target_mode)
+		ddp_desc->type_cmd_foff_lsize |=
+			cpu_to_le64(I40E_FCOE_DDP_CTX_DESC_LASTSEQH);
+
+	/* Prepare queue_context descriptor */
+	queue_desc = I40E_QUEUE_CONTEXT_DESC(tx_ring, i++);
+	if (i == tx_ring->count)
+		i = 0;
+	queue_desc->dmaindx_fbase = cpu_to_le64(ddp->xid | ((u64)ddp->udp));
+	queue_desc->flen_tph = cpu_to_le64(ddp->list_len |
+				((u64)(I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC |
+				I40E_FCOE_QUEUE_CTX_DESC_TPHDATA) <<
+				I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT));
+
+	/* Prepare filter_context_desc */
+	filter_desc = I40E_FILTER_CONTEXT_DESC(tx_ring, i);
+	i++;
+	if (i == tx_ring->count)
+		i = 0;
+
+	fh = (struct fc_frame_header *)skb_transport_header(skb);
+	filter_desc->param = cpu_to_le32(ntohl(fh->fh_parm_offset));
+	filter_desc->seqn = cpu_to_le16(ntohs(fh->fh_seq_cnt));
+	filter_desc->rsvd_dmaindx = cpu_to_le16(ddp->xid <<
+				I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT);
+
+	flags_rsvd_lanq = I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP;
+	flags_rsvd_lanq |= (u64)(target_mode ?
+			I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP :
+			I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT);
+
+	flags_rsvd_lanq |= (u64)((sof == FC_SOF_I2 || sof == FC_SOF_N2) ?
+			I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 :
+			I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3);
+
+	flags_rsvd_lanq |= ((u64)skb->queue_mapping <<
+				I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT);
+	filter_desc->flags_rsvd_lanq = cpu_to_le64(flags_rsvd_lanq);
+
+	/* By this time, all offload related descriptors has been programmed */
+	tx_ring->next_to_use = i;
+}
+
+/**
+ * i40e_fcoe_invalidate_ddp - invalidates DDP in case of abort
+ * @tx_ring: transmit ring for this packet
+ * @skb: the packet associated w/ this DDP invalidation, i.e., ABTS
+ * @ddp: the SW DDP context for this DDP
+ *
+ * Programs the Tx context descriptor to do DDP invalidation.
+ **/
+static void i40e_fcoe_invalidate_ddp(struct i40e_ring *tx_ring,
+				     struct sk_buff *skb,
+				     struct i40e_fcoe_ddp *ddp)
+{
+	struct i40e_tx_context_desc *context_desc;
+	int i;
+
+	if (test_and_set_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags))
+		return;
+
+	i = tx_ring->next_to_use;
+	context_desc = I40E_TX_CTXTDESC(tx_ring, i);
+	i++;
+	if (i == tx_ring->count)
+		i = 0;
+
+	context_desc->tunneling_params = cpu_to_le32(0);
+	context_desc->l2tag2 = cpu_to_le16(0);
+	context_desc->rsvd = cpu_to_le16(0);
+	context_desc->type_cmd_tso_mss = cpu_to_le64(
+		I40E_TX_DESC_DTYPE_FCOE_CTX |
+		(I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL <<
+		I40E_TXD_CTX_QW1_CMD_SHIFT) |
+		(I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND <<
+		I40E_TXD_CTX_QW1_CMD_SHIFT));
+	tx_ring->next_to_use = i;
+}
+
+/**
+ * i40e_fcoe_handle_ddp - check we should setup or invalidate DDP
+ * @tx_ring: transmit ring for this packet
+ * @skb: the packet to be sent out
+ * @sof: the SOF to indicate class of service
+ *
+ * Determine if it is ABTS/READ/XFER_RDY, and finds out if there is
+ * a matching SW DDP context for this command. DDP is applicable
+ * only in case of READ if initiator or WRITE in case of
+ * responder (via checking XFER_RDY). In case this is an ABTS, send
+ * just invalidate the context.
+ **/
+static void i40e_fcoe_handle_ddp(struct i40e_ring *tx_ring,
+				 struct sk_buff *skb, u8 sof)
+{
+	struct i40e_pf *pf = tx_ring->vsi->back;
+	struct i40e_fcoe *fcoe = &pf->fcoe;
+	struct fc_frame_header *fh;
+	struct i40e_fcoe_ddp *ddp;
+	u32 f_ctl;
+	u8 r_ctl;
+	u16 xid;
+
+	fh = (struct fc_frame_header *)skb_transport_header(skb);
+	f_ctl = ntoh24(fh->fh_f_ctl);
+	r_ctl = fh->fh_r_ctl;
+	ddp = NULL;
+
+	if ((r_ctl == FC_RCTL_DD_DATA_DESC) && (f_ctl & FC_FC_EX_CTX)) {
+		/* exchange responder? if so, XFER_RDY for write */
+		xid = ntohs(fh->fh_rx_id);
+		if (i40e_fcoe_xid_is_valid(xid)) {
+			ddp = &fcoe->ddp[xid];
+			if ((ddp->xid == xid) &&
+			    (test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+				i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
+		}
+	} else if (r_ctl == FC_RCTL_DD_UNSOL_CMD) {
+		/* exchange originator, check READ cmd */
+		xid = ntohs(fh->fh_ox_id);
+		if (i40e_fcoe_xid_is_valid(xid)) {
+			ddp = &fcoe->ddp[xid];
+			if ((ddp->xid == xid) &&
+			    (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+				i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
+		}
+	} else if (r_ctl == FC_RCTL_BA_ABTS) {
+		/* exchange originator, check ABTS */
+		xid = ntohs(fh->fh_ox_id);
+		if (i40e_fcoe_xid_is_valid(xid)) {
+			ddp = &fcoe->ddp[xid];
+			if ((ddp->xid == xid) &&
+			    (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+				i40e_fcoe_invalidate_ddp(tx_ring, skb, ddp);
+		}
+	}
+}
+
+/**
+ * i40e_fcoe_tso - set up FCoE TSO
+ * @tx_ring:  ring to send buffer on
+ * @skb:      send buffer
+ * @tx_flags: collected send information
+ * @hdr_len:  the tso header length
+ * @sof: the SOF to indicate class of service
+ *
+ * Note must already have sof checked to be either class 2 or class 3 before
+ * calling this function.
+ *
+ * Returns 1 to indicate sequence segmentation offload is properly setup
+ * or returns 0 to indicate no tso is needed, otherwise returns error
+ * code to drop the frame.
+ **/
+static int i40e_fcoe_tso(struct i40e_ring *tx_ring,
+			 struct sk_buff *skb,
+			 u32 tx_flags, u8 *hdr_len, u8 sof)
+{
+	struct i40e_tx_context_desc *context_desc;
+	u32 cd_type, cd_cmd, cd_tso_len, cd_mss;
+	struct fc_frame_header *fh;
+	u64 cd_type_cmd_tso_mss;
+
+	/* must match gso type as FCoE */
+	if (!skb_is_gso(skb))
+		return 0;
+
+	/* is it the expected gso type for FCoE ?*/
+	if (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) {
+		netdev_err(skb->dev,
+			   "wrong gso type %d:expecting SKB_GSO_FCOE\n",
+			   skb_shinfo(skb)->gso_type);
+		return -EINVAL;
+	}
+
+	/* header and trailer are inserted by hw */
+	*hdr_len = skb_transport_offset(skb) + sizeof(struct fc_frame_header) +
+		   sizeof(struct fcoe_crc_eof);
+
+	/* check sof to decide a class 2 or 3 TSO */
+	if (likely(i40e_fcoe_sof_is_class3(sof)))
+		cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3;
+	else
+		cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2;
+
+	/* param field valid? */
+	fh = (struct fc_frame_header *)skb_transport_header(skb);
+	if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
+		cd_cmd |= I40E_FCOE_TX_CTX_DESC_RELOFF;
+
+	/* fill the field values */
+	cd_type = I40E_TX_DESC_DTYPE_FCOE_CTX;
+	cd_tso_len = skb->len - *hdr_len;
+	cd_mss = skb_shinfo(skb)->gso_size;
+	cd_type_cmd_tso_mss =
+		((u64)cd_type  << I40E_TXD_CTX_QW1_DTYPE_SHIFT)     |
+		((u64)cd_cmd     << I40E_TXD_CTX_QW1_CMD_SHIFT)	    |
+		((u64)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+		((u64)cd_mss     << I40E_TXD_CTX_QW1_MSS_SHIFT);
+
+	/* grab the next descriptor */
+	context_desc = I40E_TX_CTXTDESC(tx_ring, tx_ring->next_to_use);
+	tx_ring->next_to_use++;
+	if (tx_ring->next_to_use == tx_ring->count)
+		tx_ring->next_to_use = 0;
+
+	context_desc->tunneling_params = 0;
+	context_desc->l2tag2 = cpu_to_le16((tx_flags & I40E_TX_FLAGS_VLAN_MASK)
+					    >> I40E_TX_FLAGS_VLAN_SHIFT);
+	context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
+
+	return 1;
+}
+
+/**
+ * i40e_fcoe_tx_map - build the tx descriptor
+ * @tx_ring:  ring to send buffer on
+ * @skb:      send buffer
+ * @first:    first buffer info buffer to use
+ * @tx_flags: collected send information
+ * @hdr_len:  ptr to the size of the packet header
+ * @eof:      the frame eof value
+ *
+ * Note, for FCoE, sof and eof are already checked
+ **/
+static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring,
+			     struct sk_buff *skb,
+			     struct i40e_tx_buffer *first,
+			     u32 tx_flags, u8 hdr_len, u8 eof)
+{
+	u32 td_offset = 0;
+	u32 td_cmd = 0;
+	u32 maclen;
+
+	/* insert CRC */
+	td_cmd = I40E_TX_DESC_CMD_ICRC;
+
+	/* setup MACLEN */
+	maclen = skb_network_offset(skb);
+	if (tx_flags & I40E_TX_FLAGS_SW_VLAN)
+		maclen += sizeof(struct vlan_hdr);
+
+	if (skb->protocol == htons(ETH_P_FCOE)) {
+		/* for FCoE, maclen should exclude ether type */
+		maclen -= 2;
+		/* setup type as FCoE and EOF insertion */
+		td_cmd |= (I40E_TX_DESC_CMD_FCOET | i40e_fcoe_ctxt_eof(eof));
+		/* setup FCoELEN and FCLEN */
+		td_offset |= ((((sizeof(struct fcoe_hdr) + 2) >> 2) <<
+				I40E_TX_DESC_LENGTH_IPLEN_SHIFT) |
+			      ((sizeof(struct fc_frame_header) >> 2) <<
+				I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT));
+		/* trim to exclude trailer */
+		pskb_trim(skb, skb->len - sizeof(struct fcoe_crc_eof));
+	}
+
+	/* MACLEN is ether header length in words not bytes */
+	td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
+
+	return i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+			   td_cmd, td_offset);
+}
+
+/**
+ * i40e_fcoe_set_skb_header - adjust skb header point for FIP/FCoE/FC
+ * @skb: the skb to be adjusted
+ *
+ * Returns true if this skb is a FCoE/FIP or VLAN carried FCoE/FIP and then
+ * adjusts the skb header pointers correspondingly. Otherwise, returns false.
+ **/
+static inline int i40e_fcoe_set_skb_header(struct sk_buff *skb)
+{
+	__be16 protocol = skb->protocol;
+
+	skb_reset_mac_header(skb);
+	skb->mac_len = sizeof(struct ethhdr);
+	if (protocol == htons(ETH_P_8021Q)) {
+		struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb);
+
+		protocol = veth->h_vlan_encapsulated_proto;
+		skb->mac_len += sizeof(struct vlan_hdr);
+	}
+
+	/* FCoE or FIP only */
+	if ((protocol != htons(ETH_P_FIP)) &&
+	    (protocol != htons(ETH_P_FCOE)))
+		return -EINVAL;
+
+	/* set header to L2 of FCoE/FIP */
+	skb_set_network_header(skb, skb->mac_len);
+	if (protocol == htons(ETH_P_FIP))
+		return 0;
+
+	/* set header to L3 of FC */
+	skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
+	return 0;
+}
+
+/**
+ * i40e_fcoe_xmit_frame - transmit buffer
+ * @skb:     send buffer
+ * @netdev:  the fcoe netdev
+ *
+ * Returns 0 if sent, else an error code
+ **/
+static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb,
+					struct net_device *netdev)
+{
+	struct i40e_netdev_priv *np = netdev_priv(skb->dev);
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping];
+	struct i40e_tx_buffer *first;
+	u32 tx_flags = 0;
+	u8 hdr_len = 0;
+	u8 sof = 0;
+	u8 eof = 0;
+	int fso;
+
+	if (i40e_fcoe_set_skb_header(skb))
+		goto out_drop;
+
+	if (!i40e_xmit_descriptor_count(skb, tx_ring))
+		return NETDEV_TX_BUSY;
+
+	/* prepare the xmit flags */
+	if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
+		goto out_drop;
+
+	/* record the location of the first descriptor for this packet */
+	first = &tx_ring->tx_bi[tx_ring->next_to_use];
+
+	/* FIP is a regular L2 traffic w/o offload */
+	if (skb->protocol == htons(ETH_P_FIP))
+		goto out_send;
+
+	/* check sof and eof, only supports FC Class 2 or 3 */
+	if (i40e_fcoe_fc_sof(skb, &sof) || i40e_fcoe_fc_eof(skb, &eof)) {
+		netdev_err(netdev, "SOF/EOF error:%02x - %02x\n", sof, eof);
+		goto out_drop;
+	}
+
+	/* always do FCCRC for FCoE */
+	tx_flags |= I40E_TX_FLAGS_FCCRC;
+
+	/* check we should do sequence offload */
+	fso = i40e_fcoe_tso(tx_ring, skb, tx_flags, &hdr_len, sof);
+	if (fso < 0)
+		goto out_drop;
+	else if (fso)
+		tx_flags |= I40E_TX_FLAGS_FSO;
+	else
+		i40e_fcoe_handle_ddp(tx_ring, skb, sof);
+
+out_send:
+	/* send out the packet */
+	i40e_fcoe_tx_map(tx_ring, skb, first, tx_flags, hdr_len, eof);
+
+	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+	return NETDEV_TX_OK;
+
+out_drop:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+/**
+ * i40e_fcoe_change_mtu - NDO callback to change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns error as operation not permitted
+ *
+ **/
+static int i40e_fcoe_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	netdev_warn(netdev, "MTU change is not supported on FCoE interfaces\n");
+	return -EPERM;
+}
+
+/**
+ * i40e_fcoe_set_features - set the netdev feature flags
+ * @netdev: ptr to the netdev being adjusted
+ * @features: the feature set that the stack is suggesting
+ *
+ **/
+static int i40e_fcoe_set_features(struct net_device *netdev,
+				  netdev_features_t features)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+
+	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		i40e_vlan_stripping_enable(vsi);
+	else
+		i40e_vlan_stripping_disable(vsi);
+
+	return 0;
+}
+
+
+static const struct net_device_ops i40e_fcoe_netdev_ops = {
+	.ndo_open		= i40e_open,
+	.ndo_stop		= i40e_close,
+	.ndo_get_stats64	= i40e_get_netdev_stats_struct,
+	.ndo_set_rx_mode	= i40e_set_rx_mode,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= i40e_set_mac,
+	.ndo_change_mtu		= i40e_fcoe_change_mtu,
+	.ndo_do_ioctl		= i40e_ioctl,
+	.ndo_tx_timeout		= i40e_tx_timeout,
+	.ndo_vlan_rx_add_vid	= i40e_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= i40e_vlan_rx_kill_vid,
+	.ndo_setup_tc		= i40e_setup_tc,
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= i40e_netpoll,
+#endif
+	.ndo_start_xmit		= i40e_fcoe_xmit_frame,
+	.ndo_fcoe_enable	= i40e_fcoe_enable,
+	.ndo_fcoe_disable	= i40e_fcoe_disable,
+	.ndo_fcoe_ddp_setup	= i40e_fcoe_ddp_get,
+	.ndo_fcoe_ddp_done	= i40e_fcoe_ddp_put,
+	.ndo_fcoe_ddp_target	= i40e_fcoe_ddp_target,
+	.ndo_set_features	= i40e_fcoe_set_features,
+};
+
+/**
+ * i40e_fcoe_config_netdev - prepares the VSI context for creating a FCoE VSI
+ * @vsi: pointer to the associated VSI struct
+ * @ctxt: pointer to the associated VSI context to be passed to HW
+ *
+ * Returns 0 on success or < 0 on error
+ **/
+void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)
+{
+	struct i40e_hw *hw = &vsi->back->hw;
+	struct i40e_pf *pf = vsi->back;
+
+	if (vsi->type != I40E_VSI_FCOE)
+		return;
+
+	netdev->features = (NETIF_F_HW_VLAN_CTAG_TX |
+			    NETIF_F_HW_VLAN_CTAG_RX |
+			    NETIF_F_HW_VLAN_CTAG_FILTER);
+
+	netdev->vlan_features = netdev->features;
+	netdev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
+				   NETIF_F_HW_VLAN_CTAG_RX |
+				   NETIF_F_HW_VLAN_CTAG_FILTER);
+	netdev->fcoe_ddp_xid = I40E_FCOE_DDP_MAX - 1;
+	netdev->features |= NETIF_F_ALL_FCOE;
+	netdev->vlan_features |= NETIF_F_ALL_FCOE;
+	netdev->hw_features |= netdev->features;
+	netdev->priv_flags |= IFF_UNICAST_FLT;
+	netdev->priv_flags |= IFF_SUPP_NOFCS;
+
+	strlcpy(netdev->name, "fcoe%d", IFNAMSIZ-1);
+	netdev->mtu = FCOE_MTU;
+	SET_NETDEV_DEV(netdev, &pf->pdev->dev);
+	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);
+	i40e_add_filter(vsi, FIP_ALL_VN2VN_MACS, 0, false, false);
+	i40e_add_filter(vsi, FIP_ALL_P2P_MACS, 0, false, false);
+
+	/* use san mac */
+	ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
+	ether_addr_copy(netdev->perm_addr, hw->mac.san_addr);
+	/* fcoe netdev ops */
+	netdev->netdev_ops = &i40e_fcoe_netdev_ops;
+}
+
+/**
+ * i40e_fcoe_vsi_setup - allocate and set up FCoE VSI
+ * @pf: the pf that VSI is associated with
+ *
+ **/
+void i40e_fcoe_vsi_setup(struct i40e_pf *pf)
+{
+	struct i40e_vsi *vsi;
+	u16 seid;
+	int i;
+
+	if (!(pf->flags & I40E_FLAG_FCOE_ENABLED))
+		return;
+
+	BUG_ON(!pf->vsi[pf->lan_vsi]);
+
+	for (i = 0; i < pf->num_alloc_vsi; i++) {
+		vsi = pf->vsi[i];
+		if (vsi && vsi->type == I40E_VSI_FCOE) {
+			dev_warn(&pf->pdev->dev,
+				 "FCoE VSI already created\n");
+			return;
+		}
+	}
+
+	seid = pf->vsi[pf->lan_vsi]->seid;
+	vsi = i40e_vsi_setup(pf, I40E_VSI_FCOE, seid, 0);
+	if (vsi) {
+		dev_dbg(&pf->pdev->dev,
+			"Successfully created FCoE VSI seid %d id %d uplink_seid %d pf seid %d\n",
+			vsi->seid, vsi->id, vsi->uplink_seid, seid);
+	} else {
+		dev_info(&pf->pdev->dev, "Failed to create FCoE VSI\n");
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_FCOE_H_
+#define _I40E_FCOE_H_
+
+/* FCoE HW context helper macros */
+#define I40E_DDP_CONTEXT_DESC(R, i)     \
+	(&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
+
+#define I40E_QUEUE_CONTEXT_DESC(R, i)   \
+	(&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
+
+#define I40E_FILTER_CONTEXT_DESC(R, i)  \
+	(&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
+
+
+/* receive queue descriptor filter status for FCoE */
+#define I40E_RX_DESC_FLTSTAT_FCMASK	0x3
+#define I40E_RX_DESC_FLTSTAT_NOMTCH	0x0	/* no ddp context match */
+#define I40E_RX_DESC_FLTSTAT_NODDP	0x1	/* no ddp due to error */
+#define I40E_RX_DESC_FLTSTAT_DDP	0x2	/* DDPed payload, post header */
+#define I40E_RX_DESC_FLTSTAT_FCPRSP	0x3	/* FCP_RSP */
+
+/* receive queue descriptor error codes for FCoE */
+#define I40E_RX_DESC_FCOE_ERROR_MASK		\
+	(I40E_RX_DESC_ERROR_L3L4E_PROT |	\
+	 I40E_RX_DESC_ERROR_L3L4E_FC |		\
+	 I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR |	\
+	 I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
+
+/* receive queue descriptor programming error */
+#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e)	\
+	(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
+
+#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)	\
+	(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
+
+#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT	\
+	(1 << I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
+#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT	\
+	(1 << I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
+
+#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e)	\
+	I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
+#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT	\
+	I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
+
+/* FCoE DDP related definitions */
+#define I40E_FCOE_MIN_XID	0x0000  /* the min xid supported by fcoe_sw */
+#define I40E_FCOE_MAX_XID	0x0FFF  /* the max xid supported by fcoe_sw */
+#define I40E_FCOE_DDP_BUFFCNT_MAX	512	/* 9 bits bufcnt */
+#define I40E_FCOE_DDP_PTR_ALIGN		16
+#define I40E_FCOE_DDP_PTR_MAX	(I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
+#define I40E_FCOE_DDP_BUF_MIN	4096
+#define I40E_FCOE_DDP_MAX	2048
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT	8
+
+/* supported netdev features for FCoE */
+#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
+	NETIF_F_HW_VLAN_CTAG_TX | \
+	NETIF_F_HW_VLAN_CTAG_RX | \
+	NETIF_F_HW_VLAN_CTAG_FILTER)
+
+/* DDP context flags */
+enum i40e_fcoe_ddp_flags {
+	__I40E_FCOE_DDP_NONE = 1,
+	__I40E_FCOE_DDP_TARGET,
+	__I40E_FCOE_DDP_INITALIZED,
+	__I40E_FCOE_DDP_PROGRAMMED,
+	__I40E_FCOE_DDP_DONE,
+	__I40E_FCOE_DDP_ABORTED,
+	__I40E_FCOE_DDP_UNMAPPED,
+};
+
+/* DDP SW context struct */
+struct i40e_fcoe_ddp {
+	int len;
+	u16 xid;
+	u16 firstoff;
+	u16 lastsize;
+	u16 list_len;
+	u8 fcerr;
+	u8 prerr;
+	unsigned long flags;
+	unsigned int sgc;
+	struct scatterlist *sgl;
+	dma_addr_t udp;
+	u64 *udl;
+	struct dma_pool *pool;
+
+};
+
+struct i40e_fcoe_ddp_pool {
+	struct dma_pool *pool;
+};
+
+struct i40e_fcoe {
+	unsigned long mode;
+	atomic_t refcnt;
+	struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
+	struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
+};
+
+#endif /* _I40E_FCOE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e.h	2014-09-28 17:29:07.000000000 -0400
@@ -54,6 +54,9 @@
 #include <linux/ptp_clock_kernel.h>
 #include "i40e_type.h"
 #include "i40e_prototype.h"
+#ifdef I40E_FCOE
+#include "i40e_fcoe.h"
+#endif
 #include "i40e_virtchnl.h"
 #include "i40e_virtchnl_pf.h"
 #include "i40e_txrx.h"
@@ -79,11 +82,16 @@
 #define I40E_MAX_QUEUES_PER_TC        64 /* should be a power of 2 */
 #define I40E_FDIR_RING                0
 #define I40E_FDIR_RING_COUNT          32
+#ifdef I40E_FCOE
+#define I40E_DEFAULT_FCOE             8 /* default number of QPs for FCoE */
+#define I40E_MINIMUM_FCOE             1 /* minimum number of QPs for FCoE */
+#endif /* I40E_FCOE */
 #define I40E_MAX_AQ_BUF_SIZE          4096
 #define I40E_AQ_LEN                   32
 #define I40E_AQ_WORK_LIMIT            16
 #define I40E_MAX_USER_PRIORITY        8
 #define I40E_DEFAULT_MSG_ENABLE       4
+#define I40E_QUEUE_WAIT_RETRY_LIMIT   10
 
 #define I40E_NVM_VERSION_LO_SHIFT  0
 #define I40E_NVM_VERSION_LO_MASK   (0xff << I40E_NVM_VERSION_LO_SHIFT)
@@ -133,7 +141,9 @@ enum i40e_state_t {
 	__I40E_EMP_RESET_REQUESTED,
 	__I40E_FILTER_OVERFLOW_PROMISC,
 	__I40E_SUSPENDED,
+	__I40E_PTP_TX_IN_PROGRESS,
 	__I40E_BAD_EEPROM,
+	__I40E_DOWN_REQUESTED,
 };
 
 enum i40e_interrupt_policy {
@@ -152,7 +162,7 @@ struct i40e_lump_tracking {
 #define I40E_DEFAULT_ATR_SAMPLE_RATE	20
 #define I40E_FDIR_MAX_RAW_PACKET_SIZE	512
 #define I40E_FDIR_BUFFER_FULL_MARGIN	10
-#define I40E_FDIR_BUFFER_HEAD_ROOM	200
+#define I40E_FDIR_BUFFER_HEAD_ROOM	32
 
 enum i40e_fd_stat_idx {
 	I40E_FD_STAT_ATR,
@@ -222,6 +232,10 @@ struct i40e_pf {
 	u16 num_vmdq_msix;         /* num queue vectors per vmdq pool */
 	u16 num_req_vfs;           /* num vfs requested for this vf */
 	u16 num_vf_qps;            /* num queue pairs per vf */
+#ifdef I40E_FCOE
+	u16 num_fcoe_qps;          /* num fcoe queues this pf has set up */
+	u16 num_fcoe_msix;         /* num queue vectors per fcoe pool */
+#endif /* I40E_FCOE */
 	u16 num_lan_qps;           /* num lan queues this pf has set up */
 	u16 num_lan_msix;          /* num queue vectors for the base pf vsi */
 	int queues_left;           /* queues left unclaimed */
@@ -262,6 +276,9 @@ struct i40e_pf {
 #define I40E_FLAG_VMDQ_ENABLED                 (u64)(1 << 7)
 #define I40E_FLAG_FDIR_REQUIRES_REINIT         (u64)(1 << 8)
 #define I40E_FLAG_NEED_LINK_UPDATE             (u64)(1 << 9)
+#ifdef I40E_FCOE
+#define I40E_FLAG_FCOE_ENABLED                 (u64)(1 << 11)
+#endif /* I40E_FCOE */
 #define I40E_FLAG_IN_NETPOLL                   (u64)(1 << 12)
 #define I40E_FLAG_16BYTE_RX_DESC_ENABLED       (u64)(1 << 13)
 #define I40E_FLAG_CLEAN_ADMINQ                 (u64)(1 << 14)
@@ -277,11 +294,16 @@ struct i40e_pf {
 #ifdef CONFIG_I40E_VXLAN
 #define I40E_FLAG_VXLAN_FILTER_SYNC            (u64)(1 << 27)
 #endif
+#define I40E_FLAG_PORT_ID_VALID                (u64)(1 << 28)
 #define I40E_FLAG_DCB_CAPABLE                  (u64)(1 << 29)
 
 	/* tracks features that get auto disabled by errors */
 	u64 auto_disable_flags;
 
+#ifdef I40E_FCOE
+	struct i40e_fcoe fcoe;
+
+#endif /* I40E_FCOE */
 	bool stat_offsets_loaded;
 	struct i40e_hw_port_stats stats;
 	struct i40e_hw_port_stats stats_offsets;
@@ -348,6 +370,7 @@ struct i40e_pf {
 	u32 rx_hwtstamp_cleared;
 	bool ptp_tx;
 	bool ptp_rx;
+	u16 rss_table_size;
 };
 
 struct i40e_mac_filter {
@@ -359,6 +382,7 @@ struct i40e_mac_filter {
 	bool is_vf;		/* filter belongs to a VF */
 	bool is_netdev;		/* filter belongs to a netdev */
 	bool changed;		/* filter needs to be sync'd to the HW */
+	bool is_laa;		/* filter is a Locally Administered Address */
 };
 
 struct i40e_veb {
@@ -402,6 +426,11 @@ struct i40e_vsi {
 	struct rtnl_link_stats64 net_stats_offsets;
 	struct i40e_eth_stats eth_stats;
 	struct i40e_eth_stats eth_stats_offsets;
+#ifdef I40E_FCOE
+	struct i40e_fcoe_stats fcoe_stats;
+	struct i40e_fcoe_stats fcoe_stats_offsets;
+	bool fcoe_stat_offsets_loaded;
+#endif
 	u32 tx_restart;
 	u32 tx_busy;
 	u32 rx_buf_failed;
@@ -578,6 +607,7 @@ int i40e_add_del_fdir(struct i40e_vsi *v
 		      struct i40e_fdir_filter *input, bool add);
 void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
 int i40e_get_current_fd_count(struct i40e_pf *pf);
+int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
 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,
@@ -591,6 +621,11 @@ struct i40e_vsi *i40e_vsi_setup(struct i
 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,
+			      u8 enabled_tc, bool is_add);
+#endif
 int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
 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,
@@ -614,9 +649,24 @@ static inline void i40e_dbg_init(void) {
 static inline void i40e_dbg_exit(void) {}
 #endif /* CONFIG_DEBUG_FS*/
 void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
+void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
 void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
 void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
+#ifdef I40E_FCOE
+struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
+					     struct net_device *netdev,
+					     struct rtnl_link_stats64 *storage);
+int i40e_set_mac(struct net_device *netdev, void *p);
+void i40e_set_rx_mode(struct net_device *netdev);
+#endif
 int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+#ifdef I40E_FCOE
+void i40e_tx_timeout(struct net_device *netdev);
+int i40e_vlan_rx_add_vid(struct net_device *netdev,
+			 __always_unused __be16 proto, u16 vid);
+int i40e_vlan_rx_kill_vid(struct net_device *netdev,
+			  __always_unused __be16 proto, u16 vid);
+#endif
 int i40e_vsi_open(struct i40e_vsi *vsi);
 void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
 int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
@@ -626,6 +676,26 @@ struct i40e_mac_filter *i40e_put_mac_in_
 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);
+#ifdef I40E_FCOE
+int i40e_open(struct net_device *netdev);
+int i40e_close(struct net_device *netdev);
+int i40e_setup_tc(struct net_device *netdev, u8 tc);
+void i40e_netpoll(struct net_device *netdev);
+int i40e_fcoe_enable(struct net_device *netdev);
+int i40e_fcoe_disable(struct net_device *netdev);
+int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt);
+u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf);
+void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi);
+void i40e_fcoe_vsi_setup(struct i40e_pf *pf);
+int i40e_init_pf_fcoe(struct i40e_pf *pf);
+int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi);
+void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi);
+int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
+			     union i40e_rx_desc *rx_desc,
+			     struct sk_buff *skb);
+void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
+			     union i40e_rx_desc *rx_desc, u8 prog_id);
+#endif /* I40E_FCOE */
 void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
 #ifdef CONFIG_I40E_DCB
 void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_hmc.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_hmc.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_hmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_hmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -127,7 +127,7 @@ struct i40e_hmc_info {
 		((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<		\
 		I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) |			\
 		(1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT);		\
-	val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
+	val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
 	wr32((hw), I40E_PFHMC_SDDATAHIGH, val1);			\
 	wr32((hw), I40E_PFHMC_SDDATALOW, val2);				\
 	wr32((hw), I40E_PFHMC_SDCMD, val3);				\
@@ -146,7 +146,7 @@ struct i40e_hmc_info {
 		I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |		\
 		((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<		\
 		I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT);			\
-	val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
+	val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
 	wr32((hw), I40E_PFHMC_SDDATAHIGH, 0);				\
 	wr32((hw), I40E_PFHMC_SDDATALOW, val2);				\
 	wr32((hw), I40E_PFHMC_SDCMD, val3);				\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -417,7 +417,6 @@ static i40e_status i40e_create_lan_hmc_o
 			default:
 				ret_code = I40E_ERR_INVALID_SD_TYPE;
 				goto exit;
-				break;
 			}
 		}
 	}
@@ -502,7 +501,6 @@ try_type_paged:
 		hw_dbg(hw, "i40e_configure_lan_hmc: Unknown SD type: %d\n",
 			  ret_code);
 		goto configure_lan_hmc_out;
-		break;
 	}
 
 	/* Configure and program the FPM registers so objects can be created */
@@ -747,6 +745,194 @@ static struct i40e_context_ele i40e_hmc_
 };
 
 /**
+ * i40e_write_byte - replace HMC context byte
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_byte(u8 *hmc_bits,
+			    struct i40e_context_ele *ce_info,
+			    u8 *src)
+{
+	u8 src_byte, dest_byte, mask;
+	u8 *from, *dest;
+	u16 shift_width;
+
+	/* copy from the next struct field */
+	from = src + ce_info->offset;
+
+	/* prepare the bits and mask */
+	shift_width = ce_info->lsb % 8;
+	mask = ((u8)1 << ce_info->width) - 1;
+
+	src_byte = *from;
+	src_byte &= mask;
+
+	/* shift to correct alignment */
+	mask <<= shift_width;
+	src_byte <<= shift_width;
+
+	/* get the current bits from the target bit string */
+	dest = hmc_bits + (ce_info->lsb / 8);
+
+	memcpy(&dest_byte, dest, sizeof(dest_byte));
+
+	dest_byte &= ~mask;	/* get the bits not changing */
+	dest_byte |= src_byte;	/* add in the new bits */
+
+	/* put it all back */
+	memcpy(dest, &dest_byte, sizeof(dest_byte));
+}
+
+/**
+ * i40e_write_word - replace HMC context word
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_word(u8 *hmc_bits,
+			    struct i40e_context_ele *ce_info,
+			    u8 *src)
+{
+	u16 src_word, mask;
+	u8 *from, *dest;
+	u16 shift_width;
+	__le16 dest_word;
+
+	/* copy from the next struct field */
+	from = src + ce_info->offset;
+
+	/* prepare the bits and mask */
+	shift_width = ce_info->lsb % 8;
+	mask = ((u16)1 << ce_info->width) - 1;
+
+	/* don't swizzle the bits until after the mask because the mask bits
+	 * will be in a different bit position on big endian machines
+	 */
+	src_word = *(u16 *)from;
+	src_word &= mask;
+
+	/* shift to correct alignment */
+	mask <<= shift_width;
+	src_word <<= shift_width;
+
+	/* get the current bits from the target bit string */
+	dest = hmc_bits + (ce_info->lsb / 8);
+
+	memcpy(&dest_word, dest, sizeof(dest_word));
+
+	dest_word &= ~(cpu_to_le16(mask));	/* get the bits not changing */
+	dest_word |= cpu_to_le16(src_word);	/* add in the new bits */
+
+	/* put it all back */
+	memcpy(dest, &dest_word, sizeof(dest_word));
+}
+
+/**
+ * i40e_write_dword - replace HMC context dword
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_dword(u8 *hmc_bits,
+			     struct i40e_context_ele *ce_info,
+			     u8 *src)
+{
+	u32 src_dword, mask;
+	u8 *from, *dest;
+	u16 shift_width;
+	__le32 dest_dword;
+
+	/* copy from the next struct field */
+	from = src + ce_info->offset;
+
+	/* prepare the bits and mask */
+	shift_width = ce_info->lsb % 8;
+
+	/* if the field width is exactly 32 on an x86 machine, then the shift
+	 * operation will not work because the SHL instructions count is masked
+	 * to 5 bits so the shift will do nothing
+	 */
+	if (ce_info->width < 32)
+		mask = ((u32)1 << ce_info->width) - 1;
+	else
+		mask = 0xFFFFFFFF;
+
+	/* don't swizzle the bits until after the mask because the mask bits
+	 * will be in a different bit position on big endian machines
+	 */
+	src_dword = *(u32 *)from;
+	src_dword &= mask;
+
+	/* shift to correct alignment */
+	mask <<= shift_width;
+	src_dword <<= shift_width;
+
+	/* get the current bits from the target bit string */
+	dest = hmc_bits + (ce_info->lsb / 8);
+
+	memcpy(&dest_dword, dest, sizeof(dest_dword));
+
+	dest_dword &= ~(cpu_to_le32(mask));	/* get the bits not changing */
+	dest_dword |= cpu_to_le32(src_dword);	/* add in the new bits */
+
+	/* put it all back */
+	memcpy(dest, &dest_dword, sizeof(dest_dword));
+}
+
+/**
+ * i40e_write_qword - replace HMC context qword
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_qword(u8 *hmc_bits,
+			     struct i40e_context_ele *ce_info,
+			     u8 *src)
+{
+	u64 src_qword, mask;
+	u8 *from, *dest;
+	u16 shift_width;
+	__le64 dest_qword;
+
+	/* copy from the next struct field */
+	from = src + ce_info->offset;
+
+	/* prepare the bits and mask */
+	shift_width = ce_info->lsb % 8;
+
+	/* if the field width is exactly 64 on an x86 machine, then the shift
+	 * operation will not work because the SHL instructions count is masked
+	 * to 6 bits so the shift will do nothing
+	 */
+	if (ce_info->width < 64)
+		mask = ((u64)1 << ce_info->width) - 1;
+	else
+		mask = 0xFFFFFFFFFFFFFFFF;
+
+	/* don't swizzle the bits until after the mask because the mask bits
+	 * will be in a different bit position on big endian machines
+	 */
+	src_qword = *(u64 *)from;
+	src_qword &= mask;
+
+	/* shift to correct alignment */
+	mask <<= shift_width;
+	src_qword <<= shift_width;
+
+	/* get the current bits from the target bit string */
+	dest = hmc_bits + (ce_info->lsb / 8);
+
+	memcpy(&dest_qword, dest, sizeof(dest_qword));
+
+	dest_qword &= ~(cpu_to_le64(mask));	/* get the bits not changing */
+	dest_qword |= cpu_to_le64(src_qword);	/* add in the new bits */
+
+	/* put it all back */
+	memcpy(dest, &dest_qword, sizeof(dest_qword));
+}
+
+/**
  * i40e_clear_hmc_context - zero out the HMC context bits
  * @hw:       the hardware struct
  * @context_bytes: pointer to the context bit array (DMA memory)
@@ -772,71 +958,28 @@ static i40e_status i40e_set_hmc_context(
 					struct i40e_context_ele *ce_info,
 					u8 *dest)
 {
-	u16 shift_width;
-	u64 bitfield;
-	u8 hi_byte;
-	u8 hi_mask;
-	u64 t_bits;
-	u64 mask;
-	u8 *p;
 	int f;
 
 	for (f = 0; ce_info[f].width != 0; f++) {
-		/* clear out the field */
-		bitfield = 0;
 
-		/* copy from the next struct field */
-		p = dest + ce_info[f].offset;
+		/* we have to deal with each element of the HMC using the
+		 * correct size so that we are correct regardless of the
+		 * endianness of the machine
+		 */
 		switch (ce_info[f].size_of) {
 		case 1:
-			bitfield = *p;
+			i40e_write_byte(context_bytes, &ce_info[f], dest);
 			break;
 		case 2:
-			bitfield = cpu_to_le16(*(u16 *)p);
+			i40e_write_word(context_bytes, &ce_info[f], dest);
 			break;
 		case 4:
-			bitfield = cpu_to_le32(*(u32 *)p);
+			i40e_write_dword(context_bytes, &ce_info[f], dest);
 			break;
 		case 8:
-			bitfield = cpu_to_le64(*(u64 *)p);
+			i40e_write_qword(context_bytes, &ce_info[f], dest);
 			break;
 		}
-
-		/* prepare the bits and mask */
-		shift_width = ce_info[f].lsb % 8;
-		mask = ((u64)1 << ce_info[f].width) - 1;
-
-		/* save upper bytes for special case */
-		hi_mask = (u8)((mask >> 56) & 0xff);
-		hi_byte = (u8)((bitfield >> 56) & 0xff);
-
-		/* shift to correct alignment */
-		mask <<= shift_width;
-		bitfield <<= shift_width;
-
-		/* get the current bits from the target bit string */
-		p = context_bytes + (ce_info[f].lsb / 8);
-		memcpy(&t_bits, p, sizeof(u64));
-
-		t_bits &= ~mask;          /* get the bits not changing */
-		t_bits |= bitfield;       /* add in the new bits */
-
-		/* put it all back */
-		memcpy(p, &t_bits, sizeof(u64));
-
-		/* deal with the special case if needed
-		 * example: 62 bit field that starts in bit 5 of first byte
-		 *          will overlap 3 bits into byte 9
-		 */
-		if ((shift_width + ce_info[f].width) > 64) {
-			u8 byte;
-
-			hi_mask >>= (8 - shift_width);
-			hi_byte >>= (8 - shift_width);
-			byte = p[8] & ~hi_mask;  /* get the bits not changing */
-			byte |= hi_byte;         /* add in the new bits */
-			p[8] = byte;             /* put it back */
-		}
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,16 +32,22 @@ struct i40e_hw;
 
 /* HMC element context information */
 
-/* Rx queue context data */
+/* Rx queue context data
+ *
+ * The sizes of the variables may be larger than needed due to crossing byte
+ * boundaries. If we do not have the width of the variable set to the correct
+ * size then we could end up shifting bits off the top of the variable when the
+ * variable is at the top of a byte and crosses over into the next byte.
+ */
 struct i40e_hmc_obj_rxq {
 	u16 head;
-	u8  cpuid;
+	u16 cpuid; /* bigger than needed, see above for reason */
 	u64 base;
 	u16 qlen;
 #define I40E_RXQ_CTX_DBUFF_SHIFT 7
-	u8  dbuff;
+	u16 dbuff; /* bigger than needed, see above for reason */
 #define I40E_RXQ_CTX_HBUFF_SHIFT 6
-	u8  hbuff;
+	u16 hbuff; /* bigger than needed, see above for reason */
 	u8  dtype;
 	u8  dsize;
 	u8  crcstrip;
@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
 	u8  hsplit_0;
 	u8  hsplit_1;
 	u8  showiv;
-	u16 rxmax;
+	u32 rxmax; /* bigger than needed, see above for reason */
 	u8  tphrdesc_ena;
 	u8  tphwdesc_ena;
 	u8  tphdata_ena;
 	u8  tphhead_ena;
-	u8  lrxqthresh;
+	u16 lrxqthresh; /* bigger than needed, see above for reason */
 	u8  prefena;	/* NOTE: normally must be set to 1 at init */
 };
 
-/* Tx queue context data */
+/* Tx queue context data
+*
+* The sizes of the variables may be larger than needed due to crossing byte
+* boundaries. If we do not have the width of the variable set to the correct
+* size then we could end up shifting bits off the top of the variable when the
+* variable is at the top of a byte and crosses over into the next byte.
+*/
 struct i40e_hmc_obj_txq {
 	u16 head;
 	u8  new_context;
@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
 	u8  fd_ena;
 	u8  alt_vlan_ena;
 	u16 thead_wb;
-	u16 cpuid;
+	u8  cpuid;
 	u8  head_wb_ena;
 	u16 qlen;
 	u8  tphrdesc_ena;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 0
 #define DRV_VERSION_MINOR 4
-#define DRV_VERSION_BUILD 10
+#define DRV_VERSION_BUILD 21
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
 	     __stringify(DRV_VERSION_MINOR) "." \
 	     __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -65,7 +65,7 @@ static int i40e_veb_get_bw_info(struct i
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(i40e_pci_tbl) = {
+static const struct pci_device_id i40e_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_XL710), 0},
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_QEMU), 0},
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_A), 0},
@@ -269,7 +269,11 @@ static void i40e_service_event_schedule(
  * device is munged, not just the one netdev port, so go for the full
  * reset.
  **/
+#ifdef I40E_FCOE
+void i40e_tx_timeout(struct net_device *netdev)
+#else
 static void i40e_tx_timeout(struct net_device *netdev)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -278,7 +282,7 @@ static void i40e_tx_timeout(struct net_d
 	pf->tx_timeout_count++;
 
 	if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20)))
-		pf->tx_timeout_recovery_level = 0;
+		pf->tx_timeout_recovery_level = 1;
 	pf->tx_timeout_last_recovery = jiffies;
 	netdev_info(netdev, "tx_timeout recovery level %d\n",
 		    pf->tx_timeout_recovery_level);
@@ -304,8 +308,8 @@ static void i40e_tx_timeout(struct net_d
 		break;
 	default:
 		netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
-		set_bit(__I40E_DOWN, &vsi->state);
-		i40e_down(vsi);
+		set_bit(__I40E_DOWN_REQUESTED, &pf->state);
+		set_bit(__I40E_DOWN_REQUESTED, &vsi->state);
 		break;
 	}
 	i40e_service_event_schedule(pf);
@@ -349,9 +353,15 @@ struct rtnl_link_stats64 *i40e_get_vsi_s
  * Returns the address of the device statistics structure.
  * The statistics are actually updated from the service task.
  **/
+#ifdef I40E_FCOE
+struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
+					     struct net_device *netdev,
+					     struct rtnl_link_stats64 *stats)
+#else
 static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
 					     struct net_device *netdev,
 					     struct rtnl_link_stats64 *stats)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_ring *tx_ring, *rx_ring;
@@ -444,9 +454,21 @@ void i40e_vsi_reset_stats(struct i40e_vs
  **/
 void i40e_pf_reset_stats(struct i40e_pf *pf)
 {
+	int i;
+
 	memset(&pf->stats, 0, sizeof(pf->stats));
 	memset(&pf->stats_offsets, 0, sizeof(pf->stats_offsets));
 	pf->stat_offsets_loaded = false;
+
+	for (i = 0; i < I40E_MAX_VEB; i++) {
+		if (pf->veb[i]) {
+			memset(&pf->veb[i]->stats, 0,
+			       sizeof(pf->veb[i]->stats));
+			memset(&pf->veb[i]->stats_offsets, 0,
+			       sizeof(pf->veb[i]->stats_offsets));
+			pf->veb[i]->stat_offsets_loaded = false;
+		}
+	}
 }
 
 /**
@@ -624,6 +646,55 @@ static void i40e_update_veb_stats(struct
 	veb->stat_offsets_loaded = true;
 }
 
+#ifdef I40E_FCOE
+/**
+ * i40e_update_fcoe_stats - Update FCoE-specific ethernet statistics counters.
+ * @vsi: the VSI that is capable of doing FCoE
+ **/
+static void i40e_update_fcoe_stats(struct i40e_vsi *vsi)
+{
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_hw *hw = &pf->hw;
+	struct i40e_fcoe_stats *ofs;
+	struct i40e_fcoe_stats *fs;     /* device's eth stats */
+	int idx;
+
+	if (vsi->type != I40E_VSI_FCOE)
+		return;
+
+	idx = (pf->pf_seid - I40E_BASE_PF_SEID) + I40E_FCOE_PF_STAT_OFFSET;
+	fs = &vsi->fcoe_stats;
+	ofs = &vsi->fcoe_stats_offsets;
+
+	i40e_stat_update32(hw, I40E_GL_FCOEPRC(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->rx_fcoe_packets, &fs->rx_fcoe_packets);
+	i40e_stat_update48(hw, I40E_GL_FCOEDWRCH(idx), I40E_GL_FCOEDWRCL(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->rx_fcoe_dwords, &fs->rx_fcoe_dwords);
+	i40e_stat_update32(hw, I40E_GL_FCOERPDC(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->rx_fcoe_dropped, &fs->rx_fcoe_dropped);
+	i40e_stat_update32(hw, I40E_GL_FCOEPTC(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->tx_fcoe_packets, &fs->tx_fcoe_packets);
+	i40e_stat_update48(hw, I40E_GL_FCOEDWTCH(idx), I40E_GL_FCOEDWTCL(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->tx_fcoe_dwords, &fs->tx_fcoe_dwords);
+	i40e_stat_update32(hw, I40E_GL_FCOECRC(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->fcoe_bad_fccrc, &fs->fcoe_bad_fccrc);
+	i40e_stat_update32(hw, I40E_GL_FCOELAST(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->fcoe_last_error, &fs->fcoe_last_error);
+	i40e_stat_update32(hw, I40E_GL_FCOEDDPC(idx),
+			   vsi->fcoe_stat_offsets_loaded,
+			   &ofs->fcoe_ddp_count, &fs->fcoe_ddp_count);
+
+	vsi->fcoe_stat_offsets_loaded = true;
+}
+
+#endif
 /**
  * i40e_update_link_xoff_rx - Update XOFF received in link flow control mode
  * @pf: the corresponding PF
@@ -1052,6 +1123,9 @@ void i40e_update_stats(struct i40e_vsi *
 		i40e_update_pf_stats(pf);
 
 	i40e_update_vsi_stats(vsi);
+#ifdef I40E_FCOE
+	i40e_update_fcoe_stats(vsi);
+#endif
 }
 
 /**
@@ -1303,7 +1377,11 @@ void i40e_del_filter(struct i40e_vsi *vs
  *
  * Returns 0 on success, negative on failure
  **/
+#ifdef I40E_FCOE
+int i40e_set_mac(struct net_device *netdev, void *p)
+#else
 static int i40e_set_mac(struct net_device *netdev, void *p)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -1315,9 +1393,6 @@ static int i40e_set_mac(struct net_devic
 
 	netdev_info(netdev, "set mac address=%pM\n", addr->sa_data);
 
-	if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
-		return 0;
-
 	if (test_bit(__I40E_DOWN, &vsi->back->state) ||
 	    test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
 		return -EADDRNOTAVAIL;
@@ -1325,7 +1400,7 @@ static int i40e_set_mac(struct net_devic
 	if (vsi->type == I40E_VSI_MAIN) {
 		i40e_status ret;
 		ret = i40e_aq_mac_address_write(&vsi->back->hw,
-						I40E_AQC_WRITE_TYPE_LAA_ONLY,
+						I40E_AQC_WRITE_TYPE_LAA_WOL,
 						addr->sa_data, NULL);
 		if (ret) {
 			netdev_info(netdev,
@@ -1333,22 +1408,27 @@ static int i40e_set_mac(struct net_devic
 				    ret);
 			return -EADDRNOTAVAIL;
 		}
-
-		ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data);
 	}
 
-	/* In order to be sure to not drop any packets, add the new address
-	 * then delete the old one.
-	 */
-	f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false);
-	if (!f)
-		return -ENOMEM;
+	f = i40e_find_mac(vsi, addr->sa_data, false, true);
+	if (!f) {
+		/* In order to be sure to not drop any packets, add the
+		 * new address first then delete the old one.
+		 */
+		f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,
+				    false, false);
+		if (!f)
+			return -ENOMEM;
 
-	i40e_sync_vsi_filters(vsi);
-	i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false);
-	i40e_sync_vsi_filters(vsi);
+		i40e_sync_vsi_filters(vsi);
+		i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
+				false, false);
+		i40e_sync_vsi_filters(vsi);
+	}
 
-	ether_addr_copy(netdev->dev_addr, addr->sa_data);
+	f->is_laa = true;
+	if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
+		ether_addr_copy(netdev->dev_addr, addr->sa_data);
 
 	return 0;
 }
@@ -1362,10 +1442,17 @@ static int i40e_set_mac(struct net_devic
  *
  * Setup VSI queue mapping for enabled traffic classes.
  **/
+#ifdef I40E_FCOE
+void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
+			      struct i40e_vsi_context *ctxt,
+			      u8 enabled_tc,
+			      bool is_add)
+#else
 static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
 				     struct i40e_vsi_context *ctxt,
 				     u8 enabled_tc,
 				     bool is_add)
+#endif
 {
 	struct i40e_pf *pf = vsi->back;
 	u16 sections = 0;
@@ -1411,6 +1498,11 @@ static void i40e_vsi_setup_queue_map(str
 			case I40E_VSI_MAIN:
 				qcount = min_t(int, pf->rss_size, num_tc_qps);
 				break;
+#ifdef I40E_FCOE
+			case I40E_VSI_FCOE:
+				qcount = num_tc_qps;
+				break;
+#endif
 			case I40E_VSI_FDIR:
 			case I40E_VSI_SRIOV:
 			case I40E_VSI_VMDQ2:
@@ -1477,7 +1569,11 @@ static void i40e_vsi_setup_queue_map(str
  * i40e_set_rx_mode - NDO callback to set the netdev filters
  * @netdev: network interface device structure
  **/
+#ifdef I40E_FCOE
+void i40e_set_rx_mode(struct net_device *netdev)
+#else
 static void i40e_set_rx_mode(struct net_device *netdev)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_mac_filter *f, *ftmp;
@@ -2055,8 +2151,13 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *
  *
  * net_device_ops implementation for adding vlan ids
  **/
+#ifdef I40E_FCOE
+int i40e_vlan_rx_add_vid(struct net_device *netdev,
+			 __always_unused __be16 proto, u16 vid)
+#else
 static int i40e_vlan_rx_add_vid(struct net_device *netdev,
 				__always_unused __be16 proto, u16 vid)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -2089,8 +2190,13 @@ static int i40e_vlan_rx_add_vid(struct n
  *
  * net_device_ops implementation for removing vlan ids
  **/
+#ifdef I40E_FCOE
+int i40e_vlan_rx_kill_vid(struct net_device *netdev,
+			  __always_unused __be16 proto, u16 vid)
+#else
 static int i40e_vlan_rx_kill_vid(struct net_device *netdev,
 				 __always_unused __be16 proto, u16 vid)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -2222,6 +2328,9 @@ static int i40e_vsi_setup_rx_resources(s
 
 	for (i = 0; i < vsi->num_queue_pairs && !err; i++)
 		err = i40e_setup_rx_descriptors(vsi->rx_rings[i]);
+#ifdef I40E_FCOE
+	i40e_fcoe_setup_ddp_resources(vsi);
+#endif
 	return err;
 }
 
@@ -2241,6 +2350,9 @@ static void i40e_vsi_free_rx_resources(s
 	for (i = 0; i < vsi->num_queue_pairs; i++)
 		if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
 			i40e_free_rx_resources(vsi->rx_rings[i]);
+#ifdef I40E_FCOE
+	i40e_fcoe_free_ddp_resources(vsi);
+#endif
 }
 
 /**
@@ -2282,6 +2394,9 @@ static int i40e_configure_tx_ring(struct
 	tx_ctx.qlen = ring->count;
 	tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FD_SB_ENABLED |
 					       I40E_FLAG_FD_ATR_ENABLED));
+#ifdef I40E_FCOE
+	tx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
+#endif
 	tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP);
 	/* FDIR VSI tx ring can still use RS bit and writebacks */
 	if (vsi->type != I40E_VSI_FDIR)
@@ -2387,10 +2502,6 @@ static int i40e_configure_rx_ring(struct
 
 	rx_ctx.rxmax = min_t(u16, vsi->max_frame,
 				  (chain_len * ring->rx_buf_len));
-	rx_ctx.tphrdesc_ena = 1;
-	rx_ctx.tphwdesc_ena = 1;
-	rx_ctx.tphdata_ena = 1;
-	rx_ctx.tphhead_ena = 1;
 	if (hw->revision_id == 0)
 		rx_ctx.lrxqthresh = 0;
 	else
@@ -2398,6 +2509,9 @@ static int i40e_configure_rx_ring(struct
 	rx_ctx.crcstrip = 1;
 	rx_ctx.l2tsel = 1;
 	rx_ctx.showiv = 1;
+#ifdef I40E_FCOE
+	rx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
+#endif
 	/* set the prefena field to 1 because the manual says to */
 	rx_ctx.prefena = 1;
 
@@ -2482,6 +2596,17 @@ static int i40e_vsi_configure_rx(struct
 		break;
 	}
 
+#ifdef I40E_FCOE
+	/* setup rx buffer for FCoE */
+	if ((vsi->type == I40E_VSI_FCOE) &&
+	    (vsi->back->flags & I40E_FLAG_FCOE_ENABLED)) {
+		vsi->rx_hdr_len = 0;
+		vsi->rx_buf_len = I40E_RXBUFFER_3072;
+		vsi->max_frame = I40E_RXBUFFER_3072;
+		vsi->dtype = I40E_RX_DTYPE_NO_SPLIT;
+	}
+
+#endif /* I40E_FCOE */
 	/* round up for the chip's needs */
 	vsi->rx_hdr_len = ALIGN(vsi->rx_hdr_len,
 				(1 << I40E_RXQ_CTX_HBUFF_SHIFT));
@@ -2756,6 +2881,22 @@ void i40e_irq_dynamic_enable(struct i40e
 }
 
 /**
+ * i40e_irq_dynamic_disable - Disable default interrupt generation settings
+ * @vsi: pointer to a vsi
+ * @vector: enable a particular Hw Interrupt vector
+ **/
+void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector)
+{
+	struct i40e_pf *pf = vsi->back;
+	struct i40e_hw *hw = &pf->hw;
+	u32 val;
+
+	val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
+	wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
+	i40e_flush(hw);
+}
+
+/**
  * i40e_msix_clean_rings - MSIX mode Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a q_vector
@@ -3057,16 +3198,33 @@ static bool i40e_clean_fdir_tx_irq(struc
 		/* clear next_to_watch to prevent false hangs */
 		tx_buf->next_to_watch = NULL;
 
+		tx_desc->buffer_addr = 0;
+		tx_desc->cmd_type_offset_bsz = 0;
+		/* move past filter desc */
+		tx_buf++;
+		tx_desc++;
+		i++;
+		if (unlikely(!i)) {
+			i -= tx_ring->count;
+			tx_buf = tx_ring->tx_bi;
+			tx_desc = I40E_TX_DESC(tx_ring, 0);
+		}
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
 				 dma_unmap_addr(tx_buf, dma),
 				 dma_unmap_len(tx_buf, len),
 				 DMA_TO_DEVICE);
+		if (tx_buf->tx_flags & I40E_TX_FLAGS_FD_SB)
+			kfree(tx_buf->raw_buf);
 
+		tx_buf->raw_buf = NULL;
+		tx_buf->tx_flags = 0;
+		tx_buf->next_to_watch = NULL;
 		dma_unmap_len_set(tx_buf, len, 0);
+		tx_desc->buffer_addr = 0;
+		tx_desc->cmd_type_offset_bsz = 0;
 
-
-		/* move to the next desc and buffer to clean */
+		/* move us past the eop_desc for start of next FD desc */
 		tx_buf++;
 		tx_desc++;
 		i++;
@@ -3151,8 +3309,12 @@ static void i40e_vsi_map_rings_to_vector
 
 	/* If we don't have enough vectors for a 1-to-1 mapping, we'll have to
 	 * group them so there are multiple queues per vector.
+	 * It is also important to go through all the vectors available to be
+	 * sure that if we don't use all the vectors, that the remaining vectors
+	 * are cleared. This is especially important when decreasing the
+	 * number of queues in use.
 	 */
-	for (; v_start < q_vectors && qp_remaining; v_start++) {
+	for (; v_start < q_vectors; v_start++) {
 		struct i40e_q_vector *q_vector = vsi->q_vectors[v_start];
 
 		num_ringpairs = DIV_ROUND_UP(qp_remaining, q_vectors - v_start);
@@ -3205,7 +3367,11 @@ static int i40e_vsi_request_irq(struct i
  * This is used by netconsole to send skbs without having to re-enable
  * interrupts.  It's not called while the normal interrupt routine is executing.
  **/
+#ifdef I40E_FCOE
+void i40e_netpoll(struct net_device *netdev)
+#else
 static void i40e_netpoll(struct net_device *netdev)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -3228,6 +3394,35 @@ static void i40e_netpoll(struct net_devi
 #endif
 
 /**
+ * i40e_pf_txq_wait - Wait for a PF's Tx queue to be enabled or disabled
+ * @pf: the PF being configured
+ * @pf_q: the PF queue
+ * @enable: enable or disable state of the queue
+ *
+ * This routine will wait for the given Tx queue of the PF to reach the
+ * enabled or disabled state.
+ * Returns -ETIMEDOUT in case of failing to reach the requested state after
+ * multiple retries; else will return 0 in case of success.
+ **/
+static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
+{
+	int i;
+	u32 tx_reg;
+
+	for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) {
+		tx_reg = rd32(&pf->hw, I40E_QTX_ENA(pf_q));
+		if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
+			break;
+
+		udelay(10);
+	}
+	if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/**
  * i40e_vsi_control_tx - Start or stop a VSI's rings
  * @vsi: the VSI being configured
  * @enable: start or stop the rings
@@ -3236,7 +3431,7 @@ static int i40e_vsi_control_tx(struct i4
 {
 	struct i40e_pf *pf = vsi->back;
 	struct i40e_hw *hw = &pf->hw;
-	int i, j, pf_q;
+	int i, j, pf_q, ret = 0;
 	u32 tx_reg;
 
 	pf_q = vsi->base_queue;
@@ -3269,22 +3464,46 @@ static int i40e_vsi_control_tx(struct i4
 		wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
 
 		/* wait for the change to finish */
-		for (j = 0; j < 10; j++) {
-			tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
-			if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
-				break;
-
-			udelay(10);
-		}
-		if (j >= 10) {
-			dev_info(&pf->pdev->dev, "Tx ring %d %sable timeout\n",
-				 pf_q, (enable ? "en" : "dis"));
-			return -ETIMEDOUT;
+		ret = i40e_pf_txq_wait(pf, pf_q, enable);
+		if (ret) {
+			dev_info(&pf->pdev->dev,
+				 "%s: VSI seid %d Tx ring %d %sable timeout\n",
+				 __func__, vsi->seid, pf_q,
+				 (enable ? "en" : "dis"));
+			break;
 		}
 	}
 
 	if (hw->revision_id == 0)
 		mdelay(50);
+	return ret;
+}
+
+/**
+ * i40e_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled
+ * @pf: the PF being configured
+ * @pf_q: the PF queue
+ * @enable: enable or disable state of the queue
+ *
+ * This routine will wait for the given Rx queue of the PF to reach the
+ * enabled or disabled state.
+ * Returns -ETIMEDOUT in case of failing to reach the requested state after
+ * multiple retries; else will return 0 in case of success.
+ **/
+static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
+{
+	int i;
+	u32 rx_reg;
+
+	for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) {
+		rx_reg = rd32(&pf->hw, I40E_QRX_ENA(pf_q));
+		if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
+			break;
+
+		udelay(10);
+	}
+	if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
+		return -ETIMEDOUT;
 
 	return 0;
 }
@@ -3298,7 +3517,7 @@ static int i40e_vsi_control_rx(struct i4
 {
 	struct i40e_pf *pf = vsi->back;
 	struct i40e_hw *hw = &pf->hw;
-	int i, j, pf_q;
+	int i, j, pf_q, ret = 0;
 	u32 rx_reg;
 
 	pf_q = vsi->base_queue;
@@ -3323,22 +3542,17 @@ static int i40e_vsi_control_rx(struct i4
 		wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
 
 		/* wait for the change to finish */
-		for (j = 0; j < 10; j++) {
-			rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
-
-			if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
-				break;
-
-			udelay(10);
-		}
-		if (j >= 10) {
-			dev_info(&pf->pdev->dev, "Rx ring %d %sable timeout\n",
-				 pf_q, (enable ? "en" : "dis"));
-			return -ETIMEDOUT;
+		ret = i40e_pf_rxq_wait(pf, pf_q, enable);
+		if (ret) {
+			dev_info(&pf->pdev->dev,
+				 "%s: VSI seid %d Rx ring %d %sable timeout\n",
+				 __func__, vsi->seid, pf_q,
+				 (enable ? "en" : "dis"));
+			break;
 		}
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -4107,12 +4321,20 @@ static void i40e_dcb_reconfigure(struct
 			continue;
 
 		/* - Enable all TCs for the LAN VSI
+#ifdef I40E_FCOE
+		 * - For FCoE VSI only enable the TC configured
+		 *   as per the APP TLV
+#endif
 		 * - For all others keep them at TC0 for now
 		 */
 		if (v == pf->lan_vsi)
 			tc_map = i40e_pf_get_tc_map(pf);
 		else
 			tc_map = i40e_pf_get_default_tc(pf);
+#ifdef I40E_FCOE
+		if (pf->vsi[v]->type == I40E_VSI_FCOE)
+			tc_map = i40e_get_fcoe_tc_map(pf);
+#endif /* #ifdef I40E_FCOE */
 
 		ret = i40e_vsi_config_tc(pf->vsi[v], tc_map);
 		if (ret) {
@@ -4193,13 +4415,13 @@ static void i40e_print_link_message(stru
 
 	switch (vsi->back->hw.phy.link_info.link_speed) {
 	case I40E_LINK_SPEED_40GB:
-		strncpy(speed, "40 Gbps", SPEED_SIZE);
+		strlcpy(speed, "40 Gbps", SPEED_SIZE);
 		break;
 	case I40E_LINK_SPEED_10GB:
-		strncpy(speed, "10 Gbps", SPEED_SIZE);
+		strlcpy(speed, "10 Gbps", SPEED_SIZE);
 		break;
 	case I40E_LINK_SPEED_1GB:
-		strncpy(speed, "1000 Mbps", SPEED_SIZE);
+		strlcpy(speed, "1000 Mbps", SPEED_SIZE);
 		break;
 	default:
 		break;
@@ -4207,16 +4429,16 @@ static void i40e_print_link_message(stru
 
 	switch (vsi->back->hw.fc.current_mode) {
 	case I40E_FC_FULL:
-		strncpy(fc, "RX/TX", FC_SIZE);
+		strlcpy(fc, "RX/TX", FC_SIZE);
 		break;
 	case I40E_FC_TX_PAUSE:
-		strncpy(fc, "TX", FC_SIZE);
+		strlcpy(fc, "TX", FC_SIZE);
 		break;
 	case I40E_FC_RX_PAUSE:
-		strncpy(fc, "RX", FC_SIZE);
+		strlcpy(fc, "RX", FC_SIZE);
 		break;
 	default:
-		strncpy(fc, "None", FC_SIZE);
+		strlcpy(fc, "None", FC_SIZE);
 		break;
 	}
 
@@ -4231,8 +4453,12 @@ static void i40e_print_link_message(stru
 static int i40e_up_complete(struct i40e_vsi *vsi)
 {
 	struct i40e_pf *pf = vsi->back;
+	u8 set_fc_aq_fail = 0;
 	int err;
 
+	/* force flow control off */
+	i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
+
 	if (pf->flags & I40E_FLAG_MSIX_ENABLED)
 		i40e_vsi_configure_msix(vsi);
 	else
@@ -4335,7 +4561,11 @@ void i40e_down(struct i40e_vsi *vsi)
  * @netdev: net device to configure
  * @tc: number of traffic classes to enable
  **/
+#ifdef I40E_FCOE
+int i40e_setup_tc(struct net_device *netdev, u8 tc)
+#else
 static int i40e_setup_tc(struct net_device *netdev, u8 tc)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -4400,7 +4630,11 @@ exit:
  *
  * Returns 0 on success, negative value on failure
  **/
+#ifdef I40E_FCOE
+int i40e_open(struct net_device *netdev)
+#else
 static int i40e_open(struct net_device *netdev)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -4536,7 +4770,11 @@ static void i40e_fdir_filter_exit(struct
  *
  * Returns 0, this is not allowed to fail
  **/
+#ifdef I40E_FCOE
+int i40e_close(struct net_device *netdev)
+#else
 static int i40e_close(struct net_device *netdev)
+#endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
@@ -4640,6 +4878,23 @@ void i40e_do_reset(struct i40e_pf *pf, u
 
 		/* no further action needed, so return now */
 		return;
+	} else if (reset_flags & (1 << __I40E_DOWN_REQUESTED)) {
+		int v;
+
+		/* Find the VSI(s) that needs to be brought down */
+		dev_info(&pf->pdev->dev, "VSI down requested\n");
+		for (v = 0; v < pf->num_alloc_vsi; v++) {
+			struct i40e_vsi *vsi = pf->vsi[v];
+			if (vsi != NULL &&
+			    test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) {
+				set_bit(__I40E_DOWN, &vsi->state);
+				i40e_down(vsi);
+				clear_bit(__I40E_DOWN_REQUESTED, &vsi->state);
+			}
+		}
+
+		/* no further action needed, so return now */
+		return;
 	} else {
 		dev_info(&pf->pdev->dev,
 			 "bad reset request 0x%08x\n", reset_flags);
@@ -4845,7 +5100,20 @@ static void i40e_service_event_complete(
 }
 
 /**
- * i40e_get_current_fd_count - Get the count of FD filters programmed in the HW
+ * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
+ * @pf: board private structure
+ **/
+int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
+{
+	int val, fcnt_prog;
+
+	val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
+	fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK);
+	return fcnt_prog;
+}
+
+/**
+ * i40e_get_current_fd_count - Get the count of total FD filters programmed
  * @pf: board private structure
  **/
 int i40e_get_current_fd_count(struct i40e_pf *pf)
@@ -4857,7 +5125,6 @@ int i40e_get_current_fd_count(struct i40
 		      I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
 	return fcnt_prog;
 }
-
 /**
  * i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
  * @pf: board private structure
@@ -4872,8 +5139,8 @@ void i40e_fdir_check_and_reenable(struct
 	if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
 	    (pf->flags & I40E_FLAG_FD_SB_ENABLED))
 		return;
-	fcnt_prog = i40e_get_current_fd_count(pf);
-	fcnt_avail = i40e_get_fd_cnt_all(pf);
+	fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
+	fcnt_avail = pf->fdir_pf_filter_count;
 	if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) {
 		if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
 		    (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) {
@@ -4922,6 +5189,9 @@ static void i40e_vsi_link_event(struct i
 
 	switch (vsi->type) {
 	case I40E_VSI_MAIN:
+#ifdef I40E_FCOE
+	case I40E_VSI_FCOE:
+#endif
 		if (!vsi->netdev || !vsi->netdev_registered)
 			break;
 
@@ -5110,6 +5380,10 @@ static void i40e_reset_subtask(struct i4
 		reset_flags |= (1 << __I40E_GLOBAL_RESET_REQUESTED);
 		clear_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state);
 	}
+	if (test_bit(__I40E_DOWN_REQUESTED, &pf->state)) {
+		reset_flags |= (1 << __I40E_DOWN_REQUESTED);
+		clear_bit(__I40E_DOWN_REQUESTED, &pf->state);
+	}
 
 	/* If there's a recovery already waiting, it takes
 	 * precedence before starting a new reset sequence.
@@ -5164,7 +5438,7 @@ static void i40e_handle_link_event(struc
 	 * then see if the status changed while processing the
 	 * initial event.
 	 */
-	i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+	i40e_update_link_info(&pf->hw, true);
 	i40e_link_event(pf);
 }
 
@@ -5182,9 +5456,6 @@ static void i40e_clean_adminq_subtask(st
 	u32 oldval;
 	u32 val;
 
-	if (!test_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state))
-		return;
-
 	/* check for error indications */
 	val = rd32(&pf->hw, pf->hw.aq.arq.len);
 	oldval = val;
@@ -5228,10 +5499,9 @@ static void i40e_clean_adminq_subtask(st
 	do {
 		event.msg_size = I40E_MAX_AQ_BUF_SIZE; /* reinit each time */
 		ret = i40e_clean_arq_element(hw, &event, &pending);
-		if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
-			dev_info(&pf->pdev->dev, "No ARQ event found\n");
+		if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK)
 			break;
-		} else if (ret) {
+		else if (ret) {
 			dev_info(&pf->pdev->dev, "ARQ event error %d\n", ret);
 			break;
 		}
@@ -5463,6 +5733,20 @@ static void i40e_fdir_sb_setup(struct i4
 	struct i40e_vsi *vsi;
 	int i;
 
+	/* quick workaround for an NVM issue that leaves a critical register
+	 * uninitialized
+	 */
+	if (!rd32(&pf->hw, I40E_GLQF_HKEY(0))) {
+		static const u32 hkey[] = {
+			0xe640d33f, 0xcdfe98ab, 0x73fa7161, 0x0d7a7d36,
+			0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb,
+			0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21,
+			0x95b3a76d};
+
+		for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++)
+			wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]);
+	}
+
 	if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
 		return;
 
@@ -5512,7 +5796,7 @@ static void i40e_fdir_teardown(struct i4
  *
  * Close up the VFs and other things in prep for pf Reset.
   **/
-static int i40e_prep_for_reset(struct i40e_pf *pf)
+static void i40e_prep_for_reset(struct i40e_pf *pf)
 {
 	struct i40e_hw *hw = &pf->hw;
 	i40e_status ret = 0;
@@ -5520,7 +5804,7 @@ static int i40e_prep_for_reset(struct i4
 
 	clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
 	if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
-		return 0;
+		return;
 
 	dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");
 
@@ -5537,13 +5821,10 @@ static int i40e_prep_for_reset(struct i4
 	/* call shutdown HMC */
 	if (hw->hmc.hmc_obj) {
 		ret = i40e_shutdown_lan_hmc(hw);
-		if (ret) {
+		if (ret)
 			dev_warn(&pf->pdev->dev,
 				 "shutdown_lan_hmc failed: %d\n", ret);
-			clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
-		}
 	}
-	return ret;
 }
 
 /**
@@ -5558,7 +5839,7 @@ static void i40e_send_version(struct i40
 	dv.minor_version = DRV_VERSION_MINOR;
 	dv.build_version = DRV_VERSION_BUILD;
 	dv.subbuild_version = 0;
-	strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
+	strlcpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
 	i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
 }
 
@@ -5629,7 +5910,12 @@ static void i40e_reset_and_rebuild(struc
 		goto end_core_reset;
 	}
 #endif /* CONFIG_I40E_DCB */
+#ifdef I40E_FCOE
+	ret = i40e_init_pf_fcoe(pf);
+	if (ret)
+		dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", ret);
 
+#endif
 	/* do basic switch setup */
 	ret = i40e_setup_pf_switch(pf, reinit);
 	if (ret)
@@ -5679,7 +5965,7 @@ static void i40e_reset_and_rebuild(struc
 	}
 
 	if (pf->vsi[pf->lan_vsi]->uplink_seid == pf->mac_seid) {
-		dev_info(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
+		dev_dbg(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
 		/* no VEB, so rebuild only the Main VSI */
 		ret = i40e_add_vsi(pf->vsi[pf->lan_vsi]);
 		if (ret) {
@@ -5717,11 +6003,8 @@ end_core_reset:
  **/
 static void i40e_handle_reset_warning(struct i40e_pf *pf)
 {
-	i40e_status ret;
-
-	ret = i40e_prep_for_reset(pf);
-	if (!ret)
-		i40e_reset_and_rebuild(pf, false);
+	i40e_prep_for_reset(pf);
+	i40e_reset_and_rebuild(pf, false);
 }
 
 /**
@@ -5734,6 +6017,7 @@ static void i40e_handle_mdd_event(struct
 {
 	struct i40e_hw *hw = &pf->hw;
 	bool mdd_detected = false;
+	bool pf_mdd_detected = false;
 	struct i40e_vf *vf;
 	u32 reg;
 	int i;
@@ -5744,26 +6028,28 @@ static void i40e_handle_mdd_event(struct
 	/* find what triggered the MDD event */
 	reg = rd32(hw, I40E_GL_MDET_TX);
 	if (reg & I40E_GL_MDET_TX_VALID_MASK) {
-		u8 func = (reg & I40E_GL_MDET_TX_FUNCTION_MASK)
-				>> I40E_GL_MDET_TX_FUNCTION_SHIFT;
-		u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT)
-				>> I40E_GL_MDET_TX_EVENT_SHIFT;
-		u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK)
-				>> I40E_GL_MDET_TX_QUEUE_SHIFT;
+		u8 pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >>
+				I40E_GL_MDET_TX_PF_NUM_SHIFT;
+		u8 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
+				I40E_GL_MDET_TX_VF_NUM_SHIFT;
+		u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) >>
+				I40E_GL_MDET_TX_EVENT_SHIFT;
+		u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
+				I40E_GL_MDET_TX_QUEUE_SHIFT;
 		dev_info(&pf->pdev->dev,
-			 "Malicious Driver Detection event 0x%02x on TX queue %d of function 0x%02x\n",
-			 event, queue, func);
+			 "Malicious Driver Detection event 0x%02x on TX queue %d pf number 0x%02x vf number 0x%02x\n",
+			 event, queue, pf_num, vf_num);
 		wr32(hw, I40E_GL_MDET_TX, 0xffffffff);
 		mdd_detected = true;
 	}
 	reg = rd32(hw, I40E_GL_MDET_RX);
 	if (reg & I40E_GL_MDET_RX_VALID_MASK) {
-		u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK)
-				>> I40E_GL_MDET_RX_FUNCTION_SHIFT;
-		u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT)
-				>> I40E_GL_MDET_RX_EVENT_SHIFT;
-		u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK)
-				>> I40E_GL_MDET_RX_QUEUE_SHIFT;
+		u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >>
+				I40E_GL_MDET_RX_FUNCTION_SHIFT;
+		u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT) >>
+				I40E_GL_MDET_RX_EVENT_SHIFT;
+		u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
+				I40E_GL_MDET_RX_QUEUE_SHIFT;
 		dev_info(&pf->pdev->dev,
 			 "Malicious Driver Detection event 0x%02x on RX queue %d of function 0x%02x\n",
 			 event, queue, func);
@@ -5771,6 +6057,30 @@ static void i40e_handle_mdd_event(struct
 		mdd_detected = true;
 	}
 
+	if (mdd_detected) {
+		reg = rd32(hw, I40E_PF_MDET_TX);
+		if (reg & I40E_PF_MDET_TX_VALID_MASK) {
+			wr32(hw, I40E_PF_MDET_TX, 0xFFFF);
+			dev_info(&pf->pdev->dev,
+				 "MDD TX event is for this function 0x%08x, requesting PF reset.\n",
+				 reg);
+			pf_mdd_detected = true;
+		}
+		reg = rd32(hw, I40E_PF_MDET_RX);
+		if (reg & I40E_PF_MDET_RX_VALID_MASK) {
+			wr32(hw, I40E_PF_MDET_RX, 0xFFFF);
+			dev_info(&pf->pdev->dev,
+				 "MDD RX event is for this function 0x%08x, requesting PF reset.\n",
+				 reg);
+			pf_mdd_detected = true;
+		}
+		/* Queue belongs to the PF, initiate a reset */
+		if (pf_mdd_detected) {
+			set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+			i40e_service_event_schedule(pf);
+		}
+	}
+
 	/* see if one of the VFs needs its hand slapped */
 	for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) {
 		vf = &(pf->vf[i]);
@@ -5860,6 +6170,12 @@ static void i40e_service_task(struct wor
 					  service_task);
 	unsigned long start_time = jiffies;
 
+	/* 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;
+	}
+
 	i40e_reset_subtask(pf);
 	i40e_handle_mdd_event(pf);
 	i40e_vc_process_vflr_event(pf);
@@ -5938,6 +6254,15 @@ static int i40e_set_num_rings_in_vsi(str
 				      I40E_REQ_DESCRIPTOR_MULTIPLE);
 		break;
 
+#ifdef I40E_FCOE
+	case I40E_VSI_FCOE:
+		vsi->alloc_queue_pairs = pf->num_fcoe_qps;
+		vsi->num_desc = ALIGN(I40E_DEFAULT_NUM_DESCRIPTORS,
+				      I40E_REQ_DESCRIPTOR_MULTIPLE);
+		vsi->num_q_vectors = pf->num_fcoe_msix;
+		break;
+
+#endif /* I40E_FCOE */
 	default:
 		WARN_ON(1);
 		return -ENODATA;
@@ -5968,7 +6293,7 @@ static int i40e_vsi_alloc_arrays(struct
 
 	if (alloc_qvectors) {
 		/* allocate memory for q_vector pointers */
-		size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
+		size = sizeof(struct i40e_q_vector *) * vsi->num_q_vectors;
 		vsi->q_vectors = kzalloc(size, GFP_KERNEL);
 		if (!vsi->q_vectors) {
 			ret = -ENOMEM;
@@ -6249,6 +6574,9 @@ static int i40e_init_msix(struct i40e_pf
 	 *		is governed by number of cpus in the system.
 	 *	- assumes symmetric Tx/Rx pairing
 	 *   - The number of VMDq pairs
+#ifdef I40E_FCOE
+	 *   - The number of FCOE qps.
+#endif
 	 * Once we count this up, try the request.
 	 *
 	 * If we can't get what we want, we'll simplify to nearly nothing
@@ -6261,6 +6589,13 @@ static int i40e_init_msix(struct i40e_pf
 	if (pf->flags & I40E_FLAG_FD_SB_ENABLED)
 		v_budget++;
 
+#ifdef I40E_FCOE
+	if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+		pf->num_fcoe_msix = pf->num_fcoe_qps;
+		v_budget += pf->num_fcoe_msix;
+	}
+
+#endif
 	/* Scale down if necessary, and the rings will share vectors */
 	v_budget = min_t(int, v_budget, hw->func_caps.num_msix_vectors);
 
@@ -6279,6 +6614,10 @@ static int i40e_init_msix(struct i40e_pf
 		 * of these features based on the policy and at the end disable
 		 * the features that did not get any vectors.
 		 */
+#ifdef I40E_FCOE
+		pf->num_fcoe_qps = 0;
+		pf->num_fcoe_msix = 0;
+#endif
 		pf->num_vmdq_msix = 0;
 	}
 
@@ -6309,9 +6648,24 @@ static int i40e_init_msix(struct i40e_pf
 			pf->num_lan_msix = 1;
 			break;
 		case 3:
+#ifdef I40E_FCOE
+			/* give one vector to FCoE */
+			if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+				pf->num_lan_msix = 1;
+				pf->num_fcoe_msix = 1;
+			}
+#else
 			pf->num_lan_msix = 2;
+#endif
 			break;
 		default:
+#ifdef I40E_FCOE
+			/* give one vector to FCoE */
+			if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+				pf->num_fcoe_msix = 1;
+				vec--;
+			}
+#endif
 			pf->num_lan_msix = min_t(int, (vec / 2),
 						 pf->num_lan_qps);
 			pf->num_vmdq_vsis = min_t(int, (vec - pf->num_lan_msix),
@@ -6325,6 +6679,13 @@ static int i40e_init_msix(struct i40e_pf
 		dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n");
 		pf->flags &= ~I40E_FLAG_VMDQ_ENABLED;
 	}
+#ifdef I40E_FCOE
+
+	if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) {
+		dev_info(&pf->pdev->dev, "FCOE disabled, not enough MSI-X vectors\n");
+		pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+	}
+#endif
 	return err;
 }
 
@@ -6408,6 +6769,9 @@ static void i40e_init_interrupt_scheme(s
 		err = i40e_init_msix(pf);
 		if (err) {
 			pf->flags &= ~(I40E_FLAG_MSIX_ENABLED	|
+#ifdef I40E_FCOE
+				       I40E_FLAG_FCOE_ENABLED	|
+#endif
 				       I40E_FLAG_RSS_ENABLED	|
 				       I40E_FLAG_DCB_CAPABLE	|
 				       I40E_FLAG_SRIOV_ENABLED	|
@@ -6492,6 +6856,7 @@ static int i40e_config_rss(struct i40e_p
 	u32 lut = 0;
 	int i, j;
 	u64 hena;
+	u32 reg_val;
 
 	/* Fill out hash function seed */
 	for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
@@ -6504,8 +6869,19 @@ static int i40e_config_rss(struct i40e_p
 	wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
 	wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
 
+	/* Check capability and Set table size and register per hw expectation*/
+	reg_val = rd32(hw, I40E_PFQF_CTL_0);
+	if (hw->func_caps.rss_table_size == 512) {
+		reg_val |= I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+		pf->rss_table_size = 512;
+	} else {
+		pf->rss_table_size = 128;
+		reg_val &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+	}
+	wr32(hw, I40E_PFQF_CTL_0, reg_val);
+
 	/* Populate the LUT with max no. of queues in round robin fashion */
-	for (i = 0, j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) {
+	for (i = 0, j = 0; i < pf->rss_table_size; i++, j++) {
 
 		/* The assumption is that lan qp count will be the highest
 		 * qp count for any PF VSI that needs RSS.
@@ -6592,13 +6968,12 @@ static int i40e_sw_init(struct i40e_pf *
 	 * maximum might end up larger than the available queues
 	 */
 	pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width;
+	pf->rss_size = 1;
 	pf->rss_size_max = min_t(int, pf->rss_size_max,
 				 pf->hw.func_caps.num_tx_qp);
 	if (pf->hw.func_caps.rss) {
 		pf->flags |= I40E_FLAG_RSS_ENABLED;
 		pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus());
-	} else {
-		pf->rss_size = 1;
 	}
 
 	/* MFP mode enabled */
@@ -6634,6 +7009,12 @@ static int i40e_sw_init(struct i40e_pf *
 		pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ;
 	}
 
+#ifdef I40E_FCOE
+	err = i40e_init_pf_fcoe(pf);
+	if (err)
+		dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", err);
+
+#endif /* I40E_FCOE */
 #ifdef CONFIG_PCI_IOV
 	if (pf->hw.func_caps.num_vfs) {
 		pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF;
@@ -6670,6 +7051,8 @@ static int i40e_sw_init(struct i40e_pf *
 	pf->irq_pile->num_entries = pf->hw.func_caps.num_msix_vectors;
 	pf->irq_pile->search_hint = 0;
 
+	pf->tx_timeout_recovery_level = 1;
+
 	mutex_init(&pf->switch_mutex);
 
 sw_init_done:
@@ -6702,9 +7085,11 @@ bool i40e_set_ntuple(struct i40e_pf *pf,
 			i40e_fdir_filter_exit(pf);
 		}
 		pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
-		/* if ATR was disabled it can be re-enabled. */
-		if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
-			pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
+		pf->auto_disable_flags &= ~I40E_FLAG_FD_SB_ENABLED;
+		/* if ATR was auto disabled it can be re-enabled. */
+		if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+		    (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED))
+			pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
 	}
 	return need_reset;
 }
@@ -6833,6 +7218,22 @@ static void i40e_del_vxlan_port(struct n
 }
 
 #endif
+static int i40e_get_phys_port_id(struct net_device *netdev,
+				 struct netdev_phys_port_id *ppid)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_hw *hw = &pf->hw;
+
+	if (!(pf->flags & I40E_FLAG_PORT_ID_VALID))
+		return -EOPNOTSUPP;
+
+	ppid->id_len = min_t(int, sizeof(hw->mac.port_addr), sizeof(ppid->id));
+	memcpy(ppid->id, hw->mac.port_addr, ppid->id_len);
+
+	return 0;
+}
+
 #ifdef HAVE_FDB_OPS
 #ifdef USE_CONST_DEV_UC_CHAR
 static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
@@ -6910,13 +7311,14 @@ static int i40e_ndo_fdb_del(struct ndmsg
 static int i40e_ndo_fdb_dump(struct sk_buff *skb,
 			     struct netlink_callback *cb,
 			     struct net_device *dev,
+			     struct net_device *filter_dev,
 			     int idx)
 {
 	struct i40e_netdev_priv *np = netdev_priv(dev);
 	struct i40e_pf *pf = np->vsi->back;
 
 	if (pf->flags & I40E_FLAG_SRIOV_ENABLED)
-		idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+		idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx);
 
 	return idx;
 }
@@ -6940,6 +7342,10 @@ static const struct net_device_ops i40e_
 	.ndo_poll_controller	= i40e_netpoll,
 #endif
 	.ndo_setup_tc		= i40e_setup_tc,
+#ifdef I40E_FCOE
+	.ndo_fcoe_enable	= i40e_fcoe_enable,
+	.ndo_fcoe_disable	= i40e_fcoe_disable,
+#endif
 	.ndo_set_features	= i40e_set_features,
 	.ndo_set_vf_mac		= i40e_ndo_set_vf_mac,
 	.ndo_set_vf_vlan	= i40e_ndo_set_vf_port_vlan,
@@ -6951,6 +7357,7 @@ static const struct net_device_ops i40e_
 	.ndo_add_vxlan_port	= i40e_add_vxlan_port,
 	.ndo_del_vxlan_port	= i40e_del_vxlan_port,
 #endif
+	.ndo_get_phys_port_id	= i40e_get_phys_port_id,
 #ifdef HAVE_FDB_OPS
 	.ndo_fdb_add		= i40e_ndo_fdb_add,
 #ifndef USE_DEFAULT_FDB_DEL_DUMP
@@ -7047,6 +7454,9 @@ static int i40e_config_netdev(struct i40
 	netdev->netdev_ops = &i40e_netdev_ops;
 	netdev->watchdog_timeo = 5 * HZ;
 	i40e_set_ethtool_ops(netdev);
+#ifdef I40E_FCOE
+	i40e_fcoe_config_netdev(netdev, vsi);
+#endif
 
 	return 0;
 }
@@ -7166,7 +7576,6 @@ static int i40e_add_vsi(struct i40e_vsi
 		 * should be set to zero by default.
 		 */
 		ctxt.info.switch_id = 0;
-		ctxt.info.switch_id |= cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB);
 		ctxt.info.switch_id |= cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
 
 		/* Setup the VSI tx/rx queue map for TC0 only for now */
@@ -7200,6 +7609,16 @@ static int i40e_add_vsi(struct i40e_vsi
 		i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, true);
 		break;
 
+#ifdef I40E_FCOE
+	case I40E_VSI_FCOE:
+		ret = i40e_fcoe_vsi_init(vsi, &ctxt);
+		if (ret) {
+			dev_info(&pf->pdev->dev, "failed to initialize FCoE VSI\n");
+			return ret;
+		}
+		break;
+
+#endif /* I40E_FCOE */
 	default:
 		return -ENODEV;
 	}
@@ -7223,6 +7642,12 @@ static int i40e_add_vsi(struct i40e_vsi
 	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
 		f->changed = true;
 		f_count++;
+
+		if (f->is_laa && vsi->type == I40E_VSI_MAIN) {
+			i40e_aq_mac_address_write(&vsi->back->hw,
+						  I40E_AQC_WRITE_TYPE_LAA_WOL,
+						  f->macaddr, NULL);
+		}
 	}
 	if (f_count) {
 		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -7552,6 +7977,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i
 	/* setup the netdev if needed */
 	case I40E_VSI_MAIN:
 	case I40E_VSI_VMDQ2:
+	case I40E_VSI_FCOE:
 		ret = i40e_config_netdev(vsi);
 		if (ret)
 			goto err_netdev;
@@ -8090,7 +8516,6 @@ int i40e_fetch_switch_configuration(stru
  **/
 static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
 {
-	u32 rxfc = 0, txfc = 0, rxfc_reg;
 	int ret;
 
 	/* find out what's out there already */
@@ -8150,68 +8575,13 @@ static int i40e_setup_pf_switch(struct i
 		i40e_config_rss(pf);
 
 	/* fill in link information and enable LSE reporting */
-	i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+	i40e_update_link_info(&pf->hw, true);
 	i40e_link_event(pf);
 
 	/* Initialize user-specific link properties */
 	pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
 				  I40E_AQ_AN_COMPLETED) ? true : false);
-	/* requested_mode is set in probe or by ethtool */
-	if (!pf->fc_autoneg_status)
-		goto no_autoneg;
-
-	if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) &&
-	    (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX))
-		pf->hw.fc.current_mode = I40E_FC_FULL;
-	else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
-		pf->hw.fc.current_mode = I40E_FC_TX_PAUSE;
-	else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
-		pf->hw.fc.current_mode = I40E_FC_RX_PAUSE;
-	else
-		pf->hw.fc.current_mode = I40E_FC_NONE;
 
-	/* sync the flow control settings with the auto-neg values */
-	switch (pf->hw.fc.current_mode) {
-	case I40E_FC_FULL:
-		txfc = 1;
-		rxfc = 1;
-		break;
-	case I40E_FC_TX_PAUSE:
-		txfc = 1;
-		rxfc = 0;
-		break;
-	case I40E_FC_RX_PAUSE:
-		txfc = 0;
-		rxfc = 1;
-		break;
-	case I40E_FC_NONE:
-	case I40E_FC_DEFAULT:
-		txfc = 0;
-		rxfc = 0;
-		break;
-	case I40E_FC_PFC:
-		/* TBD */
-		break;
-	/* no default case, we have to handle all possibilities here */
-	}
-
-	wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
-
-	rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
-		   ~I40E_PRTDCB_MFLCN_RFCE_MASK;
-	rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
-
-	wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg);
-
-	goto fc_complete;
-
-no_autoneg:
-	/* disable L2 flow control, user can turn it on if they wish */
-	wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0);
-	wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
-					 ~I40E_PRTDCB_MFLCN_RFCE_MASK);
-
-fc_complete:
 	i40e_ptp_init(pf);
 
 	return ret;
@@ -8226,6 +8596,9 @@ static void i40e_determine_queue_usage(s
 	int queues_left;
 
 	pf->num_lan_qps = 0;
+#ifdef I40E_FCOE
+	pf->num_fcoe_qps = 0;
+#endif
 
 	/* Find the max queues to be put into basic use.  We'll always be
 	 * using TC0, whether or not DCB is running, and TC0 will get the
@@ -8241,6 +8614,9 @@ static void i40e_determine_queue_usage(s
 
 		/* make sure all the fancies are disabled */
 		pf->flags &= ~(I40E_FLAG_RSS_ENABLED	|
+#ifdef I40E_FCOE
+			       I40E_FLAG_FCOE_ENABLED	|
+#endif
 			       I40E_FLAG_FD_SB_ENABLED	|
 			       I40E_FLAG_FD_ATR_ENABLED	|
 			       I40E_FLAG_DCB_CAPABLE	|
@@ -8255,6 +8631,9 @@ static void i40e_determine_queue_usage(s
 		queues_left -= pf->num_lan_qps;
 
 		pf->flags &= ~(I40E_FLAG_RSS_ENABLED	|
+#ifdef I40E_FCOE
+			       I40E_FLAG_FCOE_ENABLED	|
+#endif
 			       I40E_FLAG_FD_SB_ENABLED	|
 			       I40E_FLAG_FD_ATR_ENABLED	|
 			       I40E_FLAG_DCB_ENABLED	|
@@ -8270,6 +8649,22 @@ static void i40e_determine_queue_usage(s
 		queues_left -= pf->num_lan_qps;
 	}
 
+#ifdef I40E_FCOE
+	if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+		if (I40E_DEFAULT_FCOE <= queues_left) {
+			pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
+		} else if (I40E_MINIMUM_FCOE <= queues_left) {
+			pf->num_fcoe_qps = I40E_MINIMUM_FCOE;
+		} else {
+			pf->num_fcoe_qps = 0;
+			pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+			dev_info(&pf->pdev->dev, "not enough queues for FCoE. FCoE feature will be disabled\n");
+		}
+
+		queues_left -= pf->num_fcoe_qps;
+	}
+
+#endif
 	if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
 		if (queues_left > 1) {
 			queues_left -= 1; /* save 1 queue for FD */
@@ -8294,6 +8689,9 @@ static void i40e_determine_queue_usage(s
 	}
 
 	pf->queues_left = queues_left;
+#ifdef I40E_FCOE
+	dev_info(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps);
+#endif
 }
 
 /**
@@ -8360,6 +8758,10 @@ static void i40e_print_features(struct i
 		buf += sprintf(buf, "DCB ");
 	if (pf->flags & I40E_FLAG_PTP)
 		buf += sprintf(buf, "PTP ");
+#ifdef I40E_FCOE
+	if (pf->flags & I40E_FLAG_FCOE_ENABLED)
+		buf += sprintf(buf, "FCOE ");
+#endif
 
 	BUG_ON(buf > (string + INFO_STRING_LEN));
 	dev_info(&pf->pdev->dev, "%s\n", string);
@@ -8460,6 +8862,7 @@ static int i40e_probe(struct pci_dev *pd
 	}
 
 	/* Reset here to make sure all is clean and to define PF 'n' */
+	i40e_clear_hw(hw);
 	err = i40e_pf_reset(hw);
 	if (err) {
 		dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err);
@@ -8489,12 +8892,20 @@ static int i40e_probe(struct pci_dev *pd
 	dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
 	if (err) {
 		dev_info(&pdev->dev,
-			 "init_adminq failed: %d expecting API %02x.%02x\n",
-			 err,
-			 I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
+			 "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
 		goto err_pf_reset;
 	}
 
+	if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+	    hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
+		dev_info(&pdev->dev,
+			 "The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
+	else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
+		 hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1))
+		dev_info(&pdev->dev,
+			 "The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
+
+
 	i40e_verify_eeprom(pf);
 
 	/* Rev 0 hardware was never productized */
@@ -8535,6 +8946,21 @@ static int i40e_probe(struct pci_dev *pd
 	}
 	dev_info(&pdev->dev, "MAC address: %pM\n", hw->mac.addr);
 	ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
+	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
+	if (is_valid_ether_addr(hw->mac.port_addr))
+		pf->flags |= I40E_FLAG_PORT_ID_VALID;
+#ifdef I40E_FCOE
+	err = i40e_get_san_mac_addr(hw, hw->mac.san_addr);
+	if (err)
+		dev_info(&pdev->dev,
+			 "(non-fatal) SAN MAC retrieval failed: %d\n", err);
+	if (!is_valid_ether_addr(hw->mac.san_addr)) {
+		dev_warn(&pdev->dev, "invalid SAN MAC address %pM, falling back to LAN MAC\n",
+			 hw->mac.san_addr);
+		ether_addr_copy(hw->mac.san_addr, hw->mac.addr);
+	}
+	dev_info(&pf->pdev->dev, "SAN MAC: %pM\n", hw->mac.san_addr);
+#endif /* I40E_FCOE */
 
 	pci_set_drvdata(pdev, pf);
 	pci_save_state(pdev);
@@ -8651,6 +9077,11 @@ static int i40e_probe(struct pci_dev *pd
 	mod_timer(&pf->service_timer,
 		  round_jiffies(jiffies + pf->service_timer_period));
 
+#ifdef I40E_FCOE
+	/* create FCoE interface */
+	i40e_fcoe_vsi_setup(pf);
+
+#endif
 	/* Get the negotiated link width and speed from PCI config space */
 	pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status);
 
@@ -8722,7 +9153,6 @@ static void i40e_remove(struct pci_dev *
 {
 	struct i40e_pf *pf = pci_get_drvdata(pdev);
 	i40e_status ret_code;
-	u32 reg;
 	int i;
 
 	i40e_dbg_pf_exit(pf);
@@ -8800,11 +9230,6 @@ static void i40e_remove(struct pci_dev *
 	kfree(pf->irq_pile);
 	kfree(pf->vsi);
 
-	/* force a PF reset to clean anything leftover */
-	reg = rd32(&pf->hw, I40E_PFGEN_CTRL);
-	wr32(&pf->hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK));
-	i40e_flush(&pf->hw);
-
 	iounmap(pf->hw.hw_addr);
 	kfree(pf);
 	pci_release_selected_regions(pdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2014-09-28 17:29:07.000000000 -0400
@@ -241,6 +241,46 @@ i40e_status i40e_read_nvm_buffer(struct
 }
 
 /**
+ * i40e_write_nvm_aq - Writes Shadow RAM.
+ * @hw: pointer to the HW structure.
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: offset in words from module start
+ * @words: number of words to write
+ * @data: buffer with words to write to the Shadow RAM
+ * @last_command: tells the AdminQ that this is the last command
+ *
+ * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ **/
+static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
+				     u32 offset, u16 words, void *data,
+				     bool last_command)
+{
+	i40e_status ret_code = I40E_ERR_NVM;
+
+	/* Here we are checking the SR limit only for the flat memory model.
+	 * We cannot do it for the module-based model, as we did not acquire
+	 * the NVM resource yet (we cannot get the module pointer value).
+	 * Firmware will check the module-based model.
+	 */
+	if ((offset + words) > hw->nvm.sr_size)
+		hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n");
+	else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
+		/* We can write only up to 4KB (one sector), in one AQ write */
+		hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n");
+	else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
+		 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
+		/* A single write cannot spread over two sectors */
+		hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n");
+	else
+		ret_code = i40e_aq_update_nvm(hw, module_pointer,
+					      2 * offset,  /*bytes*/
+					      2 * words,   /*bytes*/
+					      data, last_command, NULL);
+
+	return ret_code;
+}
+
+/**
  * i40e_calc_nvm_checksum - Calculates and returns the checksum
  * @hw: pointer to hardware structure
  * @checksum: pointer to the checksum
@@ -310,6 +350,27 @@ i40e_calc_nvm_checksum_exit:
 }
 
 /**
+ * i40e_update_nvm_checksum - Updates the NVM checksum
+ * @hw: pointer to hardware structure
+ *
+ * NVM ownership must be acquired before calling this function and released
+ * on ARQ completion event reception by caller.
+ * This function will commit SR to NVM.
+ **/
+i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
+{
+	i40e_status ret_code = 0;
+	u16 checksum;
+
+	ret_code = i40e_calc_nvm_checksum(hw, &checksum);
+	if (!ret_code)
+		ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
+					     1, &checksum, true);
+
+	return ret_code;
+}
+
+/**
  * i40e_validate_nvm_checksum - Validate EEPROM checksum
  * @hw: pointer to hardware structure
  * @checksum: calculated checksum
@@ -324,13 +385,9 @@ i40e_status i40e_validate_nvm_checksum(s
 	u16 checksum_sr = 0;
 	u16 checksum_local = 0;
 
-	ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-	if (ret_code)
-		goto i40e_validate_nvm_checksum_exit;
-
 	ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
 	if (ret_code)
-		goto i40e_validate_nvm_checksum_free;
+		goto i40e_validate_nvm_checksum_exit;
 
 	/* Do not use i40e_read_nvm_word() because we do not want to take
 	 * the synchronization semaphores twice here.
@@ -347,9 +404,456 @@ i40e_status i40e_validate_nvm_checksum(s
 	if (checksum)
 		*checksum = checksum_local;
 
-i40e_validate_nvm_checksum_free:
-	i40e_release_nvm(hw);
-
 i40e_validate_nvm_checksum_exit:
 	return ret_code;
 }
+
+static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
+					  struct i40e_nvm_access *cmd,
+					  u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
+					     struct i40e_nvm_access *cmd,
+					     u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
+					     struct i40e_nvm_access *cmd,
+					     u8 *bytes, int *errno);
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+						struct i40e_nvm_access *cmd,
+						int *errno);
+static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+					 struct i40e_nvm_access *cmd,
+					 int *errno);
+static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+					 struct i40e_nvm_access *cmd,
+					 u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+					struct i40e_nvm_access *cmd,
+					u8 *bytes, int *errno);
+static inline u8 i40e_nvmupd_get_module(u32 val)
+{
+	return (u8)(val & I40E_NVM_MOD_PNT_MASK);
+}
+static inline u8 i40e_nvmupd_get_transaction(u32 val)
+{
+	return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
+}
+
+/**
+ * i40e_nvmupd_command - Process an NVM update command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * Dispatches command depending on what update state is current
+ **/
+i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
+				struct i40e_nvm_access *cmd,
+				u8 *bytes, int *errno)
+{
+	i40e_status status;
+
+	/* assume success */
+	*errno = 0;
+
+	switch (hw->nvmupd_state) {
+	case I40E_NVMUPD_STATE_INIT:
+		status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
+		break;
+
+	case I40E_NVMUPD_STATE_READING:
+		status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
+		break;
+
+	case I40E_NVMUPD_STATE_WRITING:
+		status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
+		break;
+
+	default:
+		/* invalid state, should never happen */
+		status = I40E_NOT_SUPPORTED;
+		*errno = -ESRCH;
+		break;
+	}
+	return status;
+}
+
+/**
+ * i40e_nvmupd_state_init - Handle NVM update state Init
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * Process legitimate commands of the Init state and conditionally set next
+ * state. Reject all other commands.
+ **/
+static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
+					  struct i40e_nvm_access *cmd,
+					  u8 *bytes, int *errno)
+{
+	i40e_status status = 0;
+	enum i40e_nvmupd_cmd upd_cmd;
+
+	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+	switch (upd_cmd) {
+	case I40E_NVMUPD_READ_SA:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+			i40e_release_nvm(hw);
+		}
+		break;
+
+	case I40E_NVMUPD_READ_SNT:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+			hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
+		}
+		break;
+
+	case I40E_NVMUPD_WRITE_ERA:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
+			if (status)
+				i40e_release_nvm(hw);
+			else
+				hw->aq.nvm_release_on_done = true;
+		}
+		break;
+
+	case I40E_NVMUPD_WRITE_SA:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+			if (status)
+				i40e_release_nvm(hw);
+			else
+				hw->aq.nvm_release_on_done = true;
+		}
+		break;
+
+	case I40E_NVMUPD_WRITE_SNT:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+			hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+		}
+		break;
+
+	case I40E_NVMUPD_CSUM_SA:
+		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+		if (status) {
+			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+		} else {
+			status = i40e_update_nvm_checksum(hw);
+			if (status) {
+				*errno = hw->aq.asq_last_status ?
+				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+				   -EIO;
+				i40e_release_nvm(hw);
+			} else {
+				hw->aq.nvm_release_on_done = true;
+			}
+		}
+		break;
+
+	default:
+		status = I40E_ERR_NVM;
+		*errno = -ESRCH;
+		break;
+	}
+	return status;
+}
+
+/**
+ * i40e_nvmupd_state_reading - Handle NVM update state Reading
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * NVM ownership is already held.  Process legitimate commands and set any
+ * change in state; reject all other commands.
+ **/
+static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
+					     struct i40e_nvm_access *cmd,
+					     u8 *bytes, int *errno)
+{
+	i40e_status status;
+	enum i40e_nvmupd_cmd upd_cmd;
+
+	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+	switch (upd_cmd) {
+	case I40E_NVMUPD_READ_SA:
+	case I40E_NVMUPD_READ_CON:
+		status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+		break;
+
+	case I40E_NVMUPD_READ_LCB:
+		status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+		i40e_release_nvm(hw);
+		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+		break;
+
+	default:
+		status = I40E_NOT_SUPPORTED;
+		*errno = -ESRCH;
+		break;
+	}
+	return status;
+}
+
+/**
+ * i40e_nvmupd_state_writing - Handle NVM update state Writing
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * NVM ownership is already held.  Process legitimate commands and set any
+ * change in state; reject all other commands
+ **/
+static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
+					     struct i40e_nvm_access *cmd,
+					     u8 *bytes, int *errno)
+{
+	i40e_status status;
+	enum i40e_nvmupd_cmd upd_cmd;
+
+	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+	switch (upd_cmd) {
+	case I40E_NVMUPD_WRITE_CON:
+		status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+		break;
+
+	case I40E_NVMUPD_WRITE_LCB:
+		status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+		if (!status) {
+			hw->aq.nvm_release_on_done = true;
+			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+		}
+		break;
+
+	case I40E_NVMUPD_CSUM_CON:
+		status = i40e_update_nvm_checksum(hw);
+		if (status)
+			*errno = hw->aq.asq_last_status ?
+				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+				   -EIO;
+		break;
+
+	case I40E_NVMUPD_CSUM_LCB:
+		status = i40e_update_nvm_checksum(hw);
+		if (status) {
+			*errno = hw->aq.asq_last_status ?
+				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+				   -EIO;
+		} else {
+			hw->aq.nvm_release_on_done = true;
+			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+		}
+		break;
+
+	default:
+		status = I40E_NOT_SUPPORTED;
+		*errno = -ESRCH;
+		break;
+	}
+	return status;
+}
+
+/**
+ * i40e_nvmupd_validate_command - Validate given command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @errno: pointer to return error code
+ *
+ * Return one of the valid command types or I40E_NVMUPD_INVALID
+ **/
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+						 struct i40e_nvm_access *cmd,
+						 int *errno)
+{
+	enum i40e_nvmupd_cmd upd_cmd;
+	u8 transaction, module;
+
+	/* anything that doesn't match a recognized case is an error */
+	upd_cmd = I40E_NVMUPD_INVALID;
+
+	transaction = i40e_nvmupd_get_transaction(cmd->config);
+	module = i40e_nvmupd_get_module(cmd->config);
+
+	/* limits on data size */
+	if ((cmd->data_size < 1) ||
+	    (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
+		hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n",
+		       cmd->data_size);
+		*errno = -EFAULT;
+		return I40E_NVMUPD_INVALID;
+	}
+
+	switch (cmd->command) {
+	case I40E_NVM_READ:
+		switch (transaction) {
+		case I40E_NVM_CON:
+			upd_cmd = I40E_NVMUPD_READ_CON;
+			break;
+		case I40E_NVM_SNT:
+			upd_cmd = I40E_NVMUPD_READ_SNT;
+			break;
+		case I40E_NVM_LCB:
+			upd_cmd = I40E_NVMUPD_READ_LCB;
+			break;
+		case I40E_NVM_SA:
+			upd_cmd = I40E_NVMUPD_READ_SA;
+			break;
+		}
+		break;
+
+	case I40E_NVM_WRITE:
+		switch (transaction) {
+		case I40E_NVM_CON:
+			upd_cmd = I40E_NVMUPD_WRITE_CON;
+			break;
+		case I40E_NVM_SNT:
+			upd_cmd = I40E_NVMUPD_WRITE_SNT;
+			break;
+		case I40E_NVM_LCB:
+			upd_cmd = I40E_NVMUPD_WRITE_LCB;
+			break;
+		case I40E_NVM_SA:
+			upd_cmd = I40E_NVMUPD_WRITE_SA;
+			break;
+		case I40E_NVM_ERA:
+			upd_cmd = I40E_NVMUPD_WRITE_ERA;
+			break;
+		case I40E_NVM_CSUM:
+			upd_cmd = I40E_NVMUPD_CSUM_CON;
+			break;
+		case (I40E_NVM_CSUM|I40E_NVM_SA):
+			upd_cmd = I40E_NVMUPD_CSUM_SA;
+			break;
+		case (I40E_NVM_CSUM|I40E_NVM_LCB):
+			upd_cmd = I40E_NVMUPD_CSUM_LCB;
+			break;
+		}
+		break;
+	}
+
+	if (upd_cmd == I40E_NVMUPD_INVALID) {
+		*errno = -EFAULT;
+		hw_dbg(hw,
+		       "i40e_nvmupd_validate_command returns %d  errno: %d\n",
+		       upd_cmd, *errno);
+	}
+	return upd_cmd;
+}
+
+/**
+ * i40e_nvmupd_nvm_read - Read NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+					struct i40e_nvm_access *cmd,
+					u8 *bytes, int *errno)
+{
+	i40e_status status;
+	u8 module, transaction;
+	bool last;
+
+	transaction = i40e_nvmupd_get_transaction(cmd->config);
+	module = i40e_nvmupd_get_module(cmd->config);
+	last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
+	hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 0x%x\n",
+	       module, cmd->offset, cmd->data_size);
+
+	status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+				  bytes, last, NULL);
+	hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status);
+	if (status)
+		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+	return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_erase - Erase an NVM module
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @errno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+					 struct i40e_nvm_access *cmd,
+					 int *errno)
+{
+	i40e_status status = 0;
+	u8 module, transaction;
+	bool last;
+
+	transaction = i40e_nvmupd_get_transaction(cmd->config);
+	module = i40e_nvmupd_get_module(cmd->config);
+	last = (transaction & I40E_NVM_LCB);
+	hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x  len 0x%x\n",
+	       module, cmd->offset, cmd->data_size);
+	status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+				   last, NULL);
+	hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status);
+	if (status)
+		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+	return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_write - Write NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+					 struct i40e_nvm_access *cmd,
+					 u8 *bytes, int *errno)
+{
+	i40e_status status = 0;
+	u8 module, transaction;
+	bool last;
+
+	transaction = i40e_nvmupd_get_transaction(cmd->config);
+	module = i40e_nvmupd_get_module(cmd->config);
+	last = (transaction & I40E_NVM_LCB);
+	hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
+	       module, cmd->offset, cmd->data_size);
+	status = i40e_aq_update_nvm(hw, module, cmd->offset,
+				    (u16)cmd->data_size, bytes, last, NULL);
+	hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status);
+	if (status)
+		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+	return status;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_osdep.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_osdep.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_osdep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_osdep.h	2014-09-28 17:29:07.000000000 -0400
@@ -78,4 +78,7 @@ do {
 } while (0)
 
 typedef enum i40e_status_code i40e_status;
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#define I40E_FCOE
+#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
 #endif /* _I40E_OSDEP_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2014-09-28 17:29:07.000000000 -0400
@@ -70,17 +70,31 @@ i40e_status i40e_aq_get_firmware_version
 				u16 *fw_major_version, u16 *fw_minor_version,
 				u16 *api_major_version, u16 *api_minor_version,
 				struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
+					u32 reg_addr, u64 reg_val,
+					struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
 				struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
 				struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
+			bool qualified_modules, bool report_init,
+			struct i40e_aq_get_phy_abilities_resp *abilities,
+			struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
+				struct i40e_aq_set_phy_config *config,
+				struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
+				  bool atomic_reset);
 i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
 				struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
-				struct i40e_asq_cmd_details *cmd_details);
+					bool enable_link,
+					struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
 				bool enable_lse, struct i40e_link_status *link,
 				struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse);
 i40e_status i40e_aq_set_local_advt_reg(struct i40e_hw *hw,
 				u64 advt_reg,
 				struct i40e_asq_cmd_details *cmd_details);
@@ -139,6 +153,9 @@ i40e_status i40e_aq_read_nvm(struct i40e
 				u32 offset, u16 length, void *data,
 				bool last_command,
 				struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
+			      u32 offset, u16 length, bool last_command,
+			      struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
 				void *buff, u16 buff_size, u16 *data_size,
 				enum i40e_admin_queue_opc list_type_opc,
@@ -216,12 +233,16 @@ i40e_status i40e_aq_query_switch_comp_bw
 /* i40e_common */
 i40e_status i40e_init_shared_code(struct i40e_hw *hw);
 i40e_status i40e_pf_reset(struct i40e_hw *hw);
+void i40e_clear_hw(struct i40e_hw *hw);
 void i40e_clear_pxe_mode(struct i40e_hw *hw);
 bool i40e_get_link_status(struct i40e_hw *hw);
-i40e_status i40e_get_mac_addr(struct i40e_hw *hw,
-						u8 *mac_addr);
+i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
+i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
 i40e_status i40e_validate_mac_addr(u8 *mac_addr);
 void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable);
+#ifdef I40E_FCOE
+i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
+#endif
 /* prototype for functions used for NVM access */
 i40e_status i40e_init_nvm(struct i40e_hw *hw);
 i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
@@ -233,8 +254,12 @@ i40e_status i40e_read_nvm_word(struct i4
 					 u16 *data);
 i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
 					   u16 *words, u16 *data);
+i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
 						 u16 *checksum);
+i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
+				struct i40e_nvm_access *cmd,
+				u8 *bytes, int *);
 void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
 
 extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,6 @@
  ******************************************************************************/
 
 #include "i40e.h"
-#include <linux/export.h>
 #include <linux/ptp_classify.h>
 
 /* The XL710 timesync is very much like Intel's 82599 design when it comes to
@@ -216,7 +215,7 @@ static int i40e_ptp_settime(struct ptp_c
 }
 
 /**
- * i40e_ptp_enable - Enable/disable ancillary features of the PHC subsystem
+ * i40e_ptp_feature_enable - Enable/disable ancillary features of the PHC subsystem
  * @ptp: The PTP clock structure
  * @rq: The requested feature to change
  * @on: Enable/disable flag
@@ -224,8 +223,8 @@ static int i40e_ptp_settime(struct ptp_c
  * The XL710 does not support any of the ancillary features of the PHC
  * subsystem, so this function may just return.
  **/
-static int i40e_ptp_enable(struct ptp_clock_info *ptp,
-			   struct ptp_clock_request *rq, int on)
+static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
+				   struct ptp_clock_request *rq, int on)
 {
 	return -EOPNOTSUPP;
 }
@@ -248,7 +247,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *v
 	u32 prttsyn_stat;
 	int n;
 
-	if (pf->flags & I40E_FLAG_PTP)
+	if (!(pf->flags & I40E_FLAG_PTP))
 		return;
 
 	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
@@ -315,6 +314,7 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf
 	skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
 	dev_kfree_skb_any(pf->ptp_tx_skb);
 	pf->ptp_tx_skb = NULL;
+	clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
 }
 
 /**
@@ -423,28 +423,23 @@ int i40e_ptp_get_ts_config(struct i40e_p
 }
 
 /**
- * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
+ * i40e_ptp_set_timestamp_mode - setup hardware for requested timestamp mode
  * @pf: Board private structure
- * @ifreq: ioctl data
+ * @config: hwtstamp settings requested or saved
  *
- * Respond to the user filter requests and make the appropriate hardware
- * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
- * logic, so keep track in software of whether to indicate these timestamps
- * or not.
+ * Control hardware registers to enter the specific mode requested by the
+ * user. Also used during reset path to ensure that timestamp settings are
+ * maintained.
  *
- * It is permissible to "upgrade" the user request to a broader filter, as long
- * as the user receives the timestamps they care about and the user is notified
- * the filter has been broadened.
+ * Note: modifies config in place, and may update the requested mode to be
+ * more broad if the specific filter is not directly supported.
  **/
-int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
+				       struct hwtstamp_config *config)
 {
 	struct i40e_hw *hw = &pf->hw;
-	struct hwtstamp_config *config = &pf->tstamp_config;
 	u32 pf_id, tsyntype, regval;
 
-	if (copy_from_user(config, ifr->ifr_data, sizeof(*config)))
-		return -EFAULT;
-
 	/* Reserved for future extensions. */
 	if (config->flags)
 		return -EINVAL;
@@ -452,8 +447,12 @@ int i40e_ptp_set_ts_config(struct i40e_p
 	/* Confirm that 1588 is supported on this PF. */
 	pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
 		I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
-	if (hw->pf_id != pf_id)
-		return -EINVAL;
+	if (hw->pf_id != pf_id) {
+		dev_err(&pf->pdev->dev,
+			"PF %d attempted to control timestamp mode on port %d, which is owned by PF %d\n",
+			hw->pf_id, hw->port, pf_id);
+		return -EPERM;
+	}
 
 	switch (config->tx_type) {
 	case HWTSTAMP_TX_OFF:
@@ -535,23 +534,59 @@ int i40e_ptp_set_ts_config(struct i40e_p
 		wr32(hw, I40E_PRTTSYN_CTL1, regval);
 	}
 
-	return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+	return 0;
+}
+
+/**
+ * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
+ * @pf: Board private structure
+ * @ifreq: ioctl data
+ *
+ * Respond to the user filter requests and make the appropriate hardware
+ * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
+ * logic, so keep track in software of whether to indicate these timestamps
+ * or not.
+ *
+ * It is permissible to "upgrade" the user request to a broader filter, as long
+ * as the user receives the timestamps they care about and the user is notified
+ * the filter has been broadened.
+ **/
+int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+{
+	struct hwtstamp_config config;
+	int err;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	err = i40e_ptp_set_timestamp_mode(pf, &config);
+	if (err)
+		return err;
+
+	/* save these settings for future reference */
+	pf->tstamp_config = config;
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 		-EFAULT : 0;
 }
 
 /**
- * i40e_ptp_init - Initialize the 1588 support and register the PHC
+ * i40e_ptp_create_clock - Create PTP clock device for userspace
  * @pf: Board private structure
  *
- * This function registers the device clock as a PHC. If it is successful, it
- * starts the clock in the hardware.
+ * This function creates a new PTP clock device. It only creates one if we
+ * don't already have one, so it is safe to call. Will return error if it
+ * can't create one, but success if we already have a device. Should be used
+ * by i40e_ptp_init to create clock initially, and prevent global resets from
+ * creating new clock devices.
  **/
-void i40e_ptp_init(struct i40e_pf *pf)
+static long i40e_ptp_create_clock(struct i40e_pf *pf)
 {
-	struct i40e_hw *hw = &pf->hw;
-	struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
+	/* no need to create a clock device if we already have one */
+	if (!IS_ERR_OR_NULL(pf->ptp_clock))
+		return 0;
 
-	strncpy(pf->ptp_caps.name, "i40e", sizeof(pf->ptp_caps.name));
+	strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
 	pf->ptp_caps.owner = THIS_MODULE;
 	pf->ptp_caps.max_adj = 999999999;
 	pf->ptp_caps.n_ext_ts = 0;
@@ -560,11 +595,46 @@ void i40e_ptp_init(struct i40e_pf *pf)
 	pf->ptp_caps.adjtime = i40e_ptp_adjtime;
 	pf->ptp_caps.gettime = i40e_ptp_gettime;
 	pf->ptp_caps.settime = i40e_ptp_settime;
-	pf->ptp_caps.enable = i40e_ptp_enable;
+	pf->ptp_caps.enable = i40e_ptp_feature_enable;
 
 	/* Attempt to register the clock before enabling the hardware. */
 	pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
 	if (IS_ERR(pf->ptp_clock)) {
+		return PTR_ERR(pf->ptp_clock);
+	}
+
+	/* clear the hwtstamp settings here during clock create, instead of
+	 * during regular init, so that we can maintain settings across a
+	 * reset or suspend.
+	 */
+	pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+	pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+
+	return 0;
+}
+
+/**
+ * i40e_ptp_init - Initialize the 1588 support after device probe or reset
+ * @pf: Board private structure
+ *
+ * This function sets device up for 1588 support. The first time it is run, it
+ * will create a PHC clock device. It does not create a clock device if one
+ * already exists. It also reconfigures the device after a reset.
+ **/
+void i40e_ptp_init(struct i40e_pf *pf)
+{
+	struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
+	struct i40e_hw *hw = &pf->hw;
+	long err;
+
+	/* 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);
+
+	/* ensure we have a clock device */
+	err = i40e_ptp_create_clock(pf);
+	if (err) {
 		pf->ptp_clock = NULL;
 		dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
 			__func__);
@@ -572,8 +642,6 @@ void i40e_ptp_init(struct i40e_pf *pf)
 		struct timespec ts;
 		u32 regval;
 
-		spin_lock_init(&pf->tmreg_lock);
-
 		dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
 			 netdev->name);
 		pf->flags |= I40E_FLAG_PTP;
@@ -589,8 +657,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
 		/* Set the increment value per clock tick. */
 		i40e_ptp_set_increment(pf);
 
-		/* reset the tstamp_config */
-		memset(&pf->tstamp_config, 0, sizeof(pf->tstamp_config));
+		/* reset timestamping mode */
+		i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
 
 		/* Set the clock value. */
 		ts = ktime_to_timespec(ktime_get_real());
@@ -614,6 +682,7 @@ void i40e_ptp_stop(struct i40e_pf *pf)
 	if (pf->ptp_tx_skb) {
 		dev_kfree_skb_any(pf->ptp_tx_skb);
 		pf->ptp_tx_skb = NULL;
+		clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
 	}
 
 	if (pf->ptp_clock) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_register.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_register.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_register.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_register.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,4648 +27,3343 @@
 #ifndef _I40E_REGISTER_H_
 #define _I40E_REGISTER_H_
 
-#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
-#define I40E_GL_GP_FUSE_MAX_INDEX 28
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
-#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
-
-#define I40E_PF_ARQBAH 0x00080180
+#define I40E_GL_ARQBAH 0x000801C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_GL_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAH_ARQBAH_SHIFT)
+#define I40E_GL_ARQBAL 0x000800C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_GL_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAL_ARQBAL_SHIFT)
+#define I40E_GL_ARQH 0x000803C0 /* Reset: EMPR */
+#define I40E_GL_ARQH_ARQH_SHIFT 0
+#define I40E_GL_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_GL_ARQH_ARQH_SHIFT)
+#define I40E_GL_ARQT 0x000804C0 /* Reset: EMPR */
+#define I40E_GL_ARQT_ARQT_SHIFT 0
+#define I40E_GL_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_GL_ARQT_ARQT_SHIFT)
+#define I40E_GL_ATQBAH 0x00080140 /* Reset: EMPR */
+#define I40E_GL_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_GL_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAH_ATQBAH_SHIFT)
+#define I40E_GL_ATQBAL 0x00080040 /* Reset: EMPR */
+#define I40E_GL_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_GL_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAL_ATQBAL_SHIFT)
+#define I40E_GL_ATQH 0x00080340 /* Reset: EMPR */
+#define I40E_GL_ATQH_ATQH_SHIFT 0
+#define I40E_GL_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_GL_ATQH_ATQH_SHIFT)
+#define I40E_GL_ATQLEN 0x00080240 /* Reset: EMPR */
+#define I40E_GL_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_GL_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_GL_ATQLEN_ATQLEN_SHIFT)
+#define I40E_GL_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_GL_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQVFE_SHIFT)
+#define I40E_GL_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_GL_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_GL_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_GL_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_GL_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_GL_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_GL_ATQT 0x00080440 /* Reset: EMPR */
+#define I40E_GL_ATQT_ATQT_SHIFT 0
+#define I40E_GL_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_GL_ATQT_ATQT_SHIFT)
+#define I40E_PF_ARQBAH 0x00080180 /* Reset: EMPR */
 #define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_PF_ARQBAL 0x00080080
+#define I40E_PF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_PF_ARQBAL 0x00080080 /* Reset: EMPR */
 #define I40E_PF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_PF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_PF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_PF_ARQH 0x00080380
+#define I40E_PF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_PF_ARQH 0x00080380 /* Reset: EMPR */
 #define I40E_PF_ARQH_ARQH_SHIFT 0
-#define I40E_PF_ARQH_ARQH_MASK (0x3FF << I40E_PF_ARQH_ARQH_SHIFT)
-#define I40E_PF_ARQLEN 0x00080280
+#define I40E_PF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_PF_ARQH_ARQH_SHIFT)
+#define I40E_PF_ARQLEN 0x00080280 /* Reset: EMPR */
 #define I40E_PF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_PF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_PF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_PF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ARQLEN_ARQLEN_SHIFT)
 #define I40E_PF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_PF_ARQLEN_ARQVFE_MASK (0x1 << I40E_PF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_PF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQVFE_SHIFT)
 #define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_PF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_PF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_PF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQOVFL_SHIFT)
 #define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_PF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_PF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT)
 #define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_PF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_PF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_PF_ARQT 0x00080480
+#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */
 #define I40E_PF_ARQT_ARQT_SHIFT 0
-#define I40E_PF_ARQT_ARQT_MASK (0x3FF << I40E_PF_ARQT_ARQT_SHIFT)
-#define I40E_PF_ATQBAH 0x00080100
+#define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT)
+#define I40E_PF_ATQBAH 0x00080100 /* Reset: EMPR */
 #define I40E_PF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_PF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_PF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_PF_ATQBAL 0x00080000
+#define I40E_PF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_PF_ATQBAL 0x00080000 /* Reset: EMPR */
 #define I40E_PF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_PF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_PF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_PF_ATQH 0x00080300
+#define I40E_PF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_PF_ATQH 0x00080300 /* Reset: EMPR */
 #define I40E_PF_ATQH_ATQH_SHIFT 0
-#define I40E_PF_ATQH_ATQH_MASK (0x3FF << I40E_PF_ATQH_ATQH_SHIFT)
-#define I40E_PF_ATQLEN 0x00080200
+#define I40E_PF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_PF_ATQH_ATQH_SHIFT)
+#define I40E_PF_ATQLEN 0x00080200 /* Reset: EMPR */
 #define I40E_PF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_PF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_PF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_PF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ATQLEN_ATQLEN_SHIFT)
 #define I40E_PF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_PF_ATQLEN_ATQVFE_MASK (0x1 << I40E_PF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_PF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQVFE_SHIFT)
 #define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_PF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_PF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_PF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQOVFL_SHIFT)
 #define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_PF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_PF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT)
 #define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_PF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_PF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_PF_ATQT 0x00080400
+#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */
 #define I40E_PF_ATQT_ATQT_SHIFT 0
-#define I40E_PF_ATQT_ATQT_MASK (0x3FF << I40E_PF_ATQT_ATQT_SHIFT)
-#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT)
+#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQBAH_MAX_INDEX 127
 #define I40E_VF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQBAL_MAX_INDEX 127
 #define I40E_VF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQH_MAX_INDEX 127
 #define I40E_VF_ARQH_ARQH_SHIFT 0
-#define I40E_VF_ARQH_ARQH_MASK (0x3FF << I40E_VF_ARQH_ARQH_SHIFT)
-#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH_ARQH_SHIFT)
+#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQLEN_MAX_INDEX 127
 #define I40E_VF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN_ARQLEN_SHIFT)
 #define I40E_VF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQVFE_SHIFT)
 #define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQOVFL_SHIFT)
 #define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT)
 #define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQT_MAX_INDEX 127
 #define I40E_VF_ARQT_ARQT_SHIFT 0
-#define I40E_VF_ARQT_ARQT_MASK (0x3FF << I40E_VF_ARQT_ARQT_SHIFT)
-#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT_ARQT_SHIFT)
+#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQBAH_MAX_INDEX 127
 #define I40E_VF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQBAL_MAX_INDEX 127
 #define I40E_VF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQH_MAX_INDEX 127
 #define I40E_VF_ATQH_ATQH_SHIFT 0
-#define I40E_VF_ATQH_ATQH_MASK (0x3FF << I40E_VF_ATQH_ATQH_SHIFT)
-#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH_ATQH_SHIFT)
+#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQLEN_MAX_INDEX 127
 #define I40E_VF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN_ATQLEN_SHIFT)
 #define I40E_VF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQVFE_SHIFT)
 #define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQOVFL_SHIFT)
 #define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT)
 #define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQT_MAX_INDEX 127
 #define I40E_VF_ATQT_ATQT_SHIFT 0
-#define I40E_VF_ATQT_ATQT_MASK (0x3FF << I40E_VF_ATQT_ATQT_SHIFT)
-#define I40E_PRT_L2TAGSEN 0x001C0B20
+#define I40E_VF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT_ATQT_SHIFT)
+#define I40E_PRT_L2TAGSEN 0x001C0B20 /* Reset: CORER */
 #define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0
-#define I40E_PRT_L2TAGSEN_ENABLE_MASK (0xFF << I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
-#define I40E_PFCM_LAN_ERRDATA 0x0010C080
+#define I40E_PRT_L2TAGSEN_ENABLE_MASK I40E_MASK(0xFF, I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA 0x0010C080 /* Reset: PFR */
 #define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
 #define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
 #define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK (0xFFF << I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_LAN_ERRINFO 0x0010C000
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO 0x0010C000 /* Reset: PFR */
 #define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_PFCM_LANCTXCTL 0x0010C300
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LANCTXCTL 0x0010C300 /* Reset: CORER */
 #define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0
-#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK (0xFFF << I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
 #define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12
-#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK (0x7 << I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK I40E_MASK(0x7, I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
 #define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15
-#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK (0x3 << I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
 #define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17
-#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK (0x3 << I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
-#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */
+#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
+#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PFCM_LANCTXDATA_MAX_INDEX 3
 #define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0
-#define I40E_PFCM_LANCTXDATA_DATA_MASK (0xFFFFFFFF << I40E_PFCM_LANCTXDATA_DATA_SHIFT)
-#define I40E_PFCM_LANCTXSTAT 0x0010C380
+#define I40E_PFCM_LANCTXDATA_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFCM_LANCTXDATA_DATA_SHIFT)
+#define I40E_PFCM_LANCTXSTAT 0x0010C380 /* Reset: CORER */
 #define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0
-#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
 #define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1
-#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
-#define I40E_PFCM_PE_ERRDATA 0x00138D00
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_PE_ERRINFO 0x00138C80
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127
 #define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127
 #define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
-#define I40E_GLDCB_GENC 0x00083044
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
+#define I40E_GLDCB_GENC 0x00083044 /* Reset: CORER */
 #define I40E_GLDCB_GENC_PCIRTT_SHIFT 0
-#define I40E_GLDCB_GENC_PCIRTT_MASK (0xFFFF << I40E_GLDCB_GENC_PCIRTT_SHIFT)
-#define I40E_GLDCB_RUPTI 0x00122618
+#define I40E_GLDCB_GENC_PCIRTT_MASK I40E_MASK(0xFFFF, I40E_GLDCB_GENC_PCIRTT_SHIFT)
+#define I40E_GLDCB_RUPTI 0x00122618 /* Reset: CORER */
 #define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0
-#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK (0xFFFFFFFF << I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
-#define I40E_PRTDCB_FCCFG 0x001E4640
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
+#define I40E_PRTDCB_FCCFG 0x001E4640 /* Reset: GLOBR */
 #define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3
-#define I40E_PRTDCB_FCCFG_TFCE_MASK (0x3 << I40E_PRTDCB_FCCFG_TFCE_SHIFT)
-#define I40E_PRTDCB_FCRTV 0x001E4600
+#define I40E_PRTDCB_FCCFG_TFCE_MASK I40E_MASK(0x3, I40E_PRTDCB_FCCFG_TFCE_SHIFT)
+#define I40E_PRTDCB_FCRTV 0x001E4600 /* Reset: GLOBR */
 #define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0
-#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK (0xFFFF << I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
-#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
+#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: GLOBR */
 #define I40E_PRTDCB_FCTTVN_MAX_INDEX 3
 #define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0
-#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
+#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
 #define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16
-#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
-#define I40E_PRTDCB_GENC 0x00083000
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
+#define I40E_PRTDCB_GENC 0x00083000 /* Reset: CORER */
 #define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0
-#define I40E_PRTDCB_GENC_RESERVED_1_MASK (0x3 << I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
+#define I40E_PRTDCB_GENC_RESERVED_1_MASK I40E_MASK(0x3, I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
 #define I40E_PRTDCB_GENC_NUMTC_SHIFT 2
-#define I40E_PRTDCB_GENC_NUMTC_MASK (0xF << I40E_PRTDCB_GENC_NUMTC_SHIFT)
+#define I40E_PRTDCB_GENC_NUMTC_MASK I40E_MASK(0xF, I40E_PRTDCB_GENC_NUMTC_SHIFT)
 #define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6
-#define I40E_PRTDCB_GENC_FCOEUP_MASK (0x7 << I40E_PRTDCB_GENC_FCOEUP_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_MASK I40E_MASK(0x7, I40E_PRTDCB_GENC_FCOEUP_SHIFT)
 #define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9
-#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK (0x1 << I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK I40E_MASK(0x1, I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
 #define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16
-#define I40E_PRTDCB_GENC_PFCLDA_MASK (0xFFFF << I40E_PRTDCB_GENC_PFCLDA_SHIFT)
-#define I40E_PRTDCB_GENS 0x00083020
+#define I40E_PRTDCB_GENC_PFCLDA_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_GENC_PFCLDA_SHIFT)
+#define I40E_PRTDCB_GENS 0x00083020 /* Reset: CORER */
 #define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0
-#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK (0x7 << I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
-#define I40E_PRTDCB_MFLCN 0x001E2400
+#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK I40E_MASK(0x7, I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
+#define I40E_PRTDCB_MFLCN 0x001E2400 /* Reset: GLOBR */
 #define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0
-#define I40E_PRTDCB_MFLCN_PMCF_MASK (0x1 << I40E_PRTDCB_MFLCN_PMCF_SHIFT)
+#define I40E_PRTDCB_MFLCN_PMCF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_PMCF_SHIFT)
 #define I40E_PRTDCB_MFLCN_DPF_SHIFT 1
-#define I40E_PRTDCB_MFLCN_DPF_MASK (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT)
+#define I40E_PRTDCB_MFLCN_DPF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_DPF_SHIFT)
 #define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2
-#define I40E_PRTDCB_MFLCN_RPFCM_MASK (0x1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCM_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
 #define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3
-#define I40E_PRTDCB_MFLCN_RFCE_MASK (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT)
+#define I40E_PRTDCB_MFLCN_RFCE_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RFCE_SHIFT)
 #define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4
-#define I40E_PRTDCB_MFLCN_RPFCE_MASK (0xFF << I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
-#define I40E_PRTDCB_RETSC 0x001223E0
+#define I40E_PRTDCB_MFLCN_RPFCE_MASK I40E_MASK(0xFF, I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
+#define I40E_PRTDCB_RETSC 0x001223E0 /* Reset: CORER */
 #define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0
-#define I40E_PRTDCB_RETSC_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
 #define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1
-#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
 #define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2
-#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK (0xF << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK I40E_MASK(0xF, I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
 #define I40E_PRTDCB_RETSC_LLTC_SHIFT 8
-#define I40E_PRTDCB_RETSC_LLTC_MASK (0xFF << I40E_PRTDCB_RETSC_LLTC_SHIFT)
-#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_RETSC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_RETSC_LLTC_SHIFT)
+#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTDCB_RETSTCC_MAX_INDEX 7
 #define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0
-#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK (0x7F << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK I40E_MASK(0x7F, I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
 #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30
-#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK (0x1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
 #define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31
-#define I40E_PRTDCB_RETSTCC_ETSTC_MASK (0x1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
-#define I40E_PRTDCB_RPPMC 0x001223A0
+#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
+#define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */
 #define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0
-#define I40E_PRTDCB_RPPMC_LANRPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
 #define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8
-#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
 #define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16
-#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK (0xFF << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
-#define I40E_PRTDCB_RUP 0x001C0B00
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
+#define I40E_PRTDCB_RUP 0x001C0B00 /* Reset: CORER */
 #define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0
-#define I40E_PRTDCB_RUP_NOVLANUP_MASK (0x7 << I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
-#define I40E_PRTDCB_RUP2TC 0x001C09A0
+#define I40E_PRTDCB_RUP_NOVLANUP_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
+#define I40E_PRTDCB_RUP2TC 0x001C09A0 /* Reset: CORER */
 #define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0
-#define I40E_PRTDCB_RUP2TC_UP0TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP0TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3
-#define I40E_PRTDCB_RUP2TC_UP1TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP1TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6
-#define I40E_PRTDCB_RUP2TC_UP2TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP2TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9
-#define I40E_PRTDCB_RUP2TC_UP3TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP3TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12
-#define I40E_PRTDCB_RUP2TC_UP4TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP4TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15
-#define I40E_PRTDCB_RUP2TC_UP5TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP5TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18
-#define I40E_PRTDCB_RUP2TC_UP6TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP6TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21
-#define I40E_PRTDCB_RUP2TC_UP7TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
-#define I40E_PRTDCB_TC2PFC 0x001C0980
+#define I40E_PRTDCB_RUP2TC_UP7TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
+#define I40E_PRTDCB_TC2PFC 0x001C0980 /* Reset: CORER */
 #define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0
-#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK (0xFF << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
-#define I40E_PRTDCB_TCPMC 0x000A21A0
+#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
+#define I40E_PRTDCB_TCMSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
+#define I40E_PRTDCB_TCMSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TCMSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TCMSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCMSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TCPMC 0x000A21A0 /* Reset: CORER */
 #define I40E_PRTDCB_TCPMC_CPM_SHIFT 0
-#define I40E_PRTDCB_TCPMC_CPM_MASK (0x1FFF << I40E_PRTDCB_TCPMC_CPM_SHIFT)
+#define I40E_PRTDCB_TCPMC_CPM_MASK I40E_MASK(0x1FFF, I40E_PRTDCB_TCPMC_CPM_SHIFT)
 #define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13
-#define I40E_PRTDCB_TCPMC_LLTC_MASK (0xFF << I40E_PRTDCB_TCPMC_LLTC_SHIFT)
+#define I40E_PRTDCB_TCPMC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TCPMC_LLTC_SHIFT)
 #define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTDCB_TCWSTC_MAX_INDEX 7
 #define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TCWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TDPMC 0x000A0180
+#define I40E_PRTDCB_TCWSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TDPMC 0x000A0180 /* Reset: CORER */
 #define I40E_PRTDCB_TDPMC_DPM_SHIFT 0
-#define I40E_PRTDCB_TDPMC_DPM_MASK (0xFF << I40E_PRTDCB_TDPMC_DPM_SHIFT)
+#define I40E_PRTDCB_TDPMC_DPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_TDPMC_DPM_SHIFT)
 #define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TDPUC 0x00044100
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT 0
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_MASK (0xFFFF << I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT)
-#define I40E_PRTDCB_TETSC_TCB 0x000AE060
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB 0x000AE060 /* Reset: CORER */
 #define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
 #define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
-#define I40E_PRTDCB_TETSC_TPB 0x00098060
+#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB 0x00098060 /* Reset: CORER */
 #define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
 #define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
-#define I40E_PRTDCB_TFCS 0x001E4560
+#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
+#define I40E_PRTDCB_TFCS 0x001E4560 /* Reset: GLOBR */
 #define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0
-#define I40E_PRTDCB_TFCS_TXOFF_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8
-#define I40E_PRTDCB_TFCS_TXOFF0_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF0_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9
-#define I40E_PRTDCB_TFCS_TXOFF1_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF1_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10
-#define I40E_PRTDCB_TFCS_TXOFF2_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF2_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11
-#define I40E_PRTDCB_TFCS_TXOFF3_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF3_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12
-#define I40E_PRTDCB_TFCS_TXOFF4_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF4_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13
-#define I40E_PRTDCB_TFCS_TXOFF5_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF5_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14
-#define I40E_PRTDCB_TFCS_TXOFF6_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF6_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15
-#define I40E_PRTDCB_TFCS_TXOFF7_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
-#define I40E_PRTDCB_TFWSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */
-#define I40E_PRTDCB_TFWSTC_MAX_INDEX 7
-#define I40E_PRTDCB_TFWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TFWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TFWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TFCS_TXOFF7_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
+#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */ /* Reset: GLOBR */
 #define I40E_PRTDCB_TPFCTS_MAX_INDEX 7
 #define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0
-#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK (0x3FFF << I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
-#define I40E_GLFCOE_RCTL 0x00269B94
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
+#define I40E_GLFCOE_RCTL 0x00269B94 /* Reset: CORER */
 #define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0
-#define I40E_GLFCOE_RCTL_FCOEVER_MASK (0xF << I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
+#define I40E_GLFCOE_RCTL_FCOEVER_MASK I40E_MASK(0xF, I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
 #define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4
-#define I40E_GLFCOE_RCTL_SAVBAD_MASK (0x1 << I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
+#define I40E_GLFCOE_RCTL_SAVBAD_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
 #define I40E_GLFCOE_RCTL_ICRC_SHIFT 5
-#define I40E_GLFCOE_RCTL_ICRC_MASK (0x1 << I40E_GLFCOE_RCTL_ICRC_SHIFT)
+#define I40E_GLFCOE_RCTL_ICRC_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_ICRC_SHIFT)
 #define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16
-#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK (0x3FFF << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
-#define I40E_GL_FWSTS 0x00083048
+#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK I40E_MASK(0x3FFF, I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
+#define I40E_GL_FWSTS 0x00083048 /* Reset: POR */
 #define I40E_GL_FWSTS_FWS0B_SHIFT 0
-#define I40E_GL_FWSTS_FWS0B_MASK (0xFF << I40E_GL_FWSTS_FWS0B_SHIFT)
+#define I40E_GL_FWSTS_FWS0B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS0B_SHIFT)
 #define I40E_GL_FWSTS_FWRI_SHIFT 9
-#define I40E_GL_FWSTS_FWRI_MASK (0x1 << I40E_GL_FWSTS_FWRI_SHIFT)
+#define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT)
 #define I40E_GL_FWSTS_FWS1B_SHIFT 16
-#define I40E_GL_FWSTS_FWS1B_MASK (0xFF << I40E_GL_FWSTS_FWS1B_SHIFT)
-#define I40E_GLGEN_CLKSTAT 0x000B8184
+#define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT)
+#define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */
 #define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0
-#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK (0x1 << I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
+#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
 #define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4
-#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK (0x3 << I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK I40E_MASK(0x3, I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8
-#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12
-#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16
-#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20
-#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
-#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */ /* Reset: POR */
 #define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29
 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK (0x3 << I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4
-#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5
-#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6
-#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7
-#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK (0x7 << I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK I40E_MASK(0x7, I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10
-#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11
-#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12
-#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK (0xF << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17
-#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK (0x3 << I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19
-#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20
-#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK (0x3F << I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
-#define I40E_GLGEN_GPIO_SET 0x00088184
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK I40E_MASK(0x3F, I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
+#define I40E_GLGEN_GPIO_SET 0x00088184 /* Reset: POR */
 #define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0
-#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK (0x1F << I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
 #define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5
-#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK (0x1 << I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
 #define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6
-#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK (0x1 << I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
-#define I40E_GLGEN_GPIO_STAT 0x0008817C
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
+#define I40E_GLGEN_GPIO_STAT 0x0008817C /* Reset: POR */
 #define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0
-#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
-#define I40E_GLGEN_GPIO_TRANSIT 0x00088180
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
+#define I40E_GLGEN_GPIO_TRANSIT 0x00088180 /* Reset: POR */
 #define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0
-#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
-#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
+#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_I2CCMD_MAX_INDEX 3
 #define I40E_GLGEN_I2CCMD_DATA_SHIFT 0
-#define I40E_GLGEN_I2CCMD_DATA_MASK (0xFFFF << I40E_GLGEN_I2CCMD_DATA_SHIFT)
+#define I40E_GLGEN_I2CCMD_DATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_I2CCMD_DATA_SHIFT)
 #define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16
-#define I40E_GLGEN_I2CCMD_REGADD_MASK (0xFF << I40E_GLGEN_I2CCMD_REGADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_REGADD_MASK I40E_MASK(0xFF, I40E_GLGEN_I2CCMD_REGADD_SHIFT)
 #define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24
-#define I40E_GLGEN_I2CCMD_PHYADD_MASK (0x7 << I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_PHYADD_MASK I40E_MASK(0x7, I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
 #define I40E_GLGEN_I2CCMD_OP_SHIFT 27
-#define I40E_GLGEN_I2CCMD_OP_MASK (0x1 << I40E_GLGEN_I2CCMD_OP_SHIFT)
+#define I40E_GLGEN_I2CCMD_OP_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_OP_SHIFT)
 #define I40E_GLGEN_I2CCMD_RESET_SHIFT 28
-#define I40E_GLGEN_I2CCMD_RESET_MASK (0x1 << I40E_GLGEN_I2CCMD_RESET_SHIFT)
+#define I40E_GLGEN_I2CCMD_RESET_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_RESET_SHIFT)
 #define I40E_GLGEN_I2CCMD_R_SHIFT 29
-#define I40E_GLGEN_I2CCMD_R_MASK (0x1 << I40E_GLGEN_I2CCMD_R_SHIFT)
+#define I40E_GLGEN_I2CCMD_R_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_R_SHIFT)
 #define I40E_GLGEN_I2CCMD_E_SHIFT 31
-#define I40E_GLGEN_I2CCMD_E_MASK (0x1 << I40E_GLGEN_I2CCMD_E_SHIFT)
-#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CCMD_E_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_E_SHIFT)
+#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3
 #define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0
-#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK (0x1F << I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK I40E_MASK(0x1F, I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5
-#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK (0x7 << I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK I40E_MASK(0x7, I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8
-#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9
-#define I40E_GLGEN_I2CPARAMS_CLK_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10
-#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11
-#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12
-#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13
-#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14
-#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15
-#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31
-#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
-#define I40E_GLGEN_LED_CTL 0x00088178
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
+#define I40E_GLGEN_LED_CTL 0x00088178 /* Reset: POR */
 #define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0
-#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK (0x1 << I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
-#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3
 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK (0x1FFFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK I40E_MASK(0x1FFFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
 #define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17
-#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK (0x1 << I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK (0x3FFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
-#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK I40E_MASK(0x3FFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3
 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31
-#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
-#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
+#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MSCA_MAX_INDEX 3
 #define I40E_GLGEN_MSCA_MDIADD_SHIFT 0
-#define I40E_GLGEN_MSCA_MDIADD_MASK (0xFFFF << I40E_GLGEN_MSCA_MDIADD_SHIFT)
+#define I40E_GLGEN_MSCA_MDIADD_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSCA_MDIADD_SHIFT)
 #define I40E_GLGEN_MSCA_DEVADD_SHIFT 16
-#define I40E_GLGEN_MSCA_DEVADD_MASK (0x1F << I40E_GLGEN_MSCA_DEVADD_SHIFT)
+#define I40E_GLGEN_MSCA_DEVADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_DEVADD_SHIFT)
 #define I40E_GLGEN_MSCA_PHYADD_SHIFT 21
-#define I40E_GLGEN_MSCA_PHYADD_MASK (0x1F << I40E_GLGEN_MSCA_PHYADD_SHIFT)
+#define I40E_GLGEN_MSCA_PHYADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_PHYADD_SHIFT)
 #define I40E_GLGEN_MSCA_OPCODE_SHIFT 26
-#define I40E_GLGEN_MSCA_OPCODE_MASK (0x3 << I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_GLGEN_MSCA_OPCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_OPCODE_SHIFT)
 #define I40E_GLGEN_MSCA_STCODE_SHIFT 28
-#define I40E_GLGEN_MSCA_STCODE_MASK (0x3 << I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_GLGEN_MSCA_STCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_STCODE_SHIFT)
 #define I40E_GLGEN_MSCA_MDICMD_SHIFT 30
-#define I40E_GLGEN_MSCA_MDICMD_MASK (0x1 << I40E_GLGEN_MSCA_MDICMD_SHIFT)
+#define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT)
 #define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31
-#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK (0x1 << I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
-#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
+#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MSRWD_MAX_INDEX 3
 #define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
-#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
+#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
 #define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
-#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
-#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4
+#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4 /* Reset: PCIR */
 #define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
-#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK (0x1F << I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
 #define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
-#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK (0xFF << I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
-#define I40E_GLGEN_PE_ENA 0x000B81A0
-#define I40E_GLGEN_PE_ENA_PE_ENA_SHIFT 0
-#define I40E_GLGEN_PE_ENA_PE_ENA_MASK (0x1 << I40E_GLGEN_PE_ENA_PE_ENA_SHIFT)
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT 1
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_MASK (0x3 << I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT)
-#define I40E_GLGEN_RSTAT 0x000B8188
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
+#define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */
 #define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
-#define I40E_GLGEN_RSTAT_DEVSTATE_MASK (0x3 << I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
+#define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
 #define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2
-#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK (0x3 << I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
+#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
 #define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4
-#define I40E_GLGEN_RSTAT_CORERCNT_MASK (0x3 << I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_CORERCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6
-#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8
-#define I40E_GLGEN_RSTAT_EMPRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_EMPRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10
-#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK (0x3F << I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
-#define I40E_GLGEN_RSTCTL 0x000B8180
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
+#define I40E_GLGEN_RSTCTL 0x000B8180 /* Reset: POR */
 #define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0
-#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK (0x3F << I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
+#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
 #define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8
-#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
-#define I40E_GLGEN_RSTENA_EMP 0x000B818C
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
+#define I40E_GLGEN_RSTENA_EMP 0x000B818C /* Reset: POR */
 #define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT 0
-#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
-#define I40E_GLGEN_RTRIG 0x000B8190
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
+#define I40E_GLGEN_RTRIG 0x000B8190 /* Reset: CORER */
 #define I40E_GLGEN_RTRIG_CORER_SHIFT 0
-#define I40E_GLGEN_RTRIG_CORER_MASK (0x1 << I40E_GLGEN_RTRIG_CORER_SHIFT)
+#define I40E_GLGEN_RTRIG_CORER_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_CORER_SHIFT)
 #define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1
-#define I40E_GLGEN_RTRIG_GLOBR_MASK (0x1 << I40E_GLGEN_RTRIG_GLOBR_SHIFT)
+#define I40E_GLGEN_RTRIG_GLOBR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_GLOBR_SHIFT)
 #define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2
-#define I40E_GLGEN_RTRIG_EMPFWR_MASK (0x1 << I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
-#define I40E_GLGEN_STAT 0x000B612C
+#define I40E_GLGEN_RTRIG_EMPFWR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
+#define I40E_GLGEN_STAT 0x000B612C /* Reset: POR */
 #define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0
-#define I40E_GLGEN_STAT_HWRSVD0_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD0_SHIFT)
+#define I40E_GLGEN_STAT_HWRSVD0_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD0_SHIFT)
 #define I40E_GLGEN_STAT_DCBEN_SHIFT 2
-#define I40E_GLGEN_STAT_DCBEN_MASK (0x1 << I40E_GLGEN_STAT_DCBEN_SHIFT)
+#define I40E_GLGEN_STAT_DCBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_DCBEN_SHIFT)
 #define I40E_GLGEN_STAT_VTEN_SHIFT 3
-#define I40E_GLGEN_STAT_VTEN_MASK (0x1 << I40E_GLGEN_STAT_VTEN_SHIFT)
+#define I40E_GLGEN_STAT_VTEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_VTEN_SHIFT)
 #define I40E_GLGEN_STAT_FCOEN_SHIFT 4
-#define I40E_GLGEN_STAT_FCOEN_MASK (0x1 << I40E_GLGEN_STAT_FCOEN_SHIFT)
+#define I40E_GLGEN_STAT_FCOEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_FCOEN_SHIFT)
 #define I40E_GLGEN_STAT_EVBEN_SHIFT 5
-#define I40E_GLGEN_STAT_EVBEN_MASK (0x1 << I40E_GLGEN_STAT_EVBEN_SHIFT)
+#define I40E_GLGEN_STAT_EVBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_EVBEN_SHIFT)
 #define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6
-#define I40E_GLGEN_STAT_HWRSVD1_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD1_SHIFT)
-#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_STAT_HWRSVD1_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD1_SHIFT)
+#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3
 #define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0
-#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK (0xFFFFFFFF << I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
-#define I40E_GLVFGEN_TIMER 0x000881BC
+#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK I40E_MASK(0xFFFFFFFF, I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
+#define I40E_GLVFGEN_TIMER 0x000881BC /* Reset: CORER */
 #define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0
-#define I40E_GLVFGEN_TIMER_GTIME_MASK (0xFFFFFFFF << I40E_GLVFGEN_TIMER_GTIME_SHIFT)
-#define I40E_PFGEN_CTRL 0x00092400
+#define I40E_GLVFGEN_TIMER_GTIME_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVFGEN_TIMER_GTIME_SHIFT)
+#define I40E_PFGEN_CTRL 0x00092400 /* Reset: PFR */
 #define I40E_PFGEN_CTRL_PFSWR_SHIFT 0
-#define I40E_PFGEN_CTRL_PFSWR_MASK (0x1 << I40E_PFGEN_CTRL_PFSWR_SHIFT)
-#define I40E_PFGEN_DRUN 0x00092500
+#define I40E_PFGEN_CTRL_PFSWR_MASK I40E_MASK(0x1, I40E_PFGEN_CTRL_PFSWR_SHIFT)
+#define I40E_PFGEN_DRUN 0x00092500 /* Reset: CORER */
 #define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0
-#define I40E_PFGEN_DRUN_DRVUNLD_MASK (0x1 << I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
-#define I40E_PFGEN_PORTNUM 0x001C0480
+#define I40E_PFGEN_DRUN_DRVUNLD_MASK I40E_MASK(0x1, I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
+#define I40E_PFGEN_PORTNUM 0x001C0480 /* Reset: CORER */
 #define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
-#define I40E_PFGEN_STATE 0x00088000
-#define I40E_PFGEN_STATE_PFPEEN_SHIFT 0
-#define I40E_PFGEN_STATE_PFPEEN_MASK (0x1 << I40E_PFGEN_STATE_PFPEEN_SHIFT)
+#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_STATE 0x00088000 /* Reset: CORER */
+#define I40E_PFGEN_STATE_RESERVED_0_SHIFT 0
+#define I40E_PFGEN_STATE_RESERVED_0_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_RESERVED_0_SHIFT)
 #define I40E_PFGEN_STATE_PFFCEN_SHIFT 1
-#define I40E_PFGEN_STATE_PFFCEN_MASK (0x1 << I40E_PFGEN_STATE_PFFCEN_SHIFT)
+#define I40E_PFGEN_STATE_PFFCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFFCEN_SHIFT)
 #define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2
-#define I40E_PFGEN_STATE_PFLINKEN_MASK (0x1 << I40E_PFGEN_STATE_PFLINKEN_SHIFT)
+#define I40E_PFGEN_STATE_PFLINKEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFLINKEN_SHIFT)
 #define I40E_PFGEN_STATE_PFSCEN_SHIFT 3
-#define I40E_PFGEN_STATE_PFSCEN_MASK (0x1 << I40E_PFGEN_STATE_PFSCEN_SHIFT)
-#define I40E_PRTGEN_CNF 0x000B8120
+#define I40E_PFGEN_STATE_PFSCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFSCEN_SHIFT)
+#define I40E_PRTGEN_CNF 0x000B8120 /* Reset: POR */
 #define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0
-#define I40E_PRTGEN_CNF_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
 #define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1
-#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
 #define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2
-#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
-#define I40E_PRTGEN_CNF2 0x000B8160
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF2 0x000B8160 /* Reset: POR */
 #define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0
-#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK (0x1 << I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
-#define I40E_PRTGEN_STATUS 0x000B8100
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
+#define I40E_PRTGEN_STATUS 0x000B8100 /* Reset: POR */
 #define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0
-#define I40E_PRTGEN_STATUS_PORT_VALID_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
+#define I40E_PRTGEN_STATUS_PORT_VALID_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
 #define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1
-#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
-#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
+#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFGEN_RSTAT1_MAX_INDEX 127
 #define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
-#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
+#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPGEN_VFRSTAT_MAX_INDEX 127
 #define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0
-#define I40E_VPGEN_VFRSTAT_VFRD_MASK (0x1 << I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
-#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRSTAT_VFRD_MASK I40E_MASK(0x1, I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
+#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPGEN_VFRTRIG_MAX_INDEX 127
 #define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0
-#define I40E_VPGEN_VFRTRIG_VFSWR_MASK (0x1 << I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
-#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPGEN_VFRTRIG_VFSWR_MASK I40E_MASK(0x1, I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
+#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_VSIGEN_RSTAT_MAX_INDEX 383
 #define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0
-#define I40E_VSIGEN_RSTAT_VMRD_MASK (0x1 << I40E_VSIGEN_RSTAT_VMRD_SHIFT)
-#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RSTAT_VMRD_MASK I40E_MASK(0x1, I40E_VSIGEN_RSTAT_VMRD_SHIFT)
+#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_VSIGEN_RTRIG_MAX_INDEX 383
 #define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0
-#define I40E_VSIGEN_RTRIG_VMSWR_MASK (0x1 << I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
-#define I40E_GLHMC_APBVTINUSEBASE(_i) (0x000C4a00 + ((_i) * 4))
-#define I40E_GLHMC_APBVTINUSEBASE_MAX_INDEX 15
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_CEQPART(_i) (0x001312C0 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_CEQPART_MAX_INDEX 15
-#define I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_CEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_DBCQPART(_i) (0x00131240 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBCQPART_MAX_INDEX 15
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_DBQPPART(_i) (0x00138D80 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBQPPART_MAX_INDEX 15
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VSIGEN_RTRIG_VMSWR_MASK I40E_MASK(0x1, I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
+#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15
 #define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0
-#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
-#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
+#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15
 #define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0
-#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK (0xFFFFF << I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
-#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK I40E_MASK(0xFFFFF, I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
+#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010 /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK (0xF << I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15
 #define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0
-#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
-#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
+#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15
 #define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0
-#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK (0x7FFFFF << I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
-#define I40E_GLHMC_FCOEFMAX 0x000C20D0
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK I40E_MASK(0x7FFFFF, I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
+#define I40E_GLHMC_FCOEFMAX 0x000C20D0 /* Reset: CORER */
 #define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0
-#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK (0xFFFF << I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
-#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK I40E_MASK(0xFFFF, I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
+#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018 /* Reset: CORER */
 #define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK (0xF << I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEMAX 0x000C2014
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEMAX 0x000C2014 /* Reset: CORER */
 #define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0
-#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK (0x1FFF << I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
-#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK I40E_MASK(0x1FFF, I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
+#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15
 #define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15
 #define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
 #define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_FSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_FSIAVMAX 0x000C2068
+#define I40E_GLHMC_FSIAVCNT_RSVD_MASK I40E_MASK(0x7, I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_FSIAVMAX 0x000C2068 /* Reset: CORER */
 #define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0
-#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK (0x1FFFF << I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
-#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK I40E_MASK(0x1FFFF, I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
+#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064 /* Reset: CORER */
 #define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK (0xF << I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
-#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
+#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15
 #define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0
-#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
-#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
+#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15
 #define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK (0x1FFFFFFF << I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
-#define I40E_GLHMC_FSIMCMAX 0x000C2060
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
+#define I40E_GLHMC_FSIMCMAX 0x000C2060 /* Reset: CORER */
 #define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0
-#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK (0x3FFF << I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
-#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK I40E_MASK(0x3FFF, I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
+#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c /* Reset: CORER */
 #define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK (0xF << I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
-#define I40E_GLHMC_LANQMAX 0x000C2008
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
+#define I40E_GLHMC_LANQMAX 0x000C2008 /* Reset: CORER */
 #define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0
-#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK (0x7FF << I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
-#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
+#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANRXBASE_MAX_INDEX 15
 #define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0
-#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
-#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
+#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANRXCNT_MAX_INDEX 15
 #define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0
-#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK (0x7FF << I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
-#define I40E_GLHMC_LANRXOBJSZ 0x000C200c
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
+#define I40E_GLHMC_LANRXOBJSZ 0x000C200c /* Reset: CORER */
 #define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK (0xF << I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
-#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
+#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANTXBASE_MAX_INDEX 15
 #define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0
-#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
 #define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24
-#define I40E_GLHMC_LANTXBASE_RSVD_MASK (0xFF << I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
-#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXBASE_RSVD_MASK I40E_MASK(0xFF, I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
+#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANTXCNT_MAX_INDEX 15
 #define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0
-#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK (0x7FF << I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
-#define I40E_GLHMC_LANTXOBJSZ 0x000C2004
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
+#define I40E_GLHMC_LANTXOBJSZ 0x000C2004 /* Reset: CORER */
 #define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK (0xF << I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
-#define I40E_GLHMC_PEARPBASE(_i) (0x000C4800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_PEARPCNT(_i) (0x000C4900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_PEARPMAX 0x000C2038
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT 0
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_MASK (0x1FFFF << I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT)
-#define I40E_GLHMC_PEARPOBJSZ 0x000C2034
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_MASK (0x7 << I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT)
-#define I40E_GLHMC_PECQBASE(_i) (0x000C4200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_PECQCNT(_i) (0x000C4300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_PECQOBJSZ 0x000C2020
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_MASK (0xF << I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTCNT(_i) (0x000C4700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_PEHTEBASE(_i) (0x000C4600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTEBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_PEHTEOBJSZ 0x000C202c
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_MASK (0xF << I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTMAX 0x000C2030
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT 0
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_MASK (0x1FFFFF << I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT)
-#define I40E_GLHMC_PEMRBASE(_i) (0x000C4c00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_PEMRCNT(_i) (0x000C4d00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_PEMRMAX 0x000C2040
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT 0
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_MASK (0x7FFFFF << I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT)
-#define I40E_GLHMC_PEMROBJSZ 0x000C203c
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT 0
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_MASK (0xF << I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT)
-#define I40E_GLHMC_PEPBLBASE(_i) (0x000C5800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_PEPBLCNT(_i) (0x000C5900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_PEPBLMAX 0x000C206c
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT 0
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1BASE(_i) (0x000C5200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1BASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_PEQ1CNT(_i) (0x000C5300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1CNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLBASE(_i) (0x000C5400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_PEQ1FLCNT(_i) (0x000C5500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLMAX 0x000C2058
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1MAX 0x000C2054
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
-#define I40E_GLHMC_PEQ1OBJSZ 0x000C2050
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_MASK (0xF << I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT)
-#define I40E_GLHMC_PEQPBASE(_i) (0x000C4000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_PEQPCNT(_i) (0x000C4100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_PEQPOBJSZ 0x000C201c
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_MASK (0xF << I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQBASE(_i) (0x000C4400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_PESRQCNT(_i) (0x000C4500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_PESRQMAX 0x000C2028
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT 0
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_MASK (0xFFFF << I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ 0x000C2024
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_MASK (0xF << I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PETIMERBASE(_i) (0x000C5A00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERBASE_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_PETIMERCNT(_i) (0x000C5B00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERCNT_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_PETIMERMAX 0x000C2084
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT 0
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT)
-#define I40E_GLHMC_PETIMEROBJSZ 0x000C2080
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT 0
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_MASK (0xF << I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFBASE(_i) (0x000C4e00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_PEXFCNT(_i) (0x000C4f00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLBASE(_i) (0x000C5000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_PEXFFLCNT(_i) (0x000C5100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLMAX 0x000C204c
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
-#define I40E_GLHMC_PEXFMAX 0x000C2048
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ 0x000C2044
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_MASK (0xF << I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
+#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_PFASSIGN_MAX_INDEX 15
 #define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0
-#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK (0xF << I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
-#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK I40E_MASK(0xF, I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
+#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_SDPART_MAX_INDEX 15
 #define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_SDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_SDPART_PMSDBASE_MASK I40E_MASK(0xFFF, I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
 #define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_SDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
-#define I40E_GLHMC_VFAPBVTINUSEBASE(_i) (0x000Cca00 + ((_i) * 4))
-#define I40E_GLHMC_VFAPBVTINUSEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART(_i) (0x00132240 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFCEQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART(_i) (0x00132140 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBCQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART(_i) (0x00138E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBQPPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_VFFSIAVBASE(_i) (0x000Cd600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT(_i) (0x000Cd700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_VFPDINV(_i) (0x000C8300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPDINV_MAX_INDEX 31
-#define I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT 0
-#define I40E_GLHMC_VFPDINV_PMSDIDX_MASK (0xFFF << I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT)
-#define I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT 16
-#define I40E_GLHMC_VFPDINV_PMPDIDX_MASK (0x1FF << I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT)
-#define I40E_GLHMC_VFPEARPBASE(_i) (0x000Cc800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_VFPEARPCNT(_i) (0x000Cc900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_VFPECQBASE(_i) (0x000Cc200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_VFPECQCNT(_i) (0x000Cc300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTCNT(_i) (0x000Cc700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTEBASE(_i) (0x000Cc600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRBASE(_i) (0x000Ccc00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRCNT(_i) (0x000Ccd00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_VFPEPBLBASE(_i) (0x000Cd800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_VFPEPBLCNT(_i) (0x000Cd900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1BASE(_i) (0x000Cd200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1BASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1CNT(_i) (0x000Cd300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1CNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLBASE(_i) (0x000Cd400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLCNT(_i) (0x000Cd500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQPBASE(_i) (0x000Cc000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_VFPEQPCNT(_i) (0x000Cc100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_VFPESRQBASE(_i) (0x000Cc400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_VFPESRQCNT(_i) (0x000Cc500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_VFPETIMERBASE(_i) (0x000CDA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_VFPETIMERCNT(_i) (0x000CDB00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFBASE(_i) (0x000Cce00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFCNT(_i) (0x000Ccf00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFFLBASE(_i) (0x000Cd000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFFLCNT(_i) (0x000Cd100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_VFSDPART(_i) (0x000C8800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFSDPART_MAX_INDEX 31
-#define I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_VFSDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT)
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT)
-#define I40E_PFHMC_ERRORDATA 0x000C0500
+#define I40E_GLHMC_SDPART_PMSDSIZE_MASK I40E_MASK(0x1FFF, I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
+#define I40E_PFHMC_ERRORDATA 0x000C0500 /* Reset: PFR */
 #define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0
-#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK (0x3FFFFFFF << I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
-#define I40E_PFHMC_ERRORINFO 0x000C0400
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK I40E_MASK(0x3FFFFFFF, I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
+#define I40E_PFHMC_ERRORINFO 0x000C0400 /* Reset: PFR */
 #define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0
-#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK (0x1F << I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
 #define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7
-#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK (0x1 << I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
 #define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8
-#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK (0xF << I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK I40E_MASK(0xF, I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
 #define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16
-#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK (0x1F << I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
 #define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31
-#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK (0x1 << I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
-#define I40E_PFHMC_PDINV 0x000C0300
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
+#define I40E_PFHMC_PDINV 0x000C0300 /* Reset: PFR */
 #define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_PDINV_PMSDIDX_MASK (0xFFF << I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
+#define I40E_PFHMC_PDINV_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
 #define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16
-#define I40E_PFHMC_PDINV_PMPDIDX_MASK (0x1FF << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
-#define I40E_PFHMC_SDCMD 0x000C0000
+#define I40E_PFHMC_PDINV_PMPDIDX_MASK I40E_MASK(0x1FF, I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD 0x000C0000 /* Reset: PFR */
 #define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_SDCMD_PMSDIDX_MASK (0xFFF << I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
 #define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31
-#define I40E_PFHMC_SDCMD_PMSDWR_MASK (0x1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
-#define I40E_PFHMC_SDDATAHIGH 0x000C0200
+#define I40E_PFHMC_SDCMD_PMSDWR_MASK I40E_MASK(0x1, I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
+#define I40E_PFHMC_SDDATAHIGH 0x000C0200 /* Reset: PFR */
 #define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0
-#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK (0xFFFFFFFF << I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
-#define I40E_PFHMC_SDDATALOW 0x000C0100
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
+#define I40E_PFHMC_SDDATALOW 0x000C0100 /* Reset: PFR */
 #define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0
-#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1
-#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2
-#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK (0x3FF << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK I40E_MASK(0x3FF, I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12
-#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK (0xFFFFF << I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
-#define I40E_GL_UFUSE 0x00094008
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK I40E_MASK(0xFFFFF, I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ /* Reset: POR */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
+#define I40E_GL_UFUSE 0x00094008 /* Reset: POR */
 #define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1
-#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK (0x1 << I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK I40E_MASK(0x1, I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
 #define I40E_GL_UFUSE_NIC_ID_SHIFT 2
-#define I40E_GL_UFUSE_NIC_ID_MASK (0x1 << I40E_GL_UFUSE_NIC_ID_SHIFT)
+#define I40E_GL_UFUSE_NIC_ID_MASK I40E_MASK(0x1, I40E_GL_UFUSE_NIC_ID_SHIFT)
 #define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10
-#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
+#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
 #define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11
-#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
-#define I40E_EMPINT_GPIO_ENA 0x00088188
+#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
+#define I40E_EMPINT_GPIO_ENA 0x00088188 /* Reset: POR */
 #define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100 /* Reset: CORER */
 #define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
 #define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4
-#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK (0x1 << I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
-#define I40E_PFINT_AEQCTL 0x00038700
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK I40E_MASK(0x1, I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL 0x00038700 /* Reset: CORER */
 #define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_PFINT_CEQCTL_MAX_INDEX 511
 #define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_DYN_CTL0 0x00038480
+#define I40E_PFINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_DYN_CTL0 0x00038480 /* Reset: PFR */
 #define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
 #define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_DYN_CTLN_MAX_INDEX 511
 #define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
 #define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_PFINT_GPIO_ENA 0x00088080
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_PFINT_GPIO_ENA 0x00088080 /* Reset: CORER */
 #define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFINT_ICR0 0x00038780
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
 #define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_PFINT_ICR0_INTEVENT_MASK (0x1 << I40E_PFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_PFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_0_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_PFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_1_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_PFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_2_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_PFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_3_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5
-#define I40E_PFINT_ICR0_QUEUE_4_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_4_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_4_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_4_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6
-#define I40E_PFINT_ICR0_QUEUE_5_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_5_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_5_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_5_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7
-#define I40E_PFINT_ICR0_QUEUE_6_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_6_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_6_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_6_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8
-#define I40E_PFINT_ICR0_QUEUE_7_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_7_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_7_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_7_SHIFT)
 #define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ECC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_GRST_MASK (0x1 << I40E_PFINT_ICR0_GRST_SHIFT)
+#define I40E_PFINT_ICR0_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GRST_SHIFT)
 #define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
 #define I40E_PFINT_ICR0_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_GPIO_MASK (0x1 << I40E_PFINT_ICR0_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GPIO_SHIFT)
 #define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_STORM_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
 #define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_HMC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
 #define I40E_PFINT_ICR0_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_VFLR_MASK (0x1 << I40E_PFINT_ICR0_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_VFLR_SHIFT)
 #define I40E_PFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ADMINQ_SHIFT)
 #define I40E_PFINT_ICR0_SWINT_SHIFT 31
-#define I40E_PFINT_ICR0_SWINT_MASK (0x1 << I40E_PFINT_ICR0_SWINT_SHIFT)
-#define I40E_PFINT_ICR0_ENA 0x00038800
+#define I40E_PFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_SWINT_SHIFT)
+#define I40E_PFINT_ICR0_ENA 0x00038800 /* Reset: CORER */
 #define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_ENA_GRST_MASK (0x1 << I40E_PFINT_ICR0_ENA_GRST_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GRST_SHIFT)
 #define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
 #define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_ENA_GPIO_MASK (0x1 << I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
 #define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
 #define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_ENA_VFLR_MASK (0x1 << I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
 #define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_PFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */
+#define I40E_PFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */ /* Reset: PFR */
 #define I40E_PFINT_ITR0_MAX_INDEX 2
 #define I40E_PFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_PFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4))
+#define I40E_PFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4)) /* _i=0...2, _INTPF=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_ITRN_MAX_INDEX 2
 #define I40E_PFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_PFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_PFINT_LNKLST0 0x00038500
+#define I40E_PFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_PFINT_LNKLST0 0x00038500 /* Reset: PFR */
 #define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
 #define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_LNKLSTN_MAX_INDEX 511
 #define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
 #define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_RATE0 0x00038580
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_RATE0 0x00038580 /* Reset: PFR */
 #define I40E_PFINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATE0_INTERVAL_MASK (0x3F << I40E_PFINT_RATE0_INTERVAL_SHIFT)
+#define I40E_PFINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATE0_INTERVAL_SHIFT)
 #define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_RATEN_MAX_INDEX 511
 #define I40E_PFINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATEN_INTERVAL_MASK (0x3F << I40E_PFINT_RATEN_INTERVAL_SHIFT)
+#define I40E_PFINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATEN_INTERVAL_SHIFT)
 #define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_PFINT_STAT_CTL0 0x00038400
+#define I40E_PFINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_PFINT_STAT_CTL0 0x00038400 /* Reset: PFR */
 #define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QINT_RQCTL_MAX_INDEX 1535
 #define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_RQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
 #define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_RQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_ITR_INDX_SHIFT)
 #define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_RQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
 #define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_RQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_RQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
 #define I40E_QINT_RQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_RQCTL_INTEVENT_MASK (0x1 << I40E_QINT_RQCTL_INTEVENT_SHIFT)
-#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_RQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_INTEVENT_SHIFT)
+#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QINT_TQCTL_MAX_INDEX 1535
 #define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_TQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
 #define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_TQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_TQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_ITR_INDX_SHIFT)
 #define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_TQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
 #define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_TQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_TQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
 #define I40E_QINT_TQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_TQCTL_INTEVENT_MASK (0x1 << I40E_QINT_TQCTL_INTEVENT_SHIFT)
-#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QINT_TQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_INTEVENT_SHIFT)
+#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTL0_MAX_INDEX 127
 #define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTLN_MAX_INDEX 511
 #define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VFINT_ICR0_MAX_INDEX 127
 #define I40E_VFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR0_INTEVENT_MASK (0x1 << I40E_VFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_INTEVENT_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_0_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_1_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_2_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_3_SHIFT)
 #define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_SWINT_SHIFT 31
-#define I40E_VFINT_ICR0_SWINT_MASK (0x1 << I40E_VFINT_ICR0_SWINT_SHIFT)
-#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_SWINT_SHIFT)
+#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VFINT_ICR0_ENA_MAX_INDEX 127
 #define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */
+#define I40E_VFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_ITR0_MAX_INDEX 2
 #define I40E_VFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4))
+#define I40E_VFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...511 */ /* Reset: VFR */
 #define I40E_VFINT_ITRN_MAX_INDEX 2
 #define I40E_VFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_STAT_CTL0_MAX_INDEX 127
 #define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPINT_AEQCTL_MAX_INDEX 127
 #define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_VPINT_CEQCTL_MAX_INDEX 511
 #define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPINT_LNKLST0_MAX_INDEX 127
 #define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
 #define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VPINT_LNKLSTN_MAX_INDEX 511
 #define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
 #define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPINT_RATE0_MAX_INDEX 127
 #define I40E_VPINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATE0_INTERVAL_MASK (0x3F << I40E_VPINT_RATE0_INTERVAL_SHIFT)
+#define I40E_VPINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATE0_INTERVAL_SHIFT)
 #define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VPINT_RATEN_MAX_INDEX 511
 #define I40E_VPINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATEN_INTERVAL_MASK (0x3F << I40E_VPINT_RATEN_INTERVAL_SHIFT)
+#define I40E_VPINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATEN_INTERVAL_SHIFT)
 #define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_GL_RDPU_CNTRL 0x00051060
+#define I40E_VPINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_GL_RDPU_CNTRL 0x00051060 /* Reset: CORER */
 #define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0
-#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK (0x1 << I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK I40E_MASK(0x1, I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
 #define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1
-#define I40E_GL_RDPU_CNTRL_ECO_MASK (0x7FFFFFFF << I40E_GL_RDPU_CNTRL_ECO_SHIFT)
-#define I40E_GLLAN_RCTL_0 0x0012A500
+#define I40E_GL_RDPU_CNTRL_ECO_MASK I40E_MASK(0x7FFFFFFF, I40E_GL_RDPU_CNTRL_ECO_SHIFT)
+#define I40E_GLLAN_RCTL_0 0x0012A500 /* Reset: CORER */
 #define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0
-#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK (0x1 << I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
-#define I40E_GLLAN_TSOMSK_F 0x000442D8
+#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK I40E_MASK(0x1, I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
+#define I40E_GLLAN_TSOMSK_F 0x000442D8 /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0
-#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK (0xFFF << I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
-#define I40E_GLLAN_TSOMSK_L 0x000442E0
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
+#define I40E_GLLAN_TSOMSK_L 0x000442E0 /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0
-#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK (0xFFF << I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
-#define I40E_GLLAN_TSOMSK_M 0x000442DC
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
+#define I40E_GLLAN_TSOMSK_M 0x000442DC /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0
-#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK (0xFFF << I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
-#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000E6500 + ((_i) * 4)) /* i=0..11 */
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000e6500 + ((_i) * 4)) /* _i=0...11 */ /* Reset: CORER */
+#define I40E_GLLAN_TXPRE_QDIS_MAX_INDEX 11
 #define I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT 0
-#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK (0x7FF << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK I40E_MASK(0x7FF, I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT 16
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT)
 #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30
-#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
 #define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31
-#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
-
-#define I40E_PFLAN_QALLOC 0x001C0400
+#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
+#define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */
 #define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0
-#define I40E_PFLAN_QALLOC_FIRSTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
 #define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16
-#define I40E_PFLAN_QALLOC_LASTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_LASTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT)
 #define I40E_PFLAN_QALLOC_VALID_SHIFT 31
-#define I40E_PFLAN_QALLOC_VALID_MASK (0x1 << I40E_PFLAN_QALLOC_VALID_SHIFT)
-#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT)
+#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QRX_ENA_MAX_INDEX 1535
 #define I40E_QRX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QRX_ENA_QENA_REQ_MASK (0x1 << I40E_QRX_ENA_QENA_REQ_SHIFT)
+#define I40E_QRX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_REQ_SHIFT)
 #define I40E_QRX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QRX_ENA_FAST_QDIS_MASK (0x1 << I40E_QRX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QRX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QRX_ENA_FAST_QDIS_SHIFT)
 #define I40E_QRX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QRX_ENA_QENA_STAT_MASK (0x1 << I40E_QRX_ENA_QENA_STAT_SHIFT)
-#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_STAT_SHIFT)
+#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QRX_TAIL_MAX_INDEX 1535
 #define I40E_QRX_TAIL_TAIL_SHIFT 0
-#define I40E_QRX_TAIL_TAIL_MASK (0x1FFF << I40E_QRX_TAIL_TAIL_SHIFT)
-#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL_TAIL_SHIFT)
+#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QTX_CTL_MAX_INDEX 1535
 #define I40E_QTX_CTL_PFVF_Q_SHIFT 0
-#define I40E_QTX_CTL_PFVF_Q_MASK (0x3 << I40E_QTX_CTL_PFVF_Q_SHIFT)
+#define I40E_QTX_CTL_PFVF_Q_MASK I40E_MASK(0x3, I40E_QTX_CTL_PFVF_Q_SHIFT)
 #define I40E_QTX_CTL_PF_INDX_SHIFT 2
-#define I40E_QTX_CTL_PF_INDX_MASK (0xF << I40E_QTX_CTL_PF_INDX_SHIFT)
+#define I40E_QTX_CTL_PF_INDX_MASK I40E_MASK(0xF, I40E_QTX_CTL_PF_INDX_SHIFT)
 #define I40E_QTX_CTL_VFVM_INDX_SHIFT 7
-#define I40E_QTX_CTL_VFVM_INDX_MASK (0x1FF << I40E_QTX_CTL_VFVM_INDX_SHIFT)
-#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_CTL_VFVM_INDX_MASK I40E_MASK(0x1FF, I40E_QTX_CTL_VFVM_INDX_SHIFT)
+#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QTX_ENA_MAX_INDEX 1535
 #define I40E_QTX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QTX_ENA_QENA_REQ_MASK (0x1 << I40E_QTX_ENA_QENA_REQ_SHIFT)
+#define I40E_QTX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_REQ_SHIFT)
 #define I40E_QTX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QTX_ENA_FAST_QDIS_MASK (0x1 << I40E_QTX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QTX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QTX_ENA_FAST_QDIS_SHIFT)
 #define I40E_QTX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QTX_ENA_QENA_STAT_MASK (0x1 << I40E_QTX_ENA_QENA_STAT_SHIFT)
-#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_STAT_SHIFT)
+#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QTX_HEAD_MAX_INDEX 1535
 #define I40E_QTX_HEAD_HEAD_SHIFT 0
-#define I40E_QTX_HEAD_HEAD_MASK (0x1FFF << I40E_QTX_HEAD_HEAD_SHIFT)
+#define I40E_QTX_HEAD_HEAD_MASK I40E_MASK(0x1FFF, I40E_QTX_HEAD_HEAD_SHIFT)
 #define I40E_QTX_HEAD_RS_PENDING_SHIFT 16
-#define I40E_QTX_HEAD_RS_PENDING_MASK (0x1 << I40E_QTX_HEAD_RS_PENDING_SHIFT)
-#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_HEAD_RS_PENDING_MASK I40E_MASK(0x1, I40E_QTX_HEAD_RS_PENDING_SHIFT)
+#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QTX_TAIL_MAX_INDEX 1535
 #define I40E_QTX_TAIL_TAIL_SHIFT 0
-#define I40E_QTX_TAIL_TAIL_MASK (0x1FFF << I40E_QTX_TAIL_TAIL_SHIFT)
-#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QTX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL_TAIL_SHIFT)
+#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPLAN_MAPENA_MAX_INDEX 127
 #define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0
-#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK (0x1 << I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
-#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK I40E_MASK(0x1, I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
+#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: VFR */
 #define I40E_VPLAN_QTABLE_MAX_INDEX 15
 #define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0
-#define I40E_VPLAN_QTABLE_QINDEX_MASK (0x7FF << I40E_VPLAN_QTABLE_QINDEX_SHIFT)
-#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPLAN_QTABLE_QINDEX_MASK I40E_MASK(0x7FF, I40E_VPLAN_QTABLE_QINDEX_SHIFT)
+#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
 #define I40E_VSILAN_QBASE_MAX_INDEX 383
 #define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0
-#define I40E_VSILAN_QBASE_VSIBASE_MASK (0x7FF << I40E_VSILAN_QBASE_VSIBASE_SHIFT)
+#define I40E_VSILAN_QBASE_VSIBASE_MASK I40E_MASK(0x7FF, I40E_VSILAN_QBASE_VSIBASE_SHIFT)
 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
-#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
-#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK I40E_MASK(0x1, I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
+#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...7, _VSI=0...383 */ /* Reset: PFR */
 #define I40E_VSILAN_QTABLE_MAX_INDEX 7
 #define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
-#define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
+#define I40E_VSILAN_QTABLE_QINDEX_0_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
 #define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
-#define I40E_VSILAN_QTABLE_QINDEX_1_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
-#define I40E_PRTGL_SAH 0x001E2140
+#define I40E_VSILAN_QTABLE_QINDEX_1_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
+#define I40E_PRTGL_SAH 0x001E2140 /* Reset: GLOBR */
 #define I40E_PRTGL_SAH_FC_SAH_SHIFT 0
-#define I40E_PRTGL_SAH_FC_SAH_MASK (0xFFFF << I40E_PRTGL_SAH_FC_SAH_SHIFT)
+#define I40E_PRTGL_SAH_FC_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_FC_SAH_SHIFT)
 #define I40E_PRTGL_SAH_MFS_SHIFT 16
-#define I40E_PRTGL_SAH_MFS_MASK (0xFFFF << I40E_PRTGL_SAH_MFS_SHIFT)
-#define I40E_PRTGL_SAL 0x001E2120
+#define I40E_PRTGL_SAH_MFS_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_MFS_SHIFT)
+#define I40E_PRTGL_SAL 0x001E2120 /* Reset: GLOBR */
 #define I40E_PRTGL_SAL_FC_SAL_SHIFT 0
-#define I40E_PRTGL_SAL_FC_SAL_MASK (0xFFFFFFFF << I40E_PRTGL_SAL_FC_SAL_SHIFT)
-#define I40E_PRTMAC_HLCTLA 0x001E4760
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT 1
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_MASK (0x1 << I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT)
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT 2
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT)
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP 0x001E3130
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP 0x001E3290
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP 0x001E3310
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP 0x001E3100
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP 0x001E3280
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP 0x001E3300
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0
+#define I40E_PRTGL_SAL_FC_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTGL_SAL_FC_SAL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE 0x001E3000
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSECTL1 0x001E3560
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT 3
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT 30
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT 31
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480 /* Reset: GLOBR */
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484 /* Reset: GLOBR */
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
-#define I40E_GL_MNG_FWSM 0x000B6134
-#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
-#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
+#define I40E_GL_FWRESETCNT 0x00083100 /* Reset: POR */
+#define I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT 0
+#define I40E_GL_FWRESETCNT_FWRESETCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT)
+#define I40E_GL_MNG_FWSM 0x000B6134 /* Reset: POR */
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK I40E_MASK(0x3, I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
-#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK I40E_MASK(0xF, I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
-#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
 #define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
-#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK I40E_MASK(0x7, I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
-#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
-#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
-#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK I40E_MASK(0x3F, I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
-#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
-#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28
-#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29
-#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
-#define I40E_GL_MNG_HWARB_CTRL 0x000B6130
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_HWARB_CTRL 0x000B6130 /* Reset: POR */
 #define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0
-#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK (0x1 << I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
-#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK I40E_MASK(0x1, I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
+#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */ /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31
 #define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0
-#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
-#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
+#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260 /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK (0xFF << I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7
 #define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0
-#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK (0xFFFF << I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
-#define I40E_PRT_MNG_MANC 0x00256A20
+#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
+#define I40E_PRT_MNG_MANC 0x00256A20 /* Reset: POR */
 #define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0
-#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
 #define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1
-#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
 #define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17
-#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
 #define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19
-#define I40E_PRT_MNG_MANC_RCV_ALL_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_ALL_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
 #define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25
-#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
 #define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26
-#define I40E_PRT_MNG_MANC_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
 #define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28
-#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
 #define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29
-#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
-#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
+#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MAVTV_MAX_INDEX 7
 #define I40E_PRT_MNG_MAVTV_VID_SHIFT 0
-#define I40E_PRT_MNG_MAVTV_VID_MASK (0xFFF << I40E_PRT_MNG_MAVTV_VID_SHIFT)
-#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32))
+#define I40E_PRT_MNG_MAVTV_VID_MASK I40E_MASK(0xFFF, I40E_PRT_MNG_MAVTV_VID_SHIFT)
+#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEF_MAX_INDEX 7
 #define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4
-#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5
-#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK (0xFF << I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13
-#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17
-#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26
-#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29
-#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30
-#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31
-#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
-#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7
 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK (0xFFFF << I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29
-#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
-#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3
 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
-#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
+#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_METF_MAX_INDEX 3
 #define I40E_PRT_MNG_METF_ETYPE_SHIFT 0
-#define I40E_PRT_MNG_METF_ETYPE_MASK (0xFFFF << I40E_PRT_MNG_METF_ETYPE_SHIFT)
+#define I40E_PRT_MNG_METF_ETYPE_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_METF_ETYPE_SHIFT)
 #define I40E_PRT_MNG_METF_POLARITY_SHIFT 30
-#define I40E_PRT_MNG_METF_POLARITY_MASK (0x1 << I40E_PRT_MNG_METF_POLARITY_SHIFT)
-#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_METF_POLARITY_MASK I40E_MASK(0x1, I40E_PRT_MNG_METF_POLARITY_SHIFT)
+#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
 #define I40E_PRT_MNG_MFUTP_MAX_INDEX 15
 #define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0
-#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK (0xFFFF << I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
 #define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16
-#define I40E_PRT_MNG_MFUTP_UDP_MASK (0x1 << I40E_PRT_MNG_MFUTP_UDP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_UDP_SHIFT)
 #define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17
-#define I40E_PRT_MNG_MFUTP_TCP_MASK (0x1 << I40E_PRT_MNG_MFUTP_TCP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_TCP_SHIFT)
 #define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18
-#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK (0x1 << I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
-#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
+#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3
 #define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
 #define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15
 #define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MMAH_MAX_INDEX 3
 #define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0
-#define I40E_PRT_MNG_MMAH_MMAH_MASK (0xFFFF << I40E_PRT_MNG_MMAH_MMAH_SHIFT)
-#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAH_MMAH_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MMAH_MMAH_SHIFT)
+#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MMAL_MAX_INDEX 3
 #define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0
-#define I40E_PRT_MNG_MMAL_MMAL_MASK (0xFFFFFFFF << I40E_PRT_MNG_MMAL_MMAL_SHIFT)
-#define I40E_PRT_MNG_MNGONLY 0x00256A60
+#define I40E_PRT_MNG_MMAL_MMAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MMAL_MMAL_SHIFT)
+#define I40E_PRT_MNG_MNGONLY 0x00256A60 /* Reset: POR */
 #define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0
-#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK (0xFF << I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
-#define I40E_PRT_MNG_MSFM 0x00256AA0
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
+#define I40E_PRT_MNG_MSFM 0x00256AA0 /* Reset: POR */
 #define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0
-#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1
-#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2
-#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3
-#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4
-#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5
-#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6
-#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7
-#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
-#define I40E_MSIX_PBA(_i) (0x00004900 + ((_i) * 4)) /* _i=0...5 */
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
+#define I40E_MSIX_PBA(_i) (0x00001000 + ((_i) * 4)) /* _i=0...5 */ /* Reset: FLR */
 #define I40E_MSIX_PBA_MAX_INDEX 5
 #define I40E_MSIX_PBA_PENBIT_SHIFT 0
-#define I40E_MSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_MSIX_PBA_PENBIT_SHIFT)
-#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_PBA_PENBIT_SHIFT)
+#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TADD_MAX_INDEX 128
 #define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_MSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_MSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_MSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_MSIX_TADD_MSIXTADD10_SHIFT)
 #define I40E_MSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_MSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_MSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_MSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TMSG_MAX_INDEX 128
 #define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_MSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TUADD_MAX_INDEX 128
 #define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_MSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TVCTRL_MAX_INDEX 128
 #define I40E_MSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_MSIX_TVCTRL_MASK_MASK (0x1 << I40E_MSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFMSIX_PBA1(_i) (0x00004944 + ((_i) * 4)) /* _i=0...19 */
+#define I40E_MSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_MSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */
 #define I40E_VFMSIX_PBA1_MAX_INDEX 19
 #define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA1_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA1_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TADD1_MAX_INDEX 639
 #define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
 #define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD1_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TMSG1_MAX_INDEX 639
 #define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TUADD1_MAX_INDEX 639
 #define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
 #define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL1_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
-#define I40E_GLNVM_FLA 0x000B6108
+#define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
+#define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */
 #define I40E_GLNVM_FLA_FL_SCK_SHIFT 0
-#define I40E_GLNVM_FLA_FL_SCK_MASK (0x1 << I40E_GLNVM_FLA_FL_SCK_SHIFT)
+#define I40E_GLNVM_FLA_FL_SCK_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SCK_SHIFT)
 #define I40E_GLNVM_FLA_FL_CE_SHIFT 1
-#define I40E_GLNVM_FLA_FL_CE_MASK (0x1 << I40E_GLNVM_FLA_FL_CE_SHIFT)
+#define I40E_GLNVM_FLA_FL_CE_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_CE_SHIFT)
 #define I40E_GLNVM_FLA_FL_SI_SHIFT 2
-#define I40E_GLNVM_FLA_FL_SI_MASK (0x1 << I40E_GLNVM_FLA_FL_SI_SHIFT)
+#define I40E_GLNVM_FLA_FL_SI_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SI_SHIFT)
 #define I40E_GLNVM_FLA_FL_SO_SHIFT 3
-#define I40E_GLNVM_FLA_FL_SO_MASK (0x1 << I40E_GLNVM_FLA_FL_SO_SHIFT)
+#define I40E_GLNVM_FLA_FL_SO_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SO_SHIFT)
 #define I40E_GLNVM_FLA_FL_REQ_SHIFT 4
-#define I40E_GLNVM_FLA_FL_REQ_MASK (0x1 << I40E_GLNVM_FLA_FL_REQ_SHIFT)
+#define I40E_GLNVM_FLA_FL_REQ_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_REQ_SHIFT)
 #define I40E_GLNVM_FLA_FL_GNT_SHIFT 5
-#define I40E_GLNVM_FLA_FL_GNT_MASK (0x1 << I40E_GLNVM_FLA_FL_GNT_SHIFT)
+#define I40E_GLNVM_FLA_FL_GNT_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_GNT_SHIFT)
 #define I40E_GLNVM_FLA_LOCKED_SHIFT 6
-#define I40E_GLNVM_FLA_LOCKED_MASK (0x1 << I40E_GLNVM_FLA_LOCKED_SHIFT)
+#define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SHIFT)
 #define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18
-#define I40E_GLNVM_FLA_FL_SADDR_MASK (0x7FF << I40E_GLNVM_FLA_FL_SADDR_SHIFT)
+#define I40E_GLNVM_FLA_FL_SADDR_MASK I40E_MASK(0x7FF, I40E_GLNVM_FLA_FL_SADDR_SHIFT)
 #define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30
-#define I40E_GLNVM_FLA_FL_BUSY_MASK (0x1 << I40E_GLNVM_FLA_FL_BUSY_SHIFT)
+#define I40E_GLNVM_FLA_FL_BUSY_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_BUSY_SHIFT)
 #define I40E_GLNVM_FLA_FL_DER_SHIFT 31
-#define I40E_GLNVM_FLA_FL_DER_MASK (0x1 << I40E_GLNVM_FLA_FL_DER_SHIFT)
-#define I40E_GLNVM_FLASHID 0x000B6104
+#define I40E_GLNVM_FLA_FL_DER_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_DER_SHIFT)
+#define I40E_GLNVM_FLASHID 0x000B6104 /* Reset: POR */
 #define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0
-#define I40E_GLNVM_FLASHID_FLASHID_MASK (0xFFFFFF << I40E_GLNVM_FLASHID_FLASHID_SHIFT)
-#define I40E_GLNVM_GENS 0x000B6100
+#define I40E_GLNVM_FLASHID_FLASHID_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_FLASHID_FLASHID_SHIFT)
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT 31
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_MASK I40E_MASK(0x1, I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT)
+#define I40E_GLNVM_GENS 0x000B6100 /* Reset: POR */
 #define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0
-#define I40E_GLNVM_GENS_NVM_PRES_MASK (0x1 << I40E_GLNVM_GENS_NVM_PRES_SHIFT)
+#define I40E_GLNVM_GENS_NVM_PRES_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_NVM_PRES_SHIFT)
 #define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5
-#define I40E_GLNVM_GENS_SR_SIZE_MASK (0x7 << I40E_GLNVM_GENS_SR_SIZE_SHIFT)
+#define I40E_GLNVM_GENS_SR_SIZE_MASK I40E_MASK(0x7, I40E_GLNVM_GENS_SR_SIZE_SHIFT)
 #define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8
-#define I40E_GLNVM_GENS_BANK1VAL_MASK (0x1 << I40E_GLNVM_GENS_BANK1VAL_SHIFT)
+#define I40E_GLNVM_GENS_BANK1VAL_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_BANK1VAL_SHIFT)
 #define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23
-#define I40E_GLNVM_GENS_ALT_PRST_MASK (0x1 << I40E_GLNVM_GENS_ALT_PRST_SHIFT)
+#define I40E_GLNVM_GENS_ALT_PRST_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_ALT_PRST_SHIFT)
 #define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25
-#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK (0x1 << I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
-#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */
+#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
+#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */ /* Reset: POR */
 #define I40E_GLNVM_PROTCSR_MAX_INDEX 59
 #define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0
-#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK (0xFFFFFF << I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
-#define I40E_GLNVM_SRCTL 0x000B6110
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
+#define I40E_GLNVM_SRCTL 0x000B6110 /* Reset: POR */
 #define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0
-#define I40E_GLNVM_SRCTL_SRBUSY_MASK (0x1 << I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
+#define I40E_GLNVM_SRCTL_SRBUSY_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
 #define I40E_GLNVM_SRCTL_ADDR_SHIFT 14
-#define I40E_GLNVM_SRCTL_ADDR_MASK (0x7FFF << I40E_GLNVM_SRCTL_ADDR_SHIFT)
+#define I40E_GLNVM_SRCTL_ADDR_MASK I40E_MASK(0x7FFF, I40E_GLNVM_SRCTL_ADDR_SHIFT)
 #define I40E_GLNVM_SRCTL_WRITE_SHIFT 29
-#define I40E_GLNVM_SRCTL_WRITE_MASK (0x1 << I40E_GLNVM_SRCTL_WRITE_SHIFT)
+#define I40E_GLNVM_SRCTL_WRITE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_WRITE_SHIFT)
 #define I40E_GLNVM_SRCTL_START_SHIFT 30
-#define I40E_GLNVM_SRCTL_START_MASK (0x1 << I40E_GLNVM_SRCTL_START_SHIFT)
+#define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT)
 #define I40E_GLNVM_SRCTL_DONE_SHIFT 31
-#define I40E_GLNVM_SRCTL_DONE_MASK (0x1 << I40E_GLNVM_SRCTL_DONE_SHIFT)
-#define I40E_GLNVM_SRDATA 0x000B6114
+#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT)
+#define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */
 #define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0
-#define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
+#define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT)
 #define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
-#define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
-#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_SRDATA_RDDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008 /* Reset: POR */
 #define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
-#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
-#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
-#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
-#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
-#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
-#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
-#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
-#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
-#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
-#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
-
-#define I40E_GLPCI_BYTCTH 0x0009C484
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+#define I40E_GLPCI_BYTCTH 0x0009C484 /* Reset: PCIR */
 #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_BYTCTL 0x0009C488
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_BYTCTL 0x0009C488 /* Reset: PCIR */
 #define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_CAPCTRL 0x000BE4A4
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_CAPCTRL 0x000BE4A4 /* Reset: PCIR */
 #define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0
-#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK (0x1 << I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
-#define I40E_GLPCI_CAPSUP 0x000BE4A8
+#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP 0x000BE4A8 /* Reset: PCIR */
 #define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0
-#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK (0x1 << I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
+#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
 #define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2
-#define I40E_GLPCI_CAPSUP_LTR_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_LTR_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3
-#define I40E_GLPCI_CAPSUP_TPH_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_TPH_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4
-#define I40E_GLPCI_CAPSUP_ARI_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ARI_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5
-#define I40E_GLPCI_CAPSUP_IOV_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IOV_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6
-#define I40E_GLPCI_CAPSUP_ACS_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ACS_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7
-#define I40E_GLPCI_CAPSUP_SEC_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_SEC_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16
-#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17
-#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18
-#define I40E_GLPCI_CAPSUP_IDO_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IDO_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19
-#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK (0x1 << I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
+#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
 #define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20
-#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30
-#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
 #define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31
-#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
-#define I40E_GLPCI_CNF 0x000BE4C0
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
+#define I40E_GLPCI_CNF 0x000BE4C0 /* Reset: POR */
 #define I40E_GLPCI_CNF_FLEX10_SHIFT 1
-#define I40E_GLPCI_CNF_FLEX10_MASK (0x1 << I40E_GLPCI_CNF_FLEX10_SHIFT)
+#define I40E_GLPCI_CNF_FLEX10_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_FLEX10_SHIFT)
 #define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2
-#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK (0x1 << I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
-#define I40E_GLPCI_CNF2 0x000BE494
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
+#define I40E_GLPCI_CNF2 0x000BE494 /* Reset: PCIR */
 #define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0
-#define I40E_GLPCI_CNF2_RO_DIS_MASK (0x1 << I40E_GLPCI_CNF2_RO_DIS_SHIFT)
+#define I40E_GLPCI_CNF2_RO_DIS_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_RO_DIS_SHIFT)
 #define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1
-#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK (0x1 << I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
 #define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2
-#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
 #define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13
-#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
-#define I40E_GLPCI_DREVID 0x0009C480
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
+#define I40E_GLPCI_DREVID 0x0009C480 /* Reset: PCIR */
 #define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0
-#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK (0xFF << I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
-#define I40E_GLPCI_GSCL_1 0x0009C48C
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
+#define I40E_GLPCI_GSCL_1 0x0009C48C /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28
-#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
-#define I40E_GLPCI_GSCL_2 0x0009C490
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
+#define I40E_GLPCI_GSCL_2 0x0009C490 /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
-#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
+#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3
 #define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0
-#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
 #define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16
-#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
-#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
+#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
 #define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3
 #define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0
-#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK (0xFFFFFFFF << I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
-#define I40E_GLPCI_LATCT 0x0009C4B4
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
+#define I40E_GLPCI_LATCT 0x0009C4B4 /* Reset: PCIR */
 #define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT 0
-#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK (0xFFFFFFFF << I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
-#define I40E_GLPCI_LBARCTRL 0x000BE484
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
+#define I40E_GLPCI_LBARCTRL 0x000BE484 /* Reset: POR */
 #define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0
-#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK (0x1 << I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
+#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
 #define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1
-#define I40E_GLPCI_LBARCTRL_BAR32_MASK (0x1 << I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
+#define I40E_GLPCI_LBARCTRL_BAR32_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
 #define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3
-#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK (0x1 << I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT 4
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_MASK (0x3 << I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT 4
+#define I40E_GLPCI_LBARCTRL_RSVD_4_MASK I40E_MASK(0x3, I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT)
 #define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6
-#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT 10
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_MASK (0x1 << I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT 10
+#define I40E_GLPCI_LBARCTRL_RSVD_10_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT)
 #define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11
-#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
-#define I40E_GLPCI_LINKCAP 0x000BE4AC
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
+#define I40E_GLPCI_LINKCAP 0x000BE4AC /* Reset: PCIR */
 #define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0
-#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK (0x3F << I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK I40E_MASK(0x3F, I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
 #define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6
-#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK (0x7 << I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK I40E_MASK(0x7, I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
 #define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9
-#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK (0xF << I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
-#define I40E_GLPCI_PCIERR 0x000BE4FC
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK I40E_MASK(0xF, I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
+#define I40E_GLPCI_PCIERR 0x000BE4FC /* Reset: PCIR */
 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
-#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
-#define I40E_GLPCI_PCITEST2 0x000BE4BC
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
-
-#define I40E_GLPCI_PKTCT 0x0009C4BC
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PKTCT 0x0009C4BC /* Reset: PCIR */
 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
-#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
-#define I40E_GLPCI_PMSUP 0x000BE4B0
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PMSUP 0x000BE4B0 /* Reset: PCIR */
 #define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0
-#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
+#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
 #define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2
-#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5
-#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8
-#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11
-#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14
-#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK (0x1 << I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
+#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK I40E_MASK(0x1, I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
 #define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15
-#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
-#define I40E_GLPCI_PWRDATA 0x000BE490
+#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC /* Reset: PCIR */
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
+#define I40E_GLPCI_PWRDATA 0x000BE490 /* Reset: PCIR */
 #define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0
-#define I40E_GLPCI_PWRDATA_D0_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D0_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8
-#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16
-#define I40E_GLPCI_PWRDATA_D3_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D3_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24
-#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK (0x3 << I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
-#define I40E_GLPCI_REVID 0x000BE4B4
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK I40E_MASK(0x3, I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
+#define I40E_GLPCI_REVID 0x000BE4B4 /* Reset: PCIR */
 #define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0
-#define I40E_GLPCI_REVID_NVM_REVID_MASK (0xFF << I40E_GLPCI_REVID_NVM_REVID_SHIFT)
-#define I40E_GLPCI_SERH 0x000BE49C
+#define I40E_GLPCI_REVID_NVM_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_REVID_NVM_REVID_SHIFT)
+#define I40E_GLPCI_SERH 0x000BE49C /* Reset: PCIR */
 #define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0
-#define I40E_GLPCI_SERH_SER_NUM_H_MASK (0xFFFF << I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
-#define I40E_GLPCI_SERL 0x000BE498
+#define I40E_GLPCI_SERH_SER_NUM_H_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
+#define I40E_GLPCI_SERL 0x000BE498 /* Reset: PCIR */
 #define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0
-#define I40E_GLPCI_SERL_SER_NUM_L_MASK (0xFFFFFFFF << I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
-#define I40E_GLPCI_SUBSYSID 0x000BE48C
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT 0
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT)
-#define I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT 16
-#define I40E_GLPCI_SUBSYSID_SUB_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT)
-#define I40E_GLPCI_UPADD 0x000BE4F8
+#define I40E_GLPCI_SERL_SER_NUM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SUBVENID 0x000BE48C /* Reset: PCIR */
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT 0
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT)
+#define I40E_GLPCI_UPADD 0x000BE4F8 /* Reset: PCIR */
 #define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1
-#define I40E_GLPCI_UPADD_ADDRESS_MASK (0x7FFFFFFF << I40E_GLPCI_UPADD_ADDRESS_SHIFT)
-#define I40E_GLPCI_VFSUP 0x000BE4B8
+#define I40E_GLPCI_UPADD_ADDRESS_MASK I40E_MASK(0x7FFFFFFF, I40E_GLPCI_UPADD_ADDRESS_SHIFT)
+#define I40E_GLPCI_VENDORID 0x000BE518 /* Reset: PCIR */
+#define I40E_GLPCI_VENDORID_VENDORID_SHIFT 0
+#define I40E_GLPCI_VENDORID_VENDORID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_VENDORID_VENDORID_SHIFT)
+#define I40E_GLPCI_VFSUP 0x000BE4B8 /* Reset: PCIR */
 #define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0
-#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK (0x1 << I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
 #define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1
-#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK (0x1 << I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
-#define I40E_PF_FUNC_RID 0x0009C000
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
+#define I40E_PF_FUNC_RID 0x0009C000 /* Reset: PCIR */
 #define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0
-#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK (0x7 << I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK I40E_MASK(0x7, I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
 #define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3
-#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK (0x1F << I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK I40E_MASK(0x1F, I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
 #define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8
-#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK (0xFF << I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
-#define I40E_PF_PCI_CIAA 0x0009C080
+#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK I40E_MASK(0xFF, I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
+#define I40E_PF_PCI_CIAA 0x0009C080 /* Reset: FLR */
 #define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0
-#define I40E_PF_PCI_CIAA_ADDRESS_MASK (0xFFF << I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
+#define I40E_PF_PCI_CIAA_ADDRESS_MASK I40E_MASK(0xFFF, I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
 #define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12
-#define I40E_PF_PCI_CIAA_VF_NUM_MASK (0x7F << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
-#define I40E_PF_PCI_CIAD 0x0009C100
+#define I40E_PF_PCI_CIAA_VF_NUM_MASK I40E_MASK(0x7F, I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
+#define I40E_PF_PCI_CIAD 0x0009C100 /* Reset: FLR */
 #define I40E_PF_PCI_CIAD_DATA_SHIFT 0
-#define I40E_PF_PCI_CIAD_DATA_MASK (0xFFFFFFFF << I40E_PF_PCI_CIAD_DATA_SHIFT)
-#define I40E_PFPCI_CLASS 0x000BE400
+#define I40E_PF_PCI_CIAD_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_PCI_CIAD_DATA_SHIFT)
+#define I40E_PFPCI_CLASS 0x000BE400 /* Reset: PCIR */
 #define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0
-#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK (0x1 << I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
-#define I40E_PFPCI_CNF 0x000BE000
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
+#define I40E_PFPCI_CLASS_RESERVED_1_SHIFT 1
+#define I40E_PFPCI_CLASS_RESERVED_1_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_RESERVED_1_SHIFT)
+#define I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT 2
+#define I40E_PFPCI_CLASS_PF_IS_LAN_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT)
+#define I40E_PFPCI_CNF 0x000BE000 /* Reset: PCIR */
 #define I40E_PFPCI_CNF_MSI_EN_SHIFT 2
-#define I40E_PFPCI_CNF_MSI_EN_MASK (0x1 << I40E_PFPCI_CNF_MSI_EN_SHIFT)
+#define I40E_PFPCI_CNF_MSI_EN_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_MSI_EN_SHIFT)
 #define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3
-#define I40E_PFPCI_CNF_EXROM_DIS_MASK (0x1 << I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
+#define I40E_PFPCI_CNF_EXROM_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
 #define I40E_PFPCI_CNF_IO_BAR_SHIFT 4
-#define I40E_PFPCI_CNF_IO_BAR_MASK (0x1 << I40E_PFPCI_CNF_IO_BAR_SHIFT)
+#define I40E_PFPCI_CNF_IO_BAR_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_IO_BAR_SHIFT)
 #define I40E_PFPCI_CNF_INT_PIN_SHIFT 5
-#define I40E_PFPCI_CNF_INT_PIN_MASK (0x3 << I40E_PFPCI_CNF_INT_PIN_SHIFT)
-#define I40E_PFPCI_FACTPS 0x0009C180
+#define I40E_PFPCI_CNF_INT_PIN_MASK I40E_MASK(0x3, I40E_PFPCI_CNF_INT_PIN_SHIFT)
+#define I40E_PFPCI_DEVID 0x000BE080 /* Reset: PCIR */
+#define I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT 0
+#define I40E_PFPCI_DEVID_PF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT)
+#define I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT 16
+#define I40E_PFPCI_DEVID_VF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT)
+#define I40E_PFPCI_FACTPS 0x0009C180 /* Reset: FLR */
 #define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0
-#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK (0x3 << I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK I40E_MASK(0x3, I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
 #define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3
-#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK (0x1 << I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
-#define I40E_PFPCI_FUNC 0x000BE200
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK I40E_MASK(0x1, I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
+#define I40E_PFPCI_FUNC 0x000BE200 /* Reset: POR */
 #define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
 #define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1
-#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
 #define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2
-#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK (0x1 << I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
-#define I40E_PFPCI_FUNC2 0x000BE180
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
+#define I40E_PFPCI_FUNC2 0x000BE180 /* Reset: PCIR */
 #define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
-#define I40E_PFPCI_ICAUSE 0x0009C200
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_ICAUSE 0x0009C200 /* Reset: PFR */
 #define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0
-#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK (0xFFFFFFFF << I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
-#define I40E_PFPCI_IENA 0x0009C280
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
+#define I40E_PFPCI_IENA 0x0009C280 /* Reset: PFR */
 #define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0
-#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK (0xFFFFFFFF << I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
-#define I40E_PFPCI_PFDEVID 0x000BE080
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_PM 0x000BE300
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
+#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800 /* Reset: PCIR */
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_PM 0x000BE300 /* Reset: POR */
 #define I40E_PFPCI_PM_PME_EN_SHIFT 0
-#define I40E_PFPCI_PM_PME_EN_MASK (0x1 << I40E_PFPCI_PM_PME_EN_SHIFT)
-#define I40E_PFPCI_STATUS1 0x000BE280
+#define I40E_PFPCI_PM_PME_EN_MASK I40E_MASK(0x1, I40E_PFPCI_PM_PME_EN_SHIFT)
+#define I40E_PFPCI_STATUS1 0x000BE280 /* Reset: POR */
 #define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0
-#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK (0x1 << I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
-#define I40E_PFPCI_VFDEVID 0x000BE100
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_VMINDEX 0x0009C300
+#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK I40E_MASK(0x1, I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
+#define I40E_PFPCI_SUBSYSID 0x000BE100 /* Reset: PCIR */
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT 0
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT 16
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE 0x0000E400 /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 /* Reset: PCIR */
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VMINDEX 0x0009C300 /* Reset: PCIR */
 #define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0
-#define I40E_PFPCI_VMINDEX_VMINDEX_MASK (0x1FF << I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
-#define I40E_PFPCI_VMPEND 0x0009C380
+#define I40E_PFPCI_VMINDEX_VMINDEX_MASK I40E_MASK(0x1FF, I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
+#define I40E_PFPCI_VMPEND 0x0009C380 /* Reset: PCIR */
 #define I40E_PFPCI_VMPEND_PENDING_SHIFT 0
-#define I40E_PFPCI_VMPEND_PENDING_MASK (0x1 << I40E_PFPCI_VMPEND_PENDING_SHIFT)
-#define I40E_GLPE_CPUSTATUS0 0x0000D040
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT 0
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT)
-#define I40E_GLPE_CPUSTATUS1 0x0000D044
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT 0
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT)
-#define I40E_GLPE_CPUSTATUS2 0x0000D048
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT 0
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL(_i) (0x0000D480 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPE_PFFLMOBJCTRL_MAX_INDEX 15
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMOBJCTRL_MAX_INDEX 31
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMQ1ALLOCERR(_i) (0x0000C700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMQ1ALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFFLMXMITALLOCERR(_i) (0x0000C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMXMITALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFUDACTRL(_i) (0x0000C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDACTRL_MAX_INDEX 31
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN(_i) (0x0000C100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDAUCFBQPN_MAX_INDEX 31
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT 0
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT 31
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_MASK (0x1 << I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_AEQALLOC 0x00131180
-#define I40E_PFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_PFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_PFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_PFPE_CCQPHIGH 0x00008200
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_PFPE_CCQPLOW 0x00008180
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_PFPE_CCQPSTATUS 0x00008100
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_PFPE_CQACK 0x00131100
-#define I40E_PFPE_CQACK_PECQID_SHIFT 0
-#define I40E_PFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_PFPE_CQACK_PECQID_SHIFT)
-#define I40E_PFPE_CQARM 0x00131080
-#define I40E_PFPE_CQARM_PECQID_SHIFT 0
-#define I40E_PFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_PFPE_CQARM_PECQID_SHIFT)
-#define I40E_PFPE_CQPDB 0x00008000
-#define I40E_PFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_PFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_PFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_PFPE_CQPERRCODES 0x00008880
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_PFPE_CQPTAIL 0x00008080
-#define I40E_PFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_PFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_PFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_PFPE_FLMQ1ALLOCERR 0x00008980
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_FLMXMITALLOCERR 0x00008900
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_IPCONFIG0 0x00008280
-#define I40E_PFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-
-#define I40E_PFPE_MRTEIDXMASK 0x00008600
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_PFPE_RCVUNEXPECTEDERROR 0x00008680
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_PFPE_TCPNOWTIMER 0x00008580
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_PFPE_UDACTRL 0x00008700
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN 0x00008780
-#define I40E_PFPE_UDAUCFBQPN_QPN_SHIFT 0
-#define I40E_PFPE_UDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_PFPE_UDAUCFBQPN_QPN_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN_VALID_SHIFT 31
-#define I40E_PFPE_UDAUCFBQPN_VALID_MASK (0x1 << I40E_PFPE_UDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_WQEALLOC 0x00138C00
-#define I40E_PFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_PFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_PFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFPE_AEQALLOC(_VF) (0x00130C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_AEQALLOC_MAX_INDEX 127
-#define I40E_VFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH(_VF) (0x00001000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPHIGH_MAX_INDEX 127
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW(_VF) (0x00000C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPLOW_MAX_INDEX 127
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS(_VF) (0x00000800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPSTATUS_MAX_INDEX 127
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK(_VF) (0x00130800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQACK_MAX_INDEX 127
-#define I40E_VFPE_CQACK_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK_PECQID_SHIFT)
-#define I40E_VFPE_CQARM(_VF) (0x00130400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQARM_MAX_INDEX 127
-#define I40E_VFPE_CQARM_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB(_VF) (0x00000000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPDB_MAX_INDEX 127
-#define I40E_VFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES(_VF) (0x00001800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPERRCODES_MAX_INDEX 127
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL(_VF) (0x00000400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPTAIL_MAX_INDEX 127
-#define I40E_VFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG0(_VF) (0x00001400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_IPCONFIG0_MAX_INDEX 127
-#define I40E_VFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR(_VF) (0x00003400 + ((_VF) * 4))
-#define I40E_VFPE_RCVUNEXPECTEDERROR_MAX_INDEX 127
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER(_VF) (0x00002C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_TCPNOWTIMER_MAX_INDEX 127
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC(_VF) (0x00138000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_WQEALLOC_MAX_INDEX 127
-#define I40E_VFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_GLPES_PFIP4RXDISCARD(_i) (0x00010600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSHI(_i) (0x00010804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSLO(_i) (0x00010800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSHI(_i) (0x00010A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSLO(_i) (0x00010A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSHI(_i) (0x00010C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSLO(_i) (0x00010C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSHI(_i) (0x00010204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSLO(_i) (0x00010200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSHI(_i) (0x00010404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSLO(_i) (0x00010400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXTRUNC(_i) (0x00010700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSHI(_i) (0x00011E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSLO(_i) (0x00011E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSHI(_i) (0x00012004 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSLO(_i) (0x00012000 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSHI(_i) (0x00012204 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSLO(_i) (0x00012200 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXNOROUTE(_i) (0x00012E00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSHI(_i) (0x00011A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSLO(_i) (0x00011A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSHI(_i) (0x00011C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSLO(_i) (0x00011C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXDISCARD(_i) (0x00011200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSHI(_i) (0x00011404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSLO(_i) (0x00011400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSHI(_i) (0x00011604 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSLO(_i) (0x00011600 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSHI(_i) (0x00011804 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSLO(_i) (0x00011800 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSHI(_i) (0x00010E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSLO(_i) (0x00010E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSHI(_i) (0x00011004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSLO(_i) (0x00011000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXTRUNC(_i) (0x00011300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSHI(_i) (0x00012804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSLO(_i) (0x00012800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSHI(_i) (0x00012A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSLO(_i) (0x00012A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSHI(_i) (0x00012C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSLO(_i) (0x00012C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXNOROUTE(_i) (0x00012F00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSHI(_i) (0x00012404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSLO(_i) (0x00012400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSHI(_i) (0x00012604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSLO(_i) (0x00012600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSHI(_i) (0x00013E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSLO(_i) (0x00013E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSHI(_i) (0x00014004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSLO(_i) (0x00014000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSHI(_i) (0x00013C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSLO(_i) (0x00013C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSHI(_i) (0x00014404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSLO(_i) (0x00014400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSHI(_i) (0x00014604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSLO(_i) (0x00014600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSHI(_i) (0x00014204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSLO(_i) (0x00014200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDHI(_i) (0x00014804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDLO(_i) (0x00014800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_PFRDMAVINVHI(_i) (0x00014A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_PFRDMAVINVLO(_i) (0x00014A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_PFRXVLANERR(_i) (0x00010000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFRXVLANERR_MAX_INDEX 15
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_PFTCPRTXSEG(_i) (0x00013600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRTXSEG_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_PFTCPRXOPTERR(_i) (0x00013200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXOPTERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_PFTCPRXPROTOERR(_i) (0x00013300 + ((_i) * 4))
-#define I40E_GLPES_PFTCPRXPROTOERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSHI(_i) (0x00013004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSLO(_i) (0x00013000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGHI(_i) (0x00013404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGLO(_i) (0x00013400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSHI(_i) (0x00013804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSLO(_i) (0x00013800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSHI(_i) (0x00013A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSLO(_i) (0x00013A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSHI 0x0001E014
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSLO 0x0001E010
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPHI 0x0001E01C
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPLO 0x0001E018
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT)
-#define I40E_GLPES_RDMARXOOONOMARK 0x0001E004
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT 0
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT)
-#define I40E_GLPES_RDMARXUNALIGN 0x0001E000
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT 0
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLEHI 0x0001E044
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLELO 0x0001E040
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLEHI 0x0001E02C
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLELO 0x0001E028
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKHI 0x0001E024
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKSLO 0x0001E020
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLEHI 0x0001E03C
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLELO 0x0001E038
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLEHI 0x0001E034
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLELO 0x0001E030
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXUNEXPERR 0x0001E008
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT 0
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_MASK (0xFFFFFF << I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTHI 0x0001E04C
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTLO 0x0001E048
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTHI 0x0001E054
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTLO 0x0001E050
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSHI 0x0001E05C
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSLO 0x0001E058
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXDISCARD(_i) (0x00018600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSHI(_i) (0x00018804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSLO(_i) (0x00018800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSHI(_i) (0x00018A04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSLO(_i) (0x00018A00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSHI(_i) (0x00018C04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSLO(_i) (0x00018C00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSHI(_i) (0x00018204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSLO(_i) (0x00018200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSHI(_i) (0x00018404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSLO(_i) (0x00018400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXTRUNC(_i) (0x00018700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSHI(_i) (0x00019E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSLO(_i) (0x00019E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSHI(_i) (0x0001A004 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSLO(_i) (0x0001A000 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSHI(_i) (0x0001A204 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSLO(_i) (0x0001A200 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXNOROUTE(_i) (0x0001AE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSHI(_i) (0x00019A04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSLO(_i) (0x00019A00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSHI(_i) (0x00019C04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSLO(_i) (0x00019C00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXDISCARD(_i) (0x00019200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSHI(_i) (0x00019404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSLO(_i) (0x00019400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSHI(_i) (0x00019604 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSLO(_i) (0x00019600 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSHI(_i) (0x00019804 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSLO(_i) (0x00019800 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSHI(_i) (0x00018E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSLO(_i) (0x00018E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSHI(_i) (0x00019004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSLO(_i) (0x00019000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXTRUNC(_i) (0x00019300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSHI(_i) (0x0001A804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSLO(_i) (0x0001A800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSHI(_i) (0x0001AA04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSLO(_i) (0x0001AA00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSHI(_i) (0x0001AC04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSLO(_i) (0x0001AC00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXNOROUTE(_i) (0x0001AF00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSHI(_i) (0x0001A404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSLO(_i) (0x0001A400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSHI(_i) (0x0001A604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSLO(_i) (0x0001A600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSHI(_i) (0x0001BE04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSLO(_i) (0x0001BE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSHI(_i) (0x0001C004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSLO(_i) (0x0001C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSHI(_i) (0x0001BC04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSLO(_i) (0x0001BC00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSHI(_i) (0x0001C404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSLO(_i) (0x0001C400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSHI(_i) (0x0001C604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSLO(_i) (0x0001C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSHI(_i) (0x0001C204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSLO(_i) (0x0001C200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDHI(_i) (0x0001C804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDLO(_i) (0x0001C800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_VFRDMAVINVHI(_i) (0x0001CA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_VFRDMAVINVLO(_i) (0x0001CA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_VFRXVLANERR(_i) (0x00018000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRXVLANERR_MAX_INDEX 31
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_VFTCPRTXSEG(_i) (0x0001B600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRTXSEG_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_VFTCPRXOPTERR(_i) (0x0001B200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXOPTERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_VFTCPRXPROTOERR(_i) (0x0001B300 + ((_i) * 4))
-#define I40E_GLPES_VFTCPRXPROTOERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSHI(_i) (0x0001B004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSLO(_i) (0x0001B000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGHI(_i) (0x0001B404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGLO(_i) (0x0001B400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSHI(_i) (0x0001B804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSLO(_i) (0x0001B800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSHI(_i) (0x0001BA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSLO(_i) (0x0001BA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_PRTPM_EEE_STAT 0x001E4320
+#define I40E_PFPCI_VMPEND_PENDING_MASK I40E_MASK(0x1, I40E_PFPCI_VMPEND_PENDING_SHIFT)
+#define I40E_PRTPM_EEE_STAT 0x001E4320 /* Reset: GLOBR */
 #define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
-#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
 #define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30
-#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
 #define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31
-#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
-#define I40E_PRTPM_EEEC 0x001E4380
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEEC 0x001E4380 /* Reset: GLOBR */
 #define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16
-#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK (0x3F << I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
 #define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24
-#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK (0x3 << I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK I40E_MASK(0x3, I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
 #define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26
-#define I40E_PRTPM_EEEC_TEEE_DLY_MASK (0x3F << I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
-#define I40E_PRTPM_EEEFWD 0x001E4400
+#define I40E_PRTPM_EEEC_TEEE_DLY_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
+#define I40E_PRTPM_EEEFWD 0x001E4400 /* Reset: GLOBR */
 #define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31
-#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK (0x1 << I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
-#define I40E_PRTPM_EEER 0x001E4360
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK I40E_MASK(0x1, I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
+#define I40E_PRTPM_EEER 0x001E4360 /* Reset: GLOBR */
 #define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0
-#define I40E_PRTPM_EEER_TW_SYSTEM_MASK (0xFFFF << I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
+#define I40E_PRTPM_EEER_TW_SYSTEM_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
 #define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16
-#define I40E_PRTPM_EEER_TX_LPI_EN_MASK (0x1 << I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
-#define I40E_PRTPM_EEETXC 0x001E43E0
+#define I40E_PRTPM_EEER_TX_LPI_EN_MASK I40E_MASK(0x1, I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
+#define I40E_PRTPM_EEETXC 0x001E43E0 /* Reset: GLOBR */
 #define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0
-#define I40E_PRTPM_EEETXC_TW_PHY_MASK (0xFFFF << I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
-#define I40E_PRTPM_GC 0x000B8140
+#define I40E_PRTPM_EEETXC_TW_PHY_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
+#define I40E_PRTPM_GC 0x000B8140 /* Reset: POR */
 #define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0
-#define I40E_PRTPM_GC_EMP_LINK_ON_MASK (0x1 << I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
+#define I40E_PRTPM_GC_EMP_LINK_ON_MASK I40E_MASK(0x1, I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
 #define I40E_PRTPM_GC_MNG_VETO_SHIFT 1
-#define I40E_PRTPM_GC_MNG_VETO_MASK (0x1 << I40E_PRTPM_GC_MNG_VETO_SHIFT)
+#define I40E_PRTPM_GC_MNG_VETO_MASK I40E_MASK(0x1, I40E_PRTPM_GC_MNG_VETO_SHIFT)
 #define I40E_PRTPM_GC_RATD_SHIFT 2
-#define I40E_PRTPM_GC_RATD_MASK (0x1 << I40E_PRTPM_GC_RATD_SHIFT)
+#define I40E_PRTPM_GC_RATD_MASK I40E_MASK(0x1, I40E_PRTPM_GC_RATD_SHIFT)
 #define I40E_PRTPM_GC_LCDMP_SHIFT 3
-#define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
+#define I40E_PRTPM_GC_LCDMP_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LCDMP_SHIFT)
 #define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
-#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
-#define I40E_PRTPM_RLPIC 0x001E43A0
+#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
+#define I40E_PRTPM_RLPIC 0x001E43A0 /* Reset: GLOBR */
 #define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
-#define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
-#define I40E_PRTPM_TLPIC 0x001E43C0
+#define I40E_PRTPM_RLPIC_ERLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
+#define I40E_PRTPM_TLPIC 0x001E43C0 /* Reset: GLOBR */
 #define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0
-#define I40E_PRTPM_TLPIC_ETLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
-#define I40E_GLRPB_DPSS 0x000AC828
+#define I40E_PRTPM_TLPIC_ETLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
+#define I40E_GLRPB_DPSS 0x000AC828 /* Reset: CORER */
 #define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0
-#define I40E_GLRPB_DPSS_DPS_TCN_MASK (0xFFFFF << I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
-#define I40E_GLRPB_GHW 0x000AC830
+#define I40E_GLRPB_DPSS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
+#define I40E_GLRPB_GHW 0x000AC830 /* Reset: CORER */
 #define I40E_GLRPB_GHW_GHW_SHIFT 0
-#define I40E_GLRPB_GHW_GHW_MASK (0xFFFFF << I40E_GLRPB_GHW_GHW_SHIFT)
-#define I40E_GLRPB_GLW 0x000AC834
+#define I40E_GLRPB_GHW_GHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GHW_GHW_SHIFT)
+#define I40E_GLRPB_GLW 0x000AC834 /* Reset: CORER */
 #define I40E_GLRPB_GLW_GLW_SHIFT 0
-#define I40E_GLRPB_GLW_GLW_MASK (0xFFFFF << I40E_GLRPB_GLW_GLW_SHIFT)
-#define I40E_GLRPB_PHW 0x000AC844
+#define I40E_GLRPB_GLW_GLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GLW_GLW_SHIFT)
+#define I40E_GLRPB_PHW 0x000AC844 /* Reset: CORER */
 #define I40E_GLRPB_PHW_PHW_SHIFT 0
-#define I40E_GLRPB_PHW_PHW_MASK (0xFFFFF << I40E_GLRPB_PHW_PHW_SHIFT)
-#define I40E_GLRPB_PLW 0x000AC848
+#define I40E_GLRPB_PHW_PHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PHW_PHW_SHIFT)
+#define I40E_GLRPB_PLW 0x000AC848 /* Reset: CORER */
 #define I40E_GLRPB_PLW_PLW_SHIFT 0
-#define I40E_GLRPB_PLW_PLW_MASK (0xFFFFF << I40E_GLRPB_PLW_PLW_SHIFT)
-#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_GLRPB_PLW_PLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PLW_PLW_SHIFT)
+#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DHW_MAX_INDEX 7
 #define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0
-#define I40E_PRTRPB_DHW_DHW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
-#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DHW_DHW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
+#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DLW_MAX_INDEX 7
 #define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0
-#define I40E_PRTRPB_DLW_DLW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
-#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DLW_DLW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
+#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DPS_MAX_INDEX 7
 #define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0
-#define I40E_PRTRPB_DPS_DPS_TCN_MASK (0xFFFFF << I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
-#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DPS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
+#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_SHT_MAX_INDEX 7
 #define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0
-#define I40E_PRTRPB_SHT_SHT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
-#define I40E_PRTRPB_SHW 0x000AC580
+#define I40E_PRTRPB_SHT_SHT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
+#define I40E_PRTRPB_SHW 0x000AC580 /* Reset: CORER */
 #define I40E_PRTRPB_SHW_SHW_SHIFT 0
-#define I40E_PRTRPB_SHW_SHW_MASK (0xFFFFF << I40E_PRTRPB_SHW_SHW_SHIFT)
-#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SHW_SHW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHW_SHW_SHIFT)
+#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_SLT_MAX_INDEX 7
 #define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0
-#define I40E_PRTRPB_SLT_SLT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
-#define I40E_PRTRPB_SLW 0x000AC6A0
+#define I40E_PRTRPB_SLT_SLT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
+#define I40E_PRTRPB_SLW 0x000AC6A0 /* Reset: CORER */
 #define I40E_PRTRPB_SLW_SLW_SHIFT 0
-#define I40E_PRTRPB_SLW_SLW_MASK (0xFFFFF << I40E_PRTRPB_SLW_SLW_SHIFT)
-#define I40E_PRTRPB_SPS 0x000AC7C0
+#define I40E_PRTRPB_SLW_SLW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLW_SLW_SHIFT)
+#define I40E_PRTRPB_SPS 0x000AC7C0 /* Reset: CORER */
 #define I40E_PRTRPB_SPS_SPS_SHIFT 0
-#define I40E_PRTRPB_SPS_SPS_MASK (0xFFFFF << I40E_PRTRPB_SPS_SPS_SHIFT)
-#define I40E_GLQF_APBVT(_i) (0x00260000 + ((_i) * 4)) /* _i=0...2047 */
-#define I40E_GLQF_APBVT_MAX_INDEX 2047
-#define I40E_GLQF_APBVT_APBVT_SHIFT 0
-#define I40E_GLQF_APBVT_APBVT_MASK (0xFFFFFFFF << I40E_GLQF_APBVT_APBVT_SHIFT)
-#define I40E_GLQF_CTL 0x00269BA4
+#define I40E_PRTRPB_SPS_SPS_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SPS_SPS_SHIFT)
+#define I40E_GLQF_CTL 0x00269BA4 /* Reset: CORER */
 #define I40E_GLQF_CTL_HTOEP_SHIFT 1
-#define I40E_GLQF_CTL_HTOEP_MASK (0x1 << I40E_GLQF_CTL_HTOEP_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_SHIFT)
 #define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2
-#define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_FCOE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
 #define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
-#define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_PCNT_ALLOC_MASK I40E_MASK(0x7, I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT 6
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT)
 #define I40E_GLQF_CTL_RSVD_SHIFT 7
-#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
+#define I40E_GLQF_CTL_RSVD_MASK I40E_MASK(0x1, I40E_GLQF_CTL_RSVD_SHIFT)
 #define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
-#define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXPEBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
 #define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
-#define I40E_GLQF_CTL_MAXFCBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFCBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
 #define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14
-#define I40E_GLQF_CTL_MAXFDBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFDBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
 #define I40E_GLQF_CTL_FDBEST_SHIFT 17
-#define I40E_GLQF_CTL_FDBEST_MASK (0xFF << I40E_GLQF_CTL_FDBEST_SHIFT)
+#define I40E_GLQF_CTL_FDBEST_MASK I40E_MASK(0xFF, I40E_GLQF_CTL_FDBEST_SHIFT)
 #define I40E_GLQF_CTL_PROGPRIO_SHIFT 25
-#define I40E_GLQF_CTL_PROGPRIO_MASK (0x1 << I40E_GLQF_CTL_PROGPRIO_SHIFT)
+#define I40E_GLQF_CTL_PROGPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_PROGPRIO_SHIFT)
 #define I40E_GLQF_CTL_INVALPRIO_SHIFT 26
-#define I40E_GLQF_CTL_INVALPRIO_MASK (0x1 << I40E_GLQF_CTL_INVALPRIO_SHIFT)
+#define I40E_GLQF_CTL_INVALPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_INVALPRIO_SHIFT)
 #define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27
-#define I40E_GLQF_CTL_IGNORE_IP_MASK (0x1 << I40E_GLQF_CTL_IGNORE_IP_SHIFT)
-#define I40E_GLQF_FDCNT_0 0x00269BAC
+#define I40E_GLQF_CTL_IGNORE_IP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_IGNORE_IP_SHIFT)
+#define I40E_GLQF_FDCNT_0 0x00269BAC /* Reset: CORER */
 #define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0
-#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
 #define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13
-#define I40E_GLQF_FDCNT_0_BESTCNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
-#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */
+#define I40E_GLQF_FDCNT_0_BESTCNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
+#define I40E_GLQF_HKEY(_i) (0x00270140 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
+#define I40E_GLQF_HKEY_MAX_INDEX 12
+#define I40E_GLQF_HKEY_KEY_0_SHIFT 0
+#define I40E_GLQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_0_SHIFT)
+#define I40E_GLQF_HKEY_KEY_1_SHIFT 8
+#define I40E_GLQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_1_SHIFT)
+#define I40E_GLQF_HKEY_KEY_2_SHIFT 16
+#define I40E_GLQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_2_SHIFT)
+#define I40E_GLQF_HKEY_KEY_3_SHIFT 24
+#define I40E_GLQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_3_SHIFT)
+#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */ /* Reset: CORER */
 #define I40E_GLQF_HSYM_MAX_INDEX 63
 #define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0
-#define I40E_GLQF_HSYM_SYMH_ENA_MASK (0x1 << I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
-#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */
+#define I40E_GLQF_HSYM_SYMH_ENA_MASK I40E_MASK(0x1, I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
+#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_GLQF_PCNT_MAX_INDEX 511
 #define I40E_GLQF_PCNT_PCNT_SHIFT 0
-#define I40E_GLQF_PCNT_PCNT_MASK (0xFFFFFFFF << I40E_GLQF_PCNT_PCNT_SHIFT)
-#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */
+#define I40E_GLQF_PCNT_PCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLQF_PCNT_PCNT_SHIFT)
+#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */ /* Reset: CORER */
 #define I40E_GLQF_SWAP_MAX_INDEX 1
 #define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0
-#define I40E_GLQF_SWAP_OFF0_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
 #define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6
-#define I40E_GLQF_SWAP_OFF0_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
 #define I40E_GLQF_SWAP_FLEN0_SHIFT 12
-#define I40E_GLQF_SWAP_FLEN0_MASK (0xF << I40E_GLQF_SWAP_FLEN0_SHIFT)
+#define I40E_GLQF_SWAP_FLEN0_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN0_SHIFT)
 #define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16
-#define I40E_GLQF_SWAP_OFF1_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
 #define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22
-#define I40E_GLQF_SWAP_OFF1_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
 #define I40E_GLQF_SWAP_FLEN1_SHIFT 28
-#define I40E_GLQF_SWAP_FLEN1_MASK (0xF << I40E_GLQF_SWAP_FLEN1_SHIFT)
-#define I40E_PFQF_CTL_0 0x001C0AC0
+#define I40E_GLQF_SWAP_FLEN1_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN1_SHIFT)
+#define I40E_PFQF_CTL_0 0x001C0AC0 /* Reset: CORER */
 #define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0
-#define I40E_PFQF_CTL_0_PEHSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEHSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5
-#define I40E_PFQF_CTL_0_PEDSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEDSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10
-#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14
-#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16
-#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK (0x1 << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17
-#define I40E_PFQF_CTL_0_FD_ENA_MASK (0x1 << I40E_PFQF_CTL_0_FD_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_FD_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_FD_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18
-#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK (0x1 << I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19
-#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK (0x1 << I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20
-#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24
-#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
-#define I40E_PFQF_CTL_1 0x00245D80
+#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_1 0x00245D80 /* Reset: CORER */
 #define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0
-#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK (0x1 << I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
-#define I40E_PFQF_FDALLOC 0x00246280
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
+#define I40E_PFQF_FDALLOC 0x00246280 /* Reset: CORER */
 #define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0
-#define I40E_PFQF_FDALLOC_FDALLOC_MASK (0xFF << I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
+#define I40E_PFQF_FDALLOC_FDALLOC_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
 #define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8
-#define I40E_PFQF_FDALLOC_FDBEST_MASK (0xFF << I40E_PFQF_FDALLOC_FDBEST_SHIFT)
-#define I40E_PFQF_FDSTAT 0x00246380
+#define I40E_PFQF_FDALLOC_FDBEST_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDBEST_SHIFT)
+#define I40E_PFQF_FDSTAT 0x00246380 /* Reset: CORER */
 #define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0
-#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
 #define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16
-#define I40E_PFQF_FDSTAT_BEST_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
-#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */
+#define I40E_PFQF_FDSTAT_BEST_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
+#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */ /* Reset: CORER */
 #define I40E_PFQF_HENA_MAX_INDEX 1
 #define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_PFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */
+#define I40E_PFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */ /* Reset: CORER */
 #define I40E_PFQF_HKEY_MAX_INDEX 12
 #define I40E_PFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_PFQF_HKEY_KEY_0_MASK (0xFF << I40E_PFQF_HKEY_KEY_0_SHIFT)
+#define I40E_PFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_0_SHIFT)
 #define I40E_PFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_PFQF_HKEY_KEY_1_MASK (0xFF << I40E_PFQF_HKEY_KEY_1_SHIFT)
+#define I40E_PFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_1_SHIFT)
 #define I40E_PFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_PFQF_HKEY_KEY_2_MASK (0xFF << I40E_PFQF_HKEY_KEY_2_SHIFT)
+#define I40E_PFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_2_SHIFT)
 #define I40E_PFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_PFQF_HKEY_KEY_3_MASK (0xFF << I40E_PFQF_HKEY_KEY_3_SHIFT)
-#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */
+#define I40E_PFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_3_SHIFT)
+#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_PFQF_HLUT_MAX_INDEX 127
 #define I40E_PFQF_HLUT_LUT0_SHIFT 0
-#define I40E_PFQF_HLUT_LUT0_MASK (0x3F << I40E_PFQF_HLUT_LUT0_SHIFT)
+#define I40E_PFQF_HLUT_LUT0_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT0_SHIFT)
 #define I40E_PFQF_HLUT_LUT1_SHIFT 8
-#define I40E_PFQF_HLUT_LUT1_MASK (0x3F << I40E_PFQF_HLUT_LUT1_SHIFT)
+#define I40E_PFQF_HLUT_LUT1_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT1_SHIFT)
 #define I40E_PFQF_HLUT_LUT2_SHIFT 16
-#define I40E_PFQF_HLUT_LUT2_MASK (0x3F << I40E_PFQF_HLUT_LUT2_SHIFT)
+#define I40E_PFQF_HLUT_LUT2_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT2_SHIFT)
 #define I40E_PFQF_HLUT_LUT3_SHIFT 24
-#define I40E_PFQF_HLUT_LUT3_MASK (0x3F << I40E_PFQF_HLUT_LUT3_SHIFT)
-#define I40E_PFQF_HREGION(_i) (0x00245400 + ((_i) * 128)) /* _i=0...7 */
-#define I40E_PFQF_HREGION_MAX_INDEX 7
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
-#define I40E_PFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_PFQF_HREGION_REGION_0_MASK (0x7 << I40E_PFQF_HREGION_REGION_0_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
-#define I40E_PFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_PFQF_HREGION_REGION_1_MASK (0x7 << I40E_PFQF_HREGION_REGION_1_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
-#define I40E_PFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_PFQF_HREGION_REGION_2_MASK (0x7 << I40E_PFQF_HREGION_REGION_2_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
-#define I40E_PFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_PFQF_HREGION_REGION_3_MASK (0x7 << I40E_PFQF_HREGION_REGION_3_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
-#define I40E_PFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_PFQF_HREGION_REGION_4_MASK (0x7 << I40E_PFQF_HREGION_REGION_4_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
-#define I40E_PFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_PFQF_HREGION_REGION_5_MASK (0x7 << I40E_PFQF_HREGION_REGION_5_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
-#define I40E_PFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_PFQF_HREGION_REGION_6_MASK (0x7 << I40E_PFQF_HREGION_REGION_6_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
-#define I40E_PFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_PFQF_HREGION_REGION_7_MASK (0x7 << I40E_PFQF_HREGION_REGION_7_SHIFT)
-#define I40E_PRTQF_CTL_0 0x00256E60
+#define I40E_PFQF_HLUT_LUT3_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT3_SHIFT)
+#define I40E_PRTQF_CTL_0 0x00256E60 /* Reset: CORER */
 #define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0
-#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK (0x1 << I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
-#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */
+#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK I40E_MASK(0x1, I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
+#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */ /* Reset: CORER */
 #define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63
 #define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0
-#define I40E_PRTQF_FD_FLXINSET_INSET_MASK (0xFF << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
-#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */
+#define I40E_PRTQF_FD_FLXINSET_INSET_MASK I40E_MASK(0xFF, I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
+#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */ /* Reset: CORER */
 #define I40E_PRTQF_FD_MSK_MAX_INDEX 63
 #define I40E_PRTQF_FD_MSK_MASK_SHIFT 0
-#define I40E_PRTQF_FD_MSK_MASK_MASK (0xFFFF << I40E_PRTQF_FD_MSK_MASK_SHIFT)
+#define I40E_PRTQF_FD_MSK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRTQF_FD_MSK_MASK_SHIFT)
 #define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16
-#define I40E_PRTQF_FD_MSK_OFFSET_MASK (0x3F << I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
-#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
+#define I40E_PRTQF_FD_MSK_OFFSET_MASK I40E_MASK(0x3F, I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
+#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ /* Reset: CORER */
 #define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
-#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
 #define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
-#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
 #define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
-#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
-#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK I40E_MASK(0x3F, I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
+#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...1, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HENA1_MAX_INDEX 1
 #define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA1_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */
+#define I40E_VFQF_HENA1_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HKEY1_MAX_INDEX 12
 #define I40E_VFQF_HKEY1_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY1_KEY_0_MASK (0xFF << I40E_VFQF_HKEY1_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_0_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY1_KEY_1_MASK (0xFF << I40E_VFQF_HKEY1_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_1_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY1_KEY_2_MASK (0xFF << I40E_VFQF_HKEY1_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_2_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY1_KEY_3_MASK (0xFF << I40E_VFQF_HKEY1_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VFQF_HKEY1_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HLUT1_MAX_INDEX 15
 #define I40E_VFQF_HLUT1_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT1_LUT0_MASK (0xF << I40E_VFQF_HLUT1_LUT0_SHIFT)
+#define I40E_VFQF_HLUT1_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT0_SHIFT)
 #define I40E_VFQF_HLUT1_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT1_LUT1_MASK (0xF << I40E_VFQF_HLUT1_LUT1_SHIFT)
+#define I40E_VFQF_HLUT1_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT1_SHIFT)
 #define I40E_VFQF_HLUT1_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT1_LUT2_MASK (0xF << I40E_VFQF_HLUT1_LUT2_SHIFT)
+#define I40E_VFQF_HLUT1_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT2_SHIFT)
 #define I40E_VFQF_HLUT1_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT1_LUT3_MASK (0xF << I40E_VFQF_HLUT1_LUT3_SHIFT)
-#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HLUT1_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT3_SHIFT)
+#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...7, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HREGION1_MAX_INDEX 7
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION1_REGION_0_MASK (0x7 << I40E_VFQF_HREGION1_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_0_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION1_REGION_1_MASK (0x7 << I40E_VFQF_HREGION1_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_1_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION1_REGION_2_MASK (0x7 << I40E_VFQF_HREGION1_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_2_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION1_REGION_3_MASK (0x7 << I40E_VFQF_HREGION1_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_3_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION1_REGION_4_MASK (0x7 << I40E_VFQF_HREGION1_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_4_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION1_REGION_5_MASK (0x7 << I40E_VFQF_HREGION1_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_5_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION1_REGION_6_MASK (0x7 << I40E_VFQF_HREGION1_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_6_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION1_REGION_7_MASK (0x7 << I40E_VFQF_HREGION1_REGION_7_SHIFT)
-#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFQF_HREGION1_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_7_SHIFT)
+#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPQF_CTL_MAX_INDEX 127
 #define I40E_VPQF_CTL_PEHSIZE_SHIFT 0
-#define I40E_VPQF_CTL_PEHSIZE_MASK (0x1F << I40E_VPQF_CTL_PEHSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEHSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEHSIZE_SHIFT)
 #define I40E_VPQF_CTL_PEDSIZE_SHIFT 5
-#define I40E_VPQF_CTL_PEDSIZE_MASK (0x1F << I40E_VPQF_CTL_PEDSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEDSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEDSIZE_SHIFT)
 #define I40E_VPQF_CTL_FCHSIZE_SHIFT 10
-#define I40E_VPQF_CTL_FCHSIZE_MASK (0xF << I40E_VPQF_CTL_FCHSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCHSIZE_MASK I40E_MASK(0xF, I40E_VPQF_CTL_FCHSIZE_SHIFT)
 #define I40E_VPQF_CTL_FCDSIZE_SHIFT 14
-#define I40E_VPQF_CTL_FCDSIZE_MASK (0x3 << I40E_VPQF_CTL_FCDSIZE_SHIFT)
-#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPQF_CTL_FCDSIZE_MASK I40E_MASK(0x3, I40E_VPQF_CTL_FCDSIZE_SHIFT)
+#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
 #define I40E_VSIQF_CTL_MAX_INDEX 383
 #define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0
-#define I40E_VSIQF_CTL_FCOE_ENA_MASK (0x1 << I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
+#define I40E_VSIQF_CTL_FCOE_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1
-#define I40E_VSIQF_CTL_PETCP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PETCP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2
-#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3
-#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4
-#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
-#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
-#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
+#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...3, _VSI=0...383 */ /* Reset: PFR */
 #define I40E_VSIQF_TCREGION_MAX_INDEX 3
 #define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
-#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
-#define I40E_VSIQF_TCREGION_TC_SIZE_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16
-#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25
-#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
-#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
+#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOECRC_MAX_INDEX 143
 #define I40E_GL_FCOECRC_FCOECRC_SHIFT 0
-#define I40E_GL_FCOECRC_FCOECRC_MASK (0xFFFFFFFF << I40E_GL_FCOECRC_FCOECRC_SHIFT)
-#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOECRC_FCOECRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOECRC_FCOECRC_SHIFT)
+#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDDPC_MAX_INDEX 143
 #define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
-#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
-/* _i=0...143 */
-#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
+#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIFEC_MAX_INDEX 143
 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFRC(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIFRC_MAX_INDEX 143
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIFTCL_MAX_INDEX 143
 #define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0
-#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
-#define I40E_GL_FCOEDIXAC(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIXAC_MAX_INDEX 143
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT 0
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT)
-#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
+#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIXEC_MAX_INDEX 143
 #define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0
-#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
-#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
+#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIXVC_MAX_INDEX 143
 #define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0
-#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
-#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
+#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWRCH_MAX_INDEX 143
 #define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0
-#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK (0xFFFF << I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
-#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
+#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWRCL_MAX_INDEX 143
 #define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0
-#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
-#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
+#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWTCH_MAX_INDEX 143
 #define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0
-#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK (0xFFFF << I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
-#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
+#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWTCL_MAX_INDEX 143
 #define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0
-#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
-#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
+#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOELAST_MAX_INDEX 143
 #define I40E_GL_FCOELAST_FCOELAST_SHIFT 0
-#define I40E_GL_FCOELAST_FCOELAST_MASK (0xFFFFFFFF << I40E_GL_FCOELAST_FCOELAST_SHIFT)
-#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOELAST_FCOELAST_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOELAST_FCOELAST_SHIFT)
+#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEPRC_MAX_INDEX 143
 #define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0
-#define I40E_GL_FCOEPRC_FCOEPRC_MASK (0xFFFFFFFF << I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
-#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPRC_FCOEPRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
+#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEPTC_MAX_INDEX 143
 #define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0
-#define I40E_GL_FCOEPTC_FCOEPTC_MASK (0xFFFFFFFF << I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
-#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPTC_FCOEPTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
+#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOERPDC_MAX_INDEX 143
 #define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
-#define I40E_GL_FCOERPDC_FCOERPDC_MASK (0xFFFFFFFF << I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
-#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GL_FCOERPDC_FCOERPDC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
+#define I40E_GL_RXERR1_L(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1_L_MAX_INDEX 143
+#define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0
+#define I40E_GL_RXERR1_L_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT)
+#define I40E_GL_RXERR2_L(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR2_L_MAX_INDEX 143
+#define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0
+#define I40E_GL_RXERR2_L_FCOEDIXAC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT)
+#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPRCH_MAX_INDEX 3
 #define I40E_GLPRT_BPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPRCL_MAX_INDEX 3
 #define I40E_GLPRT_BPRCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPRCL_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPRCL_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPTCH_MAX_INDEX 3
 #define I40E_GLPRT_BPTCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPTCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPTCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPTCL_MAX_INDEX 3
 #define I40E_GLPRT_BPTCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPTCL_UPRCH_SHIFT)
-#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPTCL_UPRCH_SHIFT)
+#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_CRCERRS_MAX_INDEX 3
 #define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0
-#define I40E_GLPRT_CRCERRS_CRCERRS_MASK (0xFFFFFFFF << I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
-#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_CRCERRS_CRCERRS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
+#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GORCH_MAX_INDEX 3
 #define I40E_GLPRT_GORCH_GORCH_SHIFT 0
-#define I40E_GLPRT_GORCH_GORCH_MASK (0xFFFF << I40E_GLPRT_GORCH_GORCH_SHIFT)
-#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GORCH_GORCH_SHIFT)
+#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GORCL_MAX_INDEX 3
 #define I40E_GLPRT_GORCL_GORCL_SHIFT 0
-#define I40E_GLPRT_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLPRT_GORCL_GORCL_SHIFT)
-#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GORCL_GORCL_SHIFT)
+#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GOTCH_MAX_INDEX 3
 #define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLPRT_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLPRT_GOTCH_GOTCH_SHIFT)
-#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GOTCH_GOTCH_SHIFT)
+#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GOTCL_MAX_INDEX 3
 #define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLPRT_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLPRT_GOTCL_GOTCL_SHIFT)
-#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GOTCL_GOTCL_SHIFT)
+#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_ILLERRC_MAX_INDEX 3
 #define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0
-#define I40E_GLPRT_ILLERRC_ILLERRC_MASK (0xFFFFFFFF << I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
-#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ILLERRC_ILLERRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
+#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LDPC_MAX_INDEX 3
 #define I40E_GLPRT_LDPC_LDPC_SHIFT 0
-#define I40E_GLPRT_LDPC_LDPC_MASK (0xFFFFFFFF << I40E_GLPRT_LDPC_LDPC_SHIFT)
-#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LDPC_LDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LDPC_LDPC_SHIFT)
+#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3
 #define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3
 #define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0
-#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
-#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
+#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXONRXC_MAX_INDEX 3
 #define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0
-#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
-#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
+#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXONTXC_MAX_INDEX 3
 #define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0
-#define I40E_GLPRT_LXONTXC_LXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
-#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONTXC_LXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
+#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MLFC_MAX_INDEX 3
 #define I40E_GLPRT_MLFC_MLFC_SHIFT 0
-#define I40E_GLPRT_MLFC_MLFC_MASK (0xFFFFFFFF << I40E_GLPRT_MLFC_MLFC_SHIFT)
-#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MLFC_MLFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MLFC_MLFC_SHIFT)
+#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPRCH_MAX_INDEX 3
 #define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLPRT_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLPRT_MPRCH_MPRCH_SHIFT)
-#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPRCH_MPRCH_SHIFT)
+#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPRCL_MAX_INDEX 3
 #define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLPRT_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPRCL_MPRCL_SHIFT)
-#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPRCL_MPRCL_SHIFT)
+#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPTCH_MAX_INDEX 3
 #define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLPRT_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLPRT_MPTCH_MPTCH_SHIFT)
-#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPTCH_MPTCH_SHIFT)
+#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPTCL_MAX_INDEX 3
 #define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLPRT_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPTCL_MPTCL_SHIFT)
-#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPTCL_MPTCL_SHIFT)
+#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MRFC_MAX_INDEX 3
 #define I40E_GLPRT_MRFC_MRFC_SHIFT 0
-#define I40E_GLPRT_MRFC_MRFC_MASK (0xFFFFFFFF << I40E_GLPRT_MRFC_MRFC_SHIFT)
-#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MRFC_MRFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MRFC_MRFC_SHIFT)
+#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1023H_MAX_INDEX 3
 #define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0
-#define I40E_GLPRT_PRC1023H_PRC1023H_MASK (0xFFFF << I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
-#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023H_PRC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
+#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1023L_MAX_INDEX 3
 #define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0
-#define I40E_GLPRT_PRC1023L_PRC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
-#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023L_PRC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
+#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC127H_MAX_INDEX 3
 #define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0
-#define I40E_GLPRT_PRC127H_PRC127H_MASK (0xFFFF << I40E_GLPRT_PRC127H_PRC127H_SHIFT)
-#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127H_PRC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC127H_PRC127H_SHIFT)
+#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC127L_MAX_INDEX 3
 #define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0
-#define I40E_GLPRT_PRC127L_PRC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC127L_PRC127L_SHIFT)
-#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127L_PRC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC127L_PRC127L_SHIFT)
+#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1522H_MAX_INDEX 3
 #define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC1522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1522L_MAX_INDEX 3
 #define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC1522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC255H_MAX_INDEX 3
 #define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0
-#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK (0xFFFF << I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
-#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
+#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC255L_MAX_INDEX 3
 #define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0
-#define I40E_GLPRT_PRC255L_PRC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC255L_PRC255L_SHIFT)
-#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255L_PRC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC255L_PRC255L_SHIFT)
+#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC511H_MAX_INDEX 3
 #define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0
-#define I40E_GLPRT_PRC511H_PRC511H_MASK (0xFFFF << I40E_GLPRT_PRC511H_PRC511H_SHIFT)
-#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511H_PRC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC511H_PRC511H_SHIFT)
+#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC511L_MAX_INDEX 3
 #define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0
-#define I40E_GLPRT_PRC511L_PRC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC511L_PRC511L_SHIFT)
-#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511L_PRC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC511L_PRC511L_SHIFT)
+#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC64H_MAX_INDEX 3
 #define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0
-#define I40E_GLPRT_PRC64H_PRC64H_MASK (0xFFFF << I40E_GLPRT_PRC64H_PRC64H_SHIFT)
-#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64H_PRC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC64H_PRC64H_SHIFT)
+#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC64L_MAX_INDEX 3
 #define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0
-#define I40E_GLPRT_PRC64L_PRC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC64L_PRC64L_SHIFT)
-#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64L_PRC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC64L_PRC64L_SHIFT)
+#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC9522H_MAX_INDEX 3
 #define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC9522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC9522L_MAX_INDEX 3
 #define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC9522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1023H_MAX_INDEX 3
 #define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0
-#define I40E_GLPRT_PTC1023H_PTC1023H_MASK (0xFFFF << I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
-#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023H_PTC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
+#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1023L_MAX_INDEX 3
 #define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0
-#define I40E_GLPRT_PTC1023L_PTC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
-#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023L_PTC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
+#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC127H_MAX_INDEX 3
 #define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0
-#define I40E_GLPRT_PTC127H_PTC127H_MASK (0xFFFF << I40E_GLPRT_PTC127H_PTC127H_SHIFT)
-#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127H_PTC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC127H_PTC127H_SHIFT)
+#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC127L_MAX_INDEX 3
 #define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0
-#define I40E_GLPRT_PTC127L_PTC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC127L_PTC127L_SHIFT)
-#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127L_PTC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC127L_PTC127L_SHIFT)
+#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1522H_MAX_INDEX 3
 #define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0
-#define I40E_GLPRT_PTC1522H_PTC1522H_MASK (0xFFFF << I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
-#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522H_PTC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
+#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1522L_MAX_INDEX 3
 #define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0
-#define I40E_GLPRT_PTC1522L_PTC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
-#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522L_PTC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
+#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC255H_MAX_INDEX 3
 #define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0
-#define I40E_GLPRT_PTC255H_PTC255H_MASK (0xFFFF << I40E_GLPRT_PTC255H_PTC255H_SHIFT)
-#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255H_PTC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC255H_PTC255H_SHIFT)
+#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC255L_MAX_INDEX 3
 #define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0
-#define I40E_GLPRT_PTC255L_PTC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC255L_PTC255L_SHIFT)
-#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255L_PTC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC255L_PTC255L_SHIFT)
+#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC511H_MAX_INDEX 3
 #define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0
-#define I40E_GLPRT_PTC511H_PTC511H_MASK (0xFFFF << I40E_GLPRT_PTC511H_PTC511H_SHIFT)
-#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511H_PTC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC511H_PTC511H_SHIFT)
+#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC511L_MAX_INDEX 3
 #define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0
-#define I40E_GLPRT_PTC511L_PTC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC511L_PTC511L_SHIFT)
-#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511L_PTC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC511L_PTC511L_SHIFT)
+#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC64H_MAX_INDEX 3
 #define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0
-#define I40E_GLPRT_PTC64H_PTC64H_MASK (0xFFFF << I40E_GLPRT_PTC64H_PTC64H_SHIFT)
-#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64H_PTC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC64H_PTC64H_SHIFT)
+#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC64L_MAX_INDEX 3
 #define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0
-#define I40E_GLPRT_PTC64L_PTC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC64L_PTC64L_SHIFT)
-#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64L_PTC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC64L_PTC64L_SHIFT)
+#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC9522H_MAX_INDEX 3
 #define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0
-#define I40E_GLPRT_PTC9522H_PTC9522H_MASK (0xFFFF << I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
-#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522H_PTC9522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
+#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC9522L_MAX_INDEX 3
 #define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0
-#define I40E_GLPRT_PTC9522L_PTC9522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
-#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PTC9522L_PTC9522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
+#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3
 #define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3
 #define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
-#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
+#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXONRXC_MAX_INDEX 3
 #define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0
-#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
-#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
+#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXONTXC_MAX_INDEX 3
 #define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0
-#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
-#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
+#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RDPC_MAX_INDEX 3
 #define I40E_GLPRT_RDPC_RDPC_SHIFT 0
-#define I40E_GLPRT_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLPRT_RDPC_RDPC_SHIFT)
-#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RDPC_RDPC_SHIFT)
+#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RFC_MAX_INDEX 3
 #define I40E_GLPRT_RFC_RFC_SHIFT 0
-#define I40E_GLPRT_RFC_RFC_MASK (0xFFFFFFFF << I40E_GLPRT_RFC_RFC_SHIFT)
-#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RFC_RFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RFC_RFC_SHIFT)
+#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RJC_MAX_INDEX 3
 #define I40E_GLPRT_RJC_RJC_SHIFT 0
-#define I40E_GLPRT_RJC_RJC_MASK (0xFFFFFFFF << I40E_GLPRT_RJC_RJC_SHIFT)
-#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RJC_RJC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RJC_RJC_SHIFT)
+#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RLEC_MAX_INDEX 3
 #define I40E_GLPRT_RLEC_RLEC_SHIFT 0
-#define I40E_GLPRT_RLEC_RLEC_MASK (0xFFFFFFFF << I40E_GLPRT_RLEC_RLEC_SHIFT)
-#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RLEC_RLEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RLEC_RLEC_SHIFT)
+#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_ROC_MAX_INDEX 3
 #define I40E_GLPRT_ROC_ROC_SHIFT 0
-#define I40E_GLPRT_ROC_ROC_MASK (0xFFFFFFFF << I40E_GLPRT_ROC_ROC_SHIFT)
-#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ROC_ROC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ROC_ROC_SHIFT)
+#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RUC_MAX_INDEX 3
 #define I40E_GLPRT_RUC_RUC_SHIFT 0
-#define I40E_GLPRT_RUC_RUC_MASK (0xFFFFFFFF << I40E_GLPRT_RUC_RUC_SHIFT)
-#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUC_RUC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUC_RUC_SHIFT)
+#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RUPP_MAX_INDEX 3
 #define I40E_GLPRT_RUPP_RUPP_SHIFT 0
-#define I40E_GLPRT_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLPRT_RUPP_RUPP_SHIFT)
-#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUPP_RUPP_SHIFT)
+#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3
 #define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0
-#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK (0xFFFFFFFF << I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
-#define I40E_GLPRT_STDC(_i) (0x00300640 + ((_i) * 8)) /* _i=0...3 */
-#define I40E_GLPRT_STDC_MAX_INDEX 3
-#define I40E_GLPRT_STDC_STDC_SHIFT 0
-#define I40E_GLPRT_STDC_STDC_MASK (0xFFFFFFFF << I40E_GLPRT_STDC_STDC_SHIFT)
-#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
+#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_TDOLD_MAX_INDEX 3
 #define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0
-#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK (0xFFFFFFFF << I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
-#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
+#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_TDPC_MAX_INDEX 3
 #define I40E_GLPRT_TDPC_TDPC_SHIFT 0
-#define I40E_GLPRT_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLPRT_TDPC_TDPC_SHIFT)
-#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDPC_TDPC_SHIFT)
+#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPRCH_MAX_INDEX 3
 #define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_UPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPRCL_MAX_INDEX 3
 #define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLPRT_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_UPRCL_UPRCL_SHIFT)
-#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPRCL_UPRCL_SHIFT)
+#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPTCH_MAX_INDEX 3
 #define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLPRT_UPTCH_UPTCH_SHIFT)
-#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPTCH_UPTCH_SHIFT)
+#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPTCL_MAX_INDEX 3
 #define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCL_VUPTCH_MASK (0xFFFFFFFF << I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
-#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPRT_UPTCL_VUPTCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
+#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPRCH_MAX_INDEX 15
 #define I40E_GLSW_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLSW_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLSW_BPRCH_BPRCH_SHIFT)
-#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPRCH_BPRCH_SHIFT)
+#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPRCL_MAX_INDEX 15
 #define I40E_GLSW_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLSW_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLSW_BPRCL_BPRCL_SHIFT)
-#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPRCL_BPRCL_SHIFT)
+#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPTCH_MAX_INDEX 15
 #define I40E_GLSW_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLSW_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLSW_BPTCH_BPTCH_SHIFT)
-#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPTCH_BPTCH_SHIFT)
+#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPTCL_MAX_INDEX 15
 #define I40E_GLSW_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLSW_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLSW_BPTCL_BPTCL_SHIFT)
-#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPTCL_BPTCL_SHIFT)
+#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GORCH_MAX_INDEX 15
 #define I40E_GLSW_GORCH_GORCH_SHIFT 0
-#define I40E_GLSW_GORCH_GORCH_MASK (0xFFFF << I40E_GLSW_GORCH_GORCH_SHIFT)
-#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GORCH_GORCH_SHIFT)
+#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GORCL_MAX_INDEX 15
 #define I40E_GLSW_GORCL_GORCL_SHIFT 0
-#define I40E_GLSW_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLSW_GORCL_GORCL_SHIFT)
-#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GORCL_GORCL_SHIFT)
+#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GOTCH_MAX_INDEX 15
 #define I40E_GLSW_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLSW_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLSW_GOTCH_GOTCH_SHIFT)
-#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GOTCH_GOTCH_SHIFT)
+#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GOTCL_MAX_INDEX 15
 #define I40E_GLSW_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLSW_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLSW_GOTCL_GOTCL_SHIFT)
-#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GOTCL_GOTCL_SHIFT)
+#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPRCH_MAX_INDEX 15
 #define I40E_GLSW_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLSW_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLSW_MPRCH_MPRCH_SHIFT)
-#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPRCH_MPRCH_SHIFT)
+#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPRCL_MAX_INDEX 15
 #define I40E_GLSW_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLSW_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLSW_MPRCL_MPRCL_SHIFT)
-#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPRCL_MPRCL_SHIFT)
+#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPTCH_MAX_INDEX 15
 #define I40E_GLSW_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLSW_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLSW_MPTCH_MPTCH_SHIFT)
-#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPTCH_MPTCH_SHIFT)
+#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPTCL_MAX_INDEX 15
 #define I40E_GLSW_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLSW_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLSW_MPTCL_MPTCL_SHIFT)
-#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPTCL_MPTCL_SHIFT)
+#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_RUPP_MAX_INDEX 15
 #define I40E_GLSW_RUPP_RUPP_SHIFT 0
-#define I40E_GLSW_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLSW_RUPP_RUPP_SHIFT)
-#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_RUPP_RUPP_SHIFT)
+#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_TDPC_MAX_INDEX 15
 #define I40E_GLSW_TDPC_TDPC_SHIFT 0
-#define I40E_GLSW_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLSW_TDPC_TDPC_SHIFT)
-#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_TDPC_TDPC_SHIFT)
+#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPRCH_MAX_INDEX 15
 #define I40E_GLSW_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLSW_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLSW_UPRCH_UPRCH_SHIFT)
-#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPRCH_UPRCH_SHIFT)
+#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPRCL_MAX_INDEX 15
 #define I40E_GLSW_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLSW_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLSW_UPRCL_UPRCL_SHIFT)
-#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPRCL_UPRCL_SHIFT)
+#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPTCH_MAX_INDEX 15
 #define I40E_GLSW_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLSW_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLSW_UPTCH_UPTCH_SHIFT)
-#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPTCH_UPTCH_SHIFT)
+#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPTCL_MAX_INDEX 15
 #define I40E_GLSW_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLSW_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLSW_UPTCL_UPTCL_SHIFT)
-#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLSW_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPTCL_UPTCL_SHIFT)
+#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPRCH_MAX_INDEX 383
 #define I40E_GLV_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLV_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLV_BPRCH_BPRCH_SHIFT)
-#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPRCH_BPRCH_SHIFT)
+#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPRCL_MAX_INDEX 383
 #define I40E_GLV_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLV_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLV_BPRCL_BPRCL_SHIFT)
-#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPRCL_BPRCL_SHIFT)
+#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPTCH_MAX_INDEX 383
 #define I40E_GLV_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLV_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLV_BPTCH_BPTCH_SHIFT)
-#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPTCH_BPTCH_SHIFT)
+#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPTCL_MAX_INDEX 383
 #define I40E_GLV_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLV_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLV_BPTCL_BPTCL_SHIFT)
-#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPTCL_BPTCL_SHIFT)
+#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GORCH_MAX_INDEX 383
 #define I40E_GLV_GORCH_GORCH_SHIFT 0
-#define I40E_GLV_GORCH_GORCH_MASK (0xFFFF << I40E_GLV_GORCH_GORCH_SHIFT)
-#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GORCH_GORCH_SHIFT)
+#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GORCL_MAX_INDEX 383
 #define I40E_GLV_GORCL_GORCL_SHIFT 0
-#define I40E_GLV_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLV_GORCL_GORCL_SHIFT)
-#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GORCL_GORCL_SHIFT)
+#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GOTCH_MAX_INDEX 383
 #define I40E_GLV_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLV_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLV_GOTCH_GOTCH_SHIFT)
-#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GOTCH_GOTCH_SHIFT)
+#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GOTCL_MAX_INDEX 383
 #define I40E_GLV_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLV_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLV_GOTCL_GOTCL_SHIFT)
-#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GOTCL_GOTCL_SHIFT)
+#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPRCH_MAX_INDEX 383
 #define I40E_GLV_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLV_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLV_MPRCH_MPRCH_SHIFT)
-#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPRCH_MPRCH_SHIFT)
+#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPRCL_MAX_INDEX 383
 #define I40E_GLV_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLV_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLV_MPRCL_MPRCL_SHIFT)
-#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPRCL_MPRCL_SHIFT)
+#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPTCH_MAX_INDEX 383
 #define I40E_GLV_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLV_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLV_MPTCH_MPTCH_SHIFT)
-#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPTCH_MPTCH_SHIFT)
+#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPTCL_MAX_INDEX 383
 #define I40E_GLV_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLV_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLV_MPTCL_MPTCL_SHIFT)
-#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPTCL_MPTCL_SHIFT)
+#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_RDPC_MAX_INDEX 383
 #define I40E_GLV_RDPC_RDPC_SHIFT 0
-#define I40E_GLV_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLV_RDPC_RDPC_SHIFT)
-#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RDPC_RDPC_SHIFT)
+#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_RUPP_MAX_INDEX 383
 #define I40E_GLV_RUPP_RUPP_SHIFT 0
-#define I40E_GLV_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLV_RUPP_RUPP_SHIFT)
-#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 8)) /* _i=0...383 */
+#define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT)
+#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_TEPC_MAX_INDEX 383
 #define I40E_GLV_TEPC_TEPC_SHIFT 0
-#define I40E_GLV_TEPC_TEPC_MASK (0xFFFFFFFF << I40E_GLV_TEPC_TEPC_SHIFT)
-#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT)
+#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPRCH_MAX_INDEX 383
 #define I40E_GLV_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLV_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLV_UPRCH_UPRCH_SHIFT)
-#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPRCH_UPRCH_SHIFT)
+#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPRCL_MAX_INDEX 383
 #define I40E_GLV_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLV_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLV_UPRCL_UPRCL_SHIFT)
-#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPRCL_UPRCL_SHIFT)
+#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPTCH_MAX_INDEX 383
 #define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0
-#define I40E_GLV_UPTCH_GLVUPTCH_MASK (0xFFFF << I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
-#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCH_GLVUPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
+#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPTCL_MAX_INDEX 383
 #define I40E_GLV_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLV_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLV_UPTCL_UPTCL_SHIFT)
-#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLV_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPTCL_UPTCL_SHIFT)
+#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RBCH_MAX_INDEX 7
 #define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_RBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RBCL_MAX_INDEX 7
 #define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_RBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RPCH_MAX_INDEX 7
 #define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_RPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RPCL_MAX_INDEX 7
 #define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_RPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
-#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
+#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TBCH_MAX_INDEX 7
 #define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_TBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TBCL_MAX_INDEX 7
 #define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_TBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TPCH_MAX_INDEX 7
 #define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_TPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TPCL_MAX_INDEX 7
 #define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_TPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
-#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBTC_TPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
+#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_BPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0
-#define I40E_GLVEBVL_BPCH_VLBPCH_MASK (0xFFFF << I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
-#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCH_VLBPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
+#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_BPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0
-#define I40E_GLVEBVL_BPCL_VLBPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
-#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCL_VLBPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
+#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GORCH_MAX_INDEX 127
 #define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GORCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GORCL_MAX_INDEX 127
 #define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GORCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GOTCH_MAX_INDEX 127
 #define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GOTCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GOTCL_MAX_INDEX 127
 #define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GOTCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_MPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0
-#define I40E_GLVEBVL_MPCH_VLMPCH_MASK (0xFFFF << I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
-#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCH_VLMPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
+#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_MPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0
-#define I40E_GLVEBVL_MPCL_VLMPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
-#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCL_VLMPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
+#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_UPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0
-#define I40E_GLVEBVL_UPCH_VLUPCH_MASK (0xFFFF << I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
-#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCH_VLUPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
+#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_UPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0
-#define I40E_GLVEBVL_UPCL_VLUPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C
+#define I40E_GLVEBVL_UPCL_VLUPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C /* Reset: CORER */
 #define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK (0xFFFF << I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_L 0x00269F44
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_MASK (0xFFFFFFFF << I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT)
-#define I40E_GL_SWR_DEF_ACT(_i) (0x0026CF00 + ((_i) * 4)) /* _i=0...25 */
-#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 25
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK I40E_MASK(0xFFFF, I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
+#define I40E_GL_SWR_DEF_ACT(_i) (0x00270200 + ((_i) * 4)) /* _i=0...35 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 35
 #define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
-#define I40E_GL_SWR_DEF_ACT_EN 0x0026CF84
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
+#define I40E_GL_SWR_DEF_ACT_EN(_i) (0x0026CFB8 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_EN_MAX_INDEX 1
 #define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
-#define I40E_PRT_MSCCNT 0x00256BA0
-#define I40E_PRT_MSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_MSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_MSCCNT_CCOUNT_SHIFT)
-#define I40E_PRT_SCSTS 0x00256C20
-#define I40E_PRT_SCSTS_BSCA_SHIFT 0
-#define I40E_PRT_SCSTS_BSCA_MASK (0x1 << I40E_PRT_SCSTS_BSCA_SHIFT)
-#define I40E_PRT_SCSTS_BSCAP_SHIFT 1
-#define I40E_PRT_SCSTS_BSCAP_MASK (0x1 << I40E_PRT_SCSTS_BSCAP_SHIFT)
-#define I40E_PRT_SCSTS_MSCA_SHIFT 2
-#define I40E_PRT_SCSTS_MSCA_MASK (0x1 << I40E_PRT_SCSTS_MSCA_SHIFT)
-#define I40E_PRT_SCSTS_MSCAP_SHIFT 3
-#define I40E_PRT_SCSTS_MSCAP_MASK (0x1 << I40E_PRT_SCSTS_MSCAP_SHIFT)
-#define I40E_PRT_SWT_BSCCNT 0x00256C60
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT)
-#define I40E_PRTTSYN_ADJ 0x001E4280
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
+#define I40E_PRTTSYN_ADJ 0x001E4280 /* Reset: GLOBR */
 #define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0
-#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK (0x7FFFFFFF << I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
+#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK I40E_MASK(0x7FFFFFFF, I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
 #define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31
-#define I40E_PRTTSYN_ADJ_SIGN_MASK (0x1 << I40E_PRTTSYN_ADJ_SIGN_SHIFT)
-#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_ADJ_SIGN_MASK I40E_MASK(0x1, I40E_PRTTSYN_ADJ_SIGN_SHIFT)
+#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_AUX_0_MAX_INDEX 1
 #define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0
-#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
 #define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1
-#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK (0x3 << I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
 #define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3
-#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
 #define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8
-#define I40E_PRTTSYN_AUX_0_PULSEW_MASK (0xF << I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
+#define I40E_PRTTSYN_AUX_0_PULSEW_MASK I40E_MASK(0xF, I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
 #define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16
-#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK (0x3 << I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
-#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_AUX_1_MAX_INDEX 1
 #define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0
-#define I40E_PRTTSYN_AUX_1_INSTNT_MASK (0x1 << I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
+#define I40E_PRTTSYN_AUX_1_INSTNT_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
 #define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1
-#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK (0x1 << I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
-#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
+#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_CLKO_MAX_INDEX 1
 #define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0
-#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK (0xFFFFFFFF << I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
-#define I40E_PRTTSYN_CTL0 0x001E4200
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
+#define I40E_PRTTSYN_CTL0 0x001E4200 /* Reset: GLOBR */
 #define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0
-#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK (0x1 << I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
 #define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1
-#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2
-#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3
-#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8
-#define I40E_PRTTSYN_CTL0_PF_ID_MASK (0xF << I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
+#define I40E_PRTTSYN_CTL0_PF_ID_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
 #define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12
-#define I40E_PRTTSYN_CTL0_TSYNACT_MASK (0x3 << I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNACT_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
 #define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL0_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_CTL1 0x00085020
+#define I40E_PRTTSYN_CTL0_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_CTL1 0x00085020 /* Reset: CORER */
 #define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
 #define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
 #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
 #define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
 #define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24
-#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK (0x3 << I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
 #define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26
-#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK (0x3 << I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL1_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1
 #define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0
-#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
-#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
+#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1
 #define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0
-#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
-#define I40E_PRTTSYN_INC_H 0x001E4060
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
+#define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */
 #define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0
-#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK (0x3F << I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
-#define I40E_PRTTSYN_INC_L 0x001E4040
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK I40E_MASK(0x3F, I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
+#define I40E_PRTTSYN_INC_L 0x001E4040 /* Reset: GLOBR */
 #define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0
-#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
-#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
+#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3
 #define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3
 #define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
-#define I40E_PRTTSYN_STAT_0 0x001E4220
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
+#define I40E_PRTTSYN_STAT_0 0x001E4220 /* Reset: GLOBR */
 #define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_0_EVENT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
 #define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_0_EVENT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2
-#define I40E_PRTTSYN_STAT_0_TGT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3
-#define I40E_PRTTSYN_STAT_0_TGT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4
-#define I40E_PRTTSYN_STAT_0_TXTIME_MASK (0x1 << I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
-#define I40E_PRTTSYN_STAT_1 0x00085140
+#define I40E_PRTTSYN_STAT_0_TXTIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
+#define I40E_PRTTSYN_STAT_1 0x00085140 /* Reset: CORER */
 #define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_1_RXT0_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_1_RXT1_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2
-#define I40E_PRTTSYN_STAT_1_RXT2_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT2_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3
-#define I40E_PRTTSYN_STAT_1_RXT3_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
-#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_STAT_1_RXT3_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
+#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_TGT_H_MAX_INDEX 1
 #define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0
-#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
-#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
+#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_TGT_L_MAX_INDEX 1
 #define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0
-#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
-#define I40E_PRTTSYN_TIME_H 0x001E4120
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
+#define I40E_PRTTSYN_TIME_H 0x001E4120 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0
-#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
-#define I40E_PRTTSYN_TIME_L 0x001E4100
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
+#define I40E_PRTTSYN_TIME_L 0x001E4100 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0
-#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
-#define I40E_PRTTSYN_TXTIME_H 0x001E41E0
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
+#define I40E_PRTTSYN_TXTIME_H 0x001E41E0 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_TXTIME_L 0x001E41C0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_TXTIME_L 0x001E41C0 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
-#define I40E_GLSCD_QUANTA 0x000B2080
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
+#define I40E_GLSCD_QUANTA 0x000B2080 /* Reset: CORER */
 #define I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT 0
-#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK (0x7 << I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
-#define I40E_GL_MDET_RX 0x0012A510
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK I40E_MASK(0x7, I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
+#define I40E_GL_MDET_RX 0x0012A510 /* Reset: CORER */
 #define I40E_GL_MDET_RX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_RX_FUNCTION_MASK (0xFF << I40E_GL_MDET_RX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_RX_FUNCTION_MASK I40E_MASK(0xFF, I40E_GL_MDET_RX_FUNCTION_SHIFT)
 #define I40E_GL_MDET_RX_EVENT_SHIFT 8
-#define I40E_GL_MDET_RX_EVENT_MASK (0x1FF << I40E_GL_MDET_RX_EVENT_SHIFT)
+#define I40E_GL_MDET_RX_EVENT_MASK I40E_MASK(0x1FF, I40E_GL_MDET_RX_EVENT_SHIFT)
 #define I40E_GL_MDET_RX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_RX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_RX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_QUEUE_MASK I40E_MASK(0x3FFF, I40E_GL_MDET_RX_QUEUE_SHIFT)
 #define I40E_GL_MDET_RX_VALID_SHIFT 31
-#define I40E_GL_MDET_RX_VALID_MASK (0x1 << I40E_GL_MDET_RX_VALID_SHIFT)
-#define I40E_GL_MDET_TX 0x000E6480
-#define I40E_GL_MDET_TX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_TX_FUNCTION_MASK (0xFF << I40E_GL_MDET_TX_FUNCTION_SHIFT)
-#define I40E_GL_MDET_TX_EVENT_SHIFT 8
-#define I40E_GL_MDET_TX_EVENT_MASK (0x1FF << I40E_GL_MDET_TX_EVENT_SHIFT)
-#define I40E_GL_MDET_TX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_TX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_RX_VALID_SHIFT)
+#define I40E_GL_MDET_TX 0x000E6480 /* Reset: CORER */
+#define I40E_GL_MDET_TX_QUEUE_SHIFT 0
+#define I40E_GL_MDET_TX_QUEUE_MASK I40E_MASK(0xFFF, I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_TX_VF_NUM_SHIFT 12
+#define I40E_GL_MDET_TX_VF_NUM_MASK I40E_MASK(0x1FF, I40E_GL_MDET_TX_VF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_PF_NUM_SHIFT 21
+#define I40E_GL_MDET_TX_PF_NUM_MASK I40E_MASK(0xF, I40E_GL_MDET_TX_PF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_EVENT_SHIFT 25
+#define I40E_GL_MDET_TX_EVENT_MASK I40E_MASK(0x1F, I40E_GL_MDET_TX_EVENT_SHIFT)
 #define I40E_GL_MDET_TX_VALID_SHIFT 31
-#define I40E_GL_MDET_TX_VALID_MASK (0x1 << I40E_GL_MDET_TX_VALID_SHIFT)
-#define I40E_PF_MDET_RX 0x0012A400
+#define I40E_GL_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_TX_VALID_SHIFT)
+#define I40E_PF_MDET_RX 0x0012A400 /* Reset: CORER */
 #define I40E_PF_MDET_RX_VALID_SHIFT 0
-#define I40E_PF_MDET_RX_VALID_MASK (0x1 << I40E_PF_MDET_RX_VALID_SHIFT)
-#define I40E_PF_MDET_TX 0x000E6400
+#define I40E_PF_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_RX_VALID_SHIFT)
+#define I40E_PF_MDET_TX 0x000E6400 /* Reset: CORER */
 #define I40E_PF_MDET_TX_VALID_SHIFT 0
-#define I40E_PF_MDET_TX_VALID_MASK (0x1 << I40E_PF_MDET_TX_VALID_SHIFT)
-#define I40E_PF_VT_PFALLOC 0x001C0500
+#define I40E_PF_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_TX_VALID_SHIFT)
+#define I40E_PF_VT_PFALLOC 0x001C0500 /* Reset: CORER */
 #define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0
-#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
 #define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8
-#define I40E_PF_VT_PFALLOC_LASTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
 #define I40E_PF_VT_PFALLOC_VALID_SHIFT 31
-#define I40E_PF_VT_PFALLOC_VALID_MASK (0x1 << I40E_PF_VT_PFALLOC_VALID_SHIFT)
-#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT)
+#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VP_MDET_RX_MAX_INDEX 127
 #define I40E_VP_MDET_RX_VALID_SHIFT 0
-#define I40E_VP_MDET_RX_VALID_MASK (0x1 << I40E_VP_MDET_RX_VALID_SHIFT)
-#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_RX_VALID_SHIFT)
+#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VP_MDET_TX_MAX_INDEX 127
 #define I40E_VP_MDET_TX_VALID_SHIFT 0
-#define I40E_VP_MDET_TX_VALID_MASK (0x1 << I40E_VP_MDET_TX_VALID_SHIFT)
-#define I40E_GLPM_WUMC 0x0006C800
+#define I40E_VP_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_TX_VALID_SHIFT)
+#define I40E_GLPM_WUMC 0x0006C800 /* Reset: POR */
 #define I40E_GLPM_WUMC_NOTCO_SHIFT 0
-#define I40E_GLPM_WUMC_NOTCO_MASK (0x1 << I40E_GLPM_WUMC_NOTCO_SHIFT)
+#define I40E_GLPM_WUMC_NOTCO_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_NOTCO_SHIFT)
 #define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1
-#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK (0x1 << I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
 #define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2
-#define I40E_GLPM_WUMC_ROL_MODE_MASK (0x1 << I40E_GLPM_WUMC_ROL_MODE_SHIFT)
+#define I40E_GLPM_WUMC_ROL_MODE_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_ROL_MODE_SHIFT)
 #define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3
-#define I40E_GLPM_WUMC_RESERVED_4_MASK (0x1FFF << I40E_GLPM_WUMC_RESERVED_4_SHIFT)
+#define I40E_GLPM_WUMC_RESERVED_4_MASK I40E_MASK(0x1FFF, I40E_GLPM_WUMC_RESERVED_4_SHIFT)
 #define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16
-#define I40E_GLPM_WUMC_MNG_WU_PF_MASK (0xFFFF << I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
-#define I40E_PFPM_APM 0x000B8080
+#define I40E_GLPM_WUMC_MNG_WU_PF_MASK I40E_MASK(0xFFFF, I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
+#define I40E_PFPM_APM 0x000B8080 /* Reset: POR */
 #define I40E_PFPM_APM_APME_SHIFT 0
-#define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
-#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFPM_APM_APME_MASK I40E_MASK(0x1, I40E_PFPM_APM_APME_SHIFT)
+#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
 #define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PFPM_WUC 0x0006B200
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PFPM_WUC 0x0006B200 /* Reset: POR */
 #define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
-#define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
-#define I40E_PFPM_WUFC 0x0006B400
+#define I40E_PFPM_WUC_EN_APM_D0_MASK I40E_MASK(0x1, I40E_PFPM_WUC_EN_APM_D0_SHIFT)
+#define I40E_PFPM_WUFC 0x0006B400 /* Reset: POR */
 #define I40E_PFPM_WUFC_LNKC_SHIFT 0
-#define I40E_PFPM_WUFC_LNKC_MASK (0x1 << I40E_PFPM_WUFC_LNKC_SHIFT)
+#define I40E_PFPM_WUFC_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_LNKC_SHIFT)
 #define I40E_PFPM_WUFC_MAG_SHIFT 1
-#define I40E_PFPM_WUFC_MAG_MASK (0x1 << I40E_PFPM_WUFC_MAG_SHIFT)
+#define I40E_PFPM_WUFC_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MAG_SHIFT)
 #define I40E_PFPM_WUFC_MNG_SHIFT 3
-#define I40E_PFPM_WUFC_MNG_MASK (0x1 << I40E_PFPM_WUFC_MNG_SHIFT)
+#define I40E_PFPM_WUFC_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MNG_SHIFT)
 #define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4
-#define I40E_PFPM_WUFC_FLX0_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5
-#define I40E_PFPM_WUFC_FLX1_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6
-#define I40E_PFPM_WUFC_FLX2_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7
-#define I40E_PFPM_WUFC_FLX3_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8
-#define I40E_PFPM_WUFC_FLX4_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9
-#define I40E_PFPM_WUFC_FLX5_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10
-#define I40E_PFPM_WUFC_FLX6_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11
-#define I40E_PFPM_WUFC_FLX7_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX0_SHIFT 16
-#define I40E_PFPM_WUFC_FLX0_MASK (0x1 << I40E_PFPM_WUFC_FLX0_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_SHIFT)
 #define I40E_PFPM_WUFC_FLX1_SHIFT 17
-#define I40E_PFPM_WUFC_FLX1_MASK (0x1 << I40E_PFPM_WUFC_FLX1_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_SHIFT)
 #define I40E_PFPM_WUFC_FLX2_SHIFT 18
-#define I40E_PFPM_WUFC_FLX2_MASK (0x1 << I40E_PFPM_WUFC_FLX2_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_SHIFT)
 #define I40E_PFPM_WUFC_FLX3_SHIFT 19
-#define I40E_PFPM_WUFC_FLX3_MASK (0x1 << I40E_PFPM_WUFC_FLX3_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_SHIFT)
 #define I40E_PFPM_WUFC_FLX4_SHIFT 20
-#define I40E_PFPM_WUFC_FLX4_MASK (0x1 << I40E_PFPM_WUFC_FLX4_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_SHIFT)
 #define I40E_PFPM_WUFC_FLX5_SHIFT 21
-#define I40E_PFPM_WUFC_FLX5_MASK (0x1 << I40E_PFPM_WUFC_FLX5_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_SHIFT)
 #define I40E_PFPM_WUFC_FLX6_SHIFT 22
-#define I40E_PFPM_WUFC_FLX6_MASK (0x1 << I40E_PFPM_WUFC_FLX6_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_SHIFT)
 #define I40E_PFPM_WUFC_FLX7_SHIFT 23
-#define I40E_PFPM_WUFC_FLX7_MASK (0x1 << I40E_PFPM_WUFC_FLX7_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_SHIFT)
 #define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUFC_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
-#define I40E_PFPM_WUS 0x0006B600
+#define I40E_PFPM_WUFC_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
+#define I40E_PFPM_WUS 0x0006B600 /* Reset: POR */
 #define I40E_PFPM_WUS_LNKC_SHIFT 0
-#define I40E_PFPM_WUS_LNKC_MASK (0x1 << I40E_PFPM_WUS_LNKC_SHIFT)
+#define I40E_PFPM_WUS_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUS_LNKC_SHIFT)
 #define I40E_PFPM_WUS_MAG_SHIFT 1
-#define I40E_PFPM_WUS_MAG_MASK (0x1 << I40E_PFPM_WUS_MAG_SHIFT)
+#define I40E_PFPM_WUS_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MAG_SHIFT)
 #define I40E_PFPM_WUS_PME_STATUS_SHIFT 2
-#define I40E_PFPM_WUS_PME_STATUS_MASK (0x1 << I40E_PFPM_WUS_PME_STATUS_SHIFT)
+#define I40E_PFPM_WUS_PME_STATUS_MASK I40E_MASK(0x1, I40E_PFPM_WUS_PME_STATUS_SHIFT)
 #define I40E_PFPM_WUS_MNG_SHIFT 3
-#define I40E_PFPM_WUS_MNG_MASK (0x1 << I40E_PFPM_WUS_MNG_SHIFT)
+#define I40E_PFPM_WUS_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MNG_SHIFT)
 #define I40E_PFPM_WUS_FLX0_SHIFT 16
-#define I40E_PFPM_WUS_FLX0_MASK (0x1 << I40E_PFPM_WUS_FLX0_SHIFT)
+#define I40E_PFPM_WUS_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX0_SHIFT)
 #define I40E_PFPM_WUS_FLX1_SHIFT 17
-#define I40E_PFPM_WUS_FLX1_MASK (0x1 << I40E_PFPM_WUS_FLX1_SHIFT)
+#define I40E_PFPM_WUS_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX1_SHIFT)
 #define I40E_PFPM_WUS_FLX2_SHIFT 18
-#define I40E_PFPM_WUS_FLX2_MASK (0x1 << I40E_PFPM_WUS_FLX2_SHIFT)
+#define I40E_PFPM_WUS_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX2_SHIFT)
 #define I40E_PFPM_WUS_FLX3_SHIFT 19
-#define I40E_PFPM_WUS_FLX3_MASK (0x1 << I40E_PFPM_WUS_FLX3_SHIFT)
+#define I40E_PFPM_WUS_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX3_SHIFT)
 #define I40E_PFPM_WUS_FLX4_SHIFT 20
-#define I40E_PFPM_WUS_FLX4_MASK (0x1 << I40E_PFPM_WUS_FLX4_SHIFT)
+#define I40E_PFPM_WUS_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX4_SHIFT)
 #define I40E_PFPM_WUS_FLX5_SHIFT 21
-#define I40E_PFPM_WUS_FLX5_MASK (0x1 << I40E_PFPM_WUS_FLX5_SHIFT)
+#define I40E_PFPM_WUS_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX5_SHIFT)
 #define I40E_PFPM_WUS_FLX6_SHIFT 22
-#define I40E_PFPM_WUS_FLX6_MASK (0x1 << I40E_PFPM_WUS_FLX6_SHIFT)
+#define I40E_PFPM_WUS_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX6_SHIFT)
 #define I40E_PFPM_WUS_FLX7_SHIFT 23
-#define I40E_PFPM_WUS_FLX7_MASK (0x1 << I40E_PFPM_WUS_FLX7_SHIFT)
+#define I40E_PFPM_WUS_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX7_SHIFT)
 #define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUS_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUS_FW_RST_WK_SHIFT)
-#define I40E_PRTPM_FHFHR 0x0006C000
+#define I40E_PFPM_WUS_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FW_RST_WK_SHIFT)
+#define I40E_PRTPM_FHFHR 0x0006C000 /* Reset: POR */
 #define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0
-#define I40E_PRTPM_FHFHR_UNICAST_MASK (0x1 << I40E_PRTPM_FHFHR_UNICAST_SHIFT)
+#define I40E_PRTPM_FHFHR_UNICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_UNICAST_SHIFT)
 #define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1
-#define I40E_PRTPM_FHFHR_MULTICAST_MASK (0x1 << I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
-#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_FHFHR_MULTICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
+#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
 #define I40E_PRTPM_SAH_MAX_INDEX 3
 #define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0
-#define I40E_PRTPM_SAH_PFPM_SAH_MASK (0xFFFF << I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
+#define I40E_PRTPM_SAH_PFPM_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
 #define I40E_PRTPM_SAH_PF_NUM_SHIFT 26
-#define I40E_PRTPM_SAH_PF_NUM_MASK (0xF << I40E_PRTPM_SAH_PF_NUM_SHIFT)
+#define I40E_PRTPM_SAH_PF_NUM_MASK I40E_MASK(0xF, I40E_PRTPM_SAH_PF_NUM_SHIFT)
 #define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30
-#define I40E_PRTPM_SAH_MC_MAG_EN_MASK (0x1 << I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
+#define I40E_PRTPM_SAH_MC_MAG_EN_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
 #define I40E_PRTPM_SAH_AV_SHIFT 31
-#define I40E_PRTPM_SAH_AV_MASK (0x1 << I40E_PRTPM_SAH_AV_SHIFT)
-#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAH_AV_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_AV_SHIFT)
+#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
 #define I40E_PRTPM_SAL_MAX_INDEX 3
 #define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0
-#define I40E_PRTPM_SAL_PFPM_SAL_MASK (0xFFFFFFFF << I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
-#define I40E_VF_ARQBAH1 0x00006000
+#define I40E_PRTPM_SAL_PFPM_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
+#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
 #define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH1_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH1_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL1 0x00006C00
+#define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
 #define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL1_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL1_ARQBAL_SHIFT)
-#define I40E_VF_ARQH1 0x00007400
+#define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT)
+#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
 #define I40E_VF_ARQH1_ARQH_SHIFT 0
-#define I40E_VF_ARQH1_ARQH_MASK (0x3FF << I40E_VF_ARQH1_ARQH_SHIFT)
-#define I40E_VF_ARQLEN1 0x00008000
+#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
 #define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN1_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN1_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT)
 #define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN1_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
 #define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN1_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
 #define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN1_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
 #define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN1_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT1 0x00007000
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
 #define I40E_VF_ARQT1_ARQT_SHIFT 0
-#define I40E_VF_ARQT1_ARQT_MASK (0x3FF << I40E_VF_ARQT1_ARQT_SHIFT)
-#define I40E_VF_ATQBAH1 0x00007800
+#define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT)
+#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
 #define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH1_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH1_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL1 0x00007C00
+#define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
 #define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL1_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL1_ATQBAL_SHIFT)
-#define I40E_VF_ATQH1 0x00006400
+#define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT)
+#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
 #define I40E_VF_ATQH1_ATQH_SHIFT 0
-#define I40E_VF_ATQH1_ATQH_MASK (0x3FF << I40E_VF_ATQH1_ATQH_SHIFT)
-#define I40E_VF_ATQLEN1 0x00006800
+#define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT)
+#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
 #define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN1_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN1_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT)
 #define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN1_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
 #define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN1_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
 #define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN1_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
 #define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN1_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT1 0x00008400
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
 #define I40E_VF_ATQT1_ATQT_SHIFT 0
-#define I40E_VF_ATQT1_ATQT_MASK (0x3FF << I40E_VF_ATQT1_ATQT_SHIFT)
-#define I40E_VFGEN_RSTAT 0x00008800
+#define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT)
+#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
 #define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
-#define I40E_VFINT_DYN_CTL01 0x00005C00
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
 #define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL01_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4))
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
 #define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN1_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0_ENA1 0x00005000
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
 #define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA1_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
-#define I40E_VFINT_ICR01 0x00004800
+#define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
+#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
 #define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR01_INTEVENT_MASK (0x1 << I40E_VFINT_ICR01_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR01_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR01_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR01_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR01_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT)
 #define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR01_ADMINQ_MASK (0x1 << I40E_VFINT_ICR01_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR01_SWINT_SHIFT 31
-#define I40E_VFINT_ICR01_SWINT_MASK (0x1 << I40E_VFINT_ICR01_SWINT_SHIFT)
-#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */
+#define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT)
+#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */
 #define I40E_VFINT_ITR01_MAX_INDEX 2
 #define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR01_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR01_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4))
+#define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
 #define I40E_VFINT_ITRN1_MAX_INDEX 2
 #define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN1_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN1_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL01 0x00005400
+#define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: VFR */
 #define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
-#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_QRX_TAIL1_MAX_INDEX 15
 #define I40E_QRX_TAIL1_TAIL_SHIFT 0
-#define I40E_QRX_TAIL1_TAIL_MASK (0x1FFF << I40E_QRX_TAIL1_TAIL_SHIFT)
-#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT)
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
 #define I40E_QTX_TAIL1_MAX_INDEX 15
 #define I40E_QTX_TAIL1_TAIL_SHIFT 0
-#define I40E_QTX_TAIL1_TAIL_MASK (0x1FFF << I40E_QTX_TAIL1_TAIL_SHIFT)
-#define I40E_VFMSIX_PBA 0x00002000
+#define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT)
+#define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */
 #define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TADD_MAX_INDEX 16
 #define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
 #define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TMSG_MAX_INDEX 16
 #define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TUADD_MAX_INDEX 16
 #define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
 #define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFCM_PE_ERRDATA 0x0000DC00
+#define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */
 #define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO 0x0000D800
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */
 #define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFPE_AEQALLOC1 0x0000A400
-#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH1 0x00009800
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW1 0x0000AC00
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1 0x0000B800
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK1 0x0000B000
-#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK1_PECQID_SHIFT)
-#define I40E_VFPE_CQARM1 0x0000B400
-#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM1_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB1 0x0000BC00
-#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB1_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES1 0x00009C00
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL1 0x0000A000
-#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG01 0x00008C00
-#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK1 0x00009000
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER1 0x0000A800
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC1 0x0000C000
-#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC1_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
 #define I40E_VFQF_HENA_MAX_INDEX 1
 #define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */
+#define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
 #define I40E_VFQF_HKEY_MAX_INDEX 12
 #define I40E_VFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY_KEY_0_MASK (0xFF << I40E_VFQF_HKEY_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT)
 #define I40E_VFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY_KEY_1_MASK (0xFF << I40E_VFQF_HKEY_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT)
 #define I40E_VFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY_KEY_2_MASK (0xFF << I40E_VFQF_HKEY_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT)
 #define I40E_VFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY_KEY_3_MASK (0xFF << I40E_VFQF_HKEY_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_VFQF_HLUT_MAX_INDEX 15
 #define I40E_VFQF_HLUT_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT_LUT0_MASK (0xF << I40E_VFQF_HLUT_LUT0_SHIFT)
+#define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT)
 #define I40E_VFQF_HLUT_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT_LUT1_MASK (0xF << I40E_VFQF_HLUT_LUT1_SHIFT)
+#define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT)
 #define I40E_VFQF_HLUT_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT_LUT2_MASK (0xF << I40E_VFQF_HLUT_LUT2_SHIFT)
+#define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT)
 #define I40E_VFQF_HLUT_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT_LUT3_MASK (0xF << I40E_VFQF_HLUT_LUT3_SHIFT)
-#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */
+#define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT)
+#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_VFQF_HREGION_MAX_INDEX 7
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
 #define I40E_VFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION_REGION_0_MASK (0x7 << I40E_VFQF_HREGION_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
 #define I40E_VFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION_REGION_1_MASK (0x7 << I40E_VFQF_HREGION_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
 #define I40E_VFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION_REGION_2_MASK (0x7 << I40E_VFQF_HREGION_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
 #define I40E_VFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION_REGION_3_MASK (0x7 << I40E_VFQF_HREGION_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
 #define I40E_VFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION_REGION_4_MASK (0x7 << I40E_VFQF_HREGION_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
 #define I40E_VFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION_REGION_5_MASK (0x7 << I40E_VFQF_HREGION_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
 #define I40E_VFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION_REGION_6_MASK (0x7 << I40E_VFQF_HREGION_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
 #define I40E_VFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
+#define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT)
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,6 +39,7 @@ static inline __le64 build_ctob(u32 td_c
 }
 
 #define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
+#define I40E_FD_CLEAN_DELAY 10
 /**
  * i40e_program_fdir_filter - Program a Flow Director filter
  * @fdir_data: Packet data that will be filter parameters
@@ -50,7 +51,7 @@ int i40e_program_fdir_filter(struct i40e
 			     struct i40e_pf *pf, bool add)
 {
 	struct i40e_filter_program_desc *fdir_desc;
-	struct i40e_tx_buffer *tx_buf;
+	struct i40e_tx_buffer *tx_buf, *first;
 	struct i40e_tx_desc *tx_desc;
 	struct i40e_ring *tx_ring;
 	unsigned int fpt, dcc;
@@ -58,6 +59,7 @@ int i40e_program_fdir_filter(struct i40e
 	struct device *dev;
 	dma_addr_t dma;
 	u32 td_cmd = 0;
+	u16 delay = 0;
 	u16 i;
 
 	/* find existing FDIR VSI */
@@ -71,6 +73,17 @@ int i40e_program_fdir_filter(struct i40e
 	tx_ring = vsi->tx_rings[0];
 	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;
+		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);
 	if (dma_mapping_error(dev, dma))
@@ -79,8 +92,10 @@ int i40e_program_fdir_filter(struct i40e
 	/* grab the next descriptor */
 	i = tx_ring->next_to_use;
 	fdir_desc = I40E_TX_FDIRDESC(tx_ring, i);
+	first = &tx_ring->tx_bi[i];
+	memset(first, 0, sizeof(struct i40e_tx_buffer));
 
-	tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
+	tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0;
 
 	fpt = (fdir_data->q_index << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
 	      I40E_TXD_FLTR_QW0_QINDEX_MASK;
@@ -100,8 +115,6 @@ int i40e_program_fdir_filter(struct i40e
 			I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
 		       I40E_TXD_FLTR_QW0_DEST_VSI_MASK;
 
-	fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
-
 	dcc = I40E_TX_DESC_DTYPE_FILTER_PROG;
 
 	if (add)
@@ -124,6 +137,8 @@ int i40e_program_fdir_filter(struct i40e
 			I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
 	}
 
+	fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
+	fdir_desc->rsvd = cpu_to_le32(0);
 	fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dcc);
 	fdir_desc->fd_id = cpu_to_le32(fdir_data->fd_id);
 
@@ -132,7 +147,9 @@ int i40e_program_fdir_filter(struct i40e
 	tx_desc = I40E_TX_DESC(tx_ring, i);
 	tx_buf = &tx_ring->tx_bi[i];
 
-	tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
+	tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0;
+
+	memset(tx_buf, 0, sizeof(struct i40e_tx_buffer));
 
 	/* record length, and DMA address */
 	dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_SIZE);
@@ -141,6 +158,9 @@ int i40e_program_fdir_filter(struct i40e
 	tx_desc->buffer_addr = cpu_to_le64(dma);
 	td_cmd = I40E_TXD_CMD | I40E_TX_DESC_CMD_DUMMY;
 
+	tx_buf->tx_flags = I40E_TX_FLAGS_FD_SB;
+	tx_buf->raw_buf = (void *)raw_packet;
+
 	tx_desc->cmd_type_offset_bsz =
 		build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_SIZE, 0);
 
@@ -148,14 +168,12 @@ int i40e_program_fdir_filter(struct i40e
 	tx_buf->time_stamp = jiffies;
 
 	/* 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).
+	 * know there are new descriptors to fetch.
 	 */
 	wmb();
 
 	/* Mark the data descriptor to be watched */
-	tx_buf->next_to_watch = tx_desc;
+	first->next_to_watch = tx_desc;
 
 	writel(tx_ring->next_to_use, tx_ring->tail);
 	return 0;
@@ -170,24 +188,27 @@ dma_fail:
  * i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 filters
  * @vsi: pointer to the targeted VSI
  * @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
  * @add: true adds a filter, false removes it
  *
  * Returns 0 if the filters were successfully added or removed
  **/
 static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
 				   struct i40e_fdir_filter *fd_data,
-				   u8 *raw_packet, bool add)
+				   bool add)
 {
 	struct i40e_pf *pf = vsi->back;
 	struct udphdr *udp;
 	struct iphdr *ip;
 	bool err = false;
+	u8 *raw_packet;
 	int ret;
 	static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
 		0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
+	raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+	if (!raw_packet)
+		return -ENOMEM;
 	memcpy(raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
 
 	ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
@@ -220,19 +241,19 @@ static int i40e_add_del_fdir_udpv4(struc
  * i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 filters
  * @vsi: pointer to the targeted VSI
  * @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
  * @add: true adds a filter, false removes it
  *
  * Returns 0 if the filters were successfully added or removed
  **/
 static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
 				   struct i40e_fdir_filter *fd_data,
-				   u8 *raw_packet, bool add)
+				   bool add)
 {
 	struct i40e_pf *pf = vsi->back;
 	struct tcphdr *tcp;
 	struct iphdr *ip;
 	bool err = false;
+	u8 *raw_packet;
 	int ret;
 	/* Dummy packet */
 	static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
@@ -240,6 +261,9 @@ static int i40e_add_del_fdir_tcpv4(struc
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x11,
 		0x0, 0x72, 0, 0, 0, 0};
 
+	raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+	if (!raw_packet)
+		return -ENOMEM;
 	memcpy(raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
 
 	ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
@@ -271,19 +295,6 @@ static int i40e_add_del_fdir_tcpv4(struc
 			 fd_data->pctype, ret);
 	}
 
-	fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-
-	ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
-	if (ret) {
-		dev_info(&pf->pdev->dev,
-			 "Filter command send failed for PCTYPE %d (ret = %d)\n",
-			 fd_data->pctype, ret);
-		err = true;
-	} else {
-		dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
-			  fd_data->pctype, ret);
-	}
-
 	return err ? -EOPNOTSUPP : 0;
 }
 
@@ -292,14 +303,13 @@ static int i40e_add_del_fdir_tcpv4(struc
  * a specific flow spec
  * @vsi: pointer to the targeted VSI
  * @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
  * @add: true adds a filter, false removes it
  *
  * Always returns -EOPNOTSUPP
  **/
 static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
 				    struct i40e_fdir_filter *fd_data,
-				    u8 *raw_packet, bool add)
+				    bool add)
 {
 	return -EOPNOTSUPP;
 }
@@ -310,33 +320,36 @@ static int i40e_add_del_fdir_sctpv4(stru
  * a specific flow spec
  * @vsi: pointer to the targeted VSI
  * @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
  * @add: true adds a filter, false removes it
  *
  * Returns 0 if the filters were successfully added or removed
  **/
 static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
 				  struct i40e_fdir_filter *fd_data,
-				  u8 *raw_packet, bool add)
+				  bool add)
 {
 	struct i40e_pf *pf = vsi->back;
 	struct iphdr *ip;
 	bool err = false;
+	u8 *raw_packet;
 	int ret;
 	int i;
 	static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
 		0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0};
 
-	memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
-	ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
-
-	ip->saddr = fd_data->src_ip[0];
-	ip->daddr = fd_data->dst_ip[0];
-	ip->protocol = 0;
-
 	for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
 	     i <= I40E_FILTER_PCTYPE_FRAG_IPV4;	i++) {
+		raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+		if (!raw_packet)
+			return -ENOMEM;
+		memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
+		ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
+
+		ip->saddr = fd_data->src_ip[0];
+		ip->daddr = fd_data->dst_ip[0];
+		ip->protocol = 0;
+
 		fd_data->pctype = i;
 		ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
 
@@ -366,50 +379,34 @@ int i40e_add_del_fdir(struct i40e_vsi *v
 		      struct i40e_fdir_filter *input, bool add)
 {
 	struct i40e_pf *pf = vsi->back;
-	u8 *raw_packet;
 	int ret;
 
-	/* Populate the Flow Director that we have at the moment
-	 * and allocate the raw packet buffer for the calling functions
-	 */
-	raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
-	if (!raw_packet)
-		return -ENOMEM;
-
 	switch (input->flow_type & ~FLOW_EXT) {
 	case TCP_V4_FLOW:
-		ret = i40e_add_del_fdir_tcpv4(vsi, input, raw_packet,
-					      add);
+		ret = i40e_add_del_fdir_tcpv4(vsi, input, add);
 		break;
 	case UDP_V4_FLOW:
-		ret = i40e_add_del_fdir_udpv4(vsi, input, raw_packet,
-					      add);
+		ret = i40e_add_del_fdir_udpv4(vsi, input, add);
 		break;
 	case SCTP_V4_FLOW:
-		ret = i40e_add_del_fdir_sctpv4(vsi, input, raw_packet,
-					       add);
+		ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
 		break;
 	case IPV4_FLOW:
-		ret = i40e_add_del_fdir_ipv4(vsi, input, raw_packet,
-					     add);
+		ret = i40e_add_del_fdir_ipv4(vsi, input, add);
 		break;
 	case IP_USER_FLOW:
 		switch (input->ip4_proto) {
 		case IPPROTO_TCP:
-			ret = i40e_add_del_fdir_tcpv4(vsi, input,
-						      raw_packet, add);
+			ret = i40e_add_del_fdir_tcpv4(vsi, input, add);
 			break;
 		case IPPROTO_UDP:
-			ret = i40e_add_del_fdir_udpv4(vsi, input,
-						      raw_packet, add);
+			ret = i40e_add_del_fdir_udpv4(vsi, input, add);
 			break;
 		case IPPROTO_SCTP:
-			ret = i40e_add_del_fdir_sctpv4(vsi, input,
-						       raw_packet, add);
+			ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
 			break;
 		default:
-			ret = i40e_add_del_fdir_ipv4(vsi, input,
-						     raw_packet, add);
+			ret = i40e_add_del_fdir_ipv4(vsi, input, add);
 			break;
 		}
 		break;
@@ -419,7 +416,7 @@ int i40e_add_del_fdir(struct i40e_vsi *v
 		ret = -EINVAL;
 	}
 
-	kfree(raw_packet);
+	/* The buffer allocated here is freed by the i40e_clean_tx_ring() */
 	return ret;
 }
 
@@ -450,22 +447,24 @@ static void i40e_fd_handle_status(struct
 			 rx_desc->wb.qword0.hi_dword.fd_id);
 
 		/* filter programming failed most likely due to table full */
-		fcnt_prog = i40e_get_current_fd_count(pf);
-		fcnt_avail = i40e_get_fd_cnt_all(pf);
+		fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
+		fcnt_avail = pf->fdir_pf_filter_count;
 		/* If ATR is running fcnt_prog can quickly change,
 		 * if we are very close to full, it makes sense to disable
 		 * FD ATR/SB and then re-enable it when there is room.
 		 */
 		if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) {
 			/* Turn off ATR first */
-			if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
-				pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+			if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+			    !(pf->auto_disable_flags &
+			      I40E_FLAG_FD_ATR_ENABLED)) {
 				dev_warn(&pdev->dev, "FD filter space full, ATR for further flows will be turned off\n");
 				pf->auto_disable_flags |=
 						       I40E_FLAG_FD_ATR_ENABLED;
 				pf->flags |= I40E_FLAG_FDIR_REQUIRES_REINIT;
-			} else if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
-				pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+			} else if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+				   !(pf->auto_disable_flags &
+				     I40E_FLAG_FD_SB_ENABLED)) {
 				dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n");
 				pf->auto_disable_flags |=
 							I40E_FLAG_FD_SB_ENABLED;
@@ -491,7 +490,11 @@ static void i40e_unmap_and_free_tx_resou
 					    struct i40e_tx_buffer *tx_buffer)
 {
 	if (tx_buffer->skb) {
-		dev_kfree_skb_any(tx_buffer->skb);
+		if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+			kfree(tx_buffer->raw_buf);
+		else
+			dev_kfree_skb_any(tx_buffer->skb);
+
 		if (dma_unmap_len(tx_buffer, len))
 			dma_unmap_single(ring->dev,
 					 dma_unmap_addr(tx_buffer, dma),
@@ -893,6 +896,11 @@ static void i40e_clean_programming_statu
 
 	if (id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS)
 		i40e_fd_handle_status(rx_ring, rx_desc, id);
+#ifdef I40E_FCOE
+	else if ((id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
+		 (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS))
+		i40e_fcoe_handle_status(rx_ring, rx_desc, id);
+#endif
 }
 
 /**
@@ -1234,8 +1242,6 @@ static inline void i40e_rx_checksum(stru
 
 	/* likely incorrect csum if alternate IP extension headers found */
 	if (ipv6 &&
-	    decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
-	    rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
 	    rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
 		/* don't increment checksum err here, non-fatal err */
 		return;
@@ -1488,6 +1494,12 @@ static int i40e_clean_rx_irq(struct i40e
 		vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)
 			 ? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1)
 			 : 0;
+#ifdef I40E_FCOE
+		if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) {
+			dev_kfree_skb_any(skb);
+			goto next_desc;
+		}
+#endif
 		i40e_receive_skb(rx_ring, skb, vlan_tag);
 
 		rx_ring->netdev->last_rx = jiffies;
@@ -1701,7 +1713,9 @@ static void i40e_atr(struct i40e_ring *t
 		I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
 
 	fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
+	fdir_desc->rsvd = cpu_to_le32(0);
 	fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dtype_cmd);
+	fdir_desc->fd_id = cpu_to_le32(0);
 }
 
 /**
@@ -1716,9 +1730,15 @@ static void i40e_atr(struct i40e_ring *t
  * Returns error code indicate the frame should be dropped upon error and the
  * otherwise  returns 0 to indicate the flags has been set properly.
  **/
+#ifdef I40E_FCOE
+int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
+			       struct i40e_ring *tx_ring,
+			       u32 *flags)
+#else
 static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
 				      struct i40e_ring *tx_ring,
 				      u32 *flags)
+#endif
 {
 	__be16 protocol = skb->protocol;
 	u32  tx_flags = 0;
@@ -1740,9 +1760,8 @@ static int i40e_tx_prepare_vlan_flags(st
 	}
 
 	/* Insert 802.1p priority into VLAN header */
-	if ((tx_ring->vsi->back->flags & I40E_FLAG_DCB_ENABLED) &&
-	    ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) ||
-	     (skb->priority != TC_PRIO_CONTROL))) {
+	if ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) ||
+	    (skb->priority != TC_PRIO_CONTROL)) {
 		tx_flags &= ~I40E_TX_FLAGS_VLAN_PRIO_MASK;
 		tx_flags |= (skb->priority & 0x7) <<
 				I40E_TX_FLAGS_VLAN_PRIO_SHIFT;
@@ -1850,7 +1869,8 @@ static int i40e_tsyn(struct i40e_ring *t
 	 * we are not already transmitting a packet to be timestamped
 	 */
 	pf = i40e_netdev_to_pf(tx_ring->netdev);
-	if (pf->ptp_tx && !pf->ptp_tx_skb) {
+	if (pf->ptp_tx &&
+	    !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, &pf->state)) {
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 		pf->ptp_tx_skb = skb_get(skb);
 	} else {
@@ -2000,6 +2020,7 @@ static void i40e_create_tx_ctx(struct i4
 	/* cpu_to_le32 and assign to struct fields */
 	context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
 	context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+	context_desc->rsvd = cpu_to_le16(0);
 	context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
 }
 
@@ -2013,9 +2034,15 @@ static void i40e_create_tx_ctx(struct i4
  * @td_cmd:   the command field in the descriptor
  * @td_offset: offset for checksum or crc
  **/
+#ifdef I40E_FCOE
+void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+		 struct i40e_tx_buffer *first, u32 tx_flags,
+		 const u8 hdr_len, u32 td_cmd, u32 td_offset)
+#else
 static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
 			struct i40e_tx_buffer *first, u32 tx_flags,
 			const u8 hdr_len, u32 td_cmd, u32 td_offset)
+#endif
 {
 	unsigned int data_len = skb->data_len;
 	unsigned int size = skb_headlen(skb);
@@ -2192,7 +2219,11 @@ static inline int __i40e_maybe_stop_tx(s
  *
  * Returns 0 if stop is not needed
  **/
+#ifdef I40E_FCOE
+int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#else
 static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#endif
 {
 	if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
 		return 0;
@@ -2208,8 +2239,13 @@ static int i40e_maybe_stop_tx(struct i40
  * there is not enough descriptors available in this ring since we need at least
  * one descriptor.
  **/
+#ifdef I40E_FCOE
+int i40e_xmit_descriptor_count(struct sk_buff *skb,
+			       struct i40e_ring *tx_ring)
+#else
 static int i40e_xmit_descriptor_count(struct sk_buff *skb,
 				      struct i40e_ring *tx_ring)
+#endif
 {
 	unsigned int f;
 	int count = 0;
@@ -2259,7 +2295,7 @@ static netdev_tx_t i40e_xmit_frame_ring(
 		goto out_drop;
 
 	/* obtain protocol of skb */
-	protocol = skb->protocol;
+	protocol = vlan_get_protocol(skb);
 
 	/* record the location of the first descriptor for this packet */
 	first = &tx_ring->tx_bi[tx_ring->next_to_use];
@@ -2278,13 +2314,13 @@ static netdev_tx_t i40e_xmit_frame_ring(
 	else if (tso)
 		tx_flags |= I40E_TX_FLAGS_TSO;
 
-	skb_tx_timestamp(skb);
-
 	tsyn = i40e_tsyn(tx_ring, skb, tx_flags, &cd_type_cmd_tso_mss);
 
 	if (tsyn)
 		tx_flags |= I40E_TX_FLAGS_TSYN;
 
+	skb_tx_timestamp(skb);
+
 	/* always enable CRC insertion offload */
 	td_cmd |= I40E_TX_DESC_CMD_ICRC;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
 	((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
-	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
@@ -132,6 +131,7 @@ enum i40e_dyn_idx_t {
 #define I40E_TX_FLAGS_FCCRC		(u32)(1 << 6)
 #define I40E_TX_FLAGS_FSO		(u32)(1 << 7)
 #define I40E_TX_FLAGS_TSYN		(u32)(1 << 8)
+#define I40E_TX_FLAGS_FD_SB		(u32)(1 << 9)
 #define I40E_TX_FLAGS_VLAN_MASK		0xffff0000
 #define I40E_TX_FLAGS_VLAN_PRIO_MASK	0xe0000000
 #define I40E_TX_FLAGS_VLAN_PRIO_SHIFT	29
@@ -140,7 +140,10 @@ enum i40e_dyn_idx_t {
 struct i40e_tx_buffer {
 	struct i40e_tx_desc *next_to_watch;
 	unsigned long time_stamp;
-	struct sk_buff *skb;
+	union {
+		struct sk_buff *skb;
+		void *raw_buf;
+	};
 	unsigned int bytecount;
 	unsigned short gso_segs;
 	DEFINE_DMA_UNMAP_ADDR(dma);
@@ -287,4 +290,13 @@ int i40e_setup_rx_descriptors(struct i40
 void i40e_free_tx_resources(struct i40e_ring *tx_ring);
 void i40e_free_rx_resources(struct i40e_ring *rx_ring);
 int i40e_napi_poll(struct napi_struct *napi, int budget);
+#ifdef I40E_FCOE
+void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+		 struct i40e_tx_buffer *first, u32 tx_flags,
+		 const u8 hdr_len, u32 td_cmd, u32 td_offset);
+int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
+int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring);
+int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
+			       struct i40e_ring *tx_ring, u32 *flags);
+#endif
 #endif /* _I40E_TXRX_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,9 @@
 					 (d) == I40E_DEV_ID_QSFP_B  || \
 					 (d) == I40E_DEV_ID_QSFP_C)
 
+/* I40E_MASK is a macro used on 32 bit registers */
+#define I40E_MASK(mask, shift) (mask << shift)
+
 #define I40E_MAX_VSI_QP			16
 #define I40E_MAX_VF_VSI			3
 #define I40E_MAX_CHAINED_RX_BUFFERS	5
@@ -137,6 +140,14 @@ enum i40e_fc_mode {
 	I40E_FC_DEFAULT
 };
 
+enum i40e_set_fc_aq_failures {
+	I40E_SET_FC_AQ_FAIL_NONE = 0,
+	I40E_SET_FC_AQ_FAIL_GET = 1,
+	I40E_SET_FC_AQ_FAIL_SET = 2,
+	I40E_SET_FC_AQ_FAIL_UPDATE = 4,
+	I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6
+};
+
 enum i40e_vsi_type {
 	I40E_VSI_MAIN = 0,
 	I40E_VSI_VMDQ1,
@@ -163,6 +174,7 @@ struct i40e_link_status {
 	u8 an_info;
 	u8 ext_info;
 	u8 loopback;
+	bool an_enabled;
 	/* is Link Status Event notification to SW enabled */
 	bool lse_enable;
 	u16 max_frame_size;
@@ -234,6 +246,7 @@ struct i40e_mac_info {
 	u8 addr[ETH_ALEN];
 	u8 perm_addr[ETH_ALEN];
 	u8 san_addr[ETH_ALEN];
+	u8 port_addr[ETH_ALEN];
 	u16 max_fcoeq;
 };
 
@@ -256,6 +269,61 @@ struct i40e_nvm_info {
 	u32 eetrack;              /* NVM data version */
 };
 
+/* definitions used in NVM update support */
+
+enum i40e_nvmupd_cmd {
+	I40E_NVMUPD_INVALID,
+	I40E_NVMUPD_READ_CON,
+	I40E_NVMUPD_READ_SNT,
+	I40E_NVMUPD_READ_LCB,
+	I40E_NVMUPD_READ_SA,
+	I40E_NVMUPD_WRITE_ERA,
+	I40E_NVMUPD_WRITE_CON,
+	I40E_NVMUPD_WRITE_SNT,
+	I40E_NVMUPD_WRITE_LCB,
+	I40E_NVMUPD_WRITE_SA,
+	I40E_NVMUPD_CSUM_CON,
+	I40E_NVMUPD_CSUM_SA,
+	I40E_NVMUPD_CSUM_LCB,
+};
+
+enum i40e_nvmupd_state {
+	I40E_NVMUPD_STATE_INIT,
+	I40E_NVMUPD_STATE_READING,
+	I40E_NVMUPD_STATE_WRITING
+};
+
+/* nvm_access definition and its masks/shifts need to be accessible to
+ * application, core driver, and shared code.  Where is the right file?
+ */
+#define I40E_NVM_READ	0xB
+#define I40E_NVM_WRITE	0xC
+
+#define I40E_NVM_MOD_PNT_MASK 0xFF
+
+#define I40E_NVM_TRANS_SHIFT	8
+#define I40E_NVM_TRANS_MASK	(0xf << I40E_NVM_TRANS_SHIFT)
+#define I40E_NVM_CON		0x0
+#define I40E_NVM_SNT		0x1
+#define I40E_NVM_LCB		0x2
+#define I40E_NVM_SA		(I40E_NVM_SNT | I40E_NVM_LCB)
+#define I40E_NVM_ERA		0x4
+#define I40E_NVM_CSUM		0x8
+
+#define I40E_NVM_ADAPT_SHIFT	16
+#define I40E_NVM_ADAPT_MASK	(0xffff << I40E_NVM_ADAPT_SHIFT)
+
+#define I40E_NVMUPD_MAX_DATA	4096
+#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
+
+struct i40e_nvm_access {
+	u32 command;
+	u32 config;
+	u32 offset;	/* in bytes */
+	u32 data_size;	/* in bytes */
+	u8 data[1];
+};
+
 /* PCI bus types */
 enum i40e_bus_type {
 	i40e_bus_type_unknown = 0,
@@ -391,6 +459,9 @@ struct i40e_hw {
 	/* Admin Queue info */
 	struct i40e_adminq_info aq;
 
+	/* state of nvm update process */
+	enum i40e_nvmupd_state nvmupd_state;
+
 	/* HMC info */
 	struct i40e_hmc_info hmc; /* HMC info struct */
 
@@ -875,7 +946,6 @@ enum i40e_filter_pctype {
 	I40E_FILTER_PCTYPE_FRAG_IPV4			= 36,
 	/* Note: Values 37-40 are reserved for future use */
 	I40E_FILTER_PCTYPE_NONF_IPV6_UDP		= 41,
-	I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN		= 42,
 	I40E_FILTER_PCTYPE_NONF_IPV6_TCP		= 43,
 	I40E_FILTER_PCTYPE_NONF_IPV6_SCTP		= 44,
 	I40E_FILTER_PCTYPE_NONF_IPV6_OTHER		= 45,
@@ -981,6 +1051,25 @@ struct i40e_eth_stats {
 	u64 tx_errors;			/* tepc */
 };
 
+#ifdef I40E_FCOE
+/* Statistics collected per function for FCoE */
+struct i40e_fcoe_stats {
+	u64 rx_fcoe_packets;		/* fcoeprc */
+	u64 rx_fcoe_dwords;		/* focedwrc */
+	u64 rx_fcoe_dropped;		/* fcoerpdc */
+	u64 tx_fcoe_packets;		/* fcoeptc */
+	u64 tx_fcoe_dwords;		/* focedwtc */
+	u64 fcoe_bad_fccrc;		/* fcoecrc */
+	u64 fcoe_last_error;		/* fcoelast */
+	u64 fcoe_ddp_count;		/* fcoeddpc */
+};
+
+/* offset to per function FCoE statistics block */
+#define I40E_FCOE_VF_STAT_OFFSET	0
+#define I40E_FCOE_PF_STAT_OFFSET	128
+#define I40E_FCOE_STAT_MAX		(I40E_FCOE_PF_STAT_OFFSET + I40E_MAX_PF)
+
+#endif
 /* Statistics collected by the MAC */
 struct i40e_hw_port_stats {
 	/* eth stats collected by the port */
@@ -1061,6 +1150,125 @@ struct i40e_hw_port_stats {
 
 #define I40E_SRRD_SRCTL_ATTEMPTS	100000
 
+#ifdef I40E_FCOE
+/* FCoE Tx context descriptor - Use the i40e_tx_context_desc struct */
+
+enum i40E_fcoe_tx_ctx_desc_cmd_bits {
+	I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND	= 0x00, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2	= 0x01, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3	= 0x05, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS2	= 0x02, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS3	= 0x06, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS2	= 0x03, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS3	= 0x07, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL	= 0x08, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_CTX_INVL	= 0x09, /* 4 BITS */
+	I40E_FCOE_TX_CTX_DESC_RELOFF			= 0x10,
+	I40E_FCOE_TX_CTX_DESC_CLRSEQ			= 0x20,
+	I40E_FCOE_TX_CTX_DESC_DIFENA			= 0x40,
+	I40E_FCOE_TX_CTX_DESC_IL2TAG2			= 0x80
+};
+
+/* FCoE DDP Context descriptor */
+struct i40e_fcoe_ddp_context_desc {
+	__le64 rsvd;
+	__le64 type_cmd_foff_lsize;
+};
+
+#define I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT	0
+#define I40E_FCOE_DDP_CTX_QW1_DTYPE_MASK	(0xFULL << \
+					I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT)
+
+#define I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT	4
+#define I40E_FCOE_DDP_CTX_QW1_CMD_MASK	(0xFULL << \
+					 I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)
+
+enum i40e_fcoe_ddp_ctx_desc_cmd_bits {
+	I40E_FCOE_DDP_CTX_DESC_BSIZE_512B	= 0x00, /* 2 BITS */
+	I40E_FCOE_DDP_CTX_DESC_BSIZE_4K		= 0x01, /* 2 BITS */
+	I40E_FCOE_DDP_CTX_DESC_BSIZE_8K		= 0x02, /* 2 BITS */
+	I40E_FCOE_DDP_CTX_DESC_BSIZE_16K	= 0x03, /* 2 BITS */
+	I40E_FCOE_DDP_CTX_DESC_DIFENA		= 0x04, /* 1 BIT  */
+	I40E_FCOE_DDP_CTX_DESC_LASTSEQH		= 0x08, /* 1 BIT  */
+};
+
+#define I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT	16
+#define I40E_FCOE_DDP_CTX_QW1_FOFF_MASK	(0x3FFFULL << \
+					 I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)
+
+#define I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT	32
+#define I40E_FCOE_DDP_CTX_QW1_LSIZE_MASK	(0x3FFFULL << \
+					I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT)
+
+/* FCoE DDP/DWO Queue Context descriptor */
+struct i40e_fcoe_queue_context_desc {
+	__le64 dmaindx_fbase;           /* 0:11 DMAINDX, 12:63 FBASE */
+	__le64 flen_tph;                /* 0:12 FLEN, 13:15 TPH */
+};
+
+#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT	0
+#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_MASK	(0xFFFULL << \
+					I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT	12
+#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_MASK	(0xFFFFFFFFFFFFFULL << \
+					I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT	0
+#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_MASK	(0x1FFFULL << \
+					I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT	13
+#define I40E_FCOE_QUEUE_CTX_QW1_TPH_MASK	(0x7ULL << \
+					I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
+
+enum i40e_fcoe_queue_ctx_desc_tph_bits {
+	I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC	= 0x1,
+	I40E_FCOE_QUEUE_CTX_DESC_TPHDATA	= 0x2
+};
+
+#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT	30
+#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_MASK	(0x3ULL << \
+					I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT)
+
+/* FCoE DDP/DWO Filter Context descriptor */
+struct i40e_fcoe_filter_context_desc {
+	__le32 param;
+	__le16 seqn;
+
+	/* 48:51(0:3) RSVD, 52:63(4:15) DMAINDX */
+	__le16 rsvd_dmaindx;
+
+	/* 0:7 FLAGS, 8:52 RSVD, 53:63 LANQ */
+	__le64 flags_rsvd_lanq;
+};
+
+#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT	4
+#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_MASK	(0xFFF << \
+					I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT)
+
+enum i40e_fcoe_filter_ctx_desc_flags_bits {
+	I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP	= 0x00,
+	I40E_FCOE_FILTER_CTX_DESC_CTYP_DWO	= 0x01,
+	I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT	= 0x00,
+	I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP	= 0x02,
+	I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2	= 0x00,
+	I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3	= 0x04
+};
+
+#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT	0
+#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_MASK	(0xFFULL << \
+					I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT)
+
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT     8
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_MASK      (0x3FULL << \
+			I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT)
+
+#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT     53
+#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_MASK      (0x7FFULL << \
+			I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT)
+
+#endif /* I40E_FCOE */
 enum i40e_switch_element_types {
 	I40E_SWITCH_ELEMENT_TYPE_MAC	= 1,
 	I40E_SWITCH_ELEMENT_TYPE_PF	= 2,
@@ -1162,4 +1370,7 @@ enum i40e_reset_type {
 	I40E_RESET_GLOBR	= 2,
 	I40E_RESET_EMPR		= 3,
 };
+
+/* RSS Hash Table Size */
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_512	0x00010000
 #endif /* _I40E_TYPE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c	2014-09-28 17:29:07.000000000 -0400
@@ -347,10 +347,6 @@ static int i40e_config_vsi_rx_queue(stru
 	rx_ctx.dsize = 1;
 
 	/* default values */
-	rx_ctx.tphrdesc_ena = 1;
-	rx_ctx.tphwdesc_ena = 1;
-	rx_ctx.tphdata_ena = 1;
-	rx_ctx.tphhead_ena = 1;
 	rx_ctx.lrxqthresh = 2;
 	rx_ctx.crcstrip = 1;
 	rx_ctx.prefena = 1;
@@ -673,7 +669,7 @@ void i40e_reset_vf(struct i40e_vf *vf, b
 	 */
 	for (i = 0; i < 100; i++) {
 		/* vf reset requires driver to first reset the
-		 * vf & than poll the status register to make sure
+		 * vf and then poll the status register to make sure
 		 * that the requested op was completed
 		 * successfully
 		 */
@@ -1007,11 +1003,19 @@ int i40e_pci_sriov_configure(struct pci_
 static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
 				  u32 v_retval, u8 *msg, u16 msglen)
 {
-	struct i40e_pf *pf = vf->pf;
-	struct i40e_hw *hw = &pf->hw;
-	int true_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
+	struct i40e_pf *pf;
+	struct i40e_hw *hw;
+	int abs_vf_id;
 	i40e_status aq_ret;
 
+	/* validate the request */
+	if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
+		return -EINVAL;
+
+	pf = vf->pf;
+	hw = &pf->hw;
+	abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
+
 	/* single place to detect unsuccessful return values */
 	if (v_retval) {
 		vf->num_invalid_msgs++;
@@ -1029,7 +1033,7 @@ static int i40e_vc_send_msg_to_vf(struct
 		vf->num_valid_msgs++;
 	}
 
-	aq_ret = i40e_aq_send_msg_to_vf(hw, true_vf_id,	v_opcode, v_retval,
+	aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id,	v_opcode, v_retval,
 					msg, msglen, NULL);
 	if (aq_ret) {
 		dev_err(&pf->pdev->dev,
@@ -1167,8 +1171,8 @@ static int i40e_vc_config_promiscuous_mo
 	    (struct i40e_virtchnl_promisc_info *)msg;
 	struct i40e_pf *pf = vf->pf;
 	struct i40e_hw *hw = &pf->hw;
+	struct i40e_vsi *vsi;
 	bool allmulti = false;
-	bool promisc = false;
 	i40e_status aq_ret;
 
 	if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
@@ -1178,17 +1182,10 @@ static int i40e_vc_config_promiscuous_mo
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
-
-	if (info->flags & I40E_FLAG_VF_UNICAST_PROMISC)
-		promisc = true;
-	aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, info->vsi_id,
-						     promisc, NULL);
-	if (aq_ret)
-		goto error_param;
-
+	vsi = pf->vsi[info->vsi_id];
 	if (info->flags & I40E_FLAG_VF_MULTICAST_PROMISC)
 		allmulti = true;
-	aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, info->vsi_id,
+	aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
 						       allmulti, NULL);
 
 error_param:
@@ -1941,13 +1938,18 @@ static void i40e_vc_vf_broadcast(struct
 	struct i40e_vf *vf = pf->vf;
 	int i;
 
-	for (i = 0; i < pf->num_alloc_vfs; i++) {
+	for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
+		int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
+		/* Not all vfs are enabled so skip the ones that are not */
+		if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
+		    !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+			continue;
+
 		/* Ignore return value on purpose - a given VF may fail, but
 		 * we need to keep going and send to all of them
 		 */
-		i40e_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval,
+		i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
 				       msg, msglen, NULL);
-		vf++;
 	}
 }
 
@@ -1967,7 +1969,8 @@ void i40e_vc_notify_link_state(struct i4
 
 	pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
 	pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
-	for (i = 0; i < pf->num_alloc_vfs; i++) {
+	for (i = 0; i < pf->num_alloc_vfs; i++, vf++) {
+		int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
 		if (vf->link_forced) {
 			pfe.event_data.link_event.link_status = vf->link_up;
 			pfe.event_data.link_event.link_speed =
@@ -1977,10 +1980,9 @@ void i40e_vc_notify_link_state(struct i4
 				ls->link_info & I40E_AQ_LINK_UP;
 			pfe.event_data.link_event.link_speed = ls->link_speed;
 		}
-		i40e_aq_send_msg_to_vf(hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+		i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
 				       0, (u8 *)&pfe, sizeof(pfe),
 				       NULL);
-		vf++;
 	}
 }
 
@@ -2009,10 +2011,22 @@ void i40e_vc_notify_reset(struct i40e_pf
 void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
 {
 	struct i40e_virtchnl_pf_event pfe;
+	int abs_vf_id;
+
+	/* validate the request */
+	if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
+		return;
+
+	/* verify if the VF is in either init or active before proceeding */
+	if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) &&
+	    !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
+		return;
+
+	abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id;
 
 	pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING;
 	pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM;
-	i40e_aq_send_msg_to_vf(&vf->pf->hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+	i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
 			       I40E_SUCCESS, (u8 *)&pfe,
 			       sizeof(struct i40e_virtchnl_pf_event), NULL);
 }
@@ -2077,6 +2091,8 @@ int i40e_ndo_set_vf_mac(struct net_devic
 	}
 	ether_addr_copy(vf->default_lan_addr.addr, mac);
 	vf->pf_set_mac = true;
+	/* Force the VF driver stop so it has to reload with new MAC address */
+	i40e_vc_disable_vf(pf, vf);
 	dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
 	ret = 0;
 
@@ -2347,6 +2363,7 @@ int i40e_ndo_set_vf_link_state(struct ne
 	struct i40e_virtchnl_pf_event pfe;
 	struct i40e_hw *hw = &pf->hw;
 	struct i40e_vf *vf;
+	int abs_vf_id;
 	int ret = 0;
 
 	/* validate the request */
@@ -2357,6 +2374,7 @@ int i40e_ndo_set_vf_link_state(struct ne
 	}
 
 	vf = &pf->vf[vf_id];
+	abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
 
 	pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
 	pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
@@ -2386,7 +2404,7 @@ int i40e_ndo_set_vf_link_state(struct ne
 		goto error_out;
 	}
 	/* Notify the VF of its new link state */
-	i40e_aq_send_msg_to_vf(hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+	i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
 			       0, (u8 *)&pfe, sizeof(pfe), NULL);
 
 error_out:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40e/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40e/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -44,3 +44,4 @@ i40e-objs := i40e_main.o \
 	i40e_virtchnl_pf.o
 
 i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o
+i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,16 +53,24 @@ static void i40e_adminq_init_regs(struct
 		hw->aq.asq.tail = I40E_VF_ATQT1;
 		hw->aq.asq.head = I40E_VF_ATQH1;
 		hw->aq.asq.len  = I40E_VF_ATQLEN1;
+		hw->aq.asq.bal  = I40E_VF_ATQBAL1;
+		hw->aq.asq.bah  = I40E_VF_ATQBAH1;
 		hw->aq.arq.tail = I40E_VF_ARQT1;
 		hw->aq.arq.head = I40E_VF_ARQH1;
 		hw->aq.arq.len  = I40E_VF_ARQLEN1;
+		hw->aq.arq.bal  = I40E_VF_ARQBAL1;
+		hw->aq.arq.bah  = I40E_VF_ARQBAH1;
 	} else {
 		hw->aq.asq.tail = I40E_PF_ATQT;
 		hw->aq.asq.head = I40E_PF_ATQH;
 		hw->aq.asq.len  = I40E_PF_ATQLEN;
+		hw->aq.asq.bal  = I40E_PF_ATQBAL;
+		hw->aq.asq.bah  = I40E_PF_ATQBAH;
 		hw->aq.arq.tail = I40E_PF_ARQT;
 		hw->aq.arq.head = I40E_PF_ARQH;
 		hw->aq.arq.len  = I40E_PF_ARQLEN;
+		hw->aq.arq.bal  = I40E_PF_ARQBAL;
+		hw->aq.arq.bah  = I40E_PF_ARQBAH;
 	}
 }
 
@@ -294,27 +302,18 @@ static i40e_status i40e_config_asq_regs(
 	i40e_status ret_code = 0;
 	u32 reg = 0;
 
-	if (hw->mac.type == I40E_MAC_VF) {
-		/* configure the transmit queue */
-		wr32(hw, I40E_VF_ATQBAH1,
-		    upper_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_VF_ATQBAL1,
-		    lower_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
-					  I40E_VF_ATQLEN1_ATQENABLE_MASK));
-		reg = rd32(hw, I40E_VF_ATQBAL1);
-	} else {
-		/* configure the transmit queue */
-		wr32(hw, I40E_PF_ATQBAH,
-		    upper_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_PF_ATQBAL,
-		    lower_32_bits(hw->aq.asq.desc_buf.pa));
-		wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
-					  I40E_PF_ATQLEN_ATQENABLE_MASK));
-		reg = rd32(hw, I40E_PF_ATQBAL);
-	}
+	/* Clear Head and Tail */
+	wr32(hw, hw->aq.asq.head, 0);
+	wr32(hw, hw->aq.asq.tail, 0);
+
+	/* set starting point */
+	wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
+				  I40E_PF_ATQLEN_ATQENABLE_MASK));
+	wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
+	wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
 
 	/* Check one register to verify that config was applied */
+	reg = rd32(hw, hw->aq.asq.bal);
 	if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
 
@@ -332,30 +331,21 @@ static i40e_status i40e_config_arq_regs(
 	i40e_status ret_code = 0;
 	u32 reg = 0;
 
-	if (hw->mac.type == I40E_MAC_VF) {
-		/* configure the receive queue */
-		wr32(hw, I40E_VF_ARQBAH1,
-		    upper_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_VF_ARQBAL1,
-		    lower_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
-					  I40E_VF_ARQLEN1_ARQENABLE_MASK));
-		reg = rd32(hw, I40E_VF_ARQBAL1);
-	} else {
-		/* configure the receive queue */
-		wr32(hw, I40E_PF_ARQBAH,
-		    upper_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_PF_ARQBAL,
-		    lower_32_bits(hw->aq.arq.desc_buf.pa));
-		wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
-					  I40E_PF_ARQLEN_ARQENABLE_MASK));
-		reg = rd32(hw, I40E_PF_ARQBAL);
-	}
+	/* Clear Head and Tail */
+	wr32(hw, hw->aq.arq.head, 0);
+	wr32(hw, hw->aq.arq.tail, 0);
+
+	/* set starting point */
+	wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
+				  I40E_PF_ARQLEN_ARQENABLE_MASK));
+	wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
+	wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
 
 	/* Update tail in the HW to post pre-allocated buffers */
 	wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
 
 	/* Check one register to verify that config was applied */
+	reg = rd32(hw, hw->aq.arq.bal);
 	if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
 
@@ -497,6 +487,8 @@ static i40e_status i40e_shutdown_asq(str
 	wr32(hw, hw->aq.asq.head, 0);
 	wr32(hw, hw->aq.asq.tail, 0);
 	wr32(hw, hw->aq.asq.len, 0);
+	wr32(hw, hw->aq.asq.bal, 0);
+	wr32(hw, hw->aq.asq.bah, 0);
 
 	/* make sure lock is available */
 	mutex_lock(&hw->aq.asq_mutex);
@@ -528,6 +520,8 @@ static i40e_status i40e_shutdown_arq(str
 	wr32(hw, hw->aq.arq.head, 0);
 	wr32(hw, hw->aq.arq.tail, 0);
 	wr32(hw, hw->aq.arq.len, 0);
+	wr32(hw, hw->aq.arq.bal, 0);
+	wr32(hw, hw->aq.arq.bah, 0);
 
 	/* make sure lock is available */
 	mutex_lock(&hw->aq.arq_mutex);
@@ -573,6 +567,9 @@ i40e_status i40evf_init_adminq(struct i4
 	/* Set up register offsets */
 	i40e_adminq_init_regs(hw);
 
+	/* setup ASQ command write back timeout */
+	hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
+
 	/* allocate the ASQ */
 	ret_code = i40e_init_asq(hw);
 	if (ret_code)
@@ -630,6 +627,10 @@ static u16 i40e_clean_asq(struct i40e_hw
 	desc = I40E_ADMINQ_DESC(*asq, ntc);
 	details = I40E_ADMINQ_DETAILS(*asq, ntc);
 	while (rd32(hw, hw->aq.asq.head) != ntc) {
+		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+			   "%s: ntc %d head %d.\n", __func__, ntc,
+			   rd32(hw, hw->aq.asq.head));
+
 		if (details->callback) {
 			I40E_ADMINQ_CALLBACK cb_func =
 					(I40E_ADMINQ_CALLBACK)details->callback;
@@ -690,17 +691,20 @@ i40e_status i40evf_asq_send_command(stru
 	struct i40e_aq_desc *desc_on_ring;
 	bool cmd_completed = false;
 	u16  retval = 0;
+	u32  val = 0;
 
-	if (hw->aq.asq.count == 0) {
+	val = rd32(hw, hw->aq.asq.head);
+	if (val >= hw->aq.num_asq_entries) {
 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
-			   "AQTX: Admin queue not initialized.\n");
+			   "AQTX: head overrun at %d\n", val);
 		status = I40E_ERR_QUEUE_EMPTY;
 		goto asq_send_command_exit;
 	}
 
-	if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
-		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
-		status = I40E_ERR_NVM;
+	if (hw->aq.asq.count == 0) {
+		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+			   "AQTX: Admin queue not initialized.\n");
+		status = I40E_ERR_QUEUE_EMPTY;
 		goto asq_send_command_exit;
 	}
 
@@ -783,6 +787,7 @@ i40e_status i40evf_asq_send_command(stru
 	}
 
 	/* bump the tail */
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
 	i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff);
 	(hw->aq.asq.next_to_use)++;
 	if (hw->aq.asq.next_to_use == hw->aq.asq.count)
@@ -806,7 +811,7 @@ i40e_status i40evf_asq_send_command(stru
 			/* ugh! delay while spin_lock */
 			udelay(delay_len);
 			total_delay += delay_len;
-		} while (total_delay <  I40E_ASQ_CMD_TIMEOUT);
+		} while (total_delay < hw->aq.asq_cmd_timeout);
 	}
 
 	/* if ready, copy the desc back to temp */
@@ -820,6 +825,7 @@ i40e_status i40evf_asq_send_command(stru
 				   I40E_DEBUG_AQ_MESSAGE,
 				   "AQTX: Command completed with error 0x%X.\n",
 				   retval);
+
 			/* strip off FW internal code */
 			retval &= 0xff;
 		}
@@ -834,6 +840,10 @@ i40e_status i40evf_asq_send_command(stru
 	if (i40e_is_nvm_update_op(desc))
 		hw->aq.nvm_busy = true;
 
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+		   "AQTX: desc and buffer writeback:\n");
+	i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
+
 	/* update the error if time out occurred */
 	if ((!cmd_completed) &&
 	    (!details->async && !details->postpone)) {
@@ -905,10 +915,6 @@ i40e_status i40evf_clean_arq_element(str
 	/* now clean the next descriptor */
 	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
 	desc_idx = ntc;
-	i40evf_debug_aq(hw,
-		      I40E_DEBUG_AQ_COMMAND,
-		      (void *)desc,
-		      hw->aq.arq.r.arq_bi[desc_idx].va);
 
 	flags = le16_to_cpu(desc->flags);
 	if (flags & I40E_AQ_FLAG_ERR) {
@@ -919,18 +925,21 @@ i40e_status i40evf_clean_arq_element(str
 			   I40E_DEBUG_AQ_MESSAGE,
 			   "AQRX: Event received with error 0x%X.\n",
 			   hw->aq.arq_last_status);
-	} else {
-		e->desc = *desc;
-		datalen = le16_to_cpu(desc->datalen);
-		e->msg_size = min(datalen, e->msg_size);
-		if (e->msg_buf != NULL && (e->msg_size != 0))
-			memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
-			       e->msg_size);
 	}
 
+	e->desc = *desc;
+	datalen = le16_to_cpu(desc->datalen);
+	e->msg_size = min(datalen, e->msg_size);
+	if (e->msg_buf != NULL && (e->msg_size != 0))
+		memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+		       e->msg_size);
+
 	if (i40e_is_nvm_update_op(&e->desc))
 		hw->aq.nvm_busy = false;
 
+	i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
+	i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
+
 	/* Restore the original datalen and buffer address in the desc,
 	 * FW updates datalen to indicate the event message
 	 * size
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,6 +56,8 @@ struct i40e_adminq_ring {
 	u32 head;
 	u32 tail;
 	u32 len;
+	u32 bah;
+	u32 bal;
 };
 
 /* ASQ transaction details */
@@ -82,6 +84,7 @@ struct i40e_arq_event_info {
 struct i40e_adminq_info {
 	struct i40e_adminq_ring arq;    /* receive queue */
 	struct i40e_adminq_ring asq;    /* send queue */
+	u32 asq_cmd_timeout;            /* send queue cmd write back timeout*/
 	u16 num_arq_entries;            /* receive queue depth */
 	u16 num_asq_entries;            /* send queue depth */
 	u16 arq_buf_size;               /* receive queue buffer size */
@@ -91,6 +94,7 @@ struct i40e_adminq_info {
 	u16 api_maj_ver;                /* api major version */
 	u16 api_min_ver;                /* api minor version */
 	bool nvm_busy;
+	bool nvm_release_on_done;
 
 	struct mutex asq_mutex; /* Send queue lock */
 	struct mutex arq_mutex; /* Receive queue lock */
@@ -100,6 +104,41 @@ struct i40e_adminq_info {
 	enum i40e_admin_queue_err arq_last_status;
 };
 
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_rc: AdminQ error code to convert
+ **/
+static inline int i40e_aq_rc_to_posix(u16 aq_rc)
+{
+	int aq_to_posix[] = {
+		0,           /* I40E_AQ_RC_OK */
+		-EPERM,      /* I40E_AQ_RC_EPERM */
+		-ENOENT,     /* I40E_AQ_RC_ENOENT */
+		-ESRCH,      /* I40E_AQ_RC_ESRCH */
+		-EINTR,      /* I40E_AQ_RC_EINTR */
+		-EIO,        /* I40E_AQ_RC_EIO */
+		-ENXIO,      /* I40E_AQ_RC_ENXIO */
+		-E2BIG,      /* I40E_AQ_RC_E2BIG */
+		-EAGAIN,     /* I40E_AQ_RC_EAGAIN */
+		-ENOMEM,     /* I40E_AQ_RC_ENOMEM */
+		-EACCES,     /* I40E_AQ_RC_EACCES */
+		-EFAULT,     /* I40E_AQ_RC_EFAULT */
+		-EBUSY,      /* I40E_AQ_RC_EBUSY */
+		-EEXIST,     /* I40E_AQ_RC_EEXIST */
+		-EINVAL,     /* I40E_AQ_RC_EINVAL */
+		-ENOTTY,     /* I40E_AQ_RC_ENOTTY */
+		-ENOSPC,     /* I40E_AQ_RC_ENOSPC */
+		-ENOSYS,     /* I40E_AQ_RC_ENOSYS */
+		-ERANGE,     /* I40E_AQ_RC_ERANGE */
+		-EPIPE,      /* I40E_AQ_RC_EFLUSHED */
+		-ESPIPE,     /* I40E_AQ_RC_BAD_ADDR */
+		-EROFS,      /* I40E_AQ_RC_EMODE */
+		-EFBIG,      /* I40E_AQ_RC_EFBIG */
+	};
+
+	return aq_to_posix[aq_rc];
+}
+
 /* general information */
 #define I40E_AQ_LARGE_BUF	512
 #define I40E_ASQ_CMD_TIMEOUT	100000  /* usecs */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -551,6 +551,7 @@ i40e_status i40e_aq_send_msg_to_pf(struc
 				struct i40e_asq_cmd_details *cmd_details)
 {
 	struct i40e_aq_desc desc;
+	struct i40e_asq_cmd_details details;
 	i40e_status status;
 
 	i40evf_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf);
@@ -565,7 +566,6 @@ i40e_status i40e_aq_send_msg_to_pf(struc
 		desc.datalen = cpu_to_le16(msglen);
 	}
 	if (!cmd_details) {
-		struct i40e_asq_cmd_details details;
 		memset(&details, 0, sizeof(details));
 		details.async = true;
 		cmd_details = &details;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_hmc.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_hmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_hmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -127,7 +127,7 @@ struct i40e_hmc_info {
 		((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<		\
 		I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) |			\
 		(1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT);		\
-	val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
+	val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
 	wr32((hw), I40E_PFHMC_SDDATAHIGH, val1);			\
 	wr32((hw), I40E_PFHMC_SDDATALOW, val2);				\
 	wr32((hw), I40E_PFHMC_SDCMD, val3);				\
@@ -146,7 +146,7 @@ struct i40e_hmc_info {
 		I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |		\
 		((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) <<		\
 		I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT);			\
-	val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
+	val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT);	\
 	wr32((hw), I40E_PFHMC_SDDATAHIGH, 0);				\
 	wr32((hw), I40E_PFHMC_SDDATALOW, val2);				\
 	wr32((hw), I40E_PFHMC_SDCMD, val3);				\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,16 +32,22 @@ struct i40e_hw;
 
 /* HMC element context information */
 
-/* Rx queue context data */
+/* Rx queue context data
+ *
+ * The sizes of the variables may be larger than needed due to crossing byte
+ * boundaries. If we do not have the width of the variable set to the correct
+ * size then we could end up shifting bits off the top of the variable when the
+ * variable is at the top of a byte and crosses over into the next byte.
+ */
 struct i40e_hmc_obj_rxq {
 	u16 head;
-	u8  cpuid;
+	u16 cpuid; /* bigger than needed, see above for reason */
 	u64 base;
 	u16 qlen;
 #define I40E_RXQ_CTX_DBUFF_SHIFT 7
-	u8  dbuff;
+	u16 dbuff; /* bigger than needed, see above for reason */
 #define I40E_RXQ_CTX_HBUFF_SHIFT 6
-	u8  hbuff;
+	u16 hbuff; /* bigger than needed, see above for reason */
 	u8  dtype;
 	u8  dsize;
 	u8  crcstrip;
@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
 	u8  hsplit_0;
 	u8  hsplit_1;
 	u8  showiv;
-	u16 rxmax;
+	u32 rxmax; /* bigger than needed, see above for reason */
 	u8  tphrdesc_ena;
 	u8  tphwdesc_ena;
 	u8  tphdata_ena;
 	u8  tphhead_ena;
-	u8  lrxqthresh;
+	u16 lrxqthresh; /* bigger than needed, see above for reason */
 	u8  prefena;	/* NOTE: normally must be set to 1 at init */
 };
 
-/* Tx queue context data */
+/* Tx queue context data
+*
+* The sizes of the variables may be larger than needed due to crossing byte
+* boundaries. If we do not have the width of the variable set to the correct
+* size then we could end up shifting bits off the top of the variable when the
+* variable is at the top of a byte and crosses over into the next byte.
+*/
 struct i40e_hmc_obj_txq {
 	u16 head;
 	u8  new_context;
@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
 	u8  fd_ena;
 	u8  alt_vlan_ena;
 	u16 thead_wb;
-	u16 cpuid;
+	u8  cpuid;
 	u8  head_wb_ena;
 	u16 qlen;
 	u8  tphrdesc_ena;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_register.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_register.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_register.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_register.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,4648 +27,3343 @@
 #ifndef _I40E_REGISTER_H_
 #define _I40E_REGISTER_H_
 
-#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
-#define I40E_GL_GP_FUSE_MAX_INDEX 28
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
-#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
-
-#define I40E_PF_ARQBAH 0x00080180
+#define I40E_GL_ARQBAH 0x000801C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_GL_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAH_ARQBAH_SHIFT)
+#define I40E_GL_ARQBAL 0x000800C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_GL_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAL_ARQBAL_SHIFT)
+#define I40E_GL_ARQH 0x000803C0 /* Reset: EMPR */
+#define I40E_GL_ARQH_ARQH_SHIFT 0
+#define I40E_GL_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_GL_ARQH_ARQH_SHIFT)
+#define I40E_GL_ARQT 0x000804C0 /* Reset: EMPR */
+#define I40E_GL_ARQT_ARQT_SHIFT 0
+#define I40E_GL_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_GL_ARQT_ARQT_SHIFT)
+#define I40E_GL_ATQBAH 0x00080140 /* Reset: EMPR */
+#define I40E_GL_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_GL_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAH_ATQBAH_SHIFT)
+#define I40E_GL_ATQBAL 0x00080040 /* Reset: EMPR */
+#define I40E_GL_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_GL_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAL_ATQBAL_SHIFT)
+#define I40E_GL_ATQH 0x00080340 /* Reset: EMPR */
+#define I40E_GL_ATQH_ATQH_SHIFT 0
+#define I40E_GL_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_GL_ATQH_ATQH_SHIFT)
+#define I40E_GL_ATQLEN 0x00080240 /* Reset: EMPR */
+#define I40E_GL_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_GL_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_GL_ATQLEN_ATQLEN_SHIFT)
+#define I40E_GL_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_GL_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQVFE_SHIFT)
+#define I40E_GL_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_GL_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_GL_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_GL_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_GL_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_GL_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_GL_ATQT 0x00080440 /* Reset: EMPR */
+#define I40E_GL_ATQT_ATQT_SHIFT 0
+#define I40E_GL_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_GL_ATQT_ATQT_SHIFT)
+#define I40E_PF_ARQBAH 0x00080180 /* Reset: EMPR */
 #define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_PF_ARQBAL 0x00080080
+#define I40E_PF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_PF_ARQBAL 0x00080080 /* Reset: EMPR */
 #define I40E_PF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_PF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_PF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_PF_ARQH 0x00080380
+#define I40E_PF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_PF_ARQH 0x00080380 /* Reset: EMPR */
 #define I40E_PF_ARQH_ARQH_SHIFT 0
-#define I40E_PF_ARQH_ARQH_MASK (0x3FF << I40E_PF_ARQH_ARQH_SHIFT)
-#define I40E_PF_ARQLEN 0x00080280
+#define I40E_PF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_PF_ARQH_ARQH_SHIFT)
+#define I40E_PF_ARQLEN 0x00080280 /* Reset: EMPR */
 #define I40E_PF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_PF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_PF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_PF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ARQLEN_ARQLEN_SHIFT)
 #define I40E_PF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_PF_ARQLEN_ARQVFE_MASK (0x1 << I40E_PF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_PF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQVFE_SHIFT)
 #define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_PF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_PF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_PF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQOVFL_SHIFT)
 #define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_PF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_PF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT)
 #define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_PF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_PF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_PF_ARQT 0x00080480
+#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */
 #define I40E_PF_ARQT_ARQT_SHIFT 0
-#define I40E_PF_ARQT_ARQT_MASK (0x3FF << I40E_PF_ARQT_ARQT_SHIFT)
-#define I40E_PF_ATQBAH 0x00080100
+#define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT)
+#define I40E_PF_ATQBAH 0x00080100 /* Reset: EMPR */
 #define I40E_PF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_PF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_PF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_PF_ATQBAL 0x00080000
+#define I40E_PF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_PF_ATQBAL 0x00080000 /* Reset: EMPR */
 #define I40E_PF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_PF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_PF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_PF_ATQH 0x00080300
+#define I40E_PF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_PF_ATQH 0x00080300 /* Reset: EMPR */
 #define I40E_PF_ATQH_ATQH_SHIFT 0
-#define I40E_PF_ATQH_ATQH_MASK (0x3FF << I40E_PF_ATQH_ATQH_SHIFT)
-#define I40E_PF_ATQLEN 0x00080200
+#define I40E_PF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_PF_ATQH_ATQH_SHIFT)
+#define I40E_PF_ATQLEN 0x00080200 /* Reset: EMPR */
 #define I40E_PF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_PF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_PF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_PF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ATQLEN_ATQLEN_SHIFT)
 #define I40E_PF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_PF_ATQLEN_ATQVFE_MASK (0x1 << I40E_PF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_PF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQVFE_SHIFT)
 #define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_PF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_PF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_PF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQOVFL_SHIFT)
 #define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_PF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_PF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT)
 #define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_PF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_PF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_PF_ATQT 0x00080400
+#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */
 #define I40E_PF_ATQT_ATQT_SHIFT 0
-#define I40E_PF_ATQT_ATQT_MASK (0x3FF << I40E_PF_ATQT_ATQT_SHIFT)
-#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT)
+#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQBAH_MAX_INDEX 127
 #define I40E_VF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQBAL_MAX_INDEX 127
 #define I40E_VF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQH_MAX_INDEX 127
 #define I40E_VF_ARQH_ARQH_SHIFT 0
-#define I40E_VF_ARQH_ARQH_MASK (0x3FF << I40E_VF_ARQH_ARQH_SHIFT)
-#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH_ARQH_SHIFT)
+#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQLEN_MAX_INDEX 127
 #define I40E_VF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN_ARQLEN_SHIFT)
 #define I40E_VF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQVFE_SHIFT)
 #define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQOVFL_SHIFT)
 #define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT)
 #define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ARQT_MAX_INDEX 127
 #define I40E_VF_ARQT_ARQT_SHIFT 0
-#define I40E_VF_ARQT_ARQT_MASK (0x3FF << I40E_VF_ARQT_ARQT_SHIFT)
-#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT_ARQT_SHIFT)
+#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQBAH_MAX_INDEX 127
 #define I40E_VF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQBAL_MAX_INDEX 127
 #define I40E_VF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQH_MAX_INDEX 127
 #define I40E_VF_ATQH_ATQH_SHIFT 0
-#define I40E_VF_ATQH_ATQH_MASK (0x3FF << I40E_VF_ATQH_ATQH_SHIFT)
-#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH_ATQH_SHIFT)
+#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQLEN_MAX_INDEX 127
 #define I40E_VF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN_ATQLEN_SHIFT)
 #define I40E_VF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQVFE_SHIFT)
 #define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQOVFL_SHIFT)
 #define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT)
 #define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
 #define I40E_VF_ATQT_MAX_INDEX 127
 #define I40E_VF_ATQT_ATQT_SHIFT 0
-#define I40E_VF_ATQT_ATQT_MASK (0x3FF << I40E_VF_ATQT_ATQT_SHIFT)
-#define I40E_PRT_L2TAGSEN 0x001C0B20
+#define I40E_VF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT_ATQT_SHIFT)
+#define I40E_PRT_L2TAGSEN 0x001C0B20 /* Reset: CORER */
 #define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0
-#define I40E_PRT_L2TAGSEN_ENABLE_MASK (0xFF << I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
-#define I40E_PFCM_LAN_ERRDATA 0x0010C080
+#define I40E_PRT_L2TAGSEN_ENABLE_MASK I40E_MASK(0xFF, I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA 0x0010C080 /* Reset: PFR */
 #define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
 #define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
 #define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK (0xFFF << I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_LAN_ERRINFO 0x0010C000
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO 0x0010C000 /* Reset: PFR */
 #define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
 #define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_PFCM_LANCTXCTL(_pf) (0x0010C300 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LANCTXCTL 0x0010C300 /* Reset: CORER */
 #define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0
-#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK (0xFFF << I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
 #define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12
-#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK (0x7 << I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK I40E_MASK(0x7, I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
 #define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15
-#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK (0x3 << I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
 #define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17
-#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK (0x3 << I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
-#define I40E_PFCM_LANCTXDATA(_i, _pf) (0x0010C100 + ((_i) * 4) + ((_pf) * 16))/* _i=0...3 _pf=0..15 */
+#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
+#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PFCM_LANCTXDATA_MAX_INDEX 3
 #define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0
-#define I40E_PFCM_LANCTXDATA_DATA_MASK (0xFFFFFFFF << I40E_PFCM_LANCTXDATA_DATA_SHIFT)
-#define I40E_PFCM_LANCTXSTAT(_pf) (0x0010C380 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LANCTXDATA_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFCM_LANCTXDATA_DATA_SHIFT)
+#define I40E_PFCM_LANCTXSTAT 0x0010C380 /* Reset: CORER */
 #define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0
-#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
 #define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1
-#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
-#define I40E_PFCM_PE_ERRDATA 0x00138D00
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_PE_ERRINFO 0x00138C80
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127
 #define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127
 #define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
-#define I40E_GLDCB_GENC 0x00083044
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
+#define I40E_GLDCB_GENC 0x00083044 /* Reset: CORER */
 #define I40E_GLDCB_GENC_PCIRTT_SHIFT 0
-#define I40E_GLDCB_GENC_PCIRTT_MASK (0xFFFF << I40E_GLDCB_GENC_PCIRTT_SHIFT)
-#define I40E_GLDCB_RUPTI 0x00122618
+#define I40E_GLDCB_GENC_PCIRTT_MASK I40E_MASK(0xFFFF, I40E_GLDCB_GENC_PCIRTT_SHIFT)
+#define I40E_GLDCB_RUPTI 0x00122618 /* Reset: CORER */
 #define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0
-#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK (0xFFFFFFFF << I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
-#define I40E_PRTDCB_FCCFG 0x001E4640
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
+#define I40E_PRTDCB_FCCFG 0x001E4640 /* Reset: GLOBR */
 #define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3
-#define I40E_PRTDCB_FCCFG_TFCE_MASK (0x3 << I40E_PRTDCB_FCCFG_TFCE_SHIFT)
-#define I40E_PRTDCB_FCRTV 0x001E4600
+#define I40E_PRTDCB_FCCFG_TFCE_MASK I40E_MASK(0x3, I40E_PRTDCB_FCCFG_TFCE_SHIFT)
+#define I40E_PRTDCB_FCRTV 0x001E4600 /* Reset: GLOBR */
 #define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0
-#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK (0xFFFF << I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
-#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
+#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: GLOBR */
 #define I40E_PRTDCB_FCTTVN_MAX_INDEX 3
 #define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0
-#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
+#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
 #define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16
-#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
-#define I40E_PRTDCB_GENC 0x00083000
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
+#define I40E_PRTDCB_GENC 0x00083000 /* Reset: CORER */
 #define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0
-#define I40E_PRTDCB_GENC_RESERVED_1_MASK (0x3 << I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
+#define I40E_PRTDCB_GENC_RESERVED_1_MASK I40E_MASK(0x3, I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
 #define I40E_PRTDCB_GENC_NUMTC_SHIFT 2
-#define I40E_PRTDCB_GENC_NUMTC_MASK (0xF << I40E_PRTDCB_GENC_NUMTC_SHIFT)
+#define I40E_PRTDCB_GENC_NUMTC_MASK I40E_MASK(0xF, I40E_PRTDCB_GENC_NUMTC_SHIFT)
 #define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6
-#define I40E_PRTDCB_GENC_FCOEUP_MASK (0x7 << I40E_PRTDCB_GENC_FCOEUP_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_MASK I40E_MASK(0x7, I40E_PRTDCB_GENC_FCOEUP_SHIFT)
 #define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9
-#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK (0x1 << I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK I40E_MASK(0x1, I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
 #define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16
-#define I40E_PRTDCB_GENC_PFCLDA_MASK (0xFFFF << I40E_PRTDCB_GENC_PFCLDA_SHIFT)
-#define I40E_PRTDCB_GENS 0x00083020
+#define I40E_PRTDCB_GENC_PFCLDA_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_GENC_PFCLDA_SHIFT)
+#define I40E_PRTDCB_GENS 0x00083020 /* Reset: CORER */
 #define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0
-#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK (0x7 << I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
-#define I40E_PRTDCB_MFLCN 0x001E2400
+#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK I40E_MASK(0x7, I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
+#define I40E_PRTDCB_MFLCN 0x001E2400 /* Reset: GLOBR */
 #define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0
-#define I40E_PRTDCB_MFLCN_PMCF_MASK (0x1 << I40E_PRTDCB_MFLCN_PMCF_SHIFT)
+#define I40E_PRTDCB_MFLCN_PMCF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_PMCF_SHIFT)
 #define I40E_PRTDCB_MFLCN_DPF_SHIFT 1
-#define I40E_PRTDCB_MFLCN_DPF_MASK (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT)
+#define I40E_PRTDCB_MFLCN_DPF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_DPF_SHIFT)
 #define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2
-#define I40E_PRTDCB_MFLCN_RPFCM_MASK (0x1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCM_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
 #define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3
-#define I40E_PRTDCB_MFLCN_RFCE_MASK (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT)
+#define I40E_PRTDCB_MFLCN_RFCE_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RFCE_SHIFT)
 #define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4
-#define I40E_PRTDCB_MFLCN_RPFCE_MASK (0xFF << I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
-#define I40E_PRTDCB_RETSC 0x001223E0
+#define I40E_PRTDCB_MFLCN_RPFCE_MASK I40E_MASK(0xFF, I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
+#define I40E_PRTDCB_RETSC 0x001223E0 /* Reset: CORER */
 #define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0
-#define I40E_PRTDCB_RETSC_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
 #define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1
-#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
 #define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2
-#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK (0xF << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK I40E_MASK(0xF, I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
 #define I40E_PRTDCB_RETSC_LLTC_SHIFT 8
-#define I40E_PRTDCB_RETSC_LLTC_MASK (0xFF << I40E_PRTDCB_RETSC_LLTC_SHIFT)
-#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_RETSC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_RETSC_LLTC_SHIFT)
+#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTDCB_RETSTCC_MAX_INDEX 7
 #define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0
-#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK (0x7F << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK I40E_MASK(0x7F, I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
 #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30
-#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK (0x1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
 #define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31
-#define I40E_PRTDCB_RETSTCC_ETSTC_MASK (0x1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
-#define I40E_PRTDCB_RPPMC 0x001223A0
+#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
+#define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */
 #define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0
-#define I40E_PRTDCB_RPPMC_LANRPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
 #define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8
-#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
 #define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16
-#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK (0xFF << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
-#define I40E_PRTDCB_RUP 0x001C0B00
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
+#define I40E_PRTDCB_RUP 0x001C0B00 /* Reset: CORER */
 #define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0
-#define I40E_PRTDCB_RUP_NOVLANUP_MASK (0x7 << I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
-#define I40E_PRTDCB_RUP2TC 0x001C09A0
+#define I40E_PRTDCB_RUP_NOVLANUP_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
+#define I40E_PRTDCB_RUP2TC 0x001C09A0 /* Reset: CORER */
 #define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0
-#define I40E_PRTDCB_RUP2TC_UP0TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP0TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3
-#define I40E_PRTDCB_RUP2TC_UP1TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP1TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6
-#define I40E_PRTDCB_RUP2TC_UP2TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP2TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9
-#define I40E_PRTDCB_RUP2TC_UP3TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP3TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12
-#define I40E_PRTDCB_RUP2TC_UP4TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP4TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15
-#define I40E_PRTDCB_RUP2TC_UP5TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP5TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18
-#define I40E_PRTDCB_RUP2TC_UP6TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP6TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
 #define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21
-#define I40E_PRTDCB_RUP2TC_UP7TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
-#define I40E_PRTDCB_TC2PFC 0x001C0980
+#define I40E_PRTDCB_RUP2TC_UP7TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
+#define I40E_PRTDCB_TC2PFC 0x001C0980 /* Reset: CORER */
 #define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0
-#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK (0xFF << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
-#define I40E_PRTDCB_TCPMC 0x000A21A0
+#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
+#define I40E_PRTDCB_TCMSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
+#define I40E_PRTDCB_TCMSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TCMSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TCMSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCMSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TCPMC 0x000A21A0 /* Reset: CORER */
 #define I40E_PRTDCB_TCPMC_CPM_SHIFT 0
-#define I40E_PRTDCB_TCPMC_CPM_MASK (0x1FFF << I40E_PRTDCB_TCPMC_CPM_SHIFT)
+#define I40E_PRTDCB_TCPMC_CPM_MASK I40E_MASK(0x1FFF, I40E_PRTDCB_TCPMC_CPM_SHIFT)
 #define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13
-#define I40E_PRTDCB_TCPMC_LLTC_MASK (0xFF << I40E_PRTDCB_TCPMC_LLTC_SHIFT)
+#define I40E_PRTDCB_TCPMC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TCPMC_LLTC_SHIFT)
 #define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTDCB_TCWSTC_MAX_INDEX 7
 #define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TCWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TDPMC 0x000A0180
+#define I40E_PRTDCB_TCWSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TDPMC 0x000A0180 /* Reset: CORER */
 #define I40E_PRTDCB_TDPMC_DPM_SHIFT 0
-#define I40E_PRTDCB_TDPMC_DPM_MASK (0xFF << I40E_PRTDCB_TDPMC_DPM_SHIFT)
+#define I40E_PRTDCB_TDPMC_DPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_TDPMC_DPM_SHIFT)
 #define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TDPUC 0x00044100
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT 0
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_MASK (0xFFFF << I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT)
-#define I40E_PRTDCB_TETSC_TCB 0x000AE060
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB 0x000AE060 /* Reset: CORER */
 #define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
 #define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
-#define I40E_PRTDCB_TETSC_TPB 0x00098060
+#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB 0x00098060 /* Reset: CORER */
 #define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
 #define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
-#define I40E_PRTDCB_TFCS 0x001E4560
+#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
+#define I40E_PRTDCB_TFCS 0x001E4560 /* Reset: GLOBR */
 #define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0
-#define I40E_PRTDCB_TFCS_TXOFF_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8
-#define I40E_PRTDCB_TFCS_TXOFF0_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF0_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9
-#define I40E_PRTDCB_TFCS_TXOFF1_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF1_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10
-#define I40E_PRTDCB_TFCS_TXOFF2_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF2_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11
-#define I40E_PRTDCB_TFCS_TXOFF3_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF3_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12
-#define I40E_PRTDCB_TFCS_TXOFF4_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF4_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13
-#define I40E_PRTDCB_TFCS_TXOFF5_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF5_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14
-#define I40E_PRTDCB_TFCS_TXOFF6_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF6_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
 #define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15
-#define I40E_PRTDCB_TFCS_TXOFF7_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
-#define I40E_PRTDCB_TFWSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */
-#define I40E_PRTDCB_TFWSTC_MAX_INDEX 7
-#define I40E_PRTDCB_TFWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TFWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TFWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TFCS_TXOFF7_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
+#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */ /* Reset: GLOBR */
 #define I40E_PRTDCB_TPFCTS_MAX_INDEX 7
 #define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0
-#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK (0x3FFF << I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
-#define I40E_GLFCOE_RCTL 0x00269B94
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
+#define I40E_GLFCOE_RCTL 0x00269B94 /* Reset: CORER */
 #define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0
-#define I40E_GLFCOE_RCTL_FCOEVER_MASK (0xF << I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
+#define I40E_GLFCOE_RCTL_FCOEVER_MASK I40E_MASK(0xF, I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
 #define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4
-#define I40E_GLFCOE_RCTL_SAVBAD_MASK (0x1 << I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
+#define I40E_GLFCOE_RCTL_SAVBAD_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
 #define I40E_GLFCOE_RCTL_ICRC_SHIFT 5
-#define I40E_GLFCOE_RCTL_ICRC_MASK (0x1 << I40E_GLFCOE_RCTL_ICRC_SHIFT)
+#define I40E_GLFCOE_RCTL_ICRC_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_ICRC_SHIFT)
 #define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16
-#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK (0x3FFF << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
-#define I40E_GL_FWSTS 0x00083048
+#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK I40E_MASK(0x3FFF, I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
+#define I40E_GL_FWSTS 0x00083048 /* Reset: POR */
 #define I40E_GL_FWSTS_FWS0B_SHIFT 0
-#define I40E_GL_FWSTS_FWS0B_MASK (0xFF << I40E_GL_FWSTS_FWS0B_SHIFT)
+#define I40E_GL_FWSTS_FWS0B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS0B_SHIFT)
 #define I40E_GL_FWSTS_FWRI_SHIFT 9
-#define I40E_GL_FWSTS_FWRI_MASK (0x1 << I40E_GL_FWSTS_FWRI_SHIFT)
+#define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT)
 #define I40E_GL_FWSTS_FWS1B_SHIFT 16
-#define I40E_GL_FWSTS_FWS1B_MASK (0xFF << I40E_GL_FWSTS_FWS1B_SHIFT)
-#define I40E_GLGEN_CLKSTAT 0x000B8184
+#define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT)
+#define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */
 #define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0
-#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK (0x1 << I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
+#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
 #define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4
-#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK (0x3 << I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK I40E_MASK(0x3, I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8
-#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12
-#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16
-#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
 #define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20
-#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
-#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */ /* Reset: POR */
 #define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29
 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK (0x3 << I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4
-#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5
-#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6
-#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7
-#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK (0x7 << I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK I40E_MASK(0x7, I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10
-#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11
-#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12
-#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK (0xF << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17
-#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK (0x3 << I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19
-#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
 #define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20
-#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK (0x3F << I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
-#define I40E_GLGEN_GPIO_SET 0x00088184
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK I40E_MASK(0x3F, I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
+#define I40E_GLGEN_GPIO_SET 0x00088184 /* Reset: POR */
 #define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0
-#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK (0x1F << I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
 #define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5
-#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK (0x1 << I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
 #define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6
-#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK (0x1 << I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
-#define I40E_GLGEN_GPIO_STAT 0x0008817C
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
+#define I40E_GLGEN_GPIO_STAT 0x0008817C /* Reset: POR */
 #define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0
-#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
-#define I40E_GLGEN_GPIO_TRANSIT 0x00088180
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
+#define I40E_GLGEN_GPIO_TRANSIT 0x00088180 /* Reset: POR */
 #define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0
-#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
-#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
+#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_I2CCMD_MAX_INDEX 3
 #define I40E_GLGEN_I2CCMD_DATA_SHIFT 0
-#define I40E_GLGEN_I2CCMD_DATA_MASK (0xFFFF << I40E_GLGEN_I2CCMD_DATA_SHIFT)
+#define I40E_GLGEN_I2CCMD_DATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_I2CCMD_DATA_SHIFT)
 #define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16
-#define I40E_GLGEN_I2CCMD_REGADD_MASK (0xFF << I40E_GLGEN_I2CCMD_REGADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_REGADD_MASK I40E_MASK(0xFF, I40E_GLGEN_I2CCMD_REGADD_SHIFT)
 #define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24
-#define I40E_GLGEN_I2CCMD_PHYADD_MASK (0x7 << I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_PHYADD_MASK I40E_MASK(0x7, I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
 #define I40E_GLGEN_I2CCMD_OP_SHIFT 27
-#define I40E_GLGEN_I2CCMD_OP_MASK (0x1 << I40E_GLGEN_I2CCMD_OP_SHIFT)
+#define I40E_GLGEN_I2CCMD_OP_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_OP_SHIFT)
 #define I40E_GLGEN_I2CCMD_RESET_SHIFT 28
-#define I40E_GLGEN_I2CCMD_RESET_MASK (0x1 << I40E_GLGEN_I2CCMD_RESET_SHIFT)
+#define I40E_GLGEN_I2CCMD_RESET_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_RESET_SHIFT)
 #define I40E_GLGEN_I2CCMD_R_SHIFT 29
-#define I40E_GLGEN_I2CCMD_R_MASK (0x1 << I40E_GLGEN_I2CCMD_R_SHIFT)
+#define I40E_GLGEN_I2CCMD_R_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_R_SHIFT)
 #define I40E_GLGEN_I2CCMD_E_SHIFT 31
-#define I40E_GLGEN_I2CCMD_E_MASK (0x1 << I40E_GLGEN_I2CCMD_E_SHIFT)
-#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CCMD_E_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_E_SHIFT)
+#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3
 #define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0
-#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK (0x1F << I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK I40E_MASK(0x1F, I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5
-#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK (0x7 << I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK I40E_MASK(0x7, I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8
-#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9
-#define I40E_GLGEN_I2CPARAMS_CLK_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10
-#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11
-#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12
-#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13
-#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14
-#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15
-#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
 #define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31
-#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
-#define I40E_GLGEN_LED_CTL 0x00088178
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
+#define I40E_GLGEN_LED_CTL 0x00088178 /* Reset: POR */
 #define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0
-#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK (0x1 << I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
-#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3
 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK (0x1FFFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK I40E_MASK(0x1FFFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
 #define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17
-#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK (0x1 << I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK (0x3FFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
-#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK I40E_MASK(0x3FFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3
 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
 #define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31
-#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
-#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
+#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MSCA_MAX_INDEX 3
 #define I40E_GLGEN_MSCA_MDIADD_SHIFT 0
-#define I40E_GLGEN_MSCA_MDIADD_MASK (0xFFFF << I40E_GLGEN_MSCA_MDIADD_SHIFT)
+#define I40E_GLGEN_MSCA_MDIADD_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSCA_MDIADD_SHIFT)
 #define I40E_GLGEN_MSCA_DEVADD_SHIFT 16
-#define I40E_GLGEN_MSCA_DEVADD_MASK (0x1F << I40E_GLGEN_MSCA_DEVADD_SHIFT)
+#define I40E_GLGEN_MSCA_DEVADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_DEVADD_SHIFT)
 #define I40E_GLGEN_MSCA_PHYADD_SHIFT 21
-#define I40E_GLGEN_MSCA_PHYADD_MASK (0x1F << I40E_GLGEN_MSCA_PHYADD_SHIFT)
+#define I40E_GLGEN_MSCA_PHYADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_PHYADD_SHIFT)
 #define I40E_GLGEN_MSCA_OPCODE_SHIFT 26
-#define I40E_GLGEN_MSCA_OPCODE_MASK (0x3 << I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_GLGEN_MSCA_OPCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_OPCODE_SHIFT)
 #define I40E_GLGEN_MSCA_STCODE_SHIFT 28
-#define I40E_GLGEN_MSCA_STCODE_MASK (0x3 << I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_GLGEN_MSCA_STCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_STCODE_SHIFT)
 #define I40E_GLGEN_MSCA_MDICMD_SHIFT 30
-#define I40E_GLGEN_MSCA_MDICMD_MASK (0x1 << I40E_GLGEN_MSCA_MDICMD_SHIFT)
+#define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT)
 #define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31
-#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK (0x1 << I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
-#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
+#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_GLGEN_MSRWD_MAX_INDEX 3
 #define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
-#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
+#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
 #define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
-#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
-#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4
+#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4 /* Reset: PCIR */
 #define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
-#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK (0x1F << I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
 #define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
-#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK (0xFF << I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
-#define I40E_GLGEN_PE_ENA 0x000B81A0
-#define I40E_GLGEN_PE_ENA_PE_ENA_SHIFT 0
-#define I40E_GLGEN_PE_ENA_PE_ENA_MASK (0x1 << I40E_GLGEN_PE_ENA_PE_ENA_SHIFT)
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT 1
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_MASK (0x3 << I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT)
-#define I40E_GLGEN_RSTAT 0x000B8188
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
+#define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */
 #define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
-#define I40E_GLGEN_RSTAT_DEVSTATE_MASK (0x3 << I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
+#define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
 #define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2
-#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK (0x3 << I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
+#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
 #define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4
-#define I40E_GLGEN_RSTAT_CORERCNT_MASK (0x3 << I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_CORERCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6
-#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8
-#define I40E_GLGEN_RSTAT_EMPRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_EMPRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
 #define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10
-#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK (0x3F << I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
-#define I40E_GLGEN_RSTCTL 0x000B8180
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
+#define I40E_GLGEN_RSTCTL 0x000B8180 /* Reset: POR */
 #define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0
-#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK (0x3F << I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
+#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
 #define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8
-#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
-#define I40E_GLGEN_RSTENA_EMP 0x000B818C
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
+#define I40E_GLGEN_RSTENA_EMP 0x000B818C /* Reset: POR */
 #define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT 0
-#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
-#define I40E_GLGEN_RTRIG 0x000B8190
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
+#define I40E_GLGEN_RTRIG 0x000B8190 /* Reset: CORER */
 #define I40E_GLGEN_RTRIG_CORER_SHIFT 0
-#define I40E_GLGEN_RTRIG_CORER_MASK (0x1 << I40E_GLGEN_RTRIG_CORER_SHIFT)
+#define I40E_GLGEN_RTRIG_CORER_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_CORER_SHIFT)
 #define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1
-#define I40E_GLGEN_RTRIG_GLOBR_MASK (0x1 << I40E_GLGEN_RTRIG_GLOBR_SHIFT)
+#define I40E_GLGEN_RTRIG_GLOBR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_GLOBR_SHIFT)
 #define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2
-#define I40E_GLGEN_RTRIG_EMPFWR_MASK (0x1 << I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
-#define I40E_GLGEN_STAT 0x000B612C
+#define I40E_GLGEN_RTRIG_EMPFWR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
+#define I40E_GLGEN_STAT 0x000B612C /* Reset: POR */
 #define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0
-#define I40E_GLGEN_STAT_HWRSVD0_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD0_SHIFT)
+#define I40E_GLGEN_STAT_HWRSVD0_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD0_SHIFT)
 #define I40E_GLGEN_STAT_DCBEN_SHIFT 2
-#define I40E_GLGEN_STAT_DCBEN_MASK (0x1 << I40E_GLGEN_STAT_DCBEN_SHIFT)
+#define I40E_GLGEN_STAT_DCBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_DCBEN_SHIFT)
 #define I40E_GLGEN_STAT_VTEN_SHIFT 3
-#define I40E_GLGEN_STAT_VTEN_MASK (0x1 << I40E_GLGEN_STAT_VTEN_SHIFT)
+#define I40E_GLGEN_STAT_VTEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_VTEN_SHIFT)
 #define I40E_GLGEN_STAT_FCOEN_SHIFT 4
-#define I40E_GLGEN_STAT_FCOEN_MASK (0x1 << I40E_GLGEN_STAT_FCOEN_SHIFT)
+#define I40E_GLGEN_STAT_FCOEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_FCOEN_SHIFT)
 #define I40E_GLGEN_STAT_EVBEN_SHIFT 5
-#define I40E_GLGEN_STAT_EVBEN_MASK (0x1 << I40E_GLGEN_STAT_EVBEN_SHIFT)
+#define I40E_GLGEN_STAT_EVBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_EVBEN_SHIFT)
 #define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6
-#define I40E_GLGEN_STAT_HWRSVD1_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD1_SHIFT)
-#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_STAT_HWRSVD1_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD1_SHIFT)
+#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3
 #define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0
-#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK (0xFFFFFFFF << I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
-#define I40E_GLVFGEN_TIMER 0x000881BC
+#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK I40E_MASK(0xFFFFFFFF, I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
+#define I40E_GLVFGEN_TIMER 0x000881BC /* Reset: CORER */
 #define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0
-#define I40E_GLVFGEN_TIMER_GTIME_MASK (0xFFFFFFFF << I40E_GLVFGEN_TIMER_GTIME_SHIFT)
-#define I40E_PFGEN_CTRL 0x00092400
+#define I40E_GLVFGEN_TIMER_GTIME_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVFGEN_TIMER_GTIME_SHIFT)
+#define I40E_PFGEN_CTRL 0x00092400 /* Reset: PFR */
 #define I40E_PFGEN_CTRL_PFSWR_SHIFT 0
-#define I40E_PFGEN_CTRL_PFSWR_MASK (0x1 << I40E_PFGEN_CTRL_PFSWR_SHIFT)
-#define I40E_PFGEN_DRUN 0x00092500
+#define I40E_PFGEN_CTRL_PFSWR_MASK I40E_MASK(0x1, I40E_PFGEN_CTRL_PFSWR_SHIFT)
+#define I40E_PFGEN_DRUN 0x00092500 /* Reset: CORER */
 #define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0
-#define I40E_PFGEN_DRUN_DRVUNLD_MASK (0x1 << I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
-#define I40E_PFGEN_PORTNUM 0x001C0480
+#define I40E_PFGEN_DRUN_DRVUNLD_MASK I40E_MASK(0x1, I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
+#define I40E_PFGEN_PORTNUM 0x001C0480 /* Reset: CORER */
 #define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
-#define I40E_PFGEN_STATE 0x00088000
-#define I40E_PFGEN_STATE_PFPEEN_SHIFT 0
-#define I40E_PFGEN_STATE_PFPEEN_MASK (0x1 << I40E_PFGEN_STATE_PFPEEN_SHIFT)
+#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_STATE 0x00088000 /* Reset: CORER */
+#define I40E_PFGEN_STATE_RESERVED_0_SHIFT 0
+#define I40E_PFGEN_STATE_RESERVED_0_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_RESERVED_0_SHIFT)
 #define I40E_PFGEN_STATE_PFFCEN_SHIFT 1
-#define I40E_PFGEN_STATE_PFFCEN_MASK (0x1 << I40E_PFGEN_STATE_PFFCEN_SHIFT)
+#define I40E_PFGEN_STATE_PFFCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFFCEN_SHIFT)
 #define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2
-#define I40E_PFGEN_STATE_PFLINKEN_MASK (0x1 << I40E_PFGEN_STATE_PFLINKEN_SHIFT)
+#define I40E_PFGEN_STATE_PFLINKEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFLINKEN_SHIFT)
 #define I40E_PFGEN_STATE_PFSCEN_SHIFT 3
-#define I40E_PFGEN_STATE_PFSCEN_MASK (0x1 << I40E_PFGEN_STATE_PFSCEN_SHIFT)
-#define I40E_PRTGEN_CNF 0x000B8120
+#define I40E_PFGEN_STATE_PFSCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFSCEN_SHIFT)
+#define I40E_PRTGEN_CNF 0x000B8120 /* Reset: POR */
 #define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0
-#define I40E_PRTGEN_CNF_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
 #define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1
-#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
 #define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2
-#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
-#define I40E_PRTGEN_CNF2 0x000B8160
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF2 0x000B8160 /* Reset: POR */
 #define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0
-#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK (0x1 << I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
-#define I40E_PRTGEN_STATUS 0x000B8100
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
+#define I40E_PRTGEN_STATUS 0x000B8100 /* Reset: POR */
 #define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0
-#define I40E_PRTGEN_STATUS_PORT_VALID_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
+#define I40E_PRTGEN_STATUS_PORT_VALID_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
 #define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1
-#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
-#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
+#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFGEN_RSTAT1_MAX_INDEX 127
 #define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
-#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
+#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPGEN_VFRSTAT_MAX_INDEX 127
 #define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0
-#define I40E_VPGEN_VFRSTAT_VFRD_MASK (0x1 << I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
-#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRSTAT_VFRD_MASK I40E_MASK(0x1, I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
+#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPGEN_VFRTRIG_MAX_INDEX 127
 #define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0
-#define I40E_VPGEN_VFRTRIG_VFSWR_MASK (0x1 << I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
-#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPGEN_VFRTRIG_VFSWR_MASK I40E_MASK(0x1, I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
+#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_VSIGEN_RSTAT_MAX_INDEX 383
 #define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0
-#define I40E_VSIGEN_RSTAT_VMRD_MASK (0x1 << I40E_VSIGEN_RSTAT_VMRD_SHIFT)
-#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RSTAT_VMRD_MASK I40E_MASK(0x1, I40E_VSIGEN_RSTAT_VMRD_SHIFT)
+#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_VSIGEN_RTRIG_MAX_INDEX 383
 #define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0
-#define I40E_VSIGEN_RTRIG_VMSWR_MASK (0x1 << I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
-#define I40E_GLHMC_APBVTINUSEBASE(_i) (0x000C4a00 + ((_i) * 4))
-#define I40E_GLHMC_APBVTINUSEBASE_MAX_INDEX 15
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_CEQPART(_i) (0x001312C0 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_CEQPART_MAX_INDEX 15
-#define I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_CEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_DBCQPART(_i) (0x00131240 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBCQPART_MAX_INDEX 15
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_DBQPPART(_i) (0x00138D80 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBQPPART_MAX_INDEX 15
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VSIGEN_RTRIG_VMSWR_MASK I40E_MASK(0x1, I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
+#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15
 #define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0
-#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
-#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
+#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15
 #define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0
-#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK (0xFFFFF << I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
-#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK I40E_MASK(0xFFFFF, I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
+#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010 /* Reset: CORER */
 #define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK (0xF << I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15
 #define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0
-#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
-#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
+#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15
 #define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0
-#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK (0x7FFFFF << I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
-#define I40E_GLHMC_FCOEFMAX 0x000C20D0
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK I40E_MASK(0x7FFFFF, I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
+#define I40E_GLHMC_FCOEFMAX 0x000C20D0 /* Reset: CORER */
 #define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0
-#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK (0xFFFF << I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
-#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK I40E_MASK(0xFFFF, I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
+#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018 /* Reset: CORER */
 #define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK (0xF << I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEMAX 0x000C2014
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEMAX 0x000C2014 /* Reset: CORER */
 #define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0
-#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK (0x1FFF << I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
-#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK I40E_MASK(0x1FFF, I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
+#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15
 #define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15
 #define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
 #define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_FSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_FSIAVMAX 0x000C2068
+#define I40E_GLHMC_FSIAVCNT_RSVD_MASK I40E_MASK(0x7, I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_FSIAVMAX 0x000C2068 /* Reset: CORER */
 #define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0
-#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK (0x1FFFF << I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
-#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK I40E_MASK(0x1FFFF, I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
+#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064 /* Reset: CORER */
 #define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK (0xF << I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
-#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
+#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15
 #define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0
-#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
-#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
+#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15
 #define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK (0x1FFFFFFF << I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
-#define I40E_GLHMC_FSIMCMAX 0x000C2060
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
+#define I40E_GLHMC_FSIMCMAX 0x000C2060 /* Reset: CORER */
 #define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0
-#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK (0x3FFF << I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
-#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK I40E_MASK(0x3FFF, I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
+#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c /* Reset: CORER */
 #define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK (0xF << I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
-#define I40E_GLHMC_LANQMAX 0x000C2008
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
+#define I40E_GLHMC_LANQMAX 0x000C2008 /* Reset: CORER */
 #define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0
-#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK (0x7FF << I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
-#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
+#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANRXBASE_MAX_INDEX 15
 #define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0
-#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
-#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
+#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANRXCNT_MAX_INDEX 15
 #define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0
-#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK (0x7FF << I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
-#define I40E_GLHMC_LANRXOBJSZ 0x000C200c
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
+#define I40E_GLHMC_LANRXOBJSZ 0x000C200c /* Reset: CORER */
 #define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK (0xF << I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
-#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
+#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANTXBASE_MAX_INDEX 15
 #define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0
-#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
 #define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24
-#define I40E_GLHMC_LANTXBASE_RSVD_MASK (0xFF << I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
-#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXBASE_RSVD_MASK I40E_MASK(0xFF, I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
+#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_LANTXCNT_MAX_INDEX 15
 #define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0
-#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK (0x7FF << I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
-#define I40E_GLHMC_LANTXOBJSZ 0x000C2004
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
+#define I40E_GLHMC_LANTXOBJSZ 0x000C2004 /* Reset: CORER */
 #define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK (0xF << I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
-#define I40E_GLHMC_PEARPBASE(_i) (0x000C4800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_PEARPCNT(_i) (0x000C4900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_PEARPMAX 0x000C2038
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT 0
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_MASK (0x1FFFF << I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT)
-#define I40E_GLHMC_PEARPOBJSZ 0x000C2034
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_MASK (0x7 << I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT)
-#define I40E_GLHMC_PECQBASE(_i) (0x000C4200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_PECQCNT(_i) (0x000C4300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_PECQOBJSZ 0x000C2020
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_MASK (0xF << I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTCNT(_i) (0x000C4700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_PEHTEBASE(_i) (0x000C4600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTEBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_PEHTEOBJSZ 0x000C202c
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_MASK (0xF << I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTMAX 0x000C2030
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT 0
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_MASK (0x1FFFFF << I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT)
-#define I40E_GLHMC_PEMRBASE(_i) (0x000C4c00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_PEMRCNT(_i) (0x000C4d00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_PEMRMAX 0x000C2040
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT 0
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_MASK (0x7FFFFF << I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT)
-#define I40E_GLHMC_PEMROBJSZ 0x000C203c
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT 0
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_MASK (0xF << I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT)
-#define I40E_GLHMC_PEPBLBASE(_i) (0x000C5800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_PEPBLCNT(_i) (0x000C5900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_PEPBLMAX 0x000C206c
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT 0
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1BASE(_i) (0x000C5200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1BASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_PEQ1CNT(_i) (0x000C5300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1CNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLBASE(_i) (0x000C5400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_PEQ1FLCNT(_i) (0x000C5500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLMAX 0x000C2058
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1MAX 0x000C2054
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
-#define I40E_GLHMC_PEQ1OBJSZ 0x000C2050
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_MASK (0xF << I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT)
-#define I40E_GLHMC_PEQPBASE(_i) (0x000C4000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_PEQPCNT(_i) (0x000C4100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_PEQPOBJSZ 0x000C201c
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_MASK (0xF << I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQBASE(_i) (0x000C4400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_PESRQCNT(_i) (0x000C4500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_PESRQMAX 0x000C2028
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT 0
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_MASK (0xFFFF << I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ 0x000C2024
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_MASK (0xF << I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PETIMERBASE(_i) (0x000C5A00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERBASE_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_PETIMERCNT(_i) (0x000C5B00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERCNT_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_PETIMERMAX 0x000C2084
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT 0
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT)
-#define I40E_GLHMC_PETIMEROBJSZ 0x000C2080
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT 0
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_MASK (0xF << I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFBASE(_i) (0x000C4e00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_PEXFCNT(_i) (0x000C4f00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLBASE(_i) (0x000C5000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_PEXFFLCNT(_i) (0x000C5100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLMAX 0x000C204c
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
-#define I40E_GLHMC_PEXFMAX 0x000C2048
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ 0x000C2044
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_MASK (0xF << I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
+#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_PFASSIGN_MAX_INDEX 15
 #define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0
-#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK (0xF << I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
-#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK I40E_MASK(0xF, I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
+#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLHMC_SDPART_MAX_INDEX 15
 #define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_SDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_SDPART_PMSDBASE_MASK I40E_MASK(0xFFF, I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
 #define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_SDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
-#define I40E_GLHMC_VFAPBVTINUSEBASE(_i) (0x000Cca00 + ((_i) * 4))
-#define I40E_GLHMC_VFAPBVTINUSEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART(_i) (0x00132240 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFCEQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART(_i) (0x00132140 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBCQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART(_i) (0x00138E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBQPPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_VFFSIAVBASE(_i) (0x000Cd600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT(_i) (0x000Cd700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_VFPDINV(_i) (0x000C8300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPDINV_MAX_INDEX 31
-#define I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT 0
-#define I40E_GLHMC_VFPDINV_PMSDIDX_MASK (0xFFF << I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT)
-#define I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT 16
-#define I40E_GLHMC_VFPDINV_PMPDIDX_MASK (0x1FF << I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT)
-#define I40E_GLHMC_VFPEARPBASE(_i) (0x000Cc800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_VFPEARPCNT(_i) (0x000Cc900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_VFPECQBASE(_i) (0x000Cc200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_VFPECQCNT(_i) (0x000Cc300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTCNT(_i) (0x000Cc700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTEBASE(_i) (0x000Cc600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRBASE(_i) (0x000Ccc00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRCNT(_i) (0x000Ccd00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_VFPEPBLBASE(_i) (0x000Cd800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_VFPEPBLCNT(_i) (0x000Cd900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1BASE(_i) (0x000Cd200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1BASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1CNT(_i) (0x000Cd300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1CNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLBASE(_i) (0x000Cd400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLCNT(_i) (0x000Cd500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQPBASE(_i) (0x000Cc000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_VFPEQPCNT(_i) (0x000Cc100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_VFPESRQBASE(_i) (0x000Cc400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_VFPESRQCNT(_i) (0x000Cc500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_VFPETIMERBASE(_i) (0x000CDA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_VFPETIMERCNT(_i) (0x000CDB00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFBASE(_i) (0x000Cce00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFCNT(_i) (0x000Ccf00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFFLBASE(_i) (0x000Cd000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFFLCNT(_i) (0x000Cd100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_VFSDPART(_i) (0x000C8800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFSDPART_MAX_INDEX 31
-#define I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_VFSDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT)
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT)
-#define I40E_PFHMC_ERRORDATA 0x000C0500
+#define I40E_GLHMC_SDPART_PMSDSIZE_MASK I40E_MASK(0x1FFF, I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
+#define I40E_PFHMC_ERRORDATA 0x000C0500 /* Reset: PFR */
 #define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0
-#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK (0x3FFFFFFF << I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
-#define I40E_PFHMC_ERRORINFO 0x000C0400
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK I40E_MASK(0x3FFFFFFF, I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
+#define I40E_PFHMC_ERRORINFO 0x000C0400 /* Reset: PFR */
 #define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0
-#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK (0x1F << I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
 #define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7
-#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK (0x1 << I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
 #define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8
-#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK (0xF << I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK I40E_MASK(0xF, I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
 #define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16
-#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK (0x1F << I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
 #define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31
-#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK (0x1 << I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
-#define I40E_PFHMC_PDINV 0x000C0300
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
+#define I40E_PFHMC_PDINV 0x000C0300 /* Reset: PFR */
 #define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_PDINV_PMSDIDX_MASK (0xFFF << I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
+#define I40E_PFHMC_PDINV_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
 #define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16
-#define I40E_PFHMC_PDINV_PMPDIDX_MASK (0x1FF << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
-#define I40E_PFHMC_SDCMD 0x000C0000
+#define I40E_PFHMC_PDINV_PMPDIDX_MASK I40E_MASK(0x1FF, I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD 0x000C0000 /* Reset: PFR */
 #define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_SDCMD_PMSDIDX_MASK (0xFFF << I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
 #define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31
-#define I40E_PFHMC_SDCMD_PMSDWR_MASK (0x1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
-#define I40E_PFHMC_SDDATAHIGH 0x000C0200
+#define I40E_PFHMC_SDCMD_PMSDWR_MASK I40E_MASK(0x1, I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
+#define I40E_PFHMC_SDDATAHIGH 0x000C0200 /* Reset: PFR */
 #define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0
-#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK (0xFFFFFFFF << I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
-#define I40E_PFHMC_SDDATALOW 0x000C0100
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
+#define I40E_PFHMC_SDDATALOW 0x000C0100 /* Reset: PFR */
 #define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0
-#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1
-#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2
-#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK (0x3FF << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK I40E_MASK(0x3FF, I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
 #define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12
-#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK (0xFFFFF << I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
-#define I40E_GL_UFUSE 0x00094008
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK I40E_MASK(0xFFFFF, I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ /* Reset: POR */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
+#define I40E_GL_UFUSE 0x00094008 /* Reset: POR */
 #define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1
-#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK (0x1 << I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK I40E_MASK(0x1, I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
 #define I40E_GL_UFUSE_NIC_ID_SHIFT 2
-#define I40E_GL_UFUSE_NIC_ID_MASK (0x1 << I40E_GL_UFUSE_NIC_ID_SHIFT)
+#define I40E_GL_UFUSE_NIC_ID_MASK I40E_MASK(0x1, I40E_GL_UFUSE_NIC_ID_SHIFT)
 #define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10
-#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
+#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
 #define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11
-#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
-#define I40E_EMPINT_GPIO_ENA 0x00088188
+#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
+#define I40E_EMPINT_GPIO_ENA 0x00088188 /* Reset: POR */
 #define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
 #define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100 /* Reset: CORER */
 #define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
 #define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4
-#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK (0x1 << I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
-#define I40E_PFINT_AEQCTL 0x00038700
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK I40E_MASK(0x1, I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL 0x00038700 /* Reset: CORER */
 #define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_PFINT_CEQCTL_MAX_INDEX 511
 #define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_DYN_CTL0 0x00038480
+#define I40E_PFINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_DYN_CTL0 0x00038480 /* Reset: PFR */
 #define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
 #define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_DYN_CTLN_MAX_INDEX 511
 #define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
 #define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
 #define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_PFINT_GPIO_ENA 0x00088080
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_PFINT_GPIO_ENA 0x00088080 /* Reset: CORER */
 #define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
 #define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFINT_ICR0 0x00038780
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
 #define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_PFINT_ICR0_INTEVENT_MASK (0x1 << I40E_PFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_PFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_0_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_PFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_1_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_PFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_2_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_PFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_3_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5
-#define I40E_PFINT_ICR0_QUEUE_4_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_4_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_4_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_4_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6
-#define I40E_PFINT_ICR0_QUEUE_5_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_5_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_5_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_5_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7
-#define I40E_PFINT_ICR0_QUEUE_6_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_6_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_6_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_6_SHIFT)
 #define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8
-#define I40E_PFINT_ICR0_QUEUE_7_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_7_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_7_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_7_SHIFT)
 #define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ECC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_GRST_MASK (0x1 << I40E_PFINT_ICR0_GRST_SHIFT)
+#define I40E_PFINT_ICR0_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GRST_SHIFT)
 #define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
 #define I40E_PFINT_ICR0_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_GPIO_MASK (0x1 << I40E_PFINT_ICR0_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GPIO_SHIFT)
 #define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_STORM_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
 #define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_HMC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
 #define I40E_PFINT_ICR0_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_VFLR_MASK (0x1 << I40E_PFINT_ICR0_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_VFLR_SHIFT)
 #define I40E_PFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ADMINQ_SHIFT)
 #define I40E_PFINT_ICR0_SWINT_SHIFT 31
-#define I40E_PFINT_ICR0_SWINT_MASK (0x1 << I40E_PFINT_ICR0_SWINT_SHIFT)
-#define I40E_PFINT_ICR0_ENA 0x00038800
+#define I40E_PFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_SWINT_SHIFT)
+#define I40E_PFINT_ICR0_ENA 0x00038800 /* Reset: CORER */
 #define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_ENA_GRST_MASK (0x1 << I40E_PFINT_ICR0_ENA_GRST_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GRST_SHIFT)
 #define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
 #define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_ENA_GPIO_MASK (0x1 << I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
 #define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT)
 #define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
 #define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_ENA_VFLR_MASK (0x1 << I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
 #define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
 #define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_PFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */
+#define I40E_PFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */ /* Reset: PFR */
 #define I40E_PFINT_ITR0_MAX_INDEX 2
 #define I40E_PFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_PFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4))
+#define I40E_PFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4)) /* _i=0...2, _INTPF=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_ITRN_MAX_INDEX 2
 #define I40E_PFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_PFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_PFINT_LNKLST0 0x00038500
+#define I40E_PFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_PFINT_LNKLST0 0x00038500 /* Reset: PFR */
 #define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
 #define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_LNKLSTN_MAX_INDEX 511
 #define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
 #define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_RATE0 0x00038580
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_RATE0 0x00038580 /* Reset: PFR */
 #define I40E_PFINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATE0_INTERVAL_MASK (0x3F << I40E_PFINT_RATE0_INTERVAL_SHIFT)
+#define I40E_PFINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATE0_INTERVAL_SHIFT)
 #define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
 #define I40E_PFINT_RATEN_MAX_INDEX 511
 #define I40E_PFINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATEN_INTERVAL_MASK (0x3F << I40E_PFINT_RATEN_INTERVAL_SHIFT)
+#define I40E_PFINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATEN_INTERVAL_SHIFT)
 #define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_PFINT_STAT_CTL0 0x00038400
+#define I40E_PFINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_PFINT_STAT_CTL0 0x00038400 /* Reset: PFR */
 #define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QINT_RQCTL_MAX_INDEX 1535
 #define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_RQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
 #define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_RQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_ITR_INDX_SHIFT)
 #define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_RQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
 #define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_RQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_RQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
 #define I40E_QINT_RQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_RQCTL_INTEVENT_MASK (0x1 << I40E_QINT_RQCTL_INTEVENT_SHIFT)
-#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_RQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_INTEVENT_SHIFT)
+#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QINT_TQCTL_MAX_INDEX 1535
 #define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_TQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
 #define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_TQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_TQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_ITR_INDX_SHIFT)
 #define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_TQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
 #define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_TQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_TQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
 #define I40E_QINT_TQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_TQCTL_INTEVENT_MASK (0x1 << I40E_QINT_TQCTL_INTEVENT_SHIFT)
-#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QINT_TQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_INTEVENT_SHIFT)
+#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTL0_MAX_INDEX 127
 #define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTLN_MAX_INDEX 511
 #define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VFINT_ICR0_MAX_INDEX 127
 #define I40E_VFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR0_INTEVENT_MASK (0x1 << I40E_VFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_INTEVENT_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_0_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_1_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_2_SHIFT)
 #define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_3_SHIFT)
 #define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_SWINT_SHIFT 31
-#define I40E_VFINT_ICR0_SWINT_MASK (0x1 << I40E_VFINT_ICR0_SWINT_SHIFT)
-#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_SWINT_SHIFT)
+#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VFINT_ICR0_ENA_MAX_INDEX 127
 #define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */
+#define I40E_VFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_ITR0_MAX_INDEX 2
 #define I40E_VFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4))
+#define I40E_VFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...511 */ /* Reset: VFR */
 #define I40E_VFINT_ITRN_MAX_INDEX 2
 #define I40E_VFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VFINT_STAT_CTL0_MAX_INDEX 127
 #define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VPINT_AEQCTL_MAX_INDEX 127
 #define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_VPINT_CEQCTL_MAX_INDEX 511
 #define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
 #define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
 #define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
 #define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPINT_LNKLST0_MAX_INDEX 127
 #define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
 #define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VPINT_LNKLSTN_MAX_INDEX 511
 #define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
 #define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPINT_RATE0_MAX_INDEX 127
 #define I40E_VPINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATE0_INTERVAL_MASK (0x3F << I40E_VPINT_RATE0_INTERVAL_SHIFT)
+#define I40E_VPINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATE0_INTERVAL_SHIFT)
 #define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
 #define I40E_VPINT_RATEN_MAX_INDEX 511
 #define I40E_VPINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATEN_INTERVAL_MASK (0x3F << I40E_VPINT_RATEN_INTERVAL_SHIFT)
+#define I40E_VPINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATEN_INTERVAL_SHIFT)
 #define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_GL_RDPU_CNTRL 0x00051060
+#define I40E_VPINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_GL_RDPU_CNTRL 0x00051060 /* Reset: CORER */
 #define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0
-#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK (0x1 << I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK I40E_MASK(0x1, I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
 #define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1
-#define I40E_GL_RDPU_CNTRL_ECO_MASK (0x7FFFFFFF << I40E_GL_RDPU_CNTRL_ECO_SHIFT)
-#define I40E_GLLAN_RCTL_0 0x0012A500
+#define I40E_GL_RDPU_CNTRL_ECO_MASK I40E_MASK(0x7FFFFFFF, I40E_GL_RDPU_CNTRL_ECO_SHIFT)
+#define I40E_GLLAN_RCTL_0 0x0012A500 /* Reset: CORER */
 #define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0
-#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK (0x1 << I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
-#define I40E_GLLAN_TSOMSK_F 0x000442D8
+#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK I40E_MASK(0x1, I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
+#define I40E_GLLAN_TSOMSK_F 0x000442D8 /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0
-#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK (0xFFF << I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
-#define I40E_GLLAN_TSOMSK_L 0x000442E0
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
+#define I40E_GLLAN_TSOMSK_L 0x000442E0 /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0
-#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK (0xFFF << I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
-#define I40E_GLLAN_TSOMSK_M 0x000442DC
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
+#define I40E_GLLAN_TSOMSK_M 0x000442DC /* Reset: CORER */
 #define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0
-#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK (0xFFF << I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
-#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000E6500 + ((_i) * 4)) /* i=0..11 */
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000e6500 + ((_i) * 4)) /* _i=0...11 */ /* Reset: CORER */
+#define I40E_GLLAN_TXPRE_QDIS_MAX_INDEX 11
 #define I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT 0
-#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK (0x7FF << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK I40E_MASK(0x7FF, I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT 16
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT)
 #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30
-#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
 #define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31
-#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
-
-#define I40E_PFLAN_QALLOC 0x001C0400
+#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
+#define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */
 #define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0
-#define I40E_PFLAN_QALLOC_FIRSTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
 #define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16
-#define I40E_PFLAN_QALLOC_LASTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_LASTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT)
 #define I40E_PFLAN_QALLOC_VALID_SHIFT 31
-#define I40E_PFLAN_QALLOC_VALID_MASK (0x1 << I40E_PFLAN_QALLOC_VALID_SHIFT)
-#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT)
+#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QRX_ENA_MAX_INDEX 1535
 #define I40E_QRX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QRX_ENA_QENA_REQ_MASK (0x1 << I40E_QRX_ENA_QENA_REQ_SHIFT)
+#define I40E_QRX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_REQ_SHIFT)
 #define I40E_QRX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QRX_ENA_FAST_QDIS_MASK (0x1 << I40E_QRX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QRX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QRX_ENA_FAST_QDIS_SHIFT)
 #define I40E_QRX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QRX_ENA_QENA_STAT_MASK (0x1 << I40E_QRX_ENA_QENA_STAT_SHIFT)
-#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_STAT_SHIFT)
+#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QRX_TAIL_MAX_INDEX 1535
 #define I40E_QRX_TAIL_TAIL_SHIFT 0
-#define I40E_QRX_TAIL_TAIL_MASK (0x1FFF << I40E_QRX_TAIL_TAIL_SHIFT)
-#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL_TAIL_SHIFT)
+#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QTX_CTL_MAX_INDEX 1535
 #define I40E_QTX_CTL_PFVF_Q_SHIFT 0
-#define I40E_QTX_CTL_PFVF_Q_MASK (0x3 << I40E_QTX_CTL_PFVF_Q_SHIFT)
+#define I40E_QTX_CTL_PFVF_Q_MASK I40E_MASK(0x3, I40E_QTX_CTL_PFVF_Q_SHIFT)
 #define I40E_QTX_CTL_PF_INDX_SHIFT 2
-#define I40E_QTX_CTL_PF_INDX_MASK (0xF << I40E_QTX_CTL_PF_INDX_SHIFT)
+#define I40E_QTX_CTL_PF_INDX_MASK I40E_MASK(0xF, I40E_QTX_CTL_PF_INDX_SHIFT)
 #define I40E_QTX_CTL_VFVM_INDX_SHIFT 7
-#define I40E_QTX_CTL_VFVM_INDX_MASK (0x1FF << I40E_QTX_CTL_VFVM_INDX_SHIFT)
-#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_CTL_VFVM_INDX_MASK I40E_MASK(0x1FF, I40E_QTX_CTL_VFVM_INDX_SHIFT)
+#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QTX_ENA_MAX_INDEX 1535
 #define I40E_QTX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QTX_ENA_QENA_REQ_MASK (0x1 << I40E_QTX_ENA_QENA_REQ_SHIFT)
+#define I40E_QTX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_REQ_SHIFT)
 #define I40E_QTX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QTX_ENA_FAST_QDIS_MASK (0x1 << I40E_QTX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QTX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QTX_ENA_FAST_QDIS_SHIFT)
 #define I40E_QTX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QTX_ENA_QENA_STAT_MASK (0x1 << I40E_QTX_ENA_QENA_STAT_SHIFT)
-#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_STAT_SHIFT)
+#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
 #define I40E_QTX_HEAD_MAX_INDEX 1535
 #define I40E_QTX_HEAD_HEAD_SHIFT 0
-#define I40E_QTX_HEAD_HEAD_MASK (0x1FFF << I40E_QTX_HEAD_HEAD_SHIFT)
+#define I40E_QTX_HEAD_HEAD_MASK I40E_MASK(0x1FFF, I40E_QTX_HEAD_HEAD_SHIFT)
 #define I40E_QTX_HEAD_RS_PENDING_SHIFT 16
-#define I40E_QTX_HEAD_RS_PENDING_MASK (0x1 << I40E_QTX_HEAD_RS_PENDING_SHIFT)
-#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_HEAD_RS_PENDING_MASK I40E_MASK(0x1, I40E_QTX_HEAD_RS_PENDING_SHIFT)
+#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
 #define I40E_QTX_TAIL_MAX_INDEX 1535
 #define I40E_QTX_TAIL_TAIL_SHIFT 0
-#define I40E_QTX_TAIL_TAIL_MASK (0x1FFF << I40E_QTX_TAIL_TAIL_SHIFT)
-#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QTX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL_TAIL_SHIFT)
+#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPLAN_MAPENA_MAX_INDEX 127
 #define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0
-#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK (0x1 << I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
-#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK I40E_MASK(0x1, I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
+#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: VFR */
 #define I40E_VPLAN_QTABLE_MAX_INDEX 15
 #define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0
-#define I40E_VPLAN_QTABLE_QINDEX_MASK (0x7FF << I40E_VPLAN_QTABLE_QINDEX_SHIFT)
-#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPLAN_QTABLE_QINDEX_MASK I40E_MASK(0x7FF, I40E_VPLAN_QTABLE_QINDEX_SHIFT)
+#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
 #define I40E_VSILAN_QBASE_MAX_INDEX 383
 #define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0
-#define I40E_VSILAN_QBASE_VSIBASE_MASK (0x7FF << I40E_VSILAN_QBASE_VSIBASE_SHIFT)
+#define I40E_VSILAN_QBASE_VSIBASE_MASK I40E_MASK(0x7FF, I40E_VSILAN_QBASE_VSIBASE_SHIFT)
 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
-#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
-#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK I40E_MASK(0x1, I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
+#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...7, _VSI=0...383 */ /* Reset: PFR */
 #define I40E_VSILAN_QTABLE_MAX_INDEX 7
 #define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
-#define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
+#define I40E_VSILAN_QTABLE_QINDEX_0_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
 #define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
-#define I40E_VSILAN_QTABLE_QINDEX_1_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
-#define I40E_PRTGL_SAH 0x001E2140
+#define I40E_VSILAN_QTABLE_QINDEX_1_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
+#define I40E_PRTGL_SAH 0x001E2140 /* Reset: GLOBR */
 #define I40E_PRTGL_SAH_FC_SAH_SHIFT 0
-#define I40E_PRTGL_SAH_FC_SAH_MASK (0xFFFF << I40E_PRTGL_SAH_FC_SAH_SHIFT)
+#define I40E_PRTGL_SAH_FC_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_FC_SAH_SHIFT)
 #define I40E_PRTGL_SAH_MFS_SHIFT 16
-#define I40E_PRTGL_SAH_MFS_MASK (0xFFFF << I40E_PRTGL_SAH_MFS_SHIFT)
-#define I40E_PRTGL_SAL 0x001E2120
+#define I40E_PRTGL_SAH_MFS_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_MFS_SHIFT)
+#define I40E_PRTGL_SAL 0x001E2120 /* Reset: GLOBR */
 #define I40E_PRTGL_SAL_FC_SAL_SHIFT 0
-#define I40E_PRTGL_SAL_FC_SAL_MASK (0xFFFFFFFF << I40E_PRTGL_SAL_FC_SAL_SHIFT)
-#define I40E_PRTMAC_HLCTLA 0x001E4760
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT 1
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_MASK (0x1 << I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT)
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT 2
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT)
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP 0x001E3130
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP 0x001E3290
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP 0x001E3310
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP 0x001E3100
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP 0x001E3280
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP 0x001E3300
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0
+#define I40E_PRTGL_SAL_FC_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTGL_SAL_FC_SAL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE 0x001E3000
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8
 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0 /* Reset: GLOBR */
 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSECTL1 0x001E3560
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT 3
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT 30
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT 31
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480 /* Reset: GLOBR */
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484 /* Reset: GLOBR */
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
-#define I40E_GL_MNG_FWSM 0x000B6134
-#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
-#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
+#define I40E_GL_FWRESETCNT 0x00083100 /* Reset: POR */
+#define I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT 0
+#define I40E_GL_FWRESETCNT_FWRESETCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT)
+#define I40E_GL_MNG_FWSM 0x000B6134 /* Reset: POR */
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK I40E_MASK(0x3, I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
-#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK I40E_MASK(0xF, I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
-#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
 #define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
-#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK I40E_MASK(0x7, I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
-#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
-#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
-#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK I40E_MASK(0x3F, I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
-#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
-#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28
-#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29
-#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
-#define I40E_GL_MNG_HWARB_CTRL 0x000B6130
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_HWARB_CTRL 0x000B6130 /* Reset: POR */
 #define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0
-#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK (0x1 << I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
-#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK I40E_MASK(0x1, I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
+#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */ /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31
 #define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0
-#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
-#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
+#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260 /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK (0xFF << I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7
 #define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0
-#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK (0xFFFF << I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
-#define I40E_PRT_MNG_MANC 0x00256A20
+#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
+#define I40E_PRT_MNG_MANC 0x00256A20 /* Reset: POR */
 #define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0
-#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
 #define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1
-#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
 #define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17
-#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
 #define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19
-#define I40E_PRT_MNG_MANC_RCV_ALL_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_ALL_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
 #define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25
-#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
 #define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26
-#define I40E_PRT_MNG_MANC_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
 #define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28
-#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
 #define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29
-#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
-#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
+#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MAVTV_MAX_INDEX 7
 #define I40E_PRT_MNG_MAVTV_VID_SHIFT 0
-#define I40E_PRT_MNG_MAVTV_VID_MASK (0xFFF << I40E_PRT_MNG_MAVTV_VID_SHIFT)
-#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32))
+#define I40E_PRT_MNG_MAVTV_VID_MASK I40E_MASK(0xFFF, I40E_PRT_MNG_MAVTV_VID_SHIFT)
+#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEF_MAX_INDEX 7
 #define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4
-#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5
-#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK (0xFF << I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13
-#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17
-#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26
-#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29
-#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30
-#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31
-#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
-#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7
 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK (0xFFFF << I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29
-#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
-#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3
 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
-#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
+#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_METF_MAX_INDEX 3
 #define I40E_PRT_MNG_METF_ETYPE_SHIFT 0
-#define I40E_PRT_MNG_METF_ETYPE_MASK (0xFFFF << I40E_PRT_MNG_METF_ETYPE_SHIFT)
+#define I40E_PRT_MNG_METF_ETYPE_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_METF_ETYPE_SHIFT)
 #define I40E_PRT_MNG_METF_POLARITY_SHIFT 30
-#define I40E_PRT_MNG_METF_POLARITY_MASK (0x1 << I40E_PRT_MNG_METF_POLARITY_SHIFT)
-#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_METF_POLARITY_MASK I40E_MASK(0x1, I40E_PRT_MNG_METF_POLARITY_SHIFT)
+#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
 #define I40E_PRT_MNG_MFUTP_MAX_INDEX 15
 #define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0
-#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK (0xFFFF << I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
 #define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16
-#define I40E_PRT_MNG_MFUTP_UDP_MASK (0x1 << I40E_PRT_MNG_MFUTP_UDP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_UDP_SHIFT)
 #define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17
-#define I40E_PRT_MNG_MFUTP_TCP_MASK (0x1 << I40E_PRT_MNG_MFUTP_TCP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_TCP_SHIFT)
 #define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18
-#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK (0x1 << I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
-#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
+#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3
 #define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
 #define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15
 #define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MMAH_MAX_INDEX 3
 #define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0
-#define I40E_PRT_MNG_MMAH_MMAH_MASK (0xFFFF << I40E_PRT_MNG_MMAH_MMAH_SHIFT)
-#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAH_MMAH_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MMAH_MMAH_SHIFT)
+#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
 #define I40E_PRT_MNG_MMAL_MAX_INDEX 3
 #define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0
-#define I40E_PRT_MNG_MMAL_MMAL_MASK (0xFFFFFFFF << I40E_PRT_MNG_MMAL_MMAL_SHIFT)
-#define I40E_PRT_MNG_MNGONLY 0x00256A60
+#define I40E_PRT_MNG_MMAL_MMAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MMAL_MMAL_SHIFT)
+#define I40E_PRT_MNG_MNGONLY 0x00256A60 /* Reset: POR */
 #define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0
-#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK (0xFF << I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
-#define I40E_PRT_MNG_MSFM 0x00256AA0
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
+#define I40E_PRT_MNG_MSFM 0x00256AA0 /* Reset: POR */
 #define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0
-#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1
-#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2
-#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
 #define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3
-#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4
-#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5
-#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6
-#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
 #define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7
-#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
-#define I40E_MSIX_PBA(_i) (0x00004900 + ((_i) * 4)) /* _i=0...5 */
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
+#define I40E_MSIX_PBA(_i) (0x00001000 + ((_i) * 4)) /* _i=0...5 */ /* Reset: FLR */
 #define I40E_MSIX_PBA_MAX_INDEX 5
 #define I40E_MSIX_PBA_PENBIT_SHIFT 0
-#define I40E_MSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_MSIX_PBA_PENBIT_SHIFT)
-#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_PBA_PENBIT_SHIFT)
+#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TADD_MAX_INDEX 128
 #define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_MSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_MSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_MSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_MSIX_TADD_MSIXTADD10_SHIFT)
 #define I40E_MSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_MSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_MSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_MSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TMSG_MAX_INDEX 128
 #define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_MSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TUADD_MAX_INDEX 128
 #define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_MSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
 #define I40E_MSIX_TVCTRL_MAX_INDEX 128
 #define I40E_MSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_MSIX_TVCTRL_MASK_MASK (0x1 << I40E_MSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFMSIX_PBA1(_i) (0x00004944 + ((_i) * 4)) /* _i=0...19 */
+#define I40E_MSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_MSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */
 #define I40E_VFMSIX_PBA1_MAX_INDEX 19
 #define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA1_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA1_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TADD1_MAX_INDEX 639
 #define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
 #define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD1_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TMSG1_MAX_INDEX 639
 #define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TUADD1_MAX_INDEX 639
 #define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
 #define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL1_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
-#define I40E_GLNVM_FLA 0x000B6108
+#define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
+#define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */
 #define I40E_GLNVM_FLA_FL_SCK_SHIFT 0
-#define I40E_GLNVM_FLA_FL_SCK_MASK (0x1 << I40E_GLNVM_FLA_FL_SCK_SHIFT)
+#define I40E_GLNVM_FLA_FL_SCK_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SCK_SHIFT)
 #define I40E_GLNVM_FLA_FL_CE_SHIFT 1
-#define I40E_GLNVM_FLA_FL_CE_MASK (0x1 << I40E_GLNVM_FLA_FL_CE_SHIFT)
+#define I40E_GLNVM_FLA_FL_CE_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_CE_SHIFT)
 #define I40E_GLNVM_FLA_FL_SI_SHIFT 2
-#define I40E_GLNVM_FLA_FL_SI_MASK (0x1 << I40E_GLNVM_FLA_FL_SI_SHIFT)
+#define I40E_GLNVM_FLA_FL_SI_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SI_SHIFT)
 #define I40E_GLNVM_FLA_FL_SO_SHIFT 3
-#define I40E_GLNVM_FLA_FL_SO_MASK (0x1 << I40E_GLNVM_FLA_FL_SO_SHIFT)
+#define I40E_GLNVM_FLA_FL_SO_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SO_SHIFT)
 #define I40E_GLNVM_FLA_FL_REQ_SHIFT 4
-#define I40E_GLNVM_FLA_FL_REQ_MASK (0x1 << I40E_GLNVM_FLA_FL_REQ_SHIFT)
+#define I40E_GLNVM_FLA_FL_REQ_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_REQ_SHIFT)
 #define I40E_GLNVM_FLA_FL_GNT_SHIFT 5
-#define I40E_GLNVM_FLA_FL_GNT_MASK (0x1 << I40E_GLNVM_FLA_FL_GNT_SHIFT)
+#define I40E_GLNVM_FLA_FL_GNT_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_GNT_SHIFT)
 #define I40E_GLNVM_FLA_LOCKED_SHIFT 6
-#define I40E_GLNVM_FLA_LOCKED_MASK (0x1 << I40E_GLNVM_FLA_LOCKED_SHIFT)
+#define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SHIFT)
 #define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18
-#define I40E_GLNVM_FLA_FL_SADDR_MASK (0x7FF << I40E_GLNVM_FLA_FL_SADDR_SHIFT)
+#define I40E_GLNVM_FLA_FL_SADDR_MASK I40E_MASK(0x7FF, I40E_GLNVM_FLA_FL_SADDR_SHIFT)
 #define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30
-#define I40E_GLNVM_FLA_FL_BUSY_MASK (0x1 << I40E_GLNVM_FLA_FL_BUSY_SHIFT)
+#define I40E_GLNVM_FLA_FL_BUSY_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_BUSY_SHIFT)
 #define I40E_GLNVM_FLA_FL_DER_SHIFT 31
-#define I40E_GLNVM_FLA_FL_DER_MASK (0x1 << I40E_GLNVM_FLA_FL_DER_SHIFT)
-#define I40E_GLNVM_FLASHID 0x000B6104
+#define I40E_GLNVM_FLA_FL_DER_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_DER_SHIFT)
+#define I40E_GLNVM_FLASHID 0x000B6104 /* Reset: POR */
 #define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0
-#define I40E_GLNVM_FLASHID_FLASHID_MASK (0xFFFFFF << I40E_GLNVM_FLASHID_FLASHID_SHIFT)
-#define I40E_GLNVM_GENS 0x000B6100
+#define I40E_GLNVM_FLASHID_FLASHID_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_FLASHID_FLASHID_SHIFT)
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT 31
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_MASK I40E_MASK(0x1, I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT)
+#define I40E_GLNVM_GENS 0x000B6100 /* Reset: POR */
 #define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0
-#define I40E_GLNVM_GENS_NVM_PRES_MASK (0x1 << I40E_GLNVM_GENS_NVM_PRES_SHIFT)
+#define I40E_GLNVM_GENS_NVM_PRES_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_NVM_PRES_SHIFT)
 #define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5
-#define I40E_GLNVM_GENS_SR_SIZE_MASK (0x7 << I40E_GLNVM_GENS_SR_SIZE_SHIFT)
+#define I40E_GLNVM_GENS_SR_SIZE_MASK I40E_MASK(0x7, I40E_GLNVM_GENS_SR_SIZE_SHIFT)
 #define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8
-#define I40E_GLNVM_GENS_BANK1VAL_MASK (0x1 << I40E_GLNVM_GENS_BANK1VAL_SHIFT)
+#define I40E_GLNVM_GENS_BANK1VAL_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_BANK1VAL_SHIFT)
 #define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23
-#define I40E_GLNVM_GENS_ALT_PRST_MASK (0x1 << I40E_GLNVM_GENS_ALT_PRST_SHIFT)
+#define I40E_GLNVM_GENS_ALT_PRST_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_ALT_PRST_SHIFT)
 #define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25
-#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK (0x1 << I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
-#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */
+#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
+#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */ /* Reset: POR */
 #define I40E_GLNVM_PROTCSR_MAX_INDEX 59
 #define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0
-#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK (0xFFFFFF << I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
-#define I40E_GLNVM_SRCTL 0x000B6110
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
+#define I40E_GLNVM_SRCTL 0x000B6110 /* Reset: POR */
 #define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0
-#define I40E_GLNVM_SRCTL_SRBUSY_MASK (0x1 << I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
+#define I40E_GLNVM_SRCTL_SRBUSY_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
 #define I40E_GLNVM_SRCTL_ADDR_SHIFT 14
-#define I40E_GLNVM_SRCTL_ADDR_MASK (0x7FFF << I40E_GLNVM_SRCTL_ADDR_SHIFT)
+#define I40E_GLNVM_SRCTL_ADDR_MASK I40E_MASK(0x7FFF, I40E_GLNVM_SRCTL_ADDR_SHIFT)
 #define I40E_GLNVM_SRCTL_WRITE_SHIFT 29
-#define I40E_GLNVM_SRCTL_WRITE_MASK (0x1 << I40E_GLNVM_SRCTL_WRITE_SHIFT)
+#define I40E_GLNVM_SRCTL_WRITE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_WRITE_SHIFT)
 #define I40E_GLNVM_SRCTL_START_SHIFT 30
-#define I40E_GLNVM_SRCTL_START_MASK (0x1 << I40E_GLNVM_SRCTL_START_SHIFT)
+#define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT)
 #define I40E_GLNVM_SRCTL_DONE_SHIFT 31
-#define I40E_GLNVM_SRCTL_DONE_MASK (0x1 << I40E_GLNVM_SRCTL_DONE_SHIFT)
-#define I40E_GLNVM_SRDATA 0x000B6114
+#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT)
+#define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */
 #define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0
-#define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
+#define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT)
 #define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
-#define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
-#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_SRDATA_RDDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008 /* Reset: POR */
 #define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
-#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
-#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
-#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
-#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
-#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
-#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
-#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
-#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
-#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
 #define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
-#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
-
-#define I40E_GLPCI_BYTCTH 0x0009C484
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+#define I40E_GLPCI_BYTCTH 0x0009C484 /* Reset: PCIR */
 #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_BYTCTL 0x0009C488
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_BYTCTL 0x0009C488 /* Reset: PCIR */
 #define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_CAPCTRL 0x000BE4A4
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_CAPCTRL 0x000BE4A4 /* Reset: PCIR */
 #define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0
-#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK (0x1 << I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
-#define I40E_GLPCI_CAPSUP 0x000BE4A8
+#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP 0x000BE4A8 /* Reset: PCIR */
 #define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0
-#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK (0x1 << I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
+#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
 #define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2
-#define I40E_GLPCI_CAPSUP_LTR_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_LTR_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3
-#define I40E_GLPCI_CAPSUP_TPH_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_TPH_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4
-#define I40E_GLPCI_CAPSUP_ARI_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ARI_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5
-#define I40E_GLPCI_CAPSUP_IOV_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IOV_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6
-#define I40E_GLPCI_CAPSUP_ACS_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ACS_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7
-#define I40E_GLPCI_CAPSUP_SEC_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_SEC_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16
-#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17
-#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18
-#define I40E_GLPCI_CAPSUP_IDO_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IDO_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19
-#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK (0x1 << I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
+#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
 #define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20
-#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
 #define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30
-#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
 #define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31
-#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
-#define I40E_GLPCI_CNF 0x000BE4C0
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
+#define I40E_GLPCI_CNF 0x000BE4C0 /* Reset: POR */
 #define I40E_GLPCI_CNF_FLEX10_SHIFT 1
-#define I40E_GLPCI_CNF_FLEX10_MASK (0x1 << I40E_GLPCI_CNF_FLEX10_SHIFT)
+#define I40E_GLPCI_CNF_FLEX10_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_FLEX10_SHIFT)
 #define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2
-#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK (0x1 << I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
-#define I40E_GLPCI_CNF2 0x000BE494
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
+#define I40E_GLPCI_CNF2 0x000BE494 /* Reset: PCIR */
 #define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0
-#define I40E_GLPCI_CNF2_RO_DIS_MASK (0x1 << I40E_GLPCI_CNF2_RO_DIS_SHIFT)
+#define I40E_GLPCI_CNF2_RO_DIS_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_RO_DIS_SHIFT)
 #define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1
-#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK (0x1 << I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
 #define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2
-#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
 #define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13
-#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
-#define I40E_GLPCI_DREVID 0x0009C480
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
+#define I40E_GLPCI_DREVID 0x0009C480 /* Reset: PCIR */
 #define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0
-#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK (0xFF << I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
-#define I40E_GLPCI_GSCL_1 0x0009C48C
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
+#define I40E_GLPCI_GSCL_1 0x0009C48C /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28
-#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
 #define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
-#define I40E_GLPCI_GSCL_2 0x0009C490
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
+#define I40E_GLPCI_GSCL_2 0x0009C490 /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
-#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
+#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
 #define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3
 #define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0
-#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
 #define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16
-#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
-#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
+#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
 #define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3
 #define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0
-#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK (0xFFFFFFFF << I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
-#define I40E_GLPCI_LATCT 0x0009C4B4
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
+#define I40E_GLPCI_LATCT 0x0009C4B4 /* Reset: PCIR */
 #define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT 0
-#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK (0xFFFFFFFF << I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
-#define I40E_GLPCI_LBARCTRL 0x000BE484
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
+#define I40E_GLPCI_LBARCTRL 0x000BE484 /* Reset: POR */
 #define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0
-#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK (0x1 << I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
+#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
 #define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1
-#define I40E_GLPCI_LBARCTRL_BAR32_MASK (0x1 << I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
+#define I40E_GLPCI_LBARCTRL_BAR32_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
 #define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3
-#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK (0x1 << I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT 4
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_MASK (0x3 << I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT 4
+#define I40E_GLPCI_LBARCTRL_RSVD_4_MASK I40E_MASK(0x3, I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT)
 #define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6
-#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT 10
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_MASK (0x1 << I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT 10
+#define I40E_GLPCI_LBARCTRL_RSVD_10_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT)
 #define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11
-#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
-#define I40E_GLPCI_LINKCAP 0x000BE4AC
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
+#define I40E_GLPCI_LINKCAP 0x000BE4AC /* Reset: PCIR */
 #define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0
-#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK (0x3F << I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK I40E_MASK(0x3F, I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
 #define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6
-#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK (0x7 << I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK I40E_MASK(0x7, I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
 #define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9
-#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK (0xF << I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
-#define I40E_GLPCI_PCIERR 0x000BE4FC
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK I40E_MASK(0xF, I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
+#define I40E_GLPCI_PCIERR 0x000BE4FC /* Reset: PCIR */
 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
-#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
-#define I40E_GLPCI_PCITEST2 0x000BE4BC
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
-
-#define I40E_GLPCI_PKTCT 0x0009C4BC
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PKTCT 0x0009C4BC /* Reset: PCIR */
 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
-#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
-#define I40E_GLPCI_PMSUP 0x000BE4B0
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PMSUP 0x000BE4B0 /* Reset: PCIR */
 #define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0
-#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
+#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
 #define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2
-#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5
-#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8
-#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11
-#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
 #define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14
-#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK (0x1 << I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
+#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK I40E_MASK(0x1, I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
 #define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15
-#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
-#define I40E_GLPCI_PWRDATA 0x000BE490
+#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC /* Reset: PCIR */
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
+#define I40E_GLPCI_PWRDATA 0x000BE490 /* Reset: PCIR */
 #define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0
-#define I40E_GLPCI_PWRDATA_D0_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D0_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8
-#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16
-#define I40E_GLPCI_PWRDATA_D3_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D3_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
 #define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24
-#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK (0x3 << I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
-#define I40E_GLPCI_REVID 0x000BE4B4
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK I40E_MASK(0x3, I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
+#define I40E_GLPCI_REVID 0x000BE4B4 /* Reset: PCIR */
 #define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0
-#define I40E_GLPCI_REVID_NVM_REVID_MASK (0xFF << I40E_GLPCI_REVID_NVM_REVID_SHIFT)
-#define I40E_GLPCI_SERH 0x000BE49C
+#define I40E_GLPCI_REVID_NVM_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_REVID_NVM_REVID_SHIFT)
+#define I40E_GLPCI_SERH 0x000BE49C /* Reset: PCIR */
 #define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0
-#define I40E_GLPCI_SERH_SER_NUM_H_MASK (0xFFFF << I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
-#define I40E_GLPCI_SERL 0x000BE498
+#define I40E_GLPCI_SERH_SER_NUM_H_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
+#define I40E_GLPCI_SERL 0x000BE498 /* Reset: PCIR */
 #define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0
-#define I40E_GLPCI_SERL_SER_NUM_L_MASK (0xFFFFFFFF << I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
-#define I40E_GLPCI_SUBSYSID 0x000BE48C
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT 0
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT)
-#define I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT 16
-#define I40E_GLPCI_SUBSYSID_SUB_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT)
-#define I40E_GLPCI_UPADD 0x000BE4F8
+#define I40E_GLPCI_SERL_SER_NUM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SUBVENID 0x000BE48C /* Reset: PCIR */
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT 0
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT)
+#define I40E_GLPCI_UPADD 0x000BE4F8 /* Reset: PCIR */
 #define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1
-#define I40E_GLPCI_UPADD_ADDRESS_MASK (0x7FFFFFFF << I40E_GLPCI_UPADD_ADDRESS_SHIFT)
-#define I40E_GLPCI_VFSUP 0x000BE4B8
+#define I40E_GLPCI_UPADD_ADDRESS_MASK I40E_MASK(0x7FFFFFFF, I40E_GLPCI_UPADD_ADDRESS_SHIFT)
+#define I40E_GLPCI_VENDORID 0x000BE518 /* Reset: PCIR */
+#define I40E_GLPCI_VENDORID_VENDORID_SHIFT 0
+#define I40E_GLPCI_VENDORID_VENDORID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_VENDORID_VENDORID_SHIFT)
+#define I40E_GLPCI_VFSUP 0x000BE4B8 /* Reset: PCIR */
 #define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0
-#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK (0x1 << I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
 #define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1
-#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK (0x1 << I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
-#define I40E_PF_FUNC_RID 0x0009C000
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
+#define I40E_PF_FUNC_RID 0x0009C000 /* Reset: PCIR */
 #define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0
-#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK (0x7 << I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK I40E_MASK(0x7, I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
 #define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3
-#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK (0x1F << I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK I40E_MASK(0x1F, I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
 #define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8
-#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK (0xFF << I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
-#define I40E_PF_PCI_CIAA 0x0009C080
+#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK I40E_MASK(0xFF, I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
+#define I40E_PF_PCI_CIAA 0x0009C080 /* Reset: FLR */
 #define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0
-#define I40E_PF_PCI_CIAA_ADDRESS_MASK (0xFFF << I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
+#define I40E_PF_PCI_CIAA_ADDRESS_MASK I40E_MASK(0xFFF, I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
 #define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12
-#define I40E_PF_PCI_CIAA_VF_NUM_MASK (0x7F << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
-#define I40E_PF_PCI_CIAD 0x0009C100
+#define I40E_PF_PCI_CIAA_VF_NUM_MASK I40E_MASK(0x7F, I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
+#define I40E_PF_PCI_CIAD 0x0009C100 /* Reset: FLR */
 #define I40E_PF_PCI_CIAD_DATA_SHIFT 0
-#define I40E_PF_PCI_CIAD_DATA_MASK (0xFFFFFFFF << I40E_PF_PCI_CIAD_DATA_SHIFT)
-#define I40E_PFPCI_CLASS 0x000BE400
+#define I40E_PF_PCI_CIAD_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_PCI_CIAD_DATA_SHIFT)
+#define I40E_PFPCI_CLASS 0x000BE400 /* Reset: PCIR */
 #define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0
-#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK (0x1 << I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
-#define I40E_PFPCI_CNF 0x000BE000
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
+#define I40E_PFPCI_CLASS_RESERVED_1_SHIFT 1
+#define I40E_PFPCI_CLASS_RESERVED_1_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_RESERVED_1_SHIFT)
+#define I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT 2
+#define I40E_PFPCI_CLASS_PF_IS_LAN_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT)
+#define I40E_PFPCI_CNF 0x000BE000 /* Reset: PCIR */
 #define I40E_PFPCI_CNF_MSI_EN_SHIFT 2
-#define I40E_PFPCI_CNF_MSI_EN_MASK (0x1 << I40E_PFPCI_CNF_MSI_EN_SHIFT)
+#define I40E_PFPCI_CNF_MSI_EN_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_MSI_EN_SHIFT)
 #define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3
-#define I40E_PFPCI_CNF_EXROM_DIS_MASK (0x1 << I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
+#define I40E_PFPCI_CNF_EXROM_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
 #define I40E_PFPCI_CNF_IO_BAR_SHIFT 4
-#define I40E_PFPCI_CNF_IO_BAR_MASK (0x1 << I40E_PFPCI_CNF_IO_BAR_SHIFT)
+#define I40E_PFPCI_CNF_IO_BAR_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_IO_BAR_SHIFT)
 #define I40E_PFPCI_CNF_INT_PIN_SHIFT 5
-#define I40E_PFPCI_CNF_INT_PIN_MASK (0x3 << I40E_PFPCI_CNF_INT_PIN_SHIFT)
-#define I40E_PFPCI_FACTPS 0x0009C180
+#define I40E_PFPCI_CNF_INT_PIN_MASK I40E_MASK(0x3, I40E_PFPCI_CNF_INT_PIN_SHIFT)
+#define I40E_PFPCI_DEVID 0x000BE080 /* Reset: PCIR */
+#define I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT 0
+#define I40E_PFPCI_DEVID_PF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT)
+#define I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT 16
+#define I40E_PFPCI_DEVID_VF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT)
+#define I40E_PFPCI_FACTPS 0x0009C180 /* Reset: FLR */
 #define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0
-#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK (0x3 << I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK I40E_MASK(0x3, I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
 #define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3
-#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK (0x1 << I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
-#define I40E_PFPCI_FUNC 0x000BE200
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK I40E_MASK(0x1, I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
+#define I40E_PFPCI_FUNC 0x000BE200 /* Reset: POR */
 #define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
 #define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1
-#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
 #define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2
-#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK (0x1 << I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
-#define I40E_PFPCI_FUNC2 0x000BE180
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
+#define I40E_PFPCI_FUNC2 0x000BE180 /* Reset: PCIR */
 #define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
-#define I40E_PFPCI_ICAUSE 0x0009C200
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_ICAUSE 0x0009C200 /* Reset: PFR */
 #define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0
-#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK (0xFFFFFFFF << I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
-#define I40E_PFPCI_IENA 0x0009C280
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
+#define I40E_PFPCI_IENA 0x0009C280 /* Reset: PFR */
 #define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0
-#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK (0xFFFFFFFF << I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
-#define I40E_PFPCI_PFDEVID 0x000BE080
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_PM 0x000BE300
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
+#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800 /* Reset: PCIR */
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_PM 0x000BE300 /* Reset: POR */
 #define I40E_PFPCI_PM_PME_EN_SHIFT 0
-#define I40E_PFPCI_PM_PME_EN_MASK (0x1 << I40E_PFPCI_PM_PME_EN_SHIFT)
-#define I40E_PFPCI_STATUS1 0x000BE280
+#define I40E_PFPCI_PM_PME_EN_MASK I40E_MASK(0x1, I40E_PFPCI_PM_PME_EN_SHIFT)
+#define I40E_PFPCI_STATUS1 0x000BE280 /* Reset: POR */
 #define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0
-#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK (0x1 << I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
-#define I40E_PFPCI_VFDEVID 0x000BE100
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_VMINDEX 0x0009C300
+#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK I40E_MASK(0x1, I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
+#define I40E_PFPCI_SUBSYSID 0x000BE100 /* Reset: PCIR */
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT 0
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT 16
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE 0x0000E400 /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 /* Reset: PCIR */
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VMINDEX 0x0009C300 /* Reset: PCIR */
 #define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0
-#define I40E_PFPCI_VMINDEX_VMINDEX_MASK (0x1FF << I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
-#define I40E_PFPCI_VMPEND 0x0009C380
+#define I40E_PFPCI_VMINDEX_VMINDEX_MASK I40E_MASK(0x1FF, I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
+#define I40E_PFPCI_VMPEND 0x0009C380 /* Reset: PCIR */
 #define I40E_PFPCI_VMPEND_PENDING_SHIFT 0
-#define I40E_PFPCI_VMPEND_PENDING_MASK (0x1 << I40E_PFPCI_VMPEND_PENDING_SHIFT)
-#define I40E_GLPE_CPUSTATUS0 0x0000D040
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT 0
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT)
-#define I40E_GLPE_CPUSTATUS1 0x0000D044
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT 0
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT)
-#define I40E_GLPE_CPUSTATUS2 0x0000D048
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT 0
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL(_i) (0x0000D480 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPE_PFFLMOBJCTRL_MAX_INDEX 15
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMOBJCTRL_MAX_INDEX 31
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMQ1ALLOCERR(_i) (0x0000C700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMQ1ALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFFLMXMITALLOCERR(_i) (0x0000C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMXMITALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFUDACTRL(_i) (0x0000C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDACTRL_MAX_INDEX 31
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN(_i) (0x0000C100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDAUCFBQPN_MAX_INDEX 31
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT 0
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT 31
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_MASK (0x1 << I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_AEQALLOC 0x00131180
-#define I40E_PFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_PFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_PFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_PFPE_CCQPHIGH 0x00008200
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_PFPE_CCQPLOW 0x00008180
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_PFPE_CCQPSTATUS 0x00008100
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_PFPE_CQACK 0x00131100
-#define I40E_PFPE_CQACK_PECQID_SHIFT 0
-#define I40E_PFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_PFPE_CQACK_PECQID_SHIFT)
-#define I40E_PFPE_CQARM 0x00131080
-#define I40E_PFPE_CQARM_PECQID_SHIFT 0
-#define I40E_PFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_PFPE_CQARM_PECQID_SHIFT)
-#define I40E_PFPE_CQPDB 0x00008000
-#define I40E_PFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_PFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_PFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_PFPE_CQPERRCODES 0x00008880
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_PFPE_CQPTAIL 0x00008080
-#define I40E_PFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_PFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_PFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_PFPE_FLMQ1ALLOCERR 0x00008980
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_FLMXMITALLOCERR 0x00008900
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_IPCONFIG0 0x00008280
-#define I40E_PFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-
-#define I40E_PFPE_MRTEIDXMASK 0x00008600
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_PFPE_RCVUNEXPECTEDERROR 0x00008680
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_PFPE_TCPNOWTIMER 0x00008580
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_PFPE_UDACTRL 0x00008700
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN 0x00008780
-#define I40E_PFPE_UDAUCFBQPN_QPN_SHIFT 0
-#define I40E_PFPE_UDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_PFPE_UDAUCFBQPN_QPN_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN_VALID_SHIFT 31
-#define I40E_PFPE_UDAUCFBQPN_VALID_MASK (0x1 << I40E_PFPE_UDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_WQEALLOC 0x00138C00
-#define I40E_PFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_PFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_PFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFPE_AEQALLOC(_VF) (0x00130C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_AEQALLOC_MAX_INDEX 127
-#define I40E_VFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH(_VF) (0x00001000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPHIGH_MAX_INDEX 127
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW(_VF) (0x00000C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPLOW_MAX_INDEX 127
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS(_VF) (0x00000800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPSTATUS_MAX_INDEX 127
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK(_VF) (0x00130800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQACK_MAX_INDEX 127
-#define I40E_VFPE_CQACK_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK_PECQID_SHIFT)
-#define I40E_VFPE_CQARM(_VF) (0x00130400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQARM_MAX_INDEX 127
-#define I40E_VFPE_CQARM_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB(_VF) (0x00000000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPDB_MAX_INDEX 127
-#define I40E_VFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES(_VF) (0x00001800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPERRCODES_MAX_INDEX 127
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL(_VF) (0x00000400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPTAIL_MAX_INDEX 127
-#define I40E_VFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG0(_VF) (0x00001400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_IPCONFIG0_MAX_INDEX 127
-#define I40E_VFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR(_VF) (0x00003400 + ((_VF) * 4))
-#define I40E_VFPE_RCVUNEXPECTEDERROR_MAX_INDEX 127
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER(_VF) (0x00002C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_TCPNOWTIMER_MAX_INDEX 127
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC(_VF) (0x00138000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_WQEALLOC_MAX_INDEX 127
-#define I40E_VFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_GLPES_PFIP4RXDISCARD(_i) (0x00010600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSHI(_i) (0x00010804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSLO(_i) (0x00010800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSHI(_i) (0x00010A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSLO(_i) (0x00010A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSHI(_i) (0x00010C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSLO(_i) (0x00010C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSHI(_i) (0x00010204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSLO(_i) (0x00010200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSHI(_i) (0x00010404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSLO(_i) (0x00010400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXTRUNC(_i) (0x00010700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSHI(_i) (0x00011E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSLO(_i) (0x00011E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSHI(_i) (0x00012004 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSLO(_i) (0x00012000 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSHI(_i) (0x00012204 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSLO(_i) (0x00012200 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXNOROUTE(_i) (0x00012E00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSHI(_i) (0x00011A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSLO(_i) (0x00011A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSHI(_i) (0x00011C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSLO(_i) (0x00011C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXDISCARD(_i) (0x00011200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSHI(_i) (0x00011404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSLO(_i) (0x00011400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSHI(_i) (0x00011604 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSLO(_i) (0x00011600 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSHI(_i) (0x00011804 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSLO(_i) (0x00011800 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSHI(_i) (0x00010E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSLO(_i) (0x00010E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSHI(_i) (0x00011004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSLO(_i) (0x00011000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXTRUNC(_i) (0x00011300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSHI(_i) (0x00012804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSLO(_i) (0x00012800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSHI(_i) (0x00012A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSLO(_i) (0x00012A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSHI(_i) (0x00012C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSLO(_i) (0x00012C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXNOROUTE(_i) (0x00012F00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSHI(_i) (0x00012404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSLO(_i) (0x00012400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSHI(_i) (0x00012604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSLO(_i) (0x00012600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSHI(_i) (0x00013E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSLO(_i) (0x00013E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSHI(_i) (0x00014004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSLO(_i) (0x00014000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSHI(_i) (0x00013C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSLO(_i) (0x00013C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSHI(_i) (0x00014404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSLO(_i) (0x00014400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSHI(_i) (0x00014604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSLO(_i) (0x00014600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSHI(_i) (0x00014204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSLO(_i) (0x00014200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDHI(_i) (0x00014804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDLO(_i) (0x00014800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_PFRDMAVINVHI(_i) (0x00014A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_PFRDMAVINVLO(_i) (0x00014A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_PFRXVLANERR(_i) (0x00010000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFRXVLANERR_MAX_INDEX 15
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_PFTCPRTXSEG(_i) (0x00013600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRTXSEG_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_PFTCPRXOPTERR(_i) (0x00013200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXOPTERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_PFTCPRXPROTOERR(_i) (0x00013300 + ((_i) * 4))
-#define I40E_GLPES_PFTCPRXPROTOERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSHI(_i) (0x00013004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSLO(_i) (0x00013000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGHI(_i) (0x00013404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGLO(_i) (0x00013400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSHI(_i) (0x00013804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSLO(_i) (0x00013800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSHI(_i) (0x00013A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSLO(_i) (0x00013A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSHI 0x0001E014
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSLO 0x0001E010
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPHI 0x0001E01C
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPLO 0x0001E018
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT)
-#define I40E_GLPES_RDMARXOOONOMARK 0x0001E004
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT 0
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT)
-#define I40E_GLPES_RDMARXUNALIGN 0x0001E000
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT 0
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLEHI 0x0001E044
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLELO 0x0001E040
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLEHI 0x0001E02C
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLELO 0x0001E028
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKHI 0x0001E024
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKSLO 0x0001E020
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLEHI 0x0001E03C
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLELO 0x0001E038
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLEHI 0x0001E034
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLELO 0x0001E030
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXUNEXPERR 0x0001E008
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT 0
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_MASK (0xFFFFFF << I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTHI 0x0001E04C
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTLO 0x0001E048
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTHI 0x0001E054
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTLO 0x0001E050
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSHI 0x0001E05C
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSLO 0x0001E058
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXDISCARD(_i) (0x00018600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSHI(_i) (0x00018804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSLO(_i) (0x00018800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSHI(_i) (0x00018A04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSLO(_i) (0x00018A00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSHI(_i) (0x00018C04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSLO(_i) (0x00018C00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSHI(_i) (0x00018204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSLO(_i) (0x00018200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSHI(_i) (0x00018404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSLO(_i) (0x00018400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXTRUNC(_i) (0x00018700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSHI(_i) (0x00019E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSLO(_i) (0x00019E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSHI(_i) (0x0001A004 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSLO(_i) (0x0001A000 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSHI(_i) (0x0001A204 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSLO(_i) (0x0001A200 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXNOROUTE(_i) (0x0001AE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSHI(_i) (0x00019A04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSLO(_i) (0x00019A00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSHI(_i) (0x00019C04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSLO(_i) (0x00019C00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXDISCARD(_i) (0x00019200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSHI(_i) (0x00019404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSLO(_i) (0x00019400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSHI(_i) (0x00019604 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSLO(_i) (0x00019600 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSHI(_i) (0x00019804 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSLO(_i) (0x00019800 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSHI(_i) (0x00018E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSLO(_i) (0x00018E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSHI(_i) (0x00019004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSLO(_i) (0x00019000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXTRUNC(_i) (0x00019300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSHI(_i) (0x0001A804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSLO(_i) (0x0001A800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSHI(_i) (0x0001AA04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSLO(_i) (0x0001AA00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSHI(_i) (0x0001AC04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSLO(_i) (0x0001AC00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXNOROUTE(_i) (0x0001AF00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSHI(_i) (0x0001A404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSLO(_i) (0x0001A400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSHI(_i) (0x0001A604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSLO(_i) (0x0001A600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSHI(_i) (0x0001BE04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSLO(_i) (0x0001BE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSHI(_i) (0x0001C004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSLO(_i) (0x0001C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSHI(_i) (0x0001BC04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSLO(_i) (0x0001BC00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSHI(_i) (0x0001C404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSLO(_i) (0x0001C400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSHI(_i) (0x0001C604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSLO(_i) (0x0001C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSHI(_i) (0x0001C204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSLO(_i) (0x0001C200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDHI(_i) (0x0001C804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDLO(_i) (0x0001C800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_VFRDMAVINVHI(_i) (0x0001CA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_VFRDMAVINVLO(_i) (0x0001CA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_VFRXVLANERR(_i) (0x00018000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRXVLANERR_MAX_INDEX 31
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_VFTCPRTXSEG(_i) (0x0001B600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRTXSEG_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_VFTCPRXOPTERR(_i) (0x0001B200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXOPTERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_VFTCPRXPROTOERR(_i) (0x0001B300 + ((_i) * 4))
-#define I40E_GLPES_VFTCPRXPROTOERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSHI(_i) (0x0001B004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSLO(_i) (0x0001B000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGHI(_i) (0x0001B404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGLO(_i) (0x0001B400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSHI(_i) (0x0001B804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSLO(_i) (0x0001B800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSHI(_i) (0x0001BA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSLO(_i) (0x0001BA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_PRTPM_EEE_STAT 0x001E4320
+#define I40E_PFPCI_VMPEND_PENDING_MASK I40E_MASK(0x1, I40E_PFPCI_VMPEND_PENDING_SHIFT)
+#define I40E_PRTPM_EEE_STAT 0x001E4320 /* Reset: GLOBR */
 #define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
-#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
 #define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30
-#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
 #define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31
-#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
-#define I40E_PRTPM_EEEC 0x001E4380
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEEC 0x001E4380 /* Reset: GLOBR */
 #define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16
-#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK (0x3F << I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
 #define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24
-#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK (0x3 << I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK I40E_MASK(0x3, I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
 #define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26
-#define I40E_PRTPM_EEEC_TEEE_DLY_MASK (0x3F << I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
-#define I40E_PRTPM_EEEFWD 0x001E4400
+#define I40E_PRTPM_EEEC_TEEE_DLY_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
+#define I40E_PRTPM_EEEFWD 0x001E4400 /* Reset: GLOBR */
 #define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31
-#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK (0x1 << I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
-#define I40E_PRTPM_EEER 0x001E4360
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK I40E_MASK(0x1, I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
+#define I40E_PRTPM_EEER 0x001E4360 /* Reset: GLOBR */
 #define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0
-#define I40E_PRTPM_EEER_TW_SYSTEM_MASK (0xFFFF << I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
+#define I40E_PRTPM_EEER_TW_SYSTEM_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
 #define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16
-#define I40E_PRTPM_EEER_TX_LPI_EN_MASK (0x1 << I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
-#define I40E_PRTPM_EEETXC 0x001E43E0
+#define I40E_PRTPM_EEER_TX_LPI_EN_MASK I40E_MASK(0x1, I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
+#define I40E_PRTPM_EEETXC 0x001E43E0 /* Reset: GLOBR */
 #define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0
-#define I40E_PRTPM_EEETXC_TW_PHY_MASK (0xFFFF << I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
-#define I40E_PRTPM_GC 0x000B8140
+#define I40E_PRTPM_EEETXC_TW_PHY_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
+#define I40E_PRTPM_GC 0x000B8140 /* Reset: POR */
 #define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0
-#define I40E_PRTPM_GC_EMP_LINK_ON_MASK (0x1 << I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
+#define I40E_PRTPM_GC_EMP_LINK_ON_MASK I40E_MASK(0x1, I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
 #define I40E_PRTPM_GC_MNG_VETO_SHIFT 1
-#define I40E_PRTPM_GC_MNG_VETO_MASK (0x1 << I40E_PRTPM_GC_MNG_VETO_SHIFT)
+#define I40E_PRTPM_GC_MNG_VETO_MASK I40E_MASK(0x1, I40E_PRTPM_GC_MNG_VETO_SHIFT)
 #define I40E_PRTPM_GC_RATD_SHIFT 2
-#define I40E_PRTPM_GC_RATD_MASK (0x1 << I40E_PRTPM_GC_RATD_SHIFT)
+#define I40E_PRTPM_GC_RATD_MASK I40E_MASK(0x1, I40E_PRTPM_GC_RATD_SHIFT)
 #define I40E_PRTPM_GC_LCDMP_SHIFT 3
-#define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
+#define I40E_PRTPM_GC_LCDMP_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LCDMP_SHIFT)
 #define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
-#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
-#define I40E_PRTPM_RLPIC 0x001E43A0
+#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
+#define I40E_PRTPM_RLPIC 0x001E43A0 /* Reset: GLOBR */
 #define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
-#define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
-#define I40E_PRTPM_TLPIC 0x001E43C0
+#define I40E_PRTPM_RLPIC_ERLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
+#define I40E_PRTPM_TLPIC 0x001E43C0 /* Reset: GLOBR */
 #define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0
-#define I40E_PRTPM_TLPIC_ETLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
-#define I40E_GLRPB_DPSS 0x000AC828
+#define I40E_PRTPM_TLPIC_ETLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
+#define I40E_GLRPB_DPSS 0x000AC828 /* Reset: CORER */
 #define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0
-#define I40E_GLRPB_DPSS_DPS_TCN_MASK (0xFFFFF << I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
-#define I40E_GLRPB_GHW 0x000AC830
+#define I40E_GLRPB_DPSS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
+#define I40E_GLRPB_GHW 0x000AC830 /* Reset: CORER */
 #define I40E_GLRPB_GHW_GHW_SHIFT 0
-#define I40E_GLRPB_GHW_GHW_MASK (0xFFFFF << I40E_GLRPB_GHW_GHW_SHIFT)
-#define I40E_GLRPB_GLW 0x000AC834
+#define I40E_GLRPB_GHW_GHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GHW_GHW_SHIFT)
+#define I40E_GLRPB_GLW 0x000AC834 /* Reset: CORER */
 #define I40E_GLRPB_GLW_GLW_SHIFT 0
-#define I40E_GLRPB_GLW_GLW_MASK (0xFFFFF << I40E_GLRPB_GLW_GLW_SHIFT)
-#define I40E_GLRPB_PHW 0x000AC844
+#define I40E_GLRPB_GLW_GLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GLW_GLW_SHIFT)
+#define I40E_GLRPB_PHW 0x000AC844 /* Reset: CORER */
 #define I40E_GLRPB_PHW_PHW_SHIFT 0
-#define I40E_GLRPB_PHW_PHW_MASK (0xFFFFF << I40E_GLRPB_PHW_PHW_SHIFT)
-#define I40E_GLRPB_PLW 0x000AC848
+#define I40E_GLRPB_PHW_PHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PHW_PHW_SHIFT)
+#define I40E_GLRPB_PLW 0x000AC848 /* Reset: CORER */
 #define I40E_GLRPB_PLW_PLW_SHIFT 0
-#define I40E_GLRPB_PLW_PLW_MASK (0xFFFFF << I40E_GLRPB_PLW_PLW_SHIFT)
-#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_GLRPB_PLW_PLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PLW_PLW_SHIFT)
+#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DHW_MAX_INDEX 7
 #define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0
-#define I40E_PRTRPB_DHW_DHW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
-#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DHW_DHW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
+#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DLW_MAX_INDEX 7
 #define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0
-#define I40E_PRTRPB_DLW_DLW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
-#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DLW_DLW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
+#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_DPS_MAX_INDEX 7
 #define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0
-#define I40E_PRTRPB_DPS_DPS_TCN_MASK (0xFFFFF << I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
-#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DPS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
+#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_SHT_MAX_INDEX 7
 #define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0
-#define I40E_PRTRPB_SHT_SHT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
-#define I40E_PRTRPB_SHW 0x000AC580
+#define I40E_PRTRPB_SHT_SHT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
+#define I40E_PRTRPB_SHW 0x000AC580 /* Reset: CORER */
 #define I40E_PRTRPB_SHW_SHW_SHIFT 0
-#define I40E_PRTRPB_SHW_SHW_MASK (0xFFFFF << I40E_PRTRPB_SHW_SHW_SHIFT)
-#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SHW_SHW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHW_SHW_SHIFT)
+#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_PRTRPB_SLT_MAX_INDEX 7
 #define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0
-#define I40E_PRTRPB_SLT_SLT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
-#define I40E_PRTRPB_SLW 0x000AC6A0
+#define I40E_PRTRPB_SLT_SLT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
+#define I40E_PRTRPB_SLW 0x000AC6A0 /* Reset: CORER */
 #define I40E_PRTRPB_SLW_SLW_SHIFT 0
-#define I40E_PRTRPB_SLW_SLW_MASK (0xFFFFF << I40E_PRTRPB_SLW_SLW_SHIFT)
-#define I40E_PRTRPB_SPS 0x000AC7C0
+#define I40E_PRTRPB_SLW_SLW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLW_SLW_SHIFT)
+#define I40E_PRTRPB_SPS 0x000AC7C0 /* Reset: CORER */
 #define I40E_PRTRPB_SPS_SPS_SHIFT 0
-#define I40E_PRTRPB_SPS_SPS_MASK (0xFFFFF << I40E_PRTRPB_SPS_SPS_SHIFT)
-#define I40E_GLQF_APBVT(_i) (0x00260000 + ((_i) * 4)) /* _i=0...2047 */
-#define I40E_GLQF_APBVT_MAX_INDEX 2047
-#define I40E_GLQF_APBVT_APBVT_SHIFT 0
-#define I40E_GLQF_APBVT_APBVT_MASK (0xFFFFFFFF << I40E_GLQF_APBVT_APBVT_SHIFT)
-#define I40E_GLQF_CTL 0x00269BA4
+#define I40E_PRTRPB_SPS_SPS_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SPS_SPS_SHIFT)
+#define I40E_GLQF_CTL 0x00269BA4 /* Reset: CORER */
 #define I40E_GLQF_CTL_HTOEP_SHIFT 1
-#define I40E_GLQF_CTL_HTOEP_MASK (0x1 << I40E_GLQF_CTL_HTOEP_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_SHIFT)
 #define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2
-#define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_FCOE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
 #define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
-#define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_PCNT_ALLOC_MASK I40E_MASK(0x7, I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT 6
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT)
 #define I40E_GLQF_CTL_RSVD_SHIFT 7
-#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
+#define I40E_GLQF_CTL_RSVD_MASK I40E_MASK(0x1, I40E_GLQF_CTL_RSVD_SHIFT)
 #define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
-#define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXPEBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
 #define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
-#define I40E_GLQF_CTL_MAXFCBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFCBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
 #define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14
-#define I40E_GLQF_CTL_MAXFDBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFDBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
 #define I40E_GLQF_CTL_FDBEST_SHIFT 17
-#define I40E_GLQF_CTL_FDBEST_MASK (0xFF << I40E_GLQF_CTL_FDBEST_SHIFT)
+#define I40E_GLQF_CTL_FDBEST_MASK I40E_MASK(0xFF, I40E_GLQF_CTL_FDBEST_SHIFT)
 #define I40E_GLQF_CTL_PROGPRIO_SHIFT 25
-#define I40E_GLQF_CTL_PROGPRIO_MASK (0x1 << I40E_GLQF_CTL_PROGPRIO_SHIFT)
+#define I40E_GLQF_CTL_PROGPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_PROGPRIO_SHIFT)
 #define I40E_GLQF_CTL_INVALPRIO_SHIFT 26
-#define I40E_GLQF_CTL_INVALPRIO_MASK (0x1 << I40E_GLQF_CTL_INVALPRIO_SHIFT)
+#define I40E_GLQF_CTL_INVALPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_INVALPRIO_SHIFT)
 #define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27
-#define I40E_GLQF_CTL_IGNORE_IP_MASK (0x1 << I40E_GLQF_CTL_IGNORE_IP_SHIFT)
-#define I40E_GLQF_FDCNT_0 0x00269BAC
+#define I40E_GLQF_CTL_IGNORE_IP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_IGNORE_IP_SHIFT)
+#define I40E_GLQF_FDCNT_0 0x00269BAC /* Reset: CORER */
 #define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0
-#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
 #define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13
-#define I40E_GLQF_FDCNT_0_BESTCNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
-#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */
+#define I40E_GLQF_FDCNT_0_BESTCNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
+#define I40E_GLQF_HKEY(_i) (0x00270140 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
+#define I40E_GLQF_HKEY_MAX_INDEX 12
+#define I40E_GLQF_HKEY_KEY_0_SHIFT 0
+#define I40E_GLQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_0_SHIFT)
+#define I40E_GLQF_HKEY_KEY_1_SHIFT 8
+#define I40E_GLQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_1_SHIFT)
+#define I40E_GLQF_HKEY_KEY_2_SHIFT 16
+#define I40E_GLQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_2_SHIFT)
+#define I40E_GLQF_HKEY_KEY_3_SHIFT 24
+#define I40E_GLQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_3_SHIFT)
+#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */ /* Reset: CORER */
 #define I40E_GLQF_HSYM_MAX_INDEX 63
 #define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0
-#define I40E_GLQF_HSYM_SYMH_ENA_MASK (0x1 << I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
-#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */
+#define I40E_GLQF_HSYM_SYMH_ENA_MASK I40E_MASK(0x1, I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
+#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */ /* Reset: CORER */
 #define I40E_GLQF_PCNT_MAX_INDEX 511
 #define I40E_GLQF_PCNT_PCNT_SHIFT 0
-#define I40E_GLQF_PCNT_PCNT_MASK (0xFFFFFFFF << I40E_GLQF_PCNT_PCNT_SHIFT)
-#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */
+#define I40E_GLQF_PCNT_PCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLQF_PCNT_PCNT_SHIFT)
+#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */ /* Reset: CORER */
 #define I40E_GLQF_SWAP_MAX_INDEX 1
 #define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0
-#define I40E_GLQF_SWAP_OFF0_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
 #define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6
-#define I40E_GLQF_SWAP_OFF0_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
 #define I40E_GLQF_SWAP_FLEN0_SHIFT 12
-#define I40E_GLQF_SWAP_FLEN0_MASK (0xF << I40E_GLQF_SWAP_FLEN0_SHIFT)
+#define I40E_GLQF_SWAP_FLEN0_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN0_SHIFT)
 #define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16
-#define I40E_GLQF_SWAP_OFF1_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
 #define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22
-#define I40E_GLQF_SWAP_OFF1_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
 #define I40E_GLQF_SWAP_FLEN1_SHIFT 28
-#define I40E_GLQF_SWAP_FLEN1_MASK (0xF << I40E_GLQF_SWAP_FLEN1_SHIFT)
-#define I40E_PFQF_CTL_0 0x001C0AC0
+#define I40E_GLQF_SWAP_FLEN1_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN1_SHIFT)
+#define I40E_PFQF_CTL_0 0x001C0AC0 /* Reset: CORER */
 #define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0
-#define I40E_PFQF_CTL_0_PEHSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEHSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5
-#define I40E_PFQF_CTL_0_PEDSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEDSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10
-#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14
-#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16
-#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK (0x1 << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17
-#define I40E_PFQF_CTL_0_FD_ENA_MASK (0x1 << I40E_PFQF_CTL_0_FD_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_FD_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_FD_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18
-#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK (0x1 << I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19
-#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK (0x1 << I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
 #define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20
-#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
 #define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24
-#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
-#define I40E_PFQF_CTL_1 0x00245D80
+#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_1 0x00245D80 /* Reset: CORER */
 #define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0
-#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK (0x1 << I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
-#define I40E_PFQF_FDALLOC 0x00246280
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
+#define I40E_PFQF_FDALLOC 0x00246280 /* Reset: CORER */
 #define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0
-#define I40E_PFQF_FDALLOC_FDALLOC_MASK (0xFF << I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
+#define I40E_PFQF_FDALLOC_FDALLOC_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
 #define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8
-#define I40E_PFQF_FDALLOC_FDBEST_MASK (0xFF << I40E_PFQF_FDALLOC_FDBEST_SHIFT)
-#define I40E_PFQF_FDSTAT 0x00246380
+#define I40E_PFQF_FDALLOC_FDBEST_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDBEST_SHIFT)
+#define I40E_PFQF_FDSTAT 0x00246380 /* Reset: CORER */
 #define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0
-#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
 #define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16
-#define I40E_PFQF_FDSTAT_BEST_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
-#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */
+#define I40E_PFQF_FDSTAT_BEST_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
+#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */ /* Reset: CORER */
 #define I40E_PFQF_HENA_MAX_INDEX 1
 #define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_PFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */
+#define I40E_PFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */ /* Reset: CORER */
 #define I40E_PFQF_HKEY_MAX_INDEX 12
 #define I40E_PFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_PFQF_HKEY_KEY_0_MASK (0xFF << I40E_PFQF_HKEY_KEY_0_SHIFT)
+#define I40E_PFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_0_SHIFT)
 #define I40E_PFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_PFQF_HKEY_KEY_1_MASK (0xFF << I40E_PFQF_HKEY_KEY_1_SHIFT)
+#define I40E_PFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_1_SHIFT)
 #define I40E_PFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_PFQF_HKEY_KEY_2_MASK (0xFF << I40E_PFQF_HKEY_KEY_2_SHIFT)
+#define I40E_PFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_2_SHIFT)
 #define I40E_PFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_PFQF_HKEY_KEY_3_MASK (0xFF << I40E_PFQF_HKEY_KEY_3_SHIFT)
-#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */
+#define I40E_PFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_3_SHIFT)
+#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_PFQF_HLUT_MAX_INDEX 127
 #define I40E_PFQF_HLUT_LUT0_SHIFT 0
-#define I40E_PFQF_HLUT_LUT0_MASK (0x3F << I40E_PFQF_HLUT_LUT0_SHIFT)
+#define I40E_PFQF_HLUT_LUT0_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT0_SHIFT)
 #define I40E_PFQF_HLUT_LUT1_SHIFT 8
-#define I40E_PFQF_HLUT_LUT1_MASK (0x3F << I40E_PFQF_HLUT_LUT1_SHIFT)
+#define I40E_PFQF_HLUT_LUT1_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT1_SHIFT)
 #define I40E_PFQF_HLUT_LUT2_SHIFT 16
-#define I40E_PFQF_HLUT_LUT2_MASK (0x3F << I40E_PFQF_HLUT_LUT2_SHIFT)
+#define I40E_PFQF_HLUT_LUT2_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT2_SHIFT)
 #define I40E_PFQF_HLUT_LUT3_SHIFT 24
-#define I40E_PFQF_HLUT_LUT3_MASK (0x3F << I40E_PFQF_HLUT_LUT3_SHIFT)
-#define I40E_PFQF_HREGION(_i) (0x00245400 + ((_i) * 128)) /* _i=0...7 */
-#define I40E_PFQF_HREGION_MAX_INDEX 7
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
-#define I40E_PFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_PFQF_HREGION_REGION_0_MASK (0x7 << I40E_PFQF_HREGION_REGION_0_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
-#define I40E_PFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_PFQF_HREGION_REGION_1_MASK (0x7 << I40E_PFQF_HREGION_REGION_1_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
-#define I40E_PFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_PFQF_HREGION_REGION_2_MASK (0x7 << I40E_PFQF_HREGION_REGION_2_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
-#define I40E_PFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_PFQF_HREGION_REGION_3_MASK (0x7 << I40E_PFQF_HREGION_REGION_3_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
-#define I40E_PFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_PFQF_HREGION_REGION_4_MASK (0x7 << I40E_PFQF_HREGION_REGION_4_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
-#define I40E_PFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_PFQF_HREGION_REGION_5_MASK (0x7 << I40E_PFQF_HREGION_REGION_5_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
-#define I40E_PFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_PFQF_HREGION_REGION_6_MASK (0x7 << I40E_PFQF_HREGION_REGION_6_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
-#define I40E_PFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_PFQF_HREGION_REGION_7_MASK (0x7 << I40E_PFQF_HREGION_REGION_7_SHIFT)
-#define I40E_PRTQF_CTL_0 0x00256E60
+#define I40E_PFQF_HLUT_LUT3_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT3_SHIFT)
+#define I40E_PRTQF_CTL_0 0x00256E60 /* Reset: CORER */
 #define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0
-#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK (0x1 << I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
-#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */
+#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK I40E_MASK(0x1, I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
+#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */ /* Reset: CORER */
 #define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63
 #define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0
-#define I40E_PRTQF_FD_FLXINSET_INSET_MASK (0xFF << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
-#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */
+#define I40E_PRTQF_FD_FLXINSET_INSET_MASK I40E_MASK(0xFF, I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
+#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */ /* Reset: CORER */
 #define I40E_PRTQF_FD_MSK_MAX_INDEX 63
 #define I40E_PRTQF_FD_MSK_MASK_SHIFT 0
-#define I40E_PRTQF_FD_MSK_MASK_MASK (0xFFFF << I40E_PRTQF_FD_MSK_MASK_SHIFT)
+#define I40E_PRTQF_FD_MSK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRTQF_FD_MSK_MASK_SHIFT)
 #define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16
-#define I40E_PRTQF_FD_MSK_OFFSET_MASK (0x3F << I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
-#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
+#define I40E_PRTQF_FD_MSK_OFFSET_MASK I40E_MASK(0x3F, I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
+#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ /* Reset: CORER */
 #define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
-#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
 #define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
-#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
 #define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
-#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
-#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK I40E_MASK(0x3F, I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
+#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...1, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HENA1_MAX_INDEX 1
 #define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA1_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */
+#define I40E_VFQF_HENA1_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HKEY1_MAX_INDEX 12
 #define I40E_VFQF_HKEY1_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY1_KEY_0_MASK (0xFF << I40E_VFQF_HKEY1_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_0_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY1_KEY_1_MASK (0xFF << I40E_VFQF_HKEY1_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_1_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY1_KEY_2_MASK (0xFF << I40E_VFQF_HKEY1_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_2_SHIFT)
 #define I40E_VFQF_HKEY1_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY1_KEY_3_MASK (0xFF << I40E_VFQF_HKEY1_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VFQF_HKEY1_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HLUT1_MAX_INDEX 15
 #define I40E_VFQF_HLUT1_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT1_LUT0_MASK (0xF << I40E_VFQF_HLUT1_LUT0_SHIFT)
+#define I40E_VFQF_HLUT1_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT0_SHIFT)
 #define I40E_VFQF_HLUT1_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT1_LUT1_MASK (0xF << I40E_VFQF_HLUT1_LUT1_SHIFT)
+#define I40E_VFQF_HLUT1_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT1_SHIFT)
 #define I40E_VFQF_HLUT1_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT1_LUT2_MASK (0xF << I40E_VFQF_HLUT1_LUT2_SHIFT)
+#define I40E_VFQF_HLUT1_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT2_SHIFT)
 #define I40E_VFQF_HLUT1_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT1_LUT3_MASK (0xF << I40E_VFQF_HLUT1_LUT3_SHIFT)
-#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HLUT1_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT3_SHIFT)
+#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...7, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HREGION1_MAX_INDEX 7
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION1_REGION_0_MASK (0x7 << I40E_VFQF_HREGION1_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_0_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION1_REGION_1_MASK (0x7 << I40E_VFQF_HREGION1_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_1_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION1_REGION_2_MASK (0x7 << I40E_VFQF_HREGION1_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_2_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION1_REGION_3_MASK (0x7 << I40E_VFQF_HREGION1_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_3_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION1_REGION_4_MASK (0x7 << I40E_VFQF_HREGION1_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_4_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION1_REGION_5_MASK (0x7 << I40E_VFQF_HREGION1_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_5_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION1_REGION_6_MASK (0x7 << I40E_VFQF_HREGION1_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_6_SHIFT)
 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
 #define I40E_VFQF_HREGION1_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION1_REGION_7_MASK (0x7 << I40E_VFQF_HREGION1_REGION_7_SHIFT)
-#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFQF_HREGION1_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_7_SHIFT)
+#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
 #define I40E_VPQF_CTL_MAX_INDEX 127
 #define I40E_VPQF_CTL_PEHSIZE_SHIFT 0
-#define I40E_VPQF_CTL_PEHSIZE_MASK (0x1F << I40E_VPQF_CTL_PEHSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEHSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEHSIZE_SHIFT)
 #define I40E_VPQF_CTL_PEDSIZE_SHIFT 5
-#define I40E_VPQF_CTL_PEDSIZE_MASK (0x1F << I40E_VPQF_CTL_PEDSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEDSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEDSIZE_SHIFT)
 #define I40E_VPQF_CTL_FCHSIZE_SHIFT 10
-#define I40E_VPQF_CTL_FCHSIZE_MASK (0xF << I40E_VPQF_CTL_FCHSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCHSIZE_MASK I40E_MASK(0xF, I40E_VPQF_CTL_FCHSIZE_SHIFT)
 #define I40E_VPQF_CTL_FCDSIZE_SHIFT 14
-#define I40E_VPQF_CTL_FCDSIZE_MASK (0x3 << I40E_VPQF_CTL_FCDSIZE_SHIFT)
-#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPQF_CTL_FCDSIZE_MASK I40E_MASK(0x3, I40E_VPQF_CTL_FCDSIZE_SHIFT)
+#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
 #define I40E_VSIQF_CTL_MAX_INDEX 383
 #define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0
-#define I40E_VSIQF_CTL_FCOE_ENA_MASK (0x1 << I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
+#define I40E_VSIQF_CTL_FCOE_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1
-#define I40E_VSIQF_CTL_PETCP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PETCP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2
-#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3
-#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4
-#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
 #define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
-#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
-#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
+#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...3, _VSI=0...383 */ /* Reset: PFR */
 #define I40E_VSIQF_TCREGION_MAX_INDEX 3
 #define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
-#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
-#define I40E_VSIQF_TCREGION_TC_SIZE_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16
-#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25
-#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
-#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
+#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOECRC_MAX_INDEX 143
 #define I40E_GL_FCOECRC_FCOECRC_SHIFT 0
-#define I40E_GL_FCOECRC_FCOECRC_MASK (0xFFFFFFFF << I40E_GL_FCOECRC_FCOECRC_SHIFT)
-#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOECRC_FCOECRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOECRC_FCOECRC_SHIFT)
+#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDDPC_MAX_INDEX 143
 #define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
-#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
-/* _i=0...143 */
-#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
+#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIFEC_MAX_INDEX 143
 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFRC(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIFRC_MAX_INDEX 143
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIFTCL_MAX_INDEX 143
 #define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0
-#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
-#define I40E_GL_FCOEDIXAC(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIXAC_MAX_INDEX 143
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT 0
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT)
-#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
+#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIXEC_MAX_INDEX 143
 #define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0
-#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
-#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
+#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDIXVC_MAX_INDEX 143
 #define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0
-#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
-#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
+#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWRCH_MAX_INDEX 143
 #define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0
-#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK (0xFFFF << I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
-#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
+#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWRCL_MAX_INDEX 143
 #define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0
-#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
-#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
+#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWTCH_MAX_INDEX 143
 #define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0
-#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK (0xFFFF << I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
-#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
+#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEDWTCL_MAX_INDEX 143
 #define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0
-#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
-#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
+#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOELAST_MAX_INDEX 143
 #define I40E_GL_FCOELAST_FCOELAST_SHIFT 0
-#define I40E_GL_FCOELAST_FCOELAST_MASK (0xFFFFFFFF << I40E_GL_FCOELAST_FCOELAST_SHIFT)
-#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOELAST_FCOELAST_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOELAST_FCOELAST_SHIFT)
+#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEPRC_MAX_INDEX 143
 #define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0
-#define I40E_GL_FCOEPRC_FCOEPRC_MASK (0xFFFFFFFF << I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
-#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPRC_FCOEPRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
+#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOEPTC_MAX_INDEX 143
 #define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0
-#define I40E_GL_FCOEPTC_FCOEPTC_MASK (0xFFFFFFFF << I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
-#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPTC_FCOEPTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
+#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_FCOERPDC_MAX_INDEX 143
 #define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
-#define I40E_GL_FCOERPDC_FCOERPDC_MASK (0xFFFFFFFF << I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
-#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GL_FCOERPDC_FCOERPDC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
+#define I40E_GL_RXERR1_L(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1_L_MAX_INDEX 143
+#define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0
+#define I40E_GL_RXERR1_L_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT)
+#define I40E_GL_RXERR2_L(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR2_L_MAX_INDEX 143
+#define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0
+#define I40E_GL_RXERR2_L_FCOEDIXAC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT)
+#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPRCH_MAX_INDEX 3
 #define I40E_GLPRT_BPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPRCL_MAX_INDEX 3
 #define I40E_GLPRT_BPRCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPRCL_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPRCL_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPTCH_MAX_INDEX 3
 #define I40E_GLPRT_BPTCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPTCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPTCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPTCL_MAX_INDEX 3
 #define I40E_GLPRT_BPTCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPTCL_UPRCH_SHIFT)
-#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPTCL_UPRCH_SHIFT)
+#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_CRCERRS_MAX_INDEX 3
 #define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0
-#define I40E_GLPRT_CRCERRS_CRCERRS_MASK (0xFFFFFFFF << I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
-#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_CRCERRS_CRCERRS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
+#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GORCH_MAX_INDEX 3
 #define I40E_GLPRT_GORCH_GORCH_SHIFT 0
-#define I40E_GLPRT_GORCH_GORCH_MASK (0xFFFF << I40E_GLPRT_GORCH_GORCH_SHIFT)
-#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GORCH_GORCH_SHIFT)
+#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GORCL_MAX_INDEX 3
 #define I40E_GLPRT_GORCL_GORCL_SHIFT 0
-#define I40E_GLPRT_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLPRT_GORCL_GORCL_SHIFT)
-#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GORCL_GORCL_SHIFT)
+#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GOTCH_MAX_INDEX 3
 #define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLPRT_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLPRT_GOTCH_GOTCH_SHIFT)
-#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GOTCH_GOTCH_SHIFT)
+#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_GOTCL_MAX_INDEX 3
 #define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLPRT_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLPRT_GOTCL_GOTCL_SHIFT)
-#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GOTCL_GOTCL_SHIFT)
+#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_ILLERRC_MAX_INDEX 3
 #define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0
-#define I40E_GLPRT_ILLERRC_ILLERRC_MASK (0xFFFFFFFF << I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
-#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ILLERRC_ILLERRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
+#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LDPC_MAX_INDEX 3
 #define I40E_GLPRT_LDPC_LDPC_SHIFT 0
-#define I40E_GLPRT_LDPC_LDPC_MASK (0xFFFFFFFF << I40E_GLPRT_LDPC_LDPC_SHIFT)
-#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LDPC_LDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LDPC_LDPC_SHIFT)
+#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3
 #define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3
 #define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0
-#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
-#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
+#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXONRXC_MAX_INDEX 3
 #define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0
-#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
-#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
+#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_LXONTXC_MAX_INDEX 3
 #define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0
-#define I40E_GLPRT_LXONTXC_LXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
-#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONTXC_LXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
+#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MLFC_MAX_INDEX 3
 #define I40E_GLPRT_MLFC_MLFC_SHIFT 0
-#define I40E_GLPRT_MLFC_MLFC_MASK (0xFFFFFFFF << I40E_GLPRT_MLFC_MLFC_SHIFT)
-#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MLFC_MLFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MLFC_MLFC_SHIFT)
+#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPRCH_MAX_INDEX 3
 #define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLPRT_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLPRT_MPRCH_MPRCH_SHIFT)
-#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPRCH_MPRCH_SHIFT)
+#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPRCL_MAX_INDEX 3
 #define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLPRT_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPRCL_MPRCL_SHIFT)
-#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPRCL_MPRCL_SHIFT)
+#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPTCH_MAX_INDEX 3
 #define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLPRT_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLPRT_MPTCH_MPTCH_SHIFT)
-#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPTCH_MPTCH_SHIFT)
+#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MPTCL_MAX_INDEX 3
 #define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLPRT_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPTCL_MPTCL_SHIFT)
-#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPTCL_MPTCL_SHIFT)
+#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_MRFC_MAX_INDEX 3
 #define I40E_GLPRT_MRFC_MRFC_SHIFT 0
-#define I40E_GLPRT_MRFC_MRFC_MASK (0xFFFFFFFF << I40E_GLPRT_MRFC_MRFC_SHIFT)
-#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MRFC_MRFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MRFC_MRFC_SHIFT)
+#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1023H_MAX_INDEX 3
 #define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0
-#define I40E_GLPRT_PRC1023H_PRC1023H_MASK (0xFFFF << I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
-#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023H_PRC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
+#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1023L_MAX_INDEX 3
 #define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0
-#define I40E_GLPRT_PRC1023L_PRC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
-#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023L_PRC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
+#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC127H_MAX_INDEX 3
 #define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0
-#define I40E_GLPRT_PRC127H_PRC127H_MASK (0xFFFF << I40E_GLPRT_PRC127H_PRC127H_SHIFT)
-#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127H_PRC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC127H_PRC127H_SHIFT)
+#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC127L_MAX_INDEX 3
 #define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0
-#define I40E_GLPRT_PRC127L_PRC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC127L_PRC127L_SHIFT)
-#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127L_PRC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC127L_PRC127L_SHIFT)
+#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1522H_MAX_INDEX 3
 #define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC1522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC1522L_MAX_INDEX 3
 #define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC1522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC255H_MAX_INDEX 3
 #define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0
-#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK (0xFFFF << I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
-#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
+#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC255L_MAX_INDEX 3
 #define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0
-#define I40E_GLPRT_PRC255L_PRC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC255L_PRC255L_SHIFT)
-#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255L_PRC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC255L_PRC255L_SHIFT)
+#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC511H_MAX_INDEX 3
 #define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0
-#define I40E_GLPRT_PRC511H_PRC511H_MASK (0xFFFF << I40E_GLPRT_PRC511H_PRC511H_SHIFT)
-#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511H_PRC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC511H_PRC511H_SHIFT)
+#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC511L_MAX_INDEX 3
 #define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0
-#define I40E_GLPRT_PRC511L_PRC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC511L_PRC511L_SHIFT)
-#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511L_PRC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC511L_PRC511L_SHIFT)
+#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC64H_MAX_INDEX 3
 #define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0
-#define I40E_GLPRT_PRC64H_PRC64H_MASK (0xFFFF << I40E_GLPRT_PRC64H_PRC64H_SHIFT)
-#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64H_PRC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC64H_PRC64H_SHIFT)
+#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC64L_MAX_INDEX 3
 #define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0
-#define I40E_GLPRT_PRC64L_PRC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC64L_PRC64L_SHIFT)
-#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64L_PRC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC64L_PRC64L_SHIFT)
+#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC9522H_MAX_INDEX 3
 #define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC9522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PRC9522L_MAX_INDEX 3
 #define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC9522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1023H_MAX_INDEX 3
 #define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0
-#define I40E_GLPRT_PTC1023H_PTC1023H_MASK (0xFFFF << I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
-#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023H_PTC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
+#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1023L_MAX_INDEX 3
 #define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0
-#define I40E_GLPRT_PTC1023L_PTC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
-#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023L_PTC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
+#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC127H_MAX_INDEX 3
 #define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0
-#define I40E_GLPRT_PTC127H_PTC127H_MASK (0xFFFF << I40E_GLPRT_PTC127H_PTC127H_SHIFT)
-#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127H_PTC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC127H_PTC127H_SHIFT)
+#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC127L_MAX_INDEX 3
 #define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0
-#define I40E_GLPRT_PTC127L_PTC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC127L_PTC127L_SHIFT)
-#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127L_PTC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC127L_PTC127L_SHIFT)
+#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1522H_MAX_INDEX 3
 #define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0
-#define I40E_GLPRT_PTC1522H_PTC1522H_MASK (0xFFFF << I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
-#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522H_PTC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
+#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC1522L_MAX_INDEX 3
 #define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0
-#define I40E_GLPRT_PTC1522L_PTC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
-#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522L_PTC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
+#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC255H_MAX_INDEX 3
 #define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0
-#define I40E_GLPRT_PTC255H_PTC255H_MASK (0xFFFF << I40E_GLPRT_PTC255H_PTC255H_SHIFT)
-#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255H_PTC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC255H_PTC255H_SHIFT)
+#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC255L_MAX_INDEX 3
 #define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0
-#define I40E_GLPRT_PTC255L_PTC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC255L_PTC255L_SHIFT)
-#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255L_PTC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC255L_PTC255L_SHIFT)
+#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC511H_MAX_INDEX 3
 #define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0
-#define I40E_GLPRT_PTC511H_PTC511H_MASK (0xFFFF << I40E_GLPRT_PTC511H_PTC511H_SHIFT)
-#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511H_PTC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC511H_PTC511H_SHIFT)
+#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC511L_MAX_INDEX 3
 #define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0
-#define I40E_GLPRT_PTC511L_PTC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC511L_PTC511L_SHIFT)
-#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511L_PTC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC511L_PTC511L_SHIFT)
+#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC64H_MAX_INDEX 3
 #define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0
-#define I40E_GLPRT_PTC64H_PTC64H_MASK (0xFFFF << I40E_GLPRT_PTC64H_PTC64H_SHIFT)
-#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64H_PTC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC64H_PTC64H_SHIFT)
+#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC64L_MAX_INDEX 3
 #define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0
-#define I40E_GLPRT_PTC64L_PTC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC64L_PTC64L_SHIFT)
-#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64L_PTC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC64L_PTC64L_SHIFT)
+#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC9522H_MAX_INDEX 3
 #define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0
-#define I40E_GLPRT_PTC9522H_PTC9522H_MASK (0xFFFF << I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
-#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522H_PTC9522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
+#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_PTC9522L_MAX_INDEX 3
 #define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0
-#define I40E_GLPRT_PTC9522L_PTC9522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
-#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PTC9522L_PTC9522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
+#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3
 #define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3
 #define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
-#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
+#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXONRXC_MAX_INDEX 3
 #define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0
-#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
-#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
+#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_PXONTXC_MAX_INDEX 3
 #define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0
-#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
-#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
+#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RDPC_MAX_INDEX 3
 #define I40E_GLPRT_RDPC_RDPC_SHIFT 0
-#define I40E_GLPRT_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLPRT_RDPC_RDPC_SHIFT)
-#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RDPC_RDPC_SHIFT)
+#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RFC_MAX_INDEX 3
 #define I40E_GLPRT_RFC_RFC_SHIFT 0
-#define I40E_GLPRT_RFC_RFC_MASK (0xFFFFFFFF << I40E_GLPRT_RFC_RFC_SHIFT)
-#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RFC_RFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RFC_RFC_SHIFT)
+#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RJC_MAX_INDEX 3
 #define I40E_GLPRT_RJC_RJC_SHIFT 0
-#define I40E_GLPRT_RJC_RJC_MASK (0xFFFFFFFF << I40E_GLPRT_RJC_RJC_SHIFT)
-#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RJC_RJC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RJC_RJC_SHIFT)
+#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RLEC_MAX_INDEX 3
 #define I40E_GLPRT_RLEC_RLEC_SHIFT 0
-#define I40E_GLPRT_RLEC_RLEC_MASK (0xFFFFFFFF << I40E_GLPRT_RLEC_RLEC_SHIFT)
-#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RLEC_RLEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RLEC_RLEC_SHIFT)
+#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_ROC_MAX_INDEX 3
 #define I40E_GLPRT_ROC_ROC_SHIFT 0
-#define I40E_GLPRT_ROC_ROC_MASK (0xFFFFFFFF << I40E_GLPRT_ROC_ROC_SHIFT)
-#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ROC_ROC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ROC_ROC_SHIFT)
+#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RUC_MAX_INDEX 3
 #define I40E_GLPRT_RUC_RUC_SHIFT 0
-#define I40E_GLPRT_RUC_RUC_MASK (0xFFFFFFFF << I40E_GLPRT_RUC_RUC_SHIFT)
-#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUC_RUC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUC_RUC_SHIFT)
+#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_RUPP_MAX_INDEX 3
 #define I40E_GLPRT_RUPP_RUPP_SHIFT 0
-#define I40E_GLPRT_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLPRT_RUPP_RUPP_SHIFT)
-#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUPP_RUPP_SHIFT)
+#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
 #define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3
 #define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0
-#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK (0xFFFFFFFF << I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
-#define I40E_GLPRT_STDC(_i) (0x00300640 + ((_i) * 8)) /* _i=0...3 */
-#define I40E_GLPRT_STDC_MAX_INDEX 3
-#define I40E_GLPRT_STDC_STDC_SHIFT 0
-#define I40E_GLPRT_STDC_STDC_MASK (0xFFFFFFFF << I40E_GLPRT_STDC_STDC_SHIFT)
-#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
+#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_TDOLD_MAX_INDEX 3
 #define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0
-#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK (0xFFFFFFFF << I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
-#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
+#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_TDPC_MAX_INDEX 3
 #define I40E_GLPRT_TDPC_TDPC_SHIFT 0
-#define I40E_GLPRT_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLPRT_TDPC_TDPC_SHIFT)
-#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDPC_TDPC_SHIFT)
+#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPRCH_MAX_INDEX 3
 #define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_UPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPRCL_MAX_INDEX 3
 #define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLPRT_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_UPRCL_UPRCL_SHIFT)
-#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPRCL_UPRCL_SHIFT)
+#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPTCH_MAX_INDEX 3
 #define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLPRT_UPTCH_UPTCH_SHIFT)
-#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPTCH_UPTCH_SHIFT)
+#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_UPTCL_MAX_INDEX 3
 #define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCL_VUPTCH_MASK (0xFFFFFFFF << I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
-#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPRT_UPTCL_VUPTCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
+#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPRCH_MAX_INDEX 15
 #define I40E_GLSW_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLSW_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLSW_BPRCH_BPRCH_SHIFT)
-#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPRCH_BPRCH_SHIFT)
+#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPRCL_MAX_INDEX 15
 #define I40E_GLSW_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLSW_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLSW_BPRCL_BPRCL_SHIFT)
-#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPRCL_BPRCL_SHIFT)
+#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPTCH_MAX_INDEX 15
 #define I40E_GLSW_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLSW_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLSW_BPTCH_BPTCH_SHIFT)
-#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPTCH_BPTCH_SHIFT)
+#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_BPTCL_MAX_INDEX 15
 #define I40E_GLSW_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLSW_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLSW_BPTCL_BPTCL_SHIFT)
-#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPTCL_BPTCL_SHIFT)
+#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GORCH_MAX_INDEX 15
 #define I40E_GLSW_GORCH_GORCH_SHIFT 0
-#define I40E_GLSW_GORCH_GORCH_MASK (0xFFFF << I40E_GLSW_GORCH_GORCH_SHIFT)
-#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GORCH_GORCH_SHIFT)
+#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GORCL_MAX_INDEX 15
 #define I40E_GLSW_GORCL_GORCL_SHIFT 0
-#define I40E_GLSW_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLSW_GORCL_GORCL_SHIFT)
-#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GORCL_GORCL_SHIFT)
+#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GOTCH_MAX_INDEX 15
 #define I40E_GLSW_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLSW_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLSW_GOTCH_GOTCH_SHIFT)
-#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GOTCH_GOTCH_SHIFT)
+#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_GOTCL_MAX_INDEX 15
 #define I40E_GLSW_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLSW_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLSW_GOTCL_GOTCL_SHIFT)
-#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GOTCL_GOTCL_SHIFT)
+#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPRCH_MAX_INDEX 15
 #define I40E_GLSW_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLSW_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLSW_MPRCH_MPRCH_SHIFT)
-#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPRCH_MPRCH_SHIFT)
+#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPRCL_MAX_INDEX 15
 #define I40E_GLSW_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLSW_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLSW_MPRCL_MPRCL_SHIFT)
-#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPRCL_MPRCL_SHIFT)
+#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPTCH_MAX_INDEX 15
 #define I40E_GLSW_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLSW_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLSW_MPTCH_MPTCH_SHIFT)
-#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPTCH_MPTCH_SHIFT)
+#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_MPTCL_MAX_INDEX 15
 #define I40E_GLSW_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLSW_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLSW_MPTCL_MPTCL_SHIFT)
-#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPTCL_MPTCL_SHIFT)
+#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_RUPP_MAX_INDEX 15
 #define I40E_GLSW_RUPP_RUPP_SHIFT 0
-#define I40E_GLSW_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLSW_RUPP_RUPP_SHIFT)
-#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_RUPP_RUPP_SHIFT)
+#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_TDPC_MAX_INDEX 15
 #define I40E_GLSW_TDPC_TDPC_SHIFT 0
-#define I40E_GLSW_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLSW_TDPC_TDPC_SHIFT)
-#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_TDPC_TDPC_SHIFT)
+#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPRCH_MAX_INDEX 15
 #define I40E_GLSW_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLSW_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLSW_UPRCH_UPRCH_SHIFT)
-#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPRCH_UPRCH_SHIFT)
+#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPRCL_MAX_INDEX 15
 #define I40E_GLSW_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLSW_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLSW_UPRCL_UPRCL_SHIFT)
-#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPRCL_UPRCL_SHIFT)
+#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPTCH_MAX_INDEX 15
 #define I40E_GLSW_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLSW_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLSW_UPTCH_UPTCH_SHIFT)
-#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPTCH_UPTCH_SHIFT)
+#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_GLSW_UPTCL_MAX_INDEX 15
 #define I40E_GLSW_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLSW_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLSW_UPTCL_UPTCL_SHIFT)
-#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLSW_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPTCL_UPTCL_SHIFT)
+#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPRCH_MAX_INDEX 383
 #define I40E_GLV_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLV_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLV_BPRCH_BPRCH_SHIFT)
-#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPRCH_BPRCH_SHIFT)
+#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPRCL_MAX_INDEX 383
 #define I40E_GLV_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLV_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLV_BPRCL_BPRCL_SHIFT)
-#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPRCL_BPRCL_SHIFT)
+#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPTCH_MAX_INDEX 383
 #define I40E_GLV_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLV_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLV_BPTCH_BPTCH_SHIFT)
-#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPTCH_BPTCH_SHIFT)
+#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_BPTCL_MAX_INDEX 383
 #define I40E_GLV_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLV_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLV_BPTCL_BPTCL_SHIFT)
-#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPTCL_BPTCL_SHIFT)
+#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GORCH_MAX_INDEX 383
 #define I40E_GLV_GORCH_GORCH_SHIFT 0
-#define I40E_GLV_GORCH_GORCH_MASK (0xFFFF << I40E_GLV_GORCH_GORCH_SHIFT)
-#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GORCH_GORCH_SHIFT)
+#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GORCL_MAX_INDEX 383
 #define I40E_GLV_GORCL_GORCL_SHIFT 0
-#define I40E_GLV_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLV_GORCL_GORCL_SHIFT)
-#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GORCL_GORCL_SHIFT)
+#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GOTCH_MAX_INDEX 383
 #define I40E_GLV_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLV_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLV_GOTCH_GOTCH_SHIFT)
-#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GOTCH_GOTCH_SHIFT)
+#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_GOTCL_MAX_INDEX 383
 #define I40E_GLV_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLV_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLV_GOTCL_GOTCL_SHIFT)
-#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GOTCL_GOTCL_SHIFT)
+#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPRCH_MAX_INDEX 383
 #define I40E_GLV_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLV_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLV_MPRCH_MPRCH_SHIFT)
-#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPRCH_MPRCH_SHIFT)
+#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPRCL_MAX_INDEX 383
 #define I40E_GLV_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLV_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLV_MPRCL_MPRCL_SHIFT)
-#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPRCL_MPRCL_SHIFT)
+#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPTCH_MAX_INDEX 383
 #define I40E_GLV_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLV_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLV_MPTCH_MPTCH_SHIFT)
-#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPTCH_MPTCH_SHIFT)
+#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_MPTCL_MAX_INDEX 383
 #define I40E_GLV_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLV_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLV_MPTCL_MPTCL_SHIFT)
-#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPTCL_MPTCL_SHIFT)
+#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_RDPC_MAX_INDEX 383
 #define I40E_GLV_RDPC_RDPC_SHIFT 0
-#define I40E_GLV_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLV_RDPC_RDPC_SHIFT)
-#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RDPC_RDPC_SHIFT)
+#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_RUPP_MAX_INDEX 383
 #define I40E_GLV_RUPP_RUPP_SHIFT 0
-#define I40E_GLV_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLV_RUPP_RUPP_SHIFT)
-#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 8)) /* _i=0...383 */
+#define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT)
+#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_TEPC_MAX_INDEX 383
 #define I40E_GLV_TEPC_TEPC_SHIFT 0
-#define I40E_GLV_TEPC_TEPC_MASK (0xFFFFFFFF << I40E_GLV_TEPC_TEPC_SHIFT)
-#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT)
+#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPRCH_MAX_INDEX 383
 #define I40E_GLV_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLV_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLV_UPRCH_UPRCH_SHIFT)
-#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPRCH_UPRCH_SHIFT)
+#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPRCL_MAX_INDEX 383
 #define I40E_GLV_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLV_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLV_UPRCL_UPRCL_SHIFT)
-#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPRCL_UPRCL_SHIFT)
+#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPTCH_MAX_INDEX 383
 #define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0
-#define I40E_GLV_UPTCH_GLVUPTCH_MASK (0xFFFF << I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
-#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCH_GLVUPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
+#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
 #define I40E_GLV_UPTCL_MAX_INDEX 383
 #define I40E_GLV_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLV_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLV_UPTCL_UPTCL_SHIFT)
-#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLV_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPTCL_UPTCL_SHIFT)
+#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RBCH_MAX_INDEX 7
 #define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_RBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RBCL_MAX_INDEX 7
 #define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_RBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RPCH_MAX_INDEX 7
 #define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_RPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_RPCL_MAX_INDEX 7
 #define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_RPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
-#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
+#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TBCH_MAX_INDEX 7
 #define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_TBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TBCL_MAX_INDEX 7
 #define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_TBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TPCH_MAX_INDEX 7
 #define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_TPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
 #define I40E_GLVEBTC_TPCL_MAX_INDEX 7
 #define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_TPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
-#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBTC_TPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
+#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_BPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0
-#define I40E_GLVEBVL_BPCH_VLBPCH_MASK (0xFFFF << I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
-#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCH_VLBPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
+#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_BPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0
-#define I40E_GLVEBVL_BPCL_VLBPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
-#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCL_VLBPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
+#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GORCH_MAX_INDEX 127
 #define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GORCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GORCL_MAX_INDEX 127
 #define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GORCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GOTCH_MAX_INDEX 127
 #define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GOTCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_GOTCL_MAX_INDEX 127
 #define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GOTCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_MPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0
-#define I40E_GLVEBVL_MPCH_VLMPCH_MASK (0xFFFF << I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
-#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCH_VLMPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
+#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_MPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0
-#define I40E_GLVEBVL_MPCL_VLMPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
-#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCL_VLMPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
+#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_UPCH_MAX_INDEX 127
 #define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0
-#define I40E_GLVEBVL_UPCH_VLUPCH_MASK (0xFFFF << I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
-#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCH_VLUPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
+#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_GLVEBVL_UPCL_MAX_INDEX 127
 #define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0
-#define I40E_GLVEBVL_UPCL_VLUPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C
+#define I40E_GLVEBVL_UPCL_VLUPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C /* Reset: CORER */
 #define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK (0xFFFF << I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_L 0x00269F44
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_MASK (0xFFFFFFFF << I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT)
-#define I40E_GL_SWR_DEF_ACT(_i) (0x0026CF00 + ((_i) * 4)) /* _i=0...25 */
-#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 25
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK I40E_MASK(0xFFFF, I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
+#define I40E_GL_SWR_DEF_ACT(_i) (0x00270200 + ((_i) * 4)) /* _i=0...35 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 35
 #define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
-#define I40E_GL_SWR_DEF_ACT_EN 0x0026CF84
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
+#define I40E_GL_SWR_DEF_ACT_EN(_i) (0x0026CFB8 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_EN_MAX_INDEX 1
 #define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
-#define I40E_PRT_MSCCNT 0x00256BA0
-#define I40E_PRT_MSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_MSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_MSCCNT_CCOUNT_SHIFT)
-#define I40E_PRT_SCSTS 0x00256C20
-#define I40E_PRT_SCSTS_BSCA_SHIFT 0
-#define I40E_PRT_SCSTS_BSCA_MASK (0x1 << I40E_PRT_SCSTS_BSCA_SHIFT)
-#define I40E_PRT_SCSTS_BSCAP_SHIFT 1
-#define I40E_PRT_SCSTS_BSCAP_MASK (0x1 << I40E_PRT_SCSTS_BSCAP_SHIFT)
-#define I40E_PRT_SCSTS_MSCA_SHIFT 2
-#define I40E_PRT_SCSTS_MSCA_MASK (0x1 << I40E_PRT_SCSTS_MSCA_SHIFT)
-#define I40E_PRT_SCSTS_MSCAP_SHIFT 3
-#define I40E_PRT_SCSTS_MSCAP_MASK (0x1 << I40E_PRT_SCSTS_MSCAP_SHIFT)
-#define I40E_PRT_SWT_BSCCNT 0x00256C60
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT)
-#define I40E_PRTTSYN_ADJ 0x001E4280
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
+#define I40E_PRTTSYN_ADJ 0x001E4280 /* Reset: GLOBR */
 #define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0
-#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK (0x7FFFFFFF << I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
+#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK I40E_MASK(0x7FFFFFFF, I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
 #define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31
-#define I40E_PRTTSYN_ADJ_SIGN_MASK (0x1 << I40E_PRTTSYN_ADJ_SIGN_SHIFT)
-#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_ADJ_SIGN_MASK I40E_MASK(0x1, I40E_PRTTSYN_ADJ_SIGN_SHIFT)
+#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_AUX_0_MAX_INDEX 1
 #define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0
-#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
 #define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1
-#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK (0x3 << I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
 #define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3
-#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
 #define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8
-#define I40E_PRTTSYN_AUX_0_PULSEW_MASK (0xF << I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
+#define I40E_PRTTSYN_AUX_0_PULSEW_MASK I40E_MASK(0xF, I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
 #define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16
-#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK (0x3 << I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
-#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_AUX_1_MAX_INDEX 1
 #define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0
-#define I40E_PRTTSYN_AUX_1_INSTNT_MASK (0x1 << I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
+#define I40E_PRTTSYN_AUX_1_INSTNT_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
 #define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1
-#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK (0x1 << I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
-#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
+#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_CLKO_MAX_INDEX 1
 #define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0
-#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK (0xFFFFFFFF << I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
-#define I40E_PRTTSYN_CTL0 0x001E4200
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
+#define I40E_PRTTSYN_CTL0 0x001E4200 /* Reset: GLOBR */
 #define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0
-#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK (0x1 << I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
 #define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1
-#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2
-#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3
-#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8
-#define I40E_PRTTSYN_CTL0_PF_ID_MASK (0xF << I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
+#define I40E_PRTTSYN_CTL0_PF_ID_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
 #define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12
-#define I40E_PRTTSYN_CTL0_TSYNACT_MASK (0x3 << I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNACT_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
 #define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL0_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_CTL1 0x00085020
+#define I40E_PRTTSYN_CTL0_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_CTL1 0x00085020 /* Reset: CORER */
 #define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
 #define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
 #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
 #define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
 #define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24
-#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK (0x3 << I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
 #define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26
-#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK (0x3 << I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
 #define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL1_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1
 #define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0
-#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
-#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
+#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1
 #define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0
-#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
-#define I40E_PRTTSYN_INC_H 0x001E4060
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
+#define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */
 #define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0
-#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK (0x3F << I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
-#define I40E_PRTTSYN_INC_L 0x001E4040
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK I40E_MASK(0x3F, I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
+#define I40E_PRTTSYN_INC_L 0x001E4040 /* Reset: GLOBR */
 #define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0
-#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
-#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
+#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3
 #define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3
 #define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
-#define I40E_PRTTSYN_STAT_0 0x001E4220
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
+#define I40E_PRTTSYN_STAT_0 0x001E4220 /* Reset: GLOBR */
 #define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_0_EVENT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
 #define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_0_EVENT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2
-#define I40E_PRTTSYN_STAT_0_TGT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3
-#define I40E_PRTTSYN_STAT_0_TGT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
 #define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4
-#define I40E_PRTTSYN_STAT_0_TXTIME_MASK (0x1 << I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
-#define I40E_PRTTSYN_STAT_1 0x00085140
+#define I40E_PRTTSYN_STAT_0_TXTIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
+#define I40E_PRTTSYN_STAT_1 0x00085140 /* Reset: CORER */
 #define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_1_RXT0_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_1_RXT1_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2
-#define I40E_PRTTSYN_STAT_1_RXT2_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT2_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
 #define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3
-#define I40E_PRTTSYN_STAT_1_RXT3_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
-#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_STAT_1_RXT3_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
+#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_TGT_H_MAX_INDEX 1
 #define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0
-#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
-#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
+#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
 #define I40E_PRTTSYN_TGT_L_MAX_INDEX 1
 #define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0
-#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
-#define I40E_PRTTSYN_TIME_H 0x001E4120
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
+#define I40E_PRTTSYN_TIME_H 0x001E4120 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0
-#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
-#define I40E_PRTTSYN_TIME_L 0x001E4100
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
+#define I40E_PRTTSYN_TIME_L 0x001E4100 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0
-#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
-#define I40E_PRTTSYN_TXTIME_H 0x001E41E0
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
+#define I40E_PRTTSYN_TXTIME_H 0x001E41E0 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_TXTIME_L 0x001E41C0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_TXTIME_L 0x001E41C0 /* Reset: GLOBR */
 #define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
-#define I40E_GLSCD_QUANTA 0x000B2080
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
+#define I40E_GLSCD_QUANTA 0x000B2080 /* Reset: CORER */
 #define I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT 0
-#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK (0x7 << I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
-#define I40E_GL_MDET_RX 0x0012A510
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK I40E_MASK(0x7, I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
+#define I40E_GL_MDET_RX 0x0012A510 /* Reset: CORER */
 #define I40E_GL_MDET_RX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_RX_FUNCTION_MASK (0xFF << I40E_GL_MDET_RX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_RX_FUNCTION_MASK I40E_MASK(0xFF, I40E_GL_MDET_RX_FUNCTION_SHIFT)
 #define I40E_GL_MDET_RX_EVENT_SHIFT 8
-#define I40E_GL_MDET_RX_EVENT_MASK (0x1FF << I40E_GL_MDET_RX_EVENT_SHIFT)
+#define I40E_GL_MDET_RX_EVENT_MASK I40E_MASK(0x1FF, I40E_GL_MDET_RX_EVENT_SHIFT)
 #define I40E_GL_MDET_RX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_RX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_RX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_QUEUE_MASK I40E_MASK(0x3FFF, I40E_GL_MDET_RX_QUEUE_SHIFT)
 #define I40E_GL_MDET_RX_VALID_SHIFT 31
-#define I40E_GL_MDET_RX_VALID_MASK (0x1 << I40E_GL_MDET_RX_VALID_SHIFT)
-#define I40E_GL_MDET_TX 0x000E6480
-#define I40E_GL_MDET_TX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_TX_FUNCTION_MASK (0xFF << I40E_GL_MDET_TX_FUNCTION_SHIFT)
-#define I40E_GL_MDET_TX_EVENT_SHIFT 8
-#define I40E_GL_MDET_TX_EVENT_MASK (0x1FF << I40E_GL_MDET_TX_EVENT_SHIFT)
-#define I40E_GL_MDET_TX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_TX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_RX_VALID_SHIFT)
+#define I40E_GL_MDET_TX 0x000E6480 /* Reset: CORER */
+#define I40E_GL_MDET_TX_QUEUE_SHIFT 0
+#define I40E_GL_MDET_TX_QUEUE_MASK I40E_MASK(0xFFF, I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_TX_VF_NUM_SHIFT 12
+#define I40E_GL_MDET_TX_VF_NUM_MASK I40E_MASK(0x1FF, I40E_GL_MDET_TX_VF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_PF_NUM_SHIFT 21
+#define I40E_GL_MDET_TX_PF_NUM_MASK I40E_MASK(0xF, I40E_GL_MDET_TX_PF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_EVENT_SHIFT 25
+#define I40E_GL_MDET_TX_EVENT_MASK I40E_MASK(0x1F, I40E_GL_MDET_TX_EVENT_SHIFT)
 #define I40E_GL_MDET_TX_VALID_SHIFT 31
-#define I40E_GL_MDET_TX_VALID_MASK (0x1 << I40E_GL_MDET_TX_VALID_SHIFT)
-#define I40E_PF_MDET_RX 0x0012A400
+#define I40E_GL_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_TX_VALID_SHIFT)
+#define I40E_PF_MDET_RX 0x0012A400 /* Reset: CORER */
 #define I40E_PF_MDET_RX_VALID_SHIFT 0
-#define I40E_PF_MDET_RX_VALID_MASK (0x1 << I40E_PF_MDET_RX_VALID_SHIFT)
-#define I40E_PF_MDET_TX 0x000E6400
+#define I40E_PF_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_RX_VALID_SHIFT)
+#define I40E_PF_MDET_TX 0x000E6400 /* Reset: CORER */
 #define I40E_PF_MDET_TX_VALID_SHIFT 0
-#define I40E_PF_MDET_TX_VALID_MASK (0x1 << I40E_PF_MDET_TX_VALID_SHIFT)
-#define I40E_PF_VT_PFALLOC 0x001C0500
+#define I40E_PF_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_TX_VALID_SHIFT)
+#define I40E_PF_VT_PFALLOC 0x001C0500 /* Reset: CORER */
 #define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0
-#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
 #define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8
-#define I40E_PF_VT_PFALLOC_LASTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
 #define I40E_PF_VT_PFALLOC_VALID_SHIFT 31
-#define I40E_PF_VT_PFALLOC_VALID_MASK (0x1 << I40E_PF_VT_PFALLOC_VALID_SHIFT)
-#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT)
+#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VP_MDET_RX_MAX_INDEX 127
 #define I40E_VP_MDET_RX_VALID_SHIFT 0
-#define I40E_VP_MDET_RX_VALID_MASK (0x1 << I40E_VP_MDET_RX_VALID_SHIFT)
-#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_RX_VALID_SHIFT)
+#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
 #define I40E_VP_MDET_TX_MAX_INDEX 127
 #define I40E_VP_MDET_TX_VALID_SHIFT 0
-#define I40E_VP_MDET_TX_VALID_MASK (0x1 << I40E_VP_MDET_TX_VALID_SHIFT)
-#define I40E_GLPM_WUMC 0x0006C800
+#define I40E_VP_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_TX_VALID_SHIFT)
+#define I40E_GLPM_WUMC 0x0006C800 /* Reset: POR */
 #define I40E_GLPM_WUMC_NOTCO_SHIFT 0
-#define I40E_GLPM_WUMC_NOTCO_MASK (0x1 << I40E_GLPM_WUMC_NOTCO_SHIFT)
+#define I40E_GLPM_WUMC_NOTCO_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_NOTCO_SHIFT)
 #define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1
-#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK (0x1 << I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
 #define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2
-#define I40E_GLPM_WUMC_ROL_MODE_MASK (0x1 << I40E_GLPM_WUMC_ROL_MODE_SHIFT)
+#define I40E_GLPM_WUMC_ROL_MODE_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_ROL_MODE_SHIFT)
 #define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3
-#define I40E_GLPM_WUMC_RESERVED_4_MASK (0x1FFF << I40E_GLPM_WUMC_RESERVED_4_SHIFT)
+#define I40E_GLPM_WUMC_RESERVED_4_MASK I40E_MASK(0x1FFF, I40E_GLPM_WUMC_RESERVED_4_SHIFT)
 #define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16
-#define I40E_GLPM_WUMC_MNG_WU_PF_MASK (0xFFFF << I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
-#define I40E_PFPM_APM 0x000B8080
+#define I40E_GLPM_WUMC_MNG_WU_PF_MASK I40E_MASK(0xFFFF, I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
+#define I40E_PFPM_APM 0x000B8080 /* Reset: POR */
 #define I40E_PFPM_APM_APME_SHIFT 0
-#define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
-#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFPM_APM_APME_MASK I40E_MASK(0x1, I40E_PFPM_APM_APME_SHIFT)
+#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ /* Reset: POR */
 #define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
 #define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PFPM_WUC 0x0006B200
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PFPM_WUC 0x0006B200 /* Reset: POR */
 #define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
-#define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
-#define I40E_PFPM_WUFC 0x0006B400
+#define I40E_PFPM_WUC_EN_APM_D0_MASK I40E_MASK(0x1, I40E_PFPM_WUC_EN_APM_D0_SHIFT)
+#define I40E_PFPM_WUFC 0x0006B400 /* Reset: POR */
 #define I40E_PFPM_WUFC_LNKC_SHIFT 0
-#define I40E_PFPM_WUFC_LNKC_MASK (0x1 << I40E_PFPM_WUFC_LNKC_SHIFT)
+#define I40E_PFPM_WUFC_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_LNKC_SHIFT)
 #define I40E_PFPM_WUFC_MAG_SHIFT 1
-#define I40E_PFPM_WUFC_MAG_MASK (0x1 << I40E_PFPM_WUFC_MAG_SHIFT)
+#define I40E_PFPM_WUFC_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MAG_SHIFT)
 #define I40E_PFPM_WUFC_MNG_SHIFT 3
-#define I40E_PFPM_WUFC_MNG_MASK (0x1 << I40E_PFPM_WUFC_MNG_SHIFT)
+#define I40E_PFPM_WUFC_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MNG_SHIFT)
 #define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4
-#define I40E_PFPM_WUFC_FLX0_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5
-#define I40E_PFPM_WUFC_FLX1_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6
-#define I40E_PFPM_WUFC_FLX2_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7
-#define I40E_PFPM_WUFC_FLX3_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8
-#define I40E_PFPM_WUFC_FLX4_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9
-#define I40E_PFPM_WUFC_FLX5_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10
-#define I40E_PFPM_WUFC_FLX6_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11
-#define I40E_PFPM_WUFC_FLX7_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
 #define I40E_PFPM_WUFC_FLX0_SHIFT 16
-#define I40E_PFPM_WUFC_FLX0_MASK (0x1 << I40E_PFPM_WUFC_FLX0_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_SHIFT)
 #define I40E_PFPM_WUFC_FLX1_SHIFT 17
-#define I40E_PFPM_WUFC_FLX1_MASK (0x1 << I40E_PFPM_WUFC_FLX1_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_SHIFT)
 #define I40E_PFPM_WUFC_FLX2_SHIFT 18
-#define I40E_PFPM_WUFC_FLX2_MASK (0x1 << I40E_PFPM_WUFC_FLX2_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_SHIFT)
 #define I40E_PFPM_WUFC_FLX3_SHIFT 19
-#define I40E_PFPM_WUFC_FLX3_MASK (0x1 << I40E_PFPM_WUFC_FLX3_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_SHIFT)
 #define I40E_PFPM_WUFC_FLX4_SHIFT 20
-#define I40E_PFPM_WUFC_FLX4_MASK (0x1 << I40E_PFPM_WUFC_FLX4_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_SHIFT)
 #define I40E_PFPM_WUFC_FLX5_SHIFT 21
-#define I40E_PFPM_WUFC_FLX5_MASK (0x1 << I40E_PFPM_WUFC_FLX5_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_SHIFT)
 #define I40E_PFPM_WUFC_FLX6_SHIFT 22
-#define I40E_PFPM_WUFC_FLX6_MASK (0x1 << I40E_PFPM_WUFC_FLX6_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_SHIFT)
 #define I40E_PFPM_WUFC_FLX7_SHIFT 23
-#define I40E_PFPM_WUFC_FLX7_MASK (0x1 << I40E_PFPM_WUFC_FLX7_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_SHIFT)
 #define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUFC_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
-#define I40E_PFPM_WUS 0x0006B600
+#define I40E_PFPM_WUFC_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
+#define I40E_PFPM_WUS 0x0006B600 /* Reset: POR */
 #define I40E_PFPM_WUS_LNKC_SHIFT 0
-#define I40E_PFPM_WUS_LNKC_MASK (0x1 << I40E_PFPM_WUS_LNKC_SHIFT)
+#define I40E_PFPM_WUS_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUS_LNKC_SHIFT)
 #define I40E_PFPM_WUS_MAG_SHIFT 1
-#define I40E_PFPM_WUS_MAG_MASK (0x1 << I40E_PFPM_WUS_MAG_SHIFT)
+#define I40E_PFPM_WUS_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MAG_SHIFT)
 #define I40E_PFPM_WUS_PME_STATUS_SHIFT 2
-#define I40E_PFPM_WUS_PME_STATUS_MASK (0x1 << I40E_PFPM_WUS_PME_STATUS_SHIFT)
+#define I40E_PFPM_WUS_PME_STATUS_MASK I40E_MASK(0x1, I40E_PFPM_WUS_PME_STATUS_SHIFT)
 #define I40E_PFPM_WUS_MNG_SHIFT 3
-#define I40E_PFPM_WUS_MNG_MASK (0x1 << I40E_PFPM_WUS_MNG_SHIFT)
+#define I40E_PFPM_WUS_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MNG_SHIFT)
 #define I40E_PFPM_WUS_FLX0_SHIFT 16
-#define I40E_PFPM_WUS_FLX0_MASK (0x1 << I40E_PFPM_WUS_FLX0_SHIFT)
+#define I40E_PFPM_WUS_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX0_SHIFT)
 #define I40E_PFPM_WUS_FLX1_SHIFT 17
-#define I40E_PFPM_WUS_FLX1_MASK (0x1 << I40E_PFPM_WUS_FLX1_SHIFT)
+#define I40E_PFPM_WUS_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX1_SHIFT)
 #define I40E_PFPM_WUS_FLX2_SHIFT 18
-#define I40E_PFPM_WUS_FLX2_MASK (0x1 << I40E_PFPM_WUS_FLX2_SHIFT)
+#define I40E_PFPM_WUS_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX2_SHIFT)
 #define I40E_PFPM_WUS_FLX3_SHIFT 19
-#define I40E_PFPM_WUS_FLX3_MASK (0x1 << I40E_PFPM_WUS_FLX3_SHIFT)
+#define I40E_PFPM_WUS_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX3_SHIFT)
 #define I40E_PFPM_WUS_FLX4_SHIFT 20
-#define I40E_PFPM_WUS_FLX4_MASK (0x1 << I40E_PFPM_WUS_FLX4_SHIFT)
+#define I40E_PFPM_WUS_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX4_SHIFT)
 #define I40E_PFPM_WUS_FLX5_SHIFT 21
-#define I40E_PFPM_WUS_FLX5_MASK (0x1 << I40E_PFPM_WUS_FLX5_SHIFT)
+#define I40E_PFPM_WUS_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX5_SHIFT)
 #define I40E_PFPM_WUS_FLX6_SHIFT 22
-#define I40E_PFPM_WUS_FLX6_MASK (0x1 << I40E_PFPM_WUS_FLX6_SHIFT)
+#define I40E_PFPM_WUS_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX6_SHIFT)
 #define I40E_PFPM_WUS_FLX7_SHIFT 23
-#define I40E_PFPM_WUS_FLX7_MASK (0x1 << I40E_PFPM_WUS_FLX7_SHIFT)
+#define I40E_PFPM_WUS_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX7_SHIFT)
 #define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUS_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUS_FW_RST_WK_SHIFT)
-#define I40E_PRTPM_FHFHR 0x0006C000
+#define I40E_PFPM_WUS_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FW_RST_WK_SHIFT)
+#define I40E_PRTPM_FHFHR 0x0006C000 /* Reset: POR */
 #define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0
-#define I40E_PRTPM_FHFHR_UNICAST_MASK (0x1 << I40E_PRTPM_FHFHR_UNICAST_SHIFT)
+#define I40E_PRTPM_FHFHR_UNICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_UNICAST_SHIFT)
 #define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1
-#define I40E_PRTPM_FHFHR_MULTICAST_MASK (0x1 << I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
-#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_FHFHR_MULTICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
+#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
 #define I40E_PRTPM_SAH_MAX_INDEX 3
 #define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0
-#define I40E_PRTPM_SAH_PFPM_SAH_MASK (0xFFFF << I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
+#define I40E_PRTPM_SAH_PFPM_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
 #define I40E_PRTPM_SAH_PF_NUM_SHIFT 26
-#define I40E_PRTPM_SAH_PF_NUM_MASK (0xF << I40E_PRTPM_SAH_PF_NUM_SHIFT)
+#define I40E_PRTPM_SAH_PF_NUM_MASK I40E_MASK(0xF, I40E_PRTPM_SAH_PF_NUM_SHIFT)
 #define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30
-#define I40E_PRTPM_SAH_MC_MAG_EN_MASK (0x1 << I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
+#define I40E_PRTPM_SAH_MC_MAG_EN_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
 #define I40E_PRTPM_SAH_AV_SHIFT 31
-#define I40E_PRTPM_SAH_AV_MASK (0x1 << I40E_PRTPM_SAH_AV_SHIFT)
-#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAH_AV_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_AV_SHIFT)
+#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
 #define I40E_PRTPM_SAL_MAX_INDEX 3
 #define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0
-#define I40E_PRTPM_SAL_PFPM_SAL_MASK (0xFFFFFFFF << I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
-#define I40E_VF_ARQBAH1 0x00006000
+#define I40E_PRTPM_SAL_PFPM_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
+#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
 #define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH1_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH1_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL1 0x00006C00
+#define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
 #define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL1_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL1_ARQBAL_SHIFT)
-#define I40E_VF_ARQH1 0x00007400
+#define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT)
+#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
 #define I40E_VF_ARQH1_ARQH_SHIFT 0
-#define I40E_VF_ARQH1_ARQH_MASK (0x3FF << I40E_VF_ARQH1_ARQH_SHIFT)
-#define I40E_VF_ARQLEN1 0x00008000
+#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
 #define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN1_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN1_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT)
 #define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN1_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
 #define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN1_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
 #define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN1_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
 #define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN1_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT1 0x00007000
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
 #define I40E_VF_ARQT1_ARQT_SHIFT 0
-#define I40E_VF_ARQT1_ARQT_MASK (0x3FF << I40E_VF_ARQT1_ARQT_SHIFT)
-#define I40E_VF_ATQBAH1 0x00007800
+#define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT)
+#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
 #define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH1_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH1_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL1 0x00007C00
+#define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
 #define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL1_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL1_ATQBAL_SHIFT)
-#define I40E_VF_ATQH1 0x00006400
+#define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT)
+#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
 #define I40E_VF_ATQH1_ATQH_SHIFT 0
-#define I40E_VF_ATQH1_ATQH_MASK (0x3FF << I40E_VF_ATQH1_ATQH_SHIFT)
-#define I40E_VF_ATQLEN1 0x00006800
+#define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT)
+#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
 #define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN1_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN1_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT)
 #define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN1_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
 #define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN1_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
 #define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN1_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
 #define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN1_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT1 0x00008400
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
 #define I40E_VF_ATQT1_ATQT_SHIFT 0
-#define I40E_VF_ATQT1_ATQT_MASK (0x3FF << I40E_VF_ATQT1_ATQT_SHIFT)
-#define I40E_VFGEN_RSTAT 0x00008800
+#define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT)
+#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
 #define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
-#define I40E_VFINT_DYN_CTL01 0x00005C00
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
 #define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL01_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4))
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
 #define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
 #define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN1_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
 #define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0_ENA1 0x00005000
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
 #define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA1_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
-#define I40E_VFINT_ICR01 0x00004800
+#define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
+#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
 #define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR01_INTEVENT_MASK (0x1 << I40E_VFINT_ICR01_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR01_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR01_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR01_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT)
 #define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR01_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT)
 #define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
 #define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR01_ADMINQ_MASK (0x1 << I40E_VFINT_ICR01_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT)
 #define I40E_VFINT_ICR01_SWINT_SHIFT 31
-#define I40E_VFINT_ICR01_SWINT_MASK (0x1 << I40E_VFINT_ICR01_SWINT_SHIFT)
-#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */
+#define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT)
+#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */
 #define I40E_VFINT_ITR01_MAX_INDEX 2
 #define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR01_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR01_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4))
+#define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
 #define I40E_VFINT_ITRN1_MAX_INDEX 2
 #define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN1_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN1_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL01 0x00005400
+#define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: VFR */
 #define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
-#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_QRX_TAIL1_MAX_INDEX 15
 #define I40E_QRX_TAIL1_TAIL_SHIFT 0
-#define I40E_QRX_TAIL1_TAIL_MASK (0x1FFF << I40E_QRX_TAIL1_TAIL_SHIFT)
-#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT)
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
 #define I40E_QTX_TAIL1_MAX_INDEX 15
 #define I40E_QTX_TAIL1_TAIL_SHIFT 0
-#define I40E_QTX_TAIL1_TAIL_MASK (0x1FFF << I40E_QTX_TAIL1_TAIL_SHIFT)
-#define I40E_VFMSIX_PBA 0x00002000
+#define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT)
+#define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */
 #define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TADD_MAX_INDEX 16
 #define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
 #define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TMSG_MAX_INDEX 16
 #define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TUADD_MAX_INDEX 16
 #define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
 #define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
 #define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFCM_PE_ERRDATA 0x0000DC00
+#define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */
 #define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
 #define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO 0x0000D800
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */
 #define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
 #define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFPE_AEQALLOC1 0x0000A400
-#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH1 0x00009800
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW1 0x0000AC00
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1 0x0000B800
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK1 0x0000B000
-#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK1_PECQID_SHIFT)
-#define I40E_VFPE_CQARM1 0x0000B400
-#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM1_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB1 0x0000BC00
-#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB1_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES1 0x00009C00
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL1 0x0000A000
-#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG01 0x00008C00
-#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK1 0x00009000
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER1 0x0000A800
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC1 0x0000C000
-#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC1_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
 #define I40E_VFQF_HENA_MAX_INDEX 1
 #define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */
+#define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
 #define I40E_VFQF_HKEY_MAX_INDEX 12
 #define I40E_VFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY_KEY_0_MASK (0xFF << I40E_VFQF_HKEY_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT)
 #define I40E_VFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY_KEY_1_MASK (0xFF << I40E_VFQF_HKEY_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT)
 #define I40E_VFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY_KEY_2_MASK (0xFF << I40E_VFQF_HKEY_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT)
 #define I40E_VFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY_KEY_3_MASK (0xFF << I40E_VFQF_HKEY_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
 #define I40E_VFQF_HLUT_MAX_INDEX 15
 #define I40E_VFQF_HLUT_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT_LUT0_MASK (0xF << I40E_VFQF_HLUT_LUT0_SHIFT)
+#define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT)
 #define I40E_VFQF_HLUT_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT_LUT1_MASK (0xF << I40E_VFQF_HLUT_LUT1_SHIFT)
+#define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT)
 #define I40E_VFQF_HLUT_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT_LUT2_MASK (0xF << I40E_VFQF_HLUT_LUT2_SHIFT)
+#define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT)
 #define I40E_VFQF_HLUT_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT_LUT3_MASK (0xF << I40E_VFQF_HLUT_LUT3_SHIFT)
-#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */
+#define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT)
+#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */
 #define I40E_VFQF_HREGION_MAX_INDEX 7
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
 #define I40E_VFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION_REGION_0_MASK (0x7 << I40E_VFQF_HREGION_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
 #define I40E_VFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION_REGION_1_MASK (0x7 << I40E_VFQF_HREGION_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
 #define I40E_VFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION_REGION_2_MASK (0x7 << I40E_VFQF_HREGION_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
 #define I40E_VFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION_REGION_3_MASK (0x7 << I40E_VFQF_HREGION_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
 #define I40E_VFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION_REGION_4_MASK (0x7 << I40E_VFQF_HREGION_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
 #define I40E_VFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION_REGION_5_MASK (0x7 << I40E_VFQF_HREGION_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
 #define I40E_VFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION_REGION_6_MASK (0x7 << I40E_VFQF_HREGION_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
 #define I40E_VFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
+#define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT)
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,7 +50,11 @@ static void i40e_unmap_and_free_tx_resou
 					    struct i40e_tx_buffer *tx_buffer)
 {
 	if (tx_buffer->skb) {
-		dev_kfree_skb_any(tx_buffer->skb);
+		if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+			kfree(tx_buffer->raw_buf);
+		else
+			dev_kfree_skb_any(tx_buffer->skb);
+
 		if (dma_unmap_len(tx_buffer, len))
 			dma_unmap_single(ring->dev,
 					 dma_unmap_addr(tx_buffer, dma),
@@ -769,8 +773,6 @@ static inline void i40e_rx_checksum(stru
 
 	/* likely incorrect csum if alternate IP extension headers found */
 	if (ipv6 &&
-	    decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
-	    rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
 	    rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
 		/* don't increment checksum err here, non-fatal err */
 		return;
@@ -1336,6 +1338,7 @@ static void i40e_create_tx_ctx(struct i4
 	/* cpu_to_le32 and assign to struct fields */
 	context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
 	context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+	context_desc->rsvd = cpu_to_le16(0);
 	context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
 }
 
@@ -1594,7 +1597,7 @@ static netdev_tx_t i40e_xmit_frame_ring(
 		goto out_drop;
 
 	/* obtain protocol of skb */
-	protocol = skb->protocol;
+	protocol = vlan_get_protocol(skb);
 
 	/* record the location of the first descriptor for this packet */
 	first = &tx_ring->tx_bi[tx_ring->next_to_use];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
 	((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
-	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
 	((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
@@ -131,6 +130,7 @@ enum i40e_dyn_idx_t {
 #define I40E_TX_FLAGS_IPV6		(u32)(1 << 5)
 #define I40E_TX_FLAGS_FCCRC		(u32)(1 << 6)
 #define I40E_TX_FLAGS_FSO		(u32)(1 << 7)
+#define I40E_TX_FLAGS_FD_SB		(u32)(1 << 9)
 #define I40E_TX_FLAGS_VLAN_MASK		0xffff0000
 #define I40E_TX_FLAGS_VLAN_PRIO_MASK	0xe0000000
 #define I40E_TX_FLAGS_VLAN_PRIO_SHIFT	29
@@ -139,7 +139,10 @@ enum i40e_dyn_idx_t {
 struct i40e_tx_buffer {
 	struct i40e_tx_desc *next_to_watch;
 	unsigned long time_stamp;
-	struct sk_buff *skb;
+	union {
+		struct sk_buff *skb;
+		void *raw_buf;
+	};
 	unsigned int bytecount;
 	unsigned short gso_segs;
 	DEFINE_DMA_UNMAP_ADDR(dma);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,6 +50,9 @@
 					 (d) == I40E_DEV_ID_QSFP_B  || \
 					 (d) == I40E_DEV_ID_QSFP_C)
 
+/* I40E_MASK is a macro used on 32 bit registers */
+#define I40E_MASK(mask, shift) (mask << shift)
+
 #define I40E_MAX_VSI_QP			16
 #define I40E_MAX_VF_VSI			3
 #define I40E_MAX_CHAINED_RX_BUFFERS	5
@@ -137,6 +140,14 @@ enum i40e_fc_mode {
 	I40E_FC_DEFAULT
 };
 
+enum i40e_set_fc_aq_failures {
+	I40E_SET_FC_AQ_FAIL_NONE = 0,
+	I40E_SET_FC_AQ_FAIL_GET = 1,
+	I40E_SET_FC_AQ_FAIL_SET = 2,
+	I40E_SET_FC_AQ_FAIL_UPDATE = 4,
+	I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6
+};
+
 enum i40e_vsi_type {
 	I40E_VSI_MAIN = 0,
 	I40E_VSI_VMDQ1,
@@ -163,6 +174,7 @@ struct i40e_link_status {
 	u8 an_info;
 	u8 ext_info;
 	u8 loopback;
+	bool an_enabled;
 	/* is Link Status Event notification to SW enabled */
 	bool lse_enable;
 	u16 max_frame_size;
@@ -256,6 +268,61 @@ struct i40e_nvm_info {
 	u32 eetrack;              /* NVM data version */
 };
 
+/* definitions used in NVM update support */
+
+enum i40e_nvmupd_cmd {
+	I40E_NVMUPD_INVALID,
+	I40E_NVMUPD_READ_CON,
+	I40E_NVMUPD_READ_SNT,
+	I40E_NVMUPD_READ_LCB,
+	I40E_NVMUPD_READ_SA,
+	I40E_NVMUPD_WRITE_ERA,
+	I40E_NVMUPD_WRITE_CON,
+	I40E_NVMUPD_WRITE_SNT,
+	I40E_NVMUPD_WRITE_LCB,
+	I40E_NVMUPD_WRITE_SA,
+	I40E_NVMUPD_CSUM_CON,
+	I40E_NVMUPD_CSUM_SA,
+	I40E_NVMUPD_CSUM_LCB,
+};
+
+enum i40e_nvmupd_state {
+	I40E_NVMUPD_STATE_INIT,
+	I40E_NVMUPD_STATE_READING,
+	I40E_NVMUPD_STATE_WRITING
+};
+
+/* nvm_access definition and its masks/shifts need to be accessible to
+ * application, core driver, and shared code.  Where is the right file?
+ */
+#define I40E_NVM_READ	0xB
+#define I40E_NVM_WRITE	0xC
+
+#define I40E_NVM_MOD_PNT_MASK 0xFF
+
+#define I40E_NVM_TRANS_SHIFT	8
+#define I40E_NVM_TRANS_MASK	(0xf << I40E_NVM_TRANS_SHIFT)
+#define I40E_NVM_CON		0x0
+#define I40E_NVM_SNT		0x1
+#define I40E_NVM_LCB		0x2
+#define I40E_NVM_SA		(I40E_NVM_SNT | I40E_NVM_LCB)
+#define I40E_NVM_ERA		0x4
+#define I40E_NVM_CSUM		0x8
+
+#define I40E_NVM_ADAPT_SHIFT	16
+#define I40E_NVM_ADAPT_MASK	(0xffff << I40E_NVM_ADAPT_SHIFT)
+
+#define I40E_NVMUPD_MAX_DATA	4096
+#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
+
+struct i40e_nvm_access {
+	u32 command;
+	u32 config;
+	u32 offset;	/* in bytes */
+	u32 data_size;	/* in bytes */
+	u8 data[1];
+};
+
 /* PCI bus types */
 enum i40e_bus_type {
 	i40e_bus_type_unknown = 0,
@@ -391,6 +458,9 @@ struct i40e_hw {
 	/* Admin Queue info */
 	struct i40e_adminq_info aq;
 
+	/* state of nvm update process */
+	enum i40e_nvmupd_state nvmupd_state;
+
 	/* HMC info */
 	struct i40e_hmc_info hmc; /* HMC info struct */
 
@@ -875,7 +945,6 @@ enum i40e_filter_pctype {
 	I40E_FILTER_PCTYPE_FRAG_IPV4			= 36,
 	/* Note: Values 37-40 are reserved for future use */
 	I40E_FILTER_PCTYPE_NONF_IPV6_UDP		= 41,
-	I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN		= 42,
 	I40E_FILTER_PCTYPE_NONF_IPV6_TCP		= 43,
 	I40E_FILTER_PCTYPE_NONF_IPV6_SCTP		= 44,
 	I40E_FILTER_PCTYPE_NONF_IPV6_OTHER		= 45,
@@ -1162,4 +1231,7 @@ enum i40e_reset_type {
 	I40E_RESET_GLOBR	= 2,
 	I40E_RESET_EMPR		= 3,
 };
+
+/* RSS Hash Table Size */
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_512	0x00010000
 #endif /* _I40E_TYPE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,7 +193,7 @@ static void i40evf_set_msglevel(struct n
 }
 
 /**
- * i40evf_get_drvinto - Get driver info
+ * i40evf_get_drvinfo - Get driver info
  * @netdev: network interface device structure
  * @drvinfo: ethool driver info structure
  *
@@ -632,7 +632,7 @@ static int i40evf_get_rxfh(struct net_de
 	u32 hlut_val;
 	int i, j;
 
-	for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX; i++) {
+	for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
 		hlut_val = rd32(hw, I40E_VFQF_HLUT(i));
 		indir[j++] = hlut_val & 0xff;
 		indir[j++] = (hlut_val >> 8) & 0xff;
@@ -659,7 +659,7 @@ static int i40evf_set_rxfh(struct net_de
 	u32 hlut_val;
 	int i, j;
 
-	for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX + 1; i++) {
+	for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
 		hlut_val = indir[j++];
 		hlut_val |= indir[j++] << 8;
 		hlut_val |= indir[j++] << 16;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,9 +34,9 @@ static int i40evf_close(struct net_devic
 
 char i40evf_driver_name[] = "i40evf";
 static const char i40evf_driver_string[] =
-	"Intel(R) XL710 X710 Virtual Function Network Driver";
+	"Intel(R) XL710/X710 Virtual Function Network Driver";
 
-#define DRV_VERSION "0.9.34"
+#define DRV_VERSION "0.9.40"
 const char i40evf_driver_version[] = DRV_VERSION;
 static const char i40evf_copyright[] =
 	"Copyright (c) 2013 - 2014 Intel Corporation.";
@@ -49,7 +49,7 @@ static const char i40evf_copyright[] =
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(i40evf_pci_tbl) = {
+static const struct pci_device_id i40evf_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_VF), 0},
 	/* required last entry */
 	{0, }
@@ -260,6 +260,12 @@ static void i40evf_fire_sw_int(struct i4
 	int i;
 	uint32_t dyn_ctl;
 
+	if (mask & 1) {
+		dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTL01);
+		dyn_ctl |= I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK |
+			   I40E_VFINT_DYN_CTLN_CLEARPBA_MASK;
+		wr32(hw, I40E_VFINT_DYN_CTL01, dyn_ctl);
+	}
 	for (i = 1; i < adapter->num_msix_vectors; i++) {
 		if (mask & (1 << i)) {
 			dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTLN1(i - 1));
@@ -278,6 +284,7 @@ void i40evf_irq_enable(struct i40evf_ada
 {
 	struct i40e_hw *hw = &adapter->hw;
 
+	i40evf_misc_irq_enable(adapter);
 	i40evf_irq_enable_queues(adapter, ~0);
 
 	if (flush)
@@ -520,7 +527,8 @@ static int i40evf_request_misc_irq(struc
 	struct net_device *netdev = adapter->netdev;
 	int err;
 
-	sprintf(adapter->misc_vector_name, "i40evf:mbx");
+	snprintf(adapter->misc_vector_name,
+		 sizeof(adapter->misc_vector_name) - 1, "i40evf:mbx");
 	err = request_irq(adapter->msix_entries[0].vector,
 			  &i40evf_msix_aq, 0,
 			  adapter->misc_vector_name, netdev);
@@ -761,7 +769,7 @@ i40evf_mac_filter *i40evf_add_filter(str
 
 	while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
 				&adapter->crit_section))
-		mdelay(1);
+		udelay(1);
 
 	f = i40evf_find_filter(adapter, macaddr);
 	if (NULL == f) {
@@ -833,7 +841,7 @@ static void i40evf_set_rx_mode(struct ne
 
 	while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
 				&adapter->crit_section))
-		mdelay(1);
+		udelay(1);
 	/* remove filter if not in netdev list */
 	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
 		bool found = false;
@@ -1290,12 +1298,16 @@ static void i40evf_watchdog_task(struct
 					  struct i40evf_adapter,
 					  watchdog_task);
 	struct i40e_hw *hw = &adapter->hw;
+	uint32_t rstat_val;
 
 	if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
 		goto restart_watchdog;
 
 	if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
-		if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) {
+		rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+		if ((rstat_val == I40E_VFR_VFACTIVE) ||
+		    (rstat_val == I40E_VFR_COMPLETED)) {
 			/* A chance for redemption! */
 			dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
 			adapter->state = __I40EVF_STARTUP;
@@ -1321,8 +1333,11 @@ static void i40evf_watchdog_task(struct
 		goto watchdog_done;
 
 	/* check for reset */
+	rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
 	if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) &&
-	    (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) {
+	    (rstat_val != I40E_VFR_VFACTIVE) &&
+	    (rstat_val != I40E_VFR_COMPLETED)) {
 		adapter->state = __I40EVF_RESETTING;
 		adapter->flags |= I40EVF_FLAG_RESET_PENDING;
 		dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
@@ -1388,6 +1403,8 @@ static void i40evf_watchdog_task(struct
 watchdog_done:
 	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
 restart_watchdog:
+	if (adapter->state == __I40EVF_REMOVE)
+		return;
 	if (adapter->aq_required)
 		mod_timer(&adapter->watchdog_timer,
 			  jiffies + msecs_to_jiffies(20));
@@ -1488,7 +1505,8 @@ static void i40evf_reset_task(struct wor
 	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
 		rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
 			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
-		if (rstat_val != I40E_VFR_VFACTIVE)
+		if ((rstat_val != I40E_VFR_VFACTIVE) &&
+		    (rstat_val != I40E_VFR_COMPLETED))
 			break;
 		else
 			msleep(I40EVF_RESET_WAIT_MS);
@@ -1502,12 +1520,16 @@ static void i40evf_reset_task(struct wor
 	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
 		rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
 			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
-		if (rstat_val == I40E_VFR_VFACTIVE)
+		if ((rstat_val == I40E_VFR_VFACTIVE) ||
+		    (rstat_val == I40E_VFR_COMPLETED))
 			break;
 		else
 			msleep(I40EVF_RESET_WAIT_MS);
 	}
 	if (i == I40EVF_RESET_WAIT_COUNT) {
+		struct i40evf_mac_filter *f, *ftmp;
+		struct i40evf_vlan_filter *fv, *fvtmp;
+
 		/* reset never finished */
 		dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
 			rstat_val);
@@ -1520,9 +1542,23 @@ static void i40evf_reset_task(struct wor
 			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;
@@ -1939,8 +1975,10 @@ static int i40evf_check_reset_complete(s
 	int i;
 
 	for (i = 0; i < 100; i++) {
-		rstat = rd32(hw, I40E_VFGEN_RSTAT);
-		if (rstat == I40E_VFR_VFACTIVE)
+		rstat = rd32(hw, I40E_VFGEN_RSTAT) &
+			    I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+		if ((rstat == I40E_VFR_VFACTIVE) ||
+		    (rstat == I40E_VFR_COMPLETED))
 			return 0;
 		udelay(10);
 	}
@@ -2006,7 +2044,6 @@ static void i40evf_init_task(struct work
 		}
 		adapter->state = __I40EVF_INIT_VERSION_CHECK;
 		goto restart;
-		break;
 	case __I40EVF_INIT_VERSION_CHECK:
 		if (!i40evf_asq_done(hw)) {
 			dev_err(&pdev->dev, "Admin queue command never completed\n");
@@ -2018,17 +2055,20 @@ static void i40evf_init_task(struct work
 		if (err) {
 			dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n",
 				err);
+			if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
+				dev_info(&pdev->dev, "Resending request\n");
+				err = i40evf_send_api_ver(adapter);
+			}
 			goto err;
 		}
 		err = i40evf_send_vf_config_msg(adapter);
 		if (err) {
-			dev_err(&pdev->dev, "Unable send config request (%d)\n",
+			dev_err(&pdev->dev, "Unable to send config request (%d)\n",
 				err);
 			goto err;
 		}
 		adapter->state = __I40EVF_INIT_GET_RESOURCES;
 		goto restart;
-		break;
 	case __I40EVF_INIT_GET_RESOURCES:
 		/* aq msg sent, awaiting reply */
 		if (!adapter->vf_res) {
@@ -2097,8 +2137,6 @@ static void i40evf_init_task(struct work
 	ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
 	ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
 
-	INIT_LIST_HEAD(&adapter->mac_filter_list);
-	INIT_LIST_HEAD(&adapter->vlan_filter_list);
 	f = kzalloc(sizeof(*f), GFP_ATOMIC);
 	if (NULL == f)
 		goto err_sw_init;
@@ -2280,6 +2318,9 @@ static int i40evf_probe(struct pci_dev *
 	hw->bus.device = PCI_SLOT(pdev->devfn);
 	hw->bus.func = PCI_FUNC(pdev->devfn);
 
+	INIT_LIST_HEAD(&adapter->mac_filter_list);
+	INIT_LIST_HEAD(&adapter->vlan_filter_list);
+
 	INIT_WORK(&adapter->reset_task, i40evf_reset_task);
 	INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
 	INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
@@ -2391,6 +2432,7 @@ static void i40evf_remove(struct pci_dev
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
+	struct i40evf_mac_filter *f, *ftmp;
 	struct i40e_hw *hw = &adapter->hw;
 
 	cancel_delayed_work_sync(&adapter->init_task);
@@ -2406,9 +2448,12 @@ static void i40evf_remove(struct pci_dev
 		i40evf_misc_irq_disable(adapter);
 		i40evf_free_misc_irq(adapter);
 		i40evf_reset_interrupt_capability(adapter);
+		i40evf_free_q_vectors(adapter);
 	}
 
-	del_timer_sync(&adapter->watchdog_timer);
+	if (adapter->watchdog_timer.function)
+		del_timer_sync(&adapter->watchdog_timer);
+
 	flush_scheduled_work();
 
 	if (hw->aq.asq.count)
@@ -2419,6 +2464,13 @@ static void i40evf_remove(struct pci_dev
 
 	i40evf_free_queues(adapter);
 	kfree(adapter->vf_res);
+	/* If we got removed before an up/down sequence, we've got a filter
+	 * hanging out there that we need to get rid of.
+	 */
+	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+		list_del(&f->list);
+		kfree(f);
+	}
 
 	free_netdev(netdev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,8 +80,9 @@ int i40evf_send_api_ver(struct i40evf_ad
  * @adapter: adapter structure
  *
  * Compare API versions with the PF. Must be called after admin queue is
- * initialized. Returns 0 if API versions match, -EIO if
- * they do not, or I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty.
+ * initialized. Returns 0 if API versions match, -EIO if they do not,
+ * I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
+ * from the firmware are propagated.
  **/
 int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
 {
@@ -102,13 +103,13 @@ int i40evf_verify_api_ver(struct i40evf_
 		goto out_alloc;
 
 	err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
-	if (err) {
-		err = -EIO;
+	if (err)
 		goto out_alloc;
-	}
 
 	if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) !=
 	    I40E_VIRTCHNL_OP_VERSION) {
+		dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n",
+			 le32_to_cpu(event.desc.cookie_high));
 		err = -EIO;
 		goto out_alloc;
 	}
@@ -247,11 +248,11 @@ void i40evf_configure_queues(struct i40e
 		vqpi++;
 	}
 
+	adapter->aq_pending |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+	adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
 			   (u8 *)vqci, len);
 	kfree(vqci);
-	adapter->aq_pending |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
 }
 
 /**
@@ -274,10 +275,10 @@ void i40evf_enable_queues(struct i40evf_
 	vqs.vsi_id = adapter->vsi_res->vsi_id;
 	vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
 	vqs.rx_queues = vqs.tx_queues;
-	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
-			   (u8 *)&vqs, sizeof(vqs));
 	adapter->aq_pending |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
 	adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES;
+	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+			   (u8 *)&vqs, sizeof(vqs));
 }
 
 /**
@@ -300,10 +301,10 @@ void i40evf_disable_queues(struct i40evf
 	vqs.vsi_id = adapter->vsi_res->vsi_id;
 	vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
 	vqs.rx_queues = vqs.tx_queues;
-	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
-			   (u8 *)&vqs, sizeof(vqs));
 	adapter->aq_pending |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
 	adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES;
+	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+			   (u8 *)&vqs, sizeof(vqs));
 }
 
 /**
@@ -351,11 +352,11 @@ void i40evf_map_queues(struct i40evf_ada
 	vimi->vecmap[v_idx].txq_map = 0;
 	vimi->vecmap[v_idx].rxq_map = 0;
 
+	adapter->aq_pending |= I40EVF_FLAG_AQ_MAP_VECTORS;
+	adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
 			   (u8 *)vimi, len);
 	kfree(vimi);
-	adapter->aq_pending |= I40EVF_FLAG_AQ_MAP_VECTORS;
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
 }
 
 /**
@@ -412,12 +413,11 @@ void i40evf_add_ether_addrs(struct i40ev
 			f->add = false;
 		}
 	}
+	adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+	adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
 			   (u8 *)veal, len);
 	kfree(veal);
-	adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
-
 }
 
 /**
@@ -474,11 +474,11 @@ void i40evf_del_ether_addrs(struct i40ev
 			kfree(f);
 		}
 	}
+	adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+	adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
 			   (u8 *)veal, len);
 	kfree(veal);
-	adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
 }
 
 /**
@@ -535,10 +535,10 @@ void i40evf_add_vlans(struct i40evf_adap
 			f->add = false;
 		}
 	}
-	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
-	kfree(vvfl);
 	adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
 	adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
+	kfree(vvfl);
 }
 
 /**
@@ -596,10 +596,10 @@ void i40evf_del_vlans(struct i40evf_adap
 			kfree(f);
 		}
 	}
-	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
-	kfree(vvfl);
 	adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
 	adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
+	kfree(vvfl);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/e1000_82575.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/e1000_82575.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/e1000_82575.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/e1000_82575.c	2014-09-28 17:29:07.000000000 -0400
@@ -579,7 +579,6 @@ static s32 igb_get_invariants_82575(stru
 		break;
 	default:
 		return -E1000_ERR_MAC_INIT;
-		break;
 	}
 
 	/* Set media type */
@@ -837,7 +836,6 @@ static s32 igb_get_phy_id_82575(struct e
 		default:
 			ret_val = -E1000_ERR_PHY;
 			goto out;
-			break;
 		}
 		ret_val = igb_get_phy_id(hw);
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/e1000_regs.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/e1000_regs.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/e1000_regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/e1000_regs.h	2014-09-28 17:29:07.000000000 -0400
@@ -355,6 +355,7 @@
 #define E1000_UTA       0x0A000 /* Unicast Table Array - RW */
 #define E1000_IOVTCL    0x05BBC /* IOV Control Register */
 #define E1000_TXSWC     0x05ACC /* Tx Switch Control */
+#define E1000_LVMMC	0x03548 /* Last VM Misbehavior cause */
 /* These act per VF so an array friendly macro is used */
 #define E1000_P2VMAILBOX(_n)   (0x00C00 + (4 * (_n)))
 #define E1000_VMBMEM(_n)       (0x00800 + (64 * (_n)))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/igb_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/igb_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/igb/igb_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igb/igb_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,8 +57,8 @@
 #include "igb.h"
 
 #define MAJ 5
-#define MIN 0
-#define BUILD 5
+#define MIN 2
+#define BUILD 13
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
 __stringify(BUILD) "-k"
 char igb_driver_name[] = "igb";
@@ -1630,6 +1630,8 @@ void igb_power_up_link(struct igb_adapte
 		igb_power_up_phy_copper(&adapter->hw);
 	else
 		igb_power_up_serdes_link_82575(&adapter->hw);
+
+	igb_setup_link(&adapter->hw);
 }
 
 /**
@@ -4165,6 +4167,26 @@ static bool igb_thermal_sensor_event(str
 }
 
 /**
+ *  igb_check_lvmmc - check for malformed packets received
+ *  and indicated in LVMMC register
+ *  @adapter: pointer to adapter
+ **/
+static void igb_check_lvmmc(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 lvmmc;
+
+	lvmmc = rd32(E1000_LVMMC);
+	if (lvmmc) {
+		if (unlikely(net_ratelimit())) {
+			netdev_warn(adapter->netdev,
+				    "malformed Tx packet detected and dropped, LVMMC:0x%08x\n",
+				    lvmmc);
+		}
+	}
+}
+
+/**
  *  igb_watchdog - Timer Call-back
  *  @data: pointer to adapter cast into an unsigned long
  **/
@@ -4359,6 +4381,11 @@ static void igb_watchdog_task(struct wor
 	igb_spoof_check(adapter);
 	igb_ptp_rx_hang(adapter);
 
+	/* Check LVMMC register on i350/i354 only */
+	if ((adapter->hw.mac.type == e1000_i350) ||
+	    (adapter->hw.mac.type == e1000_i354))
+		igb_check_lvmmc(adapter);
+
 	/* Reset the timer */
 	if (!test_bit(__IGB_DOWN, &adapter->state)) {
 		if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/igbvf/netdev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igbvf/netdev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/igbvf/netdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/igbvf/netdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -2853,7 +2853,7 @@ static const struct pci_error_handlers i
 	.resume = igbvf_io_resume,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = {
+static const struct pci_device_id igbvf_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_VF), board_i350_vf },
 	{ } /* terminate list */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@ MODULE_PARM_DESC(copybreak,
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(ixgb_pci_tbl) = {
+static const struct pci_device_id ixgb_pci_tbl[] = {
 	{PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX_CX4,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c	2014-09-28 17:29:07.000000000 -0400
@@ -122,7 +122,7 @@ static s32 ixgbe_init_phy_ops_82598(stru
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
 	struct ixgbe_phy_info *phy = &hw->phy;
-	s32 ret_val = 0;
+	s32 ret_val;
 	u16 list_offset, data_offset;
 
 	/* Identify the PHY */
@@ -147,28 +147,23 @@ static s32 ixgbe_init_phy_ops_82598(stru
 
 		/* Call SFP+ identify routine to get the SFP+ module type */
 		ret_val = phy->ops.identify_sfp(hw);
-		if (ret_val != 0)
-			goto out;
-		else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
-			ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
-			goto out;
-		}
+		if (ret_val)
+			return ret_val;
+		if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
+			return IXGBE_ERR_SFP_NOT_SUPPORTED;
 
 		/* Check to see if SFP+ module is supported */
 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
 							    &list_offset,
 							    &data_offset);
-		if (ret_val != 0) {
-			ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
-			goto out;
-		}
+		if (ret_val)
+			return IXGBE_ERR_SFP_NOT_SUPPORTED;
 		break;
 	default:
 		break;
 	}
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -183,7 +178,7 @@ static s32 ixgbe_start_hw_82598(struct i
 {
 	u32 regval;
 	u32 i;
-	s32 ret_val = 0;
+	s32 ret_val;
 
 	ret_val = ixgbe_start_hw_generic(hw);
 
@@ -203,11 +198,13 @@ static s32 ixgbe_start_hw_82598(struct i
 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
 	}
 
+	if (ret_val)
+		return ret_val;
+
 	/* set the completion timeout for interface */
-	if (ret_val == 0)
-		ixgbe_set_pcie_completion_timeout(hw);
+	ixgbe_set_pcie_completion_timeout(hw);
 
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -222,7 +219,6 @@ static s32 ixgbe_get_link_capabilities_8
 					     ixgbe_link_speed *speed,
 					     bool *autoneg)
 {
-	s32 status = 0;
 	u32 autoc = 0;
 
 	/*
@@ -262,11 +258,10 @@ static s32 ixgbe_get_link_capabilities_8
 		break;
 
 	default:
-		status = IXGBE_ERR_LINK_SETUP;
-		break;
+		return IXGBE_ERR_LINK_SETUP;
 	}
 
-	return status;
+	return 0;
 }
 
 /**
@@ -277,14 +272,12 @@ static s32 ixgbe_get_link_capabilities_8
  **/
 static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
 {
-	enum ixgbe_media_type media_type;
-
 	/* Detect if there is a copper PHY attached. */
 	switch (hw->phy.type) {
 	case ixgbe_phy_cu_unknown:
 	case ixgbe_phy_tn:
-		media_type = ixgbe_media_type_copper;
-		goto out;
+		return ixgbe_media_type_copper;
+
 	default:
 		break;
 	}
@@ -294,30 +287,27 @@ static enum ixgbe_media_type ixgbe_get_m
 	case IXGBE_DEV_ID_82598:
 	case IXGBE_DEV_ID_82598_BX:
 		/* Default device ID is mezzanine card KX/KX4 */
-		media_type = ixgbe_media_type_backplane;
-		break;
+		return ixgbe_media_type_backplane;
+
 	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
 	case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
 	case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
 	case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
 	case IXGBE_DEV_ID_82598EB_XF_LR:
 	case IXGBE_DEV_ID_82598EB_SFP_LOM:
-		media_type = ixgbe_media_type_fiber;
-		break;
+		return ixgbe_media_type_fiber;
+
 	case IXGBE_DEV_ID_82598EB_CX4:
 	case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
-		media_type = ixgbe_media_type_cx4;
-		break;
+		return ixgbe_media_type_cx4;
+
 	case IXGBE_DEV_ID_82598AT:
 	case IXGBE_DEV_ID_82598AT2:
-		media_type = ixgbe_media_type_copper;
-		break;
+		return ixgbe_media_type_copper;
+
 	default:
-		media_type = ixgbe_media_type_unknown;
-		break;
+		return ixgbe_media_type_unknown;
 	}
-out:
-	return media_type;
 }
 
 /**
@@ -328,7 +318,6 @@ out:
  **/
 static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
 	u32 fctrl_reg;
 	u32 rmcs_reg;
 	u32 reg;
@@ -338,10 +327,8 @@ static s32 ixgbe_fc_enable_82598(struct
 	bool link_up;
 
 	/* Validate the water mark configuration */
-	if (!hw->fc.pause_time) {
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
-	}
+	if (!hw->fc.pause_time)
+		return IXGBE_ERR_INVALID_LINK_SETTINGS;
 
 	/* Low water mark of zero causes XOFF floods */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -350,8 +337,7 @@ static s32 ixgbe_fc_enable_82598(struct
 			if (!hw->fc.low_water[i] ||
 			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
 				hw_dbg(hw, "Invalid water mark configuration\n");
-				ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-				goto out;
+				return IXGBE_ERR_INVALID_LINK_SETTINGS;
 			}
 		}
 	}
@@ -428,9 +414,7 @@ static s32 ixgbe_fc_enable_82598(struct
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = IXGBE_ERR_CONFIG;
-		goto out;
-		break;
+		return IXGBE_ERR_CONFIG;
 	}
 
 	/* Set 802.3x based flow control settings. */
@@ -461,8 +445,7 @@ static s32 ixgbe_fc_enable_82598(struct
 	/* Configure flow control refresh threshold value */
 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -598,7 +581,7 @@ static s32 ixgbe_check_mac_link_82598(st
 		}
 
 		if (!*link_up)
-			goto out;
+			return 0;
 	}
 
 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
@@ -629,7 +612,6 @@ static s32 ixgbe_check_mac_link_82598(st
 	    (ixgbe_validate_link_ready(hw) != 0))
 		*link_up = false;
 
-out:
 	return 0;
 }
 
@@ -646,7 +628,6 @@ static s32 ixgbe_setup_mac_link_82598(st
 				      bool autoneg_wait_to_complete)
 {
 	bool		 autoneg	   = false;
-	s32              status            = 0;
 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
 	u32              curr_autoc        = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32              autoc             = curr_autoc;
@@ -657,7 +638,7 @@ static s32 ixgbe_setup_mac_link_82598(st
 	speed &= link_capabilities;
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
-		status = IXGBE_ERR_LINK_SETUP;
+		return IXGBE_ERR_LINK_SETUP;
 
 	/* Set KX4/KX support according to speed requested */
 	else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
@@ -671,17 +652,11 @@ static s32 ixgbe_setup_mac_link_82598(st
 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
 	}
 
-	if (status == 0) {
-		/*
-		 * Setup and restart the link based on the new values in
-		 * ixgbe_hw This will write the AUTOC register based on the new
-		 * stored values
-		 */
-		status = ixgbe_start_mac_link_82598(hw,
-						    autoneg_wait_to_complete);
-	}
-
-	return status;
+	/* Setup and restart the link based on the new values in
+	 * ixgbe_hw This will write the AUTOC register based on the new
+	 * stored values
+	 */
+	return ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
 }
 
 
@@ -718,7 +693,7 @@ static s32 ixgbe_setup_copper_link_82598
  **/
 static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
+	s32 status;
 	s32 phy_status = 0;
 	u32 ctrl;
 	u32 gheccr;
@@ -728,8 +703,8 @@ static s32 ixgbe_reset_hw_82598(struct i
 
 	/* Call adapter stop to disable tx/rx and clear interrupts */
 	status = hw->mac.ops.stop_adapter(hw);
-	if (status != 0)
-		goto reset_hw_out;
+	if (status)
+		return status;
 
 	/*
 	 * Power up the Atlas Tx lanes if they are currently powered down.
@@ -771,7 +746,7 @@ static s32 ixgbe_reset_hw_82598(struct i
 		/* Init PHY and function pointers, perform SFP setup */
 		phy_status = hw->phy.ops.init(hw);
 		if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-			goto reset_hw_out;
+			return phy_status;
 		if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
 			goto mac_reset_top;
 
@@ -837,7 +812,6 @@ mac_reset_top:
 	 */
 	hw->mac.ops.init_rx_addrs(hw);
 
-reset_hw_out:
 	if (phy_status)
 		status = phy_status;
 
@@ -1110,106 +1084,6 @@ static s32 ixgbe_read_i2c_sff8472_82598(
 }
 
 /**
- *  ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
- *  @hw: pointer to hardware structure
- *
- *  Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
-{
-	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
-	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
-	u16 ext_ability = 0;
-
-	hw->phy.ops.identify(hw);
-
-	/* Copper PHY must be checked before AUTOC LMS to determine correct
-	 * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
-	switch (hw->phy.type) {
-	case ixgbe_phy_tn:
-	case ixgbe_phy_cu_unknown:
-		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE,
-		MDIO_MMD_PMAPMD, &ext_ability);
-		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
-		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
-		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
-		goto out;
-	default:
-		break;
-	}
-
-	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
-	case IXGBE_AUTOC_LMS_1G_AN:
-	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
-		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX)
-			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
-		else
-			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
-		break;
-	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
-		if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
-		else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
-		else /* XAUI */
-			physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-		break;
-	case IXGBE_AUTOC_LMS_KX4_AN:
-	case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
-		if (autoc & IXGBE_AUTOC_KX_SUPP)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
-		if (autoc & IXGBE_AUTOC_KX4_SUPP)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
-		break;
-	default:
-		break;
-	}
-
-	if (hw->phy.type == ixgbe_phy_nl) {
-		hw->phy.ops.identify_sfp(hw);
-
-		switch (hw->phy.sfp_type) {
-		case ixgbe_sfp_type_da_cu:
-			physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-			break;
-		case ixgbe_sfp_type_sr:
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-			break;
-		case ixgbe_sfp_type_lr:
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-			break;
-		default:
-			physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-			break;
-		}
-	}
-
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
-		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-		break;
-	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
-	case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
-	case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
-		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-		break;
-	case IXGBE_DEV_ID_82598EB_XF_LR:
-		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-		break;
-	default:
-		break;
-	}
-
-out:
-	return physical_layer;
-}
-
-/**
  *  ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple
  *  port devices.
  *  @hw: pointer to the HW structure
@@ -1286,7 +1160,6 @@ static struct ixgbe_mac_operations mac_o
 	.start_hw		= &ixgbe_start_hw_82598,
 	.clear_hw_cntrs		= &ixgbe_clear_hw_cntrs_generic,
 	.get_media_type		= &ixgbe_get_media_type_82598,
-	.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
 	.enable_rx_dma          = &ixgbe_enable_rx_dma_generic,
 	.get_mac_addr		= &ixgbe_get_mac_addr_generic,
 	.stop_adapter		= &ixgbe_stop_adapter_generic,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,7 +123,7 @@ static void ixgbe_init_mac_link_ops_8259
 
 static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
+	s32 ret_val;
 	u16 list_offset, data_offset, data_value;
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
@@ -133,16 +133,14 @@ static s32 ixgbe_setup_sfp_modules_82599
 
 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
 							      &data_offset);
-		if (ret_val != 0)
-			goto setup_sfp_out;
+		if (ret_val)
+			return ret_val;
 
 		/* PHY config will finish before releasing the semaphore */
 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
 							IXGBE_GSSR_MAC_CSR_SM);
-		if (ret_val != 0) {
-			ret_val = IXGBE_ERR_SWFW_SYNC;
-			goto setup_sfp_out;
-		}
+		if (ret_val)
+			return IXGBE_ERR_SWFW_SYNC;
 
 		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
 			goto setup_sfp_err;
@@ -169,13 +167,11 @@ static s32 ixgbe_setup_sfp_modules_82599
 
 		if (ret_val) {
 			hw_dbg(hw, " sfp module setup not complete\n");
-			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
-			goto setup_sfp_out;
+			return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
 		}
 	}
 
-setup_sfp_out:
-	return ret_val;
+	return 0;
 
 setup_sfp_err:
 	/* Release the semaphore */
@@ -294,7 +290,7 @@ static s32 ixgbe_init_phy_ops_82599(stru
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
 	struct ixgbe_phy_info *phy = &hw->phy;
-	s32 ret_val = 0;
+	s32 ret_val;
 	u32 esdp;
 
 	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
@@ -355,7 +351,6 @@ static s32 ixgbe_get_link_capabilities_8
 					     ixgbe_link_speed *speed,
 					     bool *autoneg)
 {
-	s32 status = 0;
 	u32 autoc = 0;
 
 	/* Determine 1G link capabilities off of SFP+ type */
@@ -367,7 +362,7 @@ static s32 ixgbe_get_link_capabilities_8
 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
 		*autoneg = true;
-		goto out;
+		return 0;
 	}
 
 	/*
@@ -430,9 +425,7 @@ static s32 ixgbe_get_link_capabilities_8
 		break;
 
 	default:
-		status = IXGBE_ERR_LINK_SETUP;
-		goto out;
-		break;
+		return IXGBE_ERR_LINK_SETUP;
 	}
 
 	if (hw->phy.multispeed_fiber) {
@@ -446,8 +439,7 @@ static s32 ixgbe_get_link_capabilities_8
 			*autoneg = true;
 	}
 
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -458,14 +450,12 @@ out:
  **/
 static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
 {
-	enum ixgbe_media_type media_type;
-
 	/* Detect if there is a copper PHY attached. */
 	switch (hw->phy.type) {
 	case ixgbe_phy_cu_unknown:
 	case ixgbe_phy_tn:
-		media_type = ixgbe_media_type_copper;
-		goto out;
+		return ixgbe_media_type_copper;
+
 	default:
 		break;
 	}
@@ -478,34 +468,31 @@ static enum ixgbe_media_type ixgbe_get_m
 	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
 	case IXGBE_DEV_ID_82599_XAUI_LOM:
 		/* Default device ID is mezzanine card KX/KX4 */
-		media_type = ixgbe_media_type_backplane;
-		break;
+		return ixgbe_media_type_backplane;
+
 	case IXGBE_DEV_ID_82599_SFP:
 	case IXGBE_DEV_ID_82599_SFP_FCOE:
 	case IXGBE_DEV_ID_82599_SFP_EM:
 	case IXGBE_DEV_ID_82599_SFP_SF2:
 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
 	case IXGBE_DEV_ID_82599EN_SFP:
-		media_type = ixgbe_media_type_fiber;
-		break;
+		return ixgbe_media_type_fiber;
+
 	case IXGBE_DEV_ID_82599_CX4:
-		media_type = ixgbe_media_type_cx4;
-		break;
+		return ixgbe_media_type_cx4;
+
 	case IXGBE_DEV_ID_82599_T3_LOM:
-		media_type = ixgbe_media_type_copper;
-		break;
+		return ixgbe_media_type_copper;
+
 	case IXGBE_DEV_ID_82599_LS:
-		media_type = ixgbe_media_type_fiber_lco;
-		break;
+		return ixgbe_media_type_fiber_lco;
+
 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
-		media_type = ixgbe_media_type_fiber_qsfp;
-		break;
+		return ixgbe_media_type_fiber_qsfp;
+
 	default:
-		media_type = ixgbe_media_type_unknown;
-		break;
+		return ixgbe_media_type_unknown;
 	}
-out:
-	return media_type;
 }
 
 /**
@@ -555,7 +542,7 @@ static s32 ixgbe_start_mac_link_82599(st
 		status = hw->mac.ops.acquire_swfw_sync(hw,
 						IXGBE_GSSR_MAC_CSR_SM);
 		if (status)
-			goto out;
+			return status;
 
 		got_lock = true;
 	}
@@ -592,7 +579,6 @@ static s32 ixgbe_start_mac_link_82599(st
 	/* Add delay to filter out noises during initial link setup */
 	msleep(50);
 
-out:
 	return status;
 }
 
@@ -959,7 +945,7 @@ static s32 ixgbe_setup_mac_link_82599(st
 				      bool autoneg_wait_to_complete)
 {
 	bool autoneg = false;
-	s32 status = 0;
+	s32 status;
 	u32 pma_pmd_1g, link_mode, links_reg, i;
 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
@@ -975,15 +961,13 @@ static s32 ixgbe_setup_mac_link_82599(st
 	/* Check to see if speed passed in is supported. */
 	status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
 						   &autoneg);
-	if (status != 0)
-		goto out;
+	if (status)
+		return status;
 
 	speed &= link_capabilities;
 
-	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
-		status = IXGBE_ERR_LINK_SETUP;
-		goto out;
-	}
+	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
+		return IXGBE_ERR_LINK_SETUP;
 
 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
 	if (hw->mac.orig_link_settings_stored)
@@ -1034,7 +1018,7 @@ static s32 ixgbe_setup_mac_link_82599(st
 		/* Restart link */
 		status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
 		if (status)
-			goto out;
+			return status;
 
 		/* Only poll for autoneg to complete if specified to do so */
 		if (autoneg_wait_to_complete) {
@@ -1061,7 +1045,6 @@ static s32 ixgbe_setup_mac_link_82599(st
 		msleep(50);
 	}
 
-out:
 	return status;
 }
 
@@ -1106,8 +1089,8 @@ static s32 ixgbe_reset_hw_82599(struct i
 
 	/* Call adapter stop to disable tx/rx and clear interrupts */
 	status = hw->mac.ops.stop_adapter(hw);
-	if (status != 0)
-		goto reset_hw_out;
+	if (status)
+		return status;
 
 	/* flush pending Tx transactions */
 	ixgbe_clear_tx_pending(hw);
@@ -1118,7 +1101,7 @@ static s32 ixgbe_reset_hw_82599(struct i
 	status = hw->phy.ops.init(hw);
 
 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-		goto reset_hw_out;
+		return status;
 
 	/* Setup SFP module if there is one present. */
 	if (hw->phy.sfp_setup_needed) {
@@ -1127,7 +1110,7 @@ static s32 ixgbe_reset_hw_82599(struct i
 	}
 
 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-		goto reset_hw_out;
+		return status;
 
 	/* Reset PHY */
 	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
@@ -1217,7 +1200,7 @@ mac_reset_top:
 							hw->mac.orig_autoc,
 							false);
 			if (status)
-				goto reset_hw_out;
+				return status;
 		}
 
 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
@@ -1259,7 +1242,6 @@ mac_reset_top:
 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
 				       &hw->mac.wwpn_prefix);
 
-reset_hw_out:
 	return status;
 }
 
@@ -1928,20 +1910,20 @@ static s32 ixgbe_start_hw_82599(struct i
 	s32 ret_val = 0;
 
 	ret_val = ixgbe_start_hw_generic(hw);
-	if (ret_val != 0)
-		goto out;
+	if (ret_val)
+		return ret_val;
 
 	ret_val = ixgbe_start_hw_gen2(hw);
-	if (ret_val != 0)
-		goto out;
+	if (ret_val)
+		return ret_val;
 
 	/* We need to run link autotry after the driver loads */
 	hw->mac.autotry_restart = true;
 
-	if (ret_val == 0)
-		ret_val = ixgbe_verify_fw_version_82599(hw);
-out:
-	return ret_val;
+	if (ret_val)
+		return ret_val;
+
+	return ixgbe_verify_fw_version_82599(hw);
 }
 
 /**
@@ -1954,16 +1936,15 @@ out:
  **/
 static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+	s32 status;
 
 	/* Detect PHY if not unknown - returns success if already detected. */
 	status = ixgbe_identify_phy_generic(hw);
-	if (status != 0) {
+	if (status) {
 		/* 82599 10GBASE-T requires an external PHY */
 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
-			goto out;
-		else
-			status = ixgbe_identify_module_generic(hw);
+			return status;
+		status = ixgbe_identify_module_generic(hw);
 	}
 
 	/* Set PHY type none if no PHY detected */
@@ -1974,142 +1955,12 @@ static s32 ixgbe_identify_phy_82599(stru
 
 	/* Return error if SFP module has been detected but is not supported */
 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
-		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return IXGBE_ERR_SFP_NOT_SUPPORTED;
 
-out:
 	return status;
 }
 
 /**
- *  ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
- *  @hw: pointer to hardware structure
- *
- *  Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
-{
-	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
-	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
-	u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
-	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
-	u16 ext_ability = 0;
-	u8 comp_codes_10g = 0;
-	u8 comp_codes_1g = 0;
-
-	hw->phy.ops.identify(hw);
-
-	switch (hw->phy.type) {
-	case ixgbe_phy_tn:
-	case ixgbe_phy_cu_unknown:
-		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
-							 &ext_ability);
-		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
-		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
-		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
-		goto out;
-	default:
-		break;
-	}
-
-	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
-	case IXGBE_AUTOC_LMS_1G_AN:
-	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
-		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
-			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
-			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
-			goto out;
-		} else
-			/* SFI mode so read SFP module */
-			goto sfp_check;
-		break;
-	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
-		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
-		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
-		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
-		goto out;
-		break;
-	case IXGBE_AUTOC_LMS_10G_SERIAL:
-		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
-			goto out;
-		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
-			goto sfp_check;
-		break;
-	case IXGBE_AUTOC_LMS_KX4_KX_KR:
-	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
-		if (autoc & IXGBE_AUTOC_KX_SUPP)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
-		if (autoc & IXGBE_AUTOC_KX4_SUPP)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
-		if (autoc & IXGBE_AUTOC_KR_SUPP)
-			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
-		goto out;
-		break;
-	default:
-		goto out;
-		break;
-	}
-
-sfp_check:
-	/* SFP check must be done last since DA modules are sometimes used to
-	 * test KR mode -  we need to id KR mode correctly before SFP module.
-	 * Call identify_sfp because the pluggable module may have changed */
-	hw->phy.ops.identify_sfp(hw);
-	if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
-		goto out;
-
-	switch (hw->phy.type) {
-	case ixgbe_phy_sfp_passive_tyco:
-	case ixgbe_phy_sfp_passive_unknown:
-	case ixgbe_phy_qsfp_passive_unknown:
-		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-		break;
-	case ixgbe_phy_sfp_ftl_active:
-	case ixgbe_phy_sfp_active_unknown:
-	case ixgbe_phy_qsfp_active_unknown:
-		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
-		break;
-	case ixgbe_phy_sfp_avago:
-	case ixgbe_phy_sfp_ftl:
-	case ixgbe_phy_sfp_intel:
-	case ixgbe_phy_sfp_unknown:
-		hw->phy.ops.read_i2c_eeprom(hw,
-		      IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
-		hw->phy.ops.read_i2c_eeprom(hw,
-		      IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
-		if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-		else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
-			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
-		break;
-	case ixgbe_phy_qsfp_intel:
-	case ixgbe_phy_qsfp_unknown:
-		hw->phy.ops.read_i2c_eeprom(hw,
-			IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
-		if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-		break;
-	default:
-		break;
-	}
-
-out:
-	return physical_layer;
-}
-
-/**
  *  ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
  *  @hw: pointer to hardware structure
  *  @regval: register value to write to RXCTRL
@@ -2151,26 +2002,24 @@ static s32 ixgbe_verify_fw_version_82599
 	u16 fw_version = 0;
 
 	/* firmware check is only necessary for SFI devices */
-	if (hw->phy.media_type != ixgbe_media_type_fiber) {
-		status = 0;
-		goto fw_version_out;
-	}
+	if (hw->phy.media_type != ixgbe_media_type_fiber)
+		return 0;
 
 	/* get the offset to the Firmware Module block */
 	offset = IXGBE_FW_PTR;
 	if (hw->eeprom.ops.read(hw, offset, &fw_offset))
 		goto fw_version_err;
 
-	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
-		goto fw_version_out;
+	if (fw_offset == 0 || fw_offset == 0xFFFF)
+		return IXGBE_ERR_EEPROM_VERSION;
 
 	/* get the offset to the Pass Through Patch Configuration block */
 	offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR;
 	if (hw->eeprom.ops.read(hw, offset, &fw_ptp_cfg_offset))
 		goto fw_version_err;
 
-	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
-		goto fw_version_out;
+	if (fw_ptp_cfg_offset == 0 || fw_ptp_cfg_offset == 0xFFFF)
+		return IXGBE_ERR_EEPROM_VERSION;
 
 	/* get the firmware version */
 	offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4;
@@ -2180,7 +2029,6 @@ static s32 ixgbe_verify_fw_version_82599
 	if (fw_version > 0x5)
 		status = 0;
 
-fw_version_out:
 	return status;
 
 fw_version_err:
@@ -2197,37 +2045,33 @@ fw_version_err:
  **/
 static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
 {
-	bool lesm_enabled = false;
 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
 	s32 status;
 
 	/* get the offset to the Firmware Module block */
 	status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
 
-	if ((status != 0) ||
-	    (fw_offset == 0) || (fw_offset == 0xFFFF))
-		goto out;
+	if (status || fw_offset == 0 || fw_offset == 0xFFFF)
+		return false;
 
 	/* get the offset to the LESM Parameters block */
 	status = hw->eeprom.ops.read(hw, (fw_offset +
 				     IXGBE_FW_LESM_PARAMETERS_PTR),
 				     &fw_lesm_param_offset);
 
-	if ((status != 0) ||
-	    (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
-		goto out;
+	if (status ||
+	    fw_lesm_param_offset == 0 || fw_lesm_param_offset == 0xFFFF)
+		return false;
 
 	/* get the lesm state word */
 	status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
 				     IXGBE_FW_LESM_STATE_1),
 				     &fw_lesm_state);
 
-	if ((status == 0) &&
-	    (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
-		lesm_enabled = true;
+	if (!status && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
+		return true;
 
-out:
-	return lesm_enabled;
+	return false;
 }
 
 /**
@@ -2245,22 +2089,16 @@ static s32 ixgbe_read_eeprom_buffer_8259
 					  u16 words, u16 *data)
 {
 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
-	s32 ret_val = IXGBE_ERR_CONFIG;
 
-	/*
-	 * If EEPROM is detected and can be addressed using 14 bits,
+	/* If EEPROM is detected and can be addressed using 14 bits,
 	 * use EERD otherwise use bit bang
 	 */
-	if ((eeprom->type == ixgbe_eeprom_spi) &&
-	    (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR))
-		ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words,
-							 data);
-	else
-		ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset,
-								    words,
-								    data);
+	if (eeprom->type == ixgbe_eeprom_spi &&
+	    offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)
+		return ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
 
-	return ret_val;
+	return ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words,
+							 data);
 }
 
 /**
@@ -2277,19 +2115,15 @@ static s32 ixgbe_read_eeprom_82599(struc
 				   u16 offset, u16 *data)
 {
 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
-	s32 ret_val = IXGBE_ERR_CONFIG;
 
 	/*
 	 * If EEPROM is detected and can be addressed using 14 bits,
 	 * use EERD otherwise use bit bang
 	 */
-	if ((eeprom->type == ixgbe_eeprom_spi) &&
-	    (offset <= IXGBE_EERD_MAX_ADDR))
-		ret_val = ixgbe_read_eerd_generic(hw, offset, data);
-	else
-		ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
+	if (eeprom->type == ixgbe_eeprom_spi && offset <= IXGBE_EERD_MAX_ADDR)
+		return ixgbe_read_eerd_generic(hw, offset, data);
 
-	return ret_val;
+	return ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
 }
 
 /**
@@ -2458,7 +2292,6 @@ static struct ixgbe_mac_operations mac_o
 	.start_hw               = &ixgbe_start_hw_82599,
 	.clear_hw_cntrs         = &ixgbe_clear_hw_cntrs_generic,
 	.get_media_type         = &ixgbe_get_media_type_82599,
-	.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599,
 	.enable_rx_dma          = &ixgbe_enable_rx_dma_82599,
 	.disable_rx_buff	= &ixgbe_disable_rx_buff_generic,
 	.enable_rx_buff		= &ixgbe_enable_rx_buff_generic,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -122,8 +122,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_h
 	 */
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
+		return IXGBE_ERR_INVALID_LINK_SETTINGS;
 	}
 
 	/*
@@ -143,7 +142,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_h
 		/* some MAC's need RMW protection on AUTOC */
 		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
 		if (ret_val)
-			goto out;
+			return ret_val;
 
 		/* only backplane uses autoc so fall though */
 	case ixgbe_media_type_fiber:
@@ -214,9 +213,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_h
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = IXGBE_ERR_CONFIG;
-		goto out;
-		break;
+		return IXGBE_ERR_CONFIG;
 	}
 
 	if (hw->mac.type != ixgbe_mac_X540) {
@@ -247,7 +244,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_h
 		 */
 		ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
 		if (ret_val)
-			goto out;
+			return ret_val;
 
 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
 		   ixgbe_device_supports_autoneg_fc(hw)) {
@@ -256,7 +253,6 @@ static s32 ixgbe_setup_fc(struct ixgbe_h
 	}
 
 	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
-out:
 	return ret_val;
 }
 
@@ -295,12 +291,11 @@ s32 ixgbe_start_hw_generic(struct ixgbe_
 	/* Setup flow control */
 	ret_val = ixgbe_setup_fc(hw);
 	if (!ret_val)
-		goto out;
+		return 0;
 
 	/* Clear adapter stopped flag */
 	hw->adapter_stopped = false;
 
-out:
 	return ret_val;
 }
 
@@ -837,20 +832,16 @@ s32 ixgbe_init_eeprom_params_generic(str
 s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
 					       u16 words, u16 *data)
 {
-	s32 status = 0;
+	s32 status;
 	u16 i, count;
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0) {
-		status = IXGBE_ERR_INVALID_ARGUMENT;
-		goto out;
-	}
+	if (words == 0)
+		return IXGBE_ERR_INVALID_ARGUMENT;
 
-	if (offset + words > hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
+	if (offset + words > hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
 	/*
 	 * The EEPROM page size cannot be queried from the chip. We do lazy
@@ -875,7 +866,6 @@ s32 ixgbe_write_eeprom_buffer_bit_bang_g
 			break;
 	}
 
-out:
 	return status;
 }
 
@@ -900,64 +890,61 @@ static s32 ixgbe_write_eeprom_buffer_bit
 
 	/* Prepare the EEPROM for writing  */
 	status = ixgbe_acquire_eeprom(hw);
+	if (status)
+		return status;
 
-	if (status == 0) {
-		if (ixgbe_ready_eeprom(hw) != 0) {
-			ixgbe_release_eeprom(hw);
-			status = IXGBE_ERR_EEPROM;
-		}
+	if (ixgbe_ready_eeprom(hw) != 0) {
+		ixgbe_release_eeprom(hw);
+		return IXGBE_ERR_EEPROM;
 	}
 
-	if (status == 0) {
-		for (i = 0; i < words; i++) {
-			ixgbe_standby_eeprom(hw);
+	for (i = 0; i < words; i++) {
+		ixgbe_standby_eeprom(hw);
 
-			/*  Send the WRITE ENABLE command (8 bit opcode )  */
-			ixgbe_shift_out_eeprom_bits(hw,
-						  IXGBE_EEPROM_WREN_OPCODE_SPI,
-						  IXGBE_EEPROM_OPCODE_BITS);
+		/* Send the WRITE ENABLE command (8 bit opcode) */
+		ixgbe_shift_out_eeprom_bits(hw,
+					    IXGBE_EEPROM_WREN_OPCODE_SPI,
+					    IXGBE_EEPROM_OPCODE_BITS);
 
-			ixgbe_standby_eeprom(hw);
+		ixgbe_standby_eeprom(hw);
 
-			/*
-			 * Some SPI eeproms use the 8th address bit embedded
-			 * in the opcode
-			 */
-			if ((hw->eeprom.address_bits == 8) &&
-			    ((offset + i) >= 128))
-				write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+		/* Some SPI eeproms use the 8th address bit embedded
+		 * in the opcode
+		 */
+		if ((hw->eeprom.address_bits == 8) &&
+		    ((offset + i) >= 128))
+			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
 
-			/* Send the Write command (8-bit opcode + addr) */
-			ixgbe_shift_out_eeprom_bits(hw, write_opcode,
-						    IXGBE_EEPROM_OPCODE_BITS);
-			ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
-						    hw->eeprom.address_bits);
+		/* Send the Write command (8-bit opcode + addr) */
+		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
+					    IXGBE_EEPROM_OPCODE_BITS);
+		ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+					    hw->eeprom.address_bits);
 
-			page_size = hw->eeprom.word_page_size;
+		page_size = hw->eeprom.word_page_size;
 
-			/* Send the data in burst via SPI*/
-			do {
-				word = data[i];
-				word = (word >> 8) | (word << 8);
-				ixgbe_shift_out_eeprom_bits(hw, word, 16);
+		/* Send the data in burst via SPI */
+		do {
+			word = data[i];
+			word = (word >> 8) | (word << 8);
+			ixgbe_shift_out_eeprom_bits(hw, word, 16);
 
-				if (page_size == 0)
-					break;
+			if (page_size == 0)
+				break;
 
-				/* do not wrap around page */
-				if (((offset + i) & (page_size - 1)) ==
-				    (page_size - 1))
-					break;
-			} while (++i < words);
+			/* do not wrap around page */
+			if (((offset + i) & (page_size - 1)) ==
+			    (page_size - 1))
+				break;
+		} while (++i < words);
 
-			ixgbe_standby_eeprom(hw);
-			usleep_range(10000, 20000);
-		}
-		/* Done with writing - release the EEPROM */
-		ixgbe_release_eeprom(hw);
+		ixgbe_standby_eeprom(hw);
+		usleep_range(10000, 20000);
 	}
+	/* Done with writing - release the EEPROM */
+	ixgbe_release_eeprom(hw);
 
-	return status;
+	return 0;
 }
 
 /**
@@ -971,19 +958,12 @@ static s32 ixgbe_write_eeprom_buffer_bit
  **/
 s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
 {
-	s32 status;
-
 	hw->eeprom.ops.init_params(hw);
 
-	if (offset >= hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
-
-	status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
+	if (offset >= hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
-out:
-	return status;
+	return ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
 }
 
 /**
@@ -998,20 +978,16 @@ out:
 s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
 					      u16 words, u16 *data)
 {
-	s32 status = 0;
+	s32 status;
 	u16 i, count;
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0) {
-		status = IXGBE_ERR_INVALID_ARGUMENT;
-		goto out;
-	}
+	if (words == 0)
+		return IXGBE_ERR_INVALID_ARGUMENT;
 
-	if (offset + words > hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
+	if (offset + words > hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
 	/*
 	 * We cannot hold synchronization semaphores for too long
@@ -1025,12 +1001,11 @@ s32 ixgbe_read_eeprom_buffer_bit_bang_ge
 		status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
 							   count, &data[i]);
 
-		if (status != 0)
-			break;
+		if (status)
+			return status;
 	}
 
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -1052,41 +1027,38 @@ static s32 ixgbe_read_eeprom_buffer_bit_
 
 	/* Prepare the EEPROM for reading  */
 	status = ixgbe_acquire_eeprom(hw);
+	if (status)
+		return status;
 
-	if (status == 0) {
-		if (ixgbe_ready_eeprom(hw) != 0) {
-			ixgbe_release_eeprom(hw);
-			status = IXGBE_ERR_EEPROM;
-		}
+	if (ixgbe_ready_eeprom(hw) != 0) {
+		ixgbe_release_eeprom(hw);
+		return IXGBE_ERR_EEPROM;
 	}
 
-	if (status == 0) {
-		for (i = 0; i < words; i++) {
-			ixgbe_standby_eeprom(hw);
-			/*
-			 * Some SPI eeproms use the 8th address bit embedded
-			 * in the opcode
-			 */
-			if ((hw->eeprom.address_bits == 8) &&
-			    ((offset + i) >= 128))
-				read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
-
-			/* Send the READ command (opcode + addr) */
-			ixgbe_shift_out_eeprom_bits(hw, read_opcode,
-						    IXGBE_EEPROM_OPCODE_BITS);
-			ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
-						    hw->eeprom.address_bits);
+	for (i = 0; i < words; i++) {
+		ixgbe_standby_eeprom(hw);
+		/* Some SPI eeproms use the 8th address bit embedded
+		 * in the opcode
+		 */
+		if ((hw->eeprom.address_bits == 8) &&
+		    ((offset + i) >= 128))
+			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
 
-			/* Read the data. */
-			word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
-			data[i] = (word_in >> 8) | (word_in << 8);
-		}
+		/* Send the READ command (opcode + addr) */
+		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
+					    IXGBE_EEPROM_OPCODE_BITS);
+		ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+					    hw->eeprom.address_bits);
 
-		/* End this read operation */
-		ixgbe_release_eeprom(hw);
+		/* Read the data. */
+		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
+		data[i] = (word_in >> 8) | (word_in << 8);
 	}
 
-	return status;
+	/* End this read operation */
+	ixgbe_release_eeprom(hw);
+
+	return 0;
 }
 
 /**
@@ -1100,19 +1072,12 @@ static s32 ixgbe_read_eeprom_buffer_bit_
 s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
 				       u16 *data)
 {
-	s32 status;
-
 	hw->eeprom.ops.init_params(hw);
 
-	if (offset >= hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
-
-	status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+	if (offset >= hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
-out:
-	return status;
+	return ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
 }
 
 /**
@@ -1128,20 +1093,16 @@ s32 ixgbe_read_eerd_buffer_generic(struc
 				   u16 words, u16 *data)
 {
 	u32 eerd;
-	s32 status = 0;
+	s32 status;
 	u32 i;
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0) {
-		status = IXGBE_ERR_INVALID_ARGUMENT;
-		goto out;
-	}
+	if (words == 0)
+		return IXGBE_ERR_INVALID_ARGUMENT;
 
-	if (offset >= hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
+	if (offset >= hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
 	for (i = 0; i < words; i++) {
 		eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1155,11 +1116,11 @@ s32 ixgbe_read_eerd_buffer_generic(struc
 				   IXGBE_EEPROM_RW_REG_DATA);
 		} else {
 			hw_dbg(hw, "Eeprom read timed out\n");
-			goto out;
+			return status;
 		}
 	}
-out:
-	return status;
+
+	return 0;
 }
 
 /**
@@ -1175,7 +1136,7 @@ static s32 ixgbe_detect_eeprom_page_size
 						 u16 offset)
 {
 	u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
-	s32 status = 0;
+	s32 status;
 	u16 i;
 
 	for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
@@ -1185,12 +1146,12 @@ static s32 ixgbe_detect_eeprom_page_size
 	status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
 					     IXGBE_EEPROM_PAGE_SIZE_MAX, data);
 	hw->eeprom.word_page_size = 0;
-	if (status != 0)
-		goto out;
+	if (status)
+		return status;
 
 	status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
-	if (status != 0)
-		goto out;
+	if (status)
+		return status;
 
 	/*
 	 * When writing in burst more than the actual page size
@@ -1200,8 +1161,7 @@ static s32 ixgbe_detect_eeprom_page_size
 
 	hw_dbg(hw, "Detected EEPROM page size = %d words.\n",
 	       hw->eeprom.word_page_size);
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -1230,20 +1190,16 @@ s32 ixgbe_write_eewr_buffer_generic(stru
 				    u16 words, u16 *data)
 {
 	u32 eewr;
-	s32 status = 0;
+	s32 status;
 	u16 i;
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0) {
-		status = IXGBE_ERR_INVALID_ARGUMENT;
-		goto out;
-	}
+	if (words == 0)
+		return IXGBE_ERR_INVALID_ARGUMENT;
 
-	if (offset >= hw->eeprom.word_size) {
-		status = IXGBE_ERR_EEPROM;
-		goto out;
-	}
+	if (offset >= hw->eeprom.word_size)
+		return IXGBE_ERR_EEPROM;
 
 	for (i = 0; i < words; i++) {
 		eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1251,22 +1207,21 @@ s32 ixgbe_write_eewr_buffer_generic(stru
 		       IXGBE_EEPROM_RW_REG_START;
 
 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
-		if (status != 0) {
+		if (status) {
 			hw_dbg(hw, "Eeprom write EEWR timed out\n");
-			goto out;
+			return status;
 		}
 
 		IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
 
 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
-		if (status != 0) {
+		if (status) {
 			hw_dbg(hw, "Eeprom write EEWR timed out\n");
-			goto out;
+			return status;
 		}
 	}
 
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -1294,7 +1249,6 @@ static s32 ixgbe_poll_eerd_eewr_done(str
 {
 	u32 i;
 	u32 reg;
-	s32 status = IXGBE_ERR_EEPROM;
 
 	for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
 		if (ee_reg == IXGBE_NVM_POLL_READ)
@@ -1303,12 +1257,11 @@ static s32 ixgbe_poll_eerd_eewr_done(str
 			reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
 
 		if (reg & IXGBE_EEPROM_RW_REG_DONE) {
-			status = 0;
-			break;
+			return 0;
 		}
 		udelay(5);
 	}
-	return status;
+	return IXGBE_ERR_EEPROM;
 }
 
 /**
@@ -1320,47 +1273,42 @@ static s32 ixgbe_poll_eerd_eewr_done(str
  **/
 static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
 	u32 eec;
 	u32 i;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
-		status = IXGBE_ERR_SWFW_SYNC;
-
-	if (status == 0) {
-		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		return IXGBE_ERR_SWFW_SYNC;
 
-		/* Request EEPROM Access */
-		eec |= IXGBE_EEC_REQ;
-		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
 
-		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
-			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
-			if (eec & IXGBE_EEC_GNT)
-				break;
-			udelay(5);
-		}
+	/* Request EEPROM Access */
+	eec |= IXGBE_EEC_REQ;
+	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 
-		/* Release if grant not acquired */
-		if (!(eec & IXGBE_EEC_GNT)) {
-			eec &= ~IXGBE_EEC_REQ;
-			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
-			hw_dbg(hw, "Could not acquire EEPROM grant\n");
+	for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		if (eec & IXGBE_EEC_GNT)
+			break;
+		udelay(5);
+	}
 
-			hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-			status = IXGBE_ERR_EEPROM;
-		}
+	/* Release if grant not acquired */
+	if (!(eec & IXGBE_EEC_GNT)) {
+		eec &= ~IXGBE_EEC_REQ;
+		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+		hw_dbg(hw, "Could not acquire EEPROM grant\n");
 
-		/* Setup EEPROM for Read/Write */
-		if (status == 0) {
-			/* Clear CS and SK */
-			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
-			IXGBE_WRITE_FLUSH(hw);
-			udelay(1);
-		}
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+		return IXGBE_ERR_EEPROM;
 	}
-	return status;
+
+	/* Setup EEPROM for Read/Write */
+	/* Clear CS and SK */
+	eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_FLUSH(hw);
+	udelay(1);
+	return 0;
 }
 
 /**
@@ -1371,7 +1319,6 @@ static s32 ixgbe_acquire_eeprom(struct i
  **/
 static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_EEPROM;
 	u32 timeout = 2000;
 	u32 i;
 	u32 swsm;
@@ -1383,68 +1330,60 @@ static s32 ixgbe_get_eeprom_semaphore(st
 		 * set and we have the semaphore
 		 */
 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
-		if (!(swsm & IXGBE_SWSM_SMBI)) {
-			status = 0;
+		if (!(swsm & IXGBE_SWSM_SMBI))
 			break;
-		}
-		udelay(50);
+		usleep_range(50, 100);
 	}
 
 	if (i == timeout) {
 		hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore not granted.\n");
-		/*
-		 * this release is particularly important because our attempts
+		/* this release is particularly important because our attempts
 		 * above to get the semaphore may have succeeded, and if there
 		 * was a timeout, we should unconditionally clear the semaphore
 		 * bits to free the driver to make progress
 		 */
 		ixgbe_release_eeprom_semaphore(hw);
 
-		udelay(50);
-		/*
-		 * one last try
+		usleep_range(50, 100);
+		/* one last try
 		 * If the SMBI bit is 0 when we read it, then the bit will be
 		 * set and we have the semaphore
 		 */
 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
-		if (!(swsm & IXGBE_SWSM_SMBI))
-			status = 0;
+		if (swsm & IXGBE_SWSM_SMBI) {
+			hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+			return IXGBE_ERR_EEPROM;
+		}
 	}
 
 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
-	if (status == 0) {
-		for (i = 0; i < timeout; i++) {
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+	for (i = 0; i < timeout; i++) {
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
 
-			/* Set the SW EEPROM semaphore bit to request access */
-			swsm |= IXGBE_SWSM_SWESMBI;
-			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+		/* Set the SW EEPROM semaphore bit to request access */
+		swsm |= IXGBE_SWSM_SWESMBI;
+		IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
 
-			/*
-			 * If we set the bit successfully then we got the
-			 * semaphore.
-			 */
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
-			if (swsm & IXGBE_SWSM_SWESMBI)
-				break;
+		/* If we set the bit successfully then we got the
+		 * semaphore.
+		 */
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+		if (swsm & IXGBE_SWSM_SWESMBI)
+			break;
 
-			udelay(50);
-		}
+		usleep_range(50, 100);
+	}
 
-		/*
-		 * Release semaphores and return error if SW EEPROM semaphore
-		 * was not granted because we don't have access to the EEPROM
-		 */
-		if (i >= timeout) {
-			hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
-			ixgbe_release_eeprom_semaphore(hw);
-			status = IXGBE_ERR_EEPROM;
-		}
-	} else {
-		hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+	/* Release semaphores and return error if SW EEPROM semaphore
+	 * was not granted because we don't have access to the EEPROM
+	 */
+	if (i >= timeout) {
+		hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
+		ixgbe_release_eeprom_semaphore(hw);
+		return IXGBE_ERR_EEPROM;
 	}
 
-	return status;
+	return 0;
 }
 
 /**
@@ -1471,7 +1410,6 @@ static void ixgbe_release_eeprom_semapho
  **/
 static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
 	u16 i;
 	u8 spi_stat_reg;
 
@@ -1498,10 +1436,10 @@ static s32 ixgbe_ready_eeprom(struct ixg
 	 */
 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
 		hw_dbg(hw, "SPI EEPROM Status error\n");
-		status = IXGBE_ERR_EEPROM;
+		return IXGBE_ERR_EEPROM;
 	}
 
-	return status;
+	return 0;
 }
 
 /**
@@ -2100,17 +2038,14 @@ s32 ixgbe_disable_mc_generic(struct ixgb
  **/
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
 	u32 mflcn_reg, fccfg_reg;
 	u32 reg;
 	u32 fcrtl, fcrth;
 	int i;
 
 	/* Validate the water mark configuration. */
-	if (!hw->fc.pause_time) {
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
-	}
+	if (!hw->fc.pause_time)
+		return IXGBE_ERR_INVALID_LINK_SETTINGS;
 
 	/* Low water mark of zero causes XOFF floods */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -2119,8 +2054,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 			if (!hw->fc.low_water[i] ||
 			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
 				hw_dbg(hw, "Invalid water mark configuration\n");
-				ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-				goto out;
+				return IXGBE_ERR_INVALID_LINK_SETTINGS;
 			}
 		}
 	}
@@ -2177,9 +2111,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = IXGBE_ERR_CONFIG;
-		goto out;
-		break;
+		return IXGBE_ERR_CONFIG;
 	}
 
 	/* Set 802.3x based flow control settings. */
@@ -2215,8 +2147,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 
 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -2277,7 +2208,7 @@ static s32 ixgbe_negotiate_fc(struct ixg
 static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
 {
 	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
-	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+	s32 ret_val;
 
 	/*
 	 * On multispeed fiber at 1g, bail out if
@@ -2288,7 +2219,7 @@ static s32 ixgbe_fc_autoneg_fiber(struct
 	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
 	if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
 	    (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
-		goto out;
+		return IXGBE_ERR_FC_NOT_NEGOTIATED;
 
 	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
 	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
@@ -2299,7 +2230,6 @@ static s32 ixgbe_fc_autoneg_fiber(struct
 			       IXGBE_PCS1GANA_SYM_PAUSE,
 			       IXGBE_PCS1GANA_ASM_PAUSE);
 
-out:
 	return ret_val;
 }
 
@@ -2312,7 +2242,7 @@ out:
 static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
 {
 	u32 links2, anlp1_reg, autoc_reg, links;
-	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+	s32 ret_val;
 
 	/*
 	 * On backplane, bail out if
@@ -2321,12 +2251,12 @@ static s32 ixgbe_fc_autoneg_backplane(st
 	 */
 	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
 	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
-		goto out;
+		return IXGBE_ERR_FC_NOT_NEGOTIATED;
 
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
 		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
-			goto out;
+			return IXGBE_ERR_FC_NOT_NEGOTIATED;
 	}
 	/*
 	 * Read the 10g AN autoc and LP ability registers and resolve
@@ -2339,7 +2269,6 @@ static s32 ixgbe_fc_autoneg_backplane(st
 		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
 		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
 
-out:
 	return ret_val;
 }
 
@@ -2485,7 +2414,6 @@ static u32 ixgbe_pcie_timeout_poll(struc
  **/
 static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
 	u32 i, poll;
 	u16 value;
 
@@ -2495,13 +2423,13 @@ static s32 ixgbe_disable_pcie_master(str
 	/* Exit if master requests are blocked */
 	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
 	    ixgbe_removed(hw->hw_addr))
-		goto out;
+		return 0;
 
 	/* Poll for master request bit to clear */
 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
 		udelay(100);
 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
-			goto out;
+			return 0;
 	}
 
 	/*
@@ -2524,16 +2452,13 @@ static s32 ixgbe_disable_pcie_master(str
 		udelay(100);
 		value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
 		if (ixgbe_removed(hw->hw_addr))
-			goto out;
+			return 0;
 		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
-			goto out;
+			return 0;
 	}
 
 	hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
-	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
-
-out:
-	return status;
+	return IXGBE_ERR_MASTER_REQUESTS_PENDING;
 }
 
 /**
@@ -2708,8 +2633,8 @@ s32 ixgbe_blink_led_start_generic(struct
 	bool link_up = false;
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
-	s32 ret_val = 0;
 	bool locked = false;
+	s32 ret_val;
 
 	/*
 	 * Link must be up to auto-blink the LEDs;
@@ -2720,14 +2645,14 @@ s32 ixgbe_blink_led_start_generic(struct
 	if (!link_up) {
 		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
 		if (ret_val)
-			goto out;
+			return ret_val;
 
 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 		autoc_reg |= IXGBE_AUTOC_FLU;
 
 		ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
 		if (ret_val)
-			goto out;
+			return ret_val;
 
 		IXGBE_WRITE_FLUSH(hw);
 
@@ -2739,8 +2664,7 @@ s32 ixgbe_blink_led_start_generic(struct
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -2752,19 +2676,19 @@ s32 ixgbe_blink_led_stop_generic(struct
 {
 	u32 autoc_reg = 0;
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
-	s32 ret_val = 0;
 	bool locked = false;
+	s32 ret_val;
 
 	ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
 	if (ret_val)
-		goto out;
+		return ret_val;
 
 	autoc_reg &= ~IXGBE_AUTOC_FLU;
 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 
 	ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
 	if (ret_val)
-		goto out;
+		return ret_val;
 
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
 	led_reg &= ~IXGBE_LED_BLINK(index);
@@ -2772,8 +2696,7 @@ s32 ixgbe_blink_led_stop_generic(struct
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -2865,7 +2788,7 @@ san_mac_addr_clr:
  **/
 u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 {
-	u16 msix_count = 1;
+	u16 msix_count;
 	u16 max_msix_count;
 	u16 pcie_offset;
 
@@ -2880,7 +2803,7 @@ u16 ixgbe_get_pcie_msix_count_generic(st
 		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
 		break;
 	default:
-		return msix_count;
+		return 1;
 	}
 
 	msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset);
@@ -2918,10 +2841,10 @@ s32 ixgbe_clear_vmdq_generic(struct ixgb
 	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 
 	if (ixgbe_removed(hw->hw_addr))
-		goto done;
+		return 0;
 
 	if (!mpsar_lo && !mpsar_hi)
-		goto done;
+		return 0;
 
 	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
 		if (mpsar_lo) {
@@ -2943,7 +2866,6 @@ s32 ixgbe_clear_vmdq_generic(struct ixgb
 	/* was that the last pool using this rar? */
 	if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
 		hw->mac.ops.clear_rar(hw, rar);
-done:
 	return 0;
 }
 
@@ -3312,14 +3234,14 @@ s32 ixgbe_get_wwn_prefix_generic(struct
 
 	if ((alt_san_mac_blk_offset == 0) ||
 	    (alt_san_mac_blk_offset == 0xFFFF))
-		goto wwn_prefix_out;
+		return 0;
 
 	/* check capability in alternative san mac address block */
 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
 	if (hw->eeprom.ops.read(hw, offset, &caps))
 		goto wwn_prefix_err;
 	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
-		goto wwn_prefix_out;
+		return 0;
 
 	/* get the corresponding prefix for WWNN/WWPN */
 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
@@ -3330,7 +3252,6 @@ s32 ixgbe_get_wwn_prefix_generic(struct
 	if (hw->eeprom.ops.read(hw, offset, wwpn_prefix))
 		goto wwn_prefix_err;
 
-wwn_prefix_out:
 	return 0;
 
 wwn_prefix_err:
@@ -3524,21 +3445,17 @@ static s32 ixgbe_host_interface_command(
 	u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
 	u8 buf_len, dword_len;
 
-	s32 ret_val = 0;
-
 	if (length == 0 || length & 0x3 ||
 	    length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
 		hw_dbg(hw, "Buffer length failure.\n");
-		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-		goto out;
+		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
 	}
 
 	/* Check that the host interface is enabled. */
 	hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
 	if ((hicr & IXGBE_HICR_EN) == 0) {
 		hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
-		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-		goto out;
+		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
 	}
 
 	/* Calculate length in DWORDs */
@@ -3566,8 +3483,7 @@ static s32 ixgbe_host_interface_command(
 	if (i == IXGBE_HI_COMMAND_TIMEOUT ||
 	    (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
 		hw_dbg(hw, "Command has failed with no status valid.\n");
-		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-		goto out;
+		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
 	}
 
 	/* Calculate length in DWORDs */
@@ -3582,12 +3498,11 @@ static s32 ixgbe_host_interface_command(
 	/* If there is any thing in data position pull it in */
 	buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
 	if (buf_len == 0)
-		goto out;
+		return 0;
 
 	if (length < (buf_len + hdr_size)) {
 		hw_dbg(hw, "Buffer not large enough for reply message.\n");
-		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-		goto out;
+		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
 	}
 
 	/* Calculate length in DWORDs, add 3 for odd lengths */
@@ -3599,8 +3514,7 @@ static s32 ixgbe_host_interface_command(
 		le32_to_cpus(&buffer[bi]);
 	}
 
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -3621,12 +3535,10 @@ s32 ixgbe_set_fw_drv_ver_generic(struct
 {
 	struct ixgbe_hic_drv_info fw_cmd;
 	int i;
-	s32 ret_val = 0;
+	s32 ret_val;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
-		ret_val = IXGBE_ERR_SWFW_SYNC;
-		goto out;
-	}
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM))
+		return IXGBE_ERR_SWFW_SYNC;
 
 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
@@ -3658,7 +3570,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct
 	}
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
-out:
 	return ret_val;
 }
 
@@ -3727,28 +3638,23 @@ static const u8 ixgbe_emc_therm_limit[4]
 static s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg,
 			      u16 *ets_offset)
 {
-	s32 status = 0;
+	s32 status;
 
 	status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset);
 	if (status)
-		goto out;
+		return status;
 
-	if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF)) {
-		status = IXGBE_NOT_IMPLEMENTED;
-		goto out;
-	}
+	if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF))
+		return IXGBE_NOT_IMPLEMENTED;
 
 	status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
 	if (status)
-		goto out;
+		return status;
 
-	if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED) {
-		status = IXGBE_NOT_IMPLEMENTED;
-		goto out;
-	}
+	if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED)
+		return IXGBE_NOT_IMPLEMENTED;
 
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -3759,7 +3665,7 @@ out:
  **/
 s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
+	s32 status;
 	u16 ets_offset;
 	u16 ets_cfg;
 	u16 ets_sensor;
@@ -3768,14 +3674,12 @@ s32 ixgbe_get_thermal_sensor_data_generi
 	struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
 
 	/* Only support thermal sensors attached to physical port 0 */
-	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
-		status = IXGBE_NOT_IMPLEMENTED;
-		goto out;
-	}
+	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
+		return IXGBE_NOT_IMPLEMENTED;
 
 	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
 	if (status)
-		goto out;
+		return status;
 
 	num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
 	if (num_sensors > IXGBE_MAX_SENSORS)
@@ -3788,7 +3692,7 @@ s32 ixgbe_get_thermal_sensor_data_generi
 		status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
 					     &ets_sensor);
 		if (status)
-			goto out;
+			return status;
 
 		sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
 				IXGBE_ETS_DATA_INDEX_SHIFT);
@@ -3801,11 +3705,11 @@ s32 ixgbe_get_thermal_sensor_data_generi
 					IXGBE_I2C_THERMAL_SENSOR_ADDR,
 					&data->sensor[i].temp);
 			if (status)
-				goto out;
+				return status;
 		}
 	}
-out:
-	return status;
+
+	return 0;
 }
 
 /**
@@ -3817,7 +3721,7 @@ out:
  **/
 s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
+	s32 status;
 	u16 ets_offset;
 	u16 ets_cfg;
 	u16 ets_sensor;
@@ -3830,14 +3734,12 @@ s32 ixgbe_init_thermal_sensor_thresh_gen
 	memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
 
 	/* Only support thermal sensors attached to physical port 0 */
-	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
-		status = IXGBE_NOT_IMPLEMENTED;
-		goto out;
-	}
+	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
+		return IXGBE_NOT_IMPLEMENTED;
 
 	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
 	if (status)
-		goto out;
+		return status;
 
 	low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
 			     IXGBE_ETS_LTHRES_DELTA_SHIFT);
@@ -3871,7 +3773,7 @@ s32 ixgbe_init_thermal_sensor_thresh_gen
 		data->sensor[i].caution_thresh = therm_limit;
 		data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta;
 	}
-out:
-	return status;
+
+	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -87,7 +87,6 @@ s32 ixgbe_dcb_calculate_tc_credits(struc
 	int min_credit;
 	int min_multiplier;
 	int min_percent = 100;
-	s32 ret_val = 0;
 	/* Initialization values default for Tx settings */
 	u32 credit_refill       = 0;
 	u32 credit_max          = 0;
@@ -95,10 +94,8 @@ s32 ixgbe_dcb_calculate_tc_credits(struc
 	u8  bw_percent          = 0;
 	u8  i;
 
-	if (dcb_config == NULL) {
-		ret_val = DCB_ERR_CONFIG;
-		goto out;
-	}
+	if (!dcb_config)
+		return DCB_ERR_CONFIG;
 
 	min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
 			DCB_CREDIT_QUANTUM;
@@ -174,8 +171,7 @@ s32 ixgbe_dcb_calculate_tc_credits(struc
 		p->data_credits_max = (u16)credit_max;
 	}
 
-out:
-	return ret_val;
+	return 0;
 }
 
 void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
@@ -236,7 +232,7 @@ u8 ixgbe_dcb_get_tc_from_up(struct ixgbe
 
 	/* If tc is 0 then DCB is likely not enabled or supported */
 	if (!tc)
-		goto out;
+		return 0;
 
 	/*
 	 * Test from maximum TC to 1 and report the first match we find.  If
@@ -247,7 +243,7 @@ u8 ixgbe_dcb_get_tc_from_up(struct ixgbe
 		if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
 			break;
 	}
-out:
+
 	return tc;
 }
 
@@ -269,7 +265,6 @@ void ixgbe_dcb_unpack_map(struct ixgbe_d
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
 			struct ixgbe_dcb_config *dcb_config)
 {
-	s32 ret = 0;
 	u8 pfc_en;
 	u8 ptype[MAX_TRAFFIC_CLASS];
 	u8 bwgid[MAX_TRAFFIC_CLASS];
@@ -287,37 +282,31 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		ret = ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
-						bwgid, ptype);
-		break;
+		return ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
+						 bwgid, ptype);
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ret = ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
-						bwgid, ptype, prio_tc);
-		break;
+		return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
+						 bwgid, ptype, prio_tc);
 	default:
 		break;
 	}
-	return ret;
+	return 0;
 }
 
 /* Helper routines to abstract HW specifics from DCB netlink ops */
 s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
 {
-	int ret = -EINVAL;
-
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
-		break;
+		return ixgbe_dcb_config_pfc_82598(hw, pfc_en);
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
-		break;
+		return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
 	default:
 		break;
 	}
-	return ret;
+	return -EINVAL;
 }
 
 s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -153,7 +153,6 @@ static u8 ixgbe_dcbnl_get_state(struct n
 static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	int err = 0;
 
 	/* Fail command if not in CEE mode */
 	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
@@ -161,12 +160,10 @@ static u8 ixgbe_dcbnl_set_state(struct n
 
 	/* verify there is something to do, if not then exit */
 	if (!state == !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-		goto out;
+		return 0;
 
-	err = ixgbe_setup_tc(netdev,
-			     state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
-out:
-	return !!err;
+	return !!ixgbe_setup_tc(netdev,
+				state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
 }
 
 static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
@@ -331,12 +328,12 @@ static u8 ixgbe_dcbnl_set_all(struct net
 
 	/* Fail command if not in CEE mode */
 	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
-		return ret;
+		return DCB_NO_HW_CHG;
 
 	adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter,
 						      MAX_TRAFFIC_CLASS);
 	if (!adapter->dcb_set_bitmap)
-		return ret;
+		return DCB_NO_HW_CHG;
 
 	if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
 		u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
@@ -460,7 +457,6 @@ static int ixgbe_dcbnl_getnumtcs(struct
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 	} else {
 		return -EINVAL;
@@ -495,10 +491,10 @@ static void ixgbe_dcbnl_setpfcstate(stru
  * @id: id is either ether type or TCP/UDP port number
  *
  * Returns : on success, returns a non-zero 802.1p user priority bitmap
- * otherwise returns 0 as the invalid user priority bitmap to indicate an
+ * otherwise returns -EINVAL as the invalid user priority bitmap to indicate an
  * error.
  */
-static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
+static int ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct dcb_app app = {
@@ -507,7 +503,7 @@ static u8 ixgbe_dcbnl_getapp(struct net_
 			     };
 
 	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
-		return 0;
+		return -EINVAL;
 
 	return dcb_getapp(netdev, &app);
 }
@@ -537,7 +533,7 @@ static int ixgbe_dcbnl_ieee_setets(struc
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 	int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
-	int i, err = 0;
+	int i, err;
 	__u8 max_tc = 0;
 	__u8 map_chg = 0;
 
@@ -574,17 +570,15 @@ static int ixgbe_dcbnl_ieee_setets(struc
 	if (max_tc > adapter->dcb_cfg.num_tcs.pg_tcs)
 		return -EINVAL;
 
-	if (max_tc != netdev_get_num_tc(dev))
+	if (max_tc != netdev_get_num_tc(dev)) {
 		err = ixgbe_setup_tc(dev, max_tc);
-	else if (map_chg)
+		if (err)
+			return err;
+	} else if (map_chg) {
 		ixgbe_dcbnl_devreset(dev);
+	}
 
-	if (err)
-		goto err_out;
-
-	err = ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
-err_out:
-	return err;
+	return ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
 }
 
 static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
@@ -648,10 +642,10 @@ static int ixgbe_dcbnl_ieee_setapp(struc
 				   struct dcb_app *app)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	int err = -EINVAL;
+	int err;
 
 	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
-		return err;
+		return -EINVAL;
 
 	err = dcb_ieee_setapp(dev, app);
 	if (err)
@@ -663,7 +657,7 @@ static int ixgbe_dcbnl_ieee_setapp(struc
 		u8 app_mask = dcb_ieee_getapp_mask(dev, app);
 
 		if (app_mask & (1 << adapter->fcoe.up))
-			return err;
+			return 0;
 
 		adapter->fcoe.up = app->priority;
 		ixgbe_dcbnl_devreset(dev);
@@ -706,7 +700,7 @@ static int ixgbe_dcbnl_ieee_delapp(struc
 		u8 app_mask = dcb_ieee_getapp_mask(dev, app);
 
 		if (app_mask & (1 << adapter->fcoe.up))
-			return err;
+			return 0;
 
 		adapter->fcoe.up = app_mask ?
 				   ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -1408,7 +1408,6 @@ static int ixgbe_reg_test(struct ixgbe_a
 	default:
 		*data = 1;
 		return 1;
-		break;
 	}
 
 	/*
@@ -2518,7 +2517,7 @@ static int ixgbe_update_ethtool_fdir_ent
 
 	/* add filter to the list */
 	if (parent)
-		hlist_add_after(&parent->fdir_node, &input->fdir_node);
+		hlist_add_behind(&input->fdir_node, &parent->fdir_node);
 	else
 		hlist_add_head(&input->fdir_node,
 			       &adapter->fdir_filter_list);
@@ -2866,7 +2865,6 @@ static int ixgbe_get_ts_info(struct net_
 		break;
 	default:
 		return ethtool_op_get_ts_info(dev, info);
-		break;
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -67,23 +67,23 @@ static inline void ixgbe_fcoe_clear_ddp(
  */
 int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
 {
-	int len = 0;
+	int len;
 	struct ixgbe_fcoe *fcoe;
 	struct ixgbe_adapter *adapter;
 	struct ixgbe_fcoe_ddp *ddp;
 	u32 fcbuff;
 
 	if (!netdev)
-		goto out_ddp_put;
+		return 0;
 
 	if (xid >= IXGBE_FCOE_DDP_MAX)
-		goto out_ddp_put;
+		return 0;
 
 	adapter = netdev_priv(netdev);
 	fcoe = &adapter->fcoe;
 	ddp = &fcoe->ddp[xid];
 	if (!ddp->udl)
-		goto out_ddp_put;
+		return 0;
 
 	len = ddp->len;
 	/* if there an error, force to invalidate ddp context */
@@ -114,7 +114,6 @@ int ixgbe_fcoe_ddp_put(struct net_device
 
 	ixgbe_fcoe_clear_ddp(ddp);
 
-out_ddp_put:
 	return len;
 }
 
@@ -394,17 +393,17 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter
 		xid =  be16_to_cpu(fh->fh_rx_id);
 
 	if (xid >= IXGBE_FCOE_DDP_MAX)
-		goto ddp_out;
+		return -EINVAL;
 
 	fcoe = &adapter->fcoe;
 	ddp = &fcoe->ddp[xid];
 	if (!ddp->udl)
-		goto ddp_out;
+		return -EINVAL;
 
 	ddp_err = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCEOFE |
 					      IXGBE_RXDADV_ERR_FCERR);
 	if (ddp_err)
-		goto ddp_out;
+		return -EINVAL;
 
 	switch (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_FCSTAT)) {
 	/* return 0 to bypass going to ULD for DDPed data */
@@ -447,7 +446,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter
 		crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
 		crc->fcoe_eof = FC_EOF_T;
 	}
-ddp_out:
+
 	return rc;
 }
 
@@ -878,7 +877,6 @@ int ixgbe_fcoe_disable(struct net_device
  */
 int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
 {
-	int rc = -EINVAL;
 	u16 prefix = 0xffff;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_mac_info *mac = &adapter->hw.mac;
@@ -903,9 +901,9 @@ int ixgbe_fcoe_get_wwn(struct net_device
 		       ((u64) mac->san_addr[3] << 16) |
 		       ((u64) mac->san_addr[4] << 8)  |
 		       ((u64) mac->san_addr[5]);
-		rc = 0;
+		return 0;
 	}
-	return rc;
+	return -EINVAL;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -84,7 +84,7 @@ static const struct ixgbe_info *ixgbe_in
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
+static const struct pci_device_id ixgbe_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 },
@@ -570,7 +570,7 @@ static void ixgbe_dump(struct ixgbe_adap
 
 	/* Print TX Ring Summary */
 	if (!netdev || !netif_running(netdev))
-		goto exit;
+		return;
 
 	dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
 	pr_info(" %s     %s              %s        %s\n",
@@ -685,7 +685,7 @@ rx_ring_summary:
 
 	/* Print RX Rings */
 	if (!netif_msg_rx_status(adapter))
-		goto exit;
+		return;
 
 	dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
 
@@ -787,9 +787,6 @@ rx_ring_summary:
 
 		}
 	}
-
-exit:
-	return;
 }
 
 static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
@@ -1011,7 +1008,6 @@ static inline bool ixgbe_check_tx_hang(s
 	u32 tx_done = ixgbe_get_tx_completed(tx_ring);
 	u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
 	u32 tx_pending = ixgbe_get_tx_pending(tx_ring);
-	bool ret = false;
 
 	clear_check_for_tx_hang(tx_ring);
 
@@ -1027,18 +1023,16 @@ static inline bool ixgbe_check_tx_hang(s
 	 * run the check_tx_hang logic with a transmit completion
 	 * pending but without time to complete it yet.
 	 */
-	if ((tx_done_old == tx_done) && tx_pending) {
+	if (tx_done_old == tx_done && tx_pending)
 		/* make sure it is true for two checks in a row */
-		ret = test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
-				       &tx_ring->state);
-	} else {
-		/* update completed stats and continue */
-		tx_ring->tx_stats.tx_done_old = tx_done;
-		/* reset the countdown */
-		clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
-	}
+		return test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
+					&tx_ring->state);
+	/* update completed stats and continue */
+	tx_ring->tx_stats.tx_done_old = tx_done;
+	/* reset the countdown */
+	clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
 
-	return ret;
+	return false;
 }
 
 /**
@@ -4701,18 +4695,18 @@ static int ixgbe_non_sfp_link_config(str
 		ret = hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
 	if (ret)
-		goto link_cfg_out;
+		return ret;
 
 	speed = hw->phy.autoneg_advertised;
 	if ((!speed) && (hw->mac.ops.get_link_capabilities))
 		ret = hw->mac.ops.get_link_capabilities(hw, &speed,
 							&autoneg);
 	if (ret)
-		goto link_cfg_out;
+		return ret;
 
 	if (hw->mac.ops.setup_link)
 		ret = hw->mac.ops.setup_link(hw, speed, link_up);
-link_cfg_out:
+
 	return ret;
 }
 
@@ -7973,23 +7967,32 @@ static const struct net_device_ops ixgbe
  **/
 static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
 {
-	struct list_head *entry;
+	struct pci_dev *entry, *pdev = adapter->pdev;
 	int physfns = 0;
 
 	/* Some cards can not use the generic count PCIe functions method,
 	 * because they are behind a parent switch, so we hardcode these with
 	 * the correct number of functions.
 	 */
-	if (ixgbe_pcie_from_parent(&adapter->hw)) {
+	if (ixgbe_pcie_from_parent(&adapter->hw))
 		physfns = 4;
-	} else {
-		list_for_each(entry, &adapter->pdev->bus_list) {
-			struct pci_dev *pdev =
-				list_entry(entry, struct pci_dev, bus_list);
-			/* don't count virtual functions */
-			if (!pdev->is_virtfn)
-				physfns++;
-		}
+
+	list_for_each_entry(entry, &adapter->pdev->bus->devices, bus_list) {
+		/* don't count virtual functions */
+		if (entry->is_virtfn)
+			continue;
+
+		/* When the devices on the bus don't all match our device ID,
+		 * we can't reliably determine the correct number of
+		 * functions. This can occur if a function has been direct
+		 * attached to a virtual machine using VT-d, for example. In
+		 * this case, simply return -1 to indicate this.
+		 */
+		if ((entry->vendor != pdev->vendor) ||
+		    (entry->device != pdev->device))
+			return -1;
+
+		physfns++;
 	}
 
 	return physfns;
@@ -8161,7 +8164,7 @@ static int ixgbe_probe(struct pci_dev *p
 	netdev->netdev_ops = &ixgbe_netdev_ops;
 	ixgbe_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
-	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+	strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
 
 	adapter->bd_number = cards_found;
 
@@ -8384,11 +8387,14 @@ skip_sriov:
 		expected_gts = ixgbe_enumerate_functions(adapter) * 10;
 		break;
 	}
-	ixgbe_check_minimum_link(adapter, expected_gts);
 
-	err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
+	/* don't check link if we failed to enumerate functions */
+	if (expected_gts > 0)
+		ixgbe_check_minimum_link(adapter, expected_gts);
+
+	err = ixgbe_read_pba_string_generic(hw, part_str, sizeof(part_str));
 	if (err)
-		strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
+		strlcpy(part_str, "Unknown", sizeof(part_str));
 	if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
 		e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
 			   hw->mac.type, hw->phy.type, hw->phy.sfp_type,
@@ -8477,7 +8483,7 @@ err_alloc_etherdev:
 				     pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
-	if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+	if (!adapter || !test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
 		pci_disable_device(pdev);
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -43,16 +43,15 @@
 s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
 
 	/* limit read to size of mailbox */
 	if (size > mbx->size)
 		size = mbx->size;
 
-	if (mbx->ops.read)
-		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+	if (!mbx->ops.read)
+		return IXGBE_ERR_MBX;
 
-	return ret_val;
+	return mbx->ops.read(hw, msg, size, mbx_id);
 }
 
 /**
@@ -67,15 +66,14 @@ s32 ixgbe_read_mbx(struct ixgbe_hw *hw,
 s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = 0;
 
 	if (size > mbx->size)
-		ret_val = IXGBE_ERR_MBX;
+		return IXGBE_ERR_MBX;
 
-	else if (mbx->ops.write)
-		ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+	if (!mbx->ops.write)
+		return IXGBE_ERR_MBX;
 
-	return ret_val;
+	return mbx->ops.write(hw, msg, size, mbx_id);
 }
 
 /**
@@ -88,12 +86,11 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *hw,
 s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (mbx->ops.check_for_msg)
-		ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+	if (!mbx->ops.check_for_msg)
+		return IXGBE_ERR_MBX;
 
-	return ret_val;
+	return mbx->ops.check_for_msg(hw, mbx_id);
 }
 
 /**
@@ -106,12 +103,11 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw
 s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (mbx->ops.check_for_ack)
-		ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+	if (!mbx->ops.check_for_ack)
+		return IXGBE_ERR_MBX;
 
-	return ret_val;
+	return mbx->ops.check_for_ack(hw, mbx_id);
 }
 
 /**
@@ -124,12 +120,11 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw
 s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (mbx->ops.check_for_rst)
-		ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+	if (!mbx->ops.check_for_rst)
+		return IXGBE_ERR_MBX;
 
-	return ret_val;
+	return mbx->ops.check_for_rst(hw, mbx_id);
 }
 
 /**
@@ -145,17 +140,16 @@ static s32 ixgbe_poll_for_msg(struct ixg
 	int countdown = mbx->timeout;
 
 	if (!countdown || !mbx->ops.check_for_msg)
-		goto out;
+		return IXGBE_ERR_MBX;
 
-	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+	while (mbx->ops.check_for_msg(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
-			break;
+			return IXGBE_ERR_MBX;
 		udelay(mbx->usec_delay);
 	}
 
-out:
-	return countdown ? 0 : IXGBE_ERR_MBX;
+	return 0;
 }
 
 /**
@@ -171,17 +165,16 @@ static s32 ixgbe_poll_for_ack(struct ixg
 	int countdown = mbx->timeout;
 
 	if (!countdown || !mbx->ops.check_for_ack)
-		goto out;
+		return IXGBE_ERR_MBX;
 
-	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+	while (mbx->ops.check_for_ack(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
-			break;
+			return IXGBE_ERR_MBX;
 		udelay(mbx->usec_delay);
 	}
 
-out:
-	return countdown ? 0 : IXGBE_ERR_MBX;
+	return 0;
 }
 
 /**
@@ -198,18 +191,17 @@ static s32 ixgbe_read_posted_mbx(struct
 				 u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
+	s32 ret_val;
 
 	if (!mbx->ops.read)
-		goto out;
+		return IXGBE_ERR_MBX;
 
 	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+	if (ret_val)
+		return ret_val;
 
-	/* if ack received read message, otherwise we timed out */
-	if (!ret_val)
-		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
-out:
-	return ret_val;
+	/* if ack received read message */
+	return mbx->ops.read(hw, msg, size, mbx_id);
 }
 
 /**
@@ -226,33 +218,31 @@ static s32 ixgbe_write_posted_mbx(struct
 			   u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
+	s32 ret_val;
 
 	/* exit if either we can't write or there isn't a defined timeout */
 	if (!mbx->ops.write || !mbx->timeout)
-		goto out;
+		return IXGBE_ERR_MBX;
 
 	/* send msg */
 	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+	if (ret_val)
+		return ret_val;
 
 	/* if msg sent wait until we receive an ack */
-	if (!ret_val)
-		ret_val = ixgbe_poll_for_ack(hw, mbx_id);
-out:
-	return ret_val;
+	return ixgbe_poll_for_ack(hw, mbx_id);
 }
 
 static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
 {
 	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
-	s32 ret_val = IXGBE_ERR_MBX;
 
 	if (mbvficr & mask) {
-		ret_val = 0;
 		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
+		return 0;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -264,17 +254,16 @@ static s32 ixgbe_check_for_bit_pf(struct
  **/
 static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
 	u32 vf_bit = vf_number % 16;
 
 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
 				    index)) {
-		ret_val = 0;
 		hw->mbx.stats.reqs++;
+		return 0;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -286,17 +275,16 @@ static s32 ixgbe_check_for_msg_pf(struct
  **/
 static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
 	u32 vf_bit = vf_number % 16;
 
 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
 				    index)) {
-		ret_val = 0;
 		hw->mbx.stats.acks++;
+		return 0;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -311,7 +299,6 @@ static s32 ixgbe_check_for_rst_pf(struct
 	u32 reg_offset = (vf_number < 32) ? 0 : 1;
 	u32 vf_shift = vf_number % 32;
 	u32 vflre = 0;
-	s32 ret_val = IXGBE_ERR_MBX;
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82599EB:
@@ -325,12 +312,12 @@ static s32 ixgbe_check_for_rst_pf(struct
 	}
 
 	if (vflre & (1 << vf_shift)) {
-		ret_val = 0;
 		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
 		hw->mbx.stats.rsts++;
+		return 0;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -342,7 +329,6 @@ static s32 ixgbe_check_for_rst_pf(struct
  **/
 static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
 	u32 p2v_mailbox;
 
 	/* Take ownership of the buffer */
@@ -351,9 +337,9 @@ static s32 ixgbe_obtain_mbx_lock_pf(stru
 	/* reserve mailbox for vf use */
 	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
 	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
-		ret_val = 0;
+		return 0;
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -374,7 +360,7 @@ static s32 ixgbe_write_mbx_pf(struct ixg
 	/* lock the mailbox to prevent pf/vf race condition */
 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
 	if (ret_val)
-		goto out_no_write;
+		return ret_val;
 
 	/* flush msg and acks as we are overwriting the message buffer */
 	ixgbe_check_for_msg_pf(hw, vf_number);
@@ -390,9 +376,7 @@ static s32 ixgbe_write_mbx_pf(struct ixg
 	/* update stats */
 	hw->mbx.stats.msgs_tx++;
 
-out_no_write:
-	return ret_val;
-
+	return 0;
 }
 
 /**
@@ -415,7 +399,7 @@ static s32 ixgbe_read_mbx_pf(struct ixgb
 	/* lock the mailbox to prevent pf/vf race condition */
 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
 	if (ret_val)
-		goto out_no_read;
+		return ret_val;
 
 	/* copy the message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
@@ -427,8 +411,7 @@ static s32 ixgbe_read_mbx_pf(struct ixgb
 	/* update stats */
 	hw->mbx.stats.msgs_rx++;
 
-out_no_read:
-	return ret_val;
+	return 0;
 }
 
 #ifdef CONFIG_PCI_IOV
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,6 @@ static s32 ixgbe_identify_qsfp_module_ge
  **/
 s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 	u32 phy_addr;
 	u16 ext_ability = 0;
 
@@ -84,18 +83,14 @@ s32 ixgbe_identify_phy_generic(struct ix
 							 ixgbe_phy_generic;
 				}
 
-				status = 0;
-				break;
+				return 0;
 			}
 		}
 		/* clear value if nothing found */
-		if (status != 0)
-			hw->phy.mdio.prtad = 0;
-	} else {
-		status = 0;
+		hw->phy.mdio.prtad = 0;
+		return IXGBE_ERR_PHY_ADDR_INVALID;
 	}
-
-	return status;
+	return 0;
 }
 
 /**
@@ -192,16 +187,16 @@ s32 ixgbe_reset_phy_generic(struct ixgbe
 		status = ixgbe_identify_phy_generic(hw);
 
 	if (status != 0 || hw->phy.type == ixgbe_phy_none)
-		goto out;
+		return status;
 
 	/* Don't reset PHY if it's shut down due to overtemp. */
 	if (!hw->phy.reset_if_overtemp &&
 	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
-		goto out;
+		return 0;
 
 	/* Blocked by MNG FW so bail */
 	if (ixgbe_check_reset_blocked(hw))
-		goto out;
+		return 0;
 
 	/*
 	 * Perform soft PHY reset to the PHY_XS.
@@ -227,12 +222,11 @@ s32 ixgbe_reset_phy_generic(struct ixgbe
 	}
 
 	if (ctrl & MDIO_CTRL1_RESET) {
-		status = IXGBE_ERR_RESET_FAILED;
 		hw_dbg(hw, "PHY reset polling failed to complete.\n");
+		return IXGBE_ERR_RESET_FAILED;
 	}
 
-out:
-	return status;
+	return 0;
 }
 
 /**
@@ -333,7 +327,7 @@ s32 ixgbe_read_phy_reg_generic(struct ix
 						phy_data);
 		hw->mac.ops.release_swfw_sync(hw, gssr);
 	} else {
-		status = IXGBE_ERR_SWFW_SYNC;
+		return IXGBE_ERR_SWFW_SYNC;
 	}
 
 	return status;
@@ -436,7 +430,7 @@ s32 ixgbe_write_phy_reg_generic(struct i
 						 phy_data);
 		hw->mac.ops.release_swfw_sync(hw, gssr);
 	} else {
-		status = IXGBE_ERR_SWFW_SYNC;
+		return IXGBE_ERR_SWFW_SYNC;
 	}
 
 	return status;
@@ -509,7 +503,7 @@ s32 ixgbe_setup_phy_link_generic(struct
 
 	/* Blocked by MNG FW so don't reset PHY */
 	if (ixgbe_check_reset_blocked(hw))
-		return status;
+		return 0;
 
 	/* Restart PHY autonegotiation and wait for completion */
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
@@ -535,8 +529,8 @@ s32 ixgbe_setup_phy_link_generic(struct
 	}
 
 	if (time_out == max_time_out) {
-		status = IXGBE_ERR_LINK_SETUP;
 		hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out\n");
+		return IXGBE_ERR_LINK_SETUP;
 	}
 
 	return status;
@@ -585,7 +579,7 @@ s32 ixgbe_get_copper_link_capabilities_g
 					       ixgbe_link_speed *speed,
 					       bool *autoneg)
 {
-	s32 status = IXGBE_ERR_LINK_SETUP;
+	s32 status;
 	u16 speed_ability;
 
 	*speed = 0;
@@ -616,7 +610,7 @@ s32 ixgbe_get_copper_link_capabilities_g
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 			     bool *link_up)
 {
-	s32 status = 0;
+	s32 status;
 	u32 time_out;
 	u32 max_time_out = 10;
 	u16 phy_link = 0;
@@ -662,7 +656,7 @@ s32 ixgbe_check_phy_link_tnx(struct ixgb
  **/
 s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
+	s32 status;
 	u32 time_out;
 	u32 max_time_out = 10;
 	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
@@ -719,7 +713,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgb
 
 	/* Blocked by MNG FW so don't reset PHY */
 	if (ixgbe_check_reset_blocked(hw))
-		return status;
+		return 0;
 
 	/* Restart PHY autonegotiation and wait for completion */
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
@@ -744,8 +738,8 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgb
 	}
 
 	if (time_out == max_time_out) {
-		status = IXGBE_ERR_LINK_SETUP;
 		hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out\n");
+		return IXGBE_ERR_LINK_SETUP;
 	}
 
 	return status;
@@ -759,7 +753,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgb
 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
 				       u16 *firmware_version)
 {
-	s32 status = 0;
+	s32 status;
 
 	status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
 				      MDIO_MMD_VEND1,
@@ -776,7 +770,7 @@ s32 ixgbe_get_phy_firmware_version_tnx(s
 s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
 					   u16 *firmware_version)
 {
-	s32 status = 0;
+	s32 status;
 
 	status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
 				      MDIO_MMD_VEND1,
@@ -795,12 +789,12 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *
 	bool end_data = false;
 	u16 list_offset, data_offset;
 	u16 phy_data = 0;
-	s32 ret_val = 0;
+	s32 ret_val;
 	u32 i;
 
 	/* Blocked by MNG FW so bail */
 	if (ixgbe_check_reset_blocked(hw))
-		goto out;
+		return 0;
 
 	hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data);
 
@@ -818,15 +812,14 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *
 
 	if ((phy_data & MDIO_CTRL1_RESET) != 0) {
 		hw_dbg(hw, "PHY reset did not complete.\n");
-		ret_val = IXGBE_ERR_PHY;
-		goto out;
+		return IXGBE_ERR_PHY;
 	}
 
 	/* Get init offsets */
 	ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
 						      &data_offset);
-	if (ret_val != 0)
-		goto out;
+	if (ret_val)
+		return ret_val;
 
 	ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
 	data_offset++;
@@ -876,18 +869,15 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *
 				hw_dbg(hw, "SOL\n");
 			} else {
 				hw_dbg(hw, "Bad control value\n");
-				ret_val = IXGBE_ERR_PHY;
-				goto out;
+				return IXGBE_ERR_PHY;
 			}
 			break;
 		default:
 			hw_dbg(hw, "Bad control type\n");
-			ret_val = IXGBE_ERR_PHY;
-			goto out;
+			return IXGBE_ERR_PHY;
 		}
 	}
 
-out:
 	return ret_val;
 
 err_eeprom:
@@ -903,34 +893,29 @@ err_eeprom:
  **/
 s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_SFP_NOT_PRESENT;
-
 	switch (hw->mac.ops.get_media_type(hw)) {
 	case ixgbe_media_type_fiber:
-		status = ixgbe_identify_sfp_module_generic(hw);
-		break;
+		return ixgbe_identify_sfp_module_generic(hw);
 	case ixgbe_media_type_fiber_qsfp:
-		status = ixgbe_identify_qsfp_module_generic(hw);
-		break;
+		return ixgbe_identify_qsfp_module_generic(hw);
 	default:
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		status = IXGBE_ERR_SFP_NOT_PRESENT;
-		break;
+		return IXGBE_ERR_SFP_NOT_PRESENT;
 	}
 
-	return status;
+	return IXGBE_ERR_SFP_NOT_PRESENT;
 }
 
 /**
  *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
  *  @hw: pointer to hardware structure
-*
+ *
  *  Searches for and identifies the SFP module and assigns appropriate PHY type.
  **/
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 {
 	struct ixgbe_adapter *adapter = hw->back;
-	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+	s32 status;
 	u32 vendor_oui = 0;
 	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
 	u8 identifier = 0;
@@ -943,15 +928,14 @@ s32 ixgbe_identify_sfp_module_generic(st
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		status = IXGBE_ERR_SFP_NOT_PRESENT;
-		goto out;
+		return IXGBE_ERR_SFP_NOT_PRESENT;
 	}
 
 	status = hw->phy.ops.read_i2c_eeprom(hw,
 					     IXGBE_SFF_IDENTIFIER,
 					     &identifier);
 
-	if (status != 0)
+	if (status)
 		goto err_read_i2c_eeprom;
 
 	/* LAN ID is needed for sfp_type determination */
@@ -959,239 +943,224 @@ s32 ixgbe_identify_sfp_module_generic(st
 
 	if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-	} else {
-		status = hw->phy.ops.read_i2c_eeprom(hw,
-						     IXGBE_SFF_1GBE_COMP_CODES,
-						     &comp_codes_1g);
+		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+	}
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_1GBE_COMP_CODES,
+					     &comp_codes_1g);
 
-		if (status != 0)
-			goto err_read_i2c_eeprom;
+	if (status)
+		goto err_read_i2c_eeprom;
 
-		status = hw->phy.ops.read_i2c_eeprom(hw,
-						     IXGBE_SFF_10GBE_COMP_CODES,
-						     &comp_codes_10g);
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_10GBE_COMP_CODES,
+					     &comp_codes_10g);
 
-		if (status != 0)
-			goto err_read_i2c_eeprom;
-		status = hw->phy.ops.read_i2c_eeprom(hw,
-						     IXGBE_SFF_CABLE_TECHNOLOGY,
-						     &cable_tech);
+	if (status)
+		goto err_read_i2c_eeprom;
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_CABLE_TECHNOLOGY,
+					     &cable_tech);
 
-		if (status != 0)
-			goto err_read_i2c_eeprom;
+	if (status)
+		goto err_read_i2c_eeprom;
 
-		 /* ID Module
-		  * =========
-		  * 0   SFP_DA_CU
-		  * 1   SFP_SR
-		  * 2   SFP_LR
-		  * 3   SFP_DA_CORE0 - 82599-specific
-		  * 4   SFP_DA_CORE1 - 82599-specific
-		  * 5   SFP_SR/LR_CORE0 - 82599-specific
-		  * 6   SFP_SR/LR_CORE1 - 82599-specific
-		  * 7   SFP_act_lmt_DA_CORE0 - 82599-specific
-		  * 8   SFP_act_lmt_DA_CORE1 - 82599-specific
-		  * 9   SFP_1g_cu_CORE0 - 82599-specific
-		  * 10  SFP_1g_cu_CORE1 - 82599-specific
-		  * 11  SFP_1g_sx_CORE0 - 82599-specific
-		  * 12  SFP_1g_sx_CORE1 - 82599-specific
-		  */
-		if (hw->mac.type == ixgbe_mac_82598EB) {
-			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
-				hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
-			else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-				hw->phy.sfp_type = ixgbe_sfp_type_sr;
-			else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-				hw->phy.sfp_type = ixgbe_sfp_type_lr;
+	 /* ID Module
+	  * =========
+	  * 0   SFP_DA_CU
+	  * 1   SFP_SR
+	  * 2   SFP_LR
+	  * 3   SFP_DA_CORE0 - 82599-specific
+	  * 4   SFP_DA_CORE1 - 82599-specific
+	  * 5   SFP_SR/LR_CORE0 - 82599-specific
+	  * 6   SFP_SR/LR_CORE1 - 82599-specific
+	  * 7   SFP_act_lmt_DA_CORE0 - 82599-specific
+	  * 8   SFP_act_lmt_DA_CORE1 - 82599-specific
+	  * 9   SFP_1g_cu_CORE0 - 82599-specific
+	  * 10  SFP_1g_cu_CORE1 - 82599-specific
+	  * 11  SFP_1g_sx_CORE0 - 82599-specific
+	  * 12  SFP_1g_sx_CORE1 - 82599-specific
+	  */
+	if (hw->mac.type == ixgbe_mac_82598EB) {
+		if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+			hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
+		else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+			hw->phy.sfp_type = ixgbe_sfp_type_sr;
+		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+			hw->phy.sfp_type = ixgbe_sfp_type_lr;
+		else
+			hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+	} else if (hw->mac.type == ixgbe_mac_82599EB) {
+		if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					     ixgbe_sfp_type_da_cu_core0;
 			else
-				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
-		} else if (hw->mac.type == ixgbe_mac_82599EB) {
-			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-						     ixgbe_sfp_type_da_cu_core0;
-				else
-					hw->phy.sfp_type =
-						     ixgbe_sfp_type_da_cu_core1;
-			} else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
-				hw->phy.ops.read_i2c_eeprom(
-						hw, IXGBE_SFF_CABLE_SPEC_COMP,
-						&cable_spec);
-				if (cable_spec &
-				    IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
-					if (hw->bus.lan_id == 0)
-						hw->phy.sfp_type =
-						ixgbe_sfp_type_da_act_lmt_core0;
-					else
-						hw->phy.sfp_type =
-						ixgbe_sfp_type_da_act_lmt_core1;
-				} else {
-					hw->phy.sfp_type =
-							ixgbe_sfp_type_unknown;
-				}
-			} else if (comp_codes_10g &
-				   (IXGBE_SFF_10GBASESR_CAPABLE |
-				    IXGBE_SFF_10GBASELR_CAPABLE)) {
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-						      ixgbe_sfp_type_srlr_core0;
-				else
-					hw->phy.sfp_type =
-						      ixgbe_sfp_type_srlr_core1;
-			} else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_cu_core0;
-				else
-					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_cu_core1;
-			} else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) {
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_sx_core0;
-				else
-					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_sx_core1;
-			} else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+				hw->phy.sfp_type =
+					     ixgbe_sfp_type_da_cu_core1;
+		} else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
+			hw->phy.ops.read_i2c_eeprom(
+					hw, IXGBE_SFF_CABLE_SPEC_COMP,
+					&cable_spec);
+			if (cable_spec &
+			    IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_lx_core0;
+					ixgbe_sfp_type_da_act_lmt_core0;
 				else
 					hw->phy.sfp_type =
-						ixgbe_sfp_type_1g_lx_core1;
+					ixgbe_sfp_type_da_act_lmt_core1;
 			} else {
-				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+				hw->phy.sfp_type =
+						ixgbe_sfp_type_unknown;
 			}
+		} else if (comp_codes_10g &
+			   (IXGBE_SFF_10GBASESR_CAPABLE |
+			    IXGBE_SFF_10GBASELR_CAPABLE)) {
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					      ixgbe_sfp_type_srlr_core0;
+			else
+				hw->phy.sfp_type =
+					      ixgbe_sfp_type_srlr_core1;
+		} else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_cu_core0;
+			else
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_cu_core1;
+		} else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) {
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_sx_core0;
+			else
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_sx_core1;
+		} else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+			if (hw->bus.lan_id == 0)
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_lx_core0;
+			else
+				hw->phy.sfp_type =
+					ixgbe_sfp_type_1g_lx_core1;
+		} else {
+			hw->phy.sfp_type = ixgbe_sfp_type_unknown;
 		}
+	}
 
-		if (hw->phy.sfp_type != stored_sfp_type)
-			hw->phy.sfp_setup_needed = true;
+	if (hw->phy.sfp_type != stored_sfp_type)
+		hw->phy.sfp_setup_needed = true;
 
-		/* Determine if the SFP+ PHY is dual speed or not. */
-		hw->phy.multispeed_fiber = false;
-		if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
-		   (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
-		   ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
-		   (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
-			hw->phy.multispeed_fiber = true;
+	/* Determine if the SFP+ PHY is dual speed or not. */
+	hw->phy.multispeed_fiber = false;
+	if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+	     (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+	    ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+	     (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+		hw->phy.multispeed_fiber = true;
 
-		/* Determine PHY vendor */
-		if (hw->phy.type != ixgbe_phy_nl) {
-			hw->phy.id = identifier;
-			status = hw->phy.ops.read_i2c_eeprom(hw,
-						    IXGBE_SFF_VENDOR_OUI_BYTE0,
-						    &oui_bytes[0]);
+	/* Determine PHY vendor */
+	if (hw->phy.type != ixgbe_phy_nl) {
+		hw->phy.id = identifier;
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					    IXGBE_SFF_VENDOR_OUI_BYTE0,
+					    &oui_bytes[0]);
 
-			if (status != 0)
-				goto err_read_i2c_eeprom;
+		if (status != 0)
+			goto err_read_i2c_eeprom;
 
-			status = hw->phy.ops.read_i2c_eeprom(hw,
-						    IXGBE_SFF_VENDOR_OUI_BYTE1,
-						    &oui_bytes[1]);
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					    IXGBE_SFF_VENDOR_OUI_BYTE1,
+					    &oui_bytes[1]);
 
-			if (status != 0)
-				goto err_read_i2c_eeprom;
+		if (status != 0)
+			goto err_read_i2c_eeprom;
 
-			status = hw->phy.ops.read_i2c_eeprom(hw,
-						    IXGBE_SFF_VENDOR_OUI_BYTE2,
-						    &oui_bytes[2]);
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+					    IXGBE_SFF_VENDOR_OUI_BYTE2,
+					    &oui_bytes[2]);
 
-			if (status != 0)
-				goto err_read_i2c_eeprom;
+		if (status != 0)
+			goto err_read_i2c_eeprom;
 
-			vendor_oui =
-			  ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
-			   (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
-			   (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+		vendor_oui =
+		  ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+		   (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+		   (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
 
-			switch (vendor_oui) {
-			case IXGBE_SFF_VENDOR_OUI_TYCO:
-				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
-					hw->phy.type =
-						    ixgbe_phy_sfp_passive_tyco;
-				break;
-			case IXGBE_SFF_VENDOR_OUI_FTL:
-				if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
-					hw->phy.type = ixgbe_phy_sfp_ftl_active;
-				else
-					hw->phy.type = ixgbe_phy_sfp_ftl;
-				break;
-			case IXGBE_SFF_VENDOR_OUI_AVAGO:
-				hw->phy.type = ixgbe_phy_sfp_avago;
-				break;
-			case IXGBE_SFF_VENDOR_OUI_INTEL:
-				hw->phy.type = ixgbe_phy_sfp_intel;
-				break;
-			default:
-				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
-					hw->phy.type =
-						 ixgbe_phy_sfp_passive_unknown;
-				else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
-					hw->phy.type =
-						ixgbe_phy_sfp_active_unknown;
-				else
-					hw->phy.type = ixgbe_phy_sfp_unknown;
-				break;
-			}
+		switch (vendor_oui) {
+		case IXGBE_SFF_VENDOR_OUI_TYCO:
+			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+				hw->phy.type =
+					    ixgbe_phy_sfp_passive_tyco;
+			break;
+		case IXGBE_SFF_VENDOR_OUI_FTL:
+			if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+				hw->phy.type = ixgbe_phy_sfp_ftl_active;
+			else
+				hw->phy.type = ixgbe_phy_sfp_ftl;
+			break;
+		case IXGBE_SFF_VENDOR_OUI_AVAGO:
+			hw->phy.type = ixgbe_phy_sfp_avago;
+			break;
+		case IXGBE_SFF_VENDOR_OUI_INTEL:
+			hw->phy.type = ixgbe_phy_sfp_intel;
+			break;
+		default:
+			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+				hw->phy.type =
+					 ixgbe_phy_sfp_passive_unknown;
+			else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+				hw->phy.type =
+					ixgbe_phy_sfp_active_unknown;
+			else
+				hw->phy.type = ixgbe_phy_sfp_unknown;
+			break;
 		}
+	}
 
-		/* Allow any DA cable vendor */
-		if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
-		    IXGBE_SFF_DA_ACTIVE_CABLE)) {
-			status = 0;
-			goto out;
-		}
+	/* Allow any DA cable vendor */
+	if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
+	    IXGBE_SFF_DA_ACTIVE_CABLE))
+		return 0;
 
-		/* Verify supported 1G SFP modules */
-		if (comp_codes_10g == 0 &&
-		    !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
-			hw->phy.type = ixgbe_phy_sfp_unsupported;
-			status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-			goto out;
-		}
+	/* Verify supported 1G SFP modules */
+	if (comp_codes_10g == 0 &&
+	    !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+	}
 
-		/* Anything else 82598-based is supported */
-		if (hw->mac.type == ixgbe_mac_82598EB) {
-			status = 0;
-			goto out;
-		}
+	/* Anything else 82598-based is supported */
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return 0;
 
-		hw->mac.ops.get_device_caps(hw, &enforce_sfp);
-		if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
-		    !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
-			/* Make sure we're a supported PHY type */
-			if (hw->phy.type == ixgbe_phy_sfp_intel) {
-				status = 0;
-			} else {
-				if (hw->allow_unsupported_sfp) {
-					e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics.  Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter.  Intel Corporation is not responsible for any harm caused by using untested modules.\n");
-					status = 0;
-				} else {
-					hw_dbg(hw,
-					       "SFP+ module not supported\n");
-					hw->phy.type =
-						ixgbe_phy_sfp_unsupported;
-					status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-				}
-			}
-		} else {
-			status = 0;
+	hw->mac.ops.get_device_caps(hw, &enforce_sfp);
+	if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
+	    !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
+		/* Make sure we're a supported PHY type */
+		if (hw->phy.type == ixgbe_phy_sfp_intel)
+			return 0;
+		if (hw->allow_unsupported_sfp) {
+			e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics.  Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter.  Intel Corporation is not responsible for any harm caused by using untested modules.\n");
+			return 0;
 		}
+		hw_dbg(hw, "SFP+ module not supported\n");
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		return IXGBE_ERR_SFP_NOT_SUPPORTED;
 	}
-
-out:
-	return status;
+	return 0;
 
 err_read_i2c_eeprom:
 	hw->phy.sfp_type = ixgbe_sfp_type_not_present;
@@ -1211,7 +1180,7 @@ err_read_i2c_eeprom:
 static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 {
 	struct ixgbe_adapter *adapter = hw->back;
-	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+	s32 status;
 	u32 vendor_oui = 0;
 	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
 	u8 identifier = 0;
@@ -1226,8 +1195,7 @@ static s32 ixgbe_identify_qsfp_module_ge
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		status = IXGBE_ERR_SFP_NOT_PRESENT;
-		goto out;
+		return IXGBE_ERR_SFP_NOT_PRESENT;
 	}
 
 	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
@@ -1238,8 +1206,7 @@ static s32 ixgbe_identify_qsfp_module_ge
 
 	if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-		goto out;
+		return IXGBE_ERR_SFP_NOT_SUPPORTED;
 	}
 
 	hw->phy.id = identifier;
@@ -1310,8 +1277,7 @@ static s32 ixgbe_identify_qsfp_module_ge
 		} else {
 			/* unsupported module type */
 			hw->phy.type = ixgbe_phy_sfp_unsupported;
-			status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-			goto out;
+			return IXGBE_ERR_SFP_NOT_SUPPORTED;
 		}
 	}
 
@@ -1363,27 +1329,19 @@ static s32 ixgbe_identify_qsfp_module_ge
 		hw->mac.ops.get_device_caps(hw, &enforce_sfp);
 		if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
 			/* Make sure we're a supported PHY type */
-			if (hw->phy.type == ixgbe_phy_qsfp_intel) {
-				status = 0;
-			} else {
-				if (hw->allow_unsupported_sfp == true) {
-					e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
-					status = 0;
-				} else {
-					hw_dbg(hw,
-					       "QSFP module not supported\n");
-					hw->phy.type =
-						ixgbe_phy_sfp_unsupported;
-					status = IXGBE_ERR_SFP_NOT_SUPPORTED;
-				}
+			if (hw->phy.type == ixgbe_phy_qsfp_intel)
+				return 0;
+			if (hw->allow_unsupported_sfp) {
+				e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
+				return 0;
 			}
-		} else {
-			status = 0;
+			hw_dbg(hw, "QSFP module not supported\n");
+			hw->phy.type = ixgbe_phy_sfp_unsupported;
+			return IXGBE_ERR_SFP_NOT_SUPPORTED;
 		}
+		return 0;
 	}
-
-out:
-	return status;
+	return 0;
 
 err_read_i2c_eeprom:
 	hw->phy.sfp_type = ixgbe_sfp_type_not_present;
@@ -1544,7 +1502,7 @@ s32 ixgbe_write_i2c_eeprom_generic(struc
 s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
 				u8 dev_addr, u8 *data)
 {
-	s32 status = 0;
+	s32 status;
 	u32 max_retry = 10;
 	u32 retry = 0;
 	u16 swfw_mask = 0;
@@ -1557,10 +1515,8 @@ s32 ixgbe_read_i2c_byte_generic(struct i
 		swfw_mask = IXGBE_GSSR_PHY0_SM;
 
 	do {
-		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
-			status = IXGBE_ERR_SWFW_SYNC;
-			goto read_byte_out;
-		}
+		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+			return IXGBE_ERR_SWFW_SYNC;
 
 		ixgbe_i2c_start(hw);
 
@@ -1617,7 +1573,6 @@ fail:
 
 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
 
-read_byte_out:
 	return status;
 }
 
@@ -1633,7 +1588,7 @@ read_byte_out:
 s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
 				 u8 dev_addr, u8 data)
 {
-	s32 status = 0;
+	s32 status;
 	u32 max_retry = 1;
 	u32 retry = 0;
 	u16 swfw_mask = 0;
@@ -1643,10 +1598,8 @@ s32 ixgbe_write_i2c_byte_generic(struct
 	else
 		swfw_mask = IXGBE_GSSR_PHY0_SM;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
-		status = IXGBE_ERR_SWFW_SYNC;
-		goto write_byte_out;
-	}
+	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+		return IXGBE_ERR_SWFW_SYNC;
 
 	do {
 		ixgbe_i2c_start(hw);
@@ -1689,7 +1642,6 @@ fail:
 
 	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
 
-write_byte_out:
 	return status;
 }
 
@@ -1774,7 +1726,7 @@ static s32 ixgbe_clock_in_i2c_byte(struc
  **/
 static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
 {
-	s32 status = 0;
+	s32 status;
 	s32 i;
 	u32 i2cctl;
 	bool bit = false;
@@ -1893,11 +1845,11 @@ static s32 ixgbe_clock_out_i2c_bit(struc
 		 */
 		udelay(IXGBE_I2C_T_LOW);
 	} else {
-		status = IXGBE_ERR_I2C;
 		hw_dbg(hw, "I2C data was not set to %X\n", data);
+		return IXGBE_ERR_I2C;
 	}
 
-	return status;
+	return 0;
 }
 /**
  *  ixgbe_raise_i2c_clk - Raises the I2C SCL clock
@@ -1954,8 +1906,6 @@ static void ixgbe_lower_i2c_clk(struct i
  **/
 static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
 {
-	s32 status = 0;
-
 	if (data)
 		*i2cctl |= IXGBE_I2C_DATA_OUT;
 	else
@@ -1970,11 +1920,11 @@ static s32 ixgbe_set_i2c_data(struct ixg
 	/* Verify data was set correctly */
 	*i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
 	if (data != ixgbe_get_i2c_data(i2cctl)) {
-		status = IXGBE_ERR_I2C;
 		hw_dbg(hw, "Error - I2C data was not set to %X.\n", data);
+		return IXGBE_ERR_I2C;
 	}
 
-	return status;
+	return 0;
 }
 
 /**
@@ -1986,14 +1936,9 @@ static s32 ixgbe_set_i2c_data(struct ixg
  **/
 static bool ixgbe_get_i2c_data(u32 *i2cctl)
 {
-	bool data;
-
 	if (*i2cctl & IXGBE_I2C_DATA_IN)
-		data = true;
-	else
-		data = false;
-
-	return data;
+		return true;
+	return false;
 }
 
 /**
@@ -2038,20 +1983,17 @@ static void ixgbe_i2c_bus_clear(struct i
  **/
 s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
 {
-	s32 status = 0;
 	u16 phy_data = 0;
 
 	if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
-		goto out;
+		return 0;
 
 	/* Check that the LASI temp alarm status was triggered */
 	hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
 			     MDIO_MMD_PMAPMD, &phy_data);
 
 	if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
-		goto out;
+		return 0;
 
-	status = IXGBE_ERR_OVERTEMP;
-out:
-	return status;
+	return IXGBE_ERR_OVERTEMP;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,9 +98,11 @@
 #define IXGBE_OVERFLOW_PERIOD    (HZ * 30)
 #define IXGBE_PTP_TX_TIMEOUT     (HZ * 15)
 
-#ifndef NSECS_PER_SEC
-#define NSECS_PER_SEC 1000000000ULL
-#endif
+/* half of a one second clock period, for use with PPS signal. We have to use
+ * this instead of something pre-defined like IXGBE_PTP_PPS_HALF_SECOND, in
+ * order to force at least 64bits of precision for shifting
+ */
+#define IXGBE_PTP_PPS_HALF_SECOND 500000000ULL
 
 /**
  * ixgbe_ptp_setup_sdp
@@ -146,8 +148,8 @@ static void ixgbe_ptp_setup_sdp(struct i
 			  IXGBE_TSAUXC_SDP0_INT);
 
 		/* clock period (or pulse length) */
-		clktiml = (u32)(NSECS_PER_SEC << shift);
-		clktimh = (u32)((NSECS_PER_SEC << shift) >> 32);
+		clktiml = (u32)(IXGBE_PTP_PPS_HALF_SECOND << shift);
+		clktimh = (u32)((IXGBE_PTP_PPS_HALF_SECOND << shift) >> 32);
 
 		/*
 		 * Account for the cyclecounter wrap-around value by
@@ -158,8 +160,8 @@ static void ixgbe_ptp_setup_sdp(struct i
 		clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
 		ns = timecounter_cyc2time(&adapter->tc, clock_edge);
 
-		div_u64_rem(ns, NSECS_PER_SEC, &rem);
-		clock_edge += ((NSECS_PER_SEC - (u64)rem) << shift);
+		div_u64_rem(ns, IXGBE_PTP_PPS_HALF_SECOND, &rem);
+		clock_edge += ((IXGBE_PTP_PPS_HALF_SECOND - (u64)rem) << shift);
 
 		/* specify the initial clock start time */
 		trgttiml = (u32)clock_edge;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -245,10 +245,10 @@ static int ixgbe_pci_sriov_enable(struct
 	if (pre_existing_vfs && pre_existing_vfs != num_vfs)
 		err = ixgbe_disable_sriov(adapter);
 	else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
-		goto out;
+		return num_vfs;
 
 	if (err)
-		goto err_out;
+		return err;
 
 	/* While the SR-IOV capability structure reports total VFs to be
 	 * 64 we limit the actual number that can be allocated to 63 so
@@ -256,16 +256,14 @@ static int ixgbe_pci_sriov_enable(struct
 	 * PF.  The PCI bus driver already checks for other values out of
 	 * range.
 	 */
-	if (num_vfs > IXGBE_MAX_VFS_DRV_LIMIT) {
-		err = -EPERM;
-		goto err_out;
-	}
+	if (num_vfs > IXGBE_MAX_VFS_DRV_LIMIT)
+		return -EPERM;
 
 	adapter->num_vfs = num_vfs;
 
 	err = __ixgbe_enable_sriov(adapter);
 	if (err)
-		goto err_out;
+		return  err;
 
 	for (i = 0; i < adapter->num_vfs; i++)
 		ixgbe_vf_configuration(dev, (i | 0x10000000));
@@ -273,17 +271,14 @@ static int ixgbe_pci_sriov_enable(struct
 	err = pci_enable_sriov(dev, num_vfs);
 	if (err) {
 		e_dev_warn("Failed to enable PCI sriov: %d\n", err);
-		goto err_out;
+		return err;
 	}
 	ixgbe_sriov_reinit(adapter);
 
-out:
 	return num_vfs;
-
-err_out:
-	return err;
-#endif
+#else
 	return 0;
+#endif
 }
 
 static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
@@ -807,7 +802,7 @@ static int ixgbe_set_vf_vlan_msg(struct
 	if (!add && adapter->netdev->flags & IFF_PROMISC) {
 		reg_ndx = ixgbe_find_vlvf_entry(hw, vid);
 		if (reg_ndx < 0)
-			goto out;
+			return err;
 		vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(reg_ndx));
 		/* See if any other pools are set for this VLAN filter
 		 * entry other than the PF.
@@ -833,8 +828,6 @@ static int ixgbe_set_vf_vlan_msg(struct
 			ixgbe_set_vf_vlan(adapter, add, vid, VMDQ_P(0));
 	}
 
-out:
-
 	return err;
 }
 
@@ -951,7 +944,7 @@ static int ixgbe_rcv_msg_from_vf(struct
 
 	/* this is a message we already processed, do nothing */
 	if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK))
-		return retval;
+		return 0;
 
 	/* flush the ack before we write any messages back */
 	IXGBE_WRITE_FLUSH(hw);
@@ -966,7 +959,7 @@ static int ixgbe_rcv_msg_from_vf(struct
 	if (!adapter->vfinfo[vf].clear_to_send) {
 		msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
 		ixgbe_write_mbx(hw, msgbuf, 1, vf);
-		return retval;
+		return 0;
 	}
 
 	switch ((msgbuf[0] & 0xFFFF)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h	2014-09-28 17:29:07.000000000 -0400
@@ -2440,25 +2440,6 @@ typedef u32 ixgbe_link_speed;
 					IXGBE_LINK_SPEED_1GB_FULL | \
 					IXGBE_LINK_SPEED_10GB_FULL)
 
-
-/* Physical layer type */
-typedef u32 ixgbe_physical_layer;
-#define IXGBE_PHYSICAL_LAYER_UNKNOWN      0
-#define IXGBE_PHYSICAL_LAYER_10GBASE_T    0x0001
-#define IXGBE_PHYSICAL_LAYER_1000BASE_T   0x0002
-#define IXGBE_PHYSICAL_LAYER_100BASE_TX   0x0004
-#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU  0x0008
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LR   0x0010
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM  0x0020
-#define IXGBE_PHYSICAL_LAYER_10GBASE_SR   0x0040
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4  0x0080
-#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4  0x0100
-#define IXGBE_PHYSICAL_LAYER_1000BASE_KX  0x0200
-#define IXGBE_PHYSICAL_LAYER_1000BASE_BX  0x0400
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KR   0x0800
-#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
-#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
-
 /* Flow Control Data Sheet defined values
  * Calculation and defines taken from 802.1bb Annex O
  */
@@ -2860,7 +2841,6 @@ struct ixgbe_mac_operations {
 	s32 (*start_hw)(struct ixgbe_hw *);
 	s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
 	enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
-	u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
 	s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
 	s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
 	s32 (*get_device_caps)(struct ixgbe_hw *, u16 *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2013 Intel Corporation.
+  Copyright(c) 1999 - 2014 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,
@@ -99,8 +99,8 @@ static s32 ixgbe_reset_hw_X540(struct ix
 
 	/* Call adapter stop to disable tx/rx and clear interrupts */
 	status = hw->mac.ops.stop_adapter(hw);
-	if (status != 0)
-		goto reset_hw_out;
+	if (status)
+		return status;
 
 	/* flush pending Tx transactions */
 	ixgbe_clear_tx_pending(hw);
@@ -168,7 +168,6 @@ mac_reset_top:
 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
 				   &hw->mac.wwpn_prefix);
 
-reset_hw_out:
 	return status;
 }
 
@@ -182,40 +181,13 @@ reset_hw_out:
  **/
 static s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
+	s32 ret_val;
 
 	ret_val = ixgbe_start_hw_generic(hw);
-	if (ret_val != 0)
-		goto out;
-
-	ret_val = ixgbe_start_hw_gen2(hw);
-out:
-	return ret_val;
-}
-
-/**
- *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
- *  @hw: pointer to hardware structure
- *
- *  Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
-{
-	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-	u16 ext_ability = 0;
-
-	hw->phy.ops.identify(hw);
-
-	hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
-			     &ext_ability);
-	if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
-		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
-	if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
-		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
-	if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
-		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+	if (ret_val)
+		return ret_val;
 
-	return physical_layer;
+	return ixgbe_start_hw_gen2(hw);
 }
 
 /**
@@ -258,13 +230,12 @@ static s32 ixgbe_init_eeprom_params_X540
  **/
 static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
 {
-	s32 status = 0;
+	s32 status;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-	    0)
-		status = ixgbe_read_eerd_generic(hw, offset, data);
-	else
-		status = IXGBE_ERR_SWFW_SYNC;
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return IXGBE_ERR_SWFW_SYNC;
+
+	status = ixgbe_read_eerd_generic(hw, offset, data);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 	return status;
@@ -282,14 +253,12 @@ static s32 ixgbe_read_eerd_X540(struct i
 static s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
 				       u16 offset, u16 words, u16 *data)
 {
-	s32 status = 0;
+	s32 status;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-	    0)
-		status = ixgbe_read_eerd_buffer_generic(hw, offset,
-							words, data);
-	else
-		status = IXGBE_ERR_SWFW_SYNC;
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return IXGBE_ERR_SWFW_SYNC;
+
+	status = ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 	return status;
@@ -305,12 +274,12 @@ static s32 ixgbe_read_eerd_buffer_X540(s
  **/
 static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
 {
-	s32 status = 0;
+	s32 status;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
-		status = ixgbe_write_eewr_generic(hw, offset, data);
-	else
-		status = IXGBE_ERR_SWFW_SYNC;
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return IXGBE_ERR_SWFW_SYNC;
+
+	status = ixgbe_write_eewr_generic(hw, offset, data);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 	return status;
@@ -328,14 +297,12 @@ static s32 ixgbe_write_eewr_X540(struct
 static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
 					u16 offset, u16 words, u16 *data)
 {
-	s32 status = 0;
+	s32 status;
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-	    0)
-		status = ixgbe_write_eewr_buffer_generic(hw, offset,
-							 words, data);
-	else
-		status = IXGBE_ERR_SWFW_SYNC;
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return IXGBE_ERR_SWFW_SYNC;
+
+	status = ixgbe_write_eewr_buffer_generic(hw, offset, words, data);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 	return status;
@@ -430,44 +397,37 @@ static s32 ixgbe_validate_eeprom_checksu
 	u16 checksum;
 	u16 read_checksum = 0;
 
-	/*
-	 * Read the first word from the EEPROM. If this times out or fails, do
+	/* Read the first word from the EEPROM. If this times out or fails, do
 	 * not continue or we could be in for a very long wait while every
 	 * EEPROM read fails
 	 */
 	status = hw->eeprom.ops.read(hw, 0, &checksum);
-
-	if (status != 0) {
+	if (status) {
 		hw_dbg(hw, "EEPROM read failed\n");
-		goto out;
+		return status;
 	}
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
-		checksum = hw->eeprom.ops.calc_checksum(hw);
-
-		/*
-		 * Do not use hw->eeprom.ops.read because we do not want to take
-		 * the synchronization semaphores twice here.
-		 */
-		ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
-					&read_checksum);
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return IXGBE_ERR_SWFW_SYNC;
 
-		/*
-		 * Verify read checksum from EEPROM is the same as
-		 * calculated checksum
-		 */
-		if (read_checksum != checksum)
-			status = IXGBE_ERR_EEPROM_CHECKSUM;
+	checksum = hw->eeprom.ops.calc_checksum(hw);
 
-		/* If the user cares, return the calculated checksum */
-		if (checksum_val)
-			*checksum_val = checksum;
-	} else {
-		status = IXGBE_ERR_SWFW_SYNC;
-	}
+	/* Do not use hw->eeprom.ops.read because we do not want to take
+	 * the synchronization semaphores twice here.
+	 */
+	status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
+					 &read_checksum);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-out:
+
+	/* If the user cares, return the calculated checksum */
+	if (checksum_val)
+		*checksum_val = checksum;
+
+	/* Verify read and calculated checksums are the same */
+	if (read_checksum != checksum)
+		return IXGBE_ERR_EEPROM_CHECKSUM;
+
 	return status;
 }
 
@@ -484,34 +444,29 @@ static s32 ixgbe_update_eeprom_checksum_
 	s32 status;
 	u16 checksum;
 
-	/*
-	 * Read the first word from the EEPROM. If this times out or fails, do
+	/* Read the first word from the EEPROM. If this times out or fails, do
 	 * not continue or we could be in for a very long wait while every
 	 * EEPROM read fails
 	 */
 	status = hw->eeprom.ops.read(hw, 0, &checksum);
-
-	if (status != 0)
+	if (status) {
 		hw_dbg(hw, "EEPROM read failed\n");
+		return status;
+	}
 
-	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
-		checksum = hw->eeprom.ops.calc_checksum(hw);
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+		return  IXGBE_ERR_SWFW_SYNC;
 
-		/*
-		 * Do not use hw->eeprom.ops.write because we do not want to
-		 * take the synchronization semaphores twice here.
-		 */
-		status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
-						  checksum);
+	checksum = hw->eeprom.ops.calc_checksum(hw);
 
-	if (status == 0)
+	/* Do not use hw->eeprom.ops.write because we do not want to
+	 * take the synchronization semaphores twice here.
+	 */
+	status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
+	if (!status)
 		status = ixgbe_update_flash_X540(hw);
-	else
-		status = IXGBE_ERR_SWFW_SYNC;
-	}
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-
 	return status;
 }
 
@@ -525,12 +480,12 @@ static s32 ixgbe_update_eeprom_checksum_
 static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
 {
 	u32 flup;
-	s32 status = IXGBE_ERR_EEPROM;
+	s32 status;
 
 	status = ixgbe_poll_flash_update_done_X540(hw);
 	if (status == IXGBE_ERR_EEPROM) {
 		hw_dbg(hw, "Flash update time out\n");
-		goto out;
+		return status;
 	}
 
 	flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
@@ -556,7 +511,7 @@ static s32 ixgbe_update_flash_X540(struc
 		else
 			hw_dbg(hw, "Flash update time out\n");
 	}
-out:
+
 	return status;
 }
 
@@ -571,17 +526,14 @@ static s32 ixgbe_poll_flash_update_done_
 {
 	u32 i;
 	u32 reg;
-	s32 status = IXGBE_ERR_EEPROM;
 
 	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
 		reg = IXGBE_READ_REG(hw, IXGBE_EEC);
-		if (reg & IXGBE_EEC_FLUDONE) {
-			status = 0;
-			break;
-		}
+		if (reg & IXGBE_EEC_FLUDONE)
+			return 0;
 		udelay(5);
 	}
-	return status;
+	return IXGBE_ERR_EEPROM;
 }
 
 /**
@@ -676,46 +628,44 @@ static void ixgbe_release_swfw_sync_X540
 }
 
 /**
- * ixgbe_get_nvm_semaphore - Get hardware semaphore
+ * ixgbe_get_swfw_sync_semaphore - Get hardware semaphore
  * @hw: pointer to hardware structure
  *
  * Sets the hardware semaphores so SW/FW can gain control of shared resources
- **/
+ */
 static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_EEPROM;
 	u32 timeout = 2000;
 	u32 i;
 	u32 swsm;
 
 	/* Get SMBI software semaphore between device drivers first */
 	for (i = 0; i < timeout; i++) {
-		/*
-		 * If the SMBI bit is 0 when we read it, then the bit will be
+		/* If the SMBI bit is 0 when we read it, then the bit will be
 		 * set and we have the semaphore
 		 */
 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
-		if (!(swsm & IXGBE_SWSM_SMBI)) {
-			status = 0;
+		if (!(swsm & IXGBE_SWSM_SMBI))
 			break;
-		}
-		udelay(50);
+		usleep_range(50, 100);
+	}
+
+	if (i == timeout) {
+		hw_dbg(hw,
+		       "Software semaphore SMBI between device drivers not granted.\n");
+		return IXGBE_ERR_EEPROM;
 	}
 
 	/* Now get the semaphore between SW/FW through the REGSMP bit */
-	if (status) {
-		for (i = 0; i < timeout; i++) {
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
-			if (!(swsm & IXGBE_SWFW_REGSMP))
-				break;
+	for (i = 0; i < timeout; i++) {
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+		if (!(swsm & IXGBE_SWFW_REGSMP))
+			return 0;
 
-			udelay(50);
-		}
-	} else {
-		hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+		usleep_range(50, 100);
 	}
 
-	return status;
+	return IXGBE_ERR_EEPROM;
 }
 
 /**
@@ -811,8 +761,6 @@ static struct ixgbe_mac_operations mac_o
 	.start_hw               = &ixgbe_start_hw_X540,
 	.clear_hw_cntrs         = &ixgbe_clear_hw_cntrs_generic,
 	.get_media_type         = &ixgbe_get_media_type_X540,
-	.get_supported_physical_layer =
-				  &ixgbe_get_supported_physical_layer_X540,
 	.enable_rx_dma          = &ixgbe_enable_rx_dma_generic,
 	.get_mac_addr           = &ixgbe_get_mac_addr_generic,
 	.get_san_mac_addr       = &ixgbe_get_san_mac_addr_generic,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ static const struct ixgbevf_info *ixgbev
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static DEFINE_PCI_DEVICE_TABLE(ixgbevf_pci_tbl) = {
+static const struct pci_device_id ixgbevf_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },
 	/* required last entry */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbevf/vf.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbevf/vf.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/intel/ixgbevf/vf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/intel/ixgbevf/vf.h	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,6 @@ struct ixgbe_mac_operations {
 	s32 (*start_hw)(struct ixgbe_hw *);
 	s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
 	enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
-	u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
 	s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
 	s32 (*stop_adapter)(struct ixgbe_hw *);
 	s32 (*get_bus_info)(struct ixgbe_hw *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/jme.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/jme.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/jme.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/jme.c	2014-09-28 17:29:07.000000000 -0400
@@ -3334,7 +3334,7 @@ static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme
 #define JME_PM_OPS NULL
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
+static const struct pci_device_id jme_pci_tbl[] = {
 	{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) },
 	{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/K
 source "drivers/net/ethernet/alteon/Kconfig"
 source "drivers/net/ethernet/altera/Kconfig"
 source "drivers/net/ethernet/amd/Kconfig"
+source "drivers/net/ethernet/apm/Kconfig"
 source "drivers/net/ethernet/apple/Kconfig"
 source "drivers/net/ethernet/arc/Kconfig"
 source "drivers/net/ethernet/atheros/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += al
 obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
 obj-$(CONFIG_ALTERA_TSE) += altera/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_XGENE) += apm/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
 obj-$(CONFIG_NET_VENDOR_ARC) += arc/
 obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -54,6 +54,14 @@ config MVNETA
 	  driver, which should be used for the older Marvell SoCs
 	  (Dove, Orion, Discovery, Kirkwood).
 
+config MVPP2
+	tristate "Marvell Armada 375 network interface support"
+	depends on MACH_ARMADA_375
+	select MVMDIO
+	---help---
+	  This driver supports the network interface units in the
+	  Marvell ARMADA 375 SoC.
+
 config PXA168_ETH
 	tristate "Marvell pxa168 ethernet support"
 	depends on CPU_PXA168
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MVMDIO) += mvmdio.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
 obj-$(CONFIG_MVNETA) += mvneta.o
+obj-$(CONFIG_MVPP2) += mvpp2.o
 obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/mvneta.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/mvneta.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/mvneta.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/mvneta.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/mbus.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <linux/io.h>
@@ -1371,15 +1372,16 @@ static u32 mvneta_skb_tx_csum(struct mvn
 {
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		int ip_hdr_len = 0;
+		__be16 l3_proto = vlan_get_protocol(skb);
 		u8 l4_proto;
 
-		if (skb->protocol == htons(ETH_P_IP)) {
+		if (l3_proto == htons(ETH_P_IP)) {
 			struct iphdr *ip4h = ip_hdr(skb);
 
 			/* Calculate IPv4 checksum and L4 checksum */
 			ip_hdr_len = ip4h->ihl;
 			l4_proto = ip4h->protocol;
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		} else if (l3_proto == htons(ETH_P_IPV6)) {
 			struct ipv6hdr *ip6h = ipv6_hdr(skb);
 
 			/* Read l4_protocol from one of IPv6 extra headers */
@@ -1390,7 +1392,7 @@ static u32 mvneta_skb_tx_csum(struct mvn
 			return MVNETA_TX_L4_CSUM_NOT;
 
 		return mvneta_txq_desc_csum(skb_network_offset(skb),
-				skb->protocol, ip_hdr_len, l4_proto);
+					    l3_proto, ip_hdr_len, l4_proto);
 	}
 
 	return MVNETA_TX_L4_CSUM_NOT;
@@ -2969,14 +2971,14 @@ static int mvneta_probe(struct platform_
 		/* In the case of a fixed PHY, the DT node associated
 		 * to the PHY is the Ethernet MAC DT node.
 		 */
-		phy_node = dn;
+		phy_node = of_node_get(dn);
 	}
 
 	phy_mode = of_get_phy_mode(dn);
 	if (phy_mode < 0) {
 		dev_err(&pdev->dev, "incorrect phy-mode\n");
 		err = -EINVAL;
-		goto err_free_irq;
+		goto err_put_phy_node;
 	}
 
 	dev->tx_queue_len = MVNETA_MAX_TXD;
@@ -2992,7 +2994,7 @@ static int mvneta_probe(struct platform_
 	pp->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(pp->clk)) {
 		err = PTR_ERR(pp->clk);
-		goto err_free_irq;
+		goto err_put_phy_node;
 	}
 
 	clk_prepare_enable(pp->clk);
@@ -3071,6 +3073,8 @@ err_free_stats:
 	free_percpu(pp->stats);
 err_clk:
 	clk_disable_unprepare(pp->clk);
+err_put_phy_node:
+	of_node_put(phy_node);
 err_free_irq:
 	irq_dispose_mapping(dev->irq);
 err_free_netdev:
@@ -3088,6 +3092,7 @@ static int mvneta_remove(struct platform
 	clk_disable_unprepare(pp->clk);
 	free_percpu(pp->stats);
 	irq_dispose_mapping(dev->irq);
+	of_node_put(pp->phy_node);
 	free_netdev(dev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/mvpp2.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/mvpp2.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/mvpp2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/mvpp2.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6426 @@
+/*
+ * Driver for Marvell PPv2 network controller for Armada 375 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Marcin Wojtas <mw@semihalf.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
+#include <linux/mbus.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <uapi/linux/ppp_defs.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+/* RX Fifo Registers */
+#define MVPP2_RX_DATA_FIFO_SIZE_REG(port)	(0x00 + 4 * (port))
+#define MVPP2_RX_ATTR_FIFO_SIZE_REG(port)	(0x20 + 4 * (port))
+#define MVPP2_RX_MIN_PKT_SIZE_REG		0x60
+#define MVPP2_RX_FIFO_INIT_REG			0x64
+
+/* RX DMA Top Registers */
+#define MVPP2_RX_CTRL_REG(port)			(0x140 + 4 * (port))
+#define     MVPP2_RX_LOW_LATENCY_PKT_SIZE(s)	(((s) & 0xfff) << 16)
+#define     MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK	BIT(31)
+#define MVPP2_POOL_BUF_SIZE_REG(pool)		(0x180 + 4 * (pool))
+#define     MVPP2_POOL_BUF_SIZE_OFFSET		5
+#define MVPP2_RXQ_CONFIG_REG(rxq)		(0x800 + 4 * (rxq))
+#define     MVPP2_SNOOP_PKT_SIZE_MASK		0x1ff
+#define     MVPP2_SNOOP_BUF_HDR_MASK		BIT(9)
+#define     MVPP2_RXQ_POOL_SHORT_OFFS		20
+#define     MVPP2_RXQ_POOL_SHORT_MASK		0x700000
+#define     MVPP2_RXQ_POOL_LONG_OFFS		24
+#define     MVPP2_RXQ_POOL_LONG_MASK		0x7000000
+#define     MVPP2_RXQ_PACKET_OFFSET_OFFS	28
+#define     MVPP2_RXQ_PACKET_OFFSET_MASK	0x70000000
+#define     MVPP2_RXQ_DISABLE_MASK		BIT(31)
+
+/* Parser Registers */
+#define MVPP2_PRS_INIT_LOOKUP_REG		0x1000
+#define     MVPP2_PRS_PORT_LU_MAX		0xf
+#define     MVPP2_PRS_PORT_LU_MASK(port)	(0xff << ((port) * 4))
+#define     MVPP2_PRS_PORT_LU_VAL(port, val)	((val) << ((port) * 4))
+#define MVPP2_PRS_INIT_OFFS_REG(port)		(0x1004 + ((port) & 4))
+#define     MVPP2_PRS_INIT_OFF_MASK(port)	(0x3f << (((port) % 4) * 8))
+#define     MVPP2_PRS_INIT_OFF_VAL(port, val)	((val) << (((port) % 4) * 8))
+#define MVPP2_PRS_MAX_LOOP_REG(port)		(0x100c + ((port) & 4))
+#define     MVPP2_PRS_MAX_LOOP_MASK(port)	(0xff << (((port) % 4) * 8))
+#define     MVPP2_PRS_MAX_LOOP_VAL(port, val)	((val) << (((port) % 4) * 8))
+#define MVPP2_PRS_TCAM_IDX_REG			0x1100
+#define MVPP2_PRS_TCAM_DATA_REG(idx)		(0x1104 + (idx) * 4)
+#define     MVPP2_PRS_TCAM_INV_MASK		BIT(31)
+#define MVPP2_PRS_SRAM_IDX_REG			0x1200
+#define MVPP2_PRS_SRAM_DATA_REG(idx)		(0x1204 + (idx) * 4)
+#define MVPP2_PRS_TCAM_CTRL_REG			0x1230
+#define     MVPP2_PRS_TCAM_EN_MASK		BIT(0)
+
+/* Classifier Registers */
+#define MVPP2_CLS_MODE_REG			0x1800
+#define     MVPP2_CLS_MODE_ACTIVE_MASK		BIT(0)
+#define MVPP2_CLS_PORT_WAY_REG			0x1810
+#define     MVPP2_CLS_PORT_WAY_MASK(port)	(1 << (port))
+#define MVPP2_CLS_LKP_INDEX_REG			0x1814
+#define     MVPP2_CLS_LKP_INDEX_WAY_OFFS	6
+#define MVPP2_CLS_LKP_TBL_REG			0x1818
+#define     MVPP2_CLS_LKP_TBL_RXQ_MASK		0xff
+#define     MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK	BIT(25)
+#define MVPP2_CLS_FLOW_INDEX_REG		0x1820
+#define MVPP2_CLS_FLOW_TBL0_REG			0x1824
+#define MVPP2_CLS_FLOW_TBL1_REG			0x1828
+#define MVPP2_CLS_FLOW_TBL2_REG			0x182c
+#define MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port)	(0x1980 + ((port) * 4))
+#define     MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS	3
+#define     MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK	0x7
+#define MVPP2_CLS_SWFWD_P2HQ_REG(port)		(0x19b0 + ((port) * 4))
+#define MVPP2_CLS_SWFWD_PCTRL_REG		0x19d0
+#define     MVPP2_CLS_SWFWD_PCTRL_MASK(port)	(1 << (port))
+
+/* Descriptor Manager Top Registers */
+#define MVPP2_RXQ_NUM_REG			0x2040
+#define MVPP2_RXQ_DESC_ADDR_REG			0x2044
+#define MVPP2_RXQ_DESC_SIZE_REG			0x2048
+#define     MVPP2_RXQ_DESC_SIZE_MASK		0x3ff0
+#define MVPP2_RXQ_STATUS_UPDATE_REG(rxq)	(0x3000 + 4 * (rxq))
+#define     MVPP2_RXQ_NUM_PROCESSED_OFFSET	0
+#define     MVPP2_RXQ_NUM_NEW_OFFSET		16
+#define MVPP2_RXQ_STATUS_REG(rxq)		(0x3400 + 4 * (rxq))
+#define     MVPP2_RXQ_OCCUPIED_MASK		0x3fff
+#define     MVPP2_RXQ_NON_OCCUPIED_OFFSET	16
+#define     MVPP2_RXQ_NON_OCCUPIED_MASK		0x3fff0000
+#define MVPP2_RXQ_THRESH_REG			0x204c
+#define     MVPP2_OCCUPIED_THRESH_OFFSET	0
+#define     MVPP2_OCCUPIED_THRESH_MASK		0x3fff
+#define MVPP2_RXQ_INDEX_REG			0x2050
+#define MVPP2_TXQ_NUM_REG			0x2080
+#define MVPP2_TXQ_DESC_ADDR_REG			0x2084
+#define MVPP2_TXQ_DESC_SIZE_REG			0x2088
+#define     MVPP2_TXQ_DESC_SIZE_MASK		0x3ff0
+#define MVPP2_AGGR_TXQ_UPDATE_REG		0x2090
+#define MVPP2_TXQ_THRESH_REG			0x2094
+#define     MVPP2_TRANSMITTED_THRESH_OFFSET	16
+#define     MVPP2_TRANSMITTED_THRESH_MASK	0x3fff0000
+#define MVPP2_TXQ_INDEX_REG			0x2098
+#define MVPP2_TXQ_PREF_BUF_REG			0x209c
+#define     MVPP2_PREF_BUF_PTR(desc)		((desc) & 0xfff)
+#define     MVPP2_PREF_BUF_SIZE_4		(BIT(12) | BIT(13))
+#define     MVPP2_PREF_BUF_SIZE_16		(BIT(12) | BIT(14))
+#define     MVPP2_PREF_BUF_THRESH(val)		((val) << 17)
+#define     MVPP2_TXQ_DRAIN_EN_MASK		BIT(31)
+#define MVPP2_TXQ_PENDING_REG			0x20a0
+#define     MVPP2_TXQ_PENDING_MASK		0x3fff
+#define MVPP2_TXQ_INT_STATUS_REG		0x20a4
+#define MVPP2_TXQ_SENT_REG(txq)			(0x3c00 + 4 * (txq))
+#define     MVPP2_TRANSMITTED_COUNT_OFFSET	16
+#define     MVPP2_TRANSMITTED_COUNT_MASK	0x3fff0000
+#define MVPP2_TXQ_RSVD_REQ_REG			0x20b0
+#define     MVPP2_TXQ_RSVD_REQ_Q_OFFSET		16
+#define MVPP2_TXQ_RSVD_RSLT_REG			0x20b4
+#define     MVPP2_TXQ_RSVD_RSLT_MASK		0x3fff
+#define MVPP2_TXQ_RSVD_CLR_REG			0x20b8
+#define     MVPP2_TXQ_RSVD_CLR_OFFSET		16
+#define MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu)	(0x2100 + 4 * (cpu))
+#define MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu)	(0x2140 + 4 * (cpu))
+#define     MVPP2_AGGR_TXQ_DESC_SIZE_MASK	0x3ff0
+#define MVPP2_AGGR_TXQ_STATUS_REG(cpu)		(0x2180 + 4 * (cpu))
+#define     MVPP2_AGGR_TXQ_PENDING_MASK		0x3fff
+#define MVPP2_AGGR_TXQ_INDEX_REG(cpu)		(0x21c0 + 4 * (cpu))
+
+/* MBUS bridge registers */
+#define MVPP2_WIN_BASE(w)			(0x4000 + ((w) << 2))
+#define MVPP2_WIN_SIZE(w)			(0x4020 + ((w) << 2))
+#define MVPP2_WIN_REMAP(w)			(0x4040 + ((w) << 2))
+#define MVPP2_BASE_ADDR_ENABLE			0x4060
+
+/* Interrupt Cause and Mask registers */
+#define MVPP2_ISR_RX_THRESHOLD_REG(rxq)		(0x5200 + 4 * (rxq))
+#define MVPP2_ISR_RXQ_GROUP_REG(rxq)		(0x5400 + 4 * (rxq))
+#define MVPP2_ISR_ENABLE_REG(port)		(0x5420 + 4 * (port))
+#define     MVPP2_ISR_ENABLE_INTERRUPT(mask)	((mask) & 0xffff)
+#define     MVPP2_ISR_DISABLE_INTERRUPT(mask)	(((mask) << 16) & 0xffff0000)
+#define MVPP2_ISR_RX_TX_CAUSE_REG(port)		(0x5480 + 4 * (port))
+#define     MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK	0xffff
+#define     MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK	0xff0000
+#define     MVPP2_CAUSE_RX_FIFO_OVERRUN_MASK	BIT(24)
+#define     MVPP2_CAUSE_FCS_ERR_MASK		BIT(25)
+#define     MVPP2_CAUSE_TX_FIFO_UNDERRUN_MASK	BIT(26)
+#define     MVPP2_CAUSE_TX_EXCEPTION_SUM_MASK	BIT(29)
+#define     MVPP2_CAUSE_RX_EXCEPTION_SUM_MASK	BIT(30)
+#define     MVPP2_CAUSE_MISC_SUM_MASK		BIT(31)
+#define MVPP2_ISR_RX_TX_MASK_REG(port)		(0x54a0 + 4 * (port))
+#define MVPP2_ISR_PON_RX_TX_MASK_REG		0x54bc
+#define     MVPP2_PON_CAUSE_RXQ_OCCUP_DESC_ALL_MASK	0xffff
+#define     MVPP2_PON_CAUSE_TXP_OCCUP_DESC_ALL_MASK	0x3fc00000
+#define     MVPP2_PON_CAUSE_MISC_SUM_MASK		BIT(31)
+#define MVPP2_ISR_MISC_CAUSE_REG		0x55b0
+
+/* Buffer Manager registers */
+#define MVPP2_BM_POOL_BASE_REG(pool)		(0x6000 + ((pool) * 4))
+#define     MVPP2_BM_POOL_BASE_ADDR_MASK	0xfffff80
+#define MVPP2_BM_POOL_SIZE_REG(pool)		(0x6040 + ((pool) * 4))
+#define     MVPP2_BM_POOL_SIZE_MASK		0xfff0
+#define MVPP2_BM_POOL_READ_PTR_REG(pool)	(0x6080 + ((pool) * 4))
+#define     MVPP2_BM_POOL_GET_READ_PTR_MASK	0xfff0
+#define MVPP2_BM_POOL_PTRS_NUM_REG(pool)	(0x60c0 + ((pool) * 4))
+#define     MVPP2_BM_POOL_PTRS_NUM_MASK		0xfff0
+#define MVPP2_BM_BPPI_READ_PTR_REG(pool)	(0x6100 + ((pool) * 4))
+#define MVPP2_BM_BPPI_PTRS_NUM_REG(pool)	(0x6140 + ((pool) * 4))
+#define     MVPP2_BM_BPPI_PTR_NUM_MASK		0x7ff
+#define     MVPP2_BM_BPPI_PREFETCH_FULL_MASK	BIT(16)
+#define MVPP2_BM_POOL_CTRL_REG(pool)		(0x6200 + ((pool) * 4))
+#define     MVPP2_BM_START_MASK			BIT(0)
+#define     MVPP2_BM_STOP_MASK			BIT(1)
+#define     MVPP2_BM_STATE_MASK			BIT(4)
+#define     MVPP2_BM_LOW_THRESH_OFFS		8
+#define     MVPP2_BM_LOW_THRESH_MASK		0x7f00
+#define     MVPP2_BM_LOW_THRESH_VALUE(val)	((val) << \
+						MVPP2_BM_LOW_THRESH_OFFS)
+#define     MVPP2_BM_HIGH_THRESH_OFFS		16
+#define     MVPP2_BM_HIGH_THRESH_MASK		0x7f0000
+#define     MVPP2_BM_HIGH_THRESH_VALUE(val)	((val) << \
+						MVPP2_BM_HIGH_THRESH_OFFS)
+#define MVPP2_BM_INTR_CAUSE_REG(pool)		(0x6240 + ((pool) * 4))
+#define     MVPP2_BM_RELEASED_DELAY_MASK	BIT(0)
+#define     MVPP2_BM_ALLOC_FAILED_MASK		BIT(1)
+#define     MVPP2_BM_BPPE_EMPTY_MASK		BIT(2)
+#define     MVPP2_BM_BPPE_FULL_MASK		BIT(3)
+#define     MVPP2_BM_AVAILABLE_BP_LOW_MASK	BIT(4)
+#define MVPP2_BM_INTR_MASK_REG(pool)		(0x6280 + ((pool) * 4))
+#define MVPP2_BM_PHY_ALLOC_REG(pool)		(0x6400 + ((pool) * 4))
+#define     MVPP2_BM_PHY_ALLOC_GRNTD_MASK	BIT(0)
+#define MVPP2_BM_VIRT_ALLOC_REG			0x6440
+#define MVPP2_BM_PHY_RLS_REG(pool)		(0x6480 + ((pool) * 4))
+#define     MVPP2_BM_PHY_RLS_MC_BUFF_MASK	BIT(0)
+#define     MVPP2_BM_PHY_RLS_PRIO_EN_MASK	BIT(1)
+#define     MVPP2_BM_PHY_RLS_GRNTD_MASK		BIT(2)
+#define MVPP2_BM_VIRT_RLS_REG			0x64c0
+#define MVPP2_BM_MC_RLS_REG			0x64c4
+#define     MVPP2_BM_MC_ID_MASK			0xfff
+#define     MVPP2_BM_FORCE_RELEASE_MASK		BIT(12)
+
+/* TX Scheduler registers */
+#define MVPP2_TXP_SCHED_PORT_INDEX_REG		0x8000
+#define MVPP2_TXP_SCHED_Q_CMD_REG		0x8004
+#define     MVPP2_TXP_SCHED_ENQ_MASK		0xff
+#define     MVPP2_TXP_SCHED_DISQ_OFFSET		8
+#define MVPP2_TXP_SCHED_CMD_1_REG		0x8010
+#define MVPP2_TXP_SCHED_PERIOD_REG		0x8018
+#define MVPP2_TXP_SCHED_MTU_REG			0x801c
+#define     MVPP2_TXP_MTU_MAX			0x7FFFF
+#define MVPP2_TXP_SCHED_REFILL_REG		0x8020
+#define     MVPP2_TXP_REFILL_TOKENS_ALL_MASK	0x7ffff
+#define     MVPP2_TXP_REFILL_PERIOD_ALL_MASK	0x3ff00000
+#define     MVPP2_TXP_REFILL_PERIOD_MASK(v)	((v) << 20)
+#define MVPP2_TXP_SCHED_TOKEN_SIZE_REG		0x8024
+#define     MVPP2_TXP_TOKEN_SIZE_MAX		0xffffffff
+#define MVPP2_TXQ_SCHED_REFILL_REG(q)		(0x8040 + ((q) << 2))
+#define     MVPP2_TXQ_REFILL_TOKENS_ALL_MASK	0x7ffff
+#define     MVPP2_TXQ_REFILL_PERIOD_ALL_MASK	0x3ff00000
+#define     MVPP2_TXQ_REFILL_PERIOD_MASK(v)	((v) << 20)
+#define MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(q)	(0x8060 + ((q) << 2))
+#define     MVPP2_TXQ_TOKEN_SIZE_MAX		0x7fffffff
+#define MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(q)	(0x8080 + ((q) << 2))
+#define     MVPP2_TXQ_TOKEN_CNTR_MAX		0xffffffff
+
+/* TX general registers */
+#define MVPP2_TX_SNOOP_REG			0x8800
+#define MVPP2_TX_PORT_FLUSH_REG			0x8810
+#define     MVPP2_TX_PORT_FLUSH_MASK(port)	(1 << (port))
+
+/* LMS registers */
+#define MVPP2_SRC_ADDR_MIDDLE			0x24
+#define MVPP2_SRC_ADDR_HIGH			0x28
+#define MVPP2_PHY_AN_CFG0_REG			0x34
+#define     MVPP2_PHY_AN_STOP_SMI0_MASK		BIT(7)
+#define MVPP2_MIB_COUNTERS_BASE(port)		(0x1000 + ((port) >> 1) * \
+						0x400 + (port) * 0x400)
+#define     MVPP2_MIB_LATE_COLLISION		0x7c
+#define MVPP2_ISR_SUM_MASK_REG			0x220c
+#define MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG	0x305c
+#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT		0x27
+
+/* Per-port registers */
+#define MVPP2_GMAC_CTRL_0_REG			0x0
+#define      MVPP2_GMAC_PORT_EN_MASK		BIT(0)
+#define      MVPP2_GMAC_MAX_RX_SIZE_OFFS	2
+#define      MVPP2_GMAC_MAX_RX_SIZE_MASK	0x7ffc
+#define      MVPP2_GMAC_MIB_CNTR_EN_MASK	BIT(15)
+#define MVPP2_GMAC_CTRL_1_REG			0x4
+#define      MVPP2_GMAC_PERIODIC_XON_EN_MASK	BIT(1)
+#define      MVPP2_GMAC_GMII_LB_EN_MASK		BIT(5)
+#define      MVPP2_GMAC_PCS_LB_EN_BIT		6
+#define      MVPP2_GMAC_PCS_LB_EN_MASK		BIT(6)
+#define      MVPP2_GMAC_SA_LOW_OFFS		7
+#define MVPP2_GMAC_CTRL_2_REG			0x8
+#define      MVPP2_GMAC_INBAND_AN_MASK		BIT(0)
+#define      MVPP2_GMAC_PCS_ENABLE_MASK		BIT(3)
+#define      MVPP2_GMAC_PORT_RGMII_MASK		BIT(4)
+#define      MVPP2_GMAC_PORT_RESET_MASK		BIT(6)
+#define MVPP2_GMAC_AUTONEG_CONFIG		0xc
+#define      MVPP2_GMAC_FORCE_LINK_DOWN		BIT(0)
+#define      MVPP2_GMAC_FORCE_LINK_PASS		BIT(1)
+#define      MVPP2_GMAC_CONFIG_MII_SPEED	BIT(5)
+#define      MVPP2_GMAC_CONFIG_GMII_SPEED	BIT(6)
+#define      MVPP2_GMAC_AN_SPEED_EN		BIT(7)
+#define      MVPP2_GMAC_FC_ADV_EN		BIT(9)
+#define      MVPP2_GMAC_CONFIG_FULL_DUPLEX	BIT(12)
+#define      MVPP2_GMAC_AN_DUPLEX_EN		BIT(13)
+#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG		0x1c
+#define      MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS	6
+#define      MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK	0x1fc0
+#define      MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v)	(((v) << 6) & \
+					MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+
+#define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK	0xff
+
+/* Descriptor ring Macros */
+#define MVPP2_QUEUE_NEXT_DESC(q, index) \
+	(((index) < (q)->last_desc) ? ((index) + 1) : 0)
+
+/* Various constants */
+
+/* Coalescing */
+#define MVPP2_TXDONE_COAL_PKTS_THRESH	15
+#define MVPP2_RX_COAL_PKTS		32
+#define MVPP2_RX_COAL_USEC		100
+
+/* The two bytes Marvell header. Either contains a special value used
+ * by Marvell switches when a specific hardware mode is enabled (not
+ * supported by this driver) or is filled automatically by zeroes on
+ * the RX side. Those two bytes being at the front of the Ethernet
+ * header, they allow to have the IP header aligned on a 4 bytes
+ * boundary automatically: the hardware skips those two bytes on its
+ * own.
+ */
+#define MVPP2_MH_SIZE			2
+#define MVPP2_ETH_TYPE_LEN		2
+#define MVPP2_PPPOE_HDR_SIZE		8
+#define MVPP2_VLAN_TAG_LEN		4
+
+/* Lbtd 802.3 type */
+#define MVPP2_IP_LBDT_TYPE		0xfffa
+
+#define MVPP2_CPU_D_CACHE_LINE_SIZE	32
+#define MVPP2_TX_CSUM_MAX_SIZE		9800
+
+/* Timeout constants */
+#define MVPP2_TX_DISABLE_TIMEOUT_MSEC	1000
+#define MVPP2_TX_PENDING_TIMEOUT_MSEC	1000
+
+#define MVPP2_TX_MTU_MAX		0x7ffff
+
+/* Maximum number of T-CONTs of PON port */
+#define MVPP2_MAX_TCONT			16
+
+/* Maximum number of supported ports */
+#define MVPP2_MAX_PORTS			4
+
+/* Maximum number of TXQs used by single port */
+#define MVPP2_MAX_TXQ			8
+
+/* Maximum number of RXQs used by single port */
+#define MVPP2_MAX_RXQ			8
+
+/* Dfault number of RXQs in use */
+#define MVPP2_DEFAULT_RXQ		4
+
+/* Total number of RXQs available to all ports */
+#define MVPP2_RXQ_TOTAL_NUM		(MVPP2_MAX_PORTS * MVPP2_MAX_RXQ)
+
+/* Max number of Rx descriptors */
+#define MVPP2_MAX_RXD			128
+
+/* Max number of Tx descriptors */
+#define MVPP2_MAX_TXD			1024
+
+/* Amount of Tx descriptors that can be reserved at once by CPU */
+#define MVPP2_CPU_DESC_CHUNK		64
+
+/* Max number of Tx descriptors in each aggregated queue */
+#define MVPP2_AGGR_TXQ_SIZE		256
+
+/* Descriptor aligned size */
+#define MVPP2_DESC_ALIGNED_SIZE		32
+
+/* Descriptor alignment mask */
+#define MVPP2_TX_DESC_ALIGN		(MVPP2_DESC_ALIGNED_SIZE - 1)
+
+/* RX FIFO constants */
+#define MVPP2_RX_FIFO_PORT_DATA_SIZE	0x2000
+#define MVPP2_RX_FIFO_PORT_ATTR_SIZE	0x80
+#define MVPP2_RX_FIFO_PORT_MIN_PKT	0x80
+
+/* RX buffer constants */
+#define MVPP2_SKB_SHINFO_SIZE \
+	SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
+
+#define MVPP2_RX_PKT_SIZE(mtu) \
+	ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \
+	      ETH_HLEN + ETH_FCS_LEN, MVPP2_CPU_D_CACHE_LINE_SIZE)
+
+#define MVPP2_RX_BUF_SIZE(pkt_size)	((pkt_size) + NET_SKB_PAD)
+#define MVPP2_RX_TOTAL_SIZE(buf_size)	((buf_size) + MVPP2_SKB_SHINFO_SIZE)
+#define MVPP2_RX_MAX_PKT_SIZE(total_size) \
+	((total_size) - NET_SKB_PAD - MVPP2_SKB_SHINFO_SIZE)
+
+#define MVPP2_BIT_TO_BYTE(bit)		((bit) / 8)
+
+/* IPv6 max L3 address size */
+#define MVPP2_MAX_L3_ADDR_SIZE		16
+
+/* Port flags */
+#define MVPP2_F_LOOPBACK		BIT(0)
+
+/* Marvell tag types */
+enum mvpp2_tag_type {
+	MVPP2_TAG_TYPE_NONE = 0,
+	MVPP2_TAG_TYPE_MH   = 1,
+	MVPP2_TAG_TYPE_DSA  = 2,
+	MVPP2_TAG_TYPE_EDSA = 3,
+	MVPP2_TAG_TYPE_VLAN = 4,
+	MVPP2_TAG_TYPE_LAST = 5
+};
+
+/* Parser constants */
+#define MVPP2_PRS_TCAM_SRAM_SIZE	256
+#define MVPP2_PRS_TCAM_WORDS		6
+#define MVPP2_PRS_SRAM_WORDS		4
+#define MVPP2_PRS_FLOW_ID_SIZE		64
+#define MVPP2_PRS_FLOW_ID_MASK		0x3f
+#define MVPP2_PRS_TCAM_ENTRY_INVALID	1
+#define MVPP2_PRS_TCAM_DSA_TAGGED_BIT	BIT(5)
+#define MVPP2_PRS_IPV4_HEAD		0x40
+#define MVPP2_PRS_IPV4_HEAD_MASK	0xf0
+#define MVPP2_PRS_IPV4_MC		0xe0
+#define MVPP2_PRS_IPV4_MC_MASK		0xf0
+#define MVPP2_PRS_IPV4_BC_MASK		0xff
+#define MVPP2_PRS_IPV4_IHL		0x5
+#define MVPP2_PRS_IPV4_IHL_MASK		0xf
+#define MVPP2_PRS_IPV6_MC		0xff
+#define MVPP2_PRS_IPV6_MC_MASK		0xff
+#define MVPP2_PRS_IPV6_HOP_MASK		0xff
+#define MVPP2_PRS_TCAM_PROTO_MASK	0xff
+#define MVPP2_PRS_TCAM_PROTO_MASK_L	0x3f
+#define MVPP2_PRS_DBL_VLANS_MAX		100
+
+/* Tcam structure:
+ * - lookup ID - 4 bits
+ * - port ID - 1 byte
+ * - additional information - 1 byte
+ * - header data - 8 bytes
+ * The fields are represented by MVPP2_PRS_TCAM_DATA_REG(5)->(0).
+ */
+#define MVPP2_PRS_AI_BITS			8
+#define MVPP2_PRS_PORT_MASK			0xff
+#define MVPP2_PRS_LU_MASK			0xf
+#define MVPP2_PRS_TCAM_DATA_BYTE(offs)		\
+				    (((offs) - ((offs) % 2)) * 2 + ((offs) % 2))
+#define MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)	\
+					      (((offs) * 2) - ((offs) % 2)  + 2)
+#define MVPP2_PRS_TCAM_AI_BYTE			16
+#define MVPP2_PRS_TCAM_PORT_BYTE		17
+#define MVPP2_PRS_TCAM_LU_BYTE			20
+#define MVPP2_PRS_TCAM_EN_OFFS(offs)		((offs) + 2)
+#define MVPP2_PRS_TCAM_INV_WORD			5
+/* Tcam entries ID */
+#define MVPP2_PE_DROP_ALL		0
+#define MVPP2_PE_FIRST_FREE_TID		1
+#define MVPP2_PE_LAST_FREE_TID		(MVPP2_PRS_TCAM_SRAM_SIZE - 31)
+#define MVPP2_PE_IP6_EXT_PROTO_UN	(MVPP2_PRS_TCAM_SRAM_SIZE - 30)
+#define MVPP2_PE_MAC_MC_IP6		(MVPP2_PRS_TCAM_SRAM_SIZE - 29)
+#define MVPP2_PE_IP6_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 28)
+#define MVPP2_PE_IP4_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 27)
+#define MVPP2_PE_LAST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 26)
+#define MVPP2_PE_FIRST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 19)
+#define MVPP2_PE_EDSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 18)
+#define MVPP2_PE_EDSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 17)
+#define MVPP2_PE_DSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 16)
+#define MVPP2_PE_DSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 15)
+#define MVPP2_PE_ETYPE_EDSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 14)
+#define MVPP2_PE_ETYPE_EDSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 13)
+#define MVPP2_PE_ETYPE_DSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 12)
+#define MVPP2_PE_ETYPE_DSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 11)
+#define MVPP2_PE_MH_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 10)
+#define MVPP2_PE_DSA_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 9)
+#define MVPP2_PE_IP6_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 8)
+#define MVPP2_PE_IP4_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
+#define MVPP2_PE_ETH_TYPE_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
+#define MVPP2_PE_VLAN_DBL		(MVPP2_PRS_TCAM_SRAM_SIZE - 5)
+#define MVPP2_PE_VLAN_NONE		(MVPP2_PRS_TCAM_SRAM_SIZE - 4)
+#define MVPP2_PE_MAC_MC_ALL		(MVPP2_PRS_TCAM_SRAM_SIZE - 3)
+#define MVPP2_PE_MAC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 2)
+#define MVPP2_PE_MAC_NON_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+
+/* Sram structure
+ * The fields are represented by MVPP2_PRS_TCAM_DATA_REG(3)->(0).
+ */
+#define MVPP2_PRS_SRAM_RI_OFFS			0
+#define MVPP2_PRS_SRAM_RI_WORD			0
+#define MVPP2_PRS_SRAM_RI_CTRL_OFFS		32
+#define MVPP2_PRS_SRAM_RI_CTRL_WORD		1
+#define MVPP2_PRS_SRAM_RI_CTRL_BITS		32
+#define MVPP2_PRS_SRAM_SHIFT_OFFS		64
+#define MVPP2_PRS_SRAM_SHIFT_SIGN_BIT		72
+#define MVPP2_PRS_SRAM_UDF_OFFS			73
+#define MVPP2_PRS_SRAM_UDF_BITS			8
+#define MVPP2_PRS_SRAM_UDF_MASK			0xff
+#define MVPP2_PRS_SRAM_UDF_SIGN_BIT		81
+#define MVPP2_PRS_SRAM_UDF_TYPE_OFFS		82
+#define MVPP2_PRS_SRAM_UDF_TYPE_MASK		0x7
+#define MVPP2_PRS_SRAM_UDF_TYPE_L3		1
+#define MVPP2_PRS_SRAM_UDF_TYPE_L4		4
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS	85
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_MASK	0x3
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD		1
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_IP4_ADD	2
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_IP6_ADD	3
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS		87
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_BITS		2
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_MASK		0x3
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_ADD		0
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_IP4_ADD	2
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_IP6_ADD	3
+#define MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS		89
+#define MVPP2_PRS_SRAM_AI_OFFS			90
+#define MVPP2_PRS_SRAM_AI_CTRL_OFFS		98
+#define MVPP2_PRS_SRAM_AI_CTRL_BITS		8
+#define MVPP2_PRS_SRAM_AI_MASK			0xff
+#define MVPP2_PRS_SRAM_NEXT_LU_OFFS		106
+#define MVPP2_PRS_SRAM_NEXT_LU_MASK		0xf
+#define MVPP2_PRS_SRAM_LU_DONE_BIT		110
+#define MVPP2_PRS_SRAM_LU_GEN_BIT		111
+
+/* Sram result info bits assignment */
+#define MVPP2_PRS_RI_MAC_ME_MASK		0x1
+#define MVPP2_PRS_RI_DSA_MASK			0x2
+#define MVPP2_PRS_RI_VLAN_MASK			0xc
+#define MVPP2_PRS_RI_VLAN_NONE			~(BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_VLAN_SINGLE		BIT(2)
+#define MVPP2_PRS_RI_VLAN_DOUBLE		BIT(3)
+#define MVPP2_PRS_RI_VLAN_TRIPLE		(BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_CPU_CODE_MASK		0x70
+#define MVPP2_PRS_RI_CPU_CODE_RX_SPEC		BIT(4)
+#define MVPP2_PRS_RI_L2_CAST_MASK		0x600
+#define MVPP2_PRS_RI_L2_UCAST			~(BIT(9) | BIT(10))
+#define MVPP2_PRS_RI_L2_MCAST			BIT(9)
+#define MVPP2_PRS_RI_L2_BCAST			BIT(10)
+#define MVPP2_PRS_RI_PPPOE_MASK			0x800
+#define MVPP2_PRS_RI_L3_PROTO_MASK		0x7000
+#define MVPP2_PRS_RI_L3_UN			~(BIT(12) | BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_IP4			BIT(12)
+#define MVPP2_PRS_RI_L3_IP4_OPT			BIT(13)
+#define MVPP2_PRS_RI_L3_IP4_OTHER		(BIT(12) | BIT(13))
+#define MVPP2_PRS_RI_L3_IP6			BIT(14)
+#define MVPP2_PRS_RI_L3_IP6_EXT			(BIT(12) | BIT(14))
+#define MVPP2_PRS_RI_L3_ARP			(BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_ADDR_MASK		0x18000
+#define MVPP2_PRS_RI_L3_UCAST			~(BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_L3_MCAST			BIT(15)
+#define MVPP2_PRS_RI_L3_BCAST			(BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_IP_FRAG_MASK		0x20000
+#define MVPP2_PRS_RI_UDF3_MASK			0x300000
+#define MVPP2_PRS_RI_UDF3_RX_SPECIAL		BIT(21)
+#define MVPP2_PRS_RI_L4_PROTO_MASK		0x1c00000
+#define MVPP2_PRS_RI_L4_TCP			BIT(22)
+#define MVPP2_PRS_RI_L4_UDP			BIT(23)
+#define MVPP2_PRS_RI_L4_OTHER			(BIT(22) | BIT(23))
+#define MVPP2_PRS_RI_UDF7_MASK			0x60000000
+#define MVPP2_PRS_RI_UDF7_IP6_LITE		BIT(29)
+#define MVPP2_PRS_RI_DROP_MASK			0x80000000
+
+/* Sram additional info bits assignment */
+#define MVPP2_PRS_IPV4_DIP_AI_BIT		BIT(0)
+#define MVPP2_PRS_IPV6_NO_EXT_AI_BIT		BIT(0)
+#define MVPP2_PRS_IPV6_EXT_AI_BIT		BIT(1)
+#define MVPP2_PRS_IPV6_EXT_AH_AI_BIT		BIT(2)
+#define MVPP2_PRS_IPV6_EXT_AH_LEN_AI_BIT	BIT(3)
+#define MVPP2_PRS_IPV6_EXT_AH_L4_AI_BIT		BIT(4)
+#define MVPP2_PRS_SINGLE_VLAN_AI		0
+#define MVPP2_PRS_DBL_VLAN_AI_BIT		BIT(7)
+
+/* DSA/EDSA type */
+#define MVPP2_PRS_TAGGED		true
+#define MVPP2_PRS_UNTAGGED		false
+#define MVPP2_PRS_EDSA			true
+#define MVPP2_PRS_DSA			false
+
+/* MAC entries, shadow udf */
+enum mvpp2_prs_udf {
+	MVPP2_PRS_UDF_MAC_DEF,
+	MVPP2_PRS_UDF_MAC_RANGE,
+	MVPP2_PRS_UDF_L2_DEF,
+	MVPP2_PRS_UDF_L2_DEF_COPY,
+	MVPP2_PRS_UDF_L2_USER,
+};
+
+/* Lookup ID */
+enum mvpp2_prs_lookup {
+	MVPP2_PRS_LU_MH,
+	MVPP2_PRS_LU_MAC,
+	MVPP2_PRS_LU_DSA,
+	MVPP2_PRS_LU_VLAN,
+	MVPP2_PRS_LU_L2,
+	MVPP2_PRS_LU_PPPOE,
+	MVPP2_PRS_LU_IP4,
+	MVPP2_PRS_LU_IP6,
+	MVPP2_PRS_LU_FLOWS,
+	MVPP2_PRS_LU_LAST,
+};
+
+/* L3 cast enum */
+enum mvpp2_prs_l3_cast {
+	MVPP2_PRS_L3_UNI_CAST,
+	MVPP2_PRS_L3_MULTI_CAST,
+	MVPP2_PRS_L3_BROAD_CAST
+};
+
+/* Classifier constants */
+#define MVPP2_CLS_FLOWS_TBL_SIZE	512
+#define MVPP2_CLS_FLOWS_TBL_DATA_WORDS	3
+#define MVPP2_CLS_LKP_TBL_SIZE		64
+
+/* BM constants */
+#define MVPP2_BM_POOLS_NUM		8
+#define MVPP2_BM_LONG_BUF_NUM		1024
+#define MVPP2_BM_SHORT_BUF_NUM		2048
+#define MVPP2_BM_POOL_SIZE_MAX		(16*1024 - MVPP2_BM_POOL_PTR_ALIGN/4)
+#define MVPP2_BM_POOL_PTR_ALIGN		128
+#define MVPP2_BM_SWF_LONG_POOL(port)	((port > 2) ? 2 : port)
+#define MVPP2_BM_SWF_SHORT_POOL		3
+
+/* BM cookie (32 bits) definition */
+#define MVPP2_BM_COOKIE_POOL_OFFS	8
+#define MVPP2_BM_COOKIE_CPU_OFFS	24
+
+/* BM short pool packet size
+ * These value assure that for SWF the total number
+ * of bytes allocated for each buffer will be 512
+ */
+#define MVPP2_BM_SHORT_PKT_SIZE		MVPP2_RX_MAX_PKT_SIZE(512)
+
+enum mvpp2_bm_type {
+	MVPP2_BM_FREE,
+	MVPP2_BM_SWF_LONG,
+	MVPP2_BM_SWF_SHORT
+};
+
+/* Definitions */
+
+/* Shared Packet Processor resources */
+struct mvpp2 {
+	/* Shared registers' base addresses */
+	void __iomem *base;
+	void __iomem *lms_base;
+
+	/* Common clocks */
+	struct clk *pp_clk;
+	struct clk *gop_clk;
+
+	/* List of pointers to port structures */
+	struct mvpp2_port **port_list;
+
+	/* Aggregated TXQs */
+	struct mvpp2_tx_queue *aggr_txqs;
+
+	/* BM pools */
+	struct mvpp2_bm_pool *bm_pools;
+
+	/* PRS shadow table */
+	struct mvpp2_prs_shadow *prs_shadow;
+	/* PRS auxiliary table for double vlan entries control */
+	bool *prs_double_vlans;
+
+	/* Tclk value */
+	u32 tclk;
+};
+
+struct mvpp2_pcpu_stats {
+	struct	u64_stats_sync syncp;
+	u64	rx_packets;
+	u64	rx_bytes;
+	u64	tx_packets;
+	u64	tx_bytes;
+};
+
+struct mvpp2_port {
+	u8 id;
+
+	int irq;
+
+	struct mvpp2 *priv;
+
+	/* Per-port registers' base address */
+	void __iomem *base;
+
+	struct mvpp2_rx_queue **rxqs;
+	struct mvpp2_tx_queue **txqs;
+	struct net_device *dev;
+
+	int pkt_size;
+
+	u32 pending_cause_rx;
+	struct napi_struct napi;
+
+	/* Flags */
+	unsigned long flags;
+
+	u16 tx_ring_size;
+	u16 rx_ring_size;
+	struct mvpp2_pcpu_stats __percpu *stats;
+
+	struct phy_device *phy_dev;
+	phy_interface_t phy_interface;
+	struct device_node *phy_node;
+	unsigned int link;
+	unsigned int duplex;
+	unsigned int speed;
+
+	struct mvpp2_bm_pool *pool_long;
+	struct mvpp2_bm_pool *pool_short;
+
+	/* Index of first port's physical RXQ */
+	u8 first_rxq;
+};
+
+/* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
+ * layout of the transmit and reception DMA descriptors, and their
+ * layout is therefore defined by the hardware design
+ */
+
+#define MVPP2_TXD_L3_OFF_SHIFT		0
+#define MVPP2_TXD_IP_HLEN_SHIFT		8
+#define MVPP2_TXD_L4_CSUM_FRAG		BIT(13)
+#define MVPP2_TXD_L4_CSUM_NOT		BIT(14)
+#define MVPP2_TXD_IP_CSUM_DISABLE	BIT(15)
+#define MVPP2_TXD_PADDING_DISABLE	BIT(23)
+#define MVPP2_TXD_L4_UDP		BIT(24)
+#define MVPP2_TXD_L3_IP6		BIT(26)
+#define MVPP2_TXD_L_DESC		BIT(28)
+#define MVPP2_TXD_F_DESC		BIT(29)
+
+#define MVPP2_RXD_ERR_SUMMARY		BIT(15)
+#define MVPP2_RXD_ERR_CODE_MASK		(BIT(13) | BIT(14))
+#define MVPP2_RXD_ERR_CRC		0x0
+#define MVPP2_RXD_ERR_OVERRUN		BIT(13)
+#define MVPP2_RXD_ERR_RESOURCE		(BIT(13) | BIT(14))
+#define MVPP2_RXD_BM_POOL_ID_OFFS	16
+#define MVPP2_RXD_BM_POOL_ID_MASK	(BIT(16) | BIT(17) | BIT(18))
+#define MVPP2_RXD_HWF_SYNC		BIT(21)
+#define MVPP2_RXD_L4_CSUM_OK		BIT(22)
+#define MVPP2_RXD_IP4_HEADER_ERR	BIT(24)
+#define MVPP2_RXD_L4_TCP		BIT(25)
+#define MVPP2_RXD_L4_UDP		BIT(26)
+#define MVPP2_RXD_L3_IP4		BIT(28)
+#define MVPP2_RXD_L3_IP6		BIT(30)
+#define MVPP2_RXD_BUF_HDR		BIT(31)
+
+struct mvpp2_tx_desc {
+	u32 command;		/* Options used by HW for packet transmitting.*/
+	u8  packet_offset;	/* the offset from the buffer beginning	*/
+	u8  phys_txq;		/* destination queue ID			*/
+	u16 data_size;		/* data size of transmitted packet in bytes */
+	u32 buf_phys_addr;	/* physical addr of transmitted buffer	*/
+	u32 buf_cookie;		/* cookie for access to TX buffer in tx path */
+	u32 reserved1[3];	/* hw_cmd (for future use, BM, PON, PNC) */
+	u32 reserved2;		/* reserved (for future use)		*/
+};
+
+struct mvpp2_rx_desc {
+	u32 status;		/* info about received packet		*/
+	u16 reserved1;		/* parser_info (for future use, PnC)	*/
+	u16 data_size;		/* size of received packet in bytes	*/
+	u32 buf_phys_addr;	/* physical address of the buffer	*/
+	u32 buf_cookie;		/* cookie for access to RX buffer in rx path */
+	u16 reserved2;		/* gem_port_id (for future use, PON)	*/
+	u16 reserved3;		/* csum_l4 (for future use, PnC)	*/
+	u8  reserved4;		/* bm_qset (for future use, BM)		*/
+	u8  reserved5;
+	u16 reserved6;		/* classify_info (for future use, PnC)	*/
+	u32 reserved7;		/* flow_id (for future use, PnC) */
+	u32 reserved8;
+};
+
+/* Per-CPU Tx queue control */
+struct mvpp2_txq_pcpu {
+	int cpu;
+
+	/* Number of Tx DMA descriptors in the descriptor ring */
+	int size;
+
+	/* Number of currently used Tx DMA descriptor in the
+	 * descriptor ring
+	 */
+	int count;
+
+	/* Number of Tx DMA descriptors reserved for each CPU */
+	int reserved_num;
+
+	/* Array of transmitted skb */
+	struct sk_buff **tx_skb;
+
+	/* Index of last TX DMA descriptor that was inserted */
+	int txq_put_index;
+
+	/* Index of the TX DMA descriptor to be cleaned up */
+	int txq_get_index;
+};
+
+struct mvpp2_tx_queue {
+	/* Physical number of this Tx queue */
+	u8 id;
+
+	/* Logical number of this Tx queue */
+	u8 log_id;
+
+	/* Number of Tx DMA descriptors in the descriptor ring */
+	int size;
+
+	/* Number of currently used Tx DMA descriptor in the descriptor ring */
+	int count;
+
+	/* Per-CPU control of physical Tx queues */
+	struct mvpp2_txq_pcpu __percpu *pcpu;
+
+	/* Array of transmitted skb */
+	struct sk_buff **tx_skb;
+
+	u32 done_pkts_coal;
+
+	/* Virtual address of thex Tx DMA descriptors array */
+	struct mvpp2_tx_desc *descs;
+
+	/* DMA address of the Tx DMA descriptors array */
+	dma_addr_t descs_phys;
+
+	/* Index of the last Tx DMA descriptor */
+	int last_desc;
+
+	/* Index of the next Tx DMA descriptor to process */
+	int next_desc_to_proc;
+};
+
+struct mvpp2_rx_queue {
+	/* RX queue number, in the range 0-31 for physical RXQs */
+	u8 id;
+
+	/* Num of rx descriptors in the rx descriptor ring */
+	int size;
+
+	u32 pkts_coal;
+	u32 time_coal;
+
+	/* Virtual address of the RX DMA descriptors array */
+	struct mvpp2_rx_desc *descs;
+
+	/* DMA address of the RX DMA descriptors array */
+	dma_addr_t descs_phys;
+
+	/* Index of the last RX DMA descriptor */
+	int last_desc;
+
+	/* Index of the next RX DMA descriptor to process */
+	int next_desc_to_proc;
+
+	/* ID of port to which physical RXQ is mapped */
+	int port;
+
+	/* Port's logic RXQ number to which physical RXQ is mapped */
+	int logic_rxq;
+};
+
+union mvpp2_prs_tcam_entry {
+	u32 word[MVPP2_PRS_TCAM_WORDS];
+	u8  byte[MVPP2_PRS_TCAM_WORDS * 4];
+};
+
+union mvpp2_prs_sram_entry {
+	u32 word[MVPP2_PRS_SRAM_WORDS];
+	u8  byte[MVPP2_PRS_SRAM_WORDS * 4];
+};
+
+struct mvpp2_prs_entry {
+	u32 index;
+	union mvpp2_prs_tcam_entry tcam;
+	union mvpp2_prs_sram_entry sram;
+};
+
+struct mvpp2_prs_shadow {
+	bool valid;
+	bool finish;
+
+	/* Lookup ID */
+	int lu;
+
+	/* User defined offset */
+	int udf;
+
+	/* Result info */
+	u32 ri;
+	u32 ri_mask;
+};
+
+struct mvpp2_cls_flow_entry {
+	u32 index;
+	u32 data[MVPP2_CLS_FLOWS_TBL_DATA_WORDS];
+};
+
+struct mvpp2_cls_lookup_entry {
+	u32 lkpid;
+	u32 way;
+	u32 data;
+};
+
+struct mvpp2_bm_pool {
+	/* Pool number in the range 0-7 */
+	int id;
+	enum mvpp2_bm_type type;
+
+	/* Buffer Pointers Pool External (BPPE) size */
+	int size;
+	/* Number of buffers for this pool */
+	int buf_num;
+	/* Pool buffer size */
+	int buf_size;
+	/* Packet size */
+	int pkt_size;
+
+	/* BPPE virtual base address */
+	u32 *virt_addr;
+	/* BPPE physical base address */
+	dma_addr_t phys_addr;
+
+	/* Ports using BM pool */
+	u32 port_map;
+
+	/* Occupied buffers indicator */
+	atomic_t in_use;
+	int in_use_thresh;
+
+	spinlock_t lock;
+};
+
+struct mvpp2_buff_hdr {
+	u32 next_buff_phys_addr;
+	u32 next_buff_virt_addr;
+	u16 byte_count;
+	u16 info;
+	u8  reserved1;		/* bm_qset (for future use, BM)		*/
+};
+
+/* Buffer header info bits */
+#define MVPP2_B_HDR_INFO_MC_ID_MASK	0xfff
+#define MVPP2_B_HDR_INFO_MC_ID(info)	((info) & MVPP2_B_HDR_INFO_MC_ID_MASK)
+#define MVPP2_B_HDR_INFO_LAST_OFFS	12
+#define MVPP2_B_HDR_INFO_LAST_MASK	BIT(12)
+#define MVPP2_B_HDR_INFO_IS_LAST(info) \
+	   ((info & MVPP2_B_HDR_INFO_LAST_MASK) >> MVPP2_B_HDR_INFO_LAST_OFFS)
+
+/* Static declaractions */
+
+/* Number of RXQs used by single port */
+static int rxq_number = MVPP2_DEFAULT_RXQ;
+/* Number of TXQs used by single port */
+static int txq_number = MVPP2_MAX_TXQ;
+
+#define MVPP2_DRIVER_NAME "mvpp2"
+#define MVPP2_DRIVER_VERSION "1.0"
+
+/* Utility/helper methods */
+
+static void mvpp2_write(struct mvpp2 *priv, u32 offset, u32 data)
+{
+	writel(data, priv->base + offset);
+}
+
+static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)
+{
+	return readl(priv->base + offset);
+}
+
+static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
+{
+	txq_pcpu->txq_get_index++;
+	if (txq_pcpu->txq_get_index == txq_pcpu->size)
+		txq_pcpu->txq_get_index = 0;
+}
+
+static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
+			      struct sk_buff *skb)
+{
+	txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
+	txq_pcpu->txq_put_index++;
+	if (txq_pcpu->txq_put_index == txq_pcpu->size)
+		txq_pcpu->txq_put_index = 0;
+}
+
+/* Get number of physical egress port */
+static inline int mvpp2_egress_port(struct mvpp2_port *port)
+{
+	return MVPP2_MAX_TCONT + port->id;
+}
+
+/* Get number of physical TXQ */
+static inline int mvpp2_txq_phys(int port, int txq)
+{
+	return (MVPP2_MAX_TCONT + port) * MVPP2_MAX_TXQ + txq;
+}
+
+/* Parser configuration routines */
+
+/* Update parser tcam and sram hw entries */
+static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
+{
+	int i;
+
+	if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+		return -EINVAL;
+
+	/* Clear entry invalidation bit */
+	pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] &= ~MVPP2_PRS_TCAM_INV_MASK;
+
+	/* Write tcam index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+	for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+		mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam.word[i]);
+
+	/* Write sram index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index);
+	for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+		mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), pe->sram.word[i]);
+
+	return 0;
+}
+
+/* Read tcam entry from hw */
+static int mvpp2_prs_hw_read(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
+{
+	int i;
+
+	if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+		return -EINVAL;
+
+	/* Write tcam index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+
+	pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] = mvpp2_read(priv,
+			      MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD));
+	if (pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] & MVPP2_PRS_TCAM_INV_MASK)
+		return MVPP2_PRS_TCAM_ENTRY_INVALID;
+
+	for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+		pe->tcam.word[i] = mvpp2_read(priv, MVPP2_PRS_TCAM_DATA_REG(i));
+
+	/* Write sram index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index);
+	for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+		pe->sram.word[i] = mvpp2_read(priv, MVPP2_PRS_SRAM_DATA_REG(i));
+
+	return 0;
+}
+
+/* Invalidate tcam hw entry */
+static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index)
+{
+	/* Write index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, index);
+	mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD),
+		    MVPP2_PRS_TCAM_INV_MASK);
+}
+
+/* Enable shadow table entry and set its lookup ID */
+static void mvpp2_prs_shadow_set(struct mvpp2 *priv, int index, int lu)
+{
+	priv->prs_shadow[index].valid = true;
+	priv->prs_shadow[index].lu = lu;
+}
+
+/* Update ri fields in shadow table entry */
+static void mvpp2_prs_shadow_ri_set(struct mvpp2 *priv, int index,
+				    unsigned int ri, unsigned int ri_mask)
+{
+	priv->prs_shadow[index].ri_mask = ri_mask;
+	priv->prs_shadow[index].ri = ri;
+}
+
+/* Update lookup field in tcam sw entry */
+static void mvpp2_prs_tcam_lu_set(struct mvpp2_prs_entry *pe, unsigned int lu)
+{
+	int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_LU_BYTE);
+
+	pe->tcam.byte[MVPP2_PRS_TCAM_LU_BYTE] = lu;
+	pe->tcam.byte[enable_off] = MVPP2_PRS_LU_MASK;
+}
+
+/* Update mask for single port in tcam sw entry */
+static void mvpp2_prs_tcam_port_set(struct mvpp2_prs_entry *pe,
+				    unsigned int port, bool add)
+{
+	int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+	if (add)
+		pe->tcam.byte[enable_off] &= ~(1 << port);
+	else
+		pe->tcam.byte[enable_off] |= 1 << port;
+}
+
+/* Update port map in tcam sw entry */
+static void mvpp2_prs_tcam_port_map_set(struct mvpp2_prs_entry *pe,
+					unsigned int ports)
+{
+	unsigned char port_mask = MVPP2_PRS_PORT_MASK;
+	int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+	pe->tcam.byte[MVPP2_PRS_TCAM_PORT_BYTE] = 0;
+	pe->tcam.byte[enable_off] &= ~port_mask;
+	pe->tcam.byte[enable_off] |= ~ports & MVPP2_PRS_PORT_MASK;
+}
+
+/* Obtain port map from tcam sw entry */
+static unsigned int mvpp2_prs_tcam_port_map_get(struct mvpp2_prs_entry *pe)
+{
+	int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+	return ~(pe->tcam.byte[enable_off]) & MVPP2_PRS_PORT_MASK;
+}
+
+/* Set byte of data and its enable bits in tcam sw entry */
+static void mvpp2_prs_tcam_data_byte_set(struct mvpp2_prs_entry *pe,
+					 unsigned int offs, unsigned char byte,
+					 unsigned char enable)
+{
+	pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)] = byte;
+	pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)] = enable;
+}
+
+/* Get byte of data and its enable bits from tcam sw entry */
+static void mvpp2_prs_tcam_data_byte_get(struct mvpp2_prs_entry *pe,
+					 unsigned int offs, unsigned char *byte,
+					 unsigned char *enable)
+{
+	*byte = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)];
+	*enable = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)];
+}
+
+/* Compare tcam data bytes with a pattern */
+static bool mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *pe, int offs,
+				    u16 data)
+{
+	int off = MVPP2_PRS_TCAM_DATA_BYTE(offs);
+	u16 tcam_data;
+
+	tcam_data = (8 << pe->tcam.byte[off + 1]) | pe->tcam.byte[off];
+	if (tcam_data != data)
+		return false;
+	return true;
+}
+
+/* Update ai bits in tcam sw entry */
+static void mvpp2_prs_tcam_ai_update(struct mvpp2_prs_entry *pe,
+				     unsigned int bits, unsigned int enable)
+{
+	int i, ai_idx = MVPP2_PRS_TCAM_AI_BYTE;
+
+	for (i = 0; i < MVPP2_PRS_AI_BITS; i++) {
+
+		if (!(enable & BIT(i)))
+			continue;
+
+		if (bits & BIT(i))
+			pe->tcam.byte[ai_idx] |= 1 << i;
+		else
+			pe->tcam.byte[ai_idx] &= ~(1 << i);
+	}
+
+	pe->tcam.byte[MVPP2_PRS_TCAM_EN_OFFS(ai_idx)] |= enable;
+}
+
+/* Get ai bits from tcam sw entry */
+static int mvpp2_prs_tcam_ai_get(struct mvpp2_prs_entry *pe)
+{
+	return pe->tcam.byte[MVPP2_PRS_TCAM_AI_BYTE];
+}
+
+/* Set ethertype in tcam sw entry */
+static void mvpp2_prs_match_etype(struct mvpp2_prs_entry *pe, int offset,
+				  unsigned short ethertype)
+{
+	mvpp2_prs_tcam_data_byte_set(pe, offset + 0, ethertype >> 8, 0xff);
+	mvpp2_prs_tcam_data_byte_set(pe, offset + 1, ethertype & 0xff, 0xff);
+}
+
+/* Set bits in sram sw entry */
+static void mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry *pe, int bit_num,
+				    int val)
+{
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(bit_num)] |= (val << (bit_num % 8));
+}
+
+/* Clear bits in sram sw entry */
+static void mvpp2_prs_sram_bits_clear(struct mvpp2_prs_entry *pe, int bit_num,
+				      int val)
+{
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(bit_num)] &= ~(val << (bit_num % 8));
+}
+
+/* Update ri bits in sram sw entry */
+static void mvpp2_prs_sram_ri_update(struct mvpp2_prs_entry *pe,
+				     unsigned int bits, unsigned int mask)
+{
+	unsigned int i;
+
+	for (i = 0; i < MVPP2_PRS_SRAM_RI_CTRL_BITS; i++) {
+		int ri_off = MVPP2_PRS_SRAM_RI_OFFS;
+
+		if (!(mask & BIT(i)))
+			continue;
+
+		if (bits & BIT(i))
+			mvpp2_prs_sram_bits_set(pe, ri_off + i, 1);
+		else
+			mvpp2_prs_sram_bits_clear(pe, ri_off + i, 1);
+
+		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_RI_CTRL_OFFS + i, 1);
+	}
+}
+
+/* Obtain ri bits from sram sw entry */
+static int mvpp2_prs_sram_ri_get(struct mvpp2_prs_entry *pe)
+{
+	return pe->sram.word[MVPP2_PRS_SRAM_RI_WORD];
+}
+
+/* Update ai bits in sram sw entry */
+static void mvpp2_prs_sram_ai_update(struct mvpp2_prs_entry *pe,
+				     unsigned int bits, unsigned int mask)
+{
+	unsigned int i;
+	int ai_off = MVPP2_PRS_SRAM_AI_OFFS;
+
+	for (i = 0; i < MVPP2_PRS_SRAM_AI_CTRL_BITS; i++) {
+
+		if (!(mask & BIT(i)))
+			continue;
+
+		if (bits & BIT(i))
+			mvpp2_prs_sram_bits_set(pe, ai_off + i, 1);
+		else
+			mvpp2_prs_sram_bits_clear(pe, ai_off + i, 1);
+
+		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_AI_CTRL_OFFS + i, 1);
+	}
+}
+
+/* Read ai bits from sram sw entry */
+static int mvpp2_prs_sram_ai_get(struct mvpp2_prs_entry *pe)
+{
+	u8 bits;
+	int ai_off = MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_AI_OFFS);
+	int ai_en_off = ai_off + 1;
+	int ai_shift = MVPP2_PRS_SRAM_AI_OFFS % 8;
+
+	bits = (pe->sram.byte[ai_off] >> ai_shift) |
+	       (pe->sram.byte[ai_en_off] << (8 - ai_shift));
+
+	return bits;
+}
+
+/* In sram sw entry set lookup ID field of the tcam key to be used in the next
+ * lookup interation
+ */
+static void mvpp2_prs_sram_next_lu_set(struct mvpp2_prs_entry *pe,
+				       unsigned int lu)
+{
+	int sram_next_off = MVPP2_PRS_SRAM_NEXT_LU_OFFS;
+
+	mvpp2_prs_sram_bits_clear(pe, sram_next_off,
+				  MVPP2_PRS_SRAM_NEXT_LU_MASK);
+	mvpp2_prs_sram_bits_set(pe, sram_next_off, lu);
+}
+
+/* In the sram sw entry set sign and value of the next lookup offset
+ * and the offset value generated to the classifier
+ */
+static void mvpp2_prs_sram_shift_set(struct mvpp2_prs_entry *pe, int shift,
+				     unsigned int op)
+{
+	/* Set sign */
+	if (shift < 0) {
+		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
+		shift = 0 - shift;
+	} else {
+		mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
+	}
+
+	/* Set value */
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_SHIFT_OFFS)] =
+							   (unsigned char)shift;
+
+	/* Reset and set operation */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS,
+				  MVPP2_PRS_SRAM_OP_SEL_SHIFT_MASK);
+	mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS, op);
+
+	/* Set base offset as current */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
+}
+
+/* In the sram sw entry set sign and value of the user defined offset
+ * generated to the classifier
+ */
+static void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe,
+				      unsigned int type, int offset,
+				      unsigned int op)
+{
+	/* Set sign */
+	if (offset < 0) {
+		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
+		offset = 0 - offset;
+	} else {
+		mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
+	}
+
+	/* Set value */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_OFFS,
+				  MVPP2_PRS_SRAM_UDF_MASK);
+	mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_OFFS, offset);
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_UDF_OFFS +
+					MVPP2_PRS_SRAM_UDF_BITS)] &=
+	      ~(MVPP2_PRS_SRAM_UDF_MASK >> (8 - (MVPP2_PRS_SRAM_UDF_OFFS % 8)));
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_UDF_OFFS +
+					MVPP2_PRS_SRAM_UDF_BITS)] |=
+				(offset >> (8 - (MVPP2_PRS_SRAM_UDF_OFFS % 8)));
+
+	/* Set offset type */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS,
+				  MVPP2_PRS_SRAM_UDF_TYPE_MASK);
+	mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS, type);
+
+	/* Set offset operation */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_MASK);
+	mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS, op);
+
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS +
+					MVPP2_PRS_SRAM_OP_SEL_UDF_BITS)] &=
+					     ~(MVPP2_PRS_SRAM_OP_SEL_UDF_MASK >>
+				    (8 - (MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS % 8)));
+
+	pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS +
+					MVPP2_PRS_SRAM_OP_SEL_UDF_BITS)] |=
+			     (op >> (8 - (MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS % 8)));
+
+	/* Set base offset as current */
+	mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
+}
+
+/* Find parser flow entry */
+static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid;
+
+	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+	if (!pe)
+		return NULL;
+	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+
+	/* Go through the all entires with MVPP2_PRS_LU_FLOWS */
+	for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
+		u8 bits;
+
+		if (!priv->prs_shadow[tid].valid ||
+		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
+			continue;
+
+		pe->index = tid;
+		mvpp2_prs_hw_read(priv, pe);
+		bits = mvpp2_prs_sram_ai_get(pe);
+
+		/* Sram store classification lookup ID in AI bits [5:0] */
+		if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
+			return pe;
+	}
+	kfree(pe);
+
+	return NULL;
+}
+
+/* Return first free tcam index, seeking from start to end */
+static int mvpp2_prs_tcam_first_free(struct mvpp2 *priv, unsigned char start,
+				     unsigned char end)
+{
+	int tid;
+
+	if (start > end)
+		swap(start, end);
+
+	if (end >= MVPP2_PRS_TCAM_SRAM_SIZE)
+		end = MVPP2_PRS_TCAM_SRAM_SIZE - 1;
+
+	for (tid = start; tid <= end; tid++) {
+		if (!priv->prs_shadow[tid].valid)
+			return tid;
+	}
+
+	return -EINVAL;
+}
+
+/* Enable/disable dropping all mac da's */
+static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
+{
+	struct mvpp2_prs_entry pe;
+
+	if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
+		/* Entry exist - update port only */
+		pe.index = MVPP2_PE_DROP_ALL;
+		mvpp2_prs_hw_read(priv, &pe);
+	} else {
+		/* Entry doesn't exist - create new */
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+		pe.index = MVPP2_PE_DROP_ALL;
+
+		/* Non-promiscuous mode for all ports - DROP unknown packets */
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
+					 MVPP2_PRS_RI_DROP_MASK);
+
+		mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(&pe, 0);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(&pe, port, add);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set port to promiscuous mode */
+static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, bool add)
+{
+	struct mvpp2_prs_entry pe;
+
+	/* Promiscous mode - Accept unknown packets */
+
+	if (priv->prs_shadow[MVPP2_PE_MAC_PROMISCUOUS].valid) {
+		/* Entry exist - update port only */
+		pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+		mvpp2_prs_hw_read(priv, &pe);
+	} else {
+		/* Entry doesn't exist - create new */
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+		pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+
+		/* Continue - set next lookup */
+		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+
+		/* Set result info bits */
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_UCAST,
+					 MVPP2_PRS_RI_L2_CAST_MASK);
+
+		/* Shift to ethertype */
+		mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(&pe, port, add);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Accept multicast */
+static void mvpp2_prs_mac_multi_set(struct mvpp2 *priv, int port, int index,
+				    bool add)
+{
+	struct mvpp2_prs_entry pe;
+	unsigned char da_mc;
+
+	/* Ethernet multicast address first byte is
+	 * 0x01 for IPv4 and 0x33 for IPv6
+	 */
+	da_mc = (index == MVPP2_PE_MAC_MC_ALL) ? 0x01 : 0x33;
+
+	if (priv->prs_shadow[index].valid) {
+		/* Entry exist - update port only */
+		pe.index = index;
+		mvpp2_prs_hw_read(priv, &pe);
+	} else {
+		/* Entry doesn't exist - create new */
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+		pe.index = index;
+
+		/* Continue - set next lookup */
+		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+
+		/* Set result info bits */
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_MCAST,
+					 MVPP2_PRS_RI_L2_CAST_MASK);
+
+		/* Update tcam entry data first byte */
+		mvpp2_prs_tcam_data_byte_set(&pe, 0, da_mc, 0xff);
+
+		/* Shift to ethertype */
+		mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(&pe, port, add);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set entry for dsa packets */
+static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
+				  bool tagged, bool extend)
+{
+	struct mvpp2_prs_entry pe;
+	int tid, shift;
+
+	if (extend) {
+		tid = tagged ? MVPP2_PE_EDSA_TAGGED : MVPP2_PE_EDSA_UNTAGGED;
+		shift = 8;
+	} else {
+		tid = tagged ? MVPP2_PE_DSA_TAGGED : MVPP2_PE_DSA_UNTAGGED;
+		shift = 4;
+	}
+
+	if (priv->prs_shadow[tid].valid) {
+		/* Entry exist - update port only */
+		pe.index = tid;
+		mvpp2_prs_hw_read(priv, &pe);
+	} else {
+		/* Entry doesn't exist - create new */
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+		pe.index = tid;
+
+		/* Shift 4 bytes if DSA tag or 8 bytes in case of EDSA tag*/
+		mvpp2_prs_sram_shift_set(&pe, shift,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_DSA);
+
+		if (tagged) {
+			/* Set tagged bit in DSA tag */
+			mvpp2_prs_tcam_data_byte_set(&pe, 0,
+						     MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
+						     MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
+			/* Clear all ai bits for next iteration */
+			mvpp2_prs_sram_ai_update(&pe, 0,
+						 MVPP2_PRS_SRAM_AI_MASK);
+			/* If packet is tagged continue check vlans */
+			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+		} else {
+			/* Set result info bits to 'no vlans' */
+			mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+						 MVPP2_PRS_RI_VLAN_MASK);
+			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+		}
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(&pe, 0);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(&pe, port, add);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set entry for dsa ethertype */
+static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
+					    bool add, bool tagged, bool extend)
+{
+	struct mvpp2_prs_entry pe;
+	int tid, shift, port_mask;
+
+	if (extend) {
+		tid = tagged ? MVPP2_PE_ETYPE_EDSA_TAGGED :
+		      MVPP2_PE_ETYPE_EDSA_UNTAGGED;
+		port_mask = 0;
+		shift = 8;
+	} else {
+		tid = tagged ? MVPP2_PE_ETYPE_DSA_TAGGED :
+		      MVPP2_PE_ETYPE_DSA_UNTAGGED;
+		port_mask = MVPP2_PRS_PORT_MASK;
+		shift = 4;
+	}
+
+	if (priv->prs_shadow[tid].valid) {
+		/* Entry exist - update port only */
+		pe.index = tid;
+		mvpp2_prs_hw_read(priv, &pe);
+	} else {
+		/* Entry doesn't exist - create new */
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+		pe.index = tid;
+
+		/* Set ethertype */
+		mvpp2_prs_match_etype(&pe, 0, ETH_P_EDSA);
+		mvpp2_prs_match_etype(&pe, 2, 0);
+
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DSA_MASK,
+					 MVPP2_PRS_RI_DSA_MASK);
+		/* Shift ethertype + 2 byte reserved + tag*/
+		mvpp2_prs_sram_shift_set(&pe, 2 + MVPP2_ETH_TYPE_LEN + shift,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_DSA);
+
+		if (tagged) {
+			/* Set tagged bit in DSA tag */
+			mvpp2_prs_tcam_data_byte_set(&pe,
+						     MVPP2_ETH_TYPE_LEN + 2 + 3,
+						 MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
+						 MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
+			/* Clear all ai bits for next iteration */
+			mvpp2_prs_sram_ai_update(&pe, 0,
+						 MVPP2_PRS_SRAM_AI_MASK);
+			/* If packet is tagged continue check vlans */
+			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+		} else {
+			/* Set result info bits to 'no vlans' */
+			mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+						 MVPP2_PRS_RI_VLAN_MASK);
+			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+		}
+		/* Mask/unmask all ports, depending on dsa type */
+		mvpp2_prs_tcam_port_map_set(&pe, port_mask);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(&pe, port, add);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Search for existing single/triple vlan entry */
+static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+						   unsigned short tpid, int ai)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid;
+
+	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+	if (!pe)
+		return NULL;
+	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+
+	/* Go through the all entries with MVPP2_PRS_LU_VLAN */
+	for (tid = MVPP2_PE_FIRST_FREE_TID;
+	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+		unsigned int ri_bits, ai_bits;
+		bool match;
+
+		if (!priv->prs_shadow[tid].valid ||
+		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+			continue;
+
+		pe->index = tid;
+
+		mvpp2_prs_hw_read(priv, pe);
+		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
+		if (!match)
+			continue;
+
+		/* Get vlan type */
+		ri_bits = mvpp2_prs_sram_ri_get(pe);
+		ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+
+		/* Get current ai value from tcam */
+		ai_bits = mvpp2_prs_tcam_ai_get(pe);
+		/* Clear double vlan bit */
+		ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
+
+		if (ai != ai_bits)
+			continue;
+
+		if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+		    ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+			return pe;
+	}
+	kfree(pe);
+
+	return NULL;
+}
+
+/* Add/update single/triple vlan entry */
+static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+			      unsigned int port_map)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid_aux, tid;
+
+	pe = mvpp2_prs_vlan_find(priv, tpid, ai);
+
+	if (!pe) {
+		/* Create new tcam entry */
+		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID,
+						MVPP2_PE_FIRST_FREE_TID);
+		if (tid < 0)
+			return tid;
+
+		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+		if (!pe)
+			return -ENOMEM;
+
+		/* Get last double vlan tid */
+		for (tid_aux = MVPP2_PE_LAST_FREE_TID;
+		     tid_aux >= MVPP2_PE_FIRST_FREE_TID; tid_aux--) {
+			unsigned int ri_bits;
+
+			if (!priv->prs_shadow[tid_aux].valid ||
+			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+				continue;
+
+			pe->index = tid_aux;
+			mvpp2_prs_hw_read(priv, pe);
+			ri_bits = mvpp2_prs_sram_ri_get(pe);
+			if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
+			    MVPP2_PRS_RI_VLAN_DOUBLE)
+				break;
+		}
+
+		if (tid <= tid_aux)
+			return -EINVAL;
+
+		memset(pe, 0 , sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+		pe->index = tid;
+
+		mvpp2_prs_match_etype(pe, 0, tpid);
+
+		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_L2);
+		/* Shift 4 bytes - skip 1 vlan tag */
+		mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+		/* Clear all ai bits for next iteration */
+		mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+
+		if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
+			mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
+						 MVPP2_PRS_RI_VLAN_MASK);
+		} else {
+			ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
+			mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
+						 MVPP2_PRS_RI_VLAN_MASK);
+		}
+		mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
+
+		mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+	}
+	/* Update ports' mask */
+	mvpp2_prs_tcam_port_map_set(pe, port_map);
+
+	mvpp2_prs_hw_write(priv, pe);
+
+	kfree(pe);
+
+	return 0;
+}
+
+/* Get first free double vlan ai number */
+static int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2 *priv)
+{
+	int i;
+
+	for (i = 1; i < MVPP2_PRS_DBL_VLANS_MAX; i++) {
+		if (!priv->prs_double_vlans[i])
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+/* Search for existing double vlan entry */
+static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
+							  unsigned short tpid1,
+							  unsigned short tpid2)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid;
+
+	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+	if (!pe)
+		return NULL;
+	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+
+	/* Go through the all entries with MVPP2_PRS_LU_VLAN */
+	for (tid = MVPP2_PE_FIRST_FREE_TID;
+	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+		unsigned int ri_mask;
+		bool match;
+
+		if (!priv->prs_shadow[tid].valid ||
+		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+			continue;
+
+		pe->index = tid;
+		mvpp2_prs_hw_read(priv, pe);
+
+		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
+			&& mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
+
+		if (!match)
+			continue;
+
+		ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
+		if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
+			return pe;
+	}
+	kfree(pe);
+
+	return NULL;
+}
+
+/* Add or update double vlan entry */
+static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+				     unsigned short tpid2,
+				     unsigned int port_map)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid_aux, tid, ai;
+
+	pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
+
+	if (!pe) {
+		/* Create new tcam entry */
+		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+				MVPP2_PE_LAST_FREE_TID);
+		if (tid < 0)
+			return tid;
+
+		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+		if (!pe)
+			return -ENOMEM;
+
+		/* Set ai value for new double vlan entry */
+		ai = mvpp2_prs_double_vlan_ai_free_get(priv);
+		if (ai < 0)
+			return ai;
+
+		/* Get first single/triple vlan tid */
+		for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
+		     tid_aux <= MVPP2_PE_LAST_FREE_TID; tid_aux++) {
+			unsigned int ri_bits;
+
+			if (!priv->prs_shadow[tid_aux].valid ||
+			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+				continue;
+
+			pe->index = tid_aux;
+			mvpp2_prs_hw_read(priv, pe);
+			ri_bits = mvpp2_prs_sram_ri_get(pe);
+			ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+			if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+			    ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+				break;
+		}
+
+		if (tid >= tid_aux)
+			return -ERANGE;
+
+		memset(pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+		pe->index = tid;
+
+		priv->prs_double_vlans[ai] = true;
+
+		mvpp2_prs_match_etype(pe, 0, tpid1);
+		mvpp2_prs_match_etype(pe, 4, tpid2);
+
+		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
+		/* Shift 8 bytes - skip 2 vlan tags */
+		mvpp2_prs_sram_shift_set(pe, 2 * MVPP2_VLAN_TAG_LEN,
+					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+		mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+					 MVPP2_PRS_RI_VLAN_MASK);
+		mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
+					 MVPP2_PRS_SRAM_AI_MASK);
+
+		mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+	}
+
+	/* Update ports' mask */
+	mvpp2_prs_tcam_port_map_set(pe, port_map);
+	mvpp2_prs_hw_write(priv, pe);
+
+	kfree(pe);
+	return 0;
+}
+
+/* IPv4 header parsing for fragmentation and L4 offset */
+static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
+			       unsigned int ri, unsigned int ri_mask)
+{
+	struct mvpp2_prs_entry pe;
+	int tid;
+
+	if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
+	    (proto != IPPROTO_IGMP))
+		return -EINVAL;
+
+	/* Fragmented packet */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	pe.index = tid;
+
+	/* Set next lu to IPv4 */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	/* Set L4 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+				  sizeof(struct iphdr) - 4,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+	mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+				 MVPP2_PRS_IPV4_DIP_AI_BIT);
+	mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_MASK,
+				 ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
+
+	mvpp2_prs_tcam_data_byte_set(&pe, 5, proto, MVPP2_PRS_TCAM_PROTO_MASK);
+	mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Not fragmented packet */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	pe.index = tid;
+	/* Clear ri before updating */
+	pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+	pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+	mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
+
+	mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, MVPP2_PRS_TCAM_PROTO_MASK_L);
+	mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, MVPP2_PRS_TCAM_PROTO_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* IPv4 L3 multicast or broadcast */
+static int mvpp2_prs_ip4_cast(struct mvpp2 *priv, unsigned short l3_cast)
+{
+	struct mvpp2_prs_entry pe;
+	int mask, tid;
+
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	pe.index = tid;
+
+	switch (l3_cast) {
+	case MVPP2_PRS_L3_MULTI_CAST:
+		mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV4_MC,
+					     MVPP2_PRS_IPV4_MC_MASK);
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
+					 MVPP2_PRS_RI_L3_ADDR_MASK);
+		break;
+	case  MVPP2_PRS_L3_BROAD_CAST:
+		mask = MVPP2_PRS_IPV4_BC_MASK;
+		mvpp2_prs_tcam_data_byte_set(&pe, 0, mask, mask);
+		mvpp2_prs_tcam_data_byte_set(&pe, 1, mask, mask);
+		mvpp2_prs_tcam_data_byte_set(&pe, 2, mask, mask);
+		mvpp2_prs_tcam_data_byte_set(&pe, 3, mask, mask);
+		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_BCAST,
+					 MVPP2_PRS_RI_L3_ADDR_MASK);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+				 MVPP2_PRS_IPV4_DIP_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Set entries for protocols over IPv6  */
+static int mvpp2_prs_ip6_proto(struct mvpp2 *priv, unsigned short proto,
+			       unsigned int ri, unsigned int ri_mask)
+{
+	struct mvpp2_prs_entry pe;
+	int tid;
+
+	if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
+	    (proto != IPPROTO_ICMPV6) && (proto != IPPROTO_IPIP))
+		return -EINVAL;
+
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = tid;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+				  sizeof(struct ipv6hdr) - 6,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	mvpp2_prs_tcam_data_byte_set(&pe, 0, proto, MVPP2_PRS_TCAM_PROTO_MASK);
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Write HW */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* IPv6 L3 multicast entry */
+static int mvpp2_prs_ip6_cast(struct mvpp2 *priv, unsigned short l3_cast)
+{
+	struct mvpp2_prs_entry pe;
+	int tid;
+
+	if (l3_cast != MVPP2_PRS_L3_MULTI_CAST)
+		return -EINVAL;
+
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = tid;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
+				 MVPP2_PRS_RI_L3_ADDR_MASK);
+	mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Shift back to IPv6 NH */
+	mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+	mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV6_MC,
+				     MVPP2_PRS_IPV6_MC_MASK);
+	mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Parser per-port initialization */
+static void mvpp2_prs_hw_port_init(struct mvpp2 *priv, int port, int lu_first,
+				   int lu_max, int offset)
+{
+	u32 val;
+
+	/* Set lookup ID */
+	val = mvpp2_read(priv, MVPP2_PRS_INIT_LOOKUP_REG);
+	val &= ~MVPP2_PRS_PORT_LU_MASK(port);
+	val |=  MVPP2_PRS_PORT_LU_VAL(port, lu_first);
+	mvpp2_write(priv, MVPP2_PRS_INIT_LOOKUP_REG, val);
+
+	/* Set maximum number of loops for packet received from port */
+	val = mvpp2_read(priv, MVPP2_PRS_MAX_LOOP_REG(port));
+	val &= ~MVPP2_PRS_MAX_LOOP_MASK(port);
+	val |= MVPP2_PRS_MAX_LOOP_VAL(port, lu_max);
+	mvpp2_write(priv, MVPP2_PRS_MAX_LOOP_REG(port), val);
+
+	/* Set initial offset for packet header extraction for the first
+	 * searching loop
+	 */
+	val = mvpp2_read(priv, MVPP2_PRS_INIT_OFFS_REG(port));
+	val &= ~MVPP2_PRS_INIT_OFF_MASK(port);
+	val |= MVPP2_PRS_INIT_OFF_VAL(port, offset);
+	mvpp2_write(priv, MVPP2_PRS_INIT_OFFS_REG(port), val);
+}
+
+/* Default flow entries initialization for all ports */
+static void mvpp2_prs_def_flow_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int port;
+
+	for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+		memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+		pe.index = MVPP2_PE_FIRST_DEFAULT_FLOW - port;
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+		/* Set flow ID*/
+		mvpp2_prs_sram_ai_update(&pe, port, MVPP2_PRS_FLOW_ID_MASK);
+		mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+
+		/* Update shadow table and hw entry */
+		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_FLOWS);
+		mvpp2_prs_hw_write(priv, &pe);
+	}
+}
+
+/* Set default entry for Marvell Header field */
+static void mvpp2_prs_mh_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+
+	pe.index = MVPP2_PE_MH_DEFAULT;
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MH);
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_MH_SIZE,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MH);
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set default entires (place holder) for promiscuous, non-promiscuous and
+ * multicast MAC addresses
+ */
+static void mvpp2_prs_mac_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+
+	/* Non-promiscuous mode for all ports - DROP unknown packets */
+	pe.index = MVPP2_PE_MAC_NON_PROMISCUOUS;
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
+				 MVPP2_PRS_RI_DROP_MASK);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* place holders only - no ports */
+	mvpp2_prs_mac_drop_all_set(priv, 0, false);
+	mvpp2_prs_mac_promisc_set(priv, 0, false);
+	mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_ALL, 0, false);
+	mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_IP6, 0, false);
+}
+
+/* Set default entries for various types of dsa packets */
+static void mvpp2_prs_dsa_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+
+	/* None tagged EDSA entry - place holder */
+	mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_UNTAGGED,
+			      MVPP2_PRS_EDSA);
+
+	/* Tagged EDSA entry - place holder */
+	mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+
+	/* None tagged DSA entry - place holder */
+	mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_UNTAGGED,
+			      MVPP2_PRS_DSA);
+
+	/* Tagged DSA entry - place holder */
+	mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+
+	/* None tagged EDSA ethertype entry - place holder*/
+	mvpp2_prs_dsa_tag_ethertype_set(priv, 0, false,
+					MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+
+	/* Tagged EDSA ethertype entry - place holder*/
+	mvpp2_prs_dsa_tag_ethertype_set(priv, 0, false,
+					MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+
+	/* None tagged DSA ethertype entry */
+	mvpp2_prs_dsa_tag_ethertype_set(priv, 0, true,
+					MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+
+	/* Tagged DSA ethertype entry */
+	mvpp2_prs_dsa_tag_ethertype_set(priv, 0, true,
+					MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+
+	/* Set default entry, in case DSA or EDSA tag not found */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+	pe.index = MVPP2_PE_DSA_DEFAULT;
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+
+	/* Shift 0 bytes */
+	mvpp2_prs_sram_shift_set(&pe, 0, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+
+	/* Clear all sram ai bits for next iteration */
+	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Match basic ethertypes */
+static int mvpp2_prs_etype_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int tid;
+
+	/* Ethertype: PPPoE */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, ETH_P_PPP_SES);
+
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_PPPOE_HDR_SIZE,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_PPPOE_MASK,
+				 MVPP2_PRS_RI_PPPOE_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = false;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_PPPOE_MASK,
+				MVPP2_PRS_RI_PPPOE_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Ethertype: ARP */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, ETH_P_ARP);
+
+	/* Generate flow in the next iteration*/
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_ARP,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = true;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_ARP,
+				MVPP2_PRS_RI_L3_PROTO_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Ethertype: LBTD */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, MVPP2_IP_LBDT_TYPE);
+
+	/* Generate flow in the next iteration*/
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+				 MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+				 MVPP2_PRS_RI_CPU_CODE_MASK |
+				 MVPP2_PRS_RI_UDF3_MASK);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = true;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+				MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+				MVPP2_PRS_RI_CPU_CODE_MASK |
+				MVPP2_PRS_RI_UDF3_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Ethertype: IPv4 without options */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, ETH_P_IP);
+	mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+				     MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
+				     MVPP2_PRS_IPV4_HEAD_MASK |
+				     MVPP2_PRS_IPV4_IHL_MASK);
+
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Skip eth_type + 4 bytes of IP header */
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = false;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP4,
+				MVPP2_PRS_RI_L3_PROTO_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Ethertype: IPv4 with options */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	pe.index = tid;
+
+	/* Clear tcam data before updating */
+	pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(MVPP2_ETH_TYPE_LEN)] = 0x0;
+	pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(MVPP2_ETH_TYPE_LEN)] = 0x0;
+
+	mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+				     MVPP2_PRS_IPV4_HEAD,
+				     MVPP2_PRS_IPV4_HEAD_MASK);
+
+	/* Clear ri before updating */
+	pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+	pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = false;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP4_OPT,
+				MVPP2_PRS_RI_L3_PROTO_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Ethertype: IPv6 without options */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, ETH_P_IPV6);
+
+	/* Skip DIP of IPV6 header */
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 8 +
+				 MVPP2_MAX_L3_ADDR_SIZE,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = false;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP6,
+				MVPP2_PRS_RI_L3_PROTO_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Default entry for MVPP2_PRS_LU_L2 - Unknown ethtype */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+	pe.index = MVPP2_PE_ETH_TYPE_UN;
+
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Generate flow in the next iteration*/
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Set L3 offset even it's unknown L3 */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+	priv->prs_shadow[pe.index].finish = true;
+	mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_UN,
+				MVPP2_PRS_RI_L3_PROTO_MASK);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Configure vlan entries and detect up to 2 successive VLAN tags.
+ * Possible options:
+ * 0x8100, 0x88A8
+ * 0x8100, 0x8100
+ * 0x8100
+ * 0x88A8
+ */
+static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int err;
+
+	priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool),
+					      MVPP2_PRS_DBL_VLANS_MAX,
+					      GFP_KERNEL);
+	if (!priv->prs_double_vlans)
+		return -ENOMEM;
+
+	/* Double VLAN: 0x8100, 0x88A8 */
+	err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021Q, ETH_P_8021AD,
+					MVPP2_PRS_PORT_MASK);
+	if (err)
+		return err;
+
+	/* Double VLAN: 0x8100, 0x8100 */
+	err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021Q, ETH_P_8021Q,
+					MVPP2_PRS_PORT_MASK);
+	if (err)
+		return err;
+
+	/* Single VLAN: 0x88a8 */
+	err = mvpp2_prs_vlan_add(priv, ETH_P_8021AD, MVPP2_PRS_SINGLE_VLAN_AI,
+				 MVPP2_PRS_PORT_MASK);
+	if (err)
+		return err;
+
+	/* Single VLAN: 0x8100 */
+	err = mvpp2_prs_vlan_add(priv, ETH_P_8021Q, MVPP2_PRS_SINGLE_VLAN_AI,
+				 MVPP2_PRS_PORT_MASK);
+	if (err)
+		return err;
+
+	/* Set default double vlan entry */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+	pe.index = MVPP2_PE_VLAN_DBL;
+
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+	/* Clear ai for next iterations */
+	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+				 MVPP2_PRS_RI_VLAN_MASK);
+
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_DBL_VLAN_AI_BIT,
+				 MVPP2_PRS_DBL_VLAN_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Set default vlan none entry */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+	pe.index = MVPP2_PE_VLAN_NONE;
+
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+				 MVPP2_PRS_RI_VLAN_MASK);
+
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Set entries for PPPoE ethertype */
+static int mvpp2_prs_pppoe_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int tid;
+
+	/* IPv4 over PPPoE with options */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, PPP_IP);
+
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Skip eth_type + 4 bytes of IP header */
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* IPv4 over PPPoE without options */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	pe.index = tid;
+
+	mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+				     MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
+				     MVPP2_PRS_IPV4_HEAD_MASK |
+				     MVPP2_PRS_IPV4_IHL_MASK);
+
+	/* Clear ri before updating */
+	pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+	pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* IPv6 over PPPoE */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+	pe.index = tid;
+
+	mvpp2_prs_match_etype(&pe, 0, PPP_IPV6);
+
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+	/* Skip eth_type + 4 bytes of IPv6 header */
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	/* Set L3 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Non-IP over PPPoE */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+	pe.index = tid;
+
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
+				 MVPP2_PRS_RI_L3_PROTO_MASK);
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	/* Set L3 offset even if it's unknown L3 */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+				  MVPP2_ETH_TYPE_LEN,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Initialize entries for IPv4 */
+static int mvpp2_prs_ip4_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int err;
+
+	/* Set entries for TCP, UDP and IGMP over IPv4 */
+	err = mvpp2_prs_ip4_proto(priv, IPPROTO_TCP, MVPP2_PRS_RI_L4_TCP,
+				  MVPP2_PRS_RI_L4_PROTO_MASK);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip4_proto(priv, IPPROTO_UDP, MVPP2_PRS_RI_L4_UDP,
+				  MVPP2_PRS_RI_L4_PROTO_MASK);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip4_proto(priv, IPPROTO_IGMP,
+				  MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+				  MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+				  MVPP2_PRS_RI_CPU_CODE_MASK |
+				  MVPP2_PRS_RI_UDF3_MASK);
+	if (err)
+		return err;
+
+	/* IPv4 Broadcast */
+	err = mvpp2_prs_ip4_cast(priv, MVPP2_PRS_L3_BROAD_CAST);
+	if (err)
+		return err;
+
+	/* IPv4 Multicast */
+	err = mvpp2_prs_ip4_cast(priv, MVPP2_PRS_L3_MULTI_CAST);
+	if (err)
+		return err;
+
+	/* Default IPv4 entry for unknown protocols */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	pe.index = MVPP2_PE_IP4_PROTO_UN;
+
+	/* Set next lu to IPv4 */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+	/* Set L4 offset */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+				  sizeof(struct iphdr) - 4,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+	mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+				 MVPP2_PRS_IPV4_DIP_AI_BIT);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+				 MVPP2_PRS_RI_L4_PROTO_MASK);
+
+	mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Default IPv4 entry for unicast address */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+	pe.index = MVPP2_PE_IP4_ADDR_UN;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
+				 MVPP2_PRS_RI_L3_ADDR_MASK);
+
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+				 MVPP2_PRS_IPV4_DIP_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Initialize entries for IPv6 */
+static int mvpp2_prs_ip6_init(struct mvpp2 *priv)
+{
+	struct mvpp2_prs_entry pe;
+	int tid, err;
+
+	/* Set entries for TCP, UDP and ICMP over IPv6 */
+	err = mvpp2_prs_ip6_proto(priv, IPPROTO_TCP,
+				  MVPP2_PRS_RI_L4_TCP,
+				  MVPP2_PRS_RI_L4_PROTO_MASK);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip6_proto(priv, IPPROTO_UDP,
+				  MVPP2_PRS_RI_L4_UDP,
+				  MVPP2_PRS_RI_L4_PROTO_MASK);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip6_proto(priv, IPPROTO_ICMPV6,
+				  MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+				  MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+				  MVPP2_PRS_RI_CPU_CODE_MASK |
+				  MVPP2_PRS_RI_UDF3_MASK);
+	if (err)
+		return err;
+
+	/* IPv4 is the last header. This is similar case as 6-TCP or 17-UDP */
+	/* Result Info: UDF7=1, DS lite */
+	err = mvpp2_prs_ip6_proto(priv, IPPROTO_IPIP,
+				  MVPP2_PRS_RI_UDF7_IP6_LITE,
+				  MVPP2_PRS_RI_UDF7_MASK);
+	if (err)
+		return err;
+
+	/* IPv6 multicast */
+	err = mvpp2_prs_ip6_cast(priv, MVPP2_PRS_L3_MULTI_CAST);
+	if (err)
+		return err;
+
+	/* Entry for checking hop limit */
+	tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+					MVPP2_PE_LAST_FREE_TID);
+	if (tid < 0)
+		return tid;
+
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = tid;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN |
+				 MVPP2_PRS_RI_DROP_MASK,
+				 MVPP2_PRS_RI_L3_PROTO_MASK |
+				 MVPP2_PRS_RI_DROP_MASK);
+
+	mvpp2_prs_tcam_data_byte_set(&pe, 1, 0x00, MVPP2_PRS_IPV6_HOP_MASK);
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Default IPv6 entry for unknown protocols */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = MVPP2_PE_IP6_PROTO_UN;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+				 MVPP2_PRS_RI_L4_PROTO_MASK);
+	/* Set L4 offset relatively to our current place */
+	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+				  sizeof(struct ipv6hdr) - 4,
+				  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Default IPv6 entry for unknown ext protocols */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = MVPP2_PE_IP6_EXT_PROTO_UN;
+
+	/* Finished: go to flowid generation */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+				 MVPP2_PRS_RI_L4_PROTO_MASK);
+
+	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_EXT_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	/* Default IPv6 entry for unicast address */
+	memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	pe.index = MVPP2_PE_IP6_ADDR_UN;
+
+	/* Finished: go to IPv6 again */
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
+				 MVPP2_PRS_RI_L3_ADDR_MASK);
+	mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+				 MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Shift back to IPV6 NH */
+	mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+	mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+	/* Unmask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+	mvpp2_prs_hw_write(priv, &pe);
+
+	return 0;
+}
+
+/* Parser default initialization */
+static int mvpp2_prs_default_init(struct platform_device *pdev,
+				  struct mvpp2 *priv)
+{
+	int err, index, i;
+
+	/* Enable tcam table */
+	mvpp2_write(priv, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK);
+
+	/* Clear all tcam and sram entries */
+	for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++) {
+		mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, index);
+		for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+			mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), 0);
+
+		mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, index);
+		for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+			mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), 0);
+	}
+
+	/* Invalidate all tcam entries */
+	for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++)
+		mvpp2_prs_hw_inv(priv, index);
+
+	priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE,
+					sizeof(struct mvpp2_prs_shadow),
+					GFP_KERNEL);
+	if (!priv->prs_shadow)
+		return -ENOMEM;
+
+	/* Always start from lookup = 0 */
+	for (index = 0; index < MVPP2_MAX_PORTS; index++)
+		mvpp2_prs_hw_port_init(priv, index, MVPP2_PRS_LU_MH,
+				       MVPP2_PRS_PORT_LU_MAX, 0);
+
+	mvpp2_prs_def_flow_init(priv);
+
+	mvpp2_prs_mh_init(priv);
+
+	mvpp2_prs_mac_init(priv);
+
+	mvpp2_prs_dsa_init(priv);
+
+	err = mvpp2_prs_etype_init(priv);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_vlan_init(pdev, priv);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_pppoe_init(priv);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip6_init(priv);
+	if (err)
+		return err;
+
+	err = mvpp2_prs_ip4_init(priv);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+/* Compare MAC DA with tcam entry data */
+static bool mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe,
+				       const u8 *da, unsigned char *mask)
+{
+	unsigned char tcam_byte, tcam_mask;
+	int index;
+
+	for (index = 0; index < ETH_ALEN; index++) {
+		mvpp2_prs_tcam_data_byte_get(pe, index, &tcam_byte, &tcam_mask);
+		if (tcam_mask != mask[index])
+			return false;
+
+		if ((tcam_mask & tcam_byte) != (da[index] & mask[index]))
+			return false;
+	}
+
+	return true;
+}
+
+/* Find tcam entry with matched pair <MAC DA, port> */
+static struct mvpp2_prs_entry *
+mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+			    unsigned char *mask, int udf_type)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid;
+
+	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+	if (!pe)
+		return NULL;
+	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+
+	/* Go through the all entires with MVPP2_PRS_LU_MAC */
+	for (tid = MVPP2_PE_FIRST_FREE_TID;
+	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+		unsigned int entry_pmap;
+
+		if (!priv->prs_shadow[tid].valid ||
+		    (priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
+		    (priv->prs_shadow[tid].udf != udf_type))
+			continue;
+
+		pe->index = tid;
+		mvpp2_prs_hw_read(priv, pe);
+		entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
+
+		if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
+		    entry_pmap == pmap)
+			return pe;
+	}
+	kfree(pe);
+
+	return NULL;
+}
+
+/* Update parser's mac da entry */
+static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
+				   const u8 *da, bool add)
+{
+	struct mvpp2_prs_entry *pe;
+	unsigned int pmap, len, ri;
+	unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int tid;
+
+	/* Scan TCAM and see if entry with this <MAC DA, port> already exist */
+	pe = mvpp2_prs_mac_da_range_find(priv, (1 << port), da, mask,
+					 MVPP2_PRS_UDF_MAC_DEF);
+
+	/* No such entry */
+	if (!pe) {
+		if (!add)
+			return 0;
+
+		/* Create new TCAM entry */
+		/* Find first range mac entry*/
+		for (tid = MVPP2_PE_FIRST_FREE_TID;
+		     tid <= MVPP2_PE_LAST_FREE_TID; tid++)
+			if (priv->prs_shadow[tid].valid &&
+			    (priv->prs_shadow[tid].lu == MVPP2_PRS_LU_MAC) &&
+			    (priv->prs_shadow[tid].udf ==
+						       MVPP2_PRS_UDF_MAC_RANGE))
+				break;
+
+		/* Go through the all entries from first to last */
+		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+						tid - 1);
+		if (tid < 0)
+			return tid;
+
+		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+		if (!pe)
+			return -1;
+		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+		pe->index = tid;
+
+		/* Mask all ports */
+		mvpp2_prs_tcam_port_map_set(pe, 0);
+	}
+
+	/* Update port mask */
+	mvpp2_prs_tcam_port_set(pe, port, add);
+
+	/* Invalidate the entry if no ports are left enabled */
+	pmap = mvpp2_prs_tcam_port_map_get(pe);
+	if (pmap == 0) {
+		if (add) {
+			kfree(pe);
+			return -1;
+		}
+		mvpp2_prs_hw_inv(priv, pe->index);
+		priv->prs_shadow[pe->index].valid = false;
+		kfree(pe);
+		return 0;
+	}
+
+	/* Continue - set next lookup */
+	mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_DSA);
+
+	/* Set match on DA */
+	len = ETH_ALEN;
+	while (len--)
+		mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
+
+	/* Set result info bits */
+	if (is_broadcast_ether_addr(da))
+		ri = MVPP2_PRS_RI_L2_BCAST;
+	else if (is_multicast_ether_addr(da))
+		ri = MVPP2_PRS_RI_L2_MCAST;
+	else
+		ri = MVPP2_PRS_RI_L2_UCAST | MVPP2_PRS_RI_MAC_ME_MASK;
+
+	mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+				 MVPP2_PRS_RI_MAC_ME_MASK);
+	mvpp2_prs_shadow_ri_set(priv, pe->index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+				MVPP2_PRS_RI_MAC_ME_MASK);
+
+	/* Shift to ethertype */
+	mvpp2_prs_sram_shift_set(pe, 2 * ETH_ALEN,
+				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+	/* Update shadow table and hw entry */
+	priv->prs_shadow[pe->index].udf = MVPP2_PRS_UDF_MAC_DEF;
+	mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_MAC);
+	mvpp2_prs_hw_write(priv, pe);
+
+	kfree(pe);
+
+	return 0;
+}
+
+static int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int err;
+
+	/* Remove old parser entry */
+	err = mvpp2_prs_mac_da_accept(port->priv, port->id, dev->dev_addr,
+				      false);
+	if (err)
+		return err;
+
+	/* Add new parser entry */
+	err = mvpp2_prs_mac_da_accept(port->priv, port->id, da, true);
+	if (err)
+		return err;
+
+	/* Set addr in the device */
+	ether_addr_copy(dev->dev_addr, da);
+
+	return 0;
+}
+
+/* Delete all port's multicast simple (not range) entries */
+static void mvpp2_prs_mcast_del_all(struct mvpp2 *priv, int port)
+{
+	struct mvpp2_prs_entry pe;
+	int index, tid;
+
+	for (tid = MVPP2_PE_FIRST_FREE_TID;
+	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+		unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
+
+		if (!priv->prs_shadow[tid].valid ||
+		    (priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
+		    (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
+			continue;
+
+		/* Only simple mac entries */
+		pe.index = tid;
+		mvpp2_prs_hw_read(priv, &pe);
+
+		/* Read mac addr from entry */
+		for (index = 0; index < ETH_ALEN; index++)
+			mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
+						     &da_mask[index]);
+
+		if (is_multicast_ether_addr(da) && !is_broadcast_ether_addr(da))
+			/* Delete this entry */
+			mvpp2_prs_mac_da_accept(priv, port, da, false);
+	}
+}
+
+static int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
+{
+	switch (type) {
+	case MVPP2_TAG_TYPE_EDSA:
+		/* Add port to EDSA entries */
+		mvpp2_prs_dsa_tag_set(priv, port, true,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+		mvpp2_prs_dsa_tag_set(priv, port, true,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+		/* Remove port from DSA entries */
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+		break;
+
+	case MVPP2_TAG_TYPE_DSA:
+		/* Add port to DSA entries */
+		mvpp2_prs_dsa_tag_set(priv, port, true,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+		mvpp2_prs_dsa_tag_set(priv, port, true,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+		/* Remove port from EDSA entries */
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+		break;
+
+	case MVPP2_TAG_TYPE_MH:
+	case MVPP2_TAG_TYPE_NONE:
+		/* Remove port form EDSA and DSA entries */
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+		mvpp2_prs_dsa_tag_set(priv, port, false,
+				      MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+		break;
+
+	default:
+		if ((type < 0) || (type > MVPP2_TAG_TYPE_EDSA))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Set prs flow for the port */
+static int mvpp2_prs_def_flow(struct mvpp2_port *port)
+{
+	struct mvpp2_prs_entry *pe;
+	int tid;
+
+	pe = mvpp2_prs_flow_find(port->priv, port->id);
+
+	/* Such entry not exist */
+	if (!pe) {
+		/* Go through the all entires from last to first */
+		tid = mvpp2_prs_tcam_first_free(port->priv,
+						MVPP2_PE_LAST_FREE_TID,
+					       MVPP2_PE_FIRST_FREE_TID);
+		if (tid < 0)
+			return tid;
+
+		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+		if (!pe)
+			return -ENOMEM;
+
+		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+		pe->index = tid;
+
+		/* Set flow ID*/
+		mvpp2_prs_sram_ai_update(pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
+		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+
+		/* Update shadow table */
+		mvpp2_prs_shadow_set(port->priv, pe->index, MVPP2_PRS_LU_FLOWS);
+	}
+
+	mvpp2_prs_tcam_port_map_set(pe, (1 << port->id));
+	mvpp2_prs_hw_write(port->priv, pe);
+	kfree(pe);
+
+	return 0;
+}
+
+/* Classifier configuration routines */
+
+/* Update classification flow table registers */
+static void mvpp2_cls_flow_write(struct mvpp2 *priv,
+				 struct mvpp2_cls_flow_entry *fe)
+{
+	mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
+	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG,  fe->data[0]);
+	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG,  fe->data[1]);
+	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG,  fe->data[2]);
+}
+
+/* Update classification lookup table register */
+static void mvpp2_cls_lookup_write(struct mvpp2 *priv,
+				   struct mvpp2_cls_lookup_entry *le)
+{
+	u32 val;
+
+	val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid;
+	mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val);
+	mvpp2_write(priv, MVPP2_CLS_LKP_TBL_REG, le->data);
+}
+
+/* Classifier default initialization */
+static void mvpp2_cls_init(struct mvpp2 *priv)
+{
+	struct mvpp2_cls_lookup_entry le;
+	struct mvpp2_cls_flow_entry fe;
+	int index;
+
+	/* Enable classifier */
+	mvpp2_write(priv, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK);
+
+	/* Clear classifier flow table */
+	memset(&fe.data, 0, MVPP2_CLS_FLOWS_TBL_DATA_WORDS);
+	for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) {
+		fe.index = index;
+		mvpp2_cls_flow_write(priv, &fe);
+	}
+
+	/* Clear classifier lookup table */
+	le.data = 0;
+	for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) {
+		le.lkpid = index;
+		le.way = 0;
+		mvpp2_cls_lookup_write(priv, &le);
+
+		le.way = 1;
+		mvpp2_cls_lookup_write(priv, &le);
+	}
+}
+
+static void mvpp2_cls_port_config(struct mvpp2_port *port)
+{
+	struct mvpp2_cls_lookup_entry le;
+	u32 val;
+
+	/* Set way for the port */
+	val = mvpp2_read(port->priv, MVPP2_CLS_PORT_WAY_REG);
+	val &= ~MVPP2_CLS_PORT_WAY_MASK(port->id);
+	mvpp2_write(port->priv, MVPP2_CLS_PORT_WAY_REG, val);
+
+	/* Pick the entry to be accessed in lookup ID decoding table
+	 * according to the way and lkpid.
+	 */
+	le.lkpid = port->id;
+	le.way = 0;
+	le.data = 0;
+
+	/* Set initial CPU queue for receiving packets */
+	le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK;
+	le.data |= port->first_rxq;
+
+	/* Disable classification engines */
+	le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
+
+	/* Update lookup ID table entry */
+	mvpp2_cls_lookup_write(port->priv, &le);
+}
+
+/* Set CPU queue number for oversize packets */
+static void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
+{
+	u32 val;
+
+	mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id),
+		    port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
+
+	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
+		    (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
+
+	val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
+	val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
+	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
+}
+
+/* Buffer Manager configuration routines */
+
+/* Create pool */
+static int mvpp2_bm_pool_create(struct platform_device *pdev,
+				struct mvpp2 *priv,
+				struct mvpp2_bm_pool *bm_pool, int size)
+{
+	int size_bytes;
+	u32 val;
+
+	size_bytes = sizeof(u32) * size;
+	bm_pool->virt_addr = dma_alloc_coherent(&pdev->dev, size_bytes,
+						&bm_pool->phys_addr,
+						GFP_KERNEL);
+	if (!bm_pool->virt_addr)
+		return -ENOMEM;
+
+	if (!IS_ALIGNED((u32)bm_pool->virt_addr, MVPP2_BM_POOL_PTR_ALIGN)) {
+		dma_free_coherent(&pdev->dev, size_bytes, bm_pool->virt_addr,
+				  bm_pool->phys_addr);
+		dev_err(&pdev->dev, "BM pool %d is not %d bytes aligned\n",
+			bm_pool->id, MVPP2_BM_POOL_PTR_ALIGN);
+		return -ENOMEM;
+	}
+
+	mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id),
+		    bm_pool->phys_addr);
+	mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size);
+
+	val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
+	val |= MVPP2_BM_START_MASK;
+	mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id), val);
+
+	bm_pool->type = MVPP2_BM_FREE;
+	bm_pool->size = size;
+	bm_pool->pkt_size = 0;
+	bm_pool->buf_num = 0;
+	atomic_set(&bm_pool->in_use, 0);
+	spin_lock_init(&bm_pool->lock);
+
+	return 0;
+}
+
+/* Set pool buffer size */
+static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,
+				      struct mvpp2_bm_pool *bm_pool,
+				      int buf_size)
+{
+	u32 val;
+
+	bm_pool->buf_size = buf_size;
+
+	val = ALIGN(buf_size, 1 << MVPP2_POOL_BUF_SIZE_OFFSET);
+	mvpp2_write(priv, MVPP2_POOL_BUF_SIZE_REG(bm_pool->id), val);
+}
+
+/* Free all buffers from the pool */
+static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
+{
+	int i;
+
+	for (i = 0; i < bm_pool->buf_num; i++) {
+		u32 vaddr;
+
+		/* Get buffer virtual adress (indirect access) */
+		mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+		vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
+		if (!vaddr)
+			break;
+		dev_kfree_skb_any((struct sk_buff *)vaddr);
+	}
+
+	/* Update BM driver with number of buffers removed from pool */
+	bm_pool->buf_num -= i;
+}
+
+/* Cleanup pool */
+static int mvpp2_bm_pool_destroy(struct platform_device *pdev,
+				 struct mvpp2 *priv,
+				 struct mvpp2_bm_pool *bm_pool)
+{
+	u32 val;
+
+	mvpp2_bm_bufs_free(priv, bm_pool);
+	if (bm_pool->buf_num) {
+		WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
+		return 0;
+	}
+
+	val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
+	val |= MVPP2_BM_STOP_MASK;
+	mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id), val);
+
+	dma_free_coherent(&pdev->dev, sizeof(u32) * bm_pool->size,
+			  bm_pool->virt_addr,
+			  bm_pool->phys_addr);
+	return 0;
+}
+
+static int mvpp2_bm_pools_init(struct platform_device *pdev,
+			       struct mvpp2 *priv)
+{
+	int i, err, size;
+	struct mvpp2_bm_pool *bm_pool;
+
+	/* Create all pools with maximum size */
+	size = MVPP2_BM_POOL_SIZE_MAX;
+	for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+		bm_pool = &priv->bm_pools[i];
+		bm_pool->id = i;
+		err = mvpp2_bm_pool_create(pdev, priv, bm_pool, size);
+		if (err)
+			goto err_unroll_pools;
+		mvpp2_bm_pool_bufsize_set(priv, bm_pool, 0);
+	}
+	return 0;
+
+err_unroll_pools:
+	dev_err(&pdev->dev, "failed to create BM pool %d, size %d\n", i, size);
+	for (i = i - 1; i >= 0; i--)
+		mvpp2_bm_pool_destroy(pdev, priv, &priv->bm_pools[i]);
+	return err;
+}
+
+static int mvpp2_bm_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+	int i, err;
+
+	for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+		/* Mask BM all interrupts */
+		mvpp2_write(priv, MVPP2_BM_INTR_MASK_REG(i), 0);
+		/* Clear BM cause register */
+		mvpp2_write(priv, MVPP2_BM_INTR_CAUSE_REG(i), 0);
+	}
+
+	/* Allocate and initialize BM pools */
+	priv->bm_pools = devm_kcalloc(&pdev->dev, MVPP2_BM_POOLS_NUM,
+				     sizeof(struct mvpp2_bm_pool), GFP_KERNEL);
+	if (!priv->bm_pools)
+		return -ENOMEM;
+
+	err = mvpp2_bm_pools_init(pdev, priv);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+/* Attach long pool to rxq */
+static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
+				    int lrxq, int long_pool)
+{
+	u32 val;
+	int prxq;
+
+	/* Get queue physical ID */
+	prxq = port->rxqs[lrxq]->id;
+
+	val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+	val &= ~MVPP2_RXQ_POOL_LONG_MASK;
+	val |= ((long_pool << MVPP2_RXQ_POOL_LONG_OFFS) &
+		    MVPP2_RXQ_POOL_LONG_MASK);
+
+	mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Attach short pool to rxq */
+static void mvpp2_rxq_short_pool_set(struct mvpp2_port *port,
+				     int lrxq, int short_pool)
+{
+	u32 val;
+	int prxq;
+
+	/* Get queue physical ID */
+	prxq = port->rxqs[lrxq]->id;
+
+	val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+	val &= ~MVPP2_RXQ_POOL_SHORT_MASK;
+	val |= ((short_pool << MVPP2_RXQ_POOL_SHORT_OFFS) &
+		    MVPP2_RXQ_POOL_SHORT_MASK);
+
+	mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Allocate skb for BM pool */
+static struct sk_buff *mvpp2_skb_alloc(struct mvpp2_port *port,
+				       struct mvpp2_bm_pool *bm_pool,
+				       dma_addr_t *buf_phys_addr,
+				       gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+	dma_addr_t phys_addr;
+
+	skb = __dev_alloc_skb(bm_pool->pkt_size, gfp_mask);
+	if (!skb)
+		return NULL;
+
+	phys_addr = dma_map_single(port->dev->dev.parent, skb->head,
+				   MVPP2_RX_BUF_SIZE(bm_pool->pkt_size),
+				    DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(port->dev->dev.parent, phys_addr))) {
+		dev_kfree_skb_any(skb);
+		return NULL;
+	}
+	*buf_phys_addr = phys_addr;
+
+	return skb;
+}
+
+/* Set pool number in a BM cookie */
+static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
+{
+	u32 bm;
+
+	bm = cookie & ~(0xFF << MVPP2_BM_COOKIE_POOL_OFFS);
+	bm |= ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS);
+
+	return bm;
+}
+
+/* Get pool number from a BM cookie */
+static inline int mvpp2_bm_cookie_pool_get(u32 cookie)
+{
+	return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
+}
+
+/* Release buffer to BM */
+static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
+				     u32 buf_phys_addr, u32 buf_virt_addr)
+{
+	mvpp2_write(port->priv, MVPP2_BM_VIRT_RLS_REG, buf_virt_addr);
+	mvpp2_write(port->priv, MVPP2_BM_PHY_RLS_REG(pool), buf_phys_addr);
+}
+
+/* Release multicast buffer */
+static void mvpp2_bm_pool_mc_put(struct mvpp2_port *port, int pool,
+				 u32 buf_phys_addr, u32 buf_virt_addr,
+				 int mc_id)
+{
+	u32 val = 0;
+
+	val |= (mc_id & MVPP2_BM_MC_ID_MASK);
+	mvpp2_write(port->priv, MVPP2_BM_MC_RLS_REG, val);
+
+	mvpp2_bm_pool_put(port, pool,
+			  buf_phys_addr | MVPP2_BM_PHY_RLS_MC_BUFF_MASK,
+			  buf_virt_addr);
+}
+
+/* Refill BM pool */
+static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
+			      u32 phys_addr, u32 cookie)
+{
+	int pool = mvpp2_bm_cookie_pool_get(bm);
+
+	mvpp2_bm_pool_put(port, pool, phys_addr, cookie);
+}
+
+/* Allocate buffers for the pool */
+static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
+			     struct mvpp2_bm_pool *bm_pool, int buf_num)
+{
+	struct sk_buff *skb;
+	int i, buf_size, total_size;
+	u32 bm;
+	dma_addr_t phys_addr;
+
+	buf_size = MVPP2_RX_BUF_SIZE(bm_pool->pkt_size);
+	total_size = MVPP2_RX_TOTAL_SIZE(buf_size);
+
+	if (buf_num < 0 ||
+	    (buf_num + bm_pool->buf_num > bm_pool->size)) {
+		netdev_err(port->dev,
+			   "cannot allocate %d buffers for pool %d\n",
+			   buf_num, bm_pool->id);
+		return 0;
+	}
+
+	bm = mvpp2_bm_cookie_pool_set(0, bm_pool->id);
+	for (i = 0; i < buf_num; i++) {
+		skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_KERNEL);
+		if (!skb)
+			break;
+
+		mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+	}
+
+	/* Update BM driver with number of buffers added to pool */
+	bm_pool->buf_num += i;
+	bm_pool->in_use_thresh = bm_pool->buf_num / 4;
+
+	netdev_dbg(port->dev,
+		   "%s pool %d: pkt_size=%4d, buf_size=%4d, total_size=%4d\n",
+		   bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
+		   bm_pool->id, bm_pool->pkt_size, buf_size, total_size);
+
+	netdev_dbg(port->dev,
+		   "%s pool %d: %d of %d buffers added\n",
+		   bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
+		   bm_pool->id, i, buf_num);
+	return i;
+}
+
+/* Notify the driver that BM pool is being used as specific type and return the
+ * pool pointer on success
+ */
+static struct mvpp2_bm_pool *
+mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
+		  int pkt_size)
+{
+	unsigned long flags = 0;
+	struct mvpp2_bm_pool *new_pool = &port->priv->bm_pools[pool];
+	int num;
+
+	if (new_pool->type != MVPP2_BM_FREE && new_pool->type != type) {
+		netdev_err(port->dev, "mixing pool types is forbidden\n");
+		return NULL;
+	}
+
+	spin_lock_irqsave(&new_pool->lock, flags);
+
+	if (new_pool->type == MVPP2_BM_FREE)
+		new_pool->type = type;
+
+	/* Allocate buffers in case BM pool is used as long pool, but packet
+	 * size doesn't match MTU or BM pool hasn't being used yet
+	 */
+	if (((type == MVPP2_BM_SWF_LONG) && (pkt_size > new_pool->pkt_size)) ||
+	    (new_pool->pkt_size == 0)) {
+		int pkts_num;
+
+		/* Set default buffer number or free all the buffers in case
+		 * the pool is not empty
+		 */
+		pkts_num = new_pool->buf_num;
+		if (pkts_num == 0)
+			pkts_num = type == MVPP2_BM_SWF_LONG ?
+				   MVPP2_BM_LONG_BUF_NUM :
+				   MVPP2_BM_SHORT_BUF_NUM;
+		else
+			mvpp2_bm_bufs_free(port->priv, new_pool);
+
+		new_pool->pkt_size = pkt_size;
+
+		/* Allocate buffers for this pool */
+		num = mvpp2_bm_bufs_add(port, new_pool, pkts_num);
+		if (num != pkts_num) {
+			WARN(1, "pool %d: %d of %d allocated\n",
+			     new_pool->id, num, pkts_num);
+			/* We need to undo the bufs_add() allocations */
+			spin_unlock_irqrestore(&new_pool->lock, flags);
+			return NULL;
+		}
+	}
+
+	mvpp2_bm_pool_bufsize_set(port->priv, new_pool,
+				  MVPP2_RX_BUF_SIZE(new_pool->pkt_size));
+
+	spin_unlock_irqrestore(&new_pool->lock, flags);
+
+	return new_pool;
+}
+
+/* Initialize pools for swf */
+static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+{
+	unsigned long flags = 0;
+	int rxq;
+
+	if (!port->pool_long) {
+		port->pool_long =
+		       mvpp2_bm_pool_use(port, MVPP2_BM_SWF_LONG_POOL(port->id),
+					 MVPP2_BM_SWF_LONG,
+					 port->pkt_size);
+		if (!port->pool_long)
+			return -ENOMEM;
+
+		spin_lock_irqsave(&port->pool_long->lock, flags);
+		port->pool_long->port_map |= (1 << port->id);
+		spin_unlock_irqrestore(&port->pool_long->lock, flags);
+
+		for (rxq = 0; rxq < rxq_number; rxq++)
+			mvpp2_rxq_long_pool_set(port, rxq, port->pool_long->id);
+	}
+
+	if (!port->pool_short) {
+		port->pool_short =
+			mvpp2_bm_pool_use(port, MVPP2_BM_SWF_SHORT_POOL,
+					  MVPP2_BM_SWF_SHORT,
+					  MVPP2_BM_SHORT_PKT_SIZE);
+		if (!port->pool_short)
+			return -ENOMEM;
+
+		spin_lock_irqsave(&port->pool_short->lock, flags);
+		port->pool_short->port_map |= (1 << port->id);
+		spin_unlock_irqrestore(&port->pool_short->lock, flags);
+
+		for (rxq = 0; rxq < rxq_number; rxq++)
+			mvpp2_rxq_short_pool_set(port, rxq,
+						 port->pool_short->id);
+	}
+
+	return 0;
+}
+
+static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2_bm_pool *port_pool = port->pool_long;
+	int num, pkts_num = port_pool->buf_num;
+	int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+
+	/* Update BM pool with new buffer size */
+	mvpp2_bm_bufs_free(port->priv, port_pool);
+	if (port_pool->buf_num) {
+		WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
+		return -EIO;
+	}
+
+	port_pool->pkt_size = pkt_size;
+	num = mvpp2_bm_bufs_add(port, port_pool, pkts_num);
+	if (num != pkts_num) {
+		WARN(1, "pool %d: %d of %d allocated\n",
+		     port_pool->id, num, pkts_num);
+		return -EIO;
+	}
+
+	mvpp2_bm_pool_bufsize_set(port->priv, port_pool,
+				  MVPP2_RX_BUF_SIZE(port_pool->pkt_size));
+	dev->mtu = mtu;
+	netdev_update_features(dev);
+	return 0;
+}
+
+static inline void mvpp2_interrupts_enable(struct mvpp2_port *port)
+{
+	int cpu, cpu_mask = 0;
+
+	for_each_present_cpu(cpu)
+		cpu_mask |= 1 << cpu;
+	mvpp2_write(port->priv, MVPP2_ISR_ENABLE_REG(port->id),
+		    MVPP2_ISR_ENABLE_INTERRUPT(cpu_mask));
+}
+
+static inline void mvpp2_interrupts_disable(struct mvpp2_port *port)
+{
+	int cpu, cpu_mask = 0;
+
+	for_each_present_cpu(cpu)
+		cpu_mask |= 1 << cpu;
+	mvpp2_write(port->priv, MVPP2_ISR_ENABLE_REG(port->id),
+		    MVPP2_ISR_DISABLE_INTERRUPT(cpu_mask));
+}
+
+/* Mask the current CPU's Rx/Tx interrupts */
+static void mvpp2_interrupts_mask(void *arg)
+{
+	struct mvpp2_port *port = arg;
+
+	mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id), 0);
+}
+
+/* Unmask the current CPU's Rx/Tx interrupts */
+static void mvpp2_interrupts_unmask(void *arg)
+{
+	struct mvpp2_port *port = arg;
+
+	mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id),
+		    (MVPP2_CAUSE_MISC_SUM_MASK |
+		     MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK |
+		     MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK));
+}
+
+/* Port configuration routines */
+
+static void mvpp2_port_mii_set(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	switch (port->phy_interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+		val |= MVPP2_GMAC_INBAND_AN_MASK;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+		val |= MVPP2_GMAC_PORT_RGMII_MASK;
+	default:
+		val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
+	}
+
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+}
+
+static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+	val |= MVPP2_GMAC_FC_ADV_EN;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void mvpp2_port_enable(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	val |= MVPP2_GMAC_PORT_EN_MASK;
+	val |= MVPP2_GMAC_MIB_CNTR_EN_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+static void mvpp2_port_disable(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	val &= ~(MVPP2_GMAC_PORT_EN_MASK);
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+/* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */
+static void mvpp2_port_periodic_xon_disable(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_1_REG) &
+		    ~MVPP2_GMAC_PERIODIC_XON_EN_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+}
+
+/* Configure loopback port */
+static void mvpp2_port_loopback_set(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+
+	if (port->speed == 1000)
+		val |= MVPP2_GMAC_GMII_LB_EN_MASK;
+	else
+		val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
+
+	if (port->phy_interface == PHY_INTERFACE_MODE_SGMII)
+		val |= MVPP2_GMAC_PCS_LB_EN_MASK;
+	else
+		val &= ~MVPP2_GMAC_PCS_LB_EN_MASK;
+
+	writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+}
+
+static void mvpp2_port_reset(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+		    ~MVPP2_GMAC_PORT_RESET_MASK;
+	writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+	       MVPP2_GMAC_PORT_RESET_MASK)
+		continue;
+}
+
+/* Change maximum receive size of the port */
+static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+	val &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
+	val |= (((port->pkt_size - MVPP2_MH_SIZE) / 2) <<
+		    MVPP2_GMAC_MAX_RX_SIZE_OFFS);
+	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+/* Set defaults to the MVPP2 port */
+static void mvpp2_defaults_set(struct mvpp2_port *port)
+{
+	int tx_port_num, val, queue, ptxq, lrxq;
+
+	/* Configure port to loopback if needed */
+	if (port->flags & MVPP2_F_LOOPBACK)
+		mvpp2_port_loopback_set(port);
+
+	/* Update TX FIFO MIN Threshold */
+	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+	/* Min. TX threshold must be less than minimal packet length */
+	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+	/* Disable Legacy WRR, Disable EJP, Release from reset */
+	tx_port_num = mvpp2_egress_port(port);
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG,
+		    tx_port_num);
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0);
+
+	/* Close bandwidth for all queues */
+	for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) {
+		ptxq = mvpp2_txq_phys(port->id, queue);
+		mvpp2_write(port->priv,
+			    MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0);
+	}
+
+	/* Set refill period to 1 usec, refill tokens
+	 * and bucket size to maximum
+	 */
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PERIOD_REG,
+		    port->priv->tclk / USEC_PER_SEC);
+	val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_REFILL_REG);
+	val &= ~MVPP2_TXP_REFILL_PERIOD_ALL_MASK;
+	val |= MVPP2_TXP_REFILL_PERIOD_MASK(1);
+	val |= MVPP2_TXP_REFILL_TOKENS_ALL_MASK;
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_REFILL_REG, val);
+	val = MVPP2_TXP_TOKEN_SIZE_MAX;
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
+
+	/* Set MaximumLowLatencyPacketSize value to 256 */
+	mvpp2_write(port->priv, MVPP2_RX_CTRL_REG(port->id),
+		    MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK |
+		    MVPP2_RX_LOW_LATENCY_PKT_SIZE(256));
+
+	/* Enable Rx cache snoop */
+	for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+		queue = port->rxqs[lrxq]->id;
+		val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+		val |= MVPP2_SNOOP_PKT_SIZE_MASK |
+			   MVPP2_SNOOP_BUF_HDR_MASK;
+		mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+	}
+
+	/* At default, mask all interrupts to all present cpus */
+	mvpp2_interrupts_disable(port);
+}
+
+/* Enable/disable receiving packets */
+static void mvpp2_ingress_enable(struct mvpp2_port *port)
+{
+	u32 val;
+	int lrxq, queue;
+
+	for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+		queue = port->rxqs[lrxq]->id;
+		val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+		val &= ~MVPP2_RXQ_DISABLE_MASK;
+		mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+	}
+}
+
+static void mvpp2_ingress_disable(struct mvpp2_port *port)
+{
+	u32 val;
+	int lrxq, queue;
+
+	for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+		queue = port->rxqs[lrxq]->id;
+		val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+		val |= MVPP2_RXQ_DISABLE_MASK;
+		mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+	}
+}
+
+/* Enable transmit via physical egress queue
+ * - HW starts take descriptors from DRAM
+ */
+static void mvpp2_egress_enable(struct mvpp2_port *port)
+{
+	u32 qmap;
+	int queue;
+	int tx_port_num = mvpp2_egress_port(port);
+
+	/* Enable all initialized TXs. */
+	qmap = 0;
+	for (queue = 0; queue < txq_number; queue++) {
+		struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+		if (txq->descs != NULL)
+			qmap |= (1 << queue);
+	}
+
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG, qmap);
+}
+
+/* Disable transmit via physical egress queue
+ * - HW doesn't take descriptors from DRAM
+ */
+static void mvpp2_egress_disable(struct mvpp2_port *port)
+{
+	u32 reg_data;
+	int delay;
+	int tx_port_num = mvpp2_egress_port(port);
+
+	/* Issue stop command for active channels only */
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+	reg_data = (mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG)) &
+		    MVPP2_TXP_SCHED_ENQ_MASK;
+	if (reg_data != 0)
+		mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG,
+			    (reg_data << MVPP2_TXP_SCHED_DISQ_OFFSET));
+
+	/* Wait for all Tx activity to terminate. */
+	delay = 0;
+	do {
+		if (delay >= MVPP2_TX_DISABLE_TIMEOUT_MSEC) {
+			netdev_warn(port->dev,
+				    "Tx stop timed out, status=0x%08x\n",
+				    reg_data);
+			break;
+		}
+		mdelay(1);
+		delay++;
+
+		/* Check port TX Command register that all
+		 * Tx queues are stopped
+		 */
+		reg_data = mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG);
+	} while (reg_data & MVPP2_TXP_SCHED_ENQ_MASK);
+}
+
+/* Rx descriptors helper methods */
+
+/* Get number of Rx descriptors occupied by received packets */
+static inline int
+mvpp2_rxq_received(struct mvpp2_port *port, int rxq_id)
+{
+	u32 val = mvpp2_read(port->priv, MVPP2_RXQ_STATUS_REG(rxq_id));
+
+	return val & MVPP2_RXQ_OCCUPIED_MASK;
+}
+
+/* Update Rx queue status with the number of occupied and available
+ * Rx descriptor slots.
+ */
+static inline void
+mvpp2_rxq_status_update(struct mvpp2_port *port, int rxq_id,
+			int used_count, int free_count)
+{
+	/* Decrement the number of used descriptors and increment count
+	 * increment the number of free descriptors.
+	 */
+	u32 val = used_count | (free_count << MVPP2_RXQ_NUM_NEW_OFFSET);
+
+	mvpp2_write(port->priv, MVPP2_RXQ_STATUS_UPDATE_REG(rxq_id), val);
+}
+
+/* Get pointer to next RX descriptor to be processed by SW */
+static inline struct mvpp2_rx_desc *
+mvpp2_rxq_next_desc_get(struct mvpp2_rx_queue *rxq)
+{
+	int rx_desc = rxq->next_desc_to_proc;
+
+	rxq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(rxq, rx_desc);
+	prefetch(rxq->descs + rxq->next_desc_to_proc);
+	return rxq->descs + rx_desc;
+}
+
+/* Set rx queue offset */
+static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
+				 int prxq, int offset)
+{
+	u32 val;
+
+	/* Convert offset from bytes to units of 32 bytes */
+	offset = offset >> 5;
+
+	val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+	val &= ~MVPP2_RXQ_PACKET_OFFSET_MASK;
+
+	/* Offset is in */
+	val |= ((offset << MVPP2_RXQ_PACKET_OFFSET_OFFS) &
+		    MVPP2_RXQ_PACKET_OFFSET_MASK);
+
+	mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Obtain BM cookie information from descriptor */
+static u32 mvpp2_bm_cookie_build(struct mvpp2_rx_desc *rx_desc)
+{
+	int pool = (rx_desc->status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+		   MVPP2_RXD_BM_POOL_ID_OFFS;
+	int cpu = smp_processor_id();
+
+	return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
+	       ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
+}
+
+/* Tx descriptors helper methods */
+
+/* Get number of Tx descriptors waiting to be transmitted by HW */
+static int mvpp2_txq_pend_desc_num_get(struct mvpp2_port *port,
+				       struct mvpp2_tx_queue *txq)
+{
+	u32 val;
+
+	mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+	val = mvpp2_read(port->priv, MVPP2_TXQ_PENDING_REG);
+
+	return val & MVPP2_TXQ_PENDING_MASK;
+}
+
+/* Get pointer to next Tx descriptor to be processed (send) by HW */
+static struct mvpp2_tx_desc *
+mvpp2_txq_next_desc_get(struct mvpp2_tx_queue *txq)
+{
+	int tx_desc = txq->next_desc_to_proc;
+
+	txq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(txq, tx_desc);
+	return txq->descs + tx_desc;
+}
+
+/* Update HW with number of aggregated Tx descriptors to be sent */
+static void mvpp2_aggr_txq_pend_desc_add(struct mvpp2_port *port, int pending)
+{
+	/* aggregated access - relevant TXQ number is written in TX desc */
+	mvpp2_write(port->priv, MVPP2_AGGR_TXQ_UPDATE_REG, pending);
+}
+
+
+/* Check if there are enough free descriptors in aggregated txq.
+ * If not, update the number of occupied descriptors and repeat the check.
+ */
+static int mvpp2_aggr_desc_num_check(struct mvpp2 *priv,
+				     struct mvpp2_tx_queue *aggr_txq, int num)
+{
+	if ((aggr_txq->count + num) > aggr_txq->size) {
+		/* Update number of occupied aggregated Tx descriptors */
+		int cpu = smp_processor_id();
+		u32 val = mvpp2_read(priv, MVPP2_AGGR_TXQ_STATUS_REG(cpu));
+
+		aggr_txq->count = val & MVPP2_AGGR_TXQ_PENDING_MASK;
+	}
+
+	if ((aggr_txq->count + num) > aggr_txq->size)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/* Reserved Tx descriptors allocation request */
+static int mvpp2_txq_alloc_reserved_desc(struct mvpp2 *priv,
+					 struct mvpp2_tx_queue *txq, int num)
+{
+	u32 val;
+
+	val = (txq->id << MVPP2_TXQ_RSVD_REQ_Q_OFFSET) | num;
+	mvpp2_write(priv, MVPP2_TXQ_RSVD_REQ_REG, val);
+
+	val = mvpp2_read(priv, MVPP2_TXQ_RSVD_RSLT_REG);
+
+	return val & MVPP2_TXQ_RSVD_RSLT_MASK;
+}
+
+/* Check if there are enough reserved descriptors for transmission.
+ * If not, request chunk of reserved descriptors and check again.
+ */
+static int mvpp2_txq_reserved_desc_num_proc(struct mvpp2 *priv,
+					    struct mvpp2_tx_queue *txq,
+					    struct mvpp2_txq_pcpu *txq_pcpu,
+					    int num)
+{
+	int req, cpu, desc_count;
+
+	if (txq_pcpu->reserved_num >= num)
+		return 0;
+
+	/* Not enough descriptors reserved! Update the reserved descriptor
+	 * count and check again.
+	 */
+
+	desc_count = 0;
+	/* Compute total of used descriptors */
+	for_each_present_cpu(cpu) {
+		struct mvpp2_txq_pcpu *txq_pcpu_aux;
+
+		txq_pcpu_aux = per_cpu_ptr(txq->pcpu, cpu);
+		desc_count += txq_pcpu_aux->count;
+		desc_count += txq_pcpu_aux->reserved_num;
+	}
+
+	req = max(MVPP2_CPU_DESC_CHUNK, num - txq_pcpu->reserved_num);
+	desc_count += req;
+
+	if (desc_count >
+	   (txq->size - (num_present_cpus() * MVPP2_CPU_DESC_CHUNK)))
+		return -ENOMEM;
+
+	txq_pcpu->reserved_num += mvpp2_txq_alloc_reserved_desc(priv, txq, req);
+
+	/* OK, the descriptor cound has been updated: check again. */
+	if (txq_pcpu->reserved_num < num)
+		return -ENOMEM;
+	return 0;
+}
+
+/* Release the last allocated Tx descriptor. Useful to handle DMA
+ * mapping failures in the Tx path.
+ */
+static void mvpp2_txq_desc_put(struct mvpp2_tx_queue *txq)
+{
+	if (txq->next_desc_to_proc == 0)
+		txq->next_desc_to_proc = txq->last_desc - 1;
+	else
+		txq->next_desc_to_proc--;
+}
+
+/* Set Tx descriptors fields relevant for CSUM calculation */
+static u32 mvpp2_txq_desc_csum(int l3_offs, int l3_proto,
+			       int ip_hdr_len, int l4_proto)
+{
+	u32 command;
+
+	/* fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk,
+	 * G_L4_chk, L4_type required only for checksum calculation
+	 */
+	command = (l3_offs << MVPP2_TXD_L3_OFF_SHIFT);
+	command |= (ip_hdr_len << MVPP2_TXD_IP_HLEN_SHIFT);
+	command |= MVPP2_TXD_IP_CSUM_DISABLE;
+
+	if (l3_proto == swab16(ETH_P_IP)) {
+		command &= ~MVPP2_TXD_IP_CSUM_DISABLE;	/* enable IPv4 csum */
+		command &= ~MVPP2_TXD_L3_IP6;		/* enable IPv4 */
+	} else {
+		command |= MVPP2_TXD_L3_IP6;		/* enable IPv6 */
+	}
+
+	if (l4_proto == IPPROTO_TCP) {
+		command &= ~MVPP2_TXD_L4_UDP;		/* enable TCP */
+		command &= ~MVPP2_TXD_L4_CSUM_FRAG;	/* generate L4 csum */
+	} else if (l4_proto == IPPROTO_UDP) {
+		command |= MVPP2_TXD_L4_UDP;		/* enable UDP */
+		command &= ~MVPP2_TXD_L4_CSUM_FRAG;	/* generate L4 csum */
+	} else {
+		command |= MVPP2_TXD_L4_CSUM_NOT;
+	}
+
+	return command;
+}
+
+/* Get number of sent descriptors and decrement counter.
+ * The number of sent descriptors is returned.
+ * Per-CPU access
+ */
+static inline int mvpp2_txq_sent_desc_proc(struct mvpp2_port *port,
+					   struct mvpp2_tx_queue *txq)
+{
+	u32 val;
+
+	/* Reading status reg resets transmitted descriptor counter */
+	val = mvpp2_read(port->priv, MVPP2_TXQ_SENT_REG(txq->id));
+
+	return (val & MVPP2_TRANSMITTED_COUNT_MASK) >>
+		MVPP2_TRANSMITTED_COUNT_OFFSET;
+}
+
+static void mvpp2_txq_sent_counter_clear(void *arg)
+{
+	struct mvpp2_port *port = arg;
+	int queue;
+
+	for (queue = 0; queue < txq_number; queue++) {
+		int id = port->txqs[queue]->id;
+
+		mvpp2_read(port->priv, MVPP2_TXQ_SENT_REG(id));
+	}
+}
+
+/* Set max sizes for Tx queues */
+static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
+{
+	u32	val, size, mtu;
+	int	txq, tx_port_num;
+
+	mtu = port->pkt_size * 8;
+	if (mtu > MVPP2_TXP_MTU_MAX)
+		mtu = MVPP2_TXP_MTU_MAX;
+
+	/* WA for wrong Token bucket update: Set MTU value = 3*real MTU value */
+	mtu = 3 * mtu;
+
+	/* Indirect access to registers */
+	tx_port_num = mvpp2_egress_port(port);
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+
+	/* Set MTU */
+	val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_MTU_REG);
+	val &= ~MVPP2_TXP_MTU_MAX;
+	val |= mtu;
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_MTU_REG, val);
+
+	/* TXP token size and all TXQs token size must be larger that MTU */
+	val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG);
+	size = val & MVPP2_TXP_TOKEN_SIZE_MAX;
+	if (size < mtu) {
+		size = mtu;
+		val &= ~MVPP2_TXP_TOKEN_SIZE_MAX;
+		val |= size;
+		mvpp2_write(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
+	}
+
+	for (txq = 0; txq < txq_number; txq++) {
+		val = mvpp2_read(port->priv,
+				 MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq));
+		size = val & MVPP2_TXQ_TOKEN_SIZE_MAX;
+
+		if (size < mtu) {
+			size = mtu;
+			val &= ~MVPP2_TXQ_TOKEN_SIZE_MAX;
+			val |= size;
+			mvpp2_write(port->priv,
+				    MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq),
+				    val);
+		}
+	}
+}
+
+/* Set the number of packets that will be received before Rx interrupt
+ * will be generated by HW.
+ */
+static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
+				   struct mvpp2_rx_queue *rxq, u32 pkts)
+{
+	u32 val;
+
+	val = (pkts & MVPP2_OCCUPIED_THRESH_MASK);
+	mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+	mvpp2_write(port->priv, MVPP2_RXQ_THRESH_REG, val);
+
+	rxq->pkts_coal = pkts;
+}
+
+/* Set the time delay in usec before Rx interrupt */
+static void mvpp2_rx_time_coal_set(struct mvpp2_port *port,
+				   struct mvpp2_rx_queue *rxq, u32 usec)
+{
+	u32 val;
+
+	val = (port->priv->tclk / USEC_PER_SEC) * usec;
+	mvpp2_write(port->priv, MVPP2_ISR_RX_THRESHOLD_REG(rxq->id), val);
+
+	rxq->time_coal = usec;
+}
+
+/* Set threshold for TX_DONE pkts coalescing */
+static void mvpp2_tx_done_pkts_coal_set(void *arg)
+{
+	struct mvpp2_port *port = arg;
+	int queue;
+	u32 val;
+
+	for (queue = 0; queue < txq_number; queue++) {
+		struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+		val = (txq->done_pkts_coal << MVPP2_TRANSMITTED_THRESH_OFFSET) &
+		       MVPP2_TRANSMITTED_THRESH_MASK;
+		mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+		mvpp2_write(port->priv, MVPP2_TXQ_THRESH_REG, val);
+	}
+}
+
+/* Free Tx queue skbuffs */
+static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
+				struct mvpp2_tx_queue *txq,
+				struct mvpp2_txq_pcpu *txq_pcpu, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		struct mvpp2_tx_desc *tx_desc = txq->descs +
+							txq_pcpu->txq_get_index;
+		struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
+
+		mvpp2_txq_inc_get(txq_pcpu);
+
+		if (!skb)
+			continue;
+
+		dma_unmap_single(port->dev->dev.parent, tx_desc->buf_phys_addr,
+				 tx_desc->data_size, DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+	}
+}
+
+static inline struct mvpp2_rx_queue *mvpp2_get_rx_queue(struct mvpp2_port *port,
+							u32 cause)
+{
+	int queue = fls(cause) - 1;
+
+	return port->rxqs[queue];
+}
+
+static inline struct mvpp2_tx_queue *mvpp2_get_tx_queue(struct mvpp2_port *port,
+							u32 cause)
+{
+	int queue = fls(cause >> 16) - 1;
+
+	return port->txqs[queue];
+}
+
+/* Handle end of transmission */
+static void mvpp2_txq_done(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
+			   struct mvpp2_txq_pcpu *txq_pcpu)
+{
+	struct netdev_queue *nq = netdev_get_tx_queue(port->dev, txq->log_id);
+	int tx_done;
+
+	if (txq_pcpu->cpu != smp_processor_id())
+		netdev_err(port->dev, "wrong cpu on the end of Tx processing\n");
+
+	tx_done = mvpp2_txq_sent_desc_proc(port, txq);
+	if (!tx_done)
+		return;
+	mvpp2_txq_bufs_free(port, txq, txq_pcpu, tx_done);
+
+	txq_pcpu->count -= tx_done;
+
+	if (netif_tx_queue_stopped(nq))
+		if (txq_pcpu->size - txq_pcpu->count >= MAX_SKB_FRAGS + 1)
+			netif_tx_wake_queue(nq);
+}
+
+/* Rx/Tx queue initialization/cleanup methods */
+
+/* Allocate and initialize descriptors for aggr TXQ */
+static int mvpp2_aggr_txq_init(struct platform_device *pdev,
+			       struct mvpp2_tx_queue *aggr_txq,
+			       int desc_num, int cpu,
+			       struct mvpp2 *priv)
+{
+	/* Allocate memory for TX descriptors */
+	aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
+				desc_num * MVPP2_DESC_ALIGNED_SIZE,
+				&aggr_txq->descs_phys, GFP_KERNEL);
+	if (!aggr_txq->descs)
+		return -ENOMEM;
+
+	/* Make sure descriptor address is cache line size aligned  */
+	BUG_ON(aggr_txq->descs !=
+	       PTR_ALIGN(aggr_txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+	aggr_txq->last_desc = aggr_txq->size - 1;
+
+	/* Aggr TXQ no reset WA */
+	aggr_txq->next_desc_to_proc = mvpp2_read(priv,
+						 MVPP2_AGGR_TXQ_INDEX_REG(cpu));
+
+	/* Set Tx descriptors queue starting address */
+	/* indirect access */
+	mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu),
+		    aggr_txq->descs_phys);
+	mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu), desc_num);
+
+	return 0;
+}
+
+/* Create a specified Rx queue */
+static int mvpp2_rxq_init(struct mvpp2_port *port,
+			  struct mvpp2_rx_queue *rxq)
+
+{
+	rxq->size = port->rx_ring_size;
+
+	/* Allocate memory for RX descriptors */
+	rxq->descs = dma_alloc_coherent(port->dev->dev.parent,
+					rxq->size * MVPP2_DESC_ALIGNED_SIZE,
+					&rxq->descs_phys, GFP_KERNEL);
+	if (!rxq->descs)
+		return -ENOMEM;
+
+	BUG_ON(rxq->descs !=
+	       PTR_ALIGN(rxq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+	rxq->last_desc = rxq->size - 1;
+
+	/* Zero occupied and non-occupied counters - direct access */
+	mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
+
+	/* Set Rx descriptors queue starting address - indirect access */
+	mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+	mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq->descs_phys);
+	mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
+	mvpp2_write(port->priv, MVPP2_RXQ_INDEX_REG, 0);
+
+	/* Set Offset */
+	mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD);
+
+	/* Set coalescing pkts and time */
+	mvpp2_rx_pkts_coal_set(port, rxq, rxq->pkts_coal);
+	mvpp2_rx_time_coal_set(port, rxq, rxq->time_coal);
+
+	/* Add number of descriptors ready for receiving packets */
+	mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size);
+
+	return 0;
+}
+
+/* Push packets received by the RXQ to BM pool */
+static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
+				struct mvpp2_rx_queue *rxq)
+{
+	int rx_received, i;
+
+	rx_received = mvpp2_rxq_received(port, rxq->id);
+	if (!rx_received)
+		return;
+
+	for (i = 0; i < rx_received; i++) {
+		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+		u32 bm = mvpp2_bm_cookie_build(rx_desc);
+
+		mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
+				  rx_desc->buf_cookie);
+	}
+	mvpp2_rxq_status_update(port, rxq->id, rx_received, rx_received);
+}
+
+/* Cleanup Rx queue */
+static void mvpp2_rxq_deinit(struct mvpp2_port *port,
+			     struct mvpp2_rx_queue *rxq)
+{
+	mvpp2_rxq_drop_pkts(port, rxq);
+
+	if (rxq->descs)
+		dma_free_coherent(port->dev->dev.parent,
+				  rxq->size * MVPP2_DESC_ALIGNED_SIZE,
+				  rxq->descs,
+				  rxq->descs_phys);
+
+	rxq->descs             = NULL;
+	rxq->last_desc         = 0;
+	rxq->next_desc_to_proc = 0;
+	rxq->descs_phys        = 0;
+
+	/* Clear Rx descriptors queue starting address and size;
+	 * free descriptor number
+	 */
+	mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
+	mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+	mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, 0);
+	mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, 0);
+}
+
+/* Create and initialize a Tx queue */
+static int mvpp2_txq_init(struct mvpp2_port *port,
+			  struct mvpp2_tx_queue *txq)
+{
+	u32 val;
+	int cpu, desc, desc_per_txq, tx_port_num;
+	struct mvpp2_txq_pcpu *txq_pcpu;
+
+	txq->size = port->tx_ring_size;
+
+	/* Allocate memory for Tx descriptors */
+	txq->descs = dma_alloc_coherent(port->dev->dev.parent,
+				txq->size * MVPP2_DESC_ALIGNED_SIZE,
+				&txq->descs_phys, GFP_KERNEL);
+	if (!txq->descs)
+		return -ENOMEM;
+
+	/* Make sure descriptor address is cache line size aligned  */
+	BUG_ON(txq->descs !=
+	       PTR_ALIGN(txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+	txq->last_desc = txq->size - 1;
+
+	/* Set Tx descriptors queue starting address - indirect access */
+	mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+	mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, txq->descs_phys);
+	mvpp2_write(port->priv, MVPP2_TXQ_DESC_SIZE_REG, txq->size &
+					     MVPP2_TXQ_DESC_SIZE_MASK);
+	mvpp2_write(port->priv, MVPP2_TXQ_INDEX_REG, 0);
+	mvpp2_write(port->priv, MVPP2_TXQ_RSVD_CLR_REG,
+		    txq->id << MVPP2_TXQ_RSVD_CLR_OFFSET);
+	val = mvpp2_read(port->priv, MVPP2_TXQ_PENDING_REG);
+	val &= ~MVPP2_TXQ_PENDING_MASK;
+	mvpp2_write(port->priv, MVPP2_TXQ_PENDING_REG, val);
+
+	/* Calculate base address in prefetch buffer. We reserve 16 descriptors
+	 * for each existing TXQ.
+	 * TCONTS for PON port must be continuous from 0 to MVPP2_MAX_TCONT
+	 * GBE ports assumed to be continious from 0 to MVPP2_MAX_PORTS
+	 */
+	desc_per_txq = 16;
+	desc = (port->id * MVPP2_MAX_TXQ * desc_per_txq) +
+	       (txq->log_id * desc_per_txq);
+
+	mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG,
+		    MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
+		    MVPP2_PREF_BUF_THRESH(desc_per_txq/2));
+
+	/* WRR / EJP configuration - indirect access */
+	tx_port_num = mvpp2_egress_port(port);
+	mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+
+	val = mvpp2_read(port->priv, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id));
+	val &= ~MVPP2_TXQ_REFILL_PERIOD_ALL_MASK;
+	val |= MVPP2_TXQ_REFILL_PERIOD_MASK(1);
+	val |= MVPP2_TXQ_REFILL_TOKENS_ALL_MASK;
+	mvpp2_write(port->priv, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id), val);
+
+	val = MVPP2_TXQ_TOKEN_SIZE_MAX;
+	mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq->log_id),
+		    val);
+
+	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) {
+			dma_free_coherent(port->dev->dev.parent,
+					  txq->size * MVPP2_DESC_ALIGNED_SIZE,
+					  txq->descs, txq->descs_phys);
+			return -ENOMEM;
+		}
+
+		txq_pcpu->count = 0;
+		txq_pcpu->reserved_num = 0;
+		txq_pcpu->txq_put_index = 0;
+		txq_pcpu->txq_get_index = 0;
+	}
+
+	return 0;
+}
+
+/* Free allocated TXQ resources */
+static void mvpp2_txq_deinit(struct mvpp2_port *port,
+			     struct mvpp2_tx_queue *txq)
+{
+	struct mvpp2_txq_pcpu *txq_pcpu;
+	int cpu;
+
+	for_each_present_cpu(cpu) {
+		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+		kfree(txq_pcpu->tx_skb);
+	}
+
+	if (txq->descs)
+		dma_free_coherent(port->dev->dev.parent,
+				  txq->size * MVPP2_DESC_ALIGNED_SIZE,
+				  txq->descs, txq->descs_phys);
+
+	txq->descs             = NULL;
+	txq->last_desc         = 0;
+	txq->next_desc_to_proc = 0;
+	txq->descs_phys        = 0;
+
+	/* Set minimum bandwidth for disabled TXQs */
+	mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
+
+	/* Set Tx descriptors queue starting address and size */
+	mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+	mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, 0);
+	mvpp2_write(port->priv, MVPP2_TXQ_DESC_SIZE_REG, 0);
+}
+
+/* Cleanup Tx ports */
+static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
+{
+	struct mvpp2_txq_pcpu *txq_pcpu;
+	int delay, pending, cpu;
+	u32 val;
+
+	mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+	val = mvpp2_read(port->priv, MVPP2_TXQ_PREF_BUF_REG);
+	val |= MVPP2_TXQ_DRAIN_EN_MASK;
+	mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val);
+
+	/* The napi queue has been stopped so wait for all packets
+	 * to be transmitted.
+	 */
+	delay = 0;
+	do {
+		if (delay >= MVPP2_TX_PENDING_TIMEOUT_MSEC) {
+			netdev_warn(port->dev,
+				    "port %d: cleaning queue %d timed out\n",
+				    port->id, txq->log_id);
+			break;
+		}
+		mdelay(1);
+		delay++;
+
+		pending = mvpp2_txq_pend_desc_num_get(port, txq);
+	} while (pending);
+
+	val &= ~MVPP2_TXQ_DRAIN_EN_MASK;
+	mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val);
+
+	for_each_present_cpu(cpu) {
+		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+
+		/* Release all packets */
+		mvpp2_txq_bufs_free(port, txq, txq_pcpu, txq_pcpu->count);
+
+		/* Reset queue */
+		txq_pcpu->count = 0;
+		txq_pcpu->txq_put_index = 0;
+		txq_pcpu->txq_get_index = 0;
+	}
+}
+
+/* Cleanup all Tx queues */
+static void mvpp2_cleanup_txqs(struct mvpp2_port *port)
+{
+	struct mvpp2_tx_queue *txq;
+	int queue;
+	u32 val;
+
+	val = mvpp2_read(port->priv, MVPP2_TX_PORT_FLUSH_REG);
+
+	/* Reset Tx ports and delete Tx queues */
+	val |= MVPP2_TX_PORT_FLUSH_MASK(port->id);
+	mvpp2_write(port->priv, MVPP2_TX_PORT_FLUSH_REG, val);
+
+	for (queue = 0; queue < txq_number; queue++) {
+		txq = port->txqs[queue];
+		mvpp2_txq_clean(port, txq);
+		mvpp2_txq_deinit(port, txq);
+	}
+
+	on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
+
+	val &= ~MVPP2_TX_PORT_FLUSH_MASK(port->id);
+	mvpp2_write(port->priv, MVPP2_TX_PORT_FLUSH_REG, val);
+}
+
+/* Cleanup all Rx queues */
+static void mvpp2_cleanup_rxqs(struct mvpp2_port *port)
+{
+	int queue;
+
+	for (queue = 0; queue < rxq_number; queue++)
+		mvpp2_rxq_deinit(port, port->rxqs[queue]);
+}
+
+/* Init all Rx queues for port */
+static int mvpp2_setup_rxqs(struct mvpp2_port *port)
+{
+	int queue, err;
+
+	for (queue = 0; queue < rxq_number; queue++) {
+		err = mvpp2_rxq_init(port, port->rxqs[queue]);
+		if (err)
+			goto err_cleanup;
+	}
+	return 0;
+
+err_cleanup:
+	mvpp2_cleanup_rxqs(port);
+	return err;
+}
+
+/* Init all tx queues for port */
+static int mvpp2_setup_txqs(struct mvpp2_port *port)
+{
+	struct mvpp2_tx_queue *txq;
+	int queue, err;
+
+	for (queue = 0; queue < txq_number; queue++) {
+		txq = port->txqs[queue];
+		err = mvpp2_txq_init(port, txq);
+		if (err)
+			goto err_cleanup;
+	}
+
+	on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
+	on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
+	return 0;
+
+err_cleanup:
+	mvpp2_cleanup_txqs(port);
+	return err;
+}
+
+/* The callback for per-port interrupt */
+static irqreturn_t mvpp2_isr(int irq, void *dev_id)
+{
+	struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
+
+	mvpp2_interrupts_disable(port);
+
+	napi_schedule(&port->napi);
+
+	return IRQ_HANDLED;
+}
+
+/* Adjust link */
+static void mvpp2_link_event(struct net_device *dev)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	struct phy_device *phydev = port->phy_dev;
+	int status_change = 0;
+	u32 val;
+
+	if (phydev->link) {
+		if ((port->speed != phydev->speed) ||
+		    (port->duplex != phydev->duplex)) {
+			u32 val;
+
+			val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+			val &= ~(MVPP2_GMAC_CONFIG_MII_SPEED |
+				 MVPP2_GMAC_CONFIG_GMII_SPEED |
+				 MVPP2_GMAC_CONFIG_FULL_DUPLEX |
+				 MVPP2_GMAC_AN_SPEED_EN |
+				 MVPP2_GMAC_AN_DUPLEX_EN);
+
+			if (phydev->duplex)
+				val |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
+
+			if (phydev->speed == SPEED_1000)
+				val |= MVPP2_GMAC_CONFIG_GMII_SPEED;
+			else if (phydev->speed == SPEED_100)
+				val |= MVPP2_GMAC_CONFIG_MII_SPEED;
+
+			writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+			port->duplex = phydev->duplex;
+			port->speed  = phydev->speed;
+		}
+	}
+
+	if (phydev->link != port->link) {
+		if (!phydev->link) {
+			port->duplex = -1;
+			port->speed = 0;
+		}
+
+		port->link = phydev->link;
+		status_change = 1;
+	}
+
+	if (status_change) {
+		if (phydev->link) {
+			val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+			val |= (MVPP2_GMAC_FORCE_LINK_PASS |
+				MVPP2_GMAC_FORCE_LINK_DOWN);
+			writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+			mvpp2_egress_enable(port);
+			mvpp2_ingress_enable(port);
+		} else {
+			mvpp2_ingress_disable(port);
+			mvpp2_egress_disable(port);
+		}
+		phy_print_status(phydev);
+	}
+}
+
+/* Main RX/TX processing routines */
+
+/* Display more error info */
+static void mvpp2_rx_error(struct mvpp2_port *port,
+			   struct mvpp2_rx_desc *rx_desc)
+{
+	u32 status = rx_desc->status;
+
+	switch (status & MVPP2_RXD_ERR_CODE_MASK) {
+	case MVPP2_RXD_ERR_CRC:
+		netdev_err(port->dev, "bad rx status %08x (crc error), size=%d\n",
+			   status, rx_desc->data_size);
+		break;
+	case MVPP2_RXD_ERR_OVERRUN:
+		netdev_err(port->dev, "bad rx status %08x (overrun error), size=%d\n",
+			   status, rx_desc->data_size);
+		break;
+	case MVPP2_RXD_ERR_RESOURCE:
+		netdev_err(port->dev, "bad rx status %08x (resource error), size=%d\n",
+			   status, rx_desc->data_size);
+		break;
+	}
+}
+
+/* Handle RX checksum offload */
+static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
+			  struct sk_buff *skb)
+{
+	if (((status & MVPP2_RXD_L3_IP4) &&
+	     !(status & MVPP2_RXD_IP4_HEADER_ERR)) ||
+	    (status & MVPP2_RXD_L3_IP6))
+		if (((status & MVPP2_RXD_L4_UDP) ||
+		     (status & MVPP2_RXD_L4_TCP)) &&
+		     (status & MVPP2_RXD_L4_CSUM_OK)) {
+			skb->csum = 0;
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			return;
+		}
+
+	skb->ip_summed = CHECKSUM_NONE;
+}
+
+/* Reuse skb if possible, or allocate a new skb and add it to BM pool */
+static int mvpp2_rx_refill(struct mvpp2_port *port,
+			   struct mvpp2_bm_pool *bm_pool,
+			   u32 bm, int is_recycle)
+{
+	struct sk_buff *skb;
+	dma_addr_t phys_addr;
+
+	if (is_recycle &&
+	    (atomic_read(&bm_pool->in_use) < bm_pool->in_use_thresh))
+		return 0;
+
+	/* No recycle or too many buffers are in use, so allocate a new skb */
+	skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+	atomic_dec(&bm_pool->in_use);
+	return 0;
+}
+
+/* Handle tx checksum */
+static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb)
+{
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		int ip_hdr_len = 0;
+		u8 l4_proto;
+
+		if (skb->protocol == htons(ETH_P_IP)) {
+			struct iphdr *ip4h = ip_hdr(skb);
+
+			/* Calculate IPv4 checksum and L4 checksum */
+			ip_hdr_len = ip4h->ihl;
+			l4_proto = ip4h->protocol;
+		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+			struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+			/* Read l4_protocol from one of IPv6 extra headers */
+			if (skb_network_header_len(skb) > 0)
+				ip_hdr_len = (skb_network_header_len(skb) >> 2);
+			l4_proto = ip6h->nexthdr;
+		} else {
+			return MVPP2_TXD_L4_CSUM_NOT;
+		}
+
+		return mvpp2_txq_desc_csum(skb_network_offset(skb),
+				skb->protocol, ip_hdr_len, l4_proto);
+	}
+
+	return MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE;
+}
+
+static void mvpp2_buff_hdr_rx(struct mvpp2_port *port,
+			      struct mvpp2_rx_desc *rx_desc)
+{
+	struct mvpp2_buff_hdr *buff_hdr;
+	struct sk_buff *skb;
+	u32 rx_status = rx_desc->status;
+	u32 buff_phys_addr;
+	u32 buff_virt_addr;
+	u32 buff_phys_addr_next;
+	u32 buff_virt_addr_next;
+	int mc_id;
+	int pool_id;
+
+	pool_id = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+		   MVPP2_RXD_BM_POOL_ID_OFFS;
+	buff_phys_addr = rx_desc->buf_phys_addr;
+	buff_virt_addr = rx_desc->buf_cookie;
+
+	do {
+		skb = (struct sk_buff *)buff_virt_addr;
+		buff_hdr = (struct mvpp2_buff_hdr *)skb->head;
+
+		mc_id = MVPP2_B_HDR_INFO_MC_ID(buff_hdr->info);
+
+		buff_phys_addr_next = buff_hdr->next_buff_phys_addr;
+		buff_virt_addr_next = buff_hdr->next_buff_virt_addr;
+
+		/* Release buffer */
+		mvpp2_bm_pool_mc_put(port, pool_id, buff_phys_addr,
+				     buff_virt_addr, mc_id);
+
+		buff_phys_addr = buff_phys_addr_next;
+		buff_virt_addr = buff_virt_addr_next;
+
+	} while (!MVPP2_B_HDR_INFO_IS_LAST(buff_hdr->info));
+}
+
+/* Main rx processing */
+static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
+		    struct mvpp2_rx_queue *rxq)
+{
+	struct net_device *dev = port->dev;
+	int rx_received, rx_filled, i;
+	u32 rcvd_pkts = 0;
+	u32 rcvd_bytes = 0;
+
+	/* Get number of received packets and clamp the to-do */
+	rx_received = mvpp2_rxq_received(port, rxq->id);
+	if (rx_todo > rx_received)
+		rx_todo = rx_received;
+
+	rx_filled = 0;
+	for (i = 0; i < rx_todo; i++) {
+		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+		struct mvpp2_bm_pool *bm_pool;
+		struct sk_buff *skb;
+		u32 bm, rx_status;
+		int pool, rx_bytes, err;
+
+		rx_filled++;
+		rx_status = rx_desc->status;
+		rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
+
+		bm = mvpp2_bm_cookie_build(rx_desc);
+		pool = mvpp2_bm_cookie_pool_get(bm);
+		bm_pool = &port->priv->bm_pools[pool];
+		/* Check if buffer header is used */
+		if (rx_status & MVPP2_RXD_BUF_HDR) {
+			mvpp2_buff_hdr_rx(port, rx_desc);
+			continue;
+		}
+
+		/* In case of an error, release the requested buffer pointer
+		 * to the Buffer Manager. This request process is controlled
+		 * by the hardware, and the information about the buffer is
+		 * comprised by the RX descriptor.
+		 */
+		if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
+			dev->stats.rx_errors++;
+			mvpp2_rx_error(port, rx_desc);
+			mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
+					  rx_desc->buf_cookie);
+			continue;
+		}
+
+		skb = (struct sk_buff *)rx_desc->buf_cookie;
+
+		rcvd_pkts++;
+		rcvd_bytes += rx_bytes;
+		atomic_inc(&bm_pool->in_use);
+
+		skb_reserve(skb, MVPP2_MH_SIZE);
+		skb_put(skb, rx_bytes);
+		skb->protocol = eth_type_trans(skb, dev);
+		mvpp2_rx_csum(port, rx_status, skb);
+
+		napi_gro_receive(&port->napi, skb);
+
+		err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+		if (err) {
+			netdev_err(port->dev, "failed to refill BM pools\n");
+			rx_filled--;
+		}
+	}
+
+	if (rcvd_pkts) {
+		struct mvpp2_pcpu_stats *stats = this_cpu_ptr(port->stats);
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->rx_packets += rcvd_pkts;
+		stats->rx_bytes   += rcvd_bytes;
+		u64_stats_update_end(&stats->syncp);
+	}
+
+	/* Update Rx queue management counters */
+	wmb();
+	mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled);
+
+	return rx_todo;
+}
+
+static inline void
+tx_desc_unmap_put(struct device *dev, struct mvpp2_tx_queue *txq,
+		  struct mvpp2_tx_desc *desc)
+{
+	dma_unmap_single(dev, desc->buf_phys_addr,
+			 desc->data_size, DMA_TO_DEVICE);
+	mvpp2_txq_desc_put(txq);
+}
+
+/* Handle tx fragmentation processing */
+static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
+				 struct mvpp2_tx_queue *aggr_txq,
+				 struct mvpp2_tx_queue *txq)
+{
+	struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
+	struct mvpp2_tx_desc *tx_desc;
+	int i;
+	dma_addr_t buf_phys_addr;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		void *addr = page_address(frag->page.p) + frag->page_offset;
+
+		tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+		tx_desc->phys_txq = txq->id;
+		tx_desc->data_size = frag->size;
+
+		buf_phys_addr = dma_map_single(port->dev->dev.parent, addr,
+					       tx_desc->data_size,
+					       DMA_TO_DEVICE);
+		if (dma_mapping_error(port->dev->dev.parent, buf_phys_addr)) {
+			mvpp2_txq_desc_put(txq);
+			goto error;
+		}
+
+		tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
+		tx_desc->buf_phys_addr = buf_phys_addr & (~MVPP2_TX_DESC_ALIGN);
+
+		if (i == (skb_shinfo(skb)->nr_frags - 1)) {
+			/* Last descriptor */
+			tx_desc->command = MVPP2_TXD_L_DESC;
+			mvpp2_txq_inc_put(txq_pcpu, skb);
+		} else {
+			/* Descriptor in the middle: Not First, Not Last */
+			tx_desc->command = 0;
+			mvpp2_txq_inc_put(txq_pcpu, NULL);
+		}
+	}
+
+	return 0;
+
+error:
+	/* Release all descriptors that were used to map fragments of
+	 * this packet, as well as the corresponding DMA mappings
+	 */
+	for (i = i - 1; i >= 0; i--) {
+		tx_desc = txq->descs + i;
+		tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+	}
+
+	return -ENOMEM;
+}
+
+/* Main tx processing */
+static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2_tx_queue *txq, *aggr_txq;
+	struct mvpp2_txq_pcpu *txq_pcpu;
+	struct mvpp2_tx_desc *tx_desc;
+	dma_addr_t buf_phys_addr;
+	int frags = 0;
+	u16 txq_id;
+	u32 tx_cmd;
+
+	txq_id = skb_get_queue_mapping(skb);
+	txq = port->txqs[txq_id];
+	txq_pcpu = this_cpu_ptr(txq->pcpu);
+	aggr_txq = &port->priv->aggr_txqs[smp_processor_id()];
+
+	frags = skb_shinfo(skb)->nr_frags + 1;
+
+	/* Check number of available descriptors */
+	if (mvpp2_aggr_desc_num_check(port->priv, aggr_txq, frags) ||
+	    mvpp2_txq_reserved_desc_num_proc(port->priv, txq,
+					     txq_pcpu, frags)) {
+		frags = 0;
+		goto out;
+	}
+
+	/* Get a descriptor for the first part of the packet */
+	tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+	tx_desc->phys_txq = txq->id;
+	tx_desc->data_size = skb_headlen(skb);
+
+	buf_phys_addr = dma_map_single(dev->dev.parent, skb->data,
+				       tx_desc->data_size, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev->dev.parent, buf_phys_addr))) {
+		mvpp2_txq_desc_put(txq);
+		frags = 0;
+		goto out;
+	}
+	tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
+	tx_desc->buf_phys_addr = buf_phys_addr & ~MVPP2_TX_DESC_ALIGN;
+
+	tx_cmd = mvpp2_skb_tx_csum(port, skb);
+
+	if (frags == 1) {
+		/* First and Last descriptor */
+		tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
+		tx_desc->command = tx_cmd;
+		mvpp2_txq_inc_put(txq_pcpu, skb);
+	} else {
+		/* First but not Last */
+		tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_PADDING_DISABLE;
+		tx_desc->command = tx_cmd;
+		mvpp2_txq_inc_put(txq_pcpu, NULL);
+
+		/* Continue with other skb fragments */
+		if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
+			tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+			frags = 0;
+			goto out;
+		}
+	}
+
+	txq_pcpu->reserved_num -= frags;
+	txq_pcpu->count += frags;
+	aggr_txq->count += frags;
+
+	/* Enable transmit */
+	wmb();
+	mvpp2_aggr_txq_pend_desc_add(port, frags);
+
+	if (txq_pcpu->size - txq_pcpu->count < MAX_SKB_FRAGS + 1) {
+		struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
+
+		netif_tx_stop_queue(nq);
+	}
+out:
+	if (frags > 0) {
+		struct mvpp2_pcpu_stats *stats = this_cpu_ptr(port->stats);
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->tx_packets++;
+		stats->tx_bytes += skb->len;
+		u64_stats_update_end(&stats->syncp);
+	} else {
+		dev->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+	}
+
+	return NETDEV_TX_OK;
+}
+
+static inline void mvpp2_cause_error(struct net_device *dev, int cause)
+{
+	if (cause & MVPP2_CAUSE_FCS_ERR_MASK)
+		netdev_err(dev, "FCS error\n");
+	if (cause & MVPP2_CAUSE_RX_FIFO_OVERRUN_MASK)
+		netdev_err(dev, "rx fifo overrun error\n");
+	if (cause & MVPP2_CAUSE_TX_FIFO_UNDERRUN_MASK)
+		netdev_err(dev, "tx fifo underrun error\n");
+}
+
+static void mvpp2_txq_done_percpu(void *arg)
+{
+	struct mvpp2_port *port = arg;
+	u32 cause_rx_tx, cause_tx, cause_misc;
+
+	/* Rx/Tx cause register
+	 *
+	 * Bits 0-15: each bit indicates received packets on the Rx queue
+	 * (bit 0 is for Rx queue 0).
+	 *
+	 * Bits 16-23: each bit indicates transmitted packets on the Tx queue
+	 * (bit 16 is for Tx queue 0).
+	 *
+	 * Each CPU has its own Rx/Tx cause register
+	 */
+	cause_rx_tx = mvpp2_read(port->priv,
+				 MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
+	cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
+	cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
+
+	if (cause_misc) {
+		mvpp2_cause_error(port->dev, cause_misc);
+
+		/* Clear the cause register */
+		mvpp2_write(port->priv, MVPP2_ISR_MISC_CAUSE_REG, 0);
+		mvpp2_write(port->priv, MVPP2_ISR_RX_TX_CAUSE_REG(port->id),
+			    cause_rx_tx & ~MVPP2_CAUSE_MISC_SUM_MASK);
+	}
+
+	/* Release TX descriptors */
+	if (cause_tx) {
+		struct mvpp2_tx_queue *txq = mvpp2_get_tx_queue(port, cause_tx);
+		struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
+
+		if (txq_pcpu->count)
+			mvpp2_txq_done(port, txq, txq_pcpu);
+	}
+}
+
+static int mvpp2_poll(struct napi_struct *napi, int budget)
+{
+	u32 cause_rx_tx, cause_rx;
+	int rx_done = 0;
+	struct mvpp2_port *port = netdev_priv(napi->dev);
+
+	on_each_cpu(mvpp2_txq_done_percpu, port, 1);
+
+	cause_rx_tx = mvpp2_read(port->priv,
+				 MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
+	cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK;
+
+	/* Process RX packets */
+	cause_rx |= port->pending_cause_rx;
+	while (cause_rx && budget > 0) {
+		int count;
+		struct mvpp2_rx_queue *rxq;
+
+		rxq = mvpp2_get_rx_queue(port, cause_rx);
+		if (!rxq)
+			break;
+
+		count = mvpp2_rx(port, budget, rxq);
+		rx_done += count;
+		budget -= count;
+		if (budget > 0) {
+			/* Clear the bit associated to this Rx queue
+			 * so that next iteration will continue from
+			 * the next Rx queue.
+			 */
+			cause_rx &= ~(1 << rxq->logic_rxq);
+		}
+	}
+
+	if (budget > 0) {
+		cause_rx = 0;
+		napi_complete(napi);
+
+		mvpp2_interrupts_enable(port);
+	}
+	port->pending_cause_rx = cause_rx;
+	return rx_done;
+}
+
+/* Set hw internals when starting port */
+static void mvpp2_start_dev(struct mvpp2_port *port)
+{
+	mvpp2_gmac_max_rx_size_set(port);
+	mvpp2_txp_max_tx_size_set(port);
+
+	napi_enable(&port->napi);
+
+	/* Enable interrupts on all CPUs */
+	mvpp2_interrupts_enable(port);
+
+	mvpp2_port_enable(port);
+	phy_start(port->phy_dev);
+	netif_tx_start_all_queues(port->dev);
+}
+
+/* Set hw internals when stopping port */
+static void mvpp2_stop_dev(struct mvpp2_port *port)
+{
+	/* Stop new packets from arriving to RXQs */
+	mvpp2_ingress_disable(port);
+
+	mdelay(10);
+
+	/* Disable interrupts on all CPUs */
+	mvpp2_interrupts_disable(port);
+
+	napi_disable(&port->napi);
+
+	netif_carrier_off(port->dev);
+	netif_tx_stop_all_queues(port->dev);
+
+	mvpp2_egress_disable(port);
+	mvpp2_port_disable(port);
+	phy_stop(port->phy_dev);
+}
+
+/* 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)
+{
+	u16 new_rx_pending = ring->rx_pending;
+	u16 new_tx_pending = ring->tx_pending;
+
+	if (ring->rx_pending == 0 || ring->tx_pending == 0)
+		return -EINVAL;
+
+	if (ring->rx_pending > MVPP2_MAX_RXD)
+		new_rx_pending = MVPP2_MAX_RXD;
+	else if (!IS_ALIGNED(ring->rx_pending, 16))
+		new_rx_pending = ALIGN(ring->rx_pending, 16);
+
+	if (ring->tx_pending > MVPP2_MAX_TXD)
+		new_tx_pending = MVPP2_MAX_TXD;
+	else if (!IS_ALIGNED(ring->tx_pending, 32))
+		new_tx_pending = ALIGN(ring->tx_pending, 32);
+
+	if (ring->rx_pending != new_rx_pending) {
+		netdev_info(dev, "illegal Rx ring size value %d, round to %d\n",
+			    ring->rx_pending, new_rx_pending);
+		ring->rx_pending = new_rx_pending;
+	}
+
+	if (ring->tx_pending != new_tx_pending) {
+		netdev_info(dev, "illegal Tx ring size value %d, round to %d\n",
+			    ring->tx_pending, new_tx_pending);
+		ring->tx_pending = new_tx_pending;
+	}
+
+	return 0;
+}
+
+static void mvpp2_get_mac_address(struct mvpp2_port *port, unsigned char *addr)
+{
+	u32 mac_addr_l, mac_addr_m, mac_addr_h;
+
+	mac_addr_l = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+	mac_addr_m = readl(port->priv->lms_base + MVPP2_SRC_ADDR_MIDDLE);
+	mac_addr_h = readl(port->priv->lms_base + MVPP2_SRC_ADDR_HIGH);
+	addr[0] = (mac_addr_h >> 24) & 0xFF;
+	addr[1] = (mac_addr_h >> 16) & 0xFF;
+	addr[2] = (mac_addr_h >> 8) & 0xFF;
+	addr[3] = mac_addr_h & 0xFF;
+	addr[4] = mac_addr_m & 0xFF;
+	addr[5] = (mac_addr_l >> MVPP2_GMAC_SA_LOW_OFFS) & 0xFF;
+}
+
+static int mvpp2_phy_connect(struct mvpp2_port *port)
+{
+	struct phy_device *phy_dev;
+
+	phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
+				 port->phy_interface);
+	if (!phy_dev) {
+		netdev_err(port->dev, "cannot connect to phy\n");
+		return -ENODEV;
+	}
+	phy_dev->supported &= PHY_GBIT_FEATURES;
+	phy_dev->advertising = phy_dev->supported;
+
+	port->phy_dev = phy_dev;
+	port->link    = 0;
+	port->duplex  = 0;
+	port->speed   = 0;
+
+	return 0;
+}
+
+static void mvpp2_phy_disconnect(struct mvpp2_port *port)
+{
+	phy_disconnect(port->phy_dev);
+	port->phy_dev = NULL;
+}
+
+static int mvpp2_open(struct net_device *dev)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	unsigned char mac_bcast[ETH_ALEN] = {
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int err;
+
+	err = mvpp2_prs_mac_da_accept(port->priv, port->id, mac_bcast, true);
+	if (err) {
+		netdev_err(dev, "mvpp2_prs_mac_da_accept BC failed\n");
+		return err;
+	}
+	err = mvpp2_prs_mac_da_accept(port->priv, port->id,
+				      dev->dev_addr, true);
+	if (err) {
+		netdev_err(dev, "mvpp2_prs_mac_da_accept MC failed\n");
+		return err;
+	}
+	err = mvpp2_prs_tag_mode_set(port->priv, port->id, MVPP2_TAG_TYPE_MH);
+	if (err) {
+		netdev_err(dev, "mvpp2_prs_tag_mode_set failed\n");
+		return err;
+	}
+	err = mvpp2_prs_def_flow(port);
+	if (err) {
+		netdev_err(dev, "mvpp2_prs_def_flow failed\n");
+		return err;
+	}
+
+	/* Allocate the Rx/Tx queues */
+	err = mvpp2_setup_rxqs(port);
+	if (err) {
+		netdev_err(port->dev, "cannot allocate Rx queues\n");
+		return err;
+	}
+
+	err = mvpp2_setup_txqs(port);
+	if (err) {
+		netdev_err(port->dev, "cannot allocate Tx queues\n");
+		goto err_cleanup_rxqs;
+	}
+
+	err = request_irq(port->irq, mvpp2_isr, 0, dev->name, port);
+	if (err) {
+		netdev_err(port->dev, "cannot request IRQ %d\n", port->irq);
+		goto err_cleanup_txqs;
+	}
+
+	/* In default link is down */
+	netif_carrier_off(port->dev);
+
+	err = mvpp2_phy_connect(port);
+	if (err < 0)
+		goto err_free_irq;
+
+	/* Unmask interrupts on all CPUs */
+	on_each_cpu(mvpp2_interrupts_unmask, port, 1);
+
+	mvpp2_start_dev(port);
+
+	return 0;
+
+err_free_irq:
+	free_irq(port->irq, port);
+err_cleanup_txqs:
+	mvpp2_cleanup_txqs(port);
+err_cleanup_rxqs:
+	mvpp2_cleanup_rxqs(port);
+	return err;
+}
+
+static int mvpp2_stop(struct net_device *dev)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	mvpp2_stop_dev(port);
+	mvpp2_phy_disconnect(port);
+
+	/* Mask interrupts on all CPUs */
+	on_each_cpu(mvpp2_interrupts_mask, port, 1);
+
+	free_irq(port->irq, port);
+	mvpp2_cleanup_rxqs(port);
+	mvpp2_cleanup_txqs(port);
+
+	return 0;
+}
+
+static void mvpp2_set_rx_mode(struct net_device *dev)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2 *priv = port->priv;
+	struct netdev_hw_addr *ha;
+	int id = port->id;
+	bool allmulti = dev->flags & IFF_ALLMULTI;
+
+	mvpp2_prs_mac_promisc_set(priv, id, dev->flags & IFF_PROMISC);
+	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_ALL, allmulti);
+	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_IP6, allmulti);
+
+	/* Remove all port->id's mcast enries */
+	mvpp2_prs_mcast_del_all(priv, id);
+
+	if (allmulti && !netdev_mc_empty(dev)) {
+		netdev_for_each_mc_addr(ha, dev)
+			mvpp2_prs_mac_da_accept(priv, id, ha->addr, true);
+	}
+}
+
+static int mvpp2_set_mac_address(struct net_device *dev, void *p)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	const struct sockaddr *addr = p;
+	int err;
+
+	if (!is_valid_ether_addr(addr->sa_data)) {
+		err = -EADDRNOTAVAIL;
+		goto error;
+	}
+
+	if (!netif_running(dev)) {
+		err = mvpp2_prs_update_mac_da(dev, addr->sa_data);
+		if (!err)
+			return 0;
+		/* Reconfigure parser to accept the original MAC address */
+		err = mvpp2_prs_update_mac_da(dev, dev->dev_addr);
+		if (err)
+			goto error;
+	}
+
+	mvpp2_stop_dev(port);
+
+	err = mvpp2_prs_update_mac_da(dev, addr->sa_data);
+	if (!err)
+		goto out_start;
+
+	/* Reconfigure parser accept the original MAC address */
+	err = mvpp2_prs_update_mac_da(dev, dev->dev_addr);
+	if (err)
+		goto error;
+out_start:
+	mvpp2_start_dev(port);
+	mvpp2_egress_enable(port);
+	mvpp2_ingress_enable(port);
+	return 0;
+
+error:
+	netdev_err(dev, "fail to change MAC address\n");
+	return err;
+}
+
+static int mvpp2_change_mtu(struct net_device *dev, int mtu)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int err;
+
+	mtu = mvpp2_check_mtu_valid(dev, mtu);
+	if (mtu < 0) {
+		err = mtu;
+		goto error;
+	}
+
+	if (!netif_running(dev)) {
+		err = mvpp2_bm_update_mtu(dev, mtu);
+		if (!err) {
+			port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
+			return 0;
+		}
+
+		/* Reconfigure BM to the original MTU */
+		err = mvpp2_bm_update_mtu(dev, dev->mtu);
+		if (err)
+			goto error;
+	}
+
+	mvpp2_stop_dev(port);
+
+	err = mvpp2_bm_update_mtu(dev, mtu);
+	if (!err) {
+		port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
+		goto out_start;
+	}
+
+	/* Reconfigure BM to the original MTU */
+	err = mvpp2_bm_update_mtu(dev, dev->mtu);
+	if (err)
+		goto error;
+
+out_start:
+	mvpp2_start_dev(port);
+	mvpp2_egress_enable(port);
+	mvpp2_ingress_enable(port);
+
+	return 0;
+
+error:
+	netdev_err(dev, "fail to change MTU\n");
+	return err;
+}
+
+static struct rtnl_link_stats64 *
+mvpp2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	unsigned int start;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct mvpp2_pcpu_stats *cpu_stats;
+		u64 rx_packets;
+		u64 rx_bytes;
+		u64 tx_packets;
+		u64 tx_bytes;
+
+		cpu_stats = per_cpu_ptr(port->stats, cpu);
+		do {
+			start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
+			rx_packets = cpu_stats->rx_packets;
+			rx_bytes   = cpu_stats->rx_bytes;
+			tx_packets = cpu_stats->tx_packets;
+			tx_bytes   = cpu_stats->tx_bytes;
+		} while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
+
+		stats->rx_packets += rx_packets;
+		stats->rx_bytes   += rx_bytes;
+		stats->tx_packets += tx_packets;
+		stats->tx_bytes   += tx_bytes;
+	}
+
+	stats->rx_errors	= dev->stats.rx_errors;
+	stats->rx_dropped	= dev->stats.rx_dropped;
+	stats->tx_dropped	= dev->stats.tx_dropped;
+
+	return stats;
+}
+
+static int mvpp2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int ret;
+
+	if (!port->phy_dev)
+		return -ENOTSUPP;
+
+	ret = phy_mii_ioctl(port->phy_dev, ifr, cmd);
+	if (!ret)
+		mvpp2_link_event(dev);
+
+	return ret;
+}
+
+/* Ethtool methods */
+
+/* Get settings (phy address, speed) for ethtools */
+static int mvpp2_ethtool_get_settings(struct net_device *dev,
+				      struct ethtool_cmd *cmd)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	if (!port->phy_dev)
+		return -ENODEV;
+	return phy_ethtool_gset(port->phy_dev, cmd);
+}
+
+/* Set settings (phy address, speed) for ethtools */
+static int mvpp2_ethtool_set_settings(struct net_device *dev,
+				      struct ethtool_cmd *cmd)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	if (!port->phy_dev)
+		return -ENODEV;
+	return phy_ethtool_sset(port->phy_dev, cmd);
+}
+
+/* Set interrupt coalescing for ethtools */
+static int mvpp2_ethtool_set_coalesce(struct net_device *dev,
+				      struct ethtool_coalesce *c)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int queue;
+
+	for (queue = 0; queue < rxq_number; queue++) {
+		struct mvpp2_rx_queue *rxq = port->rxqs[queue];
+
+		rxq->time_coal = c->rx_coalesce_usecs;
+		rxq->pkts_coal = c->rx_max_coalesced_frames;
+		mvpp2_rx_pkts_coal_set(port, rxq, rxq->pkts_coal);
+		mvpp2_rx_time_coal_set(port, rxq, rxq->time_coal);
+	}
+
+	for (queue = 0; queue < txq_number; queue++) {
+		struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+		txq->done_pkts_coal = c->tx_max_coalesced_frames;
+	}
+
+	on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
+	return 0;
+}
+
+/* get coalescing for ethtools */
+static int mvpp2_ethtool_get_coalesce(struct net_device *dev,
+				      struct ethtool_coalesce *c)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	c->rx_coalesce_usecs        = port->rxqs[0]->time_coal;
+	c->rx_max_coalesced_frames  = port->rxqs[0]->pkts_coal;
+	c->tx_max_coalesced_frames =  port->txqs[0]->done_pkts_coal;
+	return 0;
+}
+
+static void mvpp2_ethtool_get_drvinfo(struct net_device *dev,
+				      struct ethtool_drvinfo *drvinfo)
+{
+	strlcpy(drvinfo->driver, MVPP2_DRIVER_NAME,
+		sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, MVPP2_DRIVER_VERSION,
+		sizeof(drvinfo->version));
+	strlcpy(drvinfo->bus_info, dev_name(&dev->dev),
+		sizeof(drvinfo->bus_info));
+}
+
+static void mvpp2_ethtool_get_ringparam(struct net_device *dev,
+					struct ethtool_ringparam *ring)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	ring->rx_max_pending = MVPP2_MAX_RXD;
+	ring->tx_max_pending = MVPP2_MAX_TXD;
+	ring->rx_pending = port->rx_ring_size;
+	ring->tx_pending = port->tx_ring_size;
+}
+
+static int mvpp2_ethtool_set_ringparam(struct net_device *dev,
+				       struct ethtool_ringparam *ring)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	u16 prev_rx_ring_size = port->rx_ring_size;
+	u16 prev_tx_ring_size = port->tx_ring_size;
+	int err;
+
+	err = mvpp2_check_ringparam_valid(dev, ring);
+	if (err)
+		return err;
+
+	if (!netif_running(dev)) {
+		port->rx_ring_size = ring->rx_pending;
+		port->tx_ring_size = ring->tx_pending;
+		return 0;
+	}
+
+	/* The interface is running, so we have to force a
+	 * reallocation of the queues
+	 */
+	mvpp2_stop_dev(port);
+	mvpp2_cleanup_rxqs(port);
+	mvpp2_cleanup_txqs(port);
+
+	port->rx_ring_size = ring->rx_pending;
+	port->tx_ring_size = ring->tx_pending;
+
+	err = mvpp2_setup_rxqs(port);
+	if (err) {
+		/* Reallocate Rx queues with the original ring size */
+		port->rx_ring_size = prev_rx_ring_size;
+		ring->rx_pending = prev_rx_ring_size;
+		err = mvpp2_setup_rxqs(port);
+		if (err)
+			goto err_out;
+	}
+	err = mvpp2_setup_txqs(port);
+	if (err) {
+		/* Reallocate Tx queues with the original ring size */
+		port->tx_ring_size = prev_tx_ring_size;
+		ring->tx_pending = prev_tx_ring_size;
+		err = mvpp2_setup_txqs(port);
+		if (err)
+			goto err_clean_rxqs;
+	}
+
+	mvpp2_start_dev(port);
+	mvpp2_egress_enable(port);
+	mvpp2_ingress_enable(port);
+
+	return 0;
+
+err_clean_rxqs:
+	mvpp2_cleanup_rxqs(port);
+err_out:
+	netdev_err(dev, "fail to change ring parameters");
+	return err;
+}
+
+/* Device ops */
+
+static const struct net_device_ops mvpp2_netdev_ops = {
+	.ndo_open		= mvpp2_open,
+	.ndo_stop		= mvpp2_stop,
+	.ndo_start_xmit		= mvpp2_tx,
+	.ndo_set_rx_mode	= mvpp2_set_rx_mode,
+	.ndo_set_mac_address	= mvpp2_set_mac_address,
+	.ndo_change_mtu		= mvpp2_change_mtu,
+	.ndo_get_stats64	= mvpp2_get_stats64,
+	.ndo_do_ioctl		= mvpp2_ioctl,
+};
+
+static const struct ethtool_ops mvpp2_eth_tool_ops = {
+	.get_link	= ethtool_op_get_link,
+	.get_settings	= mvpp2_ethtool_get_settings,
+	.set_settings	= mvpp2_ethtool_set_settings,
+	.set_coalesce	= mvpp2_ethtool_set_coalesce,
+	.get_coalesce	= mvpp2_ethtool_get_coalesce,
+	.get_drvinfo	= mvpp2_ethtool_get_drvinfo,
+	.get_ringparam	= mvpp2_ethtool_get_ringparam,
+	.set_ringparam	= mvpp2_ethtool_set_ringparam,
+};
+
+/* Driver initialization */
+
+static void mvpp2_port_power_up(struct mvpp2_port *port)
+{
+	mvpp2_port_mii_set(port);
+	mvpp2_port_periodic_xon_disable(port);
+	mvpp2_port_fc_adv_enable(port);
+	mvpp2_port_reset(port);
+}
+
+/* Initialize port HW */
+static int mvpp2_port_init(struct mvpp2_port *port)
+{
+	struct device *dev = port->dev->dev.parent;
+	struct mvpp2 *priv = port->priv;
+	struct mvpp2_txq_pcpu *txq_pcpu;
+	int queue, cpu, err;
+
+	if (port->first_rxq + rxq_number > MVPP2_RXQ_TOTAL_NUM)
+		return -EINVAL;
+
+	/* Disable port */
+	mvpp2_egress_disable(port);
+	mvpp2_port_disable(port);
+
+	port->txqs = devm_kcalloc(dev, txq_number, sizeof(*port->txqs),
+				  GFP_KERNEL);
+	if (!port->txqs)
+		return -ENOMEM;
+
+	/* Associate physical Tx queues to this port and initialize.
+	 * The mapping is predefined.
+	 */
+	for (queue = 0; queue < txq_number; queue++) {
+		int queue_phy_id = mvpp2_txq_phys(port->id, queue);
+		struct mvpp2_tx_queue *txq;
+
+		txq = devm_kzalloc(dev, sizeof(*txq), GFP_KERNEL);
+		if (!txq)
+			return -ENOMEM;
+
+		txq->pcpu = alloc_percpu(struct mvpp2_txq_pcpu);
+		if (!txq->pcpu) {
+			err = -ENOMEM;
+			goto err_free_percpu;
+		}
+
+		txq->id = queue_phy_id;
+		txq->log_id = queue;
+		txq->done_pkts_coal = MVPP2_TXDONE_COAL_PKTS_THRESH;
+		for_each_present_cpu(cpu) {
+			txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+			txq_pcpu->cpu = cpu;
+		}
+
+		port->txqs[queue] = txq;
+	}
+
+	port->rxqs = devm_kcalloc(dev, rxq_number, sizeof(*port->rxqs),
+				  GFP_KERNEL);
+	if (!port->rxqs) {
+		err = -ENOMEM;
+		goto err_free_percpu;
+	}
+
+	/* Allocate and initialize Rx queue for this port */
+	for (queue = 0; queue < rxq_number; queue++) {
+		struct mvpp2_rx_queue *rxq;
+
+		/* Map physical Rx queue to port's logical Rx queue */
+		rxq = devm_kzalloc(dev, sizeof(*rxq), GFP_KERNEL);
+		if (!rxq)
+			goto err_free_percpu;
+		/* Map this Rx queue to a physical queue */
+		rxq->id = port->first_rxq + queue;
+		rxq->port = port->id;
+		rxq->logic_rxq = queue;
+
+		port->rxqs[queue] = rxq;
+	}
+
+	/* Configure Rx queue group interrupt for this port */
+	mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(port->id), rxq_number);
+
+	/* Create Rx descriptor rings */
+	for (queue = 0; queue < rxq_number; queue++) {
+		struct mvpp2_rx_queue *rxq = port->rxqs[queue];
+
+		rxq->size = port->rx_ring_size;
+		rxq->pkts_coal = MVPP2_RX_COAL_PKTS;
+		rxq->time_coal = MVPP2_RX_COAL_USEC;
+	}
+
+	mvpp2_ingress_disable(port);
+
+	/* Port default configuration */
+	mvpp2_defaults_set(port);
+
+	/* Port's classifier configuration */
+	mvpp2_cls_oversize_rxq_set(port);
+	mvpp2_cls_port_config(port);
+
+	/* Provide an initial Rx packet size */
+	port->pkt_size = MVPP2_RX_PKT_SIZE(port->dev->mtu);
+
+	/* Initialize pools for swf */
+	err = mvpp2_swf_bm_pool_init(port);
+	if (err)
+		goto err_free_percpu;
+
+	return 0;
+
+err_free_percpu:
+	for (queue = 0; queue < txq_number; queue++) {
+		if (!port->txqs[queue])
+			continue;
+		free_percpu(port->txqs[queue]->pcpu);
+	}
+	return err;
+}
+
+/* Ports initialization */
+static int mvpp2_port_probe(struct platform_device *pdev,
+			    struct device_node *port_node,
+			    struct mvpp2 *priv,
+			    int *next_first_rxq)
+{
+	struct device_node *phy_node;
+	struct mvpp2_port *port;
+	struct net_device *dev;
+	struct resource *res;
+	const char *dt_mac_addr;
+	const char *mac_from;
+	char hw_mac_addr[ETH_ALEN];
+	u32 id;
+	int features;
+	int phy_mode;
+	int priv_common_regs_num = 2;
+	int err, i;
+
+	dev = alloc_etherdev_mqs(sizeof(struct mvpp2_port), txq_number,
+				 rxq_number);
+	if (!dev)
+		return -ENOMEM;
+
+	phy_node = of_parse_phandle(port_node, "phy", 0);
+	if (!phy_node) {
+		dev_err(&pdev->dev, "missing phy\n");
+		err = -ENODEV;
+		goto err_free_netdev;
+	}
+
+	phy_mode = of_get_phy_mode(port_node);
+	if (phy_mode < 0) {
+		dev_err(&pdev->dev, "incorrect phy mode\n");
+		err = phy_mode;
+		goto err_free_netdev;
+	}
+
+	if (of_property_read_u32(port_node, "port-id", &id)) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "missing port-id value\n");
+		goto err_free_netdev;
+	}
+
+	dev->tx_queue_len = MVPP2_MAX_TXD;
+	dev->watchdog_timeo = 5 * HZ;
+	dev->netdev_ops = &mvpp2_netdev_ops;
+	dev->ethtool_ops = &mvpp2_eth_tool_ops;
+
+	port = netdev_priv(dev);
+
+	port->irq = irq_of_parse_and_map(port_node, 0);
+	if (port->irq <= 0) {
+		err = -EINVAL;
+		goto err_free_netdev;
+	}
+
+	if (of_property_read_bool(port_node, "marvell,loopback"))
+		port->flags |= MVPP2_F_LOOPBACK;
+
+	port->priv = priv;
+	port->id = id;
+	port->first_rxq = *next_first_rxq;
+	port->phy_node = phy_node;
+	port->phy_interface = phy_mode;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM,
+				    priv_common_regs_num + id);
+	port->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(port->base)) {
+		err = PTR_ERR(port->base);
+		goto err_free_irq;
+	}
+
+	/* Alloc per-cpu stats */
+	port->stats = netdev_alloc_pcpu_stats(struct mvpp2_pcpu_stats);
+	if (!port->stats) {
+		err = -ENOMEM;
+		goto err_free_irq;
+	}
+
+	dt_mac_addr = of_get_mac_address(port_node);
+	if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
+		mac_from = "device tree";
+		ether_addr_copy(dev->dev_addr, dt_mac_addr);
+	} else {
+		mvpp2_get_mac_address(port, hw_mac_addr);
+		if (is_valid_ether_addr(hw_mac_addr)) {
+			mac_from = "hardware";
+			ether_addr_copy(dev->dev_addr, hw_mac_addr);
+		} else {
+			mac_from = "random";
+			eth_hw_addr_random(dev);
+		}
+	}
+
+	port->tx_ring_size = MVPP2_MAX_TXD;
+	port->rx_ring_size = MVPP2_MAX_RXD;
+	port->dev = dev;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = mvpp2_port_init(port);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to init port %d\n", id);
+		goto err_free_stats;
+	}
+	mvpp2_port_power_up(port);
+
+	netif_napi_add(dev, &port->napi, mvpp2_poll, NAPI_POLL_WEIGHT);
+	features = NETIF_F_SG | NETIF_F_IP_CSUM;
+	dev->features = features | NETIF_F_RXCSUM;
+	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
+	dev->vlan_features |= features;
+
+	err = register_netdev(dev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register netdev\n");
+		goto err_free_txq_pcpu;
+	}
+	netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
+
+	/* Increment the first Rx queue number to be used by the next port */
+	*next_first_rxq += rxq_number;
+	priv->port_list[id] = port;
+	return 0;
+
+err_free_txq_pcpu:
+	for (i = 0; i < txq_number; i++)
+		free_percpu(port->txqs[i]->pcpu);
+err_free_stats:
+	free_percpu(port->stats);
+err_free_irq:
+	irq_dispose_mapping(port->irq);
+err_free_netdev:
+	free_netdev(dev);
+	return err;
+}
+
+/* Ports removal routine */
+static void mvpp2_port_remove(struct mvpp2_port *port)
+{
+	int i;
+
+	unregister_netdev(port->dev);
+	free_percpu(port->stats);
+	for (i = 0; i < txq_number; i++)
+		free_percpu(port->txqs[i]->pcpu);
+	irq_dispose_mapping(port->irq);
+	free_netdev(port->dev);
+}
+
+/* Initialize decoding windows */
+static void mvpp2_conf_mbus_windows(const struct mbus_dram_target_info *dram,
+				    struct mvpp2 *priv)
+{
+	u32 win_enable;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		mvpp2_write(priv, MVPP2_WIN_BASE(i), 0);
+		mvpp2_write(priv, MVPP2_WIN_SIZE(i), 0);
+
+		if (i < 4)
+			mvpp2_write(priv, MVPP2_WIN_REMAP(i), 0);
+	}
+
+	win_enable = 0;
+
+	for (i = 0; i < dram->num_cs; i++) {
+		const struct mbus_dram_window *cs = dram->cs + i;
+
+		mvpp2_write(priv, MVPP2_WIN_BASE(i),
+			    (cs->base & 0xffff0000) | (cs->mbus_attr << 8) |
+			    dram->mbus_dram_target_id);
+
+		mvpp2_write(priv, MVPP2_WIN_SIZE(i),
+			    (cs->size - 1) & 0xffff0000);
+
+		win_enable |= (1 << i);
+	}
+
+	mvpp2_write(priv, MVPP2_BASE_ADDR_ENABLE, win_enable);
+}
+
+/* Initialize Rx FIFO's */
+static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
+{
+	int port;
+
+	for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+		mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+			    MVPP2_RX_FIFO_PORT_DATA_SIZE);
+		mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+			    MVPP2_RX_FIFO_PORT_ATTR_SIZE);
+	}
+
+	mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
+		    MVPP2_RX_FIFO_PORT_MIN_PKT);
+	mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
+}
+
+/* Initialize network controller common part HW */
+static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+	const struct mbus_dram_target_info *dram_target_info;
+	int err, i;
+	u32 val;
+
+	/* Checks for hardware constraints */
+	if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) ||
+	    (txq_number > MVPP2_MAX_TXQ)) {
+		dev_err(&pdev->dev, "invalid queue size parameter\n");
+		return -EINVAL;
+	}
+
+	/* MBUS windows configuration */
+	dram_target_info = mv_mbus_dram_info();
+	if (dram_target_info)
+		mvpp2_conf_mbus_windows(dram_target_info, priv);
+
+	/* Disable HW PHY polling */
+	val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+	val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
+	writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+
+	/* Allocate and initialize aggregated TXQs */
+	priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(),
+				       sizeof(struct mvpp2_tx_queue),
+				       GFP_KERNEL);
+	if (!priv->aggr_txqs)
+		return -ENOMEM;
+
+	for_each_present_cpu(i) {
+		priv->aggr_txqs[i].id = i;
+		priv->aggr_txqs[i].size = MVPP2_AGGR_TXQ_SIZE;
+		err = mvpp2_aggr_txq_init(pdev, &priv->aggr_txqs[i],
+					  MVPP2_AGGR_TXQ_SIZE, i, priv);
+		if (err < 0)
+			return err;
+	}
+
+	/* Rx Fifo Init */
+	mvpp2_rx_fifo_init(priv);
+
+	/* Reset Rx queue group interrupt configuration */
+	for (i = 0; i < MVPP2_MAX_PORTS; i++)
+		mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(i), rxq_number);
+
+	writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+	       priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
+
+	/* Allow cache snoop when transmiting packets */
+	mvpp2_write(priv, MVPP2_TX_SNOOP_REG, 0x1);
+
+	/* Buffer Manager initialization */
+	err = mvpp2_bm_init(pdev, priv);
+	if (err < 0)
+		return err;
+
+	/* Parser default initialization */
+	err = mvpp2_prs_default_init(pdev, priv);
+	if (err < 0)
+		return err;
+
+	/* Classifier default initialization */
+	mvpp2_cls_init(priv);
+
+	return 0;
+}
+
+static int mvpp2_probe(struct platform_device *pdev)
+{
+	struct device_node *dn = pdev->dev.of_node;
+	struct device_node *port_node;
+	struct mvpp2 *priv;
+	struct resource *res;
+	int port_count, first_rxq;
+	int err;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct mvpp2), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->lms_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->lms_base))
+		return PTR_ERR(priv->lms_base);
+
+	priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
+	if (IS_ERR(priv->pp_clk))
+		return PTR_ERR(priv->pp_clk);
+	err = clk_prepare_enable(priv->pp_clk);
+	if (err < 0)
+		return err;
+
+	priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
+	if (IS_ERR(priv->gop_clk)) {
+		err = PTR_ERR(priv->gop_clk);
+		goto err_pp_clk;
+	}
+	err = clk_prepare_enable(priv->gop_clk);
+	if (err < 0)
+		goto err_pp_clk;
+
+	/* Get system's tclk rate */
+	priv->tclk = clk_get_rate(priv->pp_clk);
+
+	/* Initialize network controller */
+	err = mvpp2_init(pdev, priv);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to initialize controller\n");
+		goto err_gop_clk;
+	}
+
+	port_count = of_get_available_child_count(dn);
+	if (port_count == 0) {
+		dev_err(&pdev->dev, "no ports enabled\n");
+		err = -ENODEV;
+		goto err_gop_clk;
+	}
+
+	priv->port_list = devm_kcalloc(&pdev->dev, port_count,
+				      sizeof(struct mvpp2_port *),
+				      GFP_KERNEL);
+	if (!priv->port_list) {
+		err = -ENOMEM;
+		goto err_gop_clk;
+	}
+
+	/* Initialize ports */
+	first_rxq = 0;
+	for_each_available_child_of_node(dn, port_node) {
+		err = mvpp2_port_probe(pdev, port_node, priv, &first_rxq);
+		if (err < 0)
+			goto err_gop_clk;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	return 0;
+
+err_gop_clk:
+	clk_disable_unprepare(priv->gop_clk);
+err_pp_clk:
+	clk_disable_unprepare(priv->pp_clk);
+	return err;
+}
+
+static int mvpp2_remove(struct platform_device *pdev)
+{
+	struct mvpp2 *priv = platform_get_drvdata(pdev);
+	struct device_node *dn = pdev->dev.of_node;
+	struct device_node *port_node;
+	int i = 0;
+
+	for_each_available_child_of_node(dn, port_node) {
+		if (priv->port_list[i])
+			mvpp2_port_remove(priv->port_list[i]);
+		i++;
+	}
+
+	for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+		struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
+
+		mvpp2_bm_pool_destroy(pdev, priv, bm_pool);
+	}
+
+	for_each_present_cpu(i) {
+		struct mvpp2_tx_queue *aggr_txq = &priv->aggr_txqs[i];
+
+		dma_free_coherent(&pdev->dev,
+				  MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+				  aggr_txq->descs,
+				  aggr_txq->descs_phys);
+	}
+
+	clk_disable_unprepare(priv->pp_clk);
+	clk_disable_unprepare(priv->gop_clk);
+
+	return 0;
+}
+
+static const struct of_device_id mvpp2_match[] = {
+	{ .compatible = "marvell,armada-375-pp2" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mvpp2_match);
+
+static struct platform_driver mvpp2_driver = {
+	.probe = mvpp2_probe,
+	.remove = mvpp2_remove,
+	.driver = {
+		.name = MVPP2_DRIVER_NAME,
+		.of_match_table = mvpp2_match,
+	},
+};
+
+module_platform_driver(mvpp2_driver);
+
+MODULE_DESCRIPTION("Marvell PPv2 Ethernet Driver - www.marvell.com");
+MODULE_AUTHOR("Marcin Wojtas <mw@semihalf.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/skge.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/skge.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/skge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/skge.c	2014-09-28 17:29:07.000000000 -0400
@@ -82,7 +82,7 @@ static int debug = -1;	/* defaults above
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
-static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = {
+static const struct pci_device_id skge_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) },	  /* 3Com 3C940 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) },	  /* 3Com 3C940B */
 #ifdef CONFIG_SKGE_GENESIS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/marvell/sky2.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/sky2.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/marvell/sky2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/marvell/sky2.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ static int legacy_pme = 0;
 module_param(legacy_pme, int, 0);
 MODULE_PARM_DESC(legacy_pme, "Legacy power management");
 
-static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
+static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E01) }, /* SK-9E21M */
@@ -1622,11 +1622,10 @@ static int sky2_alloc_buffers(struct sky
 	if (!sky2->tx_ring)
 		goto nomem;
 
-	sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
-					   &sky2->rx_le_map);
+	sky2->rx_le = pci_zalloc_consistent(hw->pdev, RX_LE_BYTES,
+					    &sky2->rx_le_map);
 	if (!sky2->rx_le)
 		goto nomem;
-	memset(sky2->rx_le, 0, RX_LE_BYTES);
 
 	sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
 				GFP_KERNEL);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1311,6 +1311,15 @@ static struct mlx4_cmd_info cmd_info[] =
 		.wrapper = mlx4_MAD_IFC_wrapper
 	},
 	{
+		.opcode = MLX4_CMD_MAD_DEMUX,
+		.has_inbox = false,
+		.has_outbox = false,
+		.out_is_imm = false,
+		.encode_slave_id = false,
+		.verify = NULL,
+		.wrapper = mlx4_CMD_EPERM_wrapper
+	},
+	{
 		.opcode = MLX4_CMD_QUERY_IF_STAT,
 		.has_inbox = false,
 		.has_outbox = true,
@@ -2380,6 +2389,22 @@ struct mlx4_slaves_pport mlx4_phys_to_sl
 }
 EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport_actv);
 
+static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port)
+{
+	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
+	int min_port = find_first_bit(actv_ports.ports, dev->caps.num_ports)
+			+ 1;
+	int max_port = min_port +
+		bitmap_weight(actv_ports.ports, dev->caps.num_ports);
+
+	if (port < min_port)
+		port = min_port;
+	else if (port >= max_port)
+		port = max_port - 1;
+
+	return port;
+}
+
 int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -2393,6 +2418,7 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev
 	if (slave < 0)
 		return -EINVAL;
 
+	port = mlx4_slaves_closest_port(dev, slave, port);
 	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
 	s_info->mac = mac;
 	mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
@@ -2419,6 +2445,7 @@ int mlx4_set_vf_vlan(struct mlx4_dev *de
 	if (slave < 0)
 		return -EINVAL;
 
+	port = mlx4_slaves_closest_port(dev, slave, port);
 	vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
 
 	if ((0 == vlan) && (0 == qos))
@@ -2446,6 +2473,7 @@ bool mlx4_get_slave_default_vlan(struct
 	struct mlx4_priv *priv;
 
 	priv = mlx4_priv(dev);
+	port = mlx4_slaves_closest_port(dev, slave, port);
 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
 
 	if (MLX4_VGT != vp_oper->state.default_vlan) {
@@ -2473,6 +2501,7 @@ int mlx4_set_vf_spoofchk(struct mlx4_dev
 	if (slave < 0)
 		return -EINVAL;
 
+	port = mlx4_slaves_closest_port(dev, slave, port);
 	s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
 	s_info->spoofchk = setting;
 
@@ -2526,6 +2555,7 @@ int mlx4_set_vf_link_state(struct mlx4_d
 	if (slave < 0)
 		return -EINVAL;
 
+	port = mlx4_slaves_closest_port(dev, slave, port);
 	switch (link_state) {
 	case IFLA_VF_LINK_STATE_AUTO:
 		/* get current link state */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,6 +98,10 @@ mlx4_en_get_drvinfo(struct net_device *d
 	drvinfo->eedump_len = 0;
 }
 
+static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
+	"blueflame",
+};
+
 static const char main_strings[][ETH_GSTRING_LEN] = {
 	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
 	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@@ -235,6 +239,8 @@ static int mlx4_en_get_sset_count(struct
 	case ETH_SS_TEST:
 		return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
 					& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
+	case ETH_SS_PRIV_FLAGS:
+		return ARRAY_SIZE(mlx4_en_priv_flags);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -358,6 +364,12 @@ static void mlx4_en_get_strings(struct n
 #endif
 		}
 		break;
+	case ETH_SS_PRIV_FLAGS:
+		for (i = 0; i < ARRAY_SIZE(mlx4_en_priv_flags); i++)
+			strcpy(data + i * ETH_GSTRING_LEN,
+			       mlx4_en_priv_flags[i]);
+		break;
+
 	}
 }
 
@@ -475,6 +487,9 @@ static int mlx4_en_set_pauseparam(struct
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
 
+	if (pause->autoneg)
+		return -EINVAL;
+
 	priv->prof->tx_pause = pause->tx_pause != 0;
 	priv->prof->rx_pause = pause->rx_pause != 0;
 	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
@@ -1209,6 +1224,49 @@ static int mlx4_en_get_ts_info(struct ne
 	return ret;
 }
 
+static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+	bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+	int i;
+
+	if (bf_enabled_new == bf_enabled_old)
+		return 0; /* Nothing to do */
+
+	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;
+
+		if (!bf_supported) {
+			en_err(priv, "BlueFlame is not supported\n");
+			return -EINVAL;
+		}
+
+		priv->pflags |= MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+	} else {
+		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;
+
+	en_info(priv, "BlueFlame %s\n",
+		bf_enabled_new ?  "Enabled" : "Disabled");
+
+	return 0;
+}
+
+static u32 mlx4_en_get_priv_flags(struct net_device *dev)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	return priv->pflags;
+}
+
+
 const struct ethtool_ops mlx4_en_ethtool_ops = {
 	.get_drvinfo = mlx4_en_get_drvinfo,
 	.get_settings = mlx4_en_get_settings,
@@ -1236,6 +1294,8 @@ const struct ethtool_ops mlx4_en_ethtool
 	.get_channels = mlx4_en_get_channels,
 	.set_channels = mlx4_en_set_channels,
 	.get_ts_info = mlx4_en_get_ts_info,
+	.set_priv_flags = mlx4_en_set_priv_flags,
+	.get_priv_flags = mlx4_en_get_priv_flags,
 };
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,8 +129,10 @@ static int mlx4_en_get_profile(struct ml
 	int i;
 
 	params->udp_rss = udp_rss;
-	params->num_tx_rings_p_up = min_t(int, num_online_cpus(),
-			MLX4_EN_MAX_TX_RING_P_UP);
+	params->num_tx_rings_p_up = mlx4_low_memory_profile() ?
+		MLX4_EN_MIN_TX_RING_P_UP :
+		min_t(int, num_online_cpus(), MLX4_EN_MAX_TX_RING_P_UP);
+
 	if (params->udp_rss && !(mdev->dev->caps.flags
 					& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
 		mlx4_warn(mdev, "UDP RSS is not supported on this device\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -474,39 +474,12 @@ static int mlx4_en_tunnel_steer_add(stru
 				    int qpn, u64 *reg_id)
 {
 	int err;
-	struct mlx4_spec_list spec_eth_outer = { {NULL} };
-	struct mlx4_spec_list spec_vxlan     = { {NULL} };
-	struct mlx4_spec_list spec_eth_inner = { {NULL} };
-
-	struct mlx4_net_trans_rule rule = {
-		.queue_mode = MLX4_NET_TRANS_Q_FIFO,
-		.exclusive = 0,
-		.allow_loopback = 1,
-		.promisc_mode = MLX4_FS_REGULAR,
-		.priority = MLX4_DOMAIN_NIC,
-	};
-
-	__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
 
 	if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
 		return 0; /* do nothing */
 
-	rule.port = priv->port;
-	rule.qpn = qpn;
-	INIT_LIST_HEAD(&rule.list);
-
-	spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
-	memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
-	memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
-
-	spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN;    /* any vxlan header */
-	spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH;	 /* any inner eth header */
-
-	list_add_tail(&spec_eth_outer.list, &rule.list);
-	list_add_tail(&spec_vxlan.list,     &rule.list);
-	list_add_tail(&spec_eth_inner.list, &rule.list);
-
-	err = mlx4_flow_attach(priv->mdev->dev, &rule, reg_id);
+	err = mlx4_tunnel_steer_add(priv->mdev->dev, addr, priv->port, qpn,
+				    MLX4_DOMAIN_NIC, reg_id);
 	if (err) {
 		en_err(priv, "failed to add vxlan steering rule, err %d\n", err);
 		return err;
@@ -644,6 +617,7 @@ static int mlx4_en_get_qp(struct mlx4_en
 		goto alloc_err;
 	}
 	memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
+	memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
 	entry->reg_id = reg_id;
 
 	hlist_add_head_rcu(&entry->hlist,
@@ -760,21 +734,22 @@ static int mlx4_en_replace_mac(struct ml
 	return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64);
 }
 
-static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
+static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv,
+			      unsigned char new_mac[ETH_ALEN + 2])
 {
 	int err = 0;
 
 	if (priv->port_up) {
 		/* Remove old MAC and insert the new one */
 		err = mlx4_en_replace_mac(priv, priv->base_qpn,
-					  priv->dev->dev_addr, priv->prev_mac);
+					  new_mac, priv->current_mac);
 		if (err)
 			en_err(priv, "Failed changing HW MAC address\n");
 	} else
 		en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
 
-	memcpy(priv->prev_mac, priv->dev->dev_addr,
-	       sizeof(priv->prev_mac));
+	if (!err)
+		memcpy(priv->current_mac, new_mac, sizeof(priv->current_mac));
 
 	return err;
 }
@@ -784,14 +759,17 @@ static int mlx4_en_set_mac(struct net_de
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct sockaddr *saddr = addr;
+	unsigned char new_mac[ETH_ALEN + 2];
 	int err;
 
 	if (!is_valid_ether_addr(saddr->sa_data))
 		return -EADDRNOTAVAIL;
 
 	mutex_lock(&mdev->state_lock);
-	memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
-	err = mlx4_en_do_set_mac(priv);
+	memcpy(new_mac, saddr->sa_data, ETH_ALEN);
+	err = mlx4_en_do_set_mac(priv, new_mac);
+	if (!err)
+		memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
 	mutex_unlock(&mdev->state_lock);
 
 	return err;
@@ -940,11 +918,6 @@ static void mlx4_en_set_promisc_mode(str
 					  0, MLX4_MCAST_DISABLE);
 		if (err)
 			en_err(priv, "Failed disabling multicast filter\n");
-
-		/* Disable port VLAN filter */
-		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
-		if (err)
-			en_err(priv, "Failed disabling VLAN filter\n");
 	}
 }
 
@@ -993,11 +966,6 @@ static void mlx4_en_clear_promisc_mode(s
 			en_err(priv, "Failed disabling promiscuous mode\n");
 		break;
 	}
-
-	/* Enable port VLAN filter */
-	err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
-	if (err)
-		en_err(priv, "Failed enabling VLAN filter\n");
 }
 
 static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
@@ -1166,7 +1134,8 @@ static void mlx4_en_do_uc_filter(struct
 			}
 
 			/* MAC address of the port is not in uc list */
-			if (ether_addr_equal_64bits(entry->mac, dev->dev_addr))
+			if (ether_addr_equal_64bits(entry->mac,
+						    priv->current_mac))
 				found = true;
 
 			if (!found) {
@@ -1476,7 +1445,7 @@ static void mlx4_en_do_get_stats(struct
 		queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 	}
 	if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
-		mlx4_en_do_set_mac(priv);
+		mlx4_en_do_set_mac(priv, priv->current_mac);
 		mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
 	}
 	mutex_unlock(&mdev->state_lock);
@@ -2469,6 +2438,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	priv->port = port;
 	priv->port_up = false;
 	priv->flags = prof->flags;
+	priv->pflags = MLX4_EN_PRIV_FLAGS_BLUEFLAME;
 	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;
@@ -2535,7 +2505,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 		}
 	}
 
-	memcpy(priv->prev_mac, dev->dev_addr, sizeof(priv->prev_mac));
+	memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac));
 
 	priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
 					  DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -335,8 +335,9 @@ void mlx4_en_set_num_rx_rings(struct mlx
 					   dev->caps.comp_pool/
 					   dev->caps.num_ports) - 1;
 
-		num_rx_rings = min_t(int, num_of_eqs,
-				     netif_get_num_default_rss_queues());
+		num_rx_rings = mlx4_low_memory_profile() ? MIN_RX_RINGS :
+			min_t(int, num_of_eqs,
+			      netif_get_num_default_rss_queues());
 		mdev->profile.prof[i].rx_ring_num =
 			rounddown_pow_of_two(num_rx_rings);
 	}
@@ -933,7 +934,7 @@ static const int frag_sizes[] = {
 void mlx4_en_calc_rx_buf(struct net_device *dev)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN + ETH_LLC_SNAP_SIZE;
+	int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN;
 	int buf_size = 0;
 	int i = 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c	2014-09-28 17:29:07.000000000 -0400
@@ -159,7 +159,8 @@ void mlx4_en_ex_selftest(struct net_devi
 		if (priv->mdev->dev->caps.flags &
 					MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
 			buf[3] = mlx4_en_test_registers(priv);
-			buf[4] = mlx4_en_test_loopback(priv);
+			if (priv->port_up)
+				buf[4] = mlx4_en_test_loopback(priv);
 		}
 
 		if (carrier_ok)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,8 +126,13 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 		ring->bf.uar = &mdev->priv_uar;
 		ring->bf.uar->map = mdev->uar_map;
 		ring->bf_enabled = false;
-	} else
-		ring->bf_enabled = true;
+		ring->bf_alloced = false;
+		priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+	} else {
+		ring->bf_alloced = true;
+		ring->bf_enabled = !!(priv->pflags &
+				      MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+	}
 
 	ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
 	ring->queue_index = queue_index;
@@ -161,7 +166,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4
 	struct mlx4_en_tx_ring *ring = *pring;
 	en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
 
-	if (ring->bf_enabled)
+	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);
@@ -195,7 +200,7 @@ int mlx4_en_activate_tx_ring(struct mlx4
 
 	mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
 				ring->cqn, user_prio, &ring->context);
-	if (ring->bf_enabled)
+	if (ring->bf_alloced)
 		ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
 
 	err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/fw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/fw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/fw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/fw.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,7 +136,8 @@ static void dump_dev_cap_flags2(struct m
 		[7] = "FSM (MAC anti-spoofing) support",
 		[8] = "Dynamic QP updates support",
 		[9] = "Device managed flow steering IPoIB support",
-		[10] = "TCP/IP offloads/flow-steering for VXLAN support"
+		[10] = "TCP/IP offloads/flow-steering for VXLAN support",
+		[11] = "MAD DEMUX (Secure-Host) support"
 	};
 	int i;
 
@@ -571,6 +572,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET		0xa0
 #define QUERY_DEV_CAP_FW_REASSIGN_MAC		0x9d
 #define QUERY_DEV_CAP_VXLAN			0x9e
+#define QUERY_DEV_CAP_MAD_DEMUX_OFFSET		0xb0
 
 	dev_cap->flags2 = 0;
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -748,6 +750,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
 		MLX4_GET(dev_cap->max_counters, outbox,
 			 QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
 
+	MLX4_GET(field32, outbox,
+		 QUERY_DEV_CAP_MAD_DEMUX_OFFSET);
+	if (field32 & (1 << 0))
+		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX;
+
 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
 	if (field32 & (1 << 16))
 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
@@ -2016,3 +2023,85 @@ void mlx4_opreq_action(struct work_struc
 out:
 	mlx4_free_cmd_mailbox(dev, mailbox);
 }
+
+static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev,
+					  struct mlx4_cmd_mailbox *mailbox)
+{
+#define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET		0x10
+#define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET		0x20
+#define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET		0x40
+#define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET	0x70
+
+	u32 set_attr_mask, getresp_attr_mask;
+	u32 trap_attr_mask, traprepress_attr_mask;
+
+	MLX4_GET(set_attr_mask, mailbox->buf,
+		 MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET);
+	mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n",
+		 set_attr_mask);
+
+	MLX4_GET(getresp_attr_mask, mailbox->buf,
+		 MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET);
+	mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n",
+		 getresp_attr_mask);
+
+	MLX4_GET(trap_attr_mask, mailbox->buf,
+		 MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET);
+	mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n",
+		 trap_attr_mask);
+
+	MLX4_GET(traprepress_attr_mask, mailbox->buf,
+		 MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET);
+	mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n",
+		 traprepress_attr_mask);
+
+	if (set_attr_mask && getresp_attr_mask && trap_attr_mask &&
+	    traprepress_attr_mask)
+		return 1;
+
+	return 0;
+}
+
+int mlx4_config_mad_demux(struct mlx4_dev *dev)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	int secure_host_active;
+	int err;
+
+	/* Check if mad_demux is supported */
+	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX))
+		return 0;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX");
+		return -ENOMEM;
+	}
+
+	/* Query mad_demux to find out which MADs are handled by internal sma */
+	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */,
+			   MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX,
+			   MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+	if (err) {
+		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n",
+			  err);
+		goto out;
+	}
+
+	secure_host_active = mlx4_check_smp_firewall_active(dev, mailbox);
+
+	/* Config mad_demux to handle all MADs returned by the query above */
+	err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */,
+		       MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX,
+		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+	if (err) {
+		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err);
+		goto out;
+	}
+
+	if (secure_host_active)
+		mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n");
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -120,6 +120,16 @@ static struct mlx4_profile default_profi
 	.num_mtt	= 1 << 20, /* It is really num mtt segements */
 };
 
+static struct mlx4_profile low_mem_profile = {
+	.num_qp		= 1 << 17,
+	.num_srq	= 1 << 6,
+	.rdmarc_per_qp	= 1 << 4,
+	.num_cq		= 1 << 8,
+	.num_mcg	= 1 << 8,
+	.num_mpt	= 1 << 9,
+	.num_mtt	= 1 << 7,
+};
+
 static int log_num_mac = 7;
 module_param_named(log_num_mac, log_num_mac, int, 0444);
 MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
@@ -129,6 +139,8 @@ module_param_named(log_num_vlan, log_num
 MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
 /* Log2 max number of VLANs per ETH port (0-7) */
 #define MLX4_LOG_NUM_VLANS 7
+#define MLX4_MIN_LOG_NUM_VLANS 0
+#define MLX4_MIN_LOG_NUM_MAC 1
 
 static bool use_prio;
 module_param_named(use_prio, use_prio, bool, 0444);
@@ -287,8 +299,13 @@ static int mlx4_dev_cap(struct mlx4_dev
 	if (mlx4_is_mfunc(dev))
 		dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
 
-	dev->caps.log_num_macs  = log_num_mac;
-	dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
+	if (mlx4_low_memory_profile()) {
+		dev->caps.log_num_macs  = MLX4_MIN_LOG_NUM_MAC;
+		dev->caps.log_num_vlans = MLX4_MIN_LOG_NUM_VLANS;
+	} else {
+		dev->caps.log_num_macs  = log_num_mac;
+		dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
+	}
 
 	for (i = 1; i <= dev->caps.num_ports; ++i) {
 		dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE;
@@ -1587,7 +1604,12 @@ static int mlx4_init_hca(struct mlx4_dev
 		if (mlx4_is_master(dev))
 			mlx4_parav_master_pf_caps(dev);
 
-		profile = default_profile;
+		if (mlx4_low_memory_profile()) {
+			mlx4_info(dev, "Running from within kdump kernel. Using low memory profile\n");
+			profile = low_mem_profile;
+		} else {
+			profile = default_profile;
+		}
 		if (dev->caps.steering_mode ==
 		    MLX4_STEERING_MODE_DEVICE_MANAGED)
 			profile.num_mcg = MLX4_FS_NUM_MCG;
@@ -1831,6 +1853,11 @@ static int mlx4_setup_hca(struct mlx4_de
 			mlx4_err(dev, "Failed to initialize multicast group table, aborting\n");
 			goto err_mr_table_free;
 		}
+		err = mlx4_config_mad_demux(dev);
+		if (err) {
+			mlx4_err(dev, "Failed in config_mad_demux, aborting\n");
+			goto err_mcg_table_free;
+		}
 	}
 
 	err = mlx4_init_eq_table(dev);
@@ -2705,7 +2732,7 @@ int mlx4_restart_one(struct pci_dev *pde
 	return __mlx4_init_one(pdev, pci_dev_data);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
+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 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mcg.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mcg.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mcg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mcg.c	2014-09-28 17:29:07.000000000 -0400
@@ -270,7 +270,7 @@ static int existing_steering_entry(struc
 	 * we need to add it as a duplicate to this entry
 	 * for future references */
 	list_for_each_entry(dqp, &entry->duplicates, list) {
-		if (qpn == pqp->qpn)
+		if (qpn == dqp->qpn)
 			return 0; /* qp is already duplicated */
 	}
 
@@ -324,24 +324,22 @@ static bool check_duplicate_entry(struct
 	return true;
 }
 
-/* I a steering entry contains only promisc QPs, it can be removed. */
-static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
-				      enum mlx4_steer_type steer,
-				      unsigned int index, u32 tqpn)
+/* Returns true if all the QPs != tqpn contained in this entry
+ * are Promisc QPs. Returns false otherwise.
+ */
+static bool promisc_steering_entry(struct mlx4_dev *dev, u8 port,
+				   enum mlx4_steer_type steer,
+				   unsigned int index, u32 tqpn,
+				   u32 *members_count)
 {
-	struct mlx4_steer *s_steer;
 	struct mlx4_cmd_mailbox *mailbox;
 	struct mlx4_mgm *mgm;
-	struct mlx4_steer_index *entry = NULL, *tmp_entry;
-	u32 qpn;
-	u32 members_count;
+	u32 m_count;
 	bool ret = false;
 	int i;
 
 	if (port < 1 || port > dev->caps.num_ports)
-		return NULL;
-
-	s_steer = &mlx4_priv(dev)->steer[port - 1];
+		return false;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -350,21 +348,61 @@ static bool can_remove_steering_entry(st
 
 	if (mlx4_READ_ENTRY(dev, index, mailbox))
 		goto out;
-	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
-	for (i = 0;  i < members_count; i++) {
-		qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
+	m_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+	if (members_count)
+		*members_count = m_count;
+
+	for (i = 0;  i < m_count; i++) {
+		u32 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
 		if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
 			/* the qp is not promisc, the entry can't be removed */
 			goto out;
 		}
 	}
-	 /* All the qps currently registered for this entry are promiscuous,
+	ret = true;
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return ret;
+}
+
+/* IF a steering entry contains only promisc QPs, it can be removed. */
+static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
+				      enum mlx4_steer_type steer,
+				      unsigned int index, u32 tqpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_steer_index *entry = NULL, *tmp_entry;
+	u32 members_count;
+	bool ret = false;
+
+	if (port < 1 || port > dev->caps.num_ports)
+		return NULL;
+
+	s_steer = &mlx4_priv(dev)->steer[port - 1];
+
+	if (!promisc_steering_entry(dev, port, steer, index,
+				    tqpn, &members_count))
+		goto out;
+
+	/* All the qps currently registered for this entry are promiscuous,
 	  * Checking for duplicates */
 	ret = true;
 	list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
 		if (entry->index == index) {
-			if (list_empty(&entry->duplicates)) {
+			if (list_empty(&entry->duplicates) ||
+			    members_count == 1) {
+				struct mlx4_promisc_qp *pqp, *tmp_pqp;
+				/* If there is only 1 entry in duplicates then
+				 * this is the QP we want to delete, going over
+				 * the list and deleting the entry.
+				 */
 				list_del(&entry->list);
+				list_for_each_entry_safe(pqp, tmp_pqp,
+							 &entry->duplicates,
+							 list) {
+					list_del(&pqp->list);
+					kfree(pqp);
+				}
 				kfree(entry);
 			} else {
 				/* This entry contains duplicates so it shouldn't be removed */
@@ -375,7 +413,6 @@ static bool can_remove_steering_entry(st
 	}
 
 out:
-	mlx4_free_cmd_mailbox(dev, mailbox);
 	return ret;
 }
 
@@ -421,42 +458,57 @@ static int add_promisc_qp(struct mlx4_de
 	}
 	mgm = mailbox->buf;
 
-	/* the promisc qp needs to be added for each one of the steering
-	 * entries, if it already exists, needs to be added as a duplicate
-	 * for this entry */
-	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
-		err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
-		if (err)
-			goto out_mailbox;
+	if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+		/* The promisc QP needs to be added for each one of the steering
+		 * entries. If it already exists, needs to be added as
+		 * a duplicate for this entry.
+		 */
+		list_for_each_entry(entry,
+				    &s_steer->steer_entries[steer],
+				    list) {
+			err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+			if (err)
+				goto out_mailbox;
 
-		members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
-		prot = be32_to_cpu(mgm->members_count) >> 30;
-		found = false;
-		for (i = 0; i < members_count; i++) {
-			if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
-				/* Entry already exists, add to duplicates */
-				dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
-				if (!dqp) {
+			members_count = be32_to_cpu(mgm->members_count) &
+					0xffffff;
+			prot = be32_to_cpu(mgm->members_count) >> 30;
+			found = false;
+			for (i = 0; i < members_count; i++) {
+				if ((be32_to_cpu(mgm->qp[i]) &
+				     MGM_QPN_MASK) == qpn) {
+					/* Entry already exists.
+					 * Add to duplicates.
+					 */
+					dqp = kmalloc(sizeof(*dqp), GFP_KERNEL);
+					if (!dqp) {
+						err = -ENOMEM;
+						goto out_mailbox;
+					}
+					dqp->qpn = qpn;
+					list_add_tail(&dqp->list,
+						      &entry->duplicates);
+					found = true;
+				}
+			}
+			if (!found) {
+				/* Need to add the qpn to mgm */
+				if (members_count ==
+				    dev->caps.num_qp_per_mgm) {
+					/* entry is full */
 					err = -ENOMEM;
 					goto out_mailbox;
 				}
-				dqp->qpn = qpn;
-				list_add_tail(&dqp->list, &entry->duplicates);
-				found = true;
-			}
-		}
-		if (!found) {
-			/* Need to add the qpn to mgm */
-			if (members_count == dev->caps.num_qp_per_mgm) {
-				/* entry is full */
-				err = -ENOMEM;
-				goto out_mailbox;
+				mgm->qp[members_count++] =
+					cpu_to_be32(qpn & MGM_QPN_MASK);
+				mgm->members_count =
+					cpu_to_be32(members_count |
+						    (prot << 30));
+				err = mlx4_WRITE_ENTRY(dev, entry->index,
+						       mailbox);
+				if (err)
+					goto out_mailbox;
 			}
-			mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
-			mgm->members_count = cpu_to_be32(members_count | (prot << 30));
-			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
-			if (err)
-				goto out_mailbox;
 		}
 	}
 
@@ -465,8 +517,14 @@ static int add_promisc_qp(struct mlx4_de
 	/* now need to add all the promisc qps to default entry */
 	memset(mgm, 0, sizeof *mgm);
 	members_count = 0;
-	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
+	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) {
+		if (members_count == dev->caps.num_qp_per_mgm) {
+			/* entry is full */
+			err = -ENOMEM;
+			goto out_list;
+		}
 		mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
+	}
 	mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
 
 	err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
@@ -495,13 +553,13 @@ static int remove_promisc_qp(struct mlx4
 	struct mlx4_steer *s_steer;
 	struct mlx4_cmd_mailbox *mailbox;
 	struct mlx4_mgm *mgm;
-	struct mlx4_steer_index *entry;
+	struct mlx4_steer_index *entry, *tmp_entry;
 	struct mlx4_promisc_qp *pqp;
 	struct mlx4_promisc_qp *dqp;
 	u32 members_count;
 	bool found;
 	bool back_to_list = false;
-	int loc, i;
+	int i;
 	int err;
 
 	if (port < 1 || port > dev->caps.num_ports)
@@ -538,39 +596,73 @@ static int remove_promisc_qp(struct mlx4
 	if (err)
 		goto out_mailbox;
 
-	/* remove the qp from all the steering entries*/
-	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
-		found = false;
-		list_for_each_entry(dqp, &entry->duplicates, list) {
-			if (dqp->qpn == qpn) {
-				found = true;
-				break;
+	if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+		/* Remove the QP from all the steering entries */
+		list_for_each_entry_safe(entry, tmp_entry,
+					 &s_steer->steer_entries[steer],
+					 list) {
+			found = false;
+			list_for_each_entry(dqp, &entry->duplicates, list) {
+				if (dqp->qpn == qpn) {
+					found = true;
+					break;
+				}
 			}
-		}
-		if (found) {
-			/* a duplicate, no need to change the mgm,
-			 * only update the duplicates list */
-			list_del(&dqp->list);
-			kfree(dqp);
-		} else {
-			err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
-				if (err)
-					goto out_mailbox;
-			members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
-			for (loc = -1, i = 0; i < members_count; ++i)
-				if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
-					loc = i;
+			if (found) {
+				/* A duplicate, no need to change the MGM,
+				 * only update the duplicates list
+				 */
+				list_del(&dqp->list);
+				kfree(dqp);
+			} else {
+				int loc = -1;
 
-			mgm->members_count = cpu_to_be32(--members_count |
-							 (MLX4_PROT_ETH << 30));
-			mgm->qp[loc] = mgm->qp[i - 1];
-			mgm->qp[i - 1] = 0;
+				err = mlx4_READ_ENTRY(dev,
+						      entry->index,
+						      mailbox);
+					if (err)
+						goto out_mailbox;
+				members_count =
+					be32_to_cpu(mgm->members_count) &
+					0xffffff;
+				if (!members_count) {
+					mlx4_warn(dev, "QP %06x wasn't found in entry %x mcount=0. deleting entry...\n",
+						  qpn, entry->index);
+					list_del(&entry->list);
+					kfree(entry);
+					continue;
+				}
 
-			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
-				if (err)
+				for (i = 0; i < members_count; ++i)
+					if ((be32_to_cpu(mgm->qp[i]) &
+					     MGM_QPN_MASK) == qpn) {
+						loc = i;
+						break;
+					}
+
+				if (loc < 0) {
+					mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
+						 qpn, entry->index);
+					err = -EINVAL;
 					goto out_mailbox;
-		}
+				}
 
+				/* Copy the last QP in this MGM
+				 * over removed QP
+				 */
+				mgm->qp[loc] = mgm->qp[members_count - 1];
+				mgm->qp[members_count - 1] = 0;
+				mgm->members_count =
+					cpu_to_be32(--members_count |
+						    (MLX4_PROT_ETH << 30));
+
+				err = mlx4_WRITE_ENTRY(dev,
+						       entry->index,
+						       mailbox);
+					if (err)
+						goto out_mailbox;
+			}
+		}
 	}
 
 out_mailbox:
@@ -928,6 +1020,44 @@ int mlx4_flow_detach(struct mlx4_dev *de
 }
 EXPORT_SYMBOL_GPL(mlx4_flow_detach);
 
+int mlx4_tunnel_steer_add(struct mlx4_dev *dev, unsigned char *addr,
+			  int port, int qpn, u16 prio, u64 *reg_id)
+{
+	int err;
+	struct mlx4_spec_list spec_eth_outer = { {NULL} };
+	struct mlx4_spec_list spec_vxlan     = { {NULL} };
+	struct mlx4_spec_list spec_eth_inner = { {NULL} };
+
+	struct mlx4_net_trans_rule rule = {
+		.queue_mode = MLX4_NET_TRANS_Q_FIFO,
+		.exclusive = 0,
+		.allow_loopback = 1,
+		.promisc_mode = MLX4_FS_REGULAR,
+	};
+
+	__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+	rule.port = port;
+	rule.qpn = qpn;
+	rule.priority = prio;
+	INIT_LIST_HEAD(&rule.list);
+
+	spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
+	memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
+	memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+
+	spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN;    /* any vxlan header */
+	spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH;	 /* any inner eth header */
+
+	list_add_tail(&spec_eth_outer.list, &rule.list);
+	list_add_tail(&spec_vxlan.list,     &rule.list);
+	list_add_tail(&spec_eth_inner.list, &rule.list);
+
+	err = mlx4_flow_attach(dev, &rule, reg_id);
+	return err;
+}
+EXPORT_SYMBOL(mlx4_tunnel_steer_add);
+
 int mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn,
 				      u32 max_range_qpn)
 {
@@ -1062,7 +1192,7 @@ int mlx4_qp_detach_common(struct mlx4_de
 	struct mlx4_mgm *mgm;
 	u32 members_count;
 	int prev, index;
-	int i, loc;
+	int i, loc = -1;
 	int err;
 	u8 port = gid[5];
 	bool removed_entry = false;
@@ -1085,15 +1215,20 @@ int mlx4_qp_detach_common(struct mlx4_de
 		goto out;
 	}
 
-	/* if this pq is also a promisc qp, it shouldn't be removed */
+	/* If this QP is also a promisc QP, it shouldn't be removed only if
+	 * at least one none promisc QP is also attached to this MCG
+	 */
 	if (prot == MLX4_PROT_ETH &&
-	    check_duplicate_entry(dev, port, steer, index, qp->qpn))
-		goto out;
+	    check_duplicate_entry(dev, port, steer, index, qp->qpn) &&
+	    !promisc_steering_entry(dev, port, steer, index, qp->qpn, NULL))
+			goto out;
 
 	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
-	for (loc = -1, i = 0; i < members_count; ++i)
-		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
+	for (i = 0; i < members_count; ++i)
+		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
 			loc = i;
+			break;
+		}
 
 	if (loc == -1) {
 		mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
@@ -1101,15 +1236,15 @@ int mlx4_qp_detach_common(struct mlx4_de
 		goto out;
 	}
 
-
+	/* copy the last QP in this MGM over removed QP */
+	mgm->qp[loc] = mgm->qp[members_count - 1];
+	mgm->qp[members_count - 1] = 0;
 	mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
-	mgm->qp[loc]       = mgm->qp[i - 1];
-	mgm->qp[i - 1]     = 0;
 
 	if (prot == MLX4_PROT_ETH)
 		removed_entry = can_remove_steering_entry(dev, port, steer,
 								index, qp->qpn);
-	if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
+	if (members_count && (prot != MLX4_PROT_ETH || !removed_entry)) {
 		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h	2014-09-28 17:29:07.000000000 -0400
@@ -93,6 +93,8 @@
  * OS related constants and tunables
  */
 
+#define MLX4_EN_PRIV_FLAGS_BLUEFLAME 1
+
 #define MLX4_EN_WATCHDOG_TIMEOUT	(15 * HZ)
 
 /* Use the maximum between 16384 and a single page */
@@ -119,6 +121,7 @@ enum {
 #define MLX4_EN_MIN_TX_SIZE	(4096 / TXBB_SIZE)
 
 #define MLX4_EN_SMALL_PKT_SIZE		64
+#define MLX4_EN_MIN_TX_RING_P_UP	1
 #define MLX4_EN_MAX_TX_RING_P_UP	32
 #define MLX4_EN_NUM_UP			8
 #define MLX4_EN_DEF_TX_RING_SIZE	512
@@ -154,8 +157,6 @@ enum {
 #define MLX4_EN_TX_POLL_MODER	16
 #define MLX4_EN_TX_POLL_TIMEOUT	(HZ / 4)
 
-#define ETH_LLC_SNAP_SIZE	8
-
 #define SMALL_PACKET_SIZE      (256 - NET_IP_ALIGN)
 #define HEADER_COPY_SIZE       (128 - NET_IP_ALIGN)
 #define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN)
@@ -280,6 +281,7 @@ struct mlx4_en_tx_ring {
 	unsigned long wake_queue;
 	struct mlx4_bf bf;
 	bool bf_enabled;
+	bool bf_alloced;
 	struct netdev_queue *tx_queue;
 	int hwtstamp_tx_type;
 	int inline_thold;
@@ -535,7 +537,7 @@ struct mlx4_en_priv {
 	int registered;
 	int allocated;
 	int stride;
-	unsigned char prev_mac[ETH_ALEN + 2];
+	unsigned char current_mac[ETH_ALEN + 2];
 	int mac_index;
 	unsigned max_mtu;
 	int base_qpn;
@@ -594,6 +596,8 @@ struct mlx4_en_priv {
 #endif
 	u64 tunnel_reg_id;
 	__be16 vxlan_port;
+
+	u32 pflags;
 };
 
 enum mlx4_en_wol {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,11 +62,6 @@
 
 #define INIT_HCA_TPT_MW_ENABLE          (1 << 7)
 
-#define MLX4_NUM_UP		8
-#define MLX4_NUM_TC		8
-#define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */
-#define MLX4_RATELIMIT_DEFAULT 0xffff
-
 struct mlx4_set_port_prio2tc_context {
 	u8 prio2tc[4];
 };
@@ -279,6 +274,8 @@ struct mlx4_icm_table {
 #define MLX4_MPT_FLAG_PHYSICAL	    (1 <<  9)
 #define MLX4_MPT_FLAG_REGION	    (1 <<  8)
 
+#define MLX4_MPT_PD_MASK	    (0x1FFFFUL)
+#define MLX4_MPT_PD_VF_MASK	    (0xFE0000UL)
 #define MLX4_MPT_PD_FLAG_FAST_REG   (1 << 27)
 #define MLX4_MPT_PD_FLAG_RAE	    (1 << 28)
 #define MLX4_MPT_PD_FLAG_EN_INV	    (3 << 24)
@@ -1311,5 +1308,6 @@ void mlx4_init_quotas(struct mlx4_dev *d
 int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port);
 /* Returns the VF index of slave */
 int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave);
+int mlx4_config_mad_demux(struct mlx4_dev *dev);
 
 #endif /* MLX4_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mr.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mr.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/mr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/mr.c	2014-09-28 17:29:07.000000000 -0400
@@ -298,6 +298,130 @@ static int mlx4_HW2SW_MPT(struct mlx4_de
 			    MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
 }
 
+/* Must protect against concurrent access */
+int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
+		       struct mlx4_mpt_entry ***mpt_entry)
+{
+	int err;
+	int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1);
+	struct mlx4_cmd_mailbox *mailbox = NULL;
+
+	if (mmr->enabled != MLX4_MPT_EN_HW)
+		return -EINVAL;
+
+	err = mlx4_HW2SW_MPT(dev, NULL, key);
+	if (err) {
+		mlx4_warn(dev, "HW2SW_MPT failed (%d).", err);
+		mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n");
+		return err;
+	}
+
+	mmr->enabled = MLX4_MPT_EN_SW;
+
+	if (!mlx4_is_mfunc(dev)) {
+		**mpt_entry = mlx4_table_find(
+				&mlx4_priv(dev)->mr_table.dmpt_table,
+				key, NULL);
+	} else {
+		mailbox = mlx4_alloc_cmd_mailbox(dev);
+		if (IS_ERR_OR_NULL(mailbox))
+			return PTR_ERR(mailbox);
+
+		err = mlx4_cmd_box(dev, 0, mailbox->dma, key,
+				   0, MLX4_CMD_QUERY_MPT,
+				   MLX4_CMD_TIME_CLASS_B,
+				   MLX4_CMD_WRAPPED);
+		if (err)
+			goto free_mailbox;
+
+		*mpt_entry = (struct mlx4_mpt_entry **)&mailbox->buf;
+	}
+
+	if (!(*mpt_entry) || !(**mpt_entry)) {
+		err = -ENOMEM;
+		goto free_mailbox;
+	}
+
+	return 0;
+
+free_mailbox:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_get_mpt);
+
+int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
+			 struct mlx4_mpt_entry **mpt_entry)
+{
+	int err;
+
+	if (!mlx4_is_mfunc(dev)) {
+		/* Make sure any changes to this entry are flushed */
+		wmb();
+
+		*(u8 *)(*mpt_entry) = MLX4_MPT_STATUS_HW;
+
+		/* Make sure the new status is written */
+		wmb();
+
+		err = mlx4_SYNC_TPT(dev);
+	} else {
+		int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1);
+
+		struct mlx4_cmd_mailbox *mailbox =
+			container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,
+				     buf);
+
+		err = mlx4_SW2HW_MPT(dev, mailbox, key);
+	}
+
+	if (!err) {
+		mmr->pd = be32_to_cpu((*mpt_entry)->pd_flags) & MLX4_MPT_PD_MASK;
+		mmr->enabled = MLX4_MPT_EN_HW;
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_write_mpt);
+
+void mlx4_mr_hw_put_mpt(struct mlx4_dev *dev,
+			struct mlx4_mpt_entry **mpt_entry)
+{
+	if (mlx4_is_mfunc(dev)) {
+		struct mlx4_cmd_mailbox *mailbox =
+			container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,
+				     buf);
+		mlx4_free_cmd_mailbox(dev, mailbox);
+	}
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_put_mpt);
+
+int mlx4_mr_hw_change_pd(struct mlx4_dev *dev, struct mlx4_mpt_entry *mpt_entry,
+			 u32 pdn)
+{
+	u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags) & ~MLX4_MPT_PD_MASK;
+	/* The wrapper function will put the slave's id here */
+	if (mlx4_is_mfunc(dev))
+		pd_flags &= ~MLX4_MPT_PD_VF_MASK;
+
+	mpt_entry->pd_flags = cpu_to_be32(pd_flags |
+					  (pdn & MLX4_MPT_PD_MASK)
+					  | MLX4_MPT_PD_FLAG_EN_INV);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_change_pd);
+
+int mlx4_mr_hw_change_access(struct mlx4_dev *dev,
+			     struct mlx4_mpt_entry *mpt_entry,
+			     u32 access)
+{
+	u32 flags = (be32_to_cpu(mpt_entry->flags) & ~MLX4_PERM_MASK) |
+		    (access & MLX4_PERM_MASK);
+
+	mpt_entry->flags = cpu_to_be32(flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_change_access);
+
 static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
 			   u64 iova, u64 size, u32 access, int npages,
 			   int page_shift, struct mlx4_mr *mr)
@@ -463,6 +587,53 @@ int mlx4_mr_free(struct mlx4_dev *dev, s
 }
 EXPORT_SYMBOL_GPL(mlx4_mr_free);
 
+void mlx4_mr_rereg_mem_cleanup(struct mlx4_dev *dev, struct mlx4_mr *mr)
+{
+	mlx4_mtt_cleanup(dev, &mr->mtt);
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_rereg_mem_cleanup);
+
+int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,
+			    u64 iova, u64 size, int npages,
+			    int page_shift, struct mlx4_mpt_entry *mpt_entry)
+{
+	int err;
+
+	mpt_entry->start       = cpu_to_be64(iova);
+	mpt_entry->length      = cpu_to_be64(size);
+	mpt_entry->entity_size = cpu_to_be32(page_shift);
+
+	err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
+	if (err)
+		return err;
+
+	mpt_entry->pd_flags &= cpu_to_be32(MLX4_MPT_PD_MASK |
+					   MLX4_MPT_PD_FLAG_EN_INV);
+	mpt_entry->flags    &= cpu_to_be32(MLX4_MPT_FLAG_FREE |
+					   MLX4_MPT_FLAG_SW_OWNS);
+	if (mr->mtt.order < 0) {
+		mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
+		mpt_entry->mtt_addr = 0;
+	} else {
+		mpt_entry->mtt_addr = cpu_to_be64(mlx4_mtt_addr(dev,
+						  &mr->mtt));
+		if (mr->mtt.page_shift == 0)
+			mpt_entry->mtt_sz    = cpu_to_be32(1 << mr->mtt.order);
+	}
+	if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
+		/* fast register MR in free state */
+		mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+		mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG |
+						   MLX4_MPT_PD_FLAG_RAE);
+	} else {
+		mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
+	}
+	mr->enabled = MLX4_MPT_EN_SW;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_rereg_mem_write);
+
 int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
 {
 	struct mlx4_cmd_mailbox *mailbox;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/port.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/port.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/port.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/port.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,7 +103,8 @@ static int find_index(struct mlx4_dev *d
 	int i;
 
 	for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
-		if ((mac & MLX4_MAC_MASK) ==
+		if (table->refs[i] &&
+		    (MLX4_MAC_MASK & mac) ==
 		    (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
 			return i;
 	}
@@ -165,12 +166,14 @@ int __mlx4_register_mac(struct mlx4_dev
 
 	mutex_lock(&table->mutex);
 	for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
-		if (free < 0 && !table->entries[i]) {
-			free = i;
+		if (!table->refs[i]) {
+			if (free < 0)
+				free = i;
 			continue;
 		}
 
-		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
+		if ((MLX4_MAC_MASK & mac) ==
+		     (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
 			/* MAC already registered, increment ref count */
 			err = i;
 			++table->refs[i];
@@ -244,10 +247,16 @@ EXPORT_SYMBOL_GPL(mlx4_get_base_qpn);
 
 void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
 {
-	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
-	struct mlx4_mac_table *table = &info->mac_table;
+	struct mlx4_port_info *info;
+	struct mlx4_mac_table *table;
 	int index;
 
+	if (port < 1 || port > dev->caps.num_ports) {
+		mlx4_warn(dev, "invalid port number (%d), aborting...\n", port);
+		return;
+	}
+	info = &mlx4_priv(dev)->port[port];
+	table = &info->mac_table;
 	mutex_lock(&table->mutex);
 	index = find_index(dev, table, mac);
 
@@ -1051,14 +1060,26 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_
 
 	for (i = 0; i < MLX4_NUM_TC; i++) {
 		struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i];
-		u16 r = ratelimit && ratelimit[i] ? ratelimit[i] :
-			MLX4_RATELIMIT_DEFAULT;
+		u16 r;
+
+		if (ratelimit && ratelimit[i]) {
+			if (ratelimit[i] <= MLX4_MAX_100M_UNITS_VAL) {
+				r = ratelimit[i];
+				tc->max_bw_units =
+					htons(MLX4_RATELIMIT_100M_UNITS);
+			} else {
+				r = ratelimit[i]/10;
+				tc->max_bw_units =
+					htons(MLX4_RATELIMIT_1G_UNITS);
+			}
+			tc->max_bw_value = htons(r);
+		} else {
+			tc->max_bw_value = htons(MLX4_RATELIMIT_DEFAULT);
+			tc->max_bw_units = htons(MLX4_RATELIMIT_1G_UNITS);
+		}
 
 		tc->pg = htons(pg[i]);
 		tc->bw_precentage = htons(tc_tx_bw[i]);
-
-		tc->max_bw_units = htons(MLX4_RATELIMIT_UNITS);
-		tc->max_bw_value = htons(r);
 	}
 
 	in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/qp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/qp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/qp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/qp.c	2014-09-28 17:29:07.000000000 -0400
@@ -390,13 +390,14 @@ err_icm:
 EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
 
 #define MLX4_UPDATE_QP_SUPPORTED_ATTRS MLX4_UPDATE_QP_SMAC
-int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
+int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
 		   enum mlx4_update_qp_attr attr,
 		   struct mlx4_update_qp_params *params)
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	struct mlx4_update_qp_context *cmd;
 	u64 pri_addr_path_mask = 0;
+	u64 qp_mask = 0;
 	int err = 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -413,9 +414,16 @@ int mlx4_update_qp(struct mlx4_dev *dev,
 		cmd->qp_context.pri_path.grh_mylmc = params->smac_index;
 	}
 
+	if (attr & MLX4_UPDATE_QP_VSD) {
+		qp_mask |= 1ULL << MLX4_UPD_QP_MASK_VSD;
+		if (params->flags & MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE)
+			cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN);
+	}
+
 	cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask);
+	cmd->qp_mask = cpu_to_be64(qp_mask);
 
-	err = mlx4_cmd(dev, mailbox->dma, qp->qpn & 0xffffff, 0,
+	err = mlx4_cmd(dev, mailbox->dma, qpn & 0xffffff, 0,
 		       MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
 		       MLX4_CMD_NATIVE);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c	2014-09-28 17:29:07.000000000 -0400
@@ -702,11 +702,13 @@ static int update_vport_qp_param(struct
 	struct mlx4_qp_context	*qpc = inbox->buf + 8;
 	struct mlx4_vport_oper_state *vp_oper;
 	struct mlx4_priv *priv;
+	u32 qp_type;
 	int port;
 
 	port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
 	priv = mlx4_priv(dev);
 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+	qp_type	= (be32_to_cpu(qpc->flags) >> 16) & 0xff;
 
 	if (MLX4_VGT != vp_oper->state.default_vlan) {
 		/* the reserved QPs (special, proxy, tunnel)
@@ -715,8 +717,20 @@ static int update_vport_qp_param(struct
 		if (mlx4_is_qp_reserved(dev, qpn))
 			return 0;
 
-		/* force strip vlan by clear vsd */
-		qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+		/* force strip vlan by clear vsd, MLX QP refers to Raw Ethernet */
+		if (qp_type == MLX4_QP_ST_UD ||
+		    (qp_type == MLX4_QP_ST_MLX && mlx4_is_eth(dev, port))) {
+			if (dev->caps.bmme_flags & MLX4_BMME_FLAG_VSD_INIT2RTR) {
+				*(__be32 *)inbox->buf =
+					cpu_to_be32(be32_to_cpu(*(__be32 *)inbox->buf) |
+					MLX4_QP_OPTPAR_VLAN_STRIPPING);
+				qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+			} else {
+				struct mlx4_update_qp_params params = {.flags = 0};
+
+				mlx4_update_qp(dev, qpn, MLX4_UPDATE_QP_VSD, &params);
+			}
+		}
 
 		if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE &&
 		    dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
@@ -2613,12 +2627,34 @@ int mlx4_QUERY_MPT_wrapper(struct mlx4_d
 	if (err)
 		return err;
 
-	if (mpt->com.from_state != RES_MPT_HW) {
+	if (mpt->com.from_state == RES_MPT_MAPPED) {
+		/* In order to allow rereg in SRIOV, we need to alter the MPT entry. To do
+		 * that, the VF must read the MPT. But since the MPT entry memory is not
+		 * in the VF's virtual memory space, it must use QUERY_MPT to obtain the
+		 * entry contents. To guarantee that the MPT cannot be changed, the driver
+		 * must perform HW2SW_MPT before this query and return the MPT entry to HW
+		 * ownership fofollowing the change. The change here allows the VF to
+		 * perform QUERY_MPT also when the entry is in SW ownership.
+		 */
+		struct mlx4_mpt_entry *mpt_entry = mlx4_table_find(
+					&mlx4_priv(dev)->mr_table.dmpt_table,
+					mpt->key, NULL);
+
+		if (NULL == mpt_entry || NULL == outbox->buf) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		memcpy(outbox->buf, mpt_entry, sizeof(*mpt_entry));
+
+		err = 0;
+	} else if (mpt->com.from_state == RES_MPT_HW) {
+		err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+	} else {
 		err = -EBUSY;
 		goto out;
 	}
 
-	err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
 
 out:
 	put_res(dev, slave, id, RES_MPT);
@@ -3976,13 +4012,17 @@ int mlx4_UPDATE_QP_wrapper(struct mlx4_d
 	}
 
 	port = (rqp->sched_queue >> 6 & 1) + 1;
-	smac_index = cmd->qp_context.pri_path.grh_mylmc;
-	err = mac_find_smac_ix_in_slave(dev, slave, port,
-					smac_index, &mac);
-	if (err) {
-		mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
-			 qpn, smac_index);
-		goto err_mac;
+
+	if (pri_addr_path_mask & (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)) {
+		smac_index = cmd->qp_context.pri_path.grh_mylmc;
+		err = mac_find_smac_ix_in_slave(dev, slave, port,
+						smac_index, &mac);
+
+		if (err) {
+			mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
+				 qpn, smac_index);
+			goto err_mac;
+		}
 	}
 
 	err = mlx4_cmd(dev, inbox->dma,
@@ -4796,7 +4836,7 @@ void mlx4_vf_immed_vlan_work_handler(str
 			MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
 
 	upd_context = mailbox->buf;
-	upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD);
+	upd_context->qp_mask = cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_VSD);
 
 	spin_lock_irq(mlx4_tlock(dev));
 	list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@ int mlx5_buf_alloc(struct mlx5_core_dev
 	if (size <= max_direct) {
 		buf->nbufs        = 1;
 		buf->npages       = 1;
-		buf->page_shift   = get_order(size) + PAGE_SHIFT;
+		buf->page_shift   = (u8)get_order(size) + PAGE_SHIFT;
 		buf->direct.buf   = dma_zalloc_coherent(&dev->pdev->dev,
 							size, &t, GFP_KERNEL);
 		if (!buf->direct.buf)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -464,7 +464,7 @@ static void dump_command(struct mlx5_cor
 	struct mlx5_cmd_msg *msg = input ? ent->in : ent->out;
 	struct mlx5_cmd_mailbox *next = msg->next;
 	int data_only;
-	int offset = 0;
+	u32 offset = 0;
 	int dump_len;
 
 	data_only = !!(mlx5_core_debug_mask & (1 << MLX5_CMD_DATA));
@@ -548,7 +548,7 @@ static void cmd_work_handler(struct work
 	lay->status_own = CMD_OWNER_HW;
 	set_signature(ent, !cmd->checksum_disabled);
 	dump_command(dev, ent, 1);
-	ktime_get_ts(&ent->ts1);
+	ent->ts1 = ktime_get_ns();
 
 	/* ring doorbell after the descriptor is valid */
 	wmb();
@@ -637,7 +637,6 @@ static int mlx5_cmd_invoke(struct mlx5_c
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
 	struct mlx5_cmd_work_ent *ent;
-	ktime_t t1, t2, delta;
 	struct mlx5_cmd_stats *stats;
 	int err = 0;
 	s64 ds;
@@ -668,10 +667,7 @@ static int mlx5_cmd_invoke(struct mlx5_c
 		if (err == -ETIMEDOUT)
 			goto out;
 
-		t1 = timespec_to_ktime(ent->ts1);
-		t2 = timespec_to_ktime(ent->ts2);
-		delta = ktime_sub(t2, t1);
-		ds = ktime_to_ns(delta);
+		ds = ent->ts2 - ent->ts1;
 		op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
 		if (op < ARRAY_SIZE(cmd->stats)) {
 			stats = &cmd->stats[op];
@@ -1135,7 +1131,6 @@ void mlx5_cmd_comp_handler(struct mlx5_c
 	void *context;
 	int err;
 	int i;
-	ktime_t t1, t2, delta;
 	s64 ds;
 	struct mlx5_cmd_stats *stats;
 	unsigned long flags;
@@ -1149,7 +1144,7 @@ void mlx5_cmd_comp_handler(struct mlx5_c
 				sem = &cmd->pages_sem;
 			else
 				sem = &cmd->sem;
-			ktime_get_ts(&ent->ts2);
+			ent->ts2 = ktime_get_ns();
 			memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
 			dump_command(dev, ent, 0);
 			if (!ent->ret) {
@@ -1163,10 +1158,7 @@ void mlx5_cmd_comp_handler(struct mlx5_c
 			}
 			free_ent(cmd, ent->idx);
 			if (ent->callback) {
-				t1 = timespec_to_ktime(ent->ts1);
-				t2 = timespec_to_ktime(ent->ts2);
-				delta = ktime_sub(t2, t1);
-				ds = ktime_to_ns(delta);
+				ds = ent->ts2 - ent->ts1;
 				if (ent->op < ARRAY_SIZE(cmd->stats)) {
 					stats = &cmd->stats[ent->op];
 					spin_lock_irqsave(&stats->lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c	2014-09-28 17:29:07.000000000 -0400
@@ -252,7 +252,9 @@ static int mlx5_eq_int(struct mlx5_core_
 			case MLX5_PORT_CHANGE_SUBTYPE_GUID:
 			case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG:
 			case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED:
-				dev->event(dev, port_subtype_event(eqe->sub_type), &port);
+				if (dev->event)
+					dev->event(dev, port_subtype_event(eqe->sub_type),
+						   (unsigned long)port);
 				break;
 			default:
 				mlx5_core_warn(dev, "Port event with unrecognized subtype: port %d, sub_type %d\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/mad.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/mad.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/mad.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/mad.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #include "mlx5_core.h"
 
 int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb,
-		      u16 opmod, int port)
+		      u16 opmod, u8 port)
 {
 	struct mlx5_mad_ifc_mbox_in *in = NULL;
 	struct mlx5_mad_ifc_mbox_out *out = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,100 @@ int mlx5_core_debug_mask;
 module_param_named(debug_mask, mlx5_core_debug_mask, int, 0644);
 MODULE_PARM_DESC(debug_mask, "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0");
 
+#define MLX5_DEFAULT_PROF	2
+static int prof_sel = MLX5_DEFAULT_PROF;
+module_param_named(prof_sel, prof_sel, int, 0444);
+MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
+
 struct workqueue_struct *mlx5_core_wq;
+static LIST_HEAD(intf_list);
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(intf_mutex);
+
+struct mlx5_device_context {
+	struct list_head	list;
+	struct mlx5_interface  *intf;
+	void		       *context;
+};
+
+static struct mlx5_profile profile[] = {
+	[0] = {
+		.mask           = 0,
+	},
+	[1] = {
+		.mask		= MLX5_PROF_MASK_QP_SIZE,
+		.log_max_qp	= 12,
+	},
+	[2] = {
+		.mask		= MLX5_PROF_MASK_QP_SIZE |
+				  MLX5_PROF_MASK_MR_CACHE,
+		.log_max_qp	= 17,
+		.mr_cache[0]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[1]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[2]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[3]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[4]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[5]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[6]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[7]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[8]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[9]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[10]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[11]	= {
+			.size	= 500,
+			.limit	= 250
+		},
+		.mr_cache[12]	= {
+			.size	= 64,
+			.limit	= 32
+		},
+		.mr_cache[13]	= {
+			.size	= 32,
+			.limit	= 16
+		},
+		.mr_cache[14]	= {
+			.size	= 16,
+			.limit	= 8
+		},
+		.mr_cache[15]	= {
+			.size	= 8,
+			.limit	= 4
+		},
+	},
+};
 
 static int set_dma_caps(struct pci_dev *pdev)
 {
@@ -218,7 +311,7 @@ static int handle_hca_cap(struct mlx5_co
 
 	copy_rw_fields(&set_ctx->hca_cap, &query_out->hca_cap);
 
-	if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
+	if (dev->profile && dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
 		set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp;
 
 	flags = be64_to_cpu(query_out->hca_cap.flags);
@@ -299,7 +392,7 @@ static int mlx5_core_disable_hca(struct
 	return 0;
 }
 
-int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
+static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
 {
 	struct mlx5_priv *priv = &dev->priv;
 	int err;
@@ -489,7 +582,7 @@ err_dbg:
 }
 EXPORT_SYMBOL(mlx5_dev_init);
 
-void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
+static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
 {
 	struct mlx5_priv *priv = &dev->priv;
 
@@ -516,7 +609,190 @@ void mlx5_dev_cleanup(struct mlx5_core_d
 	pci_disable_device(dev->pdev);
 	debugfs_remove(priv->dbg_root);
 }
-EXPORT_SYMBOL(mlx5_dev_cleanup);
+
+static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+	struct mlx5_device_context *dev_ctx;
+	struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+	dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
+	if (!dev_ctx) {
+		pr_warn("mlx5_add_device: alloc context failed\n");
+		return;
+	}
+
+	dev_ctx->intf    = intf;
+	dev_ctx->context = intf->add(dev);
+
+	if (dev_ctx->context) {
+		spin_lock_irq(&priv->ctx_lock);
+		list_add_tail(&dev_ctx->list, &priv->ctx_list);
+		spin_unlock_irq(&priv->ctx_lock);
+	} else {
+		kfree(dev_ctx);
+	}
+}
+
+static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+	struct mlx5_device_context *dev_ctx;
+	struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+		if (dev_ctx->intf == intf) {
+			spin_lock_irq(&priv->ctx_lock);
+			list_del(&dev_ctx->list);
+			spin_unlock_irq(&priv->ctx_lock);
+
+			intf->remove(dev, dev_ctx->context);
+			kfree(dev_ctx);
+			return;
+		}
+}
+static int mlx5_register_device(struct mlx5_core_dev *dev)
+{
+	struct mlx5_priv *priv = &dev->priv;
+	struct mlx5_interface *intf;
+
+	mutex_lock(&intf_mutex);
+	list_add_tail(&priv->dev_list, &dev_list);
+	list_for_each_entry(intf, &intf_list, list)
+		mlx5_add_device(intf, priv);
+	mutex_unlock(&intf_mutex);
+
+	return 0;
+}
+static void mlx5_unregister_device(struct mlx5_core_dev *dev)
+{
+	struct mlx5_priv *priv = &dev->priv;
+	struct mlx5_interface *intf;
+
+	mutex_lock(&intf_mutex);
+	list_for_each_entry(intf, &intf_list, list)
+		mlx5_remove_device(intf, priv);
+	list_del(&priv->dev_list);
+	mutex_unlock(&intf_mutex);
+}
+
+int mlx5_register_interface(struct mlx5_interface *intf)
+{
+	struct mlx5_priv *priv;
+
+	if (!intf->add || !intf->remove)
+		return -EINVAL;
+
+	mutex_lock(&intf_mutex);
+	list_add_tail(&intf->list, &intf_list);
+	list_for_each_entry(priv, &dev_list, dev_list)
+		mlx5_add_device(intf, priv);
+	mutex_unlock(&intf_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(mlx5_register_interface);
+
+void mlx5_unregister_interface(struct mlx5_interface *intf)
+{
+	struct mlx5_priv *priv;
+
+	mutex_lock(&intf_mutex);
+	list_for_each_entry(priv, &dev_list, dev_list)
+	       mlx5_remove_device(intf, priv);
+	list_del(&intf->list);
+	mutex_unlock(&intf_mutex);
+}
+EXPORT_SYMBOL(mlx5_unregister_interface);
+
+static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
+			    unsigned long param)
+{
+	struct mlx5_priv *priv = &dev->priv;
+	struct mlx5_device_context *dev_ctx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->ctx_lock, flags);
+
+	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+		if (dev_ctx->intf->event)
+			dev_ctx->intf->event(dev, dev_ctx->context, event, param);
+
+	spin_unlock_irqrestore(&priv->ctx_lock, flags);
+}
+
+struct mlx5_core_event_handler {
+	void (*event)(struct mlx5_core_dev *dev,
+		      enum mlx5_dev_event event,
+		      void *data);
+};
+
+static int init_one(struct pci_dev *pdev,
+		    const struct pci_device_id *id)
+{
+	struct mlx5_core_dev *dev;
+	struct mlx5_priv *priv;
+	int err;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&pdev->dev, "kzalloc failed\n");
+		return -ENOMEM;
+	}
+	priv = &dev->priv;
+
+	pci_set_drvdata(pdev, dev);
+
+	if (prof_sel < 0 || prof_sel >= ARRAY_SIZE(profile)) {
+		pr_warn("selected profile out of range, selecting default (%d)\n",
+			MLX5_DEFAULT_PROF);
+		prof_sel = MLX5_DEFAULT_PROF;
+	}
+	dev->profile = &profile[prof_sel];
+	dev->event = mlx5_core_event;
+
+	err = mlx5_dev_init(dev, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err);
+		goto out;
+	}
+
+	INIT_LIST_HEAD(&priv->ctx_list);
+	spin_lock_init(&priv->ctx_lock);
+	err = mlx5_register_device(dev);
+	if (err) {
+		dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
+		goto out_init;
+	}
+
+	return 0;
+
+out_init:
+	mlx5_dev_cleanup(dev);
+out:
+	kfree(dev);
+	return err;
+}
+static void remove_one(struct pci_dev *pdev)
+{
+	struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
+
+	mlx5_unregister_device(dev);
+	mlx5_dev_cleanup(dev);
+	kfree(dev);
+}
+
+static const struct pci_device_id mlx5_core_pci_table[] = {
+	{ PCI_VDEVICE(MELLANOX, 4113) }, /* MT4113 Connect-IB */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
+
+static struct pci_driver mlx5_core_driver = {
+	.name           = DRIVER_NAME,
+	.id_table       = mlx5_core_pci_table,
+	.probe          = init_one,
+	.remove         = remove_one
+};
 
 static int __init init(void)
 {
@@ -530,8 +806,15 @@ static int __init init(void)
 	}
 	mlx5_health_init();
 
+	err = pci_register_driver(&mlx5_core_driver);
+	if (err)
+		goto err_health;
+
 	return 0;
 
+err_health:
+	mlx5_health_cleanup();
+	destroy_workqueue(mlx5_core_wq);
 err_debug:
 	mlx5_unregister_debugfs();
 	return err;
@@ -539,6 +822,7 @@ err_debug:
 
 static void __exit cleanup(void)
 {
+	pci_unregister_driver(&mlx5_core_driver);
 	mlx5_health_cleanup();
 	destroy_workqueue(mlx5_core_wq);
 	mlx5_unregister_debugfs();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@ enum {
 
 struct mlx5_pages_req {
 	struct mlx5_core_dev *dev;
-	u32	func_id;
+	u16	func_id;
 	s32	npages;
 	struct work_struct work;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@ struct mlx5_reg_pcap {
 	__be32			caps_31_0;
 };
 
-int mlx5_set_port_caps(struct mlx5_core_dev *dev, int port_num, u32 caps)
+int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
 {
 	struct mlx5_reg_pcap in;
 	struct mlx5_reg_pcap out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/micrel/ks8851_mll.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/micrel/ks8851_mll.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/micrel/ks8851_mll.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/micrel/ks8851_mll.c	2014-09-28 17:29:07.000000000 -0400
@@ -1519,7 +1519,8 @@ static int ks_hw_init(struct ks_net *ks)
 	ks->all_mcast = 0;
 	ks->mcast_lst_size = 0;
 
-	ks->frame_head_info = kmalloc(MHEADER_SIZE, GFP_KERNEL);
+	ks->frame_head_info = devm_kmalloc(&ks->pdev->dev, MHEADER_SIZE,
+					   GFP_KERNEL);
 	if (!ks->frame_head_info)
 		return false;
 
@@ -1537,44 +1538,41 @@ MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids
 
 static int ks8851_probe(struct platform_device *pdev)
 {
-	int err = -ENOMEM;
+	int err;
 	struct resource *io_d, *io_c;
 	struct net_device *netdev;
 	struct ks_net *ks;
 	u16 id, data;
 	const char *mac;
 
-	io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
-	if (!request_mem_region(io_d->start, resource_size(io_d), DRV_NAME))
-		goto err_mem_region;
-
-	if (!request_mem_region(io_c->start, resource_size(io_c), DRV_NAME))
-		goto err_mem_region1;
-
 	netdev = alloc_etherdev(sizeof(struct ks_net));
 	if (!netdev)
-		goto err_alloc_etherdev;
+		return -ENOMEM;
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	ks = netdev_priv(netdev);
 	ks->netdev = netdev;
-	ks->hw_addr = ioremap(io_d->start, resource_size(io_d));
 
-	if (!ks->hw_addr)
-		goto err_ioremap;
+	io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ks->hw_addr = devm_ioremap_resource(&pdev->dev, io_d);
+	if (IS_ERR(ks->hw_addr)) {
+		err = PTR_ERR(ks->hw_addr);
+		goto err_free;
+	}
 
-	ks->hw_addr_cmd = ioremap(io_c->start, resource_size(io_c));
-	if (!ks->hw_addr_cmd)
-		goto err_ioremap1;
+	io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	ks->hw_addr_cmd = devm_ioremap_resource(&pdev->dev, io_c);
+	if (IS_ERR(ks->hw_addr_cmd)) {
+		err = PTR_ERR(ks->hw_addr_cmd);
+		goto err_free;
+	}
 
 	netdev->irq = platform_get_irq(pdev, 0);
 
 	if ((int)netdev->irq < 0) {
 		err = netdev->irq;
-		goto err_get_irq;
+		goto err_free;
 	}
 
 	ks->pdev = pdev;
@@ -1604,18 +1602,18 @@ static int ks8851_probe(struct platform_
 	if ((ks_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
 		netdev_err(netdev, "failed to read device ID\n");
 		err = -ENODEV;
-		goto err_register;
+		goto err_free;
 	}
 
 	if (ks_read_selftest(ks)) {
 		netdev_err(netdev, "failed to read device ID\n");
 		err = -ENODEV;
-		goto err_register;
+		goto err_free;
 	}
 
 	err = register_netdev(netdev);
 	if (err)
-		goto err_register;
+		goto err_free;
 
 	platform_set_drvdata(pdev, netdev);
 
@@ -1663,32 +1661,17 @@ static int ks8851_probe(struct platform_
 
 err_pdata:
 	unregister_netdev(netdev);
-err_register:
-err_get_irq:
-	iounmap(ks->hw_addr_cmd);
-err_ioremap1:
-	iounmap(ks->hw_addr);
-err_ioremap:
+err_free:
 	free_netdev(netdev);
-err_alloc_etherdev:
-	release_mem_region(io_c->start, resource_size(io_c));
-err_mem_region1:
-	release_mem_region(io_d->start, resource_size(io_d));
-err_mem_region:
 	return err;
 }
 
 static int ks8851_remove(struct platform_device *pdev)
 {
 	struct net_device *netdev = platform_get_drvdata(pdev);
-	struct ks_net *ks = netdev_priv(netdev);
-	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	kfree(ks->frame_head_info);
 	unregister_netdev(netdev);
-	iounmap(ks->hw_addr);
 	free_netdev(netdev);
-	release_mem_region(iomem->start, resource_size(iomem));
 	return 0;
 
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/micrel/ksz884x.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/micrel/ksz884x.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/micrel/ksz884x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/micrel/ksz884x.c	2014-09-28 17:29:07.000000000 -0400
@@ -4409,14 +4409,13 @@ static int ksz_alloc_desc(struct dev_inf
 		DESC_ALIGNMENT;
 
 	adapter->desc_pool.alloc_virt =
-		pci_alloc_consistent(
-			adapter->pdev, adapter->desc_pool.alloc_size,
-			&adapter->desc_pool.dma_addr);
+		pci_zalloc_consistent(adapter->pdev,
+				      adapter->desc_pool.alloc_size,
+				      &adapter->desc_pool.dma_addr);
 	if (adapter->desc_pool.alloc_virt == NULL) {
 		adapter->desc_pool.alloc_size = 0;
 		return 1;
 	}
-	memset(adapter->desc_pool.alloc_virt, 0, adapter->desc_pool.alloc_size);
 
 	/* Align to the next cache line boundary. */
 	offset = (((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT) ?
@@ -7222,7 +7221,7 @@ static int pcidev_suspend(struct pci_dev
 
 static char pcidev_name[] = "ksz884xp";
 
-static DEFINE_PCI_DEVICE_TABLE(pcidev_table) = {
+static const struct pci_device_id pcidev_table[] = {
 	{ PCI_VENDOR_ID_MICREL_KS, 0x8841,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MICREL_KS, 0x8842,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/moxa/moxart_ether.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/moxa/moxart_ether.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/moxa/moxart_ether.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/moxa/moxart_ether.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,7 +206,7 @@ static int moxart_rx_poll(struct napi_st
 	int rx_head = priv->rx_head;
 	int rx = 0;
 
-	while (1) {
+	while (rx < budget) {
 		desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head);
 		desc0 = readl(desc + RX_REG_OFFSET_DESC0);
 
@@ -218,7 +218,7 @@ static int moxart_rx_poll(struct napi_st
 			net_dbg_ratelimited("packet error\n");
 			priv->stats.rx_dropped++;
 			priv->stats.rx_errors++;
-			continue;
+			goto rx_next;
 		}
 
 		len = desc0 & RX_DESC0_FRAME_LEN_MASK;
@@ -226,13 +226,19 @@ static int moxart_rx_poll(struct napi_st
 		if (len > RX_BUF_SIZE)
 			len = RX_BUF_SIZE;
 
-		skb = build_skb(priv->rx_buf[rx_head], priv->rx_buf_size);
+		dma_sync_single_for_cpu(&ndev->dev,
+					priv->rx_mapping[rx_head],
+					priv->rx_buf_size, DMA_FROM_DEVICE);
+		skb = netdev_alloc_skb_ip_align(ndev, len);
+
 		if (unlikely(!skb)) {
-			net_dbg_ratelimited("build_skb failed\n");
+			net_dbg_ratelimited("netdev_alloc_skb_ip_align failed\n");
 			priv->stats.rx_dropped++;
 			priv->stats.rx_errors++;
+			goto rx_next;
 		}
 
+		memcpy(skb->data, priv->rx_buf[rx_head], len);
 		skb_put(skb, len);
 		skb->protocol = eth_type_trans(skb, ndev);
 		napi_gro_receive(&priv->napi, skb);
@@ -244,18 +250,15 @@ static int moxart_rx_poll(struct napi_st
 		if (desc0 & RX_DESC0_MULTICAST)
 			priv->stats.multicast++;
 
+rx_next:
 		writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
 
 		rx_head = RX_NEXT(rx_head);
 		priv->rx_head = rx_head;
-
-		if (rx >= budget)
-			break;
 	}
 
 	if (rx < budget) {
-		napi_gro_flush(napi, false);
-		__napi_complete(napi);
+		napi_complete(napi);
 	}
 
 	priv->reg_imr |= RPKT_FINISH_M;
@@ -346,10 +349,12 @@ static int moxart_mac_start_xmit(struct
 		len = ETH_ZLEN;
 	}
 
-	txdes1 = readl(desc + TX_REG_OFFSET_DESC1);
-	txdes1 |= TX_DESC1_LTS | TX_DESC1_FTS;
-	txdes1 &= ~(TX_DESC1_FIFO_COMPLETE | TX_DESC1_INTR_COMPLETE);
-	txdes1 |= (len & TX_DESC1_BUF_SIZE_MASK);
+	dma_sync_single_for_device(&ndev->dev, priv->tx_mapping[tx_head],
+				   priv->tx_buf_size, DMA_TO_DEVICE);
+
+	txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK);
+	if (tx_head == TX_DESC_NUM_MASK)
+		txdes1 |= TX_DESC1_END;
 	writel(txdes1, desc + TX_REG_OFFSET_DESC1);
 	writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0);
 
@@ -465,8 +470,7 @@ static int moxart_mac_probe(struct platf
 	spin_lock_init(&priv->txlock);
 
 	priv->tx_buf_size = TX_BUF_SIZE;
-	priv->rx_buf_size = RX_BUF_SIZE +
-			    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	priv->rx_buf_size = RX_BUF_SIZE;
 
 	priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE *
 						TX_DESC_NUM, &priv->tx_base,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/myricom/myri10ge/myri10ge.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/myricom/myri10ge/myri10ge.c	2014-08-07 04:52:19.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/myricom/myri10ge/myri10ge.c	2014-09-28 21:33:50.000000000 -0400
@@ -571,6 +571,7 @@ myri10ge_validate_firmware(struct myri10
 
 	/* save firmware version for ethtool */
 	strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+	mgp->fw_version[sizeof(mgp->fw_version) - 1] = '\0';
 
 	sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
 	       &mgp->fw_ver_minor, &mgp->fw_ver_tiny);
@@ -869,6 +870,10 @@ static int myri10ge_dma_test(struct myri
 		return -ENOMEM;
 	dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
 				   DMA_BIDIRECTIONAL);
+	if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) {
+		__free_page(dmatest_page);
+		return -ENOMEM;
+	}
 
 	/* Run a small DMA test.
 	 * The magic multipliers to the length tell the firmware
@@ -1290,6 +1295,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_
 			int bytes, int watchdog)
 {
 	struct page *page;
+	dma_addr_t bus;
 	int idx;
 #if MYRI10GE_ALLOC_SIZE > 4096
 	int end_offset;
@@ -1314,11 +1320,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_
 					rx->watchdog_needed = 1;
 				return;
 			}
+
+			bus = pci_map_page(mgp->pdev, page, 0,
+					   MYRI10GE_ALLOC_SIZE,
+					   PCI_DMA_FROMDEVICE);
+			if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) {
+				__free_pages(page, MYRI10GE_ALLOC_ORDER);
+				if (rx->fill_cnt - rx->cnt < 16)
+					rx->watchdog_needed = 1;
+				return;
+			}
+
 			rx->page = page;
 			rx->page_offset = 0;
-			rx->bus = pci_map_page(mgp->pdev, page, 0,
-					       MYRI10GE_ALLOC_SIZE,
-					       PCI_DMA_FROMDEVICE);
+			rx->bus = bus;
+
 		}
 		rx->info[idx].page = rx->page;
 		rx->info[idx].page_offset = rx->page_offset;
@@ -2760,6 +2776,35 @@ myri10ge_submit_req(struct myri10ge_tx_b
 	mb();
 }
 
+static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp,
+				  struct myri10ge_tx_buf *tx, int idx)
+{
+	unsigned int len;
+	int last_idx;
+
+	/* Free any DMA resources we've alloced and clear out the skb slot */
+	last_idx = (idx + 1) & tx->mask;
+	idx = tx->req & tx->mask;
+	do {
+		len = dma_unmap_len(&tx->info[idx], len);
+		if (len) {
+			if (tx->info[idx].skb != NULL)
+				pci_unmap_single(mgp->pdev,
+						 dma_unmap_addr(&tx->info[idx],
+								bus), len,
+						 PCI_DMA_TODEVICE);
+			else
+				pci_unmap_page(mgp->pdev,
+					       dma_unmap_addr(&tx->info[idx],
+							      bus), len,
+					       PCI_DMA_TODEVICE);
+			dma_unmap_len_set(&tx->info[idx], len, 0);
+			tx->info[idx].skb = NULL;
+		}
+		idx = (idx + 1) & tx->mask;
+	} while (idx != last_idx);
+}
+
 /*
  * Transmit a packet.  We need to split the packet so that a single
  * segment does not cross myri10ge->tx_boundary, so this makes segment
@@ -2783,7 +2828,7 @@ static netdev_tx_t myri10ge_xmit(struct
 	u32 low;
 	__be32 high_swapped;
 	unsigned int len;
-	int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+	int idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
 	u16 pseudo_hdr_offset, cksum_offset, queue;
 	int cum_len, seglen, boundary, rdma_count;
 	u8 flags, odd_flag;
@@ -2880,9 +2925,12 @@ again:
 
 	/* map the skb for DMA */
 	len = skb_headlen(skb);
+	bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if (unlikely(pci_dma_mapping_error(mgp->pdev, bus)))
+		goto drop;
+
 	idx = tx->req & tx->mask;
 	tx->info[idx].skb = skb;
-	bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	dma_unmap_addr_set(&tx->info[idx], bus, bus);
 	dma_unmap_len_set(&tx->info[idx], len, len);
 
@@ -2981,12 +3029,16 @@ again:
 			break;
 
 		/* map next fragment for DMA */
-		idx = (count + tx->req) & tx->mask;
 		frag = &skb_shinfo(skb)->frags[frag_idx];
 		frag_idx++;
 		len = skb_frag_size(frag);
 		bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len,
 				       DMA_TO_DEVICE);
+		if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) {
+			myri10ge_unmap_tx_dma(mgp, tx, idx);
+			goto drop;
+		}
+		idx = (count + tx->req) & tx->mask;
 		dma_unmap_addr_set(&tx->info[idx], bus, bus);
 		dma_unmap_len_set(&tx->info[idx], len, len);
 	}
@@ -3017,31 +3069,8 @@ again:
 	return NETDEV_TX_OK;
 
 abort_linearize:
-	/* Free any DMA resources we've alloced and clear out the skb
-	 * slot so as to not trip up assertions, and to avoid a
-	 * double-free if linearizing fails */
+	myri10ge_unmap_tx_dma(mgp, tx, idx);
 
-	last_idx = (idx + 1) & tx->mask;
-	idx = tx->req & tx->mask;
-	tx->info[idx].skb = NULL;
-	do {
-		len = dma_unmap_len(&tx->info[idx], len);
-		if (len) {
-			if (tx->info[idx].skb != NULL)
-				pci_unmap_single(mgp->pdev,
-						 dma_unmap_addr(&tx->info[idx],
-								bus), len,
-						 PCI_DMA_TODEVICE);
-			else
-				pci_unmap_page(mgp->pdev,
-					       dma_unmap_addr(&tx->info[idx],
-							      bus), len,
-					       PCI_DMA_TODEVICE);
-			dma_unmap_len_set(&tx->info[idx], len, 0);
-			tx->info[idx].skb = NULL;
-		}
-		idx = (idx + 1) & tx->mask;
-	} while (idx != last_idx);
 	if (skb_is_gso(skb)) {
 		netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n");
 		goto drop;
@@ -4203,7 +4232,7 @@ static void myri10ge_remove(struct pci_d
 #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 	0x0008
 #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9	0x0009
 
-static DEFINE_PCI_DEVICE_TABLE(myri10ge_pci_tbl) = {
+static const struct pci_device_id myri10ge_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
 	{PCI_DEVICE
 	 (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/natsemi/natsemi.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/natsemi/natsemi.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/natsemi/natsemi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/natsemi/natsemi.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,7 +247,7 @@ static struct {
 	{ "NatSemi DP8381[56]", 0, 24 },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(natsemi_pci_tbl) = {
+static const struct pci_device_id natsemi_pci_tbl[] = {
 	{ PCI_VENDOR_ID_NS, 0x0020, 0x12d9,     0x000c,     0, 0, 0 },
 	{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ }	/* terminate list */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/natsemi/ns83820.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/natsemi/ns83820.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/natsemi/ns83820.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/natsemi/ns83820.c	2014-09-28 17:29:07.000000000 -0400
@@ -2260,7 +2260,7 @@ static void ns83820_remove_one(struct pc
 	free_netdev(ndev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = {
+static const struct pci_device_id ns83820_pci_tbl[] = {
 	{ 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, .driver_data = 0, },
 	{ 0, },
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/neterion/s2io.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/neterion/s2io.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/neterion/s2io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/neterion/s2io.c	2014-09-28 17:29:07.000000000 -0400
@@ -471,7 +471,7 @@ module_param_array(rts_frm_len, uint, NU
  * S2IO device table.
  * This table lists all the devices that this driver supports.
  */
-static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = {
+static const struct pci_device_id s2io_tbl[] = {
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
 	 PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/neterion/vxge/vxge-main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/neterion/vxge/vxge-main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/neterion/vxge/vxge-main.c	2014-08-07 04:53:09.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/neterion/vxge/vxge-main.c	2014-09-28 21:34:48.000000000 -0400
@@ -63,7 +63,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("Neterion's X3100 Series 10GbE PCIe I/O"
 	"Virtualized Server Adapter");
 
-static DEFINE_PCI_DEVICE_TABLE(vxge_id_table) = {
+static const struct pci_device_id vxge_id_table[] = {
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_WIN, PCI_ANY_ID,
 	PCI_ANY_ID},
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_UNI, PCI_ANY_ID,
@@ -503,7 +503,6 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *
 
 			skb_hwts = skb_hwtstamps(skb);
 			skb_hwts->hwtstamp = ns_to_ktime(ns);
-			skb_hwts->syststamp.tv64 = 0;
 		}
 
 		/* rth_hash_type and rth_it_hit are non-zero regardless of
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/nvidia/forcedeth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/nvidia/forcedeth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/nvidia/forcedeth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/nvidia/forcedeth.c	2014-09-28 17:29:07.000000000 -0400
@@ -6185,7 +6185,7 @@ static void nv_shutdown(struct pci_dev *
 #define nv_shutdown NULL
 #endif /* CONFIG_PM */
 
-static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = {
+static const struct pci_device_id pci_tbl[] = {
 	{	/* nForce Ethernet Controller */
 		PCI_DEVICE(0x10DE, 0x01C3),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/nxp/lpc_eth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/nxp/lpc_eth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/nxp/lpc_eth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/nxp/lpc_eth.c	2014-09-28 17:29:07.000000000 -0400
@@ -1220,6 +1220,9 @@ static int lpc_eth_open(struct net_devic
 
 	__lpc_eth_clock_enable(pldat, true);
 
+	/* Suspended PHY makes LPC ethernet core block, so resume now */
+	phy_resume(pldat->phy_dev);
+
 	/* Reset and initialize */
 	__lpc_eth_reset(pldat);
 	__lpc_eth_init(pldat);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/octeon/octeon_mgmt.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/octeon/octeon_mgmt.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/octeon/octeon_mgmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/octeon/octeon_mgmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,28 +247,6 @@ static void octeon_mgmt_rx_fill_ring(str
 	}
 }
 
-static ktime_t ptp_to_ktime(u64 ptptime)
-{
-	ktime_t ktimebase;
-	u64 ptpbase;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/* Fill the icache with the code */
-	ktime_get_real();
-	/* Flush all pending operations */
-	mb();
-	/* Read the time and PTP clock as close together as
-	 * possible. It is important that this sequence take the same
-	 * amount of time to reduce jitter
-	 */
-	ktimebase = ktime_get_real();
-	ptpbase = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_HI);
-	local_irq_restore(flags);
-
-	return ktime_sub_ns(ktimebase, ptpbase - ptptime);
-}
-
 static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
 {
 	union cvmx_mixx_orcnt mix_orcnt;
@@ -312,12 +290,14 @@ static void octeon_mgmt_clean_tx_buffers
 		/* Read the hardware TX timestamp if one was recorded */
 		if (unlikely(re.s.tstamp)) {
 			struct skb_shared_hwtstamps ts;
+			u64 ns;
+
+			memset(&ts, 0, sizeof(ts));
 			/* Read the timestamp */
-			u64 ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port));
+			ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port));
 			/* Remove the timestamp from the FIFO */
 			cvmx_write_csr(CVMX_MIXX_TSCTL(p->port), 0);
 			/* Tell the kernel about the timestamp */
-			ts.syststamp = ptp_to_ktime(ns);
 			ts.hwtstamp = ns_to_ktime(ns);
 			skb_tstamp_tx(skb, &ts);
 		}
@@ -429,7 +409,6 @@ good:
 			struct skb_shared_hwtstamps *ts;
 			ts = skb_hwtstamps(skb);
 			ts->hwtstamp = ns_to_ktime(ns);
-			ts->syststamp = ptp_to_ktime(ns);
 			__skb_pull(skb, 8);
 		}
 		skb->protocol = eth_type_trans(skb, netdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -7,6 +7,7 @@ config PCH_GBE
 	depends on PCI && (X86_32 || COMPILE_TEST)
 	select MII
 	select PTP_1588_CLOCK_PCH
+	select NET_PTP_CLASSIFY
 	---help---
 	  This is a gigabit ethernet driver for EG20T PCH.
 	  EG20T PCH is the platform controller hub that is used in Intel's
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -2743,7 +2743,7 @@ static struct pch_gbe_privdata pch_gbe_m
 	.platform_init = pch_gbe_minnow_platform_init,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
+static const struct pci_device_id pch_gbe_pcidev_id[] = {
 	{.vendor = PCI_VENDOR_ID_INTEL,
 	 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
 	 .subvendor = PCI_VENDOR_ID_CIRCUITCO,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/packetengines/hamachi.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/packetengines/hamachi.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/packetengines/hamachi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/packetengines/hamachi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1911,7 +1911,7 @@ static void hamachi_remove_one(struct pc
 	}
 }
 
-static DEFINE_PCI_DEVICE_TABLE(hamachi_pci_tbl) = {
+static const struct pci_device_id hamachi_pci_tbl[] = {
 	{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/packetengines/yellowfin.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/packetengines/yellowfin.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/packetengines/yellowfin.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/packetengines/yellowfin.c	2014-09-28 17:29:07.000000000 -0400
@@ -236,7 +236,7 @@ static const struct pci_id_info pci_id_t
 	{ }
 };
 
-static DEFINE_PCI_DEVICE_TABLE(yellowfin_pci_tbl) = {
+static const struct pci_device_id yellowfin_pci_tbl[] = {
 	{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/pasemi/pasemi_mac.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/pasemi/pasemi_mac.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/pasemi/pasemi_mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/pasemi/pasemi_mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -1871,7 +1871,7 @@ static void pasemi_mac_remove(struct pci
 	free_netdev(netdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = {
+static const struct pci_device_id pasemi_mac_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) },
 	{ },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,14 +129,12 @@ netxen_get_minidump_template(struct netx
 		return NX_RCODE_INVALID_ARGS;
 	}
 
-	addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr);
-
+	addr = pci_zalloc_consistent(adapter->pdev, size, &md_template_addr);
 	if (!addr) {
 		dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n");
 		return -ENOMEM;
 	}
 
-	memset(addr, 0, size);
 	memset(&cmd, 0, sizeof(cmd));
 	memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
 	cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c	2014-08-07 04:52:26.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c	2014-09-28 21:33:59.000000000 -0400
@@ -99,7 +99,7 @@ static int netxen_nic_set_mac(struct net
 	{PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \
 	.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
 
-static DEFINE_PCI_DEVICE_TABLE(netxen_pci_tbl) = {
+static const struct pci_device_id netxen_pci_tbl[] = {
 	ENTRY(PCI_DEVICE_ID_NX2031_10GXSR),
 	ENTRY(PCI_DEVICE_ID_NX2031_10GCX4),
 	ENTRY(PCI_DEVICE_ID_NX2031_4GCU),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qla3xxx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qla3xxx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qla3xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qla3xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@ static int msi;
 module_param(msi, int, 0);
 MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts.");
 
-static DEFINE_PCI_DEVICE_TABLE(ql3xxx_pci_tbl) = {
+static const struct pci_device_id ql3xxx_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)},
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3032_DEVICE_ID)},
 	/* required last entry */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/Makefile
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,7 @@ qlcnic-y := qlcnic_hw.o qlcnic_main.o ql
 	qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
 	qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
 	qlcnic_83xx_init.o qlcnic_83xx_vnic.o \
-	qlcnic_minidump.o qlcnic_sriov_common.o
+	qlcnic_sriov_common.o
 
 qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -2603,7 +2603,7 @@ int qlcnic_83xx_lockless_flash_read32(st
 	}
 
 	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
-				     (addr));
+				     (addr & 0xFFFF0000));
 
 	range = flash_offset + (count * sizeof(u32));
 	/* Check if data is spread across multiple sectors */
@@ -2753,7 +2753,7 @@ int qlcnic_83xx_read_flash_descriptor_ta
 	ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
 						(u8 *)&adapter->ahw->fdt,
 						count);
-
+	qlcnic_swap32_buffer((u32 *)&adapter->ahw->fdt, count);
 	qlcnic_83xx_unlock_flash(adapter);
 	return ret;
 }
@@ -2788,7 +2788,7 @@ int qlcnic_83xx_erase_flash_sector(struc
 
 	addr1 = (sector_start_addr & 0xFF) << 16;
 	addr2 = (sector_start_addr & 0xFF0000) >> 16;
-	reversed_addr = addr1 | addr2;
+	reversed_addr = addr1 | addr2 | (sector_start_addr & 0xFF00);
 
 	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
 				     reversed_addr);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c	2014-08-07 04:52:26.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c	2014-09-28 21:33:59.000000000 -0400
@@ -1378,31 +1378,45 @@ static int qlcnic_83xx_copy_fw_file(stru
 {
 	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
 	const struct firmware *fw = fw_info->fw;
-	u32 dest, *p_cache;
+	u32 dest, *p_cache, *temp;
 	int i, ret = -EIO;
+	__le32 *temp_le;
 	u8 data[16];
 	size_t size;
 	u64 addr;
 
+	temp = kzalloc(fw->size, GFP_KERNEL);
+	if (!temp) {
+		release_firmware(fw);
+		fw_info->fw = NULL;
+		return -ENOMEM;
+	}
+
+	temp_le = (__le32 *)fw->data;
+
+	/* FW image in file is in little endian, swap the data to nullify
+	 * the effect of writel() operation on big endian platform.
+	 */
+	for (i = 0; i < fw->size / sizeof(u32); i++)
+		temp[i] = __le32_to_cpu(temp_le[i]);
+
 	dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
 	size = (fw->size & ~0xF);
-	p_cache = (u32 *)fw->data;
+	p_cache = temp;
 	addr = (u64)dest;
 
 	ret = qlcnic_ms_mem_write128(adapter, addr,
 				     p_cache, size / 16);
 	if (ret) {
 		dev_err(&adapter->pdev->dev, "MS memory write failed\n");
-		release_firmware(fw);
-		fw_info->fw = NULL;
-		return -EIO;
+		goto exit;
 	}
 
 	/* alignment check */
 	if (fw->size & 0xF) {
 		addr = dest + size;
 		for (i = 0; i < (fw->size & 0xF); i++)
-			data[i] = fw->data[size + i];
+			data[i] = temp[size + i];
 		for (; i < 16; i++)
 			data[i] = 0;
 		ret = qlcnic_ms_mem_write128(adapter, addr,
@@ -1410,15 +1424,16 @@ static int qlcnic_83xx_copy_fw_file(stru
 		if (ret) {
 			dev_err(&adapter->pdev->dev,
 				"MS memory write failed\n");
-			release_firmware(fw);
-			fw_info->fw = NULL;
-			return -EIO;
+			goto exit;
 		}
 	}
+
+exit:
 	release_firmware(fw);
 	fw_info->fw = NULL;
+	kfree(temp);
 
-	return 0;
+	return ret;
 }
 
 static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,7 +136,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_
 	rsp = qlcnic_poll_rsp(adapter);
 
 	if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
-		dev_err(&pdev->dev, "card response timeout.\n");
+		dev_err(&pdev->dev, "command timeout, response = 0x%x\n", rsp);
 		cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
 	} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
 		cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -926,7 +926,7 @@ static int qlcnic_dcb_get_num_tcs(struct
 	}
 }
 
-static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
+static int qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct dcb_app app = {
@@ -935,7 +935,7 @@ static u8 qlcnic_dcb_get_app(struct net_
 			     };
 
 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
-		return 0;
+		return -EINVAL;
 
 	return dcb_getapp(netdev, &app);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -1290,17 +1290,25 @@ static u64 *qlcnic_fill_stats(u64 *data,
 
 void qlcnic_update_stats(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_tx_queue_stats tx_stats;
 	struct qlcnic_host_tx_ring *tx_ring;
 	int ring;
 
+	memset(&tx_stats, 0, sizeof(tx_stats));
 	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
 		tx_ring = &adapter->tx_ring[ring];
-		adapter->stats.xmit_on += tx_ring->tx_stats.xmit_on;
-		adapter->stats.xmit_off += tx_ring->tx_stats.xmit_off;
-		adapter->stats.xmitcalled += tx_ring->tx_stats.xmit_called;
-		adapter->stats.xmitfinished += tx_ring->tx_stats.xmit_finished;
-		adapter->stats.txbytes += tx_ring->tx_stats.tx_bytes;
+		tx_stats.xmit_on += tx_ring->tx_stats.xmit_on;
+		tx_stats.xmit_off += tx_ring->tx_stats.xmit_off;
+		tx_stats.xmit_called += tx_ring->tx_stats.xmit_called;
+		tx_stats.xmit_finished += tx_ring->tx_stats.xmit_finished;
+		tx_stats.tx_bytes += tx_ring->tx_stats.tx_bytes;
 	}
+
+	adapter->stats.xmit_on = tx_stats.xmit_on;
+	adapter->stats.xmit_off = tx_stats.xmit_off;
+	adapter->stats.xmitcalled = tx_stats.xmit_called;
+	adapter->stats.xmitfinished = tx_stats.xmit_finished;
+	adapter->stats.txbytes = tx_stats.tx_bytes;
 }
 
 static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h	2014-08-07 04:52:29.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h	2014-09-28 21:34:02.000000000 -0400
@@ -39,8 +39,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 60
-#define QLCNIC_LINUX_VERSIONID  "5.3.60"
+#define _QLCNIC_LINUX_SUBVERSION 61
+#define QLCNIC_LINUX_VERSIONID  "5.3.61"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -268,7 +268,7 @@ struct qlcnic_fdt {
 	u16	cksum;
 	u16	unused;
 	u8	model[16];
-	u16	mfg_id;
+	u8	mfg_id;
 	u16	id;
 	u8	flag;
 	u8	erase_cmd;
@@ -2362,6 +2362,19 @@ static inline u32 qlcnic_get_vnic_func_c
 		return QLC_DEFAULT_VNIC_COUNT;
 }
 
+static inline void qlcnic_swap32_buffer(u32 *buffer, int count)
+{
+#if defined(__BIG_ENDIAN)
+	u32 *tmp = buffer;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		*tmp = swab32(*tmp);
+		tmp++;
+	}
+#endif
+}
+
 #ifdef CONFIG_QLCNIC_HWMON
 void qlcnic_register_hwmon_dev(struct qlcnic_adapter *);
 void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c	2014-08-07 04:52:35.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c	2014-09-28 21:34:09.000000000 -0400
@@ -108,7 +108,7 @@ static u32 qlcnic_vlan_tx_check(struct q
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
 	.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
 
-static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
+static const struct pci_device_id qlcnic_pci_tbl[] = {
 	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
 	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
 	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
@@ -427,16 +427,17 @@ static int qlcnic_fdb_add(struct ndmsg *
 }
 
 static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
-			struct net_device *netdev, int idx)
+			struct net_device *netdev,
+			struct net_device *filter_dev, int idx)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
 	if (!adapter->fdb_mac_learn)
-		return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+		return ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
 
 	if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
 	    qlcnic_sriov_check(adapter))
-		idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+		idx = ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
 
 	return idx;
 }
@@ -2323,14 +2324,14 @@ qlcnic_setup_netdev(struct qlcnic_adapte
 	if (err)
 		return err;
 
+	qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
+
 	err = register_netdev(netdev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to register net device\n");
 		return err;
 	}
 
-	qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
-
 	return 0;
 }
 
@@ -2623,13 +2624,13 @@ qlcnic_probe(struct pci_dev *pdev, const
 	if (err)
 		goto err_out_disable_mbx_intr;
 
+	if (adapter->portnum == 0)
+		qlcnic_set_drv_version(adapter);
+
 	err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
 	if (err)
 		goto err_out_disable_mbx_intr;
 
-	if (adapter->portnum == 0)
-		qlcnic_set_drv_version(adapter);
-
 	pci_set_drvdata(pdev, adapter);
 
 	if (qlcnic_82xx_check(adapter))
@@ -2980,17 +2981,43 @@ static inline void dump_tx_ring_desc(str
 	}
 }
 
-static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
+static void qlcnic_dump_rings(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 	struct net_device *netdev = adapter->netdev;
+	struct qlcnic_host_rds_ring *rds_ring;
+	struct qlcnic_host_sds_ring *sds_ring;
 	struct qlcnic_host_tx_ring *tx_ring;
 	int ring;
 
 	if (!netdev || !netif_running(netdev))
 		return;
 
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+		if (!rds_ring)
+			continue;
+		netdev_info(netdev,
+			    "rds_ring=%d crb_rcv_producer=%d producer=%u num_desc=%u\n",
+			     ring, readl(rds_ring->crb_rcv_producer),
+			     rds_ring->producer, rds_ring->num_desc);
+	}
+
+	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
+		sds_ring = &(recv_ctx->sds_rings[ring]);
+		if (!sds_ring)
+			continue;
+		netdev_info(netdev,
+			    "sds_ring=%d crb_sts_consumer=%d consumer=%u crb_intr_mask=%d num_desc=%u\n",
+			    ring, readl(sds_ring->crb_sts_consumer),
+			    sds_ring->consumer, readl(sds_ring->crb_intr_mask),
+			    sds_ring->num_desc);
+	}
+
 	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
 		tx_ring = &adapter->tx_ring[ring];
+		if (!tx_ring)
+			continue;
 		netdev_info(netdev, "Tx ring=%d Context Id=0x%x\n",
 			    ring, tx_ring->ctx_id);
 		netdev_info(netdev,
@@ -3013,9 +3040,10 @@ static void qlcnic_dump_tx_rings(struct
 		netdev_info(netdev, "Total desc=%d, Available desc=%d\n",
 			    tx_ring->num_desc, qlcnic_tx_avail(tx_ring));
 
-		if (netif_msg_tx_done(adapter->ahw))
+		if (netif_msg_tx_err(adapter->ahw))
 			dump_tx_ring_desc(tx_ring);
 	}
+
 }
 
 static void qlcnic_tx_timeout(struct net_device *netdev)
@@ -3025,16 +3053,18 @@ static void qlcnic_tx_timeout(struct net
 	if (test_bit(__QLCNIC_RESETTING, &adapter->state))
 		return;
 
-	if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) {
-		netdev_info(netdev, "Tx timeout, reset the adapter.\n");
+	qlcnic_dump_rings(adapter);
+
+	if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS ||
+	    netif_msg_tx_err(adapter->ahw)) {
+		netdev_err(netdev, "Tx timeout, reset the adapter.\n");
 		if (qlcnic_82xx_check(adapter))
 			adapter->need_fw_reset = 1;
 		else if (qlcnic_83xx_check(adapter))
 			qlcnic_83xx_idc_request_reset(adapter,
 						      QLCNIC_FORCE_FW_DUMP_KEY);
 	} else {
-		netdev_info(netdev, "Tx timeout, reset adapter context.\n");
-		qlcnic_dump_tx_rings(adapter);
+		netdev_err(netdev, "Tx timeout, reset adapter context.\n");
 		adapter->ahw->reset_context = 1;
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,15 +47,26 @@ struct qlcnic_common_entry_hdr {
 	u32     type;
 	u32     offset;
 	u32     cap_size;
+#if defined(__LITTLE_ENDIAN)
 	u8      mask;
 	u8      rsvd[2];
 	u8      flags;
+#else
+	u8      flags;
+	u8      rsvd[2];
+	u8      mask;
+#endif
 } __packed;
 
 struct __crb {
 	u32	addr;
+#if defined(__LITTLE_ENDIAN)
 	u8	stride;
 	u8	rsvd1[3];
+#else
+	u8	rsvd1[3];
+	u8	stride;
+#endif
 	u32	data_size;
 	u32	no_ops;
 	u32	rsvd2[4];
@@ -63,15 +74,28 @@ struct __crb {
 
 struct __ctrl {
 	u32	addr;
+#if defined(__LITTLE_ENDIAN)
 	u8	stride;
 	u8	index_a;
 	u16	timeout;
+#else
+	u16	timeout;
+	u8	index_a;
+	u8	stride;
+#endif
 	u32	data_size;
 	u32	no_ops;
+#if defined(__LITTLE_ENDIAN)
 	u8	opcode;
 	u8	index_v;
 	u8	shl_val;
 	u8	shr_val;
+#else
+	u8	shr_val;
+	u8	shl_val;
+	u8	index_v;
+	u8	opcode;
+#endif
 	u32	val1;
 	u32	val2;
 	u32	val3;
@@ -79,16 +103,27 @@ struct __ctrl {
 
 struct __cache {
 	u32	addr;
+#if defined(__LITTLE_ENDIAN)
 	u16	stride;
 	u16	init_tag_val;
+#else
+	u16	init_tag_val;
+	u16	stride;
+#endif
 	u32	size;
 	u32	no_ops;
 	u32	ctrl_addr;
 	u32	ctrl_val;
 	u32	read_addr;
+#if defined(__LITTLE_ENDIAN)
 	u8	read_addr_stride;
 	u8	read_addr_num;
 	u8	rsvd1[2];
+#else
+	u8	rsvd1[2];
+	u8	read_addr_num;
+	u8	read_addr_stride;
+#endif
 } __packed;
 
 struct __ocm {
@@ -122,23 +157,39 @@ struct __mux {
 
 struct __queue {
 	u32	sel_addr;
+#if defined(__LITTLE_ENDIAN)
 	u16	stride;
 	u8	rsvd[2];
+#else
+	u8	rsvd[2];
+	u16	stride;
+#endif
 	u32	size;
 	u32	no_ops;
 	u8	rsvd2[8];
 	u32	read_addr;
+#if defined(__LITTLE_ENDIAN)
 	u8	read_addr_stride;
 	u8	read_addr_cnt;
 	u8	rsvd3[2];
+#else
+	u8	rsvd3[2];
+	u8	read_addr_cnt;
+	u8	read_addr_stride;
+#endif
 } __packed;
 
 struct __pollrd {
 	u32	sel_addr;
 	u32	read_addr;
 	u32	sel_val;
+#if defined(__LITTLE_ENDIAN)
 	u16	sel_val_stride;
 	u16	no_ops;
+#else
+	u16	no_ops;
+	u16	sel_val_stride;
+#endif
 	u32	poll_wait;
 	u32	poll_mask;
 	u32	data_size;
@@ -153,9 +204,15 @@ struct __mux2 {
 	u32	no_ops;
 	u32	sel_val_mask;
 	u32	read_addr;
+#if defined(__LITTLE_ENDIAN)
 	u8	sel_val_stride;
 	u8	data_size;
 	u8	rsvd[2];
+#else
+	u8	rsvd[2];
+	u8	data_size;
+	u8	sel_val_stride;
+#endif
 } __packed;
 
 struct __pollrdmwr {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -280,6 +280,7 @@ static ssize_t qlcnic_sysfs_read_crb(str
 	if (ret != 0)
 		return ret;
 	qlcnic_read_crb(adapter, buf, offset, size);
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 
 	return size;
 }
@@ -296,6 +297,7 @@ static ssize_t qlcnic_sysfs_write_crb(st
 	if (ret != 0)
 		return ret;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	qlcnic_write_crb(adapter, buf, offset, size);
 	return size;
 }
@@ -329,6 +331,7 @@ static ssize_t qlcnic_sysfs_read_mem(str
 		return -EIO;
 
 	memcpy(buf, &data, size);
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 
 	return size;
 }
@@ -346,6 +349,7 @@ static ssize_t qlcnic_sysfs_write_mem(st
 	if (ret != 0)
 		return ret;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	memcpy(&data, buf, size);
 
 	if (qlcnic_pci_mem_write_2M(adapter, offset, data))
@@ -412,6 +416,7 @@ static ssize_t qlcnic_sysfs_write_pm_con
 	if (rem)
 		return QL_STATUS_INVALID_PARAM;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
 	ret = validate_pm_config(adapter, pm_cfg, count);
 
@@ -474,6 +479,7 @@ static ssize_t qlcnic_sysfs_read_pm_conf
 		pm_cfg[pci_func].dest_npar = 0;
 		pm_cfg[pci_func].pci_func = i;
 	}
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	return size;
 }
 
@@ -555,6 +561,7 @@ static ssize_t qlcnic_sysfs_write_esw_co
 	if (rem)
 		return QL_STATUS_INVALID_PARAM;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
 	ret = validate_esw_config(adapter, esw_cfg, count);
 	if (ret)
@@ -649,6 +656,7 @@ static ssize_t qlcnic_sysfs_read_esw_con
 		if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
 			return QL_STATUS_INVALID_PARAM;
 	}
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	return size;
 }
 
@@ -688,6 +696,7 @@ static ssize_t qlcnic_sysfs_write_npar_c
 	if (rem)
 		return QL_STATUS_INVALID_PARAM;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	np_cfg = (struct qlcnic_npar_func_cfg *)buf;
 	ret = validate_npar_config(adapter, np_cfg, count);
 	if (ret)
@@ -759,6 +768,7 @@ static ssize_t qlcnic_sysfs_read_npar_co
 		np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
 		np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
 	}
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	return size;
 }
 
@@ -916,6 +926,7 @@ static ssize_t qlcnic_sysfs_read_pci_con
 
 	pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
 	count = size / sizeof(struct qlcnic_pci_func_cfg);
+	qlcnic_swap32_buffer((u32 *)pci_info, size / sizeof(u32));
 	for (i = 0; i < count; i++) {
 		pci_cfg[i].pci_func = pci_info[i].id;
 		pci_cfg[i].func_type = pci_info[i].type;
@@ -969,6 +980,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_r
 	}
 
 	qlcnic_83xx_unlock_flash(adapter);
+	qlcnic_swap32_buffer((u32 *)p_read_buf, count);
 	memcpy(buf, p_read_buf, size);
 	kfree(p_read_buf);
 
@@ -986,9 +998,10 @@ static int qlcnic_83xx_sysfs_flash_bulk_
 	if (!p_cache)
 		return -ENOMEM;
 
+	count = size / sizeof(u32);
+	qlcnic_swap32_buffer((u32 *)buf, count);
 	memcpy(p_cache, buf, size);
 	p_src = p_cache;
-	count = size / sizeof(u32);
 
 	if (qlcnic_83xx_lock_flash(adapter) != 0) {
 		kfree(p_cache);
@@ -1053,6 +1066,7 @@ static int qlcnic_83xx_sysfs_flash_write
 	if (!p_cache)
 		return -ENOMEM;
 
+	qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
 	memcpy(p_cache, buf, size);
 	p_src = p_cache;
 	count = size / sizeof(u32);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlge/qlge_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlge/qlge_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/qlogic/qlge/qlge_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/qlogic/qlge/qlge_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@ MODULE_PARM_DESC(qlge_force_coredump,
 		"Option to allow force of firmware core dump. "
 		"Default is OFF - Do not allow.");
 
-static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = {
+static const struct pci_device_id qlge_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)},
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)},
 	/* required last entry */
@@ -2556,6 +2556,7 @@ static int ql_tso(struct sk_buff *skb, s
 
 	if (skb_is_gso(skb)) {
 		int err;
+		__be16 l3_proto = vlan_get_protocol(skb);
 
 		err = skb_cow_head(skb, 0);
 		if (err < 0)
@@ -2572,7 +2573,7 @@ static int ql_tso(struct sk_buff *skb, s
 				<< OB_MAC_TRANSPORT_HDR_SHIFT);
 		mac_iocb_ptr->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
 		mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_LSO;
-		if (likely(skb->protocol == htons(ETH_P_IP))) {
+		if (likely(l3_proto == htons(ETH_P_IP))) {
 			struct iphdr *iph = ip_hdr(skb);
 			iph->check = 0;
 			mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4;
@@ -2580,7 +2581,7 @@ static int ql_tso(struct sk_buff *skb, s
 								 iph->daddr, 0,
 								 IPPROTO_TCP,
 								 0);
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		} else if (l3_proto == htons(ETH_P_IPV6)) {
 			mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP6;
 			tcp_hdr(skb)->check =
 			    ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
@@ -2727,23 +2728,22 @@ static void ql_free_shadow_space(struct
 static int ql_alloc_shadow_space(struct ql_adapter *qdev)
 {
 	qdev->rx_ring_shadow_reg_area =
-	    pci_alloc_consistent(qdev->pdev,
-				 PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma);
+		pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
+				      &qdev->rx_ring_shadow_reg_dma);
 	if (qdev->rx_ring_shadow_reg_area == NULL) {
 		netif_err(qdev, ifup, qdev->ndev,
 			  "Allocation of RX shadow space failed.\n");
 		return -ENOMEM;
 	}
-	memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE);
+
 	qdev->tx_ring_shadow_reg_area =
-	    pci_alloc_consistent(qdev->pdev, PAGE_SIZE,
-				 &qdev->tx_ring_shadow_reg_dma);
+		pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
+				      &qdev->tx_ring_shadow_reg_dma);
 	if (qdev->tx_ring_shadow_reg_area == NULL) {
 		netif_err(qdev, ifup, qdev->ndev,
 			  "Allocation of TX shadow space failed.\n");
 		goto err_wqp_sh_area;
 	}
-	memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE);
 	return 0;
 
 err_wqp_sh_area:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/rdc/r6040.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/rdc/r6040.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/rdc/r6040.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/rdc/r6040.c	2014-09-28 17:29:07.000000000 -0400
@@ -1254,7 +1254,7 @@ static void r6040_remove_one(struct pci_
 }
 
 
-static DEFINE_PCI_DEVICE_TABLE(r6040_pci_tbl) = {
+static const struct pci_device_id r6040_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) },
 	{ 0 }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/realtek/8139cp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/8139cp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/realtek/8139cp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/8139cp.c	2014-09-28 17:29:07.000000000 -0400
@@ -382,13 +382,6 @@ static int cp_get_eeprom(struct net_devi
 static int cp_set_eeprom(struct net_device *dev,
 			 struct ethtool_eeprom *eeprom, u8 *data);
 
-static DEFINE_PCI_DEVICE_TABLE(cp_pci_tbl) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	PCI_DEVICE_ID_REALTEK_8139), },
-	{ PCI_DEVICE(PCI_VENDOR_ID_TTTECH,	PCI_DEVICE_ID_TTTECH_MC322), },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
-
 static struct {
 	const char str[ETH_GSTRING_LEN];
 } ethtool_stats_keys[] = {
@@ -1887,11 +1880,7 @@ static int cp_init_one (struct pci_dev *
 	resource_size_t pciaddr;
 	unsigned int addr_len, i, pci_using_dac;
 
-#ifndef MODULE
-	static int version_printed;
-	if (version_printed++ == 0)
-		pr_info("%s", version);
-#endif
+	pr_info_once("%s", version);
 
 	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
 	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
@@ -2110,6 +2099,13 @@ static int cp_resume (struct pci_dev *pd
 }
 #endif /* CONFIG_PM */
 
+static const struct pci_device_id cp_pci_tbl[] = {
+        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     PCI_DEVICE_ID_REALTEK_8139), },
+        { PCI_DEVICE(PCI_VENDOR_ID_TTTECH,      PCI_DEVICE_ID_TTTECH_MC322), },
+        { },
+};
+MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
+
 static struct pci_driver cp_driver = {
 	.name         = DRV_NAME,
 	.id_table     = cp_pci_tbl,
@@ -2121,18 +2117,4 @@ static struct pci_driver cp_driver = {
 #endif
 };
 
-static int __init cp_init (void)
-{
-#ifdef MODULE
-	pr_info("%s", version);
-#endif
-	return pci_register_driver(&cp_driver);
-}
-
-static void __exit cp_exit (void)
-{
-	pci_unregister_driver (&cp_driver);
-}
-
-module_init(cp_init);
-module_exit(cp_exit);
+module_pci_driver(cp_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/realtek/8139too.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/8139too.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/realtek/8139too.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/8139too.c	2014-09-28 17:29:07.000000000 -0400
@@ -234,7 +234,7 @@ static const struct {
 };
 
 
-static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = {
+static const struct pci_device_id rtl8139_pci_tbl[] = {
 	{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/realtek/r8169.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/r8169.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/realtek/r8169.c	2014-08-07 04:52:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/realtek/r8169.c	2014-09-28 21:34:16.000000000 -0400
@@ -27,6 +27,8 @@
 #include <linux/firmware.h>
 #include <linux/pci-aspm.h>
 #include <linux/prefetch.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -289,7 +291,7 @@ enum cfg_version {
 	RTL_CFG_2
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
+static const struct pci_device_id rtl8169_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8129), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8136), 0, 0, RTL_CFG_2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8167), 0, 0, RTL_CFG_0 },
@@ -627,39 +629,22 @@ enum rtl_tx_desc_bit_0 {
 
 /* 8102e, 8168c and beyond. */
 enum rtl_tx_desc_bit_1 {
+	/* First doubleword. */
+	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
+	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
+#define GTTCPHO_SHIFT			18
+#define GTTCPHO_MAX			0x7fU
+
 	/* Second doubleword. */
+#define TCPHO_SHIFT			18
+#define TCPHO_MAX			0x3ffU
 #define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
-	TD1_IP_CS	= (1 << 29),		/* Calculate IP checksum */
+	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
+	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
 	TD1_TCP_CS	= (1 << 30),		/* Calculate TCP/IP checksum */
 	TD1_UDP_CS	= (1 << 31),		/* Calculate UDP/IP checksum */
 };
 
-static const struct rtl_tx_desc_info {
-	struct {
-		u32 udp;
-		u32 tcp;
-	} checksum;
-	u16 mss_shift;
-	u16 opts_offset;
-} tx_desc_info [] = {
-	[RTL_TD_0] = {
-		.checksum = {
-			.udp	= TD0_IP_CS | TD0_UDP_CS,
-			.tcp	= TD0_IP_CS | TD0_TCP_CS
-		},
-		.mss_shift	= TD0_MSS_SHIFT,
-		.opts_offset	= 0
-	},
-	[RTL_TD_1] = {
-		.checksum = {
-			.udp	= TD1_IP_CS | TD1_UDP_CS,
-			.tcp	= TD1_IP_CS | TD1_TCP_CS
-		},
-		.mss_shift	= TD1_MSS_SHIFT,
-		.opts_offset	= 1
-	}
-};
-
 enum rtl_rx_desc_bit {
 	/* Rx private */
 	PID1		= (1 << 18), /* Protocol ID bit 1/2 */
@@ -783,6 +768,7 @@ struct rtl8169_private {
 	unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
 	unsigned int (*link_ok)(void __iomem *);
 	int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
+	bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *);
 
 	struct {
 		DECLARE_BITMAP(flags, RTL_FLAG_MAX);
@@ -1783,33 +1769,31 @@ static void __rtl8169_set_features(struc
 				   netdev_features_t features)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	netdev_features_t changed = features ^ dev->features;
 	void __iomem *ioaddr = tp->mmio_addr;
+	u32 rx_config;
 
-	if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM |
-			 NETIF_F_HW_VLAN_CTAG_RX)))
-		return;
+	rx_config = RTL_R32(RxConfig);
+	if (features & NETIF_F_RXALL)
+		rx_config |= (AcceptErr | AcceptRunt);
+	else
+		rx_config &= ~(AcceptErr | AcceptRunt);
 
-	if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) {
-		if (features & NETIF_F_RXCSUM)
-			tp->cp_cmd |= RxChkSum;
-		else
-			tp->cp_cmd &= ~RxChkSum;
+	RTL_W32(RxConfig, rx_config);
 
-		if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
-			tp->cp_cmd |= RxVlan;
-		else
-			tp->cp_cmd &= ~RxVlan;
+	if (features & NETIF_F_RXCSUM)
+		tp->cp_cmd |= RxChkSum;
+	else
+		tp->cp_cmd &= ~RxChkSum;
 
-		RTL_W16(CPlusCmd, tp->cp_cmd);
-		RTL_R16(CPlusCmd);
-	}
-	if (changed & NETIF_F_RXALL) {
-		int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
-		if (features & NETIF_F_RXALL)
-			tmp |= (AcceptErr | AcceptRunt);
-		RTL_W32(RxConfig, tmp);
-	}
+	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		tp->cp_cmd |= RxVlan;
+	else
+		tp->cp_cmd &= ~RxVlan;
+
+	tp->cp_cmd |= RTL_R16(CPlusCmd) & ~(RxVlan | RxChkSum);
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+	RTL_R16(CPlusCmd);
 }
 
 static int rtl8169_set_features(struct net_device *dev,
@@ -1817,8 +1801,11 @@ static int rtl8169_set_features(struct n
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
+	features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX;
+
 	rtl_lock_work(tp);
-	__rtl8169_set_features(dev, features);
+	if (features ^ dev->features)
+		__rtl8169_set_features(dev, features);
 	rtl_unlock_work(tp);
 
 	return 0;
@@ -5954,32 +5941,179 @@ static bool rtl_test_hw_pad_bug(struct r
 	return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
 }
 
-static inline bool rtl8169_tso_csum(struct rtl8169_private *tp,
-				    struct sk_buff *skb, u32 *opts)
+static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev);
+/* r8169_csum_workaround()
+ * The hw limites the value the transport offset. When the offset is out of the
+ * range, calculate the checksum by sw.
+ */
+static void r8169_csum_workaround(struct rtl8169_private *tp,
+				  struct sk_buff *skb)
+{
+	if (skb_shinfo(skb)->gso_size) {
+		netdev_features_t features = tp->dev->features;
+		struct sk_buff *segs, *nskb;
+
+		features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+		segs = skb_gso_segment(skb, features);
+		if (IS_ERR(segs) || !segs)
+			goto drop;
+
+		do {
+			nskb = segs;
+			segs = segs->next;
+			nskb->next = NULL;
+			rtl8169_start_xmit(nskb, tp->dev);
+		} while (segs);
+
+		dev_kfree_skb(skb);
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (skb_checksum_help(skb) < 0)
+			goto drop;
+
+		rtl8169_start_xmit(skb, tp->dev);
+	} else {
+		struct net_device_stats *stats;
+
+drop:
+		stats = &tp->dev->stats;
+		stats->tx_dropped++;
+		dev_kfree_skb(skb);
+	}
+}
+
+/* msdn_giant_send_check()
+ * According to the document of microsoft, the TCP Pseudo Header excludes the
+ * packet length for IPv6 TCP large packets.
+ */
+static int msdn_giant_send_check(struct sk_buff *skb)
+{
+	const struct ipv6hdr *ipv6h;
+	struct tcphdr *th;
+	int ret;
+
+	ret = skb_cow_head(skb, 0);
+	if (ret)
+		return ret;
+
+	ipv6h = ipv6_hdr(skb);
+	th = tcp_hdr(skb);
+
+	th->check = 0;
+	th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
+
+	return ret;
+}
+
+static inline __be16 get_protocol(struct sk_buff *skb)
+{
+	__be16 protocol;
+
+	if (skb->protocol == htons(ETH_P_8021Q))
+		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+	else
+		protocol = skb->protocol;
+
+	return protocol;
+}
+
+static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp,
+				struct sk_buff *skb, u32 *opts)
 {
-	const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
 	u32 mss = skb_shinfo(skb)->gso_size;
-	int offset = info->opts_offset;
 
 	if (mss) {
 		opts[0] |= TD_LSO;
-		opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
+		opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT;
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		const struct iphdr *ip = ip_hdr(skb);
 
+		if (ip->protocol == IPPROTO_TCP)
+			opts[0] |= TD0_IP_CS | TD0_TCP_CS;
+		else if (ip->protocol == IPPROTO_UDP)
+			opts[0] |= TD0_IP_CS | TD0_UDP_CS;
+		else
+			WARN_ON_ONCE(1);
+	}
+
+	return true;
+}
+
+static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
+				struct sk_buff *skb, u32 *opts)
+{
+	u32 transport_offset = (u32)skb_transport_offset(skb);
+	u32 mss = skb_shinfo(skb)->gso_size;
+
+	if (mss) {
+		if (transport_offset > GTTCPHO_MAX) {
+			netif_warn(tp, tx_err, tp->dev,
+				   "Invalid transport offset 0x%x for TSO\n",
+				   transport_offset);
+			return false;
+		}
+
+		switch (get_protocol(skb)) {
+		case htons(ETH_P_IP):
+			opts[0] |= TD1_GTSENV4;
+			break;
+
+		case htons(ETH_P_IPV6):
+			if (msdn_giant_send_check(skb))
+				return false;
+
+			opts[0] |= TD1_GTSENV6;
+			break;
+
+		default:
+			WARN_ON_ONCE(1);
+			break;
+		}
+
+		opts[0] |= transport_offset << GTTCPHO_SHIFT;
+		opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT;
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		u8 ip_protocol;
+
 		if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
 			return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
 
-		if (ip->protocol == IPPROTO_TCP)
-			opts[offset] |= info->checksum.tcp;
-		else if (ip->protocol == IPPROTO_UDP)
-			opts[offset] |= info->checksum.udp;
+		if (transport_offset > TCPHO_MAX) {
+			netif_warn(tp, tx_err, tp->dev,
+				   "Invalid transport offset 0x%x\n",
+				   transport_offset);
+			return false;
+		}
+
+		switch (get_protocol(skb)) {
+		case htons(ETH_P_IP):
+			opts[1] |= TD1_IPv4_CS;
+			ip_protocol = ip_hdr(skb)->protocol;
+			break;
+
+		case htons(ETH_P_IPV6):
+			opts[1] |= TD1_IPv6_CS;
+			ip_protocol = ipv6_hdr(skb)->nexthdr;
+			break;
+
+		default:
+			ip_protocol = IPPROTO_RAW;
+			break;
+		}
+
+		if (ip_protocol == IPPROTO_TCP)
+			opts[1] |= TD1_TCP_CS;
+		else if (ip_protocol == IPPROTO_UDP)
+			opts[1] |= TD1_UDP_CS;
 		else
 			WARN_ON_ONCE(1);
+
+		opts[1] |= transport_offset << TCPHO_SHIFT;
 	} else {
 		if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
 			return rtl_skb_pad(skb);
 	}
+
 	return true;
 }
 
@@ -6007,8 +6141,10 @@ static netdev_tx_t rtl8169_start_xmit(st
 	opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
 	opts[0] = DescOwn;
 
-	if (!rtl8169_tso_csum(tp, skb, opts))
-		goto err_update_stats;
+	if (!tp->tso_csum(tp, skb, opts)) {
+		r8169_csum_workaround(tp, skb);
+		return NETDEV_TX_OK;
+	}
 
 	len = skb_headlen(skb);
 	mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
@@ -6073,7 +6209,6 @@ err_dma_1:
 	rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
 err_dma_0:
 	dev_kfree_skb_any(skb);
-err_update_stats:
 	dev->stats.tx_dropped++;
 	return NETDEV_TX_OK;
 
@@ -6970,8 +7105,7 @@ static void rtl_hw_initialize(struct rtl
 	}
 }
 
-static int
-rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
 	const unsigned int region = cfg->region;
@@ -7046,7 +7180,7 @@ rtl_init_one(struct pci_dev *pdev, const
 		goto err_out_mwi_2;
 	}
 
-	tp->cp_cmd = RxChkSum;
+	tp->cp_cmd = 0;
 
 	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
@@ -7087,13 +7221,6 @@ rtl_init_one(struct pci_dev *pdev, const
 
 	pci_set_master(pdev);
 
-	/*
-	 * Pretend we are using VLANs; This bypasses a nasty bug where
-	 * Interrupts stop flowing on high load on 8110SCd controllers.
-	 */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
-		tp->cp_cmd |= RxVlan;
-
 	rtl_init_mdio_ops(tp);
 	rtl_init_pll_power_ops(tp);
 	rtl_init_jumbo_ops(tp);
@@ -7154,10 +7281,24 @@ rtl_init_one(struct pci_dev *pdev, const
 	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
 		NETIF_F_HIGHDMA;
 
+	tp->cp_cmd |= RxChkSum | RxVlan;
+
+	/*
+	 * Pretend we are using VLANs; This bypasses a nasty bug where
+	 * Interrupts stop flowing on high load on 8110SCd controllers.
+	 */
 	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
-		/* 8110SCd requires hardware Rx VLAN - disallow toggling */
+		/* Disallow toggling */
 		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 
+	if (tp->txd_version == RTL_TD_0)
+		tp->tso_csum = rtl8169_tso_csum_v1;
+	else if (tp->txd_version == RTL_TD_1) {
+		tp->tso_csum = rtl8169_tso_csum_v2;
+		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+	} else
+		WARN_ON_ONCE(1);
+
 	dev->hw_features |= NETIF_F_RXALL;
 	dev->hw_features |= NETIF_F_RXFCS;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/renesas/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/renesas/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/renesas/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/renesas/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
 config SH_ETH
 	tristate "Renesas SuperH Ethernet support"
 	depends on HAS_DMA
+	depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
 	select CRC32
 	select MII
 	select MDIO_BITBANG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/renesas/sh_eth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/renesas/sh_eth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/renesas/sh_eth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/renesas/sh_eth.c	2014-09-28 17:29:07.000000000 -0400
@@ -1094,20 +1094,16 @@ static void sh_eth_ring_free(struct net_
 
 	/* Free Rx skb ringbuffer */
 	if (mdp->rx_skbuff) {
-		for (i = 0; i < mdp->num_rx_ring; i++) {
-			if (mdp->rx_skbuff[i])
-				dev_kfree_skb(mdp->rx_skbuff[i]);
-		}
+		for (i = 0; i < mdp->num_rx_ring; i++)
+			dev_kfree_skb(mdp->rx_skbuff[i]);
 	}
 	kfree(mdp->rx_skbuff);
 	mdp->rx_skbuff = NULL;
 
 	/* Free Tx skb ringbuffer */
 	if (mdp->tx_skbuff) {
-		for (i = 0; i < mdp->num_tx_ring; i++) {
-			if (mdp->tx_skbuff[i])
-				dev_kfree_skb(mdp->tx_skbuff[i]);
-		}
+		for (i = 0; i < mdp->num_tx_ring; i++)
+			dev_kfree_skb(mdp->tx_skbuff[i]);
 	}
 	kfree(mdp->tx_skbuff);
 	mdp->tx_skbuff = NULL;
@@ -2077,13 +2073,11 @@ static void sh_eth_tx_timeout(struct net
 		rxdesc = &mdp->rx_ring[i];
 		rxdesc->status = 0;
 		rxdesc->addr = 0xBADF00D0;
-		if (mdp->rx_skbuff[i])
-			dev_kfree_skb(mdp->rx_skbuff[i]);
+		dev_kfree_skb(mdp->rx_skbuff[i]);
 		mdp->rx_skbuff[i] = NULL;
 	}
 	for (i = 0; i < mdp->num_tx_ring; i++) {
-		if (mdp->tx_skbuff[i])
-			dev_kfree_skb(mdp->tx_skbuff[i]);
+		dev_kfree_skb(mdp->tx_skbuff[i]);
 		mdp->tx_skbuff[i] = NULL;
 	}
 
@@ -2752,6 +2746,7 @@ static const struct of_device_id sh_eth_
 	{ .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
 	{ .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
 	{ .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
+	{ .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data },
 	{ .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
 	{ }
 };
@@ -2978,6 +2973,7 @@ static struct platform_device_id sh_eth_
 	{ "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
 	{ "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
 	{ "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
+	{ "r8a7794-ether", (kernel_ulong_t)&r8a779x_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/ef10.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/ef10.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/ef10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/ef10.c	2014-09-28 17:29:07.000000000 -0400
@@ -755,6 +755,8 @@ static int efx_ef10_reset(struct efx_nic
 	{ NULL, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
 #define EF10_OTHER_STAT(ext_name)				\
 	[EF10_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name)				\
+	[GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
 
 static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
 	EF10_DMA_STAT(tx_bytes, TX_BYTES),
@@ -798,6 +800,8 @@ static const struct efx_hw_stat_desc efx
 	EF10_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS),
 	EF10_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
 	EF10_DMA_STAT(rx_nodesc_drops, RX_NODESC_DROPS),
+	GENERIC_SW_STAT(rx_nodesc_trunc),
+	GENERIC_SW_STAT(rx_noskb_drops),
 	EF10_DMA_STAT(rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
 	EF10_DMA_STAT(rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
 	EF10_DMA_STAT(rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
@@ -841,7 +845,9 @@ static const struct efx_hw_stat_desc efx
 			       (1ULL << EF10_STAT_rx_gtjumbo) |		\
 			       (1ULL << EF10_STAT_rx_bad_gtjumbo) |	\
 			       (1ULL << EF10_STAT_rx_overflow) |	\
-			       (1ULL << EF10_STAT_rx_nodesc_drops))
+			       (1ULL << EF10_STAT_rx_nodesc_drops) |	\
+			       (1ULL << GENERIC_STAT_rx_nodesc_trunc) |	\
+			       (1ULL << GENERIC_STAT_rx_noskb_drops))
 
 /* These statistics are only provided by the 10G MAC.  For a 10G/40G
  * switchable port we do not expose these because they might not
@@ -951,7 +957,7 @@ static int efx_ef10_try_update_nic_stats
 		stats[EF10_STAT_rx_bytes_minus_good_bytes];
 	efx_update_diff_stat(&stats[EF10_STAT_rx_bad_bytes],
 			     stats[EF10_STAT_rx_bytes_minus_good_bytes]);
-
+	efx_update_sw_stats(efx, stats);
 	return 0;
 }
 
@@ -990,7 +996,9 @@ static size_t efx_ef10_update_stats(stru
 		core_stats->tx_packets = stats[EF10_STAT_tx_packets];
 		core_stats->rx_bytes = stats[EF10_STAT_rx_bytes];
 		core_stats->tx_bytes = stats[EF10_STAT_tx_bytes];
-		core_stats->rx_dropped = stats[EF10_STAT_rx_nodesc_drops];
+		core_stats->rx_dropped = stats[EF10_STAT_rx_nodesc_drops] +
+					 stats[GENERIC_STAT_rx_nodesc_trunc] +
+					 stats[GENERIC_STAT_rx_noskb_drops];
 		core_stats->multicast = stats[EF10_STAT_rx_multicast];
 		core_stats->rx_length_errors =
 			stats[EF10_STAT_rx_gtjumbo] +
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/efx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/efx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/efx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/efx.c	2014-09-28 17:29:07.000000000 -0400
@@ -272,6 +272,9 @@ static int efx_poll(struct napi_struct *
 	struct efx_nic *efx = channel->efx;
 	int spent;
 
+	if (!efx_channel_lock_napi(channel))
+		return budget;
+
 	netif_vdbg(efx, intr, efx->net_dev,
 		   "channel %d NAPI poll executing on CPU %d\n",
 		   channel->channel, raw_smp_processor_id());
@@ -311,6 +314,7 @@ static int efx_poll(struct napi_struct *
 		efx_nic_eventq_read_ack(channel);
 	}
 
+	efx_channel_unlock_napi(channel);
 	return spent;
 }
 
@@ -357,7 +361,7 @@ static int efx_init_eventq(struct efx_ch
 }
 
 /* Enable event queue processing and NAPI */
-static void efx_start_eventq(struct efx_channel *channel)
+void efx_start_eventq(struct efx_channel *channel)
 {
 	netif_dbg(channel->efx, ifup, channel->efx->net_dev,
 		  "chan %d start event queue\n", channel->channel);
@@ -366,17 +370,20 @@ static void efx_start_eventq(struct efx_
 	channel->enabled = true;
 	smp_wmb();
 
+	efx_channel_enable(channel);
 	napi_enable(&channel->napi_str);
 	efx_nic_eventq_read_ack(channel);
 }
 
 /* Disable event queue processing and NAPI */
-static void efx_stop_eventq(struct efx_channel *channel)
+void efx_stop_eventq(struct efx_channel *channel)
 {
 	if (!channel->enabled)
 		return;
 
 	napi_disable(&channel->napi_str);
+	while (!efx_channel_disable(channel))
+		usleep_range(1000, 20000);
 	channel->enabled = false;
 }
 
@@ -1960,6 +1967,8 @@ static void efx_init_napi_channel(struct
 	channel->napi_dev = efx->net_dev;
 	netif_napi_add(channel->napi_dev, &channel->napi_str,
 		       efx_poll, napi_weight);
+	napi_hash_add(&channel->napi_str);
+	efx_channel_init_lock(channel);
 }
 
 static void efx_init_napi(struct efx_nic *efx)
@@ -1972,8 +1981,10 @@ static void efx_init_napi(struct efx_nic
 
 static void efx_fini_napi_channel(struct efx_channel *channel)
 {
-	if (channel->napi_dev)
+	if (channel->napi_dev) {
 		netif_napi_del(&channel->napi_str);
+		napi_hash_del(&channel->napi_str);
+	}
 	channel->napi_dev = NULL;
 }
 
@@ -2008,6 +2019,37 @@ static void efx_netpoll(struct net_devic
 
 #endif
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static int efx_busy_poll(struct napi_struct *napi)
+{
+	struct efx_channel *channel =
+		container_of(napi, struct efx_channel, napi_str);
+	struct efx_nic *efx = channel->efx;
+	int budget = 4;
+	int old_rx_packets, rx_packets;
+
+	if (!netif_running(efx->net_dev))
+		return LL_FLUSH_FAILED;
+
+	if (!efx_channel_lock_poll(channel))
+		return LL_FLUSH_BUSY;
+
+	old_rx_packets = channel->rx_queue.rx_packets;
+	efx_process_channel(channel, budget);
+
+	rx_packets = channel->rx_queue.rx_packets - old_rx_packets;
+
+	/* There is no race condition with NAPI here.
+	 * NAPI will automatically be rescheduled if it yielded during busy
+	 * polling, because it was not able to take the lock and thus returned
+	 * the full budget.
+	 */
+	efx_channel_unlock_poll(channel);
+
+	return rx_packets;
+}
+#endif
+
 /**************************************************************************
  *
  * Kernel net device interface
@@ -2177,6 +2219,9 @@ static const struct net_device_ops efx_f
 	.ndo_poll_controller = efx_netpoll,
 #endif
 	.ndo_setup_tc		= efx_setup_tc,
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= efx_busy_poll,
+#endif
 #ifdef CONFIG_RFS_ACCEL
 	.ndo_rx_flow_steer	= efx_filter_rfs,
 #endif
@@ -2197,6 +2242,9 @@ static const struct net_device_ops efx_e
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= efx_netpoll,
 #endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= efx_busy_poll,
+#endif
 #ifdef CONFIG_RFS_ACCEL
 	.ndo_rx_flow_steer	= efx_filter_rfs,
 #endif
@@ -2594,7 +2642,7 @@ void efx_schedule_reset(struct efx_nic *
  **************************************************************************/
 
 /* PCI device ID table */
-static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
+static const struct pci_device_id efx_pci_table[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
 		    PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
 	 .driver_data = (unsigned long) &falcon_a1_nic_type},
@@ -2607,6 +2655,8 @@ static DEFINE_PCI_DEVICE_TABLE(efx_pci_t
 	 .driver_data = (unsigned long) &siena_a0_nic_type},
 	{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903),  /* SFC9120 PF */
 	 .driver_data = (unsigned long) &efx_hunt_a0_nic_type},
+	{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0923),  /* SFC9140 PF */
+	 .driver_data = (unsigned long) &efx_hunt_a0_nic_type},
 	{0}			/* end of list */
 };
 
@@ -2722,6 +2772,17 @@ static void efx_fini_struct(struct efx_n
 	}
 }
 
+void efx_update_sw_stats(struct efx_nic *efx, u64 *stats)
+{
+	u64 n_rx_nodesc_trunc = 0;
+	struct efx_channel *channel;
+
+	efx_for_each_channel(channel, efx)
+		n_rx_nodesc_trunc += channel->n_rx_nodesc_trunc;
+	stats[GENERIC_STAT_rx_nodesc_trunc] = n_rx_nodesc_trunc;
+	stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops);
+}
+
 /**************************************************************************
  *
  * PCI interface
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/efx.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/efx.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/efx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/efx.h	2014-09-28 17:29:07.000000000 -0400
@@ -194,11 +194,16 @@ int efx_init_irq_moderation(struct efx_n
 			    bool rx_may_override_tx);
 void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
 			    unsigned int *rx_usecs, bool *rx_adaptive);
+void efx_stop_eventq(struct efx_channel *channel);
+void efx_start_eventq(struct efx_channel *channel);
 
 /* Dummy PHY ops for PHY drivers */
 int efx_port_dummy_op_int(struct efx_nic *efx);
 void efx_port_dummy_op_void(struct efx_nic *efx);
 
+/* Update the generic software stats in the passed stats array */
+void efx_update_sw_stats(struct efx_nic *efx, u64 *stats);
+
 /* MTD */
 #ifdef CONFIG_SFC_MTD
 int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,7 +77,6 @@ static const struct efx_sw_stat_desc efx
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
-	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
 };
@@ -360,6 +359,37 @@ static int efx_ethtool_fill_self_tests(s
 	return n;
 }
 
+static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
+{
+	size_t n_stats = 0;
+	struct efx_channel *channel;
+
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_has_tx_queues(channel)) {
+			n_stats++;
+			if (strings != NULL) {
+				snprintf(strings, ETH_GSTRING_LEN,
+					 "tx-%u.tx_packets",
+					 channel->tx_queue[0].queue /
+					 EFX_TXQ_TYPES);
+
+				strings += ETH_GSTRING_LEN;
+			}
+		}
+	}
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_has_rx_queue(channel)) {
+			n_stats++;
+			if (strings != NULL) {
+				snprintf(strings, ETH_GSTRING_LEN,
+					 "rx-%d.rx_packets", channel->channel);
+				strings += ETH_GSTRING_LEN;
+			}
+		}
+	}
+	return n_stats;
+}
+
 static int efx_ethtool_get_sset_count(struct net_device *net_dev,
 				      int string_set)
 {
@@ -368,8 +398,9 @@ static int efx_ethtool_get_sset_count(st
 	switch (string_set) {
 	case ETH_SS_STATS:
 		return efx->type->describe_stats(efx, NULL) +
-			EFX_ETHTOOL_SW_STAT_COUNT +
-			efx_ptp_describe_stats(efx, NULL);
+		       EFX_ETHTOOL_SW_STAT_COUNT +
+		       efx_describe_per_queue_stats(efx, NULL) +
+		       efx_ptp_describe_stats(efx, NULL);
 	case ETH_SS_TEST:
 		return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
 	default:
@@ -391,6 +422,8 @@ static void efx_ethtool_get_strings(stru
 			strlcpy(strings + i * ETH_GSTRING_LEN,
 				efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
 		strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
+		strings += (efx_describe_per_queue_stats(efx, strings) *
+			    ETH_GSTRING_LEN);
 		efx_ptp_describe_stats(efx, strings);
 		break;
 	case ETH_SS_TEST:
@@ -410,6 +443,7 @@ static void efx_ethtool_get_stats(struct
 	const struct efx_sw_stat_desc *stat;
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
+	struct efx_rx_queue *rx_queue;
 	int i;
 
 	spin_lock_bh(&efx->stats_lock);
@@ -445,6 +479,25 @@ static void efx_ethtool_get_stats(struct
 
 	spin_unlock_bh(&efx->stats_lock);
 
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_has_tx_queues(channel)) {
+			*data = 0;
+			efx_for_each_channel_tx_queue(tx_queue, channel) {
+				*data += tx_queue->tx_packets;
+			}
+			data++;
+		}
+	}
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_has_rx_queue(channel)) {
+			*data = 0;
+			efx_for_each_channel_rx_queue(rx_queue, channel) {
+				*data += rx_queue->rx_packets;
+			}
+			data++;
+		}
+	}
+
 	efx_ptp_update_stats(efx, data);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/falcon.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/falcon.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/falcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/falcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,6 +142,8 @@
 	  hw_name ## _ ## offset }
 #define FALCON_OTHER_STAT(ext_name)					\
 	[FALCON_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name)				\
+	[GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
 
 static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
 	FALCON_DMA_STAT(tx_bytes, XgTxOctets),
@@ -191,6 +193,8 @@ static const struct efx_hw_stat_desc fal
 	FALCON_DMA_STAT(rx_length_error, XgRxLengthError),
 	FALCON_DMA_STAT(rx_internal_error, XgRxInternalMACError),
 	FALCON_OTHER_STAT(rx_nodesc_drop_cnt),
+	GENERIC_SW_STAT(rx_nodesc_trunc),
+	GENERIC_SW_STAT(rx_noskb_drops),
 };
 static const unsigned long falcon_stat_mask[] = {
 	[0 ... BITS_TO_LONGS(FALCON_STAT_COUNT) - 1] = ~0UL,
@@ -2574,6 +2578,7 @@ static size_t falcon_update_nic_stats(st
 				     stats[FALCON_STAT_rx_bytes] -
 				     stats[FALCON_STAT_rx_good_bytes] -
 				     stats[FALCON_STAT_rx_control] * 64);
+		efx_update_sw_stats(efx, stats);
 	}
 
 	if (full_stats)
@@ -2584,7 +2589,9 @@ static size_t falcon_update_nic_stats(st
 		core_stats->tx_packets = stats[FALCON_STAT_tx_packets];
 		core_stats->rx_bytes = stats[FALCON_STAT_rx_bytes];
 		core_stats->tx_bytes = stats[FALCON_STAT_tx_bytes];
-		core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt];
+		core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt] +
+					 stats[GENERIC_STAT_rx_nodesc_trunc] +
+					 stats[GENERIC_STAT_rx_noskb_drops];
 		core_stats->multicast = stats[FALCON_STAT_rx_multicast];
 		core_stats->rx_length_errors =
 			stats[FALCON_STAT_rx_gtjumbo] +
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/farch.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/farch.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/farch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/farch.c	2014-09-28 17:29:07.000000000 -0400
@@ -2933,6 +2933,9 @@ void efx_farch_filter_sync_rx_mode(struc
 	u32 crc;
 	int bit;
 
+	if (!efx_dev_registered(efx))
+		return;
+
 	netif_addr_lock_bh(net_dev);
 
 	efx->unicast_filter = !(net_dev->flags & IFF_PROMISC);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/mcdi_port.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/mcdi_port.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/mcdi_port.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/mcdi_port.c	2014-09-28 17:29:07.000000000 -0400
@@ -183,6 +183,8 @@ static u32 mcdi_to_ethtool_cap(u32 media
 			result |= SUPPORTED_1000baseKX_Full;
 		if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
 			result |= SUPPORTED_10000baseKX4_Full;
+		if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
+			result |= SUPPORTED_40000baseKR4_Full;
 		break;
 
 	case MC_CMD_MEDIA_XFP:
@@ -190,6 +192,12 @@ static u32 mcdi_to_ethtool_cap(u32 media
 		result |= SUPPORTED_FIBRE;
 		break;
 
+	case MC_CMD_MEDIA_QSFP_PLUS:
+		result |= SUPPORTED_FIBRE;
+		if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
+			result |= SUPPORTED_40000baseCR4_Full;
+		break;
+
 	case MC_CMD_MEDIA_BASE_T:
 		result |= SUPPORTED_TP;
 		if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
@@ -237,6 +245,8 @@ static u32 ethtool_to_mcdi_cap(u32 cap)
 		result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
 	if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full))
 		result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
+	if (cap & (SUPPORTED_40000baseCR4_Full | SUPPORTED_40000baseKR4_Full))
+		result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN);
 	if (cap & SUPPORTED_Pause)
 		result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
 	if (cap & SUPPORTED_Asym_Pause)
@@ -285,6 +295,7 @@ static u32 mcdi_to_ethtool_media(u32 med
 
 	case MC_CMD_MEDIA_XFP:
 	case MC_CMD_MEDIA_SFP_PLUS:
+	case MC_CMD_MEDIA_QSFP_PLUS:
 		return PORT_FIBRE;
 
 	case MC_CMD_MEDIA_BASE_T:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/net_driver.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/net_driver.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/net_driver.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/net_driver.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/vmalloc.h>
 #include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
+#include <net/busy_poll.h>
 
 #include "enum.h"
 #include "bitfield.h"
@@ -249,6 +250,8 @@ struct efx_tx_queue {
 	unsigned int tso_packets;
 	unsigned int pushes;
 	unsigned int pio_packets;
+	/* Statistics to supplement MAC stats */
+	unsigned long tx_packets;
 
 	/* Members shared between paths and sometimes updated */
 	unsigned int empty_read_count ____cacheline_aligned_in_smp;
@@ -358,6 +361,8 @@ struct efx_rx_queue {
 	unsigned int recycle_count;
 	struct timer_list slow_fill;
 	unsigned int slow_fill_count;
+	/* Statistics to supplement MAC stats */
+	unsigned long rx_packets;
 };
 
 enum efx_sync_events_state {
@@ -383,6 +388,8 @@ enum efx_sync_events_state {
  * @irq_moderation: IRQ moderation value (in hardware ticks)
  * @napi_dev: Net device used with NAPI
  * @napi_str: NAPI control structure
+ * @state: state for NAPI vs busy polling
+ * @state_lock: lock protecting @state
  * @eventq: Event queue buffer
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
@@ -420,6 +427,22 @@ struct efx_channel {
 	unsigned int irq_moderation;
 	struct net_device *napi_dev;
 	struct napi_struct napi_str;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	unsigned int state;
+	spinlock_t state_lock;
+#define EFX_CHANNEL_STATE_IDLE		0
+#define EFX_CHANNEL_STATE_NAPI		(1 << 0)  /* NAPI owns this channel */
+#define EFX_CHANNEL_STATE_POLL		(1 << 1)  /* poll owns this channel */
+#define EFX_CHANNEL_STATE_DISABLED	(1 << 2)  /* channel is disabled */
+#define EFX_CHANNEL_STATE_NAPI_YIELD	(1 << 3)  /* NAPI yielded this channel */
+#define EFX_CHANNEL_STATE_POLL_YIELD	(1 << 4)  /* poll yielded this channel */
+#define EFX_CHANNEL_OWNED \
+	(EFX_CHANNEL_STATE_NAPI | EFX_CHANNEL_STATE_POLL)
+#define EFX_CHANNEL_LOCKED \
+	(EFX_CHANNEL_OWNED | EFX_CHANNEL_STATE_DISABLED)
+#define EFX_CHANNEL_USER_PEND \
+	(EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_POLL_YIELD)
+#endif /* CONFIG_NET_RX_BUSY_POLL */
 	struct efx_special_buffer eventq;
 	unsigned int eventq_mask;
 	unsigned int eventq_read_ptr;
@@ -453,6 +476,135 @@ struct efx_channel {
 	u32 sync_timestamp_minor;
 };
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void efx_channel_init_lock(struct efx_channel *channel)
+{
+	spin_lock_init(&channel->state_lock);
+}
+
+/* Called from the device poll routine to get ownership of a channel. */
+static inline bool efx_channel_lock_napi(struct efx_channel *channel)
+{
+	bool rc = true;
+
+	spin_lock_bh(&channel->state_lock);
+	if (channel->state & EFX_CHANNEL_LOCKED) {
+		WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
+		channel->state |= EFX_CHANNEL_STATE_NAPI_YIELD;
+		rc = false;
+	} else {
+		/* we don't care if someone yielded */
+		channel->state = EFX_CHANNEL_STATE_NAPI;
+	}
+	spin_unlock_bh(&channel->state_lock);
+	return rc;
+}
+
+static inline void efx_channel_unlock_napi(struct efx_channel *channel)
+{
+	spin_lock_bh(&channel->state_lock);
+	WARN_ON(channel->state &
+		(EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_YIELD));
+
+	channel->state &= EFX_CHANNEL_STATE_DISABLED;
+	spin_unlock_bh(&channel->state_lock);
+}
+
+/* Called from efx_busy_poll(). */
+static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+{
+	bool rc = true;
+
+	spin_lock_bh(&channel->state_lock);
+	if ((channel->state & EFX_CHANNEL_LOCKED)) {
+		channel->state |= EFX_CHANNEL_STATE_POLL_YIELD;
+		rc = false;
+	} else {
+		/* preserve yield marks */
+		channel->state |= EFX_CHANNEL_STATE_POLL;
+	}
+	spin_unlock_bh(&channel->state_lock);
+	return rc;
+}
+
+/* Returns true if NAPI tried to get the channel while it was locked. */
+static inline void efx_channel_unlock_poll(struct efx_channel *channel)
+{
+	spin_lock_bh(&channel->state_lock);
+	WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
+
+	/* will reset state to idle, unless channel is disabled */
+	channel->state &= EFX_CHANNEL_STATE_DISABLED;
+	spin_unlock_bh(&channel->state_lock);
+}
+
+/* True if a socket is polling, even if it did not get the lock. */
+static inline bool efx_channel_busy_polling(struct efx_channel *channel)
+{
+	WARN_ON(!(channel->state & EFX_CHANNEL_OWNED));
+	return channel->state & EFX_CHANNEL_USER_PEND;
+}
+
+static inline void efx_channel_enable(struct efx_channel *channel)
+{
+	spin_lock_bh(&channel->state_lock);
+	channel->state = EFX_CHANNEL_STATE_IDLE;
+	spin_unlock_bh(&channel->state_lock);
+}
+
+/* False if the channel is currently owned. */
+static inline bool efx_channel_disable(struct efx_channel *channel)
+{
+	bool rc = true;
+
+	spin_lock_bh(&channel->state_lock);
+	if (channel->state & EFX_CHANNEL_OWNED)
+		rc = false;
+	channel->state |= EFX_CHANNEL_STATE_DISABLED;
+	spin_unlock_bh(&channel->state_lock);
+
+	return rc;
+}
+
+#else /* CONFIG_NET_RX_BUSY_POLL */
+
+static inline void efx_channel_init_lock(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_lock_napi(struct efx_channel *channel)
+{
+	return true;
+}
+
+static inline void efx_channel_unlock_napi(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+{
+	return false;
+}
+
+static inline void efx_channel_unlock_poll(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_busy_polling(struct efx_channel *channel)
+{
+	return false;
+}
+
+static inline void efx_channel_enable(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_disable(struct efx_channel *channel)
+{
+	return true;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 /**
  * struct efx_msi_context - Context for each MSI
  * @efx: The associated NIC
@@ -777,6 +929,7 @@ struct vfdi_status;
  *	interrupt has occurred.
  * @stats_lock: Statistics update lock. Must be held when calling
  *	efx_nic_type::{update,start,stop}_stats.
+ * @n_rx_noskb_drops: Count of RX packets dropped due to failure to allocate an skb
  *
  * This is stored in the private area of the &struct net_device.
  */
@@ -930,6 +1083,7 @@ struct efx_nic {
 	spinlock_t biu_lock;
 	int last_irq_cpu;
 	spinlock_t stats_lock;
+	atomic_t n_rx_noskb_drops;
 };
 
 static inline int efx_dev_registered(struct efx_nic *efx)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/nic.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/nic.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/nic.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/nic.h	2014-09-28 17:29:07.000000000 -0400
@@ -135,6 +135,13 @@ enum {
 /* Size and alignment of buffer table entries (same) */
 #define EFX_BUF_SIZE	EFX_PAGE_SIZE
 
+/* NIC-generic software stats */
+enum {
+	GENERIC_STAT_rx_noskb_drops,
+	GENERIC_STAT_rx_nodesc_trunc,
+	GENERIC_STAT_COUNT
+};
+
 /**
  * struct falcon_board_type - board operations and type information
  * @id: Board type id, as found in NVRAM
@@ -205,7 +212,7 @@ static inline bool falcon_spi_present(co
 }
 
 enum {
-	FALCON_STAT_tx_bytes,
+	FALCON_STAT_tx_bytes = GENERIC_STAT_COUNT,
 	FALCON_STAT_tx_packets,
 	FALCON_STAT_tx_pause,
 	FALCON_STAT_tx_control,
@@ -290,7 +297,7 @@ static inline struct falcon_board *falco
 }
 
 enum {
-	SIENA_STAT_tx_bytes,
+	SIENA_STAT_tx_bytes = GENERIC_STAT_COUNT,
 	SIENA_STAT_tx_good_bytes,
 	SIENA_STAT_tx_bad_bytes,
 	SIENA_STAT_tx_packets,
@@ -361,7 +368,7 @@ struct siena_nic_data {
 };
 
 enum {
-	EF10_STAT_tx_bytes,
+	EF10_STAT_tx_bytes = GENERIC_STAT_COUNT,
 	EF10_STAT_tx_packets,
 	EF10_STAT_tx_pause,
 	EF10_STAT_tx_control,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/rx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/rx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -462,6 +462,7 @@ efx_rx_packet_gro(struct efx_channel *ch
 
 	skb_record_rx_queue(skb, channel->rx_queue.core_index);
 
+	skb_mark_napi_id(skb, &channel->napi_str);
 	gro_result = napi_gro_frags(napi);
 	if (gro_result != GRO_DROP)
 		channel->irq_mod_score += 2;
@@ -480,8 +481,10 @@ static struct sk_buff *efx_rx_mk_skb(str
 	skb = netdev_alloc_skb(efx->net_dev,
 			       efx->rx_ip_align + efx->rx_prefix_size +
 			       hdr_len);
-	if (unlikely(skb == NULL))
+	if (unlikely(skb == NULL)) {
+		atomic_inc(&efx->n_rx_noskb_drops);
 		return NULL;
+	}
 
 	EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
 
@@ -518,6 +521,8 @@ static struct sk_buff *efx_rx_mk_skb(str
 	/* Move past the ethernet header */
 	skb->protocol = eth_type_trans(skb, efx->net_dev);
 
+	skb_mark_napi_id(skb, &channel->napi_str);
+
 	return skb;
 }
 
@@ -528,6 +533,8 @@ void efx_rx_packet(struct efx_rx_queue *
 	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	struct efx_rx_buffer *rx_buf;
 
+	rx_queue->rx_packets++;
+
 	rx_buf = efx_rx_buffer(rx_queue, index);
 	rx_buf->flags |= flags;
 
@@ -662,7 +669,8 @@ void __efx_rx_packet(struct efx_channel
 	if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
 		rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
 
-	if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb)
+	if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb &&
+	    !efx_channel_busy_polling(channel))
 		efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh);
 	else
 		efx_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/selftest.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/selftest.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/selftest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/selftest.c	2014-09-28 17:29:07.000000000 -0400
@@ -188,7 +188,7 @@ static int efx_test_eventq_irq(struct ef
 		schedule_timeout_uninterruptible(wait);
 
 		efx_for_each_channel(channel, efx) {
-			napi_disable(&channel->napi_str);
+			efx_stop_eventq(channel);
 			if (channel->eventq_read_ptr !=
 			    read_ptr[channel->channel]) {
 				set_bit(channel->channel, &napi_ran);
@@ -200,8 +200,7 @@ static int efx_test_eventq_irq(struct ef
 				if (efx_nic_event_test_irq_cpu(channel) >= 0)
 					clear_bit(channel->channel, &int_pend);
 			}
-			napi_enable(&channel->napi_str);
-			efx_nic_eventq_read_ack(channel);
+			efx_start_eventq(channel);
 		}
 
 		wait *= 2;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/siena.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/siena.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/siena.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/siena.c	2014-09-28 17:29:07.000000000 -0400
@@ -424,6 +424,8 @@ static void siena_remove_nic(struct efx_
 	{ #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
 #define SIENA_OTHER_STAT(ext_name)				\
 	[SIENA_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name)				\
+	[GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
 
 static const struct efx_hw_stat_desc siena_stat_desc[SIENA_STAT_COUNT] = {
 	SIENA_DMA_STAT(tx_bytes, TX_BYTES),
@@ -483,6 +485,8 @@ static const struct efx_hw_stat_desc sie
 	SIENA_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
 	SIENA_DMA_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS),
 	SIENA_DMA_STAT(rx_nodesc_drop_cnt, RX_NODESC_DROPS),
+	GENERIC_SW_STAT(rx_nodesc_trunc),
+	GENERIC_SW_STAT(rx_noskb_drops),
 };
 static const unsigned long siena_stat_mask[] = {
 	[0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL,
@@ -528,6 +532,7 @@ static int siena_try_update_nic_stats(st
 	efx_update_diff_stat(&stats[SIENA_STAT_rx_good_bytes],
 			     stats[SIENA_STAT_rx_bytes] -
 			     stats[SIENA_STAT_rx_bad_bytes]);
+	efx_update_sw_stats(efx, stats);
 	return 0;
 }
 
@@ -554,7 +559,9 @@ static size_t siena_update_nic_stats(str
 		core_stats->tx_packets = stats[SIENA_STAT_tx_packets];
 		core_stats->rx_bytes = stats[SIENA_STAT_rx_bytes];
 		core_stats->tx_bytes = stats[SIENA_STAT_tx_bytes];
-		core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt];
+		core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt] +
+					 stats[GENERIC_STAT_rx_nodesc_trunc] +
+					 stats[GENERIC_STAT_rx_noskb_drops];
 		core_stats->multicast = stats[SIENA_STAT_rx_multicast];
 		core_stats->collisions = stats[SIENA_STAT_tx_collision];
 		core_stats->rx_length_errors =
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sfc/tx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/tx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sfc/tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sfc/tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -189,18 +189,6 @@ struct efx_short_copy_buffer {
 	u8 buf[L1_CACHE_BYTES];
 };
 
-/* Copy in explicit 64-bit writes. */
-static void efx_memcpy_64(void __iomem *dest, void *src, size_t len)
-{
-	u64 *src64 = src;
-	u64 __iomem *dest64 = dest;
-	size_t l64 = len / 8;
-	size_t i;
-
-	for (i = 0; i < l64; i++)
-		writeq(src64[i], &dest64[i]);
-}
-
 /* Copy to PIO, respecting that writes to PIO buffers must be dword aligned.
  * Advances piobuf pointer. Leaves additional data in the copy buffer.
  */
@@ -210,7 +198,7 @@ static void efx_memcpy_toio_aligned(stru
 {
 	int block_len = len & ~(sizeof(copy_buf->buf) - 1);
 
-	efx_memcpy_64(*piobuf, data, block_len);
+	__iowrite64_copy(*piobuf, data, block_len >> 3);
 	*piobuf += block_len;
 	len -= block_len;
 
@@ -242,7 +230,8 @@ static void efx_memcpy_toio_aligned_cb(s
 		if (copy_buf->used < sizeof(copy_buf->buf))
 			return;
 
-		efx_memcpy_64(*piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+		__iowrite64_copy(*piobuf, copy_buf->buf,
+				 sizeof(copy_buf->buf) >> 3);
 		*piobuf += sizeof(copy_buf->buf);
 		data += copy_to_buf;
 		len -= copy_to_buf;
@@ -257,7 +246,8 @@ static void efx_flush_copy_buffer(struct
 {
 	/* if there's anything in it, write the whole buffer, including junk */
 	if (copy_buf->used)
-		efx_memcpy_64(piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+		__iowrite64_copy(piobuf, copy_buf->buf,
+				 sizeof(copy_buf->buf) >> 3);
 }
 
 /* Traverse skb structure and copy fragments in to PIO buffer.
@@ -316,8 +306,8 @@ efx_enqueue_skb_pio(struct efx_tx_queue
 		 */
 		BUILD_BUG_ON(L1_CACHE_BYTES >
 			     SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
-		efx_memcpy_64(tx_queue->piobuf, skb->data,
-			      ALIGN(skb->len, L1_CACHE_BYTES));
+		__iowrite64_copy(tx_queue->piobuf, skb->data,
+				 ALIGN(skb->len, L1_CACHE_BYTES) >> 3);
 	}
 
 	EFX_POPULATE_QWORD_5(buffer->option,
@@ -452,6 +442,8 @@ finish_packet:
 	/* Pass off to hardware */
 	efx_nic_push_buffers(tx_queue);
 
+	tx_queue->tx_packets++;
+
 	efx_tx_maybe_stop_queue(tx_queue);
 
 	return NETDEV_TX_OK;
@@ -1245,6 +1237,8 @@ static int tso_start_new_packet(struct e
 
 	++tx_queue->tso_packets;
 
+	++tx_queue->tx_packets;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sgi/ioc3-eth.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sgi/ioc3-eth.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sgi/ioc3-eth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sgi/ioc3-eth.c	2014-09-28 17:29:07.000000000 -0400
@@ -1384,7 +1384,7 @@ static void ioc3_remove_one(struct pci_d
 	 */
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ioc3_pci_tbl) = {
+static const struct pci_device_id ioc3_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0 }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/silan/sc92031.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/silan/sc92031.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/silan/sc92031.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/silan/sc92031.c	2014-09-28 17:29:07.000000000 -0400
@@ -1561,7 +1561,7 @@ out:
 	return 0;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(sc92031_pci_device_id_table) = {
+static const struct pci_device_id sc92031_pci_device_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
 	{ PCI_DEVICE(0x1088, 0x2031) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sis/sis190.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sis/sis190.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sis/sis190.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sis/sis190.c	2014-09-28 17:29:07.000000000 -0400
@@ -330,7 +330,7 @@ static const struct {
 	{ "SiS 191 PCI Gigabit Ethernet adapter" },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(sis190_pci_tbl) = {
+static const struct pci_device_id sis190_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
 	{ 0, },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sis/sis900.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sis/sis900.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sis/sis900.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sis/sis900.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,7 +106,8 @@ static const char * card_names[] = {
 	"SiS 900 PCI Fast Ethernet",
 	"SiS 7016 PCI Fast Ethernet"
 };
-static DEFINE_PCI_DEVICE_TABLE(sis900_pci_tbl) = {
+
+static const struct pci_device_id sis900_pci_tbl[] = {
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900},
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016,
@@ -2258,7 +2259,6 @@ static int sis900_set_config(struct net_
 		case IF_PORT_100BASEFX: /* 100BaseFx */
                 	/* These Modes are not supported (are they?)*/
 			return -EOPNOTSUPP;
-			break;
 
 		default:
 			return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/smsc/epic100.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/epic100.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/smsc/epic100.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/epic100.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,7 +173,7 @@ static const struct epic_chip_info pci_i
 };
 
 
-static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = {
+static const struct pci_device_id epic_pci_tbl[] = {
 	{ 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 },
 	{ 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 },
 	{ 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smc911x.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smc911x.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smc911x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smc911x.c	2014-09-28 17:29:07.000000000 -0400
@@ -730,7 +730,7 @@ static void smc911x_phy_detect(struct ne
 			lp->phy_type = id1 << 16 | id2;
 	}
 
-	DBG(SMC_DEBUG_MISC, dev, "phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n",
+	DBG(SMC_DEBUG_MISC, dev, "phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%x\n",
 	    id1, id2, lp->mii.phy_id);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smsc911x.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smsc911x.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smsc911x.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smsc911x.h	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@
 
 #ifdef CONFIG_DEBUG_SPINLOCK
 #define SMSC_ASSERT_MAC_LOCK(pdata) \
-		WARN_ON(!spin_is_locked(&pdata->mac_lock))
+		WARN_ON_SMP(!spin_is_locked(&pdata->mac_lock))
 #else
 #define SMSC_ASSERT_MAC_LOCK(pdata) do {} while (0)
 #endif				/* CONFIG_DEBUG_SPINLOCK */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smsc9420.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smsc9420.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/smsc/smsc9420.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/smsc/smsc9420.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,7 +83,7 @@ struct smsc9420_pdata {
 	int last_carrier;
 };
 
-static DEFINE_PCI_DEVICE_TABLE(smsc9420_id_table) = {
+static const struct pci_device_id smsc9420_id_table[] = {
 	{ PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/chain_mode.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/chain_mode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/chain_mode.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 
 #include "stmmac.h"
 
-static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
 	struct stmmac_priv *priv = (struct stmmac_priv *)p;
 	unsigned int txsize = priv->dma_tx_size;
@@ -47,7 +47,9 @@ static unsigned int stmmac_jumbo_frm(voi
 
 	desc->des2 = dma_map_single(priv->device, skb->data,
 				    bmax, DMA_TO_DEVICE);
-	priv->tx_skbuff_dma[entry] = desc->des2;
+	if (dma_mapping_error(priv->device, desc->des2))
+		return -1;
+	priv->tx_skbuff_dma[entry].buf = desc->des2;
 	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
 
 	while (len != 0) {
@@ -59,7 +61,9 @@ static unsigned int stmmac_jumbo_frm(voi
 			desc->des2 = dma_map_single(priv->device,
 						    (skb->data + bmax * i),
 						    bmax, DMA_TO_DEVICE);
-			priv->tx_skbuff_dma[entry] = desc->des2;
+			if (dma_mapping_error(priv->device, desc->des2))
+				return -1;
+			priv->tx_skbuff_dma[entry].buf = desc->des2;
 			priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
 							STMMAC_CHAIN_MODE);
 			priv->hw->desc->set_tx_owner(desc);
@@ -69,7 +73,9 @@ static unsigned int stmmac_jumbo_frm(voi
 			desc->des2 = dma_map_single(priv->device,
 						    (skb->data + bmax * i), len,
 						    DMA_TO_DEVICE);
-			priv->tx_skbuff_dma[entry] = desc->des2;
+			if (dma_mapping_error(priv->device, desc->des2))
+				return -1;
+			priv->tx_skbuff_dma[entry].buf = desc->des2;
 			priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
 							STMMAC_CHAIN_MODE);
 			priv->hw->desc->set_tx_owner(desc);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/common.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/common.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -220,10 +220,10 @@ enum dma_irq_status {
 	handle_tx = 0x8,
 };
 
-#define	CORE_IRQ_TX_PATH_IN_LPI_MODE	(1 << 1)
-#define	CORE_IRQ_TX_PATH_EXIT_LPI_MODE	(1 << 2)
-#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 3)
-#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 4)
+#define	CORE_IRQ_TX_PATH_IN_LPI_MODE	(1 << 0)
+#define	CORE_IRQ_TX_PATH_EXIT_LPI_MODE	(1 << 1)
+#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 2)
+#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 3)
 
 #define	CORE_PCS_ANE_COMPLETE		(1 << 5)
 #define	CORE_PCS_LINK_STATUS		(1 << 6)
@@ -287,7 +287,7 @@ struct dma_features {
 
 /* Default LPI timers */
 #define STMMAC_DEFAULT_LIT_LS	0x3E8
-#define STMMAC_DEFAULT_TWT_LS	0x0
+#define STMMAC_DEFAULT_TWT_LS	0x1E
 
 #define STMMAC_CHAIN_MODE	0x1
 #define STMMAC_RING_MODE	0x2
@@ -368,34 +368,36 @@ struct stmmac_dma_ops {
 	void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
 };
 
+struct mac_device_info;
+
 struct stmmac_ops {
 	/* MAC core initialization */
-	void (*core_init) (void __iomem *ioaddr, int mtu);
+	void (*core_init)(struct mac_device_info *hw, int mtu);
 	/* Enable and verify that the IPC module is supported */
-	int (*rx_ipc) (void __iomem *ioaddr);
+	int (*rx_ipc)(struct mac_device_info *hw);
 	/* Dump MAC registers */
-	void (*dump_regs) (void __iomem *ioaddr);
+	void (*dump_regs)(struct mac_device_info *hw);
 	/* Handle extra events on specific interrupts hw dependent */
-	int (*host_irq_status) (void __iomem *ioaddr,
-				struct stmmac_extra_stats *x);
+	int (*host_irq_status)(struct mac_device_info *hw,
+			       struct stmmac_extra_stats *x);
 	/* Multicast filter setting */
-	void (*set_filter) (struct net_device *dev, int id);
+	void (*set_filter)(struct mac_device_info *hw, struct net_device *dev);
 	/* Flow control setting */
-	void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
-			   unsigned int fc, unsigned int pause_time);
+	void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex,
+			  unsigned int fc, unsigned int pause_time);
 	/* Set power management mode (e.g. magic frame) */
-	void (*pmt) (void __iomem *ioaddr, unsigned long mode);
+	void (*pmt)(struct mac_device_info *hw, unsigned long mode);
 	/* Set/Get Unicast MAC addresses */
-	void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
-			       unsigned int reg_n);
-	void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
-			       unsigned int reg_n);
-	void (*set_eee_mode) (void __iomem *ioaddr);
-	void (*reset_eee_mode) (void __iomem *ioaddr);
-	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
-	void (*set_eee_pls) (void __iomem *ioaddr, int link);
-	void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
-	void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
+	void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+			      unsigned int reg_n);
+	void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+			      unsigned int reg_n);
+	void (*set_eee_mode)(struct mac_device_info *hw);
+	void (*reset_eee_mode)(struct mac_device_info *hw);
+	void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
+	void (*set_eee_pls)(struct mac_device_info *hw, int link);
+	void (*ctrl_ane)(struct mac_device_info *hw, bool restart);
+	void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
 };
 
 struct stmmac_hwtimestamp {
@@ -423,7 +425,7 @@ struct stmmac_mode_ops {
 	void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
 		      unsigned int extend_desc);
 	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
-	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+	int (*jumbo_frm)(void *priv, struct sk_buff *skb, int csum);
 	int (*set_16kib_bfsize)(int mtu);
 	void (*init_desc3)(struct dma_desc *p);
 	void (*refill_desc3) (void *priv, struct dma_desc *p);
@@ -439,9 +441,15 @@ struct mac_device_info {
 	struct mii_regs mii;	/* MII register Addresses */
 	struct mac_link link;
 	unsigned int synopsys_uid;
+	void __iomem *pcsr;     /* vpointer to device CSRs */
+	int multicast_filter_bins;
+	int unicast_filter_entries;
+	int mcast_bits_log2;
+	unsigned int rx_csum;
 };
 
-struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+					int perfect_uc_entries);
 struct mac_device_info *dwmac100_setup(void __iomem *ioaddr);
 
 void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,8 +32,9 @@
 #include <asm/io.h>
 #include "dwmac1000.h"
 
-static void dwmac1000_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONTROL);
 	value |= GMAC_CORE_INIT;
 	if (mtu > 1500)
@@ -52,11 +53,16 @@ static void dwmac1000_core_init(void __i
 #endif
 }
 
-static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONTROL);
 
-	value |= GMAC_CONTROL_IPC;
+	if (hw->rx_csum)
+		value |= GMAC_CONTROL_IPC;
+	else
+		value &= ~GMAC_CONTROL_IPC;
+
 	writel(value, ioaddr + GMAC_CONTROL);
 
 	value = readl(ioaddr + GMAC_CONTROL);
@@ -64,8 +70,9 @@ static int dwmac1000_rx_ipc_enable(void
 	return !!(value & GMAC_CONTROL_IPC);
 }
 
-static void dwmac1000_dump_regs(void __iomem *ioaddr)
+static void dwmac1000_dump_regs(struct mac_device_info *hw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	int i;
 	pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
 
@@ -76,69 +83,98 @@ static void dwmac1000_dump_regs(void __i
 	}
 }
 
-static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
+				    unsigned char *addr,
 				    unsigned int reg_n)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
 			    GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
+				    unsigned char *addr,
 				    unsigned int reg_n)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
 			    GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_set_filter(struct net_device *dev, int id)
+static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
+				 int mcbitslog2)
+{
+	int numhashregs, regs;
+
+	switch (mcbitslog2) {
+	case 6:
+		writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW);
+		writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH);
+		return;
+		break;
+	case 7:
+		numhashregs = 4;
+		break;
+	case 8:
+		numhashregs = 8;
+		break;
+	default:
+		pr_debug("STMMAC: err in setting mulitcast filter\n");
+		return;
+		break;
+	}
+	for (regs = 0; regs < numhashregs; regs++)
+		writel(mcfilterbits[regs],
+		       ioaddr + GMAC_EXTHASH_BASE + regs * 4);
+}
+
+static void dwmac1000_set_filter(struct mac_device_info *hw,
+				 struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
 	unsigned int value = 0;
-	unsigned int perfect_addr_number;
+	unsigned int perfect_addr_number = hw->unicast_filter_entries;
+	u32 mc_filter[2];
+	int mcbitslog2 = hw->mcast_bits_log2;
 
 	pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
 		 netdev_mc_count(dev), netdev_uc_count(dev));
 
-	if (dev->flags & IFF_PROMISC)
+	memset(mc_filter, 0, sizeof(mc_filter));
+
+	if (dev->flags & IFF_PROMISC) {
 		value = GMAC_FRAME_FILTER_PR;
-	else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
-		 || (dev->flags & IFF_ALLMULTI)) {
+	} else if (dev->flags & IFF_ALLMULTI) {
 		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
-		writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
-		writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
 	} else if (!netdev_mc_empty(dev)) {
-		u32 mc_filter[2];
 		struct netdev_hw_addr *ha;
 
 		/* Hash filter for multicast */
 		value = GMAC_FRAME_FILTER_HMC;
 
-		memset(mc_filter, 0, sizeof(mc_filter));
 		netdev_for_each_mc_addr(ha, dev) {
-			/* The upper 6 bits of the calculated CRC are used to
-			 * index the contens of the hash table
+			/* The upper n bits of the calculated CRC are used to
+			 * index the contents of the hash table. The number of
+			 * bits used depends on the hardware configuration
+			 * selected at core configuration time.
 			 */
-			int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
+			int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
+					      ETH_ALEN)) >>
+					      (32 - mcbitslog2);
 			/* The most significant bit determines the register to
 			 * use (H/L) while the other 5 bits determine the bit
 			 * within the register.
 			 */
 			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 		}
-		writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
-		writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
 	}
 
-	/* Extra 16 regs are available in cores newer than the 3.40. */
-	if (id > DWMAC_CORE_3_40)
-		perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
-	else
-		perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2;
+	dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
 
 	/* Handle multiple unicast addresses (perfect filtering) */
 	if (netdev_uc_count(dev) > perfect_addr_number)
-		/* Switch to promiscuous mode if more than 16 addrs
-		 * are required
+		/* Switch to promiscuous mode if more than unicast
+		 * addresses are requested than supported by hardware.
 		 */
 		value |= GMAC_FRAME_FILTER_PR;
 	else {
@@ -146,7 +182,9 @@ static void dwmac1000_set_filter(struct
 		struct netdev_hw_addr *ha;
 
 		netdev_for_each_uc_addr(ha, dev) {
-			dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
+			stmmac_get_mac_addr(ioaddr, ha->addr,
+					    GMAC_ADDR_HIGH(reg),
+					    GMAC_ADDR_LOW(reg));
 			reg++;
 		}
 	}
@@ -156,15 +194,13 @@ static void dwmac1000_set_filter(struct
 	value |= GMAC_FRAME_FILTER_RA;
 #endif
 	writel(value, ioaddr + GMAC_FRAME_FILTER);
-
-	pr_debug("\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n",
-		 readl(ioaddr + GMAC_FRAME_FILTER),
-		 readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
 }
 
-static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+
+static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
 				unsigned int fc, unsigned int pause_time)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	unsigned int flow = 0;
 
 	pr_debug("GMAC Flow-Control:\n");
@@ -185,8 +221,9 @@ static void dwmac1000_flow_ctrl(void __i
 	writel(flow, ioaddr + GMAC_FLOW_CTRL);
 }
 
-static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	unsigned int pmt = 0;
 
 	if (mode & WAKE_MAGIC) {
@@ -201,9 +238,10 @@ static void dwmac1000_pmt(void __iomem *
 	writel(pmt, ioaddr + GMAC_PMT);
 }
 
-static int dwmac1000_irq_status(void __iomem *ioaddr,
+static int dwmac1000_irq_status(struct mac_device_info *hw,
 				struct stmmac_extra_stats *x)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
 	int ret = 0;
 
@@ -268,8 +306,9 @@ static int dwmac1000_irq_status(void __i
 	return ret;
 }
 
-static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value;
 
 	/* Enable the link status receive on RGMII, SGMII ore SMII
@@ -281,8 +320,9 @@ static void dwmac1000_set_eee_mode(void
 	writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value;
 
 	value = readl(ioaddr + LPI_CTRL_STATUS);
@@ -290,8 +330,9 @@ static void dwmac1000_reset_eee_mode(voi
 	writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value;
 
 	value = readl(ioaddr + LPI_CTRL_STATUS);
@@ -304,8 +345,9 @@ static void dwmac1000_set_eee_pls(void _
 	writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
 
 	/* Program the timers in the LPI timer control register:
@@ -318,8 +360,9 @@ static void dwmac1000_set_eee_timer(void
 	writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
-static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
+static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	/* auto negotiation enable and External Loopback enable */
 	u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
 
@@ -329,8 +372,9 @@ static void dwmac1000_ctrl_ane(void __io
 	writel(value, ioaddr + GMAC_AN_CTRL);
 }
 
-static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
+static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_ANE_ADV);
 
 	if (value & GMAC_ANE_FD)
@@ -368,7 +412,8 @@ static const struct stmmac_ops dwmac1000
 	.get_adv = dwmac1000_get_adv,
 };
 
-struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+					int perfect_uc_entries)
 {
 	struct mac_device_info *mac;
 	u32 hwid = readl(ioaddr + GMAC_VERSION);
@@ -377,6 +422,14 @@ struct mac_device_info *dwmac1000_setup(
 	if (!mac)
 		return NULL;
 
+	mac->pcsr = ioaddr;
+	mac->multicast_filter_bins = mcbins;
+	mac->unicast_filter_entries = perfect_uc_entries;
+	mac->mcast_bits_log2 = 0;
+
+	if (mac->multicast_filter_bins)
+		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
 	mac->mac = &dwmac1000_ops;
 	mac->dma = &dwmac1000_dma_ops;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h	2014-09-28 17:29:07.000000000 -0400
@@ -87,7 +87,7 @@ enum power_event {
 				(reg * 8))
 #define GMAC_ADDR_LOW(reg)	(((reg > 15) ? 0x00000804 : 0x00000044) + \
 				(reg * 8))
-#define GMAC_MAX_PERFECT_ADDRESSES	32
+#define GMAC_MAX_PERFECT_ADDRESSES	1
 
 /* PCS registers (AN/TBI/SGMII/RGMII) offset */
 #define GMAC_AN_CTRL	0x000000c0	/* AN control */
@@ -153,7 +153,7 @@ enum inter_frame_gap {
 #define GMAC_CONTROL_RE		0x00000004	/* Receiver Enable */
 
 #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
-			GMAC_CONTROL_BE)
+			GMAC_CONTROL_BE | GMAC_CONTROL_DCRS)
 
 /* GMAC Frame Filter defines */
 #define GMAC_FRAME_FILTER_PR	0x00000001	/* Promiscuous Mode */
@@ -261,6 +261,7 @@ enum rtc_control {
 #define GMAC_MMC_RX_INTR   0x104
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
+#define GMAC_EXTHASH_BASE  0x500
 
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,8 +32,9 @@
 #include <asm/io.h>
 #include "dwmac100.h"
 
-static void dwmac100_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac100_core_init(struct mac_device_info *hw, int mtu)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + MAC_CONTROL);
 
 	writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
@@ -43,8 +44,9 @@ static void dwmac100_core_init(void __io
 #endif
 }
 
-static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
+static void dwmac100_dump_mac_regs(struct mac_device_info *hw)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	pr_info("\t----------------------------------------------\n"
 		"\t  DWMAC 100 CSR (base addr = 0x%p)\n"
 		"\t----------------------------------------------\n", ioaddr);
@@ -66,30 +68,35 @@ static void dwmac100_dump_mac_regs(void
 		readl(ioaddr + MAC_VLAN2));
 }
 
-static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac100_rx_ipc_enable(struct mac_device_info *hw)
 {
 	return 0;
 }
 
-static int dwmac100_irq_status(void __iomem *ioaddr,
+static int dwmac100_irq_status(struct mac_device_info *hw,
 			       struct stmmac_extra_stats *x)
 {
 	return 0;
 }
 
-static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_set_umac_addr(struct mac_device_info *hw,
+				   unsigned char *addr,
 				   unsigned int reg_n)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_get_umac_addr(struct mac_device_info *hw,
+				   unsigned char *addr,
 				   unsigned int reg_n)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_set_filter(struct net_device *dev, int id)
+static void dwmac100_set_filter(struct mac_device_info *hw,
+				struct net_device *dev)
 {
 	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
 	u32 value = readl(ioaddr + MAC_CONTROL);
@@ -137,9 +144,10 @@ static void dwmac100_set_filter(struct n
 	writel(value, ioaddr + MAC_CONTROL);
 }
 
-static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
 			       unsigned int fc, unsigned int pause_time)
 {
+	void __iomem *ioaddr = hw->pcsr;
 	unsigned int flow = MAC_FLOW_CTRL_ENABLE;
 
 	if (duplex)
@@ -148,7 +156,7 @@ static void dwmac100_flow_ctrl(void __io
 }
 
 /* No PMT module supported on ST boards with this Eth chip. */
-static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode)
 {
 	return;
 }
@@ -175,6 +183,7 @@ struct mac_device_info *dwmac100_setup(v
 
 	pr_info("\tDWMAC100\n");
 
+	mac->pcsr = ioaddr;
 	mac->mac = &dwmac100_ops;
 	mac->dma = &dwmac100_dma_ops;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,9 @@
 #include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 #include <linux/stmmac.h>
+#include "stmmac.h"
 
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
@@ -34,6 +36,7 @@ struct socfpga_dwmac {
 	u32	reg_shift;
 	struct	device *dev;
 	struct regmap *sys_mgr_base_addr;
+	struct reset_control *stmmac_rst;
 };
 
 static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
@@ -43,6 +46,13 @@ static int socfpga_dwmac_parse_data(stru
 	u32 reg_offset, reg_shift;
 	int ret;
 
+	dwmac->stmmac_rst = devm_reset_control_get(dev,
+						  STMMAC_RESOURCE_NAME);
+	if (IS_ERR(dwmac->stmmac_rst)) {
+		dev_info(dev, "Could not get reset control!\n");
+		return -EINVAL;
+	}
+
 	dwmac->interface = of_get_phy_mode(np);
 
 	sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
@@ -125,6 +135,65 @@ static void *socfpga_dwmac_probe(struct
 	return dwmac;
 }
 
+static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+	struct socfpga_dwmac	*dwmac = priv;
+
+	/* On socfpga platform exit, assert and hold reset to the
+	 * enet controller - the default state after a hard reset.
+	 */
+	if (dwmac->stmmac_rst)
+		reset_control_assert(dwmac->stmmac_rst);
+}
+
+static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
+{
+	struct socfpga_dwmac	*dwmac = priv;
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct stmmac_priv *stpriv = NULL;
+	int ret = 0;
+
+	if (ndev)
+		stpriv = netdev_priv(ndev);
+
+	/* Assert reset to the enet controller before changing the phy mode */
+	if (dwmac->stmmac_rst)
+		reset_control_assert(dwmac->stmmac_rst);
+
+	/* Setup the phy mode in the system manager registers according to
+	 * devicetree configuration
+	 */
+	ret = socfpga_dwmac_setup(dwmac);
+
+	/* Deassert reset for the phy configuration to be sampled by
+	 * the enet controller, and operation to start in requested mode
+	 */
+	if (dwmac->stmmac_rst)
+		reset_control_deassert(dwmac->stmmac_rst);
+
+	/* Before the enet controller is suspended, the phy is suspended.
+	 * This causes the phy clock to be gated. The enet controller is
+	 * resumed before the phy, so the clock is still gated "off" when
+	 * the enet controller is resumed. This code makes sure the phy
+	 * is "resumed" before reinitializing the enet controller since
+	 * the enet controller depends on an active phy clock to complete
+	 * a DMA reset. A DMA reset will "time out" if executed
+	 * with no phy clock input on the Synopsys enet controller.
+	 * Verified through Synopsys Case #8000711656.
+	 *
+	 * Note that the phy clock is also gated when the phy is isolated.
+	 * Phy "suspend" and "isolate" controls are located in phy basic
+	 * control register 0, and can be modified by the phy driver
+	 * framework.
+	 */
+	if (stpriv && stpriv->phydev)
+		phy_resume(stpriv->phydev);
+
+	return ret;
+}
+
 const struct stmmac_of_data socfpga_gmac_data = {
 	.setup = socfpga_dwmac_probe,
+	.init = socfpga_dwmac_init,
+	.exit = socfpga_dwmac_exit,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/mmc_core.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/mmc_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/mmc_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,7 +196,7 @@ void dwmac_mmc_read(void __iomem *ioaddr
 	mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
 	mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
 	mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
-	mmc->mmc_rx_crc_errror += readl(ioaddr + MMC_RX_CRC_ERRROR);
+	mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERRROR);
 	mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
 	mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
 	mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/mmc.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/mmc.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/mmc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/mmc.h	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ struct stmmac_counters {
 	unsigned int mmc_rx_octetcount_g;
 	unsigned int mmc_rx_broadcastframe_g;
 	unsigned int mmc_rx_multicastframe_g;
-	unsigned int mmc_rx_crc_errror;
+	unsigned int mmc_rx_crc_error;
 	unsigned int mmc_rx_align_error;
 	unsigned int mmc_rx_run_error;
 	unsigned int mmc_rx_jabber_error;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/ring_mode.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/ring_mode.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/ring_mode.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 
 #include "stmmac.h"
 
-static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
 	struct stmmac_priv *priv = (struct stmmac_priv *)p;
 	unsigned int txsize = priv->dma_tx_size;
@@ -53,7 +53,10 @@ static unsigned int stmmac_jumbo_frm(voi
 
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					    bmax, DMA_TO_DEVICE);
-		priv->tx_skbuff_dma[entry] = desc->des2;
+		if (dma_mapping_error(priv->device, desc->des2))
+			return -1;
+
+		priv->tx_skbuff_dma[entry].buf = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
 		priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
 						STMMAC_RING_MODE);
@@ -68,7 +71,9 @@ static unsigned int stmmac_jumbo_frm(voi
 
 		desc->des2 = dma_map_single(priv->device, skb->data + bmax,
 					    len, DMA_TO_DEVICE);
-		priv->tx_skbuff_dma[entry] = desc->des2;
+		if (dma_mapping_error(priv->device, desc->des2))
+			return -1;
+		priv->tx_skbuff_dma[entry].buf = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
 						STMMAC_RING_MODE);
@@ -77,7 +82,9 @@ static unsigned int stmmac_jumbo_frm(voi
 	} else {
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					    nopaged_len, DMA_TO_DEVICE);
-		priv->tx_skbuff_dma[entry] = desc->des2;
+		if (dma_mapping_error(priv->device, desc->des2))
+			return -1;
+		priv->tx_skbuff_dma[entry].buf = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
 						STMMAC_RING_MODE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -175,7 +175,7 @@ static const struct stmmac_stats stmmac_
 	STMMAC_MMC_STAT(mmc_rx_octetcount_g),
 	STMMAC_MMC_STAT(mmc_rx_broadcastframe_g),
 	STMMAC_MMC_STAT(mmc_rx_multicastframe_g),
-	STMMAC_MMC_STAT(mmc_rx_crc_errror),
+	STMMAC_MMC_STAT(mmc_rx_crc_error),
 	STMMAC_MMC_STAT(mmc_rx_align_error),
 	STMMAC_MMC_STAT(mmc_rx_run_error),
 	STMMAC_MMC_STAT(mmc_rx_jabber_error),
@@ -262,7 +262,7 @@ static int stmmac_ethtool_getsettings(st
 
 		/* Get and convert ADV/LP_ADV from the HW AN registers */
 		if (priv->hw->mac->get_adv)
-			priv->hw->mac->get_adv(priv->ioaddr, &adv);
+			priv->hw->mac->get_adv(priv->hw, &adv);
 		else
 			return -EOPNOTSUPP;	/* should never happen indeed */
 
@@ -350,7 +350,7 @@ static int stmmac_ethtool_setsettings(st
 
 			spin_lock(&priv->lock);
 			if (priv->hw->mac->ctrl_ane)
-				priv->hw->mac->ctrl_ane(priv->ioaddr, 1);
+				priv->hw->mac->ctrl_ane(priv->hw, 1);
 			spin_unlock(&priv->lock);
 		}
 
@@ -464,7 +464,7 @@ stmmac_set_pauseparam(struct net_device
 		if (netif_running(netdev))
 			ret = phy_start_aneg(phy);
 	} else
-		priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
+		priv->hw->mac->flow_ctrl(priv->hw, phy->duplex,
 					 priv->flow_ctrl, priv->pause);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,11 @@
 #include <linux/ptp_clock_kernel.h>
 #include <linux/reset.h>
 
+struct stmmac_tx_info {
+	dma_addr_t buf;
+	bool map_as_page;
+};
+
 struct stmmac_priv {
 	/* Frequently used values are kept adjacent for cache effect */
 	struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
@@ -45,7 +50,7 @@ struct stmmac_priv {
 	u32 tx_count_frames;
 	u32 tx_coal_frames;
 	u32 tx_coal_timer;
-	dma_addr_t *tx_skbuff_dma;
+	struct stmmac_tx_info *tx_skbuff_dma;
 	dma_addr_t dma_tx_phy;
 	int tx_coalesce;
 	int hwts_tx_en;
@@ -105,6 +110,8 @@ struct stmmac_priv {
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_clock_ops;
 	unsigned int default_addend;
+	struct clk *clk_ptp_ref;
+	unsigned int clk_ptp_rate;
 	u32 adv_ts;
 	int use_riwt;
 	int irq_wake;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -233,7 +233,7 @@ static void stmmac_enable_eee_mode(struc
 	/* Check and enter in LPI mode */
 	if ((priv->dirty_tx == priv->cur_tx) &&
 	    (priv->tx_path_in_lpi_mode == false))
-		priv->hw->mac->set_eee_mode(priv->ioaddr);
+		priv->hw->mac->set_eee_mode(priv->hw);
 }
 
 /**
@@ -244,7 +244,7 @@ static void stmmac_enable_eee_mode(struc
  */
 void stmmac_disable_eee_mode(struct stmmac_priv *priv)
 {
-	priv->hw->mac->reset_eee_mode(priv->ioaddr);
+	priv->hw->mac->reset_eee_mode(priv->hw);
 	del_timer_sync(&priv->eee_ctrl_timer);
 	priv->tx_path_in_lpi_mode = false;
 }
@@ -275,6 +275,7 @@ static void stmmac_eee_ctrl_timer(unsign
  */
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
+	char *phy_bus_name = priv->plat->phy_bus_name;
 	bool ret = false;
 
 	/* Using PCS we cannot dial with the phy registers at this stage
@@ -284,6 +285,10 @@ bool stmmac_eee_init(struct stmmac_priv
 	    (priv->pcs == STMMAC_PCS_RTBI))
 		goto out;
 
+	/* Never init EEE in case of a switch is attached */
+	if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
+		goto out;
+
 	/* MAC core supports the EEE feature. */
 	if (priv->dma_cap.eee) {
 		int tx_lpi_timer = priv->tx_lpi_timer;
@@ -298,7 +303,7 @@ bool stmmac_eee_init(struct stmmac_priv
 			if (priv->eee_active) {
 				pr_debug("stmmac: disable EEE\n");
 				del_timer_sync(&priv->eee_ctrl_timer);
-				priv->hw->mac->set_eee_timer(priv->ioaddr, 0,
+				priv->hw->mac->set_eee_timer(priv->hw, 0,
 							     tx_lpi_timer);
 			}
 			priv->eee_active = 0;
@@ -313,13 +318,12 @@ bool stmmac_eee_init(struct stmmac_priv
 			priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
 			add_timer(&priv->eee_ctrl_timer);
 
-			priv->hw->mac->set_eee_timer(priv->ioaddr,
+			priv->hw->mac->set_eee_timer(priv->hw,
 						     STMMAC_DEFAULT_LIT_LS,
 						     tx_lpi_timer);
-		} else
-			/* Set HW EEE according to the speed */
-			priv->hw->mac->set_eee_pls(priv->ioaddr,
-						   priv->phydev->link);
+		}
+		/* Set HW EEE according to the speed */
+		priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
 
 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
 
@@ -603,16 +607,16 @@ static int stmmac_hwtstamp_ioctl(struct
 		/* calculate default added value:
 		 * formula is :
 		 * addend = (2^32)/freq_div_ratio;
-		 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
-		 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
-		 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
+		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
+		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
+		 * NOTE: clk_ptp_ref_i should be >= 50MHz to
 		 *       achive 20ns accuracy.
 		 *
 		 * 2^x * y == (y << x), hence
 		 * 2^32 * 50000000 ==> (50000000 << 32)
 		 */
 		temp = (u64) (50000000ULL << 32);
-		priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
+		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
 		priv->hw->ptp->config_addend(priv->ioaddr,
 					     priv->default_addend);
 
@@ -638,6 +642,16 @@ static int stmmac_init_ptp(struct stmmac
 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
 		return -EOPNOTSUPP;
 
+	/* Fall-back to main clock in case of no PTP ref is passed */
+	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
+	if (IS_ERR(priv->clk_ptp_ref)) {
+		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
+		priv->clk_ptp_ref = NULL;
+	} else {
+		clk_prepare_enable(priv->clk_ptp_ref);
+		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
+	}
+
 	priv->adv_ts = 0;
 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
 		priv->adv_ts = 1;
@@ -657,6 +671,8 @@ static int stmmac_init_ptp(struct stmmac
 
 static void stmmac_release_ptp(struct stmmac_priv *priv)
 {
+	if (priv->clk_ptp_ref)
+		clk_disable_unprepare(priv->clk_ptp_ref);
 	stmmac_ptp_unregister(priv);
 }
 
@@ -693,7 +709,7 @@ static void stmmac_adjust_link(struct ne
 		}
 		/* Flow Control operation */
 		if (phydev->pause)
-			priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
+			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
 						 fc, pause_time);
 
 		if (phydev->speed != priv->speed) {
@@ -1061,7 +1077,8 @@ static int init_dma_desc_rings(struct ne
 		else
 			p = priv->dma_tx + i;
 		p->des2 = 0;
-		priv->tx_skbuff_dma[i] = 0;
+		priv->tx_skbuff_dma[i].buf = 0;
+		priv->tx_skbuff_dma[i].map_as_page = false;
 		priv->tx_skbuff[i] = NULL;
 	}
 
@@ -1100,17 +1117,24 @@ static void dma_free_tx_skbufs(struct st
 		else
 			p = priv->dma_tx + i;
 
-		if (priv->tx_skbuff_dma[i]) {
-			dma_unmap_single(priv->device,
-					 priv->tx_skbuff_dma[i],
-					 priv->hw->desc->get_tx_len(p),
-					 DMA_TO_DEVICE);
-			priv->tx_skbuff_dma[i] = 0;
+		if (priv->tx_skbuff_dma[i].buf) {
+			if (priv->tx_skbuff_dma[i].map_as_page)
+				dma_unmap_page(priv->device,
+					       priv->tx_skbuff_dma[i].buf,
+					       priv->hw->desc->get_tx_len(p),
+					       DMA_TO_DEVICE);
+			else
+				dma_unmap_single(priv->device,
+						 priv->tx_skbuff_dma[i].buf,
+						 priv->hw->desc->get_tx_len(p),
+						 DMA_TO_DEVICE);
 		}
 
 		if (priv->tx_skbuff[i] != NULL) {
 			dev_kfree_skb_any(priv->tx_skbuff[i]);
 			priv->tx_skbuff[i] = NULL;
+			priv->tx_skbuff_dma[i].buf = 0;
+			priv->tx_skbuff_dma[i].map_as_page = false;
 		}
 	}
 }
@@ -1131,7 +1155,8 @@ static int alloc_dma_desc_resources(stru
 	if (!priv->rx_skbuff)
 		goto err_rx_skbuff;
 
-	priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+	priv->tx_skbuff_dma = kmalloc_array(txsize,
+					    sizeof(*priv->tx_skbuff_dma),
 					    GFP_KERNEL);
 	if (!priv->tx_skbuff_dma)
 		goto err_tx_skbuff_dma;
@@ -1293,12 +1318,19 @@ static void stmmac_tx_clean(struct stmma
 			pr_debug("%s: curr %d, dirty %d\n", __func__,
 				 priv->cur_tx, priv->dirty_tx);
 
-		if (likely(priv->tx_skbuff_dma[entry])) {
-			dma_unmap_single(priv->device,
-					 priv->tx_skbuff_dma[entry],
-					 priv->hw->desc->get_tx_len(p),
-					 DMA_TO_DEVICE);
-			priv->tx_skbuff_dma[entry] = 0;
+		if (likely(priv->tx_skbuff_dma[entry].buf)) {
+			if (priv->tx_skbuff_dma[entry].map_as_page)
+				dma_unmap_page(priv->device,
+					       priv->tx_skbuff_dma[entry].buf,
+					       priv->hw->desc->get_tx_len(p),
+					       DMA_TO_DEVICE);
+			else
+				dma_unmap_single(priv->device,
+						 priv->tx_skbuff_dma[entry].buf,
+						 priv->hw->desc->get_tx_len(p),
+						 DMA_TO_DEVICE);
+			priv->tx_skbuff_dma[entry].buf = 0;
+			priv->tx_skbuff_dma[entry].map_as_page = false;
 		}
 		priv->hw->mode->clean_desc3(priv, p);
 
@@ -1531,8 +1563,7 @@ static int stmmac_get_hw_features(struct
 static void stmmac_check_ether_addr(struct stmmac_priv *priv)
 {
 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
-		priv->hw->mac->get_umac_addr((void __iomem *)
-					     priv->dev->base_addr,
+		priv->hw->mac->get_umac_addr(priv->hw,
 					     priv->dev->dev_addr, 0);
 		if (!is_valid_ether_addr(priv->dev->dev_addr))
 			eth_hw_addr_random(priv->dev);
@@ -1629,14 +1660,21 @@ static int stmmac_hw_setup(struct net_de
 	}
 
 	/* Copy the MAC addr into the HW  */
-	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
 
 	/* If required, perform hw setup of the bus. */
 	if (priv->plat->bus_setup)
 		priv->plat->bus_setup(priv->ioaddr);
 
 	/* Initialize the MAC Core */
-	priv->hw->mac->core_init(priv->ioaddr, dev->mtu);
+	priv->hw->mac->core_init(priv->hw, dev->mtu);
+
+	ret = priv->hw->mac->rx_ipc(priv->hw);
+	if (!ret) {
+		pr_warn(" RX IPC Checksum Offload disabled\n");
+		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+		priv->hw->rx_csum = 0;
+	}
 
 	/* Enable the MAC Rx/Tx */
 	stmmac_set_mac(priv->ioaddr, true);
@@ -1662,7 +1700,7 @@ static int stmmac_hw_setup(struct net_de
 
 	/* Dump DMA/MAC registers */
 	if (netif_msg_hw(priv)) {
-		priv->hw->mac->dump_regs(priv->ioaddr);
+		priv->hw->mac->dump_regs(priv->hw);
 		priv->hw->dma->dump_regs(priv->ioaddr);
 	}
 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
@@ -1677,7 +1715,7 @@ static int stmmac_hw_setup(struct net_de
 	}
 
 	if (priv->pcs && priv->hw->mac->ctrl_ane)
-		priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+		priv->hw->mac->ctrl_ane(priv->hw, 0);
 
 	return 0;
 }
@@ -1888,12 +1926,16 @@ static netdev_tx_t stmmac_xmit(struct sk
 	if (likely(!is_jumbo)) {
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					    nopaged_len, DMA_TO_DEVICE);
-		priv->tx_skbuff_dma[entry] = desc->des2;
+		if (dma_mapping_error(priv->device, desc->des2))
+			goto dma_map_err;
+		priv->tx_skbuff_dma[entry].buf = desc->des2;
 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
 						csum_insertion, priv->mode);
 	} else {
 		desc = first;
 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
+		if (unlikely(entry < 0))
+			goto dma_map_err;
 	}
 
 	for (i = 0; i < nfrags; i++) {
@@ -1909,7 +1951,11 @@ static netdev_tx_t stmmac_xmit(struct sk
 
 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
 					      DMA_TO_DEVICE);
-		priv->tx_skbuff_dma[entry] = desc->des2;
+		if (dma_mapping_error(priv->device, desc->des2))
+			goto dma_map_err; /* should reuse desc w/o issues */
+
+		priv->tx_skbuff_dma[entry].buf = desc->des2;
+		priv->tx_skbuff_dma[entry].map_as_page = true;
 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
 						priv->mode);
 		wmb();
@@ -1976,7 +2022,12 @@ static netdev_tx_t stmmac_xmit(struct sk
 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
 
 	spin_unlock(&priv->tx_lock);
+	return NETDEV_TX_OK;
 
+dma_map_err:
+	dev_err(priv->device, "Tx dma map failed\n");
+	dev_kfree_skb(skb);
+	priv->dev->stats.tx_dropped++;
 	return NETDEV_TX_OK;
 }
 
@@ -2029,7 +2080,12 @@ static inline void stmmac_rx_refill(stru
 			priv->rx_skbuff_dma[entry] =
 			    dma_map_single(priv->device, skb->data, bfsize,
 					   DMA_FROM_DEVICE);
-
+			if (dma_mapping_error(priv->device,
+					      priv->rx_skbuff_dma[entry])) {
+				dev_err(priv->device, "Rx dma map failed\n");
+				dev_kfree_skb(skb);
+				break;
+			}
 			p->des2 = priv->rx_skbuff_dma[entry];
 
 			priv->hw->mode->refill_desc3(priv, p);
@@ -2056,7 +2112,7 @@ static int stmmac_rx(struct stmmac_priv
 	unsigned int entry = priv->cur_rx % rxsize;
 	unsigned int next_entry;
 	unsigned int count = 0;
-	int coe = priv->plat->rx_coe;
+	int coe = priv->hw->rx_csum;
 
 	if (netif_msg_rx_status(priv)) {
 		pr_debug("%s: descriptor ring:\n", __func__);
@@ -2226,7 +2282,7 @@ static void stmmac_set_rx_mode(struct ne
 	struct stmmac_priv *priv = netdev_priv(dev);
 
 	spin_lock(&priv->lock);
-	priv->hw->mac->set_filter(dev, priv->synopsys_id);
+	priv->hw->mac->set_filter(priv->hw, dev);
 	spin_unlock(&priv->lock);
 }
 
@@ -2277,8 +2333,7 @@ static netdev_features_t stmmac_fix_feat
 
 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
 		features &= ~NETIF_F_RXCSUM;
-	else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
-		features &= ~NETIF_F_IPV6_CSUM;
+
 	if (!priv->plat->tx_coe)
 		features &= ~NETIF_F_ALL_CSUM;
 
@@ -2293,6 +2348,24 @@ static netdev_features_t stmmac_fix_feat
 	return features;
 }
 
+static int stmmac_set_features(struct net_device *netdev,
+			       netdev_features_t features)
+{
+	struct stmmac_priv *priv = netdev_priv(netdev);
+
+	/* Keep the COE Type in case of csum is supporting */
+	if (features & NETIF_F_RXCSUM)
+		priv->hw->rx_csum = priv->plat->rx_coe;
+	else
+		priv->hw->rx_csum = 0;
+	/* No check needed because rx_coe has been set before and it will be
+	 * fixed in case of issue.
+	 */
+	priv->hw->mac->rx_ipc(priv->hw);
+
+	return 0;
+}
+
 /**
  *  stmmac_interrupt - main ISR
  *  @irq: interrupt number.
@@ -2316,8 +2389,7 @@ static irqreturn_t stmmac_interrupt(int
 
 	/* To handle GMAC own interrupts */
 	if (priv->plat->has_gmac) {
-		int status = priv->hw->mac->host_irq_status((void __iomem *)
-							    dev->base_addr,
+		int status = priv->hw->mac->host_irq_status(priv->hw,
 							    &priv->xstats);
 		if (unlikely(status)) {
 			/* For LPI we need to save the tx status */
@@ -2574,6 +2646,7 @@ static const struct net_device_ops stmma
 	.ndo_stop = stmmac_release,
 	.ndo_change_mtu = stmmac_change_mtu,
 	.ndo_fix_features = stmmac_fix_features,
+	.ndo_set_features = stmmac_set_features,
 	.ndo_set_rx_mode = stmmac_set_rx_mode,
 	.ndo_tx_timeout = stmmac_tx_timeout,
 	.ndo_do_ioctl = stmmac_ioctl,
@@ -2594,13 +2667,14 @@ static const struct net_device_ops stmma
  */
 static int stmmac_hw_init(struct stmmac_priv *priv)
 {
-	int ret;
 	struct mac_device_info *mac;
 
 	/* Identify the MAC HW device */
 	if (priv->plat->has_gmac) {
 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
-		mac = dwmac1000_setup(priv->ioaddr);
+		mac = dwmac1000_setup(priv->ioaddr,
+				      priv->plat->multicast_filter_bins,
+				      priv->plat->unicast_filter_entries);
 	} else {
 		mac = dwmac100_setup(priv->ioaddr);
 	}
@@ -2649,15 +2723,11 @@ static int stmmac_hw_init(struct stmmac_
 	/* To use alternate (extended) or normal descriptor structures */
 	stmmac_selec_desc_mode(priv);
 
-	ret = priv->hw->mac->rx_ipc(priv->ioaddr);
-	if (!ret) {
-		pr_warn(" RX IPC Checksum Offload not configured.\n");
-		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
-	}
-
-	if (priv->plat->rx_coe)
+	if (priv->plat->rx_coe) {
+		priv->hw->rx_csum = priv->plat->rx_coe;
 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
 			priv->plat->rx_coe);
+	}
 	if (priv->plat->tx_coe)
 		pr_info(" TX Checksum insertion supported\n");
 
@@ -2869,7 +2939,7 @@ int stmmac_suspend(struct net_device *nd
 
 	/* Enable Power down mode by programming the PMT regs */
 	if (device_may_wakeup(priv->device)) {
-		priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+		priv->hw->mac->pmt(priv->hw, priv->wolopts);
 		priv->irq_wake = 1;
 	} else {
 		stmmac_set_mac(priv->ioaddr, false);
@@ -2878,6 +2948,10 @@ int stmmac_suspend(struct net_device *nd
 		clk_disable_unprepare(priv->stmmac_clk);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	priv->oldlink = 0;
+	priv->speed = 0;
+	priv->oldduplex = -1;
 	return 0;
 }
 
@@ -2898,7 +2972,7 @@ int stmmac_resume(struct net_device *nde
 	 * from another devices (e.g. serial console).
 	 */
 	if (device_may_wakeup(priv->device)) {
-		priv->hw->mac->pmt(priv->ioaddr, 0);
+		priv->hw->mac->pmt(priv->hw, 0);
 		priv->irq_wake = 0;
 	} else {
 		pinctrl_pm_select_default_state(priv->device);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -170,7 +170,7 @@ static int stmmac_pci_resume(struct pci_
 #define STMMAC_VENDOR_ID 0x700
 #define STMMAC_DEVICE_ID 0x1108
 
-static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
+static const struct pci_device_id stmmac_id_table[] = {
 	{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
 	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
 	{}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,6 +52,59 @@ static const struct of_device_id stmmac_
 MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
 
 #ifdef CONFIG_OF
+
+/* This function validates the number of Multicast filtering bins specified
+ * by the configuration through the device tree. The Synopsys GMAC supports
+ * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC
+ * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds
+ * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is
+ * invalid and will cause the filtering algorithm to use Multicast
+ * promiscuous mode.
+ */
+static int dwmac1000_validate_mcast_bins(int mcast_bins)
+{
+	int x = mcast_bins;
+
+	switch (x) {
+	case HASH_TABLE_SIZE:
+	case 128:
+	case 256:
+		break;
+	default:
+		x = 0;
+		pr_info("Hash table entries set to unexpected value %d",
+			mcast_bins);
+		break;
+	}
+	return x;
+}
+
+/* This function validates the number of Unicast address entries supported
+ * by a particular Synopsys 10/100/1000 controller. The Synopsys controller
+ * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter
+ * logic. This function validates a valid, supported configuration is
+ * selected, and defaults to 1 Unicast address if an unsupported
+ * configuration is selected.
+ */
+static int dwmac1000_validate_ucast_entries(int ucast_entries)
+{
+	int x = ucast_entries;
+
+	switch (x) {
+	case 1:
+	case 32:
+	case 64:
+	case 128:
+		break;
+	default:
+		x = 1;
+		pr_info("Unicast table entries set to unexpected value %d\n",
+			ucast_entries);
+		break;
+	}
+	return x;
+}
+
 static int stmmac_probe_config_dt(struct platform_device *pdev,
 				  struct plat_stmmacenet_data *plat,
 				  const char **mac)
@@ -115,6 +168,12 @@ static int stmmac_probe_config_dt(struct
 	 */
 	plat->maxmtu = JUMBO_LEN;
 
+	/* Set default value for multicast hash bins */
+	plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+	/* Set default value for unicast filter entries */
+	plat->unicast_filter_entries = 1;
+
 	/*
 	 * Currently only the properties needed on SPEAr600
 	 * are provided. All other properties should be added
@@ -131,6 +190,14 @@ static int stmmac_probe_config_dt(struct
 		 * are clearly MTUs
 		 */
 		of_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+		of_property_read_u32(np, "snps,multicast-filter-bins",
+				     &plat->multicast_filter_bins);
+		of_property_read_u32(np, "snps,perfect-filter-entries",
+				     &plat->unicast_filter_entries);
+		plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
+					       plat->unicast_filter_entries);
+		plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
+					      plat->multicast_filter_bins);
 		plat->has_gmac = 1;
 		plat->pmt = 1;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,6 +206,7 @@ void stmmac_ptp_unregister(struct stmmac
 {
 	if (priv->ptp_clock) {
 		ptp_clock_unregister(priv->ptp_clock);
+		priv->ptp_clock = NULL;
 		pr_debug("Removed PTP HW clock successfully on %s\n",
 			 priv->dev->name);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,8 +25,6 @@
 #ifndef __STMMAC_PTP_H__
 #define __STMMAC_PTP_H__
 
-#define STMMAC_SYSCLOCK 62500000
-
 /* IEEE 1588 PTP register offsets */
 #define PTP_TCR		0x0700	/* Timestamp Control Reg */
 #define PTP_SSIR	0x0704	/* Sub-Second Increment Reg */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/cassini.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/cassini.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/cassini.c	2014-08-07 04:51:56.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/cassini.c	2014-09-28 21:33:23.000000000 -0400
@@ -229,7 +229,7 @@ static u16 link_modes[] = {
 	CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */
 };
 
-static DEFINE_PCI_DEVICE_TABLE(cas_pci_tbl) = {
+static const struct pci_device_id cas_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/niu.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/niu.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/niu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/niu.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ static void writeq(u64 val, void __iomem
 }
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = {
+static const struct pci_device_id niu_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)},
 	{}
 };
@@ -2584,7 +2584,6 @@ static int niu_determine_phy_disposition
 				break;
 			default:
 				return -EINVAL;
-				break;
 			}
 			phy_addr_off = niu_atca_port_num[np->port];
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/sungem.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sungem.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/sungem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sungem.c	2014-09-28 17:29:07.000000000 -0400
@@ -85,7 +85,7 @@ MODULE_LICENSE("GPL");
 
 #define GEM_MODULE_NAME	"gem"
 
-static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = {
+static const struct pci_device_id gem_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunhme.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunhme.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunhme.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunhme.c	2014-09-28 17:29:07.000000000 -0400
@@ -3172,7 +3172,7 @@ static void happy_meal_pci_remove(struct
 	free_netdev(net_dev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(happymeal_pci_ids) = {
+static const struct pci_device_id happymeal_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) },
 	{ }			/* Terminating entry */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunvnet.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunvnet.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunvnet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunvnet.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,6 +32,11 @@ MODULE_DESCRIPTION("Sun LDOM virtual net
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
+/* Heuristic for the number of times to exponentially backoff and
+ * retry sending an LDC trigger when EAGAIN is encountered
+ */
+#define	VNET_MAX_RETRIES	10
+
 /* Ordered from largest major to lowest */
 static struct vio_version vnet_versions[] = {
 	{ .major = 1, .minor = 0 },
@@ -260,6 +265,7 @@ static int vnet_send_ack(struct vnet_por
 		.state			= vio_dring_state,
 	};
 	int err, delay;
+	int retries = 0;
 
 	hdr.seq = dr->snd_nxt;
 	delay = 1;
@@ -272,6 +278,13 @@ static int vnet_send_ack(struct vnet_por
 		udelay(delay);
 		if ((delay <<= 1) > 128)
 			delay = 128;
+		if (retries++ > VNET_MAX_RETRIES) {
+			pr_info("ECONNRESET %x:%x:%x:%x:%x:%x\n",
+				port->raddr[0], port->raddr[1],
+				port->raddr[2], port->raddr[3],
+				port->raddr[4], port->raddr[5]);
+			err = -ECONNRESET;
+		}
 	} while (err == -EAGAIN);
 
 	return err;
@@ -337,14 +350,17 @@ static int vnet_walk_rx_one(struct vnet_
 	if (IS_ERR(desc))
 		return PTR_ERR(desc);
 
+	if (desc->hdr.state != VIO_DESC_READY)
+		return 1;
+
+	rmb();
+
 	viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%llx:%llx]\n",
 	       desc->hdr.state, desc->hdr.ack,
 	       desc->size, desc->ncookies,
 	       desc->cookies[0].cookie_addr,
 	       desc->cookies[0].cookie_size);
 
-	if (desc->hdr.state != VIO_DESC_READY)
-		return 1;
 	err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies);
 	if (err == -ECONNRESET)
 		return err;
@@ -475,8 +491,9 @@ static int handle_mcast(struct vnet_port
 	return 0;
 }
 
-static void maybe_tx_wakeup(struct vnet *vp)
+static void maybe_tx_wakeup(unsigned long param)
 {
+	struct vnet *vp = (struct vnet *)param;
 	struct net_device *dev = vp->dev;
 
 	netif_tx_lock(dev);
@@ -573,8 +590,13 @@ static void vnet_event(void *arg, int ev
 			break;
 	}
 	spin_unlock(&vio->lock);
+	/* Kick off a tasklet to wake the queue.  We cannot call
+	 * maybe_tx_wakeup directly here because we could deadlock on
+	 * netif_tx_lock() with dev_watchdog()
+	 */
 	if (unlikely(tx_wakeup && err != -ECONNRESET))
-		maybe_tx_wakeup(port->vp);
+		tasklet_schedule(&port->vp->vnet_tx_wakeup);
+
 	local_irq_restore(flags);
 }
 
@@ -593,6 +615,7 @@ static int __vnet_tx_trigger(struct vnet
 		.end_idx		= (u32) -1,
 	};
 	int err, delay;
+	int retries = 0;
 
 	hdr.seq = dr->snd_nxt;
 	delay = 1;
@@ -605,6 +628,8 @@ static int __vnet_tx_trigger(struct vnet
 		udelay(delay);
 		if ((delay <<= 1) > 128)
 			delay = 128;
+		if (retries++ > VNET_MAX_RETRIES)
+			break;
 	} while (err == -EAGAIN);
 
 	return err;
@@ -691,7 +716,15 @@ static int vnet_start_xmit(struct sk_buf
 		memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
 	}
 
-	d->hdr.ack = VIO_ACK_ENABLE;
+	/* We don't rely on the ACKs to free the skb in vnet_start_xmit(),
+	 * thus it is safe to not set VIO_ACK_ENABLE for each transmission:
+	 * the protocol itself does not require it as long as the peer
+	 * sends a VIO_SUBTYPE_ACK for VIO_DRING_STOPPED.
+	 *
+	 * An ACK for every packet in the ring is expensive as the
+	 * sending of LDC messages is slow and affects performance.
+	 */
+	d->hdr.ack = VIO_ACK_DISABLE;
 	d->size = len;
 	d->ncookies = port->tx_bufs[dr->prod].ncookies;
 	for (i = 0; i < d->ncookies; i++)
@@ -1046,6 +1079,7 @@ static struct vnet *vnet_new(const u64 *
 	vp = netdev_priv(dev);
 
 	spin_lock_init(&vp->lock);
+	tasklet_init(&vp->vnet_tx_wakeup, maybe_tx_wakeup, (unsigned long)vp);
 	vp->dev = dev;
 
 	INIT_LIST_HEAD(&vp->port_list);
@@ -1105,6 +1139,7 @@ static void vnet_cleanup(void)
 		vp = list_first_entry(&vnet_list, struct vnet, list);
 		list_del(&vp->list);
 		dev = vp->dev;
+		tasklet_kill(&vp->vnet_tx_wakeup);
 		/* vio_unregister_driver() should have cleaned up port_list */
 		BUG_ON(!list_empty(&vp->port_list));
 		unregister_netdev(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunvnet.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunvnet.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/sun/sunvnet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/sun/sunvnet.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef _SUNVNET_H
 #define _SUNVNET_H
 
+#include <linux/interrupt.h>
+
 #define DESC_NCOOKIES(entry_size)	\
 	((entry_size) - sizeof(struct vio_net_desc))
 
@@ -78,6 +80,8 @@ struct vnet {
 
 	struct list_head	list;
 	u64			local_mac;
+
+	struct tasklet_struct	vnet_tx_wakeup;
 };
 
 #endif /* _SUNVNET_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/tehuti/tehuti.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tehuti/tehuti.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/tehuti/tehuti.c	2014-08-07 04:52:52.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tehuti/tehuti.c	2014-09-28 21:34:29.000000000 -0400
@@ -66,7 +66,7 @@
 
 #include "tehuti.h"
 
-static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = {
+static const struct pci_device_id bdx_pci_tbl[] = {
 	{ PCI_VDEVICE(TEHUTI, 0x3009), },
 	{ PCI_VDEVICE(TEHUTI, 0x3010), },
 	{ PCI_VDEVICE(TEHUTI, 0x3014), },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpmac.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpmac.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpmac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpmac.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,42 +67,42 @@ MODULE_PARM_DESC(dumb_switch, "Assume sw
 #define CPMAC_RX_CONTROL		0x0014
 #define CPMAC_RX_TEARDOWN		0x0018
 #define CPMAC_MBP			0x0100
-# define MBP_RXPASSCRC			0x40000000
-# define MBP_RXQOS			0x20000000
-# define MBP_RXNOCHAIN			0x10000000
-# define MBP_RXCMF			0x01000000
-# define MBP_RXSHORT			0x00800000
-# define MBP_RXCEF			0x00400000
-# define MBP_RXPROMISC			0x00200000
-# define MBP_PROMISCCHAN(channel)	(((channel) & 0x7) << 16)
-# define MBP_RXBCAST			0x00002000
-# define MBP_BCASTCHAN(channel)		(((channel) & 0x7) << 8)
-# define MBP_RXMCAST			0x00000020
-# define MBP_MCASTCHAN(channel)		((channel) & 0x7)
+#define MBP_RXPASSCRC			0x40000000
+#define MBP_RXQOS			0x20000000
+#define MBP_RXNOCHAIN			0x10000000
+#define MBP_RXCMF			0x01000000
+#define MBP_RXSHORT			0x00800000
+#define MBP_RXCEF			0x00400000
+#define MBP_RXPROMISC			0x00200000
+#define MBP_PROMISCCHAN(channel)	(((channel) & 0x7) << 16)
+#define MBP_RXBCAST			0x00002000
+#define MBP_BCASTCHAN(channel)		(((channel) & 0x7) << 8)
+#define MBP_RXMCAST			0x00000020
+#define MBP_MCASTCHAN(channel)		((channel) & 0x7)
 #define CPMAC_UNICAST_ENABLE		0x0104
 #define CPMAC_UNICAST_CLEAR		0x0108
 #define CPMAC_MAX_LENGTH		0x010c
 #define CPMAC_BUFFER_OFFSET		0x0110
 #define CPMAC_MAC_CONTROL		0x0160
-# define MAC_TXPTYPE			0x00000200
-# define MAC_TXPACE			0x00000040
-# define MAC_MII			0x00000020
-# define MAC_TXFLOW			0x00000010
-# define MAC_RXFLOW			0x00000008
-# define MAC_MTEST			0x00000004
-# define MAC_LOOPBACK			0x00000002
-# define MAC_FDX			0x00000001
+#define MAC_TXPTYPE			0x00000200
+#define MAC_TXPACE			0x00000040
+#define MAC_MII				0x00000020
+#define MAC_TXFLOW			0x00000010
+#define MAC_RXFLOW			0x00000008
+#define MAC_MTEST			0x00000004
+#define MAC_LOOPBACK			0x00000002
+#define MAC_FDX				0x00000001
 #define CPMAC_MAC_STATUS		0x0164
-# define MAC_STATUS_QOS			0x00000004
-# define MAC_STATUS_RXFLOW		0x00000002
-# define MAC_STATUS_TXFLOW		0x00000001
+#define MAC_STATUS_QOS			0x00000004
+#define MAC_STATUS_RXFLOW		0x00000002
+#define MAC_STATUS_TXFLOW		0x00000001
 #define CPMAC_TX_INT_ENABLE		0x0178
 #define CPMAC_TX_INT_CLEAR		0x017c
 #define CPMAC_MAC_INT_VECTOR		0x0180
-# define MAC_INT_STATUS			0x00080000
-# define MAC_INT_HOST			0x00040000
-# define MAC_INT_RX			0x00020000
-# define MAC_INT_TX			0x00010000
+#define MAC_INT_STATUS			0x00080000
+#define MAC_INT_HOST			0x00040000
+#define MAC_INT_RX			0x00020000
+#define MAC_INT_TX			0x00010000
 #define CPMAC_MAC_EOI_VECTOR		0x0184
 #define CPMAC_RX_INT_ENABLE		0x0198
 #define CPMAC_RX_INT_CLEAR		0x019c
@@ -118,8 +118,8 @@ MODULE_PARM_DESC(dumb_switch, "Assume sw
 #define CPMAC_TX_ACK(channel)		(0x0640 + (channel) * 4)
 #define CPMAC_RX_ACK(channel)		(0x0660 + (channel) * 4)
 #define CPMAC_REG_END			0x0680
-/*
- * Rx/Tx statistics
+
+/* Rx/Tx statistics
  * TODO: use some of them to fill stats in cpmac_stats()
  */
 #define CPMAC_STATS_RX_GOOD		0x0200
@@ -157,24 +157,24 @@ MODULE_PARM_DESC(dumb_switch, "Assume sw
 /* MDIO bus */
 #define CPMAC_MDIO_VERSION		0x0000
 #define CPMAC_MDIO_CONTROL		0x0004
-# define MDIOC_IDLE			0x80000000
-# define MDIOC_ENABLE			0x40000000
-# define MDIOC_PREAMBLE			0x00100000
-# define MDIOC_FAULT			0x00080000
-# define MDIOC_FAULTDETECT		0x00040000
-# define MDIOC_INTTEST			0x00020000
-# define MDIOC_CLKDIV(div)		((div) & 0xff)
+#define MDIOC_IDLE			0x80000000
+#define MDIOC_ENABLE			0x40000000
+#define MDIOC_PREAMBLE			0x00100000
+#define MDIOC_FAULT			0x00080000
+#define MDIOC_FAULTDETECT		0x00040000
+#define MDIOC_INTTEST			0x00020000
+#define MDIOC_CLKDIV(div)		((div) & 0xff)
 #define CPMAC_MDIO_ALIVE		0x0008
 #define CPMAC_MDIO_LINK			0x000c
 #define CPMAC_MDIO_ACCESS(channel)	(0x0080 + (channel) * 8)
-# define MDIO_BUSY			0x80000000
-# define MDIO_WRITE			0x40000000
-# define MDIO_REG(reg)			(((reg) & 0x1f) << 21)
-# define MDIO_PHY(phy)			(((phy) & 0x1f) << 16)
-# define MDIO_DATA(data)		((data) & 0xffff)
+#define MDIO_BUSY			0x80000000
+#define MDIO_WRITE			0x40000000
+#define MDIO_REG(reg)			(((reg) & 0x1f) << 21)
+#define MDIO_PHY(phy)			(((phy) & 0x1f) << 16)
+#define MDIO_DATA(data)			((data) & 0xffff)
 #define CPMAC_MDIO_PHYSEL(channel)	(0x0084 + (channel) * 8)
-# define PHYSEL_LINKSEL			0x00000040
-# define PHYSEL_LINKINT			0x00000020
+#define PHYSEL_LINKSEL			0x00000040
+#define PHYSEL_LINKINT			0x00000020
 
 struct cpmac_desc {
 	u32 hw_next;
@@ -224,12 +224,12 @@ static void cpmac_dump_regs(struct net_d
 {
 	int i;
 	struct cpmac_priv *priv = netdev_priv(dev);
+
 	for (i = 0; i < CPMAC_REG_END; i += 4) {
 		if (i % 16 == 0) {
 			if (i)
-				pr_cont("\n");
-			printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
-			       priv->regs + i);
+				printk("\n");
+			printk("%s: reg[%p]:", dev->name, priv->regs + i);
 		}
 		printk(" %08x", cpmac_read(priv->regs, i));
 	}
@@ -239,7 +239,8 @@ static void cpmac_dump_regs(struct net_d
 static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc)
 {
 	int i;
-	printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc);
+
+	printk("%s: desc[%p]:", dev->name, desc);
 	for (i = 0; i < sizeof(*desc) / 4; i++)
 		printk(" %08x", ((u32 *)desc)[i]);
 	printk("\n");
@@ -249,6 +250,7 @@ static void cpmac_dump_all_desc(struct n
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
 	struct cpmac_desc *dump = priv->rx_head;
+
 	do {
 		cpmac_dump_desc(dev, dump);
 		dump = dump->next;
@@ -258,13 +260,13 @@ static void cpmac_dump_all_desc(struct n
 static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
 {
 	int i;
-	printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
+
+	printk("%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
 	for (i = 0; i < skb->len; i++) {
 		if (i % 16 == 0) {
 			if (i)
-				pr_cont("\n");
-			printk(KERN_DEBUG "%s: data[%p]:", dev->name,
-			       skb->data + i);
+				printk("\n");
+			printk("%s: data[%p]:", dev->name, skb->data + i);
 		}
 		printk(" %02x", ((u8 *)skb->data)[i]);
 	}
@@ -281,6 +283,7 @@ static int cpmac_mdio_read(struct mii_bu
 		    MDIO_PHY(phy_id));
 	while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY)
 		cpu_relax();
+
 	return MDIO_DATA(val);
 }
 
@@ -291,6 +294,7 @@ static int cpmac_mdio_write(struct mii_b
 		cpu_relax();
 	cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE |
 		    MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val));
+
 	return 0;
 }
 
@@ -300,12 +304,13 @@ static int cpmac_mdio_reset(struct mii_b
 
 	cpmac_clk = clk_get(&bus->dev, "cpmac");
 	if (IS_ERR(cpmac_clk)) {
-		printk(KERN_ERR "unable to get cpmac clock\n");
+		pr_err("unable to get cpmac clock\n");
 		return -1;
 	}
 	ar7_device_reset(AR7_RESET_BIT_MDIO);
 	cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE |
 		    MDIOC_CLKDIV(clk_get_rate(cpmac_clk) / 2200000 - 1));
+
 	return 0;
 }
 
@@ -331,8 +336,7 @@ static void cpmac_set_multicast_list(str
 			cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff);
 			cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff);
 		} else {
-			/*
-			 * cpmac uses some strange mac address hashing
+			/* cpmac uses some strange mac address hashing
 			 * (not crc32)
 			 */
 			netdev_for_each_mc_addr(ha, dev) {
@@ -369,8 +373,8 @@ static struct sk_buff *cpmac_rx_one(stru
 	cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping);
 	if (unlikely(!desc->datalen)) {
 		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx: spurious interrupt\n",
-			       priv->dev->name);
+			netdev_warn(priv->dev, "rx: spurious interrupt\n");
+
 		return NULL;
 	}
 
@@ -390,15 +394,14 @@ static struct sk_buff *cpmac_rx_one(stru
 						    DMA_FROM_DEVICE);
 		desc->hw_data = (u32)desc->data_mapping;
 		if (unlikely(netif_msg_pktdata(priv))) {
-			printk(KERN_DEBUG "%s: received packet:\n",
-			       priv->dev->name);
+			netdev_dbg(priv->dev, "received packet:\n");
 			cpmac_dump_skb(priv->dev, result);
 		}
 	} else {
 		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING
-			       "%s: low on skbs, dropping packet\n",
-			       priv->dev->name);
+			netdev_warn(priv->dev,
+				    "low on skbs, dropping packet\n");
+
 		priv->dev->stats.rx_dropped++;
 	}
 
@@ -418,8 +421,8 @@ static int cpmac_poll(struct napi_struct
 	spin_lock(&priv->rx_lock);
 	if (unlikely(!priv->rx_head)) {
 		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx: polling, but no queue\n",
-			       priv->dev->name);
+			netdev_warn(priv->dev, "rx: polling, but no queue\n");
+
 		spin_unlock(&priv->rx_lock);
 		napi_complete(napi);
 		return 0;
@@ -432,15 +435,15 @@ static int cpmac_poll(struct napi_struct
 
 		if ((desc->dataflags & CPMAC_EOQ) != 0) {
 			/* The last update to eoq->hw_next didn't happen
-			* soon enough, and the receiver stopped here.
-			*Remember this descriptor so we can restart
-			* the receiver after freeing some space.
-			*/
+			 * soon enough, and the receiver stopped here.
+			 * Remember this descriptor so we can restart
+			 * the receiver after freeing some space.
+			 */
 			if (unlikely(restart)) {
 				if (netif_msg_rx_err(priv))
-					printk(KERN_ERR "%s: poll found a"
-						" duplicate EOQ: %p and %p\n",
-						priv->dev->name, restart, desc);
+					netdev_err(priv->dev, "poll found a"
+						   " duplicate EOQ: %p and %p\n",
+						   restart, desc);
 				goto fatal_error;
 			}
 
@@ -457,25 +460,27 @@ static int cpmac_poll(struct napi_struct
 
 	if (desc != priv->rx_head) {
 		/* We freed some buffers, but not the whole ring,
-		 * add what we did free to the rx list */
+		 * add what we did free to the rx list
+		 */
 		desc->prev->hw_next = (u32)0;
 		priv->rx_head->prev->hw_next = priv->rx_head->mapping;
 	}
 
 	/* Optimization: If we did not actually process an EOQ (perhaps because
 	 * of quota limits), check to see if the tail of the queue has EOQ set.
-	* We should immediately restart in that case so that the receiver can
-	* restart and run in parallel with more packet processing.
-	* This lets us handle slightly larger bursts before running
-	* out of ring space (assuming dev->weight < ring_size) */
+	 * We should immediately restart in that case so that the receiver can
+	 * restart and run in parallel with more packet processing.
+	 * This lets us handle slightly larger bursts before running
+	 * out of ring space (assuming dev->weight < ring_size)
+	 */
 
 	if (!restart &&
 	     (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ))
 		    == CPMAC_EOQ &&
 	     (priv->rx_head->dataflags & CPMAC_OWN) != 0) {
 		/* reset EOQ so the poll loop (above) doesn't try to
-		* restart this when it eventually gets to this descriptor.
-		*/
+		 * restart this when it eventually gets to this descriptor.
+		 */
 		priv->rx_head->prev->dataflags &= ~CPMAC_EOQ;
 		restart = priv->rx_head;
 	}
@@ -484,15 +489,13 @@ static int cpmac_poll(struct napi_struct
 		priv->dev->stats.rx_errors++;
 		priv->dev->stats.rx_fifo_errors++;
 		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx dma ring overrun\n",
-			       priv->dev->name);
+			netdev_warn(priv->dev, "rx dma ring overrun\n");
 
 		if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) {
 			if (netif_msg_drv(priv))
-				printk(KERN_ERR "%s: cpmac_poll is trying to "
-					"restart rx from a descriptor that's "
-					"not free: %p\n",
-					priv->dev->name, restart);
+				netdev_err(priv->dev, "cpmac_poll is trying "
+					"to restart rx from a descriptor "
+					"that's not free: %p\n", restart);
 			goto fatal_error;
 		}
 
@@ -502,11 +505,12 @@ static int cpmac_poll(struct napi_struct
 	priv->rx_head = desc;
 	spin_unlock(&priv->rx_lock);
 	if (unlikely(netif_msg_rx_status(priv)))
-		printk(KERN_DEBUG "%s: poll processed %d packets\n",
-		       priv->dev->name, received);
+		netdev_dbg(priv->dev, "poll processed %d packets\n", received);
+
 	if (processed == 0) {
 		/* we ran out of packets to read,
-		 * revert to interrupt-driven mode */
+		 * revert to interrupt-driven mode
+		 */
 		napi_complete(napi);
 		cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
 		return 0;
@@ -516,16 +520,15 @@ static int cpmac_poll(struct napi_struct
 
 fatal_error:
 	/* Something went horribly wrong.
-	 * Reset hardware to try to recover rather than wedging. */
-
+	 * Reset hardware to try to recover rather than wedging.
+	 */
 	if (netif_msg_drv(priv)) {
-		printk(KERN_ERR "%s: cpmac_poll is confused. "
-				"Resetting hardware\n", priv->dev->name);
+		netdev_err(priv->dev, "cpmac_poll is confused. "
+			   "Resetting hardware\n");
 		cpmac_dump_all_desc(priv->dev);
-		printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
-			priv->dev->name,
-			cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
-			cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
+		netdev_dbg(priv->dev, "RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
+			   cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
+			   cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
 	}
 
 	spin_unlock(&priv->rx_lock);
@@ -537,6 +540,7 @@ fatal_error:
 	cpmac_hw_stop(priv->dev);
 	if (!schedule_work(&priv->reset_work))
 		atomic_dec(&priv->reset_pending);
+
 	return 0;
 
 }
@@ -560,8 +564,8 @@ static int cpmac_start_xmit(struct sk_bu
 	desc = &priv->desc_ring[queue];
 	if (unlikely(desc->dataflags & CPMAC_OWN)) {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: tx dma ring full\n",
-			       dev->name);
+			netdev_warn(dev, "tx dma ring full\n");
+
 		return NETDEV_TX_BUSY;
 	}
 
@@ -575,8 +579,7 @@ static int cpmac_start_xmit(struct sk_bu
 	desc->datalen = len;
 	desc->buflen = len;
 	if (unlikely(netif_msg_tx_queued(priv)))
-		printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb,
-		       skb->len);
+		netdev_dbg(dev, "sending 0x%p, len=%d\n", skb, skb->len);
 	if (unlikely(netif_msg_hw(priv)))
 		cpmac_dump_desc(dev, desc);
 	if (unlikely(netif_msg_pktdata(priv)))
@@ -602,8 +605,8 @@ static void cpmac_end_xmit(struct net_de
 				 DMA_TO_DEVICE);
 
 		if (unlikely(netif_msg_tx_done(priv)))
-			printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name,
-			       desc->skb, desc->skb->len);
+			netdev_dbg(dev, "sent 0x%p, len=%d\n",
+				   desc->skb, desc->skb->len);
 
 		dev_kfree_skb_irq(desc->skb);
 		desc->skb = NULL;
@@ -611,8 +614,7 @@ static void cpmac_end_xmit(struct net_de
 			netif_wake_subqueue(dev, queue);
 	} else {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING
-			       "%s: end_xmit: spurious interrupt\n", dev->name);
+			netdev_warn(dev, "end_xmit: spurious interrupt\n");
 		if (__netif_subqueue_stopped(dev, queue))
 			netif_wake_subqueue(dev, queue);
 	}
@@ -687,14 +689,14 @@ static void cpmac_clear_rx(struct net_de
 	struct cpmac_priv *priv = netdev_priv(dev);
 	struct cpmac_desc *desc;
 	int i;
+
 	if (unlikely(!priv->rx_head))
 		return;
 	desc = priv->rx_head;
 	for (i = 0; i < priv->ring_size; i++) {
 		if ((desc->dataflags & CPMAC_OWN) == 0) {
 			if (netif_msg_rx_err(priv) && net_ratelimit())
-				printk(KERN_WARNING "%s: packet dropped\n",
-				       dev->name);
+				netdev_warn(dev, "packet dropped\n");
 			if (unlikely(netif_msg_hw(priv)))
 				cpmac_dump_desc(dev, desc);
 			desc->dataflags = CPMAC_OWN;
@@ -710,6 +712,7 @@ static void cpmac_clear_tx(struct net_de
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
 	int i;
+
 	if (unlikely(!priv->desc_ring))
 		return;
 	for (i = 0; i < CPMAC_QUEUES; i++) {
@@ -751,16 +754,16 @@ static void cpmac_check_status(struct ne
 	if (rx_code || tx_code) {
 		if (netif_msg_drv(priv) && net_ratelimit()) {
 			/* Can't find any documentation on what these
-			 *error codes actually are. So just log them and hope..
+			 * error codes actually are. So just log them and hope..
 			 */
 			if (rx_code)
-				printk(KERN_WARNING "%s: host error %d on rx "
-				     "channel %d (macstatus %08x), resetting\n",
-				     dev->name, rx_code, rx_channel, macstatus);
+				netdev_warn(dev, "host error %d on rx "
+					"channel %d (macstatus %08x), resetting\n",
+					rx_code, rx_channel, macstatus);
 			if (tx_code)
-				printk(KERN_WARNING "%s: host error %d on tx "
-				     "channel %d (macstatus %08x), resetting\n",
-				     dev->name, tx_code, tx_channel, macstatus);
+				netdev_warn(dev, "host error %d on tx "
+					"channel %d (macstatus %08x), resetting\n",
+					tx_code, tx_channel, macstatus);
 		}
 
 		netif_tx_stop_all_queues(dev);
@@ -785,8 +788,7 @@ static irqreturn_t cpmac_irq(int irq, vo
 	status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
 
 	if (unlikely(netif_msg_intr(priv)))
-		printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name,
-		       status);
+		netdev_dbg(dev, "interrupt status: 0x%08x\n", status);
 
 	if (status & MAC_INT_TX)
 		cpmac_end_xmit(dev, (status & 7));
@@ -815,7 +817,7 @@ static void cpmac_tx_timeout(struct net_
 	dev->stats.tx_errors++;
 	spin_unlock(&priv->lock);
 	if (netif_msg_tx_err(priv) && net_ratelimit())
-		printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
+		netdev_warn(dev, "transmit timeout\n");
 
 	atomic_inc(&priv->reset_pending);
 	barrier();
@@ -829,6 +831,7 @@ static void cpmac_tx_timeout(struct net_
 static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
+
 	if (!(netif_running(dev)))
 		return -EINVAL;
 	if (!priv->phy)
@@ -884,6 +887,7 @@ static int cpmac_set_ringparam(struct ne
 	if (netif_running(dev))
 		return -EBUSY;
 	priv->ring_size = ring->rx_pending;
+
 	return 0;
 }
 
@@ -951,8 +955,8 @@ static int cpmac_open(struct net_device
 	mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
 	if (!request_mem_region(mem->start, resource_size(mem), dev->name)) {
 		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to request registers\n",
-			       dev->name);
+			netdev_err(dev, "failed to request registers\n");
+
 		res = -ENXIO;
 		goto fail_reserve;
 	}
@@ -960,8 +964,8 @@ static int cpmac_open(struct net_device
 	priv->regs = ioremap(mem->start, resource_size(mem));
 	if (!priv->regs) {
 		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to remap registers\n",
-			       dev->name);
+			netdev_err(dev, "failed to remap registers\n");
+
 		res = -ENXIO;
 		goto fail_remap;
 	}
@@ -1003,8 +1007,8 @@ static int cpmac_open(struct net_device
 	res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev);
 	if (res) {
 		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to obtain irq\n",
-			       dev->name);
+			netdev_err(dev, "failed to obtain irq\n");
+
 		goto fail_irq;
 	}
 
@@ -1077,6 +1081,7 @@ static int cpmac_stop(struct net_device
 	dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) *
 			  (CPMAC_QUEUES + priv->ring_size),
 			  priv->desc_ring, priv->dma_ring);
+
 	return 0;
 }
 
@@ -1121,10 +1126,11 @@ static int cpmac_probe(struct platform_d
 
 	if (phy_id == PHY_MAX_ADDR) {
 		dev_err(&pdev->dev, "no PHY present, falling back "
-					"to switch on MDIO bus 0\n");
+			"to switch on MDIO bus 0\n");
 		strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
 		phy_id = pdev->id;
 	}
+	mdio_bus_id[sizeof(mdio_bus_id) - 1] = '\0';
 
 	dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
 	if (!dev)
@@ -1137,7 +1143,7 @@ static int cpmac_probe(struct platform_d
 	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
 	if (!mem) {
 		rc = -ENODEV;
-		goto fail;
+		goto out;
 	}
 
 	dev->irq = platform_get_irq_byname(pdev, "irq");
@@ -1162,44 +1168,48 @@ static int cpmac_probe(struct platform_d
 
 	if (IS_ERR(priv->phy)) {
 		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: Could not attach to PHY\n",
-			       dev->name);
+			dev_err(&pdev->dev, "Could not attach to PHY\n");
+
 		rc = PTR_ERR(priv->phy);
-		goto fail;
+		goto out;
 	}
 
 	rc = register_netdev(dev);
 	if (rc) {
-		printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
-		       dev->name);
+		dev_err(&pdev->dev, "Could not register net device\n");
 		goto fail;
 	}
 
 	if (netif_msg_probe(priv)) {
-		printk(KERN_INFO
-		       "cpmac: device %s (regs: %p, irq: %d, phy: %s, "
-		       "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq,
-		       priv->phy_name, dev->dev_addr);
+		dev_info(&pdev->dev, "regs: %p, irq: %d, phy: %s, "
+			 "mac: %pM\n", (void *)mem->start, dev->irq,
+			 priv->phy_name, dev->dev_addr);
 	}
+
 	return 0;
 
 fail:
 	free_netdev(dev);
+out:
 	return rc;
 }
 
 static int cpmac_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+
 	unregister_netdev(dev);
 	free_netdev(dev);
+
 	return 0;
 }
 
 static struct platform_driver cpmac_driver = {
-	.driver.name = "cpmac",
-	.driver.owner = THIS_MODULE,
-	.probe = cpmac_probe,
+	.driver = {
+		.name 	= "cpmac",
+		.owner 	= THIS_MODULE,
+	},
+	.probe 	= cpmac_probe,
 	.remove = cpmac_remove,
 };
 
@@ -1221,7 +1231,7 @@ int cpmac_init(void)
 	cpmac_mii->priv = ioremap(AR7_REGS_MDIO, 256);
 
 	if (!cpmac_mii->priv) {
-		printk(KERN_ERR "Can't ioremap mdio registers\n");
+		pr_err("Can't ioremap mdio registers\n");
 		res = -ENXIO;
 		goto fail_alloc;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw_ale.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw_ale.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw_ale.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw_ale.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,8 +25,6 @@
 #include "cpsw_ale.h"
 
 #define BITMASK(bits)		(BIT(bits) - 1)
-#define ALE_ENTRY_BITS		68
-#define ALE_ENTRY_WORDS	DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
 
 #define ALE_VERSION_MAJOR(rev)	((rev >> 8) & 0xff)
 #define ALE_VERSION_MINOR(rev)	(rev & 0xff)
@@ -763,3 +761,13 @@ int cpsw_ale_destroy(struct cpsw_ale *al
 	kfree(ale);
 	return 0;
 }
+
+void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
+{
+	int i;
+
+	for (i = 0; i < ale->params.ale_entries; i++) {
+		cpsw_ale_read(ale, i, data);
+		data += ALE_ENTRY_WORDS;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw_ale.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw_ale.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw_ale.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw_ale.h	2014-09-28 17:29:07.000000000 -0400
@@ -80,6 +80,9 @@ enum cpsw_ale_port_state {
 #define ALE_MCAST_FWD_LEARN		2
 #define ALE_MCAST_FWD_2			3
 
+#define ALE_ENTRY_BITS		68
+#define ALE_ENTRY_WORDS	DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
+
 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params);
 int cpsw_ale_destroy(struct cpsw_ale *ale);
 
@@ -104,5 +107,6 @@ int cpsw_ale_del_vlan(struct cpsw_ale *a
 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
 int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
 			 int control, int value);
+void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpsw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpsw.c	2014-09-28 17:29:07.000000000 -0400
@@ -699,6 +699,28 @@ static void cpsw_rx_handler(void *token,
 	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
 
 	if (unlikely(status < 0) || unlikely(!netif_running(ndev))) {
+		bool ndev_status = false;
+		struct cpsw_slave *slave = priv->slaves;
+		int n;
+
+		if (priv->data.dual_emac) {
+			/* In dual emac mode check for all interfaces */
+			for (n = priv->data.slaves; n; n--, slave++)
+				if (netif_running(slave->ndev))
+					ndev_status = true;
+		}
+
+		if (ndev_status && (status >= 0)) {
+			/* The packet received is for the interface which
+			 * is already down and the other interface is up
+			 * and running, intead of freeing which results
+			 * in reducing of the number of rx descriptor in
+			 * DMA engine, requeue skb back to cpdma.
+			 */
+			new_skb = skb;
+			goto requeue;
+		}
+
 		/* the interface is going down, skbs are purged */
 		dev_kfree_skb_any(skb);
 		return;
@@ -717,6 +739,7 @@ static void cpsw_rx_handler(void *token,
 		new_skb = skb;
 	}
 
+requeue:
 	ret = cpdma_chan_submit(priv->rxch, new_skb, new_skb->data,
 			skb_tailroom(new_skb), 0);
 	if (WARN_ON(ret < 0))
@@ -884,14 +907,16 @@ static int cpsw_set_coalesce(struct net_
 	u32 addnl_dvdr = 1;
 	u32 coal_intvl = 0;
 
-	if (!coal->rx_coalesce_usecs)
-		return -EINVAL;
-
 	coal_intvl = coal->rx_coalesce_usecs;
 
 	int_ctrl =  readl(&priv->wr_regs->int_control);
 	prescale = priv->bus_freq_mhz * 4;
 
+	if (!coal->rx_coalesce_usecs) {
+		int_ctrl &= ~(CPSW_INTPRESCALE_MASK | CPSW_INTPACEEN);
+		goto update_return;
+	}
+
 	if (coal_intvl < CPSW_CMINTMIN_INTVL)
 		coal_intvl = CPSW_CMINTMIN_INTVL;
 
@@ -919,6 +944,8 @@ static int cpsw_set_coalesce(struct net_
 	int_ctrl |= CPSW_INTPACEEN;
 	int_ctrl &= (~CPSW_INTPRESCALE_MASK);
 	int_ctrl |= (prescale & CPSW_INTPRESCALE_MASK);
+
+update_return:
 	writel(int_ctrl, &priv->wr_regs->int_control);
 
 	cpsw_notice(priv, timer, "Set coalesce to %d usecs.\n", coal_intvl);
@@ -999,17 +1026,6 @@ static void cpsw_get_ethtool_stats(struc
 	}
 }
 
-static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
-{
-	static char *leader = "........................................";
-
-	if (!val)
-		return 0;
-	else
-		return snprintf(buf, maxlen, "%s %s %10d\n", name,
-				leader + strlen(name), val);
-}
-
 static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
 {
 	u32 i;
@@ -1671,14 +1687,34 @@ static const struct net_device_ops cpsw_
 	.ndo_vlan_rx_kill_vid	= cpsw_ndo_vlan_rx_kill_vid,
 };
 
+static int cpsw_get_regs_len(struct net_device *ndev)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+
+	return priv->data.ale_entries * ALE_ENTRY_WORDS * sizeof(u32);
+}
+
+static void cpsw_get_regs(struct net_device *ndev,
+			  struct ethtool_regs *regs, void *p)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	u32 *reg = p;
+
+	/* update CPSW IP version */
+	regs->version = priv->version;
+
+	cpsw_ale_dump(priv->ale, reg);
+}
+
 static void cpsw_get_drvinfo(struct net_device *ndev,
 			     struct ethtool_drvinfo *info)
 {
 	struct cpsw_priv *priv = netdev_priv(ndev);
 
-	strlcpy(info->driver, "TI CPSW Driver v1.0", sizeof(info->driver));
+	strlcpy(info->driver, "cpsw", sizeof(info->driver));
 	strlcpy(info->version, "1.0", sizeof(info->version));
 	strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info));
+	info->regdump_len = cpsw_get_regs_len(ndev);
 }
 
 static u32 cpsw_get_msglevel(struct net_device *ndev)
@@ -1786,6 +1822,8 @@ static const struct ethtool_ops cpsw_eth
 	.get_ethtool_stats	= cpsw_get_ethtool_stats,
 	.get_wol	= cpsw_get_wol,
 	.set_wol	= cpsw_set_wol,
+	.get_regs_len	= cpsw_get_regs_len,
+	.get_regs	= cpsw_get_regs,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
@@ -2296,10 +2334,19 @@ static int cpsw_suspend(struct device *d
 	struct net_device	*ndev = platform_get_drvdata(pdev);
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 
-	if (netif_running(ndev))
-		cpsw_ndo_stop(ndev);
+	if (priv->data.dual_emac) {
+		int i;
 
-	for_each_slave(priv, soft_reset_slave);
+		for (i = 0; i < priv->data.slaves; i++) {
+			if (netif_running(priv->slaves[i].ndev))
+				cpsw_ndo_stop(priv->slaves[i].ndev);
+			soft_reset_slave(priv->slaves + i);
+		}
+	} else {
+		if (netif_running(ndev))
+			cpsw_ndo_stop(ndev);
+		for_each_slave(priv, soft_reset_slave);
+	}
 
 	pm_runtime_put_sync(&pdev->dev);
 
@@ -2313,14 +2360,24 @@ static int cpsw_resume(struct device *de
 {
 	struct platform_device	*pdev = to_platform_device(dev);
 	struct net_device	*ndev = platform_get_drvdata(pdev);
+	struct cpsw_priv	*priv = netdev_priv(ndev);
 
 	pm_runtime_get_sync(&pdev->dev);
 
 	/* Select default pin state */
 	pinctrl_pm_select_default_state(&pdev->dev);
 
-	if (netif_running(ndev))
-		cpsw_ndo_open(ndev);
+	if (priv->data.dual_emac) {
+		int i;
+
+		for (i = 0; i < priv->data.slaves; i++) {
+			if (netif_running(priv->slaves[i].ndev))
+				cpsw_ndo_open(priv->slaves[i].ndev);
+		}
+	} else {
+		if (netif_running(ndev))
+			cpsw_ndo_open(ndev);
+	}
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpts.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpts.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/cpts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/cpts.c	2014-09-28 17:29:07.000000000 -0400
@@ -256,23 +256,21 @@ static int cpts_match(struct sk_buff *sk
 		      u16 ts_seqid, u8 ts_msgtype)
 {
 	u16 *seqid;
-	unsigned int offset;
+	unsigned int offset = 0;
 	u8 *msgtype, *data = skb->data;
 
-	switch (ptp_class) {
-	case PTP_CLASS_V1_IPV4:
-	case PTP_CLASS_V2_IPV4:
-		offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-		break;
-	case PTP_CLASS_V1_IPV6:
-	case PTP_CLASS_V2_IPV6:
-		offset = OFF_PTP6;
+	if (ptp_class & PTP_CLASS_VLAN)
+		offset += VLAN_HLEN;
+
+	switch (ptp_class & PTP_CLASS_PMASK) {
+	case PTP_CLASS_IPV4:
+		offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
 		break;
-	case PTP_CLASS_V2_L2:
-		offset = ETH_HLEN;
+	case PTP_CLASS_IPV6:
+		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
 		break;
-	case PTP_CLASS_V2_VLAN:
-		offset = ETH_HLEN + VLAN_HLEN;
+	case PTP_CLASS_L2:
+		offset += ETH_HLEN;
 		break;
 	default:
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/davinci_mdio.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/davinci_mdio.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/davinci_mdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/davinci_mdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mdio.h>
 #include <linux/pinctrl/consumer.h>
 
 /*
@@ -95,6 +96,10 @@ struct davinci_mdio_data {
 	struct mii_bus	*bus;
 	bool		suspended;
 	unsigned long	access_time; /* jiffies */
+	/* Indicates that driver shouldn't modify phy_mask in case
+	 * if MDIO bus is registered from DT.
+	 */
+	bool		skip_scan;
 };
 
 static void __davinci_mdio_reset(struct davinci_mdio_data *data)
@@ -144,6 +149,9 @@ static int davinci_mdio_reset(struct mii
 	dev_info(data->dev, "davinci mdio revision %d.%d\n",
 		 (ver >> 8) & 0xff, ver & 0xff);
 
+	if (data->skip_scan)
+		return 0;
+
 	/* get phy mask from the alive register */
 	phy_mask = __raw_readl(&data->regs->alive);
 	if (phy_mask) {
@@ -369,8 +377,17 @@ static int davinci_mdio_probe(struct pla
 		goto bail_out;
 	}
 
-	/* register the mii bus */
-	ret = mdiobus_register(data->bus);
+	/* register the mii bus
+	 * Create PHYs from DT only in case if PHY child nodes are explicitly
+	 * defined to support backward compatibility with DTs which assume that
+	 * Davinci MDIO will always scan the bus for PHYs detection.
+	 */
+	if (dev->of_node && of_get_child_count(dev->of_node)) {
+		data->skip_scan = true;
+		ret = of_mdiobus_register(data->bus, dev->of_node);
+	} else {
+		ret = mdiobus_register(data->bus);
+	}
 	if (ret)
 		goto bail_out;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,7 +5,7 @@
 config NET_VENDOR_TI
 	bool "Texas Instruments (TI) devices"
 	default y
-	depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
+	depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX || ARCH_KEYSTONE))
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -32,7 +32,7 @@ config TI_DAVINCI_EMAC
 
 config TI_DAVINCI_MDIO
 	tristate "TI DaVinci MDIO Support"
-	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX )
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX || ARCH_KEYSTONE )
 	select PHYLIB
 	---help---
 	  This driver supports TI's DaVinci MDIO module.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/tlan.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/tlan.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/tlan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/tlan.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,10 +69,6 @@ MODULE_AUTHOR("Maintainer: Samuel Chessm
 MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
 MODULE_LICENSE("GPL");
 
-
-/* Define this to enable Link beat monitoring */
-#undef MONITOR
-
 /* Turn on debugging. See Documentation/networking/tlan.txt for details */
 static  int		debug;
 module_param(debug, int, 0);
@@ -107,8 +103,10 @@ static struct board {
 	{ "Compaq Netelligent 10/100 TX Embedded UTP",
 	  TLAN_ADAPTER_NONE, 0x83 },
 	{ "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
-	{ "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
-	{ "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
+	{ "Olicom OC-2325", TLAN_ADAPTER_ACTIVITY_LED |
+	  TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
+	{ "Olicom OC-2326", TLAN_ADAPTER_ACTIVITY_LED |
+	  TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
 	{ "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
 	{ "Compaq Netelligent 10 T/2 PCI UTP/coax", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq NetFlex-3/E",
@@ -118,7 +116,7 @@ static struct board {
 	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
 };
 
-static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = {
+static const struct pci_device_id tlan_pci_tbl[] = {
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
@@ -192,9 +190,7 @@ static void	tlan_phy_power_up(struct net
 static void	tlan_phy_reset(struct net_device *);
 static void	tlan_phy_start_link(struct net_device *);
 static void	tlan_phy_finish_auto_neg(struct net_device *);
-#ifdef MONITOR
-static void     tlan_phy_monitor(struct net_device *);
-#endif
+static void     tlan_phy_monitor(unsigned long);
 
 /*
   static int	tlan_phy_nop(struct net_device *);
@@ -337,6 +333,7 @@ static void tlan_stop(struct net_device
 {
 	struct tlan_priv *priv = netdev_priv(dev);
 
+	del_timer_sync(&priv->media_timer);
 	tlan_read_and_clear_stats(dev, TLAN_RECORD);
 	outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
 	/* Reset and power down phy */
@@ -368,8 +365,10 @@ static int tlan_suspend(struct pci_dev *
 static int tlan_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	int rc = pci_enable_device(pdev);
 
-	pci_set_power_state(pdev, PCI_D0);
+	if (rc)
+		return rc;
 	pci_restore_state(pdev);
 	pci_enable_wake(pdev, PCI_D0, 0);
 	netif_device_attach(dev);
@@ -781,7 +780,43 @@ static const struct net_device_ops tlan_
 #endif
 };
 
+static void tlan_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct tlan_priv *priv = netdev_priv(dev);
+
+	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+	if (priv->pci_dev)
+		strlcpy(info->bus_info, pci_name(priv->pci_dev),
+			sizeof(info->bus_info));
+	else
+		strlcpy(info->bus_info, "EISA",	sizeof(info->bus_info));
+	info->eedump_len = TLAN_EEPROM_SIZE;
+}
+
+static int tlan_get_eeprom_len(struct net_device *dev)
+{
+	return TLAN_EEPROM_SIZE;
+}
+
+static int tlan_get_eeprom(struct net_device *dev,
+			   struct ethtool_eeprom *eeprom, u8 *data)
+{
+	int i;
+
+	for (i = 0; i < TLAN_EEPROM_SIZE; i++)
+		if (tlan_ee_read_byte(dev, i, &data[i]))
+			return -EIO;
 
+	return 0;
+}
+
+static const struct ethtool_ops tlan_ethtool_ops = {
+	.get_drvinfo	= tlan_get_drvinfo,
+	.get_link	= ethtool_op_get_link,
+	.get_eeprom_len	= tlan_get_eeprom_len,
+	.get_eeprom	= tlan_get_eeprom,
+};
 
 /***************************************************************
  *	tlan_init
@@ -830,7 +865,7 @@ static int tlan_init(struct net_device *
 		priv->rx_list_dma + sizeof(struct tlan_list)*TLAN_NUM_RX_LISTS;
 
 	err = 0;
-	for (i = 0;  i < 6 ; i++)
+	for (i = 0; i < ETH_ALEN; i++)
 		err |= tlan_ee_read_byte(dev,
 					 (u8) priv->adapter->addr_ofs + i,
 					 (u8 *) &dev->dev_addr[i]);
@@ -838,12 +873,20 @@ static int tlan_init(struct net_device *
 		pr_err("%s: Error reading MAC from eeprom: %d\n",
 		       dev->name, err);
 	}
-	dev->addr_len = 6;
+	/* Olicom OC-2325/OC-2326 have the address byte-swapped */
+	if (priv->adapter->addr_ofs == 0xf8) {
+		for (i = 0; i < ETH_ALEN; i += 2) {
+			char tmp = dev->dev_addr[i];
+			dev->dev_addr[i] = dev->dev_addr[i + 1];
+			dev->dev_addr[i + 1] = tmp;
+		}
+	}
 
 	netif_carrier_off(dev);
 
 	/* Device methods */
 	dev->netdev_ops = &tlan_netdev_ops;
+	dev->ethtool_ops = &tlan_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	return 0;
@@ -886,6 +929,7 @@ static int tlan_open(struct net_device *
 	}
 
 	init_timer(&priv->timer);
+	init_timer(&priv->media_timer);
 
 	tlan_start(dev);
 
@@ -1156,9 +1200,6 @@ static irqreturn_t tlan_handle_interrupt
 
 static int tlan_close(struct net_device *dev)
 {
-	struct tlan_priv *priv = netdev_priv(dev);
-
-	priv->neg_be_verbose = 0;
 	tlan_stop(dev);
 
 	free_irq(dev->irq, dev);
@@ -1808,11 +1849,6 @@ static void tlan_timer(unsigned long dat
 	priv->timer.function = NULL;
 
 	switch (priv->timer_type) {
-#ifdef MONITOR
-	case TLAN_TIMER_LINK_BEAT:
-		tlan_phy_monitor(dev);
-		break;
-#endif
 	case TLAN_TIMER_PHY_PDOWN:
 		tlan_phy_power_down(dev);
 		break;
@@ -1856,8 +1892,6 @@ static void tlan_timer(unsigned long dat
 }
 
 
-
-
 /*****************************************************************************
 ******************************************************************************
 
@@ -2205,7 +2239,9 @@ tlan_reset_adapter(struct net_device *de
 		}
 	}
 
-	if (priv->phy_num == 0)
+	/* don't power down internal PHY if we're going to use it */
+	if (priv->phy_num == 0 ||
+	   (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))
 		data |= TLAN_NET_CFG_PHY_EN;
 	tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
 
@@ -2255,42 +2291,39 @@ tlan_finish_reset(struct net_device *dev
 		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
 		udelay(1000);
 		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
-		if ((status & MII_GS_LINK) &&
-		    /* We only support link info on Nat.Sem. PHY's */
-		    (tlphy_id1 == NAT_SEM_ID1) &&
-		    (tlphy_id2 == NAT_SEM_ID2)) {
-			tlan_mii_read_reg(dev, phy, MII_AN_LPA, &partner);
-			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR, &tlphy_par);
-
-			netdev_info(dev,
-				    "Link active with %s %uMbps %s-Duplex\n",
-				    !(tlphy_par & TLAN_PHY_AN_EN_STAT)
-				    ? "forced" : "Autonegotiation enabled,",
-				    tlphy_par & TLAN_PHY_SPEED_100
-				    ? 100 : 10,
-				    tlphy_par & TLAN_PHY_DUPLEX_FULL
-				    ? "Full" : "Half");
+		if (status & MII_GS_LINK) {
+			/* We only support link info on Nat.Sem. PHY's */
+			if ((tlphy_id1 == NAT_SEM_ID1) &&
+			    (tlphy_id2 == NAT_SEM_ID2)) {
+				tlan_mii_read_reg(dev, phy, MII_AN_LPA,
+					&partner);
+				tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR,
+					&tlphy_par);
 
-			if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
-				netdev_info(dev, "Partner capability:");
-				for (i = 5; i < 10; i++)
-					if (partner & (1 << i))
-						pr_cont(" %s", media[i-5]);
-				pr_cont("\n");
-			}
+				netdev_info(dev,
+					"Link active, %s %uMbps %s-Duplex\n",
+					!(tlphy_par & TLAN_PHY_AN_EN_STAT)
+					? "forced" : "Autonegotiation enabled,",
+					tlphy_par & TLAN_PHY_SPEED_100
+					? 100 : 10,
+					tlphy_par & TLAN_PHY_DUPLEX_FULL
+					? "Full" : "Half");
 
-			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
-					TLAN_LED_LINK);
-#ifdef MONITOR
-			/* We have link beat..for now anyway */
-			priv->link = 1;
-			/*Enabling link beat monitoring */
-			tlan_set_timer(dev, (10*HZ), TLAN_TIMER_LINK_BEAT);
-#endif
-		} else if (status & MII_GS_LINK)  {
-			netdev_info(dev, "Link active\n");
-			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
-					TLAN_LED_LINK);
+				if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
+					netdev_info(dev, "Partner capability:");
+					for (i = 5; i < 10; i++)
+						if (partner & (1 << i))
+							pr_cont(" %s",
+								media[i-5]);
+					pr_cont("\n");
+				}
+			} else
+				netdev_info(dev, "Link active\n");
+			/* Enabling link beat monitoring */
+			priv->media_timer.function = tlan_phy_monitor;
+			priv->media_timer.data = (unsigned long) dev;
+			priv->media_timer.expires = jiffies + HZ;
+			add_timer(&priv->media_timer);
 		}
 	}
 
@@ -2312,6 +2345,7 @@ tlan_finish_reset(struct net_device *dev
 			     dev->base_addr + TLAN_HOST_CMD + 1);
 		outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM);
 		outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD);
+		tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
 		netif_carrier_on(dev);
 	} else {
 		netdev_info(dev, "Link inactive, will retry in 10 secs...\n");
@@ -2494,9 +2528,10 @@ static void tlan_phy_power_down(struct n
 	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
 	tlan_mii_sync(dev->base_addr);
 	tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
-	if ((priv->phy_num == 0) &&
-	    (priv->phy[1] != TLAN_PHY_NONE) &&
-	    (!(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))) {
+	if ((priv->phy_num == 0) && (priv->phy[1] != TLAN_PHY_NONE)) {
+		/* if using internal PHY, the external PHY must be powered on */
+		if (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10)
+			value = MII_GC_ISOLATE; /* just isolate it from MII */
 		tlan_mii_sync(dev->base_addr);
 		tlan_mii_write_reg(dev, priv->phy[1], MII_GEN_CTL, value);
 	}
@@ -2538,6 +2573,7 @@ static void tlan_phy_reset(struct net_de
 	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		phy;
 	u16		value;
+	unsigned long timeout = jiffies + HZ;
 
 	phy = priv->phy[priv->phy_num];
 
@@ -2545,9 +2581,13 @@ static void tlan_phy_reset(struct net_de
 	tlan_mii_sync(dev->base_addr);
 	value = MII_GC_LOOPBK | MII_GC_RESET;
 	tlan_mii_write_reg(dev, phy, MII_GEN_CTL, value);
-	tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
-	while (value & MII_GC_RESET)
+	do {
 		tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
+		if (time_after(jiffies, timeout)) {
+			netdev_err(dev, "PHY reset timeout\n");
+			return;
+		}
+	} while (value & MII_GC_RESET);
 
 	/* Wait for 500 ms and initialize.
 	 * I don't remember why I wait this long.
@@ -2653,7 +2693,6 @@ static void tlan_phy_finish_auto_neg(str
 	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		an_adv;
 	u16		an_lpa;
-	u16		data;
 	u16		mode;
 	u16		phy;
 	u16		status;
@@ -2668,13 +2707,7 @@ static void tlan_phy_finish_auto_neg(str
 		/* Wait for 8 sec to give the process
 		 * more time.  Perhaps we should fail after a while.
 		 */
-		if (!priv->neg_be_verbose++) {
-			pr_info("Giving autonegotiation more time.\n");
-			pr_info("Please check that your adapter has\n");
-			pr_info("been properly connected to a HUB or Switch.\n");
-			pr_info("Trying to establish link in the background...\n");
-		}
-		tlan_set_timer(dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN);
+		tlan_set_timer(dev, 2 * HZ, TLAN_TIMER_PHY_FINISH_AN);
 		return;
 	}
 
@@ -2687,13 +2720,11 @@ static void tlan_phy_finish_auto_neg(str
 	else if (!(mode & 0x0080) && (mode & 0x0040))
 		priv->tlan_full_duplex = true;
 
+	/* switch to internal PHY for 10 Mbps */
 	if ((!(mode & 0x0180)) &&
 	    (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) &&
 	    (priv->phy_num != 0)) {
 		priv->phy_num = 0;
-		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
-			| TLAN_NET_CFG_PHY_EN;
-		tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
 		tlan_set_timer(dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN);
 		return;
 	}
@@ -2717,7 +2748,6 @@ static void tlan_phy_finish_auto_neg(str
 
 }
 
-#ifdef MONITOR
 
 /*********************************************************************
  *
@@ -2727,18 +2757,18 @@ static void tlan_phy_finish_auto_neg(str
  *	      None
  *
  *     Params:
- *	      dev	     The device structure of this device.
+ *	      data	     The device structure of this device.
  *
  *
  *     This function monitors PHY condition by reading the status
- *     register via the MII bus. This can be used to give info
- *     about link changes (up/down), and possible switch to alternate
- *     media.
+ *     register via the MII bus, controls LINK LED and notifies the
+ *     kernel about link state.
  *
  *******************************************************************/
 
-void tlan_phy_monitor(struct net_device *dev)
+static void tlan_phy_monitor(unsigned long data)
 {
+	struct net_device *dev = (struct net_device *) data;
 	struct tlan_priv *priv = netdev_priv(dev);
 	u16     phy;
 	u16     phy_status;
@@ -2750,30 +2780,40 @@ void tlan_phy_monitor(struct net_device
 
 	/* Check if link has been lost */
 	if (!(phy_status & MII_GS_LINK)) {
-		if (priv->link) {
-			priv->link = 0;
+		if (netif_carrier_ok(dev)) {
 			printk(KERN_DEBUG "TLAN: %s has lost link\n",
 			       dev->name);
+			tlan_dio_write8(dev->base_addr, TLAN_LED_REG, 0);
 			netif_carrier_off(dev);
-			tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
-			return;
+			if (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) {
+				/* power down internal PHY */
+				u16 data = MII_GC_PDOWN | MII_GC_LOOPBK |
+					   MII_GC_ISOLATE;
+
+				tlan_mii_sync(dev->base_addr);
+				tlan_mii_write_reg(dev, priv->phy[0],
+						   MII_GEN_CTL, data);
+				/* set to external PHY */
+				priv->phy_num = 1;
+				/* restart autonegotiation */
+				tlan_set_timer(dev, 4 * HZ / 10,
+					       TLAN_TIMER_PHY_PDOWN);
+				return;
+			}
 		}
 	}
 
 	/* Link restablished? */
-	if ((phy_status & MII_GS_LINK) && !priv->link) {
-		priv->link = 1;
+	if ((phy_status & MII_GS_LINK) && !netif_carrier_ok(dev)) {
+		tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
 		printk(KERN_DEBUG "TLAN: %s has reestablished link\n",
 		       dev->name);
 		netif_carrier_on(dev);
 	}
-
-	/* Setup a new monitor */
-	tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
+	priv->media_timer.expires = jiffies + HZ;
+	add_timer(&priv->media_timer);
 }
 
-#endif /* MONITOR */
-
 
 /*****************************************************************************
 ******************************************************************************
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/ti/tlan.h linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/tlan.h
--- linux-libre-3.16-gnu/drivers/net/ethernet/ti/tlan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/ti/tlan.h	2014-09-28 17:29:07.000000000 -0400
@@ -195,6 +195,7 @@ struct tlan_priv {
 	u32			timer_set_at;
 	u32			timer_type;
 	struct timer_list	timer;
+	struct timer_list	media_timer;
 	struct board		*adapter;
 	u32			adapter_rev;
 	u32			aui;
@@ -206,9 +207,7 @@ struct tlan_priv {
 	u8			tlan_rev;
 	u8			tlan_full_duplex;
 	spinlock_t		lock;
-	u8			link;
 	struct work_struct			tlan_tqueue;
-	u8			neg_be_verbose;
 };
 
 
@@ -219,7 +218,6 @@ struct tlan_priv {
 	 *
 	 ****************************************************************/
 
-#define TLAN_TIMER_LINK_BEAT		1
 #define TLAN_TIMER_ACTIVITY		2
 #define TLAN_TIMER_PHY_PDOWN		3
 #define TLAN_TIMER_PHY_PUP		4
@@ -241,6 +239,7 @@ struct tlan_priv {
 #define TLAN_EEPROM_ACK		0
 #define TLAN_EEPROM_STOP	1
 
+#define TLAN_EEPROM_SIZE	256
 
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/tile/tilegx.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tile/tilegx.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/tile/tilegx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tile/tilegx.c	2014-09-28 17:29:07.000000000 -0400
@@ -2201,8 +2201,8 @@ static void tile_net_dev_init(const char
 	/* Allocate the device structure.  Normally, "name" is a
 	 * template, instantiated by register_netdev(), but not for us.
 	 */
-	dev = alloc_netdev_mqs(sizeof(*priv), name, tile_net_setup,
-			       NR_CPUS, 1);
+	dev = alloc_netdev_mqs(sizeof(*priv), name, NET_NAME_UNKNOWN,
+			       tile_net_setup, NR_CPUS, 1);
 	if (!dev) {
 		pr_err("alloc_netdev_mqs(%s) failed\n", name);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/tile/tilepro.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tile/tilepro.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/tile/tilepro.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/tile/tilepro.c	2014-09-28 17:29:07.000000000 -0400
@@ -2292,7 +2292,8 @@ static struct net_device *tile_net_dev_i
 	 * tile_net_setup(), and saves "name".  Normally, "name" is a
 	 * template, instantiated by register_netdev(), but not for us.
 	 */
-	dev = alloc_netdev(sizeof(*priv), name, tile_net_setup);
+	dev = alloc_netdev(sizeof(*priv), name, NET_NAME_UNKNOWN,
+			   tile_net_setup);
 	if (!dev) {
 		pr_err("alloc_netdev(%s) failed\n", name);
 		return NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c	2014-09-28 17:29:07.000000000 -0400
@@ -723,13 +723,10 @@ static int gelic_wl_get_scan(struct net_
 		/* If a scan in progress, caller should call me again */
 		ret = -EAGAIN;
 		goto out;
-		break;
-
 	case GELIC_WL_SCAN_STAT_INIT:
 		/* last scan request failed or never issued */
 		ret = -ENODEV;
 		goto out;
-		break;
 	case GELIC_WL_SCAN_STAT_GOT_LIST:
 		/* ok, use current list */
 		break;
@@ -1831,25 +1828,18 @@ static const char *wpasecstr(enum gelic_
 	switch (sec) {
 	case GELIC_EURUS_WPA_SEC_NONE:
 		return "NONE";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP:
 		return "WPA_TKIP_TKIP";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES:
 		return "WPA_TKIP_AES";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA_AES_AES:
 		return "WPA_AES_AES";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP:
 		return "WPA2_TKIP_TKIP";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES:
 		return "WPA2_TKIP_AES";
-		break;
 	case GELIC_EURUS_WPA_SEC_WPA2_AES_AES:
 		return "WPA2_AES_AES";
-		break;
 	}
 	return "";
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/spider_net.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/spider_net.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/spider_net.c	2014-08-07 04:52:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/spider_net.c	2014-09-28 21:34:24.000000000 -0400
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(tx_descriptors, "number
 
 char spider_net_driver_name[] = "spidernet";
 
-static DEFINE_PCI_DEVICE_TABLE(spider_net_pci_tbl) = {
+static const struct pci_device_id spider_net_pci_tbl[] = {
 	{ PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ 0, }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/tc35815.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/tc35815.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/toshiba/tc35815.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/toshiba/tc35815.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,7 @@ static const struct {
 	{ "TOSHIBA TC35815/TX4939" },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(tc35815_pci_tbl) = {
+static const struct pci_device_id tc35815_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815CF), .driver_data = TC35815CF },
 	{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_NWU), .driver_data = TC35815_NWU },
 	{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/via/via-rhine.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/via/via-rhine.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/via/via-rhine.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/via/via-rhine.c	2014-09-28 17:29:07.000000000 -0400
@@ -273,7 +273,7 @@ enum rhine_quirks {
 /* Beware of PCI posted writes */
 #define IOSYNC	do { ioread8(ioaddr + StationAddr); } while (0)
 
-static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = {
+static const struct pci_device_id rhine_pci_tbl[] = {
 	{ 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, },	/* VT86C100A */
 	{ 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, },	/* VT6102 */
 	{ 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, },	/* 6105{,L,LOM} */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/via/via-velocity.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/via/via-velocity.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/via/via-velocity.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/via/via-velocity.c	2014-09-28 17:29:07.000000000 -0400
@@ -381,7 +381,7 @@ static struct velocity_info_tbl chip_inf
  *	device driver. Used for hotplug autoloading.
  */
 
-static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = {
+static const struct pci_device_id velocity_pci_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
 	{ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/ll_temac_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/ll_temac_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/ll_temac_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/ll_temac_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,7 @@ void temac_iow(struct temac_local *lp, i
 
 int temac_indirect_busywait(struct temac_local *lp)
 {
-	long end = jiffies + 2;
+	unsigned long end = jiffies + 2;
 
 	while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) {
 		if (time_before_eq(end, jiffies)) {
@@ -1148,8 +1148,7 @@ static int temac_of_remove(struct platfo
 	temac_mdio_teardown(lp);
 	unregister_netdev(ndev);
 	sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
-	if (lp->phy_node)
-		of_node_put(lp->phy_node);
+	of_node_put(lp->phy_node);
 	lp->phy_node = NULL;
 	iounmap(lp->regs);
 	if (lp->sdma_regs)
@@ -1171,7 +1170,6 @@ static struct platform_driver temac_of_d
 	.probe = temac_of_probe,
 	.remove = temac_of_remove,
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "xilinx_temac",
 		.of_match_table = temac_of_match,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_main.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -1630,8 +1630,7 @@ static int axienet_of_remove(struct plat
 	axienet_mdio_teardown(lp);
 	unregister_netdev(ndev);
 
-	if (lp->phy_node)
-		of_node_put(lp->phy_node);
+	of_node_put(lp->phy_node);
 	lp->phy_node = NULL;
 
 	iounmap(lp->regs);
@@ -1646,7 +1645,6 @@ static struct platform_driver axienet_of
 	.probe = axienet_of_probe,
 	.remove = axienet_of_remove,
 	.driver = {
-		 .owner = THIS_MODULE,
 		 .name = "xilinx_axienet",
 		 .of_match_table = axienet_of_match,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,7 +19,7 @@
 /* Wait till MDIO interface is ready to accept a new transaction.*/
 int axienet_mdio_wait_until_ready(struct axienet_local *lp)
 {
-	long end = jiffies + 2;
+	unsigned long end = jiffies + 2;
 	while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) &
 		 XAE_MDIO_MCR_READY_MASK)) {
 		if (time_before_eq(end, jiffies)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_emaclite.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_emaclite.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/xilinx/xilinx_emaclite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xilinx/xilinx_emaclite.c	2014-09-28 17:29:07.000000000 -0400
@@ -695,7 +695,7 @@ static irqreturn_t xemaclite_interrupt(i
 
 static int xemaclite_mdio_wait(struct net_local *lp)
 {
-	long end = jiffies + 2;
+	unsigned long end = jiffies + 2;
 
 	/* wait for the MDIO interface to not be busy or timeout
 	   after some time.
@@ -1245,7 +1245,6 @@ MODULE_DEVICE_TABLE(of, xemaclite_of_mat
 static struct platform_driver xemaclite_of_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
 		.of_match_table = xemaclite_of_match,
 	},
 	.probe		= xemaclite_of_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ethernet/xircom/xirc2ps_cs.c linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xircom/xirc2ps_cs.c
--- linux-libre-3.16-gnu/drivers/net/ethernet/xircom/xirc2ps_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ethernet/xircom/xirc2ps_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -266,7 +266,7 @@ static void xirc2ps_detach(struct pcmcia
 
 static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
 
-typedef struct local_info_t {
+struct local_info {
 	struct net_device	*dev;
 	struct pcmcia_device	*p_dev;
 
@@ -281,7 +281,7 @@ typedef struct local_info_t {
     unsigned last_ptr_value; /* last packets transmitted value */
     const char *manf_str;
     struct work_struct tx_timeout_task;
-} local_info_t;
+};
 
 /****************
  * Some more prototypes
@@ -475,12 +475,12 @@ static int
 xirc2ps_probe(struct pcmcia_device *link)
 {
     struct net_device *dev;
-    local_info_t *local;
+    struct local_info *local;
 
     dev_dbg(&link->dev, "attach()\n");
 
     /* Allocate the device structure */
-    dev = alloc_etherdev(sizeof(local_info_t));
+    dev = alloc_etherdev(sizeof(struct local_info));
     if (!dev)
 	    return -ENOMEM;
     local = netdev_priv(dev);
@@ -536,7 +536,7 @@ static int
 set_card_type(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     u8 *buf;
     unsigned int cisrev, mediaid, prodid;
     size_t len;
@@ -690,7 +690,7 @@ static int
 xirc2ps_config(struct pcmcia_device * link)
 {
     struct net_device *dev = link->priv;
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     unsigned int ioaddr;
     int err;
     u8 *buf;
@@ -931,7 +931,7 @@ xirc2ps_release(struct pcmcia_device *li
 
 	if (link->resource[2]->end) {
 		struct net_device *dev = link->priv;
-		local_info_t *local = netdev_priv(dev);
+		struct local_info *local = netdev_priv(dev);
 		if (local->dingo)
 			iounmap(local->dingo_ccr - 0x0800);
 	}
@@ -975,7 +975,7 @@ static irqreturn_t
 xirc2ps_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *)dev_id;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr;
     u_char saved_page;
     unsigned bytes_rcvd;
@@ -1194,8 +1194,8 @@ xirc2ps_interrupt(int irq, void *dev_id)
 static void
 xirc2ps_tx_timeout_task(struct work_struct *work)
 {
-	local_info_t *local =
-		container_of(work, local_info_t, tx_timeout_task);
+	struct local_info *local =
+		container_of(work, struct local_info, tx_timeout_task);
 	struct net_device *dev = local->dev;
     /* reset the card */
     do_reset(dev,1);
@@ -1206,7 +1206,7 @@ xirc2ps_tx_timeout_task(struct work_stru
 static void
 xirc_tx_timeout(struct net_device *dev)
 {
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     dev->stats.tx_errors++;
     netdev_notice(dev, "transmit timed out\n");
     schedule_work(&lp->tx_timeout_task);
@@ -1215,7 +1215,7 @@ xirc_tx_timeout(struct net_device *dev)
 static netdev_tx_t
 do_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     int okay;
     unsigned freespace;
@@ -1300,7 +1300,7 @@ static void set_address(struct set_addre
 static void set_addresses(struct net_device *dev)
 {
 	unsigned int ioaddr = dev->base_addr;
-	local_info_t *lp = netdev_priv(dev);
+	struct local_info *lp = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
 	struct set_address_info sa_info;
 	int i;
@@ -1362,7 +1362,7 @@ set_multicast_list(struct net_device *de
 static int
 do_config(struct net_device *dev, struct ifmap *map)
 {
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
 
     pr_debug("do_config(%p)\n", dev);
     if (map->port != 255 && map->port != dev->if_port) {
@@ -1387,7 +1387,7 @@ do_config(struct net_device *dev, struct
 static int
 do_open(struct net_device *dev)
 {
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     struct pcmcia_device *link = lp->p_dev;
 
     dev_dbg(&link->dev, "do_open(%p)\n", dev);
@@ -1421,7 +1421,7 @@ static const struct ethtool_ops netdev_e
 static int
 do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     struct mii_ioctl_data *data = if_mii(rq);
 
@@ -1453,7 +1453,7 @@ do_ioctl(struct net_device *dev, struct
 static void
 hardreset(struct net_device *dev)
 {
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
 
     SelectPage(4);
@@ -1470,7 +1470,7 @@ hardreset(struct net_device *dev)
 static void
 do_reset(struct net_device *dev, int full)
 {
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     unsigned value;
 
@@ -1631,7 +1631,7 @@ do_reset(struct net_device *dev, int ful
 static int
 init_mii(struct net_device *dev)
 {
-    local_info_t *local = netdev_priv(dev);
+    struct local_info *local = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     unsigned control, status, linkpartner;
     int i;
@@ -1715,7 +1715,7 @@ static int
 do_stop(struct net_device *dev)
 {
     unsigned int ioaddr = dev->base_addr;
-    local_info_t *lp = netdev_priv(dev);
+    struct local_info *lp = netdev_priv(dev);
     struct pcmcia_device *link = lp->p_dev;
 
     dev_dbg(&link->dev, "do_stop(%p)\n", dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/fddi/defxx.c linux-libre-3.17-rc7-gnu/drivers/net/fddi/defxx.c
--- linux-libre-3.16-gnu/drivers/net/fddi/defxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/fddi/defxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,6 +196,7 @@
  *		14 Jun 2005	macro		Use irqreturn_t.
  *		23 Oct 2006	macro		Big-endian host support.
  *		14 Dec 2006	macro		TURBOchannel support.
+ *		01 Jul 2014	macro		Fixes for DMA on 64-bit hosts.
  */
 
 /* Include files */
@@ -224,8 +225,8 @@
 
 /* Version information string should be updated prior to each new release!  */
 #define DRV_NAME "defxx"
-#define DRV_VERSION "v1.10"
-#define DRV_RELDATE "2006/12/14"
+#define DRV_VERSION "v1.11"
+#define DRV_RELDATE "2014/07/01"
 
 static char version[] =
 	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -1126,17 +1127,16 @@ static int dfx_driver_init(struct net_de
 
 	/* Display virtual and physical addresses if debug driver */
 
-	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
-		   print_name,
-		   (long)bp->descr_block_virt, bp->descr_block_phys);
-	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
-	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
-	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
-	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
+	DBG_printk("%s: Descriptor block virt = %p, phys = %pad\n",
+		   print_name, bp->descr_block_virt, &bp->descr_block_phys);
+	DBG_printk("%s: Command Request buffer virt = %p, phys = %pad\n",
+		   print_name, bp->cmd_req_virt, &bp->cmd_req_phys);
+	DBG_printk("%s: Command Response buffer virt = %p, phys = %pad\n",
+		   print_name, bp->cmd_rsp_virt, &bp->cmd_rsp_phys);
+	DBG_printk("%s: Receive buffer block virt = %p, phys = %pad\n",
+		   print_name, bp->rcv_block_virt, &bp->rcv_block_phys);
+	DBG_printk("%s: Consumer block virt = %p, phys = %pad\n",
+		   print_name, bp->cons_block_virt, &bp->cons_block_phys);
 
 	return DFX_K_SUCCESS;
 }
@@ -2927,21 +2927,35 @@ static int dfx_rcv_init(DFX_board_t *bp,
 	for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
 		for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
 		{
-			struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
+			struct sk_buff *newskb;
+			dma_addr_t dma_addr;
+
+			newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE,
+						    GFP_NOIO);
 			if (!newskb)
 				return -ENOMEM;
-			bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-				((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
 			/*
 			 * align to 128 bytes for compatibility with
 			 * the old EISA boards.
 			 */
 
 			my_skb_align(newskb, 128);
+			dma_addr = dma_map_single(bp->bus_dev,
+						  newskb->data,
+						  PI_RCV_DATA_K_SIZE_MAX,
+						  DMA_FROM_DEVICE);
+			if (dma_mapping_error(bp->bus_dev, dma_addr)) {
+				dev_kfree_skb(newskb);
+				return -ENOMEM;
+			}
+			bp->descr_block_virt->rcv_data[i + j].long_0 =
+				(u32)(PI_RCV_DESCR_M_SOP |
+				      ((PI_RCV_DATA_K_SIZE_MAX /
+					PI_ALIGN_K_RCV_DATA_BUFF) <<
+				       PI_RCV_DESCR_V_SEG_LEN));
 			bp->descr_block_virt->rcv_data[i + j].long_1 =
-				(u32)dma_map_single(bp->bus_dev, newskb->data,
-						    NEW_SKB_SIZE,
-						    DMA_FROM_DEVICE);
+				(u32)dma_addr;
+
 			/*
 			 * p_rcv_buff_va is only used inside the
 			 * kernel so we put the skb pointer here.
@@ -3008,7 +3022,7 @@ static void dfx_rcv_queue_process(
 	PI_TYPE_2_CONSUMER	*p_type_2_cons;		/* ptr to rcv/xmt consumer block register */
 	char				*p_buff;			/* ptr to start of packet receive buffer (FMC descriptor) */
 	u32					descr, pkt_len;		/* FMC descriptor field and packet length */
-	struct sk_buff		*skb;				/* pointer to a sk_buff to hold incoming packet data */
+	struct sk_buff		*skb = NULL;			/* pointer to a sk_buff to hold incoming packet data */
 
 	/* Service all consumed LLC receive frames */
 
@@ -3016,7 +3030,7 @@ static void dfx_rcv_queue_process(
 	while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
 		{
 		/* Process any errors */
-
+		dma_addr_t dma_addr;
 		int entry;
 
 		entry = bp->rcv_xmt_reg.index.rcv_comp;
@@ -3025,6 +3039,11 @@ static void dfx_rcv_queue_process(
 #else
 		p_buff = bp->p_rcv_buff_va[entry];
 #endif
+		dma_addr = bp->descr_block_virt->rcv_data[entry].long_1;
+		dma_sync_single_for_cpu(bp->bus_dev,
+					dma_addr + RCV_BUFF_K_DESCR,
+					sizeof(u32),
+					DMA_FROM_DEVICE);
 		memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
 
 		if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
@@ -3046,31 +3065,46 @@ static void dfx_rcv_queue_process(
 				bp->rcv_length_errors++;
 			else{
 #ifdef DYNAMIC_BUFFERS
+				struct sk_buff *newskb = NULL;
+
 				if (pkt_len > SKBUFF_RX_COPYBREAK) {
-					struct sk_buff *newskb;
+					dma_addr_t new_dma_addr;
 
-					newskb = dev_alloc_skb(NEW_SKB_SIZE);
+					newskb = netdev_alloc_skb(bp->dev,
+								  NEW_SKB_SIZE);
 					if (newskb){
+						my_skb_align(newskb, 128);
+						new_dma_addr = dma_map_single(
+								bp->bus_dev,
+								newskb->data,
+								PI_RCV_DATA_K_SIZE_MAX,
+								DMA_FROM_DEVICE);
+						if (dma_mapping_error(
+								bp->bus_dev,
+								new_dma_addr)) {
+							dev_kfree_skb(newskb);
+							newskb = NULL;
+						}
+					}
+					if (newskb) {
 						rx_in_place = 1;
 
-						my_skb_align(newskb, 128);
 						skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
 						dma_unmap_single(bp->bus_dev,
-							bp->descr_block_virt->rcv_data[entry].long_1,
-							NEW_SKB_SIZE,
+							dma_addr,
+							PI_RCV_DATA_K_SIZE_MAX,
 							DMA_FROM_DEVICE);
 						skb_reserve(skb, RCV_BUFF_K_PADDING);
 						bp->p_rcv_buff_va[entry] = (char *)newskb;
-						bp->descr_block_virt->rcv_data[entry].long_1 =
-							(u32)dma_map_single(bp->bus_dev,
-								newskb->data,
-								NEW_SKB_SIZE,
-								DMA_FROM_DEVICE);
-					} else
-						skb = NULL;
-				} else
+						bp->descr_block_virt->rcv_data[entry].long_1 = (u32)new_dma_addr;
+					}
+				}
+				if (!newskb)
 #endif
-					skb = dev_alloc_skb(pkt_len+3);	/* alloc new buffer to pass up, add room for PRH */
+					/* Alloc new buffer to pass up,
+					 * add room for PRH. */
+					skb = netdev_alloc_skb(bp->dev,
+							       pkt_len + 3);
 				if (skb == NULL)
 					{
 					printk("%s: Could not allocate receive buffer.  Dropping packet.\n", bp->dev->name);
@@ -3080,6 +3114,12 @@ static void dfx_rcv_queue_process(
 				else {
 					if (!rx_in_place) {
 						/* Receive buffer allocated, pass receive packet up */
+						dma_sync_single_for_cpu(
+							bp->bus_dev,
+							dma_addr +
+							RCV_BUFF_K_PADDING,
+							pkt_len + 3,
+							DMA_FROM_DEVICE);
 
 						skb_copy_to_linear_data(skb,
 							       p_buff + RCV_BUFF_K_PADDING,
@@ -3182,6 +3222,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(str
 	u8			prod;				/* local transmit producer index */
 	PI_XMT_DESCR		*p_xmt_descr;		/* ptr to transmit descriptor block entry */
 	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
+	dma_addr_t		dma_addr;
 	unsigned long		flags;
 
 	netif_stop_queue(dev);
@@ -3229,6 +3270,20 @@ static netdev_tx_t dfx_xmt_queue_pkt(str
 			}
 		}
 
+	/* Write the three PRH bytes immediately before the FC byte */
+
+	skb_push(skb, 3);
+	skb->data[0] = DFX_PRH0_BYTE;	/* these byte values are defined */
+	skb->data[1] = DFX_PRH1_BYTE;	/* in the Motorola FDDI MAC chip */
+	skb->data[2] = DFX_PRH2_BYTE;	/* specification */
+
+	dma_addr = dma_map_single(bp->bus_dev, skb->data, skb->len,
+				  DMA_TO_DEVICE);
+	if (dma_mapping_error(bp->bus_dev, dma_addr)) {
+		skb_pull(skb, 3);
+		return NETDEV_TX_BUSY;
+	}
+
 	spin_lock_irqsave(&bp->lock, flags);
 
 	/* Get the current producer and the next free xmt data descriptor */
@@ -3249,13 +3304,6 @@ static netdev_tx_t dfx_xmt_queue_pkt(str
 
 	p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]);	/* also bump producer index */
 
-	/* Write the three PRH bytes immediately before the FC byte */
-
-	skb_push(skb,3);
-	skb->data[0] = DFX_PRH0_BYTE;	/* these byte values are defined */
-	skb->data[1] = DFX_PRH1_BYTE;	/* in the Motorola FDDI MAC chip */
-	skb->data[2] = DFX_PRH2_BYTE;	/* specification */
-
 	/*
 	 * Write the descriptor with buffer info and bump producer
 	 *
@@ -3284,8 +3332,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(str
 	 */
 
 	p_xmt_descr->long_0	= (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
-	p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
-						  skb->len, DMA_TO_DEVICE);
+	p_xmt_descr->long_1 = (u32)dma_addr;
 
 	/*
 	 * Verify that descriptor is actually available
@@ -3448,8 +3495,13 @@ static void dfx_rcv_flush( DFX_board_t *
 		{
 			struct sk_buff *skb;
 			skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
-			if (skb)
+			if (skb) {
+				dma_unmap_single(bp->bus_dev,
+						 bp->descr_block_virt->rcv_data[i+j].long_1,
+						 PI_RCV_DATA_K_SIZE_MAX,
+						 DMA_FROM_DEVICE);
 				dev_kfree_skb(skb);
+			}
 			bp->p_rcv_buff_va[i+j] = NULL;
 		}
 
@@ -3612,7 +3664,7 @@ static int __maybe_unused dfx_dev_unregi
 static int dfx_pci_register(struct pci_dev *, const struct pci_device_id *);
 static void dfx_pci_unregister(struct pci_dev *);
 
-static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
+static const struct pci_device_id dfx_pci_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
 	{ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/fddi/defxx.h linux-libre-3.17-rc7-gnu/drivers/net/fddi/defxx.h
--- linux-libre-3.16-gnu/drivers/net/fddi/defxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/fddi/defxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -1693,7 +1693,7 @@ typedef union
 /* Only execute special print call when debug driver was built */
 
 #ifdef DEFXX_DEBUG
-#define DBG_printk(args...) printk(## args)
+#define DBG_printk(args...) printk(args)
 #else
 #define DBG_printk(args...)
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/fddi/skfp/h/skfbi.h linux-libre-3.17-rc7-gnu/drivers/net/fddi/skfp/h/skfbi.h
--- linux-libre-3.16-gnu/drivers/net/fddi/skfp/h/skfbi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/fddi/skfp/h/skfbi.h	2014-09-28 17:29:07.000000000 -0400
@@ -147,11 +147,6 @@
 #define	PCI_MEM64BIT	(2<<1)	     /* Base addr anywhere in 64 Bit range */
 #define	PCI_MEMSPACE	0x00000001L  /* Bit 0:	Memory Space Indic. */
 
-/*	PCI_BASE_2ND	32 bit	2nd Base address */
-#define	PCI_IOBASE	0xffffff00L  /* Bit 31..8:  I/O Base address */
-#define	PCI_IOSIZE	0x000000fcL  /* Bit 7..2:   I/O Size Requirements */
-#define	PCI_IOSPACE	0x00000001L  /* Bit 0:	    I/O Space Indicator */
-
 /*	PCI_SUB_VID	16 bit	Subsystem Vendor ID */
 /*	PCI_SUB_ID	16 bit	Subsystem ID */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/fddi/skfp/skfddi.c linux-libre-3.17-rc7-gnu/drivers/net/fddi/skfp/skfddi.c
--- linux-libre-3.16-gnu/drivers/net/fddi/skfp/skfddi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/fddi/skfp/skfddi.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,7 +149,7 @@ extern void mac_drv_rx_mode(struct s_smc
 extern void mac_drv_clear_rx_queue(struct s_smc *smc);
 extern void enable_tx_irq(struct s_smc *smc, u_short queue);
 
-static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = {
+static const struct pci_device_id skfddi_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
 	{ }			/* Terminating entry */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/6pack.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/6pack.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/6pack.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/6pack.c	2014-09-28 17:29:07.000000000 -0400
@@ -596,7 +596,8 @@ static int sixpack_open(struct tty_struc
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
 
-	dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
+	dev = alloc_netdev(sizeof(struct sixpack), "sp%d", NET_NAME_UNKNOWN,
+			   sp_setup);
 	if (!dev) {
 		err = -ENOMEM;
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/baycom_epp.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/baycom_epp.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/baycom_epp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/baycom_epp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1206,7 +1206,7 @@ static int __init init_baycomepp(void)
 		struct net_device *dev;
 		
 		dev = alloc_netdev(sizeof(struct baycom_state), "bce%d",
-				   baycom_epp_dev_setup);
+				   NET_NAME_UNKNOWN, baycom_epp_dev_setup);
 
 		if (!dev) {
 			printk(KERN_WARNING "bce%d : out of memory\n", i);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/bpqether.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/bpqether.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/bpqether.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/bpqether.c	2014-09-28 17:29:07.000000000 -0400
@@ -501,8 +501,8 @@ static int bpq_new_device(struct net_dev
 	struct net_device *ndev;
 	struct bpqdev *bpq;
 
-	ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d",
-			   bpq_setup);
+	ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d", NET_NAME_UNKNOWN,
+			    bpq_setup);
 	if (!ndev)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/dmascc.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/dmascc.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/dmascc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/dmascc.c	2014-09-28 17:29:07.000000000 -0400
@@ -466,7 +466,7 @@ static int __init setup_adapter(int card
 	if (!info)
 		goto out;
 
-	info->dev[0] = alloc_netdev(0, "", dev_setup);
+	info->dev[0] = alloc_netdev(0, "", NET_NAME_UNKNOWN, dev_setup);
 	if (!info->dev[0]) {
 		printk(KERN_ERR "dmascc: "
 		       "could not allocate memory for %s at %#3x\n",
@@ -474,7 +474,7 @@ static int __init setup_adapter(int card
 		goto out1;
 	}
 
-	info->dev[1] = alloc_netdev(0, "", dev_setup);
+	info->dev[1] = alloc_netdev(0, "", NET_NAME_UNKNOWN, dev_setup);
 	if (!info->dev[1]) {
 		printk(KERN_ERR "dmascc: "
 		       "could not allocate memory for %s at %#3x\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/hdlcdrv.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/hdlcdrv.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/hdlcdrv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/hdlcdrv.c	2014-09-28 17:29:07.000000000 -0400
@@ -699,7 +699,7 @@ struct net_device *hdlcdrv_register(cons
 	if (privsize < sizeof(struct hdlcdrv_state))
 		privsize = sizeof(struct hdlcdrv_state);
 
-	dev = alloc_netdev(privsize, ifname, hdlcdrv_setup);
+	dev = alloc_netdev(privsize, ifname, NET_NAME_UNKNOWN, hdlcdrv_setup);
 	if (!dev)
 		return ERR_PTR(-ENOMEM);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/mkiss.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/mkiss.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/mkiss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/mkiss.c	2014-09-28 17:29:07.000000000 -0400
@@ -734,7 +734,8 @@ static int mkiss_open(struct tty_struct
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
 
-	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", NET_NAME_UNKNOWN,
+			   ax_setup);
 	if (!dev) {
 		err = -ENOMEM;
 		goto out;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/scc.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/scc.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/scc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/scc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1515,7 +1515,7 @@ static int scc_net_alloc(const char *nam
 	int err;
 	struct net_device *dev;
 
-	dev = alloc_netdev(0, name, scc_net_setup);
+	dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, scc_net_setup);
 	if (!dev) 
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hamradio/yam.c linux-libre-3.17-rc7-gnu/drivers/net/hamradio/yam.c
--- linux-libre-3.16-gnu/drivers/net/hamradio/yam.c	2014-08-07 04:53:14.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hamradio/yam.c	2014-09-28 21:34:58.000000000 -0400
@@ -1147,7 +1147,7 @@ static int __init yam_init_driver(void)
 		sprintf(name, "yam%d", i);
 		
 		dev = alloc_netdev(sizeof(struct yam_port), name,
-				   yam_setup);
+				   NET_NAME_UNKNOWN, yam_setup);
 		if (!dev) {
 			pr_err("yam: cannot allocate net device\n");
 			err = -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hippi/rrunner.c linux-libre-3.17-rc7-gnu/drivers/net/hippi/rrunner.c
--- linux-libre-3.16-gnu/drivers/net/hippi/rrunner.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hippi/rrunner.c	2014-09-28 17:29:07.000000000 -0400
@@ -1668,7 +1668,7 @@ static int rr_ioctl(struct net_device *d
 	}
 }
 
-static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = {
+static const struct pci_device_id rr_pci_tbl[] = {
 	{ PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0,}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hyperv/hyperv_net.h linux-libre-3.17-rc7-gnu/drivers/net/hyperv/hyperv_net.h
--- linux-libre-3.16-gnu/drivers/net/hyperv/hyperv_net.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hyperv/hyperv_net.h	2014-09-28 17:29:07.000000000 -0400
@@ -170,6 +170,7 @@ struct rndis_device {
 
 	enum rndis_device_state state;
 	bool link_state;
+	bool link_change;
 	atomic_t new_req_id;
 
 	spinlock_t request_lock;
@@ -185,7 +186,7 @@ int netvsc_device_remove(struct hv_devic
 int netvsc_send(struct hv_device *device,
 		struct hv_netvsc_packet *packet);
 void netvsc_linkstatus_callback(struct hv_device *device_obj,
-				unsigned int status);
+				struct rndis_message *resp);
 int netvsc_recv_callback(struct hv_device *device_obj,
 			struct hv_netvsc_packet *packet,
 			struct ndis_tcp_ip_checksum_info *csum_info);
@@ -584,7 +585,7 @@ struct nvsp_message {
 
 #define NETVSC_RECEIVE_BUFFER_SIZE		(1024*1024*16)	/* 16MB */
 #define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY	(1024*1024*15)  /* 15MB */
-#define NETVSC_SEND_BUFFER_SIZE			(1024 * 1024)   /* 1MB */
+#define NETVSC_SEND_BUFFER_SIZE			(1024 * 1024 * 15)   /* 15MB */
 #define NETVSC_INVALID_INDEX			-1
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hyperv/netvsc.c linux-libre-3.17-rc7-gnu/drivers/net/hyperv/netvsc.c
--- linux-libre-3.16-gnu/drivers/net/hyperv/netvsc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hyperv/netvsc.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,8 +193,7 @@ static int netvsc_destroy_buf(struct net
 	}
 	if (net_device->send_buf) {
 		/* Free up the receive buffer */
-		free_pages((unsigned long)net_device->send_buf,
-			   get_order(net_device->send_buf_size));
+		vfree(net_device->send_buf);
 		net_device->send_buf = NULL;
 	}
 	kfree(net_device->send_section_map);
@@ -303,9 +302,7 @@ static int netvsc_init_buf(struct hv_dev
 
 	/* Now setup the send buffer.
 	 */
-	net_device->send_buf =
-		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
-					 get_order(net_device->send_buf_size));
+	net_device->send_buf = vzalloc(net_device->send_buf_size);
 	if (!net_device->send_buf) {
 		netdev_err(ndev, "unable to allocate send "
 			   "buffer of size %d\n", net_device->send_buf_size);
@@ -1096,9 +1093,7 @@ close:
 	vmbus_close(device->channel);
 
 cleanup:
-
-	if (net_device)
-		kfree(net_device);
+	kfree(net_device);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hyperv/netvsc_drv.c linux-libre-3.17-rc7-gnu/drivers/net/hyperv/netvsc_drv.c
--- linux-libre-3.16-gnu/drivers/net/hyperv/netvsc_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hyperv/netvsc_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -579,8 +579,9 @@ drop:
  * netvsc_linkstatus_callback - Link up/down notification
  */
 void netvsc_linkstatus_callback(struct hv_device *device_obj,
-				       unsigned int status)
+				struct rndis_message *resp)
 {
+	struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
 	struct net_device *net;
 	struct net_device_context *ndev_ctx;
 	struct netvsc_device *net_device;
@@ -589,7 +590,19 @@ void netvsc_linkstatus_callback(struct h
 	net_device = hv_get_drvdata(device_obj);
 	rdev = net_device->extension;
 
-	rdev->link_state = status != 1;
+	switch (indicate->status) {
+	case RNDIS_STATUS_MEDIA_CONNECT:
+		rdev->link_state = false;
+		break;
+	case RNDIS_STATUS_MEDIA_DISCONNECT:
+		rdev->link_state = true;
+		break;
+	case RNDIS_STATUS_NETWORK_CHANGE:
+		rdev->link_change = true;
+		break;
+	default:
+		return;
+	}
 
 	net = net_device->ndev;
 
@@ -597,7 +610,7 @@ void netvsc_linkstatus_callback(struct h
 		return;
 
 	ndev_ctx = netdev_priv(net);
-	if (status == 1) {
+	if (!rdev->link_state) {
 		schedule_delayed_work(&ndev_ctx->dwork, 0);
 		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
 	} else {
@@ -736,6 +749,14 @@ static int netvsc_set_mac_addr(struct ne
 	return err;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netvsc_poll_controller(struct net_device *net)
+{
+	/* As netvsc_start_xmit() works synchronous we don't have to
+	 * trigger anything here.
+	 */
+}
+#endif
 
 static const struct ethtool_ops ethtool_ops = {
 	.get_drvinfo	= netvsc_get_drvinfo,
@@ -751,6 +772,9 @@ static const struct net_device_ops devic
 	.ndo_validate_addr =		eth_validate_addr,
 	.ndo_set_mac_address =		netvsc_set_mac_addr,
 	.ndo_select_queue =		netvsc_select_queue,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller =		netvsc_poll_controller,
+#endif
 };
 
 /*
@@ -767,7 +791,9 @@ static void netvsc_link_change(struct wo
 	struct net_device *net;
 	struct netvsc_device *net_device;
 	struct rndis_device *rdev;
-	bool notify;
+	bool notify, refresh = false;
+	char *argv[] = { "/etc/init.d/network", "restart", NULL };
+	char *envp[] = { "HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
 
 	rtnl_lock();
 
@@ -782,10 +808,17 @@ static void netvsc_link_change(struct wo
 	} else {
 		netif_carrier_on(net);
 		notify = true;
+		if (rdev->link_change) {
+			rdev->link_change = false;
+			refresh = true;
+		}
 	}
 
 	rtnl_unlock();
 
+	if (refresh)
+		call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+
 	if (notify)
 		netdev_notify_peers(net);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/hyperv/rndis_filter.c linux-libre-3.17-rc7-gnu/drivers/net/hyperv/rndis_filter.c
--- linux-libre-3.16-gnu/drivers/net/hyperv/rndis_filter.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/hyperv/rndis_filter.c	2014-09-28 17:29:07.000000000 -0400
@@ -320,25 +320,6 @@ static void rndis_filter_receive_respons
 	}
 }
 
-static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
-					     struct rndis_message *resp)
-{
-	struct rndis_indicate_status *indicate =
-			&resp->msg.indicate_status;
-
-	if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
-		netvsc_linkstatus_callback(
-			dev->net_dev->dev, 1);
-	} else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
-		netvsc_linkstatus_callback(
-			dev->net_dev->dev, 0);
-	} else {
-		/*
-		 * TODO:
-		 */
-	}
-}
-
 /*
  * Get the Per-Packet-Info with the specified type
  * return NULL if not found.
@@ -464,7 +445,7 @@ int rndis_filter_receive(struct hv_devic
 
 	case RNDIS_MSG_INDICATE:
 		/* notification msgs */
-		rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
+		netvsc_linkstatus_callback(dev, rndis_msg);
 		break;
 	default:
 		netdev_err(ndev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/at86rf230.c linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/at86rf230.c
--- linux-libre-3.16-gnu/drivers/net/ieee802154/at86rf230.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/at86rf230.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  * Written by:
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ * Alexander Aring <aar@pengutronix.de>
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -26,43 +27,75 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/at86rf230.h>
+#include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/of_gpio.h>
 
+#include <net/ieee802154.h>
 #include <net/mac802154.h>
 #include <net/wpan-phy.h>
 
-struct at86rf230_local {
-	struct spi_device *spi;
+struct at86rf230_local;
+/* at86rf2xx chip depend data.
+ * All timings are in us.
+ */
+struct at86rf2xx_chip_data {
+	u16 t_sleep_cycle;
+	u16 t_channel_switch;
+	u16 t_reset_to_off;
+	u16 t_off_to_aack;
+	u16 t_off_to_tx_on;
+	u16 t_frame;
+	u16 t_p_ack;
+	/* short interframe spacing time */
+	u16 t_sifs;
+	/* long interframe spacing time */
+	u16 t_lifs;
+	/* completion timeout for tx in msecs */
+	u16 t_tx_timeout;
+	int rssi_base_val;
 
-	u8 part;
-	u8 vers;
+	int (*set_channel)(struct at86rf230_local *, int, int);
+	int (*get_desense_steps)(struct at86rf230_local *, s32);
+};
 
-	u8 buf[2];
-	struct mutex bmux;
+#define AT86RF2XX_MAX_BUF (127 + 3)
 
-	struct work_struct irqwork;
-	struct completion tx_complete;
+struct at86rf230_state_change {
+	struct at86rf230_local *lp;
+
+	struct spi_message msg;
+	struct spi_transfer trx;
+	u8 buf[AT86RF2XX_MAX_BUF];
+
+	void (*complete)(void *context);
+	u8 from_state;
+	u8 to_state;
+};
+
+struct at86rf230_local {
+	struct spi_device *spi;
 
 	struct ieee802154_dev *dev;
+	struct at86rf2xx_chip_data *data;
+	struct regmap *regmap;
 
-	spinlock_t lock;
-	bool irq_busy;
-	bool is_tx;
-	bool tx_aret;
+	struct completion state_complete;
+	struct at86rf230_state_change state;
 
-	int rssi_base_val;
-};
+	struct at86rf230_state_change irq;
 
-static bool is_rf212(struct at86rf230_local *local)
-{
-	return local->part == 7;
-}
+	bool tx_aret;
+	bool is_tx;
+	/* spinlock for is_tx protection */
+	spinlock_t lock;
+	struct completion tx_complete;
+	struct sk_buff *tx_skb;
+	struct at86rf230_state_change tx;
+};
 
 #define	RG_TRX_STATUS	(0x01)
 #define	SR_TRX_STATUS		0x01, 0x1f, 0
@@ -256,344 +289,753 @@ static bool is_rf212(struct at86rf230_lo
 #define STATE_BUSY_RX_AACK_NOCLK 0x1E
 #define STATE_TRANSITION_IN_PROGRESS 0x1F
 
+#define AT86RF2XX_NUMREGS 0x3F
+
 static int
-__at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
-		u8 *version)
+at86rf230_async_state_change(struct at86rf230_local *lp,
+			     struct at86rf230_state_change *ctx,
+			     const u8 state, void (*complete)(void *context));
+
+static inline int
+__at86rf230_write(struct at86rf230_local *lp,
+		  unsigned int addr, unsigned int data)
 {
-	u8 data[4];
-	u8 *buf = kmalloc(2, GFP_KERNEL);
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf	= buf,
-		.rx_buf	= buf,
-	};
-	u8 reg;
+	return regmap_write(lp->regmap, addr, data);
+}
 
-	if (!buf)
-		return -ENOMEM;
+static inline int
+__at86rf230_read(struct at86rf230_local *lp,
+		 unsigned int addr, unsigned int *data)
+{
+	return regmap_read(lp->regmap, addr, data);
+}
 
-	for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) {
-		buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
-		buf[1] = 0xff;
-		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
-		spi_message_init(&msg);
-		spi_message_add_tail(&xfer, &msg);
+static inline int
+at86rf230_read_subreg(struct at86rf230_local *lp,
+		      unsigned int addr, unsigned int mask,
+		      unsigned int shift, unsigned int *data)
+{
+	int rc;
 
-		status = spi_sync(spi, &msg);
-		dev_vdbg(&spi->dev, "status = %d\n", status);
-		if (msg.status)
-			status = msg.status;
+	rc = __at86rf230_read(lp, addr, data);
+	if (rc > 0)
+		*data = (*data & mask) >> shift;
 
-		dev_vdbg(&spi->dev, "status = %d\n", status);
-		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
-		dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]);
+	return rc;
+}
 
-		if (status == 0)
-			data[reg - RG_PART_NUM] = buf[1];
-		else
-			break;
-	}
+static inline int
+at86rf230_write_subreg(struct at86rf230_local *lp,
+		       unsigned int addr, unsigned int mask,
+		       unsigned int shift, unsigned int data)
+{
+	return regmap_update_bits(lp->regmap, addr, mask, data << shift);
+}
 
-	if (status == 0) {
-		*part = data[0];
-		*version = data[1];
-		*man_id = (data[3] << 8) | data[2];
+static bool
+at86rf230_reg_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case RG_TRX_STATE:
+	case RG_TRX_CTRL_0:
+	case RG_TRX_CTRL_1:
+	case RG_PHY_TX_PWR:
+	case RG_PHY_ED_LEVEL:
+	case RG_PHY_CC_CCA:
+	case RG_CCA_THRES:
+	case RG_RX_CTRL:
+	case RG_SFD_VALUE:
+	case RG_TRX_CTRL_2:
+	case RG_ANT_DIV:
+	case RG_IRQ_MASK:
+	case RG_VREG_CTRL:
+	case RG_BATMON:
+	case RG_XOSC_CTRL:
+	case RG_RX_SYN:
+	case RG_XAH_CTRL_1:
+	case RG_FTN_CTRL:
+	case RG_PLL_CF:
+	case RG_PLL_DCU:
+	case RG_SHORT_ADDR_0:
+	case RG_SHORT_ADDR_1:
+	case RG_PAN_ID_0:
+	case RG_PAN_ID_1:
+	case RG_IEEE_ADDR_0:
+	case RG_IEEE_ADDR_1:
+	case RG_IEEE_ADDR_2:
+	case RG_IEEE_ADDR_3:
+	case RG_IEEE_ADDR_4:
+	case RG_IEEE_ADDR_5:
+	case RG_IEEE_ADDR_6:
+	case RG_IEEE_ADDR_7:
+	case RG_XAH_CTRL_0:
+	case RG_CSMA_SEED_0:
+	case RG_CSMA_SEED_1:
+	case RG_CSMA_BE:
+		return true;
+	default:
+		return false;
 	}
+}
 
-	kfree(buf);
+static bool
+at86rf230_reg_readable(struct device *dev, unsigned int reg)
+{
+	bool rc;
 
-	return status;
+	/* all writeable are also readable */
+	rc = at86rf230_reg_writeable(dev, reg);
+	if (rc)
+		return rc;
+
+	/* readonly regs */
+	switch (reg) {
+	case RG_TRX_STATUS:
+	case RG_PHY_RSSI:
+	case RG_IRQ_STATUS:
+	case RG_PART_NUM:
+	case RG_VERSION_NUM:
+	case RG_MAN_ID_1:
+	case RG_MAN_ID_0:
+		return true;
+	default:
+		return false;
+	}
 }
 
-static int
-__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
+static bool
+at86rf230_reg_volatile(struct device *dev, unsigned int reg)
 {
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf	= buf,
-	};
+	/* can be changed during runtime */
+	switch (reg) {
+	case RG_TRX_STATUS:
+	case RG_TRX_STATE:
+	case RG_PHY_RSSI:
+	case RG_PHY_ED_LEVEL:
+	case RG_IRQ_STATUS:
+	case RG_VREG_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
 
-	buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
-	buf[1] = data;
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
+static bool
+at86rf230_reg_precious(struct device *dev, unsigned int reg)
+{
+	/* don't clear irq line on read */
+	switch (reg) {
+	case RG_IRQ_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
 
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
+static struct regmap_config at86rf230_regmap_spi_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.write_flag_mask = CMD_REG | CMD_WRITE,
+	.read_flag_mask = CMD_REG,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = AT86RF2XX_NUMREGS,
+	.writeable_reg = at86rf230_reg_writeable,
+	.readable_reg = at86rf230_reg_readable,
+	.volatile_reg = at86rf230_reg_volatile,
+	.precious_reg = at86rf230_reg_precious,
+};
 
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+static void
+at86rf230_async_error_recover(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
 
-	return status;
+	at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
 }
 
+static void
+at86rf230_async_error(struct at86rf230_local *lp,
+		      struct at86rf230_state_change *ctx, int rc)
+{
+	dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
+
+	at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+				     at86rf230_async_error_recover);
+}
+
+/* Generic function to get some register value in async mode */
 static int
-__at86rf230_read_subreg(struct at86rf230_local *lp,
-			u8 addr, u8 mask, int shift, u8 *data)
+at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
+			 struct at86rf230_state_change *ctx,
+			 void (*complete)(void *context))
 {
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf	= buf,
-		.rx_buf	= buf,
-	};
+	u8 *tx_buf = ctx->buf;
 
-	buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
-	buf[1] = 0xff;
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
+	tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
+	ctx->trx.len = 2;
+	ctx->msg.complete = complete;
+	return spi_async(lp->spi, &ctx->msg);
+}
 
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
+static void
+at86rf230_async_state_assert(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	const u8 *buf = ctx->buf;
+	const u8 trx_state = buf[1] & 0x1f;
 
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+	/* Assert state change */
+	if (trx_state != ctx->to_state) {
+		/* Special handling if transceiver state is in
+		 * STATE_BUSY_RX_AACK and a SHR was detected.
+		 */
+		if  (trx_state == STATE_BUSY_RX_AACK) {
+			/* Undocumented race condition. If we send a state
+			 * change to STATE_RX_AACK_ON the transceiver could
+			 * change his state automatically to STATE_BUSY_RX_AACK
+			 * if a SHR was detected. This is not an error, but we
+			 * can't assert this.
+			 */
+			if (ctx->to_state == STATE_RX_AACK_ON)
+				goto done;
 
-	if (status == 0)
-		*data = (buf[1] & mask) >> shift;
+			/* If we change to STATE_TX_ON without forcing and
+			 * transceiver state is STATE_BUSY_RX_AACK, we wait
+			 * 'tFrame + tPAck' receiving time. In this time the
+			 * PDU should be received. If the transceiver is still
+			 * in STATE_BUSY_RX_AACK, we run a force state change
+			 * to STATE_TX_ON. This is a timeout handling, if the
+			 * transceiver stucks in STATE_BUSY_RX_AACK.
+			 */
+			if (ctx->to_state == STATE_TX_ON) {
+				at86rf230_async_state_change(lp, ctx,
+							     STATE_FORCE_TX_ON,
+							     ctx->complete);
+				return;
+			}
+		}
 
-	return status;
+
+		dev_warn(&lp->spi->dev, "unexcept state change from 0x%02x to 0x%02x. Actual state: 0x%02x\n",
+			 ctx->from_state, ctx->to_state, trx_state);
+	}
+
+done:
+	if (ctx->complete)
+		ctx->complete(context);
 }
 
-static int
-at86rf230_read_subreg(struct at86rf230_local *lp,
-		      u8 addr, u8 mask, int shift, u8 *data)
+/* Do state change timing delay. */
+static void
+at86rf230_async_state_delay(void *context)
 {
-	int status;
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	struct at86rf2xx_chip_data *c = lp->data;
+	bool force = false;
+	int rc;
 
-	mutex_lock(&lp->bmux);
-	status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
-	mutex_unlock(&lp->bmux);
+	/* The force state changes are will show as normal states in the
+	 * state status subregister. We change the to_state to the
+	 * corresponding one and remember if it was a force change, this
+	 * differs if we do a state change from STATE_BUSY_RX_AACK.
+	 */
+	switch (ctx->to_state) {
+	case STATE_FORCE_TX_ON:
+		ctx->to_state = STATE_TX_ON;
+		force = true;
+		break;
+	case STATE_FORCE_TRX_OFF:
+		ctx->to_state = STATE_TRX_OFF;
+		force = true;
+		break;
+	default:
+		break;
+	}
 
-	return status;
+	switch (ctx->from_state) {
+	case STATE_TRX_OFF:
+		switch (ctx->to_state) {
+		case STATE_RX_AACK_ON:
+			usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10);
+			goto change;
+		case STATE_TX_ON:
+			usleep_range(c->t_off_to_tx_on,
+				     c->t_off_to_tx_on + 10);
+			goto change;
+		default:
+			break;
+		}
+		break;
+	case STATE_BUSY_RX_AACK:
+		switch (ctx->to_state) {
+		case STATE_TX_ON:
+			/* Wait for worst case receiving time if we
+			 * didn't make a force change from BUSY_RX_AACK
+			 * to TX_ON.
+			 */
+			if (!force) {
+				usleep_range(c->t_frame + c->t_p_ack,
+					     c->t_frame + c->t_p_ack + 1000);
+				goto change;
+			}
+			break;
+		default:
+			break;
+		}
+		break;
+	/* Default value, means RESET state */
+	case STATE_P_ON:
+		switch (ctx->to_state) {
+		case STATE_TRX_OFF:
+			usleep_range(c->t_reset_to_off, c->t_reset_to_off + 10);
+			goto change;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* Default delay is 1us in the most cases */
+	udelay(1);
+
+change:
+	rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+				      at86rf230_async_state_assert);
+	if (rc)
+		dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 }
 
-static int
-at86rf230_write_subreg(struct at86rf230_local *lp,
-		       u8 addr, u8 mask, int shift, u8 data)
+static void
+at86rf230_async_state_change_start(void *context)
 {
-	int status;
-	u8 val;
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	u8 *buf = ctx->buf;
+	const u8 trx_state = buf[1] & 0x1f;
+	int rc;
 
-	mutex_lock(&lp->bmux);
-	status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
-	if (status)
-		goto out;
+	/* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
+	if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
+		udelay(1);
+		rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+					      at86rf230_async_state_change_start);
+		if (rc)
+			dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
+		return;
+	}
 
-	val &= ~mask;
-	val |= (data << shift) & mask;
+	/* Check if we already are in the state which we change in */
+	if (trx_state == ctx->to_state) {
+		if (ctx->complete)
+			ctx->complete(context);
+		return;
+	}
 
-	status = __at86rf230_write(lp, addr, val);
-out:
-	mutex_unlock(&lp->bmux);
+	/* Set current state to the context of state change */
+	ctx->from_state = trx_state;
 
-	return status;
+	/* Going into the next step for a state change which do a timing
+	 * relevant delay.
+	 */
+	buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+	buf[1] = ctx->to_state;
+	ctx->trx.len = 2;
+	ctx->msg.complete = at86rf230_async_state_delay;
+	rc = spi_async(lp->spi, &ctx->msg);
+	if (rc)
+		dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 }
 
 static int
-at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
+at86rf230_async_state_change(struct at86rf230_local *lp,
+			     struct at86rf230_state_change *ctx,
+			     const u8 state, void (*complete)(void *context))
 {
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer_head = {
-		.len		= 2,
-		.tx_buf		= buf,
+	/* Initialization for the state change context */
+	ctx->to_state = state;
+	ctx->complete = complete;
+	return at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+					at86rf230_async_state_change_start);
+}
 
-	};
-	struct spi_transfer xfer_buf = {
-		.len		= len,
-		.tx_buf		= data,
-	};
+static void
+at86rf230_sync_state_change_complete(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
 
-	mutex_lock(&lp->bmux);
-	buf[0] = CMD_WRITE | CMD_FB;
-	buf[1] = len + 2; /* 2 bytes for CRC that isn't written */
+	complete(&lp->state_complete);
+}
 
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+/* This function do a sync framework above the async state change.
+ * Some callbacks of the IEEE 802.15.4 driver interface need to be
+ * handled synchronously.
+ */
+static int
+at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state)
+{
+	int rc;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head, &msg);
-	spi_message_add_tail(&xfer_buf, &msg);
+	rc = at86rf230_async_state_change(lp, &lp->state, state,
+					  at86rf230_sync_state_change_complete);
+	if (rc) {
+		at86rf230_async_error(lp, &lp->state, rc);
+		return rc;
+	}
 
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
+	rc = wait_for_completion_timeout(&lp->state_complete,
+					 msecs_to_jiffies(100));
+	if (!rc)
+		return -ETIMEDOUT;
 
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+	return 0;
+}
 
-	mutex_unlock(&lp->bmux);
-	return status;
+static void
+at86rf230_tx_complete(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+
+	complete(&lp->tx_complete);
 }
 
-static int
-at86rf230_read_fbuf(struct at86rf230_local *lp, u8 *data, u8 *len, u8 *lqi)
+static void
+at86rf230_tx_on(void *context)
 {
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer_head = {
-		.len		= 2,
-		.tx_buf		= buf,
-		.rx_buf		= buf,
-	};
-	struct spi_transfer xfer_head1 = {
-		.len		= 2,
-		.tx_buf		= buf,
-		.rx_buf		= buf,
-	};
-	struct spi_transfer xfer_buf = {
-		.len		= 0,
-		.rx_buf		= data,
-	};
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	mutex_lock(&lp->bmux);
+	rc = at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
+					  at86rf230_tx_complete);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
+}
 
-	buf[0] = CMD_FB;
-	buf[1] = 0x00;
+static void
+at86rf230_tx_trac_error(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head, &msg);
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					  at86rf230_tx_on);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
+}
 
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
+static void
+at86rf230_tx_trac_check(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	const u8 *buf = ctx->buf;
+	const u8 trac = (buf[1] & 0xe0) >> 5;
+	int rc;
 
-	xfer_buf.len = *(buf + 1) + 1;
-	*len = buf[1];
+	/* If trac status is different than zero we need to do a state change
+	 * to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver
+	 * state to TX_ON.
+	 */
+	if (trac) {
+		rc = at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+						  at86rf230_tx_trac_error);
+		if (rc)
+			at86rf230_async_error(lp, ctx, rc);
+		return;
+	}
 
-	buf[0] = CMD_FB;
-	buf[1] = 0x00;
+	at86rf230_tx_on(context);
+}
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head1, &msg);
-	spi_message_add_tail(&xfer_buf, &msg);
 
-	status = spi_sync(lp->spi, &msg);
+static void
+at86rf230_tx_trac_status(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	if (msg.status)
-		status = msg.status;
+	rc = at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+				      at86rf230_tx_trac_check);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
+}
 
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+static void
+at86rf230_rx(struct at86rf230_local *lp,
+	     const u8 *data, u8 len)
+{
+	u8 lqi;
+	struct sk_buff *skb;
+	u8 rx_local_buf[AT86RF2XX_MAX_BUF];
 
-	if (status) {
-		if (lqi && (*len > lp->buf[1]))
-			*lqi = data[lp->buf[1]];
+	if (len < 2)
+		return;
+
+	/* read full frame buffer and invalid lqi value to lowest
+	 * indicator if frame was is in a corrupted state.
+	 */
+	if (len > IEEE802154_MTU) {
+		lqi = 0;
+		len = IEEE802154_MTU;
+		dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
+	} else {
+		lqi = data[len];
 	}
-	mutex_unlock(&lp->bmux);
 
-	return status;
+	memcpy(rx_local_buf, data, len);
+	enable_irq(lp->spi->irq);
+
+	skb = alloc_skb(IEEE802154_MTU, GFP_ATOMIC);
+	if (!skb) {
+		dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
+		return;
+	}
+
+	memcpy(skb_put(skb, len), rx_local_buf, len);
+
+	/* We do not put CRC into the frame */
+	skb_trim(skb, len - 2);
+
+	ieee802154_rx_irqsafe(lp->dev, skb, lqi);
 }
 
-static int
-at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
+static void
+at86rf230_rx_read_frame_complete(void *context)
 {
-	might_sleep();
-	BUG_ON(!level);
-	*level = 0xbe;
-	return 0;
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	const u8 *buf = lp->irq.buf;
+	const u8 len = buf[1];
+
+	at86rf230_rx(lp, buf + 2, len);
 }
 
 static int
-at86rf230_state(struct ieee802154_dev *dev, int state)
+at86rf230_rx_read_frame(struct at86rf230_local *lp)
 {
-	struct at86rf230_local *lp = dev->priv;
+	u8 *buf = lp->irq.buf;
+
+	buf[0] = CMD_FB;
+	lp->irq.trx.len = AT86RF2XX_MAX_BUF;
+	lp->irq.msg.complete = at86rf230_rx_read_frame_complete;
+	return spi_async(lp->spi, &lp->irq.msg);
+}
+
+static void
+at86rf230_rx_trac_check(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
 	int rc;
-	u8 val;
-	u8 desired_status;
 
-	might_sleep();
+	/* Possible check on trac status here. This could be useful to make
+	 * some stats why receive is failed. Not used at the moment, but it's
+	 * maybe timing relevant. Datasheet doesn't say anything about this.
+	 * The programming guide say do it so.
+	 */
 
-	if (state == STATE_FORCE_TX_ON)
-		desired_status = STATE_TX_ON;
-	else if (state == STATE_FORCE_TRX_OFF)
-		desired_status = STATE_TRX_OFF;
-	else
-		desired_status = state;
+	rc = at86rf230_rx_read_frame(lp);
+	if (rc) {
+		enable_irq(lp->spi->irq);
+		at86rf230_async_error(lp, ctx, rc);
+	}
+}
 
-	do {
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
+static int
+at86rf230_irq_trx_end(struct at86rf230_local *lp)
+{
+	spin_lock(&lp->lock);
+	if (lp->is_tx) {
+		lp->is_tx = 0;
+		spin_unlock(&lp->lock);
+		enable_irq(lp->spi->irq);
+
+		if (lp->tx_aret)
+			return at86rf230_async_state_change(lp, &lp->irq,
+							    STATE_FORCE_TX_ON,
+							    at86rf230_tx_trac_status);
+		else
+			return at86rf230_async_state_change(lp, &lp->irq,
+							    STATE_RX_AACK_ON,
+							    at86rf230_tx_complete);
+	} else {
+		spin_unlock(&lp->lock);
+		return at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
+						at86rf230_rx_trac_check);
+	}
+}
+
+static void
+at86rf230_irq_status(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	const u8 *buf = lp->irq.buf;
+	const u8 irq = buf[1];
+	int rc;
+
+	if (irq & IRQ_TRX_END) {
+		rc = at86rf230_irq_trx_end(lp);
 		if (rc)
-			goto err;
-	} while (val == STATE_TRANSITION_IN_PROGRESS);
+			at86rf230_async_error(lp, ctx, rc);
+	} else {
+		enable_irq(lp->spi->irq);
+		dev_err(&lp->spi->dev, "not supported irq %02x received\n",
+			irq);
+	}
+}
 
-	if (val == desired_status)
-		return 0;
+static irqreturn_t at86rf230_isr(int irq, void *data)
+{
+	struct at86rf230_local *lp = data;
+	struct at86rf230_state_change *ctx = &lp->irq;
+	u8 *buf = ctx->buf;
+	int rc;
 
-	/* state is equal to phy states */
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
+	disable_irq_nosync(lp->spi->irq);
+
+	buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
+	ctx->trx.len = 2;
+	ctx->msg.complete = at86rf230_irq_status;
+	rc = spi_async(lp->spi, &ctx->msg);
+	if (rc) {
+		at86rf230_async_error(lp, ctx, rc);
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void
+at86rf230_write_frame_complete(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	u8 *buf = ctx->buf;
+	int rc;
+
+	buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+	buf[1] = STATE_BUSY_TX;
+	ctx->trx.len = 2;
+	ctx->msg.complete = NULL;
+	rc = spi_async(lp->spi, &ctx->msg);
 	if (rc)
-		goto err;
+		at86rf230_async_error(lp, ctx, rc);
+}
 
-	do {
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
-		if (rc)
-			goto err;
-	} while (val == STATE_TRANSITION_IN_PROGRESS);
+static void
+at86rf230_write_frame(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	struct sk_buff *skb = lp->tx_skb;
+	u8 *buf = lp->tx.buf;
+	int rc;
 
+	spin_lock(&lp->lock);
+	lp->is_tx = 1;
+	spin_unlock(&lp->lock);
 
-	if (val == desired_status ||
-	    (desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
-	    (desired_status == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK))
-		return 0;
+	buf[0] = CMD_FB | CMD_WRITE;
+	buf[1] = skb->len + 2;
+	memcpy(buf + 2, skb->data, skb->len);
+	lp->tx.trx.len = skb->len + 2;
+	lp->tx.msg.complete = at86rf230_write_frame_complete;
+	rc = spi_async(lp->spi, &lp->tx.msg);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
+}
 
-	pr_err("unexpected state change: %d, asked for %d\n", val, state);
-	return -EBUSY;
+static void
+at86rf230_xmit_tx_on(void *context)
+{
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-err:
-	pr_err("error: %d\n", rc);
-	return rc;
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
+					  at86rf230_write_frame);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
 }
 
 static int
-at86rf230_start(struct ieee802154_dev *dev)
+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
 	struct at86rf230_local *lp = dev->priv;
-	u8 rc;
+	struct at86rf230_state_change *ctx = &lp->tx;
 
-	rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
-	if (rc)
-		return rc;
+	void (*tx_complete)(void *context) = at86rf230_write_frame;
+	int rc;
 
-	rc = at86rf230_state(dev, STATE_TX_ON);
-	if (rc)
+	lp->tx_skb = skb;
+
+	/* In ARET mode we need to go into STATE_TX_ARET_ON after we
+	 * are in STATE_TX_ON. The pfad differs here, so we change
+	 * the complete handler.
+	 */
+	if (lp->tx_aret)
+		tx_complete = at86rf230_xmit_tx_on;
+
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					  tx_complete);
+	if (rc) {
+		at86rf230_async_error(lp, ctx, rc);
 		return rc;
+	}
+	rc = wait_for_completion_interruptible_timeout(&lp->tx_complete,
+						       msecs_to_jiffies(lp->data->t_tx_timeout));
+	if (!rc) {
+		at86rf230_async_error(lp, ctx, rc);
+		return -ETIMEDOUT;
+	}
 
-	return at86rf230_state(dev, STATE_RX_AACK_ON);
+	/* Interfame spacing time, which is phy depend.
+	 * TODO
+	 * Move this handling in MAC 802.15.4 layer.
+	 * This is currently a workaround to avoid fragmenation issues.
+	 */
+	if (skb->len > 18)
+		usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10);
+	else
+		usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10);
+
+	return 0;
+}
+
+static int
+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
+{
+	might_sleep();
+	BUG_ON(!level);
+	*level = 0xbe;
+	return 0;
+}
+
+static int
+at86rf230_start(struct ieee802154_dev *dev)
+{
+	return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON);
 }
 
 static void
 at86rf230_stop(struct ieee802154_dev *dev)
 {
-	at86rf230_state(dev, STATE_FORCE_TRX_OFF);
+	at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF);
 }
 
 static int
-at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
+at86rf23x_set_channel(struct at86rf230_local *lp, int page, int channel)
 {
-	lp->rssi_base_val = -91;
-
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
@@ -611,10 +1053,10 @@ at86rf212_set_channel(struct at86rf230_l
 
 	if (page == 0) {
 		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
-		lp->rssi_base_val = -100;
+		lp->data->rssi_base_val = -100;
 	} else {
 		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
-		lp->rssi_base_val = -98;
+		lp->data->rssi_base_val = -98;
 	}
 	if (rc < 0)
 		return rc;
@@ -636,14 +1078,13 @@ at86rf230_channel(struct ieee802154_dev
 		return -EINVAL;
 	}
 
-	if (is_rf212(lp))
-		rc = at86rf212_set_channel(lp, page, channel);
-	else
-		rc = at86rf230_set_channel(lp, page, channel);
+	rc = lp->data->set_channel(lp, page, channel);
 	if (rc < 0)
 		return rc;
 
-	msleep(1); /* Wait for PLL */
+	/* Wait for PLL */
+	usleep_range(lp->data->t_channel_switch,
+		     lp->data->t_channel_switch + 10);
 	dev->phy->current_channel = channel;
 	dev->phy->current_page = page;
 
@@ -651,92 +1092,6 @@ at86rf230_channel(struct ieee802154_dev
 }
 
 static int
-at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
-{
-	struct at86rf230_local *lp = dev->priv;
-	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	if  (lp->irq_busy) {
-		spin_unlock_irqrestore(&lp->lock, flags);
-		return -EBUSY;
-	}
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	might_sleep();
-
-	rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
-	if (rc)
-		goto err;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->is_tx = 1;
-	reinit_completion(&lp->tx_complete);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	rc = at86rf230_write_fbuf(lp, skb->data, skb->len);
-	if (rc)
-		goto err_rx;
-
-	if (lp->tx_aret) {
-		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
-		if (rc)
-			goto err_rx;
-	}
-
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
-	if (rc)
-		goto err_rx;
-
-	rc = wait_for_completion_interruptible(&lp->tx_complete);
-	if (rc < 0)
-		goto err_rx;
-
-	return at86rf230_start(dev);
-err_rx:
-	at86rf230_start(dev);
-err:
-	pr_err("error: %d\n", rc);
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->is_tx = 0;
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	return rc;
-}
-
-static int at86rf230_rx(struct at86rf230_local *lp)
-{
-	u8 len = 128, lqi = 0;
-	struct sk_buff *skb;
-
-	skb = alloc_skb(len, GFP_KERNEL);
-
-	if (!skb)
-		return -ENOMEM;
-
-	if (at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi))
-		goto err;
-
-	if (len < 2)
-		goto err;
-
-	skb_trim(skb, len - 2); /* We do not put CRC into the frame */
-
-	ieee802154_rx_irqsafe(lp->dev, skb, lqi);
-
-	dev_dbg(&lp->spi->dev, "READ_FBUF: %d %x\n", len, lqi);
-
-	return 0;
-err:
-	pr_debug("received frame is too small\n");
-
-	kfree_skb(skb);
-	return -EINVAL;
-}
-
-static int
 at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
 			   struct ieee802154_hw_addr_filt *filt,
 			   unsigned long changed)
@@ -784,7 +1139,7 @@ at86rf230_set_hw_addr_filt(struct ieee80
 }
 
 static int
-at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
+at86rf230_set_txpower(struct ieee802154_dev *dev, int db)
 {
 	struct at86rf230_local *lp = dev->priv;
 
@@ -803,7 +1158,7 @@ at86rf212_set_txpower(struct ieee802154_
 }
 
 static int
-at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
+at86rf230_set_lbt(struct ieee802154_dev *dev, bool on)
 {
 	struct at86rf230_local *lp = dev->priv;
 
@@ -811,7 +1166,7 @@ at86rf212_set_lbt(struct ieee802154_dev
 }
 
 static int
-at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
+at86rf230_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
 {
 	struct at86rf230_local *lp = dev->priv;
 
@@ -819,21 +1174,31 @@ at86rf212_set_cca_mode(struct ieee802154
 }
 
 static int
-at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
+at86rf212_get_desens_steps(struct at86rf230_local *lp, s32 level)
+{
+	return (level - lp->data->rssi_base_val) * 100 / 207;
+}
+
+static int
+at86rf23x_get_desens_steps(struct at86rf230_local *lp, s32 level)
+{
+	return (level - lp->data->rssi_base_val) / 2;
+}
+
+static int
+at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
 {
 	struct at86rf230_local *lp = dev->priv;
-	int desens_steps;
 
-	if (level < lp->rssi_base_val || level > 30)
+	if (level < lp->data->rssi_base_val || level > 30)
 		return -EINVAL;
 
-	desens_steps = (level - lp->rssi_base_val) * 100 / 207;
-
-	return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
+	return at86rf230_write_subreg(lp, SR_CCA_ED_THRES,
+				      lp->data->get_desense_steps(lp, level));
 }
 
 static int
-at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
+at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
 			  u8 retries)
 {
 	struct at86rf230_local *lp = dev->priv;
@@ -854,7 +1219,7 @@ at86rf212_set_csma_params(struct ieee802
 }
 
 static int
-at86rf212_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
+at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
 {
 	struct at86rf230_local *lp = dev->priv;
 	int rc = 0;
@@ -878,110 +1243,84 @@ static struct ieee802154_ops at86rf230_o
 	.start = at86rf230_start,
 	.stop = at86rf230_stop,
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+	.set_txpower = at86rf230_set_txpower,
+	.set_lbt = at86rf230_set_lbt,
+	.set_cca_mode = at86rf230_set_cca_mode,
+	.set_cca_ed_level = at86rf230_set_cca_ed_level,
+	.set_csma_params = at86rf230_set_csma_params,
+	.set_frame_retries = at86rf230_set_frame_retries,
 };
 
-static struct ieee802154_ops at86rf212_ops = {
-	.owner = THIS_MODULE,
-	.xmit = at86rf230_xmit,
-	.ed = at86rf230_ed,
-	.set_channel = at86rf230_channel,
-	.start = at86rf230_start,
-	.stop = at86rf230_stop,
-	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
-	.set_txpower = at86rf212_set_txpower,
-	.set_lbt = at86rf212_set_lbt,
-	.set_cca_mode = at86rf212_set_cca_mode,
-	.set_cca_ed_level = at86rf212_set_cca_ed_level,
-	.set_csma_params = at86rf212_set_csma_params,
-	.set_frame_retries = at86rf212_set_frame_retries,
+static struct at86rf2xx_chip_data at86rf233_data = {
+	.t_sleep_cycle = 330,
+	.t_channel_switch = 11,
+	.t_reset_to_off = 26,
+	.t_off_to_aack = 80,
+	.t_off_to_tx_on = 80,
+	.t_frame = 4096,
+	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
+	.t_tx_timeout = 2000,
+	.rssi_base_val = -91,
+	.set_channel = at86rf23x_set_channel,
+	.get_desense_steps = at86rf23x_get_desens_steps
 };
 
-static void at86rf230_irqwork(struct work_struct *work)
-{
-	struct at86rf230_local *lp =
-		container_of(work, struct at86rf230_local, irqwork);
-	u8 status = 0, val;
-	int rc;
-	unsigned long flags;
-
-	rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
-	status |= val;
-
-	status &= ~IRQ_PLL_LOCK; /* ignore */
-	status &= ~IRQ_RX_START; /* ignore */
-	status &= ~IRQ_AMI; /* ignore */
-	status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/
-
-	if (status & IRQ_TRX_END) {
-		status &= ~IRQ_TRX_END;
-		spin_lock_irqsave(&lp->lock, flags);
-		if (lp->is_tx) {
-			lp->is_tx = 0;
-			spin_unlock_irqrestore(&lp->lock, flags);
-			complete(&lp->tx_complete);
-		} else {
-			spin_unlock_irqrestore(&lp->lock, flags);
-			at86rf230_rx(lp);
-		}
-	}
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->irq_busy = 0;
-	spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-static void at86rf230_irqwork_level(struct work_struct *work)
-{
-	struct at86rf230_local *lp =
-		container_of(work, struct at86rf230_local, irqwork);
-
-	at86rf230_irqwork(work);
-
-	enable_irq(lp->spi->irq);
-}
-
-static irqreturn_t at86rf230_isr(int irq, void *data)
-{
-	struct at86rf230_local *lp = data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->irq_busy = 1;
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	schedule_work(&lp->irqwork);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t at86rf230_isr_level(int irq, void *data)
-{
-	disable_irq_nosync(irq);
+static struct at86rf2xx_chip_data at86rf231_data = {
+	.t_sleep_cycle = 330,
+	.t_channel_switch = 24,
+	.t_reset_to_off = 37,
+	.t_off_to_aack = 110,
+	.t_off_to_tx_on = 110,
+	.t_frame = 4096,
+	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
+	.t_tx_timeout = 2000,
+	.rssi_base_val = -91,
+	.set_channel = at86rf23x_set_channel,
+	.get_desense_steps = at86rf23x_get_desens_steps
+};
 
-	return at86rf230_isr(irq, data);
-}
+static struct at86rf2xx_chip_data at86rf212_data = {
+	.t_sleep_cycle = 330,
+	.t_channel_switch = 11,
+	.t_reset_to_off = 26,
+	.t_off_to_aack = 200,
+	.t_off_to_tx_on = 200,
+	.t_frame = 4096,
+	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
+	.t_tx_timeout = 2000,
+	.rssi_base_val = -100,
+	.set_channel = at86rf212_set_channel,
+	.get_desense_steps = at86rf212_get_desens_steps
+};
 
 static int at86rf230_hw_init(struct at86rf230_local *lp)
 {
-	int rc, irq_pol, irq_type;
-	u8 dvdd;
+	int rc, irq_type, irq_pol = IRQ_ACTIVE_HIGH;
+	unsigned int dvdd;
 	u8 csma_seed[2];
 
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
+	rc = at86rf230_sync_state_change(lp, STATE_FORCE_TRX_OFF);
 	if (rc)
 		return rc;
 
 	irq_type = irq_get_trigger_type(lp->spi->irq);
-	/* configure irq polarity, defaults to high active */
-	if (irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
+	if (irq_type == IRQ_TYPE_EDGE_FALLING)
 		irq_pol = IRQ_ACTIVE_LOW;
-	else
-		irq_pol = IRQ_ACTIVE_HIGH;
 
 	rc = at86rf230_write_subreg(lp, SR_IRQ_POLARITY, irq_pol);
 	if (rc)
 		return rc;
 
+	rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
+	if (rc)
+		return rc;
+
 	rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, IRQ_TRX_END);
 	if (rc)
 		return rc;
@@ -1004,7 +1343,8 @@ static int at86rf230_hw_init(struct at86
 	if (rc)
 		return rc;
 	/* Wait the next SLEEP cycle */
-	msleep(100);
+	usleep_range(lp->data->t_sleep_cycle,
+		     lp->data->t_sleep_cycle + 100);
 
 	rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &dvdd);
 	if (rc)
@@ -1037,18 +1377,111 @@ done:
 	return pdata;
 }
 
+static int
+at86rf230_detect_device(struct at86rf230_local *lp)
+{
+	unsigned int part, version, val;
+	u16 man_id = 0;
+	const char *chip;
+	int rc;
+
+	rc = __at86rf230_read(lp, RG_MAN_ID_0, &val);
+	if (rc)
+		return rc;
+	man_id |= val;
+
+	rc = __at86rf230_read(lp, RG_MAN_ID_1, &val);
+	if (rc)
+		return rc;
+	man_id |= (val << 8);
+
+	rc = __at86rf230_read(lp, RG_PART_NUM, &part);
+	if (rc)
+		return rc;
+
+	rc = __at86rf230_read(lp, RG_PART_NUM, &version);
+	if (rc)
+		return rc;
+
+	if (man_id != 0x001f) {
+		dev_err(&lp->spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
+			man_id >> 8, man_id & 0xFF);
+		return -EINVAL;
+	}
+
+	lp->dev->extra_tx_headroom = 0;
+	lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
+			 IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA;
+
+	switch (part) {
+	case 2:
+		chip = "at86rf230";
+		rc = -ENOTSUPP;
+		break;
+	case 3:
+		chip = "at86rf231";
+		lp->data = &at86rf231_data;
+		lp->dev->phy->channels_supported[0] = 0x7FFF800;
+		break;
+	case 7:
+		chip = "at86rf212";
+		if (version == 1) {
+			lp->data = &at86rf212_data;
+			lp->dev->flags |= IEEE802154_HW_LBT;
+			lp->dev->phy->channels_supported[0] = 0x00007FF;
+			lp->dev->phy->channels_supported[2] = 0x00007FF;
+		} else {
+			rc = -ENOTSUPP;
+		}
+		break;
+	case 11:
+		chip = "at86rf233";
+		lp->data = &at86rf233_data;
+		lp->dev->phy->channels_supported[0] = 0x7FFF800;
+		break;
+	default:
+		chip = "unkown";
+		rc = -ENOTSUPP;
+		break;
+	}
+
+	dev_info(&lp->spi->dev, "Detected %s chip version %d\n", chip, version);
+
+	return rc;
+}
+
+static void
+at86rf230_setup_spi_messages(struct at86rf230_local *lp)
+{
+	lp->state.lp = lp;
+	spi_message_init(&lp->state.msg);
+	lp->state.msg.context = &lp->state;
+	lp->state.trx.tx_buf = lp->state.buf;
+	lp->state.trx.rx_buf = lp->state.buf;
+	spi_message_add_tail(&lp->state.trx, &lp->state.msg);
+
+	lp->irq.lp = lp;
+	spi_message_init(&lp->irq.msg);
+	lp->irq.msg.context = &lp->irq;
+	lp->irq.trx.tx_buf = lp->irq.buf;
+	lp->irq.trx.rx_buf = lp->irq.buf;
+	spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
+
+	lp->tx.lp = lp;
+	spi_message_init(&lp->tx.msg);
+	lp->tx.msg.context = &lp->tx;
+	lp->tx.trx.tx_buf = lp->tx.buf;
+	lp->tx.trx.rx_buf = lp->tx.buf;
+	spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
+}
+
 static int at86rf230_probe(struct spi_device *spi)
 {
 	struct at86rf230_platform_data *pdata;
 	struct ieee802154_dev *dev;
 	struct at86rf230_local *lp;
-	u16 man_id = 0;
-	u8 part = 0, version = 0, status;
-	irq_handler_t irq_handler;
-	work_func_t irq_worker;
+	unsigned int status;
 	int rc, irq_type;
-	const char *chip;
-	struct ieee802154_ops *ops = NULL;
 
 	if (!spi->irq) {
 		dev_err(&spi->dev, "no IRQ specified\n");
@@ -1084,107 +1517,60 @@ static int at86rf230_probe(struct spi_de
 		usleep_range(120, 240);
 	}
 
-	rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
-	if (rc < 0)
-		return rc;
-
-	if (man_id != 0x001f) {
-		dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
-			man_id >> 8, man_id & 0xFF);
-		return -EINVAL;
-	}
-
-	switch (part) {
-	case 2:
-		chip = "at86rf230";
-		/* FIXME: should be easy to support; */
-		break;
-	case 3:
-		chip = "at86rf231";
-		ops = &at86rf230_ops;
-		break;
-	case 7:
-		chip = "at86rf212";
-		if (version == 1)
-			ops = &at86rf212_ops;
-		break;
-	case 11:
-		chip = "at86rf233";
-		ops = &at86rf230_ops;
-		break;
-	default:
-		chip = "UNKNOWN";
-		break;
-	}
-
-	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
-	if (!ops)
-		return -ENOTSUPP;
-
-	dev = ieee802154_alloc_device(sizeof(*lp), ops);
+	dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
 	if (!dev)
 		return -ENOMEM;
 
 	lp = dev->priv;
 	lp->dev = dev;
-	lp->part = part;
-	lp->vers = version;
-
 	lp->spi = spi;
-
 	dev->parent = &spi->dev;
-	dev->extra_tx_headroom = 0;
-	dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
 
-	irq_type = irq_get_trigger_type(spi->irq);
-	if (!irq_type)
-		irq_type = IRQF_TRIGGER_RISING;
-	if (irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		irq_worker = at86rf230_irqwork;
-		irq_handler = at86rf230_isr;
-	} else {
-		irq_worker = at86rf230_irqwork_level;
-		irq_handler = at86rf230_isr_level;
+	lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
+	if (IS_ERR(lp->regmap)) {
+		rc = PTR_ERR(lp->regmap);
+		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+			rc);
+		goto free_dev;
 	}
 
-	mutex_init(&lp->bmux);
-	INIT_WORK(&lp->irqwork, irq_worker);
+	at86rf230_setup_spi_messages(lp);
+
+	rc = at86rf230_detect_device(lp);
+	if (rc < 0)
+		goto free_dev;
+
 	spin_lock_init(&lp->lock);
 	init_completion(&lp->tx_complete);
+	init_completion(&lp->state_complete);
 
 	spi_set_drvdata(spi, lp);
 
-	if (is_rf212(lp)) {
-		dev->phy->channels_supported[0] = 0x00007FF;
-		dev->phy->channels_supported[2] = 0x00007FF;
-	} else {
-		dev->phy->channels_supported[0] = 0x7FFF800;
-	}
-
 	rc = at86rf230_hw_init(lp);
 	if (rc)
-		goto err_hw_init;
+		goto free_dev;
 
 	/* Read irq status register to reset irq line */
 	rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
 	if (rc)
-		goto err_hw_init;
+		goto free_dev;
 
-	rc = devm_request_irq(&spi->dev, spi->irq, irq_handler,
-			      IRQF_SHARED | irq_type,
-			      dev_name(&spi->dev), lp);
+	irq_type = irq_get_trigger_type(spi->irq);
+	if (!irq_type)
+		irq_type = IRQF_TRIGGER_RISING;
+
+	rc = devm_request_irq(&spi->dev, spi->irq, at86rf230_isr,
+			      IRQF_SHARED | irq_type, dev_name(&spi->dev), lp);
 	if (rc)
-		goto err_hw_init;
+		goto free_dev;
 
 	rc = ieee802154_register_device(lp->dev);
 	if (rc)
-		goto err_hw_init;
+		goto free_dev;
 
 	return rc;
 
-err_hw_init:
-	flush_work(&lp->irqwork);
-	mutex_destroy(&lp->bmux);
+free_dev:
 	ieee802154_free_device(lp->dev);
 
 	return rc;
@@ -1197,8 +1583,6 @@ static int at86rf230_remove(struct spi_d
 	/* mask all at86rf230 irq's */
 	at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
 	ieee802154_unregister_device(lp->dev);
-	flush_work(&lp->irqwork);
-	mutex_destroy(&lp->bmux);
 	ieee802154_free_device(lp->dev);
 	dev_dbg(&spi->dev, "unregistered at86rf230\n");
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/cc2520.c linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/cc2520.c
--- linux-libre-3.16-gnu/drivers/net/ieee802154/cc2520.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/cc2520.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1039 @@
+/* Driver for TI CC2520 802.15.4 Wireless-PAN Networking controller
+ *
+ * Copyright (C) 2014 Varka Bhadram <varkab@cdac.in>
+ *		      Md.Jamal Mohiuddin <mjmohiuddin@cdac.in>
+ *		      P Sowjanya <sowjanyap@cdac.in>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/cc2520.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of_gpio.h>
+
+#include <net/mac802154.h>
+#include <net/wpan-phy.h>
+#include <net/ieee802154.h>
+
+#define	SPI_COMMAND_BUFFER	3
+#define	HIGH			1
+#define	LOW			0
+#define	STATE_IDLE		0
+#define	RSSI_VALID		0
+#define	RSSI_OFFSET		78
+
+#define	CC2520_RAM_SIZE		640
+#define	CC2520_FIFO_SIZE	128
+
+#define	CC2520RAM_TXFIFO	0x100
+#define	CC2520RAM_RXFIFO	0x180
+#define	CC2520RAM_IEEEADDR	0x3EA
+#define	CC2520RAM_PANID		0x3F2
+#define	CC2520RAM_SHORTADDR	0x3F4
+
+#define	CC2520_FREG_MASK	0x3F
+
+/* status byte values */
+#define	CC2520_STATUS_XOSC32M_STABLE	(1 << 7)
+#define	CC2520_STATUS_RSSI_VALID	(1 << 6)
+#define	CC2520_STATUS_TX_UNDERFLOW	(1 << 3)
+
+/* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
+#define	CC2520_MINCHANNEL		11
+#define	CC2520_MAXCHANNEL		26
+#define	CC2520_CHANNEL_SPACING		5
+
+/* command strobes */
+#define	CC2520_CMD_SNOP			0x00
+#define	CC2520_CMD_IBUFLD		0x02
+#define	CC2520_CMD_SIBUFEX		0x03
+#define	CC2520_CMD_SSAMPLECCA		0x04
+#define	CC2520_CMD_SRES			0x0f
+#define	CC2520_CMD_MEMORY_MASK		0x0f
+#define	CC2520_CMD_MEMORY_READ		0x10
+#define	CC2520_CMD_MEMORY_WRITE		0x20
+#define	CC2520_CMD_RXBUF		0x30
+#define	CC2520_CMD_RXBUFCP		0x38
+#define	CC2520_CMD_RXBUFMOV		0x32
+#define	CC2520_CMD_TXBUF		0x3A
+#define	CC2520_CMD_TXBUFCP		0x3E
+#define	CC2520_CMD_RANDOM		0x3C
+#define	CC2520_CMD_SXOSCON		0x40
+#define	CC2520_CMD_STXCAL		0x41
+#define	CC2520_CMD_SRXON		0x42
+#define	CC2520_CMD_STXON		0x43
+#define	CC2520_CMD_STXONCCA		0x44
+#define	CC2520_CMD_SRFOFF		0x45
+#define	CC2520_CMD_SXOSCOFF		0x46
+#define	CC2520_CMD_SFLUSHRX		0x47
+#define	CC2520_CMD_SFLUSHTX		0x48
+#define	CC2520_CMD_SACK			0x49
+#define	CC2520_CMD_SACKPEND		0x4A
+#define	CC2520_CMD_SNACK		0x4B
+#define	CC2520_CMD_SRXMASKBITSET	0x4C
+#define	CC2520_CMD_SRXMASKBITCLR	0x4D
+#define	CC2520_CMD_RXMASKAND		0x4E
+#define	CC2520_CMD_RXMASKOR		0x4F
+#define	CC2520_CMD_MEMCP		0x50
+#define	CC2520_CMD_MEMCPR		0x52
+#define	CC2520_CMD_MEMXCP		0x54
+#define	CC2520_CMD_MEMXWR		0x56
+#define	CC2520_CMD_BCLR			0x58
+#define	CC2520_CMD_BSET			0x59
+#define	CC2520_CMD_CTR_UCTR		0x60
+#define	CC2520_CMD_CBCMAC		0x64
+#define	CC2520_CMD_UCBCMAC		0x66
+#define	CC2520_CMD_CCM			0x68
+#define	CC2520_CMD_UCCM			0x6A
+#define	CC2520_CMD_ECB			0x70
+#define	CC2520_CMD_ECBO			0x72
+#define	CC2520_CMD_ECBX			0x74
+#define	CC2520_CMD_INC			0x78
+#define	CC2520_CMD_ABORT		0x7F
+#define	CC2520_CMD_REGISTER_READ	0x80
+#define	CC2520_CMD_REGISTER_WRITE	0xC0
+
+/* status registers */
+#define	CC2520_CHIPID			0x40
+#define	CC2520_VERSION			0x42
+#define	CC2520_EXTCLOCK			0x44
+#define	CC2520_MDMCTRL0			0x46
+#define	CC2520_MDMCTRL1			0x47
+#define	CC2520_FREQEST			0x48
+#define	CC2520_RXCTRL			0x4A
+#define	CC2520_FSCTRL			0x4C
+#define	CC2520_FSCAL0			0x4E
+#define	CC2520_FSCAL1			0x4F
+#define	CC2520_FSCAL2			0x50
+#define	CC2520_FSCAL3			0x51
+#define	CC2520_AGCCTRL0			0x52
+#define	CC2520_AGCCTRL1			0x53
+#define	CC2520_AGCCTRL2			0x54
+#define	CC2520_AGCCTRL3			0x55
+#define	CC2520_ADCTEST0			0x56
+#define	CC2520_ADCTEST1			0x57
+#define	CC2520_ADCTEST2			0x58
+#define	CC2520_MDMTEST0			0x5A
+#define	CC2520_MDMTEST1			0x5B
+#define	CC2520_DACTEST0			0x5C
+#define	CC2520_DACTEST1			0x5D
+#define	CC2520_ATEST			0x5E
+#define	CC2520_DACTEST2			0x5F
+#define	CC2520_PTEST0			0x60
+#define	CC2520_PTEST1			0x61
+#define	CC2520_RESERVED			0x62
+#define	CC2520_DPUBIST			0x7A
+#define	CC2520_ACTBIST			0x7C
+#define	CC2520_RAMBIST			0x7E
+
+/* frame registers */
+#define	CC2520_FRMFILT0			0x00
+#define	CC2520_FRMFILT1			0x01
+#define	CC2520_SRCMATCH			0x02
+#define	CC2520_SRCSHORTEN0		0x04
+#define	CC2520_SRCSHORTEN1		0x05
+#define	CC2520_SRCSHORTEN2		0x06
+#define	CC2520_SRCEXTEN0		0x08
+#define	CC2520_SRCEXTEN1		0x09
+#define	CC2520_SRCEXTEN2		0x0A
+#define	CC2520_FRMCTRL0			0x0C
+#define	CC2520_FRMCTRL1			0x0D
+#define	CC2520_RXENABLE0		0x0E
+#define	CC2520_RXENABLE1		0x0F
+#define	CC2520_EXCFLAG0			0x10
+#define	CC2520_EXCFLAG1			0x11
+#define	CC2520_EXCFLAG2			0x12
+#define	CC2520_EXCMASKA0		0x14
+#define	CC2520_EXCMASKA1		0x15
+#define	CC2520_EXCMASKA2		0x16
+#define	CC2520_EXCMASKB0		0x18
+#define	CC2520_EXCMASKB1		0x19
+#define	CC2520_EXCMASKB2		0x1A
+#define	CC2520_EXCBINDX0		0x1C
+#define	CC2520_EXCBINDX1		0x1D
+#define	CC2520_EXCBINDY0		0x1E
+#define	CC2520_EXCBINDY1		0x1F
+#define	CC2520_GPIOCTRL0		0x20
+#define	CC2520_GPIOCTRL1		0x21
+#define	CC2520_GPIOCTRL2		0x22
+#define	CC2520_GPIOCTRL3		0x23
+#define	CC2520_GPIOCTRL4		0x24
+#define	CC2520_GPIOCTRL5		0x25
+#define	CC2520_GPIOPOLARITY		0x26
+#define	CC2520_GPIOCTRL			0x28
+#define	CC2520_DPUCON			0x2A
+#define	CC2520_DPUSTAT			0x2C
+#define	CC2520_FREQCTRL			0x2E
+#define	CC2520_FREQTUNE			0x2F
+#define	CC2520_TXPOWER			0x30
+#define	CC2520_TXCTRL			0x31
+#define	CC2520_FSMSTAT0			0x32
+#define	CC2520_FSMSTAT1			0x33
+#define	CC2520_FIFOPCTRL		0x34
+#define	CC2520_FSMCTRL			0x35
+#define	CC2520_CCACTRL0			0x36
+#define	CC2520_CCACTRL1			0x37
+#define	CC2520_RSSI			0x38
+#define	CC2520_RSSISTAT			0x39
+#define	CC2520_RXFIRST			0x3C
+#define	CC2520_RXFIFOCNT		0x3E
+#define	CC2520_TXFIFOCNT		0x3F
+
+/* Driver private information */
+struct cc2520_private {
+	struct spi_device *spi;		/* SPI device structure */
+	struct ieee802154_dev *dev;	/* IEEE-802.15.4 device */
+	u8 *buf;			/* SPI TX/Rx data buffer */
+	struct mutex buffer_mutex;	/* SPI buffer mutex */
+	bool is_tx;			/* Flag for sync b/w Tx and Rx */
+	int fifo_pin;			/* FIFO GPIO pin number */
+	struct work_struct fifop_irqwork;/* Workqueue for FIFOP */
+	spinlock_t lock;		/* Lock for is_tx*/
+	struct completion tx_complete;	/* Work completion for Tx */
+};
+
+/* Generic Functions */
+static int
+cc2520_cmd_strobe(struct cc2520_private *priv, u8 cmd)
+{
+	int ret;
+	u8 status = 0xff;
+	struct spi_message msg;
+	struct spi_transfer xfer = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer.len++] = cmd;
+	dev_vdbg(&priv->spi->dev,
+		 "command strobe buf[0] = %02x\n",
+		 priv->buf[0]);
+
+	ret = spi_sync(priv->spi, &msg);
+	if (!ret)
+		status = priv->buf[0];
+	dev_vdbg(&priv->spi->dev,
+		 "buf[0] = %02x\n", priv->buf[0]);
+	mutex_unlock(&priv->buffer_mutex);
+
+	return ret;
+}
+
+static int
+cc2520_get_status(struct cc2520_private *priv, u8 *status)
+{
+	int ret;
+	struct spi_message msg;
+	struct spi_transfer xfer = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer.len++] = CC2520_CMD_SNOP;
+	dev_vdbg(&priv->spi->dev,
+		 "get status command buf[0] = %02x\n", priv->buf[0]);
+
+	ret = spi_sync(priv->spi, &msg);
+	if (!ret)
+		*status = priv->buf[0];
+	dev_vdbg(&priv->spi->dev,
+		 "buf[0] = %02x\n", priv->buf[0]);
+	mutex_unlock(&priv->buffer_mutex);
+
+	return ret;
+}
+
+static int
+cc2520_write_register(struct cc2520_private *priv, u8 reg, u8 value)
+{
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+
+	if (reg <= CC2520_FREG_MASK) {
+		priv->buf[xfer.len++] = CC2520_CMD_REGISTER_WRITE | reg;
+		priv->buf[xfer.len++] = value;
+	} else {
+		priv->buf[xfer.len++] = CC2520_CMD_MEMORY_WRITE;
+		priv->buf[xfer.len++] = reg;
+		priv->buf[xfer.len++] = value;
+	}
+	status = spi_sync(priv->spi, &msg);
+	if (msg.status)
+		status = msg.status;
+
+	mutex_unlock(&priv->buffer_mutex);
+
+	return status;
+}
+
+static int
+cc2520_write_ram(struct cc2520_private *priv, u16 reg, u8 len, u8 *data)
+{
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer_head = {
+		.len        = 0,
+		.tx_buf        = priv->buf,
+		.rx_buf        = priv->buf,
+	};
+
+	struct spi_transfer xfer_buf = {
+		.len = len,
+		.tx_buf = data,
+	};
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer_head.len++] = (CC2520_CMD_MEMORY_WRITE |
+						((reg >> 8) & 0xff));
+	priv->buf[xfer_head.len++] = reg & 0xff;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer_head, &msg);
+	spi_message_add_tail(&xfer_buf, &msg);
+
+	status = spi_sync(priv->spi, &msg);
+	dev_dbg(&priv->spi->dev, "spi status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+
+	mutex_unlock(&priv->buffer_mutex);
+	return status;
+}
+
+static int
+cc2520_read_register(struct cc2520_private *priv, u8 reg, u8 *data)
+{
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer1 = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+
+	struct spi_transfer xfer2 = {
+		.len = 1,
+		.rx_buf = data,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer1, &msg);
+	spi_message_add_tail(&xfer2, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer1.len++] = CC2520_CMD_MEMORY_READ;
+	priv->buf[xfer1.len++] = reg;
+
+	status = spi_sync(priv->spi, &msg);
+	dev_dbg(&priv->spi->dev,
+		"spi status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+
+	mutex_unlock(&priv->buffer_mutex);
+
+	return status;
+}
+
+static int
+cc2520_write_txfifo(struct cc2520_private *priv, u8 *data, u8 len)
+{
+	int status;
+
+	/* length byte must include FCS even
+	 * if it is calculated in the hardware
+	 */
+	int len_byte = len + 2;
+
+	struct spi_message msg;
+
+	struct spi_transfer xfer_head = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+	struct spi_transfer xfer_len = {
+		.len = 1,
+		.tx_buf = &len_byte,
+	};
+	struct spi_transfer xfer_buf = {
+		.len = len,
+		.tx_buf = data,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer_head, &msg);
+	spi_message_add_tail(&xfer_len, &msg);
+	spi_message_add_tail(&xfer_buf, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer_head.len++] = CC2520_CMD_TXBUF;
+	dev_vdbg(&priv->spi->dev,
+		 "TX_FIFO cmd buf[0] = %02x\n", priv->buf[0]);
+
+	status = spi_sync(priv->spi, &msg);
+	dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+	dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+	dev_vdbg(&priv->spi->dev, "buf[0] = %02x\n", priv->buf[0]);
+	mutex_unlock(&priv->buffer_mutex);
+
+	return status;
+}
+
+static int
+cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len, u8 *lqi)
+{
+	int status;
+	struct spi_message msg;
+
+	struct spi_transfer xfer_head = {
+		.len = 0,
+		.tx_buf = priv->buf,
+		.rx_buf = priv->buf,
+	};
+	struct spi_transfer xfer_buf = {
+		.len = len,
+		.rx_buf = data,
+	};
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer_head, &msg);
+	spi_message_add_tail(&xfer_buf, &msg);
+
+	mutex_lock(&priv->buffer_mutex);
+	priv->buf[xfer_head.len++] = CC2520_CMD_RXBUF;
+
+	dev_vdbg(&priv->spi->dev, "read rxfifo buf[0] = %02x\n", priv->buf[0]);
+	dev_vdbg(&priv->spi->dev, "buf[1] = %02x\n", priv->buf[1]);
+
+	status = spi_sync(priv->spi, &msg);
+	dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+	if (msg.status)
+		status = msg.status;
+	dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+	dev_vdbg(&priv->spi->dev,
+		 "return status buf[0] = %02x\n", priv->buf[0]);
+	dev_vdbg(&priv->spi->dev, "length buf[1] = %02x\n", priv->buf[1]);
+
+	mutex_unlock(&priv->buffer_mutex);
+
+	return status;
+}
+
+static int cc2520_start(struct ieee802154_dev *dev)
+{
+	return cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRXON);
+}
+
+static void cc2520_stop(struct ieee802154_dev *dev)
+{
+	cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRFOFF);
+}
+
+static int
+cc2520_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+{
+	struct cc2520_private *priv = dev->priv;
+	unsigned long flags;
+	int rc;
+	u8 status = 0;
+
+	rc = cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
+	if (rc)
+		goto err_tx;
+
+	rc = cc2520_write_txfifo(priv, skb->data, skb->len);
+	if (rc)
+		goto err_tx;
+
+	rc = cc2520_get_status(priv, &status);
+	if (rc)
+		goto err_tx;
+
+	if (status & CC2520_STATUS_TX_UNDERFLOW) {
+		dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
+		goto err_tx;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	BUG_ON(priv->is_tx);
+	priv->is_tx = 1;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	rc = cc2520_cmd_strobe(priv, CC2520_CMD_STXONCCA);
+	if (rc)
+		goto err;
+
+	rc = wait_for_completion_interruptible(&priv->tx_complete);
+	if (rc < 0)
+		goto err;
+
+	cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
+	cc2520_cmd_strobe(priv, CC2520_CMD_SRXON);
+
+	return rc;
+err:
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->is_tx = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+err_tx:
+	return rc;
+}
+
+
+static int cc2520_rx(struct cc2520_private *priv)
+{
+	u8 len = 0, lqi = 0, bytes = 1;
+	struct sk_buff *skb;
+
+	cc2520_read_rxfifo(priv, &len, bytes, &lqi);
+
+	if (len < 2 || len > IEEE802154_MTU)
+		return -EINVAL;
+
+	skb = alloc_skb(len, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	if (cc2520_read_rxfifo(priv, skb_put(skb, len), len, &lqi)) {
+		dev_dbg(&priv->spi->dev, "frame reception failed\n");
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+
+	skb_trim(skb, skb->len - 2);
+
+	ieee802154_rx_irqsafe(priv->dev, skb, lqi);
+
+	dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
+
+	return 0;
+}
+
+static int
+cc2520_ed(struct ieee802154_dev *dev, u8 *level)
+{
+	struct cc2520_private *priv = dev->priv;
+	u8 status = 0xff;
+	u8 rssi;
+	int ret;
+
+	ret = cc2520_read_register(priv , CC2520_RSSISTAT, &status);
+	if (ret)
+		return ret;
+
+	if (status != RSSI_VALID)
+		return -EINVAL;
+
+	ret = cc2520_read_register(priv , CC2520_RSSI, &rssi);
+	if (ret)
+		return ret;
+
+	/* level = RSSI(rssi) - OFFSET [dBm] : offset is 76dBm */
+	*level = rssi - RSSI_OFFSET;
+
+	return 0;
+}
+
+static int
+cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel)
+{
+	struct cc2520_private *priv = dev->priv;
+	int ret;
+
+	might_sleep();
+	dev_dbg(&priv->spi->dev, "trying to set channel\n");
+
+	BUG_ON(page != 0);
+	BUG_ON(channel < CC2520_MINCHANNEL);
+	BUG_ON(channel > CC2520_MAXCHANNEL);
+
+	ret = cc2520_write_register(priv, CC2520_FREQCTRL,
+				    11 + 5*(channel - 11));
+
+	return ret;
+}
+
+static int
+cc2520_filter(struct ieee802154_dev *dev,
+	      struct ieee802154_hw_addr_filt *filt, unsigned long changed)
+{
+	struct cc2520_private *priv = dev->priv;
+
+	if (changed & IEEE802515_AFILT_PANID_CHANGED) {
+		u16 panid = le16_to_cpu(filt->pan_id);
+
+		dev_vdbg(&priv->spi->dev,
+			 "cc2520_filter called for pan id\n");
+		cc2520_write_ram(priv, CC2520RAM_PANID,
+				 sizeof(panid), (u8 *)&panid);
+	}
+
+	if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
+		dev_vdbg(&priv->spi->dev,
+			 "cc2520_filter called for IEEE addr\n");
+		cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
+				 sizeof(filt->ieee_addr),
+				 (u8 *)&filt->ieee_addr);
+	}
+
+	if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
+		u16 addr = le16_to_cpu(filt->short_addr);
+
+		dev_vdbg(&priv->spi->dev,
+			 "cc2520_filter called for saddr\n");
+		cc2520_write_ram(priv, CC2520RAM_SHORTADDR,
+				 sizeof(addr), (u8 *)&addr);
+	}
+
+	if (changed & IEEE802515_AFILT_PANC_CHANGED) {
+		dev_vdbg(&priv->spi->dev,
+			 "cc2520_filter called for panc change\n");
+		if (filt->pan_coord)
+			cc2520_write_register(priv, CC2520_FRMFILT0, 0x02);
+		else
+			cc2520_write_register(priv, CC2520_FRMFILT0, 0x00);
+	}
+
+	return 0;
+}
+
+static struct ieee802154_ops cc2520_ops = {
+	.owner = THIS_MODULE,
+	.start = cc2520_start,
+	.stop = cc2520_stop,
+	.xmit = cc2520_tx,
+	.ed = cc2520_ed,
+	.set_channel = cc2520_set_channel,
+	.set_hw_addr_filt = cc2520_filter,
+};
+
+static int cc2520_register(struct cc2520_private *priv)
+{
+	int ret = -ENOMEM;
+
+	priv->dev = ieee802154_alloc_device(sizeof(*priv), &cc2520_ops);
+	if (!priv->dev)
+		goto err_ret;
+
+	priv->dev->priv = priv;
+	priv->dev->parent = &priv->spi->dev;
+	priv->dev->extra_tx_headroom = 0;
+
+	/* We do support only 2.4 Ghz */
+	priv->dev->phy->channels_supported[0] = 0x7FFF800;
+	priv->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
+
+	dev_vdbg(&priv->spi->dev, "registered cc2520\n");
+	ret = ieee802154_register_device(priv->dev);
+	if (ret)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	ieee802154_free_device(priv->dev);
+err_ret:
+	return ret;
+}
+
+static void cc2520_fifop_irqwork(struct work_struct *work)
+{
+	struct cc2520_private *priv
+		= container_of(work, struct cc2520_private, fifop_irqwork);
+
+	dev_dbg(&priv->spi->dev, "fifop interrupt received\n");
+
+	if (gpio_get_value(priv->fifo_pin))
+		cc2520_rx(priv);
+	else
+		dev_dbg(&priv->spi->dev, "rxfifo overflow\n");
+
+	cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
+	cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
+}
+
+static irqreturn_t cc2520_fifop_isr(int irq, void *data)
+{
+	struct cc2520_private *priv = data;
+
+	schedule_work(&priv->fifop_irqwork);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t cc2520_sfd_isr(int irq, void *data)
+{
+	struct cc2520_private *priv = data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->is_tx) {
+		priv->is_tx = 0;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		dev_dbg(&priv->spi->dev, "SFD for TX\n");
+		complete(&priv->tx_complete);
+	} else {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		dev_dbg(&priv->spi->dev, "SFD for RX\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cc2520_hw_init(struct cc2520_private *priv)
+{
+	u8 status = 0, state = 0xff;
+	int ret;
+	int timeout = 100;
+
+	ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state);
+	if (ret)
+		goto err_ret;
+
+	if (state != STATE_IDLE)
+		return -EINVAL;
+
+	do {
+		ret = cc2520_get_status(priv, &status);
+		if (ret)
+			goto err_ret;
+
+		if (timeout-- <= 0) {
+			dev_err(&priv->spi->dev, "oscillator start failed!\n");
+			return ret;
+		}
+		udelay(1);
+	} while (!(status & CC2520_STATUS_XOSC32M_STABLE));
+
+	dev_vdbg(&priv->spi->dev, "oscillator brought up\n");
+
+	/* Registers default value: section 28.1 in Datasheet */
+	ret = cc2520_write_register(priv, CC2520_TXPOWER, 0xF7);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FRMCTRL0, 0x60);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FRMCTRL1, 0x03);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FRMFILT0, 0x00);
+	if (ret)
+		goto err_ret;
+
+	ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127);
+	if (ret)
+		goto err_ret;
+
+	return 0;
+
+err_ret:
+	return ret;
+}
+
+static struct cc2520_platform_data *
+cc2520_get_platform_data(struct spi_device *spi)
+{
+	struct cc2520_platform_data *pdata;
+	struct device_node *np = spi->dev.of_node;
+	struct cc2520_private *priv = spi_get_drvdata(spi);
+
+	if (!np)
+		return spi->dev.platform_data;
+
+	pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		goto done;
+
+	pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0);
+	priv->fifo_pin = pdata->fifo;
+
+	pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0);
+
+	pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0);
+	pdata->cca = of_get_named_gpio(np, "cca-gpio", 0);
+	pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0);
+	pdata->reset = of_get_named_gpio(np, "reset-gpio", 0);
+
+	spi->dev.platform_data = pdata;
+
+done:
+	return pdata;
+}
+
+static int cc2520_probe(struct spi_device *spi)
+{
+	struct cc2520_private *priv;
+	struct pinctrl *pinctrl;
+	struct cc2520_platform_data *pdata;
+	int ret;
+
+	priv = devm_kzalloc(&spi->dev,
+			    sizeof(struct cc2520_private), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_ret;
+	}
+
+	spi_set_drvdata(spi, priv);
+
+	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&spi->dev,
+			 "pinctrl pins are not configured");
+
+	pdata = cc2520_get_platform_data(spi);
+	if (!pdata) {
+		dev_err(&spi->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	priv->spi = spi;
+
+	priv->buf = devm_kzalloc(&spi->dev,
+				 SPI_COMMAND_BUFFER, GFP_KERNEL);
+	if (!priv->buf) {
+		ret = -ENOMEM;
+		goto err_ret;
+	}
+
+	mutex_init(&priv->buffer_mutex);
+	INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork);
+	spin_lock_init(&priv->lock);
+	init_completion(&priv->tx_complete);
+
+	/* Request all the gpio's */
+	if (!gpio_is_valid(pdata->fifo)) {
+		dev_err(&spi->dev, "fifo gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->fifo,
+				    GPIOF_IN, "fifo");
+	if (ret)
+		goto err_hw_init;
+
+	if (!gpio_is_valid(pdata->cca)) {
+		dev_err(&spi->dev, "cca gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->cca,
+				    GPIOF_IN, "cca");
+	if (ret)
+		goto err_hw_init;
+
+	if (!gpio_is_valid(pdata->fifop)) {
+		dev_err(&spi->dev, "fifop gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->fifop,
+				    GPIOF_IN, "fifop");
+	if (ret)
+		goto err_hw_init;
+
+	if (!gpio_is_valid(pdata->sfd)) {
+		dev_err(&spi->dev, "sfd gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->sfd,
+				    GPIOF_IN, "sfd");
+	if (ret)
+		goto err_hw_init;
+
+	if (!gpio_is_valid(pdata->reset)) {
+		dev_err(&spi->dev, "reset gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->reset,
+				    GPIOF_OUT_INIT_LOW, "reset");
+	if (ret)
+		goto err_hw_init;
+
+	if (!gpio_is_valid(pdata->vreg)) {
+		dev_err(&spi->dev, "vreg gpio is not valid\n");
+		ret = -EINVAL;
+		goto err_hw_init;
+	}
+
+	ret = devm_gpio_request_one(&spi->dev, pdata->vreg,
+				    GPIOF_OUT_INIT_LOW, "vreg");
+	if (ret)
+		goto err_hw_init;
+
+
+	gpio_set_value(pdata->vreg, HIGH);
+	usleep_range(100, 150);
+
+	gpio_set_value(pdata->reset, HIGH);
+	usleep_range(200, 250);
+
+	ret = cc2520_hw_init(priv);
+	if (ret)
+		goto err_hw_init;
+
+	/* Set up fifop interrupt */
+	ret = devm_request_irq(&spi->dev,
+			       gpio_to_irq(pdata->fifop),
+			       cc2520_fifop_isr,
+			       IRQF_TRIGGER_RISING,
+			       dev_name(&spi->dev),
+			       priv);
+	if (ret) {
+		dev_err(&spi->dev, "could not get fifop irq\n");
+		goto err_hw_init;
+	}
+
+	/* Set up sfd interrupt */
+	ret = devm_request_irq(&spi->dev,
+			       gpio_to_irq(pdata->sfd),
+			       cc2520_sfd_isr,
+			       IRQF_TRIGGER_FALLING,
+			       dev_name(&spi->dev),
+			       priv);
+	if (ret) {
+		dev_err(&spi->dev, "could not get sfd irq\n");
+		goto err_hw_init;
+	}
+
+	ret = cc2520_register(priv);
+	if (ret)
+		goto err_hw_init;
+
+	return 0;
+
+err_hw_init:
+	mutex_destroy(&priv->buffer_mutex);
+	flush_work(&priv->fifop_irqwork);
+
+err_ret:
+	return ret;
+}
+
+static int cc2520_remove(struct spi_device *spi)
+{
+	struct cc2520_private *priv = spi_get_drvdata(spi);
+
+	mutex_destroy(&priv->buffer_mutex);
+	flush_work(&priv->fifop_irqwork);
+
+	ieee802154_unregister_device(priv->dev);
+	ieee802154_free_device(priv->dev);
+
+	return 0;
+}
+
+static const struct spi_device_id cc2520_ids[] = {
+	{"cc2520", },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, cc2520_ids);
+
+static const struct of_device_id cc2520_of_ids[] = {
+	{.compatible = "ti,cc2520", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cc2520_of_ids);
+
+/* SPI driver structure */
+static struct spi_driver cc2520_driver = {
+	.driver = {
+		.name = "cc2520",
+		.bus = &spi_bus_type,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(cc2520_of_ids),
+	},
+	.id_table = cc2520_ids,
+	.probe = cc2520_probe,
+	.remove = cc2520_remove,
+};
+module_spi_driver(cc2520_driver);
+
+MODULE_AUTHOR("Varka Bhadram <varkab@cdac.in>");
+MODULE_DESCRIPTION("CC2520 Transceiver Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/fakehard.c linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/fakehard.c
--- linux-libre-3.16-gnu/drivers/net/ieee802154/fakehard.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/fakehard.c	2014-09-28 17:29:07.000000000 -0400
@@ -343,7 +343,8 @@ static int ieee802154fake_probe(struct p
 	if (!phy)
 		return -ENOMEM;
 
-	dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d", ieee802154_fake_setup);
+	dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d",
+			   NET_NAME_UNKNOWN, ieee802154_fake_setup);
 	if (!dev) {
 		wpan_phy_free(phy);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/Kconfig
--- linux-libre-3.16-gnu/drivers/net/ieee802154/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@ config IEEE802154_AT86RF230
 	depends on IEEE802154_DRIVERS && MAC802154
 	tristate "AT86RF230/231/233/212 transceiver driver"
 	depends on SPI
+	select REGMAP_SPI
 	---help---
 	  Say Y here to enable the at86rf230/231/233/212 SPI 802.15.4 wireless
 	  controller.
@@ -51,3 +52,14 @@ config IEEE802154_MRF24J40
 
 	  This driver can also be built as a module. To do so, say M here.
 	  the module will be called 'mrf24j40'.
+
+config IEEE802154_CC2520
+	depends on IEEE802154_DRIVERS && MAC802154
+	tristate "CC2520 transceiver driver"
+	depends on SPI
+	---help---
+	  Say Y here to enable the CC2520 SPI 802.15.4 wireless
+	  controller.
+
+	  This driver can also be built as a module. To do so, say M here.
+	  the module will be called 'cc2520'.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/Makefile linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/Makefile
--- linux-libre-3.16-gnu/drivers/net/ieee802154/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,3 +2,4 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fak
 obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
 obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
 obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
+obj-$(CONFIG_IEEE802154_CC2520) += cc2520.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ieee802154/mrf24j40.c linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/mrf24j40.c
--- linux-libre-3.16-gnu/drivers/net/ieee802154/mrf24j40.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ieee802154/mrf24j40.c	2014-09-28 17:29:07.000000000 -0400
@@ -610,10 +610,95 @@ out:
 	return IRQ_HANDLED;
 }
 
+static int mrf24j40_hw_init(struct mrf24j40 *devrec)
+{
+	int ret;
+	u8 val;
+
+	/* Initialize the device.
+		From datasheet section 3.2: Initialization. */
+	ret = write_short_reg(devrec, REG_SOFTRST, 0x07);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_PACON2, 0x98);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_TXSTBL, 0x95);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON0, 0x03);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON1, 0x01);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON2, 0x80);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON6, 0x90);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON7, 0x80);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_RFCON8, 0x10);
+	if (ret)
+		goto err_ret;
+
+	ret = write_long_reg(devrec, REG_SLPCON1, 0x21);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_BBREG2, 0x80);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_CCAEDTH, 0x60);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_BBREG6, 0x40);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_RFCTL, 0x04);
+	if (ret)
+		goto err_ret;
+
+	ret = write_short_reg(devrec, REG_RFCTL, 0x0);
+	if (ret)
+		goto err_ret;
+
+	udelay(192);
+
+	/* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
+	ret = read_short_reg(devrec, REG_RXMCR, &val);
+	if (ret)
+		goto err_ret;
+
+	val &= ~0x3; /* Clear RX mode (normal) */
+
+	ret = write_short_reg(devrec, REG_RXMCR, val);
+	if (ret)
+		goto err_ret;
+
+	return 0;
+
+err_ret:
+	return ret;
+}
+
 static int mrf24j40_probe(struct spi_device *spi)
 {
 	int ret = -ENOMEM;
-	u8 val;
 	struct mrf24j40 *devrec;
 
 	printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
@@ -650,31 +735,9 @@ static int mrf24j40_probe(struct spi_dev
 	if (ret)
 		goto err_register_device;
 
-	/* Initialize the device.
-		From datasheet section 3.2: Initialization. */
-	write_short_reg(devrec, REG_SOFTRST, 0x07);
-	write_short_reg(devrec, REG_PACON2, 0x98);
-	write_short_reg(devrec, REG_TXSTBL, 0x95);
-	write_long_reg(devrec, REG_RFCON0, 0x03);
-	write_long_reg(devrec, REG_RFCON1, 0x01);
-	write_long_reg(devrec, REG_RFCON2, 0x80);
-	write_long_reg(devrec, REG_RFCON6, 0x90);
-	write_long_reg(devrec, REG_RFCON7, 0x80);
-	write_long_reg(devrec, REG_RFCON8, 0x10);
-	write_long_reg(devrec, REG_SLPCON1, 0x21);
-	write_short_reg(devrec, REG_BBREG2, 0x80);
-	write_short_reg(devrec, REG_CCAEDTH, 0x60);
-	write_short_reg(devrec, REG_BBREG6, 0x40);
-	write_short_reg(devrec, REG_RFCTL, 0x04);
-	write_short_reg(devrec, REG_RFCTL, 0x0);
-	udelay(192);
-
-	/* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
-	ret = read_short_reg(devrec, REG_RXMCR, &val);
+	ret = mrf24j40_hw_init(devrec);
 	if (ret)
-		goto err_read_reg;
-	val &= ~0x3; /* Clear RX mode (normal) */
-	write_short_reg(devrec, REG_RXMCR, val);
+		goto err_hw_init;
 
 	ret = devm_request_threaded_irq(&spi->dev,
 					spi->irq,
@@ -692,7 +755,7 @@ static int mrf24j40_probe(struct spi_dev
 	return 0;
 
 err_irq:
-err_read_reg:
+err_hw_init:
 	ieee802154_unregister_device(devrec->dev);
 err_register_device:
 	ieee802154_free_device(devrec->dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ifb.c linux-libre-3.17-rc7-gnu/drivers/net/ifb.c
--- linux-libre-3.16-gnu/drivers/net/ifb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ifb.c	2014-09-28 17:29:07.000000000 -0400
@@ -269,8 +269,8 @@ static int __init ifb_init_one(int index
 	struct ifb_private *dp;
 	int err;
 
-	dev_ifb = alloc_netdev(sizeof(struct ifb_private),
-				 "ifb%d", ifb_setup);
+	dev_ifb = alloc_netdev(sizeof(struct ifb_private), "ifb%d",
+			       NET_NAME_UNKNOWN, ifb_setup);
 
 	if (!dev_ifb)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/irda/au1k_ir.c linux-libre-3.17-rc7-gnu/drivers/net/irda/au1k_ir.c
--- linux-libre-3.16-gnu/drivers/net/irda/au1k_ir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/irda/au1k_ir.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
  *  with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/interrupt.h>
@@ -175,6 +176,7 @@ struct au1k_private {
 
 	struct resource *ioarea;
 	struct au1k_irda_platform_data *platdata;
+	struct clk *irda_clk;
 };
 
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -514,9 +516,39 @@ static irqreturn_t au1k_irda_interrupt(i
 static int au1k_init(struct net_device *dev)
 {
 	struct au1k_private *aup = netdev_priv(dev);
-	u32 enable, ring_address;
+	u32 enable, ring_address, phyck;
+	struct clk *c;
 	int i;
 
+	c = clk_get(NULL, "irda_clk");
+	if (IS_ERR(c))
+		return PTR_ERR(c);
+	i = clk_prepare_enable(c);
+	if (i) {
+		clk_put(c);
+		return i;
+	}
+
+	switch (clk_get_rate(c)) {
+	case 40000000:
+		phyck = IR_PHYCLK_40MHZ;
+		break;
+	case 48000000:
+		phyck = IR_PHYCLK_48MHZ;
+		break;
+	case 56000000:
+		phyck = IR_PHYCLK_56MHZ;
+		break;
+	case 64000000:
+		phyck = IR_PHYCLK_64MHZ;
+		break;
+	default:
+		clk_disable_unprepare(c);
+		clk_put(c);
+		return -EINVAL;
+	}
+	aup->irda_clk = c;
+
 	enable = IR_HC | IR_CE | IR_C;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
 	enable |= IR_BE;
@@ -545,7 +577,7 @@ static int au1k_init(struct net_device *
 	irda_write(aup, IR_RING_SIZE,
 				(RING_SIZE_64 << 8) | (RING_SIZE_64 << 12));
 
-	irda_write(aup, IR_CONFIG_2, IR_PHYCLK_48MHZ | IR_ONE_PIN);
+	irda_write(aup, IR_CONFIG_2, phyck | IR_ONE_PIN);
 	irda_write(aup, IR_RING_ADDR_CMPR, 0);
 
 	au1k_irda_set_speed(dev, 9600);
@@ -619,6 +651,9 @@ static int au1k_irda_stop(struct net_dev
 	free_irq(aup->irq_tx, dev);
 	free_irq(aup->irq_rx, dev);
 
+	clk_disable_unprepare(aup->irda_clk);
+	clk_put(aup->irda_clk);
+
 	return 0;
 }
 
@@ -853,6 +888,7 @@ static int au1k_irda_probe(struct platfo
 	struct au1k_private *aup;
 	struct net_device *dev;
 	struct resource *r;
+	struct clk *c;
 	int err;
 
 	dev = alloc_irdadev(sizeof(struct au1k_private));
@@ -886,6 +922,14 @@ static int au1k_irda_probe(struct platfo
 	if (!aup->ioarea)
 		goto out;
 
+	/* bail out early if clock doesn't exist */
+	c = clk_get(NULL, "irda_clk");
+	if (IS_ERR(c)) {
+		err = PTR_ERR(c);
+		goto out;
+	}
+	clk_put(c);
+
 	aup->iobase = ioremap_nocache(r->start, resource_size(r));
 	if (!aup->iobase)
 		goto out2;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/irda/donauboe.c linux-libre-3.17-rc7-gnu/drivers/net/irda/donauboe.c
--- linux-libre-3.16-gnu/drivers/net/irda/donauboe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/irda/donauboe.c	2014-09-28 17:29:07.000000000 -0400
@@ -184,7 +184,7 @@
 #define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC
 #define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX
 
-static DEFINE_PCI_DEVICE_TABLE(toshoboe_pci_tbl) = {
+static const struct pci_device_id toshoboe_pci_tbl[] = {
 	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, },
 	{ }			/* Terminating entry */
@@ -1755,17 +1755,4 @@ static struct pci_driver donauboe_pci_dr
 	.resume		= toshoboe_wakeup 
 };
 
-static int __init
-donauboe_init (void)
-{
-  return pci_register_driver(&donauboe_pci_driver);
-}
-
-static void __exit
-donauboe_cleanup (void)
-{
-  pci_unregister_driver(&donauboe_pci_driver);
-}
-
-module_init(donauboe_init);
-module_exit(donauboe_cleanup);
+module_pci_driver(donauboe_pci_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/irda/kingsun-sir.c linux-libre-3.17-rc7-gnu/drivers/net/irda/kingsun-sir.c
--- linux-libre-3.16-gnu/drivers/net/irda/kingsun-sir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/irda/kingsun-sir.c	2014-09-28 17:29:07.000000000 -0400
@@ -553,8 +553,8 @@ static int kingsun_probe(struct usb_inte
 	return 0;
 
 free_mem:
-	if (kingsun->out_buf) kfree(kingsun->out_buf);
-	if (kingsun->in_buf) kfree(kingsun->in_buf);
+	kfree(kingsun->out_buf);
+	kfree(kingsun->in_buf);
 	free_netdev(net);
 err_out1:
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/irda/via-ircc.c linux-libre-3.17-rc7-gnu/drivers/net/irda/via-ircc.c
--- linux-libre-3.16-gnu/drivers/net/irda/via-ircc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/irda/via-ircc.c	2014-09-28 17:29:07.000000000 -0400
@@ -115,7 +115,7 @@ static void iodelay(int udelay)
 	}
 }
 
-static DEFINE_PCI_DEVICE_TABLE(via_pci_tbl) = {
+static const struct pci_device_id via_pci_tbl[] = {
 	{ PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 },
 	{ PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 },
 	{ PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/irda/vlsi_ir.c linux-libre-3.17-rc7-gnu/drivers/net/irda/vlsi_ir.c
--- linux-libre-3.16-gnu/drivers/net/irda/vlsi_ir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/irda/vlsi_ir.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ MODULE_LICENSE("GPL");
 
 static /* const */ char drivername[] = DRIVER_NAME;
 
-static DEFINE_PCI_DEVICE_TABLE(vlsi_irda_table) = {
+static const struct pci_device_id vlsi_irda_table[] = {
 	{
 		.class =        PCI_CLASS_WIRELESS_IRDA << 8,
 		.class_mask =	PCI_CLASS_SUBCLASS_MASK << 8, 
@@ -485,13 +485,13 @@ static int vlsi_create_hwif(vlsi_irda_de
 	idev->virtaddr = NULL;
 	idev->busaddr = 0;
 
-	ringarea = pci_alloc_consistent(idev->pdev, HW_RING_AREA_SIZE, &idev->busaddr);
+	ringarea = pci_zalloc_consistent(idev->pdev, HW_RING_AREA_SIZE,
+					 &idev->busaddr);
 	if (!ringarea) {
 		IRDA_ERROR("%s: insufficient memory for descriptor rings\n",
 			   __func__);
 		goto out;
 	}
-	memset(ringarea, 0, HW_RING_AREA_SIZE);
 
 	hwmap = (struct ring_descr_hw *)ringarea;
 	idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1],
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/Kconfig
--- linux-libre-3.16-gnu/drivers/net/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -148,6 +148,7 @@ config VXLAN
        tristate "Virtual eXtensible Local Area Network (VXLAN)"
        depends on INET
        select NET_IP_TUNNEL
+       select NET_UDP_TUNNEL
        ---help---
 	  This allows one to create vxlan virtual interfaces that provide
 	  Layer 2 Networks over Layer 3 Networks. VXLAN is often used
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/loopback.c linux-libre-3.17-rc7-gnu/drivers/net/loopback.c
--- linux-libre-3.16-gnu/drivers/net/loopback.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/loopback.c	2014-09-28 17:29:07.000000000 -0400
@@ -195,7 +195,7 @@ static __net_init int loopback_net_init(
 	int err;
 
 	err = -ENOMEM;
-	dev = alloc_netdev(0, "lo", loopback_setup);
+	dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup);
 	if (!dev)
 		goto out;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/macvlan.c linux-libre-3.17-rc7-gnu/drivers/net/macvlan.c
--- linux-libre-3.16-gnu/drivers/net/macvlan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/macvlan.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/netpoll.h>
 
 #define MACVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
+#define MACVLAN_BC_QUEUE_LEN	1000
 
 struct macvlan_port {
 	struct net_device	*dev;
@@ -45,10 +46,9 @@ struct macvlan_port {
 	struct sk_buff_head	bc_queue;
 	struct work_struct	bc_work;
 	bool 			passthru;
+	int			count;
 };
 
-#define MACVLAN_PORT_IS_EMPTY(port)    list_empty(&port->vlans)
-
 struct macvlan_skb_cb {
 	const struct macvlan_dev *src;
 };
@@ -249,7 +249,7 @@ static void macvlan_broadcast_enqueue(st
 		goto err;
 
 	spin_lock(&port->bc_queue.lock);
-	if (skb_queue_len(&port->bc_queue) < skb->dev->tx_queue_len) {
+	if (skb_queue_len(&port->bc_queue) < MACVLAN_BC_QUEUE_LEN) {
 		__skb_queue_tail(&port->bc_queue, nskb);
 		err = 0;
 	}
@@ -646,6 +646,7 @@ static int macvlan_init(struct net_devic
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
 	dev->features		|= ALWAYS_ON_FEATURES;
+	dev->vlan_features	= lowerdev->vlan_features & MACVLAN_FEATURES;
 	dev->gso_max_size	= lowerdev->gso_max_size;
 	dev->iflink		= lowerdev->ifindex;
 	dev->hard_header_len	= lowerdev->hard_header_len;
@@ -666,7 +667,8 @@ static void macvlan_uninit(struct net_de
 
 	free_percpu(vlan->pcpu_stats);
 
-	if (MACVLAN_PORT_IS_EMPTY(port))
+	port->count -= 1;
+	if (!port->count)
 		macvlan_port_destroy(port->dev);
 }
 
@@ -738,7 +740,10 @@ static int macvlan_fdb_add(struct ndmsg
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	int err = -EINVAL;
 
-	if (!vlan->port->passthru)
+	/* Support unicast filter only on passthru devices.
+	 * Multicast filter should be allowed on all devices.
+	 */
+	if (!vlan->port->passthru && is_unicast_ether_addr(addr))
 		return -EOPNOTSUPP;
 
 	if (flags & NLM_F_REPLACE)
@@ -759,7 +764,10 @@ static int macvlan_fdb_del(struct ndmsg
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	int err = -EINVAL;
 
-	if (!vlan->port->passthru)
+	/* Support unicast filter only on passthru devices.
+	 * Multicast filter should be allowed on all devices.
+	 */
+	if (!vlan->port->passthru && is_unicast_ether_addr(addr))
 		return -EOPNOTSUPP;
 
 	if (is_unicast_ether_addr(addr))
@@ -799,6 +807,7 @@ static netdev_features_t macvlan_fix_fea
 					     features,
 					     mask);
 	features |= ALWAYS_ON_FEATURES;
+	features &= ~NETIF_F_NETNS_LOCAL;
 
 	return features;
 }
@@ -1019,12 +1028,13 @@ int macvlan_common_newlink(struct net *s
 		vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
 
 	if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
-		if (!MACVLAN_PORT_IS_EMPTY(port))
+		if (port->count)
 			return -EINVAL;
 		port->passthru = true;
 		eth_hw_addr_inherit(dev, lowerdev);
 	}
 
+	port->count += 1;
 	err = register_netdevice(dev);
 	if (err < 0)
 		goto destroy_port;
@@ -1042,7 +1052,8 @@ int macvlan_common_newlink(struct net *s
 unregister_netdev:
 	unregister_netdevice(dev);
 destroy_port:
-	if (MACVLAN_PORT_IS_EMPTY(port))
+	port->count -= 1;
+	if (!port->count)
 		macvlan_port_destroy(lowerdev);
 
 	return err;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/Makefile linux-libre-3.17-rc7-gnu/drivers/net/Makefile
--- linux-libre-3.16-gnu/drivers/net/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -61,15 +61,7 @@ obj-$(CONFIG_VMXNET3) += vmxnet3/
 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
 obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
 
-obj-$(CONFIG_USB_CATC)          += usb/
-obj-$(CONFIG_USB_KAWETH)        += usb/
-obj-$(CONFIG_USB_PEGASUS)       += usb/
-obj-$(CONFIG_USB_RTL8150)       += usb/
-obj-$(CONFIG_USB_HSO)		+= usb/
-obj-$(CONFIG_USB_USBNET)        += usb/
-obj-$(CONFIG_USB_ZD1201)        += usb/
-obj-$(CONFIG_USB_IPHETH)        += usb/
-obj-$(CONFIG_USB_CDC_PHONET)   += usb/
+obj-$(CONFIG_USB_NET_DRIVERS) += usb/
 
 obj-$(CONFIG_HYPERV_NET) += hyperv/
 obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/amd-xgbe-phy.c linux-libre-3.17-rc7-gnu/drivers/net/phy/amd-xgbe-phy.c
--- linux-libre-3.16-gnu/drivers/net/phy/amd-xgbe-phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/amd-xgbe-phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 #include <linux/uaccess.h>
-#include <asm/irq.h>
 
 
 MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
@@ -85,6 +84,8 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe)
 #define XGBE_PHY_ID	0x000162d0
 #define XGBE_PHY_MASK	0xfffffff0
 
+#define XGBE_PHY_SPEEDSET_PROPERTY	"amd,speed-set"
+
 #define XGBE_AN_INT_CMPLT		0x01
 #define XGBE_AN_INC_LINK		0x02
 #define XGBE_AN_PG_RCV			0x04
@@ -94,6 +95,8 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe)
 #define XNP_MP_FORMATTED		(1 << 13)
 #define XNP_NP_EXCHANGE			(1 << 15)
 
+#define XGBE_PHY_RATECHANGE_COUNT	500
+
 #ifndef MDIO_PMA_10GBR_PMD_CTRL
 #define MDIO_PMA_10GBR_PMD_CTRL		0x0096
 #endif
@@ -116,10 +119,13 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe)
 #endif
 
 /* SerDes integration register offsets */
+#define SIR0_KR_RT_1			0x002c
 #define SIR0_STATUS			0x0040
 #define SIR1_SPEED			0x0000
 
 /* SerDes integration register entry bit positions and sizes */
+#define SIR0_KR_RT_1_RESET_INDEX	11
+#define SIR0_KR_RT_1_RESET_WIDTH	1
 #define SIR0_STATUS_RX_READY_INDEX	0
 #define SIR0_STATUS_RX_READY_WIDTH	1
 #define SIR0_STATUS_TX_READY_INDEX	8
@@ -145,7 +151,7 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe)
 
 #define SPEED_2500_CDR			0x2
 #define SPEED_2500_PLL			0x0
-#define SPEED_2500_RATE			0x2
+#define SPEED_2500_RATE			0x1
 #define SPEED_2500_TXAMP		0xf
 #define SPEED_2500_WORD			0x1
 
@@ -192,6 +198,16 @@ do {									\
 	(_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index));	\
 } while (0)
 
+#define XSIR_GET_BITS(_var, _prefix, _field)				\
+	GET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH)
+
+#define XSIR_SET_BITS(_var, _prefix, _field, _val)			\
+	SET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH, (_val))
+
 /* Macros for reading or writing SerDes integration registers
  *  The ioread macros will get bit fields or full values using the
  *  register definitions formed using the input names
@@ -292,6 +308,11 @@ enum amd_xgbe_phy_mode {
 	AMD_XGBE_MODE_KX,
 };
 
+enum amd_xgbe_phy_speedset {
+	AMD_XGBE_PHY_SPEEDSET_1000_10000,
+	AMD_XGBE_PHY_SPEEDSET_2500_10000,
+};
+
 struct amd_xgbe_phy_priv {
 	struct platform_device *pdev;
 	struct device *dev;
@@ -311,6 +332,7 @@ struct amd_xgbe_phy_priv {
 	/* Maintain link status for re-starting auto-negotiation */
 	unsigned int link;
 	enum amd_xgbe_phy_mode mode;
+	unsigned int speed_set;
 
 	/* Auto-negotiation state machine support */
 	struct mutex an_mutex;
@@ -380,14 +402,25 @@ static void amd_xgbe_phy_serdes_start_ra
 static void amd_xgbe_phy_serdes_complete_ratechange(struct phy_device *phydev)
 {
 	struct amd_xgbe_phy_priv *priv = phydev->priv;
+	unsigned int wait;
+	u16 status;
 
 	/* Release Rx and Tx ratechange */
 	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, RATECHANGE, 0);
 
 	/* Wait for Rx and Tx ready */
-	while (!XSIR0_IOREAD_BITS(priv, SIR0_STATUS, RX_READY) &&
-	       !XSIR0_IOREAD_BITS(priv, SIR0_STATUS, TX_READY))
-		usleep_range(10, 20);
+	wait = XGBE_PHY_RATECHANGE_COUNT;
+	while (wait--) {
+		usleep_range(50, 75);
+
+		status = XSIR0_IOREAD(priv, SIR0_STATUS);
+		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
+			return;
+	}
+
+	netdev_dbg(phydev->attached_dev, "SerDes rx/tx not ready (%#hx)\n",
+		   status);
 }
 
 static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
@@ -546,10 +579,14 @@ static int amd_xgbe_phy_switch_mode(stru
 	int ret;
 
 	/* If we are in KR switch to KX, and vice-versa */
-	if (priv->mode == AMD_XGBE_MODE_KR)
-		ret = amd_xgbe_phy_gmii_mode(phydev);
-	else
+	if (priv->mode == AMD_XGBE_MODE_KR) {
+		if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000)
+			ret = amd_xgbe_phy_gmii_mode(phydev);
+		else
+			ret = amd_xgbe_phy_gmii_2500_mode(phydev);
+	} else {
 		ret = amd_xgbe_phy_xgmii_mode(phydev);
+	}
 
 	return ret;
 }
@@ -602,9 +639,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_
 	if (ret < 0)
 		return AMD_XGBE_AN_ERROR;
 
+	XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 1);
+
 	ret |= 0x01;
 	phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret);
 
+	XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 0);
+
 	return AMD_XGBE_AN_EVENT;
 }
 
@@ -713,7 +754,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_
 	else
 		ret &= ~0x80;
 
-	if (phydev->supported & SUPPORTED_1000baseKX_Full)
+	if ((phydev->supported & SUPPORTED_1000baseKX_Full) ||
+	    (phydev->supported & SUPPORTED_2500baseX_Full))
 		ret |= 0x20;
 	else
 		ret &= ~0x20;
@@ -815,6 +857,7 @@ static void amd_xgbe_an_state_machine(st
 	struct phy_device *phydev = priv->phydev;
 	enum amd_xgbe_phy_an cur_state;
 	int sleep;
+	unsigned int an_supported = 0;
 
 	while (1) {
 		mutex_lock(&priv->an_mutex);
@@ -824,6 +867,7 @@ static void amd_xgbe_an_state_machine(st
 		switch (priv->an_state) {
 		case AMD_XGBE_AN_START:
 			priv->an_state = amd_xgbe_an_start(phydev);
+			an_supported = 0;
 			break;
 
 		case AMD_XGBE_AN_EVENT:
@@ -832,6 +876,7 @@ static void amd_xgbe_an_state_machine(st
 
 		case AMD_XGBE_AN_PAGE_RECEIVED:
 			priv->an_state = amd_xgbe_an_page_received(phydev);
+			an_supported++;
 			break;
 
 		case AMD_XGBE_AN_INCOMPAT_LINK:
@@ -839,6 +884,11 @@ static void amd_xgbe_an_state_machine(st
 			break;
 
 		case AMD_XGBE_AN_COMPLETE:
+			netdev_info(phydev->attached_dev, "%s successful\n",
+				    an_supported ? "Auto negotiation"
+						 : "Parallel detection");
+			/* fall through */
+
 		case AMD_XGBE_AN_NO_LINK:
 		case AMD_XGBE_AN_EXIT:
 			goto exit_unlock;
@@ -896,14 +946,22 @@ static int amd_xgbe_phy_soft_reset(struc
 
 static int amd_xgbe_phy_config_init(struct phy_device *phydev)
 {
+	struct amd_xgbe_phy_priv *priv = phydev->priv;
+
 	/* Initialize supported features */
 	phydev->supported = SUPPORTED_Autoneg;
 	phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 	phydev->supported |= SUPPORTED_Backplane;
-	phydev->supported |= SUPPORTED_1000baseKX_Full |
-			     SUPPORTED_2500baseX_Full;
 	phydev->supported |= SUPPORTED_10000baseKR_Full |
 			     SUPPORTED_10000baseR_FEC;
+	switch (priv->speed_set) {
+	case AMD_XGBE_PHY_SPEEDSET_1000_10000:
+		phydev->supported |= SUPPORTED_1000baseKX_Full;
+		break;
+	case AMD_XGBE_PHY_SPEEDSET_2500_10000:
+		phydev->supported |= SUPPORTED_2500baseX_Full;
+		break;
+	}
 	phydev->advertising = phydev->supported;
 
 	/* Turn off and clear interrupts */
@@ -1020,9 +1078,9 @@ static int amd_xgbe_phy_update_link(stru
 	 * (re-)established (cable connected after the interface is
 	 * up, etc.), the link status may report no link. If there
 	 * is no link, try switching modes and checking the status
-	 * again.
+	 * again if auto negotiation is enabled.
 	 */
-	check_again = 1;
+	check_again = (phydev->autoneg == AUTONEG_ENABLE) ? 1 : 0;
 again:
 	/* Link status is latched low, so read once to clear
 	 * and then read again to get current state
@@ -1038,8 +1096,10 @@ again:
 	phydev->link = (ret & MDIO_STAT1_LSTATUS) ? 1 : 0;
 
 	if (!phydev->link) {
-		ret = amd_xgbe_phy_switch_mode(phydev);
 		if (check_again) {
+			ret = amd_xgbe_phy_switch_mode(phydev);
+			if (ret < 0)
+				return ret;
 			check_again = 0;
 			goto again;
 		}
@@ -1059,6 +1119,7 @@ again:
 
 static int amd_xgbe_phy_read_status(struct phy_device *phydev)
 {
+	struct amd_xgbe_phy_priv *priv = phydev->priv;
 	u32 mmd_mask = phydev->c45_ids.devices_in_package;
 	int ret, mode, ad_ret, lp_ret;
 
@@ -1108,9 +1169,19 @@ static int amd_xgbe_phy_read_status(stru
 					return ret;
 			}
 		} else {
-			phydev->speed = SPEED_1000;
+			int (*mode_fcn)(struct phy_device *);
+
+			if (priv->speed_set ==
+			    AMD_XGBE_PHY_SPEEDSET_1000_10000) {
+				phydev->speed = SPEED_1000;
+				mode_fcn = amd_xgbe_phy_gmii_mode;
+			} else {
+				phydev->speed = SPEED_2500;
+				mode_fcn = amd_xgbe_phy_gmii_2500_mode;
+			}
+
 			if (mode == MDIO_PCS_CTRL2_10GBR) {
-				ret = amd_xgbe_phy_gmii_mode(phydev);
+				ret = mode_fcn(phydev);
 				if (ret < 0)
 					return ret;
 			}
@@ -1118,8 +1189,15 @@ static int amd_xgbe_phy_read_status(stru
 
 		phydev->duplex = DUPLEX_FULL;
 	} else {
-		phydev->speed = (mode == MDIO_PCS_CTRL2_10GBR) ? SPEED_10000
-							       : SPEED_1000;
+		if (mode == MDIO_PCS_CTRL2_10GBR) {
+			phydev->speed = SPEED_10000;
+		} else {
+			if (priv->speed_set ==
+			    AMD_XGBE_PHY_SPEEDSET_1000_10000)
+				phydev->speed = SPEED_1000;
+			else
+				phydev->speed = SPEED_2500;
+		}
 		phydev->duplex = DUPLEX_FULL;
 		phydev->pause = 0;
 		phydev->asym_pause = 0;
@@ -1176,6 +1254,8 @@ static int amd_xgbe_phy_probe(struct phy
 	struct platform_device *pdev;
 	struct device *dev;
 	char *wq_name;
+	const __be32 *property;
+	unsigned int speed_set;
 	int ret;
 
 	if (!phydev->dev.of_node)
@@ -1227,6 +1307,26 @@ static int amd_xgbe_phy_probe(struct phy
 		goto err_sir0;
 	}
 
+	/* Get the device speed set property */
+	speed_set = 0;
+	property = of_get_property(dev->of_node, XGBE_PHY_SPEEDSET_PROPERTY,
+				   NULL);
+	if (property)
+		speed_set = be32_to_cpu(*property);
+
+	switch (speed_set) {
+	case 0:
+		priv->speed_set = AMD_XGBE_PHY_SPEEDSET_1000_10000;
+		break;
+	case 1:
+		priv->speed_set = AMD_XGBE_PHY_SPEEDSET_2500_10000;
+		break;
+	default:
+		dev_err(dev, "invalid amd,speed-set property\n");
+		ret = -EINVAL;
+		goto err_sir1;
+	}
+
 	priv->link = 1;
 
 	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/bcm7xxx.c linux-libre-3.17-rc7-gnu/drivers/net/phy/bcm7xxx.c
--- linux-libre-3.16-gnu/drivers/net/phy/bcm7xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/bcm7xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -157,6 +157,23 @@ static int bcm7xxx_28nm_config_init(stru
 	return bcm7xxx_28nm_afe_config_init(phydev);
 }
 
+static int bcm7xxx_28nm_resume(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Re-apply workarounds coming out suspend/resume */
+	ret = bcm7xxx_28nm_config_init(phydev);
+	if (ret)
+		return ret;
+
+	/* 28nm Gigabit PHYs come out of reset without any half-duplex
+	 * or "hub" compliant advertised mode, fix that. This does not
+	 * cause any problems with the PHY library since genphy_config_aneg()
+	 * gracefully handles auto-negotiated and forced modes.
+	 */
+	return genphy_config_aneg(phydev);
+}
+
 static int phy_set_clr_bits(struct phy_device *dev, int location,
 					int set_mask, int clr_mask)
 {
@@ -212,7 +229,7 @@ static int bcm7xxx_config_init(struct ph
 }
 
 /* Workaround for putting the PHY in IDDQ mode, required
- * for all BCM7XXX PHYs
+ * for all BCM7XXX 40nm and 65nm PHYs
  */
 static int bcm7xxx_suspend(struct phy_device *phydev)
 {
@@ -257,8 +274,7 @@ static struct phy_driver bcm7xxx_driver[
 	.config_init	= bcm7xxx_28nm_afe_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
-	.suspend	= bcm7xxx_suspend,
-	.resume		= bcm7xxx_28nm_afe_config_init,
+	.resume		= bcm7xxx_28nm_resume,
 	.driver		= { .owner = THIS_MODULE },
 }, {
 	.phy_id		= PHY_ID_BCM7439,
@@ -270,8 +286,7 @@ static struct phy_driver bcm7xxx_driver[
 	.config_init	= bcm7xxx_28nm_afe_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
-	.suspend	= bcm7xxx_suspend,
-	.resume		= bcm7xxx_28nm_afe_config_init,
+	.resume		= bcm7xxx_28nm_resume,
 	.driver		= { .owner = THIS_MODULE },
 }, {
 	.phy_id		= PHY_ID_BCM7445,
@@ -283,21 +298,7 @@ static struct phy_driver bcm7xxx_driver[
 	.config_init	= bcm7xxx_28nm_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
-	.suspend	= bcm7xxx_suspend,
-	.resume		= bcm7xxx_28nm_config_init,
-	.driver		= { .owner = THIS_MODULE },
-}, {
-	.name		= "Broadcom BCM7XXX 28nm",
-	.phy_id		= PHY_ID_BCM7XXX_28,
-	.phy_id_mask	= PHY_BCM_OUI_MASK,
-	.features	= PHY_GBIT_FEATURES |
-			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
-	.flags		= PHY_IS_INTERNAL,
-	.config_init	= bcm7xxx_28nm_config_init,
-	.config_aneg	= genphy_config_aneg,
-	.read_status	= genphy_read_status,
-	.suspend	= bcm7xxx_suspend,
-	.resume		= bcm7xxx_28nm_config_init,
+	.resume		= bcm7xxx_28nm_afe_config_init,
 	.driver		= { .owner = THIS_MODULE },
 }, {
 	.phy_id		= PHY_BCM_OUI_4,
@@ -331,7 +332,6 @@ static struct mdio_device_id __maybe_unu
 	{ PHY_ID_BCM7366, 0xfffffff0, },
 	{ PHY_ID_BCM7439, 0xfffffff0, },
 	{ PHY_ID_BCM7445, 0xfffffff0, },
-	{ PHY_ID_BCM7XXX_28, 0xfffffc00 },
 	{ PHY_BCM_OUI_4, 0xffff0000 },
 	{ PHY_BCM_OUI_5, 0xffffff00 },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/dp83640.c linux-libre-3.17-rc7-gnu/drivers/net/phy/dp83640.c
--- linux-libre-3.16-gnu/drivers/net/phy/dp83640.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/dp83640.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,7 @@
 #define LAYER2		0x01
 #define MAX_RXTS	64
 #define N_EXT_TS	6
+#define N_PER_OUT	7
 #define PSF_PTPVER	2
 #define PSF_EVNT	0x4000
 #define PSF_RX		0x2000
@@ -47,7 +48,6 @@
 #define EXT_EVENT	1
 #define CAL_EVENT	7
 #define CAL_TRIGGER	7
-#define PER_TRIGGER	6
 #define DP83640_N_PINS	12
 
 #define MII_DP83640_MICR 0x11
@@ -74,7 +74,10 @@
 #define ENDIAN_FLAG	PSF_ENDIAN
 #endif
 
-#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
+struct dp83640_skb_info {
+	int ptp_type;
+	unsigned long tmo;
+};
 
 struct phy_rxts {
 	u16 ns_lo;   /* ns[15:0] */
@@ -300,23 +303,23 @@ static u64 phy2txts(struct phy_txts *p)
 }
 
 static int periodic_output(struct dp83640_clock *clock,
-			   struct ptp_clock_request *clkreq, bool on)
+			   struct ptp_clock_request *clkreq, bool on,
+			   int trigger)
 {
 	struct dp83640_private *dp83640 = clock->chosen;
 	struct phy_device *phydev = dp83640->phydev;
 	u32 sec, nsec, pwidth;
-	u16 gpio, ptp_trig, trigger, val;
+	u16 gpio, ptp_trig, val;
 
 	if (on) {
-		gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT, 0);
+		gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT,
+					trigger);
 		if (gpio < 1)
 			return -EINVAL;
 	} else {
 		gpio = 0;
 	}
 
-	trigger = PER_TRIGGER;
-
 	ptp_trig = TRIG_WR |
 		(trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT |
 		(gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT |
@@ -353,6 +356,11 @@ static int periodic_output(struct dp8364
 	ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16);       /* sec[31:16] */
 	ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff); /* ns[15:0] */
 	ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16);    /* ns[31:16] */
+	/* Triggers 0 and 1 has programmable pulsewidth2 */
+	if (trigger < 2) {
+		ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff);
+		ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16);
+	}
 
 	/*enable trigger*/
 	val &= ~TRIG_LOAD;
@@ -491,9 +499,9 @@ static int ptp_dp83640_enable(struct ptp
 		return 0;
 
 	case PTP_CLK_REQ_PEROUT:
-		if (rq->perout.index != 0)
+		if (rq->perout.index >= N_PER_OUT)
 			return -EINVAL;
-		return periodic_output(clock, rq, on);
+		return periodic_output(clock, rq, on, rq->perout.index);
 
 	default:
 		break;
@@ -505,6 +513,16 @@ static int ptp_dp83640_enable(struct ptp
 static int ptp_dp83640_verify(struct ptp_clock_info *ptp, unsigned int pin,
 			      enum ptp_pin_function func, unsigned int chan)
 {
+	struct dp83640_clock *clock =
+		container_of(ptp, struct dp83640_clock, caps);
+
+	if (clock->caps.pin_config[pin].func == PTP_PF_PHYSYNC &&
+	    !list_empty(&clock->phylist))
+		return 1;
+
+	if (func == PTP_PF_PHYSYNC)
+		return 1;
+
 	return 0;
 }
 
@@ -594,7 +612,11 @@ static void recalibrate(struct dp83640_c
 	u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val;
 
 	trigger = CAL_TRIGGER;
-	cal_gpio = gpio_tab[CALIBRATE_GPIO];
+	cal_gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PHYSYNC, 0);
+	if (cal_gpio < 1) {
+		pr_err("PHY calibration pin not avaible - PHY is not calibrated.");
+		return;
+	}
 
 	mutex_lock(&clock->extreg_lock);
 
@@ -736,6 +758,9 @@ static int decode_evnt(struct dp83640_pr
 	event.type = PTP_CLOCK_EXTTS;
 	event.timestamp = phy2txts(&dp83640->edata);
 
+	/* Compensate for input path and synchronization delays */
+	event.timestamp -= 35;
+
 	for (i = 0; i < N_EXT_TS; i++) {
 		if (ext_status & exts_chan_to_edata(i)) {
 			event.index = i;
@@ -746,10 +771,51 @@ static int decode_evnt(struct dp83640_pr
 	return parsed * sizeof(u16);
 }
 
+static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
+{
+	u16 *seqid;
+	unsigned int offset = 0;
+	u8 *msgtype, *data = skb_mac_header(skb);
+
+	/* check sequenceID, messageType, 12 bit hash of offset 20-29 */
+
+	if (type & PTP_CLASS_VLAN)
+		offset += VLAN_HLEN;
+
+	switch (type & PTP_CLASS_PMASK) {
+	case PTP_CLASS_IPV4:
+		offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+		break;
+	case PTP_CLASS_IPV6:
+		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+		break;
+	case PTP_CLASS_L2:
+		offset += ETH_HLEN;
+		break;
+	default:
+		return 0;
+	}
+
+	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+		return 0;
+
+	if (unlikely(type & PTP_CLASS_V1))
+		msgtype = data + offset + OFF_PTP_CONTROL;
+	else
+		msgtype = data + offset;
+
+	seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+	return rxts->msgtype == (*msgtype & 0xf) &&
+		rxts->seqid   == ntohs(*seqid);
+}
+
 static void decode_rxts(struct dp83640_private *dp83640,
 			struct phy_rxts *phy_rxts)
 {
 	struct rxts *rxts;
+	struct skb_shared_hwtstamps *shhwtstamps = NULL;
+	struct sk_buff *skb;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dp83640->rx_lock, flags);
@@ -763,7 +829,26 @@ static void decode_rxts(struct dp83640_p
 	rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
 	list_del_init(&rxts->list);
 	phy2rxts(phy_rxts, rxts);
-	list_add_tail(&rxts->list, &dp83640->rxts);
+
+	spin_lock_irqsave(&dp83640->rx_queue.lock, flags);
+	skb_queue_walk(&dp83640->rx_queue, skb) {
+		struct dp83640_skb_info *skb_info;
+
+		skb_info = (struct dp83640_skb_info *)skb->cb;
+		if (match(skb, skb_info->ptp_type, rxts)) {
+			__skb_unlink(skb, &dp83640->rx_queue);
+			shhwtstamps = skb_hwtstamps(skb);
+			memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+			shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+			netif_rx_ni(skb);
+			list_add(&rxts->list, &dp83640->rxpool);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&dp83640->rx_queue.lock, flags);
+
+	if (!shhwtstamps)
+		list_add_tail(&rxts->list, &dp83640->rxts);
 out:
 	spin_unlock_irqrestore(&dp83640->rx_lock, flags);
 }
@@ -837,20 +922,18 @@ static int is_sync(struct sk_buff *skb,
 	u8 *data = skb->data, *msgtype;
 	unsigned int offset = 0;
 
-	switch (type) {
-	case PTP_CLASS_V1_IPV4:
-	case PTP_CLASS_V2_IPV4:
-		offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-		break;
-	case PTP_CLASS_V1_IPV6:
-	case PTP_CLASS_V2_IPV6:
-		offset = OFF_PTP6;
+	if (type & PTP_CLASS_VLAN)
+		offset += VLAN_HLEN;
+
+	switch (type & PTP_CLASS_PMASK) {
+	case PTP_CLASS_IPV4:
+		offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
 		break;
-	case PTP_CLASS_V2_L2:
-		offset = ETH_HLEN;
+	case PTP_CLASS_IPV6:
+		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
 		break;
-	case PTP_CLASS_V2_VLAN:
-		offset = ETH_HLEN + VLAN_HLEN;
+	case PTP_CLASS_L2:
+		offset += ETH_HLEN;
 		break;
 	default:
 		return 0;
@@ -867,47 +950,6 @@ static int is_sync(struct sk_buff *skb,
 	return (*msgtype & 0xf) == 0;
 }
 
-static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
-{
-	u16 *seqid;
-	unsigned int offset;
-	u8 *msgtype, *data = skb_mac_header(skb);
-
-	/* check sequenceID, messageType, 12 bit hash of offset 20-29 */
-
-	switch (type) {
-	case PTP_CLASS_V1_IPV4:
-	case PTP_CLASS_V2_IPV4:
-		offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-		break;
-	case PTP_CLASS_V1_IPV6:
-	case PTP_CLASS_V2_IPV6:
-		offset = OFF_PTP6;
-		break;
-	case PTP_CLASS_V2_L2:
-		offset = ETH_HLEN;
-		break;
-	case PTP_CLASS_V2_VLAN:
-		offset = ETH_HLEN + VLAN_HLEN;
-		break;
-	default:
-		return 0;
-	}
-
-	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
-		return 0;
-
-	if (unlikely(type & PTP_CLASS_V1))
-		msgtype = data + offset + OFF_PTP_CONTROL;
-	else
-		msgtype = data + offset;
-
-	seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
-
-	return rxts->msgtype == (*msgtype & 0xf) &&
-		rxts->seqid   == ntohs(*seqid);
-}
-
 static void dp83640_free_clocks(void)
 {
 	struct dp83640_clock *clock;
@@ -944,7 +986,7 @@ static void dp83640_clock_init(struct dp
 	clock->caps.max_adj	= 1953124;
 	clock->caps.n_alarm	= 0;
 	clock->caps.n_ext_ts	= N_EXT_TS;
-	clock->caps.n_per_out	= 1;
+	clock->caps.n_per_out	= N_PER_OUT;
 	clock->caps.n_pins	= DP83640_N_PINS;
 	clock->caps.pps		= 0;
 	clock->caps.adjfreq	= ptp_dp83640_adjfreq;
@@ -1284,44 +1326,34 @@ static void rx_timestamp_work(struct wor
 {
 	struct dp83640_private *dp83640 =
 		container_of(work, struct dp83640_private, ts_work);
-	struct list_head *this, *next;
-	struct rxts *rxts;
-	struct skb_shared_hwtstamps *shhwtstamps;
 	struct sk_buff *skb;
-	unsigned int type;
-	unsigned long flags;
 
-	/* Deliver each deferred packet, with or without a time stamp. */
+	/* Deliver expired packets. */
+	while ((skb = skb_dequeue(&dp83640->rx_queue))) {
+		struct dp83640_skb_info *skb_info;
 
-	while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) {
-		type = SKB_PTP_TYPE(skb);
-		spin_lock_irqsave(&dp83640->rx_lock, flags);
-		list_for_each_safe(this, next, &dp83640->rxts) {
-			rxts = list_entry(this, struct rxts, list);
-			if (match(skb, type, rxts)) {
-				shhwtstamps = skb_hwtstamps(skb);
-				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-				shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
-				list_del_init(&rxts->list);
-				list_add(&rxts->list, &dp83640->rxpool);
-				break;
-			}
+		skb_info = (struct dp83640_skb_info *)skb->cb;
+		if (!time_after(jiffies, skb_info->tmo)) {
+			skb_queue_head(&dp83640->rx_queue, skb);
+			break;
 		}
-		spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+
 		netif_rx_ni(skb);
 	}
 
-	/* Clear out expired time stamps. */
-
-	spin_lock_irqsave(&dp83640->rx_lock, flags);
-	prune_rx_ts(dp83640);
-	spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+	if (!skb_queue_empty(&dp83640->rx_queue))
+		schedule_work(&dp83640->ts_work);
 }
 
 static bool dp83640_rxtstamp(struct phy_device *phydev,
 			     struct sk_buff *skb, int type)
 {
 	struct dp83640_private *dp83640 = phydev->priv;
+	struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
+	struct list_head *this, *next;
+	struct rxts *rxts;
+	struct skb_shared_hwtstamps *shhwtstamps = NULL;
+	unsigned long flags;
 
 	if (is_status_frame(skb, type)) {
 		decode_status_frame(dp83640, skb);
@@ -1332,9 +1364,27 @@ static bool dp83640_rxtstamp(struct phy_
 	if (!dp83640->hwts_rx_en)
 		return false;
 
-	SKB_PTP_TYPE(skb) = type;
-	skb_queue_tail(&dp83640->rx_queue, skb);
-	schedule_work(&dp83640->ts_work);
+	spin_lock_irqsave(&dp83640->rx_lock, flags);
+	list_for_each_safe(this, next, &dp83640->rxts) {
+		rxts = list_entry(this, struct rxts, list);
+		if (match(skb, type, rxts)) {
+			shhwtstamps = skb_hwtstamps(skb);
+			memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+			shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+			netif_rx_ni(skb);
+			list_del_init(&rxts->list);
+			list_add(&rxts->list, &dp83640->rxpool);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+
+	if (!shhwtstamps) {
+		skb_info->ptp_type = type;
+		skb_info->tmo = jiffies + 2;
+		skb_queue_tail(&dp83640->rx_queue, skb);
+		schedule_work(&dp83640->ts_work);
+	}
 
 	return true;
 }
@@ -1355,7 +1405,6 @@ static void dp83640_txtstamp(struct phy_
 	case HWTSTAMP_TX_ON:
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 		skb_queue_tail(&dp83640->tx_queue, skb);
-		schedule_work(&dp83640->ts_work);
 		break;
 
 	case HWTSTAMP_TX_OFF:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/mdio_bus.c linux-libre-3.17-rc7-gnu/drivers/net/phy/mdio_bus.c
--- linux-libre-3.16-gnu/drivers/net/phy/mdio_bus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/mdio_bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -255,7 +255,6 @@ int mdiobus_register(struct mii_bus *bus
 
 	bus->dev.parent = bus->parent;
 	bus->dev.class = &mdio_bus_class;
-	bus->dev.driver = bus->parent->driver;
 	bus->dev.groups = NULL;
 	dev_set_name(&bus->dev, "%s", bus->id);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/micrel.c linux-libre-3.17-rc7-gnu/drivers/net/phy/micrel.c
--- linux-libre-3.16-gnu/drivers/net/phy/micrel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/micrel.c	2014-09-28 17:29:07.000000000 -0400
@@ -420,6 +420,26 @@ static int ksz8873mll_config_aneg(struct
 	return 0;
 }
 
+/* This routine returns -1 as an indication to the caller that the
+ * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE
+ * MMD extended PHY registers.
+ */
+static int
+ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
+		      int regnum)
+{
+	return -1;
+}
+
+/* This routine does nothing since the Micrel ksz9021 does not support
+ * standard IEEE MMD extended PHY registers.
+ */
+static void
+ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
+		      int regnum, u32 val)
+{
+}
+
 static struct phy_driver ksphy_driver[] = {
 {
 	.phy_id		= PHY_ID_KS8737,
@@ -565,13 +585,14 @@ static struct phy_driver ksphy_driver[]
 	.config_intr	= ksz9021_config_intr,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
+	.read_mmd_indirect = ksz9021_rd_mmd_phyreg,
+	.write_mmd_indirect = ksz9021_wr_mmd_phyreg,
 	.driver		= { .owner = THIS_MODULE, },
 }, {
 	.phy_id		= PHY_ID_KSZ9031,
 	.phy_id_mask	= 0x00fffff0,
 	.name		= "Micrel KSZ9031 Gigabit PHY",
-	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause
-				| SUPPORTED_Asym_Pause),
+	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause),
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= ksz9031_config_init,
 	.config_aneg	= genphy_config_aneg,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/phy.c linux-libre-3.17-rc7-gnu/drivers/net/phy/phy.c
--- linux-libre-3.16-gnu/drivers/net/phy/phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -138,11 +138,31 @@ struct phy_setting {
 /* A mapping of all SUPPORTED settings to speed/duplex */
 static const struct phy_setting settings[] = {
 	{
-		.speed = 10000,
+		.speed = SPEED_10000,
+		.duplex = DUPLEX_FULL,
+		.setting = SUPPORTED_10000baseKR_Full,
+	},
+	{
+		.speed = SPEED_10000,
+		.duplex = DUPLEX_FULL,
+		.setting = SUPPORTED_10000baseKX4_Full,
+	},
+	{
+		.speed = SPEED_10000,
 		.duplex = DUPLEX_FULL,
 		.setting = SUPPORTED_10000baseT_Full,
 	},
 	{
+		.speed = SPEED_2500,
+		.duplex = DUPLEX_FULL,
+		.setting = SUPPORTED_2500baseX_Full,
+	},
+	{
+		.speed = SPEED_1000,
+		.duplex = DUPLEX_FULL,
+		.setting = SUPPORTED_1000baseKX_Full,
+	},
+	{
 		.speed = SPEED_1000,
 		.duplex = DUPLEX_FULL,
 		.setting = SUPPORTED_1000baseT_Full,
@@ -922,7 +942,7 @@ static inline void mmd_phy_indirect(stru
 
 /**
  * phy_read_mmd_indirect - reads data from the MMD registers
- * @bus: the target MII bus
+ * @phydev: The PHY device bus
  * @prtad: MMD Address
  * @devad: MMD DEVAD
  * @addr: PHY address on the MII bus
@@ -935,18 +955,26 @@ static inline void mmd_phy_indirect(stru
  * 3) Write reg 13 // MMD Data Command for MMD DEVAD
  * 3) Read  reg 14 // Read MMD data
  */
-static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
-				 int addr)
+static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
+				 int devad, int addr)
 {
-	mmd_phy_indirect(bus, prtad, devad, addr);
+	struct phy_driver *phydrv = phydev->drv;
+	int value = -1;
 
-	/* Read the content of the MMD's selected register */
-	return bus->read(bus, addr, MII_MMD_DATA);
+	if (phydrv->read_mmd_indirect == NULL) {
+		mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+
+		/* Read the content of the MMD's selected register */
+		value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA);
+	} else {
+		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
+	}
+	return value;
 }
 
 /**
  * phy_write_mmd_indirect - writes data to the MMD registers
- * @bus: the target MII bus
+ * @phydev: The PHY device
  * @prtad: MMD Address
  * @devad: MMD DEVAD
  * @addr: PHY address on the MII bus
@@ -960,13 +988,19 @@ static int phy_read_mmd_indirect(struct
  * 3) Write reg 13 // MMD Data Command for MMD DEVAD
  * 3) Write reg 14 // Write MMD data
  */
-static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
-				   int addr, u32 data)
+static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
+				   int devad, int addr, u32 data)
 {
-	mmd_phy_indirect(bus, prtad, devad, addr);
+	struct phy_driver *phydrv = phydev->drv;
 
-	/* Write the data into MMD's selected register */
-	bus->write(bus, addr, MII_MMD_DATA, data);
+	if (phydrv->write_mmd_indirect == NULL) {
+		mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+
+		/* Write the data into MMD's selected register */
+		phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data);
+	} else {
+		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
+	}
 }
 
 /**
@@ -1000,52 +1034,53 @@ int phy_init_eee(struct phy_device *phyd
 			return status;
 
 		/* First check if the EEE ability is supported */
-		eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+		eee_cap = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,
 						MDIO_MMD_PCS, phydev->addr);
-		if (eee_cap < 0)
-			return eee_cap;
+		if (eee_cap <= 0)
+			goto eee_exit_err;
 
 		cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
 		if (!cap)
-			return -EPROTONOSUPPORT;
+			goto eee_exit_err;
 
 		/* Check which link settings negotiated and verify it in
 		 * the EEE advertising registers.
 		 */
-		eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+		eee_lp = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,
 					       MDIO_MMD_AN, phydev->addr);
-		if (eee_lp < 0)
-			return eee_lp;
+		if (eee_lp <= 0)
+			goto eee_exit_err;
 
-		eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+		eee_adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
 						MDIO_MMD_AN, phydev->addr);
-		if (eee_adv < 0)
-			return eee_adv;
+		if (eee_adv <= 0)
+			goto eee_exit_err;
 
 		adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
 		lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
 		idx = phy_find_setting(phydev->speed, phydev->duplex);
 		if (!(lp & adv & settings[idx].setting))
-			return -EPROTONOSUPPORT;
+			goto eee_exit_err;
 
 		if (clk_stop_enable) {
 			/* Configure the PHY to stop receiving xMII
 			 * clock while it is signaling LPI.
 			 */
-			int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
+			int val = phy_read_mmd_indirect(phydev, MDIO_CTRL1,
 							MDIO_MMD_PCS,
 							phydev->addr);
 			if (val < 0)
 				return val;
 
 			val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
-			phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
-					       MDIO_MMD_PCS, phydev->addr, val);
+			phy_write_mmd_indirect(phydev, MDIO_CTRL1,
+					       MDIO_MMD_PCS, phydev->addr,
+					       val);
 		}
 
 		return 0; /* EEE supported */
 	}
-
+eee_exit_err:
 	return -EPROTONOSUPPORT;
 }
 EXPORT_SYMBOL(phy_init_eee);
@@ -1059,7 +1094,7 @@ EXPORT_SYMBOL(phy_init_eee);
  */
 int phy_get_eee_err(struct phy_device *phydev)
 {
-	return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
+	return phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_WK_ERR,
 				     MDIO_MMD_PCS, phydev->addr);
 }
 EXPORT_SYMBOL(phy_get_eee_err);
@@ -1077,21 +1112,21 @@ int phy_ethtool_get_eee(struct phy_devic
 	int val;
 
 	/* Get Supported EEE */
-	val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+	val = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,
 				    MDIO_MMD_PCS, phydev->addr);
 	if (val < 0)
 		return val;
 	data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
 
 	/* Get advertisement EEE */
-	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+	val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
 				    MDIO_MMD_AN, phydev->addr);
 	if (val < 0)
 		return val;
 	data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
 
 	/* Get LP advertisement EEE */
-	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+	val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,
 				    MDIO_MMD_AN, phydev->addr);
 	if (val < 0)
 		return val;
@@ -1112,7 +1147,7 @@ int phy_ethtool_set_eee(struct phy_devic
 {
 	int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
 
-	phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
+	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
 			       phydev->addr, val);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/phy_device.c linux-libre-3.17-rc7-gnu/drivers/net/phy/phy_device.c
--- linux-libre-3.16-gnu/drivers/net/phy/phy_device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/phy_device.c	2014-09-28 17:29:07.000000000 -0400
@@ -709,6 +709,7 @@ int phy_suspend(struct phy_device *phyde
 		return phydrv->suspend(phydev);
 	return 0;
 }
+EXPORT_SYMBOL(phy_suspend);
 
 int phy_resume(struct phy_device *phydev)
 {
@@ -718,6 +719,7 @@ int phy_resume(struct phy_device *phydev
 		return phydrv->resume(phydev);
 	return 0;
 }
+EXPORT_SYMBOL(phy_resume);
 
 /* Generic PHY support and helper functions */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/smsc.c linux-libre-3.17-rc7-gnu/drivers/net/phy/smsc.c
--- linux-libre-3.16-gnu/drivers/net/phy/smsc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/smsc.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,6 +43,22 @@ static int smsc_phy_ack_interrupt(struct
 
 static int smsc_phy_config_init(struct phy_device *phydev)
 {
+	int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+
+	if (rc < 0)
+		return rc;
+
+	/* Enable energy detect mode for this SMSC Transceivers */
+	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+		       rc | MII_LAN83C185_EDPWRDOWN);
+	if (rc < 0)
+		return rc;
+
+	return smsc_phy_ack_interrupt(phydev);
+}
+
+static int smsc_phy_reset(struct phy_device *phydev)
+{
 	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
 	if (rc < 0)
 		return rc;
@@ -66,18 +82,7 @@ static int smsc_phy_config_init(struct p
 			rc = phy_read(phydev, MII_BMCR);
 		} while (rc & BMCR_RESET);
 	}
-
-	rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
-	if (rc < 0)
-		return rc;
-
-	/* Enable energy detect mode for this SMSC Transceivers */
-	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
-		       rc | MII_LAN83C185_EDPWRDOWN);
-	if (rc < 0)
-		return rc;
-
-	return smsc_phy_ack_interrupt (phydev);
+	return 0;
 }
 
 static int lan911x_config_init(struct phy_device *phydev)
@@ -142,6 +147,7 @@ static struct phy_driver smsc_phy_driver
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
+	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
 	.ack_interrupt	= smsc_phy_ack_interrupt,
@@ -164,6 +170,7 @@ static struct phy_driver smsc_phy_driver
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
+	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
 	.ack_interrupt	= smsc_phy_ack_interrupt,
@@ -186,6 +193,7 @@ static struct phy_driver smsc_phy_driver
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
+	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
 	.ack_interrupt	= smsc_phy_ack_interrupt,
@@ -230,6 +238,7 @@ static struct phy_driver smsc_phy_driver
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= lan87xx_read_status,
 	.config_init	= smsc_phy_config_init,
+	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
 	.ack_interrupt	= smsc_phy_ack_interrupt,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/phy/spi_ks8995.c linux-libre-3.17-rc7-gnu/drivers/net/phy/spi_ks8995.c
--- linux-libre-3.16-gnu/drivers/net/phy/spi_ks8995.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/phy/spi_ks8995.c	2014-09-28 17:29:07.000000000 -0400
@@ -277,7 +277,7 @@ static int ks8995_probe(struct spi_devic
 	/* Chip description */
 	pdata = spi->dev.platform_data;
 
-	ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+	ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL);
 	if (!ks)
 		return -ENOMEM;
 
@@ -291,14 +291,14 @@ static int ks8995_probe(struct spi_devic
 	err = spi_setup(spi);
 	if (err) {
 		dev_err(&spi->dev, "spi_setup failed, err=%d\n", err);
-		goto err_drvdata;
+		return err;
 	}
 
 	err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids));
 	if (err < 0) {
 		dev_err(&spi->dev, "unable to read id registers, err=%d\n",
 				err);
-		goto err_drvdata;
+		return err;
 	}
 
 	switch (ids[0]) {
@@ -306,8 +306,7 @@ static int ks8995_probe(struct spi_devic
 		break;
 	default:
 		dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]);
-		err = -ENODEV;
-		goto err_drvdata;
+		return -ENODEV;
 	}
 
 	memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
@@ -320,24 +319,24 @@ static int ks8995_probe(struct spi_devic
 			dev_err(&spi->dev,
 				"unable to read chip id register, err=%d\n",
 				err);
-			goto err_drvdata;
+			return err;
 		}
 		if ((val & 0x80) == 0) {
 			dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]);
-			goto err_drvdata;
+			return err;
 		}
 		ks->regs_attr.size = KSZ8864_REGS_SIZE;
 	}
 
 	err = ks8995_reset(ks);
 	if (err)
-		goto err_drvdata;
+		return err;
 
 	err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
 	if (err) {
 		dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
 				    err);
-		goto err_drvdata;
+		return err;
 	}
 
 	if (get_chip_id(ids[1]) == CHIPID_M) {
@@ -350,21 +349,12 @@ static int ks8995_probe(struct spi_devic
 	}
 
 	return 0;
-
-err_drvdata:
-	kfree(ks);
-	return err;
 }
 
 static int ks8995_remove(struct spi_device *spi)
 {
-	struct ks8995_data      *ks8995;
-
-	ks8995 = spi_get_drvdata(spi);
 	sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
 
-	kfree(ks8995);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/ppp/ppp_generic.c linux-libre-3.17-rc7-gnu/drivers/net/ppp/ppp_generic.c
--- linux-libre-3.16-gnu/drivers/net/ppp/ppp_generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/ppp/ppp_generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,8 +143,8 @@ struct ppp {
 	struct sk_buff_head mrq;	/* MP: receive reconstruction queue */
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
-	struct sk_filter *pass_filter;	/* filter for packets to pass */
-	struct sk_filter *active_filter;/* filter for pkts to reset idle */
+	struct bpf_prog *pass_filter;	/* filter for packets to pass */
+	struct bpf_prog *active_filter; /* filter for pkts to reset idle */
 #endif /* CONFIG_PPP_FILTER */
 	struct net	*ppp_net;	/* the net we belong to */
 	struct ppp_link_stats stats64;	/* 64 bit network stats */
@@ -655,6 +655,10 @@ static long ppp_ioctl(struct file *file,
 			break;
 		ppp_lock(ppp);
 		cflags = ppp->flags & ~val;
+#ifdef CONFIG_PPP_MULTILINK
+		if (!(ppp->flags & SC_MULTILINK) && (val & SC_MULTILINK))
+			ppp->nextseq = 0;
+#endif
 		ppp->flags = val & SC_FLAG_BITS;
 		ppp_unlock(ppp);
 		if (cflags & SC_CCP_OPEN)
@@ -758,12 +762,12 @@ static long ppp_ioctl(struct file *file,
 
 			ppp_lock(ppp);
 			if (ppp->pass_filter) {
-				sk_unattached_filter_destroy(ppp->pass_filter);
+				bpf_prog_destroy(ppp->pass_filter);
 				ppp->pass_filter = NULL;
 			}
 			if (fprog.filter != NULL)
-				err = sk_unattached_filter_create(&ppp->pass_filter,
-								  &fprog);
+				err = bpf_prog_create(&ppp->pass_filter,
+						      &fprog);
 			else
 				err = 0;
 			kfree(code);
@@ -784,12 +788,12 @@ static long ppp_ioctl(struct file *file,
 
 			ppp_lock(ppp);
 			if (ppp->active_filter) {
-				sk_unattached_filter_destroy(ppp->active_filter);
+				bpf_prog_destroy(ppp->active_filter);
 				ppp->active_filter = NULL;
 			}
 			if (fprog.filter != NULL)
-				err = sk_unattached_filter_create(&ppp->active_filter,
-								  &fprog);
+				err = bpf_prog_create(&ppp->active_filter,
+						      &fprog);
 			else
 				err = 0;
 			kfree(code);
@@ -1201,7 +1205,7 @@ ppp_send_frame(struct ppp *ppp, struct s
 		   a four-byte PPP header on each packet */
 		*skb_push(skb, 2) = 1;
 		if (ppp->pass_filter &&
-		    SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+		    BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
 			if (ppp->debug & 1)
 				netdev_printk(KERN_DEBUG, ppp->dev,
 					      "PPP: outbound frame "
@@ -1211,7 +1215,7 @@ ppp_send_frame(struct ppp *ppp, struct s
 		}
 		/* if this packet passes the active filter, record the time */
 		if (!(ppp->active_filter &&
-		      SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+		      BPF_PROG_RUN(ppp->active_filter, skb) == 0))
 			ppp->last_xmit = jiffies;
 		skb_pull(skb, 2);
 #else
@@ -1835,7 +1839,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp,
 
 			*skb_push(skb, 2) = 0;
 			if (ppp->pass_filter &&
-			    SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+			    BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
 				if (ppp->debug & 1)
 					netdev_printk(KERN_DEBUG, ppp->dev,
 						      "PPP: inbound frame "
@@ -1844,7 +1848,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp,
 				return;
 			}
 			if (!(ppp->active_filter &&
-			      SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+			      BPF_PROG_RUN(ppp->active_filter, skb) == 0))
 				ppp->last_recv = jiffies;
 			__skb_pull(skb, 2);
 		} else
@@ -2669,7 +2673,8 @@ ppp_create_interface(struct net *net, in
 	int ret = -ENOMEM;
 	int i;
 
-	dev = alloc_netdev(sizeof(struct ppp), "", ppp_setup);
+	dev = alloc_netdev(sizeof(struct ppp), "", NET_NAME_UNKNOWN,
+			   ppp_setup);
 	if (!dev)
 		goto out1;
 
@@ -2824,12 +2829,12 @@ static void ppp_destroy_interface(struct
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
 	if (ppp->pass_filter) {
-		sk_unattached_filter_destroy(ppp->pass_filter);
+		bpf_prog_destroy(ppp->pass_filter);
 		ppp->pass_filter = NULL;
 	}
 
 	if (ppp->active_filter) {
-		sk_unattached_filter_destroy(ppp->active_filter);
+		bpf_prog_destroy(ppp->active_filter);
 		ppp->active_filter = NULL;
 	}
 #endif /* CONFIG_PPP_FILTER */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/slip/slhc.c linux-libre-3.17-rc7-gnu/drivers/net/slip/slhc.c
--- linux-libre-3.16-gnu/drivers/net/slip/slhc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/slip/slhc.c	2014-09-28 17:29:07.000000000 -0400
@@ -396,7 +396,6 @@ found:
 		   ntohs(cs->cs_ip.tot_len) == hlen)
 			break;
 		goto uncompressed;
-		break;
 	case SPECIAL_I:
 	case SPECIAL_D:
 		/* actual changes match one of our special case encodings --
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/slip/slip.c linux-libre-3.17-rc7-gnu/drivers/net/slip/slip.c
--- linux-libre-3.16-gnu/drivers/net/slip/slip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/slip/slip.c	2014-09-28 17:29:07.000000000 -0400
@@ -749,7 +749,7 @@ static struct slip *sl_alloc(dev_t line)
 		return NULL;
 
 	sprintf(name, "sl%d", i);
-	dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+	dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, sl_setup);
 	if (!dev)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/team/team.c linux-libre-3.17-rc7-gnu/drivers/net/team/team.c
--- linux-libre-3.16-gnu/drivers/net/team/team.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/team/team.c	2014-09-28 17:29:07.000000000 -0400
@@ -2045,16 +2045,10 @@ static void team_setup(struct net_device
 static int team_newlink(struct net *src_net, struct net_device *dev,
 			struct nlattr *tb[], struct nlattr *data[])
 {
-	int err;
-
 	if (tb[IFLA_ADDRESS] == NULL)
 		eth_hw_addr_random(dev);
 
-	err = register_netdevice(dev);
-	if (err)
-		return err;
-
-	return 0;
+	return register_netdevice(dev);
 }
 
 static int team_validate(struct nlattr *tb[], struct nlattr *data[])
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/team/team_mode_loadbalance.c linux-libre-3.17-rc7-gnu/drivers/net/team/team_mode_loadbalance.c
--- linux-libre-3.16-gnu/drivers/net/team/team_mode_loadbalance.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/team/team_mode_loadbalance.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ struct lb_priv_ex {
 };
 
 struct lb_priv {
-	struct sk_filter __rcu *fp;
+	struct bpf_prog __rcu *fp;
 	lb_select_tx_port_func_t __rcu *select_tx_port_func;
 	struct lb_pcpu_stats __percpu *pcpu_stats;
 	struct lb_priv_ex *ex; /* priv extension */
@@ -174,14 +174,14 @@ static lb_select_tx_port_func_t *lb_sele
 static unsigned int lb_get_skb_hash(struct lb_priv *lb_priv,
 				    struct sk_buff *skb)
 {
-	struct sk_filter *fp;
+	struct bpf_prog *fp;
 	uint32_t lhash;
 	unsigned char *c;
 
 	fp = rcu_dereference_bh(lb_priv->fp);
 	if (unlikely(!fp))
 		return 0;
-	lhash = SK_RUN_FILTER(fp, skb);
+	lhash = BPF_PROG_RUN(fp, skb);
 	c = (char *) &lhash;
 	return c[0] ^ c[1] ^ c[2] ^ c[3];
 }
@@ -271,8 +271,8 @@ static void __fprog_destroy(struct sock_
 static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
 {
 	struct lb_priv *lb_priv = get_lb_priv(team);
-	struct sk_filter *fp = NULL;
-	struct sk_filter *orig_fp;
+	struct bpf_prog *fp = NULL;
+	struct bpf_prog *orig_fp = NULL;
 	struct sock_fprog_kern *fprog = NULL;
 	int err;
 
@@ -281,7 +281,7 @@ static int lb_bpf_func_set(struct team *
 				     ctx->data.bin_val.ptr);
 		if (err)
 			return err;
-		err = sk_unattached_filter_create(&fp, fprog);
+		err = bpf_prog_create(&fp, fprog);
 		if (err) {
 			__fprog_destroy(fprog);
 			return err;
@@ -293,11 +293,15 @@ static int lb_bpf_func_set(struct team *
 		__fprog_destroy(lb_priv->ex->orig_fprog);
 		orig_fp = rcu_dereference_protected(lb_priv->fp,
 						lockdep_is_held(&team->lock));
-		sk_unattached_filter_destroy(orig_fp);
 	}
 
 	rcu_assign_pointer(lb_priv->fp, fp);
 	lb_priv->ex->orig_fprog = fprog;
+
+	if (orig_fp) {
+		synchronize_rcu();
+		bpf_prog_destroy(orig_fp);
+	}
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/tun.c linux-libre-3.17-rc7-gnu/drivers/net/tun.c
--- linux-libre-3.16-gnu/drivers/net/tun.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/tun.c	2014-09-28 17:29:07.000000000 -0400
@@ -1633,7 +1633,8 @@ static int tun_set_iff(struct net *net,
 			name = ifr->ifr_name;
 
 		dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
-				       tun_setup, queues, queues);
+				       NET_NAME_UNKNOWN, tun_setup, queues,
+				       queues);
 
 		if (!dev)
 			return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/ax88179_178a.c linux-libre-3.17-rc7-gnu/drivers/net/usb/ax88179_178a.c
--- linux-libre-3.16-gnu/drivers/net/usb/ax88179_178a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/ax88179_178a.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/usb.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
+#include <uapi/linux/mdio.h>
+#include <linux/mdio.h>
 
 #define AX88179_PHY_ID				0x03
 #define AX_EEPROM_LEN				0x100
@@ -170,8 +172,12 @@
 #define GMII_PHY_PAGE_SELECT			0x1f
 	#define GMII_PHY_PGSEL_EXT	0x0007
 	#define GMII_PHY_PGSEL_PAGE0	0x0000
+	#define GMII_PHY_PGSEL_PAGE3	0x0003
+	#define GMII_PHY_PGSEL_PAGE5	0x0005
 
 struct ax88179_data {
+	u8  eee_enabled;
+	u8  eee_active;
 	u16 rxctl;
 	u16 reserved;
 };
@@ -373,6 +379,60 @@ static void ax88179_mdio_write(struct ne
 	ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
 }
 
+static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad,
+					   u16 devad)
+{
+	u16 tmp16;
+	int ret;
+
+	tmp16 = devad;
+	ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+				MII_MMD_CTRL, 2, &tmp16);
+
+	tmp16 = prtad;
+	ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+				MII_MMD_DATA, 2, &tmp16);
+
+	tmp16 = devad | MII_MMD_CTRL_NOINCR;
+	ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+				MII_MMD_CTRL, 2, &tmp16);
+
+	return ret;
+}
+
+static int
+ax88179_phy_read_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad)
+{
+	int ret;
+	u16 tmp16;
+
+	ax88179_phy_mmd_indirect(dev, prtad, devad);
+
+	ret = ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			       MII_MMD_DATA, 2, &tmp16);
+	if (ret < 0)
+		return ret;
+
+	return tmp16;
+}
+
+static int
+ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad,
+			       u16 data)
+{
+	int ret;
+
+	ax88179_phy_mmd_indirect(dev, prtad, devad);
+
+	ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+				MII_MMD_DATA, 2, &data);
+
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet *dev = usb_get_intfdata(intf);
@@ -572,6 +632,185 @@ static int ax88179_set_settings(struct n
 	return mii_ethtool_sset(&dev->mii, cmd);
 }
 
+static int
+ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
+{
+	int val;
+
+	/* Get Supported EEE */
+	val = ax88179_phy_read_mmd_indirect(dev, MDIO_PCS_EEE_ABLE,
+					    MDIO_MMD_PCS);
+	if (val < 0)
+		return val;
+	data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
+
+	/* Get advertisement EEE */
+	val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV,
+					    MDIO_MMD_AN);
+	if (val < 0)
+		return val;
+	data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+	/* Get LP advertisement EEE */
+	val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE,
+					    MDIO_MMD_AN);
+	if (val < 0)
+		return val;
+	data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+	return 0;
+}
+
+static int
+ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data)
+{
+	u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+
+	return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV,
+					      MDIO_MMD_AN, tmp16);
+}
+
+static int ax88179_chk_eee(struct usbnet *dev)
+{
+	struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+	struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+
+	mii_ethtool_gset(&dev->mii, &ecmd);
+
+	if (ecmd.duplex & DUPLEX_FULL) {
+		int eee_lp, eee_cap, eee_adv;
+		u32 lp, cap, adv, supported = 0;
+
+		eee_cap = ax88179_phy_read_mmd_indirect(dev,
+							MDIO_PCS_EEE_ABLE,
+							MDIO_MMD_PCS);
+		if (eee_cap < 0) {
+			priv->eee_active = 0;
+			return false;
+		}
+
+		cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
+		if (!cap) {
+			priv->eee_active = 0;
+			return false;
+		}
+
+		eee_lp = ax88179_phy_read_mmd_indirect(dev,
+						       MDIO_AN_EEE_LPABLE,
+						       MDIO_MMD_AN);
+		if (eee_lp < 0) {
+			priv->eee_active = 0;
+			return false;
+		}
+
+		eee_adv = ax88179_phy_read_mmd_indirect(dev,
+							MDIO_AN_EEE_ADV,
+							MDIO_MMD_AN);
+
+		if (eee_adv < 0) {
+			priv->eee_active = 0;
+			return false;
+		}
+
+		adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
+		lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
+		supported = (ecmd.speed == SPEED_1000) ?
+			     SUPPORTED_1000baseT_Full :
+			     SUPPORTED_100baseT_Full;
+
+		if (!(lp & adv & supported)) {
+			priv->eee_active = 0;
+			return false;
+		}
+
+		priv->eee_active = 1;
+		return true;
+	}
+
+	priv->eee_active = 0;
+	return false;
+}
+
+static void ax88179_disable_eee(struct usbnet *dev)
+{
+	u16 tmp16;
+
+	tmp16 = GMII_PHY_PGSEL_PAGE3;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+	tmp16 = 0x3246;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  MII_PHYADDR, 2, &tmp16);
+
+	tmp16 = GMII_PHY_PGSEL_PAGE0;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  GMII_PHY_PAGE_SELECT, 2, &tmp16);
+}
+
+static void ax88179_enable_eee(struct usbnet *dev)
+{
+	u16 tmp16;
+
+	tmp16 = GMII_PHY_PGSEL_PAGE3;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+	tmp16 = 0x3247;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  MII_PHYADDR, 2, &tmp16);
+
+	tmp16 = GMII_PHY_PGSEL_PAGE5;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+	tmp16 = 0x0680;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  MII_BMSR, 2, &tmp16);
+
+	tmp16 = GMII_PHY_PGSEL_PAGE0;
+	ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+			  GMII_PHY_PAGE_SELECT, 2, &tmp16);
+}
+
+static int ax88179_get_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+
+	edata->eee_enabled = priv->eee_enabled;
+	edata->eee_active = priv->eee_active;
+
+	return ax88179_ethtool_get_eee(dev, edata);
+}
+
+static int ax88179_set_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+	int ret = -EOPNOTSUPP;
+
+	priv->eee_enabled = edata->eee_enabled;
+	if (!priv->eee_enabled) {
+		ax88179_disable_eee(dev);
+	} else {
+		priv->eee_enabled = ax88179_chk_eee(dev);
+		if (!priv->eee_enabled)
+			return -EOPNOTSUPP;
+
+		ax88179_enable_eee(dev);
+	}
+
+	ret = ax88179_ethtool_set_eee(dev, edata);
+	if (ret)
+		return ret;
+
+	mii_nway_restart(&dev->mii);
+
+	usbnet_link_change(dev, 0, 0);
+
+	return ret;
+}
 
 static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
 {
@@ -589,6 +828,8 @@ static const struct ethtool_ops ax88179_
 	.get_eeprom		= ax88179_get_eeprom,
 	.get_settings		= ax88179_get_settings,
 	.set_settings		= ax88179_set_settings,
+	.get_eee		= ax88179_get_eee,
+	.set_eee		= ax88179_set_eee,
 	.nway_reset		= usbnet_nway_reset,
 };
 
@@ -980,6 +1221,7 @@ static int ax88179_bind(struct usbnet *d
 	u16 *tmp16;
 	u8 *tmp;
 	struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+	struct ethtool_eee eee_data;
 
 	usbnet_get_endpoints(dev, intf);
 
@@ -1062,6 +1304,15 @@ static int ax88179_bind(struct usbnet *d
 
 	ax88179_led_setting(dev);
 
+	ax179_data->eee_enabled = 0;
+	ax179_data->eee_active = 0;
+
+	ax88179_disable_eee(dev);
+
+	ax88179_ethtool_get_eee(dev, &eee_data);
+	eee_data.advertised = 0;
+	ax88179_ethtool_set_eee(dev, &eee_data);
+
 	/* Restart autoneg */
 	mii_nway_restart(&dev->mii);
 
@@ -1261,6 +1512,8 @@ static int ax88179_link_reset(struct usb
 	ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
 			  2, 2, &mode);
 
+	ax179_data->eee_enabled = ax88179_chk_eee(dev);
+
 	netif_carrier_on(dev->net);
 
 	return 0;
@@ -1271,6 +1524,8 @@ static int ax88179_reset(struct usbnet *
 	u8 buf[5];
 	u16 *tmp16;
 	u8 *tmp;
+	struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+	struct ethtool_eee eee_data;
 
 	tmp16 = (u16 *)buf;
 	tmp = (u8 *)buf;
@@ -1340,6 +1595,15 @@ static int ax88179_reset(struct usbnet *
 
 	ax88179_led_setting(dev);
 
+	ax179_data->eee_enabled = 0;
+	ax179_data->eee_active = 0;
+
+	ax88179_disable_eee(dev);
+
+	ax88179_ethtool_get_eee(dev, &eee_data);
+	eee_data.advertised = 0;
+	ax88179_ethtool_set_eee(dev, &eee_data);
+
 	/* Restart autoneg */
 	mii_nway_restart(&dev->mii);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/cdc-phonet.c linux-libre-3.17-rc7-gnu/drivers/net/usb/cdc-phonet.c
--- linux-libre-3.16-gnu/drivers/net/usb/cdc-phonet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/cdc-phonet.c	2014-09-28 17:29:07.000000000 -0400
@@ -387,7 +387,7 @@ static int usbpn_probe(struct usb_interf
 		return -EINVAL;
 
 	dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
-				ifname, usbpn_setup);
+			   ifname, NET_NAME_UNKNOWN, usbpn_setup);
 	if (!dev)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/cdc_subset.c linux-libre-3.17-rc7-gnu/drivers/net/usb/cdc_subset.c
--- linux-libre-3.16-gnu/drivers/net/usb/cdc_subset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/cdc_subset.c	2014-09-28 17:29:07.000000000 -0400
@@ -85,14 +85,28 @@ static int always_connected (struct usbn
  *
  *-------------------------------------------------------------------------*/
 
+static void m5632_recover(struct usbnet *dev)
+{
+	struct usb_device	*udev = dev->udev;
+	struct usb_interface	*intf = dev->intf;
+	int r;
+
+	r = usb_lock_device_for_reset(udev, intf);
+	if (r < 0)
+		return;
+
+	usb_reset_device(udev);
+	usb_unlock_device(udev);
+}
+
 static const struct driver_info	ali_m5632_info = {
 	.description =	"ALi M5632",
 	.flags       = FLAG_POINTTOPOINT,
+	.recover     = m5632_recover,
 };
 
 #endif
 
-
 #ifdef	CONFIG_USB_AN2720
 #define	HAVE_HARDWARE
 
@@ -326,12 +340,23 @@ static const struct usb_device_id	produc
 MODULE_DEVICE_TABLE(usb, products);
 
 /*-------------------------------------------------------------------------*/
+static int dummy_prereset(struct usb_interface *intf)
+{
+        return 0;
+}
+
+static int dummy_postreset(struct usb_interface *intf)
+{
+        return 0;
+}
 
 static struct usb_driver cdc_subset_driver = {
 	.name =		"cdc_subset",
 	.probe =	usbnet_probe,
 	.suspend =	usbnet_suspend,
 	.resume =	usbnet_resume,
+	.pre_reset =	dummy_prereset,
+	.post_reset =	dummy_postreset,
 	.disconnect =	usbnet_disconnect,
 	.id_table =	products,
 	.disable_hub_initiated_lpm = 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/hso.c linux-libre-3.17-rc7-gnu/drivers/net/usb/hso.c
--- linux-libre-3.16-gnu/drivers/net/usb/hso.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/hso.c	2014-09-28 17:29:07.000000000 -0400
@@ -467,6 +467,7 @@ static const struct usb_device_id hso_id
 	{USB_DEVICE(0x0af0, 0x8800)},
 	{USB_DEVICE(0x0af0, 0x8900)},
 	{USB_DEVICE(0x0af0, 0x9000)},
+	{USB_DEVICE(0x0af0, 0x9200)},		/* Option GTM671WFS */
 	{USB_DEVICE(0x0af0, 0xd035)},
 	{USB_DEVICE(0x0af0, 0xd055)},
 	{USB_DEVICE(0x0af0, 0xd155)},
@@ -2504,7 +2505,8 @@ static struct hso_device *hso_create_net
 
 	/* allocate our network device, then we can put in our private data */
 	/* call hso_net_init to do the basic initialization */
-	net = alloc_netdev(sizeof(struct hso_net), "hso%d", hso_net_init);
+	net = alloc_netdev(sizeof(struct hso_net), "hso%d", NET_NAME_UNKNOWN,
+			   hso_net_init);
 	if (!net) {
 		dev_err(&interface->dev, "Unable to create ethernet device\n");
 		goto exit;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/usb/Kconfig
--- linux-libre-3.16-gnu/drivers/net/usb/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,16 @@
 #
 # USB Network devices configuration
 #
-comment "Networking support is needed for USB Network Adapter support"
-	depends on USB && !NET
+comment "Host-side USB support is needed for USB Network Adapter support"
+	depends on !USB && NET
 
-menu "USB Network Adapters"
+menuconfig USB_NET_DRIVERS
+	tristate "USB Network Adapters"
+	default USB if USB
 	depends on USB && NET
 
+if USB_NET_DRIVERS
+
 config USB_CATC
 	tristate "USB CATC NetMate-based Ethernet device support"
 	select CRC32
@@ -568,5 +572,4 @@ config USB_VL600
 
 	  http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
 
-
-endmenu
+endif # USB_NET_DRIVERS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/r8152.c linux-libre-3.17-rc7-gnu/drivers/net/usb/r8152.c
--- linux-libre-3.16-gnu/drivers/net/usb/r8152.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/r8152.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,7 @@
 #define PLA_WDT6_CTRL		0xe428
 #define PLA_TCR0		0xe610
 #define PLA_TCR1		0xe612
+#define PLA_MTPS		0xe615
 #define PLA_TXFIFO_CTRL		0xe618
 #define PLA_RSTTALLY		0xe800
 #define PLA_CR			0xe813
@@ -180,6 +181,10 @@
 /* PLA_TCR1 */
 #define VERSION_MASK		0x7cf0
 
+/* PLA_MTPS */
+#define MTPS_JUMBO		(12 * 1024 / 64)
+#define MTPS_DEFAULT		(6 * 1024 / 64)
+
 /* PLA_RSTTALLY */
 #define TALLY_RESET		0x0001
 
@@ -440,8 +445,11 @@ enum rtl_register_content {
 #define BYTE_EN_START_MASK	0x0f
 #define BYTE_EN_END_MASK	0xf0
 
+#define RTL8153_MAX_PACKET	9216 /* 9K */
+#define RTL8153_MAX_MTU		(RTL8153_MAX_PACKET - VLAN_ETH_HLEN - VLAN_HLEN)
 #define RTL8152_RMS		(VLAN_ETH_FRAME_LEN + VLAN_HLEN)
-#define RTL8152_TX_TIMEOUT	(HZ)
+#define RTL8153_RMS		RTL8153_MAX_PACKET
+#define RTL8152_TX_TIMEOUT	(5 * HZ)
 
 /* rtl8152 flags */
 enum rtl8152_flags {
@@ -2011,7 +2019,7 @@ static int rtl8153_enable(struct r8152 *
 	return rtl_enable(tp);
 }
 
-static void rtl8152_disable(struct r8152 *tp)
+static void rtl_disable(struct r8152 *tp)
 {
 	u32 ocp_data;
 	int i;
@@ -2224,6 +2232,13 @@ static inline void r8152b_enable_aldps(s
 					    LINKENA | DIS_SDSAVE);
 }
 
+static void rtl8152_disable(struct r8152 *tp)
+{
+	r8152b_disable_aldps(tp);
+	rtl_disable(tp);
+	r8152b_enable_aldps(tp);
+}
+
 static void r8152b_hw_phy_cfg(struct r8152 *tp)
 {
 	u16 data;
@@ -2234,11 +2249,8 @@ static void r8152b_hw_phy_cfg(struct r81
 		r8152_mdio_write(tp, MII_BMCR, data);
 	}
 
-	r8152b_disable_aldps(tp);
-
 	rtl_clear_bp(tp);
 
-	r8152b_enable_aldps(tp);
 	set_bit(PHY_RESET, &tp->flags);
 }
 
@@ -2247,9 +2259,6 @@ static void r8152b_exit_oob(struct r8152
 	u32 ocp_data;
 	int i;
 
-	if (test_bit(RTL8152_UNPLUG, &tp->flags))
-		return;
-
 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
 	ocp_data &= ~RCR_ACPT_ALL;
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
@@ -2339,7 +2348,7 @@ static void r8152b_enter_oob(struct r815
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
 
-	rtl8152_disable(tp);
+	rtl_disable(tp);
 
 	for (i = 0; i < 1000; i++) {
 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -2477,9 +2486,6 @@ static void r8153_first_init(struct r815
 	u32 ocp_data;
 	int i;
 
-	if (test_bit(RTL8152_UNPLUG, &tp->flags))
-		return;
-
 	rxdy_gated_en(tp, true);
 	r8153_teredo_off(tp);
 
@@ -2521,7 +2527,8 @@ static void r8153_first_init(struct r815
 	ocp_data &= ~CPCR_RX_VLAN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
 
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
 	ocp_data |= TCR0_AUTO_FIFO;
@@ -2551,7 +2558,7 @@ static void r8153_enter_oob(struct r8152
 	ocp_data &= ~NOW_IS_OOB;
 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
 
-	rtl8152_disable(tp);
+	rtl_disable(tp);
 
 	for (i = 0; i < 1000; i++) {
 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
@@ -2571,7 +2578,7 @@ static void r8153_enter_oob(struct r8152
 		mdelay(1);
 	}
 
-	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
 	ocp_data &= ~TEREDO_WAKE_MASK;
@@ -2615,6 +2622,13 @@ static void r8153_enable_aldps(struct r8
 	ocp_reg_write(tp, OCP_POWER_CFG, data);
 }
 
+static void rtl8153_disable(struct r8152 *tp)
+{
+	r8153_disable_aldps(tp);
+	rtl_disable(tp);
+	r8153_enable_aldps(tp);
+}
+
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
 {
 	u16 bmcr, anar, gbcr;
@@ -2705,6 +2719,16 @@ out:
 	return ret;
 }
 
+static void rtl8152_up(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_UNPLUG, &tp->flags))
+		return;
+
+	r8152b_disable_aldps(tp);
+	r8152b_exit_oob(tp);
+	r8152b_enable_aldps(tp);
+}
+
 static void rtl8152_down(struct r8152 *tp)
 {
 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
@@ -2718,6 +2742,16 @@ static void rtl8152_down(struct r8152 *t
 	r8152b_enable_aldps(tp);
 }
 
+static void rtl8153_up(struct r8152 *tp)
+{
+	if (test_bit(RTL8152_UNPLUG, &tp->flags))
+		return;
+
+	r8153_disable_aldps(tp);
+	r8153_first_init(tp);
+	r8153_enable_aldps(tp);
+}
+
 static void rtl8153_down(struct r8152 *tp)
 {
 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
@@ -2937,6 +2971,8 @@ static void r8152b_init(struct r8152 *tp
 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
 		return;
 
+	r8152b_disable_aldps(tp);
+
 	if (tp->version == RTL_VER_01) {
 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
 		ocp_data &= ~LED_MODE_MASK;
@@ -2975,6 +3011,7 @@ static void r8153_init(struct r8152 *tp)
 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
 		return;
 
+	r8153_disable_aldps(tp);
 	r8153_u1u2en(tp, false);
 
 	for (i = 0; i < 500; i++) {
@@ -3288,6 +3325,26 @@ out:
 	return res;
 }
 
+static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct r8152 *tp = netdev_priv(dev);
+
+	switch (tp->version) {
+	case RTL_VER_01:
+	case RTL_VER_02:
+		return eth_change_mtu(dev, new_mtu);
+	default:
+		break;
+	}
+
+	if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
 static const struct net_device_ops rtl8152_netdev_ops = {
 	.ndo_open		= rtl8152_open,
 	.ndo_stop		= rtl8152_close,
@@ -3296,8 +3353,7 @@ static const struct net_device_ops rtl81
 	.ndo_tx_timeout		= rtl8152_tx_timeout,
 	.ndo_set_rx_mode	= rtl8152_set_rx_mode,
 	.ndo_set_mac_address	= rtl8152_set_mac_address,
-
-	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_change_mtu		= rtl8152_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
@@ -3364,7 +3420,7 @@ static int rtl_ops_init(struct r8152 *tp
 			ops->init		= r8152b_init;
 			ops->enable		= rtl8152_enable;
 			ops->disable		= rtl8152_disable;
-			ops->up			= r8152b_exit_oob;
+			ops->up			= rtl8152_up;
 			ops->down		= rtl8152_down;
 			ops->unload		= rtl8152_unload;
 			ret = 0;
@@ -3372,8 +3428,8 @@ static int rtl_ops_init(struct r8152 *tp
 		case PRODUCT_ID_RTL8153:
 			ops->init		= r8153_init;
 			ops->enable		= rtl8153_enable;
-			ops->disable		= rtl8152_disable;
-			ops->up			= r8153_first_init;
+			ops->disable		= rtl8153_disable;
+			ops->up			= rtl8153_up;
 			ops->down		= rtl8153_down;
 			ops->unload		= rtl8153_unload;
 			ret = 0;
@@ -3388,8 +3444,8 @@ static int rtl_ops_init(struct r8152 *tp
 		case PRODUCT_ID_SAMSUNG:
 			ops->init		= r8153_init;
 			ops->enable		= rtl8153_enable;
-			ops->disable		= rtl8152_disable;
-			ops->up			= r8153_first_init;
+			ops->disable		= rtl8153_disable;
+			ops->up			= rtl8153_up;
 			ops->down		= rtl8153_down;
 			ops->unload		= rtl8153_unload;
 			ret = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/usb/usbnet.c linux-libre-3.17-rc7-gnu/drivers/net/usb/usbnet.c
--- linux-libre-3.16-gnu/drivers/net/usb/usbnet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/usb/usbnet.c	2014-09-28 17:29:07.000000000 -0400
@@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_devic
 
 	unlink_urbs (dev, &dev->txq);
 	tasklet_schedule (&dev->bh);
-
-	// FIXME: device recovery -- reset?
+	/* this needs to be handled individually because the generic layer
+	 * doesn't know what is sufficient and could not restore private
+	 * information if a remedy of an unconditional reset were used.
+	 */
+	if (dev->driver_info->recover)
+		(dev->driver_info->recover)(dev);
 }
 EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/veth.c linux-libre-3.17-rc7-gnu/drivers/net/veth.c
--- linux-libre-3.16-gnu/drivers/net/veth.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/veth.c	2014-09-28 17:29:07.000000000 -0400
@@ -248,6 +248,21 @@ static void veth_dev_free(struct net_dev
 	free_netdev(dev);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void veth_poll_controller(struct net_device *dev)
+{
+	/* veth only receives frames when its peer sends one
+	 * Since it's a synchronous operation, we are guaranteed
+	 * never to have pending data when we poll for it so
+	 * there is nothing to do here.
+	 *
+	 * We need this though so netpoll recognizes us as an interface that
+	 * supports polling, which enables bridge devices in virt setups to
+	 * still use netconsole
+	 */
+}
+#endif	/* CONFIG_NET_POLL_CONTROLLER */
+
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
 	.ndo_open            = veth_open,
@@ -257,6 +272,9 @@ static const struct net_device_ops veth_
 	.ndo_get_stats64     = veth_get_stats64,
 	.ndo_set_rx_mode     = veth_set_multicast_list,
 	.ndo_set_mac_address = eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= veth_poll_controller,
+#endif
 };
 
 #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO |    \
@@ -317,6 +335,7 @@ static int veth_newlink(struct net *src_
 	struct veth_priv *priv;
 	char ifname[IFNAMSIZ];
 	struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+	unsigned char name_assign_type;
 	struct ifinfomsg *ifmp;
 	struct net *net;
 
@@ -344,16 +363,20 @@ static int veth_newlink(struct net *src_
 		tbp = tb;
 	}
 
-	if (tbp[IFLA_IFNAME])
+	if (tbp[IFLA_IFNAME]) {
 		nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
-	else
+		name_assign_type = NET_NAME_USER;
+	} else {
 		snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+		name_assign_type = NET_NAME_ENUM;
+	}
 
 	net = rtnl_link_get_net(src_net, tbp);
 	if (IS_ERR(net))
 		return PTR_ERR(net);
 
-	peer = rtnl_create_link(net, ifname, &veth_link_ops, tbp);
+	peer = rtnl_create_link(net, ifname, name_assign_type,
+				&veth_link_ops, tbp);
 	if (IS_ERR(peer)) {
 		put_net(net);
 		return PTR_ERR(peer);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/virtio_net.c linux-libre-3.17-rc7-gnu/drivers/net/virtio_net.c
--- linux-libre-3.16-gnu/drivers/net/virtio_net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/virtio_net.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/average.h>
+#include <net/busy_poll.h>
 
 static int napi_weight = NAPI_POLL_WEIGHT;
 module_param(napi_weight, int, 0444);
@@ -521,6 +522,8 @@ static void receive_buf(struct receive_q
 		skb_shinfo(skb)->gso_segs = 0;
 	}
 
+	skb_mark_napi_id(skb, &rq->napi);
+
 	netif_receive_skb(skb);
 	return;
 
@@ -725,15 +728,12 @@ static void refill_work(struct work_stru
 	}
 }
 
-static int virtnet_poll(struct napi_struct *napi, int budget)
+static int virtnet_receive(struct receive_queue *rq, int budget)
 {
-	struct receive_queue *rq =
-		container_of(napi, struct receive_queue, napi);
 	struct virtnet_info *vi = rq->vq->vdev->priv;
+	unsigned int len, received = 0;
 	void *buf;
-	unsigned int r, len, received = 0;
 
-again:
 	while (received < budget &&
 	       (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
 		receive_buf(rq, buf, len);
@@ -745,6 +745,18 @@ again:
 			schedule_delayed_work(&vi->refill, 0);
 	}
 
+	return received;
+}
+
+static int virtnet_poll(struct napi_struct *napi, int budget)
+{
+	struct receive_queue *rq =
+		container_of(napi, struct receive_queue, napi);
+	unsigned int r, received = 0;
+
+again:
+	received += virtnet_receive(rq, budget - received);
+
 	/* Out of packets? */
 	if (received < budget) {
 		r = virtqueue_enable_cb_prepare(rq->vq);
@@ -760,6 +772,43 @@ again:
 	return received;
 }
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+/* must be called with local_bh_disable()d */
+static int virtnet_busy_poll(struct napi_struct *napi)
+{
+	struct receive_queue *rq =
+		container_of(napi, struct receive_queue, napi);
+	struct virtnet_info *vi = rq->vq->vdev->priv;
+	int r, received = 0, budget = 4;
+
+	if (!(vi->status & VIRTIO_NET_S_LINK_UP))
+		return LL_FLUSH_FAILED;
+
+	if (!napi_schedule_prep(napi))
+		return LL_FLUSH_BUSY;
+
+	virtqueue_disable_cb(rq->vq);
+
+again:
+	received += virtnet_receive(rq, budget);
+
+	r = virtqueue_enable_cb_prepare(rq->vq);
+	clear_bit(NAPI_STATE_SCHED, &napi->state);
+	if (unlikely(virtqueue_poll(rq->vq, r)) &&
+	    napi_schedule_prep(napi)) {
+		virtqueue_disable_cb(rq->vq);
+		if (received < budget) {
+			budget -= received;
+			goto again;
+		} else {
+			__napi_schedule(napi);
+		}
+	}
+
+	return received;
+}
+#endif	/* CONFIG_NET_RX_BUSY_POLL */
+
 static int virtnet_open(struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
@@ -1347,6 +1396,9 @@ static const struct net_device_ops virtn
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = virtnet_netpoll,
 #endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= virtnet_busy_poll,
+#endif
 };
 
 static void virtnet_config_changed_work(struct work_struct *work)
@@ -1552,6 +1604,7 @@ static int virtnet_alloc_queues(struct v
 		vi->rq[i].pages = NULL;
 		netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
 			       napi_weight);
+		napi_hash_add(&vi->rq[i].napi);
 
 		sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
 		ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
@@ -1853,11 +1906,13 @@ static int virtnet_freeze(struct virtio_
 	netif_device_detach(vi->dev);
 	cancel_delayed_work_sync(&vi->refill);
 
-	if (netif_running(vi->dev))
+	if (netif_running(vi->dev)) {
 		for (i = 0; i < vi->max_queue_pairs; i++) {
 			napi_disable(&vi->rq[i].napi);
+			napi_hash_del(&vi->rq[i].napi);
 			netif_napi_del(&vi->rq[i].napi);
 		}
+	}
 
 	remove_vq_common(vi);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/vmxnet3/vmxnet3_drv.c linux-libre-3.17-rc7-gnu/drivers/net/vmxnet3/vmxnet3_drv.c
--- linux-libre-3.16-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@ char vmxnet3_driver_name[] = "vmxnet3";
  * PCI Device ID Table
  * Last entry must be all 0s
  */
-static DEFINE_PCI_DEVICE_TABLE(vmxnet3_pciid_table) = {
+static const struct pci_device_id vmxnet3_pciid_table[] = {
 	{PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)},
 	{0}
 };
@@ -766,7 +766,7 @@ vmxnet3_map_pkt(struct sk_buff *skb, str
 			gdesc->dword[3] = 0;
 
 			netdev_dbg(adapter->netdev,
-				"txd[%u]: 0x%llu %u %u\n",
+				"txd[%u]: 0x%llx %u %u\n",
 				tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
 				le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
 			vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
@@ -2056,7 +2056,6 @@ vmxnet3_set_mc(struct net_device *netdev
 		if (!netdev_mc_empty(netdev)) {
 			new_table = vmxnet3_copy_mc(netdev);
 			if (new_table) {
-				new_mode |= VMXNET3_RXM_MCAST;
 				rxConf->mfTableLen = cpu_to_le16(
 					netdev_mc_count(netdev) * ETH_ALEN);
 				new_table_pa = dma_map_single(
@@ -2064,15 +2063,18 @@ vmxnet3_set_mc(struct net_device *netdev
 							new_table,
 							rxConf->mfTableLen,
 							PCI_DMA_TODEVICE);
+			}
+
+			if (new_table_pa) {
+				new_mode |= VMXNET3_RXM_MCAST;
 				rxConf->mfTablePA = cpu_to_le64(new_table_pa);
 			} else {
-				netdev_info(netdev, "failed to copy mcast list"
-					    ", setting ALL_MULTI\n");
+				netdev_info(netdev,
+					    "failed to copy mcast list, setting ALL_MULTI\n");
 				new_mode |= VMXNET3_RXM_ALL_MULTI;
 			}
 		}
 
-
 	if (!(new_mode & VMXNET3_RXM_MCAST)) {
 		rxConf->mfTableLen = 0;
 		rxConf->mfTablePA = 0;
@@ -2091,11 +2093,10 @@ vmxnet3_set_mc(struct net_device *netdev
 			       VMXNET3_CMD_UPDATE_MAC_FILTERS);
 	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
-	if (new_table) {
+	if (new_table_pa)
 		dma_unmap_single(&adapter->pdev->dev, new_table_pa,
 				 rxConf->mfTableLen, PCI_DMA_TODEVICE);
-		kfree(new_table);
-	}
+	kfree(new_table);
 }
 
 void
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/vmxnet3/vmxnet3_int.h linux-libre-3.17-rc7-gnu/drivers/net/vmxnet3/vmxnet3_int.h
--- linux-libre-3.16-gnu/drivers/net/vmxnet3/vmxnet3_int.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/vmxnet3/vmxnet3_int.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,10 +69,10 @@
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.2.0.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.2.1.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01020000
+#define VMXNET3_DRIVER_VERSION_NUM      0x01020100
 
 #if defined(CONFIG_PCI_MSI)
 	/* RSS only makes sense if MSI-X is supported. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/vxlan.c linux-libre-3.17-rc7-gnu/drivers/net/vxlan.c
--- linux-libre-3.16-gnu/drivers/net/vxlan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/vxlan.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 #include <net/ip_tunnels.h>
 #include <net/icmp.h>
 #include <net/udp.h>
+#include <net/udp_tunnel.h>
 #include <net/rtnetlink.h>
 #include <net/route.h>
 #include <net/dsfield.h>
@@ -933,7 +934,8 @@ out:
 
 /* Dump forwarding table */
 static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
-			  struct net_device *dev, int idx)
+			  struct net_device *dev,
+			  struct net_device *filter_dev, int idx)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	unsigned int h;
@@ -1325,7 +1327,7 @@ static int arp_reduce(struct net_device
 	} else if (vxlan->flags & VXLAN_F_L3MISS) {
 		union vxlan_addr ipa = {
 			.sin.sin_addr.s_addr = tip,
-			.sa.sa_family = AF_INET,
+			.sin.sin_family = AF_INET,
 		};
 
 		vxlan_ip_miss(dev, &ipa);
@@ -1486,7 +1488,7 @@ static int neigh_reduce(struct net_devic
 	} else if (vxlan->flags & VXLAN_F_L3MISS) {
 		union vxlan_addr ipa = {
 			.sin6.sin6_addr = msg->target,
-			.sa.sa_family = AF_INET6,
+			.sin6.sin6_family = AF_INET6,
 		};
 
 		vxlan_ip_miss(dev, &ipa);
@@ -1519,7 +1521,7 @@ static bool route_shortcircuit(struct ne
 		if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin.sin_addr.s_addr = pip->daddr,
-				.sa.sa_family = AF_INET,
+				.sin.sin_family = AF_INET,
 			};
 
 			vxlan_ip_miss(dev, &ipa);
@@ -1540,7 +1542,7 @@ static bool route_shortcircuit(struct ne
 		if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin6.sin6_addr = pip6->daddr,
-				.sa.sa_family = AF_INET6,
+				.sin6.sin6_family = AF_INET6,
 			};
 
 			vxlan_ip_miss(dev, &ipa);
@@ -1570,25 +1572,6 @@ static bool route_shortcircuit(struct ne
 	return false;
 }
 
-/* Compute source port for outgoing packet
- *   first choice to use L4 flow hash since it will spread
- *     better and maybe available from hardware
- *   secondary choice is to use jhash on the Ethernet header
- */
-__be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
-{
-	unsigned int range = (port_max - port_min) + 1;
-	u32 hash;
-
-	hash = skb_get_hash(skb);
-	if (!hash)
-		hash = jhash(skb->data, 2 * ETH_ALEN,
-			     (__force u32) skb->protocol);
-
-	return htons((((u64) hash * range) >> 32) + port_min);
-}
-EXPORT_SYMBOL_GPL(vxlan_src_port);
-
 static inline struct sk_buff *vxlan_handle_offloads(struct sk_buff *skb,
 						    bool udp_csum)
 {
@@ -1807,7 +1790,8 @@ static void vxlan_xmit_one(struct sk_buf
 	if (tos == 1)
 		tos = ip_tunnel_get_dsfield(old_iph, skb);
 
-	src_port = vxlan_src_port(vxlan->port_min, vxlan->port_max, skb);
+	src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->port_min,
+				     vxlan->port_max, true);
 
 	if (dst->sa.sa_family == AF_INET) {
 		memset(&fl4, 0, sizeof(fl4));
@@ -2235,7 +2219,6 @@ static void vxlan_setup(struct net_devic
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	unsigned int h;
-	int low, high;
 
 	eth_hw_addr_random(dev);
 	ether_setup(dev);
@@ -2272,9 +2255,6 @@ static void vxlan_setup(struct net_devic
 	vxlan->age_timer.function = vxlan_cleanup;
 	vxlan->age_timer.data = (unsigned long) vxlan;
 
-	inet_get_local_port_range(dev_net(dev), &low, &high);
-	vxlan->port_min = low;
-	vxlan->port_max = high;
 	vxlan->dst_port = htons(vxlan_port);
 
 	vxlan->dev = dev;
@@ -2360,102 +2340,37 @@ static void vxlan_del_work(struct work_s
 	kfree_rcu(vs, rcu);
 }
 
-#if IS_ENABLED(CONFIG_IPV6)
-/* Create UDP socket for encapsulation receive. AF_INET6 socket
- * could be used for both IPv4 and IPv6 communications, but
- * users may set bindv6only=1.
- */
-static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
+static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
+					__be16 port, u32 flags)
 {
-	struct sock *sk;
 	struct socket *sock;
-	struct sockaddr_in6 vxlan_addr = {
-		.sin6_family = AF_INET6,
-		.sin6_port = port,
-	};
-	int rc, val = 1;
-
-	rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
-	if (rc < 0) {
-		pr_debug("UDPv6 socket create failed\n");
-		return ERR_PTR(rc);
-	}
-
-	/* Put in proper namespace */
-	sk = sock->sk;
-	sk_change_net(sk, net);
-
-	kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
-			  (char *)&val, sizeof(val));
-	rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr,
-			 sizeof(struct sockaddr_in6));
-	if (rc < 0) {
-		pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n",
-			 &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc);
-		sk_release_kernel(sk);
-		return ERR_PTR(rc);
-	}
-	/* At this point, IPv6 module should have been loaded in
-	 * sock_create_kern().
-	 */
-	BUG_ON(!ipv6_stub);
-
-	/* Disable multicast loopback */
-	inet_sk(sk)->mc_loop = 0;
-
-	if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX)
-		udp_set_no_check6_tx(sk, true);
-
-	if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX)
-		udp_set_no_check6_rx(sk, true);
-
-	return sock;
-}
-
-#else
-
-static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
-{
-		return ERR_PTR(-EPFNOSUPPORT);
-}
-#endif
+	struct udp_port_cfg udp_conf;
+	int err;
 
-static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags)
-{
-	struct sock *sk;
-	struct socket *sock;
-	struct sockaddr_in vxlan_addr = {
-		.sin_family = AF_INET,
-		.sin_addr.s_addr = htonl(INADDR_ANY),
-		.sin_port = port,
-	};
-	int rc;
+	memset(&udp_conf, 0, sizeof(udp_conf));
 
-	/* Create UDP socket for encapsulation receive. */
-	rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
-	if (rc < 0) {
-		pr_debug("UDP socket create failed\n");
-		return ERR_PTR(rc);
+	if (ipv6) {
+		udp_conf.family = AF_INET6;
+		udp_conf.use_udp6_tx_checksums =
+		    !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
+		udp_conf.use_udp6_rx_checksums =
+		    !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
+	} else {
+		udp_conf.family = AF_INET;
+		udp_conf.local_ip.s_addr = INADDR_ANY;
+		udp_conf.use_udp_checksums =
+		    !!(flags & VXLAN_F_UDP_CSUM);
 	}
 
-	/* Put in proper namespace */
-	sk = sock->sk;
-	sk_change_net(sk, net);
+	udp_conf.local_udp_port = port;
 
-	rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr,
-			 sizeof(vxlan_addr));
-	if (rc < 0) {
-		pr_debug("bind for UDP socket %pI4:%u (%d)\n",
-			 &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
-		sk_release_kernel(sk);
-		return ERR_PTR(rc);
-	}
+	/* Open UDP socket */
+	err = udp_sock_create(net, &udp_conf, &sock);
+	if (err < 0)
+		return ERR_PTR(err);
 
 	/* Disable multicast loopback */
-	inet_sk(sk)->mc_loop = 0;
-
-	if (!(flags & VXLAN_F_UDP_CSUM))
-		sock->sk->sk_no_check_tx = 1;
+	inet_sk(sock->sk)->mc_loop = 0;
 
 	return sock;
 }
@@ -2481,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_c
 
 	INIT_WORK(&vs->del_work, vxlan_del_work);
 
-	if (ipv6)
-		sock = create_v6_sock(net, port, flags);
-	else
-		sock = create_v4_sock(net, port, flags);
+	sock = vxlan_create_sock(net, ipv6, port, flags);
 	if (IS_ERR(sock)) {
 		kfree(vs);
 		return ERR_CAST(sock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/dlci.c linux-libre-3.17-rc7-gnu/drivers/net/wan/dlci.c
--- linux-libre-3.16-gnu/drivers/net/wan/dlci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/dlci.c	2014-09-28 17:29:07.000000000 -0400
@@ -255,7 +255,6 @@ static int dlci_dev_ioctl(struct net_dev
 				return -EINVAL;
 
 			return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);
-			break;
 
 		default: 
 			return -EOPNOTSUPP;
@@ -327,8 +326,8 @@ static int dlci_add(struct dlci_add *dlc
 		goto err1;
 
 	/* create device name */
-	master = alloc_netdev( sizeof(struct dlci_local), "dlci%d",
-			      dlci_setup);
+	master = alloc_netdev(sizeof(struct dlci_local), "dlci%d",
+			      NET_NAME_UNKNOWN, dlci_setup);
 	if (!master) {
 		err = -ENOMEM;
 		goto err1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/dscc4.c linux-libre-3.17-rc7-gnu/drivers/net/wan/dscc4.c
--- linux-libre-3.16-gnu/drivers/net/wan/dscc4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/dscc4.c	2014-09-28 17:29:07.000000000 -0400
@@ -2039,7 +2039,7 @@ static int __init dscc4_setup(char *str)
 __setup("dscc4.setup=", dscc4_setup);
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(dscc4_pci_tbl) = {
+static const struct pci_device_id dscc4_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4,
 	        PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0,}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/farsync.c linux-libre-3.17-rc7-gnu/drivers/net/wan/farsync.c
--- linux-libre-3.16-gnu/drivers/net/wan/farsync.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/farsync.c	2014-09-28 17:29:07.000000000 -0400
@@ -531,7 +531,7 @@ do {								\
 /*
  *      PCI ID lookup table
  */
-static DEFINE_PCI_DEVICE_TABLE(fst_pci_dev_id) = {
+static const struct pci_device_id fst_pci_dev_id[] = {
 	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID, 
 	 PCI_ANY_ID, 0, 0, FST_TYPE_T2P},
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/hdlc.c linux-libre-3.17-rc7-gnu/drivers/net/wan/hdlc.c
--- linux-libre-3.16-gnu/drivers/net/wan/hdlc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/hdlc.c	2014-09-28 17:29:07.000000000 -0400
@@ -256,7 +256,8 @@ static void hdlc_setup(struct net_device
 struct net_device *alloc_hdlcdev(void *priv)
 {
 	struct net_device *dev;
-	dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", hdlc_setup);
+	dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d",
+			   NET_NAME_UNKNOWN, hdlc_setup);
 	if (dev)
 		dev_to_hdlc(dev)->priv = priv;
 	return dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/hdlc_fr.c linux-libre-3.17-rc7-gnu/drivers/net/wan/hdlc_fr.c
--- linux-libre-3.16-gnu/drivers/net/wan/hdlc_fr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/hdlc_fr.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,7 @@
 #define LMI_ANSI_LENGTH		  14
 
 
-typedef struct {
+struct fr_hdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	unsigned ea1:	1;
 	unsigned cr:	1;
@@ -112,14 +112,14 @@ typedef struct {
 	unsigned de:	1;
 	unsigned ea2:	1;
 #endif
-}__packed fr_hdr;
+} __packed;
 
 
-typedef struct pvc_device_struct {
+struct pvc_device {
 	struct net_device *frad;
 	struct net_device *main;
 	struct net_device *ether;	/* bridged Ethernet interface	*/
-	struct pvc_device_struct *next;	/* Sorted in ascending DLCI order */
+	struct pvc_device *next;	/* Sorted in ascending DLCI order */
 	int dlci;
 	int open_count;
 
@@ -132,11 +132,11 @@ typedef struct pvc_device_struct {
 		unsigned int becn: 1;
 		unsigned int bandwidth;	/* Cisco LMI reporting only */
 	}state;
-}pvc_device;
+};
 
 struct frad_state {
 	fr_proto settings;
-	pvc_device *first_pvc;
+	struct pvc_device *first_pvc;
 	int dce_pvc_count;
 
 	struct timer_list timer;
@@ -174,9 +174,9 @@ static inline struct frad_state* state(h
 }
 
 
-static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
+static inline struct pvc_device *find_pvc(hdlc_device *hdlc, u16 dlci)
 {
-	pvc_device *pvc = state(hdlc)->first_pvc;
+	struct pvc_device *pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {
 		if (pvc->dlci == dlci)
@@ -190,10 +190,10 @@ static inline pvc_device* find_pvc(hdlc_
 }
 
 
-static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
+static struct pvc_device *add_pvc(struct net_device *dev, u16 dlci)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
+	struct pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
 
 	while (*pvc_p) {
 		if ((*pvc_p)->dlci == dlci)
@@ -203,7 +203,7 @@ static pvc_device* add_pvc(struct net_de
 		pvc_p = &(*pvc_p)->next;
 	}
 
-	pvc = kzalloc(sizeof(pvc_device), GFP_ATOMIC);
+	pvc = kzalloc(sizeof(*pvc), GFP_ATOMIC);
 #ifdef DEBUG_PVC
 	printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
 #endif
@@ -218,13 +218,13 @@ static pvc_device* add_pvc(struct net_de
 }
 
 
-static inline int pvc_is_used(pvc_device *pvc)
+static inline int pvc_is_used(struct pvc_device *pvc)
 {
 	return pvc->main || pvc->ether;
 }
 
 
-static inline void pvc_carrier(int on, pvc_device *pvc)
+static inline void pvc_carrier(int on, struct pvc_device *pvc)
 {
 	if (on) {
 		if (pvc->main)
@@ -246,11 +246,11 @@ static inline void pvc_carrier(int on, p
 
 static inline void delete_unused_pvcs(hdlc_device *hdlc)
 {
-	pvc_device **pvc_p = &state(hdlc)->first_pvc;
+	struct pvc_device **pvc_p = &state(hdlc)->first_pvc;
 
 	while (*pvc_p) {
 		if (!pvc_is_used(*pvc_p)) {
-			pvc_device *pvc = *pvc_p;
+			struct pvc_device *pvc = *pvc_p;
 #ifdef DEBUG_PVC
 			printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
 #endif
@@ -263,7 +263,8 @@ static inline void delete_unused_pvcs(hd
 }
 
 
-static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
+static inline struct net_device **get_dev_p(struct pvc_device *pvc,
+					    int type)
 {
 	if (type == ARPHRD_ETHER)
 		return &pvc->ether;
@@ -342,7 +343,7 @@ static int fr_hard_header(struct sk_buff
 
 static int pvc_open(struct net_device *dev)
 {
-	pvc_device *pvc = dev->ml_priv;
+	struct pvc_device *pvc = dev->ml_priv;
 
 	if ((pvc->frad->flags & IFF_UP) == 0)
 		return -EIO;  /* Frad must be UP in order to activate PVC */
@@ -362,7 +363,7 @@ static int pvc_open(struct net_device *d
 
 static int pvc_close(struct net_device *dev)
 {
-	pvc_device *pvc = dev->ml_priv;
+	struct pvc_device *pvc = dev->ml_priv;
 
 	if (--pvc->open_count == 0) {
 		hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
@@ -381,7 +382,7 @@ static int pvc_close(struct net_device *
 
 static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	pvc_device *pvc = dev->ml_priv;
+	struct pvc_device *pvc = dev->ml_priv;
 	fr_proto_pvc_info info;
 
 	if (ifr->ifr_settings.type == IF_GET_PROTO) {
@@ -409,7 +410,7 @@ static int pvc_ioctl(struct net_device *
 
 static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	pvc_device *pvc = dev->ml_priv;
+	struct pvc_device *pvc = dev->ml_priv;
 
 	if (pvc->state.active) {
 		if (dev->type == ARPHRD_ETHER) {
@@ -444,7 +445,7 @@ static netdev_tx_t pvc_xmit(struct sk_bu
 	return NETDEV_TX_OK;
 }
 
-static inline void fr_log_dlci_active(pvc_device *pvc)
+static inline void fr_log_dlci_active(struct pvc_device *pvc)
 {
 	netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
 		    pvc->dlci,
@@ -469,7 +470,7 @@ static void fr_lmi_send(struct net_devic
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct sk_buff *skb;
-	pvc_device *pvc = state(hdlc)->first_pvc;
+	struct pvc_device *pvc = state(hdlc)->first_pvc;
 	int lmi = state(hdlc)->settings.lmi;
 	int dce = state(hdlc)->settings.dce;
 	int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
@@ -566,7 +567,7 @@ static void fr_lmi_send(struct net_devic
 static void fr_set_link_state(int reliable, struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc = state(hdlc)->first_pvc;
+	struct pvc_device *pvc = state(hdlc)->first_pvc;
 
 	state(hdlc)->reliable = reliable;
 	if (reliable) {
@@ -652,7 +653,7 @@ static void fr_timer(unsigned long arg)
 static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc;
+	struct pvc_device *pvc;
 	u8 rxseq, txseq;
 	int lmi = state(hdlc)->settings.lmi;
 	int dce = state(hdlc)->settings.dce;
@@ -869,10 +870,10 @@ static int fr_rx(struct sk_buff *skb)
 {
 	struct net_device *frad = skb->dev;
 	hdlc_device *hdlc = dev_to_hdlc(frad);
-	fr_hdr *fh = (fr_hdr*)skb->data;
+	struct fr_hdr *fh = (struct fr_hdr *)skb->data;
 	u8 *data = skb->data;
 	u16 dlci;
-	pvc_device *pvc;
+	struct pvc_device *pvc;
 	struct net_device *dev = NULL;
 
 	if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI)
@@ -1028,7 +1029,7 @@ static void fr_stop(struct net_device *d
 static void fr_close(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc = state(hdlc)->first_pvc;
+	struct pvc_device *pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {		/* Shutdown all PVCs for this FRAD */
 		if (pvc->main)
@@ -1060,7 +1061,7 @@ static const struct net_device_ops pvc_o
 static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 {
 	hdlc_device *hdlc = dev_to_hdlc(frad);
-	pvc_device *pvc;
+	struct pvc_device *pvc;
 	struct net_device *dev;
 	int used;
 
@@ -1075,10 +1076,11 @@ static int fr_add_pvc(struct net_device
 	used = pvc_is_used(pvc);
 
 	if (type == ARPHRD_ETHER) {
-		dev = alloc_netdev(0, "pvceth%d", ether_setup);
+		dev = alloc_netdev(0, "pvceth%d", NET_NAME_UNKNOWN,
+				   ether_setup);
 		dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	} else
-		dev = alloc_netdev(0, "pvc%d", pvc_setup);
+		dev = alloc_netdev(0, "pvc%d", NET_NAME_UNKNOWN, pvc_setup);
 
 	if (!dev) {
 		netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
@@ -1116,7 +1118,7 @@ static int fr_add_pvc(struct net_device
 
 static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
 {
-	pvc_device *pvc;
+	struct pvc_device *pvc;
 	struct net_device *dev;
 
 	if ((pvc = find_pvc(hdlc, dlci)) == NULL)
@@ -1144,13 +1146,13 @@ static int fr_del_pvc(hdlc_device *hdlc,
 static void fr_destroy(struct net_device *frad)
 {
 	hdlc_device *hdlc = dev_to_hdlc(frad);
-	pvc_device *pvc = state(hdlc)->first_pvc;
+	struct pvc_device *pvc = state(hdlc)->first_pvc;
 	state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
 	state(hdlc)->dce_pvc_count = 0;
 	state(hdlc)->dce_changed = 1;
 
 	while (pvc) {
-		pvc_device *next = pvc->next;
+		struct pvc_device *next = pvc->next;
 		/* destructors will free_netdev() main and ether */
 		if (pvc->main)
 			unregister_netdevice(pvc->main);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/lapbether.c linux-libre-3.17-rc7-gnu/drivers/net/wan/lapbether.c
--- linux-libre-3.16-gnu/drivers/net/wan/lapbether.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/lapbether.c	2014-09-28 17:29:07.000000000 -0400
@@ -325,8 +325,8 @@ static int lapbeth_new_device(struct net
 
 	ASSERT_RTNL();
 
-	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", 
-			   lapbeth_setup);
+	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
+			    lapbeth_setup);
 	if (!ndev)
 		goto out;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/lmc/lmc_main.c linux-libre-3.17-rc7-gnu/drivers/net/wan/lmc/lmc_main.c
--- linux-libre-3.16-gnu/drivers/net/wan/lmc/lmc_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/lmc/lmc_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@
 
 static int LMC_PKT_BUF_SZ = 1542;
 
-static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = {
+static const struct pci_device_id lmc_pci_tbl[] = {
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
 	  PCI_VENDOR_ID_LMC, PCI_ANY_ID },
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/pc300too.c linux-libre-3.17-rc7-gnu/drivers/net/wan/pc300too.c
--- linux-libre-3.16-gnu/drivers/net/wan/pc300too.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/pc300too.c	2014-09-28 17:29:07.000000000 -0400
@@ -477,7 +477,7 @@ static int pc300_pci_init_one(struct pci
 
 
 
-static DEFINE_PCI_DEVICE_TABLE(pc300_pci_tbl) = {
+static const struct pci_device_id pc300_pci_tbl[] = {
 	{ PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID,
 	  PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/pci200syn.c linux-libre-3.17-rc7-gnu/drivers/net/wan/pci200syn.c
--- linux-libre-3.16-gnu/drivers/net/wan/pci200syn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/pci200syn.c	2014-09-28 17:29:07.000000000 -0400
@@ -414,7 +414,7 @@ static int pci200_pci_init_one(struct pc
 
 
 
-static DEFINE_PCI_DEVICE_TABLE(pci200_pci_tbl) = {
+static const struct pci_device_id pci200_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
 	  PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
 	{ 0, }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/sbni.c linux-libre-3.17-rc7-gnu/drivers/net/wan/sbni.c
--- linux-libre-3.16-gnu/drivers/net/wan/sbni.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/sbni.c	2014-09-28 17:29:07.000000000 -0400
@@ -227,7 +227,8 @@ int __init sbni_probe(int unit)
 	struct net_device *dev;
 	int err;
 
-	dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
+	dev = alloc_netdev(sizeof(struct net_local), "sbni",
+			   NET_NAME_UNKNOWN, sbni_devsetup);
 	if (!dev)
 		return -ENOMEM;
 
@@ -1477,8 +1478,8 @@ int __init init_module( void )
 	int err;
 
 	while( num < SBNI_MAX_NUM_CARDS ) {
-		dev = alloc_netdev(sizeof(struct net_local), 
-				   "sbni%d", sbni_devsetup);
+		dev = alloc_netdev(sizeof(struct net_local), "sbni%d",
+				   NET_NAME_UNKNOWN, sbni_devsetup);
 		if( !dev)
 			break;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/sdla.c linux-libre-3.17-rc7-gnu/drivers/net/wan/sdla.c
--- linux-libre-3.16-gnu/drivers/net/wan/sdla.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/sdla.c	2014-09-28 17:29:07.000000000 -0400
@@ -1631,7 +1631,8 @@ static int __init init_sdla(void)
 
 	printk("%s.\n", version);
 
-	sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);
+	sdla = alloc_netdev(sizeof(struct frad_local), "sdla0",
+			    NET_NAME_UNKNOWN, setup_sdla);
 	if (!sdla) 
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/wanxl.c linux-libre-3.17-rc7-gnu/drivers/net/wan/wanxl.c
--- linux-libre-3.16-gnu/drivers/net/wan/wanxl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/wanxl.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,24 +54,24 @@ static const char* version = "wanXL seri
 #define MBX2_MEMSZ_MASK 0xFFFF0000 /* PUTS Memory Size Register mask */
 
 
-typedef struct {
+struct port {
 	struct net_device *dev;
-	struct card_t *card;
+	struct card *card;
 	spinlock_t lock;	/* for wanxl_xmit */
         int node;		/* physical port #0 - 3 */
 	unsigned int clock_type;
 	int tx_in, tx_out;
 	struct sk_buff *tx_skbs[TX_BUFFERS];
-}port_t;
+};
 
 
-typedef struct {
+struct card_status {
 	desc_t rx_descs[RX_QUEUE_LENGTH];
 	port_status_t port_status[4];
-}card_status_t;
+};
 
 
-typedef struct card_t {
+struct card {
 	int n_ports;		/* 1, 2 or 4 ports */
 	u8 irq;
 
@@ -79,20 +79,20 @@ typedef struct card_t {
 	struct pci_dev *pdev;	/* for pci_name(pdev) */
 	int rx_in;
 	struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
-	card_status_t *status;	/* shared between host and card */
+	struct card_status *status;	/* shared between host and card */
 	dma_addr_t status_address;
-	port_t ports[0];	/* 1 - 4 port_t structures follow */
-}card_t;
+	struct port ports[0];	/* 1 - 4 port structures follow */
+};
 
 
 
-static inline port_t* dev_to_port(struct net_device *dev)
+static inline struct port *dev_to_port(struct net_device *dev)
 {
-        return (port_t *)dev_to_hdlc(dev)->priv;
+	return (struct port *)dev_to_hdlc(dev)->priv;
 }
 
 
-static inline port_status_t* get_status(port_t *port)
+static inline port_status_t *get_status(struct port *port)
 {
 	return &port->card->status->port_status[port->node];
 }
@@ -115,7 +115,7 @@ static inline dma_addr_t pci_map_single_
 
 
 /* Cable and/or personality module change interrupt service */
-static inline void wanxl_cable_intr(port_t *port)
+static inline void wanxl_cable_intr(struct port *port)
 {
 	u32 value = get_status(port)->cable;
 	int valid = 1;
@@ -160,7 +160,7 @@ static inline void wanxl_cable_intr(port
 
 
 /* Transmit complete interrupt service */
-static inline void wanxl_tx_intr(port_t *port)
+static inline void wanxl_tx_intr(struct port *port)
 {
 	struct net_device *dev = port->dev;
 	while (1) {
@@ -193,7 +193,7 @@ static inline void wanxl_tx_intr(port_t
 
 
 /* Receive complete interrupt service */
-static inline void wanxl_rx_intr(card_t *card)
+static inline void wanxl_rx_intr(struct card *card)
 {
 	desc_t *desc;
 	while (desc = &card->status->rx_descs[card->rx_in],
@@ -203,7 +203,7 @@ static inline void wanxl_rx_intr(card_t
 				pci_name(card->pdev));
 		else {
 			struct sk_buff *skb = card->rx_skbs[card->rx_in];
-			port_t *port = &card->ports[desc->stat &
+			struct port *port = &card->ports[desc->stat &
 						    PACKET_PORT_MASK];
 			struct net_device *dev = port->dev;
 
@@ -245,7 +245,7 @@ static inline void wanxl_rx_intr(card_t
 
 static irqreturn_t wanxl_intr(int irq, void* dev_id)
 {
-        card_t *card = dev_id;
+	struct card *card = dev_id;
         int i;
         u32 stat;
         int handled = 0;
@@ -272,7 +272,7 @@ static irqreturn_t wanxl_intr(int irq, v
 
 static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-        port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 	desc_t *desc;
 
         spin_lock(&port->lock);
@@ -319,7 +319,7 @@ static netdev_tx_t wanxl_xmit(struct sk_
 static int wanxl_attach(struct net_device *dev, unsigned short encoding,
 			unsigned short parity)
 {
-	port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 
 	if (encoding != ENCODING_NRZ &&
 	    encoding != ENCODING_NRZI)
@@ -343,7 +343,7 @@ static int wanxl_ioctl(struct net_device
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings line;
-	port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 
 	if (cmd != SIOCWANDEV)
 		return hdlc_ioctl(dev, ifr, cmd);
@@ -393,7 +393,7 @@ static int wanxl_ioctl(struct net_device
 
 static int wanxl_open(struct net_device *dev)
 {
-	port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 	u8 __iomem *dbr = port->card->plx + PLX_DOORBELL_TO_CARD;
 	unsigned long timeout;
 	int i;
@@ -429,7 +429,7 @@ static int wanxl_open(struct net_device
 
 static int wanxl_close(struct net_device *dev)
 {
-	port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 	unsigned long timeout;
 	int i;
 
@@ -467,7 +467,7 @@ static int wanxl_close(struct net_device
 
 static struct net_device_stats *wanxl_get_stats(struct net_device *dev)
 {
-	port_t *port = dev_to_port(dev);
+	struct port *port = dev_to_port(dev);
 
 	dev->stats.rx_over_errors = get_status(port)->rx_overruns;
 	dev->stats.rx_frame_errors = get_status(port)->rx_frame_errors;
@@ -478,7 +478,7 @@ static struct net_device_stats *wanxl_ge
 
 
 
-static int wanxl_puts_command(card_t *card, u32 cmd)
+static int wanxl_puts_command(struct card *card, u32 cmd)
 {
 	unsigned long timeout = jiffies + 5 * HZ;
 
@@ -495,7 +495,7 @@ static int wanxl_puts_command(card_t *ca
 
 
 
-static void wanxl_reset(card_t *card)
+static void wanxl_reset(struct card *card)
 {
 	u32 old_value = readl(card->plx + PLX_CONTROL) & ~PLX_CTL_RESET;
 
@@ -511,7 +511,7 @@ static void wanxl_reset(card_t *card)
 
 static void wanxl_pci_remove_one(struct pci_dev *pdev)
 {
-	card_t *card = pci_get_drvdata(pdev);
+	struct card *card = pci_get_drvdata(pdev);
 	int i;
 
 	for (i = 0; i < card->n_ports; i++) {
@@ -537,7 +537,7 @@ static void wanxl_pci_remove_one(struct
 		iounmap(card->plx);
 
 	if (card->status)
-		pci_free_consistent(pdev, sizeof(card_status_t),
+		pci_free_consistent(pdev, sizeof(struct card_status),
 				    card->status, card->status_address);
 
 	pci_release_regions(pdev);
@@ -560,7 +560,7 @@ static const struct net_device_ops wanxl
 static int wanxl_pci_init_one(struct pci_dev *pdev,
 			      const struct pci_device_id *ent)
 {
-	card_t *card;
+	struct card *card;
 	u32 ramsize, stat;
 	unsigned long timeout;
 	u32 plx_phy;		/* PLX PCI base address */
@@ -601,7 +601,7 @@ static int wanxl_pci_init_one(struct pci
 	default: ports = 4;
 	}
 
-	alloc_size = sizeof(card_t) + ports * sizeof(port_t);
+	alloc_size = sizeof(struct card) + ports * sizeof(struct port);
 	card = kzalloc(alloc_size, GFP_KERNEL);
 	if (card == NULL) {
 		pci_release_regions(pdev);
@@ -612,7 +612,8 @@ static int wanxl_pci_init_one(struct pci
 	pci_set_drvdata(pdev, card);
 	card->pdev = pdev;
 
-	card->status = pci_alloc_consistent(pdev, sizeof(card_status_t),
+	card->status = pci_alloc_consistent(pdev,
+					    sizeof(struct card_status),
 					    &card->status_address);
 	if (card->status == NULL) {
 		wanxl_pci_remove_one(pdev);
@@ -766,7 +767,7 @@ static int wanxl_pci_init_one(struct pci
 
 	for (i = 0; i < ports; i++) {
 		hdlc_device *hdlc;
-		port_t *port = &card->ports[i];
+		struct port *port = &card->ports[i];
 		struct net_device *dev = alloc_hdlcdev(port);
 		if (!dev) {
 			pr_err("%s: unable to allocate memory\n",
@@ -807,7 +808,7 @@ static int wanxl_pci_init_one(struct pci
 	return 0;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(wanxl_pci_tbl) = {
+static const struct pci_device_id wanxl_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID,
 	  PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wan/x25_asy.c linux-libre-3.17-rc7-gnu/drivers/net/wan/x25_asy.c
--- linux-libre-3.16-gnu/drivers/net/wan/x25_asy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wan/x25_asy.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,8 +81,8 @@ static struct x25_asy *x25_asy_alloc(voi
 		char name[IFNAMSIZ];
 		sprintf(name, "x25asy%d", i);
 
-		dev = alloc_netdev(sizeof(struct x25_asy),
-				   name, x25_asy_setup);
+		dev = alloc_netdev(sizeof(struct x25_asy), name,
+				   NET_NAME_UNKNOWN, x25_asy_setup);
 		if (!dev)
 			return NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wimax/i2400m/usb.c linux-libre-3.17-rc7-gnu/drivers/net/wimax/i2400m/usb.c
--- linux-libre-3.16-gnu/drivers/net/wimax/i2400m/usb.c	2014-08-07 04:58:08.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wimax/i2400m/usb.c	2014-09-28 21:40:38.000000000 -0400
@@ -472,7 +472,7 @@ int i2400mu_probe(struct usb_interface *
 
 	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
 	result = -ENOMEM;
-	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
+	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d", NET_NAME_UNKNOWN,
 			       i2400mu_netdev_setup);
 	if (net_dev == NULL) {
 		dev_err(dev, "no memory for network device instance\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/adm8211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/adm8211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/adm8211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/adm8211.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ static unsigned int rx_ring_size __read_
 module_param(tx_ring_size, uint, 0);
 module_param(rx_ring_size, uint, 0);
 
-static DEFINE_PCI_DEVICE_TABLE(adm8211_pci_id_table) = {
+static const struct pci_device_id adm8211_pci_id_table[] = {
 	/* ADMtek ADM8211 */
 	{ PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */
 	{ PCI_DEVICE(0x1200, 0x8201) }, /* ? */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/airo.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/airo.c
--- linux-libre-3.16-gnu/drivers/net/wireless/airo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/airo.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,7 @@
 #define DRV_NAME "airo"
 
 #ifdef CONFIG_PCI
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
 	{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2685,7 +2685,8 @@ static struct net_device *init_wifidev(s
 					struct net_device *ethdev)
 {
 	int err;
-	struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
+	struct net_device *dev = alloc_netdev(0, "wifi%d", NET_NAME_UNKNOWN,
+					      wifi_setup);
 	if (!dev)
 		return NULL;
 	dev->ml_priv = ethdev->ml_priv;
@@ -2785,7 +2786,7 @@ static struct net_device *_init_airo_car
 	CapabilityRid cap_rid;
 
 	/* Create the network device object. */
-	dev = alloc_netdev(sizeof(*ai), "", ether_setup);
+	dev = alloc_netdev(sizeof(*ai), "", NET_NAME_UNKNOWN, ether_setup);
 	if (!dev) {
 		airo_print_err("", "Couldn't alloc_etherdev");
 		return NULL;
@@ -7817,7 +7818,6 @@ static int readrids(struct net_device *d
 	case AIRORRID:      ridcode = comp->ridnum;     break;
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/airo_cs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/airo_cs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/airo_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/airo_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,18 +56,18 @@ static void airo_release(struct pcmcia_d
 
 static void airo_detach(struct pcmcia_device *p_dev);
 
-typedef struct local_info_t {
+struct local_info {
 	struct net_device *eth_dev;
-} local_info_t;
+};
 
 static int airo_probe(struct pcmcia_device *p_dev)
 {
-	local_info_t *local;
+	struct local_info *local;
 
 	dev_dbg(&p_dev->dev, "airo_attach()\n");
 
 	/* Allocate space for private device-specific data */
-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
+	local = kzalloc(sizeof(*local), GFP_KERNEL);
 	if (!local)
 		return -ENOMEM;
 
@@ -82,10 +82,11 @@ static void airo_detach(struct pcmcia_de
 
 	airo_release(link);
 
-	if (((local_info_t *)link->priv)->eth_dev) {
-		stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0);
+	if (((struct local_info *)link->priv)->eth_dev) {
+		stop_airo_card(((struct local_info *)link->priv)->eth_dev,
+			       0);
 	}
-	((local_info_t *)link->priv)->eth_dev = NULL;
+	((struct local_info *)link->priv)->eth_dev = NULL;
 
 	kfree(link->priv);
 } /* airo_detach */
@@ -101,7 +102,7 @@ static int airo_cs_config_check(struct p
 
 static int airo_config(struct pcmcia_device *link)
 {
-	local_info_t *dev;
+	struct local_info *dev;
 	int ret;
 
 	dev = link->priv;
@@ -121,10 +122,10 @@ static int airo_config(struct pcmcia_dev
 	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
-	((local_info_t *)link->priv)->eth_dev =
+	((struct local_info *)link->priv)->eth_dev =
 		init_airo_card(link->irq,
 			       link->resource[0]->start, 1, &link->dev);
-	if (!((local_info_t *)link->priv)->eth_dev)
+	if (!((struct local_info *)link->priv)->eth_dev)
 		goto failed;
 
 	return 0;
@@ -142,7 +143,7 @@ static void airo_release(struct pcmcia_d
 
 static int airo_suspend(struct pcmcia_device *link)
 {
-	local_info_t *local = link->priv;
+	struct local_info *local = link->priv;
 
 	netif_device_detach(local->eth_dev);
 
@@ -151,7 +152,7 @@ static int airo_suspend(struct pcmcia_de
 
 static int airo_resume(struct pcmcia_device *link)
 {
-	local_info_t *local = link->priv;
+	struct local_info *local = link->priv;
 
 	if (link->open) {
 		reset_airo_card(local->eth_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/at76c50x-usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/at76c50x-usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/at76c50x-usb.c	2014-08-07 04:53:33.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/at76c50x-usb.c	2014-09-28 21:35:22.000000000 -0400
@@ -1948,8 +1948,9 @@ static void at76_dwork_hw_scan(struct wo
 
 static int at76_hw_scan(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			struct cfg80211_scan_request *req)
+			struct ieee80211_scan_request *hw_req)
 {
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct at76_priv *priv = hw->priv;
 	struct at76_req_scan scan;
 	u8 *ssid = NULL;
@@ -2415,8 +2416,6 @@ static void at76_delete_device(struct at
 
 	kfree_skb(priv->rx_skb);
 
-	usb_put_dev(priv->udev);
-
 	at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/ieee80211_hw",
 		 __func__);
 	ieee80211_free_hw(priv->hw);
@@ -2550,6 +2549,7 @@ static void at76_disconnect(struct usb_i
 
 	wiphy_info(priv->hw->wiphy, "disconnecting\n");
 	at76_delete_device(priv);
+	usb_put_dev(priv->udev);
 	dev_info(&interface->dev, "disconnected\n");
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/ce.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/ce.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/ce.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/ce.c	2014-09-28 17:29:07.000000000 -0400
@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next
 		if (ret)
 			return ret;
 
-		src_ring->hw_index =
-			ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
-		src_ring->hw_index &= nentries_mask;
+		read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+		if (read_index == 0xffffffff)
+			return -ENODEV;
+
+		read_index &= nentries_mask;
+		src_ring->hw_index = read_index;
 
 		ath10k_pci_sleep(ar);
 	}
 
 	read_index = src_ring->hw_index;
 
-	if ((read_index == sw_index) || (read_index == 0xffffffff))
+	if (read_index == sw_index)
 		return -EIO;
 
 	sbase = src_ring->shadow_base;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/core.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/core.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/core.c	2014-08-07 04:55:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/core.c	2014-09-28 21:37:46.000000000 -0400
@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar)
 
 	INIT_LIST_HEAD(&ar->arvifs);
 
-	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
 		ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
 			    ar->hw_params.name,
 			    ar->target_version,
@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
 			    ar->fw_api,
 			    ar->htt.target_version_major,
 			    ar->htt.target_version_minor);
+		ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
+			    config_enabled(CONFIG_ATH10K_DEBUG),
+			    config_enabled(CONFIG_ATH10K_DEBUGFS),
+			    config_enabled(CONFIG_ATH10K_TRACING),
+			    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
+	}
 
 	__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
 
@@ -988,7 +994,9 @@ err_unregister_mac:
 err_release_fw:
 	ath10k_core_free_firmware_files(ar);
 err:
-	device_release_driver(ar->dev);
+	/* TODO: It's probably a good idea to release device from the driver
+	 * but calling device_release_driver() here will cause a deadlock.
+	 */
 	return;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/core.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/core.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/core.h	2014-09-28 17:29:07.000000000 -0400
@@ -290,6 +290,9 @@ struct ath10k_debug {
 	struct ath_dfs_pool_stats dfs_pool_stats;
 
 	u32 fw_dbglog_mask;
+
+	u8 htt_max_amsdu;
+	u8 htt_max_ampdu;
 };
 
 enum ath10k_state {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/debug.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/debug.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -671,6 +671,72 @@ static const struct file_operations fops
 	.llseek = default_llseek,
 };
 
+static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
+					       char __user *user_buf,
+					       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[64];
+	u8 amsdu = 3, ampdu = 64;
+	unsigned int len;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->debug.htt_max_amsdu)
+		amsdu = ar->debug.htt_max_amsdu;
+
+	if (ar->debug.htt_max_ampdu)
+		ampdu = ar->debug.htt_max_ampdu;
+
+	mutex_unlock(&ar->conf_mutex);
+
+	len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
+						const char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	int res;
+	char buf[64];
+	unsigned int amsdu, ampdu;
+
+	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+
+	/* make sure that buf is null terminated */
+	buf[sizeof(buf) - 1] = 0;
+
+	res = sscanf(buf, "%u %u", &amsdu, &ampdu);
+
+	if (res != 2)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+
+	res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
+	if (res)
+		goto out;
+
+	res = count;
+	ar->debug.htt_max_amsdu = amsdu;
+	ar->debug.htt_max_ampdu = ampdu;
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return res;
+}
+
+static const struct file_operations fops_htt_max_amsdu_ampdu = {
+	.read = ath10k_read_htt_max_amsdu_ampdu,
+	.write = ath10k_write_htt_max_amsdu_ampdu,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t ath10k_read_fw_dbglog(struct file *file,
 					    char __user *user_buf,
 					    size_t count, loff_t *ppos)
@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar
 	 * warning from del_timer(). */
 	if (ar->debug.htt_stats_mask != 0)
 		cancel_delayed_work(&ar->debug.htt_stats_dwork);
+
+	ar->debug.htt_max_amsdu = 0;
+	ar->debug.htt_max_ampdu = 0;
 }
 
 static ssize_t ath10k_write_simulate_radar(struct file *file,
@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *a
 	debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_htt_stats_mask);
 
+	debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_htt_max_amsdu_ampdu);
+
 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_dbglog);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htc.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htc.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htc.c	2014-09-28 17:29:07.000000000 -0400
@@ -546,7 +546,7 @@ static u8 ath10k_htc_get_credit_allocati
 
 int ath10k_htc_wait_target(struct ath10k_htc *htc)
 {
-	int status = 0;
+	int i, status = 0;
 	struct ath10k_htc_svc_conn_req conn_req;
 	struct ath10k_htc_svc_conn_resp conn_resp;
 	struct ath10k_htc_msg *msg;
@@ -556,10 +556,26 @@ int ath10k_htc_wait_target(struct ath10k
 
 	status = wait_for_completion_timeout(&htc->ctl_resp,
 					     ATH10K_HTC_WAIT_TIMEOUT_HZ);
-	if (status <= 0) {
+	if (status == 0) {
+		/* Workaround: In some cases the PCI HIF doesn't
+		 * receive interrupt for the control response message
+		 * even if the buffer was completed. It is suspected
+		 * iomap writes unmasking PCI CE irqs aren't propagated
+		 * properly in KVM PCI-passthrough sometimes.
+		 */
+		ath10k_warn("failed to receive control response completion, polling..\n");
+
+		for (i = 0; i < CE_COUNT; i++)
+			ath10k_hif_send_complete_check(htc->ar, i, 1);
+
+		status = wait_for_completion_timeout(&htc->ctl_resp,
+					ATH10K_HTC_WAIT_TIMEOUT_HZ);
+
 		if (status == 0)
 			status = -ETIMEDOUT;
+	}
 
+	if (status < 0) {
 		ath10k_err("ctl_resp never came in (%d)\n", status);
 		return status;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt.h	2014-09-28 17:29:07.000000000 -0400
@@ -240,16 +240,10 @@ struct htt_oob_sync_req {
 	__le16 rsvd0;
 } __packed;
 
-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB  0
-
 struct htt_aggr_conf {
 	u8 max_num_ampdu_subframes;
-	union {
-		/* dont use bitfields; undefined behaviour */
-		u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
-		u8 max_num_amsdu_subframes:5;
-	} __packed;
+	/* amsdu_subframes is limited by 0x1F mask */
+	u8 max_num_amsdu_subframes;
 } __packed;
 
 #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct a
 int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
 int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
 int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
+int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
+				u8 max_subfrms_ampdu,
+				u8 max_subfrms_amsdu);
 
 void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt_rx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt_rx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt_rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt_rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include "txrx.h"
 #include "debug.h"
 #include "trace.h"
+#include "mac.h"
 
 #include <linux/log2.h>
 
@@ -307,7 +308,8 @@ static void ath10k_htt_rx_free_msdu_chai
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 				   u8 **fw_desc, int *fw_desc_len,
 				   struct sk_buff **head_msdu,
-				   struct sk_buff **tail_msdu)
+				   struct sk_buff **tail_msdu,
+				   u32 *attention)
 {
 	int msdu_len, msdu_chaining = 0;
 	struct sk_buff *msdu;
@@ -357,6 +359,11 @@ static int ath10k_htt_rx_amsdu_pop(struc
 			break;
 		}
 
+		*attention |= __le32_to_cpu(rx_desc->attention.flags) &
+					    (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+					     RX_ATTENTION_FLAGS_DECRYPT_ERR |
+					     RX_ATTENTION_FLAGS_FCS_ERR |
+					     RX_ATTENTION_FLAGS_MGMT_TYPE);
 		/*
 		 * Copy the FW rx descriptor for this MSDU from the rx
 		 * indication message into the MSDU's netbuf. HL uses the
@@ -1215,13 +1222,15 @@ static void ath10k_htt_rx_handler(struct
 		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
 			struct sk_buff *msdu_head, *msdu_tail;
 
+			attention = 0;
 			msdu_head = NULL;
 			msdu_tail = NULL;
 			ret = ath10k_htt_rx_amsdu_pop(htt,
 						      &fw_desc,
 						      &fw_desc_len,
 						      &msdu_head,
-						      &msdu_tail);
+						      &msdu_tail,
+						      &attention);
 
 			if (ret < 0) {
 				ath10k_warn("failed to pop amsdu from htt rx ring %d\n",
@@ -1233,7 +1242,6 @@ static void ath10k_htt_rx_handler(struct
 			rxd = container_of((void *)msdu_head->data,
 					   struct htt_rx_desc,
 					   msdu_payload);
-			attention = __le32_to_cpu(rxd->attention.flags);
 
 			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
 							 status,
@@ -1286,6 +1294,7 @@ static void ath10k_htt_rx_frag_handler(s
 	u8 *fw_desc;
 	int fw_desc_len, hdrlen, paramlen;
 	int trim;
+	u32 attention = 0;
 
 	fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
 	fw_desc = (u8 *)frag->fw_msdu_rx_desc;
@@ -1295,7 +1304,8 @@ static void ath10k_htt_rx_frag_handler(s
 
 	spin_lock_bh(&htt->rx_ring.lock);
 	ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-				      &msdu_head, &msdu_tail);
+				      &msdu_head, &msdu_tail,
+				      &attention);
 	spin_unlock_bh(&htt->rx_ring.lock);
 
 	ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
@@ -1312,10 +1322,8 @@ static void ath10k_htt_rx_frag_handler(s
 
 	hdr = (struct ieee80211_hdr *)msdu_head->data;
 	rxd = (void *)msdu_head->data - sizeof(*rxd);
-	tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-	decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_DECRYPT_ERR);
+	tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+	decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
 	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
 			RX_MSDU_START_INFO1_DECAP_FORMAT);
 
@@ -1422,6 +1430,86 @@ static void ath10k_htt_rx_frm_tx_compl(s
 	}
 }
 
+static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le16_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
+		   tid, peer_id, ev->window_size);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
+		   peer->addr, tid, ev->window_size);
+
+	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_delba *ev = &resp->rx_delba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le16_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx delba tid %hu peer_id %hu\n",
+		   tid, peer_id);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx stop rx ba session sta %pM tid %hu\n",
+		   peer->addr, tid);
+
+	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
@@ -1516,9 +1604,25 @@ void ath10k_htt_t2h_msg_handler(struct a
 		trace_ath10k_htt_stats(skb->data, skb->len);
 		break;
 	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
+		/* Firmware can return tx frames if it's unable to fully
+		 * process them and suspects host may be able to fix it. ath10k
+		 * sends all tx frames as already inspected so this shouldn't
+		 * happen unless fw has a bug.
+		 */
+		ath10k_warn("received an unexpected htt tx inspect event\n");
+		break;
 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
+		ath10k_htt_rx_addba(ar, resp);
+		break;
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
-	case HTT_T2H_MSG_TYPE_RX_FLUSH:
+		ath10k_htt_rx_delba(ar, resp);
+		break;
+	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
+		/* Ignore this event because mac80211 takes care of Rx
+		 * aggregation reordering.
+		 */
+		break;
+	}
 	default:
 		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
 			   resp->hdr.msg_type);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt_tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt_tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/htt_tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/htt_tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struc
 	return 0;
 }
 
+int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
+				u8 max_subfrms_ampdu,
+				u8 max_subfrms_amsdu)
+{
+	struct htt_aggr_conf *aggr_conf;
+	struct sk_buff *skb;
+	struct htt_cmd *cmd;
+	int len;
+	int ret;
+
+	/* Firmware defaults are: amsdu = 3 and ampdu = 64 */
+
+	if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
+		return -EINVAL;
+
+	if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
+		return -EINVAL;
+
+	len = sizeof(cmd->hdr);
+	len += sizeof(cmd->aggr_conf);
+
+	skb = ath10k_htc_alloc_skb(len);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put(skb, len);
+	cmd = (struct htt_cmd *)skb->data;
+	cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
+
+	aggr_conf = &cmd->aggr_conf;
+	aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
+	aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
+
+	ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
+		   aggr_conf->max_num_amsdu_subframes,
+		   aggr_conf->max_num_ampdu_subframes);
+
+	ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
+	if (ret) {
+		dev_kfree_skb_any(skb);
+		return ret;
+	}
+
+	return 0;
+}
+
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 {
 	struct device *dev = htt->ar->dev;
@@ -485,6 +531,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt
 	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
 	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
 
+	/* Prevent firmware from sending up tx inspection requests. There's
+	 * nothing ath10k can do with frames requested for inspection so force
+	 * it to simply rely a regular tx completion with discard status.
+	 */
+	flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
+
 	skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
 	skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
 	skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/mac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/mac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -1865,15 +1865,13 @@ static u8 ath10k_tx_h_get_vdev_id(struct
 	return 0;
 }
 
-/*
- * Frames sent to the FW have to be in "Native Wifi" format.
- * Strip the QoS field from the 802.11 header.
+/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
+ * Control in the header.
  */
-static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
-				       struct ieee80211_tx_control *control,
-				       struct sk_buff *skb)
+static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
+	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
 	u8 *qos_ctl;
 
 	if (!ieee80211_is_data_qos(hdr->frame_control))
@@ -1883,6 +1881,16 @@ static void ath10k_tx_h_qos_workaround(s
 	memmove(skb->data + IEEE80211_QOS_CTL_LEN,
 		skb->data, (void *)qos_ctl - (void *)skb->data);
 	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
+
+	/* Fw/Hw generates a corrupted QoS Control Field for QoS NullFunc
+	 * frames. Powersave is handled by the fw/hw so QoS NyllFunc frames are
+	 * used only for CQM purposes (e.g. hostapd station keepalive ping) so
+	 * it is safe to downgrade to NullFunc.
+	 */
+	if (ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
+		cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+	}
 }
 
 static void ath10k_tx_wep_key_work(struct work_struct *work)
@@ -1919,14 +1927,13 @@ unlock:
 	mutex_unlock(&arvif->ar->conf_mutex);
 }
 
-static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
+static void ath10k_tx_h_update_wep_key(struct ieee80211_vif *vif,
+				       struct ieee80211_key_conf *key,
+				       struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	struct ath10k *ar = arvif->ar;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_key_conf *key = info->control.hw_key;
 
 	if (!ieee80211_has_protected(hdr->frame_control))
 		return;
@@ -1948,11 +1955,11 @@ static void ath10k_tx_h_update_wep_key(s
 	ieee80211_queue_work(ar->hw, &arvif->wep_key_work);
 }
 
-static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
+				       struct ieee80211_vif *vif,
+				       struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 
 	/* This is case only for P2P_GO */
@@ -2254,33 +2261,28 @@ static void ath10k_tx(struct ieee80211_h
 		      struct ieee80211_tx_control *control,
 		      struct sk_buff *skb)
 {
+	struct ath10k *ar = hw->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_vif *vif = info->control.vif;
+	struct ieee80211_key_conf *key = info->control.hw_key;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ath10k *ar = hw->priv;
-	u8 tid, vdev_id;
 
 	/* We should disable CCK RATE due to P2P */
 	if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
 		ath10k_dbg(ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
 
-	/* we must calculate tid before we apply qos workaround
-	 * as we'd lose the qos control field */
-	tid = ath10k_tx_h_get_tid(hdr);
-	vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
+	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
+	ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
+	ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
 
 	/* it makes no sense to process injected frames like that */
-	if (info->control.vif &&
-	    info->control.vif->type != NL80211_IFTYPE_MONITOR) {
-		ath10k_tx_h_qos_workaround(hw, control, skb);
-		ath10k_tx_h_update_wep_key(skb);
-		ath10k_tx_h_add_p2p_noa_ie(ar, skb);
-		ath10k_tx_h_seq_no(skb);
+	if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
+		ath10k_tx_h_nwifi(hw, skb);
+		ath10k_tx_h_update_wep_key(vif, key, skb);
+		ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
+		ath10k_tx_h_seq_no(vif, skb);
 	}
 
-	ATH10K_SKB_CB(skb)->vdev_id = vdev_id;
-	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
-	ATH10K_SKB_CB(skb)->htt.tid = tid;
-
 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
 		spin_lock_bh(&ar->data_lock);
 		ATH10K_SKB_CB(skb)->htt.is_offchan = true;
@@ -3137,10 +3139,11 @@ exit:
 
 static int ath10k_hw_scan(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif,
-			  struct cfg80211_scan_request *req)
+			  struct ieee80211_scan_request *hw_req)
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct wmi_start_scan_arg arg;
 	int ret = 0;
 	int i;
@@ -4330,6 +4333,38 @@ static u64 ath10k_get_tsf(struct ieee802
 	return 0;
 }
 
+static int ath10k_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
+{
+	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+	ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
+		   arvif->vdev_id, sta->addr, tid, action);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
+		 * creation/removal. Do we need to verify this?
+		 */
+		return 0;
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/* Firmware offloads Tx aggregation entirely so deny mac80211
+		 * Tx aggregation requests.
+		 */
+		return -EOPNOTSUPP;
+	}
+
+	return -EINVAL;
+}
+
 static const struct ieee80211_ops ath10k_ops = {
 	.tx				= ath10k_tx,
 	.start				= ath10k_start,
@@ -4357,6 +4392,7 @@ static const struct ieee80211_ops ath10k
 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
+	.ampdu_action			= ath10k_ampdu_action,
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
@@ -4697,7 +4733,6 @@ int ath10k_mac_register(struct ath10k *a
 
 	ar->hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
 		BIT(NL80211_IFTYPE_AP);
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
@@ -4767,6 +4802,8 @@ int ath10k_mac_register(struct ath10k *a
 		ar->hw->wiphy->iface_combinations = ath10k_if_comb;
 		ar->hw->wiphy->n_iface_combinations =
 			ARRAY_SIZE(ath10k_if_comb);
+
+		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 	}
 
 	ar->hw->netdev_features = NETIF_F_HW_CSUM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/mac.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/mac.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/mac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/mac.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,11 +43,11 @@ static inline struct ath10k_vif *ath10k_
 	return (struct ath10k_vif *)vif->drv_priv;
 }
 
-static inline void ath10k_tx_h_seq_no(struct sk_buff *skb)
+static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
+				      struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 
 	if (info->flags  & IEEE80211_TX_CTL_ASSIGN_SEQ) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/pci.c	2014-08-07 04:55:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/pci.c	2014-09-28 21:37:51.000000000 -0400
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1
 
 #define QCA988X_2_0_DEVICE_ID	(0x003c)
 
-static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
+static const struct pci_device_id ath10k_pci_id_table[] = {
 	{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
 	{0}
 };
@@ -726,18 +726,12 @@ static void ath10k_pci_ce_recv_data(stru
 	unsigned int nbytes, max_nbytes;
 	unsigned int transfer_id;
 	unsigned int flags;
-	int err;
+	int err, num_replenish = 0;
 
 	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
 					     &ce_data, &nbytes, &transfer_id,
 					     &flags) == 0) {
-		err = ath10k_pci_post_rx_pipe(pipe_info, 1);
-		if (unlikely(err)) {
-			/* FIXME: retry */
-			ath10k_warn("failed to replenish CE rx ring %d: %d\n",
-				    pipe_info->pipe_num, err);
-		}
-
+		num_replenish++;
 		skb = transfer_context;
 		max_nbytes = skb->len + skb_tailroom(skb);
 		dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
@@ -753,6 +747,13 @@ static void ath10k_pci_ce_recv_data(stru
 		skb_put(skb, nbytes);
 		cb->rx_completion(ar, skb, pipe_info->pipe_num);
 	}
+
+	err = ath10k_pci_post_rx_pipe(pipe_info, num_replenish);
+	if (unlikely(err)) {
+		/* FIXME: retry */
+		ath10k_warn("failed to replenish CE rx ring %d (%d bufs): %d\n",
+			    pipe_info->pipe_num, num_replenish, err);
+	}
 }
 
 static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
@@ -1362,8 +1363,6 @@ static int ath10k_pci_hif_exchange_bmi_m
 		ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
 	}
 
-	init_completion(&xfer.done);
-
 	ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
 	if (ret)
 		goto err_resp;
@@ -1414,10 +1413,7 @@ static void ath10k_pci_bmi_send_done(str
 					  &nbytes, &transfer_id))
 		return;
 
-	if (xfer->wait_for_resp)
-		return;
-
-	complete(&xfer->done);
+	xfer->tx_done = true;
 }
 
 static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
@@ -1438,7 +1434,7 @@ static void ath10k_pci_bmi_recv_data(str
 	}
 
 	xfer->resp_len = nbytes;
-	complete(&xfer->done);
+	xfer->rx_done = true;
 }
 
 static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
@@ -1451,7 +1447,7 @@ static int ath10k_pci_bmi_wait(struct at
 		ath10k_pci_bmi_send_done(tx_pipe);
 		ath10k_pci_bmi_recv_data(rx_pipe);
 
-		if (completion_done(&xfer->done))
+		if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
 			return 0;
 
 		schedule();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/pci.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/pci.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/pci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/pci.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,8 @@
 #define DIAG_TRANSFER_LIMIT 2048
 
 struct bmi_xfer {
-	struct completion done;
+	bool tx_done;
+	bool rx_done;
 	bool wait_for_resp;
 	u32 resp_len;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/txrx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/txrx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(str
 	return NULL;
 }
 
-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
-						  int peer_id)
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 {
 	struct ath10k_peer *peer;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/txrx.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/txrx.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/txrx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/txrx.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 				     const u8 *addr);
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
 int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
 				 const u8 *addr);
 int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/wmi.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/wmi.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath10k/wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath10k/wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1432,7 +1432,7 @@ static void ath10k_wmi_event_host_swba(s
 			continue;
 		}
 
-		ath10k_tx_h_seq_no(bcn);
+		ath10k_tx_h_seq_no(arvif->vif, bcn);
 		ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
 		ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
 
@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(s
 {
 	struct wmi_cmd_hdr *cmd_hdr;
 	enum wmi_event_id id;
-	u16 len;
 
 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(s
 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
 		return;
 
-	len = skb->len;
-
 	trace_ath10k_wmi_event(id, skb->data, skb->len);
 
 	switch (id) {
@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(st
 {
 	struct wmi_cmd_hdr *cmd_hdr;
 	enum wmi_10x_event_id id;
-	u16 len;
 
 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(st
 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
 		return;
 
-	len = skb->len;
-
 	trace_ath10k_wmi_event(id, skb->data, skb->len);
 
 	switch (id) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/ath5k.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/ath5k.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	2014-09-28 17:29:07.000000000 -0400
@@ -1285,6 +1285,7 @@ struct ath5k_hw {
 #define ATH_STAT_STARTED	3		/* opened & irqs enabled */
 
 	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
+	unsigned int		fif_filter_flags; /* Current FIF_* filter flags */
 	struct ieee80211_channel *curchan;	/* current h/w channel */
 
 	u16			nvifs;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/base.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/base.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -1382,6 +1382,9 @@ ath5k_receive_frame(struct ath5k_hw *ah,
 	rxs->flag = 0;
 	if (unlikely(rs->rs_status & AR5K_RXERR_MIC))
 		rxs->flag |= RX_FLAG_MMIC_ERROR;
+	if (unlikely(rs->rs_status & AR5K_RXERR_CRC))
+		rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+
 
 	/*
 	 * always extend the mac timestamp, since this information is
@@ -1449,6 +1452,8 @@ ath5k_receive_frame_ok(struct ath5k_hw *
 	ah->stats.rx_bytes_count += rs->rs_datalen;
 
 	if (unlikely(rs->rs_status)) {
+		unsigned int filters;
+
 		if (rs->rs_status & AR5K_RXERR_CRC)
 			ah->stats.rxerr_crc++;
 		if (rs->rs_status & AR5K_RXERR_FIFO)
@@ -1457,7 +1462,20 @@ ath5k_receive_frame_ok(struct ath5k_hw *
 			ah->stats.rxerr_phy++;
 			if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32)
 				ah->stats.rxerr_phy_code[rs->rs_phyerr]++;
-			return false;
+
+			/*
+			 * Treat packets that underwent a CCK or OFDM reset as having a bad CRC.
+			 * These restarts happen when the radio resynchronizes to a stronger frame
+			 * while receiving a weaker frame. Here we receive the prefix of the weak
+			 * frame. Since these are incomplete packets, mark their CRC as invalid.
+			 */
+			if (rs->rs_phyerr == AR5K_RX_PHY_ERROR_OFDM_RESTART ||
+			    rs->rs_phyerr == AR5K_RX_PHY_ERROR_CCK_RESTART) {
+				rs->rs_status |= AR5K_RXERR_CRC;
+				rs->rs_status &= ~AR5K_RXERR_PHY;
+			} else {
+				return false;
+			}
 		}
 		if (rs->rs_status & AR5K_RXERR_DECRYPT) {
 			/*
@@ -1480,8 +1498,15 @@ ath5k_receive_frame_ok(struct ath5k_hw *
 			return true;
 		}
 
-		/* reject any frames with non-crypto errors */
-		if (rs->rs_status & ~(AR5K_RXERR_DECRYPT))
+		/*
+		 * Reject any frames with non-crypto errors, and take into account the
+		 * current FIF_* filters.
+		 */
+		filters = AR5K_RXERR_DECRYPT;
+		if (ah->fif_filter_flags & FIF_FCSFAIL)
+			filters |= AR5K_RXERR_CRC;
+
+		if (rs->rs_status & ~filters)
 			return false;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/led.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/led.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/led.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/led.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@
 #define ATH_POLARITY(data) ((data) & 0xff)
 
 /* Devices we match on for LED config info (typically laptops) */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {
+static const struct pci_device_id ath5k_led_devices[] = {
 	/* AR5211 */
 	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
 	/* HP Compaq nc6xx, nc4000, nx6000 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2014-09-28 17:29:07.000000000 -0400
@@ -473,6 +473,8 @@ ath5k_configure_filter(struct ieee80211_
 	/* Set the cached hw filter flags, this will later actually
 	 * be set in HW */
 	ah->filter_flags = rfilt;
+	/* Store current FIF filter flags */
+	ah->fif_filter_flags = *new_flags;
 
 	mutex_unlock(&ah->lock);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath5k/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath5k/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
 #include "reg.h"
 
 /* Known PCI ids */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
+static const struct pci_device_id ath5k_pci_id_table[] = {
 	{ PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
 	{ PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
 	{ PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/bmi.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/bmi.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/bmi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/bmi.h	2014-09-28 17:29:07.000000000 -0400
@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
 		(void) (check_type == val);				\
 		addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item));	\
 		ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4);	\
-		*val = le32_to_cpu(tmp);				\
+		if (!ret)						\
+			*val = le32_to_cpu(tmp);			\
 		ret;							\
 	})
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/cfg80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/cfg80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/cfg80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/cfg80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy
 	if (info->inactivity_timeout) {
 		inactivity_timeout = info->inactivity_timeout;
 
-		if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
+		if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+			     ar->fw_capabilities))
 			inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
 							  60);
 
@@ -3636,7 +3637,7 @@ struct wireless_dev *ath6kl_interface_ad
 	struct net_device *ndev;
 	struct ath6kl_vif *vif;
 
-	ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
+	ndev = alloc_netdev(sizeof(*vif), name, NET_NAME_UNKNOWN, ether_setup);
 	if (!ndev)
 		return NULL;
 
@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *
 		ath6kl_band_5ghz.ht_cap.ht_supported = false;
 	}
 
-	if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
+	if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+		     ar->fw_capabilities)) {
 		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
 		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
 		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/core.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/core.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar,
 
 	/* FIXME: we should free all firmwares in the error cases below */
 
+	/*
+	 * Backwards compatibility support for older ar6004 firmware images
+	 * which do not set these feature flags.
+	 */
+	if (ar->target_type == TARGET_TYPE_AR6004 &&
+	    ar->fw_api <= 4) {
+		__set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+			  ar->fw_capabilities);
+		__set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+			  ar->fw_capabilities);
+
+		if (ar->hw.id == AR6004_HW_1_3_VERSION)
+			__set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+				  ar->fw_capabilities);
+	}
+
 	/* Indicate that WMI is enabled (although not ready yet) */
 	set_bit(WMI_ENABLED, &ar->flag);
 	ar->wmi = ath6kl_wmi_init(ar);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/core.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/core.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/core.h	2014-08-07 04:55:35.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/core.h	2014-09-28 21:37:40.000000000 -0400
@@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
 	 */
 	ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
 
+	/* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */
+	ATH6KL_FW_CAPABILITY_64BIT_RATES,
+
+	/* WMI_AP_CONN_INACT_CMDID uses minutes as units */
+	ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+
+	/* use low priority endpoint for all data */
+	ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+
+	/* ratetable is the 2 stream version (max MCS15) */
+	ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
+
+	/* firmare doesn't support IP checksumming */
+	ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
+
 	/* this needs to be last */
 	ATH6KL_FW_CAPABILITY_MAX,
 };
@@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
 };
 
 enum ath6kl_hw_flags {
-	ATH6KL_HW_64BIT_RATES		= BIT(0),
-	ATH6KL_HW_AP_INACTIVITY_MINS	= BIT(1),
-	ATH6KL_HW_MAP_LP_ENDPOINT	= BIT(2),
 	ATH6KL_HW_SDIO_CRC_ERROR_WAR	= BIT(3),
 };
 
 #define ATH6KL_FW_API2_FILE "/*(DEBLOBBED)*/"
 #define ATH6KL_FW_API3_FILE "/*(DEBLOBBED)*/"
 #define ATH6KL_FW_API4_FILE "/*(DEBLOBBED)*/"
+#define ATH6KL_FW_API5_FILE "/*(DEBLOBBED)*/"
 
 /* AR6003 1.0 definitions */
 #define AR6003_HW_1_0_VERSION                 0x300002ba
@@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
 #define AR6004_HW_1_3_VERSION			0x31c8088a
 #define AR6004_HW_1_3_FW_DIR			"ath6k/AR6004/hw1.3"
 #define AR6004_HW_1_3_FIRMWARE_FILE		"/*(DEBLOBBED)*/"
-#define AR6004_HW_1_3_BOARD_DATA_FILE		"/*(DEBLOBBED)*/"
-#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE	"/*(DEBLOBBED)*/"
+#define AR6004_HW_1_3_TCMD_FIRMWARE_FILE	"/*(DEBLOBBED)*/"
+#define AR6004_HW_1_3_UTF_FIRMWARE_FILE		"/*(DEBLOBBED)*/"
+#define AR6004_HW_1_3_TESTSCRIPT_FILE		"/*(DEBLOBBED)*/"
+#define AR6004_HW_1_3_BOARD_DATA_FILE	      AR6004_HW_1_3_FW_DIR "//*(DEBLOBBED)*/"
+#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "//*(DEBLOBBED)*/"
+
+/* AR6004 3.0 definitions */
+#define AR6004_HW_3_0_VERSION			0x31C809F8
+#define AR6004_HW_3_0_FW_DIR			"ath6k/AR6004/hw3.0"
+#define AR6004_HW_3_0_FIRMWARE_FILE		"/*(DEBLOBBED)*/"
+#define AR6004_HW_3_0_TCMD_FIRMWARE_FILE	"/*(DEBLOBBED)*/"
+#define AR6004_HW_3_0_UTF_FIRMWARE_FILE		"/*(DEBLOBBED)*/"
+#define AR6004_HW_3_0_TESTSCRIPT_FILE		"/*(DEBLOBBED)*/"
+#define AR6004_HW_3_0_BOARD_DATA_FILE	      AR6004_HW_3_0_FW_DIR "//*(DEBLOBBED)*/"
+#define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "//*(DEBLOBBED)*/"
 
 /* Per STA data, used in AP mode */
 #define STA_PS_AWAKE		BIT(0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/htc_pipe.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/htc_pipe.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/htc_pipe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/htc_pipe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(st
 static void htc_rxctrl_complete(struct htc_target *context,
 				struct htc_packet *packet)
 {
-	/* TODO, can't really receive HTC control messages yet.... */
-	ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__);
+	struct sk_buff *skb = packet->skb;
+
+	if (packet->endpoint == ENDPOINT_0 &&
+	    packet->status == -ECANCELED &&
+	    skb != NULL)
+		dev_kfree_skb(skb);
 }
 
 /* htc pipe initialization */
@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_cha
 
 static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target)
 {
-	/* TODO */
+	struct htc_endpoint *endpoint;
+	struct htc_packet *packet, *tmp_pkt;
+	int i;
+
+	for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+		endpoint = &target->endpoint[i];
+
+		spin_lock_bh(&target->rx_lock);
+
+		list_for_each_entry_safe(packet, tmp_pkt,
+					 &endpoint->rx_bufq, list) {
+			list_del(&packet->list);
+			spin_unlock_bh(&target->rx_lock);
+			ath6kl_dbg(ATH6KL_DBG_HTC,
+				   "htc rx flush pkt 0x%p len %d ep %d\n",
+				   packet, packet->buf_len,
+				   packet->endpoint);
+			dev_kfree_skb(packet->pkt_cntxt);
+			spin_lock_bh(&target->rx_lock);
+		}
+
+		spin_unlock_bh(&target->rx_lock);
+	}
 }
 
 static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/init.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/init.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/init.c	2014-08-07 04:55:33.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/init.c	2014-09-28 21:37:37.000000000 -0400
@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[]
 		.board_addr			= 0x433900,
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_64BIT_RATES |
-						  ATH6KL_HW_AP_INACTIVITY_MINS,
+		.flags				= 0,
 
 		.fw = {
 			.dir		= AR6004_HW_1_0_FW_DIR,
@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[]
 		.board_addr			= 0x43d400,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_64BIT_RATES |
-						  ATH6KL_HW_AP_INACTIVITY_MINS,
+		.flags				= 0,
 		.fw = {
 			.dir		= AR6004_HW_1_1_FW_DIR,
 			.fw		= AR6004_HW_1_1_FIRMWARE_FILE,
@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[]
 		.board_addr			= 0x435c00,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_64BIT_RATES |
-						  ATH6KL_HW_AP_INACTIVITY_MINS,
+		.flags				= 0,
 
 		.fw = {
 			.dir		= AR6004_HW_1_2_FW_DIR,
@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[]
 		.board_ext_data_addr		= 0x437000,
 		.reserved_ram_size		= 7168,
 		.board_addr			= 0x436400,
-		.refclk_hz                      = 40000000,
+		.refclk_hz                      = 0,
 		.uarttx_pin                     = 11,
-		.flags				= ATH6KL_HW_64BIT_RATES |
-						  ATH6KL_HW_AP_INACTIVITY_MINS |
-						  ATH6KL_HW_MAP_LP_ENDPOINT,
+		.flags				= 0,
 
 		.fw = {
 			.dir            = AR6004_HW_1_3_FW_DIR,
 			.fw             = AR6004_HW_1_3_FIRMWARE_FILE,
+			.tcmd	        = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
+			.utf		= AR6004_HW_1_3_UTF_FIRMWARE_FILE,
+			.testscript	= AR6004_HW_1_3_TESTSCRIPT_FILE,
 		},
 
 		.fw_board               = AR6004_HW_1_3_BOARD_DATA_FILE,
 		.fw_default_board       = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
 	},
+	{
+		.id				= AR6004_HW_3_0_VERSION,
+		.name				= "ar6004 hw 3.0",
+		.dataset_patch_addr		= 0,
+		.app_load_addr			= 0x1234,
+		.board_ext_data_addr		= 0,
+		.reserved_ram_size		= 7168,
+		.board_addr			= 0x436400,
+		.testscript_addr		= 0,
+		.flags				= 0,
+
+		.fw = {
+			.dir		= AR6004_HW_3_0_FW_DIR,
+			.fw		= AR6004_HW_3_0_FIRMWARE_FILE,
+			.tcmd	        = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
+			.utf		= AR6004_HW_3_0_UTF_FIRMWARE_FILE,
+			.testscript	= AR6004_HW_3_0_TESTSCRIPT_FILE,
+		},
+
+		.fw_board		= AR6004_HW_3_0_BOARD_DATA_FILE,
+		.fw_default_board	= AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
+	},
 };
 
 /*
@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6k
 	 * but possible in theory.
 	 */
 
-	if (ar->target_type == TARGET_TYPE_AR6003) {
+	if ((ar->target_type == TARGET_TYPE_AR6003) ||
+	    (ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
+	    (ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
 		param = ar->hw.board_ext_data_addr;
 		ram_reserved_size = ar->hw.reserved_ram_size;
 
@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6k
 		return status;
 
 	/* Configure target refclk_hz */
-	status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz);
-	if (status)
-		return status;
+	if (ar->hw.refclk_hz != 0) {
+		status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
+					       ar->hw.refclk_hz);
+		if (status)
+			return status;
+	}
 
 	return 0;
 }
@@ -1109,6 +1134,12 @@ int ath6kl_init_fetch_firmwares(struct a
 	if (ret)
 		return ret;
 
+	ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
+	if (ret == 0) {
+		ar->fw_api = 5;
+		goto out;
+	}
+
 	ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
 	if (ret == 0) {
 		ar->fw_api = 4;
@@ -1158,11 +1189,19 @@ static int ath6kl_upload_board_file(stru
 		ath6kl_bmi_write_hi32(ar, hi_board_data,
 				      board_address);
 	} else {
-		ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
+		ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
+		if (ret) {
+			ath6kl_err("Failed to get board file target address.\n");
+			return ret;
+		}
 	}
 
 	/* determine where in target ram to write extended board data */
-	ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
+	ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
+	if (ret) {
+		ath6kl_err("Failed to get extended board file target address.\n");
+		return ret;
+	}
 
 	if (ar->target_type == TARGET_TYPE_AR6003 &&
 	    board_ext_address == 0) {
@@ -1184,7 +1223,6 @@ static int ath6kl_upload_board_file(stru
 	default:
 		WARN_ON(1);
 		return -EINVAL;
-		break;
 	}
 
 	if (board_ext_address &&
@@ -1227,7 +1265,13 @@ static int ath6kl_upload_board_file(stru
 	}
 
 	/* record the fact that Board Data IS initialized */
-	ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1);
+	if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
+	    (ar->version.target_ver == AR6004_HW_3_0_VERSION))
+		param = board_data_size;
+	else
+		param = 1;
+
+	ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
 
 	return ret;
 }
@@ -1358,7 +1402,11 @@ static int ath6kl_upload_testscript(stru
 	}
 
 	ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
-	ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
+
+	if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
+	    (ar->version.target_ver != AR6004_HW_3_0_VERSION))
+		ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
+
 	ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
 
 	return 0;
@@ -1564,6 +1612,11 @@ static const struct fw_capa_str_map {
 	{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
 	{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
 	{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
+	{ ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
+	{ ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
+	{ ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
+	{ ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
+	{ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
 };
 
 static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(s
 	struct ath6kl *ar = vif->ar;
 	struct target_stats *stats = &vif->target_stats;
 	struct tkip_ccmp_stats *ccmp_stats;
+	s32 rate;
 	u8 ac;
 
 	if (len < sizeof(*tgt_stats))
@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(s
 		le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
 	stats->tx_rts_fail_cnt +=
 		le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
-	stats->tx_ucast_rate =
-	    ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate));
+
+	rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate);
+	stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
 
 	stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
 	stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(s
 		le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
 	stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
 	stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
-	stats->rx_ucast_rate =
-	    ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate));
+
+	rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate);
+	stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
 
 	ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
 
@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6k
 
 void init_netdev(struct net_device *dev)
 {
+	struct ath6kl *ar = ath6kl_priv(dev);
+
 	dev->netdev_ops = &ath6kl_netdev_ops;
 	dev->destructor = free_netdev;
 	dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
 					WMI_MAX_TX_META_SZ +
 					ATH6KL_HTC_ALIGN_BYTES, 4);
 
-	dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+	if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
+		      ar->fw_capabilities))
+		dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
 
 	return;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/usb.c	2014-08-07 04:55:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/usb.c	2014-09-28 21:37:46.000000000 -0400
@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(s
 		break;
 	case WMI_DATA_VI_SVC:
 
-		if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+		if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+			     ar->fw_capabilities))
 			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
 		else
 			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(s
 		break;
 	case WMI_DATA_VO_SVC:
 
-		if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+		if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+			     ar->fw_capabilities))
 			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
 		else
 			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(st
 
 /* table of devices that work with this driver */
 static struct usb_device_id ath6kl_usb_ids[] = {
+	{USB_DEVICE(0x0cf3, 0x9375)},
 	{USB_DEVICE(0x0cf3, 0x9374)},
 	{ /* Terminating entry */ },
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/wmi.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/wmi.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
 	{0, 0}
 };
 
+static const s32 wmi_rate_tbl_mcs15[][2] = {
+	/* {W/O SGI, with SGI} */
+	{1000, 1000},
+	{2000, 2000},
+	{5500, 5500},
+	{11000, 11000},
+	{6000, 6000},
+	{9000, 9000},
+	{12000, 12000},
+	{18000, 18000},
+	{24000, 24000},
+	{36000, 36000},
+	{48000, 48000},
+	{54000, 54000},
+	{6500, 7200},     /* HT 20, MCS 0 */
+	{13000, 14400},
+	{19500, 21700},
+	{26000, 28900},
+	{39000, 43300},
+	{52000, 57800},
+	{58500, 65000},
+	{65000, 72200},
+	{13000, 14400},   /* HT 20, MCS 8 */
+	{26000, 28900},
+	{39000, 43300},
+	{52000, 57800},
+	{78000, 86700},
+	{104000, 115600},
+	{117000, 130000},
+	{130000, 144400}, /* HT 20, MCS 15 */
+	{13500, 15000},   /*HT 40, MCS 0 */
+	{27000, 30000},
+	{40500, 45000},
+	{54000, 60000},
+	{81000, 90000},
+	{108000, 120000},
+	{121500, 135000},
+	{135000, 150000},
+	{27000, 30000},   /*HT 40, MCS 8 */
+	{54000, 60000},
+	{81000, 90000},
+	{108000, 120000},
+	{162000, 180000},
+	{216000, 240000},
+	{243000, 270000},
+	{270000, 300000}, /*HT 40, MCS 15 */
+	{0, 0}
+};
+
 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
 static const u8 up_to_ac[] = {
 	WMM_AC_BE,
@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct w
 {
 	struct ath6kl *ar = wmi->parent_dev;
 
-	if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
+	if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+		     ar->fw_capabilities))
 		return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
 	else
 		return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct
 				   NO_SYNC_WMIFLAG);
 }
 
-s32 ath6kl_wmi_get_rate(s8 rate_index)
+s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index)
 {
+	struct ath6kl *ar = wmi->parent_dev;
 	u8 sgi = 0;
+	s32 ret;
 
 	if (rate_index == RATE_AUTO)
 		return 0;
@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
 		sgi = 1;
 	}
 
-	if (WARN_ON(rate_index > RATE_MCS_7_40))
-		rate_index = RATE_MCS_7_40;
+	if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
+		     ar->fw_capabilities)) {
+		if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
+			return 0;
 
-	return wmi_rate_tbl[(u32) rate_index][sgi];
+		ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
+	} else {
+		if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
+			return 0;
+
+		ret = wmi_rate_tbl[(u32) rate_index][sgi];
+	}
+
+	return ret;
 }
 
 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/wmi.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/wmi.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath6kl/wmi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath6kl/wmi.h	2014-09-28 17:29:07.000000000 -0400
@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi
 			     struct ath6kl_htcap *htcap);
 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
 
-s32 ath6kl_wmi_get_rate(s8 rate_index);
+s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index);
 
 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
 			  __be32 ips0, __be32 ips1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ahb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ahb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ahb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ahb.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,6 +113,7 @@ static int ath_ahb_probe(struct platform
 
 	irq = res->start;
 
+	ath9k_fill_chanctx_ops();
 	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (hw == NULL) {
 		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9002_mac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9002_mac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9002_mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9002_mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, voi
 
 	ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
 		| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(i->txpower, AR_XmitPower)
+		| SM(i->txpower, AR_XmitPower0)
 		| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
 		| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
 		| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@@ -306,6 +306,10 @@ ar9002_set_txdesc(struct ath_hw *ah, voi
 		| set11nRateFlags(i->rates, 2)
 		| set11nRateFlags(i->rates, 3)
 		| SM(i->rtscts_rate, AR_RTSCTSRate);
+
+	ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
+	ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
+	ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
 }
 
 static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2014-09-28 17:29:07.000000000 -0400
@@ -3535,7 +3535,8 @@ static void ar9003_hw_xpa_bias_level_app
 {
 	int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl;
 
-	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+	    AR_SREV_9531(ah))
 		REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
 	else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah))
 		REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -314,10 +314,17 @@ static void ar9003_hw_init_mode_regs(str
 			       qca953x_1p0_mac_core);
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
 			       qca953x_1p0_mac_postamble);
-		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
-			       qca953x_1p0_baseband_core);
-		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
-			       qca953x_1p0_baseband_postamble);
+		if (AR_SREV_9531_20(ah)) {
+			INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				       qca953x_2p0_baseband_core);
+			INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				       qca953x_2p0_baseband_postamble);
+		} else {
+			INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				       qca953x_1p0_baseband_core);
+			INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				       qca953x_1p0_baseband_postamble);
+		}
 		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
 			       qca953x_1p0_radio_core);
 		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, voi
 
 	ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
 		| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(i->txpower, AR_XmitPower)
+		| SM(i->txpower, AR_XmitPower0)
 		| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
 		| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
 		| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, voi
 		| SM(i->rtscts_rate, AR_RTSCTSRate);
 
 	ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+
+	ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
+	ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
+	ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
 }
 
 static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -1552,13 +1552,15 @@ static int ar9003_hw_fast_chan_change(st
 				      u8 *ini_reloaded)
 {
 	unsigned int regWrites = 0;
-	u32 modesIndex;
+	u32 modesIndex, txgain_index;
 
 	if (IS_CHAN_5GHZ(chan))
 		modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
 	else
 		modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
 
+	txgain_index = AR_SREV_9531(ah) ? 1 : modesIndex;
+
 	if (modesIndex == ah->modes_index) {
 		*ini_reloaded = false;
 		goto set_rfmode;
@@ -1573,7 +1575,7 @@ static int ar9003_hw_fast_chan_change(st
 		ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
 				   modesIndex);
 
-	REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+	REG_WRITE_ARRAY(&ah->iniModesTxGain, txgain_index, regWrites);
 
 	if (AR_SREV_9462_20_OR_LATER(ah)) {
 		/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar953x_initvals.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ar953x_initvals.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ar953x_initvals.h	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,7 @@ static const u32 qca953x_1p0_baseband_co
 	{0x00009d04, 0x40206c10},
 	{0x00009d08, 0x009c4060},
 	{0x00009d0c, 0x9883800a},
-	{0x00009d10, 0x01884061},
+	{0x00009d10, 0x018848c6},
 	{0x00009d14, 0x00c0040b},
 	{0x00009d18, 0x00000000},
 	{0x00009e08, 0x0038230c},
@@ -715,4 +715,203 @@ static const u32 qca953x_1p1_modes_no_xp
 	{0x00016448, 0x6c927a70},
 };
 
+static const u32 qca953x_2p0_baseband_core[][2] = {
+	/* Addr      allmodes */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a9f6b},
+	{0x0000980c, 0x04900000},
+	{0x00009814, 0x0280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x6400a190},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14000600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x32840bbe},
+	{0x000098bc, 0x00000002},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0xff55ff55},
+	{0x00009c08, 0x0320ff55},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x9883800a},
+	{0x00009d10, 0x018848c6},
+	{0x00009d14, 0x00c0040b},
+	{0x00009d18, 0x00000000},
+	{0x00009e08, 0x0038230c},
+	{0x00009e24, 0x990bb515},
+	{0x00009e28, 0x0c6f0000},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x813e4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x00009fd0, 0x02993b93},
+	{0x0000a20c, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a248, 0x00000140},
+	{0x0000a2a0, 0x00000007},
+	{0x0000a2c0, 0x00000007},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x000400ff},
+	{0x0000a3a8, 0x6a6a6a6a},
+	{0x0000a3ac, 0x6a6a6a6a},
+	{0x0000a3b0, 0x00c8641a},
+	{0x0000a3b4, 0x0000001a},
+	{0x0000a3b8, 0x0088642a},
+	{0x0000a3bc, 0x000001fa},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000000},
+	{0x0000a3f8, 0x0c9bd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce42108},
+	{0x0000a418, 0x2d001dce},
+	{0x0000a41c, 0x1ce73908},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce738e7},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00100000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x05000080},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a458, 0x00000000},
+	{0x0000a644, 0xbfad9d74},
+	{0x0000a648, 0x0048060a},
+	{0x0000a64c, 0x00003c37},
+	{0x0000a670, 0x03020100},
+	{0x0000a674, 0x09080504},
+	{0x0000a678, 0x0d0c0b0a},
+	{0x0000a67c, 0x13121110},
+	{0x0000a680, 0x31301514},
+	{0x0000a684, 0x35343332},
+	{0x0000a688, 0x00000036},
+	{0x0000a690, 0x08000838},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000000},
+	{0x0000a8d0, 0x004b6a8e},
+	{0x0000a8d4, 0x00000820},
+	{0x0000a8dc, 0x00000000},
+	{0x0000a8f0, 0x00000000},
+	{0x0000a8f4, 0x00000000},
+	{0x0000b2d0, 0x00000080},
+	{0x0000b2d4, 0x00000000},
+	{0x0000b2ec, 0x00000000},
+	{0x0000b2f0, 0x00000000},
+	{0x0000b2f4, 0x00000000},
+	{0x0000b2f8, 0x00000000},
+	{0x0000b408, 0x0e79e5c0},
+	{0x0000b40c, 0x00820820},
+	{0x0000b420, 0x00000000},
+};
+
+static const u32 qca953x_2p0_baseband_postamble[][5] = {
+	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+	{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+	{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+	{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+	{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+	{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+	{0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+	{0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+	{0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e},
+	{0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
+	{0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
+	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+	{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+	{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+	{0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+};
+
 #endif /* INITVALS_953X_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ath9k.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ath9k.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
+#include <linux/time.h>
 
 #include "common.h"
 #include "debug.h"
@@ -35,10 +36,7 @@ extern struct ieee80211_ops ath9k_ops;
 extern int ath9k_modparam_nohwcrypt;
 extern int led_blink;
 extern bool is_ath9k_unloaded;
-
-struct ath_config {
-	u16 txpowlimit;
-};
+extern int ath9k_use_chanctx;
 
 /*************************/
 /* Descriptor Management */
@@ -167,7 +165,6 @@ struct ath_txq {
 	u32 axq_ampdu_depth;
 	bool stopped;
 	bool axq_tx_inprogress;
-	struct list_head axq_acq;
 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
 	u8 txq_headidx;
 	u8 txq_tailidx;
@@ -185,7 +182,8 @@ struct ath_atx_ac {
 
 struct ath_frame_info {
 	struct ath_buf *bf;
-	int framelen;
+	u16 framelen;
+	s8 txq;
 	enum ath9k_key_type keytype;
 	u8 keyix;
 	u8 rtscts_rate;
@@ -280,8 +278,9 @@ struct ath_node {
 struct ath_tx_control {
 	struct ath_txq *txq;
 	struct ath_node *an;
-	u8 paprd;
 	struct ieee80211_sta *sta;
+	u8 paprd;
+	bool force_channel;
 };
 
 
@@ -325,6 +324,116 @@ struct ath_rx {
 	u32 ampdu_ref;
 };
 
+struct ath_chanctx {
+	struct cfg80211_chan_def chandef;
+	struct list_head vifs;
+	struct list_head acq[IEEE80211_NUM_ACS];
+	int hw_queue_base;
+
+	/* do not dereference, use for comparison only */
+	struct ieee80211_vif *primary_sta;
+
+	struct ath_beacon_config beacon;
+	struct ath9k_hw_cal_data caldata;
+	struct timespec tsf_ts;
+	u64 tsf_val;
+	u32 last_beacon;
+
+	u16 txpower;
+	bool offchannel;
+	bool stopped;
+	bool active;
+	bool assigned;
+	bool switch_after_beacon;
+};
+
+enum ath_chanctx_event {
+	ATH_CHANCTX_EVENT_BEACON_PREPARE,
+	ATH_CHANCTX_EVENT_BEACON_SENT,
+	ATH_CHANCTX_EVENT_TSF_TIMER,
+	ATH_CHANCTX_EVENT_BEACON_RECEIVED,
+	ATH_CHANCTX_EVENT_ASSOC,
+	ATH_CHANCTX_EVENT_SWITCH,
+	ATH_CHANCTX_EVENT_UNASSIGN,
+	ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL,
+};
+
+enum ath_chanctx_state {
+	ATH_CHANCTX_STATE_IDLE,
+	ATH_CHANCTX_STATE_WAIT_FOR_BEACON,
+	ATH_CHANCTX_STATE_WAIT_FOR_TIMER,
+	ATH_CHANCTX_STATE_SWITCH,
+	ATH_CHANCTX_STATE_FORCE_ACTIVE,
+};
+
+struct ath_chanctx_sched {
+	bool beacon_pending;
+	bool offchannel_pending;
+	enum ath_chanctx_state state;
+	u8 beacon_miss;
+
+	u32 next_tbtt;
+	u32 switch_start_time;
+	unsigned int offchannel_duration;
+	unsigned int channel_switch_time;
+
+	/* backup, in case the hardware timer fails */
+	struct timer_list timer;
+};
+
+enum ath_offchannel_state {
+	ATH_OFFCHANNEL_IDLE,
+	ATH_OFFCHANNEL_PROBE_SEND,
+	ATH_OFFCHANNEL_PROBE_WAIT,
+	ATH_OFFCHANNEL_SUSPEND,
+	ATH_OFFCHANNEL_ROC_START,
+	ATH_OFFCHANNEL_ROC_WAIT,
+	ATH_OFFCHANNEL_ROC_DONE,
+};
+
+struct ath_offchannel {
+	struct ath_chanctx chan;
+	struct timer_list timer;
+	struct cfg80211_scan_request *scan_req;
+	struct ieee80211_vif *scan_vif;
+	int scan_idx;
+	enum ath_offchannel_state state;
+	struct ieee80211_channel *roc_chan;
+	struct ieee80211_vif *roc_vif;
+	int roc_duration;
+	int duration;
+};
+#define ath_for_each_chanctx(_sc, _ctx)                             \
+	for (ctx = &sc->chanctx[0];                                 \
+	     ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1];      \
+	     ctx++)
+
+void ath9k_fill_chanctx_ops(void);
+void ath9k_chanctx_force_active(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif);
+static inline struct ath_chanctx *
+ath_chanctx_get(struct ieee80211_chanctx_conf *ctx)
+{
+	struct ath_chanctx **ptr = (void *) ctx->drv_priv;
+	return *ptr;
+}
+void ath_chanctx_init(struct ath_softc *sc);
+void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
+			     struct cfg80211_chan_def *chandef);
+void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
+			struct cfg80211_chan_def *chandef);
+void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
+void ath_offchannel_timer(unsigned long data);
+void ath_offchannel_channel_change(struct ath_softc *sc);
+void ath_chanctx_offchan_switch(struct ath_softc *sc,
+				struct ieee80211_channel *chan);
+struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc,
+					      bool active);
+void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
+		       enum ath_chanctx_event ev);
+void ath_chanctx_timer(unsigned long data);
+
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan);
 int ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
@@ -341,6 +450,7 @@ void ath_draintxq(struct ath_softc *sc,
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
 void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
+void ath_txq_schedule_all(struct ath_softc *sc);
 int ath_tx_init(struct ath_softc *sc, int nbufs);
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *q);
@@ -370,32 +480,47 @@ void ath9k_release_buffered_frames(struc
 /********/
 
 struct ath_vif {
+	struct list_head list;
+
 	struct ieee80211_vif *vif;
 	struct ath_node mcast_node;
 	int av_bslot;
-	bool primary_sta_vif;
 	__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
 	struct ath_buf *av_bcbuf;
+	struct ath_chanctx *chanctx;
 
 	/* P2P Client */
 	struct ieee80211_noa_data noa;
+
+	/* P2P GO */
+	u8 noa_index;
+	u32 offchannel_start;
+	u32 offchannel_duration;
+
+	u32 periodic_noa_start;
+	u32 periodic_noa_duration;
 };
 
 struct ath9k_vif_iter_data {
 	u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
 	u8 mask[ETH_ALEN]; /* bssid mask */
 	bool has_hw_macaddr;
+	u8 slottime;
+	bool beacons;
 
 	int naps;      /* number of AP vifs */
 	int nmeshes;   /* number of mesh vifs */
 	int nstations; /* number of station vifs */
 	int nwds;      /* number of WDS vifs */
 	int nadhocs;   /* number of adhoc vifs */
+	struct ieee80211_vif *primary_sta;
 };
 
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+			       struct ath_chanctx *ctx,
 			       struct ath9k_vif_iter_data *iter_data);
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+				   struct ath_chanctx *ctx);
 
 /*******************/
 /* Beacon Handling */
@@ -458,6 +583,7 @@ void ath9k_csa_update(struct ath_softc *
 #define ATH_PAPRD_TIMEOUT         100 /* msecs */
 #define ATH_PLL_WORK_INTERVAL     100
 
+void ath_chanctx_work(struct work_struct *work);
 void ath_tx_complete_poll_work(struct work_struct *work);
 void ath_reset_work(struct work_struct *work);
 bool ath_hw_check(struct ath_softc *sc);
@@ -473,6 +599,7 @@ void ath9k_queue_reset(struct ath_softc
 void ath_ps_full_sleep(unsigned long data);
 void ath9k_p2p_ps_timer(void *priv);
 void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif);
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
 
 /**********/
 /* BTCOEX */
@@ -702,6 +829,8 @@ void ath_ant_comb_scan(struct ath_softc
 #define PS_BEACON_SYNC            BIT(4)
 #define PS_WAIT_FOR_ANI           BIT(5)
 
+#define ATH9K_NUM_CHANCTX  2 /* supports 2 operating channels */
+
 struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
@@ -720,6 +849,7 @@ struct ath_softc {
 	struct mutex mutex;
 	struct work_struct paprd_work;
 	struct work_struct hw_reset_work;
+	struct work_struct chanctx_work;
 	struct completion paprd_complete;
 	wait_queue_head_t tx_wait;
 
@@ -738,23 +868,27 @@ struct ath_softc {
 	short nvifs;
 	unsigned long ps_usecount;
 
-	struct ath_config config;
 	struct ath_rx rx;
 	struct ath_tx tx;
 	struct ath_beacon beacon;
 
+	struct cfg80211_chan_def cur_chandef;
+	struct ath_chanctx chanctx[ATH9K_NUM_CHANCTX];
+	struct ath_chanctx *cur_chan;
+	struct ath_chanctx *next_chan;
+	spinlock_t chan_lock;
+	struct ath_offchannel offchannel;
+	struct ath_chanctx_sched sched;
+
 #ifdef CONFIG_MAC80211_LEDS
 	bool led_registered;
 	char led_name[32];
 	struct led_classdev led_cdev;
 #endif
 
-	struct ath9k_hw_cal_data caldata;
-
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
 #endif
-	struct ath_beacon_config cur_beacon_conf;
 	struct delayed_work tx_complete_work;
 	struct delayed_work hw_pll_work;
 	struct timer_list sleep_timer;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/beacon.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/beacon.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,7 +80,7 @@ static void ath9k_beacon_setup(struct at
 	u8 chainmask = ah->txchainmask;
 	u8 rate = 0;
 
-	sband = &common->sbands[common->hw->conf.chandef.chan->band];
+	sband = &common->sbands[sc->cur_chandef.chan->band];
 	rate = sband->bitrates[rateidx].hw_value;
 	if (vif->bss_conf.use_short_preamble)
 		rate |= sband->bitrates[rateidx].hw_value_short;
@@ -108,6 +108,55 @@ static void ath9k_beacon_setup(struct at
 	ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
 }
 
+static void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
+				 struct sk_buff *skb)
+{
+	static const u8 noa_ie_hdr[] = {
+		WLAN_EID_VENDOR_SPECIFIC,	/* type */
+		0,				/* length */
+		0x50, 0x6f, 0x9a,		/* WFA OUI */
+		0x09,				/* P2P subtype */
+		0x0c,				/* Notice of Absence */
+		0x00,				/* LSB of little-endian len */
+		0x00,				/* MSB of little-endian len */
+	};
+
+	struct ieee80211_p2p_noa_attr *noa;
+	int noa_len, noa_desc, i = 0;
+	u8 *hdr;
+
+	if (!avp->offchannel_duration && !avp->periodic_noa_duration)
+		return;
+
+	noa_desc = !!avp->offchannel_duration + !!avp->periodic_noa_duration;
+	noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc) * noa_desc;
+
+	hdr = skb_put(skb, sizeof(noa_ie_hdr));
+	memcpy(hdr, noa_ie_hdr, sizeof(noa_ie_hdr));
+	hdr[1] = sizeof(noa_ie_hdr) + noa_len - 2;
+	hdr[7] = noa_len;
+
+	noa = (void *) skb_put(skb, noa_len);
+	memset(noa, 0, noa_len);
+
+	noa->index = avp->noa_index;
+	if (avp->periodic_noa_duration) {
+		u32 interval = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+
+		noa->desc[i].count = 255;
+		noa->desc[i].start_time = cpu_to_le32(avp->periodic_noa_start);
+		noa->desc[i].duration = cpu_to_le32(avp->periodic_noa_duration);
+		noa->desc[i].interval = cpu_to_le32(interval);
+		i++;
+	}
+
+	if (avp->offchannel_duration) {
+		noa->desc[i].count = 1;
+		noa->desc[i].start_time = cpu_to_le32(avp->offchannel_start);
+		noa->desc[i].duration = cpu_to_le32(avp->offchannel_duration);
+	}
+}
+
 static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
 					     struct ieee80211_vif *vif)
 {
@@ -155,6 +204,9 @@ static struct ath_buf *ath9k_beacon_gene
 		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
 	}
 
+	if (vif->p2p)
+		ath9k_beacon_add_noa(sc, avp, skb);
+
 	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
 					 skb->len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
@@ -249,7 +301,7 @@ void ath9k_beacon_remove_slot(struct ath
 static int ath9k_beacon_choose_slot(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 	u16 intval;
 	u32 tsftu;
 	u64 tsf;
@@ -277,8 +329,8 @@ static int ath9k_beacon_choose_slot(stru
 static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	struct ath_vif *avp = (void *)vif->drv_priv;
+	struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
 	u32 tsfadjust;
 
 	if (avp->av_bslot == 0)
@@ -374,12 +426,19 @@ void ath9k_beacon_tasklet(unsigned long
 	vif = sc->beacon.bslot[slot];
 
 	/* EDMA devices check that in the tx completion function. */
-	if (!edma && ath9k_csa_is_finished(sc, vif))
-		return;
+	if (!edma) {
+		if (sc->sched.beacon_pending)
+			ath_chanctx_event(sc, NULL,
+					  ATH_CHANCTX_EVENT_BEACON_SENT);
+
+		if (ath9k_csa_is_finished(sc, vif))
+			return;
+	}
 
 	if (!vif || !vif->bss_conf.enable_beacon)
 		return;
 
+	ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_BEACON_PREPARE);
 	bf = ath9k_beacon_generate(sc->hw, vif);
 
 	if (sc->beacon.bmisscnt != 0) {
@@ -500,7 +559,6 @@ static bool ath9k_allow_beacon_config(st
 				      struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_vif *avp = (void *)vif->drv_priv;
 
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
 		if ((vif->type != NL80211_IFTYPE_AP) ||
@@ -514,7 +572,7 @@ static bool ath9k_allow_beacon_config(st
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
 		if ((vif->type == NL80211_IFTYPE_STATION) &&
 		    test_bit(ATH_OP_BEACONS, &common->op_flags) &&
-		    !avp->primary_sta_vif) {
+		    vif != sc->cur_chan->primary_sta) {
 			ath_dbg(common, CONFIG,
 				"Beacon already configured for a station interface\n");
 			return false;
@@ -525,10 +583,11 @@ static bool ath9k_allow_beacon_config(st
 }
 
 static void ath9k_cache_beacon_config(struct ath_softc *sc,
+				      struct ath_chanctx *ctx,
 				      struct ieee80211_bss_conf *bss_conf)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	struct ath_beacon_config *cur_conf = &ctx->beacon;
 
 	ath_dbg(common, BEACON,
 		"Caching beacon data for BSS: %pM\n", bss_conf->bssid);
@@ -564,20 +623,29 @@ void ath9k_beacon_config(struct ath_soft
 			 u32 changed)
 {
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
         struct ath_hw *ah = sc->sc_ah;
         struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_vif *avp = (void *)vif->drv_priv;
+	struct ath_chanctx *ctx = avp->chanctx;
+	struct ath_beacon_config *cur_conf;
 	unsigned long flags;
 	bool skip_beacon = false;
 
+	if (!ctx)
+		return;
+
+	cur_conf = &avp->chanctx->beacon;
 	if (vif->type == NL80211_IFTYPE_AP)
 		ath9k_set_tsfadjust(sc, vif);
 
 	if (!ath9k_allow_beacon_config(sc, vif))
 		return;
 
-	if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
-		ath9k_cache_beacon_config(sc, bss_conf);
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		ath9k_cache_beacon_config(sc, ctx, bss_conf);
+		if (ctx != sc->cur_chan)
+			return;
+
 		ath9k_set_beacon(sc);
 		set_bit(ATH_OP_BEACONS, &common->op_flags);
 		return;
@@ -593,10 +661,13 @@ void ath9k_beacon_config(struct ath_soft
 			cur_conf->enable_beacon = false;
 		} else if (bss_conf->enable_beacon) {
 			cur_conf->enable_beacon = true;
-			ath9k_cache_beacon_config(sc, bss_conf);
+			ath9k_cache_beacon_config(sc, ctx, bss_conf);
 		}
 	}
 
+	if (ctx != sc->cur_chan)
+		return;
+
 	/*
 	 * Configure the HW beacon registers only when we have a valid
 	 * beacon interval.
@@ -631,7 +702,7 @@ void ath9k_beacon_config(struct ath_soft
 void ath9k_set_beacon(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 
 	switch (sc->sc_ah->opmode) {
 	case NL80211_IFTYPE_AP:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/channel.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/channel.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/channel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/channel.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+/* Set/change channels.  If the channel is really being changed, it's done
+ * by reseting the chip.  To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+ */
+static int ath_set_channel(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_hw *hw = sc->hw;
+	struct ath9k_channel *hchan;
+	struct cfg80211_chan_def *chandef = &sc->cur_chan->chandef;
+	struct ieee80211_channel *chan = chandef->chan;
+	int pos = chan->hw_value;
+	int old_pos = -1;
+	int r;
+
+	if (test_bit(ATH_OP_INVALID, &common->op_flags))
+		return -EIO;
+
+	if (ah->curchan)
+		old_pos = ah->curchan - &ah->channels[0];
+
+	ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
+		chan->center_freq, chandef->width);
+
+	/* update survey stats for the old channel before switching */
+	spin_lock_bh(&common->cc_lock);
+	ath_update_survey_stats(sc);
+	spin_unlock_bh(&common->cc_lock);
+
+	ath9k_cmn_get_channel(hw, ah, chandef);
+
+	/* If the operating channel changes, change the survey in-use flags
+	 * along with it.
+	 * Reset the survey data for the new channel, unless we're switching
+	 * back to the operating channel from an off-channel operation.
+	 */
+	if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) {
+		if (sc->cur_survey)
+			sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+		sc->cur_survey = &sc->survey[pos];
+
+		memset(sc->cur_survey, 0, sizeof(struct survey_info));
+		sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+	} else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+		memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+	}
+
+	hchan = &sc->sc_ah->channels[pos];
+	r = ath_reset_internal(sc, hchan);
+	if (r)
+		return r;
+
+	/* The most recent snapshot of channel->noisefloor for the old
+	 * channel is only available after the hardware reset. Copy it to
+	 * the survey stats now.
+	 */
+	if (old_pos >= 0)
+		ath_update_survey_nf(sc, old_pos);
+
+	/* Enable radar pulse detection if on a DFS channel. Spectral
+	 * scanning and radar detection can not be used concurrently.
+	 */
+	if (hw->conf.radar_enabled) {
+		u32 rxfilter;
+
+		/* set HW specific DFS configuration */
+		ath9k_hw_set_radar_params(ah);
+		rxfilter = ath9k_hw_getrxfilter(ah);
+		rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
+				ATH9K_RX_FILTER_PHYERR;
+		ath9k_hw_setrxfilter(ah, rxfilter);
+		ath_dbg(common, DFS, "DFS enabled at freq %d\n",
+			chan->center_freq);
+	} else {
+		/* perform spectral scan if requested. */
+		if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
+			sc->spectral_mode == SPECTRAL_CHANSCAN)
+			ath9k_spectral_scan_trigger(hw);
+	}
+
+	return 0;
+}
+
+static bool
+ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
+			      bool powersave)
+{
+	struct ieee80211_vif *vif = avp->vif;
+	struct ieee80211_sta *sta = NULL;
+	struct ieee80211_hdr_3addr *nullfunc;
+	struct ath_tx_control txctl;
+	struct sk_buff *skb;
+	int band = sc->cur_chan->chandef.chan->band;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		if (!vif->bss_conf.assoc)
+			return false;
+
+		skb = ieee80211_nullfunc_get(sc->hw, vif);
+		if (!skb)
+			return false;
+
+		nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
+		if (powersave)
+			nullfunc->frame_control |=
+				cpu_to_le16(IEEE80211_FCTL_PM);
+
+		skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+		if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
+			dev_kfree_skb_any(skb);
+			return false;
+		}
+		break;
+	default:
+		return false;
+	}
+
+	memset(&txctl, 0, sizeof(txctl));
+	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
+	txctl.sta = sta;
+	txctl.force_channel = true;
+	if (ath_tx_start(sc->hw, skb, &txctl)) {
+		ieee80211_free_txskb(sc->hw, skb);
+		return false;
+	}
+
+	return true;
+}
+
+void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
+{
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_vif *avp;
+	bool active = false;
+	u8 n_active = 0;
+
+	if (!ctx)
+		return;
+
+	list_for_each_entry(avp, &ctx->vifs, list) {
+		struct ieee80211_vif *vif = avp->vif;
+
+		switch (vif->type) {
+		case NL80211_IFTYPE_P2P_CLIENT:
+		case NL80211_IFTYPE_STATION:
+			if (vif->bss_conf.assoc)
+				active = true;
+			break;
+		default:
+			active = true;
+			break;
+		}
+	}
+	ctx->active = active;
+
+	ath_for_each_chanctx(sc, ctx) {
+		if (!ctx->assigned || list_empty(&ctx->vifs))
+			continue;
+		n_active++;
+	}
+
+	if (n_active <= 1) {
+		clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
+		return;
+	}
+	if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
+		return;
+	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL);
+}
+
+static bool
+ath_chanctx_send_ps_frame(struct ath_softc *sc, bool powersave)
+{
+	struct ath_vif *avp;
+	bool sent = false;
+
+	rcu_read_lock();
+	list_for_each_entry(avp, &sc->cur_chan->vifs, list) {
+		if (ath_chanctx_send_vif_ps_frame(sc, avp, powersave))
+			sent = true;
+	}
+	rcu_read_unlock();
+
+	return sent;
+}
+
+static bool ath_chanctx_defer_switch(struct ath_softc *sc)
+{
+	if (sc->cur_chan == &sc->offchannel.chan)
+		return false;
+
+	switch (sc->sched.state) {
+	case ATH_CHANCTX_STATE_SWITCH:
+		return false;
+	case ATH_CHANCTX_STATE_IDLE:
+		if (!sc->cur_chan->switch_after_beacon)
+			return false;
+
+		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static void ath_chanctx_set_next(struct ath_softc *sc, bool force)
+{
+	struct timespec ts;
+	bool measure_time = false;
+	bool send_ps = false;
+
+	spin_lock_bh(&sc->chan_lock);
+	if (!sc->next_chan) {
+		spin_unlock_bh(&sc->chan_lock);
+		return;
+	}
+
+	if (!force && ath_chanctx_defer_switch(sc)) {
+		spin_unlock_bh(&sc->chan_lock);
+		return;
+	}
+
+	if (sc->cur_chan != sc->next_chan) {
+		sc->cur_chan->stopped = true;
+		spin_unlock_bh(&sc->chan_lock);
+
+		if (sc->next_chan == &sc->offchannel.chan) {
+			getrawmonotonic(&ts);
+			measure_time = true;
+		}
+		__ath9k_flush(sc->hw, ~0, true);
+
+		if (ath_chanctx_send_ps_frame(sc, true))
+			__ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
+
+		send_ps = true;
+		spin_lock_bh(&sc->chan_lock);
+
+		if (sc->cur_chan != &sc->offchannel.chan) {
+			getrawmonotonic(&sc->cur_chan->tsf_ts);
+			sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
+		}
+	}
+	sc->cur_chan = sc->next_chan;
+	sc->cur_chan->stopped = false;
+	sc->next_chan = NULL;
+	sc->sched.offchannel_duration = 0;
+	if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE)
+		sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+
+	spin_unlock_bh(&sc->chan_lock);
+
+	if (sc->sc_ah->chip_fullsleep ||
+	    memcmp(&sc->cur_chandef, &sc->cur_chan->chandef,
+		   sizeof(sc->cur_chandef))) {
+		ath_set_channel(sc);
+		if (measure_time)
+			sc->sched.channel_switch_time =
+				ath9k_hw_get_tsf_offset(&ts, NULL);
+	}
+	if (send_ps)
+		ath_chanctx_send_ps_frame(sc, false);
+
+	ath_offchannel_channel_change(sc);
+	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_SWITCH);
+}
+
+void ath_chanctx_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc,
+					    chanctx_work);
+	mutex_lock(&sc->mutex);
+	ath_chanctx_set_next(sc, false);
+	mutex_unlock(&sc->mutex);
+}
+
+void ath_chanctx_init(struct ath_softc *sc)
+{
+	struct ath_chanctx *ctx;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *chan;
+	int i, j;
+
+	sband = &common->sbands[IEEE80211_BAND_2GHZ];
+	if (!sband->n_channels)
+		sband = &common->sbands[IEEE80211_BAND_5GHZ];
+
+	chan = &sband->channels[0];
+	for (i = 0; i < ATH9K_NUM_CHANCTX; i++) {
+		ctx = &sc->chanctx[i];
+		cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
+		INIT_LIST_HEAD(&ctx->vifs);
+		ctx->txpower = ATH_TXPOWER_MAX;
+		for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
+			INIT_LIST_HEAD(&ctx->acq[j]);
+	}
+	ctx = &sc->offchannel.chan;
+	cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
+	INIT_LIST_HEAD(&ctx->vifs);
+	ctx->txpower = ATH_TXPOWER_MAX;
+	for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
+		INIT_LIST_HEAD(&ctx->acq[j]);
+	sc->offchannel.chan.offchannel = true;
+
+}
+
+void ath9k_chanctx_force_active(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
+	bool changed = false;
+
+	if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
+		return;
+
+	if (!avp->chanctx)
+		return;
+
+	mutex_lock(&sc->mutex);
+
+	spin_lock_bh(&sc->chan_lock);
+	if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
+		sc->next_chan = avp->chanctx;
+		changed = true;
+	}
+	sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
+	spin_unlock_bh(&sc->chan_lock);
+
+	if (changed)
+		ath_chanctx_set_next(sc, true);
+
+	mutex_unlock(&sc->mutex);
+}
+
+void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
+			struct cfg80211_chan_def *chandef)
+{
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+	spin_lock_bh(&sc->chan_lock);
+
+	if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
+	    (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
+		sc->sched.offchannel_pending = true;
+		spin_unlock_bh(&sc->chan_lock);
+		return;
+	}
+
+	sc->next_chan = ctx;
+	if (chandef)
+		ctx->chandef = *chandef;
+
+	if (sc->next_chan == &sc->offchannel.chan) {
+		sc->sched.offchannel_duration =
+			TU_TO_USEC(sc->offchannel.duration) +
+			sc->sched.channel_switch_time;
+	}
+	spin_unlock_bh(&sc->chan_lock);
+	ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+}
+
+void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
+			     struct cfg80211_chan_def *chandef)
+{
+	bool cur_chan;
+
+	spin_lock_bh(&sc->chan_lock);
+	if (chandef)
+		memcpy(&ctx->chandef, chandef, sizeof(*chandef));
+	cur_chan = sc->cur_chan == ctx;
+	spin_unlock_bh(&sc->chan_lock);
+
+	if (!cur_chan)
+		return;
+
+	ath_set_channel(sc);
+}
+
+struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc, bool active)
+{
+	struct ath_chanctx *ctx;
+
+	ath_for_each_chanctx(sc, ctx) {
+		if (!ctx->assigned || list_empty(&ctx->vifs))
+			continue;
+		if (active && !ctx->active)
+			continue;
+
+		if (ctx->switch_after_beacon)
+			return ctx;
+	}
+
+	return &sc->chanctx[0];
+}
+
+void ath_chanctx_offchan_switch(struct ath_softc *sc,
+				struct ieee80211_channel *chan)
+{
+	struct cfg80211_chan_def chandef;
+
+	cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+
+	ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef);
+}
+
+static struct ath_chanctx *
+ath_chanctx_get_next(struct ath_softc *sc, struct ath_chanctx *ctx)
+{
+	int idx = ctx - &sc->chanctx[0];
+
+	return &sc->chanctx[!idx];
+}
+
+static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
+{
+	struct ath_chanctx *prev, *cur;
+	struct timespec ts;
+	u32 cur_tsf, prev_tsf, beacon_int;
+	s32 offset;
+
+	beacon_int = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+
+	cur = sc->cur_chan;
+	prev = ath_chanctx_get_next(sc, cur);
+
+	getrawmonotonic(&ts);
+	cur_tsf = (u32) cur->tsf_val +
+		  ath9k_hw_get_tsf_offset(&cur->tsf_ts, &ts);
+
+	prev_tsf = prev->last_beacon - (u32) prev->tsf_val + cur_tsf;
+	prev_tsf -= ath9k_hw_get_tsf_offset(&prev->tsf_ts, &ts);
+
+	/* Adjust the TSF time of the AP chanctx to keep its beacons
+	 * at half beacon interval offset relative to the STA chanctx.
+	 */
+	offset = cur_tsf - prev_tsf;
+
+	/* Ignore stale data or spurious timestamps */
+	if (offset < 0 || offset > 3 * beacon_int)
+		return;
+
+	offset = beacon_int / 2 - (offset % beacon_int);
+	prev->tsf_val += offset;
+}
+
+void ath_chanctx_timer(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *) data;
+
+	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
+}
+
+/* Configure the TSF based hardware timer for a channel switch.
+ * Also set up backup software timer, in case the gen timer fails.
+ * This could be caused by a hardware reset.
+ */
+static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
+{
+	struct ath_hw *ah = sc->sc_ah;
+
+	ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
+	tsf_time -= ath9k_hw_gettsf32(ah);
+	tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
+	mod_timer(&sc->sched.timer, tsf_time);
+}
+
+void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
+		       enum ath_chanctx_event ev)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_beacon_config *cur_conf;
+	struct ath_vif *avp = NULL;
+	struct ath_chanctx *ctx;
+	u32 tsf_time;
+	u32 beacon_int;
+	bool noa_changed = false;
+
+	if (vif)
+		avp = (struct ath_vif *) vif->drv_priv;
+
+	spin_lock_bh(&sc->chan_lock);
+
+	switch (ev) {
+	case ATH_CHANCTX_EVENT_BEACON_PREPARE:
+		if (avp->offchannel_duration)
+			avp->offchannel_duration = 0;
+
+		if (avp->chanctx != sc->cur_chan)
+			break;
+
+		if (sc->sched.offchannel_pending) {
+			sc->sched.offchannel_pending = false;
+			sc->next_chan = &sc->offchannel.chan;
+			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+		}
+
+		ctx = ath_chanctx_get_next(sc, sc->cur_chan);
+		if (ctx->active && sc->sched.state == ATH_CHANCTX_STATE_IDLE) {
+			sc->next_chan = ctx;
+			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+		}
+
+		/* if the timer missed its window, use the next interval */
+		if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
+			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+
+		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
+			break;
+
+		sc->sched.beacon_pending = true;
+		sc->sched.next_tbtt = REG_READ(ah, AR_NEXT_TBTT_TIMER);
+
+		cur_conf = &sc->cur_chan->beacon;
+		beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
+
+		/* defer channel switch by a quarter beacon interval */
+		tsf_time = sc->sched.next_tbtt + beacon_int / 4;
+		sc->sched.switch_start_time = tsf_time;
+		sc->cur_chan->last_beacon = sc->sched.next_tbtt;
+
+		/* Prevent wrap-around issues */
+		if (avp->periodic_noa_duration &&
+		    tsf_time - avp->periodic_noa_start > BIT(30))
+			avp->periodic_noa_duration = 0;
+
+		if (ctx->active && !avp->periodic_noa_duration) {
+			avp->periodic_noa_start = tsf_time;
+			avp->periodic_noa_duration =
+				TU_TO_USEC(cur_conf->beacon_interval) / 2 -
+				sc->sched.channel_switch_time;
+			noa_changed = true;
+		} else if (!ctx->active && avp->periodic_noa_duration) {
+			avp->periodic_noa_duration = 0;
+			noa_changed = true;
+		}
+
+		/* If at least two consecutive beacons were missed on the STA
+		 * chanctx, stay on the STA channel for one extra beacon period,
+		 * to resync the timer properly.
+		 */
+		if (ctx->active && sc->sched.beacon_miss >= 2)
+			sc->sched.offchannel_duration = 3 * beacon_int / 2;
+
+		if (sc->sched.offchannel_duration) {
+			noa_changed = true;
+			avp->offchannel_start = tsf_time;
+			avp->offchannel_duration =
+				sc->sched.offchannel_duration;
+		}
+
+		if (noa_changed)
+			avp->noa_index++;
+		break;
+	case ATH_CHANCTX_EVENT_BEACON_SENT:
+		if (!sc->sched.beacon_pending)
+			break;
+
+		sc->sched.beacon_pending = false;
+		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
+			break;
+
+		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
+		ath_chanctx_setup_timer(sc, sc->sched.switch_start_time);
+		break;
+	case ATH_CHANCTX_EVENT_TSF_TIMER:
+		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
+			break;
+
+		if (!sc->cur_chan->switch_after_beacon &&
+		    sc->sched.beacon_pending)
+			sc->sched.beacon_miss++;
+
+		sc->sched.state = ATH_CHANCTX_STATE_SWITCH;
+		ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+		break;
+	case ATH_CHANCTX_EVENT_BEACON_RECEIVED:
+		if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
+		    sc->cur_chan == &sc->offchannel.chan)
+			break;
+
+		ath_chanctx_adjust_tbtt_delta(sc);
+		sc->sched.beacon_pending = false;
+		sc->sched.beacon_miss = 0;
+
+		/* TSF time might have been updated by the incoming beacon,
+		 * need update the channel switch timer to reflect the change.
+		 */
+		tsf_time = sc->sched.switch_start_time;
+		tsf_time -= (u32) sc->cur_chan->tsf_val +
+			ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
+		tsf_time += ath9k_hw_gettsf32(ah);
+
+
+		ath_chanctx_setup_timer(sc, tsf_time);
+		break;
+	case ATH_CHANCTX_EVENT_ASSOC:
+		if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
+		    avp->chanctx != sc->cur_chan)
+			break;
+
+		sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+		/* fall through */
+	case ATH_CHANCTX_EVENT_SWITCH:
+		if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
+		    sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
+		    sc->cur_chan->switch_after_beacon ||
+		    sc->cur_chan == &sc->offchannel.chan)
+			break;
+
+		/* If this is a station chanctx, stay active for a half
+		 * beacon period (minus channel switch time)
+		 */
+		sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
+		cur_conf = &sc->cur_chan->beacon;
+
+		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
+
+		tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
+		if (sc->sched.beacon_miss >= 2) {
+			sc->sched.beacon_miss = 0;
+			tsf_time *= 3;
+		}
+
+		tsf_time -= sc->sched.channel_switch_time;
+		tsf_time += ath9k_hw_gettsf32(sc->sc_ah);
+		sc->sched.switch_start_time = tsf_time;
+
+		ath_chanctx_setup_timer(sc, tsf_time);
+		sc->sched.beacon_pending = true;
+		break;
+	case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
+		if (sc->cur_chan == &sc->offchannel.chan ||
+		    sc->cur_chan->switch_after_beacon)
+			break;
+
+		sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
+		ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+		break;
+	case ATH_CHANCTX_EVENT_UNASSIGN:
+		if (sc->cur_chan->assigned) {
+			if (sc->next_chan && !sc->next_chan->assigned &&
+			    sc->next_chan != &sc->offchannel.chan)
+				sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+			break;
+		}
+
+		ctx = ath_chanctx_get_next(sc, sc->cur_chan);
+		sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+		if (!ctx->assigned)
+			break;
+
+		sc->next_chan = ctx;
+		ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+		break;
+	}
+
+	spin_unlock_bh(&sc->chan_lock);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/common-beacon.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/common-beacon.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/common-beacon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/common-beacon.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,7 +112,7 @@ int ath9k_cmn_beacon_config_sta(struct a
 	 */
 
 	bs->bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
-						 conf->intval));
+						  conf->intval));
 	if (bs->bs_sleepduration > bs->bs_dtimperiod)
 		bs->bs_sleepduration = bs->bs_dtimperiod;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/debug.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/debug.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct fil
 	if (kstrtoul(buf, 0, &ani))
 		return -EINVAL;
 
-	if (ani < 0 || ani > 1)
+	if (ani > 1)
 		return -EINVAL;
 
 	common->disable_ani = !ani;
@@ -750,13 +750,13 @@ static ssize_t read_file_misc(struct fil
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ieee80211_hw *hw = sc->hw;
 	struct ath9k_vif_iter_data iter_data;
+	struct ath_chanctx *ctx;
 	char buf[512];
 	unsigned int len = 0;
 	ssize_t retval = 0;
 	unsigned int reg;
-	u32 rxfilter;
+	u32 rxfilter, i;
 
 	len += scnprintf(buf + len, sizeof(buf) - len,
 			 "BSSID: %pM\n", common->curbssid);
@@ -826,14 +826,20 @@ static ssize_t read_file_misc(struct fil
 
 	len += scnprintf(buf + len, sizeof(buf) - len, "\n");
 
-	ath9k_calculate_iter_data(hw, NULL, &iter_data);
+	i = 0;
+	ath_for_each_chanctx(sc, ctx) {
+		if (!ctx->assigned || list_empty(&ctx->vifs))
+			continue;
+		ath9k_calculate_iter_data(sc, ctx, &iter_data);
 
-	len += scnprintf(buf + len, sizeof(buf) - len,
-			 "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
-			 " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
-			 iter_data.naps, iter_data.nstations, iter_data.nmeshes,
-			 iter_data.nwds, iter_data.nadhocs,
-			 sc->nvifs, sc->nbcnvifs);
+		len += scnprintf(buf + len, sizeof(buf) - len,
+			"VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i",
+			i++, iter_data.naps, iter_data.nstations,
+			iter_data.nmeshes, iter_data.nwds);
+		len += scnprintf(buf + len, sizeof(buf) - len,
+			" ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+			iter_data.nadhocs, sc->nvifs, sc->nbcnvifs);
+	}
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -1080,7 +1086,7 @@ static ssize_t read_file_dump_nfcal(stru
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_hw *ah = sc->sc_ah;
-	struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+	struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
 	u32 len = 0, size = 1500;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -978,7 +978,7 @@ static bool ath9k_rx_prepare(struct ath9
 	struct ath_hw *ah = common->ah;
 	struct ath_htc_rx_status *rxstatus;
 	struct ath_rx_status rx_stats;
-	bool decrypt_error;
+	bool decrypt_error = false;
 
 	if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
 		ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -791,7 +791,8 @@ static void ath9k_hw_init_pll(struct ath
 				refdiv = 5;
 			} else {
 				pll2_divint = 0x11;
-				pll2_divfrac = 0x26666;
+				pll2_divfrac =
+					AR_SREV_9531(ah) ? 0x26665 : 0x26666;
 				refdiv = 1;
 			}
 		}
@@ -1730,11 +1731,27 @@ fail:
 	return -EINVAL;
 }
 
+u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur)
+{
+	struct timespec ts;
+	s64 usec;
+
+	if (!cur) {
+		getrawmonotonic(&ts);
+		cur = &ts;
+	}
+
+	usec = cur->tv_sec * 1000000ULL + cur->tv_nsec / 1000;
+	usec -= last->tv_sec * 1000000ULL + last->tv_nsec / 1000;
+
+	return (u32) usec;
+}
+EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 		   struct ath9k_hw_cal_data *caldata, bool fastcc)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
-	struct timespec ts;
 	u32 saveLedState;
 	u32 saveDefAntenna;
 	u32 macStaId1;
@@ -1784,8 +1801,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 
 	/* Save TSF before chip reset, a cold reset clears it */
 	tsf = ath9k_hw_gettsf64(ah);
-	getrawmonotonic(&ts);
-	usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
+	usec = ktime_to_us(ktime_get_raw());
 
 	saveLedState = REG_READ(ah, AR_CFG_LED) &
 		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1818,8 +1834,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	}
 
 	/* Restore TSF */
-	getrawmonotonic(&ts);
-	usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec;
+	usec = ktime_to_us(ktime_get_raw()) - usec;
 	ath9k_hw_settsf64(ah, tsf + usec);
 
 	if (AR_SREV_9280_20_OR_LATER(ah))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/hw.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/hw.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -1000,6 +1000,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 u64 ath9k_hw_gettsf64(struct ath_hw *ah);
 void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
 void ath9k_hw_reset_tsf(struct ath_hw *ah);
+u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur);
 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
 void ath9k_hw_init_global_settings(struct ath_hw *ah);
 u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/init.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/init.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,7 +61,7 @@ static int ath9k_ps_enable;
 module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
 MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
 
-static int ath9k_use_chanctx;
+int ath9k_use_chanctx;
 module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444);
 MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency");
 
@@ -169,9 +169,9 @@ static void ath9k_reg_notifier(struct wi
 
 	/* Set tx power */
 	if (ah->curchan) {
-		sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
+		sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
 		ath9k_ps_wakeup(sc);
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+		ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
 		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 		/* synchronize DFS detector if regulatory domain changed */
 		if (sc->dfs_detector != NULL)
@@ -335,7 +335,6 @@ static void ath9k_init_misc(struct ath_s
 	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
-	sc->config.txpowlimit = ATH_TXPOWER_MAX;
 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
 
@@ -511,6 +510,9 @@ static int ath9k_init_softc(u16 devid, s
 	sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
 	sc->tx99_power = MAX_RATE_POWER + 1;
 	init_waitqueue_head(&sc->tx_wait);
+	sc->cur_chan = &sc->chanctx[0];
+	if (!ath9k_use_chanctx)
+		sc->cur_chan->hw_queue_base = 0;
 
 	if (!pdata || pdata->use_eeprom) {
 		ah->ah_flags |= AH_USE_EEPROM;
@@ -556,6 +558,7 @@ static int ath9k_init_softc(u16 devid, s
 	spin_lock_init(&common->cc_lock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
+	spin_lock_init(&sc->chan_lock);
 	mutex_init(&sc->mutex);
 	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
 	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
@@ -564,7 +567,11 @@ static int ath9k_init_softc(u16 devid, s
 	setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);
 	INIT_WORK(&sc->hw_reset_work, ath_reset_work);
 	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+	INIT_WORK(&sc->chanctx_work, ath_chanctx_work);
 	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+	setup_timer(&sc->offchannel.timer, ath_offchannel_timer,
+		    (unsigned long)sc);
+	setup_timer(&sc->sched.timer, ath_chanctx_timer, (unsigned long)sc);
 
 	/*
 	 * Cache line size is used to size and align various
@@ -599,6 +606,7 @@ static int ath9k_init_softc(u16 devid, s
 	ath9k_cmn_init_crypto(sc->sc_ah);
 	ath9k_init_misc(sc);
 	ath_fill_led_pin(sc);
+	ath_chanctx_init(sc);
 
 	if (common->bus_ops->aspm_init)
 		common->bus_ops->aspm_init(common);
@@ -664,6 +672,12 @@ static const struct ieee80211_iface_limi
 	{ .max = 2048,	.types = BIT(NL80211_IFTYPE_WDS) },
 };
 
+static const struct ieee80211_iface_limit if_limits_multi[] = {
+	{ .max = 1,	.types = BIT(NL80211_IFTYPE_STATION) },
+	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+				 BIT(NL80211_IFTYPE_P2P_GO) },
+};
+
 static const struct ieee80211_iface_limit if_dfs_limits[] = {
 	{ .max = 1,	.types = BIT(NL80211_IFTYPE_AP) |
 #ifdef CONFIG_MAC80211_MESH
@@ -672,6 +686,16 @@ static const struct ieee80211_iface_limi
 				 BIT(NL80211_IFTYPE_ADHOC) },
 };
 
+static const struct ieee80211_iface_combination if_comb_multi[] = {
+	{
+		.limits = if_limits_multi,
+		.n_limits = ARRAY_SIZE(if_limits_multi),
+		.max_interfaces = 2,
+		.num_different_channels = 2,
+		.beacon_int_infra_match = true,
+	},
+};
+
 static const struct ieee80211_iface_combination if_comb[] = {
 	{
 		.limits = if_limits,
@@ -712,6 +736,7 @@ static void ath9k_set_hw_capab(struct at
 		IEEE80211_HW_SPECTRUM_MGMT |
 		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
 		IEEE80211_HW_SUPPORTS_RC_TABLE |
+		IEEE80211_HW_QUEUE_CONTROL |
 		IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
 	if (ath9k_ps_enable)
@@ -739,12 +764,21 @@ static void ath9k_set_hw_capab(struct at
 			BIT(NL80211_IFTYPE_STATION) |
 			BIT(NL80211_IFTYPE_ADHOC) |
 			BIT(NL80211_IFTYPE_MESH_POINT);
-		hw->wiphy->iface_combinations = if_comb;
 		if (!ath9k_use_chanctx) {
+			hw->wiphy->iface_combinations = if_comb;
 			hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
 			hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS);
-		} else
-			hw->wiphy->n_iface_combinations = 1;
+		} else {
+			hw->wiphy->iface_combinations = if_comb_multi;
+			hw->wiphy->n_iface_combinations =
+				ARRAY_SIZE(if_comb_multi);
+			hw->wiphy->max_scan_ssids = 255;
+			hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+			hw->wiphy->max_remain_on_channel_duration = 10000;
+			hw->chanctx_data_size = sizeof(void *);
+			hw->extra_beacon_tailroom =
+				sizeof(struct ieee80211_p2p_noa_attr) + 9;
+		}
 	}
 
 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -756,9 +790,14 @@ static void ath9k_set_hw_capab(struct at
 	hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 
-	hw->queues = 4;
+	/* allow 4 queues per channel context +
+	 * 1 cab queue + 1 offchannel tx queue
+	 */
+	hw->queues = 10;
+	/* last queue for offchannel */
+	hw->offchannel_tx_hw_queue = hw->queues - 1;
 	hw->max_rates = 4;
-	hw->max_listen_interval = 1;
+	hw->max_listen_interval = 10;
 	hw->max_rate_tries = 10;
 	hw->sta_data_size = sizeof(struct ath_node);
 	hw->vif_data_size = sizeof(struct ath_vif);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/link.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/link.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/link.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/link.c	2014-09-28 17:29:07.000000000 -0400
@@ -178,7 +178,7 @@ static bool ath_paprd_send_frame(struct
 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
 
 	memset(tx_info, 0, sizeof(*tx_info));
-	tx_info->band = hw->conf.chandef.chan->band;
+	tx_info->band = sc->cur_chandef.chan->band;
 	tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
 	tx_info->control.rates[0].idx = 0;
 	tx_info->control.rates[0].count = 1;
@@ -416,7 +416,7 @@ void ath_start_ani(struct ath_softc *sc)
 
 	if (common->disable_ani ||
 	    !test_bit(ATH_OP_ANI_RUN, &common->op_flags) ||
-	    (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+	    sc->cur_chan->offchannel)
 		return;
 
 	common->ani.longcal_timer = timestamp;
@@ -440,7 +440,7 @@ void ath_check_ani(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 
 	/*
 	 * Check for the various conditions in which ANI has to
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/mac.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/mac.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/mac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/mac.h	2014-09-28 17:29:07.000000000 -0400
@@ -346,8 +346,14 @@ struct ar5416_desc {
 #define AR_FrameLen         0x00000fff
 #define AR_VirtMoreFrag     0x00001000
 #define AR_TxCtlRsvd00      0x0000e000
-#define AR_XmitPower        0x003f0000
-#define AR_XmitPower_S      16
+#define AR_XmitPower0       0x003f0000
+#define AR_XmitPower0_S     16
+#define AR_XmitPower1	    0x3f000000
+#define AR_XmitPower1_S     24
+#define AR_XmitPower2	    0x3f000000
+#define AR_XmitPower2_S     24
+#define AR_XmitPower3	    0x3f000000
+#define AR_XmitPower3_S     24
 #define AR_RTSEnable        0x00400000
 #define AR_VEOL             0x00800000
 #define AR_ClrDestMask      0x01000000
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,9 +19,6 @@
 #include "ath9k.h"
 #include "btcoex.h"
 
-static void ath9k_set_assoc_state(struct ath_softc *sc,
-				  struct ieee80211_vif *vif);
-
 u8 ath9k_parse_mpdudensity(u8 mpdudensity)
 {
 	/*
@@ -63,9 +60,16 @@ static bool ath9k_has_pending_frames(str
 
 	spin_lock_bh(&txq->axq_lock);
 
-	if (txq->axq_depth || !list_empty(&txq->axq_acq))
+	if (txq->axq_depth)
 		pending = true;
 
+	if (txq->mac80211_qnum >= 0) {
+		struct list_head *list;
+
+		list = &sc->cur_chan->acq[txq->mac80211_qnum];
+		if (!list_empty(list))
+			pending = true;
+	}
 	spin_unlock_bh(&txq->axq_lock);
 	return pending;
 }
@@ -227,13 +231,22 @@ static bool ath_complete_reset(struct at
 	}
 
 	ath9k_cmn_update_txpow(ah, sc->curtxpow,
-			       sc->config.txpowlimit, &sc->curtxpow);
+			       sc->cur_chan->txpower, &sc->curtxpow);
 
 	clear_bit(ATH_OP_HW_RESET, &common->op_flags);
-	ath9k_hw_set_interrupts(ah);
-	ath9k_hw_enable_interrupts(ah);
+	ath9k_calculate_summary_state(sc, sc->cur_chan);
+
+	if (!sc->cur_chan->offchannel && start) {
+		/* restore per chanctx TSF timer */
+		if (sc->cur_chan->tsf_val) {
+			u32 offset;
+
+			offset = ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts,
+							 NULL);
+			ath9k_hw_settsf64(ah, sc->cur_chan->tsf_val + offset);
+		}
+
 
-	if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) {
 		if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
 			goto work;
 
@@ -247,26 +260,35 @@ static bool ath_complete_reset(struct at
 		}
 	work:
 		ath_restart_work(sc);
+		ath_txq_schedule_all(sc);
+	}
 
-		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-			if (!ATH_TXQ_SETUP(sc, i))
-				continue;
+	sc->gtt_cnt = 0;
 
-			spin_lock_bh(&sc->tx.txq[i].axq_lock);
-			ath_txq_schedule(sc, &sc->tx.txq[i]);
-			spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+	ath9k_hw_set_interrupts(ah);
+	ath9k_hw_enable_interrupts(ah);
+
+	if (!ath9k_use_chanctx)
+		ieee80211_wake_queues(sc->hw);
+	else {
+		if (sc->cur_chan == &sc->offchannel.chan)
+			ieee80211_wake_queue(sc->hw,
+					sc->hw->offchannel_tx_hw_queue);
+		else {
+			for (i = 0; i < IEEE80211_NUM_ACS; i++)
+				ieee80211_wake_queue(sc->hw,
+					sc->cur_chan->hw_queue_base + i);
 		}
+		if (ah->opmode == NL80211_IFTYPE_AP)
+			ieee80211_wake_queue(sc->hw, sc->hw->queues - 2);
 	}
 
-	sc->gtt_cnt = 0;
-	ieee80211_wake_queues(sc->hw);
-
 	ath9k_p2p_ps_timer(sc);
 
 	return true;
 }
 
-static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -279,9 +301,9 @@ static int ath_reset_internal(struct ath
 	tasklet_disable(&sc->intr_tq);
 	spin_lock_bh(&sc->sc_pcu_lock);
 
-	if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
+	if (!sc->cur_chan->offchannel) {
 		fastcc = false;
-		caldata = &sc->caldata;
+		caldata = &sc->cur_chan->caldata;
 	}
 
 	if (!hchan) {
@@ -292,6 +314,10 @@ static int ath_reset_internal(struct ath
 	if (!ath_prepare_reset(sc))
 		fastcc = false;
 
+	spin_lock_bh(&sc->chan_lock);
+	sc->cur_chandef = sc->cur_chan->chandef;
+	spin_unlock_bh(&sc->chan_lock);
+
 	ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
 		hchan->channel, IS_CHAN_HT40(hchan), fastcc);
 
@@ -307,7 +333,7 @@ static int ath_reset_internal(struct ath
 	}
 
 	if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
-	    (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+	    sc->cur_chan->offchannel)
 		ath9k_mci_set_txpower(sc, true, false);
 
 	if (!ath_complete_reset(sc, true))
@@ -320,98 +346,6 @@ out:
 	return r;
 }
 
-
-/*
- * Set/change channels.  If the channel is really being changed, it's done
- * by reseting the chip.  To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	struct ieee80211_hw *hw = sc->hw;
-	struct ath9k_channel *hchan;
-	struct ieee80211_channel *chan = chandef->chan;
-	bool offchannel;
-	int pos = chan->hw_value;
-	int old_pos = -1;
-	int r;
-
-	if (test_bit(ATH_OP_INVALID, &common->op_flags))
-		return -EIO;
-
-	offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
-
-	if (ah->curchan)
-		old_pos = ah->curchan - &ah->channels[0];
-
-	ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
-		chan->center_freq, chandef->width);
-
-	/* update survey stats for the old channel before switching */
-	spin_lock_bh(&common->cc_lock);
-	ath_update_survey_stats(sc);
-	spin_unlock_bh(&common->cc_lock);
-
-	ath9k_cmn_get_channel(hw, ah, chandef);
-
-	/*
-	 * If the operating channel changes, change the survey in-use flags
-	 * along with it.
-	 * Reset the survey data for the new channel, unless we're switching
-	 * back to the operating channel from an off-channel operation.
-	 */
-	if (!offchannel && sc->cur_survey != &sc->survey[pos]) {
-		if (sc->cur_survey)
-			sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
-
-		sc->cur_survey = &sc->survey[pos];
-
-		memset(sc->cur_survey, 0, sizeof(struct survey_info));
-		sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
-	} else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
-		memset(&sc->survey[pos], 0, sizeof(struct survey_info));
-	}
-
-	hchan = &sc->sc_ah->channels[pos];
-	r = ath_reset_internal(sc, hchan);
-	if (r)
-		return r;
-
-	/*
-	 * The most recent snapshot of channel->noisefloor for the old
-	 * channel is only available after the hardware reset. Copy it to
-	 * the survey stats now.
-	 */
-	if (old_pos >= 0)
-		ath_update_survey_nf(sc, old_pos);
-
-	/*
-	 * Enable radar pulse detection if on a DFS channel. Spectral
-	 * scanning and radar detection can not be used concurrently.
-	 */
-	if (hw->conf.radar_enabled) {
-		u32 rxfilter;
-
-		/* set HW specific DFS configuration */
-		ath9k_hw_set_radar_params(ah);
-		rxfilter = ath9k_hw_getrxfilter(ah);
-		rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
-				ATH9K_RX_FILTER_PHYERR;
-		ath9k_hw_setrxfilter(ah, rxfilter);
-		ath_dbg(common, DFS, "DFS enabled at freq %d\n",
-			chan->center_freq);
-	} else {
-		/* perform spectral scan if requested. */
-		if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
-			sc->spectral_mode == SPECTRAL_CHANSCAN)
-			ath9k_spectral_scan_trigger(hw);
-	}
-
-	return 0;
-}
-
 static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
 			    struct ieee80211_vif *vif)
 {
@@ -579,7 +513,7 @@ irqreturn_t ath_isr(int irq, void *dev)
 	 * touch anything. Note this can happen early
 	 * on if the IRQ is shared.
 	 */
-	if (test_bit(ATH_OP_INVALID, &common->op_flags))
+	if (!ah || test_bit(ATH_OP_INVALID, &common->op_flags))
 		return IRQ_NONE;
 
 	/* shared irq, not for us */
@@ -712,7 +646,8 @@ static int ath9k_start(struct ieee80211_
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+	struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
+	struct ath_chanctx *ctx = sc->cur_chan;
 	struct ath9k_channel *init_channel;
 	int r;
 
@@ -723,7 +658,8 @@ static int ath9k_start(struct ieee80211_
 	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
 
-	init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
+	init_channel = ath9k_cmn_get_channel(hw, ah, &ctx->chandef);
+	sc->cur_chandef = hw->conf.chandef;
 
 	/* Reset SERDES registers */
 	ath9k_hw_configpcipowersave(ah, false);
@@ -886,6 +822,7 @@ static void ath9k_stop(struct ieee80211_
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool prev_idle;
 
+	cancel_work_sync(&sc->chanctx_work);
 	mutex_lock(&sc->mutex);
 
 	ath_cancel_work(sc);
@@ -934,7 +871,8 @@ static void ath9k_stop(struct ieee80211_
 	}
 
 	if (!ah->curchan)
-		ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
+		ah->curchan = ath9k_cmn_get_channel(hw, ah,
+						    &sc->cur_chan->chandef);
 
 	ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	ath9k_hw_phy_disable(ah);
@@ -979,18 +917,29 @@ static void ath9k_vif_iter(void *data, u
 		iter_data->has_hw_macaddr = true;
 	}
 
+	if (!vif->bss_conf.use_short_slot)
+		iter_data->slottime = ATH9K_SLOT_TIME_20;
+
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
 		iter_data->naps++;
+		if (vif->bss_conf.enable_beacon)
+			iter_data->beacons = true;
 		break;
 	case NL80211_IFTYPE_STATION:
 		iter_data->nstations++;
+		if (vif->bss_conf.assoc && !iter_data->primary_sta)
+			iter_data->primary_sta = vif;
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		iter_data->nadhocs++;
+		if (vif->bss_conf.enable_beacon)
+			iter_data->beacons = true;
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
 		iter_data->nmeshes++;
+		if (vif->bss_conf.enable_beacon)
+			iter_data->beacons = true;
 		break;
 	case NL80211_IFTYPE_WDS:
 		iter_data->nwds++;
@@ -1000,26 +949,12 @@ static void ath9k_vif_iter(void *data, u
 	}
 }
 
-static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_softc *sc = data;
-	struct ath_vif *avp = (void *)vif->drv_priv;
-
-	if (vif->type != NL80211_IFTYPE_STATION)
-		return;
-
-	if (avp->primary_sta_vif)
-		ath9k_set_assoc_state(sc, vif);
-}
-
 /* Called with sc->mutex held. */
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+			       struct ath_chanctx *ctx,
 			       struct ath9k_vif_iter_data *iter_data)
 {
-	struct ath_softc *sc = hw->priv;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_vif *avp;
 
 	/*
 	 * Pick the MAC address of the first interface as the new hardware
@@ -1028,29 +963,80 @@ void ath9k_calculate_iter_data(struct ie
 	 */
 	memset(iter_data, 0, sizeof(*iter_data));
 	memset(&iter_data->mask, 0xff, ETH_ALEN);
+	iter_data->slottime = ATH9K_SLOT_TIME_9;
 
-	if (vif)
-		ath9k_vif_iter(iter_data, vif->addr, vif);
+	list_for_each_entry(avp, &ctx->vifs, list)
+		ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
 
-	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(
-		sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-		ath9k_vif_iter, iter_data);
+	if (ctx == &sc->offchannel.chan) {
+		struct ieee80211_vif *vif;
 
-	memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
+		if (sc->offchannel.state < ATH_OFFCHANNEL_ROC_START)
+			vif = sc->offchannel.scan_vif;
+		else
+			vif = sc->offchannel.roc_vif;
+
+		if (vif)
+			ath9k_vif_iter(iter_data, vif->addr, vif);
+		iter_data->beacons = false;
+	}
+}
+
+static void ath9k_set_assoc_state(struct ath_softc *sc,
+				  struct ieee80211_vif *vif, bool changed)
+{
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	unsigned long flags;
+
+	set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+	/* Set the AID, BSSID and do beacon-sync only when
+	 * the HW opmode is STATION.
+	 *
+	 * But the primary bit is set above in any case.
+	 */
+	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+		return;
+
+	ether_addr_copy(common->curbssid, bss_conf->bssid);
+	common->curaid = bss_conf->aid;
+	ath9k_hw_write_associd(sc->sc_ah);
+
+	if (changed) {
+		common->last_rssi = ATH_RSSI_DUMMY_MARKER;
+		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+		spin_lock_irqsave(&sc->sc_pm_lock, flags);
+		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+	}
+
+	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+		ath9k_mci_update_wlan_channels(sc, false);
+
+	ath_dbg(common, CONFIG,
+		"Primary Station interface: %pM, BSSID: %pM\n",
+		vif->addr, common->curbssid);
 }
 
 /* Called with sc->mutex held. */
-static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
-					  struct ieee80211_vif *vif)
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+				   struct ath_chanctx *ctx)
 {
-	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_vif_iter_data iter_data;
-	enum nl80211_iftype old_opmode = ah->opmode;
 
-	ath9k_calculate_iter_data(hw, vif, &iter_data);
+	ath_chanctx_check_active(sc, ctx);
+
+	if (ctx != sc->cur_chan)
+		return;
+
+	ath9k_ps_wakeup(sc);
+	ath9k_calculate_iter_data(sc, ctx, &iter_data);
+
+	if (iter_data.has_hw_macaddr)
+		ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
 
 	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
 	ath_hw_setbssidmask(common);
@@ -1073,24 +1059,57 @@ static void ath9k_calculate_summary_stat
 
 	ath9k_hw_setopmode(ah);
 
+	ctx->switch_after_beacon = false;
 	if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
 		ah->imask |= ATH9K_INT_TSFOOR;
-	else
+	else {
 		ah->imask &= ~ATH9K_INT_TSFOOR;
+		if (iter_data.naps == 1 && iter_data.beacons)
+			ctx->switch_after_beacon = true;
+	}
+
+	ah->imask &= ~ATH9K_INT_SWBA;
+	if (ah->opmode == NL80211_IFTYPE_STATION) {
+		bool changed = (iter_data.primary_sta != ctx->primary_sta);
 
+		iter_data.beacons = true;
+		if (iter_data.primary_sta) {
+			ath9k_set_assoc_state(sc, iter_data.primary_sta,
+					      changed);
+			if (!ctx->primary_sta ||
+			    !ctx->primary_sta->bss_conf.assoc)
+				ctx->primary_sta = iter_data.primary_sta;
+		} else {
+			ctx->primary_sta = NULL;
+			memset(common->curbssid, 0, ETH_ALEN);
+			common->curaid = 0;
+			ath9k_hw_write_associd(sc->sc_ah);
+			if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+				ath9k_mci_update_wlan_channels(sc, true);
+		}
+	} else if (iter_data.beacons) {
+		ah->imask |= ATH9K_INT_SWBA;
+	}
 	ath9k_hw_set_interrupts(ah);
 
-	/*
-	 * If we are changing the opmode to STATION,
-	 * a beacon sync needs to be done.
-	 */
-	if (ah->opmode == NL80211_IFTYPE_STATION &&
-	    old_opmode == NL80211_IFTYPE_AP &&
-	    test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
-		ieee80211_iterate_active_interfaces_atomic(
-			sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-			ath9k_sta_vif_iter, sc);
+	if (iter_data.beacons)
+		set_bit(ATH_OP_BEACONS, &common->op_flags);
+	else
+		clear_bit(ATH_OP_BEACONS, &common->op_flags);
+
+	if (ah->slottime != iter_data.slottime) {
+		ah->slottime = iter_data.slottime;
+		ath9k_hw_init_global_settings(ah);
 	}
+
+	if (iter_data.primary_sta)
+		set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+	else
+		clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+
+	ctx->primary_sta = iter_data.primary_sta;
+
+	ath9k_ps_restore(sc);
 }
 
 static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -1101,6 +1120,7 @@ static int ath9k_add_interface(struct ie
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
 	struct ath_node *an = &avp->mcast_node;
+	int i;
 
 	mutex_lock(&sc->mutex);
 
@@ -1115,14 +1135,20 @@ static int ath9k_add_interface(struct ie
 	ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
 	sc->nvifs++;
 
-	ath9k_ps_wakeup(sc);
-	ath9k_calculate_summary_state(hw, vif);
-	ath9k_ps_restore(sc);
-
 	if (ath9k_uses_beacons(vif->type))
 		ath9k_beacon_assign_slot(sc, vif);
 
 	avp->vif = vif;
+	if (!ath9k_use_chanctx) {
+		avp->chanctx = sc->cur_chan;
+		list_add_tail(&avp->list, &avp->chanctx->vifs);
+	}
+	for (i = 0; i < IEEE80211_NUM_ACS; i++)
+		vif->hw_queue[i] = i;
+	if (vif->type == NL80211_IFTYPE_AP)
+		vif->cab_queue = hw->queues - 2;
+	else
+		vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
 
 	an->sc = sc;
 	an->sta = NULL;
@@ -1141,6 +1167,8 @@ static int ath9k_change_interface(struct
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_vif *avp = (void *)vif->drv_priv;
+	int i;
 
 	mutex_lock(&sc->mutex);
 
@@ -1157,13 +1185,19 @@ static int ath9k_change_interface(struct
 	vif->type = new_type;
 	vif->p2p = p2p;
 
-	ath9k_ps_wakeup(sc);
-	ath9k_calculate_summary_state(hw, vif);
-	ath9k_ps_restore(sc);
-
 	if (ath9k_uses_beacons(vif->type))
 		ath9k_beacon_assign_slot(sc, vif);
 
+	for (i = 0; i < IEEE80211_NUM_ACS; i++)
+		vif->hw_queue[i] = i;
+
+	if (vif->type == NL80211_IFTYPE_AP)
+		vif->cab_queue = hw->queues - 2;
+	else
+		vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
+
+	ath9k_calculate_summary_state(sc, avp->chanctx);
+
 	mutex_unlock(&sc->mutex);
 	return 0;
 }
@@ -1211,14 +1245,12 @@ static void ath9k_remove_interface(struc
 
 	sc->nvifs--;
 	sc->tx99_vif = NULL;
+	if (!ath9k_use_chanctx)
+		list_del(&avp->list);
 
 	if (ath9k_uses_beacons(vif->type))
 		ath9k_beacon_remove_slot(sc, vif);
 
-	ath9k_ps_wakeup(sc);
-	ath9k_calculate_summary_state(hw, NULL);
-	ath9k_ps_restore(sc);
-
 	ath_tx_node_cleanup(sc, &avp->mcast_node);
 
 	mutex_unlock(&sc->mutex);
@@ -1345,7 +1377,7 @@ static int ath9k_config(struct ieee80211
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &hw->conf;
-	bool reset_channel = false;
+	struct ath_chanctx *ctx = sc->cur_chan;
 
 	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
@@ -1361,7 +1393,7 @@ static int ath9k_config(struct ieee80211
 			 * The chip needs a reset to properly wake up from
 			 * full sleep
 			 */
-			reset_channel = ah->chip_fullsleep;
+			ath_chanctx_set_channel(sc, ctx, &ctx->chandef);
 		}
 	}
 
@@ -1391,20 +1423,16 @@ static int ath9k_config(struct ieee80211
 		}
 	}
 
-	if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
-		if (ath_set_channel(sc, &hw->conf.chandef) < 0) {
-			ath_err(common, "Unable to set channel\n");
-			mutex_unlock(&sc->mutex);
-			ath9k_ps_restore(sc);
-			return -EINVAL;
-		}
+	if (!ath9k_use_chanctx && (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+		ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL);
+		ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
-		sc->config.txpowlimit = 2 * conf->power_level;
+		sc->cur_chan->txpower = 2 * conf->power_level;
 		ath9k_cmn_update_txpow(ah, sc->curtxpow,
-				       sc->config.txpowlimit, &sc->curtxpow);
+				       sc->cur_chan->txpower, &sc->curtxpow);
 	}
 
 	mutex_unlock(&sc->mutex);
@@ -1659,58 +1687,6 @@ static int ath9k_set_key(struct ieee8021
 	return ret;
 }
 
-static void ath9k_set_assoc_state(struct ath_softc *sc,
-				  struct ieee80211_vif *vif)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_vif *avp = (void *)vif->drv_priv;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	unsigned long flags;
-
-	set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
-	avp->primary_sta_vif = true;
-
-	/*
-	 * Set the AID, BSSID and do beacon-sync only when
-	 * the HW opmode is STATION.
-	 *
-	 * But the primary bit is set above in any case.
-	 */
-	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
-		return;
-
-	memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-	common->curaid = bss_conf->aid;
-	ath9k_hw_write_associd(sc->sc_ah);
-
-	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
-	sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
-
-	spin_lock_irqsave(&sc->sc_pm_lock, flags);
-	sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
-	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
-
-	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
-		ath9k_mci_update_wlan_channels(sc, false);
-
-	ath_dbg(common, CONFIG,
-		"Primary Station interface: %pM, BSSID: %pM\n",
-		vif->addr, common->curbssid);
-}
-
-static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_softc *sc = data;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-	if (test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
-		return;
-
-	if (bss_conf->assoc)
-		ath9k_set_assoc_state(sc, vif);
-}
-
 void ath9k_p2p_ps_timer(void *priv)
 {
 	struct ath_softc *sc = priv;
@@ -1720,7 +1696,11 @@ void ath9k_p2p_ps_timer(void *priv)
 	struct ath_node *an;
 	u32 tsf;
 
-	if (!avp)
+	del_timer_sync(&sc->sched.timer);
+	ath9k_hw_gen_timer_stop(sc->sc_ah, sc->p2p_ps_timer);
+	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
+
+	if (!avp || avp->chanctx != sc->cur_chan)
 		return;
 
 	tsf = ath9k_hw_gettsf32(sc->sc_ah);
@@ -1795,26 +1775,9 @@ static void ath9k_bss_info_changed(struc
 		ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
 			bss_conf->bssid, bss_conf->assoc);
 
-		if (avp->primary_sta_vif && !bss_conf->assoc) {
-			clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
-			avp->primary_sta_vif = false;
-
-			if (ah->opmode == NL80211_IFTYPE_STATION)
-				clear_bit(ATH_OP_BEACONS, &common->op_flags);
-		}
-
-		ieee80211_iterate_active_interfaces_atomic(
-			sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-			ath9k_bss_assoc_iter, sc);
-
-		if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags) &&
-		    ah->opmode == NL80211_IFTYPE_STATION) {
-			memset(common->curbssid, 0, ETH_ALEN);
-			common->curaid = 0;
-			ath9k_hw_write_associd(sc->sc_ah);
-			if (ath9k_hw_mci_is_enabled(sc->sc_ah))
-				ath9k_mci_update_wlan_channels(sc, true);
-		}
+		ath9k_calculate_summary_state(sc, avp->chanctx);
+		if (bss_conf->assoc)
+			ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_ASSOC);
 	}
 
 	if (changed & BSS_CHANGED_IBSS) {
@@ -1824,10 +1787,15 @@ static void ath9k_bss_info_changed(struc
 	}
 
 	if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
-	    (changed & BSS_CHANGED_BEACON_INT))
+	    (changed & BSS_CHANGED_BEACON_INT) ||
+	    (changed & BSS_CHANGED_BEACON_INFO)) {
+		if (changed & BSS_CHANGED_BEACON_ENABLED)
+			ath9k_calculate_summary_state(sc, avp->chanctx);
 		ath9k_beacon_config(sc, vif, changed);
+	}
 
-	if (changed & BSS_CHANGED_ERP_SLOT) {
+	if ((avp->chanctx == sc->cur_chan) &&
+	    (changed & BSS_CHANGED_ERP_SLOT)) {
 		if (bss_conf->use_short_slot)
 			slottime = 9;
 		else
@@ -2032,23 +2000,30 @@ static void ath9k_flush(struct ieee80211
 			u32 queues, bool drop)
 {
 	struct ath_softc *sc = hw->priv;
+
+	mutex_lock(&sc->mutex);
+	__ath9k_flush(hw, queues, drop);
+	mutex_unlock(&sc->mutex);
+}
+
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
+{
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	int timeout = HZ / 5; /* 200 ms */
 	bool drain_txq;
+	int i;
 
-	mutex_lock(&sc->mutex);
 	cancel_delayed_work_sync(&sc->tx_complete_work);
 
 	if (ah->ah_flags & AH_UNPLUGGED) {
 		ath_dbg(common, ANY, "Device has been unplugged!\n");
-		mutex_unlock(&sc->mutex);
 		return;
 	}
 
 	if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
 		ath_dbg(common, ANY, "Device not present\n");
-		mutex_unlock(&sc->mutex);
 		return;
 	}
 
@@ -2066,11 +2041,13 @@ static void ath9k_flush(struct ieee80211
 			ath_reset(sc);
 
 		ath9k_ps_restore(sc);
-		ieee80211_wake_queues(hw);
+		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+			ieee80211_wake_queue(sc->hw,
+					     sc->cur_chan->hw_queue_base + i);
+		}
 	}
 
 	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
-	mutex_unlock(&sc->mutex);
 }
 
 static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
@@ -2230,6 +2207,403 @@ static void ath9k_sw_scan_complete(struc
 	clear_bit(ATH_OP_SCANNING, &common->op_flags);
 }
 
+static int ath_scan_channel_duration(struct ath_softc *sc,
+				     struct ieee80211_channel *chan)
+{
+	struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+
+	if (!req->n_ssids || (chan->flags & IEEE80211_CHAN_NO_IR))
+		return (HZ / 9); /* ~110 ms */
+
+	return (HZ / 16); /* ~60 ms */
+}
+
+static void
+ath_scan_next_channel(struct ath_softc *sc)
+{
+	struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+	struct ieee80211_channel *chan;
+
+	if (sc->offchannel.scan_idx >= req->n_channels) {
+		sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+		ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
+				   NULL);
+		return;
+	}
+
+	chan = req->channels[sc->offchannel.scan_idx++];
+	sc->offchannel.duration = ath_scan_channel_duration(sc, chan);
+	sc->offchannel.state = ATH_OFFCHANNEL_PROBE_SEND;
+	ath_chanctx_offchan_switch(sc, chan);
+}
+
+static void ath_offchannel_next(struct ath_softc *sc)
+{
+	struct ieee80211_vif *vif;
+
+	if (sc->offchannel.scan_req) {
+		vif = sc->offchannel.scan_vif;
+		sc->offchannel.chan.txpower = vif->bss_conf.txpower;
+		ath_scan_next_channel(sc);
+	} else if (sc->offchannel.roc_vif) {
+		vif = sc->offchannel.roc_vif;
+		sc->offchannel.chan.txpower = vif->bss_conf.txpower;
+		sc->offchannel.duration = sc->offchannel.roc_duration;
+		sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
+		ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
+	} else {
+		ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
+				   NULL);
+		sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+		if (sc->ps_idle)
+			ath_cancel_work(sc);
+	}
+}
+
+static void ath_roc_complete(struct ath_softc *sc, bool abort)
+{
+	sc->offchannel.roc_vif = NULL;
+	sc->offchannel.roc_chan = NULL;
+	if (!abort)
+		ieee80211_remain_on_channel_expired(sc->hw);
+	ath_offchannel_next(sc);
+	ath9k_ps_restore(sc);
+}
+
+static void ath_scan_complete(struct ath_softc *sc, bool abort)
+{
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+	sc->offchannel.scan_req = NULL;
+	sc->offchannel.scan_vif = NULL;
+	sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+	ieee80211_scan_completed(sc->hw, abort);
+	clear_bit(ATH_OP_SCANNING, &common->op_flags);
+	ath_offchannel_next(sc);
+	ath9k_ps_restore(sc);
+}
+
+static void ath_scan_send_probe(struct ath_softc *sc,
+				struct cfg80211_ssid *ssid)
+{
+	struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+	struct ieee80211_vif *vif = sc->offchannel.scan_vif;
+	struct ath_tx_control txctl = {};
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+	int band = sc->offchannel.chan.chandef.chan->band;
+
+	skb = ieee80211_probereq_get(sc->hw, vif,
+			ssid->ssid, ssid->ssid_len, req->ie_len);
+	if (!skb)
+		return;
+
+	info = IEEE80211_SKB_CB(skb);
+	if (req->no_cck)
+		info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
+
+	if (req->ie_len)
+		memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
+
+	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+
+	if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL))
+		goto error;
+
+	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
+	txctl.force_channel = true;
+	if (ath_tx_start(sc->hw, skb, &txctl))
+		goto error;
+
+	return;
+
+error:
+	ieee80211_free_txskb(sc->hw, skb);
+}
+
+static void ath_scan_channel_start(struct ath_softc *sc)
+{
+	struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+	int i;
+
+	if (!(sc->cur_chan->chandef.chan->flags & IEEE80211_CHAN_NO_IR) &&
+	    req->n_ssids) {
+		for (i = 0; i < req->n_ssids; i++)
+			ath_scan_send_probe(sc, &req->ssids[i]);
+
+	}
+
+	sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT;
+	mod_timer(&sc->offchannel.timer, jiffies + sc->offchannel.duration);
+}
+
+void ath_offchannel_channel_change(struct ath_softc *sc)
+{
+	switch (sc->offchannel.state) {
+	case ATH_OFFCHANNEL_PROBE_SEND:
+		if (!sc->offchannel.scan_req)
+			return;
+
+		if (sc->cur_chan->chandef.chan !=
+		    sc->offchannel.chan.chandef.chan)
+			return;
+
+		ath_scan_channel_start(sc);
+		break;
+	case ATH_OFFCHANNEL_IDLE:
+		if (!sc->offchannel.scan_req)
+			return;
+
+		ath_scan_complete(sc, false);
+		break;
+	case ATH_OFFCHANNEL_ROC_START:
+		if (sc->cur_chan != &sc->offchannel.chan)
+			break;
+
+		sc->offchannel.state = ATH_OFFCHANNEL_ROC_WAIT;
+		mod_timer(&sc->offchannel.timer, jiffies +
+			  msecs_to_jiffies(sc->offchannel.duration));
+		ieee80211_ready_on_channel(sc->hw);
+		break;
+	case ATH_OFFCHANNEL_ROC_DONE:
+		ath_roc_complete(sc, false);
+		break;
+	default:
+		break;
+	}
+}
+
+void ath_offchannel_timer(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *)data;
+	struct ath_chanctx *ctx;
+
+	switch (sc->offchannel.state) {
+	case ATH_OFFCHANNEL_PROBE_WAIT:
+		if (!sc->offchannel.scan_req)
+			return;
+
+		/* get first active channel context */
+		ctx = ath_chanctx_get_oper_chan(sc, true);
+		if (ctx->active) {
+			sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND;
+			ath_chanctx_switch(sc, ctx, NULL);
+			mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
+			break;
+		}
+		/* fall through */
+	case ATH_OFFCHANNEL_SUSPEND:
+		if (!sc->offchannel.scan_req)
+			return;
+
+		ath_scan_next_channel(sc);
+		break;
+	case ATH_OFFCHANNEL_ROC_START:
+	case ATH_OFFCHANNEL_ROC_WAIT:
+		ctx = ath_chanctx_get_oper_chan(sc, false);
+		sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
+		ath_chanctx_switch(sc, ctx, NULL);
+		break;
+	default:
+		break;
+	}
+}
+
+static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			 struct ieee80211_scan_request *hw_req)
+{
+	struct cfg80211_scan_request *req = &hw_req->req;
+	struct ath_softc *sc = hw->priv;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	int ret = 0;
+
+	mutex_lock(&sc->mutex);
+
+	if (WARN_ON(sc->offchannel.scan_req)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ath9k_ps_wakeup(sc);
+	set_bit(ATH_OP_SCANNING, &common->op_flags);
+	sc->offchannel.scan_vif = vif;
+	sc->offchannel.scan_req = req;
+	sc->offchannel.scan_idx = 0;
+
+	if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
+		ath_offchannel_next(sc);
+
+out:
+	mutex_unlock(&sc->mutex);
+
+	return ret;
+}
+
+static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+
+	mutex_lock(&sc->mutex);
+	del_timer_sync(&sc->offchannel.timer);
+	ath_scan_complete(sc, true);
+	mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_remain_on_channel(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_channel *chan, int duration,
+				   enum ieee80211_roc_type type)
+{
+	struct ath_softc *sc = hw->priv;
+	int ret = 0;
+
+	mutex_lock(&sc->mutex);
+
+	if (WARN_ON(sc->offchannel.roc_vif)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ath9k_ps_wakeup(sc);
+	sc->offchannel.roc_vif = vif;
+	sc->offchannel.roc_chan = chan;
+	sc->offchannel.roc_duration = duration;
+
+	if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
+		ath_offchannel_next(sc);
+
+out:
+	mutex_unlock(&sc->mutex);
+
+	return ret;
+}
+
+static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+	struct ath_softc *sc = hw->priv;
+
+	mutex_lock(&sc->mutex);
+
+	del_timer_sync(&sc->offchannel.timer);
+
+	if (sc->offchannel.roc_vif) {
+		if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
+			ath_roc_complete(sc, true);
+	}
+
+	mutex_unlock(&sc->mutex);
+
+	return 0;
+}
+
+static int ath9k_add_chanctx(struct ieee80211_hw *hw,
+			     struct ieee80211_chanctx_conf *conf)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_chanctx *ctx, **ptr;
+	int pos;
+
+	mutex_lock(&sc->mutex);
+
+	ath_for_each_chanctx(sc, ctx) {
+		if (ctx->assigned)
+			continue;
+
+		ptr = (void *) conf->drv_priv;
+		*ptr = ctx;
+		ctx->assigned = true;
+		pos = ctx - &sc->chanctx[0];
+		ctx->hw_queue_base = pos * IEEE80211_NUM_ACS;
+		ath_chanctx_set_channel(sc, ctx, &conf->def);
+		mutex_unlock(&sc->mutex);
+		return 0;
+	}
+	mutex_unlock(&sc->mutex);
+	return -ENOSPC;
+}
+
+
+static void ath9k_remove_chanctx(struct ieee80211_hw *hw,
+				 struct ieee80211_chanctx_conf *conf)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_chanctx *ctx = ath_chanctx_get(conf);
+
+	mutex_lock(&sc->mutex);
+	ctx->assigned = false;
+	ctx->hw_queue_base = -1;
+	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
+	mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_change_chanctx(struct ieee80211_hw *hw,
+				 struct ieee80211_chanctx_conf *conf,
+				 u32 changed)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_chanctx *ctx = ath_chanctx_get(conf);
+
+	mutex_lock(&sc->mutex);
+	ath_chanctx_set_channel(sc, ctx, &conf->def);
+	mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_chanctx_conf *conf)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_vif *avp = (void *)vif->drv_priv;
+	struct ath_chanctx *ctx = ath_chanctx_get(conf);
+	int i;
+
+	mutex_lock(&sc->mutex);
+	avp->chanctx = ctx;
+	list_add_tail(&avp->list, &ctx->vifs);
+	ath9k_calculate_summary_state(sc, ctx);
+	for (i = 0; i < IEEE80211_NUM_ACS; i++)
+		vif->hw_queue[i] = ctx->hw_queue_base + i;
+	mutex_unlock(&sc->mutex);
+
+	return 0;
+}
+
+static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_chanctx_conf *conf)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_vif *avp = (void *)vif->drv_priv;
+	struct ath_chanctx *ctx = ath_chanctx_get(conf);
+	int ac;
+
+	mutex_lock(&sc->mutex);
+	avp->chanctx = NULL;
+	list_del(&avp->list);
+	ath9k_calculate_summary_state(sc, ctx);
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+		vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
+	mutex_unlock(&sc->mutex);
+}
+
+void ath9k_fill_chanctx_ops(void)
+{
+	if (!ath9k_use_chanctx)
+		return;
+
+	ath9k_ops.hw_scan = ath9k_hw_scan;
+	ath9k_ops.cancel_hw_scan = ath9k_cancel_hw_scan;
+	ath9k_ops.remain_on_channel  = ath9k_remain_on_channel;
+	ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
+	ath9k_ops.add_chanctx        = ath9k_add_chanctx;
+	ath9k_ops.remove_chanctx     = ath9k_remove_chanctx;
+	ath9k_ops.change_chanctx     = ath9k_change_chanctx;
+	ath9k_ops.assign_vif_chanctx = ath9k_assign_vif_chanctx;
+	ath9k_ops.unassign_vif_chanctx = ath9k_unassign_vif_chanctx;
+	ath9k_ops.mgd_prepare_tx = ath9k_chanctx_force_active;
+}
+
 struct ieee80211_ops ath9k_ops = {
 	.tx 		    = ath9k_tx,
 	.start 		    = ath9k_start,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -5,7 +5,8 @@ ath9k-y +=	beacon.o \
 		recv.o \
 		xmit.o \
 		link.o \
-		antenna.o
+		antenna.o \
+		channel.o
 
 ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/mci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/mci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/mci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/mci.c	2014-09-28 17:29:07.000000000 -0400
@@ -706,7 +706,7 @@ void ath9k_mci_set_txpower(struct ath_so
 		return;
 
 	if (setchannel) {
-		struct ath9k_hw_cal_data *caldata = &sc->caldata;
+		struct ath9k_hw_cal_data *caldata = &sc->cur_chan->caldata;
 		if (IS_CHAN_HT40PLUS(ah->curchan) &&
 		    (ah->curchan->channel > caldata->channel) &&
 		    (ah->curchan->channel <= caldata->channel + 20))
@@ -720,7 +720,7 @@ void ath9k_mci_set_txpower(struct ath_so
 		mci_hw->concur_tx = concur_tx;
 
 	if (old_concur_tx != mci_hw->concur_tx)
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+		ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
 }
 
 static void ath9k_mci_stomp_audio(struct ath_softc *sc)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include "ath9k.h"
 
-static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
+static const struct pci_device_id ath_pci_id_table[] = {
 	{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
@@ -843,6 +843,7 @@ static int ath_pci_probe(struct pci_dev
 		return -ENODEV;
 	}
 
+	ath9k_fill_chanctx_ops();
 	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (!hw) {
 		dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/recv.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/recv.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -259,7 +259,7 @@ static void ath_edma_start_recv(struct a
 	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
 	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
 	ath_opmode_init(sc);
-	ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+	ath9k_hw_startpcureceive(sc->sc_ah, sc->cur_chan->offchannel);
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -374,6 +374,7 @@ void ath_rx_cleanup(struct ath_softc *sc
 
 u32 ath_calcrxfilter(struct ath_softc *sc)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	u32 rfilt;
 
 	if (config_enabled(CONFIG_ATH9K_TX99))
@@ -424,6 +425,10 @@ u32 ath_calcrxfilter(struct ath_softc *s
 	if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah))
 		rfilt |= ATH9K_RX_FILTER_4ADDRESS;
 
+	if (ath9k_use_chanctx &&
+	    test_bit(ATH_OP_SCANNING, &common->op_flags))
+		rfilt |= ATH9K_RX_FILTER_BEACON;
+
 	return rfilt;
 
 }
@@ -457,7 +462,7 @@ int ath_startrecv(struct ath_softc *sc)
 
 start_recv:
 	ath_opmode_init(sc);
-	ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+	ath9k_hw_startpcureceive(ah, sc->cur_chan->offchannel);
 
 	return 0;
 }
@@ -540,7 +545,7 @@ static void ath_rx_ps_beacon(struct ath_
 		sc->ps_flags &= ~PS_BEACON_SYNC;
 		ath_dbg(common, PS,
 			"Reconfigure beacon timers based on synchronized timestamp\n");
-		if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0)))
+		if (!(WARN_ON_ONCE(sc->cur_chan->beacon.beacon_interval == 0)))
 			ath9k_set_beacon(sc);
 		if (sc->p2p_ps_vif)
 			ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
@@ -887,6 +892,11 @@ static int ath9k_rx_skb_preprocess(struc
 		return -EINVAL;
 	}
 
+	if (rx_stats->is_mybeacon) {
+		sc->sched.next_tbtt = rx_stats->rs_tstamp;
+		ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_BEACON_RECEIVED);
+	}
+
 	ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
 
 	rx_status->band = ah->curchan->chan->band;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -813,6 +813,7 @@
 #define AR_SREV_VERSION_9531            0x500
 #define AR_SREV_REVISION_9531_10        0
 #define AR_SREV_REVISION_9531_11        1
+#define AR_SREV_REVISION_9531_20        2
 
 #define AR_SREV_5416(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -958,6 +959,9 @@
 #define AR_SREV_9531_11(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_11))
+#define AR_SREV_9531_20(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_20))
 
 /* NOTE: When adding chips newer than Peacock, add chip check here */
 #define AR_SREV_9580_10_OR_LATER(_ah) \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/spectral.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/spectral.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/spectral.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/spectral.c	2014-09-28 17:29:07.000000000 -0400
@@ -253,7 +253,7 @@ static ssize_t write_file_spec_scan_ctl(
 
 	if (strncmp("trigger", buf, 7) == 0) {
 		ath9k_spectral_scan_trigger(sc->hw);
-	} else if (strncmp("background", buf, 9) == 0) {
+	} else if (strncmp("background", buf, 10) == 0) {
 		ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
 		ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
 	} else if (strncmp("chanscan", buf, 8) == 0) {
@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	if (val < 0 || val > 1)
+	if (val > 1)
 		return -EINVAL;
 
 	sc->spec_config.short_repeat = val;
@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	if (val < 0 || val > 255)
+	if (val > 255)
 		return -EINVAL;
 
 	sc->spec_config.count = val;
@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_perio
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	if (val < 0 || val > 255)
+	if (val > 255)
 		return -EINVAL;
 
 	sc->spec_config.period = val;
@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_p
 	if (kstrtoul(buf, 0, &val))
 		return -EINVAL;
 
-	if (val < 0 || val > 15)
+	if (val > 15)
 		return -EINVAL;
 
 	sc->spec_config.fft_period = val;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/tx99.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/tx99.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/tx99.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/tx99.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ static struct sk_buff *ath9k_build_tx99_
 	tx_info = IEEE80211_SKB_CB(skb);
 	memset(tx_info, 0, sizeof(*tx_info));
 	rate = &tx_info->control.rates[0];
-	tx_info->band = hw->conf.chandef.chan->band;
+	tx_info->band = sc->cur_chan->chandef.chan->band;
 	tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
 	tx_info->control.vif = sc->tx99_vif;
 	rate->count = 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/wow.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/wow.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/wow.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/wow.c	2014-09-28 17:29:07.000000000 -0400
@@ -193,6 +193,7 @@ int ath9k_suspend(struct ieee80211_hw *h
 	u32 wow_triggers_enabled = 0;
 	int ret = 0;
 
+	cancel_work_sync(&sc->chanctx_work);
 	mutex_lock(&sc->mutex);
 
 	ath_cancel_work(sc);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,9 +103,16 @@ void ath_txq_unlock_complete(struct ath_
 		ieee80211_tx_status(sc->hw, skb);
 }
 
-static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
+			     struct ath_atx_tid *tid)
 {
 	struct ath_atx_ac *ac = tid->ac;
+	struct list_head *list;
+	struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
+	struct ath_chanctx *ctx = avp->chanctx;
+
+	if (!ctx)
+		return;
 
 	if (tid->sched)
 		return;
@@ -117,7 +124,9 @@ static void ath_tx_queue_tid(struct ath_
 		return;
 
 	ac->sched = true;
-	list_add_tail(&ac->list, &txq->axq_acq);
+
+	list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
+	list_add_tail(&ac->list, list);
 }
 
 static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
@@ -147,21 +156,22 @@ static void ath_set_rates(struct ieee802
 static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 			     struct sk_buff *skb)
 {
-	int q;
-
-	q = skb_get_queue_mapping(skb);
-	if (txq == sc->tx.uapsdq)
-		txq = sc->tx.txq_map[q];
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ath_frame_info *fi = get_frame_info(skb);
+	int hw_queue;
+	int q = fi->txq;
 
-	if (txq != sc->tx.txq_map[q])
+	if (q < 0)
 		return;
 
+	txq = sc->tx.txq_map[q];
 	if (WARN_ON(--txq->pending_frames < 0))
 		txq->pending_frames = 0;
 
+	hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
 	if (txq->stopped &&
 	    txq->pending_frames < sc->tx.txq_max_pending[q]) {
-		ieee80211_wake_queue(sc->hw, q);
+		ieee80211_wake_queue(sc->hw, hw_queue);
 		txq->stopped = false;
 	}
 }
@@ -626,7 +636,7 @@ static void ath_tx_complete_aggr(struct
 
 		skb_queue_splice_tail(&bf_pending, &tid->retry_q);
 		if (!an->sleeping) {
-			ath_tx_queue_tid(txq, tid);
+			ath_tx_queue_tid(sc, txq, tid);
 
 			if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
 				tid->ac->clear_ps_filter = true;
@@ -1492,7 +1502,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
 		ac->clear_ps_filter = true;
 
 		if (ath_tid_has_buffered(tid)) {
-			ath_tx_queue_tid(txq, tid);
+			ath_tx_queue_tid(sc, txq, tid);
 			ath_txq_schedule(sc, txq);
 		}
 
@@ -1516,7 +1526,7 @@ void ath_tx_aggr_resume(struct ath_softc
 	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
 
 	if (ath_tid_has_buffered(tid)) {
-		ath_tx_queue_tid(txq, tid);
+		ath_tx_queue_tid(sc, txq, tid);
 		ath_txq_schedule(sc, txq);
 	}
 
@@ -1651,7 +1661,6 @@ struct ath_txq *ath_txq_setup(struct ath
 		txq->axq_link = NULL;
 		__skb_queue_head_init(&txq->complete_q);
 		INIT_LIST_HEAD(&txq->axq_q);
-		INIT_LIST_HEAD(&txq->axq_acq);
 		spin_lock_init(&txq->axq_lock);
 		txq->axq_depth = 0;
 		txq->axq_ampdu_depth = 0;
@@ -1695,7 +1704,7 @@ int ath_txq_update(struct ath_softc *sc,
 int ath_cabq_update(struct ath_softc *sc)
 {
 	struct ath9k_tx_queue_info qi;
-	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 	int qnum = sc->beacon.cabq->axq_qnum;
 
 	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@@ -1813,7 +1822,7 @@ void ath_tx_cleanupq(struct ath_softc *s
 	sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
 }
 
-/* For each axq_acq entry, for each tid, try to schedule packets
+/* For each acq entry, for each tid, try to schedule packets
  * for transmit until ampdu_depth has reached min Q depth.
  */
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
@@ -1821,19 +1830,31 @@ void ath_txq_schedule(struct ath_softc *
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_atx_ac *ac, *last_ac;
 	struct ath_atx_tid *tid, *last_tid;
+	struct list_head *ac_list;
 	bool sent = false;
 
+	if (txq->mac80211_qnum < 0)
+		return;
+
+	spin_lock_bh(&sc->chan_lock);
+	ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
+	spin_unlock_bh(&sc->chan_lock);
+
 	if (test_bit(ATH_OP_HW_RESET, &common->op_flags) ||
-	    list_empty(&txq->axq_acq))
+	    list_empty(ac_list))
 		return;
 
+	spin_lock_bh(&sc->chan_lock);
 	rcu_read_lock();
 
-	last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
-	while (!list_empty(&txq->axq_acq)) {
+	last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
+	while (!list_empty(ac_list)) {
 		bool stop = false;
 
-		ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+		if (sc->cur_chan->stopped)
+			break;
+
+		ac = list_first_entry(ac_list, struct ath_atx_ac, list);
 		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
 		list_del(&ac->list);
 		ac->sched = false;
@@ -1853,7 +1874,7 @@ void ath_txq_schedule(struct ath_softc *
 			 * are pending for the tid
 			 */
 			if (ath_tid_has_buffered(tid))
-				ath_tx_queue_tid(txq, tid);
+				ath_tx_queue_tid(sc, txq, tid);
 
 			if (stop || tid == last_tid)
 				break;
@@ -1861,7 +1882,7 @@ void ath_txq_schedule(struct ath_softc *
 
 		if (!list_empty(&ac->tid_q) && !ac->sched) {
 			ac->sched = true;
-			list_add_tail(&ac->list, &txq->axq_acq);
+			list_add_tail(&ac->list, ac_list);
 		}
 
 		if (stop)
@@ -1872,12 +1893,27 @@ void ath_txq_schedule(struct ath_softc *
 				break;
 
 			sent = false;
-			last_ac = list_entry(txq->axq_acq.prev,
+			last_ac = list_entry(ac_list->prev,
 					     struct ath_atx_ac, list);
 		}
 	}
 
 	rcu_read_unlock();
+	spin_unlock_bh(&sc->chan_lock);
+}
+
+void ath_txq_schedule_all(struct ath_softc *sc)
+{
+	struct ath_txq *txq;
+	int i;
+
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		txq = sc->tx.txq_map[i];
+
+		spin_lock_bh(&txq->axq_lock);
+		ath_txq_schedule(sc, txq);
+		spin_unlock_bh(&txq->axq_lock);
+	}
 }
 
 /***********/
@@ -2008,6 +2044,7 @@ static void setup_frame_info(struct ieee
 		an = (struct ath_node *) sta->drv_priv;
 
 	memset(fi, 0, sizeof(*fi));
+	fi->txq = -1;
 	if (hw_key)
 		fi->keyix = hw_key->hw_key_idx;
 	else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
@@ -2159,13 +2196,22 @@ int ath_tx_start(struct ieee80211_hw *hw
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = txctl->sta;
 	struct ieee80211_vif *vif = info->control.vif;
+	struct ath_frame_info *fi = get_frame_info(skb);
+	struct ath_vif *avp = NULL;
 	struct ath_softc *sc = hw->priv;
 	struct ath_txq *txq = txctl->txq;
 	struct ath_atx_tid *tid = NULL;
 	struct ath_buf *bf;
-	int q;
+	bool queue;
+	int q, hw_queue;
 	int ret;
 
+	if (vif)
+		avp = (void *)vif->drv_priv;
+
+	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+		txctl->force_channel = true;
+
 	ret = ath_tx_prepare(hw, skb, txctl);
 	if (ret)
 	    return ret;
@@ -2177,24 +2223,41 @@ int ath_tx_start(struct ieee80211_hw *hw
 	 */
 
 	q = skb_get_queue_mapping(skb);
+	hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
 
 	ath_txq_lock(sc, txq);
-	if (txq == sc->tx.txq_map[q] &&
-	    ++txq->pending_frames > sc->tx.txq_max_pending[q] &&
-	    !txq->stopped) {
-		ieee80211_stop_queue(sc->hw, q);
-		txq->stopped = true;
+	if (txq == sc->tx.txq_map[q]) {
+		fi->txq = q;
+		if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
+		    !txq->stopped) {
+			ieee80211_stop_queue(sc->hw, hw_queue);
+			txq->stopped = true;
+		}
 	}
 
-	if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
+	queue = ieee80211_is_data_present(hdr->frame_control);
+
+	/* Force queueing of all frames that belong to a virtual interface on
+	 * a different channel context, to ensure that they are sent on the
+	 * correct channel.
+	 */
+	if (((avp && avp->chanctx != sc->cur_chan) ||
+	     sc->cur_chan->stopped) && !txctl->force_channel) {
+		if (!txctl->an)
+			txctl->an = &avp->mcast_node;
+		info->flags &= ~IEEE80211_TX_CTL_PS_RESPONSE;
+		queue = true;
+	}
+
+	if (txctl->an && queue)
 		tid = ath_get_skb_tid(sc, txctl->an, skb);
 
-	if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
+	if (info->flags & (IEEE80211_TX_CTL_PS_RESPONSE |
+			   IEEE80211_TX_CTL_TX_OFFCHAN)) {
 		ath_txq_unlock(sc, txq);
 		txq = sc->tx.uapsdq;
 		ath_txq_lock(sc, txq);
-	} else if (txctl->an &&
-		   ieee80211_is_data_present(hdr->frame_control)) {
+	} else if (txctl->an && queue) {
 		WARN_ON(tid->ac->txq != txctl->txq);
 
 		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
@@ -2207,7 +2270,7 @@ int ath_tx_start(struct ieee80211_hw *hw
 		TX_STAT_INC(txq->axq_qnum, a_queued_sw);
 		__skb_queue_tail(&tid->buf_q, skb);
 		if (!txctl->an->sleeping)
-			ath_tx_queue_tid(txq, tid);
+			ath_tx_queue_tid(sc, txq, tid);
 
 		ath_txq_schedule(sc, txq);
 		goto out;
@@ -2253,8 +2316,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw
 	int max_duration;
 
 	max_duration =
-		sc->cur_beacon_conf.beacon_interval * 1000 *
-		sc->cur_beacon_conf.dtim_period / ATH_BCBUF;
+		sc->cur_chan->beacon.beacon_interval * 1000 *
+		sc->cur_chan->beacon.dtim_period / ATH_BCBUF;
 
 	do {
 		struct ath_frame_info *fi = get_frame_info(skb);
@@ -2569,6 +2632,8 @@ void ath_tx_edma_tasklet(struct ath_soft
 			sc->beacon.tx_processed = true;
 			sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
 
+			ath_chanctx_event(sc, NULL,
+					  ATH_CHANCTX_EVENT_BEACON_SENT);
 			ath9k_csa_update(sc);
 			continue;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/ath.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/ath.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/ath.h	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,7 @@ enum ath_op_flags {
 	ATH_OP_PRIM_STA_VIF,
 	ATH_OP_HW_RESET,
 	ATH_OP_SCANNING,
+	ATH_OP_MULTI_CHANNEL,
 };
 
 enum ath_bus_type {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/carl9170.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/carl9170.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/carl9170.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/carl9170.h	2014-09-28 17:29:07.000000000 -0400
@@ -256,6 +256,7 @@ struct ar9170 {
 	atomic_t rx_work_urbs;
 	atomic_t rx_pool_urbs;
 	kernel_ulong_t features;
+	bool usb_ep_cmd_is_bulk;
 
 	/* firmware settings */
 	struct completion fw_load_wait;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/phy.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/phy.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -1139,7 +1139,6 @@ static int carl9170_set_freq_cal_data(st
 
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	for (; i >= 0; i--) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/carl9170/usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/carl9170/usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *a
 		goto err_free;
 	}
 
-	usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
-		AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
-		carl9170_usb_cmd_complete, ar, 1);
+	if (ar->usb_ep_cmd_is_bulk)
+		usb_fill_bulk_urb(urb, ar->udev,
+				  usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD),
+				  cmd, cmd->hdr.len + 4,
+				  carl9170_usb_cmd_complete, ar);
+	else
+		usb_fill_int_urb(urb, ar->udev,
+				 usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD),
+				 cmd, cmd->hdr.len + 4,
+				 carl9170_usb_cmd_complete, ar, 1);
 
 	if (free_buf)
 		urb->transfer_flags |= URB_FREE_BUFFER;
@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(
 static int carl9170_usb_probe(struct usb_interface *intf,
 			      const struct usb_device_id *id)
 {
+	struct usb_endpoint_descriptor *ep;
 	struct ar9170 *ar;
 	struct usb_device *udev;
-	int err;
+	int i, err;
 
 	err = usb_reset_device(interface_to_usbdev(intf));
 	if (err)
@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb
 	ar->intf = intf;
 	ar->features = id->driver_info;
 
+	/* We need to remember the type of endpoint 4 because it differs
+	 * between high- and full-speed configuration. The high-speed
+	 * configuration specifies it as interrupt and the full-speed
+	 * configuration as bulk endpoint. This information is required
+	 * later when sending urbs to that endpoint.
+	 */
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) {
+		ep = &intf->cur_altsetting->endpoint[i].desc;
+
+		if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD &&
+		    usb_endpoint_dir_out(ep) &&
+		    usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK)
+			ar->usb_ep_cmd_is_bulk = true;
+	}
+
 	usb_set_intfdata(intf, ar);
 	SET_IEEE80211_DEV(ar->hw, &intf->dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wcn36xx/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wcn36xx/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wcn36xx/main.c	2014-08-07 04:57:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wcn36xx/main.c	2014-09-28 21:40:07.000000000 -0400
@@ -488,7 +488,6 @@ static int wcn36xx_set_key(struct ieee80
 		wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
 		ret = -EOPNOTSUPP;
 		goto out;
-		break;
 	}
 
 out:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/cfg80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/cfg80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/cfg80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/cfg80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -104,8 +104,8 @@ int wil_iftype_nl2wmi(enum nl80211_iftyp
 	return -EOPNOTSUPP;
 }
 
-static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
-			      struct station_info *sinfo)
+int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+		       struct station_info *sinfo)
 {
 	struct wmi_notify_req_cmd cmd = {
 		.cid = cid,
@@ -287,6 +287,7 @@ static int wil_cfg80211_scan(struct wiph
 		return -EBUSY;
 	}
 
+	wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
 	wil->scan_request = request;
 	mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
 
@@ -443,15 +444,15 @@ static int wil_cfg80211_disconnect(struc
 	return rc;
 }
 
-static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
-				struct wireless_dev *wdev,
-				struct cfg80211_mgmt_tx_params *params,
-				u64 *cookie)
+int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+			 struct cfg80211_mgmt_tx_params *params,
+			 u64 *cookie)
 {
 	const u8 *buf = params->buf;
 	size_t len = params->len;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int rc;
+	bool tx_status = false;
 	struct ieee80211_mgmt *mgmt_frame = (void *)buf;
 	struct wmi_sw_tx_req_cmd *cmd;
 	struct {
@@ -460,8 +461,10 @@ static int wil_cfg80211_mgmt_tx(struct w
 	} __packed evt;
 
 	cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
-	if (!cmd)
-		return -ENOMEM;
+	if (!cmd) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
 	cmd->len = cpu_to_le16(len);
@@ -470,10 +473,12 @@ static int wil_cfg80211_mgmt_tx(struct w
 	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
 	if (rc == 0)
-		rc = evt.evt.status;
+		tx_status = !evt.evt.status;
 
 	kfree(cmd);
-
+ out:
+	cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
+				tx_status, GFP_KERNEL);
 	return rc;
 }
 
@@ -562,6 +567,34 @@ static int wil_cancel_remain_on_channel(
 	return rc;
 }
 
+static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
+{
+	print_hex_dump_bytes("head     ", DUMP_PREFIX_OFFSET,
+			     b->head, b->head_len);
+	print_hex_dump_bytes("tail     ", DUMP_PREFIX_OFFSET,
+			     b->tail, b->tail_len);
+	print_hex_dump_bytes("BCON IE  ", DUMP_PREFIX_OFFSET,
+			     b->beacon_ies, b->beacon_ies_len);
+	print_hex_dump_bytes("PROBE    ", DUMP_PREFIX_OFFSET,
+			     b->probe_resp, b->probe_resp_len);
+	print_hex_dump_bytes("PROBE IE ", DUMP_PREFIX_OFFSET,
+			     b->proberesp_ies, b->proberesp_ies_len);
+	print_hex_dump_bytes("ASSOC IE ", DUMP_PREFIX_OFFSET,
+			     b->assocresp_ies, b->assocresp_ies_len);
+}
+
+static void wil_print_crypto(struct wil6210_priv *wil,
+			     struct cfg80211_crypto_settings *c)
+{
+	wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n",
+		     c->wpa_versions, c->cipher_group);
+	wil_dbg_misc(wil, "Pairwise ciphers [%d]\n", c->n_ciphers_pairwise);
+	wil_dbg_misc(wil, "AKM suites [%d]\n", c->n_akm_suites);
+	wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n",
+		     c->control_port, be16_to_cpu(c->control_port_ethertype),
+		     c->control_port_no_encrypt);
+}
+
 static int wil_fix_bcon(struct wil6210_priv *wil,
 			struct cfg80211_beacon_data *bcon)
 {
@@ -595,8 +628,11 @@ static int wil_cfg80211_start_ap(struct
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	struct ieee80211_channel *channel = info->chandef.chan;
 	struct cfg80211_beacon_data *bcon = &info->beacon;
+	struct cfg80211_crypto_settings *crypto = &info->crypto;
 	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
 
+	wil_dbg_misc(wil, "%s()\n", __func__);
+
 	if (!channel) {
 		wil_err(wil, "AP: No channel???\n");
 		return -EINVAL;
@@ -604,11 +640,19 @@ static int wil_cfg80211_start_ap(struct
 
 	wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
 		     channel->center_freq, info->privacy ? "secure" : "open");
+	wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
+		     info->privacy, info->auth_type);
+	wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
+		     info->dtim_period);
 	print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
 			     info->ssid, info->ssid_len);
+	wil_print_bcon_data(bcon);
+	wil_print_crypto(wil, crypto);
 
-	if (wil_fix_bcon(wil, bcon))
+	if (wil_fix_bcon(wil, bcon)) {
 		wil_dbg_misc(wil, "Fixed bcon\n");
+		wil_print_bcon_data(bcon);
+	}
 
 	mutex_lock(&wil->mutex);
 
@@ -663,6 +707,8 @@ static int wil_cfg80211_stop_ap(struct w
 	int rc = 0;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
+	wil_dbg_misc(wil, "%s()\n", __func__);
+
 	mutex_lock(&wil->mutex);
 
 	rc = wmi_pcp_stop(wil);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/debugfs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
+#include <linux/power_supply.h>
 
 #include "wil6210.h"
 #include "txrx.h"
@@ -69,14 +70,32 @@ static int wil_vring_debugfs_show(struct
 
 	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
 		struct vring *vring = &(wil->vring_tx[i]);
+		struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+
 		if (vring->va) {
 			int cid = wil->vring2cid_tid[i][0];
 			int tid = wil->vring2cid_tid[i][1];
+			u32 swhead = vring->swhead;
+			u32 swtail = vring->swtail;
+			int used = (vring->size + swhead - swtail)
+				   % vring->size;
+			int avail = vring->size - used - 1;
 			char name[10];
+			/* performance monitoring */
+			cycles_t now = get_cycles();
+			cycles_t idle = txdata->idle * 100;
+			cycles_t total = now - txdata->begin;
+
+			do_div(idle, total);
+			txdata->begin = now;
+			txdata->idle = 0ULL;
+
 			snprintf(name, sizeof(name), "tx_%2d", i);
 
-			seq_printf(s, "\n%pM CID %d TID %d\n",
-				   wil->sta[cid].addr, cid, tid);
+			seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
+				   wil->sta[cid].addr, cid, tid, used, avail,
+				   (int)idle);
+
 			wil_print_vring(s, wil, name, vring, '_', 'H');
 		}
 	}
@@ -231,6 +250,26 @@ static struct dentry *wil_debugfs_create
 				   &fops_iomem_x32);
 }
 
+static int wil_debugfs_ulong_set(void *data, u64 val)
+{
+	*(ulong *)data = val;
+	return 0;
+}
+static int wil_debugfs_ulong_get(void *data, u64 *val)
+{
+	*val = *(ulong *)data;
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
+			wil_debugfs_ulong_set, "%llu\n");
+
+static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
+					       struct dentry *parent,
+					       ulong *value)
+{
+	return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong);
+}
+
 static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
 				      const char *name,
 				      struct dentry *parent, u32 off)
@@ -284,11 +323,11 @@ static int wil6210_debugfs_create_ITR_CN
 	if (IS_ERR_OR_NULL(d))
 		return -ENODEV;
 
-	wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr +
+	wil_debugfs_create_iomem_x32("TRSH", S_IRUGO | S_IWUSR, d, wil->csr +
 				     HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
-	wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr +
+	wil_debugfs_create_iomem_x32("DATA", S_IRUGO | S_IWUSR, d, wil->csr +
 				     HOSTADDR(RGF_DMA_ITR_CNT_DATA));
-	wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr +
+	wil_debugfs_create_iomem_x32("CTL", S_IRUGO | S_IWUSR, d, wil->csr +
 				     HOSTADDR(RGF_DMA_ITR_CNT_CRL));
 
 	return 0;
@@ -397,6 +436,126 @@ static const struct file_operations fops
 	.write = wil_write_file_reset,
 	.open  = simple_open,
 };
+/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
+static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
+				   size_t len, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	int rc;
+	long channel;
+	bool on;
+
+	char *kbuf = kmalloc(len + 1, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+	if (copy_from_user(kbuf, buf, len)) {
+		kfree(kbuf);
+		return -EIO;
+	}
+
+	kbuf[len] = '\0';
+	rc = kstrtol(kbuf, 0, &channel);
+	kfree(kbuf);
+	if (rc)
+		return rc;
+
+	if ((channel < 0) || (channel > 4)) {
+		wil_err(wil, "Invalid channel %ld\n", channel);
+		return -EINVAL;
+	}
+	on = !!channel;
+
+	if (on) {
+		rc = wmi_set_channel(wil, (int)channel);
+		if (rc)
+			return rc;
+	}
+
+	rc = wmi_rxon(wil, on);
+	if (rc)
+		return rc;
+
+	return len;
+}
+
+static const struct file_operations fops_rxon = {
+	.write = wil_write_file_rxon,
+	.open  = simple_open,
+};
+/*---tx_mgmt---*/
+/* Write mgmt frame to this file to send it */
+static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
+				     size_t len, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	struct wiphy *wiphy = wil_to_wiphy(wil);
+	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct cfg80211_mgmt_tx_params params;
+	int rc;
+
+	void *frame = kmalloc(len, GFP_KERNEL);
+	if (!frame)
+		return -ENOMEM;
+
+	if (copy_from_user(frame, buf, len))
+		return -EIO;
+
+	params.buf = frame;
+	params.len = len;
+	params.chan = wdev->preset_chandef.chan;
+
+	rc = wil_cfg80211_mgmt_tx(wiphy, wdev, &params, NULL);
+
+	kfree(frame);
+	wil_info(wil, "%s() -> %d\n", __func__, rc);
+
+	return len;
+}
+
+static const struct file_operations fops_txmgmt = {
+	.write = wil_write_file_txmgmt,
+	.open  = simple_open,
+};
+
+/* Write WMI command (w/o mbox header) to this file to send it
+ * WMI starts from wil6210_mbox_hdr_wmi header
+ */
+static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
+				  size_t len, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	struct wil6210_mbox_hdr_wmi *wmi;
+	void *cmd;
+	int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
+	u16 cmdid;
+	int rc, rc1;
+
+	if (cmdlen <= 0)
+		return -EINVAL;
+
+	wmi = kmalloc(len, GFP_KERNEL);
+	if (!wmi)
+		return -ENOMEM;
+
+	rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
+	if (rc < 0)
+		return rc;
+
+	cmd = &wmi[1];
+	cmdid = le16_to_cpu(wmi->id);
+
+	rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
+	kfree(wmi);
+
+	wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1);
+
+	return rc;
+}
+
+static const struct file_operations fops_wmi = {
+	.write = wil_write_file_wmi,
+	.open  = simple_open,
+};
 
 static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
 			    const char *prefix)
@@ -600,8 +759,8 @@ static int wil_temp_debugfs_show(struct
 		return 0;
 	}
 
-	print_temp(s, "MAC temperature   :", t_m);
-	print_temp(s, "Radio temperature :", t_r);
+	print_temp(s, "T_mac   =", t_m);
+	print_temp(s, "T_radio =", t_r);
 
 	return 0;
 }
@@ -618,6 +777,130 @@ static const struct file_operations fops
 	.llseek		= seq_lseek,
 };
 
+/*---------freq------------*/
+static int wil_freq_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	struct wireless_dev *wdev = wil_to_wdev(wil);
+	u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
+
+	seq_printf(s, "Freq = %d\n", freq);
+
+	return 0;
+}
+
+static int wil_freq_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_freq_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_freq = {
+	.open		= wil_freq_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+/*---------link------------*/
+static int wil_link_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	struct station_info sinfo;
+	int i, rc;
+
+	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+		struct wil_sta_info *p = &wil->sta[i];
+		char *status = "unknown";
+		switch (p->status) {
+		case wil_sta_unused:
+			status = "unused   ";
+			break;
+		case wil_sta_conn_pending:
+			status = "pending  ";
+			break;
+		case wil_sta_connected:
+			status = "connected";
+			break;
+		}
+		seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
+			   (p->data_port_open ? " data_port_open" : ""));
+
+		if (p->status == wil_sta_connected) {
+			rc = wil_cid_fill_sinfo(wil, i, &sinfo);
+			if (rc)
+				return rc;
+
+			seq_printf(s, "  Tx_mcs = %d\n", sinfo.txrate.mcs);
+			seq_printf(s, "  Rx_mcs = %d\n", sinfo.rxrate.mcs);
+			seq_printf(s, "  SQ     = %d\n", sinfo.signal);
+		}
+	}
+
+	return 0;
+}
+
+static int wil_link_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_link_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_link = {
+	.open		= wil_link_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+/*---------info------------*/
+static int wil_info_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	struct net_device *ndev = wil_to_ndev(wil);
+	int is_ac = power_supply_is_system_supplied();
+	int rx = atomic_xchg(&wil->isr_count_rx, 0);
+	int tx = atomic_xchg(&wil->isr_count_tx, 0);
+	static ulong rxf_old, txf_old;
+	ulong rxf = ndev->stats.rx_packets;
+	ulong txf = ndev->stats.tx_packets;
+	unsigned int i;
+
+	/* >0 : AC; 0 : battery; <0 : error */
+	seq_printf(s, "AC powered : %d\n", is_ac);
+	seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old);
+	seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old);
+	rxf_old = rxf;
+	txf_old = txf;
+
+
+#define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
+	" " __stringify(x) : ""
+
+	for (i = 0; i < ndev->num_tx_queues; i++) {
+		struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
+		unsigned long state = txq->state;
+
+		seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state,
+			   CHECK_QSTATE(DRV_XOFF),
+			   CHECK_QSTATE(STACK_XOFF),
+			   CHECK_QSTATE(FROZEN)
+			  );
+	}
+#undef CHECK_QSTATE
+	return 0;
+}
+
+static int wil_info_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_info_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_info = {
+	.open		= wil_info_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
 /*---------Station matrix------------*/
 static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
 {
@@ -630,7 +913,7 @@ static void wil_print_rxtid(struct seq_f
 		else
 			seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
 	}
-	seq_puts(s, "]\n");
+	seq_printf(s, "] last drop 0x%03x\n", r->ssn_last_drop);
 }
 
 static int wil_sta_debugfs_show(struct seq_file *s, void *data)
@@ -682,6 +965,26 @@ static const struct file_operations fops
 };
 
 /*----------------*/
+static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
+				       struct dentry *dbg)
+{
+	int i;
+	char name[32];
+
+	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+		struct debugfs_blob_wrapper *blob = &wil->blobs[i];
+		const struct fw_map *map = &fw_mapping[i];
+
+		if (!map->name)
+			continue;
+
+		blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
+		blob->size = map->to - map->from;
+		snprintf(name, sizeof(name), "blob_%s", map->name);
+		wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
+	}
+}
+
 int wil6210_debugfs_init(struct wil6210_priv *wil)
 {
 	struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
@@ -703,6 +1006,10 @@ int wil6210_debugfs_init(struct wil6210_
 	debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
 	debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
 			   &wil->secure_pcp);
+	wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
+				 &wil->status);
+	debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version);
+	debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version);
 
 	wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
 				   HOSTADDR(RGF_USER_USER_ICR));
@@ -715,40 +1022,22 @@ int wil6210_debugfs_init(struct wil6210_
 	wil6210_debugfs_create_pseudo_ISR(wil, dbg);
 	wil6210_debugfs_create_ITR_CNT(wil, dbg);
 
+	wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg,
+				     wil->csr +
+				     HOSTADDR(RGF_USER_USAGE_1));
 	debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
 	debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
 
 	debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+	debugfs_create_file("rxon", S_IWUSR, dbg, wil, &fops_rxon);
+	debugfs_create_file("tx_mgmt", S_IWUSR, dbg, wil, &fops_txmgmt);
+	debugfs_create_file("wmi_send", S_IWUSR, dbg, wil, &fops_wmi);
 	debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
+	debugfs_create_file("freq", S_IRUGO, dbg, wil, &fops_freq);
+	debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
+	debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
 
-	wil->rgf_blob.data = (void * __force)wil->csr + 0;
-	wil->rgf_blob.size = 0xa000;
-	wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
-
-	wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
-	wil->fw_code_blob.size = 0x40000;
-	wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
-				  &wil->fw_code_blob);
-
-	wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
-	wil->fw_data_blob.size = 0x8000;
-	wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
-				  &wil->fw_data_blob);
-
-	wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
-	wil->fw_peri_blob.size = 0x18000;
-	wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
-				  &wil->fw_peri_blob);
-
-	wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
-	wil->uc_code_blob.size = 0x10000;
-	wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
-				  &wil->uc_code_blob);
-
-	wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
-	wil->uc_data_blob.size = 0x4000;
-	wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
-				  &wil->uc_data_blob);
+	wil6210_debugfs_init_blobs(wil, dbg);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/interrupt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/interrupt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/interrupt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/interrupt.c	2014-09-28 17:29:07.000000000 -0400
@@ -208,6 +208,7 @@ static irqreturn_t wil6210_irq_rx(int ir
 
 	/* Rx IRQ will be enabled when NAPI processing finished */
 
+	atomic_inc(&wil->isr_count_rx);
 	return IRQ_HANDLED;
 }
 
@@ -246,6 +247,7 @@ static irqreturn_t wil6210_irq_tx(int ir
 
 	/* Tx IRQ will be enabled when NAPI processing finished */
 
+	atomic_inc(&wil->isr_count_tx);
 	return IRQ_HANDLED;
 }
 
@@ -257,6 +259,7 @@ static void wil_notify_fw_error(struct w
 		[1] = "EVENT=FW_ERROR",
 		[2] = NULL,
 	};
+	wil_err(wil, "Notify about firmware error\n");
 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,11 +61,24 @@ void wil_memcpy_toio_32(volatile void __
 static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
 {
 	uint i;
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
 	struct wil_sta_info *sta = &wil->sta[cid];
+	wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
+		     sta->status);
 
 	sta->data_port_open = false;
 	if (sta->status != wil_sta_unused) {
 		wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
+		switch (wdev->iftype) {
+		case NL80211_IFTYPE_AP:
+		case NL80211_IFTYPE_P2P_GO:
+			/* AP-like interface */
+			cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
+			break;
+		default:
+			break;
+		}
 		sta->status = wil_sta_unused;
 	}
 
@@ -119,11 +132,6 @@ static void _wil6210_disconnect(struct w
 		clear_bit(wil_status_fwconnecting, &wil->status);
 		break;
 	default:
-		/* AP-like interface and monitor:
-		 * never scan, always connected
-		 */
-		if (bssid)
-			cfg80211_del_sta(ndev, bssid, GFP_KERNEL);
 		break;
 	}
 }
@@ -306,8 +314,9 @@ static void wil_target_reset(struct wil6
 	int delay = 0;
 	u32 hw_state;
 	u32 rev_id;
+	bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
 
-	wil_dbg_misc(wil, "Resetting...\n");
+	wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
 
 	/* register read */
 #define R(a) ioread32(wil->csr + HOSTADDR(a))
@@ -320,35 +329,59 @@ static void wil_target_reset(struct wil6
 
 	wil->hw_version = R(RGF_USER_FW_REV_ID);
 	rev_id = wil->hw_version & 0xff;
+
+	/* Clear MAC link up */
+	S(RGF_HP_CTRL, BIT(15));
 	/* hpal_perst_from_pad_src_n_mask */
 	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
 	/* car_perst_rst_src_n_mask */
 	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
 	wmb(); /* order is important here */
 
+	if (is_sparrow) {
+		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
+		wmb(); /* order is important here */
+	}
+
 	W(RGF_USER_MAC_CPU_0,  BIT(1)); /* mac_cpu_man_rst */
 	W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
 	wmb(); /* order is important here */
 
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
-	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000B0 : 0x00000170);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
 	wmb(); /* order is important here */
 
+	if (is_sparrow) {
+		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
+		wmb(); /* order is important here */
+	}
+
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
 	wmb(); /* order is important here */
 
-	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
-	if (rev_id == 1) {
-		W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
-	} else {
-		W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
+	if (is_sparrow) {
+		W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
+		/* reset A2 PCIE AHB */
 		W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
+
+	} else {
+		W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
+		if (rev_id == 1) {
+			/* reset A1 BOTH PCIE AHB & PCIE RGF */
+			W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
+		} else {
+			W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
+			W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
+		}
+
 	}
+
+	/* TODO: check order here!!! Erez code is different */
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
 	wmb(); /* order is important here */
 
@@ -363,7 +396,8 @@ static void wil_target_reset(struct wil6
 		}
 	} while (hw_state != HW_MACHINE_BOOT_DONE);
 
-	if (rev_id == 2)
+	/* TODO: Erez check rev_id != 1 */
+	if (!is_sparrow && (rev_id != 1))
 		W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
 
 	C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
@@ -465,6 +499,7 @@ void wil_link_on(struct wil6210_priv *wi
 	wil_dbg_misc(wil, "%s()\n", __func__);
 
 	netif_carrier_on(ndev);
+	wil_dbg_misc(wil, "netif_tx_wake : link on\n");
 	netif_tx_wake_all_queues(ndev);
 }
 
@@ -475,6 +510,7 @@ void wil_link_off(struct wil6210_priv *w
 	wil_dbg_misc(wil, "%s()\n", __func__);
 
 	netif_tx_stop_all_queues(ndev);
+	wil_dbg_misc(wil, "netif_tx_stop : link off\n");
 	netif_carrier_off(ndev);
 }
 
@@ -552,6 +588,8 @@ static int __wil_down(struct wil6210_pri
 	napi_disable(&wil->napi_tx);
 
 	if (wil->scan_request) {
+		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
+			     wil->scan_request);
 		del_timer_sync(&wil->scan_timer);
 		cfg80211_scan_done(wil->scan_request, true);
 		wil->scan_request = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/netdev.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/netdev.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/netdev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/netdev.c	2014-09-28 17:29:07.000000000 -0400
@@ -132,7 +132,7 @@ void *wil_if_alloc(struct device *dev, v
 	ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
 	cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
 
-	ndev = alloc_netdev(0, "wlan%d", ether_setup);
+	ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup);
 	if (!ndev) {
 		dev_err(dev, "alloc_netdev_mqs failed\n");
 		rc = -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/pcie_bus.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/pcie_bus.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/pcie_bus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/pcie_bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/debugfs.h>
 #include <linux/pci.h>
 #include <linux/moduleparam.h>
 
@@ -27,11 +26,22 @@ MODULE_PARM_DESC(use_msi,
 		 " Use MSI interrupt: "
 		 "0 - don't, 1 - (default) - single, or 3");
 
+static bool debug_fw; /* = false; */
+module_param(debug_fw, bool, S_IRUGO);
+MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug");
+
 /* Bus ops */
 static int wil_if_pcie_enable(struct wil6210_priv *wil)
 {
 	struct pci_dev *pdev = wil->pdev;
 	int rc;
+	/* on platforms with buggy ACPI, pdev->msi_enabled may be set to
+	 * allow pci_enable_device to work. This indicates INTx was not routed
+	 * and only MSI should be used
+	 */
+	int msi_only = pdev->msi_enabled;
+
+	pdev->msi_enabled = 0;
 
 	pci_set_master(pdev);
 
@@ -63,6 +73,12 @@ static int wil_if_pcie_enable(struct wil
 
 	wil->n_msi = use_msi;
 
+	if ((wil->n_msi == 0) && msi_only) {
+		wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
+		rc = -ENODEV;
+		goto stop_master;
+	}
+
 	rc = wil6210_init_irq(wil, pdev->irq);
 	if (rc)
 		goto stop_master;
@@ -71,6 +87,8 @@ static int wil_if_pcie_enable(struct wil
 	mutex_lock(&wil->mutex);
 	rc = wil_reset(wil);
 	mutex_unlock(&wil->mutex);
+	if (debug_fw)
+		rc = 0;
 	if (rc)
 		goto release_irq;
 
@@ -104,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev
 	struct wil6210_priv *wil;
 	struct device *dev = &pdev->dev;
 	void __iomem *csr;
+	struct wil_board *board = (struct wil_board *)id->driver_data;
 	int rc;
 
 	/* check HW */
-	dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
+	dev_info(&pdev->dev, WIL_NAME
+		 " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name,
 		 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
 
 	if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
@@ -119,9 +139,16 @@ static int wil_pcie_probe(struct pci_dev
 
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		dev_err(&pdev->dev, "pci_enable_device failed\n");
-		return -ENODEV;
+		dev_err(&pdev->dev,
+			"pci_enable_device failed, retry with MSI only\n");
+		/* Work around for platforms that can't allocate IRQ:
+		 * retry with MSI only
+		 */
+		pdev->msi_enabled = 1;
+		rc = pci_enable_device(pdev);
 	}
+	if (rc)
+		return -ENODEV;
 	/* rollback to err_disable_pdev */
 
 	rc = pci_request_region(pdev, 0, WIL_NAME);
@@ -150,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev
 
 	pci_set_drvdata(pdev, wil);
 	wil->pdev = pdev;
+	wil->board = board;
 
 	wil6210_clear_irq(wil);
 	/* FW should raise IRQ when ready */
@@ -200,8 +228,21 @@ static void wil_pcie_remove(struct pci_d
 	pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
-	{ PCI_DEVICE(0x1ae9, 0x0301) },
+static const struct wil_board wil_board_marlon = {
+	.board = WIL_BOARD_MARLON,
+	.name = "marlon",
+};
+
+static const struct wil_board wil_board_sparrow = {
+	.board = WIL_BOARD_SPARROW,
+	.name = "sparrow",
+};
+
+static const struct pci_device_id wil6210_pcie_ids[] = {
+	{ PCI_DEVICE(0x1ae9, 0x0301),
+	  .driver_data = (kernel_ulong_t)&wil_board_marlon },
+	{ PCI_DEVICE(0x1ae9, 0x0310),
+	  .driver_data = (kernel_ulong_t)&wil_board_sparrow },
 	{ /* end: all zeroes */	},
 };
 MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/rx_reorder.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/rx_reorder.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/rx_reorder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/rx_reorder.c	2014-09-28 17:29:07.000000000 -0400
@@ -116,6 +116,7 @@ void wil_rx_reorder(struct wil6210_priv
 
 	/* frame with out of date sequence number */
 	if (seq_less(seq, r->head_seq_num)) {
+		r->ssn_last_drop = seq;
 		dev_kfree_skb(skb);
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/txrx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/txrx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -525,6 +525,17 @@ void wil_netif_rx_any(struct sk_buff *sk
 		ndev->stats.rx_bytes += len;
 		stats->rx_bytes += len;
 	}
+	{
+		static const char * const gro_res_str[] = {
+			[GRO_MERGED]		= "GRO_MERGED",
+			[GRO_MERGED_FREE]	= "GRO_MERGED_FREE",
+			[GRO_HELD]		= "GRO_HELD",
+			[GRO_NORMAL]		= "GRO_NORMAL",
+			[GRO_DROP]		= "GRO_DROP",
+		};
+		wil_dbg_txrx(wil, "Rx complete %d bytes => %s,\n",
+			     len, gro_res_str[rc]);
+	}
 }
 
 /**
@@ -760,7 +771,7 @@ static struct vring *wil_tx_bcast(struct
 		goto found;
 	}
 
-	wil_err(wil, "Tx while no vrings active?\n");
+	wil_dbg_txrx(wil, "Tx while no vrings active?\n");
 
 	return NULL;
 
@@ -881,6 +892,7 @@ static int wil_tx_vring(struct wil6210_p
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	uint f = 0;
 	int vring_index = vring - wil->vring_tx;
+	struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
 	uint i = swhead;
 	dma_addr_t pa;
 
@@ -953,6 +965,9 @@ static int wil_tx_vring(struct wil6210_p
 	wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
 			  (const void *)d, sizeof(*d), false);
 
+	if (wil_vring_is_empty(vring)) /* performance monitoring */
+		txdata->idle += get_cycles() - txdata->last_idle;
+
 	/* advance swhead */
 	wil_vring_advance_head(vring, nr_frags + 1);
 	wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
@@ -1016,15 +1031,17 @@ netdev_tx_t wil_start_xmit(struct sk_buf
 		vring = wil_tx_bcast(wil, skb);
 	}
 	if (!vring) {
-		wil_err(wil, "No Tx VRING found for %pM\n", eth->h_dest);
+		wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
 		goto drop;
 	}
 	/* set up vring entry */
 	rc = wil_tx_vring(wil, vring, skb);
 
 	/* do we still have enough room in the vring? */
-	if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))
+	if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring)) {
 		netif_tx_stop_all_queues(wil_to_ndev(wil));
+		wil_dbg_txrx(wil, "netif_tx_stop : ring full\n");
+	}
 
 	switch (rc) {
 	case 0:
@@ -1091,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv
 		while (vring->swtail != new_swtail) {
 			struct vring_tx_desc dd, *d = &dd;
 			u16 dmalen;
-			struct wil_ctx *ctx = &vring->ctx[vring->swtail];
-			struct sk_buff *skb = ctx->skb;
+			struct sk_buff *skb;
+
+			ctx = &vring->ctx[vring->swtail];
+			skb = ctx->skb;
 			_d = &vring->va[vring->swtail].tx;
 
 			*d = *_d;
@@ -1132,8 +1151,16 @@ int wil_tx_complete(struct wil6210_priv
 			done++;
 		}
 	}
-	if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring))
+
+	if (wil_vring_is_empty(vring)) { /* performance monitoring */
+		wil_dbg_txrx(wil, "Ring[%2d] empty\n", ringid);
+		txdata->last_idle = get_cycles();
+	}
+
+	if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring)) {
+		wil_dbg_txrx(wil, "netif_tx_wake : ring not full\n");
 		netif_tx_wake_all_queues(wil_to_ndev(wil));
+	}
 
 	return done;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/wil6210.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/wil6210.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/wil6210.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/wil6210.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,9 +20,17 @@
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
+#include <linux/timex.h>
 
 #define WIL_NAME "wil6210"
 
+struct wil_board {
+	int board;
+#define WIL_BOARD_MARLON	(1)
+#define WIL_BOARD_SPARROW	(2)
+	const char * const name;
+};
+
 /**
  * extract bits [@b0:@b1] (inclusive) from the value @x
  * it should be @b0 <= @b1, or result is incorrect
@@ -77,6 +85,7 @@ struct RGF_ICR {
 } __packed;
 
 /* registers - FW addresses */
+#define RGF_USER_USAGE_1		(0x880004)
 #define RGF_USER_HW_MACHINE_STATE	(0x8801dc)
 	#define HW_MACHINE_BOOT_DONE	(0x3fffffd)
 #define RGF_USER_USER_CPU_0		(0x8801e0)
@@ -92,6 +101,7 @@ struct RGF_ICR {
 #define RGF_USER_CLKS_CTL_SW_RST_MASK_0	(0x880b14)
 #define RGF_USER_USER_ICR		(0x880b4c) /* struct RGF_ICR */
 	#define BIT_USER_USER_ICR_SW_INT_2	BIT(18)
+#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0	(0x880c18)
 
 #define RGF_DMA_EP_TX_ICR		(0x881bb4) /* struct RGF_ICR */
 	#define BIT_DMA_EP_TX_ICR_TX_DONE	BIT(0)
@@ -120,6 +130,7 @@ struct RGF_ICR {
 	#define BIT_DMA_PSEUDO_CAUSE_TX		BIT(1)
 	#define BIT_DMA_PSEUDO_CAUSE_MISC	BIT(2)
 
+#define RGF_HP_CTRL			(0x88265c)
 #define RGF_PCIE_LOS_COUNTER_CTL	(0x882dc4)
 
 /* popular locations */
@@ -134,6 +145,14 @@ struct RGF_ICR {
 #define ISR_MISC_FW_ERROR	BIT_DMA_EP_MISC_ICR_FW_INT(3)
 
 /* Hardware definitions end */
+struct fw_map {
+	u32 from; /* linker address - from, inclusive */
+	u32 to;   /* linker address - to, exclusive */
+	u32 host; /* PCI/Host address - BAR0 + 0x880000 */
+	const char *name; /* for debugfs */
+};
+/* array size should be in sync with actual definition in the wmi.c */
+extern const struct fw_map fw_mapping[7];
 
 /**
  * mk_cidxtid - construct @cidxtid field
@@ -251,7 +270,7 @@ struct vring {
  */
 struct vring_tx_data {
 	int enabled;
-
+	cycles_t idle, last_idle, begin;
 };
 
 enum { /* for wil6210_priv.status */
@@ -303,6 +322,7 @@ struct wil_tid_ampdu_rx {
 	u16 ssn;
 	u16 buf_size;
 	u16 timeout;
+	u16 ssn_last_drop;
 	u8 dialog_token;
 	bool first_time; /* is it 1-st time this buffer used? */
 };
@@ -363,6 +383,7 @@ struct wil6210_priv {
 	ulong status;
 	u32 fw_version;
 	u32 hw_version;
+	struct wil_board *board;
 	u8 n_mids; /* number of additional MIDs as reported by FW */
 	int recovery_count; /* num of FW recovery attempts in a short time */
 	unsigned long last_fw_recovery; /* jiffies of last fw recovery */
@@ -410,14 +431,10 @@ struct wil6210_priv {
 	struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
 	/* statistics */
 	struct wil6210_stats stats;
+	atomic_t isr_count_rx, isr_count_tx;
 	/* debugfs */
 	struct dentry *debug;
-	struct debugfs_blob_wrapper fw_code_blob;
-	struct debugfs_blob_wrapper fw_data_blob;
-	struct debugfs_blob_wrapper fw_peri_blob;
-	struct debugfs_blob_wrapper uc_code_blob;
-	struct debugfs_blob_wrapper uc_data_blob;
-	struct debugfs_blob_wrapper rgf_blob;
+	struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
 };
 
 #define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -504,9 +521,14 @@ int wil6210_init_irq(struct wil6210_priv
 void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
 void wil6210_disable_irq(struct wil6210_priv *wil);
 void wil6210_enable_irq(struct wil6210_priv *wil);
+int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+			 struct cfg80211_mgmt_tx_params *params,
+			 u64 *cookie);
 
 int wil6210_debugfs_init(struct wil6210_priv *wil);
 void wil6210_debugfs_remove(struct wil6210_priv *wil);
+int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+		       struct station_info *sinfo);
 
 struct wireless_dev *wil_cfg80211_init(struct device *dev);
 void wil_wdev_free(struct wil6210_priv *wil);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/wmi.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/wmi.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ath/wil6210/wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ath/wil6210/wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,17 +65,17 @@
 
 /**
  * @fw_mapping provides memory remapping table
+ *
+ * array size should be in sync with the declaration in the wil6210.h
  */
-static const struct {
-	u32 from; /* linker address - from, inclusive */
-	u32 to;   /* linker address - to, exclusive */
-	u32 host; /* PCI/Host address - BAR0 + 0x880000 */
-} fw_mapping[] = {
-	{0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */
-	{0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */
-	{0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */
-	{0x880000, 0x88a000, 0x880000}, /* various RGF */
-	{0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */
+const struct fw_map fw_mapping[] = {
+	{0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM      256k */
+	{0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM       32k */
+	{0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
+	{0x880000, 0x88a000, 0x880000, "rgf"},     /* various RGF       40k */
+	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table          4k */
+	{0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf       4k */
+	{0x8c0000, 0x949000, 0x8c0000, "upper"},   /* upper area       548k */
 	/*
 	 * 920000..930000 ucode code RAM
 	 * 930000..932000 ucode data RAM
@@ -327,6 +327,17 @@ static void wmi_evt_rx_mgmt(struct wil62
 
 	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
 		struct cfg80211_bss *bss;
+		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
+		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
+		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
+		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
+		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
+						 u.beacon.variable);
+		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
+		wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
+		wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
+		wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
+				 ie_len, true);
 
 		bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
 						d_len, signal, GFP_KERNEL);
@@ -351,6 +362,9 @@ static void wmi_evt_scan_complete(struct
 		bool aborted = (data->status != WMI_SCAN_SUCCESS);
 
 		wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+		wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
+			     wil->scan_request, aborted);
+
 		del_timer_sync(&wil->scan_timer);
 		cfg80211_scan_done(wil->scan_request, aborted);
 		wil->scan_request = NULL;
@@ -668,14 +682,12 @@ void wmi_recv_cmd(struct wil6210_priv *w
 
 	for (n = 0;; n++) {
 		u16 len;
+		bool q;
 
 		r->head = ioread32(wil->csr + HOST_MBOX +
 				   offsetof(struct wil6210_mbox_ctl, rx.head));
-		if (r->tail == r->head) {
-			if (n == 0)
-				wil_dbg_wmi(wil, "No events?\n");
-			return;
-		}
+		if (r->tail == r->head)
+			break;
 
 		wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
 			    r->head, r->tail);
@@ -684,14 +696,14 @@ void wmi_recv_cmd(struct wil6210_priv *w
 				     sizeof(struct wil6210_mbox_ring_desc));
 		if (d_tail.sync == 0) {
 			wil_err(wil, "Mbox evt not owned by FW?\n");
-			return;
+			break;
 		}
 
 		/* read cmd header from descriptor */
 		if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
 			wil_err(wil, "Mbox evt at 0x%08x?\n",
 				le32_to_cpu(d_tail.addr));
-			return;
+			break;
 		}
 		len = le16_to_cpu(hdr.len);
 		wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
@@ -705,7 +717,7 @@ void wmi_recv_cmd(struct wil6210_priv *w
 					     event.wmi) + len, 4),
 			      GFP_KERNEL);
 		if (!evt)
-			return;
+			break;
 
 		evt->event.hdr = hdr;
 		cmd = (void *)&evt->event.wmi;
@@ -737,14 +749,11 @@ void wmi_recv_cmd(struct wil6210_priv *w
 		spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 		list_add_tail(&evt->list, &wil->pending_wmi_ev);
 		spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
-		{
-			int q =	queue_work(wil->wmi_wq,
-					   &wil->wmi_event_worker);
-			wil_dbg_wmi(wil, "queue_work -> %d\n", q);
-		}
+		q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
+		wil_dbg_wmi(wil, "queue_work -> %d\n", q);
 	}
-	if (n > 1)
-		wil_dbg_wmi(wil, "%s -> %d events processed\n", __func__, n);
+	/* normally, 1 event per IRQ should be processed */
+	wil_dbg_wmi(wil, "%s -> %d events queued\n", __func__, n);
 }
 
 int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/atmel.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/atmel.c
--- linux-libre-3.16-gnu/drivers/net/wireless/atmel.c	2014-08-07 04:53:29.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/atmel.c	2014-09-28 21:35:18.000000000 -0400
@@ -2583,11 +2583,11 @@ static const iw_handler atmel_private_ha
 	NULL,				/* SIOCIWFIRSTPRIV */
 };
 
-typedef struct atmel_priv_ioctl {
+struct atmel_priv_ioctl {
 	char id[32];
 	unsigned char __user *data;
 	unsigned short len;
-} atmel_priv_ioctl;
+};
 
 #define ATMELFWL	SIOCIWFIRSTPRIV
 #define ATMELIDIFC	ATMELFWL + 1
@@ -2600,7 +2600,7 @@ static const struct iw_priv_args atmel_p
 		.cmd = ATMELFWL,
 		.set_args = IW_PRIV_TYPE_BYTE
 				| IW_PRIV_SIZE_FIXED
-				| sizeof (atmel_priv_ioctl),
+				| sizeof(struct atmel_priv_ioctl),
 		.get_args = IW_PRIV_TYPE_NONE,
 		.name = "atmelfwl"
 	}, {
@@ -2630,7 +2630,7 @@ static int atmel_ioctl(struct net_device
 {
 	int i, rc = 0;
 	struct atmel_private *priv = netdev_priv(dev);
-	atmel_priv_ioctl com;
+	struct atmel_priv_ioctl com;
 	struct iwreq *wrq = (struct iwreq *) rq;
 	unsigned char *new_firmware;
 	char domain[REGDOMAINSZ + 1];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/atmel_pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/atmel_pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/atmel_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/atmel_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@ MODULE_DESCRIPTION("Support for Atmel at
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards");
 
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
 	{ 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -122,36 +122,41 @@ config B43_PIO
 	select SSB_BLOCKIO
 	default y
 
+config B43_PHY_G
+	bool "Support for G-PHY (802.11g) devices"
+	depends on B43 && B43_SSB
+	default y
+	---help---
+	  This PHY type can be found in the following chipsets:
+	  PCI: BCM4306, BCM4311, BCM4318
+	  SoC: BCM4712, BCM5352E
+
 config B43_PHY_N
-	bool "Support for 802.11n (N-PHY) devices"
+	bool "Support for N-PHY (the main 802.11n series) devices"
 	depends on B43
 	default y
 	---help---
-	  Support for the N-PHY.
-
-	  This enables support for devices with N-PHY.
-
-	  Say N if you expect high stability and performance. Saying Y will not
-	  affect other devices support and may provide support for basic needs.
+	  This PHY type can be found in the following chipsets:
+	  PCI: BCM4321, BCM4322,
+	       BCM43222, BCM43224, BCM43225,
+	       BCM43131, BCM43217, BCM43227, BCM43228
+	  SoC: BCM4716, BCM4717, BCM4718, BCM5356, BCM5357, BCM5358
 
 config B43_PHY_LP
-	bool "Support for low-power (LP-PHY) devices"
+	bool "Support for LP-PHY (low-power 802.11g) devices"
 	depends on B43 && B43_SSB
 	default y
 	---help---
-	  Support for the LP-PHY.
 	  The LP-PHY is a low-power PHY built into some notebooks
 	  and embedded devices. It supports 802.11a/b/g
 	  (802.11a support is optional, and currently disabled).
 
 config B43_PHY_HT
-	bool "Support for HT-PHY (high throughput) devices"
+	bool "Support for HT-PHY (high throughput 802.11n) devices"
 	depends on B43 && B43_BCMA
 	default y
 	---help---
-	  Support for the HT-PHY.
-
-	  Enables support for BCM4331 and possibly other chipsets with that PHY.
+	  This PHY type with 3x3:3 MIMO can be found in the BCM4331 PCI chipset.
 
 config B43_PHY_LCN
 	bool "Support for LCN-PHY devices (BROKEN)"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/main.c	2014-08-07 04:53:37.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/main.c	2014-09-28 21:35:26.000000000 -0400
@@ -116,7 +116,11 @@ static const struct bcma_device_id b43_b
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1E, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x28, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x2A, BCMA_ANY_CLASS),
 	BCMA_CORETABLE_END
 };
 MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
@@ -200,6 +204,9 @@ static struct ieee80211_channel b43_2ghz
 	CHAN2G(13, 2472, 0),
 	CHAN2G(14, 2484, 0),
 };
+
+/* No support for the last 3 channels (12, 13, 14) */
+#define b43_2ghz_chantable_limited_size		11
 #undef CHAN2G
 
 #define CHAN4G(_channel, _flags) {				\
@@ -277,6 +284,14 @@ static struct ieee80211_channel b43_5ghz
 	CHAN5G(182, 0),
 };
 
+static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = {
+	CHAN5G(36, 0),		CHAN5G(40, 0),
+	CHAN5G(44, 0),		CHAN5G(48, 0),
+	CHAN5G(149, 0),		CHAN5G(153, 0),
+	CHAN5G(157, 0),		CHAN5G(161, 0),
+	CHAN5G(165, 0),
+};
+
 static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
 	CHAN5G(34, 0),		CHAN5G(36, 0),
 	CHAN5G(38, 0),		CHAN5G(40, 0),
@@ -309,6 +324,14 @@ static struct ieee80211_supported_band b
 	.n_bitrates	= b43_a_ratetable_size,
 };
 
+static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
+	.band		= IEEE80211_BAND_5GHZ,
+	.channels	= b43_5ghz_nphy_chantable_limited,
+	.n_channels	= ARRAY_SIZE(b43_5ghz_nphy_chantable_limited),
+	.bitrates	= b43_a_ratetable,
+	.n_bitrates	= b43_a_ratetable_size,
+};
+
 static struct ieee80211_supported_band b43_band_5GHz_aphy = {
 	.band		= IEEE80211_BAND_5GHZ,
 	.channels	= b43_5ghz_aphy_chantable,
@@ -325,6 +348,14 @@ static struct ieee80211_supported_band b
 	.n_bitrates	= b43_g_ratetable_size,
 };
 
+static struct ieee80211_supported_band b43_band_2ghz_limited = {
+	.band		= IEEE80211_BAND_2GHZ,
+	.channels	= b43_2ghz_chantable,
+	.n_channels	= b43_2ghz_chantable_limited_size,
+	.bitrates	= b43_g_ratetable,
+	.n_bitrates	= b43_g_ratetable_size,
+};
+
 static void b43_wireless_core_exit(struct b43_wldev *dev);
 static int b43_wireless_core_init(struct b43_wldev *dev);
 static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
@@ -2192,52 +2223,82 @@ err_format:
 	return -EPROTO;
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/Init/Firmware */
 static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 {
 	struct b43_wldev *dev = ctx->dev;
 	struct b43_firmware *fw = &ctx->dev->fw;
+	struct b43_phy *phy = &dev->phy;
 	const u8 rev = ctx->dev->dev->core_rev;
 	const char *filename;
-	u32 tmshigh;
 	int err;
 
-	/* Files for HT and LCN were found by trying one by one */
-
 	/* Get microcode */
-	if ((rev >= 5) && (rev <= 10)) {
-		filename = "ucode5";
-	} else if ((rev >= 11) && (rev <= 12)) {
-		filename = "ucode11";
-	} else if (rev == 13) {
-		filename = "ucode13";
-	} else if (rev == 14) {
-		filename = "ucode14";
-	} else if (rev == 15) {
+	filename = NULL;
+	switch (rev) {
+	case 42:
+		if (phy->type == B43_PHYTYPE_AC)
+			filename = "ucode42";
+		break;
+	case 40:
+		if (phy->type == B43_PHYTYPE_AC)
+			filename = "ucode40";
+		break;
+	case 33:
+		if (phy->type == B43_PHYTYPE_LCN40)
+			filename = "ucode33_lcn40";
+		break;
+	case 30:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode30_mimo";
+		break;
+	case 29:
+		if (phy->type == B43_PHYTYPE_HT)
+			filename = "ucode29_mimo";
+		break;
+	case 26:
+		if (phy->type == B43_PHYTYPE_HT)
+			filename = "ucode26_mimo";
+		break;
+	case 28:
+	case 25:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode25_mimo";
+		else if (phy->type == B43_PHYTYPE_LCN)
+			filename = "ucode25_lcn";
+		break;
+	case 24:
+		if (phy->type == B43_PHYTYPE_LCN)
+			filename = "ucode24_lcn";
+		break;
+	case 23:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode16_mimo";
+		break;
+	case 16 ... 19:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode16_mimo";
+		else if (phy->type == B43_PHYTYPE_LP)
+			filename = "ucode16_lp";
+		break;
+	case 15:
 		filename = "ucode15";
-	} else {
-		switch (dev->phy.type) {
-		case B43_PHYTYPE_N:
-			if (rev >= 16)
-				filename = "ucode16_mimo";
-			else
-				goto err_no_ucode;
-			break;
-		case B43_PHYTYPE_HT:
-			if (rev == 29)
-				filename = "ucode29_mimo";
-			else
-				goto err_no_ucode;
-			break;
-		case B43_PHYTYPE_LCN:
-			if (rev == 24)
-				filename = "ucode24_mimo";
-			else
-				goto err_no_ucode;
-			break;
-		default:
-			goto err_no_ucode;
-		}
+		break;
+	case 14:
+		filename = "ucode14";
+		break;
+	case 13:
+		filename = "ucode13";
+		break;
+	case 11 ... 12:
+		filename = "ucode11";
+		break;
+	case 5 ... 10:
+		filename = "ucode5";
+		break;
 	}
+	if (!filename)
+		goto err_no_ucode;
 	err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
 	if (err)
 		goto err_load;
@@ -2259,117 +2320,121 @@ static int b43_try_request_fw(struct b43
 		goto err_load;
 
 	/* Get initvals */
+	filename = NULL;
 	switch (dev->phy.type) {
-	case B43_PHYTYPE_A:
-		if ((rev >= 5) && (rev <= 10)) {
-			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
-			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
-				filename = "a0g1initvals5";
-			else
-				filename = "a0g0initvals5";
-		} else
-			goto err_no_initvals;
-		break;
 	case B43_PHYTYPE_G:
-		if ((rev >= 5) && (rev <= 10))
-			filename = "b0g0initvals5";
-		else if (rev >= 13)
+		if (rev == 13)
 			filename = "b0g0initvals13";
-		else
-			goto err_no_initvals;
+		else if (rev >= 5 && rev <= 10)
+			filename = "b0g0initvals5";
 		break;
 	case B43_PHYTYPE_N:
-		if (rev >= 16)
+		if (rev == 30)
+			filename = "n16initvals30";
+		else if (rev == 28 || rev == 25)
+			filename = "n0initvals25";
+		else if (rev == 24)
+			filename = "n0initvals24";
+		else if (rev == 23)
+			filename = "n0initvals16"; /* What about n0initvals22? */
+		else if (rev >= 16 && rev <= 18)
 			filename = "n0initvals16";
-		else if ((rev >= 11) && (rev <= 12))
+		else if (rev >= 11 && rev <= 12)
 			filename = "n0initvals11";
-		else
-			goto err_no_initvals;
 		break;
 	case B43_PHYTYPE_LP:
-		if (rev == 13)
-			filename = "lp0initvals13";
+		if (rev >= 16 && rev <= 18)
+			filename = "lp0initvals16";
+		else if (rev == 15)
+			filename = "lp0initvals15";
 		else if (rev == 14)
 			filename = "lp0initvals14";
-		else if (rev >= 15)
-			filename = "lp0initvals15";
-		else
-			goto err_no_initvals;
+		else if (rev == 13)
+			filename = "lp0initvals13";
 		break;
 	case B43_PHYTYPE_HT:
 		if (rev == 29)
 			filename = "ht0initvals29";
-		else
-			goto err_no_initvals;
+		else if (rev == 26)
+			filename = "ht0initvals26";
 		break;
 	case B43_PHYTYPE_LCN:
 		if (rev == 24)
 			filename = "lcn0initvals24";
-		else
-			goto err_no_initvals;
 		break;
-	default:
-		goto err_no_initvals;
+	case B43_PHYTYPE_LCN40:
+		if (rev == 33)
+			filename = "lcn400initvals33";
+		break;
+	case B43_PHYTYPE_AC:
+		if (rev == 42)
+			filename = "ac1initvals42";
+		else if (rev == 40)
+			filename = "ac0initvals40";
+		break;
 	}
+	if (!filename)
+		goto err_no_initvals;
 	err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
 	if (err)
 		goto err_load;
 
 	/* Get bandswitch initvals */
+	filename = NULL;
 	switch (dev->phy.type) {
-	case B43_PHYTYPE_A:
-		if ((rev >= 5) && (rev <= 10)) {
-			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
-			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
-				filename = "a0g1bsinitvals5";
-			else
-				filename = "a0g0bsinitvals5";
-		} else if (rev >= 11)
-			filename = NULL;
-		else
-			goto err_no_initvals;
-		break;
 	case B43_PHYTYPE_G:
-		if ((rev >= 5) && (rev <= 10))
+		if (rev == 13)
+			filename = "b0g0bsinitvals13";
+		else if (rev >= 5 && rev <= 10)
 			filename = "b0g0bsinitvals5";
-		else if (rev >= 11)
-			filename = NULL;
-		else
-			goto err_no_initvals;
 		break;
 	case B43_PHYTYPE_N:
-		if (rev >= 16)
+		if (rev == 30)
+			filename = "n16bsinitvals30";
+		else if (rev == 28 || rev == 25)
+			filename = "n0bsinitvals25";
+		else if (rev == 24)
+			filename = "n0bsinitvals24";
+		else if (rev == 23)
+			filename = "n0bsinitvals16"; /* What about n0bsinitvals22? */
+		else if (rev >= 16 && rev <= 18)
 			filename = "n0bsinitvals16";
-		else if ((rev >= 11) && (rev <= 12))
+		else if (rev >= 11 && rev <= 12)
 			filename = "n0bsinitvals11";
-		else
-			goto err_no_initvals;
 		break;
 	case B43_PHYTYPE_LP:
-		if (rev == 13)
-			filename = "lp0bsinitvals13";
+		if (rev >= 16 && rev <= 18)
+			filename = "lp0bsinitvals16";
+		else if (rev == 15)
+			filename = "lp0bsinitvals15";
 		else if (rev == 14)
 			filename = "lp0bsinitvals14";
-		else if (rev >= 15)
-			filename = "lp0bsinitvals15";
-		else
-			goto err_no_initvals;
+		else if (rev == 13)
+			filename = "lp0bsinitvals13";
 		break;
 	case B43_PHYTYPE_HT:
 		if (rev == 29)
 			filename = "ht0bsinitvals29";
-		else
-			goto err_no_initvals;
+		else if (rev == 26)
+			filename = "ht0bsinitvals26";
 		break;
 	case B43_PHYTYPE_LCN:
 		if (rev == 24)
 			filename = "lcn0bsinitvals24";
-		else
-			goto err_no_initvals;
 		break;
-	default:
-		goto err_no_initvals;
+	case B43_PHYTYPE_LCN40:
+		if (rev == 33)
+			filename = "lcn400bsinitvals33";
+		break;
+	case B43_PHYTYPE_AC:
+		if (rev == 42)
+			filename = "ac1bsinitvals42";
+		else if (rev == 40)
+			filename = "ac0bsinitvals40";
+		break;
 	}
+	if (!filename)
+		goto err_no_initvals;
 	err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
 	if (err)
 		goto err_load;
@@ -2911,6 +2976,46 @@ void b43_mac_phy_clock_set(struct b43_wl
 	}
 }
 
+/* brcms_b_switch_macfreq */
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
+{
+	u16 chip_id = dev->dev->chip_id;
+
+	if (chip_id == BCMA_CHIP_ID_BCM43131 ||
+	    chip_id == BCMA_CHIP_ID_BCM43217 ||
+	    chip_id == BCMA_CHIP_ID_BCM43222 ||
+	    chip_id == BCMA_CHIP_ID_BCM43224 ||
+	    chip_id == BCMA_CHIP_ID_BCM43225 ||
+	    chip_id == BCMA_CHIP_ID_BCM43227 ||
+	    chip_id == BCMA_CHIP_ID_BCM43228) {
+		switch (spurmode) {
+		case 2: /* 126 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		case 1: /* 123 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		default: /* 120 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		}
+	} else if (dev->phy.type == B43_PHYTYPE_LCN) {
+		switch (spurmode) {
+		case 1: /* 82 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+			break;
+		default: /* 80 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+			break;
+		}
+	}
+}
+
 static void b43_adjust_opmode(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
@@ -3794,38 +3899,29 @@ static void b43_set_retry_limits(struct
 static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
-	struct b43_wldev *dev;
-	struct b43_phy *phy;
+	struct b43_wldev *dev = wl->current_dev;
+	struct b43_phy *phy = &dev->phy;
 	struct ieee80211_conf *conf = &hw->conf;
 	int antenna;
 	int err = 0;
-	bool reload_bss = false;
 
 	mutex_lock(&wl->mutex);
-
-	dev = wl->current_dev;
-
 	b43_mac_suspend(dev);
 
-	/* Switch the band (if necessary). This might change the active core. */
-	err = b43_switch_band(dev, conf->chandef.chan);
-	if (err)
-		goto out_unlock_mutex;
-
-	/* Need to reload all settings if the core changed */
-	if (dev != wl->current_dev) {
-		dev = wl->current_dev;
-		changed = ~0;
-		reload_bss = true;
-	}
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		phy->chandef = &conf->chandef;
+		phy->channel = conf->chandef.chan->hw_value;
 
-	phy = &dev->phy;
+		/* Switch the band (if necessary). */
+		err = b43_switch_band(dev, conf->chandef.chan);
+		if (err)
+			goto out_mac_enable;
 
-	if (conf_is_ht(conf))
-		phy->is_40mhz =
-			(conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf));
-	else
-		phy->is_40mhz = false;
+		/* Switch to the requested channel.
+		 * The firmware takes care of races with the TX handler.
+		 */
+		b43_switch_channel(dev, phy->channel);
+	}
 
 	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
@@ -3834,11 +3930,6 @@ static int b43_op_config(struct ieee8021
 	if (!changed)
 		goto out_mac_enable;
 
-	/* Switch to the requested channel.
-	 * The firmware takes care of races with the TX handler. */
-	if (conf->chandef.chan->hw_value != phy->channel)
-		b43_switch_channel(dev, conf->chandef.chan->hw_value);
-
 	dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
 
 	/* Adjust the desired TX power level. */
@@ -3874,12 +3965,8 @@ static int b43_op_config(struct ieee8021
 
 out_mac_enable:
 	b43_mac_enable(dev);
-out_unlock_mutex:
 	mutex_unlock(&wl->mutex);
 
-	if (wl->vif && reload_bss)
-		b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
-
 	return err;
 }
 
@@ -4305,13 +4392,15 @@ static char *b43_phy_name(struct b43_wld
 static int b43_phy_versioning(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
+	const u8 core_rev = dev->dev->core_rev;
 	u32 tmp;
 	u8 analog_type;
 	u8 phy_type;
 	u8 phy_rev;
 	u16 radio_manuf;
-	u16 radio_ver;
+	u16 radio_id;
 	u16 radio_rev;
+	u8 radio_ver;
 	int unsupported = 0;
 
 	/* Get PHY versioning */
@@ -4319,23 +4408,23 @@ static int b43_phy_versioning(struct b43
 	analog_type = (tmp & B43_PHYVER_ANALOG) >> B43_PHYVER_ANALOG_SHIFT;
 	phy_type = (tmp & B43_PHYVER_TYPE) >> B43_PHYVER_TYPE_SHIFT;
 	phy_rev = (tmp & B43_PHYVER_VERSION);
+
+	/* LCNXN is continuation of N which run out of revisions */
+	if (phy_type == B43_PHYTYPE_LCNXN) {
+		phy_type = B43_PHYTYPE_N;
+		phy_rev += 16;
+	}
+
 	switch (phy_type) {
-	case B43_PHYTYPE_A:
-		if (phy_rev >= 4)
-			unsupported = 1;
-		break;
-	case B43_PHYTYPE_B:
-		if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6
-		    && phy_rev != 7)
-			unsupported = 1;
-		break;
+#ifdef CONFIG_B43_PHY_G
 	case B43_PHYTYPE_G:
 		if (phy_rev > 9)
 			unsupported = 1;
 		break;
+#endif
 #ifdef CONFIG_B43_PHY_N
 	case B43_PHYTYPE_N:
-		if (phy_rev > 9)
+		if (phy_rev >= 19)
 			unsupported = 1;
 		break;
 #endif
@@ -4370,7 +4459,17 @@ static int b43_phy_versioning(struct b43
 		analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
 
 	/* Get RADIO versioning */
-	if (dev->dev->core_rev >= 24) {
+	if (core_rev == 40 || core_rev == 42) {
+		radio_manuf = 0x17F;
+
+		b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0);
+		radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+		b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
+		radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+		radio_ver = 0; /* Is there version somewhere? */
+	} else if (core_rev >= 24) {
 		u16 radio24[3];
 
 		for (tmp = 0; tmp < 3; tmp++) {
@@ -4378,12 +4477,10 @@ static int b43_phy_versioning(struct b43
 			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
 		}
 
-		/* Broadcom uses "id" for our "ver" and has separated "ver" */
-		/* radio_ver = (radio24[0] & 0xF0) >> 4; */
-
 		radio_manuf = 0x17F;
-		radio_ver = (radio24[2] << 8) | radio24[1];
+		radio_id = (radio24[2] << 8) | radio24[1];
 		radio_rev = (radio24[0] & 0xF);
+		radio_ver = (radio24[0] & 0xF0) >> 4;
 	} else {
 		if (dev->dev->chip_id == 0x4317) {
 			if (dev->dev->chip_rev == 0)
@@ -4402,15 +4499,16 @@ static int b43_phy_versioning(struct b43
 				<< 16;
 		}
 		radio_manuf = (tmp & 0x00000FFF);
-		radio_ver = (tmp & 0x0FFFF000) >> 12;
+		radio_id = (tmp & 0x0FFFF000) >> 12;
 		radio_rev = (tmp & 0xF0000000) >> 28;
+		radio_ver = 0; /* Probably not available on old hw */
 	}
 
 	if (radio_manuf != 0x17F /* Broadcom */)
 		unsupported = 1;
 	switch (phy_type) {
 	case B43_PHYTYPE_A:
-		if (radio_ver != 0x2060)
+		if (radio_id != 0x2060)
 			unsupported = 1;
 		if (radio_rev != 1)
 			unsupported = 1;
@@ -4418,43 +4516,49 @@ static int b43_phy_versioning(struct b43
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_B:
-		if ((radio_ver & 0xFFF0) != 0x2050)
+		if ((radio_id & 0xFFF0) != 0x2050)
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_G:
-		if (radio_ver != 0x2050)
+		if (radio_id != 0x2050)
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_N:
-		if (radio_ver != 0x2055 && radio_ver != 0x2056)
+		if (radio_id != 0x2055 && radio_id != 0x2056 &&
+		    radio_id != 0x2057)
+			unsupported = 1;
+		if (radio_id == 0x2057 &&
+		    !(radio_rev == 9 || radio_rev == 14))
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_LP:
-		if (radio_ver != 0x2062 && radio_ver != 0x2063)
+		if (radio_id != 0x2062 && radio_id != 0x2063)
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_HT:
-		if (radio_ver != 0x2059)
+		if (radio_id != 0x2059)
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_LCN:
-		if (radio_ver != 0x2064)
+		if (radio_id != 0x2064)
 			unsupported = 1;
 		break;
 	default:
 		B43_WARN_ON(1);
 	}
 	if (unsupported) {
-		b43err(dev->wl, "FOUND UNSUPPORTED RADIO "
-		       "(Manuf 0x%X, Version 0x%X, Revision %u)\n",
-		       radio_manuf, radio_ver, radio_rev);
+		b43err(dev->wl,
+		       "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
+		       radio_manuf, radio_id, radio_rev, radio_ver);
 		return -EOPNOTSUPP;
 	}
-	b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n",
-	       radio_manuf, radio_ver, radio_rev);
+	b43info(dev->wl,
+		"Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
+		radio_manuf, radio_id, radio_rev, radio_ver);
 
+	/* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
 	phy->radio_manuf = radio_manuf;
-	phy->radio_ver = radio_ver;
+	phy->radio_ver = radio_id;
 	phy->radio_rev = radio_rev;
 
 	phy->analog = analog_type;
@@ -5062,12 +5166,24 @@ static int b43_setup_bands(struct b43_wl
 			   bool have_2ghz_phy, bool have_5ghz_phy)
 {
 	struct ieee80211_hw *hw = dev->wl->hw;
+	struct b43_phy *phy = &dev->phy;
+	bool limited_2g;
+	bool limited_5g;
+
+	/* We don't support all 2 GHz channels on some devices */
+	limited_2g = phy->radio_ver == 0x2057 &&
+		     (phy->radio_rev == 9 || phy->radio_rev == 14);
+	limited_5g = phy->radio_ver == 0x2057 &&
+		     phy->radio_rev == 9;
 
 	if (have_2ghz_phy)
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ?
+			&b43_band_2ghz_limited : &b43_band_2GHz;
 	if (dev->phy.type == B43_PHYTYPE_N) {
 		if (have_5ghz_phy)
-			hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
+			hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ?
+				&b43_band_5GHz_nphy_limited :
+				&b43_band_5GHz_nphy;
 	} else {
 		if (have_5ghz_phy)
 			hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
@@ -5215,14 +5331,15 @@ static int b43_wireless_core_attach(stru
 	b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
 
 	/* We don't support 5 GHz on some PHYs yet */
-	switch (dev->phy.type) {
-	case B43_PHYTYPE_A:
-	case B43_PHYTYPE_G:
-	case B43_PHYTYPE_N:
-	case B43_PHYTYPE_LP:
-	case B43_PHYTYPE_HT:
-		b43warn(wl, "5 GHz band is unsupported on this PHY\n");
-		have_5ghz_phy = false;
+	if (have_5ghz_phy) {
+		switch (dev->phy.type) {
+		case B43_PHYTYPE_A:
+		case B43_PHYTYPE_G:
+		case B43_PHYTYPE_LP:
+		case B43_PHYTYPE_HT:
+			b43warn(wl, "5 GHz band is unsupported on this PHY\n");
+			have_5ghz_phy = false;
+		}
 	}
 
 	if (!have_2ghz_phy && !have_5ghz_phy) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/main.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/main.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/main.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/main.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b4
 void b43_mac_suspend(struct b43_wldev *dev);
 void b43_mac_enable(struct b43_wldev *dev);
 void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
 
 
 struct b43_request_fw_context;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,11 @@
 b43-y				+= main.o
 b43-y				+= bus.o
-b43-y				+= tables.o
+b43-$(CONFIG_B43_PHY_G)		+= phy_a.o phy_g.o tables.o lo.o wa.o
 b43-$(CONFIG_B43_PHY_N)		+= tables_nphy.o
 b43-$(CONFIG_B43_PHY_N)		+= radio_2055.o
 b43-$(CONFIG_B43_PHY_N)		+= radio_2056.o
 b43-$(CONFIG_B43_PHY_N)		+= radio_2057.o
 b43-y				+= phy_common.o
-b43-y				+= phy_g.o
-b43-y				+= phy_a.o
 b43-$(CONFIG_B43_PHY_N)		+= phy_n.o
 b43-$(CONFIG_B43_PHY_LP)	+= phy_lp.o
 b43-$(CONFIG_B43_PHY_LP)	+= tables_lpphy.o
@@ -17,8 +15,6 @@ b43-$(CONFIG_B43_PHY_HT)	+= radio_2059.o
 b43-$(CONFIG_B43_PHY_LCN)	+= phy_lcn.o tables_phy_lcn.o
 b43-y				+= sysfs.o
 b43-y				+= xmit.o
-b43-y				+= lo.o
-b43-y				+= wa.o
 b43-y				+= dma.o
 b43-y				+= pio.o
 b43-y				+= rfkill.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_a.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_a.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_a.c	2014-09-28 17:29:07.000000000 -0400
@@ -573,7 +573,7 @@ static void b43_aphy_op_pwork_60sec(stru
 {//TODO
 }
 
-const struct b43_phy_operations b43_phyops_a = {
+static const struct b43_phy_operations b43_phyops_a = {
 	.allocate		= b43_aphy_op_allocate,
 	.free			= b43_aphy_op_free,
 	.prepare_structs	= b43_aphy_op_prepare_structs,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_a.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_a.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_a.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_a.h	2014-09-28 17:29:07.000000000 -0400
@@ -123,8 +123,4 @@ struct b43_phy_a {
  */
 void b43_phy_inita(struct b43_wldev *dev);
 
-
-struct b43_phy_operations;
-extern const struct b43_phy_operations b43_phyops_a;
-
 #endif /* LINUX_B43_PHY_A_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_common.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_common.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,11 +45,10 @@ int b43_phy_allocate(struct b43_wldev *d
 	phy->ops = NULL;
 
 	switch (phy->type) {
-	case B43_PHYTYPE_A:
-		phy->ops = &b43_phyops_a;
-		break;
 	case B43_PHYTYPE_G:
+#ifdef CONFIG_B43_PHY_G
 		phy->ops = &b43_phyops_g;
+#endif
 		break;
 	case B43_PHYTYPE_N:
 #ifdef CONFIG_B43_PHY_N
@@ -94,7 +93,13 @@ int b43_phy_init(struct b43_wldev *dev)
 	const struct b43_phy_operations *ops = phy->ops;
 	int err;
 
-	phy->channel = ops->get_default_chan(dev);
+	/* During PHY init we need to use some channel. On the first init this
+	 * function is called *before* b43_op_config, so our pointer is NULL.
+	 */
+	if (!phy->chandef) {
+		phy->chandef = &dev->wl->hw->conf.chandef;
+		phy->channel = phy->chandef->chan->hw_value;
+	}
 
 	phy->ops->switch_analog(dev, true);
 	b43_software_rfkill(dev, false);
@@ -106,9 +111,7 @@ int b43_phy_init(struct b43_wldev *dev)
 	}
 	phy->do_full_init = false;
 
-	/* Make sure to switch hardware and firmware (SHM) to
-	 * the default channel. */
-	err = b43_switch_channel(dev, ops->get_default_chan(dev));
+	err = b43_switch_channel(dev, phy->channel);
 	if (err) {
 		b43err(dev->wl, "PHY init: Channel switch to default failed\n");
 		goto err_phy_exit;
@@ -408,9 +411,6 @@ int b43_switch_channel(struct b43_wldev
 	u16 channelcookie, savedcookie;
 	int err;
 
-	if (new_channel == B43_DEFAULT_CHANNEL)
-		new_channel = phy->ops->get_default_chan(dev);
-
 	/* First we set the channel radio code to prevent the
 	 * firmware from sending ghost packets.
 	 */
@@ -428,7 +428,6 @@ int b43_switch_channel(struct b43_wldev
 	if (err)
 		goto err_restore_cookie;
 
-	dev->phy.channel = new_channel;
 	/* Wait for the radio to tune to the channel and stabilize. */
 	msleep(8);
 
@@ -547,10 +546,9 @@ void b43_phyop_switch_analog_generic(str
 }
 
 
-bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
+bool b43_is_40mhz(struct b43_wldev *dev)
 {
-	return (channel_type == NL80211_CHAN_HT40MINUS ||
-		channel_type == NL80211_CHAN_HT40PLUS);
+	return dev->phy.chandef->width == NL80211_CHAN_WIDTH_40;
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_common.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_common.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_common.h	2014-09-28 17:29:07.000000000 -0400
@@ -228,9 +228,6 @@ struct b43_phy {
 	bool supports_2ghz;
 	bool supports_5ghz;
 
-	/* HT info */
-	bool is_40mhz;
-
 	/* Is GMODE (2 GHz mode) bit enabled? */
 	bool gmode;
 
@@ -267,9 +264,8 @@ struct b43_phy {
 	unsigned long next_txpwr_check_time;
 
 	/* Current channel */
+	struct cfg80211_chan_def *chandef;
 	unsigned int channel;
-	u16 channel_freq;
-	enum nl80211_channel_type channel_type;
 
 	/* PHY TX errors counter. */
 	atomic_t txerr_cnt;
@@ -400,10 +396,6 @@ void b43_phy_take_out_of_reset(struct b4
  * b43_switch_channel - Switch to another channel
  */
 int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
-/**
- * B43_DEFAULT_CHANNEL - Switch to the default channel.
- */
-#define B43_DEFAULT_CHANNEL	UINT_MAX
 
 /**
  * b43_software_rfkill - Turn the radio ON or OFF in software.
@@ -454,7 +446,7 @@ int b43_phy_shm_tssi_read(struct b43_wld
  */
 void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
 
-bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+bool b43_is_40mhz(struct b43_wldev *dev);
 
 void b43_phy_force_clock(struct b43_wldev *dev, bool force);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_ht.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_ht.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_ht.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_ht.c	2014-09-28 17:29:07.000000000 -0400
@@ -596,7 +596,7 @@ static void b43_phy_ht_tx_power_ctl_setu
 	u8 target[3];
 	s16 a1[3], b0[3], b1[3];
 
-	u16 freq = dev->phy.channel_freq;
+	u16 freq = dev->phy.chandef->chan->center_freq;
 	int i, c;
 
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_lcn.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_lcn.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_lcn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_lcn.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,39 +54,6 @@ enum lcn_sense_type {
 	B43_SENSE_VBAT,
 };
 
-/* In theory it's PHY common function, move if needed */
-/* brcms_b_switch_macfreq */
-static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
-{
-	if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
-		switch (spurmode) {
-		case 2:		/* 126 Mhz */
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
-			break;
-		case 1:		/* 123 Mhz */
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
-			break;
-		default:	/* 120 Mhz */
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
-			break;
-		}
-	} else if (dev->phy.type == B43_PHYTYPE_LCN) {
-		switch (spurmode) {
-		case 1:		/* 82 Mhz */
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
-			break;
-		default:	/* 80 Mhz */
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
-			break;
-		}
-	}
-}
-
 /**************************************************
  * Radio 2064.
  **************************************************/
@@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoida
 		b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
 		b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
 	}
-	b43_phy_switch_macfreq(dev, enable);
+	b43_mac_switch_freq(dev, enable);
 }
 
 /**************************************************
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_n.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_n.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_n.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_n.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include "main.h"
 
 struct nphy_txgains {
+	u16 tx_lpf[2];
 	u16 txgm[2];
 	u16 pga[2];
 	u16 pad[2];
@@ -43,6 +44,7 @@ struct nphy_txgains {
 };
 
 struct nphy_iqcal_params {
+	u16 tx_lpf;
 	u16 txgm;
 	u16 pga;
 	u16 pad;
@@ -69,6 +71,14 @@ enum b43_nphy_rf_sequence {
 	B43_RFSEQ_UPDATE_GAINU,
 };
 
+enum n_rf_ctl_over_cmd {
+	N_RF_CTL_OVER_CMD_RXRF_PU = 0,
+	N_RF_CTL_OVER_CMD_RX_PU = 1,
+	N_RF_CTL_OVER_CMD_TX_PU = 2,
+	N_RF_CTL_OVER_CMD_RX_GAIN = 3,
+	N_RF_CTL_OVER_CMD_TX_GAIN = 4,
+};
+
 enum n_intc_override {
 	N_INTC_OVERRIDE_OFF = 0,
 	N_INTC_OVERRIDE_TRSW = 1,
@@ -140,11 +150,19 @@ ok:
 	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
 }
 
+static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
+					   u16 value, u8 core, bool off,
+					   u8 override_id)
+{
+	/* TODO */
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
 static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
 					  u16 value, u8 core, bool off,
 					  u8 override)
 {
+	struct b43_phy *phy = &dev->phy;
 	const struct nphy_rf_control_override_rev7 *e;
 	u16 en_addrs[3][2] = {
 		{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
@@ -154,6 +172,11 @@ static void b43_nphy_rf_ctl_override_rev
 	u16 val_addr;
 	u8 i;
 
+	if (phy->rev >= 19 || phy->rev < 3) {
+		B43_WARN_ON(1);
+		return;
+	}
+
 	/* Remember: we can get NULL! */
 	e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
 
@@ -181,6 +204,50 @@ static void b43_nphy_rf_ctl_override_rev
 	}
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
+static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
+						 enum n_rf_ctl_over_cmd cmd,
+						 u16 value, u8 core, bool off)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 tmp;
+
+	B43_WARN_ON(phy->rev < 7);
+
+	switch (cmd) {
+	case N_RF_CTL_OVER_CMD_RXRF_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_RX_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_TX_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_RX_GAIN:
+		tmp = value & 0xFF;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
+		tmp = value >> 8;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
+		break;
+	case N_RF_CTL_OVER_CMD_TX_GAIN:
+		tmp = value & 0x7FFF;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
+		tmp = value >> 14;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
+		break;
+	}
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
 static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
 				     u16 value, u8 core, bool off)
@@ -264,6 +331,8 @@ static void b43_nphy_rf_ctl_intc_overrid
 	u16 reg, tmp, tmp2, val;
 	int core;
 
+	/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
+
 	for (core = 0; core < 2; core++) {
 		if ((core_sel == 1 && core != 0) ||
 		    (core_sel == 2 && core != 1))
@@ -274,6 +343,7 @@ static void b43_nphy_rf_ctl_intc_overrid
 		switch (intc_override) {
 		case N_INTC_OVERRIDE_OFF:
 			b43_phy_write(dev, reg, 0);
+			b43_phy_mask(dev, 0x2ff, ~0x2000);
 			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
 			break;
 		case N_INTC_OVERRIDE_TRSW:
@@ -505,6 +575,14 @@ static void b43_nphy_stay_in_carrier_sea
 	}
 }
 
+/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
+static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
+{
+	if (!offset)
+		offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
+	return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
 static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 {
@@ -590,44 +668,270 @@ static void b43_nphy_set_rf_sequence(str
  * Radio 0x2057
  **************************************************/
 
-/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
+static void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
+					  const struct b43_nphy_chantabent_rev7 *e_r7,
+					  const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
+{
+	if (e_r7_2g) {
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
+		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
+		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
+		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
+		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
+
+	} else {
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
+		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
+		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
+		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
+		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
+		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
+		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
+		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
+		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
+		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
+		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
+		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
+	}
+}
+
+static void b43_radio_2057_setup(struct b43_wldev *dev,
+				 const struct b43_nphy_chantabent_rev7 *tabent_r7,
+				 const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);
+
+	switch (phy->radio_rev) {
+	case 0 ... 4:
+	case 6:
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
+			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+		} else {
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
+			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+		}
+		break;
+	case 9: /* e.g. PHY rev 16 */
+		b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
+		b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
+			b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
+
+			if (b43_is_40mhz(dev)) {
+				/* TODO */
+			} else {
+				b43_radio_write(dev,
+						R2057_PAD_BIAS_FILTER_BWS_CORE0,
+						0x3c);
+				b43_radio_write(dev,
+						R2057_PAD_BIAS_FILTER_BWS_CORE1,
+						0x3c);
+			}
+		}
+		break;
+	case 14: /* 2 GHz only */
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
+		break;
+	}
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		u16 txmix2g_tune_boost_pu = 0;
+		u16 pad2g_tune_pus = 0;
+
+		if (b43_nphy_ipa(dev)) {
+			switch (phy->radio_rev) {
+			case 9:
+				txmix2g_tune_boost_pu = 0x0041;
+				/* TODO */
+				break;
+			case 14:
+				txmix2g_tune_boost_pu = 0x21;
+				pad2g_tune_pus = 0x23;
+				break;
+			}
+		}
+
+		if (txmix2g_tune_boost_pu)
+			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+					txmix2g_tune_boost_pu);
+		if (pad2g_tune_pus)
+			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
+					pad2g_tune_pus);
+		if (txmix2g_tune_boost_pu)
+			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+					txmix2g_tune_boost_pu);
+		if (pad2g_tune_pus)
+			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
+					pad2g_tune_pus);
+	}
+
+	usleep_range(50, 100);
+
+	/* VCO calibration */
+	b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
+	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
+	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
+	b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
+	usleep_range(300, 600);
+}
+
+/* Calibrate resistors in LPF of PLL?
+ * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
+ */
 static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
+	u16 saved_regs_phy[12];
+	u16 saved_regs_phy_rf[6];
+	u16 saved_regs_radio[2] = { };
+	static const u16 phy_to_store[] = {
+		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
+		B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
+		B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
+		B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
+		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
+	};
+	static const u16 phy_to_store_rf[] = {
+		B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
+		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
+	};
 	u16 tmp;
+	int i;
 
-	if (phy->radio_rev == 5) {
-		b43_phy_mask(dev, 0x342, ~0x2);
+	/* Save */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
+	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+		saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
+
+	/* Set */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		b43_phy_write(dev, phy_to_store[i], 0);
+	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
+
+	switch (phy->radio_rev) {
+	case 5:
+		b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
 		udelay(10);
 		b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
-		b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
+		b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
+		break;
+	case 9:
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
+		break;
+	case 14:
+		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+		saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
+		break;
 	}
 
+	/* Enable */
 	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
 	udelay(10);
-	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
-	if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
+
+	/* Start */
+	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
+	usleep_range(100, 200);
+
+	/* Stop */
+	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
+
+	/* Wait and check for result */
+	if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
 		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
 		return 0;
 	}
-	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
 	tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
+
+	/* Disable */
 	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
 
-	if (phy->radio_rev == 5) {
-		b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
-		b43_radio_mask(dev, 0x1ca, ~0x2);
-	}
-	if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+	/* Restore */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+		b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
+
+	switch (phy->radio_rev) {
+	case 0 ... 4:
+	case 6:
 		b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
 		b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
 				  tmp << 2);
+		break;
+	case 5:
+		b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
+		b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
+		break;
+	case 9:
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+		break;
+	case 14:
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
+		break;
 	}
 
 	return tmp & 0x3e;
 }
 
-/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */
+/* Calibrate the internal RC oscillator?
+ * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
+ */
 static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
@@ -635,49 +939,76 @@ static u16 b43_radio_2057_rccal(struct b
 			phy->radio_rev == 6);
 	u16 tmp;
 
+	/* Setup cal */
 	if (special) {
 		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
 		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
 	} else {
-		b43_radio_write(dev, 0x1AE, 0x61);
-		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
 	}
 	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+	/* Start, wait, stop */
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
-	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
 				  5000000))
 		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+	usleep_range(35, 70);
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	/* Setup cal */
 	if (special) {
 		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
 		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
 	} else {
-		b43_radio_write(dev, 0x1AE, 0x69);
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
 		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
 	}
 	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+	/* Start, wait, stop */
+	usleep_range(35, 70);
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
-	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+	usleep_range(70, 140);
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
 				  5000000))
 		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+	usleep_range(35, 70);
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	/* Setup cal */
 	if (special) {
 		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
 		b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
 		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
 	} else {
-		b43_radio_write(dev, 0x1AE, 0x73);
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
 		b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
 		b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
 	}
+
+	/* Start, wait, stop */
+	usleep_range(35, 70);
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
-	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+	usleep_range(70, 140);
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
 				  5000000)) {
 		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
 		return 0;
 	}
 	tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
+	usleep_range(35, 70);
 	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	if (special)
+		b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
+	else
+		b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);
+
 	return tmp;
 }
 
@@ -694,6 +1025,9 @@ static void b43_radio_2057_init_post(str
 {
 	b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
 
+	if (0) /* FIXME: Is this BCM43217 specific? */
+		b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
+
 	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
 	b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
 	mdelay(2);
@@ -798,6 +1132,7 @@ static void b43_chantab_radio_2056_uploa
 static void b43_radio_2056_setup(struct b43_wldev *dev,
 				const struct b43_nphy_channeltab_entry_rev3 *e)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	enum ieee80211_band band = b43_current_band(dev->wl);
 	u16 offset;
@@ -895,7 +1230,7 @@ static void b43_radio_2056_setup(struct
 					offset | B2056_TX_MIXG_BOOST_TUNE,
 					mixg_boost);
 			} else {
-				bias = dev->phy.is_40mhz ? 0x40 : 0x20;
+				bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
 				b43_radio_write(dev,
 					offset | B2056_TX_INTPAG_IMAIN_STAT,
 					bias);
@@ -909,7 +1244,7 @@ static void b43_radio_2056_setup(struct
 			b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
 		}
 	} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
-		u16 freq = dev->phy.channel_freq;
+		u16 freq = phy->chandef->chan->center_freq;
 		if (freq < 5100) {
 			paa_boost = 0xA;
 			pada_boost = 0x77;
@@ -1210,8 +1545,7 @@ static u16 b43_nphy_gen_load_samples(str
 	u16 bw, len, rot, angle;
 	struct b43_c32 *samples;
 
-
-	bw = (dev->phy.is_40mhz) ? 40 : 20;
+	bw = b43_is_40mhz(dev) ? 40 : 20;
 	len = bw << 3;
 
 	if (test) {
@@ -1220,7 +1554,7 @@ static u16 b43_nphy_gen_load_samples(str
 		else
 			bw = 80;
 
-		if (dev->phy.is_40mhz)
+		if (b43_is_40mhz(dev))
 			bw <<= 1;
 
 		len = bw << 1;
@@ -1248,8 +1582,10 @@ static u16 b43_nphy_gen_load_samples(str
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
 static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
-					u16 wait, bool iqmode, bool dac_test)
+				 u16 wait, bool iqmode, bool dac_test,
+				 bool modify_bbmult)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	int i;
 	u16 seq_mode;
@@ -1257,17 +1593,35 @@ static void b43_nphy_run_samples(struct
 
 	b43_nphy_stay_in_carrier_search(dev, true);
 
+	if (phy->rev >= 7) {
+		bool lpf_bw3, lpf_bw4;
+
+		lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
+		lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
+
+		if (lpf_bw3 || lpf_bw4) {
+			/* TODO */
+		} else {
+			u16 value = b43_nphy_read_lpf_ctl(dev, 0);
+			if (phy->rev >= 19)
+				b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
+							       0, false, 1);
+			else
+				b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
+							      0, false, 1);
+			nphy->lpf_bw_overrode_for_sample_play = true;
+		}
+	}
+
 	if ((nphy->bb_mult_save & 0x80000000) == 0) {
 		tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
 		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
 	}
 
-	/* TODO: add modify_bbmult argument */
-	if (!dev->phy.is_40mhz)
-		tmp = 0x6464;
-	else
-		tmp = 0x4747;
-	b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+	if (modify_bbmult) {
+		tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
+		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+	}
 
 	b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
 
@@ -1285,10 +1639,8 @@ static void b43_nphy_run_samples(struct
 		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
 		b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
 	} else {
-		if (dac_test)
-			b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
-		else
-			b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
+		tmp = dac_test ? 5 : 1;
+		b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
 	}
 	for (i = 0; i < 100; i++) {
 		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
@@ -1388,6 +1740,12 @@ static void b43_nphy_scale_offset_rssi(s
 	}
 }
 
+static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
+				       enum n_rssi_type rssi_type)
+{
+	/* TODO */
+}
+
 static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
 				      enum n_rssi_type rssi_type)
 {
@@ -1457,13 +1815,15 @@ static void b43_nphy_rev3_rssi_select(st
 					enum ieee80211_band band =
 						b43_current_band(dev->wl);
 
-					if (b43_nphy_ipa(dev))
-						val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
-					else
-						val = 0x11;
-					reg = (i == 0) ? 0x2000 : 0x3000;
-					reg |= B2055_PADDRV;
-					b43_radio_write(dev, reg, val);
+					if (dev->phy.rev < 7) {
+						if (b43_nphy_ipa(dev))
+							val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
+						else
+							val = 0x11;
+						reg = (i == 0) ? B2056_TX0 : B2056_TX1;
+						reg |= B2056_TX_TX_SSI_MUX;
+						b43_radio_write(dev, reg, val);
+					}
 
 					reg = (i == 0) ?
 						B43_NPHY_AFECTL_OVER1 :
@@ -1550,7 +1910,9 @@ static void b43_nphy_rev2_rssi_select(st
 static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
 				 enum n_rssi_type type)
 {
-	if (dev->phy.rev >= 3)
+	if (dev->phy.rev >= 19)
+		b43_nphy_rssi_select_rev19(dev, code, type);
+	else if (dev->phy.rev >= 3)
 		b43_nphy_rev3_rssi_select(dev, code, type);
 	else
 		b43_nphy_rev2_rssi_select(dev, code, type);
@@ -1594,6 +1956,8 @@ static int b43_nphy_poll_rssi(struct b43
 	u16 save_regs_phy[9];
 	u16 s[2];
 
+	/* TODO: rev7+ is treated like rev3+, what about rev19+? */
+
 	if (dev->phy.rev >= 3) {
 		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
 		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
@@ -1675,6 +2039,7 @@ static int b43_nphy_poll_rssi(struct b43
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
 static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 
 	u16 saved_regs_phy_rfctl[2];
@@ -1692,12 +2057,14 @@ static void b43_nphy_rev3_rssi_cal(struc
 		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
 		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
 		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
-		0x342, 0x343, 0x346, 0x347,
+		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
 		0x2ff,
 		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
 		B43_NPHY_RFCTL_CMD,
 		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
-		0x340, 0x341, 0x344, 0x345,
+		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
 		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
 	};
 	u16 *regs_to_store;
@@ -1744,9 +2111,24 @@ static void b43_nphy_rev3_rssi_cal(struc
 	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
 
 	if (dev->phy.rev >= 7) {
-		/* TODO */
+		b43_nphy_rf_ctl_override_one_to_many(dev,
+						     N_RF_CTL_OVER_CMD_RXRF_PU,
+						     0, 0, false);
+		b43_nphy_rf_ctl_override_one_to_many(dev,
+						     N_RF_CTL_OVER_CMD_RX_PU,
+						     1, 0, false);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
+						      0);
+			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
+						      0);
 		} else {
+			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
+						      0);
+			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
+						      0);
 		}
 	} else {
 		b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
@@ -1775,7 +2157,10 @@ static void b43_nphy_rev3_rssi_cal(struc
 		/* Grab RSSI results for every possible VCM */
 		for (vcm = 0; vcm < 8; vcm++) {
 			if (dev->phy.rev >= 7)
-				;
+				b43_radio_maskset(dev,
+						  core ? R2057_NB_MASTER_CORE1 :
+							 R2057_NB_MASTER_CORE0,
+						  ~R2057_VCM_MASK, vcm);
 			else
 				b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
 						  0xE3, vcm << 2);
@@ -1806,7 +2191,10 @@ static void b43_nphy_rev3_rssi_cal(struc
 
 		/* Select the best VCM */
 		if (dev->phy.rev >= 7)
-			;
+			b43_radio_maskset(dev,
+					  core ? R2057_NB_MASTER_CORE1 :
+						 R2057_NB_MASTER_CORE0,
+					  ~R2057_VCM_MASK, vcm);
 		else
 			b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
 					  0xE3, vcm_final << 2);
@@ -1876,6 +2264,10 @@ static void b43_nphy_rev3_rssi_cal(struc
 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
 	}
 	if (dev->phy.rev >= 7) {
+		rssical_radio_regs[0] = b43_radio_read(dev,
+						       R2057_NB_MASTER_CORE0);
+		rssical_radio_regs[1] = b43_radio_read(dev,
+						       R2057_NB_MASTER_CORE1);
 	} else {
 		rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
 						       B2056_RX_RSSI_MISC);
@@ -1897,9 +2289,9 @@ static void b43_nphy_rev3_rssi_cal(struc
 
 	/* Remember for which channel we store configuration */
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-		nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq;
+		nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq;
 	else
-		nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_freq;
+		nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq;
 
 	/* End of calibration, restore configuration */
 	b43_nphy_classifier(dev, 7, class);
@@ -2076,7 +2468,9 @@ static void b43_nphy_rev2_rssi_cal(struc
  */
 static void b43_nphy_rssi_cal(struct b43_wldev *dev)
 {
-	if (dev->phy.rev >= 3) {
+	if (dev->phy.rev >= 19) {
+		/* TODO */
+	} else if (dev->phy.rev >= 3) {
 		b43_nphy_rev3_rssi_cal(dev);
 	} else {
 		b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
@@ -2089,7 +2483,21 @@ static void b43_nphy_rssi_cal(struct b43
  * Workarounds
  **************************************************/
 
-static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
+static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
+{
+	/* TODO */
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	switch (phy->rev) {
+	/* TODO */
+	}
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
 {
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
@@ -2192,7 +2600,7 @@ static void b43_nphy_gain_ctl_workaround
 	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
 	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
 
-	if (!dev->phy.is_40mhz) {
+	if (!b43_is_40mhz(dev)) {
 		/* Set dwell lengths */
 		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
 		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
@@ -2206,7 +2614,7 @@ static void b43_nphy_gain_ctl_workaround
 	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
 			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
 
-	if (!dev->phy.is_40mhz) {
+	if (!b43_is_40mhz(dev)) {
 		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
 			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
 		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
@@ -2221,12 +2629,12 @@ static void b43_nphy_gain_ctl_workaround
 
 	if (nphy->gain_boost) {
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
-			dev->phy.is_40mhz)
+		    b43_is_40mhz(dev))
 			code = 4;
 		else
 			code = 5;
 	} else {
-		code = dev->phy.is_40mhz ? 6 : 7;
+		code = b43_is_40mhz(dev) ? 6 : 7;
 	}
 
 	/* Set HPVGA2 index */
@@ -2286,46 +2694,54 @@ static void b43_nphy_gain_ctl_workaround
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
 static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
 {
-	if (dev->phy.rev >= 7)
-		; /* TODO */
+	if (dev->phy.rev >= 19)
+		b43_nphy_gain_ctl_workarounds_rev19(dev);
+	else if (dev->phy.rev >= 7)
+		b43_nphy_gain_ctl_workarounds_rev7(dev);
 	else if (dev->phy.rev >= 3)
-		b43_nphy_gain_ctl_workarounds_rev3plus(dev);
+		b43_nphy_gain_ctl_workarounds_rev3(dev);
 	else
 		b43_nphy_gain_ctl_workarounds_rev1_2(dev);
 }
 
-/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
-static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
-{
-	if (!offset)
-		offset = (dev->phy.is_40mhz) ? 0x159 : 0x154;
-	return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
-}
-
 static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
 {
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 
+	/* TX to RX */
+	u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
+	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
+	/* RX to TX */
 	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
 					0x1F };
 	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
 
-	u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
+	static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
 	u8 ntab7_138_146[] = { 0x11, 0x11 };
 	u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
 
-	u16 lpf_20, lpf_40, lpf_11b;
-	u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
-	u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
+	u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
+	u16 bcap_val;
+	s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
+	u16 scap_val;
+	s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
 	bool rccal_ovrd = false;
 
-	u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
 	u16 bias, conv, filt;
 
+	u32 noise_tbl[2];
+
 	u32 tmp32;
 	u8 core;
 
+	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
 	if (phy->rev == 7) {
 		b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
 		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
@@ -2345,11 +2761,18 @@ static void b43_nphy_workarounds_rev7plu
 		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
 		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
 	}
-	if (phy->rev <= 8) {
+
+	if (phy->rev >= 16) {
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
+	} else if (phy->rev <= 8) {
 		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
 		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
 	}
-	if (phy->rev >= 8)
+
+	if (phy->rev >= 16)
+		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
+	else if (phy->rev >= 8)
 		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
 
 	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
@@ -2357,9 +2780,11 @@ static void b43_nphy_workarounds_rev7plu
 	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
 	tmp32 &= 0xffffff;
 	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
-	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
-	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
 
+	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+				 ARRAY_SIZE(tx2rx_events));
 	if (b43_nphy_ipa(dev))
 		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
 				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
@@ -2367,84 +2792,176 @@ static void b43_nphy_workarounds_rev7plu
 	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
 	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
 
-	lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
-	lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
-	lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
+	for (core = 0; core < 2; core++) {
+		lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
+		lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
+		lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
+	}
+
+	bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
+	scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
+
 	if (b43_nphy_ipa(dev)) {
-		if ((phy->radio_rev == 5 && phy->is_40mhz) ||
-		    phy->radio_rev == 7 || phy->radio_rev == 8) {
-			bcap_val = b43_radio_read(dev, 0x16b);
-			scap_val = b43_radio_read(dev, 0x16a);
-			scap_val_11b = scap_val;
-			bcap_val_11b = bcap_val;
-			if (phy->radio_rev == 5 && phy->is_40mhz) {
-				scap_val_11n_20 = scap_val;
-				bcap_val_11n_20 = bcap_val;
-				scap_val_11n_40 = bcap_val_11n_40 = 0xc;
+		bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ;
+
+		switch (phy->radio_rev) {
+		case 5:
+			/* Check radio version (to be 0) by PHY rev for now */
+			if (phy->rev == 8 && b43_is_40mhz(dev)) {
+				for (core = 0; core < 2; core++) {
+					scap_val_11b[core] = scap_val;
+					bcap_val_11b[core] = bcap_val;
+					scap_val_11n_20[core] = scap_val;
+					bcap_val_11n_20[core] = bcap_val;
+					scap_val_11n_40[core] = 0xc;
+					bcap_val_11n_40[core] = 0xc;
+				}
+
 				rccal_ovrd = true;
-			} else { /* Rev 7/8 */
-				lpf_20 = 4;
-				lpf_11b = 1;
+			}
+			if (phy->rev == 9) {
+				/* TODO: Radio version 1 (e.g. BCM5357B0) */
+			}
+			break;
+		case 7:
+		case 8:
+			for (core = 0; core < 2; core++) {
+				scap_val_11b[core] = scap_val;
+				bcap_val_11b[core] = bcap_val;
+				lpf_ofdm_20mhz[core] = 4;
+				lpf_11b[core] = 1;
 				if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-					scap_val_11n_20 = 0xc;
-					bcap_val_11n_20 = 0xc;
-					scap_val_11n_40 = 0xa;
-					bcap_val_11n_40 = 0xa;
+					scap_val_11n_20[core] = 0xc;
+					bcap_val_11n_20[core] = 0xc;
+					scap_val_11n_40[core] = 0xa;
+					bcap_val_11n_40[core] = 0xa;
 				} else {
-					scap_val_11n_20 = 0x14;
-					bcap_val_11n_20 = 0x14;
-					scap_val_11n_40 = 0xf;
-					bcap_val_11n_40 = 0xf;
+					scap_val_11n_20[core] = 0x14;
+					bcap_val_11n_20[core] = 0x14;
+					scap_val_11n_40[core] = 0xf;
+					bcap_val_11n_40[core] = 0xf;
 				}
-				rccal_ovrd = true;
 			}
+
+			rccal_ovrd = true;
+			break;
+		case 9:
+			for (core = 0; core < 2; core++) {
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11b[core] = scap_val;
+				lpf_11b[core] = 1;
+
+				if (ghz2) {
+					bcap_val_11n_20[core] = bcap_val + 13;
+					scap_val_11n_20[core] = scap_val + 15;
+				} else {
+					bcap_val_11n_20[core] = bcap_val + 14;
+					scap_val_11n_20[core] = scap_val + 15;
+				}
+				lpf_ofdm_20mhz[core] = 4;
+
+				if (ghz2) {
+					bcap_val_11n_40[core] = bcap_val - 7;
+					scap_val_11n_40[core] = scap_val - 5;
+				} else {
+					bcap_val_11n_40[core] = bcap_val + 2;
+					scap_val_11n_40[core] = scap_val + 4;
+				}
+				lpf_ofdm_40mhz[core] = 4;
+			}
+
+			rccal_ovrd = true;
+			break;
+		case 14:
+			for (core = 0; core < 2; core++) {
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11b[core] = scap_val;
+				lpf_11b[core] = 1;
+			}
+
+			bcap_val_11n_20[0] = bcap_val + 20;
+			scap_val_11n_20[0] = scap_val + 20;
+			lpf_ofdm_20mhz[0] = 3;
+
+			bcap_val_11n_20[1] = bcap_val + 16;
+			scap_val_11n_20[1] = scap_val + 16;
+			lpf_ofdm_20mhz[1] = 3;
+
+			bcap_val_11n_40[0] = bcap_val + 20;
+			scap_val_11n_40[0] = scap_val + 20;
+			lpf_ofdm_40mhz[0] = 4;
+
+			bcap_val_11n_40[1] = bcap_val + 10;
+			scap_val_11n_40[1] = scap_val + 10;
+			lpf_ofdm_40mhz[1] = 4;
+
+			rccal_ovrd = true;
+			break;
 		}
 	} else {
 		if (phy->radio_rev == 5) {
-			lpf_20 = 1;
-			lpf_40 = 3;
-			bcap_val = b43_radio_read(dev, 0x16b);
-			scap_val = b43_radio_read(dev, 0x16a);
-			scap_val_11b = scap_val;
-			bcap_val_11b = bcap_val;
-			scap_val_11n_20 = 0x11;
-			scap_val_11n_40 = 0x11;
-			bcap_val_11n_20 = 0x13;
-			bcap_val_11n_40 = 0x13;
+			for (core = 0; core < 2; core++) {
+				lpf_ofdm_20mhz[core] = 1;
+				lpf_ofdm_40mhz[core] = 3;
+				scap_val_11b[core] = scap_val;
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11n_20[core] = 0x11;
+				scap_val_11n_40[core] = 0x11;
+				bcap_val_11n_20[core] = 0x13;
+				bcap_val_11n_40[core] = 0x13;
+			}
+
 			rccal_ovrd = true;
 		}
 	}
 	if (rccal_ovrd) {
-		rx2tx_lut_20_11b = (bcap_val_11b << 8) |
-				   (scap_val_11b << 3) |
-				   lpf_11b;
-		rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
-				   (scap_val_11n_20 << 3) |
-				   lpf_20;
-		rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
-				   (scap_val_11n_40 << 3) |
-				   lpf_40;
+		u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
+		u8 rx2tx_lut_extra = 1;
+
+		for (core = 0; core < 2; core++) {
+			bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
+			scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
+			bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
+			scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
+			bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
+			scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
+
+			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11b[core] << 8) |
+						 (scap_val_11b[core] << 3) |
+						 lpf_11b[core];
+			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11n_20[core] << 8) |
+						 (scap_val_11n_20[core] << 3) |
+						 lpf_ofdm_20mhz[core];
+			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11n_40[core] << 8) |
+						 (scap_val_11n_40[core] << 3) |
+						 lpf_ofdm_40mhz[core];
+		}
+
 		for (core = 0; core < 2; core++) {
 			b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
-				       rx2tx_lut_20_11b);
+				       rx2tx_lut_20_11b[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
-				       rx2tx_lut_20_11n);
+				       rx2tx_lut_20_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
-				       rx2tx_lut_20_11n);
+				       rx2tx_lut_20_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
-				       rx2tx_lut_40_11n);
+				       rx2tx_lut_40_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
-				       rx2tx_lut_40_11n);
+				       rx2tx_lut_40_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
-				       rx2tx_lut_40_11n);
+				       rx2tx_lut_40_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
-				       rx2tx_lut_40_11n);
+				       rx2tx_lut_40_11n[core]);
 			b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
-				       rx2tx_lut_40_11n);
+				       rx2tx_lut_40_11n[core]);
 		}
-		b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
 	}
+
 	b43_phy_write(dev, 0x32F, 0x3);
+
 	if (phy->radio_rev == 4 || phy->radio_rev == 6)
 		b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
 
@@ -2492,7 +3009,8 @@ static void b43_nphy_workarounds_rev7plu
 								0x7f);
 				}
 			}
-			if (phy->radio_rev == 3) {
+			switch (phy->radio_rev) {
+			case 3:
 				for (core = 0; core < 2; core++) {
 					if (core == 0) {
 						b43_radio_write(dev, 0x64,
@@ -2518,17 +3036,34 @@ static void b43_nphy_workarounds_rev7plu
 								0x3E);
 					}
 				}
-			} else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
-				if (!phy->is_40mhz) {
+				break;
+			case 7:
+			case 8:
+				if (!b43_is_40mhz(dev)) {
 					b43_radio_write(dev, 0x5F, 0x14);
 					b43_radio_write(dev, 0xE8, 0x12);
 				} else {
 					b43_radio_write(dev, 0x5F, 0x16);
 					b43_radio_write(dev, 0xE8, 0x16);
 				}
+				break;
+			case 14:
+				for (core = 0; core < 2; core++) {
+					int o = core ? 0x85 : 0;
+
+					b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
+					b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
+					b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
+					b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
+					b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
+					b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
+					b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
+					b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
+				}
+				break;
 			}
 		} else {
-			u16 freq = phy->channel_freq;
+			u16 freq = phy->chandef->chan->center_freq;
 			if ((freq >= 5180 && freq <= 5230) ||
 			    (freq >= 5745 && freq <= 5805)) {
 				b43_radio_write(dev, 0x7D, 0xFF);
@@ -2573,8 +3108,8 @@ static void b43_nphy_workarounds_rev7plu
 		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
 		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
 		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
-		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
-		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
 
 		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
 		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
@@ -2585,20 +3120,20 @@ static void b43_nphy_workarounds_rev7plu
 	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
 
 	b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
-	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
 	b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
-	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
-	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
 	b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
 	b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
 
-	if (!phy->is_40mhz) {
-		b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
-		b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
-	} else {
-		b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
-		b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
-	}
+	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
+	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
+
+	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
+	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
 
 	b43_nphy_gain_ctl_workarounds(dev);
 
@@ -2691,7 +3226,7 @@ static void b43_nphy_workarounds_rev3plu
 
 	b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
 
-	if (!dev->phy.is_40mhz) {
+	if (!b43_is_40mhz(dev)) {
 		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
 		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
 	} else {
@@ -2926,6 +3461,7 @@ static void b43_nphy_workarounds(struct
 	b43_phy_set(dev, B43_NPHY_IQFLIP,
 		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
 
+	/* TODO: rev19+ */
 	if (dev->phy.rev >= 7)
 		b43_nphy_workarounds_rev7plus(dev);
 	else if (dev->phy.rev >= 3)
@@ -2946,12 +3482,13 @@ static void b43_nphy_workarounds(struct
  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
  */
 static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
-				bool iqmode, bool dac_test)
+			    bool iqmode, bool dac_test, bool modify_bbmult)
 {
 	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
 	if (samp == 0)
 		return -1;
-	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
+	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,
+			     modify_bbmult);
 	return 0;
 }
 
@@ -2986,6 +3523,7 @@ static void b43_nphy_update_txrx_chain(s
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
 static void b43_nphy_stop_playback(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	u16 tmp;
 
@@ -3006,6 +3544,15 @@ static void b43_nphy_stop_playback(struc
 		nphy->bb_mult_save = 0;
 	}
 
+	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
+		if (phy->rev >= 19)
+			b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
+						       1);
+		else
+			b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
+		nphy->lpf_bw_overrode_for_sample_play = false;
+	}
+
 	if (nphy->hang_avoid)
 		b43_nphy_stay_in_carrier_search(dev, 0);
 }
@@ -3015,16 +3562,23 @@ static void b43_nphy_iq_cal_gain_params(
 					struct nphy_txgains target,
 					struct nphy_iqcal_params *params)
 {
+	struct b43_phy *phy = &dev->phy;
 	int i, j, indx;
 	u16 gain;
 
 	if (dev->phy.rev >= 3) {
+		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
 		params->txgm = target.txgm[core];
 		params->pga = target.pga[core];
 		params->pad = target.pad[core];
 		params->ipa = target.ipa[core];
-		params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
-					(params->pad << 4) | (params->ipa);
+		if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 7) {
+			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
+		} else {
+			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
+		}
 		for (j = 0; j < 5; j++)
 			params->ncorr[j] = 0x79;
 	} else {
@@ -3065,6 +3619,7 @@ static enum b43_txpwr_result b43_nphy_op
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
 static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	u8 i;
 	u16 bmask, val, tmp;
@@ -3114,7 +3669,7 @@ static void b43_nphy_tx_power_ctrl(struc
 			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
 				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
 
-		if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
 			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
 	} else {
 		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
@@ -3134,12 +3689,25 @@ static void b43_nphy_tx_power_ctrl(struc
 		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
 
 		if (band == IEEE80211_BAND_5GHZ) {
-			b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
-					~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
-			if (dev->phy.rev > 1)
+			if (phy->rev >= 19) {
+				/* TODO */
+			} else if (phy->rev >= 7) {
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+						~B43_NPHY_TXPCTL_CMD_INIT,
+						0x32);
 				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
 						~B43_NPHY_TXPCTL_INIT_PIDXI1,
+						0x32);
+			} else {
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+						~B43_NPHY_TXPCTL_CMD_INIT,
 						0x64);
+				if (phy->rev > 1)
+					b43_phy_maskset(dev,
+							B43_NPHY_TXPCTL_INIT,
+							~B43_NPHY_TXPCTL_INIT_PIDXI1,
+							0x64);
+			}
 		}
 
 		if (dev->phy.rev >= 3) {
@@ -3156,6 +3724,10 @@ static void b43_nphy_tx_power_ctrl(struc
 			}
 		}
 
+		if (phy->rev >= 7) {
+			/* TODO */
+		}
+
 		if (dev->phy.rev >= 3) {
 			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
 			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
@@ -3168,7 +3740,7 @@ static void b43_nphy_tx_power_ctrl(struc
 		else if (dev->phy.rev < 2)
 			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
 
-		if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
 			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
 
 		if (b43_nphy_ipa(dev)) {
@@ -3184,18 +3756,20 @@ static void b43_nphy_tx_power_ctrl(struc
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
 	u8 txpi[2], bbmult, i;
 	u16 tmp, radio_gain, dac_gain;
-	u16 freq = dev->phy.channel_freq;
+	u16 freq = phy->chandef->chan->center_freq;
 	u32 txgain;
 	/* u32 gaintbl; rev3+ */
 
 	if (nphy->hang_avoid)
 		b43_nphy_stay_in_carrier_search(dev, 1);
 
+	/* TODO: rev19+ */
 	if (dev->phy.rev >= 7) {
 		txpi[0] = txpi[1] = 30;
 	} else if (dev->phy.rev >= 3) {
@@ -3234,7 +3808,11 @@ static void b43_nphy_tx_power_fix(struct
 	*/
 
 	for (i = 0; i < 2; i++) {
-		txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]);
+		const u32 *table = b43_nphy_get_tx_gain_table(dev);
+
+		if (!table)
+			break;
+		txgain = *(table + txpi[i]);
 
 		if (dev->phy.rev >= 3)
 			radio_gain = (txgain >> 16) & 0x1FFFF;
@@ -3294,7 +3872,9 @@ static void b43_nphy_ipa_internal_tssi_s
 	u8 core;
 	u16 r; /* routing */
 
-	if (phy->rev >= 7) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
 		for (core = 0; core < 2; core++) {
 			r = core ? 0x190 : 0x170;
 			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
@@ -3377,29 +3957,38 @@ static void b43_nphy_tx_power_ctl_idle_t
 	u32 tmp;
 	s32 rssi[4] = { };
 
-	/* TODO: check if we can transmit */
+	if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
+		return;
 
 	if (b43_nphy_ipa(dev))
 		b43_nphy_ipa_internal_tssi_setup(dev);
 
-	if (phy->rev >= 7)
-		b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0);
+	if (phy->rev >= 19)
+		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
+	else if (phy->rev >= 7)
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
 	else if (phy->rev >= 3)
 		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
 
 	b43_nphy_stop_playback(dev);
-	b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
+	b43_nphy_tx_tone(dev, 4000, 0, false, false, false);
 	udelay(20);
 	tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
 	b43_nphy_stop_playback(dev);
+
 	b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
 
-	if (phy->rev >= 7)
-		b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0);
+	if (phy->rev >= 19)
+		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
+	else if (phy->rev >= 7)
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
 	else if (phy->rev >= 3)
 		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
 
-	if (phy->rev >= 3) {
+	if (phy->rev >= 19) {
+		/* TODO */
+		return;
+	} else if (phy->rev >= 3) {
 		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
 		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
 	} else {
@@ -3439,21 +4028,21 @@ static void b43_nphy_tx_prepare_adjusted
 		delta = 0;
 		switch (stf_mode) {
 		case 0:
-			if (dev->phy.is_40mhz && dev->phy.rev >= 5) {
+			if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {
 				idx = 68;
 			} else {
 				delta = 1;
-				idx = dev->phy.is_40mhz ? 52 : 4;
+				idx = b43_is_40mhz(dev) ? 52 : 4;
 			}
 			break;
 		case 1:
-			idx = dev->phy.is_40mhz ? 76 : 28;
+			idx = b43_is_40mhz(dev) ? 76 : 28;
 			break;
 		case 2:
-			idx = dev->phy.is_40mhz ? 84 : 36;
+			idx = b43_is_40mhz(dev) ? 84 : 36;
 			break;
 		case 3:
-			idx = dev->phy.is_40mhz ? 92 : 44;
+			idx = b43_is_40mhz(dev) ? 92 : 44;
 			break;
 		}
 
@@ -3474,6 +4063,7 @@ static void b43_nphy_tx_prepare_adjusted
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
 static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
@@ -3483,7 +4073,7 @@ static void b43_nphy_tx_power_ctl_setup(
 	s32 num, den, pwr;
 	u32 regval[64];
 
-	u16 freq = dev->phy.channel_freq;
+	u16 freq = phy->chandef->chan->center_freq;
 	u16 tmp;
 	u16 r; /* routing */
 	u8 i, c;
@@ -3590,7 +4180,9 @@ static void b43_nphy_tx_power_ctl_setup(
 		udelay(1);
 	}
 
-	if (dev->phy.rev >= 7) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
 		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
 				~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
 		b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
@@ -3647,27 +4239,36 @@ static void b43_nphy_tx_gain_table_uploa
 	int i;
 
 	table = b43_nphy_get_tx_gain_table(dev);
+	if (!table)
+		return;
+
 	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
 	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
 
-	if (phy->rev >= 3) {
+	if (phy->rev < 3)
+		return;
+
 #if 0
-		nphy->gmval = (table[0] >> 16) & 0x7000;
+	nphy->gmval = (table[0] >> 16) & 0x7000;
 #endif
 
-		for (i = 0; i < 128; i++) {
+	for (i = 0; i < 128; i++) {
+		if (phy->rev >= 19) {
+			/* TODO */
+			return;
+		} else if (phy->rev >= 7) {
+			/* TODO */
+			return;
+		} else {
 			pga_gain = (table[i] >> 24) & 0xF;
 			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-				rfpwr_offset =
-				 b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
 			else
-				rfpwr_offset =
-				 0; /* FIXME */
-			b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
-				       rfpwr_offset);
-			b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
-				       rfpwr_offset);
+				rfpwr_offset = 0; /* FIXME */
 		}
+
+		b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
+		b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
 	}
 }
 
@@ -3684,7 +4285,9 @@ static void b43_nphy_pa_override(struct
 		nphy->rfctrl_intc2_save = b43_phy_read(dev,
 						       B43_NPHY_RFCTL_INTC2);
 		band = b43_current_band(dev->wl);
-		if (dev->phy.rev >= 3) {
+		if (dev->phy.rev >= 7) {
+			tmp = 0x1480;
+		} else if (dev->phy.rev >= 3) {
 			if (band == IEEE80211_BAND_5GHZ)
 				tmp = 0x600;
 			else
@@ -3705,21 +4308,28 @@ static void b43_nphy_pa_override(struct
 	}
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
-static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
+/*
+ * TX low-pass filter bandwidth setup
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
+ */
+static void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)
 {
 	u16 tmp;
 
-	if (dev->phy.rev >= 3) {
-		if (b43_nphy_ipa(dev)) {
-			tmp = 4;
-			b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
-			      (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
-		}
+	if (dev->phy.rev < 3 || dev->phy.rev >= 7)
+		return;
 
-		tmp = 1;
+	if (b43_nphy_ipa(dev))
+		tmp = b43_is_40mhz(dev) ? 5 : 4;
+	else
+		tmp = b43_is_40mhz(dev) ? 3 : 1;
+	b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
+		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
+
+	if (b43_nphy_ipa(dev)) {
+		tmp = b43_is_40mhz(dev) ? 4 : 1;
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
-			      (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
+			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
 	}
 }
 
@@ -3992,7 +4602,7 @@ static void b43_nphy_spur_workaround(str
 
 	if (nphy->gband_spurwar_en) {
 		/* TODO: N PHY Adjust Analog Pfbw (7) */
-		if (channel == 11 && dev->phy.is_40mhz)
+		if (channel == 11 && b43_is_40mhz(dev))
 			; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
 		else
 			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
@@ -4124,7 +4734,13 @@ static void b43_nphy_restore_rssi_cal(st
 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
 	}
 
-	if (dev->phy.rev >= 7) {
+	if (dev->phy.rev >= 19) {
+		/* TODO */
+	} else if (dev->phy.rev >= 7) {
+		b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
+				  rssical_radio_regs[0]);
+		b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
+				  rssical_radio_regs[1]);
 	} else {
 		b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
 				  rssical_radio_regs[0]);
@@ -4148,15 +4764,78 @@ static void b43_nphy_restore_rssi_cal(st
 	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
 }
 
+static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
+{
+	/* TODO */
+}
+
+static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 *save = nphy->tx_rx_cal_radio_saveregs;
+	int core, off;
+	u16 r, tmp;
+
+	for (core = 0; core < 2; core++) {
+		r = core ? 0x20 : 0;
+		off = core * 11;
+
+		save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
+		save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
+		save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
+		save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
+		save[off + 4] = 0;
+		save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
+		if (phy->radio_rev != 5)
+			save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
+		save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
+		save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
+
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+			b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
+			if (nphy->use_int_tx_iq_lo_cal) {
+				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
+				tmp = true ? 0x31 : 0x21; /* TODO */
+				b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
+			}
+			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
+		} else {
+			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+
+			if (phy->radio_rev != 5)
+				b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
+			if (nphy->use_int_tx_iq_lo_cal) {
+				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
+				tmp = true ? 0x31 : 0x21; /* TODO */
+				b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
+			}
+			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
+		}
+	}
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
 static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	u16 *save = nphy->tx_rx_cal_radio_saveregs;
 	u16 tmp;
 	u8 offset, i;
 
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		b43_nphy_tx_cal_radio_setup_rev19(dev);
+	} else if (phy->rev >= 7) {
+		b43_nphy_tx_cal_radio_setup_rev7(dev);
+	} else if (phy->rev >= 3) {
 	    for (i = 0; i < 2; i++) {
 		tmp = (i == 0) ? 0x2000 : 0x3000;
 		offset = i * 11;
@@ -4265,41 +4944,62 @@ static void b43_nphy_update_tx_cal_ladde
 	}
 }
 
+static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
+					  const s16 *filter)
+{
+	int i;
+
+	offset = B43_PHY_N(offset);
+
+	for (i = 0; i < 15; i++, offset++)
+		b43_phy_write(dev, offset, filter[i]);
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
 static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
 {
-	int i;
-	for (i = 0; i < 15; i++)
-		b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
-				tbl_tx_filter_coef_rev4[2][i]);
+	b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
+				      tbl_tx_filter_coef_rev4[2]);
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
 static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
 {
-	int i, j;
 	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
 	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
+	static const s16 dig_filter_phy_rev16[] = {
+		-375, 136, -407, 208, -1527,
+		956, 93, 186, 93, 230,
+		-44, 230, 201, -191, 201,
+	};
+	int i;
 
 	for (i = 0; i < 3; i++)
-		for (j = 0; j < 15; j++)
-			b43_phy_write(dev, B43_PHY_N(offset[i] + j),
-					tbl_tx_filter_coef_rev4[i][j]);
+		b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
+					      tbl_tx_filter_coef_rev4[i]);
 
-	if (dev->phy.is_40mhz) {
-		for (j = 0; j < 15; j++)
-			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
-					tbl_tx_filter_coef_rev4[3][j]);
-	} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-		for (j = 0; j < 15; j++)
-			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
-					tbl_tx_filter_coef_rev4[5][j]);
+	/* Verified with BCM43227 and BCM43228 */
+	if (dev->phy.rev == 16)
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+
+	/* Verified with BCM43131 and BCM43217 */
+	if (dev->phy.rev == 17) {
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
+					      tbl_tx_filter_coef_rev4[1]);
 	}
 
-	if (dev->phy.channel == 14)
-		for (j = 0; j < 15; j++)
-			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
-					tbl_tx_filter_coef_rev4[6][j]);
+	if (b43_is_40mhz(dev)) {
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+					      tbl_tx_filter_coef_rev4[3]);
+	} else {
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+						      tbl_tx_filter_coef_rev4[5]);
+		if (dev->phy.channel == 14)
+			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+						      tbl_tx_filter_coef_rev4[6]);
+	}
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
@@ -4321,7 +5021,13 @@ static struct nphy_txgains b43_nphy_get_
 			b43_nphy_stay_in_carrier_search(dev, false);
 
 		for (i = 0; i < 2; ++i) {
-			if (dev->phy.rev >= 3) {
+			if (dev->phy.rev >= 7) {
+				target.ipa[i] = curr_gain[i] & 0x0007;
+				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
+				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
+				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
+				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
+			} else if (dev->phy.rev >= 3) {
 				target.ipa[i] = curr_gain[i] & 0x000F;
 				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
 				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
@@ -4345,7 +5051,16 @@ static struct nphy_txgains b43_nphy_get_
 
 		for (i = 0; i < 2; ++i) {
 			table = b43_nphy_get_tx_gain_table(dev);
-			if (dev->phy.rev >= 3) {
+			if (!table)
+				break;
+
+			if (dev->phy.rev >= 7) {
+				target.ipa[i] = (table[index[i]] >> 16) & 0x7;
+				target.pad[i] = (table[index[i]] >> 19) & 0x1F;
+				target.pga[i] = (table[index[i]] >> 24) & 0xF;
+				target.txgm[i] = (table[index[i]] >> 28) & 0x7;
+				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
+			} else if (dev->phy.rev >= 3) {
 				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
 				target.pad[i] = (table[index[i]] >> 20) & 0xF;
 				target.pga[i] = (table[index[i]] >> 24) & 0xF;
@@ -4394,6 +5109,8 @@ static void b43_nphy_tx_cal_phy_cleanup(
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
 static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
 	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
 	u16 tmp;
 
@@ -4425,7 +5142,12 @@ static void b43_nphy_tx_cal_phy_setup(st
 		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
 		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
 
-		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3);
+		if (!nphy->use_int_tx_iq_lo_cal)
+			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+						      1, 3);
+		else
+			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+						      0, 3);
 		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
 		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
 
@@ -4433,6 +5155,33 @@ static void b43_nphy_tx_cal_phy_setup(st
 		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
 		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
 		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
+
+		tmp = b43_nphy_read_lpf_ctl(dev, 0);
+		if (phy->rev >= 19)
+			b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
+						       1);
+		else if (phy->rev >= 7)
+			b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
+						      1);
+
+		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
+			if (phy->rev >= 19) {
+				b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
+							       false, 0);
+			} else if (phy->rev >= 8) {
+				b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
+							      false, 0);
+			} else if (phy->rev == 7) {
+				b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
+				if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
+					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
+				} else {
+					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
+					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
+				}
+			}
+		}
 	} else {
 		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
 		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
@@ -4461,6 +5210,7 @@ static void b43_nphy_tx_cal_phy_setup(st
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
 static void b43_nphy_save_cal(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 
 	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
@@ -4485,7 +5235,26 @@ static void b43_nphy_save_cal(struct b43
 
 	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
 	/* TODO use some definitions */
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		txcal_radio_regs[0] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_FINE_I);
+		txcal_radio_regs[1] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_FINE_Q);
+		txcal_radio_regs[4] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_COARSE_I);
+		txcal_radio_regs[5] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_COARSE_Q);
+		txcal_radio_regs[2] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_FINE_I);
+		txcal_radio_regs[3] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_FINE_Q);
+		txcal_radio_regs[6] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_COARSE_I);
+		txcal_radio_regs[7] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_COARSE_Q);
+	} else if (phy->rev >= 3) {
 		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
 		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
 		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
@@ -4500,8 +5269,9 @@ static void b43_nphy_save_cal(struct b43
 		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
 		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
 	}
-	iqcal_chanspec->center_freq = dev->phy.channel_freq;
-	iqcal_chanspec->channel_type = dev->phy.channel_type;
+	iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;
+	iqcal_chanspec->channel_type =
+				cfg80211_get_chandef_type(dev->phy.chandef);
 	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
 
 	if (nphy->hang_avoid)
@@ -4511,6 +5281,7 @@ static void b43_nphy_save_cal(struct b43
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
 static void b43_nphy_restore_cal(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 
 	u16 coef[4];
@@ -4558,7 +5329,26 @@ static void b43_nphy_restore_cal(struct
 	}
 
 	/* TODO use some definitions */
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
+				txcal_radio_regs[0]);
+		b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
+				txcal_radio_regs[1]);
+		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
+				txcal_radio_regs[4]);
+		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
+				txcal_radio_regs[5]);
+		b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
+				txcal_radio_regs[2]);
+		b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
+				txcal_radio_regs[3]);
+		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
+				txcal_radio_regs[6]);
+		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
+				txcal_radio_regs[7]);
+	} else if (phy->rev >= 3) {
 		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
 		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
 		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
@@ -4581,6 +5371,7 @@ static int b43_nphy_cal_tx_iq_lo(struct
 				struct nphy_txgains target,
 				bool full, bool mphase)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	int i;
 	int error = 0;
@@ -4621,7 +5412,7 @@ static int b43_nphy_cal_tx_iq_lo(struct
 		(dev->phy.rev == 5 && nphy->ipa2g_on &&
 		b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
 	if (phy6or5x) {
-		if (dev->phy.is_40mhz) {
+		if (b43_is_40mhz(dev)) {
 			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
 					tbl_tx_iqlo_cal_loft_ladder_40);
 			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
@@ -4634,18 +5425,24 @@ static int b43_nphy_cal_tx_iq_lo(struct
 		}
 	}
 
-	b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
+	} else {
+		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
+	}
 
-	if (!dev->phy.is_40mhz)
+	if (!b43_is_40mhz(dev))
 		freq = 2500;
 	else
 		freq = 5000;
 
 	if (nphy->mphase_cal_phase_id > 2)
-		b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
-					0xFFFF, 0, true, false);
+		b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,
+				     0xFFFF, 0, true, false, false);
 	else
-		error = b43_nphy_tx_tone(dev, freq, 250, true, false);
+		error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);
 
 	if (error == 0) {
 		if (nphy->mphase_cal_phase_id > 2) {
@@ -4773,9 +5570,9 @@ static int b43_nphy_cal_tx_iq_lo(struct
 						nphy->txiqlocal_bestc);
 			nphy->txiqlocal_coeffsvalid = true;
 			nphy->txiqlocal_chanspec.center_freq =
-							dev->phy.channel_freq;
+						phy->chandef->chan->center_freq;
 			nphy->txiqlocal_chanspec.channel_type =
-							dev->phy.channel_type;
+					cfg80211_get_chandef_type(phy->chandef);
 		} else {
 			length = 11;
 			if (dev->phy.rev < 3)
@@ -4811,8 +5608,8 @@ static void b43_nphy_reapply_tx_cal_coef
 	bool equal = true;
 
 	if (!nphy->txiqlocal_coeffsvalid ||
-	    nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
-	    nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
+	    nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||
+	    nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))
 		return;
 
 	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
@@ -4968,11 +5765,11 @@ static int b43_nphy_rev2_cal_rx_iq(struc
 			if (playtone) {
 				ret = b43_nphy_tx_tone(dev, 4000,
 						(nphy->rxcalparams & 0xFFFF),
-						false, false);
+						false, false, true);
 				playtone = false;
 			} else {
-				b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
-							false, false);
+				b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,
+						     false, true);
 			}
 
 			if (ret == 0) {
@@ -5028,6 +5825,9 @@ static int b43_nphy_rev3_cal_rx_iq(struc
 static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
 			struct nphy_txgains target, u8 type, bool debug)
 {
+	if (dev->phy.rev >= 7)
+		type = 0;
+
 	if (dev->phy.rev >= 3)
 		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
 	else
@@ -5114,6 +5914,9 @@ static void b43_nphy_bphy_init(struct b4
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
 static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
 {
+	if (dev->phy.rev >= 7)
+		return;
+
 	if (dev->phy.rev >= 3) {
 		if (!init)
 			return;
@@ -5189,6 +5992,10 @@ static int b43_phy_initn(struct b43_wlde
 #endif
 		}
 	}
+	nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
+		phy->rev >= 7 ||
+		(phy->rev >= 5 &&
+		 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
 	nphy->deaf_count = 0;
 	b43_nphy_tables_init(dev);
 	nphy->crsminpwr_adjusted = false;
@@ -5198,6 +6005,16 @@ static int b43_phy_initn(struct b43_wlde
 	if (dev->phy.rev >= 3) {
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
 		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+		if (phy->rev >= 7) {
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
+		}
+		if (phy->rev >= 19) {
+			/* TODO */
+		}
+
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
 	} else {
@@ -5235,7 +6052,9 @@ static int b43_phy_initn(struct b43_wlde
 	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
 	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
 
-	b43_nphy_update_mimo_config(dev, nphy->preamble_override);
+	if (phy->rev < 8)
+		b43_nphy_update_mimo_config(dev, nphy->preamble_override);
+
 	b43_nphy_update_txrx_chain(dev);
 
 	if (phy->rev < 2) {
@@ -5267,10 +6086,12 @@ static int b43_phy_initn(struct b43_wlde
 
 	b43_mac_phy_clock_set(dev, true);
 
-	b43_nphy_pa_override(dev, false);
-	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
-	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
-	b43_nphy_pa_override(dev, true);
+	if (phy->rev < 7) {
+		b43_nphy_pa_override(dev, false);
+		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+		b43_nphy_pa_override(dev, true);
+	}
 
 	b43_nphy_classifier(dev, 0, 0);
 	b43_nphy_read_clip_detection(dev, clip);
@@ -5344,7 +6165,7 @@ static int b43_phy_initn(struct b43_wlde
 	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
 	if (phy->rev >= 3 && phy->rev <= 6)
 		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
-	b43_nphy_tx_lp_fbw(dev);
+	b43_nphy_tx_lpf_bw(dev);
 	if (phy->rev >= 3)
 		b43_nphy_spur_workaround(dev);
 
@@ -5393,23 +6214,26 @@ static void b43_nphy_channel_setup(struc
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 	int ch = new_channel->hw_value;
-
-	u16 old_band_5ghz;
 	u16 tmp16;
 
-	old_band_5ghz =
-		b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
-	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+	if (new_channel->band == IEEE80211_BAND_5GHZ) {
+		/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
+		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+
 		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
 		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
-		b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
+		/* Put BPHY in the reset */
+		b43_phy_set(dev, B43_PHY_B_BBCFG,
+			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
 		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
 		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
-	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+	} else if (new_channel->band == IEEE80211_BAND_2GHZ) {
 		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
 		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
 		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
-		b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
+		/* Take BPHY out of the reset */
+		b43_phy_mask(dev, B43_PHY_B_BBCFG,
+			     (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
 		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
 	}
 
@@ -5430,35 +6254,49 @@ static void b43_nphy_channel_setup(struc
 	if (dev->phy.rev < 3)
 		b43_nphy_adjust_lna_gain_table(dev);
 
-	b43_nphy_tx_lp_fbw(dev);
+	b43_nphy_tx_lpf_bw(dev);
 
 	if (dev->phy.rev >= 3 &&
 	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
-		bool avoid = false;
+		u8 spuravoid = 0;
+
 		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
-			avoid = true;
-		} else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
-			if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
-				avoid = true;
-		} else { /* 40MHz */
-			if (nphy->aband_spurwar_en &&
-			    (ch == 38 || ch == 102 || ch == 118))
-				avoid = dev->dev->chip_id == 0x4716;
+			spuravoid = 1;
+		} else if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 18) {
+			/* TODO */
+		} else if (phy->rev >= 17) {
+			/* TODO: Off for channels 1-11, but check 12-14! */
+		} else if (phy->rev >= 16) {
+			/* TODO: Off for 2 GHz, but check 5 GHz! */
+		} else if (phy->rev >= 7) {
+			if (!b43_is_40mhz(dev)) { /* 20MHz */
+				if (ch == 13 || ch == 14 || ch == 153)
+					spuravoid = 1;
+			} else { /* 40 MHz */
+				if (ch == 54)
+					spuravoid = 1;
+			}
+		} else {
+			if (!b43_is_40mhz(dev)) { /* 20MHz */
+				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
+					spuravoid = 1;
+			} else { /* 40MHz */
+				if (nphy->aband_spurwar_en &&
+				    (ch == 38 || ch == 102 || ch == 118))
+					spuravoid = dev->dev->chip_id == 0x4716;
+			}
 		}
 
-		b43_nphy_pmu_spur_avoid(dev, avoid);
+		b43_nphy_pmu_spur_avoid(dev, spuravoid);
 
-		if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
-		    dev->dev->chip_id == 43225) {
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
-				    avoid ? 0x5341 : 0x8889);
-			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
-		}
+		b43_mac_switch_freq(dev, spuravoid);
 
 		if (dev->phy.rev == 3 || dev->phy.rev == 4)
 			; /* TODO: reset PLL */
 
-		if (avoid)
+		if (spuravoid)
 			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
 		else
 			b43_phy_mask(dev, B43_NPHY_BBCFG,
@@ -5484,10 +6322,20 @@ static int b43_nphy_set_channel(struct b
 
 	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
 	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
+	const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;
+	const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
 
 	u8 tmp;
 
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		return -ESRCH;
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		r2057_get_chantabent_rev7(dev, channel->center_freq,
+					  &tabent_r7, &tabent_r7_2g);
+		if (!tabent_r7 && !tabent_r7_2g)
+			return -ESRCH;
+	} else if (phy->rev >= 3) {
 		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
 							channel->center_freq);
 		if (!tabent_r3)
@@ -5502,20 +6350,38 @@ static int b43_nphy_set_channel(struct b
 	/* Channel is set later in common code, but we need to set it on our
 	   own to let this function's subcalls work properly. */
 	phy->channel = channel->hw_value;
-	phy->channel_freq = channel->center_freq;
 
+#if 0
 	if (b43_channel_type_is_40mhz(phy->channel_type) !=
 		b43_channel_type_is_40mhz(channel_type))
 		; /* TODO: BMAC BW Set (channel_type) */
+#endif
 
-	if (channel_type == NL80211_CHAN_HT40PLUS)
-		b43_phy_set(dev, B43_NPHY_RXCTL,
-				B43_NPHY_RXCTL_BSELU20);
-	else if (channel_type == NL80211_CHAN_HT40MINUS)
-		b43_phy_mask(dev, B43_NPHY_RXCTL,
-				~B43_NPHY_RXCTL_BSELU20);
+	if (channel_type == NL80211_CHAN_HT40PLUS) {
+		b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);
+		if (phy->rev >= 7)
+			b43_phy_set(dev, 0x310, 0x8000);
+	} else if (channel_type == NL80211_CHAN_HT40MINUS) {
+		b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);
+		if (phy->rev >= 7)
+			b43_phy_mask(dev, 0x310, (u16)~0x8000);
+	}
 
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
+			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
+
+		if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+			tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 2 : 0;
+			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);
+			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);
+		}
+
+		b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);
+		b43_nphy_channel_setup(dev, phy_regs, channel);
+	} else if (phy->rev >= 3) {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
 		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
 		b43_radio_2056_setup(dev, tabent_r3);
@@ -5656,7 +6522,7 @@ static void b43_nphy_op_maskset(struct b
 static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
 {
 	/* Register 1 is a 32-bit register. */
-	B43_WARN_ON(reg == 1);
+	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
 
 	if (dev->phy.rev >= 7)
 		reg |= 0x200; /* Radio 0x2057 */
@@ -5670,7 +6536,7 @@ static u16 b43_nphy_op_radio_read(struct
 static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
 	/* Register 1 is a 32-bit register. */
-	B43_WARN_ON(reg == 1);
+	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
 
 	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
 	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
@@ -5680,15 +6546,23 @@ static void b43_nphy_op_radio_write(stru
 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
 					bool blocked)
 {
+	struct b43_phy *phy = &dev->phy;
+
 	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
 		b43err(dev->wl, "MAC not suspended\n");
 
 	if (blocked) {
-		b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
-				~B43_NPHY_RFCTL_CMD_CHIP0PU);
-		if (dev->phy.rev >= 7) {
+		if (phy->rev >= 19) {
 			/* TODO */
-		} else if (dev->phy.rev >= 3) {
+		} else if (phy->rev >= 8) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+		} else if (phy->rev >= 7) {
+			/* Nothing needed */
+		} else if (phy->rev >= 3) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+
 			b43_radio_mask(dev, 0x09, ~0x2);
 
 			b43_radio_write(dev, 0x204D, 0);
@@ -5706,11 +6580,13 @@ static void b43_nphy_op_software_rfkill(
 			b43_radio_write(dev, 0x3064, 0);
 		}
 	} else {
-		if (dev->phy.rev >= 7) {
+		if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 7) {
 			if (!dev->phy.radio_on)
 				b43_radio_2057_init(dev);
 			b43_switch_channel(dev, dev->phy.channel);
-		} else if (dev->phy.rev >= 3) {
+		} else if (phy->rev >= 3) {
 			if (!dev->phy.radio_on)
 				b43_radio_init2056(dev);
 			b43_switch_channel(dev, dev->phy.channel);
@@ -5723,10 +6599,13 @@ static void b43_nphy_op_software_rfkill(
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
 {
+	struct b43_phy *phy = &dev->phy;
 	u16 override = on ? 0x0 : 0x7FFF;
 	u16 core = on ? 0xD : 0x00FD;
 
-	if (dev->phy.rev >= 3) {
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 3) {
 		if (on) {
 			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
 			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_n.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_n.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/phy_n.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/phy_n.h	2014-09-28 17:29:07.000000000 -0400
@@ -366,11 +366,13 @@
 #define B43_NPHY_TXF_40CO_B1S0			B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
 #define B43_NPHY_TXF_40CO_B32S1			B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
 #define B43_NPHY_TXF_40CO_B1S1			B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
+#define B43_NPHY_REV3_RFCTL_OVER0		B43_PHY_N(0x0E7)
 #define B43_NPHY_TXF_40CO_B32S2			B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
 #define B43_NPHY_TXF_40CO_B1S2			B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
 #define B43_NPHY_BIST_STAT2			B43_PHY_N(0x0EA) /* BIST status 2 */
 #define B43_NPHY_BIST_STAT3			B43_PHY_N(0x0EB) /* BIST status 3 */
 #define B43_NPHY_RFCTL_OVER			B43_PHY_N(0x0EC) /* RF control override */
+#define B43_NPHY_REV3_RFCTL_OVER1		B43_PHY_N(0x0EC)
 #define B43_NPHY_MIMOCFG			B43_PHY_N(0x0ED) /* MIMO config */
 #define  B43_NPHY_MIMOCFG_GFMIX			0x0004 /* Greenfield or mixed mode */
 #define  B43_NPHY_MIMOCFG_AUTO			0x0100 /* Greenfield/mixed mode auto */
@@ -857,7 +859,18 @@
 #define B43_NPHY_REV3_C2_CLIP2_GAIN_A		B43_PHY_N(0x2AF)
 #define B43_NPHY_REV3_C2_CLIP2_GAIN_B		B43_PHY_N(0x2B0)
 
+#define B43_NPHY_REV7_RF_CTL_MISC_REG3		B43_PHY_N(0x340)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG4		B43_PHY_N(0x341)
+#define B43_NPHY_REV7_RF_CTL_OVER3		B43_PHY_N(0x342)
+#define B43_NPHY_REV7_RF_CTL_OVER4		B43_PHY_N(0x343)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG5		B43_PHY_N(0x344)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG6		B43_PHY_N(0x345)
+#define B43_NPHY_REV7_RF_CTL_OVER5		B43_PHY_N(0x346)
+#define B43_NPHY_REV7_RF_CTL_OVER6		B43_PHY_N(0x347)
+
 #define B43_PHY_B_BBCFG				B43_PHY_N_BMODE(0x001) /* BB config */
+#define  B43_PHY_B_BBCFG_RSTCCA			0x4000 /* Reset CCA */
+#define  B43_PHY_B_BBCFG_RSTRX			0x8000 /* Reset RX */
 #define B43_PHY_B_TEST				B43_PHY_N_BMODE(0x00A)
 
 struct b43_wldev;
@@ -935,6 +948,8 @@ struct b43_phy_n {
 	bool gain_boost;
 	bool elna_gain_config;
 	bool band5g_pwrgain;
+	bool use_int_tx_iq_lo_cal;
+	bool lpf_bw_overrode_for_sample_play;
 
 	u8 mphase_cal_phase_id;
 	u16 mphase_txcal_cmdidx;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/radio_2057.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/radio_2057.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/radio_2057.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/radio_2057.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 #include "radio_2057.h"
 #include "phy_common.h"
 
-static u16 r2057_rev4_init[42][2] = {
+static u16 r2057_rev4_init[][2] = {
 	{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
 	{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
 	{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
@@ -40,7 +40,7 @@ static u16 r2057_rev4_init[42][2] = {
 	{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
 };
 
-static u16 r2057_rev5_init[44][2] = {
+static u16 r2057_rev5_init[][2] = {
 	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
 	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
 	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
@@ -54,7 +54,7 @@ static u16 r2057_rev5_init[44][2] = {
 	{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
 };
 
-static u16 r2057_rev5a_init[45][2] = {
+static u16 r2057_rev5a_init[][2] = {
 	{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
 	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
 	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
@@ -69,7 +69,7 @@ static u16 r2057_rev5a_init[45][2] = {
 	{ 0x1C2, 0x80 },
 };
 
-static u16 r2057_rev7_init[54][2] = {
+static u16 r2057_rev7_init[][2] = {
 	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
 	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
 	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
@@ -86,7 +86,8 @@ static u16 r2057_rev7_init[54][2] = {
 	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
 };
 
-static u16 r2057_rev8_init[54][2] = {
+/* TODO: Which devices should use it?
+static u16 r2057_rev8_init[][2] = {
 	{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
 	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
 	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
@@ -102,6 +103,436 @@ static u16 r2057_rev8_init[54][2] = {
 	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
 	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
 };
+*/
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static u16 r2057_rev9_init[][2] = {
+	{ 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
+	{ 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
+	{ 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
+	{ 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
+	{ 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
+	{ 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
+	{ 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
+	{ 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static u16 r2057_rev14_init[][2] = {
+	{ 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
+	{ 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
+	{ 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
+	{ 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
+	{ 0x1d4, 0x0f },
+};
+
+#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		   r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		   r20, r21, r22, r23, r24, r25, r26, r27) \
+	.radio_vcocal_countval0			= r00,	\
+	.radio_vcocal_countval1			= r01,	\
+	.radio_rfpll_refmaster_sparextalsize	= r02,	\
+	.radio_rfpll_loopfilter_r1		= r03,	\
+	.radio_rfpll_loopfilter_c2		= r04,	\
+	.radio_rfpll_loopfilter_c1		= r05,	\
+	.radio_cp_kpd_idac			= r06,	\
+	.radio_rfpll_mmd0			= r07,	\
+	.radio_rfpll_mmd1			= r08,	\
+	.radio_vcobuf_tune			= r09,	\
+	.radio_logen_mx2g_tune			= r10,	\
+	.radio_logen_mx5g_tune			= r11,	\
+	.radio_logen_indbuf2g_tune		= r12,	\
+	.radio_logen_indbuf5g_tune		= r13,	\
+	.radio_txmix2g_tune_boost_pu_core0	= r14,	\
+	.radio_pad2g_tune_pus_core0		= r15,	\
+	.radio_pga_boost_tune_core0		= r16,	\
+	.radio_txmix5g_boost_tune_core0		= r17,	\
+	.radio_pad5g_tune_misc_pus_core0	= r18,	\
+	.radio_lna2g_tune_core0			= r19,	\
+	.radio_lna5g_tune_core0			= r20,	\
+	.radio_txmix2g_tune_boost_pu_core1	= r21,	\
+	.radio_pad2g_tune_pus_core1		= r22,	\
+	.radio_pga_boost_tune_core1		= r23,	\
+	.radio_txmix5g_boost_tune_core1		= r24,	\
+	.radio_pad5g_tune_misc_pus_core1	= r25,	\
+	.radio_lna2g_tune_core1			= r26,	\
+	.radio_lna5g_tune_core1			= r27
+
+#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		      r10, r11, r12, r13, r14, r15, r16, r17) \
+	.radio_vcocal_countval0			= r00,	\
+	.radio_vcocal_countval1			= r01,	\
+	.radio_rfpll_refmaster_sparextalsize	= r02,	\
+	.radio_rfpll_loopfilter_r1		= r03,	\
+	.radio_rfpll_loopfilter_c2		= r04,	\
+	.radio_rfpll_loopfilter_c1		= r05,	\
+	.radio_cp_kpd_idac			= r06,	\
+	.radio_rfpll_mmd0			= r07,	\
+	.radio_rfpll_mmd1			= r08,	\
+	.radio_vcobuf_tune			= r09,	\
+	.radio_logen_mx2g_tune			= r10,	\
+	.radio_logen_indbuf2g_tune		= r11,	\
+	.radio_txmix2g_tune_boost_pu_core0	= r12,	\
+	.radio_pad2g_tune_pus_core0		= r13,	\
+	.radio_lna2g_tune_core0			= r14,	\
+	.radio_txmix2g_tune_boost_pu_core1	= r15,	\
+	.radio_pad2g_tune_pus_core1		= r16,	\
+	.radio_lna2g_tune_core1			= r17
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+			      0x03, 0xff),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+			      0x03, 0xff),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
+			      0x03, 0xef),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+			      0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
+			      0x03, 0xdf),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
+			      0x03, 0xcf),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
+			      0x03, 0xbf),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
+			      0x03, 0xaf),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
+			      0x03, 0x9f),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
+			      0x03, 0x8f),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
+			      0x03, 0x7f),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
+			      0x03, 0x6f),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 2467,
+		RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+			      0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
+			      0x03, 0x5f),
+		PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+	},
+	{
+		.freq			= 2472,
+		RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
+			      0x03, 0x4f),
+		PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+	},
+	{
+		.freq			= 2484,
+		RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
+			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
+			      0x03, 0x3f),
+		PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+	}
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
+			      0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
+			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
+			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
+			      0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
+			      0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
+			      0x43, 0xff),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 5180,
+		RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
+			   0x3a, 0x83, 0x00, 0xfc),
+		PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+	},
+	{
+		.freq			= 5200,
+		RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
+			   0x4a, 0x83, 0x00, 0xf8),
+		PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+	},
+	{
+		.freq			= 5220,
+		RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
+			   0x2a, 0x73, 0x00, 0xf8),
+		PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+	},
+	{
+		.freq			= 5240,
+		RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
+			   0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
+			   0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
+			   0x2b, 0x73, 0x00, 0xf8),
+		PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+	},
+	{
+		.freq			= 5745,
+		RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
+			   0x02, 0x03, 0x00, 0x30),
+		PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+	},
+	{
+		.freq			= 5765,
+		RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+			   0x02, 0x03, 0x00, 0x00),
+		PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+	},
+	{
+		.freq			= 5785,
+		RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+			   0x21, 0x03, 0x00, 0x00),
+		PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+	},
+	{
+		.freq			= 5805,
+		RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
+			   0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
+			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+			   0x00, 0x03, 0x00, 0x00),
+		PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+	},
+	{
+		.freq			= 5825,
+		RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
+			   0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
+			   0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+			   0x00, 0x03, 0x00, 0x00),
+		PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+	},
+};
 
 void r2057_upload_inittabs(struct b43_wldev *dev)
 {
@@ -109,33 +540,98 @@ void r2057_upload_inittabs(struct b43_wl
 	u16 *table = NULL;
 	u16 size, i;
 
-	if (phy->rev == 7) {
+	switch (phy->rev) {
+	case 7:
 		table = r2057_rev4_init[0];
 		size = ARRAY_SIZE(r2057_rev4_init);
-	} else if (phy->rev == 8 || phy->rev == 9) {
+		break;
+	case 8:
 		if (phy->radio_rev == 5) {
-			if (phy->radio_rev == 8) {
-				table = r2057_rev5_init[0];
-				size = ARRAY_SIZE(r2057_rev5_init);
-			} else {
-				table = r2057_rev5a_init[0];
-				size = ARRAY_SIZE(r2057_rev5a_init);
-			}
+			table = r2057_rev5_init[0];
+			size = ARRAY_SIZE(r2057_rev5_init);
 		} else if (phy->radio_rev == 7) {
 			table = r2057_rev7_init[0];
 			size = ARRAY_SIZE(r2057_rev7_init);
-		} else if (phy->radio_rev == 9) {
-			table = r2057_rev8_init[0];
-			size = ARRAY_SIZE(r2057_rev8_init);
 		}
+		break;
+	case 9:
+		if (phy->radio_rev == 5) {
+			table = r2057_rev5a_init[0];
+			size = ARRAY_SIZE(r2057_rev5a_init);
+		}
+		break;
+	case 16:
+		if (phy->radio_rev == 9) {
+			table = r2057_rev9_init[0];
+			size = ARRAY_SIZE(r2057_rev9_init);
+		}
+		break;
+	case 17:
+		if (phy->radio_rev == 14) {
+			table = r2057_rev14_init[0];
+			size = ARRAY_SIZE(r2057_rev14_init);
+		}
+		break;
 	}
 
+	B43_WARN_ON(!table);
+
 	if (table) {
-		for (i = 0; i < 10; i++) {
-			pr_info("radio_write 0x%X ", *table);
-			table++;
-			pr_info("0x%X\n", *table);
-			table++;
+		for (i = 0; i < size; i++, table += 2)
+			b43_radio_write(dev, table[0], table[1]);
+	}
+}
+
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+			       const struct b43_nphy_chantabent_rev7 **tabent_r7,
+			       const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g)
+{
+	struct b43_phy *phy = &dev->phy;
+	const struct b43_nphy_chantabent_rev7 *e_r7 = NULL;
+	const struct b43_nphy_chantabent_rev7_2g *e_r7_2g = NULL;
+	unsigned int len, i;
+
+	*tabent_r7 = NULL;
+	*tabent_r7_2g = NULL;
+
+	switch (phy->rev) {
+	case 8:
+		if (phy->radio_rev == 5) {
+			e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
 		}
+		break;
+	case 16:
+		if (phy->radio_rev == 9) {
+			e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
+		}
+		break;
+	case 17:
+		if (phy->radio_rev == 14) {
+			e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (e_r7) {
+		for (i = 0; i < len; i++, e_r7++) {
+			if (e_r7->freq == freq) {
+				*tabent_r7 = e_r7;
+				return;
+			}
+		}
+	} else if (e_r7_2g) {
+		for (i = 0; i < len; i++, e_r7_2g++) {
+			if (e_r7_2g->freq == freq) {
+				*tabent_r7_2g = e_r7_2g;
+				return;
+			}
+		}
+	} else {
+		B43_WARN_ON(1);
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/radio_2057.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/radio_2057.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/radio_2057.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/radio_2057.h	2014-09-28 17:29:07.000000000 -0400
@@ -84,6 +84,8 @@
 #define R2057_CMOSBUF_RX_RCCR			0x04c
 #define R2057_LOGEN_SEL_PKDET			0x04d
 #define R2057_CMOSBUF_SHAREIQ_PTAT		0x04e
+
+/* MISC core 0 */
 #define R2057_RXTXBIAS_CONFIG_CORE0		0x04f
 #define R2057_TXGM_TXRF_PUS_CORE0		0x050
 #define R2057_TXGM_IDAC_BLEED_CORE0		0x051
@@ -204,6 +206,8 @@
 #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0	0x0d1
 #define R2057_LPF_GAIN_CORE0			0x0d2
 #define R2057_DACBUF_IDACS_BW_CORE0		0x0d3
+
+/* MISC core 1 */
 #define R2057_RXTXBIAS_CONFIG_CORE1		0x0d4
 #define R2057_TXGM_TXRF_PUS_CORE1		0x0d5
 #define R2057_TXGM_IDAC_BLEED_CORE1		0x0d6
@@ -324,6 +328,7 @@
 #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1	0x156
 #define R2057_LPF_GAIN_CORE1			0x157
 #define R2057_DACBUF_IDACS_BW_CORE1		0x158
+
 #define R2057_DACBUF_VINCM_CORE1		0x159
 #define R2057_RCCAL_START_R1_Q1_P1		0x15a
 #define R2057_RCCAL_X1				0x15b
@@ -345,6 +350,8 @@
 #define R2057_RCCAL_BCAP_VAL			0x16b
 #define R2057_RCCAL_HPC_VAL			0x16c
 #define R2057_RCCAL_OVERRIDES			0x16d
+
+/* TX core 0 */
 #define R2057_TX0_IQCAL_GAIN_BW			0x170
 #define R2057_TX0_LOFT_FINE_I			0x171
 #define R2057_TX0_LOFT_FINE_Q			0x172
@@ -362,6 +369,8 @@
 #define R2057_TX0_TXRXCOUPLE_2G_PWRUP		0x17e
 #define R2057_TX0_TXRXCOUPLE_5G_ATTEN		0x17f
 #define R2057_TX0_TXRXCOUPLE_5G_PWRUP		0x180
+
+/* TX core 1 */
 #define R2057_TX1_IQCAL_GAIN_BW			0x190
 #define R2057_TX1_LOFT_FINE_I			0x191
 #define R2057_TX1_LOFT_FINE_Q			0x192
@@ -379,6 +388,7 @@
 #define R2057_TX1_TXRXCOUPLE_2G_PWRUP		0x19e
 #define R2057_TX1_TXRXCOUPLE_5G_ATTEN		0x19f
 #define R2057_TX1_TXRXCOUPLE_5G_PWRUP		0x1a0
+
 #define R2057_AFE_VCM_CAL_MASTER_CORE0		0x1a1
 #define R2057_AFE_SET_VCM_I_CORE0		0x1a2
 #define R2057_AFE_SET_VCM_Q_CORE0		0x1a3
@@ -425,6 +435,72 @@
 
 #define R2057_VCM_MASK				0x7
 
+struct b43_nphy_chantabent_rev7 {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio regs values on channelswitch */
+	u8 radio_vcocal_countval0;
+	u8 radio_vcocal_countval1;
+	u8 radio_rfpll_refmaster_sparextalsize;
+	u8 radio_rfpll_loopfilter_r1;
+	u8 radio_rfpll_loopfilter_c2;
+	u8 radio_rfpll_loopfilter_c1;
+	u8 radio_cp_kpd_idac;
+	u8 radio_rfpll_mmd0;
+	u8 radio_rfpll_mmd1;
+	u8 radio_vcobuf_tune;
+	u8 radio_logen_mx2g_tune;
+	u8 radio_logen_mx5g_tune;
+	u8 radio_logen_indbuf2g_tune;
+	u8 radio_logen_indbuf5g_tune;
+	u8 radio_txmix2g_tune_boost_pu_core0;
+	u8 radio_pad2g_tune_pus_core0;
+	u8 radio_pga_boost_tune_core0;
+	u8 radio_txmix5g_boost_tune_core0;
+	u8 radio_pad5g_tune_misc_pus_core0;
+	u8 radio_lna2g_tune_core0;
+	u8 radio_lna5g_tune_core0;
+	u8 radio_txmix2g_tune_boost_pu_core1;
+	u8 radio_pad2g_tune_pus_core1;
+	u8 radio_pga_boost_tune_core1;
+	u8 radio_txmix5g_boost_tune_core1;
+	u8 radio_pad5g_tune_misc_pus_core1;
+	u8 radio_lna2g_tune_core1;
+	u8 radio_lna5g_tune_core1;
+	/* PHY res values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+struct b43_nphy_chantabent_rev7_2g {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio regs values on channelswitch */
+	u8 radio_vcocal_countval0;
+	u8 radio_vcocal_countval1;
+	u8 radio_rfpll_refmaster_sparextalsize;
+	u8 radio_rfpll_loopfilter_r1;
+	u8 radio_rfpll_loopfilter_c2;
+	u8 radio_rfpll_loopfilter_c1;
+	u8 radio_cp_kpd_idac;
+	u8 radio_rfpll_mmd0;
+	u8 radio_rfpll_mmd1;
+	u8 radio_vcobuf_tune;
+	u8 radio_logen_mx2g_tune;
+	u8 radio_logen_indbuf2g_tune;
+	u8 radio_txmix2g_tune_boost_pu_core0;
+	u8 radio_pad2g_tune_pus_core0;
+	u8 radio_lna2g_tune_core0;
+	u8 radio_txmix2g_tune_boost_pu_core1;
+	u8 radio_pad2g_tune_pus_core1;
+	u8 radio_lna2g_tune_core1;
+	/* PHY regs values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
 void r2057_upload_inittabs(struct b43_wldev *dev);
 
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+			       const struct b43_nphy_chantabent_rev7 **tabent_r7,
+			       const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g);
+
 #endif /* B43_RADIO_2057_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/tables_nphy.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/tables_nphy.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/tables_nphy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/tables_nphy.c	2014-09-28 17:29:07.000000000 -0400
@@ -2146,7 +2146,196 @@ static const u16 b43_ntab_antswctl_r3[4]
 	}
 };
 
-/* TX gain tables */
+/* static tables, PHY revision >= 7 */
+
+/* Copied from brcmsmac (5.75.11) */
+static const u32 b43_ntab_tmap_r7[] = {
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+	0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+	0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+	0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+	0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+	0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+	0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+	0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+	0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+	0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+	0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+	0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+	0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+	0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+	0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+	0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+	0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+	0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+	0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+	0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+	0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+	0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+	0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+	0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+	0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+	0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_noisevar_r7[] = {
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+};
+
+/**************************************************
+ * TX gain tables
+ **************************************************/
+
 static const u32 b43_ntab_tx_gain_rev0_1_2[] = {
 	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
 	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
@@ -2182,7 +2371,9 @@ static const u32 b43_ntab_tx_gain_rev0_1
 	0x03801442, 0x03801344, 0x03801342, 0x00002b00,
 };
 
-static const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
+/* EPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = {
 	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
 	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
 	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
@@ -2217,7 +2408,44 @@ static const u32 b43_ntab_tx_gain_rev3pl
 	0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
 };
 
-static const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+/* EPA 5 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = {
 	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
 	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
 	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
@@ -2252,7 +2480,7 @@ static const u32 b43_ntab_tx_gain_rev3_5
 	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037,
 };
 
-static const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = {
 	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
 	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
 	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
@@ -2287,7 +2515,42 @@ static const u32 b43_ntab_tx_gain_rev4_5
 	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
 };
 
-static const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = {
 	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
 	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
 	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
@@ -2322,7 +2585,9 @@ static const u32 b43_ntab_tx_gain_rev5pl
 	0x0062003b, 0x00620039, 0x00620037, 0x00620035,
 };
 
-static const u32 txpwrctrl_tx_gain_ipa[] = {
+/* IPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_2g[] = {
 	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
 	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
 	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
@@ -2357,7 +2622,7 @@ static const u32 txpwrctrl_tx_gain_ipa[]
 	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025,
 };
 
-static const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
+static const u32 b43_ntab_tx_gain_ipa_rev5_2g[] = {
 	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
 	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
 	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
@@ -2392,7 +2657,7 @@ static const u32 txpwrctrl_tx_gain_ipa_r
 	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025,
 };
 
-static const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
+static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = {
 	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
 	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
 	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
@@ -2427,7 +2692,117 @@ static const u32 txpwrctrl_tx_gain_ipa_r
 	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
 };
 
-static const u32 txpwrctrl_tx_gain_ipa_5g[] = {
+/* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
+	0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
+	0x60b70029, 0x60a70029, 0x609f002a, 0x6097002b,
+	0x6087002e, 0x60770031, 0x606f0032, 0x60670034,
+	0x60670031, 0x605f0033, 0x605f0031, 0x60570033,
+	0x60570030, 0x6057002d, 0x6057002b, 0x604f002d,
+	0x604f002b, 0x604f0029, 0x604f0026, 0x60470029,
+	0x60470027, 0x603f0029, 0x603f0027, 0x603f0025,
+	0x60370029, 0x60370027, 0x60370024, 0x602f002a,
+	0x602f0028, 0x602f0026, 0x602f0024, 0x6027002a,
+	0x60270028, 0x60270026, 0x60270024, 0x60270022,
+	0x601f002b, 0x601f0029, 0x601f0027, 0x601f0024,
+	0x601f0022, 0x601f0020, 0x601f001f, 0x601f001d,
+	0x60170029, 0x60170027, 0x60170025, 0x60170023,
+	0x60170021, 0x6017001f, 0x6017001d, 0x6017001c,
+	0x6017001a, 0x60170018, 0x60170018, 0x60170016,
+	0x60170015, 0x600f0029, 0x600f0027, 0x600f0025,
+	0x600f0023, 0x600f0021, 0x600f001f, 0x600f001d,
+	0x600f001c, 0x600f001a, 0x600f0019, 0x600f0018,
+	0x600f0016, 0x600f0015, 0x600f0115, 0x600f0215,
+	0x600f0315, 0x600f0415, 0x600f0515, 0x600f0615,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = {
+	0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b,
+	0x50af002a, 0x50a70029, 0x509f0029, 0x50970028,
+	0x508f0027, 0x50870027, 0x507f0027, 0x50770027,
+	0x506f0027, 0x50670027, 0x505f0028, 0x50570029,
+	0x504f002b, 0x5047002e, 0x5047002b, 0x50470029,
+	0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a,
+	0x50370028, 0x502f002d, 0x502f002b, 0x502f0028,
+	0x502f0026, 0x5027002d, 0x5027002a, 0x50270028,
+	0x50270026, 0x50270024, 0x501f002e, 0x501f002b,
+	0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022,
+	0x501f0020, 0x501f001f, 0x5017002c, 0x50170029,
+	0x50170027, 0x50170024, 0x50170022, 0x50170021,
+	0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a,
+	0x50170018, 0x50170017, 0x50170015, 0x500f002c,
+	0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023,
+	0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c,
+	0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+};
+
+/* IPA 2 5Hz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = {
 	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
 	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
 	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
@@ -2462,6 +2837,42 @@ static const u32 txpwrctrl_tx_gain_ipa_5
 	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f,
 };
 
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_5g[] = {
+	0x7f7f0053, 0x7f7f004b, 0x7f7f0044, 0x7f7f003f,
+	0x7f7f0039, 0x7f7f0035, 0x7f7f0032, 0x7f7f0030,
+	0x7f7f002d, 0x7e7f0030, 0x7e7f002d, 0x7d7f0032,
+	0x7d7f002f, 0x7d7f002c, 0x7c7f0032, 0x7c7f0030,
+	0x7c7f002d, 0x7b7f0030, 0x7b7f002e, 0x7b7f002b,
+	0x7a7f0032, 0x7a7f0030, 0x7a7f002d, 0x7a7f002b,
+	0x797f0030, 0x797f002e, 0x797f002b, 0x797f0029,
+	0x787f0030, 0x787f002d, 0x787f002b, 0x777f0032,
+	0x777f0030, 0x777f002d, 0x777f002b, 0x767f0031,
+	0x767f002f, 0x767f002c, 0x767f002a, 0x757f0031,
+	0x757f002f, 0x757f002c, 0x757f002a, 0x747f0030,
+	0x747f002d, 0x747f002b, 0x737f0032, 0x737f002f,
+	0x737f002c, 0x737f002a, 0x727f0030, 0x727f002d,
+	0x727f002b, 0x727f0029, 0x717f0030, 0x717f002d,
+	0x717f002b, 0x707f0031, 0x707f002f, 0x707f002c,
+	0x707f002a, 0x707f0027, 0x707f0025, 0x707f0023,
+	0x707f0021, 0x707f001f, 0x707f001d, 0x707f001c,
+	0x707f001a, 0x707f0019, 0x707f0017, 0x707f0016,
+	0x707f0015, 0x707f0014, 0x707f0012, 0x707f0012,
+	0x707f0011, 0x707f0010, 0x707f000f, 0x707f000e,
+	0x707f000d, 0x707f000d, 0x707f000c, 0x707f000b,
+	0x707f000a, 0x707f000a, 0x707f0009, 0x707f0008,
+	0x707f0008, 0x707f0008, 0x707f0008, 0x707f0007,
+	0x707f0007, 0x707f0006, 0x707f0006, 0x707f0006,
+	0x707f0005, 0x707f0005, 0x707f0005, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+};
+
 const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[] = {
 	-114, -108, -98, -91, -84, -78, -70, -62,
 	-54, -46, -39, -31, -23, -15, -8, 0
@@ -2698,11 +3109,11 @@ static const struct nphy_rf_control_over
 	{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
 	{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
 	{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
-	{ 0x0080, 0x0F8, 0x0FA, 0x0080, 7 },
+	{ 0x0080, 0x07A, 0x07D, 0x0080, 7 },
 	{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
 	{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
 	{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
-	{ 0x6000, 0x348, 0x349, 0xFFFF, 0 },
+	{ 0x6000, 0x348, 0x349, 0x00FF, 0 },
 	{ 0x2000, 0x348, 0x349, 0x000F, 0 },
 };
 
@@ -3031,6 +3442,91 @@ void b43_ntab_write_bulk(struct b43_wlde
 		b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
 	} while (0)
 
+static void b43_nphy_tables_init_shared_lut(struct b43_wldev *dev)
+{
+	ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+	ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+	ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+	ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+	ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+	ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+	ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+}
+
+static void b43_nphy_tables_init_rev7_volatile(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	u8 antswlut;
+	int core, offset, i;
+
+	const int antswlut0_offsets[] = { 0, 4, 8, }; /* Offsets for values */
+	const u8 antswlut0_values[][3] = {
+		{ 0x2, 0x12, 0x8 }, /* Core 0 */
+		{ 0x2, 0x18, 0x2 }, /* Core 1 */
+	};
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+		antswlut = sprom->fem.ghz5.antswlut;
+	else
+		antswlut = sprom->fem.ghz2.antswlut;
+
+	switch (antswlut) {
+	case 0:
+		for (core = 0; core < 2; core++) {
+			for (i = 0; i < ARRAY_SIZE(antswlut0_values[0]); i++) {
+				offset = core ? 0x20 : 0x00;
+				offset += antswlut0_offsets[i];
+				b43_ntab_write(dev, B43_NTAB8(9, offset),
+					       antswlut0_values[core][i]);
+			}
+		}
+		break;
+	default:
+		b43err(dev->wl, "Unsupported antswlut: %d\n", antswlut);
+		break;
+	}
+}
+
+static void b43_nphy_tables_init_rev16(struct b43_wldev *dev)
+{
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+		b43_nphy_tables_init_shared_lut(dev);
+	}
+
+	/* Volatile tables */
+	b43_nphy_tables_init_rev7_volatile(dev);
+}
+
+static void b43_nphy_tables_init_rev7(struct b43_wldev *dev)
+{
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+		ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+		ntab_upload(dev, B43_NTAB_TMAP_R7, b43_ntab_tmap_r7);
+		ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+		ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+		ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+		ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+		ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+		ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+		ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+		b43_nphy_tables_init_shared_lut(dev);
+	}
+
+	/* Volatile tables */
+	b43_nphy_tables_init_rev7_volatile(dev);
+}
+
 static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
 {
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -3057,16 +3553,7 @@ static void b43_nphy_tables_init_rev3(st
 		ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
 		ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
 		ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
-		ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
-		ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
-		ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
-		ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
-		ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
-		ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
-		ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
-		ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
-		ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
-		ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+		b43_nphy_tables_init_shared_lut(dev);
 	}
 
 	/* Volatile tables */
@@ -3115,7 +3602,11 @@ static void b43_nphy_tables_init_rev0(st
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
 void b43_nphy_tables_init(struct b43_wldev *dev)
 {
-	if (dev->phy.rev >= 3)
+	if (dev->phy.rev >= 16)
+		b43_nphy_tables_init_rev16(dev);
+	else if (dev->phy.rev >= 7)
+		b43_nphy_tables_init_rev7(dev);
+	else if (dev->phy.rev >= 3)
 		b43_nphy_tables_init_rev3(dev);
 	else
 		b43_nphy_tables_init_rev0(dev);
@@ -3124,23 +3615,55 @@ void b43_nphy_tables_init(struct b43_wld
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
 static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
+
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-		if (dev->phy.rev >= 6) {
-			if (dev->dev->chip_id == 47162)
-				return txpwrctrl_tx_gain_ipa_rev5;
-			return txpwrctrl_tx_gain_ipa_rev6;
-		} else if (dev->phy.rev >= 5) {
-			return txpwrctrl_tx_gain_ipa_rev5;
-		} else {
-			return txpwrctrl_tx_gain_ipa;
+		switch (phy->rev) {
+		case 17:
+			if (phy->radio_rev == 14)
+				return b43_ntab_tx_gain_ipa_2057_rev14_2g;
+			break;
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_tx_gain_ipa_2057_rev9_2g;
+			break;
+		case 8:
+			if (phy->radio_rev == 5)
+				return b43_ntab_tx_gain_ipa_2057_rev5_2g;
+			break;
+		case 6:
+			if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
+				return b43_ntab_tx_gain_ipa_rev5_2g;
+			return b43_ntab_tx_gain_ipa_rev6_2g;
+		case 5:
+			return b43_ntab_tx_gain_ipa_rev5_2g;
+		case 4:
+		case 3:
+			return b43_ntab_tx_gain_ipa_rev3_2g;
 		}
+
+		b43err(dev->wl,
+		       "No 2GHz IPA gain table available for this device\n");
+		return NULL;
 	} else {
-		return txpwrctrl_tx_gain_ipa_5g;
+		switch (phy->rev) {
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_tx_gain_ipa_2057_rev9_5g;
+			break;
+		case 3 ... 6:
+			return b43_ntab_tx_gain_ipa_rev3_5g;
+		}
+
+		b43err(dev->wl,
+		       "No 5GHz IPA gain table available for this device\n");
+		return NULL;
 	}
 }
 
 const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
 {
+	struct b43_phy *phy = &dev->phy;
 	enum ieee80211_band band = b43_current_band(dev->wl);
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
@@ -3152,19 +3675,36 @@ const u32 *b43_nphy_get_tx_gain_table(st
 	    (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)) {
 		return b43_nphy_get_ipa_gain_table(dev);
 	} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-		if (dev->phy.rev == 3)
-			return b43_ntab_tx_gain_rev3_5ghz;
-		if (dev->phy.rev == 4)
+		switch (phy->rev) {
+		case 6:
+		case 5:
+			return b43_ntab_tx_gain_epa_rev5_5g;
+		case 4:
 			return sprom->fem.ghz5.extpa_gain == 3 ?
-				b43_ntab_tx_gain_rev4_5ghz :
-				b43_ntab_tx_gain_rev4_5ghz; /* FIXME */
-		else
-			return b43_ntab_tx_gain_rev5plus_5ghz;
+				b43_ntab_tx_gain_epa_rev4_5g :
+				b43_ntab_tx_gain_epa_rev4_hi_pwr_5g;
+		case 3:
+			return b43_ntab_tx_gain_epa_rev3_5g;
+		default:
+			b43err(dev->wl,
+			       "No 5GHz EPA gain table available for this device\n");
+			return NULL;
+		}
 	} else {
-		if (dev->phy.rev >= 5 && sprom->fem.ghz5.extpa_gain == 3)
-			return b43_ntab_tx_gain_rev3plus_2ghz; /* FIXME */
-		else
-			return b43_ntab_tx_gain_rev3plus_2ghz;
+		switch (phy->rev) {
+		case 6:
+		case 5:
+			if (sprom->fem.ghz5.extpa_gain == 3)
+				return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
+			/* fall through */
+		case 4:
+		case 3:
+			return b43_ntab_tx_gain_epa_rev3_2g;
+		default:
+			b43err(dev->wl,
+			       "No 2GHz EPA gain table available for this device\n");
+			return NULL;
+		}
 	}
 }
 
@@ -3191,7 +3731,7 @@ struct nphy_gain_ctl_workaround_entry *b
 	/* Some workarounds to the workarounds... */
 	if (ghz5 && dev->phy.rev >= 6) {
 		if (dev->phy.radio_rev == 11 &&
-		    !b43_channel_type_is_40mhz(dev->phy.channel_type))
+		    !b43_is_40mhz(dev))
 			e->cliplo_gain = 0x2d;
 	} else if (!ghz5 && dev->phy.rev >= 5) {
 		static const int gain_data[] = {0x0062, 0x0064, 0x006a, 0x106a,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/tables_nphy.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/tables_nphy.h
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/tables_nphy.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/tables_nphy.h	2014-09-28 17:29:07.000000000 -0400
@@ -165,6 +165,10 @@ struct nphy_gain_ctl_workaround_entry *b
 #define B43_NTAB_C1_LOFEEDTH_R3		B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
 #define B43_NTAB_C1_PAPD_COMP_R3	B43_NTAB16(27, 576)
 
+/* Static N-PHY tables, PHY revision >= 7 */
+#define B43_NTAB_TMAP_R7		B43_NTAB32(12,   0) /* TM AP */
+#define B43_NTAB_NOISEVAR_R7		B43_NTAB32(16,   0) /* noise variance */
+
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE	18
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/b43/xmit.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/xmit.c
--- linux-libre-3.16-gnu/drivers/net/wireless/b43/xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/b43/xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,9 +80,10 @@ static int b43_plcp_get_bitrate_idx_cck(
 }
 
 /* Extract the bitrate index out of an OFDM PLCP header. */
-static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
+static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
 {
-	int base = aphy ? 0 : 4;
+	/* For 2 GHz band first OFDM rate is at index 4, see main.c */
+	int base = ghz5 ? 0 : 4;
 
 	switch (plcp->raw[0] & 0xF) {
 	case 0xB:
@@ -767,7 +768,7 @@ void b43_rx(struct b43_wldev *dev, struc
 
 	if (phystat0 & B43_RX_PHYST0_OFDM)
 		rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
-						phytype == B43_PHYTYPE_A);
+					!!(chanstat & B43_RX_CHAN_5GHZ));
 	else
 		rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
 	if (unlikely(rate_idx == -1)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c	2014-09-28 17:29:07.000000000 -0400
@@ -337,6 +337,23 @@ brcmf_proto_bcdc_txdata(struct brcmf_pub
 	return brcmf_bus_txdata(drvr->bus_if, pktbuf);
 }
 
+static void
+brcmf_proto_bcdc_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				     enum proto_addr_mode addr_mode)
+{
+}
+
+static void
+brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
+			     u8 peer[ETH_ALEN])
+{
+}
+
+static void
+brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
+			       u8 peer[ETH_ALEN])
+{
+}
 
 int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
 {
@@ -356,6 +373,9 @@ int brcmf_proto_bcdc_attach(struct brcmf
 	drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
 	drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
 	drvr->proto->txdata = brcmf_proto_bcdc_txdata;
+	drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
+	drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
+	drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
 	drvr->proto->pd = bcdc;
 
 	drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,9 +16,12 @@
 #ifndef BRCMFMAC_BCDC_H
 #define BRCMFMAC_BCDC_H
 
-
+#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
 int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
 void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
-
+#else
+static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
+static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
+#endif
 
 #endif /* BRCMFMAC_BCDC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
@@ -39,10 +38,13 @@
 #include <brcm_hw_ids.h>
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
+#include <chipcommon.h>
 #include <soc.h>
+#include "chip.h"
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
 #include "sdio_host.h"
+#include "of.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
 
@@ -118,6 +120,7 @@ int brcmf_sdiod_intr_register(struct brc
 {
 	int ret = 0;
 	u8 data;
+	u32 addr, gpiocontrol;
 	unsigned long flags;
 
 	if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
@@ -147,6 +150,19 @@ int brcmf_sdiod_intr_register(struct brc
 
 		sdio_claim_host(sdiodev->func[1]);
 
+		if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
+			/* assign GPIO to SDIO core */
+			addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol);
+			gpiocontrol = brcmf_sdiod_regrl(sdiodev, addr, &ret);
+			gpiocontrol |= 0x2;
+			brcmf_sdiod_regwl(sdiodev, addr, gpiocontrol, &ret);
+
+			brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_SELECT, 0xf,
+					  &ret);
+			brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
+			brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
+		}
+
 		/* must configure SDIO_CCCR_IENx to enable irq */
 		data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
 		data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
@@ -979,18 +995,20 @@ out:
 	return ret;
 }
 
+#define BRCMF_SDIO_DEVICE(dev_id)	\
+	{SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
+
 /* devices we support, null terminated */
 static const struct sdio_device_id brcmf_sdmmc_ids[] = {
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
-		     SDIO_DEVICE_ID_BROADCOM_4335_4339)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)},
-	{ /* end: all zeroes */ },
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
+	BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
+	{ /* end: all zeroes */ }
 };
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
 
@@ -1043,6 +1061,9 @@ static int brcmf_ops_sdio_probe(struct s
 	sdiodev->dev = &sdiodev->func[1]->dev;
 	sdiodev->pdata = brcmfmac_sdio_pdata;
 
+	if (!sdiodev->pdata)
+		brcmf_of_probe(sdiodev);
+
 	atomic_set(&sdiodev->suspend, false);
 	init_waitqueue_head(&sdiodev->request_word_wait);
 	init_waitqueue_head(&sdiodev->request_buffer_wait);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c	2014-09-28 17:29:07.000000000 -0400
@@ -157,7 +157,7 @@ static void brcmf_btcoex_boost_wifi(stru
 		 */
 
 		/* save current */
-		brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n");
+		brcmf_dbg(INFO, "new SCO/eSCO coex algo {save & override}\n");
 		brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
 		brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
 		brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
@@ -165,7 +165,7 @@ static void brcmf_btcoex_boost_wifi(stru
 		brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
 
 		btci->saved_regs_part2 = true;
-		brcmf_dbg(TRACE,
+		brcmf_dbg(INFO,
 			  "saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 			  btci->reg50, btci->reg51, btci->reg64,
 			  btci->reg65, btci->reg71);
@@ -179,21 +179,21 @@ static void brcmf_btcoex_boost_wifi(stru
 
 	} else if (btci->saved_regs_part2) {
 		/* restore previously saved bt params */
-		brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n");
+		brcmf_dbg(INFO, "Do new SCO/eSCO coex algo {restore}\n");
 		brcmf_btcoex_params_write(ifp, 50, btci->reg50);
 		brcmf_btcoex_params_write(ifp, 51, btci->reg51);
 		brcmf_btcoex_params_write(ifp, 64, btci->reg64);
 		brcmf_btcoex_params_write(ifp, 65, btci->reg65);
 		brcmf_btcoex_params_write(ifp, 71, btci->reg71);
 
-		brcmf_dbg(TRACE,
+		brcmf_dbg(INFO,
 			  "restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 			  btci->reg50, btci->reg51, btci->reg64,
 			  btci->reg65, btci->reg71);
 
 		btci->saved_regs_part2 = false;
 	} else {
-		brcmf_err("attempted to restore not saved BTCOEX params\n");
+		brcmf_dbg(INFO, "attempted to restore not saved BTCOEX params\n");
 	}
 }
 
@@ -219,14 +219,14 @@ static bool brcmf_btcoex_is_sco_active(s
 			break;
 		}
 
-		brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27);
+		brcmf_dbg(INFO, "sample[%d], btc_params 27:%x\n", i, param27);
 
 		if ((param27 & 0x6) == 2) { /* count both sco & esco  */
 			sco_id_cnt++;
 		}
 
 		if (sco_id_cnt > 2) {
-			brcmf_dbg(TRACE,
+			brcmf_dbg(INFO,
 				  "sco/esco detected, pkt id_cnt:%d samples:%d\n",
 				  sco_id_cnt, i);
 			res = true;
@@ -250,7 +250,7 @@ static void btcmf_btcoex_save_part1(stru
 		brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
 		brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
 		btci->saved_regs_part1 = true;
-		brcmf_dbg(TRACE,
+		brcmf_dbg(INFO,
 			  "saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
 			  btci->reg66, btci->reg41,
 			  btci->reg68);
@@ -270,7 +270,7 @@ static void brcmf_btcoex_restore_part1(s
 		brcmf_btcoex_params_write(ifp, 66, btci->reg66);
 		brcmf_btcoex_params_write(ifp, 41, btci->reg41);
 		brcmf_btcoex_params_write(ifp, 68, btci->reg68);
-		brcmf_dbg(TRACE,
+		brcmf_dbg(INFO,
 			  "restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
 			  btci->reg66, btci->reg41,
 			  btci->reg68);
@@ -307,7 +307,7 @@ static void brcmf_btcoex_handler(struct
 		/* DHCP started provide OPPORTUNITY window
 		   to get DHCP address
 		*/
-		brcmf_dbg(TRACE, "DHCP started\n");
+		brcmf_dbg(INFO, "DHCP started\n");
 		btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
 		if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
 			mod_timer(&btci->timer, btci->timer.expires);
@@ -322,12 +322,12 @@ static void brcmf_btcoex_handler(struct
 
 	case BRCMF_BT_DHCP_OPPR_WIN:
 		if (btci->dhcp_done) {
-			brcmf_dbg(TRACE, "DHCP done before T1 expiration\n");
+			brcmf_dbg(INFO, "DHCP done before T1 expiration\n");
 			goto idle;
 		}
 
 		/* DHCP is not over yet, start lowering BT priority */
-		brcmf_dbg(TRACE, "DHCP T1:%d expired\n",
+		brcmf_dbg(INFO, "DHCP T1:%d expired\n",
 			  BRCMF_BTCOEX_OPPR_WIN_TIME);
 		brcmf_btcoex_boost_wifi(btci, true);
 
@@ -339,9 +339,9 @@ static void brcmf_btcoex_handler(struct
 
 	case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
 		if (btci->dhcp_done)
-			brcmf_dbg(TRACE, "DHCP done before T2 expiration\n");
+			brcmf_dbg(INFO, "DHCP done before T2 expiration\n");
 		else
-			brcmf_dbg(TRACE, "DHCP T2:%d expired\n",
+			brcmf_dbg(INFO, "DHCP T2:%d expired\n",
 				  BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
 
 		goto idle;
@@ -440,13 +440,13 @@ static void brcmf_btcoex_dhcp_end(struct
 	/* Stop any bt timer because DHCP session is done */
 	btci->dhcp_done = true;
 	if (btci->timer_on) {
-		brcmf_dbg(TRACE, "disable BT DHCP Timer\n");
+		brcmf_dbg(INFO, "disable BT DHCP Timer\n");
 		btci->timer_on = false;
 		del_timer_sync(&btci->timer);
 
 		/* schedule worker if transition to IDLE is needed */
 		if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
-			brcmf_dbg(TRACE, "bt_state:%d\n",
+			brcmf_dbg(INFO, "bt_state:%d\n",
 				  btci->bt_state);
 			schedule_work(&btci->work);
 		}
@@ -472,7 +472,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c
 
 	switch (mode) {
 	case BRCMF_BTCOEX_DISABLED:
-		brcmf_dbg(TRACE, "DHCP session starts\n");
+		brcmf_dbg(INFO, "DHCP session starts\n");
 		if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
 			return -EBUSY;
 		/* Start BT timer only for SCO connection */
@@ -484,14 +484,14 @@ int brcmf_btcoex_set_mode(struct brcmf_c
 		break;
 
 	case BRCMF_BTCOEX_ENABLED:
-		brcmf_dbg(TRACE, "DHCP session ends\n");
+		brcmf_dbg(INFO, "DHCP session ends\n");
 		if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
 		    vif == btci->vif) {
 			brcmf_btcoex_dhcp_end(btci);
 		}
 		break;
 	default:
-		brcmf_dbg(TRACE, "Unknown mode, ignored\n");
+		brcmf_dbg(INFO, "Unknown mode, ignored\n");
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/chip.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/chip.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/chip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/chip.c	2014-09-28 17:29:07.000000000 -0400
@@ -482,33 +482,41 @@ static inline int brcmf_chip_cores_check
 static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
 {
 	switch (ci->pub.chip) {
-	case BCM4329_CHIP_ID:
+	case BRCM_CC_4329_CHIP_ID:
 		ci->pub.ramsize = BCM4329_RAMSIZE;
 		break;
-	case BCM43143_CHIP_ID:
+	case BRCM_CC_43143_CHIP_ID:
 		ci->pub.ramsize = BCM43143_RAMSIZE;
 		break;
-	case BCM43241_CHIP_ID:
+	case BRCM_CC_43241_CHIP_ID:
 		ci->pub.ramsize = 0x90000;
 		break;
-	case BCM4330_CHIP_ID:
+	case BRCM_CC_4330_CHIP_ID:
 		ci->pub.ramsize = 0x48000;
 		break;
-	case BCM4334_CHIP_ID:
+	case BRCM_CC_4334_CHIP_ID:
 		ci->pub.ramsize = 0x80000;
 		break;
-	case BCM4335_CHIP_ID:
+	case BRCM_CC_4335_CHIP_ID:
 		ci->pub.ramsize = 0xc0000;
 		ci->pub.rambase = 0x180000;
 		break;
-	case BCM43362_CHIP_ID:
+	case BRCM_CC_43362_CHIP_ID:
 		ci->pub.ramsize = 0x3c000;
 		break;
-	case BCM4339_CHIP_ID:
-	case BCM4354_CHIP_ID:
+	case BRCM_CC_4339_CHIP_ID:
+	case BRCM_CC_4354_CHIP_ID:
+	case BRCM_CC_4356_CHIP_ID:
+	case BRCM_CC_43567_CHIP_ID:
+	case BRCM_CC_43569_CHIP_ID:
+	case BRCM_CC_43570_CHIP_ID:
 		ci->pub.ramsize = 0xc0000;
 		ci->pub.rambase = 0x180000;
 		break;
+	case BRCM_CC_43602_CHIP_ID:
+		ci->pub.ramsize = 0xf0000;
+		ci->pub.rambase = 0x180000;
+		break;
 	default:
 		brcmf_err("unknown chip: %s\n", ci->pub.name);
 		break;
@@ -682,7 +690,7 @@ static int brcmf_chip_recognition(struct
 		  ci->pub.chiprev);
 
 	if (socitype == SOCI_SB) {
-		if (ci->pub.chip != BCM4329_CHIP_ID) {
+		if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
 			brcmf_err("SB chip is not supported\n");
 			return -ENODEV;
 		}
@@ -1008,13 +1016,13 @@ bool brcmf_chip_sr_capable(struct brcmf_
 	chip = container_of(pub, struct brcmf_chip_priv, pub);
 
 	switch (pub->chip) {
-	case BCM4354_CHIP_ID:
+	case BRCM_CC_4354_CHIP_ID:
 		/* explicitly check SR engine enable bit */
 		pmu_cc3_mask = BIT(2);
 		/* fall-through */
-	case BCM43241_CHIP_ID:
-	case BCM4335_CHIP_ID:
-	case BCM4339_CHIP_ID:
+	case BRCM_CC_43241_CHIP_ID:
+	case BRCM_CC_4335_CHIP_ID:
+	case BRCM_CC_4339_CHIP_ID:
 		/* read PMU chipcontrol register 3 */
 		addr = CORE_CC_REG(base, chipcontrol_addr);
 		chip->ops->write32(chip->ctx, addr, 3);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,273 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "commonring.h"
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ * SEE ALSO msgbuf.c
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+				  int (*cr_ring_bell)(void *ctx),
+				  int (*cr_update_rptr)(void *ctx),
+				  int (*cr_update_wptr)(void *ctx),
+				  int (*cr_write_rptr)(void *ctx),
+				  int (*cr_write_wptr)(void *ctx), void *ctx)
+{
+	commonring->cr_ring_bell = cr_ring_bell;
+	commonring->cr_update_rptr = cr_update_rptr;
+	commonring->cr_update_wptr = cr_update_wptr;
+	commonring->cr_write_rptr = cr_write_rptr;
+	commonring->cr_write_wptr = cr_write_wptr;
+	commonring->cr_ctx = ctx;
+}
+
+
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+			     u16 item_len, void *buf_addr)
+{
+	commonring->depth = depth;
+	commonring->item_len = item_len;
+	commonring->buf_addr = buf_addr;
+	if (!commonring->inited) {
+		spin_lock_init(&commonring->lock);
+		commonring->inited = true;
+	}
+	commonring->r_ptr = 0;
+	if (commonring->cr_write_rptr)
+		commonring->cr_write_rptr(commonring->cr_ctx);
+	commonring->w_ptr = 0;
+	if (commonring->cr_write_wptr)
+		commonring->cr_write_wptr(commonring->cr_ctx);
+	commonring->f_ptr = 0;
+}
+
+
+void brcmf_commonring_lock(struct brcmf_commonring *commonring)
+		__acquires(&commonring->lock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&commonring->lock, flags);
+	commonring->flags = flags;
+}
+
+
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
+		__releases(&commonring->lock)
+{
+	spin_unlock_irqrestore(&commonring->lock, commonring->flags);
+}
+
+
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
+{
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		if (!commonring->was_full)
+			return true;
+		if (available > commonring->depth / 8) {
+			commonring->was_full = false;
+			return true;
+		}
+		if (retry) {
+			if (commonring->cr_update_rptr)
+				commonring->cr_update_rptr(commonring->cr_ctx);
+			retry = false;
+			goto again;
+		}
+		return false;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return false;
+}
+
+
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
+{
+	void *ret_ptr;
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		ret_ptr = commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len);
+		commonring->w_ptr++;
+		if (commonring->w_ptr == commonring->depth)
+			commonring->w_ptr = 0;
+		return ret_ptr;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return NULL;
+}
+
+
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+					    u16 n_items, u16 *alloced)
+{
+	void *ret_ptr;
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		ret_ptr = commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len);
+		*alloced = min_t(u16, n_items, available - 1);
+		if (*alloced + commonring->w_ptr > commonring->depth)
+			*alloced = commonring->depth - commonring->w_ptr;
+		commonring->w_ptr += *alloced;
+		if (commonring->w_ptr == commonring->depth)
+			commonring->w_ptr = 0;
+		return ret_ptr;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return NULL;
+}
+
+
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
+{
+	void *address;
+
+	address = commonring->buf_addr;
+	address += (commonring->f_ptr * commonring->item_len);
+	if (commonring->f_ptr > commonring->w_ptr) {
+		brcmf_dma_flush(address,
+				(commonring->depth - commonring->f_ptr) *
+				commonring->item_len);
+		address = commonring->buf_addr;
+		commonring->f_ptr = 0;
+	}
+	brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
+			commonring->item_len);
+
+	commonring->f_ptr = commonring->w_ptr;
+
+	if (commonring->cr_write_wptr)
+		commonring->cr_write_wptr(commonring->cr_ctx);
+	if (commonring->cr_ring_bell)
+		return commonring->cr_ring_bell(commonring->cr_ctx);
+
+	return -EIO;
+}
+
+
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+				   u16 n_items)
+{
+	if (commonring->w_ptr == 0)
+		commonring->w_ptr = commonring->depth - n_items;
+	else
+		commonring->w_ptr -= n_items;
+}
+
+
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+				    u16 *n_items)
+{
+	void *ret_addr;
+
+	if (commonring->cr_update_wptr)
+		commonring->cr_update_wptr(commonring->cr_ctx);
+
+	*n_items = (commonring->w_ptr >= commonring->r_ptr) ?
+				(commonring->w_ptr - commonring->r_ptr) :
+				(commonring->depth - commonring->r_ptr);
+
+	if (*n_items == 0)
+		return NULL;
+
+	ret_addr = commonring->buf_addr +
+		   (commonring->r_ptr * commonring->item_len);
+
+	commonring->r_ptr += *n_items;
+	if (commonring->r_ptr == commonring->depth)
+		commonring->r_ptr = 0;
+
+	brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
+
+	return ret_addr;
+}
+
+
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
+{
+	if (commonring->cr_write_rptr)
+		return commonring->cr_write_rptr(commonring->cr_ctx);
+
+	return -EIO;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/commonring.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,69 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_COMMONRING_H
+#define BRCMFMAC_COMMONRING_H
+
+
+struct brcmf_commonring {
+	u16 r_ptr;
+	u16 w_ptr;
+	u16 f_ptr;
+	u16 depth;
+	u16 item_len;
+
+	void *buf_addr;
+
+	int (*cr_ring_bell)(void *ctx);
+	int (*cr_update_rptr)(void *ctx);
+	int (*cr_update_wptr)(void *ctx);
+	int (*cr_write_rptr)(void *ctx);
+	int (*cr_write_wptr)(void *ctx);
+
+	void *cr_ctx;
+
+	spinlock_t lock;
+	unsigned long flags;
+	bool inited;
+	bool was_full;
+};
+
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+				  int (*cr_ring_bell)(void *ctx),
+				  int (*cr_update_rptr)(void *ctx),
+				  int (*cr_update_wptr)(void *ctx),
+				  int (*cr_write_rptr)(void *ctx),
+				  int (*cr_write_wptr)(void *ctx), void *ctx);
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+			     u16 item_len, void *buf_addr);
+void brcmf_commonring_lock(struct brcmf_commonring *commonring);
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring);
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring);
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring);
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+					    u16 n_items, u16 *alloced);
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring);
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+				   u16 n_items);
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+				    u16 *n_items);
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
+
+#define brcmf_commonring_n_items(commonring) (commonring->depth)
+#define brcmf_commonring_len_item(commonring) (commonring->item_len)
+
+
+#endif /* BRCMFMAC_COMMONRING_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,18 @@
 
 #include "dhd_dbg.h"
 
+/* IDs of the 6 default common rings of msgbuf protocol */
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT	0
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT		1
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE	2
+#define BRCMF_D2H_MSGRING_TX_COMPLETE		3
+#define BRCMF_D2H_MSGRING_RX_COMPLETE		4
+
+#define BRCMF_NROF_H2D_COMMON_MSGRINGS		2
+#define BRCMF_NROF_D2H_COMMON_MSGRINGS		3
+#define BRCMF_NROF_COMMON_MSGRINGS	(BRCMF_NROF_H2D_COMMON_MSGRINGS + \
+					 BRCMF_NROF_D2H_COMMON_MSGRINGS)
+
 /* The level of bus communication with the dongle */
 enum brcmf_bus_state {
 	BRCMF_BUS_UNKNOWN,	/* Not determined yet */
@@ -70,6 +82,25 @@ struct brcmf_bus_ops {
 	struct pktq * (*gettxq)(struct device *dev);
 };
 
+
+/**
+ * struct brcmf_bus_msgbuf - bus ringbuf if in case of msgbuf.
+ *
+ * @commonrings: commonrings which are always there.
+ * @flowrings: commonrings which are dynamically created and destroyed for data.
+ * @rx_dataoffset: if set then all rx data has this this offset.
+ * @max_rxbufpost: maximum number of buffers to post for rx.
+ * @nrof_flowrings: number of flowrings.
+ */
+struct brcmf_bus_msgbuf {
+	struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+	struct brcmf_commonring **flowrings;
+	u32 rx_dataoffset;
+	u32 max_rxbufpost;
+	u32 nrof_flowrings;
+};
+
+
 /**
  * struct brcmf_bus - interface structure between common and bus layer
  *
@@ -89,6 +120,7 @@ struct brcmf_bus {
 	union {
 		struct brcmf_sdio_dev *sdio;
 		struct brcmf_usbdev *usb;
+		struct brcmf_pciedev *pcie;
 	} bus_priv;
 	enum brcmf_bus_protocol_type proto_type;
 	struct device *dev;
@@ -101,6 +133,7 @@ struct brcmf_bus {
 	bool always_use_fws_queue;
 
 	struct brcmf_bus_ops *ops;
+	struct brcmf_bus_msgbuf *msgbuf;
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -282,6 +282,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
 	ptr = strrchr(buf, ' ') + 1;
 	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
 
+	/* set mpc */
+	err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
+	if (err) {
+		brcmf_err("failed setting mpc\n");
+		goto done;
+	}
+
 	/*
 	 * Setup timeout if Beacons are lost and roam is off to report
 	 * link down
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void)
 	root_folder = NULL;
 }
 
-static
-ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
-				   size_t count, loff_t *ppos)
-{
-	struct brcmf_pub *drvr = f->private_data;
-	struct brcmf_bus *bus = drvr->bus_if;
-	char buf[40];
-	int res;
-
-	/* only allow read from start */
-	if (*ppos > 0)
-		return 0;
-
-	res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n",
-			bus->chip, bus->chip, bus->chiprev);
-	return simple_read_from_buffer(data, count, ppos, buf, res);
-}
-
-static const struct file_operations brcmf_debugfs_chipinfo_ops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = brcmf_debugfs_chipinfo_read
-};
-
-static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr)
+static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
 {
-	struct dentry *dentry =  drvr->dbgfs_dir;
+	struct brcmf_bus *bus = dev_get_drvdata(seq->private);
 
-	if (!IS_ERR_OR_NULL(dentry))
-		debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr,
-				    &brcmf_debugfs_chipinfo_ops);
+	seq_printf(seq, "chip: %x(%u) rev %u\n",
+		   bus->chip, bus->chip, bus->chiprev);
 	return 0;
 }
 
@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pu
 		return -ENODEV;
 
 	drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
-	brcmf_debugfs_create_chipinfo(drvr);
+	brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
+
 	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
 }
 
@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(
 	return drvr->dbgfs_dir;
 }
 
-static
-ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data,
-					size_t count, loff_t *ppos)
-{
-	struct brcmf_sdio_count *sdcnt = f->private_data;
-	char buf[750];
-	int res;
-
-	/* only allow read from start */
-	if (*ppos > 0)
-		return 0;
+struct brcmf_debugfs_entry {
+	int (*read)(struct seq_file *seq, void *data);
+	struct brcmf_pub *drvr;
+};
 
-	res = scnprintf(buf, sizeof(buf),
-			"intrcount:    %u\nlastintrs:    %u\n"
-			"pollcnt:      %u\nregfails:     %u\n"
-			"tx_sderrs:    %u\nfcqueued:     %u\n"
-			"rxrtx:        %u\nrx_toolong:   %u\n"
-			"rxc_errors:   %u\nrx_hdrfail:   %u\n"
-			"rx_badhdr:    %u\nrx_badseq:    %u\n"
-			"fc_rcvd:      %u\nfc_xoff:      %u\n"
-			"fc_xon:       %u\nrxglomfail:   %u\n"
-			"rxglomframes: %u\nrxglompkts:   %u\n"
-			"f2rxhdrs:     %u\nf2rxdata:     %u\n"
-			"f2txdata:     %u\nf1regdata:    %u\n"
-			"tickcnt:      %u\ntx_ctlerrs:   %lu\n"
-			"tx_ctlpkts:   %lu\nrx_ctlerrs:   %lu\n"
-			"rx_ctlpkts:   %lu\nrx_readahead: %lu\n",
-			sdcnt->intrcount, sdcnt->lastintrs,
-			sdcnt->pollcnt, sdcnt->regfails,
-			sdcnt->tx_sderrs, sdcnt->fcqueued,
-			sdcnt->rxrtx, sdcnt->rx_toolong,
-			sdcnt->rxc_errors, sdcnt->rx_hdrfail,
-			sdcnt->rx_badhdr, sdcnt->rx_badseq,
-			sdcnt->fc_rcvd, sdcnt->fc_xoff,
-			sdcnt->fc_xon, sdcnt->rxglomfail,
-			sdcnt->rxglomframes, sdcnt->rxglompkts,
-			sdcnt->f2rxhdrs, sdcnt->f2rxdata,
-			sdcnt->f2txdata, sdcnt->f1regdata,
-			sdcnt->tickcnt, sdcnt->tx_ctlerrs,
-			sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
-			sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
+static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
+{
+	struct brcmf_debugfs_entry *entry = inode->i_private;
 
-	return simple_read_from_buffer(data, count, ppos, buf, res);
+	return single_open(f, entry->read, entry->drvr->bus_if->dev);
 }
 
-static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
+static const struct file_operations brcmf_debugfs_def_ops = {
 	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = brcmf_debugfs_sdio_counter_read
+	.open = brcmf_debugfs_entry_open,
+	.release = single_release,
+	.read = seq_read,
+	.llseek = seq_lseek
 };
 
-void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
-				     struct brcmf_sdio_count *sdcnt)
-{
-	struct dentry *dentry = drvr->dbgfs_dir;
-
-	if (!IS_ERR_OR_NULL(dentry))
-		debugfs_create_file("counters", S_IRUGO, dentry,
-				    sdcnt, &brcmf_debugfs_sdio_counter_ops);
-}
-
-static
-ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
-				     size_t count, loff_t *ppos)
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data))
 {
-	struct brcmf_fws_stats *fwstats = f->private_data;
-	char buf[650];
-	int res;
-
-	/* only allow read from start */
-	if (*ppos > 0)
-		return 0;
+	struct dentry *dentry =  drvr->dbgfs_dir;
+	struct brcmf_debugfs_entry *entry;
 
-	res = scnprintf(buf, sizeof(buf),
-			"header_pulls:      %u\n"
-			"header_only_pkt:   %u\n"
-			"tlv_parse_failed:  %u\n"
-			"tlv_invalid_type:  %u\n"
-			"mac_update_fails:  %u\n"
-			"ps_update_fails:   %u\n"
-			"if_update_fails:   %u\n"
-			"pkt2bus:           %u\n"
-			"generic_error:     %u\n"
-			"rollback_success:  %u\n"
-			"rollback_failed:   %u\n"
-			"delayq_full:       %u\n"
-			"supprq_full:       %u\n"
-			"txs_indicate:      %u\n"
-			"txs_discard:       %u\n"
-			"txs_suppr_core:    %u\n"
-			"txs_suppr_ps:      %u\n"
-			"txs_tossed:        %u\n"
-			"txs_host_tossed:   %u\n"
-			"bus_flow_block:    %u\n"
-			"fws_flow_block:    %u\n"
-			"send_pkts:         BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
-			"requested_sent:    BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
-			fwstats->header_pulls,
-			fwstats->header_only_pkt,
-			fwstats->tlv_parse_failed,
-			fwstats->tlv_invalid_type,
-			fwstats->mac_update_failed,
-			fwstats->mac_ps_update_failed,
-			fwstats->if_update_failed,
-			fwstats->pkt2bus,
-			fwstats->generic_error,
-			fwstats->rollback_success,
-			fwstats->rollback_failed,
-			fwstats->delayq_full_error,
-			fwstats->supprq_full_error,
-			fwstats->txs_indicate,
-			fwstats->txs_discard,
-			fwstats->txs_supp_core,
-			fwstats->txs_supp_ps,
-			fwstats->txs_tossed,
-			fwstats->txs_host_tossed,
-			fwstats->bus_flow_block,
-			fwstats->fws_flow_block,
-			fwstats->send_pkts[0], fwstats->send_pkts[1],
-			fwstats->send_pkts[2], fwstats->send_pkts[3],
-			fwstats->send_pkts[4],
-			fwstats->requested_sent[0],
-			fwstats->requested_sent[1],
-			fwstats->requested_sent[2],
-			fwstats->requested_sent[3],
-			fwstats->requested_sent[4]);
+	if (IS_ERR_OR_NULL(dentry))
+		return -ENOENT;
 
-	return simple_read_from_buffer(data, count, ppos, buf, res);
-}
+	entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
 
-static const struct file_operations brcmf_debugfs_fws_stats_ops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = brcmf_debugfs_fws_stats_read
-};
+	entry->read = read_fn;
+	entry->drvr = drvr;
 
-void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
-				    struct brcmf_fws_stats *stats)
-{
-	struct dentry *dentry =  drvr->dbgfs_dir;
+	dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
+				     &brcmf_debugfs_def_ops);
 
-	if (!IS_ERR_OR_NULL(dentry))
-		debugfs_create_file("fws_stats", S_IRUGO, dentry,
-				    stats, &brcmf_debugfs_fws_stats_ops);
+	return PTR_ERR_OR_ZERO(dentry);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,23 +18,25 @@
 #define _BRCMF_DBG_H_
 
 /* message levels */
-#define BRCMF_TRACE_VAL	0x00000002
-#define BRCMF_INFO_VAL	0x00000004
-#define BRCMF_DATA_VAL	0x00000008
-#define BRCMF_CTL_VAL	0x00000010
-#define BRCMF_TIMER_VAL	0x00000020
-#define BRCMF_HDRS_VAL	0x00000040
-#define BRCMF_BYTES_VAL	0x00000080
-#define BRCMF_INTR_VAL	0x00000100
-#define BRCMF_GLOM_VAL	0x00000200
-#define BRCMF_EVENT_VAL	0x00000400
-#define BRCMF_BTA_VAL	0x00000800
-#define BRCMF_FIL_VAL	0x00001000
-#define BRCMF_USB_VAL	0x00002000
-#define BRCMF_SCAN_VAL	0x00004000
-#define BRCMF_CONN_VAL	0x00008000
-#define BRCMF_BCDC_VAL	0x00010000
-#define BRCMF_SDIO_VAL	0x00020000
+#define BRCMF_TRACE_VAL		0x00000002
+#define BRCMF_INFO_VAL		0x00000004
+#define BRCMF_DATA_VAL		0x00000008
+#define BRCMF_CTL_VAL		0x00000010
+#define BRCMF_TIMER_VAL		0x00000020
+#define BRCMF_HDRS_VAL		0x00000040
+#define BRCMF_BYTES_VAL		0x00000080
+#define BRCMF_INTR_VAL		0x00000100
+#define BRCMF_GLOM_VAL		0x00000200
+#define BRCMF_EVENT_VAL		0x00000400
+#define BRCMF_BTA_VAL		0x00000800
+#define BRCMF_FIL_VAL		0x00001000
+#define BRCMF_USB_VAL		0x00002000
+#define BRCMF_SCAN_VAL		0x00004000
+#define BRCMF_CONN_VAL		0x00008000
+#define BRCMF_BCDC_VAL		0x00010000
+#define BRCMF_SDIO_VAL		0x00020000
+#define BRCMF_MSGBUF_VAL	0x00040000
+#define BRCMF_PCIE_VAL		0x00080000
 
 /* set default print format */
 #undef pr_fmt
@@ -100,68 +102,6 @@ do {									\
 
 extern int brcmf_msg_level;
 
-/*
- * hold counter variables used in brcmfmac sdio driver.
- */
-struct brcmf_sdio_count {
-	uint intrcount;		/* Count of device interrupt callbacks */
-	uint lastintrs;		/* Count as of last watchdog timer */
-	uint pollcnt;		/* Count of active polls */
-	uint regfails;		/* Count of R_REG failures */
-	uint tx_sderrs;		/* Count of tx attempts with sd errors */
-	uint fcqueued;		/* Tx packets that got queued */
-	uint rxrtx;		/* Count of rtx requests (NAK to dongle) */
-	uint rx_toolong;	/* Receive frames too long to receive */
-	uint rxc_errors;	/* SDIO errors when reading control frames */
-	uint rx_hdrfail;	/* SDIO errors on header reads */
-	uint rx_badhdr;		/* Bad received headers (roosync?) */
-	uint rx_badseq;		/* Mismatched rx sequence number */
-	uint fc_rcvd;		/* Number of flow-control events received */
-	uint fc_xoff;		/* Number which turned on flow-control */
-	uint fc_xon;		/* Number which turned off flow-control */
-	uint rxglomfail;	/* Failed deglom attempts */
-	uint rxglomframes;	/* Number of glom frames (superframes) */
-	uint rxglompkts;	/* Number of packets from glom frames */
-	uint f2rxhdrs;		/* Number of header reads */
-	uint f2rxdata;		/* Number of frame data reads */
-	uint f2txdata;		/* Number of f2 frame writes */
-	uint f1regdata;		/* Number of f1 register accesses */
-	uint tickcnt;		/* Number of watchdog been schedule */
-	ulong tx_ctlerrs;	/* Err of sending ctrl frames */
-	ulong tx_ctlpkts;	/* Ctrl frames sent to dongle */
-	ulong rx_ctlerrs;	/* Err of processing rx ctrl frames */
-	ulong rx_ctlpkts;	/* Ctrl frames processed from dongle */
-	ulong rx_readahead_cnt;	/* packets where header read-ahead was used */
-};
-
-struct brcmf_fws_stats {
-	u32 tlv_parse_failed;
-	u32 tlv_invalid_type;
-	u32 header_only_pkt;
-	u32 header_pulls;
-	u32 pkt2bus;
-	u32 send_pkts[5];
-	u32 requested_sent[5];
-	u32 generic_error;
-	u32 mac_update_failed;
-	u32 mac_ps_update_failed;
-	u32 if_update_failed;
-	u32 packet_request_failed;
-	u32 credit_request_failed;
-	u32 rollback_success;
-	u32 rollback_failed;
-	u32 delayq_full_error;
-	u32 supprq_full_error;
-	u32 txs_indicate;
-	u32 txs_discard;
-	u32 txs_supp_core;
-	u32 txs_supp_ps;
-	u32 txs_tossed;
-	u32 txs_host_tossed;
-	u32 bus_flow_block;
-	u32 fws_flow_block;
-};
-
 struct brcmf_pub;
 #ifdef DEBUG
 void brcmf_debugfs_init(void);
@@ -169,10 +109,8 @@ void brcmf_debugfs_exit(void);
 int brcmf_debugfs_attach(struct brcmf_pub *drvr);
 void brcmf_debugfs_detach(struct brcmf_pub *drvr);
 struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
-void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
-				     struct brcmf_sdio_count *sdcnt);
-void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
-				    struct brcmf_fws_stats *stats);
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data));
 #else
 static inline void brcmf_debugfs_init(void)
 {
@@ -187,9 +125,11 @@ static inline int brcmf_debugfs_attach(s
 static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
 {
 }
-static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
-						  struct brcmf_fws_stats *stats)
+static inline
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data))
 {
+	return 0;
 }
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd.h	2014-09-28 17:29:07.000000000 -0400
@@ -49,16 +49,6 @@
  */
 #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN	32
 
-/* Bus independent dongle command */
-struct brcmf_dcmd {
-	uint cmd;		/* common dongle cmd definition */
-	void *buf;		/* pointer to user buffer */
-	uint len;		/* length of user buffer */
-	u8 set;			/* get or set request (optional) */
-	uint used;		/* bytes read or written (optional) */
-	uint needed;		/* bytes needed (optional) */
-};
-
 /**
  * struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info
  *
@@ -113,6 +103,10 @@ struct brcmf_pub {
 
 	struct brcmf_ampdu_rx_reorder
 		*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
+
+	u32 feat_flags;
+	u32 chip_quirks;
+
 #ifdef DEBUG
 	struct dentry *dbgfs_dir;
 #endif
@@ -127,12 +121,12 @@ struct brcmf_fws_mac_descriptor;
  *
  * @BRCMF_NETIF_STOP_REASON_FWS_FC:
  *	netif stopped due to firmware signalling flow control.
- * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS:
- *	netif stopped due to bus blocking.
+ * @BRCMF_NETIF_STOP_REASON_FLOW:
+ *	netif stopped due to flowring full.
  */
 enum brcmf_netif_stop_reason {
 	BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
-	BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2
+	BRCMF_NETIF_STOP_REASON_FLOW = 2
 };
 
 /**
@@ -185,9 +179,9 @@ struct brcmf_if *brcmf_add_if(struct brc
 void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
 void brcmf_txflowblock_if(struct brcmf_if *ifp,
 			  enum brcmf_netif_stop_reason reason, bool state);
-u32 brcmf_get_chip_info(struct brcmf_if *ifp);
 void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
 		      bool success);
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
 
 /* Sets dongle media info (drv_version, mac address). */
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,9 @@
 #include "wl_cfg80211.h"
 #include "fwil.h"
 #include "fwsignal.h"
+#include "feature.h"
 #include "proto.h"
+#include "pcie.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -287,7 +289,7 @@ void brcmf_txflowblock(struct device *de
 	brcmf_fws_bus_blocked(drvr, state);
 }
 
-static void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
 {
 	skb->dev = ifp->ndev;
 	skb->protocol = eth_type_trans(skb, skb->dev);
@@ -808,7 +810,8 @@ struct brcmf_if *brcmf_add_if(struct brc
 	} else {
 		brcmf_dbg(INFO, "allocate netdev interface\n");
 		/* Allocate netdev, including space for private structure */
-		ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
+		ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN,
+				    ether_setup);
 		if (!ndev)
 			return ERR_PTR(-ENOMEM);
 
@@ -936,6 +939,8 @@ int brcmf_bus_start(struct device *dev)
 	if (ret < 0)
 		goto fail;
 
+	brcmf_feat_attach(drvr);
+
 	ret = brcmf_fws_init(drvr);
 	if (ret < 0)
 		goto fail;
@@ -1073,16 +1078,6 @@ int brcmf_netdev_wait_pend8021x(struct n
 	return !err;
 }
 
-/*
- * return chip id and rev of the device encoded in u32.
- */
-u32 brcmf_get_chip_info(struct brcmf_if *ifp)
-{
-	struct brcmf_bus *bus = ifp->drvr->bus_if;
-
-	return bus->chip << 4 | bus->chiprev;
-}
-
 static void brcmf_driver_register(struct work_struct *work)
 {
 #ifdef CONFIG_BRCMFMAC_SDIO
@@ -1091,6 +1086,9 @@ static void brcmf_driver_register(struct
 #ifdef CONFIG_BRCMFMAC_USB
 	brcmf_usb_register();
 #endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+	brcmf_pcie_register();
+#endif
 }
 static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
 
@@ -1116,6 +1114,9 @@ static void __exit brcmfmac_module_exit(
 #ifdef CONFIG_BRCMFMAC_USB
 	brcmf_usb_exit();
 #endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+	brcmf_pcie_exit();
+#endif
 	brcmf_debugfs_exit();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c	2014-08-07 04:53:48.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c	2014-09-28 21:35:38.000000000 -0400
@@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo {
 	u16 tail_pad;
 };
 
+/*
+ * hold counter variables
+ */
+struct brcmf_sdio_count {
+	uint intrcount;		/* Count of device interrupt callbacks */
+	uint lastintrs;		/* Count as of last watchdog timer */
+	uint pollcnt;		/* Count of active polls */
+	uint regfails;		/* Count of R_REG failures */
+	uint tx_sderrs;		/* Count of tx attempts with sd errors */
+	uint fcqueued;		/* Tx packets that got queued */
+	uint rxrtx;		/* Count of rtx requests (NAK to dongle) */
+	uint rx_toolong;	/* Receive frames too long to receive */
+	uint rxc_errors;	/* SDIO errors when reading control frames */
+	uint rx_hdrfail;	/* SDIO errors on header reads */
+	uint rx_badhdr;		/* Bad received headers (roosync?) */
+	uint rx_badseq;		/* Mismatched rx sequence number */
+	uint fc_rcvd;		/* Number of flow-control events received */
+	uint fc_xoff;		/* Number which turned on flow-control */
+	uint fc_xon;		/* Number which turned off flow-control */
+	uint rxglomfail;	/* Failed deglom attempts */
+	uint rxglomframes;	/* Number of glom frames (superframes) */
+	uint rxglompkts;	/* Number of packets from glom frames */
+	uint f2rxhdrs;		/* Number of header reads */
+	uint f2rxdata;		/* Number of frame data reads */
+	uint f2txdata;		/* Number of f2 frame writes */
+	uint f1regdata;		/* Number of f1 register accesses */
+	uint tickcnt;		/* Number of watchdog been schedule */
+	ulong tx_ctlerrs;	/* Err of sending ctrl frames */
+	ulong tx_ctlpkts;	/* Ctrl frames sent to dongle */
+	ulong rx_ctlerrs;	/* Err of processing rx ctrl frames */
+	ulong rx_ctlpkts;	/* Ctrl frames processed from dongle */
+	ulong rx_readahead_cnt;	/* packets where header read-ahead was used */
+};
+
 /* misc chip info needed by some of the routines */
 /* Private data for SDIO bus interaction */
 struct brcmf_sdio {
@@ -601,40 +635,57 @@ enum brcmf_firmware_type {
 	name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
 
 static const struct brcmf_firmware_names brcmf_fwname_data[] = {
-	{ BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
-	{ BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
-	{ BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
-	{ BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
-	{ BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
-	{ BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
-	{ BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
-	{ BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
-	{ BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
-	{ BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+	{ BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
+	{ BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
+	{ BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
+	{ BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
+	{ BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
+	{ BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
+	{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+	{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+	{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+	{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
 };
 
-static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci,
-					 enum brcmf_firmware_type type)
+static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
+				  struct brcmf_sdio_dev *sdiodev)
 {
 	int i;
+	uint fw_len, nv_len;
+	char end;
 
 	for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
 		if (brcmf_fwname_data[i].chipid == ci->chip &&
-		    brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) {
-			switch (type) {
-			case BRCMF_FIRMWARE_BIN:
-				return brcmf_fwname_data[i].bin;
-			case BRCMF_FIRMWARE_NVRAM:
-				return brcmf_fwname_data[i].nv;
-			default:
-				brcmf_err("invalid firmware type (%d)\n", type);
-				return NULL;
-			}
+		    brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(brcmf_fwname_data)) {
+		brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
+		return -ENODEV;
+	}
+
+	fw_len = sizeof(sdiodev->fw_name) - 1;
+	nv_len = sizeof(sdiodev->nvram_name) - 1;
+	/* check if firmware path is provided by module parameter */
+	if (brcmf_firmware_path[0] != '\0') {
+		strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
+		strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
+		fw_len -= strlen(sdiodev->fw_name);
+		nv_len -= strlen(sdiodev->nvram_name);
+
+		end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+		if (end != '/') {
+			strncat(sdiodev->fw_name, "/", fw_len);
+			strncat(sdiodev->nvram_name, "/", nv_len);
+			fw_len--;
+			nv_len--;
 		}
 	}
-	brcmf_err("Unknown chipid %d [%d]\n",
-		  ci->chip, ci->chiprev);
-	return NULL;
+	strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
+	strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
+
+	return 0;
 }
 
 static void pkt_align(struct sk_buff *p, int len, int align)
@@ -2879,16 +2930,13 @@ brcmf_sdio_bus_txctl(struct device *dev,
 }
 
 #ifdef DEBUG
-static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
-				   struct sdpcm_shared *sh, char __user *data,
-				   size_t count)
+static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus,
+				   struct sdpcm_shared *sh)
 {
 	u32 addr, console_ptr, console_size, console_index;
 	char *conbuf = NULL;
 	__le32 sh_val;
 	int rv;
-	loff_t pos = 0;
-	int nbytes = 0;
 
 	/* obtain console information from device memory */
 	addr = sh->console_addr + offsetof(struct rte_console, log_le);
@@ -2926,33 +2974,24 @@ static int brcmf_sdio_dump_console(struc
 	if (rv < 0)
 		goto done;
 
-	rv = simple_read_from_buffer(data, count, &pos,
-				     conbuf + console_index,
-				     console_size - console_index);
+	rv = seq_write(seq, conbuf + console_index,
+		       console_size - console_index);
 	if (rv < 0)
 		goto done;
 
-	nbytes = rv;
-	if (console_index > 0) {
-		pos = 0;
-		rv = simple_read_from_buffer(data+nbytes, count, &pos,
-					     conbuf, console_index - 1);
-		if (rv < 0)
-			goto done;
-		rv += nbytes;
-	}
+	if (console_index > 0)
+		rv = seq_write(seq, conbuf, console_index - 1);
+
 done:
 	vfree(conbuf);
 	return rv;
 }
 
-static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
-				char __user *data, size_t count)
+static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
+				struct sdpcm_shared *sh)
 {
-	int error, res;
-	char buf[350];
+	int error;
 	struct brcmf_trap_info tr;
-	loff_t pos = 0;
 
 	if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
 		brcmf_dbg(INFO, "no trap in firmware\n");
@@ -2964,34 +3003,30 @@ static int brcmf_sdio_trap_info(struct b
 	if (error < 0)
 		return error;
 
-	res = scnprintf(buf, sizeof(buf),
-			"dongle trap info: type 0x%x @ epc 0x%08x\n"
-			"  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
-			"  lr   0x%08x pc   0x%08x offset 0x%x\n"
-			"  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
-			"  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
-			le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
-			le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
-			le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
-			le32_to_cpu(tr.pc), sh->trap_addr,
-			le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
-			le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
-			le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
-			le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+	seq_printf(seq,
+		   "dongle trap info: type 0x%x @ epc 0x%08x\n"
+		   "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+		   "  lr   0x%08x pc   0x%08x offset 0x%x\n"
+		   "  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
+		   "  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
+		   le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+		   le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+		   le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+		   le32_to_cpu(tr.pc), sh->trap_addr,
+		   le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+		   le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+		   le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+		   le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
 
-	return simple_read_from_buffer(data, count, &pos, buf, res);
+	return 0;
 }
 
-static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
-				  struct sdpcm_shared *sh, char __user *data,
-				  size_t count)
+static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus,
+				  struct sdpcm_shared *sh)
 {
 	int error = 0;
-	char buf[200];
 	char file[80] = "?";
 	char expr[80] = "<???>";
-	int res;
-	loff_t pos = 0;
 
 	if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
 		brcmf_dbg(INFO, "firmware not built with -assert\n");
@@ -3016,10 +3051,9 @@ static int brcmf_sdio_assert_info(struct
 	}
 	sdio_release_host(bus->sdiodev->func[1]);
 
-	res = scnprintf(buf, sizeof(buf),
-			"dongle assert: %s:%d: assert(%s)\n",
-			file, sh->assert_line, expr);
-	return simple_read_from_buffer(data, count, &pos, buf, res);
+	seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
+		   file, sh->assert_line, expr);
+	return 0;
 }
 
 static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
@@ -3043,59 +3077,75 @@ static int brcmf_sdio_checkdied(struct b
 	return 0;
 }
 
-static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data,
-				size_t count, loff_t *ppos)
+static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus)
 {
 	int error = 0;
 	struct sdpcm_shared sh;
-	int nbytes = 0;
-	loff_t pos = *ppos;
-
-	if (pos != 0)
-		return 0;
 
 	error = brcmf_sdio_readshared(bus, &sh);
 	if (error < 0)
 		goto done;
 
-	error = brcmf_sdio_assert_info(bus, &sh, data, count);
+	error = brcmf_sdio_assert_info(seq, bus, &sh);
 	if (error < 0)
 		goto done;
-	nbytes = error;
 
-	error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
+	error = brcmf_sdio_trap_info(seq, bus, &sh);
 	if (error < 0)
 		goto done;
-	nbytes += error;
 
-	error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
-	if (error < 0)
-		goto done;
-	nbytes += error;
+	error = brcmf_sdio_dump_console(seq, bus, &sh);
 
-	error = nbytes;
-	*ppos += nbytes;
 done:
 	return error;
 }
 
-static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
-					size_t count, loff_t *ppos)
+static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data)
 {
-	struct brcmf_sdio *bus = f->private_data;
-	int res;
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus;
 
-	res = brcmf_sdio_died_dump(bus, data, count, ppos);
-	if (res > 0)
-		*ppos += res;
-	return (ssize_t)res;
+	return brcmf_sdio_died_dump(seq, bus);
 }
 
-static const struct file_operations brcmf_sdio_forensic_ops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = brcmf_sdio_forensic_read
-};
+static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt;
+
+	seq_printf(seq,
+		   "intrcount:    %u\nlastintrs:    %u\n"
+		   "pollcnt:      %u\nregfails:     %u\n"
+		   "tx_sderrs:    %u\nfcqueued:     %u\n"
+		   "rxrtx:        %u\nrx_toolong:   %u\n"
+		   "rxc_errors:   %u\nrx_hdrfail:   %u\n"
+		   "rx_badhdr:    %u\nrx_badseq:    %u\n"
+		   "fc_rcvd:      %u\nfc_xoff:      %u\n"
+		   "fc_xon:       %u\nrxglomfail:   %u\n"
+		   "rxglomframes: %u\nrxglompkts:   %u\n"
+		   "f2rxhdrs:     %u\nf2rxdata:     %u\n"
+		   "f2txdata:     %u\nf1regdata:    %u\n"
+		   "tickcnt:      %u\ntx_ctlerrs:   %lu\n"
+		   "tx_ctlpkts:   %lu\nrx_ctlerrs:   %lu\n"
+		   "rx_ctlpkts:   %lu\nrx_readahead: %lu\n",
+		   sdcnt->intrcount, sdcnt->lastintrs,
+		   sdcnt->pollcnt, sdcnt->regfails,
+		   sdcnt->tx_sderrs, sdcnt->fcqueued,
+		   sdcnt->rxrtx, sdcnt->rx_toolong,
+		   sdcnt->rxc_errors, sdcnt->rx_hdrfail,
+		   sdcnt->rx_badhdr, sdcnt->rx_badseq,
+		   sdcnt->fc_rcvd, sdcnt->fc_xoff,
+		   sdcnt->fc_xon, sdcnt->rxglomfail,
+		   sdcnt->rxglomframes, sdcnt->rxglompkts,
+		   sdcnt->f2rxhdrs, sdcnt->f2rxdata,
+		   sdcnt->f2txdata, sdcnt->f1regdata,
+		   sdcnt->tickcnt, sdcnt->tx_ctlerrs,
+		   sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
+		   sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
+
+	return 0;
+}
 
 static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
 {
@@ -3105,9 +3155,9 @@ static void brcmf_sdio_debugfs_create(st
 	if (IS_ERR_OR_NULL(dentry))
 		return;
 
-	debugfs_create_file("forensics", S_IRUGO, dentry, bus,
-			    &brcmf_sdio_forensic_ops);
-	brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
+	brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
+	brcmf_debugfs_add_entry(drvr, "counters",
+				brcmf_debugfs_sdio_count_read);
 	debugfs_create_u32("console_interval", 0644, dentry,
 			   &bus->console_interval);
 }
@@ -3579,17 +3629,17 @@ brcmf_sdio_drivestrengthinit(struct brcm
 		return;
 
 	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
-	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
+	case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12):
 		str_tab = sdiod_drvstr_tab1_1v8;
 		str_mask = 0x00003800;
 		str_shift = 11;
 		break;
-	case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
+	case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17):
 		str_tab = sdiod_drvstr_tab6_1v8;
 		str_mask = 0x00001800;
 		str_shift = 11;
 		break;
-	case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+	case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17):
 		/* note: 43143 does not support tristate */
 		i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
 		if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
@@ -3600,7 +3650,7 @@ brcmf_sdio_drivestrengthinit(struct brcm
 			brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
 				  ci->name, drivestrength);
 		break;
-	case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
+	case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13):
 		str_tab = sdiod_drive_strength_tab5_1v8;
 		str_mask = 0x00003800;
 		str_shift = 11;
@@ -3701,12 +3751,12 @@ static u32 brcmf_sdio_buscore_read32(voi
 	u32 val, rev;
 
 	val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
-	if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
+	if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID &&
 	    addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
 		rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
 		if (rev >= 2) {
 			val &= ~CID_ID_MASK;
-			val |= BCM4339_CHIP_ID;
+			val |= BRCM_CC_4339_CHIP_ID;
 		}
 	}
 	return val;
@@ -4108,11 +4158,12 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
 	brcmf_sdio_debugfs_create(bus);
 	brcmf_dbg(INFO, "completed!!\n");
 
+	ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev);
+	if (ret)
+		goto fail;
+
 	ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
-				     brcmf_sdio_get_fwname(bus->ci,
-							   BRCMF_FIRMWARE_BIN),
-				     brcmf_sdio_get_fwname(bus->ci,
-							   BRCMF_FIRMWARE_NVRAM),
+				     sdiodev->fw_name, sdiodev->nvram_name,
 				     brcmf_sdio_firmware_callback);
 	if (ret != 0) {
 		brcmf_err("async firmware request failed: %d\n", ret);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+
+#include <brcm_hw_ids.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+#include "feature.h"
+
+/*
+ * firmware error code received if iovar is unsupported.
+ */
+#define EBRCMF_FEAT_UNSUPPORTED		23
+
+/*
+ * expand feature list to array of feature strings.
+ */
+#define BRCMF_FEAT_DEF(_f) \
+	#_f,
+static const char *brcmf_feat_names[] = {
+	BRCMF_FEAT_LIST
+};
+#undef BRCMF_FEAT_DEF
+
+#ifdef DEBUG
+/*
+ * expand quirk list to array of quirk strings.
+ */
+#define BRCMF_QUIRK_DEF(_q) \
+	#_q,
+static const char * const brcmf_quirk_names[] = {
+	BRCMF_QUIRK_LIST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_debugfs_read() - expose feature info to debugfs.
+ *
+ * @seq: sequence for debugfs entry.
+ * @data: raw data pointer.
+ */
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	u32 feats = bus_if->drvr->feat_flags;
+	u32 quirks = bus_if->drvr->chip_quirks;
+	int id;
+
+	seq_printf(seq, "Features: %08x\n", feats);
+	for (id = 0; id < BRCMF_FEAT_LAST; id++)
+		if (feats & BIT(id))
+			seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
+	seq_printf(seq, "\nQuirks:   %08x\n", quirks);
+	for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
+		if (quirks & BIT(id))
+			seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
+	return 0;
+}
+#else
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+	return 0;
+}
+#endif /* DEBUG */
+
+/**
+ * brcmf_feat_iovar_int_get() - determine feature through iovar query.
+ *
+ * @ifp: interface to query.
+ * @id: feature id.
+ * @name: iovar name.
+ */
+static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
+				     enum brcmf_feat_id id, char *name)
+{
+	u32 data;
+	int err;
+
+	err = brcmf_fil_iovar_int_get(ifp, name, &data);
+	if (err == 0) {
+		brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+		ifp->drvr->feat_flags |= BIT(id);
+	} else {
+		brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+			  brcmf_feat_names[id], err);
+	}
+}
+
+void brcmf_feat_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_if *ifp = drvr->iflist[0];
+
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
+
+	/* set chip related quirks */
+	switch (drvr->bus_if->chip) {
+	case BRCM_CC_43236_CHIP_ID:
+		drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
+		break;
+	case BRCM_CC_4329_CHIP_ID:
+		drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
+		break;
+	default:
+		/* no quirks */
+		break;
+	}
+
+	brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
+}
+
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
+{
+	return (ifp->drvr->feat_flags & BIT(id));
+}
+
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+				 enum brcmf_feat_quirk quirk)
+{
+	return (ifp->drvr->chip_quirks & BIT(quirk));
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/feature.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMF_FEATURE_H
+#define _BRCMF_FEATURE_H
+
+/*
+ * Features:
+ *
+ * MCHAN: multi-channel for concurrent P2P.
+ */
+#define BRCMF_FEAT_LIST \
+	BRCMF_FEAT_DEF(MCHAN)
+/*
+ * Quirks:
+ *
+ * AUTO_AUTH: workaround needed for automatic authentication type.
+ * NEED_MPC: driver needs to disable MPC during scanning operation.
+ */
+#define BRCMF_QUIRK_LIST \
+	BRCMF_QUIRK_DEF(AUTO_AUTH) \
+	BRCMF_QUIRK_DEF(NEED_MPC)
+
+#define BRCMF_FEAT_DEF(_f) \
+	BRCMF_FEAT_ ## _f,
+/*
+ * expand feature list to enumeration.
+ */
+enum brcmf_feat_id {
+	BRCMF_FEAT_LIST
+	BRCMF_FEAT_LAST
+};
+#undef BRCMF_FEAT_DEF
+
+#define BRCMF_QUIRK_DEF(_q) \
+	BRCMF_FEAT_QUIRK_ ## _q,
+/*
+ * expand quirk list to enumeration.
+ */
+enum brcmf_feat_quirk {
+	BRCMF_QUIRK_LIST
+	BRCMF_FEAT_QUIRK_LAST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_attach() - determine features and quirks.
+ *
+ * @drvr: driver instance.
+ */
+void brcmf_feat_attach(struct brcmf_pub *drvr);
+
+/**
+ * brcmf_feat_is_enabled() - query feature.
+ *
+ * @ifp: interface instance.
+ * @id: feature id to check.
+ *
+ * Return: true is feature is enabled; otherwise false.
+ */
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
+
+/**
+ * brcmf_feat_is_quirk_enabled() - query chip quirk.
+ *
+ * @ifp: interface instance.
+ * @quirk: quirk id to check.
+ *
+ * Return: true is quirk is enabled; otherwise false.
+ */
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+				 enum brcmf_feat_quirk quirk);
+
+#endif /* _BRCMF_FEATURE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.c	2014-08-07 04:53:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.c	2014-09-28 21:35:34.000000000 -0400
@@ -18,10 +18,15 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/module.h>
 
 #include "dhd_dbg.h"
 #include "firmware.h"
 
+char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
+module_param_string(firmware_path, brcmf_firmware_path,
+		    BRCMF_FW_PATH_LEN, 0440);
+
 enum nvram_parser_state {
 	IDLE,
 	KEY,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/firmware.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,11 @@
 #define BRCMF_FW_REQ_FLAGS		0x00F0
 #define  BRCMF_FW_REQ_NV_OPTIONAL	0x0010
 
+#define	BRCMF_FW_PATH_LEN	256
+#define	BRCMF_FW_NAME_LEN	32
+
+extern char brcmf_firmware_path[];
+
 void brcmf_fw_nvram_free(void *nvram);
 /*
  * Request firmware(s) asynchronously. When the asynchronous request
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,501 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <brcmu_utils.h>
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
+#include "proto.h"
+#include "flowring.h"
+#include "msgbuf.h"
+
+
+#define BRCMF_FLOWRING_HIGH		1024
+#define BRCMF_FLOWRING_LOW		(BRCMF_FLOWRING_HIGH - 256)
+#define BRCMF_FLOWRING_INVALID_IFIDX	0xff
+
+#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
+#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
+
+static const u8 ALLZEROMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static const u8 brcmf_flowring_prio2fifo[] = {
+	1,
+	0,
+	0,
+	1,
+	2,
+	2,
+	3,
+	3
+};
+
+
+static bool
+brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
+{
+	struct brcmf_flowring_tdls_entry *search;
+
+	search = flow->tdls_entry;
+
+	while (search) {
+		if (memcmp(search->mac, mac, ETH_ALEN) == 0)
+			return true;
+		search = search->next;
+	}
+
+	return false;
+}
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx)
+{
+	struct brcmf_flowring_hash *hash;
+	u8 hash_idx;
+	u32 i;
+	bool found;
+	bool sta;
+	u8 fifo;
+	u8 *mac;
+
+	fifo = brcmf_flowring_prio2fifo[prio];
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+	mac = da;
+	if ((!sta) && (is_multicast_ether_addr(da))) {
+		mac = (u8 *)ALLFFMAC;
+		fifo = 0;
+	}
+	if ((sta) && (flow->tdls_active) &&
+	    (brcmf_flowring_is_tdls_mac(flow, da))) {
+		sta = false;
+	}
+	hash_idx =  sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+			  BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+	found = false;
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((sta || (memcmp(hash[hash_idx].mac, mac, ETH_ALEN) == 0)) &&
+		    (hash[hash_idx].fifo == fifo) &&
+		    (hash[hash_idx].ifidx == ifidx)) {
+			found = true;
+			break;
+		}
+		hash_idx++;
+	}
+	if (found)
+		return hash[hash_idx].flowid;
+
+	return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx)
+{
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_flowring_hash *hash;
+	u8 hash_idx;
+	u32 i;
+	bool found;
+	u8 fifo;
+	bool sta;
+	u8 *mac;
+
+	fifo = brcmf_flowring_prio2fifo[prio];
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+	mac = da;
+	if ((!sta) && (is_multicast_ether_addr(da))) {
+		mac = (u8 *)ALLFFMAC;
+		fifo = 0;
+	}
+	if ((sta) && (flow->tdls_active) &&
+	    (brcmf_flowring_is_tdls_mac(flow, da))) {
+		sta = false;
+	}
+	hash_idx =  sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+			  BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+	found = false;
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
+		    (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
+			found = true;
+			break;
+		}
+		hash_idx++;
+	}
+	if (found) {
+		for (i = 0; i < flow->nrofrings; i++) {
+			if (flow->rings[i] == NULL)
+				break;
+		}
+		if (i == flow->nrofrings)
+			return -ENOMEM;
+
+		ring = kzalloc(sizeof(*ring), GFP_ATOMIC);
+		if (!ring)
+			return -ENOMEM;
+
+		memcpy(hash[hash_idx].mac, mac, ETH_ALEN);
+		hash[hash_idx].fifo = fifo;
+		hash[hash_idx].ifidx = ifidx;
+		hash[hash_idx].flowid = i;
+
+		ring->hash_id = hash_idx;
+		ring->status = RING_CLOSED;
+		skb_queue_head_init(&ring->skblist);
+		flow->rings[i] = ring;
+
+		return i;
+	}
+	return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	return flow->hash[ring->hash_id].fifo;
+}
+
+
+static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
+				 bool blocked)
+{
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_bus *bus_if;
+	struct brcmf_pub *drvr;
+	struct brcmf_if *ifp;
+	bool currently_blocked;
+	int i;
+	u8 ifidx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&flow->block_lock, flags);
+
+	ring = flow->rings[flowid];
+	ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+
+	currently_blocked = false;
+	for (i = 0; i < flow->nrofrings; i++) {
+		if (flow->rings[i]) {
+			ring = flow->rings[i];
+			if ((ring->status == RING_OPEN) &&
+			    (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
+				if (ring->blocked) {
+					currently_blocked = true;
+					break;
+				}
+			}
+		}
+	}
+	ring->blocked = blocked;
+	if (currently_blocked == blocked) {
+		spin_unlock_irqrestore(&flow->block_lock, flags);
+		return;
+	}
+
+	bus_if = dev_get_drvdata(flow->dev);
+	drvr = bus_if->drvr;
+	ifp = drvr->iflist[ifidx];
+	brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
+
+	spin_unlock_irqrestore(&flow->block_lock, flags);
+}
+
+
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+	u8 hash_idx;
+	struct sk_buff *skb;
+
+	ring = flow->rings[flowid];
+	if (!ring)
+		return;
+	brcmf_flowring_block(flow, flowid, false);
+	hash_idx = ring->hash_id;
+	flow->hash[hash_idx].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+	memset(flow->hash[hash_idx].mac, 0, ETH_ALEN);
+	flow->rings[flowid] = NULL;
+
+	skb = skb_dequeue(&ring->skblist);
+	while (skb) {
+		brcmu_pkt_buf_free_skb(skb);
+		skb = skb_dequeue(&ring->skblist);
+	}
+
+	kfree(ring);
+}
+
+
+void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+			    struct sk_buff *skb)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	skb_queue_tail(&ring->skblist, skb);
+
+	if (!ring->blocked &&
+	    (skb_queue_len(&ring->skblist) > BRCMF_FLOWRING_HIGH)) {
+		brcmf_flowring_block(flow, flowid, true);
+		brcmf_dbg(MSGBUF, "Flowcontrol: BLOCK for ring %d\n", flowid);
+		/* To prevent (work around) possible race condition, check
+		 * queue len again. It is also possible to use locking to
+		 * protect, but that is undesirable for every enqueue and
+		 * dequeue. This simple check will solve a possible race
+		 * condition if it occurs.
+		 */
+		if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
+			brcmf_flowring_block(flow, flowid, false);
+	}
+}
+
+
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+	struct sk_buff *skb;
+
+	ring = flow->rings[flowid];
+	if (ring->status != RING_OPEN)
+		return NULL;
+
+	skb = skb_dequeue(&ring->skblist);
+
+	if (ring->blocked &&
+	    (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)) {
+		brcmf_flowring_block(flow, flowid, false);
+		brcmf_dbg(MSGBUF, "Flowcontrol: OPEN for ring %d\n", flowid);
+	}
+
+	return skb;
+}
+
+
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
+			     struct sk_buff *skb)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	skb_queue_head(&ring->skblist, skb);
+}
+
+
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+	if (!ring)
+		return 0;
+
+	if (ring->status != RING_OPEN)
+		return 0;
+
+	return skb_queue_len(&ring->skblist);
+}
+
+
+void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+	if (!ring) {
+		brcmf_err("Ring NULL, for flowid %d\n", flowid);
+		return;
+	}
+
+	ring->status = RING_OPEN;
+}
+
+
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+	u8 hash_idx;
+
+	ring = flow->rings[flowid];
+	hash_idx = ring->hash_id;
+
+	return flow->hash[hash_idx].ifidx;
+}
+
+
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)
+{
+	struct brcmf_flowring *flow;
+	u32 i;
+
+	flow = kzalloc(sizeof(*flow), GFP_ATOMIC);
+	if (flow) {
+		flow->dev = dev;
+		flow->nrofrings = nrofrings;
+		spin_lock_init(&flow->block_lock);
+		for (i = 0; i < ARRAY_SIZE(flow->addr_mode); i++)
+			flow->addr_mode[i] = ADDR_INDIRECT;
+		for (i = 0; i < ARRAY_SIZE(flow->hash); i++)
+			flow->hash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+		flow->rings = kcalloc(nrofrings, sizeof(*flow->rings),
+				      GFP_ATOMIC);
+		if (!flow->rings) {
+			kfree(flow);
+			flow = NULL;
+		}
+	}
+
+	return flow;
+}
+
+
+void brcmf_flowring_detach(struct brcmf_flowring *flow)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_flowring_tdls_entry *search;
+	struct brcmf_flowring_tdls_entry *remove;
+	u8 flowid;
+
+	for (flowid = 0; flowid < flow->nrofrings; flowid++) {
+		if (flow->rings[flowid])
+			brcmf_msgbuf_delete_flowring(drvr, flowid);
+	}
+
+	search = flow->tdls_entry;
+	while (search) {
+		remove = search;
+		search = search->next;
+		kfree(remove);
+	}
+	kfree(flow->rings);
+	kfree(flow);
+}
+
+
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+					enum proto_addr_mode addr_mode)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	u32 i;
+	u8 flowid;
+
+	if (flow->addr_mode[ifidx] != addr_mode) {
+		for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
+			if (flow->hash[i].ifidx == ifidx) {
+				flowid = flow->hash[i].flowid;
+				if (flow->rings[flowid]->status != RING_OPEN)
+					continue;
+				flow->rings[flowid]->status = RING_CLOSING;
+				brcmf_msgbuf_delete_flowring(drvr, flowid);
+			}
+		}
+		flow->addr_mode[ifidx] = addr_mode;
+	}
+}
+
+
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+				u8 peer[ETH_ALEN])
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_flowring_hash *hash;
+	struct brcmf_flowring_tdls_entry *prev;
+	struct brcmf_flowring_tdls_entry *search;
+	u32 i;
+	u8 flowid;
+	bool sta;
+
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+
+	search = flow->tdls_entry;
+	prev = NULL;
+	while (search) {
+		if (memcmp(search->mac, peer, ETH_ALEN) == 0) {
+			sta = false;
+			break;
+		}
+		prev = search;
+		search = search->next;
+	}
+
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
+		    (hash[i].ifidx == ifidx)) {
+			flowid = flow->hash[i].flowid;
+			if (flow->rings[flowid]->status == RING_OPEN) {
+				flow->rings[flowid]->status = RING_CLOSING;
+				brcmf_msgbuf_delete_flowring(drvr, flowid);
+			}
+		}
+	}
+
+	if (search) {
+		if (prev)
+			prev->next = search->next;
+		else
+			flow->tdls_entry = search->next;
+		kfree(search);
+		if (flow->tdls_entry == NULL)
+			flow->tdls_active = false;
+	}
+}
+
+
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+				  u8 peer[ETH_ALEN])
+{
+	struct brcmf_flowring_tdls_entry *tdls_entry;
+	struct brcmf_flowring_tdls_entry *search;
+
+	tdls_entry = kzalloc(sizeof(*tdls_entry), GFP_ATOMIC);
+	if (tdls_entry == NULL)
+		return;
+
+	memcpy(tdls_entry->mac, peer, ETH_ALEN);
+	tdls_entry->next = NULL;
+	if (flow->tdls_entry == NULL) {
+		flow->tdls_entry = tdls_entry;
+	} else {
+		search = flow->tdls_entry;
+		if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+			return;
+		while (search->next) {
+			search = search->next;
+			if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+				return;
+		}
+		search->next = tdls_entry;
+	}
+
+	flow->tdls_active = true;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/flowring.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,84 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_FLOWRING_H
+#define BRCMFMAC_FLOWRING_H
+
+
+#define BRCMF_FLOWRING_HASHSIZE		256
+#define BRCMF_FLOWRING_INVALID_ID	0xFFFFFFFF
+
+
+struct brcmf_flowring_hash {
+	u8 mac[ETH_ALEN];
+	u8 fifo;
+	u8 ifidx;
+	u8 flowid;
+};
+
+enum ring_status {
+	RING_CLOSED,
+	RING_CLOSING,
+	RING_OPEN
+};
+
+struct brcmf_flowring_ring {
+	u8 hash_id;
+	bool blocked;
+	enum ring_status status;
+	struct sk_buff_head skblist;
+};
+
+struct brcmf_flowring_tdls_entry {
+	u8 mac[ETH_ALEN];
+	struct brcmf_flowring_tdls_entry *next;
+};
+
+struct brcmf_flowring {
+	struct device *dev;
+	struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
+	struct brcmf_flowring_ring **rings;
+	spinlock_t block_lock;
+	enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
+	u16 nrofrings;
+	bool tdls_active;
+	struct brcmf_flowring_tdls_entry *tdls_entry;
+};
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx);
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx);
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+			    struct sk_buff *skb);
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
+			     struct sk_buff *skb);
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid);
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid);
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
+void brcmf_flowring_detach(struct brcmf_flowring *flow);
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+					enum proto_addr_mode addr_mode);
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+				u8 peer[ETH_ALEN]);
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+				  u8 peer[ETH_ALEN]);
+
+
+#endif /* BRCMFMAC_FLOWRING_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,7 +185,13 @@ static void brcmf_fweh_handle_if_event(s
 		  ifevent->action, ifevent->ifidx, ifevent->bssidx,
 		  ifevent->flags, ifevent->role);
 
-	if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) {
+	/* The P2P Device interface event must not be ignored
+	 * contrary to what firmware tells us. The only way to
+	 * distinguish the P2P Device is by looking at the ifidx
+	 * and bssidx received.
+	 */
+	if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
+	    (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
 		brcmf_dbg(EVENT, "event can be ignored\n");
 		return;
 	}
@@ -210,12 +216,12 @@ static void brcmf_fweh_handle_if_event(s
 				return;
 	}
 
-	if (ifevent->action == BRCMF_E_IF_CHANGE)
+	if (ifp && ifevent->action == BRCMF_E_IF_CHANGE)
 		brcmf_fws_reset_interface(ifp);
 
 	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
 
-	if (ifevent->action == BRCMF_E_IF_DEL) {
+	if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
 		brcmf_fws_del_interface(ifp);
 		brcmf_del_if(drvr, ifevent->bssidx);
 	}
@@ -293,7 +299,11 @@ static void brcmf_fweh_event_worker(stru
 			goto event_free;
 		}
 
-		ifp = drvr->iflist[emsg.bsscfgidx];
+		if ((event->code == BRCMF_E_TDLS_PEER_EVENT) &&
+		    (emsg.bsscfgidx == 1))
+			ifp = drvr->iflist[0];
+		else
+			ifp = drvr->iflist[emsg.bsscfgidx];
 		err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
 						    event->data);
 		if (err) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fweh.h	2014-09-28 17:29:07.000000000 -0400
@@ -102,6 +102,7 @@ struct brcmf_event;
 	BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
 	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
 	BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
+	BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
 	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
 	BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
 
@@ -155,6 +156,10 @@ enum brcmf_fweh_event_code {
 #define BRCMF_E_REASON_TSPEC_REJECTED		7
 #define BRCMF_E_REASON_BETTER_AP		8
 
+#define BRCMF_E_REASON_TDLS_PEER_DISCOVERED	0
+#define BRCMF_E_REASON_TDLS_PEER_CONNECTED	1
+#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED	2
+
 /* action field values for brcmf_ifevent */
 #define BRCMF_E_IF_ADD				1
 #define BRCMF_E_IF_DEL				2
@@ -167,6 +172,8 @@ enum brcmf_fweh_event_code {
 #define BRCMF_E_IF_ROLE_STA			0
 #define BRCMF_E_IF_ROLE_AP			1
 #define BRCMF_E_IF_ROLE_WDS			2
+#define BRCMF_E_IF_ROLE_P2P_GO			3
+#define BRCMF_E_IF_ROLE_P2P_CLIENT		4
 
 /**
  * definitions for event packet validation.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwil.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwil.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwil.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
 	if (err >= 0)
 		err = 0;
 	else
-		brcmf_err("Failed err=%d\n", err);
+		brcmf_dbg(FIL, "Failed err=%d\n", err);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c	2014-09-28 17:29:07.000000000 -0400
@@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table {
 	struct brcmf_fws_mac_descriptor other;
 };
 
+struct brcmf_fws_stats {
+	u32 tlv_parse_failed;
+	u32 tlv_invalid_type;
+	u32 header_only_pkt;
+	u32 header_pulls;
+	u32 pkt2bus;
+	u32 send_pkts[5];
+	u32 requested_sent[5];
+	u32 generic_error;
+	u32 mac_update_failed;
+	u32 mac_ps_update_failed;
+	u32 if_update_failed;
+	u32 packet_request_failed;
+	u32 credit_request_failed;
+	u32 rollback_success;
+	u32 rollback_failed;
+	u32 delayq_full_error;
+	u32 supprq_full_error;
+	u32 txs_indicate;
+	u32 txs_discard;
+	u32 txs_supp_core;
+	u32 txs_supp_ps;
+	u32 txs_tossed;
+	u32 txs_host_tossed;
+	u32 bus_flow_block;
+	u32 fws_flow_block;
+};
+
 struct brcmf_fws_info {
 	struct brcmf_pub *drvr;
 	spinlock_t spinlock;
@@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(str
 	brcmf_fws_unlock(fws);
 }
 
+#ifdef DEBUG
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats;
+
+	seq_printf(seq,
+		   "header_pulls:      %u\n"
+		   "header_only_pkt:   %u\n"
+		   "tlv_parse_failed:  %u\n"
+		   "tlv_invalid_type:  %u\n"
+		   "mac_update_fails:  %u\n"
+		   "ps_update_fails:   %u\n"
+		   "if_update_fails:   %u\n"
+		   "pkt2bus:           %u\n"
+		   "generic_error:     %u\n"
+		   "rollback_success:  %u\n"
+		   "rollback_failed:   %u\n"
+		   "delayq_full:       %u\n"
+		   "supprq_full:       %u\n"
+		   "txs_indicate:      %u\n"
+		   "txs_discard:       %u\n"
+		   "txs_suppr_core:    %u\n"
+		   "txs_suppr_ps:      %u\n"
+		   "txs_tossed:        %u\n"
+		   "txs_host_tossed:   %u\n"
+		   "bus_flow_block:    %u\n"
+		   "fws_flow_block:    %u\n"
+		   "send_pkts:         BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
+		   "requested_sent:    BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
+		   fwstats->header_pulls,
+		   fwstats->header_only_pkt,
+		   fwstats->tlv_parse_failed,
+		   fwstats->tlv_invalid_type,
+		   fwstats->mac_update_failed,
+		   fwstats->mac_ps_update_failed,
+		   fwstats->if_update_failed,
+		   fwstats->pkt2bus,
+		   fwstats->generic_error,
+		   fwstats->rollback_success,
+		   fwstats->rollback_failed,
+		   fwstats->delayq_full_error,
+		   fwstats->supprq_full_error,
+		   fwstats->txs_indicate,
+		   fwstats->txs_discard,
+		   fwstats->txs_supp_core,
+		   fwstats->txs_supp_ps,
+		   fwstats->txs_tossed,
+		   fwstats->txs_host_tossed,
+		   fwstats->bus_flow_block,
+		   fwstats->fws_flow_block,
+		   fwstats->send_pkts[0], fwstats->send_pkts[1],
+		   fwstats->send_pkts[2], fwstats->send_pkts[3],
+		   fwstats->send_pkts[4],
+		   fwstats->requested_sent[0],
+		   fwstats->requested_sent[1],
+		   fwstats->requested_sent[2],
+		   fwstats->requested_sent[3],
+		   fwstats->requested_sent[4]);
+
+	return 0;
+}
+#else
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+	return 0;
+}
+#endif
+
 int brcmf_fws_init(struct brcmf_pub *drvr)
 {
 	struct brcmf_fws_info *fws;
@@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drv
 			BRCMF_FWS_PSQ_LEN);
 
 	/* create debugfs file for statistics */
-	brcmf_debugfs_create_fws_stats(drvr, &fws->stats);
+	brcmf_debugfs_add_entry(drvr, "fws_stats",
+				brcmf_debugfs_fws_stats_read);
 
 	brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
 		  fws->fw_signals ? "enabled" : "disabled", tlv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -30,17 +30,28 @@ brcmfmac-objs += \
 		fwsignal.o \
 		p2p.o \
 		proto.o \
-		bcdc.o \
 		dhd_common.o \
 		dhd_linux.o \
 		firmware.o \
-		btcoex.o
+		feature.o \
+		btcoex.o \
+		vendor.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
+		bcdc.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
+		commonring.o \
+		flowring.o \
+		msgbuf.o
 brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
 		dhd_sdio.o \
 		bcmsdh.o
 brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
 		usb.o
+brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \
+		pcie.o
 brcmfmac-$(CONFIG_BRCMDBG) += \
 		dhd_dbg.o
 brcmfmac-$(CONFIG_BRCM_TRACING) += \
 		tracepoint.o
+brcmfmac-$(CONFIG_OF) += \
+		of.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1401 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "proto.h"
+#include "msgbuf.h"
+#include "commonring.h"
+#include "flowring.h"
+#include "dhd_bus.h"
+#include "tracepoint.h"
+
+
+#define MSGBUF_IOCTL_RESP_TIMEOUT		2000
+
+#define MSGBUF_TYPE_GEN_STATUS			0x1
+#define MSGBUF_TYPE_RING_STATUS			0x2
+#define MSGBUF_TYPE_FLOW_RING_CREATE		0x3
+#define MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT	0x4
+#define MSGBUF_TYPE_FLOW_RING_DELETE		0x5
+#define MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT	0x6
+#define MSGBUF_TYPE_FLOW_RING_FLUSH		0x7
+#define MSGBUF_TYPE_FLOW_RING_FLUSH_CMPLT	0x8
+#define MSGBUF_TYPE_IOCTLPTR_REQ		0x9
+#define MSGBUF_TYPE_IOCTLPTR_REQ_ACK		0xA
+#define MSGBUF_TYPE_IOCTLRESP_BUF_POST		0xB
+#define MSGBUF_TYPE_IOCTL_CMPLT			0xC
+#define MSGBUF_TYPE_EVENT_BUF_POST		0xD
+#define MSGBUF_TYPE_WL_EVENT			0xE
+#define MSGBUF_TYPE_TX_POST			0xF
+#define MSGBUF_TYPE_TX_STATUS			0x10
+#define MSGBUF_TYPE_RXBUF_POST			0x11
+#define MSGBUF_TYPE_RX_CMPLT			0x12
+#define MSGBUF_TYPE_LPBK_DMAXFER		0x13
+#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT		0x14
+
+#define NR_TX_PKTIDS				2048
+#define NR_RX_PKTIDS				1024
+
+#define BRCMF_IOCTL_REQ_PKTID			0xFFFE
+
+#define BRCMF_MSGBUF_MAX_PKT_SIZE		2048
+#define BRCMF_MSGBUF_RXBUFPOST_THRESHOLD	32
+#define BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST	8
+#define BRCMF_MSGBUF_MAX_EVENTBUF_POST		8
+
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3	0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT	5
+
+#define BRCMF_MSGBUF_TX_FLUSH_CNT1		32
+#define BRCMF_MSGBUF_TX_FLUSH_CNT2		96
+
+
+struct msgbuf_common_hdr {
+	u8				msgtype;
+	u8				ifidx;
+	u8				flags;
+	u8				rsvd0;
+	__le32				request_id;
+};
+
+struct msgbuf_buf_addr {
+	__le32				low_addr;
+	__le32				high_addr;
+};
+
+struct msgbuf_ioctl_req_hdr {
+	struct msgbuf_common_hdr	msg;
+	__le32				cmd;
+	__le16				trans_id;
+	__le16				input_buf_len;
+	__le16				output_buf_len;
+	__le16				rsvd0[3];
+	struct msgbuf_buf_addr		req_buf_addr;
+	__le32				rsvd1[2];
+};
+
+struct msgbuf_tx_msghdr {
+	struct msgbuf_common_hdr	msg;
+	u8				txhdr[ETH_HLEN];
+	u8				flags;
+	u8				seg_cnt;
+	struct msgbuf_buf_addr		metadata_buf_addr;
+	struct msgbuf_buf_addr		data_buf_addr;
+	__le16				metadata_buf_len;
+	__le16				data_len;
+	__le32				rsvd0;
+};
+
+struct msgbuf_rx_bufpost {
+	struct msgbuf_common_hdr	msg;
+	__le16				metadata_buf_len;
+	__le16				data_buf_len;
+	__le32				rsvd0;
+	struct msgbuf_buf_addr		metadata_buf_addr;
+	struct msgbuf_buf_addr		data_buf_addr;
+};
+
+struct msgbuf_rx_ioctl_resp_or_event {
+	struct msgbuf_common_hdr	msg;
+	__le16				host_buf_len;
+	__le16				rsvd0[3];
+	struct msgbuf_buf_addr		host_buf_addr;
+	__le32				rsvd1[4];
+};
+
+struct msgbuf_completion_hdr {
+	__le16				status;
+	__le16				flow_ring_id;
+};
+
+struct msgbuf_rx_event {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				event_data_len;
+	__le16				seqnum;
+	__le16				rsvd0[4];
+};
+
+struct msgbuf_ioctl_resp_hdr {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				resp_len;
+	__le16				trans_id;
+	__le32				cmd;
+	__le32				rsvd0;
+};
+
+struct msgbuf_tx_status {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				metadata_len;
+	__le16				tx_status;
+};
+
+struct msgbuf_rx_complete {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				metadata_len;
+	__le16				data_len;
+	__le16				data_offset;
+	__le16				flags;
+	__le32				rx_status_0;
+	__le32				rx_status_1;
+	__le32				rsvd0;
+};
+
+struct msgbuf_tx_flowring_create_req {
+	struct msgbuf_common_hdr	msg;
+	u8				da[ETH_ALEN];
+	u8				sa[ETH_ALEN];
+	u8				tid;
+	u8				if_flags;
+	__le16				flow_ring_id;
+	u8				tc;
+	u8				priority;
+	__le16				int_vector;
+	__le16				max_items;
+	__le16				len_item;
+	struct msgbuf_buf_addr		flow_ring_addr;
+};
+
+struct msgbuf_tx_flowring_delete_req {
+	struct msgbuf_common_hdr	msg;
+	__le16				flow_ring_id;
+	__le16				reason;
+	__le32				rsvd0[7];
+};
+
+struct msgbuf_flowring_create_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct msgbuf_flowring_delete_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct msgbuf_flowring_flush_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct brcmf_msgbuf {
+	struct brcmf_pub *drvr;
+
+	struct brcmf_commonring **commonrings;
+	struct brcmf_commonring **flowrings;
+	dma_addr_t *flowring_dma_handle;
+	u16 nrof_flowrings;
+
+	u16 rx_dataoffset;
+	u32 max_rxbufpost;
+	u16 rx_metadata_offset;
+	u32 rxbufpost;
+
+	u32 max_ioctlrespbuf;
+	u32 cur_ioctlrespbuf;
+	u32 max_eventbuf;
+	u32 cur_eventbuf;
+
+	void *ioctbuf;
+	dma_addr_t ioctbuf_handle;
+	u32 ioctbuf_phys_hi;
+	u32 ioctbuf_phys_lo;
+	u32 ioctl_resp_status;
+	u32 ioctl_resp_ret_len;
+	u32 ioctl_resp_pktid;
+
+	u16 data_seq_no;
+	u16 ioctl_seq_no;
+	u32 reqid;
+	wait_queue_head_t ioctl_resp_wait;
+	bool ctl_completed;
+
+	struct brcmf_msgbuf_pktids *tx_pktids;
+	struct brcmf_msgbuf_pktids *rx_pktids;
+	struct brcmf_flowring *flow;
+
+	struct workqueue_struct *txflow_wq;
+	struct work_struct txflow_work;
+	unsigned long *flow_map;
+	unsigned long *txstatus_done_map;
+};
+
+struct brcmf_msgbuf_pktid {
+	atomic_t  allocated;
+	u16 data_offset;
+	struct sk_buff *skb;
+	dma_addr_t physaddr;
+};
+
+struct brcmf_msgbuf_pktids {
+	u32 array_size;
+	u32 last_allocated_idx;
+	enum dma_data_direction direction;
+	struct brcmf_msgbuf_pktid *array;
+};
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
+
+
+static struct brcmf_msgbuf_pktids *
+brcmf_msgbuf_init_pktids(u32 nr_array_entries,
+			 enum dma_data_direction direction)
+{
+	struct brcmf_msgbuf_pktid *array;
+	struct brcmf_msgbuf_pktids *pktids;
+
+	array = kcalloc(nr_array_entries, sizeof(*array), GFP_ATOMIC);
+	if (!array)
+		return NULL;
+
+	pktids = kzalloc(sizeof(*pktids), GFP_ATOMIC);
+	if (!pktids) {
+		kfree(array);
+		return NULL;
+	}
+	pktids->array = array;
+	pktids->array_size = nr_array_entries;
+
+	return pktids;
+}
+
+
+static int
+brcmf_msgbuf_alloc_pktid(struct device *dev,
+			 struct brcmf_msgbuf_pktids *pktids,
+			 struct sk_buff *skb, u16 data_offset,
+			 dma_addr_t *physaddr, u32 *idx)
+{
+	struct brcmf_msgbuf_pktid *array;
+	u32 count;
+
+	array = pktids->array;
+
+	*physaddr = dma_map_single(dev, skb->data + data_offset,
+				   skb->len - data_offset, pktids->direction);
+
+	if (dma_mapping_error(dev, *physaddr)) {
+		brcmf_err("dma_map_single failed !!\n");
+		return -ENOMEM;
+	}
+
+	*idx = pktids->last_allocated_idx;
+
+	count = 0;
+	do {
+		(*idx)++;
+		if (*idx == pktids->array_size)
+			*idx = 0;
+		if (array[*idx].allocated.counter == 0)
+			if (atomic_cmpxchg(&array[*idx].allocated, 0, 1) == 0)
+				break;
+		count++;
+	} while (count < pktids->array_size);
+
+	if (count == pktids->array_size)
+		return -ENOMEM;
+
+	array[*idx].data_offset = data_offset;
+	array[*idx].physaddr = *physaddr;
+	array[*idx].skb = skb;
+
+	pktids->last_allocated_idx = *idx;
+
+	return 0;
+}
+
+
+static struct sk_buff *
+brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids,
+		       u32 idx)
+{
+	struct brcmf_msgbuf_pktid *pktid;
+	struct sk_buff *skb;
+
+	if (idx >= pktids->array_size) {
+		brcmf_err("Invalid packet id %d (max %d)\n", idx,
+			  pktids->array_size);
+		return NULL;
+	}
+	if (pktids->array[idx].allocated.counter) {
+		pktid = &pktids->array[idx];
+		dma_unmap_single(dev, pktid->physaddr,
+				 pktid->skb->len - pktid->data_offset,
+				 pktids->direction);
+		skb = pktid->skb;
+		pktid->allocated.counter = 0;
+		return skb;
+	} else {
+		brcmf_err("Invalid packet id %d (not in use)\n", idx);
+	}
+
+	return NULL;
+}
+
+
+static void
+brcmf_msgbuf_release_array(struct device *dev,
+			   struct brcmf_msgbuf_pktids *pktids)
+{
+	struct brcmf_msgbuf_pktid *array;
+	struct brcmf_msgbuf_pktid *pktid;
+	u32 count;
+
+	array = pktids->array;
+	count = 0;
+	do {
+		if (array[count].allocated.counter) {
+			pktid = &array[count];
+			dma_unmap_single(dev, pktid->physaddr,
+					 pktid->skb->len - pktid->data_offset,
+					 pktids->direction);
+			brcmu_pkt_buf_free_skb(pktid->skb);
+		}
+		count++;
+	} while (count < pktids->array_size);
+
+	kfree(array);
+	kfree(pktids);
+}
+
+
+static void brcmf_msgbuf_release_pktids(struct brcmf_msgbuf *msgbuf)
+{
+	if (msgbuf->rx_pktids)
+		brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+					   msgbuf->rx_pktids);
+	if (msgbuf->tx_pktids)
+		brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+					   msgbuf->tx_pktids);
+}
+
+
+static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
+				 uint cmd, void *buf, uint len)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_commonring *commonring;
+	struct msgbuf_ioctl_req_hdr *request;
+	u16 buf_len;
+	void *ret_ptr;
+	int err;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		return -ENOMEM;
+	}
+
+	msgbuf->reqid++;
+
+	request = (struct msgbuf_ioctl_req_hdr *)ret_ptr;
+	request->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;
+	request->msg.ifidx = (u8)ifidx;
+	request->msg.flags = 0;
+	request->msg.request_id = cpu_to_le32(BRCMF_IOCTL_REQ_PKTID);
+	request->cmd = cpu_to_le32(cmd);
+	request->output_buf_len = cpu_to_le16(len);
+	request->trans_id = cpu_to_le16(msgbuf->reqid);
+
+	buf_len = min_t(u16, len, BRCMF_TX_IOCTL_MAX_MSG_SIZE);
+	request->input_buf_len = cpu_to_le16(buf_len);
+	request->req_buf_addr.high_addr = cpu_to_le32(msgbuf->ioctbuf_phys_hi);
+	request->req_buf_addr.low_addr = cpu_to_le32(msgbuf->ioctbuf_phys_lo);
+	if (buf)
+		memcpy(msgbuf->ioctbuf, buf, buf_len);
+	else
+		memset(msgbuf->ioctbuf, 0, buf_len);
+	brcmf_dma_flush(ioctl_buf, buf_len);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+
+	return err;
+}
+
+
+static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)
+{
+	return wait_event_timeout(msgbuf->ioctl_resp_wait,
+				  msgbuf->ctl_completed,
+				  msecs_to_jiffies(MSGBUF_IOCTL_RESP_TIMEOUT));
+}
+
+
+static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
+{
+	if (waitqueue_active(&msgbuf->ioctl_resp_wait)) {
+		msgbuf->ctl_completed = true;
+		wake_up(&msgbuf->ioctl_resp_wait);
+	}
+}
+
+
+static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+				   uint cmd, void *buf, uint len)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct sk_buff *skb = NULL;
+	int timeout;
+	int err;
+
+	brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
+	msgbuf->ctl_completed = false;
+	err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
+	if (err)
+		return err;
+
+	timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf);
+	if (!timeout) {
+		brcmf_err("Timeout on response for query command\n");
+		return -EIO;
+	}
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids,
+				     msgbuf->ioctl_resp_pktid);
+	if (msgbuf->ioctl_resp_ret_len != 0) {
+		if (!skb) {
+			brcmf_err("Invalid packet id idx recv'd %d\n",
+				  msgbuf->ioctl_resp_pktid);
+			return -EBADF;
+		}
+		memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
+				       len : msgbuf->ioctl_resp_ret_len);
+	}
+	if (skb)
+		brcmu_pkt_buf_free_skb(skb);
+
+	return msgbuf->ioctl_resp_status;
+}
+
+
+static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
+				 uint cmd, void *buf, uint len)
+{
+	return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
+}
+
+
+static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+				u8 *ifidx, struct sk_buff *skb)
+{
+	return -ENODEV;
+}
+
+
+static void
+brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
+{
+	u32 dma_sz;
+	void *dma_buf;
+
+	brcmf_dbg(MSGBUF, "Removing flowring %d\n", flowid);
+
+	dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+	dma_buf = msgbuf->flowrings[flowid]->buf_addr;
+	dma_free_coherent(msgbuf->drvr->bus_if->dev, dma_sz, dma_buf,
+			  msgbuf->flowring_dma_handle[flowid]);
+
+	brcmf_flowring_delete(msgbuf->flow, flowid);
+}
+
+
+static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx,
+					struct sk_buff *skb)
+{
+	struct msgbuf_tx_flowring_create_req *create;
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u32 flowid;
+	void *dma_buf;
+	u32 dma_sz;
+	long long address;
+	int err;
+
+	flowid = brcmf_flowring_create(msgbuf->flow, eh->h_dest,
+				       skb->priority, ifidx);
+	if (flowid == BRCMF_FLOWRING_INVALID_ID)
+		return flowid;
+
+	dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+
+	dma_buf = dma_alloc_coherent(msgbuf->drvr->bus_if->dev, dma_sz,
+				     &msgbuf->flowring_dma_handle[flowid],
+				     GFP_ATOMIC);
+	if (!dma_buf) {
+		brcmf_err("dma_alloc_coherent failed\n");
+		brcmf_flowring_delete(msgbuf->flow, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	brcmf_commonring_config(msgbuf->flowrings[flowid],
+				BRCMF_H2D_TXFLOWRING_MAX_ITEM,
+				BRCMF_H2D_TXFLOWRING_ITEMSIZE, dma_buf);
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	create = (struct msgbuf_tx_flowring_create_req *)ret_ptr;
+	create->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;
+	create->msg.ifidx = ifidx;
+	create->msg.request_id = 0;
+	create->tid = brcmf_flowring_tid(msgbuf->flow, flowid);
+	create->flow_ring_id = cpu_to_le16(flowid +
+					   BRCMF_NROF_H2D_COMMON_MSGRINGS);
+	memcpy(create->sa, eh->h_source, ETH_ALEN);
+	memcpy(create->da, eh->h_dest, ETH_ALEN);
+	address = (long long)(long)msgbuf->flowring_dma_handle[flowid];
+	create->flow_ring_addr.high_addr = cpu_to_le32(address >> 32);
+	create->flow_ring_addr.low_addr = cpu_to_le32(address & 0xffffffff);
+	create->max_items = cpu_to_le16(BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+	create->len_item = cpu_to_le16(BRCMF_H2D_TXFLOWRING_ITEMSIZE);
+
+	brcmf_dbg(MSGBUF, "Send Flow Create Req flow ID %d for peer %pM prio %d ifindex %d\n",
+		  flowid, eh->h_dest, create->tid, ifidx);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+	if (err) {
+		brcmf_err("Failed to write commonring\n");
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	return flowid;
+}
+
+
+static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
+{
+	struct brcmf_flowring *flow = msgbuf->flow;
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u32 count;
+	struct sk_buff *skb;
+	dma_addr_t physaddr;
+	u32 pktid;
+	struct msgbuf_tx_msghdr *tx_msghdr;
+	long long address;
+
+	commonring = msgbuf->flowrings[flowid];
+	if (!brcmf_commonring_write_available(commonring))
+		return;
+
+	brcmf_commonring_lock(commonring);
+
+	count = BRCMF_MSGBUF_TX_FLUSH_CNT2 - BRCMF_MSGBUF_TX_FLUSH_CNT1;
+	while (brcmf_flowring_qlen(flow, flowid)) {
+		skb = brcmf_flowring_dequeue(flow, flowid);
+		if (skb == NULL) {
+			brcmf_err("No SKB, but qlen %d\n",
+				  brcmf_flowring_qlen(flow, flowid));
+			break;
+		}
+		skb_orphan(skb);
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->tx_pktids, skb, ETH_HLEN,
+					     &physaddr, &pktid)) {
+			brcmf_flowring_reinsert(flow, flowid, skb);
+			brcmf_err("No PKTID available !!\n");
+			break;
+		}
+		ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+		if (!ret_ptr) {
+			brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+					       msgbuf->tx_pktids, pktid);
+			brcmf_flowring_reinsert(flow, flowid, skb);
+			break;
+		}
+		count++;
+
+		tx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr;
+
+		tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST;
+		tx_msghdr->msg.request_id = cpu_to_le32(pktid);
+		tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+		tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;
+		tx_msghdr->flags |= (skb->priority & 0x07) <<
+				    BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
+		tx_msghdr->seg_cnt = 1;
+		memcpy(tx_msghdr->txhdr, skb->data, ETH_HLEN);
+		tx_msghdr->data_len = cpu_to_le16(skb->len - ETH_HLEN);
+		address = (long long)(long)physaddr;
+		tx_msghdr->data_buf_addr.high_addr = cpu_to_le32(address >> 32);
+		tx_msghdr->data_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		tx_msghdr->metadata_buf_len = 0;
+		tx_msghdr->metadata_buf_addr.high_addr = 0;
+		tx_msghdr->metadata_buf_addr.low_addr = 0;
+		if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) {
+			brcmf_commonring_write_complete(commonring);
+			count = 0;
+		}
+	}
+	if (count)
+		brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+}
+
+
+static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)
+{
+	struct brcmf_msgbuf *msgbuf;
+	u32 flowid;
+
+	msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);
+	for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) {
+		clear_bit(flowid, msgbuf->flow_map);
+		brcmf_msgbuf_txflow(msgbuf, flowid);
+	}
+}
+
+
+static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid)
+{
+	set_bit(flowid, msgbuf->flow_map);
+	queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+
+	return 0;
+}
+
+
+static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
+			       u8 offset, struct sk_buff *skb)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_flowring *flow = msgbuf->flow;
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	u32 flowid;
+
+	flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
+	if (flowid == BRCMF_FLOWRING_INVALID_ID) {
+		flowid = brcmf_msgbuf_flowring_create(msgbuf, ifidx, skb);
+		if (flowid == BRCMF_FLOWRING_INVALID_ID)
+			return -ENOMEM;
+	}
+	brcmf_flowring_enqueue(flow, flowid, skb);
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+
+	return 0;
+}
+
+
+static void
+brcmf_msgbuf_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				 enum proto_addr_mode addr_mode)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_configure_addr_mode(msgbuf->flow, ifidx, addr_mode);
+}
+
+
+static void
+brcmf_msgbuf_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_delete_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_add_tdls_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_ioctl_resp_hdr *ioctl_resp;
+
+	ioctl_resp = (struct msgbuf_ioctl_resp_hdr *)buf;
+
+	msgbuf->ioctl_resp_status = le16_to_cpu(ioctl_resp->compl_hdr.status);
+	msgbuf->ioctl_resp_ret_len = le16_to_cpu(ioctl_resp->resp_len);
+	msgbuf->ioctl_resp_pktid = le32_to_cpu(ioctl_resp->msg.request_id);
+
+	brcmf_msgbuf_ioctl_resp_wake(msgbuf);
+
+	if (msgbuf->cur_ioctlrespbuf)
+		msgbuf->cur_ioctlrespbuf--;
+	brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+}
+
+
+static void
+brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_tx_status *tx_status;
+	u32 idx;
+	struct sk_buff *skb;
+	u16 flowid;
+
+	tx_status = (struct msgbuf_tx_status *)buf;
+	idx = le32_to_cpu(tx_status->msg.request_id);
+	flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->tx_pktids, idx);
+	if (!skb) {
+		brcmf_err("Invalid packet id idx recv'd %d\n", idx);
+		return;
+	}
+
+	set_bit(flowid, msgbuf->txstatus_done_map);
+
+	brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
+}
+
+
+static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
+{
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	struct sk_buff *skb;
+	u16 alloced;
+	u32 pktlen;
+	dma_addr_t physaddr;
+	struct msgbuf_rx_bufpost *rx_bufpost;
+	long long address;
+	u32 pktid;
+	u32 i;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+	ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+							      count,
+							      &alloced);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		return 0;
+	}
+
+	for (i = 0; i < alloced; i++) {
+		rx_bufpost = (struct msgbuf_rx_bufpost *)ret_ptr;
+		memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+		skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+		if (skb == NULL) {
+			brcmf_err("Failed to alloc SKB\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		pktlen = skb->len;
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->rx_pktids, skb, 0,
+					     &physaddr, &pktid)) {
+			dev_kfree_skb_any(skb);
+			brcmf_err("No PKTID available !!\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		if (msgbuf->rx_metadata_offset) {
+			address = (long long)(long)physaddr;
+			rx_bufpost->metadata_buf_len =
+				cpu_to_le16(msgbuf->rx_metadata_offset);
+			rx_bufpost->metadata_buf_addr.high_addr =
+				cpu_to_le32(address >> 32);
+			rx_bufpost->metadata_buf_addr.low_addr =
+				cpu_to_le32(address & 0xffffffff);
+
+			skb_pull(skb, msgbuf->rx_metadata_offset);
+			pktlen = skb->len;
+			physaddr += msgbuf->rx_metadata_offset;
+		}
+		rx_bufpost->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
+		rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+		address = (long long)(long)physaddr;
+		rx_bufpost->data_buf_len = cpu_to_le16((u16)pktlen);
+		rx_bufpost->data_buf_addr.high_addr =
+			cpu_to_le32(address >> 32);
+		rx_bufpost->data_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+
+		ret_ptr += brcmf_commonring_len_item(commonring);
+	}
+
+	if (i)
+		brcmf_commonring_write_complete(commonring);
+
+	return i;
+}
+
+
+static void
+brcmf_msgbuf_rxbuf_data_fill(struct brcmf_msgbuf *msgbuf)
+{
+	u32 fillbufs;
+	u32 retcount;
+
+	fillbufs = msgbuf->max_rxbufpost - msgbuf->rxbufpost;
+
+	while (fillbufs) {
+		retcount = brcmf_msgbuf_rxbuf_data_post(msgbuf, fillbufs);
+		if (!retcount)
+			break;
+		msgbuf->rxbufpost += retcount;
+		fillbufs -= retcount;
+	}
+}
+
+
+static void
+brcmf_msgbuf_update_rxbufpost_count(struct brcmf_msgbuf *msgbuf, u16 rxcnt)
+{
+	msgbuf->rxbufpost -= rxcnt;
+	if (msgbuf->rxbufpost <= (msgbuf->max_rxbufpost -
+				  BRCMF_MSGBUF_RXBUFPOST_THRESHOLD))
+		brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+}
+
+
+static u32
+brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
+			     u32 count)
+{
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	struct sk_buff *skb;
+	u16 alloced;
+	u32 pktlen;
+	dma_addr_t physaddr;
+	struct msgbuf_rx_ioctl_resp_or_event *rx_bufpost;
+	long long address;
+	u32 pktid;
+	u32 i;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+							      count,
+							      &alloced);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		return 0;
+	}
+
+	for (i = 0; i < alloced; i++) {
+		rx_bufpost = (struct msgbuf_rx_ioctl_resp_or_event *)ret_ptr;
+		memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+		skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+		if (skb == NULL) {
+			brcmf_err("Failed to alloc SKB\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		pktlen = skb->len;
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->rx_pktids, skb, 0,
+					     &physaddr, &pktid)) {
+			dev_kfree_skb_any(skb);
+			brcmf_err("No PKTID available !!\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+		if (event_buf)
+			rx_bufpost->msg.msgtype = MSGBUF_TYPE_EVENT_BUF_POST;
+		else
+			rx_bufpost->msg.msgtype =
+				MSGBUF_TYPE_IOCTLRESP_BUF_POST;
+		rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+		address = (long long)(long)physaddr;
+		rx_bufpost->host_buf_len = cpu_to_le16((u16)pktlen);
+		rx_bufpost->host_buf_addr.high_addr =
+			cpu_to_le32(address >> 32);
+		rx_bufpost->host_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+
+		ret_ptr += brcmf_commonring_len_item(commonring);
+	}
+
+	if (i)
+		brcmf_commonring_write_complete(commonring);
+
+	brcmf_commonring_unlock(commonring);
+
+	return i;
+}
+
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf)
+{
+	u32 count;
+
+	count = msgbuf->max_ioctlrespbuf - msgbuf->cur_ioctlrespbuf;
+	count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, false, count);
+	msgbuf->cur_ioctlrespbuf += count;
+}
+
+
+static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf)
+{
+	u32 count;
+
+	count = msgbuf->max_eventbuf - msgbuf->cur_eventbuf;
+	count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, true, count);
+	msgbuf->cur_eventbuf += count;
+}
+
+
+static void
+brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
+		    u8 ifidx)
+{
+	struct brcmf_if *ifp;
+
+	ifp = msgbuf->drvr->iflist[ifidx];
+	if (!ifp || !ifp->ndev) {
+		brcmu_pkt_buf_free_skb(skb);
+		return;
+	}
+	brcmf_netif_rx(ifp, skb);
+}
+
+
+static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_rx_event *event;
+	u32 idx;
+	u16 buflen;
+	struct sk_buff *skb;
+
+	event = (struct msgbuf_rx_event *)buf;
+	idx = le32_to_cpu(event->msg.request_id);
+	buflen = le16_to_cpu(event->event_data_len);
+
+	if (msgbuf->cur_eventbuf)
+		msgbuf->cur_eventbuf--;
+	brcmf_msgbuf_rxbuf_event_post(msgbuf);
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids, idx);
+	if (!skb)
+		return;
+
+	if (msgbuf->rx_dataoffset)
+		skb_pull(skb, msgbuf->rx_dataoffset);
+
+	skb_trim(skb, buflen);
+
+	brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx);
+}
+
+
+static void
+brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_rx_complete *rx_complete;
+	struct sk_buff *skb;
+	u16 data_offset;
+	u16 buflen;
+	u32 idx;
+
+	brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
+
+	rx_complete = (struct msgbuf_rx_complete *)buf;
+	data_offset = le16_to_cpu(rx_complete->data_offset);
+	buflen = le16_to_cpu(rx_complete->data_len);
+	idx = le32_to_cpu(rx_complete->msg.request_id);
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids, idx);
+
+	if (data_offset)
+		skb_pull(skb, data_offset);
+	else if (msgbuf->rx_dataoffset)
+		skb_pull(skb, msgbuf->rx_dataoffset);
+
+	skb_trim(skb, buflen);
+
+	brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
+					       void *buf)
+{
+	struct msgbuf_flowring_create_resp *flowring_create_resp;
+	u16 status;
+	u16 flowid;
+
+	flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf;
+
+	flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	status =  le16_to_cpu(flowring_create_resp->compl_hdr.status);
+
+	if (status) {
+		brcmf_err("Flowring creation failed, code %d\n", status);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return;
+	}
+	brcmf_dbg(MSGBUF, "Flowring %d Create response status %d\n", flowid,
+		  status);
+
+	brcmf_flowring_open(msgbuf->flow, flowid);
+
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
+					       void *buf)
+{
+	struct msgbuf_flowring_delete_resp *flowring_delete_resp;
+	u16 status;
+	u16 flowid;
+
+	flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf;
+
+	flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	status =  le16_to_cpu(flowring_delete_resp->compl_hdr.status);
+
+	if (status) {
+		brcmf_err("Flowring deletion failed, code %d\n", status);
+		brcmf_flowring_delete(msgbuf->flow, flowid);
+		return;
+	}
+	brcmf_dbg(MSGBUF, "Flowring %d Delete response status %d\n", flowid,
+		  status);
+
+	brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+}
+
+
+static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_common_hdr *msg;
+
+	msg = (struct msgbuf_common_hdr *)buf;
+	switch (msg->msgtype) {
+	case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT\n");
+		brcmf_msgbuf_process_flow_ring_create_response(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT\n");
+		brcmf_msgbuf_process_flow_ring_delete_response(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_IOCTLPTR_REQ_ACK:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTLPTR_REQ_ACK\n");
+		break;
+	case MSGBUF_TYPE_IOCTL_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTL_CMPLT\n");
+		brcmf_msgbuf_process_ioctl_complete(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_WL_EVENT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_WL_EVENT\n");
+		brcmf_msgbuf_process_event(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_TX_STATUS:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_TX_STATUS\n");
+		brcmf_msgbuf_process_txstatus(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_RX_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RX_CMPLT\n");
+		brcmf_msgbuf_process_rx_complete(msgbuf, buf);
+		break;
+	default:
+		brcmf_err("Unsupported msgtype %d\n", msg->msgtype);
+		break;
+	}
+}
+
+
+static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
+				    struct brcmf_commonring *commonring)
+{
+	void *buf;
+	u16 count;
+
+again:
+	buf = brcmf_commonring_get_read_ptr(commonring, &count);
+	if (buf == NULL)
+		return;
+
+	while (count) {
+		brcmf_msgbuf_process_msgtype(msgbuf,
+					     buf + msgbuf->rx_dataoffset);
+		buf += brcmf_commonring_len_item(commonring);
+		count--;
+	}
+	brcmf_commonring_read_complete(commonring);
+
+	if (commonring->r_ptr == 0)
+		goto again;
+}
+
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	void *buf;
+	u32 flowid;
+
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+
+	for_each_set_bit(flowid, msgbuf->txstatus_done_map,
+			 msgbuf->nrof_flowrings) {
+		clear_bit(flowid, msgbuf->txstatus_done_map);
+		if (brcmf_flowring_qlen(msgbuf->flow, flowid))
+			brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+	}
+
+	return 0;
+}
+
+
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct msgbuf_tx_flowring_delete_req *delete;
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u8 ifidx;
+	int err;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("FW unaware, flowring will be removed !!\n");
+		brcmf_commonring_unlock(commonring);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return;
+	}
+
+	delete = (struct msgbuf_tx_flowring_delete_req *)ret_ptr;
+
+	ifidx = brcmf_flowring_ifidx_get(msgbuf->flow, flowid);
+
+	delete->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE;
+	delete->msg.ifidx = ifidx;
+	delete->msg.request_id = 0;
+
+	delete->flow_ring_id = cpu_to_le16(flowid +
+					   BRCMF_NROF_H2D_COMMON_MSGRINGS);
+	delete->reason = 0;
+
+	brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n",
+		  flowid, ifidx);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+	if (err) {
+		brcmf_err("Failed to submit RING_DELETE, flowring will be removed\n");
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+	}
+}
+
+
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_bus_msgbuf *if_msgbuf;
+	struct brcmf_msgbuf *msgbuf;
+	long long address;
+	u32 count;
+
+	if_msgbuf = drvr->bus_if->msgbuf;
+	msgbuf = kzalloc(sizeof(*msgbuf), GFP_ATOMIC);
+	if (!msgbuf)
+		goto fail;
+
+	msgbuf->txflow_wq = create_singlethread_workqueue("msgbuf_txflow");
+	if (msgbuf->txflow_wq == NULL) {
+		brcmf_err("workqueue creation failed\n");
+		goto fail;
+	}
+	INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
+	count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
+	msgbuf->flow_map = kzalloc(count, GFP_ATOMIC);
+	if (!msgbuf->flow_map)
+		goto fail;
+
+	msgbuf->txstatus_done_map = kzalloc(count, GFP_ATOMIC);
+	if (!msgbuf->txstatus_done_map)
+		goto fail;
+
+	msgbuf->drvr = drvr;
+	msgbuf->ioctbuf = dma_alloc_coherent(drvr->bus_if->dev,
+					     BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+					     &msgbuf->ioctbuf_handle,
+					     GFP_ATOMIC);
+	if (!msgbuf->ioctbuf)
+		goto fail;
+	address = (long long)(long)msgbuf->ioctbuf_handle;
+	msgbuf->ioctbuf_phys_hi = address >> 32;
+	msgbuf->ioctbuf_phys_lo = address & 0xffffffff;
+
+	drvr->proto->hdrpull = brcmf_msgbuf_hdrpull;
+	drvr->proto->query_dcmd = brcmf_msgbuf_query_dcmd;
+	drvr->proto->set_dcmd = brcmf_msgbuf_set_dcmd;
+	drvr->proto->txdata = brcmf_msgbuf_txdata;
+	drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
+	drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
+	drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
+	drvr->proto->pd = msgbuf;
+
+	init_waitqueue_head(&msgbuf->ioctl_resp_wait);
+
+	msgbuf->commonrings =
+		(struct brcmf_commonring **)if_msgbuf->commonrings;
+	msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
+	msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings;
+	msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings *
+		sizeof(*msgbuf->flowring_dma_handle), GFP_ATOMIC);
+	if (!msgbuf->flowring_dma_handle)
+		goto fail;
+
+	msgbuf->rx_dataoffset = if_msgbuf->rx_dataoffset;
+	msgbuf->max_rxbufpost = if_msgbuf->max_rxbufpost;
+
+	msgbuf->max_ioctlrespbuf = BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST;
+	msgbuf->max_eventbuf = BRCMF_MSGBUF_MAX_EVENTBUF_POST;
+
+	msgbuf->tx_pktids = brcmf_msgbuf_init_pktids(NR_TX_PKTIDS,
+						     DMA_TO_DEVICE);
+	if (!msgbuf->tx_pktids)
+		goto fail;
+	msgbuf->rx_pktids = brcmf_msgbuf_init_pktids(NR_RX_PKTIDS,
+						     DMA_FROM_DEVICE);
+	if (!msgbuf->rx_pktids)
+		goto fail;
+
+	msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev,
+					     if_msgbuf->nrof_flowrings);
+	if (!msgbuf->flow)
+		goto fail;
+
+
+	brcmf_dbg(MSGBUF, "Feeding buffers, rx data %d, rx event %d, rx ioctl resp %d\n",
+		  msgbuf->max_rxbufpost, msgbuf->max_eventbuf,
+		  msgbuf->max_ioctlrespbuf);
+	count = 0;
+	do {
+		brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+		if (msgbuf->max_rxbufpost != msgbuf->rxbufpost)
+			msleep(10);
+		else
+			break;
+		count++;
+	} while (count < 10);
+	brcmf_msgbuf_rxbuf_event_post(msgbuf);
+	brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+
+	return 0;
+
+fail:
+	if (msgbuf) {
+		kfree(msgbuf->flow_map);
+		kfree(msgbuf->txstatus_done_map);
+		brcmf_msgbuf_release_pktids(msgbuf);
+		kfree(msgbuf->flowring_dma_handle);
+		if (msgbuf->ioctbuf)
+			dma_free_coherent(drvr->bus_if->dev,
+					  BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+					  msgbuf->ioctbuf,
+					  msgbuf->ioctbuf_handle);
+		kfree(msgbuf);
+	}
+	return -ENOMEM;
+}
+
+
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr)
+{
+	struct brcmf_msgbuf *msgbuf;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (drvr->proto->pd) {
+		msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+		kfree(msgbuf->flow_map);
+		kfree(msgbuf->txstatus_done_map);
+		if (msgbuf->txflow_wq)
+			destroy_workqueue(msgbuf->txflow_wq);
+
+		brcmf_flowring_detach(msgbuf->flow);
+		dma_free_coherent(drvr->bus_if->dev,
+				  BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+				  msgbuf->ioctbuf, msgbuf->ioctbuf_handle);
+		brcmf_msgbuf_release_pktids(msgbuf);
+		kfree(msgbuf->flowring_dma_handle);
+		kfree(msgbuf);
+		drvr->proto->pd = NULL;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,47 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_MSGBUF_H
+#define BRCMFMAC_MSGBUF_H
+
+#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM	20
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM	256
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM	20
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM		1024
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM		256
+#define BRCMF_H2D_TXFLOWRING_MAX_ITEM			512
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE	40
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE	32
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE	24
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE		16
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE		32
+#define BRCMF_H2D_TXFLOWRING_ITEMSIZE			48
+
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid);
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
+#else
+static inline int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+{
+	return 0;
+}
+static inline void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) {}
+#endif
+
+#endif /* BRCMFMAC_MSGBUF_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/mmc/card.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
+#include <linux/mmc/sdio_func.h>
+
+#include <defs.h>
+#include "dhd_dbg.h"
+#include "sdio_host.h"
+
+void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
+{
+	struct device *dev = sdiodev->dev;
+	struct device_node *np = dev->of_node;
+	int irq;
+	u32 irqf;
+	u32 val;
+
+	if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+		return;
+
+	sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL);
+	if (!sdiodev->pdata)
+		return;
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq < 0) {
+		brcmf_err("interrupt could not be mapped: err=%d\n", irq);
+		devm_kfree(dev, sdiodev->pdata);
+		return;
+	}
+	irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+
+	sdiodev->pdata->oob_irq_supported = true;
+	sdiodev->pdata->oob_irq_nr = irq;
+	sdiodev->pdata->oob_irq_flags = irqf;
+
+	if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+		sdiodev->pdata->drive_strength = val;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/of.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef CONFIG_OF
+void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev);
+#else
+static void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
+{
+}
+#endif /* CONFIG_OF */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/p2p.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/p2p.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/p2p.c	2014-09-28 17:29:07.000000000 -0400
@@ -708,7 +708,7 @@ static s32 brcmf_p2p_escan(struct brcmf_
 		active = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
 	else if (num_chans == AF_PEER_SEARCH_CNT)
 		active = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
-	else if (wl_get_vif_state_all(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
+	else if (brcmf_get_vif_state_any(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
 		active = -1;
 	else
 		active = P2PAPI_SCAN_DWELL_TIME_MS;
@@ -2364,7 +2364,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
 		return 0;
 	default:
 		return -ENOTSUPP;
-		break;
 	}
 
 	clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.c	2014-09-28 21:35:43.000000000 -0400
@@ -0,0 +1,1842 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/interrupt.h>
+#include <linux/bcma/bcma.h>
+#include <linux/sched.h>
+
+#include <soc.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcm_hw_ids.h>
+
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
+#include "commonring.h"
+#include "msgbuf.h"
+#include "pcie.h"
+#include "firmware.h"
+#include "chip.h"
+
+
+enum brcmf_pcie_state {
+	BRCMFMAC_PCIE_STATE_DOWN,
+	BRCMFMAC_PCIE_STATE_UP
+};
+
+
+#define BRCMF_PCIE_43602_FW_NAME		"/*(DEBLOBBED)*/"
+#define BRCMF_PCIE_43602_NVRAM_NAME		"brcm/brcmfmac43602-pcie.txt"
+#define BRCMF_PCIE_4354_FW_NAME			"/*(DEBLOBBED)*/"
+#define BRCMF_PCIE_4354_NVRAM_NAME		"brcm/brcmfmac4354-pcie.txt"
+#define BRCMF_PCIE_4356_FW_NAME			"/*(DEBLOBBED)*/"
+#define BRCMF_PCIE_4356_NVRAM_NAME		"brcm/brcmfmac4356-pcie.txt"
+#define BRCMF_PCIE_43570_FW_NAME		"/*(DEBLOBBED)*/"
+#define BRCMF_PCIE_43570_NVRAM_NAME		"brcm/brcmfmac43570-pcie.txt"
+
+#define BRCMF_PCIE_FW_UP_TIMEOUT		2000 /* msec */
+
+#define BRCMF_PCIE_TCM_MAP_SIZE			(4096 * 1024)
+#define BRCMF_PCIE_REG_MAP_SIZE			(32 * 1024)
+
+/* backplane addres space accessed by BAR0 */
+#define	BRCMF_PCIE_BAR0_WINDOW			0x80
+#define BRCMF_PCIE_BAR0_REG_SIZE		0x1000
+#define	BRCMF_PCIE_BAR0_WRAPPERBASE		0x70
+
+#define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET	0x1000
+#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET	0x2000
+
+#define BRCMF_PCIE_ARMCR4REG_BANKIDX		0x40
+#define BRCMF_PCIE_ARMCR4REG_BANKPDA		0x4C
+
+#define BRCMF_PCIE_REG_INTSTATUS		0x90
+#define BRCMF_PCIE_REG_INTMASK			0x94
+#define BRCMF_PCIE_REG_SBMBX			0x98
+
+#define BRCMF_PCIE_PCIE2REG_INTMASK		0x24
+#define BRCMF_PCIE_PCIE2REG_MAILBOXINT		0x48
+#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK		0x4C
+#define BRCMF_PCIE_PCIE2REG_CONFIGADDR		0x120
+#define BRCMF_PCIE_PCIE2REG_CONFIGDATA		0x124
+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX		0x140
+
+#define BRCMF_PCIE_GENREV1			1
+#define BRCMF_PCIE_GENREV2			2
+
+#define BRCMF_PCIE2_INTA			0x01
+#define BRCMF_PCIE2_INTB			0x02
+
+#define BRCMF_PCIE_INT_0			0x01
+#define BRCMF_PCIE_INT_1			0x02
+#define BRCMF_PCIE_INT_DEF			(BRCMF_PCIE_INT_0 | \
+						 BRCMF_PCIE_INT_1)
+
+#define BRCMF_PCIE_MB_INT_FN0_0			0x0100
+#define BRCMF_PCIE_MB_INT_FN0_1			0x0200
+#define	BRCMF_PCIE_MB_INT_D2H0_DB0		0x10000
+#define	BRCMF_PCIE_MB_INT_D2H0_DB1		0x20000
+#define	BRCMF_PCIE_MB_INT_D2H1_DB0		0x40000
+#define	BRCMF_PCIE_MB_INT_D2H1_DB1		0x80000
+#define	BRCMF_PCIE_MB_INT_D2H2_DB0		0x100000
+#define	BRCMF_PCIE_MB_INT_D2H2_DB1		0x200000
+#define	BRCMF_PCIE_MB_INT_D2H3_DB0		0x400000
+#define	BRCMF_PCIE_MB_INT_D2H3_DB1		0x800000
+
+#define BRCMF_PCIE_MB_INT_D2H_DB		(BRCMF_PCIE_MB_INT_D2H0_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H0_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H1_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H1_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H2_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H2_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H3_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H3_DB1)
+
+#define BRCMF_PCIE_MIN_SHARED_VERSION		4
+#define BRCMF_PCIE_MAX_SHARED_VERSION		5
+#define BRCMF_PCIE_SHARED_VERSION_MASK		0x00FF
+#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT	0x4000
+
+#define BRCMF_PCIE_FLAGS_HTOD_SPLIT		0x4000
+#define BRCMF_PCIE_FLAGS_DTOH_SPLIT		0x8000
+
+#define BRCMF_SHARED_MAX_RXBUFPOST_OFFSET	34
+#define BRCMF_SHARED_RING_BASE_OFFSET		52
+#define BRCMF_SHARED_RX_DATAOFFSET_OFFSET	36
+#define BRCMF_SHARED_CONSOLE_ADDR_OFFSET	20
+#define BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET	40
+#define BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET	44
+#define BRCMF_SHARED_RING_INFO_ADDR_OFFSET	48
+#define BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET	52
+#define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET	56
+#define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET	64
+#define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET	68
+
+#define BRCMF_RING_H2D_RING_COUNT_OFFSET	0
+#define BRCMF_RING_D2H_RING_COUNT_OFFSET	1
+#define BRCMF_RING_H2D_RING_MEM_OFFSET		4
+#define BRCMF_RING_H2D_RING_STATE_OFFSET	8
+
+#define BRCMF_RING_MEM_BASE_ADDR_OFFSET		8
+#define BRCMF_RING_MAX_ITEM_OFFSET		4
+#define BRCMF_RING_LEN_ITEMS_OFFSET		6
+#define BRCMF_RING_MEM_SZ			16
+#define BRCMF_RING_STATE_SZ			8
+
+#define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET	4
+#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET	8
+#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET	12
+#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET	16
+#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET	0
+#define BRCMF_SHARED_RING_MAX_SUB_QUEUES	52
+
+#define BRCMF_DEF_MAX_RXBUFPOST			255
+
+#define BRCMF_CONSOLE_BUFADDR_OFFSET		8
+#define BRCMF_CONSOLE_BUFSIZE_OFFSET		12
+#define BRCMF_CONSOLE_WRITEIDX_OFFSET		16
+
+#define BRCMF_DMA_D2H_SCRATCH_BUF_LEN		8
+#define BRCMF_DMA_D2H_RINGUPD_BUF_LEN		1024
+
+#define BRCMF_D2H_DEV_D3_ACK			0x00000001
+#define BRCMF_D2H_DEV_DS_ENTER_REQ		0x00000002
+#define BRCMF_D2H_DEV_DS_EXIT_NOTE		0x00000004
+
+#define BRCMF_H2D_HOST_D3_INFORM		0x00000001
+#define BRCMF_H2D_HOST_DS_ACK			0x00000002
+
+#define BRCMF_PCIE_MBDATA_TIMEOUT		2000
+
+#define BRCMF_PCIE_CFGREG_STATUS_CMD		0x4
+#define BRCMF_PCIE_CFGREG_PM_CSR		0x4C
+#define BRCMF_PCIE_CFGREG_MSI_CAP		0x58
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_L		0x5C
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_H		0x60
+#define BRCMF_PCIE_CFGREG_MSI_DATA		0x64
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL	0xBC
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2	0xDC
+#define BRCMF_PCIE_CFGREG_RBAR_CTRL		0x228
+#define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1	0x248
+#define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG	0x4E0
+#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG	0x4F4
+#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB	3
+
+
+/*(DEBLOBBED)*/
+
+
+struct brcmf_pcie_console {
+	u32 base_addr;
+	u32 buf_addr;
+	u32 bufsize;
+	u32 read_idx;
+	u8 log_str[256];
+	u8 log_idx;
+};
+
+struct brcmf_pcie_shared_info {
+	u32 tcm_base_address;
+	u32 flags;
+	struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+	struct brcmf_pcie_ringbuf *flowrings;
+	u16 max_rxbufpost;
+	u32 nrof_flowrings;
+	u32 rx_dataoffset;
+	u32 htod_mb_data_addr;
+	u32 dtoh_mb_data_addr;
+	u32 ring_info_addr;
+	struct brcmf_pcie_console console;
+	void *scratch;
+	dma_addr_t scratch_dmahandle;
+	void *ringupd;
+	dma_addr_t ringupd_dmahandle;
+};
+
+struct brcmf_pcie_core_info {
+	u32 base;
+	u32 wrapbase;
+};
+
+struct brcmf_pciedev_info {
+	enum brcmf_pcie_state state;
+	bool in_irq;
+	bool irq_requested;
+	struct pci_dev *pdev;
+	char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+	char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+	void __iomem *regs;
+	void __iomem *tcm;
+	u32 tcm_size;
+	u32 ram_base;
+	u32 ram_size;
+	struct brcmf_chip *ci;
+	u32 coreid;
+	u32 generic_corerev;
+	struct brcmf_pcie_shared_info shared;
+	void (*ringbell)(struct brcmf_pciedev_info *devinfo);
+	wait_queue_head_t mbdata_resp_wait;
+	bool mbdata_completed;
+	bool irq_allocated;
+};
+
+struct brcmf_pcie_ringbuf {
+	struct brcmf_commonring commonring;
+	dma_addr_t dma_handle;
+	u32 w_idx_addr;
+	u32 r_idx_addr;
+	struct brcmf_pciedev_info *devinfo;
+	u8 id;
+};
+
+
+static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
+	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
+	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM,
+	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM,
+	BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM,
+	BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM
+};
+
+static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
+	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
+	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
+	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
+	BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE,
+	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
+};
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+static u32
+brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+{
+	void __iomem *address = devinfo->regs + reg_offset;
+
+	return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
+		       u32 value)
+{
+	void __iomem *address = devinfo->regs + reg_offset;
+
+	iowrite32(value, address);
+}
+
+
+static u8
+brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread8(address));
+}
+
+
+static u16
+brcmf_pcie_read_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread16(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u16 value)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	iowrite16(value, address);
+}
+
+
+static u32
+brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u32 value)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	iowrite32(value, address);
+}
+
+
+static u32
+brcmf_pcie_read_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+	return (ioread32(addr));
+}
+
+
+static void
+brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u32 value)
+{
+	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+	iowrite32(value, addr);
+}
+
+
+static void
+brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+			  void *srcaddr, u32 len)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+	__le32 *src32;
+	__le16 *src16;
+	u8 *src8;
+
+	if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) {
+		if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) {
+			src8 = (u8 *)srcaddr;
+			while (len) {
+				iowrite8(*src8, address);
+				address++;
+				src8++;
+				len--;
+			}
+		} else {
+			len = len / 2;
+			src16 = (__le16 *)srcaddr;
+			while (len) {
+				iowrite16(le16_to_cpu(*src16), address);
+				address += 2;
+				src16++;
+				len--;
+			}
+		}
+	} else {
+		len = len / 4;
+		src32 = (__le32 *)srcaddr;
+		while (len) {
+			iowrite32(le32_to_cpu(*src32), address);
+			address += 4;
+			src32++;
+			len--;
+		}
+	}
+}
+
+
+#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
+		CHIPCREGOFFS(reg), value)
+
+
+static void
+brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
+{
+	const struct pci_dev *pdev = devinfo->pdev;
+	struct brcmf_core *core;
+	u32 bar0_win;
+
+	core = brcmf_chip_get_core(devinfo->ci, coreid);
+	if (core) {
+		bar0_win = core->base;
+		pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, bar0_win);
+		if (pci_read_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW,
+					  &bar0_win) == 0) {
+			if (bar0_win != core->base) {
+				bar0_win = core->base;
+				pci_write_config_dword(pdev,
+						       BRCMF_PCIE_BAR0_WINDOW,
+						       bar0_win);
+			}
+		}
+	} else {
+		brcmf_err("Unsupported core selected %x\n", coreid);
+	}
+}
+
+
+static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
+{
+	u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
+			     BRCMF_PCIE_CFGREG_PM_CSR,
+			     BRCMF_PCIE_CFGREG_MSI_CAP,
+			     BRCMF_PCIE_CFGREG_MSI_ADDR_L,
+			     BRCMF_PCIE_CFGREG_MSI_ADDR_H,
+			     BRCMF_PCIE_CFGREG_MSI_DATA,
+			     BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
+			     BRCMF_PCIE_CFGREG_RBAR_CTRL,
+			     BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
+			     BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
+			     BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG };
+	u32 i;
+	u32 val;
+	u32 lsc;
+
+	if (!devinfo->ci)
+		return;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+	lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+	val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
+	WRITECC32(devinfo, watchdog, 4);
+	msleep(100);
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+				       cfg_offset[i]);
+		val = brcmf_pcie_read_reg32(devinfo,
+					    BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+		brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+			  cfg_offset[i], val);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+				       val);
+	}
+}
+
+
+static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
+{
+	u32 config;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
+		brcmf_pcie_reset_device(devinfo);
+	/* BAR1 window may not be sized properly */
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
+	config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
+
+	device_wakeup_enable(&devinfo->pdev->dev);
+}
+
+
+static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
+{
+	brcmf_chip_enter_download(devinfo->ci);
+
+	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+				       5);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+				       0);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+				       7);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+				       0);
+	}
+	return 0;
+}
+
+
+static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
+					  u32 resetintr)
+{
+	struct brcmf_core *core;
+
+	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+		core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_INTERNAL_MEM);
+		brcmf_chip_resetcore(core, 0, 0, 0);
+	}
+
+	return !brcmf_chip_exit_download(devinfo->ci, resetintr);
+}
+
+
+static void
+brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+	u32 cur_htod_mb_data;
+	u32 i;
+
+	shared = &devinfo->shared;
+	addr = shared->htod_mb_data_addr;
+	cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	if (cur_htod_mb_data != 0)
+		brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",
+			  cur_htod_mb_data);
+
+	i = 0;
+	while (cur_htod_mb_data != 0) {
+		msleep(10);
+		i++;
+		if (i > 100)
+			break;
+		cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+	}
+
+	brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+}
+
+
+static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+	u32 dtoh_mb_data;
+
+	shared = &devinfo->shared;
+	addr = shared->dtoh_mb_data_addr;
+	dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	if (!dtoh_mb_data)
+		return;
+
+	brcmf_pcie_write_tcm32(devinfo, addr, 0);
+
+	brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
+	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ)  {
+		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
+		brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
+		brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
+	}
+	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
+		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
+	if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
+		brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
+		if (waitqueue_active(&devinfo->mbdata_resp_wait)) {
+			devinfo->mbdata_completed = true;
+			wake_up(&devinfo->mbdata_resp_wait);
+		}
+	}
+}
+
+
+static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_shared_info *shared;
+	struct brcmf_pcie_console *console;
+	u32 addr;
+
+	shared = &devinfo->shared;
+	console = &shared->console;
+	addr = shared->tcm_base_address + BRCMF_SHARED_CONSOLE_ADDR_OFFSET;
+	console->base_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = console->base_addr + BRCMF_CONSOLE_BUFADDR_OFFSET;
+	console->buf_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+	addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
+	console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
+		  console->base_addr, console->buf_addr, console->bufsize);
+}
+
+
+static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_console *console;
+	u32 addr;
+	u8 ch;
+	u32 newidx;
+
+	console = &devinfo->shared.console;
+	addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
+	newidx = brcmf_pcie_read_tcm32(devinfo, addr);
+	while (newidx != console->read_idx) {
+		addr = console->buf_addr + console->read_idx;
+		ch = brcmf_pcie_read_tcm8(devinfo, addr);
+		console->read_idx++;
+		if (console->read_idx == console->bufsize)
+			console->read_idx = 0;
+		if (ch == '\r')
+			continue;
+		console->log_str[console->log_idx] = ch;
+		console->log_idx++;
+		if ((ch != '\n') &&
+		    (console->log_idx == (sizeof(console->log_str) - 2))) {
+			ch = '\n';
+			console->log_str[console->log_idx] = ch;
+			console->log_idx++;
+		}
+
+		if (ch == '\n') {
+			console->log_str[console->log_idx] = 0;
+			brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str);
+			console->log_idx = 0;
+		}
+	}
+}
+
+
+static __used void brcmf_pcie_ringbell_v1(struct brcmf_pciedev_info *devinfo)
+{
+	u32 reg_value;
+
+	brcmf_dbg(PCIE, "RING !\n");
+	reg_value = brcmf_pcie_read_reg32(devinfo,
+					  BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+	reg_value |= BRCMF_PCIE2_INTB;
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+			       reg_value);
+}
+
+
+static void brcmf_pcie_ringbell_v2(struct brcmf_pciedev_info *devinfo)
+{
+	brcmf_dbg(PCIE, "RING !\n");
+	/* Any arbitrary value will do, lets use 1 */
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1);
+}
+
+
+static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+		pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+				       0);
+	else
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+				       0);
+}
+
+
+static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+		pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+				       BRCMF_PCIE_INT_DEF);
+	else
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+				       BRCMF_PCIE_MB_INT_D2H_DB |
+				       BRCMF_PCIE_MB_INT_FN0_0 |
+				       BRCMF_PCIE_MB_INT_FN0_1);
+}
+
+
+static irqreturn_t brcmf_pcie_quick_check_isr_v1(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+	u32 status;
+
+	status = 0;
+	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+	if (status) {
+		brcmf_pcie_intr_disable(devinfo);
+		brcmf_dbg(PCIE, "Enter\n");
+		return IRQ_WAKE_THREAD;
+	}
+	return IRQ_NONE;
+}
+
+
+static irqreturn_t brcmf_pcie_quick_check_isr_v2(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+
+	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
+		brcmf_pcie_intr_disable(devinfo);
+		brcmf_dbg(PCIE, "Enter\n");
+		return IRQ_WAKE_THREAD;
+	}
+	return IRQ_NONE;
+}
+
+
+static irqreturn_t brcmf_pcie_isr_thread_v1(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+	const struct pci_dev *pdev = devinfo->pdev;
+	u32 status;
+
+	devinfo->in_irq = true;
+	status = 0;
+	pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+	brcmf_dbg(PCIE, "Enter %x\n", status);
+	if (status) {
+		pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+		if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+			brcmf_proto_msgbuf_rx_trigger(&devinfo->pdev->dev);
+	}
+	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+		brcmf_pcie_intr_enable(devinfo);
+	devinfo->in_irq = false;
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t brcmf_pcie_isr_thread_v2(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+	u32 status;
+
+	devinfo->in_irq = true;
+	status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+	brcmf_dbg(PCIE, "Enter %x\n", status);
+	if (status) {
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+				       status);
+		if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
+			      BRCMF_PCIE_MB_INT_FN0_1))
+			brcmf_pcie_handle_mb_data(devinfo);
+		if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
+			if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+				brcmf_proto_msgbuf_rx_trigger(
+							&devinfo->pdev->dev);
+		}
+	}
+	brcmf_pcie_bus_console_read(devinfo);
+	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+		brcmf_pcie_intr_enable(devinfo);
+	devinfo->in_irq = false;
+	return IRQ_HANDLED;
+}
+
+
+static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+
+	pdev = devinfo->pdev;
+
+	brcmf_pcie_intr_disable(devinfo);
+
+	brcmf_dbg(PCIE, "Enter\n");
+	/* is it a v1 or v2 implementation */
+	devinfo->irq_requested = false;
+	if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+		if (request_threaded_irq(pdev->irq,
+					 brcmf_pcie_quick_check_isr_v1,
+					 brcmf_pcie_isr_thread_v1,
+					 IRQF_SHARED, "brcmf_pcie_intr",
+					 devinfo)) {
+			brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+			return -EIO;
+		}
+	} else {
+		if (request_threaded_irq(pdev->irq,
+					 brcmf_pcie_quick_check_isr_v2,
+					 brcmf_pcie_isr_thread_v2,
+					 IRQF_SHARED, "brcmf_pcie_intr",
+					 devinfo)) {
+			brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+			return -EIO;
+		}
+	}
+	devinfo->irq_requested = true;
+	devinfo->irq_allocated = true;
+	return 0;
+}
+
+
+static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+	u32 status;
+	u32 count;
+
+	if (!devinfo->irq_allocated)
+		return;
+
+	pdev = devinfo->pdev;
+
+	brcmf_pcie_intr_disable(devinfo);
+	if (!devinfo->irq_requested)
+		return;
+	devinfo->irq_requested = false;
+	free_irq(pdev->irq, devinfo);
+
+	msleep(50);
+	count = 0;
+	while ((devinfo->in_irq) && (count < 20)) {
+		msleep(50);
+		count++;
+	}
+	if (devinfo->in_irq)
+		brcmf_err("Still in IRQ (processing) !!!\n");
+
+	if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+		status = 0;
+		pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+		pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+	} else {
+		status = brcmf_pcie_read_reg32(devinfo,
+					       BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+				       status);
+	}
+	devinfo->irq_allocated = false;
+}
+
+
+static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+		  commonring->w_ptr, ring->id);
+
+	brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+		  commonring->r_ptr, ring->id);
+
+	brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	devinfo->ringbell(devinfo);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
+
+	brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+		  commonring->w_ptr, ring->id);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
+
+	brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+		  commonring->r_ptr, ring->id);
+
+	return 0;
+}
+
+
+static void *
+brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
+				     u32 size, u32 tcm_dma_phys_addr,
+				     dma_addr_t *dma_handle)
+{
+	void *ring;
+	long long address;
+
+	ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,
+				  GFP_KERNEL);
+	if (!ring)
+		return NULL;
+
+	address = (long long)(long)*dma_handle;
+	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,
+			       address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
+
+	memset(ring, 0, size);
+
+	return (ring);
+}
+
+
+static struct brcmf_pcie_ringbuf *
+brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info *devinfo, u32 ring_id,
+			      u32 tcm_ring_phys_addr)
+{
+	void *dma_buf;
+	dma_addr_t dma_handle;
+	struct brcmf_pcie_ringbuf *ring;
+	u32 size;
+	u32 addr;
+
+	size = brcmf_ring_max_item[ring_id] * brcmf_ring_itemsize[ring_id];
+	dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,
+			tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,
+			&dma_handle);
+	if (!dma_buf)
+		return NULL;
+
+	addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;
+	brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);
+	addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;
+	brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_itemsize[ring_id]);
+
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	if (!ring) {
+		dma_free_coherent(&devinfo->pdev->dev, size, dma_buf,
+				  dma_handle);
+		return NULL;
+	}
+	brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],
+				brcmf_ring_itemsize[ring_id], dma_buf);
+	ring->dma_handle = dma_handle;
+	ring->devinfo = devinfo;
+	brcmf_commonring_register_cb(&ring->commonring,
+				     brcmf_pcie_ring_mb_ring_bell,
+				     brcmf_pcie_ring_mb_update_rptr,
+				     brcmf_pcie_ring_mb_update_wptr,
+				     brcmf_pcie_ring_mb_write_rptr,
+				     brcmf_pcie_ring_mb_write_wptr, ring);
+
+	return (ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffer(struct device *dev,
+					  struct brcmf_pcie_ringbuf *ring)
+{
+	void *dma_buf;
+	u32 size;
+
+	if (!ring)
+		return;
+
+	dma_buf = ring->commonring.buf_addr;
+	if (dma_buf) {
+		size = ring->commonring.depth * ring->commonring.item_len;
+		dma_free_coherent(dev, size, dma_buf, ring->dma_handle);
+	}
+	kfree(ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	u32 i;
+
+	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+		brcmf_pcie_release_ringbuffer(&devinfo->pdev->dev,
+					      devinfo->shared.commonrings[i]);
+		devinfo->shared.commonrings[i] = NULL;
+	}
+	kfree(devinfo->shared.flowrings);
+	devinfo->shared.flowrings = NULL;
+}
+
+
+static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_ringbuf *ring;
+	struct brcmf_pcie_ringbuf *rings;
+	u32 ring_addr;
+	u32 d2h_w_idx_ptr;
+	u32 d2h_r_idx_ptr;
+	u32 h2d_w_idx_ptr;
+	u32 h2d_r_idx_ptr;
+	u32 addr;
+	u32 ring_mem_ptr;
+	u32 i;
+	u16 max_sub_queues;
+
+	ring_addr = devinfo->shared.ring_info_addr;
+	brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
+
+	addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
+	d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+	addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
+	d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+	addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
+	h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+	addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
+	h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
+	ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
+		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+		if (!ring)
+			goto fail;
+		ring->w_idx_addr = h2d_w_idx_ptr;
+		ring->r_idx_addr = h2d_r_idx_ptr;
+		ring->id = i;
+		devinfo->shared.commonrings[i] = ring;
+
+		h2d_w_idx_ptr += sizeof(u32);
+		h2d_r_idx_ptr += sizeof(u32);
+		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+	}
+
+	for (i = BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	     i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+		if (!ring)
+			goto fail;
+		ring->w_idx_addr = d2h_w_idx_ptr;
+		ring->r_idx_addr = d2h_r_idx_ptr;
+		ring->id = i;
+		devinfo->shared.commonrings[i] = ring;
+
+		d2h_w_idx_ptr += sizeof(u32);
+		d2h_r_idx_ptr += sizeof(u32);
+		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+	}
+
+	addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
+	max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+	devinfo->shared.nrof_flowrings =
+			max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
+			GFP_KERNEL);
+	if (!rings)
+		goto fail;
+
+	brcmf_dbg(PCIE, "Nr of flowrings is %d\n",
+		  devinfo->shared.nrof_flowrings);
+
+	for (i = 0; i < devinfo->shared.nrof_flowrings; i++) {
+		ring = &rings[i];
+		ring->devinfo = devinfo;
+		ring->id = i + BRCMF_NROF_COMMON_MSGRINGS;
+		brcmf_commonring_register_cb(&ring->commonring,
+					     brcmf_pcie_ring_mb_ring_bell,
+					     brcmf_pcie_ring_mb_update_rptr,
+					     brcmf_pcie_ring_mb_update_wptr,
+					     brcmf_pcie_ring_mb_write_rptr,
+					     brcmf_pcie_ring_mb_write_wptr,
+					     ring);
+		ring->w_idx_addr = h2d_w_idx_ptr;
+		ring->r_idx_addr = h2d_r_idx_ptr;
+		h2d_w_idx_ptr += sizeof(u32);
+		h2d_r_idx_ptr += sizeof(u32);
+	}
+	devinfo->shared.flowrings = rings;
+
+	return 0;
+
+fail:
+	brcmf_err("Allocating commonring buffers failed\n");
+	brcmf_pcie_release_ringbuffers(devinfo);
+	return -ENOMEM;
+}
+
+
+static void
+brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->shared.scratch)
+		dma_free_coherent(&devinfo->pdev->dev,
+				  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+				  devinfo->shared.scratch,
+				  devinfo->shared.scratch_dmahandle);
+	if (devinfo->shared.ringupd)
+		dma_free_coherent(&devinfo->pdev->dev,
+				  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+				  devinfo->shared.ringupd,
+				  devinfo->shared.ringupd_dmahandle);
+}
+
+static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	long long address;
+	u32 addr;
+
+	devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev,
+		BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+		&devinfo->shared.scratch_dmahandle, GFP_KERNEL);
+	if (!devinfo->shared.scratch)
+		goto fail;
+
+	memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+	brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
+	address = (long long)(long)devinfo->shared.scratch_dmahandle;
+	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
+	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+
+	devinfo->shared.ringupd = dma_alloc_coherent(&devinfo->pdev->dev,
+		BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+		&devinfo->shared.ringupd_dmahandle, GFP_KERNEL);
+	if (!devinfo->shared.ringupd)
+		goto fail;
+
+	memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+	brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
+	address = (long long)(long)devinfo->shared.ringupd_dmahandle;
+	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET;
+	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+	return 0;
+
+fail:
+	brcmf_err("Allocating scratch buffers failed\n");
+	brcmf_pcie_release_scratchbuffers(devinfo);
+	return -ENOMEM;
+}
+
+
+static void brcmf_pcie_down(struct device *dev)
+{
+}
+
+
+static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
+{
+	return 0;
+}
+
+
+static int brcmf_pcie_tx_ctlpkt(struct device *dev, unsigned char *msg,
+				uint len)
+{
+	return 0;
+}
+
+
+static int brcmf_pcie_rx_ctlpkt(struct device *dev, unsigned char *msg,
+				uint len)
+{
+	return 0;
+}
+
+
+static struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+	.txdata = brcmf_pcie_tx,
+	.stop = brcmf_pcie_down,
+	.txctl = brcmf_pcie_tx_ctlpkt,
+	.rxctl = brcmf_pcie_rx_ctlpkt,
+};
+
+
+static int
+brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
+			       u32 sharedram_addr)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+	u32 version;
+
+	shared = &devinfo->shared;
+	shared->tcm_base_address = sharedram_addr;
+
+	shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
+	version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK;
+	brcmf_dbg(PCIE, "PCIe protocol version %d\n", version);
+	if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
+	    (version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
+		brcmf_err("Unsupported PCIE version %d\n", version);
+		return -EINVAL;
+	}
+	if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
+		brcmf_err("Unsupported legacy TX mode 0x%x\n",
+			  shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
+		return -EINVAL;
+	}
+
+	addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
+	shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
+	if (shared->max_rxbufpost == 0)
+		shared->max_rxbufpost = BRCMF_DEF_MAX_RXBUFPOST;
+
+	addr = sharedram_addr + BRCMF_SHARED_RX_DATAOFFSET_OFFSET;
+	shared->rx_dataoffset = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET;
+	shared->htod_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET;
+	shared->dtoh_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;
+	shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",
+		  shared->max_rxbufpost, shared->rx_dataoffset);
+
+	brcmf_pcie_bus_console_init(devinfo);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
+{
+	char *fw_name;
+	char *nvram_name;
+	uint fw_len, nv_len;
+	char end;
+
+	brcmf_dbg(PCIE, "Enter, chip 0x%04x chiprev %d\n", devinfo->ci->chip,
+		  devinfo->ci->chiprev);
+
+	switch (devinfo->ci->chip) {
+	case BRCM_CC_43602_CHIP_ID:
+		fw_name = BRCMF_PCIE_43602_FW_NAME;
+		nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
+		break;
+	case BRCM_CC_4354_CHIP_ID:
+		fw_name = BRCMF_PCIE_4354_FW_NAME;
+		nvram_name = BRCMF_PCIE_4354_NVRAM_NAME;
+		break;
+	case BRCM_CC_4356_CHIP_ID:
+		fw_name = BRCMF_PCIE_4356_FW_NAME;
+		nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
+		break;
+	case BRCM_CC_43567_CHIP_ID:
+	case BRCM_CC_43569_CHIP_ID:
+	case BRCM_CC_43570_CHIP_ID:
+		fw_name = BRCMF_PCIE_43570_FW_NAME;
+		nvram_name = BRCMF_PCIE_43570_NVRAM_NAME;
+		break;
+	default:
+		brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+		return -ENODEV;
+	}
+
+	fw_len = sizeof(devinfo->fw_name) - 1;
+	nv_len = sizeof(devinfo->nvram_name) - 1;
+	/* check if firmware path is provided by module parameter */
+	if (brcmf_firmware_path[0] != '\0') {
+		strncpy(devinfo->fw_name, brcmf_firmware_path, fw_len);
+		strncpy(devinfo->nvram_name, brcmf_firmware_path, nv_len);
+		fw_len -= strlen(devinfo->fw_name);
+		nv_len -= strlen(devinfo->nvram_name);
+
+		end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+		if (end != '/') {
+			strncat(devinfo->fw_name, "/", fw_len);
+			strncat(devinfo->nvram_name, "/", nv_len);
+			fw_len--;
+			nv_len--;
+		}
+	}
+	strncat(devinfo->fw_name, fw_name, fw_len);
+	strncat(devinfo->nvram_name, nvram_name, nv_len);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+					const struct firmware *fw, void *nvram,
+					u32 nvram_len)
+{
+	u32 sharedram_addr;
+	u32 sharedram_addr_written;
+	u32 loop_counter;
+	int err;
+	u32 address;
+	u32 resetintr;
+
+	devinfo->ringbell = brcmf_pcie_ringbell_v2;
+	devinfo->generic_corerev = BRCMF_PCIE_GENREV2;
+
+	brcmf_dbg(PCIE, "Halt ARM.\n");
+	err = brcmf_pcie_enter_download_state(devinfo);
+	if (err)
+		return err;
+
+	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
+	brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase,
+				  (void *)fw->data, fw->size);
+
+	resetintr = get_unaligned_le32(fw->data);
+	release_firmware(fw);
+
+	/* reset last 4 bytes of RAM address. to be used for shared
+	 * area. This identifies when FW is running
+	 */
+	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
+
+	if (nvram) {
+		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
+		address = devinfo->ci->rambase + devinfo->ci->ramsize -
+			  nvram_len;
+		brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
+		brcmf_fw_nvram_free(nvram);
+	} else {
+		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
+			  devinfo->nvram_name);
+	}
+
+	sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
+						       devinfo->ci->ramsize -
+						       4);
+	brcmf_dbg(PCIE, "Bring ARM in running state\n");
+	err = brcmf_pcie_exit_download_state(devinfo, resetintr);
+	if (err)
+		return err;
+
+	brcmf_dbg(PCIE, "Wait for FW init\n");
+	sharedram_addr = sharedram_addr_written;
+	loop_counter = BRCMF_PCIE_FW_UP_TIMEOUT / 50;
+	while ((sharedram_addr == sharedram_addr_written) && (loop_counter)) {
+		msleep(50);
+		sharedram_addr = brcmf_pcie_read_ram32(devinfo,
+						       devinfo->ci->ramsize -
+						       4);
+		loop_counter--;
+	}
+	if (sharedram_addr == sharedram_addr_written) {
+		brcmf_err("FW failed to initialize\n");
+		return -ENODEV;
+	}
+	brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);
+
+	return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr));
+}
+
+
+static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+	int err;
+	phys_addr_t  bar0_addr, bar1_addr;
+	ulong bar1_size;
+
+	pdev = devinfo->pdev;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		brcmf_err("pci_enable_device failed err=%d\n", err);
+		return err;
+	}
+
+	pci_set_master(pdev);
+
+	/* Bar-0 mapped address */
+	bar0_addr = pci_resource_start(pdev, 0);
+	/* Bar-1 mapped address */
+	bar1_addr = pci_resource_start(pdev, 2);
+	/* read Bar-1 mapped memory range */
+	bar1_size = pci_resource_len(pdev, 2);
+	if ((bar1_size == 0) || (bar1_addr == 0)) {
+		brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
+			  bar1_size, (unsigned long long)bar1_addr);
+		return -EINVAL;
+	}
+
+	devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
+	devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE);
+	devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE;
+
+	if (!devinfo->regs || !devinfo->tcm) {
+		brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
+			  devinfo->tcm);
+		return -EINVAL;
+	}
+	brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
+		  devinfo->regs, (unsigned long long)bar0_addr);
+	brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n",
+		  devinfo->tcm, (unsigned long long)bar1_addr);
+
+	return 0;
+}
+
+
+static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->tcm)
+		iounmap(devinfo->tcm);
+	if (devinfo->regs)
+		iounmap(devinfo->regs);
+
+	pci_disable_device(devinfo->pdev);
+}
+
+
+static int brcmf_pcie_attach_bus(struct device *dev)
+{
+	int ret;
+
+	/* Attach to the common driver interface */
+	ret = brcmf_attach(dev);
+	if (ret) {
+		brcmf_err("brcmf_attach failed\n");
+	} else {
+		ret = brcmf_bus_start(dev);
+		if (ret)
+			brcmf_err("dongle is not responding\n");
+	}
+
+	return ret;
+}
+
+
+static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
+{
+	u32 ret_addr;
+
+	ret_addr = addr & (BRCMF_PCIE_BAR0_REG_SIZE - 1);
+	addr &= ~(BRCMF_PCIE_BAR0_REG_SIZE - 1);
+	pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, addr);
+
+	return ret_addr;
+}
+
+
+static u32 brcmf_pcie_buscore_read32(void *ctx, u32 addr)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+	return brcmf_pcie_read_reg32(devinfo, addr);
+}
+
+
+static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+	brcmf_pcie_write_reg32(devinfo, addr, value);
+}
+
+
+static int brcmf_pcie_buscoreprep(void *ctx)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+	int err;
+
+	err = brcmf_pcie_get_resource(devinfo);
+	if (err == 0) {
+		/* Set CC watchdog to reset all the cores on the chip to bring
+		 * back dongle to a sane state.
+		 */
+		brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
+							    watchdog), 4);
+		msleep(100);
+	}
+
+	return err;
+}
+
+
+static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
+				      u32 rstvec)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	brcmf_pcie_write_tcm32(devinfo, 0, rstvec);
+}
+
+
+static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
+	.prepare = brcmf_pcie_buscoreprep,
+	.exit_dl = brcmf_pcie_buscore_exitdl,
+	.read32 = brcmf_pcie_buscore_read32,
+	.write32 = brcmf_pcie_buscore_write32,
+};
+
+static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw,
+			     void *nvram, u32 nvram_len)
+{
+	struct brcmf_bus *bus = dev_get_drvdata(dev);
+	struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie;
+	struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
+	struct brcmf_commonring **flowrings;
+	int ret;
+	u32 i;
+
+	brcmf_pcie_attach(devinfo);
+
+	ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
+	if (ret)
+		goto fail;
+
+	devinfo->state = BRCMFMAC_PCIE_STATE_UP;
+
+	ret = brcmf_pcie_init_ringbuffers(devinfo);
+	if (ret)
+		goto fail;
+
+	ret = brcmf_pcie_init_scratchbuffers(devinfo);
+	if (ret)
+		goto fail;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	ret = brcmf_pcie_request_irq(devinfo);
+	if (ret)
+		goto fail;
+
+	/* hook the commonrings in the bus structure. */
+	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++)
+		bus->msgbuf->commonrings[i] =
+				&devinfo->shared.commonrings[i]->commonring;
+
+	flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(flowrings),
+			    GFP_KERNEL);
+	if (!flowrings)
+		goto fail;
+
+	for (i = 0; i < devinfo->shared.nrof_flowrings; i++)
+		flowrings[i] = &devinfo->shared.flowrings[i].commonring;
+	bus->msgbuf->flowrings = flowrings;
+
+	bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
+	bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
+	bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings;
+
+	init_waitqueue_head(&devinfo->mbdata_resp_wait);
+
+	brcmf_pcie_intr_enable(devinfo);
+	if (brcmf_pcie_attach_bus(bus->dev) == 0)
+		return;
+
+	brcmf_pcie_bus_console_read(devinfo);
+
+fail:
+	device_release_driver(dev);
+}
+
+static int
+brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int ret;
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_pciedev *pcie_bus_dev;
+	struct brcmf_bus *bus;
+
+	brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
+
+	ret = -ENOMEM;
+	devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+	if (devinfo == NULL)
+		return ret;
+
+	devinfo->pdev = pdev;
+	pcie_bus_dev = NULL;
+	devinfo->ci = brcmf_chip_attach(devinfo, &brcmf_pcie_buscore_ops);
+	if (IS_ERR(devinfo->ci)) {
+		ret = PTR_ERR(devinfo->ci);
+		devinfo->ci = NULL;
+		goto fail;
+	}
+
+	pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
+	if (pcie_bus_dev == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+	if (!bus) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+	bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
+	if (!bus->msgbuf) {
+		ret = -ENOMEM;
+		kfree(bus);
+		goto fail;
+	}
+
+	/* hook it all together. */
+	pcie_bus_dev->devinfo = devinfo;
+	pcie_bus_dev->bus = bus;
+	bus->dev = &pdev->dev;
+	bus->bus_priv.pcie = pcie_bus_dev;
+	bus->ops = &brcmf_pcie_bus_ops;
+	bus->proto_type = BRCMF_PROTO_MSGBUF;
+	bus->chip = devinfo->coreid;
+	dev_set_drvdata(&pdev->dev, bus);
+
+	ret = brcmf_pcie_get_fwnames(devinfo);
+	if (ret)
+		goto fail_bus;
+
+	ret = brcmf_fw_get_firmwares(bus->dev, BRCMF_FW_REQUEST_NVRAM |
+					       BRCMF_FW_REQ_NV_OPTIONAL,
+				     devinfo->fw_name, devinfo->nvram_name,
+				     brcmf_pcie_setup);
+	if (ret == 0)
+		return 0;
+fail_bus:
+	kfree(bus->msgbuf);
+	kfree(bus);
+fail:
+	brcmf_err("failed %x:%x\n", pdev->vendor, pdev->device);
+	brcmf_pcie_release_resource(devinfo);
+	if (devinfo->ci)
+		brcmf_chip_detach(devinfo->ci);
+	kfree(pcie_bus_dev);
+	kfree(devinfo);
+	return ret;
+}
+
+
+static void
+brcmf_pcie_remove(struct pci_dev *pdev)
+{
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_bus *bus;
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	bus = dev_get_drvdata(&pdev->dev);
+	if (bus == NULL)
+		return;
+
+	devinfo = bus->bus_priv.pcie->devinfo;
+
+	devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
+	if (devinfo->ci)
+		brcmf_pcie_intr_disable(devinfo);
+
+	brcmf_detach(&pdev->dev);
+
+	kfree(bus->bus_priv.pcie);
+	kfree(bus->msgbuf->flowrings);
+	kfree(bus->msgbuf);
+	kfree(bus);
+
+	brcmf_pcie_release_irq(devinfo);
+	brcmf_pcie_release_scratchbuffers(devinfo);
+	brcmf_pcie_release_ringbuffers(devinfo);
+	brcmf_pcie_reset_device(devinfo);
+	brcmf_pcie_release_resource(devinfo);
+
+	if (devinfo->ci)
+		brcmf_chip_detach(devinfo->ci);
+
+	kfree(devinfo);
+	dev_set_drvdata(&pdev->dev, NULL);
+}
+
+
+#ifdef CONFIG_PM
+
+
+static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_bus *bus;
+	int err;
+
+	brcmf_dbg(PCIE, "Enter, state=%d, pdev=%p\n", state.event, pdev);
+
+	bus = dev_get_drvdata(&pdev->dev);
+	devinfo = bus->bus_priv.pcie->devinfo;
+
+	brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
+
+	devinfo->mbdata_completed = false;
+	brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
+
+	wait_event_timeout(devinfo->mbdata_resp_wait,
+			   devinfo->mbdata_completed,
+			   msecs_to_jiffies(BRCMF_PCIE_MBDATA_TIMEOUT));
+	if (!devinfo->mbdata_completed) {
+		brcmf_err("Timeout on response for entering D3 substate\n");
+		return -EIO;
+	}
+	brcmf_pcie_release_irq(devinfo);
+
+	err = pci_save_state(pdev);
+	if (err) {
+		brcmf_err("pci_save_state failed, err=%d\n", err);
+		return err;
+	}
+
+	brcmf_chip_detach(devinfo->ci);
+	devinfo->ci = NULL;
+
+	brcmf_pcie_remove(pdev);
+
+	return pci_prepare_to_sleep(pdev);
+}
+
+
+static int brcmf_pcie_resume(struct pci_dev *pdev)
+{
+	int err;
+
+	brcmf_dbg(PCIE, "Enter, pdev=%p\n", pdev);
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		brcmf_err("pci_set_power_state failed, err=%d\n", err);
+		return err;
+	}
+	pci_restore_state(pdev);
+
+	err = brcmf_pcie_probe(pdev, NULL);
+	if (err)
+		brcmf_err("probe after resume failed, err=%d\n", err);
+
+	return err;
+}
+
+
+#endif /* CONFIG_PM */
+
+
+#define BRCMF_PCIE_DEVICE(dev_id)	{ BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
+	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+
+static struct pci_device_id brcmf_pcie_devid_table[] = {
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+	{ /* end: all zeroes */ }
+};
+
+
+MODULE_DEVICE_TABLE(pci, brcmf_pcie_devid_table);
+
+
+static struct pci_driver brcmf_pciedrvr = {
+	.node = {},
+	.name = KBUILD_MODNAME,
+	.id_table = brcmf_pcie_devid_table,
+	.probe = brcmf_pcie_probe,
+	.remove = brcmf_pcie_remove,
+#ifdef CONFIG_PM
+	.suspend = brcmf_pcie_suspend,
+	.resume = brcmf_pcie_resume
+#endif /* CONFIG_PM */
+};
+
+
+void brcmf_pcie_register(void)
+{
+	int err;
+
+	brcmf_dbg(PCIE, "Enter\n");
+	err = pci_register_driver(&brcmf_pciedrvr);
+	if (err)
+		brcmf_err("PCIE driver registration failed, err=%d\n", err);
+}
+
+
+void brcmf_pcie_exit(void)
+{
+	brcmf_dbg(PCIE, "Enter\n");
+	pci_unregister_driver(&brcmf_pciedrvr);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/pcie.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_PCIE_H
+#define BRCMFMAC_PCIE_H
+
+
+struct brcmf_pciedev {
+	struct brcmf_bus *bus;
+	struct brcmf_pciedev_info *devinfo;
+};
+
+
+void brcmf_pcie_exit(void);
+void brcmf_pcie_register(void);
+
+
+#endif /* BRCMFMAC_PCIE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,26 +21,40 @@
 
 #include <brcmu_wifi.h>
 #include "dhd.h"
+#include "dhd_bus.h"
 #include "dhd_dbg.h"
 #include "proto.h"
 #include "bcdc.h"
+#include "msgbuf.h"
 
 
 int brcmf_proto_attach(struct brcmf_pub *drvr)
 {
 	struct brcmf_proto *proto;
 
+	brcmf_dbg(TRACE, "Enter\n");
+
 	proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
 	if (!proto)
 		goto fail;
 
 	drvr->proto = proto;
-	/* BCDC protocol is only protocol supported for the moment */
-	if (brcmf_proto_bcdc_attach(drvr))
-		goto fail;
 
+	if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) {
+		if (brcmf_proto_bcdc_attach(drvr))
+			goto fail;
+	} else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) {
+		if (brcmf_proto_msgbuf_attach(drvr))
+			goto fail;
+	} else {
+		brcmf_err("Unsupported proto type %d\n",
+			  drvr->bus_if->proto_type);
+		goto fail;
+	}
 	if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
-	    (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) {
+	    (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
+	    (proto->configure_addr_mode == NULL) ||
+	    (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
 		brcmf_err("Not all proto handlers have been installed\n");
 		goto fail;
 	}
@@ -54,8 +68,13 @@ fail:
 
 void brcmf_proto_detach(struct brcmf_pub *drvr)
 {
+	brcmf_dbg(TRACE, "Enter\n");
+
 	if (drvr->proto) {
-		brcmf_proto_bcdc_detach(drvr);
+		if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
+			brcmf_proto_bcdc_detach(drvr);
+		else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
+			brcmf_proto_msgbuf_detach(drvr);
 		kfree(drvr->proto);
 		drvr->proto = NULL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/proto.h	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,13 @@
 #ifndef BRCMFMAC_PROTO_H
 #define BRCMFMAC_PROTO_H
 
+
+enum proto_addr_mode {
+	ADDR_INDIRECT	= 0,
+	ADDR_DIRECT
+};
+
+
 struct brcmf_proto {
 	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
 		       struct sk_buff *skb);
@@ -25,6 +32,12 @@ struct brcmf_proto {
 			uint len);
 	int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
 		      struct sk_buff *skb);
+	void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
+				    enum proto_addr_mode addr_mode);
+	void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
+			    u8 peer[ETH_ALEN]);
+	void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
+			      u8 peer[ETH_ALEN]);
 	void *pd;
 };
 
@@ -48,10 +61,26 @@ static inline int brcmf_proto_set_dcmd(s
 	return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
 }
 static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
-				       u8 offset, struct sk_buff *skb)
+				     u8 offset, struct sk_buff *skb)
 {
 	return drvr->proto->txdata(drvr, ifidx, offset, skb);
 }
+static inline void
+brcmf_proto_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				enum proto_addr_mode addr_mode)
+{
+	drvr->proto->configure_addr_mode(drvr, ifidx, addr_mode);
+}
+static inline void
+brcmf_proto_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	drvr->proto->delete_peer(drvr, ifidx, peer);
+}
+static inline void
+brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	drvr->proto->add_tdls_peer(drvr, ifidx, peer);
+}
 
 
 #endif /* BRCMFMAC_PROTO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,8 @@
 #define	_BRCM_SDH_H_
 
 #include <linux/skbuff.h>
+#include <linux/firmware.h>
+#include "firmware.h"
 
 #define SDIO_FUNC_0		0
 #define SDIO_FUNC_1		1
@@ -72,12 +74,12 @@
 #define SBSDIO_SPROM_DATA_HIGH		0x10003
 /* sprom indirect access addr byte 0 */
 #define SBSDIO_SPROM_ADDR_LOW		0x10004
-/* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH		0x10005
-/* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_DATA		0x10006
-/* xtal_pu (gpio) enable */
-#define SBSDIO_CHIP_CTRL_EN		0x10007
+/* gpio select */
+#define SBSDIO_GPIO_SELECT		0x10005
+/* gpio output */
+#define SBSDIO_GPIO_OUT			0x10006
+/* gpio enable */
+#define SBSDIO_GPIO_EN			0x10007
 /* rev < 7, watermark for sdio device */
 #define SBSDIO_WATERMARK		0x10008
 /* control busy signal generation */
@@ -182,6 +184,8 @@ struct brcmf_sdio_dev {
 	uint max_segment_size;
 	uint txglomsz;
 	struct sg_table sgtable;
+	char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+	char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
 };
 
 /* sdio core registers */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/usb.c	2014-08-07 04:53:50.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/usb.c	2014-09-28 21:35:41.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/vmalloc.h>
 
 #include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
 #include <brcmu_wifi.h>
 #include <dhd_bus.h>
 #include <dhd_dbg.h>
@@ -29,32 +30,24 @@
 #include "usb_rdl.h"
 #include "usb.h"
 
-#define IOCTL_RESP_TIMEOUT  2000
+#define IOCTL_RESP_TIMEOUT		2000
 
 #define BRCMF_USB_RESET_GETVER_SPINWAIT	100	/* in unit of ms */
 #define BRCMF_USB_RESET_GETVER_LOOP_CNT	10
 
 #define BRCMF_POSTBOOT_ID		0xA123  /* ID to detect if dongle
 						   has boot up */
-#define BRCMF_USB_NRXQ	50
-#define BRCMF_USB_NTXQ	50
-
-#define CONFIGDESC(usb)         (&((usb)->actconfig)->desc)
-#define IFPTR(usb, idx)         ((usb)->actconfig->interface[(idx)])
-#define IFALTS(usb, idx)        (IFPTR((usb), (idx))->altsetting[0])
-#define IFDESC(usb, idx)        IFALTS((usb), (idx)).desc
-#define IFEPDESC(usb, idx, ep)  (IFALTS((usb), (idx)).endpoint[(ep)]).desc
-
-#define CONTROL_IF              0
-#define BULK_IF                 0
+#define BRCMF_USB_NRXQ			50
+#define BRCMF_USB_NTXQ			50
 
-#define BRCMF_USB_CBCTL_WRITE	0
-#define BRCMF_USB_CBCTL_READ	1
-#define BRCMF_USB_MAX_PKT_SIZE	1600
+#define BRCMF_USB_CBCTL_WRITE		0
+#define BRCMF_USB_CBCTL_READ		1
+#define BRCMF_USB_MAX_PKT_SIZE		1600
 
-#define BRCMF_USB_43143_FW_NAME	"/*(DEBLOBBED)*/"
-#define BRCMF_USB_43236_FW_NAME	"/*(DEBLOBBED)*/"
-#define BRCMF_USB_43242_FW_NAME	"/*(DEBLOBBED)*/"
+#define BRCMF_USB_43143_FW_NAME		"/*(DEBLOBBED)*/"
+#define BRCMF_USB_43236_FW_NAME		"/*(DEBLOBBED)*/"
+#define BRCMF_USB_43242_FW_NAME		"/*(DEBLOBBED)*/"
+#define BRCMF_USB_43569_FW_NAME		"/*(DEBLOBBED)*/"
 
 struct brcmf_usb_image {
 	struct list_head list;
@@ -70,7 +63,7 @@ struct brcmf_usbdev_info {
 	struct list_head rx_postq;
 	struct list_head tx_freeq;
 	struct list_head tx_postq;
-	uint rx_pipe, tx_pipe, rx_pipe2;
+	uint rx_pipe, tx_pipe;
 
 	int rx_low_watermark;
 	int tx_low_watermark;
@@ -97,6 +90,7 @@ struct brcmf_usbdev_info {
 	int ctl_completed;
 	wait_queue_head_t ioctl_resp_wait;
 	ulong ctl_op;
+	u8 ifnum;
 
 	struct urb *bulk_urb; /* used for FW download */
 };
@@ -576,7 +570,6 @@ fail:
 static int brcmf_usb_up(struct device *dev)
 {
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
-	u16 ifnum;
 
 	brcmf_dbg(USB, "Enter\n");
 	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
@@ -589,21 +582,19 @@ static int brcmf_usb_up(struct device *d
 		devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
 		devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
 
-		ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber;
-
 		/* CTL Write */
 		devinfo->ctl_write.bRequestType =
 			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 		devinfo->ctl_write.bRequest = 0;
 		devinfo->ctl_write.wValue = cpu_to_le16(0);
-		devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum);
+		devinfo->ctl_write.wIndex = cpu_to_le16(devinfo->ifnum);
 
 		/* CTL Read */
 		devinfo->ctl_read.bRequestType =
 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 		devinfo->ctl_read.bRequest = 1;
 		devinfo->ctl_read.wValue = cpu_to_le16(0);
-		devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum);
+		devinfo->ctl_read.wIndex = cpu_to_le16(devinfo->ifnum);
 	}
 	brcmf_usb_rx_fill_all(devinfo);
 	return 0;
@@ -642,19 +633,19 @@ brcmf_usb_sync_complete(struct urb *urb)
 	brcmf_usb_ioctl_resp_wake(devinfo);
 }
 
-static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
-			     void *buffer, int buflen)
+static int brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
+			    void *buffer, int buflen)
 {
-	int ret = 0;
+	int ret;
 	char *tmpbuf;
 	u16 size;
 
 	if ((!devinfo) || (devinfo->ctl_urb == NULL))
-		return false;
+		return -EINVAL;
 
 	tmpbuf = kmalloc(buflen, GFP_ATOMIC);
 	if (!tmpbuf)
-		return false;
+		return -ENOMEM;
 
 	size = buflen;
 	devinfo->ctl_urb->transfer_buffer_length = size;
@@ -675,14 +666,16 @@ static bool brcmf_usb_dl_cmd(struct brcm
 	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
 	if (ret < 0) {
 		brcmf_err("usb_submit_urb failed %d\n", ret);
-		kfree(tmpbuf);
-		return false;
+		goto finalize;
 	}
 
-	ret = brcmf_usb_ioctl_resp_wait(devinfo);
-	memcpy(buffer, tmpbuf, buflen);
-	kfree(tmpbuf);
+	if (!brcmf_usb_ioctl_resp_wait(devinfo))
+		ret = -ETIMEDOUT;
+	else
+		memcpy(buffer, tmpbuf, buflen);
 
+finalize:
+	kfree(tmpbuf);
 	return ret;
 }
 
@@ -724,6 +717,7 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_i
 {
 	struct bootrom_id_le id;
 	u32 loop_cnt;
+	int err;
 
 	brcmf_dbg(USB, "Enter\n");
 
@@ -732,7 +726,9 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_i
 		mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
 		loop_cnt++;
 		id.chip = cpu_to_le32(0xDEAD);       /* Get the ID */
-		brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+		err = brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+		if ((err) && (err != -ETIMEDOUT))
+			return err;
 		if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
 			break;
 	} while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
@@ -794,8 +790,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usb
 	}
 
 	/* 1) Prepare USB boot loader for runtime image */
-	brcmf_usb_dl_cmd(devinfo, DL_START, &state,
-			 sizeof(struct rdl_state_le));
+	brcmf_usb_dl_cmd(devinfo, DL_START, &state, sizeof(state));
 
 	rdlstate = le32_to_cpu(state.state);
 	rdlbytes = le32_to_cpu(state.bytes);
@@ -839,10 +834,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usb
 			dlpos += sendlen;
 			sent += sendlen;
 		}
-		if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
-				      sizeof(struct rdl_state_le))) {
-			brcmf_err("DL_GETSTATE Failed xxxx\n");
-			err = -EINVAL;
+		err = brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
+				       sizeof(state));
+		if (err) {
+			brcmf_err("DL_GETSTATE Failed\n");
 			goto fail;
 		}
 
@@ -898,13 +893,12 @@ static int brcmf_usb_dlrun(struct brcmf_
 		return -EINVAL;
 
 	/* Check we are runnable */
-	brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
-		sizeof(struct rdl_state_le));
+	state.state = 0;
+	brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, sizeof(state));
 
 	/* Start the image */
 	if (state.state == cpu_to_le32(DL_RUNNABLE)) {
-		if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state,
-			sizeof(struct rdl_state_le)))
+		if (brcmf_usb_dl_cmd(devinfo, DL_GO, &state, sizeof(state)))
 			return -ENODEV;
 		if (brcmf_usb_resetcfg(devinfo))
 			return -ENODEV;
@@ -920,13 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_
 static bool brcmf_usb_chip_support(int chipid, int chiprev)
 {
 	switch(chipid) {
-	case 43143:
+	case BRCM_CC_43143_CHIP_ID:
 		return true;
-	case 43235:
-	case 43236:
-	case 43238:
+	case BRCM_CC_43235_CHIP_ID:
+	case BRCM_CC_43236_CHIP_ID:
+	case BRCM_CC_43238_CHIP_ID:
 		return (chiprev == 3);
-	case 43242:
+	case BRCM_CC_43242_CHIP_ID:
+		return true;
+	case BRCM_CC_43566_CHIP_ID:
+	case BRCM_CC_43569_CHIP_ID:
 		return true;
 	default:
 		break;
@@ -1020,14 +1017,17 @@ static int check_file(const u8 *headers)
 static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
 {
 	switch (devinfo->bus_pub.devid) {
-	case 43143:
+	case BRCM_CC_43143_CHIP_ID:
 		return BRCMF_USB_43143_FW_NAME;
-	case 43235:
-	case 43236:
-	case 43238:
+	case BRCM_CC_43235_CHIP_ID:
+	case BRCM_CC_43236_CHIP_ID:
+	case BRCM_CC_43238_CHIP_ID:
 		return BRCMF_USB_43236_FW_NAME;
-	case 43242:
+	case BRCM_CC_43242_CHIP_ID:
 		return BRCMF_USB_43242_FW_NAME;
+	case BRCM_CC_43566_CHIP_ID:
+	case BRCM_CC_43569_CHIP_ID:
+		return BRCMF_USB_43569_FW_NAME;
 	default:
 		return NULL;
 	}
@@ -1222,15 +1222,15 @@ brcmf_usb_disconnect_cb(struct brcmf_usb
 static int
 brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	int ep;
-	struct usb_endpoint_descriptor *endpoint;
-	int ret = 0;
 	struct usb_device *usb = interface_to_usbdev(intf);
-	int num_of_eps;
-	u8 endpoint_num;
 	struct brcmf_usbdev_info *devinfo;
+	struct usb_interface_descriptor	*desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int ret = 0;
+	u32 num_of_eps;
+	u8 endpoint_num, ep;
 
-	brcmf_dbg(USB, "Enter\n");
+	brcmf_dbg(USB, "Enter 0x%04x:0x%04x\n", id->idVendor, id->idProduct);
 
 	devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
 	if (devinfo == NULL)
@@ -1238,92 +1238,71 @@ brcmf_usb_probe(struct usb_interface *in
 
 	devinfo->usbdev = usb;
 	devinfo->dev = &usb->dev;
-
 	usb_set_intfdata(intf, devinfo);
 
 	/* Check that the device supports only one configuration */
 	if (usb->descriptor.bNumConfigurations != 1) {
-		ret = -1;
-		goto fail;
-	}
-
-	if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
-		ret = -1;
-		goto fail;
-	}
-
-	/*
-	 * Only the BDC interface configuration is supported:
-	 *	Device class: USB_CLASS_VENDOR_SPEC
-	 *	if0 class: USB_CLASS_VENDOR_SPEC
-	 *	if0/ep0: control
-	 *	if0/ep1: bulk in
-	 *	if0/ep2: bulk out (ok if swapped with bulk in)
-	 */
-	if (CONFIGDESC(usb)->bNumInterfaces != 1) {
-		ret = -1;
+		brcmf_err("Number of configurations: %d not supported\n",
+			  usb->descriptor.bNumConfigurations);
+		ret = -ENODEV;
 		goto fail;
 	}
 
-	/* Check interface */
-	if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
-	    IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
-	    IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
-		brcmf_err("invalid control interface: class %d, subclass %d, proto %d\n",
-			  IFDESC(usb, CONTROL_IF).bInterfaceClass,
-			  IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
-			  IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
-		ret = -1;
+	if ((usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) &&
+	    (usb->descriptor.bDeviceClass != USB_CLASS_MISC) &&
+	    (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS_CONTROLLER)) {
+		brcmf_err("Device class: 0x%x not supported\n",
+			  usb->descriptor.bDeviceClass);
+		ret = -ENODEV;
 		goto fail;
 	}
 
-	/* Check control endpoint */
-	endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		!= USB_ENDPOINT_XFER_INT) {
-		brcmf_err("invalid control endpoint %d\n",
-			  endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-		ret = -1;
+	desc = &intf->altsetting[0].desc;
+	if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+	    (desc->bInterfaceSubClass != 2) ||
+	    (desc->bInterfaceProtocol != 0xff)) {
+		brcmf_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n",
+			  desc->bInterfaceNumber, desc->bInterfaceClass,
+			  desc->bInterfaceSubClass, desc->bInterfaceProtocol);
+		ret = -ENODEV;
 		goto fail;
 	}
 
-	devinfo->rx_pipe = 0;
-	devinfo->rx_pipe2 = 0;
-	devinfo->tx_pipe = 0;
-	num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
-
-	/* Check data endpoints and get pipes */
-	for (ep = 1; ep <= num_of_eps; ep++) {
-		endpoint = &IFEPDESC(usb, BULK_IF, ep);
-		if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
-		    USB_ENDPOINT_XFER_BULK) {
-			brcmf_err("invalid data endpoint %d\n", ep);
-			ret = -1;
-			goto fail;
-		}
-
-		endpoint_num = endpoint->bEndpointAddress &
-			       USB_ENDPOINT_NUMBER_MASK;
-		if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-			== USB_DIR_IN) {
-			if (!devinfo->rx_pipe) {
+	num_of_eps = desc->bNumEndpoints;
+	for (ep = 0; ep < num_of_eps; ep++) {
+		endpoint = &intf->altsetting[0].endpoint[ep].desc;
+		endpoint_num = usb_endpoint_num(endpoint);
+		if (!usb_endpoint_xfer_bulk(endpoint))
+			continue;
+		if (usb_endpoint_dir_in(endpoint)) {
+			if (!devinfo->rx_pipe)
 				devinfo->rx_pipe =
 					usb_rcvbulkpipe(usb, endpoint_num);
-			} else {
-				devinfo->rx_pipe2 =
-					usb_rcvbulkpipe(usb, endpoint_num);
-			}
 		} else {
-			devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num);
+			if (!devinfo->tx_pipe)
+				devinfo->tx_pipe =
+					usb_sndbulkpipe(usb, endpoint_num);
 		}
 	}
+	if (devinfo->rx_pipe == 0) {
+		brcmf_err("No RX (in) Bulk EP found\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+	if (devinfo->tx_pipe == 0) {
+		brcmf_err("No TX (out) Bulk EP found\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	devinfo->ifnum = desc->bInterfaceNumber;
 
 	if (usb->speed == USB_SPEED_SUPER)
-		brcmf_dbg(USB, "Broadcom super speed USB wireless device detected\n");
+		brcmf_dbg(USB, "Broadcom super speed USB WLAN interface detected\n");
 	else if (usb->speed == USB_SPEED_HIGH)
-		brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
+		brcmf_dbg(USB, "Broadcom high speed USB WLAN interface detected\n");
 	else
-		brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
+		brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n");
 
 	ret = brcmf_usb_probe_cb(devinfo);
 	if (ret)
@@ -1333,11 +1312,9 @@ brcmf_usb_probe(struct usb_interface *in
 	return 0;
 
 fail:
-	brcmf_err("failed with errno %d\n", ret);
 	kfree(devinfo);
 	usb_set_intfdata(intf, NULL);
 	return ret;
-
 }
 
 static void
@@ -1382,6 +1359,7 @@ static int brcmf_usb_reset_resume(struct
 {
 	struct usb_device *usb = interface_to_usbdev(intf);
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
 	brcmf_dbg(USB, "Enter\n");
 
 	return brcmf_fw_get_firmwares(&usb->dev, 0,
@@ -1389,19 +1367,17 @@ static int brcmf_usb_reset_resume(struct
 				      brcmf_usb_probe_phase2);
 }
 
-#define BRCMF_USB_VENDOR_ID_BROADCOM	0x0a5c
-#define BRCMF_USB_DEVICE_ID_43143	0xbd1e
-#define BRCMF_USB_DEVICE_ID_43236	0xbd17
-#define BRCMF_USB_DEVICE_ID_43242	0xbd1f
-#define BRCMF_USB_DEVICE_ID_BCMFW	0x0bdc
+#define BRCMF_USB_DEVICE(dev_id)	\
+	{ USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
 
 static struct usb_device_id brcmf_usb_devid_table[] = {
-	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) },
-	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
-	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) },
+	BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
 	/* special entry for device with firmware loaded and running */
-	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
-	{ }
+	BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
+	{ /* end: all zeroes */ }
 };
 
 MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include <brcmu_wifi.h>
+#include "fwil_types.h"
+#include "dhd.h"
+#include "p2p.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
+#include "vendor.h"
+#include "fwil.h"
+
+static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,
+						 struct wireless_dev *wdev,
+						 const void *data, int len)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
+	struct sk_buff *reply;
+	int ret, payload, ret_len;
+	void *dcmd_buf = NULL, *wr_pointer;
+	u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
+
+	brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
+		  cmdhdr->len);
+
+	len -= sizeof(struct brcmf_vndr_dcmd_hdr);
+	ret_len = cmdhdr->len;
+	if (ret_len > 0 || len > 0) {
+		if (len > BRCMF_DCMD_MAXLEN) {
+			brcmf_err("oversize input buffer %d\n", len);
+			len = BRCMF_DCMD_MAXLEN;
+		}
+		if (ret_len > BRCMF_DCMD_MAXLEN) {
+			brcmf_err("oversize return buffer %d\n", ret_len);
+			ret_len = BRCMF_DCMD_MAXLEN;
+		}
+		payload = max(ret_len, len) + 1;
+		dcmd_buf = vzalloc(payload);
+		if (NULL == dcmd_buf)
+			return -ENOMEM;
+
+		memcpy(dcmd_buf, (void *)cmdhdr + cmdhdr->offset, len);
+		*(char *)(dcmd_buf + len)  = '\0';
+	}
+
+	if (cmdhdr->set)
+		ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), cmdhdr->cmd,
+					     dcmd_buf, ret_len);
+	else
+		ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), cmdhdr->cmd,
+					     dcmd_buf, ret_len);
+	if (ret != 0)
+		goto exit;
+
+	wr_pointer = dcmd_buf;
+	while (ret_len > 0) {
+		msglen = ret_len > maxmsglen ? maxmsglen : ret_len;
+		ret_len -= msglen;
+		payload = msglen + sizeof(msglen);
+		reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
+		if (NULL == reply) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		if (nla_put(reply, BRCMF_NLATTR_DATA, msglen, wr_pointer) ||
+		    nla_put_u16(reply, BRCMF_NLATTR_LEN, msglen)) {
+			kfree_skb(reply);
+			ret = -ENOBUFS;
+			break;
+		}
+
+		ret = cfg80211_vendor_cmd_reply(reply);
+		if (ret)
+			break;
+
+		wr_pointer += msglen;
+	}
+
+exit:
+	vfree(dcmd_buf);
+
+	return ret;
+}
+
+const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
+	{
+		{
+			.vendor_id = BROADCOM_OUI,
+			.subcmd = BRCMF_VNDR_CMDS_DCMD
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/vendor.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _vendor_h_
+#define _vendor_h_
+
+#define BROADCOM_OUI	0x001018
+
+enum brcmf_vndr_cmds {
+	BRCMF_VNDR_CMDS_UNSPEC,
+	BRCMF_VNDR_CMDS_DCMD,
+	BRCMF_VNDR_CMDS_LAST
+};
+
+/**
+ * enum brcmf_nlattrs - nl80211 message attributes
+ *
+ * @BRCMF_NLATTR_LEN: message body length
+ * @BRCMF_NLATTR_DATA: message body
+ */
+enum brcmf_nlattrs {
+	BRCMF_NLATTR_UNSPEC,
+
+	BRCMF_NLATTR_LEN,
+	BRCMF_NLATTR_DATA,
+
+	__BRCMF_NLATTR_AFTER_LAST,
+	BRCMF_NLATTR_MAX = __BRCMF_NLATTR_AFTER_LAST - 1
+};
+
+/**
+ * struct brcmf_vndr_dcmd_hdr - message header for cfg80211 vendor command dcmd
+ *				support
+ *
+ * @cmd: common dongle cmd definition
+ * @len: length of expecting return buffer
+ * @offset: offset of data buffer
+ * @set: get or set request(optional)
+ * @magic: magic number for verification
+ */
+struct brcmf_vndr_dcmd_hdr {
+	uint cmd;
+	int len;
+	uint offset;
+	uint set;
+	uint magic;
+};
+
+extern const struct wiphy_vendor_command brcmf_vendor_cmds[];
+
+#endif /* _vendor_h_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/etherdevice.h>
 #include <linux/module.h>
+#include <linux/vmalloc.h>
 #include <net/cfg80211.h>
 #include <net/netlink.h>
 
@@ -32,7 +33,10 @@
 #include "p2p.h"
 #include "btcoex.h"
 #include "wl_cfg80211.h"
+#include "feature.h"
 #include "fwil.h"
+#include "proto.h"
+#include "vendor.h"
 
 #define BRCMF_SCAN_IE_LEN_MAX		2048
 #define BRCMF_PNO_VERSION		2
@@ -100,24 +104,6 @@ static bool check_vif_up(struct brcmf_cf
 	return true;
 }
 
-#define CHAN2G(_channel, _freq, _flags) {			\
-	.band			= IEEE80211_BAND_2GHZ,		\
-	.center_freq		= (_freq),			\
-	.hw_value		= (_channel),			\
-	.flags			= (_flags),			\
-	.max_antenna_gain	= 0,				\
-	.max_power		= 30,				\
-}
-
-#define CHAN5G(_channel, _flags) {				\
-	.band			= IEEE80211_BAND_5GHZ,		\
-	.center_freq		= 5000 + (5 * (_channel)),	\
-	.hw_value		= (_channel),			\
-	.flags			= (_flags),			\
-	.max_antenna_gain	= 0,				\
-	.max_power		= 30,				\
-}
-
 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
 #define RATETAB_ENT(_rateid, _flags) \
 	{                                                               \
@@ -146,58 +132,17 @@ static struct ieee80211_rate __wl_rates[
 #define wl_g_rates		(__wl_rates + 0)
 #define wl_g_rates_size	12
 
-static struct ieee80211_channel __wl_2ghz_channels[] = {
-	CHAN2G(1, 2412, 0),
-	CHAN2G(2, 2417, 0),
-	CHAN2G(3, 2422, 0),
-	CHAN2G(4, 2427, 0),
-	CHAN2G(5, 2432, 0),
-	CHAN2G(6, 2437, 0),
-	CHAN2G(7, 2442, 0),
-	CHAN2G(8, 2447, 0),
-	CHAN2G(9, 2452, 0),
-	CHAN2G(10, 2457, 0),
-	CHAN2G(11, 2462, 0),
-	CHAN2G(12, 2467, 0),
-	CHAN2G(13, 2472, 0),
-	CHAN2G(14, 2484, 0),
-};
-
-static struct ieee80211_channel __wl_5ghz_a_channels[] = {
-	CHAN5G(34, 0), CHAN5G(36, 0),
-	CHAN5G(38, 0), CHAN5G(40, 0),
-	CHAN5G(42, 0), CHAN5G(44, 0),
-	CHAN5G(46, 0), CHAN5G(48, 0),
-	CHAN5G(52, 0), CHAN5G(56, 0),
-	CHAN5G(60, 0), CHAN5G(64, 0),
-	CHAN5G(100, 0), CHAN5G(104, 0),
-	CHAN5G(108, 0), CHAN5G(112, 0),
-	CHAN5G(116, 0), CHAN5G(120, 0),
-	CHAN5G(124, 0), CHAN5G(128, 0),
-	CHAN5G(132, 0), CHAN5G(136, 0),
-	CHAN5G(140, 0), CHAN5G(149, 0),
-	CHAN5G(153, 0), CHAN5G(157, 0),
-	CHAN5G(161, 0), CHAN5G(165, 0),
-	CHAN5G(184, 0), CHAN5G(188, 0),
-	CHAN5G(192, 0), CHAN5G(196, 0),
-	CHAN5G(200, 0), CHAN5G(204, 0),
-	CHAN5G(208, 0), CHAN5G(212, 0),
-	CHAN5G(216, 0),
-};
-
-static struct ieee80211_supported_band __wl_band_2ghz = {
+/* Band templates duplicated per wiphy. The channel info
+ * is filled in after querying the device.
+ */
+static const struct ieee80211_supported_band __wl_band_2ghz = {
 	.band = IEEE80211_BAND_2GHZ,
-	.channels = __wl_2ghz_channels,
-	.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
 	.bitrates = wl_g_rates,
 	.n_bitrates = wl_g_rates_size,
-	.ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true},
 };
 
-static struct ieee80211_supported_band __wl_band_5ghz_a = {
+static const struct ieee80211_supported_band __wl_band_5ghz_a = {
 	.band = IEEE80211_BAND_5GHZ,
-	.channels = __wl_5ghz_a_channels,
-	.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
 	.bitrates = wl_a_rates,
 	.n_bitrates = wl_a_rates_size,
 };
@@ -549,6 +494,25 @@ brcmf_configure_arp_offload(struct brcmf
 	return err;
 }
 
+static void
+brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	ifp = vif->ifp;
+
+	if ((wdev->iftype == NL80211_IFTYPE_ADHOC) ||
+	    (wdev->iftype == NL80211_IFTYPE_AP) ||
+	    (wdev->iftype == NL80211_IFTYPE_P2P_GO))
+		brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+						ADDR_DIRECT);
+	else
+		brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+						ADDR_INDIRECT);
+}
+
 static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
 {
 	enum nl80211_iftype iftype;
@@ -568,6 +532,8 @@ static struct wireless_dev *brcmf_cfg802
 						     u32 *flags,
 						     struct vif_params *params)
 {
+	struct wireless_dev *wdev;
+
 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
 	switch (type) {
 	case NL80211_IFTYPE_ADHOC:
@@ -581,13 +547,22 @@ static struct wireless_dev *brcmf_cfg802
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_P2P_DEVICE:
-		return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
+		wdev = brcmf_p2p_add_vif(wiphy, name, type, flags, params);
+		if (!IS_ERR(wdev))
+			brcmf_cfg80211_update_proto_addr_mode(wdev);
+		return wdev;
 	case NL80211_IFTYPE_UNSPECIFIED:
 	default:
 		return ERR_PTR(-EINVAL);
 	}
 }
 
+static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
+{
+	if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC))
+		brcmf_set_mpc(ifp, mpc);
+}
+
 void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
 {
 	s32 err = 0;
@@ -641,7 +616,7 @@ s32 brcmf_notify_escan_complete(struct b
 			brcmf_err("Scan abort  failed\n");
 	}
 
-	brcmf_set_mpc(ifp, 1);
+	brcmf_scan_config_mpc(ifp, 1);
 
 	/*
 	 * e-scan can be initiated by scheduled scan
@@ -770,6 +745,8 @@ brcmf_cfg80211_change_iface(struct wiphy
 	}
 	ndev->ieee80211_ptr->iftype = type;
 
+	brcmf_cfg80211_update_proto_addr_mode(&vif->wdev);
+
 done:
 	brcmf_dbg(TRACE, "Exit\n");
 
@@ -920,7 +897,7 @@ brcmf_do_escan(struct brcmf_cfg80211_inf
 		brcmf_err("error (%d)\n", err);
 		return err;
 	}
-	brcmf_set_mpc(ifp, 0);
+	brcmf_scan_config_mpc(ifp, 0);
 	results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
 	results->version = 0;
 	results->count = 0;
@@ -928,7 +905,7 @@ brcmf_do_escan(struct brcmf_cfg80211_inf
 
 	err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START);
 	if (err)
-		brcmf_set_mpc(ifp, 1);
+		brcmf_scan_config_mpc(ifp, 1);
 	return err;
 }
 
@@ -1019,7 +996,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
 			brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
 			goto scan_out;
 		}
-		brcmf_set_mpc(ifp, 0);
+		brcmf_scan_config_mpc(ifp, 0);
 		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
 					     &sr->ssid_le, sizeof(sr->ssid_le));
 		if (err) {
@@ -1029,7 +1006,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
 			else
 				brcmf_err("WLC_SCAN error (%d)\n", err);
 
-			brcmf_set_mpc(ifp, 1);
+			brcmf_scan_config_mpc(ifp, 1);
 			goto scan_out;
 		}
 	}
@@ -1331,7 +1308,6 @@ static s32
 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
-	s32 err = 0;
 
 	brcmf_dbg(TRACE, "Enter\n");
 	if (!check_vif_up(ifp->vif))
@@ -1341,7 +1317,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *
 
 	brcmf_dbg(TRACE, "Exit\n");
 
-	return err;
+	return 0;
 }
 
 static s32 brcmf_set_wpa_version(struct net_device *ndev,
@@ -1612,17 +1588,10 @@ static
 enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
 					   enum nl80211_auth_type type)
 {
-	u32 ci;
-	if (type == NL80211_AUTHTYPE_AUTOMATIC) {
-		/* shift to ignore chip revision */
-		ci = brcmf_get_chip_info(ifp) >> 4;
-		switch (ci) {
-		case 43236:
-			brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n");
-			return NL80211_AUTHTYPE_OPEN_SYSTEM;
-		default:
-			break;
-		}
+	if (type == NL80211_AUTHTYPE_AUTOMATIC &&
+	    brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) {
+		brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n");
+		type = NL80211_AUTHTYPE_OPEN_SYSTEM;
 	}
 	return type;
 }
@@ -2388,7 +2357,6 @@ static s32 brcmf_inform_single_bss(struc
 	struct cfg80211_bss *bss;
 	struct ieee80211_supported_band *band;
 	struct brcmu_chan ch;
-	s32 err = 0;
 	u16 channel;
 	u32 freq;
 	u16 notify_capability;
@@ -2438,7 +2406,7 @@ static s32 brcmf_inform_single_bss(struc
 
 	cfg80211_put_bss(wiphy, bss);
 
-	return err;
+	return 0;
 }
 
 static struct brcmf_bss_info_le *
@@ -2690,7 +2658,6 @@ brcmf_cfg80211_escan_handler(struct brcm
 {
 	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	s32 status;
-	s32 err = 0;
 	struct brcmf_escan_result_le *escan_result_le;
 	struct brcmf_bss_info_le *bss_info_le;
 	struct brcmf_bss_info_le *bss = NULL;
@@ -2781,7 +2748,7 @@ brcmf_cfg80211_escan_handler(struct brcm
 				  status);
 	}
 exit:
-	return err;
+	return 0;
 }
 
 static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
@@ -3260,35 +3227,6 @@ static int brcmf_cfg80211_sched_scan_sto
 	return 0;
 }
 
-#ifdef CONFIG_NL80211_TESTMODE
-static int brcmf_cfg80211_testmode(struct wiphy *wiphy,
-				   struct wireless_dev *wdev,
-				   void *data, int len)
-{
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct net_device *ndev = cfg_to_ndev(cfg);
-	struct brcmf_dcmd *dcmd = data;
-	struct sk_buff *reply;
-	int ret;
-
-	brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
-		  dcmd->buf, dcmd->len);
-
-	if (dcmd->set)
-		ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
-					     dcmd->buf, dcmd->len);
-	else
-		ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
-					     dcmd->buf, dcmd->len);
-	if (ret == 0) {
-		reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
-		nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
-		ret = cfg80211_testmode_reply(reply);
-	}
-	return ret;
-}
-#endif
-
 static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
 {
 	s32 err;
@@ -3507,7 +3445,6 @@ static s32
 brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
 		     struct parsed_vndr_ies *vndr_ies)
 {
-	s32 err = 0;
 	struct brcmf_vs_tlv *vndrie;
 	struct brcmf_tlv *ie;
 	struct parsed_vndr_ie_info *parsed_info;
@@ -3560,7 +3497,7 @@ next:
 			ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
 				TLV_HDR_LEN);
 	}
-	return err;
+	return 0;
 }
 
 static u32
@@ -4221,6 +4158,27 @@ static void brcmf_cfg80211_crit_proto_st
 	clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
 }
 
+static s32
+brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,
+			     const struct brcmf_event_msg *e, void *data)
+{
+	switch (e->reason) {
+	case BRCMF_E_REASON_TDLS_PEER_DISCOVERED:
+		brcmf_dbg(TRACE, "TDLS Peer Discovered\n");
+		break;
+	case BRCMF_E_REASON_TDLS_PEER_CONNECTED:
+		brcmf_dbg(TRACE, "TDLS Peer Connected\n");
+		brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+		break;
+	case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:
+		brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+		break;
+	}
+
+	return 0;
+}
+
 static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
 {
 	int ret;
@@ -4307,120 +4265,8 @@ static struct cfg80211_ops wl_cfg80211_o
 	.crit_proto_start = brcmf_cfg80211_crit_proto_start,
 	.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
 	.tdls_oper = brcmf_cfg80211_tdls_oper,
-	CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode)
 };
 
-static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
-{
-	/* scheduled scan settings */
-	wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
-	wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
-	wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
-	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-}
-
-static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
-	{
-		.max = 2,
-		.types = BIT(NL80211_IFTYPE_STATION) |
-			 BIT(NL80211_IFTYPE_ADHOC) |
-			 BIT(NL80211_IFTYPE_AP)
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-			 BIT(NL80211_IFTYPE_P2P_GO)
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
-	}
-};
-static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
-	{
-		 .max_interfaces = BRCMF_IFACE_MAX_CNT,
-		 .num_different_channels = 2,
-		 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
-		 .limits = brcmf_iface_limits
-	}
-};
-
-static const struct ieee80211_txrx_stypes
-brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
-	[NL80211_IFTYPE_STATION] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	},
-	[NL80211_IFTYPE_P2P_CLIENT] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	},
-	[NL80211_IFTYPE_P2P_GO] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
-		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
-		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
-		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
-		      BIT(IEEE80211_STYPE_AUTH >> 4) |
-		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
-		      BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
-	[NL80211_IFTYPE_P2P_DEVICE] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	}
-};
-
-static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
-{
-	struct wiphy *wiphy;
-	s32 err = 0;
-
-	wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
-	if (!wiphy) {
-		brcmf_err("Could not allocate wiphy device\n");
-		return ERR_PTR(-ENOMEM);
-	}
-	set_wiphy_dev(wiphy, phydev);
-	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
-	wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
-	wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
-	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-				 BIT(NL80211_IFTYPE_ADHOC) |
-				 BIT(NL80211_IFTYPE_AP) |
-				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
-				 BIT(NL80211_IFTYPE_P2P_GO) |
-				 BIT(NL80211_IFTYPE_P2P_DEVICE);
-	wiphy->iface_combinations = brcmf_iface_combos;
-	wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
-	wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-	wiphy->cipher_suites = __wl_cipher_suites;
-	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
-	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
-			WIPHY_FLAG_OFFCHAN_TX |
-			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
-			WIPHY_FLAG_SUPPORTS_TDLS;
-	if (!brcmf_roamoff)
-		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
-	wiphy->mgmt_stypes = brcmf_txrx_stypes;
-	wiphy->max_remain_on_channel_duration = 5000;
-	brcmf_wiphy_pno_params(wiphy);
-	brcmf_dbg(INFO, "Registering custom regulatory\n");
-	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
-	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
-	err = wiphy_register(wiphy);
-	if (err < 0) {
-		brcmf_err("Could not register wiphy device (%d)\n", err);
-		wiphy_free(wiphy);
-		return ERR_PTR(err);
-	}
-	return wiphy;
-}
-
 struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
 					   enum nl80211_iftype type,
 					   bool pm_block)
@@ -4650,7 +4496,6 @@ brcmf_bss_connect_done(struct brcmf_cfg8
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
-	s32 err = 0;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
@@ -4676,7 +4521,7 @@ brcmf_bss_connect_done(struct brcmf_cfg8
 			  completed ? "succeeded" : "failed");
 	}
 	brcmf_dbg(TRACE, "Exit\n");
-	return err;
+	return 0;
 }
 
 static s32
@@ -4728,6 +4573,13 @@ brcmf_notify_connect_status(struct brcmf
 	struct ieee80211_channel *chan;
 	s32 err = 0;
 
+	if ((e->event_code == BRCMF_E_DEAUTH) ||
+	    (e->event_code == BRCMF_E_DEAUTH_IND) ||
+	    (e->event_code == BRCMF_E_DISASSOC_IND) ||
+	    ((e->event_code == BRCMF_E_LINK) && (!e->flags))) {
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+	}
+
 	if (brcmf_is_apmode(ifp->vif)) {
 		err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
 	} else if (brcmf_is_linkup(e)) {
@@ -4768,7 +4620,6 @@ brcmf_notify_roaming_status(struct brcmf
 			    const struct brcmf_event_msg *e, void *data)
 {
 	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
-	s32 err = 0;
 	u32 event = e->event_code;
 	u32 status = e->status;
 
@@ -4779,7 +4630,7 @@ brcmf_notify_roaming_status(struct brcmf
 			brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
 	}
 
-	return err;
+	return 0;
 }
 
 static s32
@@ -4966,135 +4817,6 @@ static void init_vif_event(struct brcmf_
 	mutex_init(&event->vif_event_lock);
 }
 
-static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
-{
-	struct brcmf_fil_bwcap_le band_bwcap;
-	u32 val;
-	int err;
-
-	/* verify support for bw_cap command */
-	val = WLC_BAND_5G;
-	err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
-
-	if (!err) {
-		/* only set 2G bandwidth using bw_cap command */
-		band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
-		band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
-		err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
-					       sizeof(band_bwcap));
-	} else {
-		brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
-		val = WLC_N_BW_40ALL;
-		err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
-	}
-	return err;
-}
-
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
-						  struct device *busdev)
-{
-	struct net_device *ndev = drvr->iflist[0]->ndev;
-	struct brcmf_cfg80211_info *cfg;
-	struct wiphy *wiphy;
-	struct brcmf_cfg80211_vif *vif;
-	struct brcmf_if *ifp;
-	s32 err = 0;
-	s32 io_type;
-
-	if (!ndev) {
-		brcmf_err("ndev is invalid\n");
-		return NULL;
-	}
-
-	ifp = netdev_priv(ndev);
-	wiphy = brcmf_setup_wiphy(busdev);
-	if (IS_ERR(wiphy))
-		return NULL;
-
-	cfg = wiphy_priv(wiphy);
-	cfg->wiphy = wiphy;
-	cfg->pub = drvr;
-	init_vif_event(&cfg->vif_event);
-	INIT_LIST_HEAD(&cfg->vif_list);
-
-	vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
-	if (IS_ERR(vif)) {
-		wiphy_free(wiphy);
-		return NULL;
-	}
-
-	vif->ifp = ifp;
-	vif->wdev.netdev = ndev;
-	ndev->ieee80211_ptr = &vif->wdev;
-	SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
-
-	err = wl_init_priv(cfg);
-	if (err) {
-		brcmf_err("Failed to init iwm_priv (%d)\n", err);
-		goto cfg80211_attach_out;
-	}
-	ifp->vif = vif;
-
-	err = brcmf_p2p_attach(cfg);
-	if (err) {
-		brcmf_err("P2P initilisation failed (%d)\n", err);
-		goto cfg80211_p2p_attach_out;
-	}
-	err = brcmf_btcoex_attach(cfg);
-	if (err) {
-		brcmf_err("BT-coex initialisation failed (%d)\n", err);
-		brcmf_p2p_detach(&cfg->p2p);
-		goto cfg80211_p2p_attach_out;
-	}
-
-	/* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
-	 * setup 40MHz in 2GHz band and enable OBSS scanning.
-	 */
-	if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap &
-	    IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-		err = brcmf_enable_bw40_2g(ifp);
-		if (!err)
-			err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
-						      BRCMF_OBSS_COEX_AUTO);
-	}
-
-	err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
-	if (err) {
-		brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
-		wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
-	}
-
-	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
-				    &io_type);
-	if (err) {
-		brcmf_err("Failed to get D11 version (%d)\n", err);
-		goto cfg80211_p2p_attach_out;
-	}
-	cfg->d11inf.io_type = (u8)io_type;
-	brcmu_d11_attach(&cfg->d11inf);
-
-	return cfg;
-
-cfg80211_p2p_attach_out:
-	wl_deinit_priv(cfg);
-
-cfg80211_attach_out:
-	brcmf_free_vif(vif);
-	return NULL;
-}
-
-void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
-{
-	if (!cfg)
-		return;
-
-	WARN_ON(!list_empty(&cfg->vif_list));
-	wiphy_unregister(cfg->wiphy);
-	brcmf_btcoex_detach(cfg);
-	wl_deinit_priv(cfg);
-	wiphy_free(cfg->wiphy);
-}
-
 static s32
 brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
 {
@@ -5187,25 +4909,77 @@ dongle_scantime_out:
 	return err;
 }
 
+/* Filter the list of channels received from firmware counting only
+ * the 20MHz channels. The wiphy band data only needs those which get
+ * flagged to indicate if they can take part in higher bandwidth.
+ */
+static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
+				       struct brcmf_chanspec_list *chlist,
+				       u32 chcnt[])
+{
+	u32 total = le32_to_cpu(chlist->count);
+	struct brcmu_chan ch;
+	int i;
+
+	for (i = 0; i < total; i++) {
+		ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
+		cfg->d11inf.decchspec(&ch);
 
-static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
-				   u32 bw_cap[])
+		/* Firmware gives a ordered list. We skip non-20MHz
+		 * channels is 2G. For 5G we can abort upon reaching
+		 * a non-20MHz channel in the list.
+		 */
+		if (ch.bw != BRCMU_CHAN_BW_20) {
+			if (ch.band == BRCMU_CHAN_BAND_5G)
+				break;
+			else
+				continue;
+		}
+
+		if (ch.band == BRCMU_CHAN_BAND_2G)
+			chcnt[0] += 1;
+		else if (ch.band == BRCMU_CHAN_BAND_5G)
+			chcnt[1] += 1;
+	}
+}
+
+static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
+					   struct brcmu_chan *ch)
+{
+	u32 ht40_flag;
+
+	ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;
+	if (ch->sb == BRCMU_CHAN_SB_U) {
+		if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+			channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+		channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
+	} else {
+		/* It should be one of
+		 * IEEE80211_CHAN_NO_HT40 or
+		 * IEEE80211_CHAN_NO_HT40PLUS
+		 */
+		channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+		if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+			channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
+	}
+}
+
+static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
+				    u32 bw_cap[])
 {
 	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-	struct ieee80211_channel *band_chan_arr;
+	struct ieee80211_supported_band *band;
+	struct ieee80211_channel *channel;
+	struct wiphy *wiphy;
 	struct brcmf_chanspec_list *list;
 	struct brcmu_chan ch;
-	s32 err;
+	int err;
 	u8 *pbuf;
 	u32 i, j;
 	u32 total;
-	enum ieee80211_band band;
-	u32 channel;
-	u32 *n_cnt;
+	u32 chaninfo;
+	u32 chcnt[2] = { 0, 0 };
 	u32 index;
-	u32 ht40_flag;
-	bool update;
-	u32 array_size;
 
 	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
 
@@ -5218,11 +4992,45 @@ static s32 brcmf_construct_reginfo(struc
 				       BRCMF_DCMD_MEDLEN);
 	if (err) {
 		brcmf_err("get chanspecs error (%d)\n", err);
-		goto exit;
+		goto fail_pbuf;
 	}
 
-	__wl_band_2ghz.n_channels = 0;
-	__wl_band_5ghz_a.n_channels = 0;
+	brcmf_count_20mhz_channels(cfg, list, chcnt);
+	wiphy = cfg_to_wiphy(cfg);
+	if (chcnt[0]) {
+		band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
+			       GFP_KERNEL);
+		if (band == NULL) {
+			err = -ENOMEM;
+			goto fail_pbuf;
+		}
+		band->channels = kcalloc(chcnt[0], sizeof(*channel),
+					 GFP_KERNEL);
+		if (band->channels == NULL) {
+			kfree(band);
+			err = -ENOMEM;
+			goto fail_pbuf;
+		}
+		band->n_channels = 0;
+		wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+	}
+	if (chcnt[1]) {
+		band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
+			       GFP_KERNEL);
+		if (band == NULL) {
+			err = -ENOMEM;
+			goto fail_band2g;
+		}
+		band->channels = kcalloc(chcnt[1], sizeof(*channel),
+					 GFP_KERNEL);
+		if (band->channels == NULL) {
+			kfree(band);
+			err = -ENOMEM;
+			goto fail_band2g;
+		}
+		band->n_channels = 0;
+		wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+	}
 
 	total = le32_to_cpu(list->count);
 	for (i = 0; i < total; i++) {
@@ -5230,100 +5038,153 @@ static s32 brcmf_construct_reginfo(struc
 		cfg->d11inf.decchspec(&ch);
 
 		if (ch.band == BRCMU_CHAN_BAND_2G) {
-			band_chan_arr = __wl_2ghz_channels;
-			array_size = ARRAY_SIZE(__wl_2ghz_channels);
-			n_cnt = &__wl_band_2ghz.n_channels;
-			band = IEEE80211_BAND_2GHZ;
+			band = wiphy->bands[IEEE80211_BAND_2GHZ];
 		} else if (ch.band == BRCMU_CHAN_BAND_5G) {
-			band_chan_arr = __wl_5ghz_a_channels;
-			array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
-			n_cnt = &__wl_band_5ghz_a.n_channels;
-			band = IEEE80211_BAND_5GHZ;
+			band = wiphy->bands[IEEE80211_BAND_5GHZ];
 		} else {
 			brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
 			continue;
 		}
-		if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
+		if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
 		    ch.bw == BRCMU_CHAN_BW_40)
 			continue;
-		if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
+		if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&
 		    ch.bw == BRCMU_CHAN_BW_80)
 			continue;
-		update = false;
-		for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
-			if (band_chan_arr[j].hw_value == ch.chnum) {
-				update = true;
+
+		channel = band->channels;
+		index = band->n_channels;
+		for (j = 0; j < band->n_channels; j++) {
+			if (channel[j].hw_value == ch.chnum) {
+				index = j;
 				break;
 			}
 		}
-		if (update)
-			index = j;
-		else
-			index = *n_cnt;
-		if (index <  array_size) {
-			band_chan_arr[index].center_freq =
-				ieee80211_channel_to_frequency(ch.chnum, band);
-			band_chan_arr[index].hw_value = ch.chnum;
+		channel[index].center_freq =
+			ieee80211_channel_to_frequency(ch.chnum, band->band);
+		channel[index].hw_value = ch.chnum;
 
-			/* assuming the chanspecs order is HT20,
-			 * HT40 upper, HT40 lower, and VHT80.
+		/* assuming the chanspecs order is HT20,
+		 * HT40 upper, HT40 lower, and VHT80.
+		 */
+		if (ch.bw == BRCMU_CHAN_BW_80) {
+			channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
+		} else if (ch.bw == BRCMU_CHAN_BW_40) {
+			brcmf_update_bw40_channel_flag(&channel[index], &ch);
+		} else {
+			/* disable other bandwidths for now as mentioned
+			 * order assure they are enabled for subsequent
+			 * chanspecs.
 			 */
-			if (ch.bw == BRCMU_CHAN_BW_80) {
-				band_chan_arr[index].flags &=
-					~IEEE80211_CHAN_NO_80MHZ;
-			} else if (ch.bw == BRCMU_CHAN_BW_40) {
-				ht40_flag = band_chan_arr[index].flags &
-					    IEEE80211_CHAN_NO_HT40;
-				if (ch.sb == BRCMU_CHAN_SB_U) {
-					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
-						band_chan_arr[index].flags &=
-							~IEEE80211_CHAN_NO_HT40;
-					band_chan_arr[index].flags |=
-						IEEE80211_CHAN_NO_HT40PLUS;
-				} else {
-					/* It should be one of
-					 * IEEE80211_CHAN_NO_HT40 or
-					 * IEEE80211_CHAN_NO_HT40PLUS
-					 */
-					band_chan_arr[index].flags &=
-							~IEEE80211_CHAN_NO_HT40;
-					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
-						band_chan_arr[index].flags |=
-						    IEEE80211_CHAN_NO_HT40MINUS;
-				}
-			} else {
-				/* disable other bandwidths for now as mentioned
-				 * order assure they are enabled for subsequent
-				 * chanspecs.
-				 */
-				band_chan_arr[index].flags =
-						IEEE80211_CHAN_NO_HT40 |
-						IEEE80211_CHAN_NO_80MHZ;
-				ch.bw = BRCMU_CHAN_BW_20;
-				cfg->d11inf.encchspec(&ch);
-				channel = ch.chspec;
-				err = brcmf_fil_bsscfg_int_get(ifp,
-							       "per_chan_info",
-							       &channel);
-				if (!err) {
-					if (channel & WL_CHAN_RADAR)
-						band_chan_arr[index].flags |=
-							(IEEE80211_CHAN_RADAR |
-							IEEE80211_CHAN_NO_IR);
-					if (channel & WL_CHAN_PASSIVE)
-						band_chan_arr[index].flags |=
-						    IEEE80211_CHAN_NO_IR;
-				}
+			channel[index].flags = IEEE80211_CHAN_NO_HT40 |
+					       IEEE80211_CHAN_NO_80MHZ;
+			ch.bw = BRCMU_CHAN_BW_20;
+			cfg->d11inf.encchspec(&ch);
+			chaninfo = ch.chspec;
+			err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info",
+						       &chaninfo);
+			if (!err) {
+				if (chaninfo & WL_CHAN_RADAR)
+					channel[index].flags |=
+						(IEEE80211_CHAN_RADAR |
+						 IEEE80211_CHAN_NO_IR);
+				if (chaninfo & WL_CHAN_PASSIVE)
+					channel[index].flags |=
+						IEEE80211_CHAN_NO_IR;
 			}
-			if (!update)
-				(*n_cnt)++;
 		}
+		if (index == band->n_channels)
+			band->n_channels++;
 	}
-exit:
+	kfree(pbuf);
+	return 0;
+
+fail_band2g:
+	kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+	kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+	wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+fail_pbuf:
 	kfree(pbuf);
 	return err;
 }
 
+static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+	struct ieee80211_supported_band *band;
+	struct brcmf_fil_bwcap_le band_bwcap;
+	struct brcmf_chanspec_list *list;
+	u8 *pbuf;
+	u32 val;
+	int err;
+	struct brcmu_chan ch;
+	u32 num_chan;
+	int i, j;
+
+	/* verify support for bw_cap command */
+	val = WLC_BAND_5G;
+	err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
+
+	if (!err) {
+		/* only set 2G bandwidth using bw_cap command */
+		band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
+		band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
+		err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
+					       sizeof(band_bwcap));
+	} else {
+		brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
+		val = WLC_N_BW_40ALL;
+		err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
+	}
+
+	if (!err) {
+		/* update channel info in 2G band */
+		pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+
+		if (pbuf == NULL)
+			return -ENOMEM;
+
+		ch.band = BRCMU_CHAN_BAND_2G;
+		ch.bw = BRCMU_CHAN_BW_40;
+		ch.sb = BRCMU_CHAN_SB_NONE;
+		ch.chnum = 0;
+		cfg->d11inf.encchspec(&ch);
+
+		/* pass encoded chanspec in query */
+		*(__le16 *)pbuf = cpu_to_le16(ch.chspec);
+
+		err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
+					       BRCMF_DCMD_MEDLEN);
+		if (err) {
+			brcmf_err("get chanspecs error (%d)\n", err);
+			kfree(pbuf);
+			return err;
+		}
+
+		band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
+		list = (struct brcmf_chanspec_list *)pbuf;
+		num_chan = le32_to_cpu(list->count);
+		for (i = 0; i < num_chan; i++) {
+			ch.chspec = (u16)le32_to_cpu(list->element[i]);
+			cfg->d11inf.decchspec(&ch);
+			if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))
+				continue;
+			if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
+				continue;
+			for (j = 0; j < band->n_channels; j++) {
+				if (band->channels[j].hw_value == ch.chnum)
+					break;
+			}
+			if (WARN_ON(j == band->n_channels))
+				continue;
+
+			brcmf_update_bw40_channel_flag(&band->channels[j], &ch);
+		}
+		kfree(pbuf);
+	}
+	return err;
+}
+
 static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
 {
 	u32 band, mimo_bwcap;
@@ -5414,44 +5275,19 @@ static void brcmf_update_vht_cap(struct
 	band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
 }
 
-static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
+static int brcmf_setup_wiphybands(struct wiphy *wiphy)
 {
+	struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
 	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-	struct wiphy *wiphy;
-	s32 phy_list;
-	u32 band_list[3];
 	u32 nmode = 0;
 	u32 vhtmode = 0;
-	u32 bw_cap[2] = { 0, 0 };
+	u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
 	u32 rxchain;
 	u32 nchain;
-	s8 phy;
-	s32 err;
-	u32 nband;
+	int err;
 	s32 i;
-	struct ieee80211_supported_band *bands[2] = { NULL, NULL };
 	struct ieee80211_supported_band *band;
 
-	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
-				     &phy_list, sizeof(phy_list));
-	if (err) {
-		brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
-		return err;
-	}
-
-	phy = ((char *)&phy_list)[0];
-	brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
-
-
-	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
-				     &band_list, sizeof(band_list));
-	if (err) {
-		brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
-		return err;
-	}
-	brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
-		  band_list[0], band_list[1], band_list[2]);
-
 	(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
 	err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
 	if (err) {
@@ -5473,44 +5309,129 @@ static s32 brcmf_update_wiphybands(struc
 	}
 	brcmf_dbg(INFO, "nchain=%d\n", nchain);
 
-	err = brcmf_construct_reginfo(cfg, bw_cap);
+	err = brcmf_construct_chaninfo(cfg, bw_cap);
 	if (err) {
-		brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
+		brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
 		return err;
 	}
 
-	nband = band_list[0];
-
-	for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
-		band = NULL;
-		if ((band_list[i] == WLC_BAND_5G) &&
-		    (__wl_band_5ghz_a.n_channels > 0))
-			band = &__wl_band_5ghz_a;
-		else if ((band_list[i] == WLC_BAND_2G) &&
-			 (__wl_band_2ghz.n_channels > 0))
-			band = &__wl_band_2ghz;
-		else
+	wiphy = cfg_to_wiphy(cfg);
+	for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
+		band = wiphy->bands[i];
+		if (band == NULL)
 			continue;
 
 		if (nmode)
 			brcmf_update_ht_cap(band, bw_cap, nchain);
 		if (vhtmode)
 			brcmf_update_vht_cap(band, bw_cap, nchain);
-		bands[band->band] = band;
 	}
 
-	wiphy = cfg_to_wiphy(cfg);
-	wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
-	wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
-	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
-
-	return err;
+	return 0;
 }
 
+static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION) |
+			 BIT(NL80211_IFTYPE_ADHOC) |
+			 BIT(NL80211_IFTYPE_AP)
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+			 BIT(NL80211_IFTYPE_P2P_GO)
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+	}
+};
+static struct ieee80211_iface_combination brcmf_iface_combos[] = {
+	{
+		 .max_interfaces = BRCMF_IFACE_MAX_CNT,
+		 .num_different_channels = 1,
+		 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
+		 .limits = brcmf_iface_limits
+	}
+};
 
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
+static const struct ieee80211_txrx_stypes
+brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_STATION] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_GO] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+		      BIT(IEEE80211_STYPE_AUTH >> 4) |
+		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+		      BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+	[NL80211_IFTYPE_P2P_DEVICE] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	}
+};
+
+static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
-	return brcmf_update_wiphybands(cfg);
+	/* scheduled scan settings */
+	wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
+	wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+	wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+}
+
+static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+	struct ieee80211_iface_combination ifc_combo;
+	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+	wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+	wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				 BIT(NL80211_IFTYPE_ADHOC) |
+				 BIT(NL80211_IFTYPE_AP) |
+				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
+				 BIT(NL80211_IFTYPE_P2P_GO) |
+				 BIT(NL80211_IFTYPE_P2P_DEVICE);
+	/* need VSDB firmware feature for concurrent channels */
+	ifc_combo = brcmf_iface_combos[0];
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+		ifc_combo.num_different_channels = 2;
+	wiphy->iface_combinations = kmemdup(&ifc_combo,
+					    sizeof(ifc_combo),
+					    GFP_KERNEL);
+	wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+	wiphy->cipher_suites = __wl_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
+			WIPHY_FLAG_OFFCHAN_TX |
+			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+			WIPHY_FLAG_SUPPORTS_TDLS;
+	if (!brcmf_roamoff)
+		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	wiphy->mgmt_stypes = brcmf_txrx_stypes;
+	wiphy->max_remain_on_channel_duration = 5000;
+	brcmf_wiphy_pno_params(wiphy);
+
+	/* vendor commands/events support */
+	wiphy->vendor_commands = brcmf_vendor_cmds;
+	wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
+
+	return brcmf_setup_wiphybands(wiphy);
 }
 
 static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
@@ -5548,9 +5469,6 @@ static s32 brcmf_config_dongle(struct br
 					  NULL, NULL);
 	if (err)
 		goto default_conf_out;
-	err = brcmf_dongle_probecap(cfg);
-	if (err)
-		goto default_conf_out;
 
 	brcmf_configure_arp_offload(ifp, true);
 
@@ -5625,16 +5543,15 @@ enum nl80211_iftype brcmf_cfg80211_get_i
 	return wdev->iftype;
 }
 
-u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state)
 {
 	struct brcmf_cfg80211_vif *vif;
-	bool result = 0;
 
 	list_for_each_entry(vif, &cfg->vif_list, list) {
 		if (test_bit(state, &vif->sme_state))
-			result++;
+			return true;
 	}
-	return result;
+	return false;
 }
 
 static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,
@@ -5679,3 +5596,153 @@ int brcmf_cfg80211_wait_vif_event_timeou
 				  vif_event_equals(event, action), timeout);
 }
 
+static void brcmf_free_wiphy(struct wiphy *wiphy)
+{
+	kfree(wiphy->iface_combinations);
+	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+	}
+	if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+		kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels);
+		kfree(wiphy->bands[IEEE80211_BAND_5GHZ]);
+	}
+	wiphy_free(wiphy);
+}
+
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+						  struct device *busdev)
+{
+	struct net_device *ndev = drvr->iflist[0]->ndev;
+	struct brcmf_cfg80211_info *cfg;
+	struct wiphy *wiphy;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+	s32 err = 0;
+	s32 io_type;
+	u16 *cap = NULL;
+
+	if (!ndev) {
+		brcmf_err("ndev is invalid\n");
+		return NULL;
+	}
+
+	ifp = netdev_priv(ndev);
+	wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
+	if (!wiphy) {
+		brcmf_err("Could not allocate wiphy device\n");
+		return NULL;
+	}
+	set_wiphy_dev(wiphy, busdev);
+
+	cfg = wiphy_priv(wiphy);
+	cfg->wiphy = wiphy;
+	cfg->pub = drvr;
+	init_vif_event(&cfg->vif_event);
+	INIT_LIST_HEAD(&cfg->vif_list);
+
+	vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
+	if (IS_ERR(vif))
+		goto wiphy_out;
+
+	vif->ifp = ifp;
+	vif->wdev.netdev = ndev;
+	ndev->ieee80211_ptr = &vif->wdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
+
+	err = wl_init_priv(cfg);
+	if (err) {
+		brcmf_err("Failed to init iwm_priv (%d)\n", err);
+		brcmf_free_vif(vif);
+		goto wiphy_out;
+	}
+	ifp->vif = vif;
+
+	/* determine d11 io type before wiphy setup */
+	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
+	if (err) {
+		brcmf_err("Failed to get D11 version (%d)\n", err);
+		goto priv_out;
+	}
+	cfg->d11inf.io_type = (u8)io_type;
+	brcmu_d11_attach(&cfg->d11inf);
+
+	err = brcmf_setup_wiphy(wiphy, ifp);
+	if (err < 0)
+		goto priv_out;
+
+	brcmf_dbg(INFO, "Registering custom regulatory\n");
+	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
+
+	/* firmware defaults to 40MHz disabled in 2G band. We signal
+	 * cfg80211 here that we do and have it decide we can enable
+	 * it. But first check if device does support 2G operation.
+	 */
+	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+		cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap;
+		*cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+	err = wiphy_register(wiphy);
+	if (err < 0) {
+		brcmf_err("Could not register wiphy device (%d)\n", err);
+		goto priv_out;
+	}
+
+	/* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
+	 * setup 40MHz in 2GHz band and enable OBSS scanning.
+	 */
+	if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
+		err = brcmf_enable_bw40_2g(cfg);
+		if (!err)
+			err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
+						      BRCMF_OBSS_COEX_AUTO);
+		else
+			*cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+
+	err = brcmf_p2p_attach(cfg);
+	if (err) {
+		brcmf_err("P2P initilisation failed (%d)\n", err);
+		goto wiphy_unreg_out;
+	}
+	err = brcmf_btcoex_attach(cfg);
+	if (err) {
+		brcmf_err("BT-coex initialisation failed (%d)\n", err);
+		brcmf_p2p_detach(&cfg->p2p);
+		goto wiphy_unreg_out;
+	}
+
+	err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
+	if (err) {
+		brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
+		wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
+	} else {
+		brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
+				    brcmf_notify_tdls_peer_event);
+	}
+
+	return cfg;
+
+wiphy_unreg_out:
+	wiphy_unregister(cfg->wiphy);
+priv_out:
+	wl_deinit_priv(cfg);
+	brcmf_free_vif(vif);
+wiphy_out:
+	brcmf_free_wiphy(wiphy);
+	return NULL;
+}
+
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
+{
+	if (!cfg)
+		return;
+
+	WARN_ON(!list_empty(&cfg->vif_list));
+	wiphy_unregister(cfg->wiphy);
+	brcmf_btcoex_detach(cfg);
+	brcmf_p2p_detach(&cfg->p2p);
+	wl_deinit_priv(cfg);
+	brcmf_free_wiphy(cfg->wiphy);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -477,7 +477,7 @@ const struct brcmf_tlv *
 brcmf_parse_tlvs(const void *buf, int buflen, uint key);
 u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
 			struct ieee80211_channel *ch);
-u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state);
 void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
 				  struct brcmf_cfg80211_vif *vif);
 bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c
 	return err;
 }
 
-static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
-{
-	uint unit;
-	unit = wlc->pub->unit;
-
-	if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
-		/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
-		wlc->band->antgain = 8;
-	} else if (wlc->band->antgain == -1) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
-			  " srom, using 2dB\n", unit, __func__);
-		wlc->band->antgain = 8;
-	} else {
-		s8 gain, fract;
-		/* Older sroms specified gain in whole dbm only.  In order
-		 * be able to specify qdbm granularity and remain backward
-		 * compatible the whole dbms are now encoded in only
-		 * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
-		 * 6 bit signed number ranges from -32 - 31.
-		 *
-		 * Examples:
-		 * 0x1 = 1 db,
-		 * 0xc1 = 1.75 db (1 + 3 quarters),
-		 * 0x3f = -1 (-1 + 0 quarters),
-		 * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
-		 * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
-		 */
-		gain = wlc->band->antgain & 0x3f;
-		gain <<= 2;	/* Sign extend */
-		gain >>= 2;
-		fract = (wlc->band->antgain & 0xc0) >> 6;
-		wlc->band->antgain = 4 * gain + fract;
-	}
-}
-
 static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
 {
 	int aa;
@@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(
 	else
 		wlc->band->antgain = sprom->antenna_gain.a0;
 
-	brcms_c_attach_antgain_init(wlc);
-
 	return true;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c	2014-09-28 17:29:07.000000000 -0400
@@ -1538,11 +1538,7 @@ static s8
 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
 				 u8 rate)
 {
-	s8 offset = 0;
-
-	if (!pi->user_txpwr_at_rfport)
-		return offset;
-	return offset;
+	return 0;
 }
 
 void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c	2014-09-28 17:29:07.000000000 -0400
@@ -22916,7 +22916,6 @@ static void wlc_phy_rssi_cal_nphy_rev2(s
 		break;
 	default:
 		return;
-		break;
 	}
 
 	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,32 +17,67 @@
 #ifndef	_BRCM_HW_IDS_H_
 #define	_BRCM_HW_IDS_H_
 
-#define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
+#include <linux/pci_ids.h>
+#include <linux/mmc/sdio_ids.h>
+
+#define BRCM_USB_VENDOR_ID_BROADCOM	0x0a5c
+#define BRCM_PCIE_VENDOR_ID_BROADCOM	PCI_VENDOR_ID_BROADCOM
+#define BRCM_SDIO_VENDOR_ID_BROADCOM	SDIO_VENDOR_ID_BROADCOM
+
+/* Chipcommon Core Chip IDs */
+#define BRCM_CC_43143_CHIP_ID		43143
+#define BRCM_CC_43235_CHIP_ID		43235
+#define BRCM_CC_43236_CHIP_ID		43236
+#define BRCM_CC_43238_CHIP_ID		43238
+#define BRCM_CC_43241_CHIP_ID		0x4324
+#define BRCM_CC_43242_CHIP_ID		43242
+#define BRCM_CC_4329_CHIP_ID		0x4329
+#define BRCM_CC_4330_CHIP_ID		0x4330
+#define BRCM_CC_4334_CHIP_ID		0x4334
+#define BRCM_CC_43362_CHIP_ID		43362
+#define BRCM_CC_4335_CHIP_ID		0x4335
+#define BRCM_CC_4339_CHIP_ID		0x4339
+#define BRCM_CC_4354_CHIP_ID		0x4354
+#define BRCM_CC_4356_CHIP_ID		0x4356
+#define BRCM_CC_43566_CHIP_ID		43566
+#define BRCM_CC_43567_CHIP_ID		43567
+#define BRCM_CC_43569_CHIP_ID		43569
+#define BRCM_CC_43570_CHIP_ID		43570
+#define BRCM_CC_43602_CHIP_ID		43602
 
+/* SDIO Device IDs */
+#define BRCM_SDIO_43143_DEVICE_ID	BRCM_CC_43143_CHIP_ID
+#define BRCM_SDIO_43241_DEVICE_ID	BRCM_CC_43241_CHIP_ID
+#define BRCM_SDIO_4329_DEVICE_ID	BRCM_CC_4329_CHIP_ID
+#define BRCM_SDIO_4330_DEVICE_ID	BRCM_CC_4330_CHIP_ID
+#define BRCM_SDIO_4334_DEVICE_ID	BRCM_CC_4334_CHIP_ID
+#define BRCM_SDIO_43362_DEVICE_ID	BRCM_CC_43362_CHIP_ID
+#define BRCM_SDIO_4335_4339_DEVICE_ID	BRCM_CC_4335_CHIP_ID
+#define BRCM_SDIO_4354_DEVICE_ID	BRCM_CC_4354_CHIP_ID
+
+/* USB Device IDs */
+#define BRCM_USB_43143_DEVICE_ID	0xbd1e
+#define BRCM_USB_43236_DEVICE_ID	0xbd17
+#define BRCM_USB_43242_DEVICE_ID	0xbd1f
+#define BRCM_USB_43569_DEVICE_ID	0xbd27
+#define BRCM_USB_BCMFW_DEVICE_ID	0x0bdc
+
+/* PCIE Device IDs */
+#define BRCM_PCIE_4354_DEVICE_ID	0x43df
+#define BRCM_PCIE_4356_DEVICE_ID	0x43ec
+#define BRCM_PCIE_43567_DEVICE_ID	0x43d3
+#define BRCM_PCIE_43570_DEVICE_ID	0x43d9
+#define BRCM_PCIE_43602_DEVICE_ID	0x43ba
+
+/* brcmsmac IDs */
+#define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
 #define BCM43224_D11N_ID	0x4353	/* 43224 802.11n dualband device */
 #define BCM43224_D11N_ID_VEN1	0x0576	/* Vendor specific 43224 802.11n db */
-
 #define BCM43225_D11N2G_ID	0x4357	/* 43225 802.11n 2.4GHz device */
-
 #define BCM43236_D11N_ID	0x4346	/* 43236 802.11n dualband device */
 #define BCM43236_D11N2G_ID	0x4347	/* 43236 802.11n 2.4GHz device */
 
-/* Chipcommon Core Chip IDs */
 #define BCM4313_CHIP_ID		0x4313
-#define BCM43143_CHIP_ID	43143
 #define BCM43224_CHIP_ID	43224
-#define BCM43225_CHIP_ID	43225
-#define BCM43235_CHIP_ID	43235
-#define BCM43236_CHIP_ID	43236
-#define BCM43238_CHIP_ID	43238
-#define BCM43241_CHIP_ID	0x4324
-#define BCM4329_CHIP_ID		0x4329
-#define BCM4330_CHIP_ID		0x4330
-#define BCM4331_CHIP_ID		0x4331
-#define BCM4334_CHIP_ID		0x4334
-#define BCM4335_CHIP_ID		0x4335
-#define BCM43362_CHIP_ID	43362
-#define BCM4339_CHIP_ID		0x4339
-#define BCM4354_CHIP_ID		0x4354
 
 #endif				/* _BRCM_HW_IDS_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/brcm80211/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/brcm80211/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -27,10 +27,17 @@ config BRCMFMAC
 	  one of the bus interface support. If you choose to build a module,
 	  it'll be called brcmfmac.ko.
 
+config BRCMFMAC_PROTO_BCDC
+	bool
+
+config BRCMFMAC_PROTO_MSGBUF
+	bool
+
 config BRCMFMAC_SDIO
 	bool "SDIO bus interface support for FullMAC driver"
 	depends on (MMC = y || MMC = BRCMFMAC)
 	depends on BRCMFMAC
+	select BRCMFMAC_PROTO_BCDC
 	select FW_LOADER
 	default y
 	---help---
@@ -42,12 +49,25 @@ config BRCMFMAC_USB
 	bool "USB bus interface support for FullMAC driver"
 	depends on (USB = y || USB = BRCMFMAC)
 	depends on BRCMFMAC
+	select BRCMFMAC_PROTO_BCDC
 	select FW_LOADER
 	---help---
 	  This option enables the USB bus interface support for Broadcom
 	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
 	  use the driver for an USB wireless card.
 
+config BRCMFMAC_PCIE
+	bool "PCIE bus interface support for FullMAC driver"
+	depends on BRCMFMAC
+	depends on PCI
+	depends on HAS_DMA
+	select BRCMFMAC_PROTO_MSGBUF
+	select FW_LOADER
+	---help---
+	  This option enables the PCIE bus interface support for Broadcom
+	  IEEE802.11ac embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for an PCIE wireless card.
+
 config BRCM_TRACING
 	bool "Broadcom device tracing"
 	depends on BRCMSMAC || BRCMFMAC
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/cw1200/fwio.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/fwio.c
--- linux-libre-3.16-gnu/drivers/net/wireless/cw1200/fwio.c	2014-08-07 04:55:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/fwio.c	2014-09-28 21:37:51.000000000 -0400
@@ -290,7 +290,6 @@ static int config_reg_write(struct cw120
 	case HIF_8601_SILICON:
 	default:
 		return cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val);
-		break;
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/cw1200/scan.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/scan.c
--- linux-libre-3.16-gnu/drivers/net/wireless/cw1200/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,9 +53,10 @@ static int cw1200_scan_start(struct cw12
 
 int cw1200_hw_scan(struct ieee80211_hw *hw,
 		   struct ieee80211_vif *vif,
-		   struct cfg80211_scan_request *req)
+		   struct ieee80211_scan_request *hw_req)
 {
 	struct cw1200_common *priv = hw->priv;
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct wsm_template_frame frame = {
 		.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
 	};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/cw1200/scan.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/scan.h
--- linux-libre-3.16-gnu/drivers/net/wireless/cw1200/scan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/scan.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@ struct cw1200_scan {
 
 int cw1200_hw_scan(struct ieee80211_hw *hw,
 		   struct ieee80211_vif *vif,
-		   struct cfg80211_scan_request *req);
+		   struct ieee80211_scan_request *hw_req);
 void cw1200_scan_work(struct work_struct *work);
 void cw1200_scan_timeout(struct work_struct *work);
 void cw1200_clear_recent_scan_work(struct work_struct *work);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/cw1200/sta.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/sta.c
--- linux-libre-3.16-gnu/drivers/net/wireless/cw1200/sta.c	2014-08-07 04:55:48.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/cw1200/sta.c	2014-09-28 21:37:53.000000000 -0400
@@ -2289,7 +2289,6 @@ static int cw1200_upload_null(struct cw1
 
 static int cw1200_upload_qosnull(struct cw1200_common *priv)
 {
-	int ret = 0;
 	/* TODO:  This needs to be implemented
 
 	struct wsm_template_frame frame = {
@@ -2306,7 +2305,7 @@ static int cw1200_upload_qosnull(struct
 	dev_kfree_skb(frame.skb);
 
 	*/
-	return ret;
+	return 0;
 }
 
 static int cw1200_enable_beaconing(struct cw1200_common *priv,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/hostap/hostap_pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/hostap/hostap_pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/hostap/hostap_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/hostap/hostap_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@ struct hostap_pci_priv {
 /* FIX: do we need mb/wmb/rmb with memory operations? */
 
 
-static DEFINE_PCI_DEVICE_TABLE(prism2_pci_id_table) = {
+static const struct pci_device_id prism2_pci_id_table[] = {
 	/* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
 	{ 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
 	/* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/hostap/hostap_plx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/hostap/hostap_plx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/hostap/hostap_plx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/hostap/hostap_plx.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,7 @@ struct hostap_plx_priv {
 
 #define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID }
 
-static DEFINE_PCI_DEVICE_TABLE(prism2_plx_id_table) = {
+static const struct pci_device_id prism2_plx_id_table[] = {
 	PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
 	PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
 	PLXDEV(0x126c, 0x8030, "Nortel emobility"),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/ipw2100.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/ipw2100.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2014-08-07 04:54:12.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2014-09-28 21:35:55.000000000 -0400
@@ -3449,8 +3449,9 @@ static int ipw2100_msg_allocate(struct i
 		return -ENOMEM;
 
 	for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
-		v = pci_alloc_consistent(priv->pci_dev,
-					 sizeof(struct ipw2100_cmd_header), &p);
+		v = pci_zalloc_consistent(priv->pci_dev,
+					  sizeof(struct ipw2100_cmd_header),
+					  &p);
 		if (!v) {
 			printk(KERN_ERR DRV_NAME ": "
 			       "%s: PCI alloc failed for msg "
@@ -3459,8 +3460,6 @@ static int ipw2100_msg_allocate(struct i
 			break;
 		}
 
-		memset(v, 0, sizeof(struct ipw2100_cmd_header));
-
 		priv->msg_buffers[i].type = COMMAND;
 		priv->msg_buffers[i].info.c_struct.cmd =
 		    (struct ipw2100_cmd_header *)v;
@@ -4336,16 +4335,12 @@ static int status_queue_allocate(struct
 	IPW_DEBUG_INFO("enter\n");
 
 	q->size = entries * sizeof(struct ipw2100_status);
-	q->drv =
-	    (struct ipw2100_status *)pci_alloc_consistent(priv->pci_dev,
-							  q->size, &q->nic);
+	q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
 	if (!q->drv) {
 		IPW_DEBUG_WARNING("Can not allocate status queue.\n");
 		return -ENOMEM;
 	}
 
-	memset(q->drv, 0, q->size);
-
 	IPW_DEBUG_INFO("exit\n");
 
 	return 0;
@@ -4374,13 +4369,12 @@ static int bd_queue_allocate(struct ipw2
 
 	q->entries = entries;
 	q->size = entries * sizeof(struct ipw2100_bd);
-	q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic);
+	q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
 	if (!q->drv) {
 		IPW_DEBUG_INFO
 		    ("can't allocate shared memory for buffer descriptors\n");
 		return -ENOMEM;
 	}
-	memset(q->drv, 0, q->size);
 
 	IPW_DEBUG_INFO("exit\n");
 
@@ -6511,7 +6505,7 @@ static void ipw2100_shutdown(struct pci_
 
 #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
 
-static DEFINE_PCI_DEVICE_TABLE(ipw2100_pci_id_table) = {
+static const struct pci_device_id ipw2100_pci_id_table[] = {
 	IPW2100_DEV_ID(0x2520),	/* IN 2100A mPCI 3A */
 	IPW2100_DEV_ID(0x2521),	/* IN 2100A mPCI 3B */
 	IPW2100_DEV_ID(0x2524),	/* IN 2100A mPCI 3B */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/ipw2200.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/ipw2200.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2014-08-07 04:54:19.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2014-09-28 21:36:02.000000000 -0400
@@ -9853,6 +9853,7 @@ static int ipw_wx_get_wireless_mode(stru
 		strncpy(extra, "unknown", MAX_WX_STRING);
 		break;
 	}
+	extra[MAX_WX_STRING - 1] = '\0';
 
 	IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
 
@@ -11542,7 +11543,7 @@ out:
 }
 
 /* PCI driver stuff */
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
 	{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0},
 	{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0},
 	{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/libipw_module.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/libipw_module.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ipw2x00/libipw_module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ipw2x00/libipw_module.c	2014-09-28 17:29:07.000000000 -0400
@@ -100,8 +100,7 @@ static inline void libipw_networks_free(
 	int i;
 
 	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
-		if (ieee->networks[i]->ibss_dfs)
-			kfree(ieee->networks[i]->ibss_dfs);
+		kfree(ieee->networks[i]->ibss_dfs);
 		kfree(ieee->networks[i]);
 	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/3945.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/3945.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/3945.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/3945.c	2014-09-28 17:29:07.000000000 -0400
@@ -2728,7 +2728,7 @@ static struct il_cfg il3945_abg_cfg = {
 	},
 };
 
-DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = {
+const struct pci_device_id il3945_hw_card_ids[] = {
 	{IL_PCI_DEVICE(0x4222, 0x1005, il3945_bg_cfg)},
 	{IL_PCI_DEVICE(0x4222, 0x1034, il3945_bg_cfg)},
 	{IL_PCI_DEVICE(0x4222, 0x1044, il3945_bg_cfg)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/4965-mac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/4965-mac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2014-08-07 04:54:30.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2014-09-28 21:36:16.000000000 -0400
@@ -6800,7 +6800,7 @@ il4965_txq_set_sched(struct il_priv *il,
  *****************************************************************************/
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = {
+static const struct pci_device_id il4965_hw_card_ids[] = {
 	{IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
 	{IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
 	{0}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/common.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/common.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -1572,8 +1572,9 @@ il_scan_initiate(struct il_priv *il, str
 
 int
 il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-	       struct cfg80211_scan_request *req)
+	       struct ieee80211_scan_request *hw_req)
 {
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct il_priv *il = hw->priv;
 	int ret;
 
@@ -2979,7 +2980,8 @@ il_tx_queue_alloc(struct il_priv *il, st
 	/* Driver ilate data, only for Tx (not command) queues,
 	 * not shared with device. */
 	if (id != il->cmd_queue) {
-		txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(struct skb *),
+		txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX,
+				    sizeof(struct sk_buff *),
 				    GFP_KERNEL);
 		if (!txq->skbs) {
 			IL_ERR("Fail to alloc skbs\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/common.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/common.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlegacy/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlegacy/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -1787,7 +1787,7 @@ int il_scan_cancel(struct il_priv *il);
 int il_scan_cancel_timeout(struct il_priv *il, unsigned long ms);
 void il_force_scan_end(struct il_priv *il);
 int il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		   struct cfg80211_scan_request *req);
+		   struct ieee80211_scan_request *hw_req);
 void il_internal_short_hw_scan(struct il_priv *il);
 int il_force_reset(struct il_priv *il, bool external);
 u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -1495,9 +1495,10 @@ static int iwlagn_mac_change_interface(s
 
 static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
-			      struct cfg80211_scan_request *req)
+			      struct ieee80211_scan_request *hw_req)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+	struct cfg80211_scan_request *req = &hw_req->req;
 	int ret;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/power.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/power.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/power.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,6 +40,10 @@
 #include "commands.h"
 #include "power.h"
 
+static bool force_cam = true;
+module_param(force_cam, bool, 0644);
+MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)");
+
 /*
  * Setting power level allows the card to go to sleep when not busy.
  *
@@ -288,6 +292,11 @@ static void iwl_power_build_cmd(struct i
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
 	int dtimper;
 
+	if (force_cam) {
+		iwl_power_sleep_cam_cmd(priv, cmd);
+		return;
+	}
+
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
 	if (priv->wowlan)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/rxon.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/rxon.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/dvm/rxon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/dvm/rxon.c	2014-09-28 17:29:07.000000000 -0400
@@ -1068,6 +1068,13 @@ int iwlagn_commit_rxon(struct iwl_priv *
 	/* recalculate basic rates */
 	iwl_calc_basic_rates(priv, ctx);
 
+	/*
+	 * force CTS-to-self frames protection if RTS-CTS is not preferred
+	 * one aggregation protection method
+	 */
+	if (!priv->hw_params.use_rts_for_aggregation)
+		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+
 	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
 	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
 		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -1473,6 +1480,11 @@ void iwlagn_bss_info_changed(struct ieee
 	else
 		ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 
+	if (bss_conf->use_cts_prot)
+		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+
 	memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
 
 	if (vif->type == NL80211_IFTYPE_AP ||
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-7000.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-7000.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-7000.c	2014-08-07 04:54:46.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-7000.c	2014-09-28 21:36:36.000000000 -0400
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX	9
-#define IWL3160_UCODE_API_MAX	9
+#define IWL7260_UCODE_API_MAX	10
+#define IWL3160_UCODE_API_MAX	10
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK	9
@@ -83,6 +83,8 @@
 #define IWL7260_TX_POWER_VERSION	0xffff /* meaningless */
 #define IWL3160_NVM_VERSION		0x709
 #define IWL3160_TX_POWER_VERSION	0xffff /* meaningless */
+#define IWL3165_NVM_VERSION		0x709
+#define IWL3165_TX_POWER_VERSION	0xffff /* meaningless */
 #define IWL7265_NVM_VERSION		0x0a1d
 #define IWL7265_TX_POWER_VERSION	0xffff /* meaningless */
 
@@ -92,6 +94,9 @@
 #define IWL3160_FW_PRE "/*(DEBLOBBED)*/"
 #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE /*(DEBLOBBED)*/
 
+#define IWL3165_FW_PRE "/*(DEBLOBBED)*/"
+#define IWL3165_MODULE_FIRMWARE(api) IWL3165_FW_PRE /*(DEBLOBBED)*/
+
 #define IWL7265_FW_PRE "/*(DEBLOBBED)*/"
 #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE /*(DEBLOBBED)*/
 
@@ -213,6 +218,16 @@ static const struct iwl_pwr_tx_backoff i
 	{0},
 };
 
+const struct iwl_cfg iwl3165_2ac_cfg = {
+	.name = "Intel(R) Dual Band Wireless AC 3165",
+	.fw_name_pre = IWL3165_FW_PRE,
+	IWL_DEVICE_7000,
+	.ht_params = &iwl7000_ht_params,
+	.nvm_ver = IWL3165_NVM_VERSION,
+	.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
+	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
+};
+
 const struct iwl_cfg iwl7265_2ac_cfg = {
 	.name = "Intel(R) Dual Band Wireless AC 7265",
 	.fw_name_pre = IWL7265_FW_PRE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-8000.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-8000.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-8000.c	2014-08-07 04:54:49.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-8000.c	2014-09-28 21:36:38.000000000 -0400
@@ -67,7 +67,7 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX	8
+#define IWL8000_UCODE_API_MAX	10
 
 /* Oldest version we won't warn about */
 #define IWL8000_UCODE_API_OK	8
@@ -85,6 +85,9 @@
 #define NVM_HW_SECTION_NUM_FAMILY_8000		10
 #define DEFAULT_NVM_FILE_FAMILY_8000		"/*(DEBLOBBED)*/"
 
+/* Max SDIO RX aggregation size of the ADDBA request/response */
+#define MAX_RX_AGG_SIZE_8260_SDIO	28
+
 static const struct iwl_base_params iwl8000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
@@ -119,10 +122,9 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
 	.ht_params = &iwl8000_ht_params,
 	.nvm_ver = IWL8000_NVM_VERSION,
 	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-	.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
 };
 
-const struct iwl_cfg iwl8260_n_cfg = {
+const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
 	.name = "Intel(R) Dual Band Wireless-AC 8260",
 	.fw_name_pre = IWL8000_FW_PRE,
 	IWL_DEVICE_8000,
@@ -130,6 +132,7 @@ const struct iwl_cfg iwl8260_n_cfg = {
 	.nvm_ver = IWL8000_NVM_VERSION,
 	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
 	.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
+	.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
 };
 
 /*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-config.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-config.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-config.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-config.h	2014-09-28 17:29:07.000000000 -0400
@@ -120,6 +120,8 @@ enum iwl_led_mode {
 #define IWL_LONG_WD_TIMEOUT	10000
 #define IWL_MAX_WD_TIMEOUT	120000
 
+#define IWL_DEFAULT_MAX_TX_POWER 22
+
 /* Antenna presence definitions */
 #define	ANT_NONE	0x0
 #define	ANT_A		BIT(0)
@@ -240,6 +242,7 @@ struct iwl_pwr_tx_backoff {
  * @d0i3: device uses d0i3 instead of d3
  * @nvm_hw_section_num: the ID of the HW NVM section
  * @pwr_tx_backoffs: translation table between power limits and backoffs
+ * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -276,6 +279,7 @@ struct iwl_cfg {
 	const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
 	bool no_power_up_nic_in_init;
 	const char *default_nvm_file;
+	unsigned int max_rx_agg_size;
 };
 
 /*
@@ -333,11 +337,12 @@ extern const struct iwl_cfg iwl7260_n_cf
 extern const struct iwl_cfg iwl3160_2ac_cfg;
 extern const struct iwl_cfg iwl3160_2n_cfg;
 extern const struct iwl_cfg iwl3160_n_cfg;
+extern const struct iwl_cfg iwl3165_2ac_cfg;
 extern const struct iwl_cfg iwl7265_2ac_cfg;
 extern const struct iwl_cfg iwl7265_2n_cfg;
 extern const struct iwl_cfg iwl7265_n_cfg;
 extern const struct iwl_cfg iwl8260_2ac_cfg;
-extern const struct iwl_cfg iwl8260_n_cfg;
+extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-drv.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-drv.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-drv.c	2014-08-07 04:54:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-drv.c	2014-09-28 21:36:23.000000000 -0400
@@ -155,6 +155,8 @@ static struct iwlwifi_opmode_table {
 	[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
 };
 
+#define IWL_DEFAULT_SCAN_CHANNELS 40
+
 /*
  * struct fw_sec: Just for the image parsing proccess.
  * For the fw storage we are using struct fw_desc.
@@ -565,6 +567,8 @@ static int iwl_parse_tlv_firmware(struct
 	}
 
 	drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+	memcpy(drv->fw.human_readable, ucode->human_readable,
+	       sizeof(drv->fw.human_readable));
 	build = le32_to_cpu(ucode->build);
 
 	if (build)
@@ -819,6 +823,12 @@ static int iwl_parse_tlv_firmware(struct
 			if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len))
 				goto invalid_tlv_len;
 			break;
+		case IWL_UCODE_TLV_N_SCAN_CHANNELS:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			capa->n_scan_channels =
+				le32_to_cpup((__le32 *)tlv_data);
+			break;
 		default:
 			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
 			break;
@@ -973,6 +983,7 @@ static void iwl_req_fw_callback(const st
 	fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
 	fw->ucode_capa.standard_phy_calibration_size =
 			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+	fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
 
 	if (!api_ok)
 		api_ok = api_max;
@@ -1394,3 +1405,7 @@ module_param_named(power_level, iwlwifi_
 		int, S_IRUGO);
 MODULE_PARM_DESC(power_level,
 		 "default power save level (range from 1 - 5, default: 1)");
+
+module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
+MODULE_PARM_DESC(fw_monitor,
+		 "firmware monitor - to debug FW (default: false - needs lots of memory)");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c	2014-09-28 17:29:07.000000000 -0400
@@ -779,7 +779,6 @@ void iwl_init_ht_hw_capab(const struct i
 	if (cfg->ht_params->ht40_bands & BIT(band)) {
 		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
-		ht_info->mcs.rx_mask[4] = 0x01;
 		max_bit_rate = MAX_BIT_RATE_40_MHZ;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h	2014-09-28 17:29:07.000000000 -0400
@@ -70,16 +70,24 @@
 /**
  * enum iwl_fw_error_dump_type - types of data in the dump file
  * @IWL_FW_ERROR_DUMP_SRAM:
- * @IWL_FW_ERROR_DUMP_REG:
+ * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
  * @IWL_FW_ERROR_DUMP_RXF:
  * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
  *	&struct iwl_fw_error_dump_txcmd packets
+ * @IWL_FW_ERROR_DUMP_DEV_FW_INFO:  struct %iwl_fw_error_dump_info
+ *	info on the device / firmware.
+ * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
+ * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
+ *	sections like this in a single file.
  */
 enum iwl_fw_error_dump_type {
 	IWL_FW_ERROR_DUMP_SRAM = 0,
-	IWL_FW_ERROR_DUMP_REG = 1,
+	IWL_FW_ERROR_DUMP_CSR = 1,
 	IWL_FW_ERROR_DUMP_RXF = 2,
 	IWL_FW_ERROR_DUMP_TXCMD = 3,
+	IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
+	IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
+	IWL_FW_ERROR_DUMP_PRPH = 6,
 
 	IWL_FW_ERROR_DUMP_MAX,
 };
@@ -87,8 +95,8 @@ enum iwl_fw_error_dump_type {
 /**
  * struct iwl_fw_error_dump_data - data for one type
  * @type: %enum iwl_fw_error_dump_type
- * @len: the length starting from %data - must be a multiplier of 4.
- * @data: the data itself padded to be a multiplier of 4.
+ * @len: the length starting from %data
+ * @data: the data itself
  */
 struct iwl_fw_error_dump_data {
 	__le32 type;
@@ -120,13 +128,60 @@ struct iwl_fw_error_dump_txcmd {
 	u8 data[];
 } __packed;
 
+enum iwl_fw_error_dump_family {
+	IWL_FW_ERROR_DUMP_FAMILY_7 = 7,
+	IWL_FW_ERROR_DUMP_FAMILY_8 = 8,
+};
+
 /**
- * iwl_mvm_fw_error_next_data - advance fw error dump data pointer
+ * struct iwl_fw_error_dump_info - info on the device / firmware
+ * @device_family: the family of the device (7 / 8)
+ * @hw_step: the step of the device
+ * @fw_human_readable: human readable FW version
+ * @dev_human_readable: name of the device
+ * @bus_human_readable: name of the bus used
+ */
+struct iwl_fw_error_dump_info {
+	__le32 device_family;
+	__le32 hw_step;
+	u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
+	u8 dev_human_readable[64];
+	u8 bus_human_readable[8];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_fw_mon - FW monitor data
+ * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
+ * @fw_mon_base_ptr: base pointer of the data
+ * @fw_mon_cycle_cnt: number of wrap arounds
+ * @reserved: for future use
+ * @data: captured data
+ */
+struct iwl_fw_error_dump_fw_mon {
+	__le32 fw_mon_wr_ptr;
+	__le32 fw_mon_base_ptr;
+	__le32 fw_mon_cycle_cnt;
+	__le32 reserved[3];
+	u8 data[];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_prph - periphery registers data
+ * @prph_start: address of the first register in this chunk
+ * @data: the content of the registers
+ */
+struct iwl_fw_error_dump_prph {
+	__le32 prph_start;
+	__le32 data[];
+};
+
+/**
+ * iwl_fw_error_next_data - advance fw error dump data pointer
  * @data: previous data block
  * Returns: next data block
  */
 static inline struct iwl_fw_error_dump_data *
-iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data)
+iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
 {
 	return (void *)(data->data + le32_to_cpu(data->len));
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw-file.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw-file.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw-file.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw-file.h	2014-09-28 17:29:07.000000000 -0400
@@ -128,6 +128,7 @@ enum iwl_ucode_tlv_type {
 	IWL_UCODE_TLV_CSCHEME		= 28,
 	IWL_UCODE_TLV_API_CHANGES_SET	= 29,
 	IWL_UCODE_TLV_ENABLED_CAPABILITIES	= 30,
+	IWL_UCODE_TLV_N_SCAN_CHANNELS		= 31,
 };
 
 struct iwl_ucode_tlv {
@@ -136,7 +137,8 @@ struct iwl_ucode_tlv {
 	u8 data[0];
 };
 
-#define IWL_TLV_UCODE_MAGIC	0x0a4c5749
+#define IWL_TLV_UCODE_MAGIC		0x0a4c5749
+#define FW_VER_HUMAN_READABLE_SZ	64
 
 struct iwl_tlv_ucode_header {
 	/*
@@ -147,7 +149,7 @@ struct iwl_tlv_ucode_header {
 	 */
 	__le32 zero;
 	__le32 magic;
-	u8 human_readable[64];
+	u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
 	__le32 ver;		/* major/minor/API/serial */
 	__le32 build;
 	__le64 ignore;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-fw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-fw.h	2014-09-28 17:29:07.000000000 -0400
@@ -65,6 +65,8 @@
 #include <linux/types.h>
 #include <net/mac80211.h>
 
+#include "iwl-fw-file.h"
+
 /**
  * enum iwl_ucode_tlv_flag - ucode API flags
  * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
@@ -118,11 +120,19 @@ enum iwl_ucode_tlv_flag {
 /**
  * enum iwl_ucode_tlv_api - ucode api
  * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
+ * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
  * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
+ * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
+ * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
  */
 enum iwl_ucode_tlv_api {
 	IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID	= BIT(0),
+	IWL_UCODE_TLV_CAPA_EXTENDED_BEACON	= BIT(1),
+	IWL_UCODE_TLV_API_BT_COEX_SPLIT         = BIT(3),
 	IWL_UCODE_TLV_API_CSA_FLOW		= BIT(4),
+	IWL_UCODE_TLV_API_DISABLE_STA_TX	= BIT(5),
+	IWL_UCODE_TLV_API_LMAC_SCAN		= BIT(6),
 };
 
 /**
@@ -179,6 +189,7 @@ enum iwl_ucode_sec {
 
 struct iwl_ucode_capabilities {
 	u32 max_probe_length;
+	u32 n_scan_channels;
 	u32 standard_phy_calibration_size;
 	u32 flags;
 	u32 api[IWL_API_ARRAY_SIZE];
@@ -312,6 +323,7 @@ struct iwl_fw {
 	bool mvm_fw;
 
 	struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
+	u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
 };
 
 #endif  /* __iwl_fw_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-modparams.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-modparams.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-modparams.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-modparams.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,10 +99,11 @@ enum iwl_disable_11n {
  * @wd_disable: disable stuck queue check, default = 1
  * @bt_coex_active: enable bt coex, default = true
  * @led_mode: system default, default = 0
- * @power_save: disable power save, default = false
+ * @power_save: enable power save, default = false
  * @power_level: power level, default = 1
  * @debug_level: levels are IWL_DL_*
  * @ant_coupling: antenna coupling in dB, default = 0
+ * @fw_monitor: allow to use firmware monitor
  */
 struct iwl_mod_params {
 	int sw_crypto;
@@ -120,6 +121,7 @@ struct iwl_mod_params {
 	int ant_coupling;
 	char *nvm_file;
 	bool uapsd_disable;
+	bool fw_monitor;
 };
 
 #endif /* #__iwl_modparams_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,6 +63,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/etherdevice.h>
+#include <linux/pci.h>
 #include "iwl-drv.h"
 #include "iwl-modparams.h"
 #include "iwl-nvm-parse.h"
@@ -87,8 +88,10 @@ enum wkp_nvm_offsets {
 
 enum family_8000_nvm_offsets {
 	/* NVM HW-Section offset (in words) definitions */
-	HW_ADDR0_FAMILY_8000 = 0x12,
-	HW_ADDR1_FAMILY_8000 = 0x16,
+	HW_ADDR0_WFPM_FAMILY_8000 = 0x12,
+	HW_ADDR1_WFPM_FAMILY_8000 = 0x16,
+	HW_ADDR0_PCIE_FAMILY_8000 = 0x8A,
+	HW_ADDR1_PCIE_FAMILY_8000 = 0x8E,
 	MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
 
 	/* NVM SW-Section offset (in words) definitions */
@@ -143,8 +146,6 @@ static const u8 iwl_nvm_channels_family_
 #define LAST_2GHZ_HT_PLUS		9
 #define LAST_5GHZ_HT			161
 
-#define DEFAULT_MAX_TX_POWER 16
-
 /* rate data (static) */
 static struct ieee80211_rate iwl_cfg80211_rates[] = {
 	{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
@@ -174,7 +175,9 @@ static struct ieee80211_rate iwl_cfg8021
  * @NVM_CHANNEL_IBSS: usable as an IBSS channel
  * @NVM_CHANNEL_ACTIVE: active scanning allowed
  * @NVM_CHANNEL_RADAR: radar detection required
- * @NVM_CHANNEL_DFS: dynamic freq selection candidate
+ * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
+ * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
+ *	on same channel on 2.4 or same UNII band on 5.2
  * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
  * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
  * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
@@ -185,7 +188,8 @@ enum iwl_nvm_channel_flags {
 	NVM_CHANNEL_IBSS = BIT(1),
 	NVM_CHANNEL_ACTIVE = BIT(3),
 	NVM_CHANNEL_RADAR = BIT(4),
-	NVM_CHANNEL_DFS = BIT(7),
+	NVM_CHANNEL_INDOOR_ONLY = BIT(5),
+	NVM_CHANNEL_GO_CONCURRENT = BIT(6),
 	NVM_CHANNEL_WIDE = BIT(8),
 	NVM_CHANNEL_40MHZ = BIT(9),
 	NVM_CHANNEL_80MHZ = BIT(10),
@@ -273,16 +277,26 @@ static int iwl_init_channel_map(struct d
 		if (ch_flags & NVM_CHANNEL_RADAR)
 			channel->flags |= IEEE80211_CHAN_RADAR;
 
+		if (ch_flags & NVM_CHANNEL_INDOOR_ONLY)
+			channel->flags |= IEEE80211_CHAN_INDOOR_ONLY;
+
+		/* Set the GO concurrent flag only in case that NO_IR is set.
+		 * Otherwise it is meaningless
+		 */
+		if ((ch_flags & NVM_CHANNEL_GO_CONCURRENT) &&
+		    (channel->flags & IEEE80211_CHAN_NO_IR))
+			channel->flags |= IEEE80211_CHAN_GO_CONCURRENT;
+
 		/* Initialize regulatory-based run-time data */
 
 		/*
 		 * Default value - highest tx power value.  max_power
 		 * is not used in mvm, and is used for backwards compatibility
 		 */
-		channel->max_power = DEFAULT_MAX_TX_POWER;
+		channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
 		is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
 		IWL_DEBUG_EEPROM(dev,
-				 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
+				 "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
 				 channel->hw_value,
 				 is_5ghz ? "5.2" : "2.4",
 				 CHECK_AND_PRINT_I(VALID),
@@ -290,7 +304,8 @@ static int iwl_init_channel_map(struct d
 				 CHECK_AND_PRINT_I(ACTIVE),
 				 CHECK_AND_PRINT_I(RADAR),
 				 CHECK_AND_PRINT_I(WIDE),
-				 CHECK_AND_PRINT_I(DFS),
+				 CHECK_AND_PRINT_I(INDOOR_ONLY),
+				 CHECK_AND_PRINT_I(GO_CONCURRENT),
 				 ch_flags,
 				 channel->max_power,
 				 ((ch_flags & NVM_CHANNEL_IBSS) &&
@@ -462,7 +477,8 @@ static void iwl_set_hw_address(const str
 	data->hw_addr[5] = hw_addr[4];
 }
 
-static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
+static void iwl_set_hw_address_family_8000(struct device *dev,
+					   const struct iwl_cfg *cfg,
 					   struct iwl_nvm_data *data,
 					   const __le16 *mac_override,
 					   const __le16 *nvm_hw)
@@ -481,20 +497,64 @@ static void iwl_set_hw_address_family_80
 		data->hw_addr[4] = hw_addr[5];
 		data->hw_addr[5] = hw_addr[4];
 
-		if (is_valid_ether_addr(hw_addr))
+		if (is_valid_ether_addr(data->hw_addr))
 			return;
+
+		IWL_ERR_DEV(dev,
+			    "mac address from nvm override section is not valid\n");
 	}
 
-	/* take the MAC address from the OTP */
-	hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
-	data->hw_addr[0] = hw_addr[3];
-	data->hw_addr[1] = hw_addr[2];
-	data->hw_addr[2] = hw_addr[1];
-	data->hw_addr[3] = hw_addr[0];
+	if (nvm_hw) {
+		/* read the MAC address from OTP */
+		if (!dev_is_pci(dev) || (data->nvm_version < 0xE08)) {
+			/* read the mac address from the WFPM location */
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR0_WFPM_FAMILY_8000);
+			data->hw_addr[0] = hw_addr[3];
+			data->hw_addr[1] = hw_addr[2];
+			data->hw_addr[2] = hw_addr[1];
+			data->hw_addr[3] = hw_addr[0];
 
-	hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
-	data->hw_addr[4] = hw_addr[1];
-	data->hw_addr[5] = hw_addr[0];
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR1_WFPM_FAMILY_8000);
+			data->hw_addr[4] = hw_addr[1];
+			data->hw_addr[5] = hw_addr[0];
+		} else if ((data->nvm_version >= 0xE08) &&
+			   (data->nvm_version < 0xE0B)) {
+			/* read "reverse order"  from the PCIe location */
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR0_PCIE_FAMILY_8000);
+			data->hw_addr[5] = hw_addr[2];
+			data->hw_addr[4] = hw_addr[1];
+			data->hw_addr[3] = hw_addr[0];
+
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR1_PCIE_FAMILY_8000);
+			data->hw_addr[2] = hw_addr[3];
+			data->hw_addr[1] = hw_addr[2];
+			data->hw_addr[0] = hw_addr[1];
+		} else {
+			/* read from the PCIe location */
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR0_PCIE_FAMILY_8000);
+			data->hw_addr[5] = hw_addr[0];
+			data->hw_addr[4] = hw_addr[1];
+			data->hw_addr[3] = hw_addr[2];
+
+			hw_addr = (const u8 *)(nvm_hw +
+					       HW_ADDR1_PCIE_FAMILY_8000);
+			data->hw_addr[2] = hw_addr[1];
+			data->hw_addr[1] = hw_addr[2];
+			data->hw_addr[0] = hw_addr[3];
+		}
+		if (!is_valid_ether_addr(data->hw_addr))
+			IWL_ERR_DEV(dev,
+				    "mac address from hw section is not valid\n");
+
+		return;
+	}
+
+	IWL_ERR_DEV(dev, "mac address is not found\n");
 }
 
 struct iwl_nvm_data *
@@ -556,7 +616,8 @@ iwl_parse_nvm_data(struct device *dev, c
 				rx_chains);
 	} else {
 		/* MAC address in family 8000 */
-		iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
+		iwl_set_hw_address_family_8000(dev, cfg, data, mac_override,
+					       nvm_hw);
 
 		iwl_init_sbands(dev, cfg, data, regulatory,
 				sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-prph.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-prph.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-prph.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-prph.h	2014-09-28 17:29:07.000000000 -0400
@@ -359,4 +359,10 @@ enum secure_load_status_reg {
 #define RXF_LD_FENCE_OFFSET_ADDR	(0xa00c10)
 #define RXF_FIFO_RD_FENCE_ADDR		(0xa00c0c)
 
+/* FW monitor */
+#define MON_BUFF_BASE_ADDR		(0xa03c3c)
+#define MON_BUFF_END_ADDR		(0xa03c40)
+#define MON_BUFF_WRPTR			(0xa03c44)
+#define MON_BUFF_CYCLE_CNT		(0xa03c48)
+
 #endif				/* __iwl_prph_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-trans.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-trans.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/iwl-trans.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/iwl-trans.h	2014-09-28 17:29:07.000000000 -0400
@@ -394,6 +394,11 @@ struct iwl_trans_config {
 	const char *const *command_names;
 };
 
+struct iwl_trans_dump_data {
+	u32 len;
+	u8 data[];
+};
+
 struct iwl_trans;
 
 /**
@@ -461,10 +466,8 @@ struct iwl_trans;
  * @unref: release a reference previously taken with @ref. Note that
  *	initially the reference count is 1, making an initial @unref
  *	necessary to allow low power states.
- * @dump_data: fill a data dump with debug data, maybe containing last
- *	TX'ed commands and similar. When called with a NULL buffer and
- *	zero buffer length, provide only the (estimated) required buffer
- *	length. Return the used buffer length.
+ * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
+ *	TX'ed commands and similar. The buffer will be vfree'd by the caller.
  *	Note that the transport must fill in the proper file headers.
  */
 struct iwl_trans_ops {
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
 	void (*unref)(struct iwl_trans *trans);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
+	struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
 #endif
 };
 
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struc
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
-				      void *buf, u32 buflen)
+static inline struct iwl_trans_dump_data *
+iwl_trans_dump_data(struct iwl_trans *trans)
 {
 	if (!trans->ops->dump_data)
-		return 0;
-	return trans->ops->dump_data(trans, buf, buflen);
+		return NULL;
+	return trans->ops->dump_data(trans);
 }
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,16 +20,17 @@ config IWLWIFI
 		Intel 2000 Series Wi-Fi Adapters
 		Intel 7260 Wi-Fi Adapter
 		Intel 3160 Wi-Fi Adapter
+		Intel 7265 Wi-Fi Adapter
 
 
 	  This driver uses the kernel's mac80211 subsystem.
 
-	  In order to use this driver, you will need a microcode (uCode)
+	  In order to use this driver, you will need a firmware
 	  image for it. You can obtain the microcode from:
 
-	          <http://intellinuxwireless.org/>.
+	          <http://wireless.kernel.org/en/users/Drivers/iwlwifi>.
 
-	  The microcode is typically installed in /lib/firmware. You can
+	  The firmware is typically installed in /lib/firmware. You can
 	  look in the hotplug script /etc/hotplug/firmware.agent to
 	  determine which directory FIRMWARE_DIR is set to when the script
 	  runs.
@@ -39,9 +40,10 @@ config IWLWIFI
 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
 	  module will be called iwlwifi.
 
+if IWLWIFI
+
 config IWLWIFI_LEDS
 	bool
-	depends on IWLWIFI
 	depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
 	select LEDS_TRIGGERS
 	select MAC80211_LEDS
@@ -49,7 +51,6 @@ config IWLWIFI_LEDS
 
 config IWLDVM
 	tristate "Intel Wireless WiFi DVM Firmware support"
-	depends on IWLWIFI
 	default IWLWIFI
 	help
 	  This is the driver that supports the DVM firmware which is
@@ -58,7 +59,6 @@ config IWLDVM
 
 config IWLMVM
 	tristate "Intel Wireless WiFi MVM Firmware support"
-	depends on IWLWIFI
 	help
 	  This is the driver that supports the MVM firmware which is
 	  currently only available for 7260 and 3160 devices.
@@ -70,7 +70,7 @@ config IWLWIFI_OPMODE_MODULAR
 	default y if IWLMVM=m
 
 comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
-	depends on IWLWIFI && IWLDVM=n && IWLMVM=n
+	depends on IWLDVM=n && IWLMVM=n
 
 config IWLWIFI_BCAST_FILTERING
 	bool "Enable broadcast filtering"
@@ -86,11 +86,9 @@ config IWLWIFI_BCAST_FILTERING
 	  expect incoming broadcasts for their normal operations.
 
 menu "Debugging Options"
-	depends on IWLWIFI
 
 config IWLWIFI_DEBUG
 	bool "Enable full debugging output in the iwlwifi driver"
-	depends on IWLWIFI
 	---help---
 	  This option will enable debug tracing output for the iwlwifi drivers
 
@@ -115,7 +113,7 @@ config IWLWIFI_DEBUG
 
 config IWLWIFI_DEBUGFS
         bool "iwlwifi debugfs support"
-        depends on IWLWIFI && MAC80211_DEBUGFS
+        depends on MAC80211_DEBUGFS
         ---help---
 	  Enable creation of debugfs files for the iwlwifi drivers. This
 	  is a low-impact option that allows getting insight into the
@@ -123,13 +121,12 @@ config IWLWIFI_DEBUGFS
 
 config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
         bool "Experimental uCode support"
-        depends on IWLWIFI && IWLWIFI_DEBUG
+        depends on IWLWIFI_DEBUG
         ---help---
 	  Enable use of experimental ucode for testing and debugging.
 
 config IWLWIFI_DEVICE_TRACING
 	bool "iwlwifi device access tracing"
-	depends on IWLWIFI
 	depends on EVENT_TRACING
 	help
 	  Say Y here to trace all commands, including TX frames and IO
@@ -145,3 +142,5 @@ config IWLWIFI_DEVICE_TRACING
 	  If unsure, say Y so we can help you better when problems
 	  occur.
 endmenu
+
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/coex.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/coex.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/coex.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/coex.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,57 +70,58 @@
 #include "mvm.h"
 #include "iwl-debug.h"
 
-#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant)			\
-	[(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) |	\
-		   ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
-
-static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
-		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
-		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
-		       BT_COEX_PRIO_TBL_PRIO_LOW, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
-		       BT_COEX_PRIO_TBL_PRIO_LOW, 1),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
-		       BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
-		       BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
-		       BT_COEX_PRIO_TBL_DISABLED, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
-		       BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
-		       BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
-	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
-		       BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
-	0, 0, 0, 0, 0, 0,
-};
-
-#undef EVENT_PRIO_ANT
-
-#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD	(-62)
-#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD	(-65)
 #define BT_ANTENNA_COUPLING_THRESHOLD		(30)
 
-static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
-{
-	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
-				    sizeof(struct iwl_bt_coex_prio_tbl_cmd),
-				    &iwl_bt_prio_tbl);
-}
+const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
+	[BT_KILL_MSK_DEFAULT] = 0xfffffc00,
+	[BT_KILL_MSK_NEVER] = 0xffffffff,
+	[BT_KILL_MSK_ALWAYS] = 0,
+};
 
-const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
-	[BT_KILL_MSK_DEFAULT] = 0xffff0000,
-	[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
-	[BT_KILL_MSK_REDUCED_TXPOW] = 0,
+const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
+	{
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+	},
+	{
+		BT_KILL_MSK_NEVER,
+		BT_KILL_MSK_NEVER,
+		BT_KILL_MSK_NEVER,
+	},
+	{
+		BT_KILL_MSK_NEVER,
+		BT_KILL_MSK_NEVER,
+		BT_KILL_MSK_NEVER,
+	},
+	{
+		BT_KILL_MSK_DEFAULT,
+		BT_KILL_MSK_NEVER,
+		BT_KILL_MSK_DEFAULT,
+	},
 };
 
-const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
-	[BT_KILL_MSK_DEFAULT] = 0xffff0000,
-	[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
-	[BT_KILL_MSK_REDUCED_TXPOW] = 0,
+const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
+	{
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+	},
+	{
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+	},
+	{
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_ALWAYS,
+	},
+	{
+		BT_KILL_MSK_DEFAULT,
+		BT_KILL_MSK_ALWAYS,
+		BT_KILL_MSK_DEFAULT,
+	},
 };
 
 static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
@@ -519,6 +520,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, c
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	enum iwl_bt_coex_lut_type ret;
 	u16 phy_ctx_id;
+	u32 primary_ch_phy_id, secondary_ch_phy_id;
 
 	/*
 	 * Checking that we hold mvm->mutex is a good idea, but the rate
@@ -535,7 +537,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, c
 	if (!chanctx_conf ||
 	     chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
 		rcu_read_unlock();
-		return BT_COEX_LOOSE_LUT;
+		return BT_COEX_INVALID_LUT;
 	}
 
 	ret = BT_COEX_TX_DIS_LUT;
@@ -546,10 +548,13 @@ iwl_get_coex_type(struct iwl_mvm *mvm, c
 	}
 
 	phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
+	primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
+	secondary_ch_phy_id =
+		le32_to_cpu(mvm->last_bt_ci_cmd.secondary_ch_phy_id);
 
-	if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id)
+	if (primary_ch_phy_id == phy_ctx_id)
 		ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
-	else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id)
+	else if (secondary_ch_phy_id == phy_ctx_id)
 		ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
 	/* else - default = TX TX disallowed */
 
@@ -567,59 +572,61 @@ int iwl_send_bt_init_conf(struct iwl_mvm
 		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
 	};
 	int ret;
-	u32 flags;
+	u32 mode;
 
-	ret = iwl_send_bt_prio_tbl(mvm);
-	if (ret)
-		return ret;
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_send_bt_init_conf_old(mvm);
 
 	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
 	if (!bt_cmd)
 		return -ENOMEM;
 	cmd.data[0] = bt_cmd;
 
-	bt_cmd->max_kill = 5;
-	bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
-	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
-	bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
-	bt_cmd->bt4_tx_rx_max_freq0 = 15;
-	bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
-	bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
+	lockdep_assert_held(&mvm->mutex);
 
-	flags = iwlwifi_mod_params.bt_coex_active ?
-			BT_COEX_NW : BT_COEX_DISABLE;
-	bt_cmd->flags = cpu_to_le32(flags);
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
+		switch (mvm->bt_force_ant_mode) {
+		case BT_FORCE_ANT_BT:
+			mode = BT_COEX_BT;
+			break;
+		case BT_FORCE_ANT_WIFI:
+			mode = BT_COEX_WIFI;
+			break;
+		default:
+			WARN_ON(1);
+			mode = 0;
+		}
 
-	bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
-					    BT_VALID_BT_PRIO_BOOST |
-					    BT_VALID_MAX_KILL |
-					    BT_VALID_3W_TMRS |
-					    BT_VALID_KILL_ACK |
-					    BT_VALID_KILL_CTS |
-					    BT_VALID_REDUCED_TX_POWER |
-					    BT_VALID_LUT |
-					    BT_VALID_WIFI_RX_SW_PRIO_BOOST |
-					    BT_VALID_WIFI_TX_SW_PRIO_BOOST |
-					    BT_VALID_ANT_ISOLATION |
-					    BT_VALID_ANT_ISOLATION_THRS |
-					    BT_VALID_TXTX_DELTA_FREQ_THRS |
-					    BT_VALID_TXRX_MAX_FREQ_0 |
-					    BT_VALID_SYNC_TO_SCO);
+		bt_cmd->mode = cpu_to_le32(mode);
+		goto send_cmd;
+	}
+
+	bt_cmd->max_kill = cpu_to_le32(5);
+	bt_cmd->bt4_antenna_isolation_thr =
+				cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
+	bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
+	bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
+	bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
+	bt_cmd->override_secondary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
+
+	mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE;
+	bt_cmd->mode = cpu_to_le32(mode);
 
 	if (IWL_MVM_BT_COEX_SYNC2SCO)
-		bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
+		bt_cmd->enabled_modules |=
+			cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
 
-	if (IWL_MVM_BT_COEX_CORUNNING) {
-		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
-						     BT_VALID_CORUN_LUT_40);
-		bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
-	}
+	if (IWL_MVM_BT_COEX_CORUNNING)
+		bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
 
 	if (IWL_MVM_BT_COEX_MPLUT) {
-		bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
-		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+		bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
+		bt_cmd->enabled_modules |=
+			cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
 	}
 
+	bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
+
 	if (mvm->cfg->bt_shared_single_ant)
 		memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
 		       sizeof(iwl_single_shared_ant));
@@ -627,21 +634,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm
 		memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
 		       sizeof(iwl_combined_lookup));
 
-	/* Take first Co-running block LUT to get started */
-	memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
-	       sizeof(bt_cmd->bt4_corun_lut20));
-	memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
-	       sizeof(bt_cmd->bt4_corun_lut40));
-
-	memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
+	memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
 	       sizeof(iwl_bt_prio_boost));
-	memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+	memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
 	       sizeof(iwl_bt_mprio_lut));
-	bt_cmd->kill_ack_msk =
-		cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
-	bt_cmd->kill_cts_msk =
-		cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
 
+send_cmd:
 	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
 	memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
 
@@ -651,82 +649,54 @@ int iwl_send_bt_init_conf(struct iwl_mvm
 	return ret;
 }
 
-static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
-					   bool reduced_tx_power)
+static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm)
 {
-	enum iwl_bt_kill_msk bt_kill_msk;
-	struct iwl_bt_coex_cmd *bt_cmd;
 	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
-	struct iwl_host_cmd cmd = {
-		.id = BT_CONFIG,
-		.data[0] = &bt_cmd,
-		.len = { sizeof(*bt_cmd), },
-		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
-	};
-	int ret = 0;
+	u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
+	u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut);
+	u32 ag = le32_to_cpu(notif->bt_activity_grading);
+	struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
+	u8 ack_kill_msk[NUM_PHY_CTX] = {};
+	u8 cts_kill_msk[NUM_PHY_CTX] = {};
+	int i;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (reduced_tx_power) {
-		/* Reduced Tx power has precedence on the type of the profile */
-		bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
-	} else {
-		/* Low latency BT profile is active: give higher prio to BT */
-		if (BT_MBOX_MSG(notif, 3, SCO_STATE)  ||
-		    BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
-		    BT_MBOX_MSG(notif, 3, SNIFF_STATE))
-			bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
-		else
-			bt_kill_msk = BT_KILL_MSK_DEFAULT;
-	}
+	ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut];
+	cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut];
 
-	IWL_DEBUG_COEX(mvm,
-		       "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
-		       bt_kill_msk,
-		       BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
-		       BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
-		       BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+	ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut];
+	cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut];
 
 	/* Don't send HCMD if there is no update */
-	if (bt_kill_msk == mvm->bt_kill_msk)
+	if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) ||
+	    !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk)))
 		return 0;
 
-	mvm->bt_kill_msk = bt_kill_msk;
-
-	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
-	if (!bt_cmd)
-		return -ENOMEM;
-	cmd.data[0] = bt_cmd;
-	bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
-
-	bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
-	bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
-	bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
-					     BT_VALID_KILL_ACK |
-					     BT_VALID_KILL_CTS);
+	memcpy(mvm->bt_ack_kill_msk, ack_kill_msk,
+	       sizeof(mvm->bt_ack_kill_msk));
+	memcpy(mvm->bt_cts_kill_msk, cts_kill_msk,
+	       sizeof(mvm->bt_cts_kill_msk));
 
-	IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
-		       iwl_bt_ack_kill_msk[bt_kill_msk],
-		       iwl_bt_cts_kill_msk[bt_kill_msk]);
+	BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values));
 
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
+	for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) {
+		cmd.boost_values[i].kill_ack_msk =
+			cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]);
+		cmd.boost_values[i].kill_cts_msk =
+			cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]);
+	}
 
-	kfree(bt_cmd);
-	return ret;
+	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
+				    sizeof(cmd), &cmd);
 }
 
 static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
 				       bool enable)
 {
-	struct iwl_bt_coex_cmd *bt_cmd;
-	/* Send ASYNC since this can be sent from an atomic context */
-	struct iwl_host_cmd cmd = {
-		.id = BT_CONFIG,
-		.len = { sizeof(*bt_cmd), },
-		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
-		.flags = CMD_ASYNC,
-	};
+	struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
 	struct iwl_mvm_sta *mvmsta;
+	u32 value;
 	int ret;
 
 	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
@@ -737,35 +707,26 @@ static int iwl_mvm_bt_coex_reduced_txp(s
 	if (mvmsta->bt_reduced_txpower == enable)
 		return 0;
 
-	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
-	if (!bt_cmd)
-		return -ENOMEM;
-	cmd.data[0] = bt_cmd;
-	bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
-
-	bt_cmd->valid_bit_msk =
-		cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
-	bt_cmd->bt_reduced_tx_power = sta_id;
+	value = mvmsta->sta_id;
 
 	if (enable)
-		bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+		value |= BT_REDUCED_TX_POWER_BIT;
 
 	IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
 		       enable ? "en" : "dis", sta_id);
 
+	cmd.reduced_txp = cpu_to_le32(value);
 	mvmsta->bt_reduced_txpower = enable;
 
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
+	ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC,
+				   sizeof(cmd), &cmd);
 
-	kfree(bt_cmd);
 	return ret;
 }
 
 struct iwl_bt_iterator_data {
 	struct iwl_bt_coex_profile_notif *notif;
 	struct iwl_mvm *mvm;
-	u32 num_bss_ifaces;
-	bool reduced_tx_power;
 	struct ieee80211_chanctx_conf *primary;
 	struct ieee80211_chanctx_conf *secondary;
 	bool primary_ll;
@@ -780,9 +741,9 @@ void iwl_mvm_bt_coex_enable_rssi_event(s
 
 	mvmvif->bf_data.last_bt_coex_event = rssi;
 	mvmvif->bf_data.bt_coex_max_thold =
-		enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0;
+		enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
 	mvmvif->bf_data.bt_coex_min_thold =
-		enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0;
+		enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
 }
 
 /* must be called under rcu_read_lock */
@@ -793,7 +754,8 @@ static void iwl_mvm_bt_notif_iterator(vo
 	struct iwl_bt_iterator_data *data = _data;
 	struct iwl_mvm *mvm = data->mvm;
 	struct ieee80211_chanctx_conf *chanctx_conf;
-	enum ieee80211_smps_mode smps_mode;
+	/* default smps_mode is AUTOMATIC - only used for client modes */
+	enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
 	u32 bt_activity_grading;
 	int ave_rssi;
 
@@ -801,22 +763,10 @@ static void iwl_mvm_bt_notif_iterator(vo
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
-		/* Count BSSes vifs */
-		data->num_bss_ifaces++;
-		/* default smps_mode for BSS / P2P client is AUTOMATIC */
-		smps_mode = IEEE80211_SMPS_AUTOMATIC;
 		break;
 	case NL80211_IFTYPE_AP:
-		/* default smps_mode for AP / GO is OFF */
-		smps_mode = IEEE80211_SMPS_OFF;
-		if (!mvmvif->ap_ibss_active) {
-			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
-					    smps_mode);
+		if (!mvmvif->ap_ibss_active)
 			return;
-		}
-
-		/* the Ack / Cts kill mask must be default if AP / GO */
-		data->reduced_tx_power = false;
 		break;
 	default:
 		return;
@@ -827,11 +777,10 @@ static void iwl_mvm_bt_notif_iterator(vo
 	/* If channel context is invalid or not on 2.4GHz .. */
 	if ((!chanctx_conf ||
 	     chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
-		/* ... relax constraints and disable rssi events */
-		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
-				    smps_mode);
-		data->reduced_tx_power = false;
 		if (vif->type == NL80211_IFTYPE_STATION) {
+			/* ... relax constraints and disable rssi events */
+			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+					    smps_mode);
 			iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
 						    false);
 			iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -843,20 +792,23 @@ static void iwl_mvm_bt_notif_iterator(vo
 	if (bt_activity_grading >= BT_HIGH_TRAFFIC)
 		smps_mode = IEEE80211_SMPS_STATIC;
 	else if (bt_activity_grading >= BT_LOW_TRAFFIC)
-		smps_mode = vif->type == NL80211_IFTYPE_AP ?
-				IEEE80211_SMPS_OFF :
-				IEEE80211_SMPS_DYNAMIC;
+		smps_mode = IEEE80211_SMPS_DYNAMIC;
 
-	/* relax SMPS contraints for next association */
+	/* relax SMPS constraints for next association */
 	if (!vif->bss_conf.assoc)
 		smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
+	if (IWL_COEX_IS_RRC_ON(mvm->last_bt_notif.ttc_rrc_status,
+			       mvmvif->phy_ctxt->id))
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
 	IWL_DEBUG_COEX(data->mvm,
-		       "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
-		       mvmvif->id, data->notif->bt_status, bt_activity_grading,
-		       smps_mode);
+		       "mac %d: bt_activity_grading %d smps_req %d\n",
+		       mvmvif->id, bt_activity_grading, smps_mode);
 
-	iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
+	if (vif->type == NL80211_IFTYPE_STATION)
+		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+				    smps_mode);
 
 	/* low latency is always primary */
 	if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -906,8 +858,7 @@ static void iwl_mvm_bt_notif_iterator(vo
 	 */
 	if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
 	    mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
-	    !data->notif->bt_status) {
-		data->reduced_tx_power = false;
+	    le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
 		iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
 		iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
 		return;
@@ -919,26 +870,12 @@ static void iwl_mvm_bt_notif_iterator(vo
 	/* if the RSSI isn't valid, fake it is very low */
 	if (!ave_rssi)
 		ave_rssi = -100;
-	if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) {
+	if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
 		if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
 			IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
-
-		/*
-		 * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
-		 * BSS / P2P clients have rssi above threshold.
-		 * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
-		 * the iteration, if one interface's rssi isn't good enough,
-		 * bt_kill_msk will be set to default values.
-		 */
-	} else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) {
+	} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
 		if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
 			IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
-
-		/*
-		 * One interface hasn't rssi above threshold, bt_kill_msk must
-		 * be set to default values.
-		 */
-		data->reduced_tx_power = false;
 	}
 
 	/* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -950,11 +887,14 @@ static void iwl_mvm_bt_coex_notif_handle
 	struct iwl_bt_iterator_data data = {
 		.mvm = mvm,
 		.notif = &mvm->last_bt_notif,
-		.reduced_tx_power = true,
 	};
 	struct iwl_bt_coex_ci_cmd cmd = {};
 	u8 ci_bw_idx;
 
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return;
+
 	rcu_read_lock();
 	ieee80211_iterate_active_interfaces_atomic(
 					mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
@@ -969,9 +909,7 @@ static void iwl_mvm_bt_coex_notif_handle
 
 		if (chan->def.width < NL80211_CHAN_WIDTH_40) {
 			ci_bw_idx = 0;
-			cmd.co_run_bw_primary = 0;
 		} else {
-			cmd.co_run_bw_primary = 1;
 			if (chan->def.center_freq1 >
 			    chan->def.chan->center_freq)
 				ci_bw_idx = 2;
@@ -981,7 +919,8 @@ static void iwl_mvm_bt_coex_notif_handle
 
 		cmd.bt_primary_ci =
 			iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
-		cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
+		cmd.primary_ch_phy_id =
+			cpu_to_le32(*((u16 *)data.primary->drv_priv));
 	}
 
 	if (data.secondary) {
@@ -993,9 +932,7 @@ static void iwl_mvm_bt_coex_notif_handle
 
 		if (chan->def.width < NL80211_CHAN_WIDTH_40) {
 			ci_bw_idx = 0;
-			cmd.co_run_bw_secondary = 0;
 		} else {
-			cmd.co_run_bw_secondary = 1;
 			if (chan->def.center_freq1 >
 			    chan->def.chan->center_freq)
 				ci_bw_idx = 2;
@@ -1005,7 +942,8 @@ static void iwl_mvm_bt_coex_notif_handle
 
 		cmd.bt_secondary_ci =
 			iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
-		cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
+		cmd.secondary_ch_phy_id =
+			cpu_to_le32(*((u16 *)data.secondary->drv_priv));
 	}
 
 	rcu_read_unlock();
@@ -1018,14 +956,7 @@ static void iwl_mvm_bt_coex_notif_handle
 		memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
 	}
 
-	/*
-	 * If there are no BSS / P2P client interfaces, reduced Tx Power is
-	 * irrelevant since it is based on the RSSI coming from the beacon.
-	 * Use BT_KILL_MSK_DEFAULT in that case.
-	 */
-	data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
-
-	if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+	if (iwl_mvm_bt_udpate_sw_boost(mvm))
 		IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
 }
 
@@ -1036,11 +967,10 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
 
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_rx_bt_coex_notif_old(mvm, rxb, dev_cmd);
 
 	IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
-	IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
-		       notif->bt_status ? "ON" : "OFF");
-	IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
 	IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
 	IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
 		       le32_to_cpu(notif->primary_ch_lut));
@@ -1048,8 +978,6 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_
 		       le32_to_cpu(notif->secondary_ch_lut));
 	IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
 		       le32_to_cpu(notif->bt_activity_grading));
-	IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
-		       notif->bt_agg_traffic_load);
 
 	/* remember this notification for future use: rssi fluctuations */
 	memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
@@ -1097,16 +1025,6 @@ static void iwl_mvm_bt_rssi_iterator(voi
 		return;
 
 	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
-	data->num_bss_ifaces++;
-
-	/*
-	 * This interface doesn't support reduced Tx power (because of low
-	 * RSSI probably), then set bt_kill_msk to default values.
-	 */
-	if (!mvmsta->bt_reduced_txpower)
-		data->reduced_tx_power = false;
-	/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
 }
 
 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1115,12 +1033,20 @@ void iwl_mvm_bt_rssi_event(struct iwl_mv
 	struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
 	struct iwl_bt_iterator_data data = {
 		.mvm = mvm,
-		.reduced_tx_power = true,
 	};
 	int ret;
 
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+		iwl_mvm_bt_rssi_event_old(mvm, vif, rssi_event);
+		return;
+	}
+
 	lockdep_assert_held(&mvm->mutex);
 
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return;
+
 	/*
 	 * Rssi update while not associated - can happen since the statistics
 	 * are handled asynchronously
@@ -1129,7 +1055,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mv
 		return;
 
 	/* No BT - reports should be disabled */
-	if (!mvm->last_bt_notif.bt_status)
+	if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF)
 		return;
 
 	IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
@@ -1153,14 +1079,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mv
 		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 		iwl_mvm_bt_rssi_iterator, &data);
 
-	/*
-	 * If there are no BSS / P2P client interfaces, reduced Tx Power is
-	 * irrelevant since it is based on the RSSI coming from the beacon.
-	 * Use BT_KILL_MSK_DEFAULT in that case.
-	 */
-	data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
-
-	if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+	if (iwl_mvm_bt_udpate_sw_boost(mvm))
 		IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
 }
 
@@ -1171,15 +1090,23 @@ u16 iwl_mvm_coex_agg_time_limit(struct i
 				struct ieee80211_sta *sta)
 {
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+	struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
 	enum iwl_bt_coex_lut_type lut_type;
 
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
+
+	if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
+		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
 	if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
 	    BT_HIGH_TRAFFIC)
 		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
 
 	lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
 
-	if (lut_type == BT_COEX_LOOSE_LUT)
+	if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
 		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
 
 	/* tight coex, high bt traffic, reduce AGG time limit */
@@ -1190,18 +1117,37 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(str
 				     struct ieee80211_sta *sta)
 {
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+	struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+	enum iwl_bt_coex_lut_type lut_type;
+
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
+
+	if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
+		return true;
 
 	if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
 	    BT_HIGH_TRAFFIC)
 		return true;
 
 	/*
-	 * In Tight, BT can't Rx while we Tx, so use both antennas since BT is
-	 * already killed.
-	 * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we
-	 * Tx.
+	 * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
+	 * since BT is already killed.
+	 * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
+	 * we Tx.
+	 * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
 	 */
-	return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT;
+	lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+	return lut_type != BT_COEX_LOOSE_LUT;
+}
+
+bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
+{
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
+
+	return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF;
 }
 
 bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
@@ -1209,6 +1155,9 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(stru
 {
 	u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
 
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_bt_coex_is_tpc_allowed_old(mvm, band);
+
 	if (band != IEEE80211_BAND_2GHZ)
 		return false;
 
@@ -1249,6 +1198,11 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mv
 
 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
 {
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+		iwl_mvm_bt_coex_vif_change_old(mvm);
+		return;
+	}
+
 	iwl_mvm_bt_coex_notif_handle(mvm);
 }
 
@@ -1258,22 +1212,22 @@ int iwl_mvm_rx_ant_coupling_notif(struct
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+	struct iwl_bt_coex_corun_lut_update_cmd cmd = {};
 	u8 __maybe_unused lower_bound, upper_bound;
-	int ret;
 	u8 lut;
 
-	struct iwl_bt_coex_cmd *bt_cmd;
-	struct iwl_host_cmd cmd = {
-		.id = BT_CONFIG,
-		.len = { sizeof(*bt_cmd), },
-		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
-	};
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+		return iwl_mvm_rx_ant_coupling_notif_old(mvm, rxb, dev_cmd);
 
 	if (!IWL_MVM_BT_COEX_CORUNNING)
 		return 0;
 
 	lockdep_assert_held(&mvm->mutex);
 
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return 0;
+
 	if (ant_isolation ==  mvm->last_ant_isol)
 		return 0;
 
@@ -1298,25 +1252,13 @@ int iwl_mvm_rx_ant_coupling_notif(struct
 
 	mvm->last_corun_lut = lut;
 
-	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
-	if (!bt_cmd)
-		return 0;
-	cmd.data[0] = bt_cmd;
-
-	bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
-	bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
-					     BT_VALID_CORUN_LUT_20 |
-					     BT_VALID_CORUN_LUT_40);
-
 	/* For the moment, use the same LUT for 20GHz and 40GHz */
-	memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
-	       sizeof(bt_cmd->bt4_corun_lut20));
-
-	memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
-	       sizeof(bt_cmd->bt4_corun_lut40));
+	memcpy(&cmd.corun_lut20, antenna_coupling_ranges[lut].lut20,
+	       sizeof(cmd.corun_lut20));
 
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
+	memcpy(&cmd.corun_lut40, antenna_coupling_ranges[lut].lut20,
+	       sizeof(cmd.corun_lut40));
 
-	kfree(bt_cmd);
-	return ret;
+	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_CORUN_LUT, 0,
+				    sizeof(cmd), &cmd);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1257 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <linux/ieee80211.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "fw-api-coex.h"
+#include "iwl-modparams.h"
+#include "mvm.h"
+#include "iwl-debug.h"
+
+#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant)			\
+	[(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) |	\
+		   ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
+
+static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
+		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
+		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
+		       BT_COEX_PRIO_TBL_PRIO_LOW, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
+		       BT_COEX_PRIO_TBL_PRIO_LOW, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
+		       BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
+		       BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
+		       BT_COEX_PRIO_TBL_DISABLED, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
+	0, 0, 0, 0, 0, 0,
+};
+
+#undef EVENT_PRIO_ANT
+
+#define BT_ANTENNA_COUPLING_THRESHOLD		(30)
+
+static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
+{
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return 0;
+
+	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
+				    sizeof(struct iwl_bt_coex_prio_tbl_cmd),
+				    &iwl_bt_prio_tbl);
+}
+
+static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
+	cpu_to_le32(0xf0f0f0f0), /* 50% */
+	cpu_to_le32(0xc0c0c0c0), /* 25% */
+	cpu_to_le32(0xfcfcfcfc), /* 75% */
+	cpu_to_le32(0xfefefefe), /* 87.5% */
+};
+
+static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
+	{
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+	},
+	{
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+	},
+	{
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x40000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x44000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+	},
+};
+
+static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
+	{
+		/* Tight */
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaeaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xcc00ff28),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0xcc00aaaa),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0x00004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xf0005000),
+	},
+	{
+		/* Loose */
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xcc00ff28),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0xcc00aaaa),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x00000000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xf0005000),
+	},
+	{
+		/* Tx Tx disabled */
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xeeaaaaaa),
+		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xcc00ff28),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0xcc00aaaa),
+		cpu_to_le32(0x0000aaaa),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xf0005000),
+	},
+};
+
+/* 20MHz / 40MHz below / 40Mhz above*/
+static const __le64 iwl_ci_mask[][3] = {
+	/* dummy entry for channel 0 */
+	{cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
+	{
+		cpu_to_le64(0x0000001FFFULL),
+		cpu_to_le64(0x0ULL),
+		cpu_to_le64(0x00007FFFFFULL),
+	},
+	{
+		cpu_to_le64(0x000000FFFFULL),
+		cpu_to_le64(0x0ULL),
+		cpu_to_le64(0x0003FFFFFFULL),
+	},
+	{
+		cpu_to_le64(0x000003FFFCULL),
+		cpu_to_le64(0x0ULL),
+		cpu_to_le64(0x000FFFFFFCULL),
+	},
+	{
+		cpu_to_le64(0x00001FFFE0ULL),
+		cpu_to_le64(0x0ULL),
+		cpu_to_le64(0x007FFFFFE0ULL),
+	},
+	{
+		cpu_to_le64(0x00007FFF80ULL),
+		cpu_to_le64(0x00007FFFFFULL),
+		cpu_to_le64(0x01FFFFFF80ULL),
+	},
+	{
+		cpu_to_le64(0x0003FFFC00ULL),
+		cpu_to_le64(0x0003FFFFFFULL),
+		cpu_to_le64(0x0FFFFFFC00ULL),
+	},
+	{
+		cpu_to_le64(0x000FFFF000ULL),
+		cpu_to_le64(0x000FFFFFFCULL),
+		cpu_to_le64(0x3FFFFFF000ULL),
+	},
+	{
+		cpu_to_le64(0x007FFF8000ULL),
+		cpu_to_le64(0x007FFFFFE0ULL),
+		cpu_to_le64(0xFFFFFF8000ULL),
+	},
+	{
+		cpu_to_le64(0x01FFFE0000ULL),
+		cpu_to_le64(0x01FFFFFF80ULL),
+		cpu_to_le64(0xFFFFFE0000ULL),
+	},
+	{
+		cpu_to_le64(0x0FFFF00000ULL),
+		cpu_to_le64(0x0FFFFFFC00ULL),
+		cpu_to_le64(0x0ULL),
+	},
+	{
+		cpu_to_le64(0x3FFFC00000ULL),
+		cpu_to_le64(0x3FFFFFF000ULL),
+		cpu_to_le64(0x0)
+	},
+	{
+		cpu_to_le64(0xFFFE000000ULL),
+		cpu_to_le64(0xFFFFFF8000ULL),
+		cpu_to_le64(0x0)
+	},
+	{
+		cpu_to_le64(0xFFF8000000ULL),
+		cpu_to_le64(0xFFFFFE0000ULL),
+		cpu_to_le64(0x0)
+	},
+	{
+		cpu_to_le64(0xFFC0000000ULL),
+		cpu_to_le64(0x0ULL),
+		cpu_to_le64(0x0ULL)
+	},
+};
+
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+	cpu_to_le32(0x28412201),
+	cpu_to_le32(0x11118451),
+};
+
+struct corunning_block_luts {
+	u8 range;
+	__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
+};
+
+/*
+ * Ranges for the antenna coupling calibration / co-running block LUT:
+ *		LUT0: [ 0, 12[
+ *		LUT1: [12, 20[
+ *		LUT2: [20, 21[
+ *		LUT3: [21, 23[
+ *		LUT4: [23, 27[
+ *		LUT5: [27, 30[
+ *		LUT6: [30, 32[
+ *		LUT7: [32, 33[
+ *		LUT8: [33, - [
+ */
+static const struct corunning_block_luts antenna_coupling_ranges[] = {
+	{
+		.range = 0,
+		.lut20 = {
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 12,
+		.lut20 = {
+			cpu_to_le32(0x00000001),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 20,
+		.lut20 = {
+			cpu_to_le32(0x00000002),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 21,
+		.lut20 = {
+			cpu_to_le32(0x00000003),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 23,
+		.lut20 = {
+			cpu_to_le32(0x00000004),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 27,
+		.lut20 = {
+			cpu_to_le32(0x00000005),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 30,
+		.lut20 = {
+			cpu_to_le32(0x00000006),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 32,
+		.lut20 = {
+			cpu_to_le32(0x00000007),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+	{
+		.range = 33,
+		.lut20 = {
+			cpu_to_le32(0x00000008),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+			cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
+		},
+	},
+};
+
+static enum iwl_bt_coex_lut_type
+iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
+{
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	enum iwl_bt_coex_lut_type ret;
+	u16 phy_ctx_id;
+
+	/*
+	 * Checking that we hold mvm->mutex is a good idea, but the rate
+	 * control can't acquire the mutex since it runs in Tx path.
+	 * So this is racy in that case, but in the worst case, the AMPDU
+	 * size limit will be wrong for a short time which is not a big
+	 * issue.
+	 */
+
+	rcu_read_lock();
+
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+
+	if (!chanctx_conf ||
+	    chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
+		rcu_read_unlock();
+		return BT_COEX_INVALID_LUT;
+	}
+
+	ret = BT_COEX_TX_DIS_LUT;
+
+	if (mvm->cfg->bt_shared_single_ant) {
+		rcu_read_unlock();
+		return ret;
+	}
+
+	phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
+
+	if (mvm->last_bt_ci_cmd_old.primary_ch_phy_id == phy_ctx_id)
+		ret = le32_to_cpu(mvm->last_bt_notif_old.primary_ch_lut);
+	else if (mvm->last_bt_ci_cmd_old.secondary_ch_phy_id == phy_ctx_id)
+		ret = le32_to_cpu(mvm->last_bt_notif_old.secondary_ch_lut);
+	/* else - default = TX TX disallowed */
+
+	rcu_read_unlock();
+
+	return ret;
+}
+
+int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
+{
+	struct iwl_bt_coex_cmd_old *bt_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+	};
+	int ret;
+	u32 flags;
+
+	ret = iwl_send_bt_prio_tbl(mvm);
+	if (ret)
+		return ret;
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
+		switch (mvm->bt_force_ant_mode) {
+		case BT_FORCE_ANT_AUTO:
+			flags = BT_COEX_AUTO_OLD;
+			break;
+		case BT_FORCE_ANT_BT:
+			flags = BT_COEX_BT_OLD;
+			break;
+		case BT_FORCE_ANT_WIFI:
+			flags = BT_COEX_WIFI_OLD;
+			break;
+		default:
+			WARN_ON(1);
+			flags = 0;
+		}
+
+		bt_cmd->flags = cpu_to_le32(flags);
+		bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE);
+		goto send_cmd;
+	}
+
+	bt_cmd->max_kill = 5;
+	bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
+	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
+	bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
+	bt_cmd->bt4_tx_rx_max_freq0 = 15;
+	bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
+	bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
+
+	flags = iwlwifi_mod_params.bt_coex_active ?
+			BT_COEX_NW_OLD : BT_COEX_DISABLE_OLD;
+	bt_cmd->flags = cpu_to_le32(flags);
+
+	bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
+					    BT_VALID_BT_PRIO_BOOST |
+					    BT_VALID_MAX_KILL |
+					    BT_VALID_3W_TMRS |
+					    BT_VALID_KILL_ACK |
+					    BT_VALID_KILL_CTS |
+					    BT_VALID_REDUCED_TX_POWER |
+					    BT_VALID_LUT |
+					    BT_VALID_WIFI_RX_SW_PRIO_BOOST |
+					    BT_VALID_WIFI_TX_SW_PRIO_BOOST |
+					    BT_VALID_ANT_ISOLATION |
+					    BT_VALID_ANT_ISOLATION_THRS |
+					    BT_VALID_TXTX_DELTA_FREQ_THRS |
+					    BT_VALID_TXRX_MAX_FREQ_0 |
+					    BT_VALID_SYNC_TO_SCO);
+
+	if (IWL_MVM_BT_COEX_SYNC2SCO)
+		bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
+
+	if (IWL_MVM_BT_COEX_CORUNNING) {
+		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
+						     BT_VALID_CORUN_LUT_40);
+		bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
+	}
+
+	if (IWL_MVM_BT_COEX_MPLUT) {
+		bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
+		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+	}
+
+	if (mvm->cfg->bt_shared_single_ant)
+		memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
+		       sizeof(iwl_single_shared_ant));
+	else
+		memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
+		       sizeof(iwl_combined_lookup));
+
+	/* Take first Co-running block LUT to get started */
+	memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
+	       sizeof(bt_cmd->bt4_corun_lut20));
+	memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
+	       sizeof(bt_cmd->bt4_corun_lut40));
+
+	memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
+	       sizeof(iwl_bt_prio_boost));
+	memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+	       sizeof(iwl_bt_mprio_lut));
+
+send_cmd:
+	memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
+	memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
+}
+
+static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
+{
+	struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
+	u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
+	u32 ag = le32_to_cpu(notif->bt_activity_grading);
+	struct iwl_bt_coex_cmd_old *bt_cmd;
+	u8 ack_kill_msk, cts_kill_msk;
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.data[0] = &bt_cmd,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+	};
+	int ret = 0;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
+	cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
+
+	if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
+	    mvm->bt_cts_kill_msk[0] == cts_kill_msk)
+		return 0;
+
+	mvm->bt_ack_kill_msk[0] = ack_kill_msk;
+	mvm->bt_cts_kill_msk[0] = cts_kill_msk;
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+	bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+
+	bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
+	bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
+	bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
+					     BT_VALID_KILL_ACK |
+					     BT_VALID_KILL_CTS);
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
+}
+
+static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
+				       bool enable)
+{
+	struct iwl_bt_coex_cmd_old *bt_cmd;
+	/* Send ASYNC since this can be sent from an atomic context */
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+		.flags = CMD_ASYNC,
+	};
+	struct iwl_mvm_sta *mvmsta;
+	int ret;
+
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
+	if (!mvmsta)
+		return 0;
+
+	/* nothing to do */
+	if (mvmsta->bt_reduced_txpower == enable)
+		return 0;
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
+	if (!bt_cmd)
+		return -ENOMEM;
+	cmd.data[0] = bt_cmd;
+	bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+
+	bt_cmd->valid_bit_msk =
+		cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
+	bt_cmd->bt_reduced_tx_power = sta_id;
+
+	if (enable)
+		bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+
+	IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
+		       enable ? "en" : "dis", sta_id);
+
+	mvmsta->bt_reduced_txpower = enable;
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
+}
+
+struct iwl_bt_iterator_data {
+	struct iwl_bt_coex_profile_notif_old *notif;
+	struct iwl_mvm *mvm;
+	struct ieee80211_chanctx_conf *primary;
+	struct ieee80211_chanctx_conf *secondary;
+	bool primary_ll;
+};
+
+static inline
+void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
+				       struct ieee80211_vif *vif,
+				       bool enable, int rssi)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	mvmvif->bf_data.last_bt_coex_event = rssi;
+	mvmvif->bf_data.bt_coex_max_thold =
+		enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
+	mvmvif->bf_data.bt_coex_min_thold =
+		enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
+}
+
+/* must be called under rcu_read_lock */
+static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
+				      struct ieee80211_vif *vif)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_bt_iterator_data *data = _data;
+	struct iwl_mvm *mvm = data->mvm;
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	enum ieee80211_smps_mode smps_mode;
+	u32 bt_activity_grading;
+	int ave_rssi;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		/* default smps_mode for BSS / P2P client is AUTOMATIC */
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+		break;
+	case NL80211_IFTYPE_AP:
+		if (!mvmvif->ap_ibss_active)
+			return;
+		break;
+	default:
+		return;
+	}
+
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+
+	/* If channel context is invalid or not on 2.4GHz .. */
+	if ((!chanctx_conf ||
+	     chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
+		if (vif->type == NL80211_IFTYPE_STATION) {
+			/* ... relax constraints and disable rssi events */
+			iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+					    smps_mode);
+			iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+						    false);
+			iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+		}
+		return;
+	}
+
+	bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
+	if (bt_activity_grading >= BT_HIGH_TRAFFIC)
+		smps_mode = IEEE80211_SMPS_STATIC;
+	else if (bt_activity_grading >= BT_LOW_TRAFFIC)
+		smps_mode = vif->type == NL80211_IFTYPE_AP ?
+				IEEE80211_SMPS_OFF :
+				IEEE80211_SMPS_DYNAMIC;
+
+	/* relax SMPS contraints for next association */
+	if (!vif->bss_conf.assoc)
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
+	IWL_DEBUG_COEX(data->mvm,
+		       "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
+		       mvmvif->id, data->notif->bt_status, bt_activity_grading,
+		       smps_mode);
+
+	if (vif->type == NL80211_IFTYPE_STATION)
+		iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+				    smps_mode);
+
+	/* low latency is always primary */
+	if (iwl_mvm_vif_low_latency(mvmvif)) {
+		data->primary_ll = true;
+
+		data->secondary = data->primary;
+		data->primary = chanctx_conf;
+	}
+
+	if (vif->type == NL80211_IFTYPE_AP) {
+		if (!mvmvif->ap_ibss_active)
+			return;
+
+		if (chanctx_conf == data->primary)
+			return;
+
+		if (!data->primary_ll) {
+			/*
+			 * downgrade the current primary no matter what its
+			 * type is.
+			 */
+			data->secondary = data->primary;
+			data->primary = chanctx_conf;
+		} else {
+			/* there is low latency vif - we will be secondary */
+			data->secondary = chanctx_conf;
+		}
+		return;
+	}
+
+	/*
+	 * STA / P2P Client, try to be primary if first vif. If we are in low
+	 * latency mode, we are already in primary and just don't do much
+	 */
+	if (!data->primary || data->primary == chanctx_conf)
+		data->primary = chanctx_conf;
+	else if (!data->secondary)
+		/* if secondary is not NULL, it might be a GO */
+		data->secondary = chanctx_conf;
+
+	/*
+	 * don't reduce the Tx power if one of these is true:
+	 *  we are in LOOSE
+	 *  single share antenna product
+	 *  BT is active
+	 *  we are associated
+	 */
+	if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
+	    mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
+	    !data->notif->bt_status) {
+		iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
+		iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+		return;
+	}
+
+	/* try to get the avg rssi from fw */
+	ave_rssi = mvmvif->bf_data.ave_beacon_signal;
+
+	/* if the RSSI isn't valid, fake it is very low */
+	if (!ave_rssi)
+		ave_rssi = -100;
+	if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
+		if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+			IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+	} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
+		if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+			IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+	}
+
+	/* Begin to monitor the RSSI: it may influence the reduced Tx power */
+	iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
+}
+
+static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
+{
+	struct iwl_bt_iterator_data data = {
+		.mvm = mvm,
+		.notif = &mvm->last_bt_notif_old,
+	};
+	struct iwl_bt_coex_ci_cmd_old cmd = {};
+	u8 ci_bw_idx;
+
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return;
+
+	rcu_read_lock();
+	ieee80211_iterate_active_interfaces_atomic(
+					mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+					iwl_mvm_bt_notif_iterator, &data);
+
+	if (data.primary) {
+		struct ieee80211_chanctx_conf *chan = data.primary;
+
+		if (WARN_ON(!chan->def.chan)) {
+			rcu_read_unlock();
+			return;
+		}
+
+		if (chan->def.width < NL80211_CHAN_WIDTH_40) {
+			ci_bw_idx = 0;
+			cmd.co_run_bw_primary = 0;
+		} else {
+			cmd.co_run_bw_primary = 1;
+			if (chan->def.center_freq1 >
+			    chan->def.chan->center_freq)
+				ci_bw_idx = 2;
+			else
+				ci_bw_idx = 1;
+		}
+
+		cmd.bt_primary_ci =
+			iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
+		cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
+	}
+
+	if (data.secondary) {
+		struct ieee80211_chanctx_conf *chan = data.secondary;
+
+		if (WARN_ON(!data.secondary->def.chan)) {
+			rcu_read_unlock();
+			return;
+		}
+
+		if (chan->def.width < NL80211_CHAN_WIDTH_40) {
+			ci_bw_idx = 0;
+			cmd.co_run_bw_secondary = 0;
+		} else {
+			cmd.co_run_bw_secondary = 1;
+			if (chan->def.center_freq1 >
+			    chan->def.chan->center_freq)
+				ci_bw_idx = 2;
+			else
+				ci_bw_idx = 1;
+		}
+
+		cmd.bt_secondary_ci =
+			iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
+		cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
+	}
+
+	rcu_read_unlock();
+
+	/* Don't spam the fw with the same command over and over */
+	if (memcmp(&cmd, &mvm->last_bt_ci_cmd_old, sizeof(cmd))) {
+		if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
+					 sizeof(cmd), &cmd))
+			IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
+		memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
+	}
+
+	if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
+		IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
+}
+
+int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
+				 struct iwl_rx_cmd_buffer *rxb,
+				 struct iwl_device_cmd *dev_cmd)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_bt_coex_profile_notif_old *notif = (void *)pkt->data;
+
+	IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
+	IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
+		       notif->bt_status ? "ON" : "OFF");
+	IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
+	IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
+	IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
+		       le32_to_cpu(notif->primary_ch_lut));
+	IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
+		       le32_to_cpu(notif->secondary_ch_lut));
+	IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
+		       le32_to_cpu(notif->bt_activity_grading));
+	IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
+		       notif->bt_agg_traffic_load);
+
+	/* remember this notification for future use: rssi fluctuations */
+	memcpy(&mvm->last_bt_notif_old, notif, sizeof(mvm->last_bt_notif_old));
+
+	iwl_mvm_bt_coex_notif_handle(mvm);
+
+	/*
+	 * This is an async handler for a notification, returning anything other
+	 * than 0 doesn't make sense even if HCMD failed.
+	 */
+	return 0;
+}
+
+static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
+				     struct ieee80211_vif *vif)
+{
+	struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+	struct iwl_bt_iterator_data *data = _data;
+	struct iwl_mvm *mvm = data->mvm;
+
+	struct ieee80211_sta *sta;
+	struct iwl_mvm_sta *mvmsta;
+
+	struct ieee80211_chanctx_conf *chanctx_conf;
+
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+	/* If channel context is invalid or not on 2.4GHz - don't count it */
+	if (!chanctx_conf ||
+	    chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
+		rcu_read_unlock();
+		return;
+	}
+	rcu_read_unlock();
+
+	if (vif->type != NL80211_IFTYPE_STATION ||
+	    mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+		return;
+
+	sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+					lockdep_is_held(&mvm->mutex));
+
+	/* This can happen if the station has been removed right now */
+	if (IS_ERR_OR_NULL(sta))
+		return;
+
+	mvmsta = iwl_mvm_sta_from_mac80211(sta);
+}
+
+void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			       enum ieee80211_rssi_event rssi_event)
+{
+	struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+	struct iwl_bt_iterator_data data = {
+		.mvm = mvm,
+	};
+	int ret;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return;
+
+	/*
+	 * Rssi update while not associated - can happen since the statistics
+	 * are handled asynchronously
+	 */
+	if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+		return;
+
+	/* No BT - reports should be disabled */
+	if (!mvm->last_bt_notif_old.bt_status)
+		return;
+
+	IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
+		       rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
+
+	/*
+	 * Check if rssi is good enough for reduced Tx power, but not in loose
+	 * scheme.
+	 */
+	if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
+	    iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
+		ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+						  false);
+	else
+		ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
+
+	if (ret)
+		IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
+
+	ieee80211_iterate_active_interfaces_atomic(
+		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+		iwl_mvm_bt_rssi_iterator, &data);
+
+	if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
+		IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
+}
+
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000)
+#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT	(1200)
+
+u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm,
+				    struct ieee80211_sta *sta)
+{
+	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+	enum iwl_bt_coex_lut_type lut_type;
+
+	if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
+	    BT_HIGH_TRAFFIC)
+		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+	if (mvm->last_bt_notif_old.ttc_enabled)
+		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+	lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+
+	if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
+		return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+	/* tight coex, high bt traffic, reduce AGG time limit */
+	return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
+}
+
+bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm,
+					 struct ieee80211_sta *sta)
+{
+	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+	enum iwl_bt_coex_lut_type lut_type;
+
+	if (mvm->last_bt_notif_old.ttc_enabled)
+		return true;
+
+	if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
+	    BT_HIGH_TRAFFIC)
+		return true;
+
+	/*
+	 * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
+	 * since BT is already killed.
+	 * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
+	 * we Tx.
+	 * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
+	 */
+	lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+	return lut_type != BT_COEX_LOOSE_LUT;
+}
+
+bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm)
+{
+	u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
+	return ag == BT_OFF;
+}
+
+bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm,
+					enum ieee80211_band band)
+{
+	u32 bt_activity =
+		le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
+
+	if (band != IEEE80211_BAND_2GHZ)
+		return false;
+
+	return bt_activity >= BT_LOW_TRAFFIC;
+}
+
+void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm)
+{
+	iwl_mvm_bt_coex_notif_handle(mvm);
+}
+
+int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
+				      struct iwl_rx_cmd_buffer *rxb,
+				      struct iwl_device_cmd *dev_cmd)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+	u8 __maybe_unused lower_bound, upper_bound;
+	int ret;
+	u8 lut;
+
+	struct iwl_bt_coex_cmd_old *bt_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = BT_CONFIG,
+		.len = { sizeof(*bt_cmd), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+	};
+
+	if (!IWL_MVM_BT_COEX_CORUNNING)
+		return 0;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	/* Ignore updates if we are in force mode */
+	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+		return 0;
+
+	if (ant_isolation ==  mvm->last_ant_isol)
+		return 0;
+
+	for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++)
+		if (ant_isolation < antenna_coupling_ranges[lut + 1].range)
+			break;
+
+	lower_bound = antenna_coupling_ranges[lut].range;
+
+	if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1)
+		upper_bound = antenna_coupling_ranges[lut + 1].range;
+	else
+		upper_bound = antenna_coupling_ranges[lut].range;
+
+	IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n",
+		       ant_isolation, lower_bound, upper_bound, lut);
+
+	mvm->last_ant_isol = ant_isolation;
+
+	if (mvm->last_corun_lut == lut)
+		return 0;
+
+	mvm->last_corun_lut = lut;
+
+	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+	if (!bt_cmd)
+		return 0;
+	cmd.data[0] = bt_cmd;
+
+	bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+	bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
+					     BT_VALID_CORUN_LUT_20 |
+					     BT_VALID_CORUN_LUT_40);
+
+	/* For the moment, use the same LUT for 20GHz and 40GHz */
+	memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
+	       sizeof(bt_cmd->bt4_corun_lut20));
+
+	memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
+	       sizeof(bt_cmd->bt4_corun_lut40));
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/constants.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/constants.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/constants.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/constants.h	2014-09-28 17:29:07.000000000 -0400
@@ -79,6 +79,8 @@
 #define IWL_MVM_PS_SNOOZE_WINDOW		50
 #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW		25
 #define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT	64
+#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH	62
+#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH	65
 #define IWL_MVM_BT_COEX_SYNC2SCO		1
 #define IWL_MVM_BT_COEX_CORUNNING		1
 #define IWL_MVM_BT_COEX_MPLUT			1
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_r
 					    char __user *user_buf,
 					    size_t count, loff_t *ppos)
 {
-	struct iwl_fw_error_dump_file *dump_file = file->private_data;
+	struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+	ssize_t bytes_read = 0;
+	ssize_t bytes_read_trans = 0;
+
+	if (*ppos < dump_ptrs->op_mode_len)
+		bytes_read +=
+			simple_read_from_buffer(user_buf, count, ppos,
+						dump_ptrs->op_mode_ptr,
+						dump_ptrs->op_mode_len);
+
+	if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
+		return bytes_read;
+
+	if (dump_ptrs->trans_ptr) {
+		*ppos -= dump_ptrs->op_mode_len;
+		bytes_read_trans =
+			simple_read_from_buffer(user_buf + bytes_read,
+						count - bytes_read, ppos,
+						dump_ptrs->trans_ptr->data,
+						dump_ptrs->trans_ptr->len);
+		*ppos += dump_ptrs->op_mode_len;
+
+		if (bytes_read_trans >= 0)
+			bytes_read += bytes_read_trans;
+		else if (!bytes_read)
+			/* propagate the failure */
+			return bytes_read_trans;
+	}
+
+	return bytes_read;
 
-	return simple_read_from_buffer(user_buf, count, ppos,
-				       dump_file,
-				       le32_to_cpu(dump_file->file_len));
 }
 
 static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
 					   struct file *file)
 {
-	vfree(file->private_data);
+	struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+
+	vfree(dump_ptrs->op_mode_ptr);
+	vfree(dump_ptrs->trans_ptr);
+	kfree(dump_ptrs);
 
 	return 0;
 }
@@ -312,20 +342,69 @@ static ssize_t iwl_dbgfs_disable_power_o
 					 BT_MBOX_MSG(notif, _num, _field),  \
 					 true ? "\n" : ", ");
 
-static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
-				       size_t count, loff_t *ppos)
+static
+int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
+			   int pos, int bufsz)
 {
-	struct iwl_mvm *mvm = file->private_data;
-	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
-	char *buf;
-	int ret, pos = 0, bufsz = sizeof(char) * 1024;
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
 
-	buf = kmalloc(bufsz, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+	BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
+	BT_MBOX_PRINT(0, LE_PROF1, false);
+	BT_MBOX_PRINT(0, LE_PROF2, false);
+	BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
+	BT_MBOX_PRINT(0, CHL_SEQ_N, false);
+	BT_MBOX_PRINT(0, INBAND_S, false);
+	BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
+	BT_MBOX_PRINT(0, LE_SCAN, false);
+	BT_MBOX_PRINT(0, LE_ADV, false);
+	BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
+	BT_MBOX_PRINT(0, OPEN_CON_1, true);
 
-	mutex_lock(&mvm->mutex);
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
+
+	BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
+	BT_MBOX_PRINT(1, IP_SR, false);
+	BT_MBOX_PRINT(1, LE_MSTR, false);
+	BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
+	BT_MBOX_PRINT(1, MSG_TYPE, false);
+	BT_MBOX_PRINT(1, SSN, true);
 
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
+
+	BT_MBOX_PRINT(2, SNIFF_ACT, false);
+	BT_MBOX_PRINT(2, PAG, false);
+	BT_MBOX_PRINT(2, INQUIRY, false);
+	BT_MBOX_PRINT(2, CONN, false);
+	BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
+	BT_MBOX_PRINT(2, DISC, false);
+	BT_MBOX_PRINT(2, SCO_TX_ACT, false);
+	BT_MBOX_PRINT(2, SCO_RX_ACT, false);
+	BT_MBOX_PRINT(2, ESCO_RE_TX, false);
+	BT_MBOX_PRINT(2, SCO_DURATION, true);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
+
+	BT_MBOX_PRINT(3, SCO_STATE, false);
+	BT_MBOX_PRINT(3, SNIFF_STATE, false);
+	BT_MBOX_PRINT(3, A2DP_STATE, false);
+	BT_MBOX_PRINT(3, ACL_STATE, false);
+	BT_MBOX_PRINT(3, MSTR_STATE, false);
+	BT_MBOX_PRINT(3, OBX_STATE, false);
+	BT_MBOX_PRINT(3, OPEN_CON_2, false);
+	BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
+	BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
+	BT_MBOX_PRINT(3, INBAND_P, false);
+	BT_MBOX_PRINT(3, MSG_TYPE_2, false);
+	BT_MBOX_PRINT(3, SSN_2, false);
+	BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
+
+	return pos;
+}
+
+static
+int iwl_mvm_coex_dump_mbox_old(struct iwl_bt_coex_profile_notif_old *notif,
+			       char *buf, int pos, int bufsz)
+{
 	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
 
 	BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
@@ -378,25 +457,59 @@ static ssize_t iwl_dbgfs_bt_notif_read(s
 	BT_MBOX_PRINT(3, SSN_2, false);
 	BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
 
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
-			 notif->bt_status);
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
-			 notif->bt_open_conn);
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
-			 notif->bt_traffic_load);
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
-			 notif->bt_agg_traffic_load);
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
-			 notif->bt_ci_compliance);
-	pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
-			 le32_to_cpu(notif->primary_ch_lut));
-	pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
-			 le32_to_cpu(notif->secondary_ch_lut));
-	pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
-			 le32_to_cpu(notif->bt_activity_grading));
-	pos += scnprintf(buf+pos, bufsz-pos,
-			 "antenna isolation = %d CORUN LUT index = %d\n",
-			 mvm->last_ant_isol, mvm->last_corun_lut);
+	return pos;
+}
+
+static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	char *buf;
+	int ret, pos = 0, bufsz = sizeof(char) * 1024;
+
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	mutex_lock(&mvm->mutex);
+
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+		struct iwl_bt_coex_profile_notif_old *notif =
+			&mvm->last_bt_notif_old;
+
+		pos += iwl_mvm_coex_dump_mbox_old(notif, buf, pos, bufsz);
+
+		pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
+				 notif->bt_ci_compliance);
+		pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
+				 le32_to_cpu(notif->primary_ch_lut));
+		pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
+				 le32_to_cpu(notif->secondary_ch_lut));
+		pos += scnprintf(buf+pos,
+				 bufsz-pos, "bt_activity_grading = %d\n",
+				 le32_to_cpu(notif->bt_activity_grading));
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "antenna isolation = %d CORUN LUT index = %d\n",
+				 mvm->last_ant_isol, mvm->last_corun_lut);
+	} else {
+		struct iwl_bt_coex_profile_notif *notif =
+			&mvm->last_bt_notif;
+
+		pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
+
+		pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
+				 notif->bt_ci_compliance);
+		pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
+				 le32_to_cpu(notif->primary_ch_lut));
+		pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
+				 le32_to_cpu(notif->secondary_ch_lut));
+		pos += scnprintf(buf+pos,
+				 bufsz-pos, "bt_activity_grading = %d\n",
+				 le32_to_cpu(notif->bt_activity_grading));
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "antenna isolation = %d CORUN LUT index = %d\n",
+				 mvm->last_ant_isol, mvm->last_corun_lut);
+	}
 
 	mutex_unlock(&mvm->mutex);
 
@@ -411,28 +524,57 @@ static ssize_t iwl_dbgfs_bt_cmd_read(str
 				     size_t count, loff_t *ppos)
 {
 	struct iwl_mvm *mvm = file->private_data;
-	struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
 	char buf[256];
 	int bufsz = sizeof(buf);
 	int pos = 0;
 
 	mutex_lock(&mvm->mutex);
 
-	pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n");
-	pos += scnprintf(buf+pos, bufsz-pos,
-		       "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
-		       le64_to_cpu(cmd->bt_primary_ci),
-		       !!cmd->co_run_bw_primary);
-	pos += scnprintf(buf+pos, bufsz-pos,
-		       "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
-		       le64_to_cpu(cmd->bt_secondary_ci),
-		       !!cmd->co_run_bw_secondary);
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+		struct iwl_bt_coex_ci_cmd_old *cmd = &mvm->last_bt_ci_cmd_old;
 
-	pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
-	pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
-			 iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
-	pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
-			 iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "Channel inhibition CMD\n");
+		pos += scnprintf(buf+pos, bufsz-pos,
+			       "\tPrimary Channel Bitmap 0x%016llx\n",
+			       le64_to_cpu(cmd->bt_primary_ci));
+		pos += scnprintf(buf+pos, bufsz-pos,
+			       "\tSecondary Channel Bitmap 0x%016llx\n",
+			       le64_to_cpu(cmd->bt_secondary_ci));
+
+		pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
+		pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
+		pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
+
+	} else {
+		struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
+
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "Channel inhibition CMD\n");
+		pos += scnprintf(buf+pos, bufsz-pos,
+			       "\tPrimary Channel Bitmap 0x%016llx\n",
+			       le64_to_cpu(cmd->bt_primary_ci));
+		pos += scnprintf(buf+pos, bufsz-pos,
+			       "\tSecondary Channel Bitmap 0x%016llx\n",
+			       le64_to_cpu(cmd->bt_secondary_ci));
+
+		pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "\tPrimary: ACK Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "\tPrimary: CTS Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "\tSecondary: ACK Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]);
+		pos += scnprintf(buf+pos, bufsz-pos,
+				 "\tSecondary: CTS Kill Mask 0x%08x\n",
+				 iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]);
+
+	}
 
 	mutex_unlock(&mvm->mutex);
 
@@ -455,6 +597,43 @@ iwl_dbgfs_bt_tx_prio_write(struct iwl_mv
 	return count;
 }
 
+static ssize_t
+iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
+			     size_t count, loff_t *ppos)
+{
+	static const char * const modes_str[BT_FORCE_ANT_MAX] = {
+		[BT_FORCE_ANT_DIS] = "dis",
+		[BT_FORCE_ANT_AUTO] = "auto",
+		[BT_FORCE_ANT_BT] = "bt",
+		[BT_FORCE_ANT_WIFI] = "wifi",
+	};
+	int ret, bt_force_ant_mode;
+
+	for (bt_force_ant_mode = 0;
+	     bt_force_ant_mode < ARRAY_SIZE(modes_str);
+	     bt_force_ant_mode++) {
+		if (!strcmp(buf, modes_str[bt_force_ant_mode]))
+			break;
+	}
+
+	if (bt_force_ant_mode >= ARRAY_SIZE(modes_str))
+		return -EINVAL;
+
+	ret = 0;
+	mutex_lock(&mvm->mutex);
+	if (mvm->bt_force_ant_mode == bt_force_ant_mode)
+		goto out;
+
+	mvm->bt_force_ant_mode = bt_force_ant_mode;
+	IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
+		       modes_str[mvm->bt_force_ant_mode]);
+	ret = iwl_send_bt_init_conf(mvm);
+
+out:
+	mutex_unlock(&mvm->mutex);
+	return ret ?: count;
+}
+
 #define PRINT_STATS_LE32(_str, _val)					\
 			 pos += scnprintf(buf + pos, bufsz - pos,	\
 					  fmt_table, _str,		\
@@ -690,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_writ
 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
 				      size_t count, loff_t *ppos)
 {
+	int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
+	if (ret)
+		return ret;
+
 	iwl_force_nmi(mvm->trans);
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
+
 	return count;
 }
 
@@ -975,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(st
 }
 #endif
 
-#define PRINT_MVM_REF(ref) do {					\
-	if (test_bit(ref, mvm->ref_bitmap))			\
-		pos += scnprintf(buf + pos, bufsz - pos,	\
-				 "\t(0x%lx) %s\n",		\
-				 BIT(ref), #ref);		\
+#define PRINT_MVM_REF(ref) do {						\
+	if (mvm->refs[ref])						\
+		pos += scnprintf(buf + pos, bufsz - pos,		\
+				 "\t(0x%lx): %d %s\n",			\
+				 BIT(ref), mvm->refs[ref], #ref);	\
 } while (0)
 
 static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@@ -987,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(
 					size_t count, loff_t *ppos)
 {
 	struct iwl_mvm *mvm = file->private_data;
-	int pos = 0;
+	int i, pos = 0;
 	char buf[256];
 	const size_t bufsz = sizeof(buf);
+	u32 refs = 0;
 
-	pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
-			 mvm->ref_bitmap[0]);
+	for (i = 0; i < IWL_MVM_REF_COUNT; i++)
+		if (mvm->refs[i])
+			refs |= BIT(i);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
+			 refs);
 
 	PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
 	PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@@ -1018,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write
 
 	mutex_lock(&mvm->mutex);
 
-	taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
+	taken = mvm->refs[IWL_MVM_REF_USER];
 	if (value == 1 && !taken)
 		iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
 	else if (value == 0 && taken)
@@ -1054,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *fil
 	int pos = 0;
 	char buf[32];
 	const size_t bufsz = sizeof(buf);
+	int ret;
 
 	if (!mvm->dbgfs_prph_reg_addr)
 		return -EINVAL;
 
+	ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
+	if (ret)
+		return ret;
+
 	pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
 		mvm->dbgfs_prph_reg_addr,
 		iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
+
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
@@ -1071,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm
 {
 	u8 args;
 	u32 value;
+	int ret;
 
 	args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
 	/* if we only want to set the reg address - nothing more to do */
@@ -1081,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm
 	if (args != 2)
 		return -EINVAL;
 
+	ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
+	if (ret)
+		return ret;
+
 	iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
+
+	iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
 out:
 	return count;
 }
@@ -1101,6 +1305,7 @@ MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
+MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
 
@@ -1142,6 +1347,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mv
 	MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR);
+	MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
 			     S_IWUSR | S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,8 +74,7 @@ static void iwl_dbgfs_update_pm(struct i
 
 	switch (param) {
 	case MVM_DEBUGFS_PM_KEEP_ALIVE: {
-		struct ieee80211_hw *hw = mvm->hw;
-		int dtimper = hw->conf.ps_dtim_period ?: 1;
+		int dtimper = vif->bss_conf.dtim_period ?: 1;
 		int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
 
 		IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h	2014-09-28 17:29:07.000000000 -0400
@@ -72,10 +72,13 @@
  * enum iwl_bt_coex_flags - flags for BT_COEX command
  * @BT_COEX_MODE_POS:
  * @BT_COEX_MODE_MSK:
- * @BT_COEX_DISABLE:
- * @BT_COEX_2W:
- * @BT_COEX_3W:
- * @BT_COEX_NW:
+ * @BT_COEX_DISABLE_OLD:
+ * @BT_COEX_2W_OLD:
+ * @BT_COEX_3W_OLD:
+ * @BT_COEX_NW_OLD:
+ * @BT_COEX_AUTO_OLD:
+ * @BT_COEX_BT_OLD: Antenna is for BT (manufacuring tests)
+ * @BT_COEX_WIFI_OLD: Antenna is for BT (manufacuring tests)
  * @BT_COEX_SYNC2SCO:
  * @BT_COEX_CORUNNING:
  * @BT_COEX_MPLUT:
@@ -85,10 +88,13 @@
 enum iwl_bt_coex_flags {
 	BT_COEX_MODE_POS		= 3,
 	BT_COEX_MODE_MSK		= BITS(3) << BT_COEX_MODE_POS,
-	BT_COEX_DISABLE			= 0x0 << BT_COEX_MODE_POS,
-	BT_COEX_2W			= 0x1 << BT_COEX_MODE_POS,
-	BT_COEX_3W			= 0x2 << BT_COEX_MODE_POS,
-	BT_COEX_NW			= 0x3 << BT_COEX_MODE_POS,
+	BT_COEX_DISABLE_OLD		= 0x0 << BT_COEX_MODE_POS,
+	BT_COEX_2W_OLD			= 0x1 << BT_COEX_MODE_POS,
+	BT_COEX_3W_OLD			= 0x2 << BT_COEX_MODE_POS,
+	BT_COEX_NW_OLD			= 0x3 << BT_COEX_MODE_POS,
+	BT_COEX_AUTO_OLD		= 0x5 << BT_COEX_MODE_POS,
+	BT_COEX_BT_OLD			= 0x6 << BT_COEX_MODE_POS,
+	BT_COEX_WIFI_OLD		= 0x7 << BT_COEX_MODE_POS,
 	BT_COEX_SYNC2SCO		= BIT(7),
 	BT_COEX_CORUNNING		= BIT(8),
 	BT_COEX_MPLUT			= BIT(9),
@@ -151,7 +157,7 @@ enum iwl_bt_coex_lut_type {
 #define BT_REDUCED_TX_POWER_BIT BIT(7)
 
 /**
- * struct iwl_bt_coex_cmd - bt coex configuration command
+ * struct iwl_bt_coex_cmd_old - bt coex configuration command
  * @flags:&enum iwl_bt_coex_flags
  * @max_kill:
  * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
@@ -176,7 +182,7 @@ enum iwl_bt_coex_lut_type {
  *
  * The structure is used for the BT_COEX command.
  */
-struct iwl_bt_coex_cmd {
+struct iwl_bt_coex_cmd_old {
 	__le32 flags;
 	u8 max_kill;
 	u8 bt_reduced_tx_power;
@@ -202,26 +208,117 @@ struct iwl_bt_coex_cmd {
 	__le32 valid_bit_msk;
 } __packed; /* BT_COEX_CMD_API_S_VER_5 */
 
+enum iwl_bt_coex_mode {
+	BT_COEX_DISABLE			= 0x0,
+	BT_COEX_NW			= 0x1,
+	BT_COEX_BT			= 0x2,
+	BT_COEX_WIFI			= 0x3,
+}; /* BT_COEX_MODES_E */
+
+enum iwl_bt_coex_enabled_modules {
+	BT_COEX_MPLUT_ENABLED		= BIT(0),
+	BT_COEX_MPLUT_BOOST_ENABLED	= BIT(1),
+	BT_COEX_SYNC2SCO_ENABLED	= BIT(2),
+	BT_COEX_CORUN_ENABLED		= BIT(3),
+	BT_COEX_HIGH_BAND_RET		= BIT(4),
+}; /* BT_COEX_MODULES_ENABLE_E_VER_1 */
+
+/**
+ * struct iwl_bt_coex_cmd - bt coex configuration command
+ * @mode: enum %iwl_bt_coex_mode
+ * @enabled_modules: enum %iwl_bt_coex_enabled_modules
+ * @max_kill: max count of Tx retries due to kill from PTA
+ * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ *	should be set by default
+ * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ *	should be set by default
+ * @bt4_antenna_isolation_thr: antenna threshold value
+ * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency
+ * @bt4_tx_rx_max_freq0: TxRx max frequency
+ * @multiprio_lut: multi priority LUT configuration
+ * @mplut_prio_boost: BT priority boost registers
+ * @decision_lut: PTA decision LUT, per Prio-Ch
+ *
+ * The structure is used for the BT_COEX command.
+ */
+struct iwl_bt_coex_cmd {
+	__le32 mode;
+	__le32 enabled_modules;
+
+	__le32 max_kill;
+	__le32 override_primary_lut;
+	__le32 override_secondary_lut;
+	__le32 bt4_antenna_isolation_thr;
+
+	__le32 bt4_tx_tx_delta_freq_thr;
+	__le32 bt4_tx_rx_max_freq0;
+
+	__le32 multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE];
+	__le32 mplut_prio_boost[BT_COEX_BOOST_SIZE];
+
+	__le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE];
+} __packed; /* BT_COEX_CMD_API_S_VER_6 */
+
+/**
+ * struct iwl_bt_coex_corun_lut_update - bt coex update the corun lut
+ * @corun_lut20: co-running 20 MHz LUT configuration
+ * @corun_lut40: co-running 40 MHz LUT configuration
+ *
+ * The structure is used for the BT_COEX_UPDATE_CORUN_LUT command.
+ */
+struct iwl_bt_coex_corun_lut_update_cmd {
+	__le32 corun_lut20[BT_COEX_CORUN_LUT_SIZE];
+	__le32 corun_lut40[BT_COEX_CORUN_LUT_SIZE];
+} __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_sw_boost - SW boost values
+ * @wifi_tx_prio_boost: SW boost of wifi tx priority
+ * @wifi_rx_prio_boost: SW boost of wifi rx priority
+ * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK.
+ * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS.
+ */
+struct iwl_bt_coex_sw_boost {
+	__le32 wifi_tx_prio_boost;
+	__le32 wifi_rx_prio_boost;
+	__le32 kill_ack_msk;
+	__le32 kill_cts_msk;
+};
+
+/**
+ * struct iwl_bt_coex_sw_boost_update_cmd - command to update the SW boost
+ * @boost_values: check struct  %iwl_bt_coex_sw_boost - one for each channel
+ *	primary / secondary / low priority
+ */
+struct iwl_bt_coex_sw_boost_update_cmd {
+	struct iwl_bt_coex_sw_boost boost_values[3];
+} __packed; /* BT_COEX_UPDATE_SW_BOOST_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_reduced_txp_update_cmd
+ * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the
+ *	bits are the sta_id (value)
+ */
+struct iwl_bt_coex_reduced_txp_update_cmd {
+	__le32 reduced_txp;
+} __packed; /* BT_COEX_UPDATE_REDUCED_TX_POWER_API_S_VER_1 */
+
 /**
  * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
  * @bt_primary_ci:
- * @bt_secondary_ci:
- * @co_run_bw_primary:
- * @co_run_bw_secondary:
  * @primary_ch_phy_id:
+ * @bt_secondary_ci:
  * @secondary_ch_phy_id:
  *
  * Used for BT_COEX_CI command
  */
 struct iwl_bt_coex_ci_cmd {
 	__le64 bt_primary_ci;
-	__le64 bt_secondary_ci;
+	__le32 primary_ch_phy_id;
 
-	u8 co_run_bw_primary;
-	u8 co_run_bw_secondary;
-	u8 primary_ch_phy_id;
-	u8 secondary_ch_phy_id;
-} __packed; /* BT_CI_MSG_API_S_VER_1 */
+	__le64 bt_secondary_ci;
+	__le32 secondary_ch_phy_id;
+} __packed; /* BT_CI_MSG_API_S_VER_2 */
 
 #define BT_MBOX(n_dw, _msg, _pos, _nbits)	\
 	BT_MBOX##n_dw##_##_msg##_POS = (_pos),	\
@@ -288,35 +385,44 @@ enum iwl_bt_activity_grading {
 	BT_ON_NO_CONNECTION	= 1,
 	BT_LOW_TRAFFIC		= 2,
 	BT_HIGH_TRAFFIC		= 3,
+
+	BT_MAX_AG,
 }; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
 
+enum iwl_bt_ci_compliance {
+	BT_CI_COMPLIANCE_NONE		= 0,
+	BT_CI_COMPLIANCE_PRIMARY	= 1,
+	BT_CI_COMPLIANCE_SECONDARY	= 2,
+	BT_CI_COMPLIANCE_BOTH		= 3,
+}; /* BT_COEX_CI_COMPLIENCE_E_VER_1 */
+
+#define IWL_COEX_IS_TTC_ON(_ttc_rrc_status, _phy_id)	\
+		(_ttc_rrc_status & BIT(_phy_id))
+
+#define IWL_COEX_IS_RRC_ON(_ttc_rrc_status, _phy_id)	\
+		((_ttc_rrc_status >> 4) & BIT(_phy_id))
+
 /**
  * struct iwl_bt_coex_profile_notif - notification about BT coex
  * @mbox_msg: message from BT to WiFi
  * @msg_idx: the index of the message
- * @bt_status: 0 - off, 1 - on
- * @bt_open_conn: number of BT connections open
- * @bt_traffic_load: load of BT traffic
- * @bt_agg_traffic_load: aggregated load of BT traffic
- * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
- * @primary_ch_lut: LUT used for primary channel
- * @secondary_ch_lut: LUT used for secondary channel
+ * @bt_ci_compliance: enum %iwl_bt_ci_compliance
+ * @primary_ch_lut: LUT used for primary channel enum %iwl_bt_coex_lut_type
+ * @secondary_ch_lut: LUT used for secondary channel enume %iwl_bt_coex_lut_type
  * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ * @ttc_rrc_status: is TTC or RRC enabled - one bit per PHY
  */
 struct iwl_bt_coex_profile_notif {
 	__le32 mbox_msg[4];
 	__le32 msg_idx;
-	u8 bt_status;
-	u8 bt_open_conn;
-	u8 bt_traffic_load;
-	u8 bt_agg_traffic_load;
-	u8 bt_ci_compliance;
-	u8 reserved[3];
+	__le32 bt_ci_compliance;
 
 	__le32 primary_ch_lut;
 	__le32 secondary_ch_lut;
 	__le32 bt_activity_grading;
-} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */
+	u8 ttc_rrc_status;
+	u8 reserved[3];
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_4 */
 
 enum iwl_bt_coex_prio_table_event {
 	BT_COEX_PRIO_TBL_EVT_INIT_CALIB1		= 0,
@@ -355,4 +461,54 @@ struct iwl_bt_coex_prio_tbl_cmd {
 	u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
 } __packed;
 
+/**
+ * struct iwl_bt_coex_ci_cmd_old - bt coex channel inhibition command
+ * @bt_primary_ci:
+ * @bt_secondary_ci:
+ * @co_run_bw_primary:
+ * @co_run_bw_secondary:
+ * @primary_ch_phy_id:
+ * @secondary_ch_phy_id:
+ *
+ * Used for BT_COEX_CI command
+ */
+struct iwl_bt_coex_ci_cmd_old {
+	__le64 bt_primary_ci;
+	__le64 bt_secondary_ci;
+
+	u8 co_run_bw_primary;
+	u8 co_run_bw_secondary;
+	u8 primary_ch_phy_id;
+	u8 secondary_ch_phy_id;
+} __packed; /* BT_CI_MSG_API_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_profile_notif_old - notification about BT coex
+ * @mbox_msg: message from BT to WiFi
+ * @msg_idx: the index of the message
+ * @bt_status: 0 - off, 1 - on
+ * @bt_open_conn: number of BT connections open
+ * @bt_traffic_load: load of BT traffic
+ * @bt_agg_traffic_load: aggregated load of BT traffic
+ * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
+ * @primary_ch_lut: LUT used for primary channel
+ * @secondary_ch_lut: LUT used for secondary channel
+ * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ */
+struct iwl_bt_coex_profile_notif_old {
+	__le32 mbox_msg[4];
+	__le32 msg_idx;
+	u8 bt_status;
+	u8 bt_open_conn;
+	u8 bt_traffic_load;
+	u8 bt_agg_traffic_load;
+	u8 bt_ci_compliance;
+	u8 ttc_enabled;
+	__le16 reserved;
+
+	__le32 primary_ch_lut;
+	__le32 secondary_ch_lut;
+	__le32 bt_activity_grading;
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */
+
 #endif /* __fw_api_bt_coex_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api.h	2014-09-28 17:29:07.000000000 -0400
@@ -86,6 +86,8 @@ enum {
 
 #define IWL_MVM_STATION_COUNT	16
 
+#define IWL_MVM_TDLS_STA_COUNT	4
+
 /* commands */
 enum {
 	MVM_ALIVE = 0x1,
@@ -131,10 +133,12 @@ enum {
 	/* Scan offload */
 	SCAN_OFFLOAD_REQUEST_CMD = 0x51,
 	SCAN_OFFLOAD_ABORT_CMD = 0x52,
+	HOT_SPOT_CMD = 0x53,
 	SCAN_OFFLOAD_COMPLETE = 0x6D,
 	SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
 	SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
 	MATCH_FOUND_NOTIFICATION = 0xd9,
+	SCAN_ITERATION_COMPLETE = 0xe7,
 
 	/* Phy */
 	PHY_CONFIGURATION_CMD = 0x6a,
@@ -163,7 +167,6 @@ enum {
 	BEACON_NOTIFICATION = 0x90,
 	BEACON_TEMPLATE_CMD = 0x91,
 	TX_ANT_CONFIGURATION_CMD = 0x98,
-	BT_CONFIG = 0x9b,
 	STATISTICS_NOTIFICATION = 0x9d,
 	EOSP_NOTIFICATION = 0x9e,
 	REDUCE_TX_POWER_CMD = 0x9f,
@@ -185,6 +188,10 @@ enum {
 	BT_COEX_PRIO_TABLE = 0xcc,
 	BT_COEX_PROT_ENV = 0xcd,
 	BT_PROFILE_NOTIFICATION = 0xce,
+	BT_CONFIG = 0x9b,
+	BT_COEX_UPDATE_SW_BOOST = 0x5a,
+	BT_COEX_UPDATE_CORUN_LUT = 0x5b,
+	BT_COEX_UPDATE_REDUCED_TXP = 0x5c,
 	BT_COEX_CI = 0x5d,
 
 	REPLY_SF_CFG_CMD = 0xd1,
@@ -534,6 +541,9 @@ enum iwl_time_event_type {
 	/* WiDi Sync Events */
 	TE_WIDI_TX_SYNC,
 
+	/* Channel Switch NoA */
+	TE_P2P_GO_CSA_NOA,
+
 	TE_MAX
 }; /* MAC_EVENT_TYPE_API_E_VER_1 */
 
@@ -901,6 +911,72 @@ struct iwl_phy_context_cmd {
 	__le32 dsp_cfg_flags;
 } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
 
+/*
+ * Aux ROC command
+ *
+ * Command requests the firmware to create a time event for a certain duration
+ * and remain on the given channel. This is done by using the Aux framework in
+ * the FW.
+ * The command was first used for Hot Spot issues - but can be used regardless
+ * to Hot Spot.
+ *
+ * ( HOT_SPOT_CMD 0x53 )
+ *
+ * @id_and_color: ID and color of the MAC
+ * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
+ *	event_unique_id should be the id of the time event assigned by ucode.
+ *	Otherwise ignore the event_unique_id.
+ * @sta_id_and_color: station id and color, resumed during "Remain On Channel"
+ *	activity.
+ * @channel_info: channel info
+ * @node_addr: Our MAC Address
+ * @reserved: reserved for alignment
+ * @apply_time: GP2 value to start (should always be the current GP2 value)
+ * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
+ *	time by which start of the event is allowed to be postponed.
+ * @duration: event duration in TU To calculate event duration:
+ *	timeEventDuration = min(duration, remainingQuota)
+ */
+struct iwl_hs20_roc_req {
+	/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
+	__le32 id_and_color;
+	__le32 action;
+	__le32 event_unique_id;
+	__le32 sta_id_and_color;
+	struct iwl_fw_channel_info channel_info;
+	u8 node_addr[ETH_ALEN];
+	__le16 reserved;
+	__le32 apply_time;
+	__le32 apply_time_max_delay;
+	__le32 duration;
+} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
+
+/*
+ * values for AUX ROC result values
+ */
+enum iwl_mvm_hot_spot {
+	HOT_SPOT_RSP_STATUS_OK,
+	HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
+	HOT_SPOT_MAX_NUM_OF_SESSIONS,
+};
+
+/*
+ * Aux ROC command response
+ *
+ * In response to iwl_hs20_roc_req the FW sends this command to notify the
+ * driver the uid of the timevent.
+ *
+ * ( HOT_SPOT_CMD 0x53 )
+ *
+ * @event_unique_id: Unique ID of time event assigned by ucode
+ * @status: Return status 0 is success, all the rest used for specific errors
+ */
+struct iwl_hs20_roc_res {
+	__le32 event_unique_id;
+	__le32 status;
+} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
+
 #define IWL_RX_INFO_PHY_CNT 8
 #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
 #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
@@ -1487,14 +1563,14 @@ enum iwl_sf_scenario {
 
 /**
  * Smart Fifo configuration command.
- * @state: smart fifo state, types listed in iwl_sf_sate.
+ * @state: smart fifo state, types listed in enum %iwl_sf_sate.
  * @watermark: Minimum allowed availabe free space in RXF for transient state.
  * @long_delay_timeouts: aging and idle timer values for each scenario
  * in long delay state.
  * @full_on_timeouts: timer values for each scenario in full on state.
  */
 struct iwl_sf_cfg_cmd {
-	enum iwl_sf_state state;
+	__le32 state;
 	__le32 watermark[SF_TRANSIENT_STATES_NUMBER];
 	__le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
 	__le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h	2014-09-28 17:29:07.000000000 -0400
@@ -336,7 +336,7 @@ struct iwl_beacon_filter_cmd {
 #define IWL_BF_DEBUG_FLAG_D0I3 0
 
 #define IWL_BF_ESCAPE_TIMER_DEFAULT 50
-#define IWL_BF_ESCAPE_TIMER_D0I3 1024
+#define IWL_BF_ESCAPE_TIMER_D0I3 0
 #define IWL_BF_ESCAPE_TIMER_MAX 1024
 #define IWL_BF_ESCAPE_TIMER_MIN 0
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h	2014-09-28 17:29:07.000000000 -0400
@@ -170,18 +170,12 @@ enum iwl_scan_type {
 }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
 
 /**
- * Maximal number of channels to scan
- * it should be equal to:
- * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000)
- */
-#define MAX_NUM_SCAN_CHANNELS 50
-
-/**
  * struct iwl_scan_cmd - scan request command
  * ( SCAN_REQUEST_CMD = 0x80 )
  * @len: command length in bytes
  * @scan_flags: scan flags from SCAN_FLAGS_*
- * @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS)
+ * @channel_count: num of channels in channel list
+ *	(1 - ucode_capa.n_scan_channels)
  * @quiet_time: in msecs, dwell this time for active scan on quiet channels
  * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
  *	this number of packets were received (typically 1)
@@ -345,7 +339,7 @@ struct iwl_scan_results_notif {
  * @last_channel: last channel that was scanned
  * @tsf_low: TSF timer (lower half) in usecs
  * @tsf_high: TSF timer (higher half) in usecs
- * @results: all scan results, only "scanned_channels" of them are valid
+ * @results: array of scan results, only "scanned_channels" of them are valid
  */
 struct iwl_scan_complete_notif {
 	u8 scanned_channels;
@@ -354,11 +348,10 @@ struct iwl_scan_complete_notif {
 	u8 last_channel;
 	__le32 tsf_low;
 	__le32 tsf_high;
-	struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS];
+	struct iwl_scan_results_notif results[];
 } __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
 
 /* scan offload */
-#define IWL_MAX_SCAN_CHANNELS		40
 #define IWL_SCAN_MAX_BLACKLIST_LEN	64
 #define IWL_SCAN_SHORT_BLACKLIST_LEN	16
 #define IWL_SCAN_MAX_PROFILES		11
@@ -423,36 +416,24 @@ enum iwl_scan_offload_channel_flags {
 	IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL	= BIT(25),
 };
 
-/**
- * iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S
- * @type:		bitmap - see enum iwl_scan_offload_channel_flags.
- *			0:	passive (0) or active (1) scan.
- *			1-20:	directed scan to i'th ssid.
- *			22:	channel width configuation - 1 for narrow.
- *			24:	full scan.
- *			25:	partial scan.
- * @channel_number:	channel number 1-13 etc.
- * @iter_count:		repetition count for the channel.
- * @iter_interval:	interval between two innteration on one channel.
- * @dwell_time:	entry 0 - active scan, entry 1 - passive scan.
+/* channel configuration for struct iwl_scan_offload_cfg. Each channels needs:
+ * __le32 type:	bitmap; bits 1-20 are for directed scan to i'th ssid and
+ *	see enum iwl_scan_offload_channel_flags.
+ * __le16 channel_number: channel number 1-13 etc.
+ * __le16 iter_count: repetition count for the channel.
+ * __le32 iter_interval: interval between two innteration on one channel.
+ * u8 active_dwell.
+ * u8 passive_dwell.
  */
-struct iwl_scan_channel_cfg {
-	__le32 type[IWL_MAX_SCAN_CHANNELS];
-	__le16 channel_number[IWL_MAX_SCAN_CHANNELS];
-	__le16 iter_count[IWL_MAX_SCAN_CHANNELS];
-	__le32 iter_interval[IWL_MAX_SCAN_CHANNELS];
-	u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2];
-} __packed;
+#define IWL_SCAN_CHAN_SIZE 14
 
 /**
  * iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S
  * @scan_cmd:		scan command fixed part
- * @channel_cfg:	scan channel configuration
- * @data:		probe request frames (one per band)
+ * @data:		scan channel configuration and probe request frames
  */
 struct iwl_scan_offload_cfg {
 	struct iwl_scan_offload_cmd scan_cmd;
-	struct iwl_scan_channel_cfg channel_cfg;
 	u8 data[0];
 } __packed;
 
@@ -528,7 +509,7 @@ struct iwl_scan_offload_profile_cfg {
  * @full_scan_mul:	number of partial scans before each full scan
  */
 struct iwl_scan_offload_schedule {
-	u16 delay;
+	__le16 delay;
 	u8 iterations;
 	u8 full_scan_mul;
 } __packed;
@@ -601,4 +582,211 @@ struct iwl_sched_scan_results {
 	u8 reserved;
 };
 
+/* Unified LMAC scan API */
+
+#define IWL_MVM_BASIC_PASSIVE_DWELL 110
+
+/**
+ * iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
+ * @tx_flags: combination of TX_CMD_FLG_*
+ * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
+ *	cleared. Combination of RATE_MCS_*
+ * @sta_id: index of destination station in FW station table
+ * @reserved: for alignment and future use
+ */
+struct iwl_scan_req_tx_cmd {
+	__le32 tx_flags;
+	__le32 rate_n_flags;
+	u8 sta_id;
+	u8 reserved[3];
+} __packed;
+
+enum iwl_scan_channel_flags_lmac {
+	IWL_UNIFIED_SCAN_CHANNEL_FULL		= BIT(27),
+	IWL_UNIFIED_SCAN_CHANNEL_PARTIAL	= BIT(28),
+};
+
+/**
+ * iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
+ * @flags:		bits 1-20: directed scan to i'th ssid
+ *			other bits &enum iwl_scan_channel_flags_lmac
+ * @channel_number:	channel number 1-13 etc
+ * @iter_count:		scan iteration on this channel
+ * @iter_interval:	interval in seconds between iterations on one channel
+ */
+struct iwl_scan_channel_cfg_lmac {
+	__le32 flags;
+	__le16 channel_num;
+	__le16 iter_count;
+	__le32 iter_interval;
+} __packed;
+
+/*
+ * iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
+ * @offset: offset in the data block
+ * @len: length of the segment
+ */
+struct iwl_scan_probe_segment {
+	__le16 offset;
+	__le16 len;
+} __packed;
+
+/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_2
+ * @mac_header: first (and common) part of the probe
+ * @band_data: band specific data
+ * @common_data: last (and common) part of the probe
+ * @buf: raw data block
+ */
+struct iwl_scan_probe_req {
+	struct iwl_scan_probe_segment mac_header;
+	struct iwl_scan_probe_segment band_data[2];
+	struct iwl_scan_probe_segment common_data;
+	u8 buf[SCAN_OFFLOAD_PROBE_REQ_SIZE];
+} __packed;
+
+enum iwl_scan_channel_flags {
+	IWL_SCAN_CHANNEL_FLAG_EBS		= BIT(0),
+	IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE	= BIT(1),
+	IWL_SCAN_CHANNEL_FLAG_CACHE_ADD		= BIT(2),
+};
+
+/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
+ * @flags: enum iwl_scan_channel_flgs
+ * @non_ebs_ratio: how many regular scan iteration before EBS
+ */
+struct iwl_scan_channel_opt {
+	__le16 flags;
+	__le16 non_ebs_ratio;
+} __packed;
+
+/**
+ * iwl_mvm_lmac_scan_flags
+ * @IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL: pass all beacons and probe responses
+ *	without filtering.
+ * @IWL_MVM_LMAC_SCAN_FLAG_PASSIVE: force passive scan on all channels
+ * @IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION: single channel scan
+ * @IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE: send iteration complete notification
+ * @IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS multiple SSID matching
+ * @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented
+ */
+enum iwl_mvm_lmac_scan_flags {
+	IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL		= BIT(0),
+	IWL_MVM_LMAC_SCAN_FLAG_PASSIVE		= BIT(1),
+	IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION	= BIT(2),
+	IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE	= BIT(3),
+	IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS	= BIT(4),
+	IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED	= BIT(5),
+};
+
+enum iwl_scan_priority {
+	IWL_SCAN_PRIORITY_LOW,
+	IWL_SCAN_PRIORITY_MEDIUM,
+	IWL_SCAN_PRIORITY_HIGH,
+};
+
+/**
+ * iwl_scan_req_unified_lmac - SCAN_REQUEST_CMD_API_S_VER_1
+ * @reserved1: for alignment and future use
+ * @channel_num: num of channels to scan
+ * @active-dwell: dwell time for active channels
+ * @passive-dwell: dwell time for passive channels
+ * @fragmented-dwell: dwell time for fragmented passive scan
+ * @reserved2: for alignment and future use
+ * @rx_chain_selct: PHY_RX_CHAIN_* flags
+ * @scan_flags: &enum iwl_mvm_lmac_scan_flags
+ * @max_out_time: max time (in TU) to be out of associated channel
+ * @suspend_time: pause scan this long (TUs) when returning to service channel
+ * @flags: RXON flags
+ * @filter_flags: RXON filter
+ * @tx_cmd: tx command for active scan; for 2GHz and for 5GHz
+ * @direct_scan: list of SSIDs for directed active scan
+ * @scan_prio: enum iwl_scan_priority
+ * @iter_num: number of scan iterations
+ * @delay: delay in seconds before first iteration
+ * @schedule: two scheduling plans. The first one is finite, the second one can
+ *	be infinite.
+ * @channel_opt: channel optimization options, for full and partial scan
+ * @data: channel configuration and probe request packet.
+ */
+struct iwl_scan_req_unified_lmac {
+	/* SCAN_REQUEST_FIXED_PART_API_S_VER_7 */
+	__le32 reserved1;
+	u8 n_channels;
+	u8 active_dwell;
+	u8 passive_dwell;
+	u8 fragmented_dwell;
+	__le16 reserved2;
+	__le16 rx_chain_select;
+	__le32 scan_flags;
+	__le32 max_out_time;
+	__le32 suspend_time;
+	/* RX_ON_FLAGS_API_S_VER_1 */
+	__le32 flags;
+	__le32 filter_flags;
+	struct iwl_scan_req_tx_cmd tx_cmd[2];
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
+	__le32 scan_prio;
+	/* SCAN_REQ_PERIODIC_PARAMS_API_S */
+	__le32 iter_num;
+	__le32 delay;
+	struct iwl_scan_offload_schedule schedule[2];
+	struct iwl_scan_channel_opt channel_opt[2];
+	u8 data[];
+} __packed;
+
+/**
+ * struct iwl_lmac_scan_results_notif - scan results for one channel -
+ *	SCAN_RESULT_NTF_API_S_VER_3
+ * @channel: which channel the results are from
+ * @band: 0 for 5.2 GHz, 1 for 2.4 GHz
+ * @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
+ * @num_probe_not_sent: # of request that weren't sent due to not enough time
+ * @duration: duration spent in channel, in usecs
+ */
+struct iwl_lmac_scan_results_notif {
+	u8 channel;
+	u8 band;
+	u8 probe_status;
+	u8 num_probe_not_sent;
+	__le32 duration;
+} __packed;
+
+/**
+ * struct iwl_lmac_scan_complete_notif - notifies end of scanning (all channels)
+ *	SCAN_COMPLETE_NTF_API_S_VER_3
+ * @scanned_channels: number of channels scanned (and number of valid results)
+ * @status: one of SCAN_COMP_STATUS_*
+ * @bt_status: BT on/off status
+ * @last_channel: last channel that was scanned
+ * @tsf_low: TSF timer (lower half) in usecs
+ * @tsf_high: TSF timer (higher half) in usecs
+ * @results: an array of scan results, only "scanned_channels" of them are valid
+ */
+struct iwl_lmac_scan_complete_notif {
+	u8 scanned_channels;
+	u8 status;
+	u8 bt_status;
+	u8 last_channel;
+	__le32 tsf_low;
+	__le32 tsf_high;
+	struct iwl_scan_results_notif results[];
+} __packed;
+
+/**
+ * iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
+ * @last_schedule_line: last schedule line executed (fast or regular)
+ * @last_schedule_iteration: last scan iteration executed before scan abort
+ * @status: enum iwl_scan_offload_complete_status
+ * @ebs_status: EBS success status &enum iwl_scan_ebs_status
+ * @time_after_last_iter; time in seconds elapsed after last iteration
+ */
+struct iwl_periodic_scan_complete {
+	u8 last_schedule_line;
+	u8 last_schedule_iteration;
+	u8 status;
+	u8 ebs_status;
+	__le32 time_after_last_iter;
+	__le32 reserved;
+} __packed;
+
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h	2014-09-28 17:29:07.000000000 -0400
@@ -67,7 +67,7 @@
  * enum iwl_sta_flags - flags for the ADD_STA host command
  * @STA_FLG_REDUCED_TX_PWR_CTRL:
  * @STA_FLG_REDUCED_TX_PWR_DATA:
- * @STA_FLG_FLG_ANT_MSK: Antenna selection
+ * @STA_FLG_DISABLE_TX: set if TX should be disabled
  * @STA_FLG_PS: set if STA is in Power Save
  * @STA_FLG_INVALID: set if STA is invalid
  * @STA_FLG_DLP_EN: Direct Link Protocol is enabled
@@ -91,10 +91,7 @@ enum iwl_sta_flags {
 	STA_FLG_REDUCED_TX_PWR_CTRL	= BIT(3),
 	STA_FLG_REDUCED_TX_PWR_DATA	= BIT(6),
 
-	STA_FLG_FLG_ANT_A		= (1 << 4),
-	STA_FLG_FLG_ANT_B		= (2 << 4),
-	STA_FLG_FLG_ANT_MSK		= (STA_FLG_FLG_ANT_A |
-					   STA_FLG_FLG_ANT_B),
+	STA_FLG_DISABLE_TX		= BIT(4),
 
 	STA_FLG_PS			= BIT(8),
 	STA_FLG_DRAIN_FLOW		= BIT(12),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,10 +69,8 @@
  * @TX_CMD_FLG_ACK: expect ACK from receiving station
  * @TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.
  *	Otherwise, use rate_n_flags from the TX command
- * @TX_CMD_FLG_BA: this frame is a block ack
  * @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
  *	Must set TX_CMD_FLG_ACK with this flag.
- * @TX_CMD_FLG_TXOP_PROT: protect frame with full TXOP protection
  * @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
  * @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
  * @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
@@ -82,12 +80,10 @@
  * @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.
  *	Should be set for mgmt, non-QOS data, mcast, bcast and in scan command
  * @TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU
- * @TX_CMD_FLG_NEXT_FRAME: this frame includes information of the next frame
  * @TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame
  *	Should be set for beacons and probe responses
  * @TX_CMD_FLG_CALIB: activate PA TX power calibrations
  * @TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count
- * @TX_CMD_FLG_AGG_START: allow this frame to start aggregation
  * @TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.
  *	Should be set for 26/30 length MAC headers
  * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
@@ -103,7 +99,6 @@ enum iwl_tx_flags {
 	TX_CMD_FLG_PROT_REQUIRE		= BIT(0),
 	TX_CMD_FLG_ACK			= BIT(3),
 	TX_CMD_FLG_STA_RATE		= BIT(4),
-	TX_CMD_FLG_BA			= BIT(5),
 	TX_CMD_FLG_BAR			= BIT(6),
 	TX_CMD_FLG_TXOP_PROT		= BIT(7),
 	TX_CMD_FLG_VHT_NDPA		= BIT(8),
@@ -113,11 +108,9 @@ enum iwl_tx_flags {
 	TX_CMD_FLG_BT_DIS		= BIT(12),
 	TX_CMD_FLG_SEQ_CTL		= BIT(13),
 	TX_CMD_FLG_MORE_FRAG		= BIT(14),
-	TX_CMD_FLG_NEXT_FRAME		= BIT(15),
 	TX_CMD_FLG_TSF			= BIT(16),
 	TX_CMD_FLG_CALIB		= BIT(17),
 	TX_CMD_FLG_KEEP_SEQ_CTL		= BIT(18),
-	TX_CMD_FLG_AGG_START		= BIT(19),
 	TX_CMD_FLG_MH_PAD		= BIT(20),
 	TX_CMD_FLG_RESP_TO_DRV		= BIT(21),
 	TX_CMD_FLG_CCMP_AGG		= BIT(22),
@@ -191,8 +184,6 @@ enum iwl_tx_flags {
  * struct iwl_tx_cmd - TX command struct to FW
  * ( TX_CMD = 0x1c )
  * @len: in bytes of the payload, see below for details
- * @next_frame_len: same as len, but for next frame (0 if not applicable)
- *	Used for fragmentation and bursting, but not in 11n aggregation.
  * @tx_flags: combination of TX_CMD_FLG_*
  * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
  *	cleared. Combination of RATE_MCS_*
@@ -210,8 +201,6 @@ enum iwl_tx_flags {
  * @data_retry_limit: max attempts to send the data packet
  * @tid_spec: TID/tspec
  * @pm_frame_timeout: PM TX frame timeout
- * @driver_txop: duration od EDCA TXOP, in 32-usec units. Set this if not
- *	specified by HCCA protocol
  *
  * The byte count (both len and next_frame_len) includes MAC header
  * (24/26/30/32 bytes)
@@ -241,8 +230,7 @@ struct iwl_tx_cmd {
 	u8 initial_rate_index;
 	u8 reserved2;
 	u8 key[16];
-	__le16 next_frame_flags;
-	__le16 reserved3;
+	__le32 reserved3;
 	__le32 life_time;
 	__le32 dram_lsb_ptr;
 	u8 dram_msb_ptr;
@@ -250,7 +238,7 @@ struct iwl_tx_cmd {
 	u8 data_retry_limit;
 	u8 tid_tspec;
 	__le16 pm_frame_timeout;
-	__le16 driver_txop;
+	__le16 reserved4;
 	u8 payload[0];
 	struct ieee80211_hdr hdr[0];
 } __packed; /* TX_CMD_API_S_VER_3 */
@@ -549,6 +537,20 @@ struct iwl_beacon_notif {
 } __packed;
 
 /**
+ * struct iwl_extended_beacon_notif - notifies about beacon transmission
+ * @beacon_notify_hdr: tx response command associated with the beacon
+ * @tsf: last beacon tsf
+ * @ibss_mgr_status: whether IBSS is manager
+ * @gp2: last beacon time in gp2
+ */
+struct iwl_extended_beacon_notif {
+	struct iwl_mvm_tx_resp beacon_notify_hdr;
+	__le64 tsf;
+	__le32 ibss_mgr_status;
+	__le32 gp2;
+} __packed; /* BEACON_NTFY_API_S_VER_5 */
+
+/**
  * enum iwl_dump_control - dump (flush) control flags
  * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
  *	and the TFD queues are empty.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,6 +80,8 @@
 #include "fw-api-scan.h"
 #include "iwl-phy-db.h"
 #include "testmode.h"
+#include "iwl-fw-error-dump.h"
+#include "iwl-prph.h"
 
 static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
 	{
@@ -209,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, en
 		return;
 
 	IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
-	WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap));
+	spin_lock_bh(&mvm->refs_lock);
+	mvm->refs[ref_type]++;
+	spin_unlock_bh(&mvm->refs_lock);
 	iwl_trans_ref(mvm->trans);
 }
 
@@ -219,26 +223,47 @@ void iwl_mvm_unref(struct iwl_mvm *mvm,
 		return;
 
 	IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
-	WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap));
+	spin_lock_bh(&mvm->refs_lock);
+	WARN_ON(!mvm->refs[ref_type]--);
+	spin_unlock_bh(&mvm->refs_lock);
 	iwl_trans_unref(mvm->trans);
 }
 
-static void
-iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref)
+static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
+				     enum iwl_mvm_ref_type except_ref)
 {
-	int i;
+	int i, j;
 
 	if (!iwl_mvm_is_d0i3_supported(mvm))
 		return;
 
-	for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) {
-		if (ref == i)
+	spin_lock_bh(&mvm->refs_lock);
+	for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
+		if (except_ref == i || !mvm->refs[i])
 			continue;
 
-		IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i);
-		clear_bit(i, mvm->ref_bitmap);
-		iwl_trans_unref(mvm->trans);
+		IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
+			      i, mvm->refs[i]);
+		for (j = 0; j < mvm->refs[i]; j++)
+			iwl_trans_unref(mvm->trans);
+		mvm->refs[i] = 0;
 	}
+	spin_unlock_bh(&mvm->refs_lock);
+}
+
+int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
+{
+	iwl_mvm_ref(mvm, ref_type);
+
+	if (!wait_event_timeout(mvm->d0i3_exit_waitq,
+				!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status),
+				HZ)) {
+		WARN_ON_ONCE(1);
+		iwl_mvm_unref(mvm, ref_type);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
@@ -276,6 +301,7 @@ int iwl_mvm_mac_setup_register(struct iw
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_TIMING_BEACON_ONLY |
 		    IEEE80211_HW_CONNECTION_MONITOR |
+		    IEEE80211_HW_CHANCTX_STA_CSA |
 		    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 		    IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -303,6 +329,9 @@ int iwl_mvm_mac_setup_register(struct iw
 		hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
 	}
 
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
+
 	hw->sta_data_size = sizeof(struct iwl_mvm_sta);
 	hw->vif_data_size = sizeof(struct iwl_mvm_vif);
 	hw->chanctx_data_size = sizeof(u16);
@@ -367,13 +396,17 @@ int iwl_mvm_mac_setup_register(struct iw
 	else
 		hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
-	hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-	hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
-	hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
-	/* we create the 802.11 header and zero length SSID IE. */
-	hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
+	if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) {
+		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+		hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
+		hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
+		/* we create the 802.11 header and zero length SSID IE. */
+		hw->wiphy->max_sched_scan_ie_len =
+			SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
+	}
 
 	hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
+			       NL80211_FEATURE_LOW_PRIORITY_SCAN |
 			       NL80211_FEATURE_P2P_GO_OPPPS;
 
 	mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
@@ -549,9 +582,6 @@ static int iwl_mvm_mac_ampdu_action(stru
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);
-		tx_agg_ref = true;
-
 		/*
 		 * for tx start, wait synchronously until D0i3 exit to
 		 * get the correct sequence number for the tid.
@@ -560,12 +590,11 @@ static int iwl_mvm_mac_ampdu_action(stru
 		 * by the trans layer (unlike commands), so wait for
 		 * d0i3 exit in these cases as well.
 		 */
-		if (!wait_event_timeout(mvm->d0i3_exit_waitq,
-			  !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {
-			WARN_ON_ONCE(1);
-			iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
-			return -EIO;
-		}
+		ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG);
+		if (ret)
+			return ret;
+
+		tx_agg_ref = true;
 		break;
 	default:
 		break;
@@ -635,7 +664,105 @@ static void iwl_mvm_cleanup_iterator(voi
 	spin_unlock_bh(&mvm->time_event_lock);
 
 	mvmvif->phy_ctxt = NULL;
+	memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
+{
+	struct iwl_fw_error_dump_file *dump_file;
+	struct iwl_fw_error_dump_data *dump_data;
+	struct iwl_fw_error_dump_info *dump_info;
+	struct iwl_mvm_dump_ptrs *fw_error_dump;
+	const struct fw_img *img;
+	u32 sram_len, sram_ofs;
+	u32 file_len, rxf_len;
+	unsigned long flags;
+	int reg_val;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	if (mvm->fw_error_dump)
+		return;
+
+	fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
+	if (!fw_error_dump)
+		return;
+
+	img = &mvm->fw->img[mvm->cur_ucode];
+	sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+	sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
+
+	/* reading buffer size */
+	reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR);
+	rxf_len = (reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS;
+
+	/* the register holds the value divided by 128 */
+	rxf_len = rxf_len << 7;
+
+	file_len = sizeof(*dump_file) +
+		   sizeof(*dump_data) * 3 +
+		   sram_len +
+		   rxf_len +
+		   sizeof(*dump_info);
+
+	dump_file = vzalloc(file_len);
+	if (!dump_file) {
+		kfree(fw_error_dump);
+		return;
+	}
+
+	fw_error_dump->op_mode_ptr = dump_file;
+
+	dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
+	dump_data = (void *)dump_file->data;
+
+	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
+	dump_data->len = cpu_to_le32(sizeof(*dump_info));
+	dump_info = (void *) dump_data->data;
+	dump_info->device_family =
+		mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
+			cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
+			cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
+	memcpy(dump_info->fw_human_readable, mvm->fw->human_readable,
+	       sizeof(dump_info->fw_human_readable));
+	strncpy(dump_info->dev_human_readable, mvm->cfg->name,
+		sizeof(dump_info->dev_human_readable));
+	strncpy(dump_info->bus_human_readable, mvm->dev->bus->name,
+		sizeof(dump_info->bus_human_readable));
+
+	dump_data = iwl_fw_error_next_data(dump_data);
+	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
+	dump_data->len = cpu_to_le32(rxf_len);
+
+	if (iwl_trans_grab_nic_access(mvm->trans, false, &flags)) {
+		u32 *rxf = (void *)dump_data->data;
+		int i;
+
+		for (i = 0; i < (rxf_len / sizeof(u32)); i++) {
+			iwl_trans_write_prph(mvm->trans,
+					     RXF_LD_FENCE_OFFSET_ADDR,
+					     i * sizeof(u32));
+			rxf[i] = iwl_trans_read_prph(mvm->trans,
+						     RXF_FIFO_RD_FENCE_ADDR);
+		}
+		iwl_trans_release_nic_access(mvm->trans, &flags);
+	}
+
+	dump_data = iwl_fw_error_next_data(dump_data);
+	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
+	dump_data->len = cpu_to_le32(sram_len);
+	iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
+				 sram_len);
+
+	fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
+	fw_error_dump->op_mode_len = file_len;
+	if (fw_error_dump->trans_ptr)
+		file_len += fw_error_dump->trans_ptr->len;
+	dump_file->file_len = cpu_to_le32(file_len);
+	mvm->fw_error_dump = fw_error_dump;
 }
+#endif
 
 static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 {
@@ -665,6 +792,12 @@ static void iwl_mvm_restart_cleanup(stru
 	iwl_mvm_reset_phy_ctxts(mvm);
 	memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
 	memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
+	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+	memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
+	memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
+	memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
+	memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk));
+	memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk));
 
 	ieee80211_wake_queues(mvm->hw);
 
@@ -688,6 +821,16 @@ static int iwl_mvm_mac_start(struct ieee
 		iwl_mvm_restart_cleanup(mvm);
 
 	ret = iwl_mvm_up(mvm);
+
+	if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+		/* Something went wrong - we need to finish some cleanup
+		 * that normally iwl_mvm_mac_restart_complete() below
+		 * would do.
+		 */
+		clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+		iwl_mvm_d0i3_enable_tx(mvm, NULL);
+	}
+
 	mutex_unlock(&mvm->mutex);
 
 	return ret;
@@ -786,6 +929,15 @@ static int iwl_mvm_mac_add_interface(str
 	int ret;
 
 	/*
+	 * make sure D0i3 exit is completed, otherwise a target access
+	 * during tx queue configuration could be done when still in
+	 * D0i3 state.
+	 */
+	ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF);
+	if (ret)
+		return ret;
+
+	/*
 	 * Not much to do here. The stack will not allow interface
 	 * types or combinations that we didn't advertise, so we
 	 * don't really have to check the types.
@@ -899,6 +1051,8 @@ static int iwl_mvm_mac_add_interface(str
  out_unlock:
 	mutex_unlock(&mvm->mutex);
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF);
+
 	return ret;
 }
 
@@ -1255,6 +1409,28 @@ static inline int iwl_mvm_configure_bcas
 }
 #endif
 
+static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
+{
+	struct ieee80211_sta *sta;
+	struct iwl_mvm_sta *mvmsta;
+	int i;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+						lockdep_is_held(&mvm->mutex));
+		if (!sta || IS_ERR(sta) || !sta->tdls)
+			continue;
+
+		mvmsta = iwl_mvm_sta_from_mac80211(sta);
+		ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
+				NL80211_TDLS_TEARDOWN,
+				WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
+				GFP_KERNEL);
+	}
+}
+
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 					     struct ieee80211_vif *vif,
 					     struct ieee80211_bss_conf *bss_conf,
@@ -1278,7 +1454,7 @@ static void iwl_mvm_bss_info_changed_sta
 	if (changes & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
 			/* add quota for this interface */
-			ret = iwl_mvm_update_quotas(mvm, vif);
+			ret = iwl_mvm_update_quotas(mvm, NULL);
 			if (ret) {
 				IWL_ERR(mvm, "failed to update quotas\n");
 				return;
@@ -1350,14 +1526,19 @@ static void iwl_mvm_bss_info_changed_sta
 		 */
 		iwl_mvm_remove_time_event(mvm, mvmvif,
 					  &mvmvif->time_event_data);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INFO) {
 		iwl_mvm_sf_update(mvm, vif, false);
 		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
-	} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
-			      BSS_CHANGED_QOS)) {
+	}
+
+	if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) {
 		ret = iwl_mvm_power_update_mac(mvm);
 		if (ret)
 			IWL_ERR(mvm, "failed to update power mode\n");
 	}
+
 	if (changes & BSS_CHANGED_TXPOWER) {
 		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
 				bss_conf->txpower);
@@ -1389,6 +1570,14 @@ static int iwl_mvm_start_ap_ibss(struct
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int ret;
 
+	/*
+	 * iwl_mvm_mac_ctxt_add() might read directly from the device
+	 * (the system time), so make sure it is available.
+	 */
+	ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
+	if (ret)
+		return ret;
+
 	mutex_lock(&mvm->mutex);
 
 	/* Send the beacon template */
@@ -1425,7 +1614,7 @@ static int iwl_mvm_start_ap_ibss(struct
 	/* power updated needs to be done before quotas */
 	iwl_mvm_power_update_mac(mvm);
 
-	ret = iwl_mvm_update_quotas(mvm, vif);
+	ret = iwl_mvm_update_quotas(mvm, NULL);
 	if (ret)
 		goto out_quota_failed;
 
@@ -1437,6 +1626,10 @@ static int iwl_mvm_start_ap_ibss(struct
 
 	iwl_mvm_bt_coex_vif_change(mvm);
 
+	/* we don't support TDLS during DCM */
+	if (iwl_mvm_phy_ctx_count(mvm) > 1)
+		iwl_mvm_teardown_tdls_peers(mvm);
+
 	mutex_unlock(&mvm->mutex);
 	return 0;
 
@@ -1450,6 +1643,7 @@ out_remove:
 	iwl_mvm_mac_ctxt_remove(mvm, vif);
 out_unlock:
 	mutex_unlock(&mvm->mutex);
+	iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
 	return ret;
 }
 
@@ -1463,7 +1657,20 @@ static void iwl_mvm_stop_ap_ibss(struct
 
 	mutex_lock(&mvm->mutex);
 
+	/* Handle AP stop while in CSA */
+	if (rcu_access_pointer(mvm->csa_vif) == vif) {
+		iwl_mvm_remove_time_event(mvm, mvmvif,
+					  &mvmvif->time_event_data);
+		RCU_INIT_POINTER(mvm->csa_vif, NULL);
+	}
+
+	if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
+		RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
+		mvm->csa_tx_block_bcn_timeout = 0;
+	}
+
 	mvmvif->ap_ibss_active = false;
+	mvm->ap_last_beacon_gp2 = 0;
 
 	iwl_mvm_bt_coex_vif_change(mvm);
 
@@ -1514,10 +1721,18 @@ static void iwl_mvm_bss_info_changed(str
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
+	/*
+	 * iwl_mvm_bss_info_changed_station() might call
+	 * iwl_mvm_protect_session(), which reads directly from
+	 * the device (the system time), so make sure it is available.
+	 */
+	if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
+		return;
+
 	mutex_lock(&mvm->mutex);
 
 	if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
-		iwl_mvm_sched_scan_stop(mvm, true);
+		iwl_mvm_scan_offload_stop(mvm, true);
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
@@ -1533,44 +1748,84 @@ static void iwl_mvm_bss_info_changed(str
 	}
 
 	mutex_unlock(&mvm->mutex);
+	iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
 }
 
+static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
+					  enum iwl_scan_status scan_type)
+{
+	int ret;
+	bool wait_for_handlers = false;
+
+	mutex_lock(&mvm->mutex);
+
+	if (mvm->scan_status != scan_type) {
+		ret = 0;
+		/* make sure there are no pending notifications */
+		wait_for_handlers = true;
+		goto out;
+	}
+
+	switch (scan_type) {
+	case IWL_MVM_SCAN_SCHED:
+		ret = iwl_mvm_scan_offload_stop(mvm, true);
+		break;
+	case IWL_MVM_SCAN_OS:
+		ret = iwl_mvm_cancel_scan(mvm);
+		break;
+	case IWL_MVM_SCAN_NONE:
+	default:
+		WARN_ON_ONCE(1);
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		goto out;
+
+	wait_for_handlers = true;
+out:
+	mutex_unlock(&mvm->mutex);
+
+	/* make sure we consume the completion notification */
+	if (wait_for_handlers)
+		iwl_mvm_wait_for_async_handlers(mvm);
+
+	return ret;
+}
 static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
-			       struct cfg80211_scan_request *req)
+			       struct ieee80211_scan_request *hw_req)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct cfg80211_scan_request *req = &hw_req->req;
 	int ret;
 
-	if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
+	if (req->n_channels == 0 ||
+	    req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
 		return -EINVAL;
 
+	ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
+	if (ret)
+		return ret;
+
 	mutex_lock(&mvm->mutex);
 
-	switch (mvm->scan_status) {
-	case IWL_MVM_SCAN_SCHED:
-		ret = iwl_mvm_sched_scan_stop(mvm, true);
-		if (ret) {
-			ret = -EBUSY;
-			goto out;
-		}
-		break;
-	case IWL_MVM_SCAN_NONE:
-		break;
-	default:
+	if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
 
-	ret = iwl_mvm_scan_request(mvm, vif, req);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
+	else
+		ret = iwl_mvm_scan_request(mvm, vif, req);
+
 	if (ret)
 		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
 out:
 	mutex_unlock(&mvm->mutex);
-	/* make sure to flush the Rx handler before the next scan arrives */
-	iwl_mvm_wait_for_async_handlers(mvm);
 	return ret;
 }
 
@@ -1680,6 +1935,48 @@ static void iwl_mvm_sta_pre_rcu_remove(s
 	mutex_unlock(&mvm->mutex);
 }
 
+int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+	struct ieee80211_sta *sta;
+	struct iwl_mvm_sta *mvmsta;
+	int count = 0;
+	int i;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+						lockdep_is_held(&mvm->mutex));
+		if (!sta || IS_ERR(sta) || !sta->tdls)
+			continue;
+
+		if (vif) {
+			mvmsta = iwl_mvm_sta_from_mac80211(sta);
+			if (mvmsta->vif != vif)
+				continue;
+		}
+
+		count++;
+	}
+
+	return count;
+}
+
+static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
+				      struct ieee80211_vif *vif,
+				      bool sta_added)
+{
+	int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
+
+	/*
+	 * Disable ps when the first TDLS sta is added and re-enable it
+	 * when the last TDLS sta is removed
+	 */
+	if ((tdls_sta_cnt == 1 && sta_added) ||
+	    (tdls_sta_cnt == 0 && !sta_added))
+		iwl_mvm_power_update_mac(mvm);
+}
+
 static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_sta *sta,
@@ -1718,7 +2015,20 @@ static int iwl_mvm_mac_sta_state(struct
 			ret = -EINVAL;
 			goto out_unlock;
 		}
+
+		if (sta->tdls &&
+		    (vif->p2p ||
+		     iwl_mvm_tdls_sta_count(mvm, NULL) ==
+						IWL_MVM_TDLS_STA_COUNT ||
+		     iwl_mvm_phy_ctx_count(mvm) > 1)) {
+			IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
+			ret = -EBUSY;
+			goto out_unlock;
+		}
+
 		ret = iwl_mvm_add_sta(mvm, vif, sta);
+		if (sta->tdls && ret == 0)
+			iwl_mvm_recalc_tdls_state(mvm, vif, true);
 	} else if (old_state == IEEE80211_STA_NONE &&
 		   new_state == IEEE80211_STA_AUTH) {
 		/*
@@ -1736,6 +2046,11 @@ static int iwl_mvm_mac_sta_state(struct
 					     true);
 	} else if (old_state == IEEE80211_STA_ASSOC &&
 		   new_state == IEEE80211_STA_AUTHORIZED) {
+
+		/* we don't support TDLS during DCM */
+		if (iwl_mvm_phy_ctx_count(mvm) > 1)
+			iwl_mvm_teardown_tdls_peers(mvm);
+
 		/* enable beacon filtering */
 		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
 		ret = 0;
@@ -1753,6 +2068,8 @@ static int iwl_mvm_mac_sta_state(struct
 	} else if (old_state == IEEE80211_STA_NONE &&
 		   new_state == IEEE80211_STA_NOTEXIST) {
 		ret = iwl_mvm_rm_sta(mvm, vif, sta);
+		if (sta->tdls)
+			iwl_mvm_recalc_tdls_state(mvm, vif, false);
 	} else {
 		ret = -EIO;
 	}
@@ -1818,20 +2135,54 @@ static void iwl_mvm_mac_mgd_prepare_tx(s
 	if (WARN_ON_ONCE(vif->bss_conf.assoc))
 		return;
 
+	/*
+	 * iwl_mvm_protect_session() reads directly from the device
+	 * (the system time), so make sure it is available.
+	 */
+	if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
+		return;
+
 	mutex_lock(&mvm->mutex);
 	/* Try really hard to protect the session and hear a beacon */
 	iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
 	mutex_unlock(&mvm->mutex);
+
+	iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
+}
+
+static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
+						  struct ieee80211_vif *vif)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
+
+	/*
+	 * iwl_mvm_protect_session() reads directly from the device
+	 * (the system time), so make sure it is available.
+	 */
+	if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
+		return;
+
+	mutex_lock(&mvm->mutex);
+	/* Protect the session to hear the TDLS setup response on the channel */
+	iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
+	mutex_unlock(&mvm->mutex);
+
+	iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
 }
 
 static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif,
 					struct cfg80211_sched_scan_request *req,
-					struct ieee80211_sched_scan_ies *ies)
+					struct ieee80211_scan_ies *ies)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 
+	ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
+	if (ret)
+		return ret;
+
 	mutex_lock(&mvm->mutex);
 
 	if (!iwl_mvm_is_idle(mvm)) {
@@ -1839,49 +2190,34 @@ static int iwl_mvm_mac_sched_scan_start(
 		goto out;
 	}
 
-	switch (mvm->scan_status) {
-	case IWL_MVM_SCAN_OS:
-		IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
-		ret = iwl_mvm_cancel_scan(mvm);
-		if (ret) {
-			ret = -EBUSY;
-			goto out;
-		}
-
-		/*
-		 * iwl_mvm_rx_scan_complete() will be called soon but will
-		 * not reset the scan status as it won't be IWL_MVM_SCAN_OS
-		 * any more since we queue the next scan immediately (below).
-		 * We make sure it is called before the next scan starts by
-		 * flushing the async-handlers work.
-		 */
-		break;
-	case IWL_MVM_SCAN_NONE:
-		break;
-	default:
+	if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	mvm->scan_status = IWL_MVM_SCAN_SCHED;
 
-	ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
-	if (ret)
-		goto err;
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+		ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
+		if (ret)
+			goto err;
+	}
 
 	ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
 	if (ret)
 		goto err;
 
-	ret = iwl_mvm_sched_scan_start(mvm, req);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
+	else
+		ret = iwl_mvm_sched_scan_start(mvm, req);
+
 	if (!ret)
 		goto out;
 err:
 	mvm->scan_status = IWL_MVM_SCAN_NONE;
 out:
 	mutex_unlock(&mvm->mutex);
-	/* make sure to flush the Rx handler before the next scan arrives */
-	iwl_mvm_wait_for_async_handlers(mvm);
 	return ret;
 }
 
@@ -1892,7 +2228,7 @@ static int iwl_mvm_mac_sched_scan_stop(s
 	int ret;
 
 	mutex_lock(&mvm->mutex);
-	ret = iwl_mvm_sched_scan_stop(mvm, false);
+	ret = iwl_mvm_scan_offload_stop(mvm, false);
 	mutex_unlock(&mvm->mutex);
 	iwl_mvm_wait_for_async_handlers(mvm);
 
@@ -2001,6 +2337,119 @@ static void iwl_mvm_mac_update_tkip_key(
 }
 
 
+static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
+			       struct iwl_rx_packet *pkt, void *data)
+{
+	struct iwl_mvm *mvm =
+		container_of(notif_wait, struct iwl_mvm, notif_wait);
+	struct iwl_hs20_roc_res *resp;
+	int resp_len = iwl_rx_packet_payload_len(pkt);
+	struct iwl_mvm_time_event_data *te_data = data;
+
+	if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD))
+		return true;
+
+	if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
+		IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n");
+		return true;
+	}
+
+	resp = (void *)pkt->data;
+
+	IWL_DEBUG_TE(mvm,
+		     "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
+		     resp->status, resp->event_unique_id);
+
+	te_data->uid = le32_to_cpu(resp->event_unique_id);
+	IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
+		     te_data->uid);
+
+	spin_lock_bh(&mvm->time_event_lock);
+	list_add_tail(&te_data->list, &mvm->aux_roc_te_list);
+	spin_unlock_bh(&mvm->time_event_lock);
+
+	return true;
+}
+
+#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
+static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
+				    struct ieee80211_channel *channel,
+				    struct ieee80211_vif *vif,
+				    int duration)
+{
+	int res, time_reg = DEVICE_SYSTEM_TIME_REG;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
+	static const u8 time_event_response[] = { HOT_SPOT_CMD };
+	struct iwl_notification_wait wait_time_event;
+	struct iwl_hs20_roc_req aux_roc_req = {
+		.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
+		.id_and_color =
+			cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
+		.sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
+		/* Set the channel info data */
+		.channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ?
+			PHY_BAND_24 : PHY_BAND_5,
+		.channel_info.channel = channel->hw_value,
+		.channel_info.width = PHY_VHT_CHANNEL_MODE20,
+		/* Set the time and duration */
+		.apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
+		.apply_time_max_delay =
+			cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
+		.duration = cpu_to_le32(MSEC_TO_TU(duration)),
+	 };
+
+	/* Set the node address */
+	memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
+
+	te_data->vif = vif;
+	te_data->duration = duration;
+	te_data->id = HOT_SPOT_CMD;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	spin_lock_bh(&mvm->time_event_lock);
+	list_add_tail(&te_data->list, &mvm->time_event_list);
+	spin_unlock_bh(&mvm->time_event_lock);
+
+	/*
+	 * Use a notification wait, which really just processes the
+	 * command response and doesn't wait for anything, in order
+	 * to be able to process the response and get the UID inside
+	 * the RX path. Using CMD_WANT_SKB doesn't work because it
+	 * stores the buffer and then wakes up this thread, by which
+	 * time another notification (that the time event started)
+	 * might already be processed unsuccessfully.
+	 */
+	iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
+				   time_event_response,
+				   ARRAY_SIZE(time_event_response),
+				   iwl_mvm_rx_aux_roc, te_data);
+
+	res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
+				   &aux_roc_req);
+
+	if (res) {
+		IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res);
+		iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
+		goto out_clear_te;
+	}
+
+	/* No need to wait for anything, so just pass 1 (0 isn't valid) */
+	res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
+	/* should never fail */
+	WARN_ON_ONCE(res);
+
+	if (res) {
+ out_clear_te:
+		spin_lock_bh(&mvm->time_event_lock);
+		iwl_mvm_te_clear_data(mvm, te_data);
+		spin_unlock_bh(&mvm->time_event_lock);
+	}
+
+	return res;
+}
+
 static int iwl_mvm_roc(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_channel *channel,
@@ -2016,8 +2465,17 @@ static int iwl_mvm_roc(struct ieee80211_
 	IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
 			   duration, type);
 
-	if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
-		IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		/* Use aux roc framework (HS20) */
+		ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+					       vif, duration);
+		return ret;
+	case NL80211_IFTYPE_P2P_DEVICE:
+		/* handle below */
+		break;
+	default:
+		IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
 		return -EINVAL;
 	}
 
@@ -2126,17 +2584,17 @@ static int iwl_mvm_cancel_roc(struct iee
 	return 0;
 }
 
-static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
-			       struct ieee80211_chanctx_conf *ctx)
+static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
+				 struct ieee80211_chanctx_conf *ctx)
 {
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
 	struct iwl_mvm_phy_ctxt *phy_ctxt;
 	int ret;
 
+	lockdep_assert_held(&mvm->mutex);
+
 	IWL_DEBUG_MAC80211(mvm, "Add channel context\n");
 
-	mutex_lock(&mvm->mutex);
 	phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
 	if (!phy_ctxt) {
 		ret = -ENOSPC;
@@ -2154,19 +2612,40 @@ static int iwl_mvm_add_chanctx(struct ie
 	iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
 	*phy_ctxt_id = phy_ctxt->id;
 out:
+	return ret;
+}
+
+static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
+			       struct ieee80211_chanctx_conf *ctx)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	int ret;
+
+	mutex_lock(&mvm->mutex);
+	ret = __iwl_mvm_add_chanctx(mvm, ctx);
 	mutex_unlock(&mvm->mutex);
+
 	return ret;
 }
 
+static void __iwl_mvm_remove_chanctx(struct iwl_mvm *mvm,
+				     struct ieee80211_chanctx_conf *ctx)
+{
+	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
+	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+
+	lockdep_assert_held(&mvm->mutex);
+
+	iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
+}
+
 static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
 				   struct ieee80211_chanctx_conf *ctx)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
-	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
 
 	mutex_lock(&mvm->mutex);
-	iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
+	__iwl_mvm_remove_chanctx(mvm, ctx);
 	mutex_unlock(&mvm->mutex);
 }
 
@@ -2195,17 +2674,17 @@ static void iwl_mvm_change_chanctx(struc
 	mutex_unlock(&mvm->mutex);
 }
 
-static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct ieee80211_chanctx_conf *ctx)
+static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
+					struct ieee80211_vif *vif,
+					struct ieee80211_chanctx_conf *ctx,
+					bool switching_chanctx)
 {
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
 	struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int ret;
 
-	mutex_lock(&mvm->mutex);
+	lockdep_assert_held(&mvm->mutex);
 
 	mvmvif->phy_ctxt = phy_ctxt;
 
@@ -2222,18 +2701,18 @@ static int iwl_mvm_assign_vif_chanctx(st
 		 * (in bss_info_changed), similarly for IBSS.
 		 */
 		ret = 0;
-		goto out_unlock;
+		goto out;
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_MONITOR:
 		break;
 	default:
 		ret = -EINVAL;
-		goto out_unlock;
+		goto out;
 	}
 
 	ret = iwl_mvm_binding_add_vif(mvm, vif);
 	if (ret)
-		goto out_unlock;
+		goto out;
 
 	/*
 	 * Power state must be updated before quotas,
@@ -2247,65 +2726,166 @@ static int iwl_mvm_assign_vif_chanctx(st
 	 */
 	if (vif->type == NL80211_IFTYPE_MONITOR) {
 		mvmvif->monitor_active = true;
-		ret = iwl_mvm_update_quotas(mvm, vif);
+		ret = iwl_mvm_update_quotas(mvm, NULL);
 		if (ret)
 			goto out_remove_binding;
 	}
 
 	/* Handle binding during CSA */
-	if (vif->type == NL80211_IFTYPE_AP) {
-		iwl_mvm_update_quotas(mvm, vif);
+	if ((vif->type == NL80211_IFTYPE_AP) ||
+	    (switching_chanctx && (vif->type == NL80211_IFTYPE_STATION))) {
+		iwl_mvm_update_quotas(mvm, NULL);
 		iwl_mvm_mac_ctxt_changed(mvm, vif, false);
 	}
 
-	goto out_unlock;
+	goto out;
 
- out_remove_binding:
+out_remove_binding:
 	iwl_mvm_binding_remove_vif(mvm, vif);
 	iwl_mvm_power_update_mac(mvm);
- out_unlock:
-	mutex_unlock(&mvm->mutex);
+out:
 	if (ret)
 		mvmvif->phy_ctxt = NULL;
 	return ret;
 }
-
-static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
-					 struct ieee80211_vif *vif,
-					 struct ieee80211_chanctx_conf *ctx)
+static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct ieee80211_chanctx_conf *ctx)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	int ret;
 
 	mutex_lock(&mvm->mutex);
+	ret = __iwl_mvm_assign_vif_chanctx(mvm, vif, ctx, false);
+	mutex_unlock(&mvm->mutex);
+
+	return ret;
+}
+
+static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
+					   struct ieee80211_vif *vif,
+					   struct ieee80211_chanctx_conf *ctx,
+					   bool switching_chanctx)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct ieee80211_vif *disabled_vif = NULL;
+
+	lockdep_assert_held(&mvm->mutex);
 
 	iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_ADHOC:
-		goto out_unlock;
+		goto out;
 	case NL80211_IFTYPE_MONITOR:
 		mvmvif->monitor_active = false;
-		iwl_mvm_update_quotas(mvm, NULL);
 		break;
 	case NL80211_IFTYPE_AP:
 		/* This part is triggered only during CSA */
 		if (!vif->csa_active || !mvmvif->ap_ibss_active)
-			goto out_unlock;
+			goto out;
+
+		/* Set CS bit on all the stations */
+		iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
+
+		/* Save blocked iface, the timeout is set on the next beacon */
+		rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
 
 		mvmvif->ap_ibss_active = false;
-		iwl_mvm_update_quotas(mvm, NULL);
-		/*TODO: bt_coex notification here? */
+		break;
+	case NL80211_IFTYPE_STATION:
+		if (!switching_chanctx)
+			break;
+
+		disabled_vif = vif;
+
+		iwl_mvm_mac_ctxt_changed(mvm, vif, true);
+		break;
 	default:
 		break;
 	}
 
+	iwl_mvm_update_quotas(mvm, disabled_vif);
 	iwl_mvm_binding_remove_vif(mvm, vif);
 
-out_unlock:
+out:
 	mvmvif->phy_ctxt = NULL;
 	iwl_mvm_power_update_mac(mvm);
+}
+
+static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
+					 struct ieee80211_vif *vif,
+					 struct ieee80211_chanctx_conf *ctx)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+	mutex_lock(&mvm->mutex);
+	__iwl_mvm_unassign_vif_chanctx(mvm, vif, ctx, false);
+	mutex_unlock(&mvm->mutex);
+}
+
+static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
+				      struct ieee80211_vif_chanctx_switch *vifs,
+				      int n_vifs,
+				      enum ieee80211_chanctx_switch_mode mode)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	int ret;
+
+	/* we only support SWAP_CONTEXTS and with a single-vif right now */
+	if (mode != CHANCTX_SWMODE_SWAP_CONTEXTS || n_vifs > 1)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&mvm->mutex);
+	__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+	__iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
+
+	ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
+	if (ret) {
+		IWL_ERR(mvm, "failed to add new_ctx during channel switch\n");
+		goto out_reassign;
+	}
+
+	ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+					   true);
+	if (ret) {
+		IWL_ERR(mvm,
+			"failed to assign new_ctx during channel switch\n");
+		goto out_remove;
+	}
+
+	/* we don't support TDLS during DCM - can be caused by channel switch */
+	if (iwl_mvm_phy_ctx_count(mvm) > 1)
+		iwl_mvm_teardown_tdls_peers(mvm);
+
+	goto out;
+
+out_remove:
+	__iwl_mvm_remove_chanctx(mvm, vifs[0].new_ctx);
+
+out_reassign:
+	ret = __iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx);
+	if (ret) {
+		IWL_ERR(mvm, "failed to add old_ctx back after failure.\n");
+		goto out_restart;
+	}
+
+	ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+					   true);
+	if (ret) {
+		IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
+		goto out_restart;
+	}
+
+	goto out;
+
+out_restart:
+	/* things keep failing, better restart the hw */
+	iwl_mvm_nic_restart(mvm, false);
+
+out:
 	mutex_unlock(&mvm->mutex);
+	return ret;
 }
 
 static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
@@ -2395,15 +2975,19 @@ static void iwl_mvm_channel_switch_beaco
 					  struct cfg80211_chan_def *chandef)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct ieee80211_vif *csa_vif;
 
 	mutex_lock(&mvm->mutex);
-	if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active,
+
+	csa_vif = rcu_dereference_protected(mvm->csa_vif,
+					    lockdep_is_held(&mvm->mutex));
+	if (WARN(csa_vif && csa_vif->csa_active,
 		 "Another CSA is already in progress"))
 		goto out_unlock;
 
 	IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
 			   chandef->center_freq1);
-	mvm->csa_vif = vif;
+	rcu_assign_pointer(mvm->csa_vif, vif);
 
 out_unlock:
 	mutex_unlock(&mvm->mutex);
@@ -2460,6 +3044,7 @@ const struct ieee80211_ops iwl_mvm_hw_op
 	.sta_rc_update = iwl_mvm_sta_rc_update,
 	.conf_tx = iwl_mvm_mac_conf_tx,
 	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+	.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
 	.flush = iwl_mvm_mac_flush,
 	.sched_scan_start = iwl_mvm_mac_sched_scan_start,
 	.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
@@ -2472,6 +3057,7 @@ const struct ieee80211_ops iwl_mvm_hw_op
 	.change_chanctx = iwl_mvm_change_chanctx,
 	.assign_vif_chanctx = iwl_mvm_assign_vif_chanctx,
 	.unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx,
+	.switch_vif_chanctx = iwl_mvm_switch_vif_chanctx,
 
 	.start_ap = iwl_mvm_start_ap_ibss,
 	.stop_ap = iwl_mvm_stop_ap_ibss,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,7 @@
 #include "iwl-prph.h"
 #include "fw-api.h"
 #include "mvm.h"
+#include "time-event.h"
 
 const u8 iwl_mvm_ac_to_tx_fifo[] = {
 	IWL_MVM_TX_FIFO_VO,
@@ -720,11 +721,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(stru
 	    !force_assoc_off) {
 		u32 dtim_offs;
 
-		/* Allow beacons to pass through as long as we are not
-		 * associated, or we do not have dtim period information.
-		 */
-		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
-
 		/*
 		 * The DTIM count counts down, so when it is N that means N
 		 * more beacon intervals happen until the DTIM TBTT. Therefore
@@ -758,6 +754,11 @@ static int iwl_mvm_mac_ctxt_cmd_sta(stru
 		ctxt_sta->is_assoc = cpu_to_le32(1);
 	} else {
 		ctxt_sta->is_assoc = cpu_to_le32(0);
+
+		/* Allow beacons to pass through as long as we are not
+		 * associated, or we do not have dtim period information.
+		 */
+		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
 	}
 
 	ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
@@ -903,7 +904,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(
 	struct iwl_mac_beacon_cmd beacon_cmd = {};
 	struct ieee80211_tx_info *info;
 	u32 beacon_skb_len;
-	u32 rate;
+	u32 rate, tx_flags;
 
 	if (WARN_ON(!beacon))
 		return -EINVAL;
@@ -913,14 +914,17 @@ static int iwl_mvm_mac_ctxt_send_beacon(
 	/* TODO: for now the beacon template id is set to be the mac context id.
 	 * Might be better to handle it as another resource ... */
 	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
+	info = IEEE80211_SKB_CB(beacon);
 
 	/* Set up TX command fields */
 	beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len);
 	beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id;
 	beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
-	beacon_cmd.tx.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
-					     TX_CMD_FLG_BT_DIS  |
-					     TX_CMD_FLG_TSF);
+	tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
+	tx_flags |=
+		iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
+						TX_CMD_FLG_BT_PRIO_POS;
+	beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags);
 
 	mvm->mgmt_last_antenna_idx =
 		iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
@@ -930,8 +934,6 @@ static int iwl_mvm_mac_ctxt_send_beacon(
 		cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
 			    RATE_MCS_ANT_POS);
 
-	info = IEEE80211_SKB_CB(beacon);
-
 	if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) {
 		rate = IWL_FIRST_OFDM_RATE;
 	} else {
@@ -968,7 +970,7 @@ int iwl_mvm_mac_ctxt_beacon_changed(stru
 	WARN_ON(vif->type != NL80211_IFTYPE_AP &&
 		vif->type != NL80211_IFTYPE_ADHOC);
 
-	beacon = ieee80211_beacon_get(mvm->hw, vif);
+	beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
 	if (!beacon)
 		return -ENOMEM;
 
@@ -1210,31 +1212,94 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_m
 	return 0;
 }
 
+static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
+				   struct ieee80211_vif *csa_vif, u32 gp2)
+{
+	struct iwl_mvm_vif *mvmvif =
+			iwl_mvm_vif_from_mac80211(csa_vif);
+
+	if (!ieee80211_csa_is_complete(csa_vif)) {
+		int c = ieee80211_csa_update_counter(csa_vif);
+
+		iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
+		if (csa_vif->p2p &&
+		    !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
+			u32 rel_time = (c + 1) *
+				       csa_vif->bss_conf.beacon_int -
+				       IWL_MVM_CHANNEL_SWITCH_TIME;
+			u32 apply_time = gp2 + rel_time * 1024;
+
+			iwl_mvm_schedule_csa_noa(mvm, csa_vif,
+						 IWL_MVM_CHANNEL_SWITCH_TIME -
+						 IWL_MVM_CHANNEL_SWITCH_MARGIN,
+						 apply_time);
+		}
+	} else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
+		/* we don't have CSA NoA scheduled yet, switch now */
+		ieee80211_csa_finish(csa_vif);
+		RCU_INIT_POINTER(mvm->csa_vif, NULL);
+	}
+}
+
 int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
 			    struct iwl_rx_cmd_buffer *rxb,
 			    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_beacon_notif *beacon = (void *)pkt->data;
-	u16 status __maybe_unused =
-		le16_to_cpu(beacon->beacon_notify_hdr.status.status);
-	u32 rate __maybe_unused =
-		le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
+	struct iwl_mvm_tx_resp *beacon_notify_hdr;
+	struct ieee80211_vif *csa_vif;
+	struct ieee80211_vif *tx_blocked_vif;
+	u64 tsf;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
-		     status & TX_STATUS_MSK,
-		     beacon->beacon_notify_hdr.failure_frame,
-		     le64_to_cpu(beacon->tsf),
-		     rate);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) {
+		struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
 
-	if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {
-		if (!ieee80211_csa_is_complete(mvm->csa_vif)) {
-			iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);
-		} else {
-			ieee80211_csa_finish(mvm->csa_vif);
-			mvm->csa_vif = NULL;
+		beacon_notify_hdr = &beacon->beacon_notify_hdr;
+		tsf = le64_to_cpu(beacon->tsf);
+		mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+	} else {
+		struct iwl_beacon_notif *beacon = (void *)pkt->data;
+
+		beacon_notify_hdr = &beacon->beacon_notify_hdr;
+		tsf = le64_to_cpu(beacon->tsf);
+	}
+
+	IWL_DEBUG_RX(mvm,
+		     "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
+		     le16_to_cpu(beacon_notify_hdr->status.status) &
+								TX_STATUS_MSK,
+		     beacon_notify_hdr->failure_frame, tsf,
+		     mvm->ap_last_beacon_gp2,
+		     le32_to_cpu(beacon_notify_hdr->initial_rate));
+
+	csa_vif = rcu_dereference_protected(mvm->csa_vif,
+					    lockdep_is_held(&mvm->mutex));
+	if (unlikely(csa_vif && csa_vif->csa_active))
+		iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2);
+
+	tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
+						lockdep_is_held(&mvm->mutex));
+	if (unlikely(tx_blocked_vif)) {
+		struct iwl_mvm_vif *mvmvif =
+			iwl_mvm_vif_from_mac80211(tx_blocked_vif);
+
+		/*
+		 * The channel switch is started and we have blocked the
+		 * stations. If this is the first beacon (the timeout wasn't
+		 * set), set the unblock timeout, otherwise countdown
+		 */
+		if (!mvm->csa_tx_block_bcn_timeout)
+			mvm->csa_tx_block_bcn_timeout =
+				IWL_MVM_CS_UNBLOCK_TX_TIMEOUT;
+		else
+			mvm->csa_tx_block_bcn_timeout--;
+
+		/* Check if the timeout is expired, and unblock tx */
+		if (mvm->csa_tx_block_bcn_timeout == 0) {
+			iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
+			RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM)   += iwlmvm.o
 iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
 iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
 iwlmvm-y += scan.o time-event.o rs.o
-iwlmvm-y += power.o coex.o
+iwlmvm-y += power.o coex.o coex_legacy.o
 iwlmvm-y += tt.o offloading.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
 iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h	2014-09-28 17:29:07.000000000 -0400
@@ -82,6 +82,26 @@
 /* RSSI offset for WkP */
 #define IWL_RSSI_OFFSET 50
 #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
+/* A TimeUnit is 1024 microsecond */
+#define MSEC_TO_TU(_msec)	(_msec*1000/1024)
+
+/*
+ * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
+ * TBTT. This value should be big enough to ensure that we switch in time.
+ */
+#define IWL_MVM_CHANNEL_SWITCH_TIME 40
+
+/*
+ * This value (in TUs) is used to fine tune the CSA NoA end time which should
+ * be just before "beacon 0" TBTT.
+ */
+#define IWL_MVM_CHANNEL_SWITCH_MARGIN 4
+
+/*
+ * Number of beacons to transmit on a new channel until we unblock tx to
+ * the stations, even if we didn't identify them on a new channel
+ */
+#define IWL_MVM_CS_UNBLOCK_TX_TIMEOUT 3
 
 enum iwl_mvm_tx_fifo {
 	IWL_MVM_TX_FIFO_BK = 0,
@@ -108,6 +128,21 @@ struct iwl_mvm_mod_params {
 };
 extern struct iwl_mvm_mod_params iwlmvm_mod_params;
 
+/**
+ * struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
+ *
+ * @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
+ * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
+ *	transport's data.
+ * @trans_len: length of the valid data in trans_ptr
+ * @op_mode_len: length of the valid data in op_mode_ptr
+ */
+struct iwl_mvm_dump_ptrs {
+	struct iwl_trans_dump_data *trans_ptr;
+	void *op_mode_ptr;
+	u32 op_mode_len;
+};
+
 struct iwl_mvm_phy_ctxt {
 	u16 id;
 	u16 color;
@@ -230,11 +265,30 @@ enum iwl_mvm_ref_type {
 	IWL_MVM_REF_USER,
 	IWL_MVM_REF_TX,
 	IWL_MVM_REF_TX_AGG,
+	IWL_MVM_REF_ADD_IF,
+	IWL_MVM_REF_START_AP,
+	IWL_MVM_REF_BSS_CHANGED,
+	IWL_MVM_REF_PREPARE_TX,
+	IWL_MVM_REF_PROTECT_TDLS,
+	IWL_MVM_REF_CHECK_CTKILL,
+	IWL_MVM_REF_PRPH_READ,
+	IWL_MVM_REF_PRPH_WRITE,
+	IWL_MVM_REF_NMI,
+	IWL_MVM_REF_TM_CMD,
 	IWL_MVM_REF_EXIT_WORK,
 
 	IWL_MVM_REF_COUNT,
 };
 
+enum iwl_bt_force_ant_mode {
+	BT_FORCE_ANT_DIS = 0,
+	BT_FORCE_ANT_AUTO,
+	BT_FORCE_ANT_BT,
+	BT_FORCE_ANT_WIFI,
+
+	BT_FORCE_ANT_MAX,
+};
+
 /**
 * struct iwl_mvm_vif_bf_data - beacon filtering related data
 * @bf_enabled: indicates if beacon filtering is enabled
@@ -299,6 +353,7 @@ struct iwl_mvm_vif {
 	 */
 	struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
 	struct iwl_mvm_time_event_data time_event_data;
+	struct iwl_mvm_time_event_data hs_time_event_data;
 
 	struct iwl_mvm_int_sta bcast_sta;
 
@@ -523,7 +578,7 @@ struct iwl_mvm {
 
 	/* Scan status, cmd (pre-allocated) and auxiliary station */
 	enum iwl_scan_status scan_status;
-	struct iwl_scan_cmd *scan_cmd;
+	void *scan_cmd;
 	struct iwl_mcast_filter_cmd *mcast_filter_cmd;
 
 	/* rx chain antennas set through debugfs for the scan command */
@@ -578,18 +633,15 @@ struct iwl_mvm {
 	 */
 	unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
 
-	/* A bitmap of reference types taken by the driver. */
-	unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)];
+	/* references taken by the driver and spinlock protecting them */
+	spinlock_t refs_lock;
+	u8 refs[IWL_MVM_REF_COUNT];
 
 	u8 vif_count;
 
 	/* -1 for always, 0 for never, >0 for that many times */
 	s8 restart_fw;
-	void *fw_error_dump;
-	void *fw_error_sram;
-	u32 fw_error_sram_len;
-	u32 *fw_error_rxf;
-	u32 fw_error_rxf_len;
+	struct iwl_mvm_dump_ptrs *fw_error_dump;
 
 #ifdef CONFIG_IWLWIFI_LEDS
 	struct led_classdev led;
@@ -623,12 +675,21 @@ struct iwl_mvm {
 	wait_queue_head_t d0i3_exit_waitq;
 
 	/* BT-Coex */
-	u8 bt_kill_msk;
+	u8 bt_ack_kill_msk[NUM_PHY_CTX];
+	u8 bt_cts_kill_msk[NUM_PHY_CTX];
+
+	struct iwl_bt_coex_profile_notif_old last_bt_notif_old;
+	struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old;
 	struct iwl_bt_coex_profile_notif last_bt_notif;
 	struct iwl_bt_coex_ci_cmd last_bt_ci_cmd;
+
 	u32 last_ant_isol;
 	u8 last_corun_lut;
 	u8 bt_tx_prio;
+	enum iwl_bt_force_ant_mode bt_force_ant_mode;
+
+	/* Aux ROC */
+	struct list_head aux_roc_te_list;
 
 	/* Thermal Throttling and CTkill */
 	struct iwl_mvm_tt_mgmt thermal_throttle;
@@ -647,7 +708,12 @@ struct iwl_mvm {
 	/* Indicate if device power save is allowed */
 	bool ps_disabled;
 
-	struct ieee80211_vif *csa_vif;
+	struct ieee80211_vif __rcu *csa_vif;
+	struct ieee80211_vif __rcu *csa_tx_blocked_vif;
+	u8 csa_tx_block_bcn_timeout;
+
+	/* system time of last beacon (for AP/GO interface) */
+	u32 ap_last_beacon_gp2;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -663,6 +729,7 @@ enum iwl_mvm_status {
 	IWL_MVM_STATUS_ROC_RUNNING,
 	IWL_MVM_STATUS_IN_HW_RESTART,
 	IWL_MVM_STATUS_IN_D0I3,
+	IWL_MVM_STATUS_ROC_AUX_RUNNING,
 };
 
 static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -719,11 +786,6 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_
 			       struct ieee80211_tx_rate *r);
 u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
 void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
-void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm);
-void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm);
-#endif
 u8 first_antenna(u8 mask);
 u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
 
@@ -809,6 +871,7 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm
 			  struct iwl_mvm_phy_ctxt *ctxt);
 void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
 			    struct iwl_mvm_phy_ctxt *ctxt);
+int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
 
 /* MAC (virtual interface) programming */
 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -835,7 +898,8 @@ int iwl_mvm_binding_add_vif(struct iwl_m
 int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 
 /* Quota management */
-int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif);
+int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
+			  struct ieee80211_vif *disabled_vif);
 
 /* Scanning */
 int iwl_mvm_scan_request(struct iwl_mvm *mvm,
@@ -854,15 +918,24 @@ int iwl_mvm_rx_scan_offload_complete_not
 int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
 			      struct ieee80211_vif *vif,
 			      struct cfg80211_sched_scan_request *req,
-			      struct ieee80211_sched_scan_ies *ies);
+			      struct ieee80211_scan_ies *ies);
 int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
 				       struct cfg80211_sched_scan_request *req);
 int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
 			     struct cfg80211_sched_scan_request *req);
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify);
-int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
-				  struct iwl_rx_cmd_buffer *rxb,
-				  struct iwl_device_cmd *cmd);
+int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
+int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
+				    struct iwl_rx_cmd_buffer *rxb,
+				    struct iwl_device_cmd *cmd);
+
+/* Unified scan */
+int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
+			      struct ieee80211_vif *vif,
+			      struct ieee80211_scan_request *req);
+int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
+				    struct ieee80211_vif *vif,
+				    struct cfg80211_sched_scan_request *req,
+				    struct ieee80211_scan_ies *ies);
 
 /* MVM debugfs */
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -948,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iw
 /* D0i3 */
 void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
+int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
 int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
 
@@ -963,19 +1037,40 @@ u16 iwl_mvm_coex_agg_time_limit(struct i
 				struct ieee80211_sta *sta);
 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
 				     struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm);
 bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
 				    enum ieee80211_band band);
 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 			   struct ieee80211_tx_info *info, u8 ac);
 
+bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm);
+void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm);
+int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm);
+int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
+				 struct iwl_rx_cmd_buffer *rxb,
+				 struct iwl_device_cmd *cmd);
+void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			       enum ieee80211_rssi_event rssi_event);
+u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm,
+				    struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm,
+					 struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm,
+					enum ieee80211_band band);
+int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
+				      struct iwl_rx_cmd_buffer *rxb,
+				      struct iwl_device_cmd *cmd);
+
 enum iwl_bt_kill_msk {
 	BT_KILL_MSK_DEFAULT,
-	BT_KILL_MSK_SCO_HID_A2DP,
-	BT_KILL_MSK_REDUCED_TXPOW,
+	BT_KILL_MSK_NEVER,
+	BT_KILL_MSK_ALWAYS,
 	BT_KILL_MSK_MAX,
 };
-extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX];
-extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX];
+
+extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
+extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
+extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX];
 
 /* beacon filtering */
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1039,4 +1134,9 @@ void iwl_mvm_set_hw_ctkill_state(struct
 int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 		      bool added_vif);
 
+/* TDLS */
+int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+
+void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
+
 #endif /* __IWL_MVM_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/nvm.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/nvm.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/nvm.c	2014-08-07 04:54:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/nvm.c	2014-09-28 21:36:34.000000000 -0400
@@ -69,7 +69,9 @@
 
 /* Default NVM size to read */
 #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
-#define IWL_MAX_NVM_SECTION_SIZE 7000
+#define IWL_MAX_NVM_SECTION_SIZE	0x1b58
+#define IWL_MAX_NVM_8000A_SECTION_SIZE	0xffc
+#define IWL_MAX_NVM_8000B_SECTION_SIZE	0x1ffc
 
 #define NVM_WRITE_OPCODE 1
 #define NVM_READ_OPCODE 0
@@ -219,7 +221,7 @@ static int iwl_nvm_write_section(struct
  * without overflowing, so no check is needed.
  */
 static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
-				u8 *data)
+				u8 *data, u32 size_read)
 {
 	u16 length, offset = 0;
 	int ret;
@@ -231,6 +233,13 @@ static int iwl_nvm_read_section(struct i
 
 	/* Read the NVM until exhausted (reading less than requested) */
 	while (ret == length) {
+		/* Check no memory assumptions fail and cause an overflow */
+		if ((size_read + offset + length) >
+		    mvm->cfg->base_params->eeprom_size) {
+			IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
+			return -ENOBUFS;
+		}
+
 		ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);
 		if (ret < 0) {
 			IWL_DEBUG_EEPROM(mvm->trans->dev,
@@ -256,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *m
 	if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
 		if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
 		    !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
-			IWL_ERR(mvm, "Can't parse empty NVM sections\n");
+			IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
 			return NULL;
 		}
 	} else {
@@ -264,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *m
 		if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
 		    !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
 			IWL_ERR(mvm,
-				"Can't parse empty family 8000 NVM sections\n");
+				"Can't parse empty family 8000 OTP/NVM sections\n");
 			return NULL;
 		}
 		/* MAC_OVERRIDE or at least HW section must exist */
@@ -326,6 +335,7 @@ static int iwl_mvm_read_external_nvm(str
 		u8 data[];
 	} *file_sec;
 	const u8 *eof, *temp;
+	int max_section_size;
 
 #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
 #define NVM_WORD2_ID(x) (x >> 12)
@@ -334,6 +344,14 @@ static int iwl_mvm_read_external_nvm(str
 
 	IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
 
+	/* Maximal size depends on HW family and step */
+	if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		max_section_size = IWL_MAX_NVM_SECTION_SIZE;
+	else if ((mvm->trans->hw_rev & 0xc) == 0) /* Family 8000 A-step */
+		max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE;
+	else /* Family 8000 B-step */
+		max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE;
+
 	/*
 	 * Obtain NVM image via reject_firmware. Since we already used
 	 * reject_firmware_nowait() for the firmware binary load and only
@@ -392,7 +410,7 @@ static int iwl_mvm_read_external_nvm(str
 						le16_to_cpu(file_sec->word1));
 		}
 
-		if (section_size > IWL_MAX_NVM_SECTION_SIZE) {
+		if (section_size > max_section_size) {
 			IWL_ERR(mvm, "ERROR - section too large (%d)\n",
 				section_size);
 			ret = -EINVAL;
@@ -459,6 +477,7 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_m
 int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
 {
 	int ret, section;
+	u32 size_read = 0;
 	u8 *nvm_buffer, *temp;
 
 	if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
@@ -475,9 +494,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bo
 			return -ENOMEM;
 		for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) {
 			/* we override the constness for initial read */
-			ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
+			ret = iwl_nvm_read_section(mvm, section, nvm_buffer,
+						   size_read);
 			if (ret < 0)
 				continue;
+			size_read += ret;
 			temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
 			if (!temp) {
 				ret = -ENOMEM;
@@ -509,6 +530,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bo
 			}
 #endif
 		}
+		if (!size_read)
+			IWL_ERR(mvm, "OTP is blank\n");
 		kfree(nvm_buffer);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,8 +166,15 @@ static void iwl_mvm_nic_config(struct iw
 	WARN_ON((radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE) &
 		 ~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE);
 
-	/* silicon bits */
-	reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
+	/*
+	 * TODO: Bits 7-8 of CSR in 8000 HW family set the ADC sampling, and
+	 * shouldn't be set to any non-zero value. The same is supposed to be
+	 * true of the other HW, but unsetting them (such as the 7260) causes
+	 * automatic tests to fail on seemingly unrelated errors. Need to
+	 * further investigate this, but for now we'll separate cases.
+	 */
+	if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+		reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
 
 	iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
 				CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
@@ -233,7 +240,7 @@ static const struct iwl_rx_handlers iwl_
 	RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true),
 	RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
 		   iwl_mvm_rx_scan_offload_complete_notif, true),
-	RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
+	RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
 		   false),
 
 	RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
@@ -282,8 +289,10 @@ static const char *const iwl_mvm_cmd_str
 	CMD(MATCH_FOUND_NOTIFICATION),
 	CMD(SCAN_OFFLOAD_REQUEST_CMD),
 	CMD(SCAN_OFFLOAD_ABORT_CMD),
+	CMD(HOT_SPOT_CMD),
 	CMD(SCAN_OFFLOAD_COMPLETE),
 	CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
+	CMD(SCAN_ITERATION_COMPLETE),
 	CMD(POWER_TABLE_CMD),
 	CMD(WEP_KEY),
 	CMD(REPLY_RX_PHY_CMD),
@@ -324,6 +333,9 @@ static const char *const iwl_mvm_cmd_str
 	CMD(REPLY_THERMAL_MNG_BACKOFF),
 	CMD(MAC_PM_POWER_TABLE),
 	CMD(BT_COEX_CI),
+	CMD(BT_COEX_UPDATE_SW_BOOST),
+	CMD(BT_COEX_UPDATE_CORUN_LUT),
+	CMD(BT_COEX_UPDATE_REDUCED_TXP),
 	CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
 	CMD(ANTENNA_COUPLING_NOTIFICATION),
 };
@@ -380,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *
 	if (!hw)
 		return NULL;
 
+	if (cfg->max_rx_agg_size)
+		hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
+
 	op_mode = hw->priv;
 	op_mode->ops = &iwl_mvm_ops;
 
@@ -405,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *
 	mutex_init(&mvm->d0i3_suspend_mutex);
 	spin_lock_init(&mvm->async_handlers_lock);
 	INIT_LIST_HEAD(&mvm->time_event_list);
+	INIT_LIST_HEAD(&mvm->aux_roc_te_list);
 	INIT_LIST_HEAD(&mvm->async_handlers_list);
 	spin_lock_init(&mvm->time_event_lock);
 
@@ -414,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *
 	INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
 
 	spin_lock_init(&mvm->d0i3_tx_lock);
+	spin_lock_init(&mvm->refs_lock);
 	skb_queue_head_init(&mvm->d0i3_tx);
 	init_waitqueue_head(&mvm->d0i3_exit_waitq);
 
@@ -502,9 +519,17 @@ iwl_op_mode_mvm_start(struct iwl_trans *
 		}
 	}
 
-	scan_size = sizeof(struct iwl_scan_cmd) +
-		mvm->fw->ucode_capa.max_probe_length +
-		(MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel));
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		scan_size = sizeof(struct iwl_scan_req_unified_lmac) +
+			sizeof(struct iwl_scan_channel_cfg_lmac) *
+				mvm->fw->ucode_capa.n_scan_channels +
+			sizeof(struct iwl_scan_probe_req);
+	else
+		scan_size = sizeof(struct iwl_scan_cmd) +
+			mvm->fw->ucode_capa.max_probe_length +
+			mvm->fw->ucode_capa.n_scan_channels *
+				sizeof(struct iwl_scan_channel);
+
 	mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
 	if (!mvm->scan_cmd)
 		goto out_free;
@@ -520,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *
 	memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
 
 	/* rpm starts with a taken ref. only set the appropriate bit here. */
-	set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap);
+	mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
 
 	return op_mode;
 
@@ -548,9 +573,11 @@ static void iwl_op_mode_mvm_stop(struct
 	ieee80211_unregister_hw(mvm->hw);
 
 	kfree(mvm->scan_cmd);
-	vfree(mvm->fw_error_dump);
-	kfree(mvm->fw_error_sram);
-	kfree(mvm->fw_error_rxf);
+	if (mvm->fw_error_dump) {
+		vfree(mvm->fw_error_dump->op_mode_ptr);
+		vfree(mvm->fw_error_dump->trans_ptr);
+		kfree(mvm->fw_error_dump);
+	}
 	kfree(mvm->mcast_filter_cmd);
 	mvm->mcast_filter_cmd = NULL;
 
@@ -754,7 +781,7 @@ static void iwl_mvm_reprobe_wk(struct wo
 	module_put(THIS_MODULE);
 }
 
-static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
+void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
 {
 	iwl_abort_notification_waits(&mvm->notif_wait);
 
@@ -811,93 +838,24 @@ static void iwl_mvm_nic_restart(struct i
 		reprobe->dev = mvm->trans->dev;
 		INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
 		schedule_work(&reprobe->work);
-	} else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
+	} else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
+		   (!fw_error || mvm->restart_fw)) {
 		/* don't let the transport/FW power down */
 		iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
 
-		if (mvm->restart_fw > 0)
+		if (fw_error && mvm->restart_fw > 0)
 			mvm->restart_fw--;
 		ieee80211_restart_hw(mvm->hw);
 	}
 }
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
-{
-	struct iwl_fw_error_dump_file *dump_file;
-	struct iwl_fw_error_dump_data *dump_data;
-	u32 file_len;
-	u32 trans_len;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	if (mvm->fw_error_dump)
-		return;
-
-	file_len = mvm->fw_error_sram_len +
-		   mvm->fw_error_rxf_len +
-		   sizeof(*dump_file) +
-		   sizeof(*dump_data) * 2;
-
-	trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
-	if (trans_len)
-		file_len += trans_len;
-
-	dump_file = vmalloc(file_len);
-	if (!dump_file)
-		return;
-
-	mvm->fw_error_dump = dump_file;
-
-	dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
-	dump_file->file_len = cpu_to_le32(file_len);
-	dump_data = (void *)dump_file->data;
-	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
-	dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);
-	memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);
-
-	dump_data = iwl_mvm_fw_error_next_data(dump_data);
-	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
-	dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
-
-	/*
-	 * No need for lock since at the stage the FW isn't loaded. So it
-	 * can't assert - we are the only one who can possibly be accessing
-	 * mvm->fw_error_sram right now.
-	 */
-	memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len);
-
-	kfree(mvm->fw_error_rxf);
-	mvm->fw_error_rxf = NULL;
-	mvm->fw_error_rxf_len = 0;
-
-	kfree(mvm->fw_error_sram);
-	mvm->fw_error_sram = NULL;
-	mvm->fw_error_sram_len = 0;
-
-	if (trans_len) {
-		void *buf = iwl_mvm_fw_error_next_data(dump_data);
-		u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
-							 trans_len);
-		dump_data = (void *)((u8 *)buf + real_trans_len);
-		dump_file->file_len =
-			cpu_to_le32(file_len - trans_len + real_trans_len);
-	}
-}
-#endif
-
 static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
 {
 	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 
 	iwl_mvm_dump_nic_error_log(mvm);
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	iwl_mvm_fw_error_sram_dump(mvm);
-	iwl_mvm_fw_error_rxf_dump(mvm);
-#endif
-
-	iwl_mvm_nic_restart(mvm);
+	iwl_mvm_nic_restart(mvm, true);
 }
 
 static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
@@ -905,7 +863,7 @@ static void iwl_mvm_cmd_queue_full(struc
 	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 
 	WARN_ON(1);
-	iwl_mvm_nic_restart(mvm);
+	iwl_mvm_nic_restart(mvm, true);
 }
 
 struct iwl_d0i3_iter_data {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c	2014-09-28 17:29:07.000000000 -0400
@@ -261,3 +261,29 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_m
 
 	ctxt->ref--;
 }
+
+static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
+				     struct ieee80211_vif *vif)
+{
+	unsigned long *data = _data;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	if (!mvmvif->phy_ctxt)
+		return;
+
+	if (vif->type == NL80211_IFTYPE_STATION ||
+	    vif->type == NL80211_IFTYPE_AP)
+		__set_bit(mvmvif->phy_ctxt->id, data);
+}
+
+int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm)
+{
+	unsigned long phy_ctxt_counter = 0;
+
+	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+						   IEEE80211_IFACE_ITER_NORMAL,
+						   iwl_mvm_binding_iterator,
+						   &phy_ctxt_counter);
+
+	return hweight8(phy_ctxt_counter);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/power.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/power.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/power.c	2014-09-28 17:29:07.000000000 -0400
@@ -246,30 +246,10 @@ static void iwl_mvm_power_configure_uaps
 		IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
 }
 
-static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
-				      struct ieee80211_vif *vif)
-{
-	unsigned long *data = _data;
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
-	if (!mvmvif->phy_ctxt)
-		return;
-
-	if (vif->type == NL80211_IFTYPE_STATION ||
-	    vif->type == NL80211_IFTYPE_AP)
-		__set_bit(mvmvif->phy_ctxt->id, data);
-}
-
 static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
 				       struct ieee80211_vif *vif)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	unsigned long phy_ctxt_counter = 0;
-
-	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
-						   IEEE80211_IFACE_ITER_NORMAL,
-						   iwl_mvm_binding_iterator,
-						   &phy_ctxt_counter);
 
 	if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
 		    ETH_ALEN))
@@ -291,7 +271,7 @@ static bool iwl_mvm_power_allow_uapsd(st
 	 * Avoid using uAPSD if client is in DCM -
 	 * low latency issue in Miracast
 	 */
-	if (hweight8(phy_ctxt_counter) >= 2)
+	if (iwl_mvm_phy_ctx_count(mvm) >= 2)
 		return false;
 
 	return true;
@@ -301,7 +281,6 @@ static void iwl_mvm_power_build_cmd(stru
 				    struct ieee80211_vif *vif,
 				    struct iwl_mac_power_cmd *cmd)
 {
-	struct ieee80211_hw *hw = mvm->hw;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	struct ieee80211_channel *chan;
 	int dtimper, dtimper_msec;
@@ -312,7 +291,7 @@ static void iwl_mvm_power_build_cmd(stru
 
 	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
 							    mvmvif->color));
-	dtimper = hw->conf.ps_dtim_period ?: 1;
+	dtimper = vif->bss_conf.dtim_period;
 
 	/*
 	 * Regardless of power management state the driver must set
@@ -503,6 +482,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_n
 }
 
 struct iwl_power_vifs {
+	struct iwl_mvm *mvm;
 	struct ieee80211_vif *bf_vif;
 	struct ieee80211_vif *bss_vif;
 	struct ieee80211_vif *p2p_vif;
@@ -512,6 +492,8 @@ struct iwl_power_vifs {
 	bool bss_active;
 	bool ap_active;
 	bool monitor_active;
+	bool bss_tdls;
+	bool p2p_tdls;
 };
 
 static void iwl_mvm_power_iterator(void *_data, u8 *mac,
@@ -548,6 +530,8 @@ static void iwl_mvm_power_iterator(void
 		/* only a single MAC of the same type */
 		WARN_ON(power_iterator->p2p_vif);
 		power_iterator->p2p_vif = vif;
+		power_iterator->p2p_tdls =
+			!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
 		if (mvmvif->phy_ctxt)
 			if (mvmvif->phy_ctxt->id < MAX_PHYS)
 				power_iterator->p2p_active = true;
@@ -557,6 +541,8 @@ static void iwl_mvm_power_iterator(void
 		/* only a single MAC of the same type */
 		WARN_ON(power_iterator->bss_vif);
 		power_iterator->bss_vif = vif;
+		power_iterator->bss_tdls =
+			!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
 		if (mvmvif->phy_ctxt)
 			if (mvmvif->phy_ctxt->id < MAX_PHYS)
 				power_iterator->bss_active = true;
@@ -599,13 +585,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm
 		ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
 
 	/* enable PM on bss if bss stand alone */
-	if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
+	if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active &&
+	    !vifs->bss_tdls) {
 		bss_mvmvif->pm_enabled = true;
 		return;
 	}
 
 	/* enable PM on p2p if p2p stand alone */
-	if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
+	if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active &&
+	    !vifs->p2p_tdls) {
 		if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
 			p2p_mvmvif->pm_enabled = true;
 		return;
@@ -831,7 +819,9 @@ int iwl_mvm_disable_beacon_filter(struct
 int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
 {
 	struct iwl_mvm_vif *mvmvif;
-	struct iwl_power_vifs vifs = {};
+	struct iwl_power_vifs vifs = {
+		.mvm = mvm,
+	};
 	bool ba_enable;
 	int ret;
 
@@ -894,7 +884,7 @@ int iwl_mvm_update_d0i3_power_mode(struc
 	iwl_mvm_power_build_cmd(mvm, vif, &cmd);
 	if (enable) {
 		/* configure skip over dtim up to 300 msec */
-		int dtimper = mvm->hw->conf.ps_dtim_period ?: 1;
+		int dtimper = vif->bss_conf.dtim_period ?: 1;
 		int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
 
 		if (WARN_ON(!dtimper_msec))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/quota.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/quota.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/quota.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/quota.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ struct iwl_mvm_quota_iterator_data {
 	int colors[MAX_BINDINGS];
 	int low_latency[MAX_BINDINGS];
 	int n_low_latency_bindings;
-	struct ieee80211_vif *new_vif;
+	struct ieee80211_vif *disabled_vif;
 };
 
 static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
@@ -83,13 +83,8 @@ static void iwl_mvm_quota_iterator(void
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	u16 id;
 
-	/*
-	 * We'll account for the new interface (if any) below,
-	 * skip it here in case we're not called from within
-	 * the add_interface callback (otherwise it won't show
-	 * up in iteration)
-	 */
-	if (vif == data->new_vif)
+	/* skip disabled interfaces here immediately */
+	if (vif == data->disabled_vif)
 		return;
 
 	if (!mvmvif->phy_ctxt)
@@ -104,11 +99,6 @@ static void iwl_mvm_quota_iterator(void
 	if (WARN_ON_ONCE(id >= MAX_BINDINGS))
 		return;
 
-	if (data->colors[id] < 0)
-		data->colors[id] = mvmvif->phy_ctxt->color;
-	else
-		WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
-
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
 		if (vif->bss_conf.assoc)
@@ -130,6 +120,11 @@ static void iwl_mvm_quota_iterator(void
 		return;
 	}
 
+	if (data->colors[id] < 0)
+		data->colors[id] = mvmvif->phy_ctxt->color;
+	else
+		WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
+
 	data->n_interfaces[id]++;
 
 	if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
@@ -171,14 +166,15 @@ static void iwl_mvm_adjust_quota_for_noa
 #endif
 }
 
-int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
+int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
+			  struct ieee80211_vif *disabled_vif)
 {
 	struct iwl_time_quota_cmd cmd = {};
 	int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
 	struct iwl_mvm_quota_iterator_data data = {
 		.n_interfaces = {},
 		.colors = { -1, -1, -1, -1 },
-		.new_vif = newvif,
+		.disabled_vif = disabled_vif,
 	};
 
 	lockdep_assert_held(&mvm->mutex);
@@ -193,10 +189,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm
 	ieee80211_iterate_active_interfaces_atomic(
 		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 		iwl_mvm_quota_iterator, &data);
-	if (newvif) {
-		data.new_vif = NULL;
-		iwl_mvm_quota_iterator(&data, newvif->addr, newvif);
-	}
 
 	/*
 	 * The FW's scheduling session consists of
@@ -285,6 +277,14 @@ int iwl_mvm_update_quotas(struct iwl_mvm
 
 	iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
 
+	/* check that we have non-zero quota for all valid bindings */
+	for (i = 0; i < MAX_BINDINGS; i++) {
+		if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
+			continue;
+		WARN_ONCE(cmd.quotas[i].quota == 0,
+			  "zero quota on binding %d\n", i);
+	}
+
 	ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
 				   sizeof(cmd), &cmd);
 	if (ret)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rs.c	2014-09-28 17:29:07.000000000 -0400
@@ -927,7 +927,7 @@ static bool rs_get_lower_rate_in_column(
 	u8 low;
 	u16 high_low;
 	u16 rate_mask;
-	struct iwl_mvm *mvm = lq_sta->drv;
+	struct iwl_mvm *mvm = lq_sta->pers.drv;
 
 	rate_mask = rs_get_supported_rates(lq_sta, rate);
 	high_low = rs_get_adjacent_rate(mvm, rate->index, rate_mask,
@@ -946,7 +946,7 @@ static bool rs_get_lower_rate_in_column(
 static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
 					  struct rs_rate *rate)
 {
-	struct iwl_mvm *mvm = lq_sta->drv;
+	struct iwl_mvm *mvm = lq_sta->pers.drv;
 
 	if (is_legacy(rate)) {
 		/* No column to downgrade from Legacy */
@@ -1026,14 +1026,14 @@ static void rs_tx_status(void *mvm_r, st
 	if (!lq_sta) {
 		IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
 		return;
-	} else if (!lq_sta->drv) {
+	} else if (!lq_sta->pers.drv) {
 		IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
 		return;
 	}
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	/* Disable last tx check if we are debugging with fixed rate */
-	if (lq_sta->dbg_fixed_rate) {
+	if (lq_sta->pers.dbg_fixed_rate) {
 		IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
 		return;
 	}
@@ -1405,7 +1405,7 @@ static void rs_stay_in_table(struct iwl_
 	int flush_interval_passed = 0;
 	struct iwl_mvm *mvm;
 
-	mvm = lq_sta->drv;
+	mvm = lq_sta->pers.drv;
 	active_tbl = lq_sta->active_tbl;
 
 	tbl = &(lq_sta->lq_info[active_tbl]);
@@ -1865,11 +1865,11 @@ static bool rs_tpc_perform(struct iwl_mv
 	int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE;
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-	if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
+	if (lq_sta->pers.dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
 		IWL_DEBUG_RATE(mvm, "fixed tpc: %d\n",
-			       lq_sta->dbg_fixed_txp_reduction);
-		lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction;
-		return cur != lq_sta->dbg_fixed_txp_reduction;
+			       lq_sta->pers.dbg_fixed_txp_reduction);
+		lq_sta->lq.reduced_tpc = lq_sta->pers.dbg_fixed_txp_reduction;
+		return cur != lq_sta->pers.dbg_fixed_txp_reduction;
 	}
 #endif
 
@@ -2382,7 +2382,7 @@ static void rs_get_rate(void *mvm_r, str
 	}
 
 	/* Treat uninitialized rate scaling data same as non-existing. */
-	if (lq_sta && !lq_sta->drv) {
+	if (lq_sta && !lq_sta->pers.drv) {
 		IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
 		mvm_sta = NULL;
 	}
@@ -2401,12 +2401,18 @@ static void *rs_alloc_sta(void *mvm_rate
 			  gfp_t gfp)
 {
 	struct iwl_mvm_sta *sta_priv = (struct iwl_mvm_sta *)sta->drv_priv;
-	struct iwl_op_mode *op_mode __maybe_unused =
-			(struct iwl_op_mode *)mvm_rate;
-	struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
+	struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate;
+	struct iwl_mvm *mvm  = IWL_OP_MODE_GET_MVM(op_mode);
+	struct iwl_lq_sta *lq_sta = &sta_priv->lq_sta;
 
 	IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
 
+	lq_sta->pers.drv = mvm;
+#ifdef CONFIG_MAC80211_DEBUGFS
+	lq_sta->pers.dbg_fixed_rate = 0;
+	lq_sta->pers.dbg_fixed_txp_reduction = TPC_INVALID;
+#endif
+
 	return &sta_priv->lq_sta;
 }
 
@@ -2552,7 +2558,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm
 
 	sta_priv = (struct iwl_mvm_sta *)sta->drv_priv;
 	lq_sta = &sta_priv->lq_sta;
-	memset(lq_sta, 0, sizeof(*lq_sta));
+
+	/* clear all non-persistent lq data */
+	memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
 
 	sband = hw->wiphy->bands[band];
 
@@ -2630,17 +2638,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm
 
 	/* as default allow aggregation for all tids */
 	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
-	lq_sta->drv = mvm;
 
 	/* Set last_txrate_idx to lowest rate */
 	lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
 	if (sband->band == IEEE80211_BAND_5GHZ)
 		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 	lq_sta->is_agg = 0;
-#ifdef CONFIG_MAC80211_DEBUGFS
-	lq_sta->dbg_fixed_rate = 0;
-	lq_sta->dbg_fixed_txp_reduction = TPC_INVALID;
-#endif
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
 #endif
@@ -2811,12 +2814,12 @@ static void rs_fill_lq_cmd(struct iwl_mv
 	u8 ant = initial_rate->ant;
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-	if (lq_sta->dbg_fixed_rate) {
+	if (lq_sta->pers.dbg_fixed_rate) {
 		rs_build_rates_table_from_fixed(mvm, lq_cmd,
 						lq_sta->band,
-						lq_sta->dbg_fixed_rate);
+						lq_sta->pers.dbg_fixed_rate);
 		lq_cmd->reduced_tpc = 0;
-		ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
+		ant = (lq_sta->pers.dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
 			RATE_MCS_ANT_POS;
 	} else
 #endif
@@ -2926,14 +2929,14 @@ static void rs_program_fix_rate(struct i
 	lq_sta->active_mimo2_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
 
 	IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n",
-		       lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
+		       lq_sta->lq.sta_id, lq_sta->pers.dbg_fixed_rate);
 
-	if (lq_sta->dbg_fixed_rate) {
+	if (lq_sta->pers.dbg_fixed_rate) {
 		struct rs_rate rate;
-		rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate,
+		rs_rate_from_ucode_rate(lq_sta->pers.dbg_fixed_rate,
 					lq_sta->band, &rate);
 		rs_fill_lq_cmd(mvm, NULL, lq_sta, &rate);
-		iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false);
+		iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
 	}
 }
 
@@ -2946,16 +2949,16 @@ static ssize_t rs_sta_dbgfs_scale_table_
 	size_t buf_size;
 	u32 parsed_rate;
 
-	mvm = lq_sta->drv;
+	mvm = lq_sta->pers.drv;
 	memset(buf, 0, sizeof(buf));
 	buf_size = min(count, sizeof(buf) -  1);
 	if (copy_from_user(buf, user_buf, buf_size))
 		return -EFAULT;
 
 	if (sscanf(buf, "%x", &parsed_rate) == 1)
-		lq_sta->dbg_fixed_rate = parsed_rate;
+		lq_sta->pers.dbg_fixed_rate = parsed_rate;
 	else
-		lq_sta->dbg_fixed_rate = 0;
+		lq_sta->pers.dbg_fixed_rate = 0;
 
 	rs_program_fix_rate(mvm, lq_sta);
 
@@ -2974,7 +2977,7 @@ static ssize_t rs_sta_dbgfs_scale_table_
 	struct iwl_mvm *mvm;
 	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
 	struct rs_rate *rate = &tbl->rate;
-	mvm = lq_sta->drv;
+	mvm = lq_sta->pers.drv;
 	buff = kmalloc(2048, GFP_KERNEL);
 	if (!buff)
 		return -ENOMEM;
@@ -2984,7 +2987,7 @@ static ssize_t rs_sta_dbgfs_scale_table_
 			lq_sta->total_failed, lq_sta->total_success,
 			lq_sta->active_legacy_rate);
 	desc += sprintf(buff+desc, "fixed rate 0x%X\n",
-			lq_sta->dbg_fixed_rate);
+			lq_sta->pers.dbg_fixed_rate);
 	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
 	    (mvm->fw->valid_tx_ant & ANT_A) ? "ANT_A," : "",
 	    (mvm->fw->valid_tx_ant & ANT_B) ? "ANT_B," : "",
@@ -3182,31 +3185,20 @@ static const struct file_operations rs_s
 static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
 {
 	struct iwl_lq_sta *lq_sta = mvm_sta;
-	lq_sta->rs_sta_dbgfs_scale_table_file =
-		debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
-				    lq_sta, &rs_sta_dbgfs_scale_table_ops);
-	lq_sta->rs_sta_dbgfs_stats_table_file =
-		debugfs_create_file("rate_stats_table", S_IRUSR, dir,
-				    lq_sta, &rs_sta_dbgfs_stats_table_ops);
-	lq_sta->rs_sta_dbgfs_drv_tx_stats_file =
-		debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir,
-				    lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops);
-	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
-		debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
-				  &lq_sta->tx_agg_tid_en);
-	lq_sta->rs_sta_dbgfs_reduced_txp_file =
-		debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir,
-				  &lq_sta->dbg_fixed_txp_reduction);
+	debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
+			    lq_sta, &rs_sta_dbgfs_scale_table_ops);
+	debugfs_create_file("rate_stats_table", S_IRUSR, dir,
+			    lq_sta, &rs_sta_dbgfs_stats_table_ops);
+	debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir,
+			    lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops);
+	debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
+			  &lq_sta->tx_agg_tid_en);
+	debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir,
+			  &lq_sta->pers.dbg_fixed_txp_reduction);
 }
 
 static void rs_remove_debugfs(void *mvm, void *mvm_sta)
 {
-	struct iwl_lq_sta *lq_sta = mvm_sta;
-	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
-	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-	debugfs_remove(lq_sta->rs_sta_dbgfs_drv_tx_stats_file);
-	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
-	debugfs_remove(lq_sta->rs_sta_dbgfs_reduced_txp_file);
 }
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rs.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rs.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rs.h	2014-09-28 17:29:07.000000000 -0400
@@ -349,16 +349,6 @@ struct iwl_lq_sta {
 	struct iwl_lq_cmd lq;
 	struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
 	u8 tx_agg_tid_en;
-#ifdef CONFIG_MAC80211_DEBUGFS
-	struct dentry *rs_sta_dbgfs_scale_table_file;
-	struct dentry *rs_sta_dbgfs_stats_table_file;
-	struct dentry *rs_sta_dbgfs_drv_tx_stats_file;
-	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
-	struct dentry *rs_sta_dbgfs_reduced_txp_file;
-	u32 dbg_fixed_rate;
-	u8 dbg_fixed_txp_reduction;
-#endif
-	struct iwl_mvm *drv;
 
 	/* used to be in sta_info */
 	int last_txrate_idx;
@@ -369,6 +359,15 @@ struct iwl_lq_sta {
 
 	/* tx power reduce for this sta */
 	int tpc_reduce;
+
+	/* persistent fields - initialized only once - keep last! */
+	struct {
+#ifdef CONFIG_MAC80211_DEBUGFS
+		u32 dbg_fixed_rate;
+		u8 dbg_fixed_txp_reduction;
+#endif
+		struct iwl_mvm *drv;
+	} pers;
 };
 
 /* Initialize station's rate scaling information after adding station */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,13 +149,13 @@ static void iwl_mvm_get_signal_strength(
 	    le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
 	energy_a = (val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
 						IWL_RX_INFO_ENERGY_ANT_A_POS;
-	energy_a = energy_a ? -energy_a : -256;
+	energy_a = energy_a ? -energy_a : S8_MIN;
 	energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
 						IWL_RX_INFO_ENERGY_ANT_B_POS;
-	energy_b = energy_b ? -energy_b : -256;
+	energy_b = energy_b ? -energy_b : S8_MIN;
 	energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
 						IWL_RX_INFO_ENERGY_ANT_C_POS;
-	energy_c = energy_c ? -energy_c : -256;
+	energy_c = energy_c ? -energy_c : S8_MIN;
 	max_energy = max(energy_a, energy_b);
 	max_energy = max(max_energy, energy_c);
 
@@ -259,6 +259,23 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *m
 	memset(&rx_status, 0, sizeof(rx_status));
 
 	/*
+	 * We have tx blocked stations (with CS bit). If we heard frames from
+	 * a blocked station on a new channel we can TX to it again.
+	 */
+	if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
+		struct ieee80211_sta *sta;
+
+		rcu_read_lock();
+
+		sta = ieee80211_find_sta(
+			rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
+		if (sta)
+			iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
+
+		rcu_read_unlock();
+	}
+
+	/*
 	 * drop the packet if it has failed being decrypted by HW
 	 */
 	if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, &rx_status, rx_pkt_status)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,10 +97,9 @@ static inline __le16 iwl_mvm_scan_rx_cha
 	return cpu_to_le16(rx_chain);
 }
 
-static inline __le32
-iwl_mvm_scan_rxon_flags(struct cfg80211_scan_request *req)
+static __le32 iwl_mvm_scan_rxon_flags(enum ieee80211_band band)
 {
-	if (req->channels[0]->band == IEEE80211_BAND_2GHZ)
+	if (band == IEEE80211_BAND_2GHZ)
 		return cpu_to_le32(PHY_BAND_24);
 	else
 		return cpu_to_le32(PHY_BAND_5);
@@ -130,19 +129,19 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm
  * request list, is not copied here, but inserted directly to the probe
  * request.
  */
-static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
-				    struct cfg80211_scan_request *req,
-				    int first)
+static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid,
+				    struct cfg80211_ssid *ssids,
+				    int n_ssids, int first)
 {
 	int fw_idx, req_idx;
 
-	for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx >= first;
+	for (req_idx = n_ssids - 1, fw_idx = 0; req_idx >= first;
 	     req_idx--, fw_idx++) {
-		cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
-		cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
-		memcpy(cmd->direct_scan[fw_idx].ssid,
-		       req->ssids[req_idx].ssid,
-		       req->ssids[req_idx].ssid_len);
+		cmd_ssid[fw_idx].id = WLAN_EID_SSID;
+		cmd_ssid[fw_idx].len = ssids[req_idx].ssid_len;
+		memcpy(cmd_ssid[fw_idx].ssid,
+		       ssids[req_idx].ssid,
+		       ssids[req_idx].ssid_len);
 	}
 }
 
@@ -204,7 +203,8 @@ static void iwl_mvm_scan_fill_channels(s
  */
 static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
 				  int n_ssids, const u8 *ssid, int ssid_len,
-				  const u8 *ie, int ie_len,
+				  const u8 *band_ie, int band_ie_len,
+				  const u8 *common_ie, int common_ie_len,
 				  int left)
 {
 	int len = 0;
@@ -244,12 +244,19 @@ static u16 iwl_mvm_fill_probe_req(struct
 
 	len += ssid_len + 2;
 
-	if (WARN_ON(left < ie_len))
+	if (WARN_ON(left < band_ie_len + common_ie_len))
 		return len;
 
-	if (ie && ie_len) {
-		memcpy(pos, ie, ie_len);
-		len += ie_len;
+	if (band_ie && band_ie_len) {
+		memcpy(pos, band_ie, band_ie_len);
+		pos += band_ie_len;
+		len += band_ie_len;
+	}
+
+	if (common_ie && common_ie_len) {
+		memcpy(pos, common_ie, common_ie_len);
+		pos += common_ie_len;
+		len += common_ie_len;
 	}
 
 	return (u16)len;
@@ -267,7 +274,7 @@ static void iwl_mvm_scan_condition_itera
 
 static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
 				     struct ieee80211_vif *vif,
-				     int n_ssids,
+				     int n_ssids, u32 flags,
 				     struct iwl_mvm_scan_params *params)
 {
 	bool global_bound = false;
@@ -289,6 +296,9 @@ static void iwl_mvm_scan_calc_params(str
 		params->max_out_time = 250;
 	}
 
+	if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+		params->max_out_time = 200;
+
 not_bound:
 
 	for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
@@ -325,22 +335,20 @@ int iwl_mvm_scan_request(struct iwl_mvm
 
 	IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n");
 	mvm->scan_status = IWL_MVM_SCAN_OS;
-	memset(cmd, 0, sizeof(struct iwl_scan_cmd) +
-	       mvm->fw->ucode_capa.max_probe_length +
-	       (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel)));
+	memset(cmd, 0, ksize(cmd));
 
 	cmd->channel_count = (u8)req->n_channels;
 	cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME);
 	cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH);
 	cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm);
 
-	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, &params);
+	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags, &params);
 	cmd->max_out_time = cpu_to_le32(params.max_out_time);
 	cmd->suspend_time = cpu_to_le32(params.suspend_time);
 	if (params.passive_fragmented)
 		cmd->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN;
 
-	cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req);
+	cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band);
 	cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
 					MAC_FILTER_IN_BEACON);
 
@@ -367,7 +375,8 @@ int iwl_mvm_scan_request(struct iwl_mvm
 		cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
 	}
 
-	iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0);
+	iwl_mvm_scan_fill_ssids(cmd->direct_scan, req->ssids, req->n_ssids,
+				basic_ssid ? 1 : 0);
 
 	cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
 					   TX_CMD_FLG_BT_DIS);
@@ -382,7 +391,7 @@ int iwl_mvm_scan_request(struct iwl_mvm
 			    (struct ieee80211_mgmt *)cmd->data,
 			    vif->addr,
 			    req->n_ssids, ssid, ssid_len,
-			    req->ie, req->ie_len,
+			    req->ie, req->ie_len, NULL, 0,
 			    mvm->fw->ucode_capa.max_probe_length));
 
 	iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, &params);
@@ -441,16 +450,27 @@ int iwl_mvm_rx_scan_complete(struct iwl_
 	return 0;
 }
 
-int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
-				  struct iwl_rx_cmd_buffer *rxb,
-				  struct iwl_device_cmd *cmd)
+int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
+				    struct iwl_rx_cmd_buffer *rxb,
+				    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_sched_scan_results *notif = (void *)pkt->data;
+	u8 client_bitmap = 0;
 
-	if (notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
-		IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
-		ieee80211_sched_scan_results(mvm->hw);
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+		struct iwl_sched_scan_results *notif = (void *)pkt->data;
+
+		client_bitmap = notif->client_bitmap;
+	}
+
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
+	    client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
+		if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
+			IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
+			ieee80211_sched_scan_results(mvm->hw);
+		} else {
+			IWL_DEBUG_SCAN(mvm, "Scan results\n");
+		}
 	}
 
 	return 0;
@@ -494,7 +514,7 @@ static bool iwl_mvm_scan_abort_notif(str
 	};
 }
 
-int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
+static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm)
 {
 	struct iwl_notification_wait wait_scan_abort;
 	static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD,
@@ -535,33 +555,52 @@ int iwl_mvm_rx_scan_offload_complete_not
 					   struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_scan_offload_complete *scan_notif = (void *)pkt->data;
+	u8 status, ebs_status;
 
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) {
+		struct iwl_periodic_scan_complete *scan_notif;
+
+		scan_notif = (void *)pkt->data;
+		status = scan_notif->status;
+		ebs_status = scan_notif->ebs_status;
+	} else  {
+		struct iwl_scan_offload_complete *scan_notif;
+
+		scan_notif = (void *)pkt->data;
+		status = scan_notif->status;
+		ebs_status = scan_notif->ebs_status;
+	}
 	/* scan status must be locked for proper checking */
 	lockdep_assert_held(&mvm->mutex);
 
 	IWL_DEBUG_SCAN(mvm,
-		       "Scheduled scan completed, status %s EBS status %s:%d\n",
-		       scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
-		       "completed" : "aborted", scan_notif->ebs_status ==
-		       IWL_SCAN_EBS_SUCCESS ? "success" : "failed",
-		       scan_notif->ebs_status);
+		       "%s completed, status %s, EBS status %s\n",
+		       mvm->scan_status == IWL_MVM_SCAN_SCHED ?
+				"Scheduled scan" : "Scan",
+		       status == IWL_SCAN_OFFLOAD_COMPLETED ?
+				"completed" : "aborted",
+		       ebs_status == IWL_SCAN_EBS_SUCCESS ?
+				"success" : "failed");
 
 
 	/* only call mac80211 completion if the stop was initiated by FW */
 	if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
 		mvm->scan_status = IWL_MVM_SCAN_NONE;
 		ieee80211_sched_scan_stopped(mvm->hw);
+	} else if (mvm->scan_status == IWL_MVM_SCAN_OS) {
+		mvm->scan_status = IWL_MVM_SCAN_NONE;
+		ieee80211_scan_completed(mvm->hw,
+					 status == IWL_SCAN_OFFLOAD_ABORTED);
 	}
 
-	mvm->last_ebs_successful = !scan_notif->ebs_status;
+	mvm->last_ebs_successful = !ebs_status;
 
 	return 0;
 }
 
 static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm,
 					  struct ieee80211_vif *vif,
-					  struct ieee80211_sched_scan_ies *ies,
+					  struct ieee80211_scan_ies *ies,
 					  enum ieee80211_band band,
 					  struct iwl_tx_cmd *cmd,
 					  u8 *data)
@@ -577,7 +616,8 @@ static void iwl_scan_offload_build_tx_cm
 	cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data,
 					 vif->addr,
 					 1, NULL, 0,
-					 ies->ie[band], ies->len[band],
+					 ies->ies[band], ies->len[band],
+					 ies->common_ies, ies->common_ie_len,
 					 SCAN_OFFLOAD_PROBE_REQ_SIZE);
 	cmd->len = cpu_to_le16(cmd_len);
 }
@@ -621,8 +661,8 @@ static int iwl_ssid_exist(u8 *ssid, u8 s
 }
 
 static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
-					struct iwl_scan_offload_cmd *scan,
-					u32 *ssid_bitmap)
+					struct iwl_ssid_ie *direct_scan,
+					u32 *ssid_bitmap, bool basic_ssid)
 {
 	int i, j;
 	int index;
@@ -636,10 +676,10 @@ static void iwl_scan_offload_build_ssid(
 		/* skip empty SSID matchsets */
 		if (!req->match_sets[i].ssid.ssid_len)
 			continue;
-		scan->direct_scan[i].id = WLAN_EID_SSID;
-		scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
-		memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
-		       scan->direct_scan[i].len);
+		direct_scan[i].id = WLAN_EID_SSID;
+		direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
+		memcpy(direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
+		       direct_scan[i].len);
 	}
 
 	/* add SSIDs from scan SSID list */
@@ -647,14 +687,14 @@ static void iwl_scan_offload_build_ssid(
 	for (j = 0; j < req->n_ssids && i < PROBE_OPTION_MAX; j++) {
 		index = iwl_ssid_exist(req->ssids[j].ssid,
 				       req->ssids[j].ssid_len,
-				       scan->direct_scan);
+				       direct_scan);
 		if (index < 0) {
-			if (!req->ssids[j].ssid_len)
+			if (!req->ssids[j].ssid_len && basic_ssid)
 				continue;
-			scan->direct_scan[i].id = WLAN_EID_SSID;
-			scan->direct_scan[i].len = req->ssids[j].ssid_len;
-			memcpy(scan->direct_scan[i].ssid, req->ssids[j].ssid,
-			       scan->direct_scan[i].len);
+			direct_scan[i].id = WLAN_EID_SSID;
+			direct_scan[i].len = req->ssids[j].ssid_len;
+			memcpy(direct_scan[i].ssid, req->ssids[j].ssid,
+			       direct_scan[i].len);
 			*ssid_bitmap |= BIT(i + 1);
 			i++;
 		} else {
@@ -665,12 +705,19 @@ static void iwl_scan_offload_build_ssid(
 
 static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
 				  struct cfg80211_sched_scan_request *req,
-				  struct iwl_scan_channel_cfg *channels,
+				  u8 *channels_buffer,
 				  enum ieee80211_band band,
 				  int *head,
 				  u32 ssid_bitmap,
 				  struct iwl_mvm_scan_params *params)
 {
+	u32 n_channels = mvm->fw->ucode_capa.n_scan_channels;
+	__le32 *type = (__le32 *)channels_buffer;
+	__le16 *channel_number = (__le16 *)(type + n_channels);
+	__le16 *iter_count = channel_number + n_channels;
+	__le32 *iter_interval = (__le32 *)(iter_count + n_channels);
+	u8 *active_dwell = (u8 *)(iter_interval + n_channels);
+	u8 *passive_dwell = active_dwell + n_channels;
 	int i, index = 0;
 
 	for (i = 0; i < req->n_channels; i++) {
@@ -682,34 +729,33 @@ static void iwl_build_channel_cfg(struct
 		index = *head;
 		(*head)++;
 
-		channels->channel_number[index] = cpu_to_le16(chan->hw_value);
-		channels->dwell_time[index][0] = params->dwell[band].active;
-		channels->dwell_time[index][1] = params->dwell[band].passive;
+		channel_number[index] = cpu_to_le16(chan->hw_value);
+		active_dwell[index] = params->dwell[band].active;
+		passive_dwell[index] = params->dwell[band].passive;
 
-		channels->iter_count[index] = cpu_to_le16(1);
-		channels->iter_interval[index] = 0;
+		iter_count[index] = cpu_to_le16(1);
+		iter_interval[index] = 0;
 
 		if (!(chan->flags & IEEE80211_CHAN_NO_IR))
-			channels->type[index] |=
+			type[index] |=
 				cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
 
-		channels->type[index] |=
-				cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
-					    IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
+		type[index] |= cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
+					   IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
 
 		if (chan->flags & IEEE80211_CHAN_NO_HT40)
-			channels->type[index] |=
+			type[index] |=
 				cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW);
 
 		/* scan for all SSIDs from req->ssids */
-		channels->type[index] |= cpu_to_le32(ssid_bitmap);
+		type[index] |= cpu_to_le32(ssid_bitmap);
 	}
 }
 
 int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
 			      struct ieee80211_vif *vif,
 			      struct cfg80211_sched_scan_request *req,
-			      struct ieee80211_sched_scan_ies *ies)
+			      struct ieee80211_scan_ies *ies)
 {
 	int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
 	int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
@@ -717,6 +763,9 @@ int iwl_mvm_config_sched_scan(struct iwl
 	u32 ssid_bitmap;
 	int cmd_len;
 	int ret;
+	u8 *probes;
+	bool basic_ssid = !(mvm->fw->ucode_capa.flags &
+			    IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID);
 
 	struct iwl_scan_offload_cfg *scan_cfg;
 	struct iwl_host_cmd cmd = {
@@ -727,24 +776,29 @@ int iwl_mvm_config_sched_scan(struct iwl
 	lockdep_assert_held(&mvm->mutex);
 
 	cmd_len = sizeof(struct iwl_scan_offload_cfg) +
+		  mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE +
 		  2 * SCAN_OFFLOAD_PROBE_REQ_SIZE;
 
 	scan_cfg = kzalloc(cmd_len, GFP_KERNEL);
 	if (!scan_cfg)
 		return -ENOMEM;
 
-	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, &params);
+	probes = scan_cfg->data +
+		mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE;
+
+	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, &params);
 	iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, &params);
 	scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len);
 
-	iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap);
+	iwl_scan_offload_build_ssid(req, scan_cfg->scan_cmd.direct_scan,
+				    &ssid_bitmap, basic_ssid);
 	/* build tx frames for supported bands */
 	if (band_2ghz) {
 		iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
 					      IEEE80211_BAND_2GHZ,
 					      &scan_cfg->scan_cmd.tx_cmd[0],
-					      scan_cfg->data);
-		iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+					      probes);
+		iwl_build_channel_cfg(mvm, req, scan_cfg->data,
 				      IEEE80211_BAND_2GHZ, &head,
 				      ssid_bitmap, &params);
 	}
@@ -752,9 +806,9 @@ int iwl_mvm_config_sched_scan(struct iwl
 		iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
 					      IEEE80211_BAND_5GHZ,
 					      &scan_cfg->scan_cmd.tx_cmd[1],
-					      scan_cfg->data +
+					      probes +
 						SCAN_OFFLOAD_PROBE_REQ_SIZE);
-		iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+		iwl_build_channel_cfg(mvm, req, scan_cfg->data,
 				      IEEE80211_BAND_5GHZ, &head,
 				      ssid_bitmap, &params);
 	}
@@ -845,11 +899,11 @@ int iwl_mvm_sched_scan_start(struct iwl_
 		.watchdog = IWL_SCHED_SCAN_WATCHDOG,
 
 		.schedule_line[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS,
-		.schedule_line[0].delay = req->interval / 1000,
+		.schedule_line[0].delay = cpu_to_le16(req->interval / 1000),
 		.schedule_line[0].full_scan_mul = 1,
 
 		.schedule_line[1].iterations = 0xff,
-		.schedule_line[1].delay = req->interval / 1000,
+		.schedule_line[1].delay = cpu_to_le16(req->interval / 1000),
 		.schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER,
 	};
 
@@ -872,7 +926,7 @@ int iwl_mvm_sched_scan_start(struct iwl_
 				    sizeof(scan_req), &scan_req);
 }
 
-static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
+static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
 {
 	int ret;
 	struct iwl_host_cmd cmd = {
@@ -883,7 +937,9 @@ static int iwl_mvm_send_sched_scan_abort
 	/* Exit instantly with error when device is not ready
 	 * to receive scan abort command or it does not perform
 	 * scheduled scan currently */
-	if (mvm->scan_status != IWL_MVM_SCAN_SCHED)
+	if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+	    (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
+	     mvm->scan_status != IWL_MVM_SCAN_OS))
 		return -EIO;
 
 	ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
@@ -905,16 +961,19 @@ static int iwl_mvm_send_sched_scan_abort
 	return ret;
 }
 
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify)
+int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
 {
 	int ret;
 	struct iwl_notification_wait wait_scan_done;
 	static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
+	bool sched = mvm->scan_status == IWL_MVM_SCAN_SCHED;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (mvm->scan_status != IWL_MVM_SCAN_SCHED) {
-		IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n");
+	if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+	    (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
+	     mvm->scan_status != IWL_MVM_SCAN_OS)) {
+		IWL_DEBUG_SCAN(mvm, "No scan to stop\n");
 		return 0;
 	}
 
@@ -923,14 +982,16 @@ int iwl_mvm_sched_scan_stop(struct iwl_m
 				   ARRAY_SIZE(scan_done_notif),
 				   NULL, NULL);
 
-	ret = iwl_mvm_send_sched_scan_abort(mvm);
+	ret = iwl_mvm_send_scan_offload_abort(mvm);
 	if (ret) {
-		IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret);
+		IWL_DEBUG_SCAN(mvm, "Send stop %sscan failed %d\n",
+			       sched ? "offloaded " : "", ret);
 		iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
 		return ret;
 	}
 
-	IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n");
+	IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
+		       sched ? "offloaded " : "");
 
 	ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
 	if (ret)
@@ -943,8 +1004,317 @@ int iwl_mvm_sched_scan_stop(struct iwl_m
 	 */
 	mvm->scan_status = IWL_MVM_SCAN_NONE;
 
-	if (notify)
-		ieee80211_sched_scan_stopped(mvm->hw);
+	if (notify) {
+		if (sched)
+			ieee80211_sched_scan_stopped(mvm->hw);
+		else
+			ieee80211_scan_completed(mvm->hw, true);
+	}
 
 	return 0;
 }
+
+static void iwl_mvm_unified_scan_fill_tx_cmd(struct iwl_mvm *mvm,
+					     struct iwl_scan_req_tx_cmd *tx_cmd,
+					     bool no_cck)
+{
+	tx_cmd[0].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
+					 TX_CMD_FLG_BT_DIS);
+	tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
+							   IEEE80211_BAND_2GHZ,
+							   no_cck);
+	tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
+
+	tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
+					 TX_CMD_FLG_BT_DIS);
+	tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
+							   IEEE80211_BAND_5GHZ,
+							   no_cck);
+	tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
+}
+
+static void
+iwl_mvm_lmac_scan_cfg_channels(struct iwl_mvm *mvm,
+			       struct ieee80211_channel **channels,
+			       int n_channels, u32 ssid_bitmap,
+			       struct iwl_scan_req_unified_lmac *cmd)
+{
+	struct iwl_scan_channel_cfg_lmac *channel_cfg = (void *)&cmd->data;
+	int i;
+
+	for (i = 0; i < n_channels; i++) {
+		channel_cfg[i].channel_num =
+			cpu_to_le16(channels[i]->hw_value);
+		channel_cfg[i].iter_count = cpu_to_le16(1);
+		channel_cfg[i].iter_interval = 0;
+		channel_cfg[i].flags =
+			cpu_to_le32(IWL_UNIFIED_SCAN_CHANNEL_PARTIAL |
+				    ssid_bitmap);
+	}
+}
+
+static void
+iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+				 struct ieee80211_scan_ies *ies,
+				 struct iwl_scan_req_unified_lmac *cmd)
+{
+	struct iwl_scan_probe_req *preq = (void *)(cmd->data +
+		sizeof(struct iwl_scan_channel_cfg_lmac) *
+			mvm->fw->ucode_capa.n_scan_channels);
+	struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
+	u8 *pos;
+
+	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+	eth_broadcast_addr(frame->da);
+	memcpy(frame->sa, vif->addr, ETH_ALEN);
+	eth_broadcast_addr(frame->bssid);
+	frame->seq_ctrl = 0;
+
+	pos = frame->u.probe_req.variable;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = 0;
+
+	preq->mac_header.offset = 0;
+	preq->mac_header.len = cpu_to_le16(24 + 2);
+
+	memcpy(pos, ies->ies[IEEE80211_BAND_2GHZ],
+	       ies->len[IEEE80211_BAND_2GHZ]);
+	preq->band_data[0].offset = cpu_to_le16(pos - preq->buf);
+	preq->band_data[0].len = cpu_to_le16(ies->len[IEEE80211_BAND_2GHZ]);
+	pos += ies->len[IEEE80211_BAND_2GHZ];
+
+	memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ],
+	       ies->len[IEEE80211_BAND_5GHZ]);
+	preq->band_data[1].offset = cpu_to_le16(pos - preq->buf);
+	preq->band_data[1].len = cpu_to_le16(ies->len[IEEE80211_BAND_5GHZ]);
+	pos += ies->len[IEEE80211_BAND_5GHZ];
+
+	memcpy(pos, ies->common_ies, ies->common_ie_len);
+	preq->common_data.offset = cpu_to_le16(pos - preq->buf);
+	preq->common_data.len = cpu_to_le16(ies->common_ie_len);
+}
+
+static void
+iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
+				       struct iwl_scan_req_unified_lmac *cmd,
+				       struct iwl_mvm_scan_params *params)
+{
+	memset(cmd, 0, ksize(cmd));
+	cmd->active_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].active;
+	cmd->passive_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].passive;
+	/* TODO: Use params; now fragmented isn't used. */
+	cmd->fragmented_dwell = 0;
+	cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
+	cmd->max_out_time = cpu_to_le32(params->max_out_time);
+	cmd->suspend_time = cpu_to_le32(params->suspend_time);
+	cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+	cmd->iter_num = cpu_to_le32(1);
+
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT &&
+	    mvm->last_ebs_successful) {
+		cmd->channel_opt[0].flags =
+			cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
+				    IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
+				    IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
+		cmd->channel_opt[1].flags =
+			cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
+				    IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
+				    IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
+	}
+}
+
+int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
+			      struct ieee80211_vif *vif,
+			      struct ieee80211_scan_request *req)
+{
+	struct iwl_host_cmd hcmd = {
+		.id = SCAN_OFFLOAD_REQUEST_CMD,
+		.len = { sizeof(struct iwl_scan_req_unified_lmac) +
+			 sizeof(struct iwl_scan_channel_cfg_lmac) *
+				mvm->fw->ucode_capa.n_scan_channels +
+			 sizeof(struct iwl_scan_probe_req), },
+		.data = { mvm->scan_cmd, },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+	};
+	struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
+	struct iwl_mvm_scan_params params = {};
+	u32 flags;
+	int ssid_bitmap = 0;
+	int ret, i;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	/* we should have failed registration if scan_cmd was NULL */
+	if (WARN_ON(mvm->scan_cmd == NULL))
+		return -ENOMEM;
+
+	if (WARN_ON_ONCE(req->req.n_ssids > PROBE_OPTION_MAX ||
+			 req->ies.common_ie_len + req->ies.len[0] +
+				req->ies.len[1] + 24 + 2 >
+					SCAN_OFFLOAD_PROBE_REQ_SIZE ||
+			 req->req.n_channels >
+				mvm->fw->ucode_capa.n_scan_channels))
+		return -1;
+
+	mvm->scan_status = IWL_MVM_SCAN_OS;
+
+	iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
+				 &params);
+
+	iwl_mvm_build_generic_unified_scan_cmd(mvm, cmd, &params);
+
+	cmd->n_channels = (u8)req->req.n_channels;
+
+	flags = IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+
+	if (req->req.n_ssids == 1 && req->req.ssids[0].ssid_len != 0)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
+
+	if (params.passive_fragmented)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
+
+	if (req->req.n_ssids == 0)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
+
+	cmd->scan_flags = cpu_to_le32(flags);
+
+	cmd->flags = iwl_mvm_scan_rxon_flags(req->req.channels[0]->band);
+	cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
+					MAC_FILTER_IN_BEACON);
+	iwl_mvm_unified_scan_fill_tx_cmd(mvm, cmd->tx_cmd, req->req.no_cck);
+	iwl_mvm_scan_fill_ssids(cmd->direct_scan, req->req.ssids,
+				req->req.n_ssids, 0);
+
+	cmd->schedule[0].delay = 0;
+	cmd->schedule[0].iterations = 1;
+	cmd->schedule[0].full_scan_mul = 0;
+	cmd->schedule[1].delay = 0;
+	cmd->schedule[1].iterations = 0;
+	cmd->schedule[1].full_scan_mul = 0;
+
+	for (i = 1; i <= req->req.n_ssids; i++)
+		ssid_bitmap |= BIT(i);
+
+	iwl_mvm_lmac_scan_cfg_channels(mvm, req->req.channels,
+				       req->req.n_channels, ssid_bitmap,
+				       cmd);
+
+	iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, cmd);
+
+	ret = iwl_mvm_send_cmd(mvm, &hcmd);
+	if (!ret) {
+		IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
+	} else {
+		/*
+		 * If the scan failed, it usually means that the FW was unable
+		 * to allocate the time events. Warn on it, but maybe we
+		 * should try to send the command again with different params.
+		 */
+		IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
+		mvm->scan_status = IWL_MVM_SCAN_NONE;
+		ret = -EIO;
+	}
+	return ret;
+}
+
+int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
+				    struct ieee80211_vif *vif,
+				    struct cfg80211_sched_scan_request *req,
+				    struct ieee80211_scan_ies *ies)
+{
+	struct iwl_host_cmd hcmd = {
+		.id = SCAN_OFFLOAD_REQUEST_CMD,
+		.len = { sizeof(struct iwl_scan_req_unified_lmac) +
+			 sizeof(struct iwl_scan_channel_cfg_lmac) *
+				mvm->fw->ucode_capa.n_scan_channels +
+			 sizeof(struct iwl_scan_probe_req), },
+		.data = { mvm->scan_cmd, },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+	};
+	struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
+	struct iwl_mvm_scan_params params = {};
+	int ret;
+	u32 flags = 0, ssid_bitmap = 0;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	/* we should have failed registration if scan_cmd was NULL */
+	if (WARN_ON(mvm->scan_cmd == NULL))
+		return -ENOMEM;
+
+	if (WARN_ON_ONCE(req->n_ssids > PROBE_OPTION_MAX ||
+			 ies->common_ie_len + ies->len[0] + ies->len[1] + 24 + 2
+				> SCAN_OFFLOAD_PROBE_REQ_SIZE ||
+			 req->n_channels > mvm->fw->ucode_capa.n_scan_channels))
+		return -ENOBUFS;
+
+	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, &params);
+
+	iwl_mvm_build_generic_unified_scan_cmd(mvm, cmd, &params);
+
+	cmd->n_channels = (u8)req->n_channels;
+
+	if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending scheduled scan with filtering, n_match_sets %d\n",
+			       req->n_match_sets);
+	} else {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending Scheduled scan without filtering\n");
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+	}
+
+	if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
+
+	if (params.passive_fragmented)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
+
+	if (req->n_ssids == 0)
+		flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
+
+	cmd->scan_flags = cpu_to_le32(flags);
+
+	cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band);
+	cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
+					MAC_FILTER_IN_BEACON);
+	iwl_mvm_unified_scan_fill_tx_cmd(mvm, cmd->tx_cmd, false);
+	iwl_scan_offload_build_ssid(req, cmd->direct_scan, &ssid_bitmap, false);
+
+	cmd->schedule[0].delay = cpu_to_le16(req->interval / MSEC_PER_SEC);
+	cmd->schedule[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS;
+	cmd->schedule[0].full_scan_mul = 1;
+
+	cmd->schedule[1].delay = cpu_to_le16(req->interval / MSEC_PER_SEC);
+	cmd->schedule[1].iterations = 0xff;
+	cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER;
+
+	iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels,
+				       ssid_bitmap, cmd);
+
+	iwl_mvm_build_unified_scan_probe(mvm, vif, ies, cmd);
+
+	ret = iwl_mvm_send_cmd(mvm, &hcmd);
+	if (!ret) {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sched scan request was sent successfully\n");
+	} else {
+		/*
+		 * If the scan failed, it usually means that the FW was unable
+		 * to allocate the time events. Warn on it, but maybe we
+		 * should try to send the command again with different params.
+		 */
+		IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
+		mvm->scan_status = IWL_MVM_SCAN_NONE;
+		ret = -EIO;
+	}
+	return ret;
+}
+
+
+int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
+{
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		return iwl_mvm_scan_offload_stop(mvm, true);
+	return iwl_mvm_cancel_regular_scan(mvm);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sf.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sf.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sf.c	2014-09-28 17:29:07.000000000 -0400
@@ -172,7 +172,7 @@ static int iwl_mvm_sf_config(struct iwl_
 			     enum iwl_sf_state new_state)
 {
 	struct iwl_sf_cfg_cmd sf_cmd = {
-		.state = new_state,
+		.state = cpu_to_le32(new_state),
 	};
 	struct ieee80211_sta *sta;
 	int ret = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sta.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sta.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sta.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sta.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mv
 			   bool update)
 {
 	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
-	struct iwl_mvm_add_sta_cmd add_sta_cmd;
+	struct iwl_mvm_add_sta_cmd add_sta_cmd = {
+		.sta_id = mvm_sta->sta_id,
+		.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
+		.add_modify = update ? 1 : 0,
+		.station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
+						 STA_FLG_MIMO_EN_MSK),
+	};
 	int ret;
 	u32 status;
 	u32 agg_size = 0, mpdu_dens = 0;
 
-	memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
-
-	add_sta_cmd.sta_id = mvm_sta->sta_id;
-	add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 	if (!update) {
 		add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
 		memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
 	}
-	add_sta_cmd.add_modify = update ? 1 : 0;
-
-	add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
-						     STA_FLG_MIMO_EN_MSK);
 
 	switch (sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_160:
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *
 
 	lockdep_assert_held(&mvm->mutex);
 
-	/* Add the aux station, but without any queues */
-	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0,
+	/* Map Aux queue to fifo - needs to happen before adding Aux station */
+	iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
+				IWL_MVM_TX_FIFO_MCAST);
+
+	/* Allocate aux station and assign to it the aux queue */
+	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
 				       NL80211_IFTYPE_UNSPECIFIED);
 	if (ret)
 		return ret;
@@ -1448,3 +1450,77 @@ int iwl_mvm_rx_eosp_notif(struct iwl_mvm
 
 	return 0;
 }
+
+void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
+				   struct iwl_mvm_sta *mvmsta, bool disable)
+{
+	struct iwl_mvm_add_sta_cmd cmd = {
+		.add_modify = STA_MODE_MODIFY,
+		.sta_id = mvmsta->sta_id,
+		.station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0,
+		.station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX),
+		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
+	};
+	int ret;
+
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_DISABLE_STA_TX))
+		return;
+
+	ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
+	if (ret)
+		IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
+}
+
+void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+				      struct ieee80211_sta *sta,
+				      bool disable)
+{
+	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+	spin_lock_bh(&mvm_sta->lock);
+
+	if (mvm_sta->disable_tx == disable) {
+		spin_unlock_bh(&mvm_sta->lock);
+		return;
+	}
+
+	mvm_sta->disable_tx = disable;
+
+	/*
+	 * Tell mac80211 to start/stop queueing tx for this station,
+	 * but don't stop queueing if there are still pending frames
+	 * for this station.
+	 */
+	if (disable || !atomic_read(&mvm->pending_frames[mvm_sta->sta_id]))
+		ieee80211_sta_block_awake(mvm->hw, sta, disable);
+
+	iwl_mvm_sta_modify_disable_tx(mvm, mvm_sta, disable);
+
+	spin_unlock_bh(&mvm_sta->lock);
+}
+
+void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
+				       struct iwl_mvm_vif *mvmvif,
+				       bool disable)
+{
+	struct ieee80211_sta *sta;
+	struct iwl_mvm_sta *mvm_sta;
+	int i;
+
+	lockdep_assert_held(&mvm->mutex);
+
+	/* Block/unblock all the stations of the given mvmvif */
+	for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+						lockdep_is_held(&mvm->mutex));
+		if (IS_ERR_OR_NULL(sta))
+			continue;
+
+		mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+		if (mvm_sta->mac_id_n_color !=
+		    FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color))
+			continue;
+
+		iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, disable);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sta.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sta.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/sta.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/sta.h	2014-09-28 17:29:07.000000000 -0400
@@ -73,6 +73,7 @@
 #include "rs.h"
 
 struct iwl_mvm;
+struct iwl_mvm_vif;
 
 /**
  * DOC: station table - introduction
@@ -295,6 +296,7 @@ static inline u16 iwl_mvm_tid_queued(str
  * @tid_data: per tid data. Look at %iwl_mvm_tid_data.
  * @tx_protection: reference counter for controlling the Tx protection.
  * @tt_tx_protection: is thermal throttling enable Tx protection?
+ * @disable_tx: is tx to this STA disabled?
  *
  * When mac80211 creates a station it reserves some space (hw->sta_data_size)
  * in the structure for use by driver. This structure is placed in that
@@ -317,6 +319,8 @@ struct iwl_mvm_sta {
 	/* Temporary, until the new TLC will control the Tx protection */
 	s8 tx_protection;
 	bool tt_tx_protection;
+
+	bool disable_tx;
 };
 
 static inline struct iwl_mvm_sta *
@@ -404,5 +408,13 @@ void iwl_mvm_sta_modify_sleep_tx_count(s
 				       bool agg);
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 		      bool drain);
+void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
+				   struct iwl_mvm_sta *mvmsta, bool disable);
+void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+				      struct ieee80211_sta *sta,
+				      bool disable);
+void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
+				       struct iwl_mvm_vif *mvmvif,
+				       bool disable);
 
 #endif /* __sta_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,9 +72,6 @@
 #include "iwl-io.h"
 #include "iwl-prph.h"
 
-/* A TimeUnit is 1024 microsecond */
-#define MSEC_TO_TU(_msec)	(_msec*1000/1024)
-
 /*
  * For the high priority TE use a time event type that has similar priority to
  * the FW's action scan priority.
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mv
 void iwl_mvm_roc_done_wk(struct work_struct *wk)
 {
 	struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk);
+	u32 queues = 0;
+
+	/*
+	 * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
+	 * This will cause the TX path to drop offchannel transmissions.
+	 * That would also be done by mac80211, but it is racy, in particular
+	 * in the case that the time event actually completed in the firmware
+	 * (which is handled in iwl_mvm_te_handle_notif).
+	 */
+	if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
+		queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
+	if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
+		queues |= BIT(mvm->aux_queue);
+
+	iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
 
 	synchronize_net();
 
@@ -113,22 +125,12 @@ void iwl_mvm_roc_done_wk(struct work_str
 	 * issue as it will have to complete before the next command is
 	 * executed, and a new time event means a new command.
 	 */
-	iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
+	iwl_mvm_flush_tx_path(mvm, queues, false);
 }
 
 static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
 {
 	/*
-	 * First, clear the ROC_RUNNING status bit. This will cause the TX
-	 * path to drop offchannel transmissions. That would also be done
-	 * by mac80211, but it is racy, in particular in the case that the
-	 * time event actually completed in the firmware (which is handled
-	 * in iwl_mvm_te_handle_notif).
-	 */
-	clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
-	iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
-
-	/*
 	 * Of course, our status bit is just as racy as mac80211, so in
 	 * addition, fire off the work struct which will drop all frames
 	 * from the hardware queues that made it through the race. First
@@ -138,6 +140,41 @@ static void iwl_mvm_roc_finished(struct
 	schedule_work(&mvm->roc_done_wk);
 }
 
+static void iwl_mvm_csa_noa_start(struct iwl_mvm *mvm)
+{
+	struct ieee80211_vif *csa_vif;
+
+	rcu_read_lock();
+
+	csa_vif = rcu_dereference(mvm->csa_vif);
+	if (!csa_vif || !csa_vif->csa_active)
+		goto out_unlock;
+
+	IWL_DEBUG_TE(mvm, "CSA NOA started\n");
+
+	/*
+	 * CSA NoA is started but we still have beacons to
+	 * transmit on the current channel.
+	 * So we just do nothing here and the switch
+	 * will be performed on the last TBTT.
+	 */
+	if (!ieee80211_csa_is_complete(csa_vif)) {
+		IWL_WARN(mvm, "CSA NOA started too early\n");
+		goto out_unlock;
+	}
+
+	ieee80211_csa_finish(csa_vif);
+
+	rcu_read_unlock();
+
+	RCU_INIT_POINTER(mvm->csa_vif, NULL);
+
+	return;
+
+out_unlock:
+	rcu_read_unlock();
+}
+
 static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
 					struct ieee80211_vif *vif,
 					const char *errmsg)
@@ -213,6 +250,14 @@ static void iwl_mvm_te_handle_notif(stru
 			set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
 			iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
 			ieee80211_ready_on_channel(mvm->hw);
+		} else if (te_data->vif->type == NL80211_IFTYPE_AP) {
+			if (le32_to_cpu(notif->status))
+				iwl_mvm_csa_noa_start(mvm);
+			else
+				IWL_DEBUG_TE(mvm, "CSA NOA failed to start\n");
+
+			/* we don't need it anymore */
+			iwl_mvm_te_clear_data(mvm, te_data);
 		}
 	} else {
 		IWL_WARN(mvm, "Got TE with unknown action\n");
@@ -220,6 +265,60 @@ static void iwl_mvm_te_handle_notif(stru
 }
 
 /*
+ * Handle A Aux ROC time event
+ */
+static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
+					   struct iwl_time_event_notif *notif)
+{
+	struct iwl_mvm_time_event_data *te_data, *tmp;
+	bool aux_roc_te = false;
+
+	list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
+		if (le32_to_cpu(notif->unique_id) == te_data->uid) {
+			aux_roc_te = true;
+			break;
+		}
+	}
+	if (!aux_roc_te) /* Not a Aux ROC time event */
+		return -EINVAL;
+
+	if (!le32_to_cpu(notif->status)) {
+		IWL_DEBUG_TE(mvm,
+			     "ERROR: Aux ROC Time Event %s notification failure\n",
+			     (le32_to_cpu(notif->action) &
+			      TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end");
+		return -EINVAL;
+	}
+
+	IWL_DEBUG_TE(mvm,
+		     "Aux ROC time event notification  - UID = 0x%x action %d\n",
+		     le32_to_cpu(notif->unique_id),
+		     le32_to_cpu(notif->action));
+
+	if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
+		/* End TE, notify mac80211 */
+		ieee80211_remain_on_channel_expired(mvm->hw);
+		iwl_mvm_roc_finished(mvm); /* flush aux queue */
+		list_del(&te_data->list); /* remove from list */
+		te_data->running = false;
+		te_data->vif = NULL;
+		te_data->uid = 0;
+	} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
+		set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
+		set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
+		te_data->running = true;
+		ieee80211_ready_on_channel(mvm->hw); /* Start TE */
+	} else {
+		IWL_DEBUG_TE(mvm,
+			     "ERROR: Unknown Aux ROC Time Event (action = %d)\n",
+			     le32_to_cpu(notif->action));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
  * The Rx handler for time event notifications
  */
 int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
@@ -235,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct i
 		     le32_to_cpu(notif->action));
 
 	spin_lock_bh(&mvm->time_event_lock);
+	/* This time event is triggered for Aux ROC request */
+	if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif))
+		goto unlock;
+
 	list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
 		if (le32_to_cpu(notif->unique_id) == te_data->uid)
 			iwl_mvm_te_handle_notif(mvm, te_data, notif);
 	}
+unlock:
 	spin_unlock_bh(&mvm->time_event_lock);
 
 	return 0;
@@ -538,3 +642,33 @@ void iwl_mvm_stop_p2p_roc(struct iwl_mvm
 
 	iwl_mvm_roc_finished(mvm);
 }
+
+int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
+			      struct ieee80211_vif *vif,
+			      u32 duration, u32 apply_time)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
+	struct iwl_time_event_cmd time_cmd = {};
+
+	lockdep_assert_held(&mvm->mutex);
+
+	if (te_data->running) {
+		IWL_DEBUG_TE(mvm, "CS NOA is already scheduled\n");
+		return -EBUSY;
+	}
+
+	time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
+	time_cmd.id_and_color =
+		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
+	time_cmd.id = cpu_to_le32(TE_P2P_GO_CSA_NOA);
+	time_cmd.apply_time = cpu_to_le32(apply_time);
+	time_cmd.max_frags = TE_V2_FRAG_NONE;
+	time_cmd.duration = cpu_to_le32(duration);
+	time_cmd.repeat = 1;
+	time_cmd.interval = cpu_to_le32(1);
+	time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
+				      TE_V2_ABSENCE);
+
+	return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/time-event.h	2014-09-28 17:29:07.000000000 -0400
@@ -214,4 +214,33 @@ void iwl_mvm_te_clear_data(struct iwl_mv
 
 void iwl_mvm_roc_done_wk(struct work_struct *wk);
 
+/**
+ * iwl_mvm_schedule_csa_noa - request NoA for channel switch
+ * @mvm: the mvm component
+ * @vif: the virtual interface for which the channel switch is issued
+ * @duration: the duration of the NoA in TU.
+ * @apply_time: NoA start time in GP2.
+ *
+ * This function is used to schedule NoA time event and is used to perform
+ * the channel switch flow.
+ */
+int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
+			     struct ieee80211_vif *vif,
+			     u32 duration, u32 apply_time);
+
+/**
+ * iwl_mvm_te_scheduled - check if the fw received the TE cmd
+ * @te_data: the time event data that corresponds to that time event
+ *
+ * This function returns true iff this TE is added to the fw.
+ */
+static inline bool
+iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
+{
+	if (!te_data)
+		return false;
+
+	return !!te_data->uid;
+}
+
 #endif /* __time_event_h__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/tt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/tt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/tt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/tt.c	2014-09-28 17:29:07.000000000 -0400
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviatio
 
 	/* TODO: move parsing to NVM code */
 	calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
-	ptat = calib[OTP_DTS_DIODE_DEVIATION];
-	pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1];
-	pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2];
+	ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
+	pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
+	pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
 
 	/* get the median: */
 	if (ptat > pa1) {
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct wor
 
 	duration = tt->params->ct_kill_duration;
 
+	/* make sure the device is available for direct read/writes */
+	if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
+		goto reschedule;
+
 	iwl_trans_start_hw(mvm->trans);
 	temp = check_nic_temperature(mvm);
 	iwl_trans_stop_device(mvm->trans);
 
+	iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
+
 	if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
 		IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
 		goto reschedule;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,7 +131,6 @@ static void iwl_mvm_set_tx_cmd(struct iw
 	    !is_multicast_ether_addr(ieee80211_get_DA(hdr)))
 		tx_flags |= TX_CMD_FLG_PROT_REQUIRE;
 
-	tx_cmd->driver_txop = 0;
 	tx_cmd->tx_flags = cpu_to_le32(tx_flags);
 	/* Total # bytes to be transmitted */
 	tx_cmd->len = cpu_to_le16((u16)skb->len);
@@ -169,10 +168,14 @@ static void iwl_mvm_set_tx_cmd_rate(stru
 
 	/*
 	 * for data packets, rate info comes from the table inside the fw. This
-	 * table is controlled by LINK_QUALITY commands
+	 * table is controlled by LINK_QUALITY commands. Exclude ctrl port
+	 * frames like EAPOLs which should be treated as mgmt frames. This
+	 * avoids them being sent initially in high rates which increases the
+	 * chances for completion of the 4-Way handshake.
 	 */
 
-	if (ieee80211_is_data(fc) && sta) {
+	if (ieee80211_is_data(fc) && sta &&
+	    !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
 		tx_cmd->initial_rate_index = 0;
 		tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
 		return;
@@ -205,7 +208,13 @@ static void iwl_mvm_set_tx_cmd_rate(stru
 	mvm->mgmt_last_antenna_idx =
 		iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
 				     mvm->mgmt_last_antenna_idx);
-	rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
+
+	if (info->band == IEEE80211_BAND_2GHZ &&
+	    !iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
+		rate_flags = BIT(ANT_A) << RATE_MCS_ANT_POS;
+	else
+		rate_flags =
+			BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
 
 	/* Set CCK flag as needed */
 	if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
@@ -306,6 +315,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
 		return -1;
 
 	/*
+	 * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
+	 * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
+	 * queue. STATION (HS2.0) uses the auxiliary context of the FW,
+	 * and hence needs to be sent on the aux queue
+	 */
+	if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
+	    info->control.vif->type == NL80211_IFTYPE_STATION)
+		IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
+
+	/*
 	 * If the interface on which frame is sent is the P2P_DEVICE
 	 * or an AP/GO interface use the broadcast station associated
 	 * with it; otherwise use the AUX station.
@@ -717,18 +736,26 @@ static void iwl_mvm_rx_tx_cmd_single(str
 	/* We can't free more than one frame at once on a shared queue */
 	WARN_ON(skb_freed > 1);
 
-	/* If we have still frames from this STA nothing to do here */
+	/* If we have still frames for this STA nothing to do here */
 	if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
 		goto out;
 
 	if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) {
+
 		/*
-		 * If there are no pending frames for this STA, notify
-		 * mac80211 that this station can go to sleep in its
+		 * If there are no pending frames for this STA and
+		 * the tx to this station is not disabled, notify
+		 * mac80211 that this station can now wake up in its
 		 * STA table.
 		 * If mvmsta is not NULL, sta is valid.
 		 */
-		ieee80211_sta_block_awake(mvm->hw, sta, false);
+
+		spin_lock_bh(&mvmsta->lock);
+
+		if (!mvmsta->disable_tx)
+			ieee80211_sta_block_awake(mvm->hw, sta, false);
+
+		spin_unlock_bh(&mvmsta->lock);
 	}
 
 	if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/utils.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/utils.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/mvm/utils.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/mvm/utils.c	2014-09-28 17:29:07.000000000 -0400
@@ -519,71 +519,6 @@ void iwl_mvm_dump_nic_error_log(struct i
 		iwl_mvm_dump_umac_error_log(mvm);
 }
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm)
-{
-	const struct fw_img *img;
-	u32 ofs, sram_len;
-	void *sram;
-
-	if (!mvm->ucode_loaded || mvm->fw_error_sram || mvm->fw_error_dump)
-		return;
-
-	img = &mvm->fw->img[mvm->cur_ucode];
-	ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
-	sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
-
-	sram = kzalloc(sram_len, GFP_ATOMIC);
-	if (!sram)
-		return;
-
-	iwl_trans_read_mem_bytes(mvm->trans, ofs, sram, sram_len);
-	mvm->fw_error_sram = sram;
-	mvm->fw_error_sram_len = sram_len;
-}
-
-void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm)
-{
-	int i, reg_val;
-	unsigned long flags;
-
-	if (!mvm->ucode_loaded || mvm->fw_error_rxf || mvm->fw_error_dump)
-		return;
-
-	/* reading buffer size */
-	reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR);
-	mvm->fw_error_rxf_len =
-		(reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS;
-
-	/* the register holds the value divided by 128 */
-	mvm->fw_error_rxf_len = mvm->fw_error_rxf_len << 7;
-
-	if (!mvm->fw_error_rxf_len)
-		return;
-
-	mvm->fw_error_rxf =  kzalloc(mvm->fw_error_rxf_len, GFP_ATOMIC);
-	if (!mvm->fw_error_rxf) {
-		mvm->fw_error_rxf_len = 0;
-		return;
-	}
-
-	if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags)) {
-		kfree(mvm->fw_error_rxf);
-		mvm->fw_error_rxf = NULL;
-		mvm->fw_error_rxf_len = 0;
-		return;
-	}
-
-	for (i = 0; i < (mvm->fw_error_rxf_len / sizeof(u32)); i++) {
-		iwl_trans_write_prph(mvm->trans, RXF_LD_FENCE_OFFSET_ADDR,
-				     i * sizeof(u32));
-		mvm->fw_error_rxf[i] =
-			iwl_trans_read_prph(mvm->trans, RXF_FIFO_RD_FENCE_ADDR);
-	}
-	iwl_trans_release_nic_access(mvm->trans, &flags);
-}
-#endif
-
 /**
  * iwl_mvm_send_lq_cmd() - Send link quality command
  * @init: This command is sent as part of station initialization right
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,7 @@
 	.driver_data = (kernel_ulong_t)&(cfg)
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+static const struct pci_device_id iwl_hw_card_ids[] = {
 #if IS_ENABLED(CONFIG_IWLDVM)
 	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
 	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
@@ -352,11 +352,17 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca
 	{IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B4, 0x8370, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B4, 0x8272, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)},
 
+/* 3165 Series */
+	{IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x3165, 0x4210, iwl3165_2ac_cfg)},
+
 /* 7265 Series */
 	{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
@@ -378,6 +384,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca
 	{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x095A, 0x900A, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/internal.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/internal.h
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -260,6 +260,9 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_t
  * @wd_timeout: queue watchdog timeout (jiffies)
  * @reg_lock: protect hw register access
  * @cmd_in_flight: true when we have a host command in flight
+ * @fw_mon_phys: physical address of the buffer for the firmware monitor
+ * @fw_mon_page: points to the first page of the buffer for the firmware monitor
+ * @fw_mon_size: size of the buffer for the firmware monitor
  */
 struct iwl_trans_pcie {
 	struct iwl_rxq rxq;
@@ -312,6 +315,10 @@ struct iwl_trans_pcie {
 	/*protect hw register */
 	spinlock_t reg_lock;
 	bool cmd_in_flight;
+
+	dma_addr_t fw_mon_phys;
+	struct page *fw_mon_page;
+	u32 fw_mon_size;
 };
 
 #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,7 @@
 #include <linux/sched.h>
 #include <linux/bitops.h>
 #include <linux/gfp.h>
+#include <linux/vmalloc.h>
 
 #include "iwl-drv.h"
 #include "iwl-trans.h"
@@ -76,6 +77,68 @@
 #include "iwl-fw-error-dump.h"
 #include "internal.h"
 
+static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	if (!trans_pcie->fw_mon_page)
+		return;
+
+	dma_unmap_page(trans->dev, trans_pcie->fw_mon_phys,
+		       trans_pcie->fw_mon_size, DMA_FROM_DEVICE);
+	__free_pages(trans_pcie->fw_mon_page,
+		     get_order(trans_pcie->fw_mon_size));
+	trans_pcie->fw_mon_page = NULL;
+	trans_pcie->fw_mon_phys = 0;
+	trans_pcie->fw_mon_size = 0;
+}
+
+static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct page *page;
+	dma_addr_t phys;
+	u32 size;
+	u8 power;
+
+	if (trans_pcie->fw_mon_page) {
+		dma_sync_single_for_device(trans->dev, trans_pcie->fw_mon_phys,
+					   trans_pcie->fw_mon_size,
+					   DMA_FROM_DEVICE);
+		return;
+	}
+
+	phys = 0;
+	for (power = 26; power >= 11; power--) {
+		int order;
+
+		size = BIT(power);
+		order = get_order(size);
+		page = alloc_pages(__GFP_COMP | __GFP_NOWARN | __GFP_ZERO,
+				   order);
+		if (!page)
+			continue;
+
+		phys = dma_map_page(trans->dev, page, 0, PAGE_SIZE << order,
+				    DMA_FROM_DEVICE);
+		if (dma_mapping_error(trans->dev, phys)) {
+			__free_pages(page, order);
+			continue;
+		}
+		IWL_INFO(trans,
+			 "Allocated 0x%08x bytes (order %d) for firmware monitor.\n",
+			 size, order);
+		break;
+	}
+
+	if (!page)
+		return;
+
+	trans_pcie->fw_mon_page = page;
+	trans_pcie->fw_mon_phys = phys;
+	trans_pcie->fw_mon_size = size;
+}
+
 static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
 {
 	iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG,
@@ -675,6 +738,7 @@ static int iwl_pcie_load_cpu_sections(st
 static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 				const struct fw_img *image)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret = 0;
 	int first_ucode_section;
 
@@ -733,6 +797,20 @@ static int iwl_pcie_load_given_ucode(str
 			return ret;
 	}
 
+	/* supported for 7000 only for the moment */
+	if (iwlwifi_mod_params.fw_monitor &&
+	    trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+		iwl_pcie_alloc_fw_monitor(trans);
+
+		if (trans_pcie->fw_mon_size) {
+			iwl_write_prph(trans, MON_BUFF_BASE_ADDR,
+				       trans_pcie->fw_mon_phys >> 4);
+			iwl_write_prph(trans, MON_BUFF_END_ADDR,
+				       (trans_pcie->fw_mon_phys +
+					trans_pcie->fw_mon_size) >> 4);
+		}
+	}
+
 	/* release CPU reset */
 	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
 		iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
@@ -1126,6 +1204,8 @@ void iwl_trans_pcie_free(struct iwl_tran
 	if (trans_pcie->napi.poll)
 		netif_napi_del(&trans_pcie->napi);
 
+	iwl_pcie_free_fw_monitor(trans);
+
 	kfree(trans);
 }
 
@@ -1494,10 +1574,12 @@ static ssize_t iwl_dbgfs_tx_queue_read(s
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
 		pos += scnprintf(buf + pos, bufsz - pos,
-				"hwq %.2d: read=%u write=%u use=%d stop=%d\n",
+				"hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d%s\n",
 				cnt, q->read_ptr, q->write_ptr,
 				!!test_bit(cnt, trans_pcie->queue_used),
-				!!test_bit(cnt, trans_pcie->queue_stopped));
+				 !!test_bit(cnt, trans_pcie->queue_stopped),
+				 txq->need_update,
+				 (cnt == trans_pcie->cmd_queue ? " HCMD" : ""));
 	}
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
@@ -1519,6 +1601,10 @@ static ssize_t iwl_dbgfs_rx_queue_read(s
 						rxq->read);
 	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
 						rxq->write);
+	pos += scnprintf(buf + pos, bufsz - pos, "write_actual: %u\n",
+						rxq->write_actual);
+	pos += scnprintf(buf + pos, bufsz - pos, "need_update: %d\n",
+						rxq->need_update);
 	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
 						rxq->free_count);
 	if (rxq->rb_stts) {
@@ -1688,23 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(str
 	return cmdlen;
 }
 
-static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
-				    void *buf, u32 buflen)
+static const struct {
+	u32 start, end;
+} iwl_prph_dump_addr[] = {
+	{ .start = 0x00a00000, .end = 0x00a00000 },
+	{ .start = 0x00a0000c, .end = 0x00a00024 },
+	{ .start = 0x00a0002c, .end = 0x00a0003c },
+	{ .start = 0x00a00410, .end = 0x00a00418 },
+	{ .start = 0x00a00420, .end = 0x00a00420 },
+	{ .start = 0x00a00428, .end = 0x00a00428 },
+	{ .start = 0x00a00430, .end = 0x00a0043c },
+	{ .start = 0x00a00444, .end = 0x00a00444 },
+	{ .start = 0x00a004c0, .end = 0x00a004cc },
+	{ .start = 0x00a004d8, .end = 0x00a004d8 },
+	{ .start = 0x00a004e0, .end = 0x00a004f0 },
+	{ .start = 0x00a00840, .end = 0x00a00840 },
+	{ .start = 0x00a00850, .end = 0x00a00858 },
+	{ .start = 0x00a01004, .end = 0x00a01008 },
+	{ .start = 0x00a01010, .end = 0x00a01010 },
+	{ .start = 0x00a01018, .end = 0x00a01018 },
+	{ .start = 0x00a01024, .end = 0x00a01024 },
+	{ .start = 0x00a0102c, .end = 0x00a01034 },
+	{ .start = 0x00a0103c, .end = 0x00a01040 },
+	{ .start = 0x00a01048, .end = 0x00a01094 },
+	{ .start = 0x00a01c00, .end = 0x00a01c20 },
+	{ .start = 0x00a01c58, .end = 0x00a01c58 },
+	{ .start = 0x00a01c7c, .end = 0x00a01c7c },
+	{ .start = 0x00a01c28, .end = 0x00a01c54 },
+	{ .start = 0x00a01c5c, .end = 0x00a01c5c },
+	{ .start = 0x00a01c84, .end = 0x00a01c84 },
+	{ .start = 0x00a01ce0, .end = 0x00a01d0c },
+	{ .start = 0x00a01d18, .end = 0x00a01d20 },
+	{ .start = 0x00a01d2c, .end = 0x00a01d30 },
+	{ .start = 0x00a01d40, .end = 0x00a01d5c },
+	{ .start = 0x00a01d80, .end = 0x00a01d80 },
+	{ .start = 0x00a01d98, .end = 0x00a01d98 },
+	{ .start = 0x00a01dc0, .end = 0x00a01dfc },
+	{ .start = 0x00a01e00, .end = 0x00a01e2c },
+	{ .start = 0x00a01e40, .end = 0x00a01e60 },
+	{ .start = 0x00a01e84, .end = 0x00a01e90 },
+	{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
+	{ .start = 0x00a01ed0, .end = 0x00a01ed0 },
+	{ .start = 0x00a01f00, .end = 0x00a01f14 },
+	{ .start = 0x00a01f44, .end = 0x00a01f58 },
+	{ .start = 0x00a01f80, .end = 0x00a01fa8 },
+	{ .start = 0x00a01fb0, .end = 0x00a01fbc },
+	{ .start = 0x00a01ff8, .end = 0x00a01ffc },
+	{ .start = 0x00a02000, .end = 0x00a02048 },
+	{ .start = 0x00a02068, .end = 0x00a020f0 },
+	{ .start = 0x00a02100, .end = 0x00a02118 },
+	{ .start = 0x00a02140, .end = 0x00a0214c },
+	{ .start = 0x00a02168, .end = 0x00a0218c },
+	{ .start = 0x00a021c0, .end = 0x00a021c0 },
+	{ .start = 0x00a02400, .end = 0x00a02410 },
+	{ .start = 0x00a02418, .end = 0x00a02420 },
+	{ .start = 0x00a02428, .end = 0x00a0242c },
+	{ .start = 0x00a02434, .end = 0x00a02434 },
+	{ .start = 0x00a02440, .end = 0x00a02460 },
+	{ .start = 0x00a02468, .end = 0x00a024b0 },
+	{ .start = 0x00a024c8, .end = 0x00a024cc },
+	{ .start = 0x00a02500, .end = 0x00a02504 },
+	{ .start = 0x00a0250c, .end = 0x00a02510 },
+	{ .start = 0x00a02540, .end = 0x00a02554 },
+	{ .start = 0x00a02580, .end = 0x00a025f4 },
+	{ .start = 0x00a02600, .end = 0x00a0260c },
+	{ .start = 0x00a02648, .end = 0x00a02650 },
+	{ .start = 0x00a02680, .end = 0x00a02680 },
+	{ .start = 0x00a026c0, .end = 0x00a026d0 },
+	{ .start = 0x00a02700, .end = 0x00a0270c },
+	{ .start = 0x00a02804, .end = 0x00a02804 },
+	{ .start = 0x00a02818, .end = 0x00a0281c },
+	{ .start = 0x00a02c00, .end = 0x00a02db4 },
+	{ .start = 0x00a02df4, .end = 0x00a02fb0 },
+	{ .start = 0x00a03000, .end = 0x00a03014 },
+	{ .start = 0x00a0301c, .end = 0x00a0302c },
+	{ .start = 0x00a03034, .end = 0x00a03038 },
+	{ .start = 0x00a03040, .end = 0x00a03048 },
+	{ .start = 0x00a03060, .end = 0x00a03068 },
+	{ .start = 0x00a03070, .end = 0x00a03074 },
+	{ .start = 0x00a0307c, .end = 0x00a0307c },
+	{ .start = 0x00a03080, .end = 0x00a03084 },
+	{ .start = 0x00a0308c, .end = 0x00a03090 },
+	{ .start = 0x00a03098, .end = 0x00a03098 },
+	{ .start = 0x00a030a0, .end = 0x00a030a0 },
+	{ .start = 0x00a030a8, .end = 0x00a030b4 },
+	{ .start = 0x00a030bc, .end = 0x00a030bc },
+	{ .start = 0x00a030c0, .end = 0x00a0312c },
+	{ .start = 0x00a03c00, .end = 0x00a03c5c },
+	{ .start = 0x00a04400, .end = 0x00a04454 },
+	{ .start = 0x00a04460, .end = 0x00a04474 },
+	{ .start = 0x00a044c0, .end = 0x00a044ec },
+	{ .start = 0x00a04500, .end = 0x00a04504 },
+	{ .start = 0x00a04510, .end = 0x00a04538 },
+	{ .start = 0x00a04540, .end = 0x00a04548 },
+	{ .start = 0x00a04560, .end = 0x00a0457c },
+	{ .start = 0x00a04590, .end = 0x00a04598 },
+	{ .start = 0x00a045c0, .end = 0x00a045f4 },
+};
+
+static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
+				    struct iwl_fw_error_dump_data **data)
+{
+	struct iwl_fw_error_dump_prph *prph;
+	unsigned long flags;
+	u32 prph_len = 0, i;
+
+	if (!iwl_trans_grab_nic_access(trans, false, &flags))
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
+		/* The range includes both boundaries */
+		int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+			 iwl_prph_dump_addr[i].start + 4;
+		int reg;
+		__le32 *val;
+
+		prph_len += sizeof(*data) + sizeof(*prph) +
+			num_bytes_in_chunk;
+
+		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
+		(*data)->len = cpu_to_le32(sizeof(*prph) +
+					num_bytes_in_chunk);
+		prph = (void *)(*data)->data;
+		prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
+		val = (void *)prph->data;
+
+		for (reg = iwl_prph_dump_addr[i].start;
+		     reg <= iwl_prph_dump_addr[i].end;
+		     reg += 4)
+			*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
+								      reg));
+		*data = iwl_fw_error_next_data(*data);
+	}
+
+	iwl_trans_release_nic_access(trans, &flags);
+
+	return prph_len;
+}
+
+#define IWL_CSR_TO_DUMP (0x250)
+
+static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans,
+				   struct iwl_fw_error_dump_data **data)
+{
+	u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP;
+	__le32 *val;
+	int i;
+
+	(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
+	(*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP);
+	val = (void *)(*data)->data;
+
+	for (i = 0; i < IWL_CSR_TO_DUMP; i += 4)
+		*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+
+	*data = iwl_fw_error_next_data(*data);
+
+	return csr_len;
+}
+
+static
+struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_fw_error_dump_data *data;
 	struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
 	struct iwl_fw_error_dump_txcmd *txcmd;
+	struct iwl_trans_dump_data *dump_data;
 	u32 len;
 	int i, ptr;
 
-	if (!buf)
-		return sizeof(*data) +
-		       cmdq->q.n_window * (sizeof(*txcmd) +
-					   TFD_MAX_PAYLOAD_SIZE);
+	/* transport dump header */
+	len = sizeof(*dump_data);
+
+	/* host commands */
+	len += sizeof(*data) +
+		cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
+
+	/* CSR registers */
+	len += sizeof(*data) + IWL_CSR_TO_DUMP;
+
+	/* PRPH registers */
+	for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
+		/* The range includes both boundaries */
+		int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+			iwl_prph_dump_addr[i].start + 4;
+
+		len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
+			num_bytes_in_chunk;
+	}
+
+	/* FW monitor */
+	if (trans_pcie->fw_mon_page)
+		len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
+			trans_pcie->fw_mon_size;
+
+	dump_data = vzalloc(len);
+	if (!dump_data)
+		return NULL;
 
 	len = 0;
-	data = buf;
+	data = (void *)dump_data->data;
 	data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
 	txcmd = (void *)data->data;
 	spin_lock_bh(&cmdq->lock);
@@ -1729,7 +1999,46 @@ static u32 iwl_trans_pcie_dump_data(stru
 	spin_unlock_bh(&cmdq->lock);
 
 	data->len = cpu_to_le32(len);
-	return sizeof(*data) + len;
+	len += sizeof(*data);
+	data = iwl_fw_error_next_data(data);
+
+	len += iwl_trans_pcie_dump_prph(trans, &data);
+	len += iwl_trans_pcie_dump_csr(trans, &data);
+	/* data is already pointing to the next section */
+
+	if (trans_pcie->fw_mon_page) {
+		struct iwl_fw_error_dump_fw_mon *fw_mon_data;
+
+		data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
+		data->len = cpu_to_le32(trans_pcie->fw_mon_size +
+					sizeof(*fw_mon_data));
+		fw_mon_data = (void *)data->data;
+		fw_mon_data->fw_mon_wr_ptr =
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_WRPTR));
+		fw_mon_data->fw_mon_cycle_cnt =
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_CYCLE_CNT));
+		fw_mon_data->fw_mon_base_ptr =
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_BASE_ADDR));
+
+		/*
+		 * The firmware is now asserted, it won't write anything to
+		 * the buffer. CPU can take ownership to fetch the data.
+		 * The buffer will be handed back to the device before the
+		 * firmware will be restarted.
+		 */
+		dma_sync_single_for_cpu(trans->dev, trans_pcie->fw_mon_phys,
+					trans_pcie->fw_mon_size,
+					DMA_FROM_DEVICE);
+		memcpy(fw_mon_data->data, page_address(trans_pcie->fw_mon_page),
+		       trans_pcie->fw_mon_size);
+
+		len += sizeof(*data) + sizeof(*fw_mon_data) +
+			trans_pcie->fw_mon_size;
+	}
+
+	dump_data->len = len;
+
+	return dump_data;
 }
 #else
 static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
@@ -1870,6 +2179,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(s
 	}
 
 	trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
+	/*
+	 * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
+	 * changed, and now the revision step also includes bit 0-1 (no more
+	 * "dash" value). To keep hw_rev backwards compatible - we'll store it
+	 * in the old format.
+	 */
+	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+		trans->hw_rev = (trans->hw_rev & 0xfff0) |
+				((trans->hw_rev << 2) & 0xc);
+
 	trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
 	snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
 		 "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/iwlwifi/pcie/tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/iwlwifi/pcie/tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1438,6 +1438,7 @@ static int iwl_pcie_enqueue_hcmd(struct
 				   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 			spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
 			trans_pcie->cmd_in_flight = false;
+			IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
 			idx = -EIO;
 			goto out;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -189,6 +189,7 @@ config USB_NET_RNDIS_WLAN
 	tristate "Wireless RNDIS USB support"
 	depends on USB
 	depends on CFG80211
+	select USB_NET_DRIVERS
 	select USB_USBNET
 	select USB_NET_CDCETHER
 	select USB_NET_RNDIS_HOST
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/libertas/cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/libertas/cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1111,6 +1111,7 @@ int lbs_set_radio(struct lbs_private *pr
 
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
+	cmd.control = 0;
 
 	/* Only v8 and below support setting the preamble */
 	if (priv->fwrelease < 0x09000000) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/libertas/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/libertas/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,7 @@ config LIBERTAS_USB
 
 config LIBERTAS_CS
 	tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
-	depends on LIBERTAS && PCMCIA
+	depends on LIBERTAS && PCMCIA && HAS_IOPORT_MAP
 	---help---
 	  A driver for Marvell Libertas 8385 CompactFlash devices.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/libertas/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/libertas/main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/main.c	2014-09-28 17:29:07.000000000 -0400
@@ -981,7 +981,7 @@ struct lbs_private *lbs_add_card(void *c
 		goto err_wdev;
 	}
 
-	dev = alloc_netdev(0, "wlan%d", ether_setup);
+	dev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup);
 	if (!dev) {
 		dev_err(dmdev, "no memory for network device instance\n");
 		goto err_adapter;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/libertas/mesh.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/mesh.c
--- linux-libre-3.16-gnu/drivers/net/wireless/libertas/mesh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/libertas/mesh.c	2014-09-28 17:29:07.000000000 -0400
@@ -1000,7 +1000,7 @@ static int lbs_add_mesh(struct lbs_priva
 		goto done;
 	}
 
-	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+	mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup);
 	if (!mesh_dev) {
 		lbs_deb_mesh("init mshX device failed\n");
 		ret = -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mac80211_hwsim.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mac80211_hwsim.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mac80211_hwsim.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mac80211_hwsim.c	2014-09-28 17:29:07.000000000 -0400
@@ -685,11 +685,16 @@ static void mac80211_hwsim_set_tsf(struc
 	struct mac80211_hwsim_data *data = hw->priv;
 	u64 now = mac80211_hwsim_get_tsf(hw, vif);
 	u32 bcn_int = data->beacon_int;
-	s64 delta = tsf - now;
+	u64 delta = abs64(tsf - now);
 
-	data->tsf_offset += delta;
 	/* adjust after beaconing with new timestamp at old TBTT */
-	data->bcn_delta = do_div(delta, bcn_int);
+	if (tsf > now) {
+		data->tsf_offset += delta;
+		data->bcn_delta = do_div(delta, bcn_int);
+	} else {
+		data->tsf_offset -= delta;
+		data->bcn_delta = -do_div(delta, bcn_int);
+	}
 }
 
 static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
@@ -781,6 +786,36 @@ static void mac80211_hwsim_monitor_ack(s
 	netif_rx(skb);
 }
 
+struct mac80211_hwsim_addr_match_data {
+	u8 addr[ETH_ALEN];
+	bool ret;
+};
+
+static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
+				     struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_addr_match_data *md = data;
+
+	if (memcmp(mac, md->addr, ETH_ALEN) == 0)
+		md->ret = true;
+}
+
+static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
+				      const u8 *addr)
+{
+	struct mac80211_hwsim_addr_match_data md = {
+		.ret = false,
+	};
+
+	memcpy(md.addr, addr, ETH_ALEN);
+
+	ieee80211_iterate_active_interfaces_atomic(data->hw,
+						   IEEE80211_IFACE_ITER_NORMAL,
+						   mac80211_hwsim_addr_iter,
+						   &md);
+
+	return md.ret;
+}
 
 static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
 			   struct sk_buff *skb)
@@ -798,8 +833,7 @@ static bool hwsim_ps_rx_ok(struct mac802
 		/* Allow unicast frames to own address if there is a pending
 		 * PS-Poll */
 		if (data->ps_poll_pending &&
-		    memcmp(data->hw->wiphy->perm_addr, skb->data + 4,
-			   ETH_ALEN) == 0) {
+		    mac80211_hwsim_addr_match(data, skb->data + 4)) {
 			data->ps_poll_pending = false;
 			return true;
 		}
@@ -809,39 +843,6 @@ static bool hwsim_ps_rx_ok(struct mac802
 	return true;
 }
 
-
-struct mac80211_hwsim_addr_match_data {
-	bool ret;
-	const u8 *addr;
-};
-
-static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
-				     struct ieee80211_vif *vif)
-{
-	struct mac80211_hwsim_addr_match_data *md = data;
-	if (memcmp(mac, md->addr, ETH_ALEN) == 0)
-		md->ret = true;
-}
-
-
-static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
-				      const u8 *addr)
-{
-	struct mac80211_hwsim_addr_match_data md;
-
-	if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0)
-		return true;
-
-	md.ret = false;
-	md.addr = addr;
-	ieee80211_iterate_active_interfaces_atomic(data->hw,
-						   IEEE80211_IFACE_ITER_NORMAL,
-						   mac80211_hwsim_addr_iter,
-						   &md);
-
-	return md.ret;
-}
-
 static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
 				       struct sk_buff *my_skb,
 				       int dst_portid)
@@ -1740,9 +1741,10 @@ static void hw_scan_work(struct work_str
 
 static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
-				  struct cfg80211_scan_request *req)
+				  struct ieee80211_scan_request *hw_req)
 {
 	struct mac80211_hwsim_data *hwsim = hw->priv;
+	struct cfg80211_scan_request *req = &hw_req->req;
 
 	mutex_lock(&hwsim->mutex);
 	if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
@@ -2679,7 +2681,8 @@ static int __init init_mac80211_hwsim(vo
 			goto out_free_radios;
 	}
 
-	hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
+	hwsim_mon = alloc_netdev(0, "hwsim%d", NET_NAME_UNKNOWN,
+				 hwsim_mon_setup);
 	if (hwsim_mon == NULL) {
 		err = -ENOMEM;
 		goto out_free_radios;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11ac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11ac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11ac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11ac.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11ac
  *
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11ac.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11ac.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11ac.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11ac.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11ac
  *
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11h.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11h.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11h.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11h.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11h
  *
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_aggr.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_aggr.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_aggr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_aggr.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n Aggregation
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_aggr.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_aggr.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_aggr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_aggr.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n Aggregation
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -541,7 +541,6 @@ void mwifiex_create_ba_tbl(struct mwifie
 int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
 {
 	struct host_cmd_ds_11n_addba_req add_ba_req;
-	struct mwifiex_sta_node *sta_ptr;
 	u32 tx_win_size = priv->add_ba_param.tx_win_size;
 	static u8 dialog_tok;
 	int ret;
@@ -553,6 +552,8 @@ int mwifiex_send_addba(struct mwifiex_pr
 	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
 	    priv->adapter->is_hw_11ac_capable &&
 	    memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
+		struct mwifiex_sta_node *sta_ptr;
+
 		sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
 		if (!sta_ptr) {
 			dev_warn(priv->adapter->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -249,13 +249,22 @@ void mwifiex_11n_del_rx_reorder_tbl_by_t
  * buffered in Rx reordering table.
  */
 static int
-mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr)
+mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
 {
+	struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
+	struct mwifiex_private *priv = ctx->priv;
+	unsigned long flags;
 	int i;
 
-	for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i)
-		if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
+	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+	for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
+		if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+					       flags);
 			return i;
+		}
+	}
+	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 
 	return -1;
 }
@@ -274,7 +283,7 @@ mwifiex_flush_data(unsigned long context
 		(struct reorder_tmr_cnxt *) context;
 	int start_win, seq_num;
 
-	seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr);
+	seq_num = mwifiex_11n_find_last_seq_num(ctx);
 
 	if (seq_num < 0)
 		return;
@@ -729,9 +738,9 @@ void mwifiex_11n_cleanup_reorder_tbl(str
 		mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
 		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
 	}
+	INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
 	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 
-	INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
 	mwifiex_reset_11n_rx_seq_num(priv);
 }
 
@@ -749,10 +758,14 @@ void mwifiex_update_rxreor_flags(struct
 		priv = adapter->priv[i];
 		if (!priv)
 			continue;
-		if (list_empty(&priv->rx_reorder_tbl_ptr))
-			continue;
 
 		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
+		if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+					       lock_flags);
+			continue;
+		}
+
 		list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
 			tbl->flags = flags;
 		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/11n_rxreorder.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: 802.11n RX Re-ordering
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfg80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfg80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfg80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfg80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: CFG80211
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -42,36 +42,6 @@ static const struct ieee80211_iface_comb
 	.beacon_int_infra_match = true,
 };
 
-static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
-	.n_reg_rules = 7,
-	.alpha2 =  "99",
-	.reg_rules = {
-		/* Channel 1 - 11 */
-		REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
-		/* Channel 12 - 13 */
-		REG_RULE(2467-10, 2472+10, 20, 3, 20,
-			 NL80211_RRF_NO_IR),
-		/* Channel 14 */
-		REG_RULE(2484-10, 2484+10, 20, 3, 20,
-			 NL80211_RRF_NO_IR |
-			 NL80211_RRF_NO_OFDM),
-		/* Channel 36 - 48 */
-		REG_RULE(5180-10, 5240+10, 40, 3, 20,
-			 NL80211_RRF_NO_IR),
-		/* Channel 149 - 165 */
-		REG_RULE(5745-10, 5825+10, 40, 3, 20,
-			 NL80211_RRF_NO_IR),
-		/* Channel 52 - 64 */
-		REG_RULE(5260-10, 5320+10, 40, 3, 30,
-			 NL80211_RRF_NO_IR |
-			 NL80211_RRF_DFS),
-		/* Channel 100 - 140 */
-		REG_RULE(5500-10, 5700+10, 40, 3, 30,
-			 NL80211_RRF_NO_IR |
-			 NL80211_RRF_DFS),
-	}
-};
-
 /*
  * This function maps the nl802.11 channel type into driver channel type.
  *
@@ -151,7 +121,6 @@ mwifiex_form_mgmt_frame(struct sk_buff *
 	u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 	u16 pkt_len;
 	u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
-	struct timeval tv;
 
 	pkt_len = len + ETH_ALEN;
 
@@ -173,8 +142,7 @@ mwifiex_form_mgmt_frame(struct sk_buff *
 	       len - sizeof(struct ieee80211_hdr_3addr));
 
 	skb->priority = LOW_PRIO_TID;
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	__net_timestamp(skb);
 
 	return 0;
 }
@@ -1636,9 +1604,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_pr
 		return -EINVAL;
 	}
 
-	/* disconnect before try to associate */
-	mwifiex_deauthenticate(priv, NULL);
-
 	/* As this is new association, clear locally stored
 	 * keys and security related flags */
 	priv->sec_info.wpa_enabled = false;
@@ -1776,6 +1741,11 @@ mwifiex_cfg80211_connect(struct wiphy *w
 		return -EINVAL;
 	}
 
+	if (priv->wdev && priv->wdev->current_bss) {
+		wiphy_warn(wiphy, "%s: already connected\n", dev->name);
+		return -EALREADY;
+	}
+
 	wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
 		  (char *) sme->ssid, sme->bssid);
 
@@ -2264,7 +2234,8 @@ struct wireless_dev *mwifiex_add_virtual
 	}
 
 	dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
-			       ether_setup, IEEE80211_NUM_ACS, 1);
+			       NET_NAME_UNKNOWN, ether_setup,
+			       IEEE80211_NUM_ACS, 1);
 	if (!dev) {
 		wiphy_err(wiphy, "no memory available for netdevice\n");
 		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2484,6 +2455,16 @@ static int mwifiex_cfg80211_suspend(stru
 		mef_entry->filter[filt_num].filt_type = TYPE_EQ;
 		if (filt_num)
 			mef_entry->filter[filt_num].filt_action = TYPE_OR;
+
+		filt_num++;
+		mef_entry->filter[filt_num].repeat = 16;
+		memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+		       ETH_ALEN);
+		mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
+								ETH_ALEN;
+		mef_entry->filter[filt_num].offset = 56;
+		mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+		mef_entry->filter[filt_num].filt_action = TYPE_OR;
 	}
 
 	if (!mef_cfg.criteria)
@@ -2632,7 +2613,8 @@ static int
 mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 			   const u8 *peer, u8 action_code, u8 dialog_token,
 			   u16 status_code, u32 peer_capability,
-			   const u8 *extra_ies, size_t extra_ies_len)
+			   bool initiator, const u8 *extra_ies,
+			   size_t extra_ies_len)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	int ret;
@@ -2917,12 +2899,6 @@ int mwifiex_register_cfg80211(struct mwi
 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
 				WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
 
-	wiphy->regulatory_flags |=
-			REGULATORY_CUSTOM_REG |
-			REGULATORY_STRICT_REG;
-
-	wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
-
 #ifdef CONFIG_PM
 	wiphy->wowlan = &mwifiex_wowlan_support;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfg80211.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfg80211.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfg80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfg80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: CFG80211
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfp.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfp.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cfp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cfp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: Channel, Frequence and Power
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cmdevt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cmdevt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/cmdevt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/cmdevt.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: commands and events
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -137,7 +137,6 @@ static int mwifiex_dnld_cmd_to_fw(struct
 	struct host_cmd_ds_command *host_cmd;
 	uint16_t cmd_code;
 	uint16_t cmd_size;
-	struct timeval tstamp;
 	unsigned long flags;
 	__le32 tmp;
 
@@ -198,10 +197,8 @@ static int mwifiex_dnld_cmd_to_fw(struct
 		 */
 		skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
 
-	do_gettimeofday(&tstamp);
-	dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
-		" seqno %#x\n",
-		tstamp.tv_sec, tstamp.tv_usec, cmd_code,
+	dev_dbg(adapter->dev,
+		"cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code,
 		le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
 		le16_to_cpu(host_cmd->seq_num));
 
@@ -283,6 +280,13 @@ static int mwifiex_dnld_sleep_confirm_cm
 					(adapter->seq_num, priv->bss_num,
 					 priv->bss_type)));
 
+	dev_dbg(adapter->dev,
+		"cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+		le16_to_cpu(sleep_cfm_buf->command),
+		le16_to_cpu(sleep_cfm_buf->action),
+		le16_to_cpu(sleep_cfm_buf->size),
+		le16_to_cpu(sleep_cfm_buf->seq_num));
+
 	if (adapter->iface_type == MWIFIEX_USB) {
 		sleep_cfm_tmp =
 			dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
@@ -433,7 +437,6 @@ int mwifiex_process_event(struct mwifiex
 		mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	struct sk_buff *skb = adapter->event_skb;
 	u32 eventcause = adapter->event_cause;
-	struct timeval tstamp;
 	struct mwifiex_rxinfo *rx_info;
 
 	/* Save the last event to debug log */
@@ -458,11 +461,8 @@ int mwifiex_process_event(struct mwifiex
 		rx_info->bss_type = priv->bss_type;
 	}
 
-	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) {
-		do_gettimeofday(&tstamp);
-		dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n",
-			tstamp.tv_sec, tstamp.tv_usec, eventcause);
-	} else {
+	dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause);
+	if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) {
 		/* Handle PS_SLEEP/AWAKE events on STA */
 		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
 		if (!priv)
@@ -773,7 +773,6 @@ int mwifiex_process_cmdresp(struct mwifi
 	uint16_t orig_cmdresp_no;
 	uint16_t cmdresp_no;
 	uint16_t cmdresp_result;
-	struct timeval tstamp;
 	unsigned long flags;
 
 	/* Now we got response from FW, cancel the command timer */
@@ -831,11 +830,10 @@ int mwifiex_process_cmdresp(struct mwifi
 	adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
 								orig_cmdresp_no;
 
-	do_gettimeofday(&tstamp);
-	dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d,"
-		" len %d, seqno 0x%x\n",
-	       tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result,
-	       le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
+	dev_dbg(adapter->dev,
+		"cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+		orig_cmdresp_no, cmdresp_result,
+		le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
 
 	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
 		dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
@@ -895,7 +893,6 @@ mwifiex_cmd_timeout_func(unsigned long f
 	struct mwifiex_adapter *adapter =
 		(struct mwifiex_adapter *) function_context;
 	struct cmd_ctrl_node *cmd_node;
-	struct timeval tstamp;
 
 	adapter->is_cmd_timedout = 1;
 	if (!adapter->curr_cmd) {
@@ -908,10 +905,8 @@ mwifiex_cmd_timeout_func(unsigned long f
 			adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
 		adapter->dbg.timeout_cmd_act =
 			adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
-		do_gettimeofday(&tstamp);
 		dev_err(adapter->dev,
-			"%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n",
-			__func__, tstamp.tv_sec, tstamp.tv_usec,
+			"%s: Timeout cmd id = %#x, act = %#x\n", __func__,
 			adapter->dbg.timeout_cmd_id,
 			adapter->dbg.timeout_cmd_act);
 
@@ -961,6 +956,9 @@ mwifiex_cmd_timeout_func(unsigned long f
 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
 		mwifiex_init_fw_complete(adapter);
 
+	if (adapter->if_ops.fw_dump)
+		adapter->if_ops.fw_dump(adapter);
+
 	if (adapter->if_ops.card_reset)
 		adapter->if_ops.card_reset(adapter);
 }
@@ -1232,6 +1230,10 @@ mwifiex_process_sleep_confirm_resp(struc
 		return;
 	}
 
+	dev_dbg(adapter->dev,
+		"cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+		command, result, le16_to_cpu(cmd->size), seq_num);
+
 	/* Get BSS number and corresponding priv */
 	priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
 				      HostCmd_GET_BSS_TYPE(seq_num));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/debugfs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: debugfs
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -692,6 +692,97 @@ done:
 	return ret;
 }
 
+/* Proc hscfg file write handler
+ * This function can be used to configure the host sleep parameters.
+ */
+static ssize_t
+mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
+		    size_t count, loff_t *ppos)
+{
+	struct mwifiex_private *priv = (void *)file->private_data;
+	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+	char *buf = (char *)addr;
+	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+	int ret, arg_num;
+	struct mwifiex_ds_hs_cfg hscfg;
+	int conditions = HS_CFG_COND_DEF;
+	u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
+
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, ubuf, buf_size)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
+
+	memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
+
+	if (arg_num > 3) {
+		dev_err(priv->adapter->dev, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (arg_num >= 1 && arg_num < 3)
+		mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+				      MWIFIEX_SYNC_CMD, &hscfg);
+
+	if (arg_num) {
+		if (conditions == HS_CFG_CANCEL) {
+			mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
+			ret = count;
+			goto done;
+		}
+		hscfg.conditions = conditions;
+	}
+	if (arg_num >= 2)
+		hscfg.gpio = gpio;
+	if (arg_num == 3)
+		hscfg.gap = gap;
+
+	hscfg.is_invoke_hostcmd = false;
+	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+			      MWIFIEX_SYNC_CMD, &hscfg);
+
+	mwifiex_enable_hs(priv->adapter);
+	priv->adapter->hs_enabling = false;
+	ret = count;
+done:
+	free_page(addr);
+	return ret;
+}
+
+/* Proc hscfg file read handler
+ * This function can be used to read host sleep configuration
+ * parameters from driver.
+ */
+static ssize_t
+mwifiex_hscfg_read(struct file *file, char __user *ubuf,
+		   size_t count, loff_t *ppos)
+{
+	struct mwifiex_private *priv = (void *)file->private_data;
+	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+	char *buf = (char *)addr;
+	int pos, ret;
+	struct mwifiex_ds_hs_cfg hscfg;
+
+	if (!buf)
+		return -ENOMEM;
+
+	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+			      MWIFIEX_SYNC_CMD, &hscfg);
+
+	pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
+		       hscfg.gpio, hscfg.gap);
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+	free_page(addr);
+	return ret;
+}
 
 #define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
 	if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir,        \
@@ -725,6 +816,7 @@ MWIFIEX_DFS_FILE_READ_OPS(getlog);
 MWIFIEX_DFS_FILE_READ_OPS(fw_dump);
 MWIFIEX_DFS_FILE_OPS(regrdwr);
 MWIFIEX_DFS_FILE_OPS(rdeeprom);
+MWIFIEX_DFS_FILE_OPS(hscfg);
 
 /*
  * This function creates the debug FS directory structure and the files.
@@ -747,6 +839,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_
 	MWIFIEX_DFS_ADD_FILE(regrdwr);
 	MWIFIEX_DFS_ADD_FILE(rdeeprom);
 	MWIFIEX_DFS_ADD_FILE(fw_dump);
+	MWIFIEX_DFS_ADD_FILE(hscfg);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/decl.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/decl.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/decl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/decl.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: generic data structures and APIs
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ethtool.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ethtool.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ethtool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ethtool.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: ethtool
  *
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -64,7 +64,90 @@ static int mwifiex_ethtool_set_wol(struc
 	return 0;
 }
 
+static int
+mwifiex_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct memory_type_mapping *entry;
+
+	if (!adapter->if_ops.fw_dump)
+		return -ENOTSUPP;
+
+	dump->flag = adapter->curr_mem_idx;
+	dump->version = 1;
+	if (adapter->curr_mem_idx != MWIFIEX_FW_DUMP_IDX) {
+		entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
+		dump->len = entry->mem_size;
+	} else {
+		dump->len = 0;
+	}
+
+	return 0;
+}
+
+static int
+mwifiex_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
+		      void *buffer)
+{
+	u8 *p = buffer;
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct memory_type_mapping *entry;
+
+	if (!adapter->if_ops.fw_dump)
+		return -ENOTSUPP;
+
+	if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
+		dev_err(adapter->dev, "firmware dump in progress!!\n");
+		return -EBUSY;
+	}
+
+	entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
+
+	if (!entry->mem_ptr)
+		return -EFAULT;
+
+	memcpy(p, entry->mem_ptr, entry->mem_size);
+
+	entry->mem_size = 0;
+	vfree(entry->mem_ptr);
+	entry->mem_ptr = NULL;
+
+	return 0;
+}
+
+static int mwifiex_set_dump(struct net_device *dev, struct ethtool_dump *val)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	struct mwifiex_adapter *adapter = priv->adapter;
+
+	if (!adapter->if_ops.fw_dump)
+		return -ENOTSUPP;
+
+	if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
+		dev_err(adapter->dev, "firmware dump in progress!!\n");
+		return -EBUSY;
+	}
+
+	if (val->flag == MWIFIEX_FW_DUMP_IDX) {
+		adapter->curr_mem_idx = val->flag;
+		adapter->if_ops.fw_dump(adapter);
+		return 0;
+	}
+
+	if (val->flag < 0 || val->flag >= adapter->num_mem_types)
+		return -EINVAL;
+
+	adapter->curr_mem_idx = val->flag;
+
+	return 0;
+}
+
 const struct ethtool_ops mwifiex_ethtool_ops = {
 	.get_wol = mwifiex_ethtool_get_wol,
 	.set_wol = mwifiex_ethtool_set_wol,
+	.get_dump_flag = mwifiex_get_dump_flag,
+	.get_dump_data = mwifiex_get_dump_data,
+	.set_dump = mwifiex_set_dump,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/fw.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/fw.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/fw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/fw.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: Firmware specific macros & structures
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -713,7 +713,7 @@ struct mwifiex_ie_types_vendor_param_set
 	u8 ie[MWIFIEX_MAX_VSIE_LEN];
 };
 
-#define MWIFIEX_TDLS_IDLE_TIMEOUT	60
+#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC	60
 
 struct mwifiex_ie_types_tdls_idle_timeout {
 	struct mwifiex_ie_types_header header;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ie.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ie.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ie.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ie.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,7 @@
  * Marvell Wireless LAN device driver: management IE handling- setting and
  * deleting IE.
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/init.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/init.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: HW/FW Initialization
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -382,6 +382,8 @@ static void mwifiex_free_lock_list(struc
 static void
 mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 {
+	int idx;
+
 	if (!adapter) {
 		pr_err("%s: adapter is NULL\n", __func__);
 		return;
@@ -396,7 +398,16 @@ mwifiex_adapter_cleanup(struct mwifiex_a
 	dev_dbg(adapter->dev, "info: free cmd buffer\n");
 	mwifiex_free_cmd_buffer(adapter);
 
-	dev_dbg(adapter->dev, "info: free scan table\n");
+	for (idx = 0; idx < adapter->num_mem_types; idx++) {
+		struct memory_type_mapping *entry =
+				&adapter->mem_type_mapping_tbl[idx];
+
+		if (entry->mem_ptr) {
+			vfree(entry->mem_ptr);
+			entry->mem_ptr = NULL;
+		}
+		entry->mem_size = 0;
+	}
 
 	if (adapter->sleep_cfm)
 		dev_kfree_skb_any(adapter->sleep_cfm);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ioctl.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ioctl.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/ioctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/ioctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: ioctl data structures & APIs
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/join.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/join.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/join.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/join.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: association and ad-hoc start/join
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -949,7 +949,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct m
 				chan_tlv->chan_scan_param[0].radio_type |=
 					(IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
 			else if (adapter->sec_chan_offset ==
-					    IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+					    IEEE80211_HT_PARAM_CHA_SEC_BELOW)
 				chan_tlv->chan_scan_param[0].radio_type |=
 					(IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
 		}
@@ -1288,8 +1288,6 @@ done:
 int mwifiex_associate(struct mwifiex_private *priv,
 		      struct mwifiex_bssdescriptor *bss_desc)
 {
-	u8 current_bssid[ETH_ALEN];
-
 	/* Return error if the adapter is not STA role or table entry
 	 * is not marked as infra.
 	 */
@@ -1304,10 +1302,6 @@ int mwifiex_associate(struct mwifiex_pri
 	else
 		mwifiex_set_ba_params(priv);
 
-	memcpy(&current_bssid,
-	       &priv->curr_bss_params.bss_descriptor.mac_address,
-	       sizeof(current_bssid));
-
 	/* Clear any past association response stored for application
 	   retrieval */
 	priv->assoc_rsp_size = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/main.c	2014-08-07 04:55:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/main.c	2014-09-28 21:37:05.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: major functions
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned
 	struct mwifiex_private *priv = (struct mwifiex_private *)data;
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct cmd_ctrl_node *cmd_node, *tmp_node;
+	spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
 	unsigned long flags;
 
 	if (adapter->surprise_removed)
@@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned
 		 * Abort scan operation by cancelling all pending scan
 		 * commands
 		 */
-		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+		spin_lock_irqsave(scan_q_lock, flags);
 		list_for_each_entry_safe(cmd_node, tmp_node,
 					 &adapter->scan_pending_q, list) {
 			list_del(&cmd_node->list);
 			mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
 		}
-		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+		spin_unlock_irqrestore(scan_q_lock, flags);
 
 		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
 		adapter->scan_processing = false;
@@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned
 			 */
 			adapter->scan_delay_cnt = 0;
 			adapter->empty_tx_q_cnt = 0;
-			spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+			spin_lock_irqsave(scan_q_lock, flags);
+
+			if (list_empty(&adapter->scan_pending_q)) {
+				spin_unlock_irqrestore(scan_q_lock, flags);
+				goto done;
+			}
+
 			cmd_node = list_first_entry(&adapter->scan_pending_q,
 						    struct cmd_ctrl_node, list);
 			list_del(&cmd_node->list);
-			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-					       flags);
+			spin_unlock_irqrestore(scan_q_lock, flags);
 
 			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
 							true);
@@ -609,7 +615,6 @@ mwifiex_hard_start_xmit(struct sk_buff *
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	struct sk_buff *new_skb;
 	struct mwifiex_txinfo *tx_info;
-	struct timeval tv;
 
 	dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
 		jiffies, priv->bss_type, priv->bss_num);
@@ -657,8 +662,7 @@ mwifiex_hard_start_xmit(struct sk_buff *
 	 * firmware for aggregate delay calculation for stats and
 	 * MSDU lifetime expiry.
 	 */
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	__net_timestamp(skb);
 
 	mwifiex_queue_tx_pkt(priv, skb);
 
@@ -882,6 +886,8 @@ mwifiex_add_card(void *card, struct sema
 		goto err_kmalloc;
 
 	INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
+	if (adapter->if_ops.iface_work)
+		INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work);
 
 	/* Register the device. Fill up the private data structure with relevant
 	   information from the card. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/main.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/main.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/main.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/main.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: major data structures and prototypes
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -30,6 +30,7 @@
 #include <linux/etherdevice.h>
 #include <net/sock.h>
 #include <net/lib80211.h>
+#include <linux/vmalloc.h>
 #include <linux/firmware.h>
 #include <linux/ctype.h>
 #include <linux/of.h>
@@ -410,6 +411,29 @@ struct mwifiex_roc_cfg {
 	struct ieee80211_channel chan;
 };
 
+#define MWIFIEX_FW_DUMP_IDX		0xff
+#define FW_DUMP_MAX_NAME_LEN		8
+#define FW_DUMP_HOST_READY		0xEE
+#define FW_DUMP_DONE			0xFF
+
+struct memory_type_mapping {
+	u8 mem_name[FW_DUMP_MAX_NAME_LEN];
+	u8 *mem_ptr;
+	u32 mem_size;
+	u8 done_flag;
+};
+
+enum rdwr_status {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+};
+
+enum mwifiex_iface_work_flags {
+	MWIFIEX_IFACE_WORK_FW_DUMP,
+	MWIFIEX_IFACE_WORK_CARD_RESET,
+};
+
 struct mwifiex_adapter;
 struct mwifiex_private;
 
@@ -674,6 +698,7 @@ struct mwifiex_if_ops {
 	void (*card_reset) (struct mwifiex_adapter *);
 	void (*fw_dump)(struct mwifiex_adapter *);
 	int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
+	void (*iface_work)(struct work_struct *work);
 };
 
 struct mwifiex_adapter {
@@ -809,6 +834,11 @@ struct mwifiex_adapter {
 	bool ext_scan;
 	u8 fw_api_ver;
 	u8 fw_key_api_major_ver, fw_key_api_minor_ver;
+	struct work_struct iface_work;
+	unsigned long iface_work_flags;
+	struct memory_type_mapping *mem_type_mapping_tbl;
+	u8 num_mem_types;
+	u8 curr_mem_idx;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -890,6 +920,8 @@ int mwifiex_ret_enh_power_mode(struct mw
 void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
 void mwifiex_hs_activated_event(struct mwifiex_private *priv,
 					u8 activated);
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+			  int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg);
 int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
 			      struct host_cmd_ds_command *resp);
 int mwifiex_process_rx_packet(struct mwifiex_private *priv,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2011, Marvell International Ltd.
+# Copyright (C) 2011-2014, Marvell International Ltd.
 #
 # This software file (the "File") is distributed by Marvell International
 # Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/pcie.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/pcie.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/pcie.c	2014-08-07 04:55:15.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/pcie.c	2014-09-28 21:37:16.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: PCIE specific handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -37,6 +37,13 @@ static struct mwifiex_if_ops pcie_ops;
 
 static struct semaphore add_remove_card_sem;
 
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, 0, 0xF0},
+	{"DTCM", NULL, 0, 0xF1},
+	{"SQRAM", NULL, 0, 0xF2},
+	{"IRAM", NULL, 0, 0xF3},
+};
+
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 		       size_t size, int flags)
@@ -192,6 +199,7 @@ static int mwifiex_pcie_probe(struct pci
 		card->pcie.reg = data->reg;
 		card->pcie.blksz_fw_dl = data->blksz_fw_dl;
 		card->pcie.tx_buf_size = data->tx_buf_size;
+		card->pcie.supports_fw_dump = data->supports_fw_dump;
 	}
 
 	if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
@@ -221,6 +229,8 @@ static void mwifiex_pcie_remove(struct p
 	if (!adapter || !adapter->priv_num)
 		return;
 
+	cancel_work_sync(&adapter->iface_work);
+
 	if (user_rmmod) {
 #ifdef CONFIG_PM_SLEEP
 		if (adapter->is_suspended)
@@ -247,7 +257,7 @@ static void mwifiex_pcie_shutdown(struct
 	return;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
+static const struct pci_device_id mwifiex_ids[] = {
 	{
 		PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -307,6 +317,17 @@ static int mwifiex_read_reg(struct mwifi
 	return 0;
 }
 
+/* This function reads u8 data from PCIE card register. */
+static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
+				 int reg, u8 *data)
+{
+	struct pcie_service_card *card = adapter->card;
+
+	*data = ioread8(card->pci_mmap1 + reg);
+
+	return 0;
+}
+
 /*
  * This function adds delay loop to ensure FW is awake before proceeding.
  */
@@ -2173,6 +2194,168 @@ static int mwifiex_pcie_host_to_card(str
 	return 0;
 }
 
+/* This function read/write firmware */
+static enum rdwr_status
+mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
+{
+	int ret, tries;
+	u8 ctrl_data;
+	struct pcie_service_card *card = adapter->card;
+	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+	ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
+	if (ret) {
+		dev_err(adapter->dev, "PCIE write err\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
+		if (ctrl_data == FW_DUMP_DONE)
+			return RDWR_STATUS_SUCCESS;
+		if (doneflag && ctrl_data == doneflag)
+			return RDWR_STATUS_DONE;
+		if (ctrl_data != FW_DUMP_HOST_READY) {
+			dev_info(adapter->dev,
+				 "The ctrl reg was changed, re-try again!\n");
+			mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
+					  FW_DUMP_HOST_READY);
+			if (ret) {
+				dev_err(adapter->dev, "PCIE write err\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		usleep_range(100, 200);
+	}
+
+	dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+	return RDWR_STATUS_FAILURE;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
+{
+	struct pcie_service_card *card = adapter->card;
+	const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+	enum rdwr_status stat;
+	u32 memory_size;
+	static char *env[] = { "DRIVER=mwifiex_pcie", "EVENT=fw_dump", NULL };
+
+	if (!card->pcie.supports_fw_dump)
+		return;
+
+	for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+		if (entry->mem_ptr) {
+			vfree(entry->mem_ptr);
+			entry->mem_ptr = NULL;
+		}
+		entry->mem_size = 0;
+	}
+
+	dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+
+	/* Read the number of the memories which will dump */
+	stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+	if (stat == RDWR_STATUS_FAILURE)
+		goto done;
+
+	reg = creg->fw_dump_start;
+	mwifiex_read_reg_byte(adapter, reg, &dump_num);
+
+	/* Read the length of every memory which will dump */
+	for (idx = 0; idx < dump_num; idx++) {
+		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+		stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+		if (stat == RDWR_STATUS_FAILURE)
+			goto done;
+
+		memory_size = 0;
+		reg = creg->fw_dump_start;
+		for (i = 0; i < 4; i++) {
+			mwifiex_read_reg_byte(adapter, reg, &read_reg);
+			memory_size |= (read_reg << (i * 8));
+			reg++;
+		}
+
+		if (memory_size == 0) {
+			dev_info(adapter->dev, "Firmware dump Finished!\n");
+			break;
+		}
+
+		dev_info(adapter->dev,
+			 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+		entry->mem_ptr = vmalloc(memory_size + 1);
+		entry->mem_size = memory_size;
+		if (!entry->mem_ptr) {
+			dev_err(adapter->dev,
+				"Vmalloc %s failed\n", entry->mem_name);
+			goto done;
+		}
+		dbg_ptr = entry->mem_ptr;
+		end_ptr = dbg_ptr + memory_size;
+
+		doneflag = entry->done_flag;
+		dev_info(adapter->dev, "Start %s output, please wait...\n",
+			 entry->mem_name);
+
+		do {
+			stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+			if (RDWR_STATUS_FAILURE == stat)
+				goto done;
+
+			reg_start = creg->fw_dump_start;
+			reg_end = creg->fw_dump_end;
+			for (reg = reg_start; reg <= reg_end; reg++) {
+				mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					dev_err(adapter->dev,
+						"Allocated buf not enough\n");
+			}
+
+			if (stat != RDWR_STATUS_DONE)
+				continue;
+
+			dev_info(adapter->dev, "%s done: size=0x%tx\n",
+				 entry->mem_name, dbg_ptr - entry->mem_ptr);
+			break;
+		} while (true);
+	}
+	dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
+
+	kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+
+done:
+	adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_pcie_work(struct work_struct *work)
+{
+	struct mwifiex_adapter *adapter =
+			container_of(work, struct mwifiex_adapter, iface_work);
+
+	if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+			       &adapter->iface_work_flags))
+		mwifiex_pcie_fw_dump_work(adapter);
+}
+
+/* This function dumps FW information */
+static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
+{
+	if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags))
+		return;
+
+	set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags);
+
+	schedule_work(&adapter->iface_work);
+}
+
 /*
  * This function initializes the PCI-E host memory space, WCB rings, etc.
  *
@@ -2342,6 +2525,8 @@ static int mwifiex_register_dev(struct m
 
 	adapter->dev = &pdev->dev;
 	adapter->tx_buf_size = card->pcie.tx_buf_size;
+	adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+	adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
 	strcpy(adapter->fw_name, card->pcie.firmware);
 
 	return 0;
@@ -2394,6 +2579,8 @@ static struct mwifiex_if_ops pcie_ops =
 	.cleanup_mpa_buf =		NULL,
 	.init_fw_port =			mwifiex_pcie_init_fw_port,
 	.clean_pcie_ring =		mwifiex_clean_pcie_ring_buf,
+	.fw_dump =			mwifiex_pcie_fw_dump,
+	.iface_work =			mwifiex_pcie_work,
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/pcie.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/pcie.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/pcie.h	2014-08-07 04:55:12.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/pcie.h	2014-09-28 21:37:13.000000000 -0400
@@ -3,7 +3,7 @@
  * @brief This file contains definitions for PCI-E interface.
  * driver.
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -129,6 +129,9 @@ struct mwifiex_pcie_card_reg {
 	u32 ring_tx_start_ptr;
 	u8 pfu_enabled;
 	u8 sleep_cookie;
+	u16 fw_dump_ctrl;
+	u16 fw_dump_start;
+	u16 fw_dump_end;
 };
 
 static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
@@ -191,6 +194,9 @@ static const struct mwifiex_pcie_card_re
 	.ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
 	.pfu_enabled = 1,
 	.sleep_cookie = 0,
+	.fw_dump_ctrl = 0xcf4,
+	.fw_dump_start = 0xcf8,
+	.fw_dump_end = 0xcff
 };
 
 struct mwifiex_pcie_device {
@@ -198,6 +204,7 @@ struct mwifiex_pcie_device {
 	const struct mwifiex_pcie_card_reg *reg;
 	u16 blksz_fw_dl;
 	u16 tx_buf_size;
+	bool supports_fw_dump;
 };
 
 static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
@@ -205,6 +212,7 @@ static const struct mwifiex_pcie_device
 	.reg            = &mwifiex_reg_8766,
 	.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+	.supports_fw_dump = false,
 };
 
 static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
@@ -212,6 +220,7 @@ static const struct mwifiex_pcie_device
 	.reg            = &mwifiex_reg_8897,
 	.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+	.supports_fw_dump = true,
 };
 
 struct mwifiex_evt_buf_desc {
@@ -322,4 +331,5 @@ mwifiex_pcie_txbd_not_full(struct pcie_s
 
 	return 0;
 }
+
 #endif /* _MWIFIEX_PCIE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/README linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/README
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/README	2014-08-07 04:55:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/README	2014-09-28 21:37:05.000000000 -0400
@@ -1,4 +1,4 @@
-# Copyright (C) 2011, Marvell International Ltd.
+# Copyright (C) 2011-2014, Marvell International Ltd.
 #
 # This software file (the "File") is distributed by Marvell International
 # Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -193,6 +193,36 @@ rdeeprom
 	Example:
 		echo "0 20" > rdeeprom      : Read 20 bytes of EEPROM data from offset 0
 
+hscfg
+	This command is used to debug/simulate host sleep feature using
+	different configuration parameters.
+
+	Usage:
+		echo "<condition> [GPIO# [gap]]]" > hscfg
+		cat hscfg
+
+	where the parameters are,
+		<condition>: bit 0 = 1   -- broadcast data
+			     bit 1 = 1   -- unicast data
+			     bit 2 = 1   -- mac event
+			     bit 3 = 1   -- multicast data
+		[GPIO#]: pin number of GPIO used to wakeup the host.
+			 GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO
+			 will be used instead).
+		[gap]:   the gap in milliseconds between wakeup signal and
+			 wakeup event or 0xff for special setting (host
+			 acknowledge required) when GPIO is used to wakeup host.
+
+	Examples:
+		echo "-1" > hscfg        : Cancel host sleep mode
+		echo "3" > hscfg         : Broadcast and unicast data;
+					   Use GPIO and gap set previously
+		echo "2 3" > hscfg       : Unicast data and GPIO 3;
+					   Use gap set previously
+		echo "2 1 160" > hscfg   : Unicast data, GPIO 1 and gap 160 ms
+		echo "2 1 0xff" > hscfg  : Unicast data, GPIO 1; Wait for host
+					   to ack before sending wakeup event
+
 getlog
         This command is used to get the statistics available in the station.
 	Usage:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/scan.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/scan.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: scan ioctl and command handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sdio.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sdio.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sdio.c	2014-08-07 04:55:10.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sdio.c	2014-09-28 21:37:10.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: SDIO specific handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -50,6 +50,24 @@ static struct mwifiex_if_ops sdio_ops;
 
 static struct semaphore add_remove_card_sem;
 
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, 0, 0xF0},
+	{"DTCM", NULL, 0, 0xF1},
+	{"SQRAM", NULL, 0, 0xF2},
+	{"APU", NULL, 0, 0xF3},
+	{"CIU", NULL, 0, 0xF4},
+	{"ICU", NULL, 0, 0xF5},
+	{"MAC", NULL, 0, 0xF6},
+	{"EXT7", NULL, 0, 0xF7},
+	{"EXT8", NULL, 0, 0xF8},
+	{"EXT9", NULL, 0, 0xF9},
+	{"EXT10", NULL, 0, 0xFA},
+	{"EXT11", NULL, 0, 0xFB},
+	{"EXT12", NULL, 0, 0xFC},
+	{"EXT13", NULL, 0, 0xFD},
+	{"EXTLAST", NULL, 0, 0xFE},
+};
+
 /*
  * SDIO probe.
  *
@@ -87,6 +105,7 @@ mwifiex_sdio_probe(struct sdio_func *fun
 		card->tx_buf_size = data->tx_buf_size;
 		card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
 		card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
+		card->supports_fw_dump = data->supports_fw_dump;
 	}
 
 	sdio_claim_host(func);
@@ -179,6 +198,8 @@ mwifiex_sdio_remove(struct sdio_func *fu
 	if (!adapter || !adapter->priv_num)
 		return;
 
+	cancel_work_sync(&adapter->iface_work);
+
 	if (user_rmmod) {
 		if (adapter->is_suspended)
 			mwifiex_sdio_resume(adapter->dev);
@@ -1777,6 +1798,8 @@ static int mwifiex_register_dev(struct m
 	adapter->dev = &func->dev;
 
 	strcpy(adapter->fw_name, card->firmware);
+	adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+	adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
 
 	return 0;
 }
@@ -1914,10 +1937,10 @@ mwifiex_update_mp_end_port(struct mwifie
 		port, card->mp_data_port_mask);
 }
 
-static struct mmc_host *reset_host;
-static void sdio_card_reset_worker(struct work_struct *work)
+static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
 {
-	struct mmc_host *target = reset_host;
+	struct sdio_mmc_card *card = adapter->card;
+	struct mmc_host *target = card->func->card->host;
 
 	/* The actual reset operation must be run outside of driver thread.
 	 * This is because mmc_remove_host() will cause the device to be
@@ -1931,17 +1954,210 @@ static void sdio_card_reset_worker(struc
 	mmc_remove_host(target);
 	/* 20ms delay is based on experiment with sdhci controller */
 	mdelay(20);
+	target->rescan_entered = 0; /* rescan non-removable cards */
 	mmc_add_host(target);
 }
-static DECLARE_WORK(card_reset_work, sdio_card_reset_worker);
+
+/* This function read/write firmware */
+static enum
+rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
+				       u8 doneflag)
+{
+	struct sdio_mmc_card *card = adapter->card;
+	int ret, tries;
+	u8 ctrl_data = 0;
+
+	sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
+		    &ret);
+	if (ret) {
+		dev_err(adapter->dev, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
+				       &ret);
+		if (ret) {
+			dev_err(adapter->dev, "SDIO read err\n");
+			return RDWR_STATUS_FAILURE;
+		}
+		if (ctrl_data == FW_DUMP_DONE)
+			break;
+		if (doneflag && ctrl_data == doneflag)
+			return RDWR_STATUS_DONE;
+		if (ctrl_data != FW_DUMP_HOST_READY) {
+			dev_info(adapter->dev,
+				 "The ctrl reg was changed, re-try again!\n");
+			sdio_writeb(card->func, FW_DUMP_HOST_READY,
+				    card->reg->fw_dump_ctrl, &ret);
+			if (ret) {
+				dev_err(adapter->dev, "SDIO write err\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		usleep_range(100, 200);
+	}
+	if (ctrl_data == FW_DUMP_HOST_READY) {
+		dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
+{
+	struct mwifiex_adapter *adapter =
+			container_of(work, struct mwifiex_adapter, iface_work);
+	struct sdio_mmc_card *card = adapter->card;
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+	enum rdwr_status stat;
+	u32 memory_size;
+	static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };
+
+	if (!card->supports_fw_dump)
+		return;
+
+	for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+		if (entry->mem_ptr) {
+			vfree(entry->mem_ptr);
+			entry->mem_ptr = NULL;
+		}
+		entry->mem_size = 0;
+	}
+
+	mwifiex_pm_wakeup_card(adapter);
+	sdio_claim_host(card->func);
+
+	dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+
+	stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+	if (stat == RDWR_STATUS_FAILURE)
+		goto done;
+
+	reg = card->reg->fw_dump_start;
+	/* Read the number of the memories which will dump */
+	dump_num = sdio_readb(card->func, reg, &ret);
+	if (ret) {
+		dev_err(adapter->dev, "SDIO read memory length err\n");
+		goto done;
+	}
+
+	/* Read the length of every memory which will dump */
+	for (idx = 0; idx < dump_num; idx++) {
+		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+		stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+		if (stat == RDWR_STATUS_FAILURE)
+			goto done;
+
+		memory_size = 0;
+		reg = card->reg->fw_dump_start;
+		for (i = 0; i < 4; i++) {
+			read_reg = sdio_readb(card->func, reg, &ret);
+			if (ret) {
+				dev_err(adapter->dev, "SDIO read err\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i*8);
+			reg++;
+		}
+
+		if (memory_size == 0) {
+			dev_info(adapter->dev, "Firmware dump Finished!\n");
+			break;
+		}
+
+		dev_info(adapter->dev,
+			 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+		entry->mem_ptr = vmalloc(memory_size + 1);
+		entry->mem_size = memory_size;
+		if (!entry->mem_ptr) {
+			dev_err(adapter->dev, "Vmalloc %s failed\n",
+				entry->mem_name);
+			goto done;
+		}
+		dbg_ptr = entry->mem_ptr;
+		end_ptr = dbg_ptr + memory_size;
+
+		doneflag = entry->done_flag;
+		dev_info(adapter->dev, "Start %s output, please wait...\n",
+			 entry->mem_name);
+
+		do {
+			stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+			if (stat == RDWR_STATUS_FAILURE)
+				goto done;
+
+			reg_start = card->reg->fw_dump_start;
+			reg_end = card->reg->fw_dump_end;
+			for (reg = reg_start; reg <= reg_end; reg++) {
+				*dbg_ptr = sdio_readb(card->func, reg, &ret);
+				if (ret) {
+					dev_err(adapter->dev,
+						"SDIO read err\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					dev_err(adapter->dev,
+						"Allocated buf not enough\n");
+			}
+
+			if (stat != RDWR_STATUS_DONE)
+				continue;
+
+			dev_info(adapter->dev, "%s done: size=0x%tx\n",
+				 entry->mem_name, dbg_ptr - entry->mem_ptr);
+			break;
+		} while (1);
+	}
+	dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
+
+	kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+
+done:
+	sdio_release_host(card->func);
+	adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_sdio_work(struct work_struct *work)
+{
+	struct mwifiex_adapter *adapter =
+			container_of(work, struct mwifiex_adapter, iface_work);
+
+	if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
+			       &adapter->iface_work_flags))
+		mwifiex_sdio_card_reset_work(adapter);
+	if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+			       &adapter->iface_work_flags))
+		mwifiex_sdio_fw_dump_work(work);
+}
 
 /* This function resets the card */
 static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
 {
-	struct sdio_mmc_card *card = adapter->card;
+	if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags))
+		return;
 
-	reset_host = card->func->card->host;
-	schedule_work(&card_reset_work);
+	set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags);
+
+	schedule_work(&adapter->iface_work);
+}
+
+/* This function dumps FW information */
+static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
+{
+	if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags))
+		return;
+
+	set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags);
+	schedule_work(&adapter->iface_work);
 }
 
 static struct mwifiex_if_ops sdio_ops = {
@@ -1964,6 +2180,8 @@ static struct mwifiex_if_ops sdio_ops =
 	.cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
 	.event_complete = mwifiex_sdio_event_complete,
 	.card_reset = mwifiex_sdio_card_reset,
+	.iface_work = mwifiex_sdio_work,
+	.fw_dump = mwifiex_sdio_fw_dump,
 };
 
 /*
@@ -2001,7 +2219,6 @@ mwifiex_sdio_cleanup_module(void)
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 
-	cancel_work_sync(&card_reset_work);
 	sdio_unregister_driver(&mwifiex_sdio);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sdio.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sdio.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sdio.h	2014-08-07 04:55:07.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sdio.h	2014-09-28 21:37:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: SDIO specific definitions
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -219,6 +219,9 @@ struct mwifiex_sdio_card_reg {
 	u8 rd_len_p0_l;
 	u8 rd_len_p0_u;
 	u8 card_misc_cfg_reg;
+	u8 fw_dump_ctrl;
+	u8 fw_dump_start;
+	u8 fw_dump_end;
 };
 
 struct sdio_mmc_card {
@@ -231,6 +234,7 @@ struct sdio_mmc_card {
 	u8 mp_agg_pkt_limit;
 	bool supports_sdio_new_mode;
 	bool has_control_mask;
+	bool supports_fw_dump;
 	u16 tx_buf_size;
 	u32 mp_tx_agg_buf_size;
 	u32 mp_rx_agg_buf_size;
@@ -257,6 +261,7 @@ struct mwifiex_sdio_device {
 	u8 mp_agg_pkt_limit;
 	bool supports_sdio_new_mode;
 	bool has_control_mask;
+	bool supports_fw_dump;
 	u16 tx_buf_size;
 	u32 mp_tx_agg_buf_size;
 	u32 mp_rx_agg_buf_size;
@@ -307,6 +312,9 @@ static const struct mwifiex_sdio_card_re
 	.rd_len_p0_l = 0x0c,
 	.rd_len_p0_u = 0x0d,
 	.card_misc_cfg_reg = 0xcc,
+	.fw_dump_ctrl = 0xe2,
+	.fw_dump_start = 0xe3,
+	.fw_dump_end = 0xea,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
@@ -319,6 +327,7 @@ static const struct mwifiex_sdio_device
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+	.supports_fw_dump = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
@@ -331,6 +340,7 @@ static const struct mwifiex_sdio_device
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+	.supports_fw_dump = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
@@ -343,6 +353,7 @@ static const struct mwifiex_sdio_device
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+	.supports_fw_dump = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
@@ -355,6 +366,7 @@ static const struct mwifiex_sdio_device
 	.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+	.supports_fw_dump = true,
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: station command handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -1647,7 +1647,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_pri
 		timeout = (void *)(pos + config_len);
 		timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
 		timeout->header.len = cpu_to_le16(sizeof(timeout->value));
-		timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT);
+		timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC);
 		config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
 
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_cmdresp.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_cmdresp.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_cmdresp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_cmdresp.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: station command response handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -908,7 +908,7 @@ static int mwifiex_ret_tdls_oper(struct
 		break;
 	default:
 		dev_err(priv->adapter->dev,
-			"Unknown TDLS command action respnse %d", action);
+			"Unknown TDLS command action response %d", action);
 		return -1;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_event.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_event.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: station event handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_ioctl.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_ioctl.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: functions for station ioctl
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -26,7 +26,7 @@
 #include "11n.h"
 #include "cfg80211.h"
 
-static int disconnect_on_suspend = 1;
+static int disconnect_on_suspend;
 module_param(disconnect_on_suspend, int, 0644);
 
 /*
@@ -283,10 +283,6 @@ int mwifiex_bss_start(struct mwifiex_pri
 	    priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
 		u8 config_bands;
 
-		ret = mwifiex_deauthenticate(priv, NULL);
-		if (ret)
-			goto done;
-
 		if (!bss_desc)
 			return -1;
 
@@ -345,12 +341,6 @@ int mwifiex_bss_start(struct mwifiex_pri
 			goto done;
 		}
 
-		/* Exit Adhoc mode first */
-		dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
-		ret = mwifiex_deauthenticate(priv, NULL);
-		if (ret)
-			goto done;
-
 		priv->adhoc_is_link_sensed = false;
 
 		ret = mwifiex_check_network_compatibility(priv, bss_desc);
@@ -389,8 +379,8 @@ done:
  * This function prepares the correct firmware command and
  * issues it.
  */
-static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
-				 int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+			  int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
 
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_rx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_rx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: station RX data handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/sta_tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/sta_tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: station TX data handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/tdls.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/tdls.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/tdls.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/tdls.c	2014-09-28 17:29:07.000000000 -0400
@@ -530,7 +530,6 @@ int mwifiex_send_tdls_data_frame(struct
 {
 	struct sk_buff *skb;
 	struct mwifiex_txinfo *tx_info;
-	struct timeval tv;
 	int ret;
 	u16 skb_len;
 
@@ -609,8 +608,7 @@ int mwifiex_send_tdls_data_frame(struct
 	tx_info->bss_num = priv->bss_num;
 	tx_info->bss_type = priv->bss_type;
 
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	__net_timestamp(skb);
 	mwifiex_queue_tx_pkt(priv, skb);
 
 	return 0;
@@ -703,7 +701,6 @@ int mwifiex_send_tdls_action_frame(struc
 {
 	struct sk_buff *skb;
 	struct mwifiex_txinfo *tx_info;
-	struct timeval tv;
 	u8 *pos;
 	u32 pkt_type, tx_control;
 	u16 pkt_len, skb_len;
@@ -769,8 +766,7 @@ int mwifiex_send_tdls_action_frame(struc
 	pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
 	memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
 	       sizeof(pkt_len));
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	__net_timestamp(skb);
 	mwifiex_queue_tx_pkt(priv, skb);
 
 	return 0;
@@ -785,6 +781,7 @@ void mwifiex_process_tdls_action_frame(s
 	struct mwifiex_sta_node *sta_ptr;
 	u8 *peer, *pos, *end;
 	u8 i, action, basic;
+	__le16 cap = 0;
 	int ie_len = 0;
 
 	if (len < (sizeof(struct ethhdr) + 3))
@@ -796,18 +793,9 @@ void mwifiex_process_tdls_action_frame(s
 
 	peer = buf + ETH_ALEN;
 	action = *(buf + sizeof(struct ethhdr) + 2);
-
-	/* just handle TDLS setup request/response/confirm */
-	if (action > WLAN_TDLS_SETUP_CONFIRM)
-		return;
-
 	dev_dbg(priv->adapter->dev,
 		"rx:tdls action: peer=%pM, action=%d\n", peer, action);
 
-	sta_ptr = mwifiex_add_sta_entry(priv, peer);
-	if (!sta_ptr)
-		return;
-
 	switch (action) {
 	case WLAN_TDLS_SETUP_REQUEST:
 		if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
@@ -815,7 +803,7 @@ void mwifiex_process_tdls_action_frame(s
 
 		pos = buf + sizeof(struct ethhdr) + 4;
 		/* payload 1+ category 1 + action 1 + dialog 1 */
-		sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+		cap = cpu_to_le16(*(u16 *)pos);
 		ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
 		pos += 2;
 		break;
@@ -825,7 +813,7 @@ void mwifiex_process_tdls_action_frame(s
 			return;
 		/* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
 		pos = buf + sizeof(struct ethhdr) + 6;
-		sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+		cap = cpu_to_le16(*(u16 *)pos);
 		ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
 		pos += 2;
 		break;
@@ -837,10 +825,16 @@ void mwifiex_process_tdls_action_frame(s
 		ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
 		break;
 	default:
-		dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
+		dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
 		return;
 	}
 
+	sta_ptr = mwifiex_add_sta_entry(priv, peer);
+	if (!sta_ptr)
+		return;
+
+	sta_ptr->tdls_cap.capab = cap;
+
 	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
 		if (pos + 2 + pos[1] > end)
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/txrx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/txrx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: generic TX/RX data handling
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: AP specific command handling
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_event.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_event.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_event.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: AP event handling
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_txrx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_txrx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/uap_txrx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/uap_txrx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: AP TX and RX data handling
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -96,7 +96,6 @@ static void mwifiex_uap_queue_bridged_pk
 	struct sk_buff *new_skb;
 	struct mwifiex_txinfo *tx_info;
 	int hdr_chop;
-	struct timeval tv;
 	struct ethhdr *p_ethhdr;
 
 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
@@ -193,8 +192,7 @@ static void mwifiex_uap_queue_bridged_pk
 		tx_info->pkt_len = skb->len;
 	}
 
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	__net_timestamp(skb);
 	mwifiex_wmm_add_buf_txqueue(priv, skb);
 	atomic_inc(&adapter->tx_pending);
 	atomic_inc(&adapter->pending_bridged_pkts);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/usb.c	2014-08-07 04:55:21.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/usb.c	2014-09-28 21:37:20.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: USB specific handling
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/usb.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/usb.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/usb.h	2014-08-07 04:55:18.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/usb.h	2014-09-28 21:37:18.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * This file contains definitions for mwifiex USB interface driver.
  *
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/util.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/util.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/util.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/util.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: utility functions
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/util.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/util.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/util.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/util.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: utility functions
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/wmm.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/wmm.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/wmm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/wmm.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: WMM
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -878,15 +878,8 @@ u8
 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
 				  const struct sk_buff *skb)
 {
+	u32 queue_delay = ktime_to_ms(net_timedelta(skb->tstamp));
 	u8 ret_val;
-	struct timeval out_tstamp, in_tstamp;
-	u32 queue_delay;
-
-	do_gettimeofday(&out_tstamp);
-	in_tstamp = ktime_to_timeval(skb->tstamp);
-
-	queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000;
-	queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000;
 
 	/*
 	 * Queue delay is passed as a uint8 in units of 2ms (ms shifted
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/wmm.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/wmm.h
--- linux-libre-3.16-gnu/drivers/net/wireless/mwifiex/wmm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwifiex/wmm.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Marvell Wireless LAN device driver: WMM
  *
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
  *
  * This software file (the "File") is distributed by Marvell International
  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/mwl8k.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwl8k.c
--- linux-libre-3.16-gnu/drivers/net/wireless/mwl8k.c	2014-08-07 04:55:25.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/mwl8k.c	2014-09-28 21:37:26.000000000 -0400
@@ -1159,12 +1159,11 @@ static int mwl8k_rxq_init(struct ieee802
 
 	size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
 
-	rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
+	rxq->rxd = pci_zalloc_consistent(priv->pdev, size, &rxq->rxd_dma);
 	if (rxq->rxd == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n");
 		return -ENOMEM;
 	}
-	memset(rxq->rxd, 0, size);
 
 	rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
 	if (rxq->buf == NULL) {
@@ -1451,12 +1450,11 @@ static int mwl8k_txq_init(struct ieee802
 
 	size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
 
-	txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
+	txq->txd = pci_zalloc_consistent(priv->pdev, size, &txq->txd_dma);
 	if (txq->txd == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n");
 		return -ENOMEM;
 	}
-	memset(txq->txd, 0, size);
 
 	txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
@@ -1633,22 +1631,17 @@ static int mwl8k_tid_queue_mapping(u8 ti
 	case 0:
 	case 3:
 		return IEEE80211_AC_BE;
-		break;
 	case 1:
 	case 2:
 		return IEEE80211_AC_BK;
-		break;
 	case 4:
 	case 5:
 		return IEEE80211_AC_VI;
-		break;
 	case 6:
 	case 7:
 		return IEEE80211_AC_VO;
-		break;
 	default:
 		return -1;
-		break;
 	}
 }
 
@@ -5675,7 +5668,7 @@ static struct mwl8k_device_info mwl8k_in
 
 /*(DEBLOBBED)*/
 
-static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
+static const struct pci_device_id mwl8k_pci_id_table[] = {
 	{ PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
 	{ PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
 	{ PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@ config PCI_HERMES
 
 config PCMCIA_HERMES
 	tristate "Hermes PCMCIA card support"
-	depends on PCMCIA && HERMES
+	depends on PCMCIA && HERMES && HAS_IOPORT_MAP
 	---help---
 	  A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
 	  as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -122,7 +122,7 @@ config PCMCIA_HERMES
 
 config PCMCIA_SPECTRUM
 	tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
-	depends on PCMCIA && HERMES
+	depends on PCMCIA && HERMES && HAS_IOPORT_MAP
 	---help---
 
 	  This is a driver for 802.11b cards using RAM-loadable Symbol
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_nortel.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_nortel.c
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_nortel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_nortel.c	2014-09-28 17:29:07.000000000 -0400
@@ -272,7 +272,7 @@ static void orinoco_nortel_remove_one(st
 	pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(orinoco_nortel_id_table) = {
+static const struct pci_device_id orinoco_nortel_id_table[] = {
 	/* Nortel emobility PCI */
 	{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
 	/* Symbol LA-4123 PCI */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -210,7 +210,7 @@ static void orinoco_pci_remove_one(struc
 	pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(orinoco_pci_id_table) = {
+static const struct pci_device_id orinoco_pci_id_table[] = {
 	/* Intersil Prism 3 */
 	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
 	/* Intersil Prism 2.5 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_plx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_plx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_plx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_plx.c	2014-09-28 17:29:07.000000000 -0400
@@ -308,7 +308,7 @@ static void orinoco_plx_remove_one(struc
 	pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(orinoco_plx_id_table) = {
+static const struct pci_device_id orinoco_plx_id_table[] = {
 	{0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,},	/* Siemens SpeedStream SS1023 */
 	{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},	/* Netgear MA301 */
 	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga  - does this work? */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_tmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_tmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_tmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_tmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -201,7 +201,7 @@ static void orinoco_tmd_remove_one(struc
 	pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(orinoco_tmd_id_table) = {
+static const struct pci_device_id orinoco_tmd_id_table[] = {
 	{0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,},      /* NDC and OEMs, e.g. pheecom */
 	{0,},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/orinoco/orinoco_usb.c	2014-08-07 04:53:55.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/orinoco/orinoco_usb.c	2014-09-28 21:35:49.000000000 -0400
@@ -921,7 +921,6 @@ static int ezusb_access_ltv(struct ezusb
 			retval = -EFAULT;
 		}
 		goto exit;
-		break;
 	}
 	if (ctx->in_rid) {
 		struct ezusb_packet *ans = ctx->buf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/p54/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/p54/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/Kconfig	2014-09-28 21:38:01.000000000 -0400
@@ -57,7 +57,7 @@ config P54_SPI_DEFAULT_EEPROM
 	 a dedicated EEPROM chip to store all device specific values
 	 for calibration, country and interface settings.
 
-	 The driver will try to load the image "3826.eeprom", if the
+	 The driver will try to load the image "DEBLOBBED", if the
 	 file is put at the right place. (usually /lib/firmware.)
 
 	 Only if this request fails, this option will provide a
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/p54/p54pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/p54pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/p54/p54pci.c	2014-08-07 04:55:55.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/p54pci.c	2014-09-28 21:38:01.000000000 -0400
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS("prism54pci");
 /*(DEBLOBBED)*/
 
-static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
+static const struct pci_device_id p54p_table[] = {
 	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
 	{ PCI_DEVICE(0x1260, 0x3890) },
 	/* 3COM 3CRWE154G72 Wireless LAN adapter */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/p54/p54spi.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/p54spi.c
--- linux-libre-3.16-gnu/drivers/net/wireless/p54/p54spi.c	2014-08-07 04:55:57.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/p54/p54spi.c	2014-09-28 21:38:04.000000000 -0400
@@ -193,7 +193,7 @@ static int p54spi_request_eeprom(struct
 	/* allow users to customize their eeprom.
 	 */
 
-	ret = reject_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
+	ret = reject_firmware_direct(&eeprom, "/*(DEBLOBBED)*/", &priv->spi->dev);
 	if (ret < 0) {
 #ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
 		dev_info(&priv->spi->dev, "loading default eeprom...\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/prism54/islpci_hotplug.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/prism54/islpci_hotplug.c
--- linux-libre-3.16-gnu/drivers/net/wireless/prism54/islpci_hotplug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/prism54/islpci_hotplug.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@ module_param(init_pcitm, int, 0);
  * driver_data
  * If you have an update for this please contact prism54-devel@prism54.org
  * The latest list can be found at http://wireless.kernel.org/en/users/Drivers/p54 */
-static DEFINE_PCI_DEVICE_TABLE(prism54_id_tbl) = {
+static const struct pci_device_id prism54_id_tbl[] = {
 	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
 	{
 	 0x1260, 0x3890,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/prism54/oid_mgt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/prism54/oid_mgt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/prism54/oid_mgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/prism54/oid_mgt.c	2014-09-28 17:29:07.000000000 -0400
@@ -793,7 +793,6 @@ mgt_response_to_str(enum oid_num_t n, un
 	switch (isl_oid[n].flags & OID_FLAG_TYPE) {
 	case OID_TYPE_U32:
 		return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u);
-		break;
 	case OID_TYPE_BUFFER:{
 			struct obj_buffer *buff = r->ptr;
 			return snprintf(str, PRIV_STR_SIZE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_core.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_core.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,6 +77,52 @@ static bool rsi_recalculate_weights(stru
 }
 
 /**
+ * rsi_get_num_pkts_dequeue() - This function determines the number of
+ *		                packets to be dequeued based on the number
+ *			        of bytes calculated using txop.
+ *
+ * @common: Pointer to the driver private structure.
+ * @q_num: the queue from which pkts have to be dequeued
+ *
+ * Return: pkt_num: Number of pkts to be dequeued.
+ */
+static u32 rsi_get_num_pkts_dequeue(struct rsi_common *common, u8 q_num)
+{
+	struct rsi_hw *adapter = common->priv;
+	struct sk_buff *skb;
+	u32 pkt_cnt = 0;
+	s16 txop = common->tx_qinfo[q_num].txop * 32;
+	__le16 r_txop;
+	struct ieee80211_rate rate;
+
+	rate.bitrate = RSI_RATE_MCS0 * 5 * 10; /* Convert to Kbps */
+	if (q_num == VI_Q)
+		txop = ((txop << 5) / 80);
+
+	if (skb_queue_len(&common->tx_queue[q_num]))
+		skb = skb_peek(&common->tx_queue[q_num]);
+	else
+		return 0;
+
+	do {
+		r_txop = ieee80211_generic_frame_duration(adapter->hw,
+							  adapter->vifs[0],
+							  common->band,
+							  skb->len, &rate);
+		txop -= le16_to_cpu(r_txop);
+		pkt_cnt += 1;
+		/*checking if pkts are still there*/
+		if (skb_queue_len(&common->tx_queue[q_num]) - pkt_cnt)
+			skb = skb->next;
+		else
+			break;
+
+	} while (txop > 0);
+
+	return pkt_cnt;
+}
+
+/**
  * rsi_core_determine_hal_queue() - This function determines the queue from
  *				    which packet has to be dequeued.
  * @common: Pointer to the driver private structure.
@@ -88,7 +134,7 @@ static u8 rsi_core_determine_hal_queue(s
 	bool recontend_queue = false;
 	u32 q_len = 0;
 	u8 q_num = INVALID_QUEUE;
-	u8 ii = 0, min = 0;
+	u8 ii = 0;
 
 	if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
 		if (!common->mgmt_q_block)
@@ -96,6 +142,9 @@ static u8 rsi_core_determine_hal_queue(s
 		return q_num;
 	}
 
+	if (common->hw_data_qs_blocked)
+		return q_num;
+
 	if (common->pkt_cnt != 0) {
 		--common->pkt_cnt;
 		return common->selected_qnum;
@@ -106,14 +155,15 @@ get_queue_num:
 
 	q_num = rsi_determine_min_weight_queue(common);
 
-	q_len = skb_queue_len(&common->tx_queue[ii]);
 	ii = q_num;
 
 	/* Selecting the queue with least back off */
 	for (; ii < NUM_EDCA_QUEUES; ii++) {
+		q_len = skb_queue_len(&common->tx_queue[ii]);
 		if (((common->tx_qinfo[ii].pkt_contended) &&
-		     (common->tx_qinfo[ii].weight < min)) && q_len) {
-			min = common->tx_qinfo[ii].weight;
+		     (common->tx_qinfo[ii].weight < common->min_weight)) &&
+		      q_len) {
+			common->min_weight = common->tx_qinfo[ii].weight;
 			q_num = ii;
 		}
 	}
@@ -140,25 +190,9 @@ get_queue_num:
 	common->selected_qnum = q_num;
 	q_len = skb_queue_len(&common->tx_queue[q_num]);
 
-	switch (common->selected_qnum) {
-	case VO_Q:
-		if (q_len > MAX_CONTINUOUS_VO_PKTS)
-			common->pkt_cnt = (MAX_CONTINUOUS_VO_PKTS - 1);
-		else
-			common->pkt_cnt = --q_len;
-		break;
-
-	case VI_Q:
-		if (q_len > MAX_CONTINUOUS_VI_PKTS)
-			common->pkt_cnt = (MAX_CONTINUOUS_VI_PKTS - 1);
-		else
-			common->pkt_cnt = --q_len;
-
-		break;
-
-	default:
-		common->pkt_cnt = 0;
-		break;
+	if (q_num == VO_Q || q_num == VI_Q) {
+		common->pkt_cnt = rsi_get_num_pkts_dequeue(common, q_num);
+		common->pkt_cnt -= 1;
 	}
 
 	return q_num;
@@ -252,6 +286,7 @@ void rsi_core_qos_processor(struct rsi_c
 
 		skb = rsi_core_dequeue_pkt(common, q_num);
 		if (skb == NULL) {
+			rsi_dbg(ERR_ZONE, "skb null\n");
 			mutex_unlock(&common->tx_rxlock);
 			break;
 		}
@@ -306,7 +341,8 @@ void rsi_core_xmit(struct rsi_common *co
 	}
 
 	if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||
-	    (ieee80211_is_ctl(tmp_hdr->frame_control))) {
+	    (ieee80211_is_ctl(tmp_hdr->frame_control)) ||
+	    (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) {
 		q_num = MGMT_SOFT_Q;
 		skb->priority = q_num;
 	} else {
@@ -325,6 +361,7 @@ void rsi_core_xmit(struct rsi_common *co
 	if ((q_num != MGMT_SOFT_Q) &&
 	    ((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
 	     DATA_QUEUE_WATER_MARK)) {
+		rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
 		if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
 			ieee80211_stop_queue(adapter->hw, WME_AC(q_num));
 		rsi_set_event(&common->tx_thread.event);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_debugfs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,7 @@ static int rsi_stats_read(struct seq_fil
 	seq_printf(seq, "total_mgmt_pkt_send : %d\n",
 		   common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
 	seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
-		   skb_queue_len(&common->tx_queue[4]));
+		   skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
 	seq_printf(seq, "total_mgmt_pkt_freed  : %d\n",
 		   common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
 
@@ -153,25 +153,25 @@ static int rsi_stats_read(struct seq_fil
 	seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
 		   common->tx_stats.total_tx_pkt_send[VO_Q]);
 	seq_printf(seq, "total_data_vo_pkt_queued:  %8d\t",
-		   skb_queue_len(&common->tx_queue[0]));
+		   skb_queue_len(&common->tx_queue[VO_Q]));
 	seq_printf(seq, "total_vo_pkt_freed: %8d\n",
 		   common->tx_stats.total_tx_pkt_freed[VO_Q]);
 	seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
 		   common->tx_stats.total_tx_pkt_send[VI_Q]);
 	seq_printf(seq, "total_data_vi_pkt_queued:  %8d\t",
-		   skb_queue_len(&common->tx_queue[1]));
+		   skb_queue_len(&common->tx_queue[VI_Q]));
 	seq_printf(seq, "total_vi_pkt_freed: %8d\n",
 		   common->tx_stats.total_tx_pkt_freed[VI_Q]);
 	seq_printf(seq,  "total_data_be_pkt_send: %8d\t",
 		   common->tx_stats.total_tx_pkt_send[BE_Q]);
 	seq_printf(seq, "total_data_be_pkt_queued:  %8d\t",
-		   skb_queue_len(&common->tx_queue[2]));
+		   skb_queue_len(&common->tx_queue[BE_Q]));
 	seq_printf(seq, "total_be_pkt_freed: %8d\n",
 		   common->tx_stats.total_tx_pkt_freed[BE_Q]);
 	seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
 		   common->tx_stats.total_tx_pkt_send[BK_Q]);
 	seq_printf(seq, "total_data_bk_pkt_queued:  %8d\t",
-		   skb_queue_len(&common->tx_queue[3]));
+		   skb_queue_len(&common->tx_queue[BK_Q]));
 	seq_printf(seq, "total_bk_pkt_freed: %8d\n",
 		   common->tx_stats.total_tx_pkt_freed[BK_Q]);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,7 +177,7 @@ static void rsi_register_rates_channels(
 	sbands->ht_cap.cap = (IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
 			      IEEE80211_HT_CAP_SGI_20 |
 			      IEEE80211_HT_CAP_SGI_40);
-	sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+	sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
 	sbands->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
 	sbands->ht_cap.mcs.rx_mask[0] = 0xff;
 	sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
@@ -185,7 +185,7 @@ static void rsi_register_rates_channels(
 }
 
 /**
- * rsi_mac80211_attach() - This function is used to de-initialize the
+ * rsi_mac80211_detach() - This function is used to de-initialize the
  *			   Mac80211 stack.
  * @adapter: Pointer to the adapter structure.
  *
@@ -341,6 +341,59 @@ static void rsi_mac80211_remove_interfac
 }
 
 /**
+ * rsi_channel_change() - This function is a performs the checks
+ *			  required for changing a channel and sets
+ *			  the channel accordingly.
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_channel_change(struct ieee80211_hw *hw)
+{
+	struct rsi_hw *adapter = hw->priv;
+	struct rsi_common *common = adapter->priv;
+	int status = -EOPNOTSUPP;
+	struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+	u16 channel = curchan->hw_value;
+	struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+
+	rsi_dbg(INFO_ZONE,
+		"%s: Set channel: %d MHz type: %d channel_no %d\n",
+		__func__, curchan->center_freq,
+		curchan->flags, channel);
+
+	if (bss->assoc) {
+		if (!common->hw_data_qs_blocked &&
+		    (rsi_get_connected_channel(adapter) != channel)) {
+			rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
+			if (!rsi_send_block_unblock_frame(common, true))
+				common->hw_data_qs_blocked = true;
+		}
+	}
+
+	status = rsi_band_check(common);
+	if (!status)
+		status = rsi_set_channel(adapter->priv, channel);
+
+	if (bss->assoc) {
+		if (common->hw_data_qs_blocked &&
+		    (rsi_get_connected_channel(adapter) == channel)) {
+			rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+			if (!rsi_send_block_unblock_frame(common, false))
+				common->hw_data_qs_blocked = false;
+		}
+	} else {
+		if (common->hw_data_qs_blocked) {
+			rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+			if (!rsi_send_block_unblock_frame(common, false))
+				common->hw_data_qs_blocked = false;
+		}
+	}
+
+	return status;
+}
+
+/**
  * rsi_mac80211_config() - This function is a handler for configuration
  *			   requests. The stack calls this function to
  *			   change hardware configuration, e.g., channel.
@@ -357,17 +410,10 @@ static int rsi_mac80211_config(struct ie
 	int status = -EOPNOTSUPP;
 
 	mutex_lock(&common->mutex);
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		struct ieee80211_channel *curchan = hw->conf.chandef.chan;
-		u16 channel = curchan->hw_value;
 
-		rsi_dbg(INFO_ZONE,
-			"%s: Set channel: %d MHz type: %d channel_no %d\n",
-			__func__, curchan->center_freq,
-			curchan->flags, channel);
-		common->band = curchan->band;
-		status = rsi_set_channel(adapter->priv, channel);
-	}
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
+		status = rsi_channel_change(hw);
+
 	mutex_unlock(&common->mutex);
 
 	return status;
@@ -421,6 +467,15 @@ static void rsi_mac80211_bss_info_change
 				      bss_conf->qos,
 				      bss_conf->aid);
 	}
+
+	if (changed & BSS_CHANGED_CQM) {
+		common->cqm_info.last_cqm_event_rssi = 0;
+		common->cqm_info.rssi_thold = bss_conf->cqm_rssi_thold;
+		common->cqm_info.rssi_hyst = bss_conf->cqm_rssi_hyst;
+		rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n",
+			common->cqm_info.rssi_thold,
+			common->cqm_info.rssi_hyst);
+	}
 	mutex_unlock(&common->mutex);
 }
 
@@ -723,17 +778,17 @@ static int rsi_mac80211_set_rate_mask(st
 {
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
+	enum ieee80211_band band = hw->conf.chandef.chan->band;
 
 	mutex_lock(&common->mutex);
+	common->fixedrate_mask[band] = 0;
 
-	common->fixedrate_mask[IEEE80211_BAND_2GHZ] = 0;
-
-	if (mask->control[IEEE80211_BAND_2GHZ].legacy == 0xfff) {
-		common->fixedrate_mask[IEEE80211_BAND_2GHZ] =
-			(mask->control[IEEE80211_BAND_2GHZ].ht_mcs[0] << 12);
+	if (mask->control[band].legacy == 0xfff) {
+		common->fixedrate_mask[band] =
+			(mask->control[band].ht_mcs[0] << 12);
 	} else {
-		common->fixedrate_mask[IEEE80211_BAND_2GHZ] =
-			mask->control[IEEE80211_BAND_2GHZ].legacy;
+		common->fixedrate_mask[band] =
+			mask->control[band].legacy;
 	}
 	mutex_unlock(&common->mutex);
 
@@ -741,6 +796,37 @@ static int rsi_mac80211_set_rate_mask(st
 }
 
 /**
+ * rsi_perform_cqm() - This function performs cqm.
+ * @common: Pointer to the driver private structure.
+ * @bssid: pointer to the bssid.
+ * @rssi: RSSI value.
+ */
+static void rsi_perform_cqm(struct rsi_common *common,
+			    u8 *bssid,
+			    s8 rssi)
+{
+	struct rsi_hw *adapter = common->priv;
+	s8 last_event = common->cqm_info.last_cqm_event_rssi;
+	int thold = common->cqm_info.rssi_thold;
+	u32 hyst = common->cqm_info.rssi_hyst;
+	enum nl80211_cqm_rssi_threshold_event event;
+
+	if (rssi < thold && (last_event == 0 || rssi < (last_event - hyst)))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+	else if (rssi > thold &&
+		 (last_event == 0 || rssi > (last_event + hyst)))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+	else
+		return;
+
+	common->cqm_info.last_cqm_event_rssi = rssi;
+	rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
+	ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
+
+	return;
+}
+
+/**
  * rsi_fill_rx_status() - This function fills rx status in
  *			  ieee80211_rx_status structure.
  * @hw: Pointer to the ieee80211_hw structure.
@@ -755,6 +841,7 @@ static void rsi_fill_rx_status(struct ie
 			       struct rsi_common *common,
 			       struct ieee80211_rx_status *rxs)
 {
+	struct ieee80211_bss_conf *bss = &common->priv->vifs[0]->bss_conf;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct skb_info *rx_params = (struct skb_info *)info->driver_data;
 	struct ieee80211_hdr *hdr;
@@ -770,10 +857,7 @@ static void rsi_fill_rx_status(struct ie
 
 	rxs->signal = -(rssi);
 
-	if (channel <= 14)
-		rxs->band = IEEE80211_BAND_2GHZ;
-	else
-		rxs->band = IEEE80211_BAND_5GHZ;
+	rxs->band = common->band;
 
 	freq = ieee80211_channel_to_frequency(channel, rxs->band);
 
@@ -792,6 +876,14 @@ static void rsi_fill_rx_status(struct ie
 		rxs->flag |= RX_FLAG_DECRYPTED;
 		rxs->flag |= RX_FLAG_IV_STRIPPED;
 	}
+
+	/* CQM only for connected AP beacons, the RSSI is a weighted avg */
+	if (bss->assoc && !(memcmp(bss->bssid, hdr->addr2, ETH_ALEN))) {
+		if (ieee80211_is_beacon(hdr->frame_control))
+			rsi_perform_cqm(common, hdr->addr2, rxs->signal);
+	}
+
+	return;
 }
 
 /**
@@ -983,6 +1075,7 @@ int rsi_mac80211_attach(struct rsi_commo
 
 	hw->max_tx_aggregation_subframes = 6;
 	rsi_register_rates_channels(adapter, IEEE80211_BAND_2GHZ);
+	rsi_register_rates_channels(adapter, IEEE80211_BAND_5GHZ);
 	hw->rate_control_algorithm = "AARF";
 
 	SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
@@ -1000,6 +1093,8 @@ int rsi_mac80211_attach(struct rsi_commo
 	wiphy->available_antennas_tx = 1;
 	wiphy->bands[IEEE80211_BAND_2GHZ] =
 		&adapter->sbands[IEEE80211_BAND_2GHZ];
+	wiphy->bands[IEEE80211_BAND_5GHZ] =
+		&adapter->sbands[IEEE80211_BAND_5GHZ];
 
 	status = ieee80211_register_hw(hw);
 	if (status)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_mgmt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_mgmt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_mgmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_mgmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -217,6 +217,7 @@ static void rsi_set_default_parameters(s
 	common->min_rate = 0xffff;
 	common->fsm_state = FSM_CARD_NOT_READY;
 	common->iface_down = true;
+	common->endpoint = EP_2GHZ_20MHZ;
 }
 
 /**
@@ -276,7 +277,6 @@ static int rsi_load_radio_caps(struct rs
 {
 	struct rsi_radio_caps *radio_caps;
 	struct rsi_hw *adapter = common->priv;
-	struct ieee80211_hw *hw = adapter->hw;
 	u16 inx = 0;
 	u8 ii;
 	u8 radio_id = 0;
@@ -285,7 +285,6 @@ static int rsi_load_radio_caps(struct rs
 		      0xf0, 0xf0, 0xf0, 0xf0,
 		      0xf0, 0xf0, 0xf0, 0xf0,
 		      0xf0, 0xf0, 0xf0, 0xf0};
-	struct ieee80211_conf *conf = &hw->conf;
 	struct sk_buff *skb;
 
 	rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);
@@ -307,29 +306,36 @@ static int rsi_load_radio_caps(struct rs
 	if (common->channel_width == BW_40MHZ) {
 		radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);
 		radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ);
-		if (common->channel_width) {
-			radio_caps->desc_word[5] =
-				cpu_to_le16(common->channel_width << 12);
-			radio_caps->desc_word[5] |= cpu_to_le16(FULL40M_ENABLE);
-		}
-
-		if (conf_is_ht40_minus(conf)) {
-			radio_caps->desc_word[5] = 0;
-			radio_caps->desc_word[5] |=
-				cpu_to_le16(LOWER_20_ENABLE);
-			radio_caps->desc_word[5] |=
-				cpu_to_le16(LOWER_20_ENABLE >> 12);
-		}
 
-		if (conf_is_ht40_plus(conf)) {
-			radio_caps->desc_word[5] = 0;
-			radio_caps->desc_word[5] |=
-				cpu_to_le16(UPPER_20_ENABLE);
-			radio_caps->desc_word[5] |=
-				cpu_to_le16(UPPER_20_ENABLE >> 12);
+		if (common->fsm_state == FSM_MAC_INIT_DONE) {
+			struct ieee80211_hw *hw = adapter->hw;
+			struct ieee80211_conf *conf = &hw->conf;
+			if (conf_is_ht40_plus(conf)) {
+				radio_caps->desc_word[5] =
+					cpu_to_le16(LOWER_20_ENABLE);
+				radio_caps->desc_word[5] |=
+					cpu_to_le16(LOWER_20_ENABLE >> 12);
+			} else if (conf_is_ht40_minus(conf)) {
+				radio_caps->desc_word[5] =
+					cpu_to_le16(UPPER_20_ENABLE);
+				radio_caps->desc_word[5] |=
+					cpu_to_le16(UPPER_20_ENABLE >> 12);
+			} else {
+				radio_caps->desc_word[5] =
+					cpu_to_le16(BW_40MHZ << 12);
+				radio_caps->desc_word[5] |=
+					cpu_to_le16(FULL40M_ENABLE);
+			}
 		}
 	}
 
+	radio_caps->sifs_tx_11n = cpu_to_le16(SIFS_TX_11N_VALUE);
+	radio_caps->sifs_tx_11b = cpu_to_le16(SIFS_TX_11B_VALUE);
+	radio_caps->slot_rx_11n = cpu_to_le16(SHORT_SLOT_VALUE);
+	radio_caps->ofdm_ack_tout = cpu_to_le16(OFDM_ACK_TOUT_VALUE);
+	radio_caps->cck_ack_tout = cpu_to_le16(CCK_ACK_TOUT_VALUE);
+	radio_caps->preamble_type = cpu_to_le16(LONG_PREAMBLE);
+
 	radio_caps->desc_word[7] |= cpu_to_le16(radio_id << 8);
 
 	for (ii = 0; ii < MAX_HW_QUEUES; ii++) {
@@ -588,7 +594,7 @@ static int rsi_program_bb_rf(struct rsi_
 
 	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 	mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA);
-	mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint << 8);
+	mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint);
 
 	if (common->rf_reset) {
 		mgmt_frame->desc_word[7] =  cpu_to_le16(RF_RESET_ENABLE);
@@ -615,6 +621,9 @@ int rsi_set_vap_capabilities(struct rsi_
 {
 	struct sk_buff *skb = NULL;
 	struct rsi_vap_caps *vap_caps;
+	struct rsi_hw *adapter = common->priv;
+	struct ieee80211_hw *hw = adapter->hw;
+	struct ieee80211_conf *conf = &hw->conf;
 	u16 vap_id = 0;
 
 	rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__);
@@ -644,13 +653,24 @@ int rsi_set_vap_capabilities(struct rsi_
 	vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD);
 
 	vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold);
-	vap_caps->default_mgmt_rate = 0;
-	if (conf_is_ht40(&common->priv->hw->conf)) {
-		vap_caps->default_ctrl_rate =
-				cpu_to_le32(RSI_RATE_6 | FULL40M_ENABLE << 16);
-	} else {
+	vap_caps->default_mgmt_rate = cpu_to_le32(RSI_RATE_6);
+
+	if (common->band == IEEE80211_BAND_5GHZ) {
 		vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6);
+		if (conf_is_ht40(&common->priv->hw->conf)) {
+			vap_caps->default_ctrl_rate |=
+				cpu_to_le32(FULL40M_ENABLE << 16);
+		}
+	} else {
+		vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_1);
+		if (conf_is_ht40_minus(conf))
+			vap_caps->default_ctrl_rate |=
+				cpu_to_le32(UPPER_20_ENABLE << 16);
+		else if (conf_is_ht40_plus(conf))
+			vap_caps->default_ctrl_rate |=
+				cpu_to_le32(LOWER_20_ENABLE << 16);
 	}
+
 	vap_caps->default_data_rate = 0;
 	vap_caps->beacon_interval = cpu_to_le16(200);
 	vap_caps->dtim_period = cpu_to_le16(4);
@@ -827,6 +847,63 @@ static int rsi_send_reset_mac(struct rsi
 }
 
 /**
+ * rsi_band_check() - This function programs the band
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_band_check(struct rsi_common *common)
+{
+	struct rsi_hw *adapter = common->priv;
+	struct ieee80211_hw *hw = adapter->hw;
+	u8 prev_bw = common->channel_width;
+	u8 prev_ep = common->endpoint;
+	struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+	int status = 0;
+
+	if (common->band != curchan->band) {
+		common->rf_reset = 1;
+		common->band = curchan->band;
+	}
+
+	if ((hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) ||
+	    (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20))
+		common->channel_width = BW_20MHZ;
+	else
+		common->channel_width = BW_40MHZ;
+
+	if (common->band == IEEE80211_BAND_2GHZ) {
+		if (common->channel_width)
+			common->endpoint = EP_2GHZ_40MHZ;
+		else
+			common->endpoint = EP_2GHZ_20MHZ;
+	} else {
+		if (common->channel_width)
+			common->endpoint = EP_5GHZ_40MHZ;
+		else
+			common->endpoint = EP_5GHZ_20MHZ;
+	}
+
+	if (common->endpoint != prev_ep) {
+		status = rsi_program_bb_rf(common);
+		if (status)
+			return status;
+	}
+
+	if (common->channel_width != prev_bw) {
+		status = rsi_load_bootup_params(common);
+		if (status)
+			return status;
+
+		status = rsi_load_radio_caps(common);
+		if (status)
+			return status;
+	}
+
+	return status;
+}
+
+/**
  * rsi_set_channel() - This function programs the channel.
  * @common: Pointer to the driver private structure.
  * @channel: Channel value to be set.
@@ -841,23 +918,6 @@ int rsi_set_channel(struct rsi_common *c
 	rsi_dbg(MGMT_TX_ZONE,
 		"%s: Sending scan req frame\n", __func__);
 
-	if (common->band == IEEE80211_BAND_5GHZ) {
-		if ((channel >= 36) && (channel <= 64))
-			channel = ((channel - 32) / 4);
-		else if ((channel > 64) && (channel <= 140))
-			channel = ((channel - 102) / 4) + 8;
-		else if (channel >= 149)
-			channel = ((channel - 151) / 4) + 18;
-		else
-			return -EINVAL;
-	} else {
-		if (channel > 14) {
-			rsi_dbg(ERR_ZONE, "%s: Invalid chno %d, band = %d\n",
-				__func__, channel, common->band);
-			return -EINVAL;
-		}
-	}
-
 	skb = dev_alloc_skb(FRAME_DESC_SZ);
 	if (!skb) {
 		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
@@ -877,6 +937,7 @@ int rsi_set_channel(struct rsi_common *c
 					       (RSI_RF_TYPE << 4));
 
 	mgmt_frame->desc_word[5] = cpu_to_le16(0x01);
+	mgmt_frame->desc_word[6] = cpu_to_le16(0x12);
 
 	if (common->channel_width == BW_40MHZ)
 		mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);
@@ -950,7 +1011,7 @@ static int rsi_send_auto_rate_request(st
 	struct ieee80211_hw *hw = common->priv->hw;
 	u8 band = hw->conf.chandef.chan->band;
 	u8 num_supported_rates = 0;
-	u8 rate_offset = 0;
+	u8 rate_table_offset, rate_offset = 0;
 	u32 rate_bitmap = common->bitrate_mask[band];
 
 	u16 *selected_rates, min_rate;
@@ -986,14 +1047,19 @@ static int rsi_send_auto_rate_request(st
 	if (common->channel_width == BW_40MHZ)
 		auto_rate->desc_word[7] |= cpu_to_le16(1);
 
-	if (band == IEEE80211_BAND_2GHZ)
-		min_rate = STD_RATE_01;
-	else
-		min_rate = STD_RATE_06;
+	if (band == IEEE80211_BAND_2GHZ) {
+		min_rate = RSI_RATE_1;
+		rate_table_offset = 0;
+	} else {
+		min_rate = RSI_RATE_6;
+		rate_table_offset = 4;
+	}
 
-	for (ii = 0, jj = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
+	for (ii = 0, jj = 0;
+	     ii < (ARRAY_SIZE(rsi_rates) - rate_table_offset); ii++) {
 		if (rate_bitmap & BIT(ii)) {
-			selected_rates[jj++] = (rsi_rates[ii].bitrate / 5);
+			selected_rates[jj++] =
+			(rsi_rates[ii + rate_table_offset].bitrate / 5);
 			rate_offset++;
 		}
 	}
@@ -1006,13 +1072,6 @@ static int rsi_send_auto_rate_request(st
 		rate_offset += ARRAY_SIZE(mcs);
 	}
 
-	if (rate_offset < (RSI_TBL_SZ / 2) - 1) {
-		for (ii = jj; ii < (RSI_TBL_SZ / 2); ii++) {
-			selected_rates[jj++] = min_rate;
-			rate_offset++;
-		}
-	}
-
 	sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL);
 
 	/* mapping the rates to RSI rates */
@@ -1028,25 +1087,25 @@ static int rsi_send_auto_rate_request(st
 
 	/* loading HT rates in the bottom half of the auto rate table */
 	if (common->vif_info[0].is_ht) {
-		if (common->vif_info[0].sgi)
-			auto_rate->supported_rates[rate_offset++] =
-				cpu_to_le16(RSI_RATE_MCS7_SG);
-
 		for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;
 		     ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {
-			if (common->vif_info[0].sgi)
+			if (common->vif_info[0].sgi ||
+			    conf_is_ht40(&common->priv->hw->conf))
 				auto_rate->supported_rates[ii++] =
 					cpu_to_le16(rsi_mcsrates[kk] | BIT(9));
 			auto_rate->supported_rates[ii] =
 				cpu_to_le16(rsi_mcsrates[kk--]);
 		}
 
-		for (; ii < RSI_TBL_SZ; ii++) {
+		for (; ii < (RSI_TBL_SZ - 1); ii++) {
 			auto_rate->supported_rates[ii] =
 				cpu_to_le16(rsi_mcsrates[0]);
 		}
 	}
 
+	for (; ii < RSI_TBL_SZ; ii++)
+		auto_rate->supported_rates[ii] = cpu_to_le16(min_rate);
+
 	auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);
 	auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);
 	auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);
@@ -1141,6 +1200,49 @@ static int rsi_eeprom_read(struct rsi_co
 }
 
 /**
+ * This function sends a frame to block/unblock
+ * data queues in the firmware
+ *
+ * @param common Pointer to the driver private structure.
+ * @param block event - block if true, unblock if false
+ * @return 0 on success, -1 on failure.
+ */
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
+{
+	struct rsi_mac_frame *mgmt_frame;
+	struct sk_buff *skb;
+
+	rsi_dbg(MGMT_TX_ZONE, "%s: Sending block/unblock frame\n", __func__);
+
+	skb = dev_alloc_skb(FRAME_DESC_SZ);
+	if (!skb) {
+		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	memset(skb->data, 0, FRAME_DESC_SZ);
+	mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+	mgmt_frame->desc_word[1] = cpu_to_le16(BLOCK_HW_QUEUE);
+
+	if (block_event == true) {
+		rsi_dbg(INFO_ZONE, "blocking the data qs\n");
+		mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
+	} else {
+		rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
+		mgmt_frame->desc_word[5] = cpu_to_le16(0xf);
+	}
+
+	skb_put(skb, FRAME_DESC_SZ);
+
+	return rsi_send_internal_mgmt_frame(common, skb);
+
+}
+
+
+/**
  * rsi_handle_ta_confirm_type() - This function handles the confirm frames.
  * @common: Pointer to the driver private structure.
  * @msg: Pointer to received packet.
@@ -1164,7 +1266,7 @@ static int rsi_handle_ta_confirm_type(st
 				common->fsm_state = FSM_EEPROM_READ_MAC_ADDR;
 			}
 		} else {
-			rsi_dbg(ERR_ZONE,
+			rsi_dbg(INFO_ZONE,
 				"%s: Received bootup params cfm in %d state\n",
 				 __func__, common->fsm_state);
 			return 0;
@@ -1227,7 +1329,7 @@ static int rsi_handle_ta_confirm_type(st
 					__func__);
 			}
 		} else {
-			rsi_dbg(ERR_ZONE,
+			rsi_dbg(INFO_ZONE,
 				"%s: Received radio caps cfm in %d state\n",
 				 __func__, common->fsm_state);
 			return 0;
@@ -1245,7 +1347,10 @@ static int rsi_handle_ta_confirm_type(st
 				return rsi_mac80211_attach(common);
 			}
 		} else {
-			goto out;
+			rsi_dbg(INFO_ZONE,
+				"%s: Received bbb_rf cfm in %d state\n",
+				 __func__, common->fsm_state);
+			return 0;
 		}
 		break;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_pkt.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_pkt.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_pkt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_pkt.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,6 +81,16 @@ int rsi_send_data_pkt(struct rsi_common
 		/* Send fixed rate */
 		frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
 		frame_desc[4] = cpu_to_le16(common->min_rate);
+
+		if (conf_is_ht40(&common->priv->hw->conf))
+			frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
+
+		if (common->vif_info[0].sgi) {
+			if (common->min_rate & 0x100) /* Only MCS rates */
+				frame_desc[4] |=
+					cpu_to_le16(ENABLE_SHORTGI_RATE);
+		}
+
 	}
 
 	frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
@@ -116,6 +126,8 @@ int rsi_send_mgmt_pkt(struct rsi_common
 	struct ieee80211_hdr *wh = NULL;
 	struct ieee80211_tx_info *info;
 	struct ieee80211_bss_conf *bss = NULL;
+	struct ieee80211_hw *hw = adapter->hw;
+	struct ieee80211_conf *conf = &hw->conf;
 	struct skb_info *tx_params;
 	int status = -E2BIG;
 	__le16 *msg = NULL;
@@ -175,6 +187,11 @@ int rsi_send_mgmt_pkt(struct rsi_common
 	else
 		msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
 
+	if (conf_is_ht40(conf)) {
+		msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
+		msg[5] = cpu_to_le16(0x6);
+	}
+
 	/* Indicate to firmware to give cfm */
 	if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
 		msg[1] |= cpu_to_le16(BIT(10));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_sdio.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_sdio.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_sdio.c	2014-08-07 04:56:09.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_sdio.c	2014-09-28 21:38:16.000000000 -0400
@@ -820,9 +820,11 @@ static struct sdio_driver rsi_driver = {
  */
 static int rsi_module_init(void)
 {
-	sdio_register_driver(&rsi_driver);
+	int ret;
+
+	ret = sdio_register_driver(&rsi_driver);
 	rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
-	return 0;
+	return ret;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c	2014-08-07 04:56:07.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c	2014-09-28 21:38:14.000000000 -0400
@@ -401,14 +401,16 @@ void rsi_interrupt_handler(struct rsi_hw
 			case BUFFER_AVAILABLE:
 				dev->rx_info.watch_bufferfull_count = 0;
 				dev->rx_info.buffer_full = false;
+				dev->rx_info.semi_buffer_full = false;
 				dev->rx_info.mgmt_buffer_full = false;
 				rsi_sdio_ack_intr(common->priv,
 						  (1 << PKT_BUFF_AVAILABLE));
-				rsi_set_event((&common->tx_thread.event));
+				rsi_set_event(&common->tx_thread.event);
+
 				rsi_dbg(ISR_ZONE,
-					"%s: ==> BUFFER_AVILABLE <==\n",
+					"%s: ==> BUFFER_AVAILABLE <==\n",
 					__func__);
-				dev->rx_info.buf_avilable_counter++;
+				dev->rx_info.buf_available_counter++;
 				break;
 
 			case FIRMWARE_ASSERT_IND:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_91x_usb.c	2014-08-07 04:56:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_91x_usb.c	2014-09-28 21:38:19.000000000 -0400
@@ -25,7 +25,7 @@
  * @len: Length to be written.
  * @endpoint: Type of endpoint.
  *
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
  */
 static int rsi_usb_card_write(struct rsi_hw *adapter,
 			      void *buf,
@@ -60,7 +60,7 @@ static int rsi_usb_card_write(struct rsi
  * @data: Pointer to the data that has to be written.
  * @count: Number of multiple bytes to be written.
  *
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_write_multiple(struct rsi_hw *adapter,
 			      u8 endpoint,
@@ -147,7 +147,7 @@ static int rsi_find_bulk_in_and_out_endp
  * @value: Value to be read.
  * @len: length of data to be read.
  *
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
  */
 static int rsi_usb_reg_read(struct usb_device *usbdev,
 			    u32 reg,
@@ -189,7 +189,7 @@ static int rsi_usb_reg_read(struct usb_d
  * @value: Value to write.
  * @len: Length of data to be written.
  *
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
  */
 static int rsi_usb_reg_write(struct usb_device *usbdev,
 			     u32 reg,
@@ -249,7 +249,7 @@ static void rsi_rx_done_handler(struct u
  * rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
  * @adapter: Pointer to the adapter structure.
  *
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_rx_urb_submit(struct rsi_hw *adapter)
 {
@@ -281,7 +281,7 @@ static int rsi_rx_urb_submit(struct rsi_
  * @data: Pointer to the data that has to be written.
  * @count: Number of multiple bytes to be written on to the registers.
  *
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
  */
 int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
 				    u32 addr,
@@ -331,7 +331,7 @@ int rsi_usb_write_register_multiple(stru
  * @pkt: Pointer to the data to be written on to the card.
  * @len: Length of the data to be written on to the card.
  *
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
 				       u8 *pkt,
@@ -359,6 +359,7 @@ static void rsi_deinit_usb_interface(str
 	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
 	rsi_kill_thread(&dev->rx_thread);
+	usb_free_urb(dev->rx_usb_urb[0]);
 	kfree(adapter->priv->rx_data_pkt);
 	kfree(dev->tx_buffer);
 }
@@ -368,7 +369,7 @@ static void rsi_deinit_usb_interface(str
  * @adapter: Pointer to the adapter structure.
  * @pfunction: Pointer to USB interface structure.
  *
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_init_usb_interface(struct rsi_hw *adapter,
 				  struct usb_interface *pfunction)
@@ -397,8 +398,16 @@ static int rsi_init_usb_interface(struct
 		return -ENOMEM;
 	}
 
-	rsi_dev->tx_buffer = kmalloc(2048, GFP_ATOMIC);
+	rsi_dev->tx_buffer = kmalloc(2048, GFP_KERNEL);
+	if (!rsi_dev->tx_buffer) {
+		status = -ENOMEM;
+		goto fail_tx;
+	}
 	rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rsi_dev->rx_usb_urb[0]) {
+		status = -ENOMEM;
+		goto fail_rx;
+	}
 	rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
 	rsi_dev->tx_blk_size = 252;
 
@@ -413,7 +422,7 @@ static int rsi_init_usb_interface(struct
 				    rsi_usb_rx_thread, "RX-Thread");
 	if (status) {
 		rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
-		goto fail;
+		goto fail_thread;
 	}
 
 #ifdef CONFIG_RSI_DEBUGFS
@@ -424,8 +433,11 @@ static int rsi_init_usb_interface(struct
 	rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
 	return 0;
 
-fail:
+fail_thread:
+	usb_free_urb(rsi_dev->rx_usb_urb[0]);
+fail_rx:
 	kfree(rsi_dev->tx_buffer);
+fail_tx:
 	kfree(common->rx_data_pkt);
 	return status;
 }
@@ -437,7 +449,7 @@ fail:
  * @pfunction: Pointer to the USB interface structure.
  * @id: Pointer to the usb_device_id structure.
  *
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_probe(struct usb_interface *pfunction,
 		     const struct usb_device_id *id)
@@ -445,6 +457,7 @@ static int rsi_probe(struct usb_interfac
 	struct rsi_hw *adapter;
 	struct rsi_91x_usbdev *dev;
 	u16 fw_status;
+	int status;
 
 	rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
 
@@ -452,10 +465,11 @@ static int rsi_probe(struct usb_interfac
 	if (!adapter) {
 		rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
 			__func__);
-		return 1;
+		return -ENOMEM;
 	}
 
-	if (rsi_init_usb_interface(adapter, pfunction)) {
+	status = rsi_init_usb_interface(adapter, pfunction);
+	if (status) {
 		rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",
 			__func__);
 		goto err;
@@ -465,26 +479,30 @@ static int rsi_probe(struct usb_interfac
 
 	dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
-	if (rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2) < 0)
+	status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
+	if (status)
 		goto err1;
 	else
 		fw_status &= 1;
 
 	if (!fw_status) {
-		if (rsi_usb_device_init(adapter->priv)) {
+		status = rsi_usb_device_init(adapter->priv);
+		if (status) {
 			rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
 				__func__);
 			goto err1;
 		}
 
-		if (rsi_usb_reg_write(dev->usbdev,
-				      USB_INTERNAL_REG_1,
-				      RSI_USB_READY_MAGIC_NUM, 1) < 0)
+		status = rsi_usb_reg_write(dev->usbdev,
+					   USB_INTERNAL_REG_1,
+					   RSI_USB_READY_MAGIC_NUM, 1);
+		if (status)
 			goto err1;
 		rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
 	}
 
-	if (rsi_rx_urb_submit(adapter))
+	status = rsi_rx_urb_submit(adapter);
+	if (status)
 		goto err1;
 
 	return 0;
@@ -493,7 +511,7 @@ err1:
 err:
 	rsi_91x_deinit(adapter);
 	rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
-	return 1;
+	return status;
 }
 
 /**
@@ -550,33 +568,7 @@ static struct usb_driver rsi_driver = {
 #endif
 };
 
-/**
- * rsi_module_init() - This function registers the client driver.
- * @void: Void.
- *
- * Return: 0 on success.
- */
-static int rsi_module_init(void)
-{
-	usb_register(&rsi_driver);
-	rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
-	return 0;
-}
-
-/**
- * rsi_module_exit() - This function unregisters the client driver.
- * @void: Void.
- *
- * Return: None.
- */
-static void rsi_module_exit(void)
-{
-	usb_deregister(&rsi_driver);
-	rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);
-}
-
-module_init(rsi_module_init);
-module_exit(rsi_module_exit);
+module_usb_driver(rsi_driver);
 
 MODULE_AUTHOR("Redpine Signals Inc");
 MODULE_DESCRIPTION("Common USB layer for RSI drivers");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_main.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_main.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_main.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_main.h	2014-09-28 17:29:07.000000000 -0400
@@ -115,6 +115,7 @@ struct wmm_qinfo {
 	s32 weight;
 	s32 wme_params;
 	s32 pkt_contended;
+	s32 txop;
 };
 
 struct transmit_q_stats {
@@ -141,6 +142,12 @@ struct rsi_thread {
 	atomic_t thread_done;
 };
 
+struct cqm_info {
+	s8 last_cqm_event_rssi;
+	int rssi_thold;
+	u32 rssi_hyst;
+};
+
 struct rsi_hw;
 
 struct rsi_common {
@@ -192,6 +199,11 @@ struct rsi_common {
 	u8 selected_qnum;
 	u32 pkt_cnt;
 	u8 min_weight;
+
+	/* bgscan related */
+	struct cqm_info cqm_info;
+
+	bool hw_data_qs_blocked;
 };
 
 struct rsi_hw {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_mgmt.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_mgmt.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_mgmt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_mgmt.h	2014-09-28 17:29:07.000000000 -0400
@@ -69,6 +69,7 @@
 
 #define RSI_LMAC_CLOCK_80MHZ            0x1
 #define RSI_ENABLE_40MHZ                (0x1 << 3)
+#define ENABLE_SHORTGI_RATE		BIT(9)
 
 #define RX_BA_INDICATION                1
 #define RSI_TBL_SZ                      40
@@ -123,6 +124,20 @@
 #define BW_20MHZ                        0
 #define BW_40MHZ                        1
 
+#define EP_2GHZ_20MHZ			0
+#define EP_2GHZ_40MHZ			1
+#define EP_5GHZ_20MHZ			2
+#define EP_5GHZ_40MHZ			3
+
+#define SIFS_TX_11N_VALUE		580
+#define SIFS_TX_11B_VALUE		346
+#define SHORT_SLOT_VALUE		360
+#define LONG_SLOT_VALUE			640
+#define OFDM_ACK_TOUT_VALUE		2720
+#define CCK_ACK_TOUT_VALUE		9440
+#define LONG_PREAMBLE			0x0000
+#define SHORT_PREAMBLE			0x0001
+
 #define RSI_SUPP_FILTERS	(FIF_ALLMULTI | FIF_PROBE_REQ |\
 				 FIF_BCN_PRBRESP_PROMISC)
 enum opmode {
@@ -153,7 +168,7 @@ enum cmd_frame_type {
 	SCAN_REQUEST,
 	TSF_UPDATE,
 	PEER_NOTIFY,
-	BLOCK_UNBLOCK,
+	BLOCK_HW_QUEUE,
 	SET_KEY_REQ,
 	AUTO_RATE_IND,
 	BOOTUP_PARAMS_REQUEST,
@@ -238,6 +253,12 @@ struct rsi_radio_caps {
 	u8 num_11n_rates;
 	u8 num_11ac_rates;
 	__le16 gcpd_per_rate[20];
+	__le16 sifs_tx_11n;
+	__le16 sifs_tx_11b;
+	__le16 slot_rx_11n;
+	__le16 ofdm_ack_tout;
+	__le16 cck_ack_tout;
+	__le16 preamble_type;
 } __packed;
 
 static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
@@ -272,6 +293,7 @@ int rsi_send_aggregation_params_frame(st
 int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
 		     u8 key_type, u8 key_id, u32 cipher);
 int rsi_set_channel(struct rsi_common *common, u16 chno);
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
 void rsi_inform_bss_status(struct rsi_common *common, u8 status,
 			   const u8 *bssid, u8 qos_enable, u16 aid);
 void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
@@ -283,4 +305,5 @@ void rsi_core_qos_processor(struct rsi_c
 void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
 int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_band_check(struct rsi_common *common);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_sdio.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_sdio.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rsi/rsi_sdio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rsi/rsi_sdio.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@
 
 enum sdio_interrupt_type {
 	BUFFER_FULL         = 0x0,
-	BUFFER_AVAILABLE    = 0x1,
+	BUFFER_AVAILABLE    = 0x2,
 	FIRMWARE_ASSERT_IND = 0x3,
 	MSDU_PACKET_PENDING = 0x4,
 	UNKNOWN_INT         = 0XE
@@ -42,7 +42,7 @@ enum sdio_interrupt_type {
 #define PKT_MGMT_BUFF_FULL                      2
 #define MSDU_PKT_PENDING                        3
 /* Interrupt Bit Related Macros */
-#define PKT_BUFF_AVAILABLE                      0
+#define PKT_BUFF_AVAILABLE                      1
 #define FW_ASSERT_IND                           2
 
 #define RSI_DEVICE_BUFFER_STATUS_REGISTER       0xf3
@@ -84,7 +84,7 @@ enum sdio_interrupt_type {
 #define TA_HOLD_THREAD_VALUE         cpu_to_le32(0xF)
 #define TA_RELEASE_THREAD_VALUE      cpu_to_le32(0xF)
 #define TA_BASE_ADDR                 0x2200
-#define MISC_CFG_BASE_ADDR           0x4150
+#define MISC_CFG_BASE_ADDR           0x4105
 
 struct receive_info {
 	bool buffer_full;
@@ -98,7 +98,7 @@ struct receive_info {
 	u32 total_sdio_msdu_pending_intr;
 	u32 total_sdio_unknown_intr;
 	u32 buf_full_counter;
-	u32 buf_avilable_counter;
+	u32 buf_available_counter;
 };
 
 struct rsi_91x_sdiodev {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2400pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2400pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -1821,7 +1821,7 @@ static const struct rt2x00_ops rt2400pci
 /*
  * RT2400pci module information.
  */
-static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
+static const struct pci_device_id rt2400pci_device_table[] = {
 	{ PCI_DEVICE(0x1814, 0x0101) },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2500pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2500pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -2120,7 +2120,7 @@ static const struct rt2x00_ops rt2500pci
 /*
  * RT2500pci module information.
  */
-static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
+static const struct pci_device_id rt2500pci_device_table[] = {
 	{ PCI_DEVICE(0x1814, 0x0201) },
 	{ 0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800lib.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offse
 	return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
 }
 
+static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue = rt2x00dev->bcn;
+	struct queue_entry *entry;
+	int i, bcn_num = 0;
+	u64 off, reg = 0;
+	u32 bssid_dw1;
+
+	/*
+	 * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
+	 */
+	for (i = 0; i < queue->limit; i++) {
+		entry = &queue->entries[i];
+		if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
+			continue;
+		off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
+		reg |= off << (8 * bcn_num);
+		bcn_num++;
+	}
+
+	WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+
+	rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
+	rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
+
+	/*
+	 * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
+	 */
+	rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+	rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
+			   bcn_num > 0 ? bcn_num - 1 : 0);
+	rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
+}
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
 
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
+	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+	/*
+	 * Change global beacons settings.
+	 */
+	rt2800_update_beacons_setup(rt2x00dev);
 
 	/*
 	 * Restore beaconing state.
@@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
 	 * Clear beacon.
 	 */
 	rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
+	__clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
 
 	/*
+	 * Change global beacons settings.
+	 */
+	rt2800_update_beacons_setup(rt2x00dev);
+	/*
 	 * Restore beaconing state.
 	 */
 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
@@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_de
 		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
 			reg = le32_to_cpu(conf->bssid[1]);
 			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
-			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
 			conf->bssid[1] = cpu_to_le32(reg);
 		}
 
@@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct
 	if (ret)
 		return ret;
 
-	rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
-			   rt2800_get_beacon_offset(rt2x00dev, 0));
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
-			   rt2800_get_beacon_offset(rt2x00dev, 1));
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
-			   rt2800_get_beacon_offset(rt2x00dev, 2));
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
-			   rt2800_get_beacon_offset(rt2x00dev, 3));
-	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
-
-	rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
-			   rt2800_get_beacon_offset(rt2x00dev, 4));
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
-			   rt2800_get_beacon_offset(rt2x00dev, 5));
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
-			   rt2800_get_beacon_offset(rt2x00dev, 6));
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
-			   rt2800_get_beacon_offset(rt2x00dev, 7));
-	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
-
 	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
 	rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2014-08-07 04:56:27.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2014-09-28 21:38:38.000000000 -0400
@@ -399,7 +399,7 @@ static const struct rt2x00_ops rt2800pci
 /*
  * RT2800pci module information.
  */
-static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
+static const struct pci_device_id rt2800pci_device_table[] = {
 	{ PCI_DEVICE(0x1814, 0x0601) },
 	{ PCI_DEVICE(0x1814, 0x0681) },
 	{ PCI_DEVICE(0x1814, 0x0701) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800usb.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2014-08-07 04:56:32.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2014-09-28 21:38:43.000000000 -0400
@@ -1284,6 +1284,8 @@ static struct usb_device_id rt2800usb_de
 	/* Arcadyan */
 	{ USB_DEVICE(0x043e, 0x7a12) },
 	{ USB_DEVICE(0x043e, 0x7a32) },
+	/* ASUS */
+	{ USB_DEVICE(0x0b05, 0x17e8) },
 	/* Azurewave */
 	{ USB_DEVICE(0x13d3, 0x3329) },
 	{ USB_DEVICE(0x13d3, 0x3365) },
@@ -1320,6 +1322,7 @@ static struct usb_device_id rt2800usb_de
 	{ USB_DEVICE(0x057c, 0x8501) },
 	/* Buffalo */
 	{ USB_DEVICE(0x0411, 0x0241) },
+	{ USB_DEVICE(0x0411, 0x0253) },
 	/* D-Link */
 	{ USB_DEVICE(0x2001, 0x3c1a) },
 	{ USB_DEVICE(0x2001, 0x3c21) },
@@ -1410,6 +1413,7 @@ static struct usb_device_id rt2800usb_de
 	{ USB_DEVICE(0x0df6, 0x0053) },
 	{ USB_DEVICE(0x0df6, 0x0069) },
 	{ USB_DEVICE(0x0df6, 0x006f) },
+	{ USB_DEVICE(0x0df6, 0x0078) },
 	/* SMC */
 	{ USB_DEVICE(0x083a, 0xa512) },
 	{ USB_DEVICE(0x083a, 0xc522) },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_ite
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return;
 
-	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
+	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
+		mutex_lock(&intf->beacon_skb_mutex);
 		rt2x00queue_update_beacon(rt2x00dev, vif);
+		mutex_unlock(&intf->beacon_skb_mutex);
+	}
 }
 
 static void rt2x00lib_intf_scheduled(struct work_struct *work)
@@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(
 	 * never be called for USB devices.
 	 */
 	WARN_ON(rt2x00_is_usb(rt2x00dev));
-	rt2x00queue_update_beacon_locked(rt2x00dev, vif);
+	rt2x00queue_update_beacon(rt2x00dev, vif);
 }
 
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -1470,8 +1473,7 @@ void rt2x00lib_remove_dev(struct rt2x00_
 	/*
 	 * Free the driver data.
 	 */
-	if (rt2x00dev->drv_data)
-		kfree(rt2x00dev->drv_data);
+	kfree(rt2x00dev->drv_data);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2014-09-28 17:29:07.000000000 -0400
@@ -626,25 +626,24 @@ void rt2x00mac_bss_info_changed(struct i
 	 * Start/stop beaconing.
 	 */
 	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		mutex_lock(&intf->beacon_skb_mutex);
 		if (!bss_conf->enable_beacon && intf->enable_beacon) {
 			rt2x00dev->intf_beaconing--;
 			intf->enable_beacon = false;
-			/*
-			 * Clear beacon in the H/W for this vif. This is needed
-			 * to disable beaconing on this particular interface
-			 * and keep it running on other interfaces.
-			 */
-			rt2x00queue_clear_beacon(rt2x00dev, vif);
 
 			if (rt2x00dev->intf_beaconing == 0) {
 				/*
 				 * Last beaconing interface disabled
 				 * -> stop beacon queue.
 				 */
-				mutex_lock(&intf->beacon_skb_mutex);
 				rt2x00queue_stop_queue(rt2x00dev->bcn);
-				mutex_unlock(&intf->beacon_skb_mutex);
 			}
+			/*
+			 * Clear beacon in the H/W for this vif. This is needed
+			 * to disable beaconing on this particular interface
+			 * and keep it running on other interfaces.
+			 */
+			rt2x00queue_clear_beacon(rt2x00dev, vif);
 		} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
 			rt2x00dev->intf_beaconing++;
 			intf->enable_beacon = true;
@@ -660,11 +659,10 @@ void rt2x00mac_bss_info_changed(struct i
 				 * First beaconing interface enabled
 				 * -> start beacon queue.
 				 */
-				mutex_lock(&intf->beacon_skb_mutex);
 				rt2x00queue_start_queue(rt2x00dev->bcn);
-				mutex_unlock(&intf->beacon_skb_mutex);
 			}
 		}
+		mutex_unlock(&intf->beacon_skb_mutex);
 	}
 
 	/*
@@ -801,6 +799,8 @@ int rt2x00mac_set_antenna(struct ieee802
 
 	setup.tx = tx_ant;
 	setup.rx = rx_ant;
+	setup.rx_chain_num = 0;
+	setup.tx_chain_num = 0;
 
 	rt2x00lib_config_antenna(rt2x00dev, setup);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00mmio.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00mmio.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00mmio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00mmio.c	2014-09-28 17:29:07.000000000 -0400
@@ -119,14 +119,12 @@ static int rt2x00mmio_alloc_queue_dma(st
 	/*
 	 * Allocate DMA memory for descriptor and buffer.
 	 */
-	addr = dma_alloc_coherent(rt2x00dev->dev,
-				  queue->limit * queue->desc_size,
-				  &dma, GFP_KERNEL);
+	addr = dma_zalloc_coherent(rt2x00dev->dev,
+				   queue->limit * queue->desc_size, &dma,
+				   GFP_KERNEL);
 	if (!addr)
 		return -ENOMEM;
 
-	memset(addr, 0, queue->limit * queue->desc_size);
-
 	/*
 	 * Initialize all queue entries to contain valid addresses.
 	 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2014-09-28 17:29:07.000000000 -0400
@@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x
 	if (unlikely(!intf->beacon))
 		return -ENOBUFS;
 
-	mutex_lock(&intf->beacon_skb_mutex);
-
 	/*
 	 * Clean up the beacon skb.
 	 */
@@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x
 	if (rt2x00dev->ops->lib->clear_beacon)
 		rt2x00dev->ops->lib->clear_beacon(intf->beacon);
 
-	mutex_unlock(&intf->beacon_skb_mutex);
-
 	return 0;
 }
 
-int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
-				     struct ieee80211_vif *vif)
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+			      struct ieee80211_vif *vif)
 {
 	struct rt2x00_intf *intf = vif_to_intf(vif);
 	struct skb_frame_desc *skbdesc;
@@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str
 
 }
 
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif)
-{
-	struct rt2x00_intf *intf = vif_to_intf(vif);
-	int ret;
-
-	mutex_lock(&intf->beacon_skb_mutex);
-	ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
-	mutex_unlock(&intf->beacon_skb_mutex);
-
-	return ret;
-}
-
 bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2014-09-28 17:29:07.000000000 -0400
@@ -353,6 +353,7 @@ struct txentry_desc {
  */
 enum queue_entry_flags {
 	ENTRY_BCN_ASSIGNED,
+	ENTRY_BCN_ENABLED,
 	ENTRY_OWNER_DEVICE_DATA,
 	ENTRY_DATA_PENDING,
 	ENTRY_DATA_IO_FAILED,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt61pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt61pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2014-08-07 04:56:18.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2014-09-28 21:38:26.000000000 -0400
@@ -3075,7 +3075,7 @@ static const struct rt2x00_ops rt61pci_o
 /*
  * RT61pci module information.
  */
-static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
+static const struct pci_device_id rt61pci_device_table[] = {
 	/* RT2561s */
 	{ PCI_DEVICE(0x1814, 0x0301) },
 	/* RT2561 v2 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
  *
  * based also on:
  *  - portions of rtl8187se Linux staging driver, Copyright Realtek corp.
+ *    (available in drivers/staging/rtl8187se directory of Linux 3.14)
  *  - other GPL, unpublished (until now), Linux driver code,
  *    Copyright Larry Finger <Larry.Finger@lwfinger.net>
  *
@@ -63,7 +64,7 @@ MODULE_AUTHOR("Andrea Merello <andrea.me
 MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver");
 MODULE_LICENSE("GPL");
 
-static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = {
+static const struct pci_device_id rtl8180_table[] = {
 
 	/* rtl8187se */
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) },
@@ -209,7 +210,7 @@ static void rtl8180_handle_rx(struct iee
 	struct rtl8180_priv *priv = dev->priv;
 	struct rtl818x_rx_cmd_desc *cmd_desc;
 	unsigned int count = 32;
-	u8 signal, agc, sq;
+	u8 agc, sq, signal = 1;
 	dma_addr_t mapping;
 
 	while (count--) {
@@ -222,12 +223,20 @@ static void rtl8180_handle_rx(struct iee
 			struct rtl8187se_rx_desc *desc = entry;
 
 			flags = le32_to_cpu(desc->flags);
+			/* if ownership flag is set, then we can trust the
+			 * HW has written other fields. We must not trust
+			 * other descriptor data read before we checked (read)
+			 * the ownership flag
+			 */
+			rmb();
 			flags2 = le32_to_cpu(desc->flags2);
 			tsft = le64_to_cpu(desc->tsft);
 		} else {
 			struct rtl8180_rx_desc *desc = entry;
 
 			flags = le32_to_cpu(desc->flags);
+			/* same as above */
+			rmb();
 			flags2 = le32_to_cpu(desc->flags2);
 			tsft = le64_to_cpu(desc->tsft);
 		}
@@ -266,18 +275,21 @@ static void rtl8180_handle_rx(struct iee
 			rx_status.rate_idx = (flags >> 20) & 0xF;
 			agc = (flags2 >> 17) & 0x7F;
 
-			if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) {
+			switch (priv->chip_family) {
+			case RTL818X_CHIP_FAMILY_RTL8185:
 				if (rx_status.rate_idx > 3)
-					signal = 90 - clamp_t(u8, agc, 25, 90);
+					signal = -clamp_t(u8, agc, 25, 90) - 9;
 				else
-					signal = 95 - clamp_t(u8, agc, 30, 95);
-			} else if (priv->chip_family ==
-				   RTL818X_CHIP_FAMILY_RTL8180) {
+					signal = -clamp_t(u8, agc, 30, 95);
+				break;
+			case RTL818X_CHIP_FAMILY_RTL8180:
 				sq = flags2 & 0xff;
 				signal = priv->rf->calc_rssi(agc, sq);
-			} else {
+				break;
+			case RTL818X_CHIP_FAMILY_RTL8187SE:
 				/* TODO: rtl8187se rssi */
 				signal = 10;
+				break;
 			}
 			rx_status.signal = signal;
 			rx_status.freq = dev->conf.chandef.chan->center_freq;
@@ -336,7 +348,6 @@ static void rtl8180_handle_tx(struct iee
 			info->flags |= IEEE80211_TX_STAT_ACK;
 
 		info->status.rates[0].count = (flags & 0xFF) + 1;
-		info->status.rates[1].idx = -1;
 
 		ieee80211_tx_status_irqsafe(dev, skb);
 		if (ring->entries - skb_queue_len(&ring->queue) == 2)
@@ -528,9 +539,7 @@ static void rtl8180_tx(struct ieee80211_
 	entry->plcp_len = cpu_to_le16(plcp_len);
 	entry->tx_buf = cpu_to_le32(mapping);
 
-	entry->flags2 = info->control.rates[1].idx >= 0 ?
-		ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
-	entry->retry_limit = info->control.rates[0].count;
+	entry->retry_limit = info->control.rates[0].count - 1;
 
 	/* We must be sure that tx_flags is written last because the HW
 	 * looks at it to check if the rest of data is valid or not
@@ -852,7 +861,7 @@ static int rtl8180_init_hw(struct ieee80
 
 	if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) {
 		rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
-		rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+		rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0);
 	} else {
 		rtl818x_iowrite8(priv, &priv->map->SECURITY, 0);
 
@@ -868,6 +877,16 @@ static int rtl8180_init_hw(struct ieee80
 		reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
 		rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2));
 		rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+		/* fix eccessive IFS after CTS-to-self */
+		if (priv->map_pio) {
+			u8 reg;
+
+			reg = rtl818x_ioread8(priv, &priv->map->PGSELECT);
+			rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1);
+			rtl818x_iowrite8(priv, REG_ADDR1(0xff), 0x35);
+			rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		} else
+			rtl818x_iowrite8(priv, REG_ADDR1(0x1ff), 0x35);
 	}
 
 	if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
@@ -953,16 +972,13 @@ static int rtl8180_init_rx_ring(struct i
 	else
 		priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc);
 
-	priv->rx_ring = pci_alloc_consistent(priv->pdev,
-					     priv->rx_ring_sz * 32,
-					     &priv->rx_ring_dma);
-
+	priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32,
+					      &priv->rx_ring_dma);
 	if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
 		wiphy_err(dev->wiphy, "Cannot allocate RX ring\n");
 		return -ENOMEM;
 	}
 
-	memset(priv->rx_ring, 0, priv->rx_ring_sz * 32);
 	priv->rx_idx = 0;
 
 	for (i = 0; i < 32; i++) {
@@ -1021,14 +1037,14 @@ static int rtl8180_init_tx_ring(struct i
 	dma_addr_t dma;
 	int i;
 
-	ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+	ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries,
+				     &dma);
 	if (!ring || (unsigned long)ring & 0xFF) {
 		wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n",
 			  prio);
 		return -ENOMEM;
 	}
 
-	memset(ring, 0, sizeof(*ring)*entries);
 	priv->tx_ring[prio].desc = ring;
 	priv->tx_ring[prio].dma = dma;
 	priv->tx_ring[prio].idx = 0;
@@ -1450,9 +1466,10 @@ static void rtl8180_bss_info_changed(str
 	vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
 
 	if (changed & BSS_CHANGED_BSSID) {
-		for (i = 0; i < ETH_ALEN; i++)
-			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
-					 info->bssid[i]);
+		rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->BSSID[0],
+				  le16_to_cpu(*(__le16 *)info->bssid));
+		rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->BSSID[2],
+				  le32_to_cpu(*(__le32 *)(info->bssid + 2)));
 
 		if (is_valid_ether_addr(info->bssid)) {
 			if (vif->type == NL80211_IFTYPE_ADHOC)
@@ -1723,17 +1740,20 @@ static int rtl8180_probe(struct pci_dev
 	priv = dev->priv;
 	priv->pdev = pdev;
 
-	dev->max_rates = 2;
+	dev->max_rates = 1;
 	SET_IEEE80211_DEV(dev, &pdev->dev);
 	pci_set_drvdata(pdev, dev);
 
+	priv->map_pio = false;
 	priv->map = pci_iomap(pdev, 1, mem_len);
-	if (!priv->map)
+	if (!priv->map) {
 		priv->map = pci_iomap(pdev, 0, io_len);
+		priv->map_pio = true;
+	}
 
 	if (!priv->map) {
-		printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n",
-		       pci_name(pdev));
+		dev_err(&pdev->dev, "Cannot map device memory/PIO\n");
+		err = -ENOMEM;
 		goto err_free_dev;
 	}
 
@@ -1751,8 +1771,7 @@ static int rtl8180_probe(struct pci_dev
 	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
 
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		     IEEE80211_HW_RX_INCLUDES_FCS |
-		     IEEE80211_HW_SIGNAL_UNSPEC;
+		IEEE80211_HW_RX_INCLUDES_FCS;
 	dev->vif_data_size = sizeof(struct rtl8180_vif);
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 					BIT(NL80211_IFTYPE_ADHOC);
@@ -1783,12 +1802,19 @@ static int rtl8180_probe(struct pci_dev
 
 	case RTL818X_TX_CONF_RTL8187SE:
 		chip_name = "RTL8187SE";
+		if (priv->map_pio) {
+			dev_err(&pdev->dev,
+				"MMIO failed. PIO not supported on RTL8187SE\n");
+			err = -ENOMEM;
+			goto err_iounmap;
+		}
 		priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE;
 		break;
 
 	default:
 		printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n",
 		       pci_name(pdev), reg >> 25);
+		err = -ENODEV;
 		goto err_iounmap;
 	}
 
@@ -1809,6 +1835,11 @@ static int rtl8180_probe(struct pci_dev
 		pci_try_set_mwi(pdev);
 	}
 
+	if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185)
+		dev->flags |= IEEE80211_HW_SIGNAL_DBM;
+	else
+		dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
+
 	rtl8180_eeprom_read(priv);
 
 	switch (priv->rf_type) {
@@ -1834,12 +1865,14 @@ static int rtl8180_probe(struct pci_dev
 	default:
 		printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n",
 		       pci_name(pdev), priv->rf_type);
+		err = -ENODEV;
 		goto err_iounmap;
 	}
 
 	if (!priv->rf) {
 		printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",
 		       pci_name(pdev), rf_name);
+		err = -ENODEV;
 		goto err_iounmap;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h	2014-09-28 17:29:07.000000000 -0400
@@ -107,6 +107,7 @@ struct rtl8180_priv {
 	struct ieee80211_vif *vif;
 
 	/* rtl8180 driver specific */
+	bool map_pio;
 	spinlock_t lock;
 	void *rx_ring;
 	u8 rx_ring_sz;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,7 @@ static bool halbtc_legacy(struct rtl_pri
 
 	bool is_legacy = false;
 
-	if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_B))
+	if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_G))
 		is_legacy = true;
 
 	return is_legacy;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,7 @@ extern u32 btc_dbg_type[];
 
 
 #define	CL_SPRINTF	snprintf
-#define	CL_PRINTF	printk
+#define	CL_PRINTF(buf)	printk("%s", buf)
 
 #define	BTC_PRINT(dbgtype, dbgflag, printstr, ...)		\
 	do {							\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/core.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/core.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/core.c	2014-08-07 04:56:32.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/core.c	2014-09-28 21:38:43.000000000 -0400
@@ -1064,7 +1064,6 @@ static int rtl_op_ampdu_action(struct ie
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
 		return rtl_tx_agg_start(hw, sta, tid, ssn);
-		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/pci.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/pci.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -1092,16 +1092,14 @@ static int _rtl_pci_init_tx_ring(struct
 	u32 nextdescaddress;
 	int i;
 
-	ring = pci_alloc_consistent(rtlpci->pdev,
-				    sizeof(*ring) * entries, &dma);
-
+	ring = pci_zalloc_consistent(rtlpci->pdev, sizeof(*ring) * entries,
+				     &dma);
 	if (!ring || (unsigned long)ring & 0xFF) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "Cannot allocate TX ring (prio = %d)\n", prio);
 		return -ENOMEM;
 	}
 
-	memset(ring, 0, sizeof(*ring) * entries);
 	rtlpci->tx_ring[prio].desc = ring;
 	rtlpci->tx_ring[prio].dma = dma;
 	rtlpci->tx_ring[prio].idx = 0;
@@ -1139,10 +1137,9 @@ static int _rtl_pci_init_rx_ring(struct
 	for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE;
 	     rx_queue_idx++) {
 		rtlpci->rx_ring[rx_queue_idx].desc =
-		    pci_alloc_consistent(rtlpci->pdev,
-					 sizeof(*rtlpci->rx_ring[rx_queue_idx].
-						desc) * rtlpci->rxringcount,
-					 &rtlpci->rx_ring[rx_queue_idx].dma);
+			pci_zalloc_consistent(rtlpci->pdev,
+					      sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) * rtlpci->rxringcount,
+					      &rtlpci->rx_ring[rx_queue_idx].dma);
 
 		if (!rtlpci->rx_ring[rx_queue_idx].desc ||
 		    (unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) {
@@ -1151,10 +1148,6 @@ static int _rtl_pci_init_rx_ring(struct
 			return -ENOMEM;
 		}
 
-		memset(rtlpci->rx_ring[rx_queue_idx].desc, 0,
-		       sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) *
-		       rtlpci->rxringcount);
-
 		rtlpci->rx_ring[rx_queue_idx].idx = 0;
 
 		/* If amsdu_8k is disabled, set buffersize to 4096. This
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1231,7 +1231,7 @@ static int _rtl88ee_set_media_status(str
 
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0xfc) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,6 @@ bool rtl88_hal_pwrseqcmdparsing(struct r
 				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
 				return true;
-				break;
 			default:
 				RT_ASSERT(false,
 					  "rtl88_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -411,6 +411,7 @@
 #define	MSR_ADHOC				0x01
 #define	MSR_INFRA				0x02
 #define	MSR_AP					0x03
+#define	MSR_MASK				0x03
 
 #define	RRSR_RSC_OFFSET				21
 #define	RRSR_SHORT_OFFSET			23
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c	2014-08-07 04:56:34.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c	2014-09-28 21:38:45.000000000 -0400
@@ -364,7 +364,7 @@ static struct rtl_hal_cfg rtl88ee_hal_cf
 	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = {
+static const struct pci_device_id rtl88ee_pci_ids[] = {
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)},
 	{},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1200,13 +1200,12 @@ static int _rtl92ce_set_media_status(str
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "Network type %d not supported!\n", type);
 		return 1;
-		break;
 
 	}
 
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0xfc) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -375,6 +375,7 @@
 #define	MSR_ADHOC				0x01
 #define	MSR_INFRA				0x02
 #define	MSR_AP					0x03
+#define	MSR_MASK				0x03
 
 #define	RRSR_RSC_OFFSET				21
 #define	RRSR_SHORT_OFFSET			23
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2014-08-07 04:56:42.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2014-09-28 21:38:55.000000000 -0400
@@ -344,7 +344,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cf
 	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
+static const struct pci_device_id rtl92ce_pci_ids[] = {
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)},
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)},
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1360,7 +1360,7 @@ static int _rtl92cu_set_media_status(str
 	}
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0xfc) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2014-08-07 04:56:44.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2014-09-28 21:38:57.000000000 -0400
@@ -314,6 +314,7 @@ static struct usb_device_id rtl8192c_usb
 	{RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
 	{RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
 	{RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+	{RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */
 	{RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/
 	{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
 	{RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1128,7 +1128,7 @@ static int _rtl92de_set_media_status(str
 	}
 	rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0xfc) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,11 +203,12 @@ u32 rtl92d_phy_query_bb_reg(struct ieee8
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 	u32 returnvalue, originalvalue, bitshift;
-	u8 dbi_direct;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
 		 regaddr, bitmask);
 	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) {
+		u8 dbi_direct = 0;
+
 		/* mac1 use phy0 read radio_b. */
 		/* mac0 use phy1 read radio_b. */
 		if (rtlhal->during_mac1init_radioa)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192de/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192de/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -369,6 +369,7 @@
 #define	MSR_ADHOC			0x01
 #define	MSR_INFRA			0x02
 #define	MSR_AP				0x03
+#define	MSR_MASK			0x03
 
 /* 6. Adaptive Control Registers  (Offset: 0x0160 - 0x01CF) */
 /* ----------------------------------------------------- */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192se/fw.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,13 +112,10 @@ static u8 _rtl92s_firmware_header_map_rf
 	switch (rtlphy->rf_type) {
 	case RF_1T1R:
 		return 0x11;
-		break;
 	case RF_1T2R:
 		return 0x12;
-		break;
 	case RF_2T2R:
 		return 0x22;
-		break;
 	default:
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown RF type(%x)\n",
 			 rtlphy->rf_type);
@@ -438,7 +435,6 @@ int rtl92s_download_fw(struct ieee80211_
 			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 				 "Unexpected Download step!!\n");
 			goto fail;
-			break;
 		}
 
 		/* <2> Download image file */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8192se/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1198,7 +1198,6 @@ static int _rtl92se_set_media_status(str
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "Network type %d not supported!\n", type);
 		return 1;
-		break;
 
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1103,13 +1103,12 @@ static int _rtl8723ae_set_media_status(s
 			 "Network type %d not supported!\n",
 			 type);
 		return 1;
-		break;
 
 	}
 
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0x03) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -361,6 +361,7 @@
 #define	MSR_ADHOC				0x01
 #define	MSR_INFRA				0x02
 #define	MSR_AP					0x03
+#define	MSR_MASK				0x03
 
 #define	RRSR_RSC_OFFSET				21
 #define	RRSR_SHORT_OFFSET			23
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/hw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -1197,7 +1197,7 @@ static int _rtl8723be_set_media_status(s
 	}
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 	rtlpriv->cfg->ops->led_control(hw, ledaction);
-	if ((bt_msr & 0x03) == MSR_AP)
+	if ((bt_msr & MSR_MASK) == MSR_AP)
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
 	else
 		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -124,7 +124,6 @@ bool rtlbe_hal_pwrseqcmdparsing(struct r
 					 "rtlbe_hal_pwrseqcmdparsing(): "
 					 "PWR_CMD_END\n");
 				return true;
-				break;
 			default:
 				RT_ASSERT(false,
 					  "rtlbe_hal_pwrseqcmdparsing(): "
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/reg.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/reg.h
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/reg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/reg.h	2014-09-28 17:29:07.000000000 -0400
@@ -412,6 +412,7 @@
 #define	MSR_ADHOC				0x01
 #define	MSR_INFRA				0x02
 #define	MSR_AP					0x03
+#define	MSR_MASK				0x03
 
 #define	RRSR_RSC_OFFSET				21
 #define	RRSR_SHORT_OFFSET			23
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/sw.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
--- linux-libre-3.16-gnu/drivers/net/wireless/rtlwifi/rtl8723be/sw.c	2014-08-07 04:57:11.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/rtlwifi/rtl8723be/sw.c	2014-09-28 21:39:36.000000000 -0400
@@ -348,7 +348,7 @@ static struct rtl_hal_cfg rtl8723be_hal_
 	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rtl8723be_pci_id) = {
+static const struct pci_device_id rtl8723be_pci_id[] = {
 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb723, rtl8723be_hal_cfg)},
 	{},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl1251/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl1251/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl1251/main.c	2014-08-07 04:57:18.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl1251/main.c	2014-09-28 21:39:43.000000000 -0400
@@ -991,8 +991,9 @@ out:
 
 static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
-			     struct cfg80211_scan_request *req)
+			     struct ieee80211_scan_request *hw_req)
 {
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct wl1251 *wl = hw->priv;
 	struct sk_buff *skb;
 	size_t ssid_len = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/main.c	2014-08-07 04:57:23.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/main.c	2014-09-28 21:39:48.000000000 -0400
@@ -1668,7 +1668,7 @@ static bool wl12xx_lnk_high_prio(struct
 {
 	u8 thold;
 
-	if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
+	if (test_bit(hlid, &wl->fw_fast_lnk_map))
 		thold = wl->conf.tx.fast_link_thold;
 	else
 		thold = wl->conf.tx.slow_link_thold;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/scan.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/scan.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -156,7 +156,7 @@ static int wl1271_scan_send(struct wl127
 					 cmd->params.role_id, band,
 					 wl->scan.ssid, wl->scan.ssid_len,
 					 wl->scan.req->ie,
-					 wl->scan.req->ie_len, false);
+					 wl->scan.req->ie_len, NULL, 0, false);
 	if (ret < 0) {
 		wl1271_error("PROBE request template failed");
 		goto out;
@@ -317,7 +317,7 @@ static void wl12xx_adjust_channels(struc
 int wl1271_scan_sched_scan_config(struct wl1271 *wl,
 				  struct wl12xx_vif *wlvif,
 				  struct cfg80211_sched_scan_request *req,
-				  struct ieee80211_sched_scan_ies *ies)
+				  struct ieee80211_scan_ies *ies)
 {
 	struct wl1271_cmd_sched_scan_config *cfg = NULL;
 	struct wlcore_scan_channels *cfg_channels = NULL;
@@ -378,8 +378,11 @@ int wl1271_scan_sched_scan_config(struct
 						 wlvif->role_id, band,
 						 req->ssids[0].ssid,
 						 req->ssids[0].ssid_len,
-						 ies->ie[band],
-						 ies->len[band], true);
+						 ies->ies[band],
+						 ies->len[band],
+						 ies->common_ies,
+						 ies->common_ie_len,
+						 true);
 		if (ret < 0) {
 			wl1271_error("2.4GHz PROBE request template failed");
 			goto out;
@@ -392,8 +395,11 @@ int wl1271_scan_sched_scan_config(struct
 						 wlvif->role_id, band,
 						 req->ssids[0].ssid,
 						 req->ssids[0].ssid_len,
-						 ies->ie[band],
-						 ies->len[band], true);
+						 ies->ies[band],
+						 ies->len[band],
+						 ies->common_ies,
+						 ies->common_ie_len,
+						 true);
 		if (ret < 0) {
 			wl1271_error("5GHz PROBE request template failed");
 			goto out;
@@ -449,7 +455,7 @@ out_free:
 
 int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif  *wlvif,
 			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_sched_scan_ies *ies)
+			    struct ieee80211_scan_ies *ies)
 {
 	int ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/scan.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/scan.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl12xx/scan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl12xx/scan.h	2014-09-28 17:29:07.000000000 -0400
@@ -135,6 +135,6 @@ int wl12xx_scan_stop(struct wl1271 *wl,
 void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif  *wlvif,
 			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_sched_scan_ies *ies);
+			    struct ieee80211_scan_ies *ies);
 void wl12xx_scan_sched_scan_stop(struct wl1271 *wl,  struct wl12xx_vif *wlvif);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,3 +78,92 @@ out_free:
 out:
 	return ret;
 }
+
+int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
+{
+	struct wl18xx_cmd_smart_config_start *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x",
+		     group_bitmap);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->group_id_bitmask = cpu_to_le32(group_bitmap);
+
+	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send smart config start command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+out:
+	return ret;
+}
+
+int wl18xx_cmd_smart_config_stop(struct wl1271 *wl)
+{
+	struct wl1271_cmd_header *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd smart config stop");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send smart config stop command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+out:
+	return ret;
+}
+
+int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+					  u8 key_len, u8 *key)
+{
+	struct wl18xx_cmd_smart_config_set_group_key *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x",
+		     group_id);
+
+	if (key_len != sizeof(cmd->key)) {
+		wl1271_error("invalid group key size: %d", key_len);
+		return -E2BIG;
+	}
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->group_id = cpu_to_le32(group_id);
+	memcpy(cmd->key, key, key_len);
+
+	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd,
+			      sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send smart config set group key cmd");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+out:
+	return ret;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/cmd.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/cmd.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,8 +45,25 @@ struct wl18xx_cmd_channel_switch {
 	u8 padding[2];
 } __packed;
 
+struct wl18xx_cmd_smart_config_start {
+	struct wl1271_cmd_header header;
+
+	__le32 group_id_bitmask;
+} __packed;
+
+struct wl18xx_cmd_smart_config_set_group_key {
+	struct wl1271_cmd_header header;
+
+	__le32 group_id;
+
+	u8 key[16];
+} __packed;
+
 int wl18xx_cmd_channel_switch(struct wl1271 *wl,
 			      struct wl12xx_vif *wlvif,
 			      struct ieee80211_channel_switch *ch_switch);
-
+int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap);
+int wl18xx_cmd_smart_config_stop(struct wl1271 *wl);
+int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+					  u8 key_len, u8 *key);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/event.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/event.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/event.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/event.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,10 +19,12 @@
  *
  */
 
+#include <net/genetlink.h>
 #include "event.h"
 #include "scan.h"
 #include "../wlcore/cmd.h"
 #include "../wlcore/debug.h"
+#include "../wlcore/vendor_cmd.h"
 
 int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
 			  bool *timeout)
@@ -45,6 +47,58 @@ int wl18xx_wait_for_event(struct wl1271
 	return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
 }
 
+static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel,
+					  u8 sync_band)
+{
+	struct sk_buff *skb;
+	enum ieee80211_band band;
+	int freq;
+
+	if (sync_band == WLCORE_BAND_5GHZ)
+		band = IEEE80211_BAND_5GHZ;
+	else
+		band = IEEE80211_BAND_2GHZ;
+
+	freq = ieee80211_channel_to_frequency(sync_channel, band);
+
+	wl1271_debug(DEBUG_EVENT,
+		     "SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)",
+		     freq, sync_channel, sync_band);
+	skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, 20,
+					  WLCORE_VENDOR_EVENT_SC_SYNC,
+					  GFP_KERNEL);
+
+	if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) {
+		kfree_skb(skb);
+		return -EMSGSIZE;
+	}
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+	return 0;
+}
+
+static int wlcore_smart_config_decode_event(struct wl1271 *wl,
+					    u8 ssid_len, u8 *ssid,
+					    u8 pwd_len, u8 *pwd)
+{
+	struct sk_buff *skb;
+
+	wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID");
+	wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len);
+
+	skb = cfg80211_vendor_event_alloc(wl->hw->wiphy,
+					  ssid_len + pwd_len + 20,
+					  WLCORE_VENDOR_EVENT_SC_DECODE,
+					  GFP_KERNEL);
+
+	if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) ||
+	    nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) {
+		kfree_skb(skb);
+		return -EMSGSIZE;
+	}
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+	return 0;
+}
+
 int wl18xx_process_mailbox_events(struct wl1271 *wl)
 {
 	struct wl18xx_event_mailbox *mbox = wl->mbox;
@@ -107,5 +161,16 @@ int wl18xx_process_mailbox_events(struct
 	if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
 		wlcore_event_roc_complete(wl);
 
+	if (vector & SMART_CONFIG_SYNC_EVENT_ID)
+		wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel,
+					       mbox->sc_sync_band);
+
+	if (vector & SMART_CONFIG_DECODE_EVENT_ID)
+		wlcore_smart_config_decode_event(wl,
+						 mbox->sc_ssid_len,
+						 mbox->sc_ssid,
+						 mbox->sc_pwd_len,
+						 mbox->sc_pwd);
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/event.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/event.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/event.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/event.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,8 @@ enum {
 	REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID      = BIT(18),
 	DFS_CHANNELS_CONFIG_COMPLETE_EVENT       = BIT(19),
 	PERIODIC_SCAN_REPORT_EVENT_ID            = BIT(20),
+	SMART_CONFIG_SYNC_EVENT_ID		 = BIT(22),
+	SMART_CONFIG_DECODE_EVENT_ID		 = BIT(23),
 };
 
 struct wl18xx_event_mailbox {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/main.c	2014-08-07 04:57:26.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/main.c	2014-09-28 21:39:52.000000000 -0400
@@ -992,7 +992,10 @@ static int wl18xx_boot(struct wl1271 *wl
 		REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
 		INACTIVE_STA_EVENT_ID |
 		CHANNEL_SWITCH_COMPLETE_EVENT_ID |
-		DFS_CHANNELS_CONFIG_COMPLETE_EVENT;
+		DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
+		SMART_CONFIG_SYNC_EVENT_ID |
+		SMART_CONFIG_DECODE_EVENT_ID;
+;
 
 	wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
 
@@ -1606,15 +1609,20 @@ static bool wl18xx_lnk_high_prio(struct
 	u8 thold;
 	struct wl18xx_fw_status_priv *status_priv =
 		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
-	u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+	unsigned long suspend_bitmap;
+
+	/* if we don't have the link map yet, assume they all low prio */
+	if (!status_priv)
+		return false;
 
 	/* suspended links are never high priority */
-	if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+	suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+	if (test_bit(hlid, &suspend_bitmap))
 		return false;
 
 	/* the priority thresholds are taken from FW */
-	if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) &&
-	    !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map))
+	if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
+	    !test_bit(hlid, &wl->ap_fw_ps_map))
 		thold = status_priv->tx_fast_link_prio_threshold;
 	else
 		thold = status_priv->tx_slow_link_prio_threshold;
@@ -1628,12 +1636,17 @@ static bool wl18xx_lnk_low_prio(struct w
 	u8 thold;
 	struct wl18xx_fw_status_priv *status_priv =
 		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
-	u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+	unsigned long suspend_bitmap;
 
-	if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+	/* if we don't have the link map yet, assume they all low prio */
+	if (!status_priv)
+		return true;
+
+	suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+	if (test_bit(hlid, &suspend_bitmap))
 		thold = status_priv->tx_suspend_threshold;
-	else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) &&
-		 !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map))
+	else if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
+		 !test_bit(hlid, &wl->ap_fw_ps_map))
 		thold = status_priv->tx_fast_stop_threshold;
 	else
 		thold = status_priv->tx_slow_stop_threshold;
@@ -1687,6 +1700,9 @@ static struct wlcore_ops wl18xx_ops = {
 	.convert_hwaddr = wl18xx_convert_hwaddr,
 	.lnk_high_prio	= wl18xx_lnk_high_prio,
 	.lnk_low_prio	= wl18xx_lnk_low_prio,
+	.smart_config_start = wl18xx_cmd_smart_config_start,
+	.smart_config_stop  = wl18xx_cmd_smart_config_stop,
+	.smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
 };
 
 /* HT cap appropriate for wide channels in 2Ghz */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/scan.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/scan.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,6 +113,8 @@ static int wl18xx_scan_send(struct wl127
 				 req->ssids ? req->ssids[0].ssid_len : 0,
 				 req->ie,
 				 req->ie_len,
+				 NULL,
+				 0,
 				 false);
 		if (ret < 0) {
 			wl1271_error("2.4GHz PROBE request template failed");
@@ -128,6 +130,8 @@ static int wl18xx_scan_send(struct wl127
 				 req->ssids ? req->ssids[0].ssid_len : 0,
 				 req->ie,
 				 req->ie_len,
+				 NULL,
+				 0,
 				 false);
 		if (ret < 0) {
 			wl1271_error("5GHz PROBE request template failed");
@@ -161,7 +165,7 @@ static
 int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
 				  struct wl12xx_vif *wlvif,
 				  struct cfg80211_sched_scan_request *req,
-				  struct ieee80211_sched_scan_ies *ies)
+				  struct ieee80211_scan_ies *ies)
 {
 	struct wl18xx_cmd_scan_params *cmd;
 	struct wlcore_scan_channels *cmd_channels = NULL;
@@ -237,8 +241,10 @@ int wl18xx_scan_sched_scan_config(struct
 				 cmd->role_id, band,
 				 req->ssids ? req->ssids[0].ssid : NULL,
 				 req->ssids ? req->ssids[0].ssid_len : 0,
-				 ies->ie[band],
+				 ies->ies[band],
 				 ies->len[band],
+				 ies->common_ies,
+				 ies->common_ie_len,
 				 true);
 		if (ret < 0) {
 			wl1271_error("2.4GHz PROBE request template failed");
@@ -252,8 +258,10 @@ int wl18xx_scan_sched_scan_config(struct
 				 cmd->role_id, band,
 				 req->ssids ? req->ssids[0].ssid : NULL,
 				 req->ssids ? req->ssids[0].ssid_len : 0,
-				 ies->ie[band],
+				 ies->ies[band],
 				 ies->len[band],
+				 ies->common_ies,
+				 ies->common_ie_len,
 				 true);
 		if (ret < 0) {
 			wl1271_error("5GHz PROBE request template failed");
@@ -277,7 +285,7 @@ out:
 
 int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_sched_scan_ies *ies)
+			    struct ieee80211_scan_ies *ies)
 {
 	return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/scan.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/scan.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/scan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/scan.h	2014-09-28 17:29:07.000000000 -0400
@@ -122,6 +122,6 @@ int wl18xx_scan_stop(struct wl1271 *wl,
 void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_sched_scan_ies *ies);
+			    struct ieee80211_scan_ies *ies);
 void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,7 +30,7 @@
 
 static
 void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
-			     struct ieee80211_tx_rate *rate)
+			     u8 band, struct ieee80211_tx_rate *rate)
 {
 	u8 fw_rate = wl->fw_status->counters.tx_last_rate;
 
@@ -43,6 +43,8 @@ void wl18xx_get_last_tx_rate(struct wl12
 
 	if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) {
 		rate->idx = fw_rate;
+		if (band == IEEE80211_BAND_5GHZ)
+			rate->idx -= CONF_HW_RATE_INDEX_6MBPS;
 		rate->flags = 0;
 	} else {
 		rate->flags = IEEE80211_TX_RC_MCS;
@@ -102,7 +104,8 @@ static void wl18xx_tx_complete_packet(st
 	 * first pass info->control.vif while it's valid, and then fill out
 	 * the info->status structures
 	 */
-	wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]);
+	wl18xx_get_last_tx_rate(wl, info->control.vif,
+				info->band, &info->status.rates[0]);
 
 	info->status.rates[0].count = 1; /* no data about retries */
 	info->status.ack_signal = -1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/wl18xx.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/wl18xx.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wl18xx/wl18xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wl18xx/wl18xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
 #define WL18XX_NUM_TX_DESCRIPTORS 32
 #define WL18XX_NUM_RX_DESCRIPTORS 32
 
-#define WL18XX_NUM_MAC_ADDRESSES 3
+#define WL18XX_NUM_MAC_ADDRESSES 2
 
 #define WL18XX_RX_BA_MAX_SESSIONS 13
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -372,9 +372,9 @@ void wl12xx_free_link(struct wl1271 *wl,
 	wl1271_tx_reset_link_queues(wl, *hlid);
 	wl->links[*hlid].wlvif = NULL;
 
-	if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
-	    (wlvif->bss_type == BSS_TYPE_AP_BSS &&
-	     *hlid == wlvif->ap.bcast_hlid)) {
+	if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+	    *hlid == wlvif->ap.bcast_hlid) {
+		u32 sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
 		/*
 		 * save the total freed packets in the wlvif, in case this is
 		 * recovery or suspend
@@ -385,9 +385,11 @@ void wl12xx_free_link(struct wl1271 *wl,
 		 * increment the initial seq number on recovery to account for
 		 * transmitted packets that we haven't yet got in the FW status
 		 */
+		if (wlvif->encryption_type == KEY_GEM)
+			sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
+
 		if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
-			wlvif->total_freed_pkts +=
-					WL1271_TX_SQN_POST_RECOVERY_PADDING;
+			wlvif->total_freed_pkts += sqn_padding;
 	}
 
 	wl->links[*hlid].total_freed_pkts = 0;
@@ -1124,7 +1126,8 @@ out:
 int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			       u8 role_id, u8 band,
 			       const u8 *ssid, size_t ssid_len,
-			       const u8 *ie, size_t ie_len, bool sched_scan)
+			       const u8 *ie0, size_t ie0_len, const u8 *ie1,
+			       size_t ie1_len, bool sched_scan)
 {
 	struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
 	struct sk_buff *skb;
@@ -1136,13 +1139,15 @@ int wl12xx_cmd_build_probe_req(struct wl
 	wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
 
 	skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
-				     ie_len);
+				     ie0_len + ie1_len);
 	if (!skb) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	if (ie_len)
-		memcpy(skb_put(skb, ie_len), ie, ie_len);
+	if (ie0_len)
+		memcpy(skb_put(skb, ie0_len), ie0, ie0_len);
+	if (ie1_len)
+		memcpy(skb_put(skb, ie1_len), ie1, ie1_len);
 
 	if (sched_scan &&
 	    (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/cmd.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/cmd.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -64,7 +64,8 @@ int wl1271_cmd_build_ps_poll(struct wl12
 int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			       u8 role_id, u8 band,
 			       const u8 *ssid, size_t ssid_len,
-			       const u8 *ie, size_t ie_len, bool sched_scan);
+			       const u8 *ie, size_t ie_len, const u8 *common_ie,
+			       size_t common_ie_len, bool sched_scan);
 struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
 					      struct wl12xx_vif *wlvif,
 					      struct sk_buff *skb);
@@ -169,6 +170,9 @@ enum wl1271_commands {
 
 	/* start of 18xx specific commands */
 	CMD_DFS_CHANNEL_CONFIG		= 60,
+	CMD_SMART_CONFIG_START		= 61,
+	CMD_SMART_CONFIG_STOP		= 62,
+	CMD_SMART_CONFIG_SET_GROUP_KEY	= 63,
 
 	MAX_COMMAND_ID = 0xFFFF,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/debugfs.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/debugfs.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/debugfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -496,7 +496,7 @@ static ssize_t driver_state_read(struct
 	DRIVER_STATE_PRINT_INT(sg_enabled);
 	DRIVER_STATE_PRINT_INT(enable_11a);
 	DRIVER_STATE_PRINT_INT(noise);
-	DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
+	DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
 	DRIVER_STATE_PRINT_LHEX(ap_ps_map);
 	DRIVER_STATE_PRINT_HEX(quirks);
 	DRIVER_STATE_PRINT_HEX(irq);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/hw_ops.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/hw_ops.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/hw_ops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/hw_ops.h	2014-09-28 17:29:07.000000000 -0400
@@ -260,4 +260,31 @@ wlcore_hw_lnk_low_prio(struct wl1271 *wl
 	return wl->ops->lnk_low_prio(wl, hlid, lnk);
 }
 
+static inline int
+wlcore_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
+{
+	if (!wl->ops->smart_config_start)
+		return -EINVAL;
+
+	return wl->ops->smart_config_start(wl, group_bitmap);
+}
+
+static inline int
+wlcore_smart_config_stop(struct wl1271 *wl)
+{
+	if (!wl->ops->smart_config_stop)
+		return -EINVAL;
+
+	return wl->ops->smart_config_stop(wl);
+}
+
+static inline int
+wlcore_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+				  u8 key_len, u8 *key)
+{
+	if (!wl->ops->smart_config_set_group_key)
+		return -EINVAL;
+
+	return wl->ops->smart_config_set_group_key(wl, group_id, key_len, key);
+}
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/main.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/main.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/main.c	2014-08-07 04:57:31.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/main.c	2014-09-28 21:39:56.000000000 -0400
@@ -37,6 +37,7 @@
 #include "init.h"
 #include "debugfs.h"
 #include "testmode.h"
+#include "vendor_cmd.h"
 #include "scan.h"
 #include "hw_ops.h"
 #include "sysfs.h"
@@ -332,7 +333,7 @@ static void wl12xx_irq_ps_regulate_link(
 {
 	bool fw_ps;
 
-	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+	fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
 
 	/*
 	 * Wake up from high level PS if the STA is asleep with too little
@@ -359,13 +360,13 @@ static void wl12xx_irq_update_links_stat
 					   struct wl12xx_vif *wlvif,
 					   struct wl_fw_status *status)
 {
-	u32 cur_fw_ps_map;
+	unsigned long cur_fw_ps_map;
 	u8 hlid;
 
 	cur_fw_ps_map = status->link_ps_bitmap;
 	if (wl->ap_fw_ps_map != cur_fw_ps_map) {
 		wl1271_debug(DEBUG_PSM,
-			     "link ps prev 0x%x cur 0x%x changed 0x%x",
+			     "link ps prev 0x%lx cur 0x%lx changed 0x%lx",
 			     wl->ap_fw_ps_map, cur_fw_ps_map,
 			     wl->ap_fw_ps_map ^ cur_fw_ps_map);
 
@@ -898,6 +899,44 @@ out:
 	wlcore_set_partition(wl, &old_part);
 }
 
+static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+				   u8 hlid, struct ieee80211_sta *sta)
+{
+	struct wl1271_station *wl_sta;
+	u32 sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
+
+	wl_sta = (void *)sta->drv_priv;
+	wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
+
+	/*
+	 * increment the initial seq number on recovery to account for
+	 * transmitted packets that we haven't yet got in the FW status
+	 */
+	if (wlvif->encryption_type == KEY_GEM)
+		sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
+
+	if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+		wl_sta->total_freed_pkts += sqn_recovery_padding;
+}
+
+static void wlcore_save_freed_pkts_addr(struct wl1271 *wl,
+					struct wl12xx_vif *wlvif,
+					u8 hlid, const u8 *addr)
+{
+	struct ieee80211_sta *sta;
+	struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+	if (WARN_ON(hlid == WL12XX_INVALID_LINK_ID ||
+		    is_zero_ether_addr(addr)))
+		return;
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(vif, addr);
+	if (sta)
+		wlcore_save_freed_pkts(wl, wlvif, hlid, sta);
+	rcu_read_unlock();
+}
+
 static void wlcore_print_recovery(struct wl1271 *wl)
 {
 	u32 pc = 0;
@@ -961,6 +1000,13 @@ static void wl1271_recovery_work(struct
 		wlvif = list_first_entry(&wl->wlvif_list,
 				       struct wl12xx_vif, list);
 		vif = wl12xx_wlvif_to_vif(wlvif);
+
+		if (wlvif->bss_type == BSS_TYPE_STA_BSS &&
+		    test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
+			wlcore_save_freed_pkts_addr(wl, wlvif, wlvif->sta.hlid,
+						    vif->bss_conf.bssid);
+		}
+
 		__wl1271_op_remove_interface(wl, vif, false);
 	}
 
@@ -3540,8 +3586,9 @@ out:
 
 static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
-			     struct cfg80211_scan_request *req)
+			     struct ieee80211_scan_request *hw_req)
 {
+	struct cfg80211_scan_request *req = &hw_req->req;
 	struct wl1271 *wl = hw->priv;
 	int ret;
 	u8 *ssid = NULL;
@@ -3636,7 +3683,7 @@ out:
 static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
 				      struct cfg80211_sched_scan_request *req,
-				      struct ieee80211_sched_scan_ies *ies)
+				      struct ieee80211_scan_ies *ies)
 {
 	struct wl1271 *wl = hw->priv;
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
@@ -4702,36 +4749,18 @@ static int wl1271_allocate_sta(struct wl
 
 void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
 {
-	struct wl1271_station *wl_sta;
-	struct ieee80211_sta *sta;
-	struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
-
 	if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
 		return;
 
 	clear_bit(hlid, wlvif->ap.sta_hlid_map);
 	__clear_bit(hlid, &wl->ap_ps_map);
-	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+	__clear_bit(hlid, &wl->ap_fw_ps_map);
 
 	/*
 	 * save the last used PN in the private part of iee80211_sta,
 	 * in case of recovery/suspend
 	 */
-	rcu_read_lock();
-	sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
-	if (sta) {
-		wl_sta = (void *)sta->drv_priv;
-		wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
-
-		/*
-		 * increment the initial seq number on recovery to account for
-		 * transmitted packets that we haven't yet got in the FW status
-		 */
-		if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
-			wl_sta->total_freed_pkts +=
-					WL1271_TX_SQN_POST_RECOVERY_PADDING;
-	}
-	rcu_read_unlock();
+	wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr);
 
 	wl12xx_free_link(wl, wlvif, &hlid);
 	wl->active_sta_count--;
@@ -4914,6 +4943,21 @@ static int wl12xx_update_sta_state(struc
 		clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags);
 	}
 
+	/* save seq number on disassoc (suspend) */
+	if (is_sta &&
+	    old_state == IEEE80211_STA_ASSOC &&
+	    new_state == IEEE80211_STA_AUTH) {
+		wlcore_save_freed_pkts(wl, wlvif, wlvif->sta.hlid, sta);
+		wlvif->total_freed_pkts = 0;
+	}
+
+	/* restore seq number on assoc (resume) */
+	if (is_sta &&
+	    old_state == IEEE80211_STA_AUTH &&
+	    new_state == IEEE80211_STA_ASSOC) {
+		wlvif->total_freed_pkts = wl_sta->total_freed_pkts;
+	}
+
 	/* clear ROCs on failure or authorization */
 	if (is_sta &&
 	    (new_state == IEEE80211_STA_AUTHORIZED ||
@@ -5148,6 +5192,10 @@ static void wl12xx_op_channel_switch(str
 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
 		wl12xx_for_each_wlvif_sta(wl, wlvif) {
 			struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+			if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+				continue;
+
 			ieee80211_chswitch_done(vif, false);
 		}
 		goto out;
@@ -5163,6 +5211,9 @@ static void wl12xx_op_channel_switch(str
 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
 		unsigned long delay_usec;
 
+		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+			continue;
+
 		ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
 		if (ret)
 			goto out_sleep;
@@ -5618,7 +5669,7 @@ static void wl12xx_derive_mac_addresses(
 		memcpy(&wl->addresses[idx], &wl->addresses[0],
 		       sizeof(wl->addresses[0]));
 		/* LAA bit */
-		wl->addresses[idx].addr[2] |= BIT(1);
+		wl->addresses[idx].addr[0] |= BIT(1);
 	}
 
 	wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES;
@@ -5763,7 +5814,7 @@ static int wl1271_init_ieee80211(struct
 	wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
 		sizeof(struct ieee80211_header);
 
-	wl->hw->wiphy->max_remain_on_channel_duration = 5000;
+	wl->hw->wiphy->max_remain_on_channel_duration = 30000;
 
 	wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD |
 				WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
@@ -5832,6 +5883,9 @@ static int wl1271_init_ieee80211(struct
 	wl->hw->wiphy->iface_combinations = wl->iface_combinations;
 	wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations;
 
+	/* register vendor commands */
+	wlcore_set_vendor_commands(wl->hw->wiphy);
+
 	SET_IEEE80211_DEV(wl->hw, wl->dev);
 
 	wl->hw->sta_data_size = sizeof(struct wl1271_station);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/Makefile linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/Makefile
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,5 @@
 wlcore-objs		= main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
-			  boot.o init.o debugfs.o scan.o sysfs.o
+			  boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o
 
 wlcore_spi-objs 	= spi.o
 wlcore_sdio-objs	= sdio.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/scan.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/scan.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/scan.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/scan.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@ void wl1271_scan_complete_work(struct wo
 int wl1271_scan_sched_scan_config(struct wl1271 *wl,
 				     struct wl12xx_vif *wlvif,
 				     struct cfg80211_sched_scan_request *req,
-				     struct ieee80211_sched_scan_ies *ies);
+				     struct ieee80211_scan_ies *ies);
 int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 void wlcore_scan_sched_scan_results(struct wl1271 *wl);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/tx.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/tx.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,7 @@ static void wl1271_tx_regulate_link(stru
 	if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
 		return;
 
-	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+	fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
 	tx_pkts = wl->links[hlid].allocated_pkts;
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.c linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.c
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2014 Texas Instruments. All 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 <net/mac80211.h>
+#include <net/netlink.h>
+
+#include "wlcore.h"
+#include "debug.h"
+#include "ps.h"
+#include "hw_ops.h"
+#include "vendor_cmd.h"
+
+static const
+struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
+	[WLCORE_VENDOR_ATTR_FREQ]		= { .type = NLA_U32 },
+	[WLCORE_VENDOR_ATTR_GROUP_ID]		= { .type = NLA_U32 },
+	[WLCORE_VENDOR_ATTR_GROUP_KEY]		= { .type = NLA_U32,
+						    .len = WLAN_MAX_KEY_LEN },
+};
+
+static int
+wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int data_len)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct wl1271 *wl = hw->priv;
+	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
+
+	if (!data)
+		return -EINVAL;
+
+	ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
+			wlcore_vendor_attr_policy);
+	if (ret)
+		return ret;
+
+	if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
+		return -EINVAL;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wlcore_smart_config_start(wl,
+			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+
+	return 0;
+}
+
+static int
+wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data, int data_len)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct wl1271 *wl = hw->priv;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wlcore_smart_config_stop(wl);
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static int
+wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data, int data_len)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct wl1271 *wl = hw->priv;
+	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
+
+	if (!data)
+		return -EINVAL;
+
+	ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
+			wlcore_vendor_attr_policy);
+	if (ret)
+		return ret;
+
+	if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
+	    !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
+		return -EINVAL;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wlcore_smart_config_set_group_key(wl,
+			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
+			nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
+			nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
+	{
+		.info = {
+			.vendor_id = TI_OUI,
+			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlcore_vendor_cmd_smart_config_start,
+	},
+	{
+		.info = {
+			.vendor_id = TI_OUI,
+			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlcore_vendor_cmd_smart_config_stop,
+	},
+	{
+		.info = {
+			.vendor_id = TI_OUI,
+			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlcore_vendor_cmd_smart_config_set_group_key,
+	},
+};
+
+static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
+	{
+		.vendor_id = TI_OUI,
+		.subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
+	},
+	{
+		.vendor_id = TI_OUI,
+		.subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
+	},
+};
+
+void wlcore_set_vendor_commands(struct wiphy *wiphy)
+{
+	wiphy->vendor_commands = wlcore_vendor_commands;
+	wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
+	wiphy->vendor_events = wlcore_vendor_events;
+	wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/vendor_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2014 Texas Instruments. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef __WLCORE_VENDOR_H__
+#define __WLCORE_VENDOR_H__
+
+#ifdef __KERNEL__
+void wlcore_set_vendor_commands(struct wiphy *wiphy);
+#endif
+
+#define TI_OUI	0x080028
+
+enum wlcore_vendor_commands {
+	WLCORE_VENDOR_CMD_SMART_CONFIG_START,
+	WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
+	WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
+
+	NUM_WLCORE_VENDOR_CMD,
+	MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1
+};
+
+enum wlcore_vendor_attributes {
+	WLCORE_VENDOR_ATTR_FREQ,
+	WLCORE_VENDOR_ATTR_PSK,
+	WLCORE_VENDOR_ATTR_SSID,
+	WLCORE_VENDOR_ATTR_GROUP_ID,
+	WLCORE_VENDOR_ATTR_GROUP_KEY,
+
+	NUM_WLCORE_VENDOR_ATTR,
+	MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1
+};
+
+enum wlcore_vendor_events {
+	WLCORE_VENDOR_EVENT_SC_SYNC,
+	WLCORE_VENDOR_EVENT_SC_DECODE,
+};
+
+#endif /* __WLCORE_VENDOR_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/wlcore.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/wlcore.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/wlcore.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/wlcore.h	2014-09-28 17:29:07.000000000 -0400
@@ -95,7 +95,7 @@ struct wlcore_ops {
 	int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 	int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 				struct cfg80211_sched_scan_request *req,
-				struct ieee80211_sched_scan_ies *ies);
+				struct ieee80211_scan_ies *ies);
 	void (*sched_scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 	int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem);
 	int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd,
@@ -117,6 +117,10 @@ struct wlcore_ops {
 			      struct wl1271_link *lnk);
 	bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
 			     struct wl1271_link *lnk);
+	int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap);
+	int (*smart_config_stop)(struct wl1271 *wl);
+	int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id,
+					  u8 key_len, u8 *key);
 };
 
 enum wlcore_partitions {
@@ -384,10 +388,10 @@ struct wl1271 {
 	int active_link_count;
 
 	/* Fast/slow links bitmap according to FW */
-	u32 fw_fast_lnk_map;
+	unsigned long fw_fast_lnk_map;
 
 	/* AP-mode - a bitmap of links currently in PS mode according to FW */
-	u32 ap_fw_ps_map;
+	unsigned long ap_fw_ps_map;
 
 	/* AP-mode - a bitmap of links currently in PS mode in mac80211 */
 	unsigned long ap_ps_map;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/wlcore_i.h linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/wlcore_i.h
--- linux-libre-3.16-gnu/drivers/net/wireless/ti/wlcore/wlcore_i.h	2014-08-07 04:57:33.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/ti/wlcore/wlcore_i.h	2014-09-28 21:39:59.000000000 -0400
@@ -45,6 +45,9 @@
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
 #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
 #define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
+/* Use smaller padding for GEM, as some  APs have issues when it's too big */
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM 0x20
+
 
 #define WL1271_CIPHER_SUITE_GEM 0x00147201
 
@@ -324,6 +327,7 @@ struct wl1271_station {
 	 * total freed FW packets on the link to the STA - used for tracking the
 	 * AES/TKIP PN across recoveries. Re-initialized each time from the
 	 * wl1271_station structure.
+	 * Used in both AP and STA mode.
 	 */
 	u64 total_freed_pkts;
 };
@@ -460,21 +464,19 @@ struct wl12xx_vif {
 	struct delayed_work pending_auth_complete_work;
 
 	/*
+	 * total freed FW packets on the link.
+	 * For STA this holds the PN of the link to the AP.
+	 * For AP this holds the PN of the broadcast link.
+	 */
+	u64 total_freed_pkts;
+
+	/*
 	 * This struct must be last!
 	 * data that has to be saved acrossed reconfigs (e.g. recovery)
 	 * should be declared in this struct.
 	 */
 	struct {
 		u8 persistent[0];
-
-		/*
-		 * total freed FW packets on the link - used for
-		 * storing the AES/TKIP PN during recovery, as this
-		 * structure is not zeroed out.
-		 * For STA this holds the PN of the link to the AP.
-		 * For AP this holds the PN of the broadcast link.
-		 */
-		u64 total_freed_pkts;
 	};
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/wireless/zd1211rw/Kconfig linux-libre-3.17-rc7-gnu/drivers/net/wireless/zd1211rw/Kconfig
--- linux-libre-3.16-gnu/drivers/net/wireless/zd1211rw/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/wireless/zd1211rw/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,11 +3,11 @@ config ZD1211RW
 	depends on USB && MAC80211
 	select FW_LOADER
 	---help---
-	  This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
+	  This is a driver for the ZyDAS ZD1211/ZD1211B wireless
 	  chip, present in many USB-wireless adapters.
 
 	  Device firmware is required alongside this driver. You can download
-	  the firmware distribution from http://zd1211.ath.cx/get-firmware
+	  the firmware distribution from http://sf.net/projects/zd1211/files/
 
 config ZD1211RW_DEBUG
 	bool "ZyDAS ZD1211 debugging"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/xen-netback/common.h linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/common.h
--- linux-libre-3.16-gnu/drivers/net/xen-netback/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/common.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,7 @@
 #include <xen/interface/grant_table.h>
 #include <xen/grant_table.h>
 #include <xen/xenbus.h>
+#include <linux/debugfs.h>
 
 typedef unsigned int pending_ring_idx_t;
 #define INVALID_PENDING_RING_IDX (~0U)
@@ -164,6 +165,7 @@ struct xenvif_queue { /* Per-queue data
 	u16 dealloc_ring[MAX_PENDING_REQS];
 	struct task_struct *dealloc_task;
 	wait_queue_head_t dealloc_wq;
+	atomic_t inflight_packets;
 
 	/* Use kthread for guest RX */
 	struct task_struct *task;
@@ -175,9 +177,9 @@ struct xenvif_queue { /* Per-queue data
 	struct xen_netif_rx_back_ring rx;
 	struct sk_buff_head rx_queue;
 	RING_IDX rx_last_skb_slots;
-	bool rx_queue_purge;
+	unsigned long status;
 
-	struct timer_list wake_queue;
+	struct timer_list rx_stalled;
 
 	struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS];
 
@@ -197,6 +199,20 @@ struct xenvif_queue { /* Per-queue data
 	struct xenvif_stats stats;
 };
 
+enum state_bit_shift {
+	/* This bit marks that the vif is connected */
+	VIF_STATUS_CONNECTED,
+	/* This bit signals the RX thread that queuing was stopped (in
+	 * start_xmit), and either the timer fired or an RX interrupt came
+	 */
+	QUEUE_STATUS_RX_PURGE_EVENT,
+	/* This bit tells the interrupt handler that this queue was the reason
+	 * for the carrier off, so it should kick the thread. Only queues which
+	 * brought it down can turn on the carrier.
+	 */
+	QUEUE_STATUS_RX_STALLED
+};
+
 struct xenvif {
 	/* Unique identifier for this interface. */
 	domid_t          domid;
@@ -219,11 +235,16 @@ struct xenvif {
 	 * frontend is rogue.
 	 */
 	bool disabled;
+	unsigned long status;
 
 	/* Queues */
 	struct xenvif_queue *queues;
 	unsigned int num_queues; /* active queues, resource allocated */
 
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *xenvif_dbg_root;
+#endif
+
 	/* Miscellaneous private stuff. */
 	struct net_device *dev;
 };
@@ -297,10 +318,20 @@ static inline pending_ring_idx_t nr_pend
 /* Callback from stack when TX packet can be released */
 void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success);
 
+irqreturn_t xenvif_interrupt(int irq, void *dev_id);
+
 extern bool separate_tx_rx_irq;
 
 extern unsigned int rx_drain_timeout_msecs;
 extern unsigned int rx_drain_timeout_jiffies;
 extern unsigned int xenvif_max_queues;
 
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *xen_netback_dbg_root;
+#endif
+
+void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
+				 struct sk_buff *skb);
+void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue);
+
 #endif /* __XEN_NETBACK__COMMON_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/xen-netback/interface.c linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/interface.c
--- linux-libre-3.16-gnu/drivers/net/xen-netback/interface.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/interface.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,6 +43,23 @@
 #define XENVIF_QUEUE_LENGTH 32
 #define XENVIF_NAPI_WEIGHT  64
 
+/* This function is used to set SKBTX_DEV_ZEROCOPY as well as
+ * increasing the inflight counter. We need to increase the inflight
+ * counter because core driver calls into xenvif_zerocopy_callback
+ * which calls xenvif_skb_zerocopy_complete.
+ */
+void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
+				 struct sk_buff *skb)
+{
+	skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+	atomic_inc(&queue->inflight_packets);
+}
+
+void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
+{
+	atomic_dec(&queue->inflight_packets);
+}
+
 static inline void xenvif_stop_queue(struct xenvif_queue *queue)
 {
 	struct net_device *dev = queue->vif->dev;
@@ -55,7 +72,8 @@ static inline void xenvif_stop_queue(str
 
 int xenvif_schedulable(struct xenvif *vif)
 {
-	return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
+	return netif_running(vif->dev) &&
+		test_bit(VIF_STATUS_CONNECTED, &vif->status);
 }
 
 static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
@@ -96,13 +114,22 @@ int xenvif_poll(struct napi_struct *napi
 static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
 {
 	struct xenvif_queue *queue = dev_id;
+	struct netdev_queue *net_queue =
+		netdev_get_tx_queue(queue->vif->dev, queue->id);
 
+	/* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR
+	 * the carrier went down and this queue was previously blocked
+	 */
+	if (unlikely(netif_tx_queue_stopped(net_queue) ||
+		     (!netif_carrier_ok(queue->vif->dev) &&
+		      test_bit(QUEUE_STATUS_RX_STALLED, &queue->status))))
+		set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
 	xenvif_kick_thread(queue);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+irqreturn_t xenvif_interrupt(int irq, void *dev_id)
 {
 	xenvif_tx_interrupt(irq, dev_id);
 	xenvif_rx_interrupt(irq, dev_id);
@@ -124,16 +151,14 @@ void xenvif_wake_queue(struct xenvif_que
 	netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
 }
 
-/* Callback to wake the queue and drain it on timeout */
-static void xenvif_wake_queue_callback(unsigned long data)
+/* Callback to wake the queue's thread and turn the carrier off on timeout */
+static void xenvif_rx_stalled(unsigned long data)
 {
 	struct xenvif_queue *queue = (struct xenvif_queue *)data;
 
 	if (xenvif_queue_stopped(queue)) {
-		netdev_err(queue->vif->dev, "draining TX queue\n");
-		queue->rx_queue_purge = true;
+		set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
 		xenvif_kick_thread(queue);
-		xenvif_wake_queue(queue);
 	}
 }
 
@@ -182,11 +207,11 @@ static int xenvif_start_xmit(struct sk_b
 	 * drain.
 	 */
 	if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) {
-		queue->wake_queue.function = xenvif_wake_queue_callback;
-		queue->wake_queue.data = (unsigned long)queue;
+		queue->rx_stalled.function = xenvif_rx_stalled;
+		queue->rx_stalled.data = (unsigned long)queue;
 		xenvif_stop_queue(queue);
-		mod_timer(&queue->wake_queue,
-			jiffies + rx_drain_timeout_jiffies);
+		mod_timer(&queue->rx_stalled,
+			  jiffies + rx_drain_timeout_jiffies);
 	}
 
 	skb_queue_tail(&queue->rx_queue, skb);
@@ -267,7 +292,7 @@ static void xenvif_down(struct xenvif *v
 static int xenvif_open(struct net_device *dev)
 {
 	struct xenvif *vif = netdev_priv(dev);
-	if (netif_carrier_ok(dev))
+	if (test_bit(VIF_STATUS_CONNECTED, &vif->status))
 		xenvif_up(vif);
 	netif_tx_start_all_queues(dev);
 	return 0;
@@ -276,7 +301,7 @@ static int xenvif_open(struct net_device
 static int xenvif_close(struct net_device *dev)
 {
 	struct xenvif *vif = netdev_priv(dev);
-	if (netif_carrier_ok(dev))
+	if (test_bit(VIF_STATUS_CONNECTED, &vif->status))
 		xenvif_down(vif);
 	netif_tx_stop_all_queues(dev);
 	return 0;
@@ -418,8 +443,8 @@ struct xenvif *xenvif_alloc(struct devic
 	 * When the guest selects the desired number, it will be updated
 	 * via netif_set_real_num_*_queues().
 	 */
-	dev = alloc_netdev_mq(sizeof(struct xenvif), name, ether_setup,
-			      xenvif_max_queues);
+	dev = alloc_netdev_mq(sizeof(struct xenvif), name, NET_NAME_UNKNOWN,
+			      ether_setup, xenvif_max_queues);
 	if (dev == NULL) {
 		pr_warn("Could not allocate netdev for %s\n", name);
 		return ERR_PTR(-ENOMEM);
@@ -514,10 +539,7 @@ int xenvif_init_queue(struct xenvif_queu
 		queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE;
 	}
 
-	init_timer(&queue->wake_queue);
-
-	netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
-			XENVIF_NAPI_WEIGHT);
+	init_timer(&queue->rx_stalled);
 
 	return 0;
 }
@@ -528,6 +550,7 @@ void xenvif_carrier_on(struct xenvif *vi
 	if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
 		dev_set_mtu(vif->dev, ETH_DATA_LEN);
 	netdev_update_features(vif->dev);
+	set_bit(VIF_STATUS_CONNECTED, &vif->status);
 	netif_carrier_on(vif->dev);
 	if (netif_running(vif->dev))
 		xenvif_up(vif);
@@ -551,6 +574,10 @@ int xenvif_connect(struct xenvif_queue *
 
 	init_waitqueue_head(&queue->wq);
 	init_waitqueue_head(&queue->dealloc_wq);
+	atomic_set(&queue->inflight_packets, 0);
+
+	netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
+			XENVIF_NAPI_WEIGHT);
 
 	if (tx_evtchn == rx_evtchn) {
 		/* feature-split-event-channels == 0 */
@@ -625,29 +652,12 @@ void xenvif_carrier_off(struct xenvif *v
 	struct net_device *dev = vif->dev;
 
 	rtnl_lock();
-	netif_carrier_off(dev); /* discard queued packets */
-	if (netif_running(dev))
-		xenvif_down(vif);
-	rtnl_unlock();
-}
-
-static void xenvif_wait_unmap_timeout(struct xenvif_queue *queue,
-				      unsigned int worst_case_skb_lifetime)
-{
-	int i, unmap_timeout = 0;
-
-	for (i = 0; i < MAX_PENDING_REQS; ++i) {
-		if (queue->grant_tx_handle[i] != NETBACK_INVALID_HANDLE) {
-			unmap_timeout++;
-			schedule_timeout(msecs_to_jiffies(1000));
-			if (unmap_timeout > worst_case_skb_lifetime &&
-			    net_ratelimit())
-				netdev_err(queue->vif->dev,
-					   "Page still granted! Index: %x\n",
-					   i);
-			i = -1;
-		}
+	if (test_and_clear_bit(VIF_STATUS_CONNECTED, &vif->status)) {
+		netif_carrier_off(dev); /* discard queued packets */
+		if (netif_running(dev))
+			xenvif_down(vif);
 	}
+	rtnl_unlock();
 }
 
 void xenvif_disconnect(struct xenvif *vif)
@@ -656,14 +666,15 @@ void xenvif_disconnect(struct xenvif *vi
 	unsigned int num_queues = vif->num_queues;
 	unsigned int queue_index;
 
-	if (netif_carrier_ok(vif->dev))
-		xenvif_carrier_off(vif);
+	xenvif_carrier_off(vif);
 
 	for (queue_index = 0; queue_index < num_queues; ++queue_index) {
 		queue = &vif->queues[queue_index];
 
+		netif_napi_del(&queue->napi);
+
 		if (queue->task) {
-			del_timer_sync(&queue->wake_queue);
+			del_timer_sync(&queue->rx_stalled);
 			kthread_stop(queue->task);
 			queue->task = NULL;
 		}
@@ -694,7 +705,6 @@ void xenvif_disconnect(struct xenvif *vi
 void xenvif_deinit_queue(struct xenvif_queue *queue)
 {
 	free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages);
-	netif_napi_del(&queue->napi);
 }
 
 void xenvif_free(struct xenvif *vif)
@@ -702,25 +712,11 @@ void xenvif_free(struct xenvif *vif)
 	struct xenvif_queue *queue = NULL;
 	unsigned int num_queues = vif->num_queues;
 	unsigned int queue_index;
-	/* Here we want to avoid timeout messages if an skb can be legitimately
-	 * stuck somewhere else. Realistically this could be an another vif's
-	 * internal or QDisc queue. That another vif also has this
-	 * rx_drain_timeout_msecs timeout, but the timer only ditches the
-	 * internal queue. After that, the QDisc queue can put in worst case
-	 * XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS skbs into that another vif's
-	 * internal queue, so we need several rounds of such timeouts until we
-	 * can be sure that no another vif should have skb's from us. We are
-	 * not sending more skb's, so newly stuck packets are not interesting
-	 * for us here.
-	 */
-	unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000) *
-		DIV_ROUND_UP(XENVIF_QUEUE_LENGTH, (XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS));
 
 	unregister_netdev(vif->dev);
 
 	for (queue_index = 0; queue_index < num_queues; ++queue_index) {
 		queue = &vif->queues[queue_index];
-		xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime);
 		xenvif_deinit_queue(queue);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/xen-netback/netback.c linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/netback.c
--- linux-libre-3.16-gnu/drivers/net/xen-netback/netback.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/netback.c	2014-09-28 17:29:07.000000000 -0400
@@ -1525,10 +1525,12 @@ static int xenvif_handle_frag_list(struc
 	/* remove traces of mapped pages and frag_list */
 	skb_frag_list_init(skb);
 	uarg = skb_shinfo(skb)->destructor_arg;
+	/* increase inflight counter to offset decrement in callback */
+	atomic_inc(&queue->inflight_packets);
 	uarg->callback(uarg, true);
 	skb_shinfo(skb)->destructor_arg = NULL;
 
-	skb_shinfo(nskb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+	xenvif_skb_zerocopy_prepare(queue, nskb);
 	kfree_skb(nskb);
 
 	return 0;
@@ -1589,7 +1591,7 @@ static int xenvif_tx_submit(struct xenvi
 				if (net_ratelimit())
 					netdev_err(queue->vif->dev,
 						   "Not enough memory to consolidate frag_list!\n");
-				skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+				xenvif_skb_zerocopy_prepare(queue, skb);
 				kfree_skb(skb);
 				continue;
 			}
@@ -1609,7 +1611,7 @@ static int xenvif_tx_submit(struct xenvi
 				   "Can't setup checksum in net_tx_action\n");
 			/* We have to set this flag to trigger the callback */
 			if (skb_shinfo(skb)->destructor_arg)
-				skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+				xenvif_skb_zerocopy_prepare(queue, skb);
 			kfree_skb(skb);
 			continue;
 		}
@@ -1641,7 +1643,7 @@ static int xenvif_tx_submit(struct xenvi
 		 * skb. E.g. the __pskb_pull_tail earlier can do such thing.
 		 */
 		if (skb_shinfo(skb)->destructor_arg) {
-			skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+			xenvif_skb_zerocopy_prepare(queue, skb);
 			queue->stats.tx_zerocopy_sent++;
 		}
 
@@ -1681,6 +1683,7 @@ void xenvif_zerocopy_callback(struct ubu
 		queue->stats.tx_zerocopy_success++;
 	else
 		queue->stats.tx_zerocopy_fail++;
+	xenvif_skb_zerocopy_complete(queue);
 }
 
 static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue)
@@ -1869,8 +1872,7 @@ void xenvif_idx_unmap(struct xenvif_queu
 static inline int rx_work_todo(struct xenvif_queue *queue)
 {
 	return (!skb_queue_empty(&queue->rx_queue) &&
-	       xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots)) ||
-	       queue->rx_queue_purge;
+	       xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots));
 }
 
 static inline int tx_work_todo(struct xenvif_queue *queue)
@@ -1935,6 +1937,75 @@ static void xenvif_start_queue(struct xe
 		xenvif_wake_queue(queue);
 }
 
+/* Only called from the queue's thread, it handles the situation when the guest
+ * doesn't post enough requests on the receiving ring.
+ * First xenvif_start_xmit disables QDisc and start a timer, and then either the
+ * timer fires, or the guest send an interrupt after posting new request. If it
+ * is the timer, the carrier is turned off here.
+ * */
+static void xenvif_rx_purge_event(struct xenvif_queue *queue)
+{
+	/* Either the last unsuccesful skb or at least 1 slot should fit */
+	int needed = queue->rx_last_skb_slots ?
+		     queue->rx_last_skb_slots : 1;
+
+	/* It is assumed that if the guest post new slots after this, the RX
+	 * interrupt will set the QUEUE_STATUS_RX_PURGE_EVENT bit and wake up
+	 * the thread again
+	 */
+	set_bit(QUEUE_STATUS_RX_STALLED, &queue->status);
+	if (!xenvif_rx_ring_slots_available(queue, needed)) {
+		rtnl_lock();
+		if (netif_carrier_ok(queue->vif->dev)) {
+			/* Timer fired and there are still no slots. Turn off
+			 * everything except the interrupts
+			 */
+			netif_carrier_off(queue->vif->dev);
+			skb_queue_purge(&queue->rx_queue);
+			queue->rx_last_skb_slots = 0;
+			if (net_ratelimit())
+				netdev_err(queue->vif->dev, "Carrier off due to lack of guest response on queue %d\n", queue->id);
+		} else {
+			/* Probably an another queue already turned the carrier
+			 * off, make sure nothing is stucked in the internal
+			 * queue of this queue
+			 */
+			skb_queue_purge(&queue->rx_queue);
+			queue->rx_last_skb_slots = 0;
+		}
+		rtnl_unlock();
+	} else if (!netif_carrier_ok(queue->vif->dev)) {
+		unsigned int num_queues = queue->vif->num_queues;
+		unsigned int i;
+		/* The carrier was down, but an interrupt kicked
+		 * the thread again after new requests were
+		 * posted
+		 */
+		clear_bit(QUEUE_STATUS_RX_STALLED,
+			  &queue->status);
+		rtnl_lock();
+		netif_carrier_on(queue->vif->dev);
+		netif_tx_wake_all_queues(queue->vif->dev);
+		rtnl_unlock();
+
+		for (i = 0; i < num_queues; i++) {
+			struct xenvif_queue *temp = &queue->vif->queues[i];
+
+			xenvif_napi_schedule_or_enable_events(temp);
+		}
+		if (net_ratelimit())
+			netdev_err(queue->vif->dev, "Carrier on again\n");
+	} else {
+		/* Queuing were stopped, but the guest posted
+		 * new requests and sent an interrupt
+		 */
+		clear_bit(QUEUE_STATUS_RX_STALLED,
+			  &queue->status);
+		del_timer_sync(&queue->rx_stalled);
+		xenvif_start_queue(queue);
+	}
+}
+
 int xenvif_kthread_guest_rx(void *data)
 {
 	struct xenvif_queue *queue = data;
@@ -1944,8 +2015,12 @@ int xenvif_kthread_guest_rx(void *data)
 		wait_event_interruptible(queue->wq,
 					 rx_work_todo(queue) ||
 					 queue->vif->disabled ||
+					 test_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status) ||
 					 kthread_should_stop());
 
+		if (kthread_should_stop())
+			break;
+
 		/* This frontend is found to be rogue, disable it in
 		 * kthread context. Currently this is only set when
 		 * netback finds out frontend sends malformed packet,
@@ -1953,26 +2028,29 @@ int xenvif_kthread_guest_rx(void *data)
 		 * context so we defer it here, if this thread is
 		 * associated with queue 0.
 		 */
-		if (unlikely(queue->vif->disabled && netif_carrier_ok(queue->vif->dev) && queue->id == 0))
+		if (unlikely(queue->vif->disabled && queue->id == 0)) {
 			xenvif_carrier_off(queue->vif);
-
-		if (kthread_should_stop())
-			break;
-
-		if (queue->rx_queue_purge) {
+		} else if (unlikely(queue->vif->disabled)) {
+			/* kthread_stop() would be called upon this thread soon,
+			 * be a bit proactive
+			 */
 			skb_queue_purge(&queue->rx_queue);
-			queue->rx_queue_purge = false;
+			queue->rx_last_skb_slots = 0;
+		} else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT,
+						     &queue->status))) {
+			xenvif_rx_purge_event(queue);
+		} else if (!netif_carrier_ok(queue->vif->dev)) {
+			/* Another queue stalled and turned the carrier off, so
+			 * purge the internal queue of queues which were not
+			 * blocked
+			 */
+			skb_queue_purge(&queue->rx_queue);
+			queue->rx_last_skb_slots = 0;
 		}
 
 		if (!skb_queue_empty(&queue->rx_queue))
 			xenvif_rx_action(queue);
 
-		if (skb_queue_empty(&queue->rx_queue) &&
-		    xenvif_queue_stopped(queue)) {
-			del_timer_sync(&queue->wake_queue);
-			xenvif_start_queue(queue);
-		}
-
 		cond_resched();
 	}
 
@@ -1983,15 +2061,24 @@ int xenvif_kthread_guest_rx(void *data)
 	return 0;
 }
 
+static bool xenvif_dealloc_kthread_should_stop(struct xenvif_queue *queue)
+{
+	/* Dealloc thread must remain running until all inflight
+	 * packets complete.
+	 */
+	return kthread_should_stop() &&
+		!atomic_read(&queue->inflight_packets);
+}
+
 int xenvif_dealloc_kthread(void *data)
 {
 	struct xenvif_queue *queue = data;
 
-	while (!kthread_should_stop()) {
+	for (;;) {
 		wait_event_interruptible(queue->dealloc_wq,
 					 tx_dealloc_work_todo(queue) ||
-					 kthread_should_stop());
-		if (kthread_should_stop())
+					 xenvif_dealloc_kthread_should_stop(queue));
+		if (xenvif_dealloc_kthread_should_stop(queue))
 			break;
 
 		xenvif_tx_dealloc_action(queue);
@@ -2027,6 +2114,13 @@ static int __init netback_init(void)
 
 	rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs);
 
+#ifdef CONFIG_DEBUG_FS
+	xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL);
+	if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+		pr_warn("Init of debugfs returned %ld!\n",
+			PTR_ERR(xen_netback_dbg_root));
+#endif /* CONFIG_DEBUG_FS */
+
 	return 0;
 
 failed_init:
@@ -2037,6 +2131,10 @@ module_init(netback_init);
 
 static void __exit netback_fini(void)
 {
+#ifdef CONFIG_DEBUG_FS
+	if (!IS_ERR_OR_NULL(xen_netback_dbg_root))
+		debugfs_remove_recursive(xen_netback_dbg_root);
+#endif /* CONFIG_DEBUG_FS */
 	xenvif_xenbus_fini();
 }
 module_exit(netback_fini);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/xen-netback/xenbus.c linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/xenbus.c
--- linux-libre-3.16-gnu/drivers/net/xen-netback/xenbus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/xen-netback/xenbus.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,177 @@ static void unregister_hotplug_status_wa
 static void set_backend_state(struct backend_info *be,
 			      enum xenbus_state state);
 
+#ifdef CONFIG_DEBUG_FS
+struct dentry *xen_netback_dbg_root = NULL;
+
+static int xenvif_read_io_ring(struct seq_file *m, void *v)
+{
+	struct xenvif_queue *queue = m->private;
+	struct xen_netif_tx_back_ring *tx_ring = &queue->tx;
+	struct xen_netif_rx_back_ring *rx_ring = &queue->rx;
+
+	if (tx_ring->sring) {
+		struct xen_netif_tx_sring *sring = tx_ring->sring;
+
+		seq_printf(m, "Queue %d\nTX: nr_ents %u\n", queue->id,
+			   tx_ring->nr_ents);
+		seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
+			   sring->req_prod,
+			   sring->req_prod - sring->rsp_prod,
+			   tx_ring->req_cons,
+			   tx_ring->req_cons - sring->rsp_prod,
+			   sring->req_event,
+			   sring->req_event - sring->rsp_prod);
+		seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n",
+			   sring->rsp_prod,
+			   tx_ring->rsp_prod_pvt,
+			   tx_ring->rsp_prod_pvt - sring->rsp_prod,
+			   sring->rsp_event,
+			   sring->rsp_event - sring->rsp_prod);
+		seq_printf(m, "pending prod %u pending cons %u nr_pending_reqs %u\n",
+			   queue->pending_prod,
+			   queue->pending_cons,
+			   nr_pending_reqs(queue));
+		seq_printf(m, "dealloc prod %u dealloc cons %u dealloc_queue %u\n\n",
+			   queue->dealloc_prod,
+			   queue->dealloc_cons,
+			   queue->dealloc_prod - queue->dealloc_cons);
+	}
+
+	if (rx_ring->sring) {
+		struct xen_netif_rx_sring *sring = rx_ring->sring;
+
+		seq_printf(m, "RX: nr_ents %u\n", rx_ring->nr_ents);
+		seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
+			   sring->req_prod,
+			   sring->req_prod - sring->rsp_prod,
+			   rx_ring->req_cons,
+			   rx_ring->req_cons - sring->rsp_prod,
+			   sring->req_event,
+			   sring->req_event - sring->rsp_prod);
+		seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n\n",
+			   sring->rsp_prod,
+			   rx_ring->rsp_prod_pvt,
+			   rx_ring->rsp_prod_pvt - sring->rsp_prod,
+			   sring->rsp_event,
+			   sring->rsp_event - sring->rsp_prod);
+	}
+
+	seq_printf(m, "NAPI state: %lx NAPI weight: %d TX queue len %u\n"
+		   "Credit timer_pending: %d, credit: %lu, usec: %lu\n"
+		   "remaining: %lu, expires: %lu, now: %lu\n",
+		   queue->napi.state, queue->napi.weight,
+		   skb_queue_len(&queue->tx_queue),
+		   timer_pending(&queue->credit_timeout),
+		   queue->credit_bytes,
+		   queue->credit_usec,
+		   queue->remaining_credit,
+		   queue->credit_timeout.expires,
+		   jiffies);
+
+	return 0;
+}
+
+#define XENVIF_KICK_STR "kick"
+#define BUFFER_SIZE     32
+
+static ssize_t
+xenvif_write_io_ring(struct file *filp, const char __user *buf, size_t count,
+		     loff_t *ppos)
+{
+	struct xenvif_queue *queue =
+		((struct seq_file *)filp->private_data)->private;
+	int len;
+	char write[BUFFER_SIZE];
+
+	/* don't allow partial writes and check the length */
+	if (*ppos != 0)
+		return 0;
+	if (count >= sizeof(write))
+		return -ENOSPC;
+
+	len = simple_write_to_buffer(write,
+				     sizeof(write) - 1,
+				     ppos,
+				     buf,
+				     count);
+	if (len < 0)
+		return len;
+
+	write[len] = '\0';
+
+	if (!strncmp(write, XENVIF_KICK_STR, sizeof(XENVIF_KICK_STR) - 1))
+		xenvif_interrupt(0, (void *)queue);
+	else {
+		pr_warn("Unknown command to io_ring_q%d. Available: kick\n",
+			queue->id);
+		count = -EINVAL;
+	}
+	return count;
+}
+
+static int xenvif_dump_open(struct inode *inode, struct file *filp)
+{
+	int ret;
+	void *queue = NULL;
+
+	if (inode->i_private)
+		queue = inode->i_private;
+	ret = single_open(filp, xenvif_read_io_ring, queue);
+	filp->f_mode |= FMODE_PWRITE;
+	return ret;
+}
+
+static const struct file_operations xenvif_dbg_io_ring_ops_fops = {
+	.owner = THIS_MODULE,
+	.open = xenvif_dump_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = xenvif_write_io_ring,
+};
+
+static void xenvif_debugfs_addif(struct xenvif *vif)
+{
+	struct dentry *pfile;
+	int i;
+
+	if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+		return;
+
+	vif->xenvif_dbg_root = debugfs_create_dir(vif->dev->name,
+						  xen_netback_dbg_root);
+	if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root)) {
+		for (i = 0; i < vif->num_queues; ++i) {
+			char filename[sizeof("io_ring_q") + 4];
+
+			snprintf(filename, sizeof(filename), "io_ring_q%d", i);
+			pfile = debugfs_create_file(filename,
+						    S_IRUSR | S_IWUSR,
+						    vif->xenvif_dbg_root,
+						    &vif->queues[i],
+						    &xenvif_dbg_io_ring_ops_fops);
+			if (IS_ERR_OR_NULL(pfile))
+				pr_warn("Creation of io_ring file returned %ld!\n",
+					PTR_ERR(pfile));
+		}
+	} else
+		netdev_warn(vif->dev,
+			    "Creation of vif debugfs dir returned %ld!\n",
+			    PTR_ERR(vif->xenvif_dbg_root));
+}
+
+static void xenvif_debugfs_delif(struct xenvif *vif)
+{
+	if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+		return;
+
+	if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root))
+		debugfs_remove_recursive(vif->xenvif_dbg_root);
+	vif->xenvif_dbg_root = NULL;
+}
+#endif /* CONFIG_DEBUG_FS */
+
 static int netback_remove(struct xenbus_device *dev)
 {
 	struct backend_info *be = dev_get_drvdata(&dev->dev);
@@ -246,8 +417,12 @@ static void backend_create_xenvif(struct
 
 static void backend_disconnect(struct backend_info *be)
 {
-	if (be->vif)
+	if (be->vif) {
+#ifdef CONFIG_DEBUG_FS
+		xenvif_debugfs_delif(be->vif);
+#endif /* CONFIG_DEBUG_FS */
 		xenvif_disconnect(be->vif);
+	}
 }
 
 static void backend_connect(struct backend_info *be)
@@ -562,6 +737,10 @@ static void connect(struct backend_info
 		}
 	}
 
+#ifdef CONFIG_DEBUG_FS
+	xenvif_debugfs_addif(be->vif);
+#endif /* CONFIG_DEBUG_FS */
+
 	/* Initialisation completed, tell core driver the number of
 	 * active queues.
 	 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/net/xen-netfront.c linux-libre-3.17-rc7-gnu/drivers/net/xen-netfront.c
--- linux-libre-3.16-gnu/drivers/net/xen-netfront.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/net/xen-netfront.c	2014-09-28 17:29:07.000000000 -0400
@@ -628,9 +628,10 @@ static int xennet_start_xmit(struct sk_b
 	slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
 		xennet_count_skb_frag_slots(skb);
 	if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
-		net_alert_ratelimited(
-			"xennet: skb rides the rocket: %d slots\n", slots);
-		goto drop;
+		net_dbg_ratelimited("xennet: skb rides the rocket: %d slots, %d bytes\n",
+				    slots, skb->len);
+		if (skb_linearize(skb))
+			goto drop;
 	}
 
 	spin_lock_irqsave(&queue->tx_lock, flags);
@@ -1196,22 +1197,6 @@ static void xennet_release_rx_bufs(struc
 	spin_unlock_bh(&queue->rx_lock);
 }
 
-static void xennet_uninit(struct net_device *dev)
-{
-	struct netfront_info *np = netdev_priv(dev);
-	unsigned int num_queues = dev->real_num_tx_queues;
-	struct netfront_queue *queue;
-	unsigned int i;
-
-	for (i = 0; i < num_queues; ++i) {
-		queue = &np->queues[i];
-		xennet_release_tx_bufs(queue);
-		xennet_release_rx_bufs(queue);
-		gnttab_free_grant_references(queue->gref_tx_head);
-		gnttab_free_grant_references(queue->gref_rx_head);
-	}
-}
-
 static netdev_features_t xennet_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
@@ -1313,7 +1298,6 @@ static void xennet_poll_controller(struc
 
 static const struct net_device_ops xennet_netdev_ops = {
 	.ndo_open            = xennet_open,
-	.ndo_uninit          = xennet_uninit,
 	.ndo_stop            = xennet_close,
 	.ndo_start_xmit      = xennet_start_xmit,
 	.ndo_change_mtu	     = xennet_change_mtu,
@@ -1455,6 +1439,11 @@ static void xennet_disconnect_backend(st
 
 		napi_synchronize(&queue->napi);
 
+		xennet_release_tx_bufs(queue);
+		xennet_release_rx_bufs(queue);
+		gnttab_free_grant_references(queue->gref_tx_head);
+		gnttab_free_grant_references(queue->gref_rx_head);
+
 		/* End access and free the pages */
 		xennet_end_access(queue->tx_ring_ref, queue->tx.sring);
 		xennet_end_access(queue->rx_ring_ref, queue->rx.sring);
@@ -1827,8 +1816,8 @@ static int xennet_create_queues(struct n
 
 		ret = xennet_init_queue(queue);
 		if (ret < 0) {
-			dev_warn(&info->netdev->dev, "only created %d queues\n",
-				 num_queues);
+			dev_warn(&info->netdev->dev,
+				 "only created %d queues\n", i);
 			num_queues = i;
 			break;
 		}
@@ -2001,7 +1990,7 @@ abort_transaction_no_dev_fatal:
 	info->queues = NULL;
 	rtnl_lock();
 	netif_set_real_num_tx_queues(info->netdev, 0);
-	rtnl_lock();
+	rtnl_unlock();
  out:
 	return err;
 }
@@ -2010,10 +1999,7 @@ static int xennet_connect(struct net_dev
 {
 	struct netfront_info *np = netdev_priv(dev);
 	unsigned int num_queues = 0;
-	int i, requeue_idx, err;
-	struct sk_buff *skb;
-	grant_ref_t ref;
-	struct xen_netif_rx_request *req;
+	int err;
 	unsigned int feature_rx_copy;
 	unsigned int j = 0;
 	struct netfront_queue *queue = NULL;
@@ -2040,47 +2026,8 @@ static int xennet_connect(struct net_dev
 	netdev_update_features(dev);
 	rtnl_unlock();
 
-	/* By now, the queue structures have been set up */
-	for (j = 0; j < num_queues; ++j) {
-		queue = &np->queues[j];
-
-		/* Step 1: Discard all pending TX packet fragments. */
-		spin_lock_irq(&queue->tx_lock);
-		xennet_release_tx_bufs(queue);
-		spin_unlock_irq(&queue->tx_lock);
-
-		/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
-		spin_lock_bh(&queue->rx_lock);
-
-		for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
-			skb_frag_t *frag;
-			const struct page *page;
-			if (!queue->rx_skbs[i])
-				continue;
-
-			skb = queue->rx_skbs[requeue_idx] = xennet_get_rx_skb(queue, i);
-			ref = queue->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(queue, i);
-			req = RING_GET_REQUEST(&queue->rx, requeue_idx);
-
-			frag = &skb_shinfo(skb)->frags[0];
-			page = skb_frag_page(frag);
-			gnttab_grant_foreign_access_ref(
-				ref, queue->info->xbdev->otherend_id,
-				pfn_to_mfn(page_to_pfn(page)),
-				0);
-			req->gref = ref;
-			req->id   = requeue_idx;
-
-			requeue_idx++;
-		}
-
-		queue->rx.req_prod_pvt = requeue_idx;
-
-		spin_unlock_bh(&queue->rx_lock);
-	}
-
 	/*
-	 * Step 3: All public and private state should now be sane.  Get
+	 * All public and private state should now be sane.  Get
 	 * ready to start sending and receiving packets and give the driver
 	 * domain a kick because we've probably just requeued some
 	 * packets.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/Kconfig linux-libre-3.17-rc7-gnu/drivers/nfc/Kconfig
--- linux-libre-3.16-gnu/drivers/nfc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -72,5 +72,5 @@ source "drivers/nfc/pn544/Kconfig"
 source "drivers/nfc/microread/Kconfig"
 source "drivers/nfc/nfcmrvl/Kconfig"
 source "drivers/nfc/st21nfca/Kconfig"
-
+source "drivers/nfc/st21nfcb/Kconfig"
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/Makefile linux-libre-3.17-rc7-gnu/drivers/nfc/Makefile
--- linux-libre-3.16-gnu/drivers/nfc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -11,6 +11,7 @@ obj-$(CONFIG_NFC_SIM)		+= nfcsim.o
 obj-$(CONFIG_NFC_PORT100)	+= port100.o
 obj-$(CONFIG_NFC_MRVL)		+= nfcmrvl/
 obj-$(CONFIG_NFC_TRF7970A)	+= trf7970a.o
-obj-$(CONFIG_NFC_ST21NFCA)  += st21nfca/
+obj-$(CONFIG_NFC_ST21NFCA)  	+= st21nfca/
+obj-$(CONFIG_NFC_ST21NFCB)	+= st21nfcb/
 
 ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/microread/microread.c linux-libre-3.17-rc7-gnu/drivers/nfc/microread/microread.c
--- linux-libre-3.16-gnu/drivers/nfc/microread/microread.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/microread/microread.c	2014-09-28 17:29:07.000000000 -0400
@@ -501,9 +501,13 @@ static void microread_target_discovered(
 		targets->sens_res =
 			 be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]);
 		targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK];
-		memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID],
-		       skb->data[MICROREAD_EMCF_A_LEN]);
 		targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN];
+		if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
+			r = -EINVAL;
+			goto exit_free;
+		}
+		memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID],
+		       targets->nfcid1_len);
 		break;
 	case MICROREAD_GATE_ID_MREAD_ISO_A_3:
 		targets->supported_protocols =
@@ -511,9 +515,13 @@ static void microread_target_discovered(
 		targets->sens_res =
 			 be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]);
 		targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK];
-		memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID],
-		       skb->data[MICROREAD_EMCF_A3_LEN]);
 		targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN];
+		if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
+			r = -EINVAL;
+			goto exit_free;
+		}
+		memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID],
+		       targets->nfcid1_len);
 		break;
 	case MICROREAD_GATE_ID_MREAD_ISO_B:
 		targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/i2c.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/i2c.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,7 +93,7 @@ struct st21nfca_i2c_phy {
 	int hard_fault;
 	struct mutex phy_lock;
 };
-static u8 len_seq[] = { 13, 24, 15, 29 };
+static u8 len_seq[] = { 16, 24, 12, 29 };
 static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};
 
 #define I2C_DUMP_SKB(info, skb)					\
@@ -397,12 +397,11 @@ static int st21nfca_hci_i2c_read(struct
 		 * The first read sequence does not start with SOF.
 		 * Data is corrupeted so we drop it.
 		 */
-		if (!phy->current_read_len && buf[0] != ST21NFCA_SOF_EOF) {
+		if (!phy->current_read_len && !IS_START_OF_FRAME(buf)) {
 			skb_trim(skb, 0);
 			phy->current_read_len = 0;
 			return -EIO;
-		} else if (phy->current_read_len &&
-			IS_START_OF_FRAME(buf)) {
+		} else if (phy->current_read_len && IS_START_OF_FRAME(buf)) {
 			/*
 			 * Previous frame transmission was interrupted and
 			 * the frame got repeated.
@@ -487,6 +486,8 @@ static irqreturn_t st21nfca_hci_irq_thre
 		 */
 		nfc_hci_recv_frame(phy->hdev, phy->pending_skb);
 		phy->crc_trials = 0;
+	} else {
+		kfree_skb(phy->pending_skb);
 	}
 
 	phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/Makefile linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/Makefile
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,8 @@
 # Makefile for ST21NFCA HCI based NFC driver
 #
 
-st21nfca_i2c-objs  = i2c.o
+st21nfca_hci-objs = st21nfca.o st21nfca_dep.o
+obj-$(CONFIG_NFC_ST21NFCA)     += st21nfca_hci.o
 
-obj-$(CONFIG_NFC_ST21NFCA)     += st21nfca.o
+st21nfca_i2c-objs  = i2c.o
 obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include <net/nfc/llc.h>
 
 #include "st21nfca.h"
+#include "st21nfca_dep.h"
 
 #define DRIVER_DESC "HCI NFC driver for ST21NFCA"
 
@@ -53,6 +54,7 @@
 #define ST21NFCA_DM_PIPE_CREATED        0x02
 #define ST21NFCA_DM_PIPE_OPEN           0x04
 #define ST21NFCA_DM_RF_ACTIVE           0x80
+#define ST21NFCA_DM_DISCONNECT		0x30
 
 #define ST21NFCA_DM_IS_PIPE_OPEN(p) \
 	((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
@@ -72,6 +74,7 @@ static struct nfc_hci_gate st21nfca_gate
 	{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
+	{ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
 };
 
 struct st21nfca_pipe_info {
@@ -299,6 +302,9 @@ static int st21nfca_hci_start_poll(struc
 				   u32 im_protocols, u32 tm_protocols)
 {
 	int r;
+	u32 pol_req;
+	u8 param[19];
+	struct sk_buff *datarate_skb;
 
 	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
 		__func__, im_protocols, tm_protocols);
@@ -331,6 +337,31 @@ static int st21nfca_hci_start_poll(struc
 					ST21NFCA_RF_READER_F_GATE);
 			if (r < 0)
 				return r;
+		} else {
+			hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
+							       &hdev->gb_len);
+
+			if (hdev->gb == NULL || hdev->gb_len == 0) {
+				im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+				tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+			}
+
+			param[0] = ST21NFCA_RF_READER_F_DATARATE_106 |
+			    ST21NFCA_RF_READER_F_DATARATE_212 |
+			    ST21NFCA_RF_READER_F_DATARATE_424;
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					      ST21NFCA_RF_READER_F_DATARATE,
+					      param, 1);
+			if (r < 0)
+				return r;
+
+			pol_req =
+			    be32_to_cpu(ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					      ST21NFCA_RF_READER_F_POL_REQ,
+					      (u8 *) &pol_req, 4);
+			if (r < 0)
+				return r;
 		}
 
 		if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) {
@@ -353,9 +384,104 @@ static int st21nfca_hci_start_poll(struc
 			nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
 					   NFC_HCI_EVT_END_OPERATION, NULL, 0);
 	}
+
+	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_DATARATE,
+				      &datarate_skb);
+		if (r < 0)
+			return r;
+
+		/* Configure the maximum supported datarate to 424Kbps */
+		if (datarate_skb->len > 0 &&
+		    datarate_skb->data[0] !=
+		    ST21NFCA_RF_CARD_F_DATARATE_212_424) {
+			param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424;
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+					      ST21NFCA_RF_CARD_F_DATARATE,
+					      param, 1);
+			if (r < 0)
+				return r;
+		}
+
+		/*
+		 * Configure sens_res
+		 *
+		 * NFC Forum Digital Spec Table 7:
+		 * NFCID1 size: triple (10 bytes)
+		 */
+		param[0] = 0x00;
+		param[1] = 0x08;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_SENS_RES, param, 2);
+		if (r < 0)
+			return r;
+
+		/*
+		 * Configure sel_res
+		 *
+		 * NFC Forum Digistal Spec Table 17:
+		 * b3 set to 0b (value b7-b6):
+		 * - 10b: Configured for NFC-DEP Protocol
+		 */
+		param[0] = 0x40;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_SEL_RES, param, 1);
+		if (r < 0)
+			return r;
+
+		/* Configure NFCID1 Random uid */
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_NFCID1, NULL, 0);
+		if (r < 0)
+			return r;
+
+		/* Configure NFCID2_LIST */
+		/* System Code */
+		param[0] = 0x00;
+		param[1] = 0x00;
+		/* NFCID2 */
+		param[2] = 0x01;
+		param[3] = 0xfe;
+		param[4] = 'S';
+		param[5] = 'T';
+		param[6] = 'M';
+		param[7] = 'i';
+		param[8] = 'c';
+		param[9] = 'r';
+		/* 8 byte Pad bytes used for polling respone frame */
+
+		/*
+		 * Configuration byte:
+		 * - bit 0: define the default NFCID2 entry used when the
+		 * system code is equal to 'FFFF'
+		 * - bit 1: use a random value for lowest 6 bytes of
+		 * NFCID2 value
+		 * - bit 2: ignore polling request frame if request code
+		 * is equal to '01'
+		 * - Other bits are RFU
+		 */
+		param[18] = 0x01;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_NFCID2_LIST, param,
+				      19);
+		if (r < 0)
+			return r;
+
+		param[0] = 0x02;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_MODE, param, 1);
+	}
+
 	return r;
 }
 
+static void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev)
+{
+	nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
 static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa)
 {
 	int r;
@@ -451,6 +577,26 @@ exit:
 	return r;
 }
 
+static int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev,
+				    struct nfc_target *target, u8 comm_mode,
+				    u8 *gb, size_t gb_len)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->dep_info.idx = target->idx;
+	return st21nfca_im_send_atr_req(hdev, gb, gb_len);
+}
+
+static int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->state = ST21NFCA_ST_READY;
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
 static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
 					 struct nfc_target *target)
 {
@@ -505,6 +651,69 @@ static int st21nfca_hci_target_from_gate
 	return 0;
 }
 
+static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
+						u8 gate,
+						struct nfc_target *target)
+{
+	int r;
+	struct sk_buff *nfcid2_skb = NULL, *nfcid1_skb;
+
+	if (gate == ST21NFCA_RF_READER_F_GATE) {
+		r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_RF_READER_F_NFCID2, &nfcid2_skb);
+		if (r < 0)
+			goto exit;
+
+		if (nfcid2_skb->len > NFC_SENSF_RES_MAXSIZE) {
+			r = -EPROTO;
+			goto exit;
+		}
+
+		/*
+		 * - After the recepton of polling response for type F frame
+		 * at 212 or 424 Kbit/s, NFCID2 registry parameters will be
+		 * updated.
+		 * - After the reception of SEL_RES with NFCIP-1 compliant bit
+		 * set for type A frame NFCID1 will be updated
+		 */
+		if (nfcid2_skb->len > 0) {
+			/* P2P in type F */
+			memcpy(target->sensf_res, nfcid2_skb->data,
+				nfcid2_skb->len);
+			target->sensf_res_len = nfcid2_skb->len;
+			/* NFC Forum Digital Protocol Table 44 */
+			if (target->sensf_res[0] == 0x01 &&
+			    target->sensf_res[1] == 0xfe)
+				target->supported_protocols =
+							NFC_PROTO_NFC_DEP_MASK;
+			else
+				target->supported_protocols =
+							NFC_PROTO_FELICA_MASK;
+		} else {
+			/* P2P in type A */
+			r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					ST21NFCA_RF_READER_F_NFCID1,
+					&nfcid1_skb);
+			if (r < 0)
+				goto exit;
+
+			if (nfcid1_skb->len > NFC_NFCID1_MAXSIZE) {
+				r = -EPROTO;
+				goto exit;
+			}
+			memcpy(target->sensf_res, nfcid1_skb->data,
+				nfcid1_skb->len);
+			target->sensf_res_len = nfcid1_skb->len;
+			target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+		}
+		target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE;
+	}
+	r = 1;
+exit:
+	kfree_skb(nfcid2_skb);
+	return r;
+}
+
 #define ST21NFCA_CB_TYPE_READER_ISO15693 1
 static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb,
 					  int err)
@@ -541,6 +750,9 @@ static int st21nfca_hci_im_transceive(st
 
 	switch (target->hci_reader_gate) {
 	case ST21NFCA_RF_READER_F_GATE:
+		if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK)
+			return st21nfca_im_send_dep_req(hdev, skb);
+
 		*skb_push(skb, 1) = 0x1a;
 		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
 					      ST21NFCA_WR_XCHG_DATA, skb->data,
@@ -569,6 +781,11 @@ static int st21nfca_hci_im_transceive(st
 	}
 }
 
+static int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	return st21nfca_tm_send_dep_res(hdev, skb);
+}
+
 static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
 				       struct nfc_target *target)
 {
@@ -594,6 +811,50 @@ static int st21nfca_hci_check_presence(s
 	}
 }
 
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
+				       u8 event, struct sk_buff *skb)
+{
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("hci event: %d\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CARD_ACTIVATED:
+		if (gate == ST21NFCA_RF_CARD_F_GATE)
+			info->dep_info.curr_nfc_dep_pni = 0;
+		break;
+	case ST21NFCA_EVT_CARD_DEACTIVATED:
+		break;
+	case ST21NFCA_EVT_FIELD_ON:
+		break;
+	case ST21NFCA_EVT_FIELD_OFF:
+		break;
+	case ST21NFCA_EVT_SEND_DATA:
+		if (gate == ST21NFCA_RF_CARD_F_GATE) {
+			r = st21nfca_tm_event_send_data(hdev, skb, gate);
+			if (r < 0)
+				goto exit;
+			return 0;
+		} else {
+			info->dep_info.curr_nfc_dep_pni = 0;
+			return 1;
+		}
+		break;
+	default:
+		return 1;
+	}
+	kfree_skb(skb);
+	return 0;
+exit:
+	return r;
+}
+
 static struct nfc_hci_ops st21nfca_hci_ops = {
 	.open = st21nfca_hci_open,
 	.close = st21nfca_hci_close,
@@ -601,9 +862,15 @@ static struct nfc_hci_ops st21nfca_hci_o
 	.hci_ready = st21nfca_hci_ready,
 	.xmit = st21nfca_hci_xmit,
 	.start_poll = st21nfca_hci_start_poll,
+	.stop_poll = st21nfca_hci_stop_poll,
+	.dep_link_up = st21nfca_hci_dep_link_up,
+	.dep_link_down = st21nfca_hci_dep_link_down,
 	.target_from_gate = st21nfca_hci_target_from_gate,
+	.complete_target_discovered = st21nfca_hci_complete_target_discovered,
 	.im_transceive = st21nfca_hci_im_transceive,
+	.tm_send = st21nfca_hci_tm_send,
 	.check_presence = st21nfca_hci_check_presence,
+	.event_received = st21nfca_hci_event_received,
 };
 
 int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
@@ -648,7 +915,8 @@ int st21nfca_hci_probe(void *phy_id, str
 	    NFC_PROTO_FELICA_MASK |
 	    NFC_PROTO_ISO14443_MASK |
 	    NFC_PROTO_ISO14443_B_MASK |
-	    NFC_PROTO_ISO15693_MASK;
+	    NFC_PROTO_ISO15693_MASK |
+	    NFC_PROTO_NFC_DEP_MASK;
 
 	set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);
 
@@ -671,6 +939,7 @@ int st21nfca_hci_probe(void *phy_id, str
 		goto err_regdev;
 
 	*hdev = info->hdev;
+	st21nfca_dep_init(info->hdev);
 
 	return 0;
 
@@ -688,6 +957,7 @@ void st21nfca_hci_remove(struct nfc_hci_
 {
 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 
+	st21nfca_dep_deinit(hdev);
 	nfc_hci_unregister_device(hdev);
 	nfc_hci_free_device(hdev);
 	kfree(info);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca_dep.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca_dep.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca_dep.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca_dep.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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 <net/nfc/hci.h>
+
+#include "st21nfca.h"
+#include "st21nfca_dep.h"
+
+#define ST21NFCA_NFCIP1_INITIATOR 0x00
+#define ST21NFCA_NFCIP1_REQ 0xd4
+#define ST21NFCA_NFCIP1_RES 0xd5
+#define ST21NFCA_NFCIP1_ATR_REQ 0x00
+#define ST21NFCA_NFCIP1_ATR_RES 0x01
+#define ST21NFCA_NFCIP1_PSL_REQ 0x04
+#define ST21NFCA_NFCIP1_PSL_RES 0x05
+#define ST21NFCA_NFCIP1_DEP_REQ 0x06
+#define ST21NFCA_NFCIP1_DEP_RES 0x07
+
+#define ST21NFCA_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
+#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
+#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
+#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10
+
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+
+#define ST21NFCA_NFC_DEP_PFB_I_PDU          0x00
+#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU   0x40
+#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
+
+#define ST21NFCA_ATR_REQ_MIN_SIZE 17
+#define ST21NFCA_ATR_REQ_MAX_SIZE 65
+#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define ST21NFCA_GB_BIT  0x02
+
+#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
+#define ST21NFCA_EVT_READER_F_BITRATE 0x13
+#define	ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
+#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07)
+#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4)
+#define ST21NFCA_CARD_BITRATE_212 0x01
+#define ST21NFCA_CARD_BITRATE_424 0x02
+
+#define ST21NFCA_DEFAULT_TIMEOUT 0x0a
+
+
+#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \
+				 __LINE__, req)
+
+struct st21nfca_atr_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_atr_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 to;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_psl_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+	u8 brs;
+	u8 fsl;
+} __packed;
+
+struct st21nfca_psl_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+} __packed;
+
+struct st21nfca_dep_req_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 pfb;
+	u8 did;
+	u8 nad;
+} __packed;
+
+static void st21nfca_tx_work(struct work_struct *work)
+{
+	struct st21nfca_hci_info *info = container_of(work,
+						struct st21nfca_hci_info,
+						dep_info.tx_work);
+
+	struct nfc_dev *dev;
+	struct sk_buff *skb;
+	if (info) {
+		dev = info->hdev->ndev;
+		skb = info->dep_info.tx_pending;
+
+		device_lock(&dev->dev);
+
+		nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
+							ST21NFCA_WR_XCHG_DATA,
+							skb->data, skb->len,
+							info->async_cb, info);
+		device_unlock(&dev->dev);
+		kfree_skb(skb);
+	}
+}
+
+static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
+						struct sk_buff *skb)
+{
+	info->dep_info.tx_pending = skb;
+	schedule_work(&info->dep_info.tx_work);
+}
+
+static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_atr_req *atr_req)
+{
+	struct st21nfca_atr_res *atr_res;
+	struct sk_buff *skb;
+	size_t gb_len;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	gb_len = atr_req->length - sizeof(struct st21nfca_atr_req);
+	skb = alloc_skb(atr_req->length + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put(skb, sizeof(struct st21nfca_atr_res));
+
+	atr_res = (struct st21nfca_atr_res *)skb->data;
+	memset(atr_res, 0, sizeof(struct st21nfca_atr_res));
+
+	atr_res->length = atr_req->length + 1;
+	atr_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES;
+
+	memcpy(atr_res->nfcid3, atr_req->nfcid3, 6);
+	atr_res->bsi = 0x00;
+	atr_res->bri = 0x00;
+	atr_res->to = ST21NFCA_DEFAULT_TIMEOUT;
+	atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+
+	if (gb_len) {
+		skb_put(skb, gb_len);
+
+		atr_res->ppi |= ST21NFCA_GB_BIT;
+		memcpy(atr_res->gbi, atr_req->gbi, gb_len);
+		r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
+						  gb_len);
+		if (r < 0)
+			return r;
+	}
+
+	info->dep_info.curr_nfc_dep_pni = 0;
+
+	return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+}
+
+static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_atr_req *atr_req;
+	size_t gb_len;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+	if (IS_ERR(skb)) {
+		r = PTR_ERR(skb);
+		goto exit;
+	}
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+
+	r = st21nfca_tm_send_atr_res(hdev, atr_req);
+	if (r)
+		goto exit;
+
+	gb_len = skb->len - sizeof(struct st21nfca_atr_req);
+
+	r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+			      NFC_COMM_PASSIVE, atr_req->gbi, gb_len);
+	if (r)
+		goto exit;
+
+	r = 0;
+
+exit:
+	return r;
+}
+
+static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_psl_req *psl_req)
+{
+	struct st21nfca_psl_res *psl_res;
+	struct sk_buff *skb;
+	u8 bitrate[2] = {0, 0};
+
+	int r;
+
+	skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+	skb_put(skb, sizeof(struct st21nfca_psl_res));
+
+	psl_res = (struct st21nfca_psl_res *)skb->data;
+
+	psl_res->length = sizeof(struct st21nfca_psl_res);
+	psl_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES;
+	psl_res->did = psl_req->did;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+
+	/*
+	 * ST21NFCA only support P2P passive.
+	 * PSL_REQ BRS value != 0 has only a meaning to
+	 * change technology to type F.
+	 * We change to BITRATE 424Kbits.
+	 * In other case switch to BITRATE 106Kbits.
+	 */
+	if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) &&
+	    ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) {
+		bitrate[0] = ST21NFCA_CARD_BITRATE_424;
+		bitrate[1] = ST21NFCA_CARD_BITRATE_424;
+	}
+
+	/* Send an event to change bitrate change event to card f */
+	return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+			ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
+}
+
+static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_psl_req *psl_req;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+	if (IS_ERR(skb)) {
+		r = PTR_ERR(skb);
+		skb = NULL;
+		goto exit;
+	}
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	psl_req = (struct st21nfca_psl_req *)skb->data;
+
+	if (skb->len < sizeof(struct st21nfca_psl_req)) {
+		r = -EIO;
+		goto exit;
+	}
+
+	r = st21nfca_tm_send_psl_res(hdev, psl_req);
+exit:
+	return r;
+}
+
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_RES;
+	*skb_push(skb, 1) = skb->len;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	kfree_skb(skb);
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_send_dep_res);
+
+static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_dep_req_res *dep_req;
+	u8 size;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb_trim(skb, skb->len - 1);
+	if (IS_ERR(skb)) {
+		r = PTR_ERR(skb);
+		skb = NULL;
+		goto exit;
+	}
+
+	size = 4;
+
+	dep_req = (struct st21nfca_dep_req_res *)skb->data;
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+		size++;
+	if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb))
+		size++;
+
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	/* Receiving DEP_REQ - Decoding */
+	switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+	case ST21NFCA_NFC_DEP_PFB_I_PDU:
+		info->dep_info.curr_nfc_dep_pni =
+				ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb);
+		break;
+	case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+		pr_err("Received a ACK/NACK PDU\n");
+		break;
+	case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+		pr_err("Received a SUPERVISOR PDU\n");
+		break;
+	}
+
+	if (IS_ERR(skb)) {
+		r = PTR_ERR(skb);
+		skb = NULL;
+		goto exit;
+	}
+
+	skb_pull(skb, size);
+
+	return nfc_tm_data_received(hdev->ndev, skb);
+exit:
+	return r;
+}
+
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+				u8 gate)
+{
+	u8 cmd0, cmd1;
+	int r;
+
+	cmd0 = skb->data[1];
+	switch (cmd0) {
+	case ST21NFCA_NFCIP1_REQ:
+		cmd1 = skb->data[2];
+		switch (cmd1) {
+		case ST21NFCA_NFCIP1_ATR_REQ:
+			r = st21nfca_tm_recv_atr_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_PSL_REQ:
+			r = st21nfca_tm_recv_psl_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_DEP_REQ:
+			r = st21nfca_tm_recv_dep_req(hdev, skb);
+			break;
+		default:
+			return 1;
+		}
+	default:
+		return 1;
+	}
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_event_send_data);
+
+static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
+				     u8 bri, u8 lri)
+{
+	struct sk_buff *skb;
+	struct st21nfca_psl_req *psl_req;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL);
+	if (!skb)
+		return;
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_psl_req));
+	psl_req = (struct st21nfca_psl_req *) skb->data;
+
+	psl_req->length = sizeof(struct st21nfca_psl_req);
+	psl_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ;
+	psl_req->did = did;
+	psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03);
+	psl_req->fsl = lri;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	st21nfca_im_send_pdu(info, skb);
+
+	kfree_skb(skb);
+}
+
+#define ST21NFCA_CB_TYPE_READER_F 1
+static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_atr_res *atr_res;
+	int r;
+
+	if (err != 0)
+		return;
+
+	if (IS_ERR(skb))
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		skb_trim(skb, skb->len - 1);
+		atr_res = (struct st21nfca_atr_res *)skb->data;
+		r = nfc_set_remote_general_bytes(info->hdev->ndev,
+				atr_res->gbi,
+				skb->len - sizeof(struct st21nfca_atr_res));
+		if (r < 0)
+			return;
+
+		if (atr_res->to >= 0x0e)
+			info->dep_info.to = 0x0e;
+		else
+			info->dep_info.to = atr_res->to + 1;
+
+		info->dep_info.to |= 0x10;
+
+		r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx,
+					NFC_COMM_PASSIVE, NFC_RF_INITIATOR);
+		if (r < 0)
+			return;
+
+		info->dep_info.curr_nfc_dep_pni = 0;
+		if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri)
+			st21nfca_im_send_psl_req(info->hdev, atr_res->did,
+						atr_res->bsi, atr_res->bri,
+						ST21NFCA_PP2LRI(atr_res->ppi));
+		break;
+	default:
+		if (err == 0)
+			kfree_skb(skb);
+		break;
+	}
+}
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
+{
+	struct sk_buff *skb;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	struct st21nfca_atr_req *atr_req;
+	struct nfc_target *target;
+	uint size;
+
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+	size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len;
+	if (size > ST21NFCA_ATR_REQ_MAX_SIZE) {
+		PROTOCOL_ERR("14.6.1.1");
+		return -EINVAL;
+	}
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_atr_req));
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+	memset(atr_req, 0, sizeof(struct st21nfca_atr_req));
+
+	atr_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ;
+	memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
+	target = hdev->ndev->targets;
+
+	if (target->sensf_res)
+		memcpy(atr_req->nfcid3, target->sensf_res,
+				target->sensf_res_len);
+	else
+		get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
+
+	atr_req->did = 0x0;
+
+	atr_req->bsi = 0x00;
+	atr_req->bri = 0x00;
+	atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+	if (gb_len) {
+		atr_req->ppi |= ST21NFCA_GB_BIT;
+		memcpy(skb_put(skb, gb_len), gb, gb_len);
+	}
+	atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_atr_res_cb;
+	info->dep_info.bri = atr_req->bri;
+	info->dep_info.bsi = atr_req->bsi;
+	info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi);
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_WR_XCHG_DATA, skb->data,
+				skb->len, info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_atr_req);
+
+static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_dep_req_res *dep_res;
+
+	int size;
+
+	if (err != 0)
+		return;
+
+	if (IS_ERR(skb))
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		dep_res = (struct st21nfca_dep_req_res *)skb->data;
+
+		size = 3;
+		if (skb->len < size)
+			goto exit;
+
+		if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb))
+			size++;
+		if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb))
+			size++;
+
+		if (skb->len < size)
+			goto exit;
+
+		skb_trim(skb, skb->len - 1);
+
+		/* Receiving DEP_REQ - Decoding */
+		switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) {
+		case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+			pr_err("Received a ACK/NACK PDU\n");
+		case ST21NFCA_NFC_DEP_PFB_I_PDU:
+			info->dep_info.curr_nfc_dep_pni =
+			    ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1);
+			size++;
+			skb_pull(skb, size);
+			nfc_tm_data_received(info->hdev->ndev, skb);
+			break;
+		case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+			pr_err("Received a SUPERVISOR PDU\n");
+			skb_pull(skb, size);
+			*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+			*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+			*skb_push(skb, 1) = skb->len;
+			*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+			st21nfca_im_send_pdu(info, skb);
+			break;
+		}
+
+		return;
+	default:
+		break;
+	}
+
+exit:
+	if (err == 0)
+		kfree_skb(skb);
+}
+
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_dep_res_cb;
+
+	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+	*skb_push(skb, 1) = skb->len;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				      ST21NFCA_WR_XCHG_DATA,
+				      skb->data, skb->len,
+				      info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_dep_req);
+
+void st21nfca_dep_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work);
+	info->dep_info.curr_nfc_dep_pni = 0;
+	info->dep_info.idx = 0;
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+}
+EXPORT_SYMBOL(st21nfca_dep_init);
+
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	cancel_work_sync(&info->dep_info.tx_work);
+}
+EXPORT_SYMBOL(st21nfca_dep_deinit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca_dep.h linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca_dep.h
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca_dep.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca_dep.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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 __ST21NFCA_DEP_H
+#define __ST21NFCA_DEP_H
+
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+
+struct st21nfca_dep_info {
+	struct sk_buff *tx_pending;
+	struct work_struct tx_work;
+	u8 curr_nfc_dep_pni;
+	u32 idx;
+	u8 to;
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 lri;
+} __packed;
+
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+				u8 gate);
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+void st21nfca_dep_init(struct nfc_hci_dev *hdev);
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
+#endif /* __ST21NFCA_DEP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca.h linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca.h
--- linux-libre-3.16-gnu/drivers/nfc/st21nfca/st21nfca.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfca/st21nfca.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,8 @@
 
 #include <net/nfc/hci.h>
 
+#include "st21nfca_dep.h"
+
 #define HCI_MODE 0
 
 /* framing in HCI mode */
@@ -73,7 +75,8 @@ struct st21nfca_hci_info {
 	data_exchange_cb_t async_cb;
 	void *async_cb_context;
 
-} __packed;
+	struct st21nfca_dep_info dep_info;
+};
 
 /* Reader RF commands */
 #define ST21NFCA_WR_XCHG_DATA            0x10
@@ -83,5 +86,26 @@ struct st21nfca_hci_info {
 #define ST21NFCA_RF_READER_F_DATARATE_106 0x01
 #define ST21NFCA_RF_READER_F_DATARATE_212 0x02
 #define ST21NFCA_RF_READER_F_DATARATE_424 0x04
+#define ST21NFCA_RF_READER_F_POL_REQ    0x02
+#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT    0xffff0000
+#define ST21NFCA_RF_READER_F_NFCID2 0x03
+#define ST21NFCA_RF_READER_F_NFCID1 0x04
+#define ST21NFCA_RF_READER_F_SENS_RES 0x05
+
+#define ST21NFCA_RF_CARD_F_GATE 0x24
+#define ST21NFCA_RF_CARD_F_MODE 0x01
+#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04
+#define ST21NFCA_RF_CARD_F_NFCID1 0x05
+#define ST21NFCA_RF_CARD_F_SENS_RES 0x06
+#define ST21NFCA_RF_CARD_F_SEL_RES 0x07
+#define ST21NFCA_RF_CARD_F_DATARATE 0x08
+#define ST21NFCA_RF_CARD_F_DATARATE_106 0x00
+#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01
+
+#define ST21NFCA_EVT_SEND_DATA 0x10
+#define ST21NFCA_EVT_FIELD_ON 0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
+#define ST21NFCA_EVT_FIELD_OFF 0x14
 
 #endif /* __LOCAL_ST21NFCA_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/i2c.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/i2c.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,462 @@
+/*
+ * I2C Link Layer for ST21NFCB NCI based Driver
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/crc-ccitt.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/nfc.h>
+#include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/platform_data/st21nfcb.h>
+
+#include <net/nfc/nci.h>
+#include <net/nfc/llc.h>
+#include <net/nfc/nfc.h>
+
+#include "ndlc.h"
+
+#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
+
+/* ndlc header */
+#define ST21NFCB_FRAME_HEADROOM	1
+#define ST21NFCB_FRAME_TAILROOM 0
+
+#define ST21NFCB_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
+#define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
+
+#define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c"
+
+static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = {
+	{ST21NFCB_NCI_DRIVER_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table);
+
+struct st21nfcb_i2c_phy {
+	struct i2c_client *i2c_dev;
+	struct llt_ndlc *ndlc;
+
+	unsigned int gpio_irq;
+	unsigned int gpio_reset;
+	unsigned int irq_polarity;
+
+	int powered;
+
+	/*
+	 * < 0 if hardware error occured (e.g. i2c err)
+	 * and prevents normal operation.
+	 */
+	int hard_fault;
+};
+
+#define I2C_DUMP_SKB(info, skb)					\
+do {								\
+	pr_debug("%s:\n", info);				\
+	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
+		       16, 1, (skb)->data, (skb)->len, 0);	\
+} while (0)
+
+static int st21nfcb_nci_i2c_enable(void *phy_id)
+{
+	struct st21nfcb_i2c_phy *phy = phy_id;
+
+	gpio_set_value(phy->gpio_reset, 0);
+	usleep_range(10000, 15000);
+	gpio_set_value(phy->gpio_reset, 1);
+	phy->powered = 1;
+	usleep_range(80000, 85000);
+
+	return 0;
+}
+
+static void st21nfcb_nci_i2c_disable(void *phy_id)
+{
+	struct st21nfcb_i2c_phy *phy = phy_id;
+
+	pr_info("\n");
+
+	phy->powered = 0;
+	/* reset chip in order to flush clf */
+	gpio_set_value(phy->gpio_reset, 0);
+	usleep_range(10000, 15000);
+	gpio_set_value(phy->gpio_reset, 1);
+}
+
+static void st21nfcb_nci_remove_header(struct sk_buff *skb)
+{
+	skb_pull(skb, ST21NFCB_FRAME_HEADROOM);
+}
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
+{
+	int r = -1;
+	struct st21nfcb_i2c_phy *phy = phy_id;
+	struct i2c_client *client = phy->i2c_dev;
+
+	I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);
+
+	if (phy->hard_fault != 0)
+		return phy->hard_fault;
+
+	r = i2c_master_send(client, skb->data, skb->len);
+	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
+		usleep_range(1000, 4000);
+		r = i2c_master_send(client, skb->data, skb->len);
+	}
+
+	if (r >= 0) {
+		if (r != skb->len)
+			r = -EREMOTEIO;
+		else
+			r = 0;
+	}
+
+	st21nfcb_nci_remove_header(skb);
+
+	return r;
+}
+
+/*
+ * Reads an ndlc frame and returns it in a newly allocated sk_buff.
+ * returns:
+ * frame size : if received frame is complete (find ST21NFCB_SOF_EOF at
+ * end of read)
+ * -EAGAIN : if received frame is incomplete (not find ST21NFCB_SOF_EOF
+ * at end of read)
+ * -EREMOTEIO : i2c read error (fatal)
+ * -EBADMSG : frame was incorrect and discarded
+ * (value returned from st21nfcb_nci_i2c_repack)
+ * -EIO : if no ST21NFCB_SOF_EOF is found after reaching
+ * the read length end sequence
+ */
+static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
+				 struct sk_buff **skb)
+{
+	int r;
+	u8 len;
+	u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE];
+	struct i2c_client *client = phy->i2c_dev;
+
+	r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
+		usleep_range(1000, 4000);
+		r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+	} else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) {
+		nfc_err(&client->dev, "cannot read ndlc & nci header\n");
+		return -EREMOTEIO;
+	}
+
+	len = be16_to_cpu(*(__be16 *) (buf + 2));
+	if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
+		nfc_err(&client->dev, "invalid frame len\n");
+		return -EBADMSG;
+	}
+
+	*skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
+	if (*skb == NULL)
+		return -ENOMEM;
+
+	skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
+	skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
+	memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+
+	if (!len)
+		return 0;
+
+	r = i2c_master_recv(client, buf, len);
+	if (r != len) {
+		kfree_skb(*skb);
+		return -EREMOTEIO;
+	}
+
+	skb_put(*skb, len);
+	memcpy((*skb)->data + ST21NFCB_NCI_I2C_MIN_SIZE, buf, len);
+
+	I2C_DUMP_SKB("i2c frame read", *skb);
+
+	return 0;
+}
+
+/*
+ * Reads an ndlc frame from the chip.
+ *
+ * On ST21NFCB, IRQ goes in idle state when read starts.
+ */
+static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
+{
+	struct st21nfcb_i2c_phy *phy = phy_id;
+	struct i2c_client *client;
+	struct sk_buff *skb = NULL;
+	int r;
+
+	if (!phy || irq != phy->i2c_dev->irq) {
+		WARN_ON_ONCE(1);
+		return IRQ_NONE;
+	}
+
+	client = phy->i2c_dev;
+	dev_dbg(&client->dev, "IRQ\n");
+
+	if (phy->hard_fault)
+		return IRQ_HANDLED;
+
+	if (!phy->powered) {
+		st21nfcb_nci_i2c_disable(phy);
+		return IRQ_HANDLED;
+	}
+
+	r = st21nfcb_nci_i2c_read(phy, &skb);
+	if (r == -EREMOTEIO) {
+		phy->hard_fault = r;
+                ndlc_recv(phy->ndlc, NULL);
+		return IRQ_HANDLED;
+	} else if (r == -ENOMEM || r == -EBADMSG) {
+		return IRQ_HANDLED;
+	}
+
+	ndlc_recv(phy->ndlc, skb);
+
+	return IRQ_HANDLED;
+}
+
+static struct nfc_phy_ops i2c_phy_ops = {
+	.write = st21nfcb_nci_i2c_write,
+	.enable = st21nfcb_nci_i2c_enable,
+	.disable = st21nfcb_nci_i2c_disable,
+};
+
+#ifdef CONFIG_OF
+static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+{
+	struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+	struct device_node *pp;
+	int gpio;
+	int r;
+
+	pp = client->dev.of_node;
+	if (!pp)
+		return -ENODEV;
+
+	/* Get GPIO from device tree */
+	gpio = of_get_named_gpio(pp, "reset-gpios", 0);
+	if (gpio < 0) {
+		nfc_err(&client->dev,
+			"Failed to retrieve reset-gpios from device tree\n");
+		return gpio;
+	}
+
+	/* GPIO request and configuration */
+	r = devm_gpio_request(&client->dev, gpio, "clf_reset");
+	if (r) {
+		nfc_err(&client->dev, "Failed to request reset pin\n");
+		return -ENODEV;
+	}
+
+	r = gpio_direction_output(gpio, 1);
+	if (r) {
+		nfc_err(&client->dev,
+			"Failed to set reset pin direction as output\n");
+		return -ENODEV;
+	}
+	phy->gpio_reset = gpio;
+
+	/* IRQ */
+	r = irq_of_parse_and_map(pp, 0);
+	if (r < 0) {
+		nfc_err(&client->dev,
+				"Unable to get irq, error: %d\n", r);
+		return r;
+	}
+
+	phy->irq_polarity = irq_get_trigger_type(r);
+	client->irq = r;
+
+	return 0;
+}
+#else
+static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+{
+	return -ENODEV;
+}
+#endif
+
+static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
+{
+	struct st21nfcb_nfc_platform_data *pdata;
+	struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+	int r;
+	int irq;
+
+	pdata = client->dev.platform_data;
+	if (pdata == NULL) {
+		nfc_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	/* store for later use */
+	phy->gpio_irq = pdata->gpio_irq;
+	phy->gpio_reset = pdata->gpio_reset;
+	phy->irq_polarity = pdata->irq_polarity;
+
+	r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up");
+	if (r) {
+		pr_err("%s : gpio_request failed\n", __FILE__);
+		return -ENODEV;
+	}
+
+	r = gpio_direction_input(phy->gpio_irq);
+	if (r) {
+		pr_err("%s : gpio_direction_input failed\n", __FILE__);
+		return -ENODEV;
+	}
+
+	r = devm_gpio_request(&client->dev,
+			      phy->gpio_reset, "clf_reset");
+	if (r) {
+		pr_err("%s : reset gpio_request failed\n", __FILE__);
+		return -ENODEV;
+	}
+
+	r = gpio_direction_output(phy->gpio_reset, 1);
+	if (r) {
+		pr_err("%s : reset gpio_direction_output failed\n",
+			__FILE__);
+		return -ENODEV;
+	}
+
+	/* IRQ */
+	irq = gpio_to_irq(phy->gpio_irq);
+	if (irq < 0) {
+		nfc_err(&client->dev,
+			"Unable to get irq number for GPIO %d error %d\n",
+			phy->gpio_irq, r);
+		return -ENODEV;
+	}
+	client->irq = irq;
+
+	return 0;
+}
+
+static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct st21nfcb_i2c_phy *phy;
+	struct st21nfcb_nfc_platform_data *pdata;
+	int r;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+	dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
+		return -ENODEV;
+	}
+
+	phy = devm_kzalloc(&client->dev, sizeof(struct st21nfcb_i2c_phy),
+			   GFP_KERNEL);
+	if (!phy) {
+		nfc_err(&client->dev,
+			"Cannot allocate memory for st21nfcb i2c phy.\n");
+		return -ENOMEM;
+	}
+
+	phy->i2c_dev = client;
+
+	i2c_set_clientdata(client, phy);
+
+	pdata = client->dev.platform_data;
+	if (!pdata && client->dev.of_node) {
+		r = st21nfcb_nci_i2c_of_request_resources(client);
+		if (r) {
+			nfc_err(&client->dev, "No platform data\n");
+			return r;
+		}
+	} else if (pdata) {
+		r = st21nfcb_nci_i2c_request_resources(client);
+		if (r) {
+			nfc_err(&client->dev,
+				"Cannot get platform resources\n");
+			return r;
+		}
+	} else {
+		nfc_err(&client->dev,
+			"st21nfcb platform resources not available\n");
+		return -ENODEV;
+	}
+
+	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+				st21nfcb_nci_irq_thread_fn,
+				phy->irq_polarity | IRQF_ONESHOT,
+				ST21NFCB_NCI_DRIVER_NAME, phy);
+	if (r < 0) {
+		nfc_err(&client->dev, "Unable to register IRQ handler\n");
+		return r;
+	}
+
+	return ndlc_probe(phy, &i2c_phy_ops, &client->dev,
+			ST21NFCB_FRAME_HEADROOM, ST21NFCB_FRAME_TAILROOM,
+			&phy->ndlc);
+}
+
+static int st21nfcb_nci_i2c_remove(struct i2c_client *client)
+{
+	struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	ndlc_remove(phy->ndlc);
+
+	if (phy->powered)
+		st21nfcb_nci_i2c_disable(phy);
+
+	return 0;
+}
+
+static const struct of_device_id of_st21nfcb_i2c_match[] = {
+	{ .compatible = "st,st21nfcb_i2c", },
+	{}
+};
+
+static struct i2c_driver st21nfcb_nci_i2c_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = ST21NFCB_NCI_I2C_DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(of_st21nfcb_i2c_match),
+	},
+	.probe = st21nfcb_nci_i2c_probe,
+	.id_table = st21nfcb_nci_i2c_id_table,
+	.remove = st21nfcb_nci_i2c_remove,
+};
+
+module_i2c_driver(st21nfcb_nci_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/Kconfig linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/Kconfig
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,22 @@
+config NFC_ST21NFCB
+	tristate "STMicroelectronics ST21NFCB NFC driver"
+	depends on NFC_NCI
+	default n
+	---help---
+	  STMicroelectronics ST21NFCB core driver. It implements the chipset
+	  NCI logic and hooks into the NFC kernel APIs. Physical layers will
+	  register against it.
+
+	  To compile this driver as a module, choose m here. The module will
+	  be called st21nfcb.
+	  Say N if unsure.
+
+config NFC_ST21NFCB_I2C
+	tristate "NFC ST21NFCB i2c support"
+	depends on NFC_ST21NFCB && I2C
+	---help---
+	  This module adds support for the STMicroelectronics st21nfcb i2c interface.
+	  Select this if your platform is using the i2c bus.
+
+	  If you choose to build a module, it'll be called st21nfcb_i2c.
+	  Say N if unsure.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/Makefile linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/Makefile
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+#
+# Makefile for ST21NFCB NCI based NFC driver
+#
+
+st21nfcb_nci-objs = ndlc.o st21nfcb.o
+obj-$(CONFIG_NFC_ST21NFCB)     += st21nfcb_nci.o
+
+st21nfcb_i2c-objs = i2c.o
+obj-$(CONFIG_NFC_ST21NFCB_I2C) += st21nfcb_i2c.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/ndlc.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/ndlc.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/ndlc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/ndlc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,298 @@
+/*
+ * Low Level Transport (NDLC) Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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/sched.h>
+#include <net/nfc/nci_core.h>
+
+#include "ndlc.h"
+#include "st21nfcb.h"
+
+#define NDLC_TIMER_T1		100
+#define NDLC_TIMER_T1_WAIT	400
+#define NDLC_TIMER_T2		1200
+
+#define PCB_TYPE_DATAFRAME		0x80
+#define PCB_TYPE_SUPERVISOR		0xc0
+#define PCB_TYPE_MASK			PCB_TYPE_SUPERVISOR
+
+#define PCB_SYNC_ACK			0x20
+#define PCB_SYNC_NACK			0x10
+#define PCB_SYNC_WAIT			0x30
+#define PCB_SYNC_NOINFO			0x00
+#define PCB_SYNC_MASK			PCB_SYNC_WAIT
+
+#define PCB_DATAFRAME_RETRANSMIT_YES	0x00
+#define PCB_DATAFRAME_RETRANSMIT_NO	0x04
+#define PCB_DATAFRAME_RETRANSMIT_MASK	PCB_DATAFRAME_RETRANSMIT_NO
+
+#define PCB_SUPERVISOR_RETRANSMIT_YES	0x00
+#define PCB_SUPERVISOR_RETRANSMIT_NO	0x02
+#define PCB_SUPERVISOR_RETRANSMIT_MASK	PCB_SUPERVISOR_RETRANSMIT_NO
+
+#define PCB_FRAME_CRC_INFO_PRESENT	0x08
+#define PCB_FRAME_CRC_INFO_NOTPRESENT	0x00
+#define PCB_FRAME_CRC_INFO_MASK		PCB_FRAME_CRC_INFO_PRESENT
+
+#define NDLC_DUMP_SKB(info, skb)                                 \
+do {                                                             \
+	pr_debug("%s:\n", info);                                 \
+	print_hex_dump(KERN_DEBUG, "ndlc: ", DUMP_PREFIX_OFFSET, \
+			16, 1, skb->data, skb->len, 0);          \
+} while (0)
+
+int ndlc_open(struct llt_ndlc *ndlc)
+{
+	/* toggle reset pin */
+	ndlc->ops->enable(ndlc->phy_id);
+	return 0;
+}
+EXPORT_SYMBOL(ndlc_open);
+
+void ndlc_close(struct llt_ndlc *ndlc)
+{
+	/* toggle reset pin */
+	ndlc->ops->disable(ndlc->phy_id);
+}
+EXPORT_SYMBOL(ndlc_close);
+
+int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb)
+{
+	/* add ndlc header */
+	u8 pcb = PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO |
+		PCB_FRAME_CRC_INFO_NOTPRESENT;
+
+	*skb_push(skb, 1) = pcb;
+	skb_queue_tail(&ndlc->send_q, skb);
+
+	schedule_work(&ndlc->sm_work);
+
+	return 0;
+}
+EXPORT_SYMBOL(ndlc_send);
+
+static void llt_ndlc_send_queue(struct llt_ndlc *ndlc)
+{
+	struct sk_buff *skb;
+	int r;
+	unsigned long time_sent;
+
+	if (ndlc->send_q.qlen)
+		pr_debug("sendQlen=%d unackQlen=%d\n",
+			 ndlc->send_q.qlen, ndlc->ack_pending_q.qlen);
+
+	while (ndlc->send_q.qlen) {
+		skb = skb_dequeue(&ndlc->send_q);
+		NDLC_DUMP_SKB("ndlc frame written", skb);
+		r = ndlc->ops->write(ndlc->phy_id, skb);
+		if (r < 0) {
+			ndlc->hard_fault = r;
+			break;
+		}
+		time_sent = jiffies;
+		*(unsigned long *)skb->cb = time_sent;
+
+		skb_queue_tail(&ndlc->ack_pending_q, skb);
+
+		/* start timer t1 for ndlc aknowledge */
+		ndlc->t1_active = true;
+		mod_timer(&ndlc->t1_timer, time_sent +
+			msecs_to_jiffies(NDLC_TIMER_T1));
+	}
+}
+
+static void llt_ndlc_requeue_data_pending(struct llt_ndlc *ndlc)
+{
+	struct sk_buff *skb;
+	u8 pcb;
+
+	while ((skb = skb_dequeue_tail(&ndlc->ack_pending_q))) {
+		pcb = skb->data[0];
+		switch (pcb & PCB_TYPE_MASK) {
+		case PCB_TYPE_SUPERVISOR:
+			skb->data[0] = (pcb & ~PCB_SUPERVISOR_RETRANSMIT_MASK) |
+				PCB_SUPERVISOR_RETRANSMIT_YES;
+			break;
+		case PCB_TYPE_DATAFRAME:
+			skb->data[0] = (pcb & ~PCB_DATAFRAME_RETRANSMIT_MASK) |
+				PCB_DATAFRAME_RETRANSMIT_YES;
+			break;
+		default:
+			pr_err("UNKNOWN Packet Control Byte=%d\n", pcb);
+			kfree_skb(skb);
+			break;
+		}
+		skb_queue_head(&ndlc->send_q, skb);
+	}
+}
+
+static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc)
+{
+	struct sk_buff *skb;
+	u8 pcb;
+	unsigned long time_sent;
+
+	if (ndlc->rcv_q.qlen)
+		pr_debug("rcvQlen=%d\n", ndlc->rcv_q.qlen);
+
+	while ((skb = skb_dequeue(&ndlc->rcv_q)) != NULL) {
+		pcb = skb->data[0];
+		skb_pull(skb, 1);
+		if ((pcb & PCB_TYPE_MASK) == PCB_TYPE_SUPERVISOR) {
+			switch (pcb & PCB_SYNC_MASK) {
+			case PCB_SYNC_ACK:
+				del_timer_sync(&ndlc->t1_timer);
+				del_timer_sync(&ndlc->t2_timer);
+				ndlc->t2_active = false;
+				ndlc->t1_active = false;
+				break;
+			case PCB_SYNC_NACK:
+				llt_ndlc_requeue_data_pending(ndlc);
+				llt_ndlc_send_queue(ndlc);
+				/* start timer t1 for ndlc aknowledge */
+				time_sent = jiffies;
+				ndlc->t1_active = true;
+				mod_timer(&ndlc->t1_timer, time_sent +
+					msecs_to_jiffies(NDLC_TIMER_T1));
+				break;
+			case PCB_SYNC_WAIT:
+				time_sent = jiffies;
+				ndlc->t1_active = true;
+				mod_timer(&ndlc->t1_timer, time_sent +
+					  msecs_to_jiffies(NDLC_TIMER_T1_WAIT));
+				break;
+			default:
+				pr_err("UNKNOWN Packet Control Byte=%d\n", pcb);
+				kfree_skb(skb);
+				break;
+			}
+		} else {
+			nci_recv_frame(ndlc->ndev, skb);
+		}
+	}
+}
+
+static void llt_ndlc_sm_work(struct work_struct *work)
+{
+	struct llt_ndlc *ndlc = container_of(work, struct llt_ndlc, sm_work);
+
+	llt_ndlc_send_queue(ndlc);
+	llt_ndlc_rcv_queue(ndlc);
+
+	if (ndlc->t1_active && timer_pending(&ndlc->t1_timer) == 0) {
+		pr_debug
+		    ("Handle T1(recv SUPERVISOR) elapsed (T1 now inactive)\n");
+		ndlc->t1_active = false;
+
+		llt_ndlc_requeue_data_pending(ndlc);
+		llt_ndlc_send_queue(ndlc);
+	}
+
+	if (ndlc->t2_active && timer_pending(&ndlc->t2_timer) == 0) {
+		pr_debug("Handle T2(recv DATA) elapsed (T2 now inactive)\n");
+		ndlc->t2_active = false;
+		ndlc->t1_active = false;
+		del_timer_sync(&ndlc->t1_timer);
+
+		ndlc_close(ndlc);
+		ndlc->hard_fault = -EREMOTEIO;
+	}
+}
+
+void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb)
+{
+	if (skb == NULL) {
+		pr_err("NULL Frame -> link is dead\n");
+		ndlc->hard_fault = -EREMOTEIO;
+		ndlc_close(ndlc);
+	} else {
+		NDLC_DUMP_SKB("incoming frame", skb);
+		skb_queue_tail(&ndlc->rcv_q, skb);
+	}
+
+	schedule_work(&ndlc->sm_work);
+}
+EXPORT_SYMBOL(ndlc_recv);
+
+static void ndlc_t1_timeout(unsigned long data)
+{
+	struct llt_ndlc *ndlc = (struct llt_ndlc *)data;
+
+	pr_debug("\n");
+
+	schedule_work(&ndlc->sm_work);
+}
+
+static void ndlc_t2_timeout(unsigned long data)
+{
+	struct llt_ndlc *ndlc = (struct llt_ndlc *)data;
+
+	pr_debug("\n");
+
+	schedule_work(&ndlc->sm_work);
+}
+
+int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
+	       int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id)
+{
+	struct llt_ndlc *ndlc;
+
+	ndlc = devm_kzalloc(dev, sizeof(struct llt_ndlc), GFP_KERNEL);
+	if (!ndlc) {
+		nfc_err(dev, "Cannot allocate memory for ndlc.\n");
+		return -ENOMEM;
+	}
+	ndlc->ops = phy_ops;
+	ndlc->phy_id = phy_id;
+	ndlc->dev = dev;
+
+	*ndlc_id = ndlc;
+
+	/* start timers */
+	init_timer(&ndlc->t1_timer);
+	ndlc->t1_timer.data = (unsigned long)ndlc;
+	ndlc->t1_timer.function = ndlc_t1_timeout;
+
+	init_timer(&ndlc->t2_timer);
+	ndlc->t2_timer.data = (unsigned long)ndlc;
+	ndlc->t2_timer.function = ndlc_t2_timeout;
+
+	skb_queue_head_init(&ndlc->rcv_q);
+	skb_queue_head_init(&ndlc->send_q);
+	skb_queue_head_init(&ndlc->ack_pending_q);
+
+	INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
+
+	return st21nfcb_nci_probe(ndlc, phy_headroom, phy_tailroom);
+}
+EXPORT_SYMBOL(ndlc_probe);
+
+void ndlc_remove(struct llt_ndlc *ndlc)
+{
+	/* cancel timers */
+	del_timer_sync(&ndlc->t1_timer);
+	del_timer_sync(&ndlc->t2_timer);
+	ndlc->t2_active = false;
+	ndlc->t1_active = false;
+
+	skb_queue_purge(&ndlc->rcv_q);
+	skb_queue_purge(&ndlc->send_q);
+
+	st21nfcb_nci_remove(ndlc->ndev);
+	kfree(ndlc);
+}
+EXPORT_SYMBOL(ndlc_remove);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/ndlc.h linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/ndlc.h
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/ndlc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/ndlc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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 __LOCAL_NDLC_H_
+#define __LOCAL_NDLC_H_
+
+#include <linux/skbuff.h>
+#include <net/nfc/nfc.h>
+
+/* Low Level Transport description */
+struct llt_ndlc {
+	struct nci_dev *ndev;
+	struct nfc_phy_ops *ops;
+	void *phy_id;
+
+	struct timer_list t1_timer;
+	bool t1_active;
+
+	struct timer_list t2_timer;
+	bool t2_active;
+
+	struct sk_buff_head rcv_q;
+	struct sk_buff_head send_q;
+	struct sk_buff_head ack_pending_q;
+
+	struct work_struct sm_work;
+
+	struct device *dev;
+
+	int hard_fault;
+};
+
+int ndlc_open(struct llt_ndlc *ndlc);
+void ndlc_close(struct llt_ndlc *ndlc);
+int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb);
+void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb);
+int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
+	int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id);
+void ndlc_remove(struct llt_ndlc *ndlc);
+#endif /* __LOCAL_NDLC_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/st21nfcb.c linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/st21nfcb.c
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/st21nfcb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/st21nfcb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,129 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+
+#include "st21nfcb.h"
+#include "ndlc.h"
+
+#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
+
+static int st21nfcb_nci_open(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	int r;
+
+	if (test_and_set_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+		return 0;
+
+	r = ndlc_open(info->ndlc);
+	if (r)
+		clear_bit(ST21NFCB_NCI_RUNNING, &info->flags);
+
+	return r;
+}
+
+static int st21nfcb_nci_close(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	if (!test_and_clear_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+		return 0;
+
+	ndlc_close(info->ndlc);
+
+	return 0;
+}
+
+static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	skb->dev = (void *)ndev;
+
+	if (!test_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+		return -EBUSY;
+
+	return ndlc_send(info->ndlc, skb);
+}
+
+static struct nci_ops st21nfcb_nci_ops = {
+	.open = st21nfcb_nci_open,
+	.close = st21nfcb_nci_close,
+	.send = st21nfcb_nci_send,
+};
+
+int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+		       int phy_tailroom)
+{
+	struct st21nfcb_nci_info *info;
+	int r;
+	u32 protocols;
+
+	info = devm_kzalloc(ndlc->dev,
+			sizeof(struct st21nfcb_nci_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	protocols = NFC_PROTO_JEWEL_MASK
+		| NFC_PROTO_MIFARE_MASK
+		| NFC_PROTO_FELICA_MASK
+		| NFC_PROTO_ISO14443_MASK
+		| NFC_PROTO_ISO14443_B_MASK
+		| NFC_PROTO_NFC_DEP_MASK;
+
+	ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols,
+					phy_headroom, phy_tailroom);
+	if (!ndlc->ndev) {
+		pr_err("Cannot allocate nfc ndev\n");
+		r = -ENOMEM;
+		goto err_alloc_ndev;
+	}
+	info->ndlc = ndlc;
+
+	nci_set_drvdata(ndlc->ndev, info);
+
+	r = nci_register_device(ndlc->ndev);
+	if (r)
+		goto err_regdev;
+
+	return r;
+err_regdev:
+	nci_free_device(ndlc->ndev);
+
+err_alloc_ndev:
+	kfree(info);
+	return r;
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_probe);
+
+void st21nfcb_nci_remove(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	nci_unregister_device(ndev);
+	nci_free_device(ndev);
+	kfree(info);
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/nfc/st21nfcb/st21nfcb.h linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/st21nfcb.h
--- linux-libre-3.16-gnu/drivers/nfc/st21nfcb/st21nfcb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/nfc/st21nfcb/st21nfcb.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  STMicroelectronics SAS. 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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 __LOCAL_ST21NFCB_H_
+#define __LOCAL_ST21NFCB_H_
+
+#include <net/nfc/nci_core.h>
+
+#include "ndlc.h"
+
+/* Define private flags: */
+#define ST21NFCB_NCI_RUNNING			1
+
+struct st21nfcb_nci_info {
+	struct llt_ndlc *ndlc;
+	unsigned long flags;
+};
+
+void st21nfcb_nci_remove(struct nci_dev *ndev);
+int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+		int phy_tailroom);
+
+#endif /* __LOCAL_ST21NFCB_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ntb/ntb_transport.c linux-libre-3.17-rc7-gnu/drivers/ntb/ntb_transport.c
--- linux-libre-3.16-gnu/drivers/ntb/ntb_transport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ntb/ntb_transport.c	2014-09-28 17:29:07.000000000 -0400
@@ -510,7 +510,7 @@ static void ntb_transport_setup_qp_mw(st
 
 	WARN_ON(nt->mw[mw_num].virt_addr == NULL);
 
-	if (nt->max_qps % mw_max && mw_num < nt->max_qps % mw_max)
+	if (nt->max_qps % mw_max && mw_num + 1 < nt->max_qps / mw_max)
 		num_qps_mw = nt->max_qps / mw_max + 1;
 	else
 		num_qps_mw = nt->max_qps / mw_max;
@@ -576,6 +576,19 @@ static int ntb_set_mw(struct ntb_transpo
 		return -ENOMEM;
 	}
 
+	/*
+	 * we must ensure that the memory address allocated is BAR size
+	 * aligned in order for the XLAT register to take the value. This
+	 * is a requirement of the hardware. It is recommended to setup CMA
+	 * for BAR sizes equal or greater than 4MB.
+	 */
+	if (!IS_ALIGNED(mw->dma_addr, mw->size)) {
+		dev_err(&pdev->dev, "DMA memory %pad not aligned to BAR size\n",
+			&mw->dma_addr);
+		ntb_free_mw(nt, num_mw);
+		return -ENOMEM;
+	}
+
 	/* Notify HW the memory location of the receive buffer */
 	ntb_set_mw_addr(nt->ndev, num_mw, mw->dma_addr);
 
@@ -856,7 +869,7 @@ static int ntb_transport_init_queue(stru
 	qp->client_ready = NTB_LINK_DOWN;
 	qp->event_handler = NULL;
 
-	if (nt->max_qps % mw_max && mw_num < nt->max_qps % mw_max)
+	if (nt->max_qps % mw_max && mw_num + 1 < nt->max_qps / mw_max)
 		num_qps_mw = nt->max_qps / mw_max + 1;
 	else
 		num_qps_mw = nt->max_qps / mw_max;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/address.c linux-libre-3.17-rc7-gnu/drivers/of/address.c
--- linux-libre-3.16-gnu/drivers/of/address.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/address.c	2014-09-28 17:29:07.000000000 -0400
@@ -702,6 +702,42 @@ void __iomem *of_iomap(struct device_nod
 }
 EXPORT_SYMBOL(of_iomap);
 
+/*
+ * of_io_request_and_map - Requests a resource and maps the memory mapped IO
+ *			   for a given device_node
+ * @device:	the device whose io range will be mapped
+ * @index:	index of the io range
+ * @name:	name of the resource
+ *
+ * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
+ * error code on failure. Usage example:
+ *
+ *	base = of_io_request_and_map(node, 0, "foo");
+ *	if (IS_ERR(base))
+ *		return PTR_ERR(base);
+ */
+void __iomem *of_io_request_and_map(struct device_node *np, int index,
+					char *name)
+{
+	struct resource res;
+	void __iomem *mem;
+
+	if (of_address_to_resource(np, index, &res))
+		return IOMEM_ERR_PTR(-EINVAL);
+
+	if (!request_mem_region(res.start, resource_size(&res), name))
+		return IOMEM_ERR_PTR(-EBUSY);
+
+	mem = ioremap(res.start, resource_size(&res));
+	if (!mem) {
+		release_mem_region(res.start, resource_size(&res));
+		return IOMEM_ERR_PTR(-ENOMEM);
+	}
+
+	return mem;
+}
+EXPORT_SYMBOL(of_io_request_and_map);
+
 /**
  * of_dma_get_range - Get DMA range info
  * @np:		device node to get DMA range info
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/base.c linux-libre-3.17-rc7-gnu/drivers/of/base.c
--- linux-libre-3.16-gnu/drivers/of/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
  *      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/ctype.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
@@ -35,15 +36,17 @@ struct device_node *of_allnodes;
 EXPORT_SYMBOL(of_allnodes);
 struct device_node *of_chosen;
 struct device_node *of_aliases;
-static struct device_node *of_stdout;
+struct device_node *of_stdout;
 
-static struct kset *of_kset;
+struct kset *of_kset;
 
 /*
- * Used to protect the of_aliases; but also overloaded to hold off addition of
- * nodes to sysfs
+ * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
+ * This mutex must be held whenever modifications are being made to the
+ * device tree. The of_{attach,detach}_node() and
+ * of_{add,remove,update}_property() helpers make sure this happens.
  */
-DEFINE_MUTEX(of_aliases_mutex);
+DEFINE_MUTEX(of_mutex);
 
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
@@ -89,79 +92,7 @@ int __weak of_node_to_nid(struct device_
 }
 #endif
 
-#if defined(CONFIG_OF_DYNAMIC)
-/**
- *	of_node_get - Increment refcount of a node
- *	@node:	Node to inc refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Returns node.
- */
-struct device_node *of_node_get(struct device_node *node)
-{
-	if (node)
-		kobject_get(&node->kobj);
-	return node;
-}
-EXPORT_SYMBOL(of_node_get);
-
-static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
-{
-	return container_of(kobj, struct device_node, kobj);
-}
-
-/**
- *	of_node_release - release a dynamically allocated node
- *	@kref:  kref element of the node to be released
- *
- *	In of_node_put() this function is passed to kref_put()
- *	as the destructor.
- */
-static void of_node_release(struct kobject *kobj)
-{
-	struct device_node *node = kobj_to_device_node(kobj);
-	struct property *prop = node->properties;
-
-	/* We should never be releasing nodes that haven't been detached. */
-	if (!of_node_check_flag(node, OF_DETACHED)) {
-		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
-		dump_stack();
-		return;
-	}
-
-	if (!of_node_check_flag(node, OF_DYNAMIC))
-		return;
-
-	while (prop) {
-		struct property *next = prop->next;
-		kfree(prop->name);
-		kfree(prop->value);
-		kfree(prop);
-		prop = next;
-
-		if (!prop) {
-			prop = node->deadprops;
-			node->deadprops = NULL;
-		}
-	}
-	kfree(node->full_name);
-	kfree(node->data);
-	kfree(node);
-}
-
-/**
- *	of_node_put - Decrement refcount of a node
- *	@node:	Node to dec refcount, NULL is supported to
- *		simplify writing of callers
- *
- */
-void of_node_put(struct device_node *node)
-{
-	if (node)
-		kobject_put(&node->kobj);
-}
-EXPORT_SYMBOL(of_node_put);
-#else
+#ifndef CONFIG_OF_DYNAMIC
 static void of_node_release(struct kobject *kobj)
 {
 	/* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
@@ -200,13 +131,19 @@ static const char *safe_name(struct kobj
 	return name;
 }
 
-static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
+int __of_add_property_sysfs(struct device_node *np, struct property *pp)
 {
 	int rc;
 
 	/* Important: Don't leak passwords */
 	bool secure = strncmp(pp->name, "security-", 9) == 0;
 
+	if (!IS_ENABLED(CONFIG_SYSFS))
+		return 0;
+
+	if (!of_kset || !of_node_is_attached(np))
+		return 0;
+
 	sysfs_bin_attr_init(&pp->attr);
 	pp->attr.attr.name = safe_name(&np->kobj, pp->name);
 	pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
@@ -218,12 +155,18 @@ static int __of_add_property_sysfs(struc
 	return rc;
 }
 
-static int __of_node_add(struct device_node *np)
+int __of_attach_node_sysfs(struct device_node *np)
 {
 	const char *name;
 	struct property *pp;
 	int rc;
 
+	if (!IS_ENABLED(CONFIG_SYSFS))
+		return 0;
+
+	if (!of_kset)
+		return 0;
+
 	np->kobj.kset = of_kset;
 	if (!np->parent) {
 		/* Nodes without parents are new top level trees */
@@ -245,59 +188,20 @@ static int __of_node_add(struct device_n
 	return 0;
 }
 
-int of_node_add(struct device_node *np)
-{
-	int rc = 0;
-
-	BUG_ON(!of_node_is_initialized(np));
-
-	/*
-	 * Grab the mutex here so that in a race condition between of_init() and
-	 * of_node_add(), node addition will still be consistent.
-	 */
-	mutex_lock(&of_aliases_mutex);
-	if (of_kset)
-		rc = __of_node_add(np);
-	else
-		/* This scenario may be perfectly valid, but report it anyway */
-		pr_info("of_node_add(%s) before of_init()\n", np->full_name);
-	mutex_unlock(&of_aliases_mutex);
-	return rc;
-}
-
-#if defined(CONFIG_OF_DYNAMIC)
-static void of_node_remove(struct device_node *np)
-{
-	struct property *pp;
-
-	BUG_ON(!of_node_is_initialized(np));
-
-	/* only remove properties if on sysfs */
-	if (of_node_is_attached(np)) {
-		for_each_property_of_node(np, pp)
-			sysfs_remove_bin_file(&np->kobj, &pp->attr);
-		kobject_del(&np->kobj);
-	}
-
-	/* finally remove the kobj_init ref */
-	of_node_put(np);
-}
-#endif
-
 static int __init of_init(void)
 {
 	struct device_node *np;
 
 	/* Create the kset, and register existing nodes */
-	mutex_lock(&of_aliases_mutex);
+	mutex_lock(&of_mutex);
 	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
 	if (!of_kset) {
-		mutex_unlock(&of_aliases_mutex);
+		mutex_unlock(&of_mutex);
 		return -ENOMEM;
 	}
 	for_each_of_allnodes(np)
-		__of_node_add(np);
-	mutex_unlock(&of_aliases_mutex);
+		__of_attach_node_sysfs(np);
+	mutex_unlock(&of_mutex);
 
 	/* Symlink in /proc as required by userspace ABI */
 	if (of_allnodes)
@@ -369,8 +273,8 @@ EXPORT_SYMBOL(of_find_all_nodes);
  * Find a property with a given name for a given node
  * and return the value.
  */
-static const void *__of_get_property(const struct device_node *np,
-				     const char *name, int *lenp)
+const void *__of_get_property(const struct device_node *np,
+			      const char *name, int *lenp)
 {
 	struct property *pp = __of_find_property(np, name, lenp);
 
@@ -1748,32 +1652,10 @@ int of_count_phandle_with_args(const str
 }
 EXPORT_SYMBOL(of_count_phandle_with_args);
 
-#if defined(CONFIG_OF_DYNAMIC)
-static int of_property_notify(int action, struct device_node *np,
-			      struct property *prop)
-{
-	struct of_prop_reconfig pr;
-
-	/* only call notifiers if the node is attached */
-	if (!of_node_is_attached(np))
-		return 0;
-
-	pr.dn = np;
-	pr.prop = prop;
-	return of_reconfig_notify(action, &pr);
-}
-#else
-static int of_property_notify(int action, struct device_node *np,
-			      struct property *prop)
-{
-	return 0;
-}
-#endif
-
 /**
  * __of_add_property - Add a property to a node without lock operations
  */
-static int __of_add_property(struct device_node *np, struct property *prop)
+int __of_add_property(struct device_node *np, struct property *prop)
 {
 	struct property **next;
 
@@ -1799,22 +1681,52 @@ int of_add_property(struct device_node *
 	unsigned long flags;
 	int rc;
 
-	rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
-	if (rc)
-		return rc;
+	mutex_lock(&of_mutex);
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
 	rc = __of_add_property(np, prop);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
-	if (rc)
-		return rc;
 
-	if (of_node_is_attached(np))
+	if (!rc)
 		__of_add_property_sysfs(np, prop);
 
+	mutex_unlock(&of_mutex);
+
+	if (!rc)
+		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
+
 	return rc;
 }
 
+int __of_remove_property(struct device_node *np, struct property *prop)
+{
+	struct property **next;
+
+	for (next = &np->properties; *next; next = &(*next)->next) {
+		if (*next == prop)
+			break;
+	}
+	if (*next == NULL)
+		return -ENODEV;
+
+	/* found the node */
+	*next = prop->next;
+	prop->next = np->deadprops;
+	np->deadprops = prop;
+
+	return 0;
+}
+
+void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
+{
+	if (!IS_ENABLED(CONFIG_SYSFS))
+		return;
+
+	/* at early boot, bail here and defer setup to of_init() */
+	if (of_kset && of_node_is_attached(np))
+		sysfs_remove_bin_file(&np->kobj, &prop->attr);
+}
+
 /**
  * of_remove_property - Remove a property from a node.
  *
@@ -1825,211 +1737,101 @@ int of_add_property(struct device_node *
  */
 int of_remove_property(struct device_node *np, struct property *prop)
 {
-	struct property **next;
 	unsigned long flags;
-	int found = 0;
 	int rc;
 
-	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
-	if (rc)
-		return rc;
+	mutex_lock(&of_mutex);
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (*next == prop) {
-			/* found the node */
-			*next = prop->next;
-			prop->next = np->deadprops;
-			np->deadprops = prop;
-			found = 1;
-			break;
-		}
-		next = &(*next)->next;
-	}
+	rc = __of_remove_property(np, prop);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	if (!found)
-		return -ENODEV;
+	if (!rc)
+		__of_remove_property_sysfs(np, prop);
 
-	/* at early boot, bail hear and defer setup to of_init() */
-	if (!of_kset)
-		return 0;
+	mutex_unlock(&of_mutex);
 
-	sysfs_remove_bin_file(&np->kobj, &prop->attr);
+	if (!rc)
+		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
 
-	return 0;
+	return rc;
 }
 
-/*
- * of_update_property - Update a property in a node, if the property does
- * not exist, add it.
- *
- * Note that we don't actually remove it, since we have given out
- * who-knows-how-many pointers to the data using get-property.
- * Instead we just move the property to the "dead properties" list,
- * and add the new property to the property list
- */
-int of_update_property(struct device_node *np, struct property *newprop)
+int __of_update_property(struct device_node *np, struct property *newprop,
+		struct property **oldpropp)
 {
 	struct property **next, *oldprop;
-	unsigned long flags;
-	int rc;
 
-	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
-	if (rc)
-		return rc;
-
-	if (!newprop->name)
-		return -EINVAL;
+	for (next = &np->properties; *next; next = &(*next)->next) {
+		if (of_prop_cmp((*next)->name, newprop->name) == 0)
+			break;
+	}
+	*oldpropp = oldprop = *next;
 
-	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	oldprop = __of_find_property(np, newprop->name, NULL);
-	if (!oldprop) {
-		/* add the new node */
-		rc = __of_add_property(np, newprop);
-	} else while (*next) {
+	if (oldprop) {
 		/* replace the node */
-		if (*next == oldprop) {
-			newprop->next = oldprop->next;
-			*next = newprop;
-			oldprop->next = np->deadprops;
-			np->deadprops = oldprop;
-			break;
-		}
-		next = &(*next)->next;
+		newprop->next = oldprop->next;
+		*next = newprop;
+		oldprop->next = np->deadprops;
+		np->deadprops = oldprop;
+	} else {
+		/* new node */
+		newprop->next = NULL;
+		*next = newprop;
 	}
-	raw_spin_unlock_irqrestore(&devtree_lock, flags);
-	if (rc)
-		return rc;
+
+	return 0;
+}
+
+void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
+		struct property *oldprop)
+{
+	if (!IS_ENABLED(CONFIG_SYSFS))
+		return;
 
 	/* At early boot, bail out and defer setup to of_init() */
 	if (!of_kset)
-		return 0;
+		return;
 
-	/* Update the sysfs attribute */
 	if (oldprop)
 		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
 	__of_add_property_sysfs(np, newprop);
-
-	return 0;
 }
 
-#if defined(CONFIG_OF_DYNAMIC)
 /*
- * Support for dynamic device trees.
+ * of_update_property - Update a property in a node, if the property does
+ * not exist, add it.
  *
- * On some platforms, the device tree can be manipulated at runtime.
- * The routines in this section support adding, removing and changing
- * device tree nodes.
- */
-
-static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
-
-int of_reconfig_notifier_register(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
-
-int of_reconfig_notifier_unregister(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
-
-int of_reconfig_notify(unsigned long action, void *p)
-{
-	int rc;
-
-	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
-	return notifier_to_errno(rc);
-}
-
-/**
- * of_attach_node - Plug a device node into the tree and global list.
+ * Note that we don't actually remove it, since we have given out
+ * who-knows-how-many pointers to the data using get-property.
+ * Instead we just move the property to the "dead properties" list,
+ * and add the new property to the property list
  */
-int of_attach_node(struct device_node *np)
+int of_update_property(struct device_node *np, struct property *newprop)
 {
+	struct property *oldprop;
 	unsigned long flags;
 	int rc;
 
-	rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
-	if (rc)
-		return rc;
-
-	raw_spin_lock_irqsave(&devtree_lock, flags);
-	np->sibling = np->parent->child;
-	np->allnext = np->parent->allnext;
-	np->parent->allnext = np;
-	np->parent->child = np;
-	of_node_clear_flag(np, OF_DETACHED);
-	raw_spin_unlock_irqrestore(&devtree_lock, flags);
-
-	of_node_add(np);
-	return 0;
-}
-
-/**
- * of_detach_node - "Unplug" a node from the device tree.
- *
- * The caller must hold a reference to the node.  The memory associated with
- * the node is not freed until its refcount goes to zero.
- */
-int of_detach_node(struct device_node *np)
-{
-	struct device_node *parent;
-	unsigned long flags;
-	int rc = 0;
+	if (!newprop->name)
+		return -EINVAL;
 
-	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
-	if (rc)
-		return rc;
+	mutex_lock(&of_mutex);
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
+	rc = __of_update_property(np, newprop, &oldprop);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	if (of_node_check_flag(np, OF_DETACHED)) {
-		/* someone already detached it */
-		raw_spin_unlock_irqrestore(&devtree_lock, flags);
-		return rc;
-	}
-
-	parent = np->parent;
-	if (!parent) {
-		raw_spin_unlock_irqrestore(&devtree_lock, flags);
-		return rc;
-	}
-
-	if (of_allnodes == np)
-		of_allnodes = np->allnext;
-	else {
-		struct device_node *prev;
-		for (prev = of_allnodes;
-		     prev->allnext != np;
-		     prev = prev->allnext)
-			;
-		prev->allnext = np->allnext;
-	}
+	if (!rc)
+		__of_update_property_sysfs(np, newprop, oldprop);
 
-	if (parent->child == np)
-		parent->child = np->sibling;
-	else {
-		struct device_node *prevsib;
-		for (prevsib = np->parent->child;
-		     prevsib->sibling != np;
-		     prevsib = prevsib->sibling)
-			;
-		prevsib->sibling = np->sibling;
-	}
+	mutex_unlock(&of_mutex);
 
-	of_node_set_flag(np, OF_DETACHED);
-	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+	if (!rc)
+		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
 
-	of_node_remove(np);
 	return rc;
 }
-#endif /* defined(CONFIG_OF_DYNAMIC) */
 
 static void of_alias_add(struct alias_prop *ap, struct device_node *np,
 			 int id, const char *stem, int stem_len)
@@ -2057,19 +1859,22 @@ void of_alias_scan(void * (*dt_alloc)(u6
 {
 	struct property *pp;
 
+	of_aliases = of_find_node_by_path("/aliases");
 	of_chosen = of_find_node_by_path("/chosen");
 	if (of_chosen == NULL)
 		of_chosen = of_find_node_by_path("/chosen@0");
 
 	if (of_chosen) {
+		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
 		const char *name = of_get_property(of_chosen, "stdout-path", NULL);
 		if (!name)
 			name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+		if (IS_ENABLED(CONFIG_PPC) && !name)
+			name = of_get_property(of_aliases, "stdout", NULL);
 		if (name)
 			of_stdout = of_find_node_by_path(name);
 	}
 
-	of_aliases = of_find_node_by_path("/aliases");
 	if (!of_aliases)
 		return;
 
@@ -2122,7 +1927,7 @@ int of_alias_get_id(struct device_node *
 	struct alias_prop *app;
 	int id = -ENODEV;
 
-	mutex_lock(&of_aliases_mutex);
+	mutex_lock(&of_mutex);
 	list_for_each_entry(app, &aliases_lookup, link) {
 		if (strcmp(app->stem, stem) != 0)
 			continue;
@@ -2132,7 +1937,7 @@ int of_alias_get_id(struct device_node *
 			break;
 		}
 	}
-	mutex_unlock(&of_aliases_mutex);
+	mutex_unlock(&of_mutex);
 
 	return id;
 }
@@ -2180,20 +1985,22 @@ const char *of_prop_next_string(struct p
 EXPORT_SYMBOL_GPL(of_prop_next_string);
 
 /**
- * of_device_is_stdout_path - check if a device node matches the
- *                            linux,stdout-path property
+ * of_console_check() - Test and setup console for DT setup
+ * @dn - Pointer to device node
+ * @name - Name to use for preferred console without index. ex. "ttyS"
+ * @index - Index to use for preferred console.
  *
- * Check if this device node matches the linux,stdout-path property
- * in the chosen node. return true if yes, false otherwise.
+ * Check if the given device node matches the stdout-path property in the
+ * /chosen node. If it does then register it as the preferred console and return
+ * TRUE. Otherwise return FALSE.
  */
-int of_device_is_stdout_path(struct device_node *dn)
+bool of_console_check(struct device_node *dn, char *name, int index)
 {
-	if (!of_stdout)
+	if (!dn || dn != of_stdout || console_set_on_cmdline)
 		return false;
-
-	return of_stdout == dn;
+	return !add_preferred_console(name, index, NULL);
 }
-EXPORT_SYMBOL_GPL(of_device_is_stdout_path);
+EXPORT_SYMBOL_GPL(of_console_check);
 
 /**
  *	of_find_next_cache_node - Find a node's subsidiary cache
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/device.c linux-libre-3.17-rc7-gnu/drivers/of/device.c
--- linux-libre-3.16-gnu/drivers/of/device.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/device.c	2014-09-28 17:29:07.000000000 -0400
@@ -160,7 +160,7 @@ void of_device_uevent(struct device *dev
 	add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
 
 	seen = 0;
-	mutex_lock(&of_aliases_mutex);
+	mutex_lock(&of_mutex);
 	list_for_each_entry(app, &aliases_lookup, link) {
 		if (dev->of_node == app->np) {
 			add_uevent_var(env, "OF_ALIAS_%d=%s", seen,
@@ -168,7 +168,7 @@ void of_device_uevent(struct device *dev
 			seen++;
 		}
 	}
-	mutex_unlock(&of_aliases_mutex);
+	mutex_unlock(&of_mutex);
 }
 
 int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/dynamic.c linux-libre-3.17-rc7-gnu/drivers/of/dynamic.c
--- linux-libre-3.16-gnu/drivers/of/dynamic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/of/dynamic.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,663 @@
+/*
+ * Support for dynamic device trees.
+ *
+ * On some platforms, the device tree can be manipulated at runtime.
+ * The routines in this section support adding, removing and changing
+ * device tree nodes.
+ */
+
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+
+#include "of_private.h"
+
+/**
+ * of_node_get() - Increment refcount of a node
+ * @node:	Node to inc refcount, NULL is supported to simplify writing of
+ *		callers
+ *
+ * Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+	if (node)
+		kobject_get(&node->kobj);
+	return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+/**
+ * of_node_put() - Decrement refcount of a node
+ * @node:	Node to dec refcount, NULL is supported to simplify writing of
+ *		callers
+ */
+void of_node_put(struct device_node *node)
+{
+	if (node)
+		kobject_put(&node->kobj);
+}
+EXPORT_SYMBOL(of_node_put);
+
+void __of_detach_node_sysfs(struct device_node *np)
+{
+	struct property *pp;
+
+	if (!IS_ENABLED(CONFIG_SYSFS))
+		return;
+
+	BUG_ON(!of_node_is_initialized(np));
+	if (!of_kset)
+		return;
+
+	/* only remove properties if on sysfs */
+	if (of_node_is_attached(np)) {
+		for_each_property_of_node(np, pp)
+			sysfs_remove_bin_file(&np->kobj, &pp->attr);
+		kobject_del(&np->kobj);
+	}
+
+	/* finally remove the kobj_init ref */
+	of_node_put(np);
+}
+
+static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
+
+int of_reconfig_notifier_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
+
+int of_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
+
+int of_reconfig_notify(unsigned long action, void *p)
+{
+	int rc;
+
+	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
+	return notifier_to_errno(rc);
+}
+
+int of_property_notify(int action, struct device_node *np,
+		       struct property *prop, struct property *oldprop)
+{
+	struct of_prop_reconfig pr;
+
+	/* only call notifiers if the node is attached */
+	if (!of_node_is_attached(np))
+		return 0;
+
+	pr.dn = np;
+	pr.prop = prop;
+	pr.old_prop = oldprop;
+	return of_reconfig_notify(action, &pr);
+}
+
+void __of_attach_node(struct device_node *np)
+{
+	const __be32 *phandle;
+	int sz;
+
+	np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
+	np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
+
+	phandle = __of_get_property(np, "phandle", &sz);
+	if (!phandle)
+		phandle = __of_get_property(np, "linux,phandle", &sz);
+	if (IS_ENABLED(PPC_PSERIES) && !phandle)
+		phandle = __of_get_property(np, "ibm,phandle", &sz);
+	np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
+
+	np->child = NULL;
+	np->sibling = np->parent->child;
+	np->allnext = np->parent->allnext;
+	np->parent->allnext = np;
+	np->parent->child = np;
+	of_node_clear_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_attach_node() - Plug a device node into the tree and global list.
+ */
+int of_attach_node(struct device_node *np)
+{
+	unsigned long flags;
+
+	mutex_lock(&of_mutex);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	__of_attach_node(np);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	__of_attach_node_sysfs(np);
+	mutex_unlock(&of_mutex);
+
+	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
+
+	return 0;
+}
+
+void __of_detach_node(struct device_node *np)
+{
+	struct device_node *parent;
+
+	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
+		return;
+
+	parent = np->parent;
+	if (WARN_ON(!parent))
+		return;
+
+	if (of_allnodes == np)
+		of_allnodes = np->allnext;
+	else {
+		struct device_node *prev;
+		for (prev = of_allnodes;
+		     prev->allnext != np;
+		     prev = prev->allnext)
+			;
+		prev->allnext = np->allnext;
+	}
+
+	if (parent->child == np)
+		parent->child = np->sibling;
+	else {
+		struct device_node *prevsib;
+		for (prevsib = np->parent->child;
+		     prevsib->sibling != np;
+		     prevsib = prevsib->sibling)
+			;
+		prevsib->sibling = np->sibling;
+	}
+
+	of_node_set_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_detach_node() - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node.  The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+int of_detach_node(struct device_node *np)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	mutex_lock(&of_mutex);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	__of_detach_node(np);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	__of_detach_node_sysfs(np);
+	mutex_unlock(&of_mutex);
+
+	of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+
+	return rc;
+}
+
+/**
+ * of_node_release() - release a dynamically allocated node
+ * @kref: kref element of the node to be released
+ *
+ * In of_node_put() this function is passed to kref_put() as the destructor.
+ */
+void of_node_release(struct kobject *kobj)
+{
+	struct device_node *node = kobj_to_device_node(kobj);
+	struct property *prop = node->properties;
+
+	/* We should never be releasing nodes that haven't been detached. */
+	if (!of_node_check_flag(node, OF_DETACHED)) {
+		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
+		dump_stack();
+		return;
+	}
+
+	if (!of_node_check_flag(node, OF_DYNAMIC))
+		return;
+
+	while (prop) {
+		struct property *next = prop->next;
+		kfree(prop->name);
+		kfree(prop->value);
+		kfree(prop);
+		prop = next;
+
+		if (!prop) {
+			prop = node->deadprops;
+			node->deadprops = NULL;
+		}
+	}
+	kfree(node->full_name);
+	kfree(node->data);
+	kfree(node);
+}
+
+/**
+ * __of_prop_dup - Copy a property dynamically.
+ * @prop:	Property to copy
+ * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Copy a property by dynamically allocating the memory of both the
+ * property stucture and the property name & contents. The property's
+ * flags have the OF_DYNAMIC bit set so that we can differentiate between
+ * dynamically allocated properties and not.
+ * Returns the newly allocated property or NULL on out of memory error.
+ */
+struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
+{
+	struct property *new;
+
+	new = kzalloc(sizeof(*new), allocflags);
+	if (!new)
+		return NULL;
+
+	/*
+	 * NOTE: There is no check for zero length value.
+	 * In case of a boolean property, this will allocate a value
+	 * of zero bytes. We do this to work around the use
+	 * of of_get_property() calls on boolean values.
+	 */
+	new->name = kstrdup(prop->name, allocflags);
+	new->value = kmemdup(prop->value, prop->length, allocflags);
+	new->length = prop->length;
+	if (!new->name || !new->value)
+		goto err_free;
+
+	/* mark the property as dynamic */
+	of_property_set_flag(new, OF_DYNAMIC);
+
+	return new;
+
+ err_free:
+	kfree(new->name);
+	kfree(new->value);
+	kfree(new);
+	return NULL;
+}
+
+/**
+ * __of_node_alloc() - Create an empty device node dynamically.
+ * @full_name:	Full name of the new device node
+ * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Create an empty device tree node, suitable for further modification.
+ * The node data are dynamically allocated and all the node flags
+ * have the OF_DYNAMIC & OF_DETACHED bits set.
+ * Returns the newly allocated node or NULL on out of memory error.
+ */
+struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags)
+{
+	struct device_node *node;
+
+	node = kzalloc(sizeof(*node), allocflags);
+	if (!node)
+		return NULL;
+
+	node->full_name = kstrdup(full_name, allocflags);
+	of_node_set_flag(node, OF_DYNAMIC);
+	of_node_set_flag(node, OF_DETACHED);
+	if (!node->full_name)
+		goto err_free;
+
+	of_node_init(node);
+
+	return node;
+
+ err_free:
+	kfree(node->full_name);
+	kfree(node);
+	return NULL;
+}
+
+static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
+{
+	of_node_put(ce->np);
+	list_del(&ce->node);
+	kfree(ce);
+}
+
+#ifdef DEBUG
+static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
+{
+	switch (ce->action) {
+	case OF_RECONFIG_ADD_PROPERTY:
+		pr_debug("%p: %s %s/%s\n",
+			ce, "ADD_PROPERTY   ", ce->np->full_name,
+			ce->prop->name);
+		break;
+	case OF_RECONFIG_REMOVE_PROPERTY:
+		pr_debug("%p: %s %s/%s\n",
+			ce, "REMOVE_PROPERTY", ce->np->full_name,
+			ce->prop->name);
+		break;
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		pr_debug("%p: %s %s/%s\n",
+			ce, "UPDATE_PROPERTY", ce->np->full_name,
+			ce->prop->name);
+		break;
+	case OF_RECONFIG_ATTACH_NODE:
+		pr_debug("%p: %s %s\n",
+			ce, "ATTACH_NODE    ", ce->np->full_name);
+		break;
+	case OF_RECONFIG_DETACH_NODE:
+		pr_debug("%p: %s %s\n",
+			ce, "DETACH_NODE    ", ce->np->full_name);
+		break;
+	}
+}
+#else
+static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
+{
+	/* empty */
+}
+#endif
+
+static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
+					  struct of_changeset_entry *rce)
+{
+	memcpy(rce, ce, sizeof(*rce));
+
+	switch (ce->action) {
+	case OF_RECONFIG_ATTACH_NODE:
+		rce->action = OF_RECONFIG_DETACH_NODE;
+		break;
+	case OF_RECONFIG_DETACH_NODE:
+		rce->action = OF_RECONFIG_ATTACH_NODE;
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+		rce->action = OF_RECONFIG_REMOVE_PROPERTY;
+		break;
+	case OF_RECONFIG_REMOVE_PROPERTY:
+		rce->action = OF_RECONFIG_ADD_PROPERTY;
+		break;
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		rce->old_prop = ce->prop;
+		rce->prop = ce->old_prop;
+		break;
+	}
+}
+
+static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert)
+{
+	struct of_changeset_entry ce_inverted;
+	int ret;
+
+	if (revert) {
+		__of_changeset_entry_invert(ce, &ce_inverted);
+		ce = &ce_inverted;
+	}
+
+	switch (ce->action) {
+	case OF_RECONFIG_ATTACH_NODE:
+	case OF_RECONFIG_DETACH_NODE:
+		ret = of_reconfig_notify(ce->action, ce->np);
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+	case OF_RECONFIG_REMOVE_PROPERTY:
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
+		break;
+	default:
+		pr_err("%s: invalid devicetree changeset action: %i\n", __func__,
+			(int)ce->action);
+		return;
+	}
+
+	if (ret)
+		pr_err("%s: notifier error @%s\n", __func__, ce->np->full_name);
+}
+
+static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
+{
+	struct property *old_prop, **propp;
+	unsigned long flags;
+	int ret = 0;
+
+	__of_changeset_entry_dump(ce);
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	switch (ce->action) {
+	case OF_RECONFIG_ATTACH_NODE:
+		__of_attach_node(ce->np);
+		break;
+	case OF_RECONFIG_DETACH_NODE:
+		__of_detach_node(ce->np);
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+		/* If the property is in deadprops then it must be removed */
+		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
+			if (*propp == ce->prop) {
+				*propp = ce->prop->next;
+				ce->prop->next = NULL;
+				break;
+			}
+		}
+
+		ret = __of_add_property(ce->np, ce->prop);
+		if (ret) {
+			pr_err("%s: add_property failed @%s/%s\n",
+				__func__, ce->np->full_name,
+				ce->prop->name);
+			break;
+		}
+		break;
+	case OF_RECONFIG_REMOVE_PROPERTY:
+		ret = __of_remove_property(ce->np, ce->prop);
+		if (ret) {
+			pr_err("%s: remove_property failed @%s/%s\n",
+				__func__, ce->np->full_name,
+				ce->prop->name);
+			break;
+		}
+		break;
+
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		/* If the property is in deadprops then it must be removed */
+		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
+			if (*propp == ce->prop) {
+				*propp = ce->prop->next;
+				ce->prop->next = NULL;
+				break;
+			}
+		}
+
+		ret = __of_update_property(ce->np, ce->prop, &old_prop);
+		if (ret) {
+			pr_err("%s: update_property failed @%s/%s\n",
+				__func__, ce->np->full_name,
+				ce->prop->name);
+			break;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	if (ret)
+		return ret;
+
+	switch (ce->action) {
+	case OF_RECONFIG_ATTACH_NODE:
+		__of_attach_node_sysfs(ce->np);
+		break;
+	case OF_RECONFIG_DETACH_NODE:
+		__of_detach_node_sysfs(ce->np);
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+		/* ignore duplicate names */
+		__of_add_property_sysfs(ce->np, ce->prop);
+		break;
+	case OF_RECONFIG_REMOVE_PROPERTY:
+		__of_remove_property_sysfs(ce->np, ce->prop);
+		break;
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		__of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
+		break;
+	}
+
+	return 0;
+}
+
+static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
+{
+	struct of_changeset_entry ce_inverted;
+
+	__of_changeset_entry_invert(ce, &ce_inverted);
+	return __of_changeset_entry_apply(&ce_inverted);
+}
+
+/**
+ * of_changeset_init - Initialize a changeset for use
+ *
+ * @ocs:	changeset pointer
+ *
+ * Initialize a changeset structure
+ */
+void of_changeset_init(struct of_changeset *ocs)
+{
+	memset(ocs, 0, sizeof(*ocs));
+	INIT_LIST_HEAD(&ocs->entries);
+}
+
+/**
+ * of_changeset_destroy - Destroy a changeset
+ *
+ * @ocs:	changeset pointer
+ *
+ * Destroys a changeset. Note that if a changeset is applied,
+ * its changes to the tree cannot be reverted.
+ */
+void of_changeset_destroy(struct of_changeset *ocs)
+{
+	struct of_changeset_entry *ce, *cen;
+
+	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
+		__of_changeset_entry_destroy(ce);
+}
+
+/**
+ * of_changeset_apply - Applies a changeset
+ *
+ * @ocs:	changeset pointer
+ *
+ * Applies a changeset to the live tree.
+ * Any side-effects of live tree state changes are applied here on
+ * sucess, like creation/destruction of devices and side-effects
+ * like creation of sysfs properties and directories.
+ * Returns 0 on success, a negative error value in case of an error.
+ * On error the partially applied effects are reverted.
+ */
+int of_changeset_apply(struct of_changeset *ocs)
+{
+	struct of_changeset_entry *ce;
+	int ret;
+
+	/* perform the rest of the work */
+	pr_debug("of_changeset: applying...\n");
+	list_for_each_entry(ce, &ocs->entries, node) {
+		ret = __of_changeset_entry_apply(ce);
+		if (ret) {
+			pr_err("%s: Error applying changeset (%d)\n", __func__, ret);
+			list_for_each_entry_continue_reverse(ce, &ocs->entries, node)
+				__of_changeset_entry_revert(ce);
+			return ret;
+		}
+	}
+	pr_debug("of_changeset: applied, emitting notifiers.\n");
+
+	/* drop the global lock while emitting notifiers */
+	mutex_unlock(&of_mutex);
+	list_for_each_entry(ce, &ocs->entries, node)
+		__of_changeset_entry_notify(ce, 0);
+	mutex_lock(&of_mutex);
+	pr_debug("of_changeset: notifiers sent.\n");
+
+	return 0;
+}
+
+/**
+ * of_changeset_revert - Reverts an applied changeset
+ *
+ * @ocs:	changeset pointer
+ *
+ * Reverts a changeset returning the state of the tree to what it
+ * was before the application.
+ * Any side-effects like creation/destruction of devices and
+ * removal of sysfs properties and directories are applied.
+ * Returns 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_revert(struct of_changeset *ocs)
+{
+	struct of_changeset_entry *ce;
+	int ret;
+
+	pr_debug("of_changeset: reverting...\n");
+	list_for_each_entry_reverse(ce, &ocs->entries, node) {
+		ret = __of_changeset_entry_revert(ce);
+		if (ret) {
+			pr_err("%s: Error reverting changeset (%d)\n", __func__, ret);
+			list_for_each_entry_continue(ce, &ocs->entries, node)
+				__of_changeset_entry_apply(ce);
+			return ret;
+		}
+	}
+	pr_debug("of_changeset: reverted, emitting notifiers.\n");
+
+	/* drop the global lock while emitting notifiers */
+	mutex_unlock(&of_mutex);
+	list_for_each_entry_reverse(ce, &ocs->entries, node)
+		__of_changeset_entry_notify(ce, 1);
+	mutex_lock(&of_mutex);
+	pr_debug("of_changeset: notifiers sent.\n");
+
+	return 0;
+}
+
+/**
+ * of_changeset_action - Perform a changeset action
+ *
+ * @ocs:	changeset pointer
+ * @action:	action to perform
+ * @np:		Pointer to device node
+ * @prop:	Pointer to property
+ *
+ * On action being one of:
+ * + OF_RECONFIG_ATTACH_NODE
+ * + OF_RECONFIG_DETACH_NODE,
+ * + OF_RECONFIG_ADD_PROPERTY
+ * + OF_RECONFIG_REMOVE_PROPERTY,
+ * + OF_RECONFIG_UPDATE_PROPERTY
+ * Returns 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_action(struct of_changeset *ocs, unsigned long action,
+		struct device_node *np, struct property *prop)
+{
+	struct of_changeset_entry *ce;
+
+	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+	if (!ce) {
+		pr_err("%s: Failed to allocate\n", __func__);
+		return -ENOMEM;
+	}
+	/* get a reference to the node */
+	ce->action = action;
+	ce->np = of_node_get(np);
+	ce->prop = prop;
+
+	if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
+		ce->old_prop = of_find_property(np, prop->name, NULL);
+
+	/* add it to the list */
+	list_add_tail(&ce->node, &ocs->entries);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/fdt.c linux-libre-3.17-rc7-gnu/drivers/of/fdt.c
--- linux-libre-3.16-gnu/drivers/of/fdt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/fdt.c	2014-09-28 17:29:07.000000000 -0400
@@ -453,7 +453,7 @@ static int __init __reserved_mem_reserve
 		base = dt_mem_next_cell(dt_root_addr_cells, &prop);
 		size = dt_mem_next_cell(dt_root_size_cells, &prop);
 
-		if (base && size &&
+		if (size &&
 		    early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
 			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n",
 				uname, &base, (unsigned long)size / SZ_1M);
@@ -923,24 +923,28 @@ int __init early_init_dt_scan_chosen(uns
 }
 
 #ifdef CONFIG_HAVE_MEMBLOCK
+#define MAX_PHYS_ADDR	((phys_addr_t)~0)
+
 void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
 {
 	const u64 phys_offset = __pa(PAGE_OFFSET);
-	base &= PAGE_MASK;
+
+	if (!PAGE_ALIGNED(base)) {
+		size -= PAGE_SIZE - (base & ~PAGE_MASK);
+		base = PAGE_ALIGN(base);
+	}
 	size &= PAGE_MASK;
 
-	if (sizeof(phys_addr_t) < sizeof(u64)) {
-		if (base > ULONG_MAX) {
-			pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
-					base, base + size);
-			return;
-		}
+	if (base > MAX_PHYS_ADDR) {
+		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
+				base, base + size);
+		return;
+	}
 
-		if (base + size > ULONG_MAX) {
-			pr_warning("Ignoring memory range 0x%lx - 0x%llx\n",
-					ULONG_MAX, base + size);
-			size = ULONG_MAX - base;
-		}
+	if (base + size - 1 > MAX_PHYS_ADDR) {
+		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
+				((u64)MAX_PHYS_ADDR) + 1, base + size);
+		size = MAX_PHYS_ADDR - base + 1;
 	}
 
 	if (base + size < phys_offset) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/irq.c linux-libre-3.17-rc7-gnu/drivers/of/irq.c
--- linux-libre-3.16-gnu/drivers/of/irq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/irq.c	2014-09-28 17:29:07.000000000 -0400
@@ -301,16 +301,17 @@ int of_irq_parse_one(struct device_node
 	/* Get the reg property (if any) */
 	addr = of_get_property(device, "reg", NULL);
 
+	/* Try the new-style interrupts-extended first */
+	res = of_parse_phandle_with_args(device, "interrupts-extended",
+					"#interrupt-cells", index, out_irq);
+	if (!res)
+		return of_irq_parse_raw(addr, out_irq);
+
 	/* Get the interrupts property */
 	intspec = of_get_property(device, "interrupts", &intlen);
-	if (intspec == NULL) {
-		/* Try the new-style interrupts-extended */
-		res = of_parse_phandle_with_args(device, "interrupts-extended",
-						"#interrupt-cells", index, out_irq);
-		if (res)
-			return -EINVAL;
-		return of_irq_parse_raw(addr, out_irq);
-	}
+	if (intspec == NULL)
+		return -EINVAL;
+
 	intlen /= sizeof(*intspec);
 
 	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/Kconfig linux-libre-3.17-rc7-gnu/drivers/of/Kconfig
--- linux-libre-3.16-gnu/drivers/of/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -9,7 +9,8 @@ menu "Device Tree and Open Firmware supp
 
 config OF_SELFTEST
 	bool "Device Tree Runtime self tests"
-	depends on OF_IRQ
+	depends on OF_IRQ && OF_EARLY_FLATTREE
+	select OF_DYNAMIC
 	help
 	  This option builds in test cases for the device tree infrastructure
 	  that are executed once at boot time, and the results dumped to the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/Makefile linux-libre-3.17-rc7-gnu/drivers/of/Makefile
--- linux-libre-3.16-gnu/drivers/of/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,11 +1,13 @@
 obj-y = base.o device.o platform.o
+obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
 obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
 obj-$(CONFIG_OF_IRQ)    += irq.o
 obj-$(CONFIG_OF_NET)	+= of_net.o
-obj-$(CONFIG_OF_SELFTEST) += selftest.o
+obj-$(CONFIG_OF_SELFTEST) += of_selftest.o
+of_selftest-objs := selftest.o testcase-data/testcases.dtb.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/of_private.h linux-libre-3.17-rc7-gnu/drivers/of/of_private.h
--- linux-libre-3.16-gnu/drivers/of/of_private.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/of_private.h	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,63 @@ struct alias_prop {
 	char stem[0];
 };
 
-extern struct mutex of_aliases_mutex;
+extern struct mutex of_mutex;
 extern struct list_head aliases_lookup;
+extern struct kset *of_kset;
+
+
+static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
+{
+	return container_of(kobj, struct device_node, kobj);
+}
+
+#if defined(CONFIG_OF_DYNAMIC)
+extern int of_property_notify(int action, struct device_node *np,
+			      struct property *prop, struct property *old_prop);
+extern void of_node_release(struct kobject *kobj);
+#else /* CONFIG_OF_DYNAMIC */
+static inline int of_property_notify(int action, struct device_node *np,
+				     struct property *prop, struct property *old_prop)
+{
+	return 0;
+}
+#endif /* CONFIG_OF_DYNAMIC */
+
+/**
+ * General utilities for working with live trees.
+ *
+ * All functions with two leading underscores operate
+ * without taking node references, so you either have to
+ * own the devtree lock or work on detached trees only.
+ */
+struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
+struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags);
+
+extern const void *__of_get_property(const struct device_node *np,
+				     const char *name, int *lenp);
+extern int __of_add_property(struct device_node *np, struct property *prop);
+extern int __of_add_property_sysfs(struct device_node *np,
+		struct property *prop);
+extern int __of_remove_property(struct device_node *np, struct property *prop);
+extern void __of_remove_property_sysfs(struct device_node *np,
+		struct property *prop);
+extern int __of_update_property(struct device_node *np,
+		struct property *newprop, struct property **oldprop);
+extern void __of_update_property_sysfs(struct device_node *np,
+		struct property *newprop, struct property *oldprop);
+
+extern void __of_attach_node(struct device_node *np);
+extern int __of_attach_node_sysfs(struct device_node *np);
+extern void __of_detach_node(struct device_node *np);
+extern void __of_detach_node_sysfs(struct device_node *np);
+
+/* iterators for transactions, used for overlays */
+/* forward iterator */
+#define for_each_transaction_entry(_oft, _te) \
+	list_for_each_entry(_te, &(_oft)->te_list, node)
+
+/* reverse iterator */
+#define for_each_transaction_entry_reverse(_oft, _te) \
+	list_for_each_entry_reverse(_te, &(_oft)->te_list, node)
+
 #endif /* _LINUX_OF_PRIVATE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/of_reserved_mem.c linux-libre-3.17-rc7-gnu/drivers/of/of_reserved_mem.c
--- linux-libre-3.16-gnu/drivers/of/of_reserved_mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/of_reserved_mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,8 +206,16 @@ void __init fdt_init_reserved_mem(void)
 	for (i = 0; i < reserved_mem_count; i++) {
 		struct reserved_mem *rmem = &reserved_mem[i];
 		unsigned long node = rmem->fdt_node;
+		int len;
+		const __be32 *prop;
 		int err = 0;
 
+		prop = of_get_flat_dt_prop(node, "phandle", &len);
+		if (!prop)
+			prop = of_get_flat_dt_prop(node, "linux,phandle", &len);
+		if (prop)
+			rmem->phandle = of_read_number(prop, len/4);
+
 		if (rmem->size == 0)
 			err = __reserved_mem_alloc_size(node, rmem->name,
 						 &rmem->base, &rmem->size);
@@ -215,3 +223,65 @@ void __init fdt_init_reserved_mem(void)
 			__reserved_mem_init_node(rmem);
 	}
 }
+
+static inline struct reserved_mem *__find_rmem(struct device_node *node)
+{
+	unsigned int i;
+
+	if (!node->phandle)
+		return NULL;
+
+	for (i = 0; i < reserved_mem_count; i++)
+		if (reserved_mem[i].phandle == node->phandle)
+			return &reserved_mem[i];
+	return NULL;
+}
+
+/**
+ * of_reserved_mem_device_init() - assign reserved memory region to given device
+ *
+ * This function assign memory region pointed by "memory-region" device tree
+ * property to the given device.
+ */
+void of_reserved_mem_device_init(struct device *dev)
+{
+	struct reserved_mem *rmem;
+	struct device_node *np;
+
+	np = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (!np)
+		return;
+
+	rmem = __find_rmem(np);
+	of_node_put(np);
+
+	if (!rmem || !rmem->ops || !rmem->ops->device_init)
+		return;
+
+	rmem->ops->device_init(rmem, dev);
+	dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
+}
+
+/**
+ * of_reserved_mem_device_release() - release reserved memory device structures
+ *
+ * This function releases structures allocated for memory region handling for
+ * the given device.
+ */
+void of_reserved_mem_device_release(struct device *dev)
+{
+	struct reserved_mem *rmem;
+	struct device_node *np;
+
+	np = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (!np)
+		return;
+
+	rmem = __find_rmem(np);
+	of_node_put(np);
+
+	if (!rmem || !rmem->ops || !rmem->ops->device_release)
+		return;
+
+	rmem->ops->device_release(rmem, dev);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/platform.c linux-libre-3.17-rc7-gnu/drivers/of/platform.c
--- linux-libre-3.16-gnu/drivers/of/platform.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -422,6 +422,7 @@ static int of_platform_bus_create(struct
 			break;
 		}
 	}
+	of_node_set_flag(bus, OF_POPULATED_BUS);
 	return rc;
 }
 
@@ -508,19 +509,13 @@ EXPORT_SYMBOL_GPL(of_platform_populate);
 
 static int of_platform_device_destroy(struct device *dev, void *data)
 {
-	bool *children_left = data;
-
 	/* Do not touch devices not populated from the device tree */
-	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
-		*children_left = true;
+	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
 		return 0;
-	}
 
-	/* Recurse, but don't touch this device if it has any children left */
-	if (of_platform_depopulate(dev) != 0) {
-		*children_left = true;
-		return 0;
-	}
+	/* Recurse for any nodes that were treated as busses */
+	if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+		device_for_each_child(dev, NULL, of_platform_device_destroy);
 
 	if (dev->bus == &platform_bus_type)
 		platform_device_unregister(to_platform_device(dev));
@@ -528,19 +523,15 @@ static int of_platform_device_destroy(st
 	else if (dev->bus == &amba_bustype)
 		amba_device_unregister(to_amba_device(dev));
 #endif
-	else {
-		*children_left = true;
-		return 0;
-	}
 
 	of_node_clear_flag(dev->of_node, OF_POPULATED);
-
+	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
 	return 0;
 }
 
 /**
  * of_platform_depopulate() - Remove devices populated from device tree
- * @parent: device which childred will be removed
+ * @parent: device which children will be removed
  *
  * Complementary to of_platform_populate(), this function removes children
  * of the given device (and, recurrently, their children) that have been
@@ -550,14 +541,9 @@ static int of_platform_device_destroy(st
  * Returns 0 when all children devices have been removed or
  * -EBUSY when some children remained.
  */
-int of_platform_depopulate(struct device *parent)
+void of_platform_depopulate(struct device *parent)
 {
-	bool children_left = false;
-
-	device_for_each_child(parent, &children_left,
-			      of_platform_device_destroy);
-
-	return children_left ? -EBUSY : 0;
+	device_for_each_child(parent, NULL, of_platform_device_destroy);
 }
 EXPORT_SYMBOL_GPL(of_platform_depopulate);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/selftest.c linux-libre-3.17-rc7-gnu/drivers/of/selftest.c
--- linux-libre-3.16-gnu/drivers/of/selftest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/selftest.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/list.h>
@@ -16,11 +17,18 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 
+#include "of_private.h"
+
 static struct selftest_results {
 	int passed;
 	int failed;
 } selftest_results;
 
+#define NO_OF_NODES 2
+static struct device_node *nodes[NO_OF_NODES];
+static int last_node_index;
+static bool selftest_live_tree;
+
 #define selftest(result, fmt, ...) { \
 	if (!(result)) { \
 		selftest_results.failed++; \
@@ -266,6 +274,81 @@ static void __init of_selftest_property_
 	selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
 }
 
+#define propcmp(p1, p2) (((p1)->length == (p2)->length) && \
+			(p1)->value && (p2)->value && \
+			!memcmp((p1)->value, (p2)->value, (p1)->length) && \
+			!strcmp((p1)->name, (p2)->name))
+static void __init of_selftest_property_copy(void)
+{
+#ifdef CONFIG_OF_DYNAMIC
+	struct property p1 = { .name = "p1", .length = 0, .value = "" };
+	struct property p2 = { .name = "p2", .length = 5, .value = "abcd" };
+	struct property *new;
+
+	new = __of_prop_dup(&p1, GFP_KERNEL);
+	selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n");
+	kfree(new->value);
+	kfree(new->name);
+	kfree(new);
+
+	new = __of_prop_dup(&p2, GFP_KERNEL);
+	selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n");
+	kfree(new->value);
+	kfree(new->name);
+	kfree(new);
+#endif
+}
+
+static void __init of_selftest_changeset(void)
+{
+#ifdef CONFIG_OF_DYNAMIC
+	struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
+	struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
+	struct property *ppremove;
+	struct device_node *n1, *n2, *n21, *nremove, *parent;
+	struct of_changeset chgset;
+
+	of_changeset_init(&chgset);
+	n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL);
+	selftest(n1, "testcase setup failure\n");
+	n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL);
+	selftest(n2, "testcase setup failure\n");
+	n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL);
+	selftest(n21, "testcase setup failure %p\n", n21);
+	nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
+	selftest(nremove, "testcase setup failure\n");
+	ppadd = __of_prop_dup(&padd, GFP_KERNEL);
+	selftest(ppadd, "testcase setup failure\n");
+	ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
+	selftest(ppupdate, "testcase setup failure\n");
+	parent = nremove->parent;
+	n1->parent = parent;
+	n2->parent = parent;
+	n21->parent = n2;
+	n2->child = n21;
+	ppremove = of_find_property(parent, "prop-remove", NULL);
+	selftest(ppremove, "failed to find removal prop");
+
+	of_changeset_init(&chgset);
+	selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
+	selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
+	selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
+	selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
+	selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
+	selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
+	selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
+	mutex_lock(&of_mutex);
+	selftest(!of_changeset_apply(&chgset), "apply failed\n");
+	mutex_unlock(&of_mutex);
+
+	mutex_lock(&of_mutex);
+	selftest(!of_changeset_revert(&chgset), "revert failed\n");
+	mutex_unlock(&of_mutex);
+
+	of_changeset_destroy(&chgset);
+#endif
+}
+
 static void __init of_selftest_parse_interrupts(void)
 {
 	struct device_node *np;
@@ -517,9 +600,177 @@ static void __init of_selftest_platform_
 	}
 }
 
+/**
+ *	update_node_properties - adds the properties
+ *	of np into dup node (present in live tree) and
+ *	updates parent of children of np to dup.
+ *
+ *	@np:	node already present in live tree
+ *	@dup:	node present in live tree to be updated
+ */
+static void update_node_properties(struct device_node *np,
+					struct device_node *dup)
+{
+	struct property *prop;
+	struct device_node *child;
+
+	for_each_property_of_node(np, prop)
+		of_add_property(dup, prop);
+
+	for_each_child_of_node(np, child)
+		child->parent = dup;
+}
+
+/**
+ *	attach_node_and_children - attaches nodes
+ *	and its children to live tree
+ *
+ *	@np:	Node to attach to live tree
+ */
+static int attach_node_and_children(struct device_node *np)
+{
+	struct device_node *next, *root = np, *dup;
+
+	/* skip root node */
+	np = np->child;
+	/* storing a copy in temporary node */
+	dup = np;
+
+	while (dup) {
+		nodes[last_node_index++] = dup;
+		dup = dup->sibling;
+	}
+	dup = NULL;
+
+	while (np) {
+		next = np->allnext;
+		dup = of_find_node_by_path(np->full_name);
+		if (dup)
+			update_node_properties(np, dup);
+		else {
+			np->child = NULL;
+			if (np->parent == root)
+				np->parent = of_allnodes;
+			of_attach_node(np);
+		}
+		np = next;
+	}
+
+	return 0;
+}
+
+/**
+ *	selftest_data_add - Reads, copies data from
+ *	linked tree and attaches it to the live tree
+ */
+static int __init selftest_data_add(void)
+{
+	void *selftest_data;
+	struct device_node *selftest_data_node, *np;
+	extern uint8_t __dtb_testcases_begin[];
+	extern uint8_t __dtb_testcases_end[];
+	const int size = __dtb_testcases_end - __dtb_testcases_begin;
+
+	if (!size) {
+		pr_warn("%s: No testcase data to attach; not running tests\n",
+			__func__);
+		return -ENODATA;
+	}
+
+	/* creating copy */
+	selftest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL);
+
+	if (!selftest_data) {
+		pr_warn("%s: Failed to allocate memory for selftest_data; "
+			"not running tests\n", __func__);
+		return -ENOMEM;
+	}
+	of_fdt_unflatten_tree(selftest_data, &selftest_data_node);
+	if (!selftest_data_node) {
+		pr_warn("%s: No tree to attach; not running tests\n", __func__);
+		return -ENODATA;
+	}
+
+	if (!of_allnodes) {
+		/* enabling flag for removing nodes */
+		selftest_live_tree = true;
+		of_allnodes = selftest_data_node;
+
+		for_each_of_allnodes(np)
+			__of_attach_node_sysfs(np);
+		of_aliases = of_find_node_by_path("/aliases");
+		of_chosen = of_find_node_by_path("/chosen");
+		return 0;
+	}
+
+	/* attach the sub-tree to live tree */
+	return attach_node_and_children(selftest_data_node);
+}
+
+/**
+ *	detach_node_and_children - detaches node
+ *	and its children from live tree
+ *
+ *	@np:	Node to detach from live tree
+ */
+static void detach_node_and_children(struct device_node *np)
+{
+	while (np->child)
+		detach_node_and_children(np->child);
+
+	while (np->sibling)
+		detach_node_and_children(np->sibling);
+
+	of_detach_node(np);
+}
+
+/**
+ *	selftest_data_remove - removes the selftest data
+ *	nodes from the live tree
+ */
+static void selftest_data_remove(void)
+{
+	struct device_node *np;
+	struct property *prop;
+
+	if (selftest_live_tree) {
+		of_node_put(of_aliases);
+		of_node_put(of_chosen);
+		of_aliases = NULL;
+		of_chosen = NULL;
+		for_each_child_of_node(of_allnodes, np)
+			detach_node_and_children(np);
+		__of_detach_node_sysfs(of_allnodes);
+		of_allnodes = NULL;
+		return;
+	}
+
+	while (last_node_index >= 0) {
+		if (nodes[last_node_index]) {
+			np = of_find_node_by_path(nodes[last_node_index]->full_name);
+			if (strcmp(np->full_name, "/aliases") != 0) {
+				detach_node_and_children(np->child);
+				of_detach_node(np);
+			} else {
+				for_each_property_of_node(np, prop) {
+					if (strcmp(prop->name, "testcase-alias") == 0)
+						of_remove_property(np, prop);
+				}
+			}
+		}
+		last_node_index--;
+	}
+}
+
 static int __init of_selftest(void)
 {
 	struct device_node *np;
+	int res;
+
+	/* adding data for selftest */
+	res = selftest_data_add();
+	if (res)
+		return res;
 
 	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
 	if (!np) {
@@ -533,12 +784,18 @@ static int __init of_selftest(void)
 	of_selftest_dynamic();
 	of_selftest_parse_phandle_with_args();
 	of_selftest_property_match_string();
+	of_selftest_property_copy();
+	of_selftest_changeset();
 	of_selftest_parse_interrupts();
 	of_selftest_parse_interrupts_extended();
 	of_selftest_match_node();
 	of_selftest_platform_populate();
 	pr_info("end of selftest - %i passed, %i failed\n",
 		selftest_results.passed, selftest_results.failed);
+
+	/* removing selftest data from live tree */
+	selftest_data_remove();
+
 	return 0;
 }
 late_initcall(of_selftest);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/testcase-data/testcases.dts linux-libre-3.17-rc7-gnu/drivers/of/testcase-data/testcases.dts
--- linux-libre-3.16-gnu/drivers/of/testcase-data/testcases.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/of/testcase-data/testcases.dts	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,15 @@
+/dts-v1/;
+/ {
+	testcase-data {
+		changeset {
+			prop-update = "hello";
+			prop-remove = "world";
+			node-remove {
+			};
+		};
+	};
+};
+#include "tests-phandle.dtsi"
+#include "tests-interrupts.dtsi"
+#include "tests-match.dtsi"
+#include "tests-platform.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/of/testcase-data/testcases.dtsi linux-libre-3.17-rc7-gnu/drivers/of/testcase-data/testcases.dtsi
--- linux-libre-3.16-gnu/drivers/of/testcase-data/testcases.dtsi	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/of/testcase-data/testcases.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#include "tests-phandle.dtsi"
-#include "tests-interrupts.dtsi"
-#include "tests-match.dtsi"
-#include "tests-platform.dtsi"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/parisc/dino.c linux-libre-3.17-rc7-gnu/drivers/parisc/dino.c
--- linux-libre-3.16-gnu/drivers/parisc/dino.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/parisc/dino.c	2014-09-28 17:29:07.000000000 -0400
@@ -913,7 +913,7 @@ static int __init dino_probe(struct pari
 	printk("%s version %s found at 0x%lx\n", name, version, hpa);
 
 	if (!request_mem_region(hpa, PAGE_SIZE, name)) {
-		printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n",
+		printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%lx)!\n",
 			hpa);
 		return 1;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/parisc/pdc_stable.c linux-libre-3.17-rc7-gnu/drivers/parisc/pdc_stable.c
--- linux-libre-3.16-gnu/drivers/parisc/pdc_stable.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/parisc/pdc_stable.c	2014-09-28 17:29:07.000000000 -0400
@@ -278,7 +278,7 @@ pdcspath_hwpath_write(struct pdcspath_en
 {
 	struct hardware_path hwpath;
 	unsigned short i;
-	char in[count+1], *temp;
+	char in[64], *temp;
 	struct device *dev;
 	int ret;
 
@@ -286,8 +286,9 @@ pdcspath_hwpath_write(struct pdcspath_en
 		return -EINVAL;
 
 	/* We'll use a local copy of buf */
-	memset(in, 0, count+1);
+	count = min_t(size_t, count, sizeof(in)-1);
 	strncpy(in, buf, count);
+	in[count] = '\0';
 	
 	/* Let's clean up the target. 0xff is a blank pattern */
 	memset(&hwpath, 0xff, sizeof(hwpath));
@@ -393,14 +394,15 @@ pdcspath_layer_write(struct pdcspath_ent
 {
 	unsigned int layers[6]; /* device-specific info (ctlr#, unit#, ...) */
 	unsigned short i;
-	char in[count+1], *temp;
+	char in[64], *temp;
 
 	if (!entry || !buf || !count)
 		return -EINVAL;
 
 	/* We'll use a local copy of buf */
-	memset(in, 0, count+1);
+	count = min_t(size_t, count, sizeof(in)-1);
 	strncpy(in, buf, count);
+	in[count] = '\0';
 	
 	/* Let's clean up the target. 0 is a blank pattern */
 	memset(&layers, 0, sizeof(layers));
@@ -755,7 +757,7 @@ static ssize_t pdcs_auto_write(struct ko
 {
 	struct pdcspath_entry *pathentry;
 	unsigned char flags;
-	char in[count+1], *temp;
+	char in[8], *temp;
 	char c;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -765,8 +767,9 @@ static ssize_t pdcs_auto_write(struct ko
 		return -EINVAL;
 
 	/* We'll use a local copy of buf */
-	memset(in, 0, count+1);
+	count = min_t(size_t, count, sizeof(in)-1);
 	strncpy(in, buf, count);
+	in[count] = '\0';
 
 	/* Current flags are stored in primary boot path entry */
 	pathentry = &pdcspath_entry_primary;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/parport/parport_ip32.c linux-libre-3.17-rc7-gnu/drivers/parport/parport_ip32.c
--- linux-libre-3.16-gnu/drivers/parport/parport_ip32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/parport/parport_ip32.c	2014-09-28 17:29:07.000000000 -0400
@@ -2204,7 +2204,7 @@ static int __init parport_ip32_init(void
 {
 	pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n");
 	this_port = parport_ip32_probe_port();
-	return IS_ERR(this_port) ? PTR_ERR(this_port) : 0;
+	return PTR_ERR_OR_ZERO(this_port);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/Kconfig linux-libre-3.17-rc7-gnu/drivers/pci/host/Kconfig
--- linux-libre-3.16-gnu/drivers/pci/host/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,18 @@
 menu "PCI host controller drivers"
 	depends on PCI
 
+config PCI_DRA7XX
+	bool "TI DRA7xx PCIe controller"
+	select PCIE_DW
+	depends on OF && HAS_IOMEM && TI_PIPE3
+	help
+	 Enables support for the PCIe controller in the DRA7xx SoC.  There
+	 are two instances of PCIe controller in DRA7xx.  This controller can
+	 act both as EP and RC.  This reuses the Designware core.
+
 config PCI_MVEBU
 	bool "Marvell EBU PCIe controller"
-	depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD
+	depends on ARCH_MVEBU || ARCH_DOVE
 	depends on OF
 
 config PCIE_DW
@@ -46,4 +55,12 @@ config PCI_HOST_GENERIC
 	  Say Y here if you want to support a simple generic PCI host
 	  controller, such as the one emulated by kvmtool.
 
+config PCIE_SPEAR13XX
+	bool "STMicroelectronics SPEAr PCIe controller"
+	depends on ARCH_SPEAR13XX
+	select PCIEPORTBUS
+	select PCIE_DW
+	help
+	  Say Y here if you want PCIe support on SPEAr13XX SoCs.
+
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/Makefile linux-libre-3.17-rc7-gnu/drivers/pci/host/Makefile
--- linux-libre-3.16-gnu/drivers/pci/host/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PCIE_DW) += pcie-designware.o
+obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
@@ -6,3 +7,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
 obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
 obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
+obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pci-dra7xx.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-dra7xx.c
--- linux-libre-3.16-gnu/drivers/pci/host/pci-dra7xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-dra7xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,458 @@
+/*
+ * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs
+ *
+ * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Authors: Kishon Vijay Abraham I <kishon@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/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/resource.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+/* PCIe controller wrapper DRA7XX configuration registers */
+
+#define	PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN		0x0024
+#define	PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN		0x0028
+#define	ERR_SYS						BIT(0)
+#define	ERR_FATAL					BIT(1)
+#define	ERR_NONFATAL					BIT(2)
+#define	ERR_COR						BIT(3)
+#define	ERR_AXI						BIT(4)
+#define	ERR_ECRC					BIT(5)
+#define	PME_TURN_OFF					BIT(8)
+#define	PME_TO_ACK					BIT(9)
+#define	PM_PME						BIT(10)
+#define	LINK_REQ_RST					BIT(11)
+#define	LINK_UP_EVT					BIT(12)
+#define	CFG_BME_EVT					BIT(13)
+#define	CFG_MSE_EVT					BIT(14)
+#define	INTERRUPTS (ERR_SYS | ERR_FATAL | ERR_NONFATAL | ERR_COR | ERR_AXI | \
+			ERR_ECRC | PME_TURN_OFF | PME_TO_ACK | PM_PME | \
+			LINK_REQ_RST | LINK_UP_EVT | CFG_BME_EVT | CFG_MSE_EVT)
+
+#define	PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI		0x0034
+#define	PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI		0x0038
+#define	INTA						BIT(0)
+#define	INTB						BIT(1)
+#define	INTC						BIT(2)
+#define	INTD						BIT(3)
+#define	MSI						BIT(4)
+#define	LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD)
+
+#define	PCIECTRL_DRA7XX_CONF_DEVICE_CMD			0x0104
+#define	LTSSM_EN					0x1
+
+#define	PCIECTRL_DRA7XX_CONF_PHY_CS			0x010C
+#define	LINK_UP						BIT(16)
+
+struct dra7xx_pcie {
+	void __iomem		*base;
+	struct phy		**phy;
+	int			phy_count;
+	struct device		*dev;
+	struct pcie_port	pp;
+};
+
+#define to_dra7xx_pcie(x)	container_of((x), struct dra7xx_pcie, pp)
+
+static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset)
+{
+	return readl(pcie->base + offset);
+}
+
+static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
+				      u32 value)
+{
+	writel(value, pcie->base + offset);
+}
+
+static int dra7xx_pcie_link_up(struct pcie_port *pp)
+{
+	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
+	u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS);
+
+	return !!(reg & LINK_UP);
+}
+
+static int dra7xx_pcie_establish_link(struct pcie_port *pp)
+{
+	u32 reg;
+	unsigned int retries = 1000;
+	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
+
+	if (dw_pcie_link_up(pp)) {
+		dev_err(pp->dev, "link is already up\n");
+		return 0;
+	}
+
+	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
+	reg |= LTSSM_EN;
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
+
+	while (retries--) {
+		reg = dra7xx_pcie_readl(dra7xx,	PCIECTRL_DRA7XX_CONF_PHY_CS);
+		if (reg & LINK_UP)
+			break;
+		usleep_range(10, 20);
+	}
+
+	if (retries == 0) {
+		dev_err(pp->dev, "link is not up\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
+{
+	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
+
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
+			   ~INTERRUPTS);
+	dra7xx_pcie_writel(dra7xx,
+			   PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS);
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
+			   ~LEG_EP_INTERRUPTS & ~MSI);
+
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		dra7xx_pcie_writel(dra7xx,
+				   PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI);
+	else
+		dra7xx_pcie_writel(dra7xx,
+				   PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
+				   LEG_EP_INTERRUPTS);
+}
+
+static void dra7xx_pcie_host_init(struct pcie_port *pp)
+{
+	dw_pcie_setup_rc(pp);
+	dra7xx_pcie_establish_link(pp);
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		dw_pcie_msi_init(pp);
+	dra7xx_pcie_enable_interrupts(pp);
+}
+
+static struct pcie_host_ops dra7xx_pcie_host_ops = {
+	.link_up = dra7xx_pcie_link_up,
+	.host_init = dra7xx_pcie_host_init,
+};
+
+static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+	.map = dra7xx_pcie_intx_map,
+};
+
+static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
+{
+	struct device *dev = pp->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *pcie_intc_node =  of_get_next_child(node, NULL);
+
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found\n");
+		return PTR_ERR(pcie_intc_node);
+	}
+
+	pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
+					       &intx_domain_ops, pp);
+	if (!pp->irq_domain) {
+		dev_err(dev, "Failed to get a INTx IRQ domain\n");
+		return PTR_ERR(pp->irq_domain);
+	}
+
+	return 0;
+}
+
+static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
+{
+	struct pcie_port *pp = arg;
+	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
+	u32 reg;
+
+	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
+
+	switch (reg) {
+	case MSI:
+		dw_handle_msi_irq(pp);
+		break;
+	case INTA:
+	case INTB:
+	case INTC:
+	case INTD:
+		generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg)));
+		break;
+	}
+
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, reg);
+
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
+{
+	struct dra7xx_pcie *dra7xx = arg;
+	u32 reg;
+
+	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
+
+	if (reg & ERR_SYS)
+		dev_dbg(dra7xx->dev, "System Error\n");
+
+	if (reg & ERR_FATAL)
+		dev_dbg(dra7xx->dev, "Fatal Error\n");
+
+	if (reg & ERR_NONFATAL)
+		dev_dbg(dra7xx->dev, "Non Fatal Error\n");
+
+	if (reg & ERR_COR)
+		dev_dbg(dra7xx->dev, "Correctable Error\n");
+
+	if (reg & ERR_AXI)
+		dev_dbg(dra7xx->dev, "AXI tag lookup fatal Error\n");
+
+	if (reg & ERR_ECRC)
+		dev_dbg(dra7xx->dev, "ECRC Error\n");
+
+	if (reg & PME_TURN_OFF)
+		dev_dbg(dra7xx->dev,
+			"Power Management Event Turn-Off message received\n");
+
+	if (reg & PME_TO_ACK)
+		dev_dbg(dra7xx->dev,
+			"Power Management Turn-Off Ack message received\n");
+
+	if (reg & PM_PME)
+		dev_dbg(dra7xx->dev,
+			"PM Power Management Event message received\n");
+
+	if (reg & LINK_REQ_RST)
+		dev_dbg(dra7xx->dev, "Link Request Reset\n");
+
+	if (reg & LINK_UP_EVT)
+		dev_dbg(dra7xx->dev, "Link-up state change\n");
+
+	if (reg & CFG_BME_EVT)
+		dev_dbg(dra7xx->dev, "CFG 'Bus Master Enable' change\n");
+
+	if (reg & CFG_MSE_EVT)
+		dev_dbg(dra7xx->dev, "CFG 'Memory Space Enable' change\n");
+
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg);
+
+	return IRQ_HANDLED;
+}
+
+static int add_pcie_port(struct dra7xx_pcie *dra7xx,
+			  struct platform_device *pdev)
+{
+	int ret;
+	struct pcie_port *pp;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	pp = &dra7xx->pp;
+	pp->dev = dev;
+	pp->ops = &dra7xx_pcie_host_ops;
+
+	pp->irq = platform_get_irq(pdev, 1);
+	if (pp->irq < 0) {
+		dev_err(dev, "missing IRQ resource\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(&pdev->dev, pp->irq,
+			       dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
+			       "dra7-pcie-msi",	pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		return ret;
+	}
+
+	if (!IS_ENABLED(CONFIG_PCI_MSI)) {
+		ret = dra7xx_pcie_init_irq_domain(pp);
+		if (ret < 0)
+			return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics");
+	pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!pp->dbi_base)
+		return -ENOMEM;
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(dra7xx->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init dra7xx_pcie_probe(struct platform_device *pdev)
+{
+	u32 reg;
+	int ret;
+	int irq;
+	int i;
+	int phy_count;
+	struct phy **phy;
+	void __iomem *base;
+	struct resource *res;
+	struct dra7xx_pcie *dra7xx;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	char name[10];
+
+	dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
+	if (!dra7xx)
+		return -ENOMEM;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "missing IRQ resource\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler,
+			       IRQF_SHARED, "dra7xx-pcie-main", dra7xx);
+	if (ret) {
+		dev_err(dev, "failed to request irq\n");
+		return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf");
+	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!base)
+		return -ENOMEM;
+
+	phy_count = of_property_count_strings(np, "phy-names");
+	if (phy_count < 0) {
+		dev_err(dev, "unable to find the strings\n");
+		return phy_count;
+	}
+
+	phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	for (i = 0; i < phy_count; i++) {
+		snprintf(name, sizeof(name), "pcie-phy%d", i);
+		phy[i] = devm_phy_get(dev, name);
+		if (IS_ERR(phy[i]))
+			return PTR_ERR(phy[i]);
+
+		ret = phy_init(phy[i]);
+		if (ret < 0)
+			goto err_phy;
+
+		ret = phy_power_on(phy[i]);
+		if (ret < 0) {
+			phy_exit(phy[i]);
+			goto err_phy;
+		}
+	}
+
+	dra7xx->base = base;
+	dra7xx->phy = phy;
+	dra7xx->dev = dev;
+	dra7xx->phy_count = phy_count;
+
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(dev, "pm_runtime_get_sync failed\n");
+		goto err_phy;
+	}
+
+	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
+	reg &= ~LTSSM_EN;
+	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
+
+	platform_set_drvdata(pdev, dra7xx);
+
+	ret = add_pcie_port(dra7xx, pdev);
+	if (ret < 0)
+		goto err_add_port;
+
+	return 0;
+
+err_add_port:
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+
+err_phy:
+	while (--i >= 0) {
+		phy_power_off(phy[i]);
+		phy_exit(phy[i]);
+	}
+
+	return ret;
+}
+
+static int __exit dra7xx_pcie_remove(struct platform_device *pdev)
+{
+	struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev);
+	struct pcie_port *pp = &dra7xx->pp;
+	struct device *dev = &pdev->dev;
+	int count = dra7xx->phy_count;
+
+	if (pp->irq_domain)
+		irq_domain_remove(pp->irq_domain);
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+	while (count--) {
+		phy_power_off(dra7xx->phy[count]);
+		phy_exit(dra7xx->phy[count]);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id of_dra7xx_pcie_match[] = {
+	{ .compatible = "ti,dra7-pcie", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match);
+
+static struct platform_driver dra7xx_pcie_driver = {
+	.remove		= __exit_p(dra7xx_pcie_remove),
+	.driver = {
+		.name	= "dra7-pcie",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_dra7xx_pcie_match,
+	},
+};
+
+module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe);
+
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_DESCRIPTION("TI PCIe controller driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pcie-designware.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-designware.c
--- linux-libre-3.16-gnu/drivers/pci/host/pcie-designware.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-designware.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/pci_regs.h>
+#include <linux/platform_device.h>
 #include <linux/types.h>
 
 #include "pcie-designware.h"
@@ -217,27 +218,47 @@ static int find_valid_pos0(struct pcie_p
 	return 0;
 }
 
+static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
+{
+	unsigned int res, bit, val;
+
+	res = (irq / 32) * 12;
+	bit = irq % 32;
+	dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val &= ~(1 << bit);
+	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+}
+
 static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,
 			    unsigned int nvec, unsigned int pos)
 {
-	unsigned int i, res, bit, val;
+	unsigned int i;
 
 	for (i = 0; i < nvec; i++) {
 		irq_set_msi_desc_off(irq_base, i, NULL);
 		clear_bit(pos + i, pp->msi_irq_in_use);
 		/* Disable corresponding interrupt on MSI controller */
-		res = ((pos + i) / 32) * 12;
-		bit = (pos + i) % 32;
-		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
-		val &= ~(1 << bit);
-		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+		if (pp->ops->msi_clear_irq)
+			pp->ops->msi_clear_irq(pp, pos + i);
+		else
+			dw_pcie_msi_clear_irq(pp, pos + i);
 	}
 }
 
+static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
+{
+	unsigned int res, bit, val;
+
+	res = (irq / 32) * 12;
+	bit = irq % 32;
+	dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val |= 1 << bit;
+	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+}
+
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
-	int res, bit, irq, pos0, pos1, i;
-	u32 val;
+	int irq, pos0, pos1, i;
 	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
 
 	if (!pp) {
@@ -281,11 +302,10 @@ static int assign_irq(int no_irqs, struc
 		}
 		set_bit(pos0 + i, pp->msi_irq_in_use);
 		/*Enable corresponding interrupt in MSI interrupt controller */
-		res = ((pos0 + i) / 32) * 12;
-		bit = (pos0 + i) % 32;
-		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
-		val |= 1 << bit;
-		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+		if (pp->ops->msi_set_irq)
+			pp->ops->msi_set_irq(pp, pos0 + i);
+		else
+			dw_pcie_msi_set_irq(pp, pos0 + i);
 	}
 
 	*pos = pos0;
@@ -353,7 +373,10 @@ static int dw_msi_setup_irq(struct msi_c
 	 */
 	desc->msi_attrib.multiple = msgvec;
 
-	msg.address_lo = virt_to_phys((void *)pp->msi_data);
+	if (pp->ops->get_msi_data)
+		msg.address_lo = pp->ops->get_msi_data(pp);
+	else
+		msg.address_lo = virt_to_phys((void *)pp->msi_data);
 	msg.address_hi = 0x0;
 	msg.data = pos;
 	write_msi_msg(irq, &msg);
@@ -396,10 +419,35 @@ static const struct irq_domain_ops msi_d
 int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
+	struct platform_device *pdev = to_platform_device(pp->dev);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
-	u32 val;
-	int i;
+	struct resource *cfg_res;
+	u32 val, na, ns;
+	const __be32 *addrp;
+	int i, index;
+
+	/* Find the address cell size and the number of cells in order to get
+	 * the untranslated address.
+	 */
+	of_property_read_u32(np, "#address-cells", &na);
+	ns = of_n_size_cells(np);
+
+	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+	if (cfg_res) {
+		pp->config.cfg0_size = resource_size(cfg_res)/2;
+		pp->config.cfg1_size = resource_size(cfg_res)/2;
+		pp->cfg0_base = cfg_res->start;
+		pp->cfg1_base = cfg_res->start + pp->config.cfg0_size;
+
+		/* Find the untranslated configuration space address */
+		index = of_property_match_string(np, "reg-names", "config");
+		addrp = of_get_address(np, index, false, false);
+		pp->cfg0_mod_base = of_read_number(addrp, ns);
+		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->config.cfg0_size;
+	} else {
+		dev_err(pp->dev, "missing *config* reg space\n");
+	}
 
 	if (of_pci_range_parser_init(&parser, np)) {
 		dev_err(pp->dev, "missing ranges property\n");
@@ -422,17 +470,33 @@ int __init dw_pcie_host_init(struct pcie
 			pp->config.io_size = resource_size(&pp->io);
 			pp->config.io_bus_addr = range.pci_addr;
 			pp->io_base = range.cpu_addr;
+
+			/* Find the untranslated IO space address */
+			pp->io_mod_base = of_read_number(parser.range -
+							 parser.np + na, ns);
 		}
 		if (restype == IORESOURCE_MEM) {
 			of_pci_range_to_resource(&range, np, &pp->mem);
 			pp->mem.name = "MEM";
 			pp->config.mem_size = resource_size(&pp->mem);
 			pp->config.mem_bus_addr = range.pci_addr;
+
+			/* Find the untranslated MEM space address */
+			pp->mem_mod_base = of_read_number(parser.range -
+							  parser.np + na, ns);
 		}
 		if (restype == 0) {
 			of_pci_range_to_resource(&range, np, &pp->cfg);
 			pp->config.cfg0_size = resource_size(&pp->cfg)/2;
 			pp->config.cfg1_size = resource_size(&pp->cfg)/2;
+			pp->cfg0_base = pp->cfg.start;
+			pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
+
+			/* Find the untranslated configuration space address */
+			pp->cfg0_mod_base = of_read_number(parser.range -
+							   parser.np + na, ns);
+			pp->cfg1_mod_base = pp->cfg0_mod_base +
+					    pp->config.cfg0_size;
 		}
 	}
 
@@ -445,8 +509,6 @@ int __init dw_pcie_host_init(struct pcie
 		}
 	}
 
-	pp->cfg0_base = pp->cfg.start;
-	pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
 	pp->mem_base = pp->mem.start;
 
 	pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -509,9 +571,9 @@ static void dw_pcie_prog_viewport_cfg0(s
 	/* Program viewport 0 : OUTBOUND : CFG0 */
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
 			  PCIE_ATU_VIEWPORT);
-	dw_pcie_writel_rc(pp, pp->cfg0_base, PCIE_ATU_LOWER_BASE);
-	dw_pcie_writel_rc(pp, (pp->cfg0_base >> 32), PCIE_ATU_UPPER_BASE);
-	dw_pcie_writel_rc(pp, pp->cfg0_base + pp->config.cfg0_size - 1,
+	dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE);
+	dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+	dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->config.cfg0_size - 1,
 			  PCIE_ATU_LIMIT);
 	dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
@@ -525,9 +587,9 @@ static void dw_pcie_prog_viewport_cfg1(s
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE);
-	dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE);
-	dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1,
+	dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE);
+	dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+	dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->config.cfg1_size - 1,
 			  PCIE_ATU_LIMIT);
 	dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
@@ -540,9 +602,9 @@ static void dw_pcie_prog_viewport_mem_ou
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);
-	dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);
-	dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1,
+	dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE);
+	dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+	dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->config.mem_size - 1,
 			  PCIE_ATU_LIMIT);
 	dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
@@ -556,9 +618,9 @@ static void dw_pcie_prog_viewport_io_out
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);
-	dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);
-	dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1,
+	dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE);
+	dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+	dw_pcie_writel_rc(pp, pp->io_mod_base + pp->config.io_size - 1,
 			  PCIE_ATU_LIMIT);
 	dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
@@ -656,7 +718,11 @@ static int dw_pcie_rd_conf(struct pci_bu
 	}
 
 	if (bus->number != pp->root_bus_nr)
-		ret = dw_pcie_rd_other_conf(pp, bus, devfn,
+		if (pp->ops->rd_other_conf)
+			ret = pp->ops->rd_other_conf(pp, bus, devfn,
+						where, size, val);
+		else
+			ret = dw_pcie_rd_other_conf(pp, bus, devfn,
 						where, size, val);
 	else
 		ret = dw_pcie_rd_own_conf(pp, where, size, val);
@@ -679,7 +745,11 @@ static int dw_pcie_wr_conf(struct pci_bu
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	if (bus->number != pp->root_bus_nr)
-		ret = dw_pcie_wr_other_conf(pp, bus, devfn,
+		if (pp->ops->wr_other_conf)
+			ret = pp->ops->wr_other_conf(pp, bus, devfn,
+						where, size, val);
+		else
+			ret = dw_pcie_wr_other_conf(pp, bus, devfn,
 						where, size, val);
 	else
 		ret = dw_pcie_wr_own_conf(pp, where, size, val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pcie-designware.h linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-designware.h
--- linux-libre-3.16-gnu/drivers/pci/host/pcie-designware.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-designware.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,11 +36,15 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
+	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u64			cfg1_base;
+	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u64			io_base;
+	u64			io_mod_base;
 	u64			mem_base;
+	u64			mem_mod_base;
 	struct resource		cfg;
 	struct resource		io;
 	struct resource		mem;
@@ -61,8 +65,15 @@ struct pcie_host_ops {
 			u32 val, void __iomem *dbi_base);
 	int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
 	int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
+	int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
+			unsigned int devfn, int where, int size, u32 *val);
+	int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
+			unsigned int devfn, int where, int size, u32 val);
 	int (*link_up)(struct pcie_port *pp);
 	void (*host_init)(struct pcie_port *pp);
+	void (*msi_set_irq)(struct pcie_port *pp, int irq);
+	void (*msi_clear_irq)(struct pcie_port *pp, int irq);
+	u32 (*get_msi_data)(struct pcie_port *pp);
 };
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pcie-rcar.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-rcar.c
--- linux-libre-3.16-gnu/drivers/pci/host/pcie-rcar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-rcar.c	2014-09-28 17:29:07.000000000 -0400
@@ -105,7 +105,7 @@
 #define  PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
 #define  PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
 
-#define PCI_MAX_RESOURCES 4
+#define RCAR_PCI_MAX_RESOURCES 4
 #define MAX_NR_INBOUND_MAPS 6
 
 struct rcar_msi {
@@ -127,7 +127,7 @@ static inline struct rcar_msi *to_rcar_m
 struct rcar_pcie {
 	struct device		*dev;
 	void __iomem		*base;
-	struct resource		res[PCI_MAX_RESOURCES];
+	struct resource		res[RCAR_PCI_MAX_RESOURCES];
 	struct resource		busn;
 	int			root_bus_nr;
 	struct clk		*clk;
@@ -140,36 +140,37 @@ static inline struct rcar_pcie *sys_to_p
 	return sys->private_data;
 }
 
-static void pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
-			  unsigned long reg)
+static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
+			       unsigned long reg)
 {
 	writel(val, pcie->base + reg);
 }
 
-static unsigned long pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
+static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie,
+				       unsigned long reg)
 {
 	return readl(pcie->base + reg);
 }
 
 enum {
-	PCI_ACCESS_READ,
-	PCI_ACCESS_WRITE,
+	RCAR_PCI_ACCESS_READ,
+	RCAR_PCI_ACCESS_WRITE,
 };
 
 static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
 {
 	int shift = 8 * (where & 3);
-	u32 val = pci_read_reg(pcie, where & ~3);
+	u32 val = rcar_pci_read_reg(pcie, where & ~3);
 
 	val &= ~(mask << shift);
 	val |= data << shift;
-	pci_write_reg(pcie, val, where & ~3);
+	rcar_pci_write_reg(pcie, val, where & ~3);
 }
 
 static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
 {
 	int shift = 8 * (where & 3);
-	u32 val = pci_read_reg(pcie, where & ~3);
+	u32 val = rcar_pci_read_reg(pcie, where & ~3);
 
 	return val >> shift;
 }
@@ -205,14 +206,14 @@ static int rcar_pcie_config_access(struc
 		if (dev != 0)
 			return PCIBIOS_DEVICE_NOT_FOUND;
 
-		if (access_type == PCI_ACCESS_READ) {
-			*data = pci_read_reg(pcie, PCICONF(index));
+		if (access_type == RCAR_PCI_ACCESS_READ) {
+			*data = rcar_pci_read_reg(pcie, PCICONF(index));
 		} else {
 			/* Keep an eye out for changes to the root bus number */
 			if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
 				pcie->root_bus_nr = *data & 0xff;
 
-			pci_write_reg(pcie, *data, PCICONF(index));
+			rcar_pci_write_reg(pcie, *data, PCICONF(index));
 		}
 
 		return PCIBIOS_SUCCESSFUL;
@@ -222,20 +223,20 @@ static int rcar_pcie_config_access(struc
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	/* Clear errors */
-	pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+	rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
 
 	/* Set the PIO address */
-	pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) |
-				PCIE_CONF_FUNC(func) | reg, PCIECAR);
+	rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
+		PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
 
 	/* Enable the configuration access */
 	if (bus->parent->number == pcie->root_bus_nr)
-		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+		rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
 	else
-		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+		rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
 
 	/* Check for errors */
-	if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+	if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	/* Check for master and target aborts */
@@ -243,13 +244,13 @@ static int rcar_pcie_config_access(struc
 		(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (access_type == PCI_ACCESS_READ)
-		*data = pci_read_reg(pcie, PCIECDR);
+	if (access_type == RCAR_PCI_ACCESS_READ)
+		*data = rcar_pci_read_reg(pcie, PCIECDR);
 	else
-		pci_write_reg(pcie, *data, PCIECDR);
+		rcar_pci_write_reg(pcie, *data, PCIECDR);
 
 	/* Disable the configuration access */
-	pci_write_reg(pcie, 0, PCIECCTLR);
+	rcar_pci_write_reg(pcie, 0, PCIECCTLR);
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -260,12 +261,7 @@ static int rcar_pcie_read_conf(struct pc
 	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
 	int ret;
 
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+	ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
 				      bus, devfn, where, val);
 	if (ret != PCIBIOS_SUCCESSFUL) {
 		*val = 0xffffffff;
@@ -291,12 +287,7 @@ static int rcar_pcie_write_conf(struct p
 	int shift, ret;
 	u32 data;
 
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+	ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
 				      bus, devfn, where, &data);
 	if (ret != PCIBIOS_SUCCESSFUL)
 		return ret;
@@ -315,7 +306,7 @@ static int rcar_pcie_write_conf(struct p
 	} else
 		data = val;
 
-	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
+	ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_WRITE,
 				      bus, devfn, where, &data);
 
 	return ret;
@@ -326,14 +317,15 @@ static struct pci_ops rcar_pcie_ops = {
 	.write	= rcar_pcie_write_conf,
 };
 
-static void rcar_pcie_setup_window(int win, struct resource *res,
-				   struct rcar_pcie *pcie)
+static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
 {
+	struct resource *res = &pcie->res[win];
+
 	/* Setup PCIe address space mappings for each resource */
 	resource_size_t size;
 	u32 mask;
 
-	pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
+	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
 
 	/*
 	 * The PAMR mask is calculated in units of 128Bytes, which
@@ -341,17 +333,17 @@ static void rcar_pcie_setup_window(int w
 	 */
 	size = resource_size(res);
 	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
-	pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
+	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
 
-	pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
-	pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
+	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
 
 	/* First resource is for IO */
 	mask = PAR_ENABLE;
 	if (res->flags & IORESOURCE_IO)
 		mask |= IO_SPACE;
 
-	pci_write_reg(pcie, mask, PCIEPTCTLR(win));
+	rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
 }
 
 static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
@@ -363,13 +355,13 @@ static int rcar_pcie_setup(int nr, struc
 	pcie->root_bus_nr = -1;
 
 	/* Setup PCI resources */
-	for (i = 0; i < PCI_MAX_RESOURCES; i++) {
+	for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
 
 		res = &pcie->res[i];
 		if (!res->flags)
 			continue;
 
-		rcar_pcie_setup_window(i, res, pcie);
+		rcar_pcie_setup_window(i, pcie);
 
 		if (res->flags & IORESOURCE_IO)
 			pci_ioremap_io(nr * SZ_64K, res->start);
@@ -415,7 +407,7 @@ static int phy_wait_for_ack(struct rcar_
 	unsigned int timeout = 100;
 
 	while (timeout--) {
-		if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+		if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
 			return 0;
 
 		udelay(100);
@@ -438,15 +430,15 @@ static void phy_write_reg(struct rcar_pc
 		((addr & 0xff) << ADR_POS);
 
 	/* Set write data */
-	pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
-	pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+	rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
+	rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
 
 	/* Ignore errors as they will be dealt with if the data link is down */
 	phy_wait_for_ack(pcie);
 
 	/* Clear command */
-	pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
-	pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+	rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
+	rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
 
 	/* Ignore errors as they will be dealt with if the data link is down */
 	phy_wait_for_ack(pcie);
@@ -457,7 +449,7 @@ static int rcar_pcie_wait_for_dl(struct
 	unsigned int timeout = 10;
 
 	while (timeout--) {
-		if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+		if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
 			return 0;
 
 		msleep(5);
@@ -471,17 +463,17 @@ static int rcar_pcie_hw_init(struct rcar
 	int err;
 
 	/* Begin initialization */
-	pci_write_reg(pcie, 0, PCIETCTLR);
+	rcar_pci_write_reg(pcie, 0, PCIETCTLR);
 
 	/* Set mode */
-	pci_write_reg(pcie, 1, PCIEMSR);
+	rcar_pci_write_reg(pcie, 1, PCIEMSR);
 
 	/*
 	 * Initial header for port config space is type 1, set the device
 	 * class to match. Hardware takes care of propagating the IDSETR
 	 * settings, so there is no need to bother with a quirk.
 	 */
-	pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+	rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
 
 	/*
 	 * Setup Secondary Bus Number & Subordinate Bus Number, even though
@@ -491,33 +483,31 @@ static int rcar_pcie_hw_init(struct rcar
 	rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
 
 	/* Initialize default capabilities. */
-	rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
+	rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
 	rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
 		PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
 	rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
 		PCI_HEADER_TYPE_BRIDGE);
 
 	/* Enable data link layer active state reporting */
-	rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC);
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
+		PCI_EXP_LNKCAP_DLLLARC);
 
 	/* Write out the physical slot number = 0 */
 	rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
 
 	/* Set the completion timer timeout to the maximum 50ms. */
-	rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
+	rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
 
 	/* Terminate list of capabilities (Next Capability Offset=0) */
-	rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
-
-	/* Enable MAC data scrambling. */
-	rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
+	rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
 
 	/* Enable MSI */
 	if (IS_ENABLED(CONFIG_PCI_MSI))
-		pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
+		rcar_pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
 
 	/* Finish initialization - establish a PCI Express link */
-	pci_write_reg(pcie, CFINIT, PCIETCTLR);
+	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
 
 	/* This will timeout if we don't have a link. */
 	err = rcar_pcie_wait_for_dl(pcie);
@@ -527,11 +517,6 @@ static int rcar_pcie_hw_init(struct rcar
 	/* Enable INTx interrupts */
 	rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
 
-	/* Enable slave Bus Mastering */
-	rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
-		PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-		PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
-
 	wmb();
 
 	return 0;
@@ -560,7 +545,7 @@ static int rcar_pcie_hw_init_h1(struct r
 	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
 
 	while (timeout--) {
-		if (pci_read_reg(pcie, H1_PCIEPHYSR))
+		if (rcar_pci_read_reg(pcie, H1_PCIEPHYSR))
 			return rcar_pcie_hw_init(pcie);
 
 		msleep(5);
@@ -599,7 +584,7 @@ static irqreturn_t rcar_pcie_msi_irq(int
 	struct rcar_msi *msi = &pcie->msi;
 	unsigned long reg;
 
-	reg = pci_read_reg(pcie, PCIEMSIFR);
+	reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
 
 	/* MSI & INTx share an interrupt - we only handle MSI here */
 	if (!reg)
@@ -610,7 +595,7 @@ static irqreturn_t rcar_pcie_msi_irq(int
 		unsigned int irq;
 
 		/* clear the interrupt */
-		pci_write_reg(pcie, 1 << index, PCIEMSIFR);
+		rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
 
 		irq = irq_find_mapping(msi->domain, index);
 		if (irq) {
@@ -624,7 +609,7 @@ static irqreturn_t rcar_pcie_msi_irq(int
 		}
 
 		/* see if there's any more pending in this vector */
-		reg = pci_read_reg(pcie, PCIEMSIFR);
+		reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
 	}
 
 	return IRQ_HANDLED;
@@ -651,8 +636,8 @@ static int rcar_msi_setup_irq(struct msi
 
 	irq_set_msi_desc(irq, desc);
 
-	msg.address_lo = pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
-	msg.address_hi = pci_read_reg(pcie, PCIEMSIAUR);
+	msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
+	msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
 	msg.data = hwirq;
 
 	write_msi_msg(irq, &msg);
@@ -729,11 +714,11 @@ static int rcar_pcie_enable_msi(struct r
 	msi->pages = __get_free_pages(GFP_KERNEL, 0);
 	base = virt_to_phys((void *)msi->pages);
 
-	pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
-	pci_write_reg(pcie, 0, PCIEMSIAUR);
+	rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
+	rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
 
 	/* enable all MSI interrupts */
-	pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+	rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
 
 	return 0;
 
@@ -826,6 +811,7 @@ static int rcar_pcie_inbound_ranges(stru
 	if (cpu_addr > 0) {
 		unsigned long nr_zeros = __ffs64(cpu_addr);
 		u64 alignment = 1ULL << nr_zeros;
+
 		size = min(range->size, alignment);
 	} else {
 		size = range->size;
@@ -841,13 +827,13 @@ static int rcar_pcie_inbound_ranges(stru
 		 * Set up 64-bit inbound regions as the range parser doesn't
 		 * distinguish between 32 and 64-bit types.
 		 */
-		pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
-		pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
-		pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
+		rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
+		rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
+		rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
 
-		pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
-		pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
-		pci_write_reg(pcie, 0, PCIELAMR(idx+1));
+		rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
+		rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
+		rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
 
 		pci_addr += size;
 		cpu_addr += size;
@@ -952,7 +938,7 @@ static int rcar_pcie_probe(struct platfo
 		of_pci_range_to_resource(&range, pdev->dev.of_node,
 						&pcie->res[win++]);
 
-		if (win > PCI_MAX_RESOURCES)
+		if (win > RCAR_PCI_MAX_RESOURCES)
 			break;
 	}
 
@@ -982,7 +968,7 @@ static int rcar_pcie_probe(struct platfo
 		return 0;
 	}
 
-	data = pci_read_reg(pcie, MACSR);
+	data = rcar_pci_read_reg(pcie, MACSR);
 	dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
 
 	rcar_pcie_enable(pcie);
@@ -1003,4 +989,4 @@ module_platform_driver(rcar_pcie_driver)
 
 MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
 MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pcie-spear13xx.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-spear13xx.c
--- linux-libre-3.16-gnu/drivers/pci/host/pcie-spear13xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pcie-spear13xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,393 @@
+/*
+ * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs
+ *
+ * SPEAr13xx PCIe Glue Layer Source Code
+ *
+ * Copyright (C) 2010-2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+
+#include "pcie-designware.h"
+
+struct spear13xx_pcie {
+	void __iomem		*app_base;
+	struct phy		*phy;
+	struct clk		*clk;
+	struct pcie_port	pp;
+	bool			is_gen1;
+};
+
+struct pcie_app_reg {
+	u32	app_ctrl_0;		/* cr0 */
+	u32	app_ctrl_1;		/* cr1 */
+	u32	app_status_0;		/* cr2 */
+	u32	app_status_1;		/* cr3 */
+	u32	msg_status;		/* cr4 */
+	u32	msg_payload;		/* cr5 */
+	u32	int_sts;		/* cr6 */
+	u32	int_clr;		/* cr7 */
+	u32	int_mask;		/* cr8 */
+	u32	mst_bmisc;		/* cr9 */
+	u32	phy_ctrl;		/* cr10 */
+	u32	phy_status;		/* cr11 */
+	u32	cxpl_debug_info_0;	/* cr12 */
+	u32	cxpl_debug_info_1;	/* cr13 */
+	u32	ven_msg_ctrl_0;		/* cr14 */
+	u32	ven_msg_ctrl_1;		/* cr15 */
+	u32	ven_msg_data_0;		/* cr16 */
+	u32	ven_msg_data_1;		/* cr17 */
+	u32	ven_msi_0;		/* cr18 */
+	u32	ven_msi_1;		/* cr19 */
+	u32	mst_rmisc;		/* cr20 */
+};
+
+/* CR0 ID */
+#define RX_LANE_FLIP_EN_ID			0
+#define TX_LANE_FLIP_EN_ID			1
+#define SYS_AUX_PWR_DET_ID			2
+#define APP_LTSSM_ENABLE_ID			3
+#define SYS_ATTEN_BUTTON_PRESSED_ID		4
+#define SYS_MRL_SENSOR_STATE_ID			5
+#define SYS_PWR_FAULT_DET_ID			6
+#define SYS_MRL_SENSOR_CHGED_ID			7
+#define SYS_PRE_DET_CHGED_ID			8
+#define SYS_CMD_CPLED_INT_ID			9
+#define APP_INIT_RST_0_ID			11
+#define APP_REQ_ENTR_L1_ID			12
+#define APP_READY_ENTR_L23_ID			13
+#define APP_REQ_EXIT_L1_ID			14
+#define DEVICE_TYPE_EP				(0 << 25)
+#define DEVICE_TYPE_LEP				(1 << 25)
+#define DEVICE_TYPE_RC				(4 << 25)
+#define SYS_INT_ID				29
+#define MISCTRL_EN_ID				30
+#define REG_TRANSLATION_ENABLE			31
+
+/* CR1 ID */
+#define APPS_PM_XMT_TURNOFF_ID			2
+#define APPS_PM_XMT_PME_ID			5
+
+/* CR3 ID */
+#define XMLH_LTSSM_STATE_DETECT_QUIET		0x00
+#define XMLH_LTSSM_STATE_DETECT_ACT		0x01
+#define XMLH_LTSSM_STATE_POLL_ACTIVE		0x02
+#define XMLH_LTSSM_STATE_POLL_COMPLIANCE	0x03
+#define XMLH_LTSSM_STATE_POLL_CONFIG		0x04
+#define XMLH_LTSSM_STATE_PRE_DETECT_QUIET	0x05
+#define XMLH_LTSSM_STATE_DETECT_WAIT		0x06
+#define XMLH_LTSSM_STATE_CFG_LINKWD_START	0x07
+#define XMLH_LTSSM_STATE_CFG_LINKWD_ACEPT	0x08
+#define XMLH_LTSSM_STATE_CFG_LANENUM_WAIT	0x09
+#define XMLH_LTSSM_STATE_CFG_LANENUM_ACEPT	0x0A
+#define XMLH_LTSSM_STATE_CFG_COMPLETE		0x0B
+#define XMLH_LTSSM_STATE_CFG_IDLE		0x0C
+#define XMLH_LTSSM_STATE_RCVRY_LOCK		0x0D
+#define XMLH_LTSSM_STATE_RCVRY_SPEED		0x0E
+#define XMLH_LTSSM_STATE_RCVRY_RCVRCFG		0x0F
+#define XMLH_LTSSM_STATE_RCVRY_IDLE		0x10
+#define XMLH_LTSSM_STATE_L0			0x11
+#define XMLH_LTSSM_STATE_L0S			0x12
+#define XMLH_LTSSM_STATE_L123_SEND_EIDLE	0x13
+#define XMLH_LTSSM_STATE_L1_IDLE		0x14
+#define XMLH_LTSSM_STATE_L2_IDLE		0x15
+#define XMLH_LTSSM_STATE_L2_WAKE		0x16
+#define XMLH_LTSSM_STATE_DISABLED_ENTRY		0x17
+#define XMLH_LTSSM_STATE_DISABLED_IDLE		0x18
+#define XMLH_LTSSM_STATE_DISABLED		0x19
+#define XMLH_LTSSM_STATE_LPBK_ENTRY		0x1A
+#define XMLH_LTSSM_STATE_LPBK_ACTIVE		0x1B
+#define XMLH_LTSSM_STATE_LPBK_EXIT		0x1C
+#define XMLH_LTSSM_STATE_LPBK_EXIT_TIMEOUT	0x1D
+#define XMLH_LTSSM_STATE_HOT_RESET_ENTRY	0x1E
+#define XMLH_LTSSM_STATE_HOT_RESET		0x1F
+#define XMLH_LTSSM_STATE_MASK			0x3F
+#define XMLH_LINK_UP				(1 << 6)
+
+/* CR4 ID */
+#define CFG_MSI_EN_ID				18
+
+/* CR6 */
+#define INTA_CTRL_INT				(1 << 7)
+#define INTB_CTRL_INT				(1 << 8)
+#define INTC_CTRL_INT				(1 << 9)
+#define INTD_CTRL_INT				(1 << 10)
+#define MSI_CTRL_INT				(1 << 26)
+
+/* CR19 ID */
+#define VEN_MSI_REQ_ID				11
+#define VEN_MSI_FUN_NUM_ID			8
+#define VEN_MSI_TC_ID				5
+#define VEN_MSI_VECTOR_ID			0
+#define VEN_MSI_REQ_EN		((u32)0x1 << VEN_MSI_REQ_ID)
+#define VEN_MSI_FUN_NUM_MASK	((u32)0x7 << VEN_MSI_FUN_NUM_ID)
+#define VEN_MSI_TC_MASK		((u32)0x7 << VEN_MSI_TC_ID)
+#define VEN_MSI_VECTOR_MASK	((u32)0x1F << VEN_MSI_VECTOR_ID)
+
+#define EXP_CAP_ID_OFFSET			0x70
+
+#define to_spear13xx_pcie(x)	container_of(x, struct spear13xx_pcie, pp)
+
+static int spear13xx_pcie_establish_link(struct pcie_port *pp)
+{
+	u32 val;
+	int count = 0;
+	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+	struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+	u32 exp_cap_off = EXP_CAP_ID_OFFSET;
+
+	if (dw_pcie_link_up(pp)) {
+		dev_err(pp->dev, "link already up\n");
+		return 0;
+	}
+
+	dw_pcie_setup_rc(pp);
+
+	/*
+	 * this controller support only 128 bytes read size, however its
+	 * default value in capability register is 512 bytes. So force
+	 * it to 128 here.
+	 */
+	dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
+	val &= ~PCI_EXP_DEVCTL_READRQ;
+	dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
+
+	dw_pcie_cfg_write(pp->dbi_base, PCI_VENDOR_ID, 2, 0x104A);
+	dw_pcie_cfg_write(pp->dbi_base, PCI_DEVICE_ID, 2, 0xCD80);
+
+	/*
+	 * if is_gen1 is set then handle it, so that some buggy card
+	 * also works
+	 */
+	if (spear13xx_pcie->is_gen1) {
+		dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCAP, 4,
+				 &val);
+		if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
+			val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+			val |= PCI_EXP_LNKCAP_SLS_2_5GB;
+			dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
+					  PCI_EXP_LNKCAP, 4, val);
+		}
+
+		dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCTL2, 4,
+				 &val);
+		if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
+			val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+			val |= PCI_EXP_LNKCAP_SLS_2_5GB;
+			dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
+					  PCI_EXP_LNKCTL2, 4, val);
+		}
+	}
+
+	/* enable ltssm */
+	writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
+			| (1 << APP_LTSSM_ENABLE_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+
+	/* check if the link is up or not */
+	while (!dw_pcie_link_up(pp)) {
+		mdelay(100);
+		count++;
+		if (count == 10) {
+			dev_err(pp->dev, "link Fail\n");
+			return -EINVAL;
+		}
+	}
+	dev_info(pp->dev, "link up\n");
+
+	return 0;
+}
+
+static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
+{
+	struct pcie_port *pp = arg;
+	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+	struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+	unsigned int status;
+
+	status = readl(&app_reg->int_sts);
+
+	if (status & MSI_CTRL_INT) {
+		if (!IS_ENABLED(CONFIG_PCI_MSI))
+			BUG();
+		dw_handle_msi_irq(pp);
+	}
+
+	writel(status, &app_reg->int_clr);
+
+	return IRQ_HANDLED;
+}
+
+static void spear13xx_pcie_enable_interrupts(struct pcie_port *pp)
+{
+	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+	struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+
+	/* Enable MSI interrupt */
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		dw_pcie_msi_init(pp);
+		writel(readl(&app_reg->int_mask) |
+				MSI_CTRL_INT, &app_reg->int_mask);
+	}
+}
+
+static int spear13xx_pcie_link_up(struct pcie_port *pp)
+{
+	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+	struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+
+	if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
+		return 1;
+
+	return 0;
+}
+
+static void spear13xx_pcie_host_init(struct pcie_port *pp)
+{
+	spear13xx_pcie_establish_link(pp);
+	spear13xx_pcie_enable_interrupts(pp);
+}
+
+static struct pcie_host_ops spear13xx_pcie_host_ops = {
+	.link_up = spear13xx_pcie_link_up,
+	.host_init = spear13xx_pcie_host_init,
+};
+
+static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	pp->irq = platform_get_irq(pdev, 0);
+	if (!pp->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -ENODEV;
+	}
+	ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
+			       IRQF_SHARED, "spear1340-pcie", pp);
+	if (ret) {
+		dev_err(dev, "failed to request irq %d\n", pp->irq);
+		return ret;
+	}
+
+	pp->root_bus_nr = -1;
+	pp->ops = &spear13xx_pcie_host_ops;
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init spear13xx_pcie_probe(struct platform_device *pdev)
+{
+	struct spear13xx_pcie *spear13xx_pcie;
+	struct pcie_port *pp;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *dbi_base;
+	int ret;
+
+	spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
+	if (!spear13xx_pcie) {
+		dev_err(dev, "no memory for SPEAr13xx pcie\n");
+		return -ENOMEM;
+	}
+
+	spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
+	if (IS_ERR(spear13xx_pcie->phy)) {
+		ret = PTR_ERR(spear13xx_pcie->phy);
+		if (ret == -EPROBE_DEFER)
+			dev_info(dev, "probe deferred\n");
+		else
+			dev_err(dev, "couldn't get pcie-phy\n");
+		return ret;
+	}
+
+	phy_init(spear13xx_pcie->phy);
+
+	spear13xx_pcie->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(spear13xx_pcie->clk)) {
+		dev_err(dev, "couldn't get clk for pcie\n");
+		return PTR_ERR(spear13xx_pcie->clk);
+	}
+	ret = clk_prepare_enable(spear13xx_pcie->clk);
+	if (ret) {
+		dev_err(dev, "couldn't enable clk for pcie\n");
+		return ret;
+	}
+
+	pp = &spear13xx_pcie->pp;
+
+	pp->dev = dev;
+
+	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
+	if (IS_ERR(pp->dbi_base)) {
+		dev_err(dev, "couldn't remap dbi base %p\n", dbi_base);
+		ret = PTR_ERR(pp->dbi_base);
+		goto fail_clk;
+	}
+	spear13xx_pcie->app_base = pp->dbi_base + 0x2000;
+
+	if (of_property_read_bool(np, "st,pcie-is-gen1"))
+		spear13xx_pcie->is_gen1 = true;
+
+	ret = add_pcie_port(pp, pdev);
+	if (ret < 0)
+		goto fail_clk;
+
+	platform_set_drvdata(pdev, spear13xx_pcie);
+	return 0;
+
+fail_clk:
+	clk_disable_unprepare(spear13xx_pcie->clk);
+
+	return ret;
+}
+
+static const struct of_device_id spear13xx_pcie_of_match[] = {
+	{ .compatible = "st,spear1340-pcie", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, spear13xx_pcie_of_match);
+
+static struct platform_driver spear13xx_pcie_driver __initdata = {
+	.probe		= spear13xx_pcie_probe,
+	.driver = {
+		.name	= "spear-pcie",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(spear13xx_pcie_of_match),
+	},
+};
+
+/* SPEAr13xx PCIe driver does not allow module unload */
+
+static int __init pcie_init(void)
+{
+	return platform_driver_register(&spear13xx_pcie_driver);
+}
+module_init(pcie_init);
+
+MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pci-host-generic.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-host-generic.c
--- linux-libre-3.16-gnu/drivers/pci/host/pci-host-generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-host-generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -385,4 +385,4 @@ module_platform_driver(gen_pci_driver);
 
 MODULE_DESCRIPTION("Generic PCI host driver");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pci-imx6.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-imx6.c
--- linux-libre-3.16-gnu/drivers/pci/host/pci-imx6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-imx6.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,6 +49,9 @@ struct imx6_pcie {
 
 /* PCIe Port Logic registers (memory-mapped) */
 #define PL_OFFSET 0x700
+#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
+#define PCIE_PL_PFLR_LINK_STATE_MASK		(0x3f << 16)
+#define PCIE_PL_PFLR_FORCE_LINK			(1 << 15)
 #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
 #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
 #define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING	(1 << 29)
@@ -214,6 +217,32 @@ static int imx6q_pcie_abort_handler(unsi
 static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
 {
 	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+	u32 val, gpr1, gpr12;
+
+	/*
+	 * If the bootloader already enabled the link we need some special
+	 * handling to get the core back into a state where it is safe to
+	 * touch it for configuration.  As there is no dedicated reset signal
+	 * wired up for MX6QDL, we need to manually force LTSSM into "detect"
+	 * state before completely disabling LTSSM, which is a prerequisite
+	 * for core configuration.
+	 *
+	 * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
+	 * indication that the bootloader activated the link.
+	 */
+	regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
+	regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
+
+	if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
+	    (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
+		val = readl(pp->dbi_base + PCIE_PL_PFLR);
+		val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+		val |= PCIE_PL_PFLR_FORCE_LINK;
+		writel(val, pp->dbi_base + PCIE_PL_PFLR);
+
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+				IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+	}
 
 	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
 			IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
@@ -589,6 +618,14 @@ static int __init imx6_pcie_probe(struct
 	return 0;
 }
 
+static void imx6_pcie_shutdown(struct platform_device *pdev)
+{
+	struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
+
+	/* bring down link, so bootloader gets clean state in case of reboot */
+	imx6_pcie_assert_core_reset(&imx6_pcie->pp);
+}
+
 static const struct of_device_id imx6_pcie_of_match[] = {
 	{ .compatible = "fsl,imx6q-pcie", },
 	{},
@@ -601,6 +638,7 @@ static struct platform_driver imx6_pcie_
 		.owner	= THIS_MODULE,
 		.of_match_table = imx6_pcie_of_match,
 	},
+	.shutdown = imx6_pcie_shutdown,
 };
 
 /* Freescale PCIe driver does not allow module unload */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pci-mvebu.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-mvebu.c
--- linux-libre-3.16-gnu/drivers/pci/host/pci-mvebu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-mvebu.c	2014-09-28 17:29:07.000000000 -0400
@@ -1094,4 +1094,4 @@ module_platform_driver(mvebu_pcie_driver
 
 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
 MODULE_DESCRIPTION("Marvell EBU PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/host/pci-tegra.c linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-tegra.c
--- linux-libre-3.16-gnu/drivers/pci/host/pci-tegra.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/host/pci-tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/interrupt.h>
@@ -41,11 +42,12 @@
 #include <linux/reset.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
-#include <linux/tegra-cpuidle.h>
-#include <linux/tegra-powergate.h>
 #include <linux/vmalloc.h>
 #include <linux/regulator/consumer.h>
 
+#include <soc/tegra/cpuidle.h>
+#include <soc/tegra/pmc.h>
+
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/pci.h>
@@ -233,7 +235,6 @@ struct tegra_pcie_soc_data {
 	bool has_pex_clkreq_en;
 	bool has_pex_bias_ctrl;
 	bool has_intr_prsnt_sense;
-	bool has_avdd_supply;
 	bool has_cml_clk;
 };
 
@@ -272,11 +273,11 @@ struct tegra_pcie {
 	unsigned int num_ports;
 	u32 xbar_config;
 
-	struct regulator *pex_clk_supply;
-	struct regulator *vdd_supply;
-	struct regulator *avdd_supply;
+	struct regulator_bulk_data *supplies;
+	unsigned int num_supplies;
 
 	const struct tegra_pcie_soc_data *soc_data;
+	struct dentry *debugfs;
 };
 
 struct tegra_pcie_port {
@@ -894,7 +895,6 @@ static int tegra_pcie_enable_controller(
 
 static void tegra_pcie_power_off(struct tegra_pcie *pcie)
 {
-	const struct tegra_pcie_soc_data *soc = pcie->soc_data;
 	int err;
 
 	/* TODO: disable and unprepare clocks? */
@@ -905,23 +905,9 @@ static void tegra_pcie_power_off(struct
 
 	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
 
-	if (soc->has_avdd_supply) {
-		err = regulator_disable(pcie->avdd_supply);
-		if (err < 0)
-			dev_warn(pcie->dev,
-				 "failed to disable AVDD regulator: %d\n",
-				 err);
-	}
-
-	err = regulator_disable(pcie->pex_clk_supply);
-	if (err < 0)
-		dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n",
-			 err);
-
-	err = regulator_disable(pcie->vdd_supply);
+	err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
 	if (err < 0)
-		dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n",
-			 err);
+		dev_warn(pcie->dev, "failed to disable regulators: %d\n", err);
 }
 
 static int tegra_pcie_power_on(struct tegra_pcie *pcie)
@@ -936,28 +922,9 @@ static int tegra_pcie_power_on(struct te
 	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
 
 	/* enable regulators */
-	err = regulator_enable(pcie->vdd_supply);
-	if (err < 0) {
-		dev_err(pcie->dev, "failed to enable VDD regulator: %d\n", err);
-		return err;
-	}
-
-	err = regulator_enable(pcie->pex_clk_supply);
-	if (err < 0) {
-		dev_err(pcie->dev, "failed to enable pex-clk regulator: %d\n",
-			err);
-		return err;
-	}
-
-	if (soc->has_avdd_supply) {
-		err = regulator_enable(pcie->avdd_supply);
-		if (err < 0) {
-			dev_err(pcie->dev,
-				"failed to enable AVDD regulator: %d\n",
-				err);
-			return err;
-		}
-	}
+	err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies);
+	if (err < 0)
+		dev_err(pcie->dev, "failed to enable regulators: %d\n", err);
 
 	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
 						pcie->pex_clk,
@@ -1394,14 +1361,157 @@ static int tegra_pcie_get_xbar_config(st
 	return -EINVAL;
 }
 
+/*
+ * Check whether a given set of supplies is available in a device tree node.
+ * This is used to check whether the new or the legacy device tree bindings
+ * should be used.
+ */
+static bool of_regulator_bulk_available(struct device_node *np,
+					struct regulator_bulk_data *supplies,
+					unsigned int num_supplies)
+{
+	char property[32];
+	unsigned int i;
+
+	for (i = 0; i < num_supplies; i++) {
+		snprintf(property, 32, "%s-supply", supplies[i].supply);
+
+		if (of_find_property(np, property, NULL) == NULL)
+			return false;
+	}
+
+	return true;
+}
+
+/*
+ * Old versions of the device tree binding for this device used a set of power
+ * supplies that didn't match the hardware inputs. This happened to work for a
+ * number of cases but is not future proof. However to preserve backwards-
+ * compatibility with old device trees, this function will try to use the old
+ * set of supplies.
+ */
+static int tegra_pcie_get_legacy_regulators(struct tegra_pcie *pcie)
+{
+	struct device_node *np = pcie->dev->of_node;
+
+	if (of_device_is_compatible(np, "nvidia,tegra30-pcie"))
+		pcie->num_supplies = 3;
+	else if (of_device_is_compatible(np, "nvidia,tegra20-pcie"))
+		pcie->num_supplies = 2;
+
+	if (pcie->num_supplies == 0) {
+		dev_err(pcie->dev, "device %s not supported in legacy mode\n",
+			np->full_name);
+		return -ENODEV;
+	}
+
+	pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+				      sizeof(*pcie->supplies),
+				      GFP_KERNEL);
+	if (!pcie->supplies)
+		return -ENOMEM;
+
+	pcie->supplies[0].supply = "pex-clk";
+	pcie->supplies[1].supply = "vdd";
+
+	if (pcie->num_supplies > 2)
+		pcie->supplies[2].supply = "avdd";
+
+	return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
+				       pcie->supplies);
+}
+
+/*
+ * Obtains the list of regulators required for a particular generation of the
+ * IP block.
+ *
+ * This would've been nice to do simply by providing static tables for use
+ * with the regulator_bulk_*() API, but unfortunately Tegra30 is a bit quirky
+ * in that it has two pairs or AVDD_PEX and VDD_PEX supplies (PEXA and PEXB)
+ * and either seems to be optional depending on which ports are being used.
+ */
+static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
+{
+	struct device_node *np = pcie->dev->of_node;
+	unsigned int i = 0;
+
+	if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
+		bool need_pexa = false, need_pexb = false;
+
+		/* VDD_PEXA and AVDD_PEXA supply lanes 0 to 3 */
+		if (lane_mask & 0x0f)
+			need_pexa = true;
+
+		/* VDD_PEXB and AVDD_PEXB supply lanes 4 to 5 */
+		if (lane_mask & 0x30)
+			need_pexb = true;
+
+		pcie->num_supplies = 4 + (need_pexa ? 2 : 0) +
+					 (need_pexb ? 2 : 0);
+
+		pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+					      sizeof(*pcie->supplies),
+					      GFP_KERNEL);
+		if (!pcie->supplies)
+			return -ENOMEM;
+
+		pcie->supplies[i++].supply = "avdd-pex-pll";
+		pcie->supplies[i++].supply = "hvdd-pex";
+		pcie->supplies[i++].supply = "vddio-pex-ctl";
+		pcie->supplies[i++].supply = "avdd-plle";
+
+		if (need_pexa) {
+			pcie->supplies[i++].supply = "avdd-pexa";
+			pcie->supplies[i++].supply = "vdd-pexa";
+		}
+
+		if (need_pexb) {
+			pcie->supplies[i++].supply = "avdd-pexb";
+			pcie->supplies[i++].supply = "vdd-pexb";
+		}
+	} else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) {
+		pcie->num_supplies = 5;
+
+		pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+					      sizeof(*pcie->supplies),
+					      GFP_KERNEL);
+		if (!pcie->supplies)
+			return -ENOMEM;
+
+		pcie->supplies[0].supply = "avdd-pex";
+		pcie->supplies[1].supply = "vdd-pex";
+		pcie->supplies[2].supply = "avdd-pex-pll";
+		pcie->supplies[3].supply = "avdd-plle";
+		pcie->supplies[4].supply = "vddio-pex-clk";
+	}
+
+	if (of_regulator_bulk_available(pcie->dev->of_node, pcie->supplies,
+					pcie->num_supplies))
+		return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
+					       pcie->supplies);
+
+	/*
+	 * If not all regulators are available for this new scheme, assume
+	 * that the device tree complies with an older version of the device
+	 * tree binding.
+	 */
+	dev_info(pcie->dev, "using legacy DT binding for power supplies\n");
+
+	devm_kfree(pcie->dev, pcie->supplies);
+	pcie->num_supplies = 0;
+
+	return tegra_pcie_get_legacy_regulators(pcie);
+}
+
 static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 {
 	const struct tegra_pcie_soc_data *soc = pcie->soc_data;
 	struct device_node *np = pcie->dev->of_node, *port;
 	struct of_pci_range_parser parser;
 	struct of_pci_range range;
+	u32 lanes = 0, mask = 0;
+	unsigned int lane = 0;
 	struct resource res;
-	u32 lanes = 0;
 	int err;
 
 	if (of_pci_range_parser_init(&parser, np)) {
@@ -1409,20 +1519,6 @@ static int tegra_pcie_parse_dt(struct te
 		return -EINVAL;
 	}
 
-	pcie->vdd_supply = devm_regulator_get(pcie->dev, "vdd");
-	if (IS_ERR(pcie->vdd_supply))
-		return PTR_ERR(pcie->vdd_supply);
-
-	pcie->pex_clk_supply = devm_regulator_get(pcie->dev, "pex-clk");
-	if (IS_ERR(pcie->pex_clk_supply))
-		return PTR_ERR(pcie->pex_clk_supply);
-
-	if (soc->has_avdd_supply) {
-		pcie->avdd_supply = devm_regulator_get(pcie->dev, "avdd");
-		if (IS_ERR(pcie->avdd_supply))
-			return PTR_ERR(pcie->avdd_supply);
-	}
-
 	for_each_of_pci_range(&parser, &range) {
 		of_pci_range_to_resource(&range, np, &res);
 
@@ -1490,8 +1586,13 @@ static int tegra_pcie_parse_dt(struct te
 
 		lanes |= value << (index << 3);
 
-		if (!of_device_is_available(port))
+		if (!of_device_is_available(port)) {
+			lane += value;
 			continue;
+		}
+
+		mask |= ((1 << value) - 1) << lane;
+		lane += value;
 
 		rp = devm_kzalloc(pcie->dev, sizeof(*rp), GFP_KERNEL);
 		if (!rp)
@@ -1522,6 +1623,10 @@ static int tegra_pcie_parse_dt(struct te
 		return err;
 	}
 
+	err = tegra_pcie_get_regulators(pcie, mask);
+	if (err < 0)
+		return err;
+
 	return 0;
 }
 
@@ -1615,7 +1720,6 @@ static const struct tegra_pcie_soc_data
 	.has_pex_clkreq_en = false,
 	.has_pex_bias_ctrl = false,
 	.has_intr_prsnt_sense = false,
-	.has_avdd_supply = false,
 	.has_cml_clk = false,
 };
 
@@ -1627,7 +1731,6 @@ static const struct tegra_pcie_soc_data
 	.has_pex_clkreq_en = true,
 	.has_pex_bias_ctrl = true,
 	.has_intr_prsnt_sense = true,
-	.has_avdd_supply = true,
 	.has_cml_clk = true,
 };
 
@@ -1638,6 +1741,115 @@ static const struct of_device_id tegra_p
 };
 MODULE_DEVICE_TABLE(of, tegra_pcie_of_match);
 
+static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct tegra_pcie *pcie = s->private;
+
+	if (list_empty(&pcie->ports))
+		return NULL;
+
+	seq_printf(s, "Index  Status\n");
+
+	return seq_list_start(&pcie->ports, *pos);
+}
+
+static void *tegra_pcie_ports_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct tegra_pcie *pcie = s->private;
+
+	return seq_list_next(v, &pcie->ports, pos);
+}
+
+static void tegra_pcie_ports_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static int tegra_pcie_ports_seq_show(struct seq_file *s, void *v)
+{
+	bool up = false, active = false;
+	struct tegra_pcie_port *port;
+	unsigned int value;
+
+	port = list_entry(v, struct tegra_pcie_port, list);
+
+	value = readl(port->base + RP_VEND_XP);
+
+	if (value & RP_VEND_XP_DL_UP)
+		up = true;
+
+	value = readl(port->base + RP_LINK_CONTROL_STATUS);
+
+	if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE)
+		active = true;
+
+	seq_printf(s, "%2u     ", port->index);
+
+	if (up)
+		seq_printf(s, "up");
+
+	if (active) {
+		if (up)
+			seq_printf(s, ", ");
+
+		seq_printf(s, "active");
+	}
+
+	seq_printf(s, "\n");
+	return 0;
+}
+
+static const struct seq_operations tegra_pcie_ports_seq_ops = {
+	.start = tegra_pcie_ports_seq_start,
+	.next = tegra_pcie_ports_seq_next,
+	.stop = tegra_pcie_ports_seq_stop,
+	.show = tegra_pcie_ports_seq_show,
+};
+
+static int tegra_pcie_ports_open(struct inode *inode, struct file *file)
+{
+	struct tegra_pcie *pcie = inode->i_private;
+	struct seq_file *s;
+	int err;
+
+	err = seq_open(file, &tegra_pcie_ports_seq_ops);
+	if (err)
+		return err;
+
+	s = file->private_data;
+	s->private = pcie;
+
+	return 0;
+}
+
+static const struct file_operations tegra_pcie_ports_ops = {
+	.owner = THIS_MODULE,
+	.open = tegra_pcie_ports_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int tegra_pcie_debugfs_init(struct tegra_pcie *pcie)
+{
+	struct dentry *file;
+
+	pcie->debugfs = debugfs_create_dir("pcie", NULL);
+	if (!pcie->debugfs)
+		return -ENOMEM;
+
+	file = debugfs_create_file("ports", S_IFREG | S_IRUGO, pcie->debugfs,
+				   pcie, &tegra_pcie_ports_ops);
+	if (!file)
+		goto remove;
+
+	return 0;
+
+remove:
+	debugfs_remove_recursive(pcie->debugfs);
+	pcie->debugfs = NULL;
+	return -ENOMEM;
+}
+
 static int tegra_pcie_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
@@ -1692,6 +1904,13 @@ static int tegra_pcie_probe(struct platf
 		goto disable_msi;
 	}
 
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_pcie_debugfs_init(pcie);
+		if (err < 0)
+			dev_err(&pdev->dev, "failed to setup debugfs: %d\n",
+				err);
+	}
+
 	platform_set_drvdata(pdev, pcie);
 	return 0;
 
@@ -1716,4 +1935,4 @@ module_platform_driver(tegra_pcie_driver
 
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/acpiphp_glue.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/acpiphp_glue.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/acpiphp_glue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/acpiphp_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,8 +80,9 @@ static struct acpiphp_context *acpiphp_i
 		return NULL;
 
 	context->refcount = 1;
-	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL,
-			    acpiphp_post_dock_fixup);
+	context->hp.notify = acpiphp_hotplug_notify;
+	context->hp.fixup = acpiphp_post_dock_fixup;
+	acpi_set_hp_context(adev, &context->hp);
 	return context;
 }
 
@@ -369,20 +370,6 @@ static acpi_status acpiphp_add_context(a
 	return AE_OK;
 }
 
-static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev)
-{
-	struct acpiphp_bridge *bridge = NULL;
-
-	acpi_lock_hp_context();
-	if (adev->hp) {
-		bridge = to_acpiphp_root_context(adev->hp)->root_bridge;
-		if (bridge)
-			get_bridge(bridge);
-	}
-	acpi_unlock_hp_context();
-	return bridge;
-}
-
 static void cleanup_bridge(struct acpiphp_bridge *bridge)
 {
 	struct acpiphp_slot *slot;
@@ -573,19 +560,15 @@ static void disable_slot(struct acpiphp_
 	slot->flags &= (~SLOT_ENABLED);
 }
 
-static bool acpiphp_no_hotplug(struct acpi_device *adev)
-{
-	return adev && adev->flags.no_hotplug;
-}
-
 static bool slot_no_hotplug(struct acpiphp_slot *slot)
 {
-	struct acpiphp_func *func;
+	struct pci_bus *bus = slot->bus;
+	struct pci_dev *dev;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		if (acpiphp_no_hotplug(func_to_acpi_device(func)))
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		if (PCI_SLOT(dev->devfn) == slot->device && dev->ignore_hotplug)
 			return true;
-
+	}
 	return false;
 }
 
@@ -658,7 +641,7 @@ static void trim_stale_devices(struct pc
 
 		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
 		alive = (ACPI_SUCCESS(status) && device_status_valid(sta))
-			|| acpiphp_no_hotplug(adev);
+			|| dev->ignore_hotplug;
 	}
 	if (!alive)
 		alive = pci_device_is_present(dev);
@@ -753,9 +736,15 @@ static void acpiphp_sanitize_bus(struct
 
 void acpiphp_check_host_bridge(struct acpi_device *adev)
 {
-	struct acpiphp_bridge *bridge;
+	struct acpiphp_bridge *bridge = NULL;
 
-	bridge = acpiphp_dev_to_bridge(adev);
+	acpi_lock_hp_context();
+	if (adev->hp) {
+		bridge = to_acpiphp_root_context(adev->hp)->root_bridge;
+		if (bridge)
+			get_bridge(bridge);
+	}
+	acpi_unlock_hp_context();
 	if (bridge) {
 		pci_lock_rescan_remove();
 
@@ -884,7 +873,7 @@ void acpiphp_enumerate_slots(struct pci_
 			goto err;
 
 		root_context->root_bridge = bridge;
-		acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL);
+		acpi_set_hp_context(adev, &root_context->hp);
 	} else {
 		struct acpiphp_context *context;
 
@@ -927,7 +916,7 @@ void acpiphp_enumerate_slots(struct pci_
 	kfree(bridge);
 }
 
-void acpiphp_drop_bridge(struct acpiphp_bridge *bridge)
+static void acpiphp_drop_bridge(struct acpiphp_bridge *bridge)
 {
 	if (pci_is_root_bus(bridge->pci_bus)) {
 		struct acpiphp_root_context *root_context;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/cpqphp_sysfs.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/cpqphp_sysfs.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/cpqphp_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/cpqphp_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,8 +216,7 @@ void cpqhp_create_debugfs_files(struct c
 
 void cpqhp_remove_debugfs_files(struct controller *ctrl)
 {
-	if (ctrl->dentry)
-		debugfs_remove(ctrl->dentry);
+	debugfs_remove(ctrl->dentry);
 	ctrl->dentry = NULL;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp_core.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp_core.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -255,6 +255,13 @@ static int pciehp_probe(struct pcie_devi
 	else if (pciehp_acpi_slot_detection_check(dev->port))
 		goto err_out_none;
 
+	if (!dev->port->subordinate) {
+		/* Can happen if we run out of bus numbers during probe */
+		dev_err(&dev->device,
+			"Hotplug bridge without secondary bus, ignoring\n");
+		goto err_out_none;
+	}
+
 	ctrl = pcie_init(dev);
 	if (!ctrl) {
 		dev_err(&dev->device, "Controller initialization failed\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp.h linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp.h
--- linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp.h	2014-09-28 17:29:07.000000000 -0400
@@ -92,9 +92,10 @@ struct controller {
 	struct slot *slot;
 	wait_queue_head_t queue;	/* sleep & wake process */
 	u32 slot_cap;
+	u32 slot_ctrl;
 	struct timer_list poll_timer;
+	unsigned long cmd_started;	/* jiffies */
 	unsigned int cmd_busy:1;
-	unsigned int no_cmd_complete:1;
 	unsigned int link_active_reporting:1;
 	unsigned int notification_enabled:1;
 	unsigned int power_fault_detected;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp_hpc.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp_hpc.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/pciehp_hpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pciehp_hpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -104,11 +104,10 @@ static inline void pciehp_free_irq(struc
 		free_irq(ctrl->pcie->irq, ctrl);
 }
 
-static int pcie_poll_cmd(struct controller *ctrl)
+static int pcie_poll_cmd(struct controller *ctrl, int timeout)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
 	u16 slot_status;
-	int timeout = 1000;
 
 	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
 	if (slot_status & PCI_EXP_SLTSTA_CC) {
@@ -129,18 +128,52 @@ static int pcie_poll_cmd(struct controll
 	return 0;	/* timeout */
 }
 
-static void pcie_wait_cmd(struct controller *ctrl, int poll)
+static void pcie_wait_cmd(struct controller *ctrl)
 {
 	unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
-	unsigned long timeout = msecs_to_jiffies(msecs);
+	unsigned long duration = msecs_to_jiffies(msecs);
+	unsigned long cmd_timeout = ctrl->cmd_started + duration;
+	unsigned long now, timeout;
 	int rc;
 
-	if (poll)
-		rc = pcie_poll_cmd(ctrl);
+	/*
+	 * If the controller does not generate notifications for command
+	 * completions, we never need to wait between writes.
+	 */
+	if (NO_CMD_CMPL(ctrl))
+		return;
+
+	if (!ctrl->cmd_busy)
+		return;
+
+	/*
+	 * Even if the command has already timed out, we want to call
+	 * pcie_poll_cmd() so it can clear PCI_EXP_SLTSTA_CC.
+	 */
+	now = jiffies;
+	if (time_before_eq(cmd_timeout, now))
+		timeout = 1;
 	else
+		timeout = cmd_timeout - now;
+
+	if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE &&
+	    ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE)
 		rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
+	else
+		rc = pcie_poll_cmd(ctrl, jiffies_to_msecs(timeout));
+
+	/*
+	 * Controllers with errata like Intel CF118 don't generate
+	 * completion notifications unless the power/indicator/interlock
+	 * control bits are changed.  On such controllers, we'll emit this
+	 * timeout message when we wait for completion of commands that
+	 * don't change those bits, e.g., commands that merely enable
+	 * interrupts.
+	 */
 	if (!rc)
-		ctrl_dbg(ctrl, "Command not completed in 1000 msec\n");
+		ctrl_info(ctrl, "Timeout on hotplug command %#010x (issued %u msec ago)\n",
+			  ctrl->slot_ctrl,
+			  jiffies_to_msecs(now - ctrl->cmd_started));
 }
 
 /**
@@ -152,34 +185,12 @@ static void pcie_wait_cmd(struct control
 static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
-	u16 slot_status;
 	u16 slot_ctrl;
 
 	mutex_lock(&ctrl->ctrl_lock);
 
-	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
-	if (slot_status & PCI_EXP_SLTSTA_CC) {
-		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
-					   PCI_EXP_SLTSTA_CC);
-		if (!ctrl->no_cmd_complete) {
-			/*
-			 * After 1 sec and CMD_COMPLETED still not set, just
-			 * proceed forward to issue the next command according
-			 * to spec. Just print out the error message.
-			 */
-			ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n");
-		} else if (!NO_CMD_CMPL(ctrl)) {
-			/*
-			 * This controller seems to notify of command completed
-			 * event even though it supports none of power
-			 * controller, attention led, power led and EMI.
-			 */
-			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to wait for command completed event\n");
-			ctrl->no_cmd_complete = 0;
-		} else {
-			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe the controller is broken\n");
-		}
-	}
+	/* Wait for any previous command that might still be in progress */
+	pcie_wait_cmd(ctrl);
 
 	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
 	slot_ctrl &= ~mask;
@@ -187,22 +198,9 @@ static void pcie_write_cmd(struct contro
 	ctrl->cmd_busy = 1;
 	smp_mb();
 	pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
+	ctrl->cmd_started = jiffies;
+	ctrl->slot_ctrl = slot_ctrl;
 
-	/*
-	 * Wait for command completion.
-	 */
-	if (!ctrl->no_cmd_complete) {
-		int poll = 0;
-		/*
-		 * if hotplug interrupt is not enabled or command
-		 * completed interrupt is not enabled, we need to poll
-		 * command completed event.
-		 */
-		if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) ||
-		    !(slot_ctrl & PCI_EXP_SLTCTL_CCIE))
-			poll = 1;
-		pcie_wait_cmd(ctrl, poll);
-	}
 	mutex_unlock(&ctrl->ctrl_lock);
 }
 
@@ -508,6 +506,8 @@ static irqreturn_t pcie_isr(int irq, voi
 {
 	struct controller *ctrl = (struct controller *)dev_id;
 	struct pci_dev *pdev = ctrl_dev(ctrl);
+	struct pci_bus *subordinate = pdev->subordinate;
+	struct pci_dev *dev;
 	struct slot *slot = ctrl->slot;
 	u16 detected, intr_loc;
 
@@ -541,6 +541,16 @@ static irqreturn_t pcie_isr(int irq, voi
 		wake_up(&ctrl->queue);
 	}
 
+	if (subordinate) {
+		list_for_each_entry(dev, &subordinate->devices, bus_list) {
+			if (dev->ignore_hotplug) {
+				ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n",
+					 intr_loc, pci_name(dev));
+				return IRQ_HANDLED;
+			}
+		}
+	}
+
 	if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
 		return IRQ_HANDLED;
 
@@ -773,15 +783,6 @@ struct controller *pcie_init(struct pcie
 	mutex_init(&ctrl->ctrl_lock);
 	init_waitqueue_head(&ctrl->queue);
 	dbg_ctrl(ctrl);
-	/*
-	 * Controller doesn't notify of command completion if the "No
-	 * Command Completed Support" bit is set in Slot Capability
-	 * register or the controller supports none of power
-	 * controller, attention led, power led and EMI.
-	 */
-	if (NO_CMD_CMPL(ctrl) ||
-	    !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
-		ctrl->no_cmd_complete = 1;
 
 	/* Check if Data Link Layer Link Active Reporting is implemented */
 	pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
@@ -794,7 +795,7 @@ struct controller *pcie_init(struct pcie
 	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
 		PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
 		PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
-		PCI_EXP_SLTSTA_CC);
+		PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
 
 	/* Disable software notification */
 	pcie_disable_notification(ctrl);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/pcihp_slot.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pcihp_slot.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/pcihp_slot.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/pcihp_slot.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,6 @@ static void program_hpp_type0(struct pci
 		 */
 		if (pci_is_pcie(dev))
 			return;
-		dev_info(&dev->dev, "using default PCI settings\n");
 		hpp = &pci_default_type0;
 	}
 
@@ -153,7 +152,6 @@ void pci_configure_slot(struct pci_dev *
 {
 	struct pci_dev *cdev;
 	struct hotplug_params hpp;
-	int ret;
 
 	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
 			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
@@ -163,9 +161,7 @@ void pci_configure_slot(struct pci_dev *
 	pcie_bus_configure_settings(dev->bus);
 
 	memset(&hpp, 0, sizeof(hpp));
-	ret = pci_get_hp_params(dev, &hpp);
-	if (ret)
-		dev_warn(&dev->dev, "no hotplug settings from platform\n");
+	pci_get_hp_params(dev, &hpp);
 
 	program_hpp_type2(dev, hpp.t2);
 	program_hpp_type1(dev, hpp.t1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/rpaphp_core.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/rpaphp_core.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/rpaphp_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/rpaphp_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -375,11 +375,11 @@ static void __exit cleanup_slots(void)
 
 static int __init rpaphp_init(void)
 {
-	struct device_node *dn = NULL;
+	struct device_node *dn;
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
-	while ((dn = of_find_node_by_name(dn, "pci")))
+	for_each_node_by_name(dn, "pci")
 		rpaphp_add_slot(dn);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/hotplug/s390_pci_hpc.c linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/s390_pci_hpc.c
--- linux-libre-3.16-gnu/drivers/pci/hotplug/s390_pci_hpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/hotplug/s390_pci_hpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,8 +7,8 @@
  *   Jan Glauber <jang@linux.vnet.ibm.com>
  */
 
-#define COMPONENT "zPCI hpc"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/ioapic.c linux-libre-3.17-rc7-gnu/drivers/pci/ioapic.c
--- linux-libre-3.16-gnu/drivers/pci/ioapic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/ioapic.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,7 +98,7 @@ static void ioapic_remove(struct pci_dev
 }
 
 
-static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
+static const struct pci_device_id ioapic_devices[] = {
 	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
 	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/msi.c linux-libre-3.17-rc7-gnu/drivers/pci/msi.c
--- linux-libre-3.16-gnu/drivers/pci/msi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/msi.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,15 +149,14 @@ static void msi_set_enable(struct pci_de
 	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
 }
 
-static void msix_set_enable(struct pci_dev *dev, int enable)
+static void msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
 {
-	u16 control;
+	u16 ctrl;
 
-	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
-	control &= ~PCI_MSIX_FLAGS_ENABLE;
-	if (enable)
-		control |= PCI_MSIX_FLAGS_ENABLE;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
+	ctrl &= ~clear;
+	ctrl |= set;
+	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl);
 }
 
 static inline __attribute_const__ u32 msi_mask(unsigned x)
@@ -168,16 +167,6 @@ static inline __attribute_const__ u32 ms
 	return (1 << (1 << x)) - 1;
 }
 
-static inline __attribute_const__ u32 msi_capable_mask(u16 control)
-{
-	return msi_mask((control >> 1) & 7);
-}
-
-static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
-{
-	return msi_mask((control >> 4) & 7);
-}
-
 /*
  * PCI 2.3 does not specify mask bits for each MSI interrupt.  Attempting to
  * mask all MSI interrupts by clearing the MSI enable bit does not work
@@ -246,7 +235,7 @@ static void msi_set_mask_bit(struct irq_
 		msix_mask_irq(desc, flag);
 		readl(desc->mask_base);		/* Flush write to device */
 	} else {
-		unsigned offset = data->irq - desc->dev->irq;
+		unsigned offset = data->irq - desc->irq;
 		msi_mask_irq(desc, 1 << offset, flag << offset);
 	}
 }
@@ -460,7 +449,8 @@ static void __pci_restore_msi_state(stru
 	arch_restore_msi_irqs(dev);
 
 	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
-	msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
+	msi_mask_irq(entry, msi_mask(entry->msi_attrib.multi_cap),
+		     entry->masked);
 	control &= ~PCI_MSI_FLAGS_QSIZE;
 	control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE;
 	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
@@ -469,26 +459,22 @@ static void __pci_restore_msi_state(stru
 static void __pci_restore_msix_state(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
-	u16 control;
 
 	if (!dev->msix_enabled)
 		return;
 	BUG_ON(list_empty(&dev->msi_list));
-	entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
-	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
 
 	/* route the table */
 	pci_intx_for_msi(dev, 0);
-	control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	msix_clear_and_set_ctrl(dev, 0,
+				PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
 
 	arch_restore_msi_irqs(dev);
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		msix_mask_irq(entry, entry->masked);
 	}
 
-	control &= ~PCI_MSIX_FLAGS_MASKALL;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 }
 
 void pci_restore_msi_state(struct pci_dev *dev)
@@ -501,7 +487,6 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state)
 static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
 	struct msi_desc *entry;
 	unsigned long irq;
 	int retval;
@@ -510,12 +495,11 @@ static ssize_t msi_mode_show(struct devi
 	if (retval)
 		return retval;
 
-	list_for_each_entry(entry, &pdev->msi_list, list) {
-		if (entry->irq == irq) {
-			return sprintf(buf, "%s\n",
-				       entry->msi_attrib.is_msix ? "msix" : "msi");
-		}
-	}
+	entry = irq_get_msi_desc(irq);
+	if (entry)
+		return sprintf(buf, "%s\n",
+				entry->msi_attrib.is_msix ? "msix" : "msi");
+
 	return -ENODEV;
 }
 
@@ -594,6 +578,38 @@ error_attrs:
 	return ret;
 }
 
+static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
+{
+	u16 control;
+	struct msi_desc *entry;
+
+	/* MSI Entry Initialization */
+	entry = alloc_msi_entry(dev);
+	if (!entry)
+		return NULL;
+
+	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
+
+	entry->msi_attrib.is_msix	= 0;
+	entry->msi_attrib.is_64		= !!(control & PCI_MSI_FLAGS_64BIT);
+	entry->msi_attrib.entry_nr	= 0;
+	entry->msi_attrib.maskbit	= !!(control & PCI_MSI_FLAGS_MASKBIT);
+	entry->msi_attrib.default_irq	= dev->irq;	/* Save IOAPIC IRQ */
+	entry->msi_attrib.pos		= dev->msi_cap;
+	entry->msi_attrib.multi_cap	= (control & PCI_MSI_FLAGS_QMASK) >> 1;
+
+	if (control & PCI_MSI_FLAGS_64BIT)
+		entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
+	else
+		entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
+
+	/* Save the initial mask status */
+	if (entry->msi_attrib.maskbit)
+		pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
+
+	return entry;
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -609,32 +625,16 @@ static int msi_capability_init(struct pc
 {
 	struct msi_desc *entry;
 	int ret;
-	u16 control;
 	unsigned mask;
 
 	msi_set_enable(dev, 0);	/* Disable MSI during set up */
 
-	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
-	/* MSI Entry Initialization */
-	entry = alloc_msi_entry(dev);
+	entry = msi_setup_entry(dev);
 	if (!entry)
 		return -ENOMEM;
 
-	entry->msi_attrib.is_msix	= 0;
-	entry->msi_attrib.is_64		= !!(control & PCI_MSI_FLAGS_64BIT);
-	entry->msi_attrib.entry_nr	= 0;
-	entry->msi_attrib.maskbit	= !!(control & PCI_MSI_FLAGS_MASKBIT);
-	entry->msi_attrib.default_irq	= dev->irq;	/* Save IOAPIC IRQ */
-	entry->msi_attrib.pos		= dev->msi_cap;
-
-	if (control & PCI_MSI_FLAGS_64BIT)
-		entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
-	else
-		entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
 	/* All MSIs are unmasked by default, Mask them all */
-	if (entry->msi_attrib.maskbit)
-		pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
-	mask = msi_capable_mask(control);
+	mask = msi_mask(entry->msi_attrib.multi_cap);
 	msi_mask_irq(entry, mask, mask);
 
 	list_add_tail(&entry->list, &dev->msi_list);
@@ -743,12 +743,10 @@ static int msix_capability_init(struct p
 	u16 control;
 	void __iomem *base;
 
-	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
-
 	/* Ensure MSI-X is disabled while it is set up */
-	control &= ~PCI_MSIX_FLAGS_ENABLE;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
 
+	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
 	/* Request & Map MSI-X table region */
 	base = msix_map_region(dev, msix_table_size(control));
 	if (!base)
@@ -767,8 +765,8 @@ static int msix_capability_init(struct p
 	 * MSI-X registers.  We need to mask all the vectors to prevent
 	 * interrupts coming in before they're fully set up.
 	 */
-	control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	msix_clear_and_set_ctrl(dev, 0,
+				PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
 
 	msix_program_entries(dev, entries);
 
@@ -780,8 +778,7 @@ static int msix_capability_init(struct p
 	pci_intx_for_msi(dev, 0);
 	dev->msix_enabled = 1;
 
-	control &= ~PCI_MSIX_FLAGS_MASKALL;
-	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+	msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 
 	return 0;
 
@@ -882,7 +879,6 @@ void pci_msi_shutdown(struct pci_dev *de
 {
 	struct msi_desc *desc;
 	u32 mask;
-	u16 ctrl;
 
 	if (!pci_msi_enable || !dev || !dev->msi_enabled)
 		return;
@@ -895,8 +891,7 @@ void pci_msi_shutdown(struct pci_dev *de
 	dev->msi_enabled = 0;
 
 	/* Return the device with MSI unmasked as initial states */
-	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);
-	mask = msi_capable_mask(ctrl);
+	mask = msi_mask(desc->msi_attrib.multi_cap);
 	/* Keep cached state to be restored */
 	arch_msi_mask_irq(desc, mask, ~mask);
 
@@ -1001,7 +996,7 @@ void pci_msix_shutdown(struct pci_dev *d
 		arch_msix_mask_irq(entry, 1);
 	}
 
-	msix_set_enable(dev, 0);
+	msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
 	pci_intx_for_msi(dev, 1);
 	dev->msix_enabled = 0;
 }
@@ -1016,24 +1011,6 @@ void pci_disable_msix(struct pci_dev *de
 }
 EXPORT_SYMBOL(pci_disable_msix);
 
-/**
- * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
- * @dev: pointer to the pci_dev data structure of MSI(X) device function
- *
- * Being called during hotplug remove, from which the device function
- * is hot-removed. All previous assigned MSI/MSI-X irqs, if
- * allocated for this device function, are reclaimed to unused state,
- * which may be used later on.
- **/
-void msi_remove_pci_irq_vectors(struct pci_dev *dev)
-{
-	if (!pci_msi_enable || !dev)
-		return;
-
-	if (dev->msi_enabled || dev->msix_enabled)
-		free_msi_irqs(dev);
-}
-
 void pci_no_msi(void)
 {
 	pci_msi_enable = 0;
@@ -1065,7 +1042,7 @@ void pci_msi_init_pci_dev(struct pci_dev
 
 	dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
 	if (dev->msix_cap)
-		msix_set_enable(dev, 0);
+		msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pci-acpi.c linux-libre-3.17-rc7-gnu/drivers/pci/pci-acpi.c
--- linux-libre-3.16-gnu/drivers/pci/pci-acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pci-acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,31 +18,31 @@
 #include "pci.h"
 
 /**
- * pci_acpi_wake_bus - Wake-up notification handler for root buses.
- * @handle: ACPI handle of a device the notification is for.
- * @event: Type of the signaled event.
- * @context: PCI root bus to wake up devices on.
+ * pci_acpi_wake_bus - Root bus wakeup notification fork function.
+ * @work: Work item to handle.
  */
-static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context)
+static void pci_acpi_wake_bus(struct work_struct *work)
 {
-	struct pci_bus *pci_bus = context;
+	struct acpi_device *adev;
+	struct acpi_pci_root *root;
 
-	if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus)
-		pci_pme_wakeup_bus(pci_bus);
+	adev = container_of(work, struct acpi_device, wakeup.context.work);
+	root = acpi_driver_data(adev);
+	pci_pme_wakeup_bus(root->bus);
 }
 
 /**
- * pci_acpi_wake_dev - Wake-up notification handler for PCI devices.
+ * pci_acpi_wake_dev - PCI device wakeup notification work function.
  * @handle: ACPI handle of a device the notification is for.
- * @event: Type of the signaled event.
- * @context: PCI device object to wake up.
+ * @work: Work item to handle.
  */
-static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
+static void pci_acpi_wake_dev(struct work_struct *work)
 {
-	struct pci_dev *pci_dev = context;
+	struct acpi_device_wakeup_context *context;
+	struct pci_dev *pci_dev;
 
-	if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
-		return;
+	context = container_of(work, struct acpi_device_wakeup_context, work);
+	pci_dev = to_pci_dev(context->dev);
 
 	if (pci_dev->pme_poll)
 		pci_dev->pme_poll = false;
@@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handl
 }
 
 /**
- * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
- * @dev: ACPI device to add the notifier for.
- * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
- */
-acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
-					 struct pci_bus *pci_bus)
-{
-	return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
-}
-
-/**
- * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier.
- * @dev: ACPI device to remove the notifier from.
+ * pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus.
+ * @dev: PCI root bridge ACPI device.
  */
-acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
+acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev)
 {
-	return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
+	return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus);
 }
 
 /**
@@ -92,16 +81,7 @@ acpi_status pci_acpi_remove_bus_pm_notif
 acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
 				     struct pci_dev *pci_dev)
 {
-	return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
-}
-
-/**
- * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier.
- * @dev: ACPI device to remove the notifier from.
- */
-acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
-{
-	return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
+	return acpi_add_pm_notifier(dev, &pci_dev->dev, pci_acpi_wake_dev);
 }
 
 phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -170,14 +150,13 @@ static pci_power_t acpi_pci_choose_state
 
 static bool acpi_pci_power_manageable(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
-
-	return handle ? acpi_bus_power_manageable(handle) : false;
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
+	return adev ? acpi_device_power_manageable(adev) : false;
 }
 
 static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
 	static const u8 state_conv[] = {
 		[PCI_D0] = ACPI_STATE_D0,
 		[PCI_D1] = ACPI_STATE_D1,
@@ -188,7 +167,7 @@ static int acpi_pci_set_power_state(stru
 	int error = -EINVAL;
 
 	/* If the ACPI device has _EJ0, ignore the device */
-	if (!handle || acpi_has_method(handle, "_EJ0"))
+	if (!adev || acpi_has_method(adev->handle, "_EJ0"))
 		return -ENODEV;
 
 	switch (state) {
@@ -202,7 +181,7 @@ static int acpi_pci_set_power_state(stru
 	case PCI_D1:
 	case PCI_D2:
 	case PCI_D3hot:
-		error = acpi_bus_set_power(handle, state_conv[state]);
+		error = acpi_device_set_power(adev, state_conv[state]);
 	}
 
 	if (!error)
@@ -214,9 +193,8 @@ static int acpi_pci_set_power_state(stru
 
 static bool acpi_pci_can_wakeup(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
-
-	return handle ? acpi_bus_can_wakeup(handle) : false;
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
+	return adev ? acpi_device_can_wakeup(adev) : false;
 }
 
 static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pci.c linux-libre-3.17-rc7-gnu/drivers/pci/pci.c
--- linux-libre-3.16-gnu/drivers/pci/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -839,12 +839,6 @@ int pci_set_power_state(struct pci_dev *
 
 	if (!__pci_complete_power_transition(dev, state))
 		error = 0;
-	/*
-	 * When aspm_policy is "powersave" this call ensures
-	 * that ASPM is configured.
-	 */
-	if (!error && dev->bus->self)
-		pcie_aspm_powersave_config_link(dev->bus->self);
 
 	return error;
 }
@@ -1195,12 +1189,18 @@ int __weak pcibios_enable_device(struct
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
 	int err;
+	struct pci_dev *bridge;
 	u16 cmd;
 	u8 pin;
 
 	err = pci_set_power_state(dev, PCI_D0);
 	if (err < 0 && err != -EIO)
 		return err;
+
+	bridge = pci_upstream_bridge(dev);
+	if (bridge)
+		pcie_aspm_powersave_config_link(bridge);
+
 	err = pcibios_enable_device(dev, bars);
 	if (err < 0)
 		return err;
@@ -3198,7 +3198,7 @@ static int pci_pm_reset(struct pci_dev *
 	return 0;
 }
 
-void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
+void pci_reset_secondary_bus(struct pci_dev *dev)
 {
 	u16 ctrl;
 
@@ -3224,6 +3224,11 @@ void __weak pcibios_reset_secondary_bus(
 	ssleep(1);
 }
 
+void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
+{
+	pci_reset_secondary_bus(dev);
+}
+
 /**
  * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
  * @dev: Bridge device
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pci-driver.c linux-libre-3.17-rc7-gnu/drivers/pci/pci-driver.c
--- linux-libre-3.16-gnu/drivers/pci/pci-driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pci-driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -582,7 +582,7 @@ static int pci_legacy_suspend_late(struc
 			WARN_ONCE(pci_dev->current_state != prev,
 				"PCI PM: Device state not saved by %pF\n",
 				drv->suspend_late);
-			return 0;
+			goto Fixup;
 		}
 	}
 
@@ -591,6 +591,9 @@ static int pci_legacy_suspend_late(struc
 
 	pci_pm_set_unknown_state(pci_dev);
 
+Fixup:
+	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
 	return 0;
 }
 
@@ -734,7 +737,7 @@ static int pci_pm_suspend_noirq(struct d
 
 	if (!pm) {
 		pci_save_state(pci_dev);
-		return 0;
+		goto Fixup;
 	}
 
 	if (pm->suspend_noirq) {
@@ -751,7 +754,7 @@ static int pci_pm_suspend_noirq(struct d
 			WARN_ONCE(pci_dev->current_state != prev,
 				"PCI PM: State of device not saved by %pF\n",
 				pm->suspend_noirq);
-			return 0;
+			goto Fixup;
 		}
 	}
 
@@ -775,6 +778,9 @@ static int pci_pm_suspend_noirq(struct d
 	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
 		pci_write_config_word(pci_dev, PCI_COMMAND, 0);
 
+Fixup:
+	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
 	return 0;
 }
 
@@ -999,8 +1005,10 @@ static int pci_pm_poweroff_noirq(struct
 	if (pci_has_legacy_pm_support(to_pci_dev(dev)))
 		return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
 
-	if (!drv || !drv->pm)
+	if (!drv || !drv->pm) {
+		pci_fixup_device(pci_fixup_suspend_late, pci_dev);
 		return 0;
+	}
 
 	if (drv->pm->poweroff_noirq) {
 		int error;
@@ -1021,6 +1029,8 @@ static int pci_pm_poweroff_noirq(struct
 	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
 		pci_write_config_word(pci_dev, PCI_COMMAND, 0);
 
+	pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
 	if (pcibios_pm_ops.poweroff_noirq)
 		return pcibios_pm_ops.poweroff_noirq(dev);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c linux-libre-3.17-rc7-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c
--- linux-libre-3.16-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,7 @@
 #include <linux/cper.h>
 
 #include "aerdrv.h"
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/ras.h>
+#include <ras/ras_event.h>
 
 #define AER_AGENT_RECEIVER		0
 #define AER_AGENT_REQUESTER		1
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pcie/aer/Kconfig linux-libre-3.17-rc7-gnu/drivers/pci/pcie/aer/Kconfig
--- linux-libre-3.16-gnu/drivers/pci/pcie/aer/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pcie/aer/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -5,6 +5,7 @@
 config PCIEAER
 	boolean "Root Port Advanced Error Reporting support"
 	depends on PCIEPORTBUS
+	select RAS
 	default y
 	help
 	  This enables PCI Express Root Port Advanced Error Reporting
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pcie/portdrv_pci.c linux-libre-3.17-rc7-gnu/drivers/pci/pcie/portdrv_pci.c
--- linux-libre-3.16-gnu/drivers/pci/pcie/portdrv_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pcie/portdrv_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci
 	     (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
 		return -ENODEV;
 
-	if (!dev->irq && dev->pin) {
-		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n",
-			 dev->vendor, dev->device);
-	}
 	status = pcie_port_device_register(dev);
 	if (status)
 		return status;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/pci-label.c linux-libre-3.17-rc7-gnu/drivers/pci/pci-label.c
--- linux-libre-3.16-gnu/drivers/pci/pci-label.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/pci-label.c	2014-09-28 17:29:07.000000000 -0400
@@ -161,8 +161,8 @@ enum acpi_attr_enum {
 static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
 {
 	int len;
-	len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer,
-			      obj->string.length,
+	len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
+			      obj->buffer.length,
 			      UTF16_LITTLE_ENDIAN,
 			      buf, PAGE_SIZE);
 	buf[len] = '\n';
@@ -187,16 +187,22 @@ static int dsm_get_label(struct device *
 	tmp = obj->package.elements;
 	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
 	    tmp[0].type == ACPI_TYPE_INTEGER &&
-	    tmp[1].type == ACPI_TYPE_STRING) {
+	    (tmp[1].type == ACPI_TYPE_STRING ||
+	     tmp[1].type == ACPI_TYPE_BUFFER)) {
 		/*
 		 * The second string element is optional even when
 		 * this _DSM is implemented; when not implemented,
 		 * this entry must return a null string.
 		 */
-		if (attr == ACPI_ATTR_INDEX_SHOW)
+		if (attr == ACPI_ATTR_INDEX_SHOW) {
 			scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value);
-		else if (attr == ACPI_ATTR_LABEL_SHOW)
-			dsm_label_utf16s_to_utf8s(tmp + 1, buf);
+		} else if (attr == ACPI_ATTR_LABEL_SHOW) {
+			if (tmp[1].type == ACPI_TYPE_STRING)
+				scnprintf(buf, PAGE_SIZE, "%s\n",
+					  tmp[1].string.pointer);
+			else if (tmp[1].type == ACPI_TYPE_BUFFER)
+				dsm_label_utf16s_to_utf8s(tmp + 1, buf);
+		}
 		len = strlen(buf) > 0 ? strlen(buf) : -1;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/probe.c linux-libre-3.17-rc7-gnu/drivers/pci/probe.c
--- linux-libre-3.16-gnu/drivers/pci/probe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/probe.c	2014-09-28 17:29:07.000000000 -0400
@@ -775,7 +775,7 @@ int pci_scan_bridge(struct pci_bus *bus,
 	/* Check if setup is sensible at all */
 	if (!pass &&
 	    (primary != bus->number || secondary <= bus->number ||
-	     secondary > subordinate || subordinate > bus->busn_res.end)) {
+	     secondary > subordinate)) {
 		dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
 			 secondary, subordinate);
 		broken = 1;
@@ -838,23 +838,18 @@ int pci_scan_bridge(struct pci_bus *bus,
 			goto out;
 		}
 
-		if (max >= bus->busn_res.end) {
-			dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
-				 max, &bus->busn_res);
-			goto out;
-		}
-
 		/* Clear errors */
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-		/* The bus will already exist if we are rescanning */
+		/* Prevent assigning a bus number that already exists.
+		 * This can happen when a bridge is hot-plugged, so in
+		 * this case we only re-scan this bus. */
 		child = pci_find_bus(pci_domain_nr(bus), max+1);
 		if (!child) {
 			child = pci_add_new_bus(bus, dev, max+1);
 			if (!child)
 				goto out;
-			pci_bus_insert_busn_res(child, max+1,
-						bus->busn_res.end);
+			pci_bus_insert_busn_res(child, max+1, 0xff);
 		}
 		max++;
 		buses = (buses & 0xff000000)
@@ -913,11 +908,6 @@ int pci_scan_bridge(struct pci_bus *bus,
 		/*
 		 * Set the subordinate bus number to its real value.
 		 */
-		if (max > bus->busn_res.end) {
-			dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
-				 max, &bus->busn_res);
-			max = bus->busn_res.end;
-		}
 		pci_bus_update_busn_res_end(child, max);
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/quirks.c linux-libre-3.17-rc7-gnu/drivers/pci/quirks.c
--- linux-libre-3.16-gnu/drivers/pci/quirks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/quirks.c	2014-09-28 17:29:07.000000000 -0400
@@ -2986,6 +2986,103 @@ DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601,
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169,
 			 quirk_broken_intx_masking);
 
+#ifdef CONFIG_ACPI
+/*
+ * Apple: Shutdown Cactus Ridge Thunderbolt controller.
+ *
+ * On Apple hardware the Cactus Ridge Thunderbolt controller needs to be
+ * shutdown before suspend. Otherwise the native host interface (NHI) will not
+ * be present after resume if a device was plugged in before suspend.
+ *
+ * The thunderbolt controller consists of a pcie switch with downstream
+ * bridges leading to the NHI and to the tunnel pci bridges.
+ *
+ * This quirk cuts power to the whole chip. Therefore we have to apply it
+ * during suspend_noirq of the upstream bridge.
+ *
+ * Power is automagically restored before resume. No action is needed.
+ */
+static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
+{
+	acpi_handle bridge, SXIO, SXFP, SXLV;
+
+	if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
+		return;
+	if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM)
+		return;
+	bridge = ACPI_HANDLE(&dev->dev);
+	if (!bridge)
+		return;
+	/*
+	 * SXIO and SXLV are present only on machines requiring this quirk.
+	 * TB bridges in external devices might have the same device id as those
+	 * on the host, but they will not have the associated ACPI methods. This
+	 * implicitly checks that we are at the right bridge.
+	 */
+	if (ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXIO", &SXIO))
+	    || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXFP", &SXFP))
+	    || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXLV", &SXLV)))
+		return;
+	dev_info(&dev->dev, "quirk: cutting power to thunderbolt controller...\n");
+
+	/* magic sequence */
+	acpi_execute_simple_method(SXIO, NULL, 1);
+	acpi_execute_simple_method(SXFP, NULL, 0);
+	msleep(300);
+	acpi_execute_simple_method(SXLV, NULL, 0);
+	acpi_execute_simple_method(SXIO, NULL, 0);
+	acpi_execute_simple_method(SXLV, NULL, 0);
+}
+DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547,
+			       quirk_apple_poweroff_thunderbolt);
+
+/*
+ * Apple: Wait for the thunderbolt controller to reestablish pci tunnels.
+ *
+ * During suspend the thunderbolt controller is reset and all pci
+ * tunnels are lost. The NHI driver will try to reestablish all tunnels
+ * during resume. We have to manually wait for the NHI since there is
+ * no parent child relationship between the NHI and the tunneled
+ * bridges.
+ */
+static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
+{
+	struct pci_dev *sibling = NULL;
+	struct pci_dev *nhi = NULL;
+
+	if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
+		return;
+	if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	/*
+	 * Find the NHI and confirm that we are a bridge on the tb host
+	 * controller and not on a tb endpoint.
+	 */
+	sibling = pci_get_slot(dev->bus, 0x0);
+	if (sibling == dev)
+		goto out; /* we are the downstream bridge to the NHI */
+	if (!sibling || !sibling->subordinate)
+		goto out;
+	nhi = pci_get_slot(sibling->subordinate, 0x0);
+	if (!nhi)
+		goto out;
+	if (nhi->vendor != PCI_VENDOR_ID_INTEL
+			|| (nhi->device != 0x1547 && nhi->device != 0x156c)
+			|| nhi->subsystem_vendor != 0x2222
+			|| nhi->subsystem_device != 0x1111)
+		goto out;
+	dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n");
+	device_pm_wait_for_dev(&dev->dev, &nhi->dev);
+out:
+	pci_dev_put(nhi);
+	pci_dev_put(sibling);
+}
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547,
+			       quirk_apple_wait_for_thunderbolt);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d,
+			       quirk_apple_wait_for_thunderbolt);
+#endif
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {
@@ -3018,6 +3115,8 @@ extern struct pci_fixup __start_pci_fixu
 extern struct pci_fixup __end_pci_fixups_resume_early[];
 extern struct pci_fixup __start_pci_fixups_suspend[];
 extern struct pci_fixup __end_pci_fixups_suspend[];
+extern struct pci_fixup __start_pci_fixups_suspend_late[];
+extern struct pci_fixup __end_pci_fixups_suspend_late[];
 
 static bool pci_apply_fixup_final_quirks;
 
@@ -3063,6 +3162,11 @@ void pci_fixup_device(enum pci_fixup_pas
 		end = __end_pci_fixups_suspend;
 		break;
 
+	case pci_fixup_suspend_late:
+		start = __start_pci_fixups_suspend_late;
+		end = __end_pci_fixups_suspend_late;
+		break;
+
 	default:
 		/* stupid compiler warning, you would think with an enum... */
 		return;
@@ -3405,6 +3509,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_A
 DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias);
 /* ITE 8892, https://bugzilla.kernel.org/show_bug.cgi?id=73551 */
 DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
+/* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
+DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
 
 static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/setup-bus.c linux-libre-3.17-rc7-gnu/drivers/pci/setup-bus.c
--- linux-libre-3.16-gnu/drivers/pci/setup-bus.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/setup-bus.c	2014-09-28 17:29:07.000000000 -0400
@@ -925,7 +925,7 @@ static int pbus_size_mem(struct pci_bus
 {
 	struct pci_dev *dev;
 	resource_size_t min_align, align, size, size0, size1;
-	resource_size_t aligns[14];	/* Alignments from 1Mb to 8Gb */
+	resource_size_t aligns[18];	/* Alignments from 1Mb to 128Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus,
 					mask | IORESOURCE_PREFETCH, type);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pci/setup-res.c linux-libre-3.17-rc7-gnu/drivers/pci/setup-res.c
--- linux-libre-3.16-gnu/drivers/pci/setup-res.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pci/setup-res.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,11 +166,10 @@ static int pci_revert_fw_address(struct
 {
 	struct resource *root, *conflict;
 	resource_size_t fw_addr, start, end;
-	int ret = 0;
 
 	fw_addr = pcibios_retrieve_fw_addr(dev, resno);
 	if (!fw_addr)
-		return 1;
+		return -ENOMEM;
 
 	start = res->start;
 	end = res->end;
@@ -189,14 +188,13 @@ static int pci_revert_fw_address(struct
 		 resno, res);
 	conflict = request_resource_conflict(root, res);
 	if (conflict) {
-		dev_info(&dev->dev,
-			 "BAR %d: %pR conflicts with %s %pR\n", resno,
-			 res, conflict->name, conflict);
+		dev_info(&dev->dev, "BAR %d: %pR conflicts with %s %pR\n",
+			 resno, res, conflict->name, conflict);
 		res->start = start;
 		res->end = end;
-		ret = 1;
+		return -EBUSY;
 	}
-	return ret;
+	return 0;
 }
 
 static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
@@ -250,10 +248,8 @@ static int __pci_assign_resource(struct
 static int _pci_assign_resource(struct pci_dev *dev, int resno,
 				resource_size_t size, resource_size_t min_align)
 {
-	struct resource *res = dev->resource + resno;
 	struct pci_bus *bus;
 	int ret;
-	char *type;
 
 	bus = dev->bus;
 	while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
@@ -262,21 +258,6 @@ static int _pci_assign_resource(struct p
 		bus = bus->parent;
 	}
 
-	if (ret) {
-		if (res->flags & IORESOURCE_MEM)
-			if (res->flags & IORESOURCE_PREFETCH)
-				type = "mem pref";
-			else
-				type = "mem";
-		else if (res->flags & IORESOURCE_IO)
-			type = "io";
-		else
-			type = "unknown";
-		dev_info(&dev->dev,
-			 "BAR %d: can't assign %s (size %#llx)\n",
-			 resno, type, (unsigned long long) resource_size(res));
-	}
-
 	return ret;
 }
 
@@ -302,17 +283,24 @@ int pci_assign_resource(struct pci_dev *
 	 * where firmware left it.  That at least has a chance of
 	 * working, which is better than just leaving it disabled.
 	 */
-	if (ret < 0)
+	if (ret < 0) {
+		dev_info(&dev->dev, "BAR %d: no space for %pR\n", resno, res);
 		ret = pci_revert_fw_address(res, dev, resno, size);
+	}
 
-	if (!ret) {
-		res->flags &= ~IORESOURCE_UNSET;
-		res->flags &= ~IORESOURCE_STARTALIGN;
-		dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
-		if (resno < PCI_BRIDGE_RESOURCES)
-			pci_update_resource(dev, resno);
+	if (ret < 0) {
+		dev_info(&dev->dev, "BAR %d: failed to assign %pR\n", resno,
+			 res);
+		return ret;
 	}
-	return ret;
+
+	res->flags &= ~IORESOURCE_UNSET;
+	res->flags &= ~IORESOURCE_STARTALIGN;
+	dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
+	if (resno < PCI_BRIDGE_RESOURCES)
+		pci_update_resource(dev, resno);
+
+	return 0;
 }
 EXPORT_SYMBOL(pci_assign_resource);
 
@@ -320,9 +308,11 @@ int pci_reassign_resource(struct pci_dev
 			resource_size_t min_align)
 {
 	struct resource *res = dev->resource + resno;
+	unsigned long flags;
 	resource_size_t new_size;
 	int ret;
 
+	flags = res->flags;
 	res->flags |= IORESOURCE_UNSET;
 	if (!res->parent) {
 		dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR\n",
@@ -333,14 +323,21 @@ int pci_reassign_resource(struct pci_dev
 	/* already aligned with min_align */
 	new_size = resource_size(res) + addsize;
 	ret = _pci_assign_resource(dev, resno, new_size, min_align);
-	if (!ret) {
-		res->flags &= ~IORESOURCE_UNSET;
-		res->flags &= ~IORESOURCE_STARTALIGN;
-		dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
-		if (resno < PCI_BRIDGE_RESOURCES)
-			pci_update_resource(dev, resno);
+	if (ret) {
+		res->flags = flags;
+		dev_info(&dev->dev, "BAR %d: %pR (failed to expand by %#llx)\n",
+			 resno, res, (unsigned long long) addsize);
+		return ret;
 	}
-	return ret;
+
+	res->flags &= ~IORESOURCE_UNSET;
+	res->flags &= ~IORESOURCE_STARTALIGN;
+	dev_info(&dev->dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
+		 resno, res, (unsigned long long) addsize);
+	if (resno < PCI_BRIDGE_RESOURCES)
+		pci_update_resource(dev, resno);
+
+	return 0;
 }
 
 int pci_enable_resources(struct pci_dev *dev, int mask)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/bcm63xx_pcmcia.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/bcm63xx_pcmcia.c
--- linux-libre-3.16-gnu/drivers/pcmcia/bcm63xx_pcmcia.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/bcm63xx_pcmcia.c	2014-09-28 17:29:07.000000000 -0400
@@ -475,7 +475,7 @@ static void bcm63xx_cb_exit(struct pci_d
 	bcm63xx_cb_dev = NULL;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(bcm63xx_cb_table) = {
+static const struct pci_device_id bcm63xx_cb_table[] = {
 	{
 		.vendor		= PCI_VENDOR_ID_BROADCOM,
 		.device		= BCM6348_CPU_ID,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/i82092.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/i82092.c
--- linux-libre-3.16-gnu/drivers/pcmcia/i82092.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/i82092.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 MODULE_LICENSE("GPL");
 
 /* PCI core routines */
-static DEFINE_PCI_DEVICE_TABLE(i82092aa_pci_ids) = {
+static const struct pci_device_id i82092aa_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
 	{ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/Kconfig linux-libre-3.17-rc7-gnu/drivers/pcmcia/Kconfig
--- linux-libre-3.16-gnu/drivers/pcmcia/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -144,16 +144,6 @@ config TCIC
 	  "Bridge" is the name used for the hardware inside your computer that
 	  PCMCIA cards are plugged into. If unsure, say N.
 
-config PCMCIA_M8XX
-	tristate "MPC8xx PCMCIA support"
-	depends on PCCARD && PPC && 8xx
-	select PCCARD_IODYN if PCMCIA != n
-	help
-	  Say Y here to include support for PowerPC 8xx series PCMCIA
-	  controller.
-
-	  This driver is also available as a module called m8xx_pcmcia.
-
 config PCMCIA_ALCHEMY_DEVBOARD
 	tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
 	depends on MIPS_ALCHEMY && PCMCIA
@@ -202,6 +192,7 @@ config PCMCIA_SA1111
 	depends on ARM && SA1111 && PCMCIA
 	select PCMCIA_SOC_COMMON
 	select PCMCIA_SA11XX_BASE if ARCH_SA1100
+	select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111
 	help
 	  Say Y  here to include support for SA1111-based PCMCIA or CF
 	  sockets, found on the Jornada 720, Graphicsmaster and other
@@ -217,7 +208,6 @@ config PCMCIA_PXA2XX
 		    || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
 		    || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
 		    || MACH_COLIBRI320 || MACH_H4700)
-	select PCMCIA_SA1111 if ARCH_LUBBOCK && SA1111
 	select PCMCIA_SOC_COMMON
 	help
 	  Say Y here to include support for the PXA2xx PCMCIA controller
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/m8xx_pcmcia.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/m8xx_pcmcia.c
--- linux-libre-3.16-gnu/drivers/pcmcia/m8xx_pcmcia.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/m8xx_pcmcia.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1168 +0,0 @@
-/*
- * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
- *
- * (C) 1999-2000 Magnus Damm <damm@opensource.se>
- * (C) 2001-2002 Montavista Software, Inc.
- *     <mlocke@mvista.com>
- *
- * Support for two slots by Cyclades Corporation
- *     <oliver.kurth@cyclades.de>
- * Further fixes, v2.6 kernel port
- *     <marcelo.tosatti@cyclades.com>
- * 
- * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
- *     <vbordug@ru.mvista.com>
- *
- * "The ExCA standard specifies that socket controllers should provide
- * two IO and five memory windows per socket, which can be independently
- * configured and positioned in the host address space and mapped to
- * arbitrary segments of card address space. " - David A Hinds. 1999
- *
- * This controller does _not_ meet the ExCA standard.
- *
- * m8xx pcmcia controller brief info:
- * + 8 windows (attrib, mem, i/o)
- * + up to two slots (SLOT_A and SLOT_B)
- * + inputpins, outputpins, event and mask registers.
- * - no offset register. sigh.
- *
- * Because of the lacking offset register we must map the whole card.
- * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
- * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
- * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
- * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
- * They are maximum 64KByte each...
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/string.h>
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/bitops.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/mpc8xx.h>
-#include <asm/8xx_immap.h>
-#include <asm/irq.h>
-#include <asm/fs_pd.h>
-
-#include <pcmcia/ss.h>
-
-#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
-#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
-
-static const char *version = "Version 0.06, Aug 2005";
-MODULE_LICENSE("Dual MPL/GPL");
-
-#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
-
-/* The ADS board use SLOT_A */
-#ifdef CONFIG_ADS
-#define CONFIG_PCMCIA_SLOT_A
-#define CONFIG_BD_IS_MHZ
-#endif
-
-/* The FADS series are a mess */
-#ifdef CONFIG_FADS
-#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
-#define CONFIG_PCMCIA_SLOT_A
-#else
-#define CONFIG_PCMCIA_SLOT_B
-#endif
-#endif
-
-#if defined(CONFIG_MPC885ADS)
-#define CONFIG_PCMCIA_SLOT_A
-#define PCMCIA_GLITCHY_CD
-#endif
-
-/* Cyclades ACS uses both slots */
-#ifdef CONFIG_PRxK
-#define CONFIG_PCMCIA_SLOT_A
-#define CONFIG_PCMCIA_SLOT_B
-#endif
-
-#endif				/* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
-
-#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
-
-#define PCMCIA_SOCKETS_NO 2
-/* We have only 8 windows, dualsocket support will be limited. */
-#define PCMCIA_MEM_WIN_NO 2
-#define PCMCIA_IO_WIN_NO  2
-#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
-
-#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
-
-#define PCMCIA_SOCKETS_NO 1
-/* full support for one slot */
-#define PCMCIA_MEM_WIN_NO 5
-#define PCMCIA_IO_WIN_NO  2
-
-/* define _slot_ to be able to optimize macros */
-
-#ifdef CONFIG_PCMCIA_SLOT_A
-#define _slot_ 0
-#define PCMCIA_SLOT_MSG "SLOT_A"
-#else
-#define _slot_ 1
-#define PCMCIA_SLOT_MSG "SLOT_B"
-#endif
-
-#else
-#error m8xx_pcmcia: Bad configuration!
-#endif
-
-/* ------------------------------------------------------------------------- */
-
-#define PCMCIA_MEM_WIN_BASE 0xe0000000	/* base address for memory window 0   */
-#define PCMCIA_MEM_WIN_SIZE 0x04000000	/* each memory window is 64 MByte     */
-#define PCMCIA_IO_WIN_BASE  _IO_BASE	/* base address for io window 0       */
-/* ------------------------------------------------------------------------- */
-
-static int pcmcia_schlvl;
-
-static DEFINE_SPINLOCK(events_lock);
-
-#define PCMCIA_SOCKET_KEY_5V 1
-#define PCMCIA_SOCKET_KEY_LV 2
-
-/* look up table for pgcrx registers */
-static u32 *m8xx_pgcrx[2];
-
-/*
- * This structure is used to address each window in the PCMCIA controller.
- *
- * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
- * after pcmcia_win[n]...
- */
-
-struct pcmcia_win {
-	u32 br;
-	u32 or;
-};
-
-/*
- * For some reason the hardware guys decided to make both slots share
- * some registers.
- *
- * Could someone invent object oriented hardware ?
- *
- * The macros are used to get the right bit from the registers.
- * SLOT_A : slot = 0
- * SLOT_B : slot = 1
- */
-
-#define M8XX_PCMCIA_VS1(slot)      (0x80000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS2(slot)      (0x40000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS_MASK(slot)  (0xc0000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
-
-#define M8XX_PCMCIA_WP(slot)       (0x20000000 >> (slot << 4))
-#define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))
-#define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))
-#define M8XX_PCMCIA_BVD2(slot)     (0x04000000 >> (slot << 4))
-#define M8XX_PCMCIA_BVD1(slot)     (0x02000000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY(slot)      (0x01000000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_L(slot)    (0x00800000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_H(slot)    (0x00400000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_R(slot)    (0x00200000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_F(slot)    (0x00100000 >> (slot << 4))
-#define M8XX_PCMCIA_MASK(slot)     (0xFFFF0000 >> (slot << 4))
-
-#define M8XX_PCMCIA_POR_VALID    0x00000001
-#define M8XX_PCMCIA_POR_WRPROT   0x00000002
-#define M8XX_PCMCIA_POR_ATTRMEM  0x00000010
-#define M8XX_PCMCIA_POR_IO       0x00000018
-#define M8XX_PCMCIA_POR_16BIT    0x00000040
-
-#define M8XX_PGCRX(slot)  m8xx_pgcrx[slot]
-
-#define M8XX_PGCRX_CXOE    0x00000080
-#define M8XX_PGCRX_CXRESET 0x00000040
-
-/* we keep one lookup table per socket to check flags */
-
-#define PCMCIA_EVENTS_MAX 5	/* 4 max at a time + termination */
-
-struct event_table {
-	u32 regbit;
-	u32 eventbit;
-};
-
-static const char driver_name[] = "m8xx-pcmcia";
-
-struct socket_info {
-	void (*handler) (void *info, u32 events);
-	void *info;
-
-	u32 slot;
-	pcmconf8xx_t *pcmcia;
-	u32 bus_freq;
-	int hwirq;
-
-	socket_state_t state;
-	struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
-	struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
-	struct event_table events[PCMCIA_EVENTS_MAX];
-	struct pcmcia_socket socket;
-};
-
-static struct socket_info socket[PCMCIA_SOCKETS_NO];
-
-/*
- * Search this table to see if the windowsize is
- * supported...
- */
-
-#define M8XX_SIZES_NO 32
-
-static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
-	0x00000001, 0x00000002, 0x00000008, 0x00000004,
-	0x00000080, 0x00000040, 0x00000010, 0x00000020,
-	0x00008000, 0x00004000, 0x00001000, 0x00002000,
-	0x00000100, 0x00000200, 0x00000800, 0x00000400,
-
-	0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-	0x01000000, 0x02000000, 0xffffffff, 0x04000000,
-	0x00010000, 0x00020000, 0x00080000, 0x00040000,
-	0x00800000, 0x00400000, 0x00100000, 0x00200000
-};
-
-/* ------------------------------------------------------------------------- */
-
-static irqreturn_t m8xx_interrupt(int irq, void *dev);
-
-#define PCMCIA_BMT_LIMIT (15*4)	/* Bus Monitor Timeout value */
-
-/* FADS Boards from Motorola                                               */
-
-#if defined(CONFIG_FADS)
-
-#define PCMCIA_BOARD_MSG "FADS"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u32 reg = 0;
-
-	switch (vcc) {
-	case 0:
-		break;
-	case 33:
-		reg |= BCSR1_PCCVCC0;
-		break;
-	case 50:
-		reg |= BCSR1_PCCVCC1;
-		break;
-	default:
-		return 1;
-	}
-
-	switch (vpp) {
-	case 0:
-		break;
-	case 33:
-	case 50:
-		if (vcc == vpp)
-			reg |= BCSR1_PCCVPP1;
-		else
-			return 1;
-		break;
-	case 120:
-		if ((vcc == 33) || (vcc == 50))
-			reg |= BCSR1_PCCVPP0;
-		else
-			return 1;
-	default:
-		return 1;
-	}
-
-	/* first, turn off all power */
-	out_be32((u32 *) BCSR1,
-		 in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
-					    BCSR1_PCCVPP_MASK));
-
-	/* enable new powersettings */
-	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
-
-	return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static void hardware_enable(int slot)
-{
-	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
-}
-
-static void hardware_disable(int slot)
-{
-	out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
-}
-
-#endif
-
-/* MPC885ADS Boards */
-
-#if defined(CONFIG_MPC885ADS)
-
-#define PCMCIA_BOARD_MSG "MPC885ADS"
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static inline void hardware_enable(int slot)
-{
-	m8xx_pcmcia_ops.hw_ctrl(slot, 1);
-}
-
-static inline void hardware_disable(int slot)
-{
-	m8xx_pcmcia_ops.hw_ctrl(slot, 0);
-}
-
-static inline int voltage_set(int slot, int vcc, int vpp)
-{
-	return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
-}
-
-#endif
-
-#if defined(CONFIG_PRxK)
-#include <asm/cpld.h>
-extern volatile fpga_pc_regs *fpga_pc;
-
-#define PCMCIA_BOARD_MSG "MPC855T"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u8 reg = 0;
-	u8 regread;
-	cpld_regs *ccpld = get_cpld();
-
-	switch (vcc) {
-	case 0:
-		break;
-	case 33:
-		reg |= PCMCIA_VCC_33;
-		break;
-	case 50:
-		reg |= PCMCIA_VCC_50;
-		break;
-	default:
-		return 1;
-	}
-
-	switch (vpp) {
-	case 0:
-		break;
-	case 33:
-	case 50:
-		if (vcc == vpp)
-			reg |= PCMCIA_VPP_VCC;
-		else
-			return 1;
-		break;
-	case 120:
-		if ((vcc == 33) || (vcc == 50))
-			reg |= PCMCIA_VPP_12;
-		else
-			return 1;
-	default:
-		return 1;
-	}
-
-	reg = reg >> (slot << 2);
-	regread = in_8(&ccpld->fpga_pc_ctl);
-	if (reg !=
-	    (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
-		/* enable new powersettings */
-		regread =
-		    regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
-				(slot << 2));
-		out_8(&ccpld->fpga_pc_ctl, reg | regread);
-		msleep(100);
-	}
-
-	return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
-#define hardware_enable(_slot_)	/* No hardware to enable */
-#define hardware_disable(_slot_)	/* No hardware to disable */
-
-#endif				/* CONFIG_PRxK */
-
-static u32 pending_events[PCMCIA_SOCKETS_NO];
-static DEFINE_SPINLOCK(pending_event_lock);
-
-static irqreturn_t m8xx_interrupt(int irq, void *dev)
-{
-	struct socket_info *s;
-	struct event_table *e;
-	unsigned int i, events, pscr, pipr, per;
-	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
-	pr_debug("m8xx_pcmcia: Interrupt!\n");
-	/* get interrupt sources */
-
-	pscr = in_be32(&pcmcia->pcmc_pscr);
-	pipr = in_be32(&pcmcia->pcmc_pipr);
-	per = in_be32(&pcmcia->pcmc_per);
-
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
-		s = &socket[i];
-		e = &s->events[0];
-		events = 0;
-
-		while (e->regbit) {
-			if (pscr & e->regbit)
-				events |= e->eventbit;
-
-			e++;
-		}
-
-		/*
-		 * report only if both card detect signals are the same
-		 * not too nice done,
-		 * we depend on that CD2 is the bit to the left of CD1...
-		 */
-		if (events & SS_DETECT)
-			if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
-			    (pipr & M8XX_PCMCIA_CD1(i))) {
-				events &= ~SS_DETECT;
-			}
-#ifdef PCMCIA_GLITCHY_CD
-		/*
-		 * I've experienced CD problems with my ADS board.
-		 * We make an extra check to see if there was a
-		 * real change of Card detection.
-		 */
-
-		if ((events & SS_DETECT) &&
-		    ((pipr &
-		      (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
-		    (s->state.Vcc | s->state.Vpp)) {
-			events &= ~SS_DETECT;
-			/*printk( "CD glitch workaround - CD = 0x%08x!\n",
-			   (pipr & (M8XX_PCMCIA_CD2(i)
-			   | M8XX_PCMCIA_CD1(i)))); */
-		}
-#endif
-
-		/* call the handler */
-
-		pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, "
-			"pipr = 0x%08x\n", i, events, pscr, pipr);
-
-		if (events) {
-			spin_lock(&pending_event_lock);
-			pending_events[i] |= events;
-			spin_unlock(&pending_event_lock);
-			/*
-			 * Turn off RDY_L bits in the PER mask on
-			 * CD interrupt receival.
-			 *
-			 * They can generate bad interrupts on the
-			 * ACS4,8,16,32.   - marcelo
-			 */
-			per &= ~M8XX_PCMCIA_RDY_L(0);
-			per &= ~M8XX_PCMCIA_RDY_L(1);
-
-			out_be32(&pcmcia->pcmc_per, per);
-
-			if (events)
-				pcmcia_parse_events(&socket[i].socket, events);
-		}
-	}
-
-	/* clear the interrupt sources */
-	out_be32(&pcmcia->pcmc_pscr, pscr);
-
-	pr_debug("m8xx_pcmcia: Interrupt done.\n");
-
-	return IRQ_HANDLED;
-}
-
-static u32 m8xx_get_graycode(u32 size)
-{
-	u32 k;
-
-	for (k = 0; k < M8XX_SIZES_NO; k++)
-		if (m8xx_size_to_gray[k] == size)
-			break;
-
-	if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
-		k = -1;
-
-	return k;
-}
-
-static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
-{
-	u32 reg, clocks, psst, psl, psht;
-
-	if (!ns) {
-
-		/*
-		 * We get called with IO maps setup to 0ns
-		 * if not specified by the user.
-		 * They should be 255ns.
-		 */
-
-		if (is_io)
-			ns = 255;
-		else
-			ns = 100;	/* fast memory if 0 */
-	}
-
-	/*
-	 * In PSST, PSL, PSHT fields we tell the controller
-	 * timing parameters in CLKOUT clock cycles.
-	 * CLKOUT is the same as GCLK2_50.
-	 */
-
-/* how we want to adjust the timing - in percent */
-
-#define ADJ 180			/* 80 % longer accesstime - to be sure */
-
-	clocks = ((bus_freq / 1000) * ns) / 1000;
-	clocks = (clocks * ADJ) / (100 * 1000);
-	if (clocks >= PCMCIA_BMT_LIMIT) {
-		printk("Max access time limit reached\n");
-		clocks = PCMCIA_BMT_LIMIT - 1;
-	}
-
-	psst = clocks / 7;	/* setup time */
-	psht = clocks / 7;	/* hold time */
-	psl = (clocks * 5) / 7;	/* strobe length */
-
-	psst += clocks - (psst + psht + psl);
-
-	reg = psst << 12;
-	reg |= psl << 7;
-	reg |= psht << 16;
-
-	return reg;
-}
-
-static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
-{
-	int lsock = container_of(sock, struct socket_info, socket)->slot;
-	struct socket_info *s = &socket[lsock];
-	unsigned int pipr, reg;
-	pcmconf8xx_t *pcmcia = s->pcmcia;
-
-	pipr = in_be32(&pcmcia->pcmc_pipr);
-
-	*value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
-			   | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
-	*value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
-
-	if (s->state.flags & SS_IOCARD)
-		*value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
-	else {
-		*value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
-		*value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
-		*value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
-	}
-
-	if (s->state.Vcc | s->state.Vpp)
-		*value |= SS_POWERON;
-
-	/*
-	 * Voltage detection:
-	 * This driver only supports 16-Bit pc-cards.
-	 * Cardbus is not handled here.
-	 *
-	 * To determine what voltage to use we must read the VS1 and VS2 pin.
-	 * Depending on what socket type is present,
-	 * different combinations mean different things.
-	 *
-	 * Card Key  Socket Key   VS1   VS2   Card         Vcc for CIS parse
-	 *
-	 * 5V        5V, LV*      NC    NC    5V only       5V (if available)
-	 *
-	 * 5V        5V, LV*      GND   NC    5 or 3.3V     as low as possible
-	 *
-	 * 5V        5V, LV*      GND   GND   5, 3.3, x.xV  as low as possible
-	 *
-	 * LV*       5V            -     -    shall not fit into socket
-	 *
-	 * LV*       LV*          GND   NC    3.3V only     3.3V
-	 *
-	 * LV*       LV*          NC    GND   x.xV          x.xV (if avail.)
-	 *
-	 * LV*       LV*          GND   GND   3.3 or x.xV   as low as possible
-	 *
-	 * *LV means Low Voltage
-	 *
-	 *
-	 * That gives us the following table:
-	 *
-	 * Socket    VS1  VS2   Voltage
-	 *
-	 * 5V        NC   NC    5V
-	 * 5V        NC   GND   none (should not be possible)
-	 * 5V        GND  NC    >= 3.3V
-	 * 5V        GND  GND   >= x.xV
-	 *
-	 * LV        NC   NC    5V   (if available)
-	 * LV        NC   GND   x.xV (if available)
-	 * LV        GND  NC    3.3V
-	 * LV        GND  GND   >= x.xV
-	 *
-	 * So, how do I determine if I have a 5V or a LV
-	 * socket on my board?  Look at the socket!
-	 *
-	 *
-	 * Socket with 5V key:
-	 * ++--------------------------------------------+
-	 * ||                                            |
-	 * ||                                           ||
-	 * ||                                           ||
-	 * |                                             |
-	 * +---------------------------------------------+
-	 *
-	 * Socket with LV key:
-	 * ++--------------------------------------------+
-	 * ||                                            |
-	 * |                                            ||
-	 * |                                            ||
-	 * |                                             |
-	 * +---------------------------------------------+
-	 *
-	 *
-	 * With other words - LV only cards does not fit
-	 * into the 5V socket!
-	 */
-
-	/* read out VS1 and VS2 */
-
-	reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
-	    >> M8XX_PCMCIA_VS_SHIFT(lsock);
-
-	if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
-		switch (reg) {
-		case 1:
-			*value |= SS_3VCARD;
-			break;	/* GND, NC - 3.3V only */
-		case 2:
-			*value |= SS_XVCARD;
-			break;	/* NC. GND - x.xV only */
-		};
-	}
-
-	pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value);
-	return 0;
-}
-
-static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
-{
-	int lsock = container_of(sock, struct socket_info, socket)->slot;
-	struct socket_info *s = &socket[lsock];
-	struct event_table *e;
-	unsigned int reg;
-	unsigned long flags;
-	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
-	pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
-		"io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
-		state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-
-	/* First, set voltage - bail out if invalid */
-	if (voltage_set(lsock, state->Vcc, state->Vpp))
-		return -EINVAL;
-
-	/* Take care of reset... */
-	if (state->flags & SS_RESET)
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET);	/* active high */
-	else
-		out_be32(M8XX_PGCRX(lsock),
-			 in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
-
-	/* ... and output enable. */
-
-	/* The CxOE signal is connected to a 74541 on the ADS.
-	   I guess most other boards used the ADS as a reference.
-	   I tried to control the CxOE signal with SS_OUTPUT_ENA,
-	   but the reset signal seems connected via the 541.
-	   If the CxOE is left high are some signals tristated and
-	   no pullups are present -> the cards act weird.
-	   So right now the buffers are enabled if the power is on. */
-
-	if (state->Vcc || state->Vpp)
-		out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE);	/* active low */
-	else
-		out_be32(M8XX_PGCRX(lsock),
-			 in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
-
-	/*
-	 * We'd better turn off interrupts before
-	 * we mess with the events-table..
-	 */
-
-	spin_lock_irqsave(&events_lock, flags);
-
-	/*
-	 * Play around with the interrupt mask to be able to
-	 * give the events the generic pcmcia driver wants us to.
-	 */
-
-	e = &s->events[0];
-	reg = 0;
-
-	if (state->csc_mask & SS_DETECT) {
-		e->eventbit = SS_DETECT;
-		reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
-				    | M8XX_PCMCIA_CD1(lsock));
-		e++;
-	}
-	if (state->flags & SS_IOCARD) {
-		/*
-		 * I/O card
-		 */
-		if (state->csc_mask & SS_STSCHG) {
-			e->eventbit = SS_STSCHG;
-			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
-			e++;
-		}
-		/*
-		 * If io_irq is non-zero we should enable irq.
-		 */
-		if (state->io_irq) {
-			out_be32(M8XX_PGCRX(lsock),
-				 in_be32(M8XX_PGCRX(lsock)) |
-				 mk_int_int_mask(s->hwirq) << 24);
-			/*
-			 * Strange thing here:
-			 * The manual does not tell us which interrupt
-			 * the sources generate.
-			 * Anyhow, I found out that RDY_L generates IREQLVL.
-			 *
-			 * We use level triggerd interrupts, and they don't
-			 * have to be cleared in PSCR in the interrupt handler.
-			 */
-			reg |= M8XX_PCMCIA_RDY_L(lsock);
-		} else
-			out_be32(M8XX_PGCRX(lsock),
-				 in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
-	} else {
-		/*
-		 * Memory card
-		 */
-		if (state->csc_mask & SS_BATDEAD) {
-			e->eventbit = SS_BATDEAD;
-			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
-			e++;
-		}
-		if (state->csc_mask & SS_BATWARN) {
-			e->eventbit = SS_BATWARN;
-			reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
-			e++;
-		}
-		/* What should I trigger on - low/high,raise,fall? */
-		if (state->csc_mask & SS_READY) {
-			e->eventbit = SS_READY;
-			reg |= e->regbit = 0;	//??
-			e++;
-		}
-	}
-
-	e->regbit = 0;		/* terminate list */
-
-	/*
-	 * Clear the status changed .
-	 * Port A and Port B share the same port.
-	 * Writing ones will clear the bits.
-	 */
-
-	out_be32(&pcmcia->pcmc_pscr, reg);
-
-	/*
-	 * Write the mask.
-	 * Port A and Port B share the same port.
-	 * Need for read-modify-write.
-	 * Ones will enable the interrupt.
-	 */
-
-	reg |=
-	    in_be32(&pcmcia->
-		    pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-	out_be32(&pcmcia->pcmc_per, reg);
-
-	spin_unlock_irqrestore(&events_lock, flags);
-
-	/* copy the struct and modify the copy */
-
-	s->state = *state;
-
-	return 0;
-}
-
-static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
-{
-	int lsock = container_of(sock, struct socket_info, socket)->slot;
-
-	struct socket_info *s = &socket[lsock];
-	struct pcmcia_win *w;
-	unsigned int reg, winnr;
-	pcmconf8xx_t *pcmcia = s->pcmcia;
-
-#define M8XX_SIZE (io->stop - io->start + 1)
-#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
-
-	pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, "
-		"%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
-		io->speed, (unsigned long long)io->start,
-		(unsigned long long)io->stop);
-
-	if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
-	    || (io->stop > 0xffff) || (io->stop < io->start))
-		return -EINVAL;
-
-	if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
-		return -EINVAL;
-
-	if (io->flags & MAP_ACTIVE) {
-
-		pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n");
-
-		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
-		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
-
-		/* setup registers */
-
-		w = (void *)&pcmcia->pcmc_pbr0;
-		w += winnr;
-
-		out_be32(&w->or, 0);	/* turn off window first */
-		out_be32(&w->br, M8XX_BASE);
-
-		reg <<= 27;
-		reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
-
-		reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
-
-		if (io->flags & MAP_WRPROT)
-			reg |= M8XX_PCMCIA_POR_WRPROT;
-
-		/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
-		if (io->flags & MAP_16BIT)
-			reg |= M8XX_PCMCIA_POR_16BIT;
-
-		if (io->flags & MAP_ACTIVE)
-			reg |= M8XX_PCMCIA_POR_VALID;
-
-		out_be32(&w->or, reg);
-
-		pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at "
-			"%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
-	} else {
-		/* shutdown IO window */
-		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
-		    + (lsock * PCMCIA_IO_WIN_NO) + io->map;
-
-		/* setup registers */
-
-		w = (void *)&pcmcia->pcmc_pbr0;
-		w += winnr;
-
-		out_be32(&w->or, 0);	/* turn off window */
-		out_be32(&w->br, 0);	/* turn off base address */
-
-		pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at "
-			"%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
-	}
-
-	/* copy the struct and modify the copy */
-	s->io_win[io->map] = *io;
-	s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
-	pr_debug("m8xx_pcmcia: SetIOMap exit\n");
-
-	return 0;
-}
-
-static int m8xx_set_mem_map(struct pcmcia_socket *sock,
-			    struct pccard_mem_map *mem)
-{
-	int lsock = container_of(sock, struct socket_info, socket)->slot;
-	struct socket_info *s = &socket[lsock];
-	struct pcmcia_win *w;
-	struct pccard_mem_map *old;
-	unsigned int reg, winnr;
-	pcmconf8xx_t *pcmcia = s->pcmcia;
-
-	pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
-		"%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
-		mem->speed, (unsigned long long)mem->static_start,
-		mem->card_start);
-
-	if ((mem->map >= PCMCIA_MEM_WIN_NO)
-//          || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
-	    || (mem->card_start >= 0x04000000)
-	    || (mem->static_start & 0xfff)	/* 4KByte resolution */
-	    ||(mem->card_start & 0xfff))
-		return -EINVAL;
-
-	if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
-		printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
-		return -EINVAL;
-	}
-	reg <<= 27;
-
-	winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
-
-	/* Setup the window in the pcmcia controller */
-
-	w = (void *)&pcmcia->pcmc_pbr0;
-	w += winnr;
-
-	reg |= lsock << 2;
-
-	reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
-
-	if (mem->flags & MAP_ATTRIB)
-		reg |= M8XX_PCMCIA_POR_ATTRMEM;
-
-	if (mem->flags & MAP_WRPROT)
-		reg |= M8XX_PCMCIA_POR_WRPROT;
-
-	if (mem->flags & MAP_16BIT)
-		reg |= M8XX_PCMCIA_POR_16BIT;
-
-	if (mem->flags & MAP_ACTIVE)
-		reg |= M8XX_PCMCIA_POR_VALID;
-
-	out_be32(&w->or, reg);
-
-	pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, "
-		"OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
-
-	if (mem->flags & MAP_ACTIVE) {
-		/* get the new base address */
-		mem->static_start = PCMCIA_MEM_WIN_BASE +
-		    (PCMCIA_MEM_WIN_SIZE * winnr)
-		    + mem->card_start;
-	}
-
-	pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
-		"%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
-		mem->speed, (unsigned long long)mem->static_start,
-		mem->card_start);
-
-	/* copy the struct and modify the copy */
-
-	old = &s->mem_win[mem->map];
-
-	*old = *mem;
-	old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
-
-	return 0;
-}
-
-static int m8xx_sock_init(struct pcmcia_socket *sock)
-{
-	int i;
-	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
-
-	pr_debug("m8xx_pcmcia: sock_init(%d)\n", s);
-
-	m8xx_set_socket(sock, &dead_socket);
-	for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
-		io.map = i;
-		m8xx_set_io_map(sock, &io);
-	}
-	for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
-		mem.map = i;
-		m8xx_set_mem_map(sock, &mem);
-	}
-
-	return 0;
-
-}
-
-static int m8xx_sock_suspend(struct pcmcia_socket *sock)
-{
-	return m8xx_set_socket(sock, &dead_socket);
-}
-
-static struct pccard_operations m8xx_services = {
-	.init = m8xx_sock_init,
-	.suspend = m8xx_sock_suspend,
-	.get_status = m8xx_get_status,
-	.set_socket = m8xx_set_socket,
-	.set_io_map = m8xx_set_io_map,
-	.set_mem_map = m8xx_set_mem_map,
-};
-
-static int __init m8xx_probe(struct platform_device *ofdev)
-{
-	struct pcmcia_win *w;
-	unsigned int i, m, hwirq;
-	pcmconf8xx_t *pcmcia;
-	int status;
-	struct device_node *np = ofdev->dev.of_node;
-
-	pcmcia_info("%s\n", version);
-
-	pcmcia = of_iomap(np, 0);
-	if (pcmcia == NULL)
-		return -EINVAL;
-
-	pcmcia_schlvl = irq_of_parse_and_map(np, 0);
-	hwirq = irq_map[pcmcia_schlvl].hwirq;
-	if (pcmcia_schlvl < 0) {
-		iounmap(pcmcia);
-		return -EINVAL;
-	}
-
-	m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
-	m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
-
-	pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
-		    " with IRQ %u  (%d). \n", pcmcia_schlvl, hwirq);
-
-	/* Configure Status change interrupt */
-
-	if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
-			driver_name, socket)) {
-		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
-			     pcmcia_schlvl);
-		iounmap(pcmcia);
-		return -1;
-	}
-
-	w = (void *)&pcmcia->pcmc_pbr0;
-
-	out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-	clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-
-	/* connect interrupt and disable CxOE */
-
-	out_be32(M8XX_PGCRX(0),
-		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
-	out_be32(M8XX_PGCRX(1),
-		 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
-
-	/* initialize the fixed memory windows */
-
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
-		for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
-			out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
-				 (PCMCIA_MEM_WIN_SIZE
-				  * (m + i * PCMCIA_MEM_WIN_NO)));
-
-			out_be32(&w->or, 0);	/* set to not valid */
-
-			w++;
-		}
-	}
-
-	/* turn off voltage */
-	voltage_set(0, 0, 0);
-	voltage_set(1, 0, 0);
-
-	/* Enable external hardware */
-	hardware_enable(0);
-	hardware_enable(1);
-
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
-		socket[i].slot = i;
-		socket[i].socket.owner = THIS_MODULE;
-		socket[i].socket.features =
-		    SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
-		socket[i].socket.irq_mask = 0x000;
-		socket[i].socket.map_size = 0x1000;
-		socket[i].socket.io_offset = 0;
-		socket[i].socket.pci_irq = pcmcia_schlvl;
-		socket[i].socket.ops = &m8xx_services;
-		socket[i].socket.resource_ops = &pccard_iodyn_ops;
-		socket[i].socket.cb_dev = NULL;
-		socket[i].socket.dev.parent = &ofdev->dev;
-		socket[i].pcmcia = pcmcia;
-		socket[i].bus_freq = ppc_proc_freq;
-		socket[i].hwirq = hwirq;
-
-	}
-
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
-		status = pcmcia_register_socket(&socket[i].socket);
-		if (status < 0)
-			pcmcia_error("Socket register failed\n");
-	}
-
-	return 0;
-}
-
-static int m8xx_remove(struct platform_device *ofdev)
-{
-	u32 m, i;
-	struct pcmcia_win *w;
-	pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
-		w = (void *)&pcmcia->pcmc_pbr0;
-
-		out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
-		out_be32(&pcmcia->pcmc_per,
-			 in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
-
-		/* turn off interrupt and disable CxOE */
-		out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
-
-		/* turn off memory windows */
-		for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
-			out_be32(&w->or, 0);	/* set to not valid */
-			w++;
-		}
-
-		/* turn off voltage */
-		voltage_set(i, 0, 0);
-
-		/* disable external hardware */
-		hardware_disable(i);
-	}
-	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
-		pcmcia_unregister_socket(&socket[i].socket);
-	iounmap(pcmcia);
-
-	free_irq(pcmcia_schlvl, NULL);
-
-	return 0;
-}
-
-static const struct of_device_id m8xx_pcmcia_match[] = {
-	{
-	 .type = "pcmcia",
-	 .compatible = "fsl,pq-pcmcia",
-	 },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
-
-static struct platform_driver m8xx_pcmcia_driver = {
-	.driver = {
-		.name = driver_name,
-		.owner = THIS_MODULE,
-		.of_match_table = m8xx_pcmcia_match,
-	},
-	.probe = m8xx_probe,
-	.remove = m8xx_remove,
-};
-
-module_platform_driver(m8xx_pcmcia_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/Makefile linux-libre-3.17-rc7-gnu/drivers/pcmcia/Makefile
--- linux-libre-3.16-gnu/drivers/pcmcia/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@ obj-$(CONFIG_PD6729)				+= pd6729.o
 obj-$(CONFIG_I82365)				+= i82365.o
 obj-$(CONFIG_I82092)				+= i82092.o
 obj-$(CONFIG_TCIC)				+= tcic.o
-obj-$(CONFIG_PCMCIA_M8XX)			+= m8xx_pcmcia.o
 obj-$(CONFIG_PCMCIA_SOC_COMMON)			+= soc_common.o
 obj-$(CONFIG_PCMCIA_SA11XX_BASE)		+= sa11xx_base.o
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa1100_cs.o
@@ -49,6 +48,7 @@ sa1100_cs-y					+= sa1100_generic.o
 sa1100_cs-$(CONFIG_SA1100_ASSABET)		+= sa1100_assabet.o
 sa1100_cs-$(CONFIG_SA1100_CERF)			+= sa1100_cerf.o
 sa1100_cs-$(CONFIG_SA1100_COLLIE)		+= pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_H3100)		+= sa1100_h3600.o
 sa1100_cs-$(CONFIG_SA1100_H3600)		+= sa1100_h3600.o
 sa1100_cs-$(CONFIG_SA1100_NANOENGINE)		+= sa1100_nanoengine.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)		+= sa1100_shannon.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/pd6729.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/pd6729.c
--- linux-libre-3.16-gnu/drivers/pcmcia/pd6729.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/pd6729.c	2014-09-28 17:29:07.000000000 -0400
@@ -764,7 +764,7 @@ static void pd6729_pci_remove(struct pci
 	kfree(socket);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(pd6729_pci_ids) = {
+static const struct pci_device_id pd6729_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) },
 	{ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/sa1111_jornada720.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/sa1111_jornada720.c
--- linux-libre-3.16-gnu/drivers/pcmcia/sa1111_jornada720.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/sa1111_jornada720.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
@@ -94,6 +95,7 @@ static struct pcmcia_low_level jornada72
 int pcmcia_jornada720_init(struct device *dev)
 {
 	int ret = -ENODEV;
+	struct sa1111_dev *sadev = SA1111_DEV(dev);
 
 	if (machine_is_jornada720()) {
 		unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
@@ -101,12 +103,12 @@ int pcmcia_jornada720_init(struct device
 		GRER |= 0x00000002;
 
 		/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
-		sa1111_set_io_dir(dev, pin, 0, 0);
-		sa1111_set_io(dev, pin, 0);
-		sa1111_set_sleep_io(dev, pin, 0);
+		sa1111_set_io_dir(sadev, pin, 0, 0);
+		sa1111_set_io(sadev, pin, 0);
+		sa1111_set_sleep_io(sadev, pin, 0);
 
 		sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
-		ret = sa1111_pcmcia_add(dev, &jornada720_pcmcia_ops,
+		ret = sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
 				sa11xx_drv_pcmcia_add_one);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/vrc4173_cardu.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/vrc4173_cardu.c
--- linux-libre-3.16-gnu/drivers/pcmcia/vrc4173_cardu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/vrc4173_cardu.c	2014-09-28 17:29:07.000000000 -0400
@@ -563,7 +563,7 @@ static int vrc4173_cardu_setup(char *opt
 
 __setup("vrc4173_cardu=", vrc4173_cardu_setup);
 
-static DEFINE_PCI_DEVICE_TABLE(vrc4173_cardu_id_table) = {
+static const struct pci_device_id vrc4173_cardu_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) },
         {0, }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pcmcia/yenta_socket.c linux-libre-3.17-rc7-gnu/drivers/pcmcia/yenta_socket.c
--- linux-libre-3.16-gnu/drivers/pcmcia/yenta_socket.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pcmcia/yenta_socket.c	2014-09-28 17:29:07.000000000 -0400
@@ -1352,7 +1352,7 @@ static const struct dev_pm_ops yenta_pm_
 		.driver_data	= CARDBUS_TYPE_##type,	\
 	}
 
-static DEFINE_PCI_DEVICE_TABLE(yenta_table) = {
+static const struct pci_device_id yenta_table[] = {
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI),
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/Kconfig linux-libre-3.17-rc7-gnu/drivers/phy/Kconfig
--- linux-libre-3.16-gnu/drivers/phy/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,13 @@ config GENERIC_PHY
 	  phy users can obtain reference to the PHY. All the users of this
 	  framework should select this config.
 
+config PHY_BERLIN_SATA
+	tristate "Marvell Berlin SATA PHY driver"
+	depends on ARCH_BERLIN && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
 config PHY_EXYNOS_MIPI_VIDEO
 	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
 	depends on HAS_IOMEM
@@ -27,9 +34,19 @@ config PHY_EXYNOS_MIPI_VIDEO
 
 config PHY_MVEBU_SATA
 	def_bool y
-	depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+	depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_MIPHY365X
+	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
+	depends on ARCH_STI
+	depends on HAS_IOMEM
 	depends on OF
 	select GENERIC_PHY
+	help
+	  Enable this to support the miphy transceiver (for SATA/PCIE)
+	  that is part of STMicroelectronics STiH41x SoC series.
 
 config OMAP_CONTROL_PHY
 	tristate "OMAP CONTROL PHY Driver"
@@ -109,6 +126,14 @@ config PHY_EXYNOS5250_SATA
 	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
 	  port to accept one SATA device.
 
+config PHY_HIX5HD2_SATA
+	tristate "HIX5HD2 SATA PHY Driver"
+	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Support for SATA PHY on Hisilicon hix5hd2 Soc.
+
 config PHY_SUN4I_USB
 	tristate "Allwinner sunxi SoC USB PHY driver"
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
@@ -124,55 +149,82 @@ config PHY_SUN4I_USB
 config PHY_SAMSUNG_USB2
 	tristate "Samsung USB 2.0 PHY driver"
 	depends on HAS_IOMEM
+	depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default ARCH_EXYNOS
 	help
 	  Enable this to support the Samsung USB 2.0 PHY driver for Samsung
-	  SoCs. This driver provides the interface for USB 2.0 PHY. Support for
-	  particular SoCs has to be enabled in addition to this driver. Number
-	  and type of supported phys depends on the SoC.
+	  SoCs. This driver provides the interface for USB 2.0 PHY. Support
+	  for particular PHYs will be enabled based on the SoC type in addition
+	  to this driver.
 
-config PHY_EXYNOS4210_USB2
-	bool "Support for Exynos 4210"
+config PHY_S5PV210_USB2
+	bool "Support for S5PV210"
 	depends on PHY_SAMSUNG_USB2
-	depends on CPU_EXYNOS4210
+	depends on ARCH_S5PV210
 	help
-	  Enable USB PHY support for Exynos 4210. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4210 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	  Enable USB PHY support for S5PV210. This option requires that Samsung
+	  USB 2.0 PHY driver is enabled and means that support for this
+	  particular SoC is compiled in the driver. In case of S5PV210 two phys
+	  are available - device and host.
+
+config PHY_EXYNOS4210_USB2
+	bool
+	depends on PHY_SAMSUNG_USB2
+	default CPU_EXYNOS4210
 
 config PHY_EXYNOS4X12_USB2
-	bool "Support for Exynos 4x12"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
-	help
-	  Enable USB PHY support for Exynos 4x12. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4x12 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
 
 config PHY_EXYNOS5250_USB2
-	bool "Support for Exynos 5250"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on SOC_EXYNOS5250
-	help
-	  Enable USB PHY support for Exynos 5250. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 5250 four
-	  phys are available - device, host, HSIC0 and HSIC.
+	default SOC_EXYNOS5250 || SOC_EXYNOS5420
 
 config PHY_EXYNOS5_USBDRD
 	tristate "Exynos5 SoC series USB DRD PHY driver"
 	depends on ARCH_EXYNOS5 && OF
 	depends on HAS_IOMEM
+	depends on USB_DWC3_EXYNOS
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default y
 	help
 	  Enable USB DRD PHY support for Exynos 5 SoC series.
 	  This driver provides PHY interface for USB 3.0 DRD controller
 	  present on Exynos5 SoC series.
 
+config PHY_QCOM_APQ8064_SATA
+	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_QCOM_IPQ806X_SATA
+	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_ST_SPEAR1310_MIPHY
+	tristate "ST SPEAR1310-MIPHY driver"
+	select GENERIC_PHY
+	depends on MACH_SPEAR1310 || COMPILE_TEST
+	help
+	  Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
+
+config PHY_ST_SPEAR1340_MIPHY
+	tristate "ST SPEAR1340-MIPHY driver"
+	select GENERIC_PHY
+	depends on MACH_SPEAR1340 || COMPILE_TEST
+	help
+	  Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
+
 config PHY_XGENE
 	tristate "APM X-Gene 15Gbps PHY support"
 	depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/Makefile linux-libre-3.17-rc7-gnu/drivers/phy/Makefile
--- linux-libre-3.16-gnu/drivers/phy/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,20 +3,28 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
 obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
+obj-$(CONFIG_PHY_MIPHY365X)		+= phy-miphy365x.o
 obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
 obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
 obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
 obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
 obj-$(CONFIG_PHY_SAMSUNG_USB2)		+= phy-exynos-usb2.o
 phy-exynos-usb2-y			+= phy-samsung-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2)	+= phy-exynos4210-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2)	+= phy-s5pv210-usb2.o
 obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
+obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
+obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-bcm-kona-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-bcm-kona-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-bcm-kona-usb2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-bcm-kona-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -117,7 +117,7 @@ static int bcm_kona_usb2_probe(struct pl
 
 	platform_set_drvdata(pdev, phy);
 
-	gphy = devm_phy_create(dev, &ops, NULL);
+	gphy = devm_phy_create(dev, NULL, &ops, NULL);
 	if (IS_ERR(gphy))
 		return PTR_ERR(gphy);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-berlin-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-berlin-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-berlin-sata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-berlin-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine TÃ©nart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR		0x0
+#define HOST_VSA_DATA		0x4
+#define PORT_SCR_CTL		0x2c
+#define PORT_VSR_ADDR		0x78
+#define PORT_VSR_DATA		0x7c
+
+#define CONTROL_REGISTER	0x0
+#define MBUS_SIZE_CONTROL	0x4
+
+#define POWER_DOWN_PHY0			BIT(6)
+#define POWER_DOWN_PHY1			BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
+
+#define PHY_BASE		0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25		BIT(0)
+#define PHY_MODE_SATA		(0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE	BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10	(0x0 << 10)
+#define DATA_BIT_WIDTH_20	(0x1 << 10)
+#define DATA_BIT_WIDTH_40	(0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5		(0x0 << 10)
+#define PHY_GEN_MAX_3_0		(0x1 << 10)
+#define PHY_GEN_MAX_6_0		(0x2 << 10)
+
+struct phy_berlin_desc {
+	struct phy	*phy;
+	u32		power_bit;
+	unsigned	index;
+};
+
+struct phy_berlin_priv {
+	void __iomem		*base;
+	spinlock_t		lock;
+	struct clk		*clk;
+	struct phy_berlin_desc	**phys;
+	unsigned		nphys;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
+					       u32 mask, u32 val)
+{
+	u32 regval;
+
+	/* select register */
+	writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+
+	/* set bits */
+	regval = readl(ctrl_reg + PORT_VSR_DATA);
+	regval &= ~mask;
+	regval |= val;
+	writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+	int ret = 0;
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power on PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval &= ~desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* Configure MBus */
+	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* set PHY mode and ref freq to 25 MHz */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
+				    REF_FREF_SEL_25 | PHY_MODE_SATA);
+
+	/* set PHY up to 6 Gbps */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+
+	/* set 40 bits width */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x23,  0xc00, DATA_BIT_WIDTH_40);
+
+	/* use max pll rate */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+
+	/* set Gen3 controller speed */
+	regval = readl(ctrl_reg + PORT_SCR_CTL);
+	regval &= ~GENMASK(7, 4);
+	regval |= 0x30;
+	writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return ret;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power down PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+					     struct of_phandle_args *args)
+{
+	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+	int i;
+
+	if (WARN_ON(args->args[0] >= priv->nphys))
+		return ERR_PTR(-ENODEV);
+
+	for (i = 0; i < priv->nphys; i++) {
+		if (priv->phys[i]->index == args->args[0])
+			break;
+	}
+
+	if (i == priv->nphys)
+		return ERR_PTR(-ENODEV);
+
+	return priv->phys[i]->phy;
+}
+
+static struct phy_ops phy_berlin_sata_ops = {
+	.power_on	= phy_berlin_sata_power_on,
+	.power_off	= phy_berlin_sata_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+	POWER_DOWN_PHY0,
+	POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	struct phy_berlin_priv *priv;
+	struct resource *res;
+	int i = 0;
+	u32 phy_id;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	priv->nphys = of_get_child_count(dev->of_node);
+	if (priv->nphys == 0)
+		return -ENODEV;
+
+	priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+				  GFP_KERNEL);
+	if (!priv->phys)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
+
+	for_each_available_child_of_node(dev->of_node, child) {
+		struct phy_berlin_desc *phy_desc;
+
+		if (of_property_read_u32(child, "reg", &phy_id)) {
+			dev_err(dev, "missing reg property in node %s\n",
+				child->name);
+			return -EINVAL;
+		}
+
+		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+			dev_err(dev, "invalid reg in node %s\n", child->name);
+			return -EINVAL;
+		}
+
+		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+		if (!phy_desc)
+			return -ENOMEM;
+
+		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY %d\n", phy_id);
+			return PTR_ERR(phy);
+		}
+
+		phy_desc->phy = phy;
+		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+		phy_desc->index = phy_id;
+		phy_set_drvdata(phy, phy_desc);
+
+		priv->phys[i++] = phy_desc;
+
+		/* Make sure the PHY is off */
+		phy_berlin_sata_power_off(phy);
+	}
+
+	phy_provider =
+		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin2q-sata-phy" },
+	{ },
+};
+
+static struct platform_driver phy_berlin_sata_driver = {
+	.probe	= phy_berlin_sata_probe,
+	.driver	= {
+		.name		= "phy-berlin-sata",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	},
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine TÃ©nart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-core.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-core.c
--- linux-libre-3.16-gnu/drivers/phy/phy-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/phy/phy.h>
 #include <linux/idr.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 static struct class *phy_class;
 static DEFINE_MUTEX(phy_provider_mutex);
@@ -86,10 +87,15 @@ static struct phy *phy_lookup(struct dev
 static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
 {
 	struct phy_provider *phy_provider;
+	struct device_node *child;
 
 	list_for_each_entry(phy_provider, &phy_provider_list, list) {
 		if (phy_provider->dev->of_node == node)
 			return phy_provider;
+
+		for_each_child_of_node(phy_provider->dev->of_node, child)
+			if (child == node)
+				return phy_provider;
 	}
 
 	return ERR_PTR(-EPROBE_DEFER);
@@ -226,6 +232,12 @@ int phy_power_on(struct phy *phy)
 	if (!phy)
 		return 0;
 
+	if (phy->pwr) {
+		ret = regulator_enable(phy->pwr);
+		if (ret)
+			return ret;
+	}
+
 	ret = phy_pm_runtime_get_sync(phy);
 	if (ret < 0 && ret != -ENOTSUPP)
 		return ret;
@@ -247,6 +259,8 @@ int phy_power_on(struct phy *phy)
 out:
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put_sync(phy);
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
 
 	return ret;
 }
@@ -272,6 +286,9 @@ int phy_power_off(struct phy *phy)
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put(phy);
 
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(phy_power_off);
@@ -398,13 +415,20 @@ struct phy *of_phy_simple_xlate(struct d
 	struct phy *phy;
 	struct class_dev_iter iter;
 	struct device_node *node = dev->of_node;
+	struct device_node *child;
 
 	class_dev_iter_init(&iter, phy_class, NULL, NULL);
 	while ((dev = class_dev_iter_next(&iter))) {
 		phy = to_phy(dev);
-		if (node != phy->dev.of_node)
+		if (node != phy->dev.of_node) {
+			for_each_child_of_node(node, child) {
+				if (child == phy->dev.of_node)
+					goto phy_found;
+			}
 			continue;
+		}
 
+phy_found:
 		class_dev_iter_exit(&iter);
 		return phy;
 	}
@@ -562,13 +586,15 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
 /**
  * phy_create() - create a new phy
  * @dev: device that is creating the new phy
+ * @node: device node of the phy
  * @ops: function pointers for performing phy operations
  * @init_data: contains the list of PHY consumers or NULL
  *
  * Called to create a phy using phy framework.
  */
-struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data)
 {
 	int ret;
 	int id;
@@ -588,12 +614,22 @@ struct phy *phy_create(struct device *de
 		goto free_phy;
 	}
 
+	/* phy-supply */
+	phy->pwr = regulator_get_optional(dev, "phy");
+	if (IS_ERR(phy->pwr)) {
+		if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto free_ida;
+		}
+		phy->pwr = NULL;
+	}
+
 	device_initialize(&phy->dev);
 	mutex_init(&phy->mutex);
 
 	phy->dev.class = phy_class;
 	phy->dev.parent = dev;
-	phy->dev.of_node = dev->of_node;
+	phy->dev.of_node = node ?: dev->of_node;
 	phy->id = id;
 	phy->ops = ops;
 	phy->init_data = init_data;
@@ -617,6 +653,9 @@ put_dev:
 	put_device(&phy->dev);  /* calls phy_release() which frees resources */
 	return ERR_PTR(ret);
 
+free_ida:
+	ida_simple_remove(&phy_ida, phy->id);
+
 free_phy:
 	kfree(phy);
 	return ERR_PTR(ret);
@@ -626,6 +665,7 @@ EXPORT_SYMBOL_GPL(phy_create);
 /**
  * devm_phy_create() - create a new phy
  * @dev: device that is creating the new phy
+ * @node: device node of the phy
  * @ops: function pointers for performing phy operations
  * @init_data: contains the list of PHY consumers or NULL
  *
@@ -634,8 +674,9 @@ EXPORT_SYMBOL_GPL(phy_create);
  * On driver detach, release function is invoked on the devres data,
  * then, devres data is freed.
  */
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+			    const struct phy_ops *ops,
+			    struct phy_init_data *init_data)
 {
 	struct phy **ptr, *phy;
 
@@ -643,7 +684,7 @@ struct phy *devm_phy_create(struct devic
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	phy = phy_create(dev, ops, init_data);
+	phy = phy_create(dev, node, ops, init_data);
 	if (!IS_ERR(phy)) {
 		*ptr = phy;
 		devres_add(dev, ptr);
@@ -800,6 +841,7 @@ static void phy_release(struct device *d
 
 	phy = to_phy(dev);
 	dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+	regulator_put(phy->pwr);
 	ida_simple_remove(&phy_ida, phy->id);
 	kfree(phy);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos4x12-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos4x12-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos4x12-usb2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos4x12-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,6 +67,8 @@
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ	(0x5 << 0)
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ	(0x7 << 0)
 
+#define EXYNOS_3250_UPHYCLK_REFCLKSEL		(0x2 << 8)
+
 #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP	BIT(3)
 #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON	BIT(4)
 #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON	BIT(7)
@@ -86,13 +88,23 @@
 #define EXYNOS_4x12_URSTCON_OTG_HLINK		BIT(1)
 #define EXYNOS_4x12_URSTCON_OTG_PHYLINK		BIT(2)
 #define EXYNOS_4x12_URSTCON_HOST_PHY		BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
 #define EXYNOS_4x12_URSTCON_PHY1		BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0		BIT(5)
-#define EXYNOS_4x12_URSTCON_HSIC1		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC0		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1		BIT(5)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL	BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(10)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_P1	BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(8)
 
 /* Isolation, configured in the power management unit */
 #define EXYNOS_4x12_USB_ISOL_OFFSET		0x704
@@ -187,7 +199,12 @@ static void exynos4x12_setup_clk(struct
 
 	clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 	clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+
+	if (drv->cfg->has_refclk_sel)
+		clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
+
 	clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+	clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
 	writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 }
 
@@ -198,27 +215,22 @@ static void exynos4x12_phy_pwr(struct sa
 	u32 phypwr = 0;
 	u32 rst;
 	u32 pwr;
-	u32 mode = 0;
-	u32 switch_mode = 0;
 
 	switch (inst->cfg->id) {
 	case EXYNOS4x12_DEVICE:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY0;
 		rstbits =	EXYNOS_4x12_URSTCON_PHY0;
-		mode =		EXYNOS_4x12_MODE_SWITCH_DEVICE;
-		switch_mode =	1;
 		break;
 	case EXYNOS4x12_HOST:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY1;
-		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY;
-		mode =		EXYNOS_4x12_MODE_SWITCH_HOST;
-		switch_mode =	1;
+		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY |
+				EXYNOS_4x12_URSTCON_PHY1 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P0;
 		break;
 	case EXYNOS4x12_HSIC0:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC0;
-		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
-				EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
-				EXYNOS_4x12_URSTCON_HOST_PHY;
+		rstbits =	EXYNOS_4x12_URSTCON_HSIC0 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
 		break;
 	case EXYNOS4x12_HSIC1:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC1;
@@ -228,11 +240,6 @@ static void exynos4x12_phy_pwr(struct sa
 	};
 
 	if (on) {
-		if (switch_mode)
-			regmap_update_bits(drv->reg_sys,
-					   EXYNOS_4x12_MODE_SWITCH_OFFSET,
-					   EXYNOS_4x12_MODE_SWITCH_MASK, mode);
-
 		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 		pwr &= ~phypwr;
 		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
@@ -253,41 +260,78 @@ static void exynos4x12_phy_pwr(struct sa
 	}
 }
 
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
+	if (inst->int_cnt++ > 0)
+		return;
 
-	inst->enabled = 1;
 	exynos4x12_setup_clk(inst);
-	exynos4x12_phy_pwr(inst, 1);
 	exynos4x12_isol(inst, 0);
+	exynos4x12_phy_pwr(inst, 1);
+}
 
-	/* Power on the device, as it is necessary for HSIC to work */
-	if (inst->cfg->id == EXYNOS4x12_HSIC0) {
-		struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
-		exynos4x12_phy_pwr(device, 1);
-		exynos4x12_isol(device, 0);
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt++ > 0)
+		return 0;
+
+	if (inst->cfg->id == EXYNOS4x12_HOST) {
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 	}
 
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_DEVICE);
+
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
+	}
+
+	exynos4x12_power_on_int(inst);
+
 	return 0;
 }
 
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
-	struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
+	if (inst->int_cnt-- > 1)
+		return;
 
-	inst->enabled = 0;
 	exynos4x12_isol(inst, 1);
 	exynos4x12_phy_pwr(inst, 0);
+}
 
-	if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
-		exynos4x12_isol(device, 1);
-		exynos4x12_phy_pwr(device, 0);
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt-- > 1)
+		return 0;
+
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+
+	if (inst->cfg->id == EXYNOS4x12_HOST)
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
 	}
 
+	exynos4x12_power_off_int(inst);
+
 	return 0;
 }
 
@@ -320,6 +364,13 @@ static const struct samsung_usb2_common_
 	{},
 };
 
+const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
+	.has_refclk_sel		= 1,
+	.num_phys		= 1,
+	.phys			= exynos4x12_phys,
+	.rate_to_clk		= exynos4x12_rate_to_clk,
+};
+
 const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
 	.has_mode_switch	= 1,
 	.num_phys		= EXYNOS4x12_NUM_PHYS,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos5250-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5250-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos5250-sata.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5250-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -210,7 +210,7 @@ static int exynos_sata_phy_probe(struct
 		return ret;
 	}
 
-	sata_phy->phy = devm_phy_create(dev, &exynos_sata_phy_ops, NULL);
+	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
 	if (IS_ERR(sata_phy->phy)) {
 		clk_disable_unprepare(sata_phy->phyclk);
 		dev_err(dev, "failed to create PHY\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos5250-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5250-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos5250-usb2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5250-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -318,7 +318,6 @@ static int exynos5250_power_on(struct sa
 
 		break;
 	}
-	inst->enabled = 1;
 	exynos5250_isol(inst, 0);
 
 	return 0;
@@ -331,7 +330,6 @@ static int exynos5250_power_off(struct s
 	u32 otg;
 	u32 hsic;
 
-	inst->enabled = 0;
 	exynos5250_isol(inst, 1);
 
 	switch (inst->cfg->id) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos5-usbdrd.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5-usbdrd.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos5-usbdrd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos5-usbdrd.c	2014-09-28 17:29:07.000000000 -0400
@@ -506,7 +506,7 @@ static struct phy_ops exynos5_usbdrd_phy
 	.owner		= THIS_MODULE,
 };
 
-const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
 		.phy_isol	= exynos5_usbdrd_phy_isol,
@@ -521,13 +521,13 @@ const struct exynos5_usbdrd_phy_config p
 	},
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 };
@@ -542,6 +542,7 @@ static const struct of_device_id exynos5
 	},
 	{ },
 };
+MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
 
 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 {
@@ -635,7 +636,8 @@ static int exynos5_usbdrd_phy_probe(stru
 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
 
 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops,
+		struct phy *phy = devm_phy_create(dev, NULL,
+						  &exynos5_usbdrd_phy_ops,
 						  NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos-dp-video.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos-dp-video.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos-dp-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos-dp-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -76,7 +77,7 @@ static int exynos_dp_video_phy_probe(str
 	if (IS_ERR(state->regs))
 		return PTR_ERR(state->regs);
 
-	phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create Display Port PHY\n");
 		return PTR_ERR(phy);
@@ -84,10 +85,8 @@ static int exynos_dp_video_phy_probe(str
 	phy_set_drvdata(phy, state);
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id exynos_dp_video_phy_of_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-exynos-mipi-video.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos-mipi-video.c
--- linux-libre-3.16-gnu/drivers/phy/phy-exynos-mipi-video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-exynos-mipi-video.c	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -135,7 +136,7 @@ static int exynos_mipi_video_phy_probe(s
 	spin_lock_init(&state->slock);
 
 	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev,
+		struct phy *phy = devm_phy_create(dev, NULL,
 					&exynos_mipi_video_phy_ops, NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
@@ -149,10 +150,8 @@ static int exynos_mipi_video_phy_probe(s
 
 	phy_provider = devm_of_phy_provider_register(dev,
 					exynos_mipi_video_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-hix5hd2-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-hix5hd2-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-hix5hd2-sata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-hix5hd2-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014 Linaro Ltd.
+ * Copyright (c) 2014 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SATA_PHY0_CTLL		0xa0
+#define MPLL_MULTIPLIER_SHIFT	1
+#define MPLL_MULTIPLIER_MASK	0xfe
+#define MPLL_MULTIPLIER_50M	0x3c
+#define MPLL_MULTIPLIER_100M	0x1e
+#define PHY_RESET		BIT(0)
+#define REF_SSP_EN		BIT(9)
+#define SSC_EN			BIT(10)
+#define REF_USE_PAD		BIT(23)
+
+#define SATA_PORT_PHYCTL	0x174
+#define SPEED_MODE_MASK		0x6f0000
+#define HALF_RATE_SHIFT		16
+#define PHY_CONFIG_SHIFT	18
+#define GEN2_EN_SHIFT		21
+#define SPEED_CTRL		BIT(20)
+
+#define SATA_PORT_PHYCTL1	0x148
+#define AMPLITUDE_MASK		0x3ffffe
+#define AMPLITUDE_GEN3		0x68
+#define AMPLITUDE_GEN3_SHIFT	15
+#define AMPLITUDE_GEN2		0x56
+#define AMPLITUDE_GEN2_SHIFT	8
+#define AMPLITUDE_GEN1		0x56
+#define AMPLITUDE_GEN1_SHIFT	1
+
+#define SATA_PORT_PHYCTL2	0x14c
+#define PREEMPH_MASK		0x3ffff
+#define PREEMPH_GEN3		0x20
+#define PREEMPH_GEN3_SHIFT	12
+#define PREEMPH_GEN2		0x15
+#define PREEMPH_GEN2_SHIFT	6
+#define PREEMPH_GEN1		0x5
+#define PREEMPH_GEN1_SHIFT	0
+
+struct hix5hd2_priv {
+	void __iomem	*base;
+	struct regmap	*peri_ctrl;
+};
+
+enum phy_speed_mode {
+	SPEED_MODE_GEN1 = 0,
+	SPEED_MODE_GEN2 = 1,
+	SPEED_MODE_GEN3 = 2,
+};
+
+static int hix5hd2_sata_phy_init(struct phy *phy)
+{
+	struct hix5hd2_priv *priv = phy_get_drvdata(phy);
+	u32 val, data[2];
+	int ret;
+
+	if (priv->peri_ctrl) {
+		ret = of_property_read_u32_array(phy->dev.of_node,
+						 "hisilicon,power-reg",
+						 &data[0], 2);
+		if (ret) {
+			dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
+			return ret;
+		}
+
+		regmap_update_bits(priv->peri_ctrl, data[0],
+				   BIT(data[1]), BIT(data[1]));
+	}
+
+	/* reset phy */
+	val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
+	val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
+	val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
+	       REF_SSP_EN | PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+	msleep(20);
+	val &= ~PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
+	val &= ~AMPLITUDE_MASK;
+	val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
+	       AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
+	       AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
+	val &= ~PREEMPH_MASK;
+	val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
+	       PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
+	       PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
+
+	/* ensure PHYCTRL setting takes effect */
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	msleep(20);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
+	val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	return 0;
+}
+
+static struct phy_ops hix5hd2_sata_phy_ops = {
+	.init		= hix5hd2_sata_phy_init,
+	.owner		= THIS_MODULE,
+};
+
+static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy *phy;
+	struct hix5hd2_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,peripheral-syscon");
+	if (IS_ERR(priv->peri_ctrl))
+		priv->peri_ctrl = NULL;
+
+	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	phy_set_drvdata(phy, priv);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
+	{.compatible = "hisilicon,hix5hd2-sata-phy",},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
+
+static struct platform_driver hix5hd2_sata_phy_driver = {
+	.probe	= hix5hd2_sata_phy_probe,
+	.driver = {
+		.name	= "hix5hd2-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= hix5hd2_sata_phy_of_match,
+	}
+};
+module_platform_driver(hix5hd2_sata_phy_driver);
+
+MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
+MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
+MODULE_ALIAS("platform:hix5hd2-sata-phy");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-miphy365x.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-miphy365x.c
--- linux-libre-3.16-gnu/drivers/phy/phy-miphy365x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-miphy365x.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics â€“ All Rights Reserved
+ *
+ * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
+ *
+ * Authors: Alexandre Torgue <alexandre.torgue@st.com>
+ *          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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+#define HFC_TIMEOUT		100
+
+#define SYSCFG_SELECT_SATA_MASK	BIT(1)
+#define SYSCFG_SELECT_SATA_POS	1
+
+/* MiPHY365x register definitions */
+#define RESET_REG		0x00
+#define RST_PLL			BIT(1)
+#define RST_PLL_CAL		BIT(2)
+#define RST_RX			BIT(4)
+#define RST_MACRO		BIT(7)
+
+#define STATUS_REG		0x01
+#define IDLL_RDY		BIT(0)
+#define PLL_RDY			BIT(1)
+#define DES_BIT_LOCK		BIT(2)
+#define DES_SYMBOL_LOCK		BIT(3)
+
+#define CTRL_REG		0x02
+#define TERM_EN			BIT(0)
+#define PCI_EN			BIT(2)
+#define DES_BIT_LOCK_EN		BIT(3)
+#define TX_POL			BIT(5)
+
+#define INT_CTRL_REG		0x03
+
+#define BOUNDARY1_REG		0x10
+#define SPDSEL_SEL		BIT(0)
+
+#define BOUNDARY3_REG		0x12
+#define TX_SPDSEL_GEN1_VAL	0
+#define TX_SPDSEL_GEN2_VAL	0x01
+#define TX_SPDSEL_GEN3_VAL	0x02
+#define RX_SPDSEL_GEN1_VAL	0
+#define RX_SPDSEL_GEN2_VAL	(0x01 << 3)
+#define RX_SPDSEL_GEN3_VAL	(0x02 << 3)
+
+#define PCIE_REG		0x16
+
+#define BUF_SEL_REG		0x20
+#define CONF_GEN_SEL_GEN3	0x02
+#define CONF_GEN_SEL_GEN2	0x01
+#define PD_VDDTFILTER		BIT(4)
+
+#define TXBUF1_REG		0x21
+#define SWING_VAL		0x04
+#define SWING_VAL_GEN1		0x03
+#define PREEMPH_VAL		(0x3 << 5)
+
+#define TXBUF2_REG		0x22
+#define TXSLEW_VAL		0x2
+#define TXSLEW_VAL_GEN1		0x4
+
+#define RXBUF_OFFSET_CTRL_REG	0x23
+
+#define RXBUF_REG		0x25
+#define SDTHRES_VAL		0x01
+#define EQ_ON3			(0x03 << 4)
+#define EQ_ON1			(0x01 << 4)
+
+#define COMP_CTRL1_REG		0x40
+#define START_COMSR		BIT(0)
+#define START_COMZC		BIT(1)
+#define COMSR_DONE		BIT(2)
+#define COMZC_DONE		BIT(3)
+#define COMP_AUTO_LOAD		BIT(4)
+
+#define COMP_CTRL2_REG		0x41
+#define COMP_2MHZ_RAT_GEN1	0x1e
+#define COMP_2MHZ_RAT		0xf
+
+#define COMP_CTRL3_REG		0x42
+#define COMSR_COMP_REF		0x33
+
+#define COMP_IDLL_REG		0x47
+#define COMZC_IDLL		0x2a
+
+#define PLL_CTRL1_REG		0x50
+#define PLL_START_CAL		BIT(0)
+#define BUF_EN			BIT(2)
+#define SYNCHRO_TX		BIT(3)
+#define SSC_EN			BIT(6)
+#define CONFIG_PLL		BIT(7)
+
+#define PLL_CTRL2_REG		0x51
+#define BYPASS_PLL_CAL		BIT(1)
+
+#define PLL_RAT_REG		0x52
+
+#define PLL_SSC_STEP_MSB_REG	0x56
+#define PLL_SSC_STEP_MSB_VAL	0x03
+
+#define PLL_SSC_STEP_LSB_REG	0x57
+#define PLL_SSC_STEP_LSB_VAL	0x63
+
+#define PLL_SSC_PER_MSB_REG	0x58
+#define PLL_SSC_PER_MSB_VAL	0
+
+#define PLL_SSC_PER_LSB_REG	0x59
+#define PLL_SSC_PER_LSB_VAL	0xf1
+
+#define IDLL_TEST_REG		0x72
+#define START_CLK_HF		BIT(6)
+
+#define DES_BITLOCK_REG		0x86
+#define BIT_LOCK_LEVEL		0x01
+#define BIT_LOCK_CNT_512	(0x03 << 5)
+
+struct miphy365x_phy {
+	struct phy *phy;
+	void __iomem *base;
+	bool pcie_tx_pol_inv;
+	bool sata_tx_pol_inv;
+	u32 sata_gen;
+	u64 ctrlreg;
+	u8 type;
+};
+
+struct miphy365x_dev {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex miphy_mutex;
+	struct miphy365x_phy **phys;
+};
+
+/*
+ * These values are represented in Device tree. They are considered to be ABI
+ * and although they can be extended any existing values must not change.
+ */
+enum miphy_sata_gen {
+	SATA_GEN1 = 1,
+	SATA_GEN2,
+	SATA_GEN3
+};
+
+static u8 rx_tx_spd[] = {
+	0, /* GEN0 doesn't exist. */
+	TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
+	TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
+	TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
+};
+
+/*
+ * This function selects the system configuration,
+ * either two SATA, one SATA and one PCIe, or two PCIe lanes.
+ */
+static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
+			      struct miphy365x_dev *miphy_dev)
+{
+	bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
+
+	return regmap_update_bits(miphy_dev->regmap,
+				  (unsigned int)miphy_phy->ctrlreg,
+				  SYSCFG_SELECT_SATA_MASK,
+				  sata << SYSCFG_SELECT_SATA_POS);
+}
+
+static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	if (miphy_phy->pcie_tx_pol_inv) {
+		/* Invert Tx polarity and clear pci_txdetect_pol bit */
+		val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
+		writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+		writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
+	}
+
+	return 0;
+}
+
+static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
+					struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if (!(regval & mask))
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "HFC ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
+				struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if ((regval & mask) == mask)
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
+				      struct miphy365x_dev *miphy_dev)
+{
+	u8 val, mask;
+
+	if (miphy_phy->sata_gen == SATA_GEN1)
+		writeb_relaxed(COMP_2MHZ_RAT_GEN1,
+			       miphy_phy->base + COMP_CTRL2_REG);
+	else
+		writeb_relaxed(COMP_2MHZ_RAT,
+			       miphy_phy->base + COMP_CTRL2_REG);
+
+	if (miphy_phy->sata_gen != SATA_GEN3) {
+		writeb_relaxed(COMSR_COMP_REF,
+			       miphy_phy->base + COMP_CTRL3_REG);
+		/*
+		 * Force VCO current to value defined by address 0x5A
+		 * and disable PCIe100Mref bit
+		 * Enable auto load compensation for pll_i_bias
+		 */
+		writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
+		writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
+	}
+
+	/*
+	 * Force restart compensation and enable auto load
+	 * for Comzc_Tx, Comzc_Rx and Comsr on macro
+	 */
+	val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
+	writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
+
+	mask = COMSR_DONE | COMZC_DONE;
+	while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask)	!= mask)
+		cpu_relax();
+}
+
+static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
+				     struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	/*
+	 * SSC Settings. SSC will be enabled through Link
+	 * SSC Ampl. = 0.4%
+	 * SSC Freq = 31KHz
+	 */
+	writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_MSB_REG);
+	writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_LSB_REG);
+	writeb_relaxed(PLL_SSC_PER_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_MSB_REG);
+	writeb_relaxed(PLL_SSC_PER_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_LSB_REG);
+
+	/* SSC Settings complete */
+	if (miphy_phy->sata_gen == SATA_GEN1) {
+		val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	} else {
+		val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	}
+}
+
+static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	int ret;
+	u8 val;
+
+	/*
+	 * Force PHY macro reset, PLL calibration reset, PLL reset
+	 * and assert Deserializer Reset
+	 */
+	val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
+	writeb_relaxed(val, miphy_phy->base + RESET_REG);
+
+	if (miphy_phy->sata_tx_pol_inv)
+		writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
+
+	/*
+	 * Force macro1 to use rx_lspd, tx_lspd
+	 * Force Rx_Clock on first I-DLL phase
+	 * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
+	 */
+	writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
+	val = rx_tx_spd[miphy_phy->sata_gen];
+	writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
+
+	/* Wait for HFC_READY = 0 */
+	ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/* Compensation Recalibration */
+	miphy365x_set_comp(miphy_phy, miphy_dev);
+
+	switch (miphy_phy->sata_gen) {
+	case SATA_GEN3:
+		/*
+		 * TX Swing target 550-600mv peak to peak diff
+		 * Tx Slew target 90-110ps rising/falling time
+		 * Rx Eq ON3, Sigdet threshold SDTH1
+		 */
+		val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
+		writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
+		val = SWING_VAL | PREEMPH_VAL;
+		writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
+		val = SDTHRES_VAL | EQ_ON3;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN2:
+		/*
+		 * conf gen sel=0x1 to program Gen2 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 550-600mV peak-to-peak diff
+		 * Tx Slew target 90-110 ps rising/falling time
+		 * RX Equalization ON1, Sigdet threshold SDTH1
+		 */
+		writeb_relaxed(CONF_GEN_SEL_GEN2,
+			       miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		val = SDTHRES_VAL | EQ_ON1;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN1:
+		/*
+		 * conf gen sel = 00b to program Gen1 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 500-550mV peak-to-peak diff
+		 * Tx Slew target120-140 ps rising/falling time
+		 */
+		writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL_GEN1,	miphy_phy->base + TXBUF2_REG);
+		break;
+	default:
+		break;
+	}
+
+	/* Force Macro1 in partial mode & release pll cal reset */
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	usleep_range(100, 150);
+
+	miphy365x_set_ssc(miphy_phy, miphy_dev);
+
+	/* Wait for phy_ready */
+	ret = miphy365x_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Enable macro1 to use rx_lspd & tx_lspd
+	 * Release Rx_Clock on first I-DLL phase on macro1
+	 * Assert deserializer reset
+	 * des_bit_lock_en is set
+	 * bit lock detection strength
+	 * Deassert deserializer reset
+	 */
+	writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	val = miphy_phy->sata_tx_pol_inv ?
+		(TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
+	writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+
+	val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
+	writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
+	writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
+
+	return 0;
+}
+
+static int miphy365x_init(struct phy *phy)
+{
+	struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
+	int ret = 0;
+
+	mutex_lock(&miphy_dev->miphy_mutex);
+
+	ret = miphy365x_set_path(miphy_phy, miphy_dev);
+	if (ret) {
+		mutex_unlock(&miphy_dev->miphy_mutex);
+		return ret;
+	}
+
+	/* Initialise Miphy for PCIe or SATA */
+	if (miphy_phy->type == MIPHY_TYPE_PCIE)
+		ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
+	else
+		ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
+
+	mutex_unlock(&miphy_dev->miphy_mutex);
+
+	return ret;
+}
+
+int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
+		       int index)
+{
+	struct device_node *phynode = miphy_phy->phy->dev.of_node;
+	const char *name;
+	const __be32 *taddr;
+	int type = miphy_phy->type;
+	int ret;
+
+	ret = of_property_read_string_index(phynode, "reg-names", index, &name);
+	if (ret) {
+		dev_err(dev, "no reg-names property not found\n");
+		return ret;
+	}
+
+	if (!strncmp(name, "syscfg", 6)) {
+		taddr = of_get_address(phynode, index, NULL, NULL);
+		if (!taddr) {
+			dev_err(dev, "failed to fetch syscfg address\n");
+			return -EINVAL;
+		}
+
+		miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
+		if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
+			dev_err(dev, "failed to translate syscfg address\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
+	      (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
+		return 0;
+
+	miphy_phy->base = of_iomap(phynode, index);
+	if (!miphy_phy->base) {
+		dev_err(dev, "Failed to map %s\n", phynode->full_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct phy *miphy365x_xlate(struct device *dev,
+				   struct of_phandle_args *args)
+{
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
+	struct miphy365x_phy *miphy_phy = NULL;
+	struct device_node *phynode = args->np;
+	int ret, index;
+
+	if (!of_device_is_available(phynode)) {
+		dev_warn(dev, "Requested PHY is disabled\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (args->args_count != 1) {
+		dev_err(dev, "Invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < of_get_child_count(dev->of_node); index++)
+		if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
+			miphy_phy = miphy_dev->phys[index];
+			break;
+		}
+
+	if (!miphy_phy) {
+		dev_err(dev, "Failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	miphy_phy->type = args->args[0];
+
+	if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
+	      miphy_phy->type == MIPHY_TYPE_PCIE)) {
+		dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Each port handles SATA and PCIE - third entry is always sysconf. */
+	for (index = 0; index < 3; index++) {
+		ret = miphy365x_get_addr(dev, miphy_phy, index);
+		if (ret < 0)
+			return ERR_PTR(ret);
+	}
+
+	return miphy_phy->phy;
+}
+
+static struct phy_ops miphy365x_ops = {
+	.init		= miphy365x_init,
+	.owner		= THIS_MODULE,
+};
+
+static int miphy365x_of_probe(struct device_node *phynode,
+			      struct miphy365x_phy *miphy_phy)
+{
+	of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
+	if (!miphy_phy->sata_gen)
+		miphy_phy->sata_gen = SATA_GEN1;
+
+	miphy_phy->pcie_tx_pol_inv =
+		of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
+
+	miphy_phy->sata_tx_pol_inv =
+		of_property_read_bool(phynode, "st,sata-tx-pol-inv");
+
+	return 0;
+}
+
+static int miphy365x_probe(struct platform_device *pdev)
+{
+	struct device_node *child, *np = pdev->dev.of_node;
+	struct miphy365x_dev *miphy_dev;
+	struct phy_provider *provider;
+	struct phy *phy;
+	int chancount, port = 0;
+	int ret;
+
+	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+	if (!miphy_dev)
+		return -ENOMEM;
+
+	chancount = of_get_child_count(np);
+	miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
+				       GFP_KERNEL);
+	if (!miphy_dev->phys)
+		return -ENOMEM;
+
+	miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (IS_ERR(miphy_dev->regmap)) {
+		dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
+		return PTR_ERR(miphy_dev->regmap);
+	}
+
+	miphy_dev->dev = &pdev->dev;
+
+	dev_set_drvdata(&pdev->dev, miphy_dev);
+
+	mutex_init(&miphy_dev->miphy_mutex);
+
+	for_each_child_of_node(np, child) {
+		struct miphy365x_phy *miphy_phy;
+
+		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+					 GFP_KERNEL);
+		if (!miphy_phy)
+			return -ENOMEM;
+
+		miphy_dev->phys[port] = miphy_phy;
+
+		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(&pdev->dev, "failed to create PHY\n");
+			return PTR_ERR(phy);
+		}
+
+		miphy_dev->phys[port]->phy = phy;
+
+		ret = miphy365x_of_probe(child, miphy_phy);
+		if (ret)
+			return ret;
+
+		phy_set_drvdata(phy, miphy_dev->phys[port]);
+		port++;
+	}
+
+	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
+	if (IS_ERR(provider))
+		return PTR_ERR(provider);
+
+	return 0;
+}
+
+static const struct of_device_id miphy365x_of_match[] = {
+	{ .compatible = "st,miphy365x-phy", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, miphy365x_of_match);
+
+static struct platform_driver miphy365x_driver = {
+	.probe	= miphy365x_probe,
+	.driver = {
+		.name	= "miphy365x-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= miphy365x_of_match,
+	}
+};
+module_platform_driver(miphy365x_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-mvebu-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-mvebu-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-mvebu-sata.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-mvebu-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@ static int phy_mvebu_sata_probe(struct p
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
-	phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
 	if (IS_ERR(phy))
 		return PTR_ERR(phy);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-omap-control.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-omap-control.c
--- linux-libre-3.16-gnu/drivers/phy/phy-omap-control.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-omap-control.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,41 @@
 #include <linux/phy/omap_control_phy.h>
 
 /**
+ * omap_control_pcie_pcs - set the PCS delay count
+ * @dev: the control module device
+ * @id: index of the pcie PHY (should be 1 or 2)
+ * @delay: 8 bit delay value
+ */
+void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
+{
+	u32 val;
+	struct omap_control_phy	*control_phy;
+
+	if (IS_ERR(dev) || !dev) {
+		pr_err("%s: invalid device\n", __func__);
+		return;
+	}
+
+	control_phy = dev_get_drvdata(dev);
+	if (!control_phy) {
+		dev_err(dev, "%s: invalid control phy device\n", __func__);
+		return;
+	}
+
+	if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
+		dev_err(dev, "%s: unsupported operation\n", __func__);
+		return;
+	}
+
+	val = readl(control_phy->pcie_pcs);
+	val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
+		(id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
+	val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+	writel(val, control_phy->pcie_pcs);
+}
+EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
+
+/**
  * omap_control_phy_power - power on/off the phy using control module reg
  * @dev: the control module device
  * @on: 0 or 1, based on powering on or off the PHY
@@ -61,6 +96,7 @@ void omap_control_phy_power(struct devic
 			val |= OMAP_CTRL_DEV_PHY_PD;
 		break;
 
+	case OMAP_CTRL_TYPE_PCIE:
 	case OMAP_CTRL_TYPE_PIPE3:
 		rate = clk_get_rate(control_phy->sys_clk);
 		rate = rate/1000000;
@@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_m
 static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
 static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
 static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
 static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
 static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
 
@@ -228,6 +265,10 @@ static const struct of_device_id omap_co
 		.data = &pipe3_data,
 	},
 	{
+		.compatible = "ti,control-phy-pcie",
+		.data = &pcie_data,
+	},
+	{
 		.compatible = "ti,control-phy-usb2-dra7",
 		.data = &dra7usb2_data,
 	},
@@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct
 		}
 	}
 
-	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) {
+	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
+	    control_phy->type == OMAP_CTRL_TYPE_PCIE) {
 		control_phy->sys_clk = devm_clk_get(control_phy->dev,
 			"sys_clkin");
 		if (IS_ERR(control_phy->sys_clk)) {
@@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct
 		}
 	}
 
+	if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pcie_pcs");
+		control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(control_phy->pcie_pcs))
+			return PTR_ERR(control_phy->pcie_pcs);
+	}
+
 	dev_set_drvdata(control_phy->dev, control_phy);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-omap-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-omap-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-omap-usb2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-omap-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -263,7 +263,7 @@ static int omap_usb2_probe(struct platfo
 
 	platform_set_drvdata(pdev, phy);
 
-	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-qcom-apq8064-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-qcom-apq8064-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-qcom-apq8064-sata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-qcom-apq8064-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2014, 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/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* PHY registers */
+#define UNIPHY_PLL_REFCLK_CFG		0x000
+#define UNIPHY_PLL_PWRGEN_CFG		0x014
+#define UNIPHY_PLL_GLB_CFG		0x020
+#define UNIPHY_PLL_SDM_CFG0		0x038
+#define UNIPHY_PLL_SDM_CFG1		0x03C
+#define UNIPHY_PLL_SDM_CFG2		0x040
+#define UNIPHY_PLL_SDM_CFG3		0x044
+#define UNIPHY_PLL_SDM_CFG4		0x048
+#define UNIPHY_PLL_SSC_CFG0		0x04C
+#define UNIPHY_PLL_SSC_CFG1		0x050
+#define UNIPHY_PLL_SSC_CFG2		0x054
+#define UNIPHY_PLL_SSC_CFG3		0x058
+#define UNIPHY_PLL_LKDET_CFG0		0x05C
+#define UNIPHY_PLL_LKDET_CFG1		0x060
+#define UNIPHY_PLL_LKDET_CFG2		0x064
+#define UNIPHY_PLL_CAL_CFG0		0x06C
+#define UNIPHY_PLL_CAL_CFG8		0x08C
+#define UNIPHY_PLL_CAL_CFG9		0x090
+#define UNIPHY_PLL_CAL_CFG10		0x094
+#define UNIPHY_PLL_CAL_CFG11		0x098
+#define UNIPHY_PLL_STATUS		0x0C0
+
+#define SATA_PHY_SER_CTRL		0x100
+#define SATA_PHY_TX_DRIV_CTRL0		0x104
+#define SATA_PHY_TX_DRIV_CTRL1		0x108
+#define SATA_PHY_TX_IMCAL0		0x11C
+#define SATA_PHY_TX_IMCAL2		0x124
+#define SATA_PHY_RX_IMCAL0		0x128
+#define SATA_PHY_EQUAL			0x13C
+#define SATA_PHY_OOB_TERM		0x144
+#define SATA_PHY_CDR_CTRL0		0x148
+#define SATA_PHY_CDR_CTRL1		0x14C
+#define SATA_PHY_CDR_CTRL2		0x150
+#define SATA_PHY_CDR_CTRL3		0x154
+#define SATA_PHY_PI_CTRL0		0x168
+#define SATA_PHY_POW_DWN_CTRL0		0x180
+#define SATA_PHY_POW_DWN_CTRL1		0x184
+#define SATA_PHY_TX_DATA_CTRL		0x188
+#define SATA_PHY_ALIGNP			0x1A4
+#define SATA_PHY_TX_IMCAL_STAT		0x1E4
+#define SATA_PHY_RX_IMCAL_STAT		0x1E8
+
+#define UNIPHY_PLL_LOCK		BIT(0)
+#define SATA_PHY_TX_CAL		BIT(0)
+#define SATA_PHY_RX_CAL		BIT(0)
+
+/* default timeout set to 1 sec */
+#define TIMEOUT_MS		10000
+#define DELAY_INTERVAL_US	100
+
+struct qcom_apq8064_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+/* Helper function to do poll and timeout */
+static int read_poll_timeout(void __iomem *addr, u32 mask)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+	do {
+		if (readl_relaxed(addr) & mask)
+			return 0;
+
+		 usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+	} while (!time_after(jiffies, timeout));
+
+	return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
+}
+
+static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+	int ret = 0;
+
+	/* SATA phy initialization */
+	writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
+	writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
+	/* Make sure the power down happens before power up */
+	mb();
+	usleep_range(10, 60);
+
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+	writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
+
+	/* Write UNIPHYPLL registers to configure PLL */
+	writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
+	writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
+
+	writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
+	writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
+	writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
+	writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
+	writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
+
+	writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
+	writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
+	writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
+	writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
+
+	writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
+	writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
+	writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
+
+	writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
+	writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
+
+	writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
+	/* make sure global config LDO power down happens before power up */
+	mb();
+
+	writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
+	writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
+
+	/* PLL Lock wait */
+	ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
+		return ret;
+	}
+
+	/* TX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* RX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* SATA phy calibrated succesfully, power up to functional mode */
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+
+	writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
+	writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
+	writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+
+	writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
+	writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
+	writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
+
+	writel_relaxed(0x01, base + SATA_PHY_EQUAL);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+
+	/* Power down PHY */
+	writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
+
+	/* Power down PLL block */
+	writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
+
+	return 0;
+}
+
+static struct phy_ops qcom_apq8064_sata_phy_ops = {
+	.init		= qcom_apq8064_sata_phy_init,
+	.exit		= qcom_apq8064_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
+				      NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
+	{ .compatible = "qcom,apq8064-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
+
+static struct platform_driver qcom_apq8064_sata_phy_driver = {
+	.probe	= qcom_apq8064_sata_phy_probe,
+	.remove	= qcom_apq8064_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-apq8064-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_apq8064_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_apq8064_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-qcom-ipq806x-sata.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-qcom-ipq806x-sata.c
--- linux-libre-3.16-gnu/drivers/phy/phy-qcom-ipq806x-sata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-qcom-ipq806x-sata.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, 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/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+struct qcom_ipq806x_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+#define __set(v, a, b)	(((v) << (b)) & GENMASK(a, b))
+
+#define SATA_PHY_P0_PARAM0		0x200
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x)	__set(x, 17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK	GENMASK(17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x)	__set(x, 11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK	GENMASK(11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x)	__set(x, 5, 0)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK	GENMASK(5, 0)
+
+#define SATA_PHY_P0_PARAM1		0x204
+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x)	__set(x, 31, 21)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x)	__set(x, 20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK	GENMASK(20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x)	__set(x, 13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK	GENMASK(13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x)	__set(x, 6, 0)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK	GENMASK(6, 0)
+
+#define SATA_PHY_P0_PARAM2		0x208
+#define SATA_PHY_P0_PARAM2_RX_EQ(x)	__set(x, 20, 18)
+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK	GENMASK(20, 18)
+
+#define SATA_PHY_P0_PARAM3		0x20C
+#define SATA_PHY_SSC_EN			0x8
+#define SATA_PHY_P0_PARAM4		0x210
+#define SATA_PHY_REF_SSP_EN		0x2
+#define SATA_PHY_RESET			0x1
+
+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting SSC_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
+	reg = reg | SATA_PHY_SSC_EN;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
+			~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
+			~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
+		~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
+	reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* Setting REF_SSP_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* make sure all changes complete before we let the PHY out of reset */
+	mb();
+
+	/* sleep for max. 50us more to combine processor wakeups */
+	usleep_range(20, 20 + 50);
+
+	/* Clearing PHY_RESET to 0 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg & ~SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+	.init		= qcom_ipq806x_sata_phy_init,
+	.exit		= qcom_ipq806x_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
+				      NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
+	{ .compatible = "qcom,ipq806x-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
+
+static struct platform_driver qcom_ipq806x_sata_phy_driver = {
+	.probe	= qcom_ipq806x_sata_phy_probe,
+	.remove	= qcom_ipq806x_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-ipq806x-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_ipq806x_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_ipq806x_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-s5pv210-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-s5pv210-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-s5pv210-usb2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-s5pv210-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Kamil Debski <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define S5PV210_UPHYPWR			0x0
+
+#define S5PV210_UPHYPWR_PHY0_SUSPEND	BIT(0)
+#define S5PV210_UPHYPWR_PHY0_PWR	BIT(3)
+#define S5PV210_UPHYPWR_PHY0_OTG_PWR	BIT(4)
+#define S5PV210_UPHYPWR_PHY0	( \
+	S5PV210_UPHYPWR_PHY0_SUSPEND | \
+	S5PV210_UPHYPWR_PHY0_PWR | \
+	S5PV210_UPHYPWR_PHY0_OTG_PWR)
+
+#define S5PV210_UPHYPWR_PHY1_SUSPEND	BIT(6)
+#define S5PV210_UPHYPWR_PHY1_PWR	BIT(7)
+#define S5PV210_UPHYPWR_PHY1 ( \
+	S5PV210_UPHYPWR_PHY1_SUSPEND | \
+	S5PV210_UPHYPWR_PHY1_PWR)
+
+/* PHY clock control */
+#define S5PV210_UPHYCLK			0x4
+
+#define S5PV210_UPHYCLK_PHYFSEL_MASK	(0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_48MHZ	(0x0 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_24MHZ	(0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_12MHZ	(0x2 << 0)
+
+#define S5PV210_UPHYCLK_PHY0_ID_PULLUP	BIT(2)
+#define S5PV210_UPHYCLK_PHY0_COMMON_ON	BIT(4)
+#define S5PV210_UPHYCLK_PHY1_COMMON_ON	BIT(7)
+
+/* PHY reset control */
+#define S5PV210_UPHYRST			0x8
+
+#define S5PV210_URSTCON_PHY0		BIT(0)
+#define S5PV210_URSTCON_OTG_HLINK	BIT(1)
+#define S5PV210_URSTCON_OTG_PHYLINK	BIT(2)
+#define S5PV210_URSTCON_PHY1_ALL	BIT(3)
+#define S5PV210_URSTCON_HOST_LINK_ALL	BIT(4)
+
+/* Isolation, configured in the power management unit */
+#define S5PV210_USB_ISOL_OFFSET		0x680c
+#define S5PV210_USB_ISOL_DEVICE		BIT(0)
+#define S5PV210_USB_ISOL_HOST		BIT(1)
+
+
+enum s5pv210_phy_id {
+	S5PV210_DEVICE,
+	S5PV210_HOST,
+	S5PV210_NUM_PHYS,
+};
+
+/*
+ * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+	switch (rate) {
+	case 12 * MHZ:
+		*reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
+		break;
+	case 24 * MHZ:
+		*reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
+		break;
+	case 48 * MHZ:
+		*reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+	u32 mask;
+
+	switch (inst->cfg->id) {
+	case S5PV210_DEVICE:
+		mask = S5PV210_USB_ISOL_DEVICE;
+		break;
+	case S5PV210_HOST:
+		mask = S5PV210_USB_ISOL_HOST;
+		break;
+	default:
+		return;
+	};
+
+	regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
+							mask, on ? 0 : mask);
+}
+
+static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+	u32 rstbits = 0;
+	u32 phypwr = 0;
+	u32 rst;
+	u32 pwr;
+
+	switch (inst->cfg->id) {
+	case S5PV210_DEVICE:
+		phypwr =	S5PV210_UPHYPWR_PHY0;
+		rstbits =	S5PV210_URSTCON_PHY0;
+		break;
+	case S5PV210_HOST:
+		phypwr =	S5PV210_UPHYPWR_PHY1;
+		rstbits =	S5PV210_URSTCON_PHY1_ALL |
+				S5PV210_URSTCON_HOST_LINK_ALL;
+		break;
+	};
+
+	if (on) {
+		writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
+
+		pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+		pwr &= ~phypwr;
+		writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+
+		rst = readl(drv->reg_phy + S5PV210_UPHYRST);
+		rst |= rstbits;
+		writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+		udelay(10);
+		rst &= ~rstbits;
+		writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+	} else {
+		pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+		pwr |= phypwr;
+		writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+	}
+}
+
+static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+	s5pv210_isol(inst, 0);
+	s5pv210_phy_pwr(inst, 1);
+
+	return 0;
+}
+
+static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+	s5pv210_phy_pwr(inst, 0);
+	s5pv210_isol(inst, 1);
+
+	return 0;
+}
+
+static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
+	[S5PV210_DEVICE] = {
+		.label		= "device",
+		.id		= S5PV210_DEVICE,
+		.power_on	= s5pv210_power_on,
+		.power_off	= s5pv210_power_off,
+	},
+	[S5PV210_HOST] = {
+		.label		= "host",
+		.id		= S5PV210_HOST,
+		.power_on	= s5pv210_power_on,
+		.power_off	= s5pv210_power_off,
+	},
+};
+
+const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
+	.num_phys	= ARRAY_SIZE(s5pv210_phys),
+	.phys		= s5pv210_phys,
+	.rate_to_clk	= s5pv210_rate_to_clk,
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-samsung-usb2.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-samsung-usb2.c
--- linux-libre-3.16-gnu/drivers/phy/phy-samsung-usb2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-samsung-usb2.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlat
 }
 
 static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+	{
+		.compatible = "samsung,exynos3250-usb2-phy",
+		.data = &exynos3250_usb2_phy_config,
+	},
+#endif
 #ifdef CONFIG_PHY_EXYNOS4210_USB2
 	{
 		.compatible = "samsung,exynos4210-usb2-phy",
@@ -105,6 +111,12 @@ static const struct of_device_id samsung
 		.data = &exynos5250_usb2_phy_config,
 	},
 #endif
+#ifdef CONFIG_PHY_S5PV210_USB2
+	{
+		.compatible = "samsung,s5pv210-usb2-phy",
+		.data = &s5pv210_usb2_phy_config,
+	},
+#endif
 	{ },
 };
 MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
@@ -190,7 +202,8 @@ static int samsung_usb2_phy_probe(struct
 		struct samsung_usb2_phy_instance *p = &drv->instances[i];
 
 		dev_dbg(dev, "Creating phy \"%s\"\n", label);
-		p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL);
+		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
+					 NULL);
 		if (IS_ERR(p->phy)) {
 			dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
 				label);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-samsung-usb2.h linux-libre-3.17-rc7-gnu/drivers/phy/phy-samsung-usb2.h
--- linux-libre-3.16-gnu/drivers/phy/phy-samsung-usb2.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-samsung-usb2.h	2014-09-28 17:29:07.000000000 -0400
@@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance {
 	const struct samsung_usb2_common_phy *cfg;
 	struct phy *phy;
 	struct samsung_usb2_phy_driver *drv;
-	bool enabled;
+	int int_cnt;
+	int ext_cnt;
 };
 
 struct samsung_usb2_phy_driver {
@@ -59,9 +60,12 @@ struct samsung_usb2_phy_config {
 	int (*rate_to_clk)(unsigned long, u32 *);
 	unsigned int num_phys;
 	bool has_mode_switch;
+	bool has_refclk_sel;
 };
 
+extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-spear1310-miphy.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-spear1310-miphy.c
--- linux-libre-3.16-gnu/drivers/phy/phy-spear1310-miphy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-spear1310-miphy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,274 @@
+/*
+ * ST SPEAr1310-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1310 Registers */
+#define SPEAR1310_PCIE_SATA_CFG			0x3A4
+	#define SPEAR1310_PCIE_SATA2_SEL_PCIE		(0 << 31)
+	#define SPEAR1310_PCIE_SATA1_SEL_PCIE		(0 << 30)
+	#define SPEAR1310_PCIE_SATA0_SEL_PCIE		(0 << 29)
+	#define SPEAR1310_PCIE_SATA2_SEL_SATA		BIT(31)
+	#define SPEAR1310_PCIE_SATA1_SEL_SATA		BIT(30)
+	#define SPEAR1310_PCIE_SATA0_SEL_SATA		BIT(29)
+	#define SPEAR1310_SATA2_CFG_TX_CLK_EN		BIT(27)
+	#define SPEAR1310_SATA2_CFG_RX_CLK_EN		BIT(26)
+	#define SPEAR1310_SATA2_CFG_POWERUP_RESET	BIT(25)
+	#define SPEAR1310_SATA2_CFG_PM_CLK_EN		BIT(24)
+	#define SPEAR1310_SATA1_CFG_TX_CLK_EN		BIT(23)
+	#define SPEAR1310_SATA1_CFG_RX_CLK_EN		BIT(22)
+	#define SPEAR1310_SATA1_CFG_POWERUP_RESET	BIT(21)
+	#define SPEAR1310_SATA1_CFG_PM_CLK_EN		BIT(20)
+	#define SPEAR1310_SATA0_CFG_TX_CLK_EN		BIT(19)
+	#define SPEAR1310_SATA0_CFG_RX_CLK_EN		BIT(18)
+	#define SPEAR1310_SATA0_CFG_POWERUP_RESET	BIT(17)
+	#define SPEAR1310_SATA0_CFG_PM_CLK_EN		BIT(16)
+	#define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT	BIT(11)
+	#define SPEAR1310_PCIE2_CFG_POWERUP_RESET	BIT(10)
+	#define SPEAR1310_PCIE2_CFG_CORE_CLK_EN		BIT(9)
+	#define SPEAR1310_PCIE2_CFG_AUX_CLK_EN		BIT(8)
+	#define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT	BIT(7)
+	#define SPEAR1310_PCIE1_CFG_POWERUP_RESET	BIT(6)
+	#define SPEAR1310_PCIE1_CFG_CORE_CLK_EN		BIT(5)
+	#define SPEAR1310_PCIE1_CFG_AUX_CLK_EN		BIT(4)
+	#define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT	BIT(3)
+	#define SPEAR1310_PCIE0_CFG_POWERUP_RESET	BIT(2)
+	#define SPEAR1310_PCIE0_CFG_CORE_CLK_EN		BIT(1)
+	#define SPEAR1310_PCIE0_CFG_AUX_CLK_EN		BIT(0)
+
+	#define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
+	#define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+			BIT((x + 29)))
+	#define SPEAR1310_PCIE_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+			SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+	#define SPEAR1310_SATA_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+			SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define SPEAR1310_PCIE_MIPHY_CFG_1		0x3A8
+	#define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT	BIT(31)
+	#define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2	BIT(28)
+	#define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)	(x << 16)
+	#define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT	BIT(15)
+	#define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2	BIT(12)
+	#define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x)	(x << 0)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+			(SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define SPEAR1310_PCIE_MIPHY_CFG_2		0x3AC
+
+enum spear1310_miphy_mode {
+	SATA,
+	PCIE,
+};
+
+struct spear1310_miphy_priv {
+	/* instance id of this phy */
+	u32				id;
+	/* phy mode: 0 for SATA 1 for PCIe */
+	enum spear1310_miphy_mode	mode;
+	/* regmap for any soc specific misc registers */
+	struct regmap			*misc;
+	/* phy struct pointer */
+	struct phy			*phy;
+};
+
+static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
+{
+	u32 val;
+
+	regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
+
+	switch (priv->id) {
+	case 0:
+		val = SPEAR1310_PCIE_CFG_VAL(0);
+		break;
+	case 1:
+		val = SPEAR1310_PCIE_CFG_VAL(1);
+		break;
+	case 2:
+		val = SPEAR1310_PCIE_CFG_VAL(2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+			   SPEAR1310_PCIE_CFG_MASK(priv->id), val);
+
+	return 0;
+}
+
+static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
+{
+	regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+			   SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
+
+	regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
+
+	return 0;
+}
+
+static int spear1310_miphy_init(struct phy *phy)
+{
+	struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+	int ret = 0;
+
+	if (priv->mode == PCIE)
+		ret = spear1310_miphy_pcie_init(priv);
+
+	return ret;
+}
+
+static int spear1310_miphy_exit(struct phy *phy)
+{
+	struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+	int ret = 0;
+
+	if (priv->mode == PCIE)
+		ret = spear1310_miphy_pcie_exit(priv);
+
+	return ret;
+}
+
+static const struct of_device_id spear1310_miphy_of_match[] = {
+	{ .compatible = "st,spear1310-miphy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
+
+static struct phy_ops spear1310_miphy_ops = {
+	.init = spear1310_miphy_init,
+	.exit = spear1310_miphy_exit,
+	.owner = THIS_MODULE,
+};
+
+static struct phy *spear1310_miphy_xlate(struct device *dev,
+					 struct of_phandle_args *args)
+{
+	struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
+
+	if (args->args_count < 1) {
+		dev_err(dev, "DT did not pass correct no of args\n");
+		return NULL;
+	}
+
+	priv->mode = args->args[0];
+
+	if (priv->mode != SATA && priv->mode != PCIE) {
+		dev_err(dev, "DT did not pass correct phy mode\n");
+		return NULL;
+	}
+
+	return priv->phy;
+}
+
+static int spear1310_miphy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct spear1310_miphy_priv *priv;
+	struct phy_provider *phy_provider;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "can't alloc spear1310_miphy private date memory\n");
+		return -ENOMEM;
+	}
+
+	priv->misc =
+		syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+	if (IS_ERR(priv->misc)) {
+		dev_err(dev, "failed to find misc regmap\n");
+		return PTR_ERR(priv->misc);
+	}
+
+	if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
+		dev_err(dev, "failed to find phy id\n");
+		return -EINVAL;
+	}
+
+	priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL);
+	if (IS_ERR(priv->phy)) {
+		dev_err(dev, "failed to create SATA PCIe PHY\n");
+		return PTR_ERR(priv->phy);
+	}
+
+	dev_set_drvdata(dev, priv);
+	phy_set_drvdata(priv->phy, priv);
+
+	phy_provider =
+		devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "failed to register phy provider\n");
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static struct platform_driver spear1310_miphy_driver = {
+	.probe		= spear1310_miphy_probe,
+	.driver = {
+		.name = "spear1310-miphy",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(spear1310_miphy_of_match),
+	},
+};
+
+static int __init spear1310_miphy_phy_init(void)
+{
+	return platform_driver_register(&spear1310_miphy_driver);
+}
+module_init(spear1310_miphy_phy_init);
+
+static void __exit spear1310_miphy_phy_exit(void)
+{
+	platform_driver_unregister(&spear1310_miphy_driver);
+}
+module_exit(spear1310_miphy_phy_exit);
+
+MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-spear1340-miphy.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-spear1340-miphy.c
--- linux-libre-3.16-gnu/drivers/phy/phy-spear1340-miphy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-spear1340-miphy.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,307 @@
+/*
+ * ST spear1340-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1340 Registers */
+/* Power Management Registers */
+#define SPEAR1340_PCM_CFG			0x100
+	#define SPEAR1340_PCM_CFG_SATA_POWER_EN		BIT(11)
+#define SPEAR1340_PCM_WKUP_CFG			0x104
+#define SPEAR1340_SWITCH_CTR			0x108
+
+#define SPEAR1340_PERIP1_SW_RST			0x318
+	#define SPEAR1340_PERIP1_SW_RSATA		BIT(12)
+#define SPEAR1340_PERIP2_SW_RST			0x31C
+#define SPEAR1340_PERIP3_SW_RST			0x320
+
+/* PCIE - SATA configuration registers */
+#define SPEAR1340_PCIE_SATA_CFG			0x424
+	/* PCIE CFG MASks */
+	#define SPEAR1340_PCIE_CFG_DEVICE_PRESENT	BIT(11)
+	#define SPEAR1340_PCIE_CFG_POWERUP_RESET	BIT(10)
+	#define SPEAR1340_PCIE_CFG_CORE_CLK_EN		BIT(9)
+	#define SPEAR1340_PCIE_CFG_AUX_CLK_EN		BIT(8)
+	#define SPEAR1340_SATA_CFG_TX_CLK_EN		BIT(4)
+	#define SPEAR1340_SATA_CFG_RX_CLK_EN		BIT(3)
+	#define SPEAR1340_SATA_CFG_POWERUP_RESET	BIT(2)
+	#define SPEAR1340_SATA_CFG_PM_CLK_EN		BIT(1)
+	#define SPEAR1340_PCIE_SATA_SEL_PCIE		(0)
+	#define SPEAR1340_PCIE_SATA_SEL_SATA		(1)
+	#define SPEAR1340_PCIE_SATA_CFG_MASK		0xF1F
+	#define SPEAR1340_PCIE_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_PCIE | \
+			SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
+			SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
+			SPEAR1340_PCIE_CFG_POWERUP_RESET | \
+			SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
+	#define SPEAR1340_SATA_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_SATA | \
+			SPEAR1340_SATA_CFG_PM_CLK_EN | \
+			SPEAR1340_SATA_CFG_POWERUP_RESET | \
+			SPEAR1340_SATA_CFG_RX_CLK_EN | \
+			SPEAR1340_SATA_CFG_TX_CLK_EN)
+
+#define SPEAR1340_PCIE_MIPHY_CFG		0x428
+	#define SPEAR1340_MIPHY_OSC_BYPASS_EXT		BIT(31)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV2		BIT(27)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV4		(2 << 27)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV8		(3 << 27)
+	#define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)	(x << 0)
+	#define SPEAR1340_PCIE_MIPHY_CFG_MASK		0xF80000FF
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
+			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+			SPEAR1340_MIPHY_CLK_REF_DIV2 | \
+			SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+			(SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
+			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+
+enum spear1340_miphy_mode {
+	SATA,
+	PCIE,
+};
+
+struct spear1340_miphy_priv {
+	/* phy mode: 0 for SATA 1 for PCIe */
+	enum spear1340_miphy_mode	mode;
+	/* regmap for any soc specific misc registers */
+	struct regmap			*misc;
+	/* phy struct pointer */
+	struct phy			*phy;
+};
+
+static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
+{
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+			   SPEAR1340_PCIE_SATA_CFG_MASK,
+			   SPEAR1340_SATA_CFG_VAL);
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+			   SPEAR1340_PCIE_MIPHY_CFG_MASK,
+			   SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
+	/* Switch on sata power domain */
+	regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+			   SPEAR1340_PCM_CFG_SATA_POWER_EN,
+			   SPEAR1340_PCM_CFG_SATA_POWER_EN);
+	/* Wait for SATA power domain on */
+	msleep(20);
+
+	/* Disable PCIE SATA Controller reset */
+	regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+			   SPEAR1340_PERIP1_SW_RSATA, 0);
+	/* Wait for SATA reset de-assert completion */
+	msleep(20);
+
+	return 0;
+}
+
+static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
+{
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+			   SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+			   SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+
+	/* Enable PCIE SATA Controller reset */
+	regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+			   SPEAR1340_PERIP1_SW_RSATA,
+			   SPEAR1340_PERIP1_SW_RSATA);
+	/* Wait for SATA power domain off */
+	msleep(20);
+	/* Switch off sata power domain */
+	regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+			   SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
+	/* Wait for SATA reset assert completion */
+	msleep(20);
+
+	return 0;
+}
+
+static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
+{
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+			   SPEAR1340_PCIE_MIPHY_CFG_MASK,
+			   SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+			   SPEAR1340_PCIE_SATA_CFG_MASK,
+			   SPEAR1340_PCIE_CFG_VAL);
+
+	return 0;
+}
+
+static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
+{
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+			   SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+			   SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+
+	return 0;
+}
+
+static int spear1340_miphy_init(struct phy *phy)
+{
+	struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+	int ret = 0;
+
+	if (priv->mode == SATA)
+		ret = spear1340_miphy_sata_init(priv);
+	else if (priv->mode == PCIE)
+		ret = spear1340_miphy_pcie_init(priv);
+
+	return ret;
+}
+
+static int spear1340_miphy_exit(struct phy *phy)
+{
+	struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+	int ret = 0;
+
+	if (priv->mode == SATA)
+		ret = spear1340_miphy_sata_exit(priv);
+	else if (priv->mode == PCIE)
+		ret = spear1340_miphy_pcie_exit(priv);
+
+	return ret;
+}
+
+static const struct of_device_id spear1340_miphy_of_match[] = {
+	{ .compatible = "st,spear1340-miphy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
+
+static struct phy_ops spear1340_miphy_ops = {
+	.init = spear1340_miphy_init,
+	.exit = spear1340_miphy_exit,
+	.owner = THIS_MODULE,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int spear1340_miphy_suspend(struct device *dev)
+{
+	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (priv->mode == SATA)
+		ret = spear1340_miphy_sata_exit(priv);
+
+	return ret;
+}
+
+static int spear1340_miphy_resume(struct device *dev)
+{
+	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (priv->mode == SATA)
+		ret = spear1340_miphy_sata_init(priv);
+
+	return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
+			 spear1340_miphy_resume);
+
+static struct phy *spear1340_miphy_xlate(struct device *dev,
+					 struct of_phandle_args *args)
+{
+	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+
+	if (args->args_count < 1) {
+		dev_err(dev, "DT did not pass correct no of args\n");
+		return NULL;
+	}
+
+	priv->mode = args->args[0];
+
+	if (priv->mode != SATA && priv->mode != PCIE) {
+		dev_err(dev, "DT did not pass correct phy mode\n");
+		return NULL;
+	}
+
+	return priv->phy;
+}
+
+static int spear1340_miphy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct spear1340_miphy_priv *priv;
+	struct phy_provider *phy_provider;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "can't alloc spear1340_miphy private date memory\n");
+		return -ENOMEM;
+	}
+
+	priv->misc =
+		syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+	if (IS_ERR(priv->misc)) {
+		dev_err(dev, "failed to find misc regmap\n");
+		return PTR_ERR(priv->misc);
+	}
+
+	priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL);
+	if (IS_ERR(priv->phy)) {
+		dev_err(dev, "failed to create SATA PCIe PHY\n");
+		return PTR_ERR(priv->phy);
+	}
+
+	dev_set_drvdata(dev, priv);
+	phy_set_drvdata(priv->phy, priv);
+
+	phy_provider =
+		devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "failed to register phy provider\n");
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static struct platform_driver spear1340_miphy_driver = {
+	.probe		= spear1340_miphy_probe,
+	.driver = {
+		.name = "spear1340-miphy",
+		.owner = THIS_MODULE,
+		.pm = &spear1340_miphy_pm_ops,
+		.of_match_table = of_match_ptr(spear1340_miphy_of_match),
+	},
+};
+
+static int __init spear1340_miphy_phy_init(void)
+{
+	return platform_driver_register(&spear1340_miphy_driver);
+}
+module_init(spear1340_miphy_phy_init);
+
+static void __exit spear1340_miphy_phy_exit(void)
+{
+	platform_driver_unregister(&spear1340_miphy_driver);
+}
+module_exit(spear1340_miphy_phy_exit);
+
+MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-sun4i-usb.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-sun4i-usb.c
--- linux-libre-3.16-gnu/drivers/phy/phy-sun4i-usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-sun4i-usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -294,7 +295,7 @@ static int sun4i_usb_phy_probe(struct pl
 				return PTR_ERR(phy->pmu);
 		}
 
-		phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+		phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
 		if (IS_ERR(phy->phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
 			return PTR_ERR(phy->phy);
@@ -306,10 +307,8 @@ static int sun4i_usb_phy_probe(struct pl
 
 	dev_set_drvdata(dev, data);
 	phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id sun4i_usb_phy_of_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-ti-pipe3.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-ti-pipe3.c
--- linux-libre-3.16-gnu/drivers/phy/phy-ti-pipe3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-ti-pipe3.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,7 +80,9 @@ struct ti_pipe3 {
 	struct clk		*wkupclk;
 	struct clk		*sys_clk;
 	struct clk		*refclk;
+	struct clk		*div_clk;
 	struct pipe3_dpll_map	*dpll_map;
+	u8			id;
 };
 
 static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,11 @@ static int ti_pipe3_init(struct phy *x)
 	u32 val;
 	int ret = 0;
 
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+		omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
+		return 0;
+	}
+
 	/* Bring it out of IDLE if it is IDLE */
 	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 	if (val & PLL_IDLE) {
@@ -238,8 +245,11 @@ static int ti_pipe3_exit(struct phy *x)
 	u32 val;
 	unsigned long timeout;
 
-	/* SATA DPLL can't be powered down due to Errata i783 */
-	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
+	/* SATA DPLL can't be powered down due to Errata i783 and PCIe
+	 * does not have internal DPLL
+	 */
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
+	    of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
 		return 0;
 
 	/* Put DPLL in IDLE mode */
@@ -286,32 +296,41 @@ static int ti_pipe3_probe(struct platfor
 	struct device_node *control_node;
 	struct platform_device *control_pdev;
 	const struct of_device_id *match;
-
-	match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
-	if (!match)
-		return -EINVAL;
+	struct clk *clk;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy) {
 		dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
 		return -ENOMEM;
 	}
+	phy->dev		= &pdev->dev;
 
-	phy->dpll_map = (struct pipe3_dpll_map *)match->data;
-	if (!phy->dpll_map) {
-		dev_err(&pdev->dev, "no DPLL data\n");
-		return -EINVAL;
-	}
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		match = of_match_device(of_match_ptr(ti_pipe3_id_table),
+					&pdev->dev);
+		if (!match)
+			return -EINVAL;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(phy->pll_ctrl_base))
-		return PTR_ERR(phy->pll_ctrl_base);
+		phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+		if (!phy->dpll_map) {
+			dev_err(&pdev->dev, "no DPLL data\n");
+			return -EINVAL;
+		}
 
-	phy->dev		= &pdev->dev;
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pll_ctrl");
+		phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(phy->pll_ctrl_base))
+			return PTR_ERR(phy->pll_ctrl_base);
 
-	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+		phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
+		if (IS_ERR(phy->sys_clk)) {
+			dev_err(&pdev->dev, "unable to get sysclk\n");
+			return -EINVAL;
+		}
+	}
 
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 		phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
 		if (IS_ERR(phy->wkupclk)) {
 			dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +347,38 @@ static int ti_pipe3_probe(struct platfor
 		phy->refclk = ERR_PTR(-ENODEV);
 	}
 
-	phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
-	if (IS_ERR(phy->sys_clk)) {
-		dev_err(&pdev->dev, "unable to get sysclk\n");
-		return -EINVAL;
+	if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		if (of_property_read_u8(node, "id", &phy->id) < 0)
+			phy->id = 1;
+
+		clk = devm_clk_get(phy->dev, "dpll_ref");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 1500000000);
+
+		clk = devm_clk_get(phy->dev, "dpll_ref_m2");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		clk = devm_clk_get(phy->dev, "phy-div");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get phy-div clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		phy->div_clk = devm_clk_get(phy->dev, "div-clk");
+		if (IS_ERR(phy->div_clk)) {
+			dev_err(&pdev->dev, "unable to get div-clk\n");
+			return PTR_ERR(phy->div_clk);
+		}
+	} else {
+		phy->div_clk = ERR_PTR(-ENODEV);
 	}
 
 	control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -353,7 +400,7 @@ static int ti_pipe3_probe(struct platfor
 	platform_set_drvdata(pdev, phy);
 	pm_runtime_enable(phy->dev);
 
-	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
@@ -387,6 +434,8 @@ static int ti_pipe3_runtime_suspend(stru
 		clk_disable_unprepare(phy->wkupclk);
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
+	if (!IS_ERR(phy->div_clk))
+		clk_disable_unprepare(phy->div_clk);
 
 	return 0;
 }
@@ -412,8 +461,19 @@ static int ti_pipe3_runtime_resume(struc
 		}
 	}
 
+	if (!IS_ERR(phy->div_clk)) {
+		ret = clk_prepare_enable(phy->div_clk);
+		if (ret) {
+			dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
+			goto err3;
+		}
+	}
 	return 0;
 
+err3:
+	if (!IS_ERR(phy->wkupclk))
+		clk_disable_unprepare(phy->wkupclk);
+
 err2:
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
@@ -446,6 +506,9 @@ static const struct of_device_id ti_pipe
 		.compatible = "ti,phy-pipe3-sata",
 		.data = dpll_map_sata,
 	},
+	{
+		.compatible = "ti,phy-pipe3-pcie",
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-twl4030-usb.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-twl4030-usb.c
--- linux-libre-3.16-gnu/drivers/phy/phy-twl4030-usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-twl4030-usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
 #include <linux/usb/musb-omap.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl
 	}
 }
 
-static int twl4030_phy_power_off(struct phy *phy)
+static int twl4030_usb_runtime_suspend(struct device *dev)
 {
-	struct twl4030_usb *twl = phy_get_drvdata(phy);
+	struct twl4030_usb *twl = dev_get_drvdata(dev);
 
+	dev_dbg(twl->dev, "%s\n", __func__);
 	if (twl->asleep)
 		return 0;
 
 	twl4030_phy_power(twl, 0);
 	twl->asleep = 1;
-	dev_dbg(twl->dev, "%s\n", __func__);
+
 	return 0;
 }
 
-static void __twl4030_phy_power_on(struct twl4030_usb *twl)
+static int twl4030_usb_runtime_resume(struct device *dev)
 {
+	struct twl4030_usb *twl = dev_get_drvdata(dev);
+
+	dev_dbg(twl->dev, "%s\n", __func__);
+	if (!twl->asleep)
+		return 0;
+
 	twl4030_phy_power(twl, 1);
-	twl4030_i2c_access(twl, 1);
-	twl4030_usb_set_mode(twl, twl->usb_mode);
-	if (twl->usb_mode == T2_USB_MODE_ULPI)
-		twl4030_i2c_access(twl, 0);
+	twl->asleep = 0;
+
+	return 0;
+}
+
+static int twl4030_phy_power_off(struct phy *phy)
+{
+	struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+	dev_dbg(twl->dev, "%s\n", __func__);
+	pm_runtime_mark_last_busy(twl->dev);
+	pm_runtime_put_autosuspend(twl->dev);
+
+	return 0;
 }
 
 static int twl4030_phy_power_on(struct phy *phy)
 {
 	struct twl4030_usb *twl = phy_get_drvdata(phy);
 
-	if (!twl->asleep)
-		return 0;
-	__twl4030_phy_power_on(twl);
-	twl->asleep = 0;
 	dev_dbg(twl->dev, "%s\n", __func__);
+	pm_runtime_get_sync(twl->dev);
+	twl4030_i2c_access(twl, 1);
+	twl4030_usb_set_mode(twl, twl->usb_mode);
+	if (twl->usb_mode == T2_USB_MODE_ULPI)
+		twl4030_i2c_access(twl, 0);
 
 	/*
 	 * XXX When VBUS gets driven after musb goes to A mode,
@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int i
 		 * USB_LINK_VBUS state.  musb_hdrc won't care until it
 		 * starts to handle softconnect right.
 		 */
+		if ((status == OMAP_MUSB_VBUS_VALID) ||
+		    (status == OMAP_MUSB_ID_GROUND)) {
+			if (twl->asleep)
+				pm_runtime_get_sync(twl->dev);
+		} else {
+			if (!twl->asleep) {
+				pm_runtime_mark_last_busy(twl->dev);
+				pm_runtime_put_autosuspend(twl->dev);
+			}
+		}
 		omap_musb_mailbox(status);
 	}
-	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+	/* don't schedule during sleep - irq works right then */
+	if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
+		cancel_delayed_work(&twl->id_workaround_work);
+		schedule_delayed_work(&twl->id_workaround_work, HZ);
+	}
+
+	if (irq)
+		sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
 	return IRQ_HANDLED;
 }
@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(s
 {
 	struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
 		id_workaround_work.work);
-	enum omap_musb_vbus_id_status status;
-	bool status_changed = false;
-
-	status = twl4030_usb_linkstat(twl);
-
-	spin_lock_irq(&twl->lock);
-	if (status >= 0 && status != twl->linkstat) {
-		twl->linkstat = status;
-		status_changed = true;
-	}
-	spin_unlock_irq(&twl->lock);
 
-	if (status_changed) {
-		dev_dbg(twl->dev, "handle missing status change to %d\n",
-				status);
-		omap_musb_mailbox(status);
-	}
-
-	/* don't schedule during sleep - irq works right then */
-	if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
-		cancel_delayed_work(&twl->id_workaround_work);
-		schedule_delayed_work(&twl->id_workaround_work, HZ);
-	}
+	twl4030_usb_irq(0, twl);
 }
 
 static int twl4030_phy_init(struct phy *phy)
@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *
 	struct twl4030_usb *twl = phy_get_drvdata(phy);
 	enum omap_musb_vbus_id_status status;
 
-	/*
-	 * Start in sleep state, we'll get called through set_suspend()
-	 * callback when musb is runtime resumed and it's time to start.
-	 */
-	__twl4030_phy_power(twl, 0);
-	twl->asleep = 1;
-
+	pm_runtime_get_sync(twl->dev);
 	status = twl4030_usb_linkstat(twl);
 	twl->linkstat = status;
 
-	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
+	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
 		omap_musb_mailbox(twl->linkstat);
-		twl4030_phy_power_on(phy);
-	}
 
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+	pm_runtime_mark_last_busy(twl->dev);
+	pm_runtime_put_autosuspend(twl->dev);
+
 	return 0;
 }
 
@@ -650,6 +661,11 @@ static const struct phy_ops ops = {
 	.owner		= THIS_MODULE,
 };
 
+static const struct dev_pm_ops twl4030_usb_pm_ops = {
+	SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
+			   twl4030_usb_runtime_resume, NULL)
+};
+
 static int twl4030_usb_probe(struct platform_device *pdev)
 {
 	struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
@@ -695,7 +711,7 @@ static int twl4030_usb_probe(struct plat
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
-	phy = devm_phy_create(twl->dev, &ops, init_data);
+	phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
 	if (IS_ERR(phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		return PTR_ERR(phy);
@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct plat
 
 	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
 
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
 	/* Our job is to use irqs and status from the power module
 	 * to keep the transceiver disabled when nothing's connected.
 	 *
@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct plat
 		return status;
 	}
 
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(twl->dev);
+
 	dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
 	return 0;
 }
@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct pla
 	struct twl4030_usb *twl = platform_get_drvdata(pdev);
 	int val;
 
+	pm_runtime_get_sync(twl->dev);
 	cancel_delayed_work(&twl->id_workaround_work);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 
@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct pla
 
 	/* disable complete OTG block */
 	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-
-	if (!twl->asleep)
-		twl4030_phy_power(twl, 0);
+	pm_runtime_mark_last_busy(twl->dev);
+	pm_runtime_put(twl->dev);
 
 	return 0;
 }
@@ -792,6 +816,7 @@ static struct platform_driver twl4030_us
 	.remove		= twl4030_usb_remove,
 	.driver		= {
 		.name	= "twl4030_usb",
+		.pm	= &twl4030_usb_pm_ops,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(twl4030_usb_id_table),
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/phy/phy-xgene.c linux-libre-3.17-rc7-gnu/drivers/phy/phy-xgene.c
--- linux-libre-3.16-gnu/drivers/phy/phy-xgene.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/phy/phy-xgene.c	2014-09-28 17:29:07.000000000 -0400
@@ -1707,7 +1707,7 @@ static int xgene_phy_probe(struct platfo
 	ctx->dev = &pdev->dev;
 	platform_set_drvdata(pdev, ctx);
 
-	ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL);
+	ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
 	if (IS_ERR(ctx->phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		rc = PTR_ERR(ctx->phy);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/core.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/core.c
--- linux-libre-3.16-gnu/drivers/pinctrl/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -992,29 +992,15 @@ int pinctrl_select_state(struct pinctrl
 
 	if (p->state) {
 		/*
-		 * The set of groups with a mux configuration in the old state
-		 * may not be identical to the set of groups with a mux setting
-		 * in the new state. While this might be unusual, it's entirely
-		 * possible for the "user"-supplied mapping table to be written
-		 * that way. For each group that was configured in the old state
-		 * but not in the new state, this code puts that group into a
-		 * safe/disabled state.
+		 * For each pinmux setting in the old state, forget SW's record
+		 * of mux owner for that pingroup. Any pingroups which are
+		 * still owned by the new state will be re-acquired by the call
+		 * to pinmux_enable_setting() in the loop below.
 		 */
 		list_for_each_entry(setting, &p->state->settings, node) {
-			bool found = false;
 			if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
 				continue;
-			list_for_each_entry(setting2, &state->settings, node) {
-				if (setting2->type != PIN_MAP_TYPE_MUX_GROUP)
-					continue;
-				if (setting2->data.mux.group ==
-						setting->data.mux.group) {
-					found = true;
-					break;
-				}
-			}
-			if (!found)
-				pinmux_disable_setting(setting);
+			pinmux_disable_setting(setting);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -11,10 +11,10 @@ menu "Pin controllers"
 	depends on PINCTRL
 
 config PINMUX
-	bool "Support pin multiplexing controllers"
+	bool "Support pin multiplexing controllers" if COMPILE_TEST
 
 config PINCONF
-	bool "Support pin configuration controllers"
+	bool "Support pin configuration controllers" if COMPILE_TEST
 
 config GENERIC_PINCONF
 	bool
@@ -26,29 +26,6 @@ config DEBUG_PINCTRL
 	help
 	  Say Y here to add some extra checks and diagnostics to PINCTRL calls.
 
-config PINCTRL_ABX500
-	bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions"
-	depends on AB8500_CORE
-	select GENERIC_PINCONF
-	help
-	  Select this to enable the ABx500 family IC GPIO driver
-
-config PINCTRL_AB8500
-	bool "AB8500 pin controller driver"
-	depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB8540
-	bool "AB8540 pin controller driver"
-	depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB9540
-	bool "AB9540 pin controller driver"
-	depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB8505
-	bool "AB8505 pin controller driver"
-	depends on PINCTRL_ABX500 && ARCH_U8500
-
 config PINCTRL_ADI2
 	bool "ADI pin controller driver"
 	depends on BLACKFIN
@@ -93,7 +70,7 @@ config PINCTRL_AT91
 config PINCTRL_BAYTRAIL
 	bool "Intel Baytrail GPIO pin control"
 	depends on GPIOLIB && ACPI && X86
-	select IRQ_DOMAIN
+	select GPIOLIB_IRQCHIP
 	help
 	  driver for memory mapped GPIO functionality on Intel Baytrail
 	  platforms. Supports 3 banks with 102, 28 and 44 gpios.
@@ -130,6 +107,13 @@ config PINCTRL_IMX1_CORE
 	select PINMUX
 	select PINCONF
 
+config PINCTRL_IMX1
+	bool "IMX1 pinctrl driver"
+	depends on SOC_IMX1
+	select PINCTRL_IMX1_CORE
+	help
+	  Say Y here to enable the imx1 pinctrl driver
+
 config PINCTRL_IMX27
 	bool "IMX27 pinctrl driver"
 	depends on SOC_IMX27
@@ -226,58 +210,6 @@ config PINCTRL_IMX28
 	bool
 	select PINCTRL_MXS
 
-config PINCTRL_MSM
-	bool
-	select PINMUX
-	select PINCONF
-	select GENERIC_PINCONF
-	select GPIOLIB_IRQCHIP
-
-config PINCTRL_APQ8064
-	tristate "Qualcomm APQ8064 pin controller driver"
-	depends on GPIOLIB && OF
-	select PINCTRL_MSM
-	help
-	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
-	  Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
-
-config PINCTRL_IPQ8064
-	tristate "Qualcomm IPQ8064 pin controller driver"
-	depends on GPIOLIB && OF
-	select PINCTRL_MSM
-	help
-	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
-	  Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
-
-config PINCTRL_MSM8X74
-	tristate "Qualcomm 8x74 pin controller driver"
-	depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST)
-	select PINCTRL_MSM
-	help
-	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
-	  Qualcomm TLMM block found in the Qualcomm 8974 platform.
-
-config PINCTRL_NOMADIK
-	bool "Nomadik pin controller driver"
-	depends on ARCH_U8500 || ARCH_NOMADIK
-	select PINMUX
-	select PINCONF
-	select GPIOLIB
-	select OF_GPIO
-	select GPIOLIB_IRQCHIP
-
-config PINCTRL_STN8815
-	bool "STN8815 pin controller driver"
-	depends on PINCTRL_NOMADIK && ARCH_NOMADIK
-
-config PINCTRL_DB8500
-	bool "DB8500 pin controller driver"
-	depends on PINCTRL_NOMADIK && ARCH_U8500
-
-config PINCTRL_DB8540
-	bool "DB8540 pin controller driver"
-	depends on PINCTRL_NOMADIK && ARCH_U8500
-
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
@@ -328,6 +260,12 @@ config PINCTRL_TEGRA124
 	bool
 	select PINCTRL_TEGRA
 
+config PINCTRL_TEGRA_XUSB
+	def_bool y if ARCH_TEGRA
+	select GENERIC_PHY
+	select PINCONF
+	select PINMUX
+
 config PINCTRL_TZ1090
 	bool "Toumaz Xenif TZ1090 pin control driver"
 	depends on SOC_TZ1090
@@ -356,22 +294,6 @@ config PINCTRL_COH901
 	  COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
 	  ports of 8 GPIO pins each.
 
-config PINCTRL_SAMSUNG
-	bool
-	select PINMUX
-	select PINCONF
-
-config PINCTRL_EXYNOS
-	bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440"
-	depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210)
-	select PINCTRL_SAMSUNG
-
-config PINCTRL_EXYNOS5440
-	bool "Samsung EXYNOS5440 SoC pinctrl driver"
-	depends on SOC_EXYNOS5440
-	select PINMUX
-	select PINCONF
-
 config PINCTRL_PALMAS
 	bool "Pinctrl driver for the PALMAS Series MFD devices"
 	depends on OF && MFD_PALMAS
@@ -383,18 +305,11 @@ config PINCTRL_PALMAS
 	  open drain configuration for the Palmas series devices like
 	  TPS65913, TPS80036 etc.
 
-config PINCTRL_S3C24XX
-	bool "Samsung S3C24XX SoC pinctrl driver"
-	depends on ARCH_S3C24XX
-	select PINCTRL_SAMSUNG
-
-config PINCTRL_S3C64XX
-	bool "Samsung S3C64XX SoC pinctrl driver"
-	depends on ARCH_S3C64XX
-	select PINCTRL_SAMSUNG
-
 source "drivers/pinctrl/berlin/Kconfig"
 source "drivers/pinctrl/mvebu/Kconfig"
+source "drivers/pinctrl/nomadik/Kconfig"
+source "drivers/pinctrl/qcom/Kconfig"
+source "drivers/pinctrl/samsung/Kconfig"
 source "drivers/pinctrl/sh-pfc/Kconfig"
 source "drivers/pinctrl/spear/Kconfig"
 source "drivers/pinctrl/sunxi/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/Makefile linux-libre-3.17-rc7-gnu/drivers/pinctrl/Makefile
--- linux-libre-3.16-gnu/drivers/pinctrl/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,11 +9,6 @@ ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_PINCTRL)		+= devicetree.o
 endif
 obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
-obj-$(CONFIG_PINCTRL_ABX500)	+= pinctrl-abx500.o
-obj-$(CONFIG_PINCTRL_AB8500)	+= pinctrl-ab8500.o
-obj-$(CONFIG_PINCTRL_AB8540)	+= pinctrl-ab8540.o
-obj-$(CONFIG_PINCTRL_AB9540)	+= pinctrl-ab9540.o
-obj-$(CONFIG_PINCTRL_AB8505)	+= pinctrl-ab8505.o
 obj-$(CONFIG_PINCTRL_ADI2)	+= pinctrl-adi2.o
 obj-$(CONFIG_PINCTRL_AS3722)	+= pinctrl-as3722.o
 obj-$(CONFIG_PINCTRL_BF54x)	+= pinctrl-adi2-bf54x.o
@@ -24,6 +19,7 @@ obj-$(CONFIG_PINCTRL_BAYTRAIL)	+= pinctr
 obj-$(CONFIG_PINCTRL_BCM281XX)	+= pinctrl-bcm281xx.o
 obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
 obj-$(CONFIG_PINCTRL_IMX1_CORE)	+= pinctrl-imx1-core.o
+obj-$(CONFIG_PINCTRL_IMX1)	+= pinctrl-imx1.o
 obj-$(CONFIG_PINCTRL_IMX27)	+= pinctrl-imx27.o
 obj-$(CONFIG_PINCTRL_IMX35)	+= pinctrl-imx35.o
 obj-$(CONFIG_PINCTRL_IMX50)	+= pinctrl-imx50.o
@@ -38,14 +34,6 @@ obj-$(CONFIG_PINCTRL_MXS)	+= pinctrl-mxs
 obj-$(CONFIG_PINCTRL_IMX23)	+= pinctrl-imx23.o
 obj-$(CONFIG_PINCTRL_IMX25)	+= pinctrl-imx25.o
 obj-$(CONFIG_PINCTRL_IMX28)	+= pinctrl-imx28.o
-obj-$(CONFIG_PINCTRL_MSM)	+= pinctrl-msm.o
-obj-$(CONFIG_PINCTRL_APQ8064)	+= pinctrl-apq8064.o
-obj-$(CONFIG_PINCTRL_IPQ8064)	+= pinctrl-ipq8064.o
-obj-$(CONFIG_PINCTRL_MSM8X74)	+= pinctrl-msm8x74.o
-obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
-obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
-obj-$(CONFIG_PINCTRL_DB8500)	+= pinctrl-nomadik-db8500.o
-obj-$(CONFIG_PINCTRL_DB8540)	+= pinctrl-nomadik-db8540.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
@@ -55,15 +43,11 @@ obj-$(CONFIG_PINCTRL_TEGRA20)	+= pinctrl
 obj-$(CONFIG_PINCTRL_TEGRA30)	+= pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_TEGRA114)	+= pinctrl-tegra114.o
 obj-$(CONFIG_PINCTRL_TEGRA124)	+= pinctrl-tegra124.o
+obj-$(CONFIG_PINCTRL_TEGRA_XUSB)	+= pinctrl-tegra-xusb.o
 obj-$(CONFIG_PINCTRL_TZ1090)	+= pinctrl-tz1090.o
 obj-$(CONFIG_PINCTRL_TZ1090_PDC)	+= pinctrl-tz1090-pdc.o
 obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
-obj-$(CONFIG_PINCTRL_SAMSUNG)	+= pinctrl-samsung.o
-obj-$(CONFIG_PINCTRL_EXYNOS)	+= pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_EXYNOS5440)	+= pinctrl-exynos5440.o
-obj-$(CONFIG_PINCTRL_S3C24XX)	+= pinctrl-s3c24xx.o
-obj-$(CONFIG_PINCTRL_S3C64XX)	+= pinctrl-s3c64xx.o
 obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
 obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
@@ -72,8 +56,11 @@ obj-$(CONFIG_PINCTRL_VF610)	+= pinctrl-v
 
 obj-$(CONFIG_ARCH_BERLIN)	+= berlin/
 obj-$(CONFIG_PLAT_ORION)        += mvebu/
+obj-y				+= nomadik/
+obj-$(CONFIG_ARCH_QCOM)		+= qcom/
+obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SHMOBILE)	+= sh-pfc/
 obj-$(CONFIG_SUPERH)		+= sh-pfc/
 obj-$(CONFIG_PLAT_SPEAR)	+= spear/
-obj-$(CONFIG_ARCH_VT8500)	+= vt8500/
 obj-$(CONFIG_ARCH_SUNXI)	+= sunxi/
+obj-$(CONFIG_ARCH_VT8500)	+= vt8500/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,51 @@
+if ARCH_U8500
+
+config PINCTRL_ABX500
+	bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions"
+	depends on AB8500_CORE
+	select GENERIC_PINCONF
+	help
+	  Select this to enable the ABx500 family IC GPIO driver
+
+config PINCTRL_AB8500
+	bool "AB8500 pin controller driver"
+	depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB8540
+	bool "AB8540 pin controller driver"
+	depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB9540
+	bool "AB9540 pin controller driver"
+	depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB8505
+	bool "AB8505 pin controller driver"
+	depends on PINCTRL_ABX500 && ARCH_U8500
+
+endif
+
+if (ARCH_U8500 || ARCH_NOMADIK)
+
+config PINCTRL_NOMADIK
+	bool "Nomadik pin controller driver"
+	depends on ARCH_U8500 || ARCH_NOMADIK
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select GPIOLIB_IRQCHIP
+
+config PINCTRL_STN8815
+	bool "STN8815 pin controller driver"
+	depends on PINCTRL_NOMADIK && ARCH_NOMADIK
+
+config PINCTRL_DB8500
+	bool "DB8500 pin controller driver"
+	depends on PINCTRL_NOMADIK && ARCH_U8500
+
+config PINCTRL_DB8540
+	bool "DB8540 pin controller driver"
+	depends on PINCTRL_NOMADIK && ARCH_U8500
+
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/Makefile linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/Makefile
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,10 @@
+# Nomadik family pin control drivers
+obj-$(CONFIG_PINCTRL_ABX500)	+= pinctrl-abx500.o
+obj-$(CONFIG_PINCTRL_AB8500)	+= pinctrl-ab8500.o
+obj-$(CONFIG_PINCTRL_AB8540)	+= pinctrl-ab8540.o
+obj-$(CONFIG_PINCTRL_AB9540)	+= pinctrl-ab9540.o
+obj-$(CONFIG_PINCTRL_AB8505)	+= pinctrl-ab8505.o
+obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
+obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
+obj-$(CONFIG_PINCTRL_DB8500)	+= pinctrl-nomadik-db8500.o
+obj-$(CONFIG_PINCTRL_DB8540)	+= pinctrl-nomadik-db8540.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8500.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include "pinctrl-abx500.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define ABX500_GPIO(offset)		(offset)
+
+#define AB8500_PIN_T10		ABX500_GPIO(1)
+#define AB8500_PIN_T9		ABX500_GPIO(2)
+#define AB8500_PIN_U9		ABX500_GPIO(3)
+#define AB8500_PIN_W2		ABX500_GPIO(4)
+/* hole */
+#define AB8500_PIN_Y18		ABX500_GPIO(6)
+#define AB8500_PIN_AA20		ABX500_GPIO(7)
+#define AB8500_PIN_W18		ABX500_GPIO(8)
+#define AB8500_PIN_AA19		ABX500_GPIO(9)
+#define AB8500_PIN_U17		ABX500_GPIO(10)
+#define AB8500_PIN_AA18		ABX500_GPIO(11)
+#define AB8500_PIN_U16		ABX500_GPIO(12)
+#define AB8500_PIN_W17		ABX500_GPIO(13)
+#define AB8500_PIN_F14		ABX500_GPIO(14)
+#define AB8500_PIN_B17		ABX500_GPIO(15)
+#define AB8500_PIN_F15		ABX500_GPIO(16)
+#define AB8500_PIN_P5		ABX500_GPIO(17)
+#define AB8500_PIN_R5		ABX500_GPIO(18)
+#define AB8500_PIN_U5		ABX500_GPIO(19)
+#define AB8500_PIN_T5		ABX500_GPIO(20)
+#define AB8500_PIN_H19		ABX500_GPIO(21)
+#define AB8500_PIN_G20		ABX500_GPIO(22)
+#define AB8500_PIN_G19		ABX500_GPIO(23)
+#define AB8500_PIN_T14		ABX500_GPIO(24)
+#define AB8500_PIN_R16		ABX500_GPIO(25)
+#define AB8500_PIN_M16		ABX500_GPIO(26)
+#define AB8500_PIN_J6		ABX500_GPIO(27)
+#define AB8500_PIN_K6		ABX500_GPIO(28)
+#define AB8500_PIN_G6		ABX500_GPIO(29)
+#define AB8500_PIN_H6		ABX500_GPIO(30)
+#define AB8500_PIN_F5		ABX500_GPIO(31)
+#define AB8500_PIN_G5		ABX500_GPIO(32)
+/* hole */
+#define AB8500_PIN_R17		ABX500_GPIO(34)
+#define AB8500_PIN_W15		ABX500_GPIO(35)
+#define AB8500_PIN_A17		ABX500_GPIO(36)
+#define AB8500_PIN_E15		ABX500_GPIO(37)
+#define AB8500_PIN_C17		ABX500_GPIO(38)
+#define AB8500_PIN_E16		ABX500_GPIO(39)
+#define AB8500_PIN_T19		ABX500_GPIO(40)
+#define AB8500_PIN_U19		ABX500_GPIO(41)
+#define AB8500_PIN_U2		ABX500_GPIO(42)
+
+/* indicates the highest GPIO number */
+#define AB8500_GPIO_MAX_NUMBER	42
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc ab8500_pins[] = {
+	PINCTRL_PIN(AB8500_PIN_T10, "GPIO1_T10"),
+	PINCTRL_PIN(AB8500_PIN_T9, "GPIO2_T9"),
+	PINCTRL_PIN(AB8500_PIN_U9, "GPIO3_U9"),
+	PINCTRL_PIN(AB8500_PIN_W2, "GPIO4_W2"),
+	/* hole */
+	PINCTRL_PIN(AB8500_PIN_Y18, "GPIO6_Y18"),
+	PINCTRL_PIN(AB8500_PIN_AA20, "GPIO7_AA20"),
+	PINCTRL_PIN(AB8500_PIN_W18, "GPIO8_W18"),
+	PINCTRL_PIN(AB8500_PIN_AA19, "GPIO9_AA19"),
+	PINCTRL_PIN(AB8500_PIN_U17, "GPIO10_U17"),
+	PINCTRL_PIN(AB8500_PIN_AA18, "GPIO11_AA18"),
+	PINCTRL_PIN(AB8500_PIN_U16, "GPIO12_U16"),
+	PINCTRL_PIN(AB8500_PIN_W17, "GPIO13_W17"),
+	PINCTRL_PIN(AB8500_PIN_F14, "GPIO14_F14"),
+	PINCTRL_PIN(AB8500_PIN_B17, "GPIO15_B17"),
+	PINCTRL_PIN(AB8500_PIN_F15, "GPIO16_F15"),
+	PINCTRL_PIN(AB8500_PIN_P5, "GPIO17_P5"),
+	PINCTRL_PIN(AB8500_PIN_R5, "GPIO18_R5"),
+	PINCTRL_PIN(AB8500_PIN_U5, "GPIO19_U5"),
+	PINCTRL_PIN(AB8500_PIN_T5, "GPIO20_T5"),
+	PINCTRL_PIN(AB8500_PIN_H19, "GPIO21_H19"),
+	PINCTRL_PIN(AB8500_PIN_G20, "GPIO22_G20"),
+	PINCTRL_PIN(AB8500_PIN_G19, "GPIO23_G19"),
+	PINCTRL_PIN(AB8500_PIN_T14, "GPIO24_T14"),
+	PINCTRL_PIN(AB8500_PIN_R16, "GPIO25_R16"),
+	PINCTRL_PIN(AB8500_PIN_M16, "GPIO26_M16"),
+	PINCTRL_PIN(AB8500_PIN_J6, "GPIO27_J6"),
+	PINCTRL_PIN(AB8500_PIN_K6, "GPIO28_K6"),
+	PINCTRL_PIN(AB8500_PIN_G6, "GPIO29_G6"),
+	PINCTRL_PIN(AB8500_PIN_H6, "GPIO30_H6"),
+	PINCTRL_PIN(AB8500_PIN_F5, "GPIO31_F5"),
+	PINCTRL_PIN(AB8500_PIN_G5, "GPIO32_G5"),
+	/* hole */
+	PINCTRL_PIN(AB8500_PIN_R17, "GPIO34_R17"),
+	PINCTRL_PIN(AB8500_PIN_W15, "GPIO35_W15"),
+	PINCTRL_PIN(AB8500_PIN_A17, "GPIO36_A17"),
+	PINCTRL_PIN(AB8500_PIN_E15, "GPIO37_E15"),
+	PINCTRL_PIN(AB8500_PIN_C17, "GPIO38_C17"),
+	PINCTRL_PIN(AB8500_PIN_E16, "GPIO39_E16"),
+	PINCTRL_PIN(AB8500_PIN_T19, "GPIO40_T19"),
+	PINCTRL_PIN(AB8500_PIN_U19, "GPIO41_U19"),
+	PINCTRL_PIN(AB8500_PIN_U2, "GPIO42_U2"),
+};
+
+/*
+ * Maps local GPIO offsets to local pin numbers
+ */
+static const struct abx500_pinrange ab8500_pinranges[] = {
+	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(6, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(10, 4, ABX500_DEFAULT),
+	ABX500_PINRANGE(14, 12, ABX500_ALT_A),
+	ABX500_PINRANGE(26, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
+	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
+	ABX500_PINRANGE(35, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(36, 7, ABX500_ALT_A),
+};
+
+/*
+ * Read the pin group names like this:
+ * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* default column */
+static const unsigned sysclkreq2_d_1_pins[] = { AB8500_PIN_T10 };
+static const unsigned sysclkreq3_d_1_pins[] = { AB8500_PIN_T9 };
+static const unsigned sysclkreq4_d_1_pins[] = { AB8500_PIN_U9 };
+static const unsigned sysclkreq6_d_1_pins[] = { AB8500_PIN_W2 };
+static const unsigned ycbcr0123_d_1_pins[] = { AB8500_PIN_Y18, AB8500_PIN_AA20,
+					AB8500_PIN_W18, AB8500_PIN_AA19};
+static const unsigned gpio10_d_1_pins[] = { AB8500_PIN_U17 };
+static const unsigned gpio11_d_1_pins[] = { AB8500_PIN_AA18 };
+static const unsigned gpio12_d_1_pins[] = { AB8500_PIN_U16 };
+static const unsigned gpio13_d_1_pins[] = { AB8500_PIN_W17 };
+static const unsigned pwmout1_d_1_pins[] = { AB8500_PIN_F14 };
+static const unsigned pwmout2_d_1_pins[] = { AB8500_PIN_B17 };
+static const unsigned pwmout3_d_1_pins[] = { AB8500_PIN_F15 };
+
+/* audio data interface 1*/
+static const unsigned adi1_d_1_pins[] = { AB8500_PIN_P5, AB8500_PIN_R5,
+					AB8500_PIN_U5, AB8500_PIN_T5 };
+/* USBUICC */
+static const unsigned usbuicc_d_1_pins[] = { AB8500_PIN_H19, AB8500_PIN_G20,
+					AB8500_PIN_G19 };
+static const unsigned sysclkreq7_d_1_pins[] = { AB8500_PIN_T14 };
+static const unsigned sysclkreq8_d_1_pins[] = { AB8500_PIN_R16 };
+static const unsigned gpio26_d_1_pins[] = { AB8500_PIN_M16 };
+/* Digital microphone 1 and 2 */
+static const unsigned dmic12_d_1_pins[] = { AB8500_PIN_J6, AB8500_PIN_K6 };
+/* Digital microphone 3 and 4 */
+static const unsigned dmic34_d_1_pins[] = { AB8500_PIN_G6, AB8500_PIN_H6 };
+/* Digital microphone 5 and 6 */
+static const unsigned dmic56_d_1_pins[] = { AB8500_PIN_F5, AB8500_PIN_G5 };
+static const unsigned extcpena_d_1_pins[] = { AB8500_PIN_R17 };
+static const unsigned gpio35_d_1_pins[] = { AB8500_PIN_W15 };
+/* APE SPI */
+static const unsigned apespi_d_1_pins[] = { AB8500_PIN_A17, AB8500_PIN_E15,
+					AB8500_PIN_C17, AB8500_PIN_E16};
+/* modem SDA/SCL */
+static const unsigned modsclsda_d_1_pins[] = { AB8500_PIN_T19, AB8500_PIN_U19 };
+static const unsigned sysclkreq5_d_1_pins[] = { AB8500_PIN_U2 };
+
+/* Altfunction A column */
+static const unsigned gpio1_a_1_pins[] = { AB8500_PIN_T10 };
+static const unsigned gpio2_a_1_pins[] = { AB8500_PIN_T9 };
+static const unsigned gpio3_a_1_pins[] = { AB8500_PIN_U9 };
+static const unsigned gpio4_a_1_pins[] = { AB8500_PIN_W2 };
+static const unsigned gpio6_a_1_pins[] = { AB8500_PIN_Y18 };
+static const unsigned gpio7_a_1_pins[] = { AB8500_PIN_AA20 };
+static const unsigned gpio8_a_1_pins[] = { AB8500_PIN_W18 };
+static const unsigned gpio9_a_1_pins[] = { AB8500_PIN_AA19 };
+/* YCbCr4 YCbCr5 YCbCr6 YCbCr7*/
+static const unsigned ycbcr4567_a_1_pins[] = { AB8500_PIN_U17, AB8500_PIN_AA18,
+					AB8500_PIN_U16, AB8500_PIN_W17};
+static const unsigned gpio14_a_1_pins[] = { AB8500_PIN_F14 };
+static const unsigned gpio15_a_1_pins[] = { AB8500_PIN_B17 };
+static const unsigned gpio16_a_1_pins[] = { AB8500_PIN_F15 };
+static const unsigned gpio17_a_1_pins[] = { AB8500_PIN_P5 };
+static const unsigned gpio18_a_1_pins[] = { AB8500_PIN_R5 };
+static const unsigned gpio19_a_1_pins[] = { AB8500_PIN_U5 };
+static const unsigned gpio20_a_1_pins[] = { AB8500_PIN_T5 };
+static const unsigned gpio21_a_1_pins[] = { AB8500_PIN_H19 };
+static const unsigned gpio22_a_1_pins[] = { AB8500_PIN_G20 };
+static const unsigned gpio23_a_1_pins[] = { AB8500_PIN_G19 };
+static const unsigned gpio24_a_1_pins[] = { AB8500_PIN_T14 };
+static const unsigned gpio25_a_1_pins[] = { AB8500_PIN_R16 };
+static const unsigned gpio27_a_1_pins[] = { AB8500_PIN_J6 };
+static const unsigned gpio28_a_1_pins[] = { AB8500_PIN_K6 };
+static const unsigned gpio29_a_1_pins[] = { AB8500_PIN_G6 };
+static const unsigned gpio30_a_1_pins[] = { AB8500_PIN_H6 };
+static const unsigned gpio31_a_1_pins[] = { AB8500_PIN_F5 };
+static const unsigned gpio32_a_1_pins[] = { AB8500_PIN_G5 };
+static const unsigned gpio34_a_1_pins[] = { AB8500_PIN_R17 };
+static const unsigned gpio36_a_1_pins[] = { AB8500_PIN_A17 };
+static const unsigned gpio37_a_1_pins[] = { AB8500_PIN_E15 };
+static const unsigned gpio38_a_1_pins[] = { AB8500_PIN_C17 };
+static const unsigned gpio39_a_1_pins[] = { AB8500_PIN_E16 };
+static const unsigned gpio40_a_1_pins[] = { AB8500_PIN_T19 };
+static const unsigned gpio41_a_1_pins[] = { AB8500_PIN_U19 };
+static const unsigned gpio42_a_1_pins[] = { AB8500_PIN_U2 };
+
+/* Altfunction B colum */
+static const unsigned hiqclkena_b_1_pins[] = { AB8500_PIN_U17 };
+static const unsigned usbuiccpd_b_1_pins[] = { AB8500_PIN_AA18 };
+static const unsigned i2ctrig1_b_1_pins[] = { AB8500_PIN_U16 };
+static const unsigned i2ctrig2_b_1_pins[] = { AB8500_PIN_W17 };
+
+/* Altfunction C column */
+static const unsigned usbvdat_c_1_pins[] = { AB8500_PIN_W17 };
+
+
+#define AB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct abx500_pingroup ab8500_groups[] = {
+	/* default column */
+	AB8500_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(ycbcr0123_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio12_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio26_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio35_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(apespi_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
+	/* Altfunction A column */
+	AB8500_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio6_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio7_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio8_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio9_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(ycbcr4567_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio21_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio22_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio23_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio24_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio25_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio36_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio37_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio38_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio39_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
+	/* Altfunction B column */
+	AB8500_PIN_GROUP(hiqclkena_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(usbuiccpd_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(i2ctrig1_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(i2ctrig2_b_1, ABX500_ALT_B),
+	/* Altfunction C column */
+	AB8500_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define AB8500_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+AB8500_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
+		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1",
+		"sysclkreq7_d_1", "sysclkreq8_d_1");
+AB8500_FUNC_GROUPS(ycbcr, "ycbcr0123_d_1", "ycbcr4567_a_1");
+AB8500_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
+		"gpio6_a_1", "gpio7_a_1", "gpio8_a_1", "gpio9_a_1",
+		"gpio10_d_1", "gpio11_d_1", "gpio12_d_1", "gpio13_d_1",
+		"gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1",
+		"gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio21_a_1",
+		"gpio22_a_1", "gpio23_a_1", "gpio24_a_1", "gpio25_a_1",
+		"gpio26_d_1", "gpio27_a_1", "gpio28_a_1", "gpio29_a_1",
+		"gpio30_a_1", "gpio31_a_1", "gpio32_a_1", "gpio34_a_1",
+		"gpio35_d_1", "gpio36_a_1", "gpio37_a_1", "gpio38_a_1",
+		"gpio39_a_1", "gpio40_a_1", "gpio41_a_1", "gpio42_a_1");
+AB8500_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
+AB8500_FUNC_GROUPS(adi1, "adi1_d_1");
+AB8500_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_b_1");
+AB8500_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
+AB8500_FUNC_GROUPS(extcpena, "extcpena_d_1");
+AB8500_FUNC_GROUPS(apespi, "apespi_d_1");
+AB8500_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
+AB8500_FUNC_GROUPS(hiqclkena, "hiqclkena_b_1");
+AB8500_FUNC_GROUPS(i2ctrig, "i2ctrig1_b_1", "i2ctrig2_b_1");
+AB8500_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct abx500_function ab8500_functions[] = {
+	FUNCTION(sysclkreq),
+	FUNCTION(ycbcr),
+	FUNCTION(gpio),
+	FUNCTION(pwmout),
+	FUNCTION(adi1),
+	FUNCTION(usbuicc),
+	FUNCTION(dmic),
+	FUNCTION(extcpena),
+	FUNCTION(apespi),
+	FUNCTION(modsclsda),
+	FUNCTION(hiqclkena),
+	FUNCTION(i2ctrig),
+	FUNCTION(usbvdat),
+};
+
+/*
+ * this table translates what's is in the AB8500 specification regarding the
+ * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
+ * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
+ * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
+ *
+ * example :
+ *
+ *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1 ,2),
+ *	means that pin AB8500_PIN_W17 (pin 13) supports 4 mux (default/ALT_A,
+ *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
+ *	select the mux.  ALTA, ALTB and ALTC val indicates values to write in
+ *	ALTERNATFUNC register. We need to specifies these values as SOC
+ *	designers didn't apply the same logic on how to select mux in the
+ *	ABx500 family.
+ *
+ *	As this pins supports at least ALT_B mux, default mux is
+ *	selected by writing 1 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
+ *	default	|       1       |          0          |          0
+ *	alt_A	|       0       |          0          |          0
+ *	alt_B	|       0       |          0          |          1
+ *	alt_C	|       0       |          1          |          0
+ *
+ *	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED),
+ *	means that pin AB8500_PIN_W18 (pin 8) supports 2 mux, so only GPIOSEL
+ *	register is used to select the mux. As this pins doesn't support at
+ *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=7 | alternatfunc bit2=  | alternatfunc bit1=
+ *	default	|       0       |          0          |          0
+ *	alt_A	|       1       |          0          |          0
+ */
+
+static struct
+alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
+	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
+	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
+	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
+	/* bit 4 reserved */
+	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
+	ALTERNATE_FUNCTIONS(6,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO6, altA controlled by bit 5*/
+	ALTERNATE_FUNCTIONS(7,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO7, altA controlled by bit 6*/
+	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO8, altA controlled by bit 7*/
+
+	ALTERNATE_FUNCTIONS(9,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO9, altA controlled by bit 0*/
+	ALTERNATE_FUNCTIONS(10,     1,      0, UNUSED, 0, 1, 0), /* GPIO10, altA and altB controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(11,     2,      1, UNUSED, 0, 1, 0), /* GPIO11, altA and altB controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(12,     3,      2, UNUSED, 0, 1, 0), /* GPIO12, altA and altB controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
+	ALTERNATE_FUNCTIONS(14,     5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(15,     6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(16,     7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
+	/*
+	 * pins 17 to 20 are special case, only bit 0 is used to select
+	 * alternate function for these 4 pins.
+	 * bits 1 to 3 are reserved
+	 */
+	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(21,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(22,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(23,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(24,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(25,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */
+	/* pin 26 special case, no alternate function, bit 1 reserved */
+	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO26 */
+	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
+	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
+	/* pin 35 special case, no alternate function, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO35 */
+	ALTERNATE_FUNCTIONS(36,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO36, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(37,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO37, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(38,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO38, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(39,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO39, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
+};
+
+/*
+ * Only some GPIOs are interrupt capable, and they are
+ * organized in discontiguous clusters:
+ *
+ *	GPIO6 to GPIO13
+ *	GPIO24 and GPIO25
+ *	GPIO36 to GPIO41
+ */
+static struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
+	GPIO_IRQ_CLUSTER(6,  13, AB8500_INT_GPIO6R),
+	GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
+	GPIO_IRQ_CLUSTER(36, 41, AB8500_INT_GPIO36R),
+};
+
+static struct abx500_pinctrl_soc_data ab8500_soc = {
+	.gpio_ranges = ab8500_pinranges,
+	.gpio_num_ranges = ARRAY_SIZE(ab8500_pinranges),
+	.pins = ab8500_pins,
+	.npins = ARRAY_SIZE(ab8500_pins),
+	.functions = ab8500_functions,
+	.nfunctions = ARRAY_SIZE(ab8500_functions),
+	.groups = ab8500_groups,
+	.ngroups = ARRAY_SIZE(ab8500_groups),
+	.alternate_functions = ab8500_alternate_functions,
+	.gpio_irq_cluster = ab8500_gpio_irq_cluster,
+	.ngpio_irq_cluster = ARRAY_SIZE(ab8500_gpio_irq_cluster),
+	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
+	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
+	.irq_gpio_factor = 1,
+};
+
+void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
+{
+	*soc = &ab8500_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8505.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8505.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8505.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8505.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include "pinctrl-abx500.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define ABX500_GPIO(offset)	(offset)
+
+#define AB8505_PIN_N4		ABX500_GPIO(1)
+#define AB8505_PIN_R5		ABX500_GPIO(2)
+#define AB8505_PIN_P5		ABX500_GPIO(3)
+/* hole */
+#define AB8505_PIN_B16		ABX500_GPIO(10)
+#define AB8505_PIN_B17		ABX500_GPIO(11)
+/* hole */
+#define AB8505_PIN_D17		ABX500_GPIO(13)
+#define AB8505_PIN_C16		ABX500_GPIO(14)
+/* hole */
+#define AB8505_PIN_P2		ABX500_GPIO(17)
+#define AB8505_PIN_N3		ABX500_GPIO(18)
+#define AB8505_PIN_T1		ABX500_GPIO(19)
+#define AB8505_PIN_P3		ABX500_GPIO(20)
+/* hole */
+#define AB8505_PIN_H14		ABX500_GPIO(34)
+/* hole */
+#define AB8505_PIN_J15		ABX500_GPIO(40)
+#define AB8505_PIN_J14		ABX500_GPIO(41)
+/* hole */
+#define AB8505_PIN_L4		ABX500_GPIO(50)
+/* hole */
+#define AB8505_PIN_D16		ABX500_GPIO(52)
+#define AB8505_PIN_D15		ABX500_GPIO(53)
+
+/* indicates the higher GPIO number */
+#define AB8505_GPIO_MAX_NUMBER	53
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc ab8505_pins[] = {
+	PINCTRL_PIN(AB8505_PIN_N4, "GPIO1_N4"),
+	PINCTRL_PIN(AB8505_PIN_R5, "GPIO2_R5"),
+	PINCTRL_PIN(AB8505_PIN_P5, "GPIO3_P5"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_B16, "GPIO10_B16"),
+	PINCTRL_PIN(AB8505_PIN_B17, "GPIO11_B17"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_D17, "GPIO13_D17"),
+	PINCTRL_PIN(AB8505_PIN_C16, "GPIO14_C16"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_P2, "GPIO17_P2"),
+	PINCTRL_PIN(AB8505_PIN_N3, "GPIO18_N3"),
+	PINCTRL_PIN(AB8505_PIN_T1, "GPIO19_T1"),
+	PINCTRL_PIN(AB8505_PIN_P3, "GPIO20_P3"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_H14, "GPIO34_H14"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_J15, "GPIO40_J15"),
+	PINCTRL_PIN(AB8505_PIN_J14, "GPIO41_J14"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_L4, "GPIO50_L4"),
+/* hole */
+	PINCTRL_PIN(AB8505_PIN_D16, "GPIO52_D16"),
+	PINCTRL_PIN(AB8505_PIN_D15, "GPIO53_D15"),
+};
+
+/*
+ * Maps local GPIO offsets to local pin numbers
+ */
+static const struct abx500_pinrange ab8505_pinranges[] = {
+	ABX500_PINRANGE(1, 3, ABX500_ALT_A),
+	ABX500_PINRANGE(10, 2, ABX500_DEFAULT),
+	ABX500_PINRANGE(13, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(14, 1, ABX500_ALT_A),
+	ABX500_PINRANGE(17, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
+	ABX500_PINRANGE(40, 2, ABX500_ALT_A),
+	ABX500_PINRANGE(50, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(52, 2, ABX500_ALT_A),
+};
+
+/*
+ * Read the pin group names like this:
+ * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* default column */
+static const unsigned sysclkreq2_d_1_pins[] = { AB8505_PIN_N4 };
+static const unsigned sysclkreq3_d_1_pins[] = { AB8505_PIN_R5 };
+static const unsigned sysclkreq4_d_1_pins[] = { AB8505_PIN_P5 };
+static const unsigned gpio10_d_1_pins[] = { AB8505_PIN_B16 };
+static const unsigned gpio11_d_1_pins[] = { AB8505_PIN_B17 };
+static const unsigned gpio13_d_1_pins[] = { AB8505_PIN_D17 };
+static const unsigned pwmout1_d_1_pins[] = { AB8505_PIN_C16 };
+/* audio data interface 2*/
+static const unsigned adi2_d_1_pins[] = { AB8505_PIN_P2, AB8505_PIN_N3,
+					AB8505_PIN_T1, AB8505_PIN_P3 };
+static const unsigned extcpena_d_1_pins[] = { AB8505_PIN_H14 };
+/* modem SDA/SCL */
+static const unsigned modsclsda_d_1_pins[] = { AB8505_PIN_J15, AB8505_PIN_J14 };
+static const unsigned gpio50_d_1_pins[] = { AB8505_PIN_L4 };
+static const unsigned resethw_d_1_pins[] = { AB8505_PIN_D16 };
+static const unsigned service_d_1_pins[] = { AB8505_PIN_D15 };
+
+/* Altfunction A column */
+static const unsigned gpio1_a_1_pins[] = { AB8505_PIN_N4 };
+static const unsigned gpio2_a_1_pins[] = { AB8505_PIN_R5 };
+static const unsigned gpio3_a_1_pins[] = { AB8505_PIN_P5 };
+static const unsigned hiqclkena_a_1_pins[] = { AB8505_PIN_B16 };
+static const unsigned pdmclk_a_1_pins[] = { AB8505_PIN_B17 };
+static const unsigned uarttxdata_a_1_pins[] = { AB8505_PIN_D17 };
+static const unsigned gpio14_a_1_pins[] = { AB8505_PIN_C16 };
+static const unsigned gpio17_a_1_pins[] = { AB8505_PIN_P2 };
+static const unsigned gpio18_a_1_pins[] = { AB8505_PIN_N3 };
+static const unsigned gpio19_a_1_pins[] = { AB8505_PIN_T1 };
+static const unsigned gpio20_a_1_pins[] = { AB8505_PIN_P3 };
+static const unsigned gpio34_a_1_pins[] = { AB8505_PIN_H14 };
+static const unsigned gpio40_a_1_pins[] = { AB8505_PIN_J15 };
+static const unsigned gpio41_a_1_pins[] = { AB8505_PIN_J14 };
+static const unsigned uartrxdata_a_1_pins[] = { AB8505_PIN_J14 };
+static const unsigned gpio50_a_1_pins[] = { AB8505_PIN_L4 };
+static const unsigned gpio52_a_1_pins[] = { AB8505_PIN_D16 };
+static const unsigned gpio53_a_1_pins[] = { AB8505_PIN_D15 };
+
+/* Altfunction B colum */
+static const unsigned pdmdata_b_1_pins[] = { AB8505_PIN_B16 };
+static const unsigned extvibrapwm1_b_1_pins[] = { AB8505_PIN_D17 };
+static const unsigned extvibrapwm2_b_1_pins[] = { AB8505_PIN_L4 };
+
+/* Altfunction C column */
+static const unsigned usbvdat_c_1_pins[] = { AB8505_PIN_D17 };
+
+#define AB8505_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct abx500_pingroup ab8505_groups[] = {
+	AB8505_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(adi2_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(resethw_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(service_d_1, ABX500_DEFAULT),
+	AB8505_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(uarttxdata_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(uartrxdata_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
+	AB8505_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B),
+	AB8505_PIN_GROUP(extvibrapwm1_b_1, ABX500_ALT_B),
+	AB8505_PIN_GROUP(extvibrapwm2_b_1, ABX500_ALT_B),
+	AB8505_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define AB8505_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+AB8505_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
+		"sysclkreq4_d_1");
+AB8505_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1",
+		"gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1",
+		"gpio17_a_1", "gpio18_a_1", "gpio19_a_1", "gpio20_a_1",
+		"gpio34_a_1", "gpio40_a_1", "gpio41_a_1", "gpio50_d_1",
+		"gpio52_a_1", "gpio53_a_1");
+AB8505_FUNC_GROUPS(pwmout, "pwmout1_d_1");
+AB8505_FUNC_GROUPS(adi2, "adi2_d_1");
+AB8505_FUNC_GROUPS(extcpena, "extcpena_d_1");
+AB8505_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
+AB8505_FUNC_GROUPS(resethw, "resethw_d_1");
+AB8505_FUNC_GROUPS(service, "service_d_1");
+AB8505_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1");
+AB8505_FUNC_GROUPS(pdm, "pdmclk_a_1", "pdmdata_b_1");
+AB8505_FUNC_GROUPS(uartdata, "uarttxdata_a_1", "uartrxdata_a_1");
+AB8505_FUNC_GROUPS(extvibra, "extvibrapwm1_b_1", "extvibrapwm2_b_1");
+AB8505_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct abx500_function ab8505_functions[] = {
+	FUNCTION(sysclkreq),
+	FUNCTION(gpio),
+	FUNCTION(pwmout),
+	FUNCTION(adi2),
+	FUNCTION(extcpena),
+	FUNCTION(modsclsda),
+	FUNCTION(resethw),
+	FUNCTION(service),
+	FUNCTION(hiqclkena),
+	FUNCTION(pdm),
+	FUNCTION(uartdata),
+	FUNCTION(extvibra),
+	FUNCTION(extvibra),
+	FUNCTION(usbvdat),
+};
+
+/*
+ * this table translates what's is in the AB8505 specification regarding the
+ * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
+ * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
+ * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
+ *
+ * example :
+ *
+ *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 1, 0, 2),
+ *	means that pin AB8505_PIN_D18 (pin 13) supports 4 mux (default/ALT_A,
+ *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
+ *	select the mux. ALTA, ALTB and ALTC val indicates values to write in
+ *	ALTERNATFUNC register. We need to specifies these values as SOC
+ *	designers didn't apply the same logic on how to select mux in the
+ *	ABx500 family.
+ *
+ *	As this pins supports at least ALT_B mux, default mux is
+ *	selected by writing 1 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
+ *	default	|       1       |          0          |          0
+ *	alt_A	|       0       |          0          |          1
+ *	alt_B	|       0       |          0          |          0
+ *	alt_C	|       0       |          1          |          0
+ *
+ *	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED),
+ *	means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL
+ *	register is used to select the mux. As this pins doesn't support at
+ *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=0 | alternatfunc bit2=  | alternatfunc bit1=
+ *	default	|       0       |          0          |          0
+ *	alt_A	|       1       |          0          |          0
+ */
+
+static struct
+alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
+	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
+	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
+	ALTERNATE_FUNCTIONS(4, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO4, bit 3 reserved */
+	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5, bit 4 reserved */
+	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6, bit 5 reserved */
+	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7, bit 6 reserved */
+	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8, bit 7 reserved */
+
+	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */
+	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(11,      2,      1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */
+	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
+	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(15, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 6 reserved */
+	ALTERNATE_FUNCTIONS(16, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 7 reserved  */
+	/*
+	 * pins 17 to 20 are special case, only bit 0 is used to select
+	 * alternate function for these 4 pins.
+	 * bits 1 to 3 are reserved
+	 */
+	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21, bit 4 reserved */
+	ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22, bit 5 reserved */
+	ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23, bit 6 reserved */
+	ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24, bit 7 reserved */
+
+	ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25, bit 0 reserved */
+	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26, bit 1 reserved */
+	ALTERNATE_FUNCTIONS(27, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO27, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(28, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO28, bit 3 reserved */
+	ALTERNATE_FUNCTIONS(29, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO29, bit 4 reserved */
+	ALTERNATE_FUNCTIONS(30, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO30, bit 5 reserved */
+	ALTERNATE_FUNCTIONS(31, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO31, bit 6 reserved */
+	ALTERNATE_FUNCTIONS(32, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO32, bit 7 reserved */
+
+	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33, bit 0 reserved */
+	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7*/
+
+	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(42, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO42, bit 1 reserved */
+	ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44, bit 3 reserved */
+	ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45, bit 4 reserved */
+	ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46, bit 5 reserved */
+	ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47, bit 6 reserved */
+	ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48, bit 7 reserved */
+
+	ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */
+	ALTERNATE_FUNCTIONS(50,	     1,      2, UNUSED, 1, 0, 0), /* GPIO50, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(51, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */
+	ALTERNATE_FUNCTIONS(52,	     3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(53,	     4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
+};
+
+/*
+ * For AB8505 Only some GPIOs are interrupt capable, and they are
+ * organized in discontiguous clusters:
+ *
+ *	GPIO10 to GPIO11
+ *	GPIO13
+ *	GPIO40 and GPIO41
+ *	GPIO50
+ *	GPIO52 to GPIO53
+ */
+static struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
+	GPIO_IRQ_CLUSTER(10, 11, AB8500_INT_GPIO10R),
+	GPIO_IRQ_CLUSTER(13, 13, AB8500_INT_GPIO13R),
+	GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
+	GPIO_IRQ_CLUSTER(50, 50, AB9540_INT_GPIO50R),
+	GPIO_IRQ_CLUSTER(52, 53, AB9540_INT_GPIO52R),
+};
+
+static struct abx500_pinctrl_soc_data ab8505_soc = {
+	.gpio_ranges = ab8505_pinranges,
+	.gpio_num_ranges = ARRAY_SIZE(ab8505_pinranges),
+	.pins = ab8505_pins,
+	.npins = ARRAY_SIZE(ab8505_pins),
+	.functions = ab8505_functions,
+	.nfunctions = ARRAY_SIZE(ab8505_functions),
+	.groups = ab8505_groups,
+	.ngroups = ARRAY_SIZE(ab8505_groups),
+	.alternate_functions = ab8505_alternate_functions,
+	.gpio_irq_cluster = ab8505_gpio_irq_cluster,
+	.ngpio_irq_cluster = ARRAY_SIZE(ab8505_gpio_irq_cluster),
+	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
+	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
+	.irq_gpio_factor = 1,
+};
+
+void
+abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc)
+{
+	*soc = &ab8505_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab8540.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab8540.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include "pinctrl-abx500.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define ABX500_GPIO(offset)		(offset)
+
+#define AB8540_PIN_J16		ABX500_GPIO(1)
+#define AB8540_PIN_D17		ABX500_GPIO(2)
+#define AB8540_PIN_C12		ABX500_GPIO(3)
+#define AB8540_PIN_G12		ABX500_GPIO(4)
+/* hole */
+#define AB8540_PIN_D16		ABX500_GPIO(14)
+#define AB8540_PIN_F15		ABX500_GPIO(15)
+#define AB8540_PIN_J8		ABX500_GPIO(16)
+#define AB8540_PIN_K16		ABX500_GPIO(17)
+#define AB8540_PIN_G15		ABX500_GPIO(18)
+#define AB8540_PIN_F17		ABX500_GPIO(19)
+#define AB8540_PIN_E17		ABX500_GPIO(20)
+/* hole */
+#define AB8540_PIN_AA16		ABX500_GPIO(27)
+#define AB8540_PIN_W18		ABX500_GPIO(28)
+#define AB8540_PIN_Y15		ABX500_GPIO(29)
+#define AB8540_PIN_W16		ABX500_GPIO(30)
+#define AB8540_PIN_V15		ABX500_GPIO(31)
+#define AB8540_PIN_W17		ABX500_GPIO(32)
+/* hole */
+#define AB8540_PIN_D12		ABX500_GPIO(42)
+#define AB8540_PIN_P4		ABX500_GPIO(43)
+#define AB8540_PIN_AB1		ABX500_GPIO(44)
+#define AB8540_PIN_K7		ABX500_GPIO(45)
+#define AB8540_PIN_L7		ABX500_GPIO(46)
+#define AB8540_PIN_G10		ABX500_GPIO(47)
+#define AB8540_PIN_K12		ABX500_GPIO(48)
+/* hole */
+#define AB8540_PIN_N8		ABX500_GPIO(51)
+#define AB8540_PIN_P12		ABX500_GPIO(52)
+#define AB8540_PIN_K8		ABX500_GPIO(53)
+#define AB8540_PIN_J11		ABX500_GPIO(54)
+#define AB8540_PIN_AC2		ABX500_GPIO(55)
+#define AB8540_PIN_AB2		ABX500_GPIO(56)
+
+/* indicates the highest GPIO number */
+#define AB8540_GPIO_MAX_NUMBER	56
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc ab8540_pins[] = {
+	PINCTRL_PIN(AB8540_PIN_J16, "GPIO1_J16"),
+	PINCTRL_PIN(AB8540_PIN_D17, "GPIO2_D17"),
+	PINCTRL_PIN(AB8540_PIN_C12, "GPIO3_C12"),
+	PINCTRL_PIN(AB8540_PIN_G12, "GPIO4_G12"),
+	/* hole */
+	PINCTRL_PIN(AB8540_PIN_D16, "GPIO14_D16"),
+	PINCTRL_PIN(AB8540_PIN_F15, "GPIO15_F15"),
+	PINCTRL_PIN(AB8540_PIN_J8, "GPIO16_J8"),
+	PINCTRL_PIN(AB8540_PIN_K16, "GPIO17_K16"),
+	PINCTRL_PIN(AB8540_PIN_G15, "GPIO18_G15"),
+	PINCTRL_PIN(AB8540_PIN_F17, "GPIO19_F17"),
+	PINCTRL_PIN(AB8540_PIN_E17, "GPIO20_E17"),
+	/* hole */
+	PINCTRL_PIN(AB8540_PIN_AA16, "GPIO27_AA16"),
+	PINCTRL_PIN(AB8540_PIN_W18, "GPIO28_W18"),
+	PINCTRL_PIN(AB8540_PIN_Y15, "GPIO29_Y15"),
+	PINCTRL_PIN(AB8540_PIN_W16, "GPIO30_W16"),
+	PINCTRL_PIN(AB8540_PIN_V15, "GPIO31_V15"),
+	PINCTRL_PIN(AB8540_PIN_W17, "GPIO32_W17"),
+	/* hole */
+	PINCTRL_PIN(AB8540_PIN_D12, "GPIO42_D12"),
+	PINCTRL_PIN(AB8540_PIN_P4, "GPIO43_P4"),
+	PINCTRL_PIN(AB8540_PIN_AB1, "GPIO44_AB1"),
+	PINCTRL_PIN(AB8540_PIN_K7, "GPIO45_K7"),
+	PINCTRL_PIN(AB8540_PIN_L7, "GPIO46_L7"),
+	PINCTRL_PIN(AB8540_PIN_G10, "GPIO47_G10"),
+	PINCTRL_PIN(AB8540_PIN_K12, "GPIO48_K12"),
+	/* hole */
+	PINCTRL_PIN(AB8540_PIN_N8, "GPIO51_N8"),
+	PINCTRL_PIN(AB8540_PIN_P12, "GPIO52_P12"),
+	PINCTRL_PIN(AB8540_PIN_K8, "GPIO53_K8"),
+	PINCTRL_PIN(AB8540_PIN_J11, "GPIO54_J11"),
+	PINCTRL_PIN(AB8540_PIN_AC2, "GPIO55_AC2"),
+	PINCTRL_PIN(AB8540_PIN_AB2, "GPIO56_AB2"),
+};
+
+/*
+ * Maps local GPIO offsets to local pin numbers
+ */
+static const struct abx500_pinrange ab8540_pinranges[] = {
+	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(14, 7, ABX500_ALT_A),
+	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
+	ABX500_PINRANGE(42, 7, ABX500_ALT_A),
+	ABX500_PINRANGE(51, 6, ABX500_ALT_A),
+};
+
+/*
+ * Read the pin group names like this:
+ * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* default column */
+static const unsigned sysclkreq2_d_1_pins[] = { AB8540_PIN_J16 };
+static const unsigned sysclkreq3_d_1_pins[] = { AB8540_PIN_D17 };
+static const unsigned sysclkreq4_d_1_pins[] = { AB8540_PIN_C12 };
+static const unsigned sysclkreq6_d_1_pins[] = { AB8540_PIN_G12 };
+static const unsigned pwmout1_d_1_pins[] = { AB8540_PIN_D16 };
+static const unsigned pwmout2_d_1_pins[] = { AB8540_PIN_F15 };
+static const unsigned pwmout3_d_1_pins[] = { AB8540_PIN_J8 };
+
+/* audio data interface 1*/
+static const unsigned adi1_d_1_pins[] = { AB8540_PIN_K16, AB8540_PIN_G15,
+					AB8540_PIN_F17, AB8540_PIN_E17 };
+/* Digital microphone 1 and 2 */
+static const unsigned dmic12_d_1_pins[] = { AB8540_PIN_AA16, AB8540_PIN_W18 };
+/* Digital microphone 3 and 4 */
+static const unsigned dmic34_d_1_pins[] = { AB8540_PIN_Y15, AB8540_PIN_W16 };
+/* Digital microphone 5 and 6 */
+static const unsigned dmic56_d_1_pins[] = { AB8540_PIN_V15, AB8540_PIN_W17 };
+static const unsigned sysclkreq5_d_1_pins[] = { AB8540_PIN_D12 };
+static const unsigned batremn_d_1_pins[] = { AB8540_PIN_P4 };
+static const unsigned service_d_1_pins[] = { AB8540_PIN_AB1 };
+static const unsigned pwrctrl0_d_1_pins[] = { AB8540_PIN_K7 };
+static const unsigned pwrctrl1_d_1_pins[] = { AB8540_PIN_L7 };
+static const unsigned pwmextvibra1_d_1_pins[] = { AB8540_PIN_G10 };
+static const unsigned pwmextvibra2_d_1_pins[] = { AB8540_PIN_K12 };
+static const unsigned gpio1_vbat_d_1_pins[] = { AB8540_PIN_N8 };
+static const unsigned gpio2_vbat_d_1_pins[] = { AB8540_PIN_P12 };
+static const unsigned gpio3_vbat_d_1_pins[] = { AB8540_PIN_K8 };
+static const unsigned gpio4_vbat_d_1_pins[] = { AB8540_PIN_J11 };
+static const unsigned pdmclkdat_d_1_pins[] = { AB8540_PIN_AC2, AB8540_PIN_AB2 };
+
+/* Altfunction A column */
+static const unsigned gpio1_a_1_pins[] = { AB8540_PIN_J16 };
+static const unsigned gpio2_a_1_pins[] = { AB8540_PIN_D17 };
+static const unsigned gpio3_a_1_pins[] = { AB8540_PIN_C12 };
+static const unsigned gpio4_a_1_pins[] = { AB8540_PIN_G12 };
+static const unsigned gpio14_a_1_pins[] = { AB8540_PIN_D16 };
+static const unsigned gpio15_a_1_pins[] = { AB8540_PIN_F15 };
+static const unsigned gpio16_a_1_pins[] = { AB8540_PIN_J8 };
+static const unsigned gpio17_a_1_pins[] = { AB8540_PIN_K16 };
+static const unsigned gpio18_a_1_pins[] = { AB8540_PIN_G15 };
+static const unsigned gpio19_a_1_pins[] = { AB8540_PIN_F17 };
+static const unsigned gpio20_a_1_pins[] = { AB8540_PIN_E17 };
+static const unsigned gpio27_a_1_pins[] = { AB8540_PIN_AA16 };
+static const unsigned gpio28_a_1_pins[] = { AB8540_PIN_W18 };
+static const unsigned gpio29_a_1_pins[] = { AB8540_PIN_Y15 };
+static const unsigned gpio30_a_1_pins[] = { AB8540_PIN_W16 };
+static const unsigned gpio31_a_1_pins[] = { AB8540_PIN_V15 };
+static const unsigned gpio32_a_1_pins[] = { AB8540_PIN_W17 };
+static const unsigned gpio42_a_1_pins[] = { AB8540_PIN_D12 };
+static const unsigned gpio43_a_1_pins[] = { AB8540_PIN_P4 };
+static const unsigned gpio44_a_1_pins[] = { AB8540_PIN_AB1 };
+static const unsigned gpio45_a_1_pins[] = { AB8540_PIN_K7 };
+static const unsigned gpio46_a_1_pins[] = { AB8540_PIN_L7 };
+static const unsigned gpio47_a_1_pins[] = { AB8540_PIN_G10 };
+static const unsigned gpio48_a_1_pins[] = { AB8540_PIN_K12 };
+static const unsigned gpio51_a_1_pins[] = { AB8540_PIN_N8 };
+static const unsigned gpio52_a_1_pins[] = { AB8540_PIN_P12 };
+static const unsigned gpio53_a_1_pins[] = { AB8540_PIN_K8 };
+static const unsigned gpio54_a_1_pins[] = { AB8540_PIN_J11 };
+static const unsigned gpio55_a_1_pins[] = { AB8540_PIN_AC2 };
+static const unsigned gpio56_a_1_pins[] = { AB8540_PIN_AB2 };
+
+#define AB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct abx500_pingroup ab8540_groups[] = {
+	/* default column */
+	AB8540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(service_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwrctrl0_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwrctrl1_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwmextvibra1_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pwmextvibra2_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(gpio1_vbat_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(gpio2_vbat_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(gpio3_vbat_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(gpio4_vbat_d_1, ABX500_DEFAULT),
+	AB8540_PIN_GROUP(pdmclkdat_d_1, ABX500_DEFAULT),
+	/* Altfunction A column */
+	AB8540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio43_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio44_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio45_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio46_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio47_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio48_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio54_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio55_a_1, ABX500_ALT_A),
+	AB8540_PIN_GROUP(gpio56_a_1, ABX500_ALT_A),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define AB8540_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+AB8540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
+		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1");
+AB8540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
+		"gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1",
+		"gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio27_a_1",
+		"gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1",
+		"gpio32_a_1", "gpio42_a_1", "gpio43_a_1", "gpio44_a_1",
+		"gpio45_a_1", "gpio46_a_1", "gpio47_a_1", "gpio48_a_1",
+		"gpio51_a_1", "gpio52_a_1", "gpio53_a_1", "gpio54_a_1",
+		"gpio55_a_1", "gpio56_a_1");
+AB8540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
+AB8540_FUNC_GROUPS(adi1, "adi1_d_1");
+AB8540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
+AB8540_FUNC_GROUPS(batremn, "batremn_d_1");
+AB8540_FUNC_GROUPS(service, "service_d_1");
+AB8540_FUNC_GROUPS(pwrctrl, "pwrctrl0_d_1", "pwrctrl1_d_1");
+AB8540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_d_1", "pwmextvibra2_d_1");
+AB8540_FUNC_GROUPS(gpio_vbat, "gpio1_vbat_d_1", "gpio2_vbat_d_1",
+		"gpio3_vbat_d_1", "gpio4_vbat_d_1");
+AB8540_FUNC_GROUPS(pdm, "pdmclkdat_d_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct abx500_function ab8540_functions[] = {
+	FUNCTION(sysclkreq),
+	FUNCTION(gpio),
+	FUNCTION(pwmout),
+	FUNCTION(adi1),
+	FUNCTION(dmic),
+	FUNCTION(batremn),
+	FUNCTION(service),
+	FUNCTION(pwrctrl),
+	FUNCTION(pwmextvibra),
+	FUNCTION(gpio_vbat),
+	FUNCTION(pdm),
+};
+
+/*
+ * this table translates what's is in the AB8540 specification regarding the
+ * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
+ * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
+ * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
+ * AB8540 only supports DEFAULT and ALTA functions, so ALTERNATFUNC
+ * registers is not used
+ *
+ */
+
+static struct
+alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
+	/* GPIOSEL1 - bit 4-7 reserved */
+	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
+	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
+	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
+	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
+	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */
+	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */
+	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */
+	/* GPIOSEL2 - bit 0-4 reserved */
+	ALTERNATE_FUNCTIONS(9,  UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
+	ALTERNATE_FUNCTIONS(10, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO10 */
+	ALTERNATE_FUNCTIONS(11, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO11 */
+	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
+	ALTERNATE_FUNCTIONS(13, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO13 */
+	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(15,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(16,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
+	/* GPIOSEL3 - bit 4-7 reserved */
+	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(18,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(19,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(20,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21 */
+	ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22 */
+	ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23 */
+	ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24 */
+	/* GPIOSEL4 - bit 0-1 reserved */
+	ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25 */
+	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */
+	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
+	/* GPIOSEL5 - bit 0-7 reserved */
+	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
+	ALTERNATE_FUNCTIONS(34, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO34 */
+	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */
+	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */
+	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */
+	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */
+	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */
+	ALTERNATE_FUNCTIONS(40, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO40 */
+	/* GPIOSEL6 - bit 0 reserved */
+	ALTERNATE_FUNCTIONS(41, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO41 */
+	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(43,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO43, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(44,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO44, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(45,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO45, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(46,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO46, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(47,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO47, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(48,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO48, altA controlled by bit 7 */
+	/* GPIOSEL7 - bit 0-1 reserved */
+	ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */
+	ALTERNATE_FUNCTIONS(50, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO50 */
+	ALTERNATE_FUNCTIONS(51,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(52,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(53,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(54,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(55,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO55, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(56,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO56, altA controlled by bit 7 */
+};
+
+static struct pullud ab8540_pullud = {
+	.first_pin = 51,	/* GPIO1_VBAT */
+	.last_pin = 54,		/* GPIO4_VBAT */
+};
+
+/*
+ * For AB8540 Only some GPIOs are interrupt capable:
+ *	GPIO43 to GPIO44
+ *	GPIO51 to GPIO54
+ */
+static struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
+	GPIO_IRQ_CLUSTER(43, 43, AB8540_INT_GPIO43F),
+	GPIO_IRQ_CLUSTER(44, 44, AB8540_INT_GPIO44F),
+	GPIO_IRQ_CLUSTER(51, 54, AB9540_INT_GPIO51R),
+};
+
+static struct abx500_pinctrl_soc_data ab8540_soc = {
+	.gpio_ranges = ab8540_pinranges,
+	.gpio_num_ranges = ARRAY_SIZE(ab8540_pinranges),
+	.pins = ab8540_pins,
+	.npins = ARRAY_SIZE(ab8540_pins),
+	.functions = ab8540_functions,
+	.nfunctions = ARRAY_SIZE(ab8540_functions),
+	.groups = ab8540_groups,
+	.ngroups = ARRAY_SIZE(ab8540_groups),
+	.alternate_functions = ab8540_alternate_functions,
+	.pullud = &ab8540_pullud,
+	.gpio_irq_cluster = ab8540_gpio_irq_cluster,
+	.ngpio_irq_cluster = ARRAY_SIZE(ab8540_gpio_irq_cluster),
+	.irq_gpio_rising_offset = AB8540_INT_GPIO43R,
+	.irq_gpio_falling_offset = AB8540_INT_GPIO43F,
+	.irq_gpio_factor = 2,
+};
+
+void
+abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc)
+{
+	*soc = &ab8540_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab9540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab9540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-ab9540.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-ab9540.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include "pinctrl-abx500.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define ABX500_GPIO(offset)		(offset)
+
+#define AB9540_PIN_R4		ABX500_GPIO(1)
+#define AB9540_PIN_V3		ABX500_GPIO(2)
+#define AB9540_PIN_T4		ABX500_GPIO(3)
+#define AB9540_PIN_T5		ABX500_GPIO(4)
+/* hole */
+#define AB9540_PIN_B18		ABX500_GPIO(10)
+#define AB9540_PIN_C18		ABX500_GPIO(11)
+/* hole */
+#define AB9540_PIN_D18		ABX500_GPIO(13)
+#define AB9540_PIN_B19		ABX500_GPIO(14)
+#define AB9540_PIN_C19		ABX500_GPIO(15)
+#define AB9540_PIN_D19		ABX500_GPIO(16)
+#define AB9540_PIN_R3		ABX500_GPIO(17)
+#define AB9540_PIN_T2		ABX500_GPIO(18)
+#define AB9540_PIN_U2		ABX500_GPIO(19)
+#define AB9540_PIN_V2		ABX500_GPIO(20)
+#define AB9540_PIN_N17		ABX500_GPIO(21)
+#define AB9540_PIN_N16		ABX500_GPIO(22)
+#define AB9540_PIN_M19		ABX500_GPIO(23)
+#define AB9540_PIN_T3		ABX500_GPIO(24)
+#define AB9540_PIN_W2		ABX500_GPIO(25)
+/* hole */
+#define AB9540_PIN_H4		ABX500_GPIO(27)
+#define AB9540_PIN_F1		ABX500_GPIO(28)
+#define AB9540_PIN_F4		ABX500_GPIO(29)
+#define AB9540_PIN_F2		ABX500_GPIO(30)
+#define AB9540_PIN_E4		ABX500_GPIO(31)
+#define AB9540_PIN_F3		ABX500_GPIO(32)
+/* hole */
+#define AB9540_PIN_J13		ABX500_GPIO(34)
+/* hole */
+#define AB9540_PIN_L17		ABX500_GPIO(40)
+#define AB9540_PIN_L16		ABX500_GPIO(41)
+#define AB9540_PIN_W3		ABX500_GPIO(42)
+#define AB9540_PIN_N4		ABX500_GPIO(50)
+#define AB9540_PIN_G12		ABX500_GPIO(51)
+#define AB9540_PIN_E17		ABX500_GPIO(52)
+#define AB9540_PIN_D11		ABX500_GPIO(53)
+#define AB9540_PIN_M18		ABX500_GPIO(54)
+
+/* indicates the highest GPIO number */
+#define AB9540_GPIO_MAX_NUMBER	54
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc ab9540_pins[] = {
+	PINCTRL_PIN(AB9540_PIN_R4, "GPIO1_R4"),
+	PINCTRL_PIN(AB9540_PIN_V3, "GPIO2_V3"),
+	PINCTRL_PIN(AB9540_PIN_T4, "GPIO3_T4"),
+	PINCTRL_PIN(AB9540_PIN_T5, "GPIO4_T5"),
+	/* hole */
+	PINCTRL_PIN(AB9540_PIN_B18, "GPIO10_B18"),
+	PINCTRL_PIN(AB9540_PIN_C18, "GPIO11_C18"),
+	/* hole */
+	PINCTRL_PIN(AB9540_PIN_D18, "GPIO13_D18"),
+	PINCTRL_PIN(AB9540_PIN_B19, "GPIO14_B19"),
+	PINCTRL_PIN(AB9540_PIN_C19, "GPIO15_C19"),
+	PINCTRL_PIN(AB9540_PIN_D19, "GPIO16_D19"),
+	PINCTRL_PIN(AB9540_PIN_R3, "GPIO17_R3"),
+	PINCTRL_PIN(AB9540_PIN_T2, "GPIO18_T2"),
+	PINCTRL_PIN(AB9540_PIN_U2, "GPIO19_U2"),
+	PINCTRL_PIN(AB9540_PIN_V2, "GPIO20_V2"),
+	PINCTRL_PIN(AB9540_PIN_N17, "GPIO21_N17"),
+	PINCTRL_PIN(AB9540_PIN_N16, "GPIO22_N16"),
+	PINCTRL_PIN(AB9540_PIN_M19, "GPIO23_M19"),
+	PINCTRL_PIN(AB9540_PIN_T3, "GPIO24_T3"),
+	PINCTRL_PIN(AB9540_PIN_W2, "GPIO25_W2"),
+	/* hole */
+	PINCTRL_PIN(AB9540_PIN_H4, "GPIO27_H4"),
+	PINCTRL_PIN(AB9540_PIN_F1, "GPIO28_F1"),
+	PINCTRL_PIN(AB9540_PIN_F4, "GPIO29_F4"),
+	PINCTRL_PIN(AB9540_PIN_F2, "GPIO30_F2"),
+	PINCTRL_PIN(AB9540_PIN_E4, "GPIO31_E4"),
+	PINCTRL_PIN(AB9540_PIN_F3, "GPIO32_F3"),
+	/* hole */
+	PINCTRL_PIN(AB9540_PIN_J13, "GPIO34_J13"),
+	/* hole */
+	PINCTRL_PIN(AB9540_PIN_L17, "GPIO40_L17"),
+	PINCTRL_PIN(AB9540_PIN_L16, "GPIO41_L16"),
+	PINCTRL_PIN(AB9540_PIN_W3, "GPIO42_W3"),
+	PINCTRL_PIN(AB9540_PIN_N4, "GPIO50_N4"),
+	PINCTRL_PIN(AB9540_PIN_G12, "GPIO51_G12"),
+	PINCTRL_PIN(AB9540_PIN_E17, "GPIO52_E17"),
+	PINCTRL_PIN(AB9540_PIN_D11, "GPIO53_D11"),
+	PINCTRL_PIN(AB9540_PIN_M18, "GPIO60_M18"),
+};
+
+/*
+ * Maps local GPIO offsets to local pin numbers
+ */
+static const struct abx500_pinrange ab9540_pinranges[] = {
+	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(10, 2, ABX500_DEFAULT),
+	ABX500_PINRANGE(13, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(14, 12, ABX500_ALT_A),
+	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
+	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
+	ABX500_PINRANGE(40, 3, ABX500_ALT_A),
+	ABX500_PINRANGE(50, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(51, 3, ABX500_ALT_A),
+	ABX500_PINRANGE(54, 1, ABX500_DEFAULT),
+};
+
+/*
+ * Read the pin group names like this:
+ * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* default column */
+static const unsigned sysclkreq2_d_1_pins[] = { AB9540_PIN_R4 };
+static const unsigned sysclkreq3_d_1_pins[] = { AB9540_PIN_V3 };
+static const unsigned sysclkreq4_d_1_pins[] = { AB9540_PIN_T4 };
+static const unsigned sysclkreq6_d_1_pins[] = { AB9540_PIN_T5 };
+static const unsigned gpio10_d_1_pins[] = { AB9540_PIN_B18 };
+static const unsigned gpio11_d_1_pins[] = { AB9540_PIN_C18 };
+static const unsigned gpio13_d_1_pins[] = { AB9540_PIN_D18 };
+static const unsigned pwmout1_d_1_pins[] = { AB9540_PIN_B19 };
+static const unsigned pwmout2_d_1_pins[] = { AB9540_PIN_C19 };
+static const unsigned pwmout3_d_1_pins[] = { AB9540_PIN_D19 };
+/* audio data interface 1*/
+static const unsigned adi1_d_1_pins[] = { AB9540_PIN_R3, AB9540_PIN_T2,
+					AB9540_PIN_U2, AB9540_PIN_V2 };
+/* USBUICC */
+static const unsigned usbuicc_d_1_pins[] = { AB9540_PIN_N17, AB9540_PIN_N16,
+					AB9540_PIN_M19 };
+static const unsigned sysclkreq7_d_1_pins[] = { AB9540_PIN_T3 };
+static const unsigned sysclkreq8_d_1_pins[] = { AB9540_PIN_W2 };
+/* Digital microphone 1 and 2 */
+static const unsigned dmic12_d_1_pins[] = { AB9540_PIN_H4, AB9540_PIN_F1 };
+/* Digital microphone 3 and 4 */
+static const unsigned dmic34_d_1_pins[] = { AB9540_PIN_F4, AB9540_PIN_F2 };
+/* Digital microphone 5 and 6 */
+static const unsigned dmic56_d_1_pins[] = { AB9540_PIN_E4, AB9540_PIN_F3 };
+static const unsigned extcpena_d_1_pins[] = { AB9540_PIN_J13 };
+/* modem SDA/SCL */
+static const unsigned modsclsda_d_1_pins[] = { AB9540_PIN_L17, AB9540_PIN_L16 };
+static const unsigned sysclkreq5_d_1_pins[] = { AB9540_PIN_W3 };
+static const unsigned gpio50_d_1_pins[] = { AB9540_PIN_N4 };
+static const unsigned batremn_d_1_pins[] = { AB9540_PIN_G12 };
+static const unsigned resethw_d_1_pins[] = { AB9540_PIN_E17 };
+static const unsigned service_d_1_pins[] = { AB9540_PIN_D11 };
+static const unsigned gpio60_d_1_pins[] = { AB9540_PIN_M18 };
+
+/* Altfunction A column */
+static const unsigned gpio1_a_1_pins[] = { AB9540_PIN_R4 };
+static const unsigned gpio2_a_1_pins[] = { AB9540_PIN_V3 };
+static const unsigned gpio3_a_1_pins[] = { AB9540_PIN_T4 };
+static const unsigned gpio4_a_1_pins[] = { AB9540_PIN_T5 };
+static const unsigned hiqclkena_a_1_pins[] = { AB9540_PIN_B18 };
+static const unsigned pdmclk_a_1_pins[] = { AB9540_PIN_C18 };
+static const unsigned uartdata_a_1_pins[] = { AB9540_PIN_D18, AB9540_PIN_N4 };
+static const unsigned gpio14_a_1_pins[] = { AB9540_PIN_B19 };
+static const unsigned gpio15_a_1_pins[] = { AB9540_PIN_C19 };
+static const unsigned gpio16_a_1_pins[] = { AB9540_PIN_D19 };
+static const unsigned gpio17_a_1_pins[] = { AB9540_PIN_R3 };
+static const unsigned gpio18_a_1_pins[] = { AB9540_PIN_T2 };
+static const unsigned gpio19_a_1_pins[] = { AB9540_PIN_U2 };
+static const unsigned gpio20_a_1_pins[] = { AB9540_PIN_V2 };
+static const unsigned gpio21_a_1_pins[] = { AB9540_PIN_N17 };
+static const unsigned gpio22_a_1_pins[] = { AB9540_PIN_N16 };
+static const unsigned gpio23_a_1_pins[] = { AB9540_PIN_M19 };
+static const unsigned gpio24_a_1_pins[] = { AB9540_PIN_T3 };
+static const unsigned gpio25_a_1_pins[] = { AB9540_PIN_W2 };
+static const unsigned gpio27_a_1_pins[] = { AB9540_PIN_H4 };
+static const unsigned gpio28_a_1_pins[] = { AB9540_PIN_F1 };
+static const unsigned gpio29_a_1_pins[] = { AB9540_PIN_F4 };
+static const unsigned gpio30_a_1_pins[] = { AB9540_PIN_F2 };
+static const unsigned gpio31_a_1_pins[] = { AB9540_PIN_E4 };
+static const unsigned gpio32_a_1_pins[] = { AB9540_PIN_F3 };
+static const unsigned gpio34_a_1_pins[] = { AB9540_PIN_J13 };
+static const unsigned gpio40_a_1_pins[] = { AB9540_PIN_L17 };
+static const unsigned gpio41_a_1_pins[] = { AB9540_PIN_L16 };
+static const unsigned gpio42_a_1_pins[] = { AB9540_PIN_W3 };
+static const unsigned gpio51_a_1_pins[] = { AB9540_PIN_G12 };
+static const unsigned gpio52_a_1_pins[] = { AB9540_PIN_E17 };
+static const unsigned gpio53_a_1_pins[] = { AB9540_PIN_D11 };
+static const unsigned usbuiccpd_a_1_pins[] = { AB9540_PIN_M18 };
+
+/* Altfunction B colum */
+static const unsigned pdmdata_b_1_pins[] = { AB9540_PIN_B18 };
+static const unsigned pwmextvibra1_b_1_pins[] = { AB9540_PIN_D18 };
+static const unsigned pwmextvibra2_b_1_pins[] = { AB9540_PIN_N4 };
+
+/* Altfunction C column */
+static const unsigned usbvdat_c_1_pins[] = { AB9540_PIN_D18 };
+
+#define AB9540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct abx500_pingroup ab9540_groups[] = {
+	/* default column */
+	AB9540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(resethw_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(service_d_1, ABX500_DEFAULT),
+	AB9540_PIN_GROUP(gpio60_d_1, ABX500_DEFAULT),
+
+	/* Altfunction A column */
+	AB9540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(uartdata_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio21_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio22_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio23_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio24_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio25_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
+	AB9540_PIN_GROUP(usbuiccpd_a_1, ABX500_ALT_A),
+
+	/* Altfunction B column */
+	AB9540_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B),
+	AB9540_PIN_GROUP(pwmextvibra1_b_1, ABX500_ALT_B),
+	AB9540_PIN_GROUP(pwmextvibra2_b_1, ABX500_ALT_B),
+
+	/* Altfunction C column */
+	AB9540_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define AB9540_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+AB9540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
+		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1",
+		"sysclkreq7_d_1", "sysclkreq8_d_1");
+AB9540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
+		"gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1",
+		"gpio15_a_1", "gpio16_a_1", "gpio17_a_1", "gpio18_a_1",
+		"gpio19_a_1", "gpio20_a_1", "gpio21_a_1", "gpio22_a_1",
+		"gpio23_a_1", "gpio24_a_1", "gpio25_a_1", "gpio27_a_1",
+		"gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1",
+		"gpio32_a_1", "gpio34_a_1", "gpio40_a_1", "gpio41_a_1",
+		"gpio42_a_1", "gpio50_d_1", "gpio51_a_1", "gpio52_a_1",
+		"gpio53_a_1", "gpio60_d_1");
+AB9540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
+AB9540_FUNC_GROUPS(adi1, "adi1_d_1");
+AB9540_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_a_1");
+AB9540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
+AB9540_FUNC_GROUPS(extcpena, "extcpena_d_1");
+AB9540_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
+AB9540_FUNC_GROUPS(batremn, "batremn_d_1");
+AB9540_FUNC_GROUPS(resethw, "resethw_d_1");
+AB9540_FUNC_GROUPS(service, "service_d_1");
+AB9540_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1");
+AB9540_FUNC_GROUPS(pdm, "pdmdata_b_1", "pdmclk_a_1");
+AB9540_FUNC_GROUPS(uartdata, "uartdata_a_1");
+AB9540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_b_1", "pwmextvibra2_b_1");
+AB9540_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct abx500_function ab9540_functions[] = {
+	FUNCTION(sysclkreq),
+	FUNCTION(gpio),
+	FUNCTION(pwmout),
+	FUNCTION(adi1),
+	FUNCTION(usbuicc),
+	FUNCTION(dmic),
+	FUNCTION(extcpena),
+	FUNCTION(modsclsda),
+	FUNCTION(batremn),
+	FUNCTION(resethw),
+	FUNCTION(service),
+	FUNCTION(hiqclkena),
+	FUNCTION(pdm),
+	FUNCTION(uartdata),
+	FUNCTION(pwmextvibra),
+	FUNCTION(usbvdat),
+};
+
+/*
+ * this table translates what's is in the AB9540 specification regarding the
+ * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
+ * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
+ * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
+ *
+ * example :
+ *
+ *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 1, 0, 2),
+ *	means that pin AB9540_PIN_D18 (pin 13) supports 4 mux (default/ALT_A,
+ *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
+ *	select the mux. ALTA, ALTB and ALTC val indicates values to write in
+ *	ALTERNATFUNC register. We need to specifies these values as SOC
+ *	designers didn't apply the same logic on how to select mux in the
+ *	ABx500 family.
+ *
+ *	As this pins supports at least ALT_B mux, default mux is
+ *	selected by writing 1 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
+ *	default	|       1       |          0          |          0
+ *	alt_A	|       0       |          0          |          1
+ *	alt_B	|       0       |          0          |          0
+ *	alt_C	|       0       |          1          |          0
+ *
+ *	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED),
+ *	means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL
+ *	register is used to select the mux. As this pins doesn't support at
+ *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=0 | alternatfunc bit2=  | alternatfunc bit1=
+ *	default	|       0       |          0          |          0
+ *	alt_A	|       1       |          0          |          0
+ */
+
+static struct
+alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
+	/* GPIOSEL1 - bits 4-7 are reserved */
+	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
+	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
+	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
+	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
+	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */
+	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */
+	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */
+	/* GPIOSEL2 - bits 0 and 3 are reserved */
+	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
+	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(11,      2,	     1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
+	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
+	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(15,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(16,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
+	/* GPIOSEL3 - bit 1-3 reserved
+	 * pins 17 to 20 are special case, only bit 0 is used to select
+	 * alternate function for these 4 pins.
+	 * bits 1 to 3 are reserved
+	 */
+	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(21,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(22,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(23,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(24,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */
+	/* GPIOSEL4 - bit 1 reserved */
+	ALTERNATE_FUNCTIONS(25,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */
+	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
+	/* GPIOSEL5 - bit 0, 2-6 are reserved */
+	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
+	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */
+	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */
+	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */
+	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */
+	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */
+	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */
+	/* GPIOSEL6 - bit 2-7 are reserved */
+	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43 */
+	ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44 */
+	ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45 */
+	ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46 */
+	ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47 */
+	ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48 */
+	/*
+	 * GPIOSEL7 - bit 0 and 6-7 are reserved
+	 * special case with GPIO60, wich is located at offset 5 of gpiosel7
+	 * don't know why it has been called GPIO60 in AB9540 datasheet,
+	 * GPIO54 would be logical..., so at SOC point of view we consider
+	 * GPIO60 = GPIO54
+	 */
+	ALTERNATE_FUNCTIONS(49,      0, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */
+	ALTERNATE_FUNCTIONS(50,      1,	     2, UNUSED, 1, 0, 0), /* GPIO50, altA and altB controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(51,	     2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(52,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(53,	     4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(54,	     5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54 = GPIO60, altA controlled by bit 5 */
+};
+
+static struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
+	GPIO_IRQ_CLUSTER(10, 13, AB8500_INT_GPIO10R),
+	GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
+	GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
+	GPIO_IRQ_CLUSTER(50, 54, AB9540_INT_GPIO50R),
+};
+
+static struct abx500_pinctrl_soc_data ab9540_soc = {
+	.gpio_ranges = ab9540_pinranges,
+	.gpio_num_ranges = ARRAY_SIZE(ab9540_pinranges),
+	.pins = ab9540_pins,
+	.npins = ARRAY_SIZE(ab9540_pins),
+	.functions = ab9540_functions,
+	.nfunctions = ARRAY_SIZE(ab9540_functions),
+	.groups = ab9540_groups,
+	.ngroups = ARRAY_SIZE(ab9540_groups),
+	.alternate_functions = ab9540alternate_functions,
+	.gpio_irq_cluster = ab9540_gpio_irq_cluster,
+	.ngpio_irq_cluster = ARRAY_SIZE(ab9540_gpio_irq_cluster),
+	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
+	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
+	.irq_gpio_factor = 1,
+};
+
+void
+abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc)
+{
+	*soc = &ab9540_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1345 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2013
+ *
+ * Author: Patrice Chotard <patrice.chotard@st.com>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/machine.h>
+
+#include "pinctrl-abx500.h"
+#include "../core.h"
+#include "../pinconf.h"
+
+/*
+ * The AB9540 and AB8540 GPIO support are extended versions
+ * of the AB8500 GPIO support.
+ * The AB9540 supports an additional (7th) register so that
+ * more GPIO may be configured and used.
+ * The AB8540 supports 4 new gpios (GPIOx_VBAT) that have
+ * internal pull-up and pull-down capabilities.
+ */
+
+/*
+ * GPIO registers offset
+ * Bank: 0x10
+ */
+#define AB8500_GPIO_SEL1_REG	0x00
+#define AB8500_GPIO_SEL2_REG	0x01
+#define AB8500_GPIO_SEL3_REG	0x02
+#define AB8500_GPIO_SEL4_REG	0x03
+#define AB8500_GPIO_SEL5_REG	0x04
+#define AB8500_GPIO_SEL6_REG	0x05
+#define AB9540_GPIO_SEL7_REG	0x06
+
+#define AB8500_GPIO_DIR1_REG	0x10
+#define AB8500_GPIO_DIR2_REG	0x11
+#define AB8500_GPIO_DIR3_REG	0x12
+#define AB8500_GPIO_DIR4_REG	0x13
+#define AB8500_GPIO_DIR5_REG	0x14
+#define AB8500_GPIO_DIR6_REG	0x15
+#define AB9540_GPIO_DIR7_REG	0x16
+
+#define AB8500_GPIO_OUT1_REG	0x20
+#define AB8500_GPIO_OUT2_REG	0x21
+#define AB8500_GPIO_OUT3_REG	0x22
+#define AB8500_GPIO_OUT4_REG	0x23
+#define AB8500_GPIO_OUT5_REG	0x24
+#define AB8500_GPIO_OUT6_REG	0x25
+#define AB9540_GPIO_OUT7_REG	0x26
+
+#define AB8500_GPIO_PUD1_REG	0x30
+#define AB8500_GPIO_PUD2_REG	0x31
+#define AB8500_GPIO_PUD3_REG	0x32
+#define AB8500_GPIO_PUD4_REG	0x33
+#define AB8500_GPIO_PUD5_REG	0x34
+#define AB8500_GPIO_PUD6_REG	0x35
+#define AB9540_GPIO_PUD7_REG	0x36
+
+#define AB8500_GPIO_IN1_REG	0x40
+#define AB8500_GPIO_IN2_REG	0x41
+#define AB8500_GPIO_IN3_REG	0x42
+#define AB8500_GPIO_IN4_REG	0x43
+#define AB8500_GPIO_IN5_REG	0x44
+#define AB8500_GPIO_IN6_REG	0x45
+#define AB9540_GPIO_IN7_REG	0x46
+#define AB8540_GPIO_VINSEL_REG	0x47
+#define AB8540_GPIO_PULL_UPDOWN_REG	0x48
+#define AB8500_GPIO_ALTFUN_REG	0x50
+#define AB8540_GPIO_PULL_UPDOWN_MASK	0x03
+#define AB8540_GPIO_VINSEL_MASK	0x03
+#define AB8540_GPIOX_VBAT_START	51
+#define AB8540_GPIOX_VBAT_END	54
+
+#define ABX500_GPIO_INPUT	0
+#define ABX500_GPIO_OUTPUT	1
+
+struct abx500_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctldev;
+	struct abx500_pinctrl_soc_data *soc;
+	struct gpio_chip chip;
+	struct ab8500 *parent;
+	struct abx500_gpio_irq_cluster *irq_cluster;
+	int irq_cluster_size;
+};
+
+/**
+ * to_abx500_pinctrl() - get the pointer to abx500_pinctrl
+ * @chip:	Member of the structure abx500_pinctrl
+ */
+static inline struct abx500_pinctrl *to_abx500_pinctrl(struct gpio_chip *chip)
+{
+	return container_of(chip, struct abx500_pinctrl, chip);
+}
+
+static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg,
+			       unsigned offset, bool *bit)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	u8 pos = offset % 8;
+	u8 val;
+	int ret;
+
+	reg += offset / 8;
+	ret = abx500_get_register_interruptible(pct->dev,
+						AB8500_MISC, reg, &val);
+
+	*bit = !!(val & BIT(pos));
+
+	if (ret < 0)
+		dev_err(pct->dev,
+			"%s read reg =%x, offset=%x failed (%d)\n",
+			__func__, reg, offset, ret);
+
+	return ret;
+}
+
+static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
+				unsigned offset, int val)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	u8 pos = offset % 8;
+	int ret;
+
+	reg += offset / 8;
+	ret = abx500_mask_and_set_register_interruptible(pct->dev,
+				AB8500_MISC, reg, BIT(pos), val << pos);
+	if (ret < 0)
+		dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n",
+				__func__, reg, offset, ret);
+
+	return ret;
+}
+
+/**
+ * abx500_gpio_get() - Get the particular GPIO value
+ * @chip:	Gpio device
+ * @offset:	GPIO number to read
+ */
+static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	bool bit;
+	bool is_out;
+	u8 gpio_offset = offset - 1;
+	int ret;
+
+	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
+			gpio_offset, &is_out);
+	if (ret < 0)
+		goto out;
+
+	if (is_out)
+		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG,
+				gpio_offset, &bit);
+	else
+		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
+				gpio_offset, &bit);
+out:
+	if (ret < 0) {
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return bit;
+}
+
+static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	int ret;
+
+	ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+	if (ret < 0)
+		dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
+}
+
+static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
+				  enum abx500_gpio_pull_updown *pull_updown)
+{
+	u8 pos;
+	u8 val;
+	int ret;
+	struct pullud *pullud;
+
+	if (!pct->soc->pullud) {
+		dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
+				__func__);
+		ret = -EPERM;
+		goto out;
+	}
+
+	pullud = pct->soc->pullud;
+
+	if ((offset < pullud->first_pin)
+		|| (offset > pullud->last_pin)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = abx500_get_register_interruptible(pct->dev,
+			AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val);
+
+	pos = (offset - pullud->first_pin) << 1;
+	*pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK;
+
+out:
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
+				  int offset, enum abx500_gpio_pull_updown val)
+{
+	u8 pos;
+	int ret;
+	struct pullud *pullud;
+
+	if (!pct->soc->pullud) {
+		dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
+				__func__);
+		ret = -EPERM;
+		goto out;
+	}
+
+	pullud = pct->soc->pullud;
+
+	if ((offset < pullud->first_pin)
+		|| (offset > pullud->last_pin)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	pos = (offset - pullud->first_pin) << 1;
+
+	ret = abx500_mask_and_set_register_interruptible(pct->dev,
+			AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG,
+			AB8540_GPIO_PULL_UPDOWN_MASK << pos, val << pos);
+
+out:
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	struct pullud *pullud = pct->soc->pullud;
+
+	return (pullud &&
+		gpio >= pullud->first_pin &&
+		gpio <= pullud->last_pin);
+}
+
+static int abx500_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset,
+					int val)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	unsigned gpio;
+	int ret;
+
+	/* set direction as output */
+	ret = abx500_gpio_set_bits(chip,
+				AB8500_GPIO_DIR1_REG,
+				offset,
+				ABX500_GPIO_OUTPUT);
+	if (ret < 0)
+		goto out;
+
+	/* disable pull down */
+	ret = abx500_gpio_set_bits(chip,
+				AB8500_GPIO_PUD1_REG,
+				offset,
+				ABX500_GPIO_PULL_NONE);
+	if (ret < 0)
+		goto out;
+
+	/* if supported, disable both pull down and pull up */
+	gpio = offset + 1;
+	if (abx500_pullud_supported(chip, gpio)) {
+		ret = abx500_set_pull_updown(pct,
+				gpio,
+				ABX500_GPIO_PULL_NONE);
+	}
+out:
+	if (ret < 0) {
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+		return ret;
+	}
+
+	/* set the output as 1 or 0 */
+	return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+}
+
+static int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	/* set the register as input */
+	return abx500_gpio_set_bits(chip,
+				AB8500_GPIO_DIR1_REG,
+				offset,
+				ABX500_GPIO_INPUT);
+}
+
+static int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	/* The AB8500 GPIO numbers are off by one */
+	int gpio = offset + 1;
+	int hwirq;
+	int i;
+
+	for (i = 0; i < pct->irq_cluster_size; i++) {
+		struct abx500_gpio_irq_cluster *cluster =
+			&pct->irq_cluster[i];
+
+		if (gpio >= cluster->start && gpio <= cluster->end) {
+			/*
+			 * The ABx500 GPIO's associated IRQs are clustered together
+			 * throughout the interrupt numbers at irregular intervals.
+			 * To solve this quandry, we have placed the read-in values
+			 * into the cluster information table.
+			 */
+			hwirq = gpio - cluster->start + cluster->to_irq;
+			return irq_create_mapping(pct->parent->domain, hwirq);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+			   unsigned gpio, int alt_setting)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	struct alternate_functions af = pct->soc->alternate_functions[gpio];
+	int ret;
+	int val;
+	unsigned offset;
+
+	const char *modes[] = {
+		[ABX500_DEFAULT]	= "default",
+		[ABX500_ALT_A]		= "altA",
+		[ABX500_ALT_B]		= "altB",
+		[ABX500_ALT_C]		= "altC",
+	};
+
+	/* sanity check */
+	if (((alt_setting == ABX500_ALT_A) && (af.gpiosel_bit == UNUSED)) ||
+	    ((alt_setting == ABX500_ALT_B) && (af.alt_bit1 == UNUSED)) ||
+	    ((alt_setting == ABX500_ALT_C) && (af.alt_bit2 == UNUSED))) {
+		dev_dbg(pct->dev, "pin %d doesn't support %s mode\n", gpio,
+				modes[alt_setting]);
+		return -EINVAL;
+	}
+
+	/* on ABx5xx, there is no GPIO0, so adjust the offset */
+	offset = gpio - 1;
+
+	switch (alt_setting) {
+	case ABX500_DEFAULT:
+		/*
+		 * for ABx5xx family, default mode is always selected by
+		 * writing 0 to GPIOSELx register, except for pins which
+		 * support at least ALT_B mode, default mode is selected
+		 * by writing 1 to GPIOSELx register
+		 */
+		val = 0;
+		if (af.alt_bit1 != UNUSED)
+			val++;
+
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
+					   offset, val);
+		break;
+
+	case ABX500_ALT_A:
+		/*
+		 * for ABx5xx family, alt_a mode is always selected by
+		 * writing 1 to GPIOSELx register, except for pins which
+		 * support at least ALT_B mode, alt_a mode is selected
+		 * by writing 0 to GPIOSELx register and 0 in ALTFUNC
+		 * register
+		 */
+		if (af.alt_bit1 != UNUSED) {
+			ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
+					offset, 0);
+			if (ret < 0)
+				goto out;
+
+			ret = abx500_gpio_set_bits(chip,
+					AB8500_GPIO_ALTFUN_REG,
+					af.alt_bit1,
+					!!(af.alta_val & BIT(0)));
+			if (ret < 0)
+				goto out;
+
+			if (af.alt_bit2 != UNUSED)
+				ret = abx500_gpio_set_bits(chip,
+					AB8500_GPIO_ALTFUN_REG,
+					af.alt_bit2,
+					!!(af.alta_val & BIT(1)));
+		} else
+			ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
+					offset, 1);
+		break;
+
+	case ABX500_ALT_B:
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
+				offset, 0);
+		if (ret < 0)
+			goto out;
+
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
+				af.alt_bit1, !!(af.altb_val & BIT(0)));
+		if (ret < 0)
+			goto out;
+
+		if (af.alt_bit2 != UNUSED)
+			ret = abx500_gpio_set_bits(chip,
+					AB8500_GPIO_ALTFUN_REG,
+					af.alt_bit2,
+					!!(af.altb_val & BIT(1)));
+		break;
+
+	case ABX500_ALT_C:
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
+				offset, 0);
+		if (ret < 0)
+			goto out;
+
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
+				af.alt_bit2, !!(af.altc_val & BIT(0)));
+		if (ret < 0)
+			goto out;
+
+		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
+				af.alt_bit2, !!(af.altc_val & BIT(1)));
+		break;
+
+	default:
+		dev_dbg(pct->dev, "unknow alt_setting %d\n", alt_setting);
+
+		return -EINVAL;
+	}
+out:
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+			  unsigned gpio)
+{
+	u8 mode;
+	bool bit_mode;
+	bool alt_bit1;
+	bool alt_bit2;
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	struct alternate_functions af = pct->soc->alternate_functions[gpio];
+	/* on ABx5xx, there is no GPIO0, so adjust the offset */
+	unsigned offset = gpio - 1;
+	int ret;
+
+	/*
+	 * if gpiosel_bit is set to unused,
+	 * it means no GPIO or special case
+	 */
+	if (af.gpiosel_bit == UNUSED)
+		return ABX500_DEFAULT;
+
+	/* read GpioSelx register */
+	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
+			af.gpiosel_bit, &bit_mode);
+	if (ret < 0)
+		goto out;
+
+	mode = bit_mode;
+
+	/* sanity check */
+	if ((af.alt_bit1 < UNUSED) || (af.alt_bit1 > 7) ||
+	    (af.alt_bit2 < UNUSED) || (af.alt_bit2 > 7)) {
+		dev_err(pct->dev,
+			"alt_bitX value not in correct range (-1 to 7)\n");
+		return -EINVAL;
+	}
+
+	/* if alt_bit2 is used, alt_bit1 must be used too */
+	if ((af.alt_bit2 != UNUSED) && (af.alt_bit1 == UNUSED)) {
+		dev_err(pct->dev,
+			"if alt_bit2 is used, alt_bit1 can't be unused\n");
+		return -EINVAL;
+	}
+
+	/* check if pin use AlternateFunction register */
+	if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED))
+		return mode;
+	/*
+	 * if pin GPIOSEL bit is set and pin supports alternate function,
+	 * it means DEFAULT mode
+	 */
+	if (mode)
+		return ABX500_DEFAULT;
+
+	/*
+	 * pin use the AlternatFunction register
+	 * read alt_bit1 value
+	 */
+	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
+			    af.alt_bit1, &alt_bit1);
+	if (ret < 0)
+		goto out;
+
+	if (af.alt_bit2 != UNUSED) {
+		/* read alt_bit2 value */
+		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
+				af.alt_bit2,
+				&alt_bit2);
+		if (ret < 0)
+			goto out;
+	} else
+		alt_bit2 = 0;
+
+	mode = (alt_bit2 << 1) + alt_bit1;
+	if (mode == af.alta_val)
+		return ABX500_ALT_A;
+	else if (mode == af.altb_val)
+		return ABX500_ALT_B;
+	else
+		return ABX500_ALT_C;
+
+out:
+	dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+	return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+static void abx500_gpio_dbg_show_one(struct seq_file *s,
+				     struct pinctrl_dev *pctldev,
+				     struct gpio_chip *chip,
+				     unsigned offset, unsigned gpio)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	const char *label = gpiochip_is_requested(chip, offset - 1);
+	u8 gpio_offset = offset - 1;
+	int mode = -1;
+	bool is_out;
+	bool pd;
+	enum abx500_gpio_pull_updown pud = 0;
+	int ret;
+
+	const char *modes[] = {
+		[ABX500_DEFAULT]	= "default",
+		[ABX500_ALT_A]		= "altA",
+		[ABX500_ALT_B]		= "altB",
+		[ABX500_ALT_C]		= "altC",
+	};
+
+	const char *pull_up_down[] = {
+		[ABX500_GPIO_PULL_DOWN]		= "pull down",
+		[ABX500_GPIO_PULL_NONE]		= "pull none",
+		[ABX500_GPIO_PULL_NONE + 1]	= "pull none",
+		[ABX500_GPIO_PULL_UP]		= "pull up",
+	};
+
+	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
+			gpio_offset, &is_out);
+	if (ret < 0)
+		goto out;
+
+	seq_printf(s, " gpio-%-3d (%-20.20s) %-3s",
+		   gpio, label ?: "(none)",
+		   is_out ? "out" : "in ");
+
+	if (!is_out) {
+		if (abx500_pullud_supported(chip, offset)) {
+			ret = abx500_get_pull_updown(pct, offset, &pud);
+			if (ret < 0)
+				goto out;
+
+			seq_printf(s, " %-9s", pull_up_down[pud]);
+		} else {
+			ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
+					gpio_offset, &pd);
+			if (ret < 0)
+				goto out;
+
+			seq_printf(s, " %-9s", pull_up_down[pd]);
+		}
+	} else
+		seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
+
+	mode = abx500_get_mode(pctldev, chip, offset);
+
+	seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
+
+out:
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+}
+
+static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	unsigned i;
+	unsigned gpio = chip->base;
+	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
+	struct pinctrl_dev *pctldev = pct->pctldev;
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		/* On AB8500, there is no GPIO0, the first is the GPIO 1 */
+		abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio);
+		seq_printf(s, "\n");
+	}
+}
+
+#else
+static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
+					    struct pinctrl_dev *pctldev,
+					    struct gpio_chip *chip,
+					    unsigned offset, unsigned gpio)
+{
+}
+#define abx500_gpio_dbg_show	NULL
+#endif
+
+static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static struct gpio_chip abx500gpio_chip = {
+	.label			= "abx500-gpio",
+	.owner			= THIS_MODULE,
+	.request		= abx500_gpio_request,
+	.free			= abx500_gpio_free,
+	.direction_input	= abx500_gpio_direction_input,
+	.get			= abx500_gpio_get,
+	.direction_output	= abx500_gpio_direction_output,
+	.set			= abx500_gpio_set,
+	.to_irq			= abx500_gpio_to_irq,
+	.dbg_show		= abx500_gpio_dbg_show,
+};
+
+static int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	return pct->soc->nfunctions;
+}
+
+static const char *abx500_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					 unsigned function)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	return pct->soc->functions[function].name;
+}
+
+static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+				      unsigned function,
+				      const char * const **groups,
+				      unsigned * const num_groups)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pct->soc->functions[function].groups;
+	*num_groups = pct->soc->functions[function].ngroups;
+
+	return 0;
+}
+
+static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
+			     unsigned group)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_chip *chip = &pct->chip;
+	const struct abx500_pingroup *g;
+	int i;
+	int ret = 0;
+
+	g = &pct->soc->groups[group];
+	if (g->altsetting < 0)
+		return -EINVAL;
+
+	dev_dbg(pct->dev, "enable group %s, %u pins\n", g->name, g->npins);
+
+	for (i = 0; i < g->npins; i++) {
+		dev_dbg(pct->dev, "setting pin %d to altsetting %d\n",
+			g->pins[i], g->altsetting);
+
+		ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting);
+	}
+
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
+			       struct pinctrl_gpio_range *range,
+			       unsigned offset)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	const struct abx500_pinrange *p;
+	int ret;
+	int i;
+
+	/*
+	 * Different ranges have different ways to enable GPIO function on a
+	 * pin, so refer back to our local range type, where we handily define
+	 * what altfunc enables GPIO for a certain pin.
+	 */
+	for (i = 0; i < pct->soc->gpio_num_ranges; i++) {
+		p = &pct->soc->gpio_ranges[i];
+		if ((offset >= p->offset) &&
+		    (offset < (p->offset + p->npins)))
+		  break;
+	}
+
+	if (i == pct->soc->gpio_num_ranges) {
+		dev_err(pct->dev, "%s failed to locate range\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n",
+		p->altfunc, offset);
+
+	ret = abx500_set_mode(pct->pctldev, &pct->chip,
+			      offset, p->altfunc);
+	if (ret < 0)
+		dev_err(pct->dev, "%s setting altfunc failed\n", __func__);
+
+	return ret;
+}
+
+static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+}
+
+static const struct pinmux_ops abx500_pinmux_ops = {
+	.get_functions_count = abx500_pmx_get_funcs_cnt,
+	.get_function_name = abx500_pmx_get_func_name,
+	.get_function_groups = abx500_pmx_get_func_groups,
+	.enable = abx500_pmx_enable,
+	.gpio_request_enable = abx500_gpio_request_enable,
+	.gpio_disable_free = abx500_gpio_disable_free,
+};
+
+static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	return pct->soc->ngroups;
+}
+
+static const char *abx500_get_group_name(struct pinctrl_dev *pctldev,
+					 unsigned selector)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	return pct->soc->groups[selector].name;
+}
+
+static int abx500_get_group_pins(struct pinctrl_dev *pctldev,
+				 unsigned selector,
+				 const unsigned **pins,
+				 unsigned *num_pins)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = pct->soc->groups[selector].pins;
+	*num_pins = pct->soc->groups[selector].npins;
+
+	return 0;
+}
+
+static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
+				struct seq_file *s, unsigned offset)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_chip *chip = &pct->chip;
+
+	abx500_gpio_dbg_show_one(s, pctldev, chip, offset,
+				 chip->base + offset - 1);
+}
+
+static void abx500_dt_free_map(struct pinctrl_dev *pctldev,
+		struct pinctrl_map *map, unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++)
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+			kfree(map[i].data.configs.configs);
+	kfree(map);
+}
+
+static int abx500_dt_reserve_map(struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps,
+		unsigned reserve)
+{
+	unsigned old_num = *reserved_maps;
+	unsigned new_num = *num_maps + reserve;
+	struct pinctrl_map *new_map;
+
+	if (old_num >= new_num)
+		return 0;
+
+	new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
+
+	*map = new_map;
+	*reserved_maps = new_num;
+
+	return 0;
+}
+
+static int abx500_dt_add_map_mux(struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps, const char *group,
+		const char *function)
+{
+	if (*num_maps == *reserved_maps)
+		return -ENOSPC;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+	(*map)[*num_maps].data.mux.group = group;
+	(*map)[*num_maps].data.mux.function = function;
+	(*num_maps)++;
+
+	return 0;
+}
+
+static int abx500_dt_add_map_configs(struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps, const char *group,
+		unsigned long *configs, unsigned num_configs)
+{
+	unsigned long *dup_configs;
+
+	if (*num_maps == *reserved_maps)
+		return -ENOSPC;
+
+	dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+			      GFP_KERNEL);
+	if (!dup_configs)
+		return -ENOMEM;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
+
+	(*map)[*num_maps].data.configs.group_or_pin = group;
+	(*map)[*num_maps].data.configs.configs = dup_configs;
+	(*map)[*num_maps].data.configs.num_configs = num_configs;
+	(*num_maps)++;
+
+	return 0;
+}
+
+static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev,
+					const char *pin_name)
+{
+	int i, pin_number;
+	struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
+		for (i = 0; i < npct->soc->npins; i++)
+			if (npct->soc->pins[i].number == pin_number)
+				return npct->soc->pins[i].name;
+	return NULL;
+}
+
+static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+		struct device_node *np,
+		struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps)
+{
+	int ret;
+	const char *function = NULL;
+	unsigned long *configs;
+	unsigned int nconfigs = 0;
+	bool has_config = 0;
+	unsigned reserve = 0;
+	struct property *prop;
+	const char *group, *gpio_name;
+	struct device_node *np_config;
+
+	ret = of_property_read_string(np, "ste,function", &function);
+	if (ret >= 0)
+		reserve = 1;
+
+	ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
+	if (nconfigs)
+		has_config = 1;
+
+	np_config = of_parse_phandle(np, "ste,config", 0);
+	if (np_config) {
+		ret = pinconf_generic_parse_dt_config(np_config, &configs,
+				&nconfigs);
+		if (ret)
+			goto exit;
+		has_config |= nconfigs;
+	}
+
+	ret = of_property_count_strings(np, "ste,pins");
+	if (ret < 0)
+		goto exit;
+
+	if (has_config)
+		reserve++;
+
+	reserve *= ret;
+
+	ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_string(np, "ste,pins", prop, group) {
+		if (function) {
+			ret = abx500_dt_add_map_mux(map, reserved_maps,
+					num_maps, group, function);
+			if (ret < 0)
+				goto exit;
+		}
+		if (has_config) {
+			gpio_name = abx500_find_pin_name(pctldev, group);
+
+			ret = abx500_dt_add_map_configs(map, reserved_maps,
+					num_maps, gpio_name, configs, 1);
+			if (ret < 0)
+				goto exit;
+		}
+
+	}
+exit:
+	return ret;
+}
+
+static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
+				 struct device_node *np_config,
+				 struct pinctrl_map **map, unsigned *num_maps)
+{
+	unsigned reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	for_each_child_of_node(np_config, np) {
+		ret = abx500_dt_subnode_to_map(pctldev, np, map,
+				&reserved_maps, num_maps);
+		if (ret < 0) {
+			abx500_dt_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct pinctrl_ops abx500_pinctrl_ops = {
+	.get_groups_count = abx500_get_groups_cnt,
+	.get_group_name = abx500_get_group_name,
+	.get_group_pins = abx500_get_group_pins,
+	.pin_dbg_show = abx500_pin_dbg_show,
+	.dt_node_to_map = abx500_dt_node_to_map,
+	.dt_free_map = abx500_dt_free_map,
+};
+
+static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
+			  unsigned pin,
+			  unsigned long *config)
+{
+	return -ENOSYS;
+}
+
+static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
+			  unsigned pin,
+			  unsigned long *configs,
+			  unsigned num_configs)
+{
+	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_chip *chip = &pct->chip;
+	unsigned offset;
+	int ret = -EINVAL;
+	int i;
+	enum pin_config_param param;
+	enum pin_config_param argument;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		argument = pinconf_to_config_argument(configs[i]);
+
+		dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n",
+			pin, configs[i],
+			(param == PIN_CONFIG_OUTPUT) ? "output " : "input",
+			(param == PIN_CONFIG_OUTPUT) ?
+			(argument ? "high" : "low") :
+			(argument ? "pull up" : "pull down"));
+
+		/* on ABx500, there is no GPIO0, so adjust the offset */
+		offset = pin - 1;
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			ret = abx500_gpio_direction_input(chip, offset);
+			if (ret < 0)
+				goto out;
+			/*
+			 * Some chips only support pull down, while some
+			 * actually support both pull up and pull down. Such
+			 * chips have a "pullud" range specified for the pins
+			 * that support both features. If the pin is not
+			 * within that range, we fall back to the old bit set
+			 * that only support pull down.
+			 */
+			if (abx500_pullud_supported(chip, pin))
+				ret = abx500_set_pull_updown(pct,
+					pin,
+					ABX500_GPIO_PULL_NONE);
+			else
+				/* Chip only supports pull down */
+				ret = abx500_gpio_set_bits(chip,
+					AB8500_GPIO_PUD1_REG, offset,
+					ABX500_GPIO_PULL_NONE);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			ret = abx500_gpio_direction_input(chip, offset);
+			if (ret < 0)
+				goto out;
+			/*
+			 * if argument = 1 set the pull down
+			 * else clear the pull down
+			 * Some chips only support pull down, while some
+			 * actually support both pull up and pull down. Such
+			 * chips have a "pullud" range specified for the pins
+			 * that support both features. If the pin is not
+			 * within that range, we fall back to the old bit set
+			 * that only support pull down.
+			 */
+			if (abx500_pullud_supported(chip, pin))
+				ret = abx500_set_pull_updown(pct,
+					pin,
+					argument ? ABX500_GPIO_PULL_DOWN :
+					ABX500_GPIO_PULL_NONE);
+			else
+				/* Chip only supports pull down */
+				ret = abx500_gpio_set_bits(chip,
+				AB8500_GPIO_PUD1_REG,
+					offset,
+					argument ? ABX500_GPIO_PULL_DOWN :
+					ABX500_GPIO_PULL_NONE);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			ret = abx500_gpio_direction_input(chip, offset);
+			if (ret < 0)
+				goto out;
+			/*
+			 * if argument = 1 set the pull up
+			 * else clear the pull up
+			 */
+			ret = abx500_gpio_direction_input(chip, offset);
+			/*
+			 * Some chips only support pull down, while some
+			 * actually support both pull up and pull down. Such
+			 * chips have a "pullud" range specified for the pins
+			 * that support both features. If the pin is not
+			 * within that range, do nothing
+			 */
+			if (abx500_pullud_supported(chip, pin))
+				ret = abx500_set_pull_updown(pct,
+					pin,
+					argument ? ABX500_GPIO_PULL_UP :
+					ABX500_GPIO_PULL_NONE);
+			break;
+
+		case PIN_CONFIG_OUTPUT:
+			ret = abx500_gpio_direction_output(chip, offset,
+				argument);
+			break;
+
+		default:
+			dev_err(chip->dev, "illegal configuration requested\n");
+		}
+	} /* for each config */
+out:
+	if (ret < 0)
+		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
+
+	return ret;
+}
+
+static const struct pinconf_ops abx500_pinconf_ops = {
+	.pin_config_get = abx500_pin_config_get,
+	.pin_config_set = abx500_pin_config_set,
+};
+
+static struct pinctrl_desc abx500_pinctrl_desc = {
+	.name = "pinctrl-abx500",
+	.pctlops = &abx500_pinctrl_ops,
+	.pmxops = &abx500_pinmux_ops,
+	.confops = &abx500_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc)
+{
+	unsigned int lowest = 0;
+	unsigned int highest = 0;
+	unsigned int npins = 0;
+	int i;
+
+	/*
+	 * Compute number of GPIOs from the last SoC gpio range descriptors
+	 * These ranges may include "holes" but the GPIO number space shall
+	 * still be homogeneous, so we need to detect and account for any
+	 * such holes so that these are included in the number of GPIO pins.
+	 */
+	for (i = 0; i < soc->gpio_num_ranges; i++) {
+		unsigned gstart;
+		unsigned gend;
+		const struct abx500_pinrange *p;
+
+		p = &soc->gpio_ranges[i];
+		gstart = p->offset;
+		gend = p->offset + p->npins - 1;
+
+		if (i == 0) {
+			/* First iteration, set start values */
+			lowest = gstart;
+			highest = gend;
+		} else {
+			if (gstart < lowest)
+				lowest = gstart;
+			if (gend > highest)
+				highest = gend;
+		}
+	}
+	/* this gives the absolute number of pins */
+	npins = highest - lowest + 1;
+	return npins;
+}
+
+static const struct of_device_id abx500_gpio_match[] = {
+	{ .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, },
+	{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
+	{ .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
+	{ .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
+	{ }
+};
+
+static int abx500_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
+	struct abx500_pinctrl *pct;
+	unsigned int id = -1;
+	int ret, err;
+	int i;
+
+	if (!np) {
+		dev_err(&pdev->dev, "gpio dt node missing\n");
+		return -ENODEV;
+	}
+
+	pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl),
+				   GFP_KERNEL);
+	if (pct == NULL) {
+		dev_err(&pdev->dev,
+			"failed to allocate memory for pct\n");
+		return -ENOMEM;
+	}
+
+	pct->dev = &pdev->dev;
+	pct->parent = dev_get_drvdata(pdev->dev.parent);
+	pct->chip = abx500gpio_chip;
+	pct->chip.dev = &pdev->dev;
+	pct->chip.base = -1; /* Dynamic allocation */
+
+	match = of_match_device(abx500_gpio_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "gpio dt not matching\n");
+		return -ENODEV;
+	}
+	id = (unsigned long)match->data;
+
+	/* Poke in other ASIC variants here */
+	switch (id) {
+	case PINCTRL_AB8500:
+		abx500_pinctrl_ab8500_init(&pct->soc);
+		break;
+	case PINCTRL_AB8540:
+		abx500_pinctrl_ab8540_init(&pct->soc);
+		break;
+	case PINCTRL_AB9540:
+		abx500_pinctrl_ab9540_init(&pct->soc);
+		break;
+	case PINCTRL_AB8505:
+		abx500_pinctrl_ab8505_init(&pct->soc);
+		break;
+	default:
+		dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id);
+		return -EINVAL;
+	}
+
+	if (!pct->soc) {
+		dev_err(&pdev->dev, "Invalid SOC data\n");
+		return -EINVAL;
+	}
+
+	pct->chip.ngpio = abx500_get_gpio_num(pct->soc);
+	pct->irq_cluster = pct->soc->gpio_irq_cluster;
+	pct->irq_cluster_size = pct->soc->ngpio_irq_cluster;
+
+	ret = gpiochip_add(&pct->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+		return ret;
+	}
+	dev_info(&pdev->dev, "added gpiochip\n");
+
+	abx500_pinctrl_desc.pins = pct->soc->pins;
+	abx500_pinctrl_desc.npins = pct->soc->npins;
+	pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct);
+	if (!pct->pctldev) {
+		dev_err(&pdev->dev,
+			"could not register abx500 pinctrl driver\n");
+		ret = -EINVAL;
+		goto out_rem_chip;
+	}
+	dev_info(&pdev->dev, "registered pin controller\n");
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < pct->soc->gpio_num_ranges; i++) {
+		const struct abx500_pinrange *p = &pct->soc->gpio_ranges[i];
+
+		ret = gpiochip_add_pin_range(&pct->chip,
+					dev_name(&pdev->dev),
+					p->offset - 1, p->offset, p->npins);
+		if (ret < 0)
+			goto out_rem_chip;
+	}
+
+	platform_set_drvdata(pdev, pct);
+	dev_info(&pdev->dev, "initialized abx500 pinctrl driver\n");
+
+	return 0;
+
+out_rem_chip:
+	err = gpiochip_remove(&pct->chip);
+	if (err)
+		dev_info(&pdev->dev, "failed to remove gpiochip\n");
+
+	return ret;
+}
+
+/**
+ * abx500_gpio_remove() - remove Ab8500-gpio driver
+ * @pdev:	Platform device registered
+ */
+static int abx500_gpio_remove(struct platform_device *pdev)
+{
+	struct abx500_pinctrl *pct = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&pct->chip);
+	if (ret < 0) {
+		dev_err(pct->dev, "unable to remove gpiochip: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver abx500_gpio_driver = {
+	.driver = {
+		.name = "abx500-gpio",
+		.owner = THIS_MODULE,
+		.of_match_table = abx500_gpio_match,
+	},
+	.probe = abx500_gpio_probe,
+	.remove = abx500_gpio_remove,
+};
+
+static int __init abx500_gpio_init(void)
+{
+	return platform_driver_register(&abx500_gpio_driver);
+}
+core_initcall(abx500_gpio_init);
+
+MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>");
+MODULE_DESCRIPTION("Driver allows to use AxB5xx unused pins to be used as GPIO");
+MODULE_ALIAS("platform:abx500-gpio");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.h
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-abx500.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,246 @@
+#ifndef PINCTRL_PINCTRL_ABx500_H
+#define PINCTRL_PINCTRL_ABx500_H
+
+/* Package definitions */
+#define PINCTRL_AB8500	0
+#define PINCTRL_AB8540	1
+#define PINCTRL_AB9540	2
+#define PINCTRL_AB8505	3
+
+/* pins alternate function */
+enum abx500_pin_func {
+	ABX500_DEFAULT,
+	ABX500_ALT_A,
+	ABX500_ALT_B,
+	ABX500_ALT_C,
+};
+
+enum abx500_gpio_pull_updown {
+	ABX500_GPIO_PULL_DOWN = 0x0,
+	ABX500_GPIO_PULL_NONE = 0x1,
+	ABX500_GPIO_PULL_UP = 0x3,
+};
+
+enum abx500_gpio_vinsel {
+	ABX500_GPIO_VINSEL_VBAT = 0x0,
+	ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
+	ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
+};
+
+/**
+ * struct abx500_function - ABx500 pinctrl mux function
+ * @name: The name of the function, exported to pinctrl core.
+ * @groups: An array of pin groups that may select this function.
+ * @ngroups: The number of entries in @groups.
+ */
+struct abx500_function {
+	const char *name;
+	const char * const *groups;
+	unsigned ngroups;
+};
+
+/**
+ * struct abx500_pingroup - describes a ABx500 pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ * @altsetting: the altsetting to apply to all pins in this group to
+ *	configure them to be used by a function
+ */
+struct abx500_pingroup {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned npins;
+	int altsetting;
+};
+
+#define ALTERNATE_FUNCTIONS(pin, sel_bit, alt1, alt2, alta, altb, altc)	\
+{									\
+	.pin_number = pin,						\
+	.gpiosel_bit = sel_bit,						\
+	.alt_bit1 = alt1,						\
+	.alt_bit2 = alt2,						\
+	.alta_val = alta,						\
+	.altb_val = altb,						\
+	.altc_val = altc,						\
+}
+
+#define UNUSED -1
+/**
+ * struct alternate_functions
+ * @pin_number:		The pin number
+ * @gpiosel_bit:	Control bit in GPIOSEL register,
+ * @alt_bit1:		First AlternateFunction bit used to select the
+ *			alternate function
+ * @alt_bit2:		Second AlternateFunction bit used to select the
+ *			alternate function
+ *
+ *			these 3 following fields are necessary due to none
+ *			coherency on how to select the altA, altB and altC
+ *			function between the ABx500 SOC family when using
+ *			alternatfunc register.
+ * @alta_val:		value to write in alternatfunc to select altA function
+ * @altb_val:		value to write in alternatfunc to select altB function
+ * @altc_val:		value to write in alternatfunc to select altC function
+ */
+struct alternate_functions {
+	unsigned pin_number;
+	s8 gpiosel_bit;
+	s8 alt_bit1;
+	s8 alt_bit2;
+	u8 alta_val;
+	u8 altb_val;
+	u8 altc_val;
+};
+
+/**
+ * struct pullud - specific pull up/down feature
+ * @first_pin:		The pin number of the first pins which support
+ *			specific pull up/down
+ * @last_pin:		The pin number of the last pins
+ */
+struct pullud {
+	unsigned first_pin;
+	unsigned last_pin;
+};
+
+#define GPIO_IRQ_CLUSTER(a, b, c)	\
+{					\
+	.start = a,			\
+	.end = b,			\
+	.to_irq = c,			\
+}
+
+/**
+ * struct abx500_gpio_irq_cluster - indicates GPIOs which are interrupt
+ *			capable
+ * @start:		The pin number of the first pin interrupt capable
+ * @end:		The pin number of the last pin interrupt capable
+ * @to_irq:		The ABx500 GPIO's associated IRQs are clustered
+ *                      together throughout the interrupt numbers at irregular
+ *                      intervals. To solve this quandary, we will place the
+ *                      read-in values into the cluster information table
+ */
+
+struct abx500_gpio_irq_cluster {
+	int start;
+	int end;
+	int to_irq;
+};
+
+/**
+ * struct abx500_pinrange - map pin numbers to GPIO offsets
+ * @offset:		offset into the GPIO local numberspace, incidentally
+ *			identical to the offset into the local pin numberspace
+ * @npins:		number of pins to map from both offsets
+ * @altfunc:		altfunc setting to be used to enable GPIO on a pin in
+ *			this range (may vary)
+ */
+struct abx500_pinrange {
+	unsigned int offset;
+	unsigned int npins;
+	int altfunc;
+};
+
+#define ABX500_PINRANGE(a, b, c) { .offset = a, .npins = b, .altfunc = c }
+
+/**
+ * struct abx500_pinctrl_soc_data - ABx500 pin controller per-SoC configuration
+ * @gpio_ranges:	An array of GPIO ranges for this SoC
+ * @gpio_num_ranges:	The number of GPIO ranges for this SoC
+ * @pins:		An array describing all pins the pin controller affects.
+ *			All pins which are also GPIOs must be listed first within the
+ *			array, and be numbered identically to the GPIO controller's
+ *			numbering.
+ * @npins:		The number of entries in @pins.
+ * @functions:		The functions supported on this SoC.
+ * @nfunction:		The number of entries in @functions.
+ * @groups:		An array describing all pin groups the pin SoC supports.
+ * @ngroups:		The number of entries in @groups.
+ * @alternate_functions: array describing pins which supports alternate and
+ *			how to set it.
+ * @pullud:		array describing pins which supports pull up/down
+ *			specific registers.
+ * @gpio_irq_cluster:	An array of GPIO interrupt capable for this SoC
+ * @ngpio_irq_cluster:	The number of GPIO inetrrupt capable for this SoC
+ * @irq_gpio_rising_offset: Interrupt offset used as base to compute specific
+ *			setting strategy of the rising interrupt line
+ * @irq_gpio_falling_offset: Interrupt offset used as base to compute specific
+ *			setting strategy of the falling interrupt line
+ * @irq_gpio_factor:	Factor used to compute specific setting strategy of
+ *			the interrupt line
+ */
+
+struct abx500_pinctrl_soc_data {
+	const struct abx500_pinrange *gpio_ranges;
+	unsigned gpio_num_ranges;
+	const struct pinctrl_pin_desc *pins;
+	unsigned npins;
+	const struct abx500_function *functions;
+	unsigned nfunctions;
+	const struct abx500_pingroup *groups;
+	unsigned ngroups;
+	struct alternate_functions *alternate_functions;
+	struct pullud *pullud;
+	struct abx500_gpio_irq_cluster *gpio_irq_cluster;
+	unsigned ngpio_irq_cluster;
+	int irq_gpio_rising_offset;
+	int irq_gpio_falling_offset;
+	int irq_gpio_factor;
+};
+
+#ifdef CONFIG_PINCTRL_AB8500
+
+void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PINCTRL_AB8540
+
+void abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PINCTRL_AB9540
+
+void abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PINCTRL_AB8505
+
+void abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#endif /* PINCTRL_PINCTRL_ABx500_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2099 @@
+/*
+ * Generic GPIO driver for logic cells found in the Nomadik SoC
+ *
+ * Copyright (C) 2008,2009 STMicroelectronics
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include "pinctrl-nomadik.h"
+#include "../core.h"
+
+/*
+ * The GPIO module in the Nomadik family of Systems-on-Chip is an
+ * AMBA device, managing 32 pins and alternate functions.  The logic block
+ * is currently used in the Nomadik and ux500.
+ *
+ * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
+ */
+
+/*
+ * pin configurations are represented by 32-bit integers:
+ *
+ *	bit  0.. 8 - Pin Number (512 Pins Maximum)
+ *	bit  9..10 - Alternate Function Selection
+ *	bit 11..12 - Pull up/down state
+ *	bit     13 - Sleep mode behaviour
+ *	bit     14 - Direction
+ *	bit     15 - Value (if output)
+ *	bit 16..18 - SLPM pull up/down state
+ *	bit 19..20 - SLPM direction
+ *	bit 21..22 - SLPM Value (if output)
+ *	bit 23..25 - PDIS value (if input)
+ *	bit	26 - Gpio mode
+ *	bit	27 - Sleep mode
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ *		     pull up/down = disabled
+ *		     sleep mode = input/wakeup
+ *		     direction = input
+ *		     value = low
+ *		     SLPM direction = same as normal
+ *		     SLPM pull = same as normal
+ *		     SLPM value = same as normal
+ *
+ * PIN_CFG	   - default config with alternate function
+ */
+
+typedef unsigned long pin_cfg_t;
+
+#define PIN_NUM_MASK		0x1ff
+#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT		9
+#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT		11
+#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT		13
+#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
+
+#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
+#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
+
+#define PIN_DIR_SHIFT		14
+#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT		15
+#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
+
+#define PIN_SLPM_PULL_SHIFT	16
+#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)	\
+	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE	\
+	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP	\
+	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN	\
+	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT	19
+#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)		\
+	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT	21
+#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)		\
+	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+#define PIN_SLPM_PDIS_SHIFT		23
+#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS(x)	\
+	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
+
+#define PIN_LOWEMI_SHIFT	25
+#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
+
+#define PIN_GPIOMODE_SHIFT	26
+#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
+
+#define PIN_SLEEPMODE_SHIFT	27
+#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
+
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
+#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
+
+#define PIN_CFG_DEFAULT		(0)
+
+#define PIN_CFG(num, alt)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_INPUT(num, alt, pull)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT	0x00
+#define NMK_GPIO_DATS	0x04
+#define NMK_GPIO_DATC	0x08
+#define NMK_GPIO_PDIS	0x0c
+#define NMK_GPIO_DIR	0x10
+#define NMK_GPIO_DIRS	0x14
+#define NMK_GPIO_DIRC	0x18
+#define NMK_GPIO_SLPC	0x1c
+#define NMK_GPIO_AFSLA	0x20
+#define NMK_GPIO_AFSLB	0x24
+#define NMK_GPIO_LOWEMI	0x28
+
+#define NMK_GPIO_RIMSC	0x40
+#define NMK_GPIO_FIMSC	0x44
+#define NMK_GPIO_IS	0x48
+#define NMK_GPIO_IC	0x4c
+#define NMK_GPIO_RWIMSC	0x50
+#define NMK_GPIO_FWIMSC	0x54
+#define NMK_GPIO_WKS	0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL	0x60
+
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+	NMK_GPIO_PULL_NONE,
+	NMK_GPIO_PULL_UP,
+	NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+struct nmk_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem *addr;
+	struct clk *clk;
+	unsigned int bank;
+	unsigned int parent_irq;
+	int latent_parent_irq;
+	u32 (*get_latent_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
+	spinlock_t lock;
+	bool sleepmode;
+	/* Keep track of configured edges */
+	u32 edge_rising;
+	u32 edge_falling;
+	u32 real_wake;
+	u32 rwimsc;
+	u32 fwimsc;
+	u32 rimsc;
+	u32 fimsc;
+	u32 pull_up;
+	u32 lowemi;
+};
+
+/**
+ * struct nmk_pinctrl - state container for the Nomadik pin controller
+ * @dev: containing device pointer
+ * @pctl: corresponding pin controller device
+ * @soc: SoC data for this specific chip
+ * @prcm_base: PRCM register range virtual base
+ */
+struct nmk_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	const struct nmk_pinctrl_soc_data *soc;
+	void __iomem *prcm_base;
+};
+
+static struct nmk_gpio_chip *
+nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
+
+static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
+
+#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
+
+static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
+				unsigned offset, int gpio_mode)
+{
+	u32 bit = 1 << offset;
+	u32 afunc, bfunc;
+
+	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
+	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
+	if (gpio_mode & NMK_GPIO_ALT_A)
+		afunc |= bit;
+	if (gpio_mode & NMK_GPIO_ALT_B)
+		bfunc |= bit;
+	writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
+	writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
+}
+
+static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
+				unsigned offset, enum nmk_gpio_slpm mode)
+{
+	u32 bit = 1 << offset;
+	u32 slpm;
+
+	slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
+	if (mode == NMK_GPIO_SLPM_NOCHANGE)
+		slpm |= bit;
+	else
+		slpm &= ~bit;
+	writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
+}
+
+static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
+				unsigned offset, enum nmk_gpio_pull pull)
+{
+	u32 bit = 1 << offset;
+	u32 pdis;
+
+	pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
+	if (pull == NMK_GPIO_PULL_NONE) {
+		pdis |= bit;
+		nmk_chip->pull_up &= ~bit;
+	} else {
+		pdis &= ~bit;
+	}
+
+	writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
+
+	if (pull == NMK_GPIO_PULL_UP) {
+		nmk_chip->pull_up |= bit;
+		writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
+	} else if (pull == NMK_GPIO_PULL_DOWN) {
+		nmk_chip->pull_up &= ~bit;
+		writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+	}
+}
+
+static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset, bool lowemi)
+{
+	u32 bit = BIT(offset);
+	bool enabled = nmk_chip->lowemi & bit;
+
+	if (lowemi == enabled)
+		return;
+
+	if (lowemi)
+		nmk_chip->lowemi |= bit;
+	else
+		nmk_chip->lowemi &= ~bit;
+
+	writel_relaxed(nmk_chip->lowemi,
+		       nmk_chip->addr + NMK_GPIO_LOWEMI);
+}
+
+static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset)
+{
+	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+}
+
+static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset, int val)
+{
+	if (val)
+		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+	else
+		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+}
+
+static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset, int val)
+{
+	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+	__nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
+static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
+				     unsigned offset, int gpio_mode,
+				     bool glitch)
+{
+	u32 rwimsc = nmk_chip->rwimsc;
+	u32 fwimsc = nmk_chip->fwimsc;
+
+	if (glitch && nmk_chip->set_ioforce) {
+		u32 bit = BIT(offset);
+
+		/* Prevent spurious wakeups */
+		writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+		nmk_chip->set_ioforce(true);
+	}
+
+	__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
+
+	if (glitch && nmk_chip->set_ioforce) {
+		nmk_chip->set_ioforce(false);
+
+		writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
+	}
+}
+
+static void
+nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
+{
+	u32 falling = nmk_chip->fimsc & BIT(offset);
+	u32 rising = nmk_chip->rimsc & BIT(offset);
+	int gpio = nmk_chip->chip.base + offset;
+	int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset);
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	if (!rising && !falling)
+		return;
+
+	if (!d || !irqd_irq_disabled(d))
+		return;
+
+	if (rising) {
+		nmk_chip->rimsc &= ~BIT(offset);
+		writel_relaxed(nmk_chip->rimsc,
+			       nmk_chip->addr + NMK_GPIO_RIMSC);
+	}
+
+	if (falling) {
+		nmk_chip->fimsc &= ~BIT(offset);
+		writel_relaxed(nmk_chip->fimsc,
+			       nmk_chip->addr + NMK_GPIO_FIMSC);
+	}
+
+	dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
+}
+
+static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
+{
+	u32 val;
+
+	val = readl(reg);
+	val = ((val & ~mask) | (value & mask));
+	writel(val, reg);
+}
+
+static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
+	unsigned offset, unsigned alt_num)
+{
+	int i;
+	u16 reg;
+	u8 bit;
+	u8 alt_index;
+	const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+	const u16 *gpiocr_regs;
+
+	if (!npct->prcm_base)
+		return;
+
+	if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) {
+		dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n",
+			alt_num);
+		return;
+	}
+
+	for (i = 0 ; i < npct->soc->npins_altcx ; i++) {
+		if (npct->soc->altcx_pins[i].pin == offset)
+			break;
+	}
+	if (i == npct->soc->npins_altcx) {
+		dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n",
+			offset);
+		return;
+	}
+
+	pin_desc = npct->soc->altcx_pins + i;
+	gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+
+	/*
+	 * If alt_num is NULL, just clear current ALTCx selection
+	 * to make sure we come back to a pure ALTC selection
+	 */
+	if (!alt_num) {
+		for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+			if (pin_desc->altcx[i].used == true) {
+				reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+				bit = pin_desc->altcx[i].control_bit;
+				if (readl(npct->prcm_base + reg) & BIT(bit)) {
+					nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
+					dev_dbg(npct->dev,
+						"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+						offset, i+1);
+				}
+			}
+		}
+		return;
+	}
+
+	alt_index = alt_num - 1;
+	if (pin_desc->altcx[alt_index].used == false) {
+		dev_warn(npct->dev,
+			"PRCM GPIOCR: pin %i: alternate-C%i does not exist\n",
+			offset, alt_num);
+		return;
+	}
+
+	/*
+	 * Check if any other ALTCx functions are activated on this pin
+	 * and disable it first.
+	 */
+	for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
+		if (i == alt_index)
+			continue;
+		if (pin_desc->altcx[i].used == true) {
+			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+			bit = pin_desc->altcx[i].control_bit;
+			if (readl(npct->prcm_base + reg) & BIT(bit)) {
+				nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
+				dev_dbg(npct->dev,
+					"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
+					offset, i+1);
+			}
+		}
+	}
+
+	reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index];
+	bit = pin_desc->altcx[alt_index].control_bit;
+	dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
+		offset, alt_index+1);
+	nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
+}
+
+/*
+ * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
+ *  - Save SLPM registers
+ *  - Set SLPM=0 for the IOs you want to switch and others to 1
+ *  - Configure the GPIO registers for the IOs that are being switched
+ *  - Set IOFORCE=1
+ *  - Modify the AFLSA/B registers for the IOs that are being switched
+ *  - Set IOFORCE=0
+ *  - Restore SLPM registers
+ *  - Any spurious wake up event during switch sequence to be ignored and
+ *    cleared
+ */
+static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+		unsigned int temp = slpm[i];
+
+		if (!chip)
+			break;
+
+		clk_enable(chip->clk);
+
+		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
+		writel(temp, chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
+static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+
+		clk_disable(chip->clk);
+	}
+}
+
+static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
+{
+	int i;
+	u16 reg;
+	u8 bit;
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+	const u16 *gpiocr_regs;
+
+	if (!npct->prcm_base)
+		return NMK_GPIO_ALT_C;
+
+	for (i = 0; i < npct->soc->npins_altcx; i++) {
+		if (npct->soc->altcx_pins[i].pin == gpio)
+			break;
+	}
+	if (i == npct->soc->npins_altcx)
+		return NMK_GPIO_ALT_C;
+
+	pin_desc = npct->soc->altcx_pins + i;
+	gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+	for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) {
+		if (pin_desc->altcx[i].used == true) {
+			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+			bit = pin_desc->altcx[i].control_bit;
+			if (readl(npct->prcm_base + reg) & BIT(bit))
+				return NMK_GPIO_ALT_C+i+1;
+		}
+	}
+	return NMK_GPIO_ALT_C;
+}
+
+int nmk_gpio_get_mode(int gpio)
+{
+	struct nmk_gpio_chip *nmk_chip;
+	u32 afunc, bfunc, bit;
+
+	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
+	if (!nmk_chip)
+		return -EINVAL;
+
+	bit = 1 << (gpio % NMK_GPIO_PER_CHIP);
+
+	clk_enable(nmk_chip->clk);
+
+	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
+	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
+
+	clk_disable(nmk_chip->clk);
+
+	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
+}
+EXPORT_SYMBOL(nmk_gpio_get_mode);
+
+
+/* IRQ functions */
+static inline int nmk_gpio_get_bitmask(int gpio)
+{
+	return 1 << (gpio % NMK_GPIO_PER_CHIP);
+}
+
+static void nmk_gpio_irq_ack(struct irq_data *d)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+
+	clk_enable(nmk_chip->clk);
+	writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
+	clk_disable(nmk_chip->clk);
+}
+
+enum nmk_gpio_irq_type {
+	NORMAL,
+	WAKE,
+};
+
+static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
+				  int gpio, enum nmk_gpio_irq_type which,
+				  bool enable)
+{
+	u32 bitmask = nmk_gpio_get_bitmask(gpio);
+	u32 *rimscval;
+	u32 *fimscval;
+	u32 rimscreg;
+	u32 fimscreg;
+
+	if (which == NORMAL) {
+		rimscreg = NMK_GPIO_RIMSC;
+		fimscreg = NMK_GPIO_FIMSC;
+		rimscval = &nmk_chip->rimsc;
+		fimscval = &nmk_chip->fimsc;
+	} else  {
+		rimscreg = NMK_GPIO_RWIMSC;
+		fimscreg = NMK_GPIO_FWIMSC;
+		rimscval = &nmk_chip->rwimsc;
+		fimscval = &nmk_chip->fwimsc;
+	}
+
+	/* we must individually set/clear the two edges */
+	if (nmk_chip->edge_rising & bitmask) {
+		if (enable)
+			*rimscval |= bitmask;
+		else
+			*rimscval &= ~bitmask;
+		writel(*rimscval, nmk_chip->addr + rimscreg);
+	}
+	if (nmk_chip->edge_falling & bitmask) {
+		if (enable)
+			*fimscval |= bitmask;
+		else
+			*fimscval &= ~bitmask;
+		writel(*fimscval, nmk_chip->addr + fimscreg);
+	}
+}
+
+static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
+				int gpio, bool on)
+{
+	/*
+	 * Ensure WAKEUP_ENABLE is on.  No need to disable it if wakeup is
+	 * disabled, since setting SLPM to 1 increases power consumption, and
+	 * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
+	 */
+	if (nmk_chip->sleepmode && on) {
+		__nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP,
+				    NMK_GPIO_SLPM_WAKEUP_ENABLE);
+	}
+
+	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+}
+
+static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
+{
+	struct nmk_gpio_chip *nmk_chip;
+	unsigned long flags;
+	u32 bitmask;
+
+	nmk_chip = irq_data_get_irq_chip_data(d);
+	bitmask = nmk_gpio_get_bitmask(d->hwirq);
+	if (!nmk_chip)
+		return -EINVAL;
+
+	clk_enable(nmk_chip->clk);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
+
+	if (!(nmk_chip->real_wake & bitmask))
+		__nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+static void nmk_gpio_irq_mask(struct irq_data *d)
+{
+	nmk_gpio_irq_maskunmask(d, false);
+}
+
+static void nmk_gpio_irq_unmask(struct irq_data *d)
+{
+	nmk_gpio_irq_maskunmask(d, true);
+}
+
+static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	struct nmk_gpio_chip *nmk_chip;
+	unsigned long flags;
+	u32 bitmask;
+
+	nmk_chip = irq_data_get_irq_chip_data(d);
+	if (!nmk_chip)
+		return -EINVAL;
+	bitmask = nmk_gpio_get_bitmask(d->hwirq);
+
+	clk_enable(nmk_chip->clk);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	if (irqd_irq_disabled(d))
+		__nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
+
+	if (on)
+		nmk_chip->real_wake |= bitmask;
+	else
+		nmk_chip->real_wake &= ~bitmask;
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	bool enabled = !irqd_irq_disabled(d);
+	bool wake = irqd_is_wakeup_set(d);
+	struct nmk_gpio_chip *nmk_chip;
+	unsigned long flags;
+	u32 bitmask;
+
+	nmk_chip = irq_data_get_irq_chip_data(d);
+	bitmask = nmk_gpio_get_bitmask(d->hwirq);
+	if (!nmk_chip)
+		return -EINVAL;
+	if (type & IRQ_TYPE_LEVEL_HIGH)
+		return -EINVAL;
+	if (type & IRQ_TYPE_LEVEL_LOW)
+		return -EINVAL;
+
+	clk_enable(nmk_chip->clk);
+	spin_lock_irqsave(&nmk_chip->lock, flags);
+
+	if (enabled)
+		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
+
+	if (enabled || wake)
+		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
+
+	nmk_chip->edge_rising &= ~bitmask;
+	if (type & IRQ_TYPE_EDGE_RISING)
+		nmk_chip->edge_rising |= bitmask;
+
+	nmk_chip->edge_falling &= ~bitmask;
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		nmk_chip->edge_falling |= bitmask;
+
+	if (enabled)
+		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
+
+	if (enabled || wake)
+		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
+
+	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	clk_enable(nmk_chip->clk);
+	nmk_gpio_irq_unmask(d);
+	return 0;
+}
+
+static void nmk_gpio_irq_shutdown(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	nmk_gpio_irq_mask(d);
+	clk_disable(nmk_chip->clk);
+}
+
+static struct irq_chip nmk_gpio_irq_chip = {
+	.name		= "Nomadik-GPIO",
+	.irq_ack	= nmk_gpio_irq_ack,
+	.irq_mask	= nmk_gpio_irq_mask,
+	.irq_unmask	= nmk_gpio_irq_unmask,
+	.irq_set_type	= nmk_gpio_irq_set_type,
+	.irq_set_wake	= nmk_gpio_irq_set_wake,
+	.irq_startup	= nmk_gpio_irq_startup,
+	.irq_shutdown	= nmk_gpio_irq_shutdown,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
+				   u32 status)
+{
+	struct irq_chip *host_chip = irq_get_chip(irq);
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(host_chip, desc);
+
+	while (status) {
+		int bit = __ffs(status);
+
+		generic_handle_irq(irq_find_mapping(chip->irqdomain, bit));
+		status &= ~BIT(bit);
+	}
+
+	chained_irq_exit(host_chip, desc);
+}
+
+static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+	u32 status;
+
+	clk_enable(nmk_chip->clk);
+	status = readl(nmk_chip->addr + NMK_GPIO_IS);
+	clk_disable(nmk_chip->clk);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
+static void nmk_gpio_latent_irq_handler(unsigned int irq,
+					   struct irq_desc *desc)
+{
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+	u32 status = nmk_chip->get_latent_status(nmk_chip->bank);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
+/* I/O Functions */
+
+static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+
+	clk_enable(nmk_chip->clk);
+
+	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+	u32 bit = 1 << offset;
+	int value;
+
+	clk_enable(nmk_chip->clk);
+
+	value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+
+	clk_disable(nmk_chip->clk);
+
+	return value;
+}
+
+static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+
+	clk_enable(nmk_chip->clk);
+
+	__nmk_gpio_set_output(nmk_chip, offset, val);
+
+	clk_disable(nmk_chip->clk);
+}
+
+static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+
+	clk_enable(nmk_chip->clk);
+
+	__nmk_gpio_make_output(nmk_chip, offset, val);
+
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+static void nmk_gpio_dbg_show_one(struct seq_file *s,
+	struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+	unsigned offset, unsigned gpio)
+{
+	const char *label = gpiochip_is_requested(chip, offset);
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+	int mode;
+	bool is_out;
+	bool pull;
+	u32 bit = 1 << offset;
+	const char *modes[] = {
+		[NMK_GPIO_ALT_GPIO]	= "gpio",
+		[NMK_GPIO_ALT_A]	= "altA",
+		[NMK_GPIO_ALT_B]	= "altB",
+		[NMK_GPIO_ALT_C]	= "altC",
+		[NMK_GPIO_ALT_C+1]	= "altC1",
+		[NMK_GPIO_ALT_C+2]	= "altC2",
+		[NMK_GPIO_ALT_C+3]	= "altC3",
+		[NMK_GPIO_ALT_C+4]	= "altC4",
+	};
+
+	clk_enable(nmk_chip->clk);
+	is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
+	pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
+	mode = nmk_gpio_get_mode(gpio);
+	if ((mode == NMK_GPIO_ALT_C) && pctldev)
+		mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
+
+	seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
+		   gpio, label ?: "(none)",
+		   is_out ? "out" : "in ",
+		   chip->get
+		   ? (chip->get(chip, offset) ? "hi" : "lo")
+		   : "?  ",
+		   (mode < 0) ? "unknown" : modes[mode],
+		   pull ? "pull" : "none");
+
+	if (!is_out) {
+		int irq = gpio_to_irq(gpio);
+		struct irq_desc	*desc = irq_to_desc(irq);
+
+		/* This races with request_irq(), set_irq_type(),
+		 * and set_irq_wake() ... but those are "rare".
+		 */
+		if (irq > 0 && desc && desc->action) {
+			char *trigger;
+			u32 bitmask = nmk_gpio_get_bitmask(gpio);
+
+			if (nmk_chip->edge_rising & bitmask)
+				trigger = "edge-rising";
+			else if (nmk_chip->edge_falling & bitmask)
+				trigger = "edge-falling";
+			else
+				trigger = "edge-undefined";
+
+			seq_printf(s, " irq-%d %s%s",
+				   irq, trigger,
+				   irqd_is_wakeup_set(&desc->irq_data)
+				   ? " wakeup" : "");
+		}
+	}
+	clk_disable(nmk_chip->clk);
+}
+
+static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	unsigned		i;
+	unsigned		gpio = chip->base;
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
+		seq_printf(s, "\n");
+	}
+}
+
+#else
+static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
+					 struct pinctrl_dev *pctldev,
+					 struct gpio_chip *chip,
+					 unsigned offset, unsigned gpio)
+{
+}
+#define nmk_gpio_dbg_show	NULL
+#endif
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip nmk_gpio_template = {
+	.request		= nmk_gpio_request,
+	.free			= nmk_gpio_free,
+	.direction_input	= nmk_gpio_make_input,
+	.get			= nmk_gpio_get_input,
+	.direction_output	= nmk_gpio_make_output,
+	.set			= nmk_gpio_set_output,
+	.dbg_show		= nmk_gpio_dbg_show,
+	.can_sleep		= false,
+};
+
+void nmk_gpio_clocks_enable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_enable(chip->clk);
+	}
+}
+
+void nmk_gpio_clocks_disable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_disable(chip->clk);
+	}
+}
+
+/*
+ * Called from the suspend/resume path to only keep the real wakeup interrupts
+ * (those that have had set_irq_wake() called on them) as wakeup interrupts,
+ * and not the rest of the interrupts which we needed to have as wakeups for
+ * cpuidle.
+ *
+ * PM ops are not used since this needs to be done at the end, after all the
+ * other drivers are done with their suspend callbacks.
+ */
+void nmk_gpio_wakeups_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		clk_enable(chip->clk);
+
+		writel(chip->rwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_FWIMSC);
+
+		clk_disable(chip->clk);
+	}
+}
+
+void nmk_gpio_wakeups_resume(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		clk_enable(chip->clk);
+
+		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
+
+		clk_disable(chip->clk);
+	}
+}
+
+/*
+ * Read the pull up/pull down status.
+ * A bit set in 'pull_up' means that pull up
+ * is selected if pull is enabled in PDIS register.
+ * Note: only pull up/down set via this driver can
+ * be detected due to HW limitations.
+ */
+void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
+{
+	if (gpio_bank < NUM_BANKS) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[gpio_bank];
+
+		if (!chip)
+			return;
+
+		*pull_up = chip->pull_up;
+	}
+}
+
+static int nmk_gpio_probe(struct platform_device *dev)
+{
+	struct device_node *np = dev->dev.of_node;
+	struct nmk_gpio_chip *nmk_chip;
+	struct gpio_chip *chip;
+	struct resource *res;
+	struct clk *clk;
+	int latent_irq;
+	bool supports_sleepmode;
+	void __iomem *base;
+	int irq;
+	int ret;
+
+	if (of_get_property(np, "st,supports-sleepmode", NULL))
+		supports_sleepmode = true;
+	else
+		supports_sleepmode = false;
+
+	if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
+		dev_err(&dev->dev, "gpio-bank property not found\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0)
+		return irq;
+
+	/* It's OK for this IRQ not to be present */
+	latent_irq = platform_get_irq(dev, 1);
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&dev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+	clk_prepare(clk);
+
+	nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL);
+	if (!nmk_chip)
+		return -ENOMEM;
+
+	/*
+	 * The virt address in nmk_chip->addr is in the nomadik register space,
+	 * so we can simply convert the resource address, without remapping
+	 */
+	nmk_chip->bank = dev->id;
+	nmk_chip->clk = clk;
+	nmk_chip->addr = base;
+	nmk_chip->chip = nmk_gpio_template;
+	nmk_chip->parent_irq = irq;
+	nmk_chip->latent_parent_irq = latent_irq;
+	nmk_chip->sleepmode = supports_sleepmode;
+	spin_lock_init(&nmk_chip->lock);
+
+	chip = &nmk_chip->chip;
+	chip->base = dev->id * NMK_GPIO_PER_CHIP;
+	chip->ngpio = NMK_GPIO_PER_CHIP;
+	chip->label = dev_name(&dev->dev);
+	chip->dev = &dev->dev;
+	chip->owner = THIS_MODULE;
+
+	clk_enable(nmk_chip->clk);
+	nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
+	clk_disable(nmk_chip->clk);
+	chip->of_node = np;
+
+	ret = gpiochip_add(&nmk_chip->chip);
+	if (ret)
+		return ret;
+
+	BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
+
+	nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
+
+	platform_set_drvdata(dev, nmk_chip);
+
+	/*
+	 * Let the generic code handle this edge IRQ, the the chained
+	 * handler will perform the actual work of handling the parent
+	 * interrupt.
+	 */
+	ret = gpiochip_irqchip_add(&nmk_chip->chip,
+				   &nmk_gpio_irq_chip,
+				   0,
+				   handle_edge_irq,
+				   IRQ_TYPE_EDGE_FALLING);
+	if (ret) {
+		dev_err(&dev->dev, "could not add irqchip\n");
+		ret = gpiochip_remove(&nmk_chip->chip);
+		return -ENODEV;
+	}
+	/* Then register the chain on the parent IRQ */
+	gpiochip_set_chained_irqchip(&nmk_chip->chip,
+				     &nmk_gpio_irq_chip,
+				     nmk_chip->parent_irq,
+				     nmk_gpio_irq_handler);
+	if (nmk_chip->latent_parent_irq > 0)
+		gpiochip_set_chained_irqchip(&nmk_chip->chip,
+					     &nmk_gpio_irq_chip,
+					     nmk_chip->latent_parent_irq,
+					     nmk_gpio_latent_irq_handler);
+
+	dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);
+
+	return 0;
+}
+
+static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	return npct->soc->ngroups;
+}
+
+static const char *nmk_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	return npct->soc->groups[selector].name;
+}
+
+static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			      const unsigned **pins,
+			      unsigned *num_pins)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = npct->soc->groups[selector].pins;
+	*num_pins = npct->soc->groups[selector].npins;
+	return 0;
+}
+
+static struct pinctrl_gpio_range *
+nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	int i;
+
+	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
+		struct pinctrl_gpio_range *range;
+
+		range = &npct->soc->gpio_ranges[i];
+		if (offset >= range->pin_base &&
+		    offset <= (range->pin_base + range->npins - 1))
+			return range;
+	}
+	return NULL;
+}
+
+static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	struct pinctrl_gpio_range *range;
+	struct gpio_chip *chip;
+
+	range = nmk_match_gpio_range(pctldev, offset);
+	if (!range || !range->gc) {
+		seq_printf(s, "invalid pin offset");
+		return;
+	}
+	chip = range->gc;
+	nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
+}
+
+static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+		struct pinctrl_map *map, unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++)
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+			kfree(map[i].data.configs.configs);
+	kfree(map);
+}
+
+static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
+		unsigned *num_maps, unsigned reserve)
+{
+	unsigned old_num = *reserved_maps;
+	unsigned new_num = *num_maps + reserve;
+	struct pinctrl_map *new_map;
+
+	if (old_num >= new_num)
+		return 0;
+
+	new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
+
+	*map = new_map;
+	*reserved_maps = new_num;
+
+	return 0;
+}
+
+static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
+		unsigned *num_maps, const char *group,
+		const char *function)
+{
+	if (*num_maps == *reserved_maps)
+		return -ENOSPC;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+	(*map)[*num_maps].data.mux.group = group;
+	(*map)[*num_maps].data.mux.function = function;
+	(*num_maps)++;
+
+	return 0;
+}
+
+static int nmk_dt_add_map_configs(struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps, const char *group,
+		unsigned long *configs, unsigned num_configs)
+{
+	unsigned long *dup_configs;
+
+	if (*num_maps == *reserved_maps)
+		return -ENOSPC;
+
+	dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+			      GFP_KERNEL);
+	if (!dup_configs)
+		return -ENOMEM;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
+
+	(*map)[*num_maps].data.configs.group_or_pin = group;
+	(*map)[*num_maps].data.configs.configs = dup_configs;
+	(*map)[*num_maps].data.configs.num_configs = num_configs;
+	(*num_maps)++;
+
+	return 0;
+}
+
+#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, }
+#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \
+	.size = ARRAY_SIZE(y), }
+
+static const unsigned long nmk_pin_input_modes[] = {
+	PIN_INPUT_NOPULL,
+	PIN_INPUT_PULLUP,
+	PIN_INPUT_PULLDOWN,
+};
+
+static const unsigned long nmk_pin_output_modes[] = {
+	PIN_OUTPUT_LOW,
+	PIN_OUTPUT_HIGH,
+	PIN_DIR_OUTPUT,
+};
+
+static const unsigned long nmk_pin_sleep_modes[] = {
+	PIN_SLEEPMODE_DISABLED,
+	PIN_SLEEPMODE_ENABLED,
+};
+
+static const unsigned long nmk_pin_sleep_input_modes[] = {
+	PIN_SLPM_INPUT_NOPULL,
+	PIN_SLPM_INPUT_PULLUP,
+	PIN_SLPM_INPUT_PULLDOWN,
+	PIN_SLPM_DIR_INPUT,
+};
+
+static const unsigned long nmk_pin_sleep_output_modes[] = {
+	PIN_SLPM_OUTPUT_LOW,
+	PIN_SLPM_OUTPUT_HIGH,
+	PIN_SLPM_DIR_OUTPUT,
+};
+
+static const unsigned long nmk_pin_sleep_wakeup_modes[] = {
+	PIN_SLPM_WAKEUP_DISABLE,
+	PIN_SLPM_WAKEUP_ENABLE,
+};
+
+static const unsigned long nmk_pin_gpio_modes[] = {
+	PIN_GPIOMODE_DISABLED,
+	PIN_GPIOMODE_ENABLED,
+};
+
+static const unsigned long nmk_pin_sleep_pdis_modes[] = {
+	PIN_SLPM_PDIS_DISABLED,
+	PIN_SLPM_PDIS_ENABLED,
+};
+
+struct nmk_cfg_param {
+	const char *property;
+	unsigned long config;
+	const unsigned long *choice;
+	int size;
+};
+
+static const struct nmk_cfg_param nmk_cfg_params[] = {
+	NMK_CONFIG_PIN_ARRAY("ste,input",		nmk_pin_input_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,output",		nmk_pin_output_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,sleep",		nmk_pin_sleep_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,sleep-input",		nmk_pin_sleep_input_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,sleep-output",	nmk_pin_sleep_output_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup",	nmk_pin_sleep_wakeup_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,gpio",		nmk_pin_gpio_modes),
+	NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable",	nmk_pin_sleep_pdis_modes),
+};
+
+static int nmk_dt_pin_config(int index, int val, unsigned long *config)
+{
+	int ret = 0;
+
+	if (nmk_cfg_params[index].choice == NULL)
+		*config = nmk_cfg_params[index].config;
+	else {
+		/* test if out of range */
+		if  (val < nmk_cfg_params[index].size) {
+			*config = nmk_cfg_params[index].config |
+				nmk_cfg_params[index].choice[val];
+		}
+	}
+	return ret;
+}
+
+static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name)
+{
+	int i, pin_number;
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
+		for (i = 0; i < npct->soc->npins; i++)
+			if (npct->soc->pins[i].number == pin_number)
+				return npct->soc->pins[i].name;
+	return NULL;
+}
+
+static bool nmk_pinctrl_dt_get_config(struct device_node *np,
+		unsigned long *configs)
+{
+	bool has_config = 0;
+	unsigned long cfg = 0;
+	int i, val, ret;
+
+	for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) {
+		ret = of_property_read_u32(np,
+				nmk_cfg_params[i].property, &val);
+		if (ret != -EINVAL) {
+			if (nmk_dt_pin_config(i, val, &cfg) == 0) {
+				*configs |= cfg;
+				has_config = 1;
+			}
+		}
+	}
+
+	return has_config;
+}
+
+static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+		struct device_node *np,
+		struct pinctrl_map **map,
+		unsigned *reserved_maps,
+		unsigned *num_maps)
+{
+	int ret;
+	const char *function = NULL;
+	unsigned long configs = 0;
+	bool has_config = 0;
+	unsigned reserve = 0;
+	struct property *prop;
+	const char *group, *gpio_name;
+	struct device_node *np_config;
+
+	ret = of_property_read_string(np, "ste,function", &function);
+	if (ret >= 0)
+		reserve = 1;
+
+	has_config = nmk_pinctrl_dt_get_config(np, &configs);
+
+	np_config = of_parse_phandle(np, "ste,config", 0);
+	if (np_config)
+		has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
+
+	ret = of_property_count_strings(np, "ste,pins");
+	if (ret < 0)
+		goto exit;
+
+	if (has_config)
+		reserve++;
+
+	reserve *= ret;
+
+	ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_string(np, "ste,pins", prop, group) {
+		if (function) {
+			ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps,
+					  group, function);
+			if (ret < 0)
+				goto exit;
+		}
+		if (has_config) {
+			gpio_name = nmk_find_pin_name(pctldev, group);
+
+			ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps,
+					      gpio_name, &configs, 1);
+			if (ret < 0)
+				goto exit;
+		}
+
+	}
+exit:
+	return ret;
+}
+
+static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				 struct device_node *np_config,
+				 struct pinctrl_map **map, unsigned *num_maps)
+{
+	unsigned reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	for_each_child_of_node(np_config, np) {
+		ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
+				&reserved_maps, num_maps);
+		if (ret < 0) {
+			nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct pinctrl_ops nmk_pinctrl_ops = {
+	.get_groups_count = nmk_get_groups_cnt,
+	.get_group_name = nmk_get_group_name,
+	.get_group_pins = nmk_get_group_pins,
+	.pin_dbg_show = nmk_pin_dbg_show,
+	.dt_node_to_map = nmk_pinctrl_dt_node_to_map,
+	.dt_free_map = nmk_pinctrl_dt_free_map,
+};
+
+static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	return npct->soc->nfunctions;
+}
+
+static const char *nmk_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					 unsigned function)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	return npct->soc->functions[function].name;
+}
+
+static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+				   unsigned function,
+				   const char * const **groups,
+				   unsigned * const num_groups)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = npct->soc->functions[function].groups;
+	*num_groups = npct->soc->functions[function].ngroups;
+
+	return 0;
+}
+
+static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
+			  unsigned group)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	const struct nmk_pingroup *g;
+	static unsigned int slpm[NUM_BANKS];
+	unsigned long flags = 0;
+	bool glitch;
+	int ret = -EINVAL;
+	int i;
+
+	g = &npct->soc->groups[group];
+
+	if (g->altsetting < 0)
+		return -EINVAL;
+
+	dev_dbg(npct->dev, "enable group %s, %u pins\n", g->name, g->npins);
+
+	/*
+	 * If we're setting altfunc C by setting both AFSLA and AFSLB to 1,
+	 * we may pass through an undesired state. In this case we take
+	 * some extra care.
+	 *
+	 * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
+	 *  - Save SLPM registers (since we have a shadow register in the
+	 *    nmk_chip we're using that as backup)
+	 *  - Set SLPM=0 for the IOs you want to switch and others to 1
+	 *  - Configure the GPIO registers for the IOs that are being switched
+	 *  - Set IOFORCE=1
+	 *  - Modify the AFLSA/B registers for the IOs that are being switched
+	 *  - Set IOFORCE=0
+	 *  - Restore SLPM registers
+	 *  - Any spurious wake up event during switch sequence to be ignored
+	 *    and cleared
+	 *
+	 * We REALLY need to save ALL slpm registers, because the external
+	 * IOFORCE will switch *all* ports to their sleepmode setting to as
+	 * to avoid glitches. (Not just one port!)
+	 */
+	glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C);
+
+	if (glitch) {
+		spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+
+		/* Initially don't put any pins to sleep when switching */
+		memset(slpm, 0xff, sizeof(slpm));
+
+		/*
+		 * Then mask the pins that need to be sleeping now when we're
+		 * switching to the ALT C function.
+		 */
+		for (i = 0; i < g->npins; i++)
+			slpm[g->pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->pins[i]);
+		nmk_gpio_glitch_slpm_init(slpm);
+	}
+
+	for (i = 0; i < g->npins; i++) {
+		struct pinctrl_gpio_range *range;
+		struct nmk_gpio_chip *nmk_chip;
+		struct gpio_chip *chip;
+		unsigned bit;
+
+		range = nmk_match_gpio_range(pctldev, g->pins[i]);
+		if (!range) {
+			dev_err(npct->dev,
+				"invalid pin offset %d in group %s at index %d\n",
+				g->pins[i], g->name, i);
+			goto out_glitch;
+		}
+		if (!range->gc) {
+			dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n",
+				g->pins[i], g->name, i);
+			goto out_glitch;
+		}
+		chip = range->gc;
+		nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+		dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting);
+
+		clk_enable(nmk_chip->clk);
+		bit = g->pins[i] % NMK_GPIO_PER_CHIP;
+		/*
+		 * If the pin is switching to altfunc, and there was an
+		 * interrupt installed on it which has been lazy disabled,
+		 * actually mask the interrupt to prevent spurious interrupts
+		 * that would occur while the pin is under control of the
+		 * peripheral. Only SKE does this.
+		 */
+		nmk_gpio_disable_lazy_irq(nmk_chip, bit);
+
+		__nmk_gpio_set_mode_safe(nmk_chip, bit,
+			(g->altsetting & NMK_GPIO_ALT_C), glitch);
+		clk_disable(nmk_chip->clk);
+
+		/*
+		 * Call PRCM GPIOCR config function in case ALTC
+		 * has been selected:
+		 * - If selection is a ALTCx, some bits in PRCM GPIOCR registers
+		 *   must be set.
+		 * - If selection is pure ALTC and previous selection was ALTCx,
+		 *   then some bits in PRCM GPIOCR registers must be cleared.
+		 */
+		if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C)
+			nmk_prcm_altcx_set_mode(npct, g->pins[i],
+				g->altsetting >> NMK_GPIO_ALT_CX_SHIFT);
+	}
+
+	/* When all pins are successfully reconfigured we get here */
+	ret = 0;
+
+out_glitch:
+	if (glitch) {
+		nmk_gpio_glitch_slpm_restore(slpm);
+		spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	}
+
+	return ret;
+}
+
+static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
+				   struct pinctrl_gpio_range *range,
+				   unsigned offset)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct nmk_gpio_chip *nmk_chip;
+	struct gpio_chip *chip;
+	unsigned bit;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	clk_enable(nmk_chip->clk);
+	bit = offset % NMK_GPIO_PER_CHIP;
+	/* There is no glitch when converting any pin to GPIO */
+	__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
+	clk_disable(nmk_chip->clk);
+
+	return 0;
+}
+
+static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
+				  struct pinctrl_gpio_range *range,
+				  unsigned offset)
+{
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops nmk_pinmux_ops = {
+	.get_functions_count = nmk_pmx_get_funcs_cnt,
+	.get_function_name = nmk_pmx_get_func_name,
+	.get_function_groups = nmk_pmx_get_func_groups,
+	.enable = nmk_pmx_enable,
+	.gpio_request_enable = nmk_gpio_request_enable,
+	.gpio_disable_free = nmk_gpio_disable_free,
+};
+
+static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+			      unsigned long *config)
+{
+	/* Not implemented */
+	return -EINVAL;
+}
+
+static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+			      unsigned long *configs, unsigned num_configs)
+{
+	static const char *pullnames[] = {
+		[NMK_GPIO_PULL_NONE]	= "none",
+		[NMK_GPIO_PULL_UP]	= "up",
+		[NMK_GPIO_PULL_DOWN]	= "down",
+		[3] /* illegal */	= "??"
+	};
+	static const char *slpmnames[] = {
+		[NMK_GPIO_SLPM_INPUT]		= "input/wakeup",
+		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change/no-wakeup",
+	};
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct nmk_gpio_chip *nmk_chip;
+	struct pinctrl_gpio_range *range;
+	struct gpio_chip *chip;
+	unsigned bit;
+	pin_cfg_t cfg;
+	int pull, slpm, output, val, i;
+	bool lowemi, gpiomode, sleep;
+
+	range = nmk_match_gpio_range(pctldev, pin);
+	if (!range) {
+		dev_err(npct->dev, "invalid pin offset %d\n", pin);
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "GPIO chip missing in range for pin %d\n",
+			pin);
+		return -EINVAL;
+	}
+	chip = range->gc;
+	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
+
+	for (i = 0; i < num_configs; i++) {
+		/*
+		 * The pin config contains pin number and altfunction fields,
+		 * here we just ignore that part. It's being handled by the
+		 * framework and pinmux callback respectively.
+		 */
+		cfg = (pin_cfg_t) configs[i];
+		pull = PIN_PULL(cfg);
+		slpm = PIN_SLPM(cfg);
+		output = PIN_DIR(cfg);
+		val = PIN_VAL(cfg);
+		lowemi = PIN_LOWEMI(cfg);
+		gpiomode = PIN_GPIOMODE(cfg);
+		sleep = PIN_SLEEPMODE(cfg);
+
+		if (sleep) {
+			int slpm_pull = PIN_SLPM_PULL(cfg);
+			int slpm_output = PIN_SLPM_DIR(cfg);
+			int slpm_val = PIN_SLPM_VAL(cfg);
+
+			/* All pins go into GPIO mode at sleep */
+			gpiomode = true;
+
+			/*
+			 * The SLPM_* values are normal values + 1 to allow zero
+			 * to mean "same as normal".
+			 */
+			if (slpm_pull)
+				pull = slpm_pull - 1;
+			if (slpm_output)
+				output = slpm_output - 1;
+			if (slpm_val)
+				val = slpm_val - 1;
+
+			dev_dbg(nmk_chip->chip.dev,
+				"pin %d: sleep pull %s, dir %s, val %s\n",
+				pin,
+				slpm_pull ? pullnames[pull] : "same",
+				slpm_output ? (output ? "output" : "input")
+				: "same",
+				slpm_val ? (val ? "high" : "low") : "same");
+		}
+
+		dev_dbg(nmk_chip->chip.dev,
+			"pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
+			pin, cfg, pullnames[pull], slpmnames[slpm],
+			output ? "output " : "input",
+			output ? (val ? "high" : "low") : "",
+			lowemi ? "on" : "off");
+
+		clk_enable(nmk_chip->clk);
+		bit = pin % NMK_GPIO_PER_CHIP;
+		if (gpiomode)
+			/* No glitch when going to GPIO mode */
+			__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
+		if (output)
+			__nmk_gpio_make_output(nmk_chip, bit, val);
+		else {
+			__nmk_gpio_make_input(nmk_chip, bit);
+			__nmk_gpio_set_pull(nmk_chip, bit, pull);
+		}
+		/* TODO: isn't this only applicable on output pins? */
+		__nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);
+
+		__nmk_gpio_set_slpm(nmk_chip, bit, slpm);
+		clk_disable(nmk_chip->clk);
+	} /* for each config */
+
+	return 0;
+}
+
+static const struct pinconf_ops nmk_pinconf_ops = {
+	.pin_config_get = nmk_pin_config_get,
+	.pin_config_set = nmk_pin_config_set,
+};
+
+static struct pinctrl_desc nmk_pinctrl_desc = {
+	.name = "pinctrl-nomadik",
+	.pctlops = &nmk_pinctrl_ops,
+	.pmxops = &nmk_pinmux_ops,
+	.confops = &nmk_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static const struct of_device_id nmk_pinctrl_match[] = {
+	{
+		.compatible = "stericsson,stn8815-pinctrl",
+		.data = (void *)PINCTRL_NMK_STN8815,
+	},
+	{
+		.compatible = "stericsson,db8500-pinctrl",
+		.data = (void *)PINCTRL_NMK_DB8500,
+	},
+	{
+		.compatible = "stericsson,db8540-pinctrl",
+		.data = (void *)PINCTRL_NMK_DB8540,
+	},
+	{},
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int nmk_pinctrl_suspend(struct device *dev)
+{
+	struct nmk_pinctrl *npct;
+
+	npct = dev_get_drvdata(dev);
+	if (!npct)
+		return -EINVAL;
+
+	return pinctrl_force_sleep(npct->pctl);
+}
+
+static int nmk_pinctrl_resume(struct device *dev)
+{
+	struct nmk_pinctrl *npct;
+
+	npct = dev_get_drvdata(dev);
+	if (!npct)
+		return -EINVAL;
+
+	return pinctrl_force_default(npct->pctl);
+}
+#endif
+
+static int nmk_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *prcm_np;
+	struct nmk_pinctrl *npct;
+	unsigned int version = 0;
+	int i;
+
+	npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL);
+	if (!npct)
+		return -ENOMEM;
+
+	match = of_match_device(nmk_pinctrl_match, &pdev->dev);
+	if (!match)
+		return -ENODEV;
+	version = (unsigned int) match->data;
+
+	/* Poke in other ASIC variants here */
+	if (version == PINCTRL_NMK_STN8815)
+		nmk_pinctrl_stn8815_init(&npct->soc);
+	if (version == PINCTRL_NMK_DB8500)
+		nmk_pinctrl_db8500_init(&npct->soc);
+	if (version == PINCTRL_NMK_DB8540)
+		nmk_pinctrl_db8540_init(&npct->soc);
+
+	prcm_np = of_parse_phandle(np, "prcm", 0);
+	if (prcm_np)
+		npct->prcm_base = of_iomap(prcm_np, 0);
+	if (!npct->prcm_base) {
+		if (version == PINCTRL_NMK_STN8815) {
+			dev_info(&pdev->dev,
+				 "No PRCM base, "
+				 "assuming no ALT-Cx control is available\n");
+		} else {
+			dev_err(&pdev->dev, "missing PRCM base address\n");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
+		if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
+			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
+			return -EPROBE_DEFER;
+		}
+		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
+	}
+
+	nmk_pinctrl_desc.pins = npct->soc->pins;
+	nmk_pinctrl_desc.npins = npct->soc->npins;
+	npct->dev = &pdev->dev;
+
+	npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
+	if (!npct->pctl) {
+		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < npct->soc->gpio_num_ranges; i++)
+		pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]);
+
+	platform_set_drvdata(pdev, npct);
+	dev_info(&pdev->dev, "initialized Nomadik pin control driver\n");
+
+	return 0;
+}
+
+static const struct of_device_id nmk_gpio_match[] = {
+	{ .compatible = "st,nomadik-gpio", },
+	{}
+};
+
+static struct platform_driver nmk_gpio_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "gpio",
+		.of_match_table = nmk_gpio_match,
+	},
+	.probe = nmk_gpio_probe,
+};
+
+static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops,
+			nmk_pinctrl_suspend,
+			nmk_pinctrl_resume);
+
+static struct platform_driver nmk_pinctrl_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "pinctrl-nomadik",
+		.of_match_table = nmk_pinctrl_match,
+		.pm = &nmk_pinctrl_pm_ops,
+	},
+	.probe = nmk_pinctrl_probe,
+};
+
+static int __init nmk_gpio_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&nmk_gpio_driver);
+	if (ret)
+		return ret;
+	return platform_driver_register(&nmk_pinctrl_driver);
+}
+
+core_initcall(nmk_gpio_init);
+
+MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
+MODULE_DESCRIPTION("Nomadik GPIO Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1257 @@
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-nomadik.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define _GPIO(offset)		(offset)
+
+#define DB8500_PIN_AJ5		_GPIO(0)
+#define DB8500_PIN_AJ3		_GPIO(1)
+#define DB8500_PIN_AH4		_GPIO(2)
+#define DB8500_PIN_AH3		_GPIO(3)
+#define DB8500_PIN_AH6		_GPIO(4)
+#define DB8500_PIN_AG6		_GPIO(5)
+#define DB8500_PIN_AF6		_GPIO(6)
+#define DB8500_PIN_AG5		_GPIO(7)
+#define DB8500_PIN_AD5		_GPIO(8)
+#define DB8500_PIN_AE4		_GPIO(9)
+#define DB8500_PIN_AF5		_GPIO(10)
+#define DB8500_PIN_AG4		_GPIO(11)
+#define DB8500_PIN_AC4		_GPIO(12)
+#define DB8500_PIN_AF3		_GPIO(13)
+#define DB8500_PIN_AE3		_GPIO(14)
+#define DB8500_PIN_AC3		_GPIO(15)
+#define DB8500_PIN_AD3		_GPIO(16)
+#define DB8500_PIN_AD4		_GPIO(17)
+#define DB8500_PIN_AC2		_GPIO(18)
+#define DB8500_PIN_AC1		_GPIO(19)
+#define DB8500_PIN_AB4		_GPIO(20)
+#define DB8500_PIN_AB3		_GPIO(21)
+#define DB8500_PIN_AA3		_GPIO(22)
+#define DB8500_PIN_AA4		_GPIO(23)
+#define DB8500_PIN_AB2		_GPIO(24)
+#define DB8500_PIN_Y4		_GPIO(25)
+#define DB8500_PIN_Y2		_GPIO(26)
+#define DB8500_PIN_AA2		_GPIO(27)
+#define DB8500_PIN_AA1		_GPIO(28)
+#define DB8500_PIN_W2		_GPIO(29)
+#define DB8500_PIN_W3		_GPIO(30)
+#define DB8500_PIN_V3		_GPIO(31)
+#define DB8500_PIN_V2		_GPIO(32)
+#define DB8500_PIN_AF2		_GPIO(33)
+#define DB8500_PIN_AE1		_GPIO(34)
+#define DB8500_PIN_AE2		_GPIO(35)
+#define DB8500_PIN_AG2		_GPIO(36)
+/* Hole */
+#define DB8500_PIN_F3		_GPIO(64)
+#define DB8500_PIN_F1		_GPIO(65)
+#define DB8500_PIN_G3		_GPIO(66)
+#define DB8500_PIN_G2		_GPIO(67)
+#define DB8500_PIN_E1		_GPIO(68)
+#define DB8500_PIN_E2		_GPIO(69)
+#define DB8500_PIN_G5		_GPIO(70)
+#define DB8500_PIN_G4		_GPIO(71)
+#define DB8500_PIN_H4		_GPIO(72)
+#define DB8500_PIN_H3		_GPIO(73)
+#define DB8500_PIN_J3		_GPIO(74)
+#define DB8500_PIN_H2		_GPIO(75)
+#define DB8500_PIN_J2		_GPIO(76)
+#define DB8500_PIN_H1		_GPIO(77)
+#define DB8500_PIN_F4		_GPIO(78)
+#define DB8500_PIN_E3		_GPIO(79)
+#define DB8500_PIN_E4		_GPIO(80)
+#define DB8500_PIN_D2		_GPIO(81)
+#define DB8500_PIN_C1		_GPIO(82)
+#define DB8500_PIN_D3		_GPIO(83)
+#define DB8500_PIN_C2		_GPIO(84)
+#define DB8500_PIN_D5		_GPIO(85)
+#define DB8500_PIN_C6		_GPIO(86)
+#define DB8500_PIN_B3		_GPIO(87)
+#define DB8500_PIN_C4		_GPIO(88)
+#define DB8500_PIN_E6		_GPIO(89)
+#define DB8500_PIN_A3		_GPIO(90)
+#define DB8500_PIN_B6		_GPIO(91)
+#define DB8500_PIN_D6		_GPIO(92)
+#define DB8500_PIN_B7		_GPIO(93)
+#define DB8500_PIN_D7		_GPIO(94)
+#define DB8500_PIN_E8		_GPIO(95)
+#define DB8500_PIN_D8		_GPIO(96)
+#define DB8500_PIN_D9		_GPIO(97)
+/* Hole */
+#define DB8500_PIN_A5		_GPIO(128)
+#define DB8500_PIN_B4		_GPIO(129)
+#define DB8500_PIN_C8		_GPIO(130)
+#define DB8500_PIN_A12		_GPIO(131)
+#define DB8500_PIN_C10		_GPIO(132)
+#define DB8500_PIN_B10		_GPIO(133)
+#define DB8500_PIN_B9		_GPIO(134)
+#define DB8500_PIN_A9		_GPIO(135)
+#define DB8500_PIN_C7		_GPIO(136)
+#define DB8500_PIN_A7		_GPIO(137)
+#define DB8500_PIN_C5		_GPIO(138)
+#define DB8500_PIN_C9		_GPIO(139)
+#define DB8500_PIN_B11		_GPIO(140)
+#define DB8500_PIN_C12		_GPIO(141)
+#define DB8500_PIN_C11		_GPIO(142)
+#define DB8500_PIN_D12		_GPIO(143)
+#define DB8500_PIN_B13		_GPIO(144)
+#define DB8500_PIN_C13		_GPIO(145)
+#define DB8500_PIN_D13		_GPIO(146)
+#define DB8500_PIN_C15		_GPIO(147)
+#define DB8500_PIN_B16		_GPIO(148)
+#define DB8500_PIN_B14		_GPIO(149)
+#define DB8500_PIN_C14		_GPIO(150)
+#define DB8500_PIN_D17		_GPIO(151)
+#define DB8500_PIN_D16		_GPIO(152)
+#define DB8500_PIN_B17		_GPIO(153)
+#define DB8500_PIN_C16		_GPIO(154)
+#define DB8500_PIN_C19		_GPIO(155)
+#define DB8500_PIN_C17		_GPIO(156)
+#define DB8500_PIN_A18		_GPIO(157)
+#define DB8500_PIN_C18		_GPIO(158)
+#define DB8500_PIN_B19		_GPIO(159)
+#define DB8500_PIN_B20		_GPIO(160)
+#define DB8500_PIN_D21		_GPIO(161)
+#define DB8500_PIN_D20		_GPIO(162)
+#define DB8500_PIN_C20		_GPIO(163)
+#define DB8500_PIN_B21		_GPIO(164)
+#define DB8500_PIN_C21		_GPIO(165)
+#define DB8500_PIN_A22		_GPIO(166)
+#define DB8500_PIN_B24		_GPIO(167)
+#define DB8500_PIN_C22		_GPIO(168)
+#define DB8500_PIN_D22		_GPIO(169)
+#define DB8500_PIN_C23		_GPIO(170)
+#define DB8500_PIN_D23		_GPIO(171)
+/* Hole */
+#define DB8500_PIN_AJ27		_GPIO(192)
+#define DB8500_PIN_AH27		_GPIO(193)
+#define DB8500_PIN_AF27		_GPIO(194)
+#define DB8500_PIN_AG28		_GPIO(195)
+#define DB8500_PIN_AG26		_GPIO(196)
+#define DB8500_PIN_AH24		_GPIO(197)
+#define DB8500_PIN_AG25		_GPIO(198)
+#define DB8500_PIN_AH23		_GPIO(199)
+#define DB8500_PIN_AH26		_GPIO(200)
+#define DB8500_PIN_AF24		_GPIO(201)
+#define DB8500_PIN_AF25		_GPIO(202)
+#define DB8500_PIN_AE23		_GPIO(203)
+#define DB8500_PIN_AF23		_GPIO(204)
+#define DB8500_PIN_AG23		_GPIO(205)
+#define DB8500_PIN_AG24		_GPIO(206)
+#define DB8500_PIN_AJ23		_GPIO(207)
+#define DB8500_PIN_AH16		_GPIO(208)
+#define DB8500_PIN_AG15		_GPIO(209)
+#define DB8500_PIN_AJ15		_GPIO(210)
+#define DB8500_PIN_AG14		_GPIO(211)
+#define DB8500_PIN_AF13		_GPIO(212)
+#define DB8500_PIN_AG13		_GPIO(213)
+#define DB8500_PIN_AH15		_GPIO(214)
+#define DB8500_PIN_AH13		_GPIO(215)
+#define DB8500_PIN_AG12		_GPIO(216)
+#define DB8500_PIN_AH12		_GPIO(217)
+#define DB8500_PIN_AH11		_GPIO(218)
+#define DB8500_PIN_AG10		_GPIO(219)
+#define DB8500_PIN_AH10		_GPIO(220)
+#define DB8500_PIN_AJ11		_GPIO(221)
+#define DB8500_PIN_AJ9		_GPIO(222)
+#define DB8500_PIN_AH9		_GPIO(223)
+#define DB8500_PIN_AG9		_GPIO(224)
+#define DB8500_PIN_AG8		_GPIO(225)
+#define DB8500_PIN_AF8		_GPIO(226)
+#define DB8500_PIN_AH7		_GPIO(227)
+#define DB8500_PIN_AJ6		_GPIO(228)
+#define DB8500_PIN_AG7		_GPIO(229)
+#define DB8500_PIN_AF7		_GPIO(230)
+/* Hole */
+#define DB8500_PIN_AF28		_GPIO(256)
+#define DB8500_PIN_AE29		_GPIO(257)
+#define DB8500_PIN_AD29		_GPIO(258)
+#define DB8500_PIN_AC29		_GPIO(259)
+#define DB8500_PIN_AD28		_GPIO(260)
+#define DB8500_PIN_AD26		_GPIO(261)
+#define DB8500_PIN_AE26		_GPIO(262)
+#define DB8500_PIN_AG29		_GPIO(263)
+#define DB8500_PIN_AE27		_GPIO(264)
+#define DB8500_PIN_AD27		_GPIO(265)
+#define DB8500_PIN_AC28		_GPIO(266)
+#define DB8500_PIN_AC27		_GPIO(267)
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc nmk_db8500_pins[] = {
+	PINCTRL_PIN(DB8500_PIN_AJ5, "GPIO0_AJ5"),
+	PINCTRL_PIN(DB8500_PIN_AJ3, "GPIO1_AJ3"),
+	PINCTRL_PIN(DB8500_PIN_AH4, "GPIO2_AH4"),
+	PINCTRL_PIN(DB8500_PIN_AH3, "GPIO3_AH3"),
+	PINCTRL_PIN(DB8500_PIN_AH6, "GPIO4_AH6"),
+	PINCTRL_PIN(DB8500_PIN_AG6, "GPIO5_AG6"),
+	PINCTRL_PIN(DB8500_PIN_AF6, "GPIO6_AF6"),
+	PINCTRL_PIN(DB8500_PIN_AG5, "GPIO7_AG5"),
+	PINCTRL_PIN(DB8500_PIN_AD5, "GPIO8_AD5"),
+	PINCTRL_PIN(DB8500_PIN_AE4, "GPIO9_AE4"),
+	PINCTRL_PIN(DB8500_PIN_AF5, "GPIO10_AF5"),
+	PINCTRL_PIN(DB8500_PIN_AG4, "GPIO11_AG4"),
+	PINCTRL_PIN(DB8500_PIN_AC4, "GPIO12_AC4"),
+	PINCTRL_PIN(DB8500_PIN_AF3, "GPIO13_AF3"),
+	PINCTRL_PIN(DB8500_PIN_AE3, "GPIO14_AE3"),
+	PINCTRL_PIN(DB8500_PIN_AC3, "GPIO15_AC3"),
+	PINCTRL_PIN(DB8500_PIN_AD3, "GPIO16_AD3"),
+	PINCTRL_PIN(DB8500_PIN_AD4, "GPIO17_AD4"),
+	PINCTRL_PIN(DB8500_PIN_AC2, "GPIO18_AC2"),
+	PINCTRL_PIN(DB8500_PIN_AC1, "GPIO19_AC1"),
+	PINCTRL_PIN(DB8500_PIN_AB4, "GPIO20_AB4"),
+	PINCTRL_PIN(DB8500_PIN_AB3, "GPIO21_AB3"),
+	PINCTRL_PIN(DB8500_PIN_AA3, "GPIO22_AA3"),
+	PINCTRL_PIN(DB8500_PIN_AA4, "GPIO23_AA4"),
+	PINCTRL_PIN(DB8500_PIN_AB2, "GPIO24_AB2"),
+	PINCTRL_PIN(DB8500_PIN_Y4, "GPIO25_Y4"),
+	PINCTRL_PIN(DB8500_PIN_Y2, "GPIO26_Y2"),
+	PINCTRL_PIN(DB8500_PIN_AA2, "GPIO27_AA2"),
+	PINCTRL_PIN(DB8500_PIN_AA1, "GPIO28_AA1"),
+	PINCTRL_PIN(DB8500_PIN_W2, "GPIO29_W2"),
+	PINCTRL_PIN(DB8500_PIN_W3, "GPIO30_W3"),
+	PINCTRL_PIN(DB8500_PIN_V3, "GPIO31_V3"),
+	PINCTRL_PIN(DB8500_PIN_V2, "GPIO32_V2"),
+	PINCTRL_PIN(DB8500_PIN_AF2, "GPIO33_AF2"),
+	PINCTRL_PIN(DB8500_PIN_AE1, "GPIO34_AE1"),
+	PINCTRL_PIN(DB8500_PIN_AE2, "GPIO35_AE2"),
+	PINCTRL_PIN(DB8500_PIN_AG2, "GPIO36_AG2"),
+	/* Hole */
+	PINCTRL_PIN(DB8500_PIN_F3, "GPIO64_F3"),
+	PINCTRL_PIN(DB8500_PIN_F1, "GPIO65_F1"),
+	PINCTRL_PIN(DB8500_PIN_G3, "GPIO66_G3"),
+	PINCTRL_PIN(DB8500_PIN_G2, "GPIO67_G2"),
+	PINCTRL_PIN(DB8500_PIN_E1, "GPIO68_E1"),
+	PINCTRL_PIN(DB8500_PIN_E2, "GPIO69_E2"),
+	PINCTRL_PIN(DB8500_PIN_G5, "GPIO70_G5"),
+	PINCTRL_PIN(DB8500_PIN_G4, "GPIO71_G4"),
+	PINCTRL_PIN(DB8500_PIN_H4, "GPIO72_H4"),
+	PINCTRL_PIN(DB8500_PIN_H3, "GPIO73_H3"),
+	PINCTRL_PIN(DB8500_PIN_J3, "GPIO74_J3"),
+	PINCTRL_PIN(DB8500_PIN_H2, "GPIO75_H2"),
+	PINCTRL_PIN(DB8500_PIN_J2, "GPIO76_J2"),
+	PINCTRL_PIN(DB8500_PIN_H1, "GPIO77_H1"),
+	PINCTRL_PIN(DB8500_PIN_F4, "GPIO78_F4"),
+	PINCTRL_PIN(DB8500_PIN_E3, "GPIO79_E3"),
+	PINCTRL_PIN(DB8500_PIN_E4, "GPIO80_E4"),
+	PINCTRL_PIN(DB8500_PIN_D2, "GPIO81_D2"),
+	PINCTRL_PIN(DB8500_PIN_C1, "GPIO82_C1"),
+	PINCTRL_PIN(DB8500_PIN_D3, "GPIO83_D3"),
+	PINCTRL_PIN(DB8500_PIN_C2, "GPIO84_C2"),
+	PINCTRL_PIN(DB8500_PIN_D5, "GPIO85_D5"),
+	PINCTRL_PIN(DB8500_PIN_C6, "GPIO86_C6"),
+	PINCTRL_PIN(DB8500_PIN_B3, "GPIO87_B3"),
+	PINCTRL_PIN(DB8500_PIN_C4, "GPIO88_C4"),
+	PINCTRL_PIN(DB8500_PIN_E6, "GPIO89_E6"),
+	PINCTRL_PIN(DB8500_PIN_A3, "GPIO90_A3"),
+	PINCTRL_PIN(DB8500_PIN_B6, "GPIO91_B6"),
+	PINCTRL_PIN(DB8500_PIN_D6, "GPIO92_D6"),
+	PINCTRL_PIN(DB8500_PIN_B7, "GPIO93_B7"),
+	PINCTRL_PIN(DB8500_PIN_D7, "GPIO94_D7"),
+	PINCTRL_PIN(DB8500_PIN_E8, "GPIO95_E8"),
+	PINCTRL_PIN(DB8500_PIN_D8, "GPIO96_D8"),
+	PINCTRL_PIN(DB8500_PIN_D9, "GPIO97_D9"),
+	/* Hole */
+	PINCTRL_PIN(DB8500_PIN_A5, "GPIO128_A5"),
+	PINCTRL_PIN(DB8500_PIN_B4, "GPIO129_B4"),
+	PINCTRL_PIN(DB8500_PIN_C8, "GPIO130_C8"),
+	PINCTRL_PIN(DB8500_PIN_A12, "GPIO131_A12"),
+	PINCTRL_PIN(DB8500_PIN_C10, "GPIO132_C10"),
+	PINCTRL_PIN(DB8500_PIN_B10, "GPIO133_B10"),
+	PINCTRL_PIN(DB8500_PIN_B9, "GPIO134_B9"),
+	PINCTRL_PIN(DB8500_PIN_A9, "GPIO135_A9"),
+	PINCTRL_PIN(DB8500_PIN_C7, "GPIO136_C7"),
+	PINCTRL_PIN(DB8500_PIN_A7, "GPIO137_A7"),
+	PINCTRL_PIN(DB8500_PIN_C5, "GPIO138_C5"),
+	PINCTRL_PIN(DB8500_PIN_C9, "GPIO139_C9"),
+	PINCTRL_PIN(DB8500_PIN_B11, "GPIO140_B11"),
+	PINCTRL_PIN(DB8500_PIN_C12, "GPIO141_C12"),
+	PINCTRL_PIN(DB8500_PIN_C11, "GPIO142_C11"),
+	PINCTRL_PIN(DB8500_PIN_D12, "GPIO143_D12"),
+	PINCTRL_PIN(DB8500_PIN_B13, "GPIO144_B13"),
+	PINCTRL_PIN(DB8500_PIN_C13, "GPIO145_C13"),
+	PINCTRL_PIN(DB8500_PIN_D13, "GPIO146_D13"),
+	PINCTRL_PIN(DB8500_PIN_C15, "GPIO147_C15"),
+	PINCTRL_PIN(DB8500_PIN_B16, "GPIO148_B16"),
+	PINCTRL_PIN(DB8500_PIN_B14, "GPIO149_B14"),
+	PINCTRL_PIN(DB8500_PIN_C14, "GPIO150_C14"),
+	PINCTRL_PIN(DB8500_PIN_D17, "GPIO151_D17"),
+	PINCTRL_PIN(DB8500_PIN_D16, "GPIO152_D16"),
+	PINCTRL_PIN(DB8500_PIN_B17, "GPIO153_B17"),
+	PINCTRL_PIN(DB8500_PIN_C16, "GPIO154_C16"),
+	PINCTRL_PIN(DB8500_PIN_C19, "GPIO155_C19"),
+	PINCTRL_PIN(DB8500_PIN_C17, "GPIO156_C17"),
+	PINCTRL_PIN(DB8500_PIN_A18, "GPIO157_A18"),
+	PINCTRL_PIN(DB8500_PIN_C18, "GPIO158_C18"),
+	PINCTRL_PIN(DB8500_PIN_B19, "GPIO159_B19"),
+	PINCTRL_PIN(DB8500_PIN_B20, "GPIO160_B20"),
+	PINCTRL_PIN(DB8500_PIN_D21, "GPIO161_D21"),
+	PINCTRL_PIN(DB8500_PIN_D20, "GPIO162_D20"),
+	PINCTRL_PIN(DB8500_PIN_C20, "GPIO163_C20"),
+	PINCTRL_PIN(DB8500_PIN_B21, "GPIO164_B21"),
+	PINCTRL_PIN(DB8500_PIN_C21, "GPIO165_C21"),
+	PINCTRL_PIN(DB8500_PIN_A22, "GPIO166_A22"),
+	PINCTRL_PIN(DB8500_PIN_B24, "GPIO167_B24"),
+	PINCTRL_PIN(DB8500_PIN_C22, "GPIO168_C22"),
+	PINCTRL_PIN(DB8500_PIN_D22, "GPIO169_D22"),
+	PINCTRL_PIN(DB8500_PIN_C23, "GPIO170_C23"),
+	PINCTRL_PIN(DB8500_PIN_D23, "GPIO171_D23"),
+	/* Hole */
+	PINCTRL_PIN(DB8500_PIN_AJ27, "GPIO192_AJ27"),
+	PINCTRL_PIN(DB8500_PIN_AH27, "GPIO193_AH27"),
+	PINCTRL_PIN(DB8500_PIN_AF27, "GPIO194_AF27"),
+	PINCTRL_PIN(DB8500_PIN_AG28, "GPIO195_AG28"),
+	PINCTRL_PIN(DB8500_PIN_AG26, "GPIO196_AG26"),
+	PINCTRL_PIN(DB8500_PIN_AH24, "GPIO197_AH24"),
+	PINCTRL_PIN(DB8500_PIN_AG25, "GPIO198_AG25"),
+	PINCTRL_PIN(DB8500_PIN_AH23, "GPIO199_AH23"),
+	PINCTRL_PIN(DB8500_PIN_AH26, "GPIO200_AH26"),
+	PINCTRL_PIN(DB8500_PIN_AF24, "GPIO201_AF24"),
+	PINCTRL_PIN(DB8500_PIN_AF25, "GPIO202_AF25"),
+	PINCTRL_PIN(DB8500_PIN_AE23, "GPIO203_AE23"),
+	PINCTRL_PIN(DB8500_PIN_AF23, "GPIO204_AF23"),
+	PINCTRL_PIN(DB8500_PIN_AG23, "GPIO205_AG23"),
+	PINCTRL_PIN(DB8500_PIN_AG24, "GPIO206_AG24"),
+	PINCTRL_PIN(DB8500_PIN_AJ23, "GPIO207_AJ23"),
+	PINCTRL_PIN(DB8500_PIN_AH16, "GPIO208_AH16"),
+	PINCTRL_PIN(DB8500_PIN_AG15, "GPIO209_AG15"),
+	PINCTRL_PIN(DB8500_PIN_AJ15, "GPIO210_AJ15"),
+	PINCTRL_PIN(DB8500_PIN_AG14, "GPIO211_AG14"),
+	PINCTRL_PIN(DB8500_PIN_AF13, "GPIO212_AF13"),
+	PINCTRL_PIN(DB8500_PIN_AG13, "GPIO213_AG13"),
+	PINCTRL_PIN(DB8500_PIN_AH15, "GPIO214_AH15"),
+	PINCTRL_PIN(DB8500_PIN_AH13, "GPIO215_AH13"),
+	PINCTRL_PIN(DB8500_PIN_AG12, "GPIO216_AG12"),
+	PINCTRL_PIN(DB8500_PIN_AH12, "GPIO217_AH12"),
+	PINCTRL_PIN(DB8500_PIN_AH11, "GPIO218_AH11"),
+	PINCTRL_PIN(DB8500_PIN_AG10, "GPIO219_AG10"),
+	PINCTRL_PIN(DB8500_PIN_AH10, "GPIO220_AH10"),
+	PINCTRL_PIN(DB8500_PIN_AJ11, "GPIO221_AJ11"),
+	PINCTRL_PIN(DB8500_PIN_AJ9, "GPIO222_AJ9"),
+	PINCTRL_PIN(DB8500_PIN_AH9, "GPIO223_AH9"),
+	PINCTRL_PIN(DB8500_PIN_AG9, "GPIO224_AG9"),
+	PINCTRL_PIN(DB8500_PIN_AG8, "GPIO225_AG8"),
+	PINCTRL_PIN(DB8500_PIN_AF8, "GPIO226_AF8"),
+	PINCTRL_PIN(DB8500_PIN_AH7, "GPIO227_AH7"),
+	PINCTRL_PIN(DB8500_PIN_AJ6, "GPIO228_AJ6"),
+	PINCTRL_PIN(DB8500_PIN_AG7, "GPIO229_AG7"),
+	PINCTRL_PIN(DB8500_PIN_AF7, "GPIO230_AF7"),
+	/* Hole */
+	PINCTRL_PIN(DB8500_PIN_AF28, "GPIO256_AF28"),
+	PINCTRL_PIN(DB8500_PIN_AE29, "GPIO257_AE29"),
+	PINCTRL_PIN(DB8500_PIN_AD29, "GPIO258_AD29"),
+	PINCTRL_PIN(DB8500_PIN_AC29, "GPIO259_AC29"),
+	PINCTRL_PIN(DB8500_PIN_AD28, "GPIO260_AD28"),
+	PINCTRL_PIN(DB8500_PIN_AD26, "GPIO261_AD26"),
+	PINCTRL_PIN(DB8500_PIN_AE26, "GPIO262_AE26"),
+	PINCTRL_PIN(DB8500_PIN_AG29, "GPIO263_AG29"),
+	PINCTRL_PIN(DB8500_PIN_AE27, "GPIO264_AE27"),
+	PINCTRL_PIN(DB8500_PIN_AD27, "GPIO265_AD27"),
+	PINCTRL_PIN(DB8500_PIN_AC28, "GPIO266_AC28"),
+	PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"),
+};
+
+#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \
+			.pin_base = b, .npins = c }
+
+/*
+ * This matches the 32-pin gpio chips registered by the GPIO portion. This
+ * cannot be const since we assign the struct gpio_chip * pointer at runtime.
+ */
+static struct pinctrl_gpio_range nmk_db8500_ranges[] = {
+	DB8500_GPIO_RANGE(0, 0, 32),
+	DB8500_GPIO_RANGE(1, 32, 5),
+	DB8500_GPIO_RANGE(2, 64, 32),
+	DB8500_GPIO_RANGE(3, 96, 2),
+	DB8500_GPIO_RANGE(4, 128, 32),
+	DB8500_GPIO_RANGE(5, 160, 12),
+	DB8500_GPIO_RANGE(6, 192, 32),
+	DB8500_GPIO_RANGE(7, 224, 7),
+	DB8500_GPIO_RANGE(8, 256, 12),
+};
+
+/*
+ * Read the pin group names like this:
+ * u0_a_1    = first groups of pins for uart0 on alt function a
+ * i2c2_b_2  = second group of pins for i2c2 on alt function b
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* Altfunction A column */
+static const unsigned u0_a_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
+					DB8500_PIN_AH4, DB8500_PIN_AH3 };
+static const unsigned u1rxtx_a_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
+static const unsigned u1ctsrts_a_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
+/* Image processor I2C line, this is driven by image processor firmware */
+static const unsigned ipi2c_a_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
+static const unsigned ipi2c_a_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
+/* MSP0 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
+static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 };
+static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Basic pins of the MMC/SD card 0 interface */
+static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
+	DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
+	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+/* Often only 4 bits are used, then these are not needed (only used for MMC) */
+static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
+	DB8500_PIN_V3, DB8500_PIN_V2};
+static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 };
+/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
+static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 };
+/* LCD interface */
+static const unsigned lcdb_a_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
+					  DB8500_PIN_G3, DB8500_PIN_G2 };
+static const unsigned lcdvsi0_a_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned lcdvsi1_a_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned lcd_d0_d7_a_1_pins[] = {
+	DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
+	DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1 };
+/* D8 thru D11 often used as TVOUT lines */
+static const unsigned lcd_d8_d11_a_1_pins[] = { DB8500_PIN_F4,
+	DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2 };
+static const unsigned lcd_d12_d23_a_1_pins[] = {
+	DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5,
+	DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6,
+	DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned kp_a_1_pins[] = { DB8500_PIN_D7, DB8500_PIN_E8,
+	DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned kpskaskb_a_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16 };
+static const unsigned kp_a_2_pins[] = {
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+/* MC2 has 8 data lines and no direction control, so only for (e)MMC */
+static const unsigned mc2_a_1_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4,
+	DB8500_PIN_C8, DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10,
+	DB8500_PIN_B9, DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7,
+	DB8500_PIN_C5 };
+static const unsigned ssp1_a_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
+					  DB8500_PIN_C12, DB8500_PIN_C11 };
+static const unsigned ssp0_a_1_pins[] = { DB8500_PIN_D12, DB8500_PIN_B13,
+					  DB8500_PIN_C13, DB8500_PIN_D13 };
+static const unsigned i2c0_a_1_pins[] = { DB8500_PIN_C15, DB8500_PIN_B16 };
+/*
+ * Image processor GPIO pins are named "ipgpio" and have their own
+ * numberspace
+ */
+static const unsigned ipgpio0_a_1_pins[] = { DB8500_PIN_B14 };
+static const unsigned ipgpio1_a_1_pins[] = { DB8500_PIN_C14 };
+/* Three modem pins named RF_PURn, MODEM_STATE and MODEM_PWREN */
+static const unsigned modem_a_1_pins[] = { DB8500_PIN_D22, DB8500_PIN_C23,
+					   DB8500_PIN_D23 };
+/*
+ * This MSP cannot switch RX and TX, SCK in a separate group since this
+ * seems to be optional.
+ */
+static const unsigned msp2sck_a_1_pins[] = { DB8500_PIN_AJ27 };
+static const unsigned msp2_a_1_pins[] = { DB8500_PIN_AH27, DB8500_PIN_AF27,
+					  DB8500_PIN_AG28, DB8500_PIN_AG26 };
+static const unsigned mc4_a_1_pins[] = { DB8500_PIN_AH24, DB8500_PIN_AG25,
+	DB8500_PIN_AH23, DB8500_PIN_AH26, DB8500_PIN_AF24, DB8500_PIN_AF25,
+	DB8500_PIN_AE23, DB8500_PIN_AF23, DB8500_PIN_AG23, DB8500_PIN_AG24,
+	DB8500_PIN_AJ23 };
+/* MC1 has only 4 data pins, designed for SD or SDIO exclusively */
+static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15,
+	DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
+	DB8500_PIN_AH15 };
+static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15,
+	DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 };
+static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+	DB8500_PIN_AH12, DB8500_PIN_AH11 };
+static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10,
+	DB8500_PIN_AJ11 };
+static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
+	DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
+static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
+	DB8500_PIN_AG9, DB8500_PIN_AG8 };
+static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 };
+static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 };
+static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 };
+static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29,
+	DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26,
+	DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27,
+	DB8500_PIN_AC28, DB8500_PIN_AC27 };
+
+/* Altfunction B column */
+static const unsigned trig_b_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3 };
+static const unsigned i2c4_b_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
+static const unsigned i2c1_b_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
+static const unsigned i2c2_b_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
+static const unsigned i2c2_b_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
+static const unsigned msp0txrx_b_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
+static const unsigned i2c1_b_2_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Just RX and TX for UART2 */
+static const unsigned u2rxtx_b_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1 };
+static const unsigned uartmodtx_b_1_pins[] = { DB8500_PIN_AB4 };
+static const unsigned msp0sck_b_1_pins[] = { DB8500_PIN_AB3 };
+static const unsigned uartmodrx_b_1_pins[] = { DB8500_PIN_AA3 };
+static const unsigned stmmod_b_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+	DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned uartmodrx_b_2_pins[] = { DB8500_PIN_AB2 };
+static const unsigned spi3_b_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
+					  DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned msp1txrx_b_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
+static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
+	DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_E1, DB8500_PIN_E2,
+	DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
+	DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1,
+	DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2,
+	DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 };
+static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
+	DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3};
+static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+	DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
+	DB8500_PIN_D9, DB8500_PIN_A5, DB8500_PIN_B4, DB8500_PIN_C8,
+	DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9,
+	DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5,
+	DB8500_PIN_C9 };
+/* This chip select pin can be "ps0" in alt C so have it separately */
+static const unsigned smcs0_b_1_pins[] = { DB8500_PIN_E8 };
+/* This chip select pin can be "ps1" in alt C so have it separately */
+static const unsigned smcs1_b_1_pins[] = { DB8500_PIN_B14 };
+static const unsigned ipgpio7_b_1_pins[] = { DB8500_PIN_B11 };
+static const unsigned ipgpio2_b_1_pins[] = { DB8500_PIN_C12 };
+static const unsigned ipgpio3_b_1_pins[] = { DB8500_PIN_C11 };
+static const unsigned lcdaclk_b_1_pins[] = { DB8500_PIN_C14 };
+static const unsigned lcda_b_1_pins[] = { DB8500_PIN_D22,
+	DB8500_PIN_C23, DB8500_PIN_D23 };
+static const unsigned lcd_b_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+static const unsigned ddrtrig_b_1_pins[] = { DB8500_PIN_AJ27 };
+static const unsigned pwl_b_1_pins[] = { DB8500_PIN_AF25 };
+static const unsigned spi1_b_1_pins[] = { DB8500_PIN_AG15, DB8500_PIN_AF13,
+					  DB8500_PIN_AG13, DB8500_PIN_AH15 };
+static const unsigned mc3_b_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+	DB8500_PIN_AH12, DB8500_PIN_AH11, DB8500_PIN_AG10, DB8500_PIN_AH10,
+	DB8500_PIN_AJ11, DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9,
+	DB8500_PIN_AG8 };
+static const unsigned pwl_b_2_pins[] = { DB8500_PIN_AF8 };
+static const unsigned pwl_b_3_pins[] = { DB8500_PIN_AG7 };
+static const unsigned pwl_b_4_pins[] = { DB8500_PIN_AF7 };
+
+/* Altfunction C column */
+static const unsigned ipjtag_c_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
+	DB8500_PIN_AH4, DB8500_PIN_AH3, DB8500_PIN_AH6 };
+static const unsigned ipgpio6_c_1_pins[] = { DB8500_PIN_AG6 };
+static const unsigned ipgpio0_c_1_pins[] = { DB8500_PIN_AF6 };
+static const unsigned ipgpio1_c_1_pins[] = { DB8500_PIN_AG5 };
+static const unsigned ipgpio3_c_1_pins[] = { DB8500_PIN_AF5 };
+static const unsigned ipgpio2_c_1_pins[] = { DB8500_PIN_AG4 };
+static const unsigned slim0_c_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
+/* Optional 4-bit Memory Stick interface */
+static const unsigned ms_c_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
+	DB8500_PIN_AB3, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
+	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned iptrigout_c_1_pins[] = { DB8500_PIN_AB4 };
+static const unsigned u2rxtx_c_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3 };
+static const unsigned u2ctsrts_c_1_pins[] = { DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned u0_c_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AE1,
+					DB8500_PIN_AE2, DB8500_PIN_AG2 };
+static const unsigned ipgpio4_c_1_pins[] = { DB8500_PIN_F3 };
+static const unsigned ipgpio5_c_1_pins[] = { DB8500_PIN_F1 };
+static const unsigned ipgpio6_c_2_pins[] = { DB8500_PIN_G3 };
+static const unsigned ipgpio7_c_1_pins[] = { DB8500_PIN_G2 };
+static const unsigned smcleale_c_1_pins[] = { DB8500_PIN_E1, DB8500_PIN_E2 };
+static const unsigned stmape_c_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned u2rxtx_c_2_pins[] = { DB8500_PIN_H2, DB8500_PIN_J2 };
+static const unsigned ipgpio2_c_2_pins[] = { DB8500_PIN_F4 };
+static const unsigned ipgpio3_c_2_pins[] = { DB8500_PIN_E3 };
+static const unsigned ipgpio4_c_2_pins[] = { DB8500_PIN_E4 };
+static const unsigned ipgpio5_c_2_pins[] = { DB8500_PIN_D2 };
+static const unsigned mc5_c_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+	DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
+	DB8500_PIN_D9 };
+static const unsigned mc2rstn_c_1_pins[] = { DB8500_PIN_C8 };
+static const unsigned kp_c_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
+	DB8500_PIN_C12, DB8500_PIN_C11, DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_C23, DB8500_PIN_D23 };
+static const unsigned smps0_c_1_pins[] = { DB8500_PIN_E8 };
+static const unsigned smps1_c_1_pins[] = { DB8500_PIN_B14 };
+static const unsigned u2rxtx_c_3_pins[] = { DB8500_PIN_B17, DB8500_PIN_C16 };
+static const unsigned stmape_c_2_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned uartmodrx_c_1_pins[] = { DB8500_PIN_D21 };
+static const unsigned uartmodtx_c_1_pins[] = { DB8500_PIN_D20 };
+static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 };
+static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 };
+static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 };
+static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 };
+static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 };
+static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 };
+static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9,
+					  DB8500_PIN_AG9, DB8500_PIN_AG8 };
+static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 };
+static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
+
+/* Other C1 column */
+static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 };
+static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+	DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+	DB8500_PIN_J2, DB8500_PIN_H1 };
+static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
+	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
+	DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 };
+static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 };
+static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 };
+static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20,
+	DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22,
+	DB8500_PIN_B24, DB8500_PIN_C22 };
+static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 };
+static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
+	DB8500_PIN_AH12, DB8500_PIN_AH11 };
+static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12,
+	DB8500_PIN_AH11 };
+
+/* Other C2 column */
+static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2,
+	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+	DB8500_PIN_J2, DB8500_PIN_H1 };
+static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C3 column */
+static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2,
+	DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 };
+static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 };
+static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C4 column */
+static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 };
+static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct nmk_pingroup nmk_db8500_groups[] = {
+	/* Altfunction A column */
+	DB8500_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc0_dat47_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc0dat31dir_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(mc1_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
+	/* Altfunction B column */
+	DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(u2rxtx_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(uartmodtx_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(msp0sck_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(uartmodrx_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(uartmodrx_b_2, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(lcdaclk_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(lcda_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(lcd_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B),
+	DB8500_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B),
+	/* Altfunction C column */
+	DB8500_PIN_GROUP(ipjtag_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(slim0_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ms_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(iptrigout_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(u2ctsrts_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(u2rxtx_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(u2rxtx_c_3, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(stmape_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(uartmodrx_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(uartmodtx_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
+	/* Other alt C1 column */
+	DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
+	/* Other alt C2 column */
+	DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+	DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2),
+	DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2),
+	/* Other alt C3 column */
+	DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3),
+	/* Other alt C4 column */
+	DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4),
+	DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define DB8500_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+DB8500_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1");
+DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
+/*
+ * UART2 can be muxed out with just RX/TX in four places, CTS+RTS is however
+ * only available on two pins in alternative function C
+ */
+DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1",
+		   "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1");
+DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
+/*
+ * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
+ * switched around by selecting the altfunction A or B. The SCK pin is
+ * only available on the altfunction B.
+ */
+DB8500_FUNC_GROUPS(msp0, "msp0txrx_a_1", "msp0tfstck_a_1", "msp0rfstck_a_1",
+		   "msp0txrx_b_1", "msp0sck_b_1");
+DB8500_FUNC_GROUPS(mc0, "mc0_a_1", "mc0_dat47_a_1", "mc0dat31dir_a_1");
+/* MSP0 can swap RX/TX like MSP0 but has no SCK pin available */
+DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");
+DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");
+DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",
+	"lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1");
+DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
+DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
+DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");
+DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1");
+DB8500_FUNC_GROUPS(i2c0, "i2c0_a_1");
+/* The image processor has 8 GPIO pins that can be muxed out */
+DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1",
+	"ipgpio2_b_1", "ipgpio3_b_1", "ipgpio6_c_1", "ipgpio0_c_1",
+	"ipgpio1_c_1", "ipgpio3_c_1", "ipgpio2_c_1", "ipgpio4_c_1",
+	"ipgpio5_c_1", "ipgpio6_c_2", "ipgpio7_c_1", "ipgpio2_c_2",
+	"ipgpio3_c_2", "ipgpio4_c_2", "ipgpio5_c_2");
+/* MSP2 can not invert the RX/TX pins but has the optional SCK pin */
+DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");
+DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
+DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1");
+DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
+DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1",
+		"clkout2_a_1", "clkout2_a_2", "clkout2_c_1");
+DB8500_FUNC_GROUPS(usb, "usb_a_1");
+DB8500_FUNC_GROUPS(trig, "trig_b_1");
+DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
+DB8500_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2");
+DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
+/*
+ * The modem UART can output its RX and TX pins in some different places,
+ * so select one of each.
+ */
+DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2",
+		"uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1",
+		"uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1");
+DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1",
+		"stmmod_oc3_1", "stmmod_oc3_2");
+DB8500_FUNC_GROUPS(spi3, "spi3_b_1");
+/* Select between CS0 on alt B or PS1 on alt C */
+DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1",
+		   "smps0_c_1", "smps1_c_1");
+DB8500_FUNC_GROUPS(lcda, "lcdaclk_b_1", "lcda_b_1");
+DB8500_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
+DB8500_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4");
+DB8500_FUNC_GROUPS(spi1, "spi1_b_1");
+DB8500_FUNC_GROUPS(mc3, "mc3_b_1");
+DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1");
+DB8500_FUNC_GROUPS(slim0, "slim0_c_1");
+DB8500_FUNC_GROUPS(ms, "ms_c_1");
+DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1");
+DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1");
+DB8500_FUNC_GROUPS(mc5, "mc5_c_1");
+DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2");
+DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2");
+DB8500_FUNC_GROUPS(spi0, "spi0_c_1");
+DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2");
+DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
+DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1");
+DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1");
+DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2");
+DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1");
+DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1");
+DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct nmk_function nmk_db8500_functions[] = {
+	FUNCTION(u0),
+	FUNCTION(u1),
+	FUNCTION(u2),
+	FUNCTION(ipi2c),
+	FUNCTION(msp0),
+	FUNCTION(mc0),
+	FUNCTION(msp1),
+	FUNCTION(lcdb),
+	FUNCTION(lcd),
+	FUNCTION(kp),
+	FUNCTION(mc2),
+	FUNCTION(ssp1),
+	FUNCTION(ssp0),
+	FUNCTION(i2c0),
+	FUNCTION(ipgpio),
+	FUNCTION(msp2),
+	FUNCTION(mc4),
+	FUNCTION(mc1),
+	FUNCTION(hsi),
+	FUNCTION(clkout),
+	FUNCTION(usb),
+	FUNCTION(trig),
+	FUNCTION(i2c4),
+	FUNCTION(i2c1),
+	FUNCTION(i2c2),
+	FUNCTION(uartmod),
+	FUNCTION(stmmod),
+	FUNCTION(spi3),
+	FUNCTION(sm),
+	FUNCTION(lcda),
+	FUNCTION(ddrtrig),
+	FUNCTION(pwl),
+	FUNCTION(spi1),
+	FUNCTION(mc3),
+	FUNCTION(ipjtag),
+	FUNCTION(slim0),
+	FUNCTION(ms),
+	FUNCTION(iptrigout),
+	FUNCTION(stmape),
+	FUNCTION(mc5),
+	FUNCTION(usbsim),
+	FUNCTION(i2c3),
+	FUNCTION(spi0),
+	FUNCTION(spi2),
+	FUNCTION(remap),
+	FUNCTION(ptm),
+	FUNCTION(rf),
+	FUNCTION(hx),
+	FUNCTION(etm),
+	FUNCTION(hwobs),
+};
+
+static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
+	PRCM_GPIOCR_ALTCX(23,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_CLK_a */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_CLK_a */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(24,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE or U2_RXD ??? */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_VAL_a */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(25,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[0] */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[0] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(26,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[1] */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[1] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(27,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[2] */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[2] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(28,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[3] */
+				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[3] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(29,	false, 0, 0,
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(30,	false, 0, 0,
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(31,	false, 0, 0,
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(32,	false, 0, 0,
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(68,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP_SELECT_ON */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(69,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP_SELECT_ON */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(70,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D23 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_CLK */
+	),
+	PRCM_GPIOCR_ALTCX(71,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D22 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D3 */
+	),
+	PRCM_GPIOCR_ALTCX(72,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D21 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D2 */
+	),
+	PRCM_GPIOCR_ALTCX(73,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D20 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D1 */
+	),
+	PRCM_GPIOCR_ALTCX(74,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D19 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D0 */
+	),
+	PRCM_GPIOCR_ALTCX(75,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D18 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 0,	/* DBG_UARTMOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(76,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D17 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				true, PRCM_IDX_GPIOCR1, 0,	/* DBG_UARTMOD_CMD0 */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(77,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D16 */
+				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_VAL */
+	),
+	PRCM_GPIOCR_ALTCX(86,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O3 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(87,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O2 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(88,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I3 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(89,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I2 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(90,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O1 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(91,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O0 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(92,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I1 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(93,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I0 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(96,	true, PRCM_IDX_GPIOCR2, 3,	/* RF_INT */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(97,	true, PRCM_IDX_GPIOCR2, 1,	/* RF_CTRL */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(151,	false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_CTL */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS17 */
+	),
+	PRCM_GPIOCR_ALTCX(152,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_CLK */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_CLK */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS16 */
+	),
+	PRCM_GPIOCR_ALTCX(153,	true, PRCM_IDX_GPIOCR1, 1,	/* UARTMOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D15 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS15 */
+	),
+	PRCM_GPIOCR_ALTCX(154,	true, PRCM_IDX_GPIOCR1, 1,	/* UARTMOD_CMD1 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D14 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS14 */
+	),
+	PRCM_GPIOCR_ALTCX(155,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D13 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS13 */
+	),
+	PRCM_GPIOCR_ALTCX(156,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D12 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS12 */
+	),
+	PRCM_GPIOCR_ALTCX(157,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D11 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS11 */
+	),
+	PRCM_GPIOCR_ALTCX(158,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D10 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS10 */
+	),
+	PRCM_GPIOCR_ALTCX(159,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D9 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS9 */
+	),
+	PRCM_GPIOCR_ALTCX(160,	false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D8 */
+				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
+				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS8 */
+	),
+	PRCM_GPIOCR_ALTCX(161,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO7 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D7 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS7 */
+	),
+	PRCM_GPIOCR_ALTCX(162,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO6 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D6 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS6 */
+	),
+	PRCM_GPIOCR_ALTCX(163,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO5 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D5 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS5 */
+	),
+	PRCM_GPIOCR_ALTCX(164,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO4 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D4 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS4 */
+	),
+	PRCM_GPIOCR_ALTCX(165,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO3 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D3 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS3 */
+	),
+	PRCM_GPIOCR_ALTCX(166,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO2 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D2 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS2 */
+	),
+	PRCM_GPIOCR_ALTCX(167,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO1 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D1 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS1 */
+	),
+	PRCM_GPIOCR_ALTCX(168,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO0 */
+				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D0 */
+				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
+				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS0 */
+	),
+	PRCM_GPIOCR_ALTCX(170,	true, PRCM_IDX_GPIOCR2, 2,	/* RF_INT */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(171,	true, PRCM_IDX_GPIOCR2, 0,	/* RF_CTRL */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(215,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_TXD */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(216,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_FRM */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(217,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_CLK */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(218,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_RXD */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+};
+
+static const u16 db8500_prcm_gpiocr_regs[] = {
+	[PRCM_IDX_GPIOCR1] = 0x138,
+	[PRCM_IDX_GPIOCR2] = 0x574,
+};
+
+static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
+	.gpio_ranges = nmk_db8500_ranges,
+	.gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
+	.pins = nmk_db8500_pins,
+	.npins = ARRAY_SIZE(nmk_db8500_pins),
+	.functions = nmk_db8500_functions,
+	.nfunctions = ARRAY_SIZE(nmk_db8500_functions),
+	.groups = nmk_db8500_groups,
+	.ngroups = ARRAY_SIZE(nmk_db8500_groups),
+	.altcx_pins = db8500_altcx_pins,
+	.npins_altcx = ARRAY_SIZE(db8500_altcx_pins),
+	.prcm_gpiocr_registers = db8500_prcm_gpiocr_regs,
+};
+
+void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
+{
+	*soc = &nmk_db8500_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1266 @@
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-nomadik.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define _GPIO(offset)		(offset)
+
+#define DB8540_PIN_AH6		_GPIO(0)
+#define DB8540_PIN_AG7		_GPIO(1)
+#define DB8540_PIN_AF2		_GPIO(2)
+#define DB8540_PIN_AD3		_GPIO(3)
+#define DB8540_PIN_AF6		_GPIO(4)
+#define DB8540_PIN_AG6		_GPIO(5)
+#define DB8540_PIN_AD5		_GPIO(6)
+#define DB8540_PIN_AF7		_GPIO(7)
+#define DB8540_PIN_AG5		_GPIO(8)
+#define DB8540_PIN_AH5		_GPIO(9)
+#define DB8540_PIN_AE4		_GPIO(10)
+#define DB8540_PIN_AD1		_GPIO(11)
+#define DB8540_PIN_AD2		_GPIO(12)
+#define DB8540_PIN_AC2		_GPIO(13)
+#define DB8540_PIN_AC4		_GPIO(14)
+#define DB8540_PIN_AC3		_GPIO(15)
+#define DB8540_PIN_AH7		_GPIO(16)
+#define DB8540_PIN_AE7		_GPIO(17)
+/* Hole */
+#define DB8540_PIN_AF8		_GPIO(22)
+#define DB8540_PIN_AH11		_GPIO(23)
+#define DB8540_PIN_AG11		_GPIO(24)
+#define DB8540_PIN_AF11		_GPIO(25)
+#define DB8540_PIN_AH10		_GPIO(26)
+#define DB8540_PIN_AG10		_GPIO(27)
+#define DB8540_PIN_AF10		_GPIO(28)
+/* Hole */
+#define DB8540_PIN_AD4		_GPIO(33)
+#define DB8540_PIN_AF3		_GPIO(34)
+#define DB8540_PIN_AF5		_GPIO(35)
+#define DB8540_PIN_AG4		_GPIO(36)
+#define DB8540_PIN_AF9		_GPIO(37)
+#define DB8540_PIN_AE8		_GPIO(38)
+/* Hole */
+#define DB8540_PIN_M26		_GPIO(64)
+#define DB8540_PIN_M25		_GPIO(65)
+#define DB8540_PIN_M27		_GPIO(66)
+#define DB8540_PIN_N25		_GPIO(67)
+/* Hole */
+#define DB8540_PIN_M28		_GPIO(70)
+#define DB8540_PIN_N26		_GPIO(71)
+#define DB8540_PIN_M22		_GPIO(72)
+#define DB8540_PIN_N22		_GPIO(73)
+#define DB8540_PIN_N27		_GPIO(74)
+#define DB8540_PIN_N28		_GPIO(75)
+#define DB8540_PIN_P22		_GPIO(76)
+#define DB8540_PIN_P28		_GPIO(77)
+#define DB8540_PIN_P26		_GPIO(78)
+#define DB8540_PIN_T22		_GPIO(79)
+#define DB8540_PIN_R27		_GPIO(80)
+#define DB8540_PIN_P27		_GPIO(81)
+#define DB8540_PIN_R26		_GPIO(82)
+#define DB8540_PIN_R25		_GPIO(83)
+#define DB8540_PIN_U22		_GPIO(84)
+#define DB8540_PIN_T27		_GPIO(85)
+#define DB8540_PIN_T25		_GPIO(86)
+#define DB8540_PIN_T26		_GPIO(87)
+/* Hole */
+#define DB8540_PIN_AF20		_GPIO(116)
+#define DB8540_PIN_AG21		_GPIO(117)
+#define DB8540_PIN_AH19		_GPIO(118)
+#define DB8540_PIN_AE19		_GPIO(119)
+#define DB8540_PIN_AG18		_GPIO(120)
+#define DB8540_PIN_AH17		_GPIO(121)
+#define DB8540_PIN_AF19		_GPIO(122)
+#define DB8540_PIN_AF18		_GPIO(123)
+#define DB8540_PIN_AE18		_GPIO(124)
+#define DB8540_PIN_AG17		_GPIO(125)
+#define DB8540_PIN_AF17		_GPIO(126)
+#define DB8540_PIN_AE17		_GPIO(127)
+#define DB8540_PIN_AC27		_GPIO(128)
+#define DB8540_PIN_AD27		_GPIO(129)
+#define DB8540_PIN_AE28		_GPIO(130)
+#define DB8540_PIN_AG26		_GPIO(131)
+#define DB8540_PIN_AF25		_GPIO(132)
+#define DB8540_PIN_AE27		_GPIO(133)
+#define DB8540_PIN_AF27		_GPIO(134)
+#define DB8540_PIN_AG28		_GPIO(135)
+#define DB8540_PIN_AF28		_GPIO(136)
+#define DB8540_PIN_AG25		_GPIO(137)
+#define DB8540_PIN_AG24		_GPIO(138)
+#define DB8540_PIN_AD25		_GPIO(139)
+#define DB8540_PIN_AH25		_GPIO(140)
+#define DB8540_PIN_AF26		_GPIO(141)
+#define DB8540_PIN_AF23		_GPIO(142)
+#define DB8540_PIN_AG23		_GPIO(143)
+#define DB8540_PIN_AE25		_GPIO(144)
+#define DB8540_PIN_AH24		_GPIO(145)
+#define DB8540_PIN_AJ25		_GPIO(146)
+#define DB8540_PIN_AG27		_GPIO(147)
+#define DB8540_PIN_AH23		_GPIO(148)
+#define DB8540_PIN_AE26		_GPIO(149)
+#define DB8540_PIN_AE24		_GPIO(150)
+#define DB8540_PIN_AJ24		_GPIO(151)
+#define DB8540_PIN_AE21		_GPIO(152)
+#define DB8540_PIN_AG22		_GPIO(153)
+#define DB8540_PIN_AF21		_GPIO(154)
+#define DB8540_PIN_AF24		_GPIO(155)
+#define DB8540_PIN_AH22		_GPIO(156)
+#define DB8540_PIN_AJ23		_GPIO(157)
+#define DB8540_PIN_AH21		_GPIO(158)
+#define DB8540_PIN_AG20		_GPIO(159)
+#define DB8540_PIN_AE23		_GPIO(160)
+#define DB8540_PIN_AH20		_GPIO(161)
+#define DB8540_PIN_AG19		_GPIO(162)
+#define DB8540_PIN_AF22		_GPIO(163)
+#define DB8540_PIN_AJ21		_GPIO(164)
+#define DB8540_PIN_AD26		_GPIO(165)
+#define DB8540_PIN_AD28		_GPIO(166)
+#define DB8540_PIN_AC28		_GPIO(167)
+#define DB8540_PIN_AC26		_GPIO(168)
+/* Hole */
+#define DB8540_PIN_J3		_GPIO(192)
+#define DB8540_PIN_H1		_GPIO(193)
+#define DB8540_PIN_J2		_GPIO(194)
+#define DB8540_PIN_H2		_GPIO(195)
+#define DB8540_PIN_H3		_GPIO(196)
+#define DB8540_PIN_H4		_GPIO(197)
+#define DB8540_PIN_G2		_GPIO(198)
+#define DB8540_PIN_G3		_GPIO(199)
+#define DB8540_PIN_G4		_GPIO(200)
+#define DB8540_PIN_F2		_GPIO(201)
+#define DB8540_PIN_C6		_GPIO(202)
+#define DB8540_PIN_B6		_GPIO(203)
+#define DB8540_PIN_B7		_GPIO(204)
+#define DB8540_PIN_A7		_GPIO(205)
+#define DB8540_PIN_D7		_GPIO(206)
+#define DB8540_PIN_D8		_GPIO(207)
+#define DB8540_PIN_F3		_GPIO(208)
+#define DB8540_PIN_E2		_GPIO(209)
+#define DB8540_PIN_C7		_GPIO(210)
+#define DB8540_PIN_B8		_GPIO(211)
+#define DB8540_PIN_C10		_GPIO(212)
+#define DB8540_PIN_C8		_GPIO(213)
+#define DB8540_PIN_C9		_GPIO(214)
+/* Hole */
+#define DB8540_PIN_B9		_GPIO(219)
+#define DB8540_PIN_A10		_GPIO(220)
+#define DB8540_PIN_D9		_GPIO(221)
+#define DB8540_PIN_B11		_GPIO(222)
+#define DB8540_PIN_B10		_GPIO(223)
+#define DB8540_PIN_E10		_GPIO(224)
+#define DB8540_PIN_B12		_GPIO(225)
+#define DB8540_PIN_D10		_GPIO(226)
+#define DB8540_PIN_D11		_GPIO(227)
+#define DB8540_PIN_AJ6		_GPIO(228)
+#define DB8540_PIN_B13		_GPIO(229)
+#define DB8540_PIN_C12		_GPIO(230)
+#define DB8540_PIN_B14		_GPIO(231)
+#define DB8540_PIN_E11		_GPIO(232)
+/* Hole */
+#define DB8540_PIN_D12		_GPIO(256)
+#define DB8540_PIN_D15		_GPIO(257)
+#define DB8540_PIN_C13		_GPIO(258)
+#define DB8540_PIN_C14		_GPIO(259)
+#define DB8540_PIN_C18		_GPIO(260)
+#define DB8540_PIN_C16		_GPIO(261)
+#define DB8540_PIN_B16		_GPIO(262)
+#define DB8540_PIN_D18		_GPIO(263)
+#define DB8540_PIN_C15		_GPIO(264)
+#define DB8540_PIN_C17		_GPIO(265)
+#define DB8540_PIN_B17		_GPIO(266)
+#define DB8540_PIN_D17		_GPIO(267)
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc nmk_db8540_pins[] = {
+	PINCTRL_PIN(DB8540_PIN_AH6, "GPIO0_AH6"),
+	PINCTRL_PIN(DB8540_PIN_AG7, "GPIO1_AG7"),
+	PINCTRL_PIN(DB8540_PIN_AF2, "GPIO2_AF2"),
+	PINCTRL_PIN(DB8540_PIN_AD3, "GPIO3_AD3"),
+	PINCTRL_PIN(DB8540_PIN_AF6, "GPIO4_AF6"),
+	PINCTRL_PIN(DB8540_PIN_AG6, "GPIO5_AG6"),
+	PINCTRL_PIN(DB8540_PIN_AD5, "GPIO6_AD5"),
+	PINCTRL_PIN(DB8540_PIN_AF7, "GPIO7_AF7"),
+	PINCTRL_PIN(DB8540_PIN_AG5, "GPIO8_AG5"),
+	PINCTRL_PIN(DB8540_PIN_AH5, "GPIO9_AH5"),
+	PINCTRL_PIN(DB8540_PIN_AE4, "GPIO10_AE4"),
+	PINCTRL_PIN(DB8540_PIN_AD1, "GPIO11_AD1"),
+	PINCTRL_PIN(DB8540_PIN_AD2, "GPIO12_AD2"),
+	PINCTRL_PIN(DB8540_PIN_AC2, "GPIO13_AC2"),
+	PINCTRL_PIN(DB8540_PIN_AC4, "GPIO14_AC4"),
+	PINCTRL_PIN(DB8540_PIN_AC3, "GPIO15_AC3"),
+	PINCTRL_PIN(DB8540_PIN_AH7, "GPIO16_AH7"),
+	PINCTRL_PIN(DB8540_PIN_AE7, "GPIO17_AE7"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_AF8, "GPIO22_AF8"),
+	PINCTRL_PIN(DB8540_PIN_AH11, "GPIO23_AH11"),
+	PINCTRL_PIN(DB8540_PIN_AG11, "GPIO24_AG11"),
+	PINCTRL_PIN(DB8540_PIN_AF11, "GPIO25_AF11"),
+	PINCTRL_PIN(DB8540_PIN_AH10, "GPIO26_AH10"),
+	PINCTRL_PIN(DB8540_PIN_AG10, "GPIO27_AG10"),
+	PINCTRL_PIN(DB8540_PIN_AF10, "GPIO28_AF10"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_AD4, "GPIO33_AD4"),
+	PINCTRL_PIN(DB8540_PIN_AF3, "GPIO34_AF3"),
+	PINCTRL_PIN(DB8540_PIN_AF5, "GPIO35_AF5"),
+	PINCTRL_PIN(DB8540_PIN_AG4, "GPIO36_AG4"),
+	PINCTRL_PIN(DB8540_PIN_AF9, "GPIO37_AF9"),
+	PINCTRL_PIN(DB8540_PIN_AE8, "GPIO38_AE8"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_M26, "GPIO64_M26"),
+	PINCTRL_PIN(DB8540_PIN_M25, "GPIO65_M25"),
+	PINCTRL_PIN(DB8540_PIN_M27, "GPIO66_M27"),
+	PINCTRL_PIN(DB8540_PIN_N25, "GPIO67_N25"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_M28, "GPIO70_M28"),
+	PINCTRL_PIN(DB8540_PIN_N26, "GPIO71_N26"),
+	PINCTRL_PIN(DB8540_PIN_M22, "GPIO72_M22"),
+	PINCTRL_PIN(DB8540_PIN_N22, "GPIO73_N22"),
+	PINCTRL_PIN(DB8540_PIN_N27, "GPIO74_N27"),
+	PINCTRL_PIN(DB8540_PIN_N28, "GPIO75_N28"),
+	PINCTRL_PIN(DB8540_PIN_P22, "GPIO76_P22"),
+	PINCTRL_PIN(DB8540_PIN_P28, "GPIO77_P28"),
+	PINCTRL_PIN(DB8540_PIN_P26, "GPIO78_P26"),
+	PINCTRL_PIN(DB8540_PIN_T22, "GPIO79_T22"),
+	PINCTRL_PIN(DB8540_PIN_R27, "GPIO80_R27"),
+	PINCTRL_PIN(DB8540_PIN_P27, "GPIO81_P27"),
+	PINCTRL_PIN(DB8540_PIN_R26, "GPIO82_R26"),
+	PINCTRL_PIN(DB8540_PIN_R25, "GPIO83_R25"),
+	PINCTRL_PIN(DB8540_PIN_U22, "GPIO84_U22"),
+	PINCTRL_PIN(DB8540_PIN_T27, "GPIO85_T27"),
+	PINCTRL_PIN(DB8540_PIN_T25, "GPIO86_T25"),
+	PINCTRL_PIN(DB8540_PIN_T26, "GPIO87_T26"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_AF20, "GPIO116_AF20"),
+	PINCTRL_PIN(DB8540_PIN_AG21, "GPIO117_AG21"),
+	PINCTRL_PIN(DB8540_PIN_AH19, "GPIO118_AH19"),
+	PINCTRL_PIN(DB8540_PIN_AE19, "GPIO119_AE19"),
+	PINCTRL_PIN(DB8540_PIN_AG18, "GPIO120_AG18"),
+	PINCTRL_PIN(DB8540_PIN_AH17, "GPIO121_AH17"),
+	PINCTRL_PIN(DB8540_PIN_AF19, "GPIO122_AF19"),
+	PINCTRL_PIN(DB8540_PIN_AF18, "GPIO123_AF18"),
+	PINCTRL_PIN(DB8540_PIN_AE18, "GPIO124_AE18"),
+	PINCTRL_PIN(DB8540_PIN_AG17, "GPIO125_AG17"),
+	PINCTRL_PIN(DB8540_PIN_AF17, "GPIO126_AF17"),
+	PINCTRL_PIN(DB8540_PIN_AE17, "GPIO127_AE17"),
+	PINCTRL_PIN(DB8540_PIN_AC27, "GPIO128_AC27"),
+	PINCTRL_PIN(DB8540_PIN_AD27, "GPIO129_AD27"),
+	PINCTRL_PIN(DB8540_PIN_AE28, "GPIO130_AE28"),
+	PINCTRL_PIN(DB8540_PIN_AG26, "GPIO131_AG26"),
+	PINCTRL_PIN(DB8540_PIN_AF25, "GPIO132_AF25"),
+	PINCTRL_PIN(DB8540_PIN_AE27, "GPIO133_AE27"),
+	PINCTRL_PIN(DB8540_PIN_AF27, "GPIO134_AF27"),
+	PINCTRL_PIN(DB8540_PIN_AG28, "GPIO135_AG28"),
+	PINCTRL_PIN(DB8540_PIN_AF28, "GPIO136_AF28"),
+	PINCTRL_PIN(DB8540_PIN_AG25, "GPIO137_AG25"),
+	PINCTRL_PIN(DB8540_PIN_AG24, "GPIO138_AG24"),
+	PINCTRL_PIN(DB8540_PIN_AD25, "GPIO139_AD25"),
+	PINCTRL_PIN(DB8540_PIN_AH25, "GPIO140_AH25"),
+	PINCTRL_PIN(DB8540_PIN_AF26, "GPIO141_AF26"),
+	PINCTRL_PIN(DB8540_PIN_AF23, "GPIO142_AF23"),
+	PINCTRL_PIN(DB8540_PIN_AG23, "GPIO143_AG23"),
+	PINCTRL_PIN(DB8540_PIN_AE25, "GPIO144_AE25"),
+	PINCTRL_PIN(DB8540_PIN_AH24, "GPIO145_AH24"),
+	PINCTRL_PIN(DB8540_PIN_AJ25, "GPIO146_AJ25"),
+	PINCTRL_PIN(DB8540_PIN_AG27, "GPIO147_AG27"),
+	PINCTRL_PIN(DB8540_PIN_AH23, "GPIO148_AH23"),
+	PINCTRL_PIN(DB8540_PIN_AE26, "GPIO149_AE26"),
+	PINCTRL_PIN(DB8540_PIN_AE24, "GPIO150_AE24"),
+	PINCTRL_PIN(DB8540_PIN_AJ24, "GPIO151_AJ24"),
+	PINCTRL_PIN(DB8540_PIN_AE21, "GPIO152_AE21"),
+	PINCTRL_PIN(DB8540_PIN_AG22, "GPIO153_AG22"),
+	PINCTRL_PIN(DB8540_PIN_AF21, "GPIO154_AF21"),
+	PINCTRL_PIN(DB8540_PIN_AF24, "GPIO155_AF24"),
+	PINCTRL_PIN(DB8540_PIN_AH22, "GPIO156_AH22"),
+	PINCTRL_PIN(DB8540_PIN_AJ23, "GPIO157_AJ23"),
+	PINCTRL_PIN(DB8540_PIN_AH21, "GPIO158_AH21"),
+	PINCTRL_PIN(DB8540_PIN_AG20, "GPIO159_AG20"),
+	PINCTRL_PIN(DB8540_PIN_AE23, "GPIO160_AE23"),
+	PINCTRL_PIN(DB8540_PIN_AH20, "GPIO161_AH20"),
+	PINCTRL_PIN(DB8540_PIN_AG19, "GPIO162_AG19"),
+	PINCTRL_PIN(DB8540_PIN_AF22, "GPIO163_AF22"),
+	PINCTRL_PIN(DB8540_PIN_AJ21, "GPIO164_AJ21"),
+	PINCTRL_PIN(DB8540_PIN_AD26, "GPIO165_AD26"),
+	PINCTRL_PIN(DB8540_PIN_AD28, "GPIO166_AD28"),
+	PINCTRL_PIN(DB8540_PIN_AC28, "GPIO167_AC28"),
+	PINCTRL_PIN(DB8540_PIN_AC26, "GPIO168_AC26"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_J3, "GPIO192_J3"),
+	PINCTRL_PIN(DB8540_PIN_H1, "GPIO193_H1"),
+	PINCTRL_PIN(DB8540_PIN_J2, "GPIO194_J2"),
+	PINCTRL_PIN(DB8540_PIN_H2, "GPIO195_H2"),
+	PINCTRL_PIN(DB8540_PIN_H3, "GPIO196_H3"),
+	PINCTRL_PIN(DB8540_PIN_H4, "GPIO197_H4"),
+	PINCTRL_PIN(DB8540_PIN_G2, "GPIO198_G2"),
+	PINCTRL_PIN(DB8540_PIN_G3, "GPIO199_G3"),
+	PINCTRL_PIN(DB8540_PIN_G4, "GPIO200_G4"),
+	PINCTRL_PIN(DB8540_PIN_F2, "GPIO201_F2"),
+	PINCTRL_PIN(DB8540_PIN_C6, "GPIO202_C6"),
+	PINCTRL_PIN(DB8540_PIN_B6, "GPIO203_B6"),
+	PINCTRL_PIN(DB8540_PIN_B7, "GPIO204_B7"),
+	PINCTRL_PIN(DB8540_PIN_A7, "GPIO205_A7"),
+	PINCTRL_PIN(DB8540_PIN_D7, "GPIO206_D7"),
+	PINCTRL_PIN(DB8540_PIN_D8, "GPIO207_D8"),
+	PINCTRL_PIN(DB8540_PIN_F3, "GPIO208_F3"),
+	PINCTRL_PIN(DB8540_PIN_E2, "GPIO209_E2"),
+	PINCTRL_PIN(DB8540_PIN_C7, "GPIO210_C7"),
+	PINCTRL_PIN(DB8540_PIN_B8, "GPIO211_B8"),
+	PINCTRL_PIN(DB8540_PIN_C10, "GPIO212_C10"),
+	PINCTRL_PIN(DB8540_PIN_C8, "GPIO213_C8"),
+	PINCTRL_PIN(DB8540_PIN_C9, "GPIO214_C9"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_B9, "GPIO219_B9"),
+	PINCTRL_PIN(DB8540_PIN_A10, "GPIO220_A10"),
+	PINCTRL_PIN(DB8540_PIN_D9, "GPIO221_D9"),
+	PINCTRL_PIN(DB8540_PIN_B11, "GPIO222_B11"),
+	PINCTRL_PIN(DB8540_PIN_B10, "GPIO223_B10"),
+	PINCTRL_PIN(DB8540_PIN_E10, "GPIO224_E10"),
+	PINCTRL_PIN(DB8540_PIN_B12, "GPIO225_B12"),
+	PINCTRL_PIN(DB8540_PIN_D10, "GPIO226_D10"),
+	PINCTRL_PIN(DB8540_PIN_D11, "GPIO227_D11"),
+	PINCTRL_PIN(DB8540_PIN_AJ6, "GPIO228_AJ6"),
+	PINCTRL_PIN(DB8540_PIN_B13, "GPIO229_B13"),
+	PINCTRL_PIN(DB8540_PIN_C12, "GPIO230_C12"),
+	PINCTRL_PIN(DB8540_PIN_B14, "GPIO231_B14"),
+	PINCTRL_PIN(DB8540_PIN_E11, "GPIO232_E11"),
+	/* Hole */
+	PINCTRL_PIN(DB8540_PIN_D12, "GPIO256_D12"),
+	PINCTRL_PIN(DB8540_PIN_D15, "GPIO257_D15"),
+	PINCTRL_PIN(DB8540_PIN_C13, "GPIO258_C13"),
+	PINCTRL_PIN(DB8540_PIN_C14, "GPIO259_C14"),
+	PINCTRL_PIN(DB8540_PIN_C18, "GPIO260_C18"),
+	PINCTRL_PIN(DB8540_PIN_C16, "GPIO261_C16"),
+	PINCTRL_PIN(DB8540_PIN_B16, "GPIO262_B16"),
+	PINCTRL_PIN(DB8540_PIN_D18, "GPIO263_D18"),
+	PINCTRL_PIN(DB8540_PIN_C15, "GPIO264_C15"),
+	PINCTRL_PIN(DB8540_PIN_C17, "GPIO265_C17"),
+	PINCTRL_PIN(DB8540_PIN_B17, "GPIO266_B17"),
+	PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"),
+};
+
+#define DB8540_GPIO_RANGE(a, b, c) { .name = "db8540", .id = a, .base = b, \
+			.pin_base = b, .npins = c }
+
+/*
+ * This matches the 32-pin gpio chips registered by the GPIO portion. This
+ * cannot be const since we assign the struct gpio_chip * pointer at runtime.
+ */
+static struct pinctrl_gpio_range nmk_db8540_ranges[] = {
+	DB8540_GPIO_RANGE(0, 0, 18),
+	DB8540_GPIO_RANGE(0, 22, 7),
+	DB8540_GPIO_RANGE(1, 33, 6),
+	DB8540_GPIO_RANGE(2, 64, 4),
+	DB8540_GPIO_RANGE(2, 70, 18),
+	DB8540_GPIO_RANGE(3, 116, 12),
+	DB8540_GPIO_RANGE(4, 128, 32),
+	DB8540_GPIO_RANGE(5, 160, 9),
+	DB8540_GPIO_RANGE(6, 192, 23),
+	DB8540_GPIO_RANGE(6, 219, 5),
+	DB8540_GPIO_RANGE(7, 224, 9),
+	DB8540_GPIO_RANGE(8, 256, 12),
+};
+
+/*
+ * Read the pin group names like this:
+ * u0_a_1    = first groups of pins for uart0 on alt function a
+ * i2c2_b_2  = second group of pins for i2c2 on alt function b
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* Altfunction A column */
+static const unsigned u0_a_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7,
+					DB8540_PIN_AF2, DB8540_PIN_AD3 };
+static const unsigned u1rxtx_a_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 };
+static const unsigned u1ctsrts_a_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 };
+/* Image processor I2C line, this is driven by image processor firmware */
+static const unsigned ipi2c_a_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 };
+static const unsigned ipi2c_a_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 };
+/* MSP0 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp0txrx_a_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 };
+static const unsigned msp0tfstck_a_1_pins[] = { DB8540_PIN_AC2,
+	DB8540_PIN_AC4 };
+static const unsigned msp0rfsrck_a_1_pins[] = { DB8540_PIN_AH7,
+	DB8540_PIN_AE7 };
+/* Basic pins of the MMC/SD card 0 interface */
+static const unsigned mc0_a_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11,
+	DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10};
+/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
+static const unsigned msp1txrx_a_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 };
+static const unsigned msp1_a_1_pins[] = { DB8540_PIN_AF3, DB8540_PIN_AF5 };
+
+static const unsigned modobsclk_a_1_pins[] = { DB8540_PIN_AF9 };
+static const unsigned clkoutreq_a_1_pins[] = { DB8540_PIN_AE8 };
+/* LCD interface */
+static const unsigned lcdb_a_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
+	DB8540_PIN_M27, DB8540_PIN_N25 };
+static const unsigned lcdvsi0_a_1_pins[] = { DB8540_PIN_AJ24 };
+static const unsigned lcdvsi1_a_1_pins[] = { DB8540_PIN_AE21 };
+static const unsigned lcd_d0_d7_a_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
+	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
+	DB8540_PIN_P22, DB8540_PIN_P28 };
+/* D8 thru D11 often used as TVOUT lines */
+static const unsigned lcd_d8_d11_a_1_pins[] = { DB8540_PIN_P26, DB8540_PIN_T22,
+	DB8540_PIN_R27, DB8540_PIN_P27 };
+static const unsigned lcd_d12_d23_a_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25,
+	DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21,
+	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
+	DB8540_PIN_AG20, DB8540_PIN_AE23 };
+static const unsigned kp_a_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
+	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 };
+/* MC2 has 8 data lines and no direction control, so only for (e)MMC */
+static const unsigned mc2_a_1_pins[] = { DB8540_PIN_AC27, DB8540_PIN_AD27,
+	DB8540_PIN_AE28, DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27,
+	DB8540_PIN_AF27, DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25,
+	DB8540_PIN_AG24 };
+static const unsigned ssp1_a_1_pins[] = {  DB8540_PIN_AD25, DB8540_PIN_AH25,
+	DB8540_PIN_AF26, DB8540_PIN_AF23 };
+static const unsigned ssp0_a_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25,
+	DB8540_PIN_AH24, DB8540_PIN_AJ25 };
+static const unsigned i2c0_a_1_pins[] = { DB8540_PIN_AG27, DB8540_PIN_AH23 };
+/*
+ * Image processor GPIO pins are named "ipgpio" and have their own
+ * numberspace
+ */
+static const unsigned ipgpio0_a_1_pins[] = { DB8540_PIN_AE26 };
+static const unsigned ipgpio1_a_1_pins[] = { DB8540_PIN_AE24 };
+/* modem i2s interface */
+static const unsigned modi2s_a_1_pins[] = { DB8540_PIN_AD26, DB8540_PIN_AD28,
+	DB8540_PIN_AC28, DB8540_PIN_AC26 };
+static const unsigned spi2_a_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21,
+	DB8540_PIN_AH19, DB8540_PIN_AE19 };
+static const unsigned u2txrx_a_1_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 };
+static const unsigned u2ctsrts_a_1_pins[] = { DB8540_PIN_AF19,
+	DB8540_PIN_AF18 };
+static const unsigned modsmb_a_1_pins[] = { DB8540_PIN_AF17, DB8540_PIN_AE17 };
+static const unsigned msp2sck_a_1_pins[] = { DB8540_PIN_J3 };
+static const unsigned msp2txdtcktfs_a_1_pins[] = { DB8540_PIN_H1, DB8540_PIN_J2,
+	DB8540_PIN_H2 };
+static const unsigned msp2rxd_a_1_pins[] = { DB8540_PIN_H3 };
+static const unsigned mc4_a_1_pins[] = { DB8540_PIN_H4, DB8540_PIN_G2,
+	DB8540_PIN_G3, DB8540_PIN_G4, DB8540_PIN_F2, DB8540_PIN_C6,
+	DB8540_PIN_B6, DB8540_PIN_B7, DB8540_PIN_A7, DB8540_PIN_D7,
+	DB8540_PIN_D8 };
+static const unsigned mc1_a_1_pins[] = { DB8540_PIN_F3, DB8540_PIN_E2,
+	DB8540_PIN_C7, DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8,
+	DB8540_PIN_C9 };
+/* mc1_a_2_pins exclude MC1_FBCLK */
+static const unsigned mc1_a_2_pins[] = { DB8540_PIN_F3,	DB8540_PIN_C7,
+	DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8,
+	DB8540_PIN_C9 };
+static const unsigned hsir_a_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10,
+	DB8540_PIN_D9 };
+static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
+	DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 };
+static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
+	DB8540_PIN_E10, DB8540_PIN_B12 };
+static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 };
+static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 };
+static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 };
+static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 };
+static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15,
+	DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16,
+	DB8540_PIN_B16, DB8540_PIN_D18, DB8540_PIN_C15, DB8540_PIN_C17,
+	DB8540_PIN_B17, DB8540_PIN_D17 };
+/* Altfunction B colum */
+static const unsigned apetrig_b_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7 };
+static const unsigned modtrig_b_1_pins[] = { DB8540_PIN_AF2, DB8540_PIN_AD3 };
+static const unsigned i2c4_b_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 };
+static const unsigned i2c1_b_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 };
+static const unsigned i2c2_b_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 };
+static const unsigned i2c2_b_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 };
+static const unsigned msp0txrx_b_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 };
+static const unsigned i2c1_b_2_pins[] = { DB8540_PIN_AH7, DB8540_PIN_AE7 };
+static const unsigned stmmod_b_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11,
+	DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
+static const unsigned moduartstmmux_b_1_pins[] = { DB8540_PIN_AG11 };
+static const unsigned msp1txrx_b_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 };
+static const unsigned kp_b_1_pins[] = { DB8540_PIN_AJ24, DB8540_PIN_AE21,
+	DB8540_PIN_M26, DB8540_PIN_M25, DB8540_PIN_M27, DB8540_PIN_N25,
+	DB8540_PIN_M28, DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22,
+	DB8540_PIN_N27, DB8540_PIN_N28, DB8540_PIN_P22, DB8540_PIN_P28,
+	DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27,
+	DB8540_PIN_R26, DB8540_PIN_R25 };
+static const unsigned u2txrx_b_1_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27 };
+static const unsigned sm_b_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
+	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
+	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22,
+	DB8540_PIN_AJ21, DB8540_PIN_AC27, DB8540_PIN_AD27, DB8540_PIN_AE28,
+	DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27, DB8540_PIN_AF27,
+	DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25, DB8540_PIN_AG24,
+	DB8540_PIN_AD25 };
+static const unsigned smcs0_b_1_pins[] = { DB8540_PIN_AG19 };
+static const unsigned smcs1_b_1_pins[] = { DB8540_PIN_AE26 };
+static const unsigned ipgpio7_b_1_pins[] = { DB8540_PIN_AH25 };
+static const unsigned ipgpio2_b_1_pins[] = { DB8540_PIN_AF26 };
+static const unsigned ipgpio3_b_1_pins[] = { DB8540_PIN_AF23 };
+static const unsigned i2c6_b_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25 };
+static const unsigned i2c5_b_1_pins[] = { DB8540_PIN_AH24, DB8540_PIN_AJ25 };
+static const unsigned u3txrx_b_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21 };
+static const unsigned u3ctsrts_b_1_pins[] = { DB8540_PIN_AH19,
+	DB8540_PIN_AE19 };
+static const unsigned i2c5_b_2_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 };
+static const unsigned i2c4_b_2_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 };
+static const unsigned u4txrx_b_1_pins[] = { DB8540_PIN_AE18, DB8540_PIN_AG17 };
+static const unsigned u4ctsrts_b_1_pins[] = { DB8540_PIN_AF17,
+	DB8540_PIN_AE17 };
+static const unsigned ddrtrig_b_1_pins[] = { DB8540_PIN_J3 };
+static const unsigned msp4_b_1_pins[] = { DB8540_PIN_H3 };
+static const unsigned pwl_b_1_pins[] = { DB8540_PIN_C6 };
+static const unsigned spi1_b_1_pins[] = { DB8540_PIN_E2, DB8540_PIN_C10,
+	DB8540_PIN_C8, DB8540_PIN_C9 };
+static const unsigned mc3_b_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10,
+	DB8540_PIN_D9, DB8540_PIN_B11, DB8540_PIN_B10, DB8540_PIN_E10,
+	DB8540_PIN_B12 };
+static const unsigned pwl_b_2_pins[] = { DB8540_PIN_D10 };
+static const unsigned pwl_b_3_pins[] = { DB8540_PIN_B13 };
+static const unsigned pwl_b_4_pins[] = { DB8540_PIN_C12 };
+static const unsigned u2txrx_b_2_pins[] = { DB8540_PIN_B17, DB8540_PIN_D17 };
+
+/* Altfunction C column */
+static const unsigned ipgpio6_c_1_pins[] = { DB8540_PIN_AG6 };
+static const unsigned ipgpio0_c_1_pins[] = { DB8540_PIN_AD5 };
+static const unsigned ipgpio1_c_1_pins[] = { DB8540_PIN_AF7 };
+static const unsigned ipgpio3_c_1_pins[] = { DB8540_PIN_AE4 };
+static const unsigned ipgpio2_c_1_pins[] = { DB8540_PIN_AD1 };
+static const unsigned u0_c_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AF3,
+	DB8540_PIN_AF5, DB8540_PIN_AG4 };
+static const unsigned smcleale_c_1_pins[] = { DB8540_PIN_AJ24,
+	DB8540_PIN_AE21 };
+static const unsigned ipgpio4_c_1_pins[] = { DB8540_PIN_M26 };
+static const unsigned ipgpio5_c_1_pins[] = { DB8540_PIN_M25 };
+static const unsigned ipgpio6_c_2_pins[] = { DB8540_PIN_M27 };
+static const unsigned ipgpio7_c_1_pins[] = { DB8540_PIN_N25 };
+static const unsigned stmape_c_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
+	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 };
+static const unsigned u2rxtx_c_1_pins[] = { DB8540_PIN_N28, DB8540_PIN_P22 };
+static const unsigned modobsresout_c_1_pins[] = { DB8540_PIN_P28 };
+static const unsigned ipgpio2_c_2_pins[] = { DB8540_PIN_P26 };
+static const unsigned ipgpio3_c_2_pins[] = { DB8540_PIN_T22 };
+static const unsigned ipgpio4_c_2_pins[] = { DB8540_PIN_R27 };
+static const unsigned ipgpio5_c_2_pins[] = { DB8540_PIN_P27 };
+static const unsigned modaccgpo_c_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25,
+	DB8540_PIN_U22 };
+static const unsigned modobspwrrst_c_1_pins[] = { DB8540_PIN_T27 };
+static const unsigned mc5_c_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
+	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
+	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22,
+	DB8540_PIN_AJ21};
+static const unsigned smps0_c_1_pins[] = { DB8540_PIN_AG19 };
+static const unsigned moduart1_c_1_pins[] = { DB8540_PIN_T25, DB8540_PIN_T26 };
+static const unsigned mc2rstn_c_1_pins[] = { DB8540_PIN_AE28 };
+static const unsigned i2c5_c_1_pins[] = { DB8540_PIN_AG28, DB8540_PIN_AF28 };
+static const unsigned ipgpio0_c_2_pins[] = { DB8540_PIN_AG25 };
+static const unsigned ipgpio1_c_2_pins[] = { DB8540_PIN_AG24 };
+static const unsigned kp_c_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25,
+	DB8540_PIN_AF26, DB8540_PIN_AF23 };
+static const unsigned modrf_c_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25,
+	DB8540_PIN_AH24 };
+static const unsigned smps1_c_1_pins[] = { DB8540_PIN_AE26 };
+static const unsigned i2c5_c_2_pins[] = { DB8540_PIN_AH19, DB8540_PIN_AE19 };
+static const unsigned u4ctsrts_c_1_pins[] = { DB8540_PIN_AG18,
+	DB8540_PIN_AH17 };
+static const unsigned u3rxtx_c_1_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 };
+static const unsigned msp4_c_1_pins[] = { DB8540_PIN_J3 };
+static const unsigned mc4rstn_c_1_pins[] = { DB8540_PIN_C6 };
+static const unsigned spi0_c_1_pins[] = { DB8540_PIN_A10, DB8540_PIN_B10,
+	DB8540_PIN_E10, DB8540_PIN_B12 };
+static const unsigned i2c3_c_1_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 };
+
+/* Other alt C1 column */
+static const unsigned spi3_oc1_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5,
+	DB8540_PIN_AE4, DB8540_PIN_AD1 };
+static const unsigned stmape_oc1_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11,
+	DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
+static const unsigned u2_oc1_1_pins[] = { DB8540_PIN_AG11 };
+static const unsigned remap0_oc1_1_pins[] = { DB8540_PIN_AJ24 };
+static const unsigned remap1_oc1_1_pins[] = { DB8540_PIN_AE21 };
+static const unsigned modobsrefclk_oc1_1_pins[] = { DB8540_PIN_M26 };
+static const unsigned modobspwrctrl_oc1_1_pins[] = { DB8540_PIN_M25 };
+static const unsigned modobsclkout_oc1_1_pins[] = { DB8540_PIN_M27 };
+static const unsigned moduart1_oc1_1_pins[] = { DB8540_PIN_N25 };
+static const unsigned modprcmudbg_oc1_1_pins[] = { DB8540_PIN_M28,
+	DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27,
+	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
+	DB8540_PIN_R26, DB8540_PIN_R25, DB8540_PIN_U22, DB8540_PIN_T27,
+	DB8540_PIN_AH20, DB8540_PIN_AG19, DB8540_PIN_AF22, DB8540_PIN_AJ21,
+	DB8540_PIN_T25};
+static const unsigned modobsresout_oc1_1_pins[] = { DB8540_PIN_N28 };
+static const unsigned modaccgpo_oc1_1_pins[] = { DB8540_PIN_R27, DB8540_PIN_P27,
+	DB8540_PIN_T26 };
+static const unsigned kp_oc1_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
+	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
+	DB8540_PIN_AG20, DB8540_PIN_AE23 };
+static const unsigned modxmip_oc1_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25,
+	DB8540_PIN_AG23, DB8540_PIN_AE25 };
+static const unsigned i2c6_oc1_1_pins[] = { DB8540_PIN_AE26, DB8540_PIN_AE24 };
+static const unsigned u2txrx_oc1_1_pins[] = { DB8540_PIN_B7, DB8540_PIN_A7 };
+static const unsigned u2ctsrts_oc1_1_pins[] = { DB8540_PIN_D7, DB8540_PIN_D8 };
+
+/* Other alt C2 column */
+static const unsigned sbag_oc2_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11,
+	DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
+static const unsigned hxclk_oc2_1_pins[] = { DB8540_PIN_M25 };
+static const unsigned modaccuart_oc2_1_pins[] = { DB8540_PIN_N25 };
+static const unsigned stmmod_oc2_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
+	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 };
+static const unsigned moduartstmmux_oc2_1_pins[] = { DB8540_PIN_N28 };
+static const unsigned hxgpio_oc2_1_pins[] = { DB8540_PIN_P22, DB8540_PIN_P28,
+	DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27,
+	DB8540_PIN_R26, DB8540_PIN_R25 };
+static const unsigned sbag_oc2_2_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27,
+	DB8540_PIN_AG22, DB8540_PIN_AF21, DB8540_PIN_AF24, DB8540_PIN_AH22 };
+static const unsigned modobsservice_oc2_1_pins[] = { DB8540_PIN_AJ23 };
+static const unsigned moduart0_oc2_1_pins[] = { DB8540_PIN_AG20,
+	DB8540_PIN_AE23 };
+static const unsigned stmape_oc2_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
+	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 };
+static const unsigned u2_oc2_1_pins[] = { DB8540_PIN_T26, DB8540_PIN_AH21 };
+static const unsigned modxmip_oc2_1_pins[] = { DB8540_PIN_AE26,
+	DB8540_PIN_AE24 };
+
+/* Other alt C3 column */
+static const unsigned modaccgpo_oc3_1_pins[] = { DB8540_PIN_AG11 };
+static const unsigned tpui_oc3_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
+	DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26,
+	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
+	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
+	DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25,
+	DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21,
+	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
+	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AG19,
+	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 };
+
+/* Other alt C4 column */
+static const unsigned hwobs_oc4_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
+	DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26,
+	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
+	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
+	DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25 };
+static const unsigned moduart1txrx_oc4_1_pins[] = { DB8540_PIN_U22,
+	DB8540_PIN_T27 };
+static const unsigned moduart1rtscts_oc4_1_pins[] = { DB8540_PIN_AG22,
+	DB8540_PIN_AF21 };
+static const unsigned modaccuarttxrx_oc4_1_pins[] = { DB8540_PIN_AF24,
+	DB8540_PIN_AH22 };
+static const unsigned modaccuartrtscts_oc4_1_pins[] = { DB8540_PIN_AJ23,
+	DB8540_PIN_AH21 };
+static const unsigned stmmod_oc4_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
+	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 };
+static const unsigned moduartstmmux_oc4_1_pins[] = { DB8540_PIN_T26 };
+
+#define DB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct nmk_pingroup nmk_db8540_groups[] = {
+	/* Altfunction A column */
+	DB8540_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(modobsclk_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkoutreq_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(modi2s_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(spi2_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(u2txrx_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(u2ctsrts_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(modsmb_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp2txdtcktfs_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp2rxd_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
+	/* Altfunction B column */
+	DB8540_PIN_GROUP(apetrig_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(modtrig_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(moduartstmmux_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u2txrx_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c6_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c5_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u3txrx_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u3ctsrts_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c5_b_2, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(i2c4_b_2, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u4txrx_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u4ctsrts_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(msp4_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B),
+	DB8540_PIN_GROUP(u2txrx_b_2, NMK_GPIO_ALT_B),
+	/* Altfunction C column */
+	DB8540_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio6_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(modobsresout_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(modaccgpo_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(modobspwrrst_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(moduart1_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(i2c5_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio0_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(ipgpio1_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(modrf_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(i2c5_c_2, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(u4ctsrts_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(u3rxtx_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(msp4_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
+	DB8540_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
+
+	/* Other alt C1 column */
+	DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C1),
+
+	/* Other alt C2 column */
+	DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C2),
+	DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C2),
+
+	/* Other alt C3 column */
+	DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C3),
+	DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C3),
+
+	/* Other alt C4 column */
+	DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4),
+
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define DB8540_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1");
+DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2",
+		"clkout2_a_1", "clkout2_a_2");
+DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
+DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
+DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
+DB8540_FUNC_GROUPS(hx, "hxclk_oc2_1", "hxgpio_oc2_1");
+DB8540_FUNC_GROUPS(i2c0, "i2c0_a_1");
+DB8540_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2");
+DB8540_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
+DB8540_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c4_b_1");
+DB8540_FUNC_GROUPS(i2c4, "i2c4_b_2");
+DB8540_FUNC_GROUPS(i2c5, "i2c5_b_1", "i2c5_b_2", "i2c5_c_1", "i2c5_c_2");
+DB8540_FUNC_GROUPS(i2c6, "i2c6_b_1", "i2c6_oc1_1");
+/* The image processor has 8 GPIO pins that can be muxed out */
+DB8540_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio0_c_1", "ipgpio0_c_2",
+		"ipgpio1_a_1", "ipgpio1_c_1", "ipgpio1_c_2",
+		"ipgpio2_b_1", "ipgpio2_c_1", "ipgpio2_c_2",
+		"ipgpio3_b_1", "ipgpio3_c_1", "ipgpio3_c_2",
+		"ipgpio4_c_1", "ipgpio4_c_2",
+		"ipgpio5_c_1", "ipgpio5_c_2",
+		"ipgpio6_c_1", "ipgpio6_c_2",
+		"ipgpio7_b_1", "ipgpio7_c_1");
+DB8540_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
+DB8540_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1");
+DB8540_FUNC_GROUPS(lcd, "lcd_d0_d7_a_1", "lcd_d12_d23_a_1", "lcd_d8_d11_a_1",
+		"lcdvsi0_a_1", "lcdvsi1_a_1");
+DB8540_FUNC_GROUPS(lcdb, "lcdb_a_1");
+DB8540_FUNC_GROUPS(mc0, "mc0_a_1");
+DB8540_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2");
+DB8540_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
+DB8540_FUNC_GROUPS(mc3, "mc3_b_1");
+DB8540_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
+DB8540_FUNC_GROUPS(mc5, "mc5_c_1");
+DB8540_FUNC_GROUPS(modaccgpo, "modaccgpo_c_1", "modaccgpo_oc1_1",
+		"modaccgpo_oc3_1");
+DB8540_FUNC_GROUPS(modaccuart, "modaccuart_oc2_1", "modaccuarttxrx_oc4_1",
+		"modaccuartrtccts_oc4_1");
+DB8540_FUNC_GROUPS(modi2s, "modi2s_a_1");
+DB8540_FUNC_GROUPS(modobs, "modobsclk_a_1", "modobsclkout_oc1_1",
+		"modobspwrctrl_oc1_1", "modobspwrrst_c_1",
+		"modobsrefclk_oc1_1", "modobsresout_c_1",
+		"modobsresout_oc1_1", "modobsservice_oc2_1");
+DB8540_FUNC_GROUPS(modprcmudbg, "modprcmudbg_oc1_1");
+DB8540_FUNC_GROUPS(modrf, "modrf_c_1");
+DB8540_FUNC_GROUPS(modsmb, "modsmb_a_1");
+DB8540_FUNC_GROUPS(modtrig, "modtrig_b_1");
+DB8540_FUNC_GROUPS(moduart, "moduart1_c_1", "moduart1_oc1_1",
+		"moduart1txrx_oc4_1", "moduart1rtscts_oc4_1", "moduart0_oc2_1");
+DB8540_FUNC_GROUPS(moduartstmmux, "moduartstmmux_b_1", "moduartstmmux_oc2_1",
+		"moduartstmmux_oc4_1");
+DB8540_FUNC_GROUPS(modxmip, "modxmip_oc1_1", "modxmip_oc2_1");
+/*
+ * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
+ * switched around by selecting the altfunction A or B.
+ */
+DB8540_FUNC_GROUPS(msp0, "msp0rfsrck_a_1", "msp0tfstck_a_1", "msp0txrx_a_1",
+		"msp0txrx_b_1");
+DB8540_FUNC_GROUPS(msp1, "msp1_a_1", "msp1txrx_a_1", "msp1txrx_b_1");
+DB8540_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2txdtcktfs_a_1", "msp2rxd_a_1");
+DB8540_FUNC_GROUPS(msp4, "msp4_a_1", "msp4_b_1", "msp4_c_1");
+DB8540_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4");
+DB8540_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
+DB8540_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc2_2");
+/* Select between CS0 on alt B or PS1 on alt C */
+DB8540_FUNC_GROUPS(sm, "sm_b_1", "smcleale_c_1", "smcs0_b_1", "smcs1_b_1",
+		"smps0_c_1", "smps1_c_1");
+DB8540_FUNC_GROUPS(spi0, "spi0_c_1");
+DB8540_FUNC_GROUPS(spi1, "spi1_b_1");
+DB8540_FUNC_GROUPS(spi2, "spi2_a_1");
+DB8540_FUNC_GROUPS(spi3, "spi3_oc1_1");
+DB8540_FUNC_GROUPS(ssp0, "ssp0_a_1");
+DB8540_FUNC_GROUPS(ssp1, "ssp1_a_1");
+DB8540_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_oc1_1", "stmape_oc2_1");
+DB8540_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_oc2_1", "stmmod_oc4_1");
+DB8540_FUNC_GROUPS(tpui, "tpui_oc3_1");
+DB8540_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1");
+DB8540_FUNC_GROUPS(u1, "u1ctsrts_a_1", "u1rxtx_a_1");
+DB8540_FUNC_GROUPS(u2, "u2_oc1_1", "u2_oc2_1", "u2ctsrts_a_1", "u2ctsrts_oc1_1",
+		"u2rxtx_c_1", "u2txrx_a_1", "u2txrx_b_1", "u2txrx_b_2",
+		"u2txrx_oc1_1");
+DB8540_FUNC_GROUPS(u3, "u3ctsrts_b_1", "u3rxtx_c_1", "u3txrxa_b_1");
+DB8540_FUNC_GROUPS(u4, "u4ctsrts_b_1", "u4ctsrts_c_1", "u4txrx_b_1");
+DB8540_FUNC_GROUPS(usb, "usb_a_1");
+
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct nmk_function nmk_db8540_functions[] = {
+	FUNCTION(apetrig),
+	FUNCTION(clkout),
+	FUNCTION(ddrtrig),
+	FUNCTION(hsi),
+	FUNCTION(hwobs),
+	FUNCTION(hx),
+	FUNCTION(i2c0),
+	FUNCTION(i2c1),
+	FUNCTION(i2c2),
+	FUNCTION(i2c3),
+	FUNCTION(i2c4),
+	FUNCTION(i2c5),
+	FUNCTION(i2c6),
+	FUNCTION(ipgpio),
+	FUNCTION(ipi2c),
+	FUNCTION(kp),
+	FUNCTION(lcd),
+	FUNCTION(lcdb),
+	FUNCTION(mc0),
+	FUNCTION(mc1),
+	FUNCTION(mc2),
+	FUNCTION(mc3),
+	FUNCTION(mc4),
+	FUNCTION(mc5),
+	FUNCTION(modaccgpo),
+	FUNCTION(modaccuart),
+	FUNCTION(modi2s),
+	FUNCTION(modobs),
+	FUNCTION(modprcmudbg),
+	FUNCTION(modrf),
+	FUNCTION(modsmb),
+	FUNCTION(modtrig),
+	FUNCTION(moduart),
+	FUNCTION(modxmip),
+	FUNCTION(msp0),
+	FUNCTION(msp1),
+	FUNCTION(msp2),
+	FUNCTION(msp4),
+	FUNCTION(pwl),
+	FUNCTION(remap),
+	FUNCTION(sbag),
+	FUNCTION(sm),
+	FUNCTION(spi0),
+	FUNCTION(spi1),
+	FUNCTION(spi2),
+	FUNCTION(spi3),
+	FUNCTION(ssp0),
+	FUNCTION(ssp1),
+	FUNCTION(stmape),
+	FUNCTION(stmmod),
+	FUNCTION(tpui),
+	FUNCTION(u0),
+	FUNCTION(u1),
+	FUNCTION(u2),
+	FUNCTION(u3),
+	FUNCTION(u4),
+	FUNCTION(usb)
+};
+
+static const struct prcm_gpiocr_altcx_pin_desc db8540_altcx_pins[] = {
+	PRCM_GPIOCR_ALTCX(8,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_CLK */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(9,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_RXD */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(10,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_FRM */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(11,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_TXD */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(23,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_CLK_a */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_CLK_a */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(24,	true, PRCM_IDX_GPIOCR3, 30,	/* U2_RXD_g */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_VAL_a */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(25,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[0] */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[0] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(26,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[1] */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[1] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(27,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[2] */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[2] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(28,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[3] */
+				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[3] */
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(64,	true, PRCM_IDX_GPIOCR1, 15,	/* MODOBS_REFCLK_REQ */
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_CTL */
+				true, PRCM_IDX_GPIOCR2, 23	/* HW_OBS_APE_PRCMU[17] */
+	),
+	PRCM_GPIOCR_ALTCX(65,	true, PRCM_IDX_GPIOCR1, 19,	/* MODOBS_PWRCTRL0 */
+				true, PRCM_IDX_GPIOCR1, 24,	/* Hx_CLK */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_CLK */
+				true, PRCM_IDX_GPIOCR2, 24	/* HW_OBS_APE_PRCMU[16] */
+	),
+	PRCM_GPIOCR_ALTCX(66,	true, PRCM_IDX_GPIOCR1, 15,	/* MODOBS_CLKOUT1 */
+				false, 0, 0,
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[15] */
+				true, PRCM_IDX_GPIOCR2, 25	/* HW_OBS_APE_PRCMU[15] */
+	),
+	PRCM_GPIOCR_ALTCX(67,	true, PRCM_IDX_GPIOCR1, 1,	/* MODUART1_TXD_a */
+				true, PRCM_IDX_GPIOCR1, 6,	/* MODACCUART_TXD_a */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[14] */
+				true, PRCM_IDX_GPIOCR2, 26	/* HW_OBS_APE_PRCMU[14] */
+	),
+	PRCM_GPIOCR_ALTCX(70,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[17] */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_CLK_b */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[13] */
+				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[13] */
+	),
+	PRCM_GPIOCR_ALTCX(71,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[16] */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[3] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[12] */
+				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[12] */
+	),
+	PRCM_GPIOCR_ALTCX(72,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[15] */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[2] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[11] */
+				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[11] */
+	),
+	PRCM_GPIOCR_ALTCX(73,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[14] */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[1] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[10] */
+				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[10] */
+	),
+	PRCM_GPIOCR_ALTCX(74,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[13] */
+				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[0] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[9] */
+				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[9] */
+	),
+	PRCM_GPIOCR_ALTCX(75,	true, PRCM_IDX_GPIOCR1, 12,	/* MODOBS_RESOUT0_N */
+				true, PRCM_IDX_GPIOCR2, 1,	/* MODUART_STMMUX_RXD_b */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[8] */
+				true, PRCM_IDX_GPIOCR2, 28	/* HW_OBS_APE_PRCMU[8] */
+	),
+	PRCM_GPIOCR_ALTCX(76,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[12] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[7] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[7] */
+				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[7] */
+	),
+	PRCM_GPIOCR_ALTCX(77,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[11] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[6] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[6] */
+				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[6] */
+	),
+	PRCM_GPIOCR_ALTCX(78,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[10] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[5] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[5] */
+				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[5] */
+	),
+	PRCM_GPIOCR_ALTCX(79,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[9] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[4] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[4] */
+				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[4] */
+	),
+	PRCM_GPIOCR_ALTCX(80,	true, PRCM_IDX_GPIOCR1, 26,	/* MODACC_GPO[0] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[3] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[3] */
+				true, PRCM_IDX_GPIOCR2, 30	/* HW_OBS_APE_PRCMU[3] */
+	),
+	PRCM_GPIOCR_ALTCX(81,	true, PRCM_IDX_GPIOCR2, 17,	/* MODACC_GPO[1] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[2] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[2] */
+				true, PRCM_IDX_GPIOCR2, 30	/* HW_OBS_APE_PRCMU[2] */
+	),
+	PRCM_GPIOCR_ALTCX(82,	true, PRCM_IDX_GPIOCR3, 8,	/* MOD_PRCMU_DEBUG[8] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[1] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[1] */
+				true, PRCM_IDX_GPIOCR2, 31	/* HW_OBS_APE_PRCMU[1] */
+	),
+	PRCM_GPIOCR_ALTCX(83,	true, PRCM_IDX_GPIOCR3, 8,	/* MOD_PRCMU_DEBUG[7] */
+				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[0] */
+				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[0] */
+				true, PRCM_IDX_GPIOCR2, 31	/* HW_OBS_APE_PRCMU[0] */
+	),
+	PRCM_GPIOCR_ALTCX(84,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[6] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_CLK_b */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[23] */
+				true, PRCM_IDX_GPIOCR1, 16	/* MODUART1_RXD_b */
+	),
+	PRCM_GPIOCR_ALTCX(85,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[5] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[3] */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[22] */
+				true, PRCM_IDX_GPIOCR1, 16	/* MODUART1_TXD_b */
+	),
+	PRCM_GPIOCR_ALTCX(86,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[0] */
+				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[0] */
+				true, PRCM_IDX_GPIOCR1, 14,	/* TPIU_D[25] */
+				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[0] */
+	),
+	PRCM_GPIOCR_ALTCX(87,	true, PRCM_IDX_GPIOCR3, 0,	/* MODACC_GPO_a[5] */
+				true, PRCM_IDX_GPIOCR2, 3,	/* U2_RXD_c */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[24] */
+				true, PRCM_IDX_GPIOCR1, 21	/* MODUART_STMMUX_RXD_c */
+	),
+	PRCM_GPIOCR_ALTCX(151,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP0 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(152,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP1 */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(153,	true, PRCM_IDX_GPIOCR3, 2,	/* KP_O_b[6] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[2] */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[21] */
+				true, PRCM_IDX_GPIOCR1, 0	/* MODUART1_RTS */
+	),
+	PRCM_GPIOCR_ALTCX(154,	true, PRCM_IDX_GPIOCR3, 2,	/* KP_I_b[6] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[1] */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[20] */
+				true, PRCM_IDX_GPIOCR1, 0	/* MODUART1_CTS */
+	),
+	PRCM_GPIOCR_ALTCX(155,	true, PRCM_IDX_GPIOCR3, 3,	/* KP_O_b[5] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[0] */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[19] */
+				true, PRCM_IDX_GPIOCR1, 5	/* MODACCUART_RXD_c */
+	),
+	PRCM_GPIOCR_ALTCX(156,	true, PRCM_IDX_GPIOCR3, 3,	/* KP_O_b[4] */
+				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_VAL_b */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[18] */
+				true, PRCM_IDX_GPIOCR1, 5	/* MODACCUART_TXD_b */
+	),
+	PRCM_GPIOCR_ALTCX(157,	true, PRCM_IDX_GPIOCR3, 4,	/* KP_I_b[5] */
+				true, PRCM_IDX_GPIOCR1, 23,	/* MODOBS_SERVICE_N */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[17] */
+				true, PRCM_IDX_GPIOCR1, 14	/* MODACCUART_RTS */
+	),
+	PRCM_GPIOCR_ALTCX(158,	true, PRCM_IDX_GPIOCR3, 4,	/* KP_I_b[4] */
+				true, PRCM_IDX_GPIOCR2, 0,	/* U2_TXD_c */
+				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[16] */
+				true, PRCM_IDX_GPIOCR1, 14	/* MODACCUART_CTS */
+	),
+	PRCM_GPIOCR_ALTCX(159,	true, PRCM_IDX_GPIOCR3, 5,	/* KP_O_b[3] */
+				true, PRCM_IDX_GPIOCR3, 10,	/* MODUART0_RXD */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[31] */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(160,	true, PRCM_IDX_GPIOCR3, 5,	/* KP_I_b[3] */
+				true, PRCM_IDX_GPIOCR3, 10,	/* MODUART0_TXD */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[30] */
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(161,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[4] */
+				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_CLK_b */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[29] */
+				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_CLK_c */
+	),
+	PRCM_GPIOCR_ALTCX(162,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[3] */
+				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[3] */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[28] */
+				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[3] */
+	),
+	PRCM_GPIOCR_ALTCX(163,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[2] */
+				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[2] */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[27] */
+				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[2] */
+	),
+	PRCM_GPIOCR_ALTCX(164,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[1] */
+				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[1] */
+				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[26] */
+				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[1] */
+	),
+	PRCM_GPIOCR_ALTCX(204,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_RXD_f */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(205,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_TXD_f */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(206,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_CTSn_b */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+	PRCM_GPIOCR_ALTCX(207,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_RTSn_b */
+				false, 0, 0,
+				false, 0, 0,
+				false, 0, 0
+	),
+};
+
+static const u16 db8540_prcm_gpiocr_regs[] = {
+	[PRCM_IDX_GPIOCR1] = 0x138,
+	[PRCM_IDX_GPIOCR2] = 0x574,
+	[PRCM_IDX_GPIOCR3] = 0x2bc,
+};
+
+static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
+	.gpio_ranges = nmk_db8540_ranges,
+	.gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
+	.pins = nmk_db8540_pins,
+	.npins = ARRAY_SIZE(nmk_db8540_pins),
+	.functions = nmk_db8540_functions,
+	.nfunctions = ARRAY_SIZE(nmk_db8540_functions),
+	.groups = nmk_db8540_groups,
+	.ngroups = ARRAY_SIZE(nmk_db8540_groups),
+	.altcx_pins = db8540_altcx_pins,
+	.npins_altcx = ARRAY_SIZE(db8540_altcx_pins),
+	.prcm_gpiocr_registers = db8540_prcm_gpiocr_regs,
+};
+
+void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
+{
+	*soc = &nmk_db8540_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.h
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,192 @@
+#ifndef PINCTRL_PINCTRL_NOMADIK_H
+#define PINCTRL_PINCTRL_NOMADIK_H
+
+/* Package definitions */
+#define PINCTRL_NMK_STN8815	0
+#define PINCTRL_NMK_DB8500	1
+#define PINCTRL_NMK_DB8540	2
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO	0
+#define NMK_GPIO_ALT_A	1
+#define NMK_GPIO_ALT_B	2
+#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
+#define PRCM_GPIOCR_ALTCX(pin_num,\
+	altc1_used, altc1_ri, altc1_cb,\
+	altc2_used, altc2_ri, altc2_cb,\
+	altc3_used, altc3_ri, altc3_cb,\
+	altc4_used, altc4_ri, altc4_cb)\
+{\
+	.pin = pin_num,\
+	.altcx[PRCM_IDX_GPIOCR_ALTC1] = {\
+		.used = altc1_used,\
+		.reg_index = altc1_ri,\
+		.control_bit = altc1_cb\
+	},\
+	.altcx[PRCM_IDX_GPIOCR_ALTC2] = {\
+		.used = altc2_used,\
+		.reg_index = altc2_ri,\
+		.control_bit = altc2_cb\
+	},\
+	.altcx[PRCM_IDX_GPIOCR_ALTC3] = {\
+		.used = altc3_used,\
+		.reg_index = altc3_ri,\
+		.control_bit = altc3_cb\
+	},\
+	.altcx[PRCM_IDX_GPIOCR_ALTC4] = {\
+		.used = altc4_used,\
+		.reg_index = altc4_ri,\
+		.control_bit = altc4_cb\
+	},\
+}
+
+/**
+ * enum prcm_gpiocr_reg_index
+ * Used to reference an PRCM GPIOCR register address.
+ */
+enum prcm_gpiocr_reg_index {
+	PRCM_IDX_GPIOCR1,
+	PRCM_IDX_GPIOCR2,
+	PRCM_IDX_GPIOCR3
+};
+/**
+ * enum prcm_gpiocr_altcx_index
+ * Used to reference an Other alternate-C function.
+ */
+enum prcm_gpiocr_altcx_index {
+	PRCM_IDX_GPIOCR_ALTC1,
+	PRCM_IDX_GPIOCR_ALTC2,
+	PRCM_IDX_GPIOCR_ALTC3,
+	PRCM_IDX_GPIOCR_ALTC4,
+	PRCM_IDX_GPIOCR_ALTC_MAX,
+};
+
+/**
+ * struct prcm_gpio_altcx - Other alternate-C function
+ * @used: other alternate-C function availability
+ * @reg_index: PRCM GPIOCR register index used to control the function
+ * @control_bit: PRCM GPIOCR bit used to control the function
+ */
+struct prcm_gpiocr_altcx {
+	bool used:1;
+	u8 reg_index:2;
+	u8 control_bit:5;
+} __packed;
+
+/**
+ * struct prcm_gpio_altcx_pin_desc - Other alternate-C pin
+ * @pin: The pin number
+ * @altcx: array of other alternate-C[1-4] functions
+ */
+struct prcm_gpiocr_altcx_pin_desc {
+	unsigned short pin;
+	struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX];
+};
+
+/**
+ * struct nmk_function - Nomadik pinctrl mux function
+ * @name: The name of the function, exported to pinctrl core.
+ * @groups: An array of pin groups that may select this function.
+ * @ngroups: The number of entries in @groups.
+ */
+struct nmk_function {
+	const char *name;
+	const char * const *groups;
+	unsigned ngroups;
+};
+
+/**
+ * struct nmk_pingroup - describes a Nomadik pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ * @altsetting: the altsetting to apply to all pins in this group to
+ *	configure them to be used by a function
+ */
+struct nmk_pingroup {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned npins;
+	int altsetting;
+};
+
+/**
+ * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration
+ * @gpio_ranges: An array of GPIO ranges for this SoC
+ * @gpio_num_ranges: The number of GPIO ranges for this SoC
+ * @pins:	An array describing all pins the pin controller affects.
+ *		All pins which are also GPIOs must be listed first within the
+ *		array, and be numbered identically to the GPIO controller's
+ *		numbering.
+ * @npins:	The number of entries in @pins.
+ * @functions:	The functions supported on this SoC.
+ * @nfunction:	The number of entries in @functions.
+ * @groups:	An array describing all pin groups the pin SoC supports.
+ * @ngroups:	The number of entries in @groups.
+ * @altcx_pins:	The pins that support Other alternate-C function on this SoC
+ * @npins_altcx: The number of Other alternate-C pins
+ * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
+ */
+struct nmk_pinctrl_soc_data {
+	struct pinctrl_gpio_range *gpio_ranges;
+	unsigned gpio_num_ranges;
+	const struct pinctrl_pin_desc *pins;
+	unsigned npins;
+	const struct nmk_function *functions;
+	unsigned nfunctions;
+	const struct nmk_pingroup *groups;
+	unsigned ngroups;
+	const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
+	unsigned npins_altcx;
+	const u16 *prcm_gpiocr_registers;
+};
+
+#ifdef CONFIG_PINCTRL_STN8815
+
+void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PINCTRL_DB8500
+
+void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PINCTRL_DB8540
+
+void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
+#endif /* PINCTRL_PINCTRL_NOMADIK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
--- linux-libre-3.16-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,356 @@
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-nomadik.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define _GPIO(offset)		(offset)
+
+#define STN8815_PIN_B4		_GPIO(0)
+#define STN8815_PIN_D5		_GPIO(1)
+#define STN8815_PIN_C5		_GPIO(2)
+#define STN8815_PIN_A4		_GPIO(3)
+#define STN8815_PIN_B5		_GPIO(4)
+#define STN8815_PIN_D6		_GPIO(5)
+#define STN8815_PIN_C6		_GPIO(6)
+#define STN8815_PIN_B6		_GPIO(7)
+#define STN8815_PIN_B10		_GPIO(8)
+#define STN8815_PIN_A10		_GPIO(9)
+#define STN8815_PIN_C11		_GPIO(10)
+#define STN8815_PIN_B11		_GPIO(11)
+#define STN8815_PIN_A11		_GPIO(12)
+#define STN8815_PIN_C12		_GPIO(13)
+#define STN8815_PIN_B12		_GPIO(14)
+#define STN8815_PIN_A12		_GPIO(15)
+#define STN8815_PIN_C13		_GPIO(16)
+#define STN8815_PIN_B13		_GPIO(17)
+#define STN8815_PIN_A13		_GPIO(18)
+#define STN8815_PIN_D13		_GPIO(19)
+#define STN8815_PIN_C14		_GPIO(20)
+#define STN8815_PIN_B14		_GPIO(21)
+#define STN8815_PIN_A14		_GPIO(22)
+#define STN8815_PIN_D15		_GPIO(23)
+#define STN8815_PIN_C15		_GPIO(24)
+#define STN8815_PIN_B15		_GPIO(25)
+#define STN8815_PIN_A15		_GPIO(26)
+#define STN8815_PIN_C16		_GPIO(27)
+#define STN8815_PIN_B16		_GPIO(28)
+#define STN8815_PIN_A16		_GPIO(29)
+#define STN8815_PIN_D17		_GPIO(30)
+#define STN8815_PIN_C17		_GPIO(31)
+#define STN8815_PIN_AB6		_GPIO(32)
+#define STN8815_PIN_AA6		_GPIO(33)
+#define STN8815_PIN_Y6		_GPIO(34)
+#define STN8815_PIN_Y5		_GPIO(35)
+#define STN8815_PIN_AA5		_GPIO(36)
+#define STN8815_PIN_AB5		_GPIO(37)
+#define STN8815_PIN_AB4		_GPIO(38)
+#define STN8815_PIN_Y4		_GPIO(39)
+#define STN8815_PIN_R1		_GPIO(40)
+#define STN8815_PIN_R2		_GPIO(41)
+#define STN8815_PIN_R3		_GPIO(42)
+#define STN8815_PIN_P1		_GPIO(43)
+#define STN8815_PIN_P2		_GPIO(44)
+#define STN8815_PIN_P3		_GPIO(45)
+#define STN8815_PIN_N1		_GPIO(46)
+#define STN8815_PIN_N2		_GPIO(47)
+#define STN8815_PIN_N3		_GPIO(48)
+#define STN8815_PIN_M1		_GPIO(49)
+#define STN8815_PIN_M3		_GPIO(50)
+#define STN8815_PIN_M2		_GPIO(51)
+#define STN8815_PIN_L1		_GPIO(52)
+#define STN8815_PIN_L4		_GPIO(53)
+#define STN8815_PIN_L3		_GPIO(54)
+#define STN8815_PIN_L2		_GPIO(55)
+#define STN8815_PIN_F3		_GPIO(56)
+#define STN8815_PIN_F2		_GPIO(57)
+#define STN8815_PIN_E1		_GPIO(58)
+#define STN8815_PIN_E3		_GPIO(59)
+#define STN8815_PIN_E2		_GPIO(60)
+#define STN8815_PIN_E4		_GPIO(61)
+#define STN8815_PIN_D3		_GPIO(62)
+#define STN8815_PIN_D2		_GPIO(63)
+#define STN8815_PIN_F21		_GPIO(64)
+#define STN8815_PIN_F20		_GPIO(65)
+#define STN8815_PIN_E22		_GPIO(66)
+#define STN8815_PIN_D22		_GPIO(67)
+#define STN8815_PIN_E21		_GPIO(68)
+#define STN8815_PIN_E20		_GPIO(69)
+#define STN8815_PIN_C22		_GPIO(70)
+#define STN8815_PIN_D21		_GPIO(71)
+#define STN8815_PIN_D20		_GPIO(72)
+#define STN8815_PIN_C21		_GPIO(73)
+#define STN8815_PIN_C20		_GPIO(74)
+#define STN8815_PIN_C19		_GPIO(75)
+#define STN8815_PIN_B20		_GPIO(76)
+#define STN8815_PIN_B8		_GPIO(77)
+#define STN8815_PIN_A8		_GPIO(78)
+#define STN8815_PIN_C9		_GPIO(79)
+#define STN8815_PIN_B9		_GPIO(80)
+#define STN8815_PIN_A9		_GPIO(81)
+#define STN8815_PIN_C10		_GPIO(82)
+#define STN8815_PIN_K1		_GPIO(83)
+#define STN8815_PIN_K3		_GPIO(84)
+#define STN8815_PIN_K2		_GPIO(85)
+#define STN8815_PIN_J1		_GPIO(86)
+#define STN8815_PIN_J3		_GPIO(87)
+#define STN8815_PIN_J2		_GPIO(88)
+#define STN8815_PIN_H1		_GPIO(89)
+#define STN8815_PIN_H3		_GPIO(90)
+#define STN8815_PIN_H2		_GPIO(91)
+#define STN8815_PIN_G1		_GPIO(92)
+#define STN8815_PIN_G3		_GPIO(93)
+#define STN8815_PIN_G2		_GPIO(94)
+#define STN8815_PIN_F1		_GPIO(95)
+#define STN8815_PIN_T20		_GPIO(96)
+#define STN8815_PIN_R21		_GPIO(97)
+#define STN8815_PIN_R20		_GPIO(98)
+#define STN8815_PIN_U22		_GPIO(99)
+#define STN8815_PIN_N21		_GPIO(100)
+#define STN8815_PIN_N20		_GPIO(101)
+#define STN8815_PIN_P22		_GPIO(102)
+#define STN8815_PIN_N22		_GPIO(103)
+#define STN8815_PIN_V22		_GPIO(104)
+#define STN8815_PIN_V21		_GPIO(105)
+#define STN8815_PIN_K22		_GPIO(106)
+#define STN8815_PIN_K21		_GPIO(107)
+#define STN8815_PIN_H20		_GPIO(108)
+#define STN8815_PIN_G20		_GPIO(109)
+#define STN8815_PIN_L21		_GPIO(110)
+#define STN8815_PIN_H21		_GPIO(111)
+#define STN8815_PIN_J21		_GPIO(112)
+#define STN8815_PIN_H22		_GPIO(113)
+#define STN8815_PIN_K20		_GPIO(114)
+#define STN8815_PIN_L22		_GPIO(115)
+#define STN8815_PIN_G21		_GPIO(116)
+#define STN8815_PIN_J20		_GPIO(117)
+#define STN8815_PIN_G22		_GPIO(118)
+#define STN8815_PIN_U19		_GPIO(119)
+#define STN8815_PIN_G19		_GPIO(120)
+#define STN8815_PIN_M22		_GPIO(121)
+#define STN8815_PIN_M19		_GPIO(122)
+#define STN8815_PIN_J22		_GPIO(123)
+/* GPIOs 124-127 not routed to pins */
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc nmk_stn8815_pins[] = {
+	PINCTRL_PIN(STN8815_PIN_B4, "GPIO0_B4"),
+	PINCTRL_PIN(STN8815_PIN_D5, "GPIO1_D5"),
+	PINCTRL_PIN(STN8815_PIN_C5, "GPIO2_C5"),
+	PINCTRL_PIN(STN8815_PIN_A4, "GPIO3_A4"),
+	PINCTRL_PIN(STN8815_PIN_B5, "GPIO4_B5"),
+	PINCTRL_PIN(STN8815_PIN_D6, "GPIO5_D6"),
+	PINCTRL_PIN(STN8815_PIN_C6, "GPIO6_C6"),
+	PINCTRL_PIN(STN8815_PIN_B6, "GPIO7_B6"),
+	PINCTRL_PIN(STN8815_PIN_B10, "GPIO8_B10"),
+	PINCTRL_PIN(STN8815_PIN_A10, "GPIO9_A10"),
+	PINCTRL_PIN(STN8815_PIN_C11, "GPIO10_C11"),
+	PINCTRL_PIN(STN8815_PIN_B11, "GPIO11_B11"),
+	PINCTRL_PIN(STN8815_PIN_A11, "GPIO12_A11"),
+	PINCTRL_PIN(STN8815_PIN_C12, "GPIO13_C12"),
+	PINCTRL_PIN(STN8815_PIN_B12, "GPIO14_B12"),
+	PINCTRL_PIN(STN8815_PIN_A12, "GPIO15_A12"),
+	PINCTRL_PIN(STN8815_PIN_C13, "GPIO16_C13"),
+	PINCTRL_PIN(STN8815_PIN_B13, "GPIO17_B13"),
+	PINCTRL_PIN(STN8815_PIN_A13, "GPIO18_A13"),
+	PINCTRL_PIN(STN8815_PIN_D13, "GPIO19_D13"),
+	PINCTRL_PIN(STN8815_PIN_C14, "GPIO20_C14"),
+	PINCTRL_PIN(STN8815_PIN_B14, "GPIO21_B14"),
+	PINCTRL_PIN(STN8815_PIN_A14, "GPIO22_A14"),
+	PINCTRL_PIN(STN8815_PIN_D15, "GPIO23_D15"),
+	PINCTRL_PIN(STN8815_PIN_C15, "GPIO24_C15"),
+	PINCTRL_PIN(STN8815_PIN_B15, "GPIO25_B15"),
+	PINCTRL_PIN(STN8815_PIN_A15, "GPIO26_A15"),
+	PINCTRL_PIN(STN8815_PIN_C16, "GPIO27_C16"),
+	PINCTRL_PIN(STN8815_PIN_B16, "GPIO28_B16"),
+	PINCTRL_PIN(STN8815_PIN_A16, "GPIO29_A16"),
+	PINCTRL_PIN(STN8815_PIN_D17, "GPIO30_D17"),
+	PINCTRL_PIN(STN8815_PIN_C17, "GPIO31_C17"),
+	PINCTRL_PIN(STN8815_PIN_AB6, "GPIO32_AB6"),
+	PINCTRL_PIN(STN8815_PIN_AA6, "GPIO33_AA6"),
+	PINCTRL_PIN(STN8815_PIN_Y6, "GPIO34_Y6"),
+	PINCTRL_PIN(STN8815_PIN_Y5, "GPIO35_Y5"),
+	PINCTRL_PIN(STN8815_PIN_AA5, "GPIO36_AA5"),
+	PINCTRL_PIN(STN8815_PIN_AB5, "GPIO37_AB5"),
+	PINCTRL_PIN(STN8815_PIN_AB4, "GPIO38_AB4"),
+	PINCTRL_PIN(STN8815_PIN_Y4, "GPIO39_Y4"),
+	PINCTRL_PIN(STN8815_PIN_R1, "GPIO40_R1"),
+	PINCTRL_PIN(STN8815_PIN_R2, "GPIO41_R2"),
+	PINCTRL_PIN(STN8815_PIN_R3, "GPIO42_R3"),
+	PINCTRL_PIN(STN8815_PIN_P1, "GPIO43_P1"),
+	PINCTRL_PIN(STN8815_PIN_P2, "GPIO44_P2"),
+	PINCTRL_PIN(STN8815_PIN_P3, "GPIO45_P3"),
+	PINCTRL_PIN(STN8815_PIN_N1, "GPIO46_N1"),
+	PINCTRL_PIN(STN8815_PIN_N2, "GPIO47_N2"),
+	PINCTRL_PIN(STN8815_PIN_N3, "GPIO48_N3"),
+	PINCTRL_PIN(STN8815_PIN_M1, "GPIO49_M1"),
+	PINCTRL_PIN(STN8815_PIN_M3, "GPIO50_M3"),
+	PINCTRL_PIN(STN8815_PIN_M2, "GPIO51_M2"),
+	PINCTRL_PIN(STN8815_PIN_L1, "GPIO52_L1"),
+	PINCTRL_PIN(STN8815_PIN_L4, "GPIO53_L4"),
+	PINCTRL_PIN(STN8815_PIN_L3, "GPIO54_L3"),
+	PINCTRL_PIN(STN8815_PIN_L2, "GPIO55_L2"),
+	PINCTRL_PIN(STN8815_PIN_F3, "GPIO56_F3"),
+	PINCTRL_PIN(STN8815_PIN_F2, "GPIO57_F2"),
+	PINCTRL_PIN(STN8815_PIN_E1, "GPIO58_E1"),
+	PINCTRL_PIN(STN8815_PIN_E3, "GPIO59_E3"),
+	PINCTRL_PIN(STN8815_PIN_E2, "GPIO60_E2"),
+	PINCTRL_PIN(STN8815_PIN_E4, "GPIO61_E4"),
+	PINCTRL_PIN(STN8815_PIN_D3, "GPIO62_D3"),
+	PINCTRL_PIN(STN8815_PIN_D2, "GPIO63_D2"),
+	PINCTRL_PIN(STN8815_PIN_F21, "GPIO64_F21"),
+	PINCTRL_PIN(STN8815_PIN_F20, "GPIO65_F20"),
+	PINCTRL_PIN(STN8815_PIN_E22, "GPIO66_E22"),
+	PINCTRL_PIN(STN8815_PIN_D22, "GPIO67_D22"),
+	PINCTRL_PIN(STN8815_PIN_E21, "GPIO68_E21"),
+	PINCTRL_PIN(STN8815_PIN_E20, "GPIO69_E20"),
+	PINCTRL_PIN(STN8815_PIN_C22, "GPIO70_C22"),
+	PINCTRL_PIN(STN8815_PIN_D21, "GPIO71_D21"),
+	PINCTRL_PIN(STN8815_PIN_D20, "GPIO72_D20"),
+	PINCTRL_PIN(STN8815_PIN_C21, "GPIO73_C21"),
+	PINCTRL_PIN(STN8815_PIN_C20, "GPIO74_C20"),
+	PINCTRL_PIN(STN8815_PIN_C19, "GPIO75_C19"),
+	PINCTRL_PIN(STN8815_PIN_B20, "GPIO76_B20"),
+	PINCTRL_PIN(STN8815_PIN_B8, "GPIO77_B8"),
+	PINCTRL_PIN(STN8815_PIN_A8, "GPIO78_A8"),
+	PINCTRL_PIN(STN8815_PIN_C9, "GPIO79_C9"),
+	PINCTRL_PIN(STN8815_PIN_B9, "GPIO80_B9"),
+	PINCTRL_PIN(STN8815_PIN_A9, "GPIO81_A9"),
+	PINCTRL_PIN(STN8815_PIN_C10, "GPIO82_C10"),
+	PINCTRL_PIN(STN8815_PIN_K1, "GPIO83_K1"),
+	PINCTRL_PIN(STN8815_PIN_K3, "GPIO84_K3"),
+	PINCTRL_PIN(STN8815_PIN_K2, "GPIO85_K2"),
+	PINCTRL_PIN(STN8815_PIN_J1, "GPIO86_J1"),
+	PINCTRL_PIN(STN8815_PIN_J3, "GPIO87_J3"),
+	PINCTRL_PIN(STN8815_PIN_J2, "GPIO88_J2"),
+	PINCTRL_PIN(STN8815_PIN_H1, "GPIO89_H1"),
+	PINCTRL_PIN(STN8815_PIN_H3, "GPIO90_H3"),
+	PINCTRL_PIN(STN8815_PIN_H2, "GPIO91_H2"),
+	PINCTRL_PIN(STN8815_PIN_G1, "GPIO92_G1"),
+	PINCTRL_PIN(STN8815_PIN_G3, "GPIO93_G3"),
+	PINCTRL_PIN(STN8815_PIN_G2, "GPIO94_G2"),
+	PINCTRL_PIN(STN8815_PIN_F1, "GPIO95_F1"),
+	PINCTRL_PIN(STN8815_PIN_T20, "GPIO96_T20"),
+	PINCTRL_PIN(STN8815_PIN_R21, "GPIO97_R21"),
+	PINCTRL_PIN(STN8815_PIN_R20, "GPIO98_R20"),
+	PINCTRL_PIN(STN8815_PIN_U22, "GPIO99_U22"),
+	PINCTRL_PIN(STN8815_PIN_N21, "GPIO100_N21"),
+	PINCTRL_PIN(STN8815_PIN_N20, "GPIO101_N20"),
+	PINCTRL_PIN(STN8815_PIN_P22, "GPIO102_P22"),
+	PINCTRL_PIN(STN8815_PIN_N22, "GPIO103_N22"),
+	PINCTRL_PIN(STN8815_PIN_V22, "GPIO104_V22"),
+	PINCTRL_PIN(STN8815_PIN_V21, "GPIO105_V21"),
+	PINCTRL_PIN(STN8815_PIN_K22, "GPIO106_K22"),
+	PINCTRL_PIN(STN8815_PIN_K21, "GPIO107_K21"),
+	PINCTRL_PIN(STN8815_PIN_H20, "GPIO108_H20"),
+	PINCTRL_PIN(STN8815_PIN_G20, "GPIO109_G20"),
+	PINCTRL_PIN(STN8815_PIN_L21, "GPIO110_L21"),
+	PINCTRL_PIN(STN8815_PIN_H21, "GPIO111_H21"),
+	PINCTRL_PIN(STN8815_PIN_J21, "GPIO112_J21"),
+	PINCTRL_PIN(STN8815_PIN_H22, "GPIO113_H22"),
+	PINCTRL_PIN(STN8815_PIN_K20, "GPIO114_K20"),
+	PINCTRL_PIN(STN8815_PIN_L22, "GPIO115_L22"),
+	PINCTRL_PIN(STN8815_PIN_G21, "GPIO116_G21"),
+	PINCTRL_PIN(STN8815_PIN_J20, "GPIO117_J20"),
+	PINCTRL_PIN(STN8815_PIN_G22, "GPIO118_G22"),
+	PINCTRL_PIN(STN8815_PIN_U19, "GPIO119_U19"),
+	PINCTRL_PIN(STN8815_PIN_G19, "GPIO120_G19"),
+	PINCTRL_PIN(STN8815_PIN_M22, "GPIO121_M22"),
+	PINCTRL_PIN(STN8815_PIN_M19, "GPIO122_M19"),
+	PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"),
+};
+
+#define STN8815_GPIO_RANGE(a, b, c) { .name = "STN8815", .id = a, .base = b, \
+			.pin_base = b, .npins = c }
+
+/*
+ * This matches the 32-pin gpio chips registered by the GPIO portion. This
+ * cannot be const since we assign the struct gpio_chip * pointer at runtime.
+ */
+static struct pinctrl_gpio_range nmk_stn8815_ranges[] = {
+	STN8815_GPIO_RANGE(0, 0, 32),
+	STN8815_GPIO_RANGE(1, 32, 32),
+	STN8815_GPIO_RANGE(2, 64, 32),
+	STN8815_GPIO_RANGE(3, 96, 28),
+};
+
+/*
+ * Read the pin group names like this:
+ * u0_a_1    = first groups of pins for uart0 on alt function a
+ * i2c2_b_2  = second group of pins for i2c2 on alt function b
+ */
+
+/* Altfunction A */
+static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5,
+	STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6,
+	STN8815_PIN_C6, STN8815_PIN_B6 };
+static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10,
+	STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12,
+	STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 };
+static const unsigned u1_a_1_pins[] = { STN8815_PIN_M2, STN8815_PIN_L1,
+					STN8815_PIN_F3, STN8815_PIN_F2 };
+static const unsigned i2c1_a_1_pins[] = { STN8815_PIN_L4, STN8815_PIN_L3 };
+static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 };
+/* Altfunction B */
+static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
+static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
+
+#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct nmk_pingroup nmk_stn8815_groups[] = {
+	STN8815_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
+	STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A),
+	STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A),
+	STN8815_PIN_GROUP(i2c1_a_1, NMK_GPIO_ALT_A),
+	STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
+	STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B),
+	STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define STN8815_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+STN8815_FUNC_GROUPS(u0, "u0_a_1");
+STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1");
+STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1");
+STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1");
+STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1");
+STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct nmk_function nmk_stn8815_functions[] = {
+	FUNCTION(u0),
+	FUNCTION(mmcsd),
+	FUNCTION(u1),
+	FUNCTION(i2c1),
+	FUNCTION(i2c0),
+	FUNCTION(i2cusb),
+};
+
+static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = {
+	.gpio_ranges = nmk_stn8815_ranges,
+	.gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges),
+	.pins = nmk_stn8815_pins,
+	.npins = ARRAY_SIZE(nmk_stn8815_pins),
+	.functions = nmk_stn8815_functions,
+	.nfunctions = ARRAY_SIZE(nmk_stn8815_functions),
+	.groups = nmk_stn8815_groups,
+	.ngroups = ARRAY_SIZE(nmk_stn8815_groups),
+};
+
+void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
+{
+	*soc = &nmk_stn8815_soc;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8500.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,485 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include "pinctrl-abx500.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define ABX500_GPIO(offset)		(offset)
-
-#define AB8500_PIN_T10		ABX500_GPIO(1)
-#define AB8500_PIN_T9		ABX500_GPIO(2)
-#define AB8500_PIN_U9		ABX500_GPIO(3)
-#define AB8500_PIN_W2		ABX500_GPIO(4)
-/* hole */
-#define AB8500_PIN_Y18		ABX500_GPIO(6)
-#define AB8500_PIN_AA20		ABX500_GPIO(7)
-#define AB8500_PIN_W18		ABX500_GPIO(8)
-#define AB8500_PIN_AA19		ABX500_GPIO(9)
-#define AB8500_PIN_U17		ABX500_GPIO(10)
-#define AB8500_PIN_AA18		ABX500_GPIO(11)
-#define AB8500_PIN_U16		ABX500_GPIO(12)
-#define AB8500_PIN_W17		ABX500_GPIO(13)
-#define AB8500_PIN_F14		ABX500_GPIO(14)
-#define AB8500_PIN_B17		ABX500_GPIO(15)
-#define AB8500_PIN_F15		ABX500_GPIO(16)
-#define AB8500_PIN_P5		ABX500_GPIO(17)
-#define AB8500_PIN_R5		ABX500_GPIO(18)
-#define AB8500_PIN_U5		ABX500_GPIO(19)
-#define AB8500_PIN_T5		ABX500_GPIO(20)
-#define AB8500_PIN_H19		ABX500_GPIO(21)
-#define AB8500_PIN_G20		ABX500_GPIO(22)
-#define AB8500_PIN_G19		ABX500_GPIO(23)
-#define AB8500_PIN_T14		ABX500_GPIO(24)
-#define AB8500_PIN_R16		ABX500_GPIO(25)
-#define AB8500_PIN_M16		ABX500_GPIO(26)
-#define AB8500_PIN_J6		ABX500_GPIO(27)
-#define AB8500_PIN_K6		ABX500_GPIO(28)
-#define AB8500_PIN_G6		ABX500_GPIO(29)
-#define AB8500_PIN_H6		ABX500_GPIO(30)
-#define AB8500_PIN_F5		ABX500_GPIO(31)
-#define AB8500_PIN_G5		ABX500_GPIO(32)
-/* hole */
-#define AB8500_PIN_R17		ABX500_GPIO(34)
-#define AB8500_PIN_W15		ABX500_GPIO(35)
-#define AB8500_PIN_A17		ABX500_GPIO(36)
-#define AB8500_PIN_E15		ABX500_GPIO(37)
-#define AB8500_PIN_C17		ABX500_GPIO(38)
-#define AB8500_PIN_E16		ABX500_GPIO(39)
-#define AB8500_PIN_T19		ABX500_GPIO(40)
-#define AB8500_PIN_U19		ABX500_GPIO(41)
-#define AB8500_PIN_U2		ABX500_GPIO(42)
-
-/* indicates the highest GPIO number */
-#define AB8500_GPIO_MAX_NUMBER	42
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc ab8500_pins[] = {
-	PINCTRL_PIN(AB8500_PIN_T10, "GPIO1_T10"),
-	PINCTRL_PIN(AB8500_PIN_T9, "GPIO2_T9"),
-	PINCTRL_PIN(AB8500_PIN_U9, "GPIO3_U9"),
-	PINCTRL_PIN(AB8500_PIN_W2, "GPIO4_W2"),
-	/* hole */
-	PINCTRL_PIN(AB8500_PIN_Y18, "GPIO6_Y18"),
-	PINCTRL_PIN(AB8500_PIN_AA20, "GPIO7_AA20"),
-	PINCTRL_PIN(AB8500_PIN_W18, "GPIO8_W18"),
-	PINCTRL_PIN(AB8500_PIN_AA19, "GPIO9_AA19"),
-	PINCTRL_PIN(AB8500_PIN_U17, "GPIO10_U17"),
-	PINCTRL_PIN(AB8500_PIN_AA18, "GPIO11_AA18"),
-	PINCTRL_PIN(AB8500_PIN_U16, "GPIO12_U16"),
-	PINCTRL_PIN(AB8500_PIN_W17, "GPIO13_W17"),
-	PINCTRL_PIN(AB8500_PIN_F14, "GPIO14_F14"),
-	PINCTRL_PIN(AB8500_PIN_B17, "GPIO15_B17"),
-	PINCTRL_PIN(AB8500_PIN_F15, "GPIO16_F15"),
-	PINCTRL_PIN(AB8500_PIN_P5, "GPIO17_P5"),
-	PINCTRL_PIN(AB8500_PIN_R5, "GPIO18_R5"),
-	PINCTRL_PIN(AB8500_PIN_U5, "GPIO19_U5"),
-	PINCTRL_PIN(AB8500_PIN_T5, "GPIO20_T5"),
-	PINCTRL_PIN(AB8500_PIN_H19, "GPIO21_H19"),
-	PINCTRL_PIN(AB8500_PIN_G20, "GPIO22_G20"),
-	PINCTRL_PIN(AB8500_PIN_G19, "GPIO23_G19"),
-	PINCTRL_PIN(AB8500_PIN_T14, "GPIO24_T14"),
-	PINCTRL_PIN(AB8500_PIN_R16, "GPIO25_R16"),
-	PINCTRL_PIN(AB8500_PIN_M16, "GPIO26_M16"),
-	PINCTRL_PIN(AB8500_PIN_J6, "GPIO27_J6"),
-	PINCTRL_PIN(AB8500_PIN_K6, "GPIO28_K6"),
-	PINCTRL_PIN(AB8500_PIN_G6, "GPIO29_G6"),
-	PINCTRL_PIN(AB8500_PIN_H6, "GPIO30_H6"),
-	PINCTRL_PIN(AB8500_PIN_F5, "GPIO31_F5"),
-	PINCTRL_PIN(AB8500_PIN_G5, "GPIO32_G5"),
-	/* hole */
-	PINCTRL_PIN(AB8500_PIN_R17, "GPIO34_R17"),
-	PINCTRL_PIN(AB8500_PIN_W15, "GPIO35_W15"),
-	PINCTRL_PIN(AB8500_PIN_A17, "GPIO36_A17"),
-	PINCTRL_PIN(AB8500_PIN_E15, "GPIO37_E15"),
-	PINCTRL_PIN(AB8500_PIN_C17, "GPIO38_C17"),
-	PINCTRL_PIN(AB8500_PIN_E16, "GPIO39_E16"),
-	PINCTRL_PIN(AB8500_PIN_T19, "GPIO40_T19"),
-	PINCTRL_PIN(AB8500_PIN_U19, "GPIO41_U19"),
-	PINCTRL_PIN(AB8500_PIN_U2, "GPIO42_U2"),
-};
-
-/*
- * Maps local GPIO offsets to local pin numbers
- */
-static const struct abx500_pinrange ab8500_pinranges[] = {
-	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
-	ABX500_PINRANGE(6, 4, ABX500_ALT_A),
-	ABX500_PINRANGE(10, 4, ABX500_DEFAULT),
-	ABX500_PINRANGE(14, 12, ABX500_ALT_A),
-	ABX500_PINRANGE(26, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
-	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
-	ABX500_PINRANGE(35, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(36, 7, ABX500_ALT_A),
-};
-
-/*
- * Read the pin group names like this:
- * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* default column */
-static const unsigned sysclkreq2_d_1_pins[] = { AB8500_PIN_T10 };
-static const unsigned sysclkreq3_d_1_pins[] = { AB8500_PIN_T9 };
-static const unsigned sysclkreq4_d_1_pins[] = { AB8500_PIN_U9 };
-static const unsigned sysclkreq6_d_1_pins[] = { AB8500_PIN_W2 };
-static const unsigned ycbcr0123_d_1_pins[] = { AB8500_PIN_Y18, AB8500_PIN_AA20,
-					AB8500_PIN_W18, AB8500_PIN_AA19};
-static const unsigned gpio10_d_1_pins[] = { AB8500_PIN_U17 };
-static const unsigned gpio11_d_1_pins[] = { AB8500_PIN_AA18 };
-static const unsigned gpio12_d_1_pins[] = { AB8500_PIN_U16 };
-static const unsigned gpio13_d_1_pins[] = { AB8500_PIN_W17 };
-static const unsigned pwmout1_d_1_pins[] = { AB8500_PIN_F14 };
-static const unsigned pwmout2_d_1_pins[] = { AB8500_PIN_B17 };
-static const unsigned pwmout3_d_1_pins[] = { AB8500_PIN_F15 };
-
-/* audio data interface 1*/
-static const unsigned adi1_d_1_pins[] = { AB8500_PIN_P5, AB8500_PIN_R5,
-					AB8500_PIN_U5, AB8500_PIN_T5 };
-/* USBUICC */
-static const unsigned usbuicc_d_1_pins[] = { AB8500_PIN_H19, AB8500_PIN_G20,
-					AB8500_PIN_G19 };
-static const unsigned sysclkreq7_d_1_pins[] = { AB8500_PIN_T14 };
-static const unsigned sysclkreq8_d_1_pins[] = { AB8500_PIN_R16 };
-static const unsigned gpio26_d_1_pins[] = { AB8500_PIN_M16 };
-/* Digital microphone 1 and 2 */
-static const unsigned dmic12_d_1_pins[] = { AB8500_PIN_J6, AB8500_PIN_K6 };
-/* Digital microphone 3 and 4 */
-static const unsigned dmic34_d_1_pins[] = { AB8500_PIN_G6, AB8500_PIN_H6 };
-/* Digital microphone 5 and 6 */
-static const unsigned dmic56_d_1_pins[] = { AB8500_PIN_F5, AB8500_PIN_G5 };
-static const unsigned extcpena_d_1_pins[] = { AB8500_PIN_R17 };
-static const unsigned gpio35_d_1_pins[] = { AB8500_PIN_W15 };
-/* APE SPI */
-static const unsigned apespi_d_1_pins[] = { AB8500_PIN_A17, AB8500_PIN_E15,
-					AB8500_PIN_C17, AB8500_PIN_E16};
-/* modem SDA/SCL */
-static const unsigned modsclsda_d_1_pins[] = { AB8500_PIN_T19, AB8500_PIN_U19 };
-static const unsigned sysclkreq5_d_1_pins[] = { AB8500_PIN_U2 };
-
-/* Altfunction A column */
-static const unsigned gpio1_a_1_pins[] = { AB8500_PIN_T10 };
-static const unsigned gpio2_a_1_pins[] = { AB8500_PIN_T9 };
-static const unsigned gpio3_a_1_pins[] = { AB8500_PIN_U9 };
-static const unsigned gpio4_a_1_pins[] = { AB8500_PIN_W2 };
-static const unsigned gpio6_a_1_pins[] = { AB8500_PIN_Y18 };
-static const unsigned gpio7_a_1_pins[] = { AB8500_PIN_AA20 };
-static const unsigned gpio8_a_1_pins[] = { AB8500_PIN_W18 };
-static const unsigned gpio9_a_1_pins[] = { AB8500_PIN_AA19 };
-/* YCbCr4 YCbCr5 YCbCr6 YCbCr7*/
-static const unsigned ycbcr4567_a_1_pins[] = { AB8500_PIN_U17, AB8500_PIN_AA18,
-					AB8500_PIN_U16, AB8500_PIN_W17};
-static const unsigned gpio14_a_1_pins[] = { AB8500_PIN_F14 };
-static const unsigned gpio15_a_1_pins[] = { AB8500_PIN_B17 };
-static const unsigned gpio16_a_1_pins[] = { AB8500_PIN_F15 };
-static const unsigned gpio17_a_1_pins[] = { AB8500_PIN_P5 };
-static const unsigned gpio18_a_1_pins[] = { AB8500_PIN_R5 };
-static const unsigned gpio19_a_1_pins[] = { AB8500_PIN_U5 };
-static const unsigned gpio20_a_1_pins[] = { AB8500_PIN_T5 };
-static const unsigned gpio21_a_1_pins[] = { AB8500_PIN_H19 };
-static const unsigned gpio22_a_1_pins[] = { AB8500_PIN_G20 };
-static const unsigned gpio23_a_1_pins[] = { AB8500_PIN_G19 };
-static const unsigned gpio24_a_1_pins[] = { AB8500_PIN_T14 };
-static const unsigned gpio25_a_1_pins[] = { AB8500_PIN_R16 };
-static const unsigned gpio27_a_1_pins[] = { AB8500_PIN_J6 };
-static const unsigned gpio28_a_1_pins[] = { AB8500_PIN_K6 };
-static const unsigned gpio29_a_1_pins[] = { AB8500_PIN_G6 };
-static const unsigned gpio30_a_1_pins[] = { AB8500_PIN_H6 };
-static const unsigned gpio31_a_1_pins[] = { AB8500_PIN_F5 };
-static const unsigned gpio32_a_1_pins[] = { AB8500_PIN_G5 };
-static const unsigned gpio34_a_1_pins[] = { AB8500_PIN_R17 };
-static const unsigned gpio36_a_1_pins[] = { AB8500_PIN_A17 };
-static const unsigned gpio37_a_1_pins[] = { AB8500_PIN_E15 };
-static const unsigned gpio38_a_1_pins[] = { AB8500_PIN_C17 };
-static const unsigned gpio39_a_1_pins[] = { AB8500_PIN_E16 };
-static const unsigned gpio40_a_1_pins[] = { AB8500_PIN_T19 };
-static const unsigned gpio41_a_1_pins[] = { AB8500_PIN_U19 };
-static const unsigned gpio42_a_1_pins[] = { AB8500_PIN_U2 };
-
-/* Altfunction B colum */
-static const unsigned hiqclkena_b_1_pins[] = { AB8500_PIN_U17 };
-static const unsigned usbuiccpd_b_1_pins[] = { AB8500_PIN_AA18 };
-static const unsigned i2ctrig1_b_1_pins[] = { AB8500_PIN_U16 };
-static const unsigned i2ctrig2_b_1_pins[] = { AB8500_PIN_W17 };
-
-/* Altfunction C column */
-static const unsigned usbvdat_c_1_pins[] = { AB8500_PIN_W17 };
-
-
-#define AB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct abx500_pingroup ab8500_groups[] = {
-	/* default column */
-	AB8500_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(ycbcr0123_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio12_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio26_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(gpio35_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(apespi_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
-	AB8500_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
-	/* Altfunction A column */
-	AB8500_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio6_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio7_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio8_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio9_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(ycbcr4567_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio21_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio22_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio23_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio24_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio25_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio36_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio37_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio38_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio39_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
-	AB8500_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
-	/* Altfunction B column */
-	AB8500_PIN_GROUP(hiqclkena_b_1, ABX500_ALT_B),
-	AB8500_PIN_GROUP(usbuiccpd_b_1, ABX500_ALT_B),
-	AB8500_PIN_GROUP(i2ctrig1_b_1, ABX500_ALT_B),
-	AB8500_PIN_GROUP(i2ctrig2_b_1, ABX500_ALT_B),
-	/* Altfunction C column */
-	AB8500_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define AB8500_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-AB8500_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
-		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1",
-		"sysclkreq7_d_1", "sysclkreq8_d_1");
-AB8500_FUNC_GROUPS(ycbcr, "ycbcr0123_d_1", "ycbcr4567_a_1");
-AB8500_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
-		"gpio6_a_1", "gpio7_a_1", "gpio8_a_1", "gpio9_a_1",
-		"gpio10_d_1", "gpio11_d_1", "gpio12_d_1", "gpio13_d_1",
-		"gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1",
-		"gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio21_a_1",
-		"gpio22_a_1", "gpio23_a_1", "gpio24_a_1", "gpio25_a_1",
-		"gpio26_d_1", "gpio27_a_1", "gpio28_a_1", "gpio29_a_1",
-		"gpio30_a_1", "gpio31_a_1", "gpio32_a_1", "gpio34_a_1",
-		"gpio35_d_1", "gpio36_a_1", "gpio37_a_1", "gpio38_a_1",
-		"gpio39_a_1", "gpio40_a_1", "gpio41_a_1", "gpio42_a_1");
-AB8500_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
-AB8500_FUNC_GROUPS(adi1, "adi1_d_1");
-AB8500_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_b_1");
-AB8500_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
-AB8500_FUNC_GROUPS(extcpena, "extcpena_d_1");
-AB8500_FUNC_GROUPS(apespi, "apespi_d_1");
-AB8500_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
-AB8500_FUNC_GROUPS(hiqclkena, "hiqclkena_b_1");
-AB8500_FUNC_GROUPS(i2ctrig, "i2ctrig1_b_1", "i2ctrig2_b_1");
-AB8500_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct abx500_function ab8500_functions[] = {
-	FUNCTION(sysclkreq),
-	FUNCTION(ycbcr),
-	FUNCTION(gpio),
-	FUNCTION(pwmout),
-	FUNCTION(adi1),
-	FUNCTION(usbuicc),
-	FUNCTION(dmic),
-	FUNCTION(extcpena),
-	FUNCTION(apespi),
-	FUNCTION(modsclsda),
-	FUNCTION(hiqclkena),
-	FUNCTION(i2ctrig),
-	FUNCTION(usbvdat),
-};
-
-/*
- * this table translates what's is in the AB8500 specification regarding the
- * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
- * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
- * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
- *
- * example :
- *
- *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1 ,2),
- *	means that pin AB8500_PIN_W17 (pin 13) supports 4 mux (default/ALT_A,
- *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
- *	select the mux.  ALTA, ALTB and ALTC val indicates values to write in
- *	ALTERNATFUNC register. We need to specifies these values as SOC
- *	designers didn't apply the same logic on how to select mux in the
- *	ABx500 family.
- *
- *	As this pins supports at least ALT_B mux, default mux is
- *	selected by writing 1 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
- *	default	|       1       |          0          |          0
- *	alt_A	|       0       |          0          |          0
- *	alt_B	|       0       |          0          |          1
- *	alt_C	|       0       |          1          |          0
- *
- *	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED),
- *	means that pin AB8500_PIN_W18 (pin 8) supports 2 mux, so only GPIOSEL
- *	register is used to select the mux. As this pins doesn't support at
- *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=7 | alternatfunc bit2=  | alternatfunc bit1=
- *	default	|       0       |          0          |          0
- *	alt_A	|       1       |          0          |          0
- */
-
-static struct
-alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
-	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
-	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
-	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
-	/* bit 4 reserved */
-	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
-	ALTERNATE_FUNCTIONS(6,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO6, altA controlled by bit 5*/
-	ALTERNATE_FUNCTIONS(7,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO7, altA controlled by bit 6*/
-	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO8, altA controlled by bit 7*/
-
-	ALTERNATE_FUNCTIONS(9,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO9, altA controlled by bit 0*/
-	ALTERNATE_FUNCTIONS(10,     1,      0, UNUSED, 0, 1, 0), /* GPIO10, altA and altB controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(11,     2,      1, UNUSED, 0, 1, 0), /* GPIO11, altA and altB controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(12,     3,      2, UNUSED, 0, 1, 0), /* GPIO12, altA and altB controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
-	ALTERNATE_FUNCTIONS(14,     5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(15,     6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(16,     7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
-	/*
-	 * pins 17 to 20 are special case, only bit 0 is used to select
-	 * alternate function for these 4 pins.
-	 * bits 1 to 3 are reserved
-	 */
-	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(21,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(22,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(23,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(24,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */
-
-	ALTERNATE_FUNCTIONS(25,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */
-	/* pin 26 special case, no alternate function, bit 1 reserved */
-	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO26 */
-	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
-
-	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
-	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
-	/* pin 35 special case, no alternate function, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO35 */
-	ALTERNATE_FUNCTIONS(36,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO36, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(37,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO37, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(38,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO38, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(39,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO39, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */
-
-	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
-};
-
-/*
- * Only some GPIOs are interrupt capable, and they are
- * organized in discontiguous clusters:
- *
- *	GPIO6 to GPIO13
- *	GPIO24 and GPIO25
- *	GPIO36 to GPIO41
- */
-static struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
-	GPIO_IRQ_CLUSTER(6,  13, AB8500_INT_GPIO6R),
-	GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
-	GPIO_IRQ_CLUSTER(36, 41, AB8500_INT_GPIO36R),
-};
-
-static struct abx500_pinctrl_soc_data ab8500_soc = {
-	.gpio_ranges = ab8500_pinranges,
-	.gpio_num_ranges = ARRAY_SIZE(ab8500_pinranges),
-	.pins = ab8500_pins,
-	.npins = ARRAY_SIZE(ab8500_pins),
-	.functions = ab8500_functions,
-	.nfunctions = ARRAY_SIZE(ab8500_functions),
-	.groups = ab8500_groups,
-	.ngroups = ARRAY_SIZE(ab8500_groups),
-	.alternate_functions = ab8500_alternate_functions,
-	.gpio_irq_cluster = ab8500_gpio_irq_cluster,
-	.ngpio_irq_cluster = ARRAY_SIZE(ab8500_gpio_irq_cluster),
-	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
-	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
-	.irq_gpio_factor = 1,
-};
-
-void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
-{
-	*soc = &ab8500_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8505.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8505.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8505.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8505.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,381 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include "pinctrl-abx500.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define ABX500_GPIO(offset)	(offset)
-
-#define AB8505_PIN_N4		ABX500_GPIO(1)
-#define AB8505_PIN_R5		ABX500_GPIO(2)
-#define AB8505_PIN_P5		ABX500_GPIO(3)
-/* hole */
-#define AB8505_PIN_B16		ABX500_GPIO(10)
-#define AB8505_PIN_B17		ABX500_GPIO(11)
-/* hole */
-#define AB8505_PIN_D17		ABX500_GPIO(13)
-#define AB8505_PIN_C16		ABX500_GPIO(14)
-/* hole */
-#define AB8505_PIN_P2		ABX500_GPIO(17)
-#define AB8505_PIN_N3		ABX500_GPIO(18)
-#define AB8505_PIN_T1		ABX500_GPIO(19)
-#define AB8505_PIN_P3		ABX500_GPIO(20)
-/* hole */
-#define AB8505_PIN_H14		ABX500_GPIO(34)
-/* hole */
-#define AB8505_PIN_J15		ABX500_GPIO(40)
-#define AB8505_PIN_J14		ABX500_GPIO(41)
-/* hole */
-#define AB8505_PIN_L4		ABX500_GPIO(50)
-/* hole */
-#define AB8505_PIN_D16		ABX500_GPIO(52)
-#define AB8505_PIN_D15		ABX500_GPIO(53)
-
-/* indicates the higher GPIO number */
-#define AB8505_GPIO_MAX_NUMBER	53
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc ab8505_pins[] = {
-	PINCTRL_PIN(AB8505_PIN_N4, "GPIO1_N4"),
-	PINCTRL_PIN(AB8505_PIN_R5, "GPIO2_R5"),
-	PINCTRL_PIN(AB8505_PIN_P5, "GPIO3_P5"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_B16, "GPIO10_B16"),
-	PINCTRL_PIN(AB8505_PIN_B17, "GPIO11_B17"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_D17, "GPIO13_D17"),
-	PINCTRL_PIN(AB8505_PIN_C16, "GPIO14_C16"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_P2, "GPIO17_P2"),
-	PINCTRL_PIN(AB8505_PIN_N3, "GPIO18_N3"),
-	PINCTRL_PIN(AB8505_PIN_T1, "GPIO19_T1"),
-	PINCTRL_PIN(AB8505_PIN_P3, "GPIO20_P3"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_H14, "GPIO34_H14"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_J15, "GPIO40_J15"),
-	PINCTRL_PIN(AB8505_PIN_J14, "GPIO41_J14"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_L4, "GPIO50_L4"),
-/* hole */
-	PINCTRL_PIN(AB8505_PIN_D16, "GPIO52_D16"),
-	PINCTRL_PIN(AB8505_PIN_D15, "GPIO53_D15"),
-};
-
-/*
- * Maps local GPIO offsets to local pin numbers
- */
-static const struct abx500_pinrange ab8505_pinranges[] = {
-	ABX500_PINRANGE(1, 3, ABX500_ALT_A),
-	ABX500_PINRANGE(10, 2, ABX500_DEFAULT),
-	ABX500_PINRANGE(13, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(14, 1, ABX500_ALT_A),
-	ABX500_PINRANGE(17, 4, ABX500_ALT_A),
-	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
-	ABX500_PINRANGE(40, 2, ABX500_ALT_A),
-	ABX500_PINRANGE(50, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(52, 2, ABX500_ALT_A),
-};
-
-/*
- * Read the pin group names like this:
- * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* default column */
-static const unsigned sysclkreq2_d_1_pins[] = { AB8505_PIN_N4 };
-static const unsigned sysclkreq3_d_1_pins[] = { AB8505_PIN_R5 };
-static const unsigned sysclkreq4_d_1_pins[] = { AB8505_PIN_P5 };
-static const unsigned gpio10_d_1_pins[] = { AB8505_PIN_B16 };
-static const unsigned gpio11_d_1_pins[] = { AB8505_PIN_B17 };
-static const unsigned gpio13_d_1_pins[] = { AB8505_PIN_D17 };
-static const unsigned pwmout1_d_1_pins[] = { AB8505_PIN_C16 };
-/* audio data interface 2*/
-static const unsigned adi2_d_1_pins[] = { AB8505_PIN_P2, AB8505_PIN_N3,
-					AB8505_PIN_T1, AB8505_PIN_P3 };
-static const unsigned extcpena_d_1_pins[] = { AB8505_PIN_H14 };
-/* modem SDA/SCL */
-static const unsigned modsclsda_d_1_pins[] = { AB8505_PIN_J15, AB8505_PIN_J14 };
-static const unsigned gpio50_d_1_pins[] = { AB8505_PIN_L4 };
-static const unsigned resethw_d_1_pins[] = { AB8505_PIN_D16 };
-static const unsigned service_d_1_pins[] = { AB8505_PIN_D15 };
-
-/* Altfunction A column */
-static const unsigned gpio1_a_1_pins[] = { AB8505_PIN_N4 };
-static const unsigned gpio2_a_1_pins[] = { AB8505_PIN_R5 };
-static const unsigned gpio3_a_1_pins[] = { AB8505_PIN_P5 };
-static const unsigned hiqclkena_a_1_pins[] = { AB8505_PIN_B16 };
-static const unsigned pdmclk_a_1_pins[] = { AB8505_PIN_B17 };
-static const unsigned uarttxdata_a_1_pins[] = { AB8505_PIN_D17 };
-static const unsigned gpio14_a_1_pins[] = { AB8505_PIN_C16 };
-static const unsigned gpio17_a_1_pins[] = { AB8505_PIN_P2 };
-static const unsigned gpio18_a_1_pins[] = { AB8505_PIN_N3 };
-static const unsigned gpio19_a_1_pins[] = { AB8505_PIN_T1 };
-static const unsigned gpio20_a_1_pins[] = { AB8505_PIN_P3 };
-static const unsigned gpio34_a_1_pins[] = { AB8505_PIN_H14 };
-static const unsigned gpio40_a_1_pins[] = { AB8505_PIN_J15 };
-static const unsigned gpio41_a_1_pins[] = { AB8505_PIN_J14 };
-static const unsigned uartrxdata_a_1_pins[] = { AB8505_PIN_J14 };
-static const unsigned gpio50_a_1_pins[] = { AB8505_PIN_L4 };
-static const unsigned gpio52_a_1_pins[] = { AB8505_PIN_D16 };
-static const unsigned gpio53_a_1_pins[] = { AB8505_PIN_D15 };
-
-/* Altfunction B colum */
-static const unsigned pdmdata_b_1_pins[] = { AB8505_PIN_B16 };
-static const unsigned extvibrapwm1_b_1_pins[] = { AB8505_PIN_D17 };
-static const unsigned extvibrapwm2_b_1_pins[] = { AB8505_PIN_L4 };
-
-/* Altfunction C column */
-static const unsigned usbvdat_c_1_pins[] = { AB8505_PIN_D17 };
-
-#define AB8505_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct abx500_pingroup ab8505_groups[] = {
-	AB8505_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(adi2_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(resethw_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(service_d_1, ABX500_DEFAULT),
-	AB8505_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(uarttxdata_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(uartrxdata_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
-	AB8505_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B),
-	AB8505_PIN_GROUP(extvibrapwm1_b_1, ABX500_ALT_B),
-	AB8505_PIN_GROUP(extvibrapwm2_b_1, ABX500_ALT_B),
-	AB8505_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define AB8505_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-AB8505_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
-		"sysclkreq4_d_1");
-AB8505_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1",
-		"gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1",
-		"gpio17_a_1", "gpio18_a_1", "gpio19_a_1", "gpio20_a_1",
-		"gpio34_a_1", "gpio40_a_1", "gpio41_a_1", "gpio50_d_1",
-		"gpio52_a_1", "gpio53_a_1");
-AB8505_FUNC_GROUPS(pwmout, "pwmout1_d_1");
-AB8505_FUNC_GROUPS(adi2, "adi2_d_1");
-AB8505_FUNC_GROUPS(extcpena, "extcpena_d_1");
-AB8505_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
-AB8505_FUNC_GROUPS(resethw, "resethw_d_1");
-AB8505_FUNC_GROUPS(service, "service_d_1");
-AB8505_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1");
-AB8505_FUNC_GROUPS(pdm, "pdmclk_a_1", "pdmdata_b_1");
-AB8505_FUNC_GROUPS(uartdata, "uarttxdata_a_1", "uartrxdata_a_1");
-AB8505_FUNC_GROUPS(extvibra, "extvibrapwm1_b_1", "extvibrapwm2_b_1");
-AB8505_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct abx500_function ab8505_functions[] = {
-	FUNCTION(sysclkreq),
-	FUNCTION(gpio),
-	FUNCTION(pwmout),
-	FUNCTION(adi2),
-	FUNCTION(extcpena),
-	FUNCTION(modsclsda),
-	FUNCTION(resethw),
-	FUNCTION(service),
-	FUNCTION(hiqclkena),
-	FUNCTION(pdm),
-	FUNCTION(uartdata),
-	FUNCTION(extvibra),
-	FUNCTION(extvibra),
-	FUNCTION(usbvdat),
-};
-
-/*
- * this table translates what's is in the AB8505 specification regarding the
- * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
- * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
- * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
- *
- * example :
- *
- *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 1, 0, 2),
- *	means that pin AB8505_PIN_D18 (pin 13) supports 4 mux (default/ALT_A,
- *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
- *	select the mux. ALTA, ALTB and ALTC val indicates values to write in
- *	ALTERNATFUNC register. We need to specifies these values as SOC
- *	designers didn't apply the same logic on how to select mux in the
- *	ABx500 family.
- *
- *	As this pins supports at least ALT_B mux, default mux is
- *	selected by writing 1 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
- *	default	|       1       |          0          |          0
- *	alt_A	|       0       |          0          |          1
- *	alt_B	|       0       |          0          |          0
- *	alt_C	|       0       |          1          |          0
- *
- *	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED),
- *	means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL
- *	register is used to select the mux. As this pins doesn't support at
- *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=0 | alternatfunc bit2=  | alternatfunc bit1=
- *	default	|       0       |          0          |          0
- *	alt_A	|       1       |          0          |          0
- */
-
-static struct
-alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
-	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
-	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
-	ALTERNATE_FUNCTIONS(4, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO4, bit 3 reserved */
-	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5, bit 4 reserved */
-	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6, bit 5 reserved */
-	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7, bit 6 reserved */
-	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8, bit 7 reserved */
-
-	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */
-	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(11,      2,      1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */
-	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
-	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(15, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 6 reserved */
-	ALTERNATE_FUNCTIONS(16, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 7 reserved  */
-	/*
-	 * pins 17 to 20 are special case, only bit 0 is used to select
-	 * alternate function for these 4 pins.
-	 * bits 1 to 3 are reserved
-	 */
-	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21, bit 4 reserved */
-	ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22, bit 5 reserved */
-	ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23, bit 6 reserved */
-	ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24, bit 7 reserved */
-
-	ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25, bit 0 reserved */
-	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26, bit 1 reserved */
-	ALTERNATE_FUNCTIONS(27, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO27, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(28, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO28, bit 3 reserved */
-	ALTERNATE_FUNCTIONS(29, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO29, bit 4 reserved */
-	ALTERNATE_FUNCTIONS(30, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO30, bit 5 reserved */
-	ALTERNATE_FUNCTIONS(31, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO31, bit 6 reserved */
-	ALTERNATE_FUNCTIONS(32, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO32, bit 7 reserved */
-
-	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33, bit 0 reserved */
-	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7*/
-
-	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(42, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO42, bit 1 reserved */
-	ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43, bit 2 reserved */
-	ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44, bit 3 reserved */
-	ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45, bit 4 reserved */
-	ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46, bit 5 reserved */
-	ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47, bit 6 reserved */
-	ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48, bit 7 reserved */
-
-	ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */
-	ALTERNATE_FUNCTIONS(50,	     1,      2, UNUSED, 1, 0, 0), /* GPIO50, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(51, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */
-	ALTERNATE_FUNCTIONS(52,	     3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(53,	     4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
-};
-
-/*
- * For AB8505 Only some GPIOs are interrupt capable, and they are
- * organized in discontiguous clusters:
- *
- *	GPIO10 to GPIO11
- *	GPIO13
- *	GPIO40 and GPIO41
- *	GPIO50
- *	GPIO52 to GPIO53
- */
-static struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
-	GPIO_IRQ_CLUSTER(10, 11, AB8500_INT_GPIO10R),
-	GPIO_IRQ_CLUSTER(13, 13, AB8500_INT_GPIO13R),
-	GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
-	GPIO_IRQ_CLUSTER(50, 50, AB9540_INT_GPIO50R),
-	GPIO_IRQ_CLUSTER(52, 53, AB9540_INT_GPIO52R),
-};
-
-static struct abx500_pinctrl_soc_data ab8505_soc = {
-	.gpio_ranges = ab8505_pinranges,
-	.gpio_num_ranges = ARRAY_SIZE(ab8505_pinranges),
-	.pins = ab8505_pins,
-	.npins = ARRAY_SIZE(ab8505_pins),
-	.functions = ab8505_functions,
-	.nfunctions = ARRAY_SIZE(ab8505_functions),
-	.groups = ab8505_groups,
-	.ngroups = ARRAY_SIZE(ab8505_groups),
-	.alternate_functions = ab8505_alternate_functions,
-	.gpio_irq_cluster = ab8505_gpio_irq_cluster,
-	.ngpio_irq_cluster = ARRAY_SIZE(ab8505_gpio_irq_cluster),
-	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
-	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
-	.irq_gpio_factor = 1,
-};
-
-void
-abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc)
-{
-	*soc = &ab8505_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab8540.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab8540.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include "pinctrl-abx500.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define ABX500_GPIO(offset)		(offset)
-
-#define AB8540_PIN_J16		ABX500_GPIO(1)
-#define AB8540_PIN_D17		ABX500_GPIO(2)
-#define AB8540_PIN_C12		ABX500_GPIO(3)
-#define AB8540_PIN_G12		ABX500_GPIO(4)
-/* hole */
-#define AB8540_PIN_D16		ABX500_GPIO(14)
-#define AB8540_PIN_F15		ABX500_GPIO(15)
-#define AB8540_PIN_J8		ABX500_GPIO(16)
-#define AB8540_PIN_K16		ABX500_GPIO(17)
-#define AB8540_PIN_G15		ABX500_GPIO(18)
-#define AB8540_PIN_F17		ABX500_GPIO(19)
-#define AB8540_PIN_E17		ABX500_GPIO(20)
-/* hole */
-#define AB8540_PIN_AA16		ABX500_GPIO(27)
-#define AB8540_PIN_W18		ABX500_GPIO(28)
-#define AB8540_PIN_Y15		ABX500_GPIO(29)
-#define AB8540_PIN_W16		ABX500_GPIO(30)
-#define AB8540_PIN_V15		ABX500_GPIO(31)
-#define AB8540_PIN_W17		ABX500_GPIO(32)
-/* hole */
-#define AB8540_PIN_D12		ABX500_GPIO(42)
-#define AB8540_PIN_P4		ABX500_GPIO(43)
-#define AB8540_PIN_AB1		ABX500_GPIO(44)
-#define AB8540_PIN_K7		ABX500_GPIO(45)
-#define AB8540_PIN_L7		ABX500_GPIO(46)
-#define AB8540_PIN_G10		ABX500_GPIO(47)
-#define AB8540_PIN_K12		ABX500_GPIO(48)
-/* hole */
-#define AB8540_PIN_N8		ABX500_GPIO(51)
-#define AB8540_PIN_P12		ABX500_GPIO(52)
-#define AB8540_PIN_K8		ABX500_GPIO(53)
-#define AB8540_PIN_J11		ABX500_GPIO(54)
-#define AB8540_PIN_AC2		ABX500_GPIO(55)
-#define AB8540_PIN_AB2		ABX500_GPIO(56)
-
-/* indicates the highest GPIO number */
-#define AB8540_GPIO_MAX_NUMBER	56
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc ab8540_pins[] = {
-	PINCTRL_PIN(AB8540_PIN_J16, "GPIO1_J16"),
-	PINCTRL_PIN(AB8540_PIN_D17, "GPIO2_D17"),
-	PINCTRL_PIN(AB8540_PIN_C12, "GPIO3_C12"),
-	PINCTRL_PIN(AB8540_PIN_G12, "GPIO4_G12"),
-	/* hole */
-	PINCTRL_PIN(AB8540_PIN_D16, "GPIO14_D16"),
-	PINCTRL_PIN(AB8540_PIN_F15, "GPIO15_F15"),
-	PINCTRL_PIN(AB8540_PIN_J8, "GPIO16_J8"),
-	PINCTRL_PIN(AB8540_PIN_K16, "GPIO17_K16"),
-	PINCTRL_PIN(AB8540_PIN_G15, "GPIO18_G15"),
-	PINCTRL_PIN(AB8540_PIN_F17, "GPIO19_F17"),
-	PINCTRL_PIN(AB8540_PIN_E17, "GPIO20_E17"),
-	/* hole */
-	PINCTRL_PIN(AB8540_PIN_AA16, "GPIO27_AA16"),
-	PINCTRL_PIN(AB8540_PIN_W18, "GPIO28_W18"),
-	PINCTRL_PIN(AB8540_PIN_Y15, "GPIO29_Y15"),
-	PINCTRL_PIN(AB8540_PIN_W16, "GPIO30_W16"),
-	PINCTRL_PIN(AB8540_PIN_V15, "GPIO31_V15"),
-	PINCTRL_PIN(AB8540_PIN_W17, "GPIO32_W17"),
-	/* hole */
-	PINCTRL_PIN(AB8540_PIN_D12, "GPIO42_D12"),
-	PINCTRL_PIN(AB8540_PIN_P4, "GPIO43_P4"),
-	PINCTRL_PIN(AB8540_PIN_AB1, "GPIO44_AB1"),
-	PINCTRL_PIN(AB8540_PIN_K7, "GPIO45_K7"),
-	PINCTRL_PIN(AB8540_PIN_L7, "GPIO46_L7"),
-	PINCTRL_PIN(AB8540_PIN_G10, "GPIO47_G10"),
-	PINCTRL_PIN(AB8540_PIN_K12, "GPIO48_K12"),
-	/* hole */
-	PINCTRL_PIN(AB8540_PIN_N8, "GPIO51_N8"),
-	PINCTRL_PIN(AB8540_PIN_P12, "GPIO52_P12"),
-	PINCTRL_PIN(AB8540_PIN_K8, "GPIO53_K8"),
-	PINCTRL_PIN(AB8540_PIN_J11, "GPIO54_J11"),
-	PINCTRL_PIN(AB8540_PIN_AC2, "GPIO55_AC2"),
-	PINCTRL_PIN(AB8540_PIN_AB2, "GPIO56_AB2"),
-};
-
-/*
- * Maps local GPIO offsets to local pin numbers
- */
-static const struct abx500_pinrange ab8540_pinranges[] = {
-	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
-	ABX500_PINRANGE(14, 7, ABX500_ALT_A),
-	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
-	ABX500_PINRANGE(42, 7, ABX500_ALT_A),
-	ABX500_PINRANGE(51, 6, ABX500_ALT_A),
-};
-
-/*
- * Read the pin group names like this:
- * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* default column */
-static const unsigned sysclkreq2_d_1_pins[] = { AB8540_PIN_J16 };
-static const unsigned sysclkreq3_d_1_pins[] = { AB8540_PIN_D17 };
-static const unsigned sysclkreq4_d_1_pins[] = { AB8540_PIN_C12 };
-static const unsigned sysclkreq6_d_1_pins[] = { AB8540_PIN_G12 };
-static const unsigned pwmout1_d_1_pins[] = { AB8540_PIN_D16 };
-static const unsigned pwmout2_d_1_pins[] = { AB8540_PIN_F15 };
-static const unsigned pwmout3_d_1_pins[] = { AB8540_PIN_J8 };
-
-/* audio data interface 1*/
-static const unsigned adi1_d_1_pins[] = { AB8540_PIN_K16, AB8540_PIN_G15,
-					AB8540_PIN_F17, AB8540_PIN_E17 };
-/* Digital microphone 1 and 2 */
-static const unsigned dmic12_d_1_pins[] = { AB8540_PIN_AA16, AB8540_PIN_W18 };
-/* Digital microphone 3 and 4 */
-static const unsigned dmic34_d_1_pins[] = { AB8540_PIN_Y15, AB8540_PIN_W16 };
-/* Digital microphone 5 and 6 */
-static const unsigned dmic56_d_1_pins[] = { AB8540_PIN_V15, AB8540_PIN_W17 };
-static const unsigned sysclkreq5_d_1_pins[] = { AB8540_PIN_D12 };
-static const unsigned batremn_d_1_pins[] = { AB8540_PIN_P4 };
-static const unsigned service_d_1_pins[] = { AB8540_PIN_AB1 };
-static const unsigned pwrctrl0_d_1_pins[] = { AB8540_PIN_K7 };
-static const unsigned pwrctrl1_d_1_pins[] = { AB8540_PIN_L7 };
-static const unsigned pwmextvibra1_d_1_pins[] = { AB8540_PIN_G10 };
-static const unsigned pwmextvibra2_d_1_pins[] = { AB8540_PIN_K12 };
-static const unsigned gpio1_vbat_d_1_pins[] = { AB8540_PIN_N8 };
-static const unsigned gpio2_vbat_d_1_pins[] = { AB8540_PIN_P12 };
-static const unsigned gpio3_vbat_d_1_pins[] = { AB8540_PIN_K8 };
-static const unsigned gpio4_vbat_d_1_pins[] = { AB8540_PIN_J11 };
-static const unsigned pdmclkdat_d_1_pins[] = { AB8540_PIN_AC2, AB8540_PIN_AB2 };
-
-/* Altfunction A column */
-static const unsigned gpio1_a_1_pins[] = { AB8540_PIN_J16 };
-static const unsigned gpio2_a_1_pins[] = { AB8540_PIN_D17 };
-static const unsigned gpio3_a_1_pins[] = { AB8540_PIN_C12 };
-static const unsigned gpio4_a_1_pins[] = { AB8540_PIN_G12 };
-static const unsigned gpio14_a_1_pins[] = { AB8540_PIN_D16 };
-static const unsigned gpio15_a_1_pins[] = { AB8540_PIN_F15 };
-static const unsigned gpio16_a_1_pins[] = { AB8540_PIN_J8 };
-static const unsigned gpio17_a_1_pins[] = { AB8540_PIN_K16 };
-static const unsigned gpio18_a_1_pins[] = { AB8540_PIN_G15 };
-static const unsigned gpio19_a_1_pins[] = { AB8540_PIN_F17 };
-static const unsigned gpio20_a_1_pins[] = { AB8540_PIN_E17 };
-static const unsigned gpio27_a_1_pins[] = { AB8540_PIN_AA16 };
-static const unsigned gpio28_a_1_pins[] = { AB8540_PIN_W18 };
-static const unsigned gpio29_a_1_pins[] = { AB8540_PIN_Y15 };
-static const unsigned gpio30_a_1_pins[] = { AB8540_PIN_W16 };
-static const unsigned gpio31_a_1_pins[] = { AB8540_PIN_V15 };
-static const unsigned gpio32_a_1_pins[] = { AB8540_PIN_W17 };
-static const unsigned gpio42_a_1_pins[] = { AB8540_PIN_D12 };
-static const unsigned gpio43_a_1_pins[] = { AB8540_PIN_P4 };
-static const unsigned gpio44_a_1_pins[] = { AB8540_PIN_AB1 };
-static const unsigned gpio45_a_1_pins[] = { AB8540_PIN_K7 };
-static const unsigned gpio46_a_1_pins[] = { AB8540_PIN_L7 };
-static const unsigned gpio47_a_1_pins[] = { AB8540_PIN_G10 };
-static const unsigned gpio48_a_1_pins[] = { AB8540_PIN_K12 };
-static const unsigned gpio51_a_1_pins[] = { AB8540_PIN_N8 };
-static const unsigned gpio52_a_1_pins[] = { AB8540_PIN_P12 };
-static const unsigned gpio53_a_1_pins[] = { AB8540_PIN_K8 };
-static const unsigned gpio54_a_1_pins[] = { AB8540_PIN_J11 };
-static const unsigned gpio55_a_1_pins[] = { AB8540_PIN_AC2 };
-static const unsigned gpio56_a_1_pins[] = { AB8540_PIN_AB2 };
-
-#define AB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct abx500_pingroup ab8540_groups[] = {
-	/* default column */
-	AB8540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(service_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwrctrl0_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwrctrl1_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwmextvibra1_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pwmextvibra2_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(gpio1_vbat_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(gpio2_vbat_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(gpio3_vbat_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(gpio4_vbat_d_1, ABX500_DEFAULT),
-	AB8540_PIN_GROUP(pdmclkdat_d_1, ABX500_DEFAULT),
-	/* Altfunction A column */
-	AB8540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio43_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio44_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio45_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio46_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio47_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio48_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio54_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio55_a_1, ABX500_ALT_A),
-	AB8540_PIN_GROUP(gpio56_a_1, ABX500_ALT_A),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define AB8540_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-AB8540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
-		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1");
-AB8540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
-		"gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1",
-		"gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio27_a_1",
-		"gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1",
-		"gpio32_a_1", "gpio42_a_1", "gpio43_a_1", "gpio44_a_1",
-		"gpio45_a_1", "gpio46_a_1", "gpio47_a_1", "gpio48_a_1",
-		"gpio51_a_1", "gpio52_a_1", "gpio53_a_1", "gpio54_a_1",
-		"gpio55_a_1", "gpio56_a_1");
-AB8540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
-AB8540_FUNC_GROUPS(adi1, "adi1_d_1");
-AB8540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
-AB8540_FUNC_GROUPS(batremn, "batremn_d_1");
-AB8540_FUNC_GROUPS(service, "service_d_1");
-AB8540_FUNC_GROUPS(pwrctrl, "pwrctrl0_d_1", "pwrctrl1_d_1");
-AB8540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_d_1", "pwmextvibra2_d_1");
-AB8540_FUNC_GROUPS(gpio_vbat, "gpio1_vbat_d_1", "gpio2_vbat_d_1",
-		"gpio3_vbat_d_1", "gpio4_vbat_d_1");
-AB8540_FUNC_GROUPS(pdm, "pdmclkdat_d_1");
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct abx500_function ab8540_functions[] = {
-	FUNCTION(sysclkreq),
-	FUNCTION(gpio),
-	FUNCTION(pwmout),
-	FUNCTION(adi1),
-	FUNCTION(dmic),
-	FUNCTION(batremn),
-	FUNCTION(service),
-	FUNCTION(pwrctrl),
-	FUNCTION(pwmextvibra),
-	FUNCTION(gpio_vbat),
-	FUNCTION(pdm),
-};
-
-/*
- * this table translates what's is in the AB8540 specification regarding the
- * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
- * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
- * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
- * AB8540 only supports DEFAULT and ALTA functions, so ALTERNATFUNC
- * registers is not used
- *
- */
-
-static struct
-alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
-	/* GPIOSEL1 - bit 4-7 reserved */
-	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
-	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
-	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
-	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
-	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */
-	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */
-	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */
-	/* GPIOSEL2 - bit 0-4 reserved */
-	ALTERNATE_FUNCTIONS(9,  UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
-	ALTERNATE_FUNCTIONS(10, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO10 */
-	ALTERNATE_FUNCTIONS(11, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO11 */
-	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
-	ALTERNATE_FUNCTIONS(13, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO13 */
-	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(15,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(16,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
-	/* GPIOSEL3 - bit 4-7 reserved */
-	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(18,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(19,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(20,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21 */
-	ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22 */
-	ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23 */
-	ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24 */
-	/* GPIOSEL4 - bit 0-1 reserved */
-	ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25 */
-	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */
-	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
-	/* GPIOSEL5 - bit 0-7 reserved */
-	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
-	ALTERNATE_FUNCTIONS(34, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO34 */
-	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */
-	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */
-	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */
-	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */
-	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */
-	ALTERNATE_FUNCTIONS(40, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO40 */
-	/* GPIOSEL6 - bit 0 reserved */
-	ALTERNATE_FUNCTIONS(41, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO41 */
-	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(43,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO43, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(44,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO44, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(45,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO45, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(46,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO46, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(47,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO47, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(48,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO48, altA controlled by bit 7 */
-	/* GPIOSEL7 - bit 0-1 reserved */
-	ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */
-	ALTERNATE_FUNCTIONS(50, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO50 */
-	ALTERNATE_FUNCTIONS(51,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(52,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(53,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(54,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(55,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO55, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(56,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO56, altA controlled by bit 7 */
-};
-
-static struct pullud ab8540_pullud = {
-	.first_pin = 51,	/* GPIO1_VBAT */
-	.last_pin = 54,		/* GPIO4_VBAT */
-};
-
-/*
- * For AB8540 Only some GPIOs are interrupt capable:
- *	GPIO43 to GPIO44
- *	GPIO51 to GPIO54
- */
-static struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
-	GPIO_IRQ_CLUSTER(43, 43, AB8540_INT_GPIO43F),
-	GPIO_IRQ_CLUSTER(44, 44, AB8540_INT_GPIO44F),
-	GPIO_IRQ_CLUSTER(51, 54, AB9540_INT_GPIO51R),
-};
-
-static struct abx500_pinctrl_soc_data ab8540_soc = {
-	.gpio_ranges = ab8540_pinranges,
-	.gpio_num_ranges = ARRAY_SIZE(ab8540_pinranges),
-	.pins = ab8540_pins,
-	.npins = ARRAY_SIZE(ab8540_pins),
-	.functions = ab8540_functions,
-	.nfunctions = ARRAY_SIZE(ab8540_functions),
-	.groups = ab8540_groups,
-	.ngroups = ARRAY_SIZE(ab8540_groups),
-	.alternate_functions = ab8540_alternate_functions,
-	.pullud = &ab8540_pullud,
-	.gpio_irq_cluster = ab8540_gpio_irq_cluster,
-	.ngpio_irq_cluster = ARRAY_SIZE(ab8540_gpio_irq_cluster),
-	.irq_gpio_rising_offset = AB8540_INT_GPIO43R,
-	.irq_gpio_falling_offset = AB8540_INT_GPIO43F,
-	.irq_gpio_factor = 2,
-};
-
-void
-abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc)
-{
-	*soc = &ab8540_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab9540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab9540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ab9540.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ab9540.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,486 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include "pinctrl-abx500.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define ABX500_GPIO(offset)		(offset)
-
-#define AB9540_PIN_R4		ABX500_GPIO(1)
-#define AB9540_PIN_V3		ABX500_GPIO(2)
-#define AB9540_PIN_T4		ABX500_GPIO(3)
-#define AB9540_PIN_T5		ABX500_GPIO(4)
-/* hole */
-#define AB9540_PIN_B18		ABX500_GPIO(10)
-#define AB9540_PIN_C18		ABX500_GPIO(11)
-/* hole */
-#define AB9540_PIN_D18		ABX500_GPIO(13)
-#define AB9540_PIN_B19		ABX500_GPIO(14)
-#define AB9540_PIN_C19		ABX500_GPIO(15)
-#define AB9540_PIN_D19		ABX500_GPIO(16)
-#define AB9540_PIN_R3		ABX500_GPIO(17)
-#define AB9540_PIN_T2		ABX500_GPIO(18)
-#define AB9540_PIN_U2		ABX500_GPIO(19)
-#define AB9540_PIN_V2		ABX500_GPIO(20)
-#define AB9540_PIN_N17		ABX500_GPIO(21)
-#define AB9540_PIN_N16		ABX500_GPIO(22)
-#define AB9540_PIN_M19		ABX500_GPIO(23)
-#define AB9540_PIN_T3		ABX500_GPIO(24)
-#define AB9540_PIN_W2		ABX500_GPIO(25)
-/* hole */
-#define AB9540_PIN_H4		ABX500_GPIO(27)
-#define AB9540_PIN_F1		ABX500_GPIO(28)
-#define AB9540_PIN_F4		ABX500_GPIO(29)
-#define AB9540_PIN_F2		ABX500_GPIO(30)
-#define AB9540_PIN_E4		ABX500_GPIO(31)
-#define AB9540_PIN_F3		ABX500_GPIO(32)
-/* hole */
-#define AB9540_PIN_J13		ABX500_GPIO(34)
-/* hole */
-#define AB9540_PIN_L17		ABX500_GPIO(40)
-#define AB9540_PIN_L16		ABX500_GPIO(41)
-#define AB9540_PIN_W3		ABX500_GPIO(42)
-#define AB9540_PIN_N4		ABX500_GPIO(50)
-#define AB9540_PIN_G12		ABX500_GPIO(51)
-#define AB9540_PIN_E17		ABX500_GPIO(52)
-#define AB9540_PIN_D11		ABX500_GPIO(53)
-#define AB9540_PIN_M18		ABX500_GPIO(54)
-
-/* indicates the highest GPIO number */
-#define AB9540_GPIO_MAX_NUMBER	54
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc ab9540_pins[] = {
-	PINCTRL_PIN(AB9540_PIN_R4, "GPIO1_R4"),
-	PINCTRL_PIN(AB9540_PIN_V3, "GPIO2_V3"),
-	PINCTRL_PIN(AB9540_PIN_T4, "GPIO3_T4"),
-	PINCTRL_PIN(AB9540_PIN_T5, "GPIO4_T5"),
-	/* hole */
-	PINCTRL_PIN(AB9540_PIN_B18, "GPIO10_B18"),
-	PINCTRL_PIN(AB9540_PIN_C18, "GPIO11_C18"),
-	/* hole */
-	PINCTRL_PIN(AB9540_PIN_D18, "GPIO13_D18"),
-	PINCTRL_PIN(AB9540_PIN_B19, "GPIO14_B19"),
-	PINCTRL_PIN(AB9540_PIN_C19, "GPIO15_C19"),
-	PINCTRL_PIN(AB9540_PIN_D19, "GPIO16_D19"),
-	PINCTRL_PIN(AB9540_PIN_R3, "GPIO17_R3"),
-	PINCTRL_PIN(AB9540_PIN_T2, "GPIO18_T2"),
-	PINCTRL_PIN(AB9540_PIN_U2, "GPIO19_U2"),
-	PINCTRL_PIN(AB9540_PIN_V2, "GPIO20_V2"),
-	PINCTRL_PIN(AB9540_PIN_N17, "GPIO21_N17"),
-	PINCTRL_PIN(AB9540_PIN_N16, "GPIO22_N16"),
-	PINCTRL_PIN(AB9540_PIN_M19, "GPIO23_M19"),
-	PINCTRL_PIN(AB9540_PIN_T3, "GPIO24_T3"),
-	PINCTRL_PIN(AB9540_PIN_W2, "GPIO25_W2"),
-	/* hole */
-	PINCTRL_PIN(AB9540_PIN_H4, "GPIO27_H4"),
-	PINCTRL_PIN(AB9540_PIN_F1, "GPIO28_F1"),
-	PINCTRL_PIN(AB9540_PIN_F4, "GPIO29_F4"),
-	PINCTRL_PIN(AB9540_PIN_F2, "GPIO30_F2"),
-	PINCTRL_PIN(AB9540_PIN_E4, "GPIO31_E4"),
-	PINCTRL_PIN(AB9540_PIN_F3, "GPIO32_F3"),
-	/* hole */
-	PINCTRL_PIN(AB9540_PIN_J13, "GPIO34_J13"),
-	/* hole */
-	PINCTRL_PIN(AB9540_PIN_L17, "GPIO40_L17"),
-	PINCTRL_PIN(AB9540_PIN_L16, "GPIO41_L16"),
-	PINCTRL_PIN(AB9540_PIN_W3, "GPIO42_W3"),
-	PINCTRL_PIN(AB9540_PIN_N4, "GPIO50_N4"),
-	PINCTRL_PIN(AB9540_PIN_G12, "GPIO51_G12"),
-	PINCTRL_PIN(AB9540_PIN_E17, "GPIO52_E17"),
-	PINCTRL_PIN(AB9540_PIN_D11, "GPIO53_D11"),
-	PINCTRL_PIN(AB9540_PIN_M18, "GPIO60_M18"),
-};
-
-/*
- * Maps local GPIO offsets to local pin numbers
- */
-static const struct abx500_pinrange ab9540_pinranges[] = {
-	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
-	ABX500_PINRANGE(10, 2, ABX500_DEFAULT),
-	ABX500_PINRANGE(13, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(14, 12, ABX500_ALT_A),
-	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
-	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
-	ABX500_PINRANGE(40, 3, ABX500_ALT_A),
-	ABX500_PINRANGE(50, 1, ABX500_DEFAULT),
-	ABX500_PINRANGE(51, 3, ABX500_ALT_A),
-	ABX500_PINRANGE(54, 1, ABX500_DEFAULT),
-};
-
-/*
- * Read the pin group names like this:
- * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* default column */
-static const unsigned sysclkreq2_d_1_pins[] = { AB9540_PIN_R4 };
-static const unsigned sysclkreq3_d_1_pins[] = { AB9540_PIN_V3 };
-static const unsigned sysclkreq4_d_1_pins[] = { AB9540_PIN_T4 };
-static const unsigned sysclkreq6_d_1_pins[] = { AB9540_PIN_T5 };
-static const unsigned gpio10_d_1_pins[] = { AB9540_PIN_B18 };
-static const unsigned gpio11_d_1_pins[] = { AB9540_PIN_C18 };
-static const unsigned gpio13_d_1_pins[] = { AB9540_PIN_D18 };
-static const unsigned pwmout1_d_1_pins[] = { AB9540_PIN_B19 };
-static const unsigned pwmout2_d_1_pins[] = { AB9540_PIN_C19 };
-static const unsigned pwmout3_d_1_pins[] = { AB9540_PIN_D19 };
-/* audio data interface 1*/
-static const unsigned adi1_d_1_pins[] = { AB9540_PIN_R3, AB9540_PIN_T2,
-					AB9540_PIN_U2, AB9540_PIN_V2 };
-/* USBUICC */
-static const unsigned usbuicc_d_1_pins[] = { AB9540_PIN_N17, AB9540_PIN_N16,
-					AB9540_PIN_M19 };
-static const unsigned sysclkreq7_d_1_pins[] = { AB9540_PIN_T3 };
-static const unsigned sysclkreq8_d_1_pins[] = { AB9540_PIN_W2 };
-/* Digital microphone 1 and 2 */
-static const unsigned dmic12_d_1_pins[] = { AB9540_PIN_H4, AB9540_PIN_F1 };
-/* Digital microphone 3 and 4 */
-static const unsigned dmic34_d_1_pins[] = { AB9540_PIN_F4, AB9540_PIN_F2 };
-/* Digital microphone 5 and 6 */
-static const unsigned dmic56_d_1_pins[] = { AB9540_PIN_E4, AB9540_PIN_F3 };
-static const unsigned extcpena_d_1_pins[] = { AB9540_PIN_J13 };
-/* modem SDA/SCL */
-static const unsigned modsclsda_d_1_pins[] = { AB9540_PIN_L17, AB9540_PIN_L16 };
-static const unsigned sysclkreq5_d_1_pins[] = { AB9540_PIN_W3 };
-static const unsigned gpio50_d_1_pins[] = { AB9540_PIN_N4 };
-static const unsigned batremn_d_1_pins[] = { AB9540_PIN_G12 };
-static const unsigned resethw_d_1_pins[] = { AB9540_PIN_E17 };
-static const unsigned service_d_1_pins[] = { AB9540_PIN_D11 };
-static const unsigned gpio60_d_1_pins[] = { AB9540_PIN_M18 };
-
-/* Altfunction A column */
-static const unsigned gpio1_a_1_pins[] = { AB9540_PIN_R4 };
-static const unsigned gpio2_a_1_pins[] = { AB9540_PIN_V3 };
-static const unsigned gpio3_a_1_pins[] = { AB9540_PIN_T4 };
-static const unsigned gpio4_a_1_pins[] = { AB9540_PIN_T5 };
-static const unsigned hiqclkena_a_1_pins[] = { AB9540_PIN_B18 };
-static const unsigned pdmclk_a_1_pins[] = { AB9540_PIN_C18 };
-static const unsigned uartdata_a_1_pins[] = { AB9540_PIN_D18, AB9540_PIN_N4 };
-static const unsigned gpio14_a_1_pins[] = { AB9540_PIN_B19 };
-static const unsigned gpio15_a_1_pins[] = { AB9540_PIN_C19 };
-static const unsigned gpio16_a_1_pins[] = { AB9540_PIN_D19 };
-static const unsigned gpio17_a_1_pins[] = { AB9540_PIN_R3 };
-static const unsigned gpio18_a_1_pins[] = { AB9540_PIN_T2 };
-static const unsigned gpio19_a_1_pins[] = { AB9540_PIN_U2 };
-static const unsigned gpio20_a_1_pins[] = { AB9540_PIN_V2 };
-static const unsigned gpio21_a_1_pins[] = { AB9540_PIN_N17 };
-static const unsigned gpio22_a_1_pins[] = { AB9540_PIN_N16 };
-static const unsigned gpio23_a_1_pins[] = { AB9540_PIN_M19 };
-static const unsigned gpio24_a_1_pins[] = { AB9540_PIN_T3 };
-static const unsigned gpio25_a_1_pins[] = { AB9540_PIN_W2 };
-static const unsigned gpio27_a_1_pins[] = { AB9540_PIN_H4 };
-static const unsigned gpio28_a_1_pins[] = { AB9540_PIN_F1 };
-static const unsigned gpio29_a_1_pins[] = { AB9540_PIN_F4 };
-static const unsigned gpio30_a_1_pins[] = { AB9540_PIN_F2 };
-static const unsigned gpio31_a_1_pins[] = { AB9540_PIN_E4 };
-static const unsigned gpio32_a_1_pins[] = { AB9540_PIN_F3 };
-static const unsigned gpio34_a_1_pins[] = { AB9540_PIN_J13 };
-static const unsigned gpio40_a_1_pins[] = { AB9540_PIN_L17 };
-static const unsigned gpio41_a_1_pins[] = { AB9540_PIN_L16 };
-static const unsigned gpio42_a_1_pins[] = { AB9540_PIN_W3 };
-static const unsigned gpio51_a_1_pins[] = { AB9540_PIN_G12 };
-static const unsigned gpio52_a_1_pins[] = { AB9540_PIN_E17 };
-static const unsigned gpio53_a_1_pins[] = { AB9540_PIN_D11 };
-static const unsigned usbuiccpd_a_1_pins[] = { AB9540_PIN_M18 };
-
-/* Altfunction B colum */
-static const unsigned pdmdata_b_1_pins[] = { AB9540_PIN_B18 };
-static const unsigned pwmextvibra1_b_1_pins[] = { AB9540_PIN_D18 };
-static const unsigned pwmextvibra2_b_1_pins[] = { AB9540_PIN_N4 };
-
-/* Altfunction C column */
-static const unsigned usbvdat_c_1_pins[] = { AB9540_PIN_D18 };
-
-#define AB9540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct abx500_pingroup ab9540_groups[] = {
-	/* default column */
-	AB9540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(resethw_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(service_d_1, ABX500_DEFAULT),
-	AB9540_PIN_GROUP(gpio60_d_1, ABX500_DEFAULT),
-
-	/* Altfunction A column */
-	AB9540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(uartdata_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio21_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio22_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio23_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio24_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio25_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A),
-	AB9540_PIN_GROUP(usbuiccpd_a_1, ABX500_ALT_A),
-
-	/* Altfunction B column */
-	AB9540_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B),
-	AB9540_PIN_GROUP(pwmextvibra1_b_1, ABX500_ALT_B),
-	AB9540_PIN_GROUP(pwmextvibra2_b_1, ABX500_ALT_B),
-
-	/* Altfunction C column */
-	AB9540_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define AB9540_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-AB9540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
-		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1",
-		"sysclkreq7_d_1", "sysclkreq8_d_1");
-AB9540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
-		"gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1",
-		"gpio15_a_1", "gpio16_a_1", "gpio17_a_1", "gpio18_a_1",
-		"gpio19_a_1", "gpio20_a_1", "gpio21_a_1", "gpio22_a_1",
-		"gpio23_a_1", "gpio24_a_1", "gpio25_a_1", "gpio27_a_1",
-		"gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1",
-		"gpio32_a_1", "gpio34_a_1", "gpio40_a_1", "gpio41_a_1",
-		"gpio42_a_1", "gpio50_d_1", "gpio51_a_1", "gpio52_a_1",
-		"gpio53_a_1", "gpio60_d_1");
-AB9540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
-AB9540_FUNC_GROUPS(adi1, "adi1_d_1");
-AB9540_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_a_1");
-AB9540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
-AB9540_FUNC_GROUPS(extcpena, "extcpena_d_1");
-AB9540_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
-AB9540_FUNC_GROUPS(batremn, "batremn_d_1");
-AB9540_FUNC_GROUPS(resethw, "resethw_d_1");
-AB9540_FUNC_GROUPS(service, "service_d_1");
-AB9540_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1");
-AB9540_FUNC_GROUPS(pdm, "pdmdata_b_1", "pdmclk_a_1");
-AB9540_FUNC_GROUPS(uartdata, "uartdata_a_1");
-AB9540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_b_1", "pwmextvibra2_b_1");
-AB9540_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct abx500_function ab9540_functions[] = {
-	FUNCTION(sysclkreq),
-	FUNCTION(gpio),
-	FUNCTION(pwmout),
-	FUNCTION(adi1),
-	FUNCTION(usbuicc),
-	FUNCTION(dmic),
-	FUNCTION(extcpena),
-	FUNCTION(modsclsda),
-	FUNCTION(batremn),
-	FUNCTION(resethw),
-	FUNCTION(service),
-	FUNCTION(hiqclkena),
-	FUNCTION(pdm),
-	FUNCTION(uartdata),
-	FUNCTION(pwmextvibra),
-	FUNCTION(usbvdat),
-};
-
-/*
- * this table translates what's is in the AB9540 specification regarding the
- * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
- * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
- * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
- *
- * example :
- *
- *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 1, 0, 2),
- *	means that pin AB9540_PIN_D18 (pin 13) supports 4 mux (default/ALT_A,
- *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
- *	select the mux. ALTA, ALTB and ALTC val indicates values to write in
- *	ALTERNATFUNC register. We need to specifies these values as SOC
- *	designers didn't apply the same logic on how to select mux in the
- *	ABx500 family.
- *
- *	As this pins supports at least ALT_B mux, default mux is
- *	selected by writing 1 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
- *	default	|       1       |          0          |          0
- *	alt_A	|       0       |          0          |          1
- *	alt_B	|       0       |          0          |          0
- *	alt_C	|       0       |          1          |          0
- *
- *	ALTERNATE_FUNCTIONS(1,      0, UNUSED, UNUSED),
- *	means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL
- *	register is used to select the mux. As this pins doesn't support at
- *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
- *
- *		| GPIOSEL bit=0 | alternatfunc bit2=  | alternatfunc bit1=
- *	default	|       0       |          0          |          0
- *	alt_A	|       1       |          0          |          0
- */
-
-static struct
-alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
-	/* GPIOSEL1 - bits 4-7 are reserved */
-	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
-	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
-	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
-	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
-	ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */
-	ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */
-	ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */
-	/* GPIOSEL2 - bits 0 and 3 are reserved */
-	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
-	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(11,      2,	     1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
-	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
-	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(15,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(16,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
-	/* GPIOSEL3 - bit 1-3 reserved
-	 * pins 17 to 20 are special case, only bit 0 is used to select
-	 * alternate function for these 4 pins.
-	 * bits 1 to 3 are reserved
-	 */
-	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(21,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(22,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(23,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(24,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */
-	/* GPIOSEL4 - bit 1 reserved */
-	ALTERNATE_FUNCTIONS(25,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */
-	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
-	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
-	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
-	/* GPIOSEL5 - bit 0, 2-6 are reserved */
-	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
-	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */
-	ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */
-	ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */
-	ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */
-	ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */
-	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */
-	/* GPIOSEL6 - bit 2-7 are reserved */
-	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43 */
-	ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44 */
-	ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45 */
-	ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46 */
-	ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47 */
-	ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48 */
-	/*
-	 * GPIOSEL7 - bit 0 and 6-7 are reserved
-	 * special case with GPIO60, wich is located at offset 5 of gpiosel7
-	 * don't know why it has been called GPIO60 in AB9540 datasheet,
-	 * GPIO54 would be logical..., so at SOC point of view we consider
-	 * GPIO60 = GPIO54
-	 */
-	ALTERNATE_FUNCTIONS(49,      0, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */
-	ALTERNATE_FUNCTIONS(50,      1,	     2, UNUSED, 1, 0, 0), /* GPIO50, altA and altB controlled by bit 1 */
-	ALTERNATE_FUNCTIONS(51,	     2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */
-	ALTERNATE_FUNCTIONS(52,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */
-	ALTERNATE_FUNCTIONS(53,	     4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */
-	ALTERNATE_FUNCTIONS(54,	     5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54 = GPIO60, altA controlled by bit 5 */
-};
-
-static struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
-	GPIO_IRQ_CLUSTER(10, 13, AB8500_INT_GPIO10R),
-	GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
-	GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
-	GPIO_IRQ_CLUSTER(50, 54, AB9540_INT_GPIO50R),
-};
-
-static struct abx500_pinctrl_soc_data ab9540_soc = {
-	.gpio_ranges = ab9540_pinranges,
-	.gpio_num_ranges = ARRAY_SIZE(ab9540_pinranges),
-	.pins = ab9540_pins,
-	.npins = ARRAY_SIZE(ab9540_pins),
-	.functions = ab9540_functions,
-	.nfunctions = ARRAY_SIZE(ab9540_functions),
-	.groups = ab9540_groups,
-	.ngroups = ARRAY_SIZE(ab9540_groups),
-	.alternate_functions = ab9540alternate_functions,
-	.gpio_irq_cluster = ab9540_gpio_irq_cluster,
-	.ngpio_irq_cluster = ARRAY_SIZE(ab9540_gpio_irq_cluster),
-	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
-	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
-	.irq_gpio_factor = 1,
-};
-
-void
-abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc)
-{
-	*soc = &ab9540_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-abx500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-abx500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-abx500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-abx500.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1361 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2013
- *
- * Author: Patrice Chotard <patrice.chotard@st.com>
- * License terms: GNU General Public License (GPL) version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/pinctrl/machine.h>
-
-#include "pinctrl-abx500.h"
-#include "core.h"
-#include "pinconf.h"
-
-/*
- * The AB9540 and AB8540 GPIO support are extended versions
- * of the AB8500 GPIO support.
- * The AB9540 supports an additional (7th) register so that
- * more GPIO may be configured and used.
- * The AB8540 supports 4 new gpios (GPIOx_VBAT) that have
- * internal pull-up and pull-down capabilities.
- */
-
-/*
- * GPIO registers offset
- * Bank: 0x10
- */
-#define AB8500_GPIO_SEL1_REG	0x00
-#define AB8500_GPIO_SEL2_REG	0x01
-#define AB8500_GPIO_SEL3_REG	0x02
-#define AB8500_GPIO_SEL4_REG	0x03
-#define AB8500_GPIO_SEL5_REG	0x04
-#define AB8500_GPIO_SEL6_REG	0x05
-#define AB9540_GPIO_SEL7_REG	0x06
-
-#define AB8500_GPIO_DIR1_REG	0x10
-#define AB8500_GPIO_DIR2_REG	0x11
-#define AB8500_GPIO_DIR3_REG	0x12
-#define AB8500_GPIO_DIR4_REG	0x13
-#define AB8500_GPIO_DIR5_REG	0x14
-#define AB8500_GPIO_DIR6_REG	0x15
-#define AB9540_GPIO_DIR7_REG	0x16
-
-#define AB8500_GPIO_OUT1_REG	0x20
-#define AB8500_GPIO_OUT2_REG	0x21
-#define AB8500_GPIO_OUT3_REG	0x22
-#define AB8500_GPIO_OUT4_REG	0x23
-#define AB8500_GPIO_OUT5_REG	0x24
-#define AB8500_GPIO_OUT6_REG	0x25
-#define AB9540_GPIO_OUT7_REG	0x26
-
-#define AB8500_GPIO_PUD1_REG	0x30
-#define AB8500_GPIO_PUD2_REG	0x31
-#define AB8500_GPIO_PUD3_REG	0x32
-#define AB8500_GPIO_PUD4_REG	0x33
-#define AB8500_GPIO_PUD5_REG	0x34
-#define AB8500_GPIO_PUD6_REG	0x35
-#define AB9540_GPIO_PUD7_REG	0x36
-
-#define AB8500_GPIO_IN1_REG	0x40
-#define AB8500_GPIO_IN2_REG	0x41
-#define AB8500_GPIO_IN3_REG	0x42
-#define AB8500_GPIO_IN4_REG	0x43
-#define AB8500_GPIO_IN5_REG	0x44
-#define AB8500_GPIO_IN6_REG	0x45
-#define AB9540_GPIO_IN7_REG	0x46
-#define AB8540_GPIO_VINSEL_REG	0x47
-#define AB8540_GPIO_PULL_UPDOWN_REG	0x48
-#define AB8500_GPIO_ALTFUN_REG	0x50
-#define AB8540_GPIO_PULL_UPDOWN_MASK	0x03
-#define AB8540_GPIO_VINSEL_MASK	0x03
-#define AB8540_GPIOX_VBAT_START	51
-#define AB8540_GPIOX_VBAT_END	54
-
-#define ABX500_GPIO_INPUT	0
-#define ABX500_GPIO_OUTPUT	1
-
-struct abx500_pinctrl {
-	struct device *dev;
-	struct pinctrl_dev *pctldev;
-	struct abx500_pinctrl_soc_data *soc;
-	struct gpio_chip chip;
-	struct ab8500 *parent;
-	struct abx500_gpio_irq_cluster *irq_cluster;
-	int irq_cluster_size;
-};
-
-/**
- * to_abx500_pinctrl() - get the pointer to abx500_pinctrl
- * @chip:	Member of the structure abx500_pinctrl
- */
-static inline struct abx500_pinctrl *to_abx500_pinctrl(struct gpio_chip *chip)
-{
-	return container_of(chip, struct abx500_pinctrl, chip);
-}
-
-static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg,
-			       unsigned offset, bool *bit)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	u8 pos = offset % 8;
-	u8 val;
-	int ret;
-
-	reg += offset / 8;
-	ret = abx500_get_register_interruptible(pct->dev,
-						AB8500_MISC, reg, &val);
-
-	*bit = !!(val & BIT(pos));
-
-	if (ret < 0)
-		dev_err(pct->dev,
-			"%s read reg =%x, offset=%x failed (%d)\n",
-			__func__, reg, offset, ret);
-
-	return ret;
-}
-
-static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
-				unsigned offset, int val)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	u8 pos = offset % 8;
-	int ret;
-
-	reg += offset / 8;
-	ret = abx500_mask_and_set_register_interruptible(pct->dev,
-				AB8500_MISC, reg, BIT(pos), val << pos);
-	if (ret < 0)
-		dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n",
-				__func__, reg, offset, ret);
-
-	return ret;
-}
-
-/**
- * abx500_gpio_get() - Get the particular GPIO value
- * @chip:	Gpio device
- * @offset:	GPIO number to read
- */
-static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	bool bit;
-	bool is_out;
-	u8 gpio_offset = offset - 1;
-	int ret;
-
-	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
-			gpio_offset, &is_out);
-	if (ret < 0)
-		goto out;
-
-	if (is_out)
-		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG,
-				gpio_offset, &bit);
-	else
-		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
-				gpio_offset, &bit);
-out:
-	if (ret < 0) {
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-		return ret;
-	}
-
-	return bit;
-}
-
-static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	int ret;
-
-	ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
-	if (ret < 0)
-		dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
-}
-
-static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
-				  enum abx500_gpio_pull_updown *pull_updown)
-{
-	u8 pos;
-	u8 val;
-	int ret;
-	struct pullud *pullud;
-
-	if (!pct->soc->pullud) {
-		dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
-				__func__);
-		ret = -EPERM;
-		goto out;
-	}
-
-	pullud = pct->soc->pullud;
-
-	if ((offset < pullud->first_pin)
-		|| (offset > pullud->last_pin)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	ret = abx500_get_register_interruptible(pct->dev,
-			AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val);
-
-	pos = (offset - pullud->first_pin) << 1;
-	*pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK;
-
-out:
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
-				  int offset, enum abx500_gpio_pull_updown val)
-{
-	u8 pos;
-	int ret;
-	struct pullud *pullud;
-
-	if (!pct->soc->pullud) {
-		dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
-				__func__);
-		ret = -EPERM;
-		goto out;
-	}
-
-	pullud = pct->soc->pullud;
-
-	if ((offset < pullud->first_pin)
-		|| (offset > pullud->last_pin)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	pos = (offset - pullud->first_pin) << 1;
-
-	ret = abx500_mask_and_set_register_interruptible(pct->dev,
-			AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG,
-			AB8540_GPIO_PULL_UPDOWN_MASK << pos, val << pos);
-
-out:
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	struct pullud *pullud = pct->soc->pullud;
-
-	return (pullud &&
-		gpio >= pullud->first_pin &&
-		gpio <= pullud->last_pin);
-}
-
-static int abx500_gpio_direction_output(struct gpio_chip *chip,
-					unsigned offset,
-					int val)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	unsigned gpio;
-	int ret;
-
-	/* set direction as output */
-	ret = abx500_gpio_set_bits(chip,
-				AB8500_GPIO_DIR1_REG,
-				offset,
-				ABX500_GPIO_OUTPUT);
-	if (ret < 0)
-		goto out;
-
-	/* disable pull down */
-	ret = abx500_gpio_set_bits(chip,
-				AB8500_GPIO_PUD1_REG,
-				offset,
-				ABX500_GPIO_PULL_NONE);
-	if (ret < 0)
-		goto out;
-
-	/* if supported, disable both pull down and pull up */
-	gpio = offset + 1;
-	if (abx500_pullud_supported(chip, gpio)) {
-		ret = abx500_set_pull_updown(pct,
-				gpio,
-				ABX500_GPIO_PULL_NONE);
-	}
-out:
-	if (ret < 0) {
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-		return ret;
-	}
-
-	/* set the output as 1 or 0 */
-	return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
-}
-
-static int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	/* set the register as input */
-	return abx500_gpio_set_bits(chip,
-				AB8500_GPIO_DIR1_REG,
-				offset,
-				ABX500_GPIO_INPUT);
-}
-
-static int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	/* The AB8500 GPIO numbers are off by one */
-	int gpio = offset + 1;
-	int hwirq;
-	int i;
-
-	for (i = 0; i < pct->irq_cluster_size; i++) {
-		struct abx500_gpio_irq_cluster *cluster =
-			&pct->irq_cluster[i];
-
-		if (gpio >= cluster->start && gpio <= cluster->end) {
-			/*
-			 * The ABx500 GPIO's associated IRQs are clustered together
-			 * throughout the interrupt numbers at irregular intervals.
-			 * To solve this quandry, we have placed the read-in values
-			 * into the cluster information table.
-			 */
-			hwirq = gpio - cluster->start + cluster->to_irq;
-			return irq_create_mapping(pct->parent->domain, hwirq);
-		}
-	}
-
-	return -EINVAL;
-}
-
-static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
-			   unsigned gpio, int alt_setting)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	struct alternate_functions af = pct->soc->alternate_functions[gpio];
-	int ret;
-	int val;
-	unsigned offset;
-
-	const char *modes[] = {
-		[ABX500_DEFAULT]	= "default",
-		[ABX500_ALT_A]		= "altA",
-		[ABX500_ALT_B]		= "altB",
-		[ABX500_ALT_C]		= "altC",
-	};
-
-	/* sanity check */
-	if (((alt_setting == ABX500_ALT_A) && (af.gpiosel_bit == UNUSED)) ||
-	    ((alt_setting == ABX500_ALT_B) && (af.alt_bit1 == UNUSED)) ||
-	    ((alt_setting == ABX500_ALT_C) && (af.alt_bit2 == UNUSED))) {
-		dev_dbg(pct->dev, "pin %d doesn't support %s mode\n", gpio,
-				modes[alt_setting]);
-		return -EINVAL;
-	}
-
-	/* on ABx5xx, there is no GPIO0, so adjust the offset */
-	offset = gpio - 1;
-
-	switch (alt_setting) {
-	case ABX500_DEFAULT:
-		/*
-		 * for ABx5xx family, default mode is always selected by
-		 * writing 0 to GPIOSELx register, except for pins which
-		 * support at least ALT_B mode, default mode is selected
-		 * by writing 1 to GPIOSELx register
-		 */
-		val = 0;
-		if (af.alt_bit1 != UNUSED)
-			val++;
-
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
-					   offset, val);
-		break;
-
-	case ABX500_ALT_A:
-		/*
-		 * for ABx5xx family, alt_a mode is always selected by
-		 * writing 1 to GPIOSELx register, except for pins which
-		 * support at least ALT_B mode, alt_a mode is selected
-		 * by writing 0 to GPIOSELx register and 0 in ALTFUNC
-		 * register
-		 */
-		if (af.alt_bit1 != UNUSED) {
-			ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
-					offset, 0);
-			if (ret < 0)
-				goto out;
-
-			ret = abx500_gpio_set_bits(chip,
-					AB8500_GPIO_ALTFUN_REG,
-					af.alt_bit1,
-					!!(af.alta_val & BIT(0)));
-			if (ret < 0)
-				goto out;
-
-			if (af.alt_bit2 != UNUSED)
-				ret = abx500_gpio_set_bits(chip,
-					AB8500_GPIO_ALTFUN_REG,
-					af.alt_bit2,
-					!!(af.alta_val & BIT(1)));
-		} else
-			ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
-					offset, 1);
-		break;
-
-	case ABX500_ALT_B:
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
-				offset, 0);
-		if (ret < 0)
-			goto out;
-
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-				af.alt_bit1, !!(af.altb_val & BIT(0)));
-		if (ret < 0)
-			goto out;
-
-		if (af.alt_bit2 != UNUSED)
-			ret = abx500_gpio_set_bits(chip,
-					AB8500_GPIO_ALTFUN_REG,
-					af.alt_bit2,
-					!!(af.altb_val & BIT(1)));
-		break;
-
-	case ABX500_ALT_C:
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
-				offset, 0);
-		if (ret < 0)
-			goto out;
-
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-				af.alt_bit2, !!(af.altc_val & BIT(0)));
-		if (ret < 0)
-			goto out;
-
-		ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-				af.alt_bit2, !!(af.altc_val & BIT(1)));
-		break;
-
-	default:
-		dev_dbg(pct->dev, "unknow alt_setting %d\n", alt_setting);
-
-		return -EINVAL;
-	}
-out:
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
-			  unsigned gpio)
-{
-	u8 mode;
-	bool bit_mode;
-	bool alt_bit1;
-	bool alt_bit2;
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	struct alternate_functions af = pct->soc->alternate_functions[gpio];
-	/* on ABx5xx, there is no GPIO0, so adjust the offset */
-	unsigned offset = gpio - 1;
-	int ret;
-
-	/*
-	 * if gpiosel_bit is set to unused,
-	 * it means no GPIO or special case
-	 */
-	if (af.gpiosel_bit == UNUSED)
-		return ABX500_DEFAULT;
-
-	/* read GpioSelx register */
-	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
-			af.gpiosel_bit, &bit_mode);
-	if (ret < 0)
-		goto out;
-
-	mode = bit_mode;
-
-	/* sanity check */
-	if ((af.alt_bit1 < UNUSED) || (af.alt_bit1 > 7) ||
-	    (af.alt_bit2 < UNUSED) || (af.alt_bit2 > 7)) {
-		dev_err(pct->dev,
-			"alt_bitX value not in correct range (-1 to 7)\n");
-		return -EINVAL;
-	}
-
-	/* if alt_bit2 is used, alt_bit1 must be used too */
-	if ((af.alt_bit2 != UNUSED) && (af.alt_bit1 == UNUSED)) {
-		dev_err(pct->dev,
-			"if alt_bit2 is used, alt_bit1 can't be unused\n");
-		return -EINVAL;
-	}
-
-	/* check if pin use AlternateFunction register */
-	if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED))
-		return mode;
-	/*
-	 * if pin GPIOSEL bit is set and pin supports alternate function,
-	 * it means DEFAULT mode
-	 */
-	if (mode)
-		return ABX500_DEFAULT;
-
-	/*
-	 * pin use the AlternatFunction register
-	 * read alt_bit1 value
-	 */
-	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
-			    af.alt_bit1, &alt_bit1);
-	if (ret < 0)
-		goto out;
-
-	if (af.alt_bit2 != UNUSED) {
-		/* read alt_bit2 value */
-		ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
-				af.alt_bit2,
-				&alt_bit2);
-		if (ret < 0)
-			goto out;
-	} else
-		alt_bit2 = 0;
-
-	mode = (alt_bit2 << 1) + alt_bit1;
-	if (mode == af.alta_val)
-		return ABX500_ALT_A;
-	else if (mode == af.altb_val)
-		return ABX500_ALT_B;
-	else
-		return ABX500_ALT_C;
-
-out:
-	dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-	return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/seq_file.h>
-
-static void abx500_gpio_dbg_show_one(struct seq_file *s,
-				     struct pinctrl_dev *pctldev,
-				     struct gpio_chip *chip,
-				     unsigned offset, unsigned gpio)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	const char *label = gpiochip_is_requested(chip, offset - 1);
-	u8 gpio_offset = offset - 1;
-	int mode = -1;
-	bool is_out;
-	bool pd;
-	enum abx500_gpio_pull_updown pud = 0;
-	int ret;
-
-	const char *modes[] = {
-		[ABX500_DEFAULT]	= "default",
-		[ABX500_ALT_A]		= "altA",
-		[ABX500_ALT_B]		= "altB",
-		[ABX500_ALT_C]		= "altC",
-	};
-
-	const char *pull_up_down[] = {
-		[ABX500_GPIO_PULL_DOWN]		= "pull down",
-		[ABX500_GPIO_PULL_NONE]		= "pull none",
-		[ABX500_GPIO_PULL_NONE + 1]	= "pull none",
-		[ABX500_GPIO_PULL_UP]		= "pull up",
-	};
-
-	ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
-			gpio_offset, &is_out);
-	if (ret < 0)
-		goto out;
-
-	seq_printf(s, " gpio-%-3d (%-20.20s) %-3s",
-		   gpio, label ?: "(none)",
-		   is_out ? "out" : "in ");
-
-	if (!is_out) {
-		if (abx500_pullud_supported(chip, offset)) {
-			ret = abx500_get_pull_updown(pct, offset, &pud);
-			if (ret < 0)
-				goto out;
-
-			seq_printf(s, " %-9s", pull_up_down[pud]);
-		} else {
-			ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
-					gpio_offset, &pd);
-			if (ret < 0)
-				goto out;
-
-			seq_printf(s, " %-9s", pull_up_down[pd]);
-		}
-	} else
-		seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
-
-	if (pctldev)
-		mode = abx500_get_mode(pctldev, chip, offset);
-
-	seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
-
-out:
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-}
-
-static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	unsigned i;
-	unsigned gpio = chip->base;
-	struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
-	struct pinctrl_dev *pctldev = pct->pctldev;
-
-	for (i = 0; i < chip->ngpio; i++, gpio++) {
-		/* On AB8500, there is no GPIO0, the first is the GPIO 1 */
-		abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio);
-		seq_printf(s, "\n");
-	}
-}
-
-#else
-static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
-					    struct pinctrl_dev *pctldev,
-					    struct gpio_chip *chip,
-					    unsigned offset, unsigned gpio)
-{
-}
-#define abx500_gpio_dbg_show	NULL
-#endif
-
-static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	int gpio = chip->base + offset;
-
-	return pinctrl_request_gpio(gpio);
-}
-
-static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	int gpio = chip->base + offset;
-
-	pinctrl_free_gpio(gpio);
-}
-
-static struct gpio_chip abx500gpio_chip = {
-	.label			= "abx500-gpio",
-	.owner			= THIS_MODULE,
-	.request		= abx500_gpio_request,
-	.free			= abx500_gpio_free,
-	.direction_input	= abx500_gpio_direction_input,
-	.get			= abx500_gpio_get,
-	.direction_output	= abx500_gpio_direction_output,
-	.set			= abx500_gpio_set,
-	.to_irq			= abx500_gpio_to_irq,
-	.dbg_show		= abx500_gpio_dbg_show,
-};
-
-static int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	return pct->soc->nfunctions;
-}
-
-static const char *abx500_pmx_get_func_name(struct pinctrl_dev *pctldev,
-					 unsigned function)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	return pct->soc->functions[function].name;
-}
-
-static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev,
-				      unsigned function,
-				      const char * const **groups,
-				      unsigned * const num_groups)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	*groups = pct->soc->functions[function].groups;
-	*num_groups = pct->soc->functions[function].ngroups;
-
-	return 0;
-}
-
-static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
-			     unsigned group)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	struct gpio_chip *chip = &pct->chip;
-	const struct abx500_pingroup *g;
-	int i;
-	int ret = 0;
-
-	g = &pct->soc->groups[group];
-	if (g->altsetting < 0)
-		return -EINVAL;
-
-	dev_dbg(pct->dev, "enable group %s, %u pins\n", g->name, g->npins);
-
-	for (i = 0; i < g->npins; i++) {
-		dev_dbg(pct->dev, "setting pin %d to altsetting %d\n",
-			g->pins[i], g->altsetting);
-
-		ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting);
-	}
-
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static void abx500_pmx_disable(struct pinctrl_dev *pctldev,
-			       unsigned function, unsigned group)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	const struct abx500_pingroup *g;
-
-	g = &pct->soc->groups[group];
-	if (g->altsetting < 0)
-		return;
-
-	/* FIXME: poke out the mux, set the pin to some default state? */
-	dev_dbg(pct->dev, "disable group %s, %u pins\n", g->name, g->npins);
-}
-
-static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
-			       struct pinctrl_gpio_range *range,
-			       unsigned offset)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	const struct abx500_pinrange *p;
-	int ret;
-	int i;
-
-	/*
-	 * Different ranges have different ways to enable GPIO function on a
-	 * pin, so refer back to our local range type, where we handily define
-	 * what altfunc enables GPIO for a certain pin.
-	 */
-	for (i = 0; i < pct->soc->gpio_num_ranges; i++) {
-		p = &pct->soc->gpio_ranges[i];
-		if ((offset >= p->offset) &&
-		    (offset < (p->offset + p->npins)))
-		  break;
-	}
-
-	if (i == pct->soc->gpio_num_ranges) {
-		dev_err(pct->dev, "%s failed to locate range\n", __func__);
-		return -ENODEV;
-	}
-
-	dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n",
-		p->altfunc, offset);
-
-	ret = abx500_set_mode(pct->pctldev, &pct->chip,
-			      offset, p->altfunc);
-	if (ret < 0)
-		dev_err(pct->dev, "%s setting altfunc failed\n", __func__);
-
-	return ret;
-}
-
-static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev,
-				     struct pinctrl_gpio_range *range,
-				     unsigned offset)
-{
-}
-
-static const struct pinmux_ops abx500_pinmux_ops = {
-	.get_functions_count = abx500_pmx_get_funcs_cnt,
-	.get_function_name = abx500_pmx_get_func_name,
-	.get_function_groups = abx500_pmx_get_func_groups,
-	.enable = abx500_pmx_enable,
-	.disable = abx500_pmx_disable,
-	.gpio_request_enable = abx500_gpio_request_enable,
-	.gpio_disable_free = abx500_gpio_disable_free,
-};
-
-static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	return pct->soc->ngroups;
-}
-
-static const char *abx500_get_group_name(struct pinctrl_dev *pctldev,
-					 unsigned selector)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	return pct->soc->groups[selector].name;
-}
-
-static int abx500_get_group_pins(struct pinctrl_dev *pctldev,
-				 unsigned selector,
-				 const unsigned **pins,
-				 unsigned *num_pins)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-
-	*pins = pct->soc->groups[selector].pins;
-	*num_pins = pct->soc->groups[selector].npins;
-
-	return 0;
-}
-
-static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
-				struct seq_file *s, unsigned offset)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	struct gpio_chip *chip = &pct->chip;
-
-	abx500_gpio_dbg_show_one(s, pctldev, chip, offset,
-				 chip->base + offset - 1);
-}
-
-static void abx500_dt_free_map(struct pinctrl_dev *pctldev,
-		struct pinctrl_map *map, unsigned num_maps)
-{
-	int i;
-
-	for (i = 0; i < num_maps; i++)
-		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
-			kfree(map[i].data.configs.configs);
-	kfree(map);
-}
-
-static int abx500_dt_reserve_map(struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps,
-		unsigned reserve)
-{
-	unsigned old_num = *reserved_maps;
-	unsigned new_num = *num_maps + reserve;
-	struct pinctrl_map *new_map;
-
-	if (old_num >= new_num)
-		return 0;
-
-	new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
-	if (!new_map)
-		return -ENOMEM;
-
-	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
-
-	*map = new_map;
-	*reserved_maps = new_num;
-
-	return 0;
-}
-
-static int abx500_dt_add_map_mux(struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps, const char *group,
-		const char *function)
-{
-	if (*num_maps == *reserved_maps)
-		return -ENOSPC;
-
-	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
-	(*map)[*num_maps].data.mux.group = group;
-	(*map)[*num_maps].data.mux.function = function;
-	(*num_maps)++;
-
-	return 0;
-}
-
-static int abx500_dt_add_map_configs(struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps, const char *group,
-		unsigned long *configs, unsigned num_configs)
-{
-	unsigned long *dup_configs;
-
-	if (*num_maps == *reserved_maps)
-		return -ENOSPC;
-
-	dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
-			      GFP_KERNEL);
-	if (!dup_configs)
-		return -ENOMEM;
-
-	(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
-
-	(*map)[*num_maps].data.configs.group_or_pin = group;
-	(*map)[*num_maps].data.configs.configs = dup_configs;
-	(*map)[*num_maps].data.configs.num_configs = num_configs;
-	(*num_maps)++;
-
-	return 0;
-}
-
-static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev,
-					const char *pin_name)
-{
-	int i, pin_number;
-	struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
-		for (i = 0; i < npct->soc->npins; i++)
-			if (npct->soc->pins[i].number == pin_number)
-				return npct->soc->pins[i].name;
-	return NULL;
-}
-
-static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev,
-		struct device_node *np,
-		struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps)
-{
-	int ret;
-	const char *function = NULL;
-	unsigned long *configs;
-	unsigned int nconfigs = 0;
-	bool has_config = 0;
-	unsigned reserve = 0;
-	struct property *prop;
-	const char *group, *gpio_name;
-	struct device_node *np_config;
-
-	ret = of_property_read_string(np, "ste,function", &function);
-	if (ret >= 0)
-		reserve = 1;
-
-	ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
-	if (nconfigs)
-		has_config = 1;
-
-	np_config = of_parse_phandle(np, "ste,config", 0);
-	if (np_config) {
-		ret = pinconf_generic_parse_dt_config(np_config, &configs,
-				&nconfigs);
-		if (ret)
-			goto exit;
-		has_config |= nconfigs;
-	}
-
-	ret = of_property_count_strings(np, "ste,pins");
-	if (ret < 0)
-		goto exit;
-
-	if (has_config)
-		reserve++;
-
-	reserve *= ret;
-
-	ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve);
-	if (ret < 0)
-		goto exit;
-
-	of_property_for_each_string(np, "ste,pins", prop, group) {
-		if (function) {
-			ret = abx500_dt_add_map_mux(map, reserved_maps,
-					num_maps, group, function);
-			if (ret < 0)
-				goto exit;
-		}
-		if (has_config) {
-			gpio_name = abx500_find_pin_name(pctldev, group);
-
-			ret = abx500_dt_add_map_configs(map, reserved_maps,
-					num_maps, gpio_name, configs, 1);
-			if (ret < 0)
-				goto exit;
-		}
-
-	}
-exit:
-	return ret;
-}
-
-static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
-				 struct device_node *np_config,
-				 struct pinctrl_map **map, unsigned *num_maps)
-{
-	unsigned reserved_maps;
-	struct device_node *np;
-	int ret;
-
-	reserved_maps = 0;
-	*map = NULL;
-	*num_maps = 0;
-
-	for_each_child_of_node(np_config, np) {
-		ret = abx500_dt_subnode_to_map(pctldev, np, map,
-				&reserved_maps, num_maps);
-		if (ret < 0) {
-			abx500_dt_free_map(pctldev, *map, *num_maps);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static const struct pinctrl_ops abx500_pinctrl_ops = {
-	.get_groups_count = abx500_get_groups_cnt,
-	.get_group_name = abx500_get_group_name,
-	.get_group_pins = abx500_get_group_pins,
-	.pin_dbg_show = abx500_pin_dbg_show,
-	.dt_node_to_map = abx500_dt_node_to_map,
-	.dt_free_map = abx500_dt_free_map,
-};
-
-static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
-			  unsigned pin,
-			  unsigned long *config)
-{
-	return -ENOSYS;
-}
-
-static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
-			  unsigned pin,
-			  unsigned long *configs,
-			  unsigned num_configs)
-{
-	struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
-	struct gpio_chip *chip = &pct->chip;
-	unsigned offset;
-	int ret = -EINVAL;
-	int i;
-	enum pin_config_param param;
-	enum pin_config_param argument;
-
-	for (i = 0; i < num_configs; i++) {
-		param = pinconf_to_config_param(configs[i]);
-		argument = pinconf_to_config_argument(configs[i]);
-
-		dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n",
-			pin, configs[i],
-			(param == PIN_CONFIG_OUTPUT) ? "output " : "input",
-			(param == PIN_CONFIG_OUTPUT) ?
-			(argument ? "high" : "low") :
-			(argument ? "pull up" : "pull down"));
-
-		/* on ABx500, there is no GPIO0, so adjust the offset */
-		offset = pin - 1;
-
-		switch (param) {
-		case PIN_CONFIG_BIAS_DISABLE:
-			ret = abx500_gpio_direction_input(chip, offset);
-			if (ret < 0)
-				goto out;
-			/*
-			 * Some chips only support pull down, while some
-			 * actually support both pull up and pull down. Such
-			 * chips have a "pullud" range specified for the pins
-			 * that support both features. If the pin is not
-			 * within that range, we fall back to the old bit set
-			 * that only support pull down.
-			 */
-			if (abx500_pullud_supported(chip, pin))
-				ret = abx500_set_pull_updown(pct,
-					pin,
-					ABX500_GPIO_PULL_NONE);
-			else
-				/* Chip only supports pull down */
-				ret = abx500_gpio_set_bits(chip,
-					AB8500_GPIO_PUD1_REG, offset,
-					ABX500_GPIO_PULL_NONE);
-			break;
-
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			ret = abx500_gpio_direction_input(chip, offset);
-			if (ret < 0)
-				goto out;
-			/*
-			 * if argument = 1 set the pull down
-			 * else clear the pull down
-			 * Some chips only support pull down, while some
-			 * actually support both pull up and pull down. Such
-			 * chips have a "pullud" range specified for the pins
-			 * that support both features. If the pin is not
-			 * within that range, we fall back to the old bit set
-			 * that only support pull down.
-			 */
-			if (abx500_pullud_supported(chip, pin))
-				ret = abx500_set_pull_updown(pct,
-					pin,
-					argument ? ABX500_GPIO_PULL_DOWN :
-					ABX500_GPIO_PULL_NONE);
-			else
-				/* Chip only supports pull down */
-				ret = abx500_gpio_set_bits(chip,
-				AB8500_GPIO_PUD1_REG,
-					offset,
-					argument ? ABX500_GPIO_PULL_DOWN :
-					ABX500_GPIO_PULL_NONE);
-			break;
-
-		case PIN_CONFIG_BIAS_PULL_UP:
-			ret = abx500_gpio_direction_input(chip, offset);
-			if (ret < 0)
-				goto out;
-			/*
-			 * if argument = 1 set the pull up
-			 * else clear the pull up
-			 */
-			ret = abx500_gpio_direction_input(chip, offset);
-			/*
-			 * Some chips only support pull down, while some
-			 * actually support both pull up and pull down. Such
-			 * chips have a "pullud" range specified for the pins
-			 * that support both features. If the pin is not
-			 * within that range, do nothing
-			 */
-			if (abx500_pullud_supported(chip, pin))
-				ret = abx500_set_pull_updown(pct,
-					pin,
-					argument ? ABX500_GPIO_PULL_UP :
-					ABX500_GPIO_PULL_NONE);
-			break;
-
-		case PIN_CONFIG_OUTPUT:
-			ret = abx500_gpio_direction_output(chip, offset,
-				argument);
-			break;
-
-		default:
-			dev_err(chip->dev, "illegal configuration requested\n");
-		}
-	} /* for each config */
-out:
-	if (ret < 0)
-		dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
-	return ret;
-}
-
-static const struct pinconf_ops abx500_pinconf_ops = {
-	.pin_config_get = abx500_pin_config_get,
-	.pin_config_set = abx500_pin_config_set,
-};
-
-static struct pinctrl_desc abx500_pinctrl_desc = {
-	.name = "pinctrl-abx500",
-	.pctlops = &abx500_pinctrl_ops,
-	.pmxops = &abx500_pinmux_ops,
-	.confops = &abx500_pinconf_ops,
-	.owner = THIS_MODULE,
-};
-
-static int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc)
-{
-	unsigned int lowest = 0;
-	unsigned int highest = 0;
-	unsigned int npins = 0;
-	int i;
-
-	/*
-	 * Compute number of GPIOs from the last SoC gpio range descriptors
-	 * These ranges may include "holes" but the GPIO number space shall
-	 * still be homogeneous, so we need to detect and account for any
-	 * such holes so that these are included in the number of GPIO pins.
-	 */
-	for (i = 0; i < soc->gpio_num_ranges; i++) {
-		unsigned gstart;
-		unsigned gend;
-		const struct abx500_pinrange *p;
-
-		p = &soc->gpio_ranges[i];
-		gstart = p->offset;
-		gend = p->offset + p->npins - 1;
-
-		if (i == 0) {
-			/* First iteration, set start values */
-			lowest = gstart;
-			highest = gend;
-		} else {
-			if (gstart < lowest)
-				lowest = gstart;
-			if (gend > highest)
-				highest = gend;
-		}
-	}
-	/* this gives the absolute number of pins */
-	npins = highest - lowest + 1;
-	return npins;
-}
-
-static const struct of_device_id abx500_gpio_match[] = {
-	{ .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, },
-	{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
-	{ .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
-	{ .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
-	{ }
-};
-
-static int abx500_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	const struct of_device_id *match;
-	struct abx500_pinctrl *pct;
-	unsigned int id = -1;
-	int ret, err;
-	int i;
-
-	if (!np) {
-		dev_err(&pdev->dev, "gpio dt node missing\n");
-		return -ENODEV;
-	}
-
-	pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl),
-				   GFP_KERNEL);
-	if (pct == NULL) {
-		dev_err(&pdev->dev,
-			"failed to allocate memory for pct\n");
-		return -ENOMEM;
-	}
-
-	pct->dev = &pdev->dev;
-	pct->parent = dev_get_drvdata(pdev->dev.parent);
-	pct->chip = abx500gpio_chip;
-	pct->chip.dev = &pdev->dev;
-	pct->chip.base = -1; /* Dynamic allocation */
-
-	match = of_match_device(abx500_gpio_match, &pdev->dev);
-	if (!match) {
-		dev_err(&pdev->dev, "gpio dt not matching\n");
-		return -ENODEV;
-	}
-	id = (unsigned long)match->data;
-
-	/* Poke in other ASIC variants here */
-	switch (id) {
-	case PINCTRL_AB8500:
-		abx500_pinctrl_ab8500_init(&pct->soc);
-		break;
-	case PINCTRL_AB8540:
-		abx500_pinctrl_ab8540_init(&pct->soc);
-		break;
-	case PINCTRL_AB9540:
-		abx500_pinctrl_ab9540_init(&pct->soc);
-		break;
-	case PINCTRL_AB8505:
-		abx500_pinctrl_ab8505_init(&pct->soc);
-		break;
-	default:
-		dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id);
-		return -EINVAL;
-	}
-
-	if (!pct->soc) {
-		dev_err(&pdev->dev, "Invalid SOC data\n");
-		return -EINVAL;
-	}
-
-	pct->chip.ngpio = abx500_get_gpio_num(pct->soc);
-	pct->irq_cluster = pct->soc->gpio_irq_cluster;
-	pct->irq_cluster_size = pct->soc->ngpio_irq_cluster;
-
-	ret = gpiochip_add(&pct->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		return ret;
-	}
-	dev_info(&pdev->dev, "added gpiochip\n");
-
-	abx500_pinctrl_desc.pins = pct->soc->pins;
-	abx500_pinctrl_desc.npins = pct->soc->npins;
-	pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct);
-	if (!pct->pctldev) {
-		dev_err(&pdev->dev,
-			"could not register abx500 pinctrl driver\n");
-		ret = -EINVAL;
-		goto out_rem_chip;
-	}
-	dev_info(&pdev->dev, "registered pin controller\n");
-
-	/* We will handle a range of GPIO pins */
-	for (i = 0; i < pct->soc->gpio_num_ranges; i++) {
-		const struct abx500_pinrange *p = &pct->soc->gpio_ranges[i];
-
-		ret = gpiochip_add_pin_range(&pct->chip,
-					dev_name(&pdev->dev),
-					p->offset - 1, p->offset, p->npins);
-		if (ret < 0)
-			goto out_rem_chip;
-	}
-
-	platform_set_drvdata(pdev, pct);
-	dev_info(&pdev->dev, "initialized abx500 pinctrl driver\n");
-
-	return 0;
-
-out_rem_chip:
-	err = gpiochip_remove(&pct->chip);
-	if (err)
-		dev_info(&pdev->dev, "failed to remove gpiochip\n");
-
-	return ret;
-}
-
-/**
- * abx500_gpio_remove() - remove Ab8500-gpio driver
- * @pdev:	Platform device registered
- */
-static int abx500_gpio_remove(struct platform_device *pdev)
-{
-	struct abx500_pinctrl *pct = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&pct->chip);
-	if (ret < 0) {
-		dev_err(pct->dev, "unable to remove gpiochip: %d\n",
-			ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct platform_driver abx500_gpio_driver = {
-	.driver = {
-		.name = "abx500-gpio",
-		.owner = THIS_MODULE,
-		.of_match_table = abx500_gpio_match,
-	},
-	.probe = abx500_gpio_probe,
-	.remove = abx500_gpio_remove,
-};
-
-static int __init abx500_gpio_init(void)
-{
-	return platform_driver_register(&abx500_gpio_driver);
-}
-core_initcall(abx500_gpio_init);
-
-MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>");
-MODULE_DESCRIPTION("Driver allows to use AxB5xx unused pins to be used as GPIO");
-MODULE_ALIAS("platform:abx500-gpio");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-abx500.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-abx500.h
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-abx500.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-abx500.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-#ifndef PINCTRL_PINCTRL_ABx500_H
-#define PINCTRL_PINCTRL_ABx500_H
-
-/* Package definitions */
-#define PINCTRL_AB8500	0
-#define PINCTRL_AB8540	1
-#define PINCTRL_AB9540	2
-#define PINCTRL_AB8505	3
-
-/* pins alternate function */
-enum abx500_pin_func {
-	ABX500_DEFAULT,
-	ABX500_ALT_A,
-	ABX500_ALT_B,
-	ABX500_ALT_C,
-};
-
-enum abx500_gpio_pull_updown {
-	ABX500_GPIO_PULL_DOWN = 0x0,
-	ABX500_GPIO_PULL_NONE = 0x1,
-	ABX500_GPIO_PULL_UP = 0x3,
-};
-
-enum abx500_gpio_vinsel {
-	ABX500_GPIO_VINSEL_VBAT = 0x0,
-	ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
-	ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
-};
-
-/**
- * struct abx500_function - ABx500 pinctrl mux function
- * @name: The name of the function, exported to pinctrl core.
- * @groups: An array of pin groups that may select this function.
- * @ngroups: The number of entries in @groups.
- */
-struct abx500_function {
-	const char *name;
-	const char * const *groups;
-	unsigned ngroups;
-};
-
-/**
- * struct abx500_pingroup - describes a ABx500 pin group
- * @name: the name of this specific pin group
- * @pins: an array of discrete physical pins used in this group, taken
- *	from the driver-local pin enumeration space
- * @num_pins: the number of pins in this group array, i.e. the number of
- *	elements in .pins so we can iterate over that array
- * @altsetting: the altsetting to apply to all pins in this group to
- *	configure them to be used by a function
- */
-struct abx500_pingroup {
-	const char *name;
-	const unsigned int *pins;
-	const unsigned npins;
-	int altsetting;
-};
-
-#define ALTERNATE_FUNCTIONS(pin, sel_bit, alt1, alt2, alta, altb, altc)	\
-{									\
-	.pin_number = pin,						\
-	.gpiosel_bit = sel_bit,						\
-	.alt_bit1 = alt1,						\
-	.alt_bit2 = alt2,						\
-	.alta_val = alta,						\
-	.altb_val = altb,						\
-	.altc_val = altc,						\
-}
-
-#define UNUSED -1
-/**
- * struct alternate_functions
- * @pin_number:		The pin number
- * @gpiosel_bit:	Control bit in GPIOSEL register,
- * @alt_bit1:		First AlternateFunction bit used to select the
- *			alternate function
- * @alt_bit2:		Second AlternateFunction bit used to select the
- *			alternate function
- *
- *			these 3 following fields are necessary due to none
- *			coherency on how to select the altA, altB and altC
- *			function between the ABx500 SOC family when using
- *			alternatfunc register.
- * @alta_val:		value to write in alternatfunc to select altA function
- * @altb_val:		value to write in alternatfunc to select altB function
- * @altc_val:		value to write in alternatfunc to select altC function
- */
-struct alternate_functions {
-	unsigned pin_number;
-	s8 gpiosel_bit;
-	s8 alt_bit1;
-	s8 alt_bit2;
-	u8 alta_val;
-	u8 altb_val;
-	u8 altc_val;
-};
-
-/**
- * struct pullud - specific pull up/down feature
- * @first_pin:		The pin number of the first pins which support
- *			specific pull up/down
- * @last_pin:		The pin number of the last pins
- */
-struct pullud {
-	unsigned first_pin;
-	unsigned last_pin;
-};
-
-#define GPIO_IRQ_CLUSTER(a, b, c)	\
-{					\
-	.start = a,			\
-	.end = b,			\
-	.to_irq = c,			\
-}
-
-/**
- * struct abx500_gpio_irq_cluster - indicates GPIOs which are interrupt
- *			capable
- * @start:		The pin number of the first pin interrupt capable
- * @end:		The pin number of the last pin interrupt capable
- * @to_irq:		The ABx500 GPIO's associated IRQs are clustered
- *                      together throughout the interrupt numbers at irregular
- *                      intervals. To solve this quandary, we will place the
- *                      read-in values into the cluster information table
- */
-
-struct abx500_gpio_irq_cluster {
-	int start;
-	int end;
-	int to_irq;
-};
-
-/**
- * struct abx500_pinrange - map pin numbers to GPIO offsets
- * @offset:		offset into the GPIO local numberspace, incidentally
- *			identical to the offset into the local pin numberspace
- * @npins:		number of pins to map from both offsets
- * @altfunc:		altfunc setting to be used to enable GPIO on a pin in
- *			this range (may vary)
- */
-struct abx500_pinrange {
-	unsigned int offset;
-	unsigned int npins;
-	int altfunc;
-};
-
-#define ABX500_PINRANGE(a, b, c) { .offset = a, .npins = b, .altfunc = c }
-
-/**
- * struct abx500_pinctrl_soc_data - ABx500 pin controller per-SoC configuration
- * @gpio_ranges:	An array of GPIO ranges for this SoC
- * @gpio_num_ranges:	The number of GPIO ranges for this SoC
- * @pins:		An array describing all pins the pin controller affects.
- *			All pins which are also GPIOs must be listed first within the
- *			array, and be numbered identically to the GPIO controller's
- *			numbering.
- * @npins:		The number of entries in @pins.
- * @functions:		The functions supported on this SoC.
- * @nfunction:		The number of entries in @functions.
- * @groups:		An array describing all pin groups the pin SoC supports.
- * @ngroups:		The number of entries in @groups.
- * @alternate_functions: array describing pins which supports alternate and
- *			how to set it.
- * @pullud:		array describing pins which supports pull up/down
- *			specific registers.
- * @gpio_irq_cluster:	An array of GPIO interrupt capable for this SoC
- * @ngpio_irq_cluster:	The number of GPIO inetrrupt capable for this SoC
- * @irq_gpio_rising_offset: Interrupt offset used as base to compute specific
- *			setting strategy of the rising interrupt line
- * @irq_gpio_falling_offset: Interrupt offset used as base to compute specific
- *			setting strategy of the falling interrupt line
- * @irq_gpio_factor:	Factor used to compute specific setting strategy of
- *			the interrupt line
- */
-
-struct abx500_pinctrl_soc_data {
-	const struct abx500_pinrange *gpio_ranges;
-	unsigned gpio_num_ranges;
-	const struct pinctrl_pin_desc *pins;
-	unsigned npins;
-	const struct abx500_function *functions;
-	unsigned nfunctions;
-	const struct abx500_pingroup *groups;
-	unsigned ngroups;
-	struct alternate_functions *alternate_functions;
-	struct pullud *pullud;
-	struct abx500_gpio_irq_cluster *gpio_irq_cluster;
-	unsigned ngpio_irq_cluster;
-	int irq_gpio_rising_offset;
-	int irq_gpio_falling_offset;
-	int irq_gpio_factor;
-};
-
-#ifdef CONFIG_PINCTRL_AB8500
-
-void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#ifdef CONFIG_PINCTRL_AB8540
-
-void abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#ifdef CONFIG_PINCTRL_AB9540
-
-void abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#ifdef CONFIG_PINCTRL_AB8505
-
-void abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#endif /* PINCTRL_PINCTRL_ABx500_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-adi2.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-adi2.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-adi2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-adi2.c	2014-09-28 17:29:07.000000000 -0400
@@ -401,7 +401,7 @@ static int adi_gpio_irq_type(struct irq_
 
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
 		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		snprintf(buf, 16, "gpio-irq%d", irq);
+		snprintf(buf, 16, "gpio-irq%u", irq);
 		port_setup(port, d->hwirq, true);
 	} else
 		goto out;
@@ -652,35 +652,6 @@ static int adi_pinmux_enable(struct pinc
 	return 0;
 }
 
-static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned func_id,
-	unsigned group_id)
-{
-	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
-	struct gpio_port *port;
-	struct pinctrl_gpio_range *range;
-	unsigned long flags;
-	unsigned short *mux, pin;
-
-	mux = (unsigned short *)pinctrl->soc->groups[group_id].mux;
-
-	while (*mux) {
-		pin = P_IDENT(*mux);
-
-		range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
-		if (range == NULL) /* should not happen */
-			return;
-
-		port = container_of(range->gc, struct gpio_port, chip);
-
-		spin_lock_irqsave(&port->lock, flags);
-
-		port_setup(port, pin_to_offset(range, pin), true);
-		mux++;
-
-		spin_unlock_irqrestore(&port->lock, flags);
-	}
-}
-
 static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
 {
 	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -728,7 +699,6 @@ static int adi_pinmux_request_gpio(struc
 
 static struct pinmux_ops adi_pinmux_ops = {
 	.enable = adi_pinmux_enable,
-	.disable = adi_pinmux_disable,
 	.get_functions_count = adi_pinmux_get_funcs_count,
 	.get_function_name = adi_pinmux_get_func_name,
 	.get_function_groups = adi_pinmux_get_groups,
@@ -979,7 +949,7 @@ static int adi_gpio_probe(struct platfor
 	struct gpio_port *port;
 	char pinctrl_devname[DEVNAME_SIZE];
 	static int gpio;
-	int ret = 0, ret1;
+	int ret = 0;
 
 	pdata = dev->platform_data;
 	if (!pdata)
@@ -1057,7 +1027,7 @@ static int adi_gpio_probe(struct platfor
 	return 0;
 
 out_remove_gpiochip:
-	ret1 = gpiochip_remove(&port->chip);
+	gpiochip_remove(&port->chip);
 out_remove_domain:
 	if (port->pint)
 		irq_domain_remove(port->domain);
@@ -1068,12 +1038,11 @@ out_remove_domain:
 static int adi_gpio_remove(struct platform_device *pdev)
 {
 	struct gpio_port *port = platform_get_drvdata(pdev);
-	int ret;
 	u8 offset;
 
 	list_del(&port->node);
 	gpiochip_remove_pin_ranges(&port->chip);
-	ret = gpiochip_remove(&port->chip);
+	gpiochip_remove(&port->chip);
 	if (port->pint) {
 		for (offset = 0; offset < port->width; offset++)
 			irq_dispose_mapping(irq_find_mapping(port->domain,
@@ -1081,7 +1050,7 @@ static int adi_gpio_remove(struct platfo
 		irq_domain_remove(port->domain);
 	}
 
-	return ret;
+	return 0;
 }
 
 static int adi_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-apq8064.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-apq8064.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-apq8064.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-apq8064.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,613 +0,0 @@
-/*
- * Copyright (c) 2014, Sony Mobile Communications AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-msm.h"
-
-static const struct pinctrl_pin_desc apq8064_pins[] = {
-	PINCTRL_PIN(0, "GPIO_0"),
-	PINCTRL_PIN(1, "GPIO_1"),
-	PINCTRL_PIN(2, "GPIO_2"),
-	PINCTRL_PIN(3, "GPIO_3"),
-	PINCTRL_PIN(4, "GPIO_4"),
-	PINCTRL_PIN(5, "GPIO_5"),
-	PINCTRL_PIN(6, "GPIO_6"),
-	PINCTRL_PIN(7, "GPIO_7"),
-	PINCTRL_PIN(8, "GPIO_8"),
-	PINCTRL_PIN(9, "GPIO_9"),
-	PINCTRL_PIN(10, "GPIO_10"),
-	PINCTRL_PIN(11, "GPIO_11"),
-	PINCTRL_PIN(12, "GPIO_12"),
-	PINCTRL_PIN(13, "GPIO_13"),
-	PINCTRL_PIN(14, "GPIO_14"),
-	PINCTRL_PIN(15, "GPIO_15"),
-	PINCTRL_PIN(16, "GPIO_16"),
-	PINCTRL_PIN(17, "GPIO_17"),
-	PINCTRL_PIN(18, "GPIO_18"),
-	PINCTRL_PIN(19, "GPIO_19"),
-	PINCTRL_PIN(20, "GPIO_20"),
-	PINCTRL_PIN(21, "GPIO_21"),
-	PINCTRL_PIN(22, "GPIO_22"),
-	PINCTRL_PIN(23, "GPIO_23"),
-	PINCTRL_PIN(24, "GPIO_24"),
-	PINCTRL_PIN(25, "GPIO_25"),
-	PINCTRL_PIN(26, "GPIO_26"),
-	PINCTRL_PIN(27, "GPIO_27"),
-	PINCTRL_PIN(28, "GPIO_28"),
-	PINCTRL_PIN(29, "GPIO_29"),
-	PINCTRL_PIN(30, "GPIO_30"),
-	PINCTRL_PIN(31, "GPIO_31"),
-	PINCTRL_PIN(32, "GPIO_32"),
-	PINCTRL_PIN(33, "GPIO_33"),
-	PINCTRL_PIN(34, "GPIO_34"),
-	PINCTRL_PIN(35, "GPIO_35"),
-	PINCTRL_PIN(36, "GPIO_36"),
-	PINCTRL_PIN(37, "GPIO_37"),
-	PINCTRL_PIN(38, "GPIO_38"),
-	PINCTRL_PIN(39, "GPIO_39"),
-	PINCTRL_PIN(40, "GPIO_40"),
-	PINCTRL_PIN(41, "GPIO_41"),
-	PINCTRL_PIN(42, "GPIO_42"),
-	PINCTRL_PIN(43, "GPIO_43"),
-	PINCTRL_PIN(44, "GPIO_44"),
-	PINCTRL_PIN(45, "GPIO_45"),
-	PINCTRL_PIN(46, "GPIO_46"),
-	PINCTRL_PIN(47, "GPIO_47"),
-	PINCTRL_PIN(48, "GPIO_48"),
-	PINCTRL_PIN(49, "GPIO_49"),
-	PINCTRL_PIN(50, "GPIO_50"),
-	PINCTRL_PIN(51, "GPIO_51"),
-	PINCTRL_PIN(52, "GPIO_52"),
-	PINCTRL_PIN(53, "GPIO_53"),
-	PINCTRL_PIN(54, "GPIO_54"),
-	PINCTRL_PIN(55, "GPIO_55"),
-	PINCTRL_PIN(56, "GPIO_56"),
-	PINCTRL_PIN(57, "GPIO_57"),
-	PINCTRL_PIN(58, "GPIO_58"),
-	PINCTRL_PIN(59, "GPIO_59"),
-	PINCTRL_PIN(60, "GPIO_60"),
-	PINCTRL_PIN(61, "GPIO_61"),
-	PINCTRL_PIN(62, "GPIO_62"),
-	PINCTRL_PIN(63, "GPIO_63"),
-	PINCTRL_PIN(64, "GPIO_64"),
-	PINCTRL_PIN(65, "GPIO_65"),
-	PINCTRL_PIN(66, "GPIO_66"),
-	PINCTRL_PIN(67, "GPIO_67"),
-	PINCTRL_PIN(68, "GPIO_68"),
-	PINCTRL_PIN(69, "GPIO_69"),
-	PINCTRL_PIN(70, "GPIO_70"),
-	PINCTRL_PIN(71, "GPIO_71"),
-	PINCTRL_PIN(72, "GPIO_72"),
-	PINCTRL_PIN(73, "GPIO_73"),
-	PINCTRL_PIN(74, "GPIO_74"),
-	PINCTRL_PIN(75, "GPIO_75"),
-	PINCTRL_PIN(76, "GPIO_76"),
-	PINCTRL_PIN(77, "GPIO_77"),
-	PINCTRL_PIN(78, "GPIO_78"),
-	PINCTRL_PIN(79, "GPIO_79"),
-	PINCTRL_PIN(80, "GPIO_80"),
-	PINCTRL_PIN(81, "GPIO_81"),
-	PINCTRL_PIN(82, "GPIO_82"),
-	PINCTRL_PIN(83, "GPIO_83"),
-	PINCTRL_PIN(84, "GPIO_84"),
-	PINCTRL_PIN(85, "GPIO_85"),
-	PINCTRL_PIN(86, "GPIO_86"),
-	PINCTRL_PIN(87, "GPIO_87"),
-	PINCTRL_PIN(88, "GPIO_88"),
-	PINCTRL_PIN(89, "GPIO_89"),
-
-	PINCTRL_PIN(90, "SDC1_CLK"),
-	PINCTRL_PIN(91, "SDC1_CMD"),
-	PINCTRL_PIN(92, "SDC1_DATA"),
-	PINCTRL_PIN(93, "SDC3_CLK"),
-	PINCTRL_PIN(94, "SDC3_CMD"),
-	PINCTRL_PIN(95, "SDC3_DATA"),
-};
-
-#define DECLARE_APQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
-DECLARE_APQ_GPIO_PINS(0);
-DECLARE_APQ_GPIO_PINS(1);
-DECLARE_APQ_GPIO_PINS(2);
-DECLARE_APQ_GPIO_PINS(3);
-DECLARE_APQ_GPIO_PINS(4);
-DECLARE_APQ_GPIO_PINS(5);
-DECLARE_APQ_GPIO_PINS(6);
-DECLARE_APQ_GPIO_PINS(7);
-DECLARE_APQ_GPIO_PINS(8);
-DECLARE_APQ_GPIO_PINS(9);
-DECLARE_APQ_GPIO_PINS(10);
-DECLARE_APQ_GPIO_PINS(11);
-DECLARE_APQ_GPIO_PINS(12);
-DECLARE_APQ_GPIO_PINS(13);
-DECLARE_APQ_GPIO_PINS(14);
-DECLARE_APQ_GPIO_PINS(15);
-DECLARE_APQ_GPIO_PINS(16);
-DECLARE_APQ_GPIO_PINS(17);
-DECLARE_APQ_GPIO_PINS(18);
-DECLARE_APQ_GPIO_PINS(19);
-DECLARE_APQ_GPIO_PINS(20);
-DECLARE_APQ_GPIO_PINS(21);
-DECLARE_APQ_GPIO_PINS(22);
-DECLARE_APQ_GPIO_PINS(23);
-DECLARE_APQ_GPIO_PINS(24);
-DECLARE_APQ_GPIO_PINS(25);
-DECLARE_APQ_GPIO_PINS(26);
-DECLARE_APQ_GPIO_PINS(27);
-DECLARE_APQ_GPIO_PINS(28);
-DECLARE_APQ_GPIO_PINS(29);
-DECLARE_APQ_GPIO_PINS(30);
-DECLARE_APQ_GPIO_PINS(31);
-DECLARE_APQ_GPIO_PINS(32);
-DECLARE_APQ_GPIO_PINS(33);
-DECLARE_APQ_GPIO_PINS(34);
-DECLARE_APQ_GPIO_PINS(35);
-DECLARE_APQ_GPIO_PINS(36);
-DECLARE_APQ_GPIO_PINS(37);
-DECLARE_APQ_GPIO_PINS(38);
-DECLARE_APQ_GPIO_PINS(39);
-DECLARE_APQ_GPIO_PINS(40);
-DECLARE_APQ_GPIO_PINS(41);
-DECLARE_APQ_GPIO_PINS(42);
-DECLARE_APQ_GPIO_PINS(43);
-DECLARE_APQ_GPIO_PINS(44);
-DECLARE_APQ_GPIO_PINS(45);
-DECLARE_APQ_GPIO_PINS(46);
-DECLARE_APQ_GPIO_PINS(47);
-DECLARE_APQ_GPIO_PINS(48);
-DECLARE_APQ_GPIO_PINS(49);
-DECLARE_APQ_GPIO_PINS(50);
-DECLARE_APQ_GPIO_PINS(51);
-DECLARE_APQ_GPIO_PINS(52);
-DECLARE_APQ_GPIO_PINS(53);
-DECLARE_APQ_GPIO_PINS(54);
-DECLARE_APQ_GPIO_PINS(55);
-DECLARE_APQ_GPIO_PINS(56);
-DECLARE_APQ_GPIO_PINS(57);
-DECLARE_APQ_GPIO_PINS(58);
-DECLARE_APQ_GPIO_PINS(59);
-DECLARE_APQ_GPIO_PINS(60);
-DECLARE_APQ_GPIO_PINS(61);
-DECLARE_APQ_GPIO_PINS(62);
-DECLARE_APQ_GPIO_PINS(63);
-DECLARE_APQ_GPIO_PINS(64);
-DECLARE_APQ_GPIO_PINS(65);
-DECLARE_APQ_GPIO_PINS(66);
-DECLARE_APQ_GPIO_PINS(67);
-DECLARE_APQ_GPIO_PINS(68);
-DECLARE_APQ_GPIO_PINS(69);
-DECLARE_APQ_GPIO_PINS(70);
-DECLARE_APQ_GPIO_PINS(71);
-DECLARE_APQ_GPIO_PINS(72);
-DECLARE_APQ_GPIO_PINS(73);
-DECLARE_APQ_GPIO_PINS(74);
-DECLARE_APQ_GPIO_PINS(75);
-DECLARE_APQ_GPIO_PINS(76);
-DECLARE_APQ_GPIO_PINS(77);
-DECLARE_APQ_GPIO_PINS(78);
-DECLARE_APQ_GPIO_PINS(79);
-DECLARE_APQ_GPIO_PINS(80);
-DECLARE_APQ_GPIO_PINS(81);
-DECLARE_APQ_GPIO_PINS(82);
-DECLARE_APQ_GPIO_PINS(83);
-DECLARE_APQ_GPIO_PINS(84);
-DECLARE_APQ_GPIO_PINS(85);
-DECLARE_APQ_GPIO_PINS(86);
-DECLARE_APQ_GPIO_PINS(87);
-DECLARE_APQ_GPIO_PINS(88);
-DECLARE_APQ_GPIO_PINS(89);
-
-static const unsigned int sdc1_clk_pins[] = { 90 };
-static const unsigned int sdc1_cmd_pins[] = { 91 };
-static const unsigned int sdc1_data_pins[] = { 92 };
-static const unsigned int sdc3_clk_pins[] = { 93 };
-static const unsigned int sdc3_cmd_pins[] = { 94 };
-static const unsigned int sdc3_data_pins[] = { 95 };
-
-#define FUNCTION(fname)					\
-	[APQ_MUX_##fname] = {				\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
-	{						\
-		.name = "gpio" #id,			\
-		.pins = gpio##id##_pins,		\
-		.npins = ARRAY_SIZE(gpio##id##_pins),	\
-		.funcs = (int[]){			\
-			APQ_MUX_NA, /* gpio mode */	\
-			APQ_MUX_##f1,			\
-			APQ_MUX_##f2,			\
-			APQ_MUX_##f3,			\
-			APQ_MUX_##f4,			\
-			APQ_MUX_##f5,			\
-			APQ_MUX_##f6,			\
-			APQ_MUX_##f7,			\
-			APQ_MUX_##f8,			\
-			APQ_MUX_##f9,			\
-			APQ_MUX_##f10,			\
-		},					\
-		.nfuncs = 11,				\
-		.ctl_reg = 0x1000 + 0x10 * id,		\
-		.io_reg = 0x1004 + 0x10 * id,		\
-		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
-		.intr_status_reg = 0x100c + 0x10 * id,	\
-		.intr_target_reg = 0x400 + 0x4 * id,	\
-		.mux_bit = 2,				\
-		.pull_bit = 0,				\
-		.drv_bit = 6,				\
-		.oe_bit = 9,				\
-		.in_bit = 0,				\
-		.out_bit = 1,				\
-		.intr_enable_bit = 0,			\
-		.intr_status_bit = 0,			\
-		.intr_ack_high = 1,			\
-		.intr_target_bit = 0,			\
-		.intr_raw_status_bit = 3,		\
-		.intr_polarity_bit = 1,			\
-		.intr_detection_bit = 2,		\
-		.intr_detection_width = 1,		\
-	}
-
-#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
-	{						\
-		.name = #pg_name,			\
-		.pins = pg_name##_pins,			\
-		.npins = ARRAY_SIZE(pg_name##_pins),	\
-		.ctl_reg = ctl,				\
-		.io_reg = 0,				\
-		.intr_cfg_reg = 0,			\
-		.intr_status_reg = 0,			\
-		.intr_target_reg = 0,			\
-		.mux_bit = -1,				\
-		.pull_bit = pull,			\
-		.drv_bit = drv,				\
-		.oe_bit = -1,				\
-		.in_bit = -1,				\
-		.out_bit = -1,				\
-		.intr_enable_bit = -1,			\
-		.intr_status_bit = -1,			\
-		.intr_target_bit = -1,			\
-		.intr_raw_status_bit = -1,		\
-		.intr_polarity_bit = -1,		\
-		.intr_detection_bit = -1,		\
-		.intr_detection_width = -1,		\
-	}
-
-enum apq8064_functions {
-	APQ_MUX_cam_mclk,
-	APQ_MUX_codec_mic_i2s,
-	APQ_MUX_codec_spkr_i2s,
-	APQ_MUX_gsbi1,
-	APQ_MUX_gsbi2,
-	APQ_MUX_gsbi3,
-	APQ_MUX_gsbi4,
-	APQ_MUX_gsbi4_cam_i2c,
-	APQ_MUX_gsbi5,
-	APQ_MUX_gsbi5_spi_cs1,
-	APQ_MUX_gsbi5_spi_cs2,
-	APQ_MUX_gsbi5_spi_cs3,
-	APQ_MUX_gsbi6,
-	APQ_MUX_gsbi6_spi_cs1,
-	APQ_MUX_gsbi6_spi_cs2,
-	APQ_MUX_gsbi6_spi_cs3,
-	APQ_MUX_gsbi7,
-	APQ_MUX_gsbi7_spi_cs1,
-	APQ_MUX_gsbi7_spi_cs2,
-	APQ_MUX_gsbi7_spi_cs3,
-	APQ_MUX_gsbi_cam_i2c,
-	APQ_MUX_hdmi,
-	APQ_MUX_mi2s,
-	APQ_MUX_riva_bt,
-	APQ_MUX_riva_fm,
-	APQ_MUX_riva_wlan,
-	APQ_MUX_sdc2,
-	APQ_MUX_sdc4,
-	APQ_MUX_slimbus,
-	APQ_MUX_spkr_i2s,
-	APQ_MUX_tsif1,
-	APQ_MUX_tsif2,
-	APQ_MUX_usb2_hsic,
-	APQ_MUX_NA,
-};
-
-static const char * const cam_mclk_groups[] = {
-	"gpio4" "gpio5"
-};
-static const char * const codec_mic_i2s_groups[] = {
-	"gpio34", "gpio35", "gpio36", "gpio37", "gpio38"
-};
-static const char * const codec_spkr_i2s_groups[] = {
-	"gpio39", "gpio40", "gpio41", "gpio42"
-};
-static const char * const gsbi1_groups[] = {
-	"gpio18", "gpio19", "gpio20", "gpio21"
-};
-static const char * const gsbi2_groups[] = {
-	"gpio22", "gpio23", "gpio24", "gpio25"
-};
-static const char * const gsbi3_groups[] = {
-	"gpio6", "gpio7", "gpio8", "gpio9"
-};
-static const char * const gsbi4_groups[] = {
-	"gpio10", "gpio11", "gpio12", "gpio13"
-};
-static const char * const gsbi4_cam_i2c_groups[] = {
-	"gpio10", "gpio11", "gpio12", "gpio13"
-};
-static const char * const gsbi5_groups[] = {
-	"gpio51", "gpio52", "gpio53", "gpio54"
-};
-static const char * const gsbi5_spi_cs1_groups[] = {
-	"gpio47"
-};
-static const char * const gsbi5_spi_cs2_groups[] = {
-	"gpio31"
-};
-static const char * const gsbi5_spi_cs3_groups[] = {
-	"gpio32"
-};
-static const char * const gsbi6_groups[] = {
-	"gpio14", "gpio15", "gpio16", "gpio17"
-};
-static const char * const gsbi6_spi_cs1_groups[] = {
-	"gpio47"
-};
-static const char * const gsbi6_spi_cs2_groups[] = {
-	"gpio31"
-};
-static const char * const gsbi6_spi_cs3_groups[] = {
-	"gpio32"
-};
-static const char * const gsbi7_groups[] = {
-	"gpio82", "gpio83", "gpio84", "gpio85"
-};
-static const char * const gsbi7_spi_cs1_groups[] = {
-	"gpio47"
-};
-static const char * const gsbi7_spi_cs2_groups[] = {
-	"gpio31"
-};
-static const char * const gsbi7_spi_cs3_groups[] = {
-	"gpio32"
-};
-static const char * const gsbi_cam_i2c_groups[] = {
-	"gpio10", "gpio11", "gpio12", "gpio13"
-};
-static const char * const hdmi_groups[] = {
-	"gpio69", "gpio70", "gpio71", "gpio72"
-};
-static const char * const mi2s_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33"
-};
-static const char * const riva_bt_groups[] = {
-	"gpio16", "gpio17"
-};
-static const char * const riva_fm_groups[] = {
-	"gpio14", "gpio15"
-};
-static const char * const riva_wlan_groups[] = {
-	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
-};
-static const char * const sdc2_groups[] = {
-	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62"
-};
-static const char * const sdc4_groups[] = {
-	"gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
-};
-static const char * const slimbus_groups[] = {
-	"gpio40", "gpio41"
-};
-static const char * const spkr_i2s_groups[] = {
-	"gpio47", "gpio48", "gpio49", "gpio50"
-};
-static const char * const tsif1_groups[] = {
-	"gpio55", "gpio56", "gpio57"
-};
-static const char * const tsif2_groups[] = {
-	"gpio58", "gpio59", "gpio60"
-};
-static const char * const usb2_hsic_groups[] = {
-	"gpio88", "gpio89"
-};
-
-static const struct msm_function apq8064_functions[] = {
-	FUNCTION(cam_mclk),
-	FUNCTION(codec_mic_i2s),
-	FUNCTION(codec_spkr_i2s),
-	FUNCTION(gsbi1),
-	FUNCTION(gsbi2),
-	FUNCTION(gsbi3),
-	FUNCTION(gsbi4),
-	FUNCTION(gsbi4_cam_i2c),
-	FUNCTION(gsbi5),
-	FUNCTION(gsbi5_spi_cs1),
-	FUNCTION(gsbi5_spi_cs2),
-	FUNCTION(gsbi5_spi_cs3),
-	FUNCTION(gsbi6),
-	FUNCTION(gsbi6_spi_cs1),
-	FUNCTION(gsbi6_spi_cs2),
-	FUNCTION(gsbi6_spi_cs3),
-	FUNCTION(gsbi7),
-	FUNCTION(gsbi7_spi_cs1),
-	FUNCTION(gsbi7_spi_cs2),
-	FUNCTION(gsbi7_spi_cs3),
-	FUNCTION(gsbi_cam_i2c),
-	FUNCTION(hdmi),
-	FUNCTION(mi2s),
-	FUNCTION(riva_bt),
-	FUNCTION(riva_fm),
-	FUNCTION(riva_wlan),
-	FUNCTION(sdc2),
-	FUNCTION(sdc4),
-	FUNCTION(slimbus),
-	FUNCTION(spkr_i2s),
-	FUNCTION(tsif1),
-	FUNCTION(tsif2),
-	FUNCTION(usb2_hsic),
-};
-
-static const struct msm_pingroup apq8064_groups[] = {
-	PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(4, NA, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(5, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(6, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(7, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(8, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(9, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(10, gsbi4, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c, NA),
-	PINGROUP(11, gsbi4, NA, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c),
-	PINGROUP(12, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
-	PINGROUP(13, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
-	PINGROUP(14, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(15, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(16, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(17, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(18, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(19, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(20, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(21, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(22, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(27, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(28, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(29, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(30, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(31, mi2s, NA, gsbi5_spi_cs2, gsbi6_spi_cs2, gsbi7_spi_cs2, NA, NA, NA, NA, NA),
-	PINGROUP(32, mi2s, NA, NA, NA, NA, gsbi5_spi_cs3, gsbi6_spi_cs3, gsbi7_spi_cs3, NA, NA),
-	PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(34, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(35, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(36, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(37, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(38, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(39, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(40, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(41, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(42, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(47, spkr_i2s, gsbi5_spi_cs1, gsbi6_spi_cs1, gsbi7_spi_cs1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(48, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(49, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(50, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(51, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(52, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(53, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(54, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(55, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(56, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(57, tsif1, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(58, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(59, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(60, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(61, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(62, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(63, NA, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(64, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(65, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(66, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(67, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(68, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(69, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(70, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(71, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(72, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(82, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(83, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(84, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(85, NA, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(88, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(89, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-
-	SDC_PINGROUP(sdc1_clk, 0x20a0, 13, 6),
-	SDC_PINGROUP(sdc1_cmd, 0x20a0, 11, 3),
-	SDC_PINGROUP(sdc1_data, 0x20a0, 9, 0),
-
-	SDC_PINGROUP(sdc3_clk, 0x20a4, 14, 6),
-	SDC_PINGROUP(sdc3_cmd, 0x20a4, 11, 3),
-	SDC_PINGROUP(sdc3_data, 0x20a4, 9, 0),
-};
-
-#define NUM_GPIO_PINGROUPS 90
-
-static const struct msm_pinctrl_soc_data apq8064_pinctrl = {
-	.pins = apq8064_pins,
-	.npins = ARRAY_SIZE(apq8064_pins),
-	.functions = apq8064_functions,
-	.nfunctions = ARRAY_SIZE(apq8064_functions),
-	.groups = apq8064_groups,
-	.ngroups = ARRAY_SIZE(apq8064_groups),
-	.ngpios = NUM_GPIO_PINGROUPS,
-};
-
-static int apq8064_pinctrl_probe(struct platform_device *pdev)
-{
-	return msm_pinctrl_probe(pdev, &apq8064_pinctrl);
-}
-
-static const struct of_device_id apq8064_pinctrl_of_match[] = {
-	{ .compatible = "qcom,apq8064-pinctrl", },
-	{ },
-};
-
-static struct platform_driver apq8064_pinctrl_driver = {
-	.driver = {
-		.name = "apq8064-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = apq8064_pinctrl_of_match,
-	},
-	.probe = apq8064_pinctrl_probe,
-	.remove = msm_pinctrl_remove,
-};
-
-static int __init apq8064_pinctrl_init(void)
-{
-	return platform_driver_register(&apq8064_pinctrl_driver);
-}
-arch_initcall(apq8064_pinctrl_init);
-
-static void __exit apq8064_pinctrl_exit(void)
-{
-	platform_driver_unregister(&apq8064_pinctrl_driver);
-}
-module_exit(apq8064_pinctrl_exit);
-
-MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
-MODULE_DESCRIPTION("Qualcomm APQ8064 pinctrl driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, apq8064_pinctrl_of_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-as3722.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-as3722.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-as3722.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-as3722.c	2014-09-28 17:29:07.000000000 -0400
@@ -565,7 +565,6 @@ static int as3722_pinctrl_probe(struct p
 {
 	struct as3722_pctrl_info *as_pci;
 	int ret;
-	int tret;
 
 	as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL);
 	if (!as_pci)
@@ -611,10 +610,7 @@ static int as3722_pinctrl_probe(struct p
 	return 0;
 
 fail_range_add:
-	tret = gpiochip_remove(&as_pci->gpio_chip);
-	if (tret < 0)
-		dev_warn(&pdev->dev, "Couldn't remove gpio chip, %d\n", tret);
-
+	gpiochip_remove(&as_pci->gpio_chip);
 fail_chip_add:
 	pinctrl_unregister(as_pci->pctl);
 	return ret;
@@ -623,11 +619,8 @@ fail_chip_add:
 static int as3722_pinctrl_remove(struct platform_device *pdev)
 {
 	struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = gpiochip_remove(&as_pci->gpio_chip);
-	if (ret < 0)
-		return ret;
+	gpiochip_remove(&as_pci->gpio_chip);
 	pinctrl_unregister(as_pci->pctl);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-at91.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-at91.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-at91.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-at91.c	2014-09-28 17:29:07.000000000 -0400
@@ -497,10 +497,10 @@ static struct at91_pinctrl_mux_ops at91s
 static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
 {
 	if (pin->mux) {
-		dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
+		dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lx\n",
 			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
 	} else {
-		dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
+		dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lx\n",
 			pin->bank + 'A', pin->pin, pin->conf);
 	}
 }
@@ -611,26 +611,6 @@ static int at91_pmx_enable(struct pinctr
 	return 0;
 }
 
-static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
-			   unsigned group)
-{
-	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-	const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
-	const struct at91_pmx_pin *pin;
-	uint32_t npins = info->groups[group].npins;
-	int i;
-	unsigned mask;
-	void __iomem *pio;
-
-	for (i = 0; i < npins; i++) {
-		pin = &pins_conf[i];
-		at91_pin_dbg(info->dev, pin);
-		pio = pin_to_controller(info, pin->bank);
-		mask = pin_to_mask(pin->pin);
-		at91_mux_gpio_enable(pio, mask, 1);
-	}
-}
-
 static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
 {
 	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
@@ -705,7 +685,6 @@ static const struct pinmux_ops at91_pmx_
 	.get_function_name	= at91_pmx_get_func_name,
 	.get_function_groups	= at91_pmx_get_groups,
 	.enable			= at91_pmx_enable,
-	.disable		= at91_pmx_disable,
 	.gpio_request_enable	= at91_gpio_request_enable,
 	.gpio_disable_free	= at91_gpio_disable_free,
 };
@@ -793,9 +772,9 @@ static void at91_pinconf_dbg_show(struct
 				   struct seq_file *s, unsigned pin_id)
 {
 	unsigned long config;
-	int ret, val, num_conf = 0;
+	int val, num_conf = 0;
 
-	ret = at91_pinconf_get(pctldev, pin_id, &config);
+	at91_pinconf_get(pctldev, pin_id, &config);
 
 	DBG_SHOW_FLAG(MULTI_DRIVE);
 	DBG_SHOW_FLAG(PULL_UP);
@@ -945,7 +924,7 @@ static int at91_pinctrl_parse_functions(
 	/* Initialise function */
 	func->name = np->name;
 	func->ngroups = of_get_child_count(np);
-	if (func->ngroups <= 0) {
+	if (func->ngroups == 0) {
 		dev_err(info->dev, "no groups defined\n");
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-baytrail.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-baytrail.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-baytrail.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-baytrail.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,9 +25,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/irqdomain.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
 #include <linux/seq_file.h>
@@ -44,6 +42,7 @@
 
 /* BYT_CONF0_REG register bits */
 #define BYT_IODEN		BIT(31)
+#define BYT_DIRECT_IRQ_EN	BIT(27)
 #define BYT_TRIG_NEG		BIT(26)
 #define BYT_TRIG_POS		BIT(25)
 #define BYT_TRIG_LVL		BIT(24)
@@ -137,7 +136,6 @@ static struct pinctrl_gpio_range byt_ran
 
 struct byt_gpio {
 	struct gpio_chip		chip;
-	struct irq_domain		*domain;
 	struct platform_device		*pdev;
 	spinlock_t			lock;
 	void __iomem			*reg_base;
@@ -217,7 +215,7 @@ static void byt_gpio_free(struct gpio_ch
 
 static int byt_irq_type(struct irq_data *d, unsigned type)
 {
-	struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
+	struct byt_gpio *vg = to_byt_gpio(irq_data_get_irq_chip_data(d));
 	u32 offset = irqd_to_hwirq(d);
 	u32 value;
 	unsigned long flags;
@@ -303,12 +301,22 @@ static int byt_gpio_direction_output(str
 				     unsigned gpio, int value)
 {
 	struct byt_gpio *vg = to_byt_gpio(chip);
+	void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG);
 	void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
 	unsigned long flags;
 	u32 reg_val;
 
 	spin_lock_irqsave(&vg->lock, flags);
 
+	/*
+	 * Before making any direction modifications, do a check if gpio
+	 * is set for direct IRQ.  On baytrail, setting GPIO to output does
+	 * not make sense, so let's at least warn the caller before they shoot
+	 * themselves in the foot.
+	 */
+	WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
+		"Potential Error: Setting GPIO with direct_irq_en to output");
+
 	reg_val = readl(reg) | BYT_DIR_MASK;
 	reg_val &= ~BYT_OUTPUT_EN;
 
@@ -393,16 +401,10 @@ static void byt_gpio_dbg_show(struct seq
 	spin_unlock_irqrestore(&vg->lock, flags);
 }
 
-static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct byt_gpio *vg = to_byt_gpio(chip);
-	return irq_create_mapping(vg->domain, offset);
-}
-
 static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
+	struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	u32 base, pin, mask;
 	void __iomem *reg;
@@ -421,7 +423,7 @@ static void byt_gpio_irq_handler(unsigne
 			/* Clear before handling so we can't lose an edge */
 			writel(mask, reg);
 
-			virq = irq_find_mapping(vg->domain, base + pin);
+			virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
 			generic_handle_irq(virq);
 
 			/* In case bios or user sets triggering incorretly a pin
@@ -454,33 +456,12 @@ static void byt_irq_mask(struct irq_data
 {
 }
 
-static int byt_irq_reqres(struct irq_data *d)
-{
-	struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
-
-	if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) {
-		dev_err(vg->chip.dev,
-			"unable to lock HW IRQ %lu for IRQ\n",
-			irqd_to_hwirq(d));
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void byt_irq_relres(struct irq_data *d)
-{
-	struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
-
-	gpio_unlock_as_irq(&vg->chip, irqd_to_hwirq(d));
-}
-
 static struct irq_chip byt_irqchip = {
 	.name = "BYT-GPIO",
 	.irq_mask = byt_irq_mask,
 	.irq_unmask = byt_irq_unmask,
 	.irq_set_type = byt_irq_type,
-	.irq_request_resources = byt_irq_reqres,
-	.irq_release_resources = byt_irq_relres,
+	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
 static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
@@ -501,23 +482,6 @@ static void byt_gpio_irq_init_hw(struct
 	}
 }
 
-static int byt_gpio_irq_map(struct irq_domain *d, unsigned int virq,
-			    irq_hw_number_t hw)
-{
-	struct byt_gpio *vg = d->host_data;
-
-	irq_set_chip_and_handler_name(virq, &byt_irqchip, handle_simple_irq,
-				      "demux");
-	irq_set_chip_data(virq, vg);
-	irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
-	return 0;
-}
-
-static const struct irq_domain_ops byt_gpio_irq_ops = {
-	.map = byt_gpio_irq_map,
-};
-
 static int byt_gpio_probe(struct platform_device *pdev)
 {
 	struct byt_gpio *vg;
@@ -527,7 +491,6 @@ static int byt_gpio_probe(struct platfor
 	struct acpi_device *acpi_dev;
 	struct pinctrl_gpio_range *range;
 	acpi_handle handle = ACPI_HANDLE(dev);
-	unsigned hwirq;
 	int ret;
 
 	if (acpi_bus_get_device(handle, &acpi_dev))
@@ -574,27 +537,27 @@ static int byt_gpio_probe(struct platfor
 	gc->can_sleep = false;
 	gc->dev = dev;
 
+	ret = gpiochip_add(gc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
+		return ret;
+	}
+
 	/* set up interrupts  */
 	irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (irq_rc && irq_rc->start) {
-		hwirq = irq_rc->start;
-		gc->to_irq = byt_gpio_to_irq;
-
-		vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
-						   &byt_gpio_irq_ops, vg);
-		if (!vg->domain)
-			return -ENXIO;
-
 		byt_gpio_irq_init_hw(vg);
+		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
+					   handle_simple_irq, IRQ_TYPE_NONE);
+		if (ret) {
+			dev_err(dev, "failed to add irqchip\n");
+			gpiochip_remove(gc);
+			return ret;
+		}
 
-		irq_set_handler_data(hwirq, vg);
-		irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
-	}
-
-	ret = gpiochip_add(gc);
-	if (ret) {
-		dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
-		return ret;
+		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
+					     (unsigned)irq_rc->start,
+					     byt_gpio_irq_handler);
 	}
 
 	pm_runtime_enable(dev);
@@ -627,12 +590,9 @@ MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_
 static int byt_gpio_remove(struct platform_device *pdev)
 {
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
-	int err;
 
 	pm_runtime_disable(&pdev->dev);
-	err = gpiochip_remove(&vg->chip);
-	if (err)
-		dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
+	gpiochip_remove(&vg->chip);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-bcm281xx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-bcm281xx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-bcm281xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-bcm281xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1396,7 +1396,7 @@ static struct pinctrl_desc bcm281xx_pinc
 	.owner = THIS_MODULE,
 };
 
-int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
+static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 {
 	struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
 	struct resource *res;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-bcm2835.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-bcm2835.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-bcm2835.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-bcm2835.c	2014-09-28 17:29:07.000000000 -0400
@@ -841,16 +841,6 @@ static int bcm2835_pmx_enable(struct pin
 	return 0;
 }
 
-static void bcm2835_pmx_disable(struct pinctrl_dev *pctldev,
-		unsigned func_selector,
-		unsigned group_selector)
-{
-	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-
-	/* disable by setting to GPIO_IN */
-	bcm2835_pinctrl_fsel_set(pc, group_selector, BCM2835_FSEL_GPIO_IN);
-}
-
 static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
 		struct pinctrl_gpio_range *range,
 		unsigned offset)
@@ -880,7 +870,6 @@ static const struct pinmux_ops bcm2835_p
 	.get_function_name = bcm2835_pmx_get_function_name,
 	.get_function_groups = bcm2835_pmx_get_function_groups,
 	.enable = bcm2835_pmx_enable,
-	.disable = bcm2835_pmx_disable,
 	.gpio_disable_free = bcm2835_pmx_gpio_disable_free,
 	.gpio_set_direction = bcm2835_pmx_gpio_set_direction,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-coh901.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-coh901.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-coh901.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-coh901.c	2014-09-28 17:29:07.000000000 -0400
@@ -756,8 +756,7 @@ static int __init u300_gpio_probe(struct
 
 err_no_range:
 err_no_irqchip:
-	if (gpiochip_remove(&gpio->chip))
-		dev_err(&pdev->dev, "failed to remove gpio chip\n");
+	gpiochip_remove(&gpio->chip);
 err_no_chip:
 	clk_disable_unprepare(gpio->clk);
 	dev_err(&pdev->dev, "module ERROR:%d\n", err);
@@ -767,16 +766,11 @@ err_no_chip:
 static int __exit u300_gpio_remove(struct platform_device *pdev)
 {
 	struct u300_gpio *gpio = platform_get_drvdata(pdev);
-	int err;
 
 	/* Turn off the GPIO block */
 	writel(0x00000000U, gpio->base + U300_GPIO_CR);
 
-	err = gpiochip_remove(&gpio->chip);
-	if (err < 0) {
-		dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
-		return err;
-	}
+	gpiochip_remove(&gpio->chip);
 	clk_disable_unprepare(gpio->clk);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos5440.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos5440.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos5440.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos5440.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1069 +0,0 @@
-/*
- * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include "core.h"
-
-/* EXYNOS5440 GPIO and Pinctrl register offsets */
-#define GPIO_MUX		0x00
-#define GPIO_IE			0x04
-#define GPIO_INT		0x08
-#define GPIO_TYPE		0x0C
-#define GPIO_VAL		0x10
-#define GPIO_OE			0x14
-#define GPIO_IN			0x18
-#define GPIO_PE			0x1C
-#define GPIO_PS			0x20
-#define GPIO_SR			0x24
-#define GPIO_DS0		0x28
-#define GPIO_DS1		0x2C
-
-#define EXYNOS5440_MAX_PINS		23
-#define EXYNOS5440_MAX_GPIO_INT	8
-#define PIN_NAME_LENGTH		10
-
-#define GROUP_SUFFIX		"-grp"
-#define GSUFFIX_LEN		sizeof(GROUP_SUFFIX)
-#define FUNCTION_SUFFIX		"-mux"
-#define FSUFFIX_LEN		sizeof(FUNCTION_SUFFIX)
-
-/*
- * pin configuration type and its value are packed together into a 16-bits.
- * The upper 8-bits represent the configuration type and the lower 8-bits
- * hold the value of the configuration type.
- */
-#define PINCFG_TYPE_MASK		0xFF
-#define PINCFG_VALUE_SHIFT		8
-#define PINCFG_VALUE_MASK		(0xFF << PINCFG_VALUE_SHIFT)
-#define PINCFG_PACK(type, value)	(((value) << PINCFG_VALUE_SHIFT) | type)
-#define PINCFG_UNPACK_TYPE(cfg)		((cfg) & PINCFG_TYPE_MASK)
-#define PINCFG_UNPACK_VALUE(cfg)	(((cfg) & PINCFG_VALUE_MASK) >> \
-						PINCFG_VALUE_SHIFT)
-
-/**
- * enum pincfg_type - possible pin configuration types supported.
- * @PINCFG_TYPE_PUD: Pull up/down configuration.
- * @PINCFG_TYPE_DRV: Drive strength configuration.
- * @PINCFG_TYPE_SKEW_RATE: Skew rate configuration.
- * @PINCFG_TYPE_INPUT_TYPE: Pin input type configuration.
- */
-enum pincfg_type {
-	PINCFG_TYPE_PUD,
-	PINCFG_TYPE_DRV,
-	PINCFG_TYPE_SKEW_RATE,
-	PINCFG_TYPE_INPUT_TYPE
-};
-
-/**
- * struct exynos5440_pin_group: represent group of pins for pincfg setting.
- * @name: name of the pin group, used to lookup the group.
- * @pins: the pins included in this group.
- * @num_pins: number of pins included in this group.
- */
-struct exynos5440_pin_group {
-	const char		*name;
-	const unsigned int	*pins;
-	u8			num_pins;
-};
-
-/**
- * struct exynos5440_pmx_func: represent a pin function.
- * @name: name of the pin function, used to lookup the function.
- * @groups: one or more names of pin groups that provide this function.
- * @num_groups: number of groups included in @groups.
- * @function: the function number to be programmed when selected.
- */
-struct exynos5440_pmx_func {
-	const char		*name;
-	const char		**groups;
-	u8			num_groups;
-	unsigned long		function;
-};
-
-/**
- * struct exynos5440_pinctrl_priv_data: driver's private runtime data.
- * @reg_base: ioremapped based address of the register space.
- * @gc: gpio chip registered with gpiolib.
- * @pin_groups: list of pin groups parsed from device tree.
- * @nr_groups: number of pin groups available.
- * @pmx_functions: list of pin functions parsed from device tree.
- * @nr_functions: number of pin functions available.
- */
-struct exynos5440_pinctrl_priv_data {
-	void __iomem			*reg_base;
-	struct gpio_chip		*gc;
-	struct irq_domain		*irq_domain;
-
-	const struct exynos5440_pin_group	*pin_groups;
-	unsigned int			nr_groups;
-	const struct exynos5440_pmx_func	*pmx_functions;
-	unsigned int			nr_functions;
-};
-
-/**
- * struct exynos5440_gpio_intr_data: private data for gpio interrupts.
- * @priv: driver's private runtime data.
- * @gpio_int: gpio interrupt number.
- */
-struct exynos5440_gpio_intr_data {
-	struct exynos5440_pinctrl_priv_data	*priv;
-	unsigned int				gpio_int;
-};
-
-/* list of all possible config options supported */
-static struct pin_config {
-	char		*prop_cfg;
-	unsigned int	cfg_type;
-} pcfgs[] = {
-	{ "samsung,exynos5440-pin-pud", PINCFG_TYPE_PUD },
-	{ "samsung,exynos5440-pin-drv", PINCFG_TYPE_DRV },
-	{ "samsung,exynos5440-pin-skew-rate", PINCFG_TYPE_SKEW_RATE },
-	{ "samsung,exynos5440-pin-input-type", PINCFG_TYPE_INPUT_TYPE },
-};
-
-/* check if the selector is a valid pin group selector */
-static int exynos5440_get_group_count(struct pinctrl_dev *pctldev)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	return priv->nr_groups;
-}
-
-/* return the name of the group selected by the group selector */
-static const char *exynos5440_get_group_name(struct pinctrl_dev *pctldev,
-						unsigned selector)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	return priv->pin_groups[selector].name;
-}
-
-/* return the pin numbers associated with the specified group */
-static int exynos5440_get_group_pins(struct pinctrl_dev *pctldev,
-		unsigned selector, const unsigned **pins, unsigned *num_pins)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	*pins = priv->pin_groups[selector].pins;
-	*num_pins = priv->pin_groups[selector].num_pins;
-	return 0;
-}
-
-/* create pinctrl_map entries by parsing device tree nodes */
-static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
-			struct device_node *np, struct pinctrl_map **maps,
-			unsigned *nmaps)
-{
-	struct device *dev = pctldev->dev;
-	struct pinctrl_map *map;
-	unsigned long *cfg = NULL;
-	char *gname, *fname;
-	int cfg_cnt = 0, map_cnt = 0, idx = 0;
-
-	/* count the number of config options specfied in the node */
-	for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++)
-		if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
-			cfg_cnt++;
-
-	/*
-	 * Find out the number of map entries to create. All the config options
-	 * can be accomadated into a single config map entry.
-	 */
-	if (cfg_cnt)
-		map_cnt = 1;
-	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL))
-		map_cnt++;
-	if (!map_cnt) {
-		dev_err(dev, "node %s does not have either config or function "
-				"configurations\n", np->name);
-		return -EINVAL;
-	}
-
-	/* Allocate memory for pin-map entries */
-	map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
-	if (!map) {
-		dev_err(dev, "could not alloc memory for pin-maps\n");
-		return -ENOMEM;
-	}
-	*nmaps = 0;
-
-	/*
-	 * Allocate memory for pin group name. The pin group name is derived
-	 * from the node name from which these map entries are be created.
-	 */
-	gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
-	if (!gname) {
-		dev_err(dev, "failed to alloc memory for group name\n");
-		goto free_map;
-	}
-	snprintf(gname, strlen(np->name) + 4, "%s%s", np->name, GROUP_SUFFIX);
-
-	/*
-	 * don't have config options? then skip over to creating function
-	 * map entries.
-	 */
-	if (!cfg_cnt)
-		goto skip_cfgs;
-
-	/* Allocate memory for config entries */
-	cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
-	if (!cfg) {
-		dev_err(dev, "failed to alloc memory for configs\n");
-		goto free_gname;
-	}
-
-	/* Prepare a list of config settings */
-	for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
-		u32 value;
-		if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
-			cfg[cfg_cnt++] =
-				PINCFG_PACK(pcfgs[idx].cfg_type, value);
-	}
-
-	/* create the config map entry */
-	map[*nmaps].data.configs.group_or_pin = gname;
-	map[*nmaps].data.configs.configs = cfg;
-	map[*nmaps].data.configs.num_configs = cfg_cnt;
-	map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
-	*nmaps += 1;
-
-skip_cfgs:
-	/* create the function map entry */
-	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) {
-		fname = kzalloc(strlen(np->name) + FSUFFIX_LEN,	GFP_KERNEL);
-		if (!fname) {
-			dev_err(dev, "failed to alloc memory for func name\n");
-			goto free_cfg;
-		}
-		snprintf(fname, strlen(np->name) + 4, "%s%s", np->name,
-			 FUNCTION_SUFFIX);
-
-		map[*nmaps].data.mux.group = gname;
-		map[*nmaps].data.mux.function = fname;
-		map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
-		*nmaps += 1;
-	}
-
-	*maps = map;
-	return 0;
-
-free_cfg:
-	kfree(cfg);
-free_gname:
-	kfree(gname);
-free_map:
-	kfree(map);
-	return -ENOMEM;
-}
-
-/* free the memory allocated to hold the pin-map table */
-static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
-			     struct pinctrl_map *map, unsigned num_maps)
-{
-	int idx;
-
-	for (idx = 0; idx < num_maps; idx++) {
-		if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
-			kfree(map[idx].data.mux.function);
-			if (!idx)
-				kfree(map[idx].data.mux.group);
-		} else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
-			kfree(map[idx].data.configs.configs);
-			if (!idx)
-				kfree(map[idx].data.configs.group_or_pin);
-		}
-	};
-
-	kfree(map);
-}
-
-/* list of pinctrl callbacks for the pinctrl core */
-static const struct pinctrl_ops exynos5440_pctrl_ops = {
-	.get_groups_count	= exynos5440_get_group_count,
-	.get_group_name		= exynos5440_get_group_name,
-	.get_group_pins		= exynos5440_get_group_pins,
-	.dt_node_to_map		= exynos5440_dt_node_to_map,
-	.dt_free_map		= exynos5440_dt_free_map,
-};
-
-/* check if the selector is a valid pin function selector */
-static int exynos5440_get_functions_count(struct pinctrl_dev *pctldev)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	return priv->nr_functions;
-}
-
-/* return the name of the pin function specified */
-static const char *exynos5440_pinmux_get_fname(struct pinctrl_dev *pctldev,
-						unsigned selector)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	return priv->pmx_functions[selector].name;
-}
-
-/* return the groups associated for the specified function selector */
-static int exynos5440_pinmux_get_groups(struct pinctrl_dev *pctldev,
-		unsigned selector, const char * const **groups,
-		unsigned * const num_groups)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	*groups = priv->pmx_functions[selector].groups;
-	*num_groups = priv->pmx_functions[selector].num_groups;
-	return 0;
-}
-
-/* enable or disable a pinmux function */
-static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
-					unsigned group, bool enable)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-	void __iomem *base;
-	u32 function;
-	u32 data;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	base = priv->reg_base;
-	function = priv->pmx_functions[selector].function;
-
-	data = readl(base + GPIO_MUX);
-	if (enable)
-		data |= (1 << function);
-	else
-		data &= ~(1 << function);
-	writel(data, base + GPIO_MUX);
-}
-
-/* enable a specified pinmux by writing to registers */
-static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
-					unsigned group)
-{
-	exynos5440_pinmux_setup(pctldev, selector, group, true);
-	return 0;
-}
-
-/* disable a specified pinmux by writing to registers */
-static void exynos5440_pinmux_disable(struct pinctrl_dev *pctldev,
-					unsigned selector, unsigned group)
-{
-	exynos5440_pinmux_setup(pctldev, selector, group, false);
-}
-
-/*
- * The calls to gpio_direction_output() and gpio_direction_input()
- * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
- * function called from the gpiolib interface).
- */
-static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
-		struct pinctrl_gpio_range *range, unsigned offset, bool input)
-{
-	return 0;
-}
-
-/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static const struct pinmux_ops exynos5440_pinmux_ops = {
-	.get_functions_count	= exynos5440_get_functions_count,
-	.get_function_name	= exynos5440_pinmux_get_fname,
-	.get_function_groups	= exynos5440_pinmux_get_groups,
-	.enable			= exynos5440_pinmux_enable,
-	.disable		= exynos5440_pinmux_disable,
-	.gpio_set_direction	= exynos5440_pinmux_gpio_set_direction,
-};
-
-/* set the pin config settings for a specified pin */
-static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-				unsigned long *configs,
-				unsigned num_configs)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-	void __iomem *base;
-	enum pincfg_type cfg_type;
-	u32 cfg_value;
-	u32 data;
-	int i;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	base = priv->reg_base;
-
-	for (i = 0; i < num_configs; i++) {
-		cfg_type = PINCFG_UNPACK_TYPE(configs[i]);
-		cfg_value = PINCFG_UNPACK_VALUE(configs[i]);
-
-		switch (cfg_type) {
-		case PINCFG_TYPE_PUD:
-			/* first set pull enable/disable bit */
-			data = readl(base + GPIO_PE);
-			data &= ~(1 << pin);
-			if (cfg_value)
-				data |= (1 << pin);
-			writel(data, base + GPIO_PE);
-
-			/* then set pull up/down bit */
-			data = readl(base + GPIO_PS);
-			data &= ~(1 << pin);
-			if (cfg_value == 2)
-				data |= (1 << pin);
-			writel(data, base + GPIO_PS);
-			break;
-
-		case PINCFG_TYPE_DRV:
-			/* set the first bit of the drive strength */
-			data = readl(base + GPIO_DS0);
-			data &= ~(1 << pin);
-			data |= ((cfg_value & 1) << pin);
-			writel(data, base + GPIO_DS0);
-			cfg_value >>= 1;
-
-			/* set the second bit of the driver strength */
-			data = readl(base + GPIO_DS1);
-			data &= ~(1 << pin);
-			data |= ((cfg_value & 1) << pin);
-			writel(data, base + GPIO_DS1);
-			break;
-		case PINCFG_TYPE_SKEW_RATE:
-			data = readl(base + GPIO_SR);
-			data &= ~(1 << pin);
-			data |= ((cfg_value & 1) << pin);
-			writel(data, base + GPIO_SR);
-			break;
-		case PINCFG_TYPE_INPUT_TYPE:
-			data = readl(base + GPIO_TYPE);
-			data &= ~(1 << pin);
-			data |= ((cfg_value & 1) << pin);
-			writel(data, base + GPIO_TYPE);
-			break;
-		default:
-			WARN_ON(1);
-			return -EINVAL;
-		}
-	} /* for each config */
-
-	return 0;
-}
-
-/* get the pin config settings for a specified pin */
-static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
-					unsigned long *config)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-	void __iomem *base;
-	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
-	u32 data;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	base = priv->reg_base;
-
-	switch (cfg_type) {
-	case PINCFG_TYPE_PUD:
-		data = readl(base + GPIO_PE);
-		data = (data >> pin) & 1;
-		if (!data)
-			*config = 0;
-		else
-			*config = ((readl(base + GPIO_PS) >> pin) & 1) + 1;
-		break;
-	case PINCFG_TYPE_DRV:
-		data = readl(base + GPIO_DS0);
-		data = (data >> pin) & 1;
-		*config = data;
-		data = readl(base + GPIO_DS1);
-		data = (data >> pin) & 1;
-		*config |= (data << 1);
-		break;
-	case PINCFG_TYPE_SKEW_RATE:
-		data = readl(base + GPIO_SR);
-		*config = (data >> pin) & 1;
-		break;
-	case PINCFG_TYPE_INPUT_TYPE:
-		data = readl(base + GPIO_TYPE);
-		*config = (data >> pin) & 1;
-		break;
-	default:
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* set the pin config settings for a specified pin group */
-static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev,
-			unsigned group, unsigned long *configs,
-			unsigned num_configs)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-	const unsigned int *pins;
-	unsigned int cnt;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	pins = priv->pin_groups[group].pins;
-
-	for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++)
-		exynos5440_pinconf_set(pctldev, pins[cnt], configs,
-				       num_configs);
-
-	return 0;
-}
-
-/* get the pin config settings for a specified pin group */
-static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev,
-				unsigned int group, unsigned long *config)
-{
-	struct exynos5440_pinctrl_priv_data *priv;
-	const unsigned int *pins;
-
-	priv = pinctrl_dev_get_drvdata(pctldev);
-	pins = priv->pin_groups[group].pins;
-	exynos5440_pinconf_get(pctldev, pins[0], config);
-	return 0;
-}
-
-/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static const struct pinconf_ops exynos5440_pinconf_ops = {
-	.pin_config_get		= exynos5440_pinconf_get,
-	.pin_config_set		= exynos5440_pinconf_set,
-	.pin_config_group_get	= exynos5440_pinconf_group_get,
-	.pin_config_group_set	= exynos5440_pinconf_group_set,
-};
-
-/* gpiolib gpio_set callback function */
-static void exynos5440_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
-{
-	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
-	void __iomem *base = priv->reg_base;
-	u32 data;
-
-	data = readl(base + GPIO_VAL);
-	data &= ~(1 << offset);
-	if (value)
-		data |= 1 << offset;
-	writel(data, base + GPIO_VAL);
-}
-
-/* gpiolib gpio_get callback function */
-static int exynos5440_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
-	void __iomem *base = priv->reg_base;
-	u32 data;
-
-	data = readl(base + GPIO_IN);
-	data >>= offset;
-	data &= 1;
-	return data;
-}
-
-/* gpiolib gpio_direction_input callback function */
-static int exynos5440_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
-	void __iomem *base = priv->reg_base;
-	u32 data;
-
-	/* first disable the data output enable on this pin */
-	data = readl(base + GPIO_OE);
-	data &= ~(1 << offset);
-	writel(data, base + GPIO_OE);
-
-	/* now enable input on this pin */
-	data =  readl(base + GPIO_IE);
-	data |= 1 << offset;
-	writel(data, base + GPIO_IE);
-	return 0;
-}
-
-/* gpiolib gpio_direction_output callback function */
-static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
-							int value)
-{
-	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
-	void __iomem *base = priv->reg_base;
-	u32 data;
-
-	exynos5440_gpio_set(gc, offset, value);
-
-	/* first disable the data input enable on this pin */
-	data = readl(base + GPIO_IE);
-	data &= ~(1 << offset);
-	writel(data, base + GPIO_IE);
-
-	/* now enable output on this pin */
-	data =  readl(base + GPIO_OE);
-	data |= 1 << offset;
-	writel(data, base + GPIO_OE);
-	return 0;
-}
-
-/* gpiolib gpio_to_irq callback function */
-static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
-	unsigned int virq;
-
-	if (offset < 16 || offset > 23)
-		return -ENXIO;
-
-	if (!priv->irq_domain)
-		return -ENXIO;
-
-	virq = irq_create_mapping(priv->irq_domain, offset - 16);
-	return virq ? : -ENXIO;
-}
-
-/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
-static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
-			struct device_node *cfg_np, unsigned int **pin_list,
-			unsigned int *npins)
-{
-	struct device *dev = &pdev->dev;
-	struct property *prop;
-
-	prop = of_find_property(cfg_np, "samsung,exynos5440-pins", NULL);
-	if (!prop)
-		return -ENOENT;
-
-	*npins = prop->length / sizeof(unsigned long);
-	if (!*npins) {
-		dev_err(dev, "invalid pin list in %s node", cfg_np->name);
-		return -EINVAL;
-	}
-
-	*pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
-	if (!*pin_list) {
-		dev_err(dev, "failed to allocate memory for pin list\n");
-		return -ENOMEM;
-	}
-
-	return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins",
-			*pin_list, *npins);
-}
-
-/*
- * Parse the information about all the available pin groups and pin functions
- * from device node of the pin-controller.
- */
-static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
-				struct exynos5440_pinctrl_priv_data *priv)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *dev_np = dev->of_node;
-	struct device_node *cfg_np;
-	struct exynos5440_pin_group *groups, *grp;
-	struct exynos5440_pmx_func *functions, *func;
-	unsigned *pin_list;
-	unsigned int npins, grp_cnt, func_idx = 0;
-	char *gname, *fname;
-	int ret;
-
-	grp_cnt = of_get_child_count(dev_np);
-	if (!grp_cnt)
-		return -EINVAL;
-
-	groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
-	if (!groups) {
-		dev_err(dev, "failed allocate memory for ping group list\n");
-		return -EINVAL;
-	}
-	grp = groups;
-
-	functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
-	if (!functions) {
-		dev_err(dev, "failed to allocate memory for function list\n");
-		return -EINVAL;
-	}
-	func = functions;
-
-	/*
-	 * Iterate over all the child nodes of the pin controller node
-	 * and create pin groups and pin function lists.
-	 */
-	for_each_child_of_node(dev_np, cfg_np) {
-		u32 function;
-
-		ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np,
-					&pin_list, &npins);
-		if (ret) {
-			gname = NULL;
-			goto skip_to_pin_function;
-		}
-
-		/* derive pin group name from the node name */
-		gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
-					GFP_KERNEL);
-		if (!gname) {
-			dev_err(dev, "failed to alloc memory for group name\n");
-			return -ENOMEM;
-		}
-		snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
-			 GROUP_SUFFIX);
-
-		grp->name = gname;
-		grp->pins = pin_list;
-		grp->num_pins = npins;
-		grp++;
-
-skip_to_pin_function:
-		ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function",
-						&function);
-		if (ret)
-			continue;
-
-		/* derive function name from the node name */
-		fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
-					GFP_KERNEL);
-		if (!fname) {
-			dev_err(dev, "failed to alloc memory for func name\n");
-			return -ENOMEM;
-		}
-		snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
-			 FUNCTION_SUFFIX);
-
-		func->name = fname;
-		func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
-		if (!func->groups) {
-			dev_err(dev, "failed to alloc memory for group list "
-					"in pin function");
-			return -ENOMEM;
-		}
-		func->groups[0] = gname;
-		func->num_groups = gname ? 1 : 0;
-		func->function = function;
-		func++;
-		func_idx++;
-	}
-
-	priv->pin_groups = groups;
-	priv->nr_groups = grp_cnt;
-	priv->pmx_functions = functions;
-	priv->nr_functions = func_idx;
-	return 0;
-}
-
-/* register the pinctrl interface with the pinctrl subsystem */
-static int exynos5440_pinctrl_register(struct platform_device *pdev,
-				struct exynos5440_pinctrl_priv_data *priv)
-{
-	struct device *dev = &pdev->dev;
-	struct pinctrl_desc *ctrldesc;
-	struct pinctrl_dev *pctl_dev;
-	struct pinctrl_pin_desc *pindesc, *pdesc;
-	struct pinctrl_gpio_range grange;
-	char *pin_names;
-	int pin, ret;
-
-	ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL);
-	if (!ctrldesc) {
-		dev_err(dev, "could not allocate memory for pinctrl desc\n");
-		return -ENOMEM;
-	}
-
-	ctrldesc->name = "exynos5440-pinctrl";
-	ctrldesc->owner = THIS_MODULE;
-	ctrldesc->pctlops = &exynos5440_pctrl_ops;
-	ctrldesc->pmxops = &exynos5440_pinmux_ops;
-	ctrldesc->confops = &exynos5440_pinconf_ops;
-
-	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
-				EXYNOS5440_MAX_PINS, GFP_KERNEL);
-	if (!pindesc) {
-		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
-		return -ENOMEM;
-	}
-	ctrldesc->pins = pindesc;
-	ctrldesc->npins = EXYNOS5440_MAX_PINS;
-
-	/* dynamically populate the pin number and pin name for pindesc */
-	for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
-		pdesc->number = pin;
-
-	/*
-	 * allocate space for storing the dynamically generated names for all
-	 * the pins which belong to this pin-controller.
-	 */
-	pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
-					ctrldesc->npins, GFP_KERNEL);
-	if (!pin_names) {
-		dev_err(&pdev->dev, "mem alloc for pin names failed\n");
-		return -ENOMEM;
-	}
-
-	/* for each pin, set the name of the pin */
-	for (pin = 0; pin < ctrldesc->npins; pin++) {
-		snprintf(pin_names, 6, "gpio%02d", pin);
-		pdesc = pindesc + pin;
-		pdesc->name = pin_names;
-		pin_names += PIN_NAME_LENGTH;
-	}
-
-	ret = exynos5440_pinctrl_parse_dt(pdev, priv);
-	if (ret)
-		return ret;
-
-	pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv);
-	if (!pctl_dev) {
-		dev_err(&pdev->dev, "could not register pinctrl driver\n");
-		return -EINVAL;
-	}
-
-	grange.name = "exynos5440-pctrl-gpio-range";
-	grange.id = 0;
-	grange.base = 0;
-	grange.npins = EXYNOS5440_MAX_PINS;
-	grange.gc = priv->gc;
-	pinctrl_add_gpio_range(pctl_dev, &grange);
-	return 0;
-}
-
-/* register the gpiolib interface with the gpiolib subsystem */
-static int exynos5440_gpiolib_register(struct platform_device *pdev,
-				struct exynos5440_pinctrl_priv_data *priv)
-{
-	struct gpio_chip *gc;
-	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc) {
-		dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
-		return -ENOMEM;
-	}
-
-	priv->gc = gc;
-	gc->base = 0;
-	gc->ngpio = EXYNOS5440_MAX_PINS;
-	gc->dev = &pdev->dev;
-	gc->set = exynos5440_gpio_set;
-	gc->get = exynos5440_gpio_get;
-	gc->direction_input = exynos5440_gpio_direction_input;
-	gc->direction_output = exynos5440_gpio_direction_output;
-	gc->to_irq = exynos5440_gpio_to_irq;
-	gc->label = "gpiolib-exynos5440";
-	gc->owner = THIS_MODULE;
-	ret = gpiochip_add(gc);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
-					"code: %d\n", gc->label, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* unregister the gpiolib interface with the gpiolib subsystem */
-static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
-				struct exynos5440_pinctrl_priv_data *priv)
-{
-	int ret = gpiochip_remove(priv->gc);
-	if (ret) {
-		dev_err(&pdev->dev, "gpio chip remove failed\n");
-		return ret;
-	}
-	return 0;
-}
-
-static void exynos5440_gpio_irq_unmask(struct irq_data *irqd)
-{
-	struct exynos5440_pinctrl_priv_data *d;
-	unsigned long gpio_int;
-
-	d = irq_data_get_irq_chip_data(irqd);
-	gpio_int = readl(d->reg_base + GPIO_INT);
-	gpio_int |= 1 << irqd->hwirq;
-	writel(gpio_int, d->reg_base + GPIO_INT);
-}
-
-static void exynos5440_gpio_irq_mask(struct irq_data *irqd)
-{
-	struct exynos5440_pinctrl_priv_data *d;
-	unsigned long gpio_int;
-
-	d = irq_data_get_irq_chip_data(irqd);
-	gpio_int = readl(d->reg_base + GPIO_INT);
-	gpio_int &= ~(1 << irqd->hwirq);
-	writel(gpio_int, d->reg_base + GPIO_INT);
-}
-
-/* irq_chip for gpio interrupts */
-static struct irq_chip exynos5440_gpio_irq_chip = {
-	.name		= "exynos5440_gpio_irq_chip",
-	.irq_unmask	= exynos5440_gpio_irq_unmask,
-	.irq_mask	= exynos5440_gpio_irq_mask,
-};
-
-/* interrupt handler for GPIO interrupts 0..7 */
-static irqreturn_t exynos5440_gpio_irq(int irq, void *data)
-{
-	struct exynos5440_gpio_intr_data *intd = data;
-	struct exynos5440_pinctrl_priv_data *d = intd->priv;
-	int virq;
-
-	virq = irq_linear_revmap(d->irq_domain, intd->gpio_int);
-	if (!virq)
-		return IRQ_NONE;
-	generic_handle_irq(virq);
-	return IRQ_HANDLED;
-}
-
-static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct exynos5440_pinctrl_priv_data *d = h->host_data;
-
-	irq_set_chip_data(virq, d);
-	irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip,
-					handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID);
-	return 0;
-}
-
-/* irq domain callbacks for gpio interrupt controller */
-static const struct irq_domain_ops exynos5440_gpio_irqd_ops = {
-	.map	= exynos5440_gpio_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-/* setup handling of gpio interrupts */
-static int exynos5440_gpio_irq_init(struct platform_device *pdev,
-				struct exynos5440_pinctrl_priv_data *priv)
-{
-	struct device *dev = &pdev->dev;
-	struct exynos5440_gpio_intr_data *intd;
-	int i, irq, ret;
-
-	intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT,
-					GFP_KERNEL);
-	if (!intd) {
-		dev_err(dev, "failed to allocate memory for gpio intr data\n");
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) {
-		irq = irq_of_parse_and_map(dev->of_node, i);
-		if (irq <= 0) {
-			dev_err(dev, "irq parsing failed\n");
-			return -EINVAL;
-		}
-
-		intd->gpio_int = i;
-		intd->priv = priv;
-		ret = devm_request_irq(dev, irq, exynos5440_gpio_irq,
-					0, dev_name(dev), intd++);
-		if (ret) {
-			dev_err(dev, "irq request failed\n");
-			return -ENXIO;
-		}
-	}
-
-	priv->irq_domain = irq_domain_add_linear(dev->of_node,
-				EXYNOS5440_MAX_GPIO_INT,
-				&exynos5440_gpio_irqd_ops, priv);
-	if (!priv->irq_domain) {
-		dev_err(dev, "failed to create irq domain\n");
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static int exynos5440_pinctrl_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct exynos5440_pinctrl_priv_data *priv;
-	struct resource *res;
-	int ret;
-
-	if (!dev->of_node) {
-		dev_err(dev, "device tree node not found\n");
-		return -ENODEV;
-	}
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(dev, "could not allocate memory for private data\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(priv->reg_base))
-		return PTR_ERR(priv->reg_base);
-
-	ret = exynos5440_gpiolib_register(pdev, priv);
-	if (ret)
-		return ret;
-
-	ret = exynos5440_pinctrl_register(pdev, priv);
-	if (ret) {
-		exynos5440_gpiolib_unregister(pdev, priv);
-		return ret;
-	}
-
-	ret = exynos5440_gpio_irq_init(pdev, priv);
-	if (ret) {
-		dev_err(dev, "failed to setup gpio interrupts\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, priv);
-	dev_info(dev, "EXYNOS5440 pinctrl driver registered\n");
-	return 0;
-}
-
-static const struct of_device_id exynos5440_pinctrl_dt_match[] = {
-	{ .compatible = "samsung,exynos5440-pinctrl" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos5440_pinctrl_dt_match);
-
-static struct platform_driver exynos5440_pinctrl_driver = {
-	.probe		= exynos5440_pinctrl_probe,
-	.driver = {
-		.name	= "exynos5440-pinctrl",
-		.owner	= THIS_MODULE,
-		.of_match_table = exynos5440_pinctrl_dt_match,
-	},
-};
-
-static int __init exynos5440_pinctrl_drv_register(void)
-{
-	return platform_driver_register(&exynos5440_pinctrl_driver);
-}
-postcore_initcall(exynos5440_pinctrl_drv_register);
-
-static void __exit exynos5440_pinctrl_drv_unregister(void)
-{
-	platform_driver_unregister(&exynos5440_pinctrl_driver);
-}
-module_exit(exynos5440_pinctrl_drv_unregister);
-
-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
-MODULE_DESCRIPTION("Samsung EXYNOS5440 SoC pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1310 +0,0 @@
-/*
- * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- *		http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the Samsung Exynos specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/err.h>
-
-#include "pinctrl-samsung.h"
-#include "pinctrl-exynos.h"
-
-
-static struct samsung_pin_bank_type bank_type_off = {
-	.fld_width = { 4, 1, 2, 2, 2, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
-};
-
-static struct samsung_pin_bank_type bank_type_alive = {
-	.fld_width = { 4, 1, 2, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
-};
-
-/* list of external wakeup controllers supported */
-static const struct of_device_id exynos_wkup_irq_ids[] = {
-	{ .compatible = "samsung,exynos4210-wakeup-eint", },
-	{ }
-};
-
-static void exynos_gpio_irq_mask(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
-	unsigned long mask;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << irqd->hwirq;
-	writel(mask, d->virt_base + reg_mask);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-}
-
-static void exynos_gpio_irq_ack(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
-
-	writel(1 << irqd->hwirq, d->virt_base + reg_pend);
-}
-
-static void exynos_gpio_irq_unmask(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
-	unsigned long mask;
-	unsigned long flags;
-
-	/*
-	 * Ack level interrupts right before unmask
-	 *
-	 * If we don't do this we'll get a double-interrupt.  Level triggered
-	 * interrupts must not fire an interrupt if the level is not
-	 * _currently_ active, even if it was active while the interrupt was
-	 * masked.
-	 */
-	if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
-		exynos_gpio_irq_ack(irqd);
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << irqd->hwirq);
-	writel(mask, d->virt_base + reg_mask);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-}
-
-static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pin_bank_type *bank_type = bank->type;
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	struct samsung_pin_ctrl *ctrl = d->ctrl;
-	unsigned int pin = irqd->hwirq;
-	unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
-	unsigned int con, trig_type;
-	unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
-	unsigned long flags;
-	unsigned int mask;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		trig_type = EXYNOS_EINT_EDGE_RISING;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		trig_type = EXYNOS_EINT_EDGE_FALLING;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		trig_type = EXYNOS_EINT_EDGE_BOTH;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		trig_type = EXYNOS_EINT_LEVEL_HIGH;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		trig_type = EXYNOS_EINT_LEVEL_LOW;
-		break;
-	default:
-		pr_err("unsupported external interrupt type\n");
-		return -EINVAL;
-	}
-
-	if (type & IRQ_TYPE_EDGE_BOTH)
-		__irq_set_handler_locked(irqd->irq, handle_edge_irq);
-	else
-		__irq_set_handler_locked(irqd->irq, handle_level_irq);
-
-	con = readl(d->virt_base + reg_con);
-	con &= ~(EXYNOS_EINT_CON_MASK << shift);
-	con |= trig_type << shift;
-	writel(con, d->virt_base + reg_con);
-
-	reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
-	shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
-	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	con = readl(d->virt_base + reg_con);
-	con &= ~(mask << shift);
-	con |= EXYNOS_EINT_FUNC << shift;
-	writel(con, d->virt_base + reg_con);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-
-	return 0;
-}
-
-/*
- * irq_chip for gpio interrupts.
- */
-static struct irq_chip exynos_gpio_irq_chip = {
-	.name		= "exynos_gpio_irq_chip",
-	.irq_unmask	= exynos_gpio_irq_unmask,
-	.irq_mask	= exynos_gpio_irq_mask,
-	.irq_ack		= exynos_gpio_irq_ack,
-	.irq_set_type	= exynos_gpio_irq_set_type,
-};
-
-static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct samsung_pin_bank *b = h->host_data;
-
-	irq_set_chip_data(virq, b);
-	irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
-					handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID);
-	return 0;
-}
-
-/*
- * irq domain callbacks for external gpio interrupt controller.
- */
-static const struct irq_domain_ops exynos_gpio_irqd_ops = {
-	.map	= exynos_gpio_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
-{
-	struct samsung_pinctrl_drv_data *d = data;
-	struct samsung_pin_ctrl *ctrl = d->ctrl;
-	struct samsung_pin_bank *bank = ctrl->pin_banks;
-	unsigned int svc, group, pin, virq;
-
-	svc = readl(d->virt_base + ctrl->svc);
-	group = EXYNOS_SVC_GROUP(svc);
-	pin = svc & EXYNOS_SVC_NUM_MASK;
-
-	if (!group)
-		return IRQ_HANDLED;
-	bank += (group - 1);
-
-	virq = irq_linear_revmap(bank->irq_domain, pin);
-	if (!virq)
-		return IRQ_NONE;
-	generic_handle_irq(virq);
-	return IRQ_HANDLED;
-}
-
-struct exynos_eint_gpio_save {
-	u32 eint_con;
-	u32 eint_fltcon0;
-	u32 eint_fltcon1;
-};
-
-/*
- * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
- * @d: driver data of samsung pinctrl driver.
- */
-static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
-{
-	struct samsung_pin_bank *bank;
-	struct device *dev = d->dev;
-	int ret;
-	int i;
-
-	if (!d->irq) {
-		dev_err(dev, "irq number not available\n");
-		return -EINVAL;
-	}
-
-	ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
-					0, dev_name(dev), d);
-	if (ret) {
-		dev_err(dev, "irq request failed\n");
-		return -ENXIO;
-	}
-
-	bank = d->ctrl->pin_banks;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-		bank->irq_domain = irq_domain_add_linear(bank->of_node,
-				bank->nr_pins, &exynos_gpio_irqd_ops, bank);
-		if (!bank->irq_domain) {
-			dev_err(dev, "gpio irq domain add failed\n");
-			ret = -ENXIO;
-			goto err_domains;
-		}
-
-		bank->soc_priv = devm_kzalloc(d->dev,
-			sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
-		if (!bank->soc_priv) {
-			irq_domain_remove(bank->irq_domain);
-			ret = -ENOMEM;
-			goto err_domains;
-		}
-	}
-
-	return 0;
-
-err_domains:
-	for (--i, --bank; i >= 0; --i, --bank) {
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-		irq_domain_remove(bank->irq_domain);
-	}
-
-	return ret;
-}
-
-static void exynos_wkup_irq_mask(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = b->drvdata;
-	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
-	unsigned long mask;
-	unsigned long flags;
-
-	spin_lock_irqsave(&b->slock, flags);
-
-	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << irqd->hwirq;
-	writel(mask, d->virt_base + reg_mask);
-
-	spin_unlock_irqrestore(&b->slock, flags);
-}
-
-static void exynos_wkup_irq_ack(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = b->drvdata;
-	unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
-
-	writel(1 << irqd->hwirq, d->virt_base + pend);
-}
-
-static void exynos_wkup_irq_unmask(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = b->drvdata;
-	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
-	unsigned long mask;
-	unsigned long flags;
-
-	/*
-	 * Ack level interrupts right before unmask
-	 *
-	 * If we don't do this we'll get a double-interrupt.  Level triggered
-	 * interrupts must not fire an interrupt if the level is not
-	 * _currently_ active, even if it was active while the interrupt was
-	 * masked.
-	 */
-	if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
-		exynos_wkup_irq_ack(irqd);
-
-	spin_lock_irqsave(&b->slock, flags);
-
-	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << irqd->hwirq);
-	writel(mask, d->virt_base + reg_mask);
-
-	spin_unlock_irqrestore(&b->slock, flags);
-}
-
-static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pin_bank_type *bank_type = bank->type;
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned int pin = irqd->hwirq;
-	unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
-	unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
-	unsigned long con, trig_type;
-	unsigned long flags;
-	unsigned int mask;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		trig_type = EXYNOS_EINT_EDGE_RISING;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		trig_type = EXYNOS_EINT_EDGE_FALLING;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		trig_type = EXYNOS_EINT_EDGE_BOTH;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		trig_type = EXYNOS_EINT_LEVEL_HIGH;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		trig_type = EXYNOS_EINT_LEVEL_LOW;
-		break;
-	default:
-		pr_err("unsupported external interrupt type\n");
-		return -EINVAL;
-	}
-
-	if (type & IRQ_TYPE_EDGE_BOTH)
-		__irq_set_handler_locked(irqd->irq, handle_edge_irq);
-	else
-		__irq_set_handler_locked(irqd->irq, handle_level_irq);
-
-	con = readl(d->virt_base + reg_con);
-	con &= ~(EXYNOS_EINT_CON_MASK << shift);
-	con |= trig_type << shift;
-	writel(con, d->virt_base + reg_con);
-
-	reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
-	shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
-	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	con = readl(d->virt_base + reg_con);
-	con &= ~(mask << shift);
-	con |= EXYNOS_EINT_FUNC << shift;
-	writel(con, d->virt_base + reg_con);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-
-	return 0;
-}
-
-static u32 exynos_eint_wake_mask = 0xffffffff;
-
-u32 exynos_get_eint_wake_mask(void)
-{
-	return exynos_eint_wake_mask;
-}
-
-static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
-
-	pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
-
-	if (!on)
-		exynos_eint_wake_mask |= bit;
-	else
-		exynos_eint_wake_mask &= ~bit;
-
-	return 0;
-}
-
-/*
- * irq_chip for wakeup interrupts
- */
-static struct irq_chip exynos_wkup_irq_chip = {
-	.name	= "exynos_wkup_irq_chip",
-	.irq_unmask	= exynos_wkup_irq_unmask,
-	.irq_mask	= exynos_wkup_irq_mask,
-	.irq_ack	= exynos_wkup_irq_ack,
-	.irq_set_type	= exynos_wkup_irq_set_type,
-	.irq_set_wake	= exynos_wkup_irq_set_wake,
-};
-
-/* interrupt handler for wakeup interrupts 0..15 */
-static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
-{
-	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
-	struct samsung_pin_bank *bank = eintd->bank;
-	struct irq_chip *chip = irq_get_chip(irq);
-	int eint_irq;
-
-	chained_irq_enter(chip, desc);
-	chip->irq_mask(&desc->irq_data);
-
-	if (chip->irq_ack)
-		chip->irq_ack(&desc->irq_data);
-
-	eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
-	generic_handle_irq(eint_irq);
-	chip->irq_unmask(&desc->irq_data);
-	chained_irq_exit(chip, desc);
-}
-
-static inline void exynos_irq_demux_eint(unsigned long pend,
-						struct irq_domain *domain)
-{
-	unsigned int irq;
-
-	while (pend) {
-		irq = fls(pend) - 1;
-		generic_handle_irq(irq_find_mapping(domain, irq));
-		pend &= ~(1 << irq);
-	}
-}
-
-/* interrupt handler for wakeup interrupt 16 */
-static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
-	struct samsung_pin_ctrl *ctrl = d->ctrl;
-	unsigned long pend;
-	unsigned long mask;
-	int i;
-
-	chained_irq_enter(chip, desc);
-
-	for (i = 0; i < eintd->nr_banks; ++i) {
-		struct samsung_pin_bank *b = eintd->banks[i];
-		pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
-		mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
-		exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
-	}
-
-	chained_irq_exit(chip, desc);
-}
-
-static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip, handle_level_irq);
-	irq_set_chip_data(virq, h->host_data);
-	set_irq_flags(virq, IRQF_VALID);
-	return 0;
-}
-
-/*
- * irq domain callbacks for external wakeup interrupt controller.
- */
-static const struct irq_domain_ops exynos_wkup_irqd_ops = {
-	.map	= exynos_wkup_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-/*
- * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
- * @d: driver data of samsung pinctrl driver.
- */
-static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
-{
-	struct device *dev = d->dev;
-	struct device_node *wkup_np = NULL;
-	struct device_node *np;
-	struct samsung_pin_bank *bank;
-	struct exynos_weint_data *weint_data;
-	struct exynos_muxed_weint_data *muxed_data;
-	unsigned int muxed_banks = 0;
-	unsigned int i;
-	int idx, irq;
-
-	for_each_child_of_node(dev->of_node, np) {
-		if (of_match_node(exynos_wkup_irq_ids, np)) {
-			wkup_np = np;
-			break;
-		}
-	}
-	if (!wkup_np)
-		return -ENODEV;
-
-	bank = d->ctrl->pin_banks;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		if (bank->eint_type != EINT_TYPE_WKUP)
-			continue;
-
-		bank->irq_domain = irq_domain_add_linear(bank->of_node,
-				bank->nr_pins, &exynos_wkup_irqd_ops, bank);
-		if (!bank->irq_domain) {
-			dev_err(dev, "wkup irq domain add failed\n");
-			return -ENXIO;
-		}
-
-		if (!of_find_property(bank->of_node, "interrupts", NULL)) {
-			bank->eint_type = EINT_TYPE_WKUP_MUX;
-			++muxed_banks;
-			continue;
-		}
-
-		weint_data = devm_kzalloc(dev, bank->nr_pins
-					* sizeof(*weint_data), GFP_KERNEL);
-		if (!weint_data) {
-			dev_err(dev, "could not allocate memory for weint_data\n");
-			return -ENOMEM;
-		}
-
-		for (idx = 0; idx < bank->nr_pins; ++idx) {
-			irq = irq_of_parse_and_map(bank->of_node, idx);
-			if (!irq) {
-				dev_err(dev, "irq number for eint-%s-%d not found\n",
-							bank->name, idx);
-				continue;
-			}
-			weint_data[idx].irq = idx;
-			weint_data[idx].bank = bank;
-			irq_set_handler_data(irq, &weint_data[idx]);
-			irq_set_chained_handler(irq, exynos_irq_eint0_15);
-		}
-	}
-
-	if (!muxed_banks)
-		return 0;
-
-	irq = irq_of_parse_and_map(wkup_np, 0);
-	if (!irq) {
-		dev_err(dev, "irq number for muxed EINTs not found\n");
-		return 0;
-	}
-
-	muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
-		+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
-	if (!muxed_data) {
-		dev_err(dev, "could not allocate memory for muxed_data\n");
-		return -ENOMEM;
-	}
-
-	irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
-	irq_set_handler_data(irq, muxed_data);
-
-	bank = d->ctrl->pin_banks;
-	idx = 0;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		if (bank->eint_type != EINT_TYPE_WKUP_MUX)
-			continue;
-
-		muxed_data->banks[idx++] = bank;
-	}
-	muxed_data->nr_banks = muxed_banks;
-
-	return 0;
-}
-
-static void exynos_pinctrl_suspend_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
-{
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	void __iomem *regs = drvdata->virt_base;
-
-	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-
-	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
-	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
-	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
-}
-
-static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	struct samsung_pin_bank *bank = ctrl->pin_banks;
-	int i;
-
-	for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO)
-			exynos_pinctrl_suspend_bank(drvdata, bank);
-}
-
-static void exynos_pinctrl_resume_bank(
-				struct samsung_pinctrl_drv_data *drvdata,
-				struct samsung_pin_bank *bank)
-{
-	struct exynos_eint_gpio_save *save = bank->soc_priv;
-	void __iomem *regs = drvdata->virt_base;
-
-	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_ECON_OFFSET
-			+ bank->eint_offset), save->eint_con);
-	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset), save->eint_fltcon0);
-	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
-			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
-			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
-
-	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
-						+ bank->eint_offset);
-	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset);
-	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
-						+ 2 * bank->eint_offset + 4);
-}
-
-static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	struct samsung_pin_bank *bank = ctrl->pin_banks;
-	int i;
-
-	for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
-		if (bank->eint_type == EINT_TYPE_GPIO)
-			exynos_pinctrl_resume_bank(drvdata, bank);
-}
-
-/* pin banks of s5pv210 pin-controller */
-static struct samsung_pin_bank s5pv210_pin_bank[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14),
-	EXYNOS_PIN_BANK_EINTG(6, 0x0c0, "gpd1", 0x18),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpe0", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x100, "gpe1", 0x20),
-	EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpf0", 0x24),
-	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpf1", 0x28),
-	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpf2", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(6, 0x180, "gpf3", 0x30),
-	EXYNOS_PIN_BANK_EINTG(7, 0x1a0, "gpg0", 0x34),
-	EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38),
-	EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c),
-	EXYNOS_PIN_BANK_EINTG(7, 0x200, "gpg3", 0x40),
-	EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x44),
-	EXYNOS_PIN_BANK_EINTG(6, 0x260, "gpj1", 0x48),
-	EXYNOS_PIN_BANK_EINTG(8, 0x280, "gpj2", 0x4c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x2a0, "gpj3", 0x50),
-	EXYNOS_PIN_BANK_EINTG(5, 0x2c0, "gpj4", 0x54),
-	EXYNOS_PIN_BANK_EINTN(8, 0x2e0, "mp01"),
-	EXYNOS_PIN_BANK_EINTN(4, 0x300, "mp02"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x320, "mp03"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x340, "mp04"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x360, "mp05"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x380, "mp06"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x3a0, "mp07"),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gph0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gph1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gph2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gph3", 0x0c),
-};
-
-struct samsung_pin_ctrl s5pv210_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= s5pv210_pin_bank,
-		.nr_banks	= ARRAY_SIZE(s5pv210_pin_bank),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "s5pv210-gpio-ctrl0",
-	},
-};
-
-/* pin banks of exynos3250 pin-controller 0 */
-static struct samsung_pin_bank exynos3250_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb",  0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpd1", 0x18),
-};
-
-/* pin banks of exynos3250 pin-controller 1 */
-static struct samsung_pin_bank exynos3250_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpe0"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpe1"),
-	EXYNOS_PIN_BANK_EINTN(3, 0x180, "gpe2"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpk0", 0x08),
-	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpl0", 0x18),
-	EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
-	EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
-	EXYNOS_PIN_BANK_EINTG(5, 0x2a0, "gpm2", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x2c0, "gpm3", 0x30),
-	EXYNOS_PIN_BANK_EINTG(8, 0x2e0, "gpm4", 0x34),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes
- * two gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos3250_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos3250_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos3250_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos3250-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos3250_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos3250_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos3250-gpio-ctrl1",
-	},
-};
-
-/* pin banks of exynos4210 pin-controller 0 */
-static struct samsung_pin_bank exynos4210_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
-	EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
-	EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
-	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
-	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
-	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
-};
-
-/* pin banks of exynos4210 pin-controller 1 */
-static struct samsung_pin_bank exynos4210_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
-	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
-	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
-	EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
-	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
-	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
-	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
-};
-
-/* pin banks of exynos4210 pin-controller 2 */
-static struct samsung_pin_bank exynos4210_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
- * three gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos4210_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4210-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos4210_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4210-gpio-ctrl1",
-	}, {
-		/* pin-controller instance 2 data */
-		.pin_banks	= exynos4210_pin_banks2,
-		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks2),
-		.label		= "exynos4210-gpio-ctrl2",
-	},
-};
-
-/* pin banks of exynos4x12 pin-controller 0 */
-static struct samsung_pin_bank exynos4x12_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
-	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
-	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40),
-	EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44),
-};
-
-/* pin banks of exynos4x12 pin-controller 1 */
-static struct samsung_pin_bank exynos4x12_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
-	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
-	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
-	EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18),
-	EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
-	EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
-	EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
-	EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30),
-	EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34),
-	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
-	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
-	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
-};
-
-/* pin banks of exynos4x12 pin-controller 2 */
-static struct samsung_pin_bank exynos4x12_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
-};
-
-/* pin banks of exynos4x12 pin-controller 3 */
-static struct samsung_pin_bank exynos4x12_pin_banks3[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes
- * four gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos4x12_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4x12-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos4x12_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4x12-gpio-ctrl1",
-	}, {
-		/* pin-controller instance 2 data */
-		.pin_banks	= exynos4x12_pin_banks2,
-		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks2),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4x12-gpio-ctrl2",
-	}, {
-		/* pin-controller instance 3 data */
-		.pin_banks	= exynos4x12_pin_banks3,
-		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks3),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos4x12-gpio-ctrl3",
-	},
-};
-
-/* pin banks of exynos5250 pin-controller 0 */
-static struct samsung_pin_bank exynos5250_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18),
-	EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20),
-	EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24),
-	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28),
-	EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30),
-	EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34),
-	EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"),
-	EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"),
-	EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
-};
-
-/* pin banks of exynos5250 pin-controller 1 */
-static struct samsung_pin_bank exynos5250_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08),
-	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
-	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20),
-};
-
-/* pin banks of exynos5250 pin-controller 2 */
-static struct samsung_pin_bank exynos5250_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10),
-};
-
-/* pin banks of exynos5250 pin-controller 3 */
-static struct samsung_pin_bank exynos5250_pin_banks3[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes
- * four gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos5250_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos5250-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos5250_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos5250-gpio-ctrl1",
-	}, {
-		/* pin-controller instance 2 data */
-		.pin_banks	= exynos5250_pin_banks2,
-		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks2),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos5250-gpio-ctrl2",
-	}, {
-		/* pin-controller instance 3 data */
-		.pin_banks	= exynos5250_pin_banks3,
-		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks3),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.suspend	= exynos_pinctrl_suspend,
-		.resume		= exynos_pinctrl_resume,
-		.label		= "exynos5250-gpio-ctrl3",
-	},
-};
-
-/* pin banks of exynos5260 pin-controller 0 */
-static struct samsung_pin_bank exynos5260_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpb1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(5, 0x0a0, "gpb2", 0x14),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpb3", 0x18),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpb4", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpb5", 0x20),
-	EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd0", 0x24),
-	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpd1", 0x28),
-	EXYNOS_PIN_BANK_EINTG(5, 0x160, "gpd2", 0x2c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpe0", 0x30),
-	EXYNOS_PIN_BANK_EINTG(5, 0x1a0, "gpe1", 0x34),
-	EXYNOS_PIN_BANK_EINTG(4, 0x1c0, "gpf0", 0x38),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1e0, "gpf1", 0x3c),
-	EXYNOS_PIN_BANK_EINTG(2, 0x200, "gpk0", 0x40),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
-};
-
-/* pin banks of exynos5260 pin-controller 1 */
-static struct samsung_pin_bank exynos5260_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpc0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpc1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpc4", 0x10),
-};
-
-/* pin banks of exynos5260 pin-controller 2 */
-static struct samsung_pin_bank exynos5260_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos5260 SoC. Exynos5260 SoC includes
- * three gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos5260_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos5260_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.label		= "exynos5260-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos5260_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5260-gpio-ctrl1",
-	}, {
-		/* pin-controller instance 2 data */
-		.pin_banks	= exynos5260_pin_banks2,
-		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks2),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5260-gpio-ctrl2",
-	},
-};
-
-/* pin banks of exynos5420 pin-controller 0 */
-static struct samsung_pin_bank exynos5420_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
-	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
-};
-
-/* pin banks of exynos5420 pin-controller 1 */
-static struct samsung_pin_bank exynos5420_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpc0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpc1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpc4", 0x10),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpd1", 0x14),
-	EXYNOS_PIN_BANK_EINTN(6, 0x0C0, "gpy0"),
-	EXYNOS_PIN_BANK_EINTN(4, 0x0E0, "gpy1"),
-	EXYNOS_PIN_BANK_EINTN(6, 0x100, "gpy2"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpy3"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpy4"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x160, "gpy5"),
-	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy6"),
-};
-
-/* pin banks of exynos5420 pin-controller 2 */
-static struct samsung_pin_bank exynos5420_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(6, 0x040, "gpf0", 0x08),
-	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpf1", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
-	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gpj4", 0x1c),
-};
-
-/* pin banks of exynos5420 pin-controller 3 */
-static struct samsung_pin_bank exynos5420_pin_banks3[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpb3", 0x18),
-	EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpb4", 0x1c),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph0", 0x20),
-};
-
-/* pin banks of exynos5420 pin-controller 4 */
-static struct samsung_pin_bank exynos5420_pin_banks4[] = {
-	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
-};
-
-/*
- * Samsung pinctrl driver data for Exynos5420 SoC. Exynos5420 SoC includes
- * four gpio/pin-mux/pinconfig controllers.
- */
-struct samsung_pin_ctrl exynos5420_pin_ctrl[] = {
-	{
-		/* pin-controller instance 0 data */
-		.pin_banks	= exynos5420_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks0),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
-		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
-		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.eint_wkup_init = exynos_eint_wkup_init,
-		.label		= "exynos5420-gpio-ctrl0",
-	}, {
-		/* pin-controller instance 1 data */
-		.pin_banks	= exynos5420_pin_banks1,
-		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks1),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5420-gpio-ctrl1",
-	}, {
-		/* pin-controller instance 2 data */
-		.pin_banks	= exynos5420_pin_banks2,
-		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks2),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5420-gpio-ctrl2",
-	}, {
-		/* pin-controller instance 3 data */
-		.pin_banks	= exynos5420_pin_banks3,
-		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks3),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5420-gpio-ctrl3",
-	}, {
-		/* pin-controller instance 4 data */
-		.pin_banks	= exynos5420_pin_banks4,
-		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks4),
-		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
-		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
-		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
-		.svc		= EXYNOS_SVC_OFFSET,
-		.eint_gpio_init = exynos_eint_gpio_init,
-		.label		= "exynos5420-gpio-ctrl4",
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos.h
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-exynos.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-exynos.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,99 +0,0 @@
-/*
- * Exynos specific definitions for Samsung pinctrl and gpiolib driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- *		http://www.linaro.org
- *
- * This file contains the Exynos specific definitions for the Samsung
- * pinctrl/gpiolib interface drivers.
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/* External GPIO and wakeup interrupt related definitions */
-#define EXYNOS_GPIO_ECON_OFFSET		0x700
-#define EXYNOS_GPIO_EFLTCON_OFFSET	0x800
-#define EXYNOS_GPIO_EMASK_OFFSET	0x900
-#define EXYNOS_GPIO_EPEND_OFFSET	0xA00
-#define EXYNOS_WKUP_ECON_OFFSET		0xE00
-#define EXYNOS_WKUP_EMASK_OFFSET	0xF00
-#define EXYNOS_WKUP_EPEND_OFFSET	0xF40
-#define EXYNOS_SVC_OFFSET		0xB08
-#define EXYNOS_EINT_FUNC		0xF
-
-/* helpers to access interrupt service register */
-#define EXYNOS_SVC_GROUP_SHIFT		3
-#define EXYNOS_SVC_GROUP_MASK		0x1f
-#define EXYNOS_SVC_NUM_MASK		7
-#define EXYNOS_SVC_GROUP(x)		((x >> EXYNOS_SVC_GROUP_SHIFT) & \
-						EXYNOS_SVC_GROUP_MASK)
-
-/* Exynos specific external interrupt trigger types */
-#define EXYNOS_EINT_LEVEL_LOW		0
-#define EXYNOS_EINT_LEVEL_HIGH		1
-#define EXYNOS_EINT_EDGE_FALLING	2
-#define EXYNOS_EINT_EDGE_RISING		3
-#define EXYNOS_EINT_EDGE_BOTH		4
-#define EXYNOS_EINT_CON_MASK		0xF
-#define EXYNOS_EINT_CON_LEN		4
-
-#define EXYNOS_EINT_MAX_PER_BANK	8
-#define EXYNOS_EINT_NR_WKUP_EINT
-
-#define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
-	{						\
-		.type		= &bank_type_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs)	\
-	{						\
-		.type		= &bank_type_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_GPIO,	\
-		.eint_offset	= offs,			\
-		.name		= id			\
-	}
-
-#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs)	\
-	{						\
-		.type		= &bank_type_alive,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_WKUP,	\
-		.eint_offset	= offs,			\
-		.name		= id			\
-	}
-
-/**
- * struct exynos_weint_data: irq specific data for all the wakeup interrupts
- * generated by the external wakeup interrupt controller.
- * @irq: interrupt number within the domain.
- * @bank: bank responsible for this interrupt
- */
-struct exynos_weint_data {
-	unsigned int irq;
-	struct samsung_pin_bank *bank;
-};
-
-/**
- * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
- * generated by the external wakeup interrupt controller.
- * @nr_banks: count of banks being part of the mux
- * @banks: array of banks being part of the mux
- */
-struct exynos_muxed_weint_data {
-	unsigned int nr_banks;
-	struct samsung_pin_bank *banks[];
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx1.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx1.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx1.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,279 @@
+/*
+ * i.MX1 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx1.h"
+
+#define PAD_ID(port, pin)	((port) * 32 + (pin))
+#define PA	0
+#define PB	1
+#define PC	2
+#define PD	3
+
+enum imx1_pads {
+	MX1_PAD_A24		= PAD_ID(PA, 0),
+	MX1_PAD_TIN		= PAD_ID(PA, 1),
+	MX1_PAD_PWMO		= PAD_ID(PA, 2),
+	MX1_PAD_CSI_MCLK	= PAD_ID(PA, 3),
+	MX1_PAD_CSI_D0		= PAD_ID(PA, 4),
+	MX1_PAD_CSI_D1		= PAD_ID(PA, 5),
+	MX1_PAD_CSI_D2		= PAD_ID(PA, 6),
+	MX1_PAD_CSI_D3		= PAD_ID(PA, 7),
+	MX1_PAD_CSI_D4		= PAD_ID(PA, 8),
+	MX1_PAD_CSI_D5		= PAD_ID(PA, 9),
+	MX1_PAD_CSI_D6		= PAD_ID(PA, 10),
+	MX1_PAD_CSI_D7		= PAD_ID(PA, 11),
+	MX1_PAD_CSI_VSYNC	= PAD_ID(PA, 12),
+	MX1_PAD_CSI_HSYNC	= PAD_ID(PA, 13),
+	MX1_PAD_CSI_PIXCLK	= PAD_ID(PA, 14),
+	MX1_PAD_I2C_SDA		= PAD_ID(PA, 15),
+	MX1_PAD_I2C_SCL		= PAD_ID(PA, 16),
+	MX1_PAD_DTACK		= PAD_ID(PA, 17),
+	MX1_PAD_BCLK		= PAD_ID(PA, 18),
+	MX1_PAD_LBA		= PAD_ID(PA, 19),
+	MX1_PAD_ECB		= PAD_ID(PA, 20),
+	MX1_PAD_A0		= PAD_ID(PA, 21),
+	MX1_PAD_CS4		= PAD_ID(PA, 22),
+	MX1_PAD_CS5		= PAD_ID(PA, 23),
+	MX1_PAD_A16		= PAD_ID(PA, 24),
+	MX1_PAD_A17		= PAD_ID(PA, 25),
+	MX1_PAD_A18		= PAD_ID(PA, 26),
+	MX1_PAD_A19		= PAD_ID(PA, 27),
+	MX1_PAD_A20		= PAD_ID(PA, 28),
+	MX1_PAD_A21		= PAD_ID(PA, 29),
+	MX1_PAD_A22		= PAD_ID(PA, 30),
+	MX1_PAD_A23		= PAD_ID(PA, 31),
+	MX1_PAD_SD_DAT0		= PAD_ID(PB, 8),
+	MX1_PAD_SD_DAT1		= PAD_ID(PB, 9),
+	MX1_PAD_SD_DAT2		= PAD_ID(PB, 10),
+	MX1_PAD_SD_DAT3		= PAD_ID(PB, 11),
+	MX1_PAD_SD_SCLK		= PAD_ID(PB, 12),
+	MX1_PAD_SD_CMD		= PAD_ID(PB, 13),
+	MX1_PAD_SIM_SVEN	= PAD_ID(PB, 14),
+	MX1_PAD_SIM_PD		= PAD_ID(PB, 15),
+	MX1_PAD_SIM_TX		= PAD_ID(PB, 16),
+	MX1_PAD_SIM_RX		= PAD_ID(PB, 17),
+	MX1_PAD_SIM_RST		= PAD_ID(PB, 18),
+	MX1_PAD_SIM_CLK		= PAD_ID(PB, 19),
+	MX1_PAD_USBD_AFE	= PAD_ID(PB, 20),
+	MX1_PAD_USBD_OE		= PAD_ID(PB, 21),
+	MX1_PAD_USBD_RCV	= PAD_ID(PB, 22),
+	MX1_PAD_USBD_SUSPND	= PAD_ID(PB, 23),
+	MX1_PAD_USBD_VP		= PAD_ID(PB, 24),
+	MX1_PAD_USBD_VM		= PAD_ID(PB, 25),
+	MX1_PAD_USBD_VPO	= PAD_ID(PB, 26),
+	MX1_PAD_USBD_VMO	= PAD_ID(PB, 27),
+	MX1_PAD_UART2_CTS	= PAD_ID(PB, 28),
+	MX1_PAD_UART2_RTS	= PAD_ID(PB, 29),
+	MX1_PAD_UART2_TXD	= PAD_ID(PB, 30),
+	MX1_PAD_UART2_RXD	= PAD_ID(PB, 31),
+	MX1_PAD_SSI_RXFS	= PAD_ID(PC, 3),
+	MX1_PAD_SSI_RXCLK	= PAD_ID(PC, 4),
+	MX1_PAD_SSI_RXDAT	= PAD_ID(PC, 5),
+	MX1_PAD_SSI_TXDAT	= PAD_ID(PC, 6),
+	MX1_PAD_SSI_TXFS	= PAD_ID(PC, 7),
+	MX1_PAD_SSI_TXCLK	= PAD_ID(PC, 8),
+	MX1_PAD_UART1_CTS	= PAD_ID(PC, 9),
+	MX1_PAD_UART1_RTS	= PAD_ID(PC, 10),
+	MX1_PAD_UART1_TXD	= PAD_ID(PC, 11),
+	MX1_PAD_UART1_RXD	= PAD_ID(PC, 12),
+	MX1_PAD_SPI1_RDY	= PAD_ID(PC, 13),
+	MX1_PAD_SPI1_SCLK	= PAD_ID(PC, 14),
+	MX1_PAD_SPI1_SS		= PAD_ID(PC, 15),
+	MX1_PAD_SPI1_MISO	= PAD_ID(PC, 16),
+	MX1_PAD_SPI1_MOSI	= PAD_ID(PC, 17),
+	MX1_PAD_BT13		= PAD_ID(PC, 19),
+	MX1_PAD_BT12		= PAD_ID(PC, 20),
+	MX1_PAD_BT11		= PAD_ID(PC, 21),
+	MX1_PAD_BT10		= PAD_ID(PC, 22),
+	MX1_PAD_BT9		= PAD_ID(PC, 23),
+	MX1_PAD_BT8		= PAD_ID(PC, 24),
+	MX1_PAD_BT7		= PAD_ID(PC, 25),
+	MX1_PAD_BT6		= PAD_ID(PC, 26),
+	MX1_PAD_BT5		= PAD_ID(PC, 27),
+	MX1_PAD_BT4		= PAD_ID(PC, 28),
+	MX1_PAD_BT3		= PAD_ID(PC, 29),
+	MX1_PAD_BT2		= PAD_ID(PC, 30),
+	MX1_PAD_BT1		= PAD_ID(PC, 31),
+	MX1_PAD_LSCLK		= PAD_ID(PD, 6),
+	MX1_PAD_REV		= PAD_ID(PD, 7),
+	MX1_PAD_CLS		= PAD_ID(PD, 8),
+	MX1_PAD_PS		= PAD_ID(PD, 9),
+	MX1_PAD_SPL_SPR		= PAD_ID(PD, 10),
+	MX1_PAD_CONTRAST	= PAD_ID(PD, 11),
+	MX1_PAD_ACD_OE		= PAD_ID(PD, 12),
+	MX1_PAD_LP_HSYNC	= PAD_ID(PD, 13),
+	MX1_PAD_FLM_VSYNC	= PAD_ID(PD, 14),
+	MX1_PAD_LD0		= PAD_ID(PD, 15),
+	MX1_PAD_LD1		= PAD_ID(PD, 16),
+	MX1_PAD_LD2		= PAD_ID(PD, 17),
+	MX1_PAD_LD3		= PAD_ID(PD, 18),
+	MX1_PAD_LD4		= PAD_ID(PD, 19),
+	MX1_PAD_LD5		= PAD_ID(PD, 20),
+	MX1_PAD_LD6		= PAD_ID(PD, 21),
+	MX1_PAD_LD7		= PAD_ID(PD, 22),
+	MX1_PAD_LD8		= PAD_ID(PD, 23),
+	MX1_PAD_LD9		= PAD_ID(PD, 24),
+	MX1_PAD_LD10		= PAD_ID(PD, 25),
+	MX1_PAD_LD11		= PAD_ID(PD, 26),
+	MX1_PAD_LD12		= PAD_ID(PD, 27),
+	MX1_PAD_LD13		= PAD_ID(PD, 28),
+	MX1_PAD_LD14		= PAD_ID(PD, 29),
+	MX1_PAD_LD15		= PAD_ID(PD, 30),
+	MX1_PAD_TMR2OUT		= PAD_ID(PD, 31),
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx1_pinctrl_pads[] = {
+	IMX_PINCTRL_PIN(MX1_PAD_A24),
+	IMX_PINCTRL_PIN(MX1_PAD_TIN),
+	IMX_PINCTRL_PIN(MX1_PAD_PWMO),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_MCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D0),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D1),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D2),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D3),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D4),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D5),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D6),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_D7),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_VSYNC),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_HSYNC),
+	IMX_PINCTRL_PIN(MX1_PAD_CSI_PIXCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_I2C_SDA),
+	IMX_PINCTRL_PIN(MX1_PAD_I2C_SCL),
+	IMX_PINCTRL_PIN(MX1_PAD_DTACK),
+	IMX_PINCTRL_PIN(MX1_PAD_BCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_LBA),
+	IMX_PINCTRL_PIN(MX1_PAD_ECB),
+	IMX_PINCTRL_PIN(MX1_PAD_A0),
+	IMX_PINCTRL_PIN(MX1_PAD_CS4),
+	IMX_PINCTRL_PIN(MX1_PAD_CS5),
+	IMX_PINCTRL_PIN(MX1_PAD_A16),
+	IMX_PINCTRL_PIN(MX1_PAD_A17),
+	IMX_PINCTRL_PIN(MX1_PAD_A18),
+	IMX_PINCTRL_PIN(MX1_PAD_A19),
+	IMX_PINCTRL_PIN(MX1_PAD_A20),
+	IMX_PINCTRL_PIN(MX1_PAD_A21),
+	IMX_PINCTRL_PIN(MX1_PAD_A22),
+	IMX_PINCTRL_PIN(MX1_PAD_A23),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_DAT0),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_DAT1),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_DAT2),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_DAT3),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_SCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_SD_CMD),
+	IMX_PINCTRL_PIN(MX1_PAD_SIM_SVEN),
+	IMX_PINCTRL_PIN(MX1_PAD_SIM_PD),
+	IMX_PINCTRL_PIN(MX1_PAD_SIM_TX),
+	IMX_PINCTRL_PIN(MX1_PAD_SIM_RX),
+	IMX_PINCTRL_PIN(MX1_PAD_SIM_CLK),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_AFE),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_OE),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_RCV),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_SUSPND),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_VP),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_VM),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_VPO),
+	IMX_PINCTRL_PIN(MX1_PAD_USBD_VMO),
+	IMX_PINCTRL_PIN(MX1_PAD_UART2_CTS),
+	IMX_PINCTRL_PIN(MX1_PAD_UART2_RTS),
+	IMX_PINCTRL_PIN(MX1_PAD_UART2_TXD),
+	IMX_PINCTRL_PIN(MX1_PAD_UART2_RXD),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_RXFS),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_RXCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_RXDAT),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_TXDAT),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_TXFS),
+	IMX_PINCTRL_PIN(MX1_PAD_SSI_TXCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_UART1_CTS),
+	IMX_PINCTRL_PIN(MX1_PAD_UART1_RTS),
+	IMX_PINCTRL_PIN(MX1_PAD_UART1_TXD),
+	IMX_PINCTRL_PIN(MX1_PAD_UART1_RXD),
+	IMX_PINCTRL_PIN(MX1_PAD_SPI1_RDY),
+	IMX_PINCTRL_PIN(MX1_PAD_SPI1_SCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_SPI1_SS),
+	IMX_PINCTRL_PIN(MX1_PAD_SPI1_MISO),
+	IMX_PINCTRL_PIN(MX1_PAD_SPI1_MOSI),
+	IMX_PINCTRL_PIN(MX1_PAD_BT13),
+	IMX_PINCTRL_PIN(MX1_PAD_BT12),
+	IMX_PINCTRL_PIN(MX1_PAD_BT11),
+	IMX_PINCTRL_PIN(MX1_PAD_BT10),
+	IMX_PINCTRL_PIN(MX1_PAD_BT9),
+	IMX_PINCTRL_PIN(MX1_PAD_BT8),
+	IMX_PINCTRL_PIN(MX1_PAD_BT7),
+	IMX_PINCTRL_PIN(MX1_PAD_BT6),
+	IMX_PINCTRL_PIN(MX1_PAD_BT5),
+	IMX_PINCTRL_PIN(MX1_PAD_BT4),
+	IMX_PINCTRL_PIN(MX1_PAD_BT3),
+	IMX_PINCTRL_PIN(MX1_PAD_BT2),
+	IMX_PINCTRL_PIN(MX1_PAD_BT1),
+	IMX_PINCTRL_PIN(MX1_PAD_LSCLK),
+	IMX_PINCTRL_PIN(MX1_PAD_REV),
+	IMX_PINCTRL_PIN(MX1_PAD_CLS),
+	IMX_PINCTRL_PIN(MX1_PAD_PS),
+	IMX_PINCTRL_PIN(MX1_PAD_SPL_SPR),
+	IMX_PINCTRL_PIN(MX1_PAD_CONTRAST),
+	IMX_PINCTRL_PIN(MX1_PAD_ACD_OE),
+	IMX_PINCTRL_PIN(MX1_PAD_LP_HSYNC),
+	IMX_PINCTRL_PIN(MX1_PAD_FLM_VSYNC),
+	IMX_PINCTRL_PIN(MX1_PAD_LD0),
+	IMX_PINCTRL_PIN(MX1_PAD_LD1),
+	IMX_PINCTRL_PIN(MX1_PAD_LD2),
+	IMX_PINCTRL_PIN(MX1_PAD_LD3),
+	IMX_PINCTRL_PIN(MX1_PAD_LD4),
+	IMX_PINCTRL_PIN(MX1_PAD_LD5),
+	IMX_PINCTRL_PIN(MX1_PAD_LD6),
+	IMX_PINCTRL_PIN(MX1_PAD_LD7),
+	IMX_PINCTRL_PIN(MX1_PAD_LD8),
+	IMX_PINCTRL_PIN(MX1_PAD_LD9),
+	IMX_PINCTRL_PIN(MX1_PAD_LD10),
+	IMX_PINCTRL_PIN(MX1_PAD_LD11),
+	IMX_PINCTRL_PIN(MX1_PAD_LD12),
+	IMX_PINCTRL_PIN(MX1_PAD_LD13),
+	IMX_PINCTRL_PIN(MX1_PAD_LD14),
+	IMX_PINCTRL_PIN(MX1_PAD_LD15),
+	IMX_PINCTRL_PIN(MX1_PAD_TMR2OUT),
+};
+
+static struct imx1_pinctrl_soc_info imx1_pinctrl_info = {
+	.pins	= imx1_pinctrl_pads,
+	.npins	= ARRAY_SIZE(imx1_pinctrl_pads),
+};
+
+static int __init imx1_pinctrl_probe(struct platform_device *pdev)
+{
+	return imx1_pinctrl_core_probe(pdev, &imx1_pinctrl_info);
+}
+
+static const struct of_device_id imx1_pinctrl_of_match[] = {
+	{ .compatible = "fsl,imx1-iomuxc", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, imx1_pinctrl_of_match);
+
+static struct platform_driver imx1_pinctrl_driver = {
+	.driver	= {
+		.name		= "imx1-pinctrl",
+		.owner		= THIS_MODULE,
+		.of_match_table	= imx1_pinctrl_of_match,
+	},
+	.remove	= imx1_pinctrl_core_remove,
+};
+module_platform_driver_probe(imx1_pinctrl_driver, imx1_pinctrl_probe);
+
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("Freescale i.MX1 pinctrl driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx1-core.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx1-core.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx1-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx1-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -526,7 +526,7 @@ static int imx1_pinctrl_parse_functions(
 	/* Initialise function */
 	func->name = np->name;
 	func->num_groups = of_get_child_count(np);
-	if (func->num_groups <= 0)
+	if (func->num_groups == 0)
 		return -EINVAL;
 
 	func->groups = devm_kzalloc(info->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx27.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx27.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx27.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx27.c	2014-09-28 17:29:07.000000000 -0400
@@ -63,10 +63,6 @@ enum imx27_pads {
 	MX27_PAD_CONTRAST = PAD_ID(PA, 30),
 	MX27_PAD_OE_ACD = PAD_ID(PA, 31),
 
-	MX27_PAD_UNUSED0 = PAD_ID(PB, 0),
-	MX27_PAD_UNUSED1 = PAD_ID(PB, 1),
-	MX27_PAD_UNUSED2 = PAD_ID(PB, 2),
-	MX27_PAD_UNUSED3 = PAD_ID(PB, 3),
 	MX27_PAD_SD2_D0 = PAD_ID(PB, 4),
 	MX27_PAD_SD2_D1 = PAD_ID(PB, 5),
 	MX27_PAD_SD2_D2 = PAD_ID(PB, 6),
@@ -96,11 +92,6 @@ enum imx27_pads {
 	MX27_PAD_USBH1_RXDM = PAD_ID(PB, 30),
 	MX27_PAD_USBH1_RXDP = PAD_ID(PB, 31),
 
-	MX27_PAD_UNUSED4 = PAD_ID(PC, 0),
-	MX27_PAD_UNUSED5 = PAD_ID(PC, 1),
-	MX27_PAD_UNUSED6 = PAD_ID(PC, 2),
-	MX27_PAD_UNUSED7 = PAD_ID(PC, 3),
-	MX27_PAD_UNUSED8 = PAD_ID(PC, 4),
 	MX27_PAD_I2C2_SDA = PAD_ID(PC, 5),
 	MX27_PAD_I2C2_SCL = PAD_ID(PC, 6),
 	MX27_PAD_USBOTG_DATA5 = PAD_ID(PC, 7),
@@ -188,12 +179,6 @@ enum imx27_pads {
 	MX27_PAD_SD1_CLK = PAD_ID(PE, 23),
 	MX27_PAD_USBOTG_CLK = PAD_ID(PE, 24),
 	MX27_PAD_USBOTG_DATA7 = PAD_ID(PE, 25),
-	MX27_PAD_UNUSED9 = PAD_ID(PE, 26),
-	MX27_PAD_UNUSED10 = PAD_ID(PE, 27),
-	MX27_PAD_UNUSED11 = PAD_ID(PE, 28),
-	MX27_PAD_UNUSED12 = PAD_ID(PE, 29),
-	MX27_PAD_UNUSED13 = PAD_ID(PE, 30),
-	MX27_PAD_UNUSED14 = PAD_ID(PE, 31),
 
 	MX27_PAD_NFRB = PAD_ID(PF, 0),
 	MX27_PAD_NFCLE = PAD_ID(PF, 1),
@@ -219,14 +204,6 @@ enum imx27_pads {
 	MX27_PAD_CS4_B = PAD_ID(PF, 21),
 	MX27_PAD_CS5_B = PAD_ID(PF, 22),
 	MX27_PAD_ATA_DATA15 = PAD_ID(PF, 23),
-	MX27_PAD_UNUSED15 = PAD_ID(PF, 24),
-	MX27_PAD_UNUSED16 = PAD_ID(PF, 25),
-	MX27_PAD_UNUSED17 = PAD_ID(PF, 26),
-	MX27_PAD_UNUSED18 = PAD_ID(PF, 27),
-	MX27_PAD_UNUSED19 = PAD_ID(PF, 28),
-	MX27_PAD_UNUSED20 = PAD_ID(PF, 29),
-	MX27_PAD_UNUSED21 = PAD_ID(PF, 30),
-	MX27_PAD_UNUSED22 = PAD_ID(PF, 31),
 };
 
 /* Pad names for the pinmux subsystem */
@@ -264,10 +241,6 @@ static const struct pinctrl_pin_desc imx
 	IMX_PINCTRL_PIN(MX27_PAD_CONTRAST),
 	IMX_PINCTRL_PIN(MX27_PAD_OE_ACD),
 
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED0),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED1),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED2),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED3),
 	IMX_PINCTRL_PIN(MX27_PAD_SD2_D0),
 	IMX_PINCTRL_PIN(MX27_PAD_SD2_D1),
 	IMX_PINCTRL_PIN(MX27_PAD_SD2_D2),
@@ -297,11 +270,6 @@ static const struct pinctrl_pin_desc imx
 	IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDM),
 	IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDP),
 
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED4),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED5),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED6),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED7),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED8),
 	IMX_PINCTRL_PIN(MX27_PAD_I2C2_SDA),
 	IMX_PINCTRL_PIN(MX27_PAD_I2C2_SCL),
 	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA5),
@@ -389,12 +357,6 @@ static const struct pinctrl_pin_desc imx
 	IMX_PINCTRL_PIN(MX27_PAD_SD1_CLK),
 	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_CLK),
 	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA7),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED9),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED10),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED11),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED12),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED13),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED14),
 
 	IMX_PINCTRL_PIN(MX27_PAD_NFRB),
 	IMX_PINCTRL_PIN(MX27_PAD_NFCLE),
@@ -420,14 +382,6 @@ static const struct pinctrl_pin_desc imx
 	IMX_PINCTRL_PIN(MX27_PAD_CS4_B),
 	IMX_PINCTRL_PIN(MX27_PAD_CS5_B),
 	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA15),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED15),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED16),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED17),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED18),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED19),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED20),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED21),
-	IMX_PINCTRL_PIN(MX27_PAD_UNUSED22),
 };
 
 static struct imx1_pinctrl_soc_info imx27_pinctrl_info = {
@@ -440,12 +394,6 @@ static struct of_device_id imx27_pinctrl
 	{ /* sentinel */ }
 };
 
-struct imx27_pinctrl_private {
-	int num_gpio_childs;
-	struct platform_device **gpio_dev;
-	struct mxc_gpio_platform_data *gpio_pdata;
-};
-
 static int imx27_pinctrl_probe(struct platform_device *pdev)
 {
 	return imx1_pinctrl_core_probe(pdev, &imx27_pinctrl_info);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -515,7 +515,7 @@ static int imx_pinctrl_parse_functions(s
 	/* Initialise function */
 	func->name = np->name;
 	func->num_groups = of_get_child_count(np);
-	if (func->num_groups <= 0) {
+	if (func->num_groups == 0) {
 		dev_err(info->dev, "no groups defined in %s\n", np->full_name);
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ipq8064.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ipq8064.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-ipq8064.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-ipq8064.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,653 +0,0 @@
-/*
- * Copyright (c) 2014, 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-msm.h"
-
-static const struct pinctrl_pin_desc ipq8064_pins[] = {
-	PINCTRL_PIN(0, "GPIO_0"),
-	PINCTRL_PIN(1, "GPIO_1"),
-	PINCTRL_PIN(2, "GPIO_2"),
-	PINCTRL_PIN(3, "GPIO_3"),
-	PINCTRL_PIN(4, "GPIO_4"),
-	PINCTRL_PIN(5, "GPIO_5"),
-	PINCTRL_PIN(6, "GPIO_6"),
-	PINCTRL_PIN(7, "GPIO_7"),
-	PINCTRL_PIN(8, "GPIO_8"),
-	PINCTRL_PIN(9, "GPIO_9"),
-	PINCTRL_PIN(10, "GPIO_10"),
-	PINCTRL_PIN(11, "GPIO_11"),
-	PINCTRL_PIN(12, "GPIO_12"),
-	PINCTRL_PIN(13, "GPIO_13"),
-	PINCTRL_PIN(14, "GPIO_14"),
-	PINCTRL_PIN(15, "GPIO_15"),
-	PINCTRL_PIN(16, "GPIO_16"),
-	PINCTRL_PIN(17, "GPIO_17"),
-	PINCTRL_PIN(18, "GPIO_18"),
-	PINCTRL_PIN(19, "GPIO_19"),
-	PINCTRL_PIN(20, "GPIO_20"),
-	PINCTRL_PIN(21, "GPIO_21"),
-	PINCTRL_PIN(22, "GPIO_22"),
-	PINCTRL_PIN(23, "GPIO_23"),
-	PINCTRL_PIN(24, "GPIO_24"),
-	PINCTRL_PIN(25, "GPIO_25"),
-	PINCTRL_PIN(26, "GPIO_26"),
-	PINCTRL_PIN(27, "GPIO_27"),
-	PINCTRL_PIN(28, "GPIO_28"),
-	PINCTRL_PIN(29, "GPIO_29"),
-	PINCTRL_PIN(30, "GPIO_30"),
-	PINCTRL_PIN(31, "GPIO_31"),
-	PINCTRL_PIN(32, "GPIO_32"),
-	PINCTRL_PIN(33, "GPIO_33"),
-	PINCTRL_PIN(34, "GPIO_34"),
-	PINCTRL_PIN(35, "GPIO_35"),
-	PINCTRL_PIN(36, "GPIO_36"),
-	PINCTRL_PIN(37, "GPIO_37"),
-	PINCTRL_PIN(38, "GPIO_38"),
-	PINCTRL_PIN(39, "GPIO_39"),
-	PINCTRL_PIN(40, "GPIO_40"),
-	PINCTRL_PIN(41, "GPIO_41"),
-	PINCTRL_PIN(42, "GPIO_42"),
-	PINCTRL_PIN(43, "GPIO_43"),
-	PINCTRL_PIN(44, "GPIO_44"),
-	PINCTRL_PIN(45, "GPIO_45"),
-	PINCTRL_PIN(46, "GPIO_46"),
-	PINCTRL_PIN(47, "GPIO_47"),
-	PINCTRL_PIN(48, "GPIO_48"),
-	PINCTRL_PIN(49, "GPIO_49"),
-	PINCTRL_PIN(50, "GPIO_50"),
-	PINCTRL_PIN(51, "GPIO_51"),
-	PINCTRL_PIN(52, "GPIO_52"),
-	PINCTRL_PIN(53, "GPIO_53"),
-	PINCTRL_PIN(54, "GPIO_54"),
-	PINCTRL_PIN(55, "GPIO_55"),
-	PINCTRL_PIN(56, "GPIO_56"),
-	PINCTRL_PIN(57, "GPIO_57"),
-	PINCTRL_PIN(58, "GPIO_58"),
-	PINCTRL_PIN(59, "GPIO_59"),
-	PINCTRL_PIN(60, "GPIO_60"),
-	PINCTRL_PIN(61, "GPIO_61"),
-	PINCTRL_PIN(62, "GPIO_62"),
-	PINCTRL_PIN(63, "GPIO_63"),
-	PINCTRL_PIN(64, "GPIO_64"),
-	PINCTRL_PIN(65, "GPIO_65"),
-	PINCTRL_PIN(66, "GPIO_66"),
-	PINCTRL_PIN(67, "GPIO_67"),
-	PINCTRL_PIN(68, "GPIO_68"),
-
-	PINCTRL_PIN(69, "SDC3_CLK"),
-	PINCTRL_PIN(70, "SDC3_CMD"),
-	PINCTRL_PIN(71, "SDC3_DATA"),
-};
-
-#define DECLARE_IPQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
-DECLARE_IPQ_GPIO_PINS(0);
-DECLARE_IPQ_GPIO_PINS(1);
-DECLARE_IPQ_GPIO_PINS(2);
-DECLARE_IPQ_GPIO_PINS(3);
-DECLARE_IPQ_GPIO_PINS(4);
-DECLARE_IPQ_GPIO_PINS(5);
-DECLARE_IPQ_GPIO_PINS(6);
-DECLARE_IPQ_GPIO_PINS(7);
-DECLARE_IPQ_GPIO_PINS(8);
-DECLARE_IPQ_GPIO_PINS(9);
-DECLARE_IPQ_GPIO_PINS(10);
-DECLARE_IPQ_GPIO_PINS(11);
-DECLARE_IPQ_GPIO_PINS(12);
-DECLARE_IPQ_GPIO_PINS(13);
-DECLARE_IPQ_GPIO_PINS(14);
-DECLARE_IPQ_GPIO_PINS(15);
-DECLARE_IPQ_GPIO_PINS(16);
-DECLARE_IPQ_GPIO_PINS(17);
-DECLARE_IPQ_GPIO_PINS(18);
-DECLARE_IPQ_GPIO_PINS(19);
-DECLARE_IPQ_GPIO_PINS(20);
-DECLARE_IPQ_GPIO_PINS(21);
-DECLARE_IPQ_GPIO_PINS(22);
-DECLARE_IPQ_GPIO_PINS(23);
-DECLARE_IPQ_GPIO_PINS(24);
-DECLARE_IPQ_GPIO_PINS(25);
-DECLARE_IPQ_GPIO_PINS(26);
-DECLARE_IPQ_GPIO_PINS(27);
-DECLARE_IPQ_GPIO_PINS(28);
-DECLARE_IPQ_GPIO_PINS(29);
-DECLARE_IPQ_GPIO_PINS(30);
-DECLARE_IPQ_GPIO_PINS(31);
-DECLARE_IPQ_GPIO_PINS(32);
-DECLARE_IPQ_GPIO_PINS(33);
-DECLARE_IPQ_GPIO_PINS(34);
-DECLARE_IPQ_GPIO_PINS(35);
-DECLARE_IPQ_GPIO_PINS(36);
-DECLARE_IPQ_GPIO_PINS(37);
-DECLARE_IPQ_GPIO_PINS(38);
-DECLARE_IPQ_GPIO_PINS(39);
-DECLARE_IPQ_GPIO_PINS(40);
-DECLARE_IPQ_GPIO_PINS(41);
-DECLARE_IPQ_GPIO_PINS(42);
-DECLARE_IPQ_GPIO_PINS(43);
-DECLARE_IPQ_GPIO_PINS(44);
-DECLARE_IPQ_GPIO_PINS(45);
-DECLARE_IPQ_GPIO_PINS(46);
-DECLARE_IPQ_GPIO_PINS(47);
-DECLARE_IPQ_GPIO_PINS(48);
-DECLARE_IPQ_GPIO_PINS(49);
-DECLARE_IPQ_GPIO_PINS(50);
-DECLARE_IPQ_GPIO_PINS(51);
-DECLARE_IPQ_GPIO_PINS(52);
-DECLARE_IPQ_GPIO_PINS(53);
-DECLARE_IPQ_GPIO_PINS(54);
-DECLARE_IPQ_GPIO_PINS(55);
-DECLARE_IPQ_GPIO_PINS(56);
-DECLARE_IPQ_GPIO_PINS(57);
-DECLARE_IPQ_GPIO_PINS(58);
-DECLARE_IPQ_GPIO_PINS(59);
-DECLARE_IPQ_GPIO_PINS(60);
-DECLARE_IPQ_GPIO_PINS(61);
-DECLARE_IPQ_GPIO_PINS(62);
-DECLARE_IPQ_GPIO_PINS(63);
-DECLARE_IPQ_GPIO_PINS(64);
-DECLARE_IPQ_GPIO_PINS(65);
-DECLARE_IPQ_GPIO_PINS(66);
-DECLARE_IPQ_GPIO_PINS(67);
-DECLARE_IPQ_GPIO_PINS(68);
-
-static const unsigned int sdc3_clk_pins[] = { 69 };
-static const unsigned int sdc3_cmd_pins[] = { 70 };
-static const unsigned int sdc3_data_pins[] = { 71 };
-
-#define FUNCTION(fname)					\
-	[IPQ_MUX_##fname] = {				\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
-	{						\
-		.name = "gpio" #id,			\
-		.pins = gpio##id##_pins,		\
-		.npins = ARRAY_SIZE(gpio##id##_pins),	\
-		.funcs = (int[]){			\
-			IPQ_MUX_NA, /* gpio mode */	\
-			IPQ_MUX_##f1,			\
-			IPQ_MUX_##f2,			\
-			IPQ_MUX_##f3,			\
-			IPQ_MUX_##f4,			\
-			IPQ_MUX_##f5,			\
-			IPQ_MUX_##f6,			\
-			IPQ_MUX_##f7,			\
-			IPQ_MUX_##f8,			\
-			IPQ_MUX_##f9,			\
-			IPQ_MUX_##f10,			\
-		},					\
-		.nfuncs = 11,				\
-		.ctl_reg = 0x1000 + 0x10 * id,		\
-		.io_reg = 0x1004 + 0x10 * id,		\
-		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
-		.intr_status_reg = 0x100c + 0x10 * id,	\
-		.intr_target_reg = 0x400 + 0x4 * id,	\
-		.mux_bit = 2,				\
-		.pull_bit = 0,				\
-		.drv_bit = 6,				\
-		.oe_bit = 9,				\
-		.in_bit = 0,				\
-		.out_bit = 1,				\
-		.intr_enable_bit = 0,			\
-		.intr_status_bit = 0,			\
-		.intr_ack_high = 1,			\
-		.intr_target_bit = 0,			\
-		.intr_raw_status_bit = 3,		\
-		.intr_polarity_bit = 1,			\
-		.intr_detection_bit = 2,		\
-		.intr_detection_width = 1,		\
-	}
-
-#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
-	{						\
-		.name = #pg_name,	                \
-		.pins = pg_name##_pins,                 \
-		.npins = ARRAY_SIZE(pg_name##_pins),    \
-		.ctl_reg = ctl,                         \
-		.io_reg = 0,                            \
-		.intr_cfg_reg = 0,                      \
-		.intr_status_reg = 0,                   \
-		.intr_target_reg = 0,                   \
-		.mux_bit = -1,                          \
-		.pull_bit = pull,                       \
-		.drv_bit = drv,                         \
-		.oe_bit = -1,                           \
-		.in_bit = -1,                           \
-		.out_bit = -1,                          \
-		.intr_enable_bit = -1,                  \
-		.intr_status_bit = -1,                  \
-		.intr_target_bit = -1,                  \
-		.intr_raw_status_bit = -1,              \
-		.intr_polarity_bit = -1,                \
-		.intr_detection_bit = -1,               \
-		.intr_detection_width = -1,             \
-	}
-
-enum ipq8064_functions {
-	IPQ_MUX_mdio,
-	IPQ_MUX_mi2s,
-	IPQ_MUX_pdm,
-	IPQ_MUX_ssbi,
-	IPQ_MUX_spmi,
-	IPQ_MUX_audio_pcm,
-	IPQ_MUX_gsbi1,
-	IPQ_MUX_gsbi2,
-	IPQ_MUX_gsbi4,
-	IPQ_MUX_gsbi5,
-	IPQ_MUX_gsbi5_spi_cs1,
-	IPQ_MUX_gsbi5_spi_cs2,
-	IPQ_MUX_gsbi5_spi_cs3,
-	IPQ_MUX_gsbi6,
-	IPQ_MUX_gsbi7,
-	IPQ_MUX_nss_spi,
-	IPQ_MUX_sdc1,
-	IPQ_MUX_spdif,
-	IPQ_MUX_nand,
-	IPQ_MUX_tsif1,
-	IPQ_MUX_tsif2,
-	IPQ_MUX_usb_fs_n,
-	IPQ_MUX_usb_fs,
-	IPQ_MUX_usb2_hsic,
-	IPQ_MUX_rgmii2,
-	IPQ_MUX_sata,
-	IPQ_MUX_pcie1_rst,
-	IPQ_MUX_pcie1_prsnt,
-	IPQ_MUX_pcie1_pwrflt,
-	IPQ_MUX_pcie1_pwren_n,
-	IPQ_MUX_pcie1_pwren,
-	IPQ_MUX_pcie1_clk_req,
-	IPQ_MUX_pcie2_rst,
-	IPQ_MUX_pcie2_prsnt,
-	IPQ_MUX_pcie2_pwrflt,
-	IPQ_MUX_pcie2_pwren_n,
-	IPQ_MUX_pcie2_pwren,
-	IPQ_MUX_pcie2_clk_req,
-	IPQ_MUX_pcie3_rst,
-	IPQ_MUX_pcie3_prsnt,
-	IPQ_MUX_pcie3_pwrflt,
-	IPQ_MUX_pcie3_pwren_n,
-	IPQ_MUX_pcie3_pwren,
-	IPQ_MUX_pcie3_clk_req,
-	IPQ_MUX_ps_hold,
-	IPQ_MUX_NA,
-};
-
-static const char * const mdio_groups[] = {
-	"gpio0", "gpio1", "gpio10", "gpio11",
-};
-
-static const char * const mi2s_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-	"gpio33", "gpio55", "gpio56", "gpio57", "gpio58",
-};
-
-static const char * const pdm_groups[] = {
-	"gpio3", "gpio16", "gpio17", "gpio22", "gpio30", "gpio31",
-	"gpio34", "gpio35", "gpio52", "gpio55", "gpio56", "gpio58",
-	"gpio59",
-};
-
-static const char * const ssbi_groups[] = {
-	"gpio10", "gpio11",
-};
-
-static const char * const spmi_groups[] = {
-	"gpio10", "gpio11",
-};
-
-static const char * const audio_pcm_groups[] = {
-	"gpio14", "gpio15", "gpio16", "gpio17",
-};
-
-static const char * const gsbi1_groups[] = {
-	"gpio51", "gpio52", "gpio53", "gpio54",
-};
-
-static const char * const gsbi2_groups[] = {
-	"gpio22", "gpio23", "gpio24", "gpio25",
-};
-
-static const char * const gsbi4_groups[] = {
-	"gpio10", "gpio11", "gpio12", "gpio13",
-};
-
-static const char * const gsbi5_groups[] = {
-	"gpio18", "gpio19", "gpio20", "gpio21",
-};
-
-static const char * const gsbi5_spi_cs1_groups[] = {
-	"gpio6", "gpio61",
-};
-
-static const char * const gsbi5_spi_cs2_groups[] = {
-	"gpio7", "gpio62",
-};
-
-static const char * const gsbi5_spi_cs3_groups[] = {
-	"gpio2",
-};
-
-static const char * const gsbi6_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30", "gpio55", "gpio56",
-	"gpio57", "gpio58",
-};
-
-static const char * const gsbi7_groups[] = {
-	"gpio6", "gpio7", "gpio8", "gpio9",
-};
-
-static const char * const nss_spi_groups[] = {
-	"gpio14", "gpio15", "gpio16", "gpio17", "gpio55", "gpio56",
-	"gpio57", "gpio58",
-};
-
-static const char * const sdc1_groups[] = {
-	"gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
-	"gpio44", "gpio45", "gpio46", "gpio47",
-};
-
-static const char * const spdif_groups[] = {
-	"gpio10", "gpio48",
-};
-
-static const char * const nand_groups[] = {
-	"gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39",
-	"gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45",
-	"gpio46", "gpio47",
-};
-
-static const char * const tsif1_groups[] = {
-	"gpio55", "gpio56", "gpio57", "gpio58",
-};
-
-static const char * const tsif2_groups[] = {
-	"gpio59", "gpio60", "gpio61", "gpio62",
-};
-
-static const char * const usb_fs_n_groups[] = {
-	"gpio6",
-};
-
-static const char * const usb_fs_groups[] = {
-	"gpio6", "gpio7", "gpio8",
-};
-
-static const char * const usb2_hsic_groups[] = {
-	"gpio67", "gpio68",
-};
-
-static const char * const rgmii2_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-	"gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62",
-};
-
-static const char * const sata_groups[] = {
-	"gpio10",
-};
-
-static const char * const pcie1_rst_groups[] = {
-	"gpio3",
-};
-
-static const char * const pcie1_prsnt_groups[] = {
-	"gpio3", "gpio11",
-};
-
-static const char * const pcie1_pwren_n_groups[] = {
-	"gpio4", "gpio12",
-};
-
-static const char * const pcie1_pwren_groups[] = {
-	"gpio4", "gpio12",
-};
-
-static const char * const pcie1_pwrflt_groups[] = {
-	"gpio5", "gpio13",
-};
-
-static const char * const pcie1_clk_req_groups[] = {
-	"gpio5",
-};
-
-static const char * const pcie2_rst_groups[] = {
-	"gpio48",
-};
-
-static const char * const pcie2_prsnt_groups[] = {
-	"gpio11", "gpio48",
-};
-
-static const char * const pcie2_pwren_n_groups[] = {
-	"gpio12", "gpio49",
-};
-
-static const char * const pcie2_pwren_groups[] = {
-	"gpio12", "gpio49",
-};
-
-static const char * const pcie2_pwrflt_groups[] = {
-	"gpio13", "gpio50",
-};
-
-static const char * const pcie2_clk_req_groups[] = {
-	"gpio50",
-};
-
-static const char * const pcie3_rst_groups[] = {
-	"gpio63",
-};
-
-static const char * const pcie3_prsnt_groups[] = {
-	"gpio11",
-};
-
-static const char * const pcie3_pwren_n_groups[] = {
-	"gpio12",
-};
-
-static const char * const pcie3_pwren_groups[] = {
-	"gpio12",
-};
-
-static const char * const pcie3_pwrflt_groups[] = {
-	"gpio13",
-};
-
-static const char * const pcie3_clk_req_groups[] = {
-	"gpio65",
-};
-
-static const char * const ps_hold_groups[] = {
-	"gpio26",
-};
-
-static const struct msm_function ipq8064_functions[] = {
-	FUNCTION(mdio),
-	FUNCTION(ssbi),
-	FUNCTION(spmi),
-	FUNCTION(mi2s),
-	FUNCTION(pdm),
-	FUNCTION(audio_pcm),
-	FUNCTION(gsbi1),
-	FUNCTION(gsbi2),
-	FUNCTION(gsbi4),
-	FUNCTION(gsbi5),
-	FUNCTION(gsbi5_spi_cs1),
-	FUNCTION(gsbi5_spi_cs2),
-	FUNCTION(gsbi5_spi_cs3),
-	FUNCTION(gsbi6),
-	FUNCTION(gsbi7),
-	FUNCTION(nss_spi),
-	FUNCTION(sdc1),
-	FUNCTION(spdif),
-	FUNCTION(nand),
-	FUNCTION(tsif1),
-	FUNCTION(tsif2),
-	FUNCTION(usb_fs_n),
-	FUNCTION(usb_fs),
-	FUNCTION(usb2_hsic),
-	FUNCTION(rgmii2),
-	FUNCTION(sata),
-	FUNCTION(pcie1_rst),
-	FUNCTION(pcie1_prsnt),
-	FUNCTION(pcie1_pwren_n),
-	FUNCTION(pcie1_pwren),
-	FUNCTION(pcie1_pwrflt),
-	FUNCTION(pcie1_clk_req),
-	FUNCTION(pcie2_rst),
-	FUNCTION(pcie2_prsnt),
-	FUNCTION(pcie2_pwren_n),
-	FUNCTION(pcie2_pwren),
-	FUNCTION(pcie2_pwrflt),
-	FUNCTION(pcie2_clk_req),
-	FUNCTION(pcie3_rst),
-	FUNCTION(pcie3_prsnt),
-	FUNCTION(pcie3_pwren_n),
-	FUNCTION(pcie3_pwren),
-	FUNCTION(pcie3_pwrflt),
-	FUNCTION(pcie3_clk_req),
-	FUNCTION(ps_hold),
-};
-
-static const struct msm_pingroup ipq8064_groups[] = {
-	PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(6, gsbi7, usb_fs, gsbi5_spi_cs1, usb_fs_n, NA, NA, NA, NA, NA, NA),
-	PINGROUP(7, gsbi7, usb_fs, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(8, gsbi7, usb_fs, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(9, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(10, gsbi4, spdif, sata, ssbi, mdio, spmi, NA, NA, NA, NA),
-	PINGROUP(11, gsbi4, pcie2_prsnt, pcie1_prsnt, pcie3_prsnt, ssbi, mdio, spmi, NA, NA, NA),
-	PINGROUP(12, gsbi4, pcie2_pwren_n, pcie1_pwren_n, pcie3_pwren_n, pcie2_pwren, pcie1_pwren, pcie3_pwren, NA, NA, NA),
-	PINGROUP(13, gsbi4, pcie2_pwrflt, pcie1_pwrflt, pcie3_pwrflt, NA, NA, NA, NA, NA, NA),
-	PINGROUP(14, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(15, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(16, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(17, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(18, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(19, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(20, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(21, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(22, gsbi2, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(26, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(27, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(28, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(29, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(30, mi2s, rgmii2, gsbi6, pdm, NA, NA, NA, NA, NA, NA),
-	PINGROUP(31, mi2s, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(32, mi2s, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(34, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(35, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(36, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(37, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(38, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(39, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(40, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(41, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(42, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(43, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(44, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(45, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(46, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(47, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(48, pcie2_rst, spdif, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(49, pcie2_pwren_n, pcie2_pwren, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(50, pcie2_clk_req, pcie2_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(51, gsbi1, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(52, gsbi1, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(53, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(54, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(55, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
-	PINGROUP(56, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
-	PINGROUP(57, tsif1, mi2s, gsbi6, nss_spi, NA, NA, NA, NA, NA, NA),
-	PINGROUP(58, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
-	PINGROUP(59, tsif2, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(60, tsif2, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(61, tsif2, rgmii2, gsbi5_spi_cs1, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(62, tsif2, rgmii2, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6),
-	SDC_PINGROUP(sdc3_cmd, 0x204a, 11, 3),
-	SDC_PINGROUP(sdc3_data, 0x204a, 9, 0),
-};
-
-#define NUM_GPIO_PINGROUPS 69
-
-static const struct msm_pinctrl_soc_data ipq8064_pinctrl = {
-	.pins = ipq8064_pins,
-	.npins = ARRAY_SIZE(ipq8064_pins),
-	.functions = ipq8064_functions,
-	.nfunctions = ARRAY_SIZE(ipq8064_functions),
-	.groups = ipq8064_groups,
-	.ngroups = ARRAY_SIZE(ipq8064_groups),
-	.ngpios = NUM_GPIO_PINGROUPS,
-};
-
-static int ipq8064_pinctrl_probe(struct platform_device *pdev)
-{
-	return msm_pinctrl_probe(pdev, &ipq8064_pinctrl);
-}
-
-static const struct of_device_id ipq8064_pinctrl_of_match[] = {
-	{ .compatible = "qcom,ipq8064-pinctrl", },
-	{ },
-};
-
-static struct platform_driver ipq8064_pinctrl_driver = {
-	.driver = {
-		.name = "ipq8064-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = ipq8064_pinctrl_of_match,
-	},
-	.probe = ipq8064_pinctrl_probe,
-	.remove = msm_pinctrl_remove,
-};
-
-static int __init ipq8064_pinctrl_init(void)
-{
-	return platform_driver_register(&ipq8064_pinctrl_driver);
-}
-arch_initcall(ipq8064_pinctrl_init);
-
-static void __exit ipq8064_pinctrl_exit(void)
-{
-	platform_driver_unregister(&ipq8064_pinctrl_driver);
-}
-module_exit(ipq8064_pinctrl_exit);
-
-MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
-MODULE_DESCRIPTION("Qualcomm IPQ8064 pinctrl driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, ipq8064_pinctrl_of_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm8x74.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm8x74.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm8x74.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm8x74.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1040 +0,0 @@
-/*
- * Copyright (c) 2013, Sony Mobile Communications AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-msm.h"
-
-static const struct pinctrl_pin_desc msm8x74_pins[] = {
-	PINCTRL_PIN(0, "GPIO_0"),
-	PINCTRL_PIN(1, "GPIO_1"),
-	PINCTRL_PIN(2, "GPIO_2"),
-	PINCTRL_PIN(3, "GPIO_3"),
-	PINCTRL_PIN(4, "GPIO_4"),
-	PINCTRL_PIN(5, "GPIO_5"),
-	PINCTRL_PIN(6, "GPIO_6"),
-	PINCTRL_PIN(7, "GPIO_7"),
-	PINCTRL_PIN(8, "GPIO_8"),
-	PINCTRL_PIN(9, "GPIO_9"),
-	PINCTRL_PIN(10, "GPIO_10"),
-	PINCTRL_PIN(11, "GPIO_11"),
-	PINCTRL_PIN(12, "GPIO_12"),
-	PINCTRL_PIN(13, "GPIO_13"),
-	PINCTRL_PIN(14, "GPIO_14"),
-	PINCTRL_PIN(15, "GPIO_15"),
-	PINCTRL_PIN(16, "GPIO_16"),
-	PINCTRL_PIN(17, "GPIO_17"),
-	PINCTRL_PIN(18, "GPIO_18"),
-	PINCTRL_PIN(19, "GPIO_19"),
-	PINCTRL_PIN(20, "GPIO_20"),
-	PINCTRL_PIN(21, "GPIO_21"),
-	PINCTRL_PIN(22, "GPIO_22"),
-	PINCTRL_PIN(23, "GPIO_23"),
-	PINCTRL_PIN(24, "GPIO_24"),
-	PINCTRL_PIN(25, "GPIO_25"),
-	PINCTRL_PIN(26, "GPIO_26"),
-	PINCTRL_PIN(27, "GPIO_27"),
-	PINCTRL_PIN(28, "GPIO_28"),
-	PINCTRL_PIN(29, "GPIO_29"),
-	PINCTRL_PIN(30, "GPIO_30"),
-	PINCTRL_PIN(31, "GPIO_31"),
-	PINCTRL_PIN(32, "GPIO_32"),
-	PINCTRL_PIN(33, "GPIO_33"),
-	PINCTRL_PIN(34, "GPIO_34"),
-	PINCTRL_PIN(35, "GPIO_35"),
-	PINCTRL_PIN(36, "GPIO_36"),
-	PINCTRL_PIN(37, "GPIO_37"),
-	PINCTRL_PIN(38, "GPIO_38"),
-	PINCTRL_PIN(39, "GPIO_39"),
-	PINCTRL_PIN(40, "GPIO_40"),
-	PINCTRL_PIN(41, "GPIO_41"),
-	PINCTRL_PIN(42, "GPIO_42"),
-	PINCTRL_PIN(43, "GPIO_43"),
-	PINCTRL_PIN(44, "GPIO_44"),
-	PINCTRL_PIN(45, "GPIO_45"),
-	PINCTRL_PIN(46, "GPIO_46"),
-	PINCTRL_PIN(47, "GPIO_47"),
-	PINCTRL_PIN(48, "GPIO_48"),
-	PINCTRL_PIN(49, "GPIO_49"),
-	PINCTRL_PIN(50, "GPIO_50"),
-	PINCTRL_PIN(51, "GPIO_51"),
-	PINCTRL_PIN(52, "GPIO_52"),
-	PINCTRL_PIN(53, "GPIO_53"),
-	PINCTRL_PIN(54, "GPIO_54"),
-	PINCTRL_PIN(55, "GPIO_55"),
-	PINCTRL_PIN(56, "GPIO_56"),
-	PINCTRL_PIN(57, "GPIO_57"),
-	PINCTRL_PIN(58, "GPIO_58"),
-	PINCTRL_PIN(59, "GPIO_59"),
-	PINCTRL_PIN(60, "GPIO_60"),
-	PINCTRL_PIN(61, "GPIO_61"),
-	PINCTRL_PIN(62, "GPIO_62"),
-	PINCTRL_PIN(63, "GPIO_63"),
-	PINCTRL_PIN(64, "GPIO_64"),
-	PINCTRL_PIN(65, "GPIO_65"),
-	PINCTRL_PIN(66, "GPIO_66"),
-	PINCTRL_PIN(67, "GPIO_67"),
-	PINCTRL_PIN(68, "GPIO_68"),
-	PINCTRL_PIN(69, "GPIO_69"),
-	PINCTRL_PIN(70, "GPIO_70"),
-	PINCTRL_PIN(71, "GPIO_71"),
-	PINCTRL_PIN(72, "GPIO_72"),
-	PINCTRL_PIN(73, "GPIO_73"),
-	PINCTRL_PIN(74, "GPIO_74"),
-	PINCTRL_PIN(75, "GPIO_75"),
-	PINCTRL_PIN(76, "GPIO_76"),
-	PINCTRL_PIN(77, "GPIO_77"),
-	PINCTRL_PIN(78, "GPIO_78"),
-	PINCTRL_PIN(79, "GPIO_79"),
-	PINCTRL_PIN(80, "GPIO_80"),
-	PINCTRL_PIN(81, "GPIO_81"),
-	PINCTRL_PIN(82, "GPIO_82"),
-	PINCTRL_PIN(83, "GPIO_83"),
-	PINCTRL_PIN(84, "GPIO_84"),
-	PINCTRL_PIN(85, "GPIO_85"),
-	PINCTRL_PIN(86, "GPIO_86"),
-	PINCTRL_PIN(87, "GPIO_87"),
-	PINCTRL_PIN(88, "GPIO_88"),
-	PINCTRL_PIN(89, "GPIO_89"),
-	PINCTRL_PIN(90, "GPIO_90"),
-	PINCTRL_PIN(91, "GPIO_91"),
-	PINCTRL_PIN(92, "GPIO_92"),
-	PINCTRL_PIN(93, "GPIO_93"),
-	PINCTRL_PIN(94, "GPIO_94"),
-	PINCTRL_PIN(95, "GPIO_95"),
-	PINCTRL_PIN(96, "GPIO_96"),
-	PINCTRL_PIN(97, "GPIO_97"),
-	PINCTRL_PIN(98, "GPIO_98"),
-	PINCTRL_PIN(99, "GPIO_99"),
-	PINCTRL_PIN(100, "GPIO_100"),
-	PINCTRL_PIN(101, "GPIO_101"),
-	PINCTRL_PIN(102, "GPIO_102"),
-	PINCTRL_PIN(103, "GPIO_103"),
-	PINCTRL_PIN(104, "GPIO_104"),
-	PINCTRL_PIN(105, "GPIO_105"),
-	PINCTRL_PIN(106, "GPIO_106"),
-	PINCTRL_PIN(107, "GPIO_107"),
-	PINCTRL_PIN(108, "GPIO_108"),
-	PINCTRL_PIN(109, "GPIO_109"),
-	PINCTRL_PIN(110, "GPIO_110"),
-	PINCTRL_PIN(111, "GPIO_111"),
-	PINCTRL_PIN(112, "GPIO_112"),
-	PINCTRL_PIN(113, "GPIO_113"),
-	PINCTRL_PIN(114, "GPIO_114"),
-	PINCTRL_PIN(115, "GPIO_115"),
-	PINCTRL_PIN(116, "GPIO_116"),
-	PINCTRL_PIN(117, "GPIO_117"),
-	PINCTRL_PIN(118, "GPIO_118"),
-	PINCTRL_PIN(119, "GPIO_119"),
-	PINCTRL_PIN(120, "GPIO_120"),
-	PINCTRL_PIN(121, "GPIO_121"),
-	PINCTRL_PIN(122, "GPIO_122"),
-	PINCTRL_PIN(123, "GPIO_123"),
-	PINCTRL_PIN(124, "GPIO_124"),
-	PINCTRL_PIN(125, "GPIO_125"),
-	PINCTRL_PIN(126, "GPIO_126"),
-	PINCTRL_PIN(127, "GPIO_127"),
-	PINCTRL_PIN(128, "GPIO_128"),
-	PINCTRL_PIN(129, "GPIO_129"),
-	PINCTRL_PIN(130, "GPIO_130"),
-	PINCTRL_PIN(131, "GPIO_131"),
-	PINCTRL_PIN(132, "GPIO_132"),
-	PINCTRL_PIN(133, "GPIO_133"),
-	PINCTRL_PIN(134, "GPIO_134"),
-	PINCTRL_PIN(135, "GPIO_135"),
-	PINCTRL_PIN(136, "GPIO_136"),
-	PINCTRL_PIN(137, "GPIO_137"),
-	PINCTRL_PIN(138, "GPIO_138"),
-	PINCTRL_PIN(139, "GPIO_139"),
-	PINCTRL_PIN(140, "GPIO_140"),
-	PINCTRL_PIN(141, "GPIO_141"),
-	PINCTRL_PIN(142, "GPIO_142"),
-	PINCTRL_PIN(143, "GPIO_143"),
-	PINCTRL_PIN(144, "GPIO_144"),
-	PINCTRL_PIN(145, "GPIO_145"),
-
-	PINCTRL_PIN(146, "SDC1_CLK"),
-	PINCTRL_PIN(147, "SDC1_CMD"),
-	PINCTRL_PIN(148, "SDC1_DATA"),
-	PINCTRL_PIN(149, "SDC2_CLK"),
-	PINCTRL_PIN(150, "SDC2_CMD"),
-	PINCTRL_PIN(151, "SDC2_DATA"),
-};
-
-#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
-DECLARE_MSM_GPIO_PINS(0);
-DECLARE_MSM_GPIO_PINS(1);
-DECLARE_MSM_GPIO_PINS(2);
-DECLARE_MSM_GPIO_PINS(3);
-DECLARE_MSM_GPIO_PINS(4);
-DECLARE_MSM_GPIO_PINS(5);
-DECLARE_MSM_GPIO_PINS(6);
-DECLARE_MSM_GPIO_PINS(7);
-DECLARE_MSM_GPIO_PINS(8);
-DECLARE_MSM_GPIO_PINS(9);
-DECLARE_MSM_GPIO_PINS(10);
-DECLARE_MSM_GPIO_PINS(11);
-DECLARE_MSM_GPIO_PINS(12);
-DECLARE_MSM_GPIO_PINS(13);
-DECLARE_MSM_GPIO_PINS(14);
-DECLARE_MSM_GPIO_PINS(15);
-DECLARE_MSM_GPIO_PINS(16);
-DECLARE_MSM_GPIO_PINS(17);
-DECLARE_MSM_GPIO_PINS(18);
-DECLARE_MSM_GPIO_PINS(19);
-DECLARE_MSM_GPIO_PINS(20);
-DECLARE_MSM_GPIO_PINS(21);
-DECLARE_MSM_GPIO_PINS(22);
-DECLARE_MSM_GPIO_PINS(23);
-DECLARE_MSM_GPIO_PINS(24);
-DECLARE_MSM_GPIO_PINS(25);
-DECLARE_MSM_GPIO_PINS(26);
-DECLARE_MSM_GPIO_PINS(27);
-DECLARE_MSM_GPIO_PINS(28);
-DECLARE_MSM_GPIO_PINS(29);
-DECLARE_MSM_GPIO_PINS(30);
-DECLARE_MSM_GPIO_PINS(31);
-DECLARE_MSM_GPIO_PINS(32);
-DECLARE_MSM_GPIO_PINS(33);
-DECLARE_MSM_GPIO_PINS(34);
-DECLARE_MSM_GPIO_PINS(35);
-DECLARE_MSM_GPIO_PINS(36);
-DECLARE_MSM_GPIO_PINS(37);
-DECLARE_MSM_GPIO_PINS(38);
-DECLARE_MSM_GPIO_PINS(39);
-DECLARE_MSM_GPIO_PINS(40);
-DECLARE_MSM_GPIO_PINS(41);
-DECLARE_MSM_GPIO_PINS(42);
-DECLARE_MSM_GPIO_PINS(43);
-DECLARE_MSM_GPIO_PINS(44);
-DECLARE_MSM_GPIO_PINS(45);
-DECLARE_MSM_GPIO_PINS(46);
-DECLARE_MSM_GPIO_PINS(47);
-DECLARE_MSM_GPIO_PINS(48);
-DECLARE_MSM_GPIO_PINS(49);
-DECLARE_MSM_GPIO_PINS(50);
-DECLARE_MSM_GPIO_PINS(51);
-DECLARE_MSM_GPIO_PINS(52);
-DECLARE_MSM_GPIO_PINS(53);
-DECLARE_MSM_GPIO_PINS(54);
-DECLARE_MSM_GPIO_PINS(55);
-DECLARE_MSM_GPIO_PINS(56);
-DECLARE_MSM_GPIO_PINS(57);
-DECLARE_MSM_GPIO_PINS(58);
-DECLARE_MSM_GPIO_PINS(59);
-DECLARE_MSM_GPIO_PINS(60);
-DECLARE_MSM_GPIO_PINS(61);
-DECLARE_MSM_GPIO_PINS(62);
-DECLARE_MSM_GPIO_PINS(63);
-DECLARE_MSM_GPIO_PINS(64);
-DECLARE_MSM_GPIO_PINS(65);
-DECLARE_MSM_GPIO_PINS(66);
-DECLARE_MSM_GPIO_PINS(67);
-DECLARE_MSM_GPIO_PINS(68);
-DECLARE_MSM_GPIO_PINS(69);
-DECLARE_MSM_GPIO_PINS(70);
-DECLARE_MSM_GPIO_PINS(71);
-DECLARE_MSM_GPIO_PINS(72);
-DECLARE_MSM_GPIO_PINS(73);
-DECLARE_MSM_GPIO_PINS(74);
-DECLARE_MSM_GPIO_PINS(75);
-DECLARE_MSM_GPIO_PINS(76);
-DECLARE_MSM_GPIO_PINS(77);
-DECLARE_MSM_GPIO_PINS(78);
-DECLARE_MSM_GPIO_PINS(79);
-DECLARE_MSM_GPIO_PINS(80);
-DECLARE_MSM_GPIO_PINS(81);
-DECLARE_MSM_GPIO_PINS(82);
-DECLARE_MSM_GPIO_PINS(83);
-DECLARE_MSM_GPIO_PINS(84);
-DECLARE_MSM_GPIO_PINS(85);
-DECLARE_MSM_GPIO_PINS(86);
-DECLARE_MSM_GPIO_PINS(87);
-DECLARE_MSM_GPIO_PINS(88);
-DECLARE_MSM_GPIO_PINS(89);
-DECLARE_MSM_GPIO_PINS(90);
-DECLARE_MSM_GPIO_PINS(91);
-DECLARE_MSM_GPIO_PINS(92);
-DECLARE_MSM_GPIO_PINS(93);
-DECLARE_MSM_GPIO_PINS(94);
-DECLARE_MSM_GPIO_PINS(95);
-DECLARE_MSM_GPIO_PINS(96);
-DECLARE_MSM_GPIO_PINS(97);
-DECLARE_MSM_GPIO_PINS(98);
-DECLARE_MSM_GPIO_PINS(99);
-DECLARE_MSM_GPIO_PINS(100);
-DECLARE_MSM_GPIO_PINS(101);
-DECLARE_MSM_GPIO_PINS(102);
-DECLARE_MSM_GPIO_PINS(103);
-DECLARE_MSM_GPIO_PINS(104);
-DECLARE_MSM_GPIO_PINS(105);
-DECLARE_MSM_GPIO_PINS(106);
-DECLARE_MSM_GPIO_PINS(107);
-DECLARE_MSM_GPIO_PINS(108);
-DECLARE_MSM_GPIO_PINS(109);
-DECLARE_MSM_GPIO_PINS(110);
-DECLARE_MSM_GPIO_PINS(111);
-DECLARE_MSM_GPIO_PINS(112);
-DECLARE_MSM_GPIO_PINS(113);
-DECLARE_MSM_GPIO_PINS(114);
-DECLARE_MSM_GPIO_PINS(115);
-DECLARE_MSM_GPIO_PINS(116);
-DECLARE_MSM_GPIO_PINS(117);
-DECLARE_MSM_GPIO_PINS(118);
-DECLARE_MSM_GPIO_PINS(119);
-DECLARE_MSM_GPIO_PINS(120);
-DECLARE_MSM_GPIO_PINS(121);
-DECLARE_MSM_GPIO_PINS(122);
-DECLARE_MSM_GPIO_PINS(123);
-DECLARE_MSM_GPIO_PINS(124);
-DECLARE_MSM_GPIO_PINS(125);
-DECLARE_MSM_GPIO_PINS(126);
-DECLARE_MSM_GPIO_PINS(127);
-DECLARE_MSM_GPIO_PINS(128);
-DECLARE_MSM_GPIO_PINS(129);
-DECLARE_MSM_GPIO_PINS(130);
-DECLARE_MSM_GPIO_PINS(131);
-DECLARE_MSM_GPIO_PINS(132);
-DECLARE_MSM_GPIO_PINS(133);
-DECLARE_MSM_GPIO_PINS(134);
-DECLARE_MSM_GPIO_PINS(135);
-DECLARE_MSM_GPIO_PINS(136);
-DECLARE_MSM_GPIO_PINS(137);
-DECLARE_MSM_GPIO_PINS(138);
-DECLARE_MSM_GPIO_PINS(139);
-DECLARE_MSM_GPIO_PINS(140);
-DECLARE_MSM_GPIO_PINS(141);
-DECLARE_MSM_GPIO_PINS(142);
-DECLARE_MSM_GPIO_PINS(143);
-DECLARE_MSM_GPIO_PINS(144);
-DECLARE_MSM_GPIO_PINS(145);
-
-static const unsigned int sdc1_clk_pins[] = { 146 };
-static const unsigned int sdc1_cmd_pins[] = { 147 };
-static const unsigned int sdc1_data_pins[] = { 148 };
-static const unsigned int sdc2_clk_pins[] = { 149 };
-static const unsigned int sdc2_cmd_pins[] = { 150 };
-static const unsigned int sdc2_data_pins[] = { 151 };
-
-#define FUNCTION(fname)					\
-	[MSM_MUX_##fname] = {				\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7)	\
-	{						\
-		.name = "gpio" #id,			\
-		.pins = gpio##id##_pins,		\
-		.npins = ARRAY_SIZE(gpio##id##_pins),	\
-		.funcs = (int[]){			\
-			MSM_MUX_NA, /* gpio mode */	\
-			MSM_MUX_##f1,			\
-			MSM_MUX_##f2,			\
-			MSM_MUX_##f3,			\
-			MSM_MUX_##f4,			\
-			MSM_MUX_##f5,			\
-			MSM_MUX_##f6,			\
-			MSM_MUX_##f7			\
-		},					\
-		.nfuncs = 8,				\
-		.ctl_reg = 0x1000 + 0x10 * id,		\
-		.io_reg = 0x1004 + 0x10 * id,		\
-		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
-		.intr_status_reg = 0x100c + 0x10 * id,	\
-		.intr_target_reg = 0x1008 + 0x10 * id,	\
-		.mux_bit = 2,				\
-		.pull_bit = 0,				\
-		.drv_bit = 6,				\
-		.oe_bit = 9,				\
-		.in_bit = 0,				\
-		.out_bit = 1,				\
-		.intr_enable_bit = 0,			\
-		.intr_status_bit = 0,			\
-		.intr_target_bit = 5,			\
-		.intr_raw_status_bit = 4,		\
-		.intr_polarity_bit = 1,			\
-		.intr_detection_bit = 2,		\
-		.intr_detection_width = 2,		\
-	}
-
-#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
-	{						\
-		.name = #pg_name,			\
-		.pins = pg_name##_pins,			\
-		.npins = ARRAY_SIZE(pg_name##_pins),	\
-		.ctl_reg = ctl,				\
-		.io_reg = 0,				\
-		.intr_cfg_reg = 0,			\
-		.intr_status_reg = 0,			\
-		.intr_target_reg = 0,			\
-		.mux_bit = -1,				\
-		.pull_bit = pull,			\
-		.drv_bit = drv,				\
-		.oe_bit = -1,				\
-		.in_bit = -1,				\
-		.out_bit = -1,				\
-		.intr_enable_bit = -1,			\
-		.intr_status_bit = -1,			\
-		.intr_target_bit = -1,			\
-		.intr_raw_status_bit = -1,		\
-		.intr_polarity_bit = -1,		\
-		.intr_detection_bit = -1,		\
-		.intr_detection_width = -1,		\
-	}
-
-/*
- * TODO: Add the rest of the possible functions and fill out
- * the pingroup table below.
- */
-enum msm8x74_functions {
-	MSM_MUX_cci_i2c0,
-	MSM_MUX_cci_i2c1,
-	MSM_MUX_blsp_i2c1,
-	MSM_MUX_blsp_i2c2,
-	MSM_MUX_blsp_i2c3,
-	MSM_MUX_blsp_i2c4,
-	MSM_MUX_blsp_i2c5,
-	MSM_MUX_blsp_i2c6,
-	MSM_MUX_blsp_i2c7,
-	MSM_MUX_blsp_i2c8,
-	MSM_MUX_blsp_i2c9,
-	MSM_MUX_blsp_i2c10,
-	MSM_MUX_blsp_i2c11,
-	MSM_MUX_blsp_i2c12,
-	MSM_MUX_blsp_spi1,
-	MSM_MUX_blsp_spi1_cs1,
-	MSM_MUX_blsp_spi1_cs2,
-	MSM_MUX_blsp_spi1_cs3,
-	MSM_MUX_blsp_spi2,
-	MSM_MUX_blsp_spi2_cs1,
-	MSM_MUX_blsp_spi2_cs2,
-	MSM_MUX_blsp_spi2_cs3,
-	MSM_MUX_blsp_spi3,
-	MSM_MUX_blsp_spi4,
-	MSM_MUX_blsp_spi5,
-	MSM_MUX_blsp_spi6,
-	MSM_MUX_blsp_spi7,
-	MSM_MUX_blsp_spi8,
-	MSM_MUX_blsp_spi9,
-	MSM_MUX_blsp_spi10,
-	MSM_MUX_blsp_spi10_cs1,
-	MSM_MUX_blsp_spi10_cs2,
-	MSM_MUX_blsp_spi10_cs3,
-	MSM_MUX_blsp_spi11,
-	MSM_MUX_blsp_spi12,
-	MSM_MUX_blsp_uart1,
-	MSM_MUX_blsp_uart2,
-	MSM_MUX_blsp_uart3,
-	MSM_MUX_blsp_uart4,
-	MSM_MUX_blsp_uart5,
-	MSM_MUX_blsp_uart6,
-	MSM_MUX_blsp_uart7,
-	MSM_MUX_blsp_uart8,
-	MSM_MUX_blsp_uart9,
-	MSM_MUX_blsp_uart10,
-	MSM_MUX_blsp_uart11,
-	MSM_MUX_blsp_uart12,
-	MSM_MUX_blsp_uim1,
-	MSM_MUX_blsp_uim2,
-	MSM_MUX_blsp_uim3,
-	MSM_MUX_blsp_uim4,
-	MSM_MUX_blsp_uim5,
-	MSM_MUX_blsp_uim6,
-	MSM_MUX_blsp_uim7,
-	MSM_MUX_blsp_uim8,
-	MSM_MUX_blsp_uim9,
-	MSM_MUX_blsp_uim10,
-	MSM_MUX_blsp_uim11,
-	MSM_MUX_blsp_uim12,
-	MSM_MUX_uim1,
-	MSM_MUX_uim2,
-	MSM_MUX_uim_batt_alarm,
-	MSM_MUX_sdc3,
-	MSM_MUX_sdc4,
-	MSM_MUX_gcc_gp_clk1,
-	MSM_MUX_gcc_gp_clk2,
-	MSM_MUX_gcc_gp_clk3,
-	MSM_MUX_qua_mi2s,
-	MSM_MUX_pri_mi2s,
-	MSM_MUX_spkr_mi2s,
-	MSM_MUX_ter_mi2s,
-	MSM_MUX_sec_mi2s,
-	MSM_MUX_hdmi_cec,
-	MSM_MUX_hdmi_ddc,
-	MSM_MUX_hdmi_hpd,
-	MSM_MUX_edp_hpd,
-	MSM_MUX_mdp_vsync,
-	MSM_MUX_cam_mclk0,
-	MSM_MUX_cam_mclk1,
-	MSM_MUX_cam_mclk2,
-	MSM_MUX_cam_mclk3,
-	MSM_MUX_cci_timer0,
-	MSM_MUX_cci_timer1,
-	MSM_MUX_cci_timer2,
-	MSM_MUX_cci_timer3,
-	MSM_MUX_cci_timer4,
-	MSM_MUX_cci_async_in0,
-	MSM_MUX_cci_async_in1,
-	MSM_MUX_cci_async_in2,
-	MSM_MUX_gp_pdm0,
-	MSM_MUX_gp_pdm1,
-	MSM_MUX_gp_pdm2,
-	MSM_MUX_gp0_clk,
-	MSM_MUX_gp1_clk,
-	MSM_MUX_gp_mn,
-	MSM_MUX_tsif1,
-	MSM_MUX_tsif2,
-	MSM_MUX_hsic,
-	MSM_MUX_grfc,
-	MSM_MUX_audio_ref_clk,
-	MSM_MUX_bt,
-	MSM_MUX_fm,
-	MSM_MUX_wlan,
-	MSM_MUX_slimbus,
-	MSM_MUX_NA,
-};
-
-static const char * const blsp_uart1_groups[] = {
-	"gpio0", "gpio1", "gpio2", "gpio3"
-};
-static const char * const blsp_uim1_groups[] = { "gpio0", "gpio1" };
-static const char * const blsp_i2c1_groups[] = { "gpio2", "gpio3" };
-static const char * const blsp_spi1_groups[] = {
-	"gpio0", "gpio1", "gpio2", "gpio3"
-};
-static const char * const blsp_spi1_cs1_groups[] = { "gpio8" };
-static const char * const blsp_spi1_cs2_groups[] = { "gpio9", "gpio11" };
-static const char * const blsp_spi1_cs3_groups[] = { "gpio10" };
-
-static const char * const blsp_uart2_groups[] = {
-	"gpio4", "gpio5", "gpio6", "gpio7"
-};
-static const char * const blsp_uim2_groups[] = { "gpio4", "gpio5" };
-static const char * const blsp_i2c2_groups[] = { "gpio6", "gpio7" };
-static const char * const blsp_spi2_groups[] = {
-	"gpio4", "gpio5", "gpio6", "gpio7"
-};
-static const char * const blsp_spi2_cs1_groups[] = { "gpio53", "gpio62" };
-static const char * const blsp_spi2_cs2_groups[] = { "gpio54", "gpio63" };
-static const char * const blsp_spi2_cs3_groups[] = { "gpio66" };
-
-static const char * const blsp_uart3_groups[] = {
-	"gpio8", "gpio9", "gpio10", "gpio11"
-};
-static const char * const blsp_uim3_groups[] = { "gpio8", "gpio9" };
-static const char * const blsp_i2c3_groups[] = { "gpio10", "gpio11" };
-static const char * const blsp_spi3_groups[] = {
-	"gpio8", "gpio9", "gpio10", "gpio11"
-};
-
-static const char * const cci_i2c0_groups[] = { "gpio19", "gpio20" };
-static const char * const cci_i2c1_groups[] = { "gpio21", "gpio22" };
-
-static const char * const blsp_uart4_groups[] = {
-	"gpio19", "gpio20", "gpio21", "gpio22"
-};
-static const char * const blsp_uim4_groups[] = { "gpio19", "gpio20" };
-static const char * const blsp_i2c4_groups[] = { "gpio21", "gpio22" };
-static const char * const blsp_spi4_groups[] = {
-	"gpio19", "gpio20", "gpio21", "gpio22"
-};
-
-static const char * const blsp_uart5_groups[] = {
-	"gpio23", "gpio24", "gpio25", "gpio26"
-};
-static const char * const blsp_uim5_groups[] = { "gpio23", "gpio24" };
-static const char * const blsp_i2c5_groups[] = { "gpio25", "gpio26" };
-static const char * const blsp_spi5_groups[] = {
-	"gpio23", "gpio24", "gpio25", "gpio26"
-};
-
-static const char * const blsp_uart6_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30"
-};
-static const char * const blsp_uim6_groups[] = { "gpio27", "gpio28" };
-static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" };
-static const char * const blsp_spi6_groups[] = {
-	"gpio27", "gpio28", "gpio29", "gpio30"
-};
-
-static const char * const blsp_uart7_groups[] = {
-	"gpio41", "gpio42", "gpio43", "gpio44"
-};
-static const char * const blsp_uim7_groups[] = { "gpio41", "gpio42" };
-static const char * const blsp_i2c7_groups[] = { "gpio43", "gpio44" };
-static const char * const blsp_spi7_groups[] = {
-	"gpio41", "gpio42", "gpio43", "gpio44"
-};
-
-static const char * const blsp_uart8_groups[] = {
-	"gpio45", "gpio46", "gpio47", "gpio48"
-};
-static const char * const blsp_uim8_groups[] = { "gpio45", "gpio46" };
-static const char * const blsp_i2c8_groups[] = { "gpio47", "gpio48" };
-static const char * const blsp_spi8_groups[] = {
-	"gpio45", "gpio46", "gpio47", "gpio48"
-};
-
-static const char * const blsp_uart9_groups[] = {
-	"gpio49", "gpio50", "gpio51", "gpio52"
-};
-static const char * const blsp_uim9_groups[] = { "gpio49", "gpio50" };
-static const char * const blsp_i2c9_groups[] = { "gpio51", "gpio52" };
-static const char * const blsp_spi9_groups[] = {
-	"gpio49", "gpio50", "gpio51", "gpio52"
-};
-
-static const char * const blsp_uart10_groups[] = {
-	"gpio53", "gpio54", "gpio55", "gpio56"
-};
-static const char * const blsp_uim10_groups[] = { "gpio53", "gpio54" };
-static const char * const blsp_i2c10_groups[] = { "gpio55", "gpio56" };
-static const char * const blsp_spi10_groups[] = {
-	"gpio53", "gpio54", "gpio55", "gpio56"
-};
-static const char * const blsp_spi10_cs1_groups[] = { "gpio47", "gpio67" };
-static const char * const blsp_spi10_cs2_groups[] = { "gpio48", "gpio68" };
-static const char * const blsp_spi10_cs3_groups[] = { "gpio90" };
-
-static const char * const blsp_uart11_groups[] = {
-	"gpio81", "gpio82", "gpio83", "gpio84"
-};
-static const char * const blsp_uim11_groups[] = { "gpio81", "gpio82" };
-static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" };
-static const char * const blsp_spi11_groups[] = {
-	"gpio81", "gpio82", "gpio83", "gpio84"
-};
-
-static const char * const blsp_uart12_groups[] = {
-	"gpio85", "gpio86", "gpio87", "gpio88"
-};
-static const char * const blsp_uim12_groups[] = { "gpio85", "gpio86" };
-static const char * const blsp_i2c12_groups[] = { "gpio87", "gpio88" };
-static const char * const blsp_spi12_groups[] = {
-	"gpio85", "gpio86", "gpio87", "gpio88"
-};
-
-static const char * const uim1_groups[] = {
-	"gpio97", "gpio98", "gpio99", "gpio100"
-};
-
-static const char * const uim2_groups[] = {
-	"gpio49", "gpio50", "gpio51", "gpio52"
-};
-
-static const char * const uim_batt_alarm_groups[] = { "gpio101" };
-
-static const char * const sdc3_groups[] = {
-	"gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40"
-};
-
-static const char * const sdc4_groups[] = {
-	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
-};
-
-static const char * const gp0_clk_groups[] = { "gpio26" };
-static const char * const gp1_clk_groups[] = { "gpio27", "gpio57", "gpio78" };
-static const char * const gp_mn_groups[] = { "gpio29" };
-static const char * const gcc_gp_clk1_groups[] = { "gpio57", "gpio78" };
-static const char * const gcc_gp_clk2_groups[] = { "gpio58", "gpio81" };
-static const char * const gcc_gp_clk3_groups[] = { "gpio59", "gpio82" };
-
-static const char * const qua_mi2s_groups[] = {
-	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
-};
-
-static const char * const pri_mi2s_groups[] = {
-	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
-};
-
-static const char * const spkr_mi2s_groups[] = {
-	"gpio69", "gpio70", "gpio71", "gpio72"
-};
-
-static const char * const ter_mi2s_groups[] = {
-	"gpio73", "gpio74", "gpio75", "gpio76", "gpio77"
-};
-
-static const char * const sec_mi2s_groups[] = {
-	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
-};
-
-static const char * const hdmi_cec_groups[] = { "gpio31" };
-static const char * const hdmi_ddc_groups[] = { "gpio32", "gpio33" };
-static const char * const hdmi_hpd_groups[] = { "gpio34" };
-static const char * const edp_hpd_groups[] = { "gpio102" };
-
-static const char * const mdp_vsync_groups[] = { "gpio12", "gpio13", "gpio14" };
-static const char * const cam_mclk0_groups[] = { "gpio15" };
-static const char * const cam_mclk1_groups[] = { "gpio16" };
-static const char * const cam_mclk2_groups[] = { "gpio17" };
-static const char * const cam_mclk3_groups[] = { "gpio18" };
-
-static const char * const cci_timer0_groups[] = { "gpio23" };
-static const char * const cci_timer1_groups[] = { "gpio24" };
-static const char * const cci_timer2_groups[] = { "gpio25" };
-static const char * const cci_timer3_groups[] = { "gpio26" };
-static const char * const cci_timer4_groups[] = { "gpio27" };
-static const char * const cci_async_in0_groups[] = { "gpio28" };
-static const char * const cci_async_in1_groups[] = { "gpio26" };
-static const char * const cci_async_in2_groups[] = { "gpio27" };
-
-static const char * const gp_pdm0_groups[] = { "gpio54", "gpio68" };
-static const char * const gp_pdm1_groups[] = { "gpio74", "gpio86" };
-static const char * const gp_pdm2_groups[] = { "gpio63", "gpio79" };
-
-static const char * const tsif1_groups[] = {
-	"gpio89", "gpio90", "gpio91", "gpio92"
-};
-
-static const char * const tsif2_groups[] = {
-	"gpio93", "gpio94", "gpio95", "gpio96"
-};
-
-static const char * const hsic_groups[] = { "gpio144", "gpio145" };
-static const char * const grfc_groups[] = {
-	"gpio104", "gpio105", "gpio106", "gpio107", "gpio108", "gpio109",
-	"gpio110", "gpio111", "gpio112", "gpio113", "gpio114", "gpio115",
-	"gpio116", "gpio117", "gpio118", "gpio119", "gpio120", "gpio121",
-	"gpio122", "gpio123", "gpio124", "gpio125", "gpio126", "gpio127",
-	"gpio128", "gpio136", "gpio137", "gpio141", "gpio143"
-};
-
-static const char * const audio_ref_clk_groups[] = { "gpio69" };
-
-static const char * const bt_groups[] = { "gpio35", "gpio43", "gpio44" };
-
-static const char * const fm_groups[] = { "gpio41", "gpio42" };
-
-static const char * const wlan_groups[] = {
-	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40"
-};
-
-static const char * const slimbus_groups[] = { "gpio70", "gpio71" };
-
-static const struct msm_function msm8x74_functions[] = {
-	FUNCTION(cci_i2c0),
-	FUNCTION(cci_i2c1),
-	FUNCTION(uim1),
-	FUNCTION(uim2),
-	FUNCTION(uim_batt_alarm),
-	FUNCTION(blsp_uim1),
-	FUNCTION(blsp_uim2),
-	FUNCTION(blsp_uim3),
-	FUNCTION(blsp_uim4),
-	FUNCTION(blsp_uim5),
-	FUNCTION(blsp_uim6),
-	FUNCTION(blsp_uim7),
-	FUNCTION(blsp_uim8),
-	FUNCTION(blsp_uim9),
-	FUNCTION(blsp_uim10),
-	FUNCTION(blsp_uim11),
-	FUNCTION(blsp_uim12),
-	FUNCTION(blsp_i2c1),
-	FUNCTION(blsp_i2c2),
-	FUNCTION(blsp_i2c3),
-	FUNCTION(blsp_i2c4),
-	FUNCTION(blsp_i2c5),
-	FUNCTION(blsp_i2c6),
-	FUNCTION(blsp_i2c7),
-	FUNCTION(blsp_i2c8),
-	FUNCTION(blsp_i2c9),
-	FUNCTION(blsp_i2c10),
-	FUNCTION(blsp_i2c11),
-	FUNCTION(blsp_i2c12),
-	FUNCTION(blsp_spi1),
-	FUNCTION(blsp_spi1_cs1),
-	FUNCTION(blsp_spi1_cs2),
-	FUNCTION(blsp_spi1_cs3),
-	FUNCTION(blsp_spi2),
-	FUNCTION(blsp_spi2_cs1),
-	FUNCTION(blsp_spi2_cs2),
-	FUNCTION(blsp_spi2_cs3),
-	FUNCTION(blsp_spi3),
-	FUNCTION(blsp_spi4),
-	FUNCTION(blsp_spi5),
-	FUNCTION(blsp_spi6),
-	FUNCTION(blsp_spi7),
-	FUNCTION(blsp_spi8),
-	FUNCTION(blsp_spi9),
-	FUNCTION(blsp_spi10),
-	FUNCTION(blsp_spi10_cs1),
-	FUNCTION(blsp_spi10_cs2),
-	FUNCTION(blsp_spi10_cs3),
-	FUNCTION(blsp_spi11),
-	FUNCTION(blsp_spi12),
-	FUNCTION(blsp_uart1),
-	FUNCTION(blsp_uart2),
-	FUNCTION(blsp_uart3),
-	FUNCTION(blsp_uart4),
-	FUNCTION(blsp_uart5),
-	FUNCTION(blsp_uart6),
-	FUNCTION(blsp_uart7),
-	FUNCTION(blsp_uart8),
-	FUNCTION(blsp_uart9),
-	FUNCTION(blsp_uart10),
-	FUNCTION(blsp_uart11),
-	FUNCTION(blsp_uart12),
-	FUNCTION(sdc3),
-	FUNCTION(sdc4),
-	FUNCTION(gcc_gp_clk1),
-	FUNCTION(gcc_gp_clk2),
-	FUNCTION(gcc_gp_clk3),
-	FUNCTION(qua_mi2s),
-	FUNCTION(pri_mi2s),
-	FUNCTION(spkr_mi2s),
-	FUNCTION(ter_mi2s),
-	FUNCTION(sec_mi2s),
-	FUNCTION(mdp_vsync),
-	FUNCTION(cam_mclk0),
-	FUNCTION(cam_mclk1),
-	FUNCTION(cam_mclk2),
-	FUNCTION(cam_mclk3),
-	FUNCTION(cci_timer0),
-	FUNCTION(cci_timer1),
-	FUNCTION(cci_timer2),
-	FUNCTION(cci_timer3),
-	FUNCTION(cci_timer4),
-	FUNCTION(cci_async_in0),
-	FUNCTION(cci_async_in1),
-	FUNCTION(cci_async_in2),
-	FUNCTION(hdmi_cec),
-	FUNCTION(hdmi_ddc),
-	FUNCTION(hdmi_hpd),
-	FUNCTION(edp_hpd),
-	FUNCTION(gp_pdm0),
-	FUNCTION(gp_pdm1),
-	FUNCTION(gp_pdm2),
-	FUNCTION(gp0_clk),
-	FUNCTION(gp1_clk),
-	FUNCTION(gp_mn),
-	FUNCTION(tsif1),
-	FUNCTION(tsif2),
-	FUNCTION(hsic),
-	FUNCTION(grfc),
-	FUNCTION(audio_ref_clk),
-	FUNCTION(bt),
-	FUNCTION(fm),
-	FUNCTION(wlan),
-	FUNCTION(slimbus),
-};
-
-static const struct msm_pingroup msm8x74_groups[] = {
-	PINGROUP(0,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA),
-	PINGROUP(1,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA),
-	PINGROUP(2,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA),
-	PINGROUP(3,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA),
-	PINGROUP(4,   blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA),
-	PINGROUP(5,   blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA),
-	PINGROUP(6,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA),
-	PINGROUP(7,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA),
-	PINGROUP(8,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA, NA),
-	PINGROUP(9,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA, NA),
-	PINGROUP(10,  blsp_spi3, blsp_uart3, blsp_i2c3, blsp_spi1_cs3, NA, NA, NA),
-	PINGROUP(11,  blsp_spi3, blsp_uart3, blsp_i2c3, blsp_spi1_cs2, NA, NA, NA),
-	PINGROUP(12,  mdp_vsync, NA, NA, NA, NA, NA, NA),
-	PINGROUP(13,  mdp_vsync, NA, NA, NA, NA, NA, NA),
-	PINGROUP(14,  mdp_vsync, NA, NA, NA, NA, NA, NA),
-	PINGROUP(15,  cam_mclk0, NA, NA, NA, NA, NA, NA),
-	PINGROUP(16,  cam_mclk1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(17,  cam_mclk2, NA, NA, NA, NA, NA, NA),
-	PINGROUP(18,  cam_mclk3, NA, NA, NA, NA, NA, NA),
-	PINGROUP(19,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA),
-	PINGROUP(20,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA),
-	PINGROUP(21,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA),
-	PINGROUP(22,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA),
-	PINGROUP(23,  cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA),
-	PINGROUP(24,  cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA),
-	PINGROUP(25,  cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA),
-	PINGROUP(26,  cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5, blsp_i2c5, gp0_clk, NA),
-	PINGROUP(27,  cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk, NA),
-	PINGROUP(28,  cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, NA, NA, NA),
-	PINGROUP(29,  blsp_spi6, blsp_uart6, blsp_i2c6, gp_mn, NA, NA, NA),
-	PINGROUP(30,  blsp_spi6, blsp_uart6, blsp_i2c6, NA, NA, NA, NA),
-	PINGROUP(31,  hdmi_cec, NA, NA, NA, NA, NA, NA),
-	PINGROUP(32,  hdmi_ddc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(33,  hdmi_ddc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(34,  hdmi_hpd, NA, NA, NA, NA, NA, NA),
-	PINGROUP(35,  bt, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(36,  wlan, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(37,  wlan, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(38,  wlan, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(39,  wlan, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(40,  wlan, sdc3, NA, NA, NA, NA, NA),
-	PINGROUP(41,  fm, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA),
-	PINGROUP(42,  fm, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA),
-	PINGROUP(43,  bt, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA),
-	PINGROUP(44,  bt, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA),
-	PINGROUP(45,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA),
-	PINGROUP(46,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA),
-	PINGROUP(47,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA, NA),
-	PINGROUP(48,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA, NA),
-	PINGROUP(49,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA),
-	PINGROUP(50,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA),
-	PINGROUP(51,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA),
-	PINGROUP(52,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA),
-	PINGROUP(53,  blsp_spi10, blsp_uart10, blsp_uim10, blsp_spi2_cs1, NA, NA, NA),
-	PINGROUP(54,  blsp_spi10, blsp_uart10, blsp_uim10, blsp_spi2_cs2, gp_pdm0, NA, NA),
-	PINGROUP(55,  blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA),
-	PINGROUP(56,  blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA),
-	PINGROUP(57,  qua_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA),
-	PINGROUP(58,  qua_mi2s, gcc_gp_clk2, NA, NA, NA, NA, NA),
-	PINGROUP(59,  qua_mi2s, gcc_gp_clk3, NA, NA, NA, NA, NA),
-	PINGROUP(60,  qua_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(61,  qua_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(62,  qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA),
-	PINGROUP(63,  qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA),
-	PINGROUP(64,  pri_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(65,  pri_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(66,  pri_mi2s, blsp_spi2_cs3, NA, NA, NA, NA, NA),
-	PINGROUP(67,  pri_mi2s, blsp_spi10_cs1, NA, NA, NA, NA, NA),
-	PINGROUP(68,  pri_mi2s, blsp_spi10_cs2, gp_pdm0, NA, NA, NA, NA),
-	PINGROUP(69,  spkr_mi2s, audio_ref_clk, NA, NA, NA, NA, NA),
-	PINGROUP(70,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA),
-	PINGROUP(71,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA),
-	PINGROUP(72,  spkr_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(73,  ter_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(74,  ter_mi2s, gp_pdm1, NA, NA, NA, NA, NA),
-	PINGROUP(75,  ter_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(76,  ter_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(77,  ter_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(78,  sec_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA),
-	PINGROUP(79,  sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA),
-	PINGROUP(80,  sec_mi2s, NA, NA, NA, NA, NA, NA),
-	PINGROUP(81,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, gcc_gp_clk2, NA, NA),
-	PINGROUP(82,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, gcc_gp_clk3, NA, NA),
-	PINGROUP(83,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA),
-	PINGROUP(84,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA),
-	PINGROUP(85,  blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, NA, NA),
-	PINGROUP(86,  blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA, NA, NA),
-	PINGROUP(87,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA),
-	PINGROUP(88,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA),
-	PINGROUP(89,  tsif1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(90,  tsif1, blsp_spi10_cs3, NA, NA, NA, NA, NA),
-	PINGROUP(91,  tsif1, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(92,  tsif1, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(93,  tsif2, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(94,  tsif2, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(95,  tsif2, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(96,  tsif2, sdc4, NA, NA, NA, NA, NA),
-	PINGROUP(97,  uim1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(98,  uim1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(99,  uim1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA),
-	PINGROUP(102, edp_hpd, NA, NA, NA, NA, NA, NA),
-	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(104, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(105, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(106, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(107, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(108, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(109, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(110, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(111, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(112, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(113, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(114, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(115, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(116, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(117, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(118, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(119, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(120, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(121, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(122, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(123, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(124, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(125, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(126, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(127, grfc, NA, NA, NA, NA, NA, NA),
-	PINGROUP(128, NA, grfc, NA, NA, NA, NA, NA),
-	PINGROUP(129, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(130, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(131, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(132, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(133, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(134, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(135, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(136, NA, grfc, NA, NA, NA, NA, NA),
-	PINGROUP(137, NA, grfc, NA, NA, NA, NA, NA),
-	PINGROUP(138, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(139, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(140, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(141, NA, grfc, NA, NA, NA, NA, NA),
-	PINGROUP(142, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(143, NA, grfc, NA, NA, NA, NA, NA),
-	PINGROUP(144, hsic, NA, NA, NA, NA, NA, NA),
-	PINGROUP(145, hsic, NA, NA, NA, NA, NA, NA),
-	SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6),
-	SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3),
-	SDC_PINGROUP(sdc1_data, 0x2044, 9, 0),
-	SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6),
-	SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3),
-	SDC_PINGROUP(sdc2_data, 0x2048, 9, 0),
-};
-
-#define NUM_GPIO_PINGROUPS 146
-
-static const struct msm_pinctrl_soc_data msm8x74_pinctrl = {
-	.pins = msm8x74_pins,
-	.npins = ARRAY_SIZE(msm8x74_pins),
-	.functions = msm8x74_functions,
-	.nfunctions = ARRAY_SIZE(msm8x74_functions),
-	.groups = msm8x74_groups,
-	.ngroups = ARRAY_SIZE(msm8x74_groups),
-	.ngpios = NUM_GPIO_PINGROUPS,
-};
-
-static int msm8x74_pinctrl_probe(struct platform_device *pdev)
-{
-	return msm_pinctrl_probe(pdev, &msm8x74_pinctrl);
-}
-
-static const struct of_device_id msm8x74_pinctrl_of_match[] = {
-	{ .compatible = "qcom,msm8974-pinctrl", },
-	{ },
-};
-
-static struct platform_driver msm8x74_pinctrl_driver = {
-	.driver = {
-		.name = "msm8x74-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = msm8x74_pinctrl_of_match,
-	},
-	.probe = msm8x74_pinctrl_probe,
-	.remove = msm_pinctrl_remove,
-};
-
-static int __init msm8x74_pinctrl_init(void)
-{
-	return platform_driver_register(&msm8x74_pinctrl_driver);
-}
-arch_initcall(msm8x74_pinctrl_init);
-
-static void __exit msm8x74_pinctrl_exit(void)
-{
-	platform_driver_unregister(&msm8x74_pinctrl_driver);
-}
-module_exit(msm8x74_pinctrl_exit);
-
-MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
-MODULE_DESCRIPTION("Qualcomm MSM8x74 pinctrl driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, msm8x74_pinctrl_of_match);
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,939 +0,0 @@
-/*
- * Copyright (c) 2013, Sony Mobile Communications AB.
- * Copyright (c) 2013, 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/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-
-#include "core.h"
-#include "pinconf.h"
-#include "pinctrl-msm.h"
-#include "pinctrl-utils.h"
-
-#define MAX_NR_GPIO 300
-
-/**
- * struct msm_pinctrl - state for a pinctrl-msm device
- * @dev:            device handle.
- * @pctrl:          pinctrl handle.
- * @chip:           gpiochip handle.
- * @irq:            parent irq for the TLMM irq_chip.
- * @lock:           Spinlock to protect register resources as well
- *                  as msm_pinctrl data structures.
- * @enabled_irqs:   Bitmap of currently enabled irqs.
- * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
- *                  detection.
- * @soc;            Reference to soc_data of platform specific data.
- * @regs:           Base address for the TLMM register map.
- */
-struct msm_pinctrl {
-	struct device *dev;
-	struct pinctrl_dev *pctrl;
-	struct gpio_chip chip;
-	int irq;
-
-	spinlock_t lock;
-
-	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
-	DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
-
-	const struct msm_pinctrl_soc_data *soc;
-	void __iomem *regs;
-};
-
-static inline struct msm_pinctrl *to_msm_pinctrl(struct gpio_chip *gc)
-{
-	return container_of(gc, struct msm_pinctrl, chip);
-}
-
-static int msm_get_groups_count(struct pinctrl_dev *pctldev)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctrl->soc->ngroups;
-}
-
-static const char *msm_get_group_name(struct pinctrl_dev *pctldev,
-				      unsigned group)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctrl->soc->groups[group].name;
-}
-
-static int msm_get_group_pins(struct pinctrl_dev *pctldev,
-			      unsigned group,
-			      const unsigned **pins,
-			      unsigned *num_pins)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	*pins = pctrl->soc->groups[group].pins;
-	*num_pins = pctrl->soc->groups[group].npins;
-	return 0;
-}
-
-static const struct pinctrl_ops msm_pinctrl_ops = {
-	.get_groups_count	= msm_get_groups_count,
-	.get_group_name		= msm_get_group_name,
-	.get_group_pins		= msm_get_group_pins,
-	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
-};
-
-static int msm_get_functions_count(struct pinctrl_dev *pctldev)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctrl->soc->nfunctions;
-}
-
-static const char *msm_get_function_name(struct pinctrl_dev *pctldev,
-					 unsigned function)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctrl->soc->functions[function].name;
-}
-
-static int msm_get_function_groups(struct pinctrl_dev *pctldev,
-				   unsigned function,
-				   const char * const **groups,
-				   unsigned * const num_groups)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-
-	*groups = pctrl->soc->functions[function].groups;
-	*num_groups = pctrl->soc->functions[function].ngroups;
-	return 0;
-}
-
-static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
-			     unsigned function,
-			     unsigned group)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-	int i;
-
-	g = &pctrl->soc->groups[group];
-
-	if (WARN_ON(g->mux_bit < 0))
-		return -EINVAL;
-
-	for (i = 0; i < g->nfuncs; i++) {
-		if (g->funcs[i] == function)
-			break;
-	}
-
-	if (WARN_ON(i == g->nfuncs))
-		return -EINVAL;
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->ctl_reg);
-	val &= ~(0x7 << g->mux_bit);
-	val |= i << g->mux_bit;
-	writel(val, pctrl->regs + g->ctl_reg);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	return 0;
-}
-
-static void msm_pinmux_disable(struct pinctrl_dev *pctldev,
-			       unsigned function,
-			       unsigned group)
-{
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[group];
-
-	if (WARN_ON(g->mux_bit < 0))
-		return;
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	/* Clear the mux bits to select gpio mode */
-	val = readl(pctrl->regs + g->ctl_reg);
-	val &= ~(0x7 << g->mux_bit);
-	writel(val, pctrl->regs + g->ctl_reg);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-static const struct pinmux_ops msm_pinmux_ops = {
-	.get_functions_count	= msm_get_functions_count,
-	.get_function_name	= msm_get_function_name,
-	.get_function_groups	= msm_get_function_groups,
-	.enable			= msm_pinmux_enable,
-	.disable		= msm_pinmux_disable,
-};
-
-static int msm_config_reg(struct msm_pinctrl *pctrl,
-			  const struct msm_pingroup *g,
-			  unsigned param,
-			  unsigned *mask,
-			  unsigned *bit)
-{
-	switch (param) {
-	case PIN_CONFIG_BIAS_DISABLE:
-	case PIN_CONFIG_BIAS_PULL_DOWN:
-	case PIN_CONFIG_BIAS_PULL_UP:
-		*bit = g->pull_bit;
-		*mask = 3;
-		break;
-	case PIN_CONFIG_DRIVE_STRENGTH:
-		*bit = g->drv_bit;
-		*mask = 7;
-		break;
-	case PIN_CONFIG_OUTPUT:
-		*bit = g->oe_bit;
-		*mask = 1;
-		break;
-	default:
-		dev_err(pctrl->dev, "Invalid config param %04x\n", param);
-		return -ENOTSUPP;
-	}
-
-	return 0;
-}
-
-static int msm_config_get(struct pinctrl_dev *pctldev,
-			  unsigned int pin,
-			  unsigned long *config)
-{
-	dev_err(pctldev->dev, "pin_config_set op not supported\n");
-	return -ENOTSUPP;
-}
-
-static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
-				unsigned long *configs, unsigned num_configs)
-{
-	dev_err(pctldev->dev, "pin_config_set op not supported\n");
-	return -ENOTSUPP;
-}
-
-#define MSM_NO_PULL	0
-#define MSM_PULL_DOWN	1
-#define MSM_PULL_UP	3
-
-static unsigned msm_regval_to_drive(u32 val)
-{
-	return (val + 1) * 2;
-}
-
-static int msm_config_group_get(struct pinctrl_dev *pctldev,
-				unsigned int group,
-				unsigned long *config)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	unsigned param = pinconf_to_config_param(*config);
-	unsigned mask;
-	unsigned arg;
-	unsigned bit;
-	int ret;
-	u32 val;
-
-	g = &pctrl->soc->groups[group];
-
-	ret = msm_config_reg(pctrl, g, param, &mask, &bit);
-	if (ret < 0)
-		return ret;
-
-	val = readl(pctrl->regs + g->ctl_reg);
-	arg = (val >> bit) & mask;
-
-	/* Convert register value to pinconf value */
-	switch (param) {
-	case PIN_CONFIG_BIAS_DISABLE:
-		arg = arg == MSM_NO_PULL;
-		break;
-	case PIN_CONFIG_BIAS_PULL_DOWN:
-		arg = arg == MSM_PULL_DOWN;
-		break;
-	case PIN_CONFIG_BIAS_PULL_UP:
-		arg = arg == MSM_PULL_UP;
-		break;
-	case PIN_CONFIG_DRIVE_STRENGTH:
-		arg = msm_regval_to_drive(arg);
-		break;
-	case PIN_CONFIG_OUTPUT:
-		/* Pin is not output */
-		if (!arg)
-			return -EINVAL;
-
-		val = readl(pctrl->regs + g->io_reg);
-		arg = !!(val & BIT(g->in_bit));
-		break;
-	default:
-		dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
-			param);
-		return -EINVAL;
-	}
-
-	*config = pinconf_to_config_packed(param, arg);
-
-	return 0;
-}
-
-static int msm_config_group_set(struct pinctrl_dev *pctldev,
-				unsigned group,
-				unsigned long *configs,
-				unsigned num_configs)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	unsigned long flags;
-	unsigned param;
-	unsigned mask;
-	unsigned arg;
-	unsigned bit;
-	int ret;
-	u32 val;
-	int i;
-
-	g = &pctrl->soc->groups[group];
-
-	for (i = 0; i < num_configs; i++) {
-		param = pinconf_to_config_param(configs[i]);
-		arg = pinconf_to_config_argument(configs[i]);
-
-		ret = msm_config_reg(pctrl, g, param, &mask, &bit);
-		if (ret < 0)
-			return ret;
-
-		/* Convert pinconf values to register values */
-		switch (param) {
-		case PIN_CONFIG_BIAS_DISABLE:
-			arg = MSM_NO_PULL;
-			break;
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			arg = MSM_PULL_DOWN;
-			break;
-		case PIN_CONFIG_BIAS_PULL_UP:
-			arg = MSM_PULL_UP;
-			break;
-		case PIN_CONFIG_DRIVE_STRENGTH:
-			/* Check for invalid values */
-			if (arg > 16 || arg < 2 || (arg % 2) != 0)
-				arg = -1;
-			else
-				arg = (arg / 2) - 1;
-			break;
-		case PIN_CONFIG_OUTPUT:
-			/* set output value */
-			spin_lock_irqsave(&pctrl->lock, flags);
-			val = readl(pctrl->regs + g->io_reg);
-			if (arg)
-				val |= BIT(g->out_bit);
-			else
-				val &= ~BIT(g->out_bit);
-			writel(val, pctrl->regs + g->io_reg);
-			spin_unlock_irqrestore(&pctrl->lock, flags);
-
-			/* enable output */
-			arg = 1;
-			break;
-		default:
-			dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
-				param);
-			return -EINVAL;
-		}
-
-		/* Range-check user-supplied value */
-		if (arg & ~mask) {
-			dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg);
-			return -EINVAL;
-		}
-
-		spin_lock_irqsave(&pctrl->lock, flags);
-		val = readl(pctrl->regs + g->ctl_reg);
-		val &= ~(mask << bit);
-		val |= arg << bit;
-		writel(val, pctrl->regs + g->ctl_reg);
-		spin_unlock_irqrestore(&pctrl->lock, flags);
-	}
-
-	return 0;
-}
-
-static const struct pinconf_ops msm_pinconf_ops = {
-	.pin_config_get		= msm_config_get,
-	.pin_config_set		= msm_config_set,
-	.pin_config_group_get	= msm_config_group_get,
-	.pin_config_group_set	= msm_config_group_set,
-};
-
-static struct pinctrl_desc msm_pinctrl_desc = {
-	.pctlops = &msm_pinctrl_ops,
-	.pmxops = &msm_pinmux_ops,
-	.confops = &msm_pinconf_ops,
-	.owner = THIS_MODULE,
-};
-
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[offset];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->ctl_reg);
-	val &= ~BIT(g->oe_bit);
-	writel(val, pctrl->regs + g->ctl_reg);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	return 0;
-}
-
-static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[offset];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->io_reg);
-	if (value)
-		val |= BIT(g->out_bit);
-	else
-		val &= ~BIT(g->out_bit);
-	writel(val, pctrl->regs + g->io_reg);
-
-	val = readl(pctrl->regs + g->ctl_reg);
-	val |= BIT(g->oe_bit);
-	writel(val, pctrl->regs + g->ctl_reg);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	return 0;
-}
-
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
-	u32 val;
-
-	g = &pctrl->soc->groups[offset];
-
-	val = readl(pctrl->regs + g->io_reg);
-	return !!(val & BIT(g->in_bit));
-}
-
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[offset];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->io_reg);
-	if (value)
-		val |= BIT(g->out_bit);
-	else
-		val &= ~BIT(g->out_bit);
-	writel(val, pctrl->regs + g->io_reg);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	int gpio = chip->base + offset;
-	return pinctrl_request_gpio(gpio);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	int gpio = chip->base + offset;
-	return pinctrl_free_gpio(gpio);
-}
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/seq_file.h>
-
-static void msm_gpio_dbg_show_one(struct seq_file *s,
-				  struct pinctrl_dev *pctldev,
-				  struct gpio_chip *chip,
-				  unsigned offset,
-				  unsigned gpio)
-{
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
-	unsigned func;
-	int is_out;
-	int drive;
-	int pull;
-	u32 ctl_reg;
-
-	static const char * const pulls[] = {
-		"no pull",
-		"pull down",
-		"keeper",
-		"pull up"
-	};
-
-	g = &pctrl->soc->groups[offset];
-	ctl_reg = readl(pctrl->regs + g->ctl_reg);
-
-	is_out = !!(ctl_reg & BIT(g->oe_bit));
-	func = (ctl_reg >> g->mux_bit) & 7;
-	drive = (ctl_reg >> g->drv_bit) & 7;
-	pull = (ctl_reg >> g->pull_bit) & 3;
-
-	seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
-	seq_printf(s, " %dmA", msm_regval_to_drive(drive));
-	seq_printf(s, " %s", pulls[pull]);
-}
-
-static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	unsigned gpio = chip->base;
-	unsigned i;
-
-	for (i = 0; i < chip->ngpio; i++, gpio++) {
-		msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
-		seq_puts(s, "\n");
-	}
-}
-
-#else
-#define msm_gpio_dbg_show NULL
-#endif
-
-static struct gpio_chip msm_gpio_template = {
-	.direction_input  = msm_gpio_direction_input,
-	.direction_output = msm_gpio_direction_output,
-	.get              = msm_gpio_get,
-	.set              = msm_gpio_set,
-	.request          = msm_gpio_request,
-	.free             = msm_gpio_free,
-	.dbg_show         = msm_gpio_dbg_show,
-};
-
-/* For dual-edge interrupts in software, since some hardware has no
- * such support:
- *
- * At appropriate moments, this function may be called to flip the polarity
- * settings of both-edge irq lines to try and catch the next edge.
- *
- * The attempt is considered successful if:
- * - the status bit goes high, indicating that an edge was caught, or
- * - the input value of the gpio doesn't change during the attempt.
- * If the value changes twice during the process, that would cause the first
- * test to fail but would force the second, as two opposite
- * transitions would cause a detection no matter the polarity setting.
- *
- * The do-loop tries to sledge-hammer closed the timing hole between
- * the initial value-read and the polarity-write - if the line value changes
- * during that window, an interrupt is lost, the new polarity setting is
- * incorrect, and the first success test will fail, causing a retry.
- *
- * Algorithm comes from Google's msmgpio driver.
- */
-static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
-					  const struct msm_pingroup *g,
-					  struct irq_data *d)
-{
-	int loop_limit = 100;
-	unsigned val, val2, intstat;
-	unsigned pol;
-
-	do {
-		val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
-
-		pol = readl(pctrl->regs + g->intr_cfg_reg);
-		pol ^= BIT(g->intr_polarity_bit);
-		writel(pol, pctrl->regs + g->intr_cfg_reg);
-
-		val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
-		intstat = readl(pctrl->regs + g->intr_status_reg);
-		if (intstat || (val == val2))
-			return;
-	} while (loop_limit-- > 0);
-	dev_err(pctrl->dev, "dual-edge irq failed to stabilize, %#08x != %#08x\n",
-		val, val2);
-}
-
-static void msm_gpio_irq_mask(struct irq_data *d)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[d->hwirq];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->intr_cfg_reg);
-	val &= ~BIT(g->intr_enable_bit);
-	writel(val, pctrl->regs + g->intr_cfg_reg);
-
-	clear_bit(d->hwirq, pctrl->enabled_irqs);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[d->hwirq];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->intr_status_reg);
-	val &= ~BIT(g->intr_status_bit);
-	writel(val, pctrl->regs + g->intr_status_reg);
-
-	val = readl(pctrl->regs + g->intr_cfg_reg);
-	val |= BIT(g->intr_enable_bit);
-	writel(val, pctrl->regs + g->intr_cfg_reg);
-
-	set_bit(d->hwirq, pctrl->enabled_irqs);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-static void msm_gpio_irq_ack(struct irq_data *d)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[d->hwirq];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	val = readl(pctrl->regs + g->intr_status_reg);
-	if (g->intr_ack_high)
-		val |= BIT(g->intr_status_bit);
-	else
-		val &= ~BIT(g->intr_status_bit);
-	writel(val, pctrl->regs + g->intr_status_reg);
-
-	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
-		msm_gpio_update_dual_edge_pos(pctrl, g, d);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-#define INTR_TARGET_PROC_APPS    4
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	const struct msm_pingroup *g;
-	unsigned long flags;
-	u32 val;
-
-	g = &pctrl->soc->groups[d->hwirq];
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	/*
-	 * For hw without possibility of detecting both edges
-	 */
-	if (g->intr_detection_width == 1 && type == IRQ_TYPE_EDGE_BOTH)
-		set_bit(d->hwirq, pctrl->dual_edge_irqs);
-	else
-		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
-
-	/* Route interrupts to application cpu */
-	val = readl(pctrl->regs + g->intr_target_reg);
-	val &= ~(7 << g->intr_target_bit);
-	val |= INTR_TARGET_PROC_APPS << g->intr_target_bit;
-	writel(val, pctrl->regs + g->intr_target_reg);
-
-	/* Update configuration for gpio.
-	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
-	 * internal circuitry of TLMM, toggling the RAW_STATUS
-	 * could cause the INTR_STATUS to be set for EDGE interrupts.
-	 */
-	val = readl(pctrl->regs + g->intr_cfg_reg);
-	val |= BIT(g->intr_raw_status_bit);
-	if (g->intr_detection_width == 2) {
-		val &= ~(3 << g->intr_detection_bit);
-		val &= ~(1 << g->intr_polarity_bit);
-		switch (type) {
-		case IRQ_TYPE_EDGE_RISING:
-			val |= 1 << g->intr_detection_bit;
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		case IRQ_TYPE_EDGE_FALLING:
-			val |= 2 << g->intr_detection_bit;
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		case IRQ_TYPE_EDGE_BOTH:
-			val |= 3 << g->intr_detection_bit;
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		case IRQ_TYPE_LEVEL_LOW:
-			break;
-		case IRQ_TYPE_LEVEL_HIGH:
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		}
-	} else if (g->intr_detection_width == 1) {
-		val &= ~(1 << g->intr_detection_bit);
-		val &= ~(1 << g->intr_polarity_bit);
-		switch (type) {
-		case IRQ_TYPE_EDGE_RISING:
-			val |= BIT(g->intr_detection_bit);
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		case IRQ_TYPE_EDGE_FALLING:
-			val |= BIT(g->intr_detection_bit);
-			break;
-		case IRQ_TYPE_EDGE_BOTH:
-			val |= BIT(g->intr_detection_bit);
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		case IRQ_TYPE_LEVEL_LOW:
-			break;
-		case IRQ_TYPE_LEVEL_HIGH:
-			val |= BIT(g->intr_polarity_bit);
-			break;
-		}
-	} else {
-		BUG();
-	}
-	writel(val, pctrl->regs + g->intr_cfg_reg);
-
-	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
-		msm_gpio_update_dual_edge_pos(pctrl, g, d);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__irq_set_handler_locked(d->irq, handle_level_irq);
-	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-
-	return 0;
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&pctrl->lock, flags);
-
-	irq_set_irq_wake(pctrl->irq, on);
-
-	spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	return 0;
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
-	.name           = "msmgpio",
-	.irq_mask       = msm_gpio_irq_mask,
-	.irq_unmask     = msm_gpio_irq_unmask,
-	.irq_ack        = msm_gpio_irq_ack,
-	.irq_set_type   = msm_gpio_irq_set_type,
-	.irq_set_wake   = msm_gpio_irq_set_wake,
-};
-
-static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-	const struct msm_pingroup *g;
-	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	struct irq_chip *chip = irq_get_chip(irq);
-	int irq_pin;
-	int handled = 0;
-	u32 val;
-	int i;
-
-	chained_irq_enter(chip, desc);
-
-	/*
-	 * Each pin has it's own IRQ status register, so use
-	 * enabled_irq bitmap to limit the number of reads.
-	 */
-	for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
-		g = &pctrl->soc->groups[i];
-		val = readl(pctrl->regs + g->intr_status_reg);
-		if (val & BIT(g->intr_status_bit)) {
-			irq_pin = irq_find_mapping(gc->irqdomain, i);
-			generic_handle_irq(irq_pin);
-			handled++;
-		}
-	}
-
-	/* No interrupts were flagged */
-	if (handled == 0)
-		handle_bad_irq(irq, desc);
-
-	chained_irq_exit(chip, desc);
-}
-
-static int msm_gpio_init(struct msm_pinctrl *pctrl)
-{
-	struct gpio_chip *chip;
-	int ret;
-	unsigned ngpio = pctrl->soc->ngpios;
-
-	if (WARN_ON(ngpio > MAX_NR_GPIO))
-		return -EINVAL;
-
-	chip = &pctrl->chip;
-	chip->base = 0;
-	chip->ngpio = ngpio;
-	chip->label = dev_name(pctrl->dev);
-	chip->dev = pctrl->dev;
-	chip->owner = THIS_MODULE;
-	chip->of_node = pctrl->dev->of_node;
-
-	ret = gpiochip_add(&pctrl->chip);
-	if (ret) {
-		dev_err(pctrl->dev, "Failed register gpiochip\n");
-		return ret;
-	}
-
-	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
-	if (ret) {
-		dev_err(pctrl->dev, "Failed to add pin range\n");
-		return ret;
-	}
-
-	ret = gpiochip_irqchip_add(chip,
-				   &msm_gpio_irq_chip,
-				   0,
-				   handle_edge_irq,
-				   IRQ_TYPE_NONE);
-	if (ret) {
-		dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
-		return -ENOSYS;
-	}
-
-	gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
-				     msm_gpio_irq_handler);
-
-	return 0;
-}
-
-int msm_pinctrl_probe(struct platform_device *pdev,
-		      const struct msm_pinctrl_soc_data *soc_data)
-{
-	struct msm_pinctrl *pctrl;
-	struct resource *res;
-	int ret;
-
-	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
-	if (!pctrl) {
-		dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n");
-		return -ENOMEM;
-	}
-	pctrl->dev = &pdev->dev;
-	pctrl->soc = soc_data;
-	pctrl->chip = msm_gpio_template;
-
-	spin_lock_init(&pctrl->lock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	pctrl->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(pctrl->regs))
-		return PTR_ERR(pctrl->regs);
-
-	pctrl->irq = platform_get_irq(pdev, 0);
-	if (pctrl->irq < 0) {
-		dev_err(&pdev->dev, "No interrupt defined for msmgpio\n");
-		return pctrl->irq;
-	}
-
-	msm_pinctrl_desc.name = dev_name(&pdev->dev);
-	msm_pinctrl_desc.pins = pctrl->soc->pins;
-	msm_pinctrl_desc.npins = pctrl->soc->npins;
-	pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl);
-	if (!pctrl->pctrl) {
-		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
-	}
-
-	ret = msm_gpio_init(pctrl);
-	if (ret) {
-		pinctrl_unregister(pctrl->pctrl);
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, pctrl);
-
-	dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n");
-
-	return 0;
-}
-EXPORT_SYMBOL(msm_pinctrl_probe);
-
-int msm_pinctrl_remove(struct platform_device *pdev)
-{
-	struct msm_pinctrl *pctrl = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&pctrl->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to remove gpiochip\n");
-		return ret;
-	}
-
-	pinctrl_unregister(pctrl->pctrl);
-
-	return 0;
-}
-EXPORT_SYMBOL(msm_pinctrl_remove);
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm.h
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-msm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-msm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2013, Sony Mobile Communications AB.
- *
- * 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 __PINCTRL_MSM_H__
-#define __PINCTRL_MSM_H__
-
-struct pinctrl_pin_desc;
-
-/**
- * struct msm_function - a pinmux function
- * @name:    Name of the pinmux function.
- * @groups:  List of pingroups for this function.
- * @ngroups: Number of entries in @groups.
- */
-struct msm_function {
-	const char *name;
-	const char * const *groups;
-	unsigned ngroups;
-};
-
-/**
- * struct msm_pingroup - Qualcomm pingroup definition
- * @name:                 Name of the pingroup.
- * @pins:	          A list of pins assigned to this pingroup.
- * @npins:	          Number of entries in @pins.
- * @funcs:                A list of pinmux functions that can be selected for
- *                        this group. The index of the selected function is used
- *                        for programming the function selector.
- *                        Entries should be indices into the groups list of the
- *                        struct msm_pinctrl_soc_data.
- * @ctl_reg:              Offset of the register holding control bits for this group.
- * @io_reg:               Offset of the register holding input/output bits for this group.
- * @intr_cfg_reg:         Offset of the register holding interrupt configuration bits.
- * @intr_status_reg:      Offset of the register holding the status bits for this group.
- * @intr_target_reg:      Offset of the register specifying routing of the interrupts
- *                        from this group.
- * @mux_bit:              Offset in @ctl_reg for the pinmux function selection.
- * @pull_bit:             Offset in @ctl_reg for the bias configuration.
- * @drv_bit:              Offset in @ctl_reg for the drive strength configuration.
- * @oe_bit:               Offset in @ctl_reg for controlling output enable.
- * @in_bit:               Offset in @io_reg for the input bit value.
- * @out_bit:              Offset in @io_reg for the output bit value.
- * @intr_enable_bit:      Offset in @intr_cfg_reg for enabling the interrupt for this group.
- * @intr_status_bit:      Offset in @intr_status_reg for reading and acking the interrupt
- *                        status.
- * @intr_target_bit:      Offset in @intr_target_reg for configuring the interrupt routing.
- * @intr_raw_status_bit:  Offset in @intr_cfg_reg for the raw status bit.
- * @intr_polarity_bit:    Offset in @intr_cfg_reg for specifying polarity of the interrupt.
- * @intr_detection_bit:   Offset in @intr_cfg_reg for specifying interrupt type.
- * @intr_detection_width: Number of bits used for specifying interrupt type,
- *                        Should be 2 for SoCs that can detect both edges in hardware,
- *                        otherwise 1.
- */
-struct msm_pingroup {
-	const char *name;
-	const unsigned *pins;
-	unsigned npins;
-
-	unsigned *funcs;
-	unsigned nfuncs;
-
-	s16 ctl_reg;
-	s16 io_reg;
-	s16 intr_cfg_reg;
-	s16 intr_status_reg;
-	s16 intr_target_reg;
-
-	unsigned mux_bit:5;
-
-	unsigned pull_bit:5;
-	unsigned drv_bit:5;
-
-	unsigned oe_bit:5;
-	unsigned in_bit:5;
-	unsigned out_bit:5;
-
-	unsigned intr_enable_bit:5;
-	unsigned intr_status_bit:5;
-	unsigned intr_ack_high:1;
-
-	unsigned intr_target_bit:5;
-	unsigned intr_raw_status_bit:5;
-	unsigned intr_polarity_bit:5;
-	unsigned intr_detection_bit:5;
-	unsigned intr_detection_width:5;
-};
-
-/**
- * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
- * @pins:       An array describing all pins the pin controller affects.
- * @npins:      The number of entries in @pins.
- * @functions:  An array describing all mux functions the SoC supports.
- * @nfunctions: The number of entries in @functions.
- * @groups:     An array describing all pin groups the pin SoC supports.
- * @ngroups:    The numbmer of entries in @groups.
- * @ngpio:      The number of pingroups the driver should expose as GPIOs.
- */
-struct msm_pinctrl_soc_data {
-	const struct pinctrl_pin_desc *pins;
-	unsigned npins;
-	const struct msm_function *functions;
-	unsigned nfunctions;
-	const struct msm_pingroup *groups;
-	unsigned ngroups;
-	unsigned ngpios;
-};
-
-int msm_pinctrl_probe(struct platform_device *pdev,
-		      const struct msm_pinctrl_soc_data *soc_data);
-int msm_pinctrl_remove(struct platform_device *pdev);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2115 +0,0 @@
-/*
- * Generic GPIO driver for logic cells found in the Nomadik SoC
- *
- * Copyright (C) 2008,2009 STMicroelectronics
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-/* Since we request GPIOs from ourself */
-#include <linux/pinctrl/consumer.h>
-#include "pinctrl-nomadik.h"
-#include "core.h"
-
-/*
- * The GPIO module in the Nomadik family of Systems-on-Chip is an
- * AMBA device, managing 32 pins and alternate functions.  The logic block
- * is currently used in the Nomadik and ux500.
- *
- * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
- */
-
-/*
- * pin configurations are represented by 32-bit integers:
- *
- *	bit  0.. 8 - Pin Number (512 Pins Maximum)
- *	bit  9..10 - Alternate Function Selection
- *	bit 11..12 - Pull up/down state
- *	bit     13 - Sleep mode behaviour
- *	bit     14 - Direction
- *	bit     15 - Value (if output)
- *	bit 16..18 - SLPM pull up/down state
- *	bit 19..20 - SLPM direction
- *	bit 21..22 - SLPM Value (if output)
- *	bit 23..25 - PDIS value (if input)
- *	bit	26 - Gpio mode
- *	bit	27 - Sleep mode
- *
- * to facilitate the definition, the following macros are provided
- *
- * PIN_CFG_DEFAULT - default config (0):
- *		     pull up/down = disabled
- *		     sleep mode = input/wakeup
- *		     direction = input
- *		     value = low
- *		     SLPM direction = same as normal
- *		     SLPM pull = same as normal
- *		     SLPM value = same as normal
- *
- * PIN_CFG	   - default config with alternate function
- */
-
-typedef unsigned long pin_cfg_t;
-
-#define PIN_NUM_MASK		0x1ff
-#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
-
-#define PIN_ALT_SHIFT		9
-#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
-#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
-#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
-#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
-#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
-#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
-
-#define PIN_PULL_SHIFT		11
-#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
-#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
-#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
-#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
-#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
-
-#define PIN_SLPM_SHIFT		13
-#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
-#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
-#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
-/* These two replace the above in DB8500v2+ */
-#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
-
-#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
-#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
-
-#define PIN_DIR_SHIFT		14
-#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
-#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
-#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
-#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
-
-#define PIN_VAL_SHIFT		15
-#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
-#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
-#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
-#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
-
-#define PIN_SLPM_PULL_SHIFT	16
-#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL(x)	\
-	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_NONE	\
-	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_UP	\
-	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_DOWN	\
-	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
-
-#define PIN_SLPM_DIR_SHIFT	19
-#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR(x)		\
-	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
-
-#define PIN_SLPM_VAL_SHIFT	21
-#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL(x)		\
-	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
-
-#define PIN_SLPM_PDIS_SHIFT		23
-#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS(x)	\
-	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
-
-#define PIN_LOWEMI_SHIFT	25
-#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
-
-#define PIN_GPIOMODE_SHIFT	26
-#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
-
-#define PIN_SLEEPMODE_SHIFT	27
-#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
-
-
-/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
-#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
-#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
-#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
-#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
-#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
-
-#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
-#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
-#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
-#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
-#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
-
-#define PIN_CFG_DEFAULT		(0)
-
-#define PIN_CFG(num, alt)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt))
-
-#define PIN_CFG_INPUT(num, alt, pull)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
-
-#define PIN_CFG_OUTPUT(num, alt, val)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-#define GPIO_BLOCK_SHIFT 5
-#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT	0x00
-#define NMK_GPIO_DATS	0x04
-#define NMK_GPIO_DATC	0x08
-#define NMK_GPIO_PDIS	0x0c
-#define NMK_GPIO_DIR	0x10
-#define NMK_GPIO_DIRS	0x14
-#define NMK_GPIO_DIRC	0x18
-#define NMK_GPIO_SLPC	0x1c
-#define NMK_GPIO_AFSLA	0x20
-#define NMK_GPIO_AFSLB	0x24
-#define NMK_GPIO_LOWEMI	0x28
-
-#define NMK_GPIO_RIMSC	0x40
-#define NMK_GPIO_FIMSC	0x44
-#define NMK_GPIO_IS	0x48
-#define NMK_GPIO_IC	0x4c
-#define NMK_GPIO_RWIMSC	0x50
-#define NMK_GPIO_FWIMSC	0x54
-#define NMK_GPIO_WKS	0x58
-/* These appear in DB8540 and later ASICs */
-#define NMK_GPIO_EDGELEVEL 0x5C
-#define NMK_GPIO_LEVEL	0x60
-
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-	NMK_GPIO_PULL_NONE,
-	NMK_GPIO_PULL_UP,
-	NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-	NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_NOCHANGE,
-	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-struct nmk_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem *addr;
-	struct clk *clk;
-	unsigned int bank;
-	unsigned int parent_irq;
-	int latent_parent_irq;
-	u32 (*get_latent_status)(unsigned int bank);
-	void (*set_ioforce)(bool enable);
-	spinlock_t lock;
-	bool sleepmode;
-	/* Keep track of configured edges */
-	u32 edge_rising;
-	u32 edge_falling;
-	u32 real_wake;
-	u32 rwimsc;
-	u32 fwimsc;
-	u32 rimsc;
-	u32 fimsc;
-	u32 pull_up;
-	u32 lowemi;
-};
-
-/**
- * struct nmk_pinctrl - state container for the Nomadik pin controller
- * @dev: containing device pointer
- * @pctl: corresponding pin controller device
- * @soc: SoC data for this specific chip
- * @prcm_base: PRCM register range virtual base
- */
-struct nmk_pinctrl {
-	struct device *dev;
-	struct pinctrl_dev *pctl;
-	const struct nmk_pinctrl_soc_data *soc;
-	void __iomem *prcm_base;
-};
-
-static struct nmk_gpio_chip *
-nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
-
-static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
-
-#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
-
-static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
-				unsigned offset, int gpio_mode)
-{
-	u32 bit = 1 << offset;
-	u32 afunc, bfunc;
-
-	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
-	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
-	if (gpio_mode & NMK_GPIO_ALT_A)
-		afunc |= bit;
-	if (gpio_mode & NMK_GPIO_ALT_B)
-		bfunc |= bit;
-	writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
-	writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
-}
-
-static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
-				unsigned offset, enum nmk_gpio_slpm mode)
-{
-	u32 bit = 1 << offset;
-	u32 slpm;
-
-	slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
-	if (mode == NMK_GPIO_SLPM_NOCHANGE)
-		slpm |= bit;
-	else
-		slpm &= ~bit;
-	writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
-}
-
-static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
-				unsigned offset, enum nmk_gpio_pull pull)
-{
-	u32 bit = 1 << offset;
-	u32 pdis;
-
-	pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
-	if (pull == NMK_GPIO_PULL_NONE) {
-		pdis |= bit;
-		nmk_chip->pull_up &= ~bit;
-	} else {
-		pdis &= ~bit;
-	}
-
-	writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
-
-	if (pull == NMK_GPIO_PULL_UP) {
-		nmk_chip->pull_up |= bit;
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
-	} else if (pull == NMK_GPIO_PULL_DOWN) {
-		nmk_chip->pull_up &= ~bit;
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
-	}
-}
-
-static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
-				  unsigned offset, bool lowemi)
-{
-	u32 bit = BIT(offset);
-	bool enabled = nmk_chip->lowemi & bit;
-
-	if (lowemi == enabled)
-		return;
-
-	if (lowemi)
-		nmk_chip->lowemi |= bit;
-	else
-		nmk_chip->lowemi &= ~bit;
-
-	writel_relaxed(nmk_chip->lowemi,
-		       nmk_chip->addr + NMK_GPIO_LOWEMI);
-}
-
-static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
-				  unsigned offset)
-{
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
-}
-
-static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
-				  unsigned offset, int val)
-{
-	if (val)
-		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
-	else
-		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
-}
-
-static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
-				  unsigned offset, int val)
-{
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
-	__nmk_gpio_set_output(nmk_chip, offset, val);
-}
-
-static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
-				     unsigned offset, int gpio_mode,
-				     bool glitch)
-{
-	u32 rwimsc = nmk_chip->rwimsc;
-	u32 fwimsc = nmk_chip->fwimsc;
-
-	if (glitch && nmk_chip->set_ioforce) {
-		u32 bit = BIT(offset);
-
-		/* Prevent spurious wakeups */
-		writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
-		writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
-
-		nmk_chip->set_ioforce(true);
-	}
-
-	__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
-
-	if (glitch && nmk_chip->set_ioforce) {
-		nmk_chip->set_ioforce(false);
-
-		writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
-		writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
-	}
-}
-
-static void
-nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
-{
-	u32 falling = nmk_chip->fimsc & BIT(offset);
-	u32 rising = nmk_chip->rimsc & BIT(offset);
-	int gpio = nmk_chip->chip.base + offset;
-	int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset);
-	struct irq_data *d = irq_get_irq_data(irq);
-
-	if (!rising && !falling)
-		return;
-
-	if (!d || !irqd_irq_disabled(d))
-		return;
-
-	if (rising) {
-		nmk_chip->rimsc &= ~BIT(offset);
-		writel_relaxed(nmk_chip->rimsc,
-			       nmk_chip->addr + NMK_GPIO_RIMSC);
-	}
-
-	if (falling) {
-		nmk_chip->fimsc &= ~BIT(offset);
-		writel_relaxed(nmk_chip->fimsc,
-			       nmk_chip->addr + NMK_GPIO_FIMSC);
-	}
-
-	dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
-}
-
-static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
-{
-	u32 val;
-
-	val = readl(reg);
-	val = ((val & ~mask) | (value & mask));
-	writel(val, reg);
-}
-
-static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
-	unsigned offset, unsigned alt_num)
-{
-	int i;
-	u16 reg;
-	u8 bit;
-	u8 alt_index;
-	const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
-	const u16 *gpiocr_regs;
-
-	if (!npct->prcm_base)
-		return;
-
-	if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) {
-		dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n",
-			alt_num);
-		return;
-	}
-
-	for (i = 0 ; i < npct->soc->npins_altcx ; i++) {
-		if (npct->soc->altcx_pins[i].pin == offset)
-			break;
-	}
-	if (i == npct->soc->npins_altcx) {
-		dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n",
-			offset);
-		return;
-	}
-
-	pin_desc = npct->soc->altcx_pins + i;
-	gpiocr_regs = npct->soc->prcm_gpiocr_registers;
-
-	/*
-	 * If alt_num is NULL, just clear current ALTCx selection
-	 * to make sure we come back to a pure ALTC selection
-	 */
-	if (!alt_num) {
-		for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
-			if (pin_desc->altcx[i].used == true) {
-				reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
-				bit = pin_desc->altcx[i].control_bit;
-				if (readl(npct->prcm_base + reg) & BIT(bit)) {
-					nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
-					dev_dbg(npct->dev,
-						"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
-						offset, i+1);
-				}
-			}
-		}
-		return;
-	}
-
-	alt_index = alt_num - 1;
-	if (pin_desc->altcx[alt_index].used == false) {
-		dev_warn(npct->dev,
-			"PRCM GPIOCR: pin %i: alternate-C%i does not exist\n",
-			offset, alt_num);
-		return;
-	}
-
-	/*
-	 * Check if any other ALTCx functions are activated on this pin
-	 * and disable it first.
-	 */
-	for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) {
-		if (i == alt_index)
-			continue;
-		if (pin_desc->altcx[i].used == true) {
-			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
-			bit = pin_desc->altcx[i].control_bit;
-			if (readl(npct->prcm_base + reg) & BIT(bit)) {
-				nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
-				dev_dbg(npct->dev,
-					"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
-					offset, i+1);
-			}
-		}
-	}
-
-	reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index];
-	bit = pin_desc->altcx[alt_index].control_bit;
-	dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
-		offset, alt_index+1);
-	nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
-}
-
-/*
- * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
- *  - Save SLPM registers
- *  - Set SLPM=0 for the IOs you want to switch and others to 1
- *  - Configure the GPIO registers for the IOs that are being switched
- *  - Set IOFORCE=1
- *  - Modify the AFLSA/B registers for the IOs that are being switched
- *  - Set IOFORCE=0
- *  - Restore SLPM registers
- *  - Any spurious wake up event during switch sequence to be ignored and
- *    cleared
- */
-static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-		unsigned int temp = slpm[i];
-
-		if (!chip)
-			break;
-
-		clk_enable(chip->clk);
-
-		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
-		writel(temp, chip->addr + NMK_GPIO_SLPC);
-	}
-}
-
-static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-		if (!chip)
-			break;
-
-		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
-
-		clk_disable(chip->clk);
-	}
-}
-
-static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
-{
-	int i;
-	u16 reg;
-	u8 bit;
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
-	const u16 *gpiocr_regs;
-
-	if (!npct->prcm_base)
-		return NMK_GPIO_ALT_C;
-
-	for (i = 0; i < npct->soc->npins_altcx; i++) {
-		if (npct->soc->altcx_pins[i].pin == gpio)
-			break;
-	}
-	if (i == npct->soc->npins_altcx)
-		return NMK_GPIO_ALT_C;
-
-	pin_desc = npct->soc->altcx_pins + i;
-	gpiocr_regs = npct->soc->prcm_gpiocr_registers;
-	for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) {
-		if (pin_desc->altcx[i].used == true) {
-			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
-			bit = pin_desc->altcx[i].control_bit;
-			if (readl(npct->prcm_base + reg) & BIT(bit))
-				return NMK_GPIO_ALT_C+i+1;
-		}
-	}
-	return NMK_GPIO_ALT_C;
-}
-
-int nmk_gpio_get_mode(int gpio)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	u32 afunc, bfunc, bit;
-
-	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
-	if (!nmk_chip)
-		return -EINVAL;
-
-	bit = 1 << (gpio % NMK_GPIO_PER_CHIP);
-
-	clk_enable(nmk_chip->clk);
-
-	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
-	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
-
-	clk_disable(nmk_chip->clk);
-
-	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
-}
-EXPORT_SYMBOL(nmk_gpio_get_mode);
-
-
-/* IRQ functions */
-static inline int nmk_gpio_get_bitmask(int gpio)
-{
-	return 1 << (gpio % NMK_GPIO_PER_CHIP);
-}
-
-static void nmk_gpio_irq_ack(struct irq_data *d)
-{
-	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
-	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-
-	clk_enable(nmk_chip->clk);
-	writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
-	clk_disable(nmk_chip->clk);
-}
-
-enum nmk_gpio_irq_type {
-	NORMAL,
-	WAKE,
-};
-
-static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
-				  int gpio, enum nmk_gpio_irq_type which,
-				  bool enable)
-{
-	u32 bitmask = nmk_gpio_get_bitmask(gpio);
-	u32 *rimscval;
-	u32 *fimscval;
-	u32 rimscreg;
-	u32 fimscreg;
-
-	if (which == NORMAL) {
-		rimscreg = NMK_GPIO_RIMSC;
-		fimscreg = NMK_GPIO_FIMSC;
-		rimscval = &nmk_chip->rimsc;
-		fimscval = &nmk_chip->fimsc;
-	} else  {
-		rimscreg = NMK_GPIO_RWIMSC;
-		fimscreg = NMK_GPIO_FWIMSC;
-		rimscval = &nmk_chip->rwimsc;
-		fimscval = &nmk_chip->fwimsc;
-	}
-
-	/* we must individually set/clear the two edges */
-	if (nmk_chip->edge_rising & bitmask) {
-		if (enable)
-			*rimscval |= bitmask;
-		else
-			*rimscval &= ~bitmask;
-		writel(*rimscval, nmk_chip->addr + rimscreg);
-	}
-	if (nmk_chip->edge_falling & bitmask) {
-		if (enable)
-			*fimscval |= bitmask;
-		else
-			*fimscval &= ~bitmask;
-		writel(*fimscval, nmk_chip->addr + fimscreg);
-	}
-}
-
-static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
-				int gpio, bool on)
-{
-	/*
-	 * Ensure WAKEUP_ENABLE is on.  No need to disable it if wakeup is
-	 * disabled, since setting SLPM to 1 increases power consumption, and
-	 * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
-	 */
-	if (nmk_chip->sleepmode && on) {
-		__nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP,
-				    NMK_GPIO_SLPM_WAKEUP_ENABLE);
-	}
-
-	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
-}
-
-static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-	u32 bitmask;
-
-	nmk_chip = irq_data_get_irq_chip_data(d);
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
-	if (!nmk_chip)
-		return -EINVAL;
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-	spin_lock(&nmk_chip->lock);
-
-	__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
-
-	if (!(nmk_chip->real_wake & bitmask))
-		__nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
-
-	spin_unlock(&nmk_chip->lock);
-	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-static void nmk_gpio_irq_mask(struct irq_data *d)
-{
-	nmk_gpio_irq_maskunmask(d, false);
-}
-
-static void nmk_gpio_irq_unmask(struct irq_data *d)
-{
-	nmk_gpio_irq_maskunmask(d, true);
-}
-
-static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-	u32 bitmask;
-
-	nmk_chip = irq_data_get_irq_chip_data(d);
-	if (!nmk_chip)
-		return -EINVAL;
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-	spin_lock(&nmk_chip->lock);
-
-	if (irqd_irq_disabled(d))
-		__nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
-
-	if (on)
-		nmk_chip->real_wake |= bitmask;
-	else
-		nmk_chip->real_wake &= ~bitmask;
-
-	spin_unlock(&nmk_chip->lock);
-	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	bool enabled = !irqd_irq_disabled(d);
-	bool wake = irqd_is_wakeup_set(d);
-	struct nmk_gpio_chip *nmk_chip;
-	unsigned long flags;
-	u32 bitmask;
-
-	nmk_chip = irq_data_get_irq_chip_data(d);
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
-	if (!nmk_chip)
-		return -EINVAL;
-	if (type & IRQ_TYPE_LEVEL_HIGH)
-		return -EINVAL;
-	if (type & IRQ_TYPE_LEVEL_LOW)
-		return -EINVAL;
-
-	clk_enable(nmk_chip->clk);
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-
-	if (enabled)
-		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
-
-	if (enabled || wake)
-		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
-
-	nmk_chip->edge_rising &= ~bitmask;
-	if (type & IRQ_TYPE_EDGE_RISING)
-		nmk_chip->edge_rising |= bitmask;
-
-	nmk_chip->edge_falling &= ~bitmask;
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		nmk_chip->edge_falling |= bitmask;
-
-	if (enabled)
-		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
-
-	if (enabled || wake)
-		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
-
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
-{
-	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
-
-	clk_enable(nmk_chip->clk);
-	nmk_gpio_irq_unmask(d);
-	return 0;
-}
-
-static void nmk_gpio_irq_shutdown(struct irq_data *d)
-{
-	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
-
-	nmk_gpio_irq_mask(d);
-	clk_disable(nmk_chip->clk);
-}
-
-static struct irq_chip nmk_gpio_irq_chip = {
-	.name		= "Nomadik-GPIO",
-	.irq_ack	= nmk_gpio_irq_ack,
-	.irq_mask	= nmk_gpio_irq_mask,
-	.irq_unmask	= nmk_gpio_irq_unmask,
-	.irq_set_type	= nmk_gpio_irq_set_type,
-	.irq_set_wake	= nmk_gpio_irq_set_wake,
-	.irq_startup	= nmk_gpio_irq_startup,
-	.irq_shutdown	= nmk_gpio_irq_shutdown,
-	.flags		= IRQCHIP_MASK_ON_SUSPEND,
-};
-
-static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
-				   u32 status)
-{
-	struct irq_chip *host_chip = irq_get_chip(irq);
-	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
-
-	chained_irq_enter(host_chip, desc);
-
-	while (status) {
-		int bit = __ffs(status);
-
-		generic_handle_irq(irq_find_mapping(chip->irqdomain, bit));
-		status &= ~BIT(bit);
-	}
-
-	chained_irq_exit(host_chip, desc);
-}
-
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
-	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-	u32 status;
-
-	clk_enable(nmk_chip->clk);
-	status = readl(nmk_chip->addr + NMK_GPIO_IS);
-	clk_disable(nmk_chip->clk);
-
-	__nmk_gpio_irq_handler(irq, desc, status);
-}
-
-static void nmk_gpio_latent_irq_handler(unsigned int irq,
-					   struct irq_desc *desc)
-{
-	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
-	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-	u32 status = nmk_chip->get_latent_status(nmk_chip->bank);
-
-	__nmk_gpio_irq_handler(irq, desc, status);
-}
-
-/* I/O Functions */
-
-static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	/*
-	 * Map back to global GPIO space and request muxing, the direction
-	 * parameter does not matter for this controller.
-	 */
-	int gpio = chip->base + offset;
-
-	return pinctrl_request_gpio(gpio);
-}
-
-static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	int gpio = chip->base + offset;
-
-	pinctrl_free_gpio(gpio);
-}
-
-static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct nmk_gpio_chip *nmk_chip =
-		container_of(chip, struct nmk_gpio_chip, chip);
-
-	clk_enable(nmk_chip->clk);
-
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
-
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct nmk_gpio_chip *nmk_chip =
-		container_of(chip, struct nmk_gpio_chip, chip);
-	u32 bit = 1 << offset;
-	int value;
-
-	clk_enable(nmk_chip->clk);
-
-	value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
-
-	clk_disable(nmk_chip->clk);
-
-	return value;
-}
-
-static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
-				int val)
-{
-	struct nmk_gpio_chip *nmk_chip =
-		container_of(chip, struct nmk_gpio_chip, chip);
-
-	clk_enable(nmk_chip->clk);
-
-	__nmk_gpio_set_output(nmk_chip, offset, val);
-
-	clk_disable(nmk_chip->clk);
-}
-
-static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
-				int val)
-{
-	struct nmk_gpio_chip *nmk_chip =
-		container_of(chip, struct nmk_gpio_chip, chip);
-
-	clk_enable(nmk_chip->clk);
-
-	__nmk_gpio_make_output(nmk_chip, offset, val);
-
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/seq_file.h>
-
-static void nmk_gpio_dbg_show_one(struct seq_file *s,
-	struct pinctrl_dev *pctldev, struct gpio_chip *chip,
-	unsigned offset, unsigned gpio)
-{
-	const char *label = gpiochip_is_requested(chip, offset);
-	struct nmk_gpio_chip *nmk_chip =
-		container_of(chip, struct nmk_gpio_chip, chip);
-	int mode;
-	bool is_out;
-	bool pull;
-	u32 bit = 1 << offset;
-	const char *modes[] = {
-		[NMK_GPIO_ALT_GPIO]	= "gpio",
-		[NMK_GPIO_ALT_A]	= "altA",
-		[NMK_GPIO_ALT_B]	= "altB",
-		[NMK_GPIO_ALT_C]	= "altC",
-		[NMK_GPIO_ALT_C+1]	= "altC1",
-		[NMK_GPIO_ALT_C+2]	= "altC2",
-		[NMK_GPIO_ALT_C+3]	= "altC3",
-		[NMK_GPIO_ALT_C+4]	= "altC4",
-	};
-
-	clk_enable(nmk_chip->clk);
-	is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
-	pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
-	mode = nmk_gpio_get_mode(gpio);
-	if ((mode == NMK_GPIO_ALT_C) && pctldev)
-		mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
-
-	seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
-		   gpio, label ?: "(none)",
-		   is_out ? "out" : "in ",
-		   chip->get
-		   ? (chip->get(chip, offset) ? "hi" : "lo")
-		   : "?  ",
-		   (mode < 0) ? "unknown" : modes[mode],
-		   pull ? "pull" : "none");
-
-	if (!is_out) {
-		int irq = gpio_to_irq(gpio);
-		struct irq_desc	*desc = irq_to_desc(irq);
-
-		/* This races with request_irq(), set_irq_type(),
-		 * and set_irq_wake() ... but those are "rare".
-		 */
-		if (irq > 0 && desc && desc->action) {
-			char *trigger;
-			u32 bitmask = nmk_gpio_get_bitmask(gpio);
-
-			if (nmk_chip->edge_rising & bitmask)
-				trigger = "edge-rising";
-			else if (nmk_chip->edge_falling & bitmask)
-				trigger = "edge-falling";
-			else
-				trigger = "edge-undefined";
-
-			seq_printf(s, " irq-%d %s%s",
-				   irq, trigger,
-				   irqd_is_wakeup_set(&desc->irq_data)
-				   ? " wakeup" : "");
-		}
-	}
-	clk_disable(nmk_chip->clk);
-}
-
-static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	unsigned		i;
-	unsigned		gpio = chip->base;
-
-	for (i = 0; i < chip->ngpio; i++, gpio++) {
-		nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
-		seq_printf(s, "\n");
-	}
-}
-
-#else
-static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
-					 struct pinctrl_dev *pctldev,
-					 struct gpio_chip *chip,
-					 unsigned offset, unsigned gpio)
-{
-}
-#define nmk_gpio_dbg_show	NULL
-#endif
-
-/* This structure is replicated for each GPIO block allocated at probe time */
-static struct gpio_chip nmk_gpio_template = {
-	.request		= nmk_gpio_request,
-	.free			= nmk_gpio_free,
-	.direction_input	= nmk_gpio_make_input,
-	.get			= nmk_gpio_get_input,
-	.direction_output	= nmk_gpio_make_output,
-	.set			= nmk_gpio_set_output,
-	.dbg_show		= nmk_gpio_dbg_show,
-	.can_sleep		= false,
-};
-
-void nmk_gpio_clocks_enable(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-		if (!chip)
-			continue;
-
-		clk_enable(chip->clk);
-	}
-}
-
-void nmk_gpio_clocks_disable(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-		if (!chip)
-			continue;
-
-		clk_disable(chip->clk);
-	}
-}
-
-/*
- * Called from the suspend/resume path to only keep the real wakeup interrupts
- * (those that have had set_irq_wake() called on them) as wakeup interrupts,
- * and not the rest of the interrupts which we needed to have as wakeups for
- * cpuidle.
- *
- * PM ops are not used since this needs to be done at the end, after all the
- * other drivers are done with their suspend callbacks.
- */
-void nmk_gpio_wakeups_suspend(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-		if (!chip)
-			break;
-
-		clk_enable(chip->clk);
-
-		writel(chip->rwimsc & chip->real_wake,
-		       chip->addr + NMK_GPIO_RWIMSC);
-		writel(chip->fwimsc & chip->real_wake,
-		       chip->addr + NMK_GPIO_FWIMSC);
-
-		clk_disable(chip->clk);
-	}
-}
-
-void nmk_gpio_wakeups_resume(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_BANKS; i++) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-		if (!chip)
-			break;
-
-		clk_enable(chip->clk);
-
-		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
-		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
-
-		clk_disable(chip->clk);
-	}
-}
-
-/*
- * Read the pull up/pull down status.
- * A bit set in 'pull_up' means that pull up
- * is selected if pull is enabled in PDIS register.
- * Note: only pull up/down set via this driver can
- * be detected due to HW limitations.
- */
-void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
-{
-	if (gpio_bank < NUM_BANKS) {
-		struct nmk_gpio_chip *chip = nmk_gpio_chips[gpio_bank];
-
-		if (!chip)
-			return;
-
-		*pull_up = chip->pull_up;
-	}
-}
-
-static int nmk_gpio_probe(struct platform_device *dev)
-{
-	struct device_node *np = dev->dev.of_node;
-	struct nmk_gpio_chip *nmk_chip;
-	struct gpio_chip *chip;
-	struct resource *res;
-	struct clk *clk;
-	int latent_irq;
-	bool supports_sleepmode;
-	void __iomem *base;
-	int irq;
-	int ret;
-
-	if (of_get_property(np, "st,supports-sleepmode", NULL))
-		supports_sleepmode = true;
-	else
-		supports_sleepmode = false;
-
-	if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
-		dev_err(&dev->dev, "gpio-bank property not found\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0)
-		return irq;
-
-	/* It's OK for this IRQ not to be present */
-	latent_irq = platform_get_irq(dev, 1);
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&dev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	clk = devm_clk_get(&dev->dev, NULL);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-	clk_prepare(clk);
-
-	nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL);
-	if (!nmk_chip)
-		return -ENOMEM;
-
-	/*
-	 * The virt address in nmk_chip->addr is in the nomadik register space,
-	 * so we can simply convert the resource address, without remapping
-	 */
-	nmk_chip->bank = dev->id;
-	nmk_chip->clk = clk;
-	nmk_chip->addr = base;
-	nmk_chip->chip = nmk_gpio_template;
-	nmk_chip->parent_irq = irq;
-	nmk_chip->latent_parent_irq = latent_irq;
-	nmk_chip->sleepmode = supports_sleepmode;
-	spin_lock_init(&nmk_chip->lock);
-
-	chip = &nmk_chip->chip;
-	chip->base = dev->id * NMK_GPIO_PER_CHIP;
-	chip->ngpio = NMK_GPIO_PER_CHIP;
-	chip->label = dev_name(&dev->dev);
-	chip->dev = &dev->dev;
-	chip->owner = THIS_MODULE;
-
-	clk_enable(nmk_chip->clk);
-	nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
-	clk_disable(nmk_chip->clk);
-	chip->of_node = np;
-
-	ret = gpiochip_add(&nmk_chip->chip);
-	if (ret)
-		return ret;
-
-	BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
-
-	nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
-
-	platform_set_drvdata(dev, nmk_chip);
-
-	/*
-	 * Let the generic code handle this edge IRQ, the the chained
-	 * handler will perform the actual work of handling the parent
-	 * interrupt.
-	 */
-	ret = gpiochip_irqchip_add(&nmk_chip->chip,
-				   &nmk_gpio_irq_chip,
-				   0,
-				   handle_edge_irq,
-				   IRQ_TYPE_EDGE_FALLING);
-	if (ret) {
-		dev_err(&dev->dev, "could not add irqchip\n");
-		ret = gpiochip_remove(&nmk_chip->chip);
-		return -ENODEV;
-	}
-	/* Then register the chain on the parent IRQ */
-	gpiochip_set_chained_irqchip(&nmk_chip->chip,
-				     &nmk_gpio_irq_chip,
-				     nmk_chip->parent_irq,
-				     nmk_gpio_irq_handler);
-	if (nmk_chip->latent_parent_irq > 0)
-		gpiochip_set_chained_irqchip(&nmk_chip->chip,
-					     &nmk_gpio_irq_chip,
-					     nmk_chip->latent_parent_irq,
-					     nmk_gpio_latent_irq_handler);
-
-	dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);
-
-	return 0;
-}
-
-static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	return npct->soc->ngroups;
-}
-
-static const char *nmk_get_group_name(struct pinctrl_dev *pctldev,
-				       unsigned selector)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	return npct->soc->groups[selector].name;
-}
-
-static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
-			      const unsigned **pins,
-			      unsigned *num_pins)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	*pins = npct->soc->groups[selector].pins;
-	*num_pins = npct->soc->groups[selector].npins;
-	return 0;
-}
-
-static struct pinctrl_gpio_range *
-nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	int i;
-
-	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
-		struct pinctrl_gpio_range *range;
-
-		range = &npct->soc->gpio_ranges[i];
-		if (offset >= range->pin_base &&
-		    offset <= (range->pin_base + range->npins - 1))
-			return range;
-	}
-	return NULL;
-}
-
-static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
-		   unsigned offset)
-{
-	struct pinctrl_gpio_range *range;
-	struct gpio_chip *chip;
-
-	range = nmk_match_gpio_range(pctldev, offset);
-	if (!range || !range->gc) {
-		seq_printf(s, "invalid pin offset");
-		return;
-	}
-	chip = range->gc;
-	nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
-}
-
-static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-		struct pinctrl_map *map, unsigned num_maps)
-{
-	int i;
-
-	for (i = 0; i < num_maps; i++)
-		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
-			kfree(map[i].data.configs.configs);
-	kfree(map);
-}
-
-static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
-		unsigned *num_maps, unsigned reserve)
-{
-	unsigned old_num = *reserved_maps;
-	unsigned new_num = *num_maps + reserve;
-	struct pinctrl_map *new_map;
-
-	if (old_num >= new_num)
-		return 0;
-
-	new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
-	if (!new_map)
-		return -ENOMEM;
-
-	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
-
-	*map = new_map;
-	*reserved_maps = new_num;
-
-	return 0;
-}
-
-static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
-		unsigned *num_maps, const char *group,
-		const char *function)
-{
-	if (*num_maps == *reserved_maps)
-		return -ENOSPC;
-
-	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
-	(*map)[*num_maps].data.mux.group = group;
-	(*map)[*num_maps].data.mux.function = function;
-	(*num_maps)++;
-
-	return 0;
-}
-
-static int nmk_dt_add_map_configs(struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps, const char *group,
-		unsigned long *configs, unsigned num_configs)
-{
-	unsigned long *dup_configs;
-
-	if (*num_maps == *reserved_maps)
-		return -ENOSPC;
-
-	dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
-			      GFP_KERNEL);
-	if (!dup_configs)
-		return -ENOMEM;
-
-	(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
-
-	(*map)[*num_maps].data.configs.group_or_pin = group;
-	(*map)[*num_maps].data.configs.configs = dup_configs;
-	(*map)[*num_maps].data.configs.num_configs = num_configs;
-	(*num_maps)++;
-
-	return 0;
-}
-
-#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, }
-#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \
-	.size = ARRAY_SIZE(y), }
-
-static const unsigned long nmk_pin_input_modes[] = {
-	PIN_INPUT_NOPULL,
-	PIN_INPUT_PULLUP,
-	PIN_INPUT_PULLDOWN,
-};
-
-static const unsigned long nmk_pin_output_modes[] = {
-	PIN_OUTPUT_LOW,
-	PIN_OUTPUT_HIGH,
-	PIN_DIR_OUTPUT,
-};
-
-static const unsigned long nmk_pin_sleep_modes[] = {
-	PIN_SLEEPMODE_DISABLED,
-	PIN_SLEEPMODE_ENABLED,
-};
-
-static const unsigned long nmk_pin_sleep_input_modes[] = {
-	PIN_SLPM_INPUT_NOPULL,
-	PIN_SLPM_INPUT_PULLUP,
-	PIN_SLPM_INPUT_PULLDOWN,
-	PIN_SLPM_DIR_INPUT,
-};
-
-static const unsigned long nmk_pin_sleep_output_modes[] = {
-	PIN_SLPM_OUTPUT_LOW,
-	PIN_SLPM_OUTPUT_HIGH,
-	PIN_SLPM_DIR_OUTPUT,
-};
-
-static const unsigned long nmk_pin_sleep_wakeup_modes[] = {
-	PIN_SLPM_WAKEUP_DISABLE,
-	PIN_SLPM_WAKEUP_ENABLE,
-};
-
-static const unsigned long nmk_pin_gpio_modes[] = {
-	PIN_GPIOMODE_DISABLED,
-	PIN_GPIOMODE_ENABLED,
-};
-
-static const unsigned long nmk_pin_sleep_pdis_modes[] = {
-	PIN_SLPM_PDIS_DISABLED,
-	PIN_SLPM_PDIS_ENABLED,
-};
-
-struct nmk_cfg_param {
-	const char *property;
-	unsigned long config;
-	const unsigned long *choice;
-	int size;
-};
-
-static const struct nmk_cfg_param nmk_cfg_params[] = {
-	NMK_CONFIG_PIN_ARRAY("ste,input",		nmk_pin_input_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,output",		nmk_pin_output_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,sleep",		nmk_pin_sleep_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,sleep-input",		nmk_pin_sleep_input_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,sleep-output",	nmk_pin_sleep_output_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup",	nmk_pin_sleep_wakeup_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,gpio",		nmk_pin_gpio_modes),
-	NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable",	nmk_pin_sleep_pdis_modes),
-};
-
-static int nmk_dt_pin_config(int index, int val, unsigned long *config)
-{
-	int ret = 0;
-
-	if (nmk_cfg_params[index].choice == NULL)
-		*config = nmk_cfg_params[index].config;
-	else {
-		/* test if out of range */
-		if  (val < nmk_cfg_params[index].size) {
-			*config = nmk_cfg_params[index].config |
-				nmk_cfg_params[index].choice[val];
-		}
-	}
-	return ret;
-}
-
-static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name)
-{
-	int i, pin_number;
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
-		for (i = 0; i < npct->soc->npins; i++)
-			if (npct->soc->pins[i].number == pin_number)
-				return npct->soc->pins[i].name;
-	return NULL;
-}
-
-static bool nmk_pinctrl_dt_get_config(struct device_node *np,
-		unsigned long *configs)
-{
-	bool has_config = 0;
-	unsigned long cfg = 0;
-	int i, val, ret;
-
-	for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) {
-		ret = of_property_read_u32(np,
-				nmk_cfg_params[i].property, &val);
-		if (ret != -EINVAL) {
-			if (nmk_dt_pin_config(i, val, &cfg) == 0) {
-				*configs |= cfg;
-				has_config = 1;
-			}
-		}
-	}
-
-	return has_config;
-}
-
-static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
-		struct device_node *np,
-		struct pinctrl_map **map,
-		unsigned *reserved_maps,
-		unsigned *num_maps)
-{
-	int ret;
-	const char *function = NULL;
-	unsigned long configs = 0;
-	bool has_config = 0;
-	unsigned reserve = 0;
-	struct property *prop;
-	const char *group, *gpio_name;
-	struct device_node *np_config;
-
-	ret = of_property_read_string(np, "ste,function", &function);
-	if (ret >= 0)
-		reserve = 1;
-
-	has_config = nmk_pinctrl_dt_get_config(np, &configs);
-
-	np_config = of_parse_phandle(np, "ste,config", 0);
-	if (np_config)
-		has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
-
-	ret = of_property_count_strings(np, "ste,pins");
-	if (ret < 0)
-		goto exit;
-
-	if (has_config)
-		reserve++;
-
-	reserve *= ret;
-
-	ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve);
-	if (ret < 0)
-		goto exit;
-
-	of_property_for_each_string(np, "ste,pins", prop, group) {
-		if (function) {
-			ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps,
-					  group, function);
-			if (ret < 0)
-				goto exit;
-		}
-		if (has_config) {
-			gpio_name = nmk_find_pin_name(pctldev, group);
-
-			ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps,
-					      gpio_name, &configs, 1);
-			if (ret < 0)
-				goto exit;
-		}
-
-	}
-exit:
-	return ret;
-}
-
-static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-				 struct device_node *np_config,
-				 struct pinctrl_map **map, unsigned *num_maps)
-{
-	unsigned reserved_maps;
-	struct device_node *np;
-	int ret;
-
-	reserved_maps = 0;
-	*map = NULL;
-	*num_maps = 0;
-
-	for_each_child_of_node(np_config, np) {
-		ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
-				&reserved_maps, num_maps);
-		if (ret < 0) {
-			nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static const struct pinctrl_ops nmk_pinctrl_ops = {
-	.get_groups_count = nmk_get_groups_cnt,
-	.get_group_name = nmk_get_group_name,
-	.get_group_pins = nmk_get_group_pins,
-	.pin_dbg_show = nmk_pin_dbg_show,
-	.dt_node_to_map = nmk_pinctrl_dt_node_to_map,
-	.dt_free_map = nmk_pinctrl_dt_free_map,
-};
-
-static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	return npct->soc->nfunctions;
-}
-
-static const char *nmk_pmx_get_func_name(struct pinctrl_dev *pctldev,
-					 unsigned function)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	return npct->soc->functions[function].name;
-}
-
-static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
-				   unsigned function,
-				   const char * const **groups,
-				   unsigned * const num_groups)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	*groups = npct->soc->functions[function].groups;
-	*num_groups = npct->soc->functions[function].ngroups;
-
-	return 0;
-}
-
-static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
-			  unsigned group)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	const struct nmk_pingroup *g;
-	static unsigned int slpm[NUM_BANKS];
-	unsigned long flags = 0;
-	bool glitch;
-	int ret = -EINVAL;
-	int i;
-
-	g = &npct->soc->groups[group];
-
-	if (g->altsetting < 0)
-		return -EINVAL;
-
-	dev_dbg(npct->dev, "enable group %s, %u pins\n", g->name, g->npins);
-
-	/*
-	 * If we're setting altfunc C by setting both AFSLA and AFSLB to 1,
-	 * we may pass through an undesired state. In this case we take
-	 * some extra care.
-	 *
-	 * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
-	 *  - Save SLPM registers (since we have a shadow register in the
-	 *    nmk_chip we're using that as backup)
-	 *  - Set SLPM=0 for the IOs you want to switch and others to 1
-	 *  - Configure the GPIO registers for the IOs that are being switched
-	 *  - Set IOFORCE=1
-	 *  - Modify the AFLSA/B registers for the IOs that are being switched
-	 *  - Set IOFORCE=0
-	 *  - Restore SLPM registers
-	 *  - Any spurious wake up event during switch sequence to be ignored
-	 *    and cleared
-	 *
-	 * We REALLY need to save ALL slpm registers, because the external
-	 * IOFORCE will switch *all* ports to their sleepmode setting to as
-	 * to avoid glitches. (Not just one port!)
-	 */
-	glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C);
-
-	if (glitch) {
-		spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-
-		/* Initially don't put any pins to sleep when switching */
-		memset(slpm, 0xff, sizeof(slpm));
-
-		/*
-		 * Then mask the pins that need to be sleeping now when we're
-		 * switching to the ALT C function.
-		 */
-		for (i = 0; i < g->npins; i++)
-			slpm[g->pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->pins[i]);
-		nmk_gpio_glitch_slpm_init(slpm);
-	}
-
-	for (i = 0; i < g->npins; i++) {
-		struct pinctrl_gpio_range *range;
-		struct nmk_gpio_chip *nmk_chip;
-		struct gpio_chip *chip;
-		unsigned bit;
-
-		range = nmk_match_gpio_range(pctldev, g->pins[i]);
-		if (!range) {
-			dev_err(npct->dev,
-				"invalid pin offset %d in group %s at index %d\n",
-				g->pins[i], g->name, i);
-			goto out_glitch;
-		}
-		if (!range->gc) {
-			dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n",
-				g->pins[i], g->name, i);
-			goto out_glitch;
-		}
-		chip = range->gc;
-		nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-		dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting);
-
-		clk_enable(nmk_chip->clk);
-		bit = g->pins[i] % NMK_GPIO_PER_CHIP;
-		/*
-		 * If the pin is switching to altfunc, and there was an
-		 * interrupt installed on it which has been lazy disabled,
-		 * actually mask the interrupt to prevent spurious interrupts
-		 * that would occur while the pin is under control of the
-		 * peripheral. Only SKE does this.
-		 */
-		nmk_gpio_disable_lazy_irq(nmk_chip, bit);
-
-		__nmk_gpio_set_mode_safe(nmk_chip, bit,
-			(g->altsetting & NMK_GPIO_ALT_C), glitch);
-		clk_disable(nmk_chip->clk);
-
-		/*
-		 * Call PRCM GPIOCR config function in case ALTC
-		 * has been selected:
-		 * - If selection is a ALTCx, some bits in PRCM GPIOCR registers
-		 *   must be set.
-		 * - If selection is pure ALTC and previous selection was ALTCx,
-		 *   then some bits in PRCM GPIOCR registers must be cleared.
-		 */
-		if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C)
-			nmk_prcm_altcx_set_mode(npct, g->pins[i],
-				g->altsetting >> NMK_GPIO_ALT_CX_SHIFT);
-	}
-
-	/* When all pins are successfully reconfigured we get here */
-	ret = 0;
-
-out_glitch:
-	if (glitch) {
-		nmk_gpio_glitch_slpm_restore(slpm);
-		spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-	}
-
-	return ret;
-}
-
-static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
-			    unsigned function, unsigned group)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	const struct nmk_pingroup *g;
-
-	g = &npct->soc->groups[group];
-
-	if (g->altsetting < 0)
-		return;
-
-	/* Poke out the mux, set the pin to some default state? */
-	dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins);
-}
-
-static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
-				   struct pinctrl_gpio_range *range,
-				   unsigned offset)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	struct nmk_gpio_chip *nmk_chip;
-	struct gpio_chip *chip;
-	unsigned bit;
-
-	if (!range) {
-		dev_err(npct->dev, "invalid range\n");
-		return -EINVAL;
-	}
-	if (!range->gc) {
-		dev_err(npct->dev, "missing GPIO chip in range\n");
-		return -EINVAL;
-	}
-	chip = range->gc;
-	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-
-	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
-
-	clk_enable(nmk_chip->clk);
-	bit = offset % NMK_GPIO_PER_CHIP;
-	/* There is no glitch when converting any pin to GPIO */
-	__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
-	clk_disable(nmk_chip->clk);
-
-	return 0;
-}
-
-static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
-				  struct pinctrl_gpio_range *range,
-				  unsigned offset)
-{
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-
-	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
-	/* Set the pin to some default state, GPIO is usually default */
-}
-
-static const struct pinmux_ops nmk_pinmux_ops = {
-	.get_functions_count = nmk_pmx_get_funcs_cnt,
-	.get_function_name = nmk_pmx_get_func_name,
-	.get_function_groups = nmk_pmx_get_func_groups,
-	.enable = nmk_pmx_enable,
-	.disable = nmk_pmx_disable,
-	.gpio_request_enable = nmk_gpio_request_enable,
-	.gpio_disable_free = nmk_gpio_disable_free,
-};
-
-static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
-			      unsigned long *config)
-{
-	/* Not implemented */
-	return -EINVAL;
-}
-
-static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
-			      unsigned long *configs, unsigned num_configs)
-{
-	static const char *pullnames[] = {
-		[NMK_GPIO_PULL_NONE]	= "none",
-		[NMK_GPIO_PULL_UP]	= "up",
-		[NMK_GPIO_PULL_DOWN]	= "down",
-		[3] /* illegal */	= "??"
-	};
-	static const char *slpmnames[] = {
-		[NMK_GPIO_SLPM_INPUT]		= "input/wakeup",
-		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change/no-wakeup",
-	};
-	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-	struct nmk_gpio_chip *nmk_chip;
-	struct pinctrl_gpio_range *range;
-	struct gpio_chip *chip;
-	unsigned bit;
-	pin_cfg_t cfg;
-	int pull, slpm, output, val, i;
-	bool lowemi, gpiomode, sleep;
-
-	range = nmk_match_gpio_range(pctldev, pin);
-	if (!range) {
-		dev_err(npct->dev, "invalid pin offset %d\n", pin);
-		return -EINVAL;
-	}
-	if (!range->gc) {
-		dev_err(npct->dev, "GPIO chip missing in range for pin %d\n",
-			pin);
-		return -EINVAL;
-	}
-	chip = range->gc;
-	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
-
-	for (i = 0; i < num_configs; i++) {
-		/*
-		 * The pin config contains pin number and altfunction fields,
-		 * here we just ignore that part. It's being handled by the
-		 * framework and pinmux callback respectively.
-		 */
-		cfg = (pin_cfg_t) configs[i];
-		pull = PIN_PULL(cfg);
-		slpm = PIN_SLPM(cfg);
-		output = PIN_DIR(cfg);
-		val = PIN_VAL(cfg);
-		lowemi = PIN_LOWEMI(cfg);
-		gpiomode = PIN_GPIOMODE(cfg);
-		sleep = PIN_SLEEPMODE(cfg);
-
-		if (sleep) {
-			int slpm_pull = PIN_SLPM_PULL(cfg);
-			int slpm_output = PIN_SLPM_DIR(cfg);
-			int slpm_val = PIN_SLPM_VAL(cfg);
-
-			/* All pins go into GPIO mode at sleep */
-			gpiomode = true;
-
-			/*
-			 * The SLPM_* values are normal values + 1 to allow zero
-			 * to mean "same as normal".
-			 */
-			if (slpm_pull)
-				pull = slpm_pull - 1;
-			if (slpm_output)
-				output = slpm_output - 1;
-			if (slpm_val)
-				val = slpm_val - 1;
-
-			dev_dbg(nmk_chip->chip.dev,
-				"pin %d: sleep pull %s, dir %s, val %s\n",
-				pin,
-				slpm_pull ? pullnames[pull] : "same",
-				slpm_output ? (output ? "output" : "input")
-				: "same",
-				slpm_val ? (val ? "high" : "low") : "same");
-		}
-
-		dev_dbg(nmk_chip->chip.dev,
-			"pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
-			pin, cfg, pullnames[pull], slpmnames[slpm],
-			output ? "output " : "input",
-			output ? (val ? "high" : "low") : "",
-			lowemi ? "on" : "off");
-
-		clk_enable(nmk_chip->clk);
-		bit = pin % NMK_GPIO_PER_CHIP;
-		if (gpiomode)
-			/* No glitch when going to GPIO mode */
-			__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
-		if (output)
-			__nmk_gpio_make_output(nmk_chip, bit, val);
-		else {
-			__nmk_gpio_make_input(nmk_chip, bit);
-			__nmk_gpio_set_pull(nmk_chip, bit, pull);
-		}
-		/* TODO: isn't this only applicable on output pins? */
-		__nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);
-
-		__nmk_gpio_set_slpm(nmk_chip, bit, slpm);
-		clk_disable(nmk_chip->clk);
-	} /* for each config */
-
-	return 0;
-}
-
-static const struct pinconf_ops nmk_pinconf_ops = {
-	.pin_config_get = nmk_pin_config_get,
-	.pin_config_set = nmk_pin_config_set,
-};
-
-static struct pinctrl_desc nmk_pinctrl_desc = {
-	.name = "pinctrl-nomadik",
-	.pctlops = &nmk_pinctrl_ops,
-	.pmxops = &nmk_pinmux_ops,
-	.confops = &nmk_pinconf_ops,
-	.owner = THIS_MODULE,
-};
-
-static const struct of_device_id nmk_pinctrl_match[] = {
-	{
-		.compatible = "stericsson,stn8815-pinctrl",
-		.data = (void *)PINCTRL_NMK_STN8815,
-	},
-	{
-		.compatible = "stericsson,db8500-pinctrl",
-		.data = (void *)PINCTRL_NMK_DB8500,
-	},
-	{
-		.compatible = "stericsson,db8540-pinctrl",
-		.data = (void *)PINCTRL_NMK_DB8540,
-	},
-	{},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int nmk_pinctrl_suspend(struct device *dev)
-{
-	struct nmk_pinctrl *npct;
-
-	npct = dev_get_drvdata(dev);
-	if (!npct)
-		return -EINVAL;
-
-	return pinctrl_force_sleep(npct->pctl);
-}
-
-static int nmk_pinctrl_resume(struct device *dev)
-{
-	struct nmk_pinctrl *npct;
-
-	npct = dev_get_drvdata(dev);
-	if (!npct)
-		return -EINVAL;
-
-	return pinctrl_force_default(npct->pctl);
-}
-#endif
-
-static int nmk_pinctrl_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *match;
-	struct device_node *np = pdev->dev.of_node;
-	struct device_node *prcm_np;
-	struct nmk_pinctrl *npct;
-	unsigned int version = 0;
-	int i;
-
-	npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL);
-	if (!npct)
-		return -ENOMEM;
-
-	match = of_match_device(nmk_pinctrl_match, &pdev->dev);
-	if (!match)
-		return -ENODEV;
-	version = (unsigned int) match->data;
-
-	/* Poke in other ASIC variants here */
-	if (version == PINCTRL_NMK_STN8815)
-		nmk_pinctrl_stn8815_init(&npct->soc);
-	if (version == PINCTRL_NMK_DB8500)
-		nmk_pinctrl_db8500_init(&npct->soc);
-	if (version == PINCTRL_NMK_DB8540)
-		nmk_pinctrl_db8540_init(&npct->soc);
-
-	prcm_np = of_parse_phandle(np, "prcm", 0);
-	if (prcm_np)
-		npct->prcm_base = of_iomap(prcm_np, 0);
-	if (!npct->prcm_base) {
-		if (version == PINCTRL_NMK_STN8815) {
-			dev_info(&pdev->dev,
-				 "No PRCM base, "
-				 "assuming no ALT-Cx control is available\n");
-		} else {
-			dev_err(&pdev->dev, "missing PRCM base address\n");
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * We need all the GPIO drivers to probe FIRST, or we will not be able
-	 * to obtain references to the struct gpio_chip * for them, and we
-	 * need this to proceed.
-	 */
-	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
-		if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
-			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
-			return -EPROBE_DEFER;
-		}
-		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
-	}
-
-	nmk_pinctrl_desc.pins = npct->soc->pins;
-	nmk_pinctrl_desc.npins = npct->soc->npins;
-	npct->dev = &pdev->dev;
-
-	npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
-	if (!npct->pctl) {
-		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
-		return -EINVAL;
-	}
-
-	/* We will handle a range of GPIO pins */
-	for (i = 0; i < npct->soc->gpio_num_ranges; i++)
-		pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]);
-
-	platform_set_drvdata(pdev, npct);
-	dev_info(&pdev->dev, "initialized Nomadik pin control driver\n");
-
-	return 0;
-}
-
-static const struct of_device_id nmk_gpio_match[] = {
-	{ .compatible = "st,nomadik-gpio", },
-	{}
-};
-
-static struct platform_driver nmk_gpio_driver = {
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = "gpio",
-		.of_match_table = nmk_gpio_match,
-	},
-	.probe = nmk_gpio_probe,
-};
-
-static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops,
-			nmk_pinctrl_suspend,
-			nmk_pinctrl_resume);
-
-static struct platform_driver nmk_pinctrl_driver = {
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = "pinctrl-nomadik",
-		.of_match_table = nmk_pinctrl_match,
-		.pm = &nmk_pinctrl_pm_ops,
-	},
-	.probe = nmk_pinctrl_probe,
-};
-
-static int __init nmk_gpio_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&nmk_gpio_driver);
-	if (ret)
-		return ret;
-	return platform_driver_register(&nmk_pinctrl_driver);
-}
-
-core_initcall(nmk_gpio_init);
-
-MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
-MODULE_DESCRIPTION("Nomadik GPIO Driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-db8500.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-db8500.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-db8500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-db8500.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1257 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pinctrl/pinctrl.h>
-#include "pinctrl-nomadik.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define _GPIO(offset)		(offset)
-
-#define DB8500_PIN_AJ5		_GPIO(0)
-#define DB8500_PIN_AJ3		_GPIO(1)
-#define DB8500_PIN_AH4		_GPIO(2)
-#define DB8500_PIN_AH3		_GPIO(3)
-#define DB8500_PIN_AH6		_GPIO(4)
-#define DB8500_PIN_AG6		_GPIO(5)
-#define DB8500_PIN_AF6		_GPIO(6)
-#define DB8500_PIN_AG5		_GPIO(7)
-#define DB8500_PIN_AD5		_GPIO(8)
-#define DB8500_PIN_AE4		_GPIO(9)
-#define DB8500_PIN_AF5		_GPIO(10)
-#define DB8500_PIN_AG4		_GPIO(11)
-#define DB8500_PIN_AC4		_GPIO(12)
-#define DB8500_PIN_AF3		_GPIO(13)
-#define DB8500_PIN_AE3		_GPIO(14)
-#define DB8500_PIN_AC3		_GPIO(15)
-#define DB8500_PIN_AD3		_GPIO(16)
-#define DB8500_PIN_AD4		_GPIO(17)
-#define DB8500_PIN_AC2		_GPIO(18)
-#define DB8500_PIN_AC1		_GPIO(19)
-#define DB8500_PIN_AB4		_GPIO(20)
-#define DB8500_PIN_AB3		_GPIO(21)
-#define DB8500_PIN_AA3		_GPIO(22)
-#define DB8500_PIN_AA4		_GPIO(23)
-#define DB8500_PIN_AB2		_GPIO(24)
-#define DB8500_PIN_Y4		_GPIO(25)
-#define DB8500_PIN_Y2		_GPIO(26)
-#define DB8500_PIN_AA2		_GPIO(27)
-#define DB8500_PIN_AA1		_GPIO(28)
-#define DB8500_PIN_W2		_GPIO(29)
-#define DB8500_PIN_W3		_GPIO(30)
-#define DB8500_PIN_V3		_GPIO(31)
-#define DB8500_PIN_V2		_GPIO(32)
-#define DB8500_PIN_AF2		_GPIO(33)
-#define DB8500_PIN_AE1		_GPIO(34)
-#define DB8500_PIN_AE2		_GPIO(35)
-#define DB8500_PIN_AG2		_GPIO(36)
-/* Hole */
-#define DB8500_PIN_F3		_GPIO(64)
-#define DB8500_PIN_F1		_GPIO(65)
-#define DB8500_PIN_G3		_GPIO(66)
-#define DB8500_PIN_G2		_GPIO(67)
-#define DB8500_PIN_E1		_GPIO(68)
-#define DB8500_PIN_E2		_GPIO(69)
-#define DB8500_PIN_G5		_GPIO(70)
-#define DB8500_PIN_G4		_GPIO(71)
-#define DB8500_PIN_H4		_GPIO(72)
-#define DB8500_PIN_H3		_GPIO(73)
-#define DB8500_PIN_J3		_GPIO(74)
-#define DB8500_PIN_H2		_GPIO(75)
-#define DB8500_PIN_J2		_GPIO(76)
-#define DB8500_PIN_H1		_GPIO(77)
-#define DB8500_PIN_F4		_GPIO(78)
-#define DB8500_PIN_E3		_GPIO(79)
-#define DB8500_PIN_E4		_GPIO(80)
-#define DB8500_PIN_D2		_GPIO(81)
-#define DB8500_PIN_C1		_GPIO(82)
-#define DB8500_PIN_D3		_GPIO(83)
-#define DB8500_PIN_C2		_GPIO(84)
-#define DB8500_PIN_D5		_GPIO(85)
-#define DB8500_PIN_C6		_GPIO(86)
-#define DB8500_PIN_B3		_GPIO(87)
-#define DB8500_PIN_C4		_GPIO(88)
-#define DB8500_PIN_E6		_GPIO(89)
-#define DB8500_PIN_A3		_GPIO(90)
-#define DB8500_PIN_B6		_GPIO(91)
-#define DB8500_PIN_D6		_GPIO(92)
-#define DB8500_PIN_B7		_GPIO(93)
-#define DB8500_PIN_D7		_GPIO(94)
-#define DB8500_PIN_E8		_GPIO(95)
-#define DB8500_PIN_D8		_GPIO(96)
-#define DB8500_PIN_D9		_GPIO(97)
-/* Hole */
-#define DB8500_PIN_A5		_GPIO(128)
-#define DB8500_PIN_B4		_GPIO(129)
-#define DB8500_PIN_C8		_GPIO(130)
-#define DB8500_PIN_A12		_GPIO(131)
-#define DB8500_PIN_C10		_GPIO(132)
-#define DB8500_PIN_B10		_GPIO(133)
-#define DB8500_PIN_B9		_GPIO(134)
-#define DB8500_PIN_A9		_GPIO(135)
-#define DB8500_PIN_C7		_GPIO(136)
-#define DB8500_PIN_A7		_GPIO(137)
-#define DB8500_PIN_C5		_GPIO(138)
-#define DB8500_PIN_C9		_GPIO(139)
-#define DB8500_PIN_B11		_GPIO(140)
-#define DB8500_PIN_C12		_GPIO(141)
-#define DB8500_PIN_C11		_GPIO(142)
-#define DB8500_PIN_D12		_GPIO(143)
-#define DB8500_PIN_B13		_GPIO(144)
-#define DB8500_PIN_C13		_GPIO(145)
-#define DB8500_PIN_D13		_GPIO(146)
-#define DB8500_PIN_C15		_GPIO(147)
-#define DB8500_PIN_B16		_GPIO(148)
-#define DB8500_PIN_B14		_GPIO(149)
-#define DB8500_PIN_C14		_GPIO(150)
-#define DB8500_PIN_D17		_GPIO(151)
-#define DB8500_PIN_D16		_GPIO(152)
-#define DB8500_PIN_B17		_GPIO(153)
-#define DB8500_PIN_C16		_GPIO(154)
-#define DB8500_PIN_C19		_GPIO(155)
-#define DB8500_PIN_C17		_GPIO(156)
-#define DB8500_PIN_A18		_GPIO(157)
-#define DB8500_PIN_C18		_GPIO(158)
-#define DB8500_PIN_B19		_GPIO(159)
-#define DB8500_PIN_B20		_GPIO(160)
-#define DB8500_PIN_D21		_GPIO(161)
-#define DB8500_PIN_D20		_GPIO(162)
-#define DB8500_PIN_C20		_GPIO(163)
-#define DB8500_PIN_B21		_GPIO(164)
-#define DB8500_PIN_C21		_GPIO(165)
-#define DB8500_PIN_A22		_GPIO(166)
-#define DB8500_PIN_B24		_GPIO(167)
-#define DB8500_PIN_C22		_GPIO(168)
-#define DB8500_PIN_D22		_GPIO(169)
-#define DB8500_PIN_C23		_GPIO(170)
-#define DB8500_PIN_D23		_GPIO(171)
-/* Hole */
-#define DB8500_PIN_AJ27		_GPIO(192)
-#define DB8500_PIN_AH27		_GPIO(193)
-#define DB8500_PIN_AF27		_GPIO(194)
-#define DB8500_PIN_AG28		_GPIO(195)
-#define DB8500_PIN_AG26		_GPIO(196)
-#define DB8500_PIN_AH24		_GPIO(197)
-#define DB8500_PIN_AG25		_GPIO(198)
-#define DB8500_PIN_AH23		_GPIO(199)
-#define DB8500_PIN_AH26		_GPIO(200)
-#define DB8500_PIN_AF24		_GPIO(201)
-#define DB8500_PIN_AF25		_GPIO(202)
-#define DB8500_PIN_AE23		_GPIO(203)
-#define DB8500_PIN_AF23		_GPIO(204)
-#define DB8500_PIN_AG23		_GPIO(205)
-#define DB8500_PIN_AG24		_GPIO(206)
-#define DB8500_PIN_AJ23		_GPIO(207)
-#define DB8500_PIN_AH16		_GPIO(208)
-#define DB8500_PIN_AG15		_GPIO(209)
-#define DB8500_PIN_AJ15		_GPIO(210)
-#define DB8500_PIN_AG14		_GPIO(211)
-#define DB8500_PIN_AF13		_GPIO(212)
-#define DB8500_PIN_AG13		_GPIO(213)
-#define DB8500_PIN_AH15		_GPIO(214)
-#define DB8500_PIN_AH13		_GPIO(215)
-#define DB8500_PIN_AG12		_GPIO(216)
-#define DB8500_PIN_AH12		_GPIO(217)
-#define DB8500_PIN_AH11		_GPIO(218)
-#define DB8500_PIN_AG10		_GPIO(219)
-#define DB8500_PIN_AH10		_GPIO(220)
-#define DB8500_PIN_AJ11		_GPIO(221)
-#define DB8500_PIN_AJ9		_GPIO(222)
-#define DB8500_PIN_AH9		_GPIO(223)
-#define DB8500_PIN_AG9		_GPIO(224)
-#define DB8500_PIN_AG8		_GPIO(225)
-#define DB8500_PIN_AF8		_GPIO(226)
-#define DB8500_PIN_AH7		_GPIO(227)
-#define DB8500_PIN_AJ6		_GPIO(228)
-#define DB8500_PIN_AG7		_GPIO(229)
-#define DB8500_PIN_AF7		_GPIO(230)
-/* Hole */
-#define DB8500_PIN_AF28		_GPIO(256)
-#define DB8500_PIN_AE29		_GPIO(257)
-#define DB8500_PIN_AD29		_GPIO(258)
-#define DB8500_PIN_AC29		_GPIO(259)
-#define DB8500_PIN_AD28		_GPIO(260)
-#define DB8500_PIN_AD26		_GPIO(261)
-#define DB8500_PIN_AE26		_GPIO(262)
-#define DB8500_PIN_AG29		_GPIO(263)
-#define DB8500_PIN_AE27		_GPIO(264)
-#define DB8500_PIN_AD27		_GPIO(265)
-#define DB8500_PIN_AC28		_GPIO(266)
-#define DB8500_PIN_AC27		_GPIO(267)
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc nmk_db8500_pins[] = {
-	PINCTRL_PIN(DB8500_PIN_AJ5, "GPIO0_AJ5"),
-	PINCTRL_PIN(DB8500_PIN_AJ3, "GPIO1_AJ3"),
-	PINCTRL_PIN(DB8500_PIN_AH4, "GPIO2_AH4"),
-	PINCTRL_PIN(DB8500_PIN_AH3, "GPIO3_AH3"),
-	PINCTRL_PIN(DB8500_PIN_AH6, "GPIO4_AH6"),
-	PINCTRL_PIN(DB8500_PIN_AG6, "GPIO5_AG6"),
-	PINCTRL_PIN(DB8500_PIN_AF6, "GPIO6_AF6"),
-	PINCTRL_PIN(DB8500_PIN_AG5, "GPIO7_AG5"),
-	PINCTRL_PIN(DB8500_PIN_AD5, "GPIO8_AD5"),
-	PINCTRL_PIN(DB8500_PIN_AE4, "GPIO9_AE4"),
-	PINCTRL_PIN(DB8500_PIN_AF5, "GPIO10_AF5"),
-	PINCTRL_PIN(DB8500_PIN_AG4, "GPIO11_AG4"),
-	PINCTRL_PIN(DB8500_PIN_AC4, "GPIO12_AC4"),
-	PINCTRL_PIN(DB8500_PIN_AF3, "GPIO13_AF3"),
-	PINCTRL_PIN(DB8500_PIN_AE3, "GPIO14_AE3"),
-	PINCTRL_PIN(DB8500_PIN_AC3, "GPIO15_AC3"),
-	PINCTRL_PIN(DB8500_PIN_AD3, "GPIO16_AD3"),
-	PINCTRL_PIN(DB8500_PIN_AD4, "GPIO17_AD4"),
-	PINCTRL_PIN(DB8500_PIN_AC2, "GPIO18_AC2"),
-	PINCTRL_PIN(DB8500_PIN_AC1, "GPIO19_AC1"),
-	PINCTRL_PIN(DB8500_PIN_AB4, "GPIO20_AB4"),
-	PINCTRL_PIN(DB8500_PIN_AB3, "GPIO21_AB3"),
-	PINCTRL_PIN(DB8500_PIN_AA3, "GPIO22_AA3"),
-	PINCTRL_PIN(DB8500_PIN_AA4, "GPIO23_AA4"),
-	PINCTRL_PIN(DB8500_PIN_AB2, "GPIO24_AB2"),
-	PINCTRL_PIN(DB8500_PIN_Y4, "GPIO25_Y4"),
-	PINCTRL_PIN(DB8500_PIN_Y2, "GPIO26_Y2"),
-	PINCTRL_PIN(DB8500_PIN_AA2, "GPIO27_AA2"),
-	PINCTRL_PIN(DB8500_PIN_AA1, "GPIO28_AA1"),
-	PINCTRL_PIN(DB8500_PIN_W2, "GPIO29_W2"),
-	PINCTRL_PIN(DB8500_PIN_W3, "GPIO30_W3"),
-	PINCTRL_PIN(DB8500_PIN_V3, "GPIO31_V3"),
-	PINCTRL_PIN(DB8500_PIN_V2, "GPIO32_V2"),
-	PINCTRL_PIN(DB8500_PIN_AF2, "GPIO33_AF2"),
-	PINCTRL_PIN(DB8500_PIN_AE1, "GPIO34_AE1"),
-	PINCTRL_PIN(DB8500_PIN_AE2, "GPIO35_AE2"),
-	PINCTRL_PIN(DB8500_PIN_AG2, "GPIO36_AG2"),
-	/* Hole */
-	PINCTRL_PIN(DB8500_PIN_F3, "GPIO64_F3"),
-	PINCTRL_PIN(DB8500_PIN_F1, "GPIO65_F1"),
-	PINCTRL_PIN(DB8500_PIN_G3, "GPIO66_G3"),
-	PINCTRL_PIN(DB8500_PIN_G2, "GPIO67_G2"),
-	PINCTRL_PIN(DB8500_PIN_E1, "GPIO68_E1"),
-	PINCTRL_PIN(DB8500_PIN_E2, "GPIO69_E2"),
-	PINCTRL_PIN(DB8500_PIN_G5, "GPIO70_G5"),
-	PINCTRL_PIN(DB8500_PIN_G4, "GPIO71_G4"),
-	PINCTRL_PIN(DB8500_PIN_H4, "GPIO72_H4"),
-	PINCTRL_PIN(DB8500_PIN_H3, "GPIO73_H3"),
-	PINCTRL_PIN(DB8500_PIN_J3, "GPIO74_J3"),
-	PINCTRL_PIN(DB8500_PIN_H2, "GPIO75_H2"),
-	PINCTRL_PIN(DB8500_PIN_J2, "GPIO76_J2"),
-	PINCTRL_PIN(DB8500_PIN_H1, "GPIO77_H1"),
-	PINCTRL_PIN(DB8500_PIN_F4, "GPIO78_F4"),
-	PINCTRL_PIN(DB8500_PIN_E3, "GPIO79_E3"),
-	PINCTRL_PIN(DB8500_PIN_E4, "GPIO80_E4"),
-	PINCTRL_PIN(DB8500_PIN_D2, "GPIO81_D2"),
-	PINCTRL_PIN(DB8500_PIN_C1, "GPIO82_C1"),
-	PINCTRL_PIN(DB8500_PIN_D3, "GPIO83_D3"),
-	PINCTRL_PIN(DB8500_PIN_C2, "GPIO84_C2"),
-	PINCTRL_PIN(DB8500_PIN_D5, "GPIO85_D5"),
-	PINCTRL_PIN(DB8500_PIN_C6, "GPIO86_C6"),
-	PINCTRL_PIN(DB8500_PIN_B3, "GPIO87_B3"),
-	PINCTRL_PIN(DB8500_PIN_C4, "GPIO88_C4"),
-	PINCTRL_PIN(DB8500_PIN_E6, "GPIO89_E6"),
-	PINCTRL_PIN(DB8500_PIN_A3, "GPIO90_A3"),
-	PINCTRL_PIN(DB8500_PIN_B6, "GPIO91_B6"),
-	PINCTRL_PIN(DB8500_PIN_D6, "GPIO92_D6"),
-	PINCTRL_PIN(DB8500_PIN_B7, "GPIO93_B7"),
-	PINCTRL_PIN(DB8500_PIN_D7, "GPIO94_D7"),
-	PINCTRL_PIN(DB8500_PIN_E8, "GPIO95_E8"),
-	PINCTRL_PIN(DB8500_PIN_D8, "GPIO96_D8"),
-	PINCTRL_PIN(DB8500_PIN_D9, "GPIO97_D9"),
-	/* Hole */
-	PINCTRL_PIN(DB8500_PIN_A5, "GPIO128_A5"),
-	PINCTRL_PIN(DB8500_PIN_B4, "GPIO129_B4"),
-	PINCTRL_PIN(DB8500_PIN_C8, "GPIO130_C8"),
-	PINCTRL_PIN(DB8500_PIN_A12, "GPIO131_A12"),
-	PINCTRL_PIN(DB8500_PIN_C10, "GPIO132_C10"),
-	PINCTRL_PIN(DB8500_PIN_B10, "GPIO133_B10"),
-	PINCTRL_PIN(DB8500_PIN_B9, "GPIO134_B9"),
-	PINCTRL_PIN(DB8500_PIN_A9, "GPIO135_A9"),
-	PINCTRL_PIN(DB8500_PIN_C7, "GPIO136_C7"),
-	PINCTRL_PIN(DB8500_PIN_A7, "GPIO137_A7"),
-	PINCTRL_PIN(DB8500_PIN_C5, "GPIO138_C5"),
-	PINCTRL_PIN(DB8500_PIN_C9, "GPIO139_C9"),
-	PINCTRL_PIN(DB8500_PIN_B11, "GPIO140_B11"),
-	PINCTRL_PIN(DB8500_PIN_C12, "GPIO141_C12"),
-	PINCTRL_PIN(DB8500_PIN_C11, "GPIO142_C11"),
-	PINCTRL_PIN(DB8500_PIN_D12, "GPIO143_D12"),
-	PINCTRL_PIN(DB8500_PIN_B13, "GPIO144_B13"),
-	PINCTRL_PIN(DB8500_PIN_C13, "GPIO145_C13"),
-	PINCTRL_PIN(DB8500_PIN_D13, "GPIO146_D13"),
-	PINCTRL_PIN(DB8500_PIN_C15, "GPIO147_C15"),
-	PINCTRL_PIN(DB8500_PIN_B16, "GPIO148_B16"),
-	PINCTRL_PIN(DB8500_PIN_B14, "GPIO149_B14"),
-	PINCTRL_PIN(DB8500_PIN_C14, "GPIO150_C14"),
-	PINCTRL_PIN(DB8500_PIN_D17, "GPIO151_D17"),
-	PINCTRL_PIN(DB8500_PIN_D16, "GPIO152_D16"),
-	PINCTRL_PIN(DB8500_PIN_B17, "GPIO153_B17"),
-	PINCTRL_PIN(DB8500_PIN_C16, "GPIO154_C16"),
-	PINCTRL_PIN(DB8500_PIN_C19, "GPIO155_C19"),
-	PINCTRL_PIN(DB8500_PIN_C17, "GPIO156_C17"),
-	PINCTRL_PIN(DB8500_PIN_A18, "GPIO157_A18"),
-	PINCTRL_PIN(DB8500_PIN_C18, "GPIO158_C18"),
-	PINCTRL_PIN(DB8500_PIN_B19, "GPIO159_B19"),
-	PINCTRL_PIN(DB8500_PIN_B20, "GPIO160_B20"),
-	PINCTRL_PIN(DB8500_PIN_D21, "GPIO161_D21"),
-	PINCTRL_PIN(DB8500_PIN_D20, "GPIO162_D20"),
-	PINCTRL_PIN(DB8500_PIN_C20, "GPIO163_C20"),
-	PINCTRL_PIN(DB8500_PIN_B21, "GPIO164_B21"),
-	PINCTRL_PIN(DB8500_PIN_C21, "GPIO165_C21"),
-	PINCTRL_PIN(DB8500_PIN_A22, "GPIO166_A22"),
-	PINCTRL_PIN(DB8500_PIN_B24, "GPIO167_B24"),
-	PINCTRL_PIN(DB8500_PIN_C22, "GPIO168_C22"),
-	PINCTRL_PIN(DB8500_PIN_D22, "GPIO169_D22"),
-	PINCTRL_PIN(DB8500_PIN_C23, "GPIO170_C23"),
-	PINCTRL_PIN(DB8500_PIN_D23, "GPIO171_D23"),
-	/* Hole */
-	PINCTRL_PIN(DB8500_PIN_AJ27, "GPIO192_AJ27"),
-	PINCTRL_PIN(DB8500_PIN_AH27, "GPIO193_AH27"),
-	PINCTRL_PIN(DB8500_PIN_AF27, "GPIO194_AF27"),
-	PINCTRL_PIN(DB8500_PIN_AG28, "GPIO195_AG28"),
-	PINCTRL_PIN(DB8500_PIN_AG26, "GPIO196_AG26"),
-	PINCTRL_PIN(DB8500_PIN_AH24, "GPIO197_AH24"),
-	PINCTRL_PIN(DB8500_PIN_AG25, "GPIO198_AG25"),
-	PINCTRL_PIN(DB8500_PIN_AH23, "GPIO199_AH23"),
-	PINCTRL_PIN(DB8500_PIN_AH26, "GPIO200_AH26"),
-	PINCTRL_PIN(DB8500_PIN_AF24, "GPIO201_AF24"),
-	PINCTRL_PIN(DB8500_PIN_AF25, "GPIO202_AF25"),
-	PINCTRL_PIN(DB8500_PIN_AE23, "GPIO203_AE23"),
-	PINCTRL_PIN(DB8500_PIN_AF23, "GPIO204_AF23"),
-	PINCTRL_PIN(DB8500_PIN_AG23, "GPIO205_AG23"),
-	PINCTRL_PIN(DB8500_PIN_AG24, "GPIO206_AG24"),
-	PINCTRL_PIN(DB8500_PIN_AJ23, "GPIO207_AJ23"),
-	PINCTRL_PIN(DB8500_PIN_AH16, "GPIO208_AH16"),
-	PINCTRL_PIN(DB8500_PIN_AG15, "GPIO209_AG15"),
-	PINCTRL_PIN(DB8500_PIN_AJ15, "GPIO210_AJ15"),
-	PINCTRL_PIN(DB8500_PIN_AG14, "GPIO211_AG14"),
-	PINCTRL_PIN(DB8500_PIN_AF13, "GPIO212_AF13"),
-	PINCTRL_PIN(DB8500_PIN_AG13, "GPIO213_AG13"),
-	PINCTRL_PIN(DB8500_PIN_AH15, "GPIO214_AH15"),
-	PINCTRL_PIN(DB8500_PIN_AH13, "GPIO215_AH13"),
-	PINCTRL_PIN(DB8500_PIN_AG12, "GPIO216_AG12"),
-	PINCTRL_PIN(DB8500_PIN_AH12, "GPIO217_AH12"),
-	PINCTRL_PIN(DB8500_PIN_AH11, "GPIO218_AH11"),
-	PINCTRL_PIN(DB8500_PIN_AG10, "GPIO219_AG10"),
-	PINCTRL_PIN(DB8500_PIN_AH10, "GPIO220_AH10"),
-	PINCTRL_PIN(DB8500_PIN_AJ11, "GPIO221_AJ11"),
-	PINCTRL_PIN(DB8500_PIN_AJ9, "GPIO222_AJ9"),
-	PINCTRL_PIN(DB8500_PIN_AH9, "GPIO223_AH9"),
-	PINCTRL_PIN(DB8500_PIN_AG9, "GPIO224_AG9"),
-	PINCTRL_PIN(DB8500_PIN_AG8, "GPIO225_AG8"),
-	PINCTRL_PIN(DB8500_PIN_AF8, "GPIO226_AF8"),
-	PINCTRL_PIN(DB8500_PIN_AH7, "GPIO227_AH7"),
-	PINCTRL_PIN(DB8500_PIN_AJ6, "GPIO228_AJ6"),
-	PINCTRL_PIN(DB8500_PIN_AG7, "GPIO229_AG7"),
-	PINCTRL_PIN(DB8500_PIN_AF7, "GPIO230_AF7"),
-	/* Hole */
-	PINCTRL_PIN(DB8500_PIN_AF28, "GPIO256_AF28"),
-	PINCTRL_PIN(DB8500_PIN_AE29, "GPIO257_AE29"),
-	PINCTRL_PIN(DB8500_PIN_AD29, "GPIO258_AD29"),
-	PINCTRL_PIN(DB8500_PIN_AC29, "GPIO259_AC29"),
-	PINCTRL_PIN(DB8500_PIN_AD28, "GPIO260_AD28"),
-	PINCTRL_PIN(DB8500_PIN_AD26, "GPIO261_AD26"),
-	PINCTRL_PIN(DB8500_PIN_AE26, "GPIO262_AE26"),
-	PINCTRL_PIN(DB8500_PIN_AG29, "GPIO263_AG29"),
-	PINCTRL_PIN(DB8500_PIN_AE27, "GPIO264_AE27"),
-	PINCTRL_PIN(DB8500_PIN_AD27, "GPIO265_AD27"),
-	PINCTRL_PIN(DB8500_PIN_AC28, "GPIO266_AC28"),
-	PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"),
-};
-
-#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \
-			.pin_base = b, .npins = c }
-
-/*
- * This matches the 32-pin gpio chips registered by the GPIO portion. This
- * cannot be const since we assign the struct gpio_chip * pointer at runtime.
- */
-static struct pinctrl_gpio_range nmk_db8500_ranges[] = {
-	DB8500_GPIO_RANGE(0, 0, 32),
-	DB8500_GPIO_RANGE(1, 32, 5),
-	DB8500_GPIO_RANGE(2, 64, 32),
-	DB8500_GPIO_RANGE(3, 96, 2),
-	DB8500_GPIO_RANGE(4, 128, 32),
-	DB8500_GPIO_RANGE(5, 160, 12),
-	DB8500_GPIO_RANGE(6, 192, 32),
-	DB8500_GPIO_RANGE(7, 224, 7),
-	DB8500_GPIO_RANGE(8, 256, 12),
-};
-
-/*
- * Read the pin group names like this:
- * u0_a_1    = first groups of pins for uart0 on alt function a
- * i2c2_b_2  = second group of pins for i2c2 on alt function b
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* Altfunction A column */
-static const unsigned u0_a_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
-					DB8500_PIN_AH4, DB8500_PIN_AH3 };
-static const unsigned u1rxtx_a_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
-static const unsigned u1ctsrts_a_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
-/* Image processor I2C line, this is driven by image processor firmware */
-static const unsigned ipi2c_a_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
-static const unsigned ipi2c_a_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
-/* MSP0 can only be on these pins, but TXD and RXD can be flipped */
-static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
-static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 };
-static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
-/* Basic pins of the MMC/SD card 0 interface */
-static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
-	DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
-	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
-/* Often only 4 bits are used, then these are not needed (only used for MMC) */
-static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
-	DB8500_PIN_V3, DB8500_PIN_V2};
-static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 };
-/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
-static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
-static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 };
-/* LCD interface */
-static const unsigned lcdb_a_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
-					  DB8500_PIN_G3, DB8500_PIN_G2 };
-static const unsigned lcdvsi0_a_1_pins[] = { DB8500_PIN_E1 };
-static const unsigned lcdvsi1_a_1_pins[] = { DB8500_PIN_E2 };
-static const unsigned lcd_d0_d7_a_1_pins[] = {
-	DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
-	DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1 };
-/* D8 thru D11 often used as TVOUT lines */
-static const unsigned lcd_d8_d11_a_1_pins[] = { DB8500_PIN_F4,
-	DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2 };
-static const unsigned lcd_d12_d23_a_1_pins[] = {
-	DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5,
-	DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6,
-	DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7 };
-static const unsigned kp_a_1_pins[] = { DB8500_PIN_D7, DB8500_PIN_E8,
-	DB8500_PIN_D8, DB8500_PIN_D9 };
-static const unsigned kpskaskb_a_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16 };
-static const unsigned kp_a_2_pins[] = {
-	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
-	DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-/* MC2 has 8 data lines and no direction control, so only for (e)MMC */
-static const unsigned mc2_a_1_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4,
-	DB8500_PIN_C8, DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10,
-	DB8500_PIN_B9, DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7,
-	DB8500_PIN_C5 };
-static const unsigned ssp1_a_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
-					  DB8500_PIN_C12, DB8500_PIN_C11 };
-static const unsigned ssp0_a_1_pins[] = { DB8500_PIN_D12, DB8500_PIN_B13,
-					  DB8500_PIN_C13, DB8500_PIN_D13 };
-static const unsigned i2c0_a_1_pins[] = { DB8500_PIN_C15, DB8500_PIN_B16 };
-/*
- * Image processor GPIO pins are named "ipgpio" and have their own
- * numberspace
- */
-static const unsigned ipgpio0_a_1_pins[] = { DB8500_PIN_B14 };
-static const unsigned ipgpio1_a_1_pins[] = { DB8500_PIN_C14 };
-/* Three modem pins named RF_PURn, MODEM_STATE and MODEM_PWREN */
-static const unsigned modem_a_1_pins[] = { DB8500_PIN_D22, DB8500_PIN_C23,
-					   DB8500_PIN_D23 };
-/*
- * This MSP cannot switch RX and TX, SCK in a separate group since this
- * seems to be optional.
- */
-static const unsigned msp2sck_a_1_pins[] = { DB8500_PIN_AJ27 };
-static const unsigned msp2_a_1_pins[] = { DB8500_PIN_AH27, DB8500_PIN_AF27,
-					  DB8500_PIN_AG28, DB8500_PIN_AG26 };
-static const unsigned mc4_a_1_pins[] = { DB8500_PIN_AH24, DB8500_PIN_AG25,
-	DB8500_PIN_AH23, DB8500_PIN_AH26, DB8500_PIN_AF24, DB8500_PIN_AF25,
-	DB8500_PIN_AE23, DB8500_PIN_AF23, DB8500_PIN_AG23, DB8500_PIN_AG24,
-	DB8500_PIN_AJ23 };
-/* MC1 has only 4 data pins, designed for SD or SDIO exclusively */
-static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15,
-	DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
-	DB8500_PIN_AH15 };
-static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15,
-	DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 };
-static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
-	DB8500_PIN_AH12, DB8500_PIN_AH11 };
-static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10,
-	DB8500_PIN_AJ11 };
-static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
-	DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
-static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
-	DB8500_PIN_AG9, DB8500_PIN_AG8 };
-static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 };
-static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 };
-static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 };
-static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 };
-static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29,
-	DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26,
-	DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27,
-	DB8500_PIN_AC28, DB8500_PIN_AC27 };
-
-/* Altfunction B column */
-static const unsigned trig_b_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3 };
-static const unsigned i2c4_b_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 };
-static const unsigned i2c1_b_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 };
-static const unsigned i2c2_b_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 };
-static const unsigned i2c2_b_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 };
-static const unsigned msp0txrx_b_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
-static const unsigned i2c1_b_2_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
-/* Just RX and TX for UART2 */
-static const unsigned u2rxtx_b_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1 };
-static const unsigned uartmodtx_b_1_pins[] = { DB8500_PIN_AB4 };
-static const unsigned msp0sck_b_1_pins[] = { DB8500_PIN_AB3 };
-static const unsigned uartmodrx_b_1_pins[] = { DB8500_PIN_AA3 };
-static const unsigned stmmod_b_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
-	DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
-static const unsigned uartmodrx_b_2_pins[] = { DB8500_PIN_AB2 };
-static const unsigned spi3_b_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
-					  DB8500_PIN_V3, DB8500_PIN_V2 };
-static const unsigned msp1txrx_b_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
-static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
-	DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_E1, DB8500_PIN_E2,
-	DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3,
-	DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1,
-	DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2,
-	DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 };
-static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,
-	DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3};
-static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
-	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
-	DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
-	DB8500_PIN_D9, DB8500_PIN_A5, DB8500_PIN_B4, DB8500_PIN_C8,
-	DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9,
-	DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5,
-	DB8500_PIN_C9 };
-/* This chip select pin can be "ps0" in alt C so have it separately */
-static const unsigned smcs0_b_1_pins[] = { DB8500_PIN_E8 };
-/* This chip select pin can be "ps1" in alt C so have it separately */
-static const unsigned smcs1_b_1_pins[] = { DB8500_PIN_B14 };
-static const unsigned ipgpio7_b_1_pins[] = { DB8500_PIN_B11 };
-static const unsigned ipgpio2_b_1_pins[] = { DB8500_PIN_C12 };
-static const unsigned ipgpio3_b_1_pins[] = { DB8500_PIN_C11 };
-static const unsigned lcdaclk_b_1_pins[] = { DB8500_PIN_C14 };
-static const unsigned lcda_b_1_pins[] = { DB8500_PIN_D22,
-	DB8500_PIN_C23, DB8500_PIN_D23 };
-static const unsigned lcd_b_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
-	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
-	DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-static const unsigned ddrtrig_b_1_pins[] = { DB8500_PIN_AJ27 };
-static const unsigned pwl_b_1_pins[] = { DB8500_PIN_AF25 };
-static const unsigned spi1_b_1_pins[] = { DB8500_PIN_AG15, DB8500_PIN_AF13,
-					  DB8500_PIN_AG13, DB8500_PIN_AH15 };
-static const unsigned mc3_b_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
-	DB8500_PIN_AH12, DB8500_PIN_AH11, DB8500_PIN_AG10, DB8500_PIN_AH10,
-	DB8500_PIN_AJ11, DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9,
-	DB8500_PIN_AG8 };
-static const unsigned pwl_b_2_pins[] = { DB8500_PIN_AF8 };
-static const unsigned pwl_b_3_pins[] = { DB8500_PIN_AG7 };
-static const unsigned pwl_b_4_pins[] = { DB8500_PIN_AF7 };
-
-/* Altfunction C column */
-static const unsigned ipjtag_c_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3,
-	DB8500_PIN_AH4, DB8500_PIN_AH3, DB8500_PIN_AH6 };
-static const unsigned ipgpio6_c_1_pins[] = { DB8500_PIN_AG6 };
-static const unsigned ipgpio0_c_1_pins[] = { DB8500_PIN_AF6 };
-static const unsigned ipgpio1_c_1_pins[] = { DB8500_PIN_AG5 };
-static const unsigned ipgpio3_c_1_pins[] = { DB8500_PIN_AF5 };
-static const unsigned ipgpio2_c_1_pins[] = { DB8500_PIN_AG4 };
-static const unsigned slim0_c_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
-/* Optional 4-bit Memory Stick interface */
-static const unsigned ms_c_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
-	DB8500_PIN_AB3, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
-	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
-static const unsigned iptrigout_c_1_pins[] = { DB8500_PIN_AB4 };
-static const unsigned u2rxtx_c_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3 };
-static const unsigned u2ctsrts_c_1_pins[] = { DB8500_PIN_V3, DB8500_PIN_V2 };
-static const unsigned u0_c_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AE1,
-					DB8500_PIN_AE2, DB8500_PIN_AG2 };
-static const unsigned ipgpio4_c_1_pins[] = { DB8500_PIN_F3 };
-static const unsigned ipgpio5_c_1_pins[] = { DB8500_PIN_F1 };
-static const unsigned ipgpio6_c_2_pins[] = { DB8500_PIN_G3 };
-static const unsigned ipgpio7_c_1_pins[] = { DB8500_PIN_G2 };
-static const unsigned smcleale_c_1_pins[] = { DB8500_PIN_E1, DB8500_PIN_E2 };
-static const unsigned stmape_c_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
-	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
-static const unsigned u2rxtx_c_2_pins[] = { DB8500_PIN_H2, DB8500_PIN_J2 };
-static const unsigned ipgpio2_c_2_pins[] = { DB8500_PIN_F4 };
-static const unsigned ipgpio3_c_2_pins[] = { DB8500_PIN_E3 };
-static const unsigned ipgpio4_c_2_pins[] = { DB8500_PIN_E4 };
-static const unsigned ipgpio5_c_2_pins[] = { DB8500_PIN_D2 };
-static const unsigned mc5_c_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
-	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
-	DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8,
-	DB8500_PIN_D9 };
-static const unsigned mc2rstn_c_1_pins[] = { DB8500_PIN_C8 };
-static const unsigned kp_c_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11,
-	DB8500_PIN_C12, DB8500_PIN_C11, DB8500_PIN_D17, DB8500_PIN_D16,
-	DB8500_PIN_C23, DB8500_PIN_D23 };
-static const unsigned smps0_c_1_pins[] = { DB8500_PIN_E8 };
-static const unsigned smps1_c_1_pins[] = { DB8500_PIN_B14 };
-static const unsigned u2rxtx_c_3_pins[] = { DB8500_PIN_B17, DB8500_PIN_C16 };
-static const unsigned stmape_c_2_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
-static const unsigned uartmodrx_c_1_pins[] = { DB8500_PIN_D21 };
-static const unsigned uartmodtx_c_1_pins[] = { DB8500_PIN_D20 };
-static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 };
-static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 };
-static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 };
-static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 };
-static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 };
-static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 };
-static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9,
-					  DB8500_PIN_AG9, DB8500_PIN_AG8 };
-static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 };
-static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
-
-/* Other C1 column */
-static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 };
-static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
-	DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
-static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 };
-static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 };
-static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
-	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
-	DB8500_PIN_J2, DB8500_PIN_H1 };
-static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
-	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
-	DB8500_PIN_D6, DB8500_PIN_B7 };
-static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 };
-static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 };
-static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 };
-static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 };
-static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
-static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20,
-	DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22,
-	DB8500_PIN_B24, DB8500_PIN_C22 };
-static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 };
-static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
-	DB8500_PIN_AH12, DB8500_PIN_AH11 };
-static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12,
-	DB8500_PIN_AH11 };
-
-/* Other C2 column */
-static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2,
-	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
-static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
-	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
-	DB8500_PIN_J2, DB8500_PIN_H1 };
-static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
-	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
-	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-
-/* Other C3 column */
-static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2,
-	DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 };
-static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
-	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
-static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 };
-static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 };
-static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
-	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
-	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-
-/* Other C4 column */
-static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
-	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 };
-static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
-	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
-	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
-	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
-	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-
-#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct nmk_pingroup nmk_db8500_groups[] = {
-	/* Altfunction A column */
-	DB8500_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc0_dat47_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc0dat31dir_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(mc1_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
-	/* Altfunction B column */
-	DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(u2rxtx_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(uartmodtx_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(msp0sck_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(uartmodrx_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(uartmodrx_b_2, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(lcdaclk_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(lcda_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(lcd_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B),
-	DB8500_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B),
-	/* Altfunction C column */
-	DB8500_PIN_GROUP(ipjtag_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(slim0_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ms_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(iptrigout_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(u2ctsrts_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(u2rxtx_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(u2rxtx_c_3, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(stmape_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(uartmodrx_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(uartmodtx_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
-	/* Other alt C1 column */
-	DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
-	DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
-	/* Other alt C2 column */
-	DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
-	DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2),
-	DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2),
-	/* Other alt C3 column */
-	DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3),
-	DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3),
-	DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3),
-	DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3),
-	DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3),
-	/* Other alt C4 column */
-	DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4),
-	DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define DB8500_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-DB8500_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1");
-DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
-/*
- * UART2 can be muxed out with just RX/TX in four places, CTS+RTS is however
- * only available on two pins in alternative function C
- */
-DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1",
-		   "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1");
-DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
-/*
- * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
- * switched around by selecting the altfunction A or B. The SCK pin is
- * only available on the altfunction B.
- */
-DB8500_FUNC_GROUPS(msp0, "msp0txrx_a_1", "msp0tfstck_a_1", "msp0rfstck_a_1",
-		   "msp0txrx_b_1", "msp0sck_b_1");
-DB8500_FUNC_GROUPS(mc0, "mc0_a_1", "mc0_dat47_a_1", "mc0dat31dir_a_1");
-/* MSP0 can swap RX/TX like MSP0 but has no SCK pin available */
-DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");
-DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");
-DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",
-	"lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1");
-DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
-DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
-DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");
-DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1");
-DB8500_FUNC_GROUPS(i2c0, "i2c0_a_1");
-/* The image processor has 8 GPIO pins that can be muxed out */
-DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1",
-	"ipgpio2_b_1", "ipgpio3_b_1", "ipgpio6_c_1", "ipgpio0_c_1",
-	"ipgpio1_c_1", "ipgpio3_c_1", "ipgpio2_c_1", "ipgpio4_c_1",
-	"ipgpio5_c_1", "ipgpio6_c_2", "ipgpio7_c_1", "ipgpio2_c_2",
-	"ipgpio3_c_2", "ipgpio4_c_2", "ipgpio5_c_2");
-/* MSP2 can not invert the RX/TX pins but has the optional SCK pin */
-DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");
-DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
-DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1");
-DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
-DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1",
-		"clkout2_a_1", "clkout2_a_2", "clkout2_c_1");
-DB8500_FUNC_GROUPS(usb, "usb_a_1");
-DB8500_FUNC_GROUPS(trig, "trig_b_1");
-DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
-DB8500_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2");
-DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
-/*
- * The modem UART can output its RX and TX pins in some different places,
- * so select one of each.
- */
-DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2",
-		"uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1",
-		"uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1");
-DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1",
-		"stmmod_oc3_1", "stmmod_oc3_2");
-DB8500_FUNC_GROUPS(spi3, "spi3_b_1");
-/* Select between CS0 on alt B or PS1 on alt C */
-DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1",
-		   "smps0_c_1", "smps1_c_1");
-DB8500_FUNC_GROUPS(lcda, "lcdaclk_b_1", "lcda_b_1");
-DB8500_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
-DB8500_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4");
-DB8500_FUNC_GROUPS(spi1, "spi1_b_1");
-DB8500_FUNC_GROUPS(mc3, "mc3_b_1");
-DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1");
-DB8500_FUNC_GROUPS(slim0, "slim0_c_1");
-DB8500_FUNC_GROUPS(ms, "ms_c_1");
-DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1");
-DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1");
-DB8500_FUNC_GROUPS(mc5, "mc5_c_1");
-DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2");
-DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2");
-DB8500_FUNC_GROUPS(spi0, "spi0_c_1");
-DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2");
-DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
-DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1");
-DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1");
-DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2");
-DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1");
-DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1");
-DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct nmk_function nmk_db8500_functions[] = {
-	FUNCTION(u0),
-	FUNCTION(u1),
-	FUNCTION(u2),
-	FUNCTION(ipi2c),
-	FUNCTION(msp0),
-	FUNCTION(mc0),
-	FUNCTION(msp1),
-	FUNCTION(lcdb),
-	FUNCTION(lcd),
-	FUNCTION(kp),
-	FUNCTION(mc2),
-	FUNCTION(ssp1),
-	FUNCTION(ssp0),
-	FUNCTION(i2c0),
-	FUNCTION(ipgpio),
-	FUNCTION(msp2),
-	FUNCTION(mc4),
-	FUNCTION(mc1),
-	FUNCTION(hsi),
-	FUNCTION(clkout),
-	FUNCTION(usb),
-	FUNCTION(trig),
-	FUNCTION(i2c4),
-	FUNCTION(i2c1),
-	FUNCTION(i2c2),
-	FUNCTION(uartmod),
-	FUNCTION(stmmod),
-	FUNCTION(spi3),
-	FUNCTION(sm),
-	FUNCTION(lcda),
-	FUNCTION(ddrtrig),
-	FUNCTION(pwl),
-	FUNCTION(spi1),
-	FUNCTION(mc3),
-	FUNCTION(ipjtag),
-	FUNCTION(slim0),
-	FUNCTION(ms),
-	FUNCTION(iptrigout),
-	FUNCTION(stmape),
-	FUNCTION(mc5),
-	FUNCTION(usbsim),
-	FUNCTION(i2c3),
-	FUNCTION(spi0),
-	FUNCTION(spi2),
-	FUNCTION(remap),
-	FUNCTION(ptm),
-	FUNCTION(rf),
-	FUNCTION(hx),
-	FUNCTION(etm),
-	FUNCTION(hwobs),
-};
-
-static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
-	PRCM_GPIOCR_ALTCX(23,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_CLK_a */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_CLK_a */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(24,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE or U2_RXD ??? */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_VAL_a */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(25,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[0] */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[0] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(26,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[1] */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[1] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(27,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[2] */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[2] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(28,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[3] */
-				true, PRCM_IDX_GPIOCR1, 7,	/* SBAG_D_a[3] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(29,	false, 0, 0,
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(30,	false, 0, 0,
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(31,	false, 0, 0,
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(32,	false, 0, 0,
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 10,	/* STM_MOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(68,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP_SELECT_ON */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(69,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP_SELECT_ON */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(70,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D23 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_CLK */
-	),
-	PRCM_GPIOCR_ALTCX(71,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D22 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D3 */
-	),
-	PRCM_GPIOCR_ALTCX(72,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D21 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D2 */
-	),
-	PRCM_GPIOCR_ALTCX(73,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D20 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D1 */
-	),
-	PRCM_GPIOCR_ALTCX(74,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D19 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 11,	/* STM_MOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_D0 */
-	),
-	PRCM_GPIOCR_ALTCX(75,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D18 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 0,	/* DBG_UARTMOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(76,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D17 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				true, PRCM_IDX_GPIOCR1, 0,	/* DBG_UARTMOD_CMD0 */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(77,	true, PRCM_IDX_GPIOCR1, 5,	/* PTM_A9_D16 */
-				true, PRCM_IDX_GPIOCR2, 2,	/* DBG_ETM_R4_CMD0 */
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 8	/* SBAG_VAL */
-	),
-	PRCM_GPIOCR_ALTCX(86,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O3 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(87,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O2 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(88,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I3 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(89,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I2 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(90,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O1 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(91,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_O0 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(92,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I1 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(93,	true, PRCM_IDX_GPIOCR1, 12,	/* KP_I0 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(96,	true, PRCM_IDX_GPIOCR2, 3,	/* RF_INT */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(97,	true, PRCM_IDX_GPIOCR2, 1,	/* RF_CTRL */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(151,	false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_CTL */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS17 */
-	),
-	PRCM_GPIOCR_ALTCX(152,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_CLK */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_CLK */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS16 */
-	),
-	PRCM_GPIOCR_ALTCX(153,	true, PRCM_IDX_GPIOCR1, 1,	/* UARTMOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D15 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS15 */
-	),
-	PRCM_GPIOCR_ALTCX(154,	true, PRCM_IDX_GPIOCR1, 1,	/* UARTMOD_CMD1 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D14 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS14 */
-	),
-	PRCM_GPIOCR_ALTCX(155,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D13 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS13 */
-	),
-	PRCM_GPIOCR_ALTCX(156,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D12 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS12 */
-	),
-	PRCM_GPIOCR_ALTCX(157,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D11 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS11 */
-	),
-	PRCM_GPIOCR_ALTCX(158,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D10 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS10 */
-	),
-	PRCM_GPIOCR_ALTCX(159,	true, PRCM_IDX_GPIOCR1, 13,	/* STM_MOD_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D9 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS9 */
-	),
-	PRCM_GPIOCR_ALTCX(160,	false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 14,	/* PTM_A9_D8 */
-				true, PRCM_IDX_GPIOCR1, 19,	/* DBG_ETM_R4_CMD2 */
-				true, PRCM_IDX_GPIOCR1, 25	/* HW_OBS8 */
-	),
-	PRCM_GPIOCR_ALTCX(161,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO7 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D7 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS7 */
-	),
-	PRCM_GPIOCR_ALTCX(162,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO6 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D6 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS6 */
-	),
-	PRCM_GPIOCR_ALTCX(163,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO5 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D5 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS5 */
-	),
-	PRCM_GPIOCR_ALTCX(164,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO4 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D4 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS4 */
-	),
-	PRCM_GPIOCR_ALTCX(165,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO3 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D3 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS3 */
-	),
-	PRCM_GPIOCR_ALTCX(166,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO2 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D2 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS2 */
-	),
-	PRCM_GPIOCR_ALTCX(167,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO1 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D1 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS1 */
-	),
-	PRCM_GPIOCR_ALTCX(168,	true, PRCM_IDX_GPIOCR1, 4,	/* Hx_GPIO0 */
-				true, PRCM_IDX_GPIOCR1, 6,	/* PTM_A9_D0 */
-				true, PRCM_IDX_GPIOCR1, 15,	/* DBG_ETM_R4_CMD1*/
-				true, PRCM_IDX_GPIOCR1, 24	/* HW_OBS0 */
-	),
-	PRCM_GPIOCR_ALTCX(170,	true, PRCM_IDX_GPIOCR2, 2,	/* RF_INT */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(171,	true, PRCM_IDX_GPIOCR2, 0,	/* RF_CTRL */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(215,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_TXD */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(216,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_FRM */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(217,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_CLK */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(218,	true, PRCM_IDX_GPIOCR1, 23,	/* SPI2_RXD */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-};
-
-static const u16 db8500_prcm_gpiocr_regs[] = {
-	[PRCM_IDX_GPIOCR1] = 0x138,
-	[PRCM_IDX_GPIOCR2] = 0x574,
-};
-
-static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
-	.gpio_ranges = nmk_db8500_ranges,
-	.gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
-	.pins = nmk_db8500_pins,
-	.npins = ARRAY_SIZE(nmk_db8500_pins),
-	.functions = nmk_db8500_functions,
-	.nfunctions = ARRAY_SIZE(nmk_db8500_functions),
-	.groups = nmk_db8500_groups,
-	.ngroups = ARRAY_SIZE(nmk_db8500_groups),
-	.altcx_pins = db8500_altcx_pins,
-	.npins_altcx = ARRAY_SIZE(db8500_altcx_pins),
-	.prcm_gpiocr_registers = db8500_prcm_gpiocr_regs,
-};
-
-void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
-{
-	*soc = &nmk_db8500_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-db8540.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-db8540.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-db8540.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-db8540.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1266 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pinctrl/pinctrl.h>
-#include "pinctrl-nomadik.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define _GPIO(offset)		(offset)
-
-#define DB8540_PIN_AH6		_GPIO(0)
-#define DB8540_PIN_AG7		_GPIO(1)
-#define DB8540_PIN_AF2		_GPIO(2)
-#define DB8540_PIN_AD3		_GPIO(3)
-#define DB8540_PIN_AF6		_GPIO(4)
-#define DB8540_PIN_AG6		_GPIO(5)
-#define DB8540_PIN_AD5		_GPIO(6)
-#define DB8540_PIN_AF7		_GPIO(7)
-#define DB8540_PIN_AG5		_GPIO(8)
-#define DB8540_PIN_AH5		_GPIO(9)
-#define DB8540_PIN_AE4		_GPIO(10)
-#define DB8540_PIN_AD1		_GPIO(11)
-#define DB8540_PIN_AD2		_GPIO(12)
-#define DB8540_PIN_AC2		_GPIO(13)
-#define DB8540_PIN_AC4		_GPIO(14)
-#define DB8540_PIN_AC3		_GPIO(15)
-#define DB8540_PIN_AH7		_GPIO(16)
-#define DB8540_PIN_AE7		_GPIO(17)
-/* Hole */
-#define DB8540_PIN_AF8		_GPIO(22)
-#define DB8540_PIN_AH11		_GPIO(23)
-#define DB8540_PIN_AG11		_GPIO(24)
-#define DB8540_PIN_AF11		_GPIO(25)
-#define DB8540_PIN_AH10		_GPIO(26)
-#define DB8540_PIN_AG10		_GPIO(27)
-#define DB8540_PIN_AF10		_GPIO(28)
-/* Hole */
-#define DB8540_PIN_AD4		_GPIO(33)
-#define DB8540_PIN_AF3		_GPIO(34)
-#define DB8540_PIN_AF5		_GPIO(35)
-#define DB8540_PIN_AG4		_GPIO(36)
-#define DB8540_PIN_AF9		_GPIO(37)
-#define DB8540_PIN_AE8		_GPIO(38)
-/* Hole */
-#define DB8540_PIN_M26		_GPIO(64)
-#define DB8540_PIN_M25		_GPIO(65)
-#define DB8540_PIN_M27		_GPIO(66)
-#define DB8540_PIN_N25		_GPIO(67)
-/* Hole */
-#define DB8540_PIN_M28		_GPIO(70)
-#define DB8540_PIN_N26		_GPIO(71)
-#define DB8540_PIN_M22		_GPIO(72)
-#define DB8540_PIN_N22		_GPIO(73)
-#define DB8540_PIN_N27		_GPIO(74)
-#define DB8540_PIN_N28		_GPIO(75)
-#define DB8540_PIN_P22		_GPIO(76)
-#define DB8540_PIN_P28		_GPIO(77)
-#define DB8540_PIN_P26		_GPIO(78)
-#define DB8540_PIN_T22		_GPIO(79)
-#define DB8540_PIN_R27		_GPIO(80)
-#define DB8540_PIN_P27		_GPIO(81)
-#define DB8540_PIN_R26		_GPIO(82)
-#define DB8540_PIN_R25		_GPIO(83)
-#define DB8540_PIN_U22		_GPIO(84)
-#define DB8540_PIN_T27		_GPIO(85)
-#define DB8540_PIN_T25		_GPIO(86)
-#define DB8540_PIN_T26		_GPIO(87)
-/* Hole */
-#define DB8540_PIN_AF20		_GPIO(116)
-#define DB8540_PIN_AG21		_GPIO(117)
-#define DB8540_PIN_AH19		_GPIO(118)
-#define DB8540_PIN_AE19		_GPIO(119)
-#define DB8540_PIN_AG18		_GPIO(120)
-#define DB8540_PIN_AH17		_GPIO(121)
-#define DB8540_PIN_AF19		_GPIO(122)
-#define DB8540_PIN_AF18		_GPIO(123)
-#define DB8540_PIN_AE18		_GPIO(124)
-#define DB8540_PIN_AG17		_GPIO(125)
-#define DB8540_PIN_AF17		_GPIO(126)
-#define DB8540_PIN_AE17		_GPIO(127)
-#define DB8540_PIN_AC27		_GPIO(128)
-#define DB8540_PIN_AD27		_GPIO(129)
-#define DB8540_PIN_AE28		_GPIO(130)
-#define DB8540_PIN_AG26		_GPIO(131)
-#define DB8540_PIN_AF25		_GPIO(132)
-#define DB8540_PIN_AE27		_GPIO(133)
-#define DB8540_PIN_AF27		_GPIO(134)
-#define DB8540_PIN_AG28		_GPIO(135)
-#define DB8540_PIN_AF28		_GPIO(136)
-#define DB8540_PIN_AG25		_GPIO(137)
-#define DB8540_PIN_AG24		_GPIO(138)
-#define DB8540_PIN_AD25		_GPIO(139)
-#define DB8540_PIN_AH25		_GPIO(140)
-#define DB8540_PIN_AF26		_GPIO(141)
-#define DB8540_PIN_AF23		_GPIO(142)
-#define DB8540_PIN_AG23		_GPIO(143)
-#define DB8540_PIN_AE25		_GPIO(144)
-#define DB8540_PIN_AH24		_GPIO(145)
-#define DB8540_PIN_AJ25		_GPIO(146)
-#define DB8540_PIN_AG27		_GPIO(147)
-#define DB8540_PIN_AH23		_GPIO(148)
-#define DB8540_PIN_AE26		_GPIO(149)
-#define DB8540_PIN_AE24		_GPIO(150)
-#define DB8540_PIN_AJ24		_GPIO(151)
-#define DB8540_PIN_AE21		_GPIO(152)
-#define DB8540_PIN_AG22		_GPIO(153)
-#define DB8540_PIN_AF21		_GPIO(154)
-#define DB8540_PIN_AF24		_GPIO(155)
-#define DB8540_PIN_AH22		_GPIO(156)
-#define DB8540_PIN_AJ23		_GPIO(157)
-#define DB8540_PIN_AH21		_GPIO(158)
-#define DB8540_PIN_AG20		_GPIO(159)
-#define DB8540_PIN_AE23		_GPIO(160)
-#define DB8540_PIN_AH20		_GPIO(161)
-#define DB8540_PIN_AG19		_GPIO(162)
-#define DB8540_PIN_AF22		_GPIO(163)
-#define DB8540_PIN_AJ21		_GPIO(164)
-#define DB8540_PIN_AD26		_GPIO(165)
-#define DB8540_PIN_AD28		_GPIO(166)
-#define DB8540_PIN_AC28		_GPIO(167)
-#define DB8540_PIN_AC26		_GPIO(168)
-/* Hole */
-#define DB8540_PIN_J3		_GPIO(192)
-#define DB8540_PIN_H1		_GPIO(193)
-#define DB8540_PIN_J2		_GPIO(194)
-#define DB8540_PIN_H2		_GPIO(195)
-#define DB8540_PIN_H3		_GPIO(196)
-#define DB8540_PIN_H4		_GPIO(197)
-#define DB8540_PIN_G2		_GPIO(198)
-#define DB8540_PIN_G3		_GPIO(199)
-#define DB8540_PIN_G4		_GPIO(200)
-#define DB8540_PIN_F2		_GPIO(201)
-#define DB8540_PIN_C6		_GPIO(202)
-#define DB8540_PIN_B6		_GPIO(203)
-#define DB8540_PIN_B7		_GPIO(204)
-#define DB8540_PIN_A7		_GPIO(205)
-#define DB8540_PIN_D7		_GPIO(206)
-#define DB8540_PIN_D8		_GPIO(207)
-#define DB8540_PIN_F3		_GPIO(208)
-#define DB8540_PIN_E2		_GPIO(209)
-#define DB8540_PIN_C7		_GPIO(210)
-#define DB8540_PIN_B8		_GPIO(211)
-#define DB8540_PIN_C10		_GPIO(212)
-#define DB8540_PIN_C8		_GPIO(213)
-#define DB8540_PIN_C9		_GPIO(214)
-/* Hole */
-#define DB8540_PIN_B9		_GPIO(219)
-#define DB8540_PIN_A10		_GPIO(220)
-#define DB8540_PIN_D9		_GPIO(221)
-#define DB8540_PIN_B11		_GPIO(222)
-#define DB8540_PIN_B10		_GPIO(223)
-#define DB8540_PIN_E10		_GPIO(224)
-#define DB8540_PIN_B12		_GPIO(225)
-#define DB8540_PIN_D10		_GPIO(226)
-#define DB8540_PIN_D11		_GPIO(227)
-#define DB8540_PIN_AJ6		_GPIO(228)
-#define DB8540_PIN_B13		_GPIO(229)
-#define DB8540_PIN_C12		_GPIO(230)
-#define DB8540_PIN_B14		_GPIO(231)
-#define DB8540_PIN_E11		_GPIO(232)
-/* Hole */
-#define DB8540_PIN_D12		_GPIO(256)
-#define DB8540_PIN_D15		_GPIO(257)
-#define DB8540_PIN_C13		_GPIO(258)
-#define DB8540_PIN_C14		_GPIO(259)
-#define DB8540_PIN_C18		_GPIO(260)
-#define DB8540_PIN_C16		_GPIO(261)
-#define DB8540_PIN_B16		_GPIO(262)
-#define DB8540_PIN_D18		_GPIO(263)
-#define DB8540_PIN_C15		_GPIO(264)
-#define DB8540_PIN_C17		_GPIO(265)
-#define DB8540_PIN_B17		_GPIO(266)
-#define DB8540_PIN_D17		_GPIO(267)
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc nmk_db8540_pins[] = {
-	PINCTRL_PIN(DB8540_PIN_AH6, "GPIO0_AH6"),
-	PINCTRL_PIN(DB8540_PIN_AG7, "GPIO1_AG7"),
-	PINCTRL_PIN(DB8540_PIN_AF2, "GPIO2_AF2"),
-	PINCTRL_PIN(DB8540_PIN_AD3, "GPIO3_AD3"),
-	PINCTRL_PIN(DB8540_PIN_AF6, "GPIO4_AF6"),
-	PINCTRL_PIN(DB8540_PIN_AG6, "GPIO5_AG6"),
-	PINCTRL_PIN(DB8540_PIN_AD5, "GPIO6_AD5"),
-	PINCTRL_PIN(DB8540_PIN_AF7, "GPIO7_AF7"),
-	PINCTRL_PIN(DB8540_PIN_AG5, "GPIO8_AG5"),
-	PINCTRL_PIN(DB8540_PIN_AH5, "GPIO9_AH5"),
-	PINCTRL_PIN(DB8540_PIN_AE4, "GPIO10_AE4"),
-	PINCTRL_PIN(DB8540_PIN_AD1, "GPIO11_AD1"),
-	PINCTRL_PIN(DB8540_PIN_AD2, "GPIO12_AD2"),
-	PINCTRL_PIN(DB8540_PIN_AC2, "GPIO13_AC2"),
-	PINCTRL_PIN(DB8540_PIN_AC4, "GPIO14_AC4"),
-	PINCTRL_PIN(DB8540_PIN_AC3, "GPIO15_AC3"),
-	PINCTRL_PIN(DB8540_PIN_AH7, "GPIO16_AH7"),
-	PINCTRL_PIN(DB8540_PIN_AE7, "GPIO17_AE7"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_AF8, "GPIO22_AF8"),
-	PINCTRL_PIN(DB8540_PIN_AH11, "GPIO23_AH11"),
-	PINCTRL_PIN(DB8540_PIN_AG11, "GPIO24_AG11"),
-	PINCTRL_PIN(DB8540_PIN_AF11, "GPIO25_AF11"),
-	PINCTRL_PIN(DB8540_PIN_AH10, "GPIO26_AH10"),
-	PINCTRL_PIN(DB8540_PIN_AG10, "GPIO27_AG10"),
-	PINCTRL_PIN(DB8540_PIN_AF10, "GPIO28_AF10"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_AD4, "GPIO33_AD4"),
-	PINCTRL_PIN(DB8540_PIN_AF3, "GPIO34_AF3"),
-	PINCTRL_PIN(DB8540_PIN_AF5, "GPIO35_AF5"),
-	PINCTRL_PIN(DB8540_PIN_AG4, "GPIO36_AG4"),
-	PINCTRL_PIN(DB8540_PIN_AF9, "GPIO37_AF9"),
-	PINCTRL_PIN(DB8540_PIN_AE8, "GPIO38_AE8"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_M26, "GPIO64_M26"),
-	PINCTRL_PIN(DB8540_PIN_M25, "GPIO65_M25"),
-	PINCTRL_PIN(DB8540_PIN_M27, "GPIO66_M27"),
-	PINCTRL_PIN(DB8540_PIN_N25, "GPIO67_N25"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_M28, "GPIO70_M28"),
-	PINCTRL_PIN(DB8540_PIN_N26, "GPIO71_N26"),
-	PINCTRL_PIN(DB8540_PIN_M22, "GPIO72_M22"),
-	PINCTRL_PIN(DB8540_PIN_N22, "GPIO73_N22"),
-	PINCTRL_PIN(DB8540_PIN_N27, "GPIO74_N27"),
-	PINCTRL_PIN(DB8540_PIN_N28, "GPIO75_N28"),
-	PINCTRL_PIN(DB8540_PIN_P22, "GPIO76_P22"),
-	PINCTRL_PIN(DB8540_PIN_P28, "GPIO77_P28"),
-	PINCTRL_PIN(DB8540_PIN_P26, "GPIO78_P26"),
-	PINCTRL_PIN(DB8540_PIN_T22, "GPIO79_T22"),
-	PINCTRL_PIN(DB8540_PIN_R27, "GPIO80_R27"),
-	PINCTRL_PIN(DB8540_PIN_P27, "GPIO81_P27"),
-	PINCTRL_PIN(DB8540_PIN_R26, "GPIO82_R26"),
-	PINCTRL_PIN(DB8540_PIN_R25, "GPIO83_R25"),
-	PINCTRL_PIN(DB8540_PIN_U22, "GPIO84_U22"),
-	PINCTRL_PIN(DB8540_PIN_T27, "GPIO85_T27"),
-	PINCTRL_PIN(DB8540_PIN_T25, "GPIO86_T25"),
-	PINCTRL_PIN(DB8540_PIN_T26, "GPIO87_T26"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_AF20, "GPIO116_AF20"),
-	PINCTRL_PIN(DB8540_PIN_AG21, "GPIO117_AG21"),
-	PINCTRL_PIN(DB8540_PIN_AH19, "GPIO118_AH19"),
-	PINCTRL_PIN(DB8540_PIN_AE19, "GPIO119_AE19"),
-	PINCTRL_PIN(DB8540_PIN_AG18, "GPIO120_AG18"),
-	PINCTRL_PIN(DB8540_PIN_AH17, "GPIO121_AH17"),
-	PINCTRL_PIN(DB8540_PIN_AF19, "GPIO122_AF19"),
-	PINCTRL_PIN(DB8540_PIN_AF18, "GPIO123_AF18"),
-	PINCTRL_PIN(DB8540_PIN_AE18, "GPIO124_AE18"),
-	PINCTRL_PIN(DB8540_PIN_AG17, "GPIO125_AG17"),
-	PINCTRL_PIN(DB8540_PIN_AF17, "GPIO126_AF17"),
-	PINCTRL_PIN(DB8540_PIN_AE17, "GPIO127_AE17"),
-	PINCTRL_PIN(DB8540_PIN_AC27, "GPIO128_AC27"),
-	PINCTRL_PIN(DB8540_PIN_AD27, "GPIO129_AD27"),
-	PINCTRL_PIN(DB8540_PIN_AE28, "GPIO130_AE28"),
-	PINCTRL_PIN(DB8540_PIN_AG26, "GPIO131_AG26"),
-	PINCTRL_PIN(DB8540_PIN_AF25, "GPIO132_AF25"),
-	PINCTRL_PIN(DB8540_PIN_AE27, "GPIO133_AE27"),
-	PINCTRL_PIN(DB8540_PIN_AF27, "GPIO134_AF27"),
-	PINCTRL_PIN(DB8540_PIN_AG28, "GPIO135_AG28"),
-	PINCTRL_PIN(DB8540_PIN_AF28, "GPIO136_AF28"),
-	PINCTRL_PIN(DB8540_PIN_AG25, "GPIO137_AG25"),
-	PINCTRL_PIN(DB8540_PIN_AG24, "GPIO138_AG24"),
-	PINCTRL_PIN(DB8540_PIN_AD25, "GPIO139_AD25"),
-	PINCTRL_PIN(DB8540_PIN_AH25, "GPIO140_AH25"),
-	PINCTRL_PIN(DB8540_PIN_AF26, "GPIO141_AF26"),
-	PINCTRL_PIN(DB8540_PIN_AF23, "GPIO142_AF23"),
-	PINCTRL_PIN(DB8540_PIN_AG23, "GPIO143_AG23"),
-	PINCTRL_PIN(DB8540_PIN_AE25, "GPIO144_AE25"),
-	PINCTRL_PIN(DB8540_PIN_AH24, "GPIO145_AH24"),
-	PINCTRL_PIN(DB8540_PIN_AJ25, "GPIO146_AJ25"),
-	PINCTRL_PIN(DB8540_PIN_AG27, "GPIO147_AG27"),
-	PINCTRL_PIN(DB8540_PIN_AH23, "GPIO148_AH23"),
-	PINCTRL_PIN(DB8540_PIN_AE26, "GPIO149_AE26"),
-	PINCTRL_PIN(DB8540_PIN_AE24, "GPIO150_AE24"),
-	PINCTRL_PIN(DB8540_PIN_AJ24, "GPIO151_AJ24"),
-	PINCTRL_PIN(DB8540_PIN_AE21, "GPIO152_AE21"),
-	PINCTRL_PIN(DB8540_PIN_AG22, "GPIO153_AG22"),
-	PINCTRL_PIN(DB8540_PIN_AF21, "GPIO154_AF21"),
-	PINCTRL_PIN(DB8540_PIN_AF24, "GPIO155_AF24"),
-	PINCTRL_PIN(DB8540_PIN_AH22, "GPIO156_AH22"),
-	PINCTRL_PIN(DB8540_PIN_AJ23, "GPIO157_AJ23"),
-	PINCTRL_PIN(DB8540_PIN_AH21, "GPIO158_AH21"),
-	PINCTRL_PIN(DB8540_PIN_AG20, "GPIO159_AG20"),
-	PINCTRL_PIN(DB8540_PIN_AE23, "GPIO160_AE23"),
-	PINCTRL_PIN(DB8540_PIN_AH20, "GPIO161_AH20"),
-	PINCTRL_PIN(DB8540_PIN_AG19, "GPIO162_AG19"),
-	PINCTRL_PIN(DB8540_PIN_AF22, "GPIO163_AF22"),
-	PINCTRL_PIN(DB8540_PIN_AJ21, "GPIO164_AJ21"),
-	PINCTRL_PIN(DB8540_PIN_AD26, "GPIO165_AD26"),
-	PINCTRL_PIN(DB8540_PIN_AD28, "GPIO166_AD28"),
-	PINCTRL_PIN(DB8540_PIN_AC28, "GPIO167_AC28"),
-	PINCTRL_PIN(DB8540_PIN_AC26, "GPIO168_AC26"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_J3, "GPIO192_J3"),
-	PINCTRL_PIN(DB8540_PIN_H1, "GPIO193_H1"),
-	PINCTRL_PIN(DB8540_PIN_J2, "GPIO194_J2"),
-	PINCTRL_PIN(DB8540_PIN_H2, "GPIO195_H2"),
-	PINCTRL_PIN(DB8540_PIN_H3, "GPIO196_H3"),
-	PINCTRL_PIN(DB8540_PIN_H4, "GPIO197_H4"),
-	PINCTRL_PIN(DB8540_PIN_G2, "GPIO198_G2"),
-	PINCTRL_PIN(DB8540_PIN_G3, "GPIO199_G3"),
-	PINCTRL_PIN(DB8540_PIN_G4, "GPIO200_G4"),
-	PINCTRL_PIN(DB8540_PIN_F2, "GPIO201_F2"),
-	PINCTRL_PIN(DB8540_PIN_C6, "GPIO202_C6"),
-	PINCTRL_PIN(DB8540_PIN_B6, "GPIO203_B6"),
-	PINCTRL_PIN(DB8540_PIN_B7, "GPIO204_B7"),
-	PINCTRL_PIN(DB8540_PIN_A7, "GPIO205_A7"),
-	PINCTRL_PIN(DB8540_PIN_D7, "GPIO206_D7"),
-	PINCTRL_PIN(DB8540_PIN_D8, "GPIO207_D8"),
-	PINCTRL_PIN(DB8540_PIN_F3, "GPIO208_F3"),
-	PINCTRL_PIN(DB8540_PIN_E2, "GPIO209_E2"),
-	PINCTRL_PIN(DB8540_PIN_C7, "GPIO210_C7"),
-	PINCTRL_PIN(DB8540_PIN_B8, "GPIO211_B8"),
-	PINCTRL_PIN(DB8540_PIN_C10, "GPIO212_C10"),
-	PINCTRL_PIN(DB8540_PIN_C8, "GPIO213_C8"),
-	PINCTRL_PIN(DB8540_PIN_C9, "GPIO214_C9"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_B9, "GPIO219_B9"),
-	PINCTRL_PIN(DB8540_PIN_A10, "GPIO220_A10"),
-	PINCTRL_PIN(DB8540_PIN_D9, "GPIO221_D9"),
-	PINCTRL_PIN(DB8540_PIN_B11, "GPIO222_B11"),
-	PINCTRL_PIN(DB8540_PIN_B10, "GPIO223_B10"),
-	PINCTRL_PIN(DB8540_PIN_E10, "GPIO224_E10"),
-	PINCTRL_PIN(DB8540_PIN_B12, "GPIO225_B12"),
-	PINCTRL_PIN(DB8540_PIN_D10, "GPIO226_D10"),
-	PINCTRL_PIN(DB8540_PIN_D11, "GPIO227_D11"),
-	PINCTRL_PIN(DB8540_PIN_AJ6, "GPIO228_AJ6"),
-	PINCTRL_PIN(DB8540_PIN_B13, "GPIO229_B13"),
-	PINCTRL_PIN(DB8540_PIN_C12, "GPIO230_C12"),
-	PINCTRL_PIN(DB8540_PIN_B14, "GPIO231_B14"),
-	PINCTRL_PIN(DB8540_PIN_E11, "GPIO232_E11"),
-	/* Hole */
-	PINCTRL_PIN(DB8540_PIN_D12, "GPIO256_D12"),
-	PINCTRL_PIN(DB8540_PIN_D15, "GPIO257_D15"),
-	PINCTRL_PIN(DB8540_PIN_C13, "GPIO258_C13"),
-	PINCTRL_PIN(DB8540_PIN_C14, "GPIO259_C14"),
-	PINCTRL_PIN(DB8540_PIN_C18, "GPIO260_C18"),
-	PINCTRL_PIN(DB8540_PIN_C16, "GPIO261_C16"),
-	PINCTRL_PIN(DB8540_PIN_B16, "GPIO262_B16"),
-	PINCTRL_PIN(DB8540_PIN_D18, "GPIO263_D18"),
-	PINCTRL_PIN(DB8540_PIN_C15, "GPIO264_C15"),
-	PINCTRL_PIN(DB8540_PIN_C17, "GPIO265_C17"),
-	PINCTRL_PIN(DB8540_PIN_B17, "GPIO266_B17"),
-	PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"),
-};
-
-#define DB8540_GPIO_RANGE(a, b, c) { .name = "db8540", .id = a, .base = b, \
-			.pin_base = b, .npins = c }
-
-/*
- * This matches the 32-pin gpio chips registered by the GPIO portion. This
- * cannot be const since we assign the struct gpio_chip * pointer at runtime.
- */
-static struct pinctrl_gpio_range nmk_db8540_ranges[] = {
-	DB8540_GPIO_RANGE(0, 0, 18),
-	DB8540_GPIO_RANGE(0, 22, 7),
-	DB8540_GPIO_RANGE(1, 33, 6),
-	DB8540_GPIO_RANGE(2, 64, 4),
-	DB8540_GPIO_RANGE(2, 70, 18),
-	DB8540_GPIO_RANGE(3, 116, 12),
-	DB8540_GPIO_RANGE(4, 128, 32),
-	DB8540_GPIO_RANGE(5, 160, 9),
-	DB8540_GPIO_RANGE(6, 192, 23),
-	DB8540_GPIO_RANGE(6, 219, 5),
-	DB8540_GPIO_RANGE(7, 224, 9),
-	DB8540_GPIO_RANGE(8, 256, 12),
-};
-
-/*
- * Read the pin group names like this:
- * u0_a_1    = first groups of pins for uart0 on alt function a
- * i2c2_b_2  = second group of pins for i2c2 on alt function b
- *
- * The groups are arranged as sets per altfunction column, so we can
- * mux in one group at a time by selecting the same altfunction for them
- * all. When functions require pins on different altfunctions, you need
- * to combine several groups.
- */
-
-/* Altfunction A column */
-static const unsigned u0_a_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7,
-					DB8540_PIN_AF2, DB8540_PIN_AD3 };
-static const unsigned u1rxtx_a_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 };
-static const unsigned u1ctsrts_a_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 };
-/* Image processor I2C line, this is driven by image processor firmware */
-static const unsigned ipi2c_a_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 };
-static const unsigned ipi2c_a_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 };
-/* MSP0 can only be on these pins, but TXD and RXD can be flipped */
-static const unsigned msp0txrx_a_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 };
-static const unsigned msp0tfstck_a_1_pins[] = { DB8540_PIN_AC2,
-	DB8540_PIN_AC4 };
-static const unsigned msp0rfsrck_a_1_pins[] = { DB8540_PIN_AH7,
-	DB8540_PIN_AE7 };
-/* Basic pins of the MMC/SD card 0 interface */
-static const unsigned mc0_a_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11,
-	DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10};
-/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
-static const unsigned msp1txrx_a_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 };
-static const unsigned msp1_a_1_pins[] = { DB8540_PIN_AF3, DB8540_PIN_AF5 };
-
-static const unsigned modobsclk_a_1_pins[] = { DB8540_PIN_AF9 };
-static const unsigned clkoutreq_a_1_pins[] = { DB8540_PIN_AE8 };
-/* LCD interface */
-static const unsigned lcdb_a_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
-	DB8540_PIN_M27, DB8540_PIN_N25 };
-static const unsigned lcdvsi0_a_1_pins[] = { DB8540_PIN_AJ24 };
-static const unsigned lcdvsi1_a_1_pins[] = { DB8540_PIN_AE21 };
-static const unsigned lcd_d0_d7_a_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
-	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
-	DB8540_PIN_P22, DB8540_PIN_P28 };
-/* D8 thru D11 often used as TVOUT lines */
-static const unsigned lcd_d8_d11_a_1_pins[] = { DB8540_PIN_P26, DB8540_PIN_T22,
-	DB8540_PIN_R27, DB8540_PIN_P27 };
-static const unsigned lcd_d12_d23_a_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25,
-	DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21,
-	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
-	DB8540_PIN_AG20, DB8540_PIN_AE23 };
-static const unsigned kp_a_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
-	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 };
-/* MC2 has 8 data lines and no direction control, so only for (e)MMC */
-static const unsigned mc2_a_1_pins[] = { DB8540_PIN_AC27, DB8540_PIN_AD27,
-	DB8540_PIN_AE28, DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27,
-	DB8540_PIN_AF27, DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25,
-	DB8540_PIN_AG24 };
-static const unsigned ssp1_a_1_pins[] = {  DB8540_PIN_AD25, DB8540_PIN_AH25,
-	DB8540_PIN_AF26, DB8540_PIN_AF23 };
-static const unsigned ssp0_a_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25,
-	DB8540_PIN_AH24, DB8540_PIN_AJ25 };
-static const unsigned i2c0_a_1_pins[] = { DB8540_PIN_AG27, DB8540_PIN_AH23 };
-/*
- * Image processor GPIO pins are named "ipgpio" and have their own
- * numberspace
- */
-static const unsigned ipgpio0_a_1_pins[] = { DB8540_PIN_AE26 };
-static const unsigned ipgpio1_a_1_pins[] = { DB8540_PIN_AE24 };
-/* modem i2s interface */
-static const unsigned modi2s_a_1_pins[] = { DB8540_PIN_AD26, DB8540_PIN_AD28,
-	DB8540_PIN_AC28, DB8540_PIN_AC26 };
-static const unsigned spi2_a_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21,
-	DB8540_PIN_AH19, DB8540_PIN_AE19 };
-static const unsigned u2txrx_a_1_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 };
-static const unsigned u2ctsrts_a_1_pins[] = { DB8540_PIN_AF19,
-	DB8540_PIN_AF18 };
-static const unsigned modsmb_a_1_pins[] = { DB8540_PIN_AF17, DB8540_PIN_AE17 };
-static const unsigned msp2sck_a_1_pins[] = { DB8540_PIN_J3 };
-static const unsigned msp2txdtcktfs_a_1_pins[] = { DB8540_PIN_H1, DB8540_PIN_J2,
-	DB8540_PIN_H2 };
-static const unsigned msp2rxd_a_1_pins[] = { DB8540_PIN_H3 };
-static const unsigned mc4_a_1_pins[] = { DB8540_PIN_H4, DB8540_PIN_G2,
-	DB8540_PIN_G3, DB8540_PIN_G4, DB8540_PIN_F2, DB8540_PIN_C6,
-	DB8540_PIN_B6, DB8540_PIN_B7, DB8540_PIN_A7, DB8540_PIN_D7,
-	DB8540_PIN_D8 };
-static const unsigned mc1_a_1_pins[] = { DB8540_PIN_F3, DB8540_PIN_E2,
-	DB8540_PIN_C7, DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8,
-	DB8540_PIN_C9 };
-/* mc1_a_2_pins exclude MC1_FBCLK */
-static const unsigned mc1_a_2_pins[] = { DB8540_PIN_F3,	DB8540_PIN_C7,
-	DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8,
-	DB8540_PIN_C9 };
-static const unsigned hsir_a_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10,
-	DB8540_PIN_D9 };
-static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
-	DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 };
-static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
-	DB8540_PIN_E10, DB8540_PIN_B12 };
-static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 };
-static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 };
-static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 };
-static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 };
-static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 };
-static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15,
-	DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16,
-	DB8540_PIN_B16, DB8540_PIN_D18, DB8540_PIN_C15, DB8540_PIN_C17,
-	DB8540_PIN_B17, DB8540_PIN_D17 };
-/* Altfunction B colum */
-static const unsigned apetrig_b_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7 };
-static const unsigned modtrig_b_1_pins[] = { DB8540_PIN_AF2, DB8540_PIN_AD3 };
-static const unsigned i2c4_b_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 };
-static const unsigned i2c1_b_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 };
-static const unsigned i2c2_b_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 };
-static const unsigned i2c2_b_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 };
-static const unsigned msp0txrx_b_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 };
-static const unsigned i2c1_b_2_pins[] = { DB8540_PIN_AH7, DB8540_PIN_AE7 };
-static const unsigned stmmod_b_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11,
-	DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
-static const unsigned moduartstmmux_b_1_pins[] = { DB8540_PIN_AG11 };
-static const unsigned msp1txrx_b_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 };
-static const unsigned kp_b_1_pins[] = { DB8540_PIN_AJ24, DB8540_PIN_AE21,
-	DB8540_PIN_M26, DB8540_PIN_M25, DB8540_PIN_M27, DB8540_PIN_N25,
-	DB8540_PIN_M28, DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22,
-	DB8540_PIN_N27, DB8540_PIN_N28, DB8540_PIN_P22, DB8540_PIN_P28,
-	DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27,
-	DB8540_PIN_R26, DB8540_PIN_R25 };
-static const unsigned u2txrx_b_1_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27 };
-static const unsigned sm_b_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
-	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
-	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22,
-	DB8540_PIN_AJ21, DB8540_PIN_AC27, DB8540_PIN_AD27, DB8540_PIN_AE28,
-	DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27, DB8540_PIN_AF27,
-	DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25, DB8540_PIN_AG24,
-	DB8540_PIN_AD25 };
-static const unsigned smcs0_b_1_pins[] = { DB8540_PIN_AG19 };
-static const unsigned smcs1_b_1_pins[] = { DB8540_PIN_AE26 };
-static const unsigned ipgpio7_b_1_pins[] = { DB8540_PIN_AH25 };
-static const unsigned ipgpio2_b_1_pins[] = { DB8540_PIN_AF26 };
-static const unsigned ipgpio3_b_1_pins[] = { DB8540_PIN_AF23 };
-static const unsigned i2c6_b_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25 };
-static const unsigned i2c5_b_1_pins[] = { DB8540_PIN_AH24, DB8540_PIN_AJ25 };
-static const unsigned u3txrx_b_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21 };
-static const unsigned u3ctsrts_b_1_pins[] = { DB8540_PIN_AH19,
-	DB8540_PIN_AE19 };
-static const unsigned i2c5_b_2_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 };
-static const unsigned i2c4_b_2_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 };
-static const unsigned u4txrx_b_1_pins[] = { DB8540_PIN_AE18, DB8540_PIN_AG17 };
-static const unsigned u4ctsrts_b_1_pins[] = { DB8540_PIN_AF17,
-	DB8540_PIN_AE17 };
-static const unsigned ddrtrig_b_1_pins[] = { DB8540_PIN_J3 };
-static const unsigned msp4_b_1_pins[] = { DB8540_PIN_H3 };
-static const unsigned pwl_b_1_pins[] = { DB8540_PIN_C6 };
-static const unsigned spi1_b_1_pins[] = { DB8540_PIN_E2, DB8540_PIN_C10,
-	DB8540_PIN_C8, DB8540_PIN_C9 };
-static const unsigned mc3_b_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10,
-	DB8540_PIN_D9, DB8540_PIN_B11, DB8540_PIN_B10, DB8540_PIN_E10,
-	DB8540_PIN_B12 };
-static const unsigned pwl_b_2_pins[] = { DB8540_PIN_D10 };
-static const unsigned pwl_b_3_pins[] = { DB8540_PIN_B13 };
-static const unsigned pwl_b_4_pins[] = { DB8540_PIN_C12 };
-static const unsigned u2txrx_b_2_pins[] = { DB8540_PIN_B17, DB8540_PIN_D17 };
-
-/* Altfunction C column */
-static const unsigned ipgpio6_c_1_pins[] = { DB8540_PIN_AG6 };
-static const unsigned ipgpio0_c_1_pins[] = { DB8540_PIN_AD5 };
-static const unsigned ipgpio1_c_1_pins[] = { DB8540_PIN_AF7 };
-static const unsigned ipgpio3_c_1_pins[] = { DB8540_PIN_AE4 };
-static const unsigned ipgpio2_c_1_pins[] = { DB8540_PIN_AD1 };
-static const unsigned u0_c_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AF3,
-	DB8540_PIN_AF5, DB8540_PIN_AG4 };
-static const unsigned smcleale_c_1_pins[] = { DB8540_PIN_AJ24,
-	DB8540_PIN_AE21 };
-static const unsigned ipgpio4_c_1_pins[] = { DB8540_PIN_M26 };
-static const unsigned ipgpio5_c_1_pins[] = { DB8540_PIN_M25 };
-static const unsigned ipgpio6_c_2_pins[] = { DB8540_PIN_M27 };
-static const unsigned ipgpio7_c_1_pins[] = { DB8540_PIN_N25 };
-static const unsigned stmape_c_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
-	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 };
-static const unsigned u2rxtx_c_1_pins[] = { DB8540_PIN_N28, DB8540_PIN_P22 };
-static const unsigned modobsresout_c_1_pins[] = { DB8540_PIN_P28 };
-static const unsigned ipgpio2_c_2_pins[] = { DB8540_PIN_P26 };
-static const unsigned ipgpio3_c_2_pins[] = { DB8540_PIN_T22 };
-static const unsigned ipgpio4_c_2_pins[] = { DB8540_PIN_R27 };
-static const unsigned ipgpio5_c_2_pins[] = { DB8540_PIN_P27 };
-static const unsigned modaccgpo_c_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25,
-	DB8540_PIN_U22 };
-static const unsigned modobspwrrst_c_1_pins[] = { DB8540_PIN_T27 };
-static const unsigned mc5_c_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
-	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
-	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22,
-	DB8540_PIN_AJ21};
-static const unsigned smps0_c_1_pins[] = { DB8540_PIN_AG19 };
-static const unsigned moduart1_c_1_pins[] = { DB8540_PIN_T25, DB8540_PIN_T26 };
-static const unsigned mc2rstn_c_1_pins[] = { DB8540_PIN_AE28 };
-static const unsigned i2c5_c_1_pins[] = { DB8540_PIN_AG28, DB8540_PIN_AF28 };
-static const unsigned ipgpio0_c_2_pins[] = { DB8540_PIN_AG25 };
-static const unsigned ipgpio1_c_2_pins[] = { DB8540_PIN_AG24 };
-static const unsigned kp_c_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25,
-	DB8540_PIN_AF26, DB8540_PIN_AF23 };
-static const unsigned modrf_c_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25,
-	DB8540_PIN_AH24 };
-static const unsigned smps1_c_1_pins[] = { DB8540_PIN_AE26 };
-static const unsigned i2c5_c_2_pins[] = { DB8540_PIN_AH19, DB8540_PIN_AE19 };
-static const unsigned u4ctsrts_c_1_pins[] = { DB8540_PIN_AG18,
-	DB8540_PIN_AH17 };
-static const unsigned u3rxtx_c_1_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 };
-static const unsigned msp4_c_1_pins[] = { DB8540_PIN_J3 };
-static const unsigned mc4rstn_c_1_pins[] = { DB8540_PIN_C6 };
-static const unsigned spi0_c_1_pins[] = { DB8540_PIN_A10, DB8540_PIN_B10,
-	DB8540_PIN_E10, DB8540_PIN_B12 };
-static const unsigned i2c3_c_1_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 };
-
-/* Other alt C1 column */
-static const unsigned spi3_oc1_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5,
-	DB8540_PIN_AE4, DB8540_PIN_AD1 };
-static const unsigned stmape_oc1_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11,
-	DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
-static const unsigned u2_oc1_1_pins[] = { DB8540_PIN_AG11 };
-static const unsigned remap0_oc1_1_pins[] = { DB8540_PIN_AJ24 };
-static const unsigned remap1_oc1_1_pins[] = { DB8540_PIN_AE21 };
-static const unsigned modobsrefclk_oc1_1_pins[] = { DB8540_PIN_M26 };
-static const unsigned modobspwrctrl_oc1_1_pins[] = { DB8540_PIN_M25 };
-static const unsigned modobsclkout_oc1_1_pins[] = { DB8540_PIN_M27 };
-static const unsigned moduart1_oc1_1_pins[] = { DB8540_PIN_N25 };
-static const unsigned modprcmudbg_oc1_1_pins[] = { DB8540_PIN_M28,
-	DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27,
-	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
-	DB8540_PIN_R26, DB8540_PIN_R25, DB8540_PIN_U22, DB8540_PIN_T27,
-	DB8540_PIN_AH20, DB8540_PIN_AG19, DB8540_PIN_AF22, DB8540_PIN_AJ21,
-	DB8540_PIN_T25};
-static const unsigned modobsresout_oc1_1_pins[] = { DB8540_PIN_N28 };
-static const unsigned modaccgpo_oc1_1_pins[] = { DB8540_PIN_R27, DB8540_PIN_P27,
-	DB8540_PIN_T26 };
-static const unsigned kp_oc1_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21,
-	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
-	DB8540_PIN_AG20, DB8540_PIN_AE23 };
-static const unsigned modxmip_oc1_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25,
-	DB8540_PIN_AG23, DB8540_PIN_AE25 };
-static const unsigned i2c6_oc1_1_pins[] = { DB8540_PIN_AE26, DB8540_PIN_AE24 };
-static const unsigned u2txrx_oc1_1_pins[] = { DB8540_PIN_B7, DB8540_PIN_A7 };
-static const unsigned u2ctsrts_oc1_1_pins[] = { DB8540_PIN_D7, DB8540_PIN_D8 };
-
-/* Other alt C2 column */
-static const unsigned sbag_oc2_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11,
-	DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 };
-static const unsigned hxclk_oc2_1_pins[] = { DB8540_PIN_M25 };
-static const unsigned modaccuart_oc2_1_pins[] = { DB8540_PIN_N25 };
-static const unsigned stmmod_oc2_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26,
-	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 };
-static const unsigned moduartstmmux_oc2_1_pins[] = { DB8540_PIN_N28 };
-static const unsigned hxgpio_oc2_1_pins[] = { DB8540_PIN_P22, DB8540_PIN_P28,
-	DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27,
-	DB8540_PIN_R26, DB8540_PIN_R25 };
-static const unsigned sbag_oc2_2_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27,
-	DB8540_PIN_AG22, DB8540_PIN_AF21, DB8540_PIN_AF24, DB8540_PIN_AH22 };
-static const unsigned modobsservice_oc2_1_pins[] = { DB8540_PIN_AJ23 };
-static const unsigned moduart0_oc2_1_pins[] = { DB8540_PIN_AG20,
-	DB8540_PIN_AE23 };
-static const unsigned stmape_oc2_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
-	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 };
-static const unsigned u2_oc2_1_pins[] = { DB8540_PIN_T26, DB8540_PIN_AH21 };
-static const unsigned modxmip_oc2_1_pins[] = { DB8540_PIN_AE26,
-	DB8540_PIN_AE24 };
-
-/* Other alt C3 column */
-static const unsigned modaccgpo_oc3_1_pins[] = { DB8540_PIN_AG11 };
-static const unsigned tpui_oc3_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
-	DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26,
-	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
-	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
-	DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25,
-	DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21,
-	DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21,
-	DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AG19,
-	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 };
-
-/* Other alt C4 column */
-static const unsigned hwobs_oc4_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25,
-	DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26,
-	DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28,
-	DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22,
-	DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25 };
-static const unsigned moduart1txrx_oc4_1_pins[] = { DB8540_PIN_U22,
-	DB8540_PIN_T27 };
-static const unsigned moduart1rtscts_oc4_1_pins[] = { DB8540_PIN_AG22,
-	DB8540_PIN_AF21 };
-static const unsigned modaccuarttxrx_oc4_1_pins[] = { DB8540_PIN_AF24,
-	DB8540_PIN_AH22 };
-static const unsigned modaccuartrtscts_oc4_1_pins[] = { DB8540_PIN_AJ23,
-	DB8540_PIN_AH21 };
-static const unsigned stmmod_oc4_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19,
-	DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 };
-static const unsigned moduartstmmux_oc4_1_pins[] = { DB8540_PIN_T26 };
-
-#define DB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct nmk_pingroup nmk_db8540_groups[] = {
-	/* Altfunction A column */
-	DB8540_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(modobsclk_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkoutreq_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(modi2s_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(spi2_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(u2txrx_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(u2ctsrts_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(modsmb_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp2txdtcktfs_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp2rxd_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
-	/* Altfunction B column */
-	DB8540_PIN_GROUP(apetrig_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(modtrig_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(moduartstmmux_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u2txrx_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c6_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c5_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u3txrx_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u3ctsrts_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c5_b_2, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(i2c4_b_2, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u4txrx_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u4ctsrts_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(msp4_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B),
-	DB8540_PIN_GROUP(u2txrx_b_2, NMK_GPIO_ALT_B),
-	/* Altfunction C column */
-	DB8540_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio6_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(modobsresout_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(modaccgpo_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(modobspwrrst_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(moduart1_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(i2c5_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio0_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(ipgpio1_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(modrf_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(i2c5_c_2, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(u4ctsrts_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(u3rxtx_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(msp4_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
-	DB8540_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
-
-	/* Other alt C1 column */
-	DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C1),
-	DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C1),
-
-	/* Other alt C2 column */
-	DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C2),
-	DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C2),
-
-	/* Other alt C3 column */
-	DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C3),
-	DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C3),
-
-	/* Other alt C4 column */
-	DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
-	DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4),
-
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define DB8540_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1");
-DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2",
-		"clkout2_a_1", "clkout2_a_2");
-DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
-DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
-DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
-DB8540_FUNC_GROUPS(hx, "hxclk_oc2_1", "hxgpio_oc2_1");
-DB8540_FUNC_GROUPS(i2c0, "i2c0_a_1");
-DB8540_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2");
-DB8540_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
-DB8540_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c4_b_1");
-DB8540_FUNC_GROUPS(i2c4, "i2c4_b_2");
-DB8540_FUNC_GROUPS(i2c5, "i2c5_b_1", "i2c5_b_2", "i2c5_c_1", "i2c5_c_2");
-DB8540_FUNC_GROUPS(i2c6, "i2c6_b_1", "i2c6_oc1_1");
-/* The image processor has 8 GPIO pins that can be muxed out */
-DB8540_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio0_c_1", "ipgpio0_c_2",
-		"ipgpio1_a_1", "ipgpio1_c_1", "ipgpio1_c_2",
-		"ipgpio2_b_1", "ipgpio2_c_1", "ipgpio2_c_2",
-		"ipgpio3_b_1", "ipgpio3_c_1", "ipgpio3_c_2",
-		"ipgpio4_c_1", "ipgpio4_c_2",
-		"ipgpio5_c_1", "ipgpio5_c_2",
-		"ipgpio6_c_1", "ipgpio6_c_2",
-		"ipgpio7_b_1", "ipgpio7_c_1");
-DB8540_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
-DB8540_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1");
-DB8540_FUNC_GROUPS(lcd, "lcd_d0_d7_a_1", "lcd_d12_d23_a_1", "lcd_d8_d11_a_1",
-		"lcdvsi0_a_1", "lcdvsi1_a_1");
-DB8540_FUNC_GROUPS(lcdb, "lcdb_a_1");
-DB8540_FUNC_GROUPS(mc0, "mc0_a_1");
-DB8540_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2");
-DB8540_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
-DB8540_FUNC_GROUPS(mc3, "mc3_b_1");
-DB8540_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
-DB8540_FUNC_GROUPS(mc5, "mc5_c_1");
-DB8540_FUNC_GROUPS(modaccgpo, "modaccgpo_c_1", "modaccgpo_oc1_1",
-		"modaccgpo_oc3_1");
-DB8540_FUNC_GROUPS(modaccuart, "modaccuart_oc2_1", "modaccuarttxrx_oc4_1",
-		"modaccuartrtccts_oc4_1");
-DB8540_FUNC_GROUPS(modi2s, "modi2s_a_1");
-DB8540_FUNC_GROUPS(modobs, "modobsclk_a_1", "modobsclkout_oc1_1",
-		"modobspwrctrl_oc1_1", "modobspwrrst_c_1",
-		"modobsrefclk_oc1_1", "modobsresout_c_1",
-		"modobsresout_oc1_1", "modobsservice_oc2_1");
-DB8540_FUNC_GROUPS(modprcmudbg, "modprcmudbg_oc1_1");
-DB8540_FUNC_GROUPS(modrf, "modrf_c_1");
-DB8540_FUNC_GROUPS(modsmb, "modsmb_a_1");
-DB8540_FUNC_GROUPS(modtrig, "modtrig_b_1");
-DB8540_FUNC_GROUPS(moduart, "moduart1_c_1", "moduart1_oc1_1",
-		"moduart1txrx_oc4_1", "moduart1rtscts_oc4_1", "moduart0_oc2_1");
-DB8540_FUNC_GROUPS(moduartstmmux, "moduartstmmux_b_1", "moduartstmmux_oc2_1",
-		"moduartstmmux_oc4_1");
-DB8540_FUNC_GROUPS(modxmip, "modxmip_oc1_1", "modxmip_oc2_1");
-/*
- * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
- * switched around by selecting the altfunction A or B.
- */
-DB8540_FUNC_GROUPS(msp0, "msp0rfsrck_a_1", "msp0tfstck_a_1", "msp0txrx_a_1",
-		"msp0txrx_b_1");
-DB8540_FUNC_GROUPS(msp1, "msp1_a_1", "msp1txrx_a_1", "msp1txrx_b_1");
-DB8540_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2txdtcktfs_a_1", "msp2rxd_a_1");
-DB8540_FUNC_GROUPS(msp4, "msp4_a_1", "msp4_b_1", "msp4_c_1");
-DB8540_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4");
-DB8540_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
-DB8540_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc2_2");
-/* Select between CS0 on alt B or PS1 on alt C */
-DB8540_FUNC_GROUPS(sm, "sm_b_1", "smcleale_c_1", "smcs0_b_1", "smcs1_b_1",
-		"smps0_c_1", "smps1_c_1");
-DB8540_FUNC_GROUPS(spi0, "spi0_c_1");
-DB8540_FUNC_GROUPS(spi1, "spi1_b_1");
-DB8540_FUNC_GROUPS(spi2, "spi2_a_1");
-DB8540_FUNC_GROUPS(spi3, "spi3_oc1_1");
-DB8540_FUNC_GROUPS(ssp0, "ssp0_a_1");
-DB8540_FUNC_GROUPS(ssp1, "ssp1_a_1");
-DB8540_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_oc1_1", "stmape_oc2_1");
-DB8540_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_oc2_1", "stmmod_oc4_1");
-DB8540_FUNC_GROUPS(tpui, "tpui_oc3_1");
-DB8540_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1");
-DB8540_FUNC_GROUPS(u1, "u1ctsrts_a_1", "u1rxtx_a_1");
-DB8540_FUNC_GROUPS(u2, "u2_oc1_1", "u2_oc2_1", "u2ctsrts_a_1", "u2ctsrts_oc1_1",
-		"u2rxtx_c_1", "u2txrx_a_1", "u2txrx_b_1", "u2txrx_b_2",
-		"u2txrx_oc1_1");
-DB8540_FUNC_GROUPS(u3, "u3ctsrts_b_1", "u3rxtx_c_1", "u3txrxa_b_1");
-DB8540_FUNC_GROUPS(u4, "u4ctsrts_b_1", "u4ctsrts_c_1", "u4txrx_b_1");
-DB8540_FUNC_GROUPS(usb, "usb_a_1");
-
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct nmk_function nmk_db8540_functions[] = {
-	FUNCTION(apetrig),
-	FUNCTION(clkout),
-	FUNCTION(ddrtrig),
-	FUNCTION(hsi),
-	FUNCTION(hwobs),
-	FUNCTION(hx),
-	FUNCTION(i2c0),
-	FUNCTION(i2c1),
-	FUNCTION(i2c2),
-	FUNCTION(i2c3),
-	FUNCTION(i2c4),
-	FUNCTION(i2c5),
-	FUNCTION(i2c6),
-	FUNCTION(ipgpio),
-	FUNCTION(ipi2c),
-	FUNCTION(kp),
-	FUNCTION(lcd),
-	FUNCTION(lcdb),
-	FUNCTION(mc0),
-	FUNCTION(mc1),
-	FUNCTION(mc2),
-	FUNCTION(mc3),
-	FUNCTION(mc4),
-	FUNCTION(mc5),
-	FUNCTION(modaccgpo),
-	FUNCTION(modaccuart),
-	FUNCTION(modi2s),
-	FUNCTION(modobs),
-	FUNCTION(modprcmudbg),
-	FUNCTION(modrf),
-	FUNCTION(modsmb),
-	FUNCTION(modtrig),
-	FUNCTION(moduart),
-	FUNCTION(modxmip),
-	FUNCTION(msp0),
-	FUNCTION(msp1),
-	FUNCTION(msp2),
-	FUNCTION(msp4),
-	FUNCTION(pwl),
-	FUNCTION(remap),
-	FUNCTION(sbag),
-	FUNCTION(sm),
-	FUNCTION(spi0),
-	FUNCTION(spi1),
-	FUNCTION(spi2),
-	FUNCTION(spi3),
-	FUNCTION(ssp0),
-	FUNCTION(ssp1),
-	FUNCTION(stmape),
-	FUNCTION(stmmod),
-	FUNCTION(tpui),
-	FUNCTION(u0),
-	FUNCTION(u1),
-	FUNCTION(u2),
-	FUNCTION(u3),
-	FUNCTION(u4),
-	FUNCTION(usb)
-};
-
-static const struct prcm_gpiocr_altcx_pin_desc db8540_altcx_pins[] = {
-	PRCM_GPIOCR_ALTCX(8,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_CLK */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(9,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_RXD */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(10,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_FRM */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(11,	true, PRCM_IDX_GPIOCR1, 20,	/* SPI3_TXD */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(23,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_CLK_a */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_CLK_a */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(24,	true, PRCM_IDX_GPIOCR3, 30,	/* U2_RXD_g */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_VAL_a */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(25,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[0] */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[0] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(26,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[1] */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[1] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(27,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[2] */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[2] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(28,	true, PRCM_IDX_GPIOCR1, 9,	/* STMAPE_DAT_a[3] */
-				true, PRCM_IDX_GPIOCR2, 10,	/* SBAG_D_a[3] */
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(64,	true, PRCM_IDX_GPIOCR1, 15,	/* MODOBS_REFCLK_REQ */
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_CTL */
-				true, PRCM_IDX_GPIOCR2, 23	/* HW_OBS_APE_PRCMU[17] */
-	),
-	PRCM_GPIOCR_ALTCX(65,	true, PRCM_IDX_GPIOCR1, 19,	/* MODOBS_PWRCTRL0 */
-				true, PRCM_IDX_GPIOCR1, 24,	/* Hx_CLK */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_CLK */
-				true, PRCM_IDX_GPIOCR2, 24	/* HW_OBS_APE_PRCMU[16] */
-	),
-	PRCM_GPIOCR_ALTCX(66,	true, PRCM_IDX_GPIOCR1, 15,	/* MODOBS_CLKOUT1 */
-				false, 0, 0,
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[15] */
-				true, PRCM_IDX_GPIOCR2, 25	/* HW_OBS_APE_PRCMU[15] */
-	),
-	PRCM_GPIOCR_ALTCX(67,	true, PRCM_IDX_GPIOCR1, 1,	/* MODUART1_TXD_a */
-				true, PRCM_IDX_GPIOCR1, 6,	/* MODACCUART_TXD_a */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[14] */
-				true, PRCM_IDX_GPIOCR2, 26	/* HW_OBS_APE_PRCMU[14] */
-	),
-	PRCM_GPIOCR_ALTCX(70,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[17] */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_CLK_b */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[13] */
-				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[13] */
-	),
-	PRCM_GPIOCR_ALTCX(71,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[16] */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[3] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[12] */
-				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[12] */
-	),
-	PRCM_GPIOCR_ALTCX(72,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[15] */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[2] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[11] */
-				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[11] */
-	),
-	PRCM_GPIOCR_ALTCX(73,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[14] */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[1] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[10] */
-				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[10] */
-	),
-	PRCM_GPIOCR_ALTCX(74,	true, PRCM_IDX_GPIOCR3, 6,	/* MOD_PRCMU_DEBUG[13] */
-				true, PRCM_IDX_GPIOCR1, 10,	/* STMMOD_DAT_b[0] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[9] */
-				true, PRCM_IDX_GPIOCR2, 27	/* HW_OBS_APE_PRCMU[9] */
-	),
-	PRCM_GPIOCR_ALTCX(75,	true, PRCM_IDX_GPIOCR1, 12,	/* MODOBS_RESOUT0_N */
-				true, PRCM_IDX_GPIOCR2, 1,	/* MODUART_STMMUX_RXD_b */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[8] */
-				true, PRCM_IDX_GPIOCR2, 28	/* HW_OBS_APE_PRCMU[8] */
-	),
-	PRCM_GPIOCR_ALTCX(76,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[12] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[7] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[7] */
-				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[7] */
-	),
-	PRCM_GPIOCR_ALTCX(77,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[11] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[6] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[6] */
-				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[6] */
-	),
-	PRCM_GPIOCR_ALTCX(78,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[10] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[5] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[5] */
-				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[5] */
-	),
-	PRCM_GPIOCR_ALTCX(79,	true, PRCM_IDX_GPIOCR3, 7,	/* MOD_PRCMU_DEBUG[9] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[4] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[4] */
-				true, PRCM_IDX_GPIOCR2, 29	/* HW_OBS_APE_PRCMU[4] */
-	),
-	PRCM_GPIOCR_ALTCX(80,	true, PRCM_IDX_GPIOCR1, 26,	/* MODACC_GPO[0] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[3] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[3] */
-				true, PRCM_IDX_GPIOCR2, 30	/* HW_OBS_APE_PRCMU[3] */
-	),
-	PRCM_GPIOCR_ALTCX(81,	true, PRCM_IDX_GPIOCR2, 17,	/* MODACC_GPO[1] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[2] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[2] */
-				true, PRCM_IDX_GPIOCR2, 30	/* HW_OBS_APE_PRCMU[2] */
-	),
-	PRCM_GPIOCR_ALTCX(82,	true, PRCM_IDX_GPIOCR3, 8,	/* MOD_PRCMU_DEBUG[8] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[1] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[1] */
-				true, PRCM_IDX_GPIOCR2, 31	/* HW_OBS_APE_PRCMU[1] */
-	),
-	PRCM_GPIOCR_ALTCX(83,	true, PRCM_IDX_GPIOCR3, 8,	/* MOD_PRCMU_DEBUG[7] */
-				true, PRCM_IDX_GPIOCR1, 25,	/* Hx_GPIO[0] */
-				true, PRCM_IDX_GPIOCR1, 2,	/* TPIU_D[0] */
-				true, PRCM_IDX_GPIOCR2, 31	/* HW_OBS_APE_PRCMU[0] */
-	),
-	PRCM_GPIOCR_ALTCX(84,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[6] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_CLK_b */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[23] */
-				true, PRCM_IDX_GPIOCR1, 16	/* MODUART1_RXD_b */
-	),
-	PRCM_GPIOCR_ALTCX(85,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[5] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[3] */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[22] */
-				true, PRCM_IDX_GPIOCR1, 16	/* MODUART1_TXD_b */
-	),
-	PRCM_GPIOCR_ALTCX(86,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[0] */
-				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[0] */
-				true, PRCM_IDX_GPIOCR1, 14,	/* TPIU_D[25] */
-				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[0] */
-	),
-	PRCM_GPIOCR_ALTCX(87,	true, PRCM_IDX_GPIOCR3, 0,	/* MODACC_GPO_a[5] */
-				true, PRCM_IDX_GPIOCR2, 3,	/* U2_RXD_c */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[24] */
-				true, PRCM_IDX_GPIOCR1, 21	/* MODUART_STMMUX_RXD_c */
-	),
-	PRCM_GPIOCR_ALTCX(151,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP0 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(152,	true, PRCM_IDX_GPIOCR1, 18,	/* REMAP1 */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(153,	true, PRCM_IDX_GPIOCR3, 2,	/* KP_O_b[6] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[2] */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[21] */
-				true, PRCM_IDX_GPIOCR1, 0	/* MODUART1_RTS */
-	),
-	PRCM_GPIOCR_ALTCX(154,	true, PRCM_IDX_GPIOCR3, 2,	/* KP_I_b[6] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[1] */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[20] */
-				true, PRCM_IDX_GPIOCR1, 0	/* MODUART1_CTS */
-	),
-	PRCM_GPIOCR_ALTCX(155,	true, PRCM_IDX_GPIOCR3, 3,	/* KP_O_b[5] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_D_b[0] */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[19] */
-				true, PRCM_IDX_GPIOCR1, 5	/* MODACCUART_RXD_c */
-	),
-	PRCM_GPIOCR_ALTCX(156,	true, PRCM_IDX_GPIOCR3, 3,	/* KP_O_b[4] */
-				true, PRCM_IDX_GPIOCR1, 8,	/* SBAG_VAL_b */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[18] */
-				true, PRCM_IDX_GPIOCR1, 5	/* MODACCUART_TXD_b */
-	),
-	PRCM_GPIOCR_ALTCX(157,	true, PRCM_IDX_GPIOCR3, 4,	/* KP_I_b[5] */
-				true, PRCM_IDX_GPIOCR1, 23,	/* MODOBS_SERVICE_N */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[17] */
-				true, PRCM_IDX_GPIOCR1, 14	/* MODACCUART_RTS */
-	),
-	PRCM_GPIOCR_ALTCX(158,	true, PRCM_IDX_GPIOCR3, 4,	/* KP_I_b[4] */
-				true, PRCM_IDX_GPIOCR2, 0,	/* U2_TXD_c */
-				true, PRCM_IDX_GPIOCR1, 3,	/* TPIU_D[16] */
-				true, PRCM_IDX_GPIOCR1, 14	/* MODACCUART_CTS */
-	),
-	PRCM_GPIOCR_ALTCX(159,	true, PRCM_IDX_GPIOCR3, 5,	/* KP_O_b[3] */
-				true, PRCM_IDX_GPIOCR3, 10,	/* MODUART0_RXD */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[31] */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(160,	true, PRCM_IDX_GPIOCR3, 5,	/* KP_I_b[3] */
-				true, PRCM_IDX_GPIOCR3, 10,	/* MODUART0_TXD */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[30] */
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(161,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[4] */
-				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_CLK_b */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[29] */
-				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_CLK_c */
-	),
-	PRCM_GPIOCR_ALTCX(162,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[3] */
-				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[3] */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[28] */
-				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[3] */
-	),
-	PRCM_GPIOCR_ALTCX(163,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[2] */
-				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[2] */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[27] */
-				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[2] */
-	),
-	PRCM_GPIOCR_ALTCX(164,	true, PRCM_IDX_GPIOCR3, 9,	/* MOD_PRCMU_DEBUG[1] */
-				true, PRCM_IDX_GPIOCR2, 18,	/* STMAPE_DAT_b[1] */
-				true, PRCM_IDX_GPIOCR1, 4,	/* TPIU_D[26] */
-				true, PRCM_IDX_GPIOCR1, 11	/* STMMOD_DAT_c[1] */
-	),
-	PRCM_GPIOCR_ALTCX(204,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_RXD_f */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(205,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_TXD_f */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(206,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_CTSn_b */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-	PRCM_GPIOCR_ALTCX(207,	true, PRCM_IDX_GPIOCR2, 2,	/* U2_RTSn_b */
-				false, 0, 0,
-				false, 0, 0,
-				false, 0, 0
-	),
-};
-
-static const u16 db8540_prcm_gpiocr_regs[] = {
-	[PRCM_IDX_GPIOCR1] = 0x138,
-	[PRCM_IDX_GPIOCR2] = 0x574,
-	[PRCM_IDX_GPIOCR3] = 0x2bc,
-};
-
-static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
-	.gpio_ranges = nmk_db8540_ranges,
-	.gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
-	.pins = nmk_db8540_pins,
-	.npins = ARRAY_SIZE(nmk_db8540_pins),
-	.functions = nmk_db8540_functions,
-	.nfunctions = ARRAY_SIZE(nmk_db8540_functions),
-	.groups = nmk_db8540_groups,
-	.ngroups = ARRAY_SIZE(nmk_db8540_groups),
-	.altcx_pins = db8540_altcx_pins,
-	.npins_altcx = ARRAY_SIZE(db8540_altcx_pins),
-	.prcm_gpiocr_registers = db8540_prcm_gpiocr_regs,
-};
-
-void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
-{
-	*soc = &nmk_db8540_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik.h
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-#ifndef PINCTRL_PINCTRL_NOMADIK_H
-#define PINCTRL_PINCTRL_NOMADIK_H
-
-/* Package definitions */
-#define PINCTRL_NMK_STN8815	0
-#define PINCTRL_NMK_DB8500	1
-#define PINCTRL_NMK_DB8540	2
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO	0
-#define NMK_GPIO_ALT_A	1
-#define NMK_GPIO_ALT_B	2
-#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-#define PRCM_GPIOCR_ALTCX(pin_num,\
-	altc1_used, altc1_ri, altc1_cb,\
-	altc2_used, altc2_ri, altc2_cb,\
-	altc3_used, altc3_ri, altc3_cb,\
-	altc4_used, altc4_ri, altc4_cb)\
-{\
-	.pin = pin_num,\
-	.altcx[PRCM_IDX_GPIOCR_ALTC1] = {\
-		.used = altc1_used,\
-		.reg_index = altc1_ri,\
-		.control_bit = altc1_cb\
-	},\
-	.altcx[PRCM_IDX_GPIOCR_ALTC2] = {\
-		.used = altc2_used,\
-		.reg_index = altc2_ri,\
-		.control_bit = altc2_cb\
-	},\
-	.altcx[PRCM_IDX_GPIOCR_ALTC3] = {\
-		.used = altc3_used,\
-		.reg_index = altc3_ri,\
-		.control_bit = altc3_cb\
-	},\
-	.altcx[PRCM_IDX_GPIOCR_ALTC4] = {\
-		.used = altc4_used,\
-		.reg_index = altc4_ri,\
-		.control_bit = altc4_cb\
-	},\
-}
-
-/**
- * enum prcm_gpiocr_reg_index
- * Used to reference an PRCM GPIOCR register address.
- */
-enum prcm_gpiocr_reg_index {
-	PRCM_IDX_GPIOCR1,
-	PRCM_IDX_GPIOCR2,
-	PRCM_IDX_GPIOCR3
-};
-/**
- * enum prcm_gpiocr_altcx_index
- * Used to reference an Other alternate-C function.
- */
-enum prcm_gpiocr_altcx_index {
-	PRCM_IDX_GPIOCR_ALTC1,
-	PRCM_IDX_GPIOCR_ALTC2,
-	PRCM_IDX_GPIOCR_ALTC3,
-	PRCM_IDX_GPIOCR_ALTC4,
-	PRCM_IDX_GPIOCR_ALTC_MAX,
-};
-
-/**
- * struct prcm_gpio_altcx - Other alternate-C function
- * @used: other alternate-C function availability
- * @reg_index: PRCM GPIOCR register index used to control the function
- * @control_bit: PRCM GPIOCR bit used to control the function
- */
-struct prcm_gpiocr_altcx {
-	bool used:1;
-	u8 reg_index:2;
-	u8 control_bit:5;
-} __packed;
-
-/**
- * struct prcm_gpio_altcx_pin_desc - Other alternate-C pin
- * @pin: The pin number
- * @altcx: array of other alternate-C[1-4] functions
- */
-struct prcm_gpiocr_altcx_pin_desc {
-	unsigned short pin;
-	struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX];
-};
-
-/**
- * struct nmk_function - Nomadik pinctrl mux function
- * @name: The name of the function, exported to pinctrl core.
- * @groups: An array of pin groups that may select this function.
- * @ngroups: The number of entries in @groups.
- */
-struct nmk_function {
-	const char *name;
-	const char * const *groups;
-	unsigned ngroups;
-};
-
-/**
- * struct nmk_pingroup - describes a Nomadik pin group
- * @name: the name of this specific pin group
- * @pins: an array of discrete physical pins used in this group, taken
- *	from the driver-local pin enumeration space
- * @num_pins: the number of pins in this group array, i.e. the number of
- *	elements in .pins so we can iterate over that array
- * @altsetting: the altsetting to apply to all pins in this group to
- *	configure them to be used by a function
- */
-struct nmk_pingroup {
-	const char *name;
-	const unsigned int *pins;
-	const unsigned npins;
-	int altsetting;
-};
-
-/**
- * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration
- * @gpio_ranges: An array of GPIO ranges for this SoC
- * @gpio_num_ranges: The number of GPIO ranges for this SoC
- * @pins:	An array describing all pins the pin controller affects.
- *		All pins which are also GPIOs must be listed first within the
- *		array, and be numbered identically to the GPIO controller's
- *		numbering.
- * @npins:	The number of entries in @pins.
- * @functions:	The functions supported on this SoC.
- * @nfunction:	The number of entries in @functions.
- * @groups:	An array describing all pin groups the pin SoC supports.
- * @ngroups:	The number of entries in @groups.
- * @altcx_pins:	The pins that support Other alternate-C function on this SoC
- * @npins_altcx: The number of Other alternate-C pins
- * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
- */
-struct nmk_pinctrl_soc_data {
-	struct pinctrl_gpio_range *gpio_ranges;
-	unsigned gpio_num_ranges;
-	const struct pinctrl_pin_desc *pins;
-	unsigned npins;
-	const struct nmk_function *functions;
-	unsigned nfunctions;
-	const struct nmk_pingroup *groups;
-	unsigned ngroups;
-	const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
-	unsigned npins_altcx;
-	const u16 *prcm_gpiocr_registers;
-};
-
-#ifdef CONFIG_PINCTRL_STN8815
-
-void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#ifdef CONFIG_PINCTRL_DB8500
-
-void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#ifdef CONFIG_PINCTRL_DB8540
-
-void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc);
-
-#else
-
-static inline void
-nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
-{
-}
-
-#endif
-
-#endif /* PINCTRL_PINCTRL_NOMADIK_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-stn8815.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-stn8815.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-nomadik-stn8815.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-nomadik-stn8815.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,356 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pinctrl/pinctrl.h>
-#include "pinctrl-nomadik.h"
-
-/* All the pins that can be used for GPIO and some other functions */
-#define _GPIO(offset)		(offset)
-
-#define STN8815_PIN_B4		_GPIO(0)
-#define STN8815_PIN_D5		_GPIO(1)
-#define STN8815_PIN_C5		_GPIO(2)
-#define STN8815_PIN_A4		_GPIO(3)
-#define STN8815_PIN_B5		_GPIO(4)
-#define STN8815_PIN_D6		_GPIO(5)
-#define STN8815_PIN_C6		_GPIO(6)
-#define STN8815_PIN_B6		_GPIO(7)
-#define STN8815_PIN_B10		_GPIO(8)
-#define STN8815_PIN_A10		_GPIO(9)
-#define STN8815_PIN_C11		_GPIO(10)
-#define STN8815_PIN_B11		_GPIO(11)
-#define STN8815_PIN_A11		_GPIO(12)
-#define STN8815_PIN_C12		_GPIO(13)
-#define STN8815_PIN_B12		_GPIO(14)
-#define STN8815_PIN_A12		_GPIO(15)
-#define STN8815_PIN_C13		_GPIO(16)
-#define STN8815_PIN_B13		_GPIO(17)
-#define STN8815_PIN_A13		_GPIO(18)
-#define STN8815_PIN_D13		_GPIO(19)
-#define STN8815_PIN_C14		_GPIO(20)
-#define STN8815_PIN_B14		_GPIO(21)
-#define STN8815_PIN_A14		_GPIO(22)
-#define STN8815_PIN_D15		_GPIO(23)
-#define STN8815_PIN_C15		_GPIO(24)
-#define STN8815_PIN_B15		_GPIO(25)
-#define STN8815_PIN_A15		_GPIO(26)
-#define STN8815_PIN_C16		_GPIO(27)
-#define STN8815_PIN_B16		_GPIO(28)
-#define STN8815_PIN_A16		_GPIO(29)
-#define STN8815_PIN_D17		_GPIO(30)
-#define STN8815_PIN_C17		_GPIO(31)
-#define STN8815_PIN_AB6		_GPIO(32)
-#define STN8815_PIN_AA6		_GPIO(33)
-#define STN8815_PIN_Y6		_GPIO(34)
-#define STN8815_PIN_Y5		_GPIO(35)
-#define STN8815_PIN_AA5		_GPIO(36)
-#define STN8815_PIN_AB5		_GPIO(37)
-#define STN8815_PIN_AB4		_GPIO(38)
-#define STN8815_PIN_Y4		_GPIO(39)
-#define STN8815_PIN_R1		_GPIO(40)
-#define STN8815_PIN_R2		_GPIO(41)
-#define STN8815_PIN_R3		_GPIO(42)
-#define STN8815_PIN_P1		_GPIO(43)
-#define STN8815_PIN_P2		_GPIO(44)
-#define STN8815_PIN_P3		_GPIO(45)
-#define STN8815_PIN_N1		_GPIO(46)
-#define STN8815_PIN_N2		_GPIO(47)
-#define STN8815_PIN_N3		_GPIO(48)
-#define STN8815_PIN_M1		_GPIO(49)
-#define STN8815_PIN_M3		_GPIO(50)
-#define STN8815_PIN_M2		_GPIO(51)
-#define STN8815_PIN_L1		_GPIO(52)
-#define STN8815_PIN_L4		_GPIO(53)
-#define STN8815_PIN_L3		_GPIO(54)
-#define STN8815_PIN_L2		_GPIO(55)
-#define STN8815_PIN_F3		_GPIO(56)
-#define STN8815_PIN_F2		_GPIO(57)
-#define STN8815_PIN_E1		_GPIO(58)
-#define STN8815_PIN_E3		_GPIO(59)
-#define STN8815_PIN_E2		_GPIO(60)
-#define STN8815_PIN_E4		_GPIO(61)
-#define STN8815_PIN_D3		_GPIO(62)
-#define STN8815_PIN_D2		_GPIO(63)
-#define STN8815_PIN_F21		_GPIO(64)
-#define STN8815_PIN_F20		_GPIO(65)
-#define STN8815_PIN_E22		_GPIO(66)
-#define STN8815_PIN_D22		_GPIO(67)
-#define STN8815_PIN_E21		_GPIO(68)
-#define STN8815_PIN_E20		_GPIO(69)
-#define STN8815_PIN_C22		_GPIO(70)
-#define STN8815_PIN_D21		_GPIO(71)
-#define STN8815_PIN_D20		_GPIO(72)
-#define STN8815_PIN_C21		_GPIO(73)
-#define STN8815_PIN_C20		_GPIO(74)
-#define STN8815_PIN_C19		_GPIO(75)
-#define STN8815_PIN_B20		_GPIO(76)
-#define STN8815_PIN_B8		_GPIO(77)
-#define STN8815_PIN_A8		_GPIO(78)
-#define STN8815_PIN_C9		_GPIO(79)
-#define STN8815_PIN_B9		_GPIO(80)
-#define STN8815_PIN_A9		_GPIO(81)
-#define STN8815_PIN_C10		_GPIO(82)
-#define STN8815_PIN_K1		_GPIO(83)
-#define STN8815_PIN_K3		_GPIO(84)
-#define STN8815_PIN_K2		_GPIO(85)
-#define STN8815_PIN_J1		_GPIO(86)
-#define STN8815_PIN_J3		_GPIO(87)
-#define STN8815_PIN_J2		_GPIO(88)
-#define STN8815_PIN_H1		_GPIO(89)
-#define STN8815_PIN_H3		_GPIO(90)
-#define STN8815_PIN_H2		_GPIO(91)
-#define STN8815_PIN_G1		_GPIO(92)
-#define STN8815_PIN_G3		_GPIO(93)
-#define STN8815_PIN_G2		_GPIO(94)
-#define STN8815_PIN_F1		_GPIO(95)
-#define STN8815_PIN_T20		_GPIO(96)
-#define STN8815_PIN_R21		_GPIO(97)
-#define STN8815_PIN_R20		_GPIO(98)
-#define STN8815_PIN_U22		_GPIO(99)
-#define STN8815_PIN_N21		_GPIO(100)
-#define STN8815_PIN_N20		_GPIO(101)
-#define STN8815_PIN_P22		_GPIO(102)
-#define STN8815_PIN_N22		_GPIO(103)
-#define STN8815_PIN_V22		_GPIO(104)
-#define STN8815_PIN_V21		_GPIO(105)
-#define STN8815_PIN_K22		_GPIO(106)
-#define STN8815_PIN_K21		_GPIO(107)
-#define STN8815_PIN_H20		_GPIO(108)
-#define STN8815_PIN_G20		_GPIO(109)
-#define STN8815_PIN_L21		_GPIO(110)
-#define STN8815_PIN_H21		_GPIO(111)
-#define STN8815_PIN_J21		_GPIO(112)
-#define STN8815_PIN_H22		_GPIO(113)
-#define STN8815_PIN_K20		_GPIO(114)
-#define STN8815_PIN_L22		_GPIO(115)
-#define STN8815_PIN_G21		_GPIO(116)
-#define STN8815_PIN_J20		_GPIO(117)
-#define STN8815_PIN_G22		_GPIO(118)
-#define STN8815_PIN_U19		_GPIO(119)
-#define STN8815_PIN_G19		_GPIO(120)
-#define STN8815_PIN_M22		_GPIO(121)
-#define STN8815_PIN_M19		_GPIO(122)
-#define STN8815_PIN_J22		_GPIO(123)
-/* GPIOs 124-127 not routed to pins */
-
-/*
- * The names of the pins are denoted by GPIO number and ball name, even
- * though they can be used for other things than GPIO, this is the first
- * column in the table of the data sheet and often used on schematics and
- * such.
- */
-static const struct pinctrl_pin_desc nmk_stn8815_pins[] = {
-	PINCTRL_PIN(STN8815_PIN_B4, "GPIO0_B4"),
-	PINCTRL_PIN(STN8815_PIN_D5, "GPIO1_D5"),
-	PINCTRL_PIN(STN8815_PIN_C5, "GPIO2_C5"),
-	PINCTRL_PIN(STN8815_PIN_A4, "GPIO3_A4"),
-	PINCTRL_PIN(STN8815_PIN_B5, "GPIO4_B5"),
-	PINCTRL_PIN(STN8815_PIN_D6, "GPIO5_D6"),
-	PINCTRL_PIN(STN8815_PIN_C6, "GPIO6_C6"),
-	PINCTRL_PIN(STN8815_PIN_B6, "GPIO7_B6"),
-	PINCTRL_PIN(STN8815_PIN_B10, "GPIO8_B10"),
-	PINCTRL_PIN(STN8815_PIN_A10, "GPIO9_A10"),
-	PINCTRL_PIN(STN8815_PIN_C11, "GPIO10_C11"),
-	PINCTRL_PIN(STN8815_PIN_B11, "GPIO11_B11"),
-	PINCTRL_PIN(STN8815_PIN_A11, "GPIO12_A11"),
-	PINCTRL_PIN(STN8815_PIN_C12, "GPIO13_C12"),
-	PINCTRL_PIN(STN8815_PIN_B12, "GPIO14_B12"),
-	PINCTRL_PIN(STN8815_PIN_A12, "GPIO15_A12"),
-	PINCTRL_PIN(STN8815_PIN_C13, "GPIO16_C13"),
-	PINCTRL_PIN(STN8815_PIN_B13, "GPIO17_B13"),
-	PINCTRL_PIN(STN8815_PIN_A13, "GPIO18_A13"),
-	PINCTRL_PIN(STN8815_PIN_D13, "GPIO19_D13"),
-	PINCTRL_PIN(STN8815_PIN_C14, "GPIO20_C14"),
-	PINCTRL_PIN(STN8815_PIN_B14, "GPIO21_B14"),
-	PINCTRL_PIN(STN8815_PIN_A14, "GPIO22_A14"),
-	PINCTRL_PIN(STN8815_PIN_D15, "GPIO23_D15"),
-	PINCTRL_PIN(STN8815_PIN_C15, "GPIO24_C15"),
-	PINCTRL_PIN(STN8815_PIN_B15, "GPIO25_B15"),
-	PINCTRL_PIN(STN8815_PIN_A15, "GPIO26_A15"),
-	PINCTRL_PIN(STN8815_PIN_C16, "GPIO27_C16"),
-	PINCTRL_PIN(STN8815_PIN_B16, "GPIO28_B16"),
-	PINCTRL_PIN(STN8815_PIN_A16, "GPIO29_A16"),
-	PINCTRL_PIN(STN8815_PIN_D17, "GPIO30_D17"),
-	PINCTRL_PIN(STN8815_PIN_C17, "GPIO31_C17"),
-	PINCTRL_PIN(STN8815_PIN_AB6, "GPIO32_AB6"),
-	PINCTRL_PIN(STN8815_PIN_AA6, "GPIO33_AA6"),
-	PINCTRL_PIN(STN8815_PIN_Y6, "GPIO34_Y6"),
-	PINCTRL_PIN(STN8815_PIN_Y5, "GPIO35_Y5"),
-	PINCTRL_PIN(STN8815_PIN_AA5, "GPIO36_AA5"),
-	PINCTRL_PIN(STN8815_PIN_AB5, "GPIO37_AB5"),
-	PINCTRL_PIN(STN8815_PIN_AB4, "GPIO38_AB4"),
-	PINCTRL_PIN(STN8815_PIN_Y4, "GPIO39_Y4"),
-	PINCTRL_PIN(STN8815_PIN_R1, "GPIO40_R1"),
-	PINCTRL_PIN(STN8815_PIN_R2, "GPIO41_R2"),
-	PINCTRL_PIN(STN8815_PIN_R3, "GPIO42_R3"),
-	PINCTRL_PIN(STN8815_PIN_P1, "GPIO43_P1"),
-	PINCTRL_PIN(STN8815_PIN_P2, "GPIO44_P2"),
-	PINCTRL_PIN(STN8815_PIN_P3, "GPIO45_P3"),
-	PINCTRL_PIN(STN8815_PIN_N1, "GPIO46_N1"),
-	PINCTRL_PIN(STN8815_PIN_N2, "GPIO47_N2"),
-	PINCTRL_PIN(STN8815_PIN_N3, "GPIO48_N3"),
-	PINCTRL_PIN(STN8815_PIN_M1, "GPIO49_M1"),
-	PINCTRL_PIN(STN8815_PIN_M3, "GPIO50_M3"),
-	PINCTRL_PIN(STN8815_PIN_M2, "GPIO51_M2"),
-	PINCTRL_PIN(STN8815_PIN_L1, "GPIO52_L1"),
-	PINCTRL_PIN(STN8815_PIN_L4, "GPIO53_L4"),
-	PINCTRL_PIN(STN8815_PIN_L3, "GPIO54_L3"),
-	PINCTRL_PIN(STN8815_PIN_L2, "GPIO55_L2"),
-	PINCTRL_PIN(STN8815_PIN_F3, "GPIO56_F3"),
-	PINCTRL_PIN(STN8815_PIN_F2, "GPIO57_F2"),
-	PINCTRL_PIN(STN8815_PIN_E1, "GPIO58_E1"),
-	PINCTRL_PIN(STN8815_PIN_E3, "GPIO59_E3"),
-	PINCTRL_PIN(STN8815_PIN_E2, "GPIO60_E2"),
-	PINCTRL_PIN(STN8815_PIN_E4, "GPIO61_E4"),
-	PINCTRL_PIN(STN8815_PIN_D3, "GPIO62_D3"),
-	PINCTRL_PIN(STN8815_PIN_D2, "GPIO63_D2"),
-	PINCTRL_PIN(STN8815_PIN_F21, "GPIO64_F21"),
-	PINCTRL_PIN(STN8815_PIN_F20, "GPIO65_F20"),
-	PINCTRL_PIN(STN8815_PIN_E22, "GPIO66_E22"),
-	PINCTRL_PIN(STN8815_PIN_D22, "GPIO67_D22"),
-	PINCTRL_PIN(STN8815_PIN_E21, "GPIO68_E21"),
-	PINCTRL_PIN(STN8815_PIN_E20, "GPIO69_E20"),
-	PINCTRL_PIN(STN8815_PIN_C22, "GPIO70_C22"),
-	PINCTRL_PIN(STN8815_PIN_D21, "GPIO71_D21"),
-	PINCTRL_PIN(STN8815_PIN_D20, "GPIO72_D20"),
-	PINCTRL_PIN(STN8815_PIN_C21, "GPIO73_C21"),
-	PINCTRL_PIN(STN8815_PIN_C20, "GPIO74_C20"),
-	PINCTRL_PIN(STN8815_PIN_C19, "GPIO75_C19"),
-	PINCTRL_PIN(STN8815_PIN_B20, "GPIO76_B20"),
-	PINCTRL_PIN(STN8815_PIN_B8, "GPIO77_B8"),
-	PINCTRL_PIN(STN8815_PIN_A8, "GPIO78_A8"),
-	PINCTRL_PIN(STN8815_PIN_C9, "GPIO79_C9"),
-	PINCTRL_PIN(STN8815_PIN_B9, "GPIO80_B9"),
-	PINCTRL_PIN(STN8815_PIN_A9, "GPIO81_A9"),
-	PINCTRL_PIN(STN8815_PIN_C10, "GPIO82_C10"),
-	PINCTRL_PIN(STN8815_PIN_K1, "GPIO83_K1"),
-	PINCTRL_PIN(STN8815_PIN_K3, "GPIO84_K3"),
-	PINCTRL_PIN(STN8815_PIN_K2, "GPIO85_K2"),
-	PINCTRL_PIN(STN8815_PIN_J1, "GPIO86_J1"),
-	PINCTRL_PIN(STN8815_PIN_J3, "GPIO87_J3"),
-	PINCTRL_PIN(STN8815_PIN_J2, "GPIO88_J2"),
-	PINCTRL_PIN(STN8815_PIN_H1, "GPIO89_H1"),
-	PINCTRL_PIN(STN8815_PIN_H3, "GPIO90_H3"),
-	PINCTRL_PIN(STN8815_PIN_H2, "GPIO91_H2"),
-	PINCTRL_PIN(STN8815_PIN_G1, "GPIO92_G1"),
-	PINCTRL_PIN(STN8815_PIN_G3, "GPIO93_G3"),
-	PINCTRL_PIN(STN8815_PIN_G2, "GPIO94_G2"),
-	PINCTRL_PIN(STN8815_PIN_F1, "GPIO95_F1"),
-	PINCTRL_PIN(STN8815_PIN_T20, "GPIO96_T20"),
-	PINCTRL_PIN(STN8815_PIN_R21, "GPIO97_R21"),
-	PINCTRL_PIN(STN8815_PIN_R20, "GPIO98_R20"),
-	PINCTRL_PIN(STN8815_PIN_U22, "GPIO99_U22"),
-	PINCTRL_PIN(STN8815_PIN_N21, "GPIO100_N21"),
-	PINCTRL_PIN(STN8815_PIN_N20, "GPIO101_N20"),
-	PINCTRL_PIN(STN8815_PIN_P22, "GPIO102_P22"),
-	PINCTRL_PIN(STN8815_PIN_N22, "GPIO103_N22"),
-	PINCTRL_PIN(STN8815_PIN_V22, "GPIO104_V22"),
-	PINCTRL_PIN(STN8815_PIN_V21, "GPIO105_V21"),
-	PINCTRL_PIN(STN8815_PIN_K22, "GPIO106_K22"),
-	PINCTRL_PIN(STN8815_PIN_K21, "GPIO107_K21"),
-	PINCTRL_PIN(STN8815_PIN_H20, "GPIO108_H20"),
-	PINCTRL_PIN(STN8815_PIN_G20, "GPIO109_G20"),
-	PINCTRL_PIN(STN8815_PIN_L21, "GPIO110_L21"),
-	PINCTRL_PIN(STN8815_PIN_H21, "GPIO111_H21"),
-	PINCTRL_PIN(STN8815_PIN_J21, "GPIO112_J21"),
-	PINCTRL_PIN(STN8815_PIN_H22, "GPIO113_H22"),
-	PINCTRL_PIN(STN8815_PIN_K20, "GPIO114_K20"),
-	PINCTRL_PIN(STN8815_PIN_L22, "GPIO115_L22"),
-	PINCTRL_PIN(STN8815_PIN_G21, "GPIO116_G21"),
-	PINCTRL_PIN(STN8815_PIN_J20, "GPIO117_J20"),
-	PINCTRL_PIN(STN8815_PIN_G22, "GPIO118_G22"),
-	PINCTRL_PIN(STN8815_PIN_U19, "GPIO119_U19"),
-	PINCTRL_PIN(STN8815_PIN_G19, "GPIO120_G19"),
-	PINCTRL_PIN(STN8815_PIN_M22, "GPIO121_M22"),
-	PINCTRL_PIN(STN8815_PIN_M19, "GPIO122_M19"),
-	PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"),
-};
-
-#define STN8815_GPIO_RANGE(a, b, c) { .name = "STN8815", .id = a, .base = b, \
-			.pin_base = b, .npins = c }
-
-/*
- * This matches the 32-pin gpio chips registered by the GPIO portion. This
- * cannot be const since we assign the struct gpio_chip * pointer at runtime.
- */
-static struct pinctrl_gpio_range nmk_stn8815_ranges[] = {
-	STN8815_GPIO_RANGE(0, 0, 32),
-	STN8815_GPIO_RANGE(1, 32, 32),
-	STN8815_GPIO_RANGE(2, 64, 32),
-	STN8815_GPIO_RANGE(3, 96, 28),
-};
-
-/*
- * Read the pin group names like this:
- * u0_a_1    = first groups of pins for uart0 on alt function a
- * i2c2_b_2  = second group of pins for i2c2 on alt function b
- */
-
-/* Altfunction A */
-static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5,
-	STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6,
-	STN8815_PIN_C6, STN8815_PIN_B6 };
-static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10,
-	STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12,
-	STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 };
-static const unsigned u1_a_1_pins[] = { STN8815_PIN_M2, STN8815_PIN_L1,
-					STN8815_PIN_F3, STN8815_PIN_F2 };
-static const unsigned i2c1_a_1_pins[] = { STN8815_PIN_L4, STN8815_PIN_L3 };
-static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 };
-/* Altfunction B */
-static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
-static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
-
-#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
-			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
-
-static const struct nmk_pingroup nmk_stn8815_groups[] = {
-	STN8815_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A),
-	STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A),
-	STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A),
-	STN8815_PIN_GROUP(i2c1_a_1, NMK_GPIO_ALT_A),
-	STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
-	STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B),
-	STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B),
-};
-
-/* We use this macro to define the groups applicable to a function */
-#define STN8815_FUNC_GROUPS(a, b...)	   \
-static const char * const a##_groups[] = { b };
-
-STN8815_FUNC_GROUPS(u0, "u0_a_1");
-STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1");
-STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1");
-STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1");
-STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1");
-STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1");
-
-#define FUNCTION(fname)					\
-	{						\
-		.name = #fname,				\
-		.groups = fname##_groups,		\
-		.ngroups = ARRAY_SIZE(fname##_groups),	\
-	}
-
-static const struct nmk_function nmk_stn8815_functions[] = {
-	FUNCTION(u0),
-	FUNCTION(mmcsd),
-	FUNCTION(u1),
-	FUNCTION(i2c1),
-	FUNCTION(i2c0),
-	FUNCTION(i2cusb),
-};
-
-static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = {
-	.gpio_ranges = nmk_stn8815_ranges,
-	.gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges),
-	.pins = nmk_stn8815_pins,
-	.npins = ARRAY_SIZE(nmk_stn8815_pins),
-	.functions = nmk_stn8815_functions,
-	.nfunctions = ARRAY_SIZE(nmk_stn8815_functions),
-	.groups = nmk_stn8815_groups,
-	.ngroups = ARRAY_SIZE(nmk_stn8815_groups),
-};
-
-void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
-{
-	*soc = &nmk_stn8815_soc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-rockchip.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-rockchip.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-rockchip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-rockchip.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,11 +62,26 @@ enum rockchip_pinctrl_type {
 	RK2928,
 	RK3066B,
 	RK3188,
+	RK3288,
 };
 
-enum rockchip_pin_bank_type {
-	COMMON_BANK,
-	RK3188_BANK0,
+/**
+ * Encode variants of iomux registers into a type variable
+ */
+#define IOMUX_GPIO_ONLY		BIT(0)
+#define IOMUX_WIDTH_4BIT	BIT(1)
+#define IOMUX_SOURCE_PMU	BIT(2)
+#define IOMUX_UNROUTED		BIT(3)
+
+/**
+ * @type: iomux variant using IOMUX_* constants
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ *	    an initial offset value the relevant source offset can be reset
+ *	    to a new value for autocalculating the following iomux registers.
+ */
+struct rockchip_iomux {
+	int				type;
+	int				offset;
 };
 
 /**
@@ -78,6 +93,7 @@ enum rockchip_pin_bank_type {
  * @nr_pins: number of pins in this bank
  * @name: name of the bank
  * @bank_num: number of the bank, to account for holes
+ * @iomux: array describing the 4 iomux sources of the bank
  * @valid: are all necessary informations present
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
@@ -95,7 +111,7 @@ struct rockchip_pin_bank {
 	u8				nr_pins;
 	char				*name;
 	u8				bank_num;
-	enum rockchip_pin_bank_type	bank_type;
+	struct rockchip_iomux		iomux[4];
 	bool				valid;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
@@ -111,6 +127,25 @@ struct rockchip_pin_bank {
 		.bank_num	= id,			\
 		.nr_pins	= pins,			\
 		.name		= label,		\
+		.iomux		= {			\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+		},					\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
 	}
 
 /**
@@ -121,7 +156,8 @@ struct rockchip_pin_ctrl {
 	u32				nr_pins;
 	char				*label;
 	enum rockchip_pinctrl_type	type;
-	int				mux_offset;
+	int				grf_mux_offset;
+	int				pmu_mux_offset;
 	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank,
 				    int pin_num, struct regmap **regmap,
 				    int *reg, u8 *bit);
@@ -343,24 +379,42 @@ static const struct pinctrl_ops rockchip
 static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
 	unsigned int val;
-	int reg, ret;
+	int reg, ret, mask;
 	u8 bit;
 
-	if (bank->bank_type == RK3188_BANK0 && pin < 16)
+	if (iomux_num > 3)
+		return -EINVAL;
+
+	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+		dev_err(info->dev, "pin %d is unrouted\n", pin);
+		return -EINVAL;
+	}
+
+	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
 		return RK_FUNC_GPIO;
 
+	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+				? info->regmap_pmu : info->regmap_base;
+
 	/* get basic quadrupel of mux registers and the correct reg inside */
-	reg = info->ctrl->mux_offset;
-	reg += bank->bank_num * 0x10;
-	reg += (pin / 8) * 4;
-	bit = (pin % 8) * 2;
+	mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+	reg = bank->iomux[iomux_num].offset;
+	if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+		if ((pin % 8) >= 4)
+			reg += 0x4;
+		bit = (pin % 4) * 4;
+	} else {
+		bit = (pin % 8) * 2;
+	}
 
-	ret = regmap_read(info->regmap_base, reg, &val);
+	ret = regmap_read(regmap, reg, &val);
 	if (ret)
 		return ret;
 
-	return ((val >> bit) & 3);
+	return ((val >> bit) & mask);
 }
 
 /*
@@ -379,16 +433,22 @@ static int rockchip_get_mux(struct rockc
 static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
-	int reg, ret;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	int reg, ret, mask;
 	unsigned long flags;
 	u8 bit;
-	u32 data;
+	u32 data, rmask;
 
-	/*
-	 * The first 16 pins of rk3188_bank0 are always gpios and do not have
-	 * a mux register at all.
-	 */
-	if (bank->bank_type == RK3188_BANK0 && pin < 16) {
+	if (iomux_num > 3)
+		return -EINVAL;
+
+	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+		dev_err(info->dev, "pin %d is unrouted\n", pin);
+		return -EINVAL;
+	}
+
+	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
 		if (mux != RK_FUNC_GPIO) {
 			dev_err(info->dev,
 				"pin %d only supports a gpio mux\n", pin);
@@ -401,17 +461,26 @@ static int rockchip_set_mux(struct rockc
 	dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
 						bank->bank_num, pin, mux);
 
+	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+				? info->regmap_pmu : info->regmap_base;
+
 	/* get basic quadrupel of mux registers and the correct reg inside */
-	reg = info->ctrl->mux_offset;
-	reg += bank->bank_num * 0x10;
-	reg += (pin / 8) * 4;
-	bit = (pin % 8) * 2;
+	mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+	reg = bank->iomux[iomux_num].offset;
+	if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+		if ((pin % 8) >= 4)
+			reg += 0x4;
+		bit = (pin % 4) * 4;
+	} else {
+		bit = (pin % 8) * 2;
+	}
 
 	spin_lock_irqsave(&bank->slock, flags);
 
-	data = (3 << (bit + 16));
-	data |= (mux & 3) << bit;
-	ret = regmap_write(info->regmap_base, reg, data);
+	data = (mask << (bit + 16));
+	rmask = data | (data >> 16);
+	data |= (mux & mask) << bit;
+	ret = regmap_update_bits(regmap, reg, rmask, data);
 
 	spin_unlock_irqrestore(&bank->slock, flags);
 
@@ -449,7 +518,7 @@ static void rk3188_calc_pull_reg_and_bit
 	struct rockchip_pinctrl *info = bank->drvdata;
 
 	/* The first 12 pins of the first bank are located elsewhere */
-	if (bank->bank_type == RK3188_BANK0 && pin_num < 12) {
+	if (bank->bank_num == 0 && pin_num < 12) {
 		*regmap = info->regmap_pmu ? info->regmap_pmu
 					   : bank->regmap_pull;
 		*reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0;
@@ -476,6 +545,128 @@ static void rk3188_calc_pull_reg_and_bit
 	}
 }
 
+#define RK3288_PULL_OFFSET		0x140
+static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3188_PULL_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3288_PULL_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+}
+
+#define RK3288_DRV_PMU_OFFSET		0x70
+#define RK3288_DRV_GRF_OFFSET		0x1c0
+#define RK3288_DRV_BITS_PER_PIN		2
+#define RK3288_DRV_PINS_PER_REG		8
+#define RK3288_DRV_BANK_STRIDE		16
+static int rk3288_drv_list[] = { 2, 4, 8, 12 };
+
+static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 24 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3288_DRV_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3288_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	}
+}
+
+static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u32 data;
+	u8 bit;
+
+	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	ret = regmap_read(regmap, reg, &data);
+	if (ret)
+		return ret;
+
+	data >>= bit;
+	data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
+
+	return rk3288_drv_list[data];
+}
+
+static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
+			    int strength)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct regmap *regmap;
+	unsigned long flags;
+	int reg, ret, i;
+	u32 data, rmask;
+	u8 bit;
+
+	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	ret = -EINVAL;
+	for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) {
+		if (rk3288_drv_list[i] == strength) {
+			ret = i;
+			break;
+		}
+	}
+
+	if (ret < 0) {
+		dev_err(info->dev, "unsupported driver strength %d\n",
+			strength);
+		return ret;
+	}
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (ret << bit);
+
+	ret = regmap_update_bits(regmap, reg, rmask, data);
+	spin_unlock_irqrestore(&bank->slock, flags);
+
+	return ret;
+}
+
 static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
@@ -501,6 +692,7 @@ static int rockchip_get_pull(struct rock
 				? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
 				: PIN_CONFIG_BIAS_DISABLE;
 	case RK3188:
+	case RK3288:
 		data >>= bit;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
@@ -532,7 +724,7 @@ static int rockchip_set_pull(struct rock
 	int reg, ret;
 	unsigned long flags;
 	u8 bit;
-	u32 data;
+	u32 data, rmask;
 
 	dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n",
 		 bank->bank_num, pin_num, pull);
@@ -555,10 +747,12 @@ static int rockchip_set_pull(struct rock
 		spin_unlock_irqrestore(&bank->slock, flags);
 		break;
 	case RK3188:
+	case RK3288:
 		spin_lock_irqsave(&bank->slock, flags);
 
 		/* enable the write to the equivalent lower bits */
 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+		rmask = data | (data >> 16);
 
 		switch (pull) {
 		case PIN_CONFIG_BIAS_DISABLE:
@@ -579,7 +773,7 @@ static int rockchip_set_pull(struct rock
 			return -EINVAL;
 		}
 
-		ret = regmap_write(regmap, reg, data);
+		ret = regmap_update_bits(regmap, reg, rmask, data);
 
 		spin_unlock_irqrestore(&bank->slock, flags);
 		break;
@@ -657,23 +851,6 @@ static int rockchip_pmx_enable(struct pi
 	return 0;
 }
 
-static void rockchip_pmx_disable(struct pinctrl_dev *pctldev,
-					unsigned selector, unsigned group)
-{
-	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-	const unsigned int *pins = info->groups[group].pins;
-	struct rockchip_pin_bank *bank;
-	int cnt;
-
-	dev_dbg(info->dev, "disable function %s group %s\n",
-		info->functions[selector].name, info->groups[group].name);
-
-	for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
-		bank = pin_to_bank(info, pins[cnt]);
-		rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
-	}
-}
-
 /*
  * The calls to gpio_direction_output() and gpio_direction_input()
  * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
@@ -716,7 +893,6 @@ static const struct pinmux_ops rockchip_
 	.get_function_name	= rockchip_pmx_get_func_name,
 	.get_function_groups	= rockchip_pmx_get_groups,
 	.enable			= rockchip_pmx_enable,
-	.disable		= rockchip_pmx_disable,
 	.gpio_set_direction	= rockchip_pmx_gpio_set_direction,
 };
 
@@ -734,6 +910,7 @@ static bool rockchip_pinconf_pull_valid(
 	case RK3066B:
 		return pull ? false : true;
 	case RK3188:
+	case RK3288:
 		return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
 	}
 
@@ -788,6 +965,15 @@ static int rockchip_pinconf_set(struct p
 			if (rc)
 				return rc;
 			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			/* rk3288 is the first with per-pin drive-strength */
+			if (info->ctrl->type != RK3288)
+				return -ENOTSUPP;
+
+			rc = rk3288_set_drive(bank, pin - bank->pin_base, arg);
+			if (rc < 0)
+				return rc;
+			break;
 		default:
 			return -ENOTSUPP;
 			break;
@@ -837,6 +1023,17 @@ static int rockchip_pinconf_get(struct p
 
 		arg = rc ? 1 : 0;
 		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		/* rk3288 is the first with per-pin drive-strength */
+		if (info->ctrl->type != RK3288)
+			return -ENOTSUPP;
+
+		rc = rk3288_get_drive(bank, pin - bank->pin_base);
+		if (rc < 0)
+			return rc;
+
+		arg = rc;
+		break;
 	default:
 		return -ENOTSUPP;
 		break;
@@ -850,6 +1047,7 @@ static int rockchip_pinconf_get(struct p
 static const struct pinconf_ops rockchip_pinconf_ops = {
 	.pin_config_get			= rockchip_pinconf_get,
 	.pin_config_set			= rockchip_pinconf_set,
+	.is_generic			= true,
 };
 
 static const struct of_device_id rockchip_bank_match[] = {
@@ -1414,10 +1612,7 @@ fail:
 	for (--i, --bank; i >= 0; --i, --bank) {
 		if (!bank->valid)
 			continue;
-
-		if (gpiochip_remove(&bank->gpio_chip))
-			dev_err(&pdev->dev, "gpio chip %s remove failed\n",
-							bank->gpio_chip.label);
+		gpiochip_remove(&bank->gpio_chip);
 	}
 	return ret;
 }
@@ -1427,20 +1622,15 @@ static int rockchip_gpiolib_unregister(s
 {
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
-	int ret = 0;
 	int i;
 
-	for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank) {
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
 		if (!bank->valid)
 			continue;
-
-		ret = gpiochip_remove(&bank->gpio_chip);
+		gpiochip_remove(&bank->gpio_chip);
 	}
 
-	if (ret)
-		dev_err(&pdev->dev, "gpio chip remove failed\n");
-
-	return ret;
+	return 0;
 }
 
 static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
@@ -1466,8 +1656,6 @@ static int rockchip_get_bank_data(struct
 				    "rockchip,rk3188-gpio-bank0")) {
 		struct device_node *node;
 
-		bank->bank_type = RK3188_BANK0;
-
 		node = of_parse_phandle(bank->of_node->parent,
 					"rockchip,pmu", 0);
 		if (!node) {
@@ -1487,9 +1675,6 @@ static int rockchip_get_bank_data(struct
 						    base,
 						    &rockchip_regmap_config);
 		}
-
-	} else {
-		bank->bank_type = COMMON_BANK;
 	}
 
 	bank->irq = irq_of_parse_and_map(bank->of_node, 0);
@@ -1513,7 +1698,7 @@ static struct rockchip_pin_ctrl *rockchi
 	struct device_node *np;
 	struct rockchip_pin_ctrl *ctrl;
 	struct rockchip_pin_bank *bank;
-	int i;
+	int grf_offs, pmu_offs, i, j;
 
 	match = of_match_node(rockchip_pinctrl_dt_match, node);
 	ctrl = (struct rockchip_pin_ctrl *)match->data;
@@ -1535,12 +1720,51 @@ static struct rockchip_pin_ctrl *rockchi
 		}
 	}
 
+	grf_offs = ctrl->grf_mux_offset;
+	pmu_offs = ctrl->pmu_mux_offset;
 	bank = ctrl->pin_banks;
 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		int bank_pins = 0;
+
 		spin_lock_init(&bank->slock);
 		bank->drvdata = d;
 		bank->pin_base = ctrl->nr_pins;
 		ctrl->nr_pins += bank->nr_pins;
+
+		/* calculate iomux offsets */
+		for (j = 0; j < 4; j++) {
+			struct rockchip_iomux *iom = &bank->iomux[j];
+			int inc;
+
+			if (bank_pins >= bank->nr_pins)
+				break;
+
+			/* preset offset value, set new start value */
+			if (iom->offset >= 0) {
+				if (iom->type & IOMUX_SOURCE_PMU)
+					pmu_offs = iom->offset;
+				else
+					grf_offs = iom->offset;
+			} else { /* set current offset */
+				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
+							pmu_offs : grf_offs;
+			}
+
+			dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n",
+				 i, j, iom->offset);
+
+			/*
+			 * Increase offset according to iomux width.
+			 * 4bit iomux'es are spread over two registers.
+			 */
+			inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4;
+			if (iom->type & IOMUX_SOURCE_PMU)
+				pmu_offs += inc;
+			else
+				grf_offs += inc;
+
+			bank_pins += 8;
+		}
 	}
 
 	return ctrl;
@@ -1644,7 +1868,7 @@ static struct rockchip_pin_ctrl rk2928_p
 		.nr_banks		= ARRAY_SIZE(rk2928_pin_banks),
 		.label			= "RK2928-GPIO",
 		.type			= RK2928,
-		.mux_offset		= 0xa8,
+		.grf_mux_offset		= 0xa8,
 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
@@ -1662,7 +1886,7 @@ static struct rockchip_pin_ctrl rk3066a_
 		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
 		.label			= "RK3066a-GPIO",
 		.type			= RK2928,
-		.mux_offset		= 0xa8,
+		.grf_mux_offset		= 0xa8,
 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
@@ -1678,11 +1902,11 @@ static struct rockchip_pin_ctrl rk3066b_
 		.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
 		.label		= "RK3066b-GPIO",
 		.type		= RK3066B,
-		.mux_offset	= 0x60,
+		.grf_mux_offset	= 0x60,
 };
 
 static struct rockchip_pin_bank rk3188_pin_banks[] = {
-	PIN_BANK(0, 32, "gpio0"),
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
 	PIN_BANK(1, 32, "gpio1"),
 	PIN_BANK(2, 32, "gpio2"),
 	PIN_BANK(3, 32, "gpio3"),
@@ -1693,10 +1917,52 @@ static struct rockchip_pin_ctrl rk3188_p
 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
 		.label			= "RK3188-GPIO",
 		.type			= RK3188,
-		.mux_offset		= 0x60,
+		.grf_mux_offset		= 0x60,
 		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3288_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
+					     IOMUX_UNROUTED,
+					     IOMUX_UNROUTED,
+					     0
+			    ),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     0,
+					     0
+			    ),
+	PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
+					     0,
+					     0,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
+	PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
+					     0,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_UNROUTED
+			    ),
+	PIN_BANK(8, 16, "gpio8"),
+};
+
+static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
+		.pin_banks		= rk3288_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3288_pin_banks),
+		.label			= "RK3288-GPIO",
+		.type			= RK3288,
+		.grf_mux_offset		= 0x0,
+		.pmu_mux_offset		= 0x84,
+		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
+};
+
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
 	{ .compatible = "rockchip,rk2928-pinctrl",
 		.data = (void *)&rk2928_pin_ctrl },
@@ -1706,6 +1972,8 @@ static const struct of_device_id rockchi
 		.data = (void *)&rk3066b_pin_ctrl },
 	{ .compatible = "rockchip,rk3188-pinctrl",
 		.data = (void *)&rk3188_pin_ctrl },
+	{ .compatible = "rockchip,rk3288-pinctrl",
+		.data = (void *)&rk3288_pin_ctrl },
 	{},
 };
 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-s3c24xx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-s3c24xx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-s3c24xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-s3c24xx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,651 +0,0 @@
-/*
- * S3C24XX specific support for Samsung pinctrl/gpiolib driver.
- *
- * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.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 file contains the SamsungS3C24XX specific information required by the
- * Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-
-#include "pinctrl-samsung.h"
-
-#define NUM_EINT	24
-#define NUM_EINT_IRQ	6
-#define EINT_MAX_PER_GROUP	8
-
-#define EINTPEND_REG	0xa8
-#define EINTMASK_REG	0xa4
-
-#define EINT_GROUP(i)		((int)((i) / EINT_MAX_PER_GROUP))
-#define EINT_REG(i)		((EINT_GROUP(i) * 4) + 0x88)
-#define EINT_OFFS(i)		((i) % EINT_MAX_PER_GROUP * 4)
-
-#define EINT_LEVEL_LOW		0
-#define EINT_LEVEL_HIGH		1
-#define EINT_EDGE_FALLING	2
-#define EINT_EDGE_RISING	4
-#define EINT_EDGE_BOTH		6
-#define EINT_MASK		0xf
-
-static struct samsung_pin_bank_type bank_type_1bit = {
-	.fld_width = { 1, 1, },
-	.reg_offset = { 0x00, 0x04, },
-};
-
-static struct samsung_pin_bank_type bank_type_2bit = {
-	.fld_width = { 2, 1, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, },
-};
-
-#define PIN_BANK_A(pins, reg, id)		\
-	{						\
-		.type		= &bank_type_1bit,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define PIN_BANK_2BIT(pins, reg, id)		\
-	{						\
-		.type		= &bank_type_2bit,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs, emask)\
-	{						\
-		.type		= &bank_type_2bit,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_WKUP,	\
-		.eint_func	= 2,			\
-		.eint_mask	= emask,		\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-/**
- * struct s3c24xx_eint_data: EINT common data
- * @drvdata: pin controller driver data
- * @domains: IRQ domains of particular EINT interrupts
- * @parents: mapped parent irqs in the main interrupt controller
- */
-struct s3c24xx_eint_data {
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct irq_domain *domains[NUM_EINT];
-	int parents[NUM_EINT_IRQ];
-};
-
-/**
- * struct s3c24xx_eint_domain_data: per irq-domain data
- * @bank: pin bank related to the domain
- * @eint_data: common data
- * eint0_3_parent_only: live eints 0-3 only in the main intc
- */
-struct s3c24xx_eint_domain_data {
-	struct samsung_pin_bank *bank;
-	struct s3c24xx_eint_data *eint_data;
-	bool eint0_3_parent_only;
-};
-
-static int s3c24xx_eint_get_trigger(unsigned int type)
-{
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		return EINT_EDGE_RISING;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		return EINT_EDGE_FALLING;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		return EINT_EDGE_BOTH;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		return EINT_LEVEL_HIGH;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		return EINT_LEVEL_LOW;
-		break;
-	default:
-		return -EINVAL;
-	}
-}
-
-static void s3c24xx_eint_set_handler(unsigned int irq, unsigned int type)
-{
-	/* Edge- and level-triggered interrupts need different handlers */
-	if (type & IRQ_TYPE_EDGE_BOTH)
-		__irq_set_handler_locked(irq, handle_edge_irq);
-	else
-		__irq_set_handler_locked(irq, handle_level_irq);
-}
-
-static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
-					struct samsung_pin_bank *bank, int pin)
-{
-	struct samsung_pin_bank_type *bank_type = bank->type;
-	unsigned long flags;
-	void __iomem *reg;
-	u8 shift;
-	u32 mask;
-	u32 val;
-
-	/* Make sure that pin is configured as interrupt */
-	reg = d->virt_base + bank->pctl_offset;
-	shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
-	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	val = readl(reg);
-	val &= ~(mask << shift);
-	val |= bank->eint_func << shift;
-	writel(val, reg);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-}
-
-static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	int index = bank->eint_offset + data->hwirq;
-	void __iomem *reg;
-	int trigger;
-	u8 shift;
-	u32 val;
-
-	trigger = s3c24xx_eint_get_trigger(type);
-	if (trigger < 0) {
-		dev_err(d->dev, "unsupported external interrupt type\n");
-		return -EINVAL;
-	}
-
-	s3c24xx_eint_set_handler(data->irq, type);
-
-	/* Set up interrupt trigger */
-	reg = d->virt_base + EINT_REG(index);
-	shift = EINT_OFFS(index);
-
-	val = readl(reg);
-	val &= ~(EINT_MASK << shift);
-	val |= trigger << shift;
-	writel(val, reg);
-
-	s3c24xx_eint_set_function(d, bank, data->hwirq);
-
-	return 0;
-}
-
-/* Handling of EINTs 0-3 on all except S3C2412 and S3C2413 */
-
-static void s3c2410_eint0_3_ack(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
-	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
-	int parent_irq = eint_data->parents[data->hwirq];
-	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
-
-	parent_chip->irq_ack(irq_get_irq_data(parent_irq));
-}
-
-static void s3c2410_eint0_3_mask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
-	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
-	int parent_irq = eint_data->parents[data->hwirq];
-	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
-
-	parent_chip->irq_mask(irq_get_irq_data(parent_irq));
-}
-
-static void s3c2410_eint0_3_unmask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
-	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
-	int parent_irq = eint_data->parents[data->hwirq];
-	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
-
-	parent_chip->irq_unmask(irq_get_irq_data(parent_irq));
-}
-
-static struct irq_chip s3c2410_eint0_3_chip = {
-	.name		= "s3c2410-eint0_3",
-	.irq_ack	= s3c2410_eint0_3_ack,
-	.irq_mask	= s3c2410_eint0_3_mask,
-	.irq_unmask	= s3c2410_eint0_3_unmask,
-	.irq_set_type	= s3c24xx_eint_type,
-};
-
-static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
-	unsigned int virq;
-
-	/* the first 4 eints have a simple 1 to 1 mapping */
-	virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
-	/* Something must be really wrong if an unmapped EINT is unmasked */
-	BUG_ON(!virq);
-
-	generic_handle_irq(virq);
-}
-
-/* Handling of EINTs 0-3 on S3C2412 and S3C2413 */
-
-static void s3c2412_eint0_3_ack(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-
-	unsigned long bitval = 1UL << data->hwirq;
-	writel(bitval, d->virt_base + EINTPEND_REG);
-}
-
-static void s3c2412_eint0_3_mask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned long mask;
-
-	mask = readl(d->virt_base + EINTMASK_REG);
-	mask |= (1UL << data->hwirq);
-	writel(mask, d->virt_base + EINTMASK_REG);
-}
-
-static void s3c2412_eint0_3_unmask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned long mask;
-
-	mask = readl(d->virt_base + EINTMASK_REG);
-	mask &= ~(1UL << data->hwirq);
-	writel(mask, d->virt_base + EINTMASK_REG);
-}
-
-static struct irq_chip s3c2412_eint0_3_chip = {
-	.name		= "s3c2412-eint0_3",
-	.irq_ack	= s3c2412_eint0_3_ack,
-	.irq_mask	= s3c2412_eint0_3_mask,
-	.irq_unmask	= s3c2412_eint0_3_unmask,
-	.irq_set_type	= s3c24xx_eint_type,
-};
-
-static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
-	unsigned int virq;
-
-	chained_irq_enter(chip, desc);
-
-	/* the first 4 eints have a simple 1 to 1 mapping */
-	virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
-	/* Something must be really wrong if an unmapped EINT is unmasked */
-	BUG_ON(!virq);
-
-	generic_handle_irq(virq);
-
-	chained_irq_exit(chip, desc);
-}
-
-/* Handling of all other eints */
-
-static void s3c24xx_eint_ack(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned char index = bank->eint_offset + data->hwirq;
-
-	writel(1UL << index, d->virt_base + EINTPEND_REG);
-}
-
-static void s3c24xx_eint_mask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned char index = bank->eint_offset + data->hwirq;
-	unsigned long mask;
-
-	mask = readl(d->virt_base + EINTMASK_REG);
-	mask |= (1UL << index);
-	writel(mask, d->virt_base + EINTMASK_REG);
-}
-
-static void s3c24xx_eint_unmask(struct irq_data *data)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned char index = bank->eint_offset + data->hwirq;
-	unsigned long mask;
-
-	mask = readl(d->virt_base + EINTMASK_REG);
-	mask &= ~(1UL << index);
-	writel(mask, d->virt_base + EINTMASK_REG);
-}
-
-static struct irq_chip s3c24xx_eint_chip = {
-	.name		= "s3c-eint",
-	.irq_ack	= s3c24xx_eint_ack,
-	.irq_mask	= s3c24xx_eint_mask,
-	.irq_unmask	= s3c24xx_eint_unmask,
-	.irq_set_type	= s3c24xx_eint_type,
-};
-
-static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
-				      u32 offset, u32 range)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c24xx_eint_data *data = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *d = data->drvdata;
-	unsigned int pend, mask;
-
-	chained_irq_enter(chip, desc);
-
-	pend = readl(d->virt_base + EINTPEND_REG);
-	mask = readl(d->virt_base + EINTMASK_REG);
-
-	pend &= ~mask;
-	pend &= range;
-
-	while (pend) {
-		unsigned int virq;
-
-		irq = __ffs(pend);
-		pend &= ~(1 << irq);
-		virq = irq_linear_revmap(data->domains[irq], irq - offset);
-		/* Something is really wrong if an unmapped EINT is unmasked */
-		BUG_ON(!virq);
-
-		generic_handle_irq(virq);
-	}
-
-	chained_irq_exit(chip, desc);
-}
-
-static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
-{
-	s3c24xx_demux_eint(irq, desc, 0, 0xf0);
-}
-
-static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
-{
-	s3c24xx_demux_eint(irq, desc, 8, 0xffff00);
-}
-
-static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = {
-	s3c2410_demux_eint0_3,
-	s3c2410_demux_eint0_3,
-	s3c2410_demux_eint0_3,
-	s3c2410_demux_eint0_3,
-	s3c24xx_demux_eint4_7,
-	s3c24xx_demux_eint8_23,
-};
-
-static irq_flow_handler_t s3c2412_eint_handlers[NUM_EINT_IRQ] = {
-	s3c2412_demux_eint0_3,
-	s3c2412_demux_eint0_3,
-	s3c2412_demux_eint0_3,
-	s3c2412_demux_eint0_3,
-	s3c24xx_demux_eint4_7,
-	s3c24xx_demux_eint8_23,
-};
-
-static int s3c24xx_gpf_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct s3c24xx_eint_domain_data *ddata = h->host_data;
-	struct samsung_pin_bank *bank = ddata->bank;
-
-	if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
-		return -EINVAL;
-
-	if (hw <= 3) {
-		if (ddata->eint0_3_parent_only)
-			irq_set_chip_and_handler(virq, &s3c2410_eint0_3_chip,
-						 handle_edge_irq);
-		else
-			irq_set_chip_and_handler(virq, &s3c2412_eint0_3_chip,
-						 handle_edge_irq);
-	} else {
-		irq_set_chip_and_handler(virq, &s3c24xx_eint_chip,
-					 handle_edge_irq);
-	}
-	irq_set_chip_data(virq, bank);
-	set_irq_flags(virq, IRQF_VALID);
-	return 0;
-}
-
-static const struct irq_domain_ops s3c24xx_gpf_irq_ops = {
-	.map	= s3c24xx_gpf_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-static int s3c24xx_gpg_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct s3c24xx_eint_domain_data *ddata = h->host_data;
-	struct samsung_pin_bank *bank = ddata->bank;
-
-	if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
-		return -EINVAL;
-
-	irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq);
-	irq_set_chip_data(virq, bank);
-	set_irq_flags(virq, IRQF_VALID);
-	return 0;
-}
-
-static const struct irq_domain_ops s3c24xx_gpg_irq_ops = {
-	.map	= s3c24xx_gpg_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-static const struct of_device_id s3c24xx_eint_irq_ids[] = {
-	{ .compatible = "samsung,s3c2410-wakeup-eint", .data = (void *)1 },
-	{ .compatible = "samsung,s3c2412-wakeup-eint", .data = (void *)0 },
-	{ }
-};
-
-static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d)
-{
-	struct device *dev = d->dev;
-	const struct of_device_id *match;
-	struct device_node *eint_np = NULL;
-	struct device_node *np;
-	struct samsung_pin_bank *bank;
-	struct s3c24xx_eint_data *eint_data;
-	const struct irq_domain_ops *ops;
-	unsigned int i;
-	bool eint0_3_parent_only;
-	irq_flow_handler_t *handlers;
-
-	for_each_child_of_node(dev->of_node, np) {
-		match = of_match_node(s3c24xx_eint_irq_ids, np);
-		if (match) {
-			eint_np = np;
-			eint0_3_parent_only = (bool)match->data;
-			break;
-		}
-	}
-	if (!eint_np)
-		return -ENODEV;
-
-	eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL);
-	if (!eint_data)
-		return -ENOMEM;
-
-	eint_data->drvdata = d;
-
-	handlers = eint0_3_parent_only ? s3c2410_eint_handlers
-				       : s3c2412_eint_handlers;
-	for (i = 0; i < NUM_EINT_IRQ; ++i) {
-		unsigned int irq;
-
-		irq = irq_of_parse_and_map(eint_np, i);
-		if (!irq) {
-			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
-			return -ENXIO;
-		}
-
-		eint_data->parents[i] = irq;
-		irq_set_chained_handler(irq, handlers[i]);
-		irq_set_handler_data(irq, eint_data);
-	}
-
-	bank = d->ctrl->pin_banks;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		struct s3c24xx_eint_domain_data *ddata;
-		unsigned int mask;
-		unsigned int irq;
-		unsigned int pin;
-
-		if (bank->eint_type != EINT_TYPE_WKUP)
-			continue;
-
-		ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
-		if (!ddata)
-			return -ENOMEM;
-
-		ddata->bank = bank;
-		ddata->eint_data = eint_data;
-		ddata->eint0_3_parent_only = eint0_3_parent_only;
-
-		ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops
-					       : &s3c24xx_gpg_irq_ops;
-
-		bank->irq_domain = irq_domain_add_linear(bank->of_node,
-				bank->nr_pins, ops, ddata);
-		if (!bank->irq_domain) {
-			dev_err(dev, "wkup irq domain add failed\n");
-			return -ENXIO;
-		}
-
-		irq = bank->eint_offset;
-		mask = bank->eint_mask;
-		for (pin = 0; mask; ++pin, mask >>= 1) {
-			if (irq >= NUM_EINT)
-				break;
-			if (!(mask & 1))
-				continue;
-			eint_data->domains[irq] = bank->irq_domain;
-			++irq;
-		}
-	}
-
-	return 0;
-}
-
-static struct samsung_pin_bank s3c2412_pin_banks[] = {
-	PIN_BANK_A(23, 0x000, "gpa"),
-	PIN_BANK_2BIT(11, 0x010, "gpb"),
-	PIN_BANK_2BIT(16, 0x020, "gpc"),
-	PIN_BANK_2BIT(16, 0x030, "gpd"),
-	PIN_BANK_2BIT(16, 0x040, "gpe"),
-	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
-	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
-	PIN_BANK_2BIT(11, 0x070, "gph"),
-	PIN_BANK_2BIT(13, 0x080, "gpj"),
-};
-
-struct samsung_pin_ctrl s3c2412_pin_ctrl[] = {
-	{
-		.pin_banks	= s3c2412_pin_banks,
-		.nr_banks	= ARRAY_SIZE(s3c2412_pin_banks),
-		.eint_wkup_init = s3c24xx_eint_init,
-		.label		= "S3C2412-GPIO",
-	},
-};
-
-static struct samsung_pin_bank s3c2416_pin_banks[] = {
-	PIN_BANK_A(27, 0x000, "gpa"),
-	PIN_BANK_2BIT(11, 0x010, "gpb"),
-	PIN_BANK_2BIT(16, 0x020, "gpc"),
-	PIN_BANK_2BIT(16, 0x030, "gpd"),
-	PIN_BANK_2BIT(16, 0x040, "gpe"),
-	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
-	PIN_BANK_2BIT_EINTW(8, 0x060, "gpg", 8, 0xff00),
-	PIN_BANK_2BIT(15, 0x070, "gph"),
-	PIN_BANK_2BIT(16, 0x0e0, "gpk"),
-	PIN_BANK_2BIT(14, 0x0f0, "gpl"),
-	PIN_BANK_2BIT(2, 0x100, "gpm"),
-};
-
-struct samsung_pin_ctrl s3c2416_pin_ctrl[] = {
-	{
-		.pin_banks	= s3c2416_pin_banks,
-		.nr_banks	= ARRAY_SIZE(s3c2416_pin_banks),
-		.eint_wkup_init = s3c24xx_eint_init,
-		.label		= "S3C2416-GPIO",
-	},
-};
-
-static struct samsung_pin_bank s3c2440_pin_banks[] = {
-	PIN_BANK_A(25, 0x000, "gpa"),
-	PIN_BANK_2BIT(11, 0x010, "gpb"),
-	PIN_BANK_2BIT(16, 0x020, "gpc"),
-	PIN_BANK_2BIT(16, 0x030, "gpd"),
-	PIN_BANK_2BIT(16, 0x040, "gpe"),
-	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
-	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
-	PIN_BANK_2BIT(11, 0x070, "gph"),
-	PIN_BANK_2BIT(13, 0x0d0, "gpj"),
-};
-
-struct samsung_pin_ctrl s3c2440_pin_ctrl[] = {
-	{
-		.pin_banks	= s3c2440_pin_banks,
-		.nr_banks	= ARRAY_SIZE(s3c2440_pin_banks),
-		.eint_wkup_init = s3c24xx_eint_init,
-		.label		= "S3C2440-GPIO",
-	},
-};
-
-static struct samsung_pin_bank s3c2450_pin_banks[] = {
-	PIN_BANK_A(28, 0x000, "gpa"),
-	PIN_BANK_2BIT(11, 0x010, "gpb"),
-	PIN_BANK_2BIT(16, 0x020, "gpc"),
-	PIN_BANK_2BIT(16, 0x030, "gpd"),
-	PIN_BANK_2BIT(16, 0x040, "gpe"),
-	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
-	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
-	PIN_BANK_2BIT(15, 0x070, "gph"),
-	PIN_BANK_2BIT(16, 0x0d0, "gpj"),
-	PIN_BANK_2BIT(16, 0x0e0, "gpk"),
-	PIN_BANK_2BIT(15, 0x0f0, "gpl"),
-	PIN_BANK_2BIT(2, 0x100, "gpm"),
-};
-
-struct samsung_pin_ctrl s3c2450_pin_ctrl[] = {
-	{
-		.pin_banks	= s3c2450_pin_banks,
-		.nr_banks	= ARRAY_SIZE(s3c2450_pin_banks),
-		.eint_wkup_init = s3c24xx_eint_init,
-		.label		= "S3C2450-GPIO",
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-s3c64xx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-s3c64xx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-s3c64xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-s3c64xx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,816 +0,0 @@
-/*
- * S3C64xx specific support for pinctrl-samsung driver.
- *
- * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
- *
- * Based on pinctrl-exynos.c, please see the file for original copyrights.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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 contains the Samsung S3C64xx specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-
-#include "pinctrl-samsung.h"
-
-#define NUM_EINT0		28
-#define NUM_EINT0_IRQ		4
-#define EINT_MAX_PER_REG	16
-#define EINT_MAX_PER_GROUP	16
-
-/* External GPIO and wakeup interrupt related definitions */
-#define SVC_GROUP_SHIFT		4
-#define SVC_GROUP_MASK		0xf
-#define SVC_NUM_MASK		0xf
-#define SVC_GROUP(x)		((x >> SVC_GROUP_SHIFT) & \
-						SVC_GROUP_MASK)
-
-#define EINT12CON_REG		0x200
-#define EINT12MASK_REG		0x240
-#define EINT12PEND_REG		0x260
-
-#define EINT_OFFS(i)		((i) % (2 * EINT_MAX_PER_GROUP))
-#define EINT_GROUP(i)		((i) / EINT_MAX_PER_GROUP)
-#define EINT_REG(g)		(4 * ((g) / 2))
-
-#define EINTCON_REG(i)		(EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
-#define EINTMASK_REG(i)		(EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
-#define EINTPEND_REG(i)		(EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
-
-#define SERVICE_REG		0x284
-#define SERVICEPEND_REG		0x288
-
-#define EINT0CON0_REG		0x900
-#define EINT0MASK_REG		0x920
-#define EINT0PEND_REG		0x924
-
-/* S3C64xx specific external interrupt trigger types */
-#define EINT_LEVEL_LOW		0
-#define EINT_LEVEL_HIGH		1
-#define EINT_EDGE_FALLING	2
-#define EINT_EDGE_RISING	4
-#define EINT_EDGE_BOTH		6
-#define EINT_CON_MASK		0xF
-#define EINT_CON_LEN		4
-
-static struct samsung_pin_bank_type bank_type_4bit_off = {
-	.fld_width = { 4, 1, 2, 0, 2, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
-};
-
-static struct samsung_pin_bank_type bank_type_4bit_alive = {
-	.fld_width = { 4, 1, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, },
-};
-
-static struct samsung_pin_bank_type bank_type_4bit2_off = {
-	.fld_width = { 4, 1, 2, 0, 2, 2, },
-	.reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
-};
-
-static struct samsung_pin_bank_type bank_type_4bit2_alive = {
-	.fld_width = { 4, 1, 2, },
-	.reg_offset = { 0x00, 0x08, 0x0c, },
-};
-
-static struct samsung_pin_bank_type bank_type_2bit_off = {
-	.fld_width = { 2, 1, 2, 0, 2, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
-};
-
-static struct samsung_pin_bank_type bank_type_2bit_alive = {
-	.fld_width = { 2, 1, 2, },
-	.reg_offset = { 0x00, 0x04, 0x08, },
-};
-
-#define PIN_BANK_4BIT(pins, reg, id)			\
-	{						\
-		.type		= &bank_type_4bit_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs)	\
-	{						\
-		.type		= &bank_type_4bit_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_GPIO,	\
-		.eint_func	= 7,			\
-		.eint_mask	= (1 << (pins)) - 1,	\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
-	{						\
-		.type		= &bank_type_4bit_alive,\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_WKUP,	\
-		.eint_func	= 3,			\
-		.eint_mask	= emask,		\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs)	\
-	{						\
-		.type		= &bank_type_4bit2_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_GPIO,	\
-		.eint_func	= 7,			\
-		.eint_mask	= (1 << (pins)) - 1,	\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
-	{						\
-		.type		= &bank_type_4bit2_alive,\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_WKUP,	\
-		.eint_func	= 3,			\
-		.eint_mask	= emask,		\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-#define PIN_BANK_4BIT2_ALIVE(pins, reg, id)		\
-	{						\
-		.type		= &bank_type_4bit2_alive,\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define PIN_BANK_2BIT(pins, reg, id)			\
-	{						\
-		.type		= &bank_type_2bit_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_NONE,	\
-		.name		= id			\
-	}
-
-#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
-	{						\
-		.type		= &bank_type_2bit_off,	\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_GPIO,	\
-		.eint_func	= 3,			\
-		.eint_mask	= emask,		\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs)	\
-	{						\
-		.type		= &bank_type_2bit_alive,\
-		.pctl_offset	= reg,			\
-		.nr_pins	= pins,			\
-		.eint_type	= EINT_TYPE_WKUP,	\
-		.eint_func	= 2,			\
-		.eint_mask	= (1 << (pins)) - 1,	\
-		.eint_offset	= eoffs,		\
-		.name		= id			\
-	}
-
-/**
- * struct s3c64xx_eint0_data: EINT0 common data
- * @drvdata: pin controller driver data
- * @domains: IRQ domains of particular EINT0 interrupts
- * @pins: pin offsets inside of banks of particular EINT0 interrupts
- */
-struct s3c64xx_eint0_data {
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct irq_domain *domains[NUM_EINT0];
-	u8 pins[NUM_EINT0];
-};
-
-/**
- * struct s3c64xx_eint0_domain_data: EINT0 per-domain data
- * @bank: pin bank related to the domain
- * @eints: EINT0 interrupts related to the domain
- */
-struct s3c64xx_eint0_domain_data {
-	struct samsung_pin_bank *bank;
-	u8 eints[];
-};
-
-/**
- * struct s3c64xx_eint_gpio_data: GPIO EINT data
- * @drvdata: pin controller driver data
- * @domains: array of domains related to EINT interrupt groups
- */
-struct s3c64xx_eint_gpio_data {
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct irq_domain *domains[];
-};
-
-/*
- * Common functions for S3C64xx EINT configuration
- */
-
-static int s3c64xx_irq_get_trigger(unsigned int type)
-{
-	int trigger;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		trigger = EINT_EDGE_RISING;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		trigger = EINT_EDGE_FALLING;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		trigger = EINT_EDGE_BOTH;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		trigger = EINT_LEVEL_HIGH;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		trigger = EINT_LEVEL_LOW;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return trigger;
-}
-
-static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
-{
-	/* Edge- and level-triggered interrupts need different handlers */
-	if (type & IRQ_TYPE_EDGE_BOTH)
-		__irq_set_handler_locked(irq, handle_edge_irq);
-	else
-		__irq_set_handler_locked(irq, handle_level_irq);
-}
-
-static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
-					struct samsung_pin_bank *bank, int pin)
-{
-	struct samsung_pin_bank_type *bank_type = bank->type;
-	unsigned long flags;
-	void __iomem *reg;
-	u8 shift;
-	u32 mask;
-	u32 val;
-
-	/* Make sure that pin is configured as interrupt */
-	reg = d->virt_base + bank->pctl_offset;
-	shift = pin;
-	if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
-		/* 4-bit bank type with 2 con regs */
-		reg += 4;
-		shift -= 8;
-	}
-
-	shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
-	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	val = readl(reg);
-	val &= ~(mask << shift);
-	val |= bank->eint_func << shift;
-	writel(val, reg);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-}
-
-/*
- * Functions for EINT GPIO configuration (EINT groups 1-9)
- */
-
-static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
-	void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
-	u32 val;
-
-	val = readl(reg);
-	if (mask)
-		val |= 1 << index;
-	else
-		val &= ~(1 << index);
-	writel(val, reg);
-}
-
-static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
-{
-	s3c64xx_gpio_irq_set_mask(irqd, false);
-}
-
-static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
-{
-	s3c64xx_gpio_irq_set_mask(irqd, true);
-}
-
-static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
-	void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
-
-	writel(1 << index, reg);
-}
-
-static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
-{
-	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	void __iomem *reg;
-	int trigger;
-	u8 shift;
-	u32 val;
-
-	trigger = s3c64xx_irq_get_trigger(type);
-	if (trigger < 0) {
-		pr_err("unsupported external interrupt type\n");
-		return -EINVAL;
-	}
-
-	s3c64xx_irq_set_handler(irqd->irq, type);
-
-	/* Set up interrupt trigger */
-	reg = d->virt_base + EINTCON_REG(bank->eint_offset);
-	shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
-	shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
-
-	val = readl(reg);
-	val &= ~(EINT_CON_MASK << shift);
-	val |= trigger << shift;
-	writel(val, reg);
-
-	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
-
-	return 0;
-}
-
-/*
- * irq_chip for gpio interrupts.
- */
-static struct irq_chip s3c64xx_gpio_irq_chip = {
-	.name		= "GPIO",
-	.irq_unmask	= s3c64xx_gpio_irq_unmask,
-	.irq_mask	= s3c64xx_gpio_irq_mask,
-	.irq_ack	= s3c64xx_gpio_irq_ack,
-	.irq_set_type	= s3c64xx_gpio_irq_set_type,
-};
-
-static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct samsung_pin_bank *bank = h->host_data;
-
-	if (!(bank->eint_mask & (1 << hw)))
-		return -EINVAL;
-
-	irq_set_chip_and_handler(virq,
-				&s3c64xx_gpio_irq_chip, handle_level_irq);
-	irq_set_chip_data(virq, bank);
-	set_irq_flags(virq, IRQF_VALID);
-
-	return 0;
-}
-
-/*
- * irq domain callbacks for external gpio interrupt controller.
- */
-static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
-	.map	= s3c64xx_gpio_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
-
-	chained_irq_enter(chip, desc);
-
-	do {
-		unsigned int svc;
-		unsigned int group;
-		unsigned int pin;
-		unsigned int virq;
-
-		svc = readl(drvdata->virt_base + SERVICE_REG);
-		group = SVC_GROUP(svc);
-		pin = svc & SVC_NUM_MASK;
-
-		if (!group)
-			break;
-
-		/* Group 1 is used for two pin banks */
-		if (group == 1) {
-			if (pin < 8)
-				group = 0;
-			else
-				pin -= 8;
-		}
-
-		virq = irq_linear_revmap(data->domains[group], pin);
-		/*
-		 * Something must be really wrong if an unmapped EINT
-		 * was unmasked...
-		 */
-		BUG_ON(!virq);
-
-		generic_handle_irq(virq);
-	} while (1);
-
-	chained_irq_exit(chip, desc);
-}
-
-/**
- * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
- * @d: driver data of samsung pinctrl driver.
- */
-static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
-{
-	struct s3c64xx_eint_gpio_data *data;
-	struct samsung_pin_bank *bank;
-	struct device *dev = d->dev;
-	unsigned int nr_domains;
-	unsigned int i;
-
-	if (!d->irq) {
-		dev_err(dev, "irq number not available\n");
-		return -EINVAL;
-	}
-
-	nr_domains = 0;
-	bank = d->ctrl->pin_banks;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		unsigned int nr_eints;
-		unsigned int mask;
-
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-
-		mask = bank->eint_mask;
-		nr_eints = fls(mask);
-
-		bank->irq_domain = irq_domain_add_linear(bank->of_node,
-					nr_eints, &s3c64xx_gpio_irqd_ops, bank);
-		if (!bank->irq_domain) {
-			dev_err(dev, "gpio irq domain add failed\n");
-			return -ENXIO;
-		}
-
-		++nr_domains;
-	}
-
-	data = devm_kzalloc(dev, sizeof(*data)
-			+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
-	if (!data) {
-		dev_err(dev, "failed to allocate handler data\n");
-		return -ENOMEM;
-	}
-	data->drvdata = d;
-
-	bank = d->ctrl->pin_banks;
-	nr_domains = 0;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-
-		data->domains[nr_domains++] = bank->irq_domain;
-	}
-
-	irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
-	irq_set_handler_data(d->irq, data);
-
-	return 0;
-}
-
-/*
- * Functions for configuration of EINT0 wake-up interrupts
- */
-
-static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
-{
-	struct s3c64xx_eint0_domain_data *ddata =
-					irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
-	u32 val;
-
-	val = readl(d->virt_base + EINT0MASK_REG);
-	if (mask)
-		val |= 1 << ddata->eints[irqd->hwirq];
-	else
-		val &= ~(1 << ddata->eints[irqd->hwirq]);
-	writel(val, d->virt_base + EINT0MASK_REG);
-}
-
-static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
-{
-	s3c64xx_eint0_irq_set_mask(irqd, false);
-}
-
-static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
-{
-	s3c64xx_eint0_irq_set_mask(irqd, true);
-}
-
-static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
-{
-	struct s3c64xx_eint0_domain_data *ddata =
-					irq_data_get_irq_chip_data(irqd);
-	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
-
-	writel(1 << ddata->eints[irqd->hwirq],
-					d->virt_base + EINT0PEND_REG);
-}
-
-static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
-{
-	struct s3c64xx_eint0_domain_data *ddata =
-					irq_data_get_irq_chip_data(irqd);
-	struct samsung_pin_bank *bank = ddata->bank;
-	struct samsung_pinctrl_drv_data *d = bank->drvdata;
-	void __iomem *reg;
-	int trigger;
-	u8 shift;
-	u32 val;
-
-	trigger = s3c64xx_irq_get_trigger(type);
-	if (trigger < 0) {
-		pr_err("unsupported external interrupt type\n");
-		return -EINVAL;
-	}
-
-	s3c64xx_irq_set_handler(irqd->irq, type);
-
-	/* Set up interrupt trigger */
-	reg = d->virt_base + EINT0CON0_REG;
-	shift = ddata->eints[irqd->hwirq];
-	if (shift >= EINT_MAX_PER_REG) {
-		reg += 4;
-		shift -= EINT_MAX_PER_REG;
-	}
-	shift = EINT_CON_LEN * (shift / 2);
-
-	val = readl(reg);
-	val &= ~(EINT_CON_MASK << shift);
-	val |= trigger << shift;
-	writel(val, reg);
-
-	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
-
-	return 0;
-}
-
-/*
- * irq_chip for wakeup interrupts
- */
-static struct irq_chip s3c64xx_eint0_irq_chip = {
-	.name		= "EINT0",
-	.irq_unmask	= s3c64xx_eint0_irq_unmask,
-	.irq_mask	= s3c64xx_eint0_irq_mask,
-	.irq_ack	= s3c64xx_eint0_irq_ack,
-	.irq_set_type	= s3c64xx_eint0_irq_set_type,
-};
-
-static inline void s3c64xx_irq_demux_eint(unsigned int irq,
-					struct irq_desc *desc, u32 range)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
-	unsigned int pend, mask;
-
-	chained_irq_enter(chip, desc);
-
-	pend = readl(drvdata->virt_base + EINT0PEND_REG);
-	mask = readl(drvdata->virt_base + EINT0MASK_REG);
-
-	pend = pend & range & ~mask;
-	pend &= range;
-
-	while (pend) {
-		unsigned int virq;
-
-		irq = fls(pend) - 1;
-		pend &= ~(1 << irq);
-
-		virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
-		/*
-		 * Something must be really wrong if an unmapped EINT
-		 * was unmasked...
-		 */
-		BUG_ON(!virq);
-
-		generic_handle_irq(virq);
-	}
-
-	chained_irq_exit(chip, desc);
-}
-
-static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
-	s3c64xx_irq_demux_eint(irq, desc, 0xf);
-}
-
-static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
-{
-	s3c64xx_irq_demux_eint(irq, desc, 0xff0);
-}
-
-static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
-{
-	s3c64xx_irq_demux_eint(irq, desc, 0xff000);
-}
-
-static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
-{
-	s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
-}
-
-static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
-	s3c64xx_demux_eint0_3,
-	s3c64xx_demux_eint4_11,
-	s3c64xx_demux_eint12_19,
-	s3c64xx_demux_eint20_27,
-};
-
-static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
-					irq_hw_number_t hw)
-{
-	struct s3c64xx_eint0_domain_data *ddata = h->host_data;
-	struct samsung_pin_bank *bank = ddata->bank;
-
-	if (!(bank->eint_mask & (1 << hw)))
-		return -EINVAL;
-
-	irq_set_chip_and_handler(virq,
-				&s3c64xx_eint0_irq_chip, handle_level_irq);
-	irq_set_chip_data(virq, ddata);
-	set_irq_flags(virq, IRQF_VALID);
-
-	return 0;
-}
-
-/*
- * irq domain callbacks for external wakeup interrupt controller.
- */
-static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
-	.map	= s3c64xx_eint0_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-/* list of external wakeup controllers supported */
-static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
-	{ .compatible = "samsung,s3c64xx-wakeup-eint", },
-	{ }
-};
-
-/**
- * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
- * @d: driver data of samsung pinctrl driver.
- */
-static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
-{
-	struct device *dev = d->dev;
-	struct device_node *eint0_np = NULL;
-	struct device_node *np;
-	struct samsung_pin_bank *bank;
-	struct s3c64xx_eint0_data *data;
-	unsigned int i;
-
-	for_each_child_of_node(dev->of_node, np) {
-		if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
-			eint0_np = np;
-			break;
-		}
-	}
-	if (!eint0_np)
-		return -ENODEV;
-
-	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		dev_err(dev, "could not allocate memory for wkup eint data\n");
-		return -ENOMEM;
-	}
-	data->drvdata = d;
-
-	for (i = 0; i < NUM_EINT0_IRQ; ++i) {
-		unsigned int irq;
-
-		irq = irq_of_parse_and_map(eint0_np, i);
-		if (!irq) {
-			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
-			return -ENXIO;
-		}
-
-		irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
-		irq_set_handler_data(irq, data);
-	}
-
-	bank = d->ctrl->pin_banks;
-	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
-		struct s3c64xx_eint0_domain_data *ddata;
-		unsigned int nr_eints;
-		unsigned int mask;
-		unsigned int irq;
-		unsigned int pin;
-
-		if (bank->eint_type != EINT_TYPE_WKUP)
-			continue;
-
-		mask = bank->eint_mask;
-		nr_eints = fls(mask);
-
-		ddata = devm_kzalloc(dev,
-				sizeof(*ddata) + nr_eints, GFP_KERNEL);
-		if (!ddata) {
-			dev_err(dev, "failed to allocate domain data\n");
-			return -ENOMEM;
-		}
-		ddata->bank = bank;
-
-		bank->irq_domain = irq_domain_add_linear(bank->of_node,
-				nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
-		if (!bank->irq_domain) {
-			dev_err(dev, "wkup irq domain add failed\n");
-			return -ENXIO;
-		}
-
-		irq = bank->eint_offset;
-		mask = bank->eint_mask;
-		for (pin = 0; mask; ++pin, mask >>= 1) {
-			if (!(mask & 1))
-				continue;
-			data->domains[irq] = bank->irq_domain;
-			data->pins[irq] = pin;
-			ddata->eints[pin] = irq;
-			++irq;
-		}
-	}
-
-	return 0;
-}
-
-/* pin banks of s3c64xx pin-controller 0 */
-static struct samsung_pin_bank s3c64xx_pin_banks0[] = {
-	PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
-	PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
-	PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
-	PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
-	PIN_BANK_4BIT(5, 0x080, "gpe"),
-	PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
-	PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
-	PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
-	PIN_BANK_2BIT(16, 0x100, "gpi"),
-	PIN_BANK_2BIT(12, 0x120, "gpj"),
-	PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
-	PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
-	PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
-	PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
-	PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
-	PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
-	PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
-};
-
-/*
- * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
- * one gpio/pin-mux/pinconfig controller.
- */
-struct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
-	{
-		/* pin-controller instance 1 data */
-		.pin_banks	= s3c64xx_pin_banks0,
-		.nr_banks	= ARRAY_SIZE(s3c64xx_pin_banks0),
-		.eint_gpio_init = s3c64xx_eint_gpio_init,
-		.eint_wkup_init = s3c64xx_eint_eint0_init,
-		.label		= "S3C64xx-GPIO",
-	},
-};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-samsung.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-samsung.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-samsung.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-samsung.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1181 +0,0 @@
-/*
- * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- *		http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver implements the Samsung pinctrl driver. It supports setting up of
- * pinmux and pinconf configurations. The gpiolib interface is also included.
- * External interrupt (gpio and wakeup) support are not included in this driver
- * but provides extensions to which platform specific implementation of the gpio
- * and wakeup interrupts can be hooked to.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/irqdomain.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-
-#include "core.h"
-#include "pinctrl-samsung.h"
-
-#define GROUP_SUFFIX		"-grp"
-#define GSUFFIX_LEN		sizeof(GROUP_SUFFIX)
-#define FUNCTION_SUFFIX		"-mux"
-#define FSUFFIX_LEN		sizeof(FUNCTION_SUFFIX)
-
-/* list of all possible config options supported */
-static struct pin_config {
-	char		*prop_cfg;
-	unsigned int	cfg_type;
-} pcfgs[] = {
-	{ "samsung,pin-pud", PINCFG_TYPE_PUD },
-	{ "samsung,pin-drv", PINCFG_TYPE_DRV },
-	{ "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
-	{ "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
-};
-
-/* Global list of devices (struct samsung_pinctrl_drv_data) */
-static LIST_HEAD(drvdata_list);
-
-static unsigned int pin_base;
-
-static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
-{
-	return container_of(gc, struct samsung_pin_bank, gpio_chip);
-}
-
-/* check if the selector is a valid pin group selector */
-static int samsung_get_group_count(struct pinctrl_dev *pctldev)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	return drvdata->nr_groups;
-}
-
-/* return the name of the group selected by the group selector */
-static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
-						unsigned selector)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	return drvdata->pin_groups[selector].name;
-}
-
-/* return the pin numbers associated with the specified group */
-static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
-		unsigned selector, const unsigned **pins, unsigned *num_pins)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	*pins = drvdata->pin_groups[selector].pins;
-	*num_pins = drvdata->pin_groups[selector].num_pins;
-	return 0;
-}
-
-/* create pinctrl_map entries by parsing device tree nodes */
-static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
-			struct device_node *np, struct pinctrl_map **maps,
-			unsigned *nmaps)
-{
-	struct device *dev = pctldev->dev;
-	struct pinctrl_map *map;
-	unsigned long *cfg = NULL;
-	char *gname, *fname;
-	int cfg_cnt = 0, map_cnt = 0, idx = 0;
-
-	/* count the number of config options specfied in the node */
-	for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
-		if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
-			cfg_cnt++;
-	}
-
-	/*
-	 * Find out the number of map entries to create. All the config options
-	 * can be accomadated into a single config map entry.
-	 */
-	if (cfg_cnt)
-		map_cnt = 1;
-	if (of_find_property(np, "samsung,pin-function", NULL))
-		map_cnt++;
-	if (!map_cnt) {
-		dev_err(dev, "node %s does not have either config or function "
-				"configurations\n", np->name);
-		return -EINVAL;
-	}
-
-	/* Allocate memory for pin-map entries */
-	map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
-	if (!map) {
-		dev_err(dev, "could not alloc memory for pin-maps\n");
-		return -ENOMEM;
-	}
-	*nmaps = 0;
-
-	/*
-	 * Allocate memory for pin group name. The pin group name is derived
-	 * from the node name from which these map entries are be created.
-	 */
-	gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
-	if (!gname) {
-		dev_err(dev, "failed to alloc memory for group name\n");
-		goto free_map;
-	}
-	sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
-
-	/*
-	 * don't have config options? then skip over to creating function
-	 * map entries.
-	 */
-	if (!cfg_cnt)
-		goto skip_cfgs;
-
-	/* Allocate memory for config entries */
-	cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
-	if (!cfg) {
-		dev_err(dev, "failed to alloc memory for configs\n");
-		goto free_gname;
-	}
-
-	/* Prepare a list of config settings */
-	for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
-		u32 value;
-		if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
-			cfg[cfg_cnt++] =
-				PINCFG_PACK(pcfgs[idx].cfg_type, value);
-	}
-
-	/* create the config map entry */
-	map[*nmaps].data.configs.group_or_pin = gname;
-	map[*nmaps].data.configs.configs = cfg;
-	map[*nmaps].data.configs.num_configs = cfg_cnt;
-	map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
-	*nmaps += 1;
-
-skip_cfgs:
-	/* create the function map entry */
-	if (of_find_property(np, "samsung,pin-function", NULL)) {
-		fname = kzalloc(strlen(np->name) + FSUFFIX_LEN,	GFP_KERNEL);
-		if (!fname) {
-			dev_err(dev, "failed to alloc memory for func name\n");
-			goto free_cfg;
-		}
-		sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
-
-		map[*nmaps].data.mux.group = gname;
-		map[*nmaps].data.mux.function = fname;
-		map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
-		*nmaps += 1;
-	}
-
-	*maps = map;
-	return 0;
-
-free_cfg:
-	kfree(cfg);
-free_gname:
-	kfree(gname);
-free_map:
-	kfree(map);
-	return -ENOMEM;
-}
-
-/* free the memory allocated to hold the pin-map table */
-static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
-			     struct pinctrl_map *map, unsigned num_maps)
-{
-	int idx;
-
-	for (idx = 0; idx < num_maps; idx++) {
-		if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
-			kfree(map[idx].data.mux.function);
-			if (!idx)
-				kfree(map[idx].data.mux.group);
-		} else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
-			kfree(map[idx].data.configs.configs);
-			if (!idx)
-				kfree(map[idx].data.configs.group_or_pin);
-		}
-	};
-
-	kfree(map);
-}
-
-/* list of pinctrl callbacks for the pinctrl core */
-static const struct pinctrl_ops samsung_pctrl_ops = {
-	.get_groups_count	= samsung_get_group_count,
-	.get_group_name		= samsung_get_group_name,
-	.get_group_pins		= samsung_get_group_pins,
-	.dt_node_to_map		= samsung_dt_node_to_map,
-	.dt_free_map		= samsung_dt_free_map,
-};
-
-/* check if the selector is a valid pin function selector */
-static int samsung_get_functions_count(struct pinctrl_dev *pctldev)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	return drvdata->nr_functions;
-}
-
-/* return the name of the pin function specified */
-static const char *samsung_pinmux_get_fname(struct pinctrl_dev *pctldev,
-						unsigned selector)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	return drvdata->pmx_functions[selector].name;
-}
-
-/* return the groups associated for the specified function selector */
-static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
-		unsigned selector, const char * const **groups,
-		unsigned * const num_groups)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	*groups = drvdata->pmx_functions[selector].groups;
-	*num_groups = drvdata->pmx_functions[selector].num_groups;
-	return 0;
-}
-
-/*
- * given a pin number that is local to a pin controller, find out the pin bank
- * and the register base of the pin bank.
- */
-static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
-			unsigned pin, void __iomem **reg, u32 *offset,
-			struct samsung_pin_bank **bank)
-{
-	struct samsung_pin_bank *b;
-
-	b = drvdata->ctrl->pin_banks;
-
-	while ((pin >= b->pin_base) &&
-			((b->pin_base + b->nr_pins - 1) < pin))
-		b++;
-
-	*reg = drvdata->virt_base + b->pctl_offset;
-	*offset = pin - b->pin_base;
-	if (bank)
-		*bank = b;
-}
-
-/* enable or disable a pinmux function */
-static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
-					unsigned group, bool enable)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-	const unsigned int *pins;
-	struct samsung_pin_bank *bank;
-	void __iomem *reg;
-	u32 mask, shift, data, pin_offset, cnt;
-	unsigned long flags;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	pins = drvdata->pin_groups[group].pins;
-
-	/*
-	 * for each pin in the pin group selected, program the correspoding pin
-	 * pin function number in the config register.
-	 */
-	for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
-		struct samsung_pin_bank_type *type;
-
-		pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
-				&reg, &pin_offset, &bank);
-		type = bank->type;
-		mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-		shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
-		if (shift >= 32) {
-			/* Some banks have two config registers */
-			shift -= 32;
-			reg += 4;
-		}
-
-		spin_lock_irqsave(&bank->slock, flags);
-
-		data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
-		data &= ~(mask << shift);
-		if (enable)
-			data |= drvdata->pin_groups[group].func << shift;
-		writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
-
-		spin_unlock_irqrestore(&bank->slock, flags);
-	}
-}
-
-/* enable a specified pinmux by writing to registers */
-static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
-					unsigned group)
-{
-	samsung_pinmux_setup(pctldev, selector, group, true);
-	return 0;
-}
-
-/* disable a specified pinmux by writing to registers */
-static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
-					unsigned selector, unsigned group)
-{
-	samsung_pinmux_setup(pctldev, selector, group, false);
-}
-
-/*
- * The calls to gpio_direction_output() and gpio_direction_input()
- * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
- * function called from the gpiolib interface).
- */
-static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
-		struct pinctrl_gpio_range *range, unsigned offset, bool input)
-{
-	struct samsung_pin_bank_type *type;
-	struct samsung_pin_bank *bank;
-	struct samsung_pinctrl_drv_data *drvdata;
-	void __iomem *reg;
-	u32 data, pin_offset, mask, shift;
-	unsigned long flags;
-
-	bank = gc_to_pin_bank(range->gc);
-	type = bank->type;
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-
-	pin_offset = offset - bank->pin_base;
-	reg = drvdata->virt_base + bank->pctl_offset +
-					type->reg_offset[PINCFG_TYPE_FUNC];
-
-	mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-	shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
-	if (shift >= 32) {
-		/* Some banks have two config registers */
-		shift -= 32;
-		reg += 4;
-	}
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	data = readl(reg);
-	data &= ~(mask << shift);
-	if (!input)
-		data |= FUNC_OUTPUT << shift;
-	writel(data, reg);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-
-	return 0;
-}
-
-/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static const struct pinmux_ops samsung_pinmux_ops = {
-	.get_functions_count	= samsung_get_functions_count,
-	.get_function_name	= samsung_pinmux_get_fname,
-	.get_function_groups	= samsung_pinmux_get_groups,
-	.enable			= samsung_pinmux_enable,
-	.disable		= samsung_pinmux_disable,
-	.gpio_set_direction	= samsung_pinmux_gpio_set_direction,
-};
-
-/* set or get the pin config settings for a specified pin */
-static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
-				unsigned long *config, bool set)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct samsung_pin_bank_type *type;
-	struct samsung_pin_bank *bank;
-	void __iomem *reg_base;
-	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
-	u32 data, width, pin_offset, mask, shift;
-	u32 cfg_value, cfg_reg;
-	unsigned long flags;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
-					&pin_offset, &bank);
-	type = bank->type;
-
-	if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
-		return -EINVAL;
-
-	width = type->fld_width[cfg_type];
-	cfg_reg = type->reg_offset[cfg_type];
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	mask = (1 << width) - 1;
-	shift = pin_offset * width;
-	data = readl(reg_base + cfg_reg);
-
-	if (set) {
-		cfg_value = PINCFG_UNPACK_VALUE(*config);
-		data &= ~(mask << shift);
-		data |= (cfg_value << shift);
-		writel(data, reg_base + cfg_reg);
-	} else {
-		data >>= shift;
-		data &= mask;
-		*config = PINCFG_PACK(cfg_type, data);
-	}
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-
-	return 0;
-}
-
-/* set the pin config settings for a specified pin */
-static int samsung_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-				unsigned long *configs, unsigned num_configs)
-{
-	int i, ret;
-
-	for (i = 0; i < num_configs; i++) {
-		ret = samsung_pinconf_rw(pctldev, pin, &configs[i], true);
-		if (ret < 0)
-			return ret;
-	} /* for each config */
-
-	return 0;
-}
-
-/* get the pin config settings for a specified pin */
-static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
-					unsigned long *config)
-{
-	return samsung_pinconf_rw(pctldev, pin, config, false);
-}
-
-/* set the pin config settings for a specified pin group */
-static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
-			unsigned group, unsigned long *configs,
-			unsigned num_configs)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-	const unsigned int *pins;
-	unsigned int cnt;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	pins = drvdata->pin_groups[group].pins;
-
-	for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++)
-		samsung_pinconf_set(pctldev, pins[cnt], configs, num_configs);
-
-	return 0;
-}
-
-/* get the pin config settings for a specified pin group */
-static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
-				unsigned int group, unsigned long *config)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-	const unsigned int *pins;
-
-	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	pins = drvdata->pin_groups[group].pins;
-	samsung_pinconf_get(pctldev, pins[0], config);
-	return 0;
-}
-
-/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static const struct pinconf_ops samsung_pinconf_ops = {
-	.pin_config_get		= samsung_pinconf_get,
-	.pin_config_set		= samsung_pinconf_set,
-	.pin_config_group_get	= samsung_pinconf_group_get,
-	.pin_config_group_set	= samsung_pinconf_group_set,
-};
-
-/* gpiolib gpio_set callback function */
-static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
-{
-	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
-	struct samsung_pin_bank_type *type = bank->type;
-	unsigned long flags;
-	void __iomem *reg;
-	u32 data;
-
-	reg = bank->drvdata->virt_base + bank->pctl_offset;
-
-	spin_lock_irqsave(&bank->slock, flags);
-
-	data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
-	data &= ~(1 << offset);
-	if (value)
-		data |= 1 << offset;
-	writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
-
-	spin_unlock_irqrestore(&bank->slock, flags);
-}
-
-/* gpiolib gpio_get callback function */
-static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-	void __iomem *reg;
-	u32 data;
-	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
-	struct samsung_pin_bank_type *type = bank->type;
-
-	reg = bank->drvdata->virt_base + bank->pctl_offset;
-
-	data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
-	data >>= offset;
-	data &= 1;
-	return data;
-}
-
-/*
- * gpiolib gpio_direction_input callback function. The setting of the pin
- * mux function as 'gpio input' will be handled by the pinctrl susbsystem
- * interface.
- */
-static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	return pinctrl_gpio_direction_input(gc->base + offset);
-}
-
-/*
- * gpiolib gpio_direction_output callback function. The setting of the pin
- * mux function as 'gpio output' will be handled by the pinctrl susbsystem
- * interface.
- */
-static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
-							int value)
-{
-	samsung_gpio_set(gc, offset, value);
-	return pinctrl_gpio_direction_output(gc->base + offset);
-}
-
-/*
- * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
- * and a virtual IRQ, if not already present.
- */
-static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
-	unsigned int virq;
-
-	if (!bank->irq_domain)
-		return -ENXIO;
-
-	virq = irq_create_mapping(bank->irq_domain, offset);
-
-	return (virq) ? : -ENXIO;
-}
-
-/*
- * Parse the pin names listed in the 'samsung,pins' property and convert it
- * into a list of gpio numbers are create a pin group from it.
- */
-static int samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
-					 struct device_node *cfg_np,
-					 struct pinctrl_desc *pctl,
-					 unsigned int **pin_list,
-					 unsigned int *npins)
-{
-	struct device *dev = &pdev->dev;
-	struct property *prop;
-	struct pinctrl_pin_desc const *pdesc = pctl->pins;
-	unsigned int idx = 0, cnt;
-	const char *pin_name;
-
-	*npins = of_property_count_strings(cfg_np, "samsung,pins");
-	if (IS_ERR_VALUE(*npins)) {
-		dev_err(dev, "invalid pin list in %s node", cfg_np->name);
-		return -EINVAL;
-	}
-
-	*pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
-	if (!*pin_list) {
-		dev_err(dev, "failed to allocate memory for pin list\n");
-		return -ENOMEM;
-	}
-
-	of_property_for_each_string(cfg_np, "samsung,pins", prop, pin_name) {
-		for (cnt = 0; cnt < pctl->npins; cnt++) {
-			if (pdesc[cnt].name) {
-				if (!strcmp(pin_name, pdesc[cnt].name)) {
-					(*pin_list)[idx++] = pdesc[cnt].number;
-					break;
-				}
-			}
-		}
-		if (cnt == pctl->npins) {
-			dev_err(dev, "pin %s not valid in %s node\n",
-					pin_name, cfg_np->name);
-			devm_kfree(dev, *pin_list);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Parse the information about all the available pin groups and pin functions
- * from device node of the pin-controller. A pin group is formed with all
- * the pins listed in the "samsung,pins" property.
- */
-static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
-				    struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *dev_np = dev->of_node;
-	struct device_node *cfg_np;
-	struct samsung_pin_group *groups, *grp;
-	struct samsung_pmx_func *functions, *func;
-	unsigned *pin_list;
-	unsigned int npins, grp_cnt, func_idx = 0;
-	char *gname, *fname;
-	int ret;
-
-	grp_cnt = of_get_child_count(dev_np);
-	if (!grp_cnt)
-		return -EINVAL;
-
-	groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
-	if (!groups) {
-		dev_err(dev, "failed allocate memory for ping group list\n");
-		return -EINVAL;
-	}
-	grp = groups;
-
-	functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
-	if (!functions) {
-		dev_err(dev, "failed to allocate memory for function list\n");
-		return -EINVAL;
-	}
-	func = functions;
-
-	/*
-	 * Iterate over all the child nodes of the pin controller node
-	 * and create pin groups and pin function lists.
-	 */
-	for_each_child_of_node(dev_np, cfg_np) {
-		u32 function;
-		if (!of_find_property(cfg_np, "samsung,pins", NULL))
-			continue;
-
-		ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
-					&drvdata->pctl,	&pin_list, &npins);
-		if (ret)
-			return ret;
-
-		/* derive pin group name from the node name */
-		gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
-					GFP_KERNEL);
-		if (!gname) {
-			dev_err(dev, "failed to alloc memory for group name\n");
-			return -ENOMEM;
-		}
-		sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
-
-		grp->name = gname;
-		grp->pins = pin_list;
-		grp->num_pins = npins;
-		of_property_read_u32(cfg_np, "samsung,pin-function", &function);
-		grp->func = function;
-		grp++;
-
-		if (!of_find_property(cfg_np, "samsung,pin-function", NULL))
-			continue;
-
-		/* derive function name from the node name */
-		fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
-					GFP_KERNEL);
-		if (!fname) {
-			dev_err(dev, "failed to alloc memory for func name\n");
-			return -ENOMEM;
-		}
-		sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
-
-		func->name = fname;
-		func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
-		if (!func->groups) {
-			dev_err(dev, "failed to alloc memory for group list "
-					"in pin function");
-			return -ENOMEM;
-		}
-		func->groups[0] = gname;
-		func->num_groups = 1;
-		func++;
-		func_idx++;
-	}
-
-	drvdata->pin_groups = groups;
-	drvdata->nr_groups = grp_cnt;
-	drvdata->pmx_functions = functions;
-	drvdata->nr_functions = func_idx;
-
-	return 0;
-}
-
-/* register the pinctrl interface with the pinctrl subsystem */
-static int samsung_pinctrl_register(struct platform_device *pdev,
-				    struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct pinctrl_desc *ctrldesc = &drvdata->pctl;
-	struct pinctrl_pin_desc *pindesc, *pdesc;
-	struct samsung_pin_bank *pin_bank;
-	char *pin_names;
-	int pin, bank, ret;
-
-	ctrldesc->name = "samsung-pinctrl";
-	ctrldesc->owner = THIS_MODULE;
-	ctrldesc->pctlops = &samsung_pctrl_ops;
-	ctrldesc->pmxops = &samsung_pinmux_ops;
-	ctrldesc->confops = &samsung_pinconf_ops;
-
-	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
-			drvdata->ctrl->nr_pins, GFP_KERNEL);
-	if (!pindesc) {
-		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
-		return -ENOMEM;
-	}
-	ctrldesc->pins = pindesc;
-	ctrldesc->npins = drvdata->ctrl->nr_pins;
-
-	/* dynamically populate the pin number and pin name for pindesc */
-	for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
-		pdesc->number = pin + drvdata->ctrl->base;
-
-	/*
-	 * allocate space for storing the dynamically generated names for all
-	 * the pins which belong to this pin-controller.
-	 */
-	pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
-					drvdata->ctrl->nr_pins, GFP_KERNEL);
-	if (!pin_names) {
-		dev_err(&pdev->dev, "mem alloc for pin names failed\n");
-		return -ENOMEM;
-	}
-
-	/* for each pin, the name of the pin is pin-bank name + pin number */
-	for (bank = 0; bank < drvdata->ctrl->nr_banks; bank++) {
-		pin_bank = &drvdata->ctrl->pin_banks[bank];
-		for (pin = 0; pin < pin_bank->nr_pins; pin++) {
-			sprintf(pin_names, "%s-%d", pin_bank->name, pin);
-			pdesc = pindesc + pin_bank->pin_base + pin;
-			pdesc->name = pin_names;
-			pin_names += PIN_NAME_LENGTH;
-		}
-	}
-
-	ret = samsung_pinctrl_parse_dt(pdev, drvdata);
-	if (ret)
-		return ret;
-
-	drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
-	if (!drvdata->pctl_dev) {
-		dev_err(&pdev->dev, "could not register pinctrl driver\n");
-		return -EINVAL;
-	}
-
-	for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
-		pin_bank = &drvdata->ctrl->pin_banks[bank];
-		pin_bank->grange.name = pin_bank->name;
-		pin_bank->grange.id = bank;
-		pin_bank->grange.pin_base = pin_bank->pin_base;
-		pin_bank->grange.base = pin_bank->gpio_chip.base;
-		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
-		pin_bank->grange.gc = &pin_bank->gpio_chip;
-		pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
-	}
-
-	return 0;
-}
-
-static const struct gpio_chip samsung_gpiolib_chip = {
-	.set = samsung_gpio_set,
-	.get = samsung_gpio_get,
-	.direction_input = samsung_gpio_direction_input,
-	.direction_output = samsung_gpio_direction_output,
-	.to_irq = samsung_gpio_to_irq,
-	.owner = THIS_MODULE,
-};
-
-/* register the gpiolib interface with the gpiolib subsystem */
-static int samsung_gpiolib_register(struct platform_device *pdev,
-				    struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	struct samsung_pin_bank *bank = ctrl->pin_banks;
-	struct gpio_chip *gc;
-	int ret;
-	int i;
-
-	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
-		bank->gpio_chip = samsung_gpiolib_chip;
-
-		gc = &bank->gpio_chip;
-		gc->base = ctrl->base + bank->pin_base;
-		gc->ngpio = bank->nr_pins;
-		gc->dev = &pdev->dev;
-		gc->of_node = bank->of_node;
-		gc->label = bank->name;
-
-		ret = gpiochip_add(gc);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
-							gc->label, ret);
-			goto fail;
-		}
-	}
-
-	return 0;
-
-fail:
-	for (--i, --bank; i >= 0; --i, --bank)
-		if (gpiochip_remove(&bank->gpio_chip))
-			dev_err(&pdev->dev, "gpio chip %s remove failed\n",
-							bank->gpio_chip.label);
-	return ret;
-}
-
-/* unregister the gpiolib interface with the gpiolib subsystem */
-static int samsung_gpiolib_unregister(struct platform_device *pdev,
-				      struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	struct samsung_pin_bank *bank = ctrl->pin_banks;
-	int ret = 0;
-	int i;
-
-	for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
-		ret = gpiochip_remove(&bank->gpio_chip);
-
-	if (ret)
-		dev_err(&pdev->dev, "gpio chip remove failed\n");
-
-	return ret;
-}
-
-static const struct of_device_id samsung_pinctrl_dt_match[];
-
-/* retrieve the soc specific data */
-static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
-				struct samsung_pinctrl_drv_data *d,
-				struct platform_device *pdev)
-{
-	int id;
-	const struct of_device_id *match;
-	struct device_node *node = pdev->dev.of_node;
-	struct device_node *np;
-	struct samsung_pin_ctrl *ctrl;
-	struct samsung_pin_bank *bank;
-	int i;
-
-	id = of_alias_get_id(node, "pinctrl");
-	if (id < 0) {
-		dev_err(&pdev->dev, "failed to get alias id\n");
-		return NULL;
-	}
-	match = of_match_node(samsung_pinctrl_dt_match, node);
-	ctrl = (struct samsung_pin_ctrl *)match->data + id;
-
-	bank = ctrl->pin_banks;
-	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
-		spin_lock_init(&bank->slock);
-		bank->drvdata = d;
-		bank->pin_base = ctrl->nr_pins;
-		ctrl->nr_pins += bank->nr_pins;
-	}
-
-	for_each_child_of_node(node, np) {
-		if (!of_find_property(np, "gpio-controller", NULL))
-			continue;
-		bank = ctrl->pin_banks;
-		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
-			if (!strcmp(bank->name, np->name)) {
-				bank->of_node = np;
-				break;
-			}
-		}
-	}
-
-	ctrl->base = pin_base;
-	pin_base += ctrl->nr_pins;
-
-	return ctrl;
-}
-
-static int samsung_pinctrl_probe(struct platform_device *pdev)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct device *dev = &pdev->dev;
-	struct samsung_pin_ctrl *ctrl;
-	struct resource *res;
-	int ret;
-
-	if (!dev->of_node) {
-		dev_err(dev, "device tree node not found\n");
-		return -ENODEV;
-	}
-
-	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		dev_err(dev, "failed to allocate memory for driver's "
-				"private data\n");
-		return -ENOMEM;
-	}
-
-	ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
-	if (!ctrl) {
-		dev_err(&pdev->dev, "driver data not available\n");
-		return -EINVAL;
-	}
-	drvdata->ctrl = ctrl;
-	drvdata->dev = dev;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(drvdata->virt_base))
-		return PTR_ERR(drvdata->virt_base);
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res)
-		drvdata->irq = res->start;
-
-	ret = samsung_gpiolib_register(pdev, drvdata);
-	if (ret)
-		return ret;
-
-	ret = samsung_pinctrl_register(pdev, drvdata);
-	if (ret) {
-		samsung_gpiolib_unregister(pdev, drvdata);
-		return ret;
-	}
-
-	if (ctrl->eint_gpio_init)
-		ctrl->eint_gpio_init(drvdata);
-	if (ctrl->eint_wkup_init)
-		ctrl->eint_wkup_init(drvdata);
-
-	platform_set_drvdata(pdev, drvdata);
-
-	/* Add to the global list */
-	list_add_tail(&drvdata->node, &drvdata_list);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-/**
- * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device
- *
- * Save data for all banks handled by this device.
- */
-static void samsung_pinctrl_suspend_dev(
-	struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	void __iomem *virt_base = drvdata->virt_base;
-	int i;
-
-	for (i = 0; i < ctrl->nr_banks; i++) {
-		struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
-		void __iomem *reg = virt_base + bank->pctl_offset;
-
-		u8 *offs = bank->type->reg_offset;
-		u8 *widths = bank->type->fld_width;
-		enum pincfg_type type;
-
-		/* Registers without a powerdown config aren't lost */
-		if (!widths[PINCFG_TYPE_CON_PDN])
-			continue;
-
-		for (type = 0; type < PINCFG_TYPE_NUM; type++)
-			if (widths[type])
-				bank->pm_save[type] = readl(reg + offs[type]);
-
-		if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
-			/* Some banks have two config registers */
-			bank->pm_save[PINCFG_TYPE_NUM] =
-				readl(reg + offs[PINCFG_TYPE_FUNC] + 4);
-			pr_debug("Save %s @ %p (con %#010x %08x)\n",
-				 bank->name, reg,
-				 bank->pm_save[PINCFG_TYPE_FUNC],
-				 bank->pm_save[PINCFG_TYPE_NUM]);
-		} else {
-			pr_debug("Save %s @ %p (con %#010x)\n", bank->name,
-				 reg, bank->pm_save[PINCFG_TYPE_FUNC]);
-		}
-	}
-
-	if (ctrl->suspend)
-		ctrl->suspend(drvdata);
-}
-
-/**
- * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
- *
- * Restore one of the banks that was saved during suspend.
- *
- * We don't bother doing anything complicated to avoid glitching lines since
- * we're called before pad retention is turned off.
- */
-static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
-{
-	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
-	void __iomem *virt_base = drvdata->virt_base;
-	int i;
-
-	if (ctrl->resume)
-		ctrl->resume(drvdata);
-
-	for (i = 0; i < ctrl->nr_banks; i++) {
-		struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
-		void __iomem *reg = virt_base + bank->pctl_offset;
-
-		u8 *offs = bank->type->reg_offset;
-		u8 *widths = bank->type->fld_width;
-		enum pincfg_type type;
-
-		/* Registers without a powerdown config aren't lost */
-		if (!widths[PINCFG_TYPE_CON_PDN])
-			continue;
-
-		if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
-			/* Some banks have two config registers */
-			pr_debug("%s @ %p (con %#010x %08x => %#010x %08x)\n",
-				 bank->name, reg,
-				 readl(reg + offs[PINCFG_TYPE_FUNC]),
-				 readl(reg + offs[PINCFG_TYPE_FUNC] + 4),
-				 bank->pm_save[PINCFG_TYPE_FUNC],
-				 bank->pm_save[PINCFG_TYPE_NUM]);
-			writel(bank->pm_save[PINCFG_TYPE_NUM],
-			       reg + offs[PINCFG_TYPE_FUNC] + 4);
-		} else {
-			pr_debug("%s @ %p (con %#010x => %#010x)\n", bank->name,
-				 reg, readl(reg + offs[PINCFG_TYPE_FUNC]),
-				 bank->pm_save[PINCFG_TYPE_FUNC]);
-		}
-		for (type = 0; type < PINCFG_TYPE_NUM; type++)
-			if (widths[type])
-				writel(bank->pm_save[type], reg + offs[type]);
-	}
-}
-
-/**
- * samsung_pinctrl_suspend - save pinctrl state for suspend
- *
- * Save data for all banks across all devices.
- */
-static int samsung_pinctrl_suspend(void)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	list_for_each_entry(drvdata, &drvdata_list, node) {
-		samsung_pinctrl_suspend_dev(drvdata);
-	}
-
-	return 0;
-}
-
-/**
- * samsung_pinctrl_resume - restore pinctrl state for suspend
- *
- * Restore data for all banks across all devices.
- */
-static void samsung_pinctrl_resume(void)
-{
-	struct samsung_pinctrl_drv_data *drvdata;
-
-	list_for_each_entry_reverse(drvdata, &drvdata_list, node) {
-		samsung_pinctrl_resume_dev(drvdata);
-	}
-}
-
-#else
-#define samsung_pinctrl_suspend		NULL
-#define samsung_pinctrl_resume		NULL
-#endif
-
-static struct syscore_ops samsung_pinctrl_syscore_ops = {
-	.suspend	= samsung_pinctrl_suspend,
-	.resume		= samsung_pinctrl_resume,
-};
-
-static const struct of_device_id samsung_pinctrl_dt_match[] = {
-#ifdef CONFIG_PINCTRL_EXYNOS
-	{ .compatible = "samsung,exynos3250-pinctrl",
-		.data = (void *)exynos3250_pin_ctrl },
-	{ .compatible = "samsung,exynos4210-pinctrl",
-		.data = (void *)exynos4210_pin_ctrl },
-	{ .compatible = "samsung,exynos4x12-pinctrl",
-		.data = (void *)exynos4x12_pin_ctrl },
-	{ .compatible = "samsung,exynos5250-pinctrl",
-		.data = (void *)exynos5250_pin_ctrl },
-	{ .compatible = "samsung,exynos5260-pinctrl",
-		.data = (void *)exynos5260_pin_ctrl },
-	{ .compatible = "samsung,exynos5420-pinctrl",
-		.data = (void *)exynos5420_pin_ctrl },
-	{ .compatible = "samsung,s5pv210-pinctrl",
-		.data = (void *)s5pv210_pin_ctrl },
-#endif
-#ifdef CONFIG_PINCTRL_S3C64XX
-	{ .compatible = "samsung,s3c64xx-pinctrl",
-		.data = s3c64xx_pin_ctrl },
-#endif
-#ifdef CONFIG_PINCTRL_S3C24XX
-	{ .compatible = "samsung,s3c2412-pinctrl",
-		.data = s3c2412_pin_ctrl },
-	{ .compatible = "samsung,s3c2416-pinctrl",
-		.data = s3c2416_pin_ctrl },
-	{ .compatible = "samsung,s3c2440-pinctrl",
-		.data = s3c2440_pin_ctrl },
-	{ .compatible = "samsung,s3c2450-pinctrl",
-		.data = s3c2450_pin_ctrl },
-#endif
-	{},
-};
-MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
-
-static struct platform_driver samsung_pinctrl_driver = {
-	.probe		= samsung_pinctrl_probe,
-	.driver = {
-		.name	= "samsung-pinctrl",
-		.owner	= THIS_MODULE,
-		.of_match_table = samsung_pinctrl_dt_match,
-	},
-};
-
-static int __init samsung_pinctrl_drv_register(void)
-{
-	/*
-	 * Register syscore ops for save/restore of registers across suspend.
-	 * It's important to ensure that this driver is running at an earlier
-	 * initcall level than any arch-specific init calls that install syscore
-	 * ops that turn off pad retention (like exynos_pm_resume).
-	 */
-	register_syscore_ops(&samsung_pinctrl_syscore_ops);
-
-	return platform_driver_register(&samsung_pinctrl_driver);
-}
-postcore_initcall(samsung_pinctrl_drv_register);
-
-static void __exit samsung_pinctrl_drv_unregister(void)
-{
-	platform_driver_unregister(&samsung_pinctrl_driver);
-}
-module_exit(samsung_pinctrl_drv_unregister);
-
-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
-MODULE_DESCRIPTION("Samsung pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-samsung.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-samsung.h
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-samsung.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-samsung.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,267 +0,0 @@
-/*
- * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- *		http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __PINCTRL_SAMSUNG_H
-#define __PINCTRL_SAMSUNG_H
-
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/machine.h>
-
-#include <linux/gpio.h>
-
-/* pinmux function number for pin as gpio output line */
-#define FUNC_OUTPUT	0x1
-
-/**
- * enum pincfg_type - possible pin configuration types supported.
- * @PINCFG_TYPE_FUNC: Function configuration.
- * @PINCFG_TYPE_DAT: Pin value configuration.
- * @PINCFG_TYPE_PUD: Pull up/down configuration.
- * @PINCFG_TYPE_DRV: Drive strength configuration.
- * @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
- * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
- */
-enum pincfg_type {
-	PINCFG_TYPE_FUNC,
-	PINCFG_TYPE_DAT,
-	PINCFG_TYPE_PUD,
-	PINCFG_TYPE_DRV,
-	PINCFG_TYPE_CON_PDN,
-	PINCFG_TYPE_PUD_PDN,
-
-	PINCFG_TYPE_NUM
-};
-
-/*
- * pin configuration (pull up/down and drive strength) type and its value are
- * packed together into a 16-bits. The upper 8-bits represent the configuration
- * type and the lower 8-bits hold the value of the configuration type.
- */
-#define PINCFG_TYPE_MASK		0xFF
-#define PINCFG_VALUE_SHIFT		8
-#define PINCFG_VALUE_MASK		(0xFF << PINCFG_VALUE_SHIFT)
-#define PINCFG_PACK(type, value)	(((value) << PINCFG_VALUE_SHIFT) | type)
-#define PINCFG_UNPACK_TYPE(cfg)		((cfg) & PINCFG_TYPE_MASK)
-#define PINCFG_UNPACK_VALUE(cfg)	(((cfg) & PINCFG_VALUE_MASK) >> \
-						PINCFG_VALUE_SHIFT)
-/**
- * enum eint_type - possible external interrupt types.
- * @EINT_TYPE_NONE: bank does not support external interrupts
- * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
- * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
- * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
- *
- * Samsung GPIO controller groups all the available pins into banks. The pins
- * in a pin bank can support external gpio interrupts or external wakeup
- * interrupts or no interrupts at all. From a software perspective, the only
- * difference between external gpio and external wakeup interrupts is that
- * the wakeup interrupts can additionally wakeup the system if it is in
- * suspended state.
- */
-enum eint_type {
-	EINT_TYPE_NONE,
-	EINT_TYPE_GPIO,
-	EINT_TYPE_WKUP,
-	EINT_TYPE_WKUP_MUX,
-};
-
-/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
-#define PIN_NAME_LENGTH	10
-
-#define PIN_GROUP(n, p, f)				\
-	{						\
-		.name		= n,			\
-		.pins		= p,			\
-		.num_pins	= ARRAY_SIZE(p),	\
-		.func		= f			\
-	}
-
-#define PMX_FUNC(n, g)					\
-	{						\
-		.name		= n,			\
-		.groups		= g,			\
-		.num_groups	= ARRAY_SIZE(g),	\
-	}
-
-struct samsung_pinctrl_drv_data;
-
-/**
- * struct samsung_pin_bank_type: pin bank type description
- * @fld_width: widths of configuration bitfields (0 if unavailable)
- * @reg_offset: offsets of configuration registers (don't care of width is 0)
- */
-struct samsung_pin_bank_type {
-	u8 fld_width[PINCFG_TYPE_NUM];
-	u8 reg_offset[PINCFG_TYPE_NUM];
-};
-
-/**
- * struct samsung_pin_bank: represent a controller pin-bank.
- * @type: type of the bank (register offsets and bitfield widths)
- * @pctl_offset: starting offset of the pin-bank registers.
- * @pin_base: starting pin number of the bank.
- * @nr_pins: number of pins included in this bank.
- * @eint_func: function to set in CON register to configure pin as EINT.
- * @eint_type: type of the external interrupt supported by the bank.
- * @eint_mask: bit mask of pins which support EINT function.
- * @name: name to be prefixed for each pin in this pin bank.
- * @of_node: OF node of the bank.
- * @drvdata: link to controller driver data
- * @irq_domain: IRQ domain of the bank.
- * @gpio_chip: GPIO chip of the bank.
- * @grange: linux gpio pin range supported by this bank.
- * @slock: spinlock protecting bank registers
- * @pm_save: saved register values during suspend
- */
-struct samsung_pin_bank {
-	struct samsung_pin_bank_type *type;
-	u32		pctl_offset;
-	u32		pin_base;
-	u8		nr_pins;
-	u8		eint_func;
-	enum eint_type	eint_type;
-	u32		eint_mask;
-	u32		eint_offset;
-	char		*name;
-	void		*soc_priv;
-	struct device_node *of_node;
-	struct samsung_pinctrl_drv_data *drvdata;
-	struct irq_domain *irq_domain;
-	struct gpio_chip gpio_chip;
-	struct pinctrl_gpio_range grange;
-	spinlock_t slock;
-
-	u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
-};
-
-/**
- * struct samsung_pin_ctrl: represent a pin controller.
- * @pin_banks: list of pin banks included in this controller.
- * @nr_banks: number of pin banks.
- * @base: starting system wide pin number.
- * @nr_pins: number of pins supported by the controller.
- * @geint_con: offset of the ext-gpio controller registers.
- * @geint_mask: offset of the ext-gpio interrupt mask registers.
- * @geint_pend: offset of the ext-gpio interrupt pending registers.
- * @weint_con: offset of the ext-wakeup controller registers.
- * @weint_mask: offset of the ext-wakeup interrupt mask registers.
- * @weint_pend: offset of the ext-wakeup interrupt pending registers.
- * @svc: offset of the interrupt service register.
- * @eint_gpio_init: platform specific callback to setup the external gpio
- *	interrupts for the controller.
- * @eint_wkup_init: platform specific callback to setup the external wakeup
- *	interrupts for the controller.
- * @label: for debug information.
- */
-struct samsung_pin_ctrl {
-	struct samsung_pin_bank	*pin_banks;
-	u32		nr_banks;
-
-	u32		base;
-	u32		nr_pins;
-
-	u32		geint_con;
-	u32		geint_mask;
-	u32		geint_pend;
-
-	u32		weint_con;
-	u32		weint_mask;
-	u32		weint_pend;
-
-	u32		svc;
-
-	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
-	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
-	void		(*suspend)(struct samsung_pinctrl_drv_data *);
-	void		(*resume)(struct samsung_pinctrl_drv_data *);
-
-	char		*label;
-};
-
-/**
- * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
- * @node: global list node
- * @virt_base: register base address of the controller.
- * @dev: device instance representing the controller.
- * @irq: interrpt number used by the controller to notify gpio interrupts.
- * @ctrl: pin controller instance managed by the driver.
- * @pctl: pin controller descriptor registered with the pinctrl subsystem.
- * @pctl_dev: cookie representing pinctrl device instance.
- * @pin_groups: list of pin groups available to the driver.
- * @nr_groups: number of such pin groups.
- * @pmx_functions: list of pin functions available to the driver.
- * @nr_function: number of such pin functions.
- */
-struct samsung_pinctrl_drv_data {
-	struct list_head		node;
-	void __iomem			*virt_base;
-	struct device			*dev;
-	int				irq;
-
-	struct samsung_pin_ctrl		*ctrl;
-	struct pinctrl_desc		pctl;
-	struct pinctrl_dev		*pctl_dev;
-
-	const struct samsung_pin_group	*pin_groups;
-	unsigned int			nr_groups;
-	const struct samsung_pmx_func	*pmx_functions;
-	unsigned int			nr_functions;
-};
-
-/**
- * struct samsung_pin_group: represent group of pins of a pinmux function.
- * @name: name of the pin group, used to lookup the group.
- * @pins: the pins included in this group.
- * @num_pins: number of pins included in this group.
- * @func: the function number to be programmed when selected.
- */
-struct samsung_pin_group {
-	const char		*name;
-	const unsigned int	*pins;
-	u8			num_pins;
-	u8			func;
-};
-
-/**
- * struct samsung_pmx_func: represent a pin function.
- * @name: name of the pin function, used to lookup the function.
- * @groups: one or more names of pin groups that provide this function.
- * @num_groups: number of groups included in @groups.
- */
-struct samsung_pmx_func {
-	const char		*name;
-	const char		**groups;
-	u8			num_groups;
-};
-
-/* list of all exported SoC specific data */
-extern struct samsung_pin_ctrl exynos3250_pin_ctrl[];
-extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
-extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
-extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
-extern struct samsung_pin_ctrl exynos5260_pin_ctrl[];
-extern struct samsung_pin_ctrl exynos5420_pin_ctrl[];
-extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
-extern struct samsung_pin_ctrl s3c2412_pin_ctrl[];
-extern struct samsung_pin_ctrl s3c2416_pin_ctrl[];
-extern struct samsung_pin_ctrl s3c2440_pin_ctrl[];
-extern struct samsung_pin_ctrl s3c2450_pin_ctrl[];
-extern struct samsung_pin_ctrl s5pv210_pin_ctrl[];
-
-#endif /* __PINCTRL_SAMSUNG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-single.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-single.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-single.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-single.c	2014-09-28 17:29:07.000000000 -0400
@@ -488,61 +488,6 @@ static int pcs_enable(struct pinctrl_dev
 	return 0;
 }
 
-static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
-					unsigned group)
-{
-	struct pcs_device *pcs;
-	struct pcs_function *func;
-	int i;
-
-	pcs = pinctrl_dev_get_drvdata(pctldev);
-	/* If function mask is null, needn't disable it. */
-	if (!pcs->fmask)
-		return;
-
-	func = radix_tree_lookup(&pcs->ftree, fselector);
-	if (!func) {
-		dev_err(pcs->dev, "%s could not find function%i\n",
-			__func__, fselector);
-		return;
-	}
-
-	/*
-	 * Ignore disable if function-off is not specified. Some hardware
-	 * does not have clearly defined disable function. For pin specific
-	 * off modes, you can use alternate named states as described in
-	 * pinctrl-bindings.txt.
-	 */
-	if (pcs->foff == PCS_OFF_DISABLED) {
-		dev_dbg(pcs->dev, "ignoring disable for %s function%i\n",
-			func->name, fselector);
-		return;
-	}
-
-	dev_dbg(pcs->dev, "disabling function%i %s\n",
-		fselector, func->name);
-
-	for (i = 0; i < func->nvals; i++) {
-		struct pcs_func_vals *vals;
-		unsigned long flags;
-		unsigned val, mask;
-
-		vals = &func->vals[i];
-		raw_spin_lock_irqsave(&pcs->lock, flags);
-		val = pcs->read(vals->reg);
-
-		if (pcs->bits_per_mux)
-			mask = vals->mask;
-		else
-			mask = pcs->fmask;
-
-		val &= ~mask;
-		val |= pcs->foff << pcs->fshift;
-		pcs->write(val, vals->reg);
-		raw_spin_unlock_irqrestore(&pcs->lock, flags);
-	}
-}
-
 static int pcs_request_gpio(struct pinctrl_dev *pctldev,
 			    struct pinctrl_gpio_range *range, unsigned pin)
 {
@@ -575,7 +520,6 @@ static const struct pinmux_ops pcs_pinmu
 	.get_function_name = pcs_get_function_name,
 	.get_function_groups = pcs_get_function_groups,
 	.enable = pcs_enable,
-	.disable = pcs_disable,
 	.gpio_request_enable = pcs_request_gpio,
 };
 
@@ -836,7 +780,7 @@ static int pcs_add_pin(struct pcs_device
 
 	pin = &pcs->pins.pa[i];
 	pn = &pcs->names[i];
-	sprintf(pn->name, "%lx.%d",
+	sprintf(pn->name, "%lx.%u",
 		(unsigned long)pcs->res->start + offset, pin_pos);
 	pin->name = pn->name;
 	pin->number = i;
@@ -1739,11 +1683,10 @@ static void pcs_irq_chain_handler(unsign
 {
 	struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip;
-	int res;
 
 	chip = irq_get_chip(irq);
 	chained_irq_enter(chip, desc);
-	res = pcs_irq_handle(pcs_soc);
+	pcs_irq_handle(pcs_soc);
 	/* REVISIT: export and add handle_bad_irq(irq, desc)? */
 	chained_irq_exit(chip, desc);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-st.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-st.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-st.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-st.c	2014-09-28 17:29:07.000000000 -0400
@@ -930,11 +930,6 @@ static int st_pmx_enable(struct pinctrl_
 	return 0;
 }
 
-static void st_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
-		unsigned group)
-{
-}
-
 static int st_pmx_set_gpio_direction(struct pinctrl_dev *pctldev,
 			struct pinctrl_gpio_range *range, unsigned gpio,
 			bool input)
@@ -957,7 +952,6 @@ static struct pinmux_ops st_pmxops = {
 	.get_function_name	= st_pmx_get_fname,
 	.get_function_groups	= st_pmx_get_groups,
 	.enable			= st_pmx_enable,
-	.disable		= st_pmx_disable,
 	.gpio_set_direction	= st_pmx_set_gpio_direction,
 };
 
@@ -1178,9 +1172,7 @@ static int st_pctl_dt_parse_groups(struc
 	const __be32 *list;
 	struct property *pp;
 	struct st_pinconf *conf;
-	phandle phandle;
 	struct device_node *pins;
-	u32 pin;
 	int i = 0, npins = 0, nr_props;
 
 	pins = of_get_child_by_name(np, "st,pins");
@@ -1218,8 +1210,8 @@ static int st_pctl_dt_parse_groups(struc
 		conf = &grp->pin_conf[i];
 
 		/* bank & offset */
-		phandle = be32_to_cpup(list++);
-		pin = be32_to_cpup(list++);
+		be32_to_cpup(list++);
+		be32_to_cpup(list++);
 		conf->pin = of_get_named_gpio(pins, pp->name, 0);
 		conf->name = pp->name;
 		grp->pins[i] = conf->pin;
@@ -1256,7 +1248,7 @@ static int st_pctl_parse_functions(struc
 	func = &info->functions[index];
 	func->name = np->name;
 	func->ngroups = of_get_child_count(np);
-	if (func->ngroups <= 0) {
+	if (func->ngroups == 0) {
 		dev_err(info->dev, "No groups defined\n");
 		return -EINVAL;
 	}
@@ -1454,6 +1446,7 @@ static struct irq_chip st_gpio_irqchip =
 	.irq_mask	= st_gpio_irq_mask,
 	.irq_unmask	= st_gpio_irq_unmask,
 	.irq_set_type	= st_gpio_irq_set_type,
+	.flags		= IRQCHIP_SKIP_SET_WAKE,
 };
 
 static int st_gpiolib_register_bank(struct st_pinctrl *info,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tb10x.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tb10x.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tb10x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tb10x.c	2014-09-28 17:29:07.000000000 -0400
@@ -738,22 +738,6 @@ static int tb10x_pctl_enable(struct pinc
 	return 0;
 }
 
-static void tb10x_pctl_disable(struct pinctrl_dev *pctl,
-			unsigned func_selector, unsigned group_selector)
-{
-	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
-	const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
-
-	if (grp->port < 0)
-		return;
-
-	mutex_lock(&state->mutex);
-
-	state->ports[grp->port].count--;
-
-	mutex_unlock(&state->mutex);
-}
-
 static struct pinmux_ops tb10x_pinmux_ops = {
 	.get_functions_count = tb10x_get_functions_count,
 	.get_function_name = tb10x_get_function_name,
@@ -761,7 +745,6 @@ static struct pinmux_ops tb10x_pinmux_op
 	.gpio_request_enable = tb10x_gpio_request_enable,
 	.gpio_disable_free = tb10x_gpio_disable_free,
 	.enable = tb10x_pctl_enable,
-	.disable = tb10x_pctl_disable,
 };
 
 static struct pinctrl_desc tb10x_pindesc = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tegra.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tegra.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tegra.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -290,24 +290,11 @@ static int tegra_pinctrl_enable(struct p
 	return 0;
 }
 
-static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
-				  unsigned function, unsigned group)
-{
-	struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-	const struct tegra_pingroup *g;
-
-	g = &pmx->soc->groups[group];
-
-	if (WARN_ON(g->mux_reg < 0))
-		return;
-}
-
 static const struct pinmux_ops tegra_pinmux_ops = {
 	.get_functions_count = tegra_pinctrl_get_funcs_count,
 	.get_function_name = tegra_pinctrl_get_func_name,
 	.get_function_groups = tegra_pinctrl_get_func_groups,
 	.enable = tegra_pinctrl_enable,
-	.disable = tegra_pinctrl_disable,
 };
 
 static int tegra_pinconf_reg(struct tegra_pmx *pmx,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tegra-xusb.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tegra-xusb.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tegra-xusb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tegra-xusb.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,974 @@
+/*
+ * Copyright (c) 2014, 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+struct tegra_xusb_padctl_function {
+	const char *name;
+	const char * const *groups;
+	unsigned int num_groups;
+};
+
+struct tegra_xusb_padctl_group {
+	const unsigned int *funcs;
+	unsigned int num_funcs;
+};
+
+struct tegra_xusb_padctl_soc {
+	const struct pinctrl_pin_desc *pins;
+	unsigned int num_pins;
+
+	const struct tegra_xusb_padctl_function *functions;
+	unsigned int num_functions;
+
+	const struct tegra_xusb_padctl_lane *lanes;
+	unsigned int num_lanes;
+};
+
+struct tegra_xusb_padctl_lane {
+	const char *name;
+
+	unsigned int offset;
+	unsigned int shift;
+	unsigned int mask;
+	unsigned int iddq;
+
+	const unsigned int *funcs;
+	unsigned int num_funcs;
+};
+
+struct tegra_xusb_padctl {
+	struct device *dev;
+	void __iomem *regs;
+	struct mutex lock;
+	struct reset_control *rst;
+
+	const struct tegra_xusb_padctl_soc *soc;
+	struct pinctrl_dev *pinctrl;
+	struct pinctrl_desc desc;
+
+	struct phy_provider *provider;
+	struct phy *phys[2];
+
+	unsigned int enable;
+};
+
+static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
+				 unsigned long offset)
+{
+	writel(value, padctl->regs + offset);
+}
+
+static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
+			       unsigned long offset)
+{
+	return readl(padctl->regs + offset);
+}
+
+static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+	return padctl->soc->num_pins;
+}
+
+static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
+						    unsigned int group)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+	return padctl->soc->pins[group].name;
+}
+
+enum tegra_xusb_padctl_param {
+	TEGRA_XUSB_PADCTL_IDDQ,
+};
+
+static const struct tegra_xusb_padctl_property {
+	const char *name;
+	enum tegra_xusb_padctl_param param;
+} properties[] = {
+	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
+};
+
+#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
+#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
+#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
+
+static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
+					   struct device_node *np,
+					   struct pinctrl_map **maps,
+					   unsigned int *reserved_maps,
+					   unsigned int *num_maps)
+{
+	unsigned int i, reserve = 0, num_configs = 0;
+	unsigned long config, *configs = NULL;
+	const char *function, *group;
+	struct property *prop;
+	int err = 0;
+	u32 value;
+
+	err = of_property_read_string(np, "nvidia,function", &function);
+	if (err < 0) {
+		if (err != -EINVAL)
+			return err;
+
+		function = NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(properties); i++) {
+		err = of_property_read_u32(np, properties[i].name, &value);
+		if (err < 0) {
+			if (err == -EINVAL)
+				continue;
+
+			return err;
+		}
+
+		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
+
+		err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
+					       &num_configs, config);
+		if (err < 0)
+			return err;
+	}
+
+	if (function)
+		reserve++;
+
+	if (num_configs)
+		reserve++;
+
+	err = of_property_count_strings(np, "nvidia,lanes");
+	if (err < 0)
+		return err;
+
+	reserve *= err;
+
+	err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
+					num_maps, reserve);
+	if (err < 0)
+		return err;
+
+	of_property_for_each_string(np, "nvidia,lanes", prop, group) {
+		if (function) {
+			err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
+					reserved_maps, num_maps, group,
+					function);
+			if (err < 0)
+				return err;
+		}
+
+		if (num_configs) {
+			err = pinctrl_utils_add_map_configs(padctl->pinctrl,
+					maps, reserved_maps, num_maps, group,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_GROUP);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
+					    struct device_node *parent,
+					    struct pinctrl_map **maps,
+					    unsigned int *num_maps)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+	unsigned int reserved_maps = 0;
+	struct device_node *np;
+	int err;
+
+	*num_maps = 0;
+	*maps = NULL;
+
+	for_each_child_of_node(parent, np) {
+		err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
+						      &reserved_maps,
+						      num_maps);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
+	.get_groups_count = tegra_xusb_padctl_get_groups_count,
+	.get_group_name = tegra_xusb_padctl_get_group_name,
+	.dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
+	.dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+	return padctl->soc->num_functions;
+}
+
+static const char *
+tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
+				    unsigned int function)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+	return padctl->soc->functions[function].name;
+}
+
+static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
+						 unsigned int function,
+						 const char * const **groups,
+						 unsigned * const num_groups)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+	*num_groups = padctl->soc->functions[function].num_groups;
+	*groups = padctl->soc->functions[function].groups;
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl,
+					   unsigned int function,
+					   unsigned int group)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+	const struct tegra_xusb_padctl_lane *lane;
+	unsigned int i;
+	u32 value;
+
+	lane = &padctl->soc->lanes[group];
+
+	for (i = 0; i < lane->num_funcs; i++)
+		if (lane->funcs[i] == function)
+			break;
+
+	if (i >= lane->num_funcs)
+		return -EINVAL;
+
+	value = padctl_readl(padctl, lane->offset);
+	value &= ~(lane->mask << lane->shift);
+	value |= i << lane->shift;
+	padctl_writel(padctl, value, lane->offset);
+
+	return 0;
+}
+
+static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
+	.get_functions_count = tegra_xusb_padctl_get_functions_count,
+	.get_function_name = tegra_xusb_padctl_get_function_name,
+	.get_function_groups = tegra_xusb_padctl_get_function_groups,
+	.enable = tegra_xusb_padctl_pinmux_enable,
+};
+
+static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
+					       unsigned int group,
+					       unsigned long *config)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+	const struct tegra_xusb_padctl_lane *lane;
+	enum tegra_xusb_padctl_param param;
+	u32 value;
+
+	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
+	lane = &padctl->soc->lanes[group];
+
+	switch (param) {
+	case TEGRA_XUSB_PADCTL_IDDQ:
+		/* lanes with iddq == 0 don't support this parameter */
+		if (lane->iddq == 0)
+			return -EINVAL;
+
+		value = padctl_readl(padctl, lane->offset);
+
+		if (value & BIT(lane->iddq))
+			value = 0;
+		else
+			value = 1;
+
+		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
+		break;
+
+	default:
+		dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
+			param);
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
+					       unsigned int group,
+					       unsigned long *configs,
+					       unsigned int num_configs)
+{
+	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+	const struct tegra_xusb_padctl_lane *lane;
+	enum tegra_xusb_padctl_param param;
+	unsigned long value;
+	unsigned int i;
+	u32 regval;
+
+	lane = &padctl->soc->lanes[group];
+
+	for (i = 0; i < num_configs; i++) {
+		param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
+		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
+
+		switch (param) {
+		case TEGRA_XUSB_PADCTL_IDDQ:
+			/* lanes with iddq == 0 don't support this parameter */
+			if (lane->iddq == 0)
+				return -EINVAL;
+
+			regval = padctl_readl(padctl, lane->offset);
+
+			if (value)
+				regval &= ~BIT(lane->iddq);
+			else
+				regval |= BIT(lane->iddq);
+
+			padctl_writel(padctl, regval, lane->offset);
+			break;
+
+		default:
+			dev_err(padctl->dev,
+				"invalid configuration parameter: %04x\n",
+				param);
+			return -ENOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const char *strip_prefix(const char *s)
+{
+	const char *comma = strchr(s, ',');
+	if (!comma)
+		return s;
+
+	return comma + 1;
+}
+
+static void
+tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
+					 struct seq_file *s,
+					 unsigned int group)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(properties); i++) {
+		unsigned long config, value;
+		int err;
+
+		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
+
+		err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
+							  &config);
+		if (err < 0)
+			continue;
+
+		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+		seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
+			   value);
+	}
+}
+
+static void
+tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
+					  struct seq_file *s,
+					  unsigned long config)
+{
+	enum tegra_xusb_padctl_param param;
+	const char *name = "unknown";
+	unsigned long value;
+	unsigned int i;
+
+	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
+	value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+	for (i = 0; i < ARRAY_SIZE(properties); i++) {
+		if (properties[i].param == param) {
+			name = properties[i].name;
+			break;
+		}
+	}
+
+	seq_printf(s, "%s=%lu", strip_prefix(name), value);
+}
+#endif
+
+static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
+	.pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
+	.pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+	.pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
+	.pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
+#endif
+};
+
+static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+{
+	u32 value;
+
+	mutex_lock(&padctl->lock);
+
+	if (padctl->enable++ > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+	u32 value;
+
+	mutex_lock(&padctl->lock);
+
+	if (WARN_ON(padctl->enable == 0))
+		goto out;
+
+	if (--padctl->enable > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static int tegra_xusb_phy_init(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+	return tegra_xusb_padctl_enable(padctl);
+}
+
+static int tegra_xusb_phy_exit(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+	return tegra_xusb_padctl_disable(padctl);
+}
+
+static int pcie_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	unsigned long timeout;
+	int err = -ETIMEDOUT;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
+		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
+		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	timeout = jiffies + msecs_to_jiffies(50);
+
+	while (time_before(jiffies, timeout)) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
+			err = 0;
+			break;
+		}
+
+		usleep_range(100, 200);
+	}
+
+	return err;
+}
+
+static int pcie_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	return 0;
+}
+
+static const struct phy_ops pcie_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = pcie_phy_power_on,
+	.power_off = pcie_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int sata_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	unsigned long timeout;
+	int err = -ETIMEDOUT;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	timeout = jiffies + msecs_to_jiffies(50);
+
+	while (time_before(jiffies, timeout)) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
+			err = 0;
+			break;
+		}
+
+		usleep_range(100, 200);
+	}
+
+	return err;
+}
+
+static int sata_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+	return 0;
+}
+
+static const struct phy_ops sata_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = sata_phy_power_on,
+	.power_off = sata_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
+					   struct of_phandle_args *args)
+{
+	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+	unsigned int index = args->args[0];
+
+	if (args->args_count <= 0)
+		return ERR_PTR(-EINVAL);
+
+	if (index >= ARRAY_SIZE(padctl->phys))
+		return ERR_PTR(-EINVAL);
+
+	return padctl->phys[index];
+}
+
+#define PIN_OTG_0   0
+#define PIN_OTG_1   1
+#define PIN_OTG_2   2
+#define PIN_ULPI_0  3
+#define PIN_HSIC_0  4
+#define PIN_HSIC_1  5
+#define PIN_PCIE_0  6
+#define PIN_PCIE_1  7
+#define PIN_PCIE_2  8
+#define PIN_PCIE_3  9
+#define PIN_PCIE_4 10
+#define PIN_SATA_0 11
+
+static const struct pinctrl_pin_desc tegra124_pins[] = {
+	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
+	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
+	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
+	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
+	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
+	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
+	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
+	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
+	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
+	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
+	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
+	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
+};
+
+static const char * const tegra124_snps_groups[] = {
+	"otg-0",
+	"otg-1",
+	"otg-2",
+	"ulpi-0",
+	"hsic-0",
+	"hsic-1",
+};
+
+static const char * const tegra124_xusb_groups[] = {
+	"otg-0",
+	"otg-1",
+	"otg-2",
+	"ulpi-0",
+	"hsic-0",
+	"hsic-1",
+};
+
+static const char * const tegra124_uart_groups[] = {
+	"otg-0",
+	"otg-1",
+	"otg-2",
+};
+
+static const char * const tegra124_pcie_groups[] = {
+	"pcie-0",
+	"pcie-1",
+	"pcie-2",
+	"pcie-3",
+	"pcie-4",
+	"sata-0",
+};
+
+static const char * const tegra124_usb3_groups[] = {
+	"pcie-0",
+	"pcie-1",
+	"pcie-2",
+	"pcie-3",
+	"pcie-4",
+	"sata-0",
+};
+
+static const char * const tegra124_sata_groups[] = {
+	"pcie-0",
+	"pcie-1",
+	"pcie-2",
+	"pcie-3",
+	"pcie-4",
+	"sata-0",
+};
+
+static const char * const tegra124_rsvd_groups[] = {
+	"otg-0",
+	"otg-1",
+	"otg-2",
+	"pcie-0",
+	"pcie-1",
+	"pcie-2",
+	"pcie-3",
+	"pcie-4",
+	"sata-0",
+};
+
+#define TEGRA124_FUNCTION(_name)					\
+	{								\
+		.name = #_name,						\
+		.num_groups = ARRAY_SIZE(tegra124_##_name##_groups),	\
+		.groups = tegra124_##_name##_groups,			\
+	}
+
+static struct tegra_xusb_padctl_function tegra124_functions[] = {
+	TEGRA124_FUNCTION(snps),
+	TEGRA124_FUNCTION(xusb),
+	TEGRA124_FUNCTION(uart),
+	TEGRA124_FUNCTION(pcie),
+	TEGRA124_FUNCTION(usb3),
+	TEGRA124_FUNCTION(sata),
+	TEGRA124_FUNCTION(rsvd),
+};
+
+enum tegra124_function {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+	TEGRA124_FUNC_UART,
+	TEGRA124_FUNC_PCIE,
+	TEGRA124_FUNC_USB3,
+	TEGRA124_FUNC_SATA,
+	TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_otg_functions[] = {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+	TEGRA124_FUNC_UART,
+	TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_usb_functions[] = {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+};
+
+static const unsigned int tegra124_pci_functions[] = {
+	TEGRA124_FUNC_PCIE,
+	TEGRA124_FUNC_USB3,
+	TEGRA124_FUNC_SATA,
+	TEGRA124_FUNC_RSVD,
+};
+
+#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
+	{								\
+		.name = _name,						\
+		.offset = _offset,					\
+		.shift = _shift,					\
+		.mask = _mask,						\
+		.iddq = _iddq,						\
+		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
+		.funcs = tegra124_##_funcs##_functions,			\
+	}
+
+static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
+	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
+	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
+	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
+	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
+	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
+	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
+	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
+	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
+	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
+	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
+};
+
+static const struct tegra_xusb_padctl_soc tegra124_soc = {
+	.num_pins = ARRAY_SIZE(tegra124_pins),
+	.pins = tegra124_pins,
+	.num_functions = ARRAY_SIZE(tegra124_functions),
+	.functions = tegra124_functions,
+	.num_lanes = ARRAY_SIZE(tegra124_lanes),
+	.lanes = tegra124_lanes,
+};
+
+static const struct of_device_id tegra_xusb_padctl_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
+
+static int tegra_xusb_padctl_probe(struct platform_device *pdev)
+{
+	struct tegra_xusb_padctl *padctl;
+	const struct of_device_id *match;
+	struct resource *res;
+	struct phy *phy;
+	int err;
+
+	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
+	if (!padctl)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, padctl);
+	mutex_init(&padctl->lock);
+	padctl->dev = &pdev->dev;
+
+	match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
+	padctl->soc = match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	padctl->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(padctl->regs))
+		return PTR_ERR(padctl->regs);
+
+	padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(padctl->rst))
+		return PTR_ERR(padctl->rst);
+
+	err = reset_control_deassert(padctl->rst);
+	if (err < 0)
+		return err;
+
+	memset(&padctl->desc, 0, sizeof(padctl->desc));
+	padctl->desc.name = dev_name(padctl->dev);
+	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
+	padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
+	padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
+	padctl->desc.owner = THIS_MODULE;
+
+	padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
+	if (!padctl->pinctrl) {
+		dev_err(&pdev->dev, "failed to register pincontrol\n");
+		err = -ENODEV;
+		goto reset;
+	}
+
+	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		err = PTR_ERR(phy);
+		goto unregister;
+	}
+
+	padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
+	phy_set_drvdata(phy, padctl);
+
+	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		err = PTR_ERR(phy);
+		goto unregister;
+	}
+
+	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
+	phy_set_drvdata(phy, padctl);
+
+	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
+							 tegra_xusb_padctl_xlate);
+	if (IS_ERR(padctl->provider)) {
+		err = PTR_ERR(padctl->provider);
+		dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
+		goto unregister;
+	}
+
+	return 0;
+
+unregister:
+	pinctrl_unregister(padctl->pinctrl);
+reset:
+	reset_control_assert(padctl->rst);
+	return err;
+}
+
+static int tegra_xusb_padctl_remove(struct platform_device *pdev)
+{
+	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
+	int err;
+
+	pinctrl_unregister(padctl->pinctrl);
+
+	err = reset_control_assert(padctl->rst);
+	if (err < 0)
+		dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
+
+	return err;
+}
+
+static struct platform_driver tegra_xusb_padctl_driver = {
+	.driver = {
+		.name = "tegra-xusb-padctl",
+		.of_match_table = tegra_xusb_padctl_of_match,
+	},
+	.probe = tegra_xusb_padctl_probe,
+	.remove = tegra_xusb_padctl_remove,
+};
+module_platform_driver(tegra_xusb_padctl_driver);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tz1090.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tz1090.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tz1090.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tz1090.c	2014-09-28 17:29:07.000000000 -0400
@@ -1479,63 +1479,6 @@ mux_pins:
 }
 
 /**
- * tz1090_pinctrl_disable() - Disable a function on a pin group.
- * @pctldev:		Pin control data
- * @function:		Function index to disable
- * @group:		Group index to disable
- *
- * Disable a particular function on a group of pins. The per GPIO pin pseudo pin
- * groups can be used (in which case the pin will be taken out of peripheral
- * mode. Some convenience pin groups can also be used in which case the effect
- * is the same as enabling the function on each individual pin in the group.
- */
-static void tz1090_pinctrl_disable(struct pinctrl_dev *pctldev,
-				   unsigned int function, unsigned int group)
-{
-	struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-	struct tz1090_pingroup *grp;
-	unsigned int pin_num, mux_group, i, npins;
-	const unsigned int *pins;
-
-	/* group of pins? */
-	if (group < ARRAY_SIZE(tz1090_groups)) {
-		grp = &tz1090_groups[group];
-		npins = grp->npins;
-		pins = grp->pins;
-		/*
-		 * All pins in the group must belong to the same mux group,
-		 * which allows us to just use the mux group of the first pin.
-		 * By explicitly listing permitted pingroups for each function
-		 * the pinmux core should ensure this is always the case.
-		 */
-	} else {
-		pin_num = group - ARRAY_SIZE(tz1090_groups);
-		npins = 1;
-		pins = &pin_num;
-	}
-	mux_group = tz1090_mux_pins[*pins];
-
-	/* no mux group, but can still be individually muxed to peripheral */
-	if (mux_group >= TZ1090_MUX_GROUP_MAX) {
-		if (function == TZ1090_MUX_PERIP)
-			goto unmux_pins;
-		return;
-	}
-
-	/* mux group already set to a different function? */
-	grp = &tz1090_mux_groups[mux_group];
-	dev_dbg(pctldev->dev, "%s: unmuxing %u pin(s) in '%s' from '%s'\n",
-		__func__, npins, grp->name, tz1090_functions[function].name);
-
-	/* subtract pins from ref count and unmux individually */
-	WARN_ON(grp->func_count < npins);
-	grp->func_count -= npins;
-unmux_pins:
-	for (i = 0; i < npins; ++i)
-		tz1090_pinctrl_perip_select(pmx, pins[i], false);
-}
-
-/**
  * tz1090_pinctrl_gpio_request_enable() - Put pin in GPIO mode.
  * @pctldev:		Pin control data
  * @range:		GPIO range
@@ -1575,7 +1518,6 @@ static struct pinmux_ops tz1090_pinmux_o
 	.get_function_name	= tz1090_pinctrl_get_func_name,
 	.get_function_groups	= tz1090_pinctrl_get_func_groups,
 	.enable			= tz1090_pinctrl_enable,
-	.disable		= tz1090_pinctrl_disable,
 	.gpio_request_enable	= tz1090_pinctrl_gpio_request_enable,
 	.gpio_disable_free	= tz1090_pinctrl_gpio_disable_free,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tz1090-pdc.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tz1090-pdc.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-tz1090-pdc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-tz1090-pdc.c	2014-09-28 17:29:07.000000000 -0400
@@ -574,33 +574,6 @@ static int tz1090_pdc_pinctrl_enable(str
 	return 0;
 }
 
-static void tz1090_pdc_pinctrl_disable(struct pinctrl_dev *pctldev,
-				       unsigned int function,
-				       unsigned int group)
-{
-	struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-	const struct tz1090_pdc_pingroup *grp = &tz1090_pdc_groups[group];
-
-	dev_dbg(pctldev->dev, "%s(func=%u (%s), group=%u (%s))\n",
-		__func__,
-		function, tz1090_pdc_functions[function].name,
-		group, tz1090_pdc_groups[group].name);
-
-	/* is it even a mux? */
-	if (grp->drv)
-		return;
-
-	/* does this group even control the function? */
-	if (function != grp->func)
-		return;
-
-	/* record the pin being unmuxed and update mux bit */
-	spin_lock(&pmx->lock);
-	pmx->mux_en &= ~BIT(grp->pins[0]);
-	tz1090_pdc_pinctrl_mux(pmx, grp);
-	spin_unlock(&pmx->lock);
-}
-
 static const struct tz1090_pdc_pingroup *find_mux_group(
 						struct tz1090_pdc_pmx *pmx,
 						unsigned int pin)
@@ -662,7 +635,6 @@ static struct pinmux_ops tz1090_pdc_pinm
 	.get_function_name	= tz1090_pdc_pinctrl_get_func_name,
 	.get_function_groups	= tz1090_pdc_pinctrl_get_func_groups,
 	.enable			= tz1090_pdc_pinctrl_enable,
-	.disable		= tz1090_pdc_pinctrl_disable,
 	.gpio_request_enable	= tz1090_pdc_pinctrl_gpio_request_enable,
 	.gpio_disable_free	= tz1090_pdc_pinctrl_gpio_disable_free,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-u300.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-u300.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinctrl-u300.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinctrl-u300.c	2014-09-28 17:29:07.000000000 -0400
@@ -970,19 +970,6 @@ static int u300_pmx_enable(struct pinctr
 	return 0;
 }
 
-static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
-			     unsigned group)
-{
-	struct u300_pmx *upmx;
-
-	/* There is nothing to do with the power pins */
-	if (selector == 0)
-		return;
-
-	upmx = pinctrl_dev_get_drvdata(pctldev);
-	u300_pmx_endisable(upmx, selector, false);
-}
-
 static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
 {
 	return ARRAY_SIZE(u300_pmx_functions);
@@ -1008,7 +995,6 @@ static const struct pinmux_ops u300_pmx_
 	.get_function_name = u300_pmx_get_func_name,
 	.get_function_groups = u300_pmx_get_groups,
 	.enable = u300_pmx_enable,
-	.disable = u300_pmx_disable,
 };
 
 static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/pinmux.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinmux.c
--- linux-libre-3.16-gnu/drivers/pinctrl/pinmux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/pinmux.c	2014-09-28 17:29:07.000000000 -0400
@@ -471,7 +471,6 @@ void pinmux_disable_setting(struct pinct
 {
 	struct pinctrl_dev *pctldev = setting->pctldev;
 	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-	const struct pinmux_ops *ops = pctldev->desc->pmxops;
 	int ret = 0;
 	const unsigned *pins = NULL;
 	unsigned num_pins = 0;
@@ -518,9 +517,6 @@ void pinmux_disable_setting(struct pinct
 				 pins[i], desc->name, gname);
 		}
 	}
-
-	if (ops->disable)
-		ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
 }
 
 #ifdef CONFIG_DEBUG_FS
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+if (ARCH_QCOM || COMPILE_TEST)
+
+config PINCTRL_MSM
+	bool
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	select GPIOLIB_IRQCHIP
+
+config PINCTRL_APQ8064
+	tristate "Qualcomm APQ8064 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
+
+config PINCTRL_IPQ8064
+	tristate "Qualcomm IPQ8064 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
+
+config PINCTRL_MSM8960
+	tristate "Qualcomm 8960 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm 8960 platform.
+
+config PINCTRL_MSM8X74
+	tristate "Qualcomm 8x74 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm 8974 platform.
+
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/Makefile linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/Makefile
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,6 @@
+# Qualcomm pin control drivers
+obj-$(CONFIG_PINCTRL_MSM)	+= pinctrl-msm.o
+obj-$(CONFIG_PINCTRL_APQ8064)	+= pinctrl-apq8064.o
+obj-$(CONFIG_PINCTRL_IPQ8064)	+= pinctrl-ipq8064.o
+obj-$(CONFIG_PINCTRL_MSM8960)	+= pinctrl-msm8960.o
+obj-$(CONFIG_PINCTRL_MSM8X74)	+= pinctrl-msm8x74.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-apq8064.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-apq8064.c
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-apq8064.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-apq8064.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc apq8064_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+
+	PINCTRL_PIN(90, "SDC1_CLK"),
+	PINCTRL_PIN(91, "SDC1_CMD"),
+	PINCTRL_PIN(92, "SDC1_DATA"),
+	PINCTRL_PIN(93, "SDC3_CLK"),
+	PINCTRL_PIN(94, "SDC3_CMD"),
+	PINCTRL_PIN(95, "SDC3_DATA"),
+};
+
+#define DECLARE_APQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_APQ_GPIO_PINS(0);
+DECLARE_APQ_GPIO_PINS(1);
+DECLARE_APQ_GPIO_PINS(2);
+DECLARE_APQ_GPIO_PINS(3);
+DECLARE_APQ_GPIO_PINS(4);
+DECLARE_APQ_GPIO_PINS(5);
+DECLARE_APQ_GPIO_PINS(6);
+DECLARE_APQ_GPIO_PINS(7);
+DECLARE_APQ_GPIO_PINS(8);
+DECLARE_APQ_GPIO_PINS(9);
+DECLARE_APQ_GPIO_PINS(10);
+DECLARE_APQ_GPIO_PINS(11);
+DECLARE_APQ_GPIO_PINS(12);
+DECLARE_APQ_GPIO_PINS(13);
+DECLARE_APQ_GPIO_PINS(14);
+DECLARE_APQ_GPIO_PINS(15);
+DECLARE_APQ_GPIO_PINS(16);
+DECLARE_APQ_GPIO_PINS(17);
+DECLARE_APQ_GPIO_PINS(18);
+DECLARE_APQ_GPIO_PINS(19);
+DECLARE_APQ_GPIO_PINS(20);
+DECLARE_APQ_GPIO_PINS(21);
+DECLARE_APQ_GPIO_PINS(22);
+DECLARE_APQ_GPIO_PINS(23);
+DECLARE_APQ_GPIO_PINS(24);
+DECLARE_APQ_GPIO_PINS(25);
+DECLARE_APQ_GPIO_PINS(26);
+DECLARE_APQ_GPIO_PINS(27);
+DECLARE_APQ_GPIO_PINS(28);
+DECLARE_APQ_GPIO_PINS(29);
+DECLARE_APQ_GPIO_PINS(30);
+DECLARE_APQ_GPIO_PINS(31);
+DECLARE_APQ_GPIO_PINS(32);
+DECLARE_APQ_GPIO_PINS(33);
+DECLARE_APQ_GPIO_PINS(34);
+DECLARE_APQ_GPIO_PINS(35);
+DECLARE_APQ_GPIO_PINS(36);
+DECLARE_APQ_GPIO_PINS(37);
+DECLARE_APQ_GPIO_PINS(38);
+DECLARE_APQ_GPIO_PINS(39);
+DECLARE_APQ_GPIO_PINS(40);
+DECLARE_APQ_GPIO_PINS(41);
+DECLARE_APQ_GPIO_PINS(42);
+DECLARE_APQ_GPIO_PINS(43);
+DECLARE_APQ_GPIO_PINS(44);
+DECLARE_APQ_GPIO_PINS(45);
+DECLARE_APQ_GPIO_PINS(46);
+DECLARE_APQ_GPIO_PINS(47);
+DECLARE_APQ_GPIO_PINS(48);
+DECLARE_APQ_GPIO_PINS(49);
+DECLARE_APQ_GPIO_PINS(50);
+DECLARE_APQ_GPIO_PINS(51);
+DECLARE_APQ_GPIO_PINS(52);
+DECLARE_APQ_GPIO_PINS(53);
+DECLARE_APQ_GPIO_PINS(54);
+DECLARE_APQ_GPIO_PINS(55);
+DECLARE_APQ_GPIO_PINS(56);
+DECLARE_APQ_GPIO_PINS(57);
+DECLARE_APQ_GPIO_PINS(58);
+DECLARE_APQ_GPIO_PINS(59);
+DECLARE_APQ_GPIO_PINS(60);
+DECLARE_APQ_GPIO_PINS(61);
+DECLARE_APQ_GPIO_PINS(62);
+DECLARE_APQ_GPIO_PINS(63);
+DECLARE_APQ_GPIO_PINS(64);
+DECLARE_APQ_GPIO_PINS(65);
+DECLARE_APQ_GPIO_PINS(66);
+DECLARE_APQ_GPIO_PINS(67);
+DECLARE_APQ_GPIO_PINS(68);
+DECLARE_APQ_GPIO_PINS(69);
+DECLARE_APQ_GPIO_PINS(70);
+DECLARE_APQ_GPIO_PINS(71);
+DECLARE_APQ_GPIO_PINS(72);
+DECLARE_APQ_GPIO_PINS(73);
+DECLARE_APQ_GPIO_PINS(74);
+DECLARE_APQ_GPIO_PINS(75);
+DECLARE_APQ_GPIO_PINS(76);
+DECLARE_APQ_GPIO_PINS(77);
+DECLARE_APQ_GPIO_PINS(78);
+DECLARE_APQ_GPIO_PINS(79);
+DECLARE_APQ_GPIO_PINS(80);
+DECLARE_APQ_GPIO_PINS(81);
+DECLARE_APQ_GPIO_PINS(82);
+DECLARE_APQ_GPIO_PINS(83);
+DECLARE_APQ_GPIO_PINS(84);
+DECLARE_APQ_GPIO_PINS(85);
+DECLARE_APQ_GPIO_PINS(86);
+DECLARE_APQ_GPIO_PINS(87);
+DECLARE_APQ_GPIO_PINS(88);
+DECLARE_APQ_GPIO_PINS(89);
+
+static const unsigned int sdc1_clk_pins[] = { 90 };
+static const unsigned int sdc1_cmd_pins[] = { 91 };
+static const unsigned int sdc1_data_pins[] = { 92 };
+static const unsigned int sdc3_clk_pins[] = { 93 };
+static const unsigned int sdc3_cmd_pins[] = { 94 };
+static const unsigned int sdc3_data_pins[] = { 95 };
+
+#define FUNCTION(fname)					\
+	[APQ_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			APQ_MUX_gpio,			\
+			APQ_MUX_##f1,			\
+			APQ_MUX_##f2,			\
+			APQ_MUX_##f3,			\
+			APQ_MUX_##f4,			\
+			APQ_MUX_##f5,			\
+			APQ_MUX_##f6,			\
+			APQ_MUX_##f7,			\
+			APQ_MUX_##f8,			\
+			APQ_MUX_##f9,			\
+			APQ_MUX_##f10,			\
+		},					\
+		.nfuncs = 11,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x400 + 0x4 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_ack_high = 1,			\
+		.intr_target_bit = 0,			\
+		.intr_raw_status_bit = 3,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 1,		\
+	}
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+
+enum apq8064_functions {
+	APQ_MUX_cam_mclk,
+	APQ_MUX_codec_mic_i2s,
+	APQ_MUX_codec_spkr_i2s,
+	APQ_MUX_gpio,
+	APQ_MUX_gsbi1,
+	APQ_MUX_gsbi2,
+	APQ_MUX_gsbi3,
+	APQ_MUX_gsbi4,
+	APQ_MUX_gsbi4_cam_i2c,
+	APQ_MUX_gsbi5,
+	APQ_MUX_gsbi5_spi_cs1,
+	APQ_MUX_gsbi5_spi_cs2,
+	APQ_MUX_gsbi5_spi_cs3,
+	APQ_MUX_gsbi6,
+	APQ_MUX_gsbi6_spi_cs1,
+	APQ_MUX_gsbi6_spi_cs2,
+	APQ_MUX_gsbi6_spi_cs3,
+	APQ_MUX_gsbi7,
+	APQ_MUX_gsbi7_spi_cs1,
+	APQ_MUX_gsbi7_spi_cs2,
+	APQ_MUX_gsbi7_spi_cs3,
+	APQ_MUX_gsbi_cam_i2c,
+	APQ_MUX_hdmi,
+	APQ_MUX_mi2s,
+	APQ_MUX_riva_bt,
+	APQ_MUX_riva_fm,
+	APQ_MUX_riva_wlan,
+	APQ_MUX_sdc2,
+	APQ_MUX_sdc4,
+	APQ_MUX_slimbus,
+	APQ_MUX_spkr_i2s,
+	APQ_MUX_tsif1,
+	APQ_MUX_tsif2,
+	APQ_MUX_usb2_hsic,
+	APQ_MUX_NA,
+};
+
+static const char * const cam_mclk_groups[] = {
+	"gpio4" "gpio5"
+};
+static const char * const codec_mic_i2s_groups[] = {
+	"gpio34", "gpio35", "gpio36", "gpio37", "gpio38"
+};
+static const char * const codec_spkr_i2s_groups[] = {
+	"gpio39", "gpio40", "gpio41", "gpio42"
+};
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89"
+};
+static const char * const gsbi1_groups[] = {
+	"gpio18", "gpio19", "gpio20", "gpio21"
+};
+static const char * const gsbi2_groups[] = {
+	"gpio22", "gpio23", "gpio24", "gpio25"
+};
+static const char * const gsbi3_groups[] = {
+	"gpio6", "gpio7", "gpio8", "gpio9"
+};
+static const char * const gsbi4_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const gsbi4_cam_i2c_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const gsbi5_groups[] = {
+	"gpio51", "gpio52", "gpio53", "gpio54"
+};
+static const char * const gsbi5_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi5_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi5_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi6_groups[] = {
+	"gpio14", "gpio15", "gpio16", "gpio17"
+};
+static const char * const gsbi6_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi6_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi6_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi7_groups[] = {
+	"gpio82", "gpio83", "gpio84", "gpio85"
+};
+static const char * const gsbi7_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi7_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi7_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi_cam_i2c_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const hdmi_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72"
+};
+static const char * const mi2s_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33"
+};
+static const char * const riva_bt_groups[] = {
+	"gpio16", "gpio17"
+};
+static const char * const riva_fm_groups[] = {
+	"gpio14", "gpio15"
+};
+static const char * const riva_wlan_groups[] = {
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const sdc2_groups[] = {
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62"
+};
+static const char * const sdc4_groups[] = {
+	"gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const slimbus_groups[] = {
+	"gpio40", "gpio41"
+};
+static const char * const spkr_i2s_groups[] = {
+	"gpio47", "gpio48", "gpio49", "gpio50"
+};
+static const char * const tsif1_groups[] = {
+	"gpio55", "gpio56", "gpio57"
+};
+static const char * const tsif2_groups[] = {
+	"gpio58", "gpio59", "gpio60"
+};
+static const char * const usb2_hsic_groups[] = {
+	"gpio88", "gpio89"
+};
+
+static const struct msm_function apq8064_functions[] = {
+	FUNCTION(cam_mclk),
+	FUNCTION(codec_mic_i2s),
+	FUNCTION(codec_spkr_i2s),
+	FUNCTION(gpio),
+	FUNCTION(gsbi1),
+	FUNCTION(gsbi2),
+	FUNCTION(gsbi3),
+	FUNCTION(gsbi4),
+	FUNCTION(gsbi4_cam_i2c),
+	FUNCTION(gsbi5),
+	FUNCTION(gsbi5_spi_cs1),
+	FUNCTION(gsbi5_spi_cs2),
+	FUNCTION(gsbi5_spi_cs3),
+	FUNCTION(gsbi6),
+	FUNCTION(gsbi6_spi_cs1),
+	FUNCTION(gsbi6_spi_cs2),
+	FUNCTION(gsbi6_spi_cs3),
+	FUNCTION(gsbi7),
+	FUNCTION(gsbi7_spi_cs1),
+	FUNCTION(gsbi7_spi_cs2),
+	FUNCTION(gsbi7_spi_cs3),
+	FUNCTION(gsbi_cam_i2c),
+	FUNCTION(hdmi),
+	FUNCTION(mi2s),
+	FUNCTION(riva_bt),
+	FUNCTION(riva_fm),
+	FUNCTION(riva_wlan),
+	FUNCTION(sdc2),
+	FUNCTION(sdc4),
+	FUNCTION(slimbus),
+	FUNCTION(spkr_i2s),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(usb2_hsic),
+};
+
+static const struct msm_pingroup apq8064_groups[] = {
+	PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, NA, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(5, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(6, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(8, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(9, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(10, gsbi4, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c, NA),
+	PINGROUP(11, gsbi4, NA, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c),
+	PINGROUP(12, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
+	PINGROUP(13, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
+	PINGROUP(14, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(20, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(21, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(22, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(27, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(29, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(30, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31, mi2s, NA, gsbi5_spi_cs2, gsbi6_spi_cs2, gsbi7_spi_cs2, NA, NA, NA, NA, NA),
+	PINGROUP(32, mi2s, NA, NA, NA, NA, gsbi5_spi_cs3, gsbi6_spi_cs3, gsbi7_spi_cs3, NA, NA),
+	PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(36, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(40, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(41, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(42, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, spkr_i2s, gsbi5_spi_cs1, gsbi6_spi_cs1, gsbi7_spi_cs1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(49, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(51, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(52, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(53, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(56, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, tsif1, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(59, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(60, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, NA, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(67, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, NA, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(89, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+
+	SDC_PINGROUP(sdc1_clk, 0x20a0, 13, 6),
+	SDC_PINGROUP(sdc1_cmd, 0x20a0, 11, 3),
+	SDC_PINGROUP(sdc1_data, 0x20a0, 9, 0),
+
+	SDC_PINGROUP(sdc3_clk, 0x20a4, 14, 6),
+	SDC_PINGROUP(sdc3_cmd, 0x20a4, 11, 3),
+	SDC_PINGROUP(sdc3_data, 0x20a4, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 90
+
+static const struct msm_pinctrl_soc_data apq8064_pinctrl = {
+	.pins = apq8064_pins,
+	.npins = ARRAY_SIZE(apq8064_pins),
+	.functions = apq8064_functions,
+	.nfunctions = ARRAY_SIZE(apq8064_functions),
+	.groups = apq8064_groups,
+	.ngroups = ARRAY_SIZE(apq8064_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int apq8064_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &apq8064_pinctrl);
+}
+
+static const struct of_device_id apq8064_pinctrl_of_match[] = {
+	{ .compatible = "qcom,apq8064-pinctrl", },
+	{ },
+};
+
+static struct platform_driver apq8064_pinctrl_driver = {
+	.driver = {
+		.name = "apq8064-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = apq8064_pinctrl_of_match,
+	},
+	.probe = apq8064_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init apq8064_pinctrl_init(void)
+{
+	return platform_driver_register(&apq8064_pinctrl_driver);
+}
+arch_initcall(apq8064_pinctrl_init);
+
+static void __exit apq8064_pinctrl_exit(void)
+{
+	platform_driver_unregister(&apq8064_pinctrl_driver);
+}
+module_exit(apq8064_pinctrl_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm APQ8064 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, apq8064_pinctrl_of_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-ipq8064.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-ipq8064.c
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-ipq8064.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-ipq8064.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 2014, 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc ipq8064_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+
+	PINCTRL_PIN(69, "SDC3_CLK"),
+	PINCTRL_PIN(70, "SDC3_CMD"),
+	PINCTRL_PIN(71, "SDC3_DATA"),
+};
+
+#define DECLARE_IPQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_IPQ_GPIO_PINS(0);
+DECLARE_IPQ_GPIO_PINS(1);
+DECLARE_IPQ_GPIO_PINS(2);
+DECLARE_IPQ_GPIO_PINS(3);
+DECLARE_IPQ_GPIO_PINS(4);
+DECLARE_IPQ_GPIO_PINS(5);
+DECLARE_IPQ_GPIO_PINS(6);
+DECLARE_IPQ_GPIO_PINS(7);
+DECLARE_IPQ_GPIO_PINS(8);
+DECLARE_IPQ_GPIO_PINS(9);
+DECLARE_IPQ_GPIO_PINS(10);
+DECLARE_IPQ_GPIO_PINS(11);
+DECLARE_IPQ_GPIO_PINS(12);
+DECLARE_IPQ_GPIO_PINS(13);
+DECLARE_IPQ_GPIO_PINS(14);
+DECLARE_IPQ_GPIO_PINS(15);
+DECLARE_IPQ_GPIO_PINS(16);
+DECLARE_IPQ_GPIO_PINS(17);
+DECLARE_IPQ_GPIO_PINS(18);
+DECLARE_IPQ_GPIO_PINS(19);
+DECLARE_IPQ_GPIO_PINS(20);
+DECLARE_IPQ_GPIO_PINS(21);
+DECLARE_IPQ_GPIO_PINS(22);
+DECLARE_IPQ_GPIO_PINS(23);
+DECLARE_IPQ_GPIO_PINS(24);
+DECLARE_IPQ_GPIO_PINS(25);
+DECLARE_IPQ_GPIO_PINS(26);
+DECLARE_IPQ_GPIO_PINS(27);
+DECLARE_IPQ_GPIO_PINS(28);
+DECLARE_IPQ_GPIO_PINS(29);
+DECLARE_IPQ_GPIO_PINS(30);
+DECLARE_IPQ_GPIO_PINS(31);
+DECLARE_IPQ_GPIO_PINS(32);
+DECLARE_IPQ_GPIO_PINS(33);
+DECLARE_IPQ_GPIO_PINS(34);
+DECLARE_IPQ_GPIO_PINS(35);
+DECLARE_IPQ_GPIO_PINS(36);
+DECLARE_IPQ_GPIO_PINS(37);
+DECLARE_IPQ_GPIO_PINS(38);
+DECLARE_IPQ_GPIO_PINS(39);
+DECLARE_IPQ_GPIO_PINS(40);
+DECLARE_IPQ_GPIO_PINS(41);
+DECLARE_IPQ_GPIO_PINS(42);
+DECLARE_IPQ_GPIO_PINS(43);
+DECLARE_IPQ_GPIO_PINS(44);
+DECLARE_IPQ_GPIO_PINS(45);
+DECLARE_IPQ_GPIO_PINS(46);
+DECLARE_IPQ_GPIO_PINS(47);
+DECLARE_IPQ_GPIO_PINS(48);
+DECLARE_IPQ_GPIO_PINS(49);
+DECLARE_IPQ_GPIO_PINS(50);
+DECLARE_IPQ_GPIO_PINS(51);
+DECLARE_IPQ_GPIO_PINS(52);
+DECLARE_IPQ_GPIO_PINS(53);
+DECLARE_IPQ_GPIO_PINS(54);
+DECLARE_IPQ_GPIO_PINS(55);
+DECLARE_IPQ_GPIO_PINS(56);
+DECLARE_IPQ_GPIO_PINS(57);
+DECLARE_IPQ_GPIO_PINS(58);
+DECLARE_IPQ_GPIO_PINS(59);
+DECLARE_IPQ_GPIO_PINS(60);
+DECLARE_IPQ_GPIO_PINS(61);
+DECLARE_IPQ_GPIO_PINS(62);
+DECLARE_IPQ_GPIO_PINS(63);
+DECLARE_IPQ_GPIO_PINS(64);
+DECLARE_IPQ_GPIO_PINS(65);
+DECLARE_IPQ_GPIO_PINS(66);
+DECLARE_IPQ_GPIO_PINS(67);
+DECLARE_IPQ_GPIO_PINS(68);
+
+static const unsigned int sdc3_clk_pins[] = { 69 };
+static const unsigned int sdc3_cmd_pins[] = { 70 };
+static const unsigned int sdc3_data_pins[] = { 71 };
+
+#define FUNCTION(fname)					\
+	[IPQ_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			IPQ_MUX_gpio,			\
+			IPQ_MUX_##f1,			\
+			IPQ_MUX_##f2,			\
+			IPQ_MUX_##f3,			\
+			IPQ_MUX_##f4,			\
+			IPQ_MUX_##f5,			\
+			IPQ_MUX_##f6,			\
+			IPQ_MUX_##f7,			\
+			IPQ_MUX_##f8,			\
+			IPQ_MUX_##f9,			\
+			IPQ_MUX_##f10,			\
+		},					\
+		.nfuncs = 11,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x400 + 0x4 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_ack_high = 1,			\
+		.intr_target_bit = 0,			\
+		.intr_raw_status_bit = 3,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 1,		\
+	}
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
+	{						\
+		.name = #pg_name,	                \
+		.pins = pg_name##_pins,                 \
+		.npins = ARRAY_SIZE(pg_name##_pins),    \
+		.ctl_reg = ctl,                         \
+		.io_reg = 0,                            \
+		.intr_cfg_reg = 0,                      \
+		.intr_status_reg = 0,                   \
+		.intr_target_reg = 0,                   \
+		.mux_bit = -1,                          \
+		.pull_bit = pull,                       \
+		.drv_bit = drv,                         \
+		.oe_bit = -1,                           \
+		.in_bit = -1,                           \
+		.out_bit = -1,                          \
+		.intr_enable_bit = -1,                  \
+		.intr_status_bit = -1,                  \
+		.intr_target_bit = -1,                  \
+		.intr_raw_status_bit = -1,              \
+		.intr_polarity_bit = -1,                \
+		.intr_detection_bit = -1,               \
+		.intr_detection_width = -1,             \
+	}
+
+enum ipq8064_functions {
+	IPQ_MUX_gpio,
+	IPQ_MUX_mdio,
+	IPQ_MUX_mi2s,
+	IPQ_MUX_pdm,
+	IPQ_MUX_ssbi,
+	IPQ_MUX_spmi,
+	IPQ_MUX_audio_pcm,
+	IPQ_MUX_gsbi1,
+	IPQ_MUX_gsbi2,
+	IPQ_MUX_gsbi4,
+	IPQ_MUX_gsbi5,
+	IPQ_MUX_gsbi5_spi_cs1,
+	IPQ_MUX_gsbi5_spi_cs2,
+	IPQ_MUX_gsbi5_spi_cs3,
+	IPQ_MUX_gsbi6,
+	IPQ_MUX_gsbi7,
+	IPQ_MUX_nss_spi,
+	IPQ_MUX_sdc1,
+	IPQ_MUX_spdif,
+	IPQ_MUX_nand,
+	IPQ_MUX_tsif1,
+	IPQ_MUX_tsif2,
+	IPQ_MUX_usb_fs_n,
+	IPQ_MUX_usb_fs,
+	IPQ_MUX_usb2_hsic,
+	IPQ_MUX_rgmii2,
+	IPQ_MUX_sata,
+	IPQ_MUX_pcie1_rst,
+	IPQ_MUX_pcie1_prsnt,
+	IPQ_MUX_pcie1_pwrflt,
+	IPQ_MUX_pcie1_pwren_n,
+	IPQ_MUX_pcie1_pwren,
+	IPQ_MUX_pcie1_clk_req,
+	IPQ_MUX_pcie2_rst,
+	IPQ_MUX_pcie2_prsnt,
+	IPQ_MUX_pcie2_pwrflt,
+	IPQ_MUX_pcie2_pwren_n,
+	IPQ_MUX_pcie2_pwren,
+	IPQ_MUX_pcie2_clk_req,
+	IPQ_MUX_pcie3_rst,
+	IPQ_MUX_pcie3_prsnt,
+	IPQ_MUX_pcie3_pwrflt,
+	IPQ_MUX_pcie3_pwren_n,
+	IPQ_MUX_pcie3_pwren,
+	IPQ_MUX_pcie3_clk_req,
+	IPQ_MUX_ps_hold,
+	IPQ_MUX_NA,
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+
+static const char * const mdio_groups[] = {
+	"gpio0", "gpio1", "gpio10", "gpio11",
+};
+
+static const char * const mi2s_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+	"gpio33", "gpio55", "gpio56", "gpio57", "gpio58",
+};
+
+static const char * const pdm_groups[] = {
+	"gpio3", "gpio16", "gpio17", "gpio22", "gpio30", "gpio31",
+	"gpio34", "gpio35", "gpio52", "gpio55", "gpio56", "gpio58",
+	"gpio59",
+};
+
+static const char * const ssbi_groups[] = {
+	"gpio10", "gpio11",
+};
+
+static const char * const spmi_groups[] = {
+	"gpio10", "gpio11",
+};
+
+static const char * const audio_pcm_groups[] = {
+	"gpio14", "gpio15", "gpio16", "gpio17",
+};
+
+static const char * const gsbi1_groups[] = {
+	"gpio51", "gpio52", "gpio53", "gpio54",
+};
+
+static const char * const gsbi2_groups[] = {
+	"gpio22", "gpio23", "gpio24", "gpio25",
+};
+
+static const char * const gsbi4_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13",
+};
+
+static const char * const gsbi5_groups[] = {
+	"gpio18", "gpio19", "gpio20", "gpio21",
+};
+
+static const char * const gsbi5_spi_cs1_groups[] = {
+	"gpio6", "gpio61",
+};
+
+static const char * const gsbi5_spi_cs2_groups[] = {
+	"gpio7", "gpio62",
+};
+
+static const char * const gsbi5_spi_cs3_groups[] = {
+	"gpio2",
+};
+
+static const char * const gsbi6_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30", "gpio55", "gpio56",
+	"gpio57", "gpio58",
+};
+
+static const char * const gsbi7_groups[] = {
+	"gpio6", "gpio7", "gpio8", "gpio9",
+};
+
+static const char * const nss_spi_groups[] = {
+	"gpio14", "gpio15", "gpio16", "gpio17", "gpio55", "gpio56",
+	"gpio57", "gpio58",
+};
+
+static const char * const sdc1_groups[] = {
+	"gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
+	"gpio44", "gpio45", "gpio46", "gpio47",
+};
+
+static const char * const spdif_groups[] = {
+	"gpio10", "gpio48",
+};
+
+static const char * const nand_groups[] = {
+	"gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39",
+	"gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45",
+	"gpio46", "gpio47",
+};
+
+static const char * const tsif1_groups[] = {
+	"gpio55", "gpio56", "gpio57", "gpio58",
+};
+
+static const char * const tsif2_groups[] = {
+	"gpio59", "gpio60", "gpio61", "gpio62",
+};
+
+static const char * const usb_fs_n_groups[] = {
+	"gpio6",
+};
+
+static const char * const usb_fs_groups[] = {
+	"gpio6", "gpio7", "gpio8",
+};
+
+static const char * const usb2_hsic_groups[] = {
+	"gpio67", "gpio68",
+};
+
+static const char * const rgmii2_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+	"gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62",
+};
+
+static const char * const sata_groups[] = {
+	"gpio10",
+};
+
+static const char * const pcie1_rst_groups[] = {
+	"gpio3",
+};
+
+static const char * const pcie1_prsnt_groups[] = {
+	"gpio3", "gpio11",
+};
+
+static const char * const pcie1_pwren_n_groups[] = {
+	"gpio4", "gpio12",
+};
+
+static const char * const pcie1_pwren_groups[] = {
+	"gpio4", "gpio12",
+};
+
+static const char * const pcie1_pwrflt_groups[] = {
+	"gpio5", "gpio13",
+};
+
+static const char * const pcie1_clk_req_groups[] = {
+	"gpio5",
+};
+
+static const char * const pcie2_rst_groups[] = {
+	"gpio48",
+};
+
+static const char * const pcie2_prsnt_groups[] = {
+	"gpio11", "gpio48",
+};
+
+static const char * const pcie2_pwren_n_groups[] = {
+	"gpio12", "gpio49",
+};
+
+static const char * const pcie2_pwren_groups[] = {
+	"gpio12", "gpio49",
+};
+
+static const char * const pcie2_pwrflt_groups[] = {
+	"gpio13", "gpio50",
+};
+
+static const char * const pcie2_clk_req_groups[] = {
+	"gpio50",
+};
+
+static const char * const pcie3_rst_groups[] = {
+	"gpio63",
+};
+
+static const char * const pcie3_prsnt_groups[] = {
+	"gpio11",
+};
+
+static const char * const pcie3_pwren_n_groups[] = {
+	"gpio12",
+};
+
+static const char * const pcie3_pwren_groups[] = {
+	"gpio12",
+};
+
+static const char * const pcie3_pwrflt_groups[] = {
+	"gpio13",
+};
+
+static const char * const pcie3_clk_req_groups[] = {
+	"gpio65",
+};
+
+static const char * const ps_hold_groups[] = {
+	"gpio26",
+};
+
+static const struct msm_function ipq8064_functions[] = {
+	FUNCTION(gpio),
+	FUNCTION(mdio),
+	FUNCTION(ssbi),
+	FUNCTION(spmi),
+	FUNCTION(mi2s),
+	FUNCTION(pdm),
+	FUNCTION(audio_pcm),
+	FUNCTION(gsbi1),
+	FUNCTION(gsbi2),
+	FUNCTION(gsbi4),
+	FUNCTION(gsbi5),
+	FUNCTION(gsbi5_spi_cs1),
+	FUNCTION(gsbi5_spi_cs2),
+	FUNCTION(gsbi5_spi_cs3),
+	FUNCTION(gsbi6),
+	FUNCTION(gsbi7),
+	FUNCTION(nss_spi),
+	FUNCTION(sdc1),
+	FUNCTION(spdif),
+	FUNCTION(nand),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(usb_fs_n),
+	FUNCTION(usb_fs),
+	FUNCTION(usb2_hsic),
+	FUNCTION(rgmii2),
+	FUNCTION(sata),
+	FUNCTION(pcie1_rst),
+	FUNCTION(pcie1_prsnt),
+	FUNCTION(pcie1_pwren_n),
+	FUNCTION(pcie1_pwren),
+	FUNCTION(pcie1_pwrflt),
+	FUNCTION(pcie1_clk_req),
+	FUNCTION(pcie2_rst),
+	FUNCTION(pcie2_prsnt),
+	FUNCTION(pcie2_pwren_n),
+	FUNCTION(pcie2_pwren),
+	FUNCTION(pcie2_pwrflt),
+	FUNCTION(pcie2_clk_req),
+	FUNCTION(pcie3_rst),
+	FUNCTION(pcie3_prsnt),
+	FUNCTION(pcie3_pwren_n),
+	FUNCTION(pcie3_pwren),
+	FUNCTION(pcie3_pwrflt),
+	FUNCTION(pcie3_clk_req),
+	FUNCTION(ps_hold),
+};
+
+static const struct msm_pingroup ipq8064_groups[] = {
+	PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(6, gsbi7, usb_fs, gsbi5_spi_cs1, usb_fs_n, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, gsbi7, usb_fs, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(8, gsbi7, usb_fs, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(9, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(10, gsbi4, spdif, sata, ssbi, mdio, spmi, NA, NA, NA, NA),
+	PINGROUP(11, gsbi4, pcie2_prsnt, pcie1_prsnt, pcie3_prsnt, ssbi, mdio, spmi, NA, NA, NA),
+	PINGROUP(12, gsbi4, pcie2_pwren_n, pcie1_pwren_n, pcie3_pwren_n, pcie2_pwren, pcie1_pwren, pcie3_pwren, NA, NA, NA),
+	PINGROUP(13, gsbi4, pcie2_pwrflt, pcie1_pwrflt, pcie3_pwrflt, NA, NA, NA, NA, NA, NA),
+	PINGROUP(14, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(20, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(21, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(22, gsbi2, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(26, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(27, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(29, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(30, mi2s, rgmii2, gsbi6, pdm, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31, mi2s, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(32, mi2s, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(36, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(40, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(41, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(42, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(43, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(44, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(45, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(46, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48, pcie2_rst, spdif, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(49, pcie2_pwren_n, pcie2_pwren, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, pcie2_clk_req, pcie2_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(51, gsbi1, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(52, gsbi1, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(53, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
+	PINGROUP(56, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
+	PINGROUP(57, tsif1, mi2s, gsbi6, nss_spi, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA),
+	PINGROUP(59, tsif2, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(60, tsif2, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, tsif2, rgmii2, gsbi5_spi_cs1, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, tsif2, rgmii2, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6),
+	SDC_PINGROUP(sdc3_cmd, 0x204a, 11, 3),
+	SDC_PINGROUP(sdc3_data, 0x204a, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 69
+
+static const struct msm_pinctrl_soc_data ipq8064_pinctrl = {
+	.pins = ipq8064_pins,
+	.npins = ARRAY_SIZE(ipq8064_pins),
+	.functions = ipq8064_functions,
+	.nfunctions = ARRAY_SIZE(ipq8064_functions),
+	.groups = ipq8064_groups,
+	.ngroups = ARRAY_SIZE(ipq8064_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int ipq8064_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &ipq8064_pinctrl);
+}
+
+static const struct of_device_id ipq8064_pinctrl_of_match[] = {
+	{ .compatible = "qcom,ipq8064-pinctrl", },
+	{ },
+};
+
+static struct platform_driver ipq8064_pinctrl_driver = {
+	.driver = {
+		.name = "ipq8064-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = ipq8064_pinctrl_of_match,
+	},
+	.probe = ipq8064_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init ipq8064_pinctrl_init(void)
+{
+	return platform_driver_register(&ipq8064_pinctrl_driver);
+}
+arch_initcall(ipq8064_pinctrl_init);
+
+static void __exit ipq8064_pinctrl_exit(void)
+{
+	platform_driver_unregister(&ipq8064_pinctrl_driver);
+}
+module_exit(ipq8064_pinctrl_exit);
+
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("Qualcomm IPQ8064 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, ipq8064_pinctrl_of_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm8960.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm8960.c
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm8960.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm8960.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc msm8960_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "GPIO_113"),
+	PINCTRL_PIN(114, "GPIO_114"),
+	PINCTRL_PIN(115, "GPIO_115"),
+	PINCTRL_PIN(116, "GPIO_116"),
+	PINCTRL_PIN(117, "GPIO_117"),
+	PINCTRL_PIN(118, "GPIO_118"),
+	PINCTRL_PIN(119, "GPIO_119"),
+	PINCTRL_PIN(120, "GPIO_120"),
+	PINCTRL_PIN(121, "GPIO_121"),
+	PINCTRL_PIN(122, "GPIO_122"),
+	PINCTRL_PIN(123, "GPIO_123"),
+	PINCTRL_PIN(124, "GPIO_124"),
+	PINCTRL_PIN(125, "GPIO_125"),
+	PINCTRL_PIN(126, "GPIO_126"),
+	PINCTRL_PIN(127, "GPIO_127"),
+	PINCTRL_PIN(128, "GPIO_128"),
+	PINCTRL_PIN(129, "GPIO_129"),
+	PINCTRL_PIN(130, "GPIO_130"),
+	PINCTRL_PIN(131, "GPIO_131"),
+	PINCTRL_PIN(132, "GPIO_132"),
+	PINCTRL_PIN(133, "GPIO_133"),
+	PINCTRL_PIN(134, "GPIO_134"),
+	PINCTRL_PIN(135, "GPIO_135"),
+	PINCTRL_PIN(136, "GPIO_136"),
+	PINCTRL_PIN(137, "GPIO_137"),
+	PINCTRL_PIN(138, "GPIO_138"),
+	PINCTRL_PIN(139, "GPIO_139"),
+	PINCTRL_PIN(140, "GPIO_140"),
+	PINCTRL_PIN(141, "GPIO_141"),
+	PINCTRL_PIN(142, "GPIO_142"),
+	PINCTRL_PIN(143, "GPIO_143"),
+	PINCTRL_PIN(144, "GPIO_144"),
+	PINCTRL_PIN(145, "GPIO_145"),
+	PINCTRL_PIN(146, "GPIO_146"),
+	PINCTRL_PIN(147, "GPIO_147"),
+	PINCTRL_PIN(148, "GPIO_148"),
+	PINCTRL_PIN(149, "GPIO_149"),
+	PINCTRL_PIN(150, "GPIO_150"),
+	PINCTRL_PIN(151, "GPIO_151"),
+
+	PINCTRL_PIN(152, "SDC1_CLK"),
+	PINCTRL_PIN(153, "SDC1_CMD"),
+	PINCTRL_PIN(154, "SDC1_DATA"),
+	PINCTRL_PIN(155, "SDC3_CLK"),
+	PINCTRL_PIN(156, "SDC3_CMD"),
+	PINCTRL_PIN(157, "SDC3_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+
+static const unsigned int sdc1_clk_pins[] = { 152 };
+static const unsigned int sdc1_cmd_pins[] = { 153 };
+static const unsigned int sdc1_data_pins[] = { 154 };
+static const unsigned int sdc3_clk_pins[] = { 155 };
+static const unsigned int sdc3_cmd_pins[] = { 156 };
+static const unsigned int sdc3_data_pins[] = { 157 };
+
+#define FUNCTION(fname)					\
+	[MSM_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			MSM_MUX_gpio,			\
+			MSM_MUX_##f1,			\
+			MSM_MUX_##f2,			\
+			MSM_MUX_##f3,			\
+			MSM_MUX_##f4,			\
+			MSM_MUX_##f5,			\
+			MSM_MUX_##f6,			\
+			MSM_MUX_##f7,			\
+			MSM_MUX_##f8,			\
+			MSM_MUX_##f9,			\
+			MSM_MUX_##f10,			\
+			MSM_MUX_##f11			\
+		},					\
+		.nfuncs = 12,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x400 + 0x4 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_ack_high = 1,			\
+		.intr_target_bit = 0,			\
+		.intr_raw_status_bit = 3,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 1,		\
+	}
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+
+enum msm8960_functions {
+	MSM_MUX_audio_pcm,
+	MSM_MUX_bt,
+	MSM_MUX_cam_mclk0,
+	MSM_MUX_cam_mclk1,
+	MSM_MUX_cam_mclk2,
+	MSM_MUX_codec_mic_i2s,
+	MSM_MUX_codec_spkr_i2s,
+	MSM_MUX_ext_gps,
+	MSM_MUX_fm,
+	MSM_MUX_gps_blanking,
+	MSM_MUX_gps_pps_in,
+	MSM_MUX_gps_pps_out,
+	MSM_MUX_gp_clk_0a,
+	MSM_MUX_gp_clk_0b,
+	MSM_MUX_gp_clk_1a,
+	MSM_MUX_gp_clk_1b,
+	MSM_MUX_gp_clk_2a,
+	MSM_MUX_gp_clk_2b,
+	MSM_MUX_gp_mn,
+	MSM_MUX_gp_pdm_0a,
+	MSM_MUX_gp_pdm_0b,
+	MSM_MUX_gp_pdm_1a,
+	MSM_MUX_gp_pdm_1b,
+	MSM_MUX_gp_pdm_2a,
+	MSM_MUX_gp_pdm_2b,
+	MSM_MUX_gpio,
+	MSM_MUX_gsbi1,
+	MSM_MUX_gsbi1_spi_cs1_n,
+	MSM_MUX_gsbi1_spi_cs2a_n,
+	MSM_MUX_gsbi1_spi_cs2b_n,
+	MSM_MUX_gsbi1_spi_cs3_n,
+	MSM_MUX_gsbi2,
+	MSM_MUX_gsbi2_spi_cs1_n,
+	MSM_MUX_gsbi2_spi_cs2_n,
+	MSM_MUX_gsbi2_spi_cs3_n,
+	MSM_MUX_gsbi3,
+	MSM_MUX_gsbi4,
+	MSM_MUX_gsbi4_3d_cam_i2c_l,
+	MSM_MUX_gsbi4_3d_cam_i2c_r,
+	MSM_MUX_gsbi5,
+	MSM_MUX_gsbi5_3d_cam_i2c_l,
+	MSM_MUX_gsbi5_3d_cam_i2c_r,
+	MSM_MUX_gsbi6,
+	MSM_MUX_gsbi7,
+	MSM_MUX_gsbi8,
+	MSM_MUX_gsbi9,
+	MSM_MUX_gsbi10,
+	MSM_MUX_gsbi11,
+	MSM_MUX_gsbi11_spi_cs1a_n,
+	MSM_MUX_gsbi11_spi_cs1b_n,
+	MSM_MUX_gsbi11_spi_cs2a_n,
+	MSM_MUX_gsbi11_spi_cs2b_n,
+	MSM_MUX_gsbi11_spi_cs3_n,
+	MSM_MUX_gsbi12,
+	MSM_MUX_hdmi_cec,
+	MSM_MUX_hdmi_ddc_clock,
+	MSM_MUX_hdmi_ddc_data,
+	MSM_MUX_hdmi_hot_plug_detect,
+	MSM_MUX_hsic,
+	MSM_MUX_mdp_vsync,
+	MSM_MUX_mi2s,
+	MSM_MUX_mic_i2s,
+	MSM_MUX_pmb_clk,
+	MSM_MUX_pmb_ext_ctrl,
+	MSM_MUX_ps_hold,
+	MSM_MUX_rpm_wdog,
+	MSM_MUX_sdc2,
+	MSM_MUX_sdc4,
+	MSM_MUX_sdc5,
+	MSM_MUX_slimbus1,
+	MSM_MUX_slimbus2,
+	MSM_MUX_spkr_i2s,
+	MSM_MUX_ssbi1,
+	MSM_MUX_ssbi2,
+	MSM_MUX_ssbi_ext_gps,
+	MSM_MUX_ssbi_pmic2,
+	MSM_MUX_ssbi_qpa1,
+	MSM_MUX_ssbi_ts,
+	MSM_MUX_tsif1,
+	MSM_MUX_tsif2,
+	MSM_MUX_ts_eoc,
+	MSM_MUX_usb_fs1,
+	MSM_MUX_usb_fs1_oe,
+	MSM_MUX_usb_fs1_oe_n,
+	MSM_MUX_usb_fs2,
+	MSM_MUX_usb_fs2_oe,
+	MSM_MUX_usb_fs2_oe_n,
+	MSM_MUX_vfe_camif_timer1_a,
+	MSM_MUX_vfe_camif_timer1_b,
+	MSM_MUX_vfe_camif_timer2,
+	MSM_MUX_vfe_camif_timer3_a,
+	MSM_MUX_vfe_camif_timer3_b,
+	MSM_MUX_vfe_camif_timer4_a,
+	MSM_MUX_vfe_camif_timer4_b,
+	MSM_MUX_vfe_camif_timer4_c,
+	MSM_MUX_vfe_camif_timer5_a,
+	MSM_MUX_vfe_camif_timer5_b,
+	MSM_MUX_vfe_camif_timer6_a,
+	MSM_MUX_vfe_camif_timer6_b,
+	MSM_MUX_vfe_camif_timer6_c,
+	MSM_MUX_vfe_camif_timer7_a,
+	MSM_MUX_vfe_camif_timer7_b,
+	MSM_MUX_vfe_camif_timer7_c,
+	MSM_MUX_wlan,
+	MSM_MUX_NA,
+};
+
+static const char * const audio_pcm_groups[] = {
+	"gpio63", "gpio64", "gpio65", "gpio66"
+};
+
+static const char * const bt_groups[] = {
+	"gpio28", "gpio29", "gpio83"
+};
+
+static const char * const cam_mclk0_groups[] = {
+	"gpio5"
+};
+
+static const char * const cam_mclk1_groups[] = {
+	"gpio4"
+};
+
+static const char * const cam_mclk2_groups[] = {
+	"gpio2"
+};
+
+static const char * const codec_mic_i2s_groups[] = {
+	"gpio54", "gpio55", "gpio56", "gpio57", "gpio58"
+};
+
+static const char * const codec_spkr_i2s_groups[] = {
+	"gpio59", "gpio60", "gpio61", "gpio62"
+};
+
+static const char * const ext_gps_groups[] = {
+	"gpio22", "gpio23", "gpio24", "gpio25"
+};
+
+static const char * const fm_groups[] = {
+	"gpio26", "gpio27"
+};
+
+static const char * const gps_blanking_groups[] = {
+	"gpio137"
+};
+
+static const char * const gps_pps_in_groups[] = {
+	"gpio37"
+};
+
+static const char * const gps_pps_out_groups[] = {
+	"gpio37"
+};
+
+static const char * const gp_clk_0a_groups[] = {
+	"gpio3"
+};
+
+static const char * const gp_clk_0b_groups[] = {
+	"gpio54"
+};
+
+static const char * const gp_clk_1a_groups[] = {
+	"gpio4"
+};
+
+static const char * const gp_clk_1b_groups[] = {
+	"gpio70"
+};
+
+static const char * const gp_clk_2a_groups[] = {
+	"gpio52"
+};
+
+static const char * const gp_clk_2b_groups[] = {
+	"gpio37"
+};
+
+static const char * const gp_mn_groups[] = {
+	"gpio2"
+};
+
+static const char * const gp_pdm_0a_groups[] = {
+	"gpio58"
+};
+
+static const char * const gp_pdm_0b_groups[] = {
+	"gpio39"
+};
+
+static const char * const gp_pdm_1a_groups[] = {
+	"gpio94"
+};
+
+static const char * const gp_pdm_1b_groups[] = {
+	"gpio64"
+};
+
+static const char * const gp_pdm_2a_groups[] = {
+	"gpio69"
+};
+
+static const char * const gp_pdm_2b_groups[] = {
+	"gpio53"
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+	"gpio147", "gpio148", "gpio149", "gpio150", "gpio151"
+};
+
+static const char * const gsbi1_groups[] = {
+	"gpio6", "gpio7", "gpio8", "gpio9"
+};
+
+static const char * const gsbi1_spi_cs1_n_groups[] = {
+	"gpio14"
+};
+
+static const char * const gsbi1_spi_cs2a_n_groups[] = {
+	"gpio15"
+};
+
+static const char * const gsbi1_spi_cs2b_n_groups[] = {
+	"gpio17"
+};
+
+static const char * const gsbi1_spi_cs3_n_groups[] = {
+	"gpio16"
+};
+
+static const char * const gsbi2_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+
+static const char * const gsbi2_spi_cs1_n_groups[] = {
+	"gpio52"
+};
+
+static const char * const gsbi2_spi_cs2_n_groups[] = {
+	"gpio68"
+};
+
+static const char * const gsbi2_spi_cs3_n_groups[] = {
+	"gpio56"
+};
+
+static const char * const gsbi3_groups[] = {
+	"gpio14", "gpio15", "gpio16", "gpio17"
+};
+
+static const char * const gsbi4_groups[] = {
+	"gpio18", "gpio19", "gpio20", "gpio21"
+};
+
+static const char * const gsbi4_3d_cam_i2c_l_groups[] = {
+	"gpio18", "gpio19"
+};
+
+static const char * const gsbi4_3d_cam_i2c_r_groups[] = {
+	"gpio20", "gpio21"
+};
+
+static const char * const gsbi5_groups[] = {
+	"gpio22", "gpio23", "gpio24", "gpio25"
+};
+
+static const char * const gsbi5_3d_cam_i2c_l_groups[] = {
+	"gpio22", "gpio23"
+};
+
+static const char * const gsbi5_3d_cam_i2c_r_groups[] = {
+	"gpio24", "gpio25"
+};
+
+static const char * const gsbi6_groups[] = {
+	"gpio26", "gpio27", "gpio28", "gpio29"
+};
+
+static const char * const gsbi7_groups[] = {
+	"gpio30", "gpio31", "gpio32", "gpio33"
+};
+
+static const char * const gsbi8_groups[] = {
+	"gpio34", "gpio35", "gpio36", "gpio37"
+};
+
+static const char * const gsbi9_groups[] = {
+	"gpio93", "gpio94", "gpio95", "gpio96"
+};
+
+static const char * const gsbi10_groups[] = {
+	"gpio71", "gpio72", "gpio73", "gpio74"
+};
+
+static const char * const gsbi11_groups[] = {
+	"gpio38", "gpio39", "gpio40", "gpio41"
+};
+
+static const char * const gsbi11_spi_cs1a_n_groups[] = {
+	"gpio36"
+};
+
+static const char * const gsbi11_spi_cs1b_n_groups[] = {
+	"gpio18"
+};
+
+static const char * const gsbi11_spi_cs2a_n_groups[] = {
+	"gpio37"
+};
+
+static const char * const gsbi11_spi_cs2b_n_groups[] = {
+	"gpio19"
+};
+
+static const char * const gsbi11_spi_cs3_n_groups[] = {
+	"gpio76"
+};
+
+static const char * const gsbi12_groups[] = {
+	"gpio42", "gpio43", "gpio44", "gpio45"
+};
+
+static const char * const hdmi_cec_groups[] = {
+	"gpio99"
+};
+
+static const char * const hdmi_ddc_clock_groups[] = {
+	"gpio100"
+};
+
+static const char * const hdmi_ddc_data_groups[] = {
+	"gpio101"
+};
+
+static const char * const hdmi_hot_plug_detect_groups[] = {
+	"gpio102"
+};
+
+static const char * const hsic_groups[] = {
+	"gpio150", "gpio151"
+};
+
+static const char * const mdp_vsync_groups[] = {
+	"gpio0", "gpio1", "gpio19"
+};
+
+static const char * const mi2s_groups[] = {
+	"gpio47", "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53"
+};
+
+static const char * const mic_i2s_groups[] = {
+	"gpio71", "gpio72", "gpio73", "gpio74"
+};
+
+static const char * const pmb_clk_groups[] = {
+	"gpio21", "gpio86", "gpio112"
+};
+
+static const char * const pmb_ext_ctrl_groups[] = {
+	"gpio4", "gpio5"
+};
+
+static const char * const ps_hold_groups[] = {
+	"gpio108"
+};
+
+static const char * const rpm_wdog_groups[] = {
+	"gpio12"
+};
+
+static const char * const sdc2_groups[] = {
+	"gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+	"gpio96", "gpio97", "gpio98"
+};
+
+static const char * const sdc4_groups[] = {
+	"gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88"
+};
+
+static const char * const sdc5_groups[] = {
+	"gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
+};
+
+static const char * const slimbus1_groups[] = {
+	"gpio50", "gpio51", "gpio60", "gpio61"
+};
+
+static const char * const slimbus2_groups[] = {
+	"gpio42", "gpio43"
+};
+
+static const char * const spkr_i2s_groups[] = {
+	"gpio67", "gpio68", "gpio69", "gpio70"
+};
+
+static const char * const ssbi1_groups[] = {
+	"gpio141", "gpio143"
+};
+
+static const char * const ssbi2_groups[] = {
+	"gpio140", "gpio142"
+};
+
+static const char * const ssbi_ext_gps_groups[] = {
+	"gpio23"
+};
+
+static const char * const ssbi_pmic2_groups[] = {
+	"gpio149"
+};
+
+static const char * const ssbi_qpa1_groups[] = {
+	"gpio131"
+};
+
+static const char * const ssbi_ts_groups[] = {
+	"gpio10"
+};
+
+static const char * const tsif1_groups[] = {
+	"gpio75", "gpio76", "gpio77", "gpio82"
+};
+
+static const char * const tsif2_groups[] = {
+	"gpio78", "gpio79", "gpio80", "gpio81"
+};
+
+static const char * const ts_eoc_groups[] = {
+	"gpio11"
+};
+
+static const char * const usb_fs1_groups[] = {
+	"gpio32", "gpio33"
+};
+
+static const char * const usb_fs1_oe_groups[] = {
+	"gpio31"
+};
+
+static const char * const usb_fs1_oe_n_groups[] = {
+	"gpio31"
+};
+
+static const char * const usb_fs2_groups[] = {
+	"gpio34", "gpio35"
+};
+
+static const char * const usb_fs2_oe_groups[] = {
+	"gpio36"
+};
+
+static const char * const usb_fs2_oe_n_groups[] = {
+	"gpio36"
+};
+
+static const char * const vfe_camif_timer1_a_groups[] = {
+	"gpio2"
+};
+
+static const char * const vfe_camif_timer1_b_groups[] = {
+	"gpio38"
+};
+
+static const char * const vfe_camif_timer2_groups[] = {
+	"gpio3"
+};
+
+static const char * const vfe_camif_timer3_a_groups[] = {
+	"gpio4"
+};
+
+static const char * const vfe_camif_timer3_b_groups[] = {
+	"gpio151"
+};
+
+static const char * const vfe_camif_timer4_a_groups[] = {
+	"gpio65"
+};
+
+static const char * const vfe_camif_timer4_b_groups[] = {
+	"gpio150"
+};
+
+static const char * const vfe_camif_timer4_c_groups[] = {
+	"gpio10"
+};
+
+static const char * const vfe_camif_timer5_a_groups[] = {
+	"gpio66"
+};
+
+static const char * const vfe_camif_timer5_b_groups[] = {
+	"gpio39"
+};
+
+static const char * const vfe_camif_timer6_a_groups[] = {
+	"gpio71"
+};
+
+static const char * const vfe_camif_timer6_b_groups[] = {
+	"gpio0"
+};
+
+static const char * const vfe_camif_timer6_c_groups[] = {
+	"gpio18"
+};
+
+static const char * const vfe_camif_timer7_a_groups[] = {
+	"gpio67"
+};
+
+static const char * const vfe_camif_timer7_b_groups[] = {
+	"gpio1"
+};
+
+static const char * const vfe_camif_timer7_c_groups[] = {
+	"gpio19"
+};
+
+static const char * const wlan_groups[] = {
+	"gpio84", "gpio85", "gpio86", "gpio87", "gpio88"
+};
+
+static const struct msm_function msm8960_functions[] = {
+	FUNCTION(audio_pcm),
+	FUNCTION(bt),
+	FUNCTION(cam_mclk0),
+	FUNCTION(cam_mclk1),
+	FUNCTION(cam_mclk2),
+	FUNCTION(codec_mic_i2s),
+	FUNCTION(codec_spkr_i2s),
+	FUNCTION(ext_gps),
+	FUNCTION(fm),
+	FUNCTION(gps_blanking),
+	FUNCTION(gps_pps_in),
+	FUNCTION(gps_pps_out),
+	FUNCTION(gp_clk_0a),
+	FUNCTION(gp_clk_0b),
+	FUNCTION(gp_clk_1a),
+	FUNCTION(gp_clk_1b),
+	FUNCTION(gp_clk_2a),
+	FUNCTION(gp_clk_2b),
+	FUNCTION(gp_mn),
+	FUNCTION(gp_pdm_0a),
+	FUNCTION(gp_pdm_0b),
+	FUNCTION(gp_pdm_1a),
+	FUNCTION(gp_pdm_1b),
+	FUNCTION(gp_pdm_2a),
+	FUNCTION(gp_pdm_2b),
+	FUNCTION(gpio),
+	FUNCTION(gsbi1),
+	FUNCTION(gsbi1_spi_cs1_n),
+	FUNCTION(gsbi1_spi_cs2a_n),
+	FUNCTION(gsbi1_spi_cs2b_n),
+	FUNCTION(gsbi1_spi_cs3_n),
+	FUNCTION(gsbi2),
+	FUNCTION(gsbi2_spi_cs1_n),
+	FUNCTION(gsbi2_spi_cs2_n),
+	FUNCTION(gsbi2_spi_cs3_n),
+	FUNCTION(gsbi3),
+	FUNCTION(gsbi4),
+	FUNCTION(gsbi4_3d_cam_i2c_l),
+	FUNCTION(gsbi4_3d_cam_i2c_r),
+	FUNCTION(gsbi5),
+	FUNCTION(gsbi5_3d_cam_i2c_l),
+	FUNCTION(gsbi5_3d_cam_i2c_r),
+	FUNCTION(gsbi6),
+	FUNCTION(gsbi7),
+	FUNCTION(gsbi8),
+	FUNCTION(gsbi9),
+	FUNCTION(gsbi10),
+	FUNCTION(gsbi11),
+	FUNCTION(gsbi11_spi_cs1a_n),
+	FUNCTION(gsbi11_spi_cs1b_n),
+	FUNCTION(gsbi11_spi_cs2a_n),
+	FUNCTION(gsbi11_spi_cs2b_n),
+	FUNCTION(gsbi11_spi_cs3_n),
+	FUNCTION(gsbi12),
+	FUNCTION(hdmi_cec),
+	FUNCTION(hdmi_ddc_clock),
+	FUNCTION(hdmi_ddc_data),
+	FUNCTION(hdmi_hot_plug_detect),
+	FUNCTION(hsic),
+	FUNCTION(mdp_vsync),
+	FUNCTION(mi2s),
+	FUNCTION(mic_i2s),
+	FUNCTION(pmb_clk),
+	FUNCTION(pmb_ext_ctrl),
+	FUNCTION(ps_hold),
+	FUNCTION(rpm_wdog),
+	FUNCTION(sdc2),
+	FUNCTION(sdc4),
+	FUNCTION(sdc5),
+	FUNCTION(slimbus1),
+	FUNCTION(slimbus2),
+	FUNCTION(spkr_i2s),
+	FUNCTION(ssbi1),
+	FUNCTION(ssbi2),
+	FUNCTION(ssbi_ext_gps),
+	FUNCTION(ssbi_pmic2),
+	FUNCTION(ssbi_qpa1),
+	FUNCTION(ssbi_ts),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(ts_eoc),
+	FUNCTION(usb_fs1),
+	FUNCTION(usb_fs1_oe),
+	FUNCTION(usb_fs1_oe_n),
+	FUNCTION(usb_fs2),
+	FUNCTION(usb_fs2_oe),
+	FUNCTION(usb_fs2_oe_n),
+	FUNCTION(vfe_camif_timer1_a),
+	FUNCTION(vfe_camif_timer1_b),
+	FUNCTION(vfe_camif_timer2),
+	FUNCTION(vfe_camif_timer3_a),
+	FUNCTION(vfe_camif_timer3_b),
+	FUNCTION(vfe_camif_timer4_a),
+	FUNCTION(vfe_camif_timer4_b),
+	FUNCTION(vfe_camif_timer4_c),
+	FUNCTION(vfe_camif_timer5_a),
+	FUNCTION(vfe_camif_timer5_b),
+	FUNCTION(vfe_camif_timer6_a),
+	FUNCTION(vfe_camif_timer6_b),
+	FUNCTION(vfe_camif_timer6_c),
+	FUNCTION(vfe_camif_timer7_a),
+	FUNCTION(vfe_camif_timer7_b),
+	FUNCTION(vfe_camif_timer7_c),
+	FUNCTION(wlan),
+};
+
+static const struct msm_pingroup msm8960_groups[] = {
+	PINGROUP(0, mdp_vsync, vfe_camif_timer6_b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, mdp_vsync, vfe_camif_timer7_b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, vfe_camif_timer1_a, gp_mn, NA, cam_mclk2, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(3, vfe_camif_timer2, gp_clk_0a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, vfe_camif_timer3_a, cam_mclk1, gp_clk_1a, pmb_ext_ctrl, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(5, cam_mclk0, pmb_ext_ctrl, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(6, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(8, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(9, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(10, gsbi2, ssbi_ts, NA, vfe_camif_timer4_c, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(11, gsbi2, ts_eoc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(12, gsbi2, rpm_wdog, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(13, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(14, gsbi3, gsbi1_spi_cs1_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15, gsbi3, gsbi1_spi_cs2a_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, gsbi3, gsbi1_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17, gsbi3, gsbi1_spi_cs2b_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18, gsbi4, gsbi11_spi_cs1b_n, NA, NA, gsbi4_3d_cam_i2c_l, vfe_camif_timer6_c, NA, NA, NA, NA, NA),
+	PINGROUP(19, gsbi4, gsbi11_spi_cs2b_n, NA, mdp_vsync, NA, gsbi4_3d_cam_i2c_l, vfe_camif_timer7_c, NA, NA, NA, NA),
+	PINGROUP(20, gsbi4, gsbi4_3d_cam_i2c_r, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(21, gsbi4, pmb_clk, gsbi4_3d_cam_i2c_r, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(22, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_l, NA),
+	PINGROUP(23, gsbi5, ssbi_ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_l, NA),
+	PINGROUP(24, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_r, NA),
+	PINGROUP(25, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_r, NA),
+	PINGROUP(26, fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(27, fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28, bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(29, bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(30, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31, gsbi7, usb_fs1_oe, usb_fs1_oe_n, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(32, gsbi7, usb_fs1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(33, gsbi7, usb_fs1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34, gsbi8, usb_fs2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35, gsbi8, usb_fs2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(36, gsbi8, usb_fs2_oe, usb_fs2_oe_n, gsbi11_spi_cs1a_n, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, gsbi8, gps_pps_out, gps_pps_in, gsbi11_spi_cs2a_n, gp_clk_2b, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, vfe_camif_timer1_b, NA),
+	PINGROUP(39, gsbi11, gp_pdm_0b, NA, NA, NA, NA, NA, NA, NA, NA, vfe_camif_timer5_b),
+	PINGROUP(40, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(41, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(42, gsbi12, slimbus2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(43, gsbi12, slimbus2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(44, gsbi12, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(45, gsbi12, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(49, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, mi2s, slimbus1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(51, mi2s, slimbus1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(52, mi2s, gp_clk_2a, gsbi2_spi_cs1_n, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(53, mi2s, gp_pdm_2b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, codec_mic_i2s, gp_clk_0b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(56, codec_mic_i2s, gsbi2_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, codec_mic_i2s, gp_pdm_0a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(59, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(60, slimbus1, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, slimbus1, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, audio_pcm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, audio_pcm, gp_pdm_1b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, audio_pcm, vfe_camif_timer4_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, audio_pcm, vfe_camif_timer5_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(67, spkr_i2s, vfe_camif_timer7_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, spkr_i2s, gsbi2_spi_cs2_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, spkr_i2s, gp_pdm_2a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, spkr_i2s, gp_clk_1b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, mic_i2s, gsbi10, vfe_camif_timer6_a, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76, tsif1, gsbi11_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, tsif1, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82, tsif1, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, bt, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, wlan, sdc4, pmb_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(87, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(89, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(91, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(92, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(93, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(94, sdc2, gsbi9, gp_pdm_1a, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(95, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(96, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(97, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(99, hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(100, hdmi_ddc_clock, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(101, hdmi_ddc_data, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(102, hdmi_hot_plug_detect, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(108, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(110, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(111, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(112, NA, pmb_clk, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(113, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(114, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(115, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(118, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(121, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(122, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(123, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(130, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(131, NA, ssbi_qpa1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(132, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(133, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(134, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(135, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(137, gps_blanking, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(138, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(139, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(140, ssbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(141, ssbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(142, ssbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(143, ssbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(144, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(145, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(146, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(147, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(148, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(149, ssbi_pmic2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(150, hsic, NA, vfe_camif_timer4_b, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(151, hsic, NA, vfe_camif_timer3_b, NA, NA, NA, NA, NA, NA, NA, NA),
+
+	SDC_PINGROUP(sdc1_clk, 0x20a0, 13, 6),
+	SDC_PINGROUP(sdc1_cmd, 0x20a0, 11, 3),
+	SDC_PINGROUP(sdc1_data, 0x20a0, 9, 0),
+
+	SDC_PINGROUP(sdc3_clk, 0x20a4, 14, 6),
+	SDC_PINGROUP(sdc3_cmd, 0x20a4, 11, 3),
+	SDC_PINGROUP(sdc3_data, 0x20a4, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 152
+
+static const struct msm_pinctrl_soc_data msm8960_pinctrl = {
+	.pins = msm8960_pins,
+	.npins = ARRAY_SIZE(msm8960_pins),
+	.functions = msm8960_functions,
+	.nfunctions = ARRAY_SIZE(msm8960_functions),
+	.groups = msm8960_groups,
+	.ngroups = ARRAY_SIZE(msm8960_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int msm8960_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8960_pinctrl);
+}
+
+static const struct of_device_id msm8960_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8960-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8960_pinctrl_driver = {
+	.driver = {
+		.name = "msm8960-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm8960_pinctrl_of_match,
+	},
+	.probe = msm8960_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8960_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8960_pinctrl_driver);
+}
+arch_initcall(msm8960_pinctrl_init);
+
+static void __exit msm8960_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8960_pinctrl_driver);
+}
+module_exit(msm8960_pinctrl_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm MSM8960 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8960_pinctrl_of_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm8x74.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm8x74.c
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm8x74.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm8x74.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1067 @@
+/*
+ * Copyright (c) 2013, Sony Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc msm8x74_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "GPIO_113"),
+	PINCTRL_PIN(114, "GPIO_114"),
+	PINCTRL_PIN(115, "GPIO_115"),
+	PINCTRL_PIN(116, "GPIO_116"),
+	PINCTRL_PIN(117, "GPIO_117"),
+	PINCTRL_PIN(118, "GPIO_118"),
+	PINCTRL_PIN(119, "GPIO_119"),
+	PINCTRL_PIN(120, "GPIO_120"),
+	PINCTRL_PIN(121, "GPIO_121"),
+	PINCTRL_PIN(122, "GPIO_122"),
+	PINCTRL_PIN(123, "GPIO_123"),
+	PINCTRL_PIN(124, "GPIO_124"),
+	PINCTRL_PIN(125, "GPIO_125"),
+	PINCTRL_PIN(126, "GPIO_126"),
+	PINCTRL_PIN(127, "GPIO_127"),
+	PINCTRL_PIN(128, "GPIO_128"),
+	PINCTRL_PIN(129, "GPIO_129"),
+	PINCTRL_PIN(130, "GPIO_130"),
+	PINCTRL_PIN(131, "GPIO_131"),
+	PINCTRL_PIN(132, "GPIO_132"),
+	PINCTRL_PIN(133, "GPIO_133"),
+	PINCTRL_PIN(134, "GPIO_134"),
+	PINCTRL_PIN(135, "GPIO_135"),
+	PINCTRL_PIN(136, "GPIO_136"),
+	PINCTRL_PIN(137, "GPIO_137"),
+	PINCTRL_PIN(138, "GPIO_138"),
+	PINCTRL_PIN(139, "GPIO_139"),
+	PINCTRL_PIN(140, "GPIO_140"),
+	PINCTRL_PIN(141, "GPIO_141"),
+	PINCTRL_PIN(142, "GPIO_142"),
+	PINCTRL_PIN(143, "GPIO_143"),
+	PINCTRL_PIN(144, "GPIO_144"),
+	PINCTRL_PIN(145, "GPIO_145"),
+
+	PINCTRL_PIN(146, "SDC1_CLK"),
+	PINCTRL_PIN(147, "SDC1_CMD"),
+	PINCTRL_PIN(148, "SDC1_DATA"),
+	PINCTRL_PIN(149, "SDC2_CLK"),
+	PINCTRL_PIN(150, "SDC2_CMD"),
+	PINCTRL_PIN(151, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+
+static const unsigned int sdc1_clk_pins[] = { 146 };
+static const unsigned int sdc1_cmd_pins[] = { 147 };
+static const unsigned int sdc1_data_pins[] = { 148 };
+static const unsigned int sdc2_clk_pins[] = { 149 };
+static const unsigned int sdc2_cmd_pins[] = { 150 };
+static const unsigned int sdc2_data_pins[] = { 151 };
+
+#define FUNCTION(fname)					\
+	[MSM_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7)	\
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			MSM_MUX_gpio,			\
+			MSM_MUX_##f1,			\
+			MSM_MUX_##f2,			\
+			MSM_MUX_##f3,			\
+			MSM_MUX_##f4,			\
+			MSM_MUX_##f5,			\
+			MSM_MUX_##f6,			\
+			MSM_MUX_##f7			\
+		},					\
+		.nfuncs = 8,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x1008 + 0x10 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_target_bit = 5,			\
+		.intr_raw_status_bit = 4,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 2,		\
+	}
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+
+/*
+ * TODO: Add the rest of the possible functions and fill out
+ * the pingroup table below.
+ */
+enum msm8x74_functions {
+	MSM_MUX_gpio,
+	MSM_MUX_cci_i2c0,
+	MSM_MUX_cci_i2c1,
+	MSM_MUX_blsp_i2c1,
+	MSM_MUX_blsp_i2c2,
+	MSM_MUX_blsp_i2c3,
+	MSM_MUX_blsp_i2c4,
+	MSM_MUX_blsp_i2c5,
+	MSM_MUX_blsp_i2c6,
+	MSM_MUX_blsp_i2c7,
+	MSM_MUX_blsp_i2c8,
+	MSM_MUX_blsp_i2c9,
+	MSM_MUX_blsp_i2c10,
+	MSM_MUX_blsp_i2c11,
+	MSM_MUX_blsp_i2c12,
+	MSM_MUX_blsp_spi1,
+	MSM_MUX_blsp_spi1_cs1,
+	MSM_MUX_blsp_spi1_cs2,
+	MSM_MUX_blsp_spi1_cs3,
+	MSM_MUX_blsp_spi2,
+	MSM_MUX_blsp_spi2_cs1,
+	MSM_MUX_blsp_spi2_cs2,
+	MSM_MUX_blsp_spi2_cs3,
+	MSM_MUX_blsp_spi3,
+	MSM_MUX_blsp_spi4,
+	MSM_MUX_blsp_spi5,
+	MSM_MUX_blsp_spi6,
+	MSM_MUX_blsp_spi7,
+	MSM_MUX_blsp_spi8,
+	MSM_MUX_blsp_spi9,
+	MSM_MUX_blsp_spi10,
+	MSM_MUX_blsp_spi10_cs1,
+	MSM_MUX_blsp_spi10_cs2,
+	MSM_MUX_blsp_spi10_cs3,
+	MSM_MUX_blsp_spi11,
+	MSM_MUX_blsp_spi12,
+	MSM_MUX_blsp_uart1,
+	MSM_MUX_blsp_uart2,
+	MSM_MUX_blsp_uart3,
+	MSM_MUX_blsp_uart4,
+	MSM_MUX_blsp_uart5,
+	MSM_MUX_blsp_uart6,
+	MSM_MUX_blsp_uart7,
+	MSM_MUX_blsp_uart8,
+	MSM_MUX_blsp_uart9,
+	MSM_MUX_blsp_uart10,
+	MSM_MUX_blsp_uart11,
+	MSM_MUX_blsp_uart12,
+	MSM_MUX_blsp_uim1,
+	MSM_MUX_blsp_uim2,
+	MSM_MUX_blsp_uim3,
+	MSM_MUX_blsp_uim4,
+	MSM_MUX_blsp_uim5,
+	MSM_MUX_blsp_uim6,
+	MSM_MUX_blsp_uim7,
+	MSM_MUX_blsp_uim8,
+	MSM_MUX_blsp_uim9,
+	MSM_MUX_blsp_uim10,
+	MSM_MUX_blsp_uim11,
+	MSM_MUX_blsp_uim12,
+	MSM_MUX_uim1,
+	MSM_MUX_uim2,
+	MSM_MUX_uim_batt_alarm,
+	MSM_MUX_sdc3,
+	MSM_MUX_sdc4,
+	MSM_MUX_gcc_gp_clk1,
+	MSM_MUX_gcc_gp_clk2,
+	MSM_MUX_gcc_gp_clk3,
+	MSM_MUX_qua_mi2s,
+	MSM_MUX_pri_mi2s,
+	MSM_MUX_spkr_mi2s,
+	MSM_MUX_ter_mi2s,
+	MSM_MUX_sec_mi2s,
+	MSM_MUX_hdmi_cec,
+	MSM_MUX_hdmi_ddc,
+	MSM_MUX_hdmi_hpd,
+	MSM_MUX_edp_hpd,
+	MSM_MUX_mdp_vsync,
+	MSM_MUX_cam_mclk0,
+	MSM_MUX_cam_mclk1,
+	MSM_MUX_cam_mclk2,
+	MSM_MUX_cam_mclk3,
+	MSM_MUX_cci_timer0,
+	MSM_MUX_cci_timer1,
+	MSM_MUX_cci_timer2,
+	MSM_MUX_cci_timer3,
+	MSM_MUX_cci_timer4,
+	MSM_MUX_cci_async_in0,
+	MSM_MUX_cci_async_in1,
+	MSM_MUX_cci_async_in2,
+	MSM_MUX_gp_pdm0,
+	MSM_MUX_gp_pdm1,
+	MSM_MUX_gp_pdm2,
+	MSM_MUX_gp0_clk,
+	MSM_MUX_gp1_clk,
+	MSM_MUX_gp_mn,
+	MSM_MUX_tsif1,
+	MSM_MUX_tsif2,
+	MSM_MUX_hsic,
+	MSM_MUX_grfc,
+	MSM_MUX_audio_ref_clk,
+	MSM_MUX_bt,
+	MSM_MUX_fm,
+	MSM_MUX_wlan,
+	MSM_MUX_slimbus,
+	MSM_MUX_NA,
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145"
+};
+
+static const char * const blsp_uart1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_uim1_groups[] = { "gpio0", "gpio1" };
+static const char * const blsp_i2c1_groups[] = { "gpio2", "gpio3" };
+static const char * const blsp_spi1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_spi1_cs1_groups[] = { "gpio8" };
+static const char * const blsp_spi1_cs2_groups[] = { "gpio9", "gpio11" };
+static const char * const blsp_spi1_cs3_groups[] = { "gpio10" };
+
+static const char * const blsp_uart2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_uim2_groups[] = { "gpio4", "gpio5" };
+static const char * const blsp_i2c2_groups[] = { "gpio6", "gpio7" };
+static const char * const blsp_spi2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_spi2_cs1_groups[] = { "gpio53", "gpio62" };
+static const char * const blsp_spi2_cs2_groups[] = { "gpio54", "gpio63" };
+static const char * const blsp_spi2_cs3_groups[] = { "gpio66" };
+
+static const char * const blsp_uart3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11"
+};
+static const char * const blsp_uim3_groups[] = { "gpio8", "gpio9" };
+static const char * const blsp_i2c3_groups[] = { "gpio10", "gpio11" };
+static const char * const blsp_spi3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11"
+};
+
+static const char * const cci_i2c0_groups[] = { "gpio19", "gpio20" };
+static const char * const cci_i2c1_groups[] = { "gpio21", "gpio22" };
+
+static const char * const blsp_uart4_groups[] = {
+	"gpio19", "gpio20", "gpio21", "gpio22"
+};
+static const char * const blsp_uim4_groups[] = { "gpio19", "gpio20" };
+static const char * const blsp_i2c4_groups[] = { "gpio21", "gpio22" };
+static const char * const blsp_spi4_groups[] = {
+	"gpio19", "gpio20", "gpio21", "gpio22"
+};
+
+static const char * const blsp_uart5_groups[] = {
+	"gpio23", "gpio24", "gpio25", "gpio26"
+};
+static const char * const blsp_uim5_groups[] = { "gpio23", "gpio24" };
+static const char * const blsp_i2c5_groups[] = { "gpio25", "gpio26" };
+static const char * const blsp_spi5_groups[] = {
+	"gpio23", "gpio24", "gpio25", "gpio26"
+};
+
+static const char * const blsp_uart6_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30"
+};
+static const char * const blsp_uim6_groups[] = { "gpio27", "gpio28" };
+static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" };
+static const char * const blsp_spi6_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30"
+};
+
+static const char * const blsp_uart7_groups[] = {
+	"gpio41", "gpio42", "gpio43", "gpio44"
+};
+static const char * const blsp_uim7_groups[] = { "gpio41", "gpio42" };
+static const char * const blsp_i2c7_groups[] = { "gpio43", "gpio44" };
+static const char * const blsp_spi7_groups[] = {
+	"gpio41", "gpio42", "gpio43", "gpio44"
+};
+
+static const char * const blsp_uart8_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48"
+};
+static const char * const blsp_uim8_groups[] = { "gpio45", "gpio46" };
+static const char * const blsp_i2c8_groups[] = { "gpio47", "gpio48" };
+static const char * const blsp_spi8_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48"
+};
+
+static const char * const blsp_uart9_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_uim9_groups[] = { "gpio49", "gpio50" };
+static const char * const blsp_i2c9_groups[] = { "gpio51", "gpio52" };
+static const char * const blsp_spi9_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+
+static const char * const blsp_uart10_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_uim10_groups[] = { "gpio53", "gpio54" };
+static const char * const blsp_i2c10_groups[] = { "gpio55", "gpio56" };
+static const char * const blsp_spi10_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_spi10_cs1_groups[] = { "gpio47", "gpio67" };
+static const char * const blsp_spi10_cs2_groups[] = { "gpio48", "gpio68" };
+static const char * const blsp_spi10_cs3_groups[] = { "gpio90" };
+
+static const char * const blsp_uart11_groups[] = {
+	"gpio81", "gpio82", "gpio83", "gpio84"
+};
+static const char * const blsp_uim11_groups[] = { "gpio81", "gpio82" };
+static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" };
+static const char * const blsp_spi11_groups[] = {
+	"gpio81", "gpio82", "gpio83", "gpio84"
+};
+
+static const char * const blsp_uart12_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88"
+};
+static const char * const blsp_uim12_groups[] = { "gpio85", "gpio86" };
+static const char * const blsp_i2c12_groups[] = { "gpio87", "gpio88" };
+static const char * const blsp_spi12_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88"
+};
+
+static const char * const uim1_groups[] = {
+	"gpio97", "gpio98", "gpio99", "gpio100"
+};
+
+static const char * const uim2_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+
+static const char * const uim_batt_alarm_groups[] = { "gpio101" };
+
+static const char * const sdc3_groups[] = {
+	"gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40"
+};
+
+static const char * const sdc4_groups[] = {
+	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
+};
+
+static const char * const gp0_clk_groups[] = { "gpio26" };
+static const char * const gp1_clk_groups[] = { "gpio27", "gpio57", "gpio78" };
+static const char * const gp_mn_groups[] = { "gpio29" };
+static const char * const gcc_gp_clk1_groups[] = { "gpio57", "gpio78" };
+static const char * const gcc_gp_clk2_groups[] = { "gpio58", "gpio81" };
+static const char * const gcc_gp_clk3_groups[] = { "gpio59", "gpio82" };
+
+static const char * const qua_mi2s_groups[] = {
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+
+static const char * const pri_mi2s_groups[] = {
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+
+static const char * const spkr_mi2s_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72"
+};
+
+static const char * const ter_mi2s_groups[] = {
+	"gpio73", "gpio74", "gpio75", "gpio76", "gpio77"
+};
+
+static const char * const sec_mi2s_groups[] = {
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
+};
+
+static const char * const hdmi_cec_groups[] = { "gpio31" };
+static const char * const hdmi_ddc_groups[] = { "gpio32", "gpio33" };
+static const char * const hdmi_hpd_groups[] = { "gpio34" };
+static const char * const edp_hpd_groups[] = { "gpio102" };
+
+static const char * const mdp_vsync_groups[] = { "gpio12", "gpio13", "gpio14" };
+static const char * const cam_mclk0_groups[] = { "gpio15" };
+static const char * const cam_mclk1_groups[] = { "gpio16" };
+static const char * const cam_mclk2_groups[] = { "gpio17" };
+static const char * const cam_mclk3_groups[] = { "gpio18" };
+
+static const char * const cci_timer0_groups[] = { "gpio23" };
+static const char * const cci_timer1_groups[] = { "gpio24" };
+static const char * const cci_timer2_groups[] = { "gpio25" };
+static const char * const cci_timer3_groups[] = { "gpio26" };
+static const char * const cci_timer4_groups[] = { "gpio27" };
+static const char * const cci_async_in0_groups[] = { "gpio28" };
+static const char * const cci_async_in1_groups[] = { "gpio26" };
+static const char * const cci_async_in2_groups[] = { "gpio27" };
+
+static const char * const gp_pdm0_groups[] = { "gpio54", "gpio68" };
+static const char * const gp_pdm1_groups[] = { "gpio74", "gpio86" };
+static const char * const gp_pdm2_groups[] = { "gpio63", "gpio79" };
+
+static const char * const tsif1_groups[] = {
+	"gpio89", "gpio90", "gpio91", "gpio92"
+};
+
+static const char * const tsif2_groups[] = {
+	"gpio93", "gpio94", "gpio95", "gpio96"
+};
+
+static const char * const hsic_groups[] = { "gpio144", "gpio145" };
+static const char * const grfc_groups[] = {
+	"gpio104", "gpio105", "gpio106", "gpio107", "gpio108", "gpio109",
+	"gpio110", "gpio111", "gpio112", "gpio113", "gpio114", "gpio115",
+	"gpio116", "gpio117", "gpio118", "gpio119", "gpio120", "gpio121",
+	"gpio122", "gpio123", "gpio124", "gpio125", "gpio126", "gpio127",
+	"gpio128", "gpio136", "gpio137", "gpio141", "gpio143"
+};
+
+static const char * const audio_ref_clk_groups[] = { "gpio69" };
+
+static const char * const bt_groups[] = { "gpio35", "gpio43", "gpio44" };
+
+static const char * const fm_groups[] = { "gpio41", "gpio42" };
+
+static const char * const wlan_groups[] = {
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40"
+};
+
+static const char * const slimbus_groups[] = { "gpio70", "gpio71" };
+
+static const struct msm_function msm8x74_functions[] = {
+	FUNCTION(gpio),
+	FUNCTION(cci_i2c0),
+	FUNCTION(cci_i2c1),
+	FUNCTION(uim1),
+	FUNCTION(uim2),
+	FUNCTION(uim_batt_alarm),
+	FUNCTION(blsp_uim1),
+	FUNCTION(blsp_uim2),
+	FUNCTION(blsp_uim3),
+	FUNCTION(blsp_uim4),
+	FUNCTION(blsp_uim5),
+	FUNCTION(blsp_uim6),
+	FUNCTION(blsp_uim7),
+	FUNCTION(blsp_uim8),
+	FUNCTION(blsp_uim9),
+	FUNCTION(blsp_uim10),
+	FUNCTION(blsp_uim11),
+	FUNCTION(blsp_uim12),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(blsp_i2c2),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(blsp_i2c5),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(blsp_i2c7),
+	FUNCTION(blsp_i2c8),
+	FUNCTION(blsp_i2c9),
+	FUNCTION(blsp_i2c10),
+	FUNCTION(blsp_i2c11),
+	FUNCTION(blsp_i2c12),
+	FUNCTION(blsp_spi1),
+	FUNCTION(blsp_spi1_cs1),
+	FUNCTION(blsp_spi1_cs2),
+	FUNCTION(blsp_spi1_cs3),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_spi2_cs1),
+	FUNCTION(blsp_spi2_cs2),
+	FUNCTION(blsp_spi2_cs3),
+	FUNCTION(blsp_spi3),
+	FUNCTION(blsp_spi4),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_spi6),
+	FUNCTION(blsp_spi7),
+	FUNCTION(blsp_spi8),
+	FUNCTION(blsp_spi9),
+	FUNCTION(blsp_spi10),
+	FUNCTION(blsp_spi10_cs1),
+	FUNCTION(blsp_spi10_cs2),
+	FUNCTION(blsp_spi10_cs3),
+	FUNCTION(blsp_spi11),
+	FUNCTION(blsp_spi12),
+	FUNCTION(blsp_uart1),
+	FUNCTION(blsp_uart2),
+	FUNCTION(blsp_uart3),
+	FUNCTION(blsp_uart4),
+	FUNCTION(blsp_uart5),
+	FUNCTION(blsp_uart6),
+	FUNCTION(blsp_uart7),
+	FUNCTION(blsp_uart8),
+	FUNCTION(blsp_uart9),
+	FUNCTION(blsp_uart10),
+	FUNCTION(blsp_uart11),
+	FUNCTION(blsp_uart12),
+	FUNCTION(sdc3),
+	FUNCTION(sdc4),
+	FUNCTION(gcc_gp_clk1),
+	FUNCTION(gcc_gp_clk2),
+	FUNCTION(gcc_gp_clk3),
+	FUNCTION(qua_mi2s),
+	FUNCTION(pri_mi2s),
+	FUNCTION(spkr_mi2s),
+	FUNCTION(ter_mi2s),
+	FUNCTION(sec_mi2s),
+	FUNCTION(mdp_vsync),
+	FUNCTION(cam_mclk0),
+	FUNCTION(cam_mclk1),
+	FUNCTION(cam_mclk2),
+	FUNCTION(cam_mclk3),
+	FUNCTION(cci_timer0),
+	FUNCTION(cci_timer1),
+	FUNCTION(cci_timer2),
+	FUNCTION(cci_timer3),
+	FUNCTION(cci_timer4),
+	FUNCTION(cci_async_in0),
+	FUNCTION(cci_async_in1),
+	FUNCTION(cci_async_in2),
+	FUNCTION(hdmi_cec),
+	FUNCTION(hdmi_ddc),
+	FUNCTION(hdmi_hpd),
+	FUNCTION(edp_hpd),
+	FUNCTION(gp_pdm0),
+	FUNCTION(gp_pdm1),
+	FUNCTION(gp_pdm2),
+	FUNCTION(gp0_clk),
+	FUNCTION(gp1_clk),
+	FUNCTION(gp_mn),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(hsic),
+	FUNCTION(grfc),
+	FUNCTION(audio_ref_clk),
+	FUNCTION(bt),
+	FUNCTION(fm),
+	FUNCTION(wlan),
+	FUNCTION(slimbus),
+};
+
+static const struct msm_pingroup msm8x74_groups[] = {
+	PINGROUP(0,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA),
+	PINGROUP(1,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA),
+	PINGROUP(2,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA),
+	PINGROUP(3,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA),
+	PINGROUP(4,   blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA),
+	PINGROUP(5,   blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA),
+	PINGROUP(6,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA),
+	PINGROUP(7,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA),
+	PINGROUP(8,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA, NA),
+	PINGROUP(9,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA, NA),
+	PINGROUP(10,  blsp_spi3, blsp_uart3, blsp_i2c3, blsp_spi1_cs3, NA, NA, NA),
+	PINGROUP(11,  blsp_spi3, blsp_uart3, blsp_i2c3, blsp_spi1_cs2, NA, NA, NA),
+	PINGROUP(12,  mdp_vsync, NA, NA, NA, NA, NA, NA),
+	PINGROUP(13,  mdp_vsync, NA, NA, NA, NA, NA, NA),
+	PINGROUP(14,  mdp_vsync, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15,  cam_mclk0, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16,  cam_mclk1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17,  cam_mclk2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18,  cam_mclk3, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA),
+	PINGROUP(20,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA),
+	PINGROUP(21,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA),
+	PINGROUP(22,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA),
+	PINGROUP(23,  cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA),
+	PINGROUP(24,  cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA),
+	PINGROUP(25,  cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA),
+	PINGROUP(26,  cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5, blsp_i2c5, gp0_clk, NA),
+	PINGROUP(27,  cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk, NA),
+	PINGROUP(28,  cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, NA, NA, NA),
+	PINGROUP(29,  blsp_spi6, blsp_uart6, blsp_i2c6, gp_mn, NA, NA, NA),
+	PINGROUP(30,  blsp_spi6, blsp_uart6, blsp_i2c6, NA, NA, NA, NA),
+	PINGROUP(31,  hdmi_cec, NA, NA, NA, NA, NA, NA),
+	PINGROUP(32,  hdmi_ddc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(33,  hdmi_ddc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34,  hdmi_hpd, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35,  bt, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(36,  wlan, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(37,  wlan, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(38,  wlan, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(39,  wlan, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(40,  wlan, sdc3, NA, NA, NA, NA, NA),
+	PINGROUP(41,  fm, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA),
+	PINGROUP(42,  fm, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA),
+	PINGROUP(43,  bt, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA),
+	PINGROUP(44,  bt, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA),
+	PINGROUP(45,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA),
+	PINGROUP(46,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA),
+	PINGROUP(47,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA, NA),
+	PINGROUP(48,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA, NA),
+	PINGROUP(49,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA),
+	PINGROUP(50,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA),
+	PINGROUP(51,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA),
+	PINGROUP(52,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA),
+	PINGROUP(53,  blsp_spi10, blsp_uart10, blsp_uim10, blsp_spi2_cs1, NA, NA, NA),
+	PINGROUP(54,  blsp_spi10, blsp_uart10, blsp_uim10, blsp_spi2_cs2, gp_pdm0, NA, NA),
+	PINGROUP(55,  blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA),
+	PINGROUP(56,  blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA),
+	PINGROUP(57,  qua_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA),
+	PINGROUP(58,  qua_mi2s, gcc_gp_clk2, NA, NA, NA, NA, NA),
+	PINGROUP(59,  qua_mi2s, gcc_gp_clk3, NA, NA, NA, NA, NA),
+	PINGROUP(60,  qua_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61,  qua_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62,  qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA),
+	PINGROUP(63,  qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA),
+	PINGROUP(64,  pri_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65,  pri_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66,  pri_mi2s, blsp_spi2_cs3, NA, NA, NA, NA, NA),
+	PINGROUP(67,  pri_mi2s, blsp_spi10_cs1, NA, NA, NA, NA, NA),
+	PINGROUP(68,  pri_mi2s, blsp_spi10_cs2, gp_pdm0, NA, NA, NA, NA),
+	PINGROUP(69,  spkr_mi2s, audio_ref_clk, NA, NA, NA, NA, NA),
+	PINGROUP(70,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA),
+	PINGROUP(71,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA),
+	PINGROUP(72,  spkr_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73,  ter_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74,  ter_mi2s, gp_pdm1, NA, NA, NA, NA, NA),
+	PINGROUP(75,  ter_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76,  ter_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77,  ter_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78,  sec_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA),
+	PINGROUP(79,  sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA),
+	PINGROUP(80,  sec_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, gcc_gp_clk2, NA, NA),
+	PINGROUP(82,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, gcc_gp_clk3, NA, NA),
+	PINGROUP(83,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA),
+	PINGROUP(84,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA),
+	PINGROUP(85,  blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, NA, NA),
+	PINGROUP(86,  blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA, NA, NA),
+	PINGROUP(87,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA),
+	PINGROUP(88,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA),
+	PINGROUP(89,  tsif1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90,  tsif1, blsp_spi10_cs3, NA, NA, NA, NA, NA),
+	PINGROUP(91,  tsif1, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(92,  tsif1, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(93,  tsif2, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(94,  tsif2, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(95,  tsif2, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(96,  tsif2, sdc4, NA, NA, NA, NA, NA),
+	PINGROUP(97,  uim1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98,  uim1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(99,  uim1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA),
+	PINGROUP(102, edp_hpd, NA, NA, NA, NA, NA, NA),
+	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(104, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(105, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(106, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(107, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(108, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(109, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(110, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(111, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(112, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(113, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(114, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(115, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(116, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(117, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(118, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(119, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(120, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(121, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(122, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(123, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(124, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(125, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(126, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(127, grfc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(128, NA, grfc, NA, NA, NA, NA, NA),
+	PINGROUP(129, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(130, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(131, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(132, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(133, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(134, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(135, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(136, NA, grfc, NA, NA, NA, NA, NA),
+	PINGROUP(137, NA, grfc, NA, NA, NA, NA, NA),
+	PINGROUP(138, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(139, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(140, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(141, NA, grfc, NA, NA, NA, NA, NA),
+	PINGROUP(142, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(143, NA, grfc, NA, NA, NA, NA, NA),
+	PINGROUP(144, hsic, NA, NA, NA, NA, NA, NA),
+	PINGROUP(145, hsic, NA, NA, NA, NA, NA, NA),
+	SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6),
+	SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3),
+	SDC_PINGROUP(sdc1_data, 0x2044, 9, 0),
+	SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6),
+	SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3),
+	SDC_PINGROUP(sdc2_data, 0x2048, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 146
+
+static const struct msm_pinctrl_soc_data msm8x74_pinctrl = {
+	.pins = msm8x74_pins,
+	.npins = ARRAY_SIZE(msm8x74_pins),
+	.functions = msm8x74_functions,
+	.nfunctions = ARRAY_SIZE(msm8x74_functions),
+	.groups = msm8x74_groups,
+	.ngroups = ARRAY_SIZE(msm8x74_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int msm8x74_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8x74_pinctrl);
+}
+
+static const struct of_device_id msm8x74_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8974-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8x74_pinctrl_driver = {
+	.driver = {
+		.name = "msm8x74-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm8x74_pinctrl_of_match,
+	},
+	.probe = msm8x74_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8x74_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8x74_pinctrl_driver);
+}
+arch_initcall(msm8x74_pinctrl_init);
+
+static void __exit msm8x74_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8x74_pinctrl_driver);
+}
+module_exit(msm8x74_pinctrl_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm MSM8x74 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8x74_pinctrl_of_match);
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm.c
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 2013, Sony Mobile Communications AB.
+ * Copyright (c) 2013, 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/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "pinctrl-msm.h"
+#include "../pinctrl-utils.h"
+
+#define MAX_NR_GPIO 300
+
+/**
+ * struct msm_pinctrl - state for a pinctrl-msm device
+ * @dev:            device handle.
+ * @pctrl:          pinctrl handle.
+ * @chip:           gpiochip handle.
+ * @irq:            parent irq for the TLMM irq_chip.
+ * @lock:           Spinlock to protect register resources as well
+ *                  as msm_pinctrl data structures.
+ * @enabled_irqs:   Bitmap of currently enabled irqs.
+ * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
+ *                  detection.
+ * @soc;            Reference to soc_data of platform specific data.
+ * @regs:           Base address for the TLMM register map.
+ */
+struct msm_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctrl;
+	struct gpio_chip chip;
+	int irq;
+
+	spinlock_t lock;
+
+	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
+	DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
+
+	const struct msm_pinctrl_soc_data *soc;
+	void __iomem *regs;
+};
+
+static inline struct msm_pinctrl *to_msm_pinctrl(struct gpio_chip *gc)
+{
+	return container_of(gc, struct msm_pinctrl, chip);
+}
+
+static int msm_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->soc->ngroups;
+}
+
+static const char *msm_get_group_name(struct pinctrl_dev *pctldev,
+				      unsigned group)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->soc->groups[group].name;
+}
+
+static int msm_get_group_pins(struct pinctrl_dev *pctldev,
+			      unsigned group,
+			      const unsigned **pins,
+			      unsigned *num_pins)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = pctrl->soc->groups[group].pins;
+	*num_pins = pctrl->soc->groups[group].npins;
+	return 0;
+}
+
+static const struct pinctrl_ops msm_pinctrl_ops = {
+	.get_groups_count	= msm_get_groups_count,
+	.get_group_name		= msm_get_group_name,
+	.get_group_pins		= msm_get_group_pins,
+	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
+	.dt_free_map		= pinctrl_utils_dt_free_map,
+};
+
+static int msm_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->soc->nfunctions;
+}
+
+static const char *msm_get_function_name(struct pinctrl_dev *pctldev,
+					 unsigned function)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->soc->functions[function].name;
+}
+
+static int msm_get_function_groups(struct pinctrl_dev *pctldev,
+				   unsigned function,
+				   const char * const **groups,
+				   unsigned * const num_groups)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pctrl->soc->functions[function].groups;
+	*num_groups = pctrl->soc->functions[function].ngroups;
+	return 0;
+}
+
+static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
+			     unsigned function,
+			     unsigned group)
+{
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	g = &pctrl->soc->groups[group];
+
+	for (i = 0; i < g->nfuncs; i++) {
+		if (g->funcs[i] == function)
+			break;
+	}
+
+	if (WARN_ON(i == g->nfuncs))
+		return -EINVAL;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->ctl_reg);
+	val &= ~(0x7 << g->mux_bit);
+	val |= i << g->mux_bit;
+	writel(val, pctrl->regs + g->ctl_reg);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return 0;
+}
+
+static const struct pinmux_ops msm_pinmux_ops = {
+	.get_functions_count	= msm_get_functions_count,
+	.get_function_name	= msm_get_function_name,
+	.get_function_groups	= msm_get_function_groups,
+	.enable			= msm_pinmux_enable,
+};
+
+static int msm_config_reg(struct msm_pinctrl *pctrl,
+			  const struct msm_pingroup *g,
+			  unsigned param,
+			  unsigned *mask,
+			  unsigned *bit)
+{
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+	case PIN_CONFIG_BIAS_BUS_HOLD:
+	case PIN_CONFIG_BIAS_PULL_UP:
+		*bit = g->pull_bit;
+		*mask = 3;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		*bit = g->drv_bit;
+		*mask = 7;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		*bit = g->oe_bit;
+		*mask = 1;
+		break;
+	default:
+		dev_err(pctrl->dev, "Invalid config param %04x\n", param);
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int msm_config_get(struct pinctrl_dev *pctldev,
+			  unsigned int pin,
+			  unsigned long *config)
+{
+	dev_err(pctldev->dev, "pin_config_set op not supported\n");
+	return -ENOTSUPP;
+}
+
+static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long *configs, unsigned num_configs)
+{
+	dev_err(pctldev->dev, "pin_config_set op not supported\n");
+	return -ENOTSUPP;
+}
+
+#define MSM_NO_PULL	0
+#define MSM_PULL_DOWN	1
+#define MSM_KEEPER	2
+#define MSM_PULL_UP	3
+
+static unsigned msm_regval_to_drive(u32 val)
+{
+	return (val + 1) * 2;
+}
+
+static int msm_config_group_get(struct pinctrl_dev *pctldev,
+				unsigned int group,
+				unsigned long *config)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned param = pinconf_to_config_param(*config);
+	unsigned mask;
+	unsigned arg;
+	unsigned bit;
+	int ret;
+	u32 val;
+
+	g = &pctrl->soc->groups[group];
+
+	ret = msm_config_reg(pctrl, g, param, &mask, &bit);
+	if (ret < 0)
+		return ret;
+
+	val = readl(pctrl->regs + g->ctl_reg);
+	arg = (val >> bit) & mask;
+
+	/* Convert register value to pinconf value */
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		arg = arg == MSM_NO_PULL;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		arg = arg == MSM_PULL_DOWN;
+		break;
+	case PIN_CONFIG_BIAS_BUS_HOLD:
+		arg = arg == MSM_KEEPER;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		arg = arg == MSM_PULL_UP;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		arg = msm_regval_to_drive(arg);
+		break;
+	case PIN_CONFIG_OUTPUT:
+		/* Pin is not output */
+		if (!arg)
+			return -EINVAL;
+
+		val = readl(pctrl->regs + g->io_reg);
+		arg = !!(val & BIT(g->in_bit));
+		break;
+	default:
+		dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
+			param);
+		return -EINVAL;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+
+	return 0;
+}
+
+static int msm_config_group_set(struct pinctrl_dev *pctldev,
+				unsigned group,
+				unsigned long *configs,
+				unsigned num_configs)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned long flags;
+	unsigned param;
+	unsigned mask;
+	unsigned arg;
+	unsigned bit;
+	int ret;
+	u32 val;
+	int i;
+
+	g = &pctrl->soc->groups[group];
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		ret = msm_config_reg(pctrl, g, param, &mask, &bit);
+		if (ret < 0)
+			return ret;
+
+		/* Convert pinconf values to register values */
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			arg = MSM_NO_PULL;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			arg = MSM_PULL_DOWN;
+			break;
+		case PIN_CONFIG_BIAS_BUS_HOLD:
+			arg = MSM_KEEPER;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			arg = MSM_PULL_UP;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			/* Check for invalid values */
+			if (arg > 16 || arg < 2 || (arg % 2) != 0)
+				arg = -1;
+			else
+				arg = (arg / 2) - 1;
+			break;
+		case PIN_CONFIG_OUTPUT:
+			/* set output value */
+			spin_lock_irqsave(&pctrl->lock, flags);
+			val = readl(pctrl->regs + g->io_reg);
+			if (arg)
+				val |= BIT(g->out_bit);
+			else
+				val &= ~BIT(g->out_bit);
+			writel(val, pctrl->regs + g->io_reg);
+			spin_unlock_irqrestore(&pctrl->lock, flags);
+
+			/* enable output */
+			arg = 1;
+			break;
+		default:
+			dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
+				param);
+			return -EINVAL;
+		}
+
+		/* Range-check user-supplied value */
+		if (arg & ~mask) {
+			dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg);
+			return -EINVAL;
+		}
+
+		spin_lock_irqsave(&pctrl->lock, flags);
+		val = readl(pctrl->regs + g->ctl_reg);
+		val &= ~(mask << bit);
+		val |= arg << bit;
+		writel(val, pctrl->regs + g->ctl_reg);
+		spin_unlock_irqrestore(&pctrl->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops msm_pinconf_ops = {
+	.pin_config_get		= msm_config_get,
+	.pin_config_set		= msm_config_set,
+	.pin_config_group_get	= msm_config_group_get,
+	.pin_config_group_set	= msm_config_group_set,
+};
+
+static struct pinctrl_desc msm_pinctrl_desc = {
+	.pctlops = &msm_pinctrl_ops,
+	.pmxops = &msm_pinmux_ops,
+	.confops = &msm_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[offset];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->ctl_reg);
+	val &= ~BIT(g->oe_bit);
+	writel(val, pctrl->regs + g->ctl_reg);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return 0;
+}
+
+static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[offset];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->io_reg);
+	if (value)
+		val |= BIT(g->out_bit);
+	else
+		val &= ~BIT(g->out_bit);
+	writel(val, pctrl->regs + g->io_reg);
+
+	val = readl(pctrl->regs + g->ctl_reg);
+	val |= BIT(g->oe_bit);
+	writel(val, pctrl->regs + g->ctl_reg);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
+	u32 val;
+
+	g = &pctrl->soc->groups[offset];
+
+	val = readl(pctrl->regs + g->io_reg);
+	return !!(val & BIT(g->in_bit));
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[offset];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->io_reg);
+	if (value)
+		val |= BIT(g->out_bit);
+	else
+		val &= ~BIT(g->out_bit);
+	writel(val, pctrl->regs + g->io_reg);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+	return pinctrl_request_gpio(gpio);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+	return pinctrl_free_gpio(gpio);
+}
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+static void msm_gpio_dbg_show_one(struct seq_file *s,
+				  struct pinctrl_dev *pctldev,
+				  struct gpio_chip *chip,
+				  unsigned offset,
+				  unsigned gpio)
+{
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
+	unsigned func;
+	int is_out;
+	int drive;
+	int pull;
+	u32 ctl_reg;
+
+	static const char * const pulls[] = {
+		"no pull",
+		"pull down",
+		"keeper",
+		"pull up"
+	};
+
+	g = &pctrl->soc->groups[offset];
+	ctl_reg = readl(pctrl->regs + g->ctl_reg);
+
+	is_out = !!(ctl_reg & BIT(g->oe_bit));
+	func = (ctl_reg >> g->mux_bit) & 7;
+	drive = (ctl_reg >> g->drv_bit) & 7;
+	pull = (ctl_reg >> g->pull_bit) & 3;
+
+	seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
+	seq_printf(s, " %dmA", msm_regval_to_drive(drive));
+	seq_printf(s, " %s", pulls[pull]);
+}
+
+static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	unsigned gpio = chip->base;
+	unsigned i;
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
+		seq_puts(s, "\n");
+	}
+}
+
+#else
+#define msm_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip msm_gpio_template = {
+	.direction_input  = msm_gpio_direction_input,
+	.direction_output = msm_gpio_direction_output,
+	.get              = msm_gpio_get,
+	.set              = msm_gpio_set,
+	.request          = msm_gpio_request,
+	.free             = msm_gpio_free,
+	.dbg_show         = msm_gpio_dbg_show,
+};
+
+/* For dual-edge interrupts in software, since some hardware has no
+ * such support:
+ *
+ * At appropriate moments, this function may be called to flip the polarity
+ * settings of both-edge irq lines to try and catch the next edge.
+ *
+ * The attempt is considered successful if:
+ * - the status bit goes high, indicating that an edge was caught, or
+ * - the input value of the gpio doesn't change during the attempt.
+ * If the value changes twice during the process, that would cause the first
+ * test to fail but would force the second, as two opposite
+ * transitions would cause a detection no matter the polarity setting.
+ *
+ * The do-loop tries to sledge-hammer closed the timing hole between
+ * the initial value-read and the polarity-write - if the line value changes
+ * during that window, an interrupt is lost, the new polarity setting is
+ * incorrect, and the first success test will fail, causing a retry.
+ *
+ * Algorithm comes from Google's msmgpio driver.
+ */
+static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
+					  const struct msm_pingroup *g,
+					  struct irq_data *d)
+{
+	int loop_limit = 100;
+	unsigned val, val2, intstat;
+	unsigned pol;
+
+	do {
+		val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
+
+		pol = readl(pctrl->regs + g->intr_cfg_reg);
+		pol ^= BIT(g->intr_polarity_bit);
+		writel(pol, pctrl->regs + g->intr_cfg_reg);
+
+		val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
+		intstat = readl(pctrl->regs + g->intr_status_reg);
+		if (intstat || (val == val2))
+			return;
+	} while (loop_limit-- > 0);
+	dev_err(pctrl->dev, "dual-edge irq failed to stabilize, %#08x != %#08x\n",
+		val, val2);
+}
+
+static void msm_gpio_irq_mask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[d->hwirq];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val &= ~BIT(g->intr_enable_bit);
+	writel(val, pctrl->regs + g->intr_cfg_reg);
+
+	clear_bit(d->hwirq, pctrl->enabled_irqs);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[d->hwirq];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->intr_status_reg);
+	val &= ~BIT(g->intr_status_bit);
+	writel(val, pctrl->regs + g->intr_status_reg);
+
+	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val |= BIT(g->intr_enable_bit);
+	writel(val, pctrl->regs + g->intr_cfg_reg);
+
+	set_bit(d->hwirq, pctrl->enabled_irqs);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void msm_gpio_irq_ack(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[d->hwirq];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	val = readl(pctrl->regs + g->intr_status_reg);
+	if (g->intr_ack_high)
+		val |= BIT(g->intr_status_bit);
+	else
+		val &= ~BIT(g->intr_status_bit);
+	writel(val, pctrl->regs + g->intr_status_reg);
+
+	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
+		msm_gpio_update_dual_edge_pos(pctrl, g, d);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+#define INTR_TARGET_PROC_APPS    4
+
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	u32 val;
+
+	g = &pctrl->soc->groups[d->hwirq];
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	/*
+	 * For hw without possibility of detecting both edges
+	 */
+	if (g->intr_detection_width == 1 && type == IRQ_TYPE_EDGE_BOTH)
+		set_bit(d->hwirq, pctrl->dual_edge_irqs);
+	else
+		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
+
+	/* Route interrupts to application cpu */
+	val = readl(pctrl->regs + g->intr_target_reg);
+	val &= ~(7 << g->intr_target_bit);
+	val |= INTR_TARGET_PROC_APPS << g->intr_target_bit;
+	writel(val, pctrl->regs + g->intr_target_reg);
+
+	/* Update configuration for gpio.
+	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
+	 * internal circuitry of TLMM, toggling the RAW_STATUS
+	 * could cause the INTR_STATUS to be set for EDGE interrupts.
+	 */
+	val = readl(pctrl->regs + g->intr_cfg_reg);
+	val |= BIT(g->intr_raw_status_bit);
+	if (g->intr_detection_width == 2) {
+		val &= ~(3 << g->intr_detection_bit);
+		val &= ~(1 << g->intr_polarity_bit);
+		switch (type) {
+		case IRQ_TYPE_EDGE_RISING:
+			val |= 1 << g->intr_detection_bit;
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		case IRQ_TYPE_EDGE_FALLING:
+			val |= 2 << g->intr_detection_bit;
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		case IRQ_TYPE_EDGE_BOTH:
+			val |= 3 << g->intr_detection_bit;
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		case IRQ_TYPE_LEVEL_LOW:
+			break;
+		case IRQ_TYPE_LEVEL_HIGH:
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		}
+	} else if (g->intr_detection_width == 1) {
+		val &= ~(1 << g->intr_detection_bit);
+		val &= ~(1 << g->intr_polarity_bit);
+		switch (type) {
+		case IRQ_TYPE_EDGE_RISING:
+			val |= BIT(g->intr_detection_bit);
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		case IRQ_TYPE_EDGE_FALLING:
+			val |= BIT(g->intr_detection_bit);
+			break;
+		case IRQ_TYPE_EDGE_BOTH:
+			val |= BIT(g->intr_detection_bit);
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		case IRQ_TYPE_LEVEL_LOW:
+			break;
+		case IRQ_TYPE_LEVEL_HIGH:
+			val |= BIT(g->intr_polarity_bit);
+			break;
+		}
+	} else {
+		BUG();
+	}
+	writel(val, pctrl->regs + g->intr_cfg_reg);
+
+	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
+		msm_gpio_update_dual_edge_pos(pctrl, g, d);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+
+	return 0;
+}
+
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	irq_set_irq_wake(pctrl->irq, on);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return 0;
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+	.name           = "msmgpio",
+	.irq_mask       = msm_gpio_irq_mask,
+	.irq_unmask     = msm_gpio_irq_unmask,
+	.irq_ack        = msm_gpio_irq_ack,
+	.irq_set_type   = msm_gpio_irq_set_type,
+	.irq_set_wake   = msm_gpio_irq_set_wake,
+};
+
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	const struct msm_pingroup *g;
+	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+	struct irq_chip *chip = irq_get_chip(irq);
+	int irq_pin;
+	int handled = 0;
+	u32 val;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	/*
+	 * Each pin has it's own IRQ status register, so use
+	 * enabled_irq bitmap to limit the number of reads.
+	 */
+	for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
+		g = &pctrl->soc->groups[i];
+		val = readl(pctrl->regs + g->intr_status_reg);
+		if (val & BIT(g->intr_status_bit)) {
+			irq_pin = irq_find_mapping(gc->irqdomain, i);
+			generic_handle_irq(irq_pin);
+			handled++;
+		}
+	}
+
+	/* No interrupts were flagged */
+	if (handled == 0)
+		handle_bad_irq(irq, desc);
+
+	chained_irq_exit(chip, desc);
+}
+
+static int msm_gpio_init(struct msm_pinctrl *pctrl)
+{
+	struct gpio_chip *chip;
+	int ret;
+	unsigned ngpio = pctrl->soc->ngpios;
+
+	if (WARN_ON(ngpio > MAX_NR_GPIO))
+		return -EINVAL;
+
+	chip = &pctrl->chip;
+	chip->base = 0;
+	chip->ngpio = ngpio;
+	chip->label = dev_name(pctrl->dev);
+	chip->dev = pctrl->dev;
+	chip->owner = THIS_MODULE;
+	chip->of_node = pctrl->dev->of_node;
+
+	ret = gpiochip_add(&pctrl->chip);
+	if (ret) {
+		dev_err(pctrl->dev, "Failed register gpiochip\n");
+		return ret;
+	}
+
+	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
+	if (ret) {
+		dev_err(pctrl->dev, "Failed to add pin range\n");
+		return ret;
+	}
+
+	ret = gpiochip_irqchip_add(chip,
+				   &msm_gpio_irq_chip,
+				   0,
+				   handle_edge_irq,
+				   IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
+		return -ENOSYS;
+	}
+
+	gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
+				     msm_gpio_irq_handler);
+
+	return 0;
+}
+
+int msm_pinctrl_probe(struct platform_device *pdev,
+		      const struct msm_pinctrl_soc_data *soc_data)
+{
+	struct msm_pinctrl *pctrl;
+	struct resource *res;
+	int ret;
+
+	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+	if (!pctrl) {
+		dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n");
+		return -ENOMEM;
+	}
+	pctrl->dev = &pdev->dev;
+	pctrl->soc = soc_data;
+	pctrl->chip = msm_gpio_template;
+
+	spin_lock_init(&pctrl->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pctrl->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pctrl->regs))
+		return PTR_ERR(pctrl->regs);
+
+	pctrl->irq = platform_get_irq(pdev, 0);
+	if (pctrl->irq < 0) {
+		dev_err(&pdev->dev, "No interrupt defined for msmgpio\n");
+		return pctrl->irq;
+	}
+
+	msm_pinctrl_desc.name = dev_name(&pdev->dev);
+	msm_pinctrl_desc.pins = pctrl->soc->pins;
+	msm_pinctrl_desc.npins = pctrl->soc->npins;
+	pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl);
+	if (!pctrl->pctrl) {
+		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+		return -ENODEV;
+	}
+
+	ret = msm_gpio_init(pctrl);
+	if (ret) {
+		pinctrl_unregister(pctrl->pctrl);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pctrl);
+
+	dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_pinctrl_probe);
+
+int msm_pinctrl_remove(struct platform_device *pdev)
+{
+	struct msm_pinctrl *pctrl = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&pctrl->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to remove gpiochip\n");
+		return ret;
+	}
+
+	pinctrl_unregister(pctrl->pctrl);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_pinctrl_remove);
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm.h
--- linux-libre-3.16-gnu/drivers/pinctrl/qcom/pinctrl-msm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/qcom/pinctrl-msm.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013, Sony Mobile Communications AB.
+ *
+ * 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 __PINCTRL_MSM_H__
+#define __PINCTRL_MSM_H__
+
+struct pinctrl_pin_desc;
+
+/**
+ * struct msm_function - a pinmux function
+ * @name:    Name of the pinmux function.
+ * @groups:  List of pingroups for this function.
+ * @ngroups: Number of entries in @groups.
+ */
+struct msm_function {
+	const char *name;
+	const char * const *groups;
+	unsigned ngroups;
+};
+
+/**
+ * struct msm_pingroup - Qualcomm pingroup definition
+ * @name:                 Name of the pingroup.
+ * @pins:	          A list of pins assigned to this pingroup.
+ * @npins:	          Number of entries in @pins.
+ * @funcs:                A list of pinmux functions that can be selected for
+ *                        this group. The index of the selected function is used
+ *                        for programming the function selector.
+ *                        Entries should be indices into the groups list of the
+ *                        struct msm_pinctrl_soc_data.
+ * @ctl_reg:              Offset of the register holding control bits for this group.
+ * @io_reg:               Offset of the register holding input/output bits for this group.
+ * @intr_cfg_reg:         Offset of the register holding interrupt configuration bits.
+ * @intr_status_reg:      Offset of the register holding the status bits for this group.
+ * @intr_target_reg:      Offset of the register specifying routing of the interrupts
+ *                        from this group.
+ * @mux_bit:              Offset in @ctl_reg for the pinmux function selection.
+ * @pull_bit:             Offset in @ctl_reg for the bias configuration.
+ * @drv_bit:              Offset in @ctl_reg for the drive strength configuration.
+ * @oe_bit:               Offset in @ctl_reg for controlling output enable.
+ * @in_bit:               Offset in @io_reg for the input bit value.
+ * @out_bit:              Offset in @io_reg for the output bit value.
+ * @intr_enable_bit:      Offset in @intr_cfg_reg for enabling the interrupt for this group.
+ * @intr_status_bit:      Offset in @intr_status_reg for reading and acking the interrupt
+ *                        status.
+ * @intr_target_bit:      Offset in @intr_target_reg for configuring the interrupt routing.
+ * @intr_raw_status_bit:  Offset in @intr_cfg_reg for the raw status bit.
+ * @intr_polarity_bit:    Offset in @intr_cfg_reg for specifying polarity of the interrupt.
+ * @intr_detection_bit:   Offset in @intr_cfg_reg for specifying interrupt type.
+ * @intr_detection_width: Number of bits used for specifying interrupt type,
+ *                        Should be 2 for SoCs that can detect both edges in hardware,
+ *                        otherwise 1.
+ */
+struct msm_pingroup {
+	const char *name;
+	const unsigned *pins;
+	unsigned npins;
+
+	unsigned *funcs;
+	unsigned nfuncs;
+
+	s16 ctl_reg;
+	s16 io_reg;
+	s16 intr_cfg_reg;
+	s16 intr_status_reg;
+	s16 intr_target_reg;
+
+	unsigned mux_bit:5;
+
+	unsigned pull_bit:5;
+	unsigned drv_bit:5;
+
+	unsigned oe_bit:5;
+	unsigned in_bit:5;
+	unsigned out_bit:5;
+
+	unsigned intr_enable_bit:5;
+	unsigned intr_status_bit:5;
+	unsigned intr_ack_high:1;
+
+	unsigned intr_target_bit:5;
+	unsigned intr_raw_status_bit:5;
+	unsigned intr_polarity_bit:5;
+	unsigned intr_detection_bit:5;
+	unsigned intr_detection_width:5;
+};
+
+/**
+ * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
+ * @pins:       An array describing all pins the pin controller affects.
+ * @npins:      The number of entries in @pins.
+ * @functions:  An array describing all mux functions the SoC supports.
+ * @nfunctions: The number of entries in @functions.
+ * @groups:     An array describing all pin groups the pin SoC supports.
+ * @ngroups:    The numbmer of entries in @groups.
+ * @ngpio:      The number of pingroups the driver should expose as GPIOs.
+ */
+struct msm_pinctrl_soc_data {
+	const struct pinctrl_pin_desc *pins;
+	unsigned npins;
+	const struct msm_function *functions;
+	unsigned nfunctions;
+	const struct msm_pingroup *groups;
+	unsigned ngroups;
+	unsigned ngpios;
+};
+
+int msm_pinctrl_probe(struct platform_device *pdev,
+		      const struct msm_pinctrl_soc_data *soc_data);
+int msm_pinctrl_remove(struct platform_device *pdev);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,28 @@
+#
+# Samsung Pin control drivers
+#
+config PINCTRL_SAMSUNG
+	bool
+	select PINMUX
+	select PINCONF
+
+config PINCTRL_EXYNOS
+	bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440"
+	depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210)
+	select PINCTRL_SAMSUNG
+
+config PINCTRL_EXYNOS5440
+	bool "Samsung EXYNOS5440 SoC pinctrl driver"
+	depends on SOC_EXYNOS5440
+	select PINMUX
+	select PINCONF
+
+config PINCTRL_S3C24XX
+	bool "Samsung S3C24XX SoC pinctrl driver"
+	depends on ARCH_S3C24XX
+	select PINCTRL_SAMSUNG
+
+config PINCTRL_S3C64XX
+	bool "Samsung S3C64XX SoC pinctrl driver"
+	depends on ARCH_S3C64XX
+	select PINCTRL_SAMSUNG
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/Makefile linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/Makefile
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,7 @@
+# Samsung pin control drivers
+
+obj-$(CONFIG_PINCTRL_SAMSUNG)	+= pinctrl-samsung.o
+obj-$(CONFIG_PINCTRL_EXYNOS)	+= pinctrl-exynos.o
+obj-$(CONFIG_PINCTRL_EXYNOS5440)	+= pinctrl-exynos5440.o
+obj-$(CONFIG_PINCTRL_S3C24XX)	+= pinctrl-s3c24xx.o
+obj-$(CONFIG_PINCTRL_S3C64XX)	+= pinctrl-s3c64xx.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos5440.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos5440.c
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos5440.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos5440.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1061 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include "../core.h"
+
+/* EXYNOS5440 GPIO and Pinctrl register offsets */
+#define GPIO_MUX		0x00
+#define GPIO_IE			0x04
+#define GPIO_INT		0x08
+#define GPIO_TYPE		0x0C
+#define GPIO_VAL		0x10
+#define GPIO_OE			0x14
+#define GPIO_IN			0x18
+#define GPIO_PE			0x1C
+#define GPIO_PS			0x20
+#define GPIO_SR			0x24
+#define GPIO_DS0		0x28
+#define GPIO_DS1		0x2C
+
+#define EXYNOS5440_MAX_PINS		23
+#define EXYNOS5440_MAX_GPIO_INT	8
+#define PIN_NAME_LENGTH		10
+
+#define GROUP_SUFFIX		"-grp"
+#define GSUFFIX_LEN		sizeof(GROUP_SUFFIX)
+#define FUNCTION_SUFFIX		"-mux"
+#define FSUFFIX_LEN		sizeof(FUNCTION_SUFFIX)
+
+/*
+ * pin configuration type and its value are packed together into a 16-bits.
+ * The upper 8-bits represent the configuration type and the lower 8-bits
+ * hold the value of the configuration type.
+ */
+#define PINCFG_TYPE_MASK		0xFF
+#define PINCFG_VALUE_SHIFT		8
+#define PINCFG_VALUE_MASK		(0xFF << PINCFG_VALUE_SHIFT)
+#define PINCFG_PACK(type, value)	(((value) << PINCFG_VALUE_SHIFT) | type)
+#define PINCFG_UNPACK_TYPE(cfg)		((cfg) & PINCFG_TYPE_MASK)
+#define PINCFG_UNPACK_VALUE(cfg)	(((cfg) & PINCFG_VALUE_MASK) >> \
+						PINCFG_VALUE_SHIFT)
+
+/**
+ * enum pincfg_type - possible pin configuration types supported.
+ * @PINCFG_TYPE_PUD: Pull up/down configuration.
+ * @PINCFG_TYPE_DRV: Drive strength configuration.
+ * @PINCFG_TYPE_SKEW_RATE: Skew rate configuration.
+ * @PINCFG_TYPE_INPUT_TYPE: Pin input type configuration.
+ */
+enum pincfg_type {
+	PINCFG_TYPE_PUD,
+	PINCFG_TYPE_DRV,
+	PINCFG_TYPE_SKEW_RATE,
+	PINCFG_TYPE_INPUT_TYPE
+};
+
+/**
+ * struct exynos5440_pin_group: represent group of pins for pincfg setting.
+ * @name: name of the pin group, used to lookup the group.
+ * @pins: the pins included in this group.
+ * @num_pins: number of pins included in this group.
+ */
+struct exynos5440_pin_group {
+	const char		*name;
+	const unsigned int	*pins;
+	u8			num_pins;
+};
+
+/**
+ * struct exynos5440_pmx_func: represent a pin function.
+ * @name: name of the pin function, used to lookup the function.
+ * @groups: one or more names of pin groups that provide this function.
+ * @num_groups: number of groups included in @groups.
+ * @function: the function number to be programmed when selected.
+ */
+struct exynos5440_pmx_func {
+	const char		*name;
+	const char		**groups;
+	u8			num_groups;
+	unsigned long		function;
+};
+
+/**
+ * struct exynos5440_pinctrl_priv_data: driver's private runtime data.
+ * @reg_base: ioremapped based address of the register space.
+ * @gc: gpio chip registered with gpiolib.
+ * @pin_groups: list of pin groups parsed from device tree.
+ * @nr_groups: number of pin groups available.
+ * @pmx_functions: list of pin functions parsed from device tree.
+ * @nr_functions: number of pin functions available.
+ */
+struct exynos5440_pinctrl_priv_data {
+	void __iomem			*reg_base;
+	struct gpio_chip		*gc;
+	struct irq_domain		*irq_domain;
+
+	const struct exynos5440_pin_group	*pin_groups;
+	unsigned int			nr_groups;
+	const struct exynos5440_pmx_func	*pmx_functions;
+	unsigned int			nr_functions;
+};
+
+/**
+ * struct exynos5440_gpio_intr_data: private data for gpio interrupts.
+ * @priv: driver's private runtime data.
+ * @gpio_int: gpio interrupt number.
+ */
+struct exynos5440_gpio_intr_data {
+	struct exynos5440_pinctrl_priv_data	*priv;
+	unsigned int				gpio_int;
+};
+
+/* list of all possible config options supported */
+static struct pin_config {
+	char		*prop_cfg;
+	unsigned int	cfg_type;
+} pcfgs[] = {
+	{ "samsung,exynos5440-pin-pud", PINCFG_TYPE_PUD },
+	{ "samsung,exynos5440-pin-drv", PINCFG_TYPE_DRV },
+	{ "samsung,exynos5440-pin-skew-rate", PINCFG_TYPE_SKEW_RATE },
+	{ "samsung,exynos5440-pin-input-type", PINCFG_TYPE_INPUT_TYPE },
+};
+
+/* check if the selector is a valid pin group selector */
+static int exynos5440_get_group_count(struct pinctrl_dev *pctldev)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->nr_groups;
+}
+
+/* return the name of the group selected by the group selector */
+static const char *exynos5440_get_group_name(struct pinctrl_dev *pctldev,
+						unsigned selector)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->pin_groups[selector].name;
+}
+
+/* return the pin numbers associated with the specified group */
+static int exynos5440_get_group_pins(struct pinctrl_dev *pctldev,
+		unsigned selector, const unsigned **pins, unsigned *num_pins)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	*pins = priv->pin_groups[selector].pins;
+	*num_pins = priv->pin_groups[selector].num_pins;
+	return 0;
+}
+
+/* create pinctrl_map entries by parsing device tree nodes */
+static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np, struct pinctrl_map **maps,
+			unsigned *nmaps)
+{
+	struct device *dev = pctldev->dev;
+	struct pinctrl_map *map;
+	unsigned long *cfg = NULL;
+	char *gname, *fname;
+	int cfg_cnt = 0, map_cnt = 0, idx = 0;
+
+	/* count the number of config options specfied in the node */
+	for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++)
+		if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
+			cfg_cnt++;
+
+	/*
+	 * Find out the number of map entries to create. All the config options
+	 * can be accomadated into a single config map entry.
+	 */
+	if (cfg_cnt)
+		map_cnt = 1;
+	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL))
+		map_cnt++;
+	if (!map_cnt) {
+		dev_err(dev, "node %s does not have either config or function "
+				"configurations\n", np->name);
+		return -EINVAL;
+	}
+
+	/* Allocate memory for pin-map entries */
+	map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
+	if (!map) {
+		dev_err(dev, "could not alloc memory for pin-maps\n");
+		return -ENOMEM;
+	}
+	*nmaps = 0;
+
+	/*
+	 * Allocate memory for pin group name. The pin group name is derived
+	 * from the node name from which these map entries are be created.
+	 */
+	gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
+	if (!gname) {
+		dev_err(dev, "failed to alloc memory for group name\n");
+		goto free_map;
+	}
+	snprintf(gname, strlen(np->name) + 4, "%s%s", np->name, GROUP_SUFFIX);
+
+	/*
+	 * don't have config options? then skip over to creating function
+	 * map entries.
+	 */
+	if (!cfg_cnt)
+		goto skip_cfgs;
+
+	/* Allocate memory for config entries */
+	cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to alloc memory for configs\n");
+		goto free_gname;
+	}
+
+	/* Prepare a list of config settings */
+	for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
+		u32 value;
+		if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
+			cfg[cfg_cnt++] =
+				PINCFG_PACK(pcfgs[idx].cfg_type, value);
+	}
+
+	/* create the config map entry */
+	map[*nmaps].data.configs.group_or_pin = gname;
+	map[*nmaps].data.configs.configs = cfg;
+	map[*nmaps].data.configs.num_configs = cfg_cnt;
+	map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+	*nmaps += 1;
+
+skip_cfgs:
+	/* create the function map entry */
+	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) {
+		fname = kzalloc(strlen(np->name) + FSUFFIX_LEN,	GFP_KERNEL);
+		if (!fname) {
+			dev_err(dev, "failed to alloc memory for func name\n");
+			goto free_cfg;
+		}
+		snprintf(fname, strlen(np->name) + 4, "%s%s", np->name,
+			 FUNCTION_SUFFIX);
+
+		map[*nmaps].data.mux.group = gname;
+		map[*nmaps].data.mux.function = fname;
+		map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+		*nmaps += 1;
+	}
+
+	*maps = map;
+	return 0;
+
+free_cfg:
+	kfree(cfg);
+free_gname:
+	kfree(gname);
+free_map:
+	kfree(map);
+	return -ENOMEM;
+}
+
+/* free the memory allocated to hold the pin-map table */
+static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
+			     struct pinctrl_map *map, unsigned num_maps)
+{
+	int idx;
+
+	for (idx = 0; idx < num_maps; idx++) {
+		if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
+			kfree(map[idx].data.mux.function);
+			if (!idx)
+				kfree(map[idx].data.mux.group);
+		} else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
+			kfree(map[idx].data.configs.configs);
+			if (!idx)
+				kfree(map[idx].data.configs.group_or_pin);
+		}
+	};
+
+	kfree(map);
+}
+
+/* list of pinctrl callbacks for the pinctrl core */
+static const struct pinctrl_ops exynos5440_pctrl_ops = {
+	.get_groups_count	= exynos5440_get_group_count,
+	.get_group_name		= exynos5440_get_group_name,
+	.get_group_pins		= exynos5440_get_group_pins,
+	.dt_node_to_map		= exynos5440_dt_node_to_map,
+	.dt_free_map		= exynos5440_dt_free_map,
+};
+
+/* check if the selector is a valid pin function selector */
+static int exynos5440_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->nr_functions;
+}
+
+/* return the name of the pin function specified */
+static const char *exynos5440_pinmux_get_fname(struct pinctrl_dev *pctldev,
+						unsigned selector)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->pmx_functions[selector].name;
+}
+
+/* return the groups associated for the specified function selector */
+static int exynos5440_pinmux_get_groups(struct pinctrl_dev *pctldev,
+		unsigned selector, const char * const **groups,
+		unsigned * const num_groups)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	*groups = priv->pmx_functions[selector].groups;
+	*num_groups = priv->pmx_functions[selector].num_groups;
+	return 0;
+}
+
+/* enable or disable a pinmux function */
+static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group, bool enable)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	u32 function;
+	u32 data;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+	function = priv->pmx_functions[selector].function;
+
+	data = readl(base + GPIO_MUX);
+	if (enable)
+		data |= (1 << function);
+	else
+		data &= ~(1 << function);
+	writel(data, base + GPIO_MUX);
+}
+
+/* enable a specified pinmux by writing to registers */
+static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group)
+{
+	exynos5440_pinmux_setup(pctldev, selector, group, true);
+	return 0;
+}
+
+/*
+ * The calls to gpio_direction_output() and gpio_direction_input()
+ * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
+ * function called from the gpiolib interface).
+ */
+static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+	return 0;
+}
+
+/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
+static const struct pinmux_ops exynos5440_pinmux_ops = {
+	.get_functions_count	= exynos5440_get_functions_count,
+	.get_function_name	= exynos5440_pinmux_get_fname,
+	.get_function_groups	= exynos5440_pinmux_get_groups,
+	.enable			= exynos5440_pinmux_enable,
+	.gpio_set_direction	= exynos5440_pinmux_gpio_set_direction,
+};
+
+/* set the pin config settings for a specified pin */
+static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long *configs,
+				unsigned num_configs)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	enum pincfg_type cfg_type;
+	u32 cfg_value;
+	u32 data;
+	int i;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+
+	for (i = 0; i < num_configs; i++) {
+		cfg_type = PINCFG_UNPACK_TYPE(configs[i]);
+		cfg_value = PINCFG_UNPACK_VALUE(configs[i]);
+
+		switch (cfg_type) {
+		case PINCFG_TYPE_PUD:
+			/* first set pull enable/disable bit */
+			data = readl(base + GPIO_PE);
+			data &= ~(1 << pin);
+			if (cfg_value)
+				data |= (1 << pin);
+			writel(data, base + GPIO_PE);
+
+			/* then set pull up/down bit */
+			data = readl(base + GPIO_PS);
+			data &= ~(1 << pin);
+			if (cfg_value == 2)
+				data |= (1 << pin);
+			writel(data, base + GPIO_PS);
+			break;
+
+		case PINCFG_TYPE_DRV:
+			/* set the first bit of the drive strength */
+			data = readl(base + GPIO_DS0);
+			data &= ~(1 << pin);
+			data |= ((cfg_value & 1) << pin);
+			writel(data, base + GPIO_DS0);
+			cfg_value >>= 1;
+
+			/* set the second bit of the driver strength */
+			data = readl(base + GPIO_DS1);
+			data &= ~(1 << pin);
+			data |= ((cfg_value & 1) << pin);
+			writel(data, base + GPIO_DS1);
+			break;
+		case PINCFG_TYPE_SKEW_RATE:
+			data = readl(base + GPIO_SR);
+			data &= ~(1 << pin);
+			data |= ((cfg_value & 1) << pin);
+			writel(data, base + GPIO_SR);
+			break;
+		case PINCFG_TYPE_INPUT_TYPE:
+			data = readl(base + GPIO_TYPE);
+			data &= ~(1 << pin);
+			data |= ((cfg_value & 1) << pin);
+			writel(data, base + GPIO_TYPE);
+			break;
+		default:
+			WARN_ON(1);
+			return -EINVAL;
+		}
+	} /* for each config */
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin */
+static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+					unsigned long *config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
+	u32 data;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+
+	switch (cfg_type) {
+	case PINCFG_TYPE_PUD:
+		data = readl(base + GPIO_PE);
+		data = (data >> pin) & 1;
+		if (!data)
+			*config = 0;
+		else
+			*config = ((readl(base + GPIO_PS) >> pin) & 1) + 1;
+		break;
+	case PINCFG_TYPE_DRV:
+		data = readl(base + GPIO_DS0);
+		data = (data >> pin) & 1;
+		*config = data;
+		data = readl(base + GPIO_DS1);
+		data = (data >> pin) & 1;
+		*config |= (data << 1);
+		break;
+	case PINCFG_TYPE_SKEW_RATE:
+		data = readl(base + GPIO_SR);
+		*config = (data >> pin) & 1;
+		break;
+	case PINCFG_TYPE_INPUT_TYPE:
+		data = readl(base + GPIO_TYPE);
+		*config = (data >> pin) & 1;
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* set the pin config settings for a specified pin group */
+static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev,
+			unsigned group, unsigned long *configs,
+			unsigned num_configs)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	const unsigned int *pins;
+	unsigned int cnt;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	pins = priv->pin_groups[group].pins;
+
+	for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++)
+		exynos5440_pinconf_set(pctldev, pins[cnt], configs,
+				       num_configs);
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin group */
+static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned int group, unsigned long *config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	const unsigned int *pins;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	pins = priv->pin_groups[group].pins;
+	exynos5440_pinconf_get(pctldev, pins[0], config);
+	return 0;
+}
+
+/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
+static const struct pinconf_ops exynos5440_pinconf_ops = {
+	.pin_config_get		= exynos5440_pinconf_get,
+	.pin_config_set		= exynos5440_pinconf_set,
+	.pin_config_group_get	= exynos5440_pinconf_group_get,
+	.pin_config_group_set	= exynos5440_pinconf_group_set,
+};
+
+/* gpiolib gpio_set callback function */
+static void exynos5440_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	data = readl(base + GPIO_VAL);
+	data &= ~(1 << offset);
+	if (value)
+		data |= 1 << offset;
+	writel(data, base + GPIO_VAL);
+}
+
+/* gpiolib gpio_get callback function */
+static int exynos5440_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	data = readl(base + GPIO_IN);
+	data >>= offset;
+	data &= 1;
+	return data;
+}
+
+/* gpiolib gpio_direction_input callback function */
+static int exynos5440_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	/* first disable the data output enable on this pin */
+	data = readl(base + GPIO_OE);
+	data &= ~(1 << offset);
+	writel(data, base + GPIO_OE);
+
+	/* now enable input on this pin */
+	data =  readl(base + GPIO_IE);
+	data |= 1 << offset;
+	writel(data, base + GPIO_IE);
+	return 0;
+}
+
+/* gpiolib gpio_direction_output callback function */
+static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+							int value)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	exynos5440_gpio_set(gc, offset, value);
+
+	/* first disable the data input enable on this pin */
+	data = readl(base + GPIO_IE);
+	data &= ~(1 << offset);
+	writel(data, base + GPIO_IE);
+
+	/* now enable output on this pin */
+	data =  readl(base + GPIO_OE);
+	data |= 1 << offset;
+	writel(data, base + GPIO_OE);
+	return 0;
+}
+
+/* gpiolib gpio_to_irq callback function */
+static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	unsigned int virq;
+
+	if (offset < 16 || offset > 23)
+		return -ENXIO;
+
+	if (!priv->irq_domain)
+		return -ENXIO;
+
+	virq = irq_create_mapping(priv->irq_domain, offset - 16);
+	return virq ? : -ENXIO;
+}
+
+/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
+static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
+			struct device_node *cfg_np, unsigned int **pin_list,
+			unsigned int *npins)
+{
+	struct device *dev = &pdev->dev;
+	struct property *prop;
+
+	prop = of_find_property(cfg_np, "samsung,exynos5440-pins", NULL);
+	if (!prop)
+		return -ENOENT;
+
+	*npins = prop->length / sizeof(unsigned long);
+	if (!*npins) {
+		dev_err(dev, "invalid pin list in %s node", cfg_np->name);
+		return -EINVAL;
+	}
+
+	*pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
+	if (!*pin_list) {
+		dev_err(dev, "failed to allocate memory for pin list\n");
+		return -ENOMEM;
+	}
+
+	return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins",
+			*pin_list, *npins);
+}
+
+/*
+ * Parse the information about all the available pin groups and pin functions
+ * from device node of the pin-controller.
+ */
+static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dev_np = dev->of_node;
+	struct device_node *cfg_np;
+	struct exynos5440_pin_group *groups, *grp;
+	struct exynos5440_pmx_func *functions, *func;
+	unsigned *pin_list;
+	unsigned int npins, grp_cnt, func_idx = 0;
+	char *gname, *fname;
+	int ret;
+
+	grp_cnt = of_get_child_count(dev_np);
+	if (!grp_cnt)
+		return -EINVAL;
+
+	groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
+	if (!groups) {
+		dev_err(dev, "failed allocate memory for ping group list\n");
+		return -EINVAL;
+	}
+	grp = groups;
+
+	functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
+	if (!functions) {
+		dev_err(dev, "failed to allocate memory for function list\n");
+		return -EINVAL;
+	}
+	func = functions;
+
+	/*
+	 * Iterate over all the child nodes of the pin controller node
+	 * and create pin groups and pin function lists.
+	 */
+	for_each_child_of_node(dev_np, cfg_np) {
+		u32 function;
+
+		ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np,
+					&pin_list, &npins);
+		if (ret) {
+			gname = NULL;
+			goto skip_to_pin_function;
+		}
+
+		/* derive pin group name from the node name */
+		gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
+					GFP_KERNEL);
+		if (!gname) {
+			dev_err(dev, "failed to alloc memory for group name\n");
+			return -ENOMEM;
+		}
+		snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
+			 GROUP_SUFFIX);
+
+		grp->name = gname;
+		grp->pins = pin_list;
+		grp->num_pins = npins;
+		grp++;
+
+skip_to_pin_function:
+		ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function",
+						&function);
+		if (ret)
+			continue;
+
+		/* derive function name from the node name */
+		fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
+					GFP_KERNEL);
+		if (!fname) {
+			dev_err(dev, "failed to alloc memory for func name\n");
+			return -ENOMEM;
+		}
+		snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
+			 FUNCTION_SUFFIX);
+
+		func->name = fname;
+		func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
+		if (!func->groups) {
+			dev_err(dev, "failed to alloc memory for group list "
+					"in pin function");
+			return -ENOMEM;
+		}
+		func->groups[0] = gname;
+		func->num_groups = gname ? 1 : 0;
+		func->function = function;
+		func++;
+		func_idx++;
+	}
+
+	priv->pin_groups = groups;
+	priv->nr_groups = grp_cnt;
+	priv->pmx_functions = functions;
+	priv->nr_functions = func_idx;
+	return 0;
+}
+
+/* register the pinctrl interface with the pinctrl subsystem */
+static int exynos5440_pinctrl_register(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct device *dev = &pdev->dev;
+	struct pinctrl_desc *ctrldesc;
+	struct pinctrl_dev *pctl_dev;
+	struct pinctrl_pin_desc *pindesc, *pdesc;
+	struct pinctrl_gpio_range grange;
+	char *pin_names;
+	int pin, ret;
+
+	ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL);
+	if (!ctrldesc) {
+		dev_err(dev, "could not allocate memory for pinctrl desc\n");
+		return -ENOMEM;
+	}
+
+	ctrldesc->name = "exynos5440-pinctrl";
+	ctrldesc->owner = THIS_MODULE;
+	ctrldesc->pctlops = &exynos5440_pctrl_ops;
+	ctrldesc->pmxops = &exynos5440_pinmux_ops;
+	ctrldesc->confops = &exynos5440_pinconf_ops;
+
+	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
+				EXYNOS5440_MAX_PINS, GFP_KERNEL);
+	if (!pindesc) {
+		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+		return -ENOMEM;
+	}
+	ctrldesc->pins = pindesc;
+	ctrldesc->npins = EXYNOS5440_MAX_PINS;
+
+	/* dynamically populate the pin number and pin name for pindesc */
+	for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
+		pdesc->number = pin;
+
+	/*
+	 * allocate space for storing the dynamically generated names for all
+	 * the pins which belong to this pin-controller.
+	 */
+	pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
+					ctrldesc->npins, GFP_KERNEL);
+	if (!pin_names) {
+		dev_err(&pdev->dev, "mem alloc for pin names failed\n");
+		return -ENOMEM;
+	}
+
+	/* for each pin, set the name of the pin */
+	for (pin = 0; pin < ctrldesc->npins; pin++) {
+		snprintf(pin_names, 6, "gpio%02d", pin);
+		pdesc = pindesc + pin;
+		pdesc->name = pin_names;
+		pin_names += PIN_NAME_LENGTH;
+	}
+
+	ret = exynos5440_pinctrl_parse_dt(pdev, priv);
+	if (ret)
+		return ret;
+
+	pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv);
+	if (!pctl_dev) {
+		dev_err(&pdev->dev, "could not register pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	grange.name = "exynos5440-pctrl-gpio-range";
+	grange.id = 0;
+	grange.base = 0;
+	grange.npins = EXYNOS5440_MAX_PINS;
+	grange.gc = priv->gc;
+	pinctrl_add_gpio_range(pctl_dev, &grange);
+	return 0;
+}
+
+/* register the gpiolib interface with the gpiolib subsystem */
+static int exynos5440_gpiolib_register(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct gpio_chip *gc;
+	int ret;
+
+	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+	if (!gc) {
+		dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
+		return -ENOMEM;
+	}
+
+	priv->gc = gc;
+	gc->base = 0;
+	gc->ngpio = EXYNOS5440_MAX_PINS;
+	gc->dev = &pdev->dev;
+	gc->set = exynos5440_gpio_set;
+	gc->get = exynos5440_gpio_get;
+	gc->direction_input = exynos5440_gpio_direction_input;
+	gc->direction_output = exynos5440_gpio_direction_output;
+	gc->to_irq = exynos5440_gpio_to_irq;
+	gc->label = "gpiolib-exynos5440";
+	gc->owner = THIS_MODULE;
+	ret = gpiochip_add(gc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
+					"code: %d\n", gc->label, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* unregister the gpiolib interface with the gpiolib subsystem */
+static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	int ret = gpiochip_remove(priv->gc);
+	if (ret) {
+		dev_err(&pdev->dev, "gpio chip remove failed\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void exynos5440_gpio_irq_unmask(struct irq_data *irqd)
+{
+	struct exynos5440_pinctrl_priv_data *d;
+	unsigned long gpio_int;
+
+	d = irq_data_get_irq_chip_data(irqd);
+	gpio_int = readl(d->reg_base + GPIO_INT);
+	gpio_int |= 1 << irqd->hwirq;
+	writel(gpio_int, d->reg_base + GPIO_INT);
+}
+
+static void exynos5440_gpio_irq_mask(struct irq_data *irqd)
+{
+	struct exynos5440_pinctrl_priv_data *d;
+	unsigned long gpio_int;
+
+	d = irq_data_get_irq_chip_data(irqd);
+	gpio_int = readl(d->reg_base + GPIO_INT);
+	gpio_int &= ~(1 << irqd->hwirq);
+	writel(gpio_int, d->reg_base + GPIO_INT);
+}
+
+/* irq_chip for gpio interrupts */
+static struct irq_chip exynos5440_gpio_irq_chip = {
+	.name		= "exynos5440_gpio_irq_chip",
+	.irq_unmask	= exynos5440_gpio_irq_unmask,
+	.irq_mask	= exynos5440_gpio_irq_mask,
+};
+
+/* interrupt handler for GPIO interrupts 0..7 */
+static irqreturn_t exynos5440_gpio_irq(int irq, void *data)
+{
+	struct exynos5440_gpio_intr_data *intd = data;
+	struct exynos5440_pinctrl_priv_data *d = intd->priv;
+	int virq;
+
+	virq = irq_linear_revmap(d->irq_domain, intd->gpio_int);
+	if (!virq)
+		return IRQ_NONE;
+	generic_handle_irq(virq);
+	return IRQ_HANDLED;
+}
+
+static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct exynos5440_pinctrl_priv_data *d = h->host_data;
+
+	irq_set_chip_data(virq, d);
+	irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip,
+					handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+	return 0;
+}
+
+/* irq domain callbacks for gpio interrupt controller */
+static const struct irq_domain_ops exynos5440_gpio_irqd_ops = {
+	.map	= exynos5440_gpio_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+/* setup handling of gpio interrupts */
+static int exynos5440_gpio_irq_init(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct device *dev = &pdev->dev;
+	struct exynos5440_gpio_intr_data *intd;
+	int i, irq, ret;
+
+	intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT,
+					GFP_KERNEL);
+	if (!intd) {
+		dev_err(dev, "failed to allocate memory for gpio intr data\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) {
+		irq = irq_of_parse_and_map(dev->of_node, i);
+		if (irq <= 0) {
+			dev_err(dev, "irq parsing failed\n");
+			return -EINVAL;
+		}
+
+		intd->gpio_int = i;
+		intd->priv = priv;
+		ret = devm_request_irq(dev, irq, exynos5440_gpio_irq,
+					0, dev_name(dev), intd++);
+		if (ret) {
+			dev_err(dev, "irq request failed\n");
+			return -ENXIO;
+		}
+	}
+
+	priv->irq_domain = irq_domain_add_linear(dev->of_node,
+				EXYNOS5440_MAX_GPIO_INT,
+				&exynos5440_gpio_irqd_ops, priv);
+	if (!priv->irq_domain) {
+		dev_err(dev, "failed to create irq domain\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static int exynos5440_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct exynos5440_pinctrl_priv_data *priv;
+	struct resource *res;
+	int ret;
+
+	if (!dev->of_node) {
+		dev_err(dev, "device tree node not found\n");
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "could not allocate memory for private data\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->reg_base))
+		return PTR_ERR(priv->reg_base);
+
+	ret = exynos5440_gpiolib_register(pdev, priv);
+	if (ret)
+		return ret;
+
+	ret = exynos5440_pinctrl_register(pdev, priv);
+	if (ret) {
+		exynos5440_gpiolib_unregister(pdev, priv);
+		return ret;
+	}
+
+	ret = exynos5440_gpio_irq_init(pdev, priv);
+	if (ret) {
+		dev_err(dev, "failed to setup gpio interrupts\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	dev_info(dev, "EXYNOS5440 pinctrl driver registered\n");
+	return 0;
+}
+
+static const struct of_device_id exynos5440_pinctrl_dt_match[] = {
+	{ .compatible = "samsung,exynos5440-pinctrl" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos5440_pinctrl_dt_match);
+
+static struct platform_driver exynos5440_pinctrl_driver = {
+	.probe		= exynos5440_pinctrl_probe,
+	.driver = {
+		.name	= "exynos5440-pinctrl",
+		.owner	= THIS_MODULE,
+		.of_match_table = exynos5440_pinctrl_dt_match,
+	},
+};
+
+static int __init exynos5440_pinctrl_drv_register(void)
+{
+	return platform_driver_register(&exynos5440_pinctrl_driver);
+}
+postcore_initcall(exynos5440_pinctrl_drv_register);
+
+static void __exit exynos5440_pinctrl_drv_unregister(void)
+{
+	platform_driver_unregister(&exynos5440_pinctrl_driver);
+}
+module_exit(exynos5440_pinctrl_drv_unregister);
+
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS5440 SoC pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos.c
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1180 @@
+/*
+ * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ *		http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file contains the Samsung Exynos specific information required by the
+ * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+ * external gpio and wakeup interrupt support.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+
+#include "pinctrl-samsung.h"
+#include "pinctrl-exynos.h"
+
+struct exynos_irq_chip {
+	struct irq_chip chip;
+
+	u32 eint_con;
+	u32 eint_mask;
+	u32 eint_pend;
+};
+
+static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
+{
+	return container_of(chip, struct exynos_irq_chip, chip);
+}
+
+static struct samsung_pin_bank_type bank_type_off = {
+	.fld_width = { 4, 1, 2, 2, 2, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
+};
+
+static struct samsung_pin_bank_type bank_type_alive = {
+	.fld_width = { 4, 1, 2, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
+};
+
+/* list of external wakeup controllers supported */
+static const struct of_device_id exynos_wkup_irq_ids[] = {
+	{ .compatible = "samsung,exynos4210-wakeup-eint", },
+	{ }
+};
+
+static void exynos_irq_mask(struct irq_data *irqd)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
+	unsigned long mask;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	mask = readl(d->virt_base + reg_mask);
+	mask |= 1 << irqd->hwirq;
+	writel(mask, d->virt_base + reg_mask);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+static void exynos_irq_ack(struct irq_data *irqd)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
+
+	writel(1 << irqd->hwirq, d->virt_base + reg_pend);
+}
+
+static void exynos_irq_unmask(struct irq_data *irqd)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
+	unsigned long mask;
+	unsigned long flags;
+
+	/*
+	 * Ack level interrupts right before unmask
+	 *
+	 * If we don't do this we'll get a double-interrupt.  Level triggered
+	 * interrupts must not fire an interrupt if the level is not
+	 * _currently_ active, even if it was active while the interrupt was
+	 * masked.
+	 */
+	if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
+		exynos_irq_ack(irqd);
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	mask = readl(d->virt_base + reg_mask);
+	mask &= ~(1 << irqd->hwirq);
+	writel(mask, d->virt_base + reg_mask);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
+	unsigned int con, trig_type;
+	unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		trig_type = EXYNOS_EINT_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		trig_type = EXYNOS_EINT_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		trig_type = EXYNOS_EINT_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		trig_type = EXYNOS_EINT_LEVEL_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		trig_type = EXYNOS_EINT_LEVEL_LOW;
+		break;
+	default:
+		pr_err("unsupported external interrupt type\n");
+		return -EINVAL;
+	}
+
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		__irq_set_handler_locked(irqd->irq, handle_edge_irq);
+	else
+		__irq_set_handler_locked(irqd->irq, handle_level_irq);
+
+	con = readl(d->virt_base + reg_con);
+	con &= ~(EXYNOS_EINT_CON_MASK << shift);
+	con |= trig_type << shift;
+	writel(con, d->virt_base + reg_con);
+
+	return 0;
+}
+
+static int exynos_irq_request_resources(struct irq_data *irqd)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pin_bank_type *bank_type = bank->type;
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
+	unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
+	unsigned long flags;
+	unsigned int mask;
+	unsigned int con;
+	int ret;
+
+	ret = gpio_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
+	if (ret) {
+		dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n",
+			bank->name, irqd->hwirq);
+		return ret;
+	}
+
+	reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
+	shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
+	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	con = readl(d->virt_base + reg_con);
+	con &= ~(mask << shift);
+	con |= EXYNOS_EINT_FUNC << shift;
+	writel(con, d->virt_base + reg_con);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+
+	exynos_irq_unmask(irqd);
+
+	return 0;
+}
+
+static void exynos_irq_release_resources(struct irq_data *irqd)
+{
+	struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pin_bank_type *bank_type = bank->type;
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
+	unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
+	unsigned long flags;
+	unsigned int mask;
+	unsigned int con;
+
+	reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
+	shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
+	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+	exynos_irq_mask(irqd);
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	con = readl(d->virt_base + reg_con);
+	con &= ~(mask << shift);
+	con |= FUNC_INPUT << shift;
+	writel(con, d->virt_base + reg_con);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+
+	gpio_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
+}
+
+/*
+ * irq_chip for gpio interrupts.
+ */
+static struct exynos_irq_chip exynos_gpio_irq_chip = {
+	.chip = {
+		.name = "exynos_gpio_irq_chip",
+		.irq_unmask = exynos_irq_unmask,
+		.irq_mask = exynos_irq_mask,
+		.irq_ack = exynos_irq_ack,
+		.irq_set_type = exynos_irq_set_type,
+		.irq_request_resources = exynos_irq_request_resources,
+		.irq_release_resources = exynos_irq_release_resources,
+	},
+	.eint_con = EXYNOS_GPIO_ECON_OFFSET,
+	.eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+	.eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+};
+
+static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct samsung_pin_bank *b = h->host_data;
+
+	irq_set_chip_data(virq, b);
+	irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip.chip,
+					handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+	return 0;
+}
+
+/*
+ * irq domain callbacks for external gpio interrupt controller.
+ */
+static const struct irq_domain_ops exynos_gpio_irqd_ops = {
+	.map	= exynos_gpio_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
+{
+	struct samsung_pinctrl_drv_data *d = data;
+	struct samsung_pin_ctrl *ctrl = d->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	unsigned int svc, group, pin, virq;
+
+	svc = readl(d->virt_base + EXYNOS_SVC_OFFSET);
+	group = EXYNOS_SVC_GROUP(svc);
+	pin = svc & EXYNOS_SVC_NUM_MASK;
+
+	if (!group)
+		return IRQ_HANDLED;
+	bank += (group - 1);
+
+	virq = irq_linear_revmap(bank->irq_domain, pin);
+	if (!virq)
+		return IRQ_NONE;
+	generic_handle_irq(virq);
+	return IRQ_HANDLED;
+}
+
+struct exynos_eint_gpio_save {
+	u32 eint_con;
+	u32 eint_fltcon0;
+	u32 eint_fltcon1;
+};
+
+/*
+ * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
+{
+	struct samsung_pin_bank *bank;
+	struct device *dev = d->dev;
+	int ret;
+	int i;
+
+	if (!d->irq) {
+		dev_err(dev, "irq number not available\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
+					0, dev_name(dev), d);
+	if (ret) {
+		dev_err(dev, "irq request failed\n");
+		return -ENXIO;
+	}
+
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "gpio irq domain add failed\n");
+			ret = -ENXIO;
+			goto err_domains;
+		}
+
+		bank->soc_priv = devm_kzalloc(d->dev,
+			sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
+		if (!bank->soc_priv) {
+			irq_domain_remove(bank->irq_domain);
+			ret = -ENOMEM;
+			goto err_domains;
+		}
+	}
+
+	return 0;
+
+err_domains:
+	for (--i, --bank; i >= 0; --i, --bank) {
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+		irq_domain_remove(bank->irq_domain);
+	}
+
+	return ret;
+}
+
+static u32 exynos_eint_wake_mask = 0xffffffff;
+
+u32 exynos_get_eint_wake_mask(void)
+{
+	return exynos_eint_wake_mask;
+}
+
+static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
+
+	pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
+
+	if (!on)
+		exynos_eint_wake_mask |= bit;
+	else
+		exynos_eint_wake_mask &= ~bit;
+
+	return 0;
+}
+
+/*
+ * irq_chip for wakeup interrupts
+ */
+static struct exynos_irq_chip exynos_wkup_irq_chip = {
+	.chip = {
+		.name = "exynos_wkup_irq_chip",
+		.irq_unmask = exynos_irq_unmask,
+		.irq_mask = exynos_irq_mask,
+		.irq_ack = exynos_irq_ack,
+		.irq_set_type = exynos_irq_set_type,
+		.irq_set_wake = exynos_wkup_irq_set_wake,
+		.irq_request_resources = exynos_irq_request_resources,
+		.irq_release_resources = exynos_irq_release_resources,
+	},
+	.eint_con = EXYNOS_WKUP_ECON_OFFSET,
+	.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
+	.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
+};
+
+/* interrupt handler for wakeup interrupts 0..15 */
+static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+{
+	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pin_bank *bank = eintd->bank;
+	struct irq_chip *chip = irq_get_chip(irq);
+	int eint_irq;
+
+	chained_irq_enter(chip, desc);
+	chip->irq_mask(&desc->irq_data);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
+	generic_handle_irq(eint_irq);
+	chip->irq_unmask(&desc->irq_data);
+	chained_irq_exit(chip, desc);
+}
+
+static inline void exynos_irq_demux_eint(unsigned long pend,
+						struct irq_domain *domain)
+{
+	unsigned int irq;
+
+	while (pend) {
+		irq = fls(pend) - 1;
+		generic_handle_irq(irq_find_mapping(domain, irq));
+		pend &= ~(1 << irq);
+	}
+}
+
+/* interrupt handler for wakeup interrupt 16 */
+static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
+	unsigned long pend;
+	unsigned long mask;
+	int i;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < eintd->nr_banks; ++i) {
+		struct samsung_pin_bank *b = eintd->banks[i];
+		pend = readl(d->virt_base + EXYNOS_WKUP_EPEND_OFFSET
+				+ b->eint_offset);
+		mask = readl(d->virt_base + EXYNOS_WKUP_EMASK_OFFSET
+				+ b->eint_offset);
+		exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip.chip,
+					handle_level_irq);
+	irq_set_chip_data(virq, h->host_data);
+	set_irq_flags(virq, IRQF_VALID);
+	return 0;
+}
+
+/*
+ * irq domain callbacks for external wakeup interrupt controller.
+ */
+static const struct irq_domain_ops exynos_wkup_irqd_ops = {
+	.map	= exynos_wkup_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+/*
+ * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
+{
+	struct device *dev = d->dev;
+	struct device_node *wkup_np = NULL;
+	struct device_node *np;
+	struct samsung_pin_bank *bank;
+	struct exynos_weint_data *weint_data;
+	struct exynos_muxed_weint_data *muxed_data;
+	unsigned int muxed_banks = 0;
+	unsigned int i;
+	int idx, irq;
+
+	for_each_child_of_node(dev->of_node, np) {
+		if (of_match_node(exynos_wkup_irq_ids, np)) {
+			wkup_np = np;
+			break;
+		}
+	}
+	if (!wkup_np)
+		return -ENODEV;
+
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP)
+			continue;
+
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_wkup_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "wkup irq domain add failed\n");
+			return -ENXIO;
+		}
+
+		if (!of_find_property(bank->of_node, "interrupts", NULL)) {
+			bank->eint_type = EINT_TYPE_WKUP_MUX;
+			++muxed_banks;
+			continue;
+		}
+
+		weint_data = devm_kzalloc(dev, bank->nr_pins
+					* sizeof(*weint_data), GFP_KERNEL);
+		if (!weint_data) {
+			dev_err(dev, "could not allocate memory for weint_data\n");
+			return -ENOMEM;
+		}
+
+		for (idx = 0; idx < bank->nr_pins; ++idx) {
+			irq = irq_of_parse_and_map(bank->of_node, idx);
+			if (!irq) {
+				dev_err(dev, "irq number for eint-%s-%d not found\n",
+							bank->name, idx);
+				continue;
+			}
+			weint_data[idx].irq = idx;
+			weint_data[idx].bank = bank;
+			irq_set_handler_data(irq, &weint_data[idx]);
+			irq_set_chained_handler(irq, exynos_irq_eint0_15);
+		}
+	}
+
+	if (!muxed_banks)
+		return 0;
+
+	irq = irq_of_parse_and_map(wkup_np, 0);
+	if (!irq) {
+		dev_err(dev, "irq number for muxed EINTs not found\n");
+		return 0;
+	}
+
+	muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+		+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
+	if (!muxed_data) {
+		dev_err(dev, "could not allocate memory for muxed_data\n");
+		return -ENOMEM;
+	}
+
+	irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+	irq_set_handler_data(irq, muxed_data);
+
+	bank = d->ctrl->pin_banks;
+	idx = 0;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP_MUX)
+			continue;
+
+		muxed_data->banks[idx++] = bank;
+	}
+	muxed_data->nr_banks = muxed_banks;
+
+	return 0;
+}
+
+static void exynos_pinctrl_suspend_bank(
+				struct samsung_pinctrl_drv_data *drvdata,
+				struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	void __iomem *regs = drvdata->virt_base;
+
+	save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+						+ bank->eint_offset);
+	save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+						+ 2 * bank->eint_offset);
+	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+						+ 2 * bank->eint_offset + 4);
+
+	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
+	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
+	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
+}
+
+static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
+		if (bank->eint_type == EINT_TYPE_GPIO)
+			exynos_pinctrl_suspend_bank(drvdata, bank);
+}
+
+static void exynos_pinctrl_resume_bank(
+				struct samsung_pinctrl_drv_data *drvdata,
+				struct samsung_pin_bank *bank)
+{
+	struct exynos_eint_gpio_save *save = bank->soc_priv;
+	void __iomem *regs = drvdata->virt_base;
+
+	pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+			readl(regs + EXYNOS_GPIO_ECON_OFFSET
+			+ bank->eint_offset), save->eint_con);
+	pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			+ 2 * bank->eint_offset), save->eint_fltcon0);
+	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
+
+	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+						+ bank->eint_offset);
+	writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+						+ 2 * bank->eint_offset);
+	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+						+ 2 * bank->eint_offset + 4);
+}
+
+static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
+		if (bank->eint_type == EINT_TYPE_GPIO)
+			exynos_pinctrl_resume_bank(drvdata, bank);
+}
+
+/* pin banks of s5pv210 pin-controller */
+static struct samsung_pin_bank s5pv210_pin_bank[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(6, 0x0c0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpe0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x100, "gpe1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpf0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpf1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpf2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(6, 0x180, "gpf3", 0x30),
+	EXYNOS_PIN_BANK_EINTG(7, 0x1a0, "gpg0", 0x34),
+	EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38),
+	EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x200, "gpg3", 0x40),
+	EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x44),
+	EXYNOS_PIN_BANK_EINTG(6, 0x260, "gpj1", 0x48),
+	EXYNOS_PIN_BANK_EINTG(8, 0x280, "gpj2", 0x4c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2a0, "gpj3", 0x50),
+	EXYNOS_PIN_BANK_EINTG(5, 0x2c0, "gpj4", 0x54),
+	EXYNOS_PIN_BANK_EINTN(8, 0x2e0, "mp01"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x300, "mp02"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x320, "mp03"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x340, "mp04"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x360, "mp05"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x380, "mp06"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x3a0, "mp07"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gph0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gph1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gph2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gph3", 0x0c),
+};
+
+struct samsung_pin_ctrl s5pv210_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= s5pv210_pin_bank,
+		.nr_banks	= ARRAY_SIZE(s5pv210_pin_bank),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "s5pv210-gpio-ctrl0",
+	},
+};
+
+/* pin banks of exynos3250 pin-controller 0 */
+static struct samsung_pin_bank exynos3250_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb",  0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpd1", 0x18),
+};
+
+/* pin banks of exynos3250 pin-controller 1 */
+static struct samsung_pin_bank exynos3250_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpe0"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpe1"),
+	EXYNOS_PIN_BANK_EINTN(3, 0x180, "gpe2"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(5, 0x2a0, "gpm2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2c0, "gpm3", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2e0, "gpm4", 0x34),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes
+ * two gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos3250_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos3250_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos3250_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos3250-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos3250_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos3250_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos3250-gpio-ctrl1",
+	},
+};
+
+/* pin banks of exynos4210 pin-controller 0 */
+static struct samsung_pin_bank exynos4210_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
+	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
+	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
+};
+
+/* pin banks of exynos4210 pin-controller 1 */
+static struct samsung_pin_bank exynos4210_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos4210 pin-controller 2 */
+static struct samsung_pin_bank exynos4210_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
+ * three gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos4210_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4210-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos4210_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4210-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos4210_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks2),
+		.label		= "exynos4210-gpio-ctrl2",
+	},
+};
+
+/* pin banks of exynos4x12 pin-controller 0 */
+static struct samsung_pin_bank exynos4x12_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40),
+	EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44),
+};
+
+/* pin banks of exynos4x12 pin-controller 1 */
+static struct samsung_pin_bank exynos4x12_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+	EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34),
+	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos4x12 pin-controller 2 */
+static struct samsung_pin_bank exynos4x12_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/* pin banks of exynos4x12 pin-controller 3 */
+static struct samsung_pin_bank exynos4x12_pin_banks3[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos4x12_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4x12-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos4x12_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4x12-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos4x12_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks2),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4x12-gpio-ctrl2",
+	}, {
+		/* pin-controller instance 3 data */
+		.pin_banks	= exynos4x12_pin_banks3,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks3),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos4x12-gpio-ctrl3",
+	},
+};
+
+/* pin banks of exynos5250 pin-controller 0 */
+static struct samsung_pin_bank exynos5250_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28),
+	EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30),
+	EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34),
+	EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5250 pin-controller 1 */
+static struct samsung_pin_bank exynos5250_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20),
+};
+
+/* pin banks of exynos5250 pin-controller 2 */
+static struct samsung_pin_bank exynos5250_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10),
+};
+
+/* pin banks of exynos5250 pin-controller 3 */
+static struct samsung_pin_bank exynos5250_pin_banks3[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos5250_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos5250-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos5250_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos5250-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos5250_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks2),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos5250-gpio-ctrl2",
+	}, {
+		/* pin-controller instance 3 data */
+		.pin_banks	= exynos5250_pin_banks3,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks3),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.suspend	= exynos_pinctrl_suspend,
+		.resume		= exynos_pinctrl_resume,
+		.label		= "exynos5250-gpio-ctrl3",
+	},
+};
+
+/* pin banks of exynos5260 pin-controller 0 */
+static struct samsung_pin_bank exynos5260_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpb1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(5, 0x0a0, "gpb2", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpb3", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpb4", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpb5", 0x20),
+	EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpd1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(5, 0x160, "gpd2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpe0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(5, 0x1a0, "gpe1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(4, 0x1c0, "gpf0", 0x38),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1e0, "gpf1", 0x3c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x200, "gpk0", 0x40),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5260 pin-controller 1 */
+static struct samsung_pin_bank exynos5260_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpc0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpc1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpc4", 0x10),
+};
+
+/* pin banks of exynos5260 pin-controller 2 */
+static struct samsung_pin_bank exynos5260_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5260 SoC. Exynos5260 SoC includes
+ * three gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5260_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos5260_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.label		= "exynos5260-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos5260_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5260-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos5260_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos5260_pin_banks2),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5260-gpio-ctrl2",
+	},
+};
+
+/* pin banks of exynos5420 pin-controller 0 */
+static struct samsung_pin_bank exynos5420_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5420 pin-controller 1 */
+static struct samsung_pin_bank exynos5420_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpc0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpc1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpc4", 0x10),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpd1", 0x14),
+	EXYNOS_PIN_BANK_EINTN(6, 0x0C0, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x0E0, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x100, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x160, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy6"),
+};
+
+/* pin banks of exynos5420 pin-controller 2 */
+static struct samsung_pin_bank exynos5420_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(6, 0x040, "gpf0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpf1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gpj4", 0x1c),
+};
+
+/* pin banks of exynos5420 pin-controller 3 */
+static struct samsung_pin_bank exynos5420_pin_banks3[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpb3", 0x18),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpb4", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph0", 0x20),
+};
+
+/* pin banks of exynos5420 pin-controller 4 */
+static struct samsung_pin_bank exynos5420_pin_banks4[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5420 SoC. Exynos5420 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5420_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos5420_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks0),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.label		= "exynos5420-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos5420_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks1),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5420-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos5420_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks2),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5420-gpio-ctrl2",
+	}, {
+		/* pin-controller instance 3 data */
+		.pin_banks	= exynos5420_pin_banks3,
+		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks3),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5420-gpio-ctrl3",
+	}, {
+		/* pin-controller instance 4 data */
+		.pin_banks	= exynos5420_pin_banks4,
+		.nr_banks	= ARRAY_SIZE(exynos5420_pin_banks4),
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5420-gpio-ctrl4",
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos.h
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-exynos.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-exynos.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Exynos specific definitions for Samsung pinctrl and gpiolib driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ *		http://www.linaro.org
+ *
+ * This file contains the Exynos specific definitions for the Samsung
+ * pinctrl/gpiolib interface drivers.
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/* External GPIO and wakeup interrupt related definitions */
+#define EXYNOS_GPIO_ECON_OFFSET		0x700
+#define EXYNOS_GPIO_EFLTCON_OFFSET	0x800
+#define EXYNOS_GPIO_EMASK_OFFSET	0x900
+#define EXYNOS_GPIO_EPEND_OFFSET	0xA00
+#define EXYNOS_WKUP_ECON_OFFSET		0xE00
+#define EXYNOS_WKUP_EMASK_OFFSET	0xF00
+#define EXYNOS_WKUP_EPEND_OFFSET	0xF40
+#define EXYNOS_SVC_OFFSET		0xB08
+#define EXYNOS_EINT_FUNC		0xF
+
+/* helpers to access interrupt service register */
+#define EXYNOS_SVC_GROUP_SHIFT		3
+#define EXYNOS_SVC_GROUP_MASK		0x1f
+#define EXYNOS_SVC_NUM_MASK		7
+#define EXYNOS_SVC_GROUP(x)		((x >> EXYNOS_SVC_GROUP_SHIFT) & \
+						EXYNOS_SVC_GROUP_MASK)
+
+/* Exynos specific external interrupt trigger types */
+#define EXYNOS_EINT_LEVEL_LOW		0
+#define EXYNOS_EINT_LEVEL_HIGH		1
+#define EXYNOS_EINT_EDGE_FALLING	2
+#define EXYNOS_EINT_EDGE_RISING		3
+#define EXYNOS_EINT_EDGE_BOTH		4
+#define EXYNOS_EINT_CON_MASK		0xF
+#define EXYNOS_EINT_CON_LEN		4
+
+#define EXYNOS_EINT_MAX_PER_BANK	8
+#define EXYNOS_EINT_NR_WKUP_EINT
+
+#define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
+	{						\
+		.type		= &bank_type_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs)	\
+	{						\
+		.type		= &bank_type_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_GPIO,	\
+		.eint_offset	= offs,			\
+		.name		= id			\
+	}
+
+#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs)	\
+	{						\
+		.type		= &bank_type_alive,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_offset	= offs,			\
+		.name		= id			\
+	}
+
+/**
+ * struct exynos_weint_data: irq specific data for all the wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @irq: interrupt number within the domain.
+ * @bank: bank responsible for this interrupt
+ */
+struct exynos_weint_data {
+	unsigned int irq;
+	struct samsung_pin_bank *bank;
+};
+
+/**
+ * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @nr_banks: count of banks being part of the mux
+ * @banks: array of banks being part of the mux
+ */
+struct exynos_muxed_weint_data {
+	unsigned int nr_banks;
+	struct samsung_pin_bank *banks[];
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-s3c24xx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-s3c24xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-s3c24xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,651 @@
+/*
+ * S3C24XX specific support for Samsung pinctrl/gpiolib driver.
+ *
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.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 file contains the SamsungS3C24XX specific information required by the
+ * Samsung pinctrl/gpiolib driver. It also includes the implementation of
+ * external gpio and wakeup interrupt support.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "pinctrl-samsung.h"
+
+#define NUM_EINT	24
+#define NUM_EINT_IRQ	6
+#define EINT_MAX_PER_GROUP	8
+
+#define EINTPEND_REG	0xa8
+#define EINTMASK_REG	0xa4
+
+#define EINT_GROUP(i)		((int)((i) / EINT_MAX_PER_GROUP))
+#define EINT_REG(i)		((EINT_GROUP(i) * 4) + 0x88)
+#define EINT_OFFS(i)		((i) % EINT_MAX_PER_GROUP * 4)
+
+#define EINT_LEVEL_LOW		0
+#define EINT_LEVEL_HIGH		1
+#define EINT_EDGE_FALLING	2
+#define EINT_EDGE_RISING	4
+#define EINT_EDGE_BOTH		6
+#define EINT_MASK		0xf
+
+static struct samsung_pin_bank_type bank_type_1bit = {
+	.fld_width = { 1, 1, },
+	.reg_offset = { 0x00, 0x04, },
+};
+
+static struct samsung_pin_bank_type bank_type_2bit = {
+	.fld_width = { 2, 1, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, },
+};
+
+#define PIN_BANK_A(pins, reg, id)		\
+	{						\
+		.type		= &bank_type_1bit,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define PIN_BANK_2BIT(pins, reg, id)		\
+	{						\
+		.type		= &bank_type_2bit,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs, emask)\
+	{						\
+		.type		= &bank_type_2bit,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_func	= 2,			\
+		.eint_mask	= emask,		\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+/**
+ * struct s3c24xx_eint_data: EINT common data
+ * @drvdata: pin controller driver data
+ * @domains: IRQ domains of particular EINT interrupts
+ * @parents: mapped parent irqs in the main interrupt controller
+ */
+struct s3c24xx_eint_data {
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *domains[NUM_EINT];
+	int parents[NUM_EINT_IRQ];
+};
+
+/**
+ * struct s3c24xx_eint_domain_data: per irq-domain data
+ * @bank: pin bank related to the domain
+ * @eint_data: common data
+ * eint0_3_parent_only: live eints 0-3 only in the main intc
+ */
+struct s3c24xx_eint_domain_data {
+	struct samsung_pin_bank *bank;
+	struct s3c24xx_eint_data *eint_data;
+	bool eint0_3_parent_only;
+};
+
+static int s3c24xx_eint_get_trigger(unsigned int type)
+{
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		return EINT_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		return EINT_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		return EINT_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		return EINT_LEVEL_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		return EINT_LEVEL_LOW;
+		break;
+	default:
+		return -EINVAL;
+	}
+}
+
+static void s3c24xx_eint_set_handler(unsigned int irq, unsigned int type)
+{
+	/* Edge- and level-triggered interrupts need different handlers */
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		__irq_set_handler_locked(irq, handle_edge_irq);
+	else
+		__irq_set_handler_locked(irq, handle_level_irq);
+}
+
+static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
+					struct samsung_pin_bank *bank, int pin)
+{
+	struct samsung_pin_bank_type *bank_type = bank->type;
+	unsigned long flags;
+	void __iomem *reg;
+	u8 shift;
+	u32 mask;
+	u32 val;
+
+	/* Make sure that pin is configured as interrupt */
+	reg = d->virt_base + bank->pctl_offset;
+	shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
+	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	val = readl(reg);
+	val &= ~(mask << shift);
+	val |= bank->eint_func << shift;
+	writel(val, reg);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	int index = bank->eint_offset + data->hwirq;
+	void __iomem *reg;
+	int trigger;
+	u8 shift;
+	u32 val;
+
+	trigger = s3c24xx_eint_get_trigger(type);
+	if (trigger < 0) {
+		dev_err(d->dev, "unsupported external interrupt type\n");
+		return -EINVAL;
+	}
+
+	s3c24xx_eint_set_handler(data->irq, type);
+
+	/* Set up interrupt trigger */
+	reg = d->virt_base + EINT_REG(index);
+	shift = EINT_OFFS(index);
+
+	val = readl(reg);
+	val &= ~(EINT_MASK << shift);
+	val |= trigger << shift;
+	writel(val, reg);
+
+	s3c24xx_eint_set_function(d, bank, data->hwirq);
+
+	return 0;
+}
+
+/* Handling of EINTs 0-3 on all except S3C2412 and S3C2413 */
+
+static void s3c2410_eint0_3_ack(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
+	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
+	int parent_irq = eint_data->parents[data->hwirq];
+	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
+
+	parent_chip->irq_ack(irq_get_irq_data(parent_irq));
+}
+
+static void s3c2410_eint0_3_mask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
+	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
+	int parent_irq = eint_data->parents[data->hwirq];
+	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
+
+	parent_chip->irq_mask(irq_get_irq_data(parent_irq));
+}
+
+static void s3c2410_eint0_3_unmask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
+	struct s3c24xx_eint_data *eint_data = ddata->eint_data;
+	int parent_irq = eint_data->parents[data->hwirq];
+	struct irq_chip *parent_chip = irq_get_chip(parent_irq);
+
+	parent_chip->irq_unmask(irq_get_irq_data(parent_irq));
+}
+
+static struct irq_chip s3c2410_eint0_3_chip = {
+	.name		= "s3c2410-eint0_3",
+	.irq_ack	= s3c2410_eint0_3_ack,
+	.irq_mask	= s3c2410_eint0_3_mask,
+	.irq_unmask	= s3c2410_eint0_3_unmask,
+	.irq_set_type	= s3c24xx_eint_type,
+};
+
+static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
+	unsigned int virq;
+
+	/* the first 4 eints have a simple 1 to 1 mapping */
+	virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
+	/* Something must be really wrong if an unmapped EINT is unmasked */
+	BUG_ON(!virq);
+
+	generic_handle_irq(virq);
+}
+
+/* Handling of EINTs 0-3 on S3C2412 and S3C2413 */
+
+static void s3c2412_eint0_3_ack(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+
+	unsigned long bitval = 1UL << data->hwirq;
+	writel(bitval, d->virt_base + EINTPEND_REG);
+}
+
+static void s3c2412_eint0_3_mask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long mask;
+
+	mask = readl(d->virt_base + EINTMASK_REG);
+	mask |= (1UL << data->hwirq);
+	writel(mask, d->virt_base + EINTMASK_REG);
+}
+
+static void s3c2412_eint0_3_unmask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long mask;
+
+	mask = readl(d->virt_base + EINTMASK_REG);
+	mask &= ~(1UL << data->hwirq);
+	writel(mask, d->virt_base + EINTMASK_REG);
+}
+
+static struct irq_chip s3c2412_eint0_3_chip = {
+	.name		= "s3c2412-eint0_3",
+	.irq_ack	= s3c2412_eint0_3_ack,
+	.irq_mask	= s3c2412_eint0_3_mask,
+	.irq_unmask	= s3c2412_eint0_3_unmask,
+	.irq_set_type	= s3c24xx_eint_type,
+};
+
+static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
+	unsigned int virq;
+
+	chained_irq_enter(chip, desc);
+
+	/* the first 4 eints have a simple 1 to 1 mapping */
+	virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
+	/* Something must be really wrong if an unmapped EINT is unmasked */
+	BUG_ON(!virq);
+
+	generic_handle_irq(virq);
+
+	chained_irq_exit(chip, desc);
+}
+
+/* Handling of all other eints */
+
+static void s3c24xx_eint_ack(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned char index = bank->eint_offset + data->hwirq;
+
+	writel(1UL << index, d->virt_base + EINTPEND_REG);
+}
+
+static void s3c24xx_eint_mask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned char index = bank->eint_offset + data->hwirq;
+	unsigned long mask;
+
+	mask = readl(d->virt_base + EINTMASK_REG);
+	mask |= (1UL << index);
+	writel(mask, d->virt_base + EINTMASK_REG);
+}
+
+static void s3c24xx_eint_unmask(struct irq_data *data)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned char index = bank->eint_offset + data->hwirq;
+	unsigned long mask;
+
+	mask = readl(d->virt_base + EINTMASK_REG);
+	mask &= ~(1UL << index);
+	writel(mask, d->virt_base + EINTMASK_REG);
+}
+
+static struct irq_chip s3c24xx_eint_chip = {
+	.name		= "s3c-eint",
+	.irq_ack	= s3c24xx_eint_ack,
+	.irq_mask	= s3c24xx_eint_mask,
+	.irq_unmask	= s3c24xx_eint_unmask,
+	.irq_set_type	= s3c24xx_eint_type,
+};
+
+static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
+				      u32 offset, u32 range)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct s3c24xx_eint_data *data = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *d = data->drvdata;
+	unsigned int pend, mask;
+
+	chained_irq_enter(chip, desc);
+
+	pend = readl(d->virt_base + EINTPEND_REG);
+	mask = readl(d->virt_base + EINTMASK_REG);
+
+	pend &= ~mask;
+	pend &= range;
+
+	while (pend) {
+		unsigned int virq;
+
+		irq = __ffs(pend);
+		pend &= ~(1 << irq);
+		virq = irq_linear_revmap(data->domains[irq], irq - offset);
+		/* Something is really wrong if an unmapped EINT is unmasked */
+		BUG_ON(!virq);
+
+		generic_handle_irq(virq);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
+{
+	s3c24xx_demux_eint(irq, desc, 0, 0xf0);
+}
+
+static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
+{
+	s3c24xx_demux_eint(irq, desc, 8, 0xffff00);
+}
+
+static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = {
+	s3c2410_demux_eint0_3,
+	s3c2410_demux_eint0_3,
+	s3c2410_demux_eint0_3,
+	s3c2410_demux_eint0_3,
+	s3c24xx_demux_eint4_7,
+	s3c24xx_demux_eint8_23,
+};
+
+static irq_flow_handler_t s3c2412_eint_handlers[NUM_EINT_IRQ] = {
+	s3c2412_demux_eint0_3,
+	s3c2412_demux_eint0_3,
+	s3c2412_demux_eint0_3,
+	s3c2412_demux_eint0_3,
+	s3c24xx_demux_eint4_7,
+	s3c24xx_demux_eint8_23,
+};
+
+static int s3c24xx_gpf_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct s3c24xx_eint_domain_data *ddata = h->host_data;
+	struct samsung_pin_bank *bank = ddata->bank;
+
+	if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
+		return -EINVAL;
+
+	if (hw <= 3) {
+		if (ddata->eint0_3_parent_only)
+			irq_set_chip_and_handler(virq, &s3c2410_eint0_3_chip,
+						 handle_edge_irq);
+		else
+			irq_set_chip_and_handler(virq, &s3c2412_eint0_3_chip,
+						 handle_edge_irq);
+	} else {
+		irq_set_chip_and_handler(virq, &s3c24xx_eint_chip,
+					 handle_edge_irq);
+	}
+	irq_set_chip_data(virq, bank);
+	set_irq_flags(virq, IRQF_VALID);
+	return 0;
+}
+
+static const struct irq_domain_ops s3c24xx_gpf_irq_ops = {
+	.map	= s3c24xx_gpf_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+static int s3c24xx_gpg_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct s3c24xx_eint_domain_data *ddata = h->host_data;
+	struct samsung_pin_bank *bank = ddata->bank;
+
+	if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
+		return -EINVAL;
+
+	irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq);
+	irq_set_chip_data(virq, bank);
+	set_irq_flags(virq, IRQF_VALID);
+	return 0;
+}
+
+static const struct irq_domain_ops s3c24xx_gpg_irq_ops = {
+	.map	= s3c24xx_gpg_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+static const struct of_device_id s3c24xx_eint_irq_ids[] = {
+	{ .compatible = "samsung,s3c2410-wakeup-eint", .data = (void *)1 },
+	{ .compatible = "samsung,s3c2412-wakeup-eint", .data = (void *)0 },
+	{ }
+};
+
+static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d)
+{
+	struct device *dev = d->dev;
+	const struct of_device_id *match;
+	struct device_node *eint_np = NULL;
+	struct device_node *np;
+	struct samsung_pin_bank *bank;
+	struct s3c24xx_eint_data *eint_data;
+	const struct irq_domain_ops *ops;
+	unsigned int i;
+	bool eint0_3_parent_only;
+	irq_flow_handler_t *handlers;
+
+	for_each_child_of_node(dev->of_node, np) {
+		match = of_match_node(s3c24xx_eint_irq_ids, np);
+		if (match) {
+			eint_np = np;
+			eint0_3_parent_only = (bool)match->data;
+			break;
+		}
+	}
+	if (!eint_np)
+		return -ENODEV;
+
+	eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL);
+	if (!eint_data)
+		return -ENOMEM;
+
+	eint_data->drvdata = d;
+
+	handlers = eint0_3_parent_only ? s3c2410_eint_handlers
+				       : s3c2412_eint_handlers;
+	for (i = 0; i < NUM_EINT_IRQ; ++i) {
+		unsigned int irq;
+
+		irq = irq_of_parse_and_map(eint_np, i);
+		if (!irq) {
+			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
+			return -ENXIO;
+		}
+
+		eint_data->parents[i] = irq;
+		irq_set_chained_handler(irq, handlers[i]);
+		irq_set_handler_data(irq, eint_data);
+	}
+
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		struct s3c24xx_eint_domain_data *ddata;
+		unsigned int mask;
+		unsigned int irq;
+		unsigned int pin;
+
+		if (bank->eint_type != EINT_TYPE_WKUP)
+			continue;
+
+		ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+		if (!ddata)
+			return -ENOMEM;
+
+		ddata->bank = bank;
+		ddata->eint_data = eint_data;
+		ddata->eint0_3_parent_only = eint0_3_parent_only;
+
+		ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops
+					       : &s3c24xx_gpg_irq_ops;
+
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, ops, ddata);
+		if (!bank->irq_domain) {
+			dev_err(dev, "wkup irq domain add failed\n");
+			return -ENXIO;
+		}
+
+		irq = bank->eint_offset;
+		mask = bank->eint_mask;
+		for (pin = 0; mask; ++pin, mask >>= 1) {
+			if (irq >= NUM_EINT)
+				break;
+			if (!(mask & 1))
+				continue;
+			eint_data->domains[irq] = bank->irq_domain;
+			++irq;
+		}
+	}
+
+	return 0;
+}
+
+static struct samsung_pin_bank s3c2412_pin_banks[] = {
+	PIN_BANK_A(23, 0x000, "gpa"),
+	PIN_BANK_2BIT(11, 0x010, "gpb"),
+	PIN_BANK_2BIT(16, 0x020, "gpc"),
+	PIN_BANK_2BIT(16, 0x030, "gpd"),
+	PIN_BANK_2BIT(16, 0x040, "gpe"),
+	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
+	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
+	PIN_BANK_2BIT(11, 0x070, "gph"),
+	PIN_BANK_2BIT(13, 0x080, "gpj"),
+};
+
+struct samsung_pin_ctrl s3c2412_pin_ctrl[] = {
+	{
+		.pin_banks	= s3c2412_pin_banks,
+		.nr_banks	= ARRAY_SIZE(s3c2412_pin_banks),
+		.eint_wkup_init = s3c24xx_eint_init,
+		.label		= "S3C2412-GPIO",
+	},
+};
+
+static struct samsung_pin_bank s3c2416_pin_banks[] = {
+	PIN_BANK_A(27, 0x000, "gpa"),
+	PIN_BANK_2BIT(11, 0x010, "gpb"),
+	PIN_BANK_2BIT(16, 0x020, "gpc"),
+	PIN_BANK_2BIT(16, 0x030, "gpd"),
+	PIN_BANK_2BIT(16, 0x040, "gpe"),
+	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
+	PIN_BANK_2BIT_EINTW(8, 0x060, "gpg", 8, 0xff00),
+	PIN_BANK_2BIT(15, 0x070, "gph"),
+	PIN_BANK_2BIT(16, 0x0e0, "gpk"),
+	PIN_BANK_2BIT(14, 0x0f0, "gpl"),
+	PIN_BANK_2BIT(2, 0x100, "gpm"),
+};
+
+struct samsung_pin_ctrl s3c2416_pin_ctrl[] = {
+	{
+		.pin_banks	= s3c2416_pin_banks,
+		.nr_banks	= ARRAY_SIZE(s3c2416_pin_banks),
+		.eint_wkup_init = s3c24xx_eint_init,
+		.label		= "S3C2416-GPIO",
+	},
+};
+
+static struct samsung_pin_bank s3c2440_pin_banks[] = {
+	PIN_BANK_A(25, 0x000, "gpa"),
+	PIN_BANK_2BIT(11, 0x010, "gpb"),
+	PIN_BANK_2BIT(16, 0x020, "gpc"),
+	PIN_BANK_2BIT(16, 0x030, "gpd"),
+	PIN_BANK_2BIT(16, 0x040, "gpe"),
+	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
+	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
+	PIN_BANK_2BIT(11, 0x070, "gph"),
+	PIN_BANK_2BIT(13, 0x0d0, "gpj"),
+};
+
+struct samsung_pin_ctrl s3c2440_pin_ctrl[] = {
+	{
+		.pin_banks	= s3c2440_pin_banks,
+		.nr_banks	= ARRAY_SIZE(s3c2440_pin_banks),
+		.eint_wkup_init = s3c24xx_eint_init,
+		.label		= "S3C2440-GPIO",
+	},
+};
+
+static struct samsung_pin_bank s3c2450_pin_banks[] = {
+	PIN_BANK_A(28, 0x000, "gpa"),
+	PIN_BANK_2BIT(11, 0x010, "gpb"),
+	PIN_BANK_2BIT(16, 0x020, "gpc"),
+	PIN_BANK_2BIT(16, 0x030, "gpd"),
+	PIN_BANK_2BIT(16, 0x040, "gpe"),
+	PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
+	PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
+	PIN_BANK_2BIT(15, 0x070, "gph"),
+	PIN_BANK_2BIT(16, 0x0d0, "gpj"),
+	PIN_BANK_2BIT(16, 0x0e0, "gpk"),
+	PIN_BANK_2BIT(15, 0x0f0, "gpl"),
+	PIN_BANK_2BIT(2, 0x100, "gpm"),
+};
+
+struct samsung_pin_ctrl s3c2450_pin_ctrl[] = {
+	{
+		.pin_banks	= s3c2450_pin_banks,
+		.nr_banks	= ARRAY_SIZE(s3c2450_pin_banks),
+		.eint_wkup_init = s3c24xx_eint_init,
+		.label		= "S3C2450-GPIO",
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-s3c64xx.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-s3c64xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-s3c64xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,816 @@
+/*
+ * S3C64xx specific support for pinctrl-samsung driver.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Based on pinctrl-exynos.c, please see the file for original copyrights.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 contains the Samsung S3C64xx specific information required by the
+ * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+ * external gpio and wakeup interrupt support.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "pinctrl-samsung.h"
+
+#define NUM_EINT0		28
+#define NUM_EINT0_IRQ		4
+#define EINT_MAX_PER_REG	16
+#define EINT_MAX_PER_GROUP	16
+
+/* External GPIO and wakeup interrupt related definitions */
+#define SVC_GROUP_SHIFT		4
+#define SVC_GROUP_MASK		0xf
+#define SVC_NUM_MASK		0xf
+#define SVC_GROUP(x)		((x >> SVC_GROUP_SHIFT) & \
+						SVC_GROUP_MASK)
+
+#define EINT12CON_REG		0x200
+#define EINT12MASK_REG		0x240
+#define EINT12PEND_REG		0x260
+
+#define EINT_OFFS(i)		((i) % (2 * EINT_MAX_PER_GROUP))
+#define EINT_GROUP(i)		((i) / EINT_MAX_PER_GROUP)
+#define EINT_REG(g)		(4 * ((g) / 2))
+
+#define EINTCON_REG(i)		(EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
+#define EINTMASK_REG(i)		(EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
+#define EINTPEND_REG(i)		(EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
+
+#define SERVICE_REG		0x284
+#define SERVICEPEND_REG		0x288
+
+#define EINT0CON0_REG		0x900
+#define EINT0MASK_REG		0x920
+#define EINT0PEND_REG		0x924
+
+/* S3C64xx specific external interrupt trigger types */
+#define EINT_LEVEL_LOW		0
+#define EINT_LEVEL_HIGH		1
+#define EINT_EDGE_FALLING	2
+#define EINT_EDGE_RISING	4
+#define EINT_EDGE_BOTH		6
+#define EINT_CON_MASK		0xF
+#define EINT_CON_LEN		4
+
+static struct samsung_pin_bank_type bank_type_4bit_off = {
+	.fld_width = { 4, 1, 2, 0, 2, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit_alive = {
+	.fld_width = { 4, 1, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit2_off = {
+	.fld_width = { 4, 1, 2, 0, 2, 2, },
+	.reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit2_alive = {
+	.fld_width = { 4, 1, 2, },
+	.reg_offset = { 0x00, 0x08, 0x0c, },
+};
+
+static struct samsung_pin_bank_type bank_type_2bit_off = {
+	.fld_width = { 2, 1, 2, 0, 2, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
+};
+
+static struct samsung_pin_bank_type bank_type_2bit_alive = {
+	.fld_width = { 2, 1, 2, },
+	.reg_offset = { 0x00, 0x04, 0x08, },
+};
+
+#define PIN_BANK_4BIT(pins, reg, id)			\
+	{						\
+		.type		= &bank_type_4bit_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs)	\
+	{						\
+		.type		= &bank_type_4bit_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_GPIO,	\
+		.eint_func	= 7,			\
+		.eint_mask	= (1 << (pins)) - 1,	\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
+	{						\
+		.type		= &bank_type_4bit_alive,\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_func	= 3,			\
+		.eint_mask	= emask,		\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs)	\
+	{						\
+		.type		= &bank_type_4bit2_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_GPIO,	\
+		.eint_func	= 7,			\
+		.eint_mask	= (1 << (pins)) - 1,	\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
+	{						\
+		.type		= &bank_type_4bit2_alive,\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_func	= 3,			\
+		.eint_mask	= emask,		\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+#define PIN_BANK_4BIT2_ALIVE(pins, reg, id)		\
+	{						\
+		.type		= &bank_type_4bit2_alive,\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define PIN_BANK_2BIT(pins, reg, id)			\
+	{						\
+		.type		= &bank_type_2bit_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_NONE,	\
+		.name		= id			\
+	}
+
+#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
+	{						\
+		.type		= &bank_type_2bit_off,	\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_GPIO,	\
+		.eint_func	= 3,			\
+		.eint_mask	= emask,		\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs)	\
+	{						\
+		.type		= &bank_type_2bit_alive,\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_func	= 2,			\
+		.eint_mask	= (1 << (pins)) - 1,	\
+		.eint_offset	= eoffs,		\
+		.name		= id			\
+	}
+
+/**
+ * struct s3c64xx_eint0_data: EINT0 common data
+ * @drvdata: pin controller driver data
+ * @domains: IRQ domains of particular EINT0 interrupts
+ * @pins: pin offsets inside of banks of particular EINT0 interrupts
+ */
+struct s3c64xx_eint0_data {
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *domains[NUM_EINT0];
+	u8 pins[NUM_EINT0];
+};
+
+/**
+ * struct s3c64xx_eint0_domain_data: EINT0 per-domain data
+ * @bank: pin bank related to the domain
+ * @eints: EINT0 interrupts related to the domain
+ */
+struct s3c64xx_eint0_domain_data {
+	struct samsung_pin_bank *bank;
+	u8 eints[];
+};
+
+/**
+ * struct s3c64xx_eint_gpio_data: GPIO EINT data
+ * @drvdata: pin controller driver data
+ * @domains: array of domains related to EINT interrupt groups
+ */
+struct s3c64xx_eint_gpio_data {
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *domains[];
+};
+
+/*
+ * Common functions for S3C64xx EINT configuration
+ */
+
+static int s3c64xx_irq_get_trigger(unsigned int type)
+{
+	int trigger;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		trigger = EINT_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		trigger = EINT_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		trigger = EINT_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		trigger = EINT_LEVEL_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		trigger = EINT_LEVEL_LOW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return trigger;
+}
+
+static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
+{
+	/* Edge- and level-triggered interrupts need different handlers */
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		__irq_set_handler_locked(irq, handle_edge_irq);
+	else
+		__irq_set_handler_locked(irq, handle_level_irq);
+}
+
+static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
+					struct samsung_pin_bank *bank, int pin)
+{
+	struct samsung_pin_bank_type *bank_type = bank->type;
+	unsigned long flags;
+	void __iomem *reg;
+	u8 shift;
+	u32 mask;
+	u32 val;
+
+	/* Make sure that pin is configured as interrupt */
+	reg = d->virt_base + bank->pctl_offset;
+	shift = pin;
+	if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
+		/* 4-bit bank type with 2 con regs */
+		reg += 4;
+		shift -= 8;
+	}
+
+	shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
+	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	val = readl(reg);
+	val &= ~(mask << shift);
+	val |= bank->eint_func << shift;
+	writel(val, reg);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+/*
+ * Functions for EINT GPIO configuration (EINT groups 1-9)
+ */
+
+static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+	void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
+	u32 val;
+
+	val = readl(reg);
+	if (mask)
+		val |= 1 << index;
+	else
+		val &= ~(1 << index);
+	writel(val, reg);
+}
+
+static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
+{
+	s3c64xx_gpio_irq_set_mask(irqd, false);
+}
+
+static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
+{
+	s3c64xx_gpio_irq_set_mask(irqd, true);
+}
+
+static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+	void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
+
+	writel(1 << index, reg);
+}
+
+static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	void __iomem *reg;
+	int trigger;
+	u8 shift;
+	u32 val;
+
+	trigger = s3c64xx_irq_get_trigger(type);
+	if (trigger < 0) {
+		pr_err("unsupported external interrupt type\n");
+		return -EINVAL;
+	}
+
+	s3c64xx_irq_set_handler(irqd->irq, type);
+
+	/* Set up interrupt trigger */
+	reg = d->virt_base + EINTCON_REG(bank->eint_offset);
+	shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+	shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
+
+	val = readl(reg);
+	val &= ~(EINT_CON_MASK << shift);
+	val |= trigger << shift;
+	writel(val, reg);
+
+	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
+
+	return 0;
+}
+
+/*
+ * irq_chip for gpio interrupts.
+ */
+static struct irq_chip s3c64xx_gpio_irq_chip = {
+	.name		= "GPIO",
+	.irq_unmask	= s3c64xx_gpio_irq_unmask,
+	.irq_mask	= s3c64xx_gpio_irq_mask,
+	.irq_ack	= s3c64xx_gpio_irq_ack,
+	.irq_set_type	= s3c64xx_gpio_irq_set_type,
+};
+
+static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct samsung_pin_bank *bank = h->host_data;
+
+	if (!(bank->eint_mask & (1 << hw)))
+		return -EINVAL;
+
+	irq_set_chip_and_handler(virq,
+				&s3c64xx_gpio_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, bank);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+/*
+ * irq domain callbacks for external gpio interrupt controller.
+ */
+static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
+	.map	= s3c64xx_gpio_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+
+	chained_irq_enter(chip, desc);
+
+	do {
+		unsigned int svc;
+		unsigned int group;
+		unsigned int pin;
+		unsigned int virq;
+
+		svc = readl(drvdata->virt_base + SERVICE_REG);
+		group = SVC_GROUP(svc);
+		pin = svc & SVC_NUM_MASK;
+
+		if (!group)
+			break;
+
+		/* Group 1 is used for two pin banks */
+		if (group == 1) {
+			if (pin < 8)
+				group = 0;
+			else
+				pin -= 8;
+		}
+
+		virq = irq_linear_revmap(data->domains[group], pin);
+		/*
+		 * Something must be really wrong if an unmapped EINT
+		 * was unmasked...
+		 */
+		BUG_ON(!virq);
+
+		generic_handle_irq(virq);
+	} while (1);
+
+	chained_irq_exit(chip, desc);
+}
+
+/**
+ * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
+{
+	struct s3c64xx_eint_gpio_data *data;
+	struct samsung_pin_bank *bank;
+	struct device *dev = d->dev;
+	unsigned int nr_domains;
+	unsigned int i;
+
+	if (!d->irq) {
+		dev_err(dev, "irq number not available\n");
+		return -EINVAL;
+	}
+
+	nr_domains = 0;
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		unsigned int nr_eints;
+		unsigned int mask;
+
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+
+		mask = bank->eint_mask;
+		nr_eints = fls(mask);
+
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+					nr_eints, &s3c64xx_gpio_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "gpio irq domain add failed\n");
+			return -ENXIO;
+		}
+
+		++nr_domains;
+	}
+
+	data = devm_kzalloc(dev, sizeof(*data)
+			+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "failed to allocate handler data\n");
+		return -ENOMEM;
+	}
+	data->drvdata = d;
+
+	bank = d->ctrl->pin_banks;
+	nr_domains = 0;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+
+		data->domains[nr_domains++] = bank->irq_domain;
+	}
+
+	irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
+	irq_set_handler_data(d->irq, data);
+
+	return 0;
+}
+
+/*
+ * Functions for configuration of EINT0 wake-up interrupts
+ */
+
+static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
+{
+	struct s3c64xx_eint0_domain_data *ddata =
+					irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+	u32 val;
+
+	val = readl(d->virt_base + EINT0MASK_REG);
+	if (mask)
+		val |= 1 << ddata->eints[irqd->hwirq];
+	else
+		val &= ~(1 << ddata->eints[irqd->hwirq]);
+	writel(val, d->virt_base + EINT0MASK_REG);
+}
+
+static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
+{
+	s3c64xx_eint0_irq_set_mask(irqd, false);
+}
+
+static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
+{
+	s3c64xx_eint0_irq_set_mask(irqd, true);
+}
+
+static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
+{
+	struct s3c64xx_eint0_domain_data *ddata =
+					irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+
+	writel(1 << ddata->eints[irqd->hwirq],
+					d->virt_base + EINT0PEND_REG);
+}
+
+static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+	struct s3c64xx_eint0_domain_data *ddata =
+					irq_data_get_irq_chip_data(irqd);
+	struct samsung_pin_bank *bank = ddata->bank;
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	void __iomem *reg;
+	int trigger;
+	u8 shift;
+	u32 val;
+
+	trigger = s3c64xx_irq_get_trigger(type);
+	if (trigger < 0) {
+		pr_err("unsupported external interrupt type\n");
+		return -EINVAL;
+	}
+
+	s3c64xx_irq_set_handler(irqd->irq, type);
+
+	/* Set up interrupt trigger */
+	reg = d->virt_base + EINT0CON0_REG;
+	shift = ddata->eints[irqd->hwirq];
+	if (shift >= EINT_MAX_PER_REG) {
+		reg += 4;
+		shift -= EINT_MAX_PER_REG;
+	}
+	shift = EINT_CON_LEN * (shift / 2);
+
+	val = readl(reg);
+	val &= ~(EINT_CON_MASK << shift);
+	val |= trigger << shift;
+	writel(val, reg);
+
+	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
+
+	return 0;
+}
+
+/*
+ * irq_chip for wakeup interrupts
+ */
+static struct irq_chip s3c64xx_eint0_irq_chip = {
+	.name		= "EINT0",
+	.irq_unmask	= s3c64xx_eint0_irq_unmask,
+	.irq_mask	= s3c64xx_eint0_irq_mask,
+	.irq_ack	= s3c64xx_eint0_irq_ack,
+	.irq_set_type	= s3c64xx_eint0_irq_set_type,
+};
+
+static inline void s3c64xx_irq_demux_eint(unsigned int irq,
+					struct irq_desc *desc, u32 range)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+	unsigned int pend, mask;
+
+	chained_irq_enter(chip, desc);
+
+	pend = readl(drvdata->virt_base + EINT0PEND_REG);
+	mask = readl(drvdata->virt_base + EINT0MASK_REG);
+
+	pend = pend & range & ~mask;
+	pend &= range;
+
+	while (pend) {
+		unsigned int virq;
+
+		irq = fls(pend) - 1;
+		pend &= ~(1 << irq);
+
+		virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
+		/*
+		 * Something must be really wrong if an unmapped EINT
+		 * was unmasked...
+		 */
+		BUG_ON(!virq);
+
+		generic_handle_irq(virq);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+	s3c64xx_irq_demux_eint(irq, desc, 0xf);
+}
+
+static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+	s3c64xx_irq_demux_eint(irq, desc, 0xff0);
+}
+
+static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+{
+	s3c64xx_irq_demux_eint(irq, desc, 0xff000);
+}
+
+static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+{
+	s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
+}
+
+static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
+	s3c64xx_demux_eint0_3,
+	s3c64xx_demux_eint4_11,
+	s3c64xx_demux_eint12_19,
+	s3c64xx_demux_eint20_27,
+};
+
+static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
+					irq_hw_number_t hw)
+{
+	struct s3c64xx_eint0_domain_data *ddata = h->host_data;
+	struct samsung_pin_bank *bank = ddata->bank;
+
+	if (!(bank->eint_mask & (1 << hw)))
+		return -EINVAL;
+
+	irq_set_chip_and_handler(virq,
+				&s3c64xx_eint0_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, ddata);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+/*
+ * irq domain callbacks for external wakeup interrupt controller.
+ */
+static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
+	.map	= s3c64xx_eint0_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+/* list of external wakeup controllers supported */
+static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
+	{ .compatible = "samsung,s3c64xx-wakeup-eint", },
+	{ }
+};
+
+/**
+ * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
+{
+	struct device *dev = d->dev;
+	struct device_node *eint0_np = NULL;
+	struct device_node *np;
+	struct samsung_pin_bank *bank;
+	struct s3c64xx_eint0_data *data;
+	unsigned int i;
+
+	for_each_child_of_node(dev->of_node, np) {
+		if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
+			eint0_np = np;
+			break;
+		}
+	}
+	if (!eint0_np)
+		return -ENODEV;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "could not allocate memory for wkup eint data\n");
+		return -ENOMEM;
+	}
+	data->drvdata = d;
+
+	for (i = 0; i < NUM_EINT0_IRQ; ++i) {
+		unsigned int irq;
+
+		irq = irq_of_parse_and_map(eint0_np, i);
+		if (!irq) {
+			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
+			return -ENXIO;
+		}
+
+		irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
+		irq_set_handler_data(irq, data);
+	}
+
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		struct s3c64xx_eint0_domain_data *ddata;
+		unsigned int nr_eints;
+		unsigned int mask;
+		unsigned int irq;
+		unsigned int pin;
+
+		if (bank->eint_type != EINT_TYPE_WKUP)
+			continue;
+
+		mask = bank->eint_mask;
+		nr_eints = fls(mask);
+
+		ddata = devm_kzalloc(dev,
+				sizeof(*ddata) + nr_eints, GFP_KERNEL);
+		if (!ddata) {
+			dev_err(dev, "failed to allocate domain data\n");
+			return -ENOMEM;
+		}
+		ddata->bank = bank;
+
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
+		if (!bank->irq_domain) {
+			dev_err(dev, "wkup irq domain add failed\n");
+			return -ENXIO;
+		}
+
+		irq = bank->eint_offset;
+		mask = bank->eint_mask;
+		for (pin = 0; mask; ++pin, mask >>= 1) {
+			if (!(mask & 1))
+				continue;
+			data->domains[irq] = bank->irq_domain;
+			data->pins[irq] = pin;
+			ddata->eints[pin] = irq;
+			++irq;
+		}
+	}
+
+	return 0;
+}
+
+/* pin banks of s3c64xx pin-controller 0 */
+static struct samsung_pin_bank s3c64xx_pin_banks0[] = {
+	PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
+	PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
+	PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
+	PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
+	PIN_BANK_4BIT(5, 0x080, "gpe"),
+	PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
+	PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
+	PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
+	PIN_BANK_2BIT(16, 0x100, "gpi"),
+	PIN_BANK_2BIT(12, 0x120, "gpj"),
+	PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
+	PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
+	PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
+	PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
+	PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
+	PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
+	PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
+};
+
+/*
+ * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
+ * one gpio/pin-mux/pinconfig controller.
+ */
+struct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
+	{
+		/* pin-controller instance 1 data */
+		.pin_banks	= s3c64xx_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(s3c64xx_pin_banks0),
+		.eint_gpio_init = s3c64xx_eint_gpio_init,
+		.eint_wkup_init = s3c64xx_eint_eint0_init,
+		.label		= "S3C64xx-GPIO",
+	},
+};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-samsung.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-samsung.c
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-samsung.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-samsung.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,1285 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ *		http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver implements the Samsung pinctrl driver. It supports setting up of
+ * pinmux and pinconf configurations. The gpiolib interface is also included.
+ * External interrupt (gpio and wakeup) support are not included in this driver
+ * but provides extensions to which platform specific implementation of the gpio
+ * and wakeup interrupts can be hooked to.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+
+#include "../core.h"
+#include "pinctrl-samsung.h"
+
+#define GROUP_SUFFIX		"-grp"
+#define GSUFFIX_LEN		sizeof(GROUP_SUFFIX)
+#define FUNCTION_SUFFIX		"-mux"
+#define FSUFFIX_LEN		sizeof(FUNCTION_SUFFIX)
+
+/* list of all possible config options supported */
+static struct pin_config {
+	const char *property;
+	enum pincfg_type param;
+} cfg_params[] = {
+	{ "samsung,pin-pud", PINCFG_TYPE_PUD },
+	{ "samsung,pin-drv", PINCFG_TYPE_DRV },
+	{ "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
+	{ "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
+	{ "samsung,pin-val", PINCFG_TYPE_DAT },
+};
+
+/* Global list of devices (struct samsung_pinctrl_drv_data) */
+static LIST_HEAD(drvdata_list);
+
+static unsigned int pin_base;
+
+static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
+{
+	return container_of(gc, struct samsung_pin_bank, gpio_chip);
+}
+
+static int samsung_get_group_count(struct pinctrl_dev *pctldev)
+{
+	struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+	return pmx->nr_groups;
+}
+
+static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
+						unsigned group)
+{
+	struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+	return pmx->pin_groups[group].name;
+}
+
+static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
+					unsigned group,
+					const unsigned **pins,
+					unsigned *num_pins)
+{
+	struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = pmx->pin_groups[group].pins;
+	*num_pins = pmx->pin_groups[group].num_pins;
+
+	return 0;
+}
+
+static int reserve_map(struct device *dev, struct pinctrl_map **map,
+		       unsigned *reserved_maps, unsigned *num_maps,
+		       unsigned reserve)
+{
+	unsigned old_num = *reserved_maps;
+	unsigned new_num = *num_maps + reserve;
+	struct pinctrl_map *new_map;
+
+	if (old_num >= new_num)
+		return 0;
+
+	new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
+	if (!new_map) {
+		dev_err(dev, "krealloc(map) failed\n");
+		return -ENOMEM;
+	}
+
+	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
+
+	*map = new_map;
+	*reserved_maps = new_num;
+
+	return 0;
+}
+
+static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
+		       unsigned *num_maps, const char *group,
+		       const char *function)
+{
+	if (WARN_ON(*num_maps == *reserved_maps))
+		return -ENOSPC;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+	(*map)[*num_maps].data.mux.group = group;
+	(*map)[*num_maps].data.mux.function = function;
+	(*num_maps)++;
+
+	return 0;
+}
+
+static int add_map_configs(struct device *dev, struct pinctrl_map **map,
+			   unsigned *reserved_maps, unsigned *num_maps,
+			   const char *group, unsigned long *configs,
+			   unsigned num_configs)
+{
+	unsigned long *dup_configs;
+
+	if (WARN_ON(*num_maps == *reserved_maps))
+		return -ENOSPC;
+
+	dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+			      GFP_KERNEL);
+	if (!dup_configs) {
+		dev_err(dev, "kmemdup(configs) failed\n");
+		return -ENOMEM;
+	}
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+	(*map)[*num_maps].data.configs.group_or_pin = group;
+	(*map)[*num_maps].data.configs.configs = dup_configs;
+	(*map)[*num_maps].data.configs.num_configs = num_configs;
+	(*num_maps)++;
+
+	return 0;
+}
+
+static int add_config(struct device *dev, unsigned long **configs,
+		      unsigned *num_configs, unsigned long config)
+{
+	unsigned old_num = *num_configs;
+	unsigned new_num = old_num + 1;
+	unsigned long *new_configs;
+
+	new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
+			       GFP_KERNEL);
+	if (!new_configs) {
+		dev_err(dev, "krealloc(configs) failed\n");
+		return -ENOMEM;
+	}
+
+	new_configs[old_num] = config;
+
+	*configs = new_configs;
+	*num_configs = new_num;
+
+	return 0;
+}
+
+static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
+				      struct pinctrl_map *map,
+				      unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++)
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+			kfree(map[i].data.configs.configs);
+
+	kfree(map);
+}
+
+static int samsung_dt_subnode_to_map(struct samsung_pinctrl_drv_data *drvdata,
+				     struct device *dev,
+				     struct device_node *np,
+				     struct pinctrl_map **map,
+				     unsigned *reserved_maps,
+				     unsigned *num_maps)
+{
+	int ret, i;
+	u32 val;
+	unsigned long config;
+	unsigned long *configs = NULL;
+	unsigned num_configs = 0;
+	unsigned reserve;
+	struct property *prop;
+	const char *group;
+	bool has_func = false;
+
+	ret = of_property_read_u32(np, "samsung,pin-function", &val);
+	if (!ret)
+		has_func = true;
+
+	for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+		ret = of_property_read_u32(np, cfg_params[i].property, &val);
+		if (!ret) {
+			config = PINCFG_PACK(cfg_params[i].param, val);
+			ret = add_config(dev, &configs, &num_configs, config);
+			if (ret < 0)
+				goto exit;
+		/* EINVAL=missing, which is fine since it's optional */
+		} else if (ret != -EINVAL) {
+			dev_err(dev, "could not parse property %s\n",
+				cfg_params[i].property);
+		}
+	}
+
+	reserve = 0;
+	if (has_func)
+		reserve++;
+	if (num_configs)
+		reserve++;
+	ret = of_property_count_strings(np, "samsung,pins");
+	if (ret < 0) {
+		dev_err(dev, "could not parse property samsung,pins\n");
+		goto exit;
+	}
+	reserve *= ret;
+
+	ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_string(np, "samsung,pins", prop, group) {
+		if (has_func) {
+			ret = add_map_mux(map, reserved_maps,
+						num_maps, group, np->full_name);
+			if (ret < 0)
+				goto exit;
+		}
+
+		if (num_configs) {
+			ret = add_map_configs(dev, map, reserved_maps,
+					      num_maps, group, configs,
+					      num_configs);
+			if (ret < 0)
+				goto exit;
+		}
+	}
+
+	ret = 0;
+
+exit:
+	kfree(configs);
+	return ret;
+}
+
+static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
+					struct device_node *np_config,
+					struct pinctrl_map **map,
+					unsigned *num_maps)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	unsigned reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	if (!of_get_child_count(np_config))
+		return samsung_dt_subnode_to_map(drvdata, pctldev->dev,
+							np_config, map,
+							&reserved_maps,
+							num_maps);
+
+	for_each_child_of_node(np_config, np) {
+		ret = samsung_dt_subnode_to_map(drvdata, pctldev->dev, np, map,
+						&reserved_maps, num_maps);
+		if (ret < 0) {
+			samsung_dt_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* list of pinctrl callbacks for the pinctrl core */
+static const struct pinctrl_ops samsung_pctrl_ops = {
+	.get_groups_count	= samsung_get_group_count,
+	.get_group_name		= samsung_get_group_name,
+	.get_group_pins		= samsung_get_group_pins,
+	.dt_node_to_map		= samsung_dt_node_to_map,
+	.dt_free_map		= samsung_dt_free_map,
+};
+
+/* check if the selector is a valid pin function selector */
+static int samsung_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	return drvdata->nr_functions;
+}
+
+/* return the name of the pin function specified */
+static const char *samsung_pinmux_get_fname(struct pinctrl_dev *pctldev,
+						unsigned selector)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	return drvdata->pmx_functions[selector].name;
+}
+
+/* return the groups associated for the specified function selector */
+static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
+		unsigned selector, const char * const **groups,
+		unsigned * const num_groups)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	*groups = drvdata->pmx_functions[selector].groups;
+	*num_groups = drvdata->pmx_functions[selector].num_groups;
+	return 0;
+}
+
+/*
+ * given a pin number that is local to a pin controller, find out the pin bank
+ * and the register base of the pin bank.
+ */
+static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
+			unsigned pin, void __iomem **reg, u32 *offset,
+			struct samsung_pin_bank **bank)
+{
+	struct samsung_pin_bank *b;
+
+	b = drvdata->ctrl->pin_banks;
+
+	while ((pin >= b->pin_base) &&
+			((b->pin_base + b->nr_pins - 1) < pin))
+		b++;
+
+	*reg = drvdata->virt_base + b->pctl_offset;
+	*offset = pin - b->pin_base;
+	if (bank)
+		*bank = b;
+}
+
+/* enable or disable a pinmux function */
+static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group, bool enable)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct samsung_pin_bank_type *type;
+	struct samsung_pin_bank *bank;
+	void __iomem *reg;
+	u32 mask, shift, data, pin_offset;
+	unsigned long flags;
+	const struct samsung_pmx_func *func;
+	const struct samsung_pin_group *grp;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	func = &drvdata->pmx_functions[selector];
+	grp = &drvdata->pin_groups[group];
+
+	pin_to_reg_bank(drvdata, grp->pins[0] - drvdata->ctrl->base,
+			&reg, &pin_offset, &bank);
+	type = bank->type;
+	mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+	shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
+	if (shift >= 32) {
+		/* Some banks have two config registers */
+		shift -= 32;
+		reg += 4;
+	}
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
+	data &= ~(mask << shift);
+	if (enable)
+		data |= func->val << shift;
+	writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+/* enable a specified pinmux by writing to registers */
+static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group)
+{
+	samsung_pinmux_setup(pctldev, selector, group, true);
+	return 0;
+}
+
+/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
+static const struct pinmux_ops samsung_pinmux_ops = {
+	.get_functions_count	= samsung_get_functions_count,
+	.get_function_name	= samsung_pinmux_get_fname,
+	.get_function_groups	= samsung_pinmux_get_groups,
+	.enable			= samsung_pinmux_enable,
+};
+
+/* set or get the pin config settings for a specified pin */
+static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long *config, bool set)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct samsung_pin_bank_type *type;
+	struct samsung_pin_bank *bank;
+	void __iomem *reg_base;
+	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
+	u32 data, width, pin_offset, mask, shift;
+	u32 cfg_value, cfg_reg;
+	unsigned long flags;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
+					&pin_offset, &bank);
+	type = bank->type;
+
+	if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
+		return -EINVAL;
+
+	width = type->fld_width[cfg_type];
+	cfg_reg = type->reg_offset[cfg_type];
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	mask = (1 << width) - 1;
+	shift = pin_offset * width;
+	data = readl(reg_base + cfg_reg);
+
+	if (set) {
+		cfg_value = PINCFG_UNPACK_VALUE(*config);
+		data &= ~(mask << shift);
+		data |= (cfg_value << shift);
+		writel(data, reg_base + cfg_reg);
+	} else {
+		data >>= shift;
+		data &= mask;
+		*config = PINCFG_PACK(cfg_type, data);
+	}
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+
+	return 0;
+}
+
+/* set the pin config settings for a specified pin */
+static int samsung_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long *configs, unsigned num_configs)
+{
+	int i, ret;
+
+	for (i = 0; i < num_configs; i++) {
+		ret = samsung_pinconf_rw(pctldev, pin, &configs[i], true);
+		if (ret < 0)
+			return ret;
+	} /* for each config */
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin */
+static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+					unsigned long *config)
+{
+	return samsung_pinconf_rw(pctldev, pin, config, false);
+}
+
+/* set the pin config settings for a specified pin group */
+static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
+			unsigned group, unsigned long *configs,
+			unsigned num_configs)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	const unsigned int *pins;
+	unsigned int cnt;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	pins = drvdata->pin_groups[group].pins;
+
+	for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++)
+		samsung_pinconf_set(pctldev, pins[cnt], configs, num_configs);
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin group */
+static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned int group, unsigned long *config)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	const unsigned int *pins;
+
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+	pins = drvdata->pin_groups[group].pins;
+	samsung_pinconf_get(pctldev, pins[0], config);
+	return 0;
+}
+
+/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
+static const struct pinconf_ops samsung_pinconf_ops = {
+	.pin_config_get		= samsung_pinconf_get,
+	.pin_config_set		= samsung_pinconf_set,
+	.pin_config_group_get	= samsung_pinconf_group_get,
+	.pin_config_group_set	= samsung_pinconf_group_set,
+};
+
+/* gpiolib gpio_set callback function */
+static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+	struct samsung_pin_bank_type *type = bank->type;
+	unsigned long flags;
+	void __iomem *reg;
+	u32 data;
+
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
+	data &= ~(1 << offset);
+	if (value)
+		data |= 1 << offset;
+	writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+/* gpiolib gpio_get callback function */
+static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	void __iomem *reg;
+	u32 data;
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+	struct samsung_pin_bank_type *type = bank->type;
+
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
+
+	data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
+	data >>= offset;
+	data &= 1;
+	return data;
+}
+
+/*
+ * The calls to gpio_direction_output() and gpio_direction_input()
+ * leads to this function call.
+ */
+static int samsung_gpio_set_direction(struct gpio_chip *gc,
+					     unsigned offset, bool input)
+{
+	struct samsung_pin_bank_type *type;
+	struct samsung_pin_bank *bank;
+	struct samsung_pinctrl_drv_data *drvdata;
+	void __iomem *reg;
+	u32 data, mask, shift;
+	unsigned long flags;
+
+	bank = gc_to_pin_bank(gc);
+	type = bank->type;
+	drvdata = bank->drvdata;
+
+	reg = drvdata->virt_base + bank->pctl_offset +
+					type->reg_offset[PINCFG_TYPE_FUNC];
+
+	mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+	shift = offset * type->fld_width[PINCFG_TYPE_FUNC];
+	if (shift >= 32) {
+		/* Some banks have two config registers */
+		shift -= 32;
+		reg += 4;
+	}
+
+	spin_lock_irqsave(&bank->slock, flags);
+
+	data = readl(reg);
+	data &= ~(mask << shift);
+	if (!input)
+		data |= FUNC_OUTPUT << shift;
+	writel(data, reg);
+
+	spin_unlock_irqrestore(&bank->slock, flags);
+
+	return 0;
+}
+
+/* gpiolib gpio_direction_input callback function. */
+static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	return samsung_gpio_set_direction(gc, offset, true);
+}
+
+/* gpiolib gpio_direction_output callback function. */
+static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+							int value)
+{
+	samsung_gpio_set(gc, offset, value);
+	return samsung_gpio_set_direction(gc, offset, false);
+}
+
+/*
+ * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
+ * and a virtual IRQ, if not already present.
+ */
+static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+	unsigned int virq;
+
+	if (!bank->irq_domain)
+		return -ENXIO;
+
+	virq = irq_create_mapping(bank->irq_domain, offset);
+
+	return (virq) ? : -ENXIO;
+}
+
+static struct samsung_pin_group *samsung_pinctrl_create_groups(
+				struct device *dev,
+				struct samsung_pinctrl_drv_data *drvdata,
+				unsigned int *cnt)
+{
+	struct pinctrl_desc *ctrldesc = &drvdata->pctl;
+	struct samsung_pin_group *groups, *grp;
+	const struct pinctrl_pin_desc *pdesc;
+	int i;
+
+	groups = devm_kzalloc(dev, ctrldesc->npins * sizeof(*groups),
+				GFP_KERNEL);
+	if (!groups)
+		return ERR_PTR(-EINVAL);
+	grp = groups;
+
+	pdesc = ctrldesc->pins;
+	for (i = 0; i < ctrldesc->npins; ++i, ++pdesc, ++grp) {
+		grp->name = pdesc->name;
+		grp->pins = &pdesc->number;
+		grp->num_pins = 1;
+	}
+
+	*cnt = ctrldesc->npins;
+	return groups;
+}
+
+static int samsung_pinctrl_create_function(struct device *dev,
+				struct samsung_pinctrl_drv_data *drvdata,
+				struct device_node *func_np,
+				struct samsung_pmx_func *func)
+{
+	int npins;
+	int ret;
+	int i;
+
+	if (of_property_read_u32(func_np, "samsung,pin-function", &func->val))
+		return 0;
+
+	npins = of_property_count_strings(func_np, "samsung,pins");
+	if (npins < 1) {
+		dev_err(dev, "invalid pin list in %s node", func_np->name);
+		return -EINVAL;
+	}
+
+	func->name = func_np->full_name;
+
+	func->groups = devm_kzalloc(dev, npins * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for (i = 0; i < npins; ++i) {
+		const char *gname;
+
+		ret = of_property_read_string_index(func_np, "samsung,pins",
+							i, &gname);
+		if (ret) {
+			dev_err(dev,
+				"failed to read pin name %d from %s node\n",
+				i, func_np->name);
+			return ret;
+		}
+
+		func->groups[i] = gname;
+	}
+
+	func->num_groups = npins;
+	return 1;
+}
+
+static struct samsung_pmx_func *samsung_pinctrl_create_functions(
+				struct device *dev,
+				struct samsung_pinctrl_drv_data *drvdata,
+				unsigned int *cnt)
+{
+	struct samsung_pmx_func *functions, *func;
+	struct device_node *dev_np = dev->of_node;
+	struct device_node *cfg_np;
+	unsigned int func_cnt = 0;
+	int ret;
+
+	/*
+	 * Iterate over all the child nodes of the pin controller node
+	 * and create pin groups and pin function lists.
+	 */
+	for_each_child_of_node(dev_np, cfg_np) {
+		struct device_node *func_np;
+
+		if (!of_get_child_count(cfg_np)) {
+			if (!of_find_property(cfg_np,
+			    "samsung,pin-function", NULL))
+				continue;
+			++func_cnt;
+			continue;
+		}
+
+		for_each_child_of_node(cfg_np, func_np) {
+			if (!of_find_property(func_np,
+			    "samsung,pin-function", NULL))
+				continue;
+			++func_cnt;
+		}
+	}
+
+	functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
+					GFP_KERNEL);
+	if (!functions) {
+		dev_err(dev, "failed to allocate memory for function list\n");
+		return ERR_PTR(-EINVAL);
+	}
+	func = functions;
+
+	/*
+	 * Iterate over all the child nodes of the pin controller node
+	 * and create pin groups and pin function lists.
+	 */
+	func_cnt = 0;
+	for_each_child_of_node(dev_np, cfg_np) {
+		struct device_node *func_np;
+
+		if (!of_get_child_count(cfg_np)) {
+			ret = samsung_pinctrl_create_function(dev, drvdata,
+							cfg_np, func);
+			if (ret < 0)
+				return ERR_PTR(ret);
+			if (ret > 0) {
+				++func;
+				++func_cnt;
+			}
+			continue;
+		}
+
+		for_each_child_of_node(cfg_np, func_np) {
+			ret = samsung_pinctrl_create_function(dev, drvdata,
+						func_np, func);
+			if (ret < 0)
+				return ERR_PTR(ret);
+			if (ret > 0) {
+				++func;
+				++func_cnt;
+			}
+		}
+	}
+
+	*cnt = func_cnt;
+	return functions;
+}
+
+/*
+ * Parse the information about all the available pin groups and pin functions
+ * from device node of the pin-controller. A pin group is formed with all
+ * the pins listed in the "samsung,pins" property.
+ */
+
+static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
+				    struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct device *dev = &pdev->dev;
+	struct samsung_pin_group *groups;
+	struct samsung_pmx_func *functions;
+	unsigned int grp_cnt = 0, func_cnt = 0;
+
+	groups = samsung_pinctrl_create_groups(dev, drvdata, &grp_cnt);
+	if (IS_ERR(groups)) {
+		dev_err(dev, "failed to parse pin groups\n");
+		return PTR_ERR(groups);
+	}
+
+	functions = samsung_pinctrl_create_functions(dev, drvdata, &func_cnt);
+	if (IS_ERR(functions)) {
+		dev_err(dev, "failed to parse pin functions\n");
+		return PTR_ERR(groups);
+	}
+
+	drvdata->pin_groups = groups;
+	drvdata->nr_groups = grp_cnt;
+	drvdata->pmx_functions = functions;
+	drvdata->nr_functions = func_cnt;
+
+	return 0;
+}
+
+/* register the pinctrl interface with the pinctrl subsystem */
+static int samsung_pinctrl_register(struct platform_device *pdev,
+				    struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct pinctrl_desc *ctrldesc = &drvdata->pctl;
+	struct pinctrl_pin_desc *pindesc, *pdesc;
+	struct samsung_pin_bank *pin_bank;
+	char *pin_names;
+	int pin, bank, ret;
+
+	ctrldesc->name = "samsung-pinctrl";
+	ctrldesc->owner = THIS_MODULE;
+	ctrldesc->pctlops = &samsung_pctrl_ops;
+	ctrldesc->pmxops = &samsung_pinmux_ops;
+	ctrldesc->confops = &samsung_pinconf_ops;
+
+	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
+			drvdata->ctrl->nr_pins, GFP_KERNEL);
+	if (!pindesc) {
+		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+		return -ENOMEM;
+	}
+	ctrldesc->pins = pindesc;
+	ctrldesc->npins = drvdata->ctrl->nr_pins;
+
+	/* dynamically populate the pin number and pin name for pindesc */
+	for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
+		pdesc->number = pin + drvdata->ctrl->base;
+
+	/*
+	 * allocate space for storing the dynamically generated names for all
+	 * the pins which belong to this pin-controller.
+	 */
+	pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
+					drvdata->ctrl->nr_pins, GFP_KERNEL);
+	if (!pin_names) {
+		dev_err(&pdev->dev, "mem alloc for pin names failed\n");
+		return -ENOMEM;
+	}
+
+	/* for each pin, the name of the pin is pin-bank name + pin number */
+	for (bank = 0; bank < drvdata->ctrl->nr_banks; bank++) {
+		pin_bank = &drvdata->ctrl->pin_banks[bank];
+		for (pin = 0; pin < pin_bank->nr_pins; pin++) {
+			sprintf(pin_names, "%s-%d", pin_bank->name, pin);
+			pdesc = pindesc + pin_bank->pin_base + pin;
+			pdesc->name = pin_names;
+			pin_names += PIN_NAME_LENGTH;
+		}
+	}
+
+	ret = samsung_pinctrl_parse_dt(pdev, drvdata);
+	if (ret)
+		return ret;
+
+	drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
+	if (!drvdata->pctl_dev) {
+		dev_err(&pdev->dev, "could not register pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
+		pin_bank = &drvdata->ctrl->pin_banks[bank];
+		pin_bank->grange.name = pin_bank->name;
+		pin_bank->grange.id = bank;
+		pin_bank->grange.pin_base = drvdata->ctrl->base
+						+ pin_bank->pin_base;
+		pin_bank->grange.base = pin_bank->gpio_chip.base;
+		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+		pin_bank->grange.gc = &pin_bank->gpio_chip;
+		pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
+	}
+
+	return 0;
+}
+
+static int samsung_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void samsung_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static const struct gpio_chip samsung_gpiolib_chip = {
+	.request = samsung_gpio_request,
+	.free = samsung_gpio_free,
+	.set = samsung_gpio_set,
+	.get = samsung_gpio_get,
+	.direction_input = samsung_gpio_direction_input,
+	.direction_output = samsung_gpio_direction_output,
+	.to_irq = samsung_gpio_to_irq,
+	.owner = THIS_MODULE,
+};
+
+/* register the gpiolib interface with the gpiolib subsystem */
+static int samsung_gpiolib_register(struct platform_device *pdev,
+				    struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	struct gpio_chip *gc;
+	int ret;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		bank->gpio_chip = samsung_gpiolib_chip;
+
+		gc = &bank->gpio_chip;
+		gc->base = ctrl->base + bank->pin_base;
+		gc->ngpio = bank->nr_pins;
+		gc->dev = &pdev->dev;
+		gc->of_node = bank->of_node;
+		gc->label = bank->name;
+
+		ret = gpiochip_add(gc);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+							gc->label, ret);
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	for (--i, --bank; i >= 0; --i, --bank)
+		if (gpiochip_remove(&bank->gpio_chip))
+			dev_err(&pdev->dev, "gpio chip %s remove failed\n",
+							bank->gpio_chip.label);
+	return ret;
+}
+
+/* unregister the gpiolib interface with the gpiolib subsystem */
+static int samsung_gpiolib_unregister(struct platform_device *pdev,
+				      struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	int ret = 0;
+	int i;
+
+	for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
+		ret = gpiochip_remove(&bank->gpio_chip);
+
+	if (ret)
+		dev_err(&pdev->dev, "gpio chip remove failed\n");
+
+	return ret;
+}
+
+static const struct of_device_id samsung_pinctrl_dt_match[];
+
+/* retrieve the soc specific data */
+static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+				struct samsung_pinctrl_drv_data *d,
+				struct platform_device *pdev)
+{
+	int id;
+	const struct of_device_id *match;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *np;
+	struct samsung_pin_ctrl *ctrl;
+	struct samsung_pin_bank *bank;
+	int i;
+
+	id = of_alias_get_id(node, "pinctrl");
+	if (id < 0) {
+		dev_err(&pdev->dev, "failed to get alias id\n");
+		return NULL;
+	}
+	match = of_match_node(samsung_pinctrl_dt_match, node);
+	ctrl = (struct samsung_pin_ctrl *)match->data + id;
+
+	bank = ctrl->pin_banks;
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		spin_lock_init(&bank->slock);
+		bank->drvdata = d;
+		bank->pin_base = ctrl->nr_pins;
+		ctrl->nr_pins += bank->nr_pins;
+	}
+
+	for_each_child_of_node(node, np) {
+		if (!of_find_property(np, "gpio-controller", NULL))
+			continue;
+		bank = ctrl->pin_banks;
+		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+			if (!strcmp(bank->name, np->name)) {
+				bank->of_node = np;
+				break;
+			}
+		}
+	}
+
+	ctrl->base = pin_base;
+	pin_base += ctrl->nr_pins;
+
+	return ctrl;
+}
+
+static int samsung_pinctrl_probe(struct platform_device *pdev)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct device *dev = &pdev->dev;
+	struct samsung_pin_ctrl *ctrl;
+	struct resource *res;
+	int ret;
+
+	if (!dev->of_node) {
+		dev_err(dev, "device tree node not found\n");
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata) {
+		dev_err(dev, "failed to allocate memory for driver's "
+				"private data\n");
+		return -ENOMEM;
+	}
+
+	ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
+	if (!ctrl) {
+		dev_err(&pdev->dev, "driver data not available\n");
+		return -EINVAL;
+	}
+	drvdata->ctrl = ctrl;
+	drvdata->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(drvdata->virt_base))
+		return PTR_ERR(drvdata->virt_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res)
+		drvdata->irq = res->start;
+
+	ret = samsung_gpiolib_register(pdev, drvdata);
+	if (ret)
+		return ret;
+
+	ret = samsung_pinctrl_register(pdev, drvdata);
+	if (ret) {
+		samsung_gpiolib_unregister(pdev, drvdata);
+		return ret;
+	}
+
+	if (ctrl->eint_gpio_init)
+		ctrl->eint_gpio_init(drvdata);
+	if (ctrl->eint_wkup_init)
+		ctrl->eint_wkup_init(drvdata);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	/* Add to the global list */
+	list_add_tail(&drvdata->node, &drvdata_list);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/**
+ * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device
+ *
+ * Save data for all banks handled by this device.
+ */
+static void samsung_pinctrl_suspend_dev(
+	struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	void __iomem *virt_base = drvdata->virt_base;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; i++) {
+		struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
+		void __iomem *reg = virt_base + bank->pctl_offset;
+
+		u8 *offs = bank->type->reg_offset;
+		u8 *widths = bank->type->fld_width;
+		enum pincfg_type type;
+
+		/* Registers without a powerdown config aren't lost */
+		if (!widths[PINCFG_TYPE_CON_PDN])
+			continue;
+
+		for (type = 0; type < PINCFG_TYPE_NUM; type++)
+			if (widths[type])
+				bank->pm_save[type] = readl(reg + offs[type]);
+
+		if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
+			/* Some banks have two config registers */
+			bank->pm_save[PINCFG_TYPE_NUM] =
+				readl(reg + offs[PINCFG_TYPE_FUNC] + 4);
+			pr_debug("Save %s @ %p (con %#010x %08x)\n",
+				 bank->name, reg,
+				 bank->pm_save[PINCFG_TYPE_FUNC],
+				 bank->pm_save[PINCFG_TYPE_NUM]);
+		} else {
+			pr_debug("Save %s @ %p (con %#010x)\n", bank->name,
+				 reg, bank->pm_save[PINCFG_TYPE_FUNC]);
+		}
+	}
+
+	if (ctrl->suspend)
+		ctrl->suspend(drvdata);
+}
+
+/**
+ * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
+ *
+ * Restore one of the banks that was saved during suspend.
+ *
+ * We don't bother doing anything complicated to avoid glitching lines since
+ * we're called before pad retention is turned off.
+ */
+static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
+{
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	void __iomem *virt_base = drvdata->virt_base;
+	int i;
+
+	if (ctrl->resume)
+		ctrl->resume(drvdata);
+
+	for (i = 0; i < ctrl->nr_banks; i++) {
+		struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
+		void __iomem *reg = virt_base + bank->pctl_offset;
+
+		u8 *offs = bank->type->reg_offset;
+		u8 *widths = bank->type->fld_width;
+		enum pincfg_type type;
+
+		/* Registers without a powerdown config aren't lost */
+		if (!widths[PINCFG_TYPE_CON_PDN])
+			continue;
+
+		if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
+			/* Some banks have two config registers */
+			pr_debug("%s @ %p (con %#010x %08x => %#010x %08x)\n",
+				 bank->name, reg,
+				 readl(reg + offs[PINCFG_TYPE_FUNC]),
+				 readl(reg + offs[PINCFG_TYPE_FUNC] + 4),
+				 bank->pm_save[PINCFG_TYPE_FUNC],
+				 bank->pm_save[PINCFG_TYPE_NUM]);
+			writel(bank->pm_save[PINCFG_TYPE_NUM],
+			       reg + offs[PINCFG_TYPE_FUNC] + 4);
+		} else {
+			pr_debug("%s @ %p (con %#010x => %#010x)\n", bank->name,
+				 reg, readl(reg + offs[PINCFG_TYPE_FUNC]),
+				 bank->pm_save[PINCFG_TYPE_FUNC]);
+		}
+		for (type = 0; type < PINCFG_TYPE_NUM; type++)
+			if (widths[type])
+				writel(bank->pm_save[type], reg + offs[type]);
+	}
+}
+
+/**
+ * samsung_pinctrl_suspend - save pinctrl state for suspend
+ *
+ * Save data for all banks across all devices.
+ */
+static int samsung_pinctrl_suspend(void)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+
+	list_for_each_entry(drvdata, &drvdata_list, node) {
+		samsung_pinctrl_suspend_dev(drvdata);
+	}
+
+	return 0;
+}
+
+/**
+ * samsung_pinctrl_resume - restore pinctrl state for suspend
+ *
+ * Restore data for all banks across all devices.
+ */
+static void samsung_pinctrl_resume(void)
+{
+	struct samsung_pinctrl_drv_data *drvdata;
+
+	list_for_each_entry_reverse(drvdata, &drvdata_list, node) {
+		samsung_pinctrl_resume_dev(drvdata);
+	}
+}
+
+#else
+#define samsung_pinctrl_suspend		NULL
+#define samsung_pinctrl_resume		NULL
+#endif
+
+static struct syscore_ops samsung_pinctrl_syscore_ops = {
+	.suspend	= samsung_pinctrl_suspend,
+	.resume		= samsung_pinctrl_resume,
+};
+
+static const struct of_device_id samsung_pinctrl_dt_match[] = {
+#ifdef CONFIG_PINCTRL_EXYNOS
+	{ .compatible = "samsung,exynos3250-pinctrl",
+		.data = (void *)exynos3250_pin_ctrl },
+	{ .compatible = "samsung,exynos4210-pinctrl",
+		.data = (void *)exynos4210_pin_ctrl },
+	{ .compatible = "samsung,exynos4x12-pinctrl",
+		.data = (void *)exynos4x12_pin_ctrl },
+	{ .compatible = "samsung,exynos5250-pinctrl",
+		.data = (void *)exynos5250_pin_ctrl },
+	{ .compatible = "samsung,exynos5260-pinctrl",
+		.data = (void *)exynos5260_pin_ctrl },
+	{ .compatible = "samsung,exynos5420-pinctrl",
+		.data = (void *)exynos5420_pin_ctrl },
+	{ .compatible = "samsung,s5pv210-pinctrl",
+		.data = (void *)s5pv210_pin_ctrl },
+#endif
+#ifdef CONFIG_PINCTRL_S3C64XX
+	{ .compatible = "samsung,s3c64xx-pinctrl",
+		.data = s3c64xx_pin_ctrl },
+#endif
+#ifdef CONFIG_PINCTRL_S3C24XX
+	{ .compatible = "samsung,s3c2412-pinctrl",
+		.data = s3c2412_pin_ctrl },
+	{ .compatible = "samsung,s3c2416-pinctrl",
+		.data = s3c2416_pin_ctrl },
+	{ .compatible = "samsung,s3c2440-pinctrl",
+		.data = s3c2440_pin_ctrl },
+	{ .compatible = "samsung,s3c2450-pinctrl",
+		.data = s3c2450_pin_ctrl },
+#endif
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
+
+static struct platform_driver samsung_pinctrl_driver = {
+	.probe		= samsung_pinctrl_probe,
+	.driver = {
+		.name	= "samsung-pinctrl",
+		.owner	= THIS_MODULE,
+		.of_match_table = samsung_pinctrl_dt_match,
+	},
+};
+
+static int __init samsung_pinctrl_drv_register(void)
+{
+	/*
+	 * Register syscore ops for save/restore of registers across suspend.
+	 * It's important to ensure that this driver is running at an earlier
+	 * initcall level than any arch-specific init calls that install syscore
+	 * ops that turn off pad retention (like exynos_pm_resume).
+	 */
+	register_syscore_ops(&samsung_pinctrl_syscore_ops);
+
+	return platform_driver_register(&samsung_pinctrl_driver);
+}
+postcore_initcall(samsung_pinctrl_drv_register);
+
+static void __exit samsung_pinctrl_drv_unregister(void)
+{
+	platform_driver_unregister(&samsung_pinctrl_driver);
+}
+module_exit(samsung_pinctrl_drv_unregister);
+
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_DESCRIPTION("Samsung pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-samsung.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-samsung.h
--- linux-libre-3.16-gnu/drivers/pinctrl/samsung/pinctrl-samsung.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/samsung/pinctrl-samsung.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,252 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ *		http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __PINCTRL_SAMSUNG_H
+#define __PINCTRL_SAMSUNG_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+
+#include <linux/gpio.h>
+
+/* pinmux function number for pin as gpio output line */
+#define FUNC_INPUT	0x0
+#define FUNC_OUTPUT	0x1
+
+/**
+ * enum pincfg_type - possible pin configuration types supported.
+ * @PINCFG_TYPE_FUNC: Function configuration.
+ * @PINCFG_TYPE_DAT: Pin value configuration.
+ * @PINCFG_TYPE_PUD: Pull up/down configuration.
+ * @PINCFG_TYPE_DRV: Drive strength configuration.
+ * @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
+ * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
+ */
+enum pincfg_type {
+	PINCFG_TYPE_FUNC,
+	PINCFG_TYPE_DAT,
+	PINCFG_TYPE_PUD,
+	PINCFG_TYPE_DRV,
+	PINCFG_TYPE_CON_PDN,
+	PINCFG_TYPE_PUD_PDN,
+
+	PINCFG_TYPE_NUM
+};
+
+/*
+ * pin configuration (pull up/down and drive strength) type and its value are
+ * packed together into a 16-bits. The upper 8-bits represent the configuration
+ * type and the lower 8-bits hold the value of the configuration type.
+ */
+#define PINCFG_TYPE_MASK		0xFF
+#define PINCFG_VALUE_SHIFT		8
+#define PINCFG_VALUE_MASK		(0xFF << PINCFG_VALUE_SHIFT)
+#define PINCFG_PACK(type, value)	(((value) << PINCFG_VALUE_SHIFT) | type)
+#define PINCFG_UNPACK_TYPE(cfg)		((cfg) & PINCFG_TYPE_MASK)
+#define PINCFG_UNPACK_VALUE(cfg)	(((cfg) & PINCFG_VALUE_MASK) >> \
+						PINCFG_VALUE_SHIFT)
+/**
+ * enum eint_type - possible external interrupt types.
+ * @EINT_TYPE_NONE: bank does not support external interrupts
+ * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
+ * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
+ *
+ * Samsung GPIO controller groups all the available pins into banks. The pins
+ * in a pin bank can support external gpio interrupts or external wakeup
+ * interrupts or no interrupts at all. From a software perspective, the only
+ * difference between external gpio and external wakeup interrupts is that
+ * the wakeup interrupts can additionally wakeup the system if it is in
+ * suspended state.
+ */
+enum eint_type {
+	EINT_TYPE_NONE,
+	EINT_TYPE_GPIO,
+	EINT_TYPE_WKUP,
+	EINT_TYPE_WKUP_MUX,
+};
+
+/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
+#define PIN_NAME_LENGTH	10
+
+#define PIN_GROUP(n, p, f)				\
+	{						\
+		.name		= n,			\
+		.pins		= p,			\
+		.num_pins	= ARRAY_SIZE(p),	\
+		.func		= f			\
+	}
+
+#define PMX_FUNC(n, g)					\
+	{						\
+		.name		= n,			\
+		.groups		= g,			\
+		.num_groups	= ARRAY_SIZE(g),	\
+	}
+
+struct samsung_pinctrl_drv_data;
+
+/**
+ * struct samsung_pin_bank_type: pin bank type description
+ * @fld_width: widths of configuration bitfields (0 if unavailable)
+ * @reg_offset: offsets of configuration registers (don't care of width is 0)
+ */
+struct samsung_pin_bank_type {
+	u8 fld_width[PINCFG_TYPE_NUM];
+	u8 reg_offset[PINCFG_TYPE_NUM];
+};
+
+/**
+ * struct samsung_pin_bank: represent a controller pin-bank.
+ * @type: type of the bank (register offsets and bitfield widths)
+ * @pctl_offset: starting offset of the pin-bank registers.
+ * @pin_base: starting pin number of the bank.
+ * @nr_pins: number of pins included in this bank.
+ * @eint_func: function to set in CON register to configure pin as EINT.
+ * @eint_type: type of the external interrupt supported by the bank.
+ * @eint_mask: bit mask of pins which support EINT function.
+ * @name: name to be prefixed for each pin in this pin bank.
+ * @of_node: OF node of the bank.
+ * @drvdata: link to controller driver data
+ * @irq_domain: IRQ domain of the bank.
+ * @gpio_chip: GPIO chip of the bank.
+ * @grange: linux gpio pin range supported by this bank.
+ * @slock: spinlock protecting bank registers
+ * @pm_save: saved register values during suspend
+ */
+struct samsung_pin_bank {
+	struct samsung_pin_bank_type *type;
+	u32		pctl_offset;
+	u32		pin_base;
+	u8		nr_pins;
+	u8		eint_func;
+	enum eint_type	eint_type;
+	u32		eint_mask;
+	u32		eint_offset;
+	char		*name;
+	void		*soc_priv;
+	struct device_node *of_node;
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *irq_domain;
+	struct gpio_chip gpio_chip;
+	struct pinctrl_gpio_range grange;
+	spinlock_t slock;
+
+	u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
+};
+
+/**
+ * struct samsung_pin_ctrl: represent a pin controller.
+ * @pin_banks: list of pin banks included in this controller.
+ * @nr_banks: number of pin banks.
+ * @base: starting system wide pin number.
+ * @nr_pins: number of pins supported by the controller.
+ * @eint_gpio_init: platform specific callback to setup the external gpio
+ *	interrupts for the controller.
+ * @eint_wkup_init: platform specific callback to setup the external wakeup
+ *	interrupts for the controller.
+ * @label: for debug information.
+ */
+struct samsung_pin_ctrl {
+	struct samsung_pin_bank	*pin_banks;
+	u32		nr_banks;
+
+	u32		base;
+	u32		nr_pins;
+
+	int		(*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
+	int		(*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
+	void		(*suspend)(struct samsung_pinctrl_drv_data *);
+	void		(*resume)(struct samsung_pinctrl_drv_data *);
+
+	char		*label;
+};
+
+/**
+ * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
+ * @node: global list node
+ * @virt_base: register base address of the controller.
+ * @dev: device instance representing the controller.
+ * @irq: interrpt number used by the controller to notify gpio interrupts.
+ * @ctrl: pin controller instance managed by the driver.
+ * @pctl: pin controller descriptor registered with the pinctrl subsystem.
+ * @pctl_dev: cookie representing pinctrl device instance.
+ * @pin_groups: list of pin groups available to the driver.
+ * @nr_groups: number of such pin groups.
+ * @pmx_functions: list of pin functions available to the driver.
+ * @nr_function: number of such pin functions.
+ */
+struct samsung_pinctrl_drv_data {
+	struct list_head		node;
+	void __iomem			*virt_base;
+	struct device			*dev;
+	int				irq;
+
+	struct samsung_pin_ctrl		*ctrl;
+	struct pinctrl_desc		pctl;
+	struct pinctrl_dev		*pctl_dev;
+
+	const struct samsung_pin_group	*pin_groups;
+	unsigned int			nr_groups;
+	const struct samsung_pmx_func	*pmx_functions;
+	unsigned int			nr_functions;
+};
+
+/**
+ * struct samsung_pin_group: represent group of pins of a pinmux function.
+ * @name: name of the pin group, used to lookup the group.
+ * @pins: the pins included in this group.
+ * @num_pins: number of pins included in this group.
+ * @func: the function number to be programmed when selected.
+ */
+struct samsung_pin_group {
+	const char		*name;
+	const unsigned int	*pins;
+	u8			num_pins;
+	u8			func;
+};
+
+/**
+ * struct samsung_pmx_func: represent a pin function.
+ * @name: name of the pin function, used to lookup the function.
+ * @groups: one or more names of pin groups that provide this function.
+ * @num_groups: number of groups included in @groups.
+ */
+struct samsung_pmx_func {
+	const char		*name;
+	const char		**groups;
+	u8			num_groups;
+	u32			val;
+};
+
+/* list of all exported SoC specific data */
+extern struct samsung_pin_ctrl exynos3250_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5260_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5420_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c2412_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c2416_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c2440_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c2450_pin_ctrl[];
+extern struct samsung_pin_ctrl s5pv210_pin_ctrl[];
+
+#endif /* __PINCTRL_SAMSUNG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/gpio.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/gpio.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -409,11 +409,8 @@ int sh_pfc_register_gpiochip(struct sh_p
 
 int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc)
 {
-	int err;
-	int ret;
-
-	ret = gpiochip_remove(&pfc->gpio->gpio_chip);
-	err = gpiochip_remove(&pfc->func->gpio_chip);
+	gpiochip_remove(&pfc->gpio->gpio_chip);
+	gpiochip_remove(&pfc->func->gpio_chip);
 
-	return ret < 0 ? ret : err;
+	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pfc-r8a7791.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pfc-r8a7791.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pfc-r8a7791.c	2014-09-28 17:29:07.000000000 -0400
@@ -1726,6 +1726,133 @@ static const unsigned int audio_clkout_m
 	AUDIO_CLKOUT_MARK,
 };
 
+/* - CAN -------------------------------------------------------------------- */
+
+static const unsigned int can0_data_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 29),
+};
+
+static const unsigned int can0_data_mux[] = {
+	CAN0_TX_MARK, CAN0_RX_MARK,
+};
+
+static const unsigned int can0_data_b_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(7, 4), RCAR_GP_PIN(7, 3),
+};
+
+static const unsigned int can0_data_b_mux[] = {
+	CAN0_TX_B_MARK, CAN0_RX_B_MARK,
+};
+
+static const unsigned int can0_data_c_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 18),
+};
+
+static const unsigned int can0_data_c_mux[] = {
+	CAN0_TX_C_MARK,	CAN0_RX_C_MARK,
+};
+
+static const unsigned int can0_data_d_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 27),
+};
+
+static const unsigned int can0_data_d_mux[] = {
+	CAN0_TX_D_MARK, CAN0_RX_D_MARK,
+};
+
+static const unsigned int can0_data_e_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(4, 18), RCAR_GP_PIN(4, 28),
+};
+
+static const unsigned int can0_data_e_mux[] = {
+	CAN0_TX_E_MARK, CAN0_RX_E_MARK,
+};
+
+static const unsigned int can0_data_f_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+};
+
+static const unsigned int can0_data_f_mux[] = {
+	CAN0_TX_F_MARK, CAN0_RX_F_MARK,
+};
+
+static const unsigned int can1_data_pins[] = {
+	/* TX, RX */
+	 RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 20),
+};
+
+static const unsigned int can1_data_mux[] = {
+	CAN1_TX_MARK, CAN1_RX_MARK,
+};
+
+static const unsigned int can1_data_b_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(7, 8), RCAR_GP_PIN(7, 9),
+};
+
+static const unsigned int can1_data_b_mux[] = {
+	CAN1_TX_B_MARK, CAN1_RX_B_MARK,
+};
+
+static const unsigned int can1_data_c_pins[] = {
+	/* TX, RX */
+	RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 19),
+};
+
+static const unsigned int can1_data_c_mux[] = {
+	CAN1_TX_C_MARK, CAN1_RX_C_MARK,
+};
+
+static const unsigned int can1_data_d_pins[] = {
+	/* TX, RX */
+	 RCAR_GP_PIN(4, 29), RCAR_GP_PIN(4, 31),
+};
+
+static const unsigned int can1_data_d_mux[] = {
+	CAN1_TX_D_MARK, CAN1_RX_D_MARK,
+};
+
+static const unsigned int can_clk_pins[] = {
+	/* CLK */
+	RCAR_GP_PIN(7, 2),
+};
+
+static const unsigned int can_clk_mux[] = {
+	CAN_CLK_MARK,
+};
+
+static const unsigned int can_clk_b_pins[] = {
+	/* CLK */
+	RCAR_GP_PIN(5, 21),
+};
+
+static const unsigned int can_clk_b_mux[] = {
+	CAN_CLK_B_MARK,
+};
+
+static const unsigned int can_clk_c_pins[] = {
+	/* CLK */
+	RCAR_GP_PIN(4, 30),
+};
+
+static const unsigned int can_clk_c_mux[] = {
+	CAN_CLK_C_MARK,
+};
+
+static const unsigned int can_clk_d_pins[] = {
+	/* CLK */
+	RCAR_GP_PIN(7, 19),
+};
+
+static const unsigned int can_clk_d_mux[] = {
+	CAN_CLK_D_MARK,
+};
 
 /* - DU --------------------------------------------------------------------- */
 static const unsigned int du_rgb666_pins[] = {
@@ -1867,6 +1994,192 @@ static const unsigned int eth_rmii_mux[]
 	ETH_RXD0_MARK, ETH_RXD1_MARK, ETH_RX_ER_MARK, ETH_CRS_DV_MARK,
 	ETH_TXD0_MARK, ETH_TXD1_MARK, ETH_TX_EN_MARK, ETH_REFCLK_MARK,
 };
+
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(7, 3), RCAR_GP_PIN(7, 4),
+};
+static const unsigned int hscif0_data_mux[] = {
+	HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 2),
+};
+static const unsigned int hscif0_clk_mux[] = {
+	HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(7, 1), RCAR_GP_PIN(7, 0),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+	HRTS0_N_MARK, HCTS0_N_MARK,
+};
+static const unsigned int hscif0_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int hscif0_data_b_mux[] = {
+	HRX0_B_MARK, HTX0_B_MARK,
+};
+static const unsigned int hscif0_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int hscif0_ctrl_b_mux[] = {
+	HRTS0_N_B_MARK, HCTS0_N_B_MARK,
+};
+static const unsigned int hscif0_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int hscif0_data_c_mux[] = {
+	HRX0_C_MARK, HTX0_C_MARK,
+};
+static const unsigned int hscif0_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif0_clk_c_mux[] = {
+	HSCK0_C_MARK,
+};
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(7, 5), RCAR_GP_PIN(7, 6),
+};
+static const unsigned int hscif1_data_mux[] = {
+	HRX1_MARK, HTX1_MARK,
+};
+static const unsigned int hscif1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 7),
+};
+static const unsigned int hscif1_clk_mux[] = {
+	HSCK1_MARK,
+};
+static const unsigned int hscif1_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(7, 9), RCAR_GP_PIN(7, 8),
+};
+static const unsigned int hscif1_ctrl_mux[] = {
+	HRTS1_N_MARK, HCTS1_N_MARK,
+};
+static const unsigned int hscif1_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 18),
+};
+static const unsigned int hscif1_data_b_mux[] = {
+	HRX1_B_MARK, HTX1_B_MARK,
+};
+static const unsigned int hscif1_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(7, 14), RCAR_GP_PIN(7, 15),
+};
+static const unsigned int hscif1_data_c_mux[] = {
+	HRX1_C_MARK, HTX1_C_MARK,
+};
+static const unsigned int hscif1_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 16),
+};
+static const unsigned int hscif1_clk_c_mux[] = {
+	HSCK1_C_MARK,
+};
+static const unsigned int hscif1_ctrl_c_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(7, 18), RCAR_GP_PIN(7, 17),
+};
+static const unsigned int hscif1_ctrl_c_mux[] = {
+	HRTS1_N_C_MARK, HCTS1_N_C_MARK,
+};
+static const unsigned int hscif1_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 18),
+};
+static const unsigned int hscif1_data_d_mux[] = {
+	HRX1_D_MARK, HTX1_D_MARK,
+};
+static const unsigned int hscif1_data_e_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(7, 14), RCAR_GP_PIN(7, 15),
+};
+static const unsigned int hscif1_data_e_mux[] = {
+	HRX1_C_MARK, HTX1_C_MARK,
+};
+static const unsigned int hscif1_clk_e_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(2, 6),
+};
+static const unsigned int hscif1_clk_e_mux[] = {
+	HSCK1_E_MARK,
+};
+static const unsigned int hscif1_ctrl_e_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 7),
+};
+static const unsigned int hscif1_ctrl_e_mux[] = {
+	HRTS1_N_E_MARK, HCTS1_N_E_MARK,
+};
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 16), RCAR_GP_PIN(4, 17),
+};
+static const unsigned int hscif2_data_mux[] = {
+	HRX2_MARK, HTX2_MARK,
+};
+static const unsigned int hscif2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 15),
+};
+static const unsigned int hscif2_clk_mux[] = {
+	HSCK2_MARK,
+};
+static const unsigned int hscif2_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13),
+};
+static const unsigned int hscif2_ctrl_mux[] = {
+	HRTS2_N_MARK, HCTS2_N_MARK,
+};
+static const unsigned int hscif2_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(1, 20), RCAR_GP_PIN(1, 22),
+};
+static const unsigned int hscif2_data_b_mux[] = {
+	HRX2_B_MARK, HTX2_B_MARK,
+};
+static const unsigned int hscif2_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 21),
+};
+static const unsigned int hscif2_ctrl_b_mux[] = {
+	HRTS2_N_B_MARK, HCTS2_N_B_MARK,
+};
+static const unsigned int hscif2_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int hscif2_data_c_mux[] = {
+	HRX2_C_MARK, HTX2_C_MARK,
+};
+static const unsigned int hscif2_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif2_clk_c_mux[] = {
+	HSCK2_C_MARK,
+};
+static const unsigned int hscif2_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(1, 20), RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif2_data_d_mux[] = {
+	HRX2_B_MARK, HTX2_D_MARK,
+};
 /* - I2C0 ------------------------------------------------------------------- */
 static const unsigned int i2c0_pins[] = {
 	/* SCL, SDA */
@@ -3869,6 +4182,20 @@ static const struct sh_pfc_pin_group pin
 	SH_PFC_PIN_GROUP(audio_clk_b_b),
 	SH_PFC_PIN_GROUP(audio_clk_c),
 	SH_PFC_PIN_GROUP(audio_clkout),
+	SH_PFC_PIN_GROUP(can0_data),
+	SH_PFC_PIN_GROUP(can0_data_b),
+	SH_PFC_PIN_GROUP(can0_data_c),
+	SH_PFC_PIN_GROUP(can0_data_d),
+	SH_PFC_PIN_GROUP(can0_data_e),
+	SH_PFC_PIN_GROUP(can0_data_f),
+	SH_PFC_PIN_GROUP(can1_data),
+	SH_PFC_PIN_GROUP(can1_data_b),
+	SH_PFC_PIN_GROUP(can1_data_c),
+	SH_PFC_PIN_GROUP(can1_data_d),
+	SH_PFC_PIN_GROUP(can_clk),
+	SH_PFC_PIN_GROUP(can_clk_b),
+	SH_PFC_PIN_GROUP(can_clk_c),
+	SH_PFC_PIN_GROUP(can_clk_d),
 	SH_PFC_PIN_GROUP(du_rgb666),
 	SH_PFC_PIN_GROUP(du_rgb888),
 	SH_PFC_PIN_GROUP(du_clk_out_0),
@@ -3885,6 +4212,32 @@ static const struct sh_pfc_pin_group pin
 	SH_PFC_PIN_GROUP(eth_magic),
 	SH_PFC_PIN_GROUP(eth_mdio),
 	SH_PFC_PIN_GROUP(eth_rmii),
+	SH_PFC_PIN_GROUP(hscif0_data),
+	SH_PFC_PIN_GROUP(hscif0_clk),
+	SH_PFC_PIN_GROUP(hscif0_ctrl),
+	SH_PFC_PIN_GROUP(hscif0_data_b),
+	SH_PFC_PIN_GROUP(hscif0_ctrl_b),
+	SH_PFC_PIN_GROUP(hscif0_data_c),
+	SH_PFC_PIN_GROUP(hscif0_clk_c),
+	SH_PFC_PIN_GROUP(hscif1_data),
+	SH_PFC_PIN_GROUP(hscif1_clk),
+	SH_PFC_PIN_GROUP(hscif1_ctrl),
+	SH_PFC_PIN_GROUP(hscif1_data_b),
+	SH_PFC_PIN_GROUP(hscif1_data_c),
+	SH_PFC_PIN_GROUP(hscif1_clk_c),
+	SH_PFC_PIN_GROUP(hscif1_ctrl_c),
+	SH_PFC_PIN_GROUP(hscif1_data_d),
+	SH_PFC_PIN_GROUP(hscif1_data_e),
+	SH_PFC_PIN_GROUP(hscif1_clk_e),
+	SH_PFC_PIN_GROUP(hscif1_ctrl_e),
+	SH_PFC_PIN_GROUP(hscif2_data),
+	SH_PFC_PIN_GROUP(hscif2_clk),
+	SH_PFC_PIN_GROUP(hscif2_ctrl),
+	SH_PFC_PIN_GROUP(hscif2_data_b),
+	SH_PFC_PIN_GROUP(hscif2_ctrl_b),
+	SH_PFC_PIN_GROUP(hscif2_data_c),
+	SH_PFC_PIN_GROUP(hscif2_clk_c),
+	SH_PFC_PIN_GROUP(hscif2_data_d),
 	SH_PFC_PIN_GROUP(i2c0),
 	SH_PFC_PIN_GROUP(i2c0_b),
 	SH_PFC_PIN_GROUP(i2c0_c),
@@ -4155,6 +4508,30 @@ static const char * const audio_clk_grou
 	"audio_clkout",
 };
 
+static const char * const can0_groups[] = {
+	"can0_data",
+	"can0_data_b",
+	"can0_data_c",
+	"can0_data_d",
+	"can0_data_e",
+	"can0_data_f",
+	"can_clk",
+	"can_clk_b",
+	"can_clk_c",
+	"can_clk_d",
+};
+
+static const char * const can1_groups[] = {
+	"can1_data",
+	"can1_data_b",
+	"can1_data_c",
+	"can1_data_d",
+	"can_clk",
+	"can_clk_b",
+	"can_clk_c",
+	"can_clk_d",
+};
+
 static const char * const du_groups[] = {
 	"du_rgb666",
 	"du_rgb888",
@@ -4183,6 +4560,41 @@ static const char * const eth_groups[] =
 	"eth_rmii",
 };
 
+static const char * const hscif0_groups[] = {
+	"hscif0_data",
+	"hscif0_clk",
+	"hscif0_ctrl",
+	"hscif0_data_b",
+	"hscif0_ctrl_b",
+	"hscif0_data_c",
+	"hscif0_clk_c",
+};
+
+static const char * const hscif1_groups[] = {
+	"hscif1_data",
+	"hscif1_clk",
+	"hscif1_ctrl",
+	"hscif1_data_b",
+	"hscif1_data_c",
+	"hscif1_clk_c",
+	"hscif1_ctrl_c",
+	"hscif1_data_d",
+	"hscif1_data_e",
+	"hscif1_clk_e",
+	"hscif1_ctrl_e",
+};
+
+static const char * const hscif2_groups[] = {
+	"hscif2_data",
+	"hscif2_clk",
+	"hscif2_ctrl",
+	"hscif2_data_b",
+	"hscif2_ctrl_b",
+	"hscif2_data_c",
+	"hscif2_clk_c",
+	"hscif2_data_d",
+};
+
 static const char * const i2c0_groups[] = {
 	"i2c0",
 	"i2c0_b",
@@ -4543,10 +4955,15 @@ static const char * const vin2_groups[]
 
 static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(audio_clk),
+	SH_PFC_FUNCTION(can0),
+	SH_PFC_FUNCTION(can1),
 	SH_PFC_FUNCTION(du),
 	SH_PFC_FUNCTION(du0),
 	SH_PFC_FUNCTION(du1),
 	SH_PFC_FUNCTION(eth),
+	SH_PFC_FUNCTION(hscif0),
+	SH_PFC_FUNCTION(hscif1),
+	SH_PFC_FUNCTION(hscif2),
 	SH_PFC_FUNCTION(i2c0),
 	SH_PFC_FUNCTION(i2c1),
 	SH_PFC_FUNCTION(i2c2),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pfc-sh73a0.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pfc-sh73a0.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pfc-sh73a0.c	2014-09-28 17:29:07.000000000 -0400
@@ -3842,7 +3842,8 @@ static int sh73a0_pinmux_soc_init(struct
 	cfg.init_data = &sh73a0_vccq_mc0_init_data;
 	cfg.driver_data = pfc;
 
-	data->vccq_mc0 = regulator_register(&sh73a0_vccq_mc0_desc, &cfg);
+	data->vccq_mc0 = devm_regulator_register(pfc->dev,
+						 &sh73a0_vccq_mc0_desc, &cfg);
 	if (IS_ERR(data->vccq_mc0)) {
 		ret = PTR_ERR(data->vccq_mc0);
 		dev_err(pfc->dev, "Failed to register VCCQ MC0 regulator: %d\n",
@@ -3855,16 +3856,8 @@ static int sh73a0_pinmux_soc_init(struct
 	return 0;
 }
 
-static void sh73a0_pinmux_soc_exit(struct sh_pfc *pfc)
-{
-	struct sh73a0_pinmux_data *data = pfc->soc_data;
-
-	regulator_unregister(data->vccq_mc0);
-}
-
 static const struct sh_pfc_soc_operations sh73a0_pinmux_ops = {
 	.init = sh73a0_pinmux_soc_init,
-	.exit = sh73a0_pinmux_soc_exit,
 	.get_bias = sh73a0_pinmux_get_bias,
 	.set_bias = sh73a0_pinmux_set_bias,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pinctrl.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pinctrl.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sh-pfc/pinctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sh-pfc/pinctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -345,27 +345,6 @@ done:
 	return ret;
 }
 
-static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector,
-				unsigned group)
-{
-	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
-	struct sh_pfc *pfc = pmx->pfc;
-	const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
-	unsigned long flags;
-	unsigned int i;
-
-	spin_lock_irqsave(&pfc->lock, flags);
-
-	for (i = 0; i < grp->nr_pins; ++i) {
-		int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
-		struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
-
-		cfg->type = PINMUX_TYPE_NONE;
-	}
-
-	spin_unlock_irqrestore(&pfc->lock, flags);
-}
-
 static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
 				      struct pinctrl_gpio_range *range,
 				      unsigned offset)
@@ -464,7 +443,6 @@ static const struct pinmux_ops sh_pfc_pi
 	.get_function_name	= sh_pfc_get_function_name,
 	.get_function_groups	= sh_pfc_get_function_groups,
 	.enable			= sh_pfc_func_enable,
-	.disable		= sh_pfc_func_disable,
 	.gpio_request_enable	= sh_pfc_gpio_request_enable,
 	.gpio_disable_free	= sh_pfc_gpio_disable_free,
 	.gpio_set_direction	= sh_pfc_gpio_set_direction,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sirf/pinctrl-sirf.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sirf/pinctrl-sirf.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sirf/pinctrl-sirf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sirf/pinctrl-sirf.c	2014-09-28 17:29:07.000000000 -0400
@@ -186,15 +186,6 @@ static int sirfsoc_pinmux_enable(struct
 	return 0;
 }
 
-static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector,
-	unsigned group)
-{
-	struct sirfsoc_pmx *spmx;
-
-	spmx = pinctrl_dev_get_drvdata(pmxdev);
-	sirfsoc_pinmux_endisable(spmx, selector, false);
-}
-
 static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
 {
 	return sirfsoc_pmxfunc_cnt;
@@ -240,7 +231,6 @@ static int sirfsoc_pinmux_request_gpio(s
 
 static struct pinmux_ops sirfsoc_pinmux_ops = {
 	.enable = sirfsoc_pinmux_enable,
-	.disable = sirfsoc_pinmux_disable,
 	.get_functions_count = sirfsoc_pinmux_get_funcs_count,
 	.get_function_name = sirfsoc_pinmux_get_func_name,
 	.get_function_groups = sirfsoc_pinmux_get_groups,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/spear/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/spear/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,7 @@ config PINCTRL_SPEAR1340
 config PINCTRL_SPEAR_PLGPIO
 	bool "SPEAr SoC PLGPIO Controller"
 	depends on GPIOLIB && PINCTRL_SPEAR
+	select GPIOLIB_IRQCHIP
 	help
 	  Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
 	  SoCs.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/spear/pinctrl-plgpio.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/pinctrl-plgpio.c
--- linux-libre-3.16-gnu/drivers/pinctrl/spear/pinctrl-plgpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/pinctrl-plgpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,12 +11,11 @@
 
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
@@ -54,7 +53,6 @@ struct plgpio_regs {
  *
  * lock: lock for guarding gpio registers
  * base: base address of plgpio block
- * irq_base: irq number of plgpio0
  * chip: gpio framework specific chip information structure
  * p2o: function ptr for pin to offset conversion. This is required only for
  *	machines where mapping b/w pin and offset is not 1-to-1.
@@ -68,8 +66,6 @@ struct plgpio {
 	spinlock_t		lock;
 	void __iomem		*base;
 	struct clk		*clk;
-	unsigned		irq_base;
-	struct irq_domain	*irq_domain;
 	struct gpio_chip	chip;
 	int			(*p2o)(int pin);	/* pin_to_offset */
 	int			(*o2p)(int offset);	/* offset_to_pin */
@@ -280,21 +276,12 @@ disable_clk:
 	pinctrl_free_gpio(gpio);
 }
 
-static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
-
-	if (IS_ERR_VALUE(plgpio->irq_base))
-		return -EINVAL;
-
-	return irq_find_mapping(plgpio->irq_domain, offset);
-}
-
 /* PLGPIO IRQ */
 static void plgpio_irq_disable(struct irq_data *d)
 {
-	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - plgpio->irq_base;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+	int offset = d->hwirq;
 	unsigned long flags;
 
 	/* get correct offset for "offset" pin */
@@ -311,8 +298,9 @@ static void plgpio_irq_disable(struct ir
 
 static void plgpio_irq_enable(struct irq_data *d)
 {
-	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - plgpio->irq_base;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+	int offset = d->hwirq;
 	unsigned long flags;
 
 	/* get correct offset for "offset" pin */
@@ -329,8 +317,9 @@ static void plgpio_irq_enable(struct irq
 
 static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
 {
-	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - plgpio->irq_base;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+	int offset = d->hwirq;
 	void __iomem *reg_off;
 	unsigned int supported_type = 0, val;
 
@@ -369,7 +358,8 @@ static struct irq_chip plgpio_irqchip =
 
 static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct plgpio *plgpio = irq_get_handler_data(irq);
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
 	int regs_count, count, pin, offset, i = 0;
 	unsigned long pending;
@@ -410,7 +400,8 @@ static void plgpio_irq_handler(unsigned
 
 			/* get correct irq line number */
 			pin = i * MAX_GPIO_PER_REG + pin;
-			generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+			generic_handle_irq(
+				irq_find_mapping(gc->irqdomain, pin));
 		}
 	}
 	chained_irq_exit(irqchip, desc);
@@ -523,10 +514,9 @@ end:
 }
 static int plgpio_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
 	struct plgpio *plgpio;
 	struct resource *res;
-	int ret, irq, i;
+	int ret, irq;
 
 	plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
 	if (!plgpio) {
@@ -563,7 +553,6 @@ static int plgpio_probe(struct platform_
 	platform_set_drvdata(pdev, plgpio);
 	spin_lock_init(&plgpio->lock);
 
-	plgpio->irq_base = -1;
 	plgpio->chip.base = -1;
 	plgpio->chip.request = plgpio_request;
 	plgpio->chip.free = plgpio_free;
@@ -571,10 +560,10 @@ static int plgpio_probe(struct platform_
 	plgpio->chip.direction_output = plgpio_direction_output;
 	plgpio->chip.get = plgpio_get_value;
 	plgpio->chip.set = plgpio_set_value;
-	plgpio->chip.to_irq = plgpio_to_irq;
 	plgpio->chip.label = dev_name(&pdev->dev);
 	plgpio->chip.dev = &pdev->dev;
 	plgpio->chip.owner = THIS_MODULE;
+	plgpio->chip.of_node = pdev->dev.of_node;
 
 	if (!IS_ERR(plgpio->clk)) {
 		ret = clk_prepare(plgpio->clk);
@@ -592,43 +581,32 @@ static int plgpio_probe(struct platform_
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_info(&pdev->dev, "irqs not supported\n");
-		return 0;
-	}
-
-	plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
-	if (IS_ERR_VALUE(plgpio->irq_base)) {
-		/* we would not support irq for gpio */
-		dev_warn(&pdev->dev, "couldn't allocate irq base\n");
+		dev_info(&pdev->dev, "PLGPIO registered without IRQs\n");
 		return 0;
 	}
 
-	plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
-			plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
-	if (WARN_ON(!plgpio->irq_domain)) {
-		dev_err(&pdev->dev, "irq domain init failed\n");
-		irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
-		ret = -ENXIO;
+	ret = gpiochip_irqchip_add(&plgpio->chip,
+				   &plgpio_irqchip,
+				   0,
+				   handle_simple_irq,
+				   IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add irqchip to gpiochip\n");
 		goto remove_gpiochip;
 	}
 
-	irq_set_chained_handler(irq, plgpio_irq_handler);
-	for (i = 0; i < plgpio->chip.ngpio; i++) {
-		irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
-				handle_simple_irq);
-		set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
-		irq_set_chip_data(i + plgpio->irq_base, plgpio);
-	}
+	gpiochip_set_chained_irqchip(&plgpio->chip,
+				     &plgpio_irqchip,
+				     irq,
+				     plgpio_irq_handler);
 
-	irq_set_handler_data(irq, plgpio);
 	dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
 
 	return 0;
 
 remove_gpiochip:
 	dev_info(&pdev->dev, "Remove gpiochip\n");
-	if (gpiochip_remove(&plgpio->chip))
-		dev_err(&pdev->dev, "unable to remove gpiochip\n");
+	gpiochip_remove(&plgpio->chip);
 unprepare_clk:
 	if (!IS_ERR(plgpio->clk))
 		clk_unprepare(plgpio->clk);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/spear/pinctrl-spear.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/pinctrl-spear.c
--- linux-libre-3.16-gnu/drivers/pinctrl/spear/pinctrl-spear.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/spear/pinctrl-spear.c	2014-09-28 17:29:07.000000000 -0400
@@ -274,12 +274,6 @@ static int spear_pinctrl_enable(struct p
 	return spear_pinctrl_endisable(pctldev, function, group, true);
 }
 
-static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
-		unsigned function, unsigned group)
-{
-	spear_pinctrl_endisable(pctldev, function, group, false);
-}
-
 /* gpio with pinmux */
 static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
 		unsigned pin)
@@ -345,7 +339,6 @@ static const struct pinmux_ops spear_pin
 	.get_function_name = spear_pinctrl_get_func_name,
 	.get_function_groups = spear_pinctrl_get_func_groups,
 	.enable = spear_pinctrl_enable,
-	.disable = spear_pinctrl_disable,
 	.gpio_request_enable = gpio_request_enable,
 	.gpio_disable_free = gpio_disable_free,
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/Kconfig linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/Kconfig
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,36 +1,42 @@
 if ARCH_SUNXI
 
-config PINCTRL_SUNXI
-	bool
-
 config PINCTRL_SUNXI_COMMON
 	bool
 	select PINMUX
 	select GENERIC_PINCONF
 
 config PINCTRL_SUN4I_A10
-	def_bool PINCTRL_SUNXI || MACH_SUN4I
+	def_bool MACH_SUN4I
 	select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN5I_A10S
-	def_bool PINCTRL_SUNXI || MACH_SUN5I
+	def_bool MACH_SUN5I
 	select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN5I_A13
-	def_bool PINCTRL_SUNXI || MACH_SUN5I
+	def_bool MACH_SUN5I
 	select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN6I_A31
-	def_bool PINCTRL_SUNXI || MACH_SUN6I
+	def_bool MACH_SUN6I
 	select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN6I_A31_R
-	def_bool PINCTRL_SUNXI || MACH_SUN6I
+	def_bool MACH_SUN6I
 	depends on RESET_CONTROLLER
 	select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN7I_A20
-	def_bool PINCTRL_SUNXI || MACH_SUN7I
+	def_bool MACH_SUN7I
+	select PINCTRL_SUNXI_COMMON
+
+config PINCTRL_SUN8I_A23
+	def_bool MACH_SUN8I
+	select PINCTRL_SUNXI_COMMON
+
+config PINCTRL_SUN8I_A23_R
+	def_bool MACH_SUN8I
+	depends on RESET_CONTROLLER
 	select PINCTRL_SUNXI_COMMON
 
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/Makefile linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/Makefile
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,3 +8,5 @@ obj-$(CONFIG_PINCTRL_SUN5I_A13)		+= pinc
 obj-$(CONFIG_PINCTRL_SUN6I_A31)		+= pinctrl-sun6i-a31.o
 obj-$(CONFIG_PINCTRL_SUN6I_A31_R)	+= pinctrl-sun6i-a31-r.o
 obj-$(CONFIG_PINCTRL_SUN7I_A20)		+= pinctrl-sun7i-a20.o
+obj-$(CONFIG_PINCTRL_SUN8I_A23)		+= pinctrl-sun8i-a23.o
+obj-$(CONFIG_PINCTRL_SUN8I_A23_R)	+= pinctrl-sun8i-a23-r.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c	2014-09-28 17:29:07.000000000 -0400
@@ -1010,6 +1010,7 @@ static const struct sunxi_desc_pin sun4i
 static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
 	.pins = sun4i_a10_pins,
 	.npins = ARRAY_SIZE(sun4i_a10_pins),
+	.irq_banks = 1,
 };
 
 static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c	2014-09-28 17:29:07.000000000 -0400
@@ -661,6 +661,7 @@ static const struct sunxi_desc_pin sun5i
 static const struct sunxi_pinctrl_desc sun5i_a10s_pinctrl_data = {
 	.pins = sun5i_a10s_pins,
 	.npins = ARRAY_SIZE(sun5i_a10s_pins),
+	.irq_banks = 1,
 };
 
 static int sun5i_a10s_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c	2014-09-28 17:29:07.000000000 -0400
@@ -330,15 +330,12 @@ static const struct sunxi_desc_pin sun5i
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
-		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION_IRQ(0x6, 0)),		/* EINT0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
-		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION_IRQ(0x6, 1)),		/* EINT1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
-		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION_IRQ(0x6, 2)),		/* EINT2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -382,6 +379,7 @@ static const struct sunxi_desc_pin sun5i
 static const struct sunxi_pinctrl_desc sun5i_a13_pinctrl_data = {
 	.pins = sun5i_a13_pins,
 	.npins = ARRAY_SIZE(sun5i_a13_pins),
+	.irq_banks = 1,
 };
 
 static int sun5i_a13_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,208 +24,244 @@ static const struct sunxi_desc_pin sun6i
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD0 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D0 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* DTR */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* DTR */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),	/* PA_EINT0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD1 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D1 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* DSR */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* DSR */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),	/* PA_EINT1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD2 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D2 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* DCD */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* DCD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),	/* PA_EINT2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD3 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D3 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* RING */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* RING */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),	/* PA_EINT3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD4 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D4 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* TX */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),	/* PA_EINT4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD5 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D5 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* RX */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),	/* PA_EINT5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD6 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D6 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* RTS */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),	/* PA_EINT6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXD7 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D7 */
-		  SUNXI_FUNCTION(0x4, "uart1")),	/* CTS */
+		  SUNXI_FUNCTION(0x4, "uart1"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),	/* PA_EINT7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXCLK */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* D8 */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D8 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),	/* PA_EINT8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXEN */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D9 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* CMD */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* CMD */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),	/* PA_EINT9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* GTXCLK */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D10 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* CLK */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* CLK */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)),	/* PA_EINT10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD0 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D11 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* D0 */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* D0 */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)),	/* PA_EINT11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD1 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D12 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* D1 */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* D1 */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)),	/* PA_EINT12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD2 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D13 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* D2 */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* D2 */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)),	/* PA_EINT13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD3 */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D14 */
 		  SUNXI_FUNCTION(0x4, "mmc3"),		/* D3 */
-		  SUNXI_FUNCTION(0x5, "mmc2")),		/* D3 */
+		  SUNXI_FUNCTION(0x5, "mmc2"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)),	/* PA_EINT14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD4 */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* D15 */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D15 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)),	/* PA_EINT15 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD5 */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* D16 */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D16 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)),	/* PA_EINT16 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD6 */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* D17 */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D17 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)),	/* PA_EINT17 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXD7 */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* D18 */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D18 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)),	/* PA_EINT18 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXDV */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D19 */
-		  SUNXI_FUNCTION(0x4, "pwm3")),		/* Positive */
+		  SUNXI_FUNCTION(0x4, "pwm3"),		/* Positive */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)),	/* PA_EINT19 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXCLK */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D20 */
-		  SUNXI_FUNCTION(0x4, "pwm3")),		/* Negative */
+		  SUNXI_FUNCTION(0x4, "pwm3"),		/* Negative */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)),	/* PA_EINT20 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* TXERR */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D21 */
-		  SUNXI_FUNCTION(0x4, "spi3")),		/* CS0 */
+		  SUNXI_FUNCTION(0x4, "spi3"),		/* CS0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)),	/* PA_EINT21 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 22),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* RXERR */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D22 */
-		  SUNXI_FUNCTION(0x4, "spi3")),		/* CLK */
+		  SUNXI_FUNCTION(0x4, "spi3"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 22)),	/* PA_EINT22 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 23),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* COL */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* D23 */
-		  SUNXI_FUNCTION(0x4, "spi3")),		/* MOSI */
+		  SUNXI_FUNCTION(0x4, "spi3"),		/* MOSI */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 23)),	/* PA_EINT23 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 24),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* CRS */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* CLK */
-		  SUNXI_FUNCTION(0x4, "spi3")),		/* MISO */
+		  SUNXI_FUNCTION(0x4, "spi3"),		/* MISO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 24)),	/* PA_EINT24 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 25),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* CLKIN */
 		  SUNXI_FUNCTION(0x3, "lcd1"),		/* DE */
-		  SUNXI_FUNCTION(0x4, "spi3")),		/* CS1 */
+		  SUNXI_FUNCTION(0x4, "spi3"),		/* CS1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 25)),	/* PA_EINT25 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 26),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* MDC */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* HSYNC */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* HSYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 26)),	/* PA_EINT26 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 27),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "gmac"),		/* MDIO */
-		  SUNXI_FUNCTION(0x3, "lcd1")),		/* VSYNC */
+		  SUNXI_FUNCTION(0x3, "lcd1"),		/* VSYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 27)),	/* PA_EINT27 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2s0"),		/* MCLK */
 		  SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
-		  SUNXI_FUNCTION(0x4, "csi")),		/* MCLK1 */
+		  SUNXI_FUNCTION(0x4, "csi"),		/* MCLK1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),	/* PB_EINT0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "i2s0")),		/* BCLK */
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* BCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),	/* PB_EINT1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "i2s0")),		/* LRCK */
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* LRCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),	/* PB_EINT2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "i2s0")),		/* DO0 */
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DO0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),	/* PB_EINT3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DO1 */
-		  SUNXI_FUNCTION(0x3, "uart3")),	/* RTS */
+		  SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),	/* PB_EINT4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DO2 */
 		  SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
-		  SUNXI_FUNCTION(0x4, "i2c3")),		/* SCK */
+		  SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),	/* PB_EINT5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DO3 */
 		  SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
-		  SUNXI_FUNCTION(0x4, "i2c3")),		/* SDA */
+		  SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),	/* PB_EINT6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x3, "i2s0")),		/* DI */
+		  SUNXI_FUNCTION(0x3, "i2s0"),		/* DI */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)),	/* PB_EINT7 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -510,86 +546,103 @@ static const struct sunxi_desc_pin sun6i
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* PCLK */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),	/* PE_EINT0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* MCLK */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* ERR */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* ERR */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),	/* PE_EINT1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* HSYNC */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* SYNC */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* SYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),	/* PE_EINT2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* VSYNC */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* DVLD */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* DVLD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),	/* PE_EINT3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D0 */
-		  SUNXI_FUNCTION(0x3, "uart5")),	/* TX */
+		  SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),	/* PE_EINT4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D1 */
-		  SUNXI_FUNCTION(0x3, "uart5")),	/* RX */
+		  SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),	/* PE_EINT5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D2 */
-		  SUNXI_FUNCTION(0x3, "uart5")),	/* RTS */
+		  SUNXI_FUNCTION(0x3, "uart5"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),	/* PE_EINT6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D3 */
-		  SUNXI_FUNCTION(0x3, "uart5")),	/* CTS */
+		  SUNXI_FUNCTION(0x3, "uart5"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),	/* PE_EINT7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D4 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D0 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),	/* PE_EINT8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D5 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D1 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),	/* PE_EINT9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D6 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D2 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)),	/* PE_EINT10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D7 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D3 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)),	/* PE_EINT11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D8 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D4 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D4 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)),	/* PE_EINT12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D9 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D5 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D5 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)),	/* PE_EINT13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D10 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D6 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D6 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)),	/* PE_EINT14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "csi"),		/* D11 */
-		  SUNXI_FUNCTION(0x3, "ts")),		/* D7 */
+		  SUNXI_FUNCTION(0x3, "ts"),		/* D7 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 15)),	/* PE_EINT15 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "csi")),		/* MIPI CSI MCLK */
+		  SUNXI_FUNCTION(0x2, "csi"),		/* MIPI CSI MCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 16)),	/* PE_EINT16 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -625,86 +678,105 @@ static const struct sunxi_desc_pin sun6i
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* CLK */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)),	/* PG_EINT0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* CMD */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)),	/* PG_EINT1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* D0 */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)),	/* PG_EINT2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* D1 */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)),	/* PG_EINT3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* D2 */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)),	/* PG_EINT4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "mmc1")),		/* D3 */
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)),	/* PG_EINT5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2")),	/* TX */
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)),	/* PG_EINT6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2")),	/* RX */
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)),	/* PG_EINT7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2")),	/* RTS */
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)),	/* PG_EINT8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2")),	/* CTS */
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)),	/* PG_EINT9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2c3"),		/* SCK */
-		  SUNXI_FUNCTION(0x3, "usb")),		/* DP3 */
+		  SUNXI_FUNCTION(0x3, "usb"),		/* DP3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 10)),	/* PG_EINT10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "i2c3"),		/* SDA */
-		  SUNXI_FUNCTION(0x3, "usb")),		/* DM3 */
+		  SUNXI_FUNCTION(0x3, "usb"),		/* DM3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 11)),	/* PG_EINT11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "spi1"),		/* CS1 */
-		  SUNXI_FUNCTION(0x3, "i2s1")),		/* MCLK */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 12)),	/* PG_EINT12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "spi1"),		/* CS0 */
-		  SUNXI_FUNCTION(0x3, "i2s1")),		/* BCLK */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 13)),	/* PG_EINT13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "spi1"),		/* CLK */
-		  SUNXI_FUNCTION(0x3, "i2s1")),		/* LRCK */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* LRCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 14)),	/* PG_EINT14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "spi1"),		/* MOSI */
-		  SUNXI_FUNCTION(0x3, "i2s1")),		/* DIN */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* DIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 15)),	/* PG_EINT15 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "spi1"),		/* MISO */
-		  SUNXI_FUNCTION(0x3, "i2s1")),		/* DOUT */
+		  SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 16)),	/* PG_EINT16 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart4")),	/* TX */
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 17)),	/* PG_EINT17 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart4")),	/* RX */
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 18)),	/* PG_EINT18 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -836,6 +908,7 @@ static const struct sunxi_desc_pin sun6i
 static const struct sunxi_pinctrl_desc sun6i_a31_pinctrl_data = {
 	.pins = sun6i_a31_pins,
 	.npins = ARRAY_SIZE(sun6i_a31_pins),
+	.irq_banks = 4,
 };
 
 static int sun6i_a31_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,6 +93,7 @@ static const struct sunxi_pinctrl_desc s
 	.pins = sun6i_a31_r_pins,
 	.npins = ARRAY_SIZE(sun6i_a31_r_pins),
 	.pin_base = PL_BASE,
+	.irq_banks = 2,
 };
 
 static int sun6i_a31_r_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c	2014-09-28 17:29:07.000000000 -0400
@@ -1036,6 +1036,7 @@ static const struct sunxi_desc_pin sun7i
 static const struct sunxi_pinctrl_desc sun7i_a20_pinctrl_data = {
 	.pins = sun7i_a20_pins,
 	.npins = ARRAY_SIZE(sun7i_a20_pins),
+	.irq_banks = 1,
 };
 
 static int sun7i_a20_pinctrl_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,593 @@
+/*
+ * Allwinner A23 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_a23_pins[] = {
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* CS */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* MS0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 0)),	/* PA_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* CKO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 1)),	/* PA_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* MOSI */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* DOO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 2)),	/* PA_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi1"),		/* MISO */
+		  SUNXI_FUNCTION(0x3, "jtag"),		/* DIO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 3)),	/* PA_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 4)),	/* PA_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 5)),	/* PA_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 6)),	/* PA_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart4"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 7)),	/* PA_EINT7 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)),	/* PB_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)),	/* PB_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)),	/* PB_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)),	/* PB_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* SYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)),	/* PB_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)),	/* PB_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s0"),		/* DIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)),	/* PB_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "i2s0"),		/* DI */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)),	/* PB_EINT7 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* WE */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* MOSI */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* ALE */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* MISO */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CLE */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* CE1 */
+		  SUNXI_FUNCTION(0x3, "spi0")),		/* CS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* CE0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RE */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* RB0 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* CMD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* RB1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ0 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ1 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ2 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ3 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ4 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ5 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
+		  SUNXI_FUNCTION(0x3, "mmc2")),		/* RST */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* CE2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 18),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* CE3 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* CMD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
+		  SUNXI_FUNCTION(0x3, "mmc1")),		/* D3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* TX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* RX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
+		  SUNXI_FUNCTION(0x3, "uart1")),	/* TX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
+		  SUNXI_FUNCTION(0x3, "uart1")),	/* RX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
+		  SUNXI_FUNCTION(0x3, "uart1")),	/* RTS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
+		  SUNXI_FUNCTION(0x3, "uart1")),	/* CTS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
+		  SUNXI_FUNCTION(0x3, "i2s1")),		/* SYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
+		  SUNXI_FUNCTION(0x3, "i2s1")),		/* CLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
+		  SUNXI_FUNCTION(0x3, "i2s1")),		/* DOUT */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
+		  SUNXI_FUNCTION(0x3, "i2s1")),		/* DIN */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VN0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VP0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VP1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VN1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VP2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 23),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VN2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 24),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VPC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 25),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 26),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VP3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 27),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
+		  SUNXI_FUNCTION(0x3, "lvds0")),	/* VN3 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* PCLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* MCLK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* HSYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* VSYNC */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi")),		/* D7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "i2c2")),		/* SCK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "csi"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "i2c2")),		/* SDA */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out")),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out")),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out")),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out")),
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* MS1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* DI1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "uart0")),	/* TX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* DO1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
+		  SUNXI_FUNCTION(0x3, "uart0")),	/* RX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
+		  SUNXI_FUNCTION(0x3, "jtag")),		/* CK1 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 0)),	/* PG_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 1)),	/* PG_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 2)),	/* PG_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 3)),	/* PG_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 4)),	/* PG_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 5)),	/* PG_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 6)),	/* PG_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 7)),	/* PG_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 8)),	/* PG_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 9)),	/* PG_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* SYNC */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 10)),	/* PG_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* CLK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 11)),	/* PG_EINT11 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* DOUT */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 12)),	/* PG_EINT12 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2s1"),		/* DIN */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 13)),	/* PG_EINT13 */
+	/* Hole */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "pwm0")),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "pwm1")),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0")),		/* SCK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c0")),		/* SDA */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1")),		/* SCK */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "i2c1")),		/* SDA */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi0"),		/* CS */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* TX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* RX */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi0"),		/* DOUT */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* RTS */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "spi0"),		/* DIN */
+		  SUNXI_FUNCTION(0x3, "uart3")),	/* CTS */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_a23_pinctrl_data = {
+	.pins = sun8i_a23_pins,
+	.npins = ARRAY_SIZE(sun8i_a23_pins),
+	.irq_banks = 3,
+};
+
+static int sun8i_a23_pinctrl_probe(struct platform_device *pdev)
+{
+	return sunxi_pinctrl_init(pdev,
+				  &sun8i_a23_pinctrl_data);
+}
+
+static struct of_device_id sun8i_a23_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun8i-a23-pinctrl", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match);
+
+static struct platform_driver sun8i_a23_pinctrl_driver = {
+	.probe	= sun8i_a23_pinctrl_probe,
+	.driver	= {
+		.name		= "sun8i-a23-pinctrl",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun8i_a23_pinctrl_match,
+	},
+};
+module_platform_driver(sun8i_a23_pinctrl_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner A23 pinctrl driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,142 @@
+/*
+ * Allwinner A23 SoCs special pins pinctrl driver.
+ *
+ * Copyright (C) 2014 Chen-Yu Tsai
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Copyright (C) 2014 Boris Brezillon
+ * Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_a23_r_pins[] = {
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_rsb"),		/* SCK */
+		  SUNXI_FUNCTION(0x3, "s_twi"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 0)),	/* PL_EINT0 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_rsb"),		/* SDA */
+		  SUNXI_FUNCTION(0x3, "s_twi"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 1)),	/* PL_EINT1 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* TX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 2)),	/* PL_EINT2 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_uart"),	/* RX */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 3)),	/* PL_EINT3 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* MS */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 4)),	/* PL_EINT4 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* CK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 5)),	/* PL_EINT5 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DO */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 6)),	/* PL_EINT6 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x3, "s_jtag"),	/* DI */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 7)),	/* PL_EINT7 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_twi"),		/* SCK */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 8)),	/* PL_EINT8 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_twi"),		/* SDA */
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 9)),	/* PL_EINT9 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION(0x2, "s_pwm"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 10)),	/* PL_EINT10 */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 11),
+		  SUNXI_FUNCTION(0x0, "gpio_in"),
+		  SUNXI_FUNCTION(0x1, "gpio_out"),
+		  SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 11)),	/* PL_EINT11 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_a23_r_pinctrl_data = {
+	.pins = sun8i_a23_r_pins,
+	.npins = ARRAY_SIZE(sun8i_a23_r_pins),
+	.pin_base = PL_BASE,
+	.irq_banks = 1,
+};
+
+static int sun8i_a23_r_pinctrl_probe(struct platform_device *pdev)
+{
+	struct reset_control *rstc;
+	int ret;
+
+	rstc = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		dev_err(&pdev->dev, "Reset controller missing\n");
+		return PTR_ERR(rstc);
+	}
+
+	ret = reset_control_deassert(rstc);
+	if (ret)
+		return ret;
+
+	ret = sunxi_pinctrl_init(pdev,
+				 &sun8i_a23_r_pinctrl_data);
+
+	if (ret)
+		reset_control_assert(rstc);
+
+	return ret;
+}
+
+static struct of_device_id sun8i_a23_r_pinctrl_match[] = {
+	{ .compatible = "allwinner,sun8i-a23-r-pinctrl", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match);
+
+static struct platform_driver sun8i_a23_r_pinctrl_driver = {
+	.probe	= sun8i_a23_r_pinctrl_probe,
+	.driver	= {
+		.name		= "sun8i-a23-r-pinctrl",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun8i_a23_r_pinctrl_match,
+	},
+};
+module_platform_driver(sun8i_a23_r_pinctrl_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner A23 R_PIO pinctrl driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.c
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,9 @@
 #include "../core.h"
 #include "pinctrl-sunxi.h"
 
+static struct irq_chip sunxi_pinctrl_edge_irq_chip;
+static struct irq_chip sunxi_pinctrl_level_irq_chip;
+
 static struct sunxi_pinctrl_group *
 sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
 {
@@ -508,7 +511,7 @@ static int sunxi_pinctrl_gpio_of_xlate(s
 	base = PINS_PER_BANK * gpiospec->args[0];
 	pin = base + gpiospec->args[1];
 
-	if (pin > (gc->base + gc->ngpio))
+	if (pin > gc->ngpio)
 		return -EINVAL;
 
 	if (flags)
@@ -521,25 +524,61 @@ static int sunxi_pinctrl_gpio_to_irq(str
 {
 	struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
 	struct sunxi_desc_function *desc;
+	unsigned pinnum = pctl->desc->pin_base + offset;
+	unsigned irqnum;
 
 	if (offset >= chip->ngpio)
 		return -ENXIO;
 
-	desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq");
+	desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pinnum, "irq");
 	if (!desc)
 		return -EINVAL;
 
+	irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum;
+
 	dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
-		chip->label, offset + chip->base, desc->irqnum);
+		chip->label, offset + chip->base, irqnum);
 
-	return irq_find_mapping(pctl->domain, desc->irqnum);
+	return irq_find_mapping(pctl->domain, irqnum);
 }
 
+static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
+{
+	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+	struct sunxi_desc_function *func;
+	int ret;
 
-static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
-				      unsigned int type)
+	func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
+					pctl->irq_array[d->hwirq], "irq");
+	if (!func)
+		return -EINVAL;
+
+	ret = gpio_lock_as_irq(pctl->chip,
+			pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
+	if (ret) {
+		dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
+			irqd_to_hwirq(d));
+		return ret;
+	}
+
+	/* Change muxing to INT mode */
+	sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
+
+	return 0;
+}
+
+static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
+{
+	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+
+	gpio_unlock_as_irq(pctl->chip,
+			   pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
+}
+
+static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+	struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
 	u32 reg = sunxi_irq_cfg_reg(d->hwirq);
 	u8 index = sunxi_irq_cfg_offset(d->hwirq);
 	unsigned long flags;
@@ -566,6 +605,14 @@ static int sunxi_pinctrl_irq_set_type(st
 		return -EINVAL;
 	}
 
+	if (type & IRQ_TYPE_LEVEL_MASK) {
+		d->chip = &sunxi_pinctrl_level_irq_chip;
+		desc->handle_irq = handle_fasteoi_irq;
+	} else {
+		d->chip = &sunxi_pinctrl_edge_irq_chip;
+		desc->handle_irq = handle_edge_irq;
+	}
+
 	spin_lock_irqsave(&pctl->lock, flags);
 
 	regval = readl(pctl->membase + reg);
@@ -577,26 +624,14 @@ static int sunxi_pinctrl_irq_set_type(st
 	return 0;
 }
 
-static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
+static void sunxi_pinctrl_irq_ack(struct irq_data *d)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	u32 ctrl_reg = sunxi_irq_ctrl_reg(d->hwirq);
-	u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
 	u32 status_reg = sunxi_irq_status_reg(d->hwirq);
 	u8 status_idx = sunxi_irq_status_offset(d->hwirq);
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&pctl->lock, flags);
-
-	/* Mask the IRQ */
-	val = readl(pctl->membase + ctrl_reg);
-	writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
 
 	/* Clear the IRQ */
 	writel(1 << status_idx, pctl->membase + status_reg);
-
-	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -619,19 +654,11 @@ static void sunxi_pinctrl_irq_mask(struc
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
 {
 	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-	struct sunxi_desc_function *func;
 	u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
 	u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
 	unsigned long flags;
 	u32 val;
 
-	func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
-						       pctl->irq_array[d->hwirq],
-						       "irq");
-
-	/* Change muxing to INT mode */
-	sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
-
 	spin_lock_irqsave(&pctl->lock, flags);
 
 	/* Unmask the IRQ */
@@ -641,28 +668,60 @@ static void sunxi_pinctrl_irq_unmask(str
 	spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
-static struct irq_chip sunxi_pinctrl_irq_chip = {
+static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
+{
+	sunxi_pinctrl_irq_ack(d);
+	sunxi_pinctrl_irq_unmask(d);
+}
+
+static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
+	.irq_ack	= sunxi_pinctrl_irq_ack,
 	.irq_mask	= sunxi_pinctrl_irq_mask,
-	.irq_mask_ack	= sunxi_pinctrl_irq_mask_ack,
 	.irq_unmask	= sunxi_pinctrl_irq_unmask,
+	.irq_request_resources = sunxi_pinctrl_irq_request_resources,
+	.irq_release_resources = sunxi_pinctrl_irq_release_resources,
 	.irq_set_type	= sunxi_pinctrl_irq_set_type,
+	.flags		= IRQCHIP_SKIP_SET_WAKE,
+};
+
+static struct irq_chip sunxi_pinctrl_level_irq_chip = {
+	.irq_eoi	= sunxi_pinctrl_irq_ack,
+	.irq_mask	= sunxi_pinctrl_irq_mask,
+	.irq_unmask	= sunxi_pinctrl_irq_unmask,
+	/* Define irq_enable / disable to avoid spurious irqs for drivers
+	 * using these to suppress irqs while they clear the irq source */
+	.irq_enable	= sunxi_pinctrl_irq_ack_unmask,
+	.irq_disable	= sunxi_pinctrl_irq_mask,
+	.irq_request_resources = sunxi_pinctrl_irq_request_resources,
+	.irq_release_resources = sunxi_pinctrl_irq_release_resources,
+	.irq_set_type	= sunxi_pinctrl_irq_set_type,
+	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED |
+			  IRQCHIP_EOI_IF_HANDLED,
 };
 
 static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_get_chip(irq);
 	struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
-	const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
+	unsigned long bank, reg, val;
 
-	/* Clear all interrupts */
-	writel(reg, pctl->membase + IRQ_STATUS_REG);
+	for (bank = 0; bank < pctl->desc->irq_banks; bank++)
+		if (irq == pctl->irq[bank])
+			break;
 
-	if (reg) {
+	if (bank == pctl->desc->irq_banks)
+		return;
+
+	reg = sunxi_irq_status_reg_from_bank(bank);
+	val = readl(pctl->membase + reg);
+
+	if (val) {
 		int irqoffset;
 
 		chained_irq_enter(chip, desc);
-		for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
-			int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
+		for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
+			int pin_irq = irq_find_mapping(pctl->domain,
+						       bank * IRQ_PER_BANK + irqoffset);
 			generic_handle_irq(pin_irq);
 		}
 		chained_irq_exit(chip, desc);
@@ -730,8 +789,11 @@ static int sunxi_pinctrl_build_state(str
 
 		while (func->name) {
 			/* Create interrupt mapping while we're at it */
-			if (!strcmp(func->name, "irq"))
-				pctl->irq_array[func->irqnum] = pin->pin.number;
+			if (!strcmp(func->name, "irq")) {
+				int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
+				pctl->irq_array[irqnum] = pin->pin.number;
+			}
+
 			sunxi_pinctrl_add_function(pctl, func->name);
 			func++;
 		}
@@ -801,6 +863,13 @@ int sunxi_pinctrl_init(struct platform_d
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 
+	pctl->irq_array = devm_kcalloc(&pdev->dev,
+				       IRQ_PER_BANK * pctl->desc->irq_banks,
+				       sizeof(*pctl->irq_array),
+				       GFP_KERNEL);
+	if (!pctl->irq_array)
+		return -ENOMEM;
+
 	ret = sunxi_pinctrl_build_state(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
@@ -869,7 +938,7 @@ int sunxi_pinctrl_init(struct platform_d
 		const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
 
 		ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
-					     pin->pin.number,
+					     pin->pin.number - pctl->desc->pin_base,
 					     pin->pin.number, 1);
 		if (ret)
 			goto gpiochip_error;
@@ -885,30 +954,51 @@ int sunxi_pinctrl_init(struct platform_d
 	if (ret)
 		goto gpiochip_error;
 
-	pctl->irq = irq_of_parse_and_map(node, 0);
+	pctl->irq = devm_kcalloc(&pdev->dev,
+				 pctl->desc->irq_banks,
+				 sizeof(*pctl->irq),
+				 GFP_KERNEL);
 	if (!pctl->irq) {
-		ret = -EINVAL;
+		ret = -ENOMEM;
 		goto clk_error;
 	}
 
-	pctl->domain = irq_domain_add_linear(node, SUNXI_IRQ_NUMBER,
-					     &irq_domain_simple_ops, NULL);
+	for (i = 0; i < pctl->desc->irq_banks; i++) {
+		pctl->irq[i] = platform_get_irq(pdev, i);
+		if (pctl->irq[i] < 0) {
+			ret = pctl->irq[i];
+			goto clk_error;
+		}
+	}
+
+	pctl->domain = irq_domain_add_linear(node,
+					     pctl->desc->irq_banks * IRQ_PER_BANK,
+					     &irq_domain_simple_ops,
+					     NULL);
 	if (!pctl->domain) {
 		dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
 		ret = -ENOMEM;
 		goto clk_error;
 	}
 
-	for (i = 0; i < SUNXI_IRQ_NUMBER; i++) {
+	for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) {
 		int irqno = irq_create_mapping(pctl->domain, i);
 
-		irq_set_chip_and_handler(irqno, &sunxi_pinctrl_irq_chip,
-					 handle_simple_irq);
+		irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
+					 handle_edge_irq);
 		irq_set_chip_data(irqno, pctl);
 	};
 
-	irq_set_chained_handler(pctl->irq, sunxi_pinctrl_irq_handler);
-	irq_set_handler_data(pctl->irq, pctl);
+	for (i = 0; i < pctl->desc->irq_banks; i++) {
+		/* Mask and clear all IRQs before registering a handler */
+		writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i));
+		writel(0xffffffff,
+			pctl->membase + sunxi_irq_status_reg_from_bank(i));
+
+		irq_set_chained_handler(pctl->irq[i],
+					sunxi_pinctrl_irq_handler);
+		irq_set_handler_data(pctl->irq[i], pctl);
+	}
 
 	dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
 
@@ -917,8 +1007,7 @@ int sunxi_pinctrl_init(struct platform_d
 clk_error:
 	clk_disable_unprepare(clk);
 gpiochip_error:
-	if (gpiochip_remove(pctl->chip))
-		dev_err(&pdev->dev, "failed to remove gpio chip\n");
+	gpiochip_remove(pctl->chip);
 pinctrl_error:
 	pinctrl_unregister(pctl->pctl_dev);
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.h linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.h
--- linux-libre-3.16-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/sunxi/pinctrl-sunxi.h	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@
 #define PULL_PINS_BITS		2
 #define PULL_PINS_MASK		0x03
 
-#define SUNXI_IRQ_NUMBER	32
+#define IRQ_PER_BANK		32
 
 #define IRQ_CFG_REG		0x200
 #define IRQ_CFG_IRQ_PER_REG		8
@@ -68,6 +68,8 @@
 #define IRQ_STATUS_IRQ_BITS		1
 #define IRQ_STATUS_IRQ_MASK		((1 << IRQ_STATUS_IRQ_BITS) - 1)
 
+#define IRQ_MEM_SIZE		0x20
+
 #define IRQ_EDGE_RISING		0x00
 #define IRQ_EDGE_FALLING	0x01
 #define IRQ_LEVEL_HIGH		0x02
@@ -77,6 +79,7 @@
 struct sunxi_desc_function {
 	const char	*name;
 	u8		muxval;
+	u8		irqbank;
 	u8		irqnum;
 };
 
@@ -89,6 +92,7 @@ struct sunxi_pinctrl_desc {
 	const struct sunxi_desc_pin	*pins;
 	int				npins;
 	unsigned			pin_base;
+	unsigned			irq_banks;
 };
 
 struct sunxi_pinctrl_function {
@@ -113,8 +117,8 @@ struct sunxi_pinctrl {
 	unsigned			nfunctions;
 	struct sunxi_pinctrl_group	*groups;
 	unsigned			ngroups;
-	int				irq;
-	int				irq_array[SUNXI_IRQ_NUMBER];
+	int				*irq;
+	unsigned			*irq_array;
 	spinlock_t			lock;
 	struct pinctrl_dev		*pctl_dev;
 };
@@ -139,6 +143,14 @@ struct sunxi_pinctrl {
 		.irqnum = _irq,					\
 	}
 
+#define SUNXI_FUNCTION_IRQ_BANK(_val, _bank, _irq)		\
+	{							\
+		.name = "irq",					\
+		.muxval = _val,					\
+		.irqbank = _bank,				\
+		.irqnum = _irq,					\
+	}
+
 /*
  * The sunXi PIO registers are organized as is:
  * 0x00 - 0x0c	Muxing values.
@@ -218,8 +230,10 @@ static inline u32 sunxi_pull_offset(u16
 
 static inline u32 sunxi_irq_cfg_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
-	return reg + IRQ_CFG_REG;
+	u8 bank = irq / IRQ_PER_BANK;
+	u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04;
+
+	return IRQ_CFG_REG + bank * IRQ_MEM_SIZE + reg;
 }
 
 static inline u32 sunxi_irq_cfg_offset(u16 irq)
@@ -228,10 +242,16 @@ static inline u32 sunxi_irq_cfg_offset(u
 	return irq_num * IRQ_CFG_IRQ_BITS;
 }
 
+static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank)
+{
+	return IRQ_CTRL_REG + bank * IRQ_MEM_SIZE;
+}
+
 static inline u32 sunxi_irq_ctrl_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
-	return reg + IRQ_CTRL_REG;
+	u8 bank = irq / IRQ_PER_BANK;
+
+	return sunxi_irq_ctrl_reg_from_bank(bank);
 }
 
 static inline u32 sunxi_irq_ctrl_offset(u16 irq)
@@ -240,10 +260,16 @@ static inline u32 sunxi_irq_ctrl_offset(
 	return irq_num * IRQ_CTRL_IRQ_BITS;
 }
 
+static inline u32 sunxi_irq_status_reg_from_bank(u8 bank)
+{
+	return IRQ_STATUS_REG + bank * IRQ_MEM_SIZE;
+}
+
 static inline u32 sunxi_irq_status_reg(u16 irq)
 {
-	u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
-	return reg + IRQ_STATUS_REG;
+	u8 bank = irq / IRQ_PER_BANK;
+
+	return sunxi_irq_status_reg_from_bank(bank);
 }
 
 static inline u32 sunxi_irq_status_offset(u16 irq)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pinctrl/vt8500/pinctrl-wmt.c linux-libre-3.17-rc7-gnu/drivers/pinctrl/vt8500/pinctrl-wmt.c
--- linux-libre-3.16-gnu/drivers/pinctrl/vt8500/pinctrl-wmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pinctrl/vt8500/pinctrl-wmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,17 +141,6 @@ static int wmt_pmx_enable(struct pinctrl
 	return wmt_set_pinmux(data, func_selector, pinnum);
 }
 
-static void wmt_pmx_disable(struct pinctrl_dev *pctldev,
-			    unsigned func_selector,
-			    unsigned group_selector)
-{
-	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
-	u32 pinnum = data->pins[group_selector].number;
-
-	/* disable by setting GPIO_IN */
-	wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, pinnum);
-}
-
 static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
 				      struct pinctrl_gpio_range *range,
 				      unsigned offset)
@@ -180,7 +169,6 @@ static struct pinmux_ops wmt_pinmux_ops
 	.get_function_name = wmt_pmx_get_function_name,
 	.get_function_groups = wmt_pmx_get_function_groups,
 	.enable = wmt_pmx_enable,
-	.disable = wmt_pmx_disable,
 	.gpio_disable_free = wmt_pmx_gpio_disable_free,
 	.gpio_set_direction = wmt_pmx_gpio_set_direction,
 };
@@ -627,8 +615,7 @@ int wmt_pinctrl_probe(struct platform_de
 	return 0;
 
 fail_range:
-	if (gpiochip_remove(&data->gpio_chip))
-		dev_err(&pdev->dev, "failed to remove gpio chip\n");
+	gpiochip_remove(&data->gpio_chip);
 fail_gpio:
 	pinctrl_unregister(data->pctl_dev);
 	return err;
@@ -637,12 +624,8 @@ fail_gpio:
 int wmt_pinctrl_remove(struct platform_device *pdev)
 {
 	struct wmt_pinctrl_data *data = platform_get_drvdata(pdev);
-	int err;
-
-	err = gpiochip_remove(&data->gpio_chip);
-	if (err)
-		dev_err(&pdev->dev, "failed to remove gpio chip\n");
 
+	gpiochip_remove(&data->gpio_chip);
 	pinctrl_unregister(data->pctl_dev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/chrome/chromeos_laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/chrome/chromeos_laptop.c
--- linux-libre-3.16-gnu/drivers/platform/chrome/chromeos_laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/chrome/chromeos_laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,8 @@
 #define ISL_ALS_I2C_ADDR	0x44
 #define TAOS_ALS_I2C_ADDR	0x29
 
+#define MAX_I2C_DEVICE_DEFERRALS	5
+
 static struct i2c_client *als;
 static struct i2c_client *tp;
 static struct i2c_client *ts;
@@ -45,6 +47,8 @@ static const char *i2c_adapter_names[] =
 	"SMBus I801 adapter",
 	"i915 gmbus vga",
 	"i915 gmbus panel",
+	"i2c-designware-pci",
+	"i2c-designware-pci",
 };
 
 /* Keep this enum consistent with i2c_adapter_names */
@@ -52,11 +56,21 @@ enum i2c_adapter_type {
 	I2C_ADAPTER_SMBUS = 0,
 	I2C_ADAPTER_VGADDC,
 	I2C_ADAPTER_PANEL,
+	I2C_ADAPTER_DESIGNWARE_0,
+	I2C_ADAPTER_DESIGNWARE_1,
+};
+
+enum i2c_peripheral_state {
+	UNPROBED = 0,
+	PROBED,
+	TIMEDOUT,
 };
 
 struct i2c_peripheral {
 	int (*add)(enum i2c_adapter_type type);
 	enum i2c_adapter_type type;
+	enum i2c_peripheral_state state;
+	int tries;
 };
 
 #define MAX_I2C_PERIPHERALS 3
@@ -97,8 +111,6 @@ static struct mxt_platform_data atmel_22
 	.irqflags		= IRQF_TRIGGER_FALLING,
 	.t19_num_keys		= ARRAY_SIZE(mxt_t19_keys),
 	.t19_keymap		= mxt_t19_keys,
-	.config			= NULL,
-	.config_length		= 0,
 };
 
 static struct i2c_board_info atmel_224s_tp_device = {
@@ -109,8 +121,6 @@ static struct i2c_board_info atmel_224s_
 
 static struct mxt_platform_data atmel_1664s_platform_data = {
 	.irqflags		= IRQF_TRIGGER_FALLING,
-	.config			= NULL,
-	.config_length		= 0,
 };
 
 static struct i2c_board_info atmel_1664s_device = {
@@ -162,8 +172,8 @@ static struct i2c_client *__add_probed_i
 	/* add the i2c device */
 	client = i2c_new_probed_device(adapter, info, addrs, NULL);
 	if (!client)
-		pr_err("%s failed to register device %d-%02x\n",
-		       __func__, bus, info->addr);
+		pr_notice("%s failed to register device %d-%02x\n",
+			  __func__, bus, info->addr);
 	else
 		pr_debug("%s added i2c device %d-%02x\n",
 			 __func__, bus, info->addr);
@@ -172,29 +182,43 @@ static struct i2c_client *__add_probed_i
 	return client;
 }
 
+struct i2c_lookup {
+	const char *name;
+	int instance;
+	int n;
+};
+
 static int __find_i2c_adap(struct device *dev, void *data)
 {
-	const char *name = data;
+	struct i2c_lookup *lookup = data;
 	static const char *prefix = "i2c-";
 	struct i2c_adapter *adapter;
+
 	if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
 		return 0;
 	adapter = to_i2c_adapter(dev);
-	return (strncmp(adapter->name, name, strlen(name)) == 0);
+	if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 &&
+	    lookup->n++ == lookup->instance)
+		return 1;
+	return 0;
 }
 
 static int find_i2c_adapter_num(enum i2c_adapter_type type)
 {
 	struct device *dev = NULL;
 	struct i2c_adapter *adapter;
-	const char *name = i2c_adapter_names[type];
+	struct i2c_lookup lookup;
+
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.name = i2c_adapter_names[type];
+	lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0;
+
 	/* find the adapter by name */
-	dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
-			      __find_i2c_adap);
+	dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap);
 	if (!dev) {
 		/* Adapters may appear later. Deferred probing will retry */
 		pr_notice("%s: i2c adapter %s not found on system.\n", __func__,
-			  name);
+			  lookup.name);
 		return -ENODEV;
 	}
 	adapter = to_i2c_adapter(dev);
@@ -231,6 +255,7 @@ static struct i2c_client *add_i2c_device
 						struct i2c_board_info *info)
 {
 	const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
+
 	return __add_probed_i2c_device(name,
 				       find_i2c_adapter_num(type),
 				       info,
@@ -328,9 +353,36 @@ static int chromeos_laptop_probe(struct
 		if (i2c_dev->add == NULL)
 			break;
 
-		/* Add the device. Set -EPROBE_DEFER on any failure */
-		if (i2c_dev->add(i2c_dev->type))
+		if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED)
+			continue;
+
+		/*
+		 * Check that the i2c adapter is present.
+		 * -EPROBE_DEFER if missing as the adapter may appear much
+		 * later.
+		 */
+		if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) {
 			ret = -EPROBE_DEFER;
+			continue;
+		}
+
+		/* Add the device. */
+		if (i2c_dev->add(i2c_dev->type) == -EAGAIN) {
+			/*
+			 * Set -EPROBE_DEFER a limited num of times
+			 * if device is not successfully added.
+			 */
+			if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) {
+				ret = -EPROBE_DEFER;
+			} else {
+				/* Ran out of tries. */
+				pr_notice("%s: Ran out of tries for device.\n",
+					  __func__);
+				i2c_dev->state = TIMEDOUT;
+			}
+		} else {
+			i2c_dev->state = PROBED;
+		}
 	}
 
 	return ret;
@@ -363,6 +415,27 @@ static struct chromeos_laptop chromebook
 	},
 };
 
+static struct chromeos_laptop hp_chromebook_14 = {
+	.i2c_peripherals = {
+		/* Touchpad. */
+		{ .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+	},
+};
+
+static struct chromeos_laptop dell_chromebook_11 = {
+	.i2c_peripherals = {
+		/* Touchpad. */
+		{ .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+	},
+};
+
+static struct chromeos_laptop toshiba_cb35 = {
+	.i2c_peripherals = {
+		/* Touchpad. */
+		{ .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+	},
+};
+
 static struct chromeos_laptop acer_c7_chromebook = {
 	.i2c_peripherals = {
 		/* Touchpad. */
@@ -377,6 +450,17 @@ static struct chromeos_laptop acer_ac700
 	},
 };
 
+static struct chromeos_laptop acer_c720 = {
+	.i2c_peripherals = {
+		/* Touchscreen. */
+		{ .add = setup_atmel_1664s_ts, I2C_ADAPTER_DESIGNWARE_1 },
+		/* Touchpad. */
+		{ .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+		/* Light Sensor. */
+		{ .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 },
+	},
+};
+
 static struct chromeos_laptop hp_pavilion_14_chromebook = {
 	.i2c_peripherals = {
 		/* Touchpad. */
@@ -420,6 +504,30 @@ static struct dmi_system_id chromeos_lap
 		_CBDD(chromebook_pixel),
 	},
 	{
+		.ident = "Wolf",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"),
+		},
+		_CBDD(dell_chromebook_11),
+	},
+	{
+		.ident = "HP Chromebook 14",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Falco"),
+		},
+		_CBDD(hp_chromebook_14),
+	},
+	{
+		.ident = "Toshiba CB35",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Leon"),
+		},
+		_CBDD(toshiba_cb35),
+	},
+	{
 		.ident = "Acer C7 Chromebook",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
@@ -434,6 +542,13 @@ static struct dmi_system_id chromeos_lap
 		_CBDD(acer_ac700),
 	},
 	{
+		.ident = "Acer C720",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
+		},
+		_CBDD(acer_c720),
+	},
+	{
 		.ident = "HP Pavilion 14 Chromebook",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
@@ -464,6 +579,7 @@ static struct platform_driver cros_platf
 static int __init chromeos_laptop_init(void)
 {
 	int ret;
+
 	if (!dmi_check_system(chromeos_laptop_dmi_table)) {
 		pr_debug("%s unsupported system.\n", __func__);
 		return -ENODEV;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/chrome/chromeos_pstore.c linux-libre-3.17-rc7-gnu/drivers/platform/chrome/chromeos_pstore.c
--- linux-libre-3.16-gnu/drivers/platform/chrome/chromeos_pstore.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/chrome/chromeos_pstore.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,23 +16,13 @@
 static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = {
 	{
 		/*
-		 * Today all Chromebooks/boxes ship with GOOGLE as vendor and
+		 * Today all Chromebooks/boxes ship with Google_* as version and
 		 * coreboot as bios vendor. No other systems with this
 		 * combination are known to date.
 		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
-		},
-	},
-	{
-		/*
-		 * The first Samsung Chromebox and Chromebook Series 5 550 use
-		 * coreboot but with Samsung as the system vendor.
-		 */
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
 			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+			DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
 		},
 	},
 	{
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/acer-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/acer-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/acer-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/acer-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -96,7 +96,7 @@ enum acer_wmi_event_ids {
 	WMID_ACCEL_EVENT = 0x5,
 };
 
-static const struct key_entry acer_wmi_keymap[] = {
+static const struct key_entry acer_wmi_keymap[] __initconst = {
 	{KE_KEY, 0x01, {KEY_WLAN} },     /* WiFi */
 	{KE_KEY, 0x03, {KEY_WLAN} },     /* WiFi */
 	{KE_KEY, 0x04, {KEY_WLAN} },     /* WiFi */
@@ -294,7 +294,7 @@ struct quirk_entry {
 
 static struct quirk_entry *quirks;
 
-static void set_quirks(void)
+static void __init set_quirks(void)
 {
 	if (!interface)
 		return;
@@ -306,7 +306,7 @@ static void set_quirks(void)
 		interface->capability |= ACER_CAP_BRIGHTNESS;
 }
 
-static int dmi_matched(const struct dmi_system_id *dmi)
+static int __init dmi_matched(const struct dmi_system_id *dmi)
 {
 	quirks = dmi->driver_data;
 	return 1;
@@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_i
 };
 
 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
-static struct dmi_system_id acer_blacklist[] = {
+static const struct dmi_system_id acer_blacklist[] __initconst = {
 	{
 		.ident = "Acer Aspire One (SSD)",
 		.matches = {
@@ -355,7 +355,7 @@ static struct dmi_system_id acer_blackli
 	{}
 };
 
-static struct dmi_system_id acer_quirks[] = {
+static const struct dmi_system_id acer_quirks[] __initconst = {
 	{
 		.callback = dmi_matched,
 		.ident = "Acer Aspire 1360",
@@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[
 	{}
 };
 
-static int video_set_backlight_video_vendor(const struct dmi_system_id *d)
+static int __init
+video_set_backlight_video_vendor(const struct dmi_system_id *d)
 {
 	interface->capability &= ~ACER_CAP_BRIGHTNESS;
 	pr_info("Brightness must be controlled by generic video driver\n");
 	return 0;
 }
 
-static const struct dmi_system_id video_vendor_dmi_table[] = {
+static const struct dmi_system_id video_vendor_dmi_table[] __initconst = {
 	{
 		.callback = video_set_backlight_video_vendor,
 		.ident = "Acer TravelMate 4750",
@@ -582,7 +583,7 @@ static const struct dmi_system_id video_
 };
 
 /* Find which quirks are needed for a particular vendor/ model pair */
-static void find_quirks(void)
+static void __init find_quirks(void)
 {
 	if (!force_series) {
 		dmi_check_system(acer_quirks);
@@ -749,7 +750,7 @@ static acpi_status AMW0_set_u32(u32 valu
 	return wmab_execute(&args, NULL);
 }
 
-static acpi_status AMW0_find_mailled(void)
+static acpi_status __init AMW0_find_mailled(void)
 {
 	struct wmab_args args;
 	struct wmab_ret ret;
@@ -781,16 +782,16 @@ static acpi_status AMW0_find_mailled(voi
 	return AE_OK;
 }
 
-static int AMW0_set_cap_acpi_check_device_found;
+static int AMW0_set_cap_acpi_check_device_found __initdata;
 
-static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
+static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
 	u32 level, void *context, void **retval)
 {
 	AMW0_set_cap_acpi_check_device_found = 1;
 	return AE_OK;
 }
 
-static const struct acpi_device_id norfkill_ids[] = {
+static const struct acpi_device_id norfkill_ids[] __initconst = {
 	{ "VPC2004", 0},
 	{ "IBM0068", 0},
 	{ "LEN0068", 0},
@@ -798,7 +799,7 @@ static const struct acpi_device_id norfk
 	{ "", 0},
 };
 
-static int AMW0_set_cap_acpi_check_device(void)
+static int __init AMW0_set_cap_acpi_check_device(void)
 {
 	const struct acpi_device_id *id;
 
@@ -808,7 +809,7 @@ static int AMW0_set_cap_acpi_check_devic
 	return AMW0_set_cap_acpi_check_device_found;
 }
 
-static acpi_status AMW0_set_capabilities(void)
+static acpi_status __init AMW0_set_capabilities(void)
 {
 	struct wmab_args args;
 	struct wmab_ret ret;
@@ -1184,7 +1185,7 @@ static acpi_status wmid_v2_set_u32(u32 v
 	return wmid3_set_device_status(value, device);
 }
 
-static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
+static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)
 {
 	struct hotkey_function_type_aa *type_aa;
 
@@ -1209,7 +1210,7 @@ static void type_aa_dmi_decode(const str
 	commun_fn_key_number = type_aa->commun_fn_key_number;
 }
 
-static acpi_status WMID_set_capabilities(void)
+static acpi_status __init WMID_set_capabilities(void)
 {
 	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
 	union acpi_object *obj;
@@ -1658,7 +1659,7 @@ static ssize_t show_bool_threeg(struct d
 	u32 result; \
 	acpi_status status;
 
-	pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+	pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
 		current->comm);
 	status = get_u32(&result, ACER_CAP_THREEG);
 	if (ACPI_SUCCESS(status))
@@ -1671,7 +1672,7 @@ static ssize_t set_bool_threeg(struct de
 {
 	u32 tmp = simple_strtoul(buf, NULL, 10);
 	acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
-	pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+	pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
 		current->comm);
 	if (ACPI_FAILURE(status))
 		return -EINVAL;
@@ -1683,7 +1684,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_I
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
 	char *buf)
 {
-	pr_info("This interface sysfs will be removed in 2012 - used by: %s\n",
+	pr_info("This interface sysfs will be removed in 2014 - used by: %s\n",
 		current->comm);
 	switch (interface->type) {
 	case ACER_AMW0:
@@ -1777,7 +1778,7 @@ static void acer_wmi_notify(u32 value, v
 	}
 }
 
-static acpi_status
+static acpi_status __init
 wmid3_set_lm_mode(struct lm_input_params *params,
 		  struct lm_return_value *return_value)
 {
@@ -1811,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params
 	return status;
 }
 
-static int acer_wmi_enable_ec_raw(void)
+static int __init acer_wmi_enable_ec_raw(void)
 {
 	struct lm_return_value return_value;
 	acpi_status status;
@@ -1834,7 +1835,7 @@ static int acer_wmi_enable_ec_raw(void)
 	return status;
 }
 
-static int acer_wmi_enable_lm(void)
+static int __init acer_wmi_enable_lm(void)
 {
 	struct lm_return_value return_value;
 	acpi_status status;
@@ -2043,6 +2044,7 @@ static int acer_platform_remove(struct p
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int acer_suspend(struct device *dev)
 {
 	u32 value;
@@ -2083,6 +2085,10 @@ static int acer_resume(struct device *de
 
 	return 0;
 }
+#else
+#define acer_suspend	NULL
+#define acer_resume	NULL
+#endif
 
 static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
 
@@ -2120,7 +2126,7 @@ static int remove_sysfs(struct platform_
 	return 0;
 }
 
-static int create_sysfs(void)
+static int __init create_sysfs(void)
 {
 	int retval = -ENOMEM;
 
@@ -2149,7 +2155,7 @@ static void remove_debugfs(void)
 	debugfs_remove(interface->debug.root);
 }
 
-static int create_debugfs(void)
+static int __init create_debugfs(void)
 {
 	interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
 	if (!interface->debug.root) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/alienware-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/alienware-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/alienware-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/alienware-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES {
 
 struct quirk_entry {
 	u8 num_zones;
+	u8 hdmi_mux;
 };
 
 static struct quirk_entry *quirks;
 
 static struct quirk_entry quirk_unknown = {
 	.num_zones = 2,
+	.hdmi_mux = 0,
 };
 
 static struct quirk_entry quirk_x51_family = {
 	.num_zones = 3,
+	.hdmi_mux = 0.
 };
 
-static int dmi_matched(const struct dmi_system_id *dmi)
+static struct quirk_entry quirk_asm100 = {
+	.num_zones = 2,
+	.hdmi_mux = 1,
+};
+
+static int __init dmi_matched(const struct dmi_system_id *dmi)
 {
 	quirks = dmi->driver_data;
 	return 1;
 }
 
-static struct dmi_system_id alienware_quirks[] = {
+static const struct dmi_system_id alienware_quirks[] __initconst = {
 	{
 	 .callback = dmi_matched,
 	 .ident = "Alienware X51 R1",
@@ -96,6 +104,15 @@ static struct dmi_system_id alienware_qu
 		     },
 	 .driver_data = &quirk_x51_family,
 	 },
+	{
+		.callback = dmi_matched,
+		.ident = "Alienware ASM100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"),
+		},
+		.driver_data = &quirk_asm100,
+	},
 	{}
 };
 
@@ -537,7 +554,8 @@ static struct attribute_group hdmi_attri
 
 static void remove_hdmi(struct platform_device *dev)
 {
-	sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group);
+	if (quirks->hdmi_mux > 0)
+		sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group);
 }
 
 static int create_hdmi(struct platform_device *dev)
@@ -583,7 +601,7 @@ static int __init alienware_wmi_init(voi
 	if (ret)
 		goto fail_platform_device2;
 
-	if (interface == WMAX) {
+	if (quirks->hdmi_mux > 0) {
 		ret = create_hdmi(platform_device);
 		if (ret)
 			goto fail_prep_hdmi;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/asus-nb-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/asus-nb-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/asus-nb-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/asus-nb-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55
 	.no_display_toggle = true,
 };
 
-static struct quirk_entry quirk_asus_x401u = {
+static struct quirk_entry quirk_asus_wapf4 = {
 	.wapf = 4,
 };
 
+static struct quirk_entry quirk_asus_x200ca = {
+	.wapf = 2,
+};
+
 static int dmi_matched(const struct dmi_system_id *dmi)
 {
 	quirks = dmi->driver_data;
 	return 1;
 }
 
-static struct dmi_system_id asus_quirks[] = {
+static const struct dmi_system_id asus_quirks[] = {
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. U32U",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "U32U"),
+		},
+		/*
+		 * Note this machine has a Brazos APU, and most Brazos Asus
+		 * machines need quirk_asus_x55u / wmi_backlight_power but
+		 * here acpi-video seems to work fine for backlight control.
+		 */
+		.driver_data = &quirk_asus_wapf4,
+	},
 	{
 		.callback = dmi_matched,
 		.ident = "ASUSTeK COMPUTER INC. X401U",
@@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X401A"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X501A"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -142,7 +160,25 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. X550CC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"),
+		},
+		.driver_data = &quirk_asus_wapf4,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. X550CL",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"),
+		},
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -151,7 +187,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X55A"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -160,7 +196,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X55C"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -178,7 +214,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -187,7 +223,16 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. X75VBP",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"),
+		},
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -196,7 +241,7 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "1015E"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
 	},
 	{
 		.callback = dmi_matched,
@@ -205,7 +250,16 @@ static struct dmi_system_id asus_quirks[
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "1015U"),
 		},
-		.driver_data = &quirk_asus_x401u,
+		.driver_data = &quirk_asus_wapf4,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. X200CA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"),
+		},
+		.driver_data = &quirk_asus_x200ca,
 	},
 	{},
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/asus-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/asus-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/asus-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/asus-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,7 @@
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <acpi/video.h>
 
 #include "asus-wmi.h"
@@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus
 			goto error;
 	}
 
-	if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) {
+	if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) {
 		INIT_WORK(&asus->wlan_led_work, wlan_led_update);
 
 		asus->wlan_led.name = "asus::wlan";
@@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_w
 		return -EINVAL;
 
 	if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
-			(asus->driver->quirks->wapf == 4))
+			(asus->driver->quirks->wapf > 0))
 		rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
 
 	rfkill_init_sw_state(*rfkill, !result);
@@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struc
 	int power;
 
 	max = read_brightness_max(asus);
-
-	if (max == -ENODEV)
-		max = 0;
-	else if (max < 0)
+	if (max < 0)
 		return max;
 
 	power = read_backlight_power(asus);
@@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_
 	struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
 	struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
 	struct asus_wmi *asus;
+	const char *chassis_type;
 	acpi_status status;
 	int err;
 	u32 result;
@@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_
 	if (err)
 		goto fail_rfkill;
 
+	/* Some Asus desktop boards export an acpi-video backlight interface,
+	   stop this from showing up */
+	chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
+	if (chassis_type && !strcmp(chassis_type, "3"))
+		acpi_video_dmi_promote_vendor();
 	if (asus->driver->quirks->wmi_backlight_power)
 		acpi_video_dmi_promote_vendor();
 	if (!acpi_video_backlight_support()) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/compal-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/compal-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/compal-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/compal-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_
 		return err;
 
 	hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-						      DRIVER_NAME, data,
+						      "compal", data,
 						      compal_hwmon_groups);
 	if (IS_ERR(hwmon_dev)) {
 		err = PTR_ERR(hwmon_dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/dell-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/dell-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/dell-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/dell-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vos
 	.touchpad_led = 1,
 };
 
-static int dmi_matched(const struct dmi_system_id *dmi)
+static int __init dmi_matched(const struct dmi_system_id *dmi)
 {
 	quirks = dmi->driver_data;
 	return 1;
@@ -123,7 +123,7 @@ static const struct dmi_system_id dell_d
 };
 MODULE_DEVICE_TABLE(dmi, dell_device_table);
 
-static struct dmi_system_id dell_quirks[] = {
+static const struct dmi_system_id dell_quirks[] __initconst = {
 	{
 		.callback = dmi_matched,
 		.ident = "Dell Vostro V130",
@@ -780,7 +780,7 @@ static struct led_classdev touchpad_led
 	.flags = LED_CORE_SUSPENDRESUME,
 };
 
-static int touchpad_led_init(struct device *dev)
+static int __init touchpad_led_init(struct device *dev)
 {
 	return led_classdev_register(dev, &touchpad_led);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/eeepc-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/eeepc-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/eeepc-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/eeepc-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -1053,20 +1053,20 @@ static ssize_t show_sys_hwmon(int (*get)
 	return sprintf(buf, "%d\n", get());
 }
 
-#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get)		\
+#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set)		\
 	static ssize_t show_##_name(struct device *dev,			\
 				    struct device_attribute *attr,	\
 				    char *buf)				\
 	{								\
-		return show_sys_hwmon(_set, buf);			\
+		return show_sys_hwmon(_get, buf);			\
 	}								\
 	static ssize_t store_##_name(struct device *dev,		\
 				     struct device_attribute *attr,	\
 				     const char *buf, size_t count)	\
 	{								\
-		return store_sys_hwmon(_get, buf, count);		\
+		return store_sys_hwmon(_set, buf, count);		\
 	}								\
-	static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name);
+	static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name)
 
 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/eeepc-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/eeepc-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/eeepc-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/eeepc-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_
 	return 1;
 }
 
-static struct dmi_system_id asus_quirks[] = {
+static const struct dmi_system_id asus_quirks[] = {
 	{
 		.callback = dmi_matched,
 		.ident = "ASUSTeK Computer INC. 1000H",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/fujitsu-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/fujitsu-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/fujitsu-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/fujitsu-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -129,15 +129,14 @@
 #define FUJLAPTOP_DBG_INFO	  0x0004
 #define FUJLAPTOP_DBG_TRACE	  0x0008
 
-#define dbg_printk(a_dbg_level, format, arg...) \
+#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
+#define vdbg_printk(a_dbg_level, format, arg...) \
 	do { if (dbg_level & a_dbg_level) \
 		printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \
 	} while (0)
-#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
-#define vdbg_printk(a_dbg_level, format, arg...) \
-	dbg_printk(a_dbg_level, format, ## arg)
 #else
-#define vdbg_printk(a_dbg_level, format, arg...)
+#define vdbg_printk(a_dbg_level, format, arg...) \
+	do { } while (0)
 #endif
 
 /* Device controlling the backlight and associated keys */
@@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_
 		   }
 };
 
-static void dmi_check_cb_common(const struct dmi_system_id *id)
+static void __init dmi_check_cb_common(const struct dmi_system_id *id)
 {
 	pr_info("Identified laptop model '%s'\n", id->ident);
 	if (use_alt_lcd_levels == -1) {
@@ -578,7 +577,7 @@ static void dmi_check_cb_common(const st
 	}
 }
 
-static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+static int __init dmi_check_cb_s6410(const struct dmi_system_id *id)
 {
 	dmi_check_cb_common(id);
 	fujitsu->keycode1 = KEY_SCREENLOCK;	/* "Lock" */
@@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const stru
 	return 1;
 }
 
-static int dmi_check_cb_s6420(const struct dmi_system_id *id)
+static int __init dmi_check_cb_s6420(const struct dmi_system_id *id)
 {
 	dmi_check_cb_common(id);
 	fujitsu->keycode1 = KEY_SCREENLOCK;	/* "Lock" */
@@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const stru
 	return 1;
 }
 
-static int dmi_check_cb_p8010(const struct dmi_system_id *id)
+static int __init dmi_check_cb_p8010(const struct dmi_system_id *id)
 {
 	dmi_check_cb_common(id);
 	fujitsu->keycode1 = KEY_HELP;	/* "Support" */
@@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const stru
 	return 1;
 }
 
-static struct dmi_system_id fujitsu_dmi_table[] = {
+static const struct dmi_system_id fujitsu_dmi_table[] __initconst = {
 	{
 	 .ident = "Fujitsu Siemens S6410",
 	 .matches = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/fujitsu-tablet.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/fujitsu-tablet.c
--- linux-libre-3.16-gnu/drivers/platform/x86/fujitsu-tablet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/fujitsu-tablet.c	2014-09-28 17:29:07.000000000 -0400
@@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int
 	return IRQ_HANDLED;
 }
 
-static void fujitsu_dmi_common(const struct dmi_system_id *dmi)
+static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi)
 {
 	pr_info("%s\n", dmi->ident);
 	memcpy(fujitsu.config.keymap, dmi->driver_data,
 			sizeof(fujitsu.config.keymap));
 }
 
-static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
+static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
 {
 	fujitsu_dmi_common(dmi);
 	fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
 	return 1;
 }
 
-static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
+static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
 {
 	fujitsu_dmi_common(dmi);
 	fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/hp_accel.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/hp_accel.c
--- linux-libre-3.16-gnu/drivers/platform/x86/hp_accel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/hp_accel.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,7 +74,7 @@ static inline void delayed_sysfs_set(str
 /* HP-specific accelerometer driver ------------------------------------ */
 
 /* For automatic insertion of the module */
-static struct acpi_device_id lis3lv02d_device_ids[] = {
+static const struct acpi_device_id lis3lv02d_device_ids[] = {
 	{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
 	{"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
 	{"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */
@@ -192,7 +192,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1,
 	},						\
 	.driver_data = &lis3lv02d_axis_##_axis		\
 }
-static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+static const struct dmi_system_id lis3lv02d_dmi_ids[] = {
 	/* product names are truncated to match all kinds of a same model */
 	AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
 	AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/hp-wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/hp-wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/hp-wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/hp-wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void)
 	return (state & 0x4) ? 1 : 0;
 }
 
-static int hp_wmi_bios_2009_later(void)
+static int __init hp_wmi_bios_2009_later(void)
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state,
@@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platfor
 	device_remove_file(&device->dev, &dev_attr_postcode);
 }
 
-static int hp_wmi_rfkill_setup(struct platform_device *device)
+static int __init hp_wmi_rfkill_setup(struct platform_device *device)
 {
 	int err;
 	int wireless = 0;
@@ -806,7 +806,7 @@ register_wifi_error:
 	return err;
 }
 
-static int hp_wmi_rfkill2_setup(struct platform_device *device)
+static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
 {
 	int err, i;
 	struct bios_rfkill2_state state;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/ideapad-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/ideapad-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/ideapad-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/ideapad-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -87,6 +87,7 @@ struct ideapad_private {
 	struct backlight_device *blightdev;
 	struct dentry *debug;
 	unsigned long cfg;
+	bool has_hw_rfkill_switch;
 };
 
 static bool no_bt_rfkill;
@@ -439,7 +440,7 @@ static umode_t ideapad_is_visible(struct
 	return supported ? attr->mode : 0;
 }
 
-static struct attribute_group ideapad_attribute_group = {
+static const struct attribute_group ideapad_attribute_group = {
 	.is_visible = ideapad_is_visible,
 	.attrs = ideapad_attributes
 };
@@ -454,7 +455,7 @@ struct ideapad_rfk_data {
 	int type;
 };
 
-const struct ideapad_rfk_data ideapad_rfk_data[] = {
+static const struct ideapad_rfk_data ideapad_rfk_data[] = {
 	{ "ideapad_wlan",    CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
 	{ "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
 	{ "ideapad_3g",        CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
@@ -473,12 +474,14 @@ static struct rfkill_ops ideapad_rfk_ops
 
 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
 {
-	unsigned long hw_blocked;
+	unsigned long hw_blocked = 0;
 	int i;
 
-	if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
-		return;
-	hw_blocked = !hw_blocked;
+	if (priv->has_hw_rfkill_switch) {
+		if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
+			return;
+		hw_blocked = !hw_blocked;
+	}
 
 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
 		if (priv->rfk[i])
@@ -821,14 +824,17 @@ static void ideapad_acpi_notify(acpi_han
 	}
 }
 
-/* Blacklist for devices where the ideapad rfkill interface does not work */
-static struct dmi_system_id rfkill_blacklist[] = {
-	/* The Lenovo Yoga 2 11 always reports everything as blocked */
+/*
+ * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
+ * always results in 0 on these models, causing ideapad_laptop to wrongly
+ * report all radios as hardware-blocked.
+ */
+static const struct dmi_system_id no_hw_rfkill_list[] = {
 	{
-		.ident = "Lenovo Yoga 2 11",
+		.ident = "Lenovo Yoga 2 11 / 13 / Pro",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
 		},
 	},
 	{}
@@ -856,6 +862,7 @@ static int ideapad_acpi_add(struct platf
 	priv->cfg = cfg;
 	priv->adev = adev;
 	priv->platform_device = pdev;
+	priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
 
 	ret = ideapad_sysfs_init(priv);
 	if (ret)
@@ -869,11 +876,17 @@ static int ideapad_acpi_add(struct platf
 	if (ret)
 		goto input_failed;
 
-	if (!dmi_check_system(rfkill_blacklist)) {
-		for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
-			if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
-				ideapad_register_rfkill(priv, i);
-	}
+	/*
+	 * On some models without a hw-switch (the yoga 2 13 at least)
+	 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
+	 */
+	if (!priv->has_hw_rfkill_switch)
+		write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
+
+	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
+		if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
+			ideapad_register_rfkill(priv, i);
+
 	ideapad_sync_rfk_state(priv);
 	ideapad_sync_touchpad_state(priv);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/intel_ips.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/intel_ips.c
--- linux-libre-3.16-gnu/drivers/platform/x86/intel_ips.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/intel_ips.c	2014-09-28 17:29:07.000000000 -0400
@@ -269,7 +269,7 @@ struct ips_mcp_limits {
 
 /* Max temps are -10 degrees C to avoid PROCHOT# */
 
-struct ips_mcp_limits ips_sv_limits = {
+static struct ips_mcp_limits ips_sv_limits = {
 	.mcp_power_limit = 35000,
 	.core_power_limit = 29000,
 	.mch_power_limit = 20000,
@@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = {
 	.mch_temp_limit = 90
 };
 
-struct ips_mcp_limits ips_lv_limits = {
+static struct ips_mcp_limits ips_lv_limits = {
 	.mcp_power_limit = 25000,
 	.core_power_limit = 21000,
 	.mch_power_limit = 13000,
@@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = {
 	.mch_temp_limit = 90
 };
 
-struct ips_mcp_limits ips_ulv_limits = {
+static struct ips_mcp_limits ips_ulv_limits = {
 	.mcp_power_limit = 18000,
 	.core_power_limit = 14000,
 	.mch_power_limit = 11000,
@@ -1478,7 +1478,7 @@ ips_link_to_i915_driver(void)
 }
 EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
 
-static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
+static const struct pci_device_id ips_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
 		     PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
 	{ 0, }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/intel_scu_ipc.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/intel_scu_ipc.c
--- linux-libre-3.16-gnu/drivers/platform/x86/intel_scu_ipc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/intel_scu_ipc.c	2014-09-28 17:29:07.000000000 -0400
@@ -640,7 +640,7 @@ static void ipc_remove(struct pci_dev *p
 	intel_scu_devices_destroy();
 }
 
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
+static const struct pci_device_id pci_ids[] = {
 	{
 		PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT),
 		(kernel_ulong_t)&intel_scu_ipc_lincroft_pdata,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/Kconfig linux-libre-3.17-rc7-gnu/drivers/platform/x86/Kconfig
--- linux-libre-3.16-gnu/drivers/platform/x86/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -652,6 +652,25 @@ config TOSHIBA_BT_RFKILL
 	  If you have a modern Toshiba laptop with a Bluetooth and an
 	  RFKill switch (such as the Portege R500), say Y.
 
+config TOSHIBA_HAPS
+	tristate "Toshiba HDD Active Protection Sensor"
+	depends on ACPI
+	---help---
+	  This driver adds support for the built-in accelerometer
+	  found on recent Toshiba laptops equiped with HID TOS620A
+	  device.
+
+	  This driver receives ACPI notify events 0x80 when the sensor
+	  detects a sudden move or a harsh vibration, as well as an
+	  ACPI notify event 0x81 whenever the movement or vibration has
+	  been stabilized.
+
+	  Also provides sysfs entries to get/set the desired protection
+	  level and reseting the HDD protection interface.
+
+	  If you have a recent Toshiba laptop with a built-in accelerometer
+	  device, say Y.
+
 config ACPI_CMPC
 	tristate "CMPC Laptop Extras"
 	depends on X86 && ACPI
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/Makefile linux-libre-3.17-rc7-gnu/drivers/platform/x86/Makefile
--- linux-libre-3.16-gnu/drivers/platform/x86/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP)	+= topstar-
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
 
 obj-$(CONFIG_TOSHIBA_BT_RFKILL)	+= toshiba_bluetooth.o
+obj-$(CONFIG_TOSHIBA_HAPS)	+= toshiba_haps.o
 obj-$(CONFIG_INTEL_SCU_IPC)	+= intel_scu_ipc.o
 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
 obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/samsung-q10.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/samsung-q10.c
--- linux-libre-3.16-gnu/drivers/platform/x86/samsung-q10.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/samsung-q10.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,13 +46,7 @@ static int samsungq10_bl_set_intensity(s
 	return 0;
 }
 
-static int samsungq10_bl_get_intensity(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
 static const struct backlight_ops samsungq10_bl_ops = {
-	.get_brightness = samsungq10_bl_get_intensity,
 	.update_status	= samsungq10_bl_set_intensity,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/sony-laptop.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/sony-laptop.c
--- linux-libre-3.16-gnu/drivers/platform/x86/sony-laptop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/sony-laptop.c	2014-09-28 17:29:07.000000000 -0400
@@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(stru
 		lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store;
 	}
 	for (i = 0; i < LID_RESUME_MAX &&
-			lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) {
+			lid_ctl->attrs[i].attr.name; i++) {
 		result = device_create_file(&pd->dev, &lid_ctl->attrs[i]);
 		if (result)
 			goto liderror;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/thinkpad_acpi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/thinkpad_acpi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/thinkpad_acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/thinkpad_acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm
 		KEY_UNKNOWN,
 
 		/* Extra keys in use since the X240 / T440 / T540 */
-		KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER,
+		KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE,
 		},
 	};
 
@@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int v
 {
 	int res;
 
-	if (value > bright_maxlvl || value < 0)
+	if (value > bright_maxlvl)
 		return -EINVAL;
 
 	vdbg_printk(TPACPI_DBG_BRGHT,
@@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct s
 	return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
 }
 
-static struct snd_kcontrol_new volume_alsa_control_vol = {
+static struct snd_kcontrol_new volume_alsa_control_vol __initdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Console Playback Volume",
 	.index = 0,
@@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_al
 	.get = volume_alsa_vol_get,
 };
 
-static struct snd_kcontrol_new volume_alsa_control_mute = {
+static struct snd_kcontrol_new volume_alsa_control_mute __initdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Console Playback Switch",
 	.index = 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/toshiba_acpi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/toshiba_acpi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/toshiba_acpi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/toshiba_acpi.c	2014-09-28 17:29:07.000000000 -0400
@@ -222,6 +222,12 @@ static const struct dmi_system_id toshib
 			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"),
 		},
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"),
+		},
+	},
 	{}
 };
 
@@ -229,6 +235,7 @@ static const struct key_entry toshiba_ac
 	{ KE_KEY, 0x157, { KEY_MUTE } },
 	{ KE_KEY, 0x102, { KEY_ZOOMOUT } },
 	{ KE_KEY, 0x103, { KEY_ZOOMIN } },
+	{ KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
 	{ KE_KEY, 0x139, { KEY_ZOOMRESET } },
 	{ KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } },
 	{ KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } },
@@ -872,7 +879,9 @@ static int lcd_proc_open(struct inode *i
 
 static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
 {
-	u32 hci_result;
+	u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 };
+	u32 out[HCI_WORDS];
+	acpi_status status;
 
 	if (dev->tr_backlight_supported) {
 		bool enable = !value;
@@ -883,9 +892,20 @@ static int set_lcd_brightness(struct tos
 			value--;
 	}
 
-	value = value << HCI_LCD_BRIGHTNESS_SHIFT;
-	hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
-	return hci_result == HCI_SUCCESS ? 0 : -EIO;
+	in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT;
+	status = hci_raw(dev, in, out);
+	if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) {
+		pr_err("ACPI call to set brightness failed");
+		return -EIO;
+	}
+	/* Extra check for "incomplete" backlight method, where the AML code
+	 * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS,
+	 * the actual brightness, and in some cases the max brightness.
+	 */
+	if (out[2] > 0  || out[3] == 0xE000)
+		return -ENODEV;
+
+	return out[0] == HCI_SUCCESS ? 0 : -EIO;
 }
 
 static int set_lcd_status(struct backlight_device *bd)
@@ -1235,10 +1255,15 @@ static ssize_t toshiba_kbd_bl_mode_store
 					 const char *buf, size_t count)
 {
 	struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
-	int mode = -1;
-	int time = -1;
+	int mode;
+	int time;
+	int ret;
 
-	if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1))
+
+	ret = kstrtoint(buf, 0, &mode);
+	if (ret)
+		return ret;
+	if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO)
 		return -EINVAL;
 
 	/* Set the Keyboard Backlight Mode where:
@@ -1246,11 +1271,12 @@ static ssize_t toshiba_kbd_bl_mode_store
 	 *	Auto - KBD backlight turns off automatically in given time
 	 *	FN-Z - KBD backlight "toggles" when hotkey pressed
 	 */
-	if (mode != -1 && toshiba->kbd_mode != mode) {
+	if (toshiba->kbd_mode != mode) {
 		time = toshiba->kbd_time << HCI_MISC_SHIFT;
 		time = time + toshiba->kbd_mode;
-		if (toshiba_kbd_illum_status_set(toshiba, time) < 0)
-			return -EIO;
+		ret = toshiba_kbd_illum_status_set(toshiba, time);
+		if (ret)
+			return ret;
 		toshiba->kbd_mode = mode;
 	}
 
@@ -1837,9 +1863,16 @@ static int toshiba_acpi_resume(struct de
 {
 	struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
 	u32 result;
+	acpi_status status;
+
+	if (dev->hotkey_dev) {
+		status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB",
+				NULL, NULL);
+		if (ACPI_FAILURE(status))
+			pr_info("Unable to re-enable hotkeys\n");
 
-	if (dev->hotkey_dev)
 		hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result);
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/toshiba_haps.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/toshiba_haps.c
--- linux-libre-3.16-gnu/drivers/platform/x86/toshiba_haps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/toshiba_haps.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,265 @@
+/*
+ * Toshiba HDD Active Protection Sensor (HAPS) driver
+ *
+ * Copyright (C) 2014 Azael Avalos <coproscefalo@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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+
+MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>");
+MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor");
+MODULE_LICENSE("GPL");
+
+struct toshiba_haps_dev {
+	struct acpi_device *acpi_dev;
+
+	int protection_level;
+};
+
+static struct toshiba_haps_dev *toshiba_haps;
+
+/* HAPS functions */
+static int toshiba_haps_reset_protection(acpi_handle handle)
+{
+	acpi_status status;
+
+	status = acpi_evaluate_object(handle, "RSSS", NULL, NULL);
+	if (ACPI_FAILURE(status)) {
+		pr_err("Unable to reset the HDD protection\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int toshiba_haps_protection_level(acpi_handle handle, int level)
+{
+	acpi_status status;
+
+	status = acpi_execute_simple_method(handle, "PTLV", level);
+	if (ACPI_FAILURE(status)) {
+		pr_err("Error while setting the protection level\n");
+		return -EIO;
+	}
+
+	pr_info("HDD protection level set to: %d\n", level);
+
+	return 0;
+}
+
+/* sysfs files */
+static ssize_t protection_level_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%i\n", haps->protection_level);
+}
+
+static ssize_t protection_level_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
+	int level, ret;
+
+	if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3)
+		return -EINVAL;
+
+	/* Set the sensor level.
+	 * Acceptable levels are:
+	 * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High
+	 */
+	ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level);
+	if (ret != 0)
+		return ret;
+
+	haps->protection_level = level;
+
+	return count;
+}
+
+static ssize_t reset_protection_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
+	int reset, ret;
+
+	if (sscanf(buf, "%d", &reset) != 1 || reset != 1)
+		return -EINVAL;
+
+	/* Reset the protection interface */
+	ret = toshiba_haps_reset_protection(haps->acpi_dev->handle);
+	if (ret != 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR,
+		   protection_level_show, protection_level_store);
+static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store);
+
+static struct attribute *haps_attributes[] = {
+	&dev_attr_protection_level.attr,
+	&dev_attr_reset_protection.attr,
+	NULL,
+};
+
+static struct attribute_group haps_attr_group = {
+	.attrs = haps_attributes,
+};
+
+/*
+ * ACPI stuff
+ */
+static void toshiba_haps_notify(struct acpi_device *device, u32 event)
+{
+	pr_info("Received event: 0x%x", event);
+
+	acpi_bus_generate_netlink_event(device->pnp.device_class,
+					dev_name(&device->dev),
+					event, 0);
+}
+
+static int toshiba_haps_remove(struct acpi_device *device)
+{
+	sysfs_remove_group(&device->dev.kobj, &haps_attr_group);
+
+	if (toshiba_haps)
+		toshiba_haps = NULL;
+
+	return 0;
+}
+
+/* Helper function */
+static int toshiba_haps_available(acpi_handle handle)
+{
+	acpi_status status;
+	u64 hdd_present;
+
+	/*
+	 * A non existent device as well as having (only)
+	 * Solid State Drives can cause the call to fail.
+	 */
+	status = acpi_evaluate_integer(handle, "_STA", NULL,
+				       &hdd_present);
+	if (ACPI_FAILURE(status) || !hdd_present) {
+		pr_info("HDD protection not available or using SSD\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int toshiba_haps_add(struct acpi_device *acpi_dev)
+{
+	struct toshiba_haps_dev *haps;
+	int ret;
+
+	if (toshiba_haps)
+		return -EBUSY;
+
+	if (!toshiba_haps_available(acpi_dev->handle))
+		return -ENODEV;
+
+	pr_info("Toshiba HDD Active Protection Sensor device\n");
+
+	haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL);
+	if (!haps)
+		return -ENOMEM;
+
+	haps->acpi_dev = acpi_dev;
+	haps->protection_level = 2;
+	acpi_dev->driver_data = haps;
+	dev_set_drvdata(&acpi_dev->dev, haps);
+
+	/* Set the protection level, currently at level 2 (Medium) */
+	ret = toshiba_haps_protection_level(acpi_dev->handle, 2);
+	if (ret != 0)
+		return ret;
+
+	ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group);
+	if (ret)
+		return ret;
+
+	toshiba_haps = haps;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int toshiba_haps_suspend(struct device *device)
+{
+	struct toshiba_haps_dev *haps;
+	int ret;
+
+	haps = acpi_driver_data(to_acpi_device(device));
+
+	/* Deactivate the protection on suspend */
+	ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0);
+
+	return ret;
+}
+
+static int toshiba_haps_resume(struct device *device)
+{
+	struct toshiba_haps_dev *haps;
+	int ret;
+
+	haps = acpi_driver_data(to_acpi_device(device));
+
+	/* Set the stored protection level */
+	ret = toshiba_haps_protection_level(haps->acpi_dev->handle,
+					    haps->protection_level);
+
+	/* Reset the protection on resume */
+	ret = toshiba_haps_reset_protection(haps->acpi_dev->handle);
+	if (ret != 0)
+		return ret;
+
+	return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(toshiba_haps_pm,
+			 toshiba_haps_suspend, toshiba_haps_resume);
+
+static const struct acpi_device_id haps_device_ids[] = {
+	{"TOS620A", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, haps_device_ids);
+
+static struct acpi_driver toshiba_haps_driver = {
+	.name = "Toshiba HAPS",
+	.owner = THIS_MODULE,
+	.ids = haps_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+	.ops = {
+		.add =		toshiba_haps_add,
+		.remove =	toshiba_haps_remove,
+		.notify =	toshiba_haps_notify,
+	},
+	.drv.pm = &toshiba_haps_pm,
+};
+
+module_acpi_driver(toshiba_haps_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/platform/x86/wmi.c linux-libre-3.17-rc7-gnu/drivers/platform/x86/wmi.c
--- linux-libre-3.16-gnu/drivers/platform/x86/wmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/platform/x86/wmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(str
 	block = &wblock->gblock;
 	handle = wblock->handle;
 
-	if (!block)
-		return AE_NOT_EXIST;
-
-
 	snprintf(method, 5, "WE%02X", block->notify_id);
 	status = acpi_execute_simple_method(handle, method, enable);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pnp/pnpacpi/core.c linux-libre-3.17-rc7-gnu/drivers/pnp/pnpacpi/core.c
--- linux-libre-3.16-gnu/drivers/pnp/pnpacpi/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pnp/pnpacpi/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -67,8 +67,8 @@ static int pnpacpi_set_resources(struct
 
 	pnp_dbg(&dev->dev, "set resources\n");
 
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+	acpi_dev = ACPI_COMPANION(&dev->dev);
+	if (!acpi_dev) {
 		dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
 		return -ENODEV;
 	}
@@ -76,6 +76,7 @@ static int pnpacpi_set_resources(struct
 	if (WARN_ON_ONCE(acpi_dev != dev->data))
 		dev->data = acpi_dev;
 
+	handle = acpi_dev->handle;
 	if (acpi_has_method(handle, METHOD_NAME__SRS)) {
 		struct acpi_buffer buffer;
 
@@ -93,8 +94,8 @@ static int pnpacpi_set_resources(struct
 		}
 		kfree(buffer.pointer);
 	}
-	if (!ret && acpi_bus_power_manageable(handle))
-		ret = acpi_bus_set_power(handle, ACPI_STATE_D0);
+	if (!ret && acpi_device_power_manageable(acpi_dev))
+		ret = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
 
 	return ret;
 }
@@ -102,23 +103,22 @@ static int pnpacpi_set_resources(struct
 static int pnpacpi_disable_resources(struct pnp_dev *dev)
 {
 	struct acpi_device *acpi_dev;
-	acpi_handle handle;
 	acpi_status status;
 
 	dev_dbg(&dev->dev, "disable resources\n");
 
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+	acpi_dev = ACPI_COMPANION(&dev->dev);
+	if (!acpi_dev) {
 		dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
 		return 0;
 	}
 
 	/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
-	if (acpi_bus_power_manageable(handle))
-		acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
+	if (acpi_device_power_manageable(acpi_dev))
+		acpi_device_set_power(acpi_dev, ACPI_STATE_D3_COLD);
 
-	/* continue even if acpi_bus_set_power() fails */
-	status = acpi_evaluate_object(handle, "_DIS", NULL, NULL);
+	/* continue even if acpi_device_set_power() fails */
+	status = acpi_evaluate_object(acpi_dev->handle, "_DIS", NULL, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
 		return -ENODEV;
 
@@ -128,26 +128,22 @@ static int pnpacpi_disable_resources(str
 #ifdef CONFIG_ACPI_SLEEP
 static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
 {
-	struct acpi_device *acpi_dev;
-	acpi_handle handle;
+	struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
 
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+	if (!acpi_dev) {
 		dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
 		return false;
 	}
 
-	return acpi_bus_can_wakeup(handle);
+	return acpi_bus_can_wakeup(acpi_dev->handle);
 }
 
 static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
 {
-	struct acpi_device *acpi_dev;
-	acpi_handle handle;
+	struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
 	int error = 0;
 
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+	if (!acpi_dev) {
 		dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
 		return 0;
 	}
@@ -159,7 +155,7 @@ static int pnpacpi_suspend(struct pnp_de
 			return error;
 	}
 
-	if (acpi_bus_power_manageable(handle)) {
+	if (acpi_device_power_manageable(acpi_dev)) {
 		int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
 							ACPI_STATE_D3_COLD);
 		if (power_state < 0)
@@ -167,12 +163,12 @@ static int pnpacpi_suspend(struct pnp_de
 					ACPI_STATE_D0 : ACPI_STATE_D3_COLD;
 
 		/*
-		 * acpi_bus_set_power() often fails (keyboard port can't be
+		 * acpi_device_set_power() can fail (keyboard port can't be
 		 * powered-down?), and in any case, our return value is ignored
 		 * by pnp_bus_suspend().  Hence we don't revert the wakeup
 		 * setting if the set_power fails.
 		 */
-		error = acpi_bus_set_power(handle, power_state);
+		error = acpi_device_set_power(acpi_dev, power_state);
 	}
 
 	return error;
@@ -180,11 +176,10 @@ static int pnpacpi_suspend(struct pnp_de
 
 static int pnpacpi_resume(struct pnp_dev *dev)
 {
-	struct acpi_device *acpi_dev;
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
 	int error = 0;
 
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+	if (!acpi_dev) {
 		dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
 		return -ENODEV;
 	}
@@ -192,8 +187,8 @@ static int pnpacpi_resume(struct pnp_dev
 	if (device_may_wakeup(&dev->dev))
 		acpi_pm_device_sleep_wake(&dev->dev, false);
 
-	if (acpi_bus_power_manageable(handle))
-		error = acpi_bus_set_power(handle, ACPI_STATE_D0);
+	if (acpi_device_power_manageable(acpi_dev))
+		error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
 
 	return error;
 }
@@ -295,9 +290,11 @@ static int __init pnpacpi_add_device(str
 		return error;
 	}
 
+	error = acpi_bind_one(&dev->dev, device);
+
 	num++;
 
-	return 0;
+	return error;
 }
 
 static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
@@ -313,40 +310,6 @@ static acpi_status __init pnpacpi_add_de
 	return AE_OK;
 }
 
-static int __init acpi_pnp_match(struct device *dev, void *_pnp)
-{
-	struct acpi_device *acpi = to_acpi_device(dev);
-	struct pnp_dev *pnp = _pnp;
-
-	/* true means it matched */
-	return pnp->data == acpi;
-}
-
-static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev)
-{
-	dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev),
-			      acpi_pnp_match);
-	if (!dev)
-		return NULL;
-
-	put_device(dev);
-	return to_acpi_device(dev);
-}
-
-/* complete initialization of a PNPACPI device includes having
- * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling.
- */
-static bool acpi_pnp_bus_match(struct device *dev)
-{
-	return dev->bus == &pnp_bus_type;
-}
-
-static struct acpi_bus_type __initdata acpi_pnp_bus = {
-	.name	     = "PNP",
-	.match	     = acpi_pnp_bus_match,
-	.find_companion = acpi_pnp_find_companion,
-};
-
 int pnpacpi_disabled __initdata;
 static int __init pnpacpi_init(void)
 {
@@ -356,10 +319,8 @@ static int __init pnpacpi_init(void)
 	}
 	printk(KERN_INFO "pnp: PnP ACPI init\n");
 	pnp_register_protocol(&pnpacpi_protocol);
-	register_acpi_bus_type(&acpi_pnp_bus);
 	acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
 	printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num);
-	unregister_acpi_bus_type(&acpi_pnp_bus);
 	pnp_platform_devices = 1;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/bq2415x_charger.c linux-libre-3.17-rc7-gnu/drivers/power/bq2415x_charger.c
--- linux-libre-3.16-gnu/drivers/power/bq2415x_charger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/bq2415x_charger.c	2014-09-28 17:29:07.000000000 -0400
@@ -840,8 +840,7 @@ static int bq2415x_notifier_call(struct
 	if (bq->automode < 1)
 		return NOTIFY_OK;
 
-	sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
-	bq2415x_set_mode(bq, bq->reported_mode);
+	schedule_delayed_work(&bq->work, 0);
 
 	return NOTIFY_OK;
 }
@@ -892,6 +891,11 @@ static void bq2415x_timer_work(struct wo
 	int error;
 	int boost;
 
+	if (bq->automode > 0 && (bq->reported_mode != bq->mode)) {
+		sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
+		bq2415x_set_mode(bq, bq->reported_mode);
+	}
+
 	if (!bq->autotimer)
 		return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/bq27x00_battery.c linux-libre-3.17-rc7-gnu/drivers/power/bq27x00_battery.c
--- linux-libre-3.16-gnu/drivers/power/bq27x00_battery.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/bq27x00_battery.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@
  * http://www.ti.com/product/bq27425-g1
  */
 
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/jiffies.h>
@@ -415,6 +416,9 @@ static void bq27x00_update(struct bq27x0
 	bool is_bq27425 = di->chip == BQ27425;
 
 	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
+	if ((cache.flags & 0xff) == 0xff)
+		/* read error */
+		cache.flags = -1;
 	if (cache.flags >= 0) {
 		if (!is_bq27500 && !is_bq27425
 				&& (cache.flags & BQ27000_FLAG_CI)) {
@@ -804,7 +808,7 @@ static int bq27x00_battery_probe(struct
 		goto batt_failed_1;
 	}
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
 	if (!di) {
 		dev_err(&client->dev, "failed to allocate device info data\n");
 		retval = -ENOMEM;
@@ -819,14 +823,12 @@ static int bq27x00_battery_probe(struct
 
 	retval = bq27x00_powersupply_init(di);
 	if (retval)
-		goto batt_failed_3;
+		goto batt_failed_2;
 
 	i2c_set_clientdata(client, di);
 
 	return 0;
 
-batt_failed_3:
-	kfree(di);
 batt_failed_2:
 	kfree(name);
 batt_failed_1:
@@ -849,8 +851,6 @@ static int bq27x00_battery_remove(struct
 	idr_remove(&battery_id, di->id);
 	mutex_unlock(&battery_mutex);
 
-	kfree(di);
-
 	return 0;
 }
 
@@ -933,7 +933,6 @@ static int bq27000_battery_probe(struct
 {
 	struct bq27x00_device_info *di;
 	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
-	int ret;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform_data supplied\n");
@@ -945,7 +944,7 @@ static int bq27000_battery_probe(struct
 		return -EINVAL;
 	}
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
 	if (!di) {
 		dev_err(&pdev->dev, "failed to allocate device info data\n");
 		return -ENOMEM;
@@ -959,16 +958,7 @@ static int bq27000_battery_probe(struct
 	di->bat.name = pdata->name ?: dev_name(&pdev->dev);
 	di->bus.read = &bq27000_read_platform;
 
-	ret = bq27x00_powersupply_init(di);
-	if (ret)
-		goto err_free;
-
-	return 0;
-
-err_free:
-	kfree(di);
-
-	return ret;
+	return bq27x00_powersupply_init(di);
 }
 
 static int bq27000_battery_remove(struct platform_device *pdev)
@@ -977,8 +967,6 @@ static int bq27000_battery_remove(struct
 
 	bq27x00_powersupply_unregister(di);
 
-	kfree(di);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/ipaq_micro_battery.c linux-libre-3.17-rc7-gnu/drivers/power/ipaq_micro_battery.c
--- linux-libre-3.16-gnu/drivers/power/ipaq_micro_battery.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/power/ipaq_micro_battery.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,290 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * h3xxx atmel micro companion support, battery subdevice
+ * based on previous kernel 2.4 version
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ipaq-micro.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+
+#define BATT_PERIOD 100000 /* 100 seconds in milliseconds */
+
+#define MICRO_BATT_CHEM_ALKALINE	0x01
+#define MICRO_BATT_CHEM_NICD		0x02
+#define MICRO_BATT_CHEM_NIMH		0x03
+#define MICRO_BATT_CHEM_LION		0x04
+#define MICRO_BATT_CHEM_LIPOLY		0x05
+#define MICRO_BATT_CHEM_NOT_INSTALLED	0x06
+#define MICRO_BATT_CHEM_UNKNOWN		0xff
+
+#define MICRO_BATT_STATUS_HIGH		0x01
+#define MICRO_BATT_STATUS_LOW		0x02
+#define MICRO_BATT_STATUS_CRITICAL	0x04
+#define MICRO_BATT_STATUS_CHARGING	0x08
+#define MICRO_BATT_STATUS_CHARGEMAIN	0x10
+#define MICRO_BATT_STATUS_DEAD		0x20 /* Battery will not charge */
+#define MICRO_BATT_STATUS_NOTINSTALLED	0x20 /* For expansion pack batteries */
+#define MICRO_BATT_STATUS_FULL		0x40 /* Battery fully charged */
+#define MICRO_BATT_STATUS_NOBATTERY	0x80
+#define MICRO_BATT_STATUS_UNKNOWN	0xff
+
+struct micro_battery {
+	struct ipaq_micro *micro;
+	struct workqueue_struct *wq;
+	struct delayed_work update;
+	u8 ac;
+	u8 chemistry;
+	unsigned int voltage;
+	u16 temperature;
+	u8 flag;
+};
+
+static void micro_battery_work(struct work_struct *work)
+{
+	struct micro_battery *mb = container_of(work,
+				struct micro_battery, update.work);
+	struct ipaq_micro_msg msg_battery = {
+		.id = MSG_BATTERY,
+	};
+	struct ipaq_micro_msg msg_sensor = {
+		.id = MSG_THERMAL_SENSOR,
+	};
+
+	/* First send battery message */
+	ipaq_micro_tx_msg_sync(mb->micro, &msg_battery);
+	if (msg_battery.rx_len < 4)
+		pr_info("ERROR");
+
+	/*
+	 * Returned message format:
+	 * byte 0:   0x00 = Not plugged in
+	 *           0x01 = AC adapter plugged in
+	 * byte 1:   chemistry
+	 * byte 2:   voltage LSB
+	 * byte 3:   voltage MSB
+	 * byte 4:   flags
+	 * byte 5-9: same for battery 2
+	 */
+	mb->ac = msg_battery.rx_data[0];
+	mb->chemistry = msg_battery.rx_data[1];
+	mb->voltage = ((((unsigned short)msg_battery.rx_data[3] << 8) +
+			msg_battery.rx_data[2]) * 5000L) * 1000 / 1024;
+	mb->flag = msg_battery.rx_data[4];
+
+	if (msg_battery.rx_len == 9)
+		pr_debug("second battery ignored\n");
+
+	/* Then read the sensor */
+	ipaq_micro_tx_msg_sync(mb->micro, &msg_sensor);
+	mb->temperature = msg_sensor.rx_data[1] << 8 | msg_sensor.rx_data[0];
+
+	queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
+}
+
+static int get_capacity(struct power_supply *b)
+{
+	struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+	switch (mb->flag & 0x07) {
+	case MICRO_BATT_STATUS_HIGH:
+		return 100;
+		break;
+	case MICRO_BATT_STATUS_LOW:
+		return 50;
+		break;
+	case MICRO_BATT_STATUS_CRITICAL:
+		return 5;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int get_status(struct power_supply *b)
+{
+	struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+	if (mb->flag == MICRO_BATT_STATUS_UNKNOWN)
+		return POWER_SUPPLY_STATUS_UNKNOWN;
+
+	if (mb->flag & MICRO_BATT_STATUS_FULL)
+		return POWER_SUPPLY_STATUS_FULL;
+
+	if ((mb->flag & MICRO_BATT_STATUS_CHARGING) ||
+		(mb->flag & MICRO_BATT_STATUS_CHARGEMAIN))
+		return POWER_SUPPLY_STATUS_CHARGING;
+
+	return POWER_SUPPLY_STATUS_DISCHARGING;
+}
+
+static int micro_batt_get_property(struct power_supply *b,
+					enum power_supply_property psp,
+					union power_supply_propval *val)
+{
+	struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		switch (mb->chemistry) {
+		case MICRO_BATT_CHEM_NICD:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd;
+			break;
+		case MICRO_BATT_CHEM_NIMH:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+			break;
+		case MICRO_BATT_CHEM_LION:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+			break;
+		case MICRO_BATT_CHEM_LIPOLY:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+			break;
+		default:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+			break;
+		};
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = get_status(b);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = 4700000;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = get_capacity(b);
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = mb->temperature;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = mb->voltage;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static int micro_ac_get_property(struct power_supply *b,
+				 enum power_supply_property psp,
+				 union power_supply_propval *val)
+{
+	struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = mb->ac;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static enum power_supply_property micro_batt_power_props[] = {
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static struct power_supply micro_batt_power = {
+	.name			= "main-battery",
+	.type			= POWER_SUPPLY_TYPE_BATTERY,
+	.properties		= micro_batt_power_props,
+	.num_properties		= ARRAY_SIZE(micro_batt_power_props),
+	.get_property		= micro_batt_get_property,
+	.use_for_apm		= 1,
+};
+
+static enum power_supply_property micro_ac_power_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply micro_ac_power = {
+	.name			= "ac",
+	.type			= POWER_SUPPLY_TYPE_MAINS,
+	.properties		= micro_ac_power_props,
+	.num_properties		= ARRAY_SIZE(micro_ac_power_props),
+	.get_property		= micro_ac_get_property,
+};
+
+static int micro_batt_probe(struct platform_device *pdev)
+{
+	struct micro_battery *mb;
+
+	mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
+	if (!mb)
+		return -ENOMEM;
+
+	mb->micro = dev_get_drvdata(pdev->dev.parent);
+	mb->wq = create_singlethread_workqueue("ipaq-battery-wq");
+	INIT_DELAYED_WORK(&mb->update, micro_battery_work);
+	platform_set_drvdata(pdev, mb);
+	queue_delayed_work(mb->wq, &mb->update, 1);
+	power_supply_register(&pdev->dev, &micro_batt_power);
+	power_supply_register(&pdev->dev, &micro_ac_power);
+
+	dev_info(&pdev->dev, "iPAQ micro battery driver\n");
+	return 0;
+}
+
+static int micro_batt_remove(struct platform_device *pdev)
+
+{
+	struct micro_battery *mb = platform_get_drvdata(pdev);
+
+	power_supply_unregister(&micro_ac_power);
+	power_supply_unregister(&micro_batt_power);
+	cancel_delayed_work_sync(&mb->update);
+
+	return 0;
+}
+
+static int micro_batt_suspend(struct device *dev)
+{
+	struct micro_battery *mb = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&mb->update);
+	return 0;
+}
+
+static int micro_batt_resume(struct device *dev)
+{
+	struct micro_battery *mb = dev_get_drvdata(dev);
+
+	queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
+	return 0;
+}
+
+static const struct dev_pm_ops micro_batt_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(micro_batt_suspend, micro_batt_resume)
+};
+
+static struct platform_driver micro_batt_device_driver = {
+	.driver		= {
+		.name	= "ipaq-micro-battery",
+		.pm	= &micro_batt_dev_pm_ops,
+	},
+	.probe		= micro_batt_probe,
+	.remove		= micro_batt_remove,
+};
+module_platform_driver(micro_batt_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro battery");
+MODULE_ALIAS("platform:battery-ipaq-micro");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/Kconfig linux-libre-3.17-rc7-gnu/drivers/power/Kconfig
--- linux-libre-3.16-gnu/drivers/power/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -137,6 +137,13 @@ config BATTERY_COLLIE
 	  Say Y to enable support for the battery on the Sharp Zaurus
 	  SL-5500 (collie) models.
 
+config BATTERY_IPAQ_MICRO
+	tristate "iPAQ Atmel Micro ASIC battery driver"
+	depends on MFD_IPAQ_MICRO
+	help
+	  Choose this option if you want to monitor battery status on
+	  Compaq/HP iPAQ h3100 and h3600.
+
 config BATTERY_WM97XX
 	bool "WM97xx generic battery driver"
 	depends on TOUCHSCREEN_WM97XX=y
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/Makefile linux-libre-3.17-rc7-gnu/drivers/power/Makefile
--- linux-libre-3.16-gnu/drivers/power/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,7 @@ obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery
 obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
 obj-$(CONFIG_BATTERY_TOSA)	+= tosa_battery.o
 obj-$(CONFIG_BATTERY_COLLIE)	+= collie_battery.o
+obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)	+= wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)	+= sbs-battery.o
 obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/power_supply_core.c linux-libre-3.17-rc7-gnu/drivers/power/power_supply_core.c
--- linux-libre-3.16-gnu/drivers/power/power_supply_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/power_supply_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -537,7 +537,8 @@ static void psy_unregister_cooler(struct
 }
 #endif
 
-int __power_supply_register(struct device *parent, struct power_supply *psy, bool ws)
+static int __power_supply_register(struct device *parent,
+				   struct power_supply *psy, bool ws)
 {
 	struct device *dev;
 	int rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/power_supply_sysfs.c linux-libre-3.17-rc7-gnu/drivers/power/power_supply_sysfs.c
--- linux-libre-3.16-gnu/drivers/power/power_supply_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/power_supply_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,6 +167,7 @@ static struct device_attribute power_sup
 	POWER_SUPPLY_ATTR(constant_charge_voltage_max),
 	POWER_SUPPLY_ATTR(charge_control_limit),
 	POWER_SUPPLY_ATTR(charge_control_limit_max),
+	POWER_SUPPLY_ATTR(input_current_limit),
 	POWER_SUPPLY_ATTR(energy_full_design),
 	POWER_SUPPLY_ATTR(energy_empty_design),
 	POWER_SUPPLY_ATTR(energy_full),
@@ -178,6 +179,8 @@ static struct device_attribute power_sup
 	POWER_SUPPLY_ATTR(capacity_alert_max),
 	POWER_SUPPLY_ATTR(capacity_level),
 	POWER_SUPPLY_ATTR(temp),
+	POWER_SUPPLY_ATTR(temp_max),
+	POWER_SUPPLY_ATTR(temp_min),
 	POWER_SUPPLY_ATTR(temp_alert_min),
 	POWER_SUPPLY_ATTR(temp_alert_max),
 	POWER_SUPPLY_ATTR(temp_ambient),
@@ -189,6 +192,7 @@ static struct device_attribute power_sup
 	POWER_SUPPLY_ATTR(time_to_full_avg),
 	POWER_SUPPLY_ATTR(type),
 	POWER_SUPPLY_ATTR(scope),
+	POWER_SUPPLY_ATTR(charge_term_current),
 	/* Properties of type `const char *' */
 	POWER_SUPPLY_ATTR(model_name),
 	POWER_SUPPLY_ATTR(manufacturer),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/brcmstb-reboot.c linux-libre-3.17-rc7-gnu/drivers/power/reset/brcmstb-reboot.c
--- linux-libre-3.16-gnu/drivers/power/reset/brcmstb-reboot.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/brcmstb-reboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 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 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/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+#include <linux/smp.h>
+#include <linux/mfd/syscon.h>
+
+#include <asm/system_misc.h>
+
+#define RESET_SOURCE_ENABLE_REG 1
+#define SW_MASTER_RESET_REG 2
+
+static struct regmap *regmap;
+static u32 rst_src_en;
+static u32 sw_mstr_rst;
+
+static void brcmstb_reboot(enum reboot_mode mode, const char *cmd)
+{
+	int rc;
+	u32 tmp;
+
+	rc = regmap_write(regmap, rst_src_en, 1);
+	if (rc) {
+		pr_err("failed to write rst_src_en (%d)\n", rc);
+		return;
+	}
+
+	rc = regmap_read(regmap, rst_src_en, &tmp);
+	if (rc) {
+		pr_err("failed to read rst_src_en (%d)\n", rc);
+		return;
+	}
+
+	rc = regmap_write(regmap, sw_mstr_rst, 1);
+	if (rc) {
+		pr_err("failed to write sw_mstr_rst (%d)\n", rc);
+		return;
+	}
+
+	rc = regmap_read(regmap, sw_mstr_rst, &tmp);
+	if (rc) {
+		pr_err("failed to read sw_mstr_rst (%d)\n", rc);
+		return;
+	}
+
+	while (1)
+		;
+}
+
+static int brcmstb_reboot_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct device_node *np = pdev->dev.of_node;
+
+	regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
+	if (IS_ERR(regmap)) {
+		pr_err("failed to get syscon phandle\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_index(np, "syscon", RESET_SOURCE_ENABLE_REG,
+					&rst_src_en);
+	if (rc) {
+		pr_err("can't get rst_src_en offset (%d)\n", rc);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_index(np, "syscon", SW_MASTER_RESET_REG,
+					&sw_mstr_rst);
+	if (rc) {
+		pr_err("can't get sw_mstr_rst offset (%d)\n", rc);
+		return -EINVAL;
+	}
+
+	arm_pm_restart = brcmstb_reboot;
+
+	return 0;
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "brcm,brcmstb-reboot", },
+	{},
+};
+
+static struct platform_driver brcmstb_reboot_driver = {
+	.probe = brcmstb_reboot_probe,
+	.driver = {
+		.name = "brcmstb-reboot",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match,
+	},
+};
+
+static int __init brcmstb_reboot_init(void)
+{
+	return platform_driver_probe(&brcmstb_reboot_driver,
+					brcmstb_reboot_probe);
+}
+subsys_initcall(brcmstb_reboot_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/gpio-poweroff.c linux-libre-3.17-rc7-gnu/drivers/power/reset/gpio-poweroff.c
--- linux-libre-3.16-gnu/drivers/power/reset/gpio-poweroff.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/gpio-poweroff.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,31 +15,29 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/module.h>
 
 /*
  * Hold configuration here, cannot be more than one instance of the driver
  * since pm_power_off itself is global.
  */
-static int gpio_num = -1;
-static int gpio_active_low;
+static struct gpio_desc *reset_gpio;
 
 static void gpio_poweroff_do_poweroff(void)
 {
-	BUG_ON(!gpio_is_valid(gpio_num));
+	BUG_ON(!reset_gpio);
 
 	/* drive it active, also inactive->active edge */
-	gpio_direction_output(gpio_num, !gpio_active_low);
+	gpiod_direction_output(reset_gpio, 1);
 	mdelay(100);
 	/* drive inactive, also active->inactive edge */
-	gpio_set_value(gpio_num, gpio_active_low);
+	gpiod_set_value(reset_gpio, 0);
 	mdelay(100);
 
 	/* drive it active, also inactive->active edge */
-	gpio_set_value(gpio_num, !gpio_active_low);
+	gpiod_set_value(reset_gpio, 1);
 
 	/* give it some time */
 	mdelay(3000);
@@ -49,54 +47,42 @@ static void gpio_poweroff_do_poweroff(vo
 
 static int gpio_poweroff_probe(struct platform_device *pdev)
 {
-	enum of_gpio_flags flags;
 	bool input = false;
-	int ret;
 
 	/* If a pm_power_off function has already been added, leave it alone */
 	if (pm_power_off != NULL) {
-		pr_err("%s: pm_power_off function already registered",
+		dev_err(&pdev->dev,
+			"%s: pm_power_off function already registered",
 		       __func__);
 		return -EBUSY;
 	}
 
-	gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
-	if (!gpio_is_valid(gpio_num))
-		return gpio_num;
-
-	gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+	reset_gpio = devm_gpiod_get(&pdev->dev, NULL);
+	if (IS_ERR(reset_gpio))
+		return PTR_ERR(reset_gpio);
 
 	input = of_property_read_bool(pdev->dev.of_node, "input");
 
-	ret = gpio_request(gpio_num, "poweroff-gpio");
-	if (ret) {
-		pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
-		return ret;
-	}
 	if (input) {
-		if (gpio_direction_input(gpio_num)) {
-			pr_err("Could not set direction of GPIO %d to input",
-			       gpio_num);
-			goto err;
+		if (gpiod_direction_input(reset_gpio)) {
+			dev_err(&pdev->dev,
+				"Could not set direction of reset GPIO to input\n");
+			return -ENODEV;
 		}
 	} else {
-		if (gpio_direction_output(gpio_num, gpio_active_low)) {
-			pr_err("Could not set direction of GPIO %d", gpio_num);
-			goto err;
+		if (gpiod_direction_output(reset_gpio, 0)) {
+			dev_err(&pdev->dev,
+				"Could not set direction of reset GPIO\n");
+			return -ENODEV;
 		}
 	}
 
 	pm_power_off = &gpio_poweroff_do_poweroff;
 	return 0;
-
-err:
-	gpio_free(gpio_num);
-	return -ENODEV;
 }
 
 static int gpio_poweroff_remove(struct platform_device *pdev)
 {
-	gpio_free(gpio_num);
 	if (pm_power_off == &gpio_poweroff_do_poweroff)
 		pm_power_off = NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/hisi-reboot.c linux-libre-3.17-rc7-gnu/drivers/power/reset/hisi-reboot.c
--- linux-libre-3.16-gnu/drivers/power/reset/hisi-reboot.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/hisi-reboot.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * Hisilicon SoC reset code
+ *
+ * Copyright (c) 2014 Hisilicon Ltd.
+ * Copyright (c) 2014 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/proc-fns.h>
+#include <asm/system_misc.h>
+
+static void __iomem *base;
+static u32 reboot_offset;
+
+static void hisi_restart(enum reboot_mode mode, const char *cmd)
+{
+	writel_relaxed(0xdeadbeef, base + reboot_offset);
+
+	while (1)
+		cpu_do_idle();
+}
+
+static int hisi_reboot_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		WARN(1, "failed to map base address");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
+		pr_err("failed to find reboot-offset property\n");
+		return -EINVAL;
+	}
+
+	arm_pm_restart = hisi_restart;
+
+	return 0;
+}
+
+static struct of_device_id hisi_reboot_of_match[] = {
+	{ .compatible = "hisilicon,sysctrl" },
+	{}
+};
+
+static struct platform_driver hisi_reboot_driver = {
+	.probe = hisi_reboot_probe,
+	.driver = {
+		.name = "hisi-reboot",
+		.of_match_table = hisi_reboot_of_match,
+	},
+};
+module_platform_driver(hisi_reboot_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/Kconfig linux-libre-3.17-rc7-gnu/drivers/power/reset/Kconfig
--- linux-libre-3.16-gnu/drivers/power/reset/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,17 @@ config POWER_RESET_AXXIA
 
 	  Say Y if you have an Axxia family SoC.
 
+config POWER_RESET_BRCMSTB
+	bool "Broadcom STB reset driver" if COMPILE_TEST
+	depends on POWER_RESET && ARM
+	default ARCH_BRCMSTB
+	help
+	  This driver provides restart support for ARM-based Broadcom STB
+	  boards.
+
+	  Say Y here if you have an ARM-based Broadcom STB board and you wish
+	  to have restart support.
+
 config POWER_RESET_GPIO
 	bool "GPIO power-off driver"
 	depends on OF_GPIO && POWER_RESET
@@ -28,6 +39,12 @@ config POWER_RESET_GPIO
 	  If your board needs a GPIO high/low to power down, say Y and
 	  create a binding in your devicetree.
 
+config POWER_RESET_HISI
+	bool "Hisilicon power-off driver"
+	depends on POWER_RESET && ARCH_HISI
+	help
+	  Reboot support for Hisilicon boards.
+
 config POWER_RESET_MSM
 	bool "Qualcomm MSM power-off driver"
 	depends on POWER_RESET && ARCH_QCOM
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/Makefile linux-libre-3.17-rc7-gnu/drivers/power/reset/Makefile
--- linux-libre-3.16-gnu/drivers/power/reset/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,8 @@
 obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
+obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
+obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/reset/restart-poweroff.c linux-libre-3.17-rc7-gnu/drivers/power/reset/restart-poweroff.c
--- linux-libre-3.16-gnu/drivers/power/reset/restart-poweroff.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/reset/restart-poweroff.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,5 +62,5 @@ module_platform_driver(restart_poweroff_
 
 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch");
 MODULE_DESCRIPTION("restart poweroff driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:poweroff-restart");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/rx51_battery.c linux-libre-3.17-rc7-gnu/drivers/power/rx51_battery.c
--- linux-libre-3.16-gnu/drivers/power/rx51_battery.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/rx51_battery.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,34 +24,27 @@
 #include <linux/power_supply.h>
 #include <linux/slab.h>
 #include <linux/i2c/twl4030-madc.h>
-
-/* RX51 specific channels */
-#define TWL4030_MADC_BTEMP_RX51	TWL4030_MADC_ADCIN0
-#define TWL4030_MADC_BCI_RX51	TWL4030_MADC_ADCIN4
+#include <linux/iio/consumer.h>
+#include <linux/of.h>
 
 struct rx51_device_info {
 	struct device *dev;
 	struct power_supply bat;
+	struct iio_channel *channel_temp;
+	struct iio_channel *channel_bsi;
+	struct iio_channel *channel_vbat;
 };
 
 /*
  * Read ADCIN channel value, code copied from maemo kernel
  */
-static int rx51_battery_read_adc(int channel)
+static int rx51_battery_read_adc(struct iio_channel *channel)
 {
-	struct twl4030_madc_request req;
-
-	req.channels = channel;
-	req.do_avg = 1;
-	req.method = TWL4030_MADC_SW1;
-	req.func_cb = NULL;
-	req.type = TWL4030_MADC_WAIT;
-	req.raw = true;
-
-	if (twl4030_madc_conversion(&req) <= 0)
-		return -ENODATA;
-
-	return req.rbuf[ffs(channel) - 1];
+	int val, err;
+	err = iio_read_channel_average_raw(channel, &val);
+	if (err < 0)
+		return err;
+	return val;
 }
 
 /*
@@ -60,10 +53,12 @@ static int rx51_battery_read_adc(int cha
  */
 static int rx51_battery_read_voltage(struct rx51_device_info *di)
 {
-	int voltage = rx51_battery_read_adc(TWL4030_MADC_VBAT);
+	int voltage = rx51_battery_read_adc(di->channel_vbat);
 
-	if (voltage < 0)
+	if (voltage < 0) {
+		dev_err(di->dev, "Could not read ADC: %d\n", voltage);
 		return voltage;
+	}
 
 	return 1000 * (10000 * voltage / 1705);
 }
@@ -112,7 +107,10 @@ static int rx51_battery_read_temperature
 {
 	int min = 0;
 	int max = ARRAY_SIZE(rx51_temp_table2) - 1;
-	int raw = rx51_battery_read_adc(TWL4030_MADC_BTEMP_RX51);
+	int raw = rx51_battery_read_adc(di->channel_temp);
+
+	if (raw < 0)
+		dev_err(di->dev, "Could not read ADC: %d\n", raw);
 
 	/* Zero and negative values are undefined */
 	if (raw <= 0)
@@ -146,10 +144,12 @@ static int rx51_battery_read_temperature
  */
 static int rx51_battery_read_capacity(struct rx51_device_info *di)
 {
-	int capacity = rx51_battery_read_adc(TWL4030_MADC_BCI_RX51);
+	int capacity = rx51_battery_read_adc(di->channel_bsi);
 
-	if (capacity < 0)
+	if (capacity < 0) {
+		dev_err(di->dev, "Could not read ADC: %d\n", capacity);
 		return capacity;
+	}
 
 	return 1280 * (1200 * capacity)/(1024 - capacity);
 }
@@ -213,17 +213,46 @@ static int rx51_battery_probe(struct pla
 
 	platform_set_drvdata(pdev, di);
 
+	di->dev = &pdev->dev;
 	di->bat.name = dev_name(&pdev->dev);
 	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
 	di->bat.properties = rx51_battery_props;
 	di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
 	di->bat.get_property = rx51_battery_get_property;
 
+	di->channel_temp = iio_channel_get(di->dev, "temp");
+	if (IS_ERR(di->channel_temp)) {
+		ret = PTR_ERR(di->channel_temp);
+		goto error;
+	}
+
+	di->channel_bsi  = iio_channel_get(di->dev, "bsi");
+	if (IS_ERR(di->channel_bsi)) {
+		ret = PTR_ERR(di->channel_bsi);
+		goto error_channel_temp;
+	}
+
+	di->channel_vbat = iio_channel_get(di->dev, "vbat");
+	if (IS_ERR(di->channel_vbat)) {
+		ret = PTR_ERR(di->channel_vbat);
+		goto error_channel_bsi;
+	}
+
 	ret = power_supply_register(di->dev, &di->bat);
 	if (ret)
-		return ret;
+		goto error_channel_vbat;
 
 	return 0;
+
+error_channel_vbat:
+	iio_channel_release(di->channel_vbat);
+error_channel_bsi:
+	iio_channel_release(di->channel_bsi);
+error_channel_temp:
+	iio_channel_release(di->channel_temp);
+error:
+
+	return ret;
 }
 
 static int rx51_battery_remove(struct platform_device *pdev)
@@ -232,15 +261,28 @@ static int rx51_battery_remove(struct pl
 
 	power_supply_unregister(&di->bat);
 
+	iio_channel_release(di->channel_vbat);
+	iio_channel_release(di->channel_bsi);
+	iio_channel_release(di->channel_temp);
+
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id n900_battery_of_match[] = {
+	{.compatible = "nokia,n900-battery", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, n900_battery_of_match);
+#endif
+
 static struct platform_driver rx51_battery_driver = {
 	.probe = rx51_battery_probe,
 	.remove = rx51_battery_remove,
 	.driver = {
 		.name = "rx51-battery",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(n900_battery_of_match),
 	},
 };
 module_platform_driver(rx51_battery_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/tps65090-charger.c linux-libre-3.17-rc7-gnu/drivers/power/tps65090-charger.c
--- linux-libre-3.16-gnu/drivers/power/tps65090-charger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/tps65090-charger.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,9 +17,11 @@
  */
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -32,11 +34,15 @@
 #define TPS65090_VACG		BIT(1)
 #define TPS65090_NOITERM	BIT(5)
 
+#define POLL_INTERVAL		(HZ * 2)	/* Used when no irq */
+
 struct tps65090_charger {
 	struct	device	*dev;
 	int	ac_online;
 	int	prev_ac_online;
 	int	irq;
+	struct task_struct	*poll_task;
+	bool			passive_mode;
 	struct power_supply	ac;
 	struct tps65090_platform_data *pdata;
 };
@@ -49,6 +55,9 @@ static int tps65090_low_chrg_current(str
 {
 	int ret;
 
+	if (charger->passive_mode)
+		return 0;
+
 	ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
 			TPS65090_NOITERM);
 	if (ret < 0) {
@@ -64,6 +73,9 @@ static int tps65090_enable_charging(stru
 	int ret;
 	uint8_t ctrl0 = 0;
 
+	if (charger->passive_mode)
+		return 0;
+
 	ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
 			    &ctrl0);
 	if (ret < 0) {
@@ -87,6 +99,9 @@ static int tps65090_config_charger(struc
 	uint8_t intrmask = 0;
 	int ret;
 
+	if (charger->passive_mode)
+		return 0;
+
 	if (charger->pdata->enable_low_current_chrg) {
 		ret = tps65090_low_chrg_current(charger);
 		if (ret < 0) {
@@ -164,10 +179,14 @@ static irqreturn_t tps65090_charger_isr(
 	}
 
 	/* Clear interrupts. */
-	ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_STS, 0x00);
-	if (ret < 0) {
-		dev_err(charger->dev, "%s(): Error in writing reg 0x%x\n",
+	if (!charger->passive_mode) {
+		ret = tps65090_write(charger->dev->parent,
+				     TPS65090_REG_INTR_STS, 0x00);
+		if (ret < 0) {
+			dev_err(charger->dev,
+				"%s(): Error in writing reg 0x%x\n",
 				__func__, TPS65090_REG_INTR_STS);
+		}
 	}
 
 	if (charger->prev_ac_online != charger->ac_online)
@@ -198,6 +217,18 @@ static struct tps65090_platform_data *
 
 }
 
+static int tps65090_charger_poll_task(void *data)
+{
+	set_freezable();
+
+	while (!kthread_should_stop()) {
+		schedule_timeout_interruptible(POLL_INTERVAL);
+		try_to_freeze();
+		tps65090_charger_isr(-1, data);
+	}
+	return 0;
+}
+
 static int tps65090_charger_probe(struct platform_device *pdev)
 {
 	struct tps65090_charger *cdata;
@@ -244,22 +275,10 @@ static int tps65090_charger_probe(struct
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
-		dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq);
-		ret = irq;
-		goto fail_unregister_supply;
-	}
-
+	if (irq < 0)
+		irq = -ENXIO;
 	cdata->irq = irq;
 
-	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-		tps65090_charger_isr, 0, "tps65090-charger", cdata);
-	if (ret) {
-		dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq,
-			ret);
-		goto fail_unregister_supply;
-	}
-
 	ret = tps65090_config_charger(cdata);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
@@ -285,6 +304,27 @@ static int tps65090_charger_probe(struct
 		power_supply_changed(&cdata->ac);
 	}
 
+	if (irq != -ENXIO) {
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+			tps65090_charger_isr, 0, "tps65090-charger", cdata);
+		if (ret) {
+			dev_err(cdata->dev,
+				"Unable to register irq %d err %d\n", irq,
+				ret);
+			goto fail_unregister_supply;
+		}
+	} else {
+		cdata->poll_task = kthread_run(tps65090_charger_poll_task,
+					      cdata, "ktps65090charger");
+		cdata->passive_mode = true;
+		if (IS_ERR(cdata->poll_task)) {
+			ret = PTR_ERR(cdata->poll_task);
+			dev_err(cdata->dev,
+				"Unable to run kthread err %d\n", ret);
+			goto fail_unregister_supply;
+		}
+	}
+
 	return 0;
 
 fail_unregister_supply:
@@ -297,6 +337,8 @@ static int tps65090_charger_remove(struc
 {
 	struct tps65090_charger *cdata = platform_get_drvdata(pdev);
 
+	if (cdata->irq == -ENXIO)
+		kthread_stop(cdata->poll_task);
 	power_supply_unregister(&cdata->ac);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/power/twl4030_charger.c linux-libre-3.17-rc7-gnu/drivers/power/twl4030_charger.c
--- linux-libre-3.16-gnu/drivers/power/twl4030_charger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/power/twl4030_charger.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,10 +28,13 @@
 #define TWL4030_BCIICHG		0x08
 #define TWL4030_BCIVAC		0x0a
 #define TWL4030_BCIVBUS		0x0c
+#define TWL4030_BCIMFSTS3	0x0F
 #define TWL4030_BCIMFSTS4	0x10
 #define TWL4030_BCICTL1		0x23
 #define TWL4030_BB_CFG		0x12
 
+#define TWL4030_BCIMFSTS1	0x01
+
 #define TWL4030_BCIAUTOWEN	BIT(5)
 #define TWL4030_CONFIG_DONE	BIT(4)
 #define TWL4030_BCIAUTOUSB	BIT(1)
@@ -52,6 +55,9 @@
 #define TWL4030_BBISEL_500uA	0x02
 #define TWL4030_BBISEL_1000uA	0x03
 
+#define TWL4030_BATSTSPCHG	BIT(2)
+#define TWL4030_BATSTSMCHG	BIT(6)
+
 /* BCI interrupts */
 #define TWL4030_WOVF		BIT(0) /* Watchdog overflow */
 #define TWL4030_TMOVF		BIT(1) /* Timer overflow */
@@ -145,6 +151,35 @@ static int twl4030bci_read_adc_val(u8 re
 }
 
 /*
+ * Check if Battery Pack was present
+ */
+static int twl4030_is_battery_present(struct twl4030_bci *bci)
+{
+	int ret;
+	u8 val = 0;
+
+	/* Battery presence in Main charge? */
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMFSTS3);
+	if (ret)
+		return ret;
+	if (val & TWL4030_BATSTSMCHG)
+		return 0;
+
+	/*
+	 * OK, It could be that bootloader did not enable main charger,
+	 * pre-charge is h/w auto. So, Battery presence in Pre-charge?
+	 */
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE, &val,
+			      TWL4030_BCIMFSTS1);
+	if (ret)
+		return ret;
+	if (val & TWL4030_BATSTSPCHG)
+		return 0;
+
+	return -ENODEV;
+}
+
+/*
  * Check if VBUS power is present
  */
 static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
@@ -541,8 +576,14 @@ static int __init twl4030_bci_probe(stru
 	bci->irq_chg = platform_get_irq(pdev, 0);
 	bci->irq_bci = platform_get_irq(pdev, 1);
 
-	platform_set_drvdata(pdev, bci);
+	/* Only proceed further *IF* battery is physically present */
+	ret = twl4030_is_battery_present(bci);
+	if  (ret) {
+		dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
+		goto fail_no_battery;
+	}
 
+	platform_set_drvdata(pdev, bci);
 	bci->ac.name = "twl4030_ac";
 	bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
 	bci->ac.properties = twl4030_charger_props;
@@ -633,6 +674,7 @@ fail_chg_irq:
 fail_register_usb:
 	power_supply_unregister(&bci->ac);
 fail_register_ac:
+fail_no_battery:
 	kfree(bci);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/powercap/intel_rapl.c linux-libre-3.17-rc7-gnu/drivers/powercap/intel_rapl.c
--- linux-libre-3.16-gnu/drivers/powercap/intel_rapl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/powercap/intel_rapl.c	2014-09-28 17:29:07.000000000 -0400
@@ -953,6 +953,7 @@ static const struct x86_cpu_id rapl_ids[
 	{ X86_VENDOR_INTEL, 6, 0x3a},/* Ivy Bridge */
 	{ X86_VENDOR_INTEL, 6, 0x3c},/* Haswell */
 	{ X86_VENDOR_INTEL, 6, 0x3d},/* Broadwell */
+	{ X86_VENDOR_INTEL, 6, 0x3f},/* Haswell */
 	{ X86_VENDOR_INTEL, 6, 0x45},/* Haswell ULT */
 	/* TODO: Add more CPU IDs after testing */
 	{}
@@ -1166,11 +1167,10 @@ static int rapl_detect_domains(struct ra
 
 	for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
 		/* use physical package id to read counters */
-		if (!rapl_check_domain(cpu, i))
+		if (!rapl_check_domain(cpu, i)) {
 			rp->domain_map |= 1 << i;
-		else
-			pr_warn("RAPL domain %s detection failed\n",
-				rapl_domain_names[i]);
+			pr_info("Found RAPL domain %s\n", rapl_domain_names[i]);
+		}
 	}
 	rp->nr_domains = bitmap_weight(&rp->domain_map,	RAPL_DOMAIN_MAX);
 	if (!rp->nr_domains) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ptp/ptp_chardev.c linux-libre-3.17-rc7-gnu/drivers/ptp/ptp_chardev.c
--- linux-libre-3.16-gnu/drivers/ptp/ptp_chardev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ptp/ptp_chardev.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,17 +86,12 @@ int ptp_set_pinfunc(struct ptp_clock *pt
 			return -EINVAL;
 		break;
 	case PTP_PF_PHYSYNC:
-		pr_err("sorry, cannot reassign the calibration pin\n");
-		return -EINVAL;
+		if (chan != 0)
+			return -EINVAL;
 	default:
 		return -EINVAL;
 	}
 
-	if (pin2->func == PTP_PF_PHYSYNC) {
-		pr_err("sorry, cannot reprogram the calibration pin\n");
-		return -EINVAL;
-	}
-
 	if (info->verify(info, pin, func, chan)) {
 		pr_err("driver cannot use function %u on pin %u\n", func, chan);
 		return -EOPNOTSUPP;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ptp/ptp_pch.c linux-libre-3.17-rc7-gnu/drivers/ptp/ptp_pch.c
--- linux-libre-3.16-gnu/drivers/ptp/ptp_pch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ptp/ptp_pch.c	2014-09-28 17:29:07.000000000 -0400
@@ -691,7 +691,7 @@ err_pci_en:
 	return ret;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(pch_ieee1588_pcidev_id) = {
+static const struct pci_device_id pch_ieee1588_pcidev_id[] = {
 	{
 	  .vendor = PCI_VENDOR_ID_INTEL,
 	  .device = PCI_DEVICE_ID_PCH_1588
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/core.c linux-libre-3.17-rc7-gnu/drivers/pwm/core.c
--- linux-libre-3.16-gnu/drivers/pwm/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -606,6 +606,8 @@ struct pwm_device *pwm_get(struct device
 	unsigned int best = 0;
 	struct pwm_lookup *p;
 	unsigned int match;
+	unsigned int period;
+	enum pwm_polarity polarity;
 
 	/* look up via DT first */
 	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
@@ -653,6 +655,8 @@ struct pwm_device *pwm_get(struct device
 		if (match > best) {
 			chip = pwmchip_find_by_name(p->provider);
 			index = p->index;
+			period = p->period;
+			polarity = p->polarity;
 
 			if (match != 3)
 				best = match;
@@ -668,8 +672,8 @@ struct pwm_device *pwm_get(struct device
 	if (IS_ERR(pwm))
 		return pwm;
 
-	pwm_set_period(pwm, p->period);
-	pwm_set_polarity(pwm, p->polarity);
+	pwm_set_period(pwm, period);
+	pwm_set_polarity(pwm, polarity);
 
 
 	return pwm;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/Kconfig linux-libre-3.17-rc7-gnu/drivers/pwm/Kconfig
--- linux-libre-3.16-gnu/drivers/pwm/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@ config PWM_AB8500
 
 config PWM_ATMEL
 	tristate "Atmel PWM support"
-	depends on ARCH_AT91
+	depends on ARCH_AT91 || AVR32
 	help
 	  Generic PWM framework driver for Atmel SoC.
 
@@ -206,6 +206,13 @@ config PWM_RENESAS_TPU
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-renesas-tpu.
 
+config PWM_ROCKCHIP
+	tristate "Rockchip PWM support"
+	depends on ARCH_ROCKCHIP
+	help
+	  Generic PWM framework driver for the PWM controller found on
+	  Rockchip SoCs.
+
 config PWM_SAMSUNG
 	tristate "Samsung PWM support"
 	depends on PLAT_SAMSUNG
@@ -226,6 +233,16 @@ config PWM_SPEAR
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-spear.
 
+config PWM_STI
+	tristate "STiH4xx PWM support"
+	depends on ARCH_STI
+	depends on OF
+	help
+	  Generic PWM framework driver for STiH4xx SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-sti.
+
 config PWM_TEGRA
 	tristate "NVIDIA Tegra PWM support"
 	depends on ARCH_TEGRA
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/Makefile linux-libre-3.17-rc7-gnu/drivers/pwm/Makefile
--- linux-libre-3.16-gnu/drivers/pwm/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -18,8 +18,10 @@ obj-$(CONFIG_PWM_PCA9685)	+= pwm-pca9685
 obj-$(CONFIG_PWM_PUV3)		+= pwm-puv3.o
 obj-$(CONFIG_PWM_PXA)		+= pwm-pxa.o
 obj-$(CONFIG_PWM_RENESAS_TPU)	+= pwm-renesas-tpu.o
+obj-$(CONFIG_PWM_ROCKCHIP)	+= pwm-rockchip.o
 obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
 obj-$(CONFIG_PWM_SPEAR)		+= pwm-spear.o
+obj-$(CONFIG_PWM_STI)		+= pwm-sti.o
 obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
 obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
 obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/pwm-imx.c linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-imx.c
--- linux-libre-3.16-gnu/drivers/pwm/pwm-imx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-imx.c	2014-09-28 17:29:07.000000000 -0400
@@ -262,6 +262,7 @@ static int imx_pwm_probe(struct platform
 	imx->chip.dev = &pdev->dev;
 	imx->chip.base = -1;
 	imx->chip.npwm = 1;
+	imx->chip.can_sleep = true;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/pwm-lpss.c linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-lpss.c
--- linux-libre-3.16-gnu/drivers/pwm/pwm-lpss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-lpss.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -37,7 +36,6 @@ static int pci_drv, plat_drv;	/* So we k
 struct pwm_lpss_chip {
 	struct pwm_chip chip;
 	void __iomem *regs;
-	struct clk *clk;
 	unsigned long clk_rate;
 };
 
@@ -97,11 +95,6 @@ static int pwm_lpss_enable(struct pwm_ch
 {
 	struct pwm_lpss_chip *lpwm = to_lpwm(chip);
 	u32 ctrl;
-	int ret;
-
-	ret = clk_prepare_enable(lpwm->clk);
-	if (ret)
-		return ret;
 
 	ctrl = readl(lpwm->regs + PWM);
 	writel(ctrl | PWM_ENABLE, lpwm->regs + PWM);
@@ -116,8 +109,6 @@ static void pwm_lpss_disable(struct pwm_
 
 	ctrl = readl(lpwm->regs + PWM);
 	writel(ctrl & ~PWM_ENABLE, lpwm->regs + PWM);
-
-	clk_disable_unprepare(lpwm->clk);
 }
 
 static const struct pwm_ops pwm_lpss_ops = {
@@ -142,17 +133,7 @@ static struct pwm_lpss_chip *pwm_lpss_pr
 	if (IS_ERR(lpwm->regs))
 		return ERR_CAST(lpwm->regs);
 
-	if (info) {
-		lpwm->clk_rate = info->clk_rate;
-	} else {
-		lpwm->clk = devm_clk_get(dev, NULL);
-		if (IS_ERR(lpwm->clk)) {
-			dev_err(dev, "failed to get PWM clock\n");
-			return ERR_CAST(lpwm->clk);
-		}
-		lpwm->clk_rate = clk_get_rate(lpwm->clk);
-	}
-
+	lpwm->clk_rate = info->clk_rate;
 	lpwm->chip.dev = dev;
 	lpwm->chip.ops = &pwm_lpss_ops;
 	lpwm->chip.base = -1;
@@ -221,12 +202,19 @@ static struct pci_driver pwm_lpss_driver
 
 static int pwm_lpss_probe_platform(struct platform_device *pdev)
 {
+	const struct pwm_lpss_boardinfo *info;
+	const struct acpi_device_id *id;
 	struct pwm_lpss_chip *lpwm;
 	struct resource *r;
 
+	id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+	if (!id)
+		return -ENODEV;
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	lpwm = pwm_lpss_probe(&pdev->dev, r, NULL);
+	info = (struct pwm_lpss_boardinfo *)id->driver_data;
+	lpwm = pwm_lpss_probe(&pdev->dev, r, info);
 	if (IS_ERR(lpwm))
 		return PTR_ERR(lpwm);
 
@@ -242,7 +230,7 @@ static int pwm_lpss_remove_platform(stru
 }
 
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
-	{ "80860F09", 0 },
+	{ "80860F09", (unsigned long)&byt_info },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/pwm-rockchip.c linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-rockchip.c
--- linux-libre-3.16-gnu/drivers/pwm/pwm-rockchip.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-rockchip.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,264 @@
+/*
+ * PWM driver for Rockchip SoCs
+ *
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ * Copyright (C) 2014 ROCKCHIP, 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/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/time.h>
+
+#define PWM_CTRL_TIMER_EN	(1 << 0)
+#define PWM_CTRL_OUTPUT_EN	(1 << 3)
+
+#define PWM_ENABLE		(1 << 0)
+#define PWM_CONTINUOUS		(1 << 1)
+#define PWM_DUTY_POSITIVE	(1 << 3)
+#define PWM_INACTIVE_NEGATIVE	(0 << 4)
+#define PWM_OUTPUT_LEFT		(0 << 5)
+#define PWM_LP_DISABLE		(0 << 8)
+
+struct rockchip_pwm_chip {
+	struct pwm_chip chip;
+	struct clk *clk;
+	const struct rockchip_pwm_data *data;
+	void __iomem *base;
+};
+
+struct rockchip_pwm_regs {
+	unsigned long duty;
+	unsigned long period;
+	unsigned long cntr;
+	unsigned long ctrl;
+};
+
+struct rockchip_pwm_data {
+	struct rockchip_pwm_regs regs;
+	unsigned int prescaler;
+
+	void (*set_enable)(struct pwm_chip *chip, bool enable);
+};
+
+static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
+{
+	return container_of(c, struct rockchip_pwm_chip, chip);
+}
+
+static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
+	u32 val;
+
+	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+	if (enable)
+		val |= enable_conf;
+	else
+		val &= ~enable_conf;
+
+	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
+static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
+			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
+			  PWM_INACTIVE_NEGATIVE;
+	u32 val;
+
+	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+	if (enable)
+		val |= enable_conf;
+	else
+		val &= ~enable_conf;
+
+	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
+static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			       int duty_ns, int period_ns)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	unsigned long period, duty;
+	u64 clk_rate, div;
+	int ret;
+
+	clk_rate = clk_get_rate(pc->clk);
+
+	/*
+	 * Since period and duty cycle registers have a width of 32
+	 * bits, every possible input period can be obtained using the
+	 * default prescaler value for all practical clock rate values.
+	 */
+	div = clk_rate * period_ns;
+	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
+	period = div;
+
+	div = clk_rate * duty_ns;
+	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
+	duty = div;
+
+	ret = clk_enable(pc->clk);
+	if (ret)
+		return ret;
+
+	writel(period, pc->base + pc->data->regs.period);
+	writel(duty, pc->base + pc->data->regs.duty);
+	writel(0, pc->base + pc->data->regs.cntr);
+
+	clk_disable(pc->clk);
+
+	return 0;
+}
+
+static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	int ret;
+
+	ret = clk_enable(pc->clk);
+	if (ret)
+		return ret;
+
+	pc->data->set_enable(chip, true);
+
+	return 0;
+}
+
+static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+
+	pc->data->set_enable(chip, false);
+
+	clk_disable(pc->clk);
+}
+
+static const struct pwm_ops rockchip_pwm_ops = {
+	.config = rockchip_pwm_config,
+	.enable = rockchip_pwm_enable,
+	.disable = rockchip_pwm_disable,
+	.owner = THIS_MODULE,
+};
+
+static const struct rockchip_pwm_data pwm_data_v1 = {
+	.regs = {
+		.duty = 0x04,
+		.period = 0x08,
+		.cntr = 0x00,
+		.ctrl = 0x0c,
+	},
+	.prescaler = 2,
+	.set_enable = rockchip_pwm_set_enable_v1,
+};
+
+static const struct rockchip_pwm_data pwm_data_v2 = {
+	.regs = {
+		.duty = 0x08,
+		.period = 0x04,
+		.cntr = 0x00,
+		.ctrl = 0x0c,
+	},
+	.prescaler = 1,
+	.set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct rockchip_pwm_data pwm_data_vop = {
+	.regs = {
+		.duty = 0x08,
+		.period = 0x04,
+		.cntr = 0x0c,
+		.ctrl = 0x00,
+	},
+	.prescaler = 1,
+	.set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct of_device_id rockchip_pwm_dt_ids[] = {
+	{ .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
+	{ .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
+	{ .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
+
+static int rockchip_pwm_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *id;
+	struct rockchip_pwm_chip *pc;
+	struct resource *r;
+	int ret;
+
+	id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
+	if (!id)
+		return -EINVAL;
+
+	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pc->base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(pc->base))
+		return PTR_ERR(pc->base);
+
+	pc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pc->clk))
+		return PTR_ERR(pc->clk);
+
+	ret = clk_prepare(pc->clk);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, pc);
+
+	pc->data = id->data;
+	pc->chip.dev = &pdev->dev;
+	pc->chip.ops = &rockchip_pwm_ops;
+	pc->chip.base = -1;
+	pc->chip.npwm = 1;
+
+	ret = pwmchip_add(&pc->chip);
+	if (ret < 0) {
+		clk_unprepare(pc->clk);
+		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int rockchip_pwm_remove(struct platform_device *pdev)
+{
+	struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
+
+	clk_unprepare(pc->clk);
+
+	return pwmchip_remove(&pc->chip);
+}
+
+static struct platform_driver rockchip_pwm_driver = {
+	.driver = {
+		.name = "rockchip-pwm",
+		.of_match_table = rockchip_pwm_dt_ids,
+	},
+	.probe = rockchip_pwm_probe,
+	.remove = rockchip_pwm_remove,
+};
+module_platform_driver(rockchip_pwm_driver);
+
+MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
+MODULE_DESCRIPTION("Rockchip SoC PWM driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/pwm-sti.c linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-sti.c
--- linux-libre-3.16-gnu/drivers/pwm/pwm-sti.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-sti.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,418 @@
+/*
+ * PWM device driver for ST SoCs.
+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>
+ *
+ * Copyright (C) 2013-2014 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 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/math64.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#define STI_DS_REG(ch)	(4 * (ch))	/* Channel's Duty Cycle register */
+#define STI_PWMCR	0x50		/* Control/Config register */
+#define STI_INTEN	0x54		/* Interrupt Enable/Disable register */
+#define PWM_PRESCALE_LOW_MASK		0x0f
+#define PWM_PRESCALE_HIGH_MASK		0xf0
+
+/* Regfield IDs */
+enum {
+	PWMCLK_PRESCALE_LOW,
+	PWMCLK_PRESCALE_HIGH,
+	PWM_EN,
+	PWM_INT_EN,
+
+	/* Keep last */
+	MAX_REGFIELDS
+};
+
+struct sti_pwm_compat_data {
+	const struct reg_field *reg_fields;
+	unsigned int num_chan;
+	unsigned int max_pwm_cnt;
+	unsigned int max_prescale;
+};
+
+struct sti_pwm_chip {
+	struct device *dev;
+	struct clk *clk;
+	unsigned long clk_rate;
+	struct regmap *regmap;
+	struct sti_pwm_compat_data *cdata;
+	struct regmap_field *prescale_low;
+	struct regmap_field *prescale_high;
+	struct regmap_field *pwm_en;
+	struct regmap_field *pwm_int_en;
+	struct pwm_chip chip;
+	struct pwm_device *cur;
+	unsigned int en_count;
+	struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
+	void __iomem *mmio;
+};
+
+static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
+	[PWMCLK_PRESCALE_LOW]	= REG_FIELD(STI_PWMCR, 0, 3),
+	[PWMCLK_PRESCALE_HIGH]	= REG_FIELD(STI_PWMCR, 11, 14),
+	[PWM_EN]		= REG_FIELD(STI_PWMCR, 9, 9),
+	[PWM_INT_EN]		= REG_FIELD(STI_INTEN, 0, 0),
+};
+
+static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct sti_pwm_chip, chip);
+}
+
+/*
+ * Calculate the prescaler value corresponding to the period.
+ */
+static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
+				unsigned int *prescale)
+{
+	struct sti_pwm_compat_data *cdata = pc->cdata;
+	unsigned long val;
+	unsigned int ps;
+
+	/*
+	 * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_count + 1)) - 1
+	 */
+	val = NSEC_PER_SEC / pc->clk_rate;
+	val *= cdata->max_pwm_cnt + 1;
+
+	if (period % val) {
+		return -EINVAL;
+	} else {
+		ps  = period / val - 1;
+		if (ps > cdata->max_prescale)
+			return -EINVAL;
+	}
+	*prescale = ps;
+
+	return 0;
+}
+
+/* Calculate the number of PWM devices configured with a period. */
+static unsigned int sti_pwm_count_configured(struct pwm_chip *chip)
+{
+	struct pwm_device *pwm;
+	unsigned int ncfg = 0;
+	unsigned int i;
+
+	for (i = 0; i < chip->npwm; i++) {
+		pwm = &chip->pwms[i];
+		if (test_bit(PWMF_REQUESTED, &pwm->flags)) {
+			if (pwm_get_period(pwm))
+				ncfg++;
+		}
+	}
+
+	return ncfg;
+}
+
+/*
+ * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
+ * The only way to change the period (apart from changing the PWM input clock)
+ * is to change the PWM clock prescaler.
+ * The prescaler is of 8 bits, so 256 prescaler values and hence
+ * 256 possible period values are supported (for a particular clock rate).
+ * The requested period will be applied only if it matches one of these
+ * 256 values.
+ */
+static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			 int duty_ns, int period_ns)
+{
+	struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+	struct sti_pwm_compat_data *cdata = pc->cdata;
+	struct pwm_device *cur = pc->cur;
+	struct device *dev = pc->dev;
+	unsigned int prescale = 0, pwmvalx;
+	int ret;
+	unsigned int ncfg;
+	bool period_same = false;
+
+	ncfg = sti_pwm_count_configured(chip);
+	if (ncfg)
+		period_same = (period_ns == pwm_get_period(cur));
+
+	/* Allow configuration changes if one of the
+	 * following conditions satisfy.
+	 * 1. No channels have been configured.
+	 * 2. Only one channel has been configured and the new request
+	 *    is for the same channel.
+	 * 3. Only one channel has been configured and the new request is
+	 *    for a new channel and period of the new channel is same as
+	 *    the current configured period.
+	 * 4. More than one channels are configured and period of the new
+	 *    requestis the same as the current period.
+	 */
+	if (!ncfg ||
+	    ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) ||
+	    ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) ||
+	    ((ncfg > 1) && period_same)) {
+		/* Enable clock before writing to PWM registers. */
+		ret = clk_enable(pc->clk);
+		if (ret)
+			return ret;
+
+		if (!period_same) {
+			ret = sti_pwm_get_prescale(pc, period_ns, &prescale);
+			if (ret)
+				goto clk_dis;
+
+			ret =
+			regmap_field_write(pc->prescale_low,
+					   prescale & PWM_PRESCALE_LOW_MASK);
+			if (ret)
+				goto clk_dis;
+
+			ret =
+			regmap_field_write(pc->prescale_high,
+				(prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
+			if (ret)
+				goto clk_dis;
+		}
+
+		/*
+		 * When PWMVal == 0, PWM pulse = 1 local clock cycle.
+		 * When PWMVal == max_pwm_count,
+		 * PWM pulse = (max_pwm_count + 1) local cycles,
+		 * that is continuous pulse: signal never goes low.
+		 */
+		pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns;
+
+		ret = regmap_write(pc->regmap, STI_DS_REG(pwm->hwpwm), pwmvalx);
+		if (ret)
+			goto clk_dis;
+
+		ret = regmap_field_write(pc->pwm_int_en, 0);
+
+		pc->cur = pwm;
+
+		dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n",
+			prescale, period_ns, duty_ns, pwmvalx);
+	} else {
+		return -EINVAL;
+	}
+
+clk_dis:
+	clk_disable(pc->clk);
+	return ret;
+}
+
+static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+	struct device *dev = pc->dev;
+	int ret = 0;
+
+	/*
+	 * Since we have a common enable for all PWM channels,
+	 * do not enable if already enabled.
+	 */
+	mutex_lock(&pc->sti_pwm_lock);
+	if (!pc->en_count) {
+		ret = clk_enable(pc->clk);
+		if (ret)
+			goto out;
+
+		ret = regmap_field_write(pc->pwm_en, 1);
+		if (ret) {
+			dev_err(dev, "failed to enable PWM device:%d\n",
+				pwm->hwpwm);
+			goto out;
+		}
+	}
+	pc->en_count++;
+out:
+	mutex_unlock(&pc->sti_pwm_lock);
+	return ret;
+}
+
+static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+
+	mutex_lock(&pc->sti_pwm_lock);
+	if (--pc->en_count) {
+		mutex_unlock(&pc->sti_pwm_lock);
+		return;
+	}
+	regmap_field_write(pc->pwm_en, 0);
+
+	clk_disable(pc->clk);
+	mutex_unlock(&pc->sti_pwm_lock);
+}
+
+static const struct pwm_ops sti_pwm_ops = {
+	.config = sti_pwm_config,
+	.enable = sti_pwm_enable,
+	.disable = sti_pwm_disable,
+	.owner = THIS_MODULE,
+};
+
+static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
+{
+	struct device *dev = pc->dev;
+	const struct reg_field *reg_fields;
+	struct device_node *np = dev->of_node;
+	struct sti_pwm_compat_data *cdata = pc->cdata;
+	u32 num_chan;
+
+	of_property_read_u32(np, "st,pwm-num-chan", &num_chan);
+	if (num_chan)
+		cdata->num_chan = num_chan;
+
+	reg_fields = cdata->reg_fields;
+
+	pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
+					reg_fields[PWMCLK_PRESCALE_LOW]);
+	if (IS_ERR(pc->prescale_low))
+		return PTR_ERR(pc->prescale_low);
+
+	pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
+					reg_fields[PWMCLK_PRESCALE_HIGH]);
+	if (IS_ERR(pc->prescale_high))
+		return PTR_ERR(pc->prescale_high);
+
+	pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
+					     reg_fields[PWM_EN]);
+	if (IS_ERR(pc->pwm_en))
+		return PTR_ERR(pc->pwm_en);
+
+	pc->pwm_int_en = devm_regmap_field_alloc(dev, pc->regmap,
+						 reg_fields[PWM_INT_EN]);
+	if (IS_ERR(pc->pwm_int_en))
+		return PTR_ERR(pc->pwm_int_en);
+
+	return 0;
+}
+
+static const struct regmap_config sti_pwm_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int sti_pwm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sti_pwm_compat_data *cdata;
+	struct sti_pwm_chip *pc;
+	struct resource *res;
+	int ret;
+
+	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
+	if (!cdata)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	pc->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pc->mmio))
+		return PTR_ERR(pc->mmio);
+
+	pc->regmap = devm_regmap_init_mmio(dev, pc->mmio,
+					   &sti_pwm_regmap_config);
+	if (IS_ERR(pc->regmap))
+		return PTR_ERR(pc->regmap);
+
+	/*
+	 * Setup PWM data with default values: some values could be replaced
+	 * with specific ones provided from Device Tree.
+	 */
+	cdata->reg_fields   = &sti_pwm_regfields[0];
+	cdata->max_prescale = 0xff;
+	cdata->max_pwm_cnt  = 255;
+	cdata->num_chan     = 1;
+
+	pc->cdata = cdata;
+	pc->dev = dev;
+	pc->en_count = 0;
+	mutex_init(&pc->sti_pwm_lock);
+
+	ret = sti_pwm_probe_dt(pc);
+	if (ret)
+		return ret;
+
+	pc->clk = of_clk_get_by_name(dev->of_node, "pwm");
+	if (IS_ERR(pc->clk)) {
+		dev_err(dev, "failed to get PWM clock\n");
+		return PTR_ERR(pc->clk);
+	}
+
+	pc->clk_rate = clk_get_rate(pc->clk);
+	if (!pc->clk_rate) {
+		dev_err(dev, "failed to get clock rate\n");
+		return -EINVAL;
+	}
+
+	ret = clk_prepare(pc->clk);
+	if (ret) {
+		dev_err(dev, "failed to prepare clock\n");
+		return ret;
+	}
+
+	pc->chip.dev = dev;
+	pc->chip.ops = &sti_pwm_ops;
+	pc->chip.base = -1;
+	pc->chip.npwm = pc->cdata->num_chan;
+	pc->chip.can_sleep = true;
+
+	ret = pwmchip_add(&pc->chip);
+	if (ret < 0) {
+		clk_unprepare(pc->clk);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pc);
+
+	return 0;
+}
+
+static int sti_pwm_remove(struct platform_device *pdev)
+{
+	struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
+	unsigned int i;
+
+	for (i = 0; i < pc->cdata->num_chan; i++)
+		pwm_disable(&pc->chip.pwms[i]);
+
+	clk_unprepare(pc->clk);
+
+	return pwmchip_remove(&pc->chip);
+}
+
+static const struct of_device_id sti_pwm_of_match[] = {
+	{ .compatible = "st,sti-pwm", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sti_pwm_of_match);
+
+static struct platform_driver sti_pwm_driver = {
+	.driver = {
+		.name = "sti-pwm",
+		.of_match_table = sti_pwm_of_match,
+	},
+	.probe = sti_pwm_probe,
+	.remove = sti_pwm_remove,
+};
+module_platform_driver(sti_pwm_driver);
+
+MODULE_AUTHOR("Ajit Pal Singh <ajitpal.singh@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST PWM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/pwm/pwm-tipwmss.c linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-tipwmss.c
--- linux-libre-3.16-gnu/drivers/pwm/pwm-tipwmss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/pwm/pwm-tipwmss.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,10 +62,8 @@ static int pwmss_probe(struct platform_d
 	struct device_node *node = pdev->dev.of_node;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	if (!info)
 		return -ENOMEM;
-	}
 
 	mutex_init(&info->pwmss_lock);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721.c linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721.c
--- linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721.c	2014-09-28 17:29:07.000000000 -0400
@@ -2493,7 +2493,7 @@ err_exit:
 	return err;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(tsi721_pci_tbl) = {
+static const struct pci_device_id tsi721_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_TSI721) },
 	{ 0, }	/* terminate list */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721_dma.c linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721_dma.c
--- linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721_dma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721_dma.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * DMA Engine support for Tsi721 PCIExpress-to-SRIO bridge
  *
- * Copyright 2011 Integrated Device Technology, Inc.
+ * Copyright (c) 2011-2014 Integrated Device Technology, Inc.
  * Alexandre Bounine <alexandre.bounine@idt.com>
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -14,9 +14,8 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
  */
 
 #include <linux/io.h>
@@ -32,9 +31,22 @@
 #include <linux/interrupt.h>
 #include <linux/kfifo.h>
 #include <linux/delay.h>
+#include "../../dma/dmaengine.h"
 
 #include "tsi721.h"
 
+#define TSI721_DMA_TX_QUEUE_SZ	16	/* number of transaction descriptors */
+
+#ifdef CONFIG_PCI_MSI
+static irqreturn_t tsi721_bdma_msix(int irq, void *ptr);
+#endif
+static int tsi721_submit_sg(struct tsi721_tx_desc *desc);
+
+static unsigned int dma_desc_per_channel = 128;
+module_param(dma_desc_per_channel, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(dma_desc_per_channel,
+		 "Number of DMA descriptors per channel (default: 128)");
+
 static inline struct tsi721_bdma_chan *to_tsi721_chan(struct dma_chan *chan)
 {
 	return container_of(chan, struct tsi721_bdma_chan, dchan);
@@ -59,7 +71,7 @@ struct tsi721_tx_desc *tsi721_dma_first_
 				struct tsi721_tx_desc, desc_node);
 }
 
-static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
+static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
 {
 	struct tsi721_dma_desc *bd_ptr;
 	struct device *dev = bdma_chan->dchan.device->dev;
@@ -67,17 +79,23 @@ static int tsi721_bdma_ch_init(struct ts
 	dma_addr_t	bd_phys;
 	dma_addr_t	sts_phys;
 	int		sts_size;
-	int		bd_num = bdma_chan->bd_num;
+#ifdef CONFIG_PCI_MSI
+	struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
+#endif
 
 	dev_dbg(dev, "Init Block DMA Engine, CH%d\n", bdma_chan->id);
 
-	/* Allocate space for DMA descriptors */
+	/*
+	 * Allocate space for DMA descriptors
+	 * (add an extra element for link descriptor)
+	 */
 	bd_ptr = dma_zalloc_coherent(dev,
-				bd_num * sizeof(struct tsi721_dma_desc),
+				(bd_num + 1) * sizeof(struct tsi721_dma_desc),
 				&bd_phys, GFP_KERNEL);
 	if (!bd_ptr)
 		return -ENOMEM;
 
+	bdma_chan->bd_num = bd_num;
 	bdma_chan->bd_phys = bd_phys;
 	bdma_chan->bd_base = bd_ptr;
 
@@ -85,8 +103,8 @@ static int tsi721_bdma_ch_init(struct ts
 		bd_ptr, (unsigned long long)bd_phys);
 
 	/* Allocate space for descriptor status FIFO */
-	sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
-					bd_num : TSI721_DMA_MINSTSSZ;
+	sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ?
+					(bd_num + 1) : TSI721_DMA_MINSTSSZ;
 	sts_size = roundup_pow_of_two(sts_size);
 	sts_ptr = dma_zalloc_coherent(dev,
 				     sts_size * sizeof(struct tsi721_dma_sts),
@@ -94,7 +112,7 @@ static int tsi721_bdma_ch_init(struct ts
 	if (!sts_ptr) {
 		/* Free space allocated for DMA descriptors */
 		dma_free_coherent(dev,
-				  bd_num * sizeof(struct tsi721_dma_desc),
+				  (bd_num + 1) * sizeof(struct tsi721_dma_desc),
 				  bd_ptr, bd_phys);
 		bdma_chan->bd_base = NULL;
 		return -ENOMEM;
@@ -108,11 +126,11 @@ static int tsi721_bdma_ch_init(struct ts
 		"desc status FIFO @ %p (phys = %llx) size=0x%x\n",
 		sts_ptr, (unsigned long long)sts_phys, sts_size);
 
-	/* Initialize DMA descriptors ring */
-	bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29);
-	bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys &
+	/* Initialize DMA descriptors ring using added link descriptor */
+	bd_ptr[bd_num].type_id = cpu_to_le32(DTYPE3 << 29);
+	bd_ptr[bd_num].next_lo = cpu_to_le32((u64)bd_phys &
 						 TSI721_DMAC_DPTRL_MASK);
-	bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32);
+	bd_ptr[bd_num].next_hi = cpu_to_le32((u64)bd_phys >> 32);
 
 	/* Setup DMA descriptor pointers */
 	iowrite32(((u64)bd_phys >> 32),
@@ -134,6 +152,55 @@ static int tsi721_bdma_ch_init(struct ts
 
 	ioread32(bdma_chan->regs + TSI721_DMAC_INT);
 
+#ifdef CONFIG_PCI_MSI
+	/* Request interrupt service if we are in MSI-X mode */
+	if (priv->flags & TSI721_USING_MSIX) {
+		int rc, idx;
+
+		idx = TSI721_VECT_DMA0_DONE + bdma_chan->id;
+
+		rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0,
+				 priv->msix[idx].irq_name, (void *)bdma_chan);
+
+		if (rc) {
+			dev_dbg(dev, "Unable to get MSI-X for BDMA%d-DONE\n",
+				bdma_chan->id);
+			goto err_out;
+		}
+
+		idx = TSI721_VECT_DMA0_INT + bdma_chan->id;
+
+		rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0,
+				priv->msix[idx].irq_name, (void *)bdma_chan);
+
+		if (rc)	{
+			dev_dbg(dev, "Unable to get MSI-X for BDMA%d-INT\n",
+				bdma_chan->id);
+			free_irq(
+				priv->msix[TSI721_VECT_DMA0_DONE +
+					    bdma_chan->id].vector,
+				(void *)bdma_chan);
+		}
+
+err_out:
+		if (rc) {
+			/* Free space allocated for DMA descriptors */
+			dma_free_coherent(dev,
+				(bd_num + 1) * sizeof(struct tsi721_dma_desc),
+				bd_ptr, bd_phys);
+			bdma_chan->bd_base = NULL;
+
+			/* Free space allocated for status descriptors */
+			dma_free_coherent(dev,
+				sts_size * sizeof(struct tsi721_dma_sts),
+				sts_ptr, sts_phys);
+			bdma_chan->sts_base = NULL;
+
+			return -EIO;
+		}
+	}
+#endif /* CONFIG_PCI_MSI */
+
 	/* Toggle DMA channel initialization */
 	iowrite32(TSI721_DMAC_CTL_INIT,	bdma_chan->regs + TSI721_DMAC_CTL);
 	ioread32(bdma_chan->regs + TSI721_DMAC_CTL);
@@ -147,6 +214,9 @@ static int tsi721_bdma_ch_init(struct ts
 static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan)
 {
 	u32 ch_stat;
+#ifdef CONFIG_PCI_MSI
+	struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
+#endif
 
 	if (bdma_chan->bd_base == NULL)
 		return 0;
@@ -159,9 +229,18 @@ static int tsi721_bdma_ch_free(struct ts
 	/* Put DMA channel into init state */
 	iowrite32(TSI721_DMAC_CTL_INIT,	bdma_chan->regs + TSI721_DMAC_CTL);
 
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
+				    bdma_chan->id].vector, (void *)bdma_chan);
+		free_irq(priv->msix[TSI721_VECT_DMA0_INT +
+				    bdma_chan->id].vector, (void *)bdma_chan);
+	}
+#endif /* CONFIG_PCI_MSI */
+
 	/* Free space allocated for DMA descriptors */
 	dma_free_coherent(bdma_chan->dchan.device->dev,
-		bdma_chan->bd_num * sizeof(struct tsi721_dma_desc),
+		(bdma_chan->bd_num + 1) * sizeof(struct tsi721_dma_desc),
 		bdma_chan->bd_base, bdma_chan->bd_phys);
 	bdma_chan->bd_base = NULL;
 
@@ -243,8 +322,8 @@ static void tsi721_start_dma(struct tsi7
 	}
 
 	dev_dbg(bdma_chan->dchan.device->dev,
-		"tx_chan: %p, chan: %d, regs: %p\n",
-		bdma_chan, bdma_chan->dchan.chan_id, bdma_chan->regs);
+		"%s: chan_%d (wrc=%d)\n", __func__, bdma_chan->id,
+		bdma_chan->wr_count_next);
 
 	iowrite32(bdma_chan->wr_count_next,
 		bdma_chan->regs + TSI721_DMAC_DWRCNT);
@@ -253,72 +332,19 @@ static void tsi721_start_dma(struct tsi7
 	bdma_chan->wr_count = bdma_chan->wr_count_next;
 }
 
-static void tsi721_desc_put(struct tsi721_bdma_chan *bdma_chan,
-			    struct tsi721_tx_desc *desc)
-{
-	dev_dbg(bdma_chan->dchan.device->dev,
-		"Put desc: %p into free list\n", desc);
-
-	if (desc) {
-		spin_lock_bh(&bdma_chan->lock);
-		list_splice_init(&desc->tx_list, &bdma_chan->free_list);
-		list_add(&desc->desc_node, &bdma_chan->free_list);
-		bdma_chan->wr_count_next = bdma_chan->wr_count;
-		spin_unlock_bh(&bdma_chan->lock);
-	}
-}
-
-static
-struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan)
-{
-	struct tsi721_tx_desc *tx_desc, *_tx_desc;
-	struct tsi721_tx_desc *ret = NULL;
-	int i;
-
-	spin_lock_bh(&bdma_chan->lock);
-	list_for_each_entry_safe(tx_desc, _tx_desc,
-				 &bdma_chan->free_list, desc_node) {
-		if (async_tx_test_ack(&tx_desc->txd)) {
-			list_del(&tx_desc->desc_node);
-			ret = tx_desc;
-			break;
-		}
-		dev_dbg(bdma_chan->dchan.device->dev,
-			"desc %p not ACKed\n", tx_desc);
-	}
-
-	if (ret == NULL) {
-		dev_dbg(bdma_chan->dchan.device->dev,
-			"%s: unable to obtain tx descriptor\n", __func__);
-		goto err_out;
-	}
-
-	i = bdma_chan->wr_count_next % bdma_chan->bd_num;
-	if (i == bdma_chan->bd_num - 1) {
-		i = 0;
-		bdma_chan->wr_count_next++; /* skip link descriptor */
-	}
-
-	bdma_chan->wr_count_next++;
-	tx_desc->txd.phys = bdma_chan->bd_phys +
-				i * sizeof(struct tsi721_dma_desc);
-	tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i];
-err_out:
-	spin_unlock_bh(&bdma_chan->lock);
-
-	return ret;
-}
-
 static int
-tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg,
-	enum dma_rtype rtype, u32 sys_size)
+tsi721_desc_fill_init(struct tsi721_tx_desc *desc,
+		      struct tsi721_dma_desc *bd_ptr,
+		      struct scatterlist *sg, u32 sys_size)
 {
-	struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
 	u64 rio_addr;
 
+	if (bd_ptr == NULL)
+		return -EINVAL;
+
 	/* Initialize DMA descriptor */
 	bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) |
-					(rtype << 19) | desc->destid);
+				      (desc->rtype << 19) | desc->destid);
 	bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) |
 				     (sys_size << 26));
 	rio_addr = (desc->rio_addr >> 2) |
@@ -335,51 +361,32 @@ tsi721_desc_fill_init(struct tsi721_tx_d
 }
 
 static int
-tsi721_desc_fill_end(struct tsi721_tx_desc *desc)
+tsi721_desc_fill_end(struct tsi721_dma_desc *bd_ptr, u32 bcount, bool interrupt)
 {
-	struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
+	if (bd_ptr == NULL)
+		return -EINVAL;
 
 	/* Update DMA descriptor */
-	if (desc->interrupt)
+	if (interrupt)
 		bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF);
-	bd_ptr->bcount |= cpu_to_le32(desc->bcount & TSI721_DMAD_BCOUNT1);
+	bd_ptr->bcount |= cpu_to_le32(bcount & TSI721_DMAD_BCOUNT1);
 
 	return 0;
 }
 
-
-static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan,
-				      struct tsi721_tx_desc *desc)
+static void tsi721_dma_tx_err(struct tsi721_bdma_chan *bdma_chan,
+			      struct tsi721_tx_desc *desc)
 {
 	struct dma_async_tx_descriptor *txd = &desc->txd;
 	dma_async_tx_callback callback = txd->callback;
 	void *param = txd->callback_param;
 
-	list_splice_init(&desc->tx_list, &bdma_chan->free_list);
 	list_move(&desc->desc_node, &bdma_chan->free_list);
-	bdma_chan->completed_cookie = txd->cookie;
 
 	if (callback)
 		callback(param);
 }
 
-static void tsi721_dma_complete_all(struct tsi721_bdma_chan *bdma_chan)
-{
-	struct tsi721_tx_desc *desc, *_d;
-	LIST_HEAD(list);
-
-	BUG_ON(!tsi721_dma_is_idle(bdma_chan));
-
-	if (!list_empty(&bdma_chan->queue))
-		tsi721_start_dma(bdma_chan);
-
-	list_splice_init(&bdma_chan->active_list, &list);
-	list_splice_init(&bdma_chan->queue, &bdma_chan->active_list);
-
-	list_for_each_entry_safe(desc, _d, &list, desc_node)
-		tsi721_dma_chain_complete(bdma_chan, desc);
-}
-
 static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan)
 {
 	u32 srd_ptr;
@@ -403,20 +410,159 @@ static void tsi721_clr_stat(struct tsi72
 	bdma_chan->sts_rdptr = srd_ptr;
 }
 
+/* Must be called with the channel spinlock held */
+static int tsi721_submit_sg(struct tsi721_tx_desc *desc)
+{
+	struct dma_chan *dchan = desc->txd.chan;
+	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
+	u32 sys_size;
+	u64 rio_addr;
+	dma_addr_t next_addr;
+	u32 bcount;
+	struct scatterlist *sg;
+	unsigned int i;
+	int err = 0;
+	struct tsi721_dma_desc *bd_ptr = NULL;
+	u32 idx, rd_idx;
+	u32 add_count = 0;
+
+	if (!tsi721_dma_is_idle(bdma_chan)) {
+		dev_err(bdma_chan->dchan.device->dev,
+			"BUG: Attempt to use non-idle channel\n");
+		return -EIO;
+	}
+
+	/*
+	 * Fill DMA channel's hardware buffer descriptors.
+	 * (NOTE: RapidIO destination address is limited to 64 bits for now)
+	 */
+	rio_addr = desc->rio_addr;
+	next_addr = -1;
+	bcount = 0;
+	sys_size = dma_to_mport(bdma_chan->dchan.device)->sys_size;
+
+	rd_idx = ioread32(bdma_chan->regs + TSI721_DMAC_DRDCNT);
+	rd_idx %= (bdma_chan->bd_num + 1);
+
+	idx = bdma_chan->wr_count_next % (bdma_chan->bd_num + 1);
+	if (idx == bdma_chan->bd_num) {
+		/* wrap around link descriptor */
+		idx = 0;
+		add_count++;
+	}
+
+	dev_dbg(dchan->device->dev, "%s: BD ring status: rdi=%d wri=%d\n",
+		__func__, rd_idx, idx);
+
+	for_each_sg(desc->sg, sg, desc->sg_len, i) {
+
+		dev_dbg(dchan->device->dev, "sg%d/%d addr: 0x%llx len: %d\n",
+			i, desc->sg_len,
+			(unsigned long long)sg_dma_address(sg), sg_dma_len(sg));
+
+		if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) {
+			dev_err(dchan->device->dev,
+				"%s: SG entry %d is too large\n", __func__, i);
+			err = -EINVAL;
+			break;
+		}
+
+		/*
+		 * If this sg entry forms contiguous block with previous one,
+		 * try to merge it into existing DMA descriptor
+		 */
+		if (next_addr == sg_dma_address(sg) &&
+		    bcount + sg_dma_len(sg) <= TSI721_BDMA_MAX_BCOUNT) {
+			/* Adjust byte count of the descriptor */
+			bcount += sg_dma_len(sg);
+			goto entry_done;
+		} else if (next_addr != -1) {
+			/* Finalize descriptor using total byte count value */
+			tsi721_desc_fill_end(bd_ptr, bcount, 0);
+			dev_dbg(dchan->device->dev,
+				"%s: prev desc final len: %d\n",
+				__func__, bcount);
+		}
+
+		desc->rio_addr = rio_addr;
+
+		if (i && idx == rd_idx) {
+			dev_dbg(dchan->device->dev,
+				"%s: HW descriptor ring is full @ %d\n",
+				__func__, i);
+			desc->sg = sg;
+			desc->sg_len -= i;
+			break;
+		}
+
+		bd_ptr = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[idx];
+		err = tsi721_desc_fill_init(desc, bd_ptr, sg, sys_size);
+		if (err) {
+			dev_err(dchan->device->dev,
+				"Failed to build desc: err=%d\n", err);
+			break;
+		}
+
+		dev_dbg(dchan->device->dev, "bd_ptr = %p did=%d raddr=0x%llx\n",
+			bd_ptr, desc->destid, desc->rio_addr);
+
+		next_addr = sg_dma_address(sg);
+		bcount = sg_dma_len(sg);
+
+		add_count++;
+		if (++idx == bdma_chan->bd_num) {
+			/* wrap around link descriptor */
+			idx = 0;
+			add_count++;
+		}
+
+entry_done:
+		if (sg_is_last(sg)) {
+			tsi721_desc_fill_end(bd_ptr, bcount, 0);
+			dev_dbg(dchan->device->dev, "%s: last desc final len: %d\n",
+				__func__, bcount);
+			desc->sg_len = 0;
+		} else {
+			rio_addr += sg_dma_len(sg);
+			next_addr += sg_dma_len(sg);
+		}
+	}
+
+	if (!err)
+		bdma_chan->wr_count_next += add_count;
+
+	return err;
+}
+
 static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan)
 {
-	if (list_empty(&bdma_chan->active_list) ||
-		list_is_singular(&bdma_chan->active_list)) {
-		dev_dbg(bdma_chan->dchan.device->dev,
-			"%s: Active_list empty\n", __func__);
-		tsi721_dma_complete_all(bdma_chan);
-	} else {
-		dev_dbg(bdma_chan->dchan.device->dev,
-			"%s: Active_list NOT empty\n", __func__);
-		tsi721_dma_chain_complete(bdma_chan,
-					tsi721_dma_first_active(bdma_chan));
-		tsi721_start_dma(bdma_chan);
+	struct tsi721_tx_desc *desc;
+	int err;
+
+	dev_dbg(bdma_chan->dchan.device->dev, "%s: Enter\n", __func__);
+
+	/*
+	 * If there are any new transactions in the queue add them
+	 * into the processing list
+	 */
+	if (!list_empty(&bdma_chan->queue))
+		list_splice_init(&bdma_chan->queue, &bdma_chan->active_list);
+
+	/* Start new transaction (if available) */
+	if (!list_empty(&bdma_chan->active_list)) {
+		desc = tsi721_dma_first_active(bdma_chan);
+		err = tsi721_submit_sg(desc);
+		if (!err)
+			tsi721_start_dma(bdma_chan);
+		else {
+			tsi721_dma_tx_err(bdma_chan, desc);
+			dev_dbg(bdma_chan->dchan.device->dev,
+				"ERR: tsi721_submit_sg failed with err=%d\n",
+				err);
+		}
 	}
+
+	dev_dbg(bdma_chan->dchan.device->dev, "%s: Exit\n", __func__);
 }
 
 static void tsi721_dma_tasklet(unsigned long data)
@@ -444,8 +590,29 @@ static void tsi721_dma_tasklet(unsigned
 	}
 
 	if (dmac_int & (TSI721_DMAC_INT_DONE | TSI721_DMAC_INT_IOFDONE)) {
+		struct tsi721_tx_desc *desc;
+
 		tsi721_clr_stat(bdma_chan);
 		spin_lock(&bdma_chan->lock);
+		desc = tsi721_dma_first_active(bdma_chan);
+
+		if (desc->sg_len == 0) {
+			dma_async_tx_callback callback = NULL;
+			void *param = NULL;
+
+			desc->status = DMA_COMPLETE;
+			dma_cookie_complete(&desc->txd);
+			if (desc->txd.flags & DMA_PREP_INTERRUPT) {
+				callback = desc->txd.callback;
+				param = desc->txd.callback_param;
+			}
+			list_move(&desc->desc_node, &bdma_chan->free_list);
+			spin_unlock(&bdma_chan->lock);
+			if (callback)
+				callback(param);
+			spin_lock(&bdma_chan->lock);
+		}
+
 		tsi721_advance_work(bdma_chan);
 		spin_unlock(&bdma_chan->lock);
 	}
@@ -460,21 +627,24 @@ static dma_cookie_t tsi721_tx_submit(str
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(txd->chan);
 	dma_cookie_t cookie;
 
-	spin_lock_bh(&bdma_chan->lock);
+	/* Check if the descriptor is detached from any lists */
+	if (!list_empty(&desc->desc_node)) {
+		dev_err(bdma_chan->dchan.device->dev,
+			"%s: wrong state of descriptor %p\n", __func__, txd);
+		return -EIO;
+	}
 
-	cookie = txd->chan->cookie;
-	if (++cookie < 0)
-		cookie = 1;
-	txd->chan->cookie = cookie;
-	txd->cookie = cookie;
+	spin_lock_bh(&bdma_chan->lock);
 
-	if (list_empty(&bdma_chan->active_list)) {
-		list_add_tail(&desc->desc_node, &bdma_chan->active_list);
-		tsi721_start_dma(bdma_chan);
-	} else {
-		list_add_tail(&desc->desc_node, &bdma_chan->queue);
+	if (!bdma_chan->active) {
+		spin_unlock_bh(&bdma_chan->lock);
+		return -ENODEV;
 	}
 
+	cookie = dma_cookie_assign(txd);
+	desc->status = DMA_IN_PROGRESS;
+	list_add_tail(&desc->desc_node, &bdma_chan->queue);
+
 	spin_unlock_bh(&bdma_chan->lock);
 	return cookie;
 }
@@ -482,115 +652,52 @@ static dma_cookie_t tsi721_tx_submit(str
 static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
 {
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-#ifdef CONFIG_PCI_MSI
-	struct tsi721_device *priv = to_tsi721(dchan->device);
-#endif
 	struct tsi721_tx_desc *desc = NULL;
-	LIST_HEAD(tmp_list);
 	int i;
-	int rc;
+
+	dev_dbg(dchan->device->dev, "%s: for channel %d\n",
+		__func__, bdma_chan->id);
 
 	if (bdma_chan->bd_base)
-		return bdma_chan->bd_num - 1;
+		return TSI721_DMA_TX_QUEUE_SZ;
 
 	/* Initialize BDMA channel */
-	if (tsi721_bdma_ch_init(bdma_chan)) {
+	if (tsi721_bdma_ch_init(bdma_chan, dma_desc_per_channel)) {
 		dev_err(dchan->device->dev, "Unable to initialize data DMA"
 			" channel %d, aborting\n", bdma_chan->id);
-		return -ENOMEM;
+		return -ENODEV;
 	}
 
-	/* Alocate matching number of logical descriptors */
-	desc = kcalloc((bdma_chan->bd_num - 1), sizeof(struct tsi721_tx_desc),
+	/* Allocate queue of transaction descriptors */
+	desc = kcalloc(TSI721_DMA_TX_QUEUE_SZ, sizeof(struct tsi721_tx_desc),
 			GFP_KERNEL);
 	if (!desc) {
 		dev_err(dchan->device->dev,
 			"Failed to allocate logical descriptors\n");
-		rc = -ENOMEM;
-		goto err_out;
+		tsi721_bdma_ch_free(bdma_chan);
+		return -ENOMEM;
 	}
 
 	bdma_chan->tx_desc = desc;
 
-	for (i = 0; i < bdma_chan->bd_num - 1; i++) {
+	for (i = 0; i < TSI721_DMA_TX_QUEUE_SZ; i++) {
 		dma_async_tx_descriptor_init(&desc[i].txd, dchan);
 		desc[i].txd.tx_submit = tsi721_tx_submit;
 		desc[i].txd.flags = DMA_CTRL_ACK;
-		INIT_LIST_HEAD(&desc[i].tx_list);
-		list_add_tail(&desc[i].desc_node, &tmp_list);
+		list_add(&desc[i].desc_node, &bdma_chan->free_list);
 	}
 
-	spin_lock_bh(&bdma_chan->lock);
-	list_splice(&tmp_list, &bdma_chan->free_list);
-	bdma_chan->completed_cookie = dchan->cookie = 1;
-	spin_unlock_bh(&bdma_chan->lock);
-
-#ifdef CONFIG_PCI_MSI
-	if (priv->flags & TSI721_USING_MSIX) {
-		/* Request interrupt service if we are in MSI-X mode */
-		rc = request_irq(
-			priv->msix[TSI721_VECT_DMA0_DONE +
-				   bdma_chan->id].vector,
-			tsi721_bdma_msix, 0,
-			priv->msix[TSI721_VECT_DMA0_DONE +
-				   bdma_chan->id].irq_name,
-			(void *)bdma_chan);
-
-		if (rc) {
-			dev_dbg(dchan->device->dev,
-				"Unable to allocate MSI-X interrupt for "
-				"BDMA%d-DONE\n", bdma_chan->id);
-			goto err_out;
-		}
-
-		rc = request_irq(priv->msix[TSI721_VECT_DMA0_INT +
-					    bdma_chan->id].vector,
-				tsi721_bdma_msix, 0,
-				priv->msix[TSI721_VECT_DMA0_INT +
-					   bdma_chan->id].irq_name,
-				(void *)bdma_chan);
-
-		if (rc)	{
-			dev_dbg(dchan->device->dev,
-				"Unable to allocate MSI-X interrupt for "
-				"BDMA%d-INT\n", bdma_chan->id);
-			free_irq(
-				priv->msix[TSI721_VECT_DMA0_DONE +
-					   bdma_chan->id].vector,
-				(void *)bdma_chan);
-			rc = -EIO;
-			goto err_out;
-		}
-	}
-#endif /* CONFIG_PCI_MSI */
+	dma_cookie_init(dchan);
 
 	bdma_chan->active = true;
 	tsi721_bdma_interrupt_enable(bdma_chan, 1);
 
-	return bdma_chan->bd_num - 1;
-
-err_out:
-	kfree(desc);
-	tsi721_bdma_ch_free(bdma_chan);
-	return rc;
+	return TSI721_DMA_TX_QUEUE_SZ;
 }
 
-static void tsi721_free_chan_resources(struct dma_chan *dchan)
+static void tsi721_sync_dma_irq(struct tsi721_bdma_chan *bdma_chan)
 {
-	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-	struct tsi721_device *priv = to_tsi721(dchan->device);
-	LIST_HEAD(list);
-
-	dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
-
-	if (bdma_chan->bd_base == NULL)
-		return;
-
-	BUG_ON(!list_empty(&bdma_chan->active_list));
-	BUG_ON(!list_empty(&bdma_chan->queue));
-
-	tsi721_bdma_interrupt_enable(bdma_chan, 0);
-	bdma_chan->active = false;
+	struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
 
 #ifdef CONFIG_PCI_MSI
 	if (priv->flags & TSI721_USING_MSIX) {
@@ -601,64 +708,48 @@ static void tsi721_free_chan_resources(s
 	} else
 #endif
 	synchronize_irq(priv->pdev->irq);
+}
 
-	tasklet_kill(&bdma_chan->tasklet);
+static void tsi721_free_chan_resources(struct dma_chan *dchan)
+{
+	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
 
-	spin_lock_bh(&bdma_chan->lock);
-	list_splice_init(&bdma_chan->free_list, &list);
-	spin_unlock_bh(&bdma_chan->lock);
+	dev_dbg(dchan->device->dev, "%s: for channel %d\n",
+		__func__, bdma_chan->id);
 
-#ifdef CONFIG_PCI_MSI
-	if (priv->flags & TSI721_USING_MSIX) {
-		free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
-				    bdma_chan->id].vector, (void *)bdma_chan);
-		free_irq(priv->msix[TSI721_VECT_DMA0_INT +
-				    bdma_chan->id].vector, (void *)bdma_chan);
-	}
-#endif /* CONFIG_PCI_MSI */
+	if (bdma_chan->bd_base == NULL)
+		return;
 
-	tsi721_bdma_ch_free(bdma_chan);
+	BUG_ON(!list_empty(&bdma_chan->active_list));
+	BUG_ON(!list_empty(&bdma_chan->queue));
+
+	tsi721_bdma_interrupt_enable(bdma_chan, 0);
+	bdma_chan->active = false;
+	tsi721_sync_dma_irq(bdma_chan);
+	tasklet_kill(&bdma_chan->tasklet);
+	INIT_LIST_HEAD(&bdma_chan->free_list);
 	kfree(bdma_chan->tx_desc);
+	tsi721_bdma_ch_free(bdma_chan);
 }
 
 static
 enum dma_status tsi721_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
 				 struct dma_tx_state *txstate)
 {
-	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-	dma_cookie_t		last_used;
-	dma_cookie_t		last_completed;
-	int			ret;
-
-	spin_lock_bh(&bdma_chan->lock);
-	last_completed = bdma_chan->completed_cookie;
-	last_used = dchan->cookie;
-	spin_unlock_bh(&bdma_chan->lock);
-
-	ret = dma_async_is_complete(cookie, last_completed, last_used);
-
-	dma_set_tx_state(txstate, last_completed, last_used, 0);
-
-	dev_dbg(dchan->device->dev,
-		"%s: exit, ret: %d, last_completed: %d, last_used: %d\n",
-		__func__, ret, last_completed, last_used);
-
-	return ret;
+	return dma_cookie_status(dchan, cookie, txstate);
 }
 
 static void tsi721_issue_pending(struct dma_chan *dchan)
 {
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
 
-	dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
+	dev_dbg(dchan->device->dev, "%s: Enter\n", __func__);
 
-	if (tsi721_dma_is_idle(bdma_chan)) {
+	if (tsi721_dma_is_idle(bdma_chan) && bdma_chan->active) {
 		spin_lock_bh(&bdma_chan->lock);
 		tsi721_advance_work(bdma_chan);
 		spin_unlock_bh(&bdma_chan->lock);
-	} else
-		dev_dbg(dchan->device->dev,
-			"%s: DMA channel still busy\n", __func__);
+	}
 }
 
 static
@@ -668,21 +759,19 @@ struct dma_async_tx_descriptor *tsi721_p
 			void *tinfo)
 {
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-	struct tsi721_tx_desc *desc = NULL;
-	struct tsi721_tx_desc *first = NULL;
-	struct scatterlist *sg;
+	struct tsi721_tx_desc *desc, *_d;
 	struct rio_dma_ext *rext = tinfo;
-	u64 rio_addr = rext->rio_addr; /* limited to 64-bit rio_addr for now */
-	unsigned int i;
-	u32 sys_size = dma_to_mport(dchan->device)->sys_size;
 	enum dma_rtype rtype;
-	dma_addr_t next_addr = -1;
+	struct dma_async_tx_descriptor *txd = NULL;
 
 	if (!sgl || !sg_len) {
 		dev_err(dchan->device->dev, "%s: No SG list\n", __func__);
 		return NULL;
 	}
 
+	dev_dbg(dchan->device->dev, "%s: %s\n", __func__,
+		(dir == DMA_DEV_TO_MEM)?"READ":"WRITE");
+
 	if (dir == DMA_DEV_TO_MEM)
 		rtype = NREAD;
 	else if (dir == DMA_MEM_TO_DEV) {
@@ -704,97 +793,26 @@ struct dma_async_tx_descriptor *tsi721_p
 		return NULL;
 	}
 
-	for_each_sg(sgl, sg, sg_len, i) {
-		int err;
-
-		if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) {
-			dev_err(dchan->device->dev,
-				"%s: SG entry %d is too large\n", __func__, i);
-			goto err_desc_put;
-		}
-
-		/*
-		 * If this sg entry forms contiguous block with previous one,
-		 * try to merge it into existing DMA descriptor
-		 */
-		if (desc) {
-			if (next_addr == sg_dma_address(sg) &&
-			    desc->bcount + sg_dma_len(sg) <=
-						TSI721_BDMA_MAX_BCOUNT) {
-				/* Adjust byte count of the descriptor */
-				desc->bcount += sg_dma_len(sg);
-				goto entry_done;
-			}
-
-			/*
-			 * Finalize this descriptor using total
-			 * byte count value.
-			 */
-			tsi721_desc_fill_end(desc);
-			dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
-				__func__, desc->bcount);
-		}
-
-		/*
-		 * Obtain and initialize a new descriptor
-		 */
-		desc = tsi721_desc_get(bdma_chan);
-		if (!desc) {
-			dev_err(dchan->device->dev,
-				"%s: Failed to get new descriptor for SG %d\n",
-				__func__, i);
-			goto err_desc_put;
-		}
-
-		desc->destid = rext->destid;
-		desc->rio_addr = rio_addr;
-		desc->rio_addr_u = 0;
-		desc->bcount = sg_dma_len(sg);
-
-		dev_dbg(dchan->device->dev,
-			"sg%d desc: 0x%llx, addr: 0x%llx len: %d\n",
-			i, (u64)desc->txd.phys,
-			(unsigned long long)sg_dma_address(sg),
-			sg_dma_len(sg));
-
-		dev_dbg(dchan->device->dev,
-			"bd_ptr = %p did=%d raddr=0x%llx\n",
-			desc->hw_desc, desc->destid, desc->rio_addr);
-
-		err = tsi721_desc_fill_init(desc, sg, rtype, sys_size);
-		if (err) {
-			dev_err(dchan->device->dev,
-				"Failed to build desc: %d\n", err);
-			goto err_desc_put;
-		}
-
-		next_addr = sg_dma_address(sg);
-
-		if (!first)
-			first = desc;
-		else
-			list_add_tail(&desc->desc_node, &first->tx_list);
+	spin_lock_bh(&bdma_chan->lock);
 
-entry_done:
-		if (sg_is_last(sg)) {
-			desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0;
-			tsi721_desc_fill_end(desc);
-			dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
-				__func__, desc->bcount);
-		} else {
-			rio_addr += sg_dma_len(sg);
-			next_addr += sg_dma_len(sg);
+	list_for_each_entry_safe(desc, _d, &bdma_chan->free_list, desc_node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del_init(&desc->desc_node);
+			desc->destid = rext->destid;
+			desc->rio_addr = rext->rio_addr;
+			desc->rio_addr_u = 0;
+			desc->rtype = rtype;
+			desc->sg_len	= sg_len;
+			desc->sg	= sgl;
+			txd		= &desc->txd;
+			txd->flags	= flags;
+			break;
 		}
 	}
 
-	first->txd.cookie = -EBUSY;
-	desc->txd.flags = flags;
-
-	return &first->txd;
+	spin_unlock_bh(&bdma_chan->lock);
 
-err_desc_put:
-	tsi721_desc_put(bdma_chan, first);
-	return NULL;
+	return txd;
 }
 
 static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
@@ -802,23 +820,34 @@ static int tsi721_device_control(struct
 {
 	struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
 	struct tsi721_tx_desc *desc, *_d;
+	u32 dmac_int;
 	LIST_HEAD(list);
 
 	dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
 
 	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
+		return -ENOSYS;
 
 	spin_lock_bh(&bdma_chan->lock);
 
-	/* make sure to stop the transfer */
-	iowrite32(TSI721_DMAC_CTL_SUSP, bdma_chan->regs + TSI721_DMAC_CTL);
+	bdma_chan->active = false;
+
+	if (!tsi721_dma_is_idle(bdma_chan)) {
+		/* make sure to stop the transfer */
+		iowrite32(TSI721_DMAC_CTL_SUSP,
+			  bdma_chan->regs + TSI721_DMAC_CTL);
+
+		/* Wait until DMA channel stops */
+		do {
+			dmac_int = ioread32(bdma_chan->regs + TSI721_DMAC_INT);
+		} while ((dmac_int & TSI721_DMAC_INT_SUSP) == 0);
+	}
 
 	list_splice_init(&bdma_chan->active_list, &list);
 	list_splice_init(&bdma_chan->queue, &list);
 
 	list_for_each_entry_safe(desc, _d, &list, desc_node)
-		tsi721_dma_chain_complete(bdma_chan, desc);
+		tsi721_dma_tx_err(bdma_chan, desc);
 
 	spin_unlock_bh(&bdma_chan->lock);
 
@@ -828,22 +857,18 @@ static int tsi721_device_control(struct
 int tsi721_register_dma(struct tsi721_device *priv)
 {
 	int i;
-	int nr_channels = TSI721_DMA_MAXCH;
+	int nr_channels = 0;
 	int err;
 	struct rio_mport *mport = priv->mport;
 
-	mport->dma.dev = &priv->pdev->dev;
-	mport->dma.chancnt = nr_channels;
-
 	INIT_LIST_HEAD(&mport->dma.channels);
 
-	for (i = 0; i < nr_channels; i++) {
+	for (i = 0; i < TSI721_DMA_MAXCH; i++) {
 		struct tsi721_bdma_chan *bdma_chan = &priv->bdma[i];
 
 		if (i == TSI721_DMACH_MAINT)
 			continue;
 
-		bdma_chan->bd_num = TSI721_BDMA_BD_RING_SZ;
 		bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i);
 
 		bdma_chan->dchan.device = &mport->dma;
@@ -862,12 +887,15 @@ int tsi721_register_dma(struct tsi721_de
 			     (unsigned long)bdma_chan);
 		list_add_tail(&bdma_chan->dchan.device_node,
 			      &mport->dma.channels);
+		nr_channels++;
 	}
 
+	mport->dma.chancnt = nr_channels;
 	dma_cap_zero(mport->dma.cap_mask);
 	dma_cap_set(DMA_PRIVATE, mport->dma.cap_mask);
 	dma_cap_set(DMA_SLAVE, mport->dma.cap_mask);
 
+	mport->dma.dev = &priv->pdev->dev;
 	mport->dma.device_alloc_chan_resources = tsi721_alloc_chan_resources;
 	mport->dma.device_free_chan_resources = tsi721_free_chan_resources;
 	mport->dma.device_tx_status = tsi721_tx_status;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721.h linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721.h
--- linux-libre-3.16-gnu/drivers/rapidio/devices/tsi721.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rapidio/devices/tsi721.h	2014-09-28 17:29:07.000000000 -0400
@@ -644,27 +644,26 @@ enum tsi721_smsg_int_flag {
 
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 
-#define TSI721_BDMA_BD_RING_SZ	128
 #define TSI721_BDMA_MAX_BCOUNT	(TSI721_DMAD_BCOUNT1 + 1)
 
 struct tsi721_tx_desc {
 	struct dma_async_tx_descriptor	txd;
-	struct tsi721_dma_desc		*hw_desc;
 	u16				destid;
 	/* low 64-bits of 66-bit RIO address */
 	u64				rio_addr;
 	/* upper 2-bits of 66-bit RIO address */
 	u8				rio_addr_u;
-	u32				bcount;
-	bool				interrupt;
+	enum dma_rtype			rtype;
 	struct list_head		desc_node;
-	struct list_head		tx_list;
+	struct scatterlist		*sg;
+	unsigned int			sg_len;
+	enum dma_status			status;
 };
 
 struct tsi721_bdma_chan {
 	int		id;
 	void __iomem	*regs;
-	int		bd_num;		/* number of buffer descriptors */
+	int		bd_num;		/* number of HW buffer descriptors */
 	void		*bd_base;	/* start of DMA descriptors */
 	dma_addr_t	bd_phys;
 	void		*sts_base;	/* start of DMA BD status FIFO */
@@ -680,7 +679,6 @@ struct tsi721_bdma_chan {
 	struct list_head	active_list;
 	struct list_head	queue;
 	struct list_head	free_list;
-	dma_cookie_t		completed_cookie;
 	struct tasklet_struct	tasklet;
 	bool			active;
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rapidio/rio.c linux-libre-3.17-rc7-gnu/drivers/rapidio/rio.c
--- linux-libre-3.16-gnu/drivers/rapidio/rio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rapidio/rio.c	2014-09-28 17:29:07.000000000 -0400
@@ -1509,30 +1509,39 @@ EXPORT_SYMBOL_GPL(rio_route_clr_table);
 
 static bool rio_chan_filter(struct dma_chan *chan, void *arg)
 {
-	struct rio_dev *rdev = arg;
+	struct rio_mport *mport = arg;
 
 	/* Check that DMA device belongs to the right MPORT */
-	return (rdev->net->hport ==
-		container_of(chan->device, struct rio_mport, dma));
+	return mport == container_of(chan->device, struct rio_mport, dma);
 }
 
 /**
- * rio_request_dma - request RapidIO capable DMA channel that supports
- *   specified target RapidIO device.
- * @rdev: RIO device control structure
+ * rio_request_mport_dma - request RapidIO capable DMA channel associated
+ *   with specified local RapidIO mport device.
+ * @mport: RIO mport to perform DMA data transfers
  *
  * Returns pointer to allocated DMA channel or NULL if failed.
  */
-struct dma_chan *rio_request_dma(struct rio_dev *rdev)
+struct dma_chan *rio_request_mport_dma(struct rio_mport *mport)
 {
 	dma_cap_mask_t mask;
-	struct dma_chan *dchan;
 
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
-	dchan = dma_request_channel(mask, rio_chan_filter, rdev);
+	return dma_request_channel(mask, rio_chan_filter, mport);
+}
+EXPORT_SYMBOL_GPL(rio_request_mport_dma);
 
-	return dchan;
+/**
+ * rio_request_dma - request RapidIO capable DMA channel that supports
+ *   specified target RapidIO device.
+ * @rdev: RIO device associated with DMA transfer
+ *
+ * Returns pointer to allocated DMA channel or NULL if failed.
+ */
+struct dma_chan *rio_request_dma(struct rio_dev *rdev)
+{
+	return rio_request_mport_dma(rdev->net->hport);
 }
 EXPORT_SYMBOL_GPL(rio_request_dma);
 
@@ -1547,10 +1556,10 @@ void rio_release_dma(struct dma_chan *dc
 EXPORT_SYMBOL_GPL(rio_release_dma);
 
 /**
- * rio_dma_prep_slave_sg - RapidIO specific wrapper
+ * rio_dma_prep_xfer - RapidIO specific wrapper
  *   for device_prep_slave_sg callback defined by DMAENGINE.
- * @rdev: RIO device control structure
  * @dchan: DMA channel to configure
+ * @destid: target RapidIO device destination ID
  * @data: RIO specific data descriptor
  * @direction: DMA data transfer direction (TO or FROM the device)
  * @flags: dmaengine defined flags
@@ -1560,11 +1569,10 @@ EXPORT_SYMBOL_GPL(rio_release_dma);
  * target RIO device.
  * Returns pointer to DMA transaction descriptor or NULL if failed.
  */
-struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
-	struct dma_chan *dchan, struct rio_dma_data *data,
+struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan,
+	u16 destid, struct rio_dma_data *data,
 	enum dma_transfer_direction direction, unsigned long flags)
 {
-	struct dma_async_tx_descriptor *txd = NULL;
 	struct rio_dma_ext rio_ext;
 
 	if (dchan->device->device_prep_slave_sg == NULL) {
@@ -1572,15 +1580,35 @@ struct dma_async_tx_descriptor *rio_dma_
 		return NULL;
 	}
 
-	rio_ext.destid = rdev->destid;
+	rio_ext.destid = destid;
 	rio_ext.rio_addr_u = data->rio_addr_u;
 	rio_ext.rio_addr = data->rio_addr;
 	rio_ext.wr_type = data->wr_type;
 
-	txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len,
-					direction, flags, &rio_ext);
+	return dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len,
+				     direction, flags, &rio_ext);
+}
+EXPORT_SYMBOL_GPL(rio_dma_prep_xfer);
 
-	return txd;
+/**
+ * rio_dma_prep_slave_sg - RapidIO specific wrapper
+ *   for device_prep_slave_sg callback defined by DMAENGINE.
+ * @rdev: RIO device control structure
+ * @dchan: DMA channel to configure
+ * @data: RIO specific data descriptor
+ * @direction: DMA data transfer direction (TO or FROM the device)
+ * @flags: dmaengine defined flags
+ *
+ * Initializes RapidIO capable DMA channel for the specified data transfer.
+ * Uses DMA channel private extension to pass information related to remote
+ * target RIO device.
+ * Returns pointer to DMA transaction descriptor or NULL if failed.
+ */
+struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
+	struct dma_chan *dchan, struct rio_dma_data *data,
+	enum dma_transfer_direction direction, unsigned long flags)
+{
+	return rio_dma_prep_xfer(dchan,	rdev->destid, data, direction, flags);
 }
 EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ras/debugfs.c linux-libre-3.17-rc7-gnu/drivers/ras/debugfs.c
--- linux-libre-3.16-gnu/drivers/ras/debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/ras/debugfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,56 @@
+#include <linux/debugfs.h>
+
+static struct dentry *ras_debugfs_dir;
+
+static atomic_t trace_count = ATOMIC_INIT(0);
+
+int ras_userspace_consumers(void)
+{
+	return atomic_read(&trace_count);
+}
+EXPORT_SYMBOL_GPL(ras_userspace_consumers);
+
+static int trace_show(struct seq_file *m, void *v)
+{
+	return atomic_read(&trace_count);
+}
+
+static int trace_open(struct inode *inode, struct file *file)
+{
+	atomic_inc(&trace_count);
+	return single_open(file, trace_show, NULL);
+}
+
+static int trace_release(struct inode *inode, struct file *file)
+{
+	atomic_dec(&trace_count);
+	return single_release(inode, file);
+}
+
+static const struct file_operations trace_fops = {
+	.open    = trace_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = trace_release,
+};
+
+int __init ras_add_daemon_trace(void)
+{
+	struct dentry *fentry;
+
+	if (!ras_debugfs_dir)
+		return -ENOENT;
+
+	fentry = debugfs_create_file("daemon_active", S_IRUSR, ras_debugfs_dir,
+				     NULL, &trace_fops);
+	if (!fentry)
+		return -ENODEV;
+
+	return 0;
+
+}
+
+void __init ras_debugfs_init(void)
+{
+	ras_debugfs_dir = debugfs_create_dir("ras", NULL);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ras/Kconfig linux-libre-3.17-rc7-gnu/drivers/ras/Kconfig
--- linux-libre-3.16-gnu/drivers/ras/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/ras/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2 @@
+config RAS
+	bool
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ras/Makefile linux-libre-3.17-rc7-gnu/drivers/ras/Makefile
--- linux-libre-3.16-gnu/drivers/ras/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/ras/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_RAS) += ras.o debugfs.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ras/ras.c linux-libre-3.17-rc7-gnu/drivers/ras/ras.c
--- linux-libre-3.16-gnu/drivers/ras/ras.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/ras/ras.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Authors:
+ *	Chen, Gong <gong.chen@linux.intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/ras.h>
+
+#define CREATE_TRACE_POINTS
+#define TRACE_INCLUDE_PATH ../../include/ras
+#include <ras/ras_event.h>
+
+static int __init ras_init(void)
+{
+	int rc = 0;
+
+	ras_debugfs_init();
+	rc = ras_add_daemon_trace();
+
+	return rc;
+}
+subsys_initcall(ras_init);
+
+#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
+EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
+#endif
+EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/88pm800.c linux-libre-3.17-rc7-gnu/drivers/regulator/88pm800.c
--- linux-libre-3.16-gnu/drivers/regulator/88pm800.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/88pm800.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,7 +52,6 @@
 #define PM800_BUCK1_3		(0x3F)
 #define PM800_BUCK2		(0x40)
 #define PM800_BUCK3		(0x41)
-#define PM800_BUCK3		(0x41)
 #define PM800_BUCK4		(0x42)
 #define PM800_BUCK4_1		(0x43)
 #define PM800_BUCK4_2		(0x44)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/88pm8607.c linux-libre-3.17-rc7-gnu/drivers/regulator/88pm8607.c
--- linux-libre-3.16-gnu/drivers/regulator/88pm8607.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/88pm8607.c	2014-09-28 17:29:07.000000000 -0400
@@ -319,7 +319,7 @@ static int pm8607_regulator_dt_init(stru
 				    struct regulator_config *config)
 {
 	struct device_node *nproot, *np;
-	nproot = of_node_get(pdev->dev.parent->of_node);
+	nproot = pdev->dev.parent->of_node;
 	if (!nproot)
 		return -ENODEV;
 	nproot = of_get_child_by_name(nproot, "regulators");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/ab8500.c linux-libre-3.17-rc7-gnu/drivers/regulator/ab8500.c
--- linux-libre-3.16-gnu/drivers/regulator/ab8500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/ab8500.c	2014-09-28 17:29:07.000000000 -0400
@@ -3037,28 +3037,12 @@ static int ab8500_regulator_register(str
 	return 0;
 }
 
-static int
-ab8500_regulator_of_probe(struct platform_device *pdev,
-			  struct device_node *np)
-{
-	struct of_regulator_match *match = abx500_regulator.match;
-	int err, i;
-
-	for (i = 0; i < abx500_regulator.info_size; i++) {
-		err = ab8500_regulator_register(
-			pdev, match[i].init_data, i, match[i].of_node);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
 static int ab8500_regulator_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 	struct device_node *np = pdev->dev.of_node;
-	int err;
+	struct of_regulator_match *match;
+	int err, i;
 
 	if (!ab8500) {
 		dev_err(&pdev->dev, "null mfd parent\n");
@@ -3075,24 +3059,20 @@ static int ab8500_regulator_probe(struct
 			"Error parsing regulator init data: %d\n", err);
 		return err;
 	}
-	return ab8500_regulator_of_probe(pdev, np);
-}
-
-static int ab8500_regulator_remove(struct platform_device *pdev)
-{
-	int err;
 
-	/* remove regulator debug */
-	err = ab8500_regulator_debug_exit(pdev);
-	if (err)
-		return err;
+	match = abx500_regulator.match;
+	for (i = 0; i < abx500_regulator.info_size; i++) {
+		err = ab8500_regulator_register(pdev, match[i].init_data, i,
+						match[i].of_node);
+		if (err)
+			return err;
+	}
 
 	return 0;
 }
 
 static struct platform_driver ab8500_regulator_driver = {
 	.probe = ab8500_regulator_probe,
-	.remove = ab8500_regulator_remove,
 	.driver         = {
 		.name   = "ab8500-regulator",
 		.owner  = THIS_MODULE,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/act8865-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/act8865-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/act8865-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/act8865-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,7 @@
 /*
- * act8865-regulator.c - Voltage regulation for the active-semi ACT8865
- * http://www.active-semi.com/sheets/ACT8865_Datasheet.pdf
+ * act8865-regulator.c - Voltage regulation for active-semi ACT88xx PMUs
+ *
+ * http://www.active-semi.com/products/power-management-units/act88xx/
  *
  * Copyright (C) 2013 Atmel Corporation
  *
@@ -28,6 +29,40 @@
 #include <linux/regmap.h>
 
 /*
+ * ACT8846 Global Register Map.
+ */
+#define	ACT8846_SYS0		0x00
+#define	ACT8846_SYS1		0x01
+#define	ACT8846_REG1_VSET	0x10
+#define	ACT8846_REG1_CTRL	0x12
+#define	ACT8846_REG2_VSET0	0x20
+#define	ACT8846_REG2_VSET1	0x21
+#define	ACT8846_REG2_CTRL	0x22
+#define	ACT8846_REG3_VSET0	0x30
+#define	ACT8846_REG3_VSET1	0x31
+#define	ACT8846_REG3_CTRL	0x32
+#define	ACT8846_REG4_VSET0	0x40
+#define	ACT8846_REG4_VSET1	0x41
+#define	ACT8846_REG4_CTRL	0x42
+#define	ACT8846_REG5_VSET	0x50
+#define	ACT8846_REG5_CTRL	0x51
+#define	ACT8846_REG6_VSET	0x58
+#define	ACT8846_REG6_CTRL	0x59
+#define	ACT8846_REG7_VSET	0x60
+#define	ACT8846_REG7_CTRL	0x61
+#define	ACT8846_REG8_VSET	0x68
+#define	ACT8846_REG8_CTRL	0x69
+#define	ACT8846_REG9_VSET	0x70
+#define	ACT8846_REG9_CTRL	0x71
+#define	ACT8846_REG10_VSET	0x80
+#define	ACT8846_REG10_CTRL	0x81
+#define	ACT8846_REG11_VSET	0x90
+#define	ACT8846_REG11_CTRL	0x91
+#define	ACT8846_REG12_VSET	0xa0
+#define	ACT8846_REG12_CTRL	0xa1
+#define	ACT8846_REG13_CTRL	0xb1
+
+/*
  * ACT8865 Global Register Map.
  */
 #define	ACT8865_SYS_MODE	0x00
@@ -70,7 +105,7 @@ static const struct regmap_config act886
 	.val_bits = 8,
 };
 
-static const struct regulator_linear_range act8865_volatge_ranges[] = {
+static const struct regulator_linear_range act8865_voltage_ranges[] = {
 	REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
 	REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
 	REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
@@ -86,114 +121,70 @@ static struct regulator_ops act8865_ops
 	.is_enabled		= regulator_is_enabled_regmap,
 };
 
-static const struct regulator_desc act8865_reg[] = {
-	{
-		.name = "DCDC_REG1",
-		.id = ACT8865_ID_DCDC1,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_DCDC1_VSET1,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_DCDC1_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "DCDC_REG2",
-		.id = ACT8865_ID_DCDC2,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_DCDC2_VSET1,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_DCDC2_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "DCDC_REG3",
-		.id = ACT8865_ID_DCDC3,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_DCDC3_VSET1,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_DCDC3_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "LDO_REG1",
-		.id = ACT8865_ID_LDO1,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_LDO1_VSET,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_LDO1_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "LDO_REG2",
-		.id = ACT8865_ID_LDO2,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_LDO2_VSET,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_LDO2_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "LDO_REG3",
-		.id = ACT8865_ID_LDO3,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_LDO3_VSET,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_LDO3_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
-	{
-		.name = "LDO_REG4",
-		.id = ACT8865_ID_LDO4,
-		.ops = &act8865_ops,
-		.type = REGULATOR_VOLTAGE,
-		.n_voltages = ACT8865_VOLTAGE_NUM,
-		.linear_ranges = act8865_volatge_ranges,
-		.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
-		.vsel_reg = ACT8865_LDO4_VSET,
-		.vsel_mask = ACT8865_VSEL_MASK,
-		.enable_reg = ACT8865_LDO4_CTRL,
-		.enable_mask = ACT8865_ENA,
-		.owner = THIS_MODULE,
-	},
+#define ACT88xx_REG(_name, _family, _id, _vsel_reg)			\
+	[_family##_ID_##_id] = {					\
+		.name			= _name,			\
+		.id			= _family##_ID_##_id,		\
+		.type			= REGULATOR_VOLTAGE,		\
+		.ops			= &act8865_ops,			\
+		.n_voltages		= ACT8865_VOLTAGE_NUM,		\
+		.linear_ranges		= act8865_voltage_ranges,	\
+		.n_linear_ranges	= ARRAY_SIZE(act8865_voltage_ranges), \
+		.vsel_reg		= _family##_##_id##_##_vsel_reg, \
+		.vsel_mask		= ACT8865_VSEL_MASK,		\
+		.enable_reg		= _family##_##_id##_CTRL,	\
+		.enable_mask		= ACT8865_ENA,			\
+		.owner			= THIS_MODULE,			\
+	}
+
+static const struct regulator_desc act8846_regulators[] = {
+	ACT88xx_REG("REG1", ACT8846, REG1, VSET),
+	ACT88xx_REG("REG2", ACT8846, REG2, VSET0),
+	ACT88xx_REG("REG3", ACT8846, REG3, VSET0),
+	ACT88xx_REG("REG4", ACT8846, REG4, VSET0),
+	ACT88xx_REG("REG5", ACT8846, REG5, VSET),
+	ACT88xx_REG("REG6", ACT8846, REG6, VSET),
+	ACT88xx_REG("REG7", ACT8846, REG7, VSET),
+	ACT88xx_REG("REG8", ACT8846, REG8, VSET),
+	ACT88xx_REG("REG9", ACT8846, REG9, VSET),
+	ACT88xx_REG("REG10", ACT8846, REG10, VSET),
+	ACT88xx_REG("REG11", ACT8846, REG11, VSET),
+	ACT88xx_REG("REG12", ACT8846, REG12, VSET),
+};
+
+static const struct regulator_desc act8865_regulators[] = {
+	ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1),
+	ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1),
+	ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1),
+	ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET),
+	ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET),
+	ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET),
+	ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET),
 };
 
 #ifdef CONFIG_OF
 static const struct of_device_id act8865_dt_ids[] = {
-	{ .compatible = "active-semi,act8865" },
+	{ .compatible = "active-semi,act8846", .data = (void *)ACT8846 },
+	{ .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, act8865_dt_ids);
 
+static struct of_regulator_match act8846_matches[] = {
+	[ACT8846_ID_REG1]	= { .name = "REG1" },
+	[ACT8846_ID_REG2]	= { .name = "REG2" },
+	[ACT8846_ID_REG3]	= { .name = "REG3" },
+	[ACT8846_ID_REG4]	= { .name = "REG4" },
+	[ACT8846_ID_REG5]	= { .name = "REG5" },
+	[ACT8846_ID_REG6]	= { .name = "REG6" },
+	[ACT8846_ID_REG7]	= { .name = "REG7" },
+	[ACT8846_ID_REG8]	= { .name = "REG8" },
+	[ACT8846_ID_REG9]	= { .name = "REG9" },
+	[ACT8846_ID_REG10]	= { .name = "REG10" },
+	[ACT8846_ID_REG11]	= { .name = "REG11" },
+	[ACT8846_ID_REG12]	= { .name = "REG12" },
+};
+
 static struct of_regulator_match act8865_matches[] = {
 	[ACT8865_ID_DCDC1]	= { .name = "DCDC_REG1"},
 	[ACT8865_ID_DCDC2]	= { .name = "DCDC_REG2"},
@@ -206,11 +197,13 @@ static struct of_regulator_match act8865
 
 static int act8865_pdata_from_dt(struct device *dev,
 				 struct device_node **of_node,
-				 struct act8865_platform_data *pdata)
+				 struct act8865_platform_data *pdata,
+				 unsigned long type)
 {
-	int matched, i;
+	int matched, i, num_matches;
 	struct device_node *np;
 	struct act8865_regulator_data *regulator;
+	struct of_regulator_match *matches;
 
 	np = of_get_child_by_name(dev->of_node, "regulators");
 	if (!np) {
@@ -218,26 +211,39 @@ static int act8865_pdata_from_dt(struct
 		return -EINVAL;
 	}
 
-	matched = of_regulator_match(dev, np,
-				act8865_matches, ARRAY_SIZE(act8865_matches));
+	switch (type) {
+	case ACT8846:
+		matches = act8846_matches;
+		num_matches = ARRAY_SIZE(act8846_matches);
+		break;
+	case ACT8865:
+		matches = act8865_matches;
+		num_matches = ARRAY_SIZE(act8865_matches);
+		break;
+	default:
+		dev_err(dev, "invalid device id %lu\n", type);
+		return -EINVAL;
+	}
+
+	matched = of_regulator_match(dev, np, matches, num_matches);
 	of_node_put(np);
 	if (matched <= 0)
 		return matched;
 
 	pdata->regulators = devm_kzalloc(dev,
-				sizeof(struct act8865_regulator_data) *
-				ARRAY_SIZE(act8865_matches), GFP_KERNEL);
+					 sizeof(struct act8865_regulator_data) *
+					 num_matches, GFP_KERNEL);
 	if (!pdata->regulators)
 		return -ENOMEM;
 
-	pdata->num_regulators = matched;
+	pdata->num_regulators = num_matches;
 	regulator = pdata->regulators;
 
-	for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) {
+	for (i = 0; i < num_matches; i++) {
 		regulator->id = i;
-		regulator->name = act8865_matches[i].name;
-		regulator->platform_data = act8865_matches[i].init_data;
-		of_node[i] = act8865_matches[i].of_node;
+		regulator->name = matches[i].name;
+		regulator->platform_data = matches[i].init_data;
+		of_node[i] = matches[i].of_node;
 		regulator++;
 	}
 
@@ -246,42 +252,84 @@ static int act8865_pdata_from_dt(struct
 #else
 static inline int act8865_pdata_from_dt(struct device *dev,
 					struct device_node **of_node,
-					struct act8865_platform_data *pdata)
+					struct act8865_platform_data *pdata,
+					unsigned long type)
 {
 	return 0;
 }
 #endif
 
+static struct regulator_init_data
+*act8865_get_init_data(int id, struct act8865_platform_data *pdata)
+{
+	int i;
+
+	if (!pdata)
+		return NULL;
+
+	for (i = 0; i < pdata->num_regulators; i++) {
+		if (pdata->regulators[i].id == id)
+			return pdata->regulators[i].platform_data;
+	}
+
+	return NULL;
+}
+
 static int act8865_pmic_probe(struct i2c_client *client,
-			   const struct i2c_device_id *i2c_id)
+			      const struct i2c_device_id *i2c_id)
 {
-	struct regulator_dev *rdev;
+	static const struct regulator_desc *regulators;
+	struct act8865_platform_data pdata_of, *pdata;
 	struct device *dev = &client->dev;
-	struct act8865_platform_data *pdata = dev_get_platdata(dev);
-	struct regulator_config config = { };
+	struct device_node **of_node;
+	int i, ret, num_regulators;
 	struct act8865 *act8865;
-	struct device_node *of_node[ACT8865_REG_NUM];
-	int i, id;
-	int ret = -EINVAL;
-	int error;
+	unsigned long type;
+
+	pdata = dev_get_platdata(dev);
 
 	if (dev->of_node && !pdata) {
 		const struct of_device_id *id;
-		struct act8865_platform_data pdata_of;
 
 		id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
 		if (!id)
 			return -ENODEV;
 
-		ret = act8865_pdata_from_dt(dev, of_node, &pdata_of);
+		type = (unsigned long) id->data;
+	} else {
+		type = i2c_id->driver_data;
+	}
+
+	switch (type) {
+	case ACT8846:
+		regulators = act8846_regulators;
+		num_regulators = ARRAY_SIZE(act8846_regulators);
+		break;
+	case ACT8865:
+		regulators = act8865_regulators;
+		num_regulators = ARRAY_SIZE(act8865_regulators);
+		break;
+	default:
+		dev_err(dev, "invalid device id %lu\n", type);
+		return -EINVAL;
+	}
+
+	of_node = devm_kzalloc(dev, sizeof(struct device_node *) *
+			       num_regulators, GFP_KERNEL);
+	if (!of_node)
+		return -ENOMEM;
+
+	if (dev->of_node && !pdata) {
+		ret = act8865_pdata_from_dt(dev, of_node, &pdata_of, type);
 		if (ret < 0)
 			return ret;
 
 		pdata = &pdata_of;
 	}
 
-	if (pdata->num_regulators > ACT8865_REG_NUM) {
-		dev_err(dev, "Too many regulators found!\n");
+	if (pdata->num_regulators > num_regulators) {
+		dev_err(dev, "too many regulators: %d\n",
+			pdata->num_regulators);
 		return -EINVAL;
 	}
 
@@ -291,39 +339,40 @@ static int act8865_pmic_probe(struct i2c
 
 	act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
 	if (IS_ERR(act8865->regmap)) {
-		error = PTR_ERR(act8865->regmap);
+		ret = PTR_ERR(act8865->regmap);
 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
-			error);
-		return error;
+			ret);
+		return ret;
 	}
 
 	/* Finally register devices */
-	for (i = 0; i < ACT8865_REG_NUM; i++) {
-
-		id = pdata->regulators[i].id;
+	for (i = 0; i < num_regulators; i++) {
+		const struct regulator_desc *desc = &regulators[i];
+		struct regulator_config config = { };
+		struct regulator_dev *rdev;
 
 		config.dev = dev;
-		config.init_data = pdata->regulators[i].platform_data;
+		config.init_data = act8865_get_init_data(desc->id, pdata);
 		config.of_node = of_node[i];
 		config.driver_data = act8865;
 		config.regmap = act8865->regmap;
 
-		rdev = devm_regulator_register(&client->dev, &act8865_reg[i],
-					       &config);
+		rdev = devm_regulator_register(&client->dev, desc, &config);
 		if (IS_ERR(rdev)) {
-			dev_err(dev, "failed to register %s\n",
-				act8865_reg[id].name);
+			dev_err(dev, "failed to register %s\n", desc->name);
 			return PTR_ERR(rdev);
 		}
 	}
 
 	i2c_set_clientdata(client, act8865);
+	devm_kfree(dev, of_node);
 
 	return 0;
 }
 
 static const struct i2c_device_id act8865_ids[] = {
-	{ "act8865", 0 },
+	{ .name = "act8846", .driver_data = ACT8846 },
+	{ .name = "act8865", .driver_data = ACT8865 },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, act8865_ids);
@@ -339,6 +388,6 @@ static struct i2c_driver act8865_pmic_dr
 
 module_i2c_driver(act8865_pmic_driver);
 
-MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver");
+MODULE_DESCRIPTION("active-semi act88xx voltage regulator driver");
 MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/arizona-ldo1.c linux-libre-3.17-rc7-gnu/drivers/regulator/arizona-ldo1.c
--- linux-libre-3.16-gnu/drivers/regulator/arizona-ldo1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/arizona-ldo1.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,8 +143,6 @@ static struct regulator_ops arizona_ldo1
 	.map_voltage = regulator_map_voltage_linear,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
-	.get_bypass = regulator_get_bypass_regmap,
-	.set_bypass = regulator_set_bypass_regmap,
 };
 
 static const struct regulator_desc arizona_ldo1 = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/as3722-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/as3722-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/as3722-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/as3722-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,7 @@ static const struct as3722_register_mapp
 	{
 		.regulator_id = AS3722_REGULATOR_ID_LDO3,
 		.name = "as3722-ldo3",
-		.name = "vin-ldo3-4",
+		.sname = "vin-ldo3-4",
 		.vsel_reg = AS3722_LDO3_VOLTAGE_REG,
 		.vsel_mask = AS3722_LDO3_VSEL_MASK,
 		.enable_reg = AS3722_LDOCONTROL0_REG,
@@ -231,7 +231,7 @@ static const struct as3722_register_mapp
 	{
 		.regulator_id = AS3722_REGULATOR_ID_LDO4,
 		.name = "as3722-ldo4",
-		.name = "vin-ldo3-4",
+		.sname = "vin-ldo3-4",
 		.vsel_reg = AS3722_LDO4_VOLTAGE_REG,
 		.vsel_mask = AS3722_LDO_VSEL_MASK,
 		.enable_reg = AS3722_LDOCONTROL0_REG,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/bcm590xx-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/bcm590xx-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/bcm590xx-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/bcm590xx-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -331,10 +331,8 @@ static struct bcm590xx_board *bcm590xx_p
 	}
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		dev_err(&pdev->dev, "failed to allocate regulator board data\n");
+	if (!data)
 		return NULL;
-	}
 
 	np = of_node_get(np);
 	regulators = of_get_child_by_name(np, "regulators");
@@ -379,10 +377,8 @@ static int bcm590xx_probe(struct platfor
 					      &bcm590xx_reg_matches);
 
 	pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
-	if (!pmu) {
-		dev_err(&pdev->dev, "Memory allocation failed for pmu\n");
+	if (!pmu)
 		return -ENOMEM;
-	}
 
 	pmu->mfd = bcm590xx;
 
@@ -390,17 +386,13 @@ static int bcm590xx_probe(struct platfor
 
 	pmu->desc = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS *
 			sizeof(struct regulator_desc), GFP_KERNEL);
-	if (!pmu->desc) {
-		dev_err(&pdev->dev, "Memory alloc fails for desc\n");
+	if (!pmu->desc)
 		return -ENOMEM;
-	}
 
 	pmu->info = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS *
 			sizeof(struct bcm590xx_info *), GFP_KERNEL);
-	if (!pmu->info) {
-		dev_err(&pdev->dev, "Memory alloc fails for info\n");
+	if (!pmu->info)
 		return -ENOMEM;
-	}
 
 	info = bcm590xx_regs;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/core.c linux-libre-3.17-rc7-gnu/drivers/regulator/core.c
--- linux-libre-3.16-gnu/drivers/regulator/core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/core.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
@@ -77,7 +78,7 @@ struct regulator_map {
  */
 struct regulator_enable_gpio {
 	struct list_head list;
-	int gpio;
+	struct gpio_desc *gpiod;
 	u32 enable_count;	/* a number of enabled shared GPIO */
 	u32 request_count;	/* a number of requested shared GPIO */
 	unsigned int ena_gpio_invert:1;
@@ -846,7 +847,9 @@ static int machine_constraints_voltage(s
 	    rdev->constraints->min_uV == rdev->constraints->max_uV) {
 		int current_uV = _regulator_get_voltage(rdev);
 		if (current_uV < 0) {
-			rdev_err(rdev, "failed to get the current voltage\n");
+			rdev_err(rdev,
+				 "failed to get the current voltage(%d)\n",
+				 current_uV);
 			return current_uV;
 		}
 		if (current_uV < rdev->constraints->min_uV ||
@@ -856,8 +859,8 @@ static int machine_constraints_voltage(s
 				rdev->constraints->max_uV);
 			if (ret < 0) {
 				rdev_err(rdev,
-					"failed to apply %duV constraint\n",
-					rdev->constraints->min_uV);
+					"failed to apply %duV constraint(%d)\n",
+					rdev->constraints->min_uV, ret);
 				return ret;
 			}
 		}
@@ -1660,10 +1663,13 @@ static int regulator_ena_gpio_request(st
 				const struct regulator_config *config)
 {
 	struct regulator_enable_gpio *pin;
+	struct gpio_desc *gpiod;
 	int ret;
 
+	gpiod = gpio_to_desc(config->ena_gpio);
+
 	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
-		if (pin->gpio == config->ena_gpio) {
+		if (pin->gpiod == gpiod) {
 			rdev_dbg(rdev, "GPIO %d is already used\n",
 				config->ena_gpio);
 			goto update_ena_gpio_to_rdev;
@@ -1682,7 +1688,7 @@ static int regulator_ena_gpio_request(st
 		return -ENOMEM;
 	}
 
-	pin->gpio = config->ena_gpio;
+	pin->gpiod = gpiod;
 	pin->ena_gpio_invert = config->ena_gpio_invert;
 	list_add(&pin->list, &regulator_ena_gpio_list);
 
@@ -1701,10 +1707,10 @@ static void regulator_ena_gpio_free(stru
 
 	/* Free the GPIO only in case of no use */
 	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
-		if (pin->gpio == rdev->ena_pin->gpio) {
+		if (pin->gpiod == rdev->ena_pin->gpiod) {
 			if (pin->request_count <= 1) {
 				pin->request_count = 0;
-				gpio_free(pin->gpio);
+				gpiod_put(pin->gpiod);
 				list_del(&pin->list);
 				kfree(pin);
 			} else {
@@ -1732,8 +1738,8 @@ static int regulator_ena_gpio_ctrl(struc
 	if (enable) {
 		/* Enable GPIO at initial use */
 		if (pin->enable_count == 0)
-			gpio_set_value_cansleep(pin->gpio,
-						!pin->ena_gpio_invert);
+			gpiod_set_value_cansleep(pin->gpiod,
+						 !pin->ena_gpio_invert);
 
 		pin->enable_count++;
 	} else {
@@ -1744,8 +1750,8 @@ static int regulator_ena_gpio_ctrl(struc
 
 		/* Disable GPIO if not used */
 		if (pin->enable_count <= 1) {
-			gpio_set_value_cansleep(pin->gpio,
-						pin->ena_gpio_invert);
+			gpiod_set_value_cansleep(pin->gpiod,
+						 pin->ena_gpio_invert);
 			pin->enable_count = 0;
 		}
 	}
@@ -2180,7 +2186,13 @@ int regulator_count_voltages(struct regu
 {
 	struct regulator_dev	*rdev = regulator->rdev;
 
-	return rdev->desc->n_voltages ? : -EINVAL;
+	if (rdev->desc->n_voltages)
+		return rdev->desc->n_voltages;
+
+	if (!rdev->supply)
+		return -EINVAL;
+
+	return regulator_count_voltages(rdev->supply);
 }
 EXPORT_SYMBOL_GPL(regulator_count_voltages);
 
@@ -2203,12 +2215,17 @@ int regulator_list_voltage(struct regula
 	if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
 		return rdev->desc->fixed_uV;
 
-	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
+	if (ops->list_voltage) {
+		if (selector >= rdev->desc->n_voltages)
+			return -EINVAL;
+		mutex_lock(&rdev->mutex);
+		ret = ops->list_voltage(rdev, selector);
+		mutex_unlock(&rdev->mutex);
+	} else if (rdev->supply) {
+		ret = regulator_list_voltage(rdev->supply, selector);
+	} else {
 		return -EINVAL;
-
-	mutex_lock(&rdev->mutex);
-	ret = ops->list_voltage(rdev, selector);
-	mutex_unlock(&rdev->mutex);
+	}
 
 	if (ret > 0) {
 		if (ret < rdev->constraints->min_uV)
@@ -2222,6 +2239,77 @@ int regulator_list_voltage(struct regula
 EXPORT_SYMBOL_GPL(regulator_list_voltage);
 
 /**
+ * regulator_get_regmap - get the regulator's register map
+ * @regulator: regulator source
+ *
+ * Returns the register map for the given regulator, or an ERR_PTR value
+ * if the regulator doesn't use regmap.
+ */
+struct regmap *regulator_get_regmap(struct regulator *regulator)
+{
+	struct regmap *map = regulator->rdev->regmap;
+
+	return map ? map : ERR_PTR(-EOPNOTSUPP);
+}
+
+/**
+ * regulator_get_hardware_vsel_register - get the HW voltage selector register
+ * @regulator: regulator source
+ * @vsel_reg: voltage selector register, output parameter
+ * @vsel_mask: mask for voltage selector bitfield, output parameter
+ *
+ * Returns the hardware register offset and bitmask used for setting the
+ * regulator voltage. This might be useful when configuring voltage-scaling
+ * hardware or firmware that can make I2C requests behind the kernel's back,
+ * for example.
+ *
+ * On success, the output parameters @vsel_reg and @vsel_mask are filled in
+ * and 0 is returned, otherwise a negative errno is returned.
+ */
+int regulator_get_hardware_vsel_register(struct regulator *regulator,
+					 unsigned *vsel_reg,
+					 unsigned *vsel_mask)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops = rdev->desc->ops;
+
+	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
+		return -EOPNOTSUPP;
+
+	 *vsel_reg = rdev->desc->vsel_reg;
+	 *vsel_mask = rdev->desc->vsel_mask;
+
+	 return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
+
+/**
+ * regulator_list_hardware_vsel - get the HW-specific register value for a selector
+ * @regulator: regulator source
+ * @selector: identify voltage to list
+ *
+ * Converts the selector to a hardware-specific voltage selector that can be
+ * directly written to the regulator registers. The address of the voltage
+ * register can be determined by calling @regulator_get_hardware_vsel_register.
+ *
+ * On error a negative errno is returned.
+ */
+int regulator_list_hardware_vsel(struct regulator *regulator,
+				 unsigned selector)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops = rdev->desc->ops;
+
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
+		return -EOPNOTSUPP;
+
+	return selector;
+}
+EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
+
+/**
  * regulator_get_linear_step - return the voltage step size between VSEL values
  * @regulator: regulator source
  *
@@ -2618,6 +2706,8 @@ static int _regulator_get_voltage(struct
 		ret = rdev->desc->ops->list_voltage(rdev, 0);
 	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
 		ret = rdev->desc->fixed_uV;
+	} else if (rdev->supply) {
+		ret = regulator_get_voltage(rdev->supply);
 	} else {
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/da9052-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/da9052-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/da9052-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/da9052-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -422,9 +422,9 @@ static int da9052_regulator_probe(struct
 		config.init_data = pdata->regulators[pdev->id];
 	} else {
 #ifdef CONFIG_OF
-		struct device_node *nproot, *np;
+		struct device_node *nproot = da9052->dev->of_node;
+		struct device_node *np;
 
-		nproot = of_node_get(da9052->dev->of_node);
 		if (!nproot)
 			return -ENODEV;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/da9211-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/da9211-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/da9211-regulator.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/da9211-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,368 @@
+/*
+ * da9211-regulator.c - Regulator device driver for DA9211
+ * Copyright (C) 2014  Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/regulator/da9211.h>
+#include "da9211-regulator.h"
+
+#define DA9211_BUCK_MODE_SLEEP	1
+#define DA9211_BUCK_MODE_SYNC	2
+#define DA9211_BUCK_MODE_AUTO	3
+
+/* DA9211 REGULATOR IDs */
+#define DA9211_ID_BUCKA	0
+#define DA9211_ID_BUCKB	1
+
+struct da9211 {
+	struct device *dev;
+	struct regmap *regmap;
+	struct da9211_pdata *pdata;
+	struct regulator_dev *rdev[DA9211_MAX_REGULATORS];
+	int num_regulator;
+	int chip_irq;
+};
+
+static const struct regmap_range_cfg da9211_regmap_range[] = {
+	{
+		.selector_reg = DA9211_REG_PAGE_CON,
+		.selector_mask  = DA9211_REG_PAGE_MASK,
+		.selector_shift = DA9211_REG_PAGE_SHIFT,
+		.window_start = 0,
+		.window_len = 256,
+		.range_min = 0,
+		.range_max = 2*256,
+	},
+};
+
+static const struct regmap_config da9211_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 2 * 256,
+	.ranges = da9211_regmap_range,
+	.num_ranges = ARRAY_SIZE(da9211_regmap_range),
+};
+
+/* Default limits measured in millivolts and milliamps */
+#define DA9211_MIN_MV		300
+#define DA9211_MAX_MV		1570
+#define DA9211_STEP_MV		10
+
+/* Current limits for buck (uA) indices corresponds with register values */
+static const int da9211_current_limits[] = {
+	2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000,
+	3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000
+};
+
+static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
+{
+	int id = rdev_get_id(rdev);
+	struct da9211 *chip = rdev_get_drvdata(rdev);
+	unsigned int data;
+	int ret, mode = 0;
+
+	ret = regmap_read(chip->regmap, DA9211_REG_BUCKA_CONF+id, &data);
+	if (ret < 0)
+		return ret;
+
+	switch (data & 0x03) {
+	case DA9211_BUCK_MODE_SYNC:
+		mode = REGULATOR_MODE_FAST;
+		break;
+	case DA9211_BUCK_MODE_AUTO:
+		mode = REGULATOR_MODE_NORMAL;
+		break;
+	case DA9211_BUCK_MODE_SLEEP:
+		mode = REGULATOR_MODE_STANDBY;
+		break;
+	}
+
+	return mode;
+}
+
+static int da9211_buck_set_mode(struct regulator_dev *rdev,
+					unsigned int mode)
+{
+	int id = rdev_get_id(rdev);
+	struct da9211 *chip = rdev_get_drvdata(rdev);
+	int val = 0;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = DA9211_BUCK_MODE_SYNC;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = DA9211_BUCK_MODE_AUTO;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val = DA9211_BUCK_MODE_SLEEP;
+		break;
+	}
+
+	return regmap_update_bits(chip->regmap, DA9211_REG_BUCKA_CONF+id,
+					0x03, val);
+}
+
+static int da9211_set_current_limit(struct regulator_dev *rdev, int min,
+				    int max)
+{
+	int id = rdev_get_id(rdev);
+	struct da9211 *chip = rdev_get_drvdata(rdev);
+	int i;
+
+	/* search for closest to maximum */
+	for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) {
+		if (min <= da9211_current_limits[i] &&
+		    max >= da9211_current_limits[i]) {
+				return regmap_update_bits(chip->regmap,
+					DA9211_REG_BUCK_ILIM,
+					(0x0F << id*4), (i << id*4));
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int da9211_get_current_limit(struct regulator_dev *rdev)
+{
+	int id = rdev_get_id(rdev);
+	struct da9211 *chip = rdev_get_drvdata(rdev);
+	unsigned int data;
+	int ret;
+
+	ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data);
+	if (ret < 0)
+		return ret;
+
+	/* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */
+	data = (data >> id*4) & 0x0F;
+	return da9211_current_limits[data];
+}
+
+static struct regulator_ops da9211_buck_ops = {
+	.get_mode = da9211_buck_get_mode,
+	.set_mode = da9211_buck_set_mode,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.set_current_limit = da9211_set_current_limit,
+	.get_current_limit = da9211_get_current_limit,
+};
+
+#define DA9211_BUCK(_id) \
+{\
+	.name = #_id,\
+	.ops = &da9211_buck_ops,\
+	.type = REGULATOR_VOLTAGE,\
+	.id = DA9211_ID_##_id,\
+	.n_voltages = (DA9211_MAX_MV - DA9211_MIN_MV) / DA9211_STEP_MV + 1,\
+	.min_uV = (DA9211_MIN_MV * 1000),\
+	.uV_step = (DA9211_STEP_MV * 1000),\
+	.enable_reg = DA9211_REG_BUCKA_CONT + DA9211_ID_##_id,\
+	.enable_mask = DA9211_BUCKA_EN,\
+	.vsel_reg = DA9211_REG_VBUCKA_A + DA9211_ID_##_id * 2,\
+	.vsel_mask = DA9211_VBUCK_MASK,\
+	.owner = THIS_MODULE,\
+}
+
+static struct regulator_desc da9211_regulators[] = {
+	DA9211_BUCK(BUCKA),
+	DA9211_BUCK(BUCKB),
+};
+
+static irqreturn_t da9211_irq_handler(int irq, void *data)
+{
+	struct da9211 *chip = data;
+	int reg_val, err, ret = IRQ_NONE;
+
+	err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, &reg_val);
+	if (err < 0)
+		goto error_i2c;
+
+	if (reg_val & DA9211_E_OV_CURR_A) {
+		regulator_notifier_call_chain(chip->rdev[0],
+			REGULATOR_EVENT_OVER_CURRENT,
+			rdev_get_drvdata(chip->rdev[0]));
+
+		err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
+			DA9211_E_OV_CURR_A);
+		if (err < 0)
+			goto error_i2c;
+
+		ret = IRQ_HANDLED;
+	}
+
+	if (reg_val & DA9211_E_OV_CURR_B) {
+		regulator_notifier_call_chain(chip->rdev[1],
+			REGULATOR_EVENT_OVER_CURRENT,
+			rdev_get_drvdata(chip->rdev[1]));
+
+		err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
+			DA9211_E_OV_CURR_B);
+		if (err < 0)
+			goto error_i2c;
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+
+error_i2c:
+	dev_err(chip->dev, "I2C error : %d\n", err);
+	return IRQ_NONE;
+}
+
+static int da9211_regulator_init(struct da9211 *chip)
+{
+	struct regulator_config config = { };
+	int i, ret;
+	unsigned int data;
+
+	ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read CONTROL_E reg: %d\n", ret);
+		return ret;
+	}
+
+	data &= DA9211_SLAVE_SEL;
+	/* If configuration for 1/2 bucks is different between platform data
+	 * and the register, driver should exit.
+	 */
+	if ((chip->pdata->num_buck == 2 && data == 0x40)
+		|| (chip->pdata->num_buck == 1 && data == 0x00)) {
+		if (data == 0)
+			chip->num_regulator = 1;
+		else
+			chip->num_regulator = 2;
+	} else {
+		dev_err(chip->dev, "Configuration is mismatched\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < chip->num_regulator; i++) {
+		if (chip->pdata)
+			config.init_data =
+				&(chip->pdata->init_data[i]);
+
+		config.dev = chip->dev;
+		config.driver_data = chip;
+		config.regmap = chip->regmap;
+
+		chip->rdev[i] = devm_regulator_register(chip->dev,
+			&da9211_regulators[i], &config);
+		if (IS_ERR(chip->rdev[i])) {
+			dev_err(chip->dev,
+				"Failed to register DA9211 regulator\n");
+			return PTR_ERR(chip->rdev[i]);
+		}
+
+		if (chip->chip_irq != 0) {
+			ret = regmap_update_bits(chip->regmap,
+				DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 1);
+			if (ret < 0) {
+				dev_err(chip->dev,
+					"Failed to update mask reg: %d\n", ret);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+/*
+ * I2C driver interface functions
+ */
+static int da9211_i2c_probe(struct i2c_client *i2c,
+		const struct i2c_device_id *id)
+{
+	struct da9211 *chip;
+	int error, ret;
+
+	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL);
+
+	chip->dev = &i2c->dev;
+	chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		error = PTR_ERR(chip->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			error);
+		return error;
+	}
+
+	i2c_set_clientdata(i2c, chip);
+
+	chip->pdata = i2c->dev.platform_data;
+	if (!chip->pdata) {
+		dev_err(&i2c->dev, "No platform init data supplied\n");
+		return -ENODEV;
+	}
+
+	chip->chip_irq = i2c->irq;
+
+	if (chip->chip_irq != 0) {
+		ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+					da9211_irq_handler,
+					IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+					"da9211", chip);
+		if (ret != 0) {
+			dev_err(chip->dev, "Failed to request IRQ: %d\n",
+				chip->chip_irq);
+			return ret;
+		}
+	} else {
+		dev_warn(chip->dev, "No IRQ configured\n");
+	}
+
+	ret = da9211_regulator_init(chip);
+
+	if (ret < 0)
+		dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret);
+
+	return ret;
+}
+
+static const struct i2c_device_id da9211_i2c_id[] = {
+	{"da9211", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
+
+static struct i2c_driver da9211_regulator_driver = {
+	.driver = {
+		.name = "da9211",
+		.owner = THIS_MODULE,
+	},
+	.probe = da9211_i2c_probe,
+	.id_table = da9211_i2c_id,
+};
+
+module_i2c_driver(da9211_regulator_driver);
+
+MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
+MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/da9211-regulator.h linux-libre-3.17-rc7-gnu/drivers/regulator/da9211-regulator.h
--- linux-libre-3.16-gnu/drivers/regulator/da9211-regulator.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/da9211-regulator.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,271 @@
+/*
+ * da9211-regulator.h - Regulator definitions for DA9211
+ * Copyright (C) 2014  Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ */
+
+#ifndef __DA9211_REGISTERS_H__
+#define __DA9211_REGISTERS_H__
+
+/* Page selection */
+#define	DA9211_REG_PAGE_CON			0x00
+
+/* System Control and Event Registers */
+#define	DA9211_REG_STATUS_A			0x50
+#define	DA9211_REG_STATUS_B			0x51
+#define	DA9211_REG_EVENT_A			0x52
+#define	DA9211_REG_EVENT_B			0x53
+#define	DA9211_REG_MASK_A			0x54
+#define	DA9211_REG_MASK_B			0x55
+#define	DA9211_REG_CONTROL_A		0x56
+
+/* GPIO Control Registers */
+#define	DA9211_REG_GPIO_0_1			0x58
+#define	DA9211_REG_GPIO_2_3			0x59
+#define	DA9211_REG_GPIO_4			0x5A
+
+/* Regulator Registers */
+#define	DA9211_REG_BUCKA_CONT			0x5D
+#define	DA9211_REG_BUCKB_CONT			0x5E
+#define	DA9211_REG_BUCK_ILIM			0xD0
+#define	DA9211_REG_BUCKA_CONF			0xD1
+#define	DA9211_REG_BUCKB_CONF			0xD2
+#define	DA9211_REG_BUCK_CONF			0xD3
+#define	DA9211_REG_VBACKA_MAX			0xD5
+#define	DA9211_REG_VBACKB_MAX			0xD6
+#define	DA9211_REG_VBUCKA_A				0xD7
+#define	DA9211_REG_VBUCKA_B				0xD8
+#define	DA9211_REG_VBUCKB_A				0xD9
+#define	DA9211_REG_VBUCKB_B				0xDA
+
+/* I2C Interface Settings */
+#define DA9211_REG_INTERFACE			0x105
+
+/* BUCK Phase Selection*/
+#define DA9211_REG_CONFIG_E			0x147
+
+/*
+ * Registers bits
+ */
+/* DA9211_REG_PAGE_CON (addr=0x00) */
+#define	DA9211_REG_PAGE_SHIFT			1
+#define	DA9211_REG_PAGE_MASK			0x02
+/* On I2C registers 0x00 - 0xFF */
+#define	DA9211_REG_PAGE0			0
+/* On I2C registers 0x100 - 0x1FF */
+#define	DA9211_REG_PAGE2			2
+#define	DA9211_PAGE_WRITE_MODE			0x00
+#define	DA9211_REPEAT_WRITE_MODE		0x40
+#define	DA9211_PAGE_REVERT			0x80
+
+/* DA9211_REG_STATUS_A (addr=0x50) */
+#define	DA9211_GPI0				0x01
+#define	DA9211_GPI1				0x02
+#define	DA9211_GPI2				0x04
+#define	DA9211_GPI3				0x08
+#define	DA9211_GPI4				0x10
+
+/* DA9211_REG_EVENT_A (addr=0x52) */
+#define	DA9211_E_GPI0				0x01
+#define	DA9211_E_GPI1				0x02
+#define	DA9211_E_GPI2				0x04
+#define	DA9211_E_GPI3				0x08
+#define	DA9211_E_GPI4				0x10
+#define	DA9211_E_UVLO_IO			0x40
+
+/* DA9211_REG_EVENT_B (addr=0x53) */
+#define	DA9211_E_PWRGOOD_A			0x01
+#define	DA9211_E_PWRGOOD_B			0x02
+#define	DA9211_E_TEMP_WARN			0x04
+#define	DA9211_E_TEMP_CRIT			0x08
+#define	DA9211_E_OV_CURR_A			0x10
+#define	DA9211_E_OV_CURR_B			0x20
+
+/* DA9211_REG_MASK_A (addr=0x54) */
+#define	DA9211_M_GPI0				0x01
+#define	DA9211_M_GPI1				0x02
+#define	DA9211_M_GPI2				0x04
+#define	DA9211_M_GPI3				0x08
+#define	DA9211_M_GPI4				0x10
+#define	DA9211_M_UVLO_IO			0x40
+
+/* DA9211_REG_MASK_B (addr=0x55) */
+#define	DA9211_M_PWRGOOD_A			0x01
+#define	DA9211_M_PWRGOOD_B			0x02
+#define	DA9211_M_TEMP_WARN			0x04
+#define	DA9211_M_TEMP_CRIT			0x08
+#define	DA9211_M_OV_CURR_A			0x10
+#define	DA9211_M_OV_CURR_B			0x20
+
+/* DA9211_REG_CONTROL_A (addr=0x56) */
+#define	DA9211_DEBOUNCING_SHIFT		0
+#define	DA9211_DEBOUNCING_MASK		0x07
+#define	DA9211_SLEW_RATE_SHIFT		3
+#define	DA9211_SLEW_RATE_A_MASK		0x18
+#define	DA9211_SLEW_RATE_B_SHIFT	5
+#define	DA9211_SLEW_RATE_B_MASK		0x60
+#define	DA9211_V_LOCK				0x80
+
+/* DA9211_REG_GPIO_0_1 (addr=0x58) */
+#define	DA9211_GPIO0_PIN_SHIFT		0
+#define	DA9211_GPIO0_PIN_MASK		0x03
+#define	DA9211_GPIO0_PIN_GPI		0x00
+#define	DA9211_GPIO0_PIN_GPO_OD		0x02
+#define	DA9211_GPIO0_PIN_GPO		0x03
+#define	DA9211_GPIO0_TYPE			0x04
+#define	DA9211_GPIO0_TYPE_GPI		0x00
+#define	DA9211_GPIO0_TYPE_GPO		0x04
+#define	DA9211_GPIO0_MODE			0x08
+#define	DA9211_GPIO1_PIN_SHIFT		4
+#define	DA9211_GPIO1_PIN_MASK		0x30
+#define	DA9211_GPIO1_PIN_GPI		0x00
+#define	DA9211_GPIO1_PIN_VERROR		0x10
+#define	DA9211_GPIO1_PIN_GPO_OD		0x20
+#define	DA9211_GPIO1_PIN_GPO		0x30
+#define	DA9211_GPIO1_TYPE_SHIFT		0x40
+#define	DA9211_GPIO1_TYPE_GPI		0x00
+#define	DA9211_GPIO1_TYPE_GPO		0x40
+#define	DA9211_GPIO1_MODE			0x80
+
+/* DA9211_REG_GPIO_2_3 (addr=0x59) */
+#define	DA9211_GPIO2_PIN_SHIFT		0
+#define	DA9211_GPIO2_PIN_MASK		0x03
+#define	DA9211_GPIO2_PIN_GPI		0x00
+#define	DA9211_GPIO5_PIN_BUCK_CLK	0x10
+#define	DA9211_GPIO2_PIN_GPO_OD		0x02
+#define	DA9211_GPIO2_PIN_GPO		0x03
+#define	DA9211_GPIO2_TYPE			0x04
+#define	DA9211_GPIO2_TYPE_GPI		0x00
+#define	DA9211_GPIO2_TYPE_GPO		0x04
+#define	DA9211_GPIO2_MODE			0x08
+#define	DA9211_GPIO3_PIN_SHIFT		4
+#define	DA9211_GPIO3_PIN_MASK		0x30
+#define	DA9211_GPIO3_PIN_GPI		0x00
+#define	DA9211_GPIO3_PIN_IERROR		0x10
+#define	DA9211_GPIO3_PIN_GPO_OD		0x20
+#define	DA9211_GPIO3_PIN_GPO		0x30
+#define	DA9211_GPIO3_TYPE_SHIFT		0x40
+#define	DA9211_GPIO3_TYPE_GPI		0x00
+#define	DA9211_GPIO3_TYPE_GPO		0x40
+#define	DA9211_GPIO3_MODE			0x80
+
+/* DA9211_REG_GPIO_4 (addr=0x5A) */
+#define	DA9211_GPIO4_PIN_SHIFT		0
+#define	DA9211_GPIO4_PIN_MASK		0x03
+#define	DA9211_GPIO4_PIN_GPI		0x00
+#define	DA9211_GPIO4_PIN_GPO_OD		0x02
+#define	DA9211_GPIO4_PIN_GPO		0x03
+#define	DA9211_GPIO4_TYPE			0x04
+#define	DA9211_GPIO4_TYPE_GPI		0x00
+#define	DA9211_GPIO4_TYPE_GPO		0x04
+#define	DA9211_GPIO4_MODE			0x08
+
+/* DA9211_REG_BUCKA_CONT (addr=0x5D) */
+#define	DA9211_BUCKA_EN				0x01
+#define	DA9211_BUCKA_GPI_SHIFT		1
+#define DA9211_BUCKA_GPI_MASK		0x06
+#define	DA9211_BUCKA_GPI_OFF		0x00
+#define	DA9211_BUCKA_GPI_GPIO0		0x02
+#define	DA9211_BUCKA_GPI_GPIO1		0x04
+#define	DA9211_BUCKA_GPI_GPIO3		0x06
+#define	DA9211_BUCKA_PD_DIS			0x08
+#define	DA9211_VBUCKA_SEL			0x10
+#define	DA9211_VBUCKA_SEL_A			0x00
+#define	DA9211_VBUCKA_SEL_B			0x10
+#define	DA9211_VBUCKA_GPI_SHIFT		5
+#define	DA9211_VBUCKA_GPI_MASK		0x60
+#define	DA9211_VBUCKA_GPI_OFF		0x00
+#define	DA9211_VBUCKA_GPI_GPIO1		0x20
+#define	DA9211_VBUCKA_GPI_GPIO2		0x40
+#define	DA9211_VBUCKA_GPI_GPIO4		0x60
+
+/* DA9211_REG_BUCKB_CONT (addr=0x5E) */
+#define	DA9211_BUCKB_EN				0x01
+#define	DA9211_BUCKB_GPI_SHIFT		1
+#define DA9211_BUCKB_GPI_MASK		0x06
+#define	DA9211_BUCKB_GPI_OFF		0x00
+#define	DA9211_BUCKB_GPI_GPIO0		0x02
+#define	DA9211_BUCKB_GPI_GPIO1		0x04
+#define	DA9211_BUCKB_GPI_GPIO3		0x06
+#define	DA9211_BUCKB_PD_DIS			0x08
+#define	DA9211_VBUCKB_SEL			0x10
+#define	DA9211_VBUCKB_SEL_A			0x00
+#define	DA9211_VBUCKB_SEL_B			0x10
+#define	DA9211_VBUCKB_GPI_SHIFT		5
+#define	DA9211_VBUCKB_GPI_MASK		0x60
+#define	DA9211_VBUCKB_GPI_OFF		0x00
+#define	DA9211_VBUCKB_GPI_GPIO1		0x20
+#define	DA9211_VBUCKB_GPI_GPIO2		0x40
+#define	DA9211_VBUCKB_GPI_GPIO4		0x60
+
+/* DA9211_REG_BUCK_ILIM (addr=0xD0) */
+#define DA9211_BUCKA_ILIM_SHIFT			0
+#define DA9211_BUCKA_ILIM_MASK			0x0F
+#define DA9211_BUCKB_ILIM_SHIFT			4
+#define DA9211_BUCKB_ILIM_MASK			0xF0
+
+/* DA9211_REG_BUCKA_CONF (addr=0xD1) */
+#define DA9211_BUCKA_MODE_SHIFT			0
+#define DA9211_BUCKA_MODE_MASK			0x03
+#define	DA9211_BUCKA_MODE_MANUAL		0x00
+#define	DA9211_BUCKA_MODE_SLEEP			0x01
+#define	DA9211_BUCKA_MODE_SYNC			0x02
+#define	DA9211_BUCKA_MODE_AUTO			0x03
+#define DA9211_BUCKA_UP_CTRL_SHIFT		2
+#define DA9211_BUCKA_UP_CTRL_MASK		0x1C
+#define DA9211_BUCKA_DOWN_CTRL_SHIFT	5
+#define DA9211_BUCKA_DOWN_CTRL_MASK		0xE0
+
+/* DA9211_REG_BUCKB_CONF (addr=0xD2) */
+#define DA9211_BUCKB_MODE_SHIFT			0
+#define DA9211_BUCKB_MODE_MASK			0x03
+#define	DA9211_BUCKB_MODE_MANUAL		0x00
+#define	DA9211_BUCKB_MODE_SLEEP			0x01
+#define	DA9211_BUCKB_MODE_SYNC			0x02
+#define	DA9211_BUCKB_MODE_AUTO			0x03
+#define DA9211_BUCKB_UP_CTRL_SHIFT		2
+#define DA9211_BUCKB_UP_CTRL_MASK		0x1C
+#define DA9211_BUCKB_DOWN_CTRL_SHIFT	5
+#define DA9211_BUCKB_DOWN_CTRL_MASK		0xE0
+
+/* DA9211_REG_BUCK_CONF (addr=0xD3) */
+#define DA9211_PHASE_SEL_A_SHIFT		0
+#define DA9211_PHASE_SEL_A_MASK			0x03
+#define DA9211_PHASE_SEL_B_SHIFT		2
+#define DA9211_PHASE_SEL_B_MASK			0x04
+#define DA9211_PH_SH_EN_A_SHIFT			3
+#define DA9211_PH_SH_EN_A_MASK			0x08
+#define DA9211_PH_SH_EN_B_SHIFT			4
+#define DA9211_PH_SH_EN_B_MASK			0x10
+
+/* DA9211_REG_VBUCKA_MAX (addr=0xD5) */
+#define DA9211_VBUCKA_BASE_SHIFT		0
+#define DA9211_VBUCKA_BASE_MASK			0x7F
+
+/* DA9211_REG_VBUCKB_MAX (addr=0xD6) */
+#define DA9211_VBUCKB_BASE_SHIFT		0
+#define DA9211_VBUCKB_BASE_MASK			0x7F
+
+/* DA9211_REG_VBUCKA/B_A/B (addr=0xD7/0xD8/0xD9/0xDA) */
+#define DA9211_VBUCK_SHIFT			0
+#define DA9211_VBUCK_MASK			0x7F
+#define DA9211_VBUCK_BIAS			0
+#define DA9211_BUCK_SL				0x80
+
+/* DA9211_REG_INTERFACE (addr=0x105) */
+#define DA9211_IF_BASE_ADDR_SHIFT		4
+#define DA9211_IF_BASE_ADDR_MASK		0xF0
+
+/* DA9211_REG_CONFIG_E (addr=0x147) */
+#define DA9211_SLAVE_SEL			0x40
+
+#endif	/* __DA9211_REGISTERS_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/Kconfig linux-libre-3.17-rc7-gnu/drivers/regulator/Kconfig
--- linux-libre-3.16-gnu/drivers/regulator/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -198,6 +198,16 @@ config REGULATOR_DA9210
 	  converter 12A DC-DC Buck controlled through an I2C
 	  interface.
 
+config REGULATOR_DA9211
+	tristate "Dialog Semiconductor DA9211/DA9212 regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say y here to support for the Dialog Semiconductor DA9211/DA9212.
+	  The DA9211/DA9212 is a multi-phase synchronous step down
+	  converter 12A DC-DC Buck controlled through an I2C
+	  interface.
+
 config REGULATOR_DBX500_PRCMU
 	bool
 
@@ -457,10 +467,10 @@ config REGULATOR_S2MPA01
 	 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
 
 config REGULATOR_S2MPS11
-	tristate "Samsung S2MPS11/S2MPS14 voltage regulator"
+	tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
 	depends on MFD_SEC_CORE
 	help
-	 This driver supports a Samsung S2MPS11/S2MPS14 voltage output
+	 This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
 	 regulator via I2C bus. The chip is comprised of high efficient Buck
 	 converters including Dual-Phase Buck converter, Buck-Boost converter,
 	 various LDOs.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/lp872x.c linux-libre-3.17-rc7-gnu/drivers/regulator/lp872x.c
--- linux-libre-3.16-gnu/drivers/regulator/lp872x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/lp872x.c	2014-09-28 17:29:07.000000000 -0400
@@ -845,7 +845,6 @@ static struct lp872x_platform_data
 	struct device_node *np = dev->of_node;
 	struct lp872x_platform_data *pdata;
 	struct of_regulator_match *match;
-	struct regulator_init_data *d;
 	int num_matches;
 	int count;
 	int i;
@@ -892,14 +891,6 @@ static struct lp872x_platform_data
 		pdata->regulator_data[i].id =
 				(enum lp872x_regulator_id)match[i].driver_data;
 		pdata->regulator_data[i].init_data = match[i].init_data;
-
-		/* Operation mode configuration for buck/buck1/buck2 */
-		if (strncmp(match[i].name, "buck", 4))
-			continue;
-
-		d = pdata->regulator_data[i].init_data;
-		d->constraints.valid_modes_mask |= LP872X_VALID_OPMODE;
-		d->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
 	}
 out:
 	return pdata;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/lp8755.c linux-libre-3.17-rc7-gnu/drivers/regulator/lp8755.c
--- linux-libre-3.16-gnu/drivers/regulator/lp8755.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/lp8755.c	2014-09-28 17:29:07.000000000 -0400
@@ -339,22 +339,18 @@ static int lp8755_regulator_init(struct
 		rconfig.init_data = pdata->buck_data[buck_num];
 		rconfig.of_node = pchip->dev->of_node;
 		pchip->rdev[buck_num] =
-		    regulator_register(&lp8755_regulators[buck_num], &rconfig);
+		    devm_regulator_register(pchip->dev,
+				    &lp8755_regulators[buck_num], &rconfig);
 		if (IS_ERR(pchip->rdev[buck_num])) {
 			ret = PTR_ERR(pchip->rdev[buck_num]);
 			pchip->rdev[buck_num] = NULL;
 			dev_err(pchip->dev, "regulator init failed: buck %d\n",
 				buck_num);
-			goto err_buck;
+			return ret;
 		}
 	}
 
 	return 0;
-
-err_buck:
-	for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
-		regulator_unregister(pchip->rdev[icnt]);
-	return ret;
 }
 
 static irqreturn_t lp8755_irq_handler(int irq, void *data)
@@ -490,23 +486,19 @@ static int lp8755_probe(struct i2c_clien
 	ret = lp8755_regulator_init(pchip);
 	if (ret < 0) {
 		dev_err(&client->dev, "fail to initialize regulators\n");
-		goto err_regulator;
+		goto err;
 	}
 
 	pchip->irq = client->irq;
 	ret = lp8755_int_config(pchip);
 	if (ret < 0) {
 		dev_err(&client->dev, "fail to irq config\n");
-		goto err_irq;
+		goto err;
 	}
 
 	return ret;
 
-err_irq:
-	for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++)
-		regulator_unregister(pchip->rdev[icnt]);
-
-err_regulator:
+err:
 	/* output disable */
 	for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
 		lp8755_write(pchip, icnt, 0x00);
@@ -519,9 +511,6 @@ static int lp8755_remove(struct i2c_clie
 	int icnt;
 	struct lp8755_chip *pchip = i2c_get_clientdata(client);
 
-	for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++)
-		regulator_unregister(pchip->rdev[icnt]);
-
 	for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
 		lp8755_write(pchip, icnt, 0x00);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/ltc3589.c linux-libre-3.17-rc7-gnu/drivers/regulator/ltc3589.c
--- linux-libre-3.16-gnu/drivers/regulator/ltc3589.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/ltc3589.c	2014-09-28 17:29:07.000000000 -0400
@@ -377,7 +377,7 @@ static bool ltc3589_volatile_reg(struct
 	return false;
 }
 
-struct reg_default ltc3589_reg_defaults[] = {
+static struct reg_default ltc3589_reg_defaults[] = {
 	{ LTC3589_SCR1,   0x00 },
 	{ LTC3589_OVEN,   0x00 },
 	{ LTC3589_SCR2,   0x00 },
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/Makefile linux-libre-3.17-rc7-gnu/drivers/regulator/Makefile
--- linux-libre-3.16-gnu/drivers/regulator/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_DA9052)	+= da9052
 obj-$(CONFIG_REGULATOR_DA9055)	+= da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DA9063)	+= da9063-regulator.o
 obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
+obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/max77693.c linux-libre-3.17-rc7-gnu/drivers/regulator/max77693.c
--- linux-libre-3.16-gnu/drivers/regulator/max77693.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/max77693.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/mfd/max77693.h>
 #include <linux/mfd/max77693-private.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/regmap.h>
 
 #define CHGIN_ILIM_STEP_20mA			20000
 
@@ -39,9 +40,9 @@
 static int max77693_chg_is_enabled(struct regulator_dev *rdev)
 {
 	int ret;
-	u8 val;
+	unsigned int val;
 
-	ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val);
+	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
 	if (ret)
 		return ret;
 
@@ -57,12 +58,11 @@ static int max77693_chg_get_current_limi
 {
 	unsigned int chg_min_uA = rdev->constraints->min_uA;
 	unsigned int chg_max_uA = rdev->constraints->max_uA;
-	u8 reg, sel;
+	unsigned int reg, sel;
 	unsigned int val;
 	int ret;
 
-	ret = max77693_read_reg(rdev->regmap,
-				MAX77693_CHG_REG_CHG_CNFG_09, &reg);
+	ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, &reg);
 	if (ret < 0)
 		return ret;
 
@@ -96,7 +96,7 @@ static int max77693_chg_set_current_limi
 	/* the first four codes for charger current are all 60mA */
 	sel += 3;
 
-	return max77693_write_reg(rdev->regmap,
+	return regmap_write(rdev->regmap,
 				MAX77693_CHG_REG_CHG_CNFG_09, sel);
 }
 /* end of CHARGER regulator ops */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/max8907-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/max8907-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/max8907-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/max8907-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -226,7 +226,7 @@ static int max8907_regulator_parse_dt(st
 	struct device_node *np, *regulators;
 	int ret;
 
-	np = of_node_get(pdev->dev.parent->of_node);
+	np = pdev->dev.parent->of_node;
 	if (!np)
 		return 0;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/max8925-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/max8925-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/max8925-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/max8925-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -250,7 +250,7 @@ static int max8925_regulator_dt_init(str
 	struct device_node *nproot, *np;
 	int rcount;
 
-	nproot = of_node_get(pdev->dev.parent->of_node);
+	nproot = pdev->dev.parent->of_node;
 	if (!nproot)
 		return -ENODEV;
 	np = of_get_child_by_name(nproot, "regulators");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/max8952.c linux-libre-3.17-rc7-gnu/drivers/regulator/max8952.c
--- linux-libre-3.16-gnu/drivers/regulator/max8952.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/max8952.c	2014-09-28 17:29:07.000000000 -0400
@@ -229,7 +229,6 @@ static int max8952_pmic_probe(struct i2c
 		config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
 
 	rdev = devm_regulator_register(&client->dev, &regulator, &config);
-
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(&client->dev, "regulator init failed (%d)\n", ret);
@@ -241,21 +240,19 @@ static int max8952_pmic_probe(struct i2c
 
 	if (gpio_is_valid(pdata->gpio_vid0) &&
 			gpio_is_valid(pdata->gpio_vid1)) {
-		if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
-			gpio_direction_output(pdata->gpio_vid0,
-					(pdata->default_mode) & 0x1);
-		else
+		unsigned long gpio_flags;
+
+		gpio_flags = max8952->vid0 ?
+			     GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+		if (devm_gpio_request_one(&client->dev, pdata->gpio_vid0,
+					  gpio_flags, "MAX8952 VID0"))
 			err = 1;
 
-		if (!gpio_request(pdata->gpio_vid1, "MAX8952 VID1"))
-			gpio_direction_output(pdata->gpio_vid1,
-				(pdata->default_mode >> 1) & 0x1);
-		else {
-			if (!err)
-				gpio_free(pdata->gpio_vid0);
+		gpio_flags = max8952->vid1 ?
+			     GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+		if (devm_gpio_request_one(&client->dev, pdata->gpio_vid1,
+					  gpio_flags, "MAX8952 VID1"))
 			err = 2;
-		}
-
 	} else
 		err = 3;
 
@@ -314,16 +311,6 @@ static int max8952_pmic_probe(struct i2c
 	return 0;
 }
 
-static int max8952_pmic_remove(struct i2c_client *client)
-{
-	struct max8952_data *max8952 = i2c_get_clientdata(client);
-	struct max8952_platform_data *pdata = max8952->pdata;
-
-	gpio_free(pdata->gpio_vid0);
-	gpio_free(pdata->gpio_vid1);
-	return 0;
-}
-
 static const struct i2c_device_id max8952_ids[] = {
 	{ "max8952", 0 },
 	{ },
@@ -332,7 +319,6 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
 
 static struct i2c_driver max8952_pmic_driver = {
 	.probe		= max8952_pmic_probe,
-	.remove		= max8952_pmic_remove,
 	.driver		= {
 		.name	= "max8952",
 		.of_match_table = of_match_ptr(max8952_dt_match),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/max8997.c linux-libre-3.17-rc7-gnu/drivers/regulator/max8997.c
--- linux-libre-3.16-gnu/drivers/regulator/max8997.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/max8997.c	2014-09-28 17:29:07.000000000 -0400
@@ -917,7 +917,7 @@ static int max8997_pmic_dt_parse_pdata(s
 	struct max8997_regulator_data *rdata;
 	unsigned int i, dvs_voltage_nr = 1, ret;
 
-	pmic_np = of_node_get(iodev->dev->of_node);
+	pmic_np = iodev->dev->of_node;
 	if (!pmic_np) {
 		dev_err(&pdev->dev, "could not find pmic sub-node\n");
 		return -ENODEV;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/mc13xxx.h linux-libre-3.17-rc7-gnu/drivers/regulator/mc13xxx.h
--- linux-libre-3.16-gnu/drivers/regulator/mc13xxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/mc13xxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,6 @@ struct mc13xxx_regulator {
 	int vsel_reg;
 	int vsel_shift;
 	int vsel_mask;
-	int hi_bit;
 };
 
 struct mc13xxx_regulator_priv {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/mc13xxx-regulator-core.c linux-libre-3.17-rc7-gnu/drivers/regulator/mc13xxx-regulator-core.c
--- linux-libre-3.16-gnu/drivers/regulator/mc13xxx-regulator-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/mc13xxx-regulator-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,17 +33,12 @@ static int mc13xxx_regulator_enable(stru
 	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 	int id = rdev_get_id(rdev);
-	int ret;
 
 	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
-	mc13xxx_lock(priv->mc13xxx);
-	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
-			mc13xxx_regulators[id].enable_bit,
-			mc13xxx_regulators[id].enable_bit);
-	mc13xxx_unlock(priv->mc13xxx);
-
-	return ret;
+	return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
+			       mc13xxx_regulators[id].enable_bit,
+			       mc13xxx_regulators[id].enable_bit);
 }
 
 static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
@@ -51,16 +46,11 @@ static int mc13xxx_regulator_disable(str
 	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 	int id = rdev_get_id(rdev);
-	int ret;
 
 	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
-	mc13xxx_lock(priv->mc13xxx);
-	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
-			mc13xxx_regulators[id].enable_bit, 0);
-	mc13xxx_unlock(priv->mc13xxx);
-
-	return ret;
+	return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
+			       mc13xxx_regulators[id].enable_bit, 0);
 }
 
 static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
@@ -70,10 +60,7 @@ static int mc13xxx_regulator_is_enabled(
 	int ret, id = rdev_get_id(rdev);
 	unsigned int val;
 
-	mc13xxx_lock(priv->mc13xxx);
 	ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
-	mc13xxx_unlock(priv->mc13xxx);
-
 	if (ret)
 		return ret;
 
@@ -86,15 +73,10 @@ static int mc13xxx_regulator_set_voltage
 	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 	int id = rdev_get_id(rdev);
-	int ret;
-
-	mc13xxx_lock(priv->mc13xxx);
-	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
-			mc13xxx_regulators[id].vsel_mask,
-			selector << mc13xxx_regulators[id].vsel_shift);
-	mc13xxx_unlock(priv->mc13xxx);
 
-	return ret;
+	return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
+			       mc13xxx_regulators[id].vsel_mask,
+			       selector << mc13xxx_regulators[id].vsel_shift);
 }
 
 static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
@@ -106,11 +88,8 @@ static int mc13xxx_regulator_get_voltage
 
 	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
-	mc13xxx_lock(priv->mc13xxx);
 	ret = mc13xxx_reg_read(priv->mc13xxx,
 				mc13xxx_regulators[id].vsel_reg, &val);
-	mc13xxx_unlock(priv->mc13xxx);
-
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/palmas-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/palmas-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/palmas-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/palmas-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,15 +27,6 @@
 #include <linux/of_platform.h>
 #include <linux/regulator/of_regulator.h>
 
-struct regs_info {
-	char	*name;
-	char	*sname;
-	u8	vsel_addr;
-	u8	ctrl_addr;
-	u8	tstep_addr;
-	int	sleep_id;
-};
-
 static const struct regulator_linear_range smps_low_ranges[] = {
 	REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
 	REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0),
@@ -50,7 +41,7 @@ static const struct regulator_linear_ran
 	REGULATOR_LINEAR_RANGE(3300000, 0x7A, 0x7f, 0),
 };
 
-static const struct regs_info palmas_regs_info[] = {
+static struct palmas_regs_info palmas_generic_regs_info[] = {
 	{
 		.name		= "SMPS12",
 		.sname		= "smps1-in",
@@ -236,6 +227,153 @@ static const struct regs_info palmas_reg
 	},
 };
 
+static struct palmas_regs_info tps65917_regs_info[] = {
+	{
+		.name		= "SMPS1",
+		.sname		= "smps1-in",
+		.vsel_addr	= TPS65917_SMPS1_VOLTAGE,
+		.ctrl_addr	= TPS65917_SMPS1_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_SMPS1,
+	},
+	{
+		.name		= "SMPS2",
+		.sname		= "smps2-in",
+		.vsel_addr	= TPS65917_SMPS2_VOLTAGE,
+		.ctrl_addr	= TPS65917_SMPS2_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_SMPS2,
+	},
+	{
+		.name		= "SMPS3",
+		.sname		= "smps3-in",
+		.vsel_addr	= TPS65917_SMPS3_VOLTAGE,
+		.ctrl_addr	= TPS65917_SMPS3_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_SMPS3,
+	},
+	{
+		.name		= "SMPS4",
+		.sname		= "smps4-in",
+		.vsel_addr	= TPS65917_SMPS4_VOLTAGE,
+		.ctrl_addr	= TPS65917_SMPS4_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_SMPS4,
+	},
+	{
+		.name		= "SMPS5",
+		.sname		= "smps5-in",
+		.vsel_addr	= TPS65917_SMPS5_VOLTAGE,
+		.ctrl_addr	= TPS65917_SMPS5_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_SMPS5,
+	},
+	{
+		.name		= "LDO1",
+		.sname		= "ldo1-in",
+		.vsel_addr	= TPS65917_LDO1_VOLTAGE,
+		.ctrl_addr	= TPS65917_LDO1_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_LDO1,
+	},
+	{
+		.name		= "LDO2",
+		.sname		= "ldo2-in",
+		.vsel_addr	= TPS65917_LDO2_VOLTAGE,
+		.ctrl_addr	= TPS65917_LDO2_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_LDO2,
+	},
+	{
+		.name		= "LDO3",
+		.sname		= "ldo3-in",
+		.vsel_addr	= TPS65917_LDO3_VOLTAGE,
+		.ctrl_addr	= TPS65917_LDO3_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_LDO3,
+	},
+	{
+		.name		= "LDO4",
+		.sname		= "ldo4-in",
+		.vsel_addr	= TPS65917_LDO4_VOLTAGE,
+		.ctrl_addr	= TPS65917_LDO4_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_LDO4,
+	},
+	{
+		.name		= "LDO5",
+		.sname		= "ldo5-in",
+		.vsel_addr	= TPS65917_LDO5_VOLTAGE,
+		.ctrl_addr	= TPS65917_LDO5_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_LDO5,
+	},
+	{
+		.name		= "REGEN1",
+		.ctrl_addr	= TPS65917_REGEN1_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_REGEN1,
+	},
+	{
+		.name		= "REGEN2",
+		.ctrl_addr	= TPS65917_REGEN2_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_REGEN2,
+	},
+	{
+		.name		= "REGEN3",
+		.ctrl_addr	= TPS65917_REGEN3_CTRL,
+		.sleep_id	= TPS65917_EXTERNAL_REQSTR_ID_REGEN3,
+	},
+};
+
+#define EXTERNAL_REQUESTOR(_id, _offset, _pos)		\
+	[PALMAS_EXTERNAL_REQSTR_ID_##_id] = {		\
+		.id = PALMAS_EXTERNAL_REQSTR_ID_##_id,	\
+		.reg_offset = _offset,			\
+		.bit_pos = _pos,			\
+	}
+
+static struct palmas_sleep_requestor_info palma_sleep_req_info[] = {
+	EXTERNAL_REQUESTOR(REGEN1, 0, 0),
+	EXTERNAL_REQUESTOR(REGEN2, 0, 1),
+	EXTERNAL_REQUESTOR(SYSEN1, 0, 2),
+	EXTERNAL_REQUESTOR(SYSEN2, 0, 3),
+	EXTERNAL_REQUESTOR(CLK32KG, 0, 4),
+	EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5),
+	EXTERNAL_REQUESTOR(REGEN3, 0, 6),
+	EXTERNAL_REQUESTOR(SMPS12, 1, 0),
+	EXTERNAL_REQUESTOR(SMPS3, 1, 1),
+	EXTERNAL_REQUESTOR(SMPS45, 1, 2),
+	EXTERNAL_REQUESTOR(SMPS6, 1, 3),
+	EXTERNAL_REQUESTOR(SMPS7, 1, 4),
+	EXTERNAL_REQUESTOR(SMPS8, 1, 5),
+	EXTERNAL_REQUESTOR(SMPS9, 1, 6),
+	EXTERNAL_REQUESTOR(SMPS10, 1, 7),
+	EXTERNAL_REQUESTOR(LDO1, 2, 0),
+	EXTERNAL_REQUESTOR(LDO2, 2, 1),
+	EXTERNAL_REQUESTOR(LDO3, 2, 2),
+	EXTERNAL_REQUESTOR(LDO4, 2, 3),
+	EXTERNAL_REQUESTOR(LDO5, 2, 4),
+	EXTERNAL_REQUESTOR(LDO6, 2, 5),
+	EXTERNAL_REQUESTOR(LDO7, 2, 6),
+	EXTERNAL_REQUESTOR(LDO8, 2, 7),
+	EXTERNAL_REQUESTOR(LDO9, 3, 0),
+	EXTERNAL_REQUESTOR(LDOLN, 3, 1),
+	EXTERNAL_REQUESTOR(LDOUSB, 3, 2),
+};
+
+#define EXTERNAL_REQUESTOR_TPS65917(_id, _offset, _pos)		\
+	[TPS65917_EXTERNAL_REQSTR_ID_##_id] = {		\
+		.id = TPS65917_EXTERNAL_REQSTR_ID_##_id,	\
+		.reg_offset = _offset,			\
+		.bit_pos = _pos,			\
+	}
+
+static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = {
+	EXTERNAL_REQUESTOR_TPS65917(REGEN1, 0, 0),
+	EXTERNAL_REQUESTOR_TPS65917(REGEN2, 0, 1),
+	EXTERNAL_REQUESTOR_TPS65917(REGEN3, 0, 6),
+	EXTERNAL_REQUESTOR_TPS65917(SMPS1, 1, 0),
+	EXTERNAL_REQUESTOR_TPS65917(SMPS2, 1, 1),
+	EXTERNAL_REQUESTOR_TPS65917(SMPS3, 1, 2),
+	EXTERNAL_REQUESTOR_TPS65917(SMPS4, 1, 3),
+	EXTERNAL_REQUESTOR_TPS65917(SMPS5, 1, 4),
+	EXTERNAL_REQUESTOR_TPS65917(LDO1, 2, 0),
+	EXTERNAL_REQUESTOR_TPS65917(LDO2, 2, 1),
+	EXTERNAL_REQUESTOR_TPS65917(LDO3, 2, 2),
+	EXTERNAL_REQUESTOR_TPS65917(LDO4, 2, 3),
+	EXTERNAL_REQUESTOR_TPS65917(LDO5, 2, 4),
+};
+
 static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
 
 #define SMPS_CTRL_MODE_OFF		0x00
@@ -296,12 +434,15 @@ static int palmas_ldo_write(struct palma
 
 static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
 {
-	struct palmas_pmic *pmic = rdev_get_drvdata(dev);
 	int id = rdev_get_id(dev);
+	struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+	struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 	unsigned int reg;
 	bool rail_enable = true;
 
-	palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+	palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, &reg);
+
 	reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
 	if (reg == SMPS_CTRL_MODE_OFF)
@@ -323,8 +464,7 @@ static int palmas_set_mode_smps(struct r
 
 	pmic->current_reg_mode[id] = reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 	if (rail_enable)
-		palmas_smps_write(pmic->palmas,
-			palmas_regs_info[id].ctrl_addr, reg);
+		palmas_smps_write(pmic->palmas, rinfo->ctrl_addr, reg);
 
 	/* Switch the enable value to ensure this is used for enable */
 	pmic->desc[id].enable_val = pmic->current_reg_mode[id];
@@ -355,10 +495,11 @@ static unsigned int palmas_get_mode_smps
 static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
 		 int ramp_delay)
 {
-	struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
 	int id = rdev_get_id(rdev);
+	struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
+	struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 	unsigned int reg = 0;
-	unsigned int addr = palmas_regs_info[id].tstep_addr;
 	int ret;
 
 	/* SMPS3 and SMPS7 do not have tstep_addr setting */
@@ -377,7 +518,7 @@ static int palmas_smps_set_ramp_delay(st
 	else
 		reg = 1;
 
-	ret = palmas_smps_write(pmic->palmas, addr, reg);
+	ret = palmas_smps_write(pmic->palmas, rinfo->tstep_addr, reg);
 	if (ret < 0) {
 		dev_err(pmic->palmas->dev, "TSTEP write failed: %d\n", ret);
 		return ret;
@@ -424,13 +565,37 @@ static struct regulator_ops palmas_ops_s
 	.get_bypass		= regulator_get_bypass_regmap,
 };
 
+static struct regulator_ops tps65917_ops_smps = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.set_mode		= palmas_set_mode_smps,
+	.get_mode		= palmas_get_mode_smps,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops tps65917_ops_ext_control_smps = {
+	.set_mode		= palmas_set_mode_smps,
+	.get_mode		= palmas_get_mode_smps,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+};
+
 static int palmas_is_enabled_ldo(struct regulator_dev *dev)
 {
-	struct palmas_pmic *pmic = rdev_get_drvdata(dev);
 	int id = rdev_get_id(dev);
+	struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+	struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 	unsigned int reg;
 
-	palmas_ldo_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+	palmas_ldo_read(pmic->palmas, rinfo->ctrl_addr, &reg);
 
 	reg &= PALMAS_LDO1_CTRL_STATUS;
 
@@ -463,14 +628,26 @@ static struct regulator_ops palmas_ops_e
 static struct regulator_ops palmas_ops_ext_control_extreg = {
 };
 
+static struct regulator_ops tps65917_ops_ldo = {
+	.is_enabled		= palmas_is_enabled_ldo,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+};
+
 static int palmas_regulator_config_external(struct palmas *palmas, int id,
 		struct palmas_reg_init *reg_init)
 {
-	int sleep_id = palmas_regs_info[id].sleep_id;
+	struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 	int ret;
 
-	ret = palmas_ext_control_req_config(palmas, sleep_id,
-					reg_init->roof_floor, true);
+	ret = palmas_ext_control_req_config(palmas, rinfo->sleep_id,
+					    reg_init->roof_floor, true);
 	if (ret < 0)
 		dev_err(palmas->dev,
 			"Ext control config for regulator %d failed %d\n",
@@ -488,10 +665,10 @@ static int palmas_smps_init(struct palma
 		struct palmas_reg_init *reg_init)
 {
 	unsigned int reg;
-	unsigned int addr;
 	int ret;
-
-	addr = palmas_regs_info[id].ctrl_addr;
+	struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
+	unsigned int addr = rinfo->ctrl_addr;
 
 	ret = palmas_smps_read(palmas, addr, &reg);
 	if (ret)
@@ -526,12 +703,11 @@ static int palmas_smps_init(struct palma
 	if (ret)
 		return ret;
 
-	if (palmas_regs_info[id].vsel_addr && reg_init->vsel) {
-		addr = palmas_regs_info[id].vsel_addr;
+	if (rinfo->vsel_addr && reg_init->vsel) {
 
 		reg = reg_init->vsel;
 
-		ret = palmas_smps_write(palmas, addr, reg);
+		ret = palmas_smps_write(palmas, rinfo->vsel_addr, reg);
 		if (ret)
 			return ret;
 	}
@@ -539,7 +715,6 @@ static int palmas_smps_init(struct palma
 	if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
 			(id != PALMAS_REG_SMPS10_OUT2)) {
 		/* Enable externally controlled regulator */
-		addr = palmas_regs_info[id].ctrl_addr;
 		ret = palmas_smps_read(palmas, addr, &reg);
 		if (ret < 0)
 			return ret;
@@ -561,8 +736,10 @@ static int palmas_ldo_init(struct palmas
 	unsigned int reg;
 	unsigned int addr;
 	int ret;
+	struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 
-	addr = palmas_regs_info[id].ctrl_addr;
+	addr = rinfo->ctrl_addr;
 
 	ret = palmas_ldo_read(palmas, addr, &reg);
 	if (ret)
@@ -584,7 +761,6 @@ static int palmas_ldo_init(struct palmas
 
 	if (reg_init->roof_floor) {
 		/* Enable externally controlled regulator */
-		addr = palmas_regs_info[id].ctrl_addr;
 		ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
 				addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
 				PALMAS_LDO1_CTRL_MODE_ACTIVE);
@@ -605,8 +781,10 @@ static int palmas_extreg_init(struct pal
 	unsigned int addr;
 	int ret;
 	unsigned int val = 0;
+	struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
 
-	addr = palmas_regs_info[id].ctrl_addr;
+	addr = rinfo->ctrl_addr;
 
 	if (reg_init->mode_sleep)
 		val = PALMAS_REGEN1_CTRL_MODE_SLEEP;
@@ -621,7 +799,6 @@ static int palmas_extreg_init(struct pal
 
 	if (reg_init->roof_floor) {
 		/* Enable externally controlled regulator */
-		addr = palmas_regs_info[id].ctrl_addr;
 		ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
 				addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
 				PALMAS_REGEN1_CTRL_MODE_ACTIVE);
@@ -641,8 +818,11 @@ static void palmas_enable_ldo8_track(str
 	unsigned int reg;
 	unsigned int addr;
 	int ret;
+	struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+	struct palmas_regs_info *rinfo;
 
-	addr = palmas_regs_info[PALMAS_REG_LDO8].ctrl_addr;
+	rinfo = &ddata->palmas_regs_info[PALMAS_REG_LDO8];
+	addr = rinfo->ctrl_addr;
 
 	ret = palmas_ldo_read(palmas, addr, &reg);
 	if (ret) {
@@ -661,7 +841,7 @@ static void palmas_enable_ldo8_track(str
 	 * output is defined by the LDO8_VOLTAGE.VSEL register divided by two,
 	 * and can be set from 0.45 to 1.65 V.
 	 */
-	addr = palmas_regs_info[PALMAS_REG_LDO8].vsel_addr;
+	addr = rinfo->vsel_addr;
 	ret = palmas_ldo_read(palmas, addr, &reg);
 	if (ret) {
 		dev_err(palmas->dev, "Error in reading ldo8 voltage reg\n");
@@ -676,169 +856,230 @@ static void palmas_enable_ldo8_track(str
 	return;
 }
 
-static struct of_regulator_match palmas_matches[] = {
-	{ .name = "smps12", },
-	{ .name = "smps123", },
-	{ .name = "smps3", },
-	{ .name = "smps45", },
-	{ .name = "smps457", },
-	{ .name = "smps6", },
-	{ .name = "smps7", },
-	{ .name = "smps8", },
-	{ .name = "smps9", },
-	{ .name = "smps10_out2", },
-	{ .name = "smps10_out1", },
-	{ .name = "ldo1", },
-	{ .name = "ldo2", },
-	{ .name = "ldo3", },
-	{ .name = "ldo4", },
-	{ .name = "ldo5", },
-	{ .name = "ldo6", },
-	{ .name = "ldo7", },
-	{ .name = "ldo8", },
-	{ .name = "ldo9", },
-	{ .name = "ldoln", },
-	{ .name = "ldousb", },
-	{ .name = "regen1", },
-	{ .name = "regen2", },
-	{ .name = "regen3", },
-	{ .name = "sysen1", },
-	{ .name = "sysen2", },
-};
-
-static void palmas_dt_to_pdata(struct device *dev,
-		struct device_node *node,
-		struct palmas_pmic_platform_data *pdata)
+static int palmas_ldo_registration(struct palmas_pmic *pmic,
+				   struct palmas_pmic_driver_data *ddata,
+				   struct palmas_pmic_platform_data *pdata,
+				   const char *pdev_name,
+				   struct regulator_config config)
 {
-	struct device_node *regulators;
-	u32 prop;
-	int idx, ret;
+	int id, ret;
+	struct regulator_dev *rdev;
+	struct palmas_reg_init *reg_init;
+	struct palmas_regs_info *rinfo;
+	struct regulator_desc *desc;
 
-	node = of_node_get(node);
-	regulators = of_get_child_by_name(node, "regulators");
-	if (!regulators) {
-		dev_info(dev, "regulator node not found\n");
-		return;
-	}
+	for (id = ddata->ldo_begin; id < ddata->max_reg; id++) {
+		if (pdata && pdata->reg_init[id])
+			reg_init = pdata->reg_init[id];
+		else
+			reg_init = NULL;
 
-	ret = of_regulator_match(dev, regulators, palmas_matches,
-			PALMAS_NUM_REGS);
-	of_node_put(regulators);
-	if (ret < 0) {
-		dev_err(dev, "Error parsing regulator init data: %d\n", ret);
-		return;
-	}
+		rinfo = &ddata->palmas_regs_info[id];
+		/* Miss out regulators which are not available due
+		 * to alternate functions.
+		 */
 
-	for (idx = 0; idx < PALMAS_NUM_REGS; idx++) {
-		if (!palmas_matches[idx].init_data ||
-				!palmas_matches[idx].of_node)
-			continue;
+		/* Register the regulators */
+		desc = &pmic->desc[id];
+		desc->name = rinfo->name;
+		desc->id = id;
+		desc->type = REGULATOR_VOLTAGE;
+		desc->owner = THIS_MODULE;
 
-		pdata->reg_data[idx] = palmas_matches[idx].init_data;
+		if (id < PALMAS_REG_REGEN1) {
+			desc->n_voltages = PALMAS_LDO_NUM_VOLTAGES;
+			if (reg_init && reg_init->roof_floor)
+				desc->ops = &palmas_ops_ext_control_ldo;
+			else
+				desc->ops = &palmas_ops_ldo;
+			desc->min_uV = 900000;
+			desc->uV_step = 50000;
+			desc->linear_min_sel = 1;
+			desc->enable_time = 500;
+			desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+							    rinfo->vsel_addr);
+			desc->vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
+			desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+							      rinfo->ctrl_addr);
+			desc->enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
 
-		pdata->reg_init[idx] = devm_kzalloc(dev,
-				sizeof(struct palmas_reg_init), GFP_KERNEL);
+			/* Check if LDO8 is in tracking mode or not */
+			if (pdata && (id == PALMAS_REG_LDO8) &&
+			    pdata->enable_ldo8_tracking) {
+				palmas_enable_ldo8_track(pmic->palmas);
+				desc->min_uV = 450000;
+				desc->uV_step = 25000;
+			}
 
-		pdata->reg_init[idx]->warm_reset =
-			of_property_read_bool(palmas_matches[idx].of_node,
-					     "ti,warm-reset");
+			/* LOD6 in vibrator mode will have enable time 2000us */
+			if (pdata && pdata->ldo6_vibrator &&
+			    (id == PALMAS_REG_LDO6))
+				desc->enable_time = 2000;
+		} else {
+			desc->n_voltages = 1;
+			if (reg_init && reg_init->roof_floor)
+				desc->ops = &palmas_ops_ext_control_extreg;
+			else
+				desc->ops = &palmas_ops_extreg;
+			desc->enable_reg =
+					PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
+							   rinfo->ctrl_addr);
+			desc->enable_mask = PALMAS_REGEN1_CTRL_MODE_ACTIVE;
+		}
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-					      "ti,roof-floor", &prop);
-		/* EINVAL: Property not found */
-		if (ret != -EINVAL) {
-			int econtrol;
+		if (pdata)
+			config.init_data = pdata->reg_data[id];
+		else
+			config.init_data = NULL;
 
-			/* use default value, when no value is specified */
-			econtrol = PALMAS_EXT_CONTROL_NSLEEP;
-			if (!ret) {
-				switch (prop) {
-				case 1:
-					econtrol = PALMAS_EXT_CONTROL_ENABLE1;
-					break;
-				case 2:
-					econtrol = PALMAS_EXT_CONTROL_ENABLE2;
-					break;
-				case 3:
-					econtrol = PALMAS_EXT_CONTROL_NSLEEP;
-					break;
-				default:
-					WARN_ON(1);
-					dev_warn(dev,
-					"%s: Invalid roof-floor option: %u\n",
-					     palmas_matches[idx].name, prop);
-					break;
-				}
-			}
-			pdata->reg_init[idx]->roof_floor = econtrol;
-		}
+		desc->supply_name = rinfo->sname;
+		config.of_node = ddata->palmas_matches[id].of_node;
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,mode-sleep", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->mode_sleep = prop;
+		rdev = devm_regulator_register(pmic->dev, desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(pmic->dev,
+				"failed to register %s regulator\n",
+				pdev_name);
+			return PTR_ERR(rdev);
+		}
 
-		ret = of_property_read_bool(palmas_matches[idx].of_node,
-					    "ti,smps-range");
-		if (ret)
-			pdata->reg_init[idx]->vsel =
-				PALMAS_SMPS12_VOLTAGE_RANGE;
+		/* Save regulator for cleanup */
+		pmic->rdev[id] = rdev;
 
-		if (idx == PALMAS_REG_LDO8)
-			pdata->enable_ldo8_tracking = of_property_read_bool(
-						palmas_matches[idx].of_node,
-						"ti,enable-ldo8-tracking");
+		/* Initialise sleep/init values from platform data */
+		if (pdata) {
+			reg_init = pdata->reg_init[id];
+			if (reg_init) {
+				if (id <= ddata->ldo_end)
+					ret = palmas_ldo_init(pmic->palmas, id,
+							      reg_init);
+				else
+					ret = palmas_extreg_init(pmic->palmas,
+								 id, reg_init);
+				if (ret)
+					return ret;
+			}
+		}
 	}
 
-	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
+	return 0;
 }
 
-
-static int palmas_regulators_probe(struct platform_device *pdev)
+static int tps65917_ldo_registration(struct palmas_pmic *pmic,
+				     struct palmas_pmic_driver_data *ddata,
+				     struct palmas_pmic_platform_data *pdata,
+				     const char *pdev_name,
+				     struct regulator_config config)
 {
-	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
-	struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct device_node *node = pdev->dev.of_node;
+	int id, ret;
 	struct regulator_dev *rdev;
-	struct regulator_config config = { };
-	struct palmas_pmic *pmic;
 	struct palmas_reg_init *reg_init;
-	int id = 0, ret;
-	unsigned int addr, reg;
+	struct palmas_regs_info *rinfo;
+	struct regulator_desc *desc;
 
-	if (node && !pdata) {
-		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	for (id = ddata->ldo_begin; id < ddata->max_reg; id++) {
+		if (pdata && pdata->reg_init[id])
+			reg_init = pdata->reg_init[id];
+		else
+			reg_init = NULL;
 
-		if (!pdata)
-			return -ENOMEM;
+		/* Miss out regulators which are not available due
+		 * to alternate functions.
+		 */
+		rinfo = &ddata->palmas_regs_info[id];
 
-		palmas_dt_to_pdata(&pdev->dev, node, pdata);
-	}
+		/* Register the regulators */
+		desc = &pmic->desc[id];
+		desc->name = rinfo->name;
+		desc->id = id;
+		desc->type = REGULATOR_VOLTAGE;
+		desc->owner = THIS_MODULE;
 
-	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
-	if (!pmic)
-		return -ENOMEM;
+		if (id < TPS65917_REG_REGEN1) {
+			desc->n_voltages = PALMAS_LDO_NUM_VOLTAGES;
+			if (reg_init && reg_init->roof_floor)
+				desc->ops = &palmas_ops_ext_control_ldo;
+			else
+				desc->ops = &tps65917_ops_ldo;
+			desc->min_uV = 900000;
+			desc->uV_step = 50000;
+			desc->linear_min_sel = 1;
+			desc->enable_time = 500;
+			desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+							    rinfo->vsel_addr);
+			desc->vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
+			desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+							      rinfo->ctrl_addr);
+			desc->enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
+			/*
+			 * To be confirmed. Discussion on going with PMIC Team.
+			 * It is of the order of ~60mV/uS.
+			 */
+			desc->ramp_delay = 2500;
+		} else {
+			desc->n_voltages = 1;
+			if (reg_init && reg_init->roof_floor)
+				desc->ops = &palmas_ops_ext_control_extreg;
+			else
+				desc->ops = &palmas_ops_extreg;
+			desc->enable_reg =
+					PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
+							   rinfo->ctrl_addr);
+			desc->enable_mask = PALMAS_REGEN1_CTRL_MODE_ACTIVE;
+		}
 
-	pmic->dev = &pdev->dev;
-	pmic->palmas = palmas;
-	palmas->pmic = pmic;
-	platform_set_drvdata(pdev, pmic);
+		if (pdata)
+			config.init_data = pdata->reg_data[id];
+		else
+			config.init_data = NULL;
 
-	ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
-	if (ret)
-		return ret;
+		desc->supply_name = rinfo->sname;
+		config.of_node = ddata->palmas_matches[id].of_node;
 
-	if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)
-		pmic->smps123 = 1;
+		rdev = devm_regulator_register(pmic->dev, desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(pmic->dev,
+				"failed to register %s regulator\n",
+				pdev_name);
+			return PTR_ERR(rdev);
+		}
 
-	if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
-		pmic->smps457 = 1;
+		/* Save regulator for cleanup */
+		pmic->rdev[id] = rdev;
 
-	config.regmap = palmas->regmap[REGULATOR_SLAVE];
-	config.dev = &pdev->dev;
-	config.driver_data = pmic;
+		/* Initialise sleep/init values from platform data */
+		if (pdata) {
+			reg_init = pdata->reg_init[id];
+			if (reg_init) {
+				if (id < TPS65917_REG_REGEN1)
+					ret = palmas_ldo_init(pmic->palmas,
+							      id, reg_init);
+				else
+					ret = palmas_extreg_init(pmic->palmas,
+								 id, reg_init);
+				if (ret)
+					return ret;
+			}
+		}
+	}
 
-	for (id = 0; id < PALMAS_REG_LDO1; id++) {
+	return 0;
+}
+
+static int palmas_smps_registration(struct palmas_pmic *pmic,
+				    struct palmas_pmic_driver_data *ddata,
+				    struct palmas_pmic_platform_data *pdata,
+				    const char *pdev_name,
+				    struct regulator_config config)
+{
+	int id, ret;
+	unsigned int addr, reg;
+	struct regulator_dev *rdev;
+	struct palmas_reg_init *reg_init;
+	struct palmas_regs_info *rinfo;
+	struct regulator_desc *desc;
+
+	for (id = ddata->smps_start; id <= ddata->smps_end; id++) {
 		bool ramp_delay_support = false;
 
 		/*
@@ -872,30 +1113,31 @@ static int palmas_regulators_probe(struc
 			break;
 		case PALMAS_REG_SMPS10_OUT1:
 		case PALMAS_REG_SMPS10_OUT2:
-			if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST))
+			if (!PALMAS_PMIC_HAS(pmic->palmas, SMPS10_BOOST))
 				continue;
 		}
+		rinfo = &ddata->palmas_regs_info[id];
+		desc = &pmic->desc[id];
 
 		if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8))
 			ramp_delay_support = true;
 
 		if (ramp_delay_support) {
-			addr = palmas_regs_info[id].tstep_addr;
+			addr = rinfo->tstep_addr;
 			ret = palmas_smps_read(pmic->palmas, addr, &reg);
 			if (ret < 0) {
-				dev_err(&pdev->dev,
+				dev_err(pmic->dev,
 					"reading TSTEP reg failed: %d\n", ret);
 				return ret;
 			}
-			pmic->desc[id].ramp_delay =
-					palmas_smps_ramp_delay[reg & 0x3];
-			pmic->ramp_delay[id] = pmic->desc[id].ramp_delay;
+			desc->ramp_delay = palmas_smps_ramp_delay[reg & 0x3];
+			pmic->ramp_delay[id] = desc->ramp_delay;
 		}
 
 		/* Initialise sleep/init values from platform data */
 		if (pdata && pdata->reg_init[id]) {
 			reg_init = pdata->reg_init[id];
-			ret = palmas_smps_init(palmas, id, reg_init);
+			ret = palmas_smps_init(pmic->palmas, id, reg_init);
 			if (ret)
 				return ret;
 		} else {
@@ -903,31 +1145,28 @@ static int palmas_regulators_probe(struc
 		}
 
 		/* Register the regulators */
-		pmic->desc[id].name = palmas_regs_info[id].name;
-		pmic->desc[id].id = id;
+		desc->name = rinfo->name;
+		desc->id = id;
 
 		switch (id) {
 		case PALMAS_REG_SMPS10_OUT1:
 		case PALMAS_REG_SMPS10_OUT2:
-			pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
-			pmic->desc[id].ops = &palmas_ops_smps10;
-			pmic->desc[id].vsel_reg =
-					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-							PALMAS_SMPS10_CTRL);
-			pmic->desc[id].vsel_mask = SMPS10_VSEL;
-			pmic->desc[id].enable_reg =
-					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-							PALMAS_SMPS10_CTRL);
+			desc->n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
+			desc->ops = &palmas_ops_smps10;
+			desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+							    PALMAS_SMPS10_CTRL);
+			desc->vsel_mask = SMPS10_VSEL;
+			desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+							    PALMAS_SMPS10_CTRL);
 			if (id == PALMAS_REG_SMPS10_OUT1)
-				pmic->desc[id].enable_mask = SMPS10_SWITCH_EN;
+				desc->enable_mask = SMPS10_SWITCH_EN;
 			else
-				pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
-			pmic->desc[id].bypass_reg =
-					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-							PALMAS_SMPS10_CTRL);
-			pmic->desc[id].bypass_mask = SMPS10_BYPASS_EN;
-			pmic->desc[id].min_uV = 3750000;
-			pmic->desc[id].uV_step = 1250000;
+				desc->enable_mask = SMPS10_BOOST_EN;
+			desc->bypass_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+							    PALMAS_SMPS10_CTRL);
+			desc->bypass_mask = SMPS10_BYPASS_EN;
+			desc->min_uV = 3750000;
+			desc->uV_step = 1250000;
 			break;
 		default:
 			/*
@@ -936,8 +1175,8 @@ static int palmas_regulators_probe(struc
 			 * otherwise we error in probe with unsupportable
 			 * ranges. Read the current smps mode for later use.
 			 */
-			addr = palmas_regs_info[id].vsel_addr;
-			pmic->desc[id].n_linear_ranges = 3;
+			addr = rinfo->vsel_addr;
+			desc->n_linear_ranges = 3;
 
 			ret = palmas_smps_read(pmic->palmas, addr, &reg);
 			if (ret)
@@ -945,56 +1184,50 @@ static int palmas_regulators_probe(struc
 			if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
 				pmic->range[id] = 1;
 			if (pmic->range[id])
-				pmic->desc[id].linear_ranges = smps_high_ranges;
+				desc->linear_ranges = smps_high_ranges;
 			else
-				pmic->desc[id].linear_ranges = smps_low_ranges;
+				desc->linear_ranges = smps_low_ranges;
 
 			if (reg_init && reg_init->roof_floor)
-				pmic->desc[id].ops =
-						&palmas_ops_ext_control_smps;
+				desc->ops = &palmas_ops_ext_control_smps;
 			else
-				pmic->desc[id].ops = &palmas_ops_smps;
-			pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
-			pmic->desc[id].vsel_reg =
-					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-						palmas_regs_info[id].vsel_addr);
-			pmic->desc[id].vsel_mask =
-					PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
+				desc->ops = &palmas_ops_smps;
+			desc->n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+			desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+							    rinfo->vsel_addr);
+			desc->vsel_mask = PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
 
 			/* Read the smps mode for later use. */
-			addr = palmas_regs_info[id].ctrl_addr;
+			addr = rinfo->ctrl_addr;
 			ret = palmas_smps_read(pmic->palmas, addr, &reg);
 			if (ret)
 				return ret;
 			pmic->current_reg_mode[id] = reg &
 					PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
-			pmic->desc[id].enable_reg =
-					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-						palmas_regs_info[id].ctrl_addr);
-			pmic->desc[id].enable_mask =
-					PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+			desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+							      rinfo->ctrl_addr);
+			desc->enable_mask = PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 			/* set_mode overrides this value */
-			pmic->desc[id].enable_val = SMPS_CTRL_MODE_ON;
+			desc->enable_val = SMPS_CTRL_MODE_ON;
 		}
 
-		pmic->desc[id].type = REGULATOR_VOLTAGE;
-		pmic->desc[id].owner = THIS_MODULE;
+		desc->type = REGULATOR_VOLTAGE;
+		desc->owner = THIS_MODULE;
 
 		if (pdata)
 			config.init_data = pdata->reg_data[id];
 		else
 			config.init_data = NULL;
 
-		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
-		config.of_node = palmas_matches[id].of_node;
+		desc->supply_name = rinfo->sname;
+		config.of_node = ddata->palmas_matches[id].of_node;
 
-		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
-					       &config);
+		rdev = devm_regulator_register(pmic->dev, desc, &config);
 		if (IS_ERR(rdev)) {
-			dev_err(&pdev->dev,
+			dev_err(pmic->dev,
 				"failed to register %s regulator\n",
-				pdev->name);
+				pdev_name);
 			return PTR_ERR(rdev);
 		}
 
@@ -1002,123 +1235,377 @@ static int palmas_regulators_probe(struc
 		pmic->rdev[id] = rdev;
 	}
 
-	/* Start this loop from the id left from previous loop */
-	for (; id < PALMAS_NUM_REGS; id++) {
-		if (pdata && pdata->reg_init[id])
+	return 0;
+}
+
+static int tps65917_smps_registration(struct palmas_pmic *pmic,
+				      struct palmas_pmic_driver_data *ddata,
+				      struct palmas_pmic_platform_data *pdata,
+				      const char *pdev_name,
+				      struct regulator_config config)
+{
+	int id, ret;
+	unsigned int addr, reg;
+	struct regulator_dev *rdev;
+	struct palmas_reg_init *reg_init;
+	struct palmas_regs_info *rinfo;
+	struct regulator_desc *desc;
+
+	for (id = ddata->smps_start; id <= ddata->smps_end; id++) {
+		/*
+		 * Miss out regulators which are not available due
+		 * to slaving configurations.
+		 */
+		desc = &pmic->desc[id];
+		desc->n_linear_ranges = 3;
+		if ((id == TPS65917_REG_SMPS2) && pmic->smps12)
+			continue;
+
+		/* Initialise sleep/init values from platform data */
+		if (pdata && pdata->reg_init[id]) {
 			reg_init = pdata->reg_init[id];
-		else
+			ret = palmas_smps_init(pmic->palmas, id, reg_init);
+			if (ret)
+				return ret;
+		} else {
 			reg_init = NULL;
+		}
+		rinfo = &ddata->palmas_regs_info[id];
 
-		/* Miss out regulators which are not available due
-		 * to alternate functions.
+		/* Register the regulators */
+		desc->name = rinfo->name;
+		desc->id = id;
+
+		/*
+		 * Read and store the RANGE bit for later use
+		 * This must be done before regulator is probed,
+		 * otherwise we error in probe with unsupportable
+		 * ranges. Read the current smps mode for later use.
 		 */
+		addr = rinfo->vsel_addr;
 
-		/* Register the regulators */
-		pmic->desc[id].name = palmas_regs_info[id].name;
-		pmic->desc[id].id = id;
-		pmic->desc[id].type = REGULATOR_VOLTAGE;
-		pmic->desc[id].owner = THIS_MODULE;
+		ret = palmas_smps_read(pmic->palmas, addr, &reg);
+		if (ret)
+			return ret;
+		if (reg & TPS65917_SMPS1_VOLTAGE_RANGE)
+			pmic->range[id] = 1;
 
-		if (id < PALMAS_REG_REGEN1) {
-			pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
-			if (reg_init && reg_init->roof_floor)
-				pmic->desc[id].ops =
-					&palmas_ops_ext_control_ldo;
-			else
-				pmic->desc[id].ops = &palmas_ops_ldo;
-			pmic->desc[id].min_uV = 900000;
-			pmic->desc[id].uV_step = 50000;
-			pmic->desc[id].linear_min_sel = 1;
-			pmic->desc[id].enable_time = 500;
-			pmic->desc[id].vsel_reg =
-					PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
-						palmas_regs_info[id].vsel_addr);
-			pmic->desc[id].vsel_mask =
-					PALMAS_LDO1_VOLTAGE_VSEL_MASK;
-			pmic->desc[id].enable_reg =
-					PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
-						palmas_regs_info[id].ctrl_addr);
-			pmic->desc[id].enable_mask =
-					PALMAS_LDO1_CTRL_MODE_ACTIVE;
+		if (pmic->range[id])
+			desc->linear_ranges = smps_high_ranges;
+		else
+			desc->linear_ranges = smps_low_ranges;
 
-			/* Check if LDO8 is in tracking mode or not */
-			if (pdata && (id == PALMAS_REG_LDO8) &&
-					pdata->enable_ldo8_tracking) {
-				palmas_enable_ldo8_track(palmas);
-				pmic->desc[id].min_uV = 450000;
-				pmic->desc[id].uV_step = 25000;
-			}
+		if (reg_init && reg_init->roof_floor)
+			desc->ops = &tps65917_ops_ext_control_smps;
+		else
+			desc->ops = &tps65917_ops_smps;
+		desc->n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+		desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+						    rinfo->vsel_addr);
+		desc->vsel_mask = PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
+		desc->ramp_delay = 2500;
 
-			/* LOD6 in vibrator mode will have enable time 2000us */
-			if (pdata && pdata->ldo6_vibrator &&
-				(id == PALMAS_REG_LDO6))
-				pmic->desc[id].enable_time = 2000;
-		} else {
-			pmic->desc[id].n_voltages = 1;
-			if (reg_init && reg_init->roof_floor)
-				pmic->desc[id].ops =
-					&palmas_ops_ext_control_extreg;
-			else
-				pmic->desc[id].ops = &palmas_ops_extreg;
-			pmic->desc[id].enable_reg =
-					PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
-						palmas_regs_info[id].ctrl_addr);
-			pmic->desc[id].enable_mask =
-					PALMAS_REGEN1_CTRL_MODE_ACTIVE;
-		}
+		/* Read the smps mode for later use. */
+		addr = rinfo->ctrl_addr;
+		ret = palmas_smps_read(pmic->palmas, addr, &reg);
+		if (ret)
+			return ret;
+		pmic->current_reg_mode[id] = reg &
+				PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+		desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+						      rinfo->ctrl_addr);
+		desc->enable_mask = PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+		/* set_mode overrides this value */
+		desc->enable_val = SMPS_CTRL_MODE_ON;
+
+		desc->type = REGULATOR_VOLTAGE;
+		desc->owner = THIS_MODULE;
 
 		if (pdata)
 			config.init_data = pdata->reg_data[id];
 		else
 			config.init_data = NULL;
 
-		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
-		config.of_node = palmas_matches[id].of_node;
+		desc->supply_name = rinfo->sname;
+		config.of_node = ddata->palmas_matches[id].of_node;
 
-		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
-					       &config);
+		rdev = devm_regulator_register(pmic->dev, desc, &config);
 		if (IS_ERR(rdev)) {
-			dev_err(&pdev->dev,
+			dev_err(pmic->dev,
 				"failed to register %s regulator\n",
-				pdev->name);
+				pdev_name);
 			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
 		pmic->rdev[id] = rdev;
+	}
 
-		/* Initialise sleep/init values from platform data */
-		if (pdata) {
-			reg_init = pdata->reg_init[id];
-			if (reg_init) {
-				if (id < PALMAS_REG_REGEN1)
-					ret = palmas_ldo_init(palmas,
-							id, reg_init);
-				else
-					ret = palmas_extreg_init(palmas,
-							id, reg_init);
-				if (ret)
-					return ret;
+	return 0;
+}
+
+static struct of_regulator_match palmas_matches[] = {
+	{ .name = "smps12", },
+	{ .name = "smps123", },
+	{ .name = "smps3", },
+	{ .name = "smps45", },
+	{ .name = "smps457", },
+	{ .name = "smps6", },
+	{ .name = "smps7", },
+	{ .name = "smps8", },
+	{ .name = "smps9", },
+	{ .name = "smps10_out2", },
+	{ .name = "smps10_out1", },
+	{ .name = "ldo1", },
+	{ .name = "ldo2", },
+	{ .name = "ldo3", },
+	{ .name = "ldo4", },
+	{ .name = "ldo5", },
+	{ .name = "ldo6", },
+	{ .name = "ldo7", },
+	{ .name = "ldo8", },
+	{ .name = "ldo9", },
+	{ .name = "ldoln", },
+	{ .name = "ldousb", },
+	{ .name = "regen1", },
+	{ .name = "regen2", },
+	{ .name = "regen3", },
+	{ .name = "sysen1", },
+	{ .name = "sysen2", },
+};
+
+static struct of_regulator_match tps65917_matches[] = {
+	{ .name = "smps1", },
+	{ .name = "smps2", },
+	{ .name = "smps3", },
+	{ .name = "smps4", },
+	{ .name = "smps5", },
+	{ .name = "ldo1", },
+	{ .name = "ldo2", },
+	{ .name = "ldo3", },
+	{ .name = "ldo4", },
+	{ .name = "ldo5", },
+	{ .name = "regen1", },
+	{ .name = "regen2", },
+	{ .name = "regen3", },
+	{ .name = "sysen1", },
+	{ .name = "sysen2", },
+};
+
+static struct palmas_pmic_driver_data palmas_ddata = {
+	.smps_start = PALMAS_REG_SMPS12,
+	.smps_end = PALMAS_REG_SMPS10_OUT1,
+	.ldo_begin = PALMAS_REG_LDO1,
+	.ldo_end = PALMAS_REG_LDOUSB,
+	.max_reg = PALMAS_NUM_REGS,
+	.palmas_regs_info = palmas_generic_regs_info,
+	.palmas_matches = palmas_matches,
+	.sleep_req_info = palma_sleep_req_info,
+	.smps_register = palmas_smps_registration,
+	.ldo_register = palmas_ldo_registration,
+};
+
+static struct palmas_pmic_driver_data tps65917_ddata = {
+	.smps_start = TPS65917_REG_SMPS1,
+	.smps_end = TPS65917_REG_SMPS5,
+	.ldo_begin = TPS65917_REG_LDO1,
+	.ldo_end = TPS65917_REG_LDO5,
+	.max_reg = TPS65917_NUM_REGS,
+	.palmas_regs_info = tps65917_regs_info,
+	.palmas_matches = tps65917_matches,
+	.sleep_req_info = tps65917_sleep_req_info,
+	.smps_register = tps65917_smps_registration,
+	.ldo_register = tps65917_ldo_registration,
+};
+
+static void palmas_dt_to_pdata(struct device *dev,
+			       struct device_node *node,
+			       struct palmas_pmic_platform_data *pdata,
+			       struct palmas_pmic_driver_data *ddata)
+{
+	struct device_node *regulators;
+	u32 prop;
+	int idx, ret;
+
+	regulators = of_get_child_by_name(node, "regulators");
+	if (!regulators) {
+		dev_info(dev, "regulator node not found\n");
+		return;
+	}
+
+	ret = of_regulator_match(dev, regulators, ddata->palmas_matches,
+				 ddata->max_reg);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+		return;
+	}
+
+	for (idx = 0; idx < ddata->max_reg; idx++) {
+		if (!ddata->palmas_matches[idx].init_data ||
+		    !ddata->palmas_matches[idx].of_node)
+			continue;
+
+		pdata->reg_data[idx] = ddata->palmas_matches[idx].init_data;
+
+		pdata->reg_init[idx] = devm_kzalloc(dev,
+				sizeof(struct palmas_reg_init), GFP_KERNEL);
+
+		pdata->reg_init[idx]->warm_reset =
+			of_property_read_bool(ddata->palmas_matches[idx].of_node,
+					      "ti,warm-reset");
+
+		ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
+					   "ti,roof-floor", &prop);
+		/* EINVAL: Property not found */
+		if (ret != -EINVAL) {
+			int econtrol;
+
+			/* use default value, when no value is specified */
+			econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+			if (!ret) {
+				switch (prop) {
+				case 1:
+					econtrol = PALMAS_EXT_CONTROL_ENABLE1;
+					break;
+				case 2:
+					econtrol = PALMAS_EXT_CONTROL_ENABLE2;
+					break;
+				case 3:
+					econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+					break;
+				default:
+					WARN_ON(1);
+					dev_warn(dev,
+						 "%s: Invalid roof-floor option: %u\n",
+					     palmas_matches[idx].name, prop);
+					break;
+				}
 			}
+			pdata->reg_init[idx]->roof_floor = econtrol;
 		}
-	}
 
+		ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
+					   "ti,mode-sleep", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->mode_sleep = prop;
 
-	return 0;
+		ret = of_property_read_bool(ddata->palmas_matches[idx].of_node,
+					    "ti,smps-range");
+		if (ret)
+			pdata->reg_init[idx]->vsel =
+				PALMAS_SMPS12_VOLTAGE_RANGE;
+
+		if (idx == PALMAS_REG_LDO8)
+			pdata->enable_ldo8_tracking = of_property_read_bool(
+						ddata->palmas_matches[idx].of_node,
+						"ti,enable-ldo8-tracking");
+	}
+
+	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
-static const struct of_device_id of_palmas_match_tbl[] = {
-	{ .compatible = "ti,palmas-pmic", },
-	{ .compatible = "ti,twl6035-pmic", },
-	{ .compatible = "ti,twl6036-pmic", },
-	{ .compatible = "ti,twl6037-pmic", },
-	{ .compatible = "ti,tps65913-pmic", },
-	{ .compatible = "ti,tps65914-pmic", },
-	{ .compatible = "ti,tps80036-pmic", },
-	{ .compatible = "ti,tps659038-pmic", },
+static struct of_device_id of_palmas_match_tbl[] = {
+	{
+		.compatible = "ti,palmas-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,twl6035-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,twl6036-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,twl6037-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,tps65913-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,tps65914-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,tps80036-pmic",
+		.data = &palmas_ddata,
+	},
+	{
+		.compatible = "ti,tps659038-pmic",
+		.data = &palmas_ddata,
+	},
+	 {
+		.compatible = "ti,tps65917-pmic",
+		.data = &tps65917_ddata,
+	},
 	{ /* end */ }
 };
 
+static int palmas_regulators_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct device_node *node = pdev->dev.of_node;
+	struct palmas_pmic_driver_data *driver_data;
+	struct regulator_config config = { };
+	struct palmas_pmic *pmic;
+	const char *pdev_name;
+	const struct of_device_id *match;
+	int ret = 0;
+	unsigned int reg;
+
+	match = of_match_device(of_match_ptr(of_palmas_match_tbl), &pdev->dev);
+
+	if (!match)
+		return -ENODATA;
+
+	driver_data = (struct palmas_pmic_driver_data *)match->data;
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+	if (!pmic)
+		return -ENOMEM;
+
+	pmic->dev = &pdev->dev;
+	pmic->palmas = palmas;
+	palmas->pmic = pmic;
+	platform_set_drvdata(pdev, pmic);
+	pmic->palmas->pmic_ddata = driver_data;
+
+	palmas_dt_to_pdata(&pdev->dev, node, pdata, driver_data);
+
+	ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
+	if (ret)
+		return ret;
+
+	if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)
+		pmic->smps123 = 1;
+
+	if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
+		pmic->smps457 = 1;
+
+	config.regmap = palmas->regmap[REGULATOR_SLAVE];
+	config.dev = &pdev->dev;
+	config.driver_data = pmic;
+	pdev_name = pdev->name;
+
+	ret = driver_data->smps_register(pmic, driver_data, pdata, pdev_name,
+					 config);
+	if (ret)
+		return ret;
+
+	ret = driver_data->ldo_register(pmic, driver_data, pdata, pdev_name,
+					config);
+
+	return ret;
+}
+
 static struct platform_driver palmas_driver = {
 	.driver = {
 		.name = "palmas-pmic",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/s2mps11.c linux-libre-3.17-rc7-gnu/drivers/regulator/s2mps11.c
--- linux-libre-3.16-gnu/drivers/regulator/s2mps11.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/s2mps11.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
 
 struct s2mps11_info {
 	unsigned int rdev_num;
@@ -40,11 +41,15 @@ struct s2mps11_info {
 	int ramp_delay16;
 	int ramp_delay7810;
 	int ramp_delay9;
+
+	enum sec_device_type dev_type;
+
 	/*
-	 * One bit for each S2MPS14 regulator whether the suspend mode
+	 * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
 	 * was enabled.
 	 */
-	unsigned int s2mps14_suspend_state:30;
+	unsigned long long s2mps14_suspend_state:35;
+
 	/* Array of size rdev_num with GPIO-s for external sleep control */
 	int *ext_control_gpio;
 };
@@ -415,12 +420,24 @@ static int s2mps14_regulator_enable(stru
 	struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
 	unsigned int val;
 
-	if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
-		val = S2MPS14_ENABLE_SUSPEND;
-	else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
-		val = S2MPS14_ENABLE_EXT_CONTROL;
-	else
-		val = rdev->desc->enable_mask;
+	switch (s2mps11->dev_type) {
+	case S2MPS14X:
+		if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+			val = S2MPS14_ENABLE_SUSPEND;
+		else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
+			val = S2MPS14_ENABLE_EXT_CONTROL;
+		else
+			val = rdev->desc->enable_mask;
+		break;
+	case S2MPU02:
+		if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+			val = S2MPU02_ENABLE_SUSPEND;
+		else
+			val = rdev->desc->enable_mask;
+		break;
+	default:
+		return -EINVAL;
+	};
 
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 			rdev->desc->enable_mask, val);
@@ -429,12 +446,38 @@ static int s2mps14_regulator_enable(stru
 static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
 {
 	int ret;
-	unsigned int val;
+	unsigned int val, state;
 	struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+	int rdev_id = rdev_get_id(rdev);
 
-	/* LDO3 should be always on and does not support suspend mode */
-	if (rdev_get_id(rdev) == S2MPS14_LDO3)
-		return 0;
+	/* Below LDO should be always on or does not support suspend mode. */
+	switch (s2mps11->dev_type) {
+	case S2MPS14X:
+		switch (rdev_id) {
+		case S2MPS14_LDO3:
+			return 0;
+		default:
+			state = S2MPS14_ENABLE_SUSPEND;
+			break;
+		};
+		break;
+	case S2MPU02:
+		switch (rdev_id) {
+		case S2MPU02_LDO13:
+		case S2MPU02_LDO14:
+		case S2MPU02_LDO15:
+		case S2MPU02_LDO17:
+		case S2MPU02_BUCK7:
+			state = S2MPU02_DISABLE_SUSPEND;
+			break;
+		default:
+			state = S2MPU02_ENABLE_SUSPEND;
+			break;
+		};
+		break;
+	default:
+		return -EINVAL;
+	};
 
 	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
 	if (ret < 0)
@@ -452,7 +495,7 @@ static int s2mps14_regulator_set_suspend
 		return 0;
 
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-			rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND);
+			rdev->desc->enable_mask, state);
 }
 
 static struct regulator_ops s2mps14_reg_ops = {
@@ -605,8 +648,7 @@ static void s2mps14_pmic_dt_parse_ext_co
 }
 
 static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
-		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
-		enum sec_device_type dev_type)
+		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
 {
 	struct device_node *reg_np;
 
@@ -617,7 +659,7 @@ static int s2mps11_pmic_dt_parse(struct
 	}
 
 	of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
-	if (dev_type == S2MPS14X)
+	if (s2mps11->dev_type == S2MPS14X)
 		s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
 
 	of_node_put(reg_np);
@@ -625,6 +667,238 @@ static int s2mps11_pmic_dt_parse(struct
 	return 0;
 }
 
+static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+	unsigned int ramp_val, ramp_shift, ramp_reg;
+
+	switch (rdev_get_id(rdev)) {
+	case S2MPU02_BUCK1:
+		ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT;
+		break;
+	case S2MPU02_BUCK2:
+		ramp_shift = S2MPU02_BUCK2_RAMP_SHIFT;
+		break;
+	case S2MPU02_BUCK3:
+		ramp_shift = S2MPU02_BUCK3_RAMP_SHIFT;
+		break;
+	case S2MPU02_BUCK4:
+		ramp_shift = S2MPU02_BUCK4_RAMP_SHIFT;
+		break;
+	default:
+		return 0;
+	}
+	ramp_reg = S2MPU02_REG_RAMP1;
+	ramp_val = get_ramp_delay(ramp_delay);
+
+	return regmap_update_bits(rdev->regmap, ramp_reg,
+				  S2MPU02_BUCK1234_RAMP_MASK << ramp_shift,
+				  ramp_val << ramp_shift);
+}
+
+static struct regulator_ops s2mpu02_ldo_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= s2mps14_regulator_enable,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_suspend_disable	= s2mps14_regulator_set_suspend_disable,
+};
+
+static struct regulator_ops s2mpu02_buck_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= s2mps14_regulator_enable,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_suspend_disable	= s2mps14_regulator_set_suspend_disable,
+	.set_ramp_delay		= s2mpu02_set_ramp_delay,
+};
+
+#define regulator_desc_s2mpu02_ldo1(num) {		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPU02_LDO##num,		\
+	.ops		= &s2mpu02_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPU02_LDO_MIN_900MV,	\
+	.uV_step	= S2MPU02_LDO_STEP_12_5MV,	\
+	.linear_min_sel	= S2MPU02_LDO_GROUP1_START_SEL,	\
+	.n_voltages	= S2MPU02_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPU02_REG_L1CTRL,		\
+	.vsel_mask	= S2MPU02_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPU02_REG_L1CTRL,		\
+	.enable_mask	= S2MPU02_ENABLE_MASK		\
+}
+#define regulator_desc_s2mpu02_ldo2(num) {		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPU02_LDO##num,		\
+	.ops		= &s2mpu02_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPU02_LDO_MIN_1050MV,	\
+	.uV_step	= S2MPU02_LDO_STEP_25MV,	\
+	.linear_min_sel	= S2MPU02_LDO_GROUP2_START_SEL,	\
+	.n_voltages	= S2MPU02_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPU02_REG_L2CTRL1,		\
+	.vsel_mask	= S2MPU02_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPU02_REG_L2CTRL1,		\
+	.enable_mask	= S2MPU02_ENABLE_MASK		\
+}
+#define regulator_desc_s2mpu02_ldo3(num) {		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPU02_LDO##num,		\
+	.ops		= &s2mpu02_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPU02_LDO_MIN_900MV,	\
+	.uV_step	= S2MPU02_LDO_STEP_12_5MV,	\
+	.linear_min_sel	= S2MPU02_LDO_GROUP1_START_SEL,	\
+	.n_voltages	= S2MPU02_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.vsel_mask	= S2MPU02_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.enable_mask	= S2MPU02_ENABLE_MASK		\
+}
+#define regulator_desc_s2mpu02_ldo4(num) {		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPU02_LDO##num,		\
+	.ops		= &s2mpu02_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPU02_LDO_MIN_1050MV,	\
+	.uV_step	= S2MPU02_LDO_STEP_25MV,	\
+	.linear_min_sel	= S2MPU02_LDO_GROUP2_START_SEL,	\
+	.n_voltages	= S2MPU02_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.vsel_mask	= S2MPU02_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.enable_mask	= S2MPU02_ENABLE_MASK		\
+}
+#define regulator_desc_s2mpu02_ldo5(num) {		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPU02_LDO##num,		\
+	.ops		= &s2mpu02_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPU02_LDO_MIN_1600MV,	\
+	.uV_step	= S2MPU02_LDO_STEP_50MV,	\
+	.linear_min_sel	= S2MPU02_LDO_GROUP3_START_SEL,	\
+	.n_voltages	= S2MPU02_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.vsel_mask	= S2MPU02_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPU02_REG_L3CTRL + num - 3,	\
+	.enable_mask	= S2MPU02_ENABLE_MASK		\
+}
+
+#define regulator_desc_s2mpu02_buck1234(num) {			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPU02_BUCK##num,			\
+	.ops		= &s2mpu02_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPU02_BUCK1234_MIN_600MV,		\
+	.uV_step	= S2MPU02_BUCK1234_STEP_6_25MV,		\
+	.n_voltages	= S2MPU02_BUCK_N_VOLTAGES,		\
+	.linear_min_sel = S2MPU02_BUCK1234_START_SEL,		\
+	.ramp_delay	= S2MPU02_BUCK_RAMP_DELAY,		\
+	.vsel_reg	= S2MPU02_REG_B1CTRL2 + (num - 1) * 2,	\
+	.vsel_mask	= S2MPU02_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPU02_REG_B1CTRL1 + (num - 1) * 2,	\
+	.enable_mask	= S2MPU02_ENABLE_MASK			\
+}
+#define regulator_desc_s2mpu02_buck5(num) {			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPU02_BUCK##num,			\
+	.ops		= &s2mpu02_ldo_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPU02_BUCK5_MIN_1081_25MV,		\
+	.uV_step	= S2MPU02_BUCK5_STEP_6_25MV,		\
+	.n_voltages	= S2MPU02_BUCK_N_VOLTAGES,		\
+	.linear_min_sel = S2MPU02_BUCK5_START_SEL,		\
+	.ramp_delay	= S2MPU02_BUCK_RAMP_DELAY,		\
+	.vsel_reg	= S2MPU02_REG_B5CTRL2,			\
+	.vsel_mask	= S2MPU02_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPU02_REG_B5CTRL1,			\
+	.enable_mask	= S2MPU02_ENABLE_MASK			\
+}
+#define regulator_desc_s2mpu02_buck6(num) {			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPU02_BUCK##num,			\
+	.ops		= &s2mpu02_ldo_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPU02_BUCK6_MIN_1700MV,		\
+	.uV_step	= S2MPU02_BUCK6_STEP_2_50MV,		\
+	.n_voltages	= S2MPU02_BUCK_N_VOLTAGES,		\
+	.linear_min_sel = S2MPU02_BUCK6_START_SEL,		\
+	.ramp_delay	= S2MPU02_BUCK_RAMP_DELAY,		\
+	.vsel_reg	= S2MPU02_REG_B6CTRL2,			\
+	.vsel_mask	= S2MPU02_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPU02_REG_B6CTRL1,			\
+	.enable_mask	= S2MPU02_ENABLE_MASK			\
+}
+#define regulator_desc_s2mpu02_buck7(num) {			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPU02_BUCK##num,			\
+	.ops		= &s2mpu02_ldo_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPU02_BUCK7_MIN_900MV,		\
+	.uV_step	= S2MPU02_BUCK7_STEP_6_25MV,		\
+	.n_voltages	= S2MPU02_BUCK_N_VOLTAGES,		\
+	.linear_min_sel = S2MPU02_BUCK7_START_SEL,		\
+	.ramp_delay	= S2MPU02_BUCK_RAMP_DELAY,		\
+	.vsel_reg	= S2MPU02_REG_B7CTRL2,			\
+	.vsel_mask	= S2MPU02_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPU02_REG_B7CTRL1,			\
+	.enable_mask	= S2MPU02_ENABLE_MASK			\
+}
+
+static const struct regulator_desc s2mpu02_regulators[] = {
+	regulator_desc_s2mpu02_ldo1(1),
+	regulator_desc_s2mpu02_ldo2(2),
+	regulator_desc_s2mpu02_ldo4(3),
+	regulator_desc_s2mpu02_ldo5(4),
+	regulator_desc_s2mpu02_ldo4(5),
+	regulator_desc_s2mpu02_ldo3(6),
+	regulator_desc_s2mpu02_ldo3(7),
+	regulator_desc_s2mpu02_ldo4(8),
+	regulator_desc_s2mpu02_ldo5(9),
+	regulator_desc_s2mpu02_ldo3(10),
+	regulator_desc_s2mpu02_ldo4(11),
+	regulator_desc_s2mpu02_ldo5(12),
+	regulator_desc_s2mpu02_ldo5(13),
+	regulator_desc_s2mpu02_ldo5(14),
+	regulator_desc_s2mpu02_ldo5(15),
+	regulator_desc_s2mpu02_ldo5(16),
+	regulator_desc_s2mpu02_ldo4(17),
+	regulator_desc_s2mpu02_ldo5(18),
+	regulator_desc_s2mpu02_ldo3(19),
+	regulator_desc_s2mpu02_ldo4(20),
+	regulator_desc_s2mpu02_ldo5(21),
+	regulator_desc_s2mpu02_ldo5(22),
+	regulator_desc_s2mpu02_ldo5(23),
+	regulator_desc_s2mpu02_ldo4(24),
+	regulator_desc_s2mpu02_ldo5(25),
+	regulator_desc_s2mpu02_ldo4(26),
+	regulator_desc_s2mpu02_ldo5(27),
+	regulator_desc_s2mpu02_ldo5(28),
+	regulator_desc_s2mpu02_buck1234(1),
+	regulator_desc_s2mpu02_buck1234(2),
+	regulator_desc_s2mpu02_buck1234(3),
+	regulator_desc_s2mpu02_buck1234(4),
+	regulator_desc_s2mpu02_buck5(5),
+	regulator_desc_s2mpu02_buck6(6),
+	regulator_desc_s2mpu02_buck7(7),
+};
+
 static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -634,15 +908,14 @@ static int s2mps11_pmic_probe(struct pla
 	struct s2mps11_info *s2mps11;
 	int i, ret = 0;
 	const struct regulator_desc *regulators;
-	enum sec_device_type dev_type;
 
 	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
 				GFP_KERNEL);
 	if (!s2mps11)
 		return -ENOMEM;
 
-	dev_type = platform_get_device_id(pdev)->driver_data;
-	switch (dev_type) {
+	s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
+	switch (s2mps11->dev_type) {
 	case S2MPS11X:
 		s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
 		regulators = s2mps11_regulators;
@@ -651,8 +924,13 @@ static int s2mps11_pmic_probe(struct pla
 		s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
 		regulators = s2mps14_regulators;
 		break;
+	case S2MPU02:
+		s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
+		regulators = s2mpu02_regulators;
+		break;
 	default:
-		dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
+		dev_err(&pdev->dev, "Invalid device type: %u\n",
+				    s2mps11->dev_type);
 		return -EINVAL;
 	};
 
@@ -686,7 +964,7 @@ static int s2mps11_pmic_probe(struct pla
 	for (i = 0; i < s2mps11->rdev_num; i++)
 		rdata[i].name = regulators[i].name;
 
-	ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
+	ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
 	if (ret)
 		goto out;
 
@@ -739,6 +1017,7 @@ out:
 static const struct platform_device_id s2mps11_pmic_id[] = {
 	{ "s2mps11-pmic", S2MPS11X},
 	{ "s2mps14-pmic", S2MPS14X},
+	{ "s2mpu02-pmic", S2MPU02},
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
@@ -766,5 +1045,5 @@ module_exit(s2mps11_pmic_exit);
 
 /* Module information */
 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14 Regulator Driver");
+MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPU02 Regulator Driver");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/s5m8767.c linux-libre-3.17-rc7-gnu/drivers/regulator/s5m8767.c
--- linux-libre-3.16-gnu/drivers/regulator/s5m8767.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/s5m8767.c	2014-09-28 17:29:07.000000000 -0400
@@ -686,7 +686,7 @@ static int s5m8767_pmic_probe(struct pla
 	struct sec_platform_data *pdata = iodev->pdata;
 	struct regulator_config config = { };
 	struct s5m8767_info *s5m8767;
-	int i, ret, size, buck_init;
+	int i, ret, buck_init;
 
 	if (!pdata) {
 		dev_err(pdev->dev.parent, "Platform data not supplied\n");
@@ -725,8 +725,6 @@ static int s5m8767_pmic_probe(struct pla
 	if (!s5m8767)
 		return -ENOMEM;
 
-	size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2);
-
 	s5m8767->dev = &pdev->dev;
 	s5m8767->iodev = iodev;
 	s5m8767->num_regulators = pdata->num_regulators;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/tps65090-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/tps65090-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/tps65090-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/tps65090-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -192,12 +192,14 @@ static struct regulator_ops tps65090_fet
 static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _ops)	\
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
 {							\
 	.name = "TPS65090_RAILS"#_id,			\
 	.supply_name = _sname,				\
 	.id = TPS65090_REGULATOR_##_id,			\
+	.n_voltages = _nvolt,				\
 	.ops = &_ops,					\
+	.fixed_uV = _volt,				\
 	.enable_reg = _en_reg,				\
 	.enable_val = _en_bits,				\
 	.enable_mask = _en_bits,			\
@@ -205,40 +207,46 @@ static struct regulator_ops tps65090_ldo
 	.owner = THIS_MODULE,				\
 }
 
+#define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \
+	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 1, _volt, _ops)
+
+#define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \
+	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 0, 0, _ops)
+
 static struct regulator_desc tps65090_regulator_desc[] = {
-	tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, BIT(CTRL_EN_BIT),
-			  tps65090_reg_control_ops),
-	tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, BIT(CTRL_EN_BIT),
-			  tps65090_reg_control_ops),
-	tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, BIT(CTRL_EN_BIT),
-			  tps65090_reg_control_ops),
+	tps65090_REG_FIXEDV(DCDC1, "vsys1",   0x0C, BIT(CTRL_EN_BIT), 5000000,
+			    tps65090_reg_control_ops),
+	tps65090_REG_FIXEDV(DCDC2, "vsys2",   0x0D, BIT(CTRL_EN_BIT), 3300000,
+			    tps65090_reg_control_ops),
+	tps65090_REG_SWITCH(DCDC3, "vsys3",   0x0E, BIT(CTRL_EN_BIT),
+			    tps65090_reg_control_ops),
 
-	tps65090_REG_DESC(FET1,  "infet1",  0x0F,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET2,  "infet2",  0x10,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET3,  "infet3",  0x11,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET4,  "infet4",  0x12,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET5,  "infet5",  0x13,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET6,  "infet6",  0x14,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
-	tps65090_REG_DESC(FET7,  "infet7",  0x15,
-			  BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
-			  tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET1,  "infet1",  0x0F,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET2,  "infet2",  0x10,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET3,  "infet3",  0x11,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET4,  "infet4",  0x12,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET5,  "infet5",  0x13,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET6,  "infet6",  0x14,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
+	tps65090_REG_SWITCH(FET7,  "infet7",  0x15,
+			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+			    tps65090_fet_control_ops),
 
-	tps65090_REG_DESC(LDO1,  "vsys-l1", 0, 0,
-			  tps65090_ldo_ops),
-	tps65090_REG_DESC(LDO2,  "vsys-l2", 0, 0,
-			  tps65090_ldo_ops),
+	tps65090_REG_FIXEDV(LDO1,  "vsys-l1", 0, 0, 5000000,
+			    tps65090_ldo_ops),
+	tps65090_REG_FIXEDV(LDO2,  "vsys-l2", 0, 0, 3300000,
+			    tps65090_ldo_ops),
 };
 
 static inline bool is_dcdc(int id)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/tps65217-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/tps65217-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/tps65217-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/tps65217-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ static const struct regulator_linear_ran
 static int tps65217_pmic_enable(struct regulator_dev *dev)
 {
 	struct tps65217 *tps = rdev_get_drvdata(dev);
-	unsigned int rid = rdev_get_id(dev);
+	int rid = rdev_get_id(dev);
 
 	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
 		return -EINVAL;
@@ -82,7 +82,7 @@ static int tps65217_pmic_enable(struct r
 static int tps65217_pmic_disable(struct regulator_dev *dev)
 {
 	struct tps65217 *tps = rdev_get_drvdata(dev);
-	unsigned int rid = rdev_get_id(dev);
+	int rid = rdev_get_id(dev);
 
 	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/tps65218-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/tps65218-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/tps65218-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/tps65218-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,8 +29,8 @@
 
 enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
 
-#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \
-			    _lr, _nlr, _delay)			\
+#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, \
+			    _lr, _nlr, _delay, _fuv)		\
 	{							\
 		.name			= _name,		\
 		.id			= _id,			\
@@ -42,14 +42,15 @@ enum tps65218_regulators { DCDC1, DCDC2,
 		.vsel_mask		= _vm,			\
 		.enable_reg		= _er,			\
 		.enable_mask		= _em,			\
-		.volt_table		= _t,			\
+		.volt_table		= NULL,			\
 		.linear_ranges		= _lr,			\
 		.n_linear_ranges	= _nlr,			\
 		.ramp_delay		= _delay,		\
+		.fixed_uV		= _fuv			\
 	}							\
 
 #define TPS65218_INFO(_id, _nm, _min, _max)	\
-	{						\
+	[_id] = {					\
 		.id		= _id,			\
 		.name		= _nm,			\
 		.min_uV		= _min,			\
@@ -68,17 +69,17 @@ static const struct regulator_linear_ran
 
 static const struct regulator_linear_range dcdc4_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
-	REGULATOR_LINEAR_RANGE(1550000, 0x10, 0x34, 50000),
+	REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000),
 };
 
 static struct tps_info tps65218_pmic_regs[] = {
-	TPS65218_INFO(0, "DCDC1", 850000, 167500),
-	TPS65218_INFO(1, "DCDC2", 850000, 1675000),
-	TPS65218_INFO(2, "DCDC3", 900000, 3400000),
-	TPS65218_INFO(3, "DCDC4", 1175000, 3400000),
-	TPS65218_INFO(4, "DCDC5", 1000000, 1000000),
-	TPS65218_INFO(5, "DCDC6", 1800000, 1800000),
-	TPS65218_INFO(6, "LDO1", 900000, 3400000),
+	TPS65218_INFO(DCDC1, "DCDC1", 850000, 167500),
+	TPS65218_INFO(DCDC2, "DCDC2", 850000, 1675000),
+	TPS65218_INFO(DCDC3, "DCDC3", 900000, 3400000),
+	TPS65218_INFO(DCDC4, "DCDC4", 1175000, 3400000),
+	TPS65218_INFO(DCDC5, "DCDC5", 1000000, 1000000),
+	TPS65218_INFO(DCDC6, "DCDC6", 1800000, 1800000),
+	TPS65218_INFO(LDO1, "LDO1", 900000, 3400000),
 };
 
 #define TPS65218_OF_MATCH(comp, label) \
@@ -127,7 +128,7 @@ static int tps65218_pmic_set_voltage_sel
 static int tps65218_pmic_enable(struct regulator_dev *dev)
 {
 	struct tps65218 *tps = rdev_get_drvdata(dev);
-	unsigned int rid = rdev_get_id(dev);
+	int rid = rdev_get_id(dev);
 
 	if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
 		return -EINVAL;
@@ -141,7 +142,7 @@ static int tps65218_pmic_enable(struct r
 static int tps65218_pmic_disable(struct regulator_dev *dev)
 {
 	struct tps65218 *tps = rdev_get_drvdata(dev);
-	unsigned int rid = rdev_get_id(dev);
+	int rid = rdev_get_id(dev);
 
 	if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
 		return -EINVAL;
@@ -185,34 +186,33 @@ static const struct regulator_desc regul
 	TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64,
 			   TPS65218_REG_CONTROL_DCDC1,
 			   TPS65218_CONTROL_DCDC1_MASK,
-			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL,
-			   dcdc1_dcdc2_ranges, 2, 4000),
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN,
+			   dcdc1_dcdc2_ranges, 2, 4000, 0),
 	TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
 			   TPS65218_REG_CONTROL_DCDC2,
 			   TPS65218_CONTROL_DCDC2_MASK,
-			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL,
-			   dcdc1_dcdc2_ranges, 2, 4000),
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN,
+			   dcdc1_dcdc2_ranges, 2, 4000, 0),
 	TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
 			   64, TPS65218_REG_CONTROL_DCDC3,
 			   TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
-			   TPS65218_ENABLE1_DC3_EN, NULL,
-			   ldo1_dcdc3_ranges, 2, 0),
+			   TPS65218_ENABLE1_DC3_EN, ldo1_dcdc3_ranges, 2, 0, 0),
 	TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
 			   53, TPS65218_REG_CONTROL_DCDC4,
 			   TPS65218_CONTROL_DCDC4_MASK,
-			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL,
-			   dcdc4_ranges, 2, 0),
+			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN,
+			   dcdc4_ranges, 2, 0, 0),
 	TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
 			   1, -1, -1, TPS65218_REG_ENABLE1,
-			   TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0, 0),
+			   TPS65218_ENABLE1_DC5_EN, NULL, 0, 0, 1000000),
 	TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
 			   1, -1, -1, TPS65218_REG_ENABLE1,
-			   TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0, 0),
+			   TPS65218_ENABLE1_DC6_EN, NULL, 0, 0, 1800000),
 	TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
 			   TPS65218_REG_CONTROL_LDO1,
 			   TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
-			   TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges,
-			   2, 0),
+			   TPS65218_ENABLE2_LDO1_EN, ldo1_dcdc3_ranges,
+			   2, 0, 0),
 };
 
 static int tps65218_regulator_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/tps6586x-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/tps6586x-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/tps6586x-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/tps6586x-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -74,6 +74,16 @@ static struct regulator_ops tps6586x_rw_
 	.disable = regulator_disable_regmap,
 };
 
+static struct regulator_ops tps6586x_rw_linear_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+};
+
 static struct regulator_ops tps6586x_ro_regulator_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.map_voltage = regulator_map_voltage_ascend,
@@ -91,48 +101,11 @@ static const unsigned int tps6586x_ldo0_
 	1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 };
 
-static const unsigned int tps6586x_ldo4_voltages[] = {
-	1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
-	1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
-	2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
-	2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
-};
-
-#define tps658623_sm2_voltages tps6586x_ldo4_voltages
-
 static const unsigned int tps6586x_ldo_voltages[] = {
 	1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 };
 
-static const unsigned int tps6586x_sm2_voltages[] = {
-	3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
-	3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
-	3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
-	4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
-};
-
-static int tps658640_sm2_voltages[] = {
-	2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000,
-	2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000,
-	2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000,
-	3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000,
-};
-
-static const unsigned int tps658643_sm2_voltages[] = {
-	1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
-	1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
-	1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000,
-	1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,
-};
-
-static const unsigned int tps6586x_dvm_voltages[] = {
-	 725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
-	 925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
-	1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
-	1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
-};
-
-static int tps658640_rtc_voltages[] = {
+static const unsigned int tps658640_rtc_voltages[] = {
 	2500000, 2850000, 3100000, 3300000,
 };
 
@@ -159,6 +132,31 @@ static int tps658640_rtc_voltages[] = {
 	.enable_reg[1]	= TPS6586X_SUPPLY##ereg1,			\
 	.enable_bit[1]	= (ebit1),
 
+#define TPS6586X_REGULATOR_LINEAR(_id, _ops, _pin_name, n_volt, min_uv,	\
+				  uv_step, vreg, shift, nbits, ereg0,	\
+				  ebit0, ereg1, ebit1, goreg, gobit)	\
+	.desc	= {							\
+		.supply_name = _pin_name,				\
+		.name	= "REG-" #_id,					\
+		.ops	= &tps6586x_## _ops ## _regulator_ops,		\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= TPS6586X_ID_##_id,				\
+		.n_voltages = n_volt,					\
+		.min_uV = min_uv,					\
+		.uV_step = uv_step,					\
+		.owner	= THIS_MODULE,					\
+		.enable_reg = TPS6586X_SUPPLY##ereg0,			\
+		.enable_mask = 1 << (ebit0),				\
+		.vsel_reg = TPS6586X_##vreg,				\
+		.vsel_mask = ((1 << (nbits)) - 1) << (shift),		\
+		.apply_reg = (goreg),				\
+		.apply_bit = (gobit),				\
+	},								\
+	.enable_reg[0]	= TPS6586X_SUPPLY##ereg0,			\
+	.enable_bit[0]	= (ebit0),					\
+	.enable_reg[1]	= TPS6586X_SUPPLY##ereg1,			\
+	.enable_bit[1]	= (ebit1),
+
 #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,		\
 		     ereg0, ebit0, ereg1, ebit1)			\
 {									\
@@ -166,6 +164,14 @@ static int tps658640_rtc_voltages[] = {
 			   ereg0, ebit0, ereg1, ebit1, 0, 0)		\
 }
 
+#define TPS6586X_LDO_LINEAR(_id, _pname, n_volt, min_uv, uv_step, vreg,	\
+			    shift, nbits, ereg0, ebit0, ereg1, ebit1)	\
+{									\
+	TPS6586X_REGULATOR_LINEAR(_id, rw_linear, _pname, n_volt,	\
+				  min_uv, uv_step, vreg, shift, nbits,	\
+				  ereg0, ebit0, ereg1, ebit1, 0, 0)	\
+}
+
 #define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits,	\
 			  ereg0, ebit0, ereg1, ebit1)			\
 {									\
@@ -173,11 +179,13 @@ static int tps658640_rtc_voltages[] = {
 			   ereg0, ebit0, ereg1, ebit1, 0, 0)		\
 }
 
-#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,		\
-		     ereg0, ebit0, ereg1, ebit1, goreg, gobit)		\
+#define TPS6586X_DVM(_id, _pname, n_volt, min_uv, uv_step, vreg, shift,	\
+		     nbits, ereg0, ebit0, ereg1, ebit1, goreg, gobit)	\
 {									\
-	TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits,	\
-			   ereg0, ebit0, ereg1, ebit1, goreg, gobit)	\
+	TPS6586X_REGULATOR_LINEAR(_id, rw_linear, _pname, n_volt,	\
+				  min_uv, uv_step, vreg, shift, nbits,	\
+				  ereg0, ebit0, ereg1, ebit1, goreg,	\
+				  gobit)				\
 }
 
 #define TPS6586X_SYS_REGULATOR()					\
@@ -210,24 +218,23 @@ static struct tps6586x_regulator tps6586
 					ENE, 7),
 	TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7,
 					V4, 7),
-	TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1,
-					END, 1),
-	TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7,
-					END, 7),
-
-	TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3,
-					ENB, 3, TPS6586X_VCC2, BIT(6)),
-	TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3,
-					END, 3, TPS6586X_VCC1, BIT(6)),
-	TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1,
-					ENB, 1, TPS6586X_VCC1, BIT(2)),
-	TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0,
-					ENB, 0, TPS6586X_VCC1, BIT(0)),
+	TPS6586X_LDO_LINEAR(LDO_1, "vinldo01", 32, 725000, 25000, SUPPLYV1,
+			    0, 5, ENC, 1, END, 1),
+	TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 3000000, 50000, SUPPLYV2,
+			    0, 5, ENC, 7, END, 7),
+	TPS6586X_DVM(LDO_2, "vinldo23", 32, 725000, 25000, LDO2BV1, 0, 5,
+		     ENA, 3, ENB, 3, TPS6586X_VCC2, BIT(6)),
+	TPS6586X_DVM(LDO_4, "vinldo4", 32, 1700000, 25000, LDO4V1, 0, 5,
+		     ENC, 3, END, 3, TPS6586X_VCC1, BIT(6)),
+	TPS6586X_DVM(SM_0, "vin-sm0", 32, 725000, 25000, SM0V1, 0, 5,
+		     ENA, 1, ENB, 1, TPS6586X_VCC1, BIT(2)),
+	TPS6586X_DVM(SM_1, "vin-sm1", 32, 725000, 25000, SM1V1, 0, 5,
+		     ENA, 0, ENB, 0, TPS6586X_VCC1, BIT(0)),
 };
 
 static struct tps6586x_regulator tps658623_regulator[] = {
-	TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7,
-					END, 7),
+	TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 1700000, 25000, SUPPLYV2,
+			    0, 5, ENC, 7, END, 7),
 };
 
 static struct tps6586x_regulator tps658640_regulator[] = {
@@ -243,16 +250,16 @@ static struct tps6586x_regulator tps6586
 					ENC, 6, END, 6),
 	TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3,
 					ENE, 7, ENE, 7),
-	TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5,
-					ENC, 7, END, 7),
+	TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 2150000, 50000, SUPPLYV2,
+			    0, 5, ENC, 7, END, 7),
 
 	TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2,
 					V4, 7, V4, 7),
 };
 
 static struct tps6586x_regulator tps658643_regulator[] = {
-	TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
-					END, 7),
+	TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 1025000, 25000, SUPPLYV2,
+			    0, 5, ENC, 7, END, 7),
 };
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/tps65910-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/tps65910-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/tps65910-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/tps65910-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -1014,7 +1014,7 @@ static struct tps65910_board *tps65910_p
 	if (!pmic_plat_data)
 		return NULL;
 
-	np = of_node_get(pdev->dev.parent->of_node);
+	np = pdev->dev.parent->of_node;
 	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
 		dev_err(&pdev->dev, "regulator node not found\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/regulator/twl-regulator.c linux-libre-3.17-rc7-gnu/drivers/regulator/twl-regulator.c
--- linux-libre-3.16-gnu/drivers/regulator/twl-regulator.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/regulator/twl-regulator.c	2014-09-28 17:29:07.000000000 -0400
@@ -1128,7 +1128,7 @@ static int twlreg_probe(struct platform_
 	if (!initdata)
 		return -EINVAL;
 
-	info = kmemdup(template, sizeof(*info), GFP_KERNEL);
+	info = devm_kmemdup(&pdev->dev, template, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -1192,7 +1192,6 @@ static int twlreg_probe(struct platform_
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "can't register %s, %ld\n",
 				info->desc.name, PTR_ERR(rdev));
-		kfree(info);
 		return PTR_ERR(rdev);
 	}
 	platform_set_drvdata(pdev, rdev);
@@ -1212,20 +1211,10 @@ static int twlreg_probe(struct platform_
 	return 0;
 }
 
-static int twlreg_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-	struct twlreg_info *info = rdev->reg_data;
-
-	kfree(info);
-	return 0;
-}
-
 MODULE_ALIAS("platform:twl_reg");
 
 static struct platform_driver twlreg_driver = {
 	.probe		= twlreg_probe,
-	.remove		= twlreg_remove,
 	/* NOTE: short name, to work around driver model truncation of
 	 * "twl_regulator.12" (and friends) to "twl_regulator.1".
 	 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/class.c linux-libre-3.17-rc7-gnu/drivers/rtc/class.c
--- linux-libre-3.16-gnu/drivers/rtc/class.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/class.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,6 +53,7 @@ static int rtc_suspend(struct device *de
 	struct rtc_device	*rtc = to_rtc_device(dev);
 	struct rtc_time		tm;
 	struct timespec		delta, delta_delta;
+	int err;
 
 	if (has_persistent_clock())
 		return 0;
@@ -61,7 +62,12 @@ static int rtc_suspend(struct device *de
 		return 0;
 
 	/* snapshot the current RTC and system time at suspend*/
-	rtc_read_time(rtc, &tm);
+	err = rtc_read_time(rtc, &tm);
+	if (err < 0) {
+		pr_debug("%s:  fail to read rtc time\n", dev_name(&rtc->dev));
+		return 0;
+	}
+
 	getnstimeofday(&old_system);
 	rtc_tm_to_time(&tm, &old_rtc.tv_sec);
 
@@ -94,6 +100,7 @@ static int rtc_resume(struct device *dev
 	struct rtc_time		tm;
 	struct timespec		new_system, new_rtc;
 	struct timespec		sleep_time;
+	int err;
 
 	if (has_persistent_clock())
 		return 0;
@@ -104,7 +111,12 @@ static int rtc_resume(struct device *dev
 
 	/* snapshot the current rtc and system time at resume */
 	getnstimeofday(&new_system);
-	rtc_read_time(rtc, &tm);
+	err = rtc_read_time(rtc, &tm);
+	if (err < 0) {
+		pr_debug("%s:  fail to read rtc time\n", dev_name(&rtc->dev));
+		return 0;
+	}
+
 	if (rtc_valid_tm(&tm) != 0) {
 		pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
 		return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/interface.c linux-libre-3.17-rc7-gnu/drivers/rtc/interface.c
--- linux-libre-3.16-gnu/drivers/rtc/interface.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/interface.c	2014-09-28 17:29:07.000000000 -0400
@@ -348,6 +348,8 @@ static int __rtc_set_alarm(struct rtc_de
 
 	/* Make sure we're not setting alarms in the past */
 	err = __rtc_read_time(rtc, &tm);
+	if (err)
+		return err;
 	rtc_tm_to_time(&tm, &now);
 	if (scheduled <= now)
 		return -ETIME;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/Kconfig linux-libre-3.17-rc7-gnu/drivers/rtc/Kconfig
--- linux-libre-3.16-gnu/drivers/rtc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -373,6 +373,14 @@ config RTC_DRV_PCF8563
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8563.
 
+config RTC_DRV_PCF85063
+	tristate "nxp PCF85063"
+	help
+	  If you say yes here you get support for the PCF85063 RTC chip
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf85063.
+
 config RTC_DRV_PCF8583
 	tristate "Philips PCF8583"
 	help
@@ -760,6 +768,15 @@ config RTC_DRV_DS1742
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1742.
 
+config RTC_DRV_DS2404
+	tristate "Maxim/Dallas DS2404"
+	help
+	  If you say yes here you get support for the
+	  Dallas DS2404 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds2404.
+
 config RTC_DRV_DA9052
 	tristate "Dialog DA9052/DA9053 RTC"
 	depends on PMIC_DA9052
@@ -789,7 +806,7 @@ config RTC_DRV_DA9063
 
 config RTC_DRV_EFI
 	tristate "EFI RTC"
-	depends on IA64
+	depends on EFI
 	help
 	  If you say yes here you will get support for the EFI
 	  Real Time Clock.
@@ -873,15 +890,6 @@ config RTC_DRV_V3020
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-v3020.
 
-config RTC_DRV_DS2404
-	tristate "Dallas DS2404"
-	help
-	  If you say yes here you get support for the
-	  Dallas DS2404 RTC chip.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-ds2404.
-
 config RTC_DRV_WM831X
 	tristate "Wolfson Microelectronics WM831x RTC"
 	depends on MFD_WM831X
@@ -1349,6 +1357,7 @@ config RTC_DRV_SIRFSOC
 
 config RTC_DRV_MOXART
 	tristate "MOXA ART RTC"
+	depends on ARCH_MOXART || COMPILE_TEST
 	help
 	   If you say yes here you get support for the MOXA ART
 	   RTC module.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/Makefile linux-libre-3.17-rc7-gnu/drivers/rtc/Makefile
--- linux-libre-3.16-gnu/drivers/rtc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC)	+= systohc.o
 obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o
 rtc-core-y			:= class.o interface.o
 
+ifdef CONFIG_RTC_DRV_EFI
+rtc-core-y			+= rtc-efi-platform.o
+endif
+
 rtc-core-$(CONFIG_RTC_INTF_DEV)	+= rtc-dev.o
 rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
 rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
@@ -93,6 +97,7 @@ obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o
 obj-$(CONFIG_RTC_DRV_PCF2127)	+= rtc-pcf2127.o
 obj-$(CONFIG_RTC_DRV_PCF8523)	+= rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_PCF85063)	+= rtc-pcf85063.o
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o
 obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-au1xxx.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-au1xxx.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-au1xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-au1xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@ static int au1xtoy_rtc_read_time(struct
 {
 	unsigned long t;
 
-	t = au_readl(SYS_TOYREAD);
+	t = alchemy_rdsys(AU1000_SYS_TOYREAD);
 
 	rtc_time_to_tm(t, tm);
 
@@ -45,13 +45,12 @@ static int au1xtoy_rtc_set_time(struct d
 
 	rtc_tm_to_time(tm, &t);
 
-	au_writel(t, SYS_TOYWRITE);
-	au_sync();
+	alchemy_wrsys(t, AU1000_SYS_TOYWRITE);
 
 	/* wait for the pending register write to succeed.  This can
 	 * take up to 6 seconds...
 	 */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
 		msleep(1);
 
 	return 0;
@@ -68,7 +67,7 @@ static int au1xtoy_rtc_probe(struct plat
 	unsigned long t;
 	int ret;
 
-	t = au_readl(SYS_COUNTER_CNTRL);
+	t = alchemy_rdsys(AU1000_SYS_CNTRCTRL);
 	if (!(t & CNTR_OK)) {
 		dev_err(&pdev->dev, "counters not working; aborting.\n");
 		ret = -ENODEV;
@@ -78,10 +77,10 @@ static int au1xtoy_rtc_probe(struct plat
 	ret = -ETIMEDOUT;
 
 	/* set counter0 tickrate to 1Hz if necessary */
-	if (au_readl(SYS_TOYTRIM) != 32767) {
+	if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) {
 		/* wait until hardware gives access to TRIM register */
 		t = 0x00100000;
-		while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t)
+		while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T0S) && --t)
 			msleep(1);
 
 		if (!t) {
@@ -93,12 +92,11 @@ static int au1xtoy_rtc_probe(struct plat
 		}
 
 		/* set 1Hz TOY tick rate */
-		au_writel(32767, SYS_TOYTRIM);
-		au_sync();
+		alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
 	}
 
 	/* wait until the hardware allows writes to the counter reg */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
 		msleep(1);
 
 	rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-da9063.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-da9063.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-da9063.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-da9063.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,8 @@
 #define YEARS_FROM_DA9063(year)		((year) + 100)
 #define MONTHS_FROM_DA9063(month)	((month) - 1)
 
+#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)
+
 #define RTC_DATA_LEN	(DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
 #define RTC_SEC		0
 #define RTC_MIN		1
@@ -42,6 +44,10 @@ struct da9063_rtc {
 	struct da9063		*hw;
 	struct rtc_time		alarm_time;
 	bool			rtc_sync;
+	int			alarm_year;
+	int			alarm_start;
+	int			alarm_len;
+	int			data_start;
 };
 
 static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
@@ -83,7 +89,7 @@ static int da9063_rtc_stop_alarm(struct
 {
 	struct da9063_rtc *rtc = dev_get_drvdata(dev);
 
-	return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+	return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
 				  DA9063_ALARM_ON, 0);
 }
 
@@ -91,7 +97,7 @@ static int da9063_rtc_start_alarm(struct
 {
 	struct da9063_rtc *rtc = dev_get_drvdata(dev);
 
-	return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+	return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
 				  DA9063_ALARM_ON, DA9063_ALARM_ON);
 }
 
@@ -151,8 +157,9 @@ static int da9063_rtc_read_alarm(struct
 	int ret;
 	unsigned int val;
 
-	ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S,
-			       &data[RTC_SEC], RTC_DATA_LEN);
+	data[RTC_SEC] = 0;
+	ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
+			       &data[rtc->data_start], rtc->alarm_len);
 	if (ret < 0)
 		return ret;
 
@@ -186,14 +193,14 @@ static int da9063_rtc_set_alarm(struct d
 		return ret;
 	}
 
-	ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S,
-				data, RTC_DATA_LEN);
+	ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
+			       &data[rtc->data_start], rtc->alarm_len);
 	if (ret < 0) {
 		dev_err(dev, "Failed to write alarm: %d\n", ret);
 		return ret;
 	}
 
-	rtc->alarm_time = alrm->time;
+	da9063_data_to_tm(data, &rtc->alarm_time);
 
 	if (alrm->enabled) {
 		ret = da9063_rtc_start_alarm(dev);
@@ -218,7 +225,7 @@ static irqreturn_t da9063_alarm_event(in
 {
 	struct da9063_rtc *rtc = data;
 
-	regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+	regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
 			   DA9063_ALARM_ON, 0);
 
 	rtc->rtc_sync = true;
@@ -257,7 +264,23 @@ static int da9063_rtc_probe(struct platf
 		goto err;
 	}
 
-	ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	if (da9063->variant_code == PMIC_DA9063_AD) {
+		rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
+		rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
+		rtc->alarm_len = RTC_ALARM_DATA_LEN;
+		rtc->data_start = RTC_MIN;
+	} else {
+		rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
+		rtc->alarm_start = DA9063_BB_REG_ALARM_S;
+		rtc->alarm_len = RTC_DATA_LEN;
+		rtc->data_start = RTC_SEC;
+	}
+
+	ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
 			DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
 			0);
 	if (ret < 0) {
@@ -265,7 +288,7 @@ static int da9063_rtc_probe(struct platf
 		goto err;
 	}
 
-	ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+	ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
 				 DA9063_ALARM_STATUS_ALARM,
 				 DA9063_ALARM_STATUS_ALARM);
 	if (ret < 0) {
@@ -273,25 +296,22 @@ static int da9063_rtc_probe(struct platf
 		goto err;
 	}
 
-	ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y,
+	ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
 				 DA9063_TICK_ON, 0);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to disable TICKs\n");
 		goto err;
 	}
 
-	ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S,
-			       data, RTC_DATA_LEN);
+	data[RTC_SEC] = 0;
+	ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
+			       &data[rtc->data_start], rtc->alarm_len);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
 			ret);
 		goto err;
 	}
 
-	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
-	if (!rtc)
-		return -ENOMEM;
-
 	platform_set_drvdata(pdev, rtc);
 
 	irq_alarm = platform_get_irq_byname(pdev, "ALARM");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-ds1343.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-ds1343.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-ds1343.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-ds1343.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
  * Real Time Clock
  *
  * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>
+ *	    Ankur Srivastava <sankurece@gmail.com> : DS1343 Nvram Support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -45,6 +46,9 @@
 #define DS1343_CONTROL_REG	0x0F
 #define DS1343_STATUS_REG	0x10
 #define DS1343_TRICKLE_REG	0x11
+#define DS1343_NVRAM		0x20
+
+#define DS1343_NVRAM_LEN	96
 
 /* DS1343 Control Registers bits */
 #define DS1343_EOSC		0x80
@@ -149,6 +153,64 @@ static ssize_t ds1343_store_glitchfilter
 static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
 			ds1343_store_glitchfilter);
 
+static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *attr,
+			char *buf, loff_t off, size_t count)
+{
+	int ret;
+	unsigned char address;
+	struct device *dev = kobj_to_dev(kobj);
+	struct ds1343_priv *priv = dev_get_drvdata(dev);
+
+	if (unlikely(!count))
+		return count;
+
+	if ((count + off) > DS1343_NVRAM_LEN)
+		count = DS1343_NVRAM_LEN - off;
+
+	address = DS1343_NVRAM + off;
+
+	ret = regmap_bulk_write(priv->map, address, buf, count);
+	if (ret < 0)
+		dev_err(&priv->spi->dev, "Error in nvram write %d", ret);
+
+	return (ret < 0) ? ret : count;
+}
+
+
+static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj,
+				struct bin_attribute *attr,
+				char *buf, loff_t off, size_t count)
+{
+	int ret;
+	unsigned char address;
+	struct device *dev = kobj_to_dev(kobj);
+	struct ds1343_priv *priv = dev_get_drvdata(dev);
+
+	if (unlikely(!count))
+		return count;
+
+	if ((count + off) > DS1343_NVRAM_LEN)
+		count = DS1343_NVRAM_LEN - off;
+
+	address = DS1343_NVRAM + off;
+
+	ret = regmap_bulk_read(priv->map, address, buf, count);
+	if (ret < 0)
+		dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret);
+
+	return (ret < 0) ? ret : count;
+}
+
+
+static struct bin_attribute nvram_attr = {
+	.attr.name	= "nvram",
+	.attr.mode	= S_IRUGO | S_IWUSR,
+	.read		= ds1343_nvram_read,
+	.write		= ds1343_nvram_write,
+	.size		= DS1343_NVRAM_LEN,
+};
+
 static ssize_t ds1343_show_alarmstatus(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -274,12 +336,16 @@ static int ds1343_sysfs_register(struct
 	if (err)
 		goto error1;
 
+	err = device_create_bin_file(dev, &nvram_attr);
+	if (err)
+		goto error2;
+
 	if (priv->irq <= 0)
 		return err;
 
 	err = device_create_file(dev, &dev_attr_alarm_mode);
 	if (err)
-		goto error2;
+		goto error3;
 
 	err = device_create_file(dev, &dev_attr_alarm_status);
 	if (!err)
@@ -287,6 +353,9 @@ static int ds1343_sysfs_register(struct
 
 	device_remove_file(dev, &dev_attr_alarm_mode);
 
+error3:
+	device_remove_bin_file(dev, &nvram_attr);
+
 error2:
 	device_remove_file(dev, &dev_attr_trickle_charger);
 
@@ -302,6 +371,7 @@ static void ds1343_sysfs_unregister(stru
 
 	device_remove_file(dev, &dev_attr_glitch_filter);
 	device_remove_file(dev, &dev_attr_trickle_charger);
+	device_remove_bin_file(dev, &nvram_attr);
 
 	if (priv->irq <= 0)
 		return;
@@ -684,6 +754,7 @@ static struct spi_driver ds1343_driver =
 module_spi_driver(ds1343_driver);
 
 MODULE_DESCRIPTION("DS1343 RTC SPI Driver");
-MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>");
+MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>,"
+		"Ankur Srivastava <sankurece@gmail.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION(DS1343_DRV_VERSION);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-ds1742.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-ds1742.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-ds1742.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-ds1742.c	2014-09-28 17:29:07.000000000 -0400
@@ -231,7 +231,7 @@ static struct platform_driver ds1742_rtc
 	.driver		= {
 		.name	= "rtc-ds1742",
 		.owner	= THIS_MODULE,
-		.of_match_table = ds1742_rtc_of_match,
+		.of_match_table = of_match_ptr(ds1742_rtc_of_match),
 	},
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-efi.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-efi.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-efi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-efi.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/stringify.h>
 #include <linux/time.h>
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
@@ -48,8 +49,8 @@ compute_wday(efi_time_t *eft)
 	int y;
 	int ndays = 0;
 
-	if (eft->year < 1998) {
-		pr_err("EFI year < 1998, invalid date\n");
+	if (eft->year < EFI_RTC_EPOCH) {
+		pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", invalid date\n");
 		return -1;
 	}
 
@@ -78,19 +79,36 @@ convert_to_efi_time(struct rtc_time *wti
 	eft->timezone	= EFI_UNSPECIFIED_TIMEZONE;
 }
 
-static void
+static bool
 convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
 {
 	memset(wtime, 0, sizeof(*wtime));
+
+	if (eft->second >= 60)
+		return false;
 	wtime->tm_sec  = eft->second;
+
+	if (eft->minute >= 60)
+		return false;
 	wtime->tm_min  = eft->minute;
+
+	if (eft->hour >= 24)
+		return false;
 	wtime->tm_hour = eft->hour;
+
+	if (!eft->day || eft->day > 31)
+		return false;
 	wtime->tm_mday = eft->day;
+
+	if (!eft->month || eft->month > 12)
+		return false;
 	wtime->tm_mon  = eft->month - 1;
 	wtime->tm_year = eft->year - 1900;
 
 	/* day of the week [0-6], Sunday=0 */
 	wtime->tm_wday = compute_wday(eft);
+	if (wtime->tm_wday < 0)
+		return false;
 
 	/* day in the year [1-365]*/
 	wtime->tm_yday = compute_yday(eft);
@@ -106,6 +124,8 @@ convert_from_efi_time(efi_time_t *eft, s
 	default:
 		wtime->tm_isdst = -1;
 	}
+
+	return true;
 }
 
 static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
@@ -122,7 +142,8 @@ static int efi_read_alarm(struct device
 	if (status != EFI_SUCCESS)
 		return -EINVAL;
 
-	convert_from_efi_time(&eft, &wkalrm->time);
+	if (!convert_from_efi_time(&eft, &wkalrm->time))
+		return -EIO;
 
 	return rtc_valid_tm(&wkalrm->time);
 }
@@ -163,7 +184,8 @@ static int efi_read_time(struct device *
 		return -EINVAL;
 	}
 
-	convert_from_efi_time(&eft, tm);
+	if (!convert_from_efi_time(&eft, tm))
+		return -EIO;
 
 	return rtc_valid_tm(tm);
 }
@@ -210,6 +232,7 @@ static struct platform_driver efi_rtc_dr
 
 module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
 
+MODULE_ALIAS("platform:rtc-efi");
 MODULE_AUTHOR("dann frazier <dannf@hp.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("EFI RTC driver");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-efi-platform.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-efi-platform.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-efi-platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-efi-platform.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * Moved from arch/ia64/kernel/time.c
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *	Stephane Eranian <eranian@hpl.hp.com>
+ *	David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ * Copyright (C) 1999-2000 VA Linux Systems
+ * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+#include <linux/platform_device.h>
+
+static struct platform_device rtc_efi_dev = {
+	.name = "rtc-efi",
+	.id = -1,
+};
+
+static int __init rtc_init(void)
+{
+	if (efi_enabled(EFI_RUNTIME_SERVICES))
+		if (platform_device_register(&rtc_efi_dev) < 0)
+			pr_err("unable to register rtc device...\n");
+
+	/* not necessarily an error */
+	return 0;
+}
+module_init(rtc_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-isl12022.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-isl12022.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-isl12022.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-isl12022.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #define DRV_VERSION "0.1"
 
@@ -271,6 +273,13 @@ static int isl12022_probe(struct i2c_cli
 	return PTR_ERR_OR_ZERO(isl12022->rtc);
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id isl12022_dt_match[] = {
+	{ .compatible = "isl,isl12022" },
+	{ },
+};
+#endif
+
 static const struct i2c_device_id isl12022_id[] = {
 	{ "isl12022", 0 },
 	{ }
@@ -280,6 +289,9 @@ MODULE_DEVICE_TABLE(i2c, isl12022_id);
 static struct i2c_driver isl12022_driver = {
 	.driver		= {
 		.name	= "rtc-isl12022",
+#ifdef CONFIG_OF
+		.of_match_table = of_match_ptr(isl12022_dt_match),
+#endif
 	},
 	.probe		= isl12022_probe,
 	.id_table	= isl12022_id,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-max77686.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-max77686.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-max77686.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-max77686.c	2014-09-28 17:29:07.000000000 -0400
@@ -492,16 +492,11 @@ static int max77686_rtc_init_reg(struct
 	return ret;
 }
 
-static struct regmap_config max77686_rtc_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
 static int max77686_rtc_probe(struct platform_device *pdev)
 {
 	struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
 	struct max77686_rtc_info *info;
-	int ret, virq;
+	int ret;
 
 	dev_info(&pdev->dev, "%s\n", __func__);
 
@@ -514,14 +509,7 @@ static int max77686_rtc_probe(struct pla
 	info->dev = &pdev->dev;
 	info->max77686 = max77686;
 	info->rtc = max77686->rtc;
-	info->max77686->rtc_regmap = devm_regmap_init_i2c(info->max77686->rtc,
-					 &max77686_rtc_regmap_config);
-	if (IS_ERR(info->max77686->rtc_regmap)) {
-		ret = PTR_ERR(info->max77686->rtc_regmap);
-		dev_err(info->max77686->dev, "Failed to allocate register map: %d\n",
-				ret);
-		return ret;
-	}
+
 	platform_set_drvdata(pdev, info);
 
 	ret = max77686_rtc_init_reg(info);
@@ -550,15 +538,16 @@ static int max77686_rtc_probe(struct pla
 			ret = -EINVAL;
 		goto err_rtc;
 	}
-	virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1);
-	if (!virq) {
+
+	info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
+					 MAX77686_RTCIRQ_RTCA1);
+	if (!info->virq) {
 		ret = -ENXIO;
 		goto err_rtc;
 	}
-	info->virq = virq;
 
-	ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
-				max77686_rtc_alarm_irq, 0, "rtc-alarm0", info);
+	ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
+				max77686_rtc_alarm_irq, 0, "rtc-alarm1", info);
 	if (ret < 0)
 		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
 			info->virq, ret);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-pcf85063.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-pcf85063.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-pcf85063.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-pcf85063.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,204 @@
+/*
+ * An I2C driver for the PCF85063 RTC
+ * Copyright 2014 Rose Technology
+ *
+ * Author: SÃ¸ren Andersen <san@rosetechnology.dk>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * based on the other drivers in this same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/module.h>
+
+#define DRV_VERSION "0.0.1"
+
+#define PCF85063_REG_CTRL1		0x00 /* status */
+#define PCF85063_REG_CTRL2		0x01
+
+#define PCF85063_REG_SC			0x04 /* datetime */
+#define PCF85063_REG_MN			0x05
+#define PCF85063_REG_HR			0x06
+#define PCF85063_REG_DM			0x07
+#define PCF85063_REG_DW			0x08
+#define PCF85063_REG_MO			0x09
+#define PCF85063_REG_YR			0x0A
+
+#define PCF85063_MO_C			0x80 /* century */
+
+static struct i2c_driver pcf85063_driver;
+
+struct pcf85063 {
+	struct rtc_device *rtc;
+	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
+	int voltage_low; /* indicates if a low_voltage was detected */
+};
+
+/*
+ * In the routines that deal directly with the pcf85063 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	struct pcf85063 *pcf85063 = i2c_get_clientdata(client);
+	unsigned char buf[13] = { PCF85063_REG_CTRL1 };
+	struct i2c_msg msgs[] = {
+		{/* setup read ptr */
+			.addr = client->addr,
+			.len = 1,
+			.buf = buf
+		},
+		{/* read status + date */
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 13,
+			.buf = buf
+		},
+	};
+
+	/* read registers */
+	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __func__);
+		return -EIO;
+	}
+
+	tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F);
+	tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F);
+	tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */
+	tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F);
+	tm->tm_wday = buf[PCF85063_REG_DW] & 0x07;
+	tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+	tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]);
+	if (tm->tm_year < 70)
+		tm->tm_year += 100;	/* assume we are in 1970...2069 */
+	/* detect the polarity heuristically. see note above. */
+	pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
+		(tm->tm_year >= 100) : (tm->tm_year < 100);
+
+	/* the clock can give out invalid datetime, but we cannot return
+	 * -EINVAL otherwise hwclock will refuse to set the time on bootup.
+	 */
+	if (rtc_valid_tm(tm) < 0)
+		dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+	return 0;
+}
+
+static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	int i = 0, err = 0;
+	unsigned char buf[11];
+
+	/* Control & status */
+	buf[PCF85063_REG_CTRL1] = 0;
+	buf[PCF85063_REG_CTRL2] = 5;
+
+	/* hours, minutes and seconds */
+	buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F;
+
+	buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min);
+	buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour);
+
+	/* Day of month, 1 - 31 */
+	buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday);
+
+	/* Day, 0 - 6 */
+	buf[PCF85063_REG_DW] = tm->tm_wday & 0x07;
+
+	/* month, 1 - 12 */
+	buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1);
+
+	/* year and century */
+	buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100);
+
+	/* write register's data */
+	for (i = 0; i < sizeof(buf); i++) {
+		unsigned char data[2] = { i, buf[i] };
+
+		err = i2c_master_send(client, data, sizeof(data));
+		if (err != sizeof(data)) {
+			dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n",
+					__func__, err, data[0], data[1]);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	return pcf85063_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	return pcf85063_set_datetime(to_i2c_client(dev), tm);
+}
+
+static const struct rtc_class_ops pcf85063_rtc_ops = {
+	.read_time	= pcf85063_rtc_read_time,
+	.set_time	= pcf85063_rtc_set_time
+};
+
+static int pcf85063_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct pcf85063 *pcf85063;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
+				GFP_KERNEL);
+	if (!pcf85063)
+		return -ENOMEM;
+
+	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+	i2c_set_clientdata(client, pcf85063);
+
+	pcf85063->rtc = devm_rtc_device_register(&client->dev,
+				pcf85063_driver.driver.name,
+				&pcf85063_rtc_ops, THIS_MODULE);
+
+	return PTR_ERR_OR_ZERO(pcf85063->rtc);
+}
+
+static const struct i2c_device_id pcf85063_id[] = {
+	{ "pcf85063", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf85063_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pcf85063_of_match[] = {
+	{ .compatible = "nxp,pcf85063" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pcf85063_of_match);
+#endif
+
+static struct i2c_driver pcf85063_driver = {
+	.driver		= {
+		.name	= "rtc-pcf85063",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcf85063_of_match),
+	},
+	.probe		= pcf85063_probe,
+	.id_table	= pcf85063_id,
+};
+
+module_i2c_driver(pcf85063_driver);
+
+MODULE_AUTHOR("SÃ¸ren Andersen <san@rosetechnology.dk>");
+MODULE_DESCRIPTION("PCF85063 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-pcf8563.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-pcf8563.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-pcf8563.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-pcf8563.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,6 +26,8 @@
 
 #define PCF8563_REG_ST1		0x00 /* status */
 #define PCF8563_REG_ST2		0x01
+#define PCF8563_BIT_AIE		(1 << 1)
+#define PCF8563_BIT_AF		(1 << 3)
 
 #define PCF8563_REG_SC		0x02 /* datetime */
 #define PCF8563_REG_MN		0x03
@@ -36,9 +38,6 @@
 #define PCF8563_REG_YR		0x08
 
 #define PCF8563_REG_AMN		0x09 /* alarm */
-#define PCF8563_REG_AHR		0x0A
-#define PCF8563_REG_ADM		0x0B
-#define PCF8563_REG_ADW		0x0C
 
 #define PCF8563_REG_CLKO	0x0D /* clock out */
 #define PCF8563_REG_TMRC	0x0E /* timer control */
@@ -67,37 +66,133 @@ struct pcf8563 {
 	 */
 	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
 	int voltage_low; /* incicates if a low_voltage was detected */
+
+	struct i2c_client *client;
 };
 
-/*
- * In the routines that deal directly with the pcf8563 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- */
-static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
+				   unsigned char length, unsigned char *buf)
 {
-	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
-	unsigned char buf[13] = { PCF8563_REG_ST1 };
-
 	struct i2c_msg msgs[] = {
 		{/* setup read ptr */
 			.addr = client->addr,
 			.len = 1,
-			.buf = buf
+			.buf = &reg,
 		},
-		{/* read status + date */
+		{
 			.addr = client->addr,
 			.flags = I2C_M_RD,
-			.len = 13,
+			.len = length,
 			.buf = buf
 		},
 	};
 
-	/* read registers */
 	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
 		dev_err(&client->dev, "%s: read error\n", __func__);
 		return -EIO;
 	}
 
+	return 0;
+}
+
+static int pcf8563_write_block_data(struct i2c_client *client,
+				   unsigned char reg, unsigned char length,
+				   unsigned char *buf)
+{
+	int i, err;
+
+	for (i = 0; i < length; i++) {
+		unsigned char data[2] = { reg + i, buf[i] };
+
+		err = i2c_master_send(client, data, sizeof(data));
+		if (err != sizeof(data)) {
+			dev_err(&client->dev,
+				"%s: err=%d addr=%02x, data=%02x\n",
+				__func__, err, data[0], data[1]);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
+{
+	unsigned char buf[2];
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, buf + 1);
+	if (err < 0)
+		return err;
+
+	if (on)
+		buf[1] |= PCF8563_BIT_AIE;
+	else
+		buf[1] &= ~PCF8563_BIT_AIE;
+
+	buf[1] &= ~PCF8563_BIT_AF;
+	buf[0] = PCF8563_REG_ST2;
+
+	err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, buf + 1);
+	if (err < 0) {
+		dev_err(&client->dev, "%s: write error\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
+				  unsigned char *pen)
+{
+	unsigned char buf;
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+	if (err)
+		return err;
+
+	if (en)
+		*en = !!(buf & PCF8563_BIT_AIE);
+	if (pen)
+		*pen = !!(buf & PCF8563_BIT_AF);
+
+	return 0;
+}
+
+static irqreturn_t pcf8563_irq(int irq, void *dev_id)
+{
+	struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id);
+	int err;
+	char pending;
+
+	err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
+	if (err < 0)
+		return err;
+
+	if (pending) {
+		rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
+		pcf8563_set_alarm_mode(pcf8563->client, 1);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+	unsigned char buf[9];
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf);
+	if (err)
+		return err;
+
 	if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
 		pcf8563->voltage_low = 1;
 		dev_info(&client->dev,
@@ -144,7 +239,7 @@ static int pcf8563_get_datetime(struct i
 static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
 	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
-	int i, err;
+	int err;
 	unsigned char buf[9];
 
 	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
@@ -170,19 +265,10 @@ static int pcf8563_set_datetime(struct i
 
 	buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
 
-	/* write register's data */
-	for (i = 0; i < 7; i++) {
-		unsigned char data[2] = { PCF8563_REG_SC + i,
-						buf[PCF8563_REG_SC + i] };
-
-		err = i2c_master_send(client, data, sizeof(data));
-		if (err != sizeof(data)) {
-			dev_err(&client->dev,
-				"%s: err=%d addr=%02x, data=%02x\n",
-				__func__, err, data[0], data[1]);
-			return -EIO;
-		}
-	}
+	err = pcf8563_write_block_data(client, PCF8563_REG_SC,
+				9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
+	if (err)
+		return err;
 
 	return 0;
 }
@@ -235,16 +321,83 @@ static int pcf8563_rtc_set_time(struct d
 	return pcf8563_set_datetime(to_i2c_client(dev), tm);
 }
 
+static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char buf[4];
+	int err;
+
+	err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf);
+	if (err)
+		return err;
+
+	dev_dbg(&client->dev,
+		"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
+		__func__, buf[0], buf[1], buf[2], buf[3]);
+
+	tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
+	tm->time.tm_hour = bcd2bin(buf[1] & 0x7F);
+	tm->time.tm_mday = bcd2bin(buf[2] & 0x1F);
+	tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
+	tm->time.tm_mon = -1;
+	tm->time.tm_year = -1;
+	tm->time.tm_yday = -1;
+	tm->time.tm_isdst = -1;
+
+	err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
+	if (err < 0)
+		return err;
+
+	dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
+		" enabled=%d, pending=%d\n", __func__, tm->time.tm_min,
+		tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
+		tm->enabled, tm->pending);
+
+	return 0;
+}
+
+static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char buf[4];
+	int err;
+
+	dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d "
+		"enabled=%d pending=%d\n", __func__,
+		tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday,
+		tm->time.tm_mday, tm->enabled, tm->pending);
+
+	buf[0] = bin2bcd(tm->time.tm_min);
+	buf[1] = bin2bcd(tm->time.tm_hour);
+	buf[2] = bin2bcd(tm->time.tm_mday);
+	buf[3] = tm->time.tm_wday & 0x07;
+
+	err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
+	if (err)
+		return err;
+
+	return pcf8563_set_alarm_mode(client, 1);
+}
+
+static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
+{
+	return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
+}
+
 static const struct rtc_class_ops pcf8563_rtc_ops = {
 	.ioctl		= pcf8563_rtc_ioctl,
 	.read_time	= pcf8563_rtc_read_time,
 	.set_time	= pcf8563_rtc_set_time,
+	.read_alarm	= pcf8563_rtc_read_alarm,
+	.set_alarm	= pcf8563_rtc_set_alarm,
+	.alarm_irq_enable = pcf8563_irq_enable,
 };
 
 static int pcf8563_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct pcf8563 *pcf8563;
+	int err;
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
@@ -259,12 +412,30 @@ static int pcf8563_probe(struct i2c_clie
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
 	i2c_set_clientdata(client, pcf8563);
+	pcf8563->client = client;
+	device_set_wakeup_capable(&client->dev, 1);
 
 	pcf8563->rtc = devm_rtc_device_register(&client->dev,
 				pcf8563_driver.driver.name,
 				&pcf8563_rtc_ops, THIS_MODULE);
 
-	return PTR_ERR_OR_ZERO(pcf8563->rtc);
+	if (IS_ERR(pcf8563->rtc))
+		return PTR_ERR(pcf8563->rtc);
+
+	if (client->irq > 0) {
+		err = devm_request_threaded_irq(&client->dev, client->irq,
+				NULL, pcf8563_irq,
+				IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING,
+				pcf8563->rtc->name, client);
+		if (err) {
+			dev_err(&client->dev, "unable to request IRQ %d\n",
+								client->irq);
+			return err;
+		}
+
+	}
+
+	return 0;
 }
 
 static const struct i2c_device_id pcf8563_id[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-s5m.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-s5m.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-s5m.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-s5m.c	2014-09-28 17:29:07.000000000 -0400
@@ -717,12 +717,14 @@ static int s5m_rtc_probe(struct platform
 	info->device_type = s5m87xx->device_type;
 	info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
-	info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
-	if (info->irq <= 0) {
-		ret = -EINVAL;
-		dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
+	if (s5m87xx->irq_data) {
+		info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
+		if (info->irq <= 0) {
+			ret = -EINVAL;
+			dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
 				alarm_irq);
-		goto err;
+			goto err;
+		}
 	}
 
 	platform_set_drvdata(pdev, info);
@@ -744,6 +746,11 @@ static int s5m_rtc_probe(struct platform
 		goto err;
 	}
 
+	if (!info->irq) {
+		dev_info(&pdev->dev, "Alarm IRQ not available\n");
+		return 0;
+	}
+
 	ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
 					s5m_rtc_alarm_irq, 0, "rtc-alarm0",
 					info);
@@ -802,7 +809,7 @@ static int s5m_rtc_resume(struct device
 	struct s5m_rtc_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (device_may_wakeup(dev))
+	if (info->irq && device_may_wakeup(dev))
 		ret = disable_irq_wake(info->irq);
 
 	return ret;
@@ -813,7 +820,7 @@ static int s5m_rtc_suspend(struct device
 	struct s5m_rtc_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (device_may_wakeup(dev))
+	if (info->irq && device_may_wakeup(dev))
 		ret = enable_irq_wake(info->irq);
 
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/rtc/rtc-tps65910.c linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-tps65910.c
--- linux-libre-3.16-gnu/drivers/rtc/rtc-tps65910.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/rtc/rtc-tps65910.c	2014-09-28 17:29:07.000000000 -0400
@@ -258,6 +258,8 @@ static int tps65910_rtc_probe(struct pla
 	if (ret < 0)
 		return ret;
 
+	platform_set_drvdata(pdev, tps_rtc);
+
 	irq  = platform_get_irq(pdev, 0);
 	if (irq <= 0) {
 		dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
@@ -283,8 +285,6 @@ static int tps65910_rtc_probe(struct pla
 		return ret;
 	}
 
-	platform_set_drvdata(pdev, tps_rtc);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/block/dasd.c linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd.c
--- linux-libre-3.16-gnu/drivers/s390/block/dasd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,10 @@
  * SECTION: exported variables of dasd.c
  */
 debug_info_t *dasd_debug_area;
+EXPORT_SYMBOL(dasd_debug_area);
 static struct dentry *dasd_debugfs_root_entry;
 struct dasd_discipline *dasd_diag_discipline_pointer;
+EXPORT_SYMBOL(dasd_diag_discipline_pointer);
 void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
 MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
@@ -164,6 +166,7 @@ struct dasd_block *dasd_alloc_block(void
 
 	return block;
 }
+EXPORT_SYMBOL_GPL(dasd_alloc_block);
 
 /*
  * Free memory of a device structure.
@@ -172,6 +175,7 @@ void dasd_free_block(struct dasd_block *
 {
 	kfree(block);
 }
+EXPORT_SYMBOL_GPL(dasd_free_block);
 
 /*
  * Make a new device known to the system.
@@ -281,10 +285,15 @@ static int dasd_state_basic_to_known(str
 {
 	int rc;
 
+	if (device->discipline->basic_to_known) {
+		rc = device->discipline->basic_to_known(device);
+		if (rc)
+			return rc;
+	}
+
 	if (device->block) {
 		dasd_profile_exit(&device->block->profile);
-		if (device->block->debugfs_dentry)
-			debugfs_remove(device->block->debugfs_dentry);
+		debugfs_remove(device->block->debugfs_dentry);
 		dasd_gendisk_free(device->block);
 		dasd_block_clear_timer(device->block);
 	}
@@ -293,9 +302,7 @@ static int dasd_state_basic_to_known(str
 		return rc;
 	dasd_device_clear_timer(device);
 	dasd_profile_exit(&device->profile);
-	if (device->debugfs_dentry)
-		debugfs_remove(device->debugfs_dentry);
-
+	debugfs_remove(device->debugfs_dentry);
 	DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
 	if (device->debug_area != NULL) {
 		debug_unregister(device->debug_area);
@@ -374,11 +381,6 @@ static int dasd_state_ready_to_basic(str
 {
 	int rc;
 
-	if (device->discipline->ready_to_basic) {
-		rc = device->discipline->ready_to_basic(device);
-		if (rc)
-			return rc;
-	}
 	device->state = DASD_STATE_BASIC;
 	if (device->block) {
 		struct dasd_block *block = device->block;
@@ -579,6 +581,7 @@ void dasd_kick_device(struct dasd_device
 	/* queue call to dasd_kick_device to the kernel event daemon. */
 	schedule_work(&device->kick_work);
 }
+EXPORT_SYMBOL(dasd_kick_device);
 
 /*
  * dasd_reload_device will schedule a call do do_reload_device to the kernel
@@ -639,6 +642,7 @@ void dasd_set_target_state(struct dasd_d
 	mutex_unlock(&device->state_mutex);
 	dasd_put_device(device);
 }
+EXPORT_SYMBOL(dasd_set_target_state);
 
 /*
  * Enable devices with device numbers in [from..to].
@@ -661,6 +665,7 @@ void dasd_enable_device(struct dasd_devi
 	if (device->discipline->kick_validate)
 		device->discipline->kick_validate(device);
 }
+EXPORT_SYMBOL(dasd_enable_device);
 
 /*
  * SECTION: device operation (interrupt handler, start i/o, term i/o ...)
@@ -972,37 +977,37 @@ static void dasd_stats_seq_print(struct
 	seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
 	seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
 	seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
-	seq_printf(m, "histogram_sectors ");
+	seq_puts(m, "histogram_sectors ");
 	dasd_stats_array(m, data->dasd_io_secs);
-	seq_printf(m, "histogram_io_times ");
+	seq_puts(m, "histogram_io_times ");
 	dasd_stats_array(m, data->dasd_io_times);
-	seq_printf(m, "histogram_io_times_weighted ");
+	seq_puts(m, "histogram_io_times_weighted ");
 	dasd_stats_array(m, data->dasd_io_timps);
-	seq_printf(m, "histogram_time_build_to_ssch ");
+	seq_puts(m, "histogram_time_build_to_ssch ");
 	dasd_stats_array(m, data->dasd_io_time1);
-	seq_printf(m, "histogram_time_ssch_to_irq ");
+	seq_puts(m, "histogram_time_ssch_to_irq ");
 	dasd_stats_array(m, data->dasd_io_time2);
-	seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+	seq_puts(m, "histogram_time_ssch_to_irq_weighted ");
 	dasd_stats_array(m, data->dasd_io_time2ps);
-	seq_printf(m, "histogram_time_irq_to_end ");
+	seq_puts(m, "histogram_time_irq_to_end ");
 	dasd_stats_array(m, data->dasd_io_time3);
-	seq_printf(m, "histogram_ccw_queue_length ");
+	seq_puts(m, "histogram_ccw_queue_length ");
 	dasd_stats_array(m, data->dasd_io_nr_req);
 	seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
 	seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
 	seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
 	seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
-	seq_printf(m, "histogram_read_sectors ");
+	seq_puts(m, "histogram_read_sectors ");
 	dasd_stats_array(m, data->dasd_read_secs);
-	seq_printf(m, "histogram_read_times ");
+	seq_puts(m, "histogram_read_times ");
 	dasd_stats_array(m, data->dasd_read_times);
-	seq_printf(m, "histogram_read_time_build_to_ssch ");
+	seq_puts(m, "histogram_read_time_build_to_ssch ");
 	dasd_stats_array(m, data->dasd_read_time1);
-	seq_printf(m, "histogram_read_time_ssch_to_irq ");
+	seq_puts(m, "histogram_read_time_ssch_to_irq ");
 	dasd_stats_array(m, data->dasd_read_time2);
-	seq_printf(m, "histogram_read_time_irq_to_end ");
+	seq_puts(m, "histogram_read_time_irq_to_end ");
 	dasd_stats_array(m, data->dasd_read_time3);
-	seq_printf(m, "histogram_read_ccw_queue_length ");
+	seq_puts(m, "histogram_read_ccw_queue_length ");
 	dasd_stats_array(m, data->dasd_read_nr_req);
 }
 
@@ -1016,7 +1021,7 @@ static int dasd_stats_show(struct seq_fi
 	data = profile->data;
 	if (!data) {
 		spin_unlock_bh(&profile->lock);
-		seq_printf(m, "disabled\n");
+		seq_puts(m, "disabled\n");
 		return 0;
 	}
 	dasd_stats_seq_print(m, data);
@@ -1069,7 +1074,7 @@ static ssize_t dasd_stats_global_write(s
 static int dasd_stats_global_show(struct seq_file *m, void *v)
 {
 	if (!dasd_global_profile_level) {
-		seq_printf(m, "disabled\n");
+		seq_puts(m, "disabled\n");
 		return 0;
 	}
 	dasd_stats_seq_print(m, &dasd_global_profile_data);
@@ -1111,23 +1116,17 @@ static void dasd_profile_init(struct das
 static void dasd_profile_exit(struct dasd_profile *profile)
 {
 	dasd_profile_off(profile);
-	if (profile->dentry) {
-		debugfs_remove(profile->dentry);
-		profile->dentry = NULL;
-	}
+	debugfs_remove(profile->dentry);
+	profile->dentry = NULL;
 }
 
 static void dasd_statistics_removeroot(void)
 {
 	dasd_global_profile_level = DASD_PROFILE_OFF;
-	if (dasd_global_profile_dentry) {
-		debugfs_remove(dasd_global_profile_dentry);
-		dasd_global_profile_dentry = NULL;
-	}
-	if (dasd_debugfs_global_entry)
-		debugfs_remove(dasd_debugfs_global_entry);
-	if (dasd_debugfs_root_entry)
-		debugfs_remove(dasd_debugfs_root_entry);
+	debugfs_remove(dasd_global_profile_dentry);
+	dasd_global_profile_dentry = NULL;
+	debugfs_remove(dasd_debugfs_global_entry);
+	debugfs_remove(dasd_debugfs_root_entry);
 }
 
 static void dasd_statistics_createroot(void)
@@ -1178,7 +1177,7 @@ static void dasd_statistics_removeroot(v
 
 int dasd_stats_generic_show(struct seq_file *m, void *v)
 {
-	seq_printf(m, "Statistics are not activated in this kernel\n");
+	seq_puts(m, "Statistics are not activated in this kernel\n");
 	return 0;
 }
 
@@ -1243,6 +1242,7 @@ struct dasd_ccw_req *dasd_kmalloc_reques
 	dasd_get_device(device);
 	return cqr;
 }
+EXPORT_SYMBOL(dasd_kmalloc_request);
 
 struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
 					  int datasize,
@@ -1282,6 +1282,7 @@ struct dasd_ccw_req *dasd_smalloc_reques
 	dasd_get_device(device);
 	return cqr;
 }
+EXPORT_SYMBOL(dasd_smalloc_request);
 
 /*
  * Free memory of a channel program. This function needs to free all the
@@ -1304,6 +1305,7 @@ void dasd_kfree_request(struct dasd_ccw_
 	kfree(cqr);
 	dasd_put_device(device);
 }
+EXPORT_SYMBOL(dasd_kfree_request);
 
 void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
 {
@@ -1314,6 +1316,7 @@ void dasd_sfree_request(struct dasd_ccw_
 	spin_unlock_irqrestore(&device->mem_lock, flags);
 	dasd_put_device(device);
 }
+EXPORT_SYMBOL(dasd_sfree_request);
 
 /*
  * Check discipline magic in cqr.
@@ -1391,6 +1394,7 @@ int dasd_term_IO(struct dasd_ccw_req *cq
 	dasd_schedule_device_bh(device);
 	return rc;
 }
+EXPORT_SYMBOL(dasd_term_IO);
 
 /*
  * Start the i/o. This start_IO can fail if the channel is really busy.
@@ -1509,6 +1513,7 @@ int dasd_start_IO(struct dasd_ccw_req *c
 	cqr->intrc = rc;
 	return rc;
 }
+EXPORT_SYMBOL(dasd_start_IO);
 
 /*
  * Timeout function for dasd devices. This is used for different purposes
@@ -1541,6 +1546,7 @@ void dasd_device_set_timer(struct dasd_d
 	else
 		mod_timer(&device->timer, jiffies + expires);
 }
+EXPORT_SYMBOL(dasd_device_set_timer);
 
 /*
  * Clear timeout for a device.
@@ -1549,6 +1555,7 @@ void dasd_device_clear_timer(struct dasd
 {
 	del_timer(&device->timer);
 }
+EXPORT_SYMBOL(dasd_device_clear_timer);
 
 static void dasd_handle_killed_request(struct ccw_device *cdev,
 				       unsigned long intparm)
@@ -1601,6 +1608,7 @@ void dasd_generic_handle_state_change(st
 	if (device->block)
 		dasd_schedule_block_bh(device->block);
 }
+EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
 
 /*
  * Interrupt handler for "normal" ssch-io based dasd devices.
@@ -1667,8 +1675,11 @@ void dasd_int_handler(struct ccw_device
 	if (cqr->status == DASD_CQR_CLEAR_PENDING &&
 	    scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) {
 		cqr->status = DASD_CQR_CLEARED;
+		if (cqr->callback_data == DASD_SLEEPON_START_TAG)
+			cqr->callback_data = DASD_SLEEPON_END_TAG;
 		dasd_device_clear_timer(device);
 		wake_up(&dasd_flush_wq);
+		wake_up(&generic_waitq);
 		dasd_schedule_device_bh(device);
 		return;
 	}
@@ -1722,6 +1733,7 @@ void dasd_int_handler(struct ccw_device
 		dasd_device_clear_timer(device);
 	dasd_schedule_device_bh(device);
 }
+EXPORT_SYMBOL(dasd_int_handler);
 
 enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
 {
@@ -1995,6 +2007,7 @@ finished:
 	__dasd_device_process_final_queue(device, &flush_queue);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(dasd_flush_device_queue);
 
 /*
  * Acquire the device lock and process queues for the device.
@@ -2034,6 +2047,7 @@ void dasd_schedule_device_bh(struct dasd
 	dasd_get_device(device);
 	tasklet_hi_schedule(&device->tasklet);
 }
+EXPORT_SYMBOL(dasd_schedule_device_bh);
 
 void dasd_device_set_stop_bits(struct dasd_device *device, int bits)
 {
@@ -2066,6 +2080,7 @@ void dasd_add_request_head(struct dasd_c
 	dasd_schedule_device_bh(device);
 	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 }
+EXPORT_SYMBOL(dasd_add_request_head);
 
 /*
  * Queue a request to the tail of the device ccw_queue.
@@ -2084,6 +2099,7 @@ void dasd_add_request_tail(struct dasd_c
 	dasd_schedule_device_bh(device);
 	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 }
+EXPORT_SYMBOL(dasd_add_request_tail);
 
 /*
  * Wakeup helper for the 'sleep_on' functions.
@@ -2291,13 +2307,27 @@ retry:
 
 	rc = 0;
 	list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
-		if (__dasd_sleep_on_erp(cqr))
-			rc = 1;
+		/*
+		 * for alias devices simplify error recovery and
+		 * return to upper layer
+		 */
+		if (cqr->startdev != cqr->basedev &&
+		    (cqr->status == DASD_CQR_TERMINATED ||
+		     cqr->status == DASD_CQR_NEED_ERP))
+			return -EAGAIN;
+		else {
+			/* normal recovery for basedev IO */
+			if (__dasd_sleep_on_erp(cqr)) {
+				if (!cqr->status == DASD_CQR_TERMINATED &&
+				    !cqr->status == DASD_CQR_NEED_ERP)
+					break;
+				rc = 1;
+			}
+		}
 	}
 	if (rc)
 		goto retry;
 
-
 	return 0;
 }
 
@@ -2309,6 +2339,7 @@ int dasd_sleep_on(struct dasd_ccw_req *c
 {
 	return _dasd_sleep_on(cqr, 0);
 }
+EXPORT_SYMBOL(dasd_sleep_on);
 
 /*
  * Start requests from a ccw_queue and wait for their completion.
@@ -2327,6 +2358,7 @@ int dasd_sleep_on_interruptible(struct d
 {
 	return _dasd_sleep_on(cqr, 1);
 }
+EXPORT_SYMBOL(dasd_sleep_on_interruptible);
 
 /*
  * Whoa nelly now it gets really hairy. For some functions (e.g. steal lock
@@ -2401,6 +2433,7 @@ int dasd_sleep_on_immediatly(struct dasd
 
 	return rc;
 }
+EXPORT_SYMBOL(dasd_sleep_on_immediatly);
 
 /*
  * Cancels a request that was started with dasd_sleep_on_req.
@@ -2423,6 +2456,8 @@ int dasd_cancel_req(struct dasd_ccw_req
 	case DASD_CQR_QUEUED:
 		/* request was not started - just set to cleared */
 		cqr->status = DASD_CQR_CLEARED;
+		if (cqr->callback_data == DASD_SLEEPON_START_TAG)
+			cqr->callback_data = DASD_SLEEPON_END_TAG;
 		break;
 	case DASD_CQR_IN_IO:
 		/* request in IO - terminate IO and release again */
@@ -2442,6 +2477,7 @@ int dasd_cancel_req(struct dasd_ccw_req
 	dasd_schedule_device_bh(device);
 	return rc;
 }
+EXPORT_SYMBOL(dasd_cancel_req);
 
 /*
  * SECTION: Operations of the dasd_block layer.
@@ -2475,6 +2511,7 @@ void dasd_block_set_timer(struct dasd_bl
 	else
 		mod_timer(&block->timer, jiffies + expires);
 }
+EXPORT_SYMBOL(dasd_block_set_timer);
 
 /*
  * Clear timeout for a dasd_block.
@@ -2483,6 +2520,7 @@ void dasd_block_clear_timer(struct dasd_
 {
 	del_timer(&block->timer);
 }
+EXPORT_SYMBOL(dasd_block_clear_timer);
 
 /*
  * Process finished error recovery ccw.
@@ -2864,6 +2902,7 @@ void dasd_schedule_block_bh(struct dasd_
 	dasd_get_device(block->base);
 	tasklet_hi_schedule(&block->tasklet);
 }
+EXPORT_SYMBOL(dasd_schedule_block_bh);
 
 
 /*
@@ -3202,8 +3241,8 @@ static void dasd_generic_auto_online(voi
 
 	ret = ccw_device_set_online(cdev);
 	if (ret)
-		pr_warning("%s: Setting the DASD online failed with rc=%d\n",
-			   dev_name(&cdev->dev), ret);
+		pr_warn("%s: Setting the DASD online failed with rc=%d\n",
+			dev_name(&cdev->dev), ret);
 }
 
 /*
@@ -3234,6 +3273,7 @@ int dasd_generic_probe(struct ccw_device
 		async_schedule(dasd_generic_auto_online, cdev);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dasd_generic_probe);
 
 /*
  * This will one day be called from a global not_oper handler.
@@ -3276,6 +3316,7 @@ void dasd_generic_remove(struct ccw_devi
 
 	dasd_remove_sysfs_files(cdev);
 }
+EXPORT_SYMBOL_GPL(dasd_generic_remove);
 
 /*
  * Activate a device. This is called from dasd_{eckd,fba}_probe() when either
@@ -3298,9 +3339,8 @@ int dasd_generic_set_online(struct ccw_d
 	discipline = base_discipline;
 	if (device->features & DASD_FEATURE_USEDIAG) {
 	  	if (!dasd_diag_discipline_pointer) {
-			pr_warning("%s Setting the DASD online failed because "
-				   "of missing DIAG discipline\n",
-				   dev_name(&cdev->dev));
+			pr_warn("%s Setting the DASD online failed because of missing DIAG discipline\n",
+				dev_name(&cdev->dev));
 			dasd_delete_device(device);
 			return -ENODEV;
 		}
@@ -3321,9 +3361,8 @@ int dasd_generic_set_online(struct ccw_d
 	/* check_device will allocate block device if necessary */
 	rc = discipline->check_device(device);
 	if (rc) {
-		pr_warning("%s Setting the DASD online with discipline %s "
-			   "failed with rc=%i\n",
-			   dev_name(&cdev->dev), discipline->name, rc);
+		pr_warn("%s Setting the DASD online with discipline %s failed with rc=%i\n",
+			dev_name(&cdev->dev), discipline->name, rc);
 		module_put(discipline->owner);
 		module_put(base_discipline->owner);
 		dasd_delete_device(device);
@@ -3332,8 +3371,8 @@ int dasd_generic_set_online(struct ccw_d
 
 	dasd_set_target_state(device, DASD_STATE_ONLINE);
 	if (device->state <= DASD_STATE_KNOWN) {
-		pr_warning("%s Setting the DASD online failed because of a "
-			   "missing discipline\n", dev_name(&cdev->dev));
+		pr_warn("%s Setting the DASD online failed because of a missing discipline\n",
+			dev_name(&cdev->dev));
 		rc = -ENODEV;
 		dasd_set_target_state(device, DASD_STATE_NEW);
 		if (device->block)
@@ -3348,6 +3387,7 @@ int dasd_generic_set_online(struct ccw_d
 	dasd_put_device(device);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(dasd_generic_set_online);
 
 int dasd_generic_set_offline(struct ccw_device *cdev)
 {
@@ -3371,13 +3411,11 @@ int dasd_generic_set_offline(struct ccw_
 		open_count = atomic_read(&device->block->open_count);
 		if (open_count > max_count) {
 			if (open_count > 0)
-				pr_warning("%s: The DASD cannot be set offline "
-					   "with open count %i\n",
-					   dev_name(&cdev->dev), open_count);
+				pr_warn("%s: The DASD cannot be set offline with open count %i\n",
+					dev_name(&cdev->dev), open_count);
 			else
-				pr_warning("%s: The DASD cannot be set offline "
-					   "while it is in use\n",
-					   dev_name(&cdev->dev));
+				pr_warn("%s: The DASD cannot be set offline while it is in use\n",
+					dev_name(&cdev->dev));
 			clear_bit(DASD_FLAG_OFFLINE, &device->flags);
 			dasd_put_device(device);
 			return -EBUSY;
@@ -3451,6 +3489,7 @@ interrupted:
 	dasd_put_device(device);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
 
 int dasd_generic_last_path_gone(struct dasd_device *device)
 {
@@ -3492,6 +3531,10 @@ int dasd_generic_path_operational(struct
 	dasd_schedule_device_bh(device);
 	if (device->block)
 		dasd_schedule_block_bh(device->block);
+
+	if (!device->stopped)
+		wake_up(&generic_waitq);
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(dasd_generic_path_operational);
@@ -3523,6 +3566,7 @@ int dasd_generic_notify(struct ccw_devic
 	dasd_put_device(device);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dasd_generic_notify);
 
 void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
 {
@@ -3872,39 +3916,3 @@ failed:
 
 module_init(dasd_init);
 module_exit(dasd_exit);
-
-EXPORT_SYMBOL(dasd_debug_area);
-EXPORT_SYMBOL(dasd_diag_discipline_pointer);
-
-EXPORT_SYMBOL(dasd_add_request_head);
-EXPORT_SYMBOL(dasd_add_request_tail);
-EXPORT_SYMBOL(dasd_cancel_req);
-EXPORT_SYMBOL(dasd_device_clear_timer);
-EXPORT_SYMBOL(dasd_block_clear_timer);
-EXPORT_SYMBOL(dasd_enable_device);
-EXPORT_SYMBOL(dasd_int_handler);
-EXPORT_SYMBOL(dasd_kfree_request);
-EXPORT_SYMBOL(dasd_kick_device);
-EXPORT_SYMBOL(dasd_kmalloc_request);
-EXPORT_SYMBOL(dasd_schedule_device_bh);
-EXPORT_SYMBOL(dasd_schedule_block_bh);
-EXPORT_SYMBOL(dasd_set_target_state);
-EXPORT_SYMBOL(dasd_device_set_timer);
-EXPORT_SYMBOL(dasd_block_set_timer);
-EXPORT_SYMBOL(dasd_sfree_request);
-EXPORT_SYMBOL(dasd_sleep_on);
-EXPORT_SYMBOL(dasd_sleep_on_immediatly);
-EXPORT_SYMBOL(dasd_sleep_on_interruptible);
-EXPORT_SYMBOL(dasd_smalloc_request);
-EXPORT_SYMBOL(dasd_start_IO);
-EXPORT_SYMBOL(dasd_term_IO);
-
-EXPORT_SYMBOL_GPL(dasd_generic_probe);
-EXPORT_SYMBOL_GPL(dasd_generic_remove);
-EXPORT_SYMBOL_GPL(dasd_generic_notify);
-EXPORT_SYMBOL_GPL(dasd_generic_set_online);
-EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
-EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
-EXPORT_SYMBOL_GPL(dasd_flush_device_queue);
-EXPORT_SYMBOL_GPL(dasd_alloc_block);
-EXPORT_SYMBOL_GPL(dasd_free_block);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/block/dasd_devmap.c linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_devmap.c
--- linux-libre-3.16-gnu/drivers/s390/block/dasd_devmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_devmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(dasd_nofcx);
  * strings when running as a module.
  */
 static char *dasd[256];
-module_param_array(dasd, charp, NULL, 0);
+module_param_array(dasd, charp, NULL, S_IRUGO);
 
 /*
  * Single spinlock to protect devmap and servermap structures and lists.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/block/dasd_eckd.c linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_eckd.c
--- linux-libre-3.16-gnu/drivers/s390/block/dasd_eckd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_eckd.c	2014-09-28 17:29:07.000000000 -0400
@@ -2039,7 +2039,7 @@ static int dasd_eckd_online_to_ready(str
 	return 0;
 };
 
-static int dasd_eckd_ready_to_basic(struct dasd_device *device)
+static int dasd_eckd_basic_to_known(struct dasd_device *device)
 {
 	return dasd_alias_remove_device(device);
 };
@@ -2061,11 +2061,12 @@ dasd_eckd_fill_geometry(struct dasd_bloc
 
 static struct dasd_ccw_req *
 dasd_eckd_build_format(struct dasd_device *base,
-		       struct format_data_t *fdata)
+		       struct format_data_t *fdata,
+		       int enable_pav)
 {
 	struct dasd_eckd_private *base_priv;
 	struct dasd_eckd_private *start_priv;
-	struct dasd_device *startdev;
+	struct dasd_device *startdev = NULL;
 	struct dasd_ccw_req *fcp;
 	struct eckd_count *ect;
 	struct ch_t address;
@@ -2079,7 +2080,9 @@ dasd_eckd_build_format(struct dasd_devic
 	int nr_tracks;
 	int use_prefix;
 
-	startdev = dasd_alias_get_start_dev(base);
+	if (enable_pav)
+		startdev = dasd_alias_get_start_dev(base);
+
 	if (!startdev)
 		startdev = base;
 
@@ -2309,6 +2312,7 @@ dasd_eckd_build_format(struct dasd_devic
 
 	fcp->startdev = startdev;
 	fcp->memdev = startdev;
+	fcp->basedev = base;
 	fcp->retries = 256;
 	fcp->expires = startdev->default_expires * HZ;
 	fcp->buildclk = get_tod_clock();
@@ -2319,7 +2323,8 @@ dasd_eckd_build_format(struct dasd_devic
 
 static int
 dasd_eckd_format_device(struct dasd_device *base,
-			struct format_data_t *fdata)
+			struct format_data_t *fdata,
+			int enable_pav)
 {
 	struct dasd_ccw_req *cqr, *n;
 	struct dasd_block *block;
@@ -2327,7 +2332,7 @@ dasd_eckd_format_device(struct dasd_devi
 	struct list_head format_queue;
 	struct dasd_device *device;
 	int old_stop, format_step;
-	int step, rc = 0;
+	int step, rc = 0, sleep_rc;
 
 	block = base->block;
 	private = (struct dasd_eckd_private *) base->private;
@@ -2361,11 +2366,11 @@ dasd_eckd_format_device(struct dasd_devi
 	}
 
 	INIT_LIST_HEAD(&format_queue);
-	old_stop = fdata->stop_unit;
 
+	old_stop = fdata->stop_unit;
 	while (fdata->start_unit <= 1) {
 		fdata->stop_unit = fdata->start_unit;
-		cqr = dasd_eckd_build_format(base, fdata);
+		cqr = dasd_eckd_build_format(base, fdata, enable_pav);
 		list_add(&cqr->blocklist, &format_queue);
 
 		fdata->stop_unit = old_stop;
@@ -2383,7 +2388,7 @@ retry:
 		if (step > format_step)
 			fdata->stop_unit = fdata->start_unit + format_step - 1;
 
-		cqr = dasd_eckd_build_format(base, fdata);
+		cqr = dasd_eckd_build_format(base, fdata, enable_pav);
 		if (IS_ERR(cqr)) {
 			if (PTR_ERR(cqr) == -ENOMEM) {
 				/*
@@ -2403,7 +2408,7 @@ retry:
 	}
 
 sleep:
-	dasd_sleep_on_queue(&format_queue);
+	sleep_rc = dasd_sleep_on_queue(&format_queue);
 
 	list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
 		device = cqr->startdev;
@@ -2415,6 +2420,9 @@ sleep:
 		private->count--;
 	}
 
+	if (sleep_rc)
+		return sleep_rc;
+
 	/*
 	 * in case of ENOMEM we need to retry after
 	 * first requests are finished
@@ -4511,7 +4519,7 @@ static struct dasd_discipline dasd_eckd_
 	.verify_path = dasd_eckd_verify_path,
 	.basic_to_ready = dasd_eckd_basic_to_ready,
 	.online_to_ready = dasd_eckd_online_to_ready,
-	.ready_to_basic = dasd_eckd_ready_to_basic,
+	.basic_to_known = dasd_eckd_basic_to_known,
 	.fill_geometry = dasd_eckd_fill_geometry,
 	.start_IO = dasd_start_IO,
 	.term_IO = dasd_term_IO,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/block/dasd_int.h linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_int.h
--- linux-libre-3.16-gnu/drivers/s390/block/dasd_int.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_int.h	2014-09-28 17:29:07.000000000 -0400
@@ -175,6 +175,7 @@ struct dasd_ccw_req {
 	struct dasd_block *block;	/* the originating block device */
 	struct dasd_device *memdev;	/* the device used to allocate this */
 	struct dasd_device *startdev;	/* device the request is started on */
+	struct dasd_device *basedev;	/* base device if no block->base */
 	void *cpaddr;			/* address of ccw or tcw */
 	unsigned char cpmode;		/* 0 = cmd mode, 1 = itcw */
 	char status;			/* status of this request */
@@ -304,7 +305,7 @@ struct dasd_discipline {
 	 */
 	int (*basic_to_ready) (struct dasd_device *);
 	int (*online_to_ready) (struct dasd_device *);
-	int (*ready_to_basic)  (struct dasd_device *);
+	int (*basic_to_known)(struct dasd_device *);
 
 	/* (struct dasd_device *);
 	 * Device operation functions. build_cp creates a ccw chain for
@@ -321,7 +322,7 @@ struct dasd_discipline {
 	int (*term_IO) (struct dasd_ccw_req *);
 	void (*handle_terminated_request) (struct dasd_ccw_req *);
 	int (*format_device) (struct dasd_device *,
-			      struct format_data_t *);
+			      struct format_data_t *, int enable_pav);
 	int (*free_cp) (struct dasd_ccw_req *, struct request *);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/block/dasd_ioctl.c linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_ioctl.c
--- linux-libre-3.16-gnu/drivers/s390/block/dasd_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/block/dasd_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,7 +203,9 @@ static int
 dasd_format(struct dasd_block *block, struct format_data_t *fdata)
 {
 	struct dasd_device *base;
-	int rc;
+	int enable_pav = 1;
+	int rc, retries;
+	int start, stop;
 
 	base = block->base;
 	if (base->discipline->format_device == NULL)
@@ -231,11 +233,30 @@ dasd_format(struct dasd_block *block, st
 		bdput(bdev);
 	}
 
-	rc = base->discipline->format_device(base, fdata);
-	if (rc)
-		return rc;
+	retries = 255;
+	/* backup start- and endtrack for retries */
+	start = fdata->start_unit;
+	stop = fdata->stop_unit;
+	do {
+		rc = base->discipline->format_device(base, fdata, enable_pav);
+		if (rc) {
+			if (rc == -EAGAIN) {
+				retries--;
+				/* disable PAV in case of errors */
+				enable_pav = 0;
+				fdata->start_unit = start;
+				fdata->stop_unit = stop;
+			} else
+				return rc;
+		} else
+			/* success */
+			break;
+	} while (retries);
 
-	return 0;
+	if (!retries)
+		return -EIO;
+	else
+		return 0;
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/char/con3215.c linux-libre-3.17-rc7-gnu/drivers/s390/char/con3215.c
--- linux-libre-3.16-gnu/drivers/s390/char/con3215.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/char/con3215.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned lon
 	unsigned long flags;
 
 	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
-	if (raw->flags & RAW3215_TIMER_RUNS) {
-		del_timer(&raw->timer);
-		raw->flags &= ~RAW3215_TIMER_RUNS;
-		if (!(raw->port.flags & ASYNC_SUSPENDED)) {
-			raw3215_mk_write_req(raw);
-			raw3215_start_io(raw);
+	raw->flags &= ~RAW3215_TIMER_RUNS;
+	if (!(raw->port.flags & ASYNC_SUSPENDED)) {
+		raw3215_mk_write_req(raw);
+		raw3215_start_io(raw);
+		if ((raw->queued_read || raw->queued_write) &&
+		    !(raw->flags & RAW3215_WORKING) &&
+		    !(raw->flags & RAW3215_TIMER_RUNS)) {
+			raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+			add_timer(&raw->timer);
+			raw->flags |= RAW3215_TIMER_RUNS;
 		}
 	}
 	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct
 		    (raw->flags & RAW3215_FLUSHING)) {
 			/* execute write requests bigger than minimum size */
 			raw3215_start_io(raw);
-			if (raw->flags & RAW3215_TIMER_RUNS) {
-				del_timer(&raw->timer);
-				raw->flags &= ~RAW3215_TIMER_RUNS;
-			}
-		} else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
-			/* delay small writes */
-			raw->timer.expires = RAW3215_TIMEOUT + jiffies;
-			add_timer(&raw->timer);
-			raw->flags |= RAW3215_TIMER_RUNS;
 		}
 	}
+	if ((raw->queued_read || raw->queued_write) &&
+	    !(raw->flags & RAW3215_WORKING) &&
+	    !(raw->flags & RAW3215_TIMER_RUNS)) {
+		raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+		add_timer(&raw->timer);
+		raw->flags |= RAW3215_TIMER_RUNS;
+	}
 }
 
 /*
@@ -1033,12 +1035,26 @@ static int tty3215_write(struct tty_stru
 			 const unsigned char *buf, int count)
 {
 	struct raw3215_info *raw;
+	int i, written;
 
 	if (!tty)
 		return 0;
 	raw = (struct raw3215_info *) tty->driver_data;
-	raw3215_write(raw, buf, count);
-	return count;
+	written = count;
+	while (count > 0) {
+		for (i = 0; i < count; i++)
+			if (buf[i] == '\t' || buf[i] == '\n')
+				break;
+		raw3215_write(raw, buf, i);
+		count -= i;
+		buf += i;
+		if (count > 0) {
+			raw3215_putchar(raw, *buf);
+			count--;
+			buf++;
+		}
+	}
+	return written;
 }
 
 /*
@@ -1186,7 +1202,7 @@ static int __init tty3215_init(void)
 	driver->subtype = SYSTEM_TYPE_TTY;
 	driver->init_termios = tty_std_termios;
 	driver->init_termios.c_iflag = IGNBRK | IGNPAR;
-	driver->init_termios.c_oflag = ONLCR | XTABS;
+	driver->init_termios.c_oflag = ONLCR;
 	driver->init_termios.c_lflag = ISIG;
 	driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(driver, &tty3215_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/char/sclp_tty.c linux-libre-3.17-rc7-gnu/drivers/s390/char/sclp_tty.c
--- linux-libre-3.16-gnu/drivers/s390/char/sclp_tty.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/char/sclp_tty.c	2014-09-28 17:29:07.000000000 -0400
@@ -559,7 +559,7 @@ sclp_tty_init(void)
 	driver->subtype = SYSTEM_TYPE_TTY;
 	driver->init_termios = tty_std_termios;
 	driver->init_termios.c_iflag = IGNBRK | IGNPAR;
-	driver->init_termios.c_oflag = ONLCR | XTABS;
+	driver->init_termios.c_oflag = ONLCR;
 	driver->init_termios.c_lflag = ISIG | ECHO;
 	driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(driver, &sclp_ops);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/cio/qdio_setup.c linux-libre-3.17-rc7-gnu/drivers/s390/cio/qdio_setup.c
--- linux-libre-3.16-gnu/drivers/s390/cio/qdio_setup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/cio/qdio_setup.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,8 @@
 #include "qdio.h"
 #include "qdio_debug.h"
 
+#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
+
 static struct kmem_cache *qdio_q_cache;
 static struct kmem_cache *qdio_aob_cache;
 
@@ -32,6 +34,57 @@ void qdio_release_aob(struct qaob *aob)
 }
 EXPORT_SYMBOL_GPL(qdio_release_aob);
 
+/**
+ * qdio_free_buffers() - free qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers to free
+ */
+void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+	int pos;
+
+	for (pos = 0; pos < count; pos += QBUFF_PER_PAGE)
+		free_page((unsigned long) buf[pos]);
+}
+EXPORT_SYMBOL_GPL(qdio_free_buffers);
+
+/**
+ * qdio_alloc_buffers() - allocate qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers to allocate
+ */
+int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+	int pos;
+
+	for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) {
+		buf[pos] = (void *) get_zeroed_page(GFP_KERNEL);
+		if (!buf[pos]) {
+			qdio_free_buffers(buf, count);
+			return -ENOMEM;
+		}
+	}
+	for (pos = 0; pos < count; pos++)
+		if (pos % QBUFF_PER_PAGE)
+			buf[pos] = buf[pos - 1] + 1;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qdio_alloc_buffers);
+
+/**
+ * qdio_reset_buffers() - reset qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers that will be zeroed
+ */
+void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+	int pos;
+
+	for (pos = 0; pos < count; pos++)
+		memset(buf[pos], 0, sizeof(struct qdio_buffer));
+}
+EXPORT_SYMBOL_GPL(qdio_reset_buffers);
+
 /*
  * qebsm is only available under 64bit but the adapter sets the feature
  * flag anyway, so we manually override it.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/claw.c linux-libre-3.17-rc7-gnu/drivers/s390/net/claw.c
--- linux-libre-3.16-gnu/drivers/s390/net/claw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/claw.c	2014-09-28 17:29:07.000000000 -0400
@@ -2915,7 +2915,7 @@ claw_new_device(struct ccwgroup_device *
 			"failed with error code %d\n", ret);
 		goto out;
 	}
-	dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
+	dev = alloc_netdev(0, "claw%d", NET_NAME_UNKNOWN, claw_init_netdevice);
 	if (!dev) {
 		dev_warn(&cgdev->dev,
 			"Activating the CLAW device failed\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/ctcm_main.c linux-libre-3.17-rc7-gnu/drivers/s390/net/ctcm_main.c
--- linux-libre-3.16-gnu/drivers/s390/net/ctcm_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/ctcm_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -1137,9 +1137,11 @@ static struct net_device *ctcm_init_netd
 		return NULL;
 
 	if (IS_MPC(priv))
-		dev = alloc_netdev(0, MPC_DEVICE_GENE, ctcm_dev_setup);
+		dev = alloc_netdev(0, MPC_DEVICE_GENE, NET_NAME_UNKNOWN,
+				   ctcm_dev_setup);
 	else
-		dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
+		dev = alloc_netdev(0, CTC_DEVICE_GENE, NET_NAME_UNKNOWN,
+				   ctcm_dev_setup);
 
 	if (!dev) {
 		CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/netiucv.c linux-libre-3.17-rc7-gnu/drivers/s390/net/netiucv.c
--- linux-libre-3.16-gnu/drivers/s390/net/netiucv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/netiucv.c	2014-09-28 17:29:07.000000000 -0400
@@ -2015,7 +2015,7 @@ static struct net_device *netiucv_init_n
 	struct net_device *dev;
 
 	dev = alloc_netdev(sizeof(struct netiucv_priv), "iucv%d",
-			   netiucv_setup_netdevice);
+			   NET_NAME_UNKNOWN, netiucv_setup_netdevice);
 	if (!dev)
 		return NULL;
 	rtnl_lock();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_core.h linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core.h
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_core.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core.h	2014-09-28 17:29:07.000000000 -0400
@@ -439,10 +439,10 @@ struct qeth_qdio_buffer {
 };
 
 struct qeth_qdio_q {
-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+	struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
 	struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
 	int next_buf_to_init;
-} __attribute__ ((aligned(256)));
+};
 
 struct qeth_qdio_out_buffer {
 	struct qdio_buffer *buffer;
@@ -465,7 +465,7 @@ enum qeth_out_q_states {
 };
 
 struct qeth_qdio_out_q {
-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+	struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
 	struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
 	struct qdio_outbuf_state *bufstates; /* convenience pointer */
 	int queue_no;
@@ -483,7 +483,7 @@ struct qeth_qdio_out_q {
 	atomic_t used_buffers;
 	/* indicates whether PCI flag must be set (or if one is outstanding) */
 	atomic_t set_pci_flags_count;
-} __attribute__ ((aligned(256)));
+};
 
 struct qeth_qdio_info {
 	atomic_t state;
@@ -766,6 +766,11 @@ struct carrier_info {
 	__u32 port_speed;
 };
 
+struct qeth_switch_info {
+	__u32 capabilities;
+	__u32 settings;
+};
+
 #define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
 
 struct qeth_card {
@@ -884,6 +889,7 @@ extern const struct attribute_group *qet
 extern const struct attribute_group *qeth_osn_attr_groups[];
 extern struct workqueue_struct *qeth_wq;
 
+int qeth_card_hw_is_reachable(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
 int qeth_realloc_buffer_pool(struct qeth_card *, int);
 int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
@@ -946,6 +952,8 @@ struct qeth_cmd_buffer *qeth_wait_for_bu
 int qeth_mdio_read(struct net_device *, int, int);
 int qeth_snmp_command(struct qeth_card *, char __user *);
 int qeth_query_oat_command(struct qeth_card *, char __user *);
+int qeth_query_switch_attributes(struct qeth_card *card,
+				  struct qeth_switch_info *sw_info);
 int qeth_query_card_info(struct qeth_card *card,
 	struct carrier_info *carrier_info);
 int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_core_main.c linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_main.c
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_core_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -73,6 +73,13 @@ static int qeth_init_qdio_out_buf(struct
 struct workqueue_struct *qeth_wq;
 EXPORT_SYMBOL_GPL(qeth_wq);
 
+int qeth_card_hw_is_reachable(struct qeth_card *card)
+{
+	return (card->state == CARD_STATE_SOFTSETUP) ||
+		(card->state == CARD_STATE_UP);
+}
+EXPORT_SYMBOL_GPL(qeth_card_hw_is_reachable);
+
 static void qeth_close_dev_handler(struct work_struct *work)
 {
 	struct qeth_card *card;
@@ -292,14 +299,43 @@ int qeth_realloc_buffer_pool(struct qeth
 }
 EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
 
+static void qeth_free_qdio_queue(struct qeth_qdio_q *q)
+{
+	if (!q)
+		return;
+
+	qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+	kfree(q);
+}
+
+static struct qeth_qdio_q *qeth_alloc_qdio_queue(void)
+{
+	struct qeth_qdio_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+	int i;
+
+	if (!q)
+		return NULL;
+
+	if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
+		kfree(q);
+		return NULL;
+	}
+
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+		q->bufs[i].buffer = q->qdio_bufs[i];
+
+	QETH_DBF_HEX(SETUP, 2, &q, sizeof(void *));
+	return q;
+}
+
 static inline int qeth_cq_init(struct qeth_card *card)
 {
 	int rc;
 
 	if (card->options.cq == QETH_CQ_ENABLED) {
 		QETH_DBF_TEXT(SETUP, 2, "cqinit");
-		memset(card->qdio.c_q->qdio_bufs, 0,
-		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+		qdio_reset_buffers(card->qdio.c_q->qdio_bufs,
+				   QDIO_MAX_BUFFERS_PER_Q);
 		card->qdio.c_q->next_buf_to_init = 127;
 		rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT,
 			     card->qdio.no_in_queues - 1, 0,
@@ -323,21 +359,12 @@ static inline int qeth_alloc_cq(struct q
 		struct qdio_outbuf_state *outbuf_states;
 
 		QETH_DBF_TEXT(SETUP, 2, "cqon");
-		card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q),
-					 GFP_KERNEL);
+		card->qdio.c_q = qeth_alloc_qdio_queue();
 		if (!card->qdio.c_q) {
 			rc = -1;
 			goto kmsg_out;
 		}
-		QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *));
-
-		for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-			card->qdio.c_q->bufs[i].buffer =
-				&card->qdio.c_q->qdio_bufs[i];
-		}
-
 		card->qdio.no_in_queues = 2;
-
 		card->qdio.out_bufstates =
 			kzalloc(card->qdio.no_out_queues *
 				QDIO_MAX_BUFFERS_PER_Q *
@@ -361,7 +388,7 @@ static inline int qeth_alloc_cq(struct q
 out:
 	return rc;
 free_cq_out:
-	kfree(card->qdio.c_q);
+	qeth_free_qdio_queue(card->qdio.c_q);
 	card->qdio.c_q = NULL;
 kmsg_out:
 	dev_err(&card->gdev->dev, "Failed to create completion queue\n");
@@ -372,7 +399,7 @@ static inline void qeth_free_cq(struct q
 {
 	if (card->qdio.c_q) {
 		--card->qdio.no_in_queues;
-		kfree(card->qdio.c_q);
+		qeth_free_qdio_queue(card->qdio.c_q);
 		card->qdio.c_q = NULL;
 	}
 	kfree(card->qdio.out_bufstates);
@@ -1282,35 +1309,6 @@ static void qeth_free_buffer_pool(struct
 	}
 }
 
-static void qeth_free_qdio_buffers(struct qeth_card *card)
-{
-	int i, j;
-
-	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
-		QETH_QDIO_UNINITIALIZED)
-		return;
-
-	qeth_free_cq(card);
-	cancel_delayed_work_sync(&card->buffer_reclaim_work);
-	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
-		if (card->qdio.in_q->bufs[j].rx_skb)
-			dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
-	}
-	kfree(card->qdio.in_q);
-	card->qdio.in_q = NULL;
-	/* inbound buffer pool */
-	qeth_free_buffer_pool(card);
-	/* free outbound qdio_qs */
-	if (card->qdio.out_qs) {
-		for (i = 0; i < card->qdio.no_out_queues; ++i) {
-			qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-			kfree(card->qdio.out_qs[i]);
-		}
-		kfree(card->qdio.out_qs);
-		card->qdio.out_qs = NULL;
-	}
-}
-
 static void qeth_clean_channel(struct qeth_channel *channel)
 {
 	int cnt;
@@ -2392,7 +2390,7 @@ static int qeth_init_qdio_out_buf(struct
 		rc = -ENOMEM;
 		goto out;
 	}
-	newbuf->buffer = &q->qdio_bufs[bidx];
+	newbuf->buffer = q->qdio_bufs[bidx];
 	skb_queue_head_init(&newbuf->skb_list);
 	lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
 	newbuf->q = q;
@@ -2411,6 +2409,28 @@ out:
 	return rc;
 }
 
+static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+{
+	if (!q)
+		return;
+
+	qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+	kfree(q);
+}
+
+static struct qeth_qdio_out_q *qeth_alloc_qdio_out_buf(void)
+{
+	struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+
+	if (!q)
+		return NULL;
+
+	if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
+		kfree(q);
+		return NULL;
+	}
+	return q;
+}
 
 static int qeth_alloc_qdio_buffers(struct qeth_card *card)
 {
@@ -2422,19 +2442,11 @@ static int qeth_alloc_qdio_buffers(struc
 		QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
 		return 0;
 
-	card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q),
-				   GFP_KERNEL);
+	QETH_DBF_TEXT(SETUP, 2, "inq");
+	card->qdio.in_q = qeth_alloc_qdio_queue();
 	if (!card->qdio.in_q)
 		goto out_nomem;
-	QETH_DBF_TEXT(SETUP, 2, "inq");
-	QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
-	memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
-	/* give inbound qeth_qdio_buffers their qdio_buffers */
-	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-		card->qdio.in_q->bufs[i].buffer =
-			&card->qdio.in_q->qdio_bufs[i];
-		card->qdio.in_q->bufs[i].rx_skb = NULL;
-	}
+
 	/* inbound buffer pool */
 	if (qeth_alloc_buffer_pool(card))
 		goto out_freeinq;
@@ -2446,8 +2458,7 @@ static int qeth_alloc_qdio_buffers(struc
 	if (!card->qdio.out_qs)
 		goto out_freepool;
 	for (i = 0; i < card->qdio.no_out_queues; ++i) {
-		card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
-					       GFP_KERNEL);
+		card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
 		if (!card->qdio.out_qs[i])
 			goto out_freeoutq;
 		QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
@@ -2476,7 +2487,7 @@ out_freeoutqbufs:
 	}
 out_freeoutq:
 	while (i > 0) {
-		kfree(card->qdio.out_qs[--i]);
+		qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
 		qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
 	}
 	kfree(card->qdio.out_qs);
@@ -2484,13 +2495,42 @@ out_freeoutq:
 out_freepool:
 	qeth_free_buffer_pool(card);
 out_freeinq:
-	kfree(card->qdio.in_q);
+	qeth_free_qdio_queue(card->qdio.in_q);
 	card->qdio.in_q = NULL;
 out_nomem:
 	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
 	return -ENOMEM;
 }
 
+static void qeth_free_qdio_buffers(struct qeth_card *card)
+{
+	int i, j;
+
+	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+		QETH_QDIO_UNINITIALIZED)
+		return;
+
+	qeth_free_cq(card);
+	cancel_delayed_work_sync(&card->buffer_reclaim_work);
+	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+		if (card->qdio.in_q->bufs[j].rx_skb)
+			dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
+	}
+	qeth_free_qdio_queue(card->qdio.in_q);
+	card->qdio.in_q = NULL;
+	/* inbound buffer pool */
+	qeth_free_buffer_pool(card);
+	/* free outbound qdio_qs */
+	if (card->qdio.out_qs) {
+		for (i = 0; i < card->qdio.no_out_queues; ++i) {
+			qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+			qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
+		}
+		kfree(card->qdio.out_qs);
+		card->qdio.out_qs = NULL;
+	}
+}
+
 static void qeth_create_qib_param_field(struct qeth_card *card,
 		char *param_field)
 {
@@ -2788,8 +2828,8 @@ int qeth_init_qdio_queues(struct qeth_ca
 	QETH_DBF_TEXT(SETUP, 2, "initqdqs");
 
 	/* inbound queue */
-	memset(card->qdio.in_q->qdio_bufs, 0,
-	       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+	qdio_reset_buffers(card->qdio.in_q->qdio_bufs,
+			   QDIO_MAX_BUFFERS_PER_Q);
 	qeth_initialize_working_pool_list(card);
 	/*give only as many buffers to hardware as we have buffer pool entries*/
 	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
@@ -2811,8 +2851,8 @@ int qeth_init_qdio_queues(struct qeth_ca
 
 	/* outbound queue */
 	for (i = 0; i < card->qdio.no_out_queues; ++i) {
-		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
-		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+		qdio_reset_buffers(card->qdio.out_qs[i]->qdio_bufs,
+				   QDIO_MAX_BUFFERS_PER_Q);
 		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
 			qeth_clear_output_buffer(card->qdio.out_qs[i],
 					card->qdio.out_qs[i]->bufs[j],
@@ -3037,6 +3077,45 @@ int qeth_query_ipassists(struct qeth_car
 }
 EXPORT_SYMBOL_GPL(qeth_query_ipassists);
 
+static int qeth_query_switch_attributes_cb(struct qeth_card *card,
+				struct qeth_reply *reply, unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_switch_info *sw_info;
+	struct qeth_query_switch_attributes *attrs;
+
+	QETH_CARD_TEXT(card, 2, "qswiatcb");
+	cmd = (struct qeth_ipa_cmd *) data;
+	sw_info = (struct qeth_switch_info *)reply->param;
+	if (cmd->data.setadapterparms.hdr.return_code == 0) {
+		attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
+		sw_info->capabilities = attrs->capabilities;
+		sw_info->settings = attrs->settings;
+		QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
+							sw_info->settings);
+	}
+	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
+
+	return 0;
+}
+
+int qeth_query_switch_attributes(struct qeth_card *card,
+				 struct qeth_switch_info *sw_info)
+{
+	struct qeth_cmd_buffer *iob;
+
+	QETH_CARD_TEXT(card, 2, "qswiattr");
+	if (!qeth_adp_supported(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES))
+		return -EOPNOTSUPP;
+	if (!netif_carrier_ok(card->dev))
+		return -ENOMEDIUM;
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES,
+				sizeof(struct qeth_ipacmd_setadpparms_hdr));
+	return qeth_send_ipa_cmd(card, iob,
+				qeth_query_switch_attributes_cb, sw_info);
+}
+EXPORT_SYMBOL_GPL(qeth_query_switch_attributes);
+
 static int qeth_query_setdiagass_cb(struct qeth_card *card,
 		struct qeth_reply *reply, unsigned long data)
 {
@@ -3530,7 +3609,7 @@ static void qeth_qdio_cq_handler(struct
 
 	for (i = first_element; i < first_element + count; ++i) {
 		int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
-		struct qdio_buffer *buffer = &cq->qdio_bufs[bidx];
+		struct qdio_buffer *buffer = cq->qdio_bufs[bidx];
 		int e;
 
 		e = 0;
@@ -5718,6 +5797,7 @@ int qeth_core_ethtool_get_settings(struc
 	struct qeth_card *card = netdev->ml_priv;
 	enum qeth_link_types link_type;
 	struct carrier_info carrier_info;
+	int rc;
 	u32 speed;
 
 	if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
@@ -5760,8 +5840,14 @@ int qeth_core_ethtool_get_settings(struc
 	/* Check if we can obtain more accurate information.	 */
 	/* If QUERY_CARD_INFO command is not supported or fails, */
 	/* just return the heuristics that was filled above.	 */
-	if (qeth_query_card_info(card, &carrier_info) != 0)
+	if (!qeth_card_hw_is_reachable(card))
+		return -ENODEV;
+	rc = qeth_query_card_info(card, &carrier_info);
+	if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
 		return 0;
+	if (rc) /* report error from the hardware operation */
+		return rc;
+	/* on success, fill in the information got from the hardware */
 
 	netdev_dbg(netdev,
 	"card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_core_mpc.h linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_mpc.h
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_core_mpc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_mpc.h	2014-09-28 17:29:07.000000000 -0400
@@ -242,6 +242,7 @@ enum qeth_ipa_setadp_cmd {
 	IPA_SETADP_SET_DIAG_ASSIST		= 0x00002000L,
 	IPA_SETADP_SET_ACCESS_CONTROL		= 0x00010000L,
 	IPA_SETADP_QUERY_OAT			= 0x00080000L,
+	IPA_SETADP_QUERY_SWITCH_ATTRIBUTES	= 0x00100000L,
 };
 enum qeth_ipa_mac_ops {
 	CHANGE_ADDR_READ_MAC		= 0,
@@ -431,6 +432,21 @@ struct qeth_query_card_info {
 	__u32	reserved2;
 };
 
+#define QETH_SWITCH_FORW_802_1		0x00000001
+#define QETH_SWITCH_FORW_REFL_RELAY	0x00000002
+#define QETH_SWITCH_CAP_RTE		0x00000004
+#define QETH_SWITCH_CAP_ECP		0x00000008
+#define QETH_SWITCH_CAP_VDP		0x00000010
+
+struct qeth_query_switch_attributes {
+	__u8  version;
+	__u8  reserved1;
+	__u16 reserved2;
+	__u32 capabilities;
+	__u32 settings;
+	__u8  reserved3[8];
+};
+
 struct qeth_ipacmd_setadpparms_hdr {
 	__u32 supp_hw_cmds;
 	__u32 reserved1;
@@ -452,6 +468,7 @@ struct qeth_ipacmd_setadpparms {
 		struct qeth_set_access_ctrl set_access_ctrl;
 		struct qeth_query_oat query_oat;
 		struct qeth_query_card_info card_info;
+		struct qeth_query_switch_attributes query_switch_attributes;
 		__u32 mode;
 	} data;
 } __attribute__ ((packed));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_core_sys.c linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_sys.c
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_core_sys.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_core_sys.c	2014-09-28 17:29:07.000000000 -0400
@@ -543,7 +543,42 @@ out:
 }
 
 static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
-		   qeth_dev_isolation_store);
+			qeth_dev_isolation_store);
+
+static ssize_t qeth_dev_switch_attrs_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct qeth_card *card = dev_get_drvdata(dev);
+	struct qeth_switch_info sw_info;
+	int	rc = 0;
+
+	if (!card)
+		return -EINVAL;
+
+	if (card->state != CARD_STATE_SOFTSETUP && card->state != CARD_STATE_UP)
+		return sprintf(buf, "n/a\n");
+
+	rc = qeth_query_switch_attributes(card, &sw_info);
+	if (rc)
+		return rc;
+
+	if (!sw_info.capabilities)
+		rc = sprintf(buf, "unknown");
+
+	if (sw_info.capabilities & QETH_SWITCH_FORW_802_1)
+		rc = sprintf(buf, (sw_info.settings & QETH_SWITCH_FORW_802_1 ?
+							"[802.1]" : "802.1"));
+	if (sw_info.capabilities & QETH_SWITCH_FORW_REFL_RELAY)
+		rc += sprintf(buf + rc,
+			(sw_info.settings & QETH_SWITCH_FORW_REFL_RELAY ?
+							" [rr]" : " rr"));
+	rc += sprintf(buf + rc, "\n");
+
+	return rc;
+}
+
+static DEVICE_ATTR(switch_attrs, 0444,
+		   qeth_dev_switch_attrs_show, NULL);
 
 static ssize_t qeth_hw_trap_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -728,6 +763,7 @@ static struct attribute *qeth_device_att
 	&dev_attr_layer2.attr,
 	&dev_attr_isolation.attr,
 	&dev_attr_hw_trap.attr,
+	&dev_attr_switch_attrs.attr,
 	NULL,
 };
 static struct attribute_group qeth_device_attr_group = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_l2_main.c linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l2_main.c
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_l2_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l2_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -952,10 +952,12 @@ static int qeth_l2_setup_netdev(struct q
 {
 	switch (card->info.type) {
 	case QETH_CARD_TYPE_IQD:
-		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+		card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
+					 ether_setup);
 		break;
 	case QETH_CARD_TYPE_OSN:
-		card->dev = alloc_netdev(0, "osn%d", ether_setup);
+		card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
+					 ether_setup);
 		card->dev->flags |= IFF_NOARP;
 		break;
 	default:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_l2_sys.c linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l2_sys.c
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_l2_sys.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l2_sys.c	2014-09-28 17:29:07.000000000 -0400
@@ -5,17 +5,12 @@
 
 #include <linux/slab.h>
 #include <asm/ebcdic.h>
+#include "qeth_core.h"
 #include "qeth_l2.h"
 
 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
 struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
 
-static int qeth_card_hw_is_reachable(struct qeth_card *card)
-{
-	return (card->state == CARD_STATE_SOFTSETUP) ||
-		(card->state == CARD_STATE_UP);
-}
-
 static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
 				struct device_attribute *attr, char *buf,
 				int show_state)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/net/qeth_l3_main.c linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l3_main.c
--- linux-libre-3.16-gnu/drivers/s390/net/qeth_l3_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/net/qeth_l3_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -3287,7 +3287,8 @@ static int qeth_l3_setup_netdev(struct q
 			}
 		}
 	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
-		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+		card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
+					 ether_setup);
 		if (!card->dev)
 			return -ENODEV;
 		card->dev->flags |= IFF_NOARP;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_dbf.c linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_dbf.c
--- linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_dbf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_dbf.c	2014-09-28 17:29:07.000000000 -0400
@@ -418,7 +418,8 @@ void zfcp_dbf_scsi(char *tag, struct scs
 	rec->scsi_retries = sc->retries;
 	rec->scsi_allowed = sc->allowed;
 	rec->scsi_id = sc->device->id;
-	rec->scsi_lun = sc->device->lun;
+	/* struct zfcp_dbf_scsi needs to be updated to handle 64bit LUNs */
+	rec->scsi_lun = (u32)sc->device->lun;
 	rec->host_scribble = (unsigned long)sc->host_scribble;
 
 	memcpy(rec->scsi_opcode, sc->cmnd,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_qdio.c linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_qdio.c
--- linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_qdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_qdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,27 +14,10 @@
 #include "zfcp_ext.h"
 #include "zfcp_qdio.h"
 
-#define QBUFF_PER_PAGE		(PAGE_SIZE / sizeof(struct qdio_buffer))
-
 static bool enable_multibuffer = 1;
 module_param_named(datarouter, enable_multibuffer, bool, 0400);
 MODULE_PARM_DESC(datarouter, "Enable hardware data router support (default on)");
 
-static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
-{
-	int pos;
-
-	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
-		sbal[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
-		if (!sbal[pos])
-			return -ENOMEM;
-	}
-	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
-		if (pos % QBUFF_PER_PAGE)
-			sbal[pos] = sbal[pos - 1] + 1;
-	return 0;
-}
-
 static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
 				    unsigned int qdio_err)
 {
@@ -326,15 +309,30 @@ static void zfcp_qdio_setup_init_data(st
 static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
 {
 	struct qdio_initialize init_data;
+	int ret;
 
-	if (zfcp_qdio_buffers_enqueue(qdio->req_q) ||
-	    zfcp_qdio_buffers_enqueue(qdio->res_q))
+	ret = qdio_alloc_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+	if (ret)
 		return -ENOMEM;
 
+	ret = qdio_alloc_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
+	if (ret)
+		goto free_req_q;
+
 	zfcp_qdio_setup_init_data(&init_data, qdio);
 	init_waitqueue_head(&qdio->req_q_wq);
 
-	return qdio_allocate(&init_data);
+	ret = qdio_allocate(&init_data);
+	if (ret)
+		goto free_res_q;
+
+	return 0;
+
+free_res_q:
+	qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
+free_req_q:
+	qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+	return ret;
 }
 
 /**
@@ -448,19 +446,14 @@ failed_establish:
 
 void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
 {
-	int p;
-
 	if (!qdio)
 		return;
 
 	if (qdio->adapter->ccw_device)
 		qdio_free(qdio->adapter->ccw_device);
 
-	for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
-		free_page((unsigned long) qdio->req_q[p]);
-		free_page((unsigned long) qdio->res_q[p]);
-	}
-
+	qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+	qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
 	kfree(qdio);
 }
 
@@ -475,7 +468,7 @@ int zfcp_qdio_setup(struct zfcp_adapter
 	qdio->adapter = adapter;
 
 	if (zfcp_qdio_allocate(qdio)) {
-		zfcp_qdio_destroy(qdio);
+		kfree(qdio);
 		return -ENOMEM;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_unit.c linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_unit.c
--- linux-libre-3.16-gnu/drivers/s390/scsi/zfcp_unit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/s390/scsi/zfcp_unit.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,7 @@
 void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
 {
 	struct fc_rport *rport = unit->port->rport;
-	unsigned int lun;
+	u64 lun;
 
 	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
 
@@ -188,7 +188,7 @@ struct scsi_device *zfcp_unit_sdev(struc
 {
 	struct Scsi_Host *shost;
 	struct zfcp_port *port;
-	unsigned int lun;
+	u64 lun;
 
 	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
 	port = unit->port;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/sbus/char/bbc_envctrl.c linux-libre-3.17-rc7-gnu/drivers/sbus/char/bbc_envctrl.c
--- linux-libre-3.16-gnu/drivers/sbus/char/bbc_envctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/sbus/char/bbc_envctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i
 	if (!tp)
 		return;
 
+	INIT_LIST_HEAD(&tp->bp_list);
+	INIT_LIST_HEAD(&tp->glob_list);
+
 	tp->client = bbc_i2c_attach(bp, op);
 	if (!tp->client) {
 		kfree(tp);
@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2
 	if (!fp)
 		return;
 
+	INIT_LIST_HEAD(&fp->bp_list);
+	INIT_LIST_HEAD(&fp->glob_list);
+
 	fp->client = bbc_i2c_attach(bp, op);
 	if (!fp->client) {
 		kfree(fp);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/sbus/char/bbc_i2c.c linux-libre-3.17-rc7-gnu/drivers/sbus/char/bbc_i2c.c
--- linux-libre-3.16-gnu/drivers/sbus/char/bbc_i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/sbus/char/bbc_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -300,13 +300,18 @@ static struct bbc_i2c_bus * attach_one_i
 	if (!bp)
 		return NULL;
 
+	INIT_LIST_HEAD(&bp->temps);
+	INIT_LIST_HEAD(&bp->fans);
+
 	bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
 	if (!bp->i2c_control_regs)
 		goto fail;
 
-	bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
-	if (!bp->i2c_bussel_reg)
-		goto fail;
+	if (op->num_resources == 2) {
+		bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
+		if (!bp->i2c_bussel_reg)
+			goto fail;
+	}
 
 	bp->waiting = 0;
 	init_waitqueue_head(&bp->wq);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/sbus/char/display7seg.c linux-libre-3.17-rc7-gnu/drivers/sbus/char/display7seg.c
--- linux-libre-3.16-gnu/drivers/sbus/char/display7seg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/sbus/char/display7seg.c	2014-09-28 17:29:07.000000000 -0400
@@ -4,6 +4,7 @@
  * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
  */
 
+#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -143,10 +144,7 @@ static long d7s_ioctl(struct file *file,
 
 	case D7SIOCTM:
 		/* toggle device mode-- flip display orientation */
-		if (regs & D7S_FLIP)
-			regs &= ~D7S_FLIP;
-		else
-			regs |= D7S_FLIP;
+		regs ^= D7S_FLIP;
 		writeb(regs, p->regs);
 		break;
 	}
@@ -180,7 +178,7 @@ static int d7s_probe(struct platform_dev
 	if (d7s_device)
 		goto out;
 
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
 	err = -ENOMEM;
 	if (!p)
 		goto out;
@@ -231,7 +229,6 @@ out_iounmap:
 	of_iounmap(&op->resource[0], p->regs, sizeof(u8));
 
 out_free:
-	kfree(p);
 	goto out;
 }
 
@@ -251,7 +248,6 @@ static int d7s_remove(struct platform_de
 
 	misc_deregister(&d7s_miscdev);
 	of_iounmap(&op->resource[0], p->regs, sizeof(u8));
-	kfree(p);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/3w-sas.c linux-libre-3.17-rc7-gnu/drivers/scsi/3w-sas.c
--- linux-libre-3.16-gnu/drivers/scsi/3w-sas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/3w-sas.c	2014-09-28 17:29:07.000000000 -0400
@@ -683,14 +683,13 @@ static int twl_allocate_memory(TW_Device
 	unsigned long *cpu_addr;
 	int retval = 1;
 
-	cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
+	cpu_addr = pci_zalloc_consistent(tw_dev->tw_pci_dev, size * TW_Q_LENGTH,
+					 &dma_handle);
 	if (!cpu_addr) {
 		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
 		goto out;
 	}
 
-	memset(cpu_addr, 0, size*TW_Q_LENGTH);
-
 	for (i = 0; i < TW_Q_LENGTH; i++) {
 		switch(which) {
 		case 0:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/3w-xxxx.h linux-libre-3.17-rc7-gnu/drivers/scsi/3w-xxxx.h
--- linux-libre-3.16-gnu/drivers/scsi/3w-xxxx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/3w-xxxx.h	2014-09-28 17:29:07.000000000 -0400
@@ -392,6 +392,8 @@ typedef struct TAG_TW_Passthru
 	unsigned char padding[12];
 } TW_Passthru;
 
+#pragma pack()
+
 typedef struct TAG_TW_Device_Extension {
 	u32			base_addr;
 	unsigned long		*alignment_virtual_address[TW_Q_LENGTH];
@@ -430,6 +432,4 @@ typedef struct TAG_TW_Device_Extension {
 	wait_queue_head_t	ioctl_wqueue;
 } TW_Device_Extension;
 
-#pragma pack()
-
 #endif /* _3W_XXXX_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/53c700.c linux-libre-3.17-rc7-gnu/drivers/scsi/53c700.c
--- linux-libre-3.16-gnu/drivers/scsi/53c700.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/53c700.c	2014-09-28 17:29:07.000000000 -0400
@@ -1005,7 +1005,7 @@ process_script_interrupt(__u32 dsps, __u
 						 DMA_TO_DEVICE);
 
 				cmnd[0] = REQUEST_SENSE;
-				cmnd[1] = (SCp->device->lun & 0x7) << 5;
+				cmnd[1] = (lun & 0x7) << 5;
 				cmnd[2] = 0;
 				cmnd[3] = 0;
 				cmnd[4] = SCSI_SENSE_BUFFERSIZE;
@@ -1396,7 +1396,8 @@ NCR_700_start_command(struct scsi_cmnd *
 	struct NCR_700_Host_Parameters *hostdata =
 		(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
 	__u16 count = 1;	/* for IDENTIFY message */
-	
+	u8 lun = SCp->device->lun;
+
 	if(hostdata->state != NCR_700_HOST_FREE) {
 		/* keep this inside the lock to close the race window where
 		 * the running command finishes on another CPU while we don't
@@ -1415,7 +1416,7 @@ NCR_700_start_command(struct scsi_cmnd *
 
 	hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE &&
 						slot->flags != NCR_700_FLAG_AUTOSENSE),
-					       SCp->device->lun);
+					       lun);
 	/* for INQUIRY or REQUEST_SENSE commands, we cannot be sure
 	 * if the negotiated transfer parameters still hold, so
 	 * always renegotiate them */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/a100u2w.c linux-libre-3.17-rc7-gnu/drivers/scsi/a100u2w.c
--- linux-libre-3.16-gnu/drivers/scsi/a100u2w.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/a100u2w.c	2014-09-28 17:29:07.000000000 -0400
@@ -891,7 +891,7 @@ static int inia100_build_scb(struct orc_
 		printk("max cdb length= %x\b", cmd->cmd_len);
 		scb->cdb_len = IMAX_CDB;
 	}
-	scb->ident = cmd->device->lun | DISC_ALLOW;
+	scb->ident = (u8)(cmd->device->lun & 0xff) | DISC_ALLOW;
 	if (cmd->device->tagged_supported) {	/* Tag Support                  */
 		scb->tag_msg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */
 	} else {
@@ -1125,23 +1125,19 @@ static int inia100_probe_one(struct pci_
 
 	/* Get total memory needed for SCB */
 	sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
-	host->scb_virt = pci_alloc_consistent(pdev, sz,
-			&host->scb_phys);
+	host->scb_virt = pci_zalloc_consistent(pdev, sz, &host->scb_phys);
 	if (!host->scb_virt) {
 		printk("inia100: SCB memory allocation error\n");
 		goto out_host_put;
 	}
-	memset(host->scb_virt, 0, sz);
 
 	/* Get total memory needed for ESCB */
 	sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
-	host->escb_virt = pci_alloc_consistent(pdev, sz,
-			&host->escb_phys);
+	host->escb_virt = pci_zalloc_consistent(pdev, sz, &host->escb_phys);
 	if (!host->escb_virt) {
 		printk("inia100: ESCB memory allocation error\n");
 		goto out_free_scb_array;
 	}
-	memset(host->escb_virt, 0, sz);
 
 	biosaddr = host->BIOScfg;
 	biosaddr = (biosaddr << 4);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aacraid/linit.c linux-libre-3.17-rc7-gnu/drivers/scsi/aacraid/linit.c
--- linux-libre-3.16-gnu/drivers/scsi/aacraid/linit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aacraid/linit.c	2014-09-28 17:29:07.000000000 -0400
@@ -551,7 +551,7 @@ static int aac_eh_abort(struct scsi_cmnd
 	int count;
 	int ret = FAILED;
 
-	printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
+	printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n",
 		AAC_DRIVERNAME,
 		host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
 	switch (cmd->cmnd[0]) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/advansys.c linux-libre-3.17-rc7-gnu/drivers/scsi/advansys.c
--- linux-libre-3.16-gnu/drivers/scsi/advansys.c	2014-08-07 04:59:24.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/advansys.c	2014-09-28 21:42:01.000000000 -0400
@@ -2512,7 +2512,7 @@ static void asc_prt_scsi_host(struct Scs
 
 	printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
 	printk(" host_busy %u, host_no %d,\n",
-	       s->host_busy, s->host_no);
+	       atomic_read(&s->host_busy), s->host_no);
 
 	printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
 	       (ulong)s->base, (ulong)s->io_port, boardp->irq);
@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct s
 		shost->host_no);
 
 	seq_printf(m,
-		   " host_busy %u, max_id %u, max_lun %u, max_channel %u\n",
-		   shost->host_busy, shost->max_id,
+		   " host_busy %u, max_id %u, max_lun %llu, max_channel %u\n",
+		   atomic_read(&shost->host_busy), shost->max_id,
 		   shost->max_lun, shost->max_channel);
 
 	seq_printf(m,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aha152x.c linux-libre-3.17-rc7-gnu/drivers/scsi/aha152x.c
--- linux-libre-3.16-gnu/drivers/scsi/aha152x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aha152x.c	2014-09-28 17:29:07.000000000 -0400
@@ -321,7 +321,7 @@ static LIST_HEAD(aha152x_host_list);
 #define CMDINFO(cmd) \
 			(cmd) ? ((cmd)->device->host->host_no) : -1, \
                         (cmd) ? ((cmd)->device->id & 0x0f) : -1, \
-			(cmd) ? ((cmd)->device->lun & 0x07) : -1
+			(cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1
 
 static inline void
 CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
@@ -1602,7 +1602,7 @@ static void busfree_run(struct Scsi_Host
 #if defined(AHA152X_DEBUG)
 			int hostno=DONE_SC->device->host->host_no;
 			int id=DONE_SC->device->id & 0xf;
-			int lun=DONE_SC->device->lun & 0x7;
+			int lun=((u8)DONE_SC->device->lun) & 0x7;
 #endif
 			Scsi_Cmnd *ptr = DONE_SC;
 			DONE_SC=NULL;
@@ -2984,7 +2984,7 @@ static void get_command(struct seq_file
 	int i;
 
 	SPRINTF("%p: target=%d; lun=%d; cmnd=( ",
-		ptr, ptr->device->id, ptr->device->lun);
+		ptr, ptr->device->id, (u8)ptr->device->lun);
 
 	for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
 		SPRINTF("0x%02x ", ptr->cmnd[i]);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7770_osm.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7770_osm.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7770_osm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7770_osm.c	2014-09-28 17:29:07.000000000 -0400
@@ -85,10 +85,9 @@ aic7770_probe(struct device *dev)
 	int	error;
 
 	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
-	name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+	name = kstrdup(buf, GFP_ATOMIC);
 	if (name == NULL)
 		return (ENOMEM);
-	strcpy(name, buf);
 	ahc = ahc_alloc(&aic7xxx_driver_template, name);
 	if (ahc == NULL)
 		return (ENOMEM);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx.h linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx.h
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -115,7 +115,7 @@ struct scb_platform_data;
 #endif
 
 #define AHD_BUILD_COL_IDX(target, lun)				\
-	(((lun) << 4) | target)
+	((((u8)lun) << 4) | target)
 
 #define AHD_GET_SCB_COL_IDX(ahd, scb)				\
 	((SCB_GET_LUN(scb) << 4) | SCB_GET_TARGET(ahd, scb))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c	2014-09-28 17:29:07.000000000 -0400
@@ -2137,7 +2137,7 @@ ahd_linux_queue_cmd_complete(struct ahd_
 	if (do_fallback) {
 		printk("%s: device overrun (status %x) on %d:%d:%d\n",
 		       ahd_name(ahd), status, cmd->device->channel,
-		       cmd->device->id, cmd->device->lun);
+		       cmd->device->id, (u8)cmd->device->lun);
 	}
 
 	ahd_cmd_set_transaction_status(cmd, new_status);
@@ -2253,13 +2253,13 @@ ahd_linux_queue_abort_cmd(struct scsi_cm
 	disconnected = TRUE;
 	if (ahd_search_qinfifo(ahd, cmd->device->id, 
 			       cmd->device->channel + 'A',
-			       cmd->device->lun, 
+			       cmd->device->lun,
 			       pending_scb->hscb->tag,
 			       ROLE_INITIATOR, CAM_REQ_ABORTED,
 			       SEARCH_COMPLETE) > 0) {
 		printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
 		       ahd_name(ahd), cmd->device->channel, 
-		       cmd->device->id, cmd->device->lun);
+		       cmd->device->id, (u8)cmd->device->lun);
 		retval = SUCCESS;
 		goto done;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_osm_pci.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_osm_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_osm_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -178,10 +178,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 		ahd_get_pci_bus(pci),
 		ahd_get_pci_slot(pci),
 		ahd_get_pci_function(pci));
-	name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+	name = kstrdup(buf, GFP_ATOMIC);
 	if (name == NULL)
 		return (-ENOMEM);
-	strcpy(name, buf);
 	ahd = ahd_alloc(NULL, name);
 	if (ahd == NULL)
 		return (-ENOMEM);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_proc.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_proc.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic79xx_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic79xx_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -197,7 +197,7 @@ ahd_dump_device_state(struct seq_file *m
 
 	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
-		  sdev->sdev_target->id, sdev->lun);
+		   sdev->sdev_target->id, (u8)sdev->lun);
 
 	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
 	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c	2014-09-28 17:29:07.000000000 -0400
@@ -2110,7 +2110,7 @@ ahc_linux_queue_recovery_cmd(struct scsi
 		 */
 		printk("%s:%d:%d:%d: Is not an active device\n",
 		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
+		       (u8)cmd->device->lun);
 		retval = SUCCESS;
 		goto no_cmd;
 	}
@@ -2118,11 +2118,11 @@ ahc_linux_queue_recovery_cmd(struct scsi
 	if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
 	 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
 				       cmd->device->channel + 'A',
-				       cmd->device->lun,
+				       (u8)cmd->device->lun,
 				       CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) {
 		printk("%s:%d:%d:%d: Command found on untagged queue\n",
 		       ahc_name(ahc), cmd->device->channel, cmd->device->id,
-		       cmd->device->lun);
+		       (u8)cmd->device->lun);
 		retval = SUCCESS;
 		goto done;
 	}
@@ -2188,13 +2188,14 @@ ahc_linux_queue_recovery_cmd(struct scsi
 				       SEARCH_COMPLETE) > 0) {
 			printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
 			       ahc_name(ahc), cmd->device->channel,
-					cmd->device->id, cmd->device->lun);
+			       cmd->device->id, (u8)cmd->device->lun);
 			retval = SUCCESS;
 			goto done;
 		}
 	} else if (ahc_search_qinfifo(ahc, cmd->device->id,
 				      cmd->device->channel + 'A',
-				      cmd->device->lun, pending_scb->hscb->tag,
+				      cmd->device->lun,
+				      pending_scb->hscb->tag,
 				      ROLE_INITIATOR, /*status*/0,
 				      SEARCH_COUNT) > 0) {
 		disconnected = FALSE;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -225,10 +225,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 		ahc_get_pci_bus(pci),
 		ahc_get_pci_slot(pci),
 		ahc_get_pci_function(pci));
-	name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+	name = kstrdup(buf, GFP_ATOMIC);
 	if (name == NULL)
 		return (-ENOMEM);
-	strcpy(name, buf);
 	ahc = ahc_alloc(NULL, name);
 	if (ahc == NULL)
 		return (-ENOMEM);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_proc.c linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_proc.c
--- linux-libre-3.16-gnu/drivers/scsi/aic7xxx/aic7xxx_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/aic7xxx/aic7xxx_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -175,7 +175,7 @@ ahc_dump_device_state(struct seq_file *m
 
 	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
-		  sdev->sdev_target->id, sdev->lun);
+		   sdev->sdev_target->id, (u8)sdev->lun);
 
 	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
 	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/arcmsr/arcmsr_hba.c linux-libre-3.17-rc7-gnu/drivers/scsi/arcmsr/arcmsr_hba.c
--- linux-libre-3.16-gnu/drivers/scsi/arcmsr/arcmsr_hba.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/arcmsr/arcmsr_hba.c	2014-09-28 17:29:07.000000000 -0400
@@ -2335,7 +2335,7 @@ static int arcmsr_polling_hba_ccbdone(st
 					" poll command abort successfully \n"
 					, acb->host->host_no
 					, ccb->pcmd->device->id
-					, ccb->pcmd->device->lun
+					, (u32)ccb->pcmd->device->lun
 					, ccb);
 				ccb->pcmd->result = DID_ABORT << 16;
 				arcmsr_ccb_complete(ccb);
@@ -2399,7 +2399,7 @@ static int arcmsr_polling_hbb_ccbdone(st
 					" poll command abort successfully \n"
 					,acb->host->host_no
 					,ccb->pcmd->device->id
-					,ccb->pcmd->device->lun
+					,(u32)ccb->pcmd->device->lun
 					,ccb);
 				ccb->pcmd->result = DID_ABORT << 16;
 				arcmsr_ccb_complete(ccb);
@@ -2456,7 +2456,7 @@ polling_hbc_ccb_retry:
 					" poll command abort successfully \n"
 					, acb->host->host_no
 					, pCCB->pcmd->device->id
-					, pCCB->pcmd->device->lun
+					, (u32)pCCB->pcmd->device->lun
 					, pCCB);
 					pCCB->pcmd->result = DID_ABORT << 16;
 					arcmsr_ccb_complete(pCCB);
@@ -3058,7 +3058,7 @@ static int arcmsr_abort(struct scsi_cmnd
 	int rtn = FAILED;
 	printk(KERN_NOTICE
 		"arcmsr%d: abort device command of scsi id = %d lun = %d \n",
-		acb->host->host_no, cmd->device->id, cmd->device->lun);
+		acb->host->host_no, cmd->device->id, (u32)cmd->device->lun);
 	acb->acb_flags |= ACB_F_ABORT;
 	acb->num_aborts++;
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/arm/acornscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/arm/acornscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/arm/acornscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/arm/acornscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -760,7 +760,8 @@ intr_ret_t acornscsi_kick(AS_Host *host)
 	    SCpnt->tag = SCpnt->device->current_tag;
 	} else
 #endif
-	    set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+	    set_bit(SCpnt->device->id * 8 +
+		    (u8)(SCpnt->device->lun & 0x07), host->busyluns);
 
 	host->stats.removes += 1;
 
@@ -863,7 +864,8 @@ static void acornscsi_done(AS_Host *host
 	if (!SCpnt->scsi_done)
 	    panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
 
-	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+	clear_bit(SCpnt->device->id * 8 +
+		  (u8)(SCpnt->device->lun & 0x7), host->busyluns);
 
 	SCpnt->scsi_done(SCpnt);
     } else
@@ -1576,7 +1578,8 @@ void acornscsi_message(AS_Host *host)
 	    printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
 		    host->host->host_no, acornscsi_target(host));
 	    host->SCpnt->device->simple_tags = 0;
-	    set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
+	    set_bit(host->SCpnt->device->id * 8 +
+		    (u8)(host->SCpnt->device->lun & 0x7), host->busyluns);
 	    break;
 #endif
 	case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
@@ -2671,7 +2674,8 @@ int acornscsi_abort(struct scsi_cmnd *SC
 //#if (DEBUG & DEBUG_ABORT)
 		printk("clear ");
 //#endif
-		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+		clear_bit(SCpnt->device->id * 8 +
+			  (u8)(SCpnt->device->lun & 0x7), host->busyluns);
 
 	/*
 	 * We found the command, and cleared it out.  Either
@@ -2853,7 +2857,7 @@ static int acornscsi_show_info(struct se
 
     shost_for_each_device(scd, instance) {
 	seq_printf(m, "Device/Lun TaggedQ      Sync\n");
-	seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
+	seq_printf(m, "     %d/%llu   ", scd->id, scd->lun);
 	if (scd->tagged_supported)
 		seq_printf(m, "%3sabled(%3d) ",
 			     scd->simple_tags ? "en" : "dis",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/arm/fas216.c linux-libre-3.17-rc7-gnu/drivers/scsi/arm/fas216.c
--- linux-libre-3.16-gnu/drivers/scsi/arm/fas216.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/arm/fas216.c	2014-09-28 17:29:07.000000000 -0400
@@ -1821,7 +1821,8 @@ static void fas216_allocate_tag(FAS216_I
 			SCpnt->tag = SCpnt->device->current_tag;
 	} else
 #endif
-		set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+		set_bit(SCpnt->device->id * 8 +
+			(u8)(SCpnt->device->lun & 0x7), info->busyluns);
 
 	info->stats.removes += 1;
 	switch (SCpnt->cmnd[0]) {
@@ -2171,7 +2172,8 @@ static void fas216_done(FAS216_Info *inf
 	 * status.
 	 */
 	info->device[SCpnt->device->id].parity_check = 0;
-	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+	clear_bit(SCpnt->device->id * 8 +
+		  (u8)(SCpnt->device->lun & 0x7), info->busyluns);
 
 	fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;
 	fn(info, SCpnt, result);
@@ -2398,7 +2400,8 @@ static enum res_find fas216_find_command
 		 * been set.
 		 */
 		info->origSCpnt = NULL;
-		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+		clear_bit(SCpnt->device->id * 8 +
+			  (u8)(SCpnt->device->lun & 0x7), info->busyluns);
 		printk("waiting for execution ");
 		res = res_success;
 	} else
@@ -3000,7 +3003,7 @@ void fas216_print_devices(FAS216_Info *i
 
 	shost_for_each_device(scd, info->host) {
 		dev = &info->device[scd->id];
-		seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
+		seq_printf(m, "     %d/%llu   ", scd->id, scd->lun);
 		if (scd->tagged_supported)
 			seq_printf(m, "%3sabled(%3d) ",
 				     scd->simple_tags ? "en" : "dis",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/arm/queue.c linux-libre-3.17-rc7-gnu/drivers/scsi/arm/queue.c
--- linux-libre-3.16-gnu/drivers/scsi/arm/queue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/arm/queue.c	2014-09-28 17:29:07.000000000 -0400
@@ -167,7 +167,8 @@ struct scsi_cmnd *queue_remove_exclude(Q
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
 		QE_t *q = list_entry(l, QE_t, list);
-		if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) {
+		if (!test_bit(q->SCpnt->device->id * 8 +
+			      (u8)(q->SCpnt->device->lun & 0x7), exclude)) {
 			SCpnt = __queue_remove(queue, l);
 			break;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/atari_NCR5380.c linux-libre-3.17-rc7-gnu/drivers/scsi/atari_NCR5380.c
--- linux-libre-3.16-gnu/drivers/scsi/atari_NCR5380.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/atari_NCR5380.c	2014-09-28 17:29:07.000000000 -0400
@@ -361,17 +361,18 @@ static void __init init_tags(void)
 
 static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
 {
+	u8 lun = cmd->device->lun;
 	SETUP_HOSTDATA(cmd->device->host);
 
-	if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+	if (hostdata->busy[cmd->device->id] & (1 << lun))
 		return 1;
 	if (!should_be_tagged ||
 	    !setup_use_tagged_queuing || !cmd->device->tagged_supported)
 		return 0;
-	if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
-	    TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
+	if (TagAlloc[cmd->device->id][lun].nr_allocated >=
+	    TagAlloc[cmd->device->id][lun].queue_size) {
 		dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n",
-			   H_NO(cmd), cmd->device->id, cmd->device->lun);
+			   H_NO(cmd), cmd->device->id, lun);
 		return 1;
 	}
 	return 0;
@@ -385,6 +386,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, i
 
 static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
 {
+	u8 lun = cmd->device->lun;
 	SETUP_HOSTDATA(cmd->device->host);
 
 	/* If we or the target don't support tagged queuing, allocate the LUN for
@@ -393,11 +395,11 @@ static void cmd_get_tag(Scsi_Cmnd *cmd,
 	if (!should_be_tagged ||
 	    !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
 		cmd->tag = TAG_NONE;
-		hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+		hostdata->busy[cmd->device->id] |= (1 << lun);
 		dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged "
-			   "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
+			   "command\n", H_NO(cmd), cmd->device->id, lun);
 	} else {
-		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
 
 		cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
 		set_bit(cmd->tag, ta->allocated);
@@ -405,7 +407,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd,
 		dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d "
 			   "(now %d tags in use)\n",
 			   H_NO(cmd), cmd->tag, cmd->device->id,
-			   cmd->device->lun, ta->nr_allocated);
+			   lun, ta->nr_allocated);
 	}
 }
 
@@ -416,21 +418,22 @@ static void cmd_get_tag(Scsi_Cmnd *cmd,
 
 static void cmd_free_tag(Scsi_Cmnd *cmd)
 {
+	u8 lun = cmd->device->lun;
 	SETUP_HOSTDATA(cmd->device->host);
 
 	if (cmd->tag == TAG_NONE) {
-		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+		hostdata->busy[cmd->device->id] &= ~(1 << lun);
 		dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n",
-			   H_NO(cmd), cmd->device->id, cmd->device->lun);
+			   H_NO(cmd), cmd->device->id, lun);
 	} else if (cmd->tag >= MAX_TAGS) {
 		printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
 		       H_NO(cmd), cmd->tag);
 	} else {
-		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
 		clear_bit(cmd->tag, ta->allocated);
 		ta->nr_allocated--;
 		dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n",
-			   H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
+			   H_NO(cmd), cmd->tag, cmd->device->id, lun);
 	}
 }
 
@@ -713,7 +716,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *
 {
 	int i, s;
 	unsigned char *command;
-	printk("scsi%d: destination target %d, lun %d\n",
+	printk("scsi%d: destination target %d, lun %llu\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
 	printk(KERN_CONT "        command = ");
 	command = cmd->cmnd;
@@ -759,7 +762,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cm
 {
 	int i, s;
 	unsigned char *command;
-	seq_printf(m, "scsi%d: destination target %d, lun %d\n",
+	seq_printf(m, "scsi%d: destination target %d, lun %llu\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
 	seq_printf(m, "        command = ");
 	command = cmd->cmnd;
@@ -1060,12 +1063,13 @@ static void NCR5380_main(struct work_str
 #endif
 			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
 			     prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
+				u8 lun = tmp->device->lun;
 
 #if (NDEBUG & NDEBUG_LISTS)
 				if (prev != tmp)
-					printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
+					printk("MAIN tmp=%p   target=%d   busy=%d lun=%llu\n",
 					       tmp, tmp->device->id, hostdata->busy[tmp->device->id],
-					       tmp->device->lun);
+					       lun);
 #endif
 				/*  When we find one, remove it from the issue queue. */
 				/* ++guenther: possible race with Falcon locking */
@@ -1073,7 +1077,7 @@ static void NCR5380_main(struct work_str
 #ifdef SUPPORT_TAGS
 				    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
 #else
-				    !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+				    !(hostdata->busy[tmp->device->id] & (1 << lun))
 #endif
 				    ) {
 					/* ++guenther: just to be sure, this must be atomic */
@@ -1099,7 +1103,7 @@ static void NCR5380_main(struct work_str
 					 */
 					dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d "
 						    "lun %d removed from issue_queue\n",
-						    HOSTNO, tmp->device->id, tmp->device->lun);
+						    HOSTNO, tmp->device->id, lun);
 					/*
 					 * REQUEST SENSE commands are issued without tagged
 					 * queueing, even on SCSI-II devices because the
@@ -2061,7 +2065,7 @@ static void NCR5380_information_transfer
 						 * accesses to this device will use the
 						 * polled-IO. */
 						printk(KERN_NOTICE "scsi%d: switching target %d "
-							   "lun %d to slow handshake\n", HOSTNO,
+							   "lun %llu to slow handshake\n", HOSTNO,
 							   cmd->device->id, cmd->device->lun);
 						cmd->device->borken = 1;
 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
@@ -2113,7 +2117,7 @@ static void NCR5380_information_transfer
 					/* Accept message by clearing ACK */
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-					dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command "
+					dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command "
 						   "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
 
 					/* Enable reselect interrupts */
@@ -2125,7 +2129,7 @@ static void NCR5380_information_transfer
 					 */
 
 					if (!cmd->next_link) {
-						 printk(KERN_NOTICE "scsi%d: target %d lun %d "
+						 printk(KERN_NOTICE "scsi%d: target %d lun %llu "
 							"linked command complete, no next_link\n",
 							HOSTNO, cmd->device->id, cmd->device->lun);
 						sink = 1;
@@ -2138,7 +2142,7 @@ static void NCR5380_information_transfer
 					 * and don't free it! */
 					cmd->next_link->tag = cmd->tag;
 					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
-					dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request "
+					dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
 						   "done, calling scsi_done().\n",
 						   HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef NCR5380_STATS
@@ -2155,7 +2159,7 @@ static void NCR5380_information_transfer
 					/* ++guenther: possible race with Falcon locking */
 					falcon_dont_release++;
 					hostdata->connected = NULL;
-					dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d "
+					dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
 						  "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef SUPPORT_TAGS
 					cmd_free_tag(cmd);
@@ -2169,7 +2173,7 @@ static void NCR5380_information_transfer
 						/* ++Andreas: the mid level code knows about
 						   QUEUE_FULL now. */
 						TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-						dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned "
+						dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
 							   "QUEUE_FULL after %d commands\n",
 							   HOSTNO, cmd->device->id, cmd->device->lun,
 							   ta->nr_allocated);
@@ -2267,7 +2271,7 @@ static void NCR5380_information_transfer
 						cmd->device->tagged_supported = 0;
 						hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 						cmd->tag = TAG_NONE;
-						dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected "
+						dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected "
 							   "QUEUE_TAG message; tagged queuing "
 							   "disabled\n",
 							   HOSTNO, cmd->device->id, cmd->device->lun);
@@ -2284,7 +2288,7 @@ static void NCR5380_information_transfer
 					hostdata->connected = NULL;
 					hostdata->disconnected_queue = cmd;
 					local_irq_restore(flags);
-					dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was "
+					dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was "
 						  "moved from connected to the "
 						  "disconnected_queue\n", HOSTNO,
 						  cmd->device->id, cmd->device->lun);
@@ -2385,12 +2389,12 @@ static void NCR5380_information_transfer
 						printk("\n");
 					} else if (tmp != EXTENDED_MESSAGE)
 						printk(KERN_DEBUG "scsi%d: rejecting unknown "
-						       "message %02x from target %d, lun %d\n",
+						       "message %02x from target %d, lun %llu\n",
 						       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
 					else
 						printk(KERN_DEBUG "scsi%d: rejecting unknown "
 						       "extended message "
-						       "code %02x, length %d from target %d, lun %d\n",
+						       "code %02x, length %d from target %d, lun %llu\n",
 						       HOSTNO, extended_msg[1], extended_msg[0],
 						       cmd->device->id, cmd->device->lun);
 
@@ -2588,7 +2592,7 @@ static void NCR5380_reselect(struct Scsi
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
 	hostdata->connected = tmp;
-	dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+	dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
 		   HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
 	falcon_dont_release--;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_iscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_iscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_iscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_iscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi
 	stats->r2t_pdus = conn->r2t_pdus_cnt;
 	stats->digest_err = 0;
 	stats->timeout_err = 0;
-	stats->custom_length = 0;
+	stats->custom_length = 1;
 	strcpy(stats->custom[0].desc, "eh_abort_cnt");
 	stats->custom[0].value = conn->eh_abort_cnt;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_main.c linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_main.c
--- linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_main.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_main.c	2014-09-28 17:29:07.000000000 -0400
@@ -539,7 +539,7 @@ static umode_t beiscsi_eth_get_attr_visi
 }
 
 /*------------------- PCI Driver operations and data ----------------- */
-static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
+static const struct pci_device_id beiscsi_pci_id_table[] = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
@@ -3538,10 +3538,9 @@ static int be_queue_alloc(struct beiscsi
 	q->len = len;
 	q->entry_size = entry_size;
 	mem->size = len * entry_size;
-	mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma);
+	mem->va = pci_zalloc_consistent(phba->pcidev, mem->size, &mem->dma);
 	if (!mem->va)
 		return -ENOMEM;
-	memset(mem->va, 0, mem->size);
 	return 0;
 }
 
@@ -4320,9 +4319,9 @@ static int beiscsi_get_boot_info(struct
 			    "BM_%d : No boot session\n");
 		return ret;
 	}
-	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
-				sizeof(*session_resp),
-				&nonemb_cmd.dma);
+	nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev,
+					      sizeof(*session_resp),
+					      &nonemb_cmd.dma);
 	if (nonemb_cmd.va == NULL) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
@@ -4332,7 +4331,6 @@ static int beiscsi_get_boot_info(struct
 		return -ENOMEM;
 	}
 
-	memset(nonemb_cmd.va, 0, sizeof(*session_resp));
 	tag = mgmt_get_session_info(phba, s_handle,
 				    &nonemb_cmd);
 	if (!tag) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_mgmt.c linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_mgmt.c
--- linux-libre-3.16-gnu/drivers/scsi/be2iscsi/be_mgmt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/be2iscsi/be_mgmt.c	2014-09-28 17:29:07.000000000 -0400
@@ -900,13 +900,12 @@ free_cmd:
 static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
 			       int iscsi_cmd, int size)
 {
-	cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
+	cmd->va = pci_zalloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
 	if (!cmd->va) {
 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 			    "BG_%d : Failed to allocate memory for if info\n");
 		return -ENOMEM;
 	}
-	memset(cmd->va, 0, size);
 	cmd->size = size;
 	be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
 	return 0;
@@ -1015,7 +1014,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 		if (if_info->dhcp_state) {
 			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
 				    "BG_%d : DHCP Already Enabled\n");
-			return 0;
+			goto exit;
 		}
 		/* The ip_param->len is 1 in DHCP case. Setting
 		   proper IP len as this it is used while
@@ -1033,7 +1032,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 				sizeof(*reldhcp));
 
 			if (rc)
-				return rc;
+				goto exit;
 
 			reldhcp = nonemb_cmd.va;
 			reldhcp->interface_hndl = phba->interface_handle;
@@ -1044,7 +1043,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 				beiscsi_log(phba, KERN_WARNING,
 					    BEISCSI_LOG_CONFIG,
 					    "BG_%d : Failed to Delete existing dhcp\n");
-				return rc;
+				goto exit;
 			}
 		}
 	}
@@ -1054,7 +1053,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 		rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
 					   IP_ACTION_DEL);
 		if (rc)
-			return rc;
+			goto exit;
 	}
 
 	/* Delete the Gateway settings if mode change is to DHCP */
@@ -1064,7 +1063,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 		if (rc) {
 			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
 				    "BG_%d : Failed to Get Gateway Addr\n");
-			return rc;
+			goto exit;
 		}
 
 		if (gtway_addr_set.ip_addr.addr[0]) {
@@ -1076,7 +1075,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 				beiscsi_log(phba, KERN_WARNING,
 					    BEISCSI_LOG_CONFIG,
 					    "BG_%d : Failed to clear Gateway Addr Set\n");
-				return rc;
+				goto exit;
 			}
 		}
 	}
@@ -1087,7 +1086,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 			OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
 			sizeof(*dhcpreq));
 		if (rc)
-			return rc;
+			goto exit;
 
 		dhcpreq = nonemb_cmd.va;
 		dhcpreq->flags = BLOCKING;
@@ -1095,12 +1094,14 @@ int mgmt_set_ip(struct beiscsi_hba *phba
 		dhcpreq->interface_hndl = phba->interface_handle;
 		dhcpreq->ip_type = BE2_DHCP_V4;
 
-		return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+		rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
 	} else {
-		return mgmt_static_ip_modify(phba, if_info, ip_param,
+		rc = mgmt_static_ip_modify(phba, if_info, ip_param,
 					     subnet_param, IP_ACTION_ADD);
 	}
 
+exit:
+	kfree(if_info);
 	return rc;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bfa/bfad_bsg.c linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfad_bsg.c
--- linux-libre-3.16-gnu/drivers/scsi/bfa/bfad_bsg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfad_bsg.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,6 @@ int
 bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
 {
 	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
-	int	rc = 0;
 	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -34,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfa
 	if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		iocmd->status = BFA_STATUS_OK;
-		return rc;
+		return 0;
 	}
 
 	init_completion(&bfad->enable_comp);
@@ -43,21 +42,20 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfa
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->enable_comp);
 
-	return rc;
+	return 0;
 }
 
 int
 bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
 {
 	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
-	int	rc = 0;
 	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		iocmd->status = BFA_STATUS_OK;
-		return rc;
+		return 0;
 	}
 
 	if (bfad->disable_active) {
@@ -74,7 +72,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bf
 	bfad->disable_active = BFA_FALSE;
 	iocmd->status = BFA_STATUS_OK;
 
-	return rc;
+	return 0;
 }
 
 static int
@@ -3270,13 +3268,13 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, vo
 	/* Allocate dma coherent memory */
 	buf_info = buf_base;
 	buf_info->size = payload_len;
-	buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
-					&buf_info->phys, GFP_KERNEL);
+	buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
+					     buf_info->size, &buf_info->phys,
+					     GFP_KERNEL);
 	if (!buf_info->virt)
 		goto out_free_mem;
 
 	/* copy the linear bsg buffer to buf_info */
-	memset(buf_info->virt, 0, buf_info->size);
 	memcpy(buf_info->virt, payload_kbuf, buf_info->size);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bfa/bfad.c linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfad.c
--- linux-libre-3.16-gnu/drivers/scsi/bfa/bfad.c	2014-08-07 04:59:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfad.c	2014-09-28 21:42:16.000000000 -0400
@@ -1217,7 +1217,7 @@ bfad_install_msix_handler(struct bfad_s
 int
 bfad_setup_intr(struct bfad_s *bfad)
 {
-	int error = 0;
+	int error;
 	u32 mask = 0, i, num_bit = 0, max_bit = 0;
 	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
 	struct pci_dev *pdev = bfad->pcidev;
@@ -1232,34 +1232,24 @@ bfad_setup_intr(struct bfad_s *bfad)
 	if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
 	   (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
 
-		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
-		if (error) {
-			/* In CT1 & CT2, try to allocate just one vector */
-			if (bfa_asic_id_ctc(pdev->device)) {
-				printk(KERN_WARNING "bfa %s: trying one msix "
-				       "vector failed to allocate %d[%d]\n",
-				       bfad->pci_name, bfad->nvec, error);
-				bfad->nvec = 1;
-				error = pci_enable_msix(bfad->pcidev,
-						msix_entries, bfad->nvec);
-			}
+		error = pci_enable_msix_exact(bfad->pcidev,
+					      msix_entries, bfad->nvec);
+		/* In CT1 & CT2, try to allocate just one vector */
+		if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) {
+			printk(KERN_WARNING "bfa %s: trying one msix "
+			       "vector failed to allocate %d[%d]\n",
+			       bfad->pci_name, bfad->nvec, error);
+			bfad->nvec = 1;
+			error = pci_enable_msix_exact(bfad->pcidev,
+						      msix_entries, 1);
+		}
 
-			/*
-			 * Only error number of vector is available.
-			 * We don't have a mechanism to map multiple
-			 * interrupts into one vector, so even if we
-			 * can try to request less vectors, we don't
-			 * know how to associate interrupt events to
-			 *  vectors. Linux doesn't duplicate vectors
-			 * in the MSIX table for this case.
-			 */
-			if (error) {
-				printk(KERN_WARNING "bfad%d: "
-				       "pci_enable_msix failed (%d), "
-				       "use line based.\n",
-					bfad->inst_no, error);
-				goto line_based;
-			}
+		if (error) {
+			printk(KERN_WARNING "bfad%d: "
+			       "pci_enable_msix_exact failed (%d), "
+			       "use line based.\n",
+				bfad->inst_no, error);
+			goto line_based;
 		}
 
 		/* Disable INTX in MSI-X mode */
@@ -1279,20 +1269,18 @@ bfad_setup_intr(struct bfad_s *bfad)
 
 		bfad->bfad_flags |= BFAD_MSIX_ON;
 
-		return error;
+		return 0;
 	}
 
 line_based:
-	error = 0;
-	if (request_irq
-	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
-	     BFAD_DRIVER_NAME, bfad) != 0) {
-		/* Enable interrupt handler failed */
-		return 1;
-	}
+	error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx,
+			    BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad);
+	if (error)
+		return error;
+
 	bfad->bfad_flags |= BFAD_INTX_ON;
 
-	return error;
+	return 0;
 }
 
 void
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bfa/bfa_fcs.c linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfa_fcs.c
--- linux-libre-3.16-gnu/drivers/scsi/bfa/bfa_fcs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfa_fcs.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,7 +81,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, st
 	bfa->fcs = BFA_TRUE;
 	fcbuild_init();
 
-	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
 		mod = &fcs_modules[i];
 		if (mod->attach)
 			mod->attach(fcs);
@@ -97,7 +97,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs)
 	int	i;
 	struct bfa_fcs_mod_s  *mod;
 
-	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
 		mod = &fcs_modules[i];
 		if (mod->modinit)
 			mod->modinit(fcs);
@@ -184,7 +184,7 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
 
 	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
 
-	nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+	nmods = ARRAY_SIZE(fcs_modules);
 
 	for (i = 0; i < nmods; i++) {
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bfa/bfa_ioc.h linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfa_ioc.h
--- linux-libre-3.16-gnu/drivers/scsi/bfa/bfa_ioc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bfa/bfa_ioc.h	2014-09-28 17:29:07.000000000 -0400
@@ -72,7 +72,7 @@ struct bfa_sge_s {
 } while (0)
 
 #define bfa_swap_words(_x)  (	\
-	((_x) << 32) | ((_x) >> 32))
+	((u64)(_x) << 32) | ((u64)(_x) >> 32))
 
 #ifdef __BIG_ENDIAN
 #define bfa_sge_to_be(_x)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,16 @@
+/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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 __57XX_FCOE_HSI_LINUX_LE__
 #define __57XX_FCOE_HSI_LINUX_LE__
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,16 @@
+/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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 __BNX2FC_CONSTANTS_H_
 #define __BNX2FC_CONSTANTS_H_
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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 "bnx2fc.h"
 
 void BNX2FC_IO_DBG(const struct bnx2fc_cmd *io_req, const char *fmt, ...)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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 __BNX2FC_DEBUG__
 #define __BNX2FC_DEBUG__
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,10 @@
 /*
- * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains helper routines that handle ELS requests
  * and responses.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,9 +1,10 @@
-/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains the code that interacts with libfc, libfcoe,
  * cnic modules to create FCoE instances, send/receive non-offloaded
  * FIP/FCoE packets, listen to link events etc.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
@@ -26,12 +27,12 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, b
 
 
 static char version[] =
-		"Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+		"QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \
 		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -692,7 +693,7 @@ static int bnx2fc_shost_config(struct fc
 	if (!lport->vport)
 		fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
 	snprintf(fc_host_symbolic_name(lport->host), 256,
-		 "%s (Broadcom %s) v%s over %s",
+		 "%s (QLogic %s) v%s over %s",
 		BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION,
 		interface->netdev->name);
 
@@ -2775,7 +2776,7 @@ static struct fc_function_template bnx2f
  */
 static struct scsi_host_template bnx2fc_shost_template = {
 	.module			= THIS_MODULE,
-	.name			= "Broadcom Offload FCoE Initiator",
+	.name			= "QLogic Offload FCoE Initiator",
 	.queuecommand		= bnx2fc_queuecommand,
 	.eh_abort_handler	= bnx2fc_eh_abort,	  /* abts */
 	.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,7 @@
-#ifndef _BNX2FC_H_
-#define _BNX2FC_H_
-/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
@@ -11,6 +10,8 @@
  * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
  */
 
+#ifndef _BNX2FC_H_
+#define _BNX2FC_H_
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,9 @@
-/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver.
  * This file contains the code that low level functions that interact
  * with 57712 FCoE firmware.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,8 @@
-/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver.
  * IO manager and SCSI IO processing.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
@@ -1450,9 +1451,9 @@ static void bnx2fc_lun_reset_cmpl(struct
 	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
 	struct bnx2fc_rport *tgt = io_req->tgt;
 	struct bnx2fc_cmd *cmd, *tmp;
-	int tm_lun = sc_cmd->device->lun;
+	u64 tm_lun = sc_cmd->device->lun;
+	u64 lun;
 	int rc = 0;
-	int lun;
 
 	/* called with tgt_lock held */
 	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,9 @@
-/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
  * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic 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
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2fc/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/bnx2fc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2fc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,13 @@
 config SCSI_BNX2X_FCOE
-	tristate "Broadcom NetXtreme II FCoE support"
+	tristate "QLogic NetXtreme II FCoE support"
 	depends on PCI
+	depends on (IPV6 || IPV6=n)
+	depends on LIBFC
+	depends on LIBFCOE
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_BROADCOM
-	select LIBFC
-	select LIBFCOE
 	select CNIC
 	---help---
-	This driver supports FCoE offload for the Broadcom NetXtreme II
+	This driver supports FCoE offload for the QLogic NetXtreme II
 	devices.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/57xx_iscsi_constants.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/57xx_iscsi_constants.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/57xx_iscsi_constants.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/57xx_iscsi_constants.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
+/* 57xx_iscsi_constants.h: QLogic NetXtreme II iSCSI HSI
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 #ifndef __57XX_ISCSI_CONSTANTS_H_
 #define __57XX_ISCSI_CONSTANTS_H_
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/57xx_iscsi_hsi.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/57xx_iscsi_hsi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/57xx_iscsi_hsi.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
+/* 57xx_iscsi_hsi.h: QLogic NetXtreme II iSCSI HSI.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 #ifndef __57XX_ISCSI_HSI_LINUX_LE__
 #define __57XX_ISCSI_HSI_LINUX_LE__
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i.h linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i.h
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,15 +1,17 @@
-/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.h: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #ifndef _BNX2I_H_
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,15 +1,17 @@
-/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_hwi.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include <linux/gfp.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_init.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,15 +1,17 @@
-/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include "bnx2i.h"
@@ -18,18 +20,18 @@ static struct list_head adapter_list = L
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.7.6.2"
-#define DRV_MODULE_RELDATE	"Jun 06, 2013"
+#define DRV_MODULE_VERSION	"2.7.10.1"
+#define DRV_MODULE_RELDATE	"Jul 16, 2014"
 
 static char version[] =
-		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
+		"QLogic NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
 		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
 	      "Eddie Wai <eddie.wai@broadcom.com>");
 
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/57710/57711/57712"
 		   "/57800/57810/57840 iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,16 +1,18 @@
 /*
- * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
+ * bnx2i_iscsi.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2006 - 2013 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include <linux/slab.h>
@@ -1643,12 +1645,11 @@ static void bnx2i_conn_get_stats(struct
 	stats->r2t_pdus = conn->r2t_pdus_cnt;
 	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-	stats->custom_length = 3;
-	strcpy(stats->custom[2].desc, "eh_abort_cnt");
-	stats->custom[2].value = conn->eh_abort_cnt;
 	stats->digest_err = 0;
 	stats->timeout_err = 0;
-	stats->custom_length = 0;
+	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+	stats->custom[0].value = conn->eh_abort_cnt;
+	stats->custom_length = 1;
 }
 
 
@@ -2249,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int
  */
 static struct scsi_host_template bnx2i_host_template = {
 	.module			= THIS_MODULE,
-	.name			= "Broadcom Offload iSCSI Initiator",
+	.name			= "QLogic Offload iSCSI Initiator",
 	.proc_name		= "bnx2i",
 	.queuecommand		= iscsi_queuecommand,
 	.eh_abort_handler	= iscsi_eh_abort,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_sysfs.c linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_sysfs.c
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/bnx2i_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/bnx2i_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,13 +1,15 @@
-/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_sysfs.c: QLogic NetXtreme II iSCSI driver.
  *
  * Copyright (c) 2004 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
  */
 
 #include "bnx2i.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/bnx2i/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/bnx2i/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/bnx2i/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,12 +1,13 @@
 config SCSI_BNX2_ISCSI
-	tristate "Broadcom NetXtreme II iSCSI support"
+	tristate "QLogic NetXtreme II iSCSI support"
 	depends on NET
 	depends on PCI
+	depends on (IPV6 || IPV6=n)
 	select SCSI_ISCSI_ATTRS
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_BROADCOM
 	select CNIC
 	---help---
-	This driver supports iSCSI offload for the Broadcom NetXtreme II
+	This driver supports iSCSI offload for the QLogic NetXtreme II
 	devices.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/BusLogic.c linux-libre-3.17-rc7-gnu/drivers/scsi/BusLogic.c
--- linux-libre-3.16-gnu/drivers/scsi/BusLogic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/BusLogic.c	2014-09-28 17:29:07.000000000 -0400
@@ -3893,7 +3893,7 @@ __setup("BusLogic=", blogic_setup);
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ }
 };*/
-static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = {
+static const struct pci_device_id blogic_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ch.c linux-libre-3.17-rc7-gnu/drivers/scsi/ch.c
--- linux-libre-3.16-gnu/drivers/scsi/ch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ch.c	2014-09-28 17:29:07.000000000 -0400
@@ -84,15 +84,19 @@ static const char * vendor_labels[CH_TYP
 };
 // module_param_string_array(vendor_labels, NULL, 0444);
 
+#define ch_printk(prefix, ch, fmt, a...) \
+	sdev_printk(prefix, (ch)->device, "[%s] " fmt, \
+		    (ch)->name, ##a)
+
 #define DPRINTK(fmt, arg...)						\
 do {									\
 	if (debug)							\
-		printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg);		\
+		ch_printk(KERN_DEBUG, ch, fmt, ##arg);			\
 } while (0)
 #define VPRINTK(level, fmt, arg...)					\
 do {									\
 	if (verbose)							\
-		printk(level "%s: " fmt, ch->name, ##arg);		\
+		ch_printk(level, ch, fmt, ##arg);			\
 } while (0)
 
 /* ------------------------------------------------------------------- */
@@ -196,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned ch
 		__scsi_print_command(cmd);
 	}
 
-        result = scsi_execute_req(ch->device, cmd, direction, buffer,
+	result = scsi_execute_req(ch->device, cmd, direction, buffer,
 				  buflength, &sshdr, timeout * HZ,
 				  MAX_RETRIES, NULL);
 
@@ -247,7 +251,7 @@ ch_read_element_status(scsi_changer *ch,
  retry:
 	memset(cmd,0,sizeof(cmd));
 	cmd[0] = READ_ELEMENT_STATUS;
-	cmd[1] = (ch->device->lun << 5) |
+	cmd[1] = ((ch->device->lun & 0x7) << 5) |
 		(ch->voltags ? 0x10 : 0) |
 		ch_elem_to_typecode(ch,elem);
 	cmd[2] = (elem >> 8) & 0xff;
@@ -283,7 +287,7 @@ ch_init_elem(scsi_changer *ch)
 	VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n");
 	memset(cmd,0,sizeof(cmd));
 	cmd[0] = INITIALIZE_ELEMENT_STATUS;
-	cmd[1] = ch->device->lun << 5;
+	cmd[1] = (ch->device->lun & 0x7) << 5;
 	err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
 	VPRINTK(KERN_INFO, "... finished\n");
 	return err;
@@ -303,7 +307,7 @@ ch_readconfig(scsi_changer *ch)
 
 	memset(cmd,0,sizeof(cmd));
 	cmd[0] = MODE_SENSE;
-	cmd[1] = ch->device->lun << 5;
+	cmd[1] = (ch->device->lun & 0x7) << 5;
 	cmd[2] = 0x1d;
 	cmd[4] = 255;
 	result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
@@ -428,7 +432,7 @@ ch_position(scsi_changer *ch, u_int tran
 		trans = ch->firsts[CHET_MT];
 	memset(cmd,0,sizeof(cmd));
 	cmd[0]  = POSITION_TO_ELEMENT;
-	cmd[1]  = ch->device->lun << 5;
+	cmd[1]  = (ch->device->lun & 0x7) << 5;
 	cmd[2]  = (trans >> 8) & 0xff;
 	cmd[3]  =  trans       & 0xff;
 	cmd[4]  = (elem  >> 8) & 0xff;
@@ -447,7 +451,7 @@ ch_move(scsi_changer *ch, u_int trans, u
 		trans = ch->firsts[CHET_MT];
 	memset(cmd,0,sizeof(cmd));
 	cmd[0]  = MOVE_MEDIUM;
-	cmd[1]  = ch->device->lun << 5;
+	cmd[1]  = (ch->device->lun & 0x7) << 5;
 	cmd[2]  = (trans >> 8) & 0xff;
 	cmd[3]  =  trans       & 0xff;
 	cmd[4]  = (src   >> 8) & 0xff;
@@ -470,7 +474,7 @@ ch_exchange(scsi_changer *ch, u_int tran
 		trans = ch->firsts[CHET_MT];
 	memset(cmd,0,sizeof(cmd));
 	cmd[0]  = EXCHANGE_MEDIUM;
-	cmd[1]  = ch->device->lun << 5;
+	cmd[1]  = (ch->device->lun & 0x7) << 5;
 	cmd[2]  = (trans >> 8) & 0xff;
 	cmd[3]  =  trans       & 0xff;
 	cmd[4]  = (src   >> 8) & 0xff;
@@ -518,7 +522,7 @@ ch_set_voltag(scsi_changer *ch, u_int el
 		elem, tag);
 	memset(cmd,0,sizeof(cmd));
 	cmd[0]  = SEND_VOLUME_TAG;
-	cmd[1] = (ch->device->lun << 5) |
+	cmd[1] = ((ch->device->lun & 0x7) << 5) |
 		ch_elem_to_typecode(ch,elem);
 	cmd[2] = (elem >> 8) & 0xff;
 	cmd[3] = elem        & 0xff;
@@ -754,7 +758,7 @@ static long ch_ioctl(struct file *file,
 	voltag_retry:
 		memset(ch_cmd, 0, sizeof(ch_cmd));
 		ch_cmd[0] = READ_ELEMENT_STATUS;
-		ch_cmd[1] = (ch->device->lun << 5) |
+		ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
 			(ch->voltags ? 0x10 : 0) |
 			ch_elem_to_typecode(ch,elem);
 		ch_cmd[2] = (elem >> 8) & 0xff;
@@ -924,8 +928,8 @@ static int ch_probe(struct device *dev)
 				  MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
 				  "s%s", ch->name);
 	if (IS_ERR(class_dev)) {
-		printk(KERN_WARNING "ch%d: device_create failed\n",
-		       ch->minor);
+		sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n",
+			    ch->minor);
 		ret = PTR_ERR(class_dev);
 		goto remove_idr;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_init.c
--- linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_init.c	2014-08-07 04:59:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_init.c	2014-09-28 21:42:21.000000000 -0400
@@ -1167,7 +1167,7 @@ static struct pci_error_handlers csio_er
 	.resume		= csio_pci_resume,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
+static const struct pci_device_id csio_pci_tbl[] = {
 	CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0),        /* T4 DEBUG FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0),		/* T420CR FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0),		/* T422CR FCOE */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_scsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_scsi.c
--- linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1657,7 +1657,7 @@ csio_scsi_err_handler(struct csio_hw *hw
 	case FW_SCSI_UNDER_FLOW_ERR:
 		csio_warn(hw,
 			  "Under-flow error,cmnd:0x%x expected"
-			  " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n",
+			  " len:0x%x resid:0x%x lun:0x%llx ssn:0x%x\n",
 			  cmnd->cmnd[0], scsi_bufflen(cmnd),
 			  scsi_get_resid(cmnd), cmnd->device->lun,
 			  rn->flowid);
@@ -1957,7 +1957,7 @@ csio_eh_abort_handler(struct scsi_cmnd *
 
 	csio_dbg(hw,
 		 "Request to abort ioreq:%p cmd:%p cdb:%08llx"
-		 " ssni:0x%x lun:%d iq:0x%x\n",
+		 " ssni:0x%x lun:%llu iq:0x%x\n",
 		ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid,
 		cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx));
 
@@ -2015,13 +2015,13 @@ inval_scmnd:
 	/* FW successfully aborted the request */
 	if (host_byte(cmnd->result) == DID_REQUEUE) {
 		csio_info(hw,
-			"Aborted SCSI command to (%d:%d) serial#:0x%lx\n",
+			"Aborted SCSI command to (%d:%llu) serial#:0x%lx\n",
 			cmnd->device->id, cmnd->device->lun,
 			cmnd->serial_number);
 		return SUCCESS;
 	} else {
 		csio_info(hw,
-			"Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n",
+			"Failed to abort SCSI command, (%d:%llu) serial#:0x%lx\n",
 			cmnd->device->id, cmnd->device->lun,
 			cmnd->serial_number);
 		return FAILED;
@@ -2100,13 +2100,13 @@ csio_eh_lun_reset_handler(struct scsi_cm
 	if (!rn)
 		goto fail;
 
-	csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n",
+	csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n",
 		      cmnd->device->lun, rn->flowid, rn->scsi_id);
 
 	if (!csio_is_lnode_ready(ln)) {
 		csio_err(hw,
 			 "LUN reset cannot be issued on non-ready"
-			 " local node vnpi:0x%x (LUN:%d)\n",
+			 " local node vnpi:0x%x (LUN:%llu)\n",
 			 ln->vnp_flowid, cmnd->device->lun);
 		goto fail;
 	}
@@ -2126,7 +2126,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 	if (fc_remote_port_chkready(rn->rport)) {
 		csio_err(hw,
 			 "LUN reset cannot be issued on non-ready"
-			 " remote node ssni:0x%x (LUN:%d)\n",
+			 " remote node ssni:0x%x (LUN:%llu)\n",
 			 rn->flowid, cmnd->device->lun);
 		goto fail;
 	}
@@ -2168,7 +2168,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 	sld.level = CSIO_LEV_LUN;
 	sld.lnode = ioreq->lnode;
 	sld.rnode = ioreq->rnode;
-	sld.oslun = (uint64_t)cmnd->device->lun;
+	sld.oslun = cmnd->device->lun;
 
 	spin_lock_irqsave(&hw->lock, flags);
 	/* Kick off TM SM on the ioreq */
@@ -2190,7 +2190,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 
 	/* LUN reset timed-out */
 	if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
-		csio_err(hw, "LUN reset (%d:%d) timed out\n",
+		csio_err(hw, "LUN reset (%d:%llu) timed out\n",
 			 cmnd->device->id, cmnd->device->lun);
 
 		spin_lock_irq(&hw->lock);
@@ -2203,7 +2203,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 
 	/* LUN reset returned, check cached status */
 	if (cmnd->SCp.Status != FW_SUCCESS) {
-		csio_err(hw, "LUN reset failed (%d:%d), status: %d\n",
+		csio_err(hw, "LUN reset failed (%d:%llu), status: %d\n",
 			 cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status);
 		goto fail;
 	}
@@ -2223,7 +2223,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 	/* Aborts may have timed out */
 	if (retval != 0) {
 		csio_err(hw,
-			 "Attempt to abort I/Os during LUN reset of %d"
+			 "Attempt to abort I/Os during LUN reset of %llu"
 			 " returned %d\n", cmnd->device->lun, retval);
 		/* Return I/Os back to active_q */
 		spin_lock_irq(&hw->lock);
@@ -2234,7 +2234,7 @@ csio_eh_lun_reset_handler(struct scsi_cm
 
 	CSIO_INC_STATS(rn, n_lun_rst);
 
-	csio_info(hw, "LUN reset occurred (%d:%d)\n",
+	csio_info(hw, "LUN reset occurred (%d:%llu)\n",
 		  cmnd->device->id, cmnd->device->lun);
 
 	return SUCCESS;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_wr.c linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_wr.c
--- linux-libre-3.16-gnu/drivers/scsi/csiostor/csio_wr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/csio_wr.c	2014-09-28 17:29:07.000000000 -0400
@@ -232,7 +232,7 @@ csio_wr_alloc_q(struct csio_hw *hw, uint
 
 	q = wrm->q_arr[free_idx];
 
-	q->vstart = pci_alloc_consistent(hw->pdev, qsz, &q->pstart);
+	q->vstart = pci_zalloc_consistent(hw->pdev, qsz, &q->pstart);
 	if (!q->vstart) {
 		csio_err(hw,
 			 "Failed to allocate DMA memory for "
@@ -240,12 +240,6 @@ csio_wr_alloc_q(struct csio_hw *hw, uint
 		return -1;
 	}
 
-	/*
-	 * We need to zero out the contents, importantly for ingress,
-	 * since we start with a generatiom bit of 1 for ingress.
-	 */
-	memset(q->vstart, 0, qsz);
-
 	q->type		= type;
 	q->owner	= owner;
 	q->pidx		= q->cidx = q->inc_idx = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/csiostor/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/csiostor/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/csiostor/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,7 @@
 config SCSI_CHELSIO_FCOE
 	tristate "Chelsio Communications FCoE support"
 	depends on PCI && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	select FW_LOADER
 	help
 	  This driver supports FCoE Offload functionality over
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 config SCSI_CXGB3_ISCSI
 	tristate "Chelsio T3 iSCSI support"
-	depends on PCI && INET
+	depends on PCI && INET && (IPV6 || IPV6=n)
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_CHELSIO
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
--- linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <net/tcp.h>
 #include <net/dst.h>
 #include <linux/netdevice.h>
+#include <net/addrconf.h>
 
 #include "t4_regs.h"
 #include "t4_msg.h"
@@ -150,6 +151,7 @@ static struct scsi_transport_template *c
  * The section below implments CPLs that related to iscsi tcp connection
  * open/close/abort and data send/receive.
  */
+
 #define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
 #define RCV_BUFSIZ_MASK		0x3FFU
 #define MAX_IMM_TX_PKT_LEN	128
@@ -179,6 +181,7 @@ static void send_act_open_req(struct cxg
 				struct l2t_entry *e)
 {
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	int t4 = is_t4(lldi->adapter_type);
 	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
 	unsigned long long opt0;
 	unsigned int opt2;
@@ -248,6 +251,97 @@ static void send_act_open_req(struct cxg
 	}
 
 	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+	pr_info_ipaddr("t%d csk 0x%p,%u,0x%lx,%u, rss_qid %u.\n",
+		       (&csk->saddr), (&csk->daddr), t4 ? 4 : 5, csk,
+		       csk->state, csk->flags, csk->atid, csk->rss_qid);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_act_open_req6(struct cxgbi_sock *csk, struct sk_buff *skb,
+			       struct l2t_entry *e)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	int t4 = is_t4(lldi->adapter_type);
+	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+	unsigned long long opt0;
+	unsigned int opt2;
+	unsigned int qid_atid = ((unsigned int)csk->atid) |
+				 (((unsigned int)csk->rss_qid) << 14);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		ULP_MODE(ULP_MODE_ISCSI) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		RX_FC_DISABLE |
+		RSS_QUEUE(csk->rss_qid);
+
+	if (t4) {
+		struct cpl_act_open_req6 *req =
+			    (struct cpl_act_open_req6 *)skb->head;
+
+		INIT_TP_WR(req, 0);
+		OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+							    qid_atid));
+		req->local_port = csk->saddr6.sin6_port;
+		req->peer_port = csk->daddr6.sin6_port;
+
+		req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+		req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+								    8);
+		req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+		req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+								    8);
+
+		req->opt0 = cpu_to_be64(opt0);
+
+		opt2 |= RX_FC_VALID;
+		req->opt2 = cpu_to_be32(opt2);
+
+		req->params = cpu_to_be32(cxgb4_select_ntuple(
+					  csk->cdev->ports[csk->port_id],
+					  csk->l2t));
+	} else {
+		struct cpl_t5_act_open_req6 *req =
+				(struct cpl_t5_act_open_req6 *)skb->head;
+
+		INIT_TP_WR(req, 0);
+		OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+							    qid_atid));
+		req->local_port = csk->saddr6.sin6_port;
+		req->peer_port = csk->daddr6.sin6_port;
+		req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+		req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+									8);
+		req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+		req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+									8);
+		req->opt0 = cpu_to_be64(opt0);
+
+		opt2 |= T5_OPT_2_VALID;
+		req->opt2 = cpu_to_be32(opt2);
+
+		req->params = cpu_to_be64(V_FILTER_TUPLE(cxgb4_select_ntuple(
+					  csk->cdev->ports[csk->port_id],
+					  csk->l2t)));
+	}
+
+	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+	pr_info("t%d csk 0x%p,%u,0x%lx,%u, [%pI6]:%u-[%pI6]:%u, rss_qid %u.\n",
+		t4 ? 4 : 5, csk, csk->state, csk->flags, csk->atid,
+		&csk->saddr6.sin6_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr6.sin6_addr, ntohs(csk->daddr.sin_port),
+		csk->rss_qid);
+
 	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
 }
 
@@ -586,9 +680,11 @@ static void do_act_establish(struct cxgb
 		goto rel_skb;
 	}
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
-		csk, csk->state, csk->flags, tid, atid, rcv_isn);
+	pr_info_ipaddr("atid 0x%x, tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       atid, tid, csk, csk->state, csk->flags, rcv_isn);
+
+	module_put(THIS_MODULE);
 
 	cxgbi_sock_get(csk);
 	csk->tid = tid;
@@ -663,6 +759,9 @@ static void csk_act_open_retry_timer(uns
 	struct sk_buff *skb;
 	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	void (*send_act_open_func)(struct cxgbi_sock *, struct sk_buff *,
+				   struct l2t_entry *);
+	int t4 = is_t4(lldi->adapter_type), size, size6;
 
 	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
 		"csk 0x%p,%u,0x%lx,%u.\n",
@@ -670,20 +769,35 @@ static void csk_act_open_retry_timer(uns
 
 	cxgbi_sock_get(csk);
 	spin_lock_bh(&csk->lock);
-	skb = alloc_wr(is_t4(lldi->adapter_type) ?
-				sizeof(struct cpl_act_open_req) :
-				sizeof(struct cpl_t5_act_open_req),
-			0, GFP_ATOMIC);
+
+	if (t4) {
+		size = sizeof(struct cpl_act_open_req);
+		size6 = sizeof(struct cpl_act_open_req6);
+	} else {
+		size = sizeof(struct cpl_t5_act_open_req);
+		size6 = sizeof(struct cpl_t5_act_open_req6);
+	}
+
+	if (csk->csk_family == AF_INET) {
+		send_act_open_func = send_act_open_req;
+		skb = alloc_wr(size, 0, GFP_ATOMIC);
+	} else {
+		send_act_open_func = send_act_open_req6;
+		skb = alloc_wr(size6, 0, GFP_ATOMIC);
+	}
+
 	if (!skb)
 		cxgbi_sock_fail_act_open(csk, -ENOMEM);
 	else {
 		skb->sk = (struct sock *)csk;
 		t4_set_arp_err_handler(skb, csk,
-					cxgbi_sock_act_open_req_arp_failure);
-		send_act_open_req(csk, skb, csk->l2t);
+				       cxgbi_sock_act_open_req_arp_failure);
+		send_act_open_func(csk, skb, csk->l2t);
 	}
+
 	spin_unlock_bh(&csk->lock);
 	cxgbi_sock_put(csk);
+
 }
 
 static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
@@ -703,10 +817,9 @@ static void do_act_open_rpl(struct cxgbi
 		goto rel_skb;
 	}
 
-	pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
-		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
-		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
-		atid, tid, status, csk, csk->state, csk->flags);
+	pr_info_ipaddr("tid %u/%u, status %u.\n"
+		       "csk 0x%p,%u,0x%lx. ", (&csk->saddr), (&csk->daddr),
+		       atid, tid, status, csk, csk->state, csk->flags);
 
 	if (status == CPL_ERR_RTX_NEG_ADVICE)
 		goto rel_skb;
@@ -746,9 +859,9 @@ static void do_peer_close(struct cxgbi_d
 		pr_err("can't find connection for tid %u.\n", tid);
 		goto rel_skb;
 	}
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx,%u.\n",
-		csk, csk->state, csk->flags, csk->tid);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid);
 	cxgbi_sock_rcv_peer_close(csk);
 rel_skb:
 	__kfree_skb(skb);
@@ -767,9 +880,9 @@ static void do_close_con_rpl(struct cxgb
 		pr_err("can't find connection for tid %u.\n", tid);
 		goto rel_skb;
 	}
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx,%u.\n",
-		csk, csk->state, csk->flags, csk->tid);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid);
 	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
 rel_skb:
 	__kfree_skb(skb);
@@ -808,9 +921,9 @@ static void do_abort_req_rss(struct cxgb
 		goto rel_skb;
 	}
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
-		csk, csk->state, csk->flags, csk->tid, req->status);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid, req->status);
 
 	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
 	    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
@@ -851,10 +964,10 @@ static void do_abort_rpl_rss(struct cxgb
 	if (!csk)
 		goto rel_skb;
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
-		rpl->status, csk, csk ? csk->state : 0,
-		csk ? csk->flags : 0UL);
+	if (csk)
+		pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+			       (&csk->saddr), (&csk->daddr), csk,
+			       csk->state, csk->flags, csk->tid, rpl->status);
 
 	if (rpl->status == CPL_ERR_ABORT_FAILED)
 		goto rel_skb;
@@ -1163,15 +1276,35 @@ static int init_act_open(struct cxgbi_so
 	struct cxgbi_device *cdev = csk->cdev;
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
 	struct net_device *ndev = cdev->ports[csk->port_id];
-	struct port_info *pi = netdev_priv(ndev);
 	struct sk_buff *skb = NULL;
-	struct neighbour *n;
+	struct neighbour *n = NULL;
+	void *daddr;
 	unsigned int step;
+	unsigned int size, size6;
+	int t4 = is_t4(lldi->adapter_type);
 
 	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
 		"csk 0x%p,%u,0x%lx,%u.\n",
 		csk, csk->state, csk->flags, csk->tid);
 
+	if (csk->csk_family == AF_INET)
+		daddr = &csk->daddr.sin_addr.s_addr;
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (csk->csk_family == AF_INET6)
+		daddr = &csk->daddr6.sin6_addr;
+#endif
+	else {
+		pr_err("address family 0x%x not supported\n", csk->csk_family);
+		goto rel_resource;
+	}
+
+	n = dst_neigh_lookup(csk->dst, daddr);
+
+	if (!n) {
+		pr_err("%s, can't get neighbour of csk->dst.\n", ndev->name);
+		goto rel_resource;
+	}
+
 	csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
 	if (csk->atid < 0) {
 		pr_err("%s, NO atid available.\n", ndev->name);
@@ -1192,10 +1325,19 @@ static int init_act_open(struct cxgbi_so
 	}
 	cxgbi_sock_get(csk);
 
-	skb = alloc_wr(is_t4(lldi->adapter_type) ?
-				sizeof(struct cpl_act_open_req) :
-				sizeof(struct cpl_t5_act_open_req),
-			0, GFP_ATOMIC);
+	if (t4) {
+		size = sizeof(struct cpl_act_open_req);
+		size6 = sizeof(struct cpl_act_open_req6);
+	} else {
+		size = sizeof(struct cpl_t5_act_open_req);
+		size6 = sizeof(struct cpl_t5_act_open_req6);
+	}
+
+	if (csk->csk_family == AF_INET)
+		skb = alloc_wr(size, 0, GFP_NOIO);
+	else
+		skb = alloc_wr(size6, 0, GFP_NOIO);
+
 	if (!skb)
 		goto rel_resource;
 	skb->sk = (struct sock *)csk;
@@ -1211,19 +1353,27 @@ static int init_act_open(struct cxgbi_so
 	csk->txq_idx = cxgb4_port_idx(ndev) * step;
 	step = lldi->nrxq / lldi->nchan;
 	csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
-	csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+	csk->wr_cred = lldi->wr_cred -
+		       DIV_ROUND_UP(sizeof(struct cpl_abort_req), 16);
+	csk->wr_max_cred = csk->wr_cred;
 	csk->wr_una_cred = 0;
 	cxgbi_sock_reset_wr_list(csk);
 	csk->err = 0;
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
-		csk, pi->port_id, ndev->name, csk->tx_chan,
-		csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
-		csk->smac_idx);
 
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u,%u,%u, mtu %u,%u, smac %u.\n",
+		       (&csk->saddr), (&csk->daddr), csk, csk->state,
+		       csk->flags, csk->tx_chan, csk->txq_idx, csk->rss_qid,
+		       csk->mtu, csk->mss_idx, csk->smac_idx);
+
+	/* must wait for either a act_open_rpl or act_open_establish */
+	try_module_get(THIS_MODULE);
 	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
-	send_act_open_req(csk, skb, csk->l2t);
+	if (csk->csk_family == AF_INET)
+		send_act_open_req(csk, skb, csk->l2t);
+	else
+		send_act_open_req6(csk, skb, csk->l2t);
 	neigh_release(n);
+
 	return 0;
 
 rel_resource:
@@ -1234,8 +1384,6 @@ rel_resource:
 	return -EINVAL;
 }
 
-#define CPL_ISCSI_DATA		0xB2
-#define CPL_RX_ISCSI_DDP	0x49
 cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
 	[CPL_ACT_ESTABLISH] = do_act_establish,
 	[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
@@ -1487,6 +1635,129 @@ static int cxgb4i_ddp_init(struct cxgbi_
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
+static int cxgbi_inet6addr_handler(struct notifier_block *this,
+				   unsigned long event, void *data)
+{
+	struct inet6_ifaddr *ifa = data;
+	struct net_device *event_dev = ifa->idev->dev;
+	struct cxgbi_device *cdev;
+	int ret = NOTIFY_DONE;
+
+	if (event_dev->priv_flags & IFF_802_1Q_VLAN)
+		event_dev = vlan_dev_real_dev(event_dev);
+
+	cdev = cxgbi_device_find_by_netdev(event_dev, NULL);
+
+	if (!cdev)
+		return ret;
+
+	switch (event) {
+	case NETDEV_UP:
+		ret = cxgb4_clip_get(event_dev,
+				     (const struct in6_addr *)
+				     ((ifa)->addr.s6_addr));
+		if (ret < 0)
+			return ret;
+
+		ret = NOTIFY_OK;
+		break;
+
+	case NETDEV_DOWN:
+		cxgb4_clip_release(event_dev,
+				   (const struct in6_addr *)
+				   ((ifa)->addr.s6_addr));
+		ret = NOTIFY_OK;
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static struct notifier_block cxgbi_inet6addr_notifier = {
+	.notifier_call = cxgbi_inet6addr_handler
+};
+
+/* Retrieve IPv6 addresses from a root device (bond, vlan) associated with
+ * a physical device.
+ * The physical device reference is needed to send the actual CLIP command.
+ */
+static int update_dev_clip(struct net_device *root_dev, struct net_device *dev)
+{
+	struct inet6_dev *idev = NULL;
+	struct inet6_ifaddr *ifa;
+	int ret = 0;
+
+	idev = __in6_dev_get(root_dev);
+	if (!idev)
+		return ret;
+
+	read_lock_bh(&idev->lock);
+	list_for_each_entry(ifa, &idev->addr_list, if_list) {
+		pr_info("updating the clip for addr %pI6\n",
+			ifa->addr.s6_addr);
+		ret = cxgb4_clip_get(dev, (const struct in6_addr *)
+				     ifa->addr.s6_addr);
+		if (ret < 0)
+			break;
+	}
+
+	read_unlock_bh(&idev->lock);
+	return ret;
+}
+
+static int update_root_dev_clip(struct net_device *dev)
+{
+	struct net_device *root_dev = NULL;
+	int i, ret = 0;
+
+	/* First populate the real net device's IPv6 address */
+	ret = update_dev_clip(dev, dev);
+	if (ret)
+		return ret;
+
+	/* Parse all bond and vlan devices layered on top of the physical dev */
+	root_dev = netdev_master_upper_dev_get(dev);
+	if (root_dev) {
+		ret = update_dev_clip(root_dev, dev);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < VLAN_N_VID; i++) {
+		root_dev = __vlan_find_dev_deep_rcu(dev, htons(ETH_P_8021Q), i);
+		if (!root_dev)
+			continue;
+
+		ret = update_dev_clip(root_dev, dev);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static void cxgbi_update_clip(struct cxgbi_device *cdev)
+{
+	int i;
+
+	rcu_read_lock();
+
+	for (i = 0; i < cdev->nports; i++) {
+		struct net_device *dev = cdev->ports[i];
+		int ret = 0;
+
+		if (dev)
+			ret = update_root_dev_clip(dev);
+		if (ret < 0)
+			break;
+	}
+	rcu_read_unlock();
+}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+
 static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
 {
 	struct cxgbi_device *cdev;
@@ -1605,6 +1876,9 @@ static int t4_uld_state_change(void *han
 	switch (state) {
 	case CXGB4_STATE_UP:
 		pr_info("cdev 0x%p, UP.\n", cdev);
+#if IS_ENABLED(CONFIG_IPV6)
+		cxgbi_update_clip(cdev);
+#endif
 		/* re-initialize */
 		break;
 	case CXGB4_STATE_START_RECOVERY:
@@ -1635,11 +1909,18 @@ static int __init cxgb4i_init_module(voi
 	if (rc < 0)
 		return rc;
 	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+
+#if IS_ENABLED(CONFIG_IPV6)
+	register_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+#endif
 	return 0;
 }
 
 static void __exit cxgb4i_exit_module(void)
 {
+#if IS_ENABLED(CONFIG_IPV6)
+	unregister_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+#endif
 	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
 	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
 	cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 config SCSI_CXGB4_ISCSI
 	tristate "Chelsio T4 iSCSI support"
-	depends on PCI && INET
+	depends on PCI && INET && (IPV6 || IPV6=n)
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_CHELSIO
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/cxgbi/libcxgbi.c linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/libcxgbi.c
--- linux-libre-3.16-gnu/drivers/scsi/cxgbi/libcxgbi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/libcxgbi.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,10 @@
 #include <linux/inet.h>
 #include <net/dst.h>
 #include <net/route.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+
 #include <linux/inetdevice.h>	/* ip_dev_find */
 #include <linux/module.h>
 #include <net/tcp.h>
@@ -193,8 +197,8 @@ struct cxgbi_device *cxgbi_device_find_b
 }
 EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
 
-static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
-							int *port)
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+						 int *port)
 {
 	struct net_device *vdev = NULL;
 	struct cxgbi_device *cdev, *tmp;
@@ -224,6 +228,40 @@ static struct cxgbi_device *cxgbi_device
 		"ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_netdev);
+
+static struct cxgbi_device *cxgbi_device_find_by_mac(struct net_device *ndev,
+						     int *port)
+{
+	struct net_device *vdev = NULL;
+	struct cxgbi_device *cdev, *tmp;
+	int i;
+
+	if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+		vdev = ndev;
+		ndev = vlan_dev_real_dev(ndev);
+		pr_info("vlan dev %s -> %s.\n", vdev->name, ndev->name);
+	}
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		for (i = 0; i < cdev->nports; i++) {
+			if (!memcmp(ndev->dev_addr, cdev->ports[i]->dev_addr,
+				    MAX_ADDR_LEN)) {
+				cdev->hbas[i]->vdev = vdev;
+				mutex_unlock(&cdev_mutex);
+				if (port)
+					*port = i;
+				return cdev;
+			}
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		  "ndev 0x%p, %s, NO match mac found.\n",
+		  ndev, ndev->name);
+	return NULL;
+}
 
 void cxgbi_hbas_remove(struct cxgbi_device *cdev)
 {
@@ -245,7 +283,7 @@ void cxgbi_hbas_remove(struct cxgbi_devi
 }
 EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
 
-int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun,
+int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun,
 		unsigned int max_id, struct scsi_host_template *sht,
 		struct scsi_transport_template *stt)
 {
@@ -320,6 +358,7 @@ static int sock_get_port(struct cxgbi_so
 	struct cxgbi_ports_map *pmap = &cdev->pmap;
 	unsigned int start;
 	int idx;
+	__be16 *port;
 
 	if (!pmap->max_connect) {
 		pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
@@ -327,9 +366,14 @@ static int sock_get_port(struct cxgbi_so
 		return -EADDRNOTAVAIL;
 	}
 
-	if (csk->saddr.sin_port) {
+	if (csk->csk_family == AF_INET)
+		port = &csk->saddr.sin_port;
+	else /* ipv6 */
+		port = &csk->saddr6.sin6_port;
+
+	if (*port) {
 		pr_err("source port NON-ZERO %u.\n",
-			ntohs(csk->saddr.sin_port));
+			ntohs(*port));
 		return -EADDRINUSE;
 	}
 
@@ -347,8 +391,7 @@ static int sock_get_port(struct cxgbi_so
 			idx = 0;
 		if (!pmap->port_csk[idx]) {
 			pmap->used++;
-			csk->saddr.sin_port =
-				htons(pmap->sport_base + idx);
+			*port = htons(pmap->sport_base + idx);
 			pmap->next = idx;
 			pmap->port_csk[idx] = csk;
 			spin_unlock_bh(&pmap->lock);
@@ -374,16 +417,22 @@ static void sock_put_port(struct cxgbi_s
 {
 	struct cxgbi_device *cdev = csk->cdev;
 	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	__be16 *port;
 
-	if (csk->saddr.sin_port) {
-		int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+	if (csk->csk_family == AF_INET)
+		port = &csk->saddr.sin_port;
+	else /* ipv6 */
+		port = &csk->saddr6.sin6_port;
 
-		csk->saddr.sin_port = 0;
+	if (*port) {
+		int idx = ntohs(*port) - pmap->sport_base;
+
+		*port = 0;
 		if (idx < 0 || idx >= pmap->max_connect) {
 			pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
 				cdev, csk->port_id,
 				cdev->ports[csk->port_id]->name,
-				ntohs(csk->saddr.sin_port));
+				ntohs(*port));
 			return;
 		}
 
@@ -479,17 +528,11 @@ static struct cxgbi_sock *cxgbi_check_ro
 	int port = 0xFFFF;
 	int err = 0;
 
-	if (daddr->sin_family != AF_INET) {
-		pr_info("address family 0x%x NOT supported.\n",
-			daddr->sin_family);
-		err = -EAFNOSUPPORT;
-		goto err_out;
-	}
-
 	rt = find_route_ipv4(&fl4, 0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
 	if (!rt) {
 		pr_info("no route to ipv4 0x%x, port %u.\n",
-			daddr->sin_addr.s_addr, daddr->sin_port);
+			be32_to_cpu(daddr->sin_addr.s_addr),
+			be16_to_cpu(daddr->sin_port));
 		err = -ENETUNREACH;
 		goto err_out;
 	}
@@ -537,9 +580,12 @@ static struct cxgbi_sock *cxgbi_check_ro
 	csk->port_id = port;
 	csk->mtu = mtu;
 	csk->dst = dst;
+
+	csk->csk_family = AF_INET;
 	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
 	csk->daddr.sin_port = daddr->sin_port;
 	csk->daddr.sin_family = daddr->sin_family;
+	csk->saddr.sin_family = daddr->sin_family;
 	csk->saddr.sin_addr.s_addr = fl4.saddr;
 	neigh_release(n);
 
@@ -556,6 +602,123 @@ err_out:
 	return ERR_PTR(err);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
+static struct rt6_info *find_route_ipv6(const struct in6_addr *saddr,
+					const struct in6_addr *daddr)
+{
+	struct flowi6 fl;
+
+	if (saddr)
+		memcpy(&fl.saddr, saddr, sizeof(struct in6_addr));
+	if (daddr)
+		memcpy(&fl.daddr, daddr, sizeof(struct in6_addr));
+	return (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
+}
+
+static struct cxgbi_sock *cxgbi_check_route6(struct sockaddr *dst_addr)
+{
+	struct sockaddr_in6 *daddr6 = (struct sockaddr_in6 *)dst_addr;
+	struct dst_entry *dst;
+	struct net_device *ndev;
+	struct cxgbi_device *cdev;
+	struct rt6_info *rt = NULL;
+	struct neighbour *n;
+	struct in6_addr pref_saddr;
+	struct cxgbi_sock *csk = NULL;
+	unsigned int mtu = 0;
+	int port = 0xFFFF;
+	int err = 0;
+
+	rt = find_route_ipv6(NULL, &daddr6->sin6_addr);
+
+	if (!rt) {
+		pr_info("no route to ipv6 %pI6 port %u\n",
+			daddr6->sin6_addr.s6_addr,
+			be16_to_cpu(daddr6->sin6_port));
+		err = -ENETUNREACH;
+		goto err_out;
+	}
+
+	dst = &rt->dst;
+
+	n = dst_neigh_lookup(dst, &daddr6->sin6_addr);
+
+	if (!n) {
+		pr_info("%pI6, port %u, dst no neighbour.\n",
+			daddr6->sin6_addr.s6_addr,
+			be16_to_cpu(daddr6->sin6_port));
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	ndev = n->dev;
+
+	if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
+		pr_info("multi-cast route %pI6 port %u, dev %s.\n",
+			daddr6->sin6_addr.s6_addr,
+			ntohs(daddr6->sin6_port), ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+
+	cdev = cxgbi_device_find_by_netdev(ndev, &port);
+	if (!cdev)
+		cdev = cxgbi_device_find_by_mac(ndev, &port);
+	if (!cdev) {
+		pr_info("dst %pI6 %s, NOT cxgbi device.\n",
+			daddr6->sin6_addr.s6_addr, ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	log_debug(1 << CXGBI_DBG_SOCK,
+		  "route to %pI6 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+		  daddr6->sin6_addr.s6_addr, ntohs(daddr6->sin6_port), port,
+		  ndev->name, cdev);
+
+	csk = cxgbi_sock_create(cdev);
+	if (!csk) {
+		err = -ENOMEM;
+		goto rel_rt;
+	}
+	csk->cdev = cdev;
+	csk->port_id = port;
+	csk->mtu = mtu;
+	csk->dst = dst;
+
+	if (ipv6_addr_any(&rt->rt6i_prefsrc.addr)) {
+		struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt);
+
+		err = ipv6_dev_get_saddr(&init_net, idev ? idev->dev : NULL,
+					 &daddr6->sin6_addr, 0, &pref_saddr);
+		if (err) {
+			pr_info("failed to get source address to reach %pI6\n",
+				&daddr6->sin6_addr);
+			goto rel_rt;
+		}
+	} else {
+		pref_saddr = rt->rt6i_prefsrc.addr;
+	}
+
+	csk->csk_family = AF_INET6;
+	csk->daddr6.sin6_addr = daddr6->sin6_addr;
+	csk->daddr6.sin6_port = daddr6->sin6_port;
+	csk->daddr6.sin6_family = daddr6->sin6_family;
+	csk->saddr6.sin6_addr = pref_saddr;
+
+	neigh_release(n);
+	return csk;
+
+rel_rt:
+	if (n)
+		neigh_release(n);
+
+	ip6_rt_put(rt);
+	if (csk)
+		cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+
 void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
 			unsigned int opt)
 {
@@ -2194,6 +2357,34 @@ int cxgbi_set_conn_param(struct iscsi_cl
 }
 EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
 
+static inline int csk_print_port(struct cxgbi_sock *csk, char *buf)
+{
+	int len;
+
+	cxgbi_sock_get(csk);
+	len = sprintf(buf, "%hu\n", ntohs(csk->daddr.sin_port));
+	cxgbi_sock_put(csk);
+
+	return len;
+}
+
+static inline int csk_print_ip(struct cxgbi_sock *csk, char *buf)
+{
+	int len;
+
+	cxgbi_sock_get(csk);
+	if (csk->csk_family == AF_INET)
+		len = sprintf(buf, "%pI4",
+			      &csk->daddr.sin_addr.s_addr);
+	else
+		len = sprintf(buf, "%pI6",
+			      &csk->daddr6.sin6_addr);
+
+	cxgbi_sock_put(csk);
+
+	return len;
+}
+
 int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
 		       char *buf)
 {
@@ -2447,7 +2638,19 @@ struct iscsi_endpoint *cxgbi_ep_connect(
 		}
 	}
 
-	csk = cxgbi_check_route(dst_addr);
+	if (dst_addr->sa_family == AF_INET) {
+		csk = cxgbi_check_route(dst_addr);
+#if IS_ENABLED(CONFIG_IPV6)
+	} else if (dst_addr->sa_family == AF_INET6) {
+		csk = cxgbi_check_route6(dst_addr);
+#endif
+	} else {
+		pr_info("address family 0x%x NOT supported.\n",
+			dst_addr->sa_family);
+		err = -EAFNOSUPPORT;
+		return (struct iscsi_endpoint *)ERR_PTR(err);
+	}
+
 	if (IS_ERR(csk))
 		return (struct iscsi_endpoint *)csk;
 	cxgbi_sock_get(csk);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/cxgbi/libcxgbi.h linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/libcxgbi.h
--- linux-libre-3.16-gnu/drivers/scsi/cxgbi/libcxgbi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/cxgbi/libcxgbi.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,15 @@ enum cxgbi_dbg_flag {
 			pr_info(fmt, ##__VA_ARGS__); \
 	} while (0)
 
+#define pr_info_ipaddr(fmt_trail,					\
+			addr1, addr2, args_trail...)			\
+do {									\
+	if (!((1 << CXGBI_DBG_SOCK) & dbg_level))			\
+		break;							\
+	pr_info("%pISpc - %pISpc, " fmt_trail,				\
+		addr1, addr2, args_trail);				\
+} while (0)
+
 /* max. connections per adapter */
 #define CXGBI_MAX_CONN		16384
 
@@ -202,8 +211,15 @@ struct cxgbi_sock {
 	spinlock_t lock;
 	struct kref refcnt;
 	unsigned int state;
-	struct sockaddr_in saddr;
-	struct sockaddr_in daddr;
+	unsigned int csk_family;
+	union {
+		struct sockaddr_in saddr;
+		struct sockaddr_in6 saddr6;
+	};
+	union {
+		struct sockaddr_in daddr;
+		struct sockaddr_in6 daddr6;
+	};
 	struct dst_entry *dst;
 	struct sk_buff_head receive_queue;
 	struct sk_buff_head write_queue;
@@ -692,7 +708,8 @@ struct cxgbi_device *cxgbi_device_regist
 void cxgbi_device_unregister(struct cxgbi_device *);
 void cxgbi_device_unregister_all(unsigned int flag);
 struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
-int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *);
+int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int,
 			struct scsi_host_template *,
 			struct scsi_transport_template *);
 void cxgbi_hbas_remove(struct cxgbi_device *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/dc395x.c linux-libre-3.17-rc7-gnu/drivers/scsi/dc395x.c
--- linux-libre-3.16-gnu/drivers/scsi/dc395x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/dc395x.c	2014-09-28 17:29:07.000000000 -0400
@@ -519,9 +519,7 @@ static struct ParameterData cfg_data[] =
 		CFG_PARAM_UNSET,
 		0,
 		0x2f,
-#ifdef CONFIG_SCSI_MULTI_LUN
-			NAC_SCANLUN |
-#endif
+		NAC_SCANLUN |
 		NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET
 			/*| NAC_ACTIVE_NEG*/,
 		NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08
@@ -1089,7 +1087,7 @@ static int dc395x_queue_command_lck(stru
 	struct AdapterCtlBlk *acb =
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
 	dprintkdbg(DBG_0, "queue_command: (0x%p) <%02i-%i> cmnd=0x%02x\n",
-		cmd, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+		cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0]);
 
 	/* Assume BAD_TARGET; will be cleared later */
 	cmd->result = DID_BAD_TARGET << 16;
@@ -1104,7 +1102,7 @@ static int dc395x_queue_command_lck(stru
 	/* does the specified lun on the specified device exist */
 	if (!(acb->dcb_map[cmd->device->id] & (1 << cmd->device->lun))) {
 		dprintkl(KERN_INFO, "queue_command: Ignore target <%02i-%i>\n",
-			cmd->device->id, cmd->device->lun);
+			cmd->device->id, (u8)cmd->device->lun);
 		goto complete;
 	}
 
@@ -1113,7 +1111,7 @@ static int dc395x_queue_command_lck(stru
 	if (!dcb) {
 		/* should never happen */
 		dprintkl(KERN_ERR, "queue_command: No such device <%02i-%i>",
-			cmd->device->id, cmd->device->lun);
+			cmd->device->id, (u8)cmd->device->lun);
 		goto complete;
 	}
 
@@ -1209,7 +1207,7 @@ static void dump_register_info(struct Ad
 				 "cmnd=0x%02x <%02i-%i>\n",
 				srb, srb->cmd,
 				srb->cmd->cmnd[0], srb->cmd->device->id,
-			       	srb->cmd->device->lun);
+				(u8)srb->cmd->device->lun);
 		printk("  sglist=%p cnt=%i idx=%i len=%zu\n",
 		       srb->segment_x, srb->sg_count, srb->sg_index,
 		       srb->total_xfer_length);
@@ -1304,7 +1302,7 @@ static int __dc395x_eh_bus_reset(struct
 		(struct AdapterCtlBlk *)cmd->device->host->hostdata;
 	dprintkl(KERN_INFO,
 		"eh_bus_reset: (0%p) target=<%02i-%i> cmd=%p\n",
-		cmd, cmd->device->id, cmd->device->lun, cmd);
+		cmd, cmd->device->id, (u8)cmd->device->lun, cmd);
 
 	if (timer_pending(&acb->waiting_timer))
 		del_timer(&acb->waiting_timer);
@@ -1371,7 +1369,7 @@ static int dc395x_eh_abort(struct scsi_c
 	struct DeviceCtlBlk *dcb;
 	struct ScsiReqBlk *srb;
 	dprintkl(KERN_INFO, "eh_abort: (0x%p) target=<%02i-%i> cmd=%p\n",
-		cmd, cmd->device->id, cmd->device->lun, cmd);
+		cmd, cmd->device->id, (u8)cmd->device->lun, cmd);
 
 	dcb = find_dcb(acb, cmd->device->id, cmd->device->lun);
 	if (!dcb) {
@@ -1607,7 +1605,7 @@ static u8 start_scsi(struct AdapterCtlBl
 			dprintkl(KERN_WARNING, "start_scsi: (0x%p) "
 				"Out of tags target=<%02i-%i>)\n",
 				srb->cmd, srb->cmd->device->id,
-				srb->cmd->device->lun);
+				(u8)srb->cmd->device->lun);
 			srb->state = SRB_READY;
 			DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
 				       DO_HWRESELECT);
@@ -1625,7 +1623,7 @@ static u8 start_scsi(struct AdapterCtlBl
 /*polling:*/
 	/* Send CDB ..command block ......... */
 	dprintkdbg(DBG_KG, "start_scsi: (0x%p) <%02i-%i> cmnd=0x%02x tag=%i\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun,
 		srb->cmd->cmnd[0], srb->tag_number);
 	if (srb->flag & AUTO_REQSENSE) {
 		DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE);
@@ -2043,7 +2041,7 @@ static void data_out_phase0(struct Adapt
 	u16 scsi_status = *pscsi_status;
 	u32 d_left_counter = 0;
 	dprintkdbg(DBG_0, "data_out_phase0: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 
 	/*
 	 * KG: We need to drain the buffers before we draw any conclusions!
@@ -2173,7 +2171,7 @@ static void data_out_phase1(struct Adapt
 		u16 *pscsi_status)
 {
 	dprintkdbg(DBG_0, "data_out_phase1: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 	clear_fifo(acb, "data_out_phase1");
 	/* do prepare before transfer when data out phase */
 	data_io_transfer(acb, srb, XFERDATAOUT);
@@ -2185,7 +2183,7 @@ static void data_in_phase0(struct Adapte
 	u16 scsi_status = *pscsi_status;
 
 	dprintkdbg(DBG_0, "data_in_phase0: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 
 	/*
 	 * KG: DataIn is much more tricky than DataOut. When the device is finished
@@ -2396,7 +2394,7 @@ static void data_in_phase1(struct Adapte
 		u16 *pscsi_status)
 {
 	dprintkdbg(DBG_0, "data_in_phase1: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 	data_io_transfer(acb, srb, XFERDATAIN);
 }
 
@@ -2408,7 +2406,7 @@ static void data_io_transfer(struct Adap
 	u8 bval;
 	dprintkdbg(DBG_0,
 		"data_io_transfer: (0x%p) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun,
 		((io_dir & DMACMD_DIR) ? 'r' : 'w'),
 		srb->total_xfer_length, srb->sg_index, srb->sg_count);
 	if (srb == acb->tmp_srb)
@@ -2581,7 +2579,7 @@ static void status_phase0(struct Adapter
 		u16 *pscsi_status)
 {
 	dprintkdbg(DBG_0, "status_phase0: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 	srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
 	srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);	/* get message */
 	srb->state = SRB_COMPLETED;
@@ -2595,7 +2593,7 @@ static void status_phase1(struct Adapter
 		u16 *pscsi_status)
 {
 	dprintkdbg(DBG_0, "status_phase1: (0x%p) <%02i-%i>\n",
-		srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
 	srb->state = SRB_STATUS;
 	DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);	/* it's important for atn stop */
 	DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
@@ -3320,7 +3318,7 @@ static void srb_done(struct AdapterCtlBl
 	int ckc_only = 1;
 
 	dprintkdbg(DBG_1, "srb_done: (0x%p) <%02i-%i>\n", srb->cmd,
-		srb->cmd->device->id, srb->cmd->device->lun);
+		srb->cmd->device->id, (u8)srb->cmd->device->lun);
 	dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
 		   srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
 		   scsi_sgtalbe(cmd));
@@ -3500,7 +3498,7 @@ static void srb_done(struct AdapterCtlBl
 		if (srb->total_xfer_length)
 			dprintkdbg(DBG_KG, "srb_done: (0x%p) <%02i-%i> "
 				"cmnd=0x%02x Missed %i bytes\n",
-				cmd, cmd->device->id, cmd->device->lun,
+				cmd, cmd->device->id, (u8)cmd->device->lun,
 				cmd->cmnd[0], srb->total_xfer_length);
 	}
 
@@ -3540,7 +3538,7 @@ static void doing_srb_done(struct Adapte
 			dir = p->sc_data_direction;
 			result = MK_RES(0, did_flag, 0, 0);
 			printk("G:%p(%02i-%i) ", p,
-			       p->device->id, p->device->lun);
+			       p->device->id, (u8)p->device->lun);
 			srb_going_remove(dcb, srb);
 			free_tag(dcb, srb);
 			srb_free_insert(acb, srb);
@@ -3570,7 +3568,7 @@ static void doing_srb_done(struct Adapte
 
 			result = MK_RES(0, did_flag, 0, 0);
 			printk("W:%p<%02i-%i>", p, p->device->id,
-			       p->device->lun);
+			       (u8)p->device->lun);
 			srb_waiting_remove(dcb, srb);
 			srb_free_insert(acb, srb);
 			p->result = result;
@@ -3679,7 +3677,7 @@ static void request_sense(struct Adapter
 {
 	struct scsi_cmnd *cmd = srb->cmd;
 	dprintkdbg(DBG_1, "request_sense: (0x%p) <%02i-%i>\n",
-		cmd, cmd->device->id, cmd->device->lun);
+		cmd, cmd->device->id, (u8)cmd->device->lun);
 
 	srb->flag |= AUTO_REQSENSE;
 	srb->adapter_status = 0;
@@ -4434,15 +4432,10 @@ static void adapter_init_scsi_host(struc
 	if (host->max_id - 1 == eeprom->scsi_id)
 		host->max_id--;
 
-#ifdef CONFIG_SCSI_MULTI_LUN
 	if (eeprom->channel_cfg & NAC_SCANLUN)
 		host->max_lun = 8;
 	else
 		host->max_lun = 1;
-#else
-	host->max_lun = 1;
-#endif
-
 }
 
 
@@ -4645,7 +4638,7 @@ static int dc395x_show_info(struct seq_f
 	SPRINTF("irq_level 0x%04x, ", acb->irq_level);
 	SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000);
 
-	SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun);
+	SPRINTF("MaxID %i, MaxLUN %llu, ", host->max_id, host->max_lun);
 	SPRINTF("AdapterID %i\n", host->this_id);
 
 	SPRINTF("tag_max_num %i", acb->tag_max_num);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/dpt_i2o.c linux-libre-3.17-rc7-gnu/drivers/scsi/dpt_i2o.c
--- linux-libre-3.16-gnu/drivers/scsi/dpt_i2o.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/dpt_i2o.c	2014-09-28 17:29:07.000000000 -0400
@@ -459,7 +459,7 @@ static int adpt_queue_lck(struct scsi_cm
 		 * to the device structure.  This should be a TEST_UNIT_READY
 		 * command from scan_scsis_single.
 		 */
-		if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun)) == NULL) {
+		if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun)) == NULL) {
 			// TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response 
 			// with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
 			cmd->result = (DID_NO_CONNECT << 16);
@@ -579,8 +579,8 @@ static int adpt_show_info(struct seq_fil
 				seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev);
 
 				unit = d->pI2o_dev->lct_data.tid;
-				seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d)  (%s)\n\n",
-					       unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
+				seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%llu)  (%s)\n\n",
+					       unit, (int)d->scsi_channel, (int)d->scsi_id, d->scsi_lun,
 					       scsi_device_online(d->pScsi_dev)? "online":"offline"); 
 				d = d->next_lun;
 			}
@@ -1162,7 +1162,7 @@ static void adpt_i2o_delete_hba(adpt_hba
 	}
 }
 
-static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun)
+static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun)
 {
 	struct adpt_device* d;
 
@@ -1462,7 +1462,7 @@ static int adpt_i2o_parse_lct(adpt_hba*
 	i2o_lct *lct = pHba->lct;
 	u8 bus_no = 0;
 	s16 scsi_id;
-	s16 scsi_lun;
+	u64 scsi_lun;
 	u32 buf[10]; // larger than 7, or 8 ...
 	struct adpt_device* pDev; 
 	
@@ -1496,7 +1496,7 @@ static int adpt_i2o_parse_lct(adpt_hba*
 			}
 			bus_no = buf[0]>>16;
 			scsi_id = buf[1];
-			scsi_lun = (buf[2]>>8 )&0xff;
+			scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
 			if(bus_no >= MAX_CHANNEL) {	// Something wrong skip it
 				printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
 				continue;
@@ -1571,7 +1571,7 @@ static int adpt_i2o_parse_lct(adpt_hba*
 			if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) {
 				bus_no = buf[0]>>16;
 				scsi_id = buf[1];
-				scsi_lun = (buf[2]>>8 )&0xff;
+				scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
 				if(bus_no >= MAX_CHANNEL) {	// Something wrong skip it
 					continue;
 				}
@@ -2407,8 +2407,8 @@ static s32 adpt_i2o_to_scsi(void __iomem
 		case I2O_SCSI_DSC_COMMAND_TIMEOUT:
 		case I2O_SCSI_DSC_NO_ADAPTER:
 		case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:
-			printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
-				pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]);
+			printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
+				pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]);
 			cmd->result = (DID_TIME_OUT << 16);
 			break;
 		case I2O_SCSI_DSC_ADAPTER_BUSY:
@@ -2447,8 +2447,8 @@ static s32 adpt_i2o_to_scsi(void __iomem
 		case I2O_SCSI_DSC_QUEUE_FROZEN:
 		case I2O_SCSI_DSC_REQUEST_INVALID:
 		default:
-			printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
-				pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
+			printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
+				pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
 			       hba_status, dev_status, cmd->cmnd[0]);
 			cmd->result = (DID_ERROR << 16);
 			break;
@@ -2464,8 +2464,8 @@ static s32 adpt_i2o_to_scsi(void __iomem
 			   cmd->sense_buffer[2] == DATA_PROTECT ){
 				/* This is to handle an array failed */
 				cmd->result = (DID_TIME_OUT << 16);
-				printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
-					pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, 
+				printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
+					pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
 					hba_status, dev_status, cmd->cmnd[0]);
 
 			}
@@ -2476,8 +2476,8 @@ static s32 adpt_i2o_to_scsi(void __iomem
 		 * for a limitted number of retries.
 		 */
 		cmd->result = (DID_TIME_OUT << 16);
-		printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n",
-			pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
+		printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n",
+			pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
 			((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);
 	}
 
@@ -2517,7 +2517,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba
 	i2o_lct *lct = pHba->lct;
 	u8 bus_no = 0;
 	s16 scsi_id;
-	s16 scsi_lun;
+	u64 scsi_lun;
 	u32 buf[10]; // at least 8 u32's
 	struct adpt_device* pDev = NULL;
 	struct i2o_device* pI2o_dev = NULL;
@@ -2564,7 +2564,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba
 			}
 
 			scsi_id = buf[1];
-			scsi_lun = (buf[2]>>8 )&0xff;
+			scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
 			pDev = pHba->channel[bus_no].device[scsi_id];
 			/* da lun */
 			while(pDev) {
@@ -2633,7 +2633,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba
 			while(pDev) {
 				if(pDev->scsi_lun == scsi_lun) {
 					if(!scsi_device_online(pDev->pScsi_dev)) {
-						printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n",
+						printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n",
 								pHba->name,bus_no,scsi_id,scsi_lun);
 						if (pDev->pScsi_dev) {
 							scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
@@ -2665,7 +2665,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba
 		// in the LCT table
 		if (pDev->state & DPTI_DEV_UNSCANNED){
 			pDev->state = DPTI_DEV_OFFLINE;
-			printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
+			printk(KERN_WARNING"%s: Device (%d,%d,%llu) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
 			if (pDev->pScsi_dev) {
 				scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
 			}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/dpti.h linux-libre-3.17-rc7-gnu/drivers/scsi/dpti.h
--- linux-libre-3.16-gnu/drivers/scsi/dpti.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/dpti.h	2014-09-28 17:29:07.000000000 -0400
@@ -184,7 +184,7 @@ struct adpt_device {
 	u32	block_size;
 	u8	scsi_channel;
 	u8	scsi_id;
-	u8 	scsi_lun;
+	u64	scsi_lun;
 	u8	state;
 	u16	tid;
 	struct i2o_device* pI2o_dev;
@@ -231,7 +231,7 @@ typedef struct _adpt_hba {
 	u32  sg_tablesize;	// Scatter/Gather List Size.       
 	u8  top_scsi_channel;
 	u8  top_scsi_id;
-	u8  top_scsi_lun;
+	u64  top_scsi_lun;
 	u8  dma64;
 
 	i2o_status_block* status_block;
@@ -300,7 +300,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u
 static void adpt_i2o_delete_hba(adpt_hba* pHba);
 static void adpt_inquiry(adpt_hba* pHba);
 static void adpt_fail_posted_scbs(adpt_hba* pHba);
-static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun);
+static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun);
 static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
 static int adpt_i2o_online_hba(adpt_hba* pHba);
 static void adpt_i2o_post_wait_complete(u32, int);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/eata.c linux-libre-3.17-rc7-gnu/drivers/scsi/eata.c
--- linux-libre-3.16-gnu/drivers/scsi/eata.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/eata.c	2014-09-28 17:29:07.000000000 -0400
@@ -1238,8 +1238,8 @@ static int port_detect(unsigned long por
 		struct eata_config *cf;
 		dma_addr_t cf_dma_addr;
 
-		cf = pci_alloc_consistent(pdev, sizeof(struct eata_config),
-					  &cf_dma_addr);
+		cf = pci_zalloc_consistent(pdev, sizeof(struct eata_config),
+					   &cf_dma_addr);
 
 		if (!cf) {
 			printk
@@ -1249,7 +1249,6 @@ static int port_detect(unsigned long por
 		}
 
 		/* Set board configuration */
-		memset((char *)cf, 0, sizeof(struct eata_config));
 		cf->len = (ushort) H2DEV16((ushort) 510);
 		cf->ocena = 1;
 
@@ -1399,7 +1398,7 @@ static int port_detect(unsigned long por
 
 	if (shost->max_id > 8 || shost->max_lun > 8)
 		printk
-		    ("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
+		    ("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n",
 		     ha->board_name, shost->max_id, shost->max_lun);
 
 	for (i = 0; i <= shost->max_channel; i++)
@@ -2449,7 +2448,7 @@ static irqreturn_t ihdlr(struct Scsi_Hos
 			       "target_status 0x%x, sense key 0x%x.\n",
 			       ha->board_name,
 			       SCpnt->device->channel, SCpnt->device->id,
-			       SCpnt->device->lun,
+			       (u8)SCpnt->device->lun,
 			       spp->target_status, SCpnt->sense_buffer[2]);
 
 		ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/fnic/fnic_isr.c linux-libre-3.17-rc7-gnu/drivers/scsi/fnic/fnic_isr.c
--- linux-libre-3.16-gnu/drivers/scsi/fnic/fnic_isr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/fnic/fnic_isr.c	2014-09-28 17:29:07.000000000 -0400
@@ -257,8 +257,8 @@ int fnic_set_intr_mode(struct fnic *fnic
 	    fnic->raw_wq_count >= m &&
 	    fnic->wq_copy_count >= o &&
 	    fnic->cq_count >= n + m + o) {
-		if (!pci_enable_msix(fnic->pdev, fnic->msix_entry,
-				    n + m + o + 1)) {
+		if (!pci_enable_msix_exact(fnic->pdev, fnic->msix_entry,
+					   n + m + o + 1)) {
 			fnic->rq_count = n;
 			fnic->raw_wq_count = m;
 			fnic->wq_copy_count = o;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/fnic/fnic_scsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/fnic/fnic_scsi.c
--- linux-libre-3.16-gnu/drivers/scsi/fnic/fnic_scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/fnic/fnic_scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1753,7 +1753,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
 	tag = sc->request->tag;
 	FNIC_SCSI_DBG(KERN_DEBUG,
 		fnic->lport->host,
-		"Abort Cmd called FCID 0x%x, LUN 0x%x TAG %x flags %x\n",
+		"Abort Cmd called FCID 0x%x, LUN 0x%llx TAG %x flags %x\n",
 		rport->port_id, sc->device->lun, tag, CMD_FLAGS(sc));
 
 	CMD_FLAGS(sc) = FNIC_NO_FLAGS;
@@ -2207,7 +2207,7 @@ int fnic_device_reset(struct scsi_cmnd *
 
 	rport = starget_to_rport(scsi_target(sc->device));
 	FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
-		      "Device reset called FCID 0x%x, LUN 0x%x sc 0x%p\n",
+		      "Device reset called FCID 0x%x, LUN 0x%llx sc 0x%p\n",
 		      rport->port_id, sc->device->lun, sc);
 
 	if (lp->state != LPORT_ST_READY || !(lp->link_up))
@@ -2224,6 +2224,22 @@ int fnic_device_reset(struct scsi_cmnd *
 
 	tag = sc->request->tag;
 	if (unlikely(tag < 0)) {
+		/*
+		 * XXX(hch): current the midlayer fakes up a struct
+		 * request for the explicit reset ioctls, and those
+		 * don't have a tag allocated to them.  The below
+		 * code pokes into midlayer structures to paper over
+		 * this design issue, but that won't work for blk-mq.
+		 *
+		 * Either someone who can actually test the hardware
+		 * will have to come up with a similar hack for the
+		 * blk-mq case, or we'll have to bite the bullet and
+		 * fix the way the EH ioctls work for real, but until
+		 * that happens we fail these explicit requests here.
+		 */
+		if (shost_use_blk_mq(sc->device->host))
+			goto fnic_device_reset_end;
+
 		tag = fnic_scsi_host_start_tag(fnic, sc);
 		if (unlikely(tag == SCSI_NO_TAG))
 			goto fnic_device_reset_end;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/g_NCR5380.c linux-libre-3.17-rc7-gnu/drivers/scsi/g_NCR5380.c
--- linux-libre-3.16-gnu/drivers/scsi/g_NCR5380.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/g_NCR5380.c	2014-09-28 17:29:07.000000000 -0400
@@ -768,7 +768,7 @@ static void sprint_command(struct seq_fi
 
 static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
 {
-	PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
+	PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
 	PRINTP("        command = ");
 	sprint_command(m, cmd->cmnd);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/hosts.c linux-libre-3.17-rc7-gnu/drivers/scsi/hosts.c
--- linux-libre-3.16-gnu/drivers/scsi/hosts.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/hosts.c	2014-09-28 17:29:07.000000000 -0400
@@ -204,18 +204,33 @@ int scsi_add_host_with_dma(struct Scsi_H
 	struct scsi_host_template *sht = shost->hostt;
 	int error = -EINVAL;
 
-	printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
+	shost_printk(KERN_INFO, shost, "%s\n",
 			sht->info ? sht->info(shost) : sht->name);
 
 	if (!shost->can_queue) {
-		printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
-				sht->name);
+		shost_printk(KERN_ERR, shost,
+			     "can_queue = 0 no longer supported\n");
 		goto fail;
 	}
 
+	if (shost_use_blk_mq(shost)) {
+		error = scsi_mq_setup_tags(shost);
+		if (error)
+			goto fail;
+	}
+
+	/*
+	 * Note that we allocate the freelist even for the MQ case for now,
+	 * as we need a command set aside for scsi_reset_provider.  Having
+	 * the full host freelist and one command available for that is a
+	 * little heavy-handed, but avoids introducing a special allocator
+	 * just for this.  Eventually the structure of scsi_reset_provider
+	 * will need a major overhaul.
+	 */
 	error = scsi_setup_command_freelist(shost);
 	if (error)
-		goto fail;
+		goto out_destroy_tags;
+
 
 	if (!shost->shost_gendev.parent)
 		shost->shost_gendev.parent = dev ? dev : &platform_bus;
@@ -226,7 +241,7 @@ int scsi_add_host_with_dma(struct Scsi_H
 
 	error = device_add(&shost->shost_gendev);
 	if (error)
-		goto out;
+		goto out_destroy_freelist;
 
 	pm_runtime_set_active(&shost->shost_gendev);
 	pm_runtime_enable(&shost->shost_gendev);
@@ -279,8 +294,11 @@ int scsi_add_host_with_dma(struct Scsi_H
 	device_del(&shost->shost_dev);
  out_del_gendev:
 	device_del(&shost->shost_gendev);
- out:
+ out_destroy_freelist:
 	scsi_destroy_command_freelist(shost);
+ out_destroy_tags:
+	if (shost_use_blk_mq(shost))
+		scsi_mq_destroy_tags(shost);
  fail:
 	return error;
 }
@@ -309,8 +327,13 @@ static void scsi_host_dev_release(struct
 	}
 
 	scsi_destroy_command_freelist(shost);
-	if (shost->bqt)
-		blk_free_tags(shost->bqt);
+	if (shost_use_blk_mq(shost)) {
+		if (shost->tag_set.tags)
+			scsi_mq_destroy_tags(shost);
+	} else {
+		if (shost->bqt)
+			blk_free_tags(shost->bqt);
+	}
 
 	kfree(shost->shost_data);
 
@@ -436,6 +459,8 @@ struct Scsi_Host *scsi_host_alloc(struct
 	else
 		shost->dma_boundary = 0xffffffff;
 
+	shost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq;
+
 	device_initialize(&shost->shost_gendev);
 	dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
 	shost->shost_gendev.bus = &scsi_bus_type;
@@ -450,8 +475,9 @@ struct Scsi_Host *scsi_host_alloc(struct
 	shost->ehandler = kthread_run(scsi_error_handler, shost,
 			"scsi_eh_%d", shost->host_no);
 	if (IS_ERR(shost->ehandler)) {
-		printk(KERN_WARNING "scsi%d: error handler thread failed to spawn, error = %ld\n",
-			shost->host_no, PTR_ERR(shost->ehandler));
+		shost_printk(KERN_WARNING, shost,
+			"error handler thread failed to spawn, error = %ld\n",
+			PTR_ERR(shost->ehandler));
 		goto fail_kfree;
 	}
 
@@ -584,7 +610,7 @@ EXPORT_SYMBOL(scsi_is_host_device);
 int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)
 {
 	if (unlikely(!shost->work_q)) {
-		printk(KERN_ERR
+		shost_printk(KERN_ERR, shost,
 			"ERROR: Scsi host '%s' attempted to queue scsi-work, "
 			"when no workqueue created.\n", shost->hostt->name);
 		dump_stack();
@@ -603,7 +629,7 @@ EXPORT_SYMBOL_GPL(scsi_queue_work);
 void scsi_flush_work(struct Scsi_Host *shost)
 {
 	if (!shost->work_q) {
-		printk(KERN_ERR
+		shost_printk(KERN_ERR, shost,
 			"ERROR: Scsi host '%s' attempted to flush scsi-work, "
 			"when no workqueue created.\n", shost->hostt->name);
 		dump_stack();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/hpsa.c linux-libre-3.17-rc7-gnu/drivers/scsi/hpsa.c
--- linux-libre-3.16-gnu/drivers/scsi/hpsa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/hpsa.c	2014-09-28 17:29:07.000000000 -0400
@@ -1708,7 +1708,14 @@ static void complete_scsi_command(struct
 
 	cmd->result |= ei->ScsiStatus;
 
-	/* copy the sense data whether we need to or not. */
+	scsi_set_resid(cmd, ei->ResidualCnt);
+	if (ei->CommandStatus == 0) {
+		cmd_free(h, cp);
+		cmd->scsi_done(cmd);
+		return;
+	}
+
+	/* copy the sense data */
 	if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo))
 		sense_data_size = SCSI_SENSE_BUFFERSIZE;
 	else
@@ -1717,13 +1724,6 @@ static void complete_scsi_command(struct
 		sense_data_size = ei->SenseLen;
 
 	memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size);
-	scsi_set_resid(cmd, ei->ResidualCnt);
-
-	if (ei->CommandStatus == 0) {
-		cmd_free(h, cp);
-		cmd->scsi_done(cmd);
-		return;
-	}
 
 	/* For I/O accelerator commands, copy over some fields to the normal
 	 * CISS header used below for error handling.
@@ -3686,6 +3686,8 @@ static int hpsa_scsi_ioaccel_raid_map(st
 			(((u64) cmd->cmnd[2]) << 8) |
 			cmd->cmnd[3];
 		block_cnt = cmd->cmnd[4];
+		if (block_cnt == 0)
+			block_cnt = 256;
 		break;
 	case WRITE_10:
 		is_write = 1;
@@ -3734,7 +3736,6 @@ static int hpsa_scsi_ioaccel_raid_map(st
 	default:
 		return IO_ACCEL_INELIGIBLE; /* process via normal I/O path */
 	}
-	BUG_ON(block_cnt == 0);
 	last_block = first_block + block_cnt - 1;
 
 	/* check for write to non-RAID-0 */
@@ -4590,7 +4591,7 @@ static int hpsa_eh_abort_handler(struct
 		return FAILED;
 
 	memset(msg, 0, sizeof(msg));
-	ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%d ",
+	ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%llu ",
 		h->scsi_host->host_no, sc->device->channel,
 		sc->device->id, sc->device->lun);
 
@@ -4731,23 +4732,21 @@ static struct CommandList *cmd_special_a
 	union u64bit temp64;
 	dma_addr_t cmd_dma_handle, err_dma_handle;
 
-	c = pci_alloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
+	c = pci_zalloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
 	if (c == NULL)
 		return NULL;
-	memset(c, 0, sizeof(*c));
 
 	c->cmd_type = CMD_SCSI;
 	c->cmdindex = -1;
 
-	c->err_info = pci_alloc_consistent(h->pdev, sizeof(*c->err_info),
-		    &err_dma_handle);
+	c->err_info = pci_zalloc_consistent(h->pdev, sizeof(*c->err_info),
+					    &err_dma_handle);
 
 	if (c->err_info == NULL) {
 		pci_free_consistent(h->pdev,
 			sizeof(*c), c, cmd_dma_handle);
 		return NULL;
 	}
-	memset(c->err_info, 0, sizeof(*c->err_info));
 
 	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
@@ -5092,7 +5091,7 @@ static int hpsa_big_passthru_ioctl(struc
 		}
 		if (ioc->Request.Type.Direction & XFER_WRITE) {
 			if (copy_from_user(buff[sg_used], data_ptr, sz)) {
-				status = -ENOMEM;
+				status = -EFAULT;
 				goto cleanup1;
 			}
 		} else
@@ -6365,9 +6364,9 @@ static inline void hpsa_set_driver_suppo
 {
 	u32 driver_support;
 
-#ifdef CONFIG_X86
-	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
 	driver_support = readl(&(h->cfgtable->driver_support));
+	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
+#ifdef CONFIG_X86
 	driver_support |= ENABLE_SCSI_PREFETCH;
 #endif
 	driver_support |= ENABLE_UNIT_ATTN;
@@ -6913,8 +6912,12 @@ static int hpsa_offline_devices_ready(st
 		d = list_entry(this, struct offline_device_entry,
 				offline_list);
 		spin_unlock_irqrestore(&h->offline_device_lock, flags);
-		if (!hpsa_volume_offline(h, d->scsi3addr))
+		if (!hpsa_volume_offline(h, d->scsi3addr)) {
+			spin_lock_irqsave(&h->offline_device_lock, flags);
+			list_del(&d->offline_list);
+			spin_unlock_irqrestore(&h->offline_device_lock, flags);
 			return 1;
+		}
 		spin_lock_irqsave(&h->offline_device_lock, flags);
 	}
 	spin_unlock_irqrestore(&h->offline_device_lock, flags);
@@ -6995,8 +6998,10 @@ reinit_after_soft_reset:
 
 	/* Allocate and clear per-cpu variable lockup_detected */
 	h->lockup_detected = alloc_percpu(u32);
-	if (!h->lockup_detected)
+	if (!h->lockup_detected) {
+		rc = -ENOMEM;
 		goto clean1;
+	}
 	set_lockup_detected_for_all_cpus(h, 0);
 
 	rc = hpsa_pci_init(h);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/hptiop.c linux-libre-3.17-rc7-gnu/drivers/scsi/hptiop.c
--- linux-libre-3.16-gnu/drivers/scsi/hptiop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/hptiop.c	2014-09-28 17:29:07.000000000 -0400
@@ -1024,7 +1024,7 @@ static int hptiop_queuecommand_lck(struc
 
 	_req->scp = scp;
 
-	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%08x-%08x-%08x-%08x) "
+	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%llu cdb=(%08x-%08x-%08x-%08x) "
 			"req_index=%d, req=%p\n",
 			scp,
 			host->host_no, scp->device->channel,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvfc.c linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvfc.c
--- linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvfc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvfc.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,7 +46,7 @@
 
 static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT;
 static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT;
-static unsigned int max_lun = IBMVFC_MAX_LUN;
+static u64 max_lun = IBMVFC_MAX_LUN;
 static unsigned int max_targets = IBMVFC_MAX_TARGETS;
 static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
 static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
@@ -71,7 +71,7 @@ MODULE_PARM_DESC(default_timeout,
 module_param_named(max_requests, max_requests, uint, S_IRUGO);
 MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. "
 		 "[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]");
-module_param_named(max_lun, max_lun, uint, S_IRUGO);
+module_param_named(max_lun, max_lun, ullong, S_IRUGO);
 MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. "
 		 "[Default=" __stringify(IBMVFC_MAX_LUN) "]");
 module_param_named(max_targets, max_targets, uint, S_IRUGO);
@@ -166,13 +166,13 @@ static void ibmvfc_trc_start(struct ibmv
 	switch (entry->fmt) {
 	case IBMVFC_CMD_FORMAT:
 		entry->op_code = vfc_cmd->iu.cdb[0];
-		entry->scsi_id = vfc_cmd->tgt_scsi_id;
+		entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
 		entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
 		entry->tmf_flags = vfc_cmd->iu.tmf_flags;
-		entry->u.start.xfer_len = vfc_cmd->iu.xfer_len;
+		entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len);
 		break;
 	case IBMVFC_MAD_FORMAT:
-		entry->op_code = mad->opcode;
+		entry->op_code = be32_to_cpu(mad->opcode);
 		break;
 	default:
 		break;
@@ -199,18 +199,18 @@ static void ibmvfc_trc_end(struct ibmvfc
 	switch (entry->fmt) {
 	case IBMVFC_CMD_FORMAT:
 		entry->op_code = vfc_cmd->iu.cdb[0];
-		entry->scsi_id = vfc_cmd->tgt_scsi_id;
+		entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
 		entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
 		entry->tmf_flags = vfc_cmd->iu.tmf_flags;
-		entry->u.end.status = vfc_cmd->status;
-		entry->u.end.error = vfc_cmd->error;
+		entry->u.end.status = be16_to_cpu(vfc_cmd->status);
+		entry->u.end.error = be16_to_cpu(vfc_cmd->error);
 		entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags;
 		entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code;
 		entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status;
 		break;
 	case IBMVFC_MAD_FORMAT:
-		entry->op_code = mad->opcode;
-		entry->u.end.status = mad->status;
+		entry->op_code = be32_to_cpu(mad->opcode);
+		entry->u.end.status = be16_to_cpu(mad->status);
 		break;
 	default:
 		break;
@@ -270,14 +270,14 @@ static int ibmvfc_get_err_result(struct
 {
 	int err;
 	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
-	int fc_rsp_len = rsp->fcp_rsp_len;
+	int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
 
 	if ((rsp->flags & FCP_RSP_LEN_VALID) &&
 	    ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) ||
 	     rsp->data.info.rsp_code))
 		return DID_ERROR << 16;
 
-	err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+	err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
 	if (err >= 0)
 		return rsp->scsi_status | (cmd_status[err].result << 16);
 	return rsp->scsi_status | (DID_ERROR << 16);
@@ -807,7 +807,7 @@ static void ibmvfc_fail_request(struct i
 		evt->cmnd->result = (error_code << 16);
 		evt->done = ibmvfc_scsi_eh_done;
 	} else
-		evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED;
+		evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED);
 
 	list_del(&evt->queue);
 	del_timer(&evt->timer);
@@ -955,7 +955,7 @@ static void ibmvfc_get_host_speed(struct
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (vhost->state == IBMVFC_ACTIVE) {
-		switch (vhost->login_buf->resp.link_speed / 100) {
+		switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) {
 		case 1:
 			fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 			break;
@@ -976,7 +976,7 @@ static void ibmvfc_get_host_speed(struct
 			break;
 		default:
 			ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n",
-				   vhost->login_buf->resp.link_speed / 100);
+				   be64_to_cpu(vhost->login_buf->resp.link_speed) / 100);
 			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 			break;
 		}
@@ -1171,21 +1171,21 @@ static void ibmvfc_set_login_info(struct
 
 	memset(login_info, 0, sizeof(*login_info));
 
-	login_info->ostype = IBMVFC_OS_LINUX;
-	login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9;
-	login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu);
-	login_info->max_response = sizeof(struct ibmvfc_fcp_rsp);
-	login_info->partition_num = vhost->partition_number;
-	login_info->vfc_frame_version = 1;
-	login_info->fcp_version = 3;
-	login_info->flags = IBMVFC_FLUSH_ON_HALT;
+	login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX);
+	login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9);
+	login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu));
+	login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp));
+	login_info->partition_num = cpu_to_be32(vhost->partition_number);
+	login_info->vfc_frame_version = cpu_to_be32(1);
+	login_info->fcp_version = cpu_to_be16(3);
+	login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT);
 	if (vhost->client_migrated)
-		login_info->flags |= IBMVFC_CLIENT_MIGRATED;
+		login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED);
 
-	login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
-	login_info->capabilities = IBMVFC_CAN_MIGRATE;
-	login_info->async.va = vhost->async_crq.msg_token;
-	login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
+	login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ);
+	login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE);
+	login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
+	login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs));
 	strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
 	strncpy(login_info->device_name,
 		dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
@@ -1225,7 +1225,7 @@ static int ibmvfc_init_event_pool(struct
 		struct ibmvfc_event *evt = &pool->events[i];
 		atomic_set(&evt->free, 1);
 		evt->crq.valid = 0x80;
-		evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i);
+		evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
 		evt->xfer_iu = pool->iu_storage + i;
 		evt->vhost = vhost;
 		evt->ext_list = NULL;
@@ -1310,8 +1310,8 @@ static void ibmvfc_map_sg_list(struct sc
 	struct scatterlist *sg;
 
 	scsi_for_each_sg(scmd, sg, nseg, i) {
-		md[i].va = sg_dma_address(sg);
-		md[i].len = sg_dma_len(sg);
+		md[i].va = cpu_to_be64(sg_dma_address(sg));
+		md[i].len = cpu_to_be32(sg_dma_len(sg));
 		md[i].key = 0;
 	}
 }
@@ -1337,7 +1337,7 @@ static int ibmvfc_map_sg_data(struct scs
 
 	sg_mapped = scsi_dma_map(scmd);
 	if (!sg_mapped) {
-		vfc_cmd->flags |= IBMVFC_NO_MEM_DESC;
+		vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC);
 		return 0;
 	} else if (unlikely(sg_mapped < 0)) {
 		if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
@@ -1346,10 +1346,10 @@ static int ibmvfc_map_sg_data(struct scs
 	}
 
 	if (scmd->sc_data_direction == DMA_TO_DEVICE) {
-		vfc_cmd->flags |= IBMVFC_WRITE;
+		vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE);
 		vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA;
 	} else {
-		vfc_cmd->flags |= IBMVFC_READ;
+		vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ);
 		vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA;
 	}
 
@@ -1358,7 +1358,7 @@ static int ibmvfc_map_sg_data(struct scs
 		return 0;
 	}
 
-	vfc_cmd->flags |= IBMVFC_SCATTERLIST;
+	vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST);
 
 	if (!evt->ext_list) {
 		evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC,
@@ -1374,8 +1374,8 @@ static int ibmvfc_map_sg_data(struct scs
 
 	ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list);
 
-	data->va = evt->ext_list_token;
-	data->len = sg_mapped * sizeof(struct srp_direct_buf);
+	data->va = cpu_to_be64(evt->ext_list_token);
+	data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf));
 	data->key = 0;
 	return 0;
 }
@@ -1404,15 +1404,15 @@ static void ibmvfc_timeout(struct ibmvfc
 static int ibmvfc_send_event(struct ibmvfc_event *evt,
 			     struct ibmvfc_host *vhost, unsigned long timeout)
 {
-	u64 *crq_as_u64 = (u64 *) &evt->crq;
+	__be64 *crq_as_u64 = (__be64 *) &evt->crq;
 	int rc;
 
 	/* Copy the IU into the transfer area */
 	*evt->xfer_iu = evt->iu;
 	if (evt->crq.format == IBMVFC_CMD_FORMAT)
-		evt->xfer_iu->cmd.tag = (u64)evt;
+		evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt);
 	else if (evt->crq.format == IBMVFC_MAD_FORMAT)
-		evt->xfer_iu->mad_common.tag = (u64)evt;
+		evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt);
 	else
 		BUG();
 
@@ -1428,7 +1428,8 @@ static int ibmvfc_send_event(struct ibmv
 
 	mb();
 
-	if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) {
+	if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
+				  be64_to_cpu(crq_as_u64[1])))) {
 		list_del(&evt->queue);
 		del_timer(&evt->timer);
 
@@ -1451,7 +1452,7 @@ static int ibmvfc_send_event(struct ibmv
 			evt->cmnd->result = DID_ERROR << 16;
 			evt->done = ibmvfc_scsi_eh_done;
 		} else
-			evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR;
+			evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR);
 
 		evt->done(evt);
 	} else
@@ -1472,7 +1473,7 @@ static void ibmvfc_log_error(struct ibmv
 	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
 	struct scsi_cmnd *cmnd = evt->cmnd;
 	const char *err = unknown_error;
-	int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+	int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
 	int logerr = 0;
 	int rsp_code = 0;
 
@@ -1526,13 +1527,13 @@ static void ibmvfc_scsi_done(struct ibmv
 	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
 	struct scsi_cmnd *cmnd = evt->cmnd;
 	u32 rsp_len = 0;
-	u32 sense_len = rsp->fcp_sense_len;
+	u32 sense_len = be32_to_cpu(rsp->fcp_sense_len);
 
 	if (cmnd) {
-		if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
-			scsi_set_resid(cmnd, vfc_cmd->adapter_resid);
+		if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID)
+			scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid));
 		else if (rsp->flags & FCP_RESID_UNDER)
-			scsi_set_resid(cmnd, rsp->fcp_resid);
+			scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid));
 		else
 			scsi_set_resid(cmnd, 0);
 
@@ -1540,12 +1541,13 @@ static void ibmvfc_scsi_done(struct ibmv
 			cmnd->result = ibmvfc_get_err_result(vfc_cmd);
 
 			if (rsp->flags & FCP_RSP_LEN_VALID)
-				rsp_len = rsp->fcp_rsp_len;
+				rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
 			if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
 				sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
 			if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
 				memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
-			if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
+			if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) &&
+			    (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED))
 				ibmvfc_relogin(cmnd->device);
 
 			if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
@@ -1630,19 +1632,19 @@ static int ibmvfc_queuecommand_lck(struc
 	cmnd->scsi_done = done;
 	vfc_cmd = &evt->iu.cmd;
 	memset(vfc_cmd, 0, sizeof(*vfc_cmd));
-	vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-	vfc_cmd->resp.len = sizeof(vfc_cmd->rsp);
-	vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE;
-	vfc_cmd->payload_len = sizeof(vfc_cmd->iu);
-	vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
-	vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
-	vfc_cmd->tgt_scsi_id = rport->port_id;
-	vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
+	vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+	vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+	vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+	vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu));
+	vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+	vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata);
+	vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id);
+	vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
 	int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
 	memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
 
 	if (scsi_populate_tag_msg(cmnd, tag)) {
-		vfc_cmd->task_tag = tag[1];
+		vfc_cmd->task_tag = cpu_to_be64(tag[1]);
 		switch (tag[0]) {
 		case MSG_SIMPLE_TAG:
 			vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
@@ -1732,12 +1734,12 @@ static int ibmvfc_bsg_timeout(struct fc_
 
 	tmf = &evt->iu.tmf;
 	memset(tmf, 0, sizeof(*tmf));
-	tmf->common.version = 1;
-	tmf->common.opcode = IBMVFC_TMF_MAD;
-	tmf->common.length = sizeof(*tmf);
-	tmf->scsi_id = port_id;
-	tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
-	tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY;
+	tmf->common.version = cpu_to_be32(1);
+	tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+	tmf->common.length = cpu_to_be16(sizeof(*tmf));
+	tmf->scsi_id = cpu_to_be64(port_id);
+	tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
+	tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY);
 	rc = ibmvfc_send_event(evt, vhost, default_timeout);
 
 	if (rc != 0) {
@@ -1789,10 +1791,10 @@ static int ibmvfc_bsg_plogi(struct ibmvf
 	ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
 	plogi = &evt->iu.plogi;
 	memset(plogi, 0, sizeof(*plogi));
-	plogi->common.version = 1;
-	plogi->common.opcode = IBMVFC_PORT_LOGIN;
-	plogi->common.length = sizeof(*plogi);
-	plogi->scsi_id = port_id;
+	plogi->common.version = cpu_to_be32(1);
+	plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+	plogi->common.length = cpu_to_be16(sizeof(*plogi));
+	plogi->scsi_id = cpu_to_be64(port_id);
 	evt->sync_iu = &rsp_iu;
 	init_completion(&evt->comp);
 
@@ -1904,26 +1906,26 @@ static int ibmvfc_bsg_request(struct fc_
 	mad = &evt->iu.passthru;
 
 	memset(mad, 0, sizeof(*mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_PASSTHRU;
-	mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+	mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
 
-	mad->cmd_ioba.va = (u64)evt->crq.ioba +
-		offsetof(struct ibmvfc_passthru_mad, iu);
-	mad->cmd_ioba.len = sizeof(mad->iu);
+	mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) +
+		offsetof(struct ibmvfc_passthru_mad, iu));
+	mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
 
-	mad->iu.cmd_len = job->request_payload.payload_len;
-	mad->iu.rsp_len = job->reply_payload.payload_len;
-	mad->iu.flags = fc_flags;
-	mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
+	mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len);
+	mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len);
+	mad->iu.flags = cpu_to_be32(fc_flags);
+	mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
 
-	mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list);
-	mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list);
-	mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list);
-	mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list);
-	mad->iu.scsi_id = port_id;
-	mad->iu.tag = (u64)evt;
-	rsp_len = mad->iu.rsp.len;
+	mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list));
+	mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list));
+	mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list));
+	mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list));
+	mad->iu.scsi_id = cpu_to_be64(port_id);
+	mad->iu.tag = cpu_to_be64((u64)evt);
+	rsp_len = be32_to_cpu(mad->iu.rsp.len);
 
 	evt->sync_iu = &rsp_iu;
 	init_completion(&evt->comp);
@@ -1986,15 +1988,15 @@ static int ibmvfc_reset_device(struct sc
 
 		tmf = &evt->iu.cmd;
 		memset(tmf, 0, sizeof(*tmf));
-		tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-		tmf->resp.len = sizeof(tmf->rsp);
-		tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
-		tmf->payload_len = sizeof(tmf->iu);
-		tmf->resp_len = sizeof(tmf->rsp);
-		tmf->cancel_key = (unsigned long)sdev->hostdata;
-		tmf->tgt_scsi_id = rport->port_id;
+		tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+		tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+		tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+		tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+		tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+		tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+		tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
 		int_to_scsilun(sdev->lun, &tmf->iu.lun);
-		tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+		tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
 		tmf->iu.tmf_flags = type;
 		evt->sync_iu = &rsp_iu;
 
@@ -2020,8 +2022,8 @@ static int ibmvfc_reset_device(struct sc
 			rsp_code = fc_rsp->data.info.rsp_code;
 
 		sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) "
-			    "flags: %x fcp_rsp: %x, scsi_status: %x\n",
-			    desc, ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+			    "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc,
+			    ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
 			    rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
 			    fc_rsp->scsi_status);
 		rsp_rc = -EIO;
@@ -2185,19 +2187,19 @@ static int ibmvfc_cancel_all(struct scsi
 
 		tmf = &evt->iu.tmf;
 		memset(tmf, 0, sizeof(*tmf));
-		tmf->common.version = 1;
-		tmf->common.opcode = IBMVFC_TMF_MAD;
-		tmf->common.length = sizeof(*tmf);
-		tmf->scsi_id = rport->port_id;
+		tmf->common.version = cpu_to_be32(1);
+		tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+		tmf->common.length = cpu_to_be16(sizeof(*tmf));
+		tmf->scsi_id = cpu_to_be64(rport->port_id);
 		int_to_scsilun(sdev->lun, &tmf->lun);
-		if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS))
+		if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS))
 			type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
 		if (vhost->state == IBMVFC_ACTIVE)
-			tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+			tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID));
 		else
-			tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID);
-		tmf->cancel_key = (unsigned long)sdev->hostdata;
-		tmf->my_cancel_key = (unsigned long)starget->hostdata;
+			tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID));
+		tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+		tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata);
 
 		evt->sync_iu = &rsp;
 		init_completion(&evt->comp);
@@ -2217,7 +2219,7 @@ static int ibmvfc_cancel_all(struct scsi
 	sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n");
 
 	wait_for_completion(&evt->comp);
-	status = rsp.mad_common.status;
+	status = be16_to_cpu(rsp.mad_common.status);
 	spin_lock_irqsave(vhost->host->host_lock, flags);
 	ibmvfc_free_event(evt);
 	spin_unlock_irqrestore(vhost->host->host_lock, flags);
@@ -2252,7 +2254,7 @@ static int ibmvfc_match_key(struct ibmvf
 	unsigned long cancel_key = (unsigned long)key;
 
 	if (evt->crq.format == IBMVFC_CMD_FORMAT &&
-	    evt->iu.cmd.cancel_key == cancel_key)
+	    be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key)
 		return 1;
 	return 0;
 }
@@ -2316,15 +2318,15 @@ static int ibmvfc_abort_task_set(struct
 
 		tmf = &evt->iu.cmd;
 		memset(tmf, 0, sizeof(*tmf));
-		tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
-		tmf->resp.len = sizeof(tmf->rsp);
-		tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
-		tmf->payload_len = sizeof(tmf->iu);
-		tmf->resp_len = sizeof(tmf->rsp);
-		tmf->cancel_key = (unsigned long)sdev->hostdata;
-		tmf->tgt_scsi_id = rport->port_id;
+		tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+		tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+		tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+		tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+		tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+		tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+		tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
 		int_to_scsilun(sdev->lun, &tmf->iu.lun);
-		tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+		tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
 		tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET;
 		evt->sync_iu = &rsp_iu;
 
@@ -2380,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct
 
 		sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) "
 			    "flags: %x fcp_rsp: %x, scsi_status: %x\n",
-			    ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+			    ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
 			    rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
 			    fc_rsp->scsi_status);
 		rsp_rc = -EIO;
@@ -2641,14 +2643,14 @@ static const char *ibmvfc_get_link_state
 static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
 				struct ibmvfc_host *vhost)
 {
-	const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
+	const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event));
 	struct ibmvfc_target *tgt;
 
 	ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
 		   " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
 		   ibmvfc_get_link_state(crq->link_state));
 
-	switch (crq->event) {
+	switch (be64_to_cpu(crq->event)) {
 	case IBMVFC_AE_RESUME:
 		switch (crq->link_state) {
 		case IBMVFC_AE_LS_LINK_DOWN:
@@ -2691,15 +2693,15 @@ static void ibmvfc_handle_async(struct i
 		list_for_each_entry(tgt, &vhost->targets, queue) {
 			if (!crq->scsi_id && !crq->wwpn && !crq->node_name)
 				break;
-			if (crq->scsi_id && tgt->scsi_id != crq->scsi_id)
+			if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id)
 				continue;
-			if (crq->wwpn && tgt->ids.port_name != crq->wwpn)
+			if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn)
 				continue;
-			if (crq->node_name && tgt->ids.node_name != crq->node_name)
+			if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name)
 				continue;
-			if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO)
+			if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO)
 				tgt->logo_rcvd = 1;
-			if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) {
+			if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) {
 				ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 				ibmvfc_reinit_host(vhost);
 			}
@@ -2730,7 +2732,7 @@ static void ibmvfc_handle_async(struct i
 static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
 {
 	long rc;
-	struct ibmvfc_event *evt = (struct ibmvfc_event *)crq->ioba;
+	struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba);
 
 	switch (crq->valid) {
 	case IBMVFC_CRQ_INIT_RSP:
@@ -3336,7 +3338,7 @@ static void ibmvfc_tgt_prli_done(struct
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
 	struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
-	u32 status = rsp->common.status;
+	u32 status = be16_to_cpu(rsp->common.status);
 	int index, level = IBMVFC_DEFAULT_LOG_LEVEL;
 
 	vhost->discovery_threads--;
@@ -3347,14 +3349,14 @@ static void ibmvfc_tgt_prli_done(struct
 			parms->type, parms->flags, parms->service_parms);
 
 		if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
-			index = ibmvfc_get_prli_rsp(parms->flags);
+			index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags));
 			if (prli_rsp[index].logged_in) {
-				if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) {
+				if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) {
 					tgt->need_login = 0;
 					tgt->ids.roles = 0;
-					if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC)
+					if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC)
 						tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
-					if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
+					if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC)
 						tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
 					tgt->add_rport = 1;
 				} else
@@ -3373,17 +3375,18 @@ static void ibmvfc_tgt_prli_done(struct
 		break;
 	case IBMVFC_MAD_FAILED:
 	default:
-		if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED)
+		if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) &&
+		     be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED)
 			level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
 		else if (tgt->logo_rcvd)
 			level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
-		else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+		else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
 			level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
 		else
 			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
 		tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
-			ibmvfc_get_cmd_error(rsp->status, rsp->error),
+			ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
 			rsp->status, rsp->error, status);
 		break;
 	};
@@ -3414,14 +3417,14 @@ static void ibmvfc_tgt_send_prli(struct
 	evt->tgt = tgt;
 	prli = &evt->iu.prli;
 	memset(prli, 0, sizeof(*prli));
-	prli->common.version = 1;
-	prli->common.opcode = IBMVFC_PROCESS_LOGIN;
-	prli->common.length = sizeof(*prli);
-	prli->scsi_id = tgt->scsi_id;
+	prli->common.version = cpu_to_be32(1);
+	prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN);
+	prli->common.length = cpu_to_be16(sizeof(*prli));
+	prli->scsi_id = cpu_to_be64(tgt->scsi_id);
 
 	prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
-	prli->parms.flags = IBMVFC_PRLI_EST_IMG_PAIR;
-	prli->parms.service_parms = IBMVFC_PRLI_INITIATOR_FUNC;
+	prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
+	prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
 
 	ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
 	if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3442,7 +3445,7 @@ static void ibmvfc_tgt_plogi_done(struct
 	struct ibmvfc_target *tgt = evt->tgt;
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi;
-	u32 status = rsp->common.status;
+	u32 status = be16_to_cpu(rsp->common.status);
 	int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
 	vhost->discovery_threads--;
@@ -3472,15 +3475,15 @@ static void ibmvfc_tgt_plogi_done(struct
 		break;
 	case IBMVFC_MAD_FAILED:
 	default:
-		if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+		if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
 			level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
 		else
 			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
 		tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-			ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
-			ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
-			ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status);
+			ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error,
+			ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type,
+			ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status);
 		break;
 	};
 
@@ -3512,10 +3515,10 @@ static void ibmvfc_tgt_send_plogi(struct
 	evt->tgt = tgt;
 	plogi = &evt->iu.plogi;
 	memset(plogi, 0, sizeof(*plogi));
-	plogi->common.version = 1;
-	plogi->common.opcode = IBMVFC_PORT_LOGIN;
-	plogi->common.length = sizeof(*plogi);
-	plogi->scsi_id = tgt->scsi_id;
+	plogi->common.version = cpu_to_be32(1);
+	plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+	plogi->common.length = cpu_to_be16(sizeof(*plogi));
+	plogi->scsi_id = cpu_to_be64(tgt->scsi_id);
 
 	if (ibmvfc_send_event(evt, vhost, default_timeout)) {
 		vhost->discovery_threads--;
@@ -3535,7 +3538,7 @@ static void ibmvfc_tgt_implicit_logout_d
 	struct ibmvfc_target *tgt = evt->tgt;
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout;
-	u32 status = rsp->common.status;
+	u32 status = be16_to_cpu(rsp->common.status);
 
 	vhost->discovery_threads--;
 	ibmvfc_free_event(evt);
@@ -3585,10 +3588,10 @@ static void ibmvfc_tgt_implicit_logout(s
 	evt->tgt = tgt;
 	mad = &evt->iu.implicit_logout;
 	memset(mad, 0, sizeof(*mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_IMPLICIT_LOGOUT;
-	mad->common.length = sizeof(*mad);
-	mad->old_scsi_id = tgt->scsi_id;
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT);
+	mad->common.length = cpu_to_be16(sizeof(*mad));
+	mad->old_scsi_id = cpu_to_be64(tgt->scsi_id);
 
 	ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
 	if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3616,7 +3619,7 @@ static int ibmvfc_adisc_needs_plogi(stru
 	if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
 		   sizeof(tgt->ids.node_name)))
 		return 1;
-	if (mad->fc_iu.response[6] != tgt->scsi_id)
+	if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id)
 		return 1;
 	return 0;
 }
@@ -3631,7 +3634,7 @@ static void ibmvfc_tgt_adisc_done(struct
 	struct ibmvfc_target *tgt = evt->tgt;
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
-	u32 status = mad->common.status;
+	u32 status = be16_to_cpu(mad->common.status);
 	u8 fc_reason, fc_explain;
 
 	vhost->discovery_threads--;
@@ -3649,10 +3652,10 @@ static void ibmvfc_tgt_adisc_done(struct
 	case IBMVFC_MAD_FAILED:
 	default:
 		ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
-		fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
-		fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
+		fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16;
+		fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8;
 		tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-			 ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
+			 ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)),
 			 mad->iu.status, mad->iu.error,
 			 ibmvfc_get_fc_type(fc_reason), fc_reason,
 			 ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
@@ -3674,22 +3677,22 @@ static void ibmvfc_init_passthru(struct
 	struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
 
 	memset(mad, 0, sizeof(*mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_PASSTHRU;
-	mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
-	mad->cmd_ioba.va = (u64)evt->crq.ioba +
-		offsetof(struct ibmvfc_passthru_mad, iu);
-	mad->cmd_ioba.len = sizeof(mad->iu);
-	mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
-	mad->iu.rsp_len = sizeof(mad->fc_iu.response);
-	mad->iu.cmd.va = (u64)evt->crq.ioba +
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+	mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
+	mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
+		offsetof(struct ibmvfc_passthru_mad, iu));
+	mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
+	mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+	mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response));
+	mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
 		offsetof(struct ibmvfc_passthru_mad, fc_iu) +
-		offsetof(struct ibmvfc_passthru_fc_iu, payload);
-	mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
-	mad->iu.rsp.va = (u64)evt->crq.ioba +
+		offsetof(struct ibmvfc_passthru_fc_iu, payload));
+	mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+	mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
 		offsetof(struct ibmvfc_passthru_mad, fc_iu) +
-		offsetof(struct ibmvfc_passthru_fc_iu, response);
-	mad->iu.rsp.len = sizeof(mad->fc_iu.response);
+		offsetof(struct ibmvfc_passthru_fc_iu, response));
+	mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response));
 }
 
 /**
@@ -3748,11 +3751,11 @@ static void ibmvfc_adisc_timeout(struct
 	evt->tgt = tgt;
 	tmf = &evt->iu.tmf;
 	memset(tmf, 0, sizeof(*tmf));
-	tmf->common.version = 1;
-	tmf->common.opcode = IBMVFC_TMF_MAD;
-	tmf->common.length = sizeof(*tmf);
-	tmf->scsi_id = tgt->scsi_id;
-	tmf->cancel_key = tgt->cancel_key;
+	tmf->common.version = cpu_to_be32(1);
+	tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+	tmf->common.length = cpu_to_be16(sizeof(*tmf));
+	tmf->scsi_id = cpu_to_be64(tgt->scsi_id);
+	tmf->cancel_key = cpu_to_be32(tgt->cancel_key);
 
 	rc = ibmvfc_send_event(evt, vhost, default_timeout);
 
@@ -3794,16 +3797,16 @@ static void ibmvfc_tgt_adisc(struct ibmv
 
 	ibmvfc_init_passthru(evt);
 	mad = &evt->iu.passthru;
-	mad->iu.flags = IBMVFC_FC_ELS;
-	mad->iu.scsi_id = tgt->scsi_id;
-	mad->iu.cancel_key = tgt->cancel_key;
+	mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS);
+	mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id);
+	mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key);
 
-	mad->fc_iu.payload[0] = IBMVFC_ADISC;
+	mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC);
 	memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
 	       sizeof(vhost->login_buf->resp.port_name));
 	memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
 	       sizeof(vhost->login_buf->resp.node_name));
-	mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+	mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff);
 
 	if (timer_pending(&tgt->timer))
 		mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ));
@@ -3834,7 +3837,7 @@ static void ibmvfc_tgt_query_target_done
 	struct ibmvfc_target *tgt = evt->tgt;
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt;
-	u32 status = rsp->common.status;
+	u32 status = be16_to_cpu(rsp->common.status);
 	int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
 	vhost->discovery_threads--;
@@ -3842,8 +3845,8 @@ static void ibmvfc_tgt_query_target_done
 	switch (status) {
 	case IBMVFC_MAD_SUCCESS:
 		tgt_dbg(tgt, "Query Target succeeded\n");
-		tgt->new_scsi_id = rsp->scsi_id;
-		if (rsp->scsi_id != tgt->scsi_id)
+		tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id);
+		if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id)
 			ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
 		else
 			ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
@@ -3855,19 +3858,20 @@ static void ibmvfc_tgt_query_target_done
 		break;
 	case IBMVFC_MAD_FAILED:
 	default:
-		if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
-		    rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ &&
-		    rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG)
+		if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
+		    be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ &&
+		    be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG)
 			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
-		else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+		else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
 			level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
 		else
 			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
 		tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-			ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
-			ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
-			ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status);
+			ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+			rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)),
+			rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)),
+			rsp->fc_explain, status);
 		break;
 	};
 
@@ -3897,10 +3901,10 @@ static void ibmvfc_tgt_query_target(stru
 	ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT);
 	query_tgt = &evt->iu.query_tgt;
 	memset(query_tgt, 0, sizeof(*query_tgt));
-	query_tgt->common.version = 1;
-	query_tgt->common.opcode = IBMVFC_QUERY_TARGET;
-	query_tgt->common.length = sizeof(*query_tgt);
-	query_tgt->wwpn = tgt->ids.port_name;
+	query_tgt->common.version = cpu_to_be32(1);
+	query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET);
+	query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt));
+	query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name);
 
 	ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
 	if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3971,7 +3975,8 @@ static int ibmvfc_alloc_targets(struct i
 
 	for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++)
 		rc = ibmvfc_alloc_target(vhost,
-					 vhost->disc_buf->scsi_id[i] & IBMVFC_DISC_TGT_SCSI_ID_MASK);
+					 be32_to_cpu(vhost->disc_buf->scsi_id[i]) &
+					 IBMVFC_DISC_TGT_SCSI_ID_MASK);
 
 	return rc;
 }
@@ -3985,19 +3990,20 @@ static void ibmvfc_discover_targets_done
 {
 	struct ibmvfc_host *vhost = evt->vhost;
 	struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets;
-	u32 mad_status = rsp->common.status;
+	u32 mad_status = be16_to_cpu(rsp->common.status);
 	int level = IBMVFC_DEFAULT_LOG_LEVEL;
 
 	switch (mad_status) {
 	case IBMVFC_MAD_SUCCESS:
 		ibmvfc_dbg(vhost, "Discover Targets succeeded\n");
-		vhost->num_targets = rsp->num_written;
+		vhost->num_targets = be32_to_cpu(rsp->num_written);
 		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS);
 		break;
 	case IBMVFC_MAD_FAILED:
 		level += ibmvfc_retry_host_init(vhost);
 		ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n",
-			   ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+			   ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+			   rsp->status, rsp->error);
 		break;
 	case IBMVFC_MAD_DRIVER_FAILED:
 		break;
@@ -4024,12 +4030,12 @@ static void ibmvfc_discover_targets(stru
 	ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT);
 	mad = &evt->iu.discover_targets;
 	memset(mad, 0, sizeof(*mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_DISC_TARGETS;
-	mad->common.length = sizeof(*mad);
-	mad->bufflen = vhost->disc_buf_sz;
-	mad->buffer.va = vhost->disc_buf_dma;
-	mad->buffer.len = vhost->disc_buf_sz;
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS);
+	mad->common.length = cpu_to_be16(sizeof(*mad));
+	mad->bufflen = cpu_to_be32(vhost->disc_buf_sz);
+	mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma);
+	mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz);
 	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
 
 	if (!ibmvfc_send_event(evt, vhost, default_timeout))
@@ -4046,7 +4052,7 @@ static void ibmvfc_discover_targets(stru
 static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
 {
 	struct ibmvfc_host *vhost = evt->vhost;
-	u32 mad_status = evt->xfer_iu->npiv_login.common.status;
+	u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status);
 	struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp;
 	unsigned int npiv_max_sectors;
 	int level = IBMVFC_DEFAULT_LOG_LEVEL;
@@ -4056,12 +4062,13 @@ static void ibmvfc_npiv_login_done(struc
 		ibmvfc_free_event(evt);
 		break;
 	case IBMVFC_MAD_FAILED:
-		if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+		if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
 			level += ibmvfc_retry_host_init(vhost);
 		else
 			ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
 		ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n",
-			   ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+			   ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+						rsp->status, rsp->error);
 		ibmvfc_free_event(evt);
 		return;
 	case IBMVFC_MAD_CRQ_ERROR:
@@ -4078,7 +4085,7 @@ static void ibmvfc_npiv_login_done(struc
 
 	vhost->client_migrated = 0;
 
-	if (!(rsp->flags & IBMVFC_NATIVE_FC)) {
+	if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) {
 		dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n",
 			rsp->flags);
 		ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4086,7 +4093,7 @@ static void ibmvfc_npiv_login_done(struc
 		return;
 	}
 
-	if (rsp->max_cmds <= IBMVFC_NUM_INTERNAL_REQ) {
+	if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) {
 		dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n",
 			rsp->max_cmds);
 		ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4095,27 +4102,27 @@ static void ibmvfc_npiv_login_done(struc
 	}
 
 	vhost->logged_in = 1;
-	npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS);
+	npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS);
 	dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n",
 		 rsp->partition_name, rsp->device_name, rsp->port_loc_code,
 		 rsp->drc_name, npiv_max_sectors);
 
-	fc_host_fabric_name(vhost->host) = rsp->node_name;
-	fc_host_node_name(vhost->host) = rsp->node_name;
-	fc_host_port_name(vhost->host) = rsp->port_name;
-	fc_host_port_id(vhost->host) = rsp->scsi_id;
+	fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name);
+	fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name);
+	fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name);
+	fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id);
 	fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV;
 	fc_host_supported_classes(vhost->host) = 0;
-	if (rsp->service_parms.class1_parms[0] & 0x80000000)
+	if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000)
 		fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1;
-	if (rsp->service_parms.class2_parms[0] & 0x80000000)
+	if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000)
 		fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2;
-	if (rsp->service_parms.class3_parms[0] & 0x80000000)
+	if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000)
 		fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3;
 	fc_host_maxframe_size(vhost->host) =
-		rsp->service_parms.common.bb_rcv_sz & 0x0fff;
+		be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff;
 
-	vhost->host->can_queue = rsp->max_cmds - IBMVFC_NUM_INTERNAL_REQ;
+	vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ;
 	vhost->host->max_sectors = npiv_max_sectors;
 	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
 	wake_up(&vhost->work_wait_q);
@@ -4138,11 +4145,11 @@ static void ibmvfc_npiv_login(struct ibm
 	memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info));
 	mad = &evt->iu.npiv_login;
 	memset(mad, 0, sizeof(struct ibmvfc_npiv_login_mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_NPIV_LOGIN;
-	mad->common.length = sizeof(struct ibmvfc_npiv_login_mad);
-	mad->buffer.va = vhost->login_buf_dma;
-	mad->buffer.len = sizeof(*vhost->login_buf);
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN);
+	mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad));
+	mad->buffer.va = cpu_to_be64(vhost->login_buf_dma);
+	mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf));
 
 	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
 
@@ -4160,7 +4167,7 @@ static void ibmvfc_npiv_login(struct ibm
 static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt)
 {
 	struct ibmvfc_host *vhost = evt->vhost;
-	u32 mad_status = evt->xfer_iu->npiv_logout.common.status;
+	u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status);
 
 	ibmvfc_free_event(evt);
 
@@ -4199,9 +4206,9 @@ static void ibmvfc_npiv_logout(struct ib
 
 	mad = &evt->iu.npiv_logout;
 	memset(mad, 0, sizeof(*mad));
-	mad->common.version = 1;
-	mad->common.opcode = IBMVFC_NPIV_LOGOUT;
-	mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad);
+	mad->common.version = cpu_to_be32(1);
+	mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT);
+	mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad));
 
 	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT);
 
@@ -4343,14 +4350,14 @@ static void ibmvfc_tgt_add_rport(struct
 	if (rport) {
 		tgt_dbg(tgt, "rport add succeeded\n");
 		tgt->rport = rport;
-		rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
+		rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff;
 		rport->supported_classes = 0;
 		tgt->target_id = rport->scsi_target_id;
-		if (tgt->service_parms.class1_parms[0] & 0x80000000)
+		if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000)
 			rport->supported_classes |= FC_COS_CLASS1;
-		if (tgt->service_parms.class2_parms[0] & 0x80000000)
+		if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000)
 			rport->supported_classes |= FC_COS_CLASS2;
-		if (tgt->service_parms.class3_parms[0] & 0x80000000)
+		if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000)
 			rport->supported_classes |= FC_COS_CLASS3;
 		if (rport->rqst_q)
 			blk_queue_max_segments(rport->rqst_q, 1);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvfc.h linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvfc.h
--- linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvfc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvfc.h	2014-09-28 17:29:07.000000000 -0400
@@ -135,12 +135,12 @@ enum ibmvfc_mad_types {
 };
 
 struct ibmvfc_mad_common {
-	u32 version;
-	u32 reserved;
-	u32 opcode;
-	u16 status;
-	u16 length;
-	u64 tag;
+	__be32 version;
+	__be32 reserved;
+	__be32 opcode;
+	__be16 status;
+	__be16 length;
+	__be64 tag;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_npiv_login_mad {
@@ -155,76 +155,76 @@ struct ibmvfc_npiv_logout_mad {
 #define IBMVFC_MAX_NAME 256
 
 struct ibmvfc_npiv_login {
-	u32 ostype;
+	__be32 ostype;
 #define IBMVFC_OS_LINUX	0x02
-	u32 pad;
-	u64 max_dma_len;
-	u32 max_payload;
-	u32 max_response;
-	u32 partition_num;
-	u32 vfc_frame_version;
-	u16 fcp_version;
-	u16 flags;
+	__be32 pad;
+	__be64 max_dma_len;
+	__be32 max_payload;
+	__be32 max_response;
+	__be32 partition_num;
+	__be32 vfc_frame_version;
+	__be16 fcp_version;
+	__be16 flags;
 #define IBMVFC_CLIENT_MIGRATED	0x01
 #define IBMVFC_FLUSH_ON_HALT		0x02
-	u32 max_cmds;
-	u64 capabilities;
+	__be32 max_cmds;
+	__be64 capabilities;
 #define IBMVFC_CAN_MIGRATE		0x01
-	u64 node_name;
+	__be64 node_name;
 	struct srp_direct_buf async;
 	u8 partition_name[IBMVFC_MAX_NAME];
 	u8 device_name[IBMVFC_MAX_NAME];
 	u8 drc_name[IBMVFC_MAX_NAME];
-	u64 reserved2[2];
+	__be64 reserved2[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_common_svc_parms {
-	u16 fcph_version;
-	u16 b2b_credit;
-	u16 features;
-	u16 bb_rcv_sz; /* upper nibble is BB_SC_N */
-	u32 ratov;
-	u32 edtov;
+	__be16 fcph_version;
+	__be16 b2b_credit;
+	__be16 features;
+	__be16 bb_rcv_sz; /* upper nibble is BB_SC_N */
+	__be32 ratov;
+	__be32 edtov;
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_service_parms {
 	struct ibmvfc_common_svc_parms common;
 	u8 port_name[8];
 	u8 node_name[8];
-	u32 class1_parms[4];
-	u32 class2_parms[4];
-	u32 class3_parms[4];
-	u32 obsolete[4];
-	u32 vendor_version[4];
-	u32 services_avail[2];
-	u32 ext_len;
-	u32 reserved[30];
-	u32 clk_sync_qos[2];
+	__be32 class1_parms[4];
+	__be32 class2_parms[4];
+	__be32 class3_parms[4];
+	__be32 obsolete[4];
+	__be32 vendor_version[4];
+	__be32 services_avail[2];
+	__be32 ext_len;
+	__be32 reserved[30];
+	__be32 clk_sync_qos[2];
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_npiv_login_resp {
-	u32 version;
-	u16 status;
-	u16 error;
-	u32 flags;
+	__be32 version;
+	__be16 status;
+	__be16 error;
+	__be32 flags;
 #define IBMVFC_NATIVE_FC		0x01
-	u32 reserved;
-	u64 capabilities;
+	__be32 reserved;
+	__be64 capabilities;
 #define IBMVFC_CAN_FLUSH_ON_HALT	0x08
 #define IBMVFC_CAN_SUPPRESS_ABTS	0x10
-	u32 max_cmds;
-	u32 scsi_id_sz;
-	u64 max_dma_len;
-	u64 scsi_id;
-	u64 port_name;
-	u64 node_name;
-	u64 link_speed;
+	__be32 max_cmds;
+	__be32 scsi_id_sz;
+	__be64 max_dma_len;
+	__be64 scsi_id;
+	__be64 port_name;
+	__be64 node_name;
+	__be64 link_speed;
 	u8 partition_name[IBMVFC_MAX_NAME];
 	u8 device_name[IBMVFC_MAX_NAME];
 	u8 port_loc_code[IBMVFC_MAX_NAME];
 	u8 drc_name[IBMVFC_MAX_NAME];
 	struct ibmvfc_service_parms service_parms;
-	u64 reserved2;
+	__be64 reserved2;
 }__attribute__((packed, aligned (8)));
 
 union ibmvfc_npiv_login_data {
@@ -233,20 +233,20 @@ union ibmvfc_npiv_login_data {
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_discover_targets_buf {
-	u32 scsi_id[1];
+	__be32 scsi_id[1];
 #define IBMVFC_DISC_TGT_SCSI_ID_MASK	0x00ffffff
 };
 
 struct ibmvfc_discover_targets {
 	struct ibmvfc_mad_common common;
 	struct srp_direct_buf buffer;
-	u32 flags;
-	u16 status;
-	u16 error;
-	u32 bufflen;
-	u32 num_avail;
-	u32 num_written;
-	u64 reserved[2];
+	__be32 flags;
+	__be16 status;
+	__be16 error;
+	__be32 bufflen;
+	__be32 num_avail;
+	__be32 num_written;
+	__be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 enum ibmvfc_fc_reason {
@@ -278,32 +278,32 @@ enum ibmvfc_gs_explain {
 
 struct ibmvfc_port_login {
 	struct ibmvfc_mad_common common;
-	u64 scsi_id;
-	u16 reserved;
-	u16 fc_service_class;
-	u32 blksz;
-	u32 hdr_per_blk;
-	u16 status;
-	u16 error;		/* also fc_reason */
-	u16 fc_explain;
-	u16 fc_type;
-	u32 reserved2;
+	__be64 scsi_id;
+	__be16 reserved;
+	__be16 fc_service_class;
+	__be32 blksz;
+	__be32 hdr_per_blk;
+	__be16 status;
+	__be16 error;		/* also fc_reason */
+	__be16 fc_explain;
+	__be16 fc_type;
+	__be32 reserved2;
 	struct ibmvfc_service_parms service_parms;
 	struct ibmvfc_service_parms service_parms_change;
-	u64 reserved3[2];
+	__be64 reserved3[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_prli_svc_parms {
 	u8 type;
 #define IBMVFC_SCSI_FCP_TYPE		0x08
 	u8 type_ext;
-	u16 flags;
+	__be16 flags;
 #define IBMVFC_PRLI_ORIG_PA_VALID			0x8000
 #define IBMVFC_PRLI_RESP_PA_VALID			0x4000
 #define IBMVFC_PRLI_EST_IMG_PAIR			0x2000
-	u32 orig_pa;
-	u32 resp_pa;
-	u32 service_parms;
+	__be32 orig_pa;
+	__be32 resp_pa;
+	__be32 service_parms;
 #define IBMVFC_PRLI_TASK_RETRY			0x00000200
 #define IBMVFC_PRLI_RETRY				0x00000100
 #define IBMVFC_PRLI_DATA_OVERLAY			0x00000040
@@ -315,47 +315,47 @@ struct ibmvfc_prli_svc_parms {
 
 struct ibmvfc_process_login {
 	struct ibmvfc_mad_common common;
-	u64 scsi_id;
+	__be64 scsi_id;
 	struct ibmvfc_prli_svc_parms parms;
 	u8 reserved[48];
-	u16 status;
-	u16 error;			/* also fc_reason */
-	u32 reserved2;
-	u64 reserved3[2];
+	__be16 status;
+	__be16 error;			/* also fc_reason */
+	__be32 reserved2;
+	__be64 reserved3[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_query_tgt {
 	struct ibmvfc_mad_common common;
-	u64 wwpn;
-	u64 scsi_id;
-	u16 status;
-	u16 error;
-	u16 fc_explain;
-	u16 fc_type;
-	u64 reserved[2];
+	__be64 wwpn;
+	__be64 scsi_id;
+	__be16 status;
+	__be16 error;
+	__be16 fc_explain;
+	__be16 fc_type;
+	__be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_implicit_logout {
 	struct ibmvfc_mad_common common;
-	u64 old_scsi_id;
-	u64 reserved[2];
+	__be64 old_scsi_id;
+	__be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_tmf {
 	struct ibmvfc_mad_common common;
-	u64 scsi_id;
+	__be64 scsi_id;
 	struct scsi_lun lun;
-	u32 flags;
+	__be32 flags;
 #define IBMVFC_TMF_ABORT_TASK		0x02
 #define IBMVFC_TMF_ABORT_TASK_SET	0x04
 #define IBMVFC_TMF_LUN_RESET		0x10
 #define IBMVFC_TMF_TGT_RESET		0x20
 #define IBMVFC_TMF_LUA_VALID		0x40
 #define IBMVFC_TMF_SUPPRESS_ABTS	0x80
-	u32 cancel_key;
-	u32 my_cancel_key;
-	u32 pad;
-	u64 reserved[2];
+	__be32 cancel_key;
+	__be32 my_cancel_key;
+	__be32 pad;
+	__be64 reserved[2];
 }__attribute__((packed, aligned (8)));
 
 enum ibmvfc_fcp_rsp_info_codes {
@@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes {
 };
 
 struct ibmvfc_fcp_rsp_info {
-	u16 reserved;
+	__be16 reserved;
 	u8 rsp_code;
 	u8 reserved2[4];
 }__attribute__((packed, aligned (2)));
@@ -388,13 +388,13 @@ union ibmvfc_fcp_rsp_data {
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_fcp_rsp {
-	u64 reserved;
-	u16 retry_delay_timer;
+	__be64 reserved;
+	__be16 retry_delay_timer;
 	u8 flags;
 	u8 scsi_status;
-	u32 fcp_resid;
-	u32 fcp_sense_len;
-	u32 fcp_rsp_len;
+	__be32 fcp_resid;
+	__be32 fcp_sense_len;
+	__be32 fcp_rsp_len;
 	union ibmvfc_fcp_rsp_data data;
 }__attribute__((packed, aligned (8)));
 
@@ -429,58 +429,58 @@ struct ibmvfc_fcp_cmd_iu {
 #define IBMVFC_RDDATA		0x02
 #define IBMVFC_WRDATA		0x01
 	u8 cdb[IBMVFC_MAX_CDB_LEN];
-	u32 xfer_len;
+	__be32 xfer_len;
 }__attribute__((packed, aligned (4)));
 
 struct ibmvfc_cmd {
-	u64 task_tag;
-	u32 frame_type;
-	u32 payload_len;
-	u32 resp_len;
-	u32 adapter_resid;
-	u16 status;
-	u16 error;
-	u16 flags;
-	u16 response_flags;
+	__be64 task_tag;
+	__be32 frame_type;
+	__be32 payload_len;
+	__be32 resp_len;
+	__be32 adapter_resid;
+	__be16 status;
+	__be16 error;
+	__be16 flags;
+	__be16 response_flags;
 #define IBMVFC_ADAPTER_RESID_VALID	0x01
-	u32 cancel_key;
-	u32 exchange_id;
+	__be32 cancel_key;
+	__be32 exchange_id;
 	struct srp_direct_buf ext_func;
 	struct srp_direct_buf ioba;
 	struct srp_direct_buf resp;
-	u64 correlation;
-	u64 tgt_scsi_id;
-	u64 tag;
-	u64 reserved3[2];
+	__be64 correlation;
+	__be64 tgt_scsi_id;
+	__be64 tag;
+	__be64 reserved3[2];
 	struct ibmvfc_fcp_cmd_iu iu;
 	struct ibmvfc_fcp_rsp rsp;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_passthru_fc_iu {
-	u32 payload[7];
+	__be32 payload[7];
 #define IBMVFC_ADISC	0x52000000
-	u32 response[7];
+	__be32 response[7];
 };
 
 struct ibmvfc_passthru_iu {
-	u64 task_tag;
-	u32 cmd_len;
-	u32 rsp_len;
-	u16 status;
-	u16 error;
-	u32 flags;
+	__be64 task_tag;
+	__be32 cmd_len;
+	__be32 rsp_len;
+	__be16 status;
+	__be16 error;
+	__be32 flags;
 #define IBMVFC_FC_ELS		0x01
 #define IBMVFC_FC_CT_IU		0x02
-	u32 cancel_key;
+	__be32 cancel_key;
 #define IBMVFC_PASSTHRU_CANCEL_KEY	0x80000000
 #define IBMVFC_INTERNAL_CANCEL_KEY	0x80000001
-	u32 reserved;
+	__be32 reserved;
 	struct srp_direct_buf cmd;
 	struct srp_direct_buf rsp;
-	u64 correlation;
-	u64 scsi_id;
-	u64 tag;
-	u64 reserved2[2];
+	__be64 correlation;
+	__be64 scsi_id;
+	__be64 tag;
+	__be64 reserved2[2];
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_passthru_mad {
@@ -552,7 +552,7 @@ struct ibmvfc_crq {
 	volatile u8 valid;
 	volatile u8 format;
 	u8 reserved[6];
-	volatile u64 ioba;
+	volatile __be64 ioba;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_crq_queue {
@@ -572,12 +572,12 @@ struct ibmvfc_async_crq {
 	volatile u8 valid;
 	u8 link_state;
 	u8 pad[2];
-	u32 pad2;
-	volatile u64 event;
-	volatile u64 scsi_id;
-	volatile u64 wwpn;
-	volatile u64 node_name;
-	u64 reserved;
+	__be32 pad2;
+	volatile __be64 event;
+	volatile __be64 scsi_id;
+	volatile __be64 wwpn;
+	volatile __be64 node_name;
+	__be64 reserved;
 }__attribute__((packed, aligned (8)));
 
 struct ibmvfc_async_crq_queue {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvstgt.c linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvstgt.c
--- linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/ibmvstgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/ibmvstgt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1001 +0,0 @@
-/*
- * IBM eServer i/pSeries Virtual SCSI Target Driver
- * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp.
- *			   Santiago Leon (santil@us.ibm.com) IBM Corp.
- *			   Linda Xie (lxie@us.ibm.com) IBM Corp.
- *
- * Copyright (C) 2005-2006 FUJITA Tomonori <tomof@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport_srp.h>
-#include <scsi/scsi_tgt.h>
-#include <scsi/libsrp.h>
-#include <asm/hvcall.h>
-#include <asm/iommu.h>
-#include <asm/prom.h>
-#include <asm/vio.h>
-
-#include "ibmvscsi.h"
-
-#define	INITIAL_SRP_LIMIT	16
-#define	DEFAULT_MAX_SECTORS	256
-
-#define	TGT_NAME	"ibmvstgt"
-
-/*
- * Hypervisor calls.
- */
-#define h_copy_rdma(l, sa, sb, da, db) \
-			plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db)
-#define h_send_crq(ua, l, h) \
-			plpar_hcall_norets(H_SEND_CRQ, ua, l, h)
-#define h_reg_crq(ua, tok, sz)\
-			plpar_hcall_norets(H_REG_CRQ, ua, tok, sz);
-#define h_free_crq(ua) \
-			plpar_hcall_norets(H_FREE_CRQ, ua);
-
-/* tmp - will replace with SCSI logging stuff */
-#define eprintk(fmt, args...)					\
-do {								\
-	printk("%s(%d) " fmt, __func__, __LINE__, ##args);	\
-} while (0)
-/* #define dprintk eprintk */
-#define dprintk(fmt, args...)
-
-struct vio_port {
-	struct vio_dev *dma_dev;
-
-	struct crq_queue crq_queue;
-	struct work_struct crq_work;
-
-	unsigned long liobn;
-	unsigned long riobn;
-	struct srp_target *target;
-
-	struct srp_rport *rport;
-};
-
-static struct workqueue_struct *vtgtd;
-static struct scsi_transport_template *ibmvstgt_transport_template;
-
-/*
- * These are fixed for the system and come from the Open Firmware device tree.
- * We just store them here to save getting them every time.
- */
-static char system_id[64] = "";
-static char partition_name[97] = "UNKNOWN";
-static unsigned int partition_number = -1;
-
-static struct vio_port *target_to_port(struct srp_target *target)
-{
-	return (struct vio_port *) target->ldata;
-}
-
-static inline union viosrp_iu *vio_iu(struct iu_entry *iue)
-{
-	return (union viosrp_iu *) (iue->sbuf->buf);
-}
-
-static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format)
-{
-	struct srp_target *target = iue->target;
-	struct vio_port *vport = target_to_port(target);
-	long rc, rc1;
-	union {
-		struct viosrp_crq cooked;
-		uint64_t raw[2];
-	} crq;
-
-	/* First copy the SRP */
-	rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma,
-			 vport->riobn, iue->remote_token);
-
-	if (rc)
-		eprintk("Error %ld transferring data\n", rc);
-
-	crq.cooked.valid = 0x80;
-	crq.cooked.format = format;
-	crq.cooked.reserved = 0x00;
-	crq.cooked.timeout = 0x00;
-	crq.cooked.IU_length = length;
-	crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag;
-
-	if (rc == 0)
-		crq.cooked.status = 0x99;	/* Just needs to be non-zero */
-	else
-		crq.cooked.status = 0x00;
-
-	rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]);
-
-	if (rc1) {
-		eprintk("%ld sending response\n", rc1);
-		return rc1;
-	}
-
-	return rc;
-}
-
-#define SRP_RSP_SENSE_DATA_LEN	18
-
-static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc,
-		    unsigned char status, unsigned char asc)
-{
-	union viosrp_iu *iu = vio_iu(iue);
-	uint64_t tag = iu->srp.rsp.tag;
-
-	/* If the linked bit is on and status is good */
-	if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE))
-		status = 0x10;
-
-	memset(iu, 0, sizeof(struct srp_rsp));
-	iu->srp.rsp.opcode = SRP_RSP;
-	iu->srp.rsp.req_lim_delta = 1;
-	iu->srp.rsp.tag = tag;
-
-	if (test_bit(V_DIOVER, &iue->flags))
-		iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER;
-
-	iu->srp.rsp.data_in_res_cnt = 0;
-	iu->srp.rsp.data_out_res_cnt = 0;
-
-	iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID;
-
-	iu->srp.rsp.resp_data_len = 0;
-	iu->srp.rsp.status = status;
-	if (status) {
-		uint8_t *sense = iu->srp.rsp.data;
-
-		if (sc) {
-			iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
-			iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE;
-			memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE);
-		} else {
-			iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION;
-			iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
-			iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN;
-
-			/* Valid bit and 'current errors' */
-			sense[0] = (0x1 << 7 | 0x70);
-			/* Sense key */
-			sense[2] = status;
-			/* Additional sense length */
-			sense[7] = 0xa;	/* 10 bytes */
-			/* Additional sense code */
-			sense[12] = asc;
-		}
-	}
-
-	send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN,
-		VIOSRP_SRP_FORMAT);
-
-	return 0;
-}
-
-static void handle_cmd_queue(struct srp_target *target)
-{
-	struct Scsi_Host *shost = target->shost;
-	struct srp_rport *rport = target_to_port(target)->rport;
-	struct iu_entry *iue;
-	struct srp_cmd *cmd;
-	unsigned long flags;
-	int err;
-
-retry:
-	spin_lock_irqsave(&target->lock, flags);
-
-	list_for_each_entry(iue, &target->cmd_queue, ilist) {
-		if (!test_and_set_bit(V_FLYING, &iue->flags)) {
-			spin_unlock_irqrestore(&target->lock, flags);
-			cmd = iue->sbuf->buf;
-			err = srp_cmd_queue(shost, cmd, iue,
-					    (unsigned long)rport, 0);
-			if (err) {
-				eprintk("cannot queue cmd %p %d\n", cmd, err);
-				srp_iu_put(iue);
-			}
-			goto retry;
-		}
-	}
-
-	spin_unlock_irqrestore(&target->lock, flags);
-}
-
-static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
-			 struct srp_direct_buf *md, int nmd,
-			 enum dma_data_direction dir, unsigned int rest)
-{
-	struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-	struct srp_target *target = iue->target;
-	struct vio_port *vport = target_to_port(target);
-	dma_addr_t token;
-	long err;
-	unsigned int done = 0;
-	int i, sidx, soff;
-
-	sidx = soff = 0;
-	token = sg_dma_address(sg + sidx);
-
-	for (i = 0; i < nmd && rest; i++) {
-		unsigned int mdone, mlen;
-
-		mlen = min(rest, md[i].len);
-		for (mdone = 0; mlen;) {
-			int slen = min(sg_dma_len(sg + sidx) - soff, mlen);
-
-			if (dir == DMA_TO_DEVICE)
-				err = h_copy_rdma(slen,
-						  vport->riobn,
-						  md[i].va + mdone,
-						  vport->liobn,
-						  token + soff);
-			else
-				err = h_copy_rdma(slen,
-						  vport->liobn,
-						  token + soff,
-						  vport->riobn,
-						  md[i].va + mdone);
-
-			if (err != H_SUCCESS) {
-				eprintk("rdma error %d %d %ld\n", dir, slen, err);
-				return -EIO;
-			}
-
-			mlen -= slen;
-			mdone += slen;
-			soff += slen;
-			done += slen;
-
-			if (soff == sg_dma_len(sg + sidx)) {
-				sidx++;
-				soff = 0;
-				token = sg_dma_address(sg + sidx);
-
-				if (sidx > nsg) {
-					eprintk("out of sg %p %d %d\n",
-						iue, sidx, nsg);
-					return -EIO;
-				}
-			}
-		};
-
-		rest -= mlen;
-	}
-	return 0;
-}
-
-static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
-			     void (*done)(struct scsi_cmnd *))
-{
-	unsigned long flags;
-	struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-	struct srp_target *target = iue->target;
-	int err = 0;
-
-	dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
-		scsi_sg_count(sc));
-
-	if (scsi_sg_count(sc))
-		err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
-	spin_lock_irqsave(&target->lock, flags);
-	list_del(&iue->ilist);
-	spin_unlock_irqrestore(&target->lock, flags);
-
-	if (err|| sc->result != SAM_STAT_GOOD) {
-		eprintk("operation failed %p %d %x\n",
-			iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
-		send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
-	} else
-		send_rsp(iue, sc, NO_SENSE, 0x00);
-
-	done(sc);
-	srp_iu_put(iue);
-	return 0;
-}
-
-int send_adapter_info(struct iu_entry *iue,
-		      dma_addr_t remote_buffer, uint16_t length)
-{
-	struct srp_target *target = iue->target;
-	struct vio_port *vport = target_to_port(target);
-	struct Scsi_Host *shost = target->shost;
-	dma_addr_t data_token;
-	struct mad_adapter_info_data *info;
-	int err;
-
-	info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token,
-				  GFP_KERNEL);
-	if (!info) {
-		eprintk("bad dma_alloc_coherent %p\n", target);
-		return 1;
-	}
-
-	/* Get remote info */
-	err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer,
-			  vport->liobn, data_token);
-	if (err == H_SUCCESS) {
-		dprintk("Client connect: %s (%d)\n",
-			info->partition_name, info->partition_number);
-	}
-
-	memset(info, 0, sizeof(*info));
-
-	strcpy(info->srp_version, "16.a");
-	strncpy(info->partition_name, partition_name,
-		sizeof(info->partition_name));
-	info->partition_number = partition_number;
-	info->mad_version = 1;
-	info->os_type = 2;
-	info->port_max_txu[0] = shost->hostt->max_sectors << 9;
-
-	/* Send our info to remote */
-	err = h_copy_rdma(sizeof(*info), vport->liobn, data_token,
-			  vport->riobn, remote_buffer);
-
-	dma_free_coherent(target->dev, sizeof(*info), info, data_token);
-
-	if (err != H_SUCCESS) {
-		eprintk("Error sending adapter info %d\n", err);
-		return 1;
-	}
-
-	return 0;
-}
-
-static void process_login(struct iu_entry *iue)
-{
-	union viosrp_iu *iu = vio_iu(iue);
-	struct srp_login_rsp *rsp = &iu->srp.login_rsp;
-	uint64_t tag = iu->srp.rsp.tag;
-	struct Scsi_Host *shost = iue->target->shost;
-	struct srp_target *target = host_to_srp_target(shost);
-	struct vio_port *vport = target_to_port(target);
-	struct srp_rport_identifiers ids;
-
-	memset(&ids, 0, sizeof(ids));
-	sprintf(ids.port_id, "%x", vport->dma_dev->unit_address);
-	ids.roles = SRP_RPORT_ROLE_INITIATOR;
-	if (!vport->rport)
-		vport->rport = srp_rport_add(shost, &ids);
-
-	/* TODO handle case that requested size is wrong and
-	 * buffer format is wrong
-	 */
-	memset(iu, 0, sizeof(struct srp_login_rsp));
-	rsp->opcode = SRP_LOGIN_RSP;
-	rsp->req_lim_delta = INITIAL_SRP_LIMIT;
-	rsp->tag = tag;
-	rsp->max_it_iu_len = sizeof(union srp_iu);
-	rsp->max_ti_iu_len = sizeof(union srp_iu);
-	/* direct and indirect */
-	rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
-
-	send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT);
-}
-
-static inline void queue_cmd(struct iu_entry *iue)
-{
-	struct srp_target *target = iue->target;
-	unsigned long flags;
-
-	spin_lock_irqsave(&target->lock, flags);
-	list_add_tail(&iue->ilist, &target->cmd_queue);
-	spin_unlock_irqrestore(&target->lock, flags);
-}
-
-static int process_tsk_mgmt(struct iu_entry *iue)
-{
-	union viosrp_iu *iu = vio_iu(iue);
-	int fn;
-
-	dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func);
-
-	switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
-	case SRP_TSK_ABORT_TASK:
-		fn = ABORT_TASK;
-		break;
-	case SRP_TSK_ABORT_TASK_SET:
-		fn = ABORT_TASK_SET;
-		break;
-	case SRP_TSK_CLEAR_TASK_SET:
-		fn = CLEAR_TASK_SET;
-		break;
-	case SRP_TSK_LUN_RESET:
-		fn = LOGICAL_UNIT_RESET;
-		break;
-	case SRP_TSK_CLEAR_ACA:
-		fn = CLEAR_ACA;
-		break;
-	default:
-		fn = 0;
-	}
-	if (fn)
-		scsi_tgt_tsk_mgmt_request(iue->target->shost,
-					  (unsigned long)iue->target->shost,
-					  fn,
-					  iu->srp.tsk_mgmt.task_tag,
-					  (struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
-					  iue);
-	else
-		send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20);
-
-	return !fn;
-}
-
-static int process_mad_iu(struct iu_entry *iue)
-{
-	union viosrp_iu *iu = vio_iu(iue);
-	struct viosrp_adapter_info *info;
-	struct viosrp_host_config *conf;
-
-	switch (iu->mad.empty_iu.common.type) {
-	case VIOSRP_EMPTY_IU_TYPE:
-		eprintk("%s\n", "Unsupported EMPTY MAD IU");
-		break;
-	case VIOSRP_ERROR_LOG_TYPE:
-		eprintk("%s\n", "Unsupported ERROR LOG MAD IU");
-		iu->mad.error_log.common.status = 1;
-		send_iu(iue, sizeof(iu->mad.error_log),	VIOSRP_MAD_FORMAT);
-		break;
-	case VIOSRP_ADAPTER_INFO_TYPE:
-		info = &iu->mad.adapter_info;
-		info->common.status = send_adapter_info(iue, info->buffer,
-							info->common.length);
-		send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT);
-		break;
-	case VIOSRP_HOST_CONFIG_TYPE:
-		conf = &iu->mad.host_config;
-		conf->common.status = 1;
-		send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT);
-		break;
-	default:
-		eprintk("Unknown type %u\n", iu->srp.rsp.opcode);
-	}
-
-	return 1;
-}
-
-static int process_srp_iu(struct iu_entry *iue)
-{
-	union viosrp_iu *iu = vio_iu(iue);
-	int done = 1;
-	u8 opcode = iu->srp.rsp.opcode;
-
-	switch (opcode) {
-	case SRP_LOGIN_REQ:
-		process_login(iue);
-		break;
-	case SRP_TSK_MGMT:
-		done = process_tsk_mgmt(iue);
-		break;
-	case SRP_CMD:
-		queue_cmd(iue);
-		done = 0;
-		break;
-	case SRP_LOGIN_RSP:
-	case SRP_I_LOGOUT:
-	case SRP_T_LOGOUT:
-	case SRP_RSP:
-	case SRP_CRED_REQ:
-	case SRP_CRED_RSP:
-	case SRP_AER_REQ:
-	case SRP_AER_RSP:
-		eprintk("Unsupported type %u\n", opcode);
-		break;
-	default:
-		eprintk("Unknown type %u\n", opcode);
-	}
-
-	return done;
-}
-
-static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
-{
-	struct vio_port *vport = target_to_port(target);
-	struct iu_entry *iue;
-	long err;
-	int done = 1;
-
-	iue = srp_iu_get(target);
-	if (!iue) {
-		eprintk("Error getting IU from pool, %p\n", target);
-		return;
-	}
-
-	iue->remote_token = crq->IU_data_ptr;
-
-	err = h_copy_rdma(crq->IU_length, vport->riobn,
-			  iue->remote_token, vport->liobn, iue->sbuf->dma);
-
-	if (err != H_SUCCESS) {
-		eprintk("%ld transferring data error %p\n", err, iue);
-		goto out;
-	}
-
-	if (crq->format == VIOSRP_MAD_FORMAT)
-		done = process_mad_iu(iue);
-	else
-		done = process_srp_iu(iue);
-out:
-	if (done)
-		srp_iu_put(iue);
-}
-
-static irqreturn_t ibmvstgt_interrupt(int dummy, void *data)
-{
-	struct srp_target *target = data;
-	struct vio_port *vport = target_to_port(target);
-
-	vio_disable_interrupts(vport->dma_dev);
-	queue_work(vtgtd, &vport->crq_work);
-
-	return IRQ_HANDLED;
-}
-
-static int crq_queue_create(struct crq_queue *queue, struct srp_target *target)
-{
-	int err;
-	struct vio_port *vport = target_to_port(target);
-
-	queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL);
-	if (!queue->msgs)
-		goto malloc_failed;
-	queue->size = PAGE_SIZE / sizeof(*queue->msgs);
-
-	queue->msg_token = dma_map_single(target->dev, queue->msgs,
-					  queue->size * sizeof(*queue->msgs),
-					  DMA_BIDIRECTIONAL);
-
-	if (dma_mapping_error(target->dev, queue->msg_token))
-		goto map_failed;
-
-	err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
-			PAGE_SIZE);
-
-	/* If the adapter was left active for some reason (like kexec)
-	 * try freeing and re-registering
-	 */
-	if (err == H_RESOURCE) {
-	    do {
-		err = h_free_crq(vport->dma_dev->unit_address);
-	    } while (err == H_BUSY || H_IS_LONG_BUSY(err));
-
-	    err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
-			    PAGE_SIZE);
-	}
-
-	if (err != H_SUCCESS && err != 2) {
-		eprintk("Error 0x%x opening virtual adapter\n", err);
-		goto reg_crq_failed;
-	}
-
-	err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt,
-			  0, "ibmvstgt", target);
-	if (err)
-		goto req_irq_failed;
-
-	vio_enable_interrupts(vport->dma_dev);
-
-	h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0);
-
-	queue->cur = 0;
-	spin_lock_init(&queue->lock);
-
-	return 0;
-
-req_irq_failed:
-	do {
-		err = h_free_crq(vport->dma_dev->unit_address);
-	} while (err == H_BUSY || H_IS_LONG_BUSY(err));
-
-reg_crq_failed:
-	dma_unmap_single(target->dev, queue->msg_token,
-			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
-map_failed:
-	free_page((unsigned long) queue->msgs);
-
-malloc_failed:
-	return -ENOMEM;
-}
-
-static void crq_queue_destroy(struct srp_target *target)
-{
-	struct vio_port *vport = target_to_port(target);
-	struct crq_queue *queue = &vport->crq_queue;
-	int err;
-
-	free_irq(vport->dma_dev->irq, target);
-	do {
-		err = h_free_crq(vport->dma_dev->unit_address);
-	} while (err == H_BUSY || H_IS_LONG_BUSY(err));
-
-	dma_unmap_single(target->dev, queue->msg_token,
-			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
-
-	free_page((unsigned long) queue->msgs);
-}
-
-static void process_crq(struct viosrp_crq *crq,	struct srp_target *target)
-{
-	struct vio_port *vport = target_to_port(target);
-	dprintk("%x %x\n", crq->valid, crq->format);
-
-	switch (crq->valid) {
-	case 0xC0:
-		/* initialization */
-		switch (crq->format) {
-		case 0x01:
-			h_send_crq(vport->dma_dev->unit_address,
-				   0xC002000000000000, 0);
-			break;
-		case 0x02:
-			break;
-		default:
-			eprintk("Unknown format %u\n", crq->format);
-		}
-		break;
-	case 0xFF:
-		/* transport event */
-		break;
-	case 0x80:
-		/* real payload */
-		switch (crq->format) {
-		case VIOSRP_SRP_FORMAT:
-		case VIOSRP_MAD_FORMAT:
-			process_iu(crq, target);
-			break;
-		case VIOSRP_OS400_FORMAT:
-		case VIOSRP_AIX_FORMAT:
-		case VIOSRP_LINUX_FORMAT:
-		case VIOSRP_INLINE_FORMAT:
-			eprintk("Unsupported format %u\n", crq->format);
-			break;
-		default:
-			eprintk("Unknown format %u\n", crq->format);
-		}
-		break;
-	default:
-		eprintk("unknown message type 0x%02x!?\n", crq->valid);
-	}
-}
-
-static inline struct viosrp_crq *next_crq(struct crq_queue *queue)
-{
-	struct viosrp_crq *crq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&queue->lock, flags);
-	crq = &queue->msgs[queue->cur];
-	if (crq->valid & 0x80) {
-		if (++queue->cur == queue->size)
-			queue->cur = 0;
-	} else
-		crq = NULL;
-	spin_unlock_irqrestore(&queue->lock, flags);
-
-	return crq;
-}
-
-static void handle_crq(struct work_struct *work)
-{
-	struct vio_port *vport = container_of(work, struct vio_port, crq_work);
-	struct srp_target *target = vport->target;
-	struct viosrp_crq *crq;
-	int done = 0;
-
-	while (!done) {
-		while ((crq = next_crq(&vport->crq_queue)) != NULL) {
-			process_crq(crq, target);
-			crq->valid = 0x00;
-		}
-
-		vio_enable_interrupts(vport->dma_dev);
-
-		crq = next_crq(&vport->crq_queue);
-		if (crq) {
-			vio_disable_interrupts(vport->dma_dev);
-			process_crq(crq, target);
-			crq->valid = 0x00;
-		} else
-			done = 1;
-	}
-
-	handle_cmd_queue(target);
-}
-
-
-static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc)
-{
-	unsigned long flags;
-	struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-	struct srp_target *target = iue->target;
-
-	dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
-
-	spin_lock_irqsave(&target->lock, flags);
-	list_del(&iue->ilist);
-	spin_unlock_irqrestore(&target->lock, flags);
-
-	srp_iu_put(iue);
-
-	return 0;
-}
-
-static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost,
-				      u64 itn_id, u64 mid, int result)
-{
-	struct iu_entry *iue = (struct iu_entry *) ((void *) mid);
-	union viosrp_iu *iu = vio_iu(iue);
-	unsigned char status, asc;
-
-	eprintk("%p %d\n", iue, result);
-	status = NO_SENSE;
-	asc = 0;
-
-	switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
-	case SRP_TSK_ABORT_TASK:
-		asc = 0x14;
-		if (result)
-			status = ABORTED_COMMAND;
-		break;
-	default:
-		break;
-	}
-
-	send_rsp(iue, NULL, status, asc);
-	srp_iu_put(iue);
-
-	return 0;
-}
-
-static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id,
-				      int result)
-{
-	struct srp_target *target = host_to_srp_target(shost);
-	struct vio_port *vport = target_to_port(target);
-
-	if (result) {
-		eprintk("%p %d\n", shost, result);
-		srp_rport_del(vport->rport);
-		vport->rport = NULL;
-	}
-	return 0;
-}
-
-static ssize_t system_id_show(struct device *dev,
-			      struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
-}
-
-static ssize_t partition_number_show(struct device *dev,
-				     struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
-}
-
-static ssize_t unit_address_show(struct device *dev,
-				  struct device_attribute *attr, char *buf)
-{
-	struct Scsi_Host *shost = class_to_shost(dev);
-	struct srp_target *target = host_to_srp_target(shost);
-	struct vio_port *vport = target_to_port(target);
-	return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address);
-}
-
-static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
-static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
-static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
-
-static struct device_attribute *ibmvstgt_attrs[] = {
-	&dev_attr_system_id,
-	&dev_attr_partition_number,
-	&dev_attr_unit_address,
-	NULL,
-};
-
-static struct scsi_host_template ibmvstgt_sht = {
-	.name			= TGT_NAME,
-	.module			= THIS_MODULE,
-	.can_queue		= INITIAL_SRP_LIMIT,
-	.sg_tablesize		= SG_ALL,
-	.use_clustering		= DISABLE_CLUSTERING,
-	.max_sectors		= DEFAULT_MAX_SECTORS,
-	.transfer_response	= ibmvstgt_cmd_done,
-	.eh_abort_handler	= ibmvstgt_eh_abort_handler,
-	.shost_attrs		= ibmvstgt_attrs,
-	.proc_name		= TGT_NAME,
-	.supported_mode		= MODE_TARGET,
-};
-
-static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
-{
-	struct Scsi_Host *shost;
-	struct srp_target *target;
-	struct vio_port *vport;
-	unsigned int *dma, dma_size;
-	int err = -ENOMEM;
-
-	vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL);
-	if (!vport)
-		return err;
-	shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target));
-	if (!shost)
-		goto free_vport;
-	shost->transportt = ibmvstgt_transport_template;
-
-	target = host_to_srp_target(shost);
-	target->shost = shost;
-	vport->dma_dev = dev;
-	target->ldata = vport;
-	vport->target = target;
-	err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT,
-			       SRP_MAX_IU_LEN);
-	if (err)
-		goto put_host;
-
-	dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window",
-						 &dma_size);
-	if (!dma || dma_size != 40) {
-		eprintk("Couldn't get window property %d\n", dma_size);
-		err = -EIO;
-		goto free_srp_target;
-	}
-	vport->liobn = dma[0];
-	vport->riobn = dma[5];
-
-	INIT_WORK(&vport->crq_work, handle_crq);
-
-	err = scsi_add_host(shost, target->dev);
-	if (err)
-		goto free_srp_target;
-
-	err = scsi_tgt_alloc_queue(shost);
-	if (err)
-		goto remove_host;
-
-	err = crq_queue_create(&vport->crq_queue, target);
-	if (err)
-		goto free_queue;
-
-	return 0;
-free_queue:
-	scsi_tgt_free_queue(shost);
-remove_host:
-	scsi_remove_host(shost);
-free_srp_target:
-	srp_target_free(target);
-put_host:
-	scsi_host_put(shost);
-free_vport:
-	kfree(vport);
-	return err;
-}
-
-static int ibmvstgt_remove(struct vio_dev *dev)
-{
-	struct srp_target *target = dev_get_drvdata(&dev->dev);
-	struct Scsi_Host *shost = target->shost;
-	struct vio_port *vport = target->ldata;
-
-	crq_queue_destroy(target);
-	srp_remove_host(shost);
-	scsi_remove_host(shost);
-	scsi_tgt_free_queue(shost);
-	srp_target_free(target);
-	kfree(vport);
-	scsi_host_put(shost);
-	return 0;
-}
-
-static struct vio_device_id ibmvstgt_device_table[] = {
-	{"v-scsi-host", "IBM,v-scsi-host"},
-	{"",""}
-};
-
-MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table);
-
-static struct vio_driver ibmvstgt_driver = {
-	.id_table = ibmvstgt_device_table,
-	.probe = ibmvstgt_probe,
-	.remove = ibmvstgt_remove,
-	.name = "ibmvscsis",
-};
-
-static int get_system_info(void)
-{
-	struct device_node *rootdn;
-	const char *id, *model, *name;
-	const unsigned int *num;
-
-	rootdn = of_find_node_by_path("/");
-	if (!rootdn)
-		return -ENOENT;
-
-	model = of_get_property(rootdn, "model", NULL);
-	id = of_get_property(rootdn, "system-id", NULL);
-	if (model && id)
-		snprintf(system_id, sizeof(system_id), "%s-%s", model, id);
-
-	name = of_get_property(rootdn, "ibm,partition-name", NULL);
-	if (name)
-		strncpy(partition_name, name, sizeof(partition_name));
-
-	num = of_get_property(rootdn, "ibm,partition-no", NULL);
-	if (num)
-		partition_number = *num;
-
-	of_node_put(rootdn);
-	return 0;
-}
-
-static struct srp_function_template ibmvstgt_transport_functions = {
-	.tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
-	.it_nexus_response = ibmvstgt_it_nexus_response,
-};
-
-static int __init ibmvstgt_init(void)
-{
-	int err = -ENOMEM;
-
-	printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n");
-
-	ibmvstgt_transport_template =
-		srp_attach_transport(&ibmvstgt_transport_functions);
-	if (!ibmvstgt_transport_template)
-		return err;
-
-	vtgtd = create_workqueue("ibmvtgtd");
-	if (!vtgtd)
-		goto release_transport;
-
-	err = get_system_info();
-	if (err)
-		goto destroy_wq;
-
-	err = vio_register_driver(&ibmvstgt_driver);
-	if (err)
-		goto destroy_wq;
-
-	return 0;
-destroy_wq:
-	destroy_workqueue(vtgtd);
-release_transport:
-	srp_release_transport(ibmvstgt_transport_template);
-	return err;
-}
-
-static void __exit ibmvstgt_exit(void)
-{
-	printk("Unregister IBM virtual SCSI driver\n");
-
-	destroy_workqueue(vtgtd);
-	vio_unregister_driver(&ibmvstgt_driver);
-	srp_release_transport(ibmvstgt_transport_template);
-}
-
-MODULE_DESCRIPTION("IBM Virtual SCSI Target");
-MODULE_AUTHOR("Santiago Leon");
-MODULE_LICENSE("GPL");
-
-module_init(ibmvstgt_init);
-module_exit(ibmvstgt_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/Makefile linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/Makefile
--- linux-libre-3.16-gnu/drivers/scsi/ibmvscsi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ibmvscsi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,2 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi.o
-obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o
 obj-$(CONFIG_SCSI_IBMVFC)	+= ibmvfc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/in2000.c linux-libre-3.17-rc7-gnu/drivers/scsi/in2000.c
--- linux-libre-3.16-gnu/drivers/scsi/in2000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/in2000.c	2014-09-28 17:29:07.000000000 -0400
@@ -2251,14 +2251,14 @@ static int in2000_show_info(struct seq_f
 		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (Scsi_Cmnd *) hd->connected;
-			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+			seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 		}
 	}
 	if (hd->proc & PR_INPUTQ) {
 		seq_printf(m, "\ninput_Q:       ");
 		cmd = (Scsi_Cmnd *) hd->input_Q;
 		while (cmd) {
-			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+			seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
@@ -2266,7 +2266,7 @@ static int in2000_show_info(struct seq_f
 		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (Scsi_Cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+			seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/isci/init.c linux-libre-3.17-rc7-gnu/drivers/scsi/isci/init.c
--- linux-libre-3.16-gnu/drivers/scsi/isci/init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/isci/init.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,7 +75,7 @@ MODULE_VERSION(DRV_VERSION);
 
 static struct scsi_transport_template *isci_transport_template;
 
-static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
+static const struct pci_device_id isci_id_table[] = {
 	{ PCI_VDEVICE(INTEL, 0x1D61),},
 	{ PCI_VDEVICE(INTEL, 0x1D63),},
 	{ PCI_VDEVICE(INTEL, 0x1D65),},
@@ -356,7 +356,7 @@ static int isci_setup_interrupts(struct
 	for (i = 0; i < num_msix; i++)
 		pci_info->msix_entries[i].entry = i;
 
-	err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
+	err = pci_enable_msix_exact(pdev, pci_info->msix_entries, num_msix);
 	if (err)
 		goto intx;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -40,17 +40,10 @@ config SCSI_DMA
 	bool
 	default n
 
-config SCSI_TGT
-	tristate "SCSI target support"
-	depends on SCSI
-	---help---
-	  If you want to use SCSI target mode drivers enable this option.
-	  If you choose M, the module will be called scsi_tgt.
-
 config SCSI_NETLINK
 	bool
 	default	n
-	select NET
+	depends on NET
 
 config SCSI_PROC_FS
 	bool "legacy /proc/scsi/ support"
@@ -197,20 +190,6 @@ config SCSI_ENCLOSURE
 	  it has an enclosure device.  Selecting this option will just allow
 	  certain enclosure conditions to be reported and is not required.
 
-config SCSI_MULTI_LUN
-	bool "Probe all LUNs on each SCSI device"
-	depends on SCSI
-	help
-	  Some devices support more than one LUN (Logical Unit Number) in order
-	  to allow access to several media, e.g. CD jukebox, USB card reader,
-	  mobile phone in mass storage mode. This option forces the kernel to
-	  probe for all LUNs by default. This setting can be overridden by
-	  max_luns boot/module parameter. Note that this option does not affect
-	  devices conforming to SCSI-3 or higher as they can explicitly report
-	  their number of LUNs. It is safe to say Y here unless you have one of
-	  those rare devices which reacts in an unexpected way when probed for
-	  multiple LUNs.
-
 config SCSI_CONSTANTS
 	bool "Verbose SCSI error reporting (kernel size +=12K)"
 	depends on SCSI
@@ -278,20 +257,13 @@ config SCSI_SPI_ATTRS
 
 config SCSI_FC_ATTRS
 	tristate "FiberChannel Transport Attributes"
-	depends on SCSI
+	depends on SCSI && NET
 	select SCSI_NETLINK
 	help
 	  If you wish to export transport-specific information about
 	  each attached FiberChannel device to sysfs, say Y.
 	  Otherwise, say N.
 
-config SCSI_FC_TGT_ATTRS
-	bool "SCSI target support for FiberChannel Transport Attributes"
-	depends on SCSI_FC_ATTRS
-	depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS
-	help
-		If you want to use SCSI target mode drivers enable this option.
-
 config SCSI_ISCSI_ATTRS
 	tristate "iSCSI Transport Attributes"
 	depends on SCSI && NET
@@ -318,13 +290,6 @@ config SCSI_SRP_ATTRS
 	  If you wish to export transport-specific information about
 	  each attached SRP device to sysfs, say Y.
 
-config SCSI_SRP_TGT_ATTRS
-	bool "SCSI target support for SRP Transport Attributes"
-	depends on SCSI_SRP_ATTRS
-	depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS
-	help
-		If you want to use SCSI target mode drivers enable this option.
-
 endmenu
 
 menuconfig SCSI_LOWLEVEL
@@ -528,7 +493,7 @@ config SCSI_DPT_I2O
 
 config SCSI_ADVANSYS
 	tristate "AdvanSys SCSI support"
-	depends on SCSI && VIRT_TO_BUS
+	depends on SCSI && VIRT_TO_BUS && !ARM
 	depends on ISA || EISA || PCI
 	help
 	  This is a driver for all SCSI host adapters manufactured by
@@ -620,28 +585,28 @@ config HYPERV_STORAGE
 
 config LIBFC
 	tristate "LibFC module"
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	select CRC32
 	---help---
 	  Fibre Channel library module
 
 config LIBFCOE
 	tristate "LibFCoE module"
-	select LIBFC
+	depends on LIBFC
 	---help---
 	  Library for Fibre Channel over Ethernet module
 
 config FCOE
 	tristate "FCoE module"
 	depends on PCI
-	select LIBFCOE
+	depends on LIBFCOE
 	---help---
 	  Fibre Channel over Ethernet module
 
 config FCOE_FNIC
 	tristate "Cisco FNIC Driver"
 	depends on PCI && X86
-	select LIBFCOE
+	depends on LIBFCOE
 	help
 	  This is support for the Cisco PCI-Express FCoE HBA.
 
@@ -848,24 +813,10 @@ config SCSI_IBMVSCSI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ibmvscsi.
 
-config SCSI_IBMVSCSIS
-	tristate "IBM Virtual SCSI Server support"
-	depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS
-	help
-	  This is the SRP target driver for IBM pSeries virtual environments.
-
-	  The userspace component needed to initialize the driver and
-	  documentation can be found:
-
-	  http://stgt.berlios.de/
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ibmvstgt.
-
 config SCSI_IBMVFC
 	tristate "IBM Virtual FC support"
 	depends on PPC_PSERIES && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	help
 	  This is the IBM POWER Virtual FC Client
 
@@ -1315,7 +1266,7 @@ source "drivers/scsi/qla4xxx/Kconfig"
 config SCSI_LPFC
 	tristate "Emulex LightPulse Fibre Channel Support"
 	depends on PCI && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	select CRC_T10DIF
 	help
           This lpfc driver supports the Emulex LightPulse
@@ -1725,7 +1676,7 @@ config SCSI_SUNESP
 config ZFCP
 	tristate "FCP host bus adapter driver for IBM eServer zSeries"
 	depends on S390 && QDIO && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	help
           If you want to access SCSI devices attached to your IBM eServer
           zSeries by means of Fibre Channel interfaces say Y.
@@ -1750,20 +1701,10 @@ config SCSI_PM8001
 	  This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip
 	  based host adapters.
 
-config SCSI_SRP
-	tristate "SCSI RDMA Protocol helper library"
-	depends on SCSI && PCI
-	select SCSI_TGT
-	help
-	  If you wish to use SRP target drivers, say Y.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called libsrp.
-
 config SCSI_BFA_FC
 	tristate "Brocade BFA Fibre Channel Support"
 	depends on PCI && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	help
 	  This bfa driver supports all Brocade PCIe FC/FCOE host adapters.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/libiscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/libiscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/libiscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/libiscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -260,7 +260,7 @@ static int iscsi_check_tmf_restrictions(
 {
 	struct iscsi_conn *conn = task->conn;
 	struct iscsi_tm *tmf = &conn->tmhdr;
-	unsigned int hdr_lun;
+	u64 hdr_lun;
 
 	if (conn->tmf_state == TMF_INITIAL)
 		return 0;
@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn
 			return NULL;
 		}
 
+		if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) {
+			iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN);
+			return NULL;
+		}
+
 		task = conn->login_task;
 	} else {
 		if (session->state != ISCSI_STATE_LOGGED_IN)
 			return NULL;
 
+		if (data_size != 0) {
+			iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode);
+			return NULL;
+		}
+
 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
 
@@ -1859,8 +1869,7 @@ static int iscsi_exec_task_mgmt_fn(struc
  * Fail commands. session lock held and recv side suspended and xmit
  * thread flushed
  */
-static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
-			    int error)
+static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
 {
 	struct iscsi_task *task;
 	int i;
@@ -2098,7 +2107,7 @@ static void iscsi_check_transport_timeou
 				  conn->ping_timeout, conn->recv_timeout,
 				  last_recv, conn->last_ping, jiffies);
 		spin_unlock(&session->frwd_lock);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		iscsi_conn_failure(conn, ISCSI_ERR_NOP_TIMEDOUT);
 		return;
 	}
 
@@ -2279,7 +2288,8 @@ int iscsi_eh_device_reset(struct scsi_cm
 	cls_session = starget_to_session(scsi_target(sc->device));
 	session = cls_session->dd_data;
 
-	ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]\n", sc, sc->device->lun);
+	ISCSI_DBG_EH(session, "LU Reset [sc %p lun %llu]\n", sc,
+		     sc->device->lun);
 
 	mutex_lock(&session->eh_mutex);
 	spin_lock_bh(&session->frwd_lock);
@@ -2971,7 +2981,7 @@ void iscsi_conn_teardown(struct iscsi_cl
 	 */
 	for (;;) {
 		spin_lock_irqsave(session->host->host_lock, flags);
-		if (!session->host->host_busy) { /* OK for ERL == 0 */
+		if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */
 			spin_unlock_irqrestore(session->host->host_lock, flags);
 			break;
 		}
@@ -2979,7 +2989,7 @@ void iscsi_conn_teardown(struct iscsi_cl
 		msleep_interruptible(500);
 		iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
 				  "host_busy %d host_failed %d\n",
-				  session->host->host_busy,
+				  atomic_read(&session->host->host_busy),
 				  session->host->host_failed);
 		/*
 		 * force eh_abort() to unblock
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/libsas/sas_scsi_host.c linux-libre-3.17-rc7-gnu/drivers/scsi/libsas/sas_scsi_host.c
--- linux-libre-3.16-gnu/drivers/scsi/libsas/sas_scsi_host.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/libsas/sas_scsi_host.c	2014-09-28 17:29:07.000000000 -0400
@@ -404,7 +404,7 @@ static int sas_recover_lu(struct domain_
 
 	int_to_scsilun(cmd->device->lun, &lun);
 
-	SAS_DPRINTK("eh: device %llx LUN %x has the task\n",
+	SAS_DPRINTK("eh: device %llx LUN %llx has the task\n",
 		    SAS_ADDR(dev->sas_addr),
 		    cmd->device->lun);
 
@@ -490,7 +490,8 @@ static void sas_wait_eh(struct domain_de
 }
 EXPORT_SYMBOL(sas_wait_eh);
 
-static int sas_queue_reset(struct domain_device *dev, int reset_type, int lun, int wait)
+static int sas_queue_reset(struct domain_device *dev, int reset_type,
+			   u64 lun, int wait)
 {
 	struct sas_ha_struct *ha = dev->port->ha;
 	int scheduled = 0, tries = 100;
@@ -689,7 +690,7 @@ static void sas_eh_handle_sas_errors(str
  reset:
 			tmf_resp = sas_recover_lu(task->dev, cmd);
 			if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
-				SAS_DPRINTK("dev %016llx LU %x is "
+				SAS_DPRINTK("dev %016llx LU %llx is "
 					    "recovered\n",
 					    SAS_ADDR(task->dev),
 					    cmd->device->lun);
@@ -742,7 +743,7 @@ static void sas_eh_handle_sas_errors(str
 			 * of effort could recover from errors.  Quite
 			 * possibly the HA just disappeared.
 			 */
-			SAS_DPRINTK("error from  device %llx, LUN %x "
+			SAS_DPRINTK("error from  device %llx, LUN %llx "
 				    "couldn't be recovered in any way\n",
 				    SAS_ADDR(task->dev->sas_addr),
 				    cmd->device->lun);
@@ -812,7 +813,7 @@ retry:
 	spin_unlock_irq(shost->host_lock);
 
 	SAS_DPRINTK("Enter %s busy: %d failed: %d\n",
-		    __func__, shost->host_busy, shost->host_failed);
+		    __func__, atomic_read(&shost->host_busy), shost->host_failed);
 	/*
 	 * Deal with commands that still have SAS tasks (i.e. they didn't
 	 * complete via the normal sas_task completion mechanism),
@@ -857,7 +858,8 @@ out:
 		goto retry;
 
 	SAS_DPRINTK("--- Exit %s: busy: %d failed: %d tries: %d\n",
-		    __func__, shost->host_busy, shost->host_failed, tries);
+		    __func__, atomic_read(&shost->host_busy),
+		    shost->host_failed, tries);
 }
 
 enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
@@ -941,7 +943,7 @@ int sas_slave_configure(struct scsi_devi
 		scsi_set_tag_type(scsi_dev, MSG_SIMPLE_TAG);
 		scsi_activate_tcq(scsi_dev, SAS_DEF_QD);
 	} else {
-		SAS_DPRINTK("device %llx, LUN %x doesn't support "
+		SAS_DPRINTK("device %llx, LUN %llx doesn't support "
 			    "TCQ\n", SAS_ADDR(dev->sas_addr),
 			    scsi_dev->lun);
 		scsi_dev->tagged_supported = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/libsrp.c linux-libre-3.17-rc7-gnu/drivers/scsi/libsrp.c
--- linux-libre-3.16-gnu/drivers/scsi/libsrp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/libsrp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,447 +0,0 @@
-/*
- * SCSI RDMA Protocol lib functions
- *
- * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/kfifo.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_tgt.h>
-#include <scsi/srp.h>
-#include <scsi/libsrp.h>
-
-enum srp_task_attributes {
-	SRP_SIMPLE_TASK = 0,
-	SRP_HEAD_TASK = 1,
-	SRP_ORDERED_TASK = 2,
-	SRP_ACA_TASK = 4
-};
-
-/* tmp - will replace with SCSI logging stuff */
-#define eprintk(fmt, args...)					\
-do {								\
-	printk("%s(%d) " fmt, __func__, __LINE__, ##args);	\
-} while (0)
-/* #define dprintk eprintk */
-#define dprintk(fmt, args...)
-
-static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
-			     struct srp_buf **ring)
-{
-	int i;
-	struct iu_entry *iue;
-
-	q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL);
-	if (!q->pool)
-		return -ENOMEM;
-	q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL);
-	if (!q->items)
-		goto free_pool;
-
-	spin_lock_init(&q->lock);
-	kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *));
-
-	for (i = 0, iue = q->items; i < max; i++) {
-		kfifo_in(&q->queue, (void *) &iue, sizeof(void *));
-		iue->sbuf = ring[i];
-		iue++;
-	}
-	return 0;
-
-	kfree(q->items);
-free_pool:
-	kfree(q->pool);
-	return -ENOMEM;
-}
-
-static void srp_iu_pool_free(struct srp_queue *q)
-{
-	kfree(q->items);
-	kfree(q->pool);
-}
-
-static struct srp_buf **srp_ring_alloc(struct device *dev,
-				       size_t max, size_t size)
-{
-	int i;
-	struct srp_buf **ring;
-
-	ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL);
-	if (!ring)
-		return NULL;
-
-	for (i = 0; i < max; i++) {
-		ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL);
-		if (!ring[i])
-			goto out;
-		ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma,
-						  GFP_KERNEL);
-		if (!ring[i]->buf)
-			goto out;
-	}
-	return ring;
-
-out:
-	for (i = 0; i < max && ring[i]; i++) {
-		if (ring[i]->buf)
-			dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
-		kfree(ring[i]);
-	}
-	kfree(ring);
-
-	return NULL;
-}
-
-static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max,
-			  size_t size)
-{
-	int i;
-
-	for (i = 0; i < max; i++) {
-		dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
-		kfree(ring[i]);
-	}
-	kfree(ring);
-}
-
-int srp_target_alloc(struct srp_target *target, struct device *dev,
-		     size_t nr, size_t iu_size)
-{
-	int err;
-
-	spin_lock_init(&target->lock);
-	INIT_LIST_HEAD(&target->cmd_queue);
-
-	target->dev = dev;
-	dev_set_drvdata(target->dev, target);
-
-	target->srp_iu_size = iu_size;
-	target->rx_ring_size = nr;
-	target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size);
-	if (!target->rx_ring)
-		return -ENOMEM;
-	err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring);
-	if (err)
-		goto free_ring;
-
-	return 0;
-
-free_ring:
-	srp_ring_free(target->dev, target->rx_ring, nr, iu_size);
-	return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(srp_target_alloc);
-
-void srp_target_free(struct srp_target *target)
-{
-	srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size,
-		      target->srp_iu_size);
-	srp_iu_pool_free(&target->iu_queue);
-}
-EXPORT_SYMBOL_GPL(srp_target_free);
-
-struct iu_entry *srp_iu_get(struct srp_target *target)
-{
-	struct iu_entry *iue = NULL;
-
-	if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue,
-		sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) {
-			WARN_ONCE(1, "unexpected fifo state");
-			return NULL;
-	}
-	if (!iue)
-		return iue;
-	iue->target = target;
-	INIT_LIST_HEAD(&iue->ilist);
-	iue->flags = 0;
-	return iue;
-}
-EXPORT_SYMBOL_GPL(srp_iu_get);
-
-void srp_iu_put(struct iu_entry *iue)
-{
-	kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue,
-			sizeof(void *), &iue->target->iu_queue.lock);
-}
-EXPORT_SYMBOL_GPL(srp_iu_put);
-
-static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md,
-			   enum dma_data_direction dir, srp_rdma_t rdma_io,
-			   int dma_map, int ext_desc)
-{
-	struct iu_entry *iue = NULL;
-	struct scatterlist *sg = NULL;
-	int err, nsg = 0, len;
-
-	if (dma_map) {
-		iue = (struct iu_entry *) sc->SCp.ptr;
-		sg = scsi_sglist(sc);
-
-		dprintk("%p %u %u %d\n", iue, scsi_bufflen(sc),
-			md->len, scsi_sg_count(sc));
-
-		nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc),
-				 DMA_BIDIRECTIONAL);
-		if (!nsg) {
-			printk("fail to map %p %d\n", iue, scsi_sg_count(sc));
-			return 0;
-		}
-		len = min(scsi_bufflen(sc), md->len);
-	} else
-		len = md->len;
-
-	err = rdma_io(sc, sg, nsg, md, 1, dir, len);
-
-	if (dma_map)
-		dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
-
-	return err;
-}
-
-static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
-			     struct srp_indirect_buf *id,
-			     enum dma_data_direction dir, srp_rdma_t rdma_io,
-			     int dma_map, int ext_desc)
-{
-	struct iu_entry *iue = NULL;
-	struct srp_direct_buf *md = NULL;
-	struct scatterlist dummy, *sg = NULL;
-	dma_addr_t token = 0;
-	int err = 0;
-	int nmd, nsg = 0, len;
-
-	if (dma_map || ext_desc) {
-		iue = (struct iu_entry *) sc->SCp.ptr;
-		sg = scsi_sglist(sc);
-
-		dprintk("%p %u %u %d %d\n",
-			iue, scsi_bufflen(sc), id->len,
-			cmd->data_in_desc_cnt, cmd->data_out_desc_cnt);
-	}
-
-	nmd = id->table_desc.len / sizeof(struct srp_direct_buf);
-
-	if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) ||
-	    (dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) {
-		md = &id->desc_list[0];
-		goto rdma;
-	}
-
-	if (ext_desc && dma_map) {
-		md = dma_alloc_coherent(iue->target->dev, id->table_desc.len,
-				&token, GFP_KERNEL);
-		if (!md) {
-			eprintk("Can't get dma memory %u\n", id->table_desc.len);
-			return -ENOMEM;
-		}
-
-		sg_init_one(&dummy, md, id->table_desc.len);
-		sg_dma_address(&dummy) = token;
-		sg_dma_len(&dummy) = id->table_desc.len;
-		err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
-			      id->table_desc.len);
-		if (err) {
-			eprintk("Error copying indirect table %d\n", err);
-			goto free_mem;
-		}
-	} else {
-		eprintk("This command uses external indirect buffer\n");
-		return -EINVAL;
-	}
-
-rdma:
-	if (dma_map) {
-		nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc),
-				 DMA_BIDIRECTIONAL);
-		if (!nsg) {
-			eprintk("fail to map %p %d\n", iue, scsi_sg_count(sc));
-			err = -EIO;
-			goto free_mem;
-		}
-		len = min(scsi_bufflen(sc), id->len);
-	} else
-		len = id->len;
-
-	err = rdma_io(sc, sg, nsg, md, nmd, dir, len);
-
-	if (dma_map)
-		dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
-
-free_mem:
-	if (token && dma_map)
-		dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
-
-	return err;
-}
-
-static int data_out_desc_size(struct srp_cmd *cmd)
-{
-	int size = 0;
-	u8 fmt = cmd->buf_fmt >> 4;
-
-	switch (fmt) {
-	case SRP_NO_DATA_DESC:
-		break;
-	case SRP_DATA_DESC_DIRECT:
-		size = sizeof(struct srp_direct_buf);
-		break;
-	case SRP_DATA_DESC_INDIRECT:
-		size = sizeof(struct srp_indirect_buf) +
-			sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt;
-		break;
-	default:
-		eprintk("client error. Invalid data_out_format %x\n", fmt);
-		break;
-	}
-	return size;
-}
-
-/*
- * TODO: this can be called multiple times for a single command if it
- * has very long data.
- */
-int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
-		      srp_rdma_t rdma_io, int dma_map, int ext_desc)
-{
-	struct srp_direct_buf *md;
-	struct srp_indirect_buf *id;
-	enum dma_data_direction dir;
-	int offset, err = 0;
-	u8 format;
-
-	offset = cmd->add_cdb_len & ~3;
-
-	dir = srp_cmd_direction(cmd);
-	if (dir == DMA_FROM_DEVICE)
-		offset += data_out_desc_size(cmd);
-
-	if (dir == DMA_TO_DEVICE)
-		format = cmd->buf_fmt >> 4;
-	else
-		format = cmd->buf_fmt & ((1U << 4) - 1);
-
-	switch (format) {
-	case SRP_NO_DATA_DESC:
-		break;
-	case SRP_DATA_DESC_DIRECT:
-		md = (struct srp_direct_buf *)
-			(cmd->add_data + offset);
-		err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc);
-		break;
-	case SRP_DATA_DESC_INDIRECT:
-		id = (struct srp_indirect_buf *)
-			(cmd->add_data + offset);
-		err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map,
-					ext_desc);
-		break;
-	default:
-		eprintk("Unknown format %d %x\n", dir, format);
-		err = -EINVAL;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(srp_transfer_data);
-
-static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir)
-{
-	struct srp_direct_buf *md;
-	struct srp_indirect_buf *id;
-	int len = 0, offset = cmd->add_cdb_len & ~3;
-	u8 fmt;
-
-	if (dir == DMA_TO_DEVICE)
-		fmt = cmd->buf_fmt >> 4;
-	else {
-		fmt = cmd->buf_fmt & ((1U << 4) - 1);
-		offset += data_out_desc_size(cmd);
-	}
-
-	switch (fmt) {
-	case SRP_NO_DATA_DESC:
-		break;
-	case SRP_DATA_DESC_DIRECT:
-		md = (struct srp_direct_buf *) (cmd->add_data + offset);
-		len = md->len;
-		break;
-	case SRP_DATA_DESC_INDIRECT:
-		id = (struct srp_indirect_buf *) (cmd->add_data + offset);
-		len = id->len;
-		break;
-	default:
-		eprintk("invalid data format %x\n", fmt);
-		break;
-	}
-	return len;
-}
-
-int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
-		  u64 itn_id, u64 addr)
-{
-	enum dma_data_direction dir;
-	struct scsi_cmnd *sc;
-	int tag, len, err;
-
-	switch (cmd->task_attr) {
-	case SRP_SIMPLE_TASK:
-		tag = MSG_SIMPLE_TAG;
-		break;
-	case SRP_ORDERED_TASK:
-		tag = MSG_ORDERED_TAG;
-		break;
-	case SRP_HEAD_TASK:
-		tag = MSG_HEAD_TAG;
-		break;
-	default:
-		eprintk("Task attribute %d not supported\n", cmd->task_attr);
-		tag = MSG_ORDERED_TAG;
-	}
-
-	dir = srp_cmd_direction(cmd);
-	len = vscsis_data_length(cmd, dir);
-
-	dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0],
-		cmd->lun, dir, len, tag, (unsigned long long) cmd->tag);
-
-	sc = scsi_host_get_command(shost, dir, GFP_KERNEL);
-	if (!sc)
-		return -ENOMEM;
-
-	sc->SCp.ptr = info;
-	memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
-	sc->sdb.length = len;
-	sc->sdb.table.sgl = (void *) (unsigned long) addr;
-	sc->tag = tag;
-	err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
-				     cmd->tag);
-	if (err)
-		scsi_host_put_command(shost, sc);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(srp_cmd_queue);
-
-MODULE_DESCRIPTION("SCSI RDMA Protocol lib functions");
-MODULE_AUTHOR("FUJITA Tomonori");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_attr.c linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_attr.c
--- linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_attr.c	2014-08-07 04:59:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_attr.c	2014-09-28 21:42:22.000000000 -0400
@@ -1998,6 +1998,14 @@ lpfc_vport_param_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
 static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
 
+#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \
+static uint64_t lpfc_##name = defval;\
+module_param(lpfc_##name, ullong, S_IRUGO);\
+MODULE_PARM_DESC(lpfc_##name, desc);\
+lpfc_vport_param_show(name)\
+lpfc_vport_param_init(name, defval, minval, maxval)\
+static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+
 #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
 module_param(lpfc_##name, uint, S_IRUGO);\
@@ -4596,7 +4604,7 @@ LPFC_VPORT_ATTR(discovery_threads, 32, 1
 # Value range is [0,65535]. Default value is 255.
 # NOTE: The SCSI layer might probe all allowed LUN on some old targets.
 */
-LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");
+LPFC_VPORT_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");
 
 /*
 # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_init.c
--- linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_init.c	2014-08-07 04:59:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_init.c	2014-09-28 21:42:22.000000000 -0400
@@ -8242,7 +8242,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *ph
 	if (rc) {
 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
 				"0420 PCI enable MSI-X failed (%d)\n", rc);
-		goto msi_fail_out;
+		goto vec_fail_out;
 	}
 	for (i = 0; i < LPFC_MSIX_VECTORS; i++)
 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
@@ -8320,6 +8320,8 @@ irq_fail_out:
 msi_fail_out:
 	/* Unconfigure MSI-X capability structure */
 	pci_disable_msix(phba->pcidev);
+
+vec_fail_out:
 	return rc;
 }
 
@@ -8812,7 +8814,7 @@ enable_msix_vectors:
 	} else if (rc) {
 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
 				"0484 PCI enable MSI-X failed (%d)\n", rc);
-		goto msi_fail_out;
+		goto vec_fail_out;
 	}
 
 	/* Log MSI-X vector assignment */
@@ -8875,9 +8877,10 @@ cfg_fail_out:
 			 &phba->sli4_hba.fcp_eq_hdl[index]);
 	}
 
-msi_fail_out:
 	/* Unconfigure MSI-X capability structure */
 	pci_disable_msix(phba->pcidev);
+
+vec_fail_out:
 	return rc;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_scsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_scsi.c
--- linux-libre-3.16-gnu/drivers/scsi/lpfc/lpfc_scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/lpfc/lpfc_scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -258,7 +258,7 @@ static void
 lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
 		struct lpfc_vport  *vport,
 		struct lpfc_nodelist *ndlp,
-		uint32_t lun,
+		uint64_t lun,
 		uint32_t old_val,
 		uint32_t new_val)
 {
@@ -3823,7 +3823,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *v
 		if (rsplen != 0 && rsplen != 4 && rsplen != 8) {
 			lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
 				 "2719 Invalid response length: "
-				 "tgt x%x lun x%x cmnd x%x rsplen x%x\n",
+				 "tgt x%x lun x%llx cmnd x%x rsplen x%x\n",
 				 cmnd->device->id,
 				 cmnd->device->lun, cmnd->cmnd[0],
 				 rsplen);
@@ -3834,7 +3834,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *v
 			lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
 				 "2757 Protocol failure detected during "
 				 "processing of FCP I/O op: "
-				 "tgt x%x lun x%x cmnd x%x rspInfo3 x%x\n",
+				 "tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n",
 				 cmnd->device->id,
 				 cmnd->device->lun, cmnd->cmnd[0],
 				 fcprsp->rspInfo3);
@@ -4045,7 +4045,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba
 		else
 			logit = LOG_FCP | LOG_FCP_UNDER;
 		lpfc_printf_vlog(vport, KERN_WARNING, logit,
-			 "9030 FCP cmd x%x failed <%d/%d> "
+			 "9030 FCP cmd x%x failed <%d/%lld> "
 			 "status: x%x result: x%x "
 			 "sid: x%x did: x%x oxid: x%x "
 			 "Data: x%x x%x\n",
@@ -4157,7 +4157,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba
 		uint32_t *lp = (uint32_t *)cmd->sense_buffer;
 
 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
-				 "0710 Iodone <%d/%d> cmd %p, error "
+				 "0710 Iodone <%d/%llu> cmd %p, error "
 				 "x%x SNS x%x x%x Data: x%x x%x\n",
 				 cmd->device->id, cmd->device->lun, cmd,
 				 cmd->result, *lp, *(lp + 3), cmd->retries,
@@ -4390,7 +4390,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *v
 static int
 lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
 			     struct lpfc_scsi_buf *lpfc_cmd,
-			     unsigned int lun,
+			     uint64_t lun,
 			     uint8_t task_mgmt_cmd)
 {
 	struct lpfc_iocbq *piocbq;
@@ -4719,12 +4719,12 @@ lpfc_queuecommand(struct Scsi_Host *shos
 		atomic_dec(&ndlp->cmd_pending);
 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
 				 "3376 FCP could not issue IOCB err %x"
-				 "FCP cmd x%x <%d/%d> "
+				 "FCP cmd x%x <%d/%llu> "
 				 "sid: x%x did: x%x oxid: x%x "
 				 "Data: x%x x%x x%x x%x\n",
 				 err, cmnd->cmnd[0],
 				 cmnd->device ? cmnd->device->id : 0xffff,
-				 cmnd->device ? cmnd->device->lun : 0xffff,
+				 cmnd->device ? cmnd->device->lun : (u64) -1,
 				 vport->fc_myDID, ndlp->nlp_DID,
 				 phba->sli_rev == LPFC_SLI_REV4 ?
 				 lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff,
@@ -4807,7 +4807,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmn
 		spin_unlock_irqrestore(&phba->hbalock, flags);
 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
 			 "2873 SCSI Layer I/O Abort Request IO CMPL Status "
-			 "x%x ID %d LUN %d\n",
+			 "x%x ID %d LUN %llu\n",
 			 SUCCESS, cmnd->device->id, cmnd->device->lun);
 		return SUCCESS;
 	}
@@ -4924,7 +4924,7 @@ wait_for_cmpl:
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
 				 "0748 abort handler timed out waiting "
 				 "for abortng I/O (xri:x%x) to complete: "
-				 "ret %#x, ID %d, LUN %d\n",
+				 "ret %#x, ID %d, LUN %llu\n",
 				 iocb->sli4_xritag, ret,
 				 cmnd->device->id, cmnd->device->lun);
 	}
@@ -4935,7 +4935,7 @@ out_unlock:
 out:
 	lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
 			 "0749 SCSI Layer I/O Abort Request Status x%x ID %d "
-			 "LUN %d\n", ret, cmnd->device->id,
+			 "LUN %llu\n", ret, cmnd->device->id,
 			 cmnd->device->lun);
 	return ret;
 }
@@ -5047,7 +5047,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vp
  **/
 static int
 lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
-		    unsigned  tgt_id, unsigned int lun_id,
+		    unsigned  tgt_id, uint64_t lun_id,
 		    uint8_t task_mgmt_cmd)
 {
 	struct lpfc_hba   *phba = vport->phba;
@@ -5083,7 +5083,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp
 	iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
 
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
-			 "0702 Issue %s to TGT %d LUN %d "
+			 "0702 Issue %s to TGT %d LUN %llu "
 			 "rpi x%x nlp_flag x%x Data: x%x x%x\n",
 			 lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id,
 			 pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag,
@@ -5094,7 +5094,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp
 	if ((status != IOCB_SUCCESS) ||
 	    (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-			 "0727 TMF %s to TGT %d LUN %d failed (%d, %d) "
+			 "0727 TMF %s to TGT %d LUN %llu failed (%d, %d) "
 			 "iocb_flag x%x\n",
 			 lpfc_taskmgmt_name(task_mgmt_cmd),
 			 tgt_id, lun_id, iocbqrsp->iocb.ulpStatus,
@@ -5238,7 +5238,7 @@ lpfc_device_reset_handler(struct scsi_cm
 	struct lpfc_rport_data *rdata;
 	struct lpfc_nodelist *pnode;
 	unsigned tgt_id = cmnd->device->id;
-	unsigned int lun_id = cmnd->device->lun;
+	uint64_t lun_id = cmnd->device->lun;
 	struct lpfc_scsi_event_header scsi_event;
 	int status;
 
@@ -5273,7 +5273,7 @@ lpfc_device_reset_handler(struct scsi_cm
 						FCP_LUN_RESET);
 
 	lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-			 "0713 SCSI layer issued Device Reset (%d, %d) "
+			 "0713 SCSI layer issued Device Reset (%d, %llu) "
 			 "return x%x\n", tgt_id, lun_id, status);
 
 	/*
@@ -5308,7 +5308,7 @@ lpfc_target_reset_handler(struct scsi_cm
 	struct lpfc_rport_data *rdata;
 	struct lpfc_nodelist *pnode;
 	unsigned tgt_id = cmnd->device->id;
-	unsigned int lun_id = cmnd->device->lun;
+	uint64_t lun_id = cmnd->device->lun;
 	struct lpfc_scsi_event_header scsi_event;
 	int status;
 
@@ -5343,7 +5343,7 @@ lpfc_target_reset_handler(struct scsi_cm
 					FCP_TARGET_RESET);
 
 	lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-			 "0723 SCSI layer issued Target Reset (%d, %d) "
+			 "0723 SCSI layer issued Target Reset (%d, %llu) "
 			 "return x%x\n", tgt_id, lun_id, status);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/Makefile linux-libre-3.17-rc7-gnu/drivers/scsi/Makefile
--- linux-libre-3.16-gnu/drivers/scsi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,6 @@ CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__
 obj-$(CONFIG_PCMCIA)		+= pcmcia/
 
 obj-$(CONFIG_SCSI)		+= scsi_mod.o
-obj-$(CONFIG_SCSI_TGT)		+= scsi_tgt.o
 
 obj-$(CONFIG_RAID_ATTRS)	+= raid_class.o
 
@@ -127,9 +126,7 @@ obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o l
 obj-$(CONFIG_SCSI_SNI_53C710)	+= 53c700.o sni_53c710.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
-obj-$(CONFIG_SCSI_SRP)		+= libsrp.o
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi/
-obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_IBMVFC)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_HPTIOP)	+= hptiop.o
 obj-$(CONFIG_SCSI_STEX)		+= stex.o
@@ -173,8 +170,6 @@ scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
 
 hv_storvsc-y			:= storvsc_drv.o
 
-scsi_tgt-y			+= scsi_tgt_lib.o scsi_tgt_if.o
-
 sd_mod-objs	:= sd.o
 sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/megaraid/mega_common.h linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/mega_common.h
--- linux-libre-3.16-gnu/drivers/scsi/megaraid/mega_common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/mega_common.h	2014-09-28 17:29:07.000000000 -0400
@@ -204,7 +204,7 @@ typedef struct {
 #define SCP2HOSTDATA(scp)		SCP2HOST(scp)->hostdata	// to soft state
 #define SCP2CHANNEL(scp)		(scp)->device->channel	// to channel
 #define SCP2TARGET(scp)			(scp)->device->id	// to target
-#define SCP2LUN(scp)			(scp)->device->lun	// to LUN
+#define SCP2LUN(scp)			(u32)(scp)->device->lun	// to LUN
 
 // generic macro to convert scsi command and host to controller's soft state
 #define SCSIHOST2ADAP(host)	(((caddr_t *)(host->hostdata))[0])
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_mbox.c linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_mbox.c
--- linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_mbox.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_mbox.c	2014-09-28 17:29:07.000000000 -0400
@@ -998,8 +998,9 @@ megaraid_alloc_cmd_packets(adapter_t *ad
 	 * Allocate the common 16-byte aligned memory for the handshake
 	 * mailbox.
 	 */
-	raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,
-			sizeof(mbox64_t), &raid_dev->una_mbox64_dma);
+	raid_dev->una_mbox64 = pci_zalloc_consistent(adapter->pdev,
+						     sizeof(mbox64_t),
+						     &raid_dev->una_mbox64_dma);
 
 	if (!raid_dev->una_mbox64) {
 		con_log(CL_ANN, (KERN_WARNING
@@ -1007,7 +1008,6 @@ megaraid_alloc_cmd_packets(adapter_t *ad
 			__LINE__));
 		return -1;
 	}
-	memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));
 
 	/*
 	 * Align the mailbox at 16-byte boundary
@@ -1026,8 +1026,8 @@ megaraid_alloc_cmd_packets(adapter_t *ad
 			align;
 
 	// Allocate memory for commands issued internally
-	adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,
-				&adapter->ibuf_dma_h);
+	adapter->ibuf = pci_zalloc_consistent(pdev, MBOX_IBUF_SIZE,
+					      &adapter->ibuf_dma_h);
 	if (!adapter->ibuf) {
 
 		con_log(CL_ANN, (KERN_WARNING
@@ -1036,7 +1036,6 @@ megaraid_alloc_cmd_packets(adapter_t *ad
 
 		goto out_free_common_mbox;
 	}
-	memset(adapter->ibuf, 0, MBOX_IBUF_SIZE);
 
 	// Allocate memory for our SCSI Command Blocks and their associated
 	// memory
@@ -2972,8 +2971,8 @@ megaraid_mbox_product_info(adapter_t *ad
 	 * Issue an ENQUIRY3 command to find out certain adapter parameters,
 	 * e.g., max channels, max commands etc.
 	 */
-	pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
-			&pinfo_dma_h);
+	pinfo = pci_zalloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+				      &pinfo_dma_h);
 
 	if (pinfo == NULL) {
 		con_log(CL_ANN, (KERN_WARNING
@@ -2982,7 +2981,6 @@ megaraid_mbox_product_info(adapter_t *ad
 
 		return -1;
 	}
-	memset(pinfo, 0, sizeof(mraid_pinfo_t));
 
 	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
 	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_sas_base.c linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_sas_base.c
--- linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -2038,9 +2038,9 @@ int megasas_sriov_start_heartbeat(struct
 
 	if (initial) {
 		instance->hb_host_mem =
-			pci_alloc_consistent(instance->pdev,
-					     sizeof(struct MR_CTRL_HB_HOST_MEM),
-					     &instance->hb_host_mem_h);
+			pci_zalloc_consistent(instance->pdev,
+					      sizeof(struct MR_CTRL_HB_HOST_MEM),
+					      &instance->hb_host_mem_h);
 		if (!instance->hb_host_mem) {
 			printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate"
 			       " memory for heartbeat host memory for "
@@ -2048,8 +2048,6 @@ int megasas_sriov_start_heartbeat(struct
 			retval = -ENOMEM;
 			goto out;
 		}
-		memset(instance->hb_host_mem, 0,
-		       sizeof(struct MR_CTRL_HB_HOST_MEM));
 	}
 
 	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c
--- linux-libre-3.16-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c	2014-09-28 17:29:07.000000000 -0400
@@ -1690,7 +1690,7 @@ NonFastPath:
 			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
 	}
 	io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id);
-	io_request->LUN[1] = scmd->device->lun;
+	int_to_scsilun(scmd->device->lun, (struct scsi_lun *)io_request->LUN);
 }
 
 /**
@@ -1713,7 +1713,7 @@ megasas_build_io_fusion(struct megasas_i
 	device_id = MEGASAS_DEV_INDEX(instance, scp);
 
 	/* Zero out some fields so they don't get reused */
-	io_request->LUN[1] = 0;
+	memset(io_request->LUN, 0x0, 8);
 	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
 	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
 	io_request->EEDPFlags = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/megaraid.c linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid.c
--- linux-libre-3.16-gnu/drivers/scsi/megaraid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/megaraid.c	2014-09-28 17:29:07.000000000 -0400
@@ -1860,7 +1860,7 @@ megaraid_info(struct Scsi_Host *host)
 		 "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns",
 		 adapter->fw_version, adapter->product_info.max_commands,
 		 adapter->host->max_id, adapter->host->max_channel,
-		 adapter->host->max_lun);
+		 (u32)adapter->host->max_lun);
 	return buffer;
 }
 
@@ -1941,8 +1941,8 @@ megaraid_abort_and_reset(adapter_t *adap
 
 	printk(KERN_WARNING "megaraid: %s cmd=%x <c=%d t=%d l=%d>\n",
 	     (aor == SCB_ABORT)? "ABORTING":"RESET",
-	     cmd->cmnd[0], cmd->device->channel, 
-	     cmd->device->id, cmd->device->lun);
+	     cmd->cmnd[0], cmd->device->channel,
+	     cmd->device->id, (u32)cmd->device->lun);
 
 	if(list_empty(&adapter->pending_list))
 		return FALSE;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mesh.c linux-libre-3.17-rc7-gnu/drivers/scsi/mesh.c
--- linux-libre-3.16-gnu/drivers/scsi/mesh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mesh.c	2014-09-28 17:29:07.000000000 -0400
@@ -1230,7 +1230,7 @@ static void handle_msgin(struct mesh_sta
 				ms->msgphase = msg_out;
 			} else if (code != cmd->device->lun + IDENTIFY_BASE) {
 				printk(KERN_WARNING "mesh: lun mismatch "
-				       "(%d != %d) on reselection from "
+				       "(%d != %llu) on reselection from "
 				       "target %d\n", code - IDENTIFY_BASE,
 				       cmd->device->lun, ms->conn_tgt);
 			}
@@ -1915,14 +1915,12 @@ static int mesh_probe(struct macio_dev *
 	/* We use the PCI APIs for now until the generic one gets fixed
 	 * enough or until we get some macio-specific versions
 	 */
-	dma_cmd_space = pci_alloc_consistent(macio_get_pci_dev(mdev),
-					     ms->dma_cmd_size,
-					     &dma_cmd_bus);
+	dma_cmd_space = pci_zalloc_consistent(macio_get_pci_dev(mdev),
+					      ms->dma_cmd_size, &dma_cmd_bus);
 	if (dma_cmd_space == NULL) {
 		printk(KERN_ERR "mesh: can't allocate DMA table\n");
 		goto out_unmap;
 	}
-	memset(dma_cmd_space, 0, ms->dma_cmd_size);
 
 	ms->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space);
        	ms->dma_cmd_space = dma_cmd_space;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c
--- linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -277,7 +277,7 @@ mpt2sas_base_stop_watchdog(struct MPT2SA
 	ioc->fault_reset_work_q = NULL;
 	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 	if (wq) {
-		if (!cancel_delayed_work(&ioc->fault_reset_work))
+		if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
 			flush_workqueue(wq);
 		destroy_workqueue(wq);
 	}
@@ -1332,53 +1332,35 @@ _base_request_irq(struct MPT2SAS_ADAPTER
 static void
 _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
 {
-	struct adapter_reply_queue *reply_q;
-	int cpu_id;
-	int cpu_grouping, loop, grouping, grouping_mod;
+	unsigned int cpu, nr_cpus, nr_msix, index = 0;
 
 	if (!_base_is_controller_msix_enabled(ioc))
 		return;
 
 	memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
-	/* when there are more cpus than available msix vectors,
-	 * then group cpus togeather on same irq
-	 */
-	if (ioc->cpu_count > ioc->msix_vector_count) {
-		grouping = ioc->cpu_count / ioc->msix_vector_count;
-		grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
-		if (grouping < 2 || (grouping == 2 && !grouping_mod))
-			cpu_grouping = 2;
-		else if (grouping < 4 || (grouping == 4 && !grouping_mod))
-			cpu_grouping = 4;
-		else if (grouping < 8 || (grouping == 8 && !grouping_mod))
-			cpu_grouping = 8;
-		else
-			cpu_grouping = 16;
-	} else
-		cpu_grouping = 0;
 
-	loop = 0;
-	reply_q = list_entry(ioc->reply_queue_list.next,
-	     struct adapter_reply_queue, list);
-	for_each_online_cpu(cpu_id) {
-		if (!cpu_grouping) {
-			ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
-			reply_q = list_entry(reply_q->list.next,
-			    struct adapter_reply_queue, list);
-		} else {
-			if (loop < cpu_grouping) {
-				ioc->cpu_msix_table[cpu_id] =
-					reply_q->msix_index;
-				loop++;
-			} else {
-				reply_q = list_entry(reply_q->list.next,
-				    struct adapter_reply_queue, list);
-				ioc->cpu_msix_table[cpu_id] =
-					reply_q->msix_index;
-				loop = 1;
-			}
+	nr_cpus = num_online_cpus();
+	nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
+					       ioc->facts.MaxMSIxVectors);
+	if (!nr_msix)
+		return;
+
+	cpu = cpumask_first(cpu_online_mask);
+
+	do {
+		unsigned int i, group = nr_cpus / nr_msix;
+
+		if (index < nr_cpus % nr_msix)
+			group++;
+
+		for (i = 0 ; i < group ; i++) {
+			ioc->cpu_msix_table[cpu] = index;
+			cpu = cpumask_next(cpu, cpu_online_mask);
 		}
-	}
+
+		index++;
+
+	} while (cpu < nr_cpus);
 }
 
 /**
@@ -4295,12 +4277,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPT
 		goto out_free_resources;
 
 	if (ioc->is_warpdrive) {
-		ioc->reply_post_host_index[0] =
-		    (resource_size_t *)&ioc->chip->ReplyPostHostIndex;
+		ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
+		    &ioc->chip->ReplyPostHostIndex;
 
 		for (i = 1; i < ioc->cpu_msix_table_sz; i++)
-			ioc->reply_post_host_index[i] = (resource_size_t *)
-			((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+			ioc->reply_post_host_index[i] =
+			(resource_size_t __iomem *)
+			((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
 			* 4)));
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h
--- linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h	2014-09-28 17:29:07.000000000 -0400
@@ -837,7 +837,7 @@ struct MPT2SAS_ADAPTER {
 	u8		msix_enable;
 	u16		msix_vector_count;
 	u8		*cpu_msix_table;
-	resource_size_t	**reply_post_host_index;
+	resource_size_t	__iomem **reply_post_host_index;
 	u16		cpu_msix_table_sz;
 	u32		ioc_reset_count;
 	MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c
--- linux-libre-3.16-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,7 +173,7 @@ struct fw_event_work {
 	u8			VP_ID;
 	u8			ignore;
 	u16			event;
-	void			*event_data;
+	char			event_data[0] __aligned(4);
 };
 
 /* raid transport support */
@@ -1292,7 +1292,8 @@ _scsih_target_alloc(struct scsi_target *
 	unsigned long flags;
 	struct sas_rphy *rphy;
 
-	sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+	sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
+				       GFP_KERNEL);
 	if (!sas_target_priv_data)
 		return -ENOMEM;
 
@@ -1406,7 +1407,8 @@ _scsih_slave_alloc(struct scsi_device *s
 	struct _sas_device *sas_device;
 	unsigned long flags;
 
-	sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+	sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
+				       GFP_KERNEL);
 	if (!sas_device_priv_data)
 		return -ENOMEM;
 
@@ -2832,7 +2834,6 @@ _scsih_fw_event_free(struct MPT2SAS_ADAP
 
 	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 	list_del(&fw_event->list);
-	kfree(fw_event->event_data);
 	kfree(fw_event);
 	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
@@ -2899,11 +2900,10 @@ _scsih_fw_event_cleanup_queue(struct MPT
 		return;
 
 	list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
-		if (cancel_delayed_work(&fw_event->delayed_work)) {
+		if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
 			_scsih_fw_event_free(ioc, fw_event);
 			continue;
 		}
-		fw_event->cancel_pending_work = 1;
 	}
 }
 
@@ -3518,7 +3518,8 @@ _scsih_check_topo_delete_events(struct M
 		if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
 		    fw_event->ignore)
 			continue;
-		local_event_data = fw_event->event_data;
+		local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
+			fw_event->event_data;
 		if (local_event_data->ExpStatus ==
 		    MPI2_EVENT_SAS_TOPO_ES_ADDED ||
 		    local_event_data->ExpStatus ==
@@ -5502,7 +5503,9 @@ _scsih_sas_topology_change_event(struct
 	u64 sas_address;
 	unsigned long flags;
 	u8 link_rate, prev_link_rate;
-	Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasTopologyChangeList_t *event_data =
+		(Mpi2EventDataSasTopologyChangeList_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5697,7 +5700,8 @@ _scsih_sas_device_status_change_event(st
 	u64 sas_address;
 	unsigned long flags;
 	Mpi2EventDataSasDeviceStatusChange_t *event_data =
-	    fw_event->event_data;
+		(Mpi2EventDataSasDeviceStatusChange_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5792,6 +5796,7 @@ _scsih_sas_enclosure_dev_status_change_e
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
 		_scsih_sas_enclosure_dev_status_change_event_debug(ioc,
+		     (Mpi2EventDataSasEnclDevStatusChange_t *)
 		     fw_event->event_data);
 #endif
 }
@@ -5816,7 +5821,9 @@ _scsih_sas_broadcast_primitive_event(str
 	u32 termination_count;
 	u32 query_count;
 	Mpi2SCSITaskManagementReply_t *mpi_reply;
-	Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasBroadcastPrimitive_t *event_data =
+		(Mpi2EventDataSasBroadcastPrimitive_t *)
+		fw_event->event_data;
 	u16 ioc_status;
 	unsigned long flags;
 	int r;
@@ -5967,7 +5974,9 @@ static void
 _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
-	Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasDiscovery_t *event_data =
+		(Mpi2EventDataSasDiscovery_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
@@ -6355,7 +6364,9 @@ _scsih_sas_ir_config_change_event(struct
 	Mpi2EventIrConfigElement_t *element;
 	int i;
 	u8 foreign_config;
-	Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrConfigChangeList_t *event_data =
+		(Mpi2EventDataIrConfigChangeList_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -6423,7 +6434,9 @@ _scsih_sas_ir_volume_event(struct MPT2SA
 	u16 handle;
 	u32 state;
 	int rc;
-	Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrVolume_t *event_data =
+		(Mpi2EventDataIrVolume_t *)
+		fw_event->event_data;
 
 	if (ioc->shost_recovery)
 		return;
@@ -6507,7 +6520,9 @@ _scsih_sas_ir_physical_disk_event(struct
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasDevicePage0_t sas_device_pg0;
 	u32 ioc_status;
-	Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrPhysicalDisk_t *event_data =
+		(Mpi2EventDataIrPhysicalDisk_t *)
+		fw_event->event_data;
 	u64 sas_address;
 
 	if (ioc->shost_recovery)
@@ -6630,7 +6645,9 @@ static void
 _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
-	Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrOperationStatus_t *event_data =
+		(Mpi2EventDataIrOperationStatus_t *)
+		fw_event->event_data;
 	static struct _raid_device *raid_device;
 	unsigned long flags;
 	u16 handle;
@@ -7401,7 +7418,7 @@ _firmware_event_work(struct work_struct
 	struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
 
 	/* the queue is being flushed so ignore this event */
-	if (ioc->remove_host || fw_event->cancel_pending_work ||
+	if (ioc->remove_host ||
 	    ioc->pci_error_recovery) {
 		_scsih_fw_event_free(ioc, fw_event);
 		return;
@@ -7590,23 +7607,15 @@ mpt2sas_scsih_event_callback(struct MPT2
 		return;
 	}
 
-	fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
-	if (!fw_event) {
-		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-		    ioc->name, __FILE__, __LINE__, __func__);
-		return;
-	}
 	sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-	fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
-	if (!fw_event->event_data) {
+	fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+	if (!fw_event) {
 		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 		    ioc->name, __FILE__, __LINE__, __func__);
-		kfree(fw_event);
 		return;
 	}
 
-	memcpy(fw_event->event_data, mpi_reply->EventData,
-	    sz);
+	memcpy(fw_event->event_data, mpi_reply->EventData, sz);
 	fw_event->ioc = ioc;
 	fw_event->VF_ID = mpi_reply->VF_ID;
 	fw_event->VP_ID = mpi_reply->VP_ID;
@@ -7857,9 +7866,9 @@ _scsih_remove(struct pci_dev *pdev)
 	}
 
 	sas_remove_host(shost);
+	scsi_remove_host(shost);
 	mpt2sas_base_detach(ioc);
 	list_del(&ioc->list);
-	scsi_remove_host(shost);
 	scsi_host_put(shost);
 }
 
@@ -8200,13 +8209,6 @@ _scsih_probe(struct pci_dev *pdev, const
 		}
 	}
 
-	if ((scsi_add_host(shost, &pdev->dev))) {
-		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-		    ioc->name, __FILE__, __LINE__, __func__);
-		list_del(&ioc->list);
-		goto out_add_shost_fail;
-	}
-
 	/* register EEDP capabilities with SCSI layer */
 	if (prot_mask)
 		scsi_host_set_prot(shost, prot_mask);
@@ -8248,16 +8250,23 @@ _scsih_probe(struct pci_dev *pdev, const
 		}
 	} else
 		ioc->hide_drives = 0;
+
+	if ((scsi_add_host(shost, &pdev->dev))) {
+		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+		    ioc->name, __FILE__, __LINE__, __func__);
+		goto out_add_shost_fail;
+	}
+
 	scsi_scan_host(shost);
 
 	return 0;
 
+ out_add_shost_fail:
+	mpt2sas_base_detach(ioc);
  out_attach_fail:
 	destroy_workqueue(ioc->firmware_event_thread);
  out_thread_fail:
 	list_del(&ioc->list);
-	scsi_remove_host(shost);
- out_add_shost_fail:
 	scsi_host_put(shost);
 	return -ENODEV;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mpt3sas/mpt3sas_base.c linux-libre-3.17-rc7-gnu/drivers/scsi/mpt3sas/mpt3sas_base.c
--- linux-libre-3.16-gnu/drivers/scsi/mpt3sas/mpt3sas_base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mpt3sas/mpt3sas_base.c	2014-09-28 17:29:07.000000000 -0400
@@ -266,7 +266,7 @@ mpt3sas_base_stop_watchdog(struct MPT3SA
 	ioc->fault_reset_work_q = NULL;
 	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 	if (wq) {
-		if (!cancel_delayed_work(&ioc->fault_reset_work))
+		if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
 			flush_workqueue(wq);
 		destroy_workqueue(wq);
 	}
@@ -1624,66 +1624,35 @@ _base_request_irq(struct MPT3SAS_ADAPTER
 static void
 _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
 {
-	struct adapter_reply_queue *reply_q;
-	int cpu_id;
-	int cpu_grouping, loop, grouping, grouping_mod;
-	int reply_queue;
+	unsigned int cpu, nr_cpus, nr_msix, index = 0;
 
 	if (!_base_is_controller_msix_enabled(ioc))
 		return;
 
 	memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
 
-	/* NUMA Hardware bug workaround - drop to less reply queues */
-	if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) {
-		ioc->reply_queue_count = ioc->facts.MaxMSIxVectors;
-		reply_queue = 0;
-		list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-			reply_q->msix_index = reply_queue;
-			if (++reply_queue == ioc->reply_queue_count)
-				reply_queue = 0;
-		}
-	}
+	nr_cpus = num_online_cpus();
+	nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
+					       ioc->facts.MaxMSIxVectors);
+	if (!nr_msix)
+		return;
 
-	/* when there are more cpus than available msix vectors,
-	 * then group cpus togeather on same irq
-	 */
-	if (ioc->cpu_count > ioc->msix_vector_count) {
-		grouping = ioc->cpu_count / ioc->msix_vector_count;
-		grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
-		if (grouping < 2 || (grouping == 2 && !grouping_mod))
-			cpu_grouping = 2;
-		else if (grouping < 4 || (grouping == 4 && !grouping_mod))
-			cpu_grouping = 4;
-		else if (grouping < 8 || (grouping == 8 && !grouping_mod))
-			cpu_grouping = 8;
-		else
-			cpu_grouping = 16;
-	} else
-		cpu_grouping = 0;
+	cpu = cpumask_first(cpu_online_mask);
 
-	loop = 0;
-	reply_q = list_entry(ioc->reply_queue_list.next,
-	     struct adapter_reply_queue, list);
-	for_each_online_cpu(cpu_id) {
-		if (!cpu_grouping) {
-			ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
-			reply_q = list_entry(reply_q->list.next,
-			    struct adapter_reply_queue, list);
-		} else {
-			if (loop < cpu_grouping) {
-				ioc->cpu_msix_table[cpu_id] =
-				    reply_q->msix_index;
-				loop++;
-			} else {
-				reply_q = list_entry(reply_q->list.next,
-				    struct adapter_reply_queue, list);
-				ioc->cpu_msix_table[cpu_id] =
-				    reply_q->msix_index;
-				loop = 1;
-			}
+	do {
+		unsigned int i, group = nr_cpus / nr_msix;
+
+		if (index < nr_cpus % nr_msix)
+			group++;
+
+		for (i = 0 ; i < group ; i++) {
+			ioc->cpu_msix_table[cpu] = index;
+			cpu = cpumask_next(cpu, cpu_online_mask);
 		}
-	}
+
+		index++;
+
+	} while (cpu < nr_cpus);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mpt3sas/mpt3sas_scsih.c linux-libre-3.17-rc7-gnu/drivers/scsi/mpt3sas/mpt3sas_scsih.c
--- linux-libre-3.16-gnu/drivers/scsi/mpt3sas/mpt3sas_scsih.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mpt3sas/mpt3sas_scsih.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,8 +112,8 @@ MODULE_PARM_DESC(missing_delay, " device
 
 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
 #define MPT3SAS_MAX_LUN (16895)
-static int max_lun = MPT3SAS_MAX_LUN;
-module_param(max_lun, int, 0);
+static u64 max_lun = MPT3SAS_MAX_LUN;
+module_param(max_lun, ullong, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
 
@@ -190,7 +190,7 @@ struct fw_event_work {
 	u8			VP_ID;
 	u8			ignore;
 	u16			event;
-	void			*event_data;
+	char			event_data[0] __aligned(4);
 };
 
 /* raid transport support */
@@ -247,7 +247,7 @@ struct _scsi_io_transfer {
 /*
  * The pci device ids are defined in mpi/mpi2_cnfg.h.
  */
-static DEFINE_PCI_DEVICE_TABLE(scsih_pci_table) = {
+static const struct pci_device_id scsih_pci_table[] = {
 	/* Fury ~ 3004 and 3008 */
 	{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
 		PCI_ANY_ID, PCI_ANY_ID },
@@ -1163,7 +1163,8 @@ _scsih_target_alloc(struct scsi_target *
 	unsigned long flags;
 	struct sas_rphy *rphy;
 
-	sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+	sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
+				       GFP_KERNEL);
 	if (!sas_target_priv_data)
 		return -ENOMEM;
 
@@ -1277,7 +1278,8 @@ _scsih_slave_alloc(struct scsi_device *s
 	struct _sas_device *sas_device;
 	unsigned long flags;
 
-	sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+	sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
+				       GFP_KERNEL);
 	if (!sas_device_priv_data)
 		return -ENOMEM;
 
@@ -2490,7 +2492,6 @@ _scsih_fw_event_free(struct MPT3SAS_ADAP
 
 	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 	list_del(&fw_event->list);
-	kfree(fw_event->event_data);
 	kfree(fw_event);
 	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
@@ -2511,12 +2512,10 @@ mpt3sas_send_trigger_data_event(struct M
 
 	if (ioc->is_driver_loading)
 		return;
-	fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+	fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data),
+			   GFP_ATOMIC);
 	if (!fw_event)
 		return;
-	fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC);
-	if (!fw_event->event_data)
-		return;
 	fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
 	fw_event->ioc = ioc;
 	memcpy(fw_event->event_data, event_data, sizeof(*event_data));
@@ -2582,11 +2581,10 @@ _scsih_fw_event_cleanup_queue(struct MPT
 		return;
 
 	list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
-		if (cancel_delayed_work(&fw_event->delayed_work)) {
+		if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
 			_scsih_fw_event_free(ioc, fw_event);
 			continue;
 		}
-		fw_event->cancel_pending_work = 1;
 	}
 }
 
@@ -3211,7 +3209,8 @@ _scsih_check_topo_delete_events(struct M
 		if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
 		    fw_event->ignore)
 			continue;
-		local_event_data = fw_event->event_data;
+		local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
+				   fw_event->event_data;
 		if (local_event_data->ExpStatus ==
 		    MPI2_EVENT_SAS_TOPO_ES_ADDED ||
 		    local_event_data->ExpStatus ==
@@ -5043,7 +5042,9 @@ _scsih_sas_topology_change_event(struct
 	u64 sas_address;
 	unsigned long flags;
 	u8 link_rate, prev_link_rate;
-	Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasTopologyChangeList_t *event_data =
+		(Mpi2EventDataSasTopologyChangeList_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5241,7 +5242,8 @@ _scsih_sas_device_status_change_event(st
 	u64 sas_address;
 	unsigned long flags;
 	Mpi2EventDataSasDeviceStatusChange_t *event_data =
-	    fw_event->event_data;
+		(Mpi2EventDataSasDeviceStatusChange_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -5337,6 +5339,7 @@ _scsih_sas_enclosure_dev_status_change_e
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
 		_scsih_sas_enclosure_dev_status_change_event_debug(ioc,
+		     (Mpi2EventDataSasEnclDevStatusChange_t *)
 		     fw_event->event_data);
 #endif
 }
@@ -5361,7 +5364,9 @@ _scsih_sas_broadcast_primitive_event(str
 	u32 termination_count;
 	u32 query_count;
 	Mpi2SCSITaskManagementReply_t *mpi_reply;
-	Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasBroadcastPrimitive_t *event_data =
+		(Mpi2EventDataSasBroadcastPrimitive_t *)
+		fw_event->event_data;
 	u16 ioc_status;
 	unsigned long flags;
 	int r;
@@ -5513,7 +5518,8 @@ static void
 _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
 	struct fw_event_work *fw_event)
 {
-	Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+	Mpi2EventDataSasDiscovery_t *event_data =
+		(Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
@@ -5999,7 +6005,9 @@ _scsih_sas_ir_config_change_event(struct
 	Mpi2EventIrConfigElement_t *element;
 	int i;
 	u8 foreign_config;
-	Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrConfigChangeList_t *event_data =
+		(Mpi2EventDataIrConfigChangeList_t *)
+		fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 	if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -6069,7 +6077,8 @@ _scsih_sas_ir_volume_event(struct MPT3SA
 	u16 handle;
 	u32 state;
 	int rc;
-	Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrVolume_t *event_data =
+		(Mpi2EventDataIrVolume_t *) fw_event->event_data;
 
 	if (ioc->shost_recovery)
 		return;
@@ -6152,7 +6161,8 @@ _scsih_sas_ir_physical_disk_event(struct
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasDevicePage0_t sas_device_pg0;
 	u32 ioc_status;
-	Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrPhysicalDisk_t *event_data =
+		(Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
 	u64 sas_address;
 
 	if (ioc->shost_recovery)
@@ -6272,7 +6282,9 @@ static void
 _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
 	struct fw_event_work *fw_event)
 {
-	Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
+	Mpi2EventDataIrOperationStatus_t *event_data =
+		(Mpi2EventDataIrOperationStatus_t *)
+		fw_event->event_data;
 	static struct _raid_device *raid_device;
 	unsigned long flags;
 	u16 handle;
@@ -7026,7 +7038,7 @@ static void
 _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 {
 	/* the queue is being flushed so ignore this event */
-	if (ioc->remove_host || fw_event->cancel_pending_work ||
+	if (ioc->remove_host ||
 	    ioc->pci_error_recovery) {
 		_scsih_fw_event_free(ioc, fw_event);
 		return;
@@ -7034,7 +7046,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER
 
 	switch (fw_event->event) {
 	case MPT3SAS_PROCESS_TRIGGER_DIAG:
-		mpt3sas_process_trigger_data(ioc, fw_event->event_data);
+		mpt3sas_process_trigger_data(ioc,
+			(struct SL_WH_TRIGGERS_EVENT_DATA_T *)
+			fw_event->event_data);
 		break;
 	case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
 		while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
@@ -7192,18 +7206,11 @@ mpt3sas_scsih_event_callback(struct MPT3
 		return 1;
 	}
 
-	fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
-	if (!fw_event) {
-		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
-		    ioc->name, __FILE__, __LINE__, __func__);
-		return 1;
-	}
 	sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-	fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
-	if (!fw_event->event_data) {
+	fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+	if (!fw_event) {
 		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
 		    ioc->name, __FILE__, __LINE__, __func__);
-		kfree(fw_event);
 		return 1;
 	}
 
@@ -7431,9 +7438,9 @@ static void _scsih_remove(struct pci_dev
 	}
 
 	sas_remove_host(shost);
+	scsi_remove_host(shost);
 	mpt3sas_base_detach(ioc);
 	list_del(&ioc->list);
-	scsi_remove_host(shost);
 	scsi_host_put(shost);
 }
 
@@ -7801,13 +7808,6 @@ _scsih_probe(struct pci_dev *pdev, const
 		}
 	}
 
-	if ((scsi_add_host(shost, &pdev->dev))) {
-		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
-		    ioc->name, __FILE__, __LINE__, __func__);
-		list_del(&ioc->list);
-		goto out_add_shost_fail;
-	}
-
 	/* register EEDP capabilities with SCSI layer */
 	if (prot_mask > 0)
 		scsi_host_set_prot(shost, prot_mask);
@@ -7835,15 +7835,21 @@ _scsih_probe(struct pci_dev *pdev, const
 		    ioc->name, __FILE__, __LINE__, __func__);
 		goto out_attach_fail;
 	}
+	if ((scsi_add_host(shost, &pdev->dev))) {
+		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+		    ioc->name, __FILE__, __LINE__, __func__);
+		list_del(&ioc->list);
+		goto out_add_shost_fail;
+	}
+
 	scsi_scan_host(shost);
 	return 0;
-
+out_add_shost_fail:
+	mpt3sas_base_detach(ioc);
  out_attach_fail:
 	destroy_workqueue(ioc->firmware_event_thread);
  out_thread_fail:
 	list_del(&ioc->list);
-	scsi_remove_host(shost);
- out_add_shost_fail:
 	scsi_host_put(shost);
 	return -ENODEV;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mvsas/mv_sas.c linux-libre-3.17-rc7-gnu/drivers/scsi/mvsas/mv_sas.c
--- linux-libre-3.16-gnu/drivers/scsi/mvsas/mv_sas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mvsas/mv_sas.c	2014-09-28 17:29:07.000000000 -0400
@@ -1344,19 +1344,23 @@ void mvs_dev_gone_notify(struct domain_d
 {
 	unsigned long flags = 0;
 	struct mvs_device *mvi_dev = dev->lldd_dev;
-	struct mvs_info *mvi = mvi_dev->mvi_info;
-
-	spin_lock_irqsave(&mvi->lock, flags);
+	struct mvs_info *mvi;
 
-	if (mvi_dev) {
-		mv_dprintk("found dev[%d:%x] is gone.\n",
-			mvi_dev->device_id, mvi_dev->dev_type);
-		mvs_release_task(mvi, dev);
-		mvs_free_reg_set(mvi, mvi_dev);
-		mvs_free_dev(mvi_dev);
-	} else {
+	if (!mvi_dev) {
 		mv_dprintk("found dev has gone.\n");
+		return;
 	}
+
+	mvi = mvi_dev->mvi_info;
+
+	spin_lock_irqsave(&mvi->lock, flags);
+
+	mv_dprintk("found dev[%d:%x] is gone.\n",
+		mvi_dev->device_id, mvi_dev->dev_type);
+	mvs_release_task(mvi, dev);
+	mvs_free_reg_set(mvi, mvi_dev);
+	mvs_free_dev(mvi_dev);
+
 	dev->lldd_dev = NULL;
 	mvi_dev->sas_device = NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/mvumi.c linux-libre-3.17-rc7-gnu/drivers/scsi/mvumi.c
--- linux-libre-3.16-gnu/drivers/scsi/mvumi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/mvumi.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("jyli@marvell.com");
 MODULE_DESCRIPTION("Marvell UMI Driver");
 
-static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
+static const struct pci_device_id mvumi_pci_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) },
 	{ 0 }
@@ -142,8 +142,8 @@ static struct mvumi_res *mvumi_alloc_mem
 
 	case RESOURCE_UNCACHED_MEMORY:
 		size = round_up(size, 8);
-		res->virt_addr = pci_alloc_consistent(mhba->pdev, size,
-							&res->bus_addr);
+		res->virt_addr = pci_zalloc_consistent(mhba->pdev, size,
+						       &res->bus_addr);
 		if (!res->virt_addr) {
 			dev_err(&mhba->pdev->dev,
 					"unable to allocate consistent mem,"
@@ -151,7 +151,6 @@ static struct mvumi_res *mvumi_alloc_mem
 			kfree(res);
 			return NULL;
 		}
-		memset(res->virt_addr, 0, size);
 		break;
 
 	default:
@@ -258,12 +257,10 @@ static int mvumi_internal_cmd_sgl(struct
 	if (size == 0)
 		return 0;
 
-	virt_addr = pci_alloc_consistent(mhba->pdev, size, &phy_addr);
+	virt_addr = pci_zalloc_consistent(mhba->pdev, size, &phy_addr);
 	if (!virt_addr)
 		return -1;
 
-	memset(virt_addr, 0, size);
-
 	m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
 	cmd->frame->sg_counts = 1;
 	cmd->data_buf = virt_addr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/NCR5380.c linux-libre-3.17-rc7-gnu/drivers/scsi/NCR5380.c
--- linux-libre-3.16-gnu/drivers/scsi/NCR5380.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/NCR5380.c	2014-09-28 17:29:07.000000000 -0400
@@ -762,7 +762,7 @@ static int __maybe_unused NCR5380_show_i
 
 static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
 {
-	SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
+	SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
 	SPRINTF("        command = ");
 	lprint_command(cmd->cmnd, m);
 }
@@ -1039,9 +1039,10 @@ static void NCR5380_main(struct work_str
 			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) 
 			{
 				if (prev != tmp)
-					dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
+				    dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
 				/*  When we find one, remove it from the issue queue. */
-				if (!(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))) {
+				if (!(hostdata->busy[tmp->device->id] &
+				      (1 << (u8)(tmp->device->lun & 0xff)))) {
 					if (prev) {
 						REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
 						prev->host_scribble = tmp->host_scribble;
@@ -1057,7 +1058,7 @@ static void NCR5380_main(struct work_str
 					 * On failure, we must add the command back to the
 					 *   issue queue so we can keep trying. 
 					 */
-					dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun);
+					dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun);
 	
 					/*
 					 * A successful selection is defined as one that 
@@ -1524,7 +1525,7 @@ part2:
 	dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no);
 	/* XXX need to handle errors here */
 	hostdata->connected = cmd;
-	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+	hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
 
 	initialize_SCp(cmd);
 
@@ -2210,14 +2211,14 @@ static void NCR5380_information_transfer
 				case LINKED_FLG_CMD_COMPLETE:
 					/* Accept message by clearing ACK */
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-					dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun);
+					dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun);
 					/* 
 					 * Sanity check : A linked command should only terminate with
 					 * one of these messages if there are more linked commands
 					 * available.
 					 */
 					if (!cmd->next_link) {
-						printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun);
+					    printk("scsi%d : target %d lun %llu linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun);
 						sink = 1;
 						do_abort(instance);
 						return;
@@ -2226,7 +2227,7 @@ static void NCR5380_information_transfer
 					/* The next command is still part of this process */
 					cmd->next_link->tag = cmd->tag;
 					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
-					dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
+					dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
 					collect_stats(hostdata, cmd);
 					cmd->scsi_done(cmd);
 					cmd = hostdata->connected;
@@ -2238,8 +2239,8 @@ static void NCR5380_information_transfer
 					sink = 1;
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 					hostdata->connected = NULL;
-					dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->device->id, cmd->device->lun);
-					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+					dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %llu completed\n", instance->host_no, cmd->device->id, cmd->device->lun);
+					hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
 
 					/* 
 					 * I'm not sure what the correct thing to do here is : 
@@ -2304,7 +2305,7 @@ static void NCR5380_information_transfer
 					case ORDERED_QUEUE_TAG:
 					case SIMPLE_QUEUE_TAG:
 						cmd->device->simple_tags = 0;
-						hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+						hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
 						break;
 					default:
 						break;
@@ -2318,7 +2319,7 @@ static void NCR5380_information_transfer
 						    hostdata->disconnected_queue;
 						hostdata->connected = NULL;
 						hostdata->disconnected_queue = cmd;
-						dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %d was moved from connected to" "  the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun);
+						dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %llu was moved from connected to" "  the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun);
 						/* 
 						 * Restore phase bits to 0 so an interrupted selection, 
 						 * arbitration can resume.
@@ -2426,7 +2427,7 @@ static void NCR5380_information_transfer
 				hostdata->last_message = msgout;
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
 				if (msgout == ABORT) {
-					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+					hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
 					hostdata->connected = NULL;
 					cmd->result = DID_ERROR << 16;
 					collect_stats(hostdata, cmd);
@@ -2562,7 +2563,7 @@ static void NCR5380_reselect(struct Scsi
 
 
 		for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
-			if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+			if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)
 			    ) {
 				if (prev) {
 					REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
@@ -2588,7 +2589,7 @@ static void NCR5380_reselect(struct Scsi
 		do_abort(instance);
 	} else {
 		hostdata->connected = tmp;
-		dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag);
+		dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/NCR53c406a.c linux-libre-3.17-rc7-gnu/drivers/scsi/NCR53c406a.c
--- linux-libre-3.16-gnu/drivers/scsi/NCR53c406a.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/NCR53c406a.c	2014-09-28 17:29:07.000000000 -0400
@@ -595,7 +595,7 @@ static int NCR53c406a_release(struct Scs
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
-#ifdef USE_DMA
+#if USE_DMA
 	if (shost->dma_channel != 0xff)
 		free_dma(shost->dma_channel);
 #endif
@@ -698,7 +698,7 @@ static int NCR53c406a_queue_lck(Scsi_Cmn
 	int i;
 
 	VDEB(printk("NCR53c406a_queue called\n"));
-	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
+        DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->target, (u8)SCpnt->device->lun, scsi_bufflen(SCpnt)));
 
 #if 0
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ncr53c8xx.c linux-libre-3.17-rc7-gnu/drivers/scsi/ncr53c8xx.c
--- linux-libre-3.16-gnu/drivers/scsi/ncr53c8xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ncr53c8xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -6633,7 +6633,7 @@ static void ncr_sir_to_redo(struct ncb *
 		**	patch requested size into sense command
 		*/
 		cp->sensecmd[0]		= 0x03;
-		cp->sensecmd[1]		= cmd->device->lun << 5;
+		cp->sensecmd[1]		= (cmd->device->lun & 0x7) << 5;
 		cp->sensecmd[4]		= sizeof(cp->sense_buf);
 
 		/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ncr53c8xx.h linux-libre-3.17-rc7-gnu/drivers/scsi/ncr53c8xx.h
--- linux-libre-3.16-gnu/drivers/scsi/ncr53c8xx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ncr53c8xx.h	2014-09-28 17:29:07.000000000 -0400
@@ -264,11 +264,7 @@
 #define SCSI_NCR_SG_TABLESIZE	(SCSI_NCR_MAX_SCATTER)
 #define SCSI_NCR_TIMER_INTERVAL	(HZ)
 
-#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
 #define SCSI_NCR_MAX_LUN	(16)
-#else
-#define SCSI_NCR_MAX_LUN	(1)
-#endif
 
 /*
  *  IO functions definition for big/little endian CPU support.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/nsp32.c linux-libre-3.17-rc7-gnu/drivers/scsi/nsp32.c
--- linux-libre-3.16-gnu/drivers/scsi/nsp32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/nsp32.c	2014-09-28 17:29:07.000000000 -0400
@@ -915,7 +915,7 @@ static int nsp32_queuecommand_lck(struct
 	int ret;
 
 	nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND,
-		  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
+		  "enter. target: 0x%x LUN: 0x%llu cmnd: 0x%x cmndlen: 0x%x "
 		  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
 		  SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
 		  scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pas16.c linux-libre-3.17-rc7-gnu/drivers/scsi/pas16.c
--- linux-libre-3.16-gnu/drivers/scsi/pas16.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pas16.c	2014-09-28 17:29:07.000000000 -0400
@@ -607,8 +607,6 @@ static int pas16_release(struct Scsi_Hos
 	if (shost->irq)
 		free_irq(shost->irq, shost);
 	NCR5380_exit(shost);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 	scsi_unregister(shost);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pcmcia/nsp_cs.c linux-libre-3.17-rc7-gnu/drivers/scsi/pcmcia/nsp_cs.c
--- linux-libre-3.16-gnu/drivers/scsi/pcmcia/nsp_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pcmcia/nsp_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -195,7 +195,7 @@ static int nsp_queuecommand_lck(struct s
 	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
 
 	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
-		"SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
+		"SCpnt=0x%p target=%d lun=%llu sglist=0x%p bufflen=%d sg_count=%d",
 		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
 		scsi_bufflen(SCpnt), scsi_sg_count(SCpnt));
 	//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pcmcia/sym53c500_cs.c linux-libre-3.17-rc7-gnu/drivers/scsi/pcmcia/sym53c500_cs.c
--- linux-libre-3.16-gnu/drivers/scsi/pcmcia/sym53c500_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pcmcia/sym53c500_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -558,7 +558,7 @@ SYM53C500_queue_lck(struct scsi_cmnd *SC
 
 	DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
 	    SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, 
-	    SCpnt->device->lun,  scsi_bufflen(SCpnt)));
+		   (u8)SCpnt->device->lun,  scsi_bufflen(SCpnt)));
 
 	VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
 	    printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_ctl.c linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_ctl.c
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_ctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_ctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -397,7 +397,10 @@ static ssize_t pm8001_ctl_bios_version_s
 	payload.func_specific = kzalloc(4096, GFP_KERNEL);
 	if (!payload.func_specific)
 		return -ENOMEM;
-	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+	if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) {
+		kfree(payload.func_specific);
+		return -ENOMEM;
+	}
 	wait_for_completion(&completion);
 	virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr;
 	for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT;
@@ -523,18 +526,19 @@ static int pm8001_set_nvmd(struct pm8001
 {
 	struct pm8001_ioctl_payload	*payload;
 	DECLARE_COMPLETION_ONSTACK(completion);
-	u8		*ioctlbuffer = NULL;
-	u32		length = 0;
-	u32		ret = 0;
+	u8		*ioctlbuffer;
+	u32		ret;
+	u32		length = 1024 * 5 + sizeof(*payload) - 1;
+
+	if (pm8001_ha->fw_image->size > 4096) {
+		pm8001_ha->fw_status = FAIL_FILE_SIZE;
+		return -EFAULT;
+	}
 
-	length = 1024 * 5 + sizeof(*payload) - 1;
 	ioctlbuffer = kzalloc(length, GFP_KERNEL);
-	if (!ioctlbuffer)
+	if (!ioctlbuffer) {
+		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
 		return -ENOMEM;
-	if ((pm8001_ha->fw_image->size <= 0) ||
-	    (pm8001_ha->fw_image->size > 4096)) {
-		ret = FAIL_FILE_SIZE;
-		goto out;
 	}
 	payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
 	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
@@ -544,6 +548,10 @@ static int pm8001_set_nvmd(struct pm8001
 	payload->minor_function = 0x1;
 	pm8001_ha->nvmd_completion = &completion;
 	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
+	if (ret) {
+		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
+		goto out;
+	}
 	wait_for_completion(&completion);
 out:
 	kfree(ioctlbuffer);
@@ -554,35 +562,31 @@ static int pm8001_update_flash(struct pm
 {
 	struct pm8001_ioctl_payload	*payload;
 	DECLARE_COMPLETION_ONSTACK(completion);
-	u8		*ioctlbuffer = NULL;
-	u32		length = 0;
+	u8		*ioctlbuffer;
 	struct fw_control_info	*fwControl;
-	u32		loopNumber, loopcount = 0;
-	u32		sizeRead = 0;
 	u32		partitionSize, partitionSizeTmp;
-	u32		ret = 0;
-	u32		partitionNumber = 0;
+	u32		loopNumber, loopcount;
 	struct pm8001_fw_image_header *image_hdr;
+	u32		sizeRead = 0;
+	u32		ret = 0;
+	u32		length = 1024 * 16 + sizeof(*payload) - 1;
 
-	length = 1024 * 16 + sizeof(*payload) - 1;
+	if (pm8001_ha->fw_image->size < 28) {
+		pm8001_ha->fw_status = FAIL_FILE_SIZE;
+		return -EFAULT;
+	}
 	ioctlbuffer = kzalloc(length, GFP_KERNEL);
-	image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data;
-	if (!ioctlbuffer)
+	if (!ioctlbuffer) {
+		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
 		return -ENOMEM;
-	if (pm8001_ha->fw_image->size < 28) {
-		ret = FAIL_FILE_SIZE;
-		goto out;
 	}
-
+	image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data;
 	while (sizeRead < pm8001_ha->fw_image->size) {
 		partitionSizeTmp =
 			*(u32 *)((u8 *)&image_hdr->image_length + sizeRead);
 		partitionSize = be32_to_cpu(partitionSizeTmp);
-		loopcount = (partitionSize + HEADER_LEN)/IOCTL_BUF_SIZE;
-		if (loopcount % IOCTL_BUF_SIZE)
-			loopcount++;
-		if (loopcount == 0)
-			loopcount++;
+		loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN,
+					IOCTL_BUF_SIZE);
 		for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
 			payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
 			payload->length = 1024*16;
@@ -614,18 +618,18 @@ static int pm8001_update_flash(struct pm
 
 		pm8001_ha->nvmd_completion = &completion;
 		ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload);
+		if (ret) {
+			pm8001_ha->fw_status = FAIL_OUT_MEMORY;
+			goto out;
+		}
 		wait_for_completion(&completion);
-		if (ret || (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS)) {
-			ret = fwControl->retcode;
-			kfree(ioctlbuffer);
-			ioctlbuffer = NULL;
-			break;
+		if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) {
+			pm8001_ha->fw_status = fwControl->retcode;
+			ret = -EFAULT;
+			goto out;
+		}
 		}
 	}
-	if (ret)
-		break;
-	partitionNumber++;
-}
 out:
 	kfree(ioctlbuffer);
 	return ret;
@@ -640,22 +644,29 @@ static ssize_t pm8001_store_update_fw(st
 	char *cmd_ptr, *filename_ptr;
 	int res, i;
 	int flash_command = FLASH_CMD_NONE;
-	int err = 0;
+	int ret;
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	cmd_ptr = kzalloc(count*2, GFP_KERNEL);
+	/* this test protects us from running two flash processes at once,
+	 * so we should start with this test */
+	if (pm8001_ha->fw_status == FLASH_IN_PROGRESS)
+		return -EINPROGRESS;
+	pm8001_ha->fw_status = FLASH_IN_PROGRESS;
 
+	cmd_ptr = kzalloc(count*2, GFP_KERNEL);
 	if (!cmd_ptr) {
-		err = FAIL_OUT_MEMORY;
-		goto out;
+		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
+		return -ENOMEM;
 	}
 
 	filename_ptr = cmd_ptr + count;
 	res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr);
 	if (res != 2) {
-		err = FAIL_PARAMETERS;
-		goto out1;
+		pm8001_ha->fw_status = FAIL_PARAMETERS;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) {
@@ -666,50 +677,38 @@ static ssize_t pm8001_store_update_fw(st
 		}
 	}
 	if (flash_command == FLASH_CMD_NONE) {
-		err = FAIL_PARAMETERS;
-		goto out1;
+		pm8001_ha->fw_status = FAIL_PARAMETERS;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) {
-		err = FLASH_IN_PROGRESS;
-		goto out1;
-	}
-	err = request_firmware(&pm8001_ha->fw_image,
+	ret = request_firmware(&pm8001_ha->fw_image,
 			       filename_ptr,
 			       pm8001_ha->dev);
 
-	if (err) {
+	if (ret) {
 		PM8001_FAIL_DBG(pm8001_ha,
-			pm8001_printk("Failed to load firmware image file %s,"
-			" error %d\n", filename_ptr, err));
-		err = FAIL_OPEN_BIOS_FILE;
-		goto out1;
+			pm8001_printk(
+			"Failed to load firmware image file %s,	error %d\n",
+			filename_ptr, ret));
+		pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
+		goto out;
 	}
 
-	switch (flash_command) {
-	case FLASH_CMD_UPDATE:
-		pm8001_ha->fw_status = FLASH_IN_PROGRESS;
-		err = pm8001_update_flash(pm8001_ha);
-		break;
-	case FLASH_CMD_SET_NVMD:
-		pm8001_ha->fw_status = FLASH_IN_PROGRESS;
-		err = pm8001_set_nvmd(pm8001_ha);
-		break;
-	default:
-		pm8001_ha->fw_status = FAIL_PARAMETERS;
-		err = FAIL_PARAMETERS;
-		break;
-	}
+	if (FLASH_CMD_UPDATE == flash_command)
+		ret = pm8001_update_flash(pm8001_ha);
+	else
+		ret = pm8001_set_nvmd(pm8001_ha);
+
 	release_firmware(pm8001_ha->fw_image);
-out1:
-	kfree(cmd_ptr);
 out:
-	pm8001_ha->fw_status = err;
+	kfree(cmd_ptr);
 
-	if (!err)
-		return count;
-	else
-		return -err;
+	if (ret)
+		return ret;
+
+	pm8001_ha->fw_status = FLASH_OK;
+	return count;
 }
 
 static ssize_t pm8001_show_update_fw(struct device *cdev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_hwi.c linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_hwi.c
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_hwi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_hwi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1346,7 +1346,7 @@ int pm8001_mpi_build_cmd(struct pm8001_h
 		&pMessage) < 0) {
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("No free mpi buffer\n"));
-		return -1;
+		return -ENOMEM;
 	}
 	BUG_ON(!payload);
 	/*Copy to the payload*/
@@ -1751,6 +1751,8 @@ static void pm8001_send_abort_all(struct
 	task_abort.tag = cpu_to_le32(ccb_tag);
 
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+	if (ret)
+		pm8001_tag_free(pm8001_ha, ccb_tag);
 
 }
 
@@ -1778,6 +1780,7 @@ static void pm8001_send_read_log(struct
 
 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
 	if (res) {
+		sas_free_task(task);
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("cannot allocate tag !!!\n"));
 		return;
@@ -1788,14 +1791,14 @@ static void pm8001_send_read_log(struct
 	*/
 	dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
 	if (!dev) {
+		sas_free_task(task);
+		pm8001_tag_free(pm8001_ha, ccb_tag);
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("Domain device cannot be allocated\n"));
-		sas_free_task(task);
 		return;
-	} else {
-		task->dev = dev;
-		task->dev->lldd_dev = pm8001_ha_dev;
 	}
+	task->dev = dev;
+	task->dev->lldd_dev = pm8001_ha_dev;
 
 	ccb = &pm8001_ha->ccb_info[ccb_tag];
 	ccb->device = pm8001_ha_dev;
@@ -1821,7 +1824,11 @@ static void pm8001_send_read_log(struct
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
 	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
-
+	if (res) {
+		sas_free_task(task);
+		pm8001_tag_free(pm8001_ha, ccb_tag);
+		kfree(dev);
+	}
 }
 
 /**
@@ -3100,7 +3107,7 @@ void pm8001_mpi_set_dev_state_resp(struc
 	complete(pm8001_dev->setds_completion);
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
-	pm8001_ccb_free(pm8001_ha, tag);
+	pm8001_tag_free(pm8001_ha, tag);
 }
 
 void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3119,13 +3126,12 @@ void pm8001_mpi_set_nvmd_resp(struct pm8
 	}
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
-	pm8001_ccb_free(pm8001_ha, tag);
+	pm8001_tag_free(pm8001_ha, tag);
 }
 
 void
 pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
-	struct fw_control_ex	*fw_control_context;
 	struct get_nvm_data_resp *pPayload =
 		(struct get_nvm_data_resp *)(piomb + 4);
 	u32 tag = le32_to_cpu(pPayload->tag);
@@ -3134,7 +3140,6 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_h
 	u32 ir_tds_bn_dps_das_nvm =
 		le32_to_cpu(pPayload->ir_tda_bn_dps_das_nvm);
 	void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr;
-	fw_control_context = ccb->fw_control_context;
 
 	PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n"));
 	if ((dlen_status & NVMD_STAT) != 0) {
@@ -3175,13 +3180,11 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_h
 			pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n",
 			(dlen_status & NVMD_LEN) >> 24));
 	}
-	memcpy(fw_control_context->usrAddr,
-		pm8001_ha->memoryMap.region[NVMD].virt_ptr,
-		fw_control_context->len);
-	complete(pm8001_ha->nvmd_completion);
+	kfree(ccb->fw_control_context);
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
-	pm8001_ccb_free(pm8001_ha, tag);
+	pm8001_tag_free(pm8001_ha, tag);
+	complete(pm8001_ha->nvmd_completion);
 }
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3588,7 +3591,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hb
 	complete(pm8001_dev->dcompletion);
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
-	pm8001_ccb_free(pm8001_ha, htag);
+	pm8001_tag_free(pm8001_ha, htag);
 	return 0;
 }
 
@@ -3617,15 +3620,11 @@ int pm8001_mpi_fw_flash_update_resp(stru
 		void *piomb)
 {
 	u32 status;
-	struct fw_control_ex	fw_control_context;
 	struct fw_flash_Update_resp *ppayload =
 		(struct fw_flash_Update_resp *)(piomb + 4);
 	u32 tag = le32_to_cpu(ppayload->tag);
 	struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
 	status = le32_to_cpu(ppayload->status);
-	memcpy(&fw_control_context,
-		ccb->fw_control_context,
-		sizeof(fw_control_context));
 	switch (status) {
 	case FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
 		PM8001_MSG_DBG(pm8001_ha,
@@ -3668,11 +3667,11 @@ int pm8001_mpi_fw_flash_update_resp(stru
 			pm8001_printk("No matched status = %d\n", status));
 		break;
 	}
-	ccb->fw_control_context->fw_control->retcode = status;
-	complete(pm8001_ha->nvmd_completion);
+	kfree(ccb->fw_control_context);
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
-	pm8001_ccb_free(pm8001_ha, tag);
+	pm8001_tag_free(pm8001_ha, tag);
+	complete(pm8001_ha->nvmd_completion);
 	return 0;
 }
 
@@ -4257,7 +4256,11 @@ static int pm8001_chip_smp_req(struct pm
 	smp_cmd.long_smp_req.long_resp_size =
 		cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+					(u32 *)&smp_cmd, 0);
+	if (rc)
+		goto err_out_2;
+
 	return 0;
 
 err_out_2:
@@ -4398,7 +4401,7 @@ static int pm8001_chip_sata_req(struct p
 
 	/* Check for read log for failed drive and return */
 	if (sata_cmd.sata_fis.command == 0x2f) {
-		if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+		if (((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
 			(pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
 			(pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
 			struct task_status_struct *ts;
@@ -4789,6 +4792,10 @@ int pm8001_chip_get_nvmd_req(struct pm80
 		break;
 	}
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+	if (rc) {
+		kfree(fw_control_context);
+		pm8001_tag_free(pm8001_ha, tag);
+	}
 	return rc;
 }
 
@@ -4817,7 +4824,7 @@ int pm8001_chip_set_nvmd_req(struct pm80
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc) {
 		kfree(fw_control_context);
-		return rc;
+		return -EBUSY;
 	}
 	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->fw_control_context = fw_control_context;
@@ -4869,6 +4876,10 @@ int pm8001_chip_set_nvmd_req(struct pm80
 		break;
 	}
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+	if (rc) {
+		kfree(fw_control_context);
+		pm8001_tag_free(pm8001_ha, tag);
+	}
 	return rc;
 }
 
@@ -4935,7 +4946,7 @@ pm8001_chip_fw_flash_update_req(struct p
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc) {
 		kfree(fw_control_context);
-		return rc;
+		return -EBUSY;
 	}
 	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->fw_control_context = fw_control_context;
@@ -5061,7 +5072,7 @@ pm8001_chip_sas_re_initialization(struct
 	memset(&payload, 0, sizeof(payload));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc)
-		return -1;
+		return -ENOMEM;
 	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->ccb_tag = tag;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -5070,6 +5081,8 @@ pm8001_chip_sas_re_initialization(struct
 	payload.sata_hol_tmo = cpu_to_le32(80);
 	payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 	return rc;
 
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_init.c
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hb
 {
 	int i;
 	spin_lock_init(&pm8001_ha->lock);
+	spin_lock_init(&pm8001_ha->bitmap_lock);
 	PM8001_INIT_DBG(pm8001_ha,
 		pm8001_printk("pm8001_alloc: PHY:%x\n",
 				pm8001_ha->chip->n_phy));
@@ -621,6 +622,8 @@ static void pm8001_init_sas_add(struct p
 	DECLARE_COMPLETION_ONSTACK(completion);
 	struct pm8001_ioctl_payload payload;
 	u16 deviceid;
+	int rc;
+
 	pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
 	pm8001_ha->nvmd_completion = &completion;
 
@@ -638,7 +641,16 @@ static void pm8001_init_sas_add(struct p
 	}
 	payload.offset = 0;
 	payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
-	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+	if (!payload.func_specific) {
+		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n"));
+		return;
+	}
+	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+	if (rc) {
+		kfree(payload.func_specific);
+		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+		return;
+	}
 	wait_for_completion(&completion);
 
 	for (i = 0, j = 0; i <= 7; i++, j++) {
@@ -661,6 +673,7 @@ static void pm8001_init_sas_add(struct p
 			pm8001_printk("phy %d sas_addr = %016llx\n", i,
 			pm8001_ha->phy[i].dev_sas_addr));
 	}
+	kfree(payload.func_specific);
 #else
 	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
 		pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL;
@@ -684,6 +697,7 @@ static int pm8001_get_phy_settings_info(
 	/*OPTION ROM FLASH read for the SPC cards */
 	DECLARE_COMPLETION_ONSTACK(completion);
 	struct pm8001_ioctl_payload payload;
+	int rc;
 
 	pm8001_ha->nvmd_completion = &completion;
 	/* SAS ADDRESS read from flash / EEPROM */
@@ -694,7 +708,12 @@ static int pm8001_get_phy_settings_info(
 	if (!payload.func_specific)
 		return -ENOMEM;
 	/* Read phy setting values from flash */
-	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+	rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
+	if (rc) {
+		kfree(payload.func_specific);
+		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+		return -ENOMEM;
+	}
 	wait_for_completion(&completion);
 	pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);
 	kfree(payload.func_specific);
@@ -729,33 +748,35 @@ static u32 pm8001_setup_msix(struct pm80
 		sizeof(pm8001_ha->msix_entries[0]);
 	for (i = 0; i < max_entry ; i++)
 		pm8001_ha->msix_entries[i].entry = i;
-	rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries,
+	rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries,
 		number_of_intr);
 	pm8001_ha->number_of_intr = number_of_intr;
-	if (!rc) {
-		PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
-			"pci_enable_msix request ret:%d no of intr %d\n",
-					rc, pm8001_ha->number_of_intr));
+	if (rc)
+		return rc;
 
+	PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+		"pci_enable_msix_exact request ret:%d no of intr %d\n",
+				rc, pm8001_ha->number_of_intr));
 
-		for (i = 0; i < number_of_intr; i++) {
-			snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
-					DRV_NAME"%d", i);
-			pm8001_ha->irq_vector[i].irq_id = i;
-			pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
+	for (i = 0; i < number_of_intr; i++) {
+		snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
+				DRV_NAME"%d", i);
+		pm8001_ha->irq_vector[i].irq_id = i;
+		pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
 
-			if (request_irq(pm8001_ha->msix_entries[i].vector,
-				pm8001_interrupt_handler_msix, flag,
-				intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
-				for (j = 0; j < i; j++)
-					free_irq(
-					pm8001_ha->msix_entries[j].vector,
+		rc = request_irq(pm8001_ha->msix_entries[i].vector,
+			pm8001_interrupt_handler_msix, flag,
+			intr_drvname[i], &(pm8001_ha->irq_vector[i]));
+		if (rc) {
+			for (j = 0; j < i; j++) {
+				free_irq(pm8001_ha->msix_entries[j].vector,
 					&(pm8001_ha->irq_vector[i]));
-				pci_disable_msix(pm8001_ha->pdev);
-				break;
 			}
+			pci_disable_msix(pm8001_ha->pdev);
+			break;
 		}
 	}
+
 	return rc;
 }
 #endif
@@ -964,6 +985,7 @@ static int pm8001_pci_suspend(struct pci
 	int  i, j;
 	u32 device_state;
 	pm8001_ha = sha->lldd_ha;
+	sas_suspend_ha(sha);
 	flush_workqueue(pm8001_wq);
 	scsi_block_requests(pm8001_ha->shost);
 	if (!pdev->pm_cap) {
@@ -1013,6 +1035,7 @@ static int pm8001_pci_resume(struct pci_
 	int rc;
 	u8 i = 0, j;
 	u32 device_state;
+	DECLARE_COMPLETION_ONSTACK(completion);
 	pm8001_ha = sha->lldd_ha;
 	device_state = pdev->current_state;
 
@@ -1033,7 +1056,7 @@ static int pm8001_pci_resume(struct pci_
 	rc = pci_go_44(pdev);
 	if (rc)
 		goto err_out_disable;
-
+	sas_prep_resume_ha(sha);
 	/* chip soft rst only for spc */
 	if (pm8001_ha->chip_id == chip_8001) {
 		PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
@@ -1065,7 +1088,13 @@ static int pm8001_pci_resume(struct pci_
 		for (i = 1; i < pm8001_ha->number_of_intr; i++)
 			PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
 	}
-	scsi_unblock_requests(pm8001_ha->shost);
+	pm8001_ha->flags = PM8001F_RUN_TIME;
+	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+		pm8001_ha->phy[i].enable_completion = &completion;
+		PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
+		wait_for_completion(&completion);
+	}
+	sas_resume_ha(sha);
 	return 0;
 
 err_out_disable:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_sas.c linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_sas.c
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_sas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_sas.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,25 +58,14 @@ static int pm8001_find_tag(struct sas_ta
 }
 
 /**
-  * pm8001_tag_clear - clear the tags bitmap
+  * pm8001_tag_free - free the no more needed tag
   * @pm8001_ha: our hba struct
   * @tag: the found tag associated with the task
   */
-static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag)
-{
-	void *bitmap = pm8001_ha->tags;
-	clear_bit(tag, bitmap);
-}
-
 void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
 {
-	pm8001_tag_clear(pm8001_ha, tag);
-}
-
-static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag)
-{
 	void *bitmap = pm8001_ha->tags;
-	set_bit(tag, bitmap);
+	clear_bit(tag, bitmap);
 }
 
 /**
@@ -86,14 +75,18 @@ static void pm8001_tag_set(struct pm8001
   */
 inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
 {
-	unsigned int index, tag;
+	unsigned int tag;
 	void *bitmap = pm8001_ha->tags;
+	unsigned long flags;
 
-	index = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
-	tag = index;
-	if (tag >= pm8001_ha->tags_num)
+	spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags);
+	tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
+	if (tag >= pm8001_ha->tags_num) {
+		spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
 		return -SAS_QUEUE_FULL;
-	pm8001_tag_set(pm8001_ha, tag);
+	}
+	set_bit(tag, bitmap);
+	spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
 	*tag_out = tag;
 	return 0;
 }
@@ -102,7 +95,7 @@ void pm8001_tag_init(struct pm8001_hba_i
 {
 	int i;
 	for (i = 0; i < pm8001_ha->tags_num; ++i)
-		pm8001_tag_clear(pm8001_ha, i);
+		pm8001_tag_free(pm8001_ha, i);
 }
 
  /**
@@ -123,13 +116,12 @@ int pm8001_mem_alloc(struct pci_dev *pde
 	u64 align_offset = 0;
 	if (align)
 		align_offset = (dma_addr_t)align - 1;
-	mem_virt_alloc =
-		pci_alloc_consistent(pdev, mem_size + align, &mem_dma_handle);
+	mem_virt_alloc = pci_zalloc_consistent(pdev, mem_size + align,
+					       &mem_dma_handle);
 	if (!mem_virt_alloc) {
 		pm8001_printk("memory allocation error\n");
 		return -1;
 	}
-	memset((void *)mem_virt_alloc, 0, mem_size+align);
 	*pphys_addr = mem_dma_handle;
 	phys_align = (*pphys_addr + align_offset) & ~align_offset;
 	*virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr;
@@ -501,11 +493,6 @@ int pm8001_queue_command(struct sas_task
 	return pm8001_task_exec(task, num, gfp_flags, 0, NULL);
 }
 
-void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx)
-{
-	pm8001_tag_clear(pm8001_ha, ccb_idx);
-}
-
 /**
   * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb.
   * @pm8001_ha: our hba card information
@@ -542,7 +529,7 @@ void pm8001_ccb_task_free(struct pm8001_
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
 	ccb->open_retry = 0;
-	pm8001_ccb_free(pm8001_ha, ccb_idx);
+	pm8001_tag_free(pm8001_ha, ccb_idx);
 }
 
  /**
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_sas.h linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_sas.h
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm8001_sas.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm8001_sas.h	2014-09-28 17:29:07.000000000 -0400
@@ -475,6 +475,7 @@ struct pm8001_hba_info {
 	struct list_head	list;
 	unsigned long		flags;
 	spinlock_t		lock;/* host-wide lock */
+	spinlock_t		bitmap_lock;
 	struct pci_dev		*pdev;/* our device */
 	struct device		*dev;
 	struct pm8001_hba_memspace io_mem[6];
@@ -616,7 +617,6 @@ extern struct workqueue_struct *pm8001_w
 int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out);
 void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha);
 u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag);
-void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx);
 void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
 	struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx);
 int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pm8001/pm80xx_hwi.c linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm80xx_hwi.c
--- linux-libre-3.16-gnu/drivers/scsi/pm8001/pm80xx_hwi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pm8001/pm80xx_hwi.c	2014-09-28 17:29:07.000000000 -0400
@@ -856,6 +856,8 @@ pm80xx_set_thermal_config(struct pm8001_
 	payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
 
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 	return rc;
 
 }
@@ -936,6 +938,8 @@ pm80xx_set_sas_protocol_timer_config(str
 			 sizeof(SASProtocolTimerConfig_t));
 
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 
 	return rc;
 }
@@ -948,7 +952,7 @@ static int
 pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
 {
 	u32 scratch3_value;
-	int ret;
+	int ret = -1;
 
 	/* Read encryption status from SCRATCH PAD 3 */
 	scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
@@ -982,7 +986,7 @@ pm80xx_get_encrypt_info(struct pm8001_hb
 		pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
 		pm8001_ha->encrypt_info.cipher_mode = 0;
 		pm8001_ha->encrypt_info.sec_mode = 0;
-		return 0;
+		ret = 0;
 	} else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
 				SCRATCH_PAD3_ENC_DIS_ERR) {
 		pm8001_ha->encrypt_info.status =
@@ -1004,7 +1008,6 @@ pm80xx_get_encrypt_info(struct pm8001_hb
 			scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
 			pm8001_ha->encrypt_info.sec_mode,
 			pm8001_ha->encrypt_info.status));
-		ret = -1;
 	} else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
 				 SCRATCH_PAD3_ENC_ENA_ERR) {
 
@@ -1028,7 +1031,6 @@ pm80xx_get_encrypt_info(struct pm8001_hb
 			scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
 			pm8001_ha->encrypt_info.sec_mode,
 			pm8001_ha->encrypt_info.status));
-		ret = -1;
 	}
 	return ret;
 }
@@ -1059,6 +1061,8 @@ static int pm80xx_encrypt_update(struct
 					KEK_MGMT_SUBOP_KEYCARDUPDATE);
 
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 
 	return rc;
 }
@@ -1383,8 +1387,10 @@ static void pm80xx_send_abort_all(struct
 	task->task_done = pm8001_task_done;
 
 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res)
+	if (res) {
+		sas_free_task(task);
 		return;
+	}
 
 	ccb = &pm8001_ha->ccb_info[ccb_tag];
 	ccb->device = pm8001_ha_dev;
@@ -1399,7 +1405,10 @@ static void pm80xx_send_abort_all(struct
 	task_abort.tag = cpu_to_le32(ccb_tag);
 
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
-
+	if (ret) {
+		sas_free_task(task);
+		pm8001_tag_free(pm8001_ha, ccb_tag);
+	}
 }
 
 static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
@@ -1426,6 +1435,7 @@ static void pm80xx_send_read_log(struct
 
 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
 	if (res) {
+		sas_free_task(task);
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("cannot allocate tag !!!\n"));
 		return;
@@ -1436,15 +1446,16 @@ static void pm80xx_send_read_log(struct
 	*/
 	dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
 	if (!dev) {
+		sas_free_task(task);
+		pm8001_tag_free(pm8001_ha, ccb_tag);
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("Domain device cannot be allocated\n"));
-		sas_free_task(task);
 		return;
-	} else {
-		task->dev = dev;
-		task->dev->lldd_dev = pm8001_ha_dev;
 	}
 
+	task->dev = dev;
+	task->dev->lldd_dev = pm8001_ha_dev;
+
 	ccb = &pm8001_ha->ccb_info[ccb_tag];
 	ccb->device = pm8001_ha_dev;
 	ccb->ccb_tag = ccb_tag;
@@ -1469,7 +1480,11 @@ static void pm80xx_send_read_log(struct
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
 	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
-
+	if (res) {
+		sas_free_task(task);
+		pm8001_tag_free(pm8001_ha, ccb_tag);
+		kfree(dev);
+	}
 }
 
 /**
@@ -3815,7 +3830,10 @@ static int pm80xx_chip_smp_req(struct pm
 
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
 				&smp_cmd, pm8001_ha->smp_exp_mode, length);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+					(u32 *)&smp_cmd, 0);
+	if (rc)
+		goto err_out_2;
 	return 0;
 
 err_out_2:
@@ -4406,6 +4424,8 @@ static int pm80xx_chip_reg_dev_req(struc
 		SAS_ADDR_SIZE);
 
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 
 	return rc;
 }
@@ -4484,7 +4504,9 @@ void mpi_set_phy_profile_req(struct pm80
 		payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
 		j++;
 	}
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
 }
 
 void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/pmcraid.c linux-libre-3.17-rc7-gnu/drivers/scsi/pmcraid.c
--- linux-libre-3.16-gnu/drivers/scsi/pmcraid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/pmcraid.c	2014-09-28 17:29:07.000000000 -0400
@@ -237,7 +237,7 @@ static int pmcraid_slave_configure(struc
 		     scsi_dev->host->unique_id,
 		     scsi_dev->channel,
 		     scsi_dev->id,
-		     scsi_dev->lun);
+		     (u8)scsi_dev->lun);
 
 	if (RES_IS_GSCSI(res->cfg_entry)) {
 		scsi_dev->allow_restart = 1;
@@ -4213,9 +4213,9 @@ static ssize_t pmcraid_store_log_level(
 {
 	struct Scsi_Host *shost;
 	struct pmcraid_instance *pinstance;
-	unsigned long val;
+	u8 val;
 
-	if (strict_strtoul(buf, 10, &val))
+	if (kstrtou8(buf, 10, &val))
 		return -EINVAL;
 	/* log-level should be from 0 to 2 */
 	if (val > 2)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ps3rom.c linux-libre-3.17-rc7-gnu/drivers/scsi/ps3rom.c
--- linux-libre-3.16-gnu/drivers/scsi/ps3rom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ps3rom.c	2014-09-28 17:29:07.000000000 -0400
@@ -78,7 +78,7 @@ static int ps3rom_slave_configure(struct
 	struct ps3rom_private *priv = shost_priv(scsi_dev->host);
 	struct ps3_storage_device *dev = priv->dev;
 
-	dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__,
+	dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %llu, channel %u\n", __func__,
 		__LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/Kconfig linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/Kconfig
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/Kconfig	2014-08-07 04:59:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/Kconfig	2014-09-28 21:42:22.000000000 -0400
@@ -1,7 +1,7 @@
 config SCSI_QLA_FC
 	tristate "QLogic QLA2XXX Fibre Channel Support"
 	depends on PCI && SCSI
-	select SCSI_FC_ATTRS
+	depends on SCSI_FC_ATTRS
 	select FW_LOADER
 	---help---
 	This qla2xxx driver supports all QLogic Fibre Channel
@@ -10,7 +10,7 @@ config SCSI_QLA_FC
 	/*(DEBLOBBED)*/
 	tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs"
 	depends on SCSI_QLA_FC && TARGET_CORE
-	select LIBFC
+	depends on LIBFC
 	select BTREE
 	default n
 	---help---
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_def.h linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_def.h
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_def.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_def.h	2014-09-28 17:29:07.000000000 -0400
@@ -320,8 +320,8 @@ struct srb_iocb {
 			 * defined in tsk_mgmt_entry struct
 			 * for control_flags field in qla_fw.h.
 			 */
+			uint64_t lun;
 			uint32_t flags;
-			uint32_t lun;
 			uint32_t data;
 			struct completion comp;
 			__le16 comp_status;
@@ -2529,8 +2529,8 @@ struct isp_operations {
 	void (*disable_intrs) (struct qla_hw_data *);
 
 	int (*abort_command) (srb_t *);
-	int (*target_reset) (struct fc_port *, unsigned int, int);
-	int (*lun_reset) (struct fc_port *, unsigned int, int);
+	int (*target_reset) (struct fc_port *, uint64_t, int);
+	int (*lun_reset) (struct fc_port *, uint64_t, int);
 	int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
 		uint8_t, uint8_t, uint16_t *, uint8_t);
 	int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_gbl.h linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_gbl.h
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_gbl.h	2014-08-07 04:59:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_gbl.h	2014-09-28 21:42:22.000000000 -0400
@@ -113,7 +113,7 @@ extern int ql2xenabledif;
 extern int ql2xenablehba_err_chk;
 extern int ql2xtargetreset;
 extern int ql2xdontresethba;
-extern unsigned int ql2xmaxlun;
+extern uint64_t ql2xmaxlun;
 extern int ql2xmdcapmask;
 extern int ql2xmdenable;
 
@@ -212,7 +212,7 @@ extern void qla2x00_build_scsi_iocbs_64(
 extern int qla2x00_start_scsi(srb_t *sp);
 extern int qla24xx_start_scsi(srb_t *sp);
 int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
-						uint16_t, uint16_t, uint8_t);
+						uint16_t, uint64_t, uint8_t);
 extern int qla2x00_start_sp(srb_t *);
 extern int qla24xx_dif_start_scsi(srb_t *);
 extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
@@ -262,10 +262,10 @@ extern int
 qla2x00_abort_command(srb_t *);
 
 extern int
-qla2x00_abort_target(struct fc_port *, unsigned int, int);
+qla2x00_abort_target(struct fc_port *, uint64_t, int);
 
 extern int
-qla2x00_lun_reset(struct fc_port *, unsigned int, int);
+qla2x00_lun_reset(struct fc_port *, uint64_t, int);
 
 extern int
 qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
@@ -339,12 +339,12 @@ qla24xx_get_isp_stats(scsi_qla_host_t *,
 extern int qla24xx_abort_command(srb_t *);
 extern int qla24xx_async_abort_command(srb_t *);
 extern int
-qla24xx_abort_target(struct fc_port *, unsigned int, int);
+qla24xx_abort_target(struct fc_port *, uint64_t, int);
 extern int
-qla24xx_lun_reset(struct fc_port *, unsigned int, int);
+qla24xx_lun_reset(struct fc_port *, uint64_t, int);
 extern int
 qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *, unsigned int,
-	unsigned int, enum nexus_wait_type);
+	uint64_t, enum nexus_wait_type);
 extern int
 qla2x00_system_error(scsi_qla_host_t *);
 
@@ -617,8 +617,8 @@ extern char *qlafx00_fw_version_str(stru
 extern irqreturn_t qlafx00_intr_handler(int, void *);
 extern void qlafx00_enable_intrs(struct qla_hw_data *);
 extern void qlafx00_disable_intrs(struct qla_hw_data *);
-extern int qlafx00_abort_target(fc_port_t *, unsigned int, int);
-extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int);
+extern int qlafx00_abort_target(fc_port_t *, uint64_t, int);
+extern int qlafx00_lun_reset(fc_port_t *, uint64_t, int);
 extern int qlafx00_start_scsi(srb_t *);
 extern int qlafx00_abort_isp(scsi_qla_host_t *);
 extern int qlafx00_iospace_config(struct qla_hw_data *);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_init.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_init.c	2014-08-07 04:59:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_init.c	2014-09-28 21:42:22.000000000 -0400
@@ -1526,8 +1526,8 @@ try_fce:
 			    FCE_SIZE, ha->fce, ha->fce_dma);
 
 		/* Allocate memory for Fibre Channel Event Buffer. */
-		tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
-		    GFP_KERNEL);
+		tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+					 GFP_KERNEL);
 		if (!tc) {
 			ql_log(ql_log_warn, vha, 0x00be,
 			    "Unable to allocate (%d KB) for FCE.\n",
@@ -1535,7 +1535,6 @@ try_fce:
 			goto try_eft;
 		}
 
-		memset(tc, 0, FCE_SIZE);
 		rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
 		    ha->fce_mb, &ha->fce_bufs);
 		if (rval) {
@@ -1560,8 +1559,8 @@ try_eft:
 			    EFT_SIZE, ha->eft, ha->eft_dma);
 
 		/* Allocate memory for Extended Trace Buffer. */
-		tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-		    GFP_KERNEL);
+		tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+					 GFP_KERNEL);
 		if (!tc) {
 			ql_log(ql_log_warn, vha, 0x00c1,
 			    "Unable to allocate (%d KB) for EFT.\n",
@@ -1569,7 +1568,6 @@ try_eft:
 			goto cont_alloc;
 		}
 
-		memset(tc, 0, EFT_SIZE);
 		rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
 		if (rval) {
 			ql_log(ql_log_warn, vha, 0x00c2,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_iocb.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_iocb.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_iocb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_iocb.c	2014-09-28 17:29:07.000000000 -0400
@@ -520,7 +520,7 @@ qla2x00_start_iocbs(struct scsi_qla_host
 static int
 __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
 			struct rsp_que *rsp, uint16_t loop_id,
-			uint16_t lun, uint8_t type)
+			uint64_t lun, uint8_t type)
 {
 	mrk_entry_t *mrk;
 	struct mrk_entry_24xx *mrk24 = NULL;
@@ -543,14 +543,13 @@ __qla2x00_marker(struct scsi_qla_host *v
 		if (IS_FWI2_CAPABLE(ha)) {
 			mrk24 = (struct mrk_entry_24xx *) mrk;
 			mrk24->nport_handle = cpu_to_le16(loop_id);
-			mrk24->lun[1] = LSB(lun);
-			mrk24->lun[2] = MSB(lun);
+			int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
 			host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
 			mrk24->vp_index = vha->vp_idx;
 			mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle);
 		} else {
 			SET_TARGET_ID(ha, mrk->target, loop_id);
-			mrk->lun = cpu_to_le16(lun);
+			mrk->lun = cpu_to_le16((uint16_t)lun);
 		}
 	}
 	wmb();
@@ -562,7 +561,7 @@ __qla2x00_marker(struct scsi_qla_host *v
 
 int
 qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
-		struct rsp_que *rsp, uint16_t loop_id, uint16_t lun,
+		struct rsp_que *rsp, uint16_t loop_id, uint64_t lun,
 		uint8_t type)
 {
 	int ret;
@@ -2047,7 +2046,7 @@ static void
 qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
 {
 	uint32_t flags;
-	unsigned int lun;
+	uint64_t lun;
 	struct fc_port *fcport = sp->fcport;
 	scsi_qla_host_t *vha = fcport->vha;
 	struct qla_hw_data *ha = vha->hw;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_isr.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_isr.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_isr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_isr.c	2014-09-28 17:29:07.000000000 -0400
@@ -1659,7 +1659,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t
 
 	if (sense_len) {
 		ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c,
-		    "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n",
+		    "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
 		    sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
 		    cp);
 		ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
@@ -2281,7 +2281,7 @@ check_scsi_status:
 out:
 	if (logit)
 		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
-		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d "
+		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
 		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
 		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n",
 		    comp_status, scsi_status, res, vha->host_no,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_mbx.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_mbx.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_mbx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_mbx.c	2014-09-28 17:29:07.000000000 -0400
@@ -947,7 +947,7 @@ qla2x00_abort_command(srb_t *sp)
 }
 
 int
-qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
+qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag)
 {
 	int rval, rval2;
 	mbx_cmd_t  mc;
@@ -1000,7 +1000,7 @@ qla2x00_abort_target(struct fc_port *fcp
 }
 
 int
-qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
+qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
 {
 	int rval, rval2;
 	mbx_cmd_t  mc;
@@ -1022,7 +1022,7 @@ qla2x00_lun_reset(struct fc_port *fcport
 		mcp->mb[1] = fcport->loop_id;
 	else
 		mcp->mb[1] = fcport->loop_id << 8;
-	mcp->mb[2] = l;
+	mcp->mb[2] = (u32)l;
 	mcp->mb[3] = 0;
 	mcp->mb[9] = vha->vp_idx;
 
@@ -2666,7 +2666,7 @@ struct tsk_mgmt_cmd {
 
 static int
 __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
-    unsigned int l, int tag)
+    uint64_t l, int tag)
 {
 	int		rval, rval2;
 	struct tsk_mgmt_cmd *tsk;
@@ -2760,7 +2760,7 @@ __qla24xx_issue_tmf(char *name, uint32_t
 }
 
 int
-qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
+qla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag)
 {
 	struct qla_hw_data *ha = fcport->vha->hw;
 
@@ -2771,7 +2771,7 @@ qla24xx_abort_target(struct fc_port *fcp
 }
 
 int
-qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
+qla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
 {
 	struct qla_hw_data *ha = fcport->vha->hw;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_mr.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_mr.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_mr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_mr.c	2014-09-28 17:29:07.000000000 -0400
@@ -726,13 +726,13 @@ qlafx00_disable_intrs(struct qla_hw_data
 }
 
 int
-qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag)
+qlafx00_abort_target(fc_port_t *fcport, uint64_t l, int tag)
 {
 	return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
 }
 
 int
-qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag)
+qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag)
 {
 	return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
 }
@@ -2159,7 +2159,7 @@ qlafx00_handle_sense(srb_t *sp, uint8_t
 
 	if (sense_len) {
 		ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039,
-		    "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n",
+		    "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
 		    sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
 		    cp);
 		ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049,
@@ -2524,7 +2524,7 @@ check_scsi_status:
 
 	if (logit)
 		ql_dbg(ql_dbg_io, fcport->vha, 0x3058,
-		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d "
+		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
 		    "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x "
 		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sense_len=0x%x, "
 		    "par_sense_len=0x%x, rsp_info_len=0x%x\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_os.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_os.c
--- linux-libre-3.16-gnu/drivers/scsi/qla2xxx/qla_os.c	2014-08-07 04:59:45.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla2xxx/qla_os.c	2014-09-28 21:42:27.000000000 -0400
@@ -202,8 +202,8 @@ MODULE_PARM_DESC(ql2xdontresethba,
 		" 0 (Default) -- Reset on failure.\n"
 		" 1 -- Do not reset on failure.\n");
 
-uint ql2xmaxlun = MAX_LUNS;
-module_param(ql2xmaxlun, uint, S_IRUGO);
+uint64_t ql2xmaxlun = MAX_LUNS;
+module_param(ql2xmaxlun, ullong, S_IRUGO);
 MODULE_PARM_DESC(ql2xmaxlun,
 		"Defines the maximum LU number to register with the SCSI "
 		"midlayer. Default is 65535.");
@@ -920,7 +920,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	srb_t *sp;
 	int ret;
-	unsigned int id, lun;
+	unsigned int id;
+	uint64_t lun;
 	unsigned long flags;
 	int rval, wait = 0;
 	struct qla_hw_data *ha = vha->hw;
@@ -944,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	}
 
 	ql_dbg(ql_dbg_taskm, vha, 0x8002,
-	    "Aborting from RISC nexus=%ld:%d:%d sp=%p cmd=%p\n",
+	    "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p\n",
 	    vha->host_no, id, lun, sp, cmd);
 
 	/* Get a reference to the sp and drop the lock.*/
@@ -995,7 +996,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	}
 
 	ql_log(ql_log_info, vha, 0x801c,
-	    "Abort command issued nexus=%ld:%d:%d --  %d %x.\n",
+	    "Abort command issued nexus=%ld:%d:%llu --  %d %x.\n",
 	    vha->host_no, id, lun, wait, ret);
 
 	return ret;
@@ -1003,7 +1004,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
 int
 qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
-	unsigned int l, enum nexus_wait_type type)
+	uint64_t l, enum nexus_wait_type type)
 {
 	int cnt, match, status;
 	unsigned long flags;
@@ -1060,7 +1061,7 @@ static char *reset_errors[] = {
 
 static int
 __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
-    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
+    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, uint64_t, int))
 {
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -1075,7 +1076,7 @@ __qla2xxx_eh_generic_reset(char *name, e
 		return err;
 
 	ql_log(ql_log_info, vha, 0x8009,
-	    "%s RESET ISSUED nexus=%ld:%d:%d cmd=%p.\n", name, vha->host_no,
+	    "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no,
 	    cmd->device->id, cmd->device->lun, cmd);
 
 	err = 0;
@@ -1100,14 +1101,14 @@ __qla2xxx_eh_generic_reset(char *name, e
 	}
 
 	ql_log(ql_log_info, vha, 0x800e,
-	    "%s RESET SUCCEEDED nexus:%ld:%d:%d cmd=%p.\n", name,
+	    "%s RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n", name,
 	    vha->host_no, cmd->device->id, cmd->device->lun, cmd);
 
 	return SUCCESS;
 
 eh_reset_failed:
 	ql_log(ql_log_info, vha, 0x800f,
-	    "%s RESET FAILED: %s nexus=%ld:%d:%d cmd=%p.\n", name,
+	    "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name,
 	    reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
 	    cmd);
 	return FAILED;
@@ -1154,7 +1155,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *c
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
 	int ret = FAILED;
-	unsigned int id, lun;
+	unsigned int id;
+	uint64_t lun;
 
 	id = cmd->device->id;
 	lun = cmd->device->lun;
@@ -1169,7 +1171,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *c
 	ret = FAILED;
 
 	ql_log(ql_log_info, vha, 0x8012,
-	    "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun);
+	    "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun);
 
 	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
 		ql_log(ql_log_fatal, vha, 0x8013,
@@ -1193,7 +1195,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *c
 
 eh_bus_reset_done:
 	ql_log(ql_log_warn, vha, 0x802b,
-	    "BUS RESET %s nexus=%ld:%d:%d.\n",
+	    "BUS RESET %s nexus=%ld:%d:%llu.\n",
 	    (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun);
 
 	return ret;
@@ -1220,14 +1222,15 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	struct qla_hw_data *ha = vha->hw;
 	int ret = FAILED;
-	unsigned int id, lun;
+	unsigned int id;
+	uint64_t lun;
 	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
 	ql_log(ql_log_info, vha, 0x8018,
-	    "ADAPTER RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun);
+	    "ADAPTER RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun);
 
 	/*
 	 * No point in issuing another reset if one is active.  Also do not
@@ -1273,7 +1276,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *
 
 eh_host_reset_lock:
 	ql_log(ql_log_info, vha, 0x8017,
-	    "ADAPTER RESET %s nexus=%ld:%d:%d.\n",
+	    "ADAPTER RESET %s nexus=%ld:%d:%llu.\n",
 	    (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun);
 
 	return ret;
@@ -1409,7 +1412,7 @@ static void qla2x00_handle_queue_full(st
 		return;
 
 	ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
-	    "Queue depth adjusted-down to %d for nexus=%ld:%d:%d.\n",
+	    "Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n",
 	    sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
 }
 
@@ -1432,7 +1435,7 @@ static void qla2x00_adjust_sdev_qdepth_u
 		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
 
 	ql_dbg(ql_dbg_io, vha, 0x302a,
-	    "Queue depth adjusted-up to %d for nexus=%ld:%d:%d.\n",
+	    "Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n",
 	    sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
 }
 
@@ -2661,14 +2664,19 @@ qla2x00_probe_one(struct pci_dev *pdev,
 	else
 		host->max_cmd_len = MAX_CMDSZ;
 	host->max_channel = MAX_BUSES - 1;
-	host->max_lun = ql2xmaxlun;
+	/* Older HBAs support only 16-bit LUNs */
+	if (!IS_QLAFX00(ha) && !IS_FWI2_CAPABLE(ha) &&
+	    ql2xmaxlun > 0xffff)
+		host->max_lun = 0xffff;
+	else
+		host->max_lun = ql2xmaxlun;
 	host->transportt = qla2xxx_transport_template;
 	sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
 
 	ql_dbg(ql_dbg_init, base_vha, 0x0033,
 	    "max_id=%d this_id=%d "
 	    "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d "
-	    "max_lun=%d transportt=%p, vendor_id=%llu.\n", host->max_id,
+	    "max_lun=%llu transportt=%p, vendor_id=%llu.\n", host->max_id,
 	    host->this_id, host->cmd_per_lun, host->unique_id,
 	    host->max_cmd_len, host->max_channel, host->max_lun,
 	    host->transportt, sht->vendor_id);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_glbl.h linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_glbl.h
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_glbl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_glbl.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@ void qla4xxx_process_aen(struct scsi_qla
 int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha);
 int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
 int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry,
-		      int lun);
+		      uint64_t lun);
 int qla4xxx_reset_target(struct scsi_qla_host *ha,
 			 struct ddb_entry *ddb_entry);
 int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
@@ -76,7 +76,7 @@ int qla4xxx_process_ddb_changed(struct s
 		uint32_t state, uint32_t conn_error);
 void qla4xxx_dump_buffer(void *b, uint32_t size);
 int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
-	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
+	struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod);
 int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
 		      uint32_t offset, uint32_t length, uint32_t options);
 int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_init.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_init.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_init.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_init.c	2014-09-28 17:29:07.000000000 -0400
@@ -334,6 +334,12 @@ void qla4xxx_alloc_fw_dump(struct scsi_q
 	/* Allocate memory for saving the template */
 	md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size,
 				    &md_tmp_dma, GFP_KERNEL);
+	if (!md_tmp) {
+		ql4_printk(KERN_INFO, ha,
+			   "scsi%ld: Failed to allocate DMA memory\n",
+			   ha->host_no);
+		return;
+	}
 
 	/* Request template */
 	status =  qla4xxx_get_minidump_template(ha, md_tmp_dma);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_iocb.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_iocb.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_iocb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_iocb.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,7 +83,7 @@ static int qla4xxx_get_req_pkt(struct sc
  * This routine issues a marker IOCB.
  **/
 int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
-	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
+	struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod)
 {
 	struct qla4_marker_entry *marker_entry;
 	unsigned long flags = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_isr.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_isr.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_isr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_isr.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@ static void qla4xxx_copy_sense(struct sc
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	sense_len = le16_to_cpu(sts_entry->senseDataByteCnt);
 	if (sense_len == 0) {
-		DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: %s:"
+		DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%llu: %s:"
 				  " sense len 0\n", ha->host_no,
 				  cmd->device->channel, cmd->device->id,
 				  cmd->device->lun, __func__));
@@ -43,7 +43,7 @@ static void qla4xxx_copy_sense(struct sc
 	sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN);
 	memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len);
 
-	DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, "
+	DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: %s: sense key = %x, "
 		"ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no,
 		cmd->device->channel, cmd->device->id,
 		cmd->device->lun, __func__,
@@ -169,7 +169,7 @@ static void qla4xxx_status_entry(struct
 
 				cmd->result = DID_ERROR << 16;
 
-				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
+				DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: "
 					"Mid-layer Data underrun0, "
 					"xferlen = 0x%x, "
 					"residual = 0x%x\n", ha->host_no,
@@ -197,7 +197,7 @@ static void qla4xxx_status_entry(struct
 		break;
 
 	case SCS_RESET_OCCURRED:
-		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Device RESET occurred\n",
+		DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Device RESET occurred\n",
 			      ha->host_no, cmd->device->channel,
 			      cmd->device->id, cmd->device->lun, __func__));
 
@@ -205,7 +205,7 @@ static void qla4xxx_status_entry(struct
 		break;
 
 	case SCS_ABORTED:
-		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Abort occurred\n",
+		DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Abort occurred\n",
 			      ha->host_no, cmd->device->channel,
 			      cmd->device->id, cmd->device->lun, __func__));
 
@@ -213,7 +213,7 @@ static void qla4xxx_status_entry(struct
 		break;
 
 	case SCS_TIMEOUT:
-		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: Timeout\n",
+		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: Timeout\n",
 			      ha->host_no, cmd->device->channel,
 			      cmd->device->id, cmd->device->lun));
 
@@ -232,7 +232,7 @@ static void qla4xxx_status_entry(struct
 	case SCS_DATA_OVERRUN:
 		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
 		     (sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
-			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun\n",
+			DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Data overrun\n",
 				      ha->host_no,
 				      cmd->device->channel, cmd->device->id,
 				      cmd->device->lun, __func__));
@@ -259,7 +259,7 @@ static void qla4xxx_status_entry(struct
 			if (!scsi_status && (scsi_bufflen(cmd) - residual) <
 			    cmd->underflow) {
 				DEBUG2(ql4_printk(KERN_INFO, ha,
-						  "scsi%ld:%d:%d:%d: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n",
+						  "scsi%ld:%d:%d:%llu: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n",
 						   ha->host_no,
 						   cmd->device->channel,
 						   cmd->device->id,
@@ -291,7 +291,7 @@ static void qla4xxx_status_entry(struct
 			 */
 
 			DEBUG2(ql4_printk(KERN_INFO, ha,
-					  "scsi%ld:%d:%d:%d: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
+					  "scsi%ld:%d:%d:%llu: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
 					  ha->host_no,
 					  cmd->device->channel,
 					  cmd->device->id,
@@ -313,7 +313,7 @@ check_scsi_status:
 
 	case SCS_DEVICE_LOGGED_OUT:
 	case SCS_DEVICE_UNAVAILABLE:
-		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE "
+		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: SCS_DEVICE "
 		    "state: 0x%x\n", ha->host_no,
 		    cmd->device->channel, cmd->device->id,
 		    cmd->device->lun, sts_entry->completionStatus));
@@ -333,7 +333,7 @@ check_scsi_status:
 		 * SCSI Mid-Layer handles device queue full
 		 */
 		cmd->result = DID_OK << 16 | sts_entry->scsiStatus;
-		DEBUG2(printk("scsi%ld:%d:%d: %s: QUEUE FULL detected "
+		DEBUG2(printk("scsi%ld:%d:%llu: %s: QUEUE FULL detected "
 			      "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x,"
 			      " iResp=%02x\n", ha->host_no, cmd->device->id,
 			      cmd->device->lun, __func__,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_mbx.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_mbx.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_mbx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_mbx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1205,7 +1205,7 @@ int qla4xxx_abort_task(struct scsi_qla_h
 	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) {
 		status = QLA_ERROR;
 
-		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: "
+		DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: "
 		    "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n",
 		    ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0],
 		    mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4]));
@@ -1225,14 +1225,14 @@ int qla4xxx_abort_task(struct scsi_qla_h
  * are valid before calling this routine.
  **/
 int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
-		      int lun)
+		      uint64_t lun)
 {
 	uint32_t mbox_cmd[MBOX_REG_COUNT];
 	uint32_t mbox_sts[MBOX_REG_COUNT];
 	uint32_t scsi_lun[2];
 	int status = QLA_SUCCESS;
 
-	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
+	DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no,
 		      ddb_entry->fw_ddb_index, lun));
 
 	/*
@@ -1620,8 +1620,8 @@ int qla4xxx_get_chap(struct scsi_qla_hos
 		goto exit_get_chap;
 	}
 
-	strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
-	strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+	strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+	strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
 
 exit_get_chap:
@@ -1663,8 +1663,8 @@ int qla4xxx_set_chap(struct scsi_qla_hos
 	else
 		chap_table->flags |= BIT_7; /* local */
 	chap_table->secret_len = strlen(password);
-	strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
-	strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
+	strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1);
+	strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1);
 	chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
 
 	if (is_qla40XX(ha)) {
@@ -1742,8 +1742,8 @@ int qla4xxx_get_uni_chap_at_index(struct
 		goto exit_unlock_uni_chap;
 	}
 
-	strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
-	strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
+	strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
+	strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
 
 	rval = QLA_SUCCESS;
 
@@ -2295,7 +2295,7 @@ int qla4_8xxx_set_param(struct scsi_qla_
 	if (param == SET_DRVR_VERSION) {
 		mbox_cmd[1] = SET_DRVR_VERSION;
 		strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION,
-			MAX_DRVR_VER_LEN);
+			MAX_DRVR_VER_LEN - 1);
 	} else {
 		ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n",
 			   __func__, param);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_nx.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_nx.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_nx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_nx.c	2014-09-28 17:29:07.000000000 -0400
@@ -4221,7 +4221,7 @@ qla4_8xxx_enable_msix(struct scsi_qla_ho
 	for (i = 0; i < QLA_MSIX_ENTRIES; i++)
 		entries[i].entry = qla4_8xxx_msix_entries[i].entry;
 
-	ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
+	ret = pci_enable_msix_exact(ha->pdev, entries, ARRAY_SIZE(entries));
 	if (ret) {
 		ql4_printk(KERN_WARNING, ha,
 		    "MSI-X: Failed to enable support -- %d/%d\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_os.c linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_os.c
--- linux-libre-3.16-gnu/drivers/scsi/qla4xxx/ql4_os.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qla4xxx/ql4_os.c	2014-09-28 17:29:07.000000000 -0400
@@ -756,9 +756,9 @@ static int qla4xxx_get_chap_list(struct
 			continue;
 
 		chap_rec->chap_tbl_idx = i;
-		strncpy(chap_rec->username, chap_table->name,
+		strlcpy(chap_rec->username, chap_table->name,
 			ISCSI_CHAP_AUTH_NAME_MAX_LEN);
-		strncpy(chap_rec->password, chap_table->secret,
+		strlcpy(chap_rec->password, chap_table->secret,
 			QL4_CHAP_MAX_SECRET_LEN);
 		chap_rec->password_length = chap_table->secret_len;
 
@@ -1050,6 +1050,7 @@ static int qla4xxx_get_host_stats(struct
 	if (!ql_iscsi_stats) {
 		ql4_printk(KERN_ERR, ha,
 			   "Unable to allocate memory for iscsi stats\n");
+		ret = -ENOMEM;
 		goto exit_host_stats;
 	}
 
@@ -1058,6 +1059,7 @@ static int qla4xxx_get_host_stats(struct
 	if (ret != QLA_SUCCESS) {
 		ql4_printk(KERN_ERR, ha,
 			   "Unable to retrieve iscsi stats\n");
+		ret = -EIO;
 		goto exit_host_stats;
 	}
 	host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames);
@@ -6027,8 +6029,8 @@ static int qla4xxx_get_bidi_chap(struct
 		if (!(chap_table->flags & BIT_6)) /* Not BIDI */
 			continue;
 
-		strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
-		strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+		strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+		strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
 		ret = 0;
 		break;
 	}
@@ -6258,8 +6260,8 @@ static void qla4xxx_get_param_ddb(struct
 
 	tddb->tpgt = sess->tpgt;
 	tddb->port = conn->persistent_port;
-	strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
-	strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
+	strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
+	strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
 }
 
 static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
@@ -7764,7 +7766,7 @@ static int qla4xxx_sysfs_ddb_logout(stru
 		goto exit_ddb_logout;
 	}
 
-	strncpy(flash_tddb->iscsi_name, fnode_sess->targetname,
+	strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname,
 		ISCSI_NAME_SIZE);
 
 	if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
@@ -9223,20 +9225,20 @@ static int qla4xxx_eh_abort(struct scsi_
 {
 	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
 	unsigned int id = cmd->device->id;
-	unsigned int lun = cmd->device->lun;
+	uint64_t lun = cmd->device->lun;
 	unsigned long flags;
 	struct srb *srb = NULL;
 	int ret = SUCCESS;
 	int wait = 0;
 
-	ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command issued cmd=%p, cdb=0x%x\n",
+	ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n",
 		   ha->host_no, id, lun, cmd, cmd->cmnd[0]);
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	srb = (struct srb *) CMD_SP(cmd);
 	if (!srb) {
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-		ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Specified command has already completed.\n",
+		ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n",
 			   ha->host_no, id, lun);
 		return SUCCESS;
 	}
@@ -9244,11 +9246,11 @@ static int qla4xxx_eh_abort(struct scsi_
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
-		DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
+		DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx failed.\n",
 		    ha->host_no, id, lun));
 		ret = FAILED;
 	} else {
-		DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
+		DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx success.\n",
 		    ha->host_no, id, lun));
 		wait = 1;
 	}
@@ -9258,14 +9260,14 @@ static int qla4xxx_eh_abort(struct scsi_
 	/* Wait for command to complete */
 	if (wait) {
 		if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
-			DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
+			DEBUG2(printk("scsi%ld:%d:%llu: Abort handler timed out\n",
 			    ha->host_no, id, lun));
 			ret = FAILED;
 		}
 	}
 
 	ql4_printk(KERN_INFO, ha,
-	    "scsi%ld:%d:%d: Abort command - %s\n",
+	    "scsi%ld:%d:%llu: Abort command - %s\n",
 	    ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed");
 
 	return ret;
@@ -9293,7 +9295,7 @@ static int qla4xxx_eh_device_reset(struc
 	ret = FAILED;
 
 	ql4_printk(KERN_INFO, ha,
-		   "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
+		   "scsi%ld:%d:%d:%llu: DEVICE RESET ISSUED.\n", ha->host_no,
 		   cmd->device->channel, cmd->device->id, cmd->device->lun);
 
 	DEBUG2(printk(KERN_INFO
@@ -9323,7 +9325,7 @@ static int qla4xxx_eh_device_reset(struc
 		goto eh_dev_reset_done;
 
 	ql4_printk(KERN_INFO, ha,
-		   "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
+		   "scsi(%ld:%d:%d:%llu): DEVICE RESET SUCCEEDED.\n",
 		   ha->host_no, cmd->device->channel, cmd->device->id,
 		   cmd->device->lun);
 
@@ -9440,7 +9442,7 @@ static int qla4xxx_eh_host_reset(struct
 	}
 
 	ql4_printk(KERN_INFO, ha,
-		   "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no,
+		   "scsi(%ld:%d:%d:%llu): HOST RESET ISSUED.\n", ha->host_no,
 		   cmd->device->channel, cmd->device->id, cmd->device->lun);
 
 	if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qlogicfas.c linux-libre-3.17-rc7-gnu/drivers/scsi/qlogicfas.c
--- linux-libre-3.16-gnu/drivers/scsi/qlogicfas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qlogicfas.c	2014-09-28 17:29:07.000000000 -0400
@@ -171,8 +171,6 @@ static int qlogicfas_release(struct Scsi
 		qlogicfas408_disable_ints(priv);	
 		free_irq(shost->irq, shost);
 	}
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 	scsi_host_put(shost);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/qlogicpti.c linux-libre-3.17-rc7-gnu/drivers/scsi/qlogicpti.c
--- linux-libre-3.16-gnu/drivers/scsi/qlogicpti.c	2014-08-07 04:59:16.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/qlogicpti.c	2014-09-28 21:41:53.000000000 -0400
@@ -959,7 +959,7 @@ static inline void update_can_queue(stru
 	/* Temporary workaround until bug is found and fixed (one bug has been found
 	   already, but fixing it makes things even worse) -jj */
 	int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64;
-	host->can_queue = host->host_busy + num_free;
+	host->can_queue = atomic_read(&host->host_busy) + num_free;
 	host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,8 +72,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/scsi.h>
 
-static void scsi_done(struct scsi_cmnd *cmd);
-
 /*
  * Definitions and constants.
  */
@@ -124,6 +122,8 @@ static const char *const scsi_device_typ
 	"Bridge controller",
 	"Object storage   ",
 	"Automation/Drive ",
+	"Security Manager ",
+	"Direct-Access-ZBC",
 };
 
 /**
@@ -235,7 +235,8 @@ fail:
  * Description: allocate a struct scsi_cmd from host's slab, recycling from the
  *              host's free_list if necessary.
  */
-struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
+static struct scsi_cmnd *
+__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
 	struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
 
@@ -265,7 +266,6 @@ struct scsi_cmnd *__scsi_get_command(str
 
 	return cmd;
 }
-EXPORT_SYMBOL_GPL(__scsi_get_command);
 
 /**
  * scsi_get_command - Allocate and setup a scsi command block
@@ -291,14 +291,13 @@ struct scsi_cmnd *scsi_get_command(struc
 	cmd->jiffies_at_alloc = jiffies;
 	return cmd;
 }
-EXPORT_SYMBOL(scsi_get_command);
 
 /**
  * __scsi_put_command - Free a struct scsi_cmnd
  * @shost: dev->host
  * @cmd: Command to free
  */
-void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+static void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 {
 	unsigned long flags;
 
@@ -314,7 +313,6 @@ void __scsi_put_command(struct Scsi_Host
 	if (likely(cmd != NULL))
 		scsi_host_free_command(shost, cmd);
 }
-EXPORT_SYMBOL(__scsi_put_command);
 
 /**
  * scsi_put_command - Free a scsi command block
@@ -334,11 +332,10 @@ void scsi_put_command(struct scsi_cmnd *
 	list_del_init(&cmd->list);
 	spin_unlock_irqrestore(&cmd->device->list_lock, flags);
 
-	cancel_delayed_work(&cmd->abort_work);
+	BUG_ON(delayed_work_pending(&cmd->abort_work));
 
 	__scsi_put_command(cmd->device->host, cmd);
 }
-EXPORT_SYMBOL(scsi_put_command);
 
 static struct scsi_host_cmd_pool *
 scsi_find_host_cmd_pool(struct Scsi_Host *shost)
@@ -368,8 +365,8 @@ scsi_alloc_host_cmd_pool(struct Scsi_Hos
 	if (!pool)
 		return NULL;
 
-	pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->name);
-	pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->name);
+	pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->proc_name);
+	pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->proc_name);
 	if (!pool->cmd_name || !pool->sense_name) {
 		scsi_free_host_cmd_pool(pool);
 		return NULL;
@@ -380,6 +377,10 @@ scsi_alloc_host_cmd_pool(struct Scsi_Hos
 		pool->slab_flags |= SLAB_CACHE_DMA;
 		pool->gfp_mask = __GFP_DMA;
 	}
+
+	if (hostt->cmd_size)
+		hostt->cmd_pool = pool;
+
 	return pool;
 }
 
@@ -424,8 +425,10 @@ out:
 out_free_slab:
 	kmem_cache_destroy(pool->cmd_slab);
 out_free_pool:
-	if (hostt->cmd_size)
+	if (hostt->cmd_size) {
 		scsi_free_host_cmd_pool(pool);
+		hostt->cmd_pool = NULL;
+	}
 	goto out;
 }
 
@@ -447,8 +450,10 @@ static void scsi_put_host_cmd_pool(struc
 	if (!--pool->users) {
 		kmem_cache_destroy(pool->cmd_slab);
 		kmem_cache_destroy(pool->sense_slab);
-		if (hostt->cmd_size)
+		if (hostt->cmd_size) {
 			scsi_free_host_cmd_pool(pool);
+			hostt->cmd_pool = NULL;
+		}
 	}
 	mutex_unlock(&host_cmd_pool_mutex);
 }
@@ -605,7 +610,7 @@ void scsi_log_completion(struct scsi_cmn
 			if (level > 3)
 				scmd_printk(KERN_INFO, cmd,
 					    "scsi host busy %d failed %d\n",
-					    cmd->device->host->host_busy,
+					    atomic_read(&cmd->device->host->host_busy),
 					    cmd->device->host->host_failed);
 		}
 	}
@@ -648,33 +653,24 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 		 * returns an immediate error upwards, and signals
 		 * that the device is no longer present */
 		cmd->result = DID_NO_CONNECT << 16;
-		scsi_done(cmd);
-		/* return 0 (because the command has been processed) */
-		goto out;
+		goto done;
 	}
 
 	/* Check to see if the scsi lld made this device blocked. */
 	if (unlikely(scsi_device_blocked(cmd->device))) {
-		/* 
+		/*
 		 * in blocked state, the command is just put back on
 		 * the device queue.  The suspend state has already
 		 * blocked the queue so future requests should not
 		 * occur until the device transitions out of the
 		 * suspend state.
 		 */
-
-		scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
-
-		SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n"));
-
-		/*
-		 * NOTE: rtn is still zero here because we don't need the
-		 * queue to be plugged on return (it's already stopped)
-		 */
-		goto out;
+		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+			"queuecommand : device blocked\n"));
+		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
 
-	/* 
+	/*
 	 * If SCSI-2 or lower, store the LUN value in cmnd.
 	 */
 	if (cmd->device->scsi_level <= SCSI_2 &&
@@ -690,57 +686,36 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 	 * length exceeds what the host adapter can handle.
 	 */
 	if (cmd->cmd_len > cmd->device->host->max_cmd_len) {
-		SCSI_LOG_MLQUEUE(3,
-			printk("queuecommand : command too long. "
+		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+			       "queuecommand : command too long. "
 			       "cdb_size=%d host->max_cmd_len=%d\n",
 			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
-
-		scsi_done(cmd);
-		goto out;
+		goto done;
 	}
 
 	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
-		scsi_done(cmd);
-	} else {
-		trace_scsi_dispatch_cmd_start(cmd);
-		cmd->scsi_done = scsi_done;
-		rtn = host->hostt->queuecommand(host, cmd);
+		goto done;
+
 	}
 
+	trace_scsi_dispatch_cmd_start(cmd);
+	rtn = host->hostt->queuecommand(host, cmd);
 	if (rtn) {
 		trace_scsi_dispatch_cmd_error(cmd, rtn);
 		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
 		    rtn != SCSI_MLQUEUE_TARGET_BUSY)
 			rtn = SCSI_MLQUEUE_HOST_BUSY;
 
-		scsi_queue_insert(cmd, rtn);
-
-		SCSI_LOG_MLQUEUE(3,
-		    printk("queuecommand : request rejected\n"));
+		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+			"queuecommand : request rejected\n"));
 	}
 
- out:
-	SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n"));
 	return rtn;
-}
-
-/**
- * scsi_done - Invoke completion on finished SCSI command.
- * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
- * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
- *
- * Description: This function is the mid-level's (SCSI Core) interrupt routine,
- * which regains ownership of the SCSI command (de facto) from a LLDD, and
- * calls blk_complete_request() for further processing.
- *
- * This function is interrupt context safe.
- */
-static void scsi_done(struct scsi_cmnd *cmd)
-{
-	trace_scsi_dispatch_cmd_done(cmd);
-	blk_complete_request(cmd->request);
+ done:
+	cmd->scsi_done(cmd);
+	return 0;
 }
 
 /**
@@ -761,17 +736,16 @@ void scsi_finish_command(struct scsi_cmn
 
 	scsi_device_unbusy(sdev);
 
-        /*
-         * Clear the flags which say that the device/host is no longer
-         * capable of accepting new commands.  These are set in scsi_queue.c
-         * for both the queue full condition on a device, and for a
-         * host full condition on the host.
-	 *
-	 * XXX(hch): What about locking?
-         */
-        shost->host_blocked = 0;
-	starget->target_blocked = 0;
-        sdev->device_blocked = 0;
+	/*
+	 * Clear the flags that say that the device/target/host is no longer
+	 * capable of accepting new commands.
+	 */
+	if (atomic_read(&shost->host_blocked))
+		atomic_set(&shost->host_blocked, 0);
+	if (atomic_read(&starget->target_blocked))
+		atomic_set(&starget->target_blocked, 0);
+	if (atomic_read(&sdev->device_blocked))
+		atomic_set(&sdev->device_blocked, 0);
 
 	/*
 	 * If we have valid sense information, then some kind of recovery
@@ -801,7 +775,6 @@ void scsi_finish_command(struct scsi_cmn
 	}
 	scsi_io_completion(cmd, good_bytes);
 }
-EXPORT_SYMBOL(scsi_finish_command);
 
 /**
  * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth
@@ -842,7 +815,7 @@ void scsi_adjust_queue_depth(struct scsi
 	 * is more IO than the LLD's can_queue (so there are not enuogh
 	 * tags) request_fn's host queue ready check will handle it.
 	 */
-	if (!sdev->host->bqt) {
+	if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
 		if (blk_queue_tagged(sdev->request_queue) &&
 		    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
 			goto out;
@@ -850,6 +823,10 @@ void scsi_adjust_queue_depth(struct scsi
 
 	sdev->queue_depth = tags;
 	switch (tagged) {
+		case 0:
+			sdev->ordered_tags = 0;
+			sdev->simple_tags = 0;
+			break;
 		case MSG_ORDERED_TAG:
 			sdev->ordered_tags = 1;
 			sdev->simple_tags = 1;
@@ -859,13 +836,11 @@ void scsi_adjust_queue_depth(struct scsi
 			sdev->simple_tags = 1;
 			break;
 		default:
+			sdev->ordered_tags = 0;
+			sdev->simple_tags = 0;
 			sdev_printk(KERN_WARNING, sdev,
 				    "scsi_adjust_queue_depth, bad queue type, "
 				    "disabled\n");
-		case 0:
-			sdev->ordered_tags = sdev->simple_tags = 0;
-			sdev->queue_depth = tags;
-			break;
 	}
  out:
 	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
@@ -1291,7 +1266,7 @@ EXPORT_SYMBOL(__starget_for_each_device)
  * really want to use scsi_device_lookup_by_target instead.
  **/
 struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget,
-						   uint lun)
+						   u64 lun)
 {
 	struct scsi_device *sdev;
 
@@ -1316,7 +1291,7 @@ EXPORT_SYMBOL(__scsi_device_lookup_by_ta
  * needs to be released with scsi_device_put once you're done with it.
  **/
 struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget,
-						 uint lun)
+						 u64 lun)
 {
 	struct scsi_device *sdev;
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -1349,7 +1324,7 @@ EXPORT_SYMBOL(scsi_device_lookup_by_targ
  * really want to use scsi_device_lookup instead.
  **/
 struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost,
-		uint channel, uint id, uint lun)
+		uint channel, uint id, u64 lun)
 {
 	struct scsi_device *sdev;
 
@@ -1375,7 +1350,7 @@ EXPORT_SYMBOL(__scsi_device_lookup);
  * needs to be released with scsi_device_put once you're done with it.
  **/
 struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost,
-		uint channel, uint id, uint lun)
+		uint channel, uint id, u64 lun)
 {
 	struct scsi_device *sdev;
 	unsigned long flags;
@@ -1396,6 +1371,9 @@ MODULE_LICENSE("GPL");
 module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
 
+bool scsi_use_blk_mq = false;
+module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
+
 static int __init init_scsi(void)
 {
 	int error;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_debug.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_debug.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,6 +42,10 @@
 #include <linux/scatterlist.h>
 #include <linux/blkdev.h>
 #include <linux/crc-t10dif.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/atomic.h>
+#include <linux/hrtimer.h>
 
 #include <net/checksum.h>
 
@@ -53,13 +57,16 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_dbg.h>
 
 #include "sd.h"
 #include "scsi_logging.h"
 
-#define SCSI_DEBUG_VERSION "1.82"
-static const char * scsi_debug_version_date = "20100324";
+#define SCSI_DEBUG_VERSION "1.84"
+static const char *scsi_debug_version_date = "20140706";
+
+#define MY_NAME "scsi_debug"
 
 /* Additional Sense Code (ASC) */
 #define NO_ADDITIONAL_SENSE 0x0
@@ -72,7 +79,11 @@ static const char * scsi_debug_version_d
 #define INVALID_COMMAND_OPCODE 0x20
 #define INVALID_FIELD_IN_CDB 0x24
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
-#define POWERON_RESET 0x29
+#define UA_RESET_ASC 0x29
+#define UA_CHANGED_ASC 0x2a
+#define POWER_ON_RESET_ASCQ 0x0
+#define BUS_RESET_ASCQ 0x2	/* scsi bus reset occurred */
+#define MODE_CHANGED_ASCQ 0x1	/* mode parameters changed */
 #define SAVING_PARAMS_UNSUP 0x39
 #define TRANSPORT_PROBLEM 0x4b
 #define THRESHOLD_EXCEEDED 0x5d
@@ -81,7 +92,6 @@ static const char * scsi_debug_version_d
 /* Additional Sense Code Qualifier (ASCQ) */
 #define ACK_NAK_TO 0x3
 
-#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
 /* Default values for driver parameters */
 #define DEF_NUM_HOST   1
@@ -91,7 +101,7 @@ static const char * scsi_debug_version_d
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
 #define DEF_ATO 1
-#define DEF_DELAY   1
+#define DEF_DELAY   1		/* if > 0 unit is a jiffy */
 #define DEF_DEV_SIZE_MB   8
 #define DEF_DIF 0
 #define DEF_DIX 0
@@ -99,11 +109,13 @@ static const char * scsi_debug_version_d
 #define DEF_EVERY_NTH   0
 #define DEF_FAKE_RW	0
 #define DEF_GUARD 0
+#define DEF_HOST_LOCK 0
 #define DEF_LBPU 0
 #define DEF_LBPWS 0
 #define DEF_LBPWS10 0
 #define DEF_LBPRZ 1
 #define DEF_LOWEST_ALIGNED 0
+#define DEF_NDELAY   0		/* if > 0 unit is a nanosecond */
 #define DEF_NO_LUN_0   0
 #define DEF_NUM_PARTS   0
 #define DEF_OPTS   0
@@ -113,6 +125,7 @@ static const char * scsi_debug_version_d
 #define DEF_REMOVABLE false
 #define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
 #define DEF_SECTOR_SIZE 512
+#define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 #define DEF_UNMAP_ALIGNMENT 0
 #define DEF_UNMAP_GRANULARITY 1
 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
@@ -120,6 +133,7 @@ static const char * scsi_debug_version_d
 #define DEF_VIRTUAL_GB   0
 #define DEF_VPD_USE_HOSTNO 1
 #define DEF_WRITESAME_LENGTH 0xFFFF
+#define DELAY_OVERRIDDEN -9999
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -130,7 +144,14 @@ static const char * scsi_debug_version_d
 #define SCSI_DEBUG_OPT_DIF_ERR   32
 #define SCSI_DEBUG_OPT_DIX_ERR   64
 #define SCSI_DEBUG_OPT_MAC_TIMEOUT  128
-#define SCSI_DEBUG_OPT_SHORT_TRANSFER	256
+#define SCSI_DEBUG_OPT_SHORT_TRANSFER	0x100
+#define SCSI_DEBUG_OPT_Q_NOISE	0x200
+#define SCSI_DEBUG_OPT_ALL_TSF	0x400
+#define SCSI_DEBUG_OPT_RARE_TSF	0x800
+#define SCSI_DEBUG_OPT_N_WCE	0x1000
+#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
+#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
+#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
 /* When "every_nth" > 0 then modulo "every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
@@ -148,6 +169,19 @@ static const char * scsi_debug_version_d
  * writing a new value (other than -1 or 1) to every_nth via sysfs).
  */
 
+/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
+ * priority order. In the subset implemented here lower numbers have higher
+ * priority. The UA numbers should be a sequence starting from 0 with
+ * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
+#define SDEBUG_UA_POR 0		/* Power on, reset, or bus device reset */
+#define SDEBUG_UA_BUS_RESET 1
+#define SDEBUG_UA_MODE_CHANGED 2
+#define SDEBUG_NUM_UAS 3
+
+/* for check_readiness() */
+#define UAS_ONLY 1
+#define UAS_TUR 0
+
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
@@ -158,9 +192,19 @@ static const char * scsi_debug_version_d
 #define SAM2_LUN_ADDRESS_METHOD 0
 #define SAM2_WLUN_REPORT_LUNS 0xc101
 
-/* Can queue up to this number of commands. Typically commands that
- * that have a non-zero delay are queued. */
-#define SCSI_DEBUG_CANQUEUE  255
+/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
+ * (for response) at one time. Can be reduced by max_queue option. Command
+ * responses are not queued when delay=0 and ndelay=0. The per-device
+ * DEF_CMD_PER_LUN can be changed via sysfs:
+ * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
+ * SCSI_DEBUG_CANQUEUE. */
+#define SCSI_DEBUG_CANQUEUE_WORDS  9	/* a WORD is bits in a long */
+#define SCSI_DEBUG_CANQUEUE  (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
+#define DEF_CMD_PER_LUN  255
+
+#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
+#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
+#endif
 
 static int scsi_debug_add_host = DEF_NUM_HOST;
 static int scsi_debug_ato = DEF_ATO;
@@ -175,6 +219,8 @@ static unsigned int scsi_debug_guard = D
 static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
 static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
+static atomic_t retired_max_queue;	/* if > 0 then was prior max_queue */
+static int scsi_debug_ndelay = DEF_NDELAY;
 static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
 static int scsi_debug_no_uld = 0;
 static int scsi_debug_num_parts = DEF_NUM_PARTS;
@@ -198,8 +244,11 @@ static unsigned int scsi_debug_unmap_max
 static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
 static bool scsi_debug_removable = DEF_REMOVABLE;
 static bool scsi_debug_clustering;
+static bool scsi_debug_host_lock = DEF_HOST_LOCK;
 
-static int scsi_debug_cmnd_count = 0;
+static atomic_t sdebug_cmnd_count;
+static atomic_t sdebug_completions;
+static atomic_t sdebug_a_tsf;		/* counter of 'almost' TSFs */
 
 #define DEV_READONLY(TGT)      (0)
 
@@ -214,24 +263,23 @@ static int sdebug_sectors_per;		/* secto
 
 #define SDEBUG_MAX_PARTS 4
 
-#define SDEBUG_SENSE_LEN 32
-
 #define SCSI_DEBUG_MAX_CMD_LEN 32
 
 static unsigned int scsi_debug_lbp(void)
 {
-	return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;
+	return ((0 == scsi_debug_fake_rw) &&
+		(scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
 }
 
 struct sdebug_dev_info {
 	struct list_head dev_list;
-	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
 	unsigned int channel;
 	unsigned int target;
-	unsigned int lun;
+	u64 lun;
 	struct sdebug_host_info *sdbg_host;
-	unsigned int wlun;
-	char reset;
+	u64 wlun;
+	unsigned long uas_bm[1];
+	atomic_t num_in_q;
 	char stopped;
 	char used;
 };
@@ -249,26 +297,33 @@ struct sdebug_host_info {
 static LIST_HEAD(sdebug_host_list);
 static DEFINE_SPINLOCK(sdebug_host_list_lock);
 
-typedef void (* done_funct_t) (struct scsi_cmnd *);
+
+struct sdebug_hrtimer {		/* ... is derived from hrtimer */
+	struct hrtimer hrt;	/* must be first element */
+	int qa_indx;
+};
 
 struct sdebug_queued_cmd {
-	int in_use;
-	struct timer_list cmnd_timer;
-	done_funct_t done_funct;
+	/* in_use flagged by a bit in queued_in_use_bm[] */
+	struct timer_list *cmnd_timerp;
+	struct tasklet_struct *tletp;
+	struct sdebug_hrtimer *sd_hrtp;
 	struct scsi_cmnd * a_cmnd;
-	int scsi_result;
 };
 static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
+
 
 static unsigned char * fake_storep;	/* ramdisk storage */
 static struct sd_dif_tuple *dif_storep;	/* protection info */
 static void *map_storep;		/* provisioning map */
 
 static unsigned long map_size;
-static int num_aborts = 0;
-static int num_dev_resets = 0;
-static int num_bus_resets = 0;
-static int num_host_resets = 0;
+static int num_aborts;
+static int num_dev_resets;
+static int num_target_resets;
+static int num_bus_resets;
+static int num_host_resets;
 static int dix_writes;
 static int dix_reads;
 static int dif_errors;
@@ -276,7 +331,8 @@ static int dif_errors;
 static DEFINE_SPINLOCK(queued_arr_lock);
 static DEFINE_RWLOCK(atomic_rw);
 
-static char sdebug_proc_name[] = "scsi_debug";
+static char sdebug_proc_name[] = MY_NAME;
+static const char *my_name = MY_NAME;
 
 static struct bus_type pseudo_lld_bus;
 
@@ -291,6 +347,12 @@ static const int check_condition_result
 static const int illegal_condition_result =
 	(DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
 
+static const int device_qfull_result =
+	(DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
+
+static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
+				     0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
+				     0, 0, 0, 0};
 static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
 				    0, 0, 0x2, 0x4b};
 static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
@@ -332,19 +394,24 @@ static void sdebug_max_tgts_luns(void)
 	spin_unlock(&sdebug_host_list_lock);
 }
 
-static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
-			    int asc, int asq)
+static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
 {
 	unsigned char *sbuff;
 
-	sbuff = devip->sense_buff;
-	memset(sbuff, 0, SDEBUG_SENSE_LEN);
+	sbuff = scp->sense_buffer;
+	if (!sbuff) {
+		sdev_printk(KERN_ERR, scp->device,
+			    "%s: sense_buffer is NULL\n", __func__);
+		return;
+	}
+	memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
 
 	scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
-		      "[0x%x,0x%x,0x%x]\n", key, asc, asq);
+		sdev_printk(KERN_INFO, scp->device,
+			    "%s:  [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
+			    my_name, key, asc, asq);
 }
 
 static void get_data_transfer_info(unsigned char *cmd,
@@ -409,29 +476,71 @@ static void get_data_transfer_info(unsig
 static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
-		printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);
+		if (0x1261 == cmd)
+			sdev_printk(KERN_INFO, dev,
+				    "%s: BLKFLSBUF [0x1261]\n", __func__);
+		else if (0x5331 == cmd)
+			sdev_printk(KERN_INFO, dev,
+				    "%s: CDROM_GET_CAPABILITY [0x5331]\n",
+				    __func__);
+		else
+			sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
+				    __func__, cmd);
 	}
 	return -EINVAL;
 	/* return -ENOTTY; // correct return but upsets fdisk */
 }
 
-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 			   struct sdebug_dev_info * devip)
 {
-	if (devip->reset) {
-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: Reporting Unit "
-			       "attention: power on reset\n");
-		devip->reset = 0;
-		mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
+	int k;
+	bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
+
+	k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
+	if (k != SDEBUG_NUM_UAS) {
+		const char *cp = NULL;
+
+		switch (k) {
+		case SDEBUG_UA_POR:
+			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+					UA_RESET_ASC, POWER_ON_RESET_ASCQ);
+			if (debug)
+				cp = "power on reset";
+			break;
+		case SDEBUG_UA_BUS_RESET:
+			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+					UA_RESET_ASC, BUS_RESET_ASCQ);
+			if (debug)
+				cp = "bus reset";
+			break;
+		case SDEBUG_UA_MODE_CHANGED:
+			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+					UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
+			if (debug)
+				cp = "mode parameters changed";
+			break;
+		default:
+			pr_warn("%s: unexpected unit attention code=%d\n",
+				__func__, k);
+			if (debug)
+				cp = "unknown";
+			break;
+		}
+		clear_bit(k, devip->uas_bm);
+		if (debug)
+			sdev_printk(KERN_INFO, SCpnt->device,
+				   "%s reports: Unit attention: %s\n",
+				   my_name, cp);
 		return check_condition_result;
 	}
-	if ((0 == reset_only) && devip->stopped) {
-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: Reporting Not "
-			       "ready: initializing command required\n");
-		mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
+	if ((UAS_TUR == uas_only) && devip->stopped) {
+		mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
 				0x2);
+		if (debug)
+			sdev_printk(KERN_INFO, SCpnt->device,
+				    "%s reports: Not ready: %s\n", my_name,
+				    "initializing command required");
 		return check_condition_result;
 	}
 	return 0;
@@ -471,8 +580,9 @@ static int fetch_to_dev_buffer(struct sc
 
 static const char * inq_vendor_id = "Linux   ";
 static const char * inq_product_id = "scsi_debug      ";
-static const char * inq_product_rev = "0004";
+static const char *inq_product_rev = "0184";	/* version less '.' */
 
+/* Device identification VPD page. Returns number of bytes placed in arr */
 static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
 			   int target_dev_id, int dev_id_num,
 			   const char * dev_id_str,
@@ -573,12 +683,14 @@ static unsigned char vpd84_data[] = {
     0x22,0x22,0x22,0x0,0xbb,0x2,
 };
 
+/*  Software interface identification VPD page */
 static int inquiry_evpd_84(unsigned char * arr)
 {
 	memcpy(arr, vpd84_data, sizeof(vpd84_data));
 	return sizeof(vpd84_data);
 }
 
+/* Management network addresses VPD page */
 static int inquiry_evpd_85(unsigned char * arr)
 {
 	int num = 0;
@@ -713,6 +825,7 @@ static unsigned char vpd89_data[] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
 };
 
+/* ATA Information VPD page */
 static int inquiry_evpd_89(unsigned char * arr)
 {
 	memcpy(arr, vpd89_data, sizeof(vpd89_data));
@@ -720,7 +833,6 @@ static int inquiry_evpd_89(unsigned char
 }
 
 
-/* Block limits VPD page (SBC-3) */
 static unsigned char vpdb0_data[] = {
 	/* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -728,6 +840,7 @@ static unsigned char vpdb0_data[] = {
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 };
 
+/* Block limits VPD page (SBC-3) */
 static int inquiry_evpd_b0(unsigned char * arr)
 {
 	unsigned int gran;
@@ -811,7 +924,7 @@ static int inquiry_evpd_b2(unsigned char
 #define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 584
 
-static int resp_inquiry(struct scsi_cmnd * scp, int target,
+static int resp_inquiry(struct scsi_cmnd *scp, int target,
 			struct sdebug_dev_info * devip)
 {
 	unsigned char pq_pdt;
@@ -831,7 +944,7 @@ static int resp_inquiry(struct scsi_cmnd
 		pq_pdt = (scsi_debug_ptype & 0x1f);
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 			       	0);
 		kfree(arr);
 		return check_condition_result;
@@ -917,7 +1030,7 @@ static int resp_inquiry(struct scsi_cmnd
 			arr[3] = inquiry_evpd_b2(&arr[4]);
 		} else {
 			/* Illegal request, invalid field in cdb */
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(scp, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			kfree(arr);
 			return check_condition_result;
@@ -963,15 +1076,13 @@ static int resp_requests(struct scsi_cmn
 {
 	unsigned char * sbuff;
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
-	unsigned char arr[SDEBUG_SENSE_LEN];
+	unsigned char arr[SCSI_SENSE_BUFFERSIZE];
 	int want_dsense;
 	int len = 18;
 
 	memset(arr, 0, sizeof(arr));
-	if (devip->reset == 1)
-		mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
 	want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
-	sbuff = devip->sense_buff;
+	sbuff = scp->sense_buffer;
 	if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
 		if (want_dsense) {
 			arr[0] = 0x72;
@@ -986,7 +1097,7 @@ static int resp_requests(struct scsi_cmn
 			arr[13] = 0xff;		/* TEST set and MRIE==6 */
 		}
 	} else {
-		memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
+		memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
 		if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
 			/* DESC bit set and sense_buff in fixed format */
 			memset(arr, 0, sizeof(arr));
@@ -997,7 +1108,7 @@ static int resp_requests(struct scsi_cmn
 			len = 8;
 		}
 	}
-	mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
+	mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
 	return fill_from_dev_buffer(scp, arr, len);
 }
 
@@ -1007,11 +1118,12 @@ static int resp_start_stop(struct scsi_c
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
 	int power_cond, errsts, start;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	power_cond = (cmd[4] & 0xf0) >> 4;
 	if (power_cond) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 			       	0);
 		return check_condition_result;
 	}
@@ -1038,7 +1150,8 @@ static int resp_readcap(struct scsi_cmnd
 	unsigned int capac;
 	int errsts;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	/* following just in case virtual_gb changed */
 	sdebug_capacity = get_sdebug_capacity();
@@ -1069,7 +1182,8 @@ static int resp_readcap16(struct scsi_cm
 	unsigned long long capac;
 	int errsts, k, alloc_len;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
 		     + cmd[13]);
@@ -1230,12 +1344,18 @@ static int resp_format_pg(unsigned char
 
 static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 { 	/* Caching page for mode_sense */
-	unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
+	unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
 		0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,     0, 0, 0, 0};
 
+	if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
+		caching_pg[2] &= ~0x4;	/* set WCE=0 (default WCE=1) */
 	memcpy(p, caching_pg, sizeof(caching_pg));
 	if (1 == pcontrol)
-		memset(p + 2, 0, sizeof(caching_pg) - 2);
+		memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
+	else if (2 == pcontrol)
+		memcpy(p, d_caching_pg, sizeof(d_caching_pg));
 	return sizeof(caching_pg);
 }
 
@@ -1350,7 +1470,8 @@ static int resp_mode_sense(struct scsi_c
 	unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	dbd = !!(cmd[1] & 0x8);
 	pcontrol = (cmd[2] & 0xc0) >> 6;
@@ -1365,8 +1486,7 @@ static int resp_mode_sense(struct scsi_c
 	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
 	memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
 	if (0x3 == pcontrol) {  /* Saving values not supported */
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
-			       	0);
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
 		return check_condition_result;
 	}
 	target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
@@ -1422,7 +1542,7 @@ static int resp_mode_sense(struct scsi_c
 
 	if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
 		/* TODO: Control Extension page */
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 			       	0);
 		return check_condition_result;
 	}
@@ -1449,7 +1569,7 @@ static int resp_mode_sense(struct scsi_c
 		break;
 	case 0x19:	/* if spc==1 then sas phy, control+discover */
 		if ((subpcode > 0x2) && (subpcode < 0xff)) {
-		        mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(scp, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			return check_condition_result;
 	        }
@@ -1482,14 +1602,14 @@ static int resp_mode_sense(struct scsi_c
 			}
 			len += resp_iec_m_pg(ap + len, pcontrol, target);
 		} else {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(scp, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			return check_condition_result;
                 }
 		offset += len;
 		break;
 	default:
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 			       	0);
 		return check_condition_result;
 	}
@@ -1512,14 +1632,15 @@ static int resp_mode_select(struct scsi_
 	unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	memset(arr, 0, sizeof(arr));
 	pf = cmd[1] & 0x10;
 	sp = cmd[1] & 0x1;
 	param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
 	if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
 	}
@@ -1528,12 +1649,13 @@ static int resp_mode_select(struct scsi_
                 return (DID_ERROR << 16);
         else if ((res < param_len) &&
                  (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-                printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, "
-                       " IO sent=%d bytes\n", param_len, res);
+		sdev_printk(KERN_INFO, scp->device,
+			    "%s: cdb indicated=%d, IO sent=%d bytes\n",
+			    __func__, param_len, res);
 	md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
 	bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
 	if (md_len > 2) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_PARAM_LIST, 0);
 		return check_condition_result;
 	}
@@ -1541,7 +1663,7 @@ static int resp_mode_select(struct scsi_
 	mpage = arr[off] & 0x3f;
 	ps = !!(arr[off] & 0x80);
 	if (ps) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_PARAM_LIST, 0);
 		return check_condition_result;
 	}
@@ -1549,32 +1671,42 @@ static int resp_mode_select(struct scsi_
 	pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
 		       (arr[off + 1] + 2);
 	if ((pg_len + off) > param_len) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				PARAMETER_LIST_LENGTH_ERR, 0);
 		return check_condition_result;
 	}
 	switch (mpage) {
+	case 0x8:      /* Caching Mode page */
+		if (caching_pg[1] == arr[off + 1]) {
+			memcpy(caching_pg + 2, arr + off + 2,
+			       sizeof(caching_pg) - 2);
+			goto set_mode_changed_ua;
+		}
+		break;
 	case 0xa:      /* Control Mode page */
 		if (ctrl_m_pg[1] == arr[off + 1]) {
 			memcpy(ctrl_m_pg + 2, arr + off + 2,
 			       sizeof(ctrl_m_pg) - 2);
 			scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
-			return 0;
+			goto set_mode_changed_ua;
 		}
 		break;
 	case 0x1c:      /* Informational Exceptions Mode page */
 		if (iec_m_pg[1] == arr[off + 1]) {
 			memcpy(iec_m_pg + 2, arr + off + 2,
 			       sizeof(iec_m_pg) - 2);
-			return 0;
+			goto set_mode_changed_ua;
 		}
 		break;
 	default:
 		break;
 	}
-	mk_sense_buffer(devip, ILLEGAL_REQUEST,
+	mk_sense_buffer(scp, ILLEGAL_REQUEST,
 			INVALID_FIELD_IN_PARAM_LIST, 0);
 	return check_condition_result;
+set_mode_changed_ua:
+	set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
+	return 0;
 }
 
 static int resp_temp_l_pg(unsigned char * arr)
@@ -1609,13 +1741,14 @@ static int resp_log_sense(struct scsi_cm
 	unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-	if ((errsts = check_readiness(scp, 1, devip)))
+	errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (errsts)
 		return errsts;
 	memset(arr, 0, sizeof(arr));
 	ppc = cmd[1] & 0x2;
 	sp = cmd[1] & 0x1;
 	if (ppc || sp) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
 	}
@@ -1640,7 +1773,7 @@ static int resp_log_sense(struct scsi_cm
 			arr[3] = resp_ie_l_pg(arr + 4);
 			break;
 		default:
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(scp, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			return check_condition_result;
 		}
@@ -1673,12 +1806,12 @@ static int resp_log_sense(struct scsi_cm
 			arr[3] = n - 4;
 			break;
 		default:
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(scp, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			return check_condition_result;
 		}
 	} else {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
 	}
@@ -1687,16 +1820,16 @@ static int resp_log_sense(struct scsi_cm
 		    min(len, SDEBUG_MAX_INQ_ARR_SZ));
 }
 
-static int check_device_access_params(struct sdebug_dev_info *devi,
+static int check_device_access_params(struct scsi_cmnd *scp,
 				      unsigned long long lba, unsigned int num)
 {
 	if (lba + num > sdebug_capacity) {
-		mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
 		return check_condition_result;
 	}
 	/* transfer length excessive (tie in to block limits VPD page) */
 	if (num > sdebug_store_sectors) {
-		mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
 	}
 	return 0;
@@ -1704,7 +1837,6 @@ static int check_device_access_params(st
 
 /* Returns number of bytes copied or -1 if error. */
 static int do_device_access(struct scsi_cmnd *scmd,
-			    struct sdebug_dev_info *devi,
 			    unsigned long long lba, unsigned int num, int write)
 {
 	int ret;
@@ -1861,13 +1993,12 @@ static int prot_verify_read(struct scsi_
 }
 
 static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
-		     unsigned int num, struct sdebug_dev_info *devip,
-		     u32 ei_lba)
+		     unsigned int num, u32 ei_lba)
 {
 	unsigned long iflags;
 	int ret;
 
-	ret = check_device_access_params(devip, lba, num);
+	ret = check_device_access_params(SCpnt, lba, num);
 	if (ret)
 		return ret;
 
@@ -1875,16 +2006,16 @@ static int resp_read(struct scsi_cmnd *S
 	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
 	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
 		/* claim unrecoverable read error */
-		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
+		mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
 		/* set info field and valid bit for fixed descriptor */
-		if (0x70 == (devip->sense_buff[0] & 0x7f)) {
-			devip->sense_buff[0] |= 0x80;	/* Valid bit */
+		if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) {
+			SCpnt->sense_buffer[0] |= 0x80;	/* Valid bit */
 			ret = (lba < OPT_MEDIUM_ERR_ADDR)
 			      ? OPT_MEDIUM_ERR_ADDR : (int)lba;
-			devip->sense_buff[3] = (ret >> 24) & 0xff;
-			devip->sense_buff[4] = (ret >> 16) & 0xff;
-			devip->sense_buff[5] = (ret >> 8) & 0xff;
-			devip->sense_buff[6] = ret & 0xff;
+			SCpnt->sense_buffer[3] = (ret >> 24) & 0xff;
+			SCpnt->sense_buffer[4] = (ret >> 16) & 0xff;
+			SCpnt->sense_buffer[5] = (ret >> 8) & 0xff;
+			SCpnt->sense_buffer[6] = ret & 0xff;
 		}
 	        scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
 		return check_condition_result;
@@ -1898,12 +2029,12 @@ static int resp_read(struct scsi_cmnd *S
 
 		if (prot_ret) {
 			read_unlock_irqrestore(&atomic_rw, iflags);
-			mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
+			mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret);
 			return illegal_condition_result;
 		}
 	}
 
-	ret = do_device_access(SCpnt, devip, lba, num, 0);
+	ret = do_device_access(SCpnt, lba, num, 0);
 	read_unlock_irqrestore(&atomic_rw, iflags);
 	if (ret == -1)
 		return DID_ERROR << 16;
@@ -1915,22 +2046,23 @@ static int resp_read(struct scsi_cmnd *S
 
 void dump_sector(unsigned char *buf, int len)
 {
-	int i, j;
-
-	printk(KERN_ERR ">>> Sector Dump <<<\n");
+	int i, j, n;
 
+	pr_err(">>> Sector Dump <<<\n");
 	for (i = 0 ; i < len ; i += 16) {
-		printk(KERN_ERR "%04d: ", i);
+		char b[128];
 
-		for (j = 0 ; j < 16 ; j++) {
+		for (j = 0, n = 0; j < 16; j++) {
 			unsigned char c = buf[i+j];
+
 			if (c >= 0x20 && c < 0x7e)
-				printk(" %c ", buf[i+j]);
+				n += scnprintf(b + n, sizeof(b) - n,
+					       " %c ", buf[i+j]);
 			else
-				printk("%02x ", buf[i+j]);
+				n += scnprintf(b + n, sizeof(b) - n,
+					       "%02x ", buf[i+j]);
 		}
-
-		printk("\n");
+		pr_err("%04d: %s\n", i, b);
 	}
 }
 
@@ -2092,13 +2224,12 @@ static void unmap_region(sector_t lba, u
 }
 
 static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
-		      unsigned int num, struct sdebug_dev_info *devip,
-		      u32 ei_lba)
+		      unsigned int num, u32 ei_lba)
 {
 	unsigned long iflags;
 	int ret;
 
-	ret = check_device_access_params(devip, lba, num);
+	ret = check_device_access_params(SCpnt, lba, num);
 	if (ret)
 		return ret;
 
@@ -2110,12 +2241,13 @@ static int resp_write(struct scsi_cmnd *
 
 		if (prot_ret) {
 			write_unlock_irqrestore(&atomic_rw, iflags);
-			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10,
+					prot_ret);
 			return illegal_condition_result;
 		}
 	}
 
-	ret = do_device_access(SCpnt, devip, lba, num, 1);
+	ret = do_device_access(SCpnt, lba, num, 1);
 	if (scsi_debug_lbp())
 		map_region(lba, num);
 	write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2123,26 +2255,26 @@ static int resp_write(struct scsi_cmnd *
 		return (DID_ERROR << 16);
 	else if ((ret < (num * scsi_debug_sector_size)) &&
 		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-		printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
-		       " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
+		sdev_printk(KERN_INFO, SCpnt->device,
+			    "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
+			    my_name, num * scsi_debug_sector_size, ret);
 
 	return 0;
 }
 
 static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
-		      unsigned int num, struct sdebug_dev_info *devip,
-			   u32 ei_lba, unsigned int unmap)
+		      unsigned int num, u32 ei_lba, unsigned int unmap)
 {
 	unsigned long iflags;
 	unsigned long long i;
 	int ret;
 
-	ret = check_device_access_params(devip, lba, num);
+	ret = check_device_access_params(scmd, lba, num);
 	if (ret)
 		return ret;
 
 	if (num > scsi_debug_write_same_length) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 				0);
 		return check_condition_result;
 	}
@@ -2164,8 +2296,10 @@ static int resp_write_same(struct scsi_c
 		return (DID_ERROR << 16);
 	} else if ((ret < (num * scsi_debug_sector_size)) &&
 		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-		printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, "
-		       " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
+		sdev_printk(KERN_INFO, scmd->device,
+			    "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
+			    my_name, "write same",
+			    num * scsi_debug_sector_size, ret);
 
 	/* Copy first sector to remaining blocks */
 	for (i = 1 ; i < num ; i++)
@@ -2195,7 +2329,7 @@ static int resp_unmap(struct scsi_cmnd *
 	int ret;
 	unsigned long iflags;
 
-	ret = check_readiness(scmd, 1, devip);
+	ret = check_readiness(scmd, UAS_ONLY, devip);
 	if (ret)
 		return ret;
 
@@ -2221,7 +2355,7 @@ static int resp_unmap(struct scsi_cmnd *
 		unsigned long long lba = get_unaligned_be64(&desc[i].lba);
 		unsigned int num = get_unaligned_be32(&desc[i].blocks);
 
-		ret = check_device_access_params(devip, lba, num);
+		ret = check_device_access_params(scmd, lba, num);
 		if (ret)
 			goto out;
 
@@ -2247,7 +2381,7 @@ static int resp_get_lba_status(struct sc
 	unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
 	int ret;
 
-	ret = check_readiness(scmd, 1, devip);
+	ret = check_readiness(scmd, UAS_ONLY, devip);
 	if (ret)
 		return ret;
 
@@ -2257,7 +2391,7 @@ static int resp_get_lba_status(struct sc
 	if (alloc_len < 24)
 		return 0;
 
-	ret = check_device_access_params(devip, lba, 1);
+	ret = check_device_access_params(scmd, lba, 1);
 	if (ret)
 		return ret;
 
@@ -2278,7 +2412,8 @@ static int resp_report_luns(struct scsi_
 			    struct sdebug_dev_info * devip)
 {
 	unsigned int alloc_len;
-	int lun_cnt, i, upper, num, n, wlun, lun;
+	int lun_cnt, i, upper, num, n;
+	u64 wlun, lun;
 	unsigned char *cmd = (unsigned char *)scp->cmnd;
 	int select_report = (int)cmd[2];
 	struct scsi_lun *one_lun;
@@ -2287,7 +2422,7 @@ static int resp_report_luns(struct scsi_
 
 	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
 	if ((alloc_len < 4) || (select_report > 2)) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
 			       	0);
 		return check_condition_result;
 	}
@@ -2341,7 +2476,7 @@ static int resp_xdwriteread(struct scsi_
 	/* better not to use temporary buffer. */
 	buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
 	if (!buf) {
-		mk_sense_buffer(devip, NOT_READY,
+		mk_sense_buffer(scp, NOT_READY,
 				LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 		return check_condition_result;
 	}
@@ -2365,34 +2500,125 @@ static int resp_xdwriteread(struct scsi_
 	return 0;
 }
 
-/* When timer goes off this function is called. */
-static void timer_intr_handler(unsigned long indx)
+/* When timer or tasklet goes off this function is called. */
+static void sdebug_q_cmd_complete(unsigned long indx)
 {
-	struct sdebug_queued_cmd * sqcp;
+	int qa_indx;
+	int retiring = 0;
 	unsigned long iflags;
+	struct sdebug_queued_cmd *sqcp;
+	struct scsi_cmnd *scp;
+	struct sdebug_dev_info *devip;
 
-	if (indx >= scsi_debug_max_queue) {
-		printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too "
-		       "large\n");
+	atomic_inc(&sdebug_completions);
+	qa_indx = indx;
+	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
+		pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
 		return;
 	}
 	spin_lock_irqsave(&queued_arr_lock, iflags);
-	sqcp = &queued_arr[(int)indx];
-	if (! sqcp->in_use) {
-		printk(KERN_ERR "scsi_debug:timer_intr_handler: Unexpected "
-		       "interrupt\n");
+	sqcp = &queued_arr[qa_indx];
+	scp = sqcp->a_cmnd;
+	if (NULL == scp) {
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		pr_err("%s: scp is NULL\n", __func__);
 		return;
 	}
-	sqcp->in_use = 0;
-	if (sqcp->done_funct) {
-		sqcp->a_cmnd->result = sqcp->scsi_result;
-		sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
+	devip = (struct sdebug_dev_info *)scp->device->hostdata;
+	if (devip)
+		atomic_dec(&devip->num_in_q);
+	else
+		pr_err("%s: devip=NULL\n", __func__);
+	if (atomic_read(&retired_max_queue) > 0)
+		retiring = 1;
+
+	sqcp->a_cmnd = NULL;
+	if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		pr_err("%s: Unexpected completion\n", __func__);
+		return;
+	}
+
+	if (unlikely(retiring)) {	/* user has reduced max_queue */
+		int k, retval;
+
+		retval = atomic_read(&retired_max_queue);
+		if (qa_indx >= retval) {
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			pr_err("%s: index %d too large\n", __func__, retval);
+			return;
+		}
+		k = find_last_bit(queued_in_use_bm, retval);
+		if ((k < scsi_debug_max_queue) || (k == retval))
+			atomic_set(&retired_max_queue, 0);
+		else
+			atomic_set(&retired_max_queue, k + 1);
 	}
-	sqcp->done_funct = NULL;
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	scp->scsi_done(scp); /* callback to mid level */
 }
 
+/* When high resolution timer goes off this function is called. */
+static enum hrtimer_restart
+sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
+{
+	int qa_indx;
+	int retiring = 0;
+	unsigned long iflags;
+	struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
+	struct sdebug_queued_cmd *sqcp;
+	struct scsi_cmnd *scp;
+	struct sdebug_dev_info *devip;
+
+	atomic_inc(&sdebug_completions);
+	qa_indx = sd_hrtp->qa_indx;
+	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
+		pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+		goto the_end;
+	}
+	spin_lock_irqsave(&queued_arr_lock, iflags);
+	sqcp = &queued_arr[qa_indx];
+	scp = sqcp->a_cmnd;
+	if (NULL == scp) {
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		pr_err("%s: scp is NULL\n", __func__);
+		goto the_end;
+	}
+	devip = (struct sdebug_dev_info *)scp->device->hostdata;
+	if (devip)
+		atomic_dec(&devip->num_in_q);
+	else
+		pr_err("%s: devip=NULL\n", __func__);
+	if (atomic_read(&retired_max_queue) > 0)
+		retiring = 1;
+
+	sqcp->a_cmnd = NULL;
+	if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		pr_err("%s: Unexpected completion\n", __func__);
+		goto the_end;
+	}
+
+	if (unlikely(retiring)) {	/* user has reduced max_queue */
+		int k, retval;
+
+		retval = atomic_read(&retired_max_queue);
+		if (qa_indx >= retval) {
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			pr_err("%s: index %d too large\n", __func__, retval);
+			goto the_end;
+		}
+		k = find_last_bit(queued_in_use_bm, retval);
+		if ((k < scsi_debug_max_queue) || (k == retval))
+			atomic_set(&retired_max_queue, 0);
+		else
+			atomic_set(&retired_max_queue, k + 1);
+	}
+	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	scp->scsi_done(scp); /* callback to mid level */
+the_end:
+	return HRTIMER_NORESTART;
+}
 
 static struct sdebug_dev_info *
 sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
@@ -2418,7 +2644,7 @@ static struct sdebug_dev_info * devInfoR
 		return devip;
 	sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
 	if (!sdbg_host) {
-                printk(KERN_ERR "Host info NULL\n");
+		pr_err("%s: Host info NULL\n", __func__);
 		return NULL;
         }
 	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
@@ -2444,15 +2670,9 @@ static struct sdebug_dev_info * devInfoR
 	open_devip->target = sdev->id;
 	open_devip->lun = sdev->lun;
 	open_devip->sdbg_host = sdbg_host;
-	open_devip->reset = 1;
+	atomic_set(&open_devip->num_in_q, 0);
+	set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
 	open_devip->used = 1;
-	memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
-	if (scsi_debug_dsense)
-		open_devip->sense_buff[0] = 0x72;
-	else {
-		open_devip->sense_buff[0] = 0x70;
-		open_devip->sense_buff[7] = 0xa;
-	}
 	if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
 		open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
 
@@ -2462,7 +2682,7 @@ static struct sdebug_dev_info * devInfoR
 static int scsi_debug_slave_alloc(struct scsi_device *sdp)
 {
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+		printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
 	return 0;
@@ -2473,7 +2693,7 @@ static int scsi_debug_slave_configure(st
 	struct sdebug_dev_info *devip;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
+		printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
@@ -2481,10 +2701,11 @@ static int scsi_debug_slave_configure(st
 	if (NULL == devip)
 		return 1;	/* no resources, will be marked offline */
 	sdp->hostdata = devip;
+	sdp->tagged_supported = 1;
 	if (sdp->host->cmd_per_lun)
-		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
-					sdp->host->cmd_per_lun);
-	blk_queue_max_segment_size(sdp->request_queue, 256 * 1024);
+		scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING,
+					DEF_CMD_PER_LUN);
+	blk_queue_max_segment_size(sdp->request_queue, -1U);
 	if (scsi_debug_no_uld)
 		sdp->no_uld_attach = 1;
 	return 0;
@@ -2496,7 +2717,7 @@ static void scsi_debug_slave_destroy(str
 		(struct sdebug_dev_info *)sdp->hostdata;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
+		printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (devip) {
 		/* make this slot available for re-use */
@@ -2505,150 +2726,230 @@ static void scsi_debug_slave_destroy(str
 	}
 }
 
-/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
+/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
 static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
 	unsigned long iflags;
-	int k;
+	int k, qmax, r_qmax;
 	struct sdebug_queued_cmd *sqcp;
+	struct sdebug_dev_info *devip;
 
 	spin_lock_irqsave(&queued_arr_lock, iflags);
-	for (k = 0; k < scsi_debug_max_queue; ++k) {
-		sqcp = &queued_arr[k];
-		if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
-			del_timer_sync(&sqcp->cmnd_timer);
-			sqcp->in_use = 0;
-			sqcp->a_cmnd = NULL;
-			break;
+	qmax = scsi_debug_max_queue;
+	r_qmax = atomic_read(&retired_max_queue);
+	if (r_qmax > qmax)
+		qmax = r_qmax;
+	for (k = 0; k < qmax; ++k) {
+		if (test_bit(k, queued_in_use_bm)) {
+			sqcp = &queued_arr[k];
+			if (cmnd == sqcp->a_cmnd) {
+				if (scsi_debug_ndelay > 0) {
+					if (sqcp->sd_hrtp)
+						hrtimer_cancel(
+							&sqcp->sd_hrtp->hrt);
+				} else if (scsi_debug_delay > 0) {
+					if (sqcp->cmnd_timerp)
+						del_timer_sync(
+							sqcp->cmnd_timerp);
+				} else if (scsi_debug_delay < 0) {
+					if (sqcp->tletp)
+						tasklet_kill(sqcp->tletp);
+				}
+				__clear_bit(k, queued_in_use_bm);
+				devip = (struct sdebug_dev_info *)
+					cmnd->device->hostdata;
+				if (devip)
+					atomic_dec(&devip->num_in_q);
+				sqcp->a_cmnd = NULL;
+				break;
+			}
 		}
 	}
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
-	return (k < scsi_debug_max_queue) ? 1 : 0;
+	return (k < qmax) ? 1 : 0;
 }
 
-/* Deletes (stops) timers of all queued commands */
+/* Deletes (stops) timers or tasklets of all queued commands */
 static void stop_all_queued(void)
 {
 	unsigned long iflags;
 	int k;
 	struct sdebug_queued_cmd *sqcp;
+	struct sdebug_dev_info *devip;
 
 	spin_lock_irqsave(&queued_arr_lock, iflags);
-	for (k = 0; k < scsi_debug_max_queue; ++k) {
-		sqcp = &queued_arr[k];
-		if (sqcp->in_use && sqcp->a_cmnd) {
-			del_timer_sync(&sqcp->cmnd_timer);
-			sqcp->in_use = 0;
-			sqcp->a_cmnd = NULL;
+	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+		if (test_bit(k, queued_in_use_bm)) {
+			sqcp = &queued_arr[k];
+			if (sqcp->a_cmnd) {
+				if (scsi_debug_ndelay > 0) {
+					if (sqcp->sd_hrtp)
+						hrtimer_cancel(
+							&sqcp->sd_hrtp->hrt);
+				} else if (scsi_debug_delay > 0) {
+					if (sqcp->cmnd_timerp)
+						del_timer_sync(
+							sqcp->cmnd_timerp);
+				} else if (scsi_debug_delay < 0) {
+					if (sqcp->tletp)
+						tasklet_kill(sqcp->tletp);
+				}
+				__clear_bit(k, queued_in_use_bm);
+				devip = (struct sdebug_dev_info *)
+					sqcp->a_cmnd->device->hostdata;
+				if (devip)
+					atomic_dec(&devip->num_in_q);
+				sqcp->a_cmnd = NULL;
+			}
 		}
 	}
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
+/* Free queued command memory on heap */
+static void free_all_queued(void)
 {
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: abort\n");
-	++num_aborts;
-	stop_queued_cmnd(SCpnt);
-	return SUCCESS;
+	unsigned long iflags;
+	int k;
+	struct sdebug_queued_cmd *sqcp;
+
+	spin_lock_irqsave(&queued_arr_lock, iflags);
+	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+		sqcp = &queued_arr[k];
+		kfree(sqcp->cmnd_timerp);
+		sqcp->cmnd_timerp = NULL;
+		kfree(sqcp->tletp);
+		sqcp->tletp = NULL;
+		kfree(sqcp->sd_hrtp);
+		sqcp->sd_hrtp = NULL;
+	}
+	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_biosparam(struct scsi_device *sdev,
-		struct block_device * bdev, sector_t capacity, int *info)
+static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
 {
-	int res;
-	unsigned char *buf;
-
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: biosparam\n");
-	buf = scsi_bios_ptable(bdev);
-	if (buf) {
-		res = scsi_partsize(buf, capacity,
-				    &info[2], &info[0], &info[1]);
-		kfree(buf);
-		if (! res)
-			return res;
+	++num_aborts;
+	if (SCpnt) {
+		if (SCpnt->device &&
+		    (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+			sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
+				    __func__);
+		stop_queued_cmnd(SCpnt);
 	}
-	info[0] = sdebug_heads;
-	info[1] = sdebug_sectors_per;
-	info[2] = sdebug_cylinders_per;
-	return 0;
+	return SUCCESS;
 }
 
 static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
 {
 	struct sdebug_dev_info * devip;
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: device_reset\n");
 	++num_dev_resets;
-	if (SCpnt) {
-		devip = devInfoReg(SCpnt->device);
+	if (SCpnt && SCpnt->device) {
+		struct scsi_device *sdp = SCpnt->device;
+
+		if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+			sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+		devip = devInfoReg(sdp);
 		if (devip)
-			devip->reset = 1;
+			set_bit(SDEBUG_UA_POR, devip->uas_bm);
+	}
+	return SUCCESS;
+}
+
+static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
+{
+	struct sdebug_host_info *sdbg_host;
+	struct sdebug_dev_info *devip;
+	struct scsi_device *sdp;
+	struct Scsi_Host *hp;
+	int k = 0;
+
+	++num_target_resets;
+	if (!SCpnt)
+		goto lie;
+	sdp = SCpnt->device;
+	if (!sdp)
+		goto lie;
+	if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+		sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+	hp = sdp->host;
+	if (!hp)
+		goto lie;
+	sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
+	if (sdbg_host) {
+		list_for_each_entry(devip,
+				    &sdbg_host->dev_info_list,
+				    dev_list)
+			if (devip->target == sdp->id) {
+				set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+				++k;
+			}
 	}
+	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+		sdev_printk(KERN_INFO, sdp,
+			    "%s: %d device(s) found in target\n", __func__, k);
+lie:
 	return SUCCESS;
 }
 
 static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	struct sdebug_host_info *sdbg_host;
-        struct sdebug_dev_info * dev_info;
+	struct sdebug_dev_info *devip;
         struct scsi_device * sdp;
         struct Scsi_Host * hp;
+	int k = 0;
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: bus_reset\n");
 	++num_bus_resets;
-	if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+	if (!(SCpnt && SCpnt->device))
+		goto lie;
+	sdp = SCpnt->device;
+	if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+		sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+	hp = sdp->host;
+	if (hp) {
 		sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
 		if (sdbg_host) {
-			list_for_each_entry(dev_info,
+			list_for_each_entry(devip,
                                             &sdbg_host->dev_info_list,
-                                            dev_list)
-				dev_info->reset = 1;
+					    dev_list) {
+				set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+				++k;
+			}
 		}
 	}
+	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+		sdev_printk(KERN_INFO, sdp,
+			    "%s: %d device(s) found in host\n", __func__, k);
+lie:
 	return SUCCESS;
 }
 
 static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
 {
 	struct sdebug_host_info * sdbg_host;
-        struct sdebug_dev_info * dev_info;
+	struct sdebug_dev_info *devip;
+	int k = 0;
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: host_reset\n");
 	++num_host_resets;
+	if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+		sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
         spin_lock(&sdebug_host_list_lock);
         list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
-                list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
-                                    dev_list)
-                        dev_info->reset = 1;
+		list_for_each_entry(devip, &sdbg_host->dev_info_list,
+				    dev_list) {
+			set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
+			++k;
+		}
         }
         spin_unlock(&sdebug_host_list_lock);
 	stop_all_queued();
+	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+		sdev_printk(KERN_INFO, SCpnt->device,
+			    "%s: %d device(s) found\n", __func__, k);
 	return SUCCESS;
 }
 
-/* Initializes timers in queued array */
-static void __init init_all_queued(void)
-{
-	unsigned long iflags;
-	int k;
-	struct sdebug_queued_cmd * sqcp;
-
-	spin_lock_irqsave(&queued_arr_lock, iflags);
-	for (k = 0; k < scsi_debug_max_queue; ++k) {
-		sqcp = &queued_arr[k];
-		init_timer(&sqcp->cmnd_timer);
-		sqcp->in_use = 0;
-		sqcp->a_cmnd = NULL;
-	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
-}
-
 static void __init sdebug_build_parts(unsigned char *ramp,
 				      unsigned long store_size)
 {
@@ -2662,8 +2963,8 @@ static void __init sdebug_build_parts(un
 		return;
 	if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
 		scsi_debug_num_parts = SDEBUG_MAX_PARTS;
-		printk(KERN_WARNING "scsi_debug:build_parts: reducing "
-				    "partitions to %d\n", SDEBUG_MAX_PARTS);
+		pr_warn("%s: reducing partitions to %d\n", __func__,
+			SDEBUG_MAX_PARTS);
 	}
 	num_sectors = (int)sdebug_store_sectors;
 	sectors_per_part = (num_sectors - sdebug_sectors_per)
@@ -2700,62 +3001,130 @@ static void __init sdebug_build_parts(un
 	}
 }
 
-static int schedule_resp(struct scsi_cmnd * cmnd,
-			 struct sdebug_dev_info * devip,
-			 done_funct_t done, int scsi_result, int delta_jiff)
+static int
+schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
+	      int scsi_result, int delta_jiff)
 {
-	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
-		if (scsi_result) {
-			struct scsi_device * sdp = cmnd->device;
+	unsigned long iflags;
+	int k, num_in_q, tsf, qdepth, inject;
+	struct sdebug_queued_cmd *sqcp = NULL;
+	struct scsi_device *sdp = cmnd->device;
 
-			printk(KERN_INFO "scsi_debug:    <%u %u %u %u> "
-			       "non-zero result=0x%x\n", sdp->host->host_no,
-			       sdp->channel, sdp->id, sdp->lun, scsi_result);
-		}
+	if (NULL == cmnd || NULL == devip) {
+		pr_warn("%s: called with NULL cmnd or devip pointer\n",
+			__func__);
+		/* no particularly good error to report back */
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
-	if (cmnd && devip) {
-		/* simulate autosense by this driver */
-		if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
-			memcpy(cmnd->sense_buffer, devip->sense_buff,
-			       (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
-			       SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
+	if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+		sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
+			    __func__, scsi_result);
+	if (delta_jiff == 0) {
+		/* using same thread to call back mid-layer */
+		cmnd->result = scsi_result;
+		cmnd->scsi_done(cmnd);
+		return 0;
 	}
-	if (delta_jiff <= 0) {
-		if (cmnd)
+
+	/* deferred response cases */
+	spin_lock_irqsave(&queued_arr_lock, iflags);
+	num_in_q = atomic_read(&devip->num_in_q);
+	qdepth = cmnd->device->queue_depth;
+	k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
+	tsf = 0;
+	inject = 0;
+	if ((qdepth > 0) && (num_in_q >= qdepth))
+		tsf = 1;
+	else if ((scsi_debug_every_nth != 0) &&
+		 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts)) {
+		if ((num_in_q == (qdepth - 1)) &&
+		    (atomic_inc_return(&sdebug_a_tsf) >=
+		     abs(scsi_debug_every_nth))) {
+			atomic_set(&sdebug_a_tsf, 0);
+			inject = 1;
+			tsf = 1;
+		}
+	}
+
+	/* if (tsf) simulate device reporting SCSI status of TASK SET FULL.
+	 * Might override existing CHECK CONDITION. */
+	if (tsf)
+		scsi_result = device_qfull_result;
+	if (k >= scsi_debug_max_queue) {
+		if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
+			tsf = 1;
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
+			sdev_printk(KERN_INFO, sdp,
+				    "%s: num_in_q=%d, bypass q, %s%s\n",
+				    __func__, num_in_q,
+				    (inject ? "<inject> " : ""),
+				    (tsf ?  "status: TASK SET FULL" :
+					    "report: host busy"));
+		if (tsf) {
+			/* queued_arr full so respond in same thread */
 			cmnd->result = scsi_result;
-		if (done)
-			done(cmnd);
-		return 0;
-	} else {
-		unsigned long iflags;
-		int k;
-		struct sdebug_queued_cmd * sqcp = NULL;
+			cmnd->scsi_done(cmnd);
+			/* As scsi_done() is called "inline" must return 0 */
+			return 0;
+		} else
+			return SCSI_MLQUEUE_HOST_BUSY;
+	}
+	__set_bit(k, queued_in_use_bm);
+	atomic_inc(&devip->num_in_q);
+	sqcp = &queued_arr[k];
+	sqcp->a_cmnd = cmnd;
+	cmnd->result = scsi_result;
+	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	if (delta_jiff > 0) {
+		if (NULL == sqcp->cmnd_timerp) {
+			sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
+						    GFP_ATOMIC);
+			if (NULL == sqcp->cmnd_timerp)
+				return SCSI_MLQUEUE_HOST_BUSY;
+			init_timer(sqcp->cmnd_timerp);
+		}
+		sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
+		sqcp->cmnd_timerp->data = k;
+		sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
+		add_timer(sqcp->cmnd_timerp);
+	} else if (scsi_debug_ndelay > 0) {
+		ktime_t kt = ktime_set(0, scsi_debug_ndelay);
+		struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
 
-		spin_lock_irqsave(&queued_arr_lock, iflags);
-		for (k = 0; k < scsi_debug_max_queue; ++k) {
-			sqcp = &queued_arr[k];
-			if (! sqcp->in_use)
-				break;
+		if (NULL == sd_hp) {
+			sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
+			if (NULL == sd_hp)
+				return SCSI_MLQUEUE_HOST_BUSY;
+			sqcp->sd_hrtp = sd_hp;
+			hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
+				     HRTIMER_MODE_REL);
+			sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
+			sd_hp->qa_indx = k;
 		}
-		if (k >= scsi_debug_max_queue) {
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
-			printk(KERN_WARNING "scsi_debug: can_queue exceeded\n");
-			return 1;	/* report busy to mid level */
+		hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
+	} else {	/* delay < 0 */
+		if (NULL == sqcp->tletp) {
+			sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
+					      GFP_ATOMIC);
+			if (NULL == sqcp->tletp)
+				return SCSI_MLQUEUE_HOST_BUSY;
+			tasklet_init(sqcp->tletp,
+				     sdebug_q_cmd_complete, k);
 		}
-		sqcp->in_use = 1;
-		sqcp->a_cmnd = cmnd;
-		sqcp->scsi_result = scsi_result;
-		sqcp->done_funct = done;
-		sqcp->cmnd_timer.function = timer_intr_handler;
-		sqcp->cmnd_timer.data = k;
-		sqcp->cmnd_timer.expires = jiffies + delta_jiff;
-		add_timer(&sqcp->cmnd_timer);
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
-		if (cmnd)
-			cmnd->result = 0;
-		return 0;
+		if (-1 == delta_jiff)
+			tasklet_hi_schedule(sqcp->tletp);
+		else
+			tasklet_schedule(sqcp->tletp);
 	}
+	if (tsf && (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts))
+		sdev_printk(KERN_INFO, sdp,
+			    "%s: num_in_q=%d +1, %s%s\n", __func__,
+			    num_in_q, (inject ? "<inject> " : ""),
+			    "status: TASK SET FULL");
+	return 0;
 }
+
 /* Note: The following macros create attribute files in the
    /sys/module/scsi_debug/parameters directory. Unfortunately this
    driver is unaware of a change and cannot trigger auxiliary actions
@@ -2773,6 +3142,7 @@ module_param_named(dsense, scsi_debug_ds
 module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
 module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
 module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
+module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
 module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
 module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
 module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
@@ -2780,6 +3150,7 @@ module_param_named(lbprz, scsi_debug_lbp
 module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
 module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
 module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
+module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
 module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
 module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
 module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
@@ -2809,7 +3180,7 @@ MODULE_VERSION(SCSI_DEBUG_VERSION);
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
 MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
 MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
-MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
+MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
 MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
 MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
@@ -2817,13 +3188,15 @@ MODULE_PARM_DESC(dsense, "use descriptor
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
 MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
 MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
 MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
 MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
-MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))");
+MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
+MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
@@ -2854,9 +3227,7 @@ static const char * scsi_debug_info(stru
 	return sdebug_info;
 }
 
-/* scsi_debug_proc_info
- * Used if the driver currently has no own support for /proc/scsi
- */
+/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
 static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
 	char arr[16];
@@ -2871,27 +3242,49 @@ static int scsi_debug_write_info(struct
 		return -EINVAL;
 	scsi_debug_opts = opts;
 	if (scsi_debug_every_nth != 0)
-		scsi_debug_cmnd_count = 0;
+		atomic_set(&sdebug_cmnd_count, 0);
 	return length;
 }
 
+/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
+ * same for each scsi_debug host (if more than one). Some of the counters
+ * output are not atomics so might be inaccurate in a busy system. */
 static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	seq_printf(m, "scsi_debug adapter driver, version "
-	    "%s [%s]\n"
-	    "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
-	    "every_nth=%d(curr:%d)\n"
-	    "delay=%d, max_luns=%d, scsi_level=%d\n"
-	    "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
-	    "number of aborts=%d, device_reset=%d, bus_resets=%d, "
-	    "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n",
-	    SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
-	    scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
-	    scsi_debug_cmnd_count, scsi_debug_delay,
-	    scsi_debug_max_luns, scsi_debug_scsi_level,
-	    scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
-	    sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
-	    num_host_resets, dix_reads, dix_writes, dif_errors);
+	int f, l;
+	char b[32];
+
+	if (scsi_debug_every_nth > 0)
+		snprintf(b, sizeof(b), " (curr:%d)",
+			 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
+				atomic_read(&sdebug_a_tsf) :
+				atomic_read(&sdebug_cmnd_count)));
+	else
+		b[0] = '\0';
+
+	seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
+		"num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
+		"every_nth=%d%s\n"
+		"delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
+		"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
+		"command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
+		"host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
+		"usec_in_jiffy=%lu\n",
+		SCSI_DEBUG_VERSION, scsi_debug_version_date,
+		scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
+		scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
+		scsi_debug_max_luns, atomic_read(&sdebug_completions),
+		scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
+		sdebug_sectors_per, num_aborts, num_dev_resets,
+		num_target_resets, num_bus_resets, num_host_resets,
+		dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
+
+	f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
+	if (f != scsi_debug_max_queue) {
+		l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
+		seq_printf(m, "   %s BUSY: first,last bits set: %d,%d\n",
+			   "queued_in_use_bm", f, l);
+	}
 	return 0;
 }
 
@@ -2899,23 +3292,69 @@ static ssize_t delay_show(struct device_
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
 }
-
+/* Returns -EBUSY if delay is being changed and commands are queued */
 static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
 {
-        int delay;
-	char work[20];
+	int delay, res;
 
-        if (1 == sscanf(buf, "%10s", work)) {
-		if ((1 == sscanf(work, "%d", &delay)) && (delay >= 0)) {
-			scsi_debug_delay = delay;
-			return count;
+	if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
+		res = count;
+		if (scsi_debug_delay != delay) {
+			unsigned long iflags;
+			int k;
+
+			spin_lock_irqsave(&queued_arr_lock, iflags);
+			k = find_first_bit(queued_in_use_bm,
+					   scsi_debug_max_queue);
+			if (k != scsi_debug_max_queue)
+				res = -EBUSY;	/* have queued commands */
+			else {
+				scsi_debug_delay = delay;
+				scsi_debug_ndelay = 0;
+			}
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		}
+		return res;
 	}
 	return -EINVAL;
 }
 static DRIVER_ATTR_RW(delay);
 
+static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
+}
+/* Returns -EBUSY if ndelay is being changed and commands are queued */
+/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
+static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
+			   size_t count)
+{
+	unsigned long iflags;
+	int ndelay, res, k;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
+	    (ndelay >= 0) && (ndelay < 1000000000)) {
+		res = count;
+		if (scsi_debug_ndelay != ndelay) {
+			spin_lock_irqsave(&queued_arr_lock, iflags);
+			k = find_first_bit(queued_in_use_bm,
+					   scsi_debug_max_queue);
+			if (k != scsi_debug_max_queue)
+				res = -EBUSY;	/* have queued commands */
+			else {
+				scsi_debug_ndelay = ndelay;
+				scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
+							  : DEF_DELAY;
+			}
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		}
+		return res;
+	}
+	return -EINVAL;
+}
+static DRIVER_ATTR_RW(ndelay);
+
 static ssize_t opts_show(struct device_driver *ddp, char *buf)
 {
         return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
@@ -2939,7 +3378,8 @@ static ssize_t opts_store(struct device_
 	return -EINVAL;
 opts_done:
 	scsi_debug_opts = opts;
-	scsi_debug_cmnd_count = 0;
+	atomic_set(&sdebug_cmnd_count, 0);
+	atomic_set(&sdebug_a_tsf, 0);
 	return count;
 }
 static DRIVER_ATTR_RW(opts);
@@ -2988,7 +3428,24 @@ static ssize_t fake_rw_store(struct devi
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_fake_rw = n;
+		n = (n > 0);
+		scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
+		if (scsi_debug_fake_rw != n) {
+			if ((0 == n) && (NULL == fake_storep)) {
+				unsigned long sz =
+					(unsigned long)scsi_debug_dev_size_mb *
+					1048576;
+
+				fake_storep = vmalloc(sz);
+				if (NULL == fake_storep) {
+					pr_err("%s: out of memory, 9\n",
+					       __func__);
+					return -ENOMEM;
+				}
+				memset(fake_storep, 0, sz);
+			}
+			scsi_debug_fake_rw = n;
+		}
 		return count;
 	}
 	return -EINVAL;
@@ -3053,7 +3510,7 @@ static ssize_t every_nth_store(struct de
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
 		scsi_debug_every_nth = nth;
-		scsi_debug_cmnd_count = 0;
+		atomic_set(&sdebug_cmnd_count, 0);
 		return count;
 	}
 	return -EINVAL;
@@ -3082,14 +3539,26 @@ static ssize_t max_queue_show(struct dev
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
 }
+/* N.B. max_queue can be changed while there are queued commands. In flight
+ * commands beyond the new max_queue will be completed. */
 static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
 			       size_t count)
 {
-        int n;
+	unsigned long iflags;
+	int n, k;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
 	    (n <= SCSI_DEBUG_CANQUEUE)) {
+		spin_lock_irqsave(&queued_arr_lock, iflags);
+		k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
 		scsi_debug_max_queue = n;
+		if (SCSI_DEBUG_CANQUEUE == k)
+			atomic_set(&retired_max_queue, 0);
+		else if (k >= n)
+			atomic_set(&retired_max_queue, k + 1);
+		else
+			atomic_set(&retired_max_queue, 0);
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		return count;
 	}
 	return -EINVAL;
@@ -3234,6 +3703,40 @@ static ssize_t removable_store(struct de
 }
 static DRIVER_ATTR_RW(removable);
 
+static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
+}
+/* Returns -EBUSY if host_lock is being changed and commands are queued */
+static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
+			       size_t count)
+{
+	int n, res;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		bool new_host_lock = (n > 0);
+
+		res = count;
+		if (new_host_lock != scsi_debug_host_lock) {
+			unsigned long iflags;
+			int k;
+
+			spin_lock_irqsave(&queued_arr_lock, iflags);
+			k = find_first_bit(queued_in_use_bm,
+					   scsi_debug_max_queue);
+			if (k != scsi_debug_max_queue)
+				res = -EBUSY;	/* have queued commands */
+			else
+				scsi_debug_host_lock = new_host_lock;
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		}
+		return res;
+	}
+	return -EINVAL;
+}
+static DRIVER_ATTR_RW(host_lock);
+
+
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
    files (over those found in the /sys/module/scsi_debug/parameters
@@ -3266,6 +3769,8 @@ static struct attribute *sdebug_drv_attr
 	&driver_attr_ato.attr,
 	&driver_attr_map.attr,
 	&driver_attr_removable.attr,
+	&driver_attr_host_lock.attr,
+	&driver_attr_ndelay.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);
@@ -3279,6 +3784,17 @@ static int __init scsi_debug_init(void)
 	int k;
 	int ret;
 
+	atomic_set(&sdebug_cmnd_count, 0);
+	atomic_set(&sdebug_completions, 0);
+	atomic_set(&retired_max_queue, 0);
+
+	if (scsi_debug_ndelay >= 1000000000) {
+		pr_warn("%s: ndelay must be less than 1 second, ignored\n",
+			__func__);
+		scsi_debug_ndelay = 0;
+	} else if (scsi_debug_ndelay > 0)
+		scsi_debug_delay = DELAY_OVERRIDDEN;
+
 	switch (scsi_debug_sector_size) {
 	case  512:
 	case 1024:
@@ -3286,7 +3802,7 @@ static int __init scsi_debug_init(void)
 	case 4096:
 		break;
 	default:
-		printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n",
+		pr_err("%s: invalid sector_size %d\n", __func__,
 		       scsi_debug_sector_size);
 		return -EINVAL;
 	}
@@ -3300,28 +3816,28 @@ static int __init scsi_debug_init(void)
 		break;
 
 	default:
-		printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n");
+		pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
 		return -EINVAL;
 	}
 
 	if (scsi_debug_guard > 1) {
-		printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n");
+		pr_err("%s: guard must be 0 or 1\n", __func__);
 		return -EINVAL;
 	}
 
 	if (scsi_debug_ato > 1) {
-		printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n");
+		pr_err("%s: ato must be 0 or 1\n", __func__);
 		return -EINVAL;
 	}
 
 	if (scsi_debug_physblk_exp > 15) {
-		printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n",
+		pr_err("%s: invalid physblk_exp %u\n", __func__,
 		       scsi_debug_physblk_exp);
 		return -EINVAL;
 	}
 
 	if (scsi_debug_lowest_aligned > 0x3fff) {
-		printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n",
+		pr_err("%s: lowest_aligned too big: %u\n", __func__,
 		       scsi_debug_lowest_aligned);
 		return -EINVAL;
 	}
@@ -3349,14 +3865,16 @@ static int __init scsi_debug_init(void)
 			       (sdebug_sectors_per * sdebug_heads);
 	}
 
-	fake_storep = vmalloc(sz);
-	if (NULL == fake_storep) {
-		printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
-		return -ENOMEM;
+	if (0 == scsi_debug_fake_rw) {
+		fake_storep = vmalloc(sz);
+		if (NULL == fake_storep) {
+			pr_err("%s: out of memory, 1\n", __func__);
+			return -ENOMEM;
+		}
+		memset(fake_storep, 0, sz);
+		if (scsi_debug_num_parts > 0)
+			sdebug_build_parts(fake_storep, sz);
 	}
-	memset(fake_storep, 0, sz);
-	if (scsi_debug_num_parts > 0)
-		sdebug_build_parts(fake_storep, sz);
 
 	if (scsi_debug_dix) {
 		int dif_size;
@@ -3364,11 +3882,11 @@ static int __init scsi_debug_init(void)
 		dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
 		dif_storep = vmalloc(dif_size);
 
-		printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n",
-		       dif_size, dif_storep);
+		pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
+			dif_storep);
 
 		if (dif_storep == NULL) {
-			printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n");
+			pr_err("%s: out of mem. (DIX)\n", __func__);
 			ret = -ENOMEM;
 			goto free_vm;
 		}
@@ -3390,8 +3908,7 @@ static int __init scsi_debug_init(void)
 		if (scsi_debug_unmap_alignment &&
 		    scsi_debug_unmap_granularity <=
 		    scsi_debug_unmap_alignment) {
-			printk(KERN_ERR
-			       "%s: ERR: unmap_granularity <= unmap_alignment\n",
+			pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
 			       __func__);
 			return -EINVAL;
 		}
@@ -3399,11 +3916,10 @@ static int __init scsi_debug_init(void)
 		map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
 		map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
 
-		printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
-		       map_size);
+		pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
 
 		if (map_storep == NULL) {
-			printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n");
+			pr_err("%s: out of mem. (MAP)\n", __func__);
 			ret = -ENOMEM;
 			goto free_vm;
 		}
@@ -3417,39 +3933,35 @@ static int __init scsi_debug_init(void)
 
 	pseudo_primary = root_device_register("pseudo_0");
 	if (IS_ERR(pseudo_primary)) {
-		printk(KERN_WARNING "scsi_debug: root_device_register() error\n");
+		pr_warn("%s: root_device_register() error\n", __func__);
 		ret = PTR_ERR(pseudo_primary);
 		goto free_vm;
 	}
 	ret = bus_register(&pseudo_lld_bus);
 	if (ret < 0) {
-		printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
-			ret);
+		pr_warn("%s: bus_register error: %d\n", __func__, ret);
 		goto dev_unreg;
 	}
 	ret = driver_register(&sdebug_driverfs_driver);
 	if (ret < 0) {
-		printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
-			ret);
+		pr_warn("%s: driver_register error: %d\n", __func__, ret);
 		goto bus_unreg;
 	}
 
-	init_all_queued();
-
 	host_to_add = scsi_debug_add_host;
         scsi_debug_add_host = 0;
 
         for (k = 0; k < host_to_add; k++) {
                 if (sdebug_add_adapter()) {
-                        printk(KERN_ERR "scsi_debug_init: "
-                               "sdebug_add_adapter failed k=%d\n", k);
+			pr_err("%s: sdebug_add_adapter failed k=%d\n",
+				__func__, k);
                         break;
                 }
         }
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
-		printk(KERN_INFO "scsi_debug_init: built %d host(s)\n",
-		       scsi_debug_add_host);
+		pr_info("%s: built %d host(s)\n", __func__,
+			scsi_debug_add_host);
 	}
 	return 0;
 
@@ -3472,6 +3984,7 @@ static void __exit scsi_debug_exit(void)
 	int k = scsi_debug_add_host;
 
 	stop_all_queued();
+	free_all_queued();
 	for (; k; k--)
 		sdebug_remove_adapter();
 	driver_unregister(&sdebug_driverfs_driver);
@@ -3569,8 +4082,8 @@ static void sdebug_remove_adapter(void)
         --scsi_debug_add_host;
 }
 
-static
-int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
+static int
+scsi_debug_queuecommand(struct scsi_cmnd *SCpnt)
 {
 	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
 	int len, k;
@@ -3589,32 +4102,34 @@ int scsi_debug_queuecommand_lck(struct s
 	int unmap = 0;
 
 	scsi_set_resid(SCpnt, 0);
-	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
-		printk(KERN_INFO "scsi_debug: cmd ");
-		for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
-			printk("%02x ", (int)cmd[k]);
-		printk("\n");
-	}
+	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) &&
+	    !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts) && cmd) {
+		char b[120];
+		int n;
 
-	if (target == SCpnt->device->host->hostt->this_id) {
-		printk(KERN_INFO "scsi_debug: initiator's id used as "
-		       "target!\n");
-		return schedule_resp(SCpnt, NULL, done,
-				     DID_NO_CONNECT << 16, 0);
+		len = SCpnt->cmd_len;
+		if (len > 32)
+			strcpy(b, "too long, over 32 bytes");
+		else {
+			for (k = 0, n = 0; k < len; ++k)
+				n += scnprintf(b + n, sizeof(b) - n, "%02x ",
+					       (unsigned int)cmd[k]);
+		}
+		sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name,
+			    b);
 	}
 
 	if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
 	    (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
-		return schedule_resp(SCpnt, NULL, done,
-				     DID_NO_CONNECT << 16, 0);
+		return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
 	devip = devInfoReg(SCpnt->device);
 	if (NULL == devip)
-		return schedule_resp(SCpnt, NULL, done,
-				     DID_NO_CONNECT << 16, 0);
+		return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
 
 	if ((scsi_debug_every_nth != 0) &&
-	    (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
-		scsi_debug_cmnd_count = 0;
+	    (atomic_inc_return(&sdebug_cmnd_count) >=
+	     abs(scsi_debug_every_nth))) {
+		atomic_set(&sdebug_cmnd_count, 0);
 		if (scsi_debug_every_nth < -1)
 			scsi_debug_every_nth = -1;
 		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
@@ -3645,11 +4160,10 @@ int scsi_debug_queuecommand_lck(struct s
 			if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 				printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
 				       "not supported for wlun\n", *cmd);
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_OPCODE, 0);
 			errsts = check_condition_result;
-			return schedule_resp(SCpnt, devip, done, errsts,
-					     0);
+			return schedule_resp(SCpnt, devip, errsts, 0);
 		}
 	}
 
@@ -3667,7 +4181,7 @@ int scsi_debug_queuecommand_lck(struct s
 		errsts = resp_start_stop(SCpnt, devip);
 		break;
 	case ALLOW_MEDIUM_REMOVAL:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		if (errsts)
 			break;
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -3675,23 +4189,23 @@ int scsi_debug_queuecommand_lck(struct s
 			       cmd[4] ? "inhibited" : "enabled");
 		break;
 	case SEND_DIAGNOSTIC:     /* mandatory */
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case TEST_UNIT_READY:     /* mandatory */
-		delay_override = 1;
-		errsts = check_readiness(SCpnt, 0, devip);
+		/* delay_override = 1; */
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		break;
 	case RESERVE:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case RESERVE_10:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case RELEASE:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case RELEASE_10:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case READ_CAPACITY:
 		errsts = resp_readcap(SCpnt, devip);
@@ -3702,20 +4216,20 @@ int scsi_debug_queuecommand_lck(struct s
 		else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
 			if (scsi_debug_lbp() == 0) {
-				mk_sense_buffer(devip, ILLEGAL_REQUEST,
+				mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 						INVALID_COMMAND_OPCODE, 0);
 				errsts = check_condition_result;
 			} else
 				errsts = resp_get_lba_status(SCpnt, devip);
 		} else {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_OPCODE, 0);
 			errsts = check_condition_result;
 		}
 		break;
 	case MAINTENANCE_IN:
 		if (MI_REPORT_TARGET_PGS != cmd[1]) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_OPCODE, 0);
 			errsts = check_condition_result;
 			break;
@@ -3728,7 +4242,7 @@ int scsi_debug_queuecommand_lck(struct s
 		/* READ{10,12,16} and DIF Type 2 are natural enemies */
 		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    cmd[1] & 0xe0) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
 			break;
@@ -3742,7 +4256,7 @@ int scsi_debug_queuecommand_lck(struct s
 		/* fall through */
 	case READ_6:
 read:
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		if (errsts)
 			break;
 		if (scsi_debug_fake_rw)
@@ -3752,20 +4266,21 @@ read:
 		if (inj_short)
 			num /= 2;
 
-		errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
+		errsts = resp_read(SCpnt, lba, num, ei_lba);
 		if (inj_recovered && (0 == errsts)) {
-			mk_sense_buffer(devip, RECOVERED_ERROR,
+			mk_sense_buffer(SCpnt, RECOVERED_ERROR,
 					THRESHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
 		} else if (inj_transport && (0 == errsts)) {
-			mk_sense_buffer(devip, ABORTED_COMMAND,
+			mk_sense_buffer(SCpnt, ABORTED_COMMAND,
 					TRANSPORT_PROBLEM, ACK_NAK_TO);
 			errsts = check_condition_result;
 		} else if (inj_dif && (0 == errsts)) {
-			mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+			/* Logical block guard check failed */
+			mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
 			errsts = illegal_condition_result;
 		} else if (inj_dix && (0 == errsts)) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
 			errsts = illegal_condition_result;
 		}
 		break;
@@ -3774,7 +4289,7 @@ read:
 		errsts = resp_report_luns(SCpnt, devip);
 		break;
 	case VERIFY:		/* 10 byte SBC-2 command */
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		break;
 	case WRITE_16:
 	case WRITE_12:
@@ -3782,7 +4297,7 @@ read:
 		/* WRITE{10,12,16} and DIF Type 2 are natural enemies */
 		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    cmd[1] & 0xe0) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
 			break;
@@ -3796,22 +4311,22 @@ read:
 		/* fall through */
 	case WRITE_6:
 write:
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		if (errsts)
 			break;
 		if (scsi_debug_fake_rw)
 			break;
 		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-		errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
+		errsts = resp_write(SCpnt, lba, num, ei_lba);
 		if (inj_recovered && (0 == errsts)) {
-			mk_sense_buffer(devip, RECOVERED_ERROR,
+			mk_sense_buffer(SCpnt, RECOVERED_ERROR,
 					THRESHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
 		} else if (inj_dif && (0 == errsts)) {
-			mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+			mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
 			errsts = illegal_condition_result;
 		} else if (inj_dix && (0 == errsts)) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
 			errsts = illegal_condition_result;
 		}
 		break;
@@ -3820,7 +4335,7 @@ write:
 		if (cmd[1] & 0x8) {
 			if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
 			    (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
-				mk_sense_buffer(devip, ILLEGAL_REQUEST,
+				mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 						INVALID_FIELD_IN_CDB, 0);
 				errsts = check_condition_result;
 			} else
@@ -3828,19 +4343,23 @@ write:
 		}
 		if (errsts)
 			break;
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		if (errsts)
 			break;
+		if (scsi_debug_fake_rw)
+			break;
 		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-		errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap);
+		errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap);
 		break;
 	case UNMAP:
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		if (errsts)
 			break;
+		if (scsi_debug_fake_rw)
+			break;
 
 		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
 		} else
@@ -3861,29 +4380,29 @@ write:
 		break;
 	case SYNCHRONIZE_CACHE:
 		delay_override = 1;
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		break;
 	case WRITE_BUFFER:
-		errsts = check_readiness(SCpnt, 1, devip);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		break;
 	case XDWRITEREAD_10:
 		if (!scsi_bidi_cmnd(SCpnt)) {
-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+			mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0);
 			errsts = check_condition_result;
 			break;
 		}
 
-		errsts = check_readiness(SCpnt, 0, devip);
+		errsts = check_readiness(SCpnt, UAS_TUR, devip);
 		if (errsts)
 			break;
 		if (scsi_debug_fake_rw)
 			break;
 		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-		errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
+		errsts = resp_read(SCpnt, lba, num, ei_lba);
 		if (errsts)
 			break;
-		errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
+		errsts = resp_write(SCpnt, lba, num, ei_lba);
 		if (errsts)
 			break;
 		errsts = resp_xdwriteread(SCpnt, lba, num, devip);
@@ -3906,27 +4425,138 @@ write:
 			}
 		}
 
-		mk_sense_buffer(devip, ILLEGAL_REQUEST,
+		mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
 				INVALID_FIELD_IN_CDB, 0);
 		errsts = check_condition_result;
 		break;
-
+	case 0x85:
+		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+			sdev_printk(KERN_INFO, SCpnt->device,
+			"%s: ATA PASS-THROUGH(16) not supported\n", my_name);
+		mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
+				INVALID_OPCODE, 0);
+		errsts = check_condition_result;
+		break;
 	default:
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
-			       "supported\n", *cmd);
-		errsts = check_readiness(SCpnt, 1, devip);
+			sdev_printk(KERN_INFO, SCpnt->device,
+				    "%s: Opcode: 0x%x not supported\n",
+				    my_name, *cmd);
+		errsts = check_readiness(SCpnt, UAS_ONLY, devip);
 		if (errsts)
 			break;	/* Unit attention takes precedence */
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
+		mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
 		errsts = check_condition_result;
 		break;
 	}
-	return schedule_resp(SCpnt, devip, done, errsts,
+	return schedule_resp(SCpnt, devip, errsts,
 			     (delay_override ? 0 : scsi_debug_delay));
 }
 
-static DEF_SCSI_QCMD(scsi_debug_queuecommand)
+static int
+sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+{
+	if (scsi_debug_host_lock) {
+		unsigned long iflags;
+		int rc;
+
+		spin_lock_irqsave(shost->host_lock, iflags);
+		rc = scsi_debug_queuecommand(cmd);
+		spin_unlock_irqrestore(shost->host_lock, iflags);
+		return rc;
+	} else
+		return scsi_debug_queuecommand(cmd);
+}
+
+static int
+sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason)
+{
+	int num_in_q = 0;
+	int bad = 0;
+	unsigned long iflags;
+	struct sdebug_dev_info *devip;
+
+	spin_lock_irqsave(&queued_arr_lock, iflags);
+	devip = (struct sdebug_dev_info *)sdev->hostdata;
+	if (NULL == devip) {
+		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		return	-ENODEV;
+	}
+	num_in_q = atomic_read(&devip->num_in_q);
+	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) {
+		if (qdepth < 1)
+			qdepth = 1;
+		/* allow to exceed max host queued_arr elements for testing */
+		if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
+			qdepth = SCSI_DEBUG_CANQUEUE + 10;
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+	} else if (reason == SCSI_QDEPTH_QFULL)
+		scsi_track_queue_full(sdev, qdepth);
+	else
+		bad = 1;
+	if (bad)
+		sdev_printk(KERN_WARNING, sdev,
+			    "%s: unknown reason=0x%x\n", __func__, reason);
+	if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
+		if (SCSI_QDEPTH_QFULL == reason)
+			sdev_printk(KERN_INFO, sdev,
+			    "%s: -> %d, num_in_q=%d, reason: queue full\n",
+				    __func__, qdepth, num_in_q);
+		else {
+			const char *cp;
+
+			switch (reason) {
+			case SCSI_QDEPTH_DEFAULT:
+				cp = "default (sysfs ?)";
+				break;
+			case SCSI_QDEPTH_RAMP_UP:
+				cp = "ramp up";
+				break;
+			default:
+				cp = "unknown";
+				break;
+			}
+			sdev_printk(KERN_INFO, sdev,
+				    "%s: qdepth=%d, num_in_q=%d, reason: %s\n",
+				    __func__, qdepth, num_in_q, cp);
+		}
+	}
+	return sdev->queue_depth;
+}
+
+static int
+sdebug_change_qtype(struct scsi_device *sdev, int qtype)
+{
+	if (sdev->tagged_supported) {
+		scsi_set_tag_type(sdev, qtype);
+		if (qtype)
+			scsi_activate_tcq(sdev, sdev->queue_depth);
+		else
+			scsi_deactivate_tcq(sdev, sdev->queue_depth);
+	} else
+		qtype = 0;
+	if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
+		const char *cp;
+
+		switch (qtype) {
+		case 0:
+			cp = "untagged";
+			break;
+		case MSG_SIMPLE_TAG:
+			cp = "simple tags";
+			break;
+		case MSG_ORDERED_TAG:
+			cp = "ordered tags";
+			break;
+		default:
+			cp = "unknown";
+			break;
+		}
+		sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp);
+	}
+	return qtype;
+}
 
 static struct scsi_host_template sdebug_driver_template = {
 	.show_info =		scsi_debug_show_info,
@@ -3938,17 +4568,19 @@ static struct scsi_host_template sdebug_
 	.slave_configure =	scsi_debug_slave_configure,
 	.slave_destroy =	scsi_debug_slave_destroy,
 	.ioctl =		scsi_debug_ioctl,
-	.queuecommand =		scsi_debug_queuecommand,
+	.queuecommand =		sdebug_queuecommand_lock_or_not,
+	.change_queue_depth =	sdebug_change_qdepth,
+	.change_queue_type =	sdebug_change_qtype,
 	.eh_abort_handler =	scsi_debug_abort,
-	.eh_bus_reset_handler = scsi_debug_bus_reset,
 	.eh_device_reset_handler = scsi_debug_device_reset,
+	.eh_target_reset_handler = scsi_debug_target_reset,
+	.eh_bus_reset_handler = scsi_debug_bus_reset,
 	.eh_host_reset_handler = scsi_debug_host_reset,
-	.bios_param =		scsi_debug_biosparam,
 	.can_queue =		SCSI_DEBUG_CANQUEUE,
 	.this_id =		7,
-	.sg_tablesize =		256,
-	.cmd_per_lun =		16,
-	.max_sectors =		0xffff,
+	.sg_tablesize =		SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.cmd_per_lun =		DEF_CMD_PER_LUN,
+	.max_sectors =		-1U,
 	.use_clustering = 	DISABLE_CLUSTERING,
 	.module =		THIS_MODULE,
 };
@@ -4032,8 +4664,7 @@ static int sdebug_driver_probe(struct de
         } else
 		scsi_scan_host(hpnt);
 
-
-        return error;
+	return error;
 }
 
 static int sdebug_driver_remove(struct device * dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_devinfo.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_devinfo.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_devinfo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_devinfo.c	2014-09-28 17:29:07.000000000 -0400
@@ -222,6 +222,7 @@ static struct {
 	{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+	{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
 	{"Promise", "", NULL, BLIST_SPARSELUN},
 	{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
 	{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_error.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_error.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_error.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_error.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,11 +59,11 @@ static int scsi_try_to_abort_cmd(struct
 /* called with shost->host_lock held */
 void scsi_eh_wakeup(struct Scsi_Host *shost)
 {
-	if (shost->host_busy == shost->host_failed) {
+	if (atomic_read(&shost->host_busy) == shost->host_failed) {
 		trace_scsi_eh_wakeup(shost);
 		wake_up_process(shost->ehandler);
-		SCSI_LOG_ERROR_RECOVERY(5,
-				printk("Waking error handler thread\n"));
+		SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost,
+			"Waking error handler thread\n"));
 	}
 }
 
@@ -193,7 +193,7 @@ scsi_abort_command(struct scsi_cmnd *scm
 		SCSI_LOG_ERROR_RECOVERY(3,
 			scmd_printk(KERN_INFO, scmd,
 				    "scmd %p previous abort failed\n", scmd));
-		cancel_delayed_work(&scmd->abort_work);
+		BUG_ON(delayed_work_pending(&scmd->abort_work));
 		return FAILED;
 	}
 
@@ -319,8 +319,8 @@ int scsi_block_when_processing_errors(st
 
 	online = scsi_device_online(sdev);
 
-	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __func__,
-					  online));
+	SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_INFO, sdev,
+		"%s: rtn: %d\n", __func__, online));
 
 	return online;
 }
@@ -365,8 +365,9 @@ static inline void scsi_eh_prt_fail_stat
 		}
 	}
 
-	SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d"
-					  " devices require eh work\n",
+	SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost,
+				   "Total of %d commands on %d"
+				   " devices require eh work\n",
 				   total_failures, devices_failed));
 }
 #endif
@@ -738,8 +739,8 @@ static void scsi_eh_done(struct scsi_cmn
 {
 	struct completion *eh_action;
 
-	SCSI_LOG_ERROR_RECOVERY(3,
-		printk("%s scmd: %p result: %x\n",
+	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+			"%s scmd: %p result: %x\n",
 			__func__, scmd, scmd->result));
 
 	eh_action = scmd->device->host->eh_action;
@@ -758,8 +759,8 @@ static int scsi_try_host_reset(struct sc
 	struct Scsi_Host *host = scmd->device->host;
 	struct scsi_host_template *hostt = host->hostt;
 
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
-					  __func__));
+	SCSI_LOG_ERROR_RECOVERY(3,
+		shost_printk(KERN_INFO, host, "Snd Host RST\n"));
 
 	if (!hostt->eh_host_reset_handler)
 		return FAILED;
@@ -788,8 +789,8 @@ static int scsi_try_bus_reset(struct scs
 	struct Scsi_Host *host = scmd->device->host;
 	struct scsi_host_template *hostt = host->hostt;
 
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
-					  __func__));
+	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+		"%s: Snd Bus RST\n", __func__));
 
 	if (!hostt->eh_bus_reset_handler)
 		return FAILED;
@@ -1036,8 +1037,8 @@ retry:
 
 	scsi_log_completion(scmd, rtn);
 
-	SCSI_LOG_ERROR_RECOVERY(3,
-		printk("%s: scmd: %p, timeleft: %ld\n",
+	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+			"%s: scmd: %p, timeleft: %ld\n",
 			__func__, scmd, timeleft));
 
 	/*
@@ -1051,9 +1052,8 @@ retry:
 	 */
 	if (timeleft) {
 		rtn = scsi_eh_completed_normally(scmd);
-		SCSI_LOG_ERROR_RECOVERY(3,
-			printk("%s: scsi_eh_completed_normally %x\n",
-			       __func__, rtn));
+		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+			"%s: scsi_eh_completed_normally %x\n", __func__, rtn));
 
 		switch (rtn) {
 		case SUCCESS:
@@ -1177,9 +1177,9 @@ int scsi_eh_get_sense(struct list_head *
 		if (rtn != SUCCESS)
 			continue;
 
-		SCSI_LOG_ERROR_RECOVERY(3, printk("sense requested for %p"
-						  " result %x\n", scmd,
-						  scmd->result));
+		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+			"sense requested for %p result %x\n",
+			scmd, scmd->result));
 		SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd));
 
 		rtn = scsi_decide_disposition(scmd);
@@ -1220,8 +1220,8 @@ retry_tur:
 	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6,
 				scmd->device->eh_timeout, 0);
 
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
-		__func__, scmd, rtn));
+	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
+		"%s: scmd %p rtn %x\n", __func__, scmd, rtn));
 
 	switch (rtn) {
 	case NEEDS_RETRY:
@@ -1323,16 +1323,16 @@ static int scsi_eh_abort_cmds(struct lis
 					     __func__));
 			return list_empty(work_q);
 		}
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
-						  "0x%p\n", current->comm,
-						  scmd));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: aborting cmd: 0x%p\n",
+				     current->comm, scmd));
 		rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
 		if (rtn == FAILED) {
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
-							  " cmd failed:"
-							  "0x%p\n",
-							  current->comm,
-							  scmd));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				shost_printk(KERN_INFO, shost,
+					     "%s: aborting cmd failed: 0x%p\n",
+					     current->comm, scmd));
 			list_splice_init(&check_list, work_q);
 			return list_empty(work_q);
 		}
@@ -1406,8 +1406,10 @@ static int scsi_eh_stu(struct Scsi_Host
 		if (!stu_scmd)
 			continue;
 
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending START_UNIT to sdev:"
-						  " 0x%p\n", current->comm, sdev));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: Sending START_UNIT to sdev: 0x%p\n",
+				     current->comm, sdev));
 
 		if (!scsi_eh_try_stu(stu_scmd)) {
 			if (!scsi_device_online(sdev) ||
@@ -1421,8 +1423,9 @@ static int scsi_eh_stu(struct Scsi_Host
 			}
 		} else {
 			SCSI_LOG_ERROR_RECOVERY(3,
-						printk("%s: START_UNIT failed to sdev:"
-						       " 0x%p\n", current->comm, sdev));
+				shost_printk(KERN_INFO, shost,
+					     "%s: START_UNIT failed to sdev:"
+					     " 0x%p\n", current->comm, sdev));
 		}
 	}
 
@@ -1468,9 +1471,10 @@ static int scsi_eh_bus_device_reset(stru
 		if (!bdr_scmd)
 			continue;
 
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BDR sdev:"
-						  " 0x%p\n", current->comm,
-						  sdev));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: Sending BDR sdev: 0x%p\n",
+				     current->comm, sdev));
 		rtn = scsi_try_bus_device_reset(bdr_scmd);
 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
 			if (!scsi_device_online(sdev) ||
@@ -1485,11 +1489,10 @@ static int scsi_eh_bus_device_reset(stru
 				}
 			}
 		} else {
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BDR"
-							  " failed sdev:"
-							  "0x%p\n",
-							  current->comm,
-							   sdev));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				shost_printk(KERN_INFO, shost,
+					     "%s: BDR failed sdev: 0x%p\n",
+					     current->comm, sdev));
 		}
 	}
 
@@ -1533,15 +1536,17 @@ static int scsi_eh_target_reset(struct S
 		scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
 		id = scmd_id(scmd);
 
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
-						  "to target %d\n",
-						  current->comm, id));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: Sending target reset to target %d\n",
+				     current->comm, id));
 		rtn = scsi_try_target_reset(scmd);
 		if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
-							  " failed target: "
-							  "%d\n",
-							  current->comm, id));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				shost_printk(KERN_INFO, shost,
+					     "%s: Target reset failed"
+					     " target: %d\n",
+					     current->comm, id));
 		list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
 			if (scmd_id(scmd) != id)
 				continue;
@@ -1605,9 +1610,10 @@ static int scsi_eh_bus_reset(struct Scsi
 
 		if (!chan_scmd)
 			continue;
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BRST chan:"
-						  " %d\n", current->comm,
-						  channel));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: Sending BRST chan: %d\n",
+				     current->comm, channel));
 		rtn = scsi_try_bus_reset(chan_scmd);
 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
 			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
@@ -1621,10 +1627,10 @@ static int scsi_eh_bus_reset(struct Scsi
 				}
 			}
 		} else {
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST"
-							  " failed chan: %d\n",
-							  current->comm,
-							  channel));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				shost_printk(KERN_INFO, shost,
+					     "%s: BRST failed chan: %d\n",
+					     current->comm, channel));
 		}
 	}
 	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
@@ -1635,7 +1641,8 @@ static int scsi_eh_bus_reset(struct Scsi
  * @work_q:	list_head for processed commands.
  * @done_q:	list_head for processed commands.
  */
-static int scsi_eh_host_reset(struct list_head *work_q,
+static int scsi_eh_host_reset(struct Scsi_Host *shost,
+			      struct list_head *work_q,
 			      struct list_head *done_q)
 {
 	struct scsi_cmnd *scmd, *next;
@@ -1646,8 +1653,10 @@ static int scsi_eh_host_reset(struct lis
 		scmd = list_entry(work_q->next,
 				  struct scsi_cmnd, eh_entry);
 
-		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending HRST\n"
-						  , current->comm));
+		SCSI_LOG_ERROR_RECOVERY(3,
+			shost_printk(KERN_INFO, shost,
+				     "%s: Sending HRST\n",
+				     current->comm));
 
 		rtn = scsi_try_host_reset(scmd);
 		if (rtn == SUCCESS) {
@@ -1657,9 +1666,10 @@ static int scsi_eh_host_reset(struct lis
 					scsi_eh_finish_cmd(scmd, done_q);
 			}
 		} else {
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: HRST"
-							  " failed\n",
-							  current->comm));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				shost_printk(KERN_INFO, shost,
+					     "%s: HRST failed\n",
+					     current->comm));
 		}
 	}
 	return scsi_eh_test_devices(&check_list, work_q, done_q, 1);
@@ -1751,9 +1761,8 @@ int scsi_decide_disposition(struct scsi_
 	 * up to the top level.
 	 */
 	if (!scsi_device_online(scmd->device)) {
-		SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report"
-						  " as SUCCESS\n",
-						  __func__));
+		SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd,
+			"%s: device offline - report as SUCCESS\n", __func__));
 		return SUCCESS;
 	}
 
@@ -1999,8 +2008,7 @@ static void scsi_restart_operations(stru
 	 * ioctls to queued block devices.
 	 */
 	SCSI_LOG_ERROR_RECOVERY(3,
-		printk("scsi_eh_%d waking up host to restart\n",
-		       shost->host_no));
+		shost_printk(KERN_INFO, shost, "waking up host to restart\n"));
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (scsi_host_set_state(shost, SHOST_RUNNING))
@@ -2047,7 +2055,7 @@ void scsi_eh_ready_devs(struct Scsi_Host
 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
 			if (!scsi_eh_target_reset(shost, work_q, done_q))
 				if (!scsi_eh_bus_reset(shost, work_q, done_q))
-					if (!scsi_eh_host_reset(work_q, done_q))
+					if (!scsi_eh_host_reset(shost, work_q, done_q))
 						scsi_eh_offline_sdevs(work_q,
 								      done_q);
 }
@@ -2066,10 +2074,10 @@ void scsi_eh_flush_done_q(struct list_he
 		if (scsi_device_online(scmd->device) &&
 		    !scsi_noretry_cmd(scmd) &&
 		    (++scmd->retries <= scmd->allowed)) {
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
-							  " retry cmd: %p\n",
-							  current->comm,
-							  scmd));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				scmd_printk(KERN_INFO, scmd,
+					     "%s: flush retry cmd: %p\n",
+					     current->comm, scmd));
 				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
 		} else {
 			/*
@@ -2079,9 +2087,10 @@ void scsi_eh_flush_done_q(struct list_he
 			 */
 			if (!scmd->result)
 				scmd->result |= (DRIVER_TIMEOUT << 24);
-			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish"
-							" cmd: %p\n",
-							current->comm, scmd));
+			SCSI_LOG_ERROR_RECOVERY(3,
+				scmd_printk(KERN_INFO, scmd,
+					     "%s: flush finish cmd: %p\n",
+					     current->comm, scmd));
 			scsi_finish_command(scmd);
 		}
 	}
@@ -2155,19 +2164,22 @@ int scsi_error_handler(void *data)
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
-		    shost->host_failed != shost->host_busy) {
+		    shost->host_failed != atomic_read(&shost->host_busy)) {
 			SCSI_LOG_ERROR_RECOVERY(1,
-				printk("scsi_eh_%d: sleeping\n",
-					shost->host_no));
+				shost_printk(KERN_INFO, shost,
+					     "scsi_eh_%d: sleeping\n",
+					     shost->host_no));
 			schedule();
 			continue;
 		}
 
 		__set_current_state(TASK_RUNNING);
 		SCSI_LOG_ERROR_RECOVERY(1,
-			printk("scsi_eh_%d: waking up %d/%d/%d\n",
-			       shost->host_no, shost->host_eh_scheduled,
-			       shost->host_failed, shost->host_busy));
+			shost_printk(KERN_INFO, shost,
+				     "scsi_eh_%d: waking up %d/%d/%d\n",
+				     shost->host_no, shost->host_eh_scheduled,
+				     shost->host_failed,
+				     atomic_read(&shost->host_busy)));
 
 		/*
 		 * We have a host that is failing for some reason.  Figure out
@@ -2201,7 +2213,9 @@ int scsi_error_handler(void *data)
 	__set_current_state(TASK_RUNNING);
 
 	SCSI_LOG_ERROR_RECOVERY(1,
-		printk("Error handler scsi_eh_%d exiting\n", shost->host_no));
+		shost_printk(KERN_INFO, shost,
+			     "Error handler scsi_eh_%d exiting\n",
+			     shost->host_no));
 	shost->ehandler = NULL;
 	return 0;
 }
@@ -2362,8 +2376,8 @@ scsi_reset_provider(struct scsi_device *
 	 * suspended while we performed the TMF.
 	 */
 	SCSI_LOG_ERROR_RECOVERY(3,
-		printk("%s: waking up host to restart after TMF\n",
-		__func__));
+		shost_printk(KERN_INFO, shost,
+			     "waking up host to restart after TMF\n"));
 
 	wake_up(&shost->host_wait);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_ioctl.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_ioctl.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -91,12 +91,14 @@ static int ioctl_internal_command(struct
 	int result;
 	struct scsi_sense_hdr sshdr;
 
-	SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
+	SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev,
+				      "Trying ioctl with scsi command %d\n", *cmd));
 
 	result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0,
 				  &sshdr, timeout, retries, NULL);
 
-	SCSI_LOG_IOCTL(2, printk("Ioctl returned  0x%x\n", result));
+	SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
+				      "Ioctl returned  0x%x\n", result));
 
 	if ((driver_byte(result) & DRIVER_SENSE) &&
 	    (scsi_sense_valid(&sshdr))) {
@@ -105,9 +107,11 @@ static int ioctl_internal_command(struct
 			if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
 				sdev->lockable = 0;
 			else
-				printk(KERN_INFO "ioctl_internal_command: "
-				       "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n",
-				       sshdr.asc, sshdr.ascq);
+				sdev_printk(KERN_INFO, sdev,
+					    "ioctl_internal_command: "
+					    "ILLEGAL REQUEST "
+					    "asc=0x%x ascq=0x%x\n",
+					    sshdr.asc, sshdr.ascq);
 			break;
 		case NOT_READY:	/* This happens if there is no disc in drive */
 			if (sdev->removable)
@@ -127,7 +131,8 @@ static int ioctl_internal_command(struct
 		}
 	}
 
-	SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n"));
+	SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
+				      "IOCTL Releasing command\n"));
 	return result;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_lib.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_lib.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,6 @@
 /*
- *  scsi_lib.c Copyright (C) 1999 Eric Youngdale
+ * Copyright (C) 1999 Eric Youngdale
+ * Copyright (C) 2014 Christoph Hellwig
  *
  *  SCSI queueing library.
  *      Initial versions: Eric Youngdale (eric@andante.org).
@@ -20,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/hardirq.h>
 #include <linux/scatterlist.h>
+#include <linux/blk-mq.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -29,6 +31,8 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 
+#include <trace/events/scsi.h>
+
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
@@ -75,28 +79,12 @@ struct kmem_cache *scsi_sdb_cache;
  */
 #define SCSI_QUEUE_DELAY	3
 
-/**
- * __scsi_queue_insert - private queue insertion
- * @cmd: The SCSI command being requeued
- * @reason:  The reason for the requeue
- * @unbusy: Whether the queue should be unbusied
- *
- * This is a private queue insertion.  The public interface
- * scsi_queue_insert() always assumes the queue should be unbusied
- * because it's always called before the completion.  This function is
- * for a requeue after completion, which should only occur in this
- * file.
- */
-static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
+static void
+scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
 {
 	struct Scsi_Host *host = cmd->device->host;
 	struct scsi_device *device = cmd->device;
 	struct scsi_target *starget = scsi_target(device);
-	struct request_queue *q = device->request_queue;
-	unsigned long flags;
-
-	SCSI_LOG_MLQUEUE(1,
-		 printk("Inserting command %p into mlqueue\n", cmd));
 
 	/*
 	 * Set the appropriate busy bit for the device/host.
@@ -113,16 +101,52 @@ static void __scsi_queue_insert(struct s
 	 */
 	switch (reason) {
 	case SCSI_MLQUEUE_HOST_BUSY:
-		host->host_blocked = host->max_host_blocked;
+		atomic_set(&host->host_blocked, host->max_host_blocked);
 		break;
 	case SCSI_MLQUEUE_DEVICE_BUSY:
 	case SCSI_MLQUEUE_EH_RETRY:
-		device->device_blocked = device->max_device_blocked;
+		atomic_set(&device->device_blocked,
+			   device->max_device_blocked);
 		break;
 	case SCSI_MLQUEUE_TARGET_BUSY:
-		starget->target_blocked = starget->max_target_blocked;
+		atomic_set(&starget->target_blocked,
+			   starget->max_target_blocked);
 		break;
 	}
+}
+
+static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
+{
+	struct scsi_device *sdev = cmd->device;
+	struct request_queue *q = cmd->request->q;
+
+	blk_mq_requeue_request(cmd->request);
+	blk_mq_kick_requeue_list(q);
+	put_device(&sdev->sdev_gendev);
+}
+
+/**
+ * __scsi_queue_insert - private queue insertion
+ * @cmd: The SCSI command being requeued
+ * @reason:  The reason for the requeue
+ * @unbusy: Whether the queue should be unbusied
+ *
+ * This is a private queue insertion.  The public interface
+ * scsi_queue_insert() always assumes the queue should be unbusied
+ * because it's always called before the completion.  This function is
+ * for a requeue after completion, which should only occur in this
+ * file.
+ */
+static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
+{
+	struct scsi_device *device = cmd->device;
+	struct request_queue *q = device->request_queue;
+	unsigned long flags;
+
+	SCSI_LOG_MLQUEUE(1, scmd_printk(KERN_INFO, cmd,
+		"Inserting command %p into mlqueue\n", cmd));
+
+	scsi_set_blocked(cmd, reason);
 
 	/*
 	 * Decrement the counters, since these commands are no longer
@@ -138,6 +162,10 @@ static void __scsi_queue_insert(struct s
 	 * before blk_cleanup_queue() finishes.
 	 */
 	cmd->result = 0;
+	if (q->mq_ops) {
+		scsi_mq_requeue_cmd(cmd);
+		return;
+	}
 	spin_lock_irqsave(q->queue_lock, flags);
 	blk_requeue_request(q, cmd->request);
 	kblockd_schedule_work(&device->requeue_work);
@@ -282,16 +310,26 @@ void scsi_device_unbusy(struct scsi_devi
 	struct scsi_target *starget = scsi_target(sdev);
 	unsigned long flags;
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	shost->host_busy--;
-	starget->target_busy--;
+	atomic_dec(&shost->host_busy);
+	if (starget->can_queue > 0)
+		atomic_dec(&starget->target_busy);
+
 	if (unlikely(scsi_host_in_recovery(shost) &&
-		     (shost->host_failed || shost->host_eh_scheduled)))
+		     (shost->host_failed || shost->host_eh_scheduled))) {
+		spin_lock_irqsave(shost->host_lock, flags);
 		scsi_eh_wakeup(shost);
-	spin_unlock(shost->host_lock);
-	spin_lock(sdev->request_queue->queue_lock);
-	sdev->device_busy--;
-	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+		spin_unlock_irqrestore(shost->host_lock, flags);
+	}
+
+	atomic_dec(&sdev->device_busy);
+}
+
+static void scsi_kick_queue(struct request_queue *q)
+{
+	if (q->mq_ops)
+		blk_mq_start_hw_queues(q);
+	else
+		blk_run_queue(q);
 }
 
 /*
@@ -318,7 +356,7 @@ static void scsi_single_lun_run(struct s
 	 * but in most cases, we will be first. Ideally, each LU on the
 	 * target would get some limited time or requests on the target.
 	 */
-	blk_run_queue(current_sdev->request_queue);
+	scsi_kick_queue(current_sdev->request_queue);
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (starget->starget_sdev_user)
@@ -331,7 +369,7 @@ static void scsi_single_lun_run(struct s
 			continue;
 
 		spin_unlock_irqrestore(shost->host_lock, flags);
-		blk_run_queue(sdev->request_queue);
+		scsi_kick_queue(sdev->request_queue);
 		spin_lock_irqsave(shost->host_lock, flags);
 	
 		scsi_device_put(sdev);
@@ -340,28 +378,36 @@ static void scsi_single_lun_run(struct s
 	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
-static inline int scsi_device_is_busy(struct scsi_device *sdev)
+static inline bool scsi_device_is_busy(struct scsi_device *sdev)
 {
-	if (sdev->device_busy >= sdev->queue_depth || sdev->device_blocked)
-		return 1;
-
-	return 0;
+	if (atomic_read(&sdev->device_busy) >= sdev->queue_depth)
+		return true;
+	if (atomic_read(&sdev->device_blocked) > 0)
+		return true;
+	return false;
 }
 
-static inline int scsi_target_is_busy(struct scsi_target *starget)
+static inline bool scsi_target_is_busy(struct scsi_target *starget)
 {
-	return ((starget->can_queue > 0 &&
-		 starget->target_busy >= starget->can_queue) ||
-		 starget->target_blocked);
+	if (starget->can_queue > 0) {
+		if (atomic_read(&starget->target_busy) >= starget->can_queue)
+			return true;
+		if (atomic_read(&starget->target_blocked) > 0)
+			return true;
+	}
+	return false;
 }
 
-static inline int scsi_host_is_busy(struct Scsi_Host *shost)
+static inline bool scsi_host_is_busy(struct Scsi_Host *shost)
 {
-	if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) ||
-	    shost->host_blocked || shost->host_self_blocked)
-		return 1;
-
-	return 0;
+	if (shost->can_queue > 0 &&
+	    atomic_read(&shost->host_busy) >= shost->can_queue)
+		return true;
+	if (atomic_read(&shost->host_blocked) > 0)
+		return true;
+	if (shost->host_self_blocked)
+		return true;
+	return false;
 }
 
 static void scsi_starved_list_run(struct Scsi_Host *shost)
@@ -413,7 +459,7 @@ static void scsi_starved_list_run(struct
 			continue;
 		spin_unlock_irqrestore(shost->host_lock, flags);
 
-		blk_run_queue(slq);
+		scsi_kick_queue(slq);
 		blk_put_queue(slq);
 
 		spin_lock_irqsave(shost->host_lock, flags);
@@ -444,7 +490,10 @@ static void scsi_run_queue(struct reques
 	if (!list_empty(&sdev->host->starved_list))
 		scsi_starved_list_run(sdev->host);
 
-	blk_run_queue(q);
+	if (q->mq_ops)
+		blk_mq_start_stopped_hw_queues(q, false);
+	else
+		blk_run_queue(q);
 }
 
 void scsi_requeue_run_queue(struct work_struct *work)
@@ -542,25 +591,70 @@ static struct scatterlist *scsi_sg_alloc
 	return mempool_alloc(sgp->pool, gfp_mask);
 }
 
+static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
+{
+	if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS)
+		return;
+	__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
+}
+
 static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
-			      gfp_t gfp_mask)
+			      gfp_t gfp_mask, bool mq)
 {
+	struct scatterlist *first_chunk = NULL;
 	int ret;
 
 	BUG_ON(!nents);
 
+	if (mq) {
+		if (nents <= SCSI_MAX_SG_SEGMENTS) {
+			sdb->table.nents = nents;
+			sg_init_table(sdb->table.sgl, sdb->table.nents);
+			return 0;
+		}
+		first_chunk = sdb->table.sgl;
+	}
+
 	ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS,
-			       gfp_mask, scsi_sg_alloc);
+			       first_chunk, gfp_mask, scsi_sg_alloc);
 	if (unlikely(ret))
-		__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS,
-				scsi_sg_free);
-
+		scsi_free_sgtable(sdb, mq);
 	return ret;
 }
 
-static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
+static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
 {
-	__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
+	if (cmd->request->cmd_type == REQ_TYPE_FS) {
+		struct scsi_driver *drv = scsi_cmd_to_driver(cmd);
+
+		if (drv->uninit_command)
+			drv->uninit_command(cmd);
+	}
+}
+
+static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd)
+{
+	if (cmd->sdb.table.nents)
+		scsi_free_sgtable(&cmd->sdb, true);
+	if (cmd->request->next_rq && cmd->request->next_rq->special)
+		scsi_free_sgtable(cmd->request->next_rq->special, true);
+	if (scsi_prot_sg_count(cmd))
+		scsi_free_sgtable(cmd->prot_sdb, true);
+}
+
+static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
+{
+	struct scsi_device *sdev = cmd->device;
+	unsigned long flags;
+
+	BUG_ON(list_empty(&cmd->list));
+
+	scsi_mq_free_sgtables(cmd);
+	scsi_uninit_cmd(cmd);
+
+	spin_lock_irqsave(&sdev->list_lock, flags);
+	list_del_init(&cmd->list);
+	spin_unlock_irqrestore(&sdev->list_lock, flags);
 }
 
 /*
@@ -579,27 +673,80 @@ static void scsi_free_sgtable(struct scs
  *		the __init_io() function.  Primarily this would involve
  *		the scatter-gather table.
  */
-void scsi_release_buffers(struct scsi_cmnd *cmd)
+static void scsi_release_buffers(struct scsi_cmnd *cmd)
 {
 	if (cmd->sdb.table.nents)
-		scsi_free_sgtable(&cmd->sdb);
+		scsi_free_sgtable(&cmd->sdb, false);
 
 	memset(&cmd->sdb, 0, sizeof(cmd->sdb));
 
 	if (scsi_prot_sg_count(cmd))
-		scsi_free_sgtable(cmd->prot_sdb);
+		scsi_free_sgtable(cmd->prot_sdb, false);
 }
-EXPORT_SYMBOL(scsi_release_buffers);
 
 static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd)
 {
 	struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special;
 
-	scsi_free_sgtable(bidi_sdb);
+	scsi_free_sgtable(bidi_sdb, false);
 	kmem_cache_free(scsi_sdb_cache, bidi_sdb);
 	cmd->request->next_rq->special = NULL;
 }
 
+static bool scsi_end_request(struct request *req, int error,
+		unsigned int bytes, unsigned int bidi_bytes)
+{
+	struct scsi_cmnd *cmd = req->special;
+	struct scsi_device *sdev = cmd->device;
+	struct request_queue *q = sdev->request_queue;
+
+	if (blk_update_request(req, error, bytes))
+		return true;
+
+	/* Bidi request must be completed as a whole */
+	if (unlikely(bidi_bytes) &&
+	    blk_update_request(req->next_rq, error, bidi_bytes))
+		return true;
+
+	if (blk_queue_add_random(q))
+		add_disk_randomness(req->rq_disk);
+
+	if (req->mq_ctx) {
+		/*
+		 * In the MQ case the command gets freed by __blk_mq_end_io,
+		 * so we have to do all cleanup that depends on it earlier.
+		 *
+		 * We also can't kick the queues from irq context, so we
+		 * will have to defer it to a workqueue.
+		 */
+		scsi_mq_uninit_cmd(cmd);
+
+		__blk_mq_end_io(req, error);
+
+		if (scsi_target(sdev)->single_lun ||
+		    !list_empty(&sdev->host->starved_list))
+			kblockd_schedule_work(&sdev->requeue_work);
+		else
+			blk_mq_start_stopped_hw_queues(q, true);
+
+		put_device(&sdev->sdev_gendev);
+	} else {
+		unsigned long flags;
+
+		if (bidi_bytes)
+			scsi_release_bidi_buffers(cmd);
+
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_finish_request(req, error);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
+		scsi_release_buffers(cmd);
+		scsi_next_command(cmd);
+	}
+
+	return false;
+}
+
 /**
  * __scsi_error_from_host_byte - translate SCSI error code into errno
  * @cmd:	SCSI command (unused)
@@ -672,7 +819,7 @@ static int __scsi_error_from_host_byte(s
  *		   be put back on the queue and retried using the same
  *		   command as before, possibly after a delay.
  *
- *		c) We can call blk_end_request() with -EIO to fail
+ *		c) We can call scsi_end_request() with -EIO to fail
  *		   the remainder of the request.
  */
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
@@ -686,7 +833,6 @@ void scsi_io_completion(struct scsi_cmnd
 	int sense_deferred = 0;
 	enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
 	      ACTION_DELAYED_RETRY} action;
-	char *description = NULL;
 	unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
 
 	if (result) {
@@ -724,13 +870,9 @@ void scsi_io_completion(struct scsi_cmnd
 			 * both sides at once.
 			 */
 			req->next_rq->resid_len = scsi_in(cmd)->resid;
-
-			scsi_release_buffers(cmd);
-			scsi_release_bidi_buffers(cmd);
-
-			blk_end_request_all(req, 0);
-
-			scsi_next_command(cmd);
+			if (scsi_end_request(req, 0, blk_rq_bytes(req),
+					blk_rq_bytes(req->next_rq)))
+				BUG();
 			return;
 		}
 	} else if (blk_rq_bytes(req) == 0 && result && !sense_deferred) {
@@ -750,9 +892,9 @@ void scsi_io_completion(struct scsi_cmnd
 	 * Next deal with any sectors which we were able to correctly
 	 * handle.
 	 */
-	SCSI_LOG_HLCOMPLETE(1, printk("%u sectors total, "
-				      "%d bytes done.\n",
-				      blk_rq_sectors(req), good_bytes));
+	SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, cmd,
+		"%u sectors total, %d bytes done.\n",
+		blk_rq_sectors(req), good_bytes));
 
 	/*
 	 * Recovered errors need reporting, but they're always treated
@@ -777,15 +919,16 @@ void scsi_io_completion(struct scsi_cmnd
 	/*
 	 * If we finished all bytes in the request we are done now.
 	 */
-	if (!blk_end_request(req, error, good_bytes))
-		goto next_command;
+	if (!scsi_end_request(req, error, good_bytes, 0))
+		return;
 
 	/*
 	 * Kill remainder if no retrys.
 	 */
 	if (error && scsi_noretry_cmd(cmd)) {
-		blk_end_request_all(req, error);
-		goto next_command;
+		if (scsi_end_request(req, error, blk_rq_bytes(req), 0))
+			BUG();
+		return;
 	}
 
 	/*
@@ -811,7 +954,6 @@ void scsi_io_completion(struct scsi_cmnd
 				 * and quietly refuse further access.
 				 */
 				cmd->device->changed = 1;
-				description = "Media Changed";
 				action = ACTION_FAIL;
 			} else {
 				/* Must have been a power glitch, or a
@@ -839,27 +981,10 @@ void scsi_io_completion(struct scsi_cmnd
 				cmd->device->use_10_for_rw = 0;
 				action = ACTION_REPREP;
 			} else if (sshdr.asc == 0x10) /* DIX */ {
-				description = "Host Data Integrity Failure";
 				action = ACTION_FAIL;
 				error = -EILSEQ;
 			/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
 			} else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
-				switch (cmd->cmnd[0]) {
-				case UNMAP:
-					description = "Discard failure";
-					break;
-				case WRITE_SAME:
-				case WRITE_SAME_16:
-					if (cmd->cmnd[1] & 0x8)
-						description = "Discard failure";
-					else
-						description =
-							"Write same failure";
-					break;
-				default:
-					description = "Invalid command failure";
-					break;
-				}
 				action = ACTION_FAIL;
 				error = -EREMOTEIO;
 			} else
@@ -867,10 +992,8 @@ void scsi_io_completion(struct scsi_cmnd
 			break;
 		case ABORTED_COMMAND:
 			action = ACTION_FAIL;
-			if (sshdr.asc == 0x10) { /* DIF */
-				description = "Target Data Integrity Failure";
+			if (sshdr.asc == 0x10) /* DIF */
 				error = -EILSEQ;
-			}
 			break;
 		case NOT_READY:
 			/* If the device is in the process of becoming
@@ -889,57 +1012,52 @@ void scsi_io_completion(struct scsi_cmnd
 					action = ACTION_DELAYED_RETRY;
 					break;
 				default:
-					description = "Device not ready";
 					action = ACTION_FAIL;
 					break;
 				}
-			} else {
-				description = "Device not ready";
+			} else
 				action = ACTION_FAIL;
-			}
 			break;
 		case VOLUME_OVERFLOW:
 			/* See SSC3rXX or current. */
 			action = ACTION_FAIL;
 			break;
 		default:
-			description = "Unhandled sense code";
 			action = ACTION_FAIL;
 			break;
 		}
-	} else {
-		description = "Unhandled error code";
+	} else
 		action = ACTION_FAIL;
-	}
 
 	if (action != ACTION_FAIL &&
-	    time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+	    time_before(cmd->jiffies_at_alloc + wait_for, jiffies))
 		action = ACTION_FAIL;
-		description = "Command timed out";
-	}
 
 	switch (action) {
 	case ACTION_FAIL:
 		/* Give up and fail the remainder of the request */
 		if (!(req->cmd_flags & REQ_QUIET)) {
-			if (description)
-				scmd_printk(KERN_INFO, cmd, "%s\n",
-					    description);
 			scsi_print_result(cmd);
 			if (driver_byte(result) & DRIVER_SENSE)
 				scsi_print_sense("", cmd);
 			scsi_print_command(cmd);
 		}
-		if (!blk_end_request_err(req, error))
-			goto next_command;
+		if (!scsi_end_request(req, error, blk_rq_err_bytes(req), 0))
+			return;
 		/*FALLTHRU*/
 	case ACTION_REPREP:
 	requeue:
 		/* Unprep the request and put it back at the head of the queue.
 		 * A new command will be prepared and issued.
 		 */
-		scsi_release_buffers(cmd);
-		scsi_requeue_command(q, cmd);
+		if (q->mq_ops) {
+			cmd->request->cmd_flags &= ~REQ_DONTPREP;
+			scsi_mq_uninit_cmd(cmd);
+			scsi_mq_requeue_cmd(cmd);
+		} else {
+			scsi_release_buffers(cmd);
+			scsi_requeue_command(q, cmd);
+		}
 		break;
 	case ACTION_RETRY:
 		/* Retry the same command immediately */
@@ -950,11 +1068,6 @@ void scsi_io_completion(struct scsi_cmnd
 		__scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0);
 		break;
 	}
-	return;
-
-next_command:
-	scsi_release_buffers(cmd);
-	scsi_next_command(cmd);
 }
 
 static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
@@ -966,9 +1079,8 @@ static int scsi_init_sgtable(struct requ
 	 * If sg table allocation fails, requeue request later.
 	 */
 	if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments,
-					gfp_mask))) {
+					gfp_mask, req->mq_ctx != NULL)))
 		return BLKPREP_DEFER;
-	}
 
 	/* 
 	 * Next, walk the list, and fill in the addresses and sizes of
@@ -996,21 +1108,29 @@ int scsi_init_io(struct scsi_cmnd *cmd,
 {
 	struct scsi_device *sdev = cmd->device;
 	struct request *rq = cmd->request;
+	bool is_mq = (rq->mq_ctx != NULL);
+	int error;
 
-	int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
+	BUG_ON(!rq->nr_phys_segments);
+
+	error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
 	if (error)
 		goto err_exit;
 
 	if (blk_bidi_rq(rq)) {
-		struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc(
-			scsi_sdb_cache, GFP_ATOMIC);
-		if (!bidi_sdb) {
-			error = BLKPREP_DEFER;
-			goto err_exit;
+		if (!rq->q->mq_ops) {
+			struct scsi_data_buffer *bidi_sdb =
+				kmem_cache_zalloc(scsi_sdb_cache, GFP_ATOMIC);
+			if (!bidi_sdb) {
+				error = BLKPREP_DEFER;
+				goto err_exit;
+			}
+
+			rq->next_rq->special = bidi_sdb;
 		}
 
-		rq->next_rq->special = bidi_sdb;
-		error = scsi_init_sgtable(rq->next_rq, bidi_sdb, GFP_ATOMIC);
+		error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special,
+					  GFP_ATOMIC);
 		if (error)
 			goto err_exit;
 	}
@@ -1022,7 +1142,7 @@ int scsi_init_io(struct scsi_cmnd *cmd,
 		BUG_ON(prot_sdb == NULL);
 		ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio);
 
-		if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) {
+		if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask, is_mq)) {
 			error = BLKPREP_DEFER;
 			goto err_exit;
 		}
@@ -1036,13 +1156,16 @@ int scsi_init_io(struct scsi_cmnd *cmd,
 		cmd->prot_sdb->table.nents = count;
 	}
 
-	return BLKPREP_OK ;
-
+	return BLKPREP_OK;
 err_exit:
-	scsi_release_buffers(cmd);
-	cmd->request->special = NULL;
-	scsi_put_command(cmd);
-	put_device(&sdev->sdev_gendev);
+	if (is_mq) {
+		scsi_mq_free_sgtables(cmd);
+	} else {
+		scsi_release_buffers(cmd);
+		cmd->request->special = NULL;
+		scsi_put_command(cmd);
+		put_device(&sdev->sdev_gendev);
+	}
 	return error;
 }
 EXPORT_SYMBOL(scsi_init_io);
@@ -1077,7 +1200,7 @@ static struct scsi_cmnd *scsi_get_cmd_fr
 	return cmd;
 }
 
-int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
+static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 {
 	struct scsi_cmnd *cmd = req->special;
 
@@ -1088,11 +1211,7 @@ int scsi_setup_blk_pc_cmnd(struct scsi_d
 	 * submit a request without an attached bio.
 	 */
 	if (req->bio) {
-		int ret;
-
-		BUG_ON(!req->nr_phys_segments);
-
-		ret = scsi_init_io(cmd, GFP_ATOMIC);
+		int ret = scsi_init_io(cmd, GFP_ATOMIC);
 		if (unlikely(ret))
 			return ret;
 	} else {
@@ -1102,25 +1221,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_d
 	}
 
 	cmd->cmd_len = req->cmd_len;
-	if (!blk_rq_bytes(req))
-		cmd->sc_data_direction = DMA_NONE;
-	else if (rq_data_dir(req) == WRITE)
-		cmd->sc_data_direction = DMA_TO_DEVICE;
-	else
-		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
 	cmd->transfersize = blk_rq_bytes(req);
 	cmd->allowed = req->retries;
 	return BLKPREP_OK;
 }
-EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd);
 
 /*
- * Setup a REQ_TYPE_FS command.  These are simple read/write request
- * from filesystems that still need to be translated to SCSI CDBs from
- * the ULD.
+ * Setup a REQ_TYPE_FS command.  These are simple request from filesystems
+ * that still need to be translated to SCSI CDBs from the ULD.
  */
-int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
+static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 {
 	struct scsi_cmnd *cmd = req->special;
 
@@ -1131,15 +1241,30 @@ int scsi_setup_fs_cmnd(struct scsi_devic
 			return ret;
 	}
 
-	/*
-	 * Filesystem requests must transfer data.
-	 */
-	BUG_ON(!req->nr_phys_segments);
-
 	memset(cmd->cmnd, 0, BLK_MAX_CDB);
-	return scsi_init_io(cmd, GFP_ATOMIC);
+	return scsi_cmd_to_driver(cmd)->init_command(cmd);
+}
+
+static int scsi_setup_cmnd(struct scsi_device *sdev, struct request *req)
+{
+	struct scsi_cmnd *cmd = req->special;
+
+	if (!blk_rq_bytes(req))
+		cmd->sc_data_direction = DMA_NONE;
+	else if (rq_data_dir(req) == WRITE)
+		cmd->sc_data_direction = DMA_TO_DEVICE;
+	else
+		cmd->sc_data_direction = DMA_FROM_DEVICE;
+
+	switch (req->cmd_type) {
+	case REQ_TYPE_FS:
+		return scsi_setup_fs_cmnd(sdev, req);
+	case REQ_TYPE_BLOCK_PC:
+		return scsi_setup_blk_pc_cmnd(sdev, req);
+	default:
+		return BLKPREP_KILL;
+	}
 }
-EXPORT_SYMBOL(scsi_setup_fs_cmnd);
 
 static int
 scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
@@ -1218,7 +1343,7 @@ scsi_prep_return(struct request_queue *q
 		 * queue must be restarted, so we schedule a callback to happen
 		 * shortly.
 		 */
-		if (sdev->device_busy == 0)
+		if (atomic_read(&sdev->device_busy) == 0)
 			blk_delay_queue(q, SCSI_QUEUE_DELAY);
 		break;
 	default:
@@ -1244,26 +1369,14 @@ static int scsi_prep_fn(struct request_q
 		goto out;
 	}
 
-	if (req->cmd_type == REQ_TYPE_FS)
-		ret = scsi_cmd_to_driver(cmd)->init_command(cmd);
-	else if (req->cmd_type == REQ_TYPE_BLOCK_PC)
-		ret = scsi_setup_blk_pc_cmnd(sdev, req);
-	else
-		ret = BLKPREP_KILL;
-
+	ret = scsi_setup_cmnd(sdev, req);
 out:
 	return scsi_prep_return(q, req, ret);
 }
 
 static void scsi_unprep_fn(struct request_queue *q, struct request *req)
 {
-	if (req->cmd_type == REQ_TYPE_FS) {
-		struct scsi_cmnd *cmd = req->special;
-		struct scsi_driver *drv = scsi_cmd_to_driver(cmd);
-
-		if (drv->uninit_command)
-			drv->uninit_command(cmd);
-	}
+	scsi_uninit_cmd(req->special);
 }
 
 /*
@@ -1275,99 +1388,144 @@ static void scsi_unprep_fn(struct reques
 static inline int scsi_dev_queue_ready(struct request_queue *q,
 				  struct scsi_device *sdev)
 {
-	if (sdev->device_busy == 0 && sdev->device_blocked) {
+	unsigned int busy;
+
+	busy = atomic_inc_return(&sdev->device_busy) - 1;
+	if (atomic_read(&sdev->device_blocked)) {
+		if (busy)
+			goto out_dec;
+
 		/*
 		 * unblock after device_blocked iterates to zero
 		 */
-		if (--sdev->device_blocked == 0) {
-			SCSI_LOG_MLQUEUE(3,
-				   sdev_printk(KERN_INFO, sdev,
-				   "unblocking device at zero depth\n"));
-		} else {
-			blk_delay_queue(q, SCSI_QUEUE_DELAY);
-			return 0;
+		if (atomic_dec_return(&sdev->device_blocked) > 0) {
+			/*
+			 * For the MQ case we take care of this in the caller.
+			 */
+			if (!q->mq_ops)
+				blk_delay_queue(q, SCSI_QUEUE_DELAY);
+			goto out_dec;
 		}
+		SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev,
+				   "unblocking device at zero depth\n"));
 	}
-	if (scsi_device_is_busy(sdev))
-		return 0;
+
+	if (busy >= sdev->queue_depth)
+		goto out_dec;
 
 	return 1;
+out_dec:
+	atomic_dec(&sdev->device_busy);
+	return 0;
 }
 
-
 /*
  * scsi_target_queue_ready: checks if there we can send commands to target
  * @sdev: scsi device on starget to check.
- *
- * Called with the host lock held.
  */
 static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
 					   struct scsi_device *sdev)
 {
 	struct scsi_target *starget = scsi_target(sdev);
+	unsigned int busy;
 
 	if (starget->single_lun) {
+		spin_lock_irq(shost->host_lock);
 		if (starget->starget_sdev_user &&
-		    starget->starget_sdev_user != sdev)
+		    starget->starget_sdev_user != sdev) {
+			spin_unlock_irq(shost->host_lock);
 			return 0;
+		}
 		starget->starget_sdev_user = sdev;
+		spin_unlock_irq(shost->host_lock);
 	}
 
-	if (starget->target_busy == 0 && starget->target_blocked) {
+	if (starget->can_queue <= 0)
+		return 1;
+
+	busy = atomic_inc_return(&starget->target_busy) - 1;
+	if (atomic_read(&starget->target_blocked) > 0) {
+		if (busy)
+			goto starved;
+
 		/*
 		 * unblock after target_blocked iterates to zero
 		 */
-		if (--starget->target_blocked == 0) {
-			SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
-					 "unblocking target at zero depth\n"));
-		} else
-			return 0;
-	}
+		if (atomic_dec_return(&starget->target_blocked) > 0)
+			goto out_dec;
 
-	if (scsi_target_is_busy(starget)) {
-		list_move_tail(&sdev->starved_entry, &shost->starved_list);
-		return 0;
+		SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
+				 "unblocking target at zero depth\n"));
 	}
 
+	if (busy >= starget->can_queue)
+		goto starved;
+
 	return 1;
+
+starved:
+	spin_lock_irq(shost->host_lock);
+	list_move_tail(&sdev->starved_entry, &shost->starved_list);
+	spin_unlock_irq(shost->host_lock);
+out_dec:
+	if (starget->can_queue > 0)
+		atomic_dec(&starget->target_busy);
+	return 0;
 }
 
 /*
  * scsi_host_queue_ready: if we can send requests to shost, return 1 else
  * return 0. We must end up running the queue again whenever 0 is
  * returned, else IO can hang.
- *
- * Called with host_lock held.
  */
 static inline int scsi_host_queue_ready(struct request_queue *q,
 				   struct Scsi_Host *shost,
 				   struct scsi_device *sdev)
 {
+	unsigned int busy;
+
 	if (scsi_host_in_recovery(shost))
 		return 0;
-	if (shost->host_busy == 0 && shost->host_blocked) {
+
+	busy = atomic_inc_return(&shost->host_busy) - 1;
+	if (atomic_read(&shost->host_blocked) > 0) {
+		if (busy)
+			goto starved;
+
 		/*
 		 * unblock after host_blocked iterates to zero
 		 */
-		if (--shost->host_blocked == 0) {
-			SCSI_LOG_MLQUEUE(3,
-				printk("scsi%d unblocking host at zero depth\n",
-					shost->host_no));
-		} else {
-			return 0;
-		}
-	}
-	if (scsi_host_is_busy(shost)) {
-		if (list_empty(&sdev->starved_entry))
-			list_add_tail(&sdev->starved_entry, &shost->starved_list);
-		return 0;
+		if (atomic_dec_return(&shost->host_blocked) > 0)
+			goto out_dec;
+
+		SCSI_LOG_MLQUEUE(3,
+			shost_printk(KERN_INFO, shost,
+				     "unblocking host at zero depth\n"));
 	}
 
+	if (shost->can_queue > 0 && busy >= shost->can_queue)
+		goto starved;
+	if (shost->host_self_blocked)
+		goto starved;
+
 	/* We're OK to process the command, so we can't be starved */
-	if (!list_empty(&sdev->starved_entry))
-		list_del_init(&sdev->starved_entry);
+	if (!list_empty(&sdev->starved_entry)) {
+		spin_lock_irq(shost->host_lock);
+		if (!list_empty(&sdev->starved_entry))
+			list_del_init(&sdev->starved_entry);
+		spin_unlock_irq(shost->host_lock);
+	}
 
 	return 1;
+
+starved:
+	spin_lock_irq(shost->host_lock);
+	if (list_empty(&sdev->starved_entry))
+		list_add_tail(&sdev->starved_entry, &shost->starved_list);
+	spin_unlock_irq(shost->host_lock);
+out_dec:
+	atomic_dec(&shost->host_busy);
+	return 0;
 }
 
 /*
@@ -1430,13 +1588,10 @@ static void scsi_kill_request(struct req
 	 * bump busy counts.  To bump the counters, we need to dance
 	 * with the locks as normal issue path does.
 	 */
-	sdev->device_busy++;
-	spin_unlock(sdev->request_queue->queue_lock);
-	spin_lock(shost->host_lock);
-	shost->host_busy++;
-	starget->target_busy++;
-	spin_unlock(shost->host_lock);
-	spin_lock(sdev->request_queue->queue_lock);
+	atomic_inc(&sdev->device_busy);
+	atomic_inc(&shost->host_busy);
+	if (starget->can_queue > 0)
+		atomic_inc(&starget->target_busy);
 
 	blk_complete_request(req);
 }
@@ -1461,7 +1616,7 @@ static void scsi_softirq_done(struct req
 			    wait_for/HZ);
 		disposition = SUCCESS;
 	}
-			
+
 	scsi_log_completion(cmd, disposition);
 
 	switch (disposition) {
@@ -1480,6 +1635,23 @@ static void scsi_softirq_done(struct req
 	}
 }
 
+/**
+ * scsi_done - Invoke completion on finished SCSI command.
+ * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
+ * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
+ *
+ * Description: This function is the mid-level's (SCSI Core) interrupt routine,
+ * which regains ownership of the SCSI command (de facto) from a LLDD, and
+ * calls blk_complete_request() for further processing.
+ *
+ * This function is interrupt context safe.
+ */
+static void scsi_done(struct scsi_cmnd *cmd)
+{
+	trace_scsi_dispatch_cmd_done(cmd);
+	blk_complete_request(cmd->request);
+}
+
 /*
  * Function:    scsi_request_fn()
  *
@@ -1509,11 +1681,11 @@ static void scsi_request_fn(struct reque
 		int rtn;
 		/*
 		 * get next queueable request.  We do this early to make sure
-		 * that the request is fully prepared even if we cannot 
+		 * that the request is fully prepared even if we cannot
 		 * accept it.
 		 */
 		req = blk_peek_request(q);
-		if (!req || !scsi_dev_queue_ready(q, sdev))
+		if (!req)
 			break;
 
 		if (unlikely(!scsi_device_online(sdev))) {
@@ -1523,15 +1695,16 @@ static void scsi_request_fn(struct reque
 			continue;
 		}
 
+		if (!scsi_dev_queue_ready(q, sdev))
+			break;
 
 		/*
 		 * Remove the request from the request list.
 		 */
 		if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req)))
 			blk_start_request(req);
-		sdev->device_busy++;
 
-		spin_unlock(q->queue_lock);
+		spin_unlock_irq(q->queue_lock);
 		cmd = req->special;
 		if (unlikely(cmd == NULL)) {
 			printk(KERN_CRIT "impossible request in %s.\n"
@@ -1541,7 +1714,6 @@ static void scsi_request_fn(struct reque
 			blk_dump_rq_flags(req, "foo");
 			BUG();
 		}
-		spin_lock(shost->host_lock);
 
 		/*
 		 * We hit this when the driver is using a host wide
@@ -1552,9 +1724,11 @@ static void scsi_request_fn(struct reque
 		 * a run when a tag is freed.
 		 */
 		if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
+			spin_lock_irq(shost->host_lock);
 			if (list_empty(&sdev->starved_entry))
 				list_add_tail(&sdev->starved_entry,
 					      &shost->starved_list);
+			spin_unlock_irq(shost->host_lock);
 			goto not_ready;
 		}
 
@@ -1562,16 +1736,7 @@ static void scsi_request_fn(struct reque
 			goto not_ready;
 
 		if (!scsi_host_queue_ready(q, shost, sdev))
-			goto not_ready;
-
-		scsi_target(sdev)->target_busy++;
-		shost->host_busy++;
-
-		/*
-		 * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will
-		 *		take the lock again.
-		 */
-		spin_unlock_irq(shost->host_lock);
+			goto host_not_ready;
 
 		/*
 		 * Finally, initialize any error handling parameters, and set up
@@ -1582,17 +1747,22 @@ static void scsi_request_fn(struct reque
 		/*
 		 * Dispatch the command to the low-level driver.
 		 */
+		cmd->scsi_done = scsi_done;
 		rtn = scsi_dispatch_cmd(cmd);
-		spin_lock_irq(q->queue_lock);
-		if (rtn)
+		if (rtn) {
+			scsi_queue_insert(cmd, rtn);
+			spin_lock_irq(q->queue_lock);
 			goto out_delay;
+		}
+		spin_lock_irq(q->queue_lock);
 	}
 
 	return;
 
+ host_not_ready:
+	if (scsi_target(sdev)->can_queue > 0)
+		atomic_dec(&scsi_target(sdev)->target_busy);
  not_ready:
-	spin_unlock_irq(shost->host_lock);
-
 	/*
 	 * lock q, handle tag, requeue req, and decrement device_busy. We
 	 * must return with queue_lock held.
@@ -1603,13 +1773,186 @@ static void scsi_request_fn(struct reque
 	 */
 	spin_lock_irq(q->queue_lock);
 	blk_requeue_request(q, req);
-	sdev->device_busy--;
+	atomic_dec(&sdev->device_busy);
 out_delay:
-	if (sdev->device_busy == 0)
+	if (!atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev))
 		blk_delay_queue(q, SCSI_QUEUE_DELAY);
 }
 
-u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
+static inline int prep_to_mq(int ret)
+{
+	switch (ret) {
+	case BLKPREP_OK:
+		return 0;
+	case BLKPREP_DEFER:
+		return BLK_MQ_RQ_QUEUE_BUSY;
+	default:
+		return BLK_MQ_RQ_QUEUE_ERROR;
+	}
+}
+
+static int scsi_mq_prep_fn(struct request *req)
+{
+	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
+	struct scsi_device *sdev = req->q->queuedata;
+	struct Scsi_Host *shost = sdev->host;
+	unsigned char *sense_buf = cmd->sense_buffer;
+	struct scatterlist *sg;
+
+	memset(cmd, 0, sizeof(struct scsi_cmnd));
+
+	req->special = cmd;
+
+	cmd->request = req;
+	cmd->device = sdev;
+	cmd->sense_buffer = sense_buf;
+
+	cmd->tag = req->tag;
+
+	cmd->cmnd = req->cmd;
+	cmd->prot_op = SCSI_PROT_NORMAL;
+
+	INIT_LIST_HEAD(&cmd->list);
+	INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
+	cmd->jiffies_at_alloc = jiffies;
+
+	/*
+	 * XXX: cmd_list lookups are only used by two drivers, try to get
+	 * rid of this list in common code.
+	 */
+	spin_lock_irq(&sdev->list_lock);
+	list_add_tail(&cmd->list, &sdev->cmd_list);
+	spin_unlock_irq(&sdev->list_lock);
+
+	sg = (void *)cmd + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size;
+	cmd->sdb.table.sgl = sg;
+
+	if (scsi_host_get_prot(shost)) {
+		cmd->prot_sdb = (void *)sg +
+			shost->sg_tablesize * sizeof(struct scatterlist);
+		memset(cmd->prot_sdb, 0, sizeof(struct scsi_data_buffer));
+
+		cmd->prot_sdb->table.sgl =
+			(struct scatterlist *)(cmd->prot_sdb + 1);
+	}
+
+	if (blk_bidi_rq(req)) {
+		struct request *next_rq = req->next_rq;
+		struct scsi_data_buffer *bidi_sdb = blk_mq_rq_to_pdu(next_rq);
+
+		memset(bidi_sdb, 0, sizeof(struct scsi_data_buffer));
+		bidi_sdb->table.sgl =
+			(struct scatterlist *)(bidi_sdb + 1);
+
+		next_rq->special = bidi_sdb;
+	}
+
+	return scsi_setup_cmnd(sdev, req);
+}
+
+static void scsi_mq_done(struct scsi_cmnd *cmd)
+{
+	trace_scsi_dispatch_cmd_done(cmd);
+	blk_mq_complete_request(cmd->request);
+}
+
+static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
+{
+	struct request_queue *q = req->q;
+	struct scsi_device *sdev = q->queuedata;
+	struct Scsi_Host *shost = sdev->host;
+	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
+	int ret;
+	int reason;
+
+	ret = prep_to_mq(scsi_prep_state_check(sdev, req));
+	if (ret)
+		goto out;
+
+	ret = BLK_MQ_RQ_QUEUE_BUSY;
+	if (!get_device(&sdev->sdev_gendev))
+		goto out;
+
+	if (!scsi_dev_queue_ready(q, sdev))
+		goto out_put_device;
+	if (!scsi_target_queue_ready(shost, sdev))
+		goto out_dec_device_busy;
+	if (!scsi_host_queue_ready(q, shost, sdev))
+		goto out_dec_target_busy;
+
+	if (!(req->cmd_flags & REQ_DONTPREP)) {
+		ret = prep_to_mq(scsi_mq_prep_fn(req));
+		if (ret)
+			goto out_dec_host_busy;
+		req->cmd_flags |= REQ_DONTPREP;
+	}
+
+	scsi_init_cmd_errh(cmd);
+	cmd->scsi_done = scsi_mq_done;
+
+	reason = scsi_dispatch_cmd(cmd);
+	if (reason) {
+		scsi_set_blocked(cmd, reason);
+		ret = BLK_MQ_RQ_QUEUE_BUSY;
+		goto out_dec_host_busy;
+	}
+
+	return BLK_MQ_RQ_QUEUE_OK;
+
+out_dec_host_busy:
+	atomic_dec(&shost->host_busy);
+out_dec_target_busy:
+	if (scsi_target(sdev)->can_queue > 0)
+		atomic_dec(&scsi_target(sdev)->target_busy);
+out_dec_device_busy:
+	atomic_dec(&sdev->device_busy);
+out_put_device:
+	put_device(&sdev->sdev_gendev);
+out:
+	switch (ret) {
+	case BLK_MQ_RQ_QUEUE_BUSY:
+		blk_mq_stop_hw_queue(hctx);
+		if (atomic_read(&sdev->device_busy) == 0 &&
+		    !scsi_device_blocked(sdev))
+			blk_mq_delay_queue(hctx, SCSI_QUEUE_DELAY);
+		break;
+	case BLK_MQ_RQ_QUEUE_ERROR:
+		/*
+		 * Make sure to release all allocated ressources when
+		 * we hit an error, as we will never see this command
+		 * again.
+		 */
+		if (req->cmd_flags & REQ_DONTPREP)
+			scsi_mq_uninit_cmd(cmd);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int scsi_init_request(void *data, struct request *rq,
+		unsigned int hctx_idx, unsigned int request_idx,
+		unsigned int numa_node)
+{
+	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+	cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL,
+			numa_node);
+	if (!cmd->sense_buffer)
+		return -ENOMEM;
+	return 0;
+}
+
+static void scsi_exit_request(void *data, struct request *rq,
+		unsigned int hctx_idx, unsigned int request_idx)
+{
+	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+	kfree(cmd->sense_buffer);
+}
+
+static u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
 {
 	struct device *host_dev;
 	u64 bounce_limit = 0xffffffff;
@@ -1629,18 +1972,11 @@ u64 scsi_calculate_bounce_limit(struct S
 
 	return bounce_limit;
 }
-EXPORT_SYMBOL(scsi_calculate_bounce_limit);
 
-struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
-					 request_fn_proc *request_fn)
+static void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
 {
-	struct request_queue *q;
 	struct device *dev = shost->dma_dev;
 
-	q = blk_init_queue(request_fn, NULL);
-	if (!q)
-		return NULL;
-
 	/*
 	 * this limit is imposed by hardware restrictions
 	 */
@@ -1671,7 +2007,17 @@ struct request_queue *__scsi_alloc_queue
 	 * blk_queue_update_dma_alignment() later.
 	 */
 	blk_queue_dma_alignment(q, 0x03);
+}
+
+struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
+					 request_fn_proc *request_fn)
+{
+	struct request_queue *q;
 
+	q = blk_init_queue(request_fn, NULL);
+	if (!q)
+		return NULL;
+	__scsi_init_queue(shost, q);
 	return q;
 }
 EXPORT_SYMBOL(__scsi_alloc_queue);
@@ -1692,6 +2038,55 @@ struct request_queue *scsi_alloc_queue(s
 	return q;
 }
 
+static struct blk_mq_ops scsi_mq_ops = {
+	.map_queue	= blk_mq_map_queue,
+	.queue_rq	= scsi_queue_rq,
+	.complete	= scsi_softirq_done,
+	.timeout	= scsi_times_out,
+	.init_request	= scsi_init_request,
+	.exit_request	= scsi_exit_request,
+};
+
+struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev)
+{
+	sdev->request_queue = blk_mq_init_queue(&sdev->host->tag_set);
+	if (IS_ERR(sdev->request_queue))
+		return NULL;
+
+	sdev->request_queue->queuedata = sdev;
+	__scsi_init_queue(sdev->host, sdev->request_queue);
+	return sdev->request_queue;
+}
+
+int scsi_mq_setup_tags(struct Scsi_Host *shost)
+{
+	unsigned int cmd_size, sgl_size, tbl_size;
+
+	tbl_size = shost->sg_tablesize;
+	if (tbl_size > SCSI_MAX_SG_SEGMENTS)
+		tbl_size = SCSI_MAX_SG_SEGMENTS;
+	sgl_size = tbl_size * sizeof(struct scatterlist);
+	cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size;
+	if (scsi_host_get_prot(shost))
+		cmd_size += sizeof(struct scsi_data_buffer) + sgl_size;
+
+	memset(&shost->tag_set, 0, sizeof(shost->tag_set));
+	shost->tag_set.ops = &scsi_mq_ops;
+	shost->tag_set.nr_hw_queues = 1;
+	shost->tag_set.queue_depth = shost->can_queue;
+	shost->tag_set.cmd_size = cmd_size;
+	shost->tag_set.numa_node = NUMA_NO_NODE;
+	shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE;
+	shost->tag_set.driver_data = shost;
+
+	return blk_mq_alloc_tag_set(&shost->tag_set);
+}
+
+void scsi_mq_destroy_tags(struct Scsi_Host *shost)
+{
+	blk_mq_free_tag_set(&shost->tag_set);
+}
+
 /*
  * Function:    scsi_block_requests()
  *
@@ -2147,9 +2542,9 @@ scsi_device_set_state(struct scsi_device
 	return 0;
 
  illegal:
-	SCSI_LOG_ERROR_RECOVERY(1, 
+	SCSI_LOG_ERROR_RECOVERY(1,
 				sdev_printk(KERN_ERR, sdev,
-					    "Illegal state transition %s->%s\n",
+					    "Illegal state transition %s->%s",
 					    scsi_device_state_name(oldstate),
 					    scsi_device_state_name(state))
 				);
@@ -2345,7 +2740,7 @@ scsi_device_quiesce(struct scsi_device *
 		return err;
 
 	scsi_run_queue(sdev->request_queue);
-	while (sdev->device_busy) {
+	while (atomic_read(&sdev->device_busy)) {
 		msleep_interruptible(200);
 		scsi_run_queue(sdev->request_queue);
 	}
@@ -2437,9 +2832,13 @@ scsi_internal_device_block(struct scsi_d
 	 * block layer from calling the midlayer with this device's
 	 * request queue. 
 	 */
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_stop_queue(q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	if (q->mq_ops) {
+		blk_mq_stop_hw_queues(q);
+	} else {
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_stop_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
 
 	return 0;
 }
@@ -2485,9 +2884,13 @@ scsi_internal_device_unblock(struct scsi
 		 sdev->sdev_state != SDEV_OFFLINE)
 		return -EINVAL;
 
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_start_queue(q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	if (q->mq_ops) {
+		blk_mq_start_stopped_hw_queues(q, false);
+	} else {
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_start_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_priv.h linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_priv.h
--- linux-libre-3.16-gnu/drivers/scsi/scsi_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_priv.h	2014-09-28 17:29:07.000000000 -0400
@@ -88,6 +88,9 @@ extern void scsi_next_command(struct scs
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
 extern void scsi_run_host_queues(struct Scsi_Host *shost);
 extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
+extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev);
+extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
+extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
 extern int scsi_init_queue(void);
 extern void scsi_exit_queue(void);
 struct request_queue;
@@ -115,7 +118,7 @@ extern void scsi_exit_procfs(void);
 extern char scsi_scan_type[];
 extern int scsi_complete_async_scans(void);
 extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
-				   unsigned int, unsigned int, int);
+				   unsigned int, u64, int);
 extern void scsi_forget_host(struct Scsi_Host *);
 extern void scsi_rescan_device(struct device *);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_proc.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_proc.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,7 +185,7 @@ static int proc_print_scsidevice(struct
 
 	sdev = to_scsi_device(dev);
 	seq_printf(s,
-		"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
+		"Host: scsi%d Channel: %02d Id: %02d Lun: %02llu\n  Vendor: ",
 		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 	for (i = 0; i < 8; i++) {
 		if (sdev->vendor[i] >= 0x20)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_scan.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_scan.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_scan.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_scan.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,15 +81,11 @@ static const char *scsi_null_device_strs
 
 #define MAX_SCSI_LUNS	512
 
-#ifdef CONFIG_SCSI_MULTI_LUN
-static unsigned int max_scsi_luns = MAX_SCSI_LUNS;
-#else
-static unsigned int max_scsi_luns = 1;
-#endif
+static u64 max_scsi_luns = MAX_SCSI_LUNS;
 
-module_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR);
+module_param_named(max_luns, max_scsi_luns, ullong, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(max_luns,
-		 "last scsi LUN (should be between 1 and 2^32-1)");
+		 "last scsi LUN (should be between 1 and 2^64-1)");
 
 #ifdef CONFIG_SCSI_SCAN_ASYNC
 #define SCSI_SCAN_TYPE_DEFAULT "async"
@@ -198,7 +194,7 @@ static void scsi_unlock_floptical(struct
 {
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 
-	printk(KERN_NOTICE "scsi: unlocking floptical drive\n");
+	sdev_printk(KERN_NOTICE, sdev, "unlocking floptical drive\n");
 	scsi_cmd[0] = MODE_SENSE;
 	scsi_cmd[1] = 0;
 	scsi_cmd[2] = 0x2e;
@@ -224,7 +220,7 @@ static void scsi_unlock_floptical(struct
  *     scsi_Device pointer, or NULL on failure.
  **/
 static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
-					   unsigned int lun, void *hostdata)
+					   u64 lun, void *hostdata)
 {
 	struct scsi_device *sdev;
 	int display_failure_msg = 1, ret;
@@ -277,7 +273,10 @@ static struct scsi_device *scsi_alloc_sd
 	 */
 	sdev->borken = 1;
 
-	sdev->request_queue = scsi_alloc_queue(sdev);
+	if (shost_use_blk_mq(shost))
+		sdev->request_queue = scsi_mq_alloc_queue(sdev);
+	else
+		sdev->request_queue = scsi_alloc_queue(sdev);
 	if (!sdev->request_queue) {
 		/* release fn is set up in scsi_sysfs_device_initialise, so
 		 * have to free and put manually here */
@@ -600,8 +599,8 @@ static int scsi_probe_lun(struct scsi_de
 					  HZ / 2 + HZ * scsi_inq_timeout, 3,
 					  &resid);
 
-		SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s "
-				"with code 0x%x\n",
+		SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev,
+				"scsi scan: INQUIRY %s with code 0x%x\n",
 				result ? "failed" : "successful", result));
 
 		if (result) {
@@ -671,9 +670,10 @@ static int scsi_probe_lun(struct scsi_de
 		}
 
 	} else if (pass == 2) {
-		printk(KERN_INFO "scsi scan: %d byte inquiry failed.  "
-				"Consider BLIST_INQUIRY_36 for this device\n",
-				try_inquiry_len);
+		sdev_printk(KERN_INFO, sdev,
+			    "scsi scan: %d byte inquiry failed.  "
+			    "Consider BLIST_INQUIRY_36 for this device\n",
+			    try_inquiry_len);
 
 		/* If this pass failed, the third pass goes back and transfers
 		 * the same amount as we successfully got in the first pass. */
@@ -706,8 +706,9 @@ static int scsi_probe_lun(struct scsi_de
 	 * strings.
 	 */
 	if (sdev->inquiry_len < 36) {
-		printk(KERN_INFO "scsi scan: INQUIRY result too short (%d),"
-				" using 36\n", sdev->inquiry_len);
+		sdev_printk(KERN_INFO, sdev,
+			    "scsi scan: INQUIRY result too short (%d),"
+			    " using 36\n", sdev->inquiry_len);
 		sdev->inquiry_len = 36;
 	}
 
@@ -806,29 +807,6 @@ static int scsi_add_lun(struct scsi_devi
 		sdev->removable = (inq_result[1] & 0x80) >> 7;
 	}
 
-	switch (sdev->type) {
-	case TYPE_RBC:
-	case TYPE_TAPE:
-	case TYPE_DISK:
-	case TYPE_PRINTER:
-	case TYPE_MOD:
-	case TYPE_PROCESSOR:
-	case TYPE_SCANNER:
-	case TYPE_MEDIUM_CHANGER:
-	case TYPE_ENCLOSURE:
-	case TYPE_COMM:
-	case TYPE_RAID:
-	case TYPE_OSD:
-		sdev->writeable = 1;
-		break;
-	case TYPE_ROM:
-	case TYPE_WORM:
-		sdev->writeable = 0;
-		break;
-	default:
-		printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type);
-	}
-
 	if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) {
 		/* RBC and MMC devices can return SCSI-3 compliance and yet
 		 * still not support REPORT LUNS, so make them act as
@@ -922,6 +900,12 @@ static int scsi_add_lun(struct scsi_devi
 	if (*bflags & BLIST_USE_10_BYTE_MS)
 		sdev->use_10_for_ms = 1;
 
+	/* some devices don't like REPORT SUPPORTED OPERATION CODES
+	 * and will simply timeout causing sd_mod init to take a very
+	 * very long time */
+	if (*bflags & BLIST_NO_RSOC)
+		sdev->no_report_opcodes = 1;
+
 	/* set the device running here so that slave configure
 	 * may do I/O */
 	ret = scsi_device_set_state(sdev, SDEV_RUNNING);
@@ -950,7 +934,9 @@ static int scsi_add_lun(struct scsi_devi
 
 	sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT;
 
-	if (*bflags & BLIST_SKIP_VPD_PAGES)
+	if (*bflags & BLIST_TRY_VPD_PAGES)
+		sdev->try_vpd_pages = 1;
+	else if (*bflags & BLIST_SKIP_VPD_PAGES)
 		sdev->skip_vpd_pages = 1;
 
 	transport_configure_device(&sdev->sdev_gendev);
@@ -1032,7 +1018,7 @@ static unsigned char *scsi_inq_str(unsig
  *     SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
  **/
 static int scsi_probe_and_add_lun(struct scsi_target *starget,
-				  uint lun, int *bflagsp,
+				  u64 lun, int *bflagsp,
 				  struct scsi_device **sdevp, int rescan,
 				  void *hostdata)
 {
@@ -1048,7 +1034,7 @@ static int scsi_probe_and_add_lun(struct
 	sdev = scsi_device_lookup_by_target(starget, lun);
 	if (sdev) {
 		if (rescan || !scsi_device_created(sdev)) {
-			SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+			SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev,
 				"scsi scan: device exists on %s\n",
 				dev_name(&sdev->sdev_gendev)));
 			if (sdevp)
@@ -1135,7 +1121,7 @@ static int scsi_probe_and_add_lun(struct
 	if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) &&
 	    (result[0] & 0x1f) == 0x1f &&
 	    !scsi_is_wlun(lun)) {
-		SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+		SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev,
 					"scsi scan: peripheral device type"
 					" of 31, no device added\n"));
 		res = SCSI_SCAN_TARGET_PRESENT;
@@ -1185,11 +1171,12 @@ static int scsi_probe_and_add_lun(struct
 static void scsi_sequential_lun_scan(struct scsi_target *starget,
 				     int bflags, int scsi_level, int rescan)
 {
-	unsigned int sparse_lun, lun, max_dev_lun;
+	uint max_dev_lun;
+	u64 sparse_lun, lun;
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 
-	SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of"
-				    "%s\n", dev_name(&starget->dev)));
+	SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget,
+		"scsi scan: Sequential scan\n"));
 
 	max_dev_lun = min(max_scsi_luns, shost->max_lun);
 	/*
@@ -1239,6 +1226,12 @@ static void scsi_sequential_lun_scan(str
 		max_dev_lun = min(8U, max_dev_lun);
 
 	/*
+	 * Stop scanning at 255 unless BLIST_SCSI3LUN
+	 */
+	if (!(bflags & BLIST_SCSI3LUN))
+		max_dev_lun = min(256U, max_dev_lun);
+
+	/*
 	 * We have already scanned LUN 0, so start at LUN 1. Keep scanning
 	 * until we reach the max, or no LUN is found and we are not
 	 * sparse_lun.
@@ -1260,24 +1253,25 @@ static void scsi_sequential_lun_scan(str
  *     truncation before using this function.
  *
  * Notes:
- *     The struct scsi_lun is assumed to be four levels, with each level
- *     effectively containing a SCSI byte-ordered (big endian) short; the
- *     addressing bits of each level are ignored (the highest two bits).
  *     For a description of the LUN format, post SCSI-3 see the SCSI
  *     Architecture Model, for SCSI-3 see the SCSI Controller Commands.
  *
- *     Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns
- *     the integer: 0x0b030a04
+ *     Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function
+ *     returns the integer: 0x0b03d204
+ *
+ *     This encoding will return a standard integer LUN for LUNs smaller
+ *     than 256, which typically use a single level LUN structure with
+ *     addressing method 0.
  **/
-int scsilun_to_int(struct scsi_lun *scsilun)
+u64 scsilun_to_int(struct scsi_lun *scsilun)
 {
 	int i;
-	unsigned int lun;
+	u64 lun;
 
 	lun = 0;
 	for (i = 0; i < sizeof(lun); i += 2)
-		lun = lun | (((scsilun->scsi_lun[i] << 8) |
-			      scsilun->scsi_lun[i + 1]) << (i * 8));
+		lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) |
+			     ((u64)scsilun->scsi_lun[i + 1] << (i * 8)));
 	return lun;
 }
 EXPORT_SYMBOL(scsilun_to_int);
@@ -1291,16 +1285,13 @@ EXPORT_SYMBOL(scsilun_to_int);
  *     Reverts the functionality of the scsilun_to_int, which packed
  *     an 8-byte lun value into an int. This routine unpacks the int
  *     back into the lun value.
- *     Note: the scsilun_to_int() routine does not truly handle all
- *     8bytes of the lun value. This functions restores only as much
- *     as was set by the routine.
  *
  * Notes:
- *     Given an integer : 0x0b030a04,  this function returns a
- *     scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *     Given an integer : 0x0b03d204,  this function returns a
+ *     struct scsi_lun of: d2 04 0b 03 00 00 00 00
  *
  **/
-void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+void int_to_scsilun(u64 lun, struct scsi_lun *scsilun)
 {
 	int i;
 
@@ -1340,7 +1331,7 @@ static int scsi_report_lun_scan(struct s
 	char devname[64];
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 	unsigned int length;
-	unsigned int lun;
+	u64 lun;
 	unsigned int num_luns;
 	unsigned int retries;
 	int result;
@@ -1430,17 +1421,19 @@ static int scsi_report_lun_scan(struct s
 	 * a retry.
 	 */
 	for (retries = 0; retries < 3; retries++) {
-		SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending"
-				" REPORT LUNS to %s (try %d)\n", devname,
+		SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+				"scsi scan: Sending REPORT LUNS to (try %d)\n",
 				retries));
 
 		result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
 					  lun_data, length, &sshdr,
 					  SCSI_TIMEOUT + 4 * HZ, 3, NULL);
 
-		SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS"
-				" %s (try %d) result 0x%x\n", result
-				?  "failed" : "successful", retries, result));
+		SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+				"scsi scan: REPORT LUNS"
+				" %s (try %d) result 0x%x\n",
+				result ?  "failed" : "successful",
+				retries, result));
 		if (result == 0)
 			break;
 		else if (scsi_sense_valid(&sshdr)) {
@@ -1466,10 +1459,11 @@ static int scsi_report_lun_scan(struct s
 
 	num_luns = (length / sizeof(struct scsi_lun));
 	if (num_luns > max_scsi_report_luns) {
-		printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)"
-		       " of %d luns reported, try increasing"
-		       " max_scsi_report_luns.\n", devname,
-		       max_scsi_report_luns, num_luns);
+		sdev_printk(KERN_WARNING, sdev,
+			    "Only %d (max_scsi_report_luns)"
+			    " of %d luns reported, try increasing"
+			    " max_scsi_report_luns.\n",
+			    max_scsi_report_luns, num_luns);
 		num_luns = max_scsi_report_luns;
 	}
 
@@ -1483,27 +1477,10 @@ static int scsi_report_lun_scan(struct s
 	for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) {
 		lun = scsilun_to_int(lunp);
 
-		/*
-		 * Check if the unused part of lunp is non-zero, and so
-		 * does not fit in lun.
-		 */
-		if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) {
-			int i;
-
-			/*
-			 * Output an error displaying the LUN in byte order,
-			 * this differs from what linux would print for the
-			 * integer LUN value.
-			 */
-			printk(KERN_WARNING "scsi: %s lun 0x", devname);
-			data = (char *)lunp->scsi_lun;
-			for (i = 0; i < sizeof(struct scsi_lun); i++)
-				printk("%02x", data[i]);
-			printk(" has a LUN larger than currently supported.\n");
-		} else if (lun > sdev->host->max_lun) {
-			printk(KERN_WARNING "scsi: %s lun%d has a LUN larger"
-			       " than allowed by the host adapter\n",
-			       devname, lun);
+		if (lun > sdev->host->max_lun) {
+			sdev_printk(KERN_WARNING, sdev,
+				    "lun%llu has a LUN larger than"
+				    " allowed by the host adapter\n", lun);
 		} else {
 			int res;
 
@@ -1515,8 +1492,8 @@ static int scsi_report_lun_scan(struct s
 				 */
 				sdev_printk(KERN_ERR, sdev,
 					"Unexpected response"
-				        " from lun %d while scanning, scan"
-				        " aborted\n", lun);
+					" from lun %llu while scanning, scan"
+					" aborted\n", (unsigned long long)lun);
 				break;
 			}
 		}
@@ -1535,7 +1512,7 @@ static int scsi_report_lun_scan(struct s
 }
 
 struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
-				      uint id, uint lun, void *hostdata)
+				      uint id, u64 lun, void *hostdata)
 {
 	struct scsi_device *sdev = ERR_PTR(-ENODEV);
 	struct device *parent = &shost->shost_gendev;
@@ -1571,7 +1548,7 @@ struct scsi_device *__scsi_add_device(st
 EXPORT_SYMBOL(__scsi_add_device);
 
 int scsi_add_device(struct Scsi_Host *host, uint channel,
-		    uint target, uint lun)
+		    uint target, u64 lun)
 {
 	struct scsi_device *sdev = 
 		__scsi_add_device(host, channel, target, lun, NULL);
@@ -1600,7 +1577,7 @@ void scsi_rescan_device(struct device *d
 EXPORT_SYMBOL(scsi_rescan_device);
 
 static void __scsi_scan_target(struct device *parent, unsigned int channel,
-		unsigned int id, unsigned int lun, int rescan)
+		unsigned int id, u64 lun, int rescan)
 {
 	struct Scsi_Host *shost = dev_to_shost(parent);
 	int bflags = 0;
@@ -1668,7 +1645,7 @@ static void __scsi_scan_target(struct de
  *     sequential scan of LUNs on the target id.
  **/
 void scsi_scan_target(struct device *parent, unsigned int channel,
-		      unsigned int id, unsigned int lun, int rescan)
+		      unsigned int id, u64 lun, int rescan)
 {
 	struct Scsi_Host *shost = dev_to_shost(parent);
 
@@ -1688,7 +1665,7 @@ void scsi_scan_target(struct device *par
 EXPORT_SYMBOL(scsi_scan_target);
 
 static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
-			      unsigned int id, unsigned int lun, int rescan)
+			      unsigned int id, u64 lun, int rescan)
 {
 	uint order_id;
 
@@ -1719,10 +1696,10 @@ static void scsi_scan_channel(struct Scs
 }
 
 int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
-			    unsigned int id, unsigned int lun, int rescan)
+			    unsigned int id, u64 lun, int rescan)
 {
 	SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost,
-		"%s: <%u:%u:%u>\n",
+		"%s: <%u:%u:%llu>\n",
 		__func__, channel, id, lun));
 
 	if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
@@ -1781,8 +1758,7 @@ static struct async_scan_data *scsi_prep
 		return NULL;
 
 	if (shost->async_scan) {
-		printk("%s called twice for host %d", __func__,
-				shost->host_no);
+		shost_printk(KERN_INFO, shost, "%s called twice\n", __func__);
 		dump_stack();
 		return NULL;
 	}
@@ -1835,8 +1811,7 @@ static void scsi_finish_async_scan(struc
 	mutex_lock(&shost->scan_mutex);
 
 	if (!shost->async_scan) {
-		printk("%s called twice for host %d", __func__,
-				shost->host_no);
+		shost_printk(KERN_INFO, shost, "%s called twice\n", __func__);
 		dump_stack();
 		mutex_unlock(&shost->scan_mutex);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_sysfs.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_sysfs.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,7 +80,7 @@ const char *scsi_host_state_name(enum sc
 	return name;
 }
 
-static int check_set(unsigned int *val, char *src)
+static int check_set(unsigned long long *val, char *src)
 {
 	char *last;
 
@@ -90,7 +90,7 @@ static int check_set(unsigned int *val,
 		/*
 		 * Doesn't check for int overflow
 		 */
-		*val = simple_strtoul(src, &last, 0);
+		*val = simple_strtoull(src, &last, 0);
 		if (*last != '\0')
 			return 1;
 	}
@@ -99,11 +99,11 @@ static int check_set(unsigned int *val,
 
 static int scsi_scan(struct Scsi_Host *shost, const char *str)
 {
-	char s1[15], s2[15], s3[15], junk;
-	unsigned int channel, id, lun;
+	char s1[15], s2[15], s3[17], junk;
+	unsigned long long channel, id, lun;
 	int res;
 
-	res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
+	res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk);
 	if (res != 3)
 		return -EINVAL;
 	if (check_set(&channel, s1))
@@ -333,8 +333,8 @@ store_shost_eh_deadline(struct device *d
 
 static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline);
 
+shost_rd_attr(use_blk_mq, "%d\n");
 shost_rd_attr(unique_id, "%u\n");
-shost_rd_attr(host_busy, "%hu\n");
 shost_rd_attr(cmd_per_lun, "%hd\n");
 shost_rd_attr(can_queue, "%hd\n");
 shost_rd_attr(sg_tablesize, "%hu\n");
@@ -344,7 +344,16 @@ shost_rd_attr(prot_capabilities, "%u\n")
 shost_rd_attr(prot_guard_type, "%hd\n");
 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
 
+static ssize_t
+show_host_busy(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	return snprintf(buf, 20, "%d\n", atomic_read(&shost->host_busy));
+}
+static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL);
+
 static struct attribute *scsi_sysfs_shost_attrs[] = {
+	&dev_attr_use_blk_mq.attr,
 	&dev_attr_unique_id.attr,
 	&dev_attr_host_busy.attr,
 	&dev_attr_cmd_per_lun.attr,
@@ -577,14 +586,30 @@ static int scsi_sdev_check_buf_bit(const
 /*
  * Create the actual show/store functions and data structures.
  */
-sdev_rd_attr (device_blocked, "%d\n");
-sdev_rd_attr (device_busy, "%d\n");
 sdev_rd_attr (type, "%d\n");
 sdev_rd_attr (scsi_level, "%d\n");
 sdev_rd_attr (vendor, "%.8s\n");
 sdev_rd_attr (model, "%.16s\n");
 sdev_rd_attr (rev, "%.4s\n");
 
+static ssize_t
+sdev_show_device_busy(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_busy));
+}
+static DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL);
+
+static ssize_t
+sdev_show_device_blocked(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_blocked));
+}
+static DEVICE_ATTR(device_blocked, S_IRUGO, sdev_show_device_blocked, NULL);
+
 /*
  * TODO: can we make these symlinks to the block layer ones?
  */
@@ -885,9 +910,9 @@ sdev_store_queue_ramp_up_period(struct d
 				const char *buf, size_t count)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
-	unsigned long period;
+	unsigned int period;
 
-	if (strict_strtoul(buf, 10, &period))
+	if (kstrtouint(buf, 10, &period))
 		return -EINVAL;
 
 	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
@@ -1230,13 +1255,13 @@ void scsi_sysfs_device_initialize(struct
 	device_initialize(&sdev->sdev_gendev);
 	sdev->sdev_gendev.bus = &scsi_bus_type;
 	sdev->sdev_gendev.type = &scsi_dev_type;
-	dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%d",
+	dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu",
 		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 
 	device_initialize(&sdev->sdev_dev);
 	sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
 	sdev->sdev_dev.class = &sdev_class;
-	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d",
+	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu",
 		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 	sdev->scsi_level = starget->scsi_level;
 	transport_setup_device(&sdev->sdev_gendev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_if.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_if.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_if.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_if.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,399 +0,0 @@
-/*
- * SCSI target kernel/user interface functions
- *
- * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
- * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have 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/miscdevice.h>
-#include <linux/gfp.h>
-#include <linux/file.h>
-#include <linux/export.h>
-#include <net/tcp.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tgt.h>
-#include <scsi/scsi_tgt_if.h>
-
-#include <asm/cacheflush.h>
-
-#include "scsi_tgt_priv.h"
-
-#if TGT_RING_SIZE < PAGE_SIZE
-#  define TGT_RING_SIZE PAGE_SIZE
-#endif
-
-#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
-#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
-#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
-
-struct tgt_ring {
-	u32 tr_idx;
-	unsigned long tr_pages[TGT_RING_PAGES];
-	spinlock_t tr_lock;
-};
-
-/* tx_ring : kernel->user, rx_ring : user->kernel */
-static struct tgt_ring tx_ring, rx_ring;
-static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait);
-
-static inline void tgt_ring_idx_inc(struct tgt_ring *ring)
-{
-	if (ring->tr_idx == TGT_MAX_EVENTS - 1)
-		ring->tr_idx = 0;
-	else
-		ring->tr_idx++;
-}
-
-static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx)
-{
-	u32 pidx, off;
-
-	pidx = idx / TGT_EVENT_PER_PAGE;
-	off = idx % TGT_EVENT_PER_PAGE;
-
-	return (struct tgt_event *)
-		(ring->tr_pages[pidx] + sizeof(struct tgt_event) * off);
-}
-
-static int tgt_uspace_send_event(u32 type, struct tgt_event *p)
-{
-	struct tgt_event *ev;
-	struct tgt_ring *ring = &tx_ring;
-	unsigned long flags;
-	int err = 0;
-
-	spin_lock_irqsave(&ring->tr_lock, flags);
-
-	ev = tgt_head_event(ring, ring->tr_idx);
-	if (!ev->hdr.status)
-		tgt_ring_idx_inc(ring);
-	else
-		err = -BUSY;
-
-	spin_unlock_irqrestore(&ring->tr_lock, flags);
-
-	if (err)
-		return err;
-
-	memcpy(ev, p, sizeof(*ev));
-	ev->hdr.type = type;
-	mb();
-	ev->hdr.status = 1;
-
-	flush_dcache_page(virt_to_page(ev));
-
-	wake_up_interruptible(&tgt_poll_wait);
-
-	return 0;
-}
-
-int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id,
-			     struct scsi_lun *lun, u64 tag)
-{
-	struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
-	struct tgt_event ev;
-	int err;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.p.cmd_req.host_no = shost->host_no;
-	ev.p.cmd_req.itn_id = itn_id;
-	ev.p.cmd_req.data_len = scsi_bufflen(cmd);
-	memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb));
-	memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
-	ev.p.cmd_req.attribute = cmd->tag;
-	ev.p.cmd_req.tag = tag;
-
-	dprintk("%p %d %u %x %llx\n", cmd, shost->host_no,
-		ev.p.cmd_req.data_len, cmd->tag,
-		(unsigned long long) ev.p.cmd_req.tag);
-
-	err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev);
-	if (err)
-		eprintk("tx buf is full, could not send\n");
-
-	return err;
-}
-
-int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag)
-{
-	struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
-	struct tgt_event ev;
-	int err;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.p.cmd_done.host_no = shost->host_no;
-	ev.p.cmd_done.itn_id = itn_id;
-	ev.p.cmd_done.tag = tag;
-	ev.p.cmd_done.result = cmd->result;
-
-	dprintk("%p %d %llu %u %x\n", cmd, shost->host_no,
-		(unsigned long long) ev.p.cmd_req.tag,
-		ev.p.cmd_req.data_len, cmd->tag);
-
-	err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev);
-	if (err)
-		eprintk("tx buf is full, could not send\n");
-
-	return err;
-}
-
-int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function,
-				  u64 tag, struct scsi_lun *scsilun, void *data)
-{
-	struct tgt_event ev;
-	int err;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.p.tsk_mgmt_req.host_no = host_no;
-	ev.p.tsk_mgmt_req.itn_id = itn_id;
-	ev.p.tsk_mgmt_req.function = function;
-	ev.p.tsk_mgmt_req.tag = tag;
-	memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun));
-	ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data;
-
-	dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag,
-		(unsigned long long) ev.p.tsk_mgmt_req.mid);
-
-	err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev);
-	if (err)
-		eprintk("tx buf is full, could not send\n");
-
-	return err;
-}
-
-int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id,
-					  int function, char *initiator_id)
-{
-	struct tgt_event ev;
-	int err;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.p.it_nexus_req.host_no = host_no;
-	ev.p.it_nexus_req.function = function;
-	ev.p.it_nexus_req.itn_id = itn_id;
-	if (initiator_id)
-		strncpy(ev.p.it_nexus_req.initiator_id, initiator_id,
-			sizeof(ev.p.it_nexus_req.initiator_id));
-
-	dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id);
-
-	err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev);
-	if (err)
-		eprintk("tx buf is full, could not send\n");
-
-	return err;
-}
-
-static int event_recv_msg(struct tgt_event *ev)
-{
-	int err = 0;
-
-	switch (ev->hdr.type) {
-	case TGT_UEVENT_CMD_RSP:
-		err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
-					   ev->p.cmd_rsp.itn_id,
-					   ev->p.cmd_rsp.result,
-					   ev->p.cmd_rsp.tag,
-					   ev->p.cmd_rsp.uaddr,
-					   ev->p.cmd_rsp.len,
-					   ev->p.cmd_rsp.sense_uaddr,
-					   ev->p.cmd_rsp.sense_len,
-					   ev->p.cmd_rsp.rw);
-		break;
-	case TGT_UEVENT_TSK_MGMT_RSP:
-		err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no,
-					       ev->p.tsk_mgmt_rsp.itn_id,
-					       ev->p.tsk_mgmt_rsp.mid,
-					       ev->p.tsk_mgmt_rsp.result);
-		break;
-	case TGT_UEVENT_IT_NEXUS_RSP:
-		err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no,
-						   ev->p.it_nexus_rsp.itn_id,
-						   ev->p.it_nexus_rsp.result);
-		break;
-	default:
-		eprintk("unknown type %d\n", ev->hdr.type);
-		err = -EINVAL;
-	}
-
-	return err;
-}
-
-static ssize_t tgt_write(struct file *file, const char __user * buffer,
-			 size_t count, loff_t * ppos)
-{
-	struct tgt_event *ev;
-	struct tgt_ring *ring = &rx_ring;
-
-	while (1) {
-		ev = tgt_head_event(ring, ring->tr_idx);
-		/* do we need this? */
-		flush_dcache_page(virt_to_page(ev));
-
-		if (!ev->hdr.status)
-			break;
-
-		tgt_ring_idx_inc(ring);
-		event_recv_msg(ev);
-		ev->hdr.status = 0;
-	};
-
-	return count;
-}
-
-static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait)
-{
-	struct tgt_event *ev;
-	struct tgt_ring *ring = &tx_ring;
-	unsigned long flags;
-	unsigned int mask = 0;
-	u32 idx;
-
-	poll_wait(file, &tgt_poll_wait, wait);
-
-	spin_lock_irqsave(&ring->tr_lock, flags);
-
-	idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1;
-	ev = tgt_head_event(ring, idx);
-	if (ev->hdr.status)
-		mask |= POLLIN | POLLRDNORM;
-
-	spin_unlock_irqrestore(&ring->tr_lock, flags);
-
-	return mask;
-}
-
-static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr,
-			   struct tgt_ring *ring)
-{
-	int i, err;
-
-	for (i = 0; i < TGT_RING_PAGES; i++) {
-		struct page *page = virt_to_page(ring->tr_pages[i]);
-		err = vm_insert_page(vma, addr, page);
-		if (err)
-			return err;
-		addr += PAGE_SIZE;
-	}
-
-	return 0;
-}
-
-static int tgt_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	unsigned long addr;
-	int err;
-
-	if (vma->vm_pgoff)
-		return -EINVAL;
-
-	if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) {
-		eprintk("mmap size must be %lu, not %lu \n",
-			TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start);
-		return -EINVAL;
-	}
-
-	addr = vma->vm_start;
-	err = uspace_ring_map(vma, addr, &tx_ring);
-	if (err)
-		return err;
-	err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring);
-
-	return err;
-}
-
-static int tgt_open(struct inode *inode, struct file *file)
-{
-	tx_ring.tr_idx = rx_ring.tr_idx = 0;
-
-	return 0;
-}
-
-static const struct file_operations tgt_fops = {
-	.owner		= THIS_MODULE,
-	.open		= tgt_open,
-	.poll		= tgt_poll,
-	.write		= tgt_write,
-	.mmap		= tgt_mmap,
-	.llseek		= noop_llseek,
-};
-
-static struct miscdevice tgt_miscdev = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "tgt",
-	.fops = &tgt_fops,
-};
-
-static void tgt_ring_exit(struct tgt_ring *ring)
-{
-	int i;
-
-	for (i = 0; i < TGT_RING_PAGES; i++)
-		free_page(ring->tr_pages[i]);
-}
-
-static int tgt_ring_init(struct tgt_ring *ring)
-{
-	int i;
-
-	spin_lock_init(&ring->tr_lock);
-
-	for (i = 0; i < TGT_RING_PAGES; i++) {
-		ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL);
-		if (!ring->tr_pages[i]) {
-			eprintk("out of memory\n");
-			return -ENOMEM;
-		}
-	}
-
-	return 0;
-}
-
-void scsi_tgt_if_exit(void)
-{
-	tgt_ring_exit(&tx_ring);
-	tgt_ring_exit(&rx_ring);
-	misc_deregister(&tgt_miscdev);
-}
-
-int scsi_tgt_if_init(void)
-{
-	int err;
-
-	err = tgt_ring_init(&tx_ring);
-	if (err)
-		return err;
-
-	err = tgt_ring_init(&rx_ring);
-	if (err)
-		goto free_tx_ring;
-
-	err = misc_register(&tgt_miscdev);
-	if (err)
-		goto free_rx_ring;
-
-	return 0;
-free_rx_ring:
-	tgt_ring_exit(&rx_ring);
-free_tx_ring:
-	tgt_ring_exit(&tx_ring);
-
-	return err;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_lib.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_lib.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_lib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,661 +0,0 @@
-/*
- * SCSI target lib functions
- *
- * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu>
- * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-#include <linux/blkdev.h>
-#include <linux/hash.h>
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport.h>
-#include <scsi/scsi_tgt.h>
-
-#include "scsi_tgt_priv.h"
-
-static struct workqueue_struct *scsi_tgtd;
-static struct kmem_cache *scsi_tgt_cmd_cache;
-
-/*
- * TODO: this struct will be killed when the block layer supports large bios
- * and James's work struct code is in
- */
-struct scsi_tgt_cmd {
-	/* TODO replace work with James b's code */
-	struct work_struct work;
-	/* TODO fix limits of some drivers */
-	struct bio *bio;
-
-	struct list_head hash_list;
-	struct request *rq;
-	u64 itn_id;
-	u64 tag;
-};
-
-#define TGT_HASH_ORDER	4
-#define cmd_hashfn(tag)	hash_long((unsigned long) (tag), TGT_HASH_ORDER)
-
-struct scsi_tgt_queuedata {
-	struct Scsi_Host *shost;
-	struct list_head cmd_hash[1 << TGT_HASH_ORDER];
-	spinlock_t cmd_hash_lock;
-};
-
-/*
- * Function:	scsi_host_get_command()
- *
- * Purpose:	Allocate and setup a scsi command block and blk request
- *
- * Arguments:	shost	- scsi host
- *		data_dir - dma data dir
- *		gfp_mask- allocator flags
- *
- * Returns:	The allocated scsi command structure.
- *
- * This should be called by target LLDs to get a command.
- */
-struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
-					enum dma_data_direction data_dir,
-					gfp_t gfp_mask)
-{
-	int write = (data_dir == DMA_TO_DEVICE);
-	struct request *rq;
-	struct scsi_cmnd *cmd;
-	struct scsi_tgt_cmd *tcmd;
-
-	/* Bail if we can't get a reference to the device */
-	if (!get_device(&shost->shost_gendev))
-		return NULL;
-
-	tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC);
-	if (!tcmd)
-		goto put_dev;
-
-	/*
-	 * The blk helpers are used to the READ/WRITE requests
-	 * transferring data from a initiator point of view. Since
-	 * we are in target mode we want the opposite.
-	 */
-	rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
-	if (!rq)
-		goto free_tcmd;
-
-	cmd = __scsi_get_command(shost, gfp_mask);
-	if (!cmd)
-		goto release_rq;
-
-	cmd->sc_data_direction = data_dir;
-	cmd->jiffies_at_alloc = jiffies;
-	cmd->request = rq;
-
-	cmd->cmnd = rq->cmd;
-
-	rq->special = cmd;
-	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
-	rq->end_io_data = tcmd;
-
-	tcmd->rq = rq;
-
-	return cmd;
-
-release_rq:
-	blk_put_request(rq);
-free_tcmd:
-	kmem_cache_free(scsi_tgt_cmd_cache, tcmd);
-put_dev:
-	put_device(&shost->shost_gendev);
-	return NULL;
-
-}
-EXPORT_SYMBOL_GPL(scsi_host_get_command);
-
-/*
- * Function:	scsi_host_put_command()
- *
- * Purpose:	Free a scsi command block
- *
- * Arguments:	shost	- scsi host
- * 		cmd	- command block to free
- *
- * Returns:	Nothing.
- *
- * Notes:	The command must not belong to any lists.
- */
-void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
-{
-	struct request_queue *q = shost->uspace_req_q;
-	struct request *rq = cmd->request;
-	struct scsi_tgt_cmd *tcmd = rq->end_io_data;
-	unsigned long flags;
-
-	kmem_cache_free(scsi_tgt_cmd_cache, tcmd);
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	__blk_put_request(q, rq);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	__scsi_put_command(shost, cmd);
-	put_device(&shost->shost_gendev);
-}
-EXPORT_SYMBOL_GPL(scsi_host_put_command);
-
-static void cmd_hashlist_del(struct scsi_cmnd *cmd)
-{
-	struct request_queue *q = cmd->request->q;
-	struct scsi_tgt_queuedata *qdata = q->queuedata;
-	unsigned long flags;
-	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-
-	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
-	list_del(&tcmd->hash_list);
-	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
-}
-
-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
-{
-	blk_rq_unmap_user(tcmd->bio);
-}
-
-static void scsi_tgt_cmd_destroy(struct work_struct *work)
-{
-	struct scsi_tgt_cmd *tcmd =
-		container_of(work, struct scsi_tgt_cmd, work);
-	struct scsi_cmnd *cmd = tcmd->rq->special;
-
-	dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction,
-		rq_data_dir(cmd->request));
-	scsi_unmap_user_pages(tcmd);
-	tcmd->rq->bio = NULL;
-	scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
-}
-
-static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
-			      u64 itn_id, u64 tag)
-{
-	struct scsi_tgt_queuedata *qdata = rq->q->queuedata;
-	unsigned long flags;
-	struct list_head *head;
-
-	tcmd->itn_id = itn_id;
-	tcmd->tag = tag;
-	tcmd->bio = NULL;
-	INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
-	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
-	head = &qdata->cmd_hash[cmd_hashfn(tag)];
-	list_add(&tcmd->hash_list, head);
-	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
-}
-
-/*
- * scsi_tgt_alloc_queue - setup queue used for message passing
- * shost: scsi host
- *
- * This should be called by the LLD after host allocation.
- * And will be released when the host is released.
- */
-int scsi_tgt_alloc_queue(struct Scsi_Host *shost)
-{
-	struct scsi_tgt_queuedata *queuedata;
-	struct request_queue *q;
-	int err, i;
-
-	/*
-	 * Do we need to send a netlink event or should uspace
-	 * just respond to the hotplug event?
-	 */
-	q = __scsi_alloc_queue(shost, NULL);
-	if (!q)
-		return -ENOMEM;
-
-	queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL);
-	if (!queuedata) {
-		err = -ENOMEM;
-		goto cleanup_queue;
-	}
-	queuedata->shost = shost;
-	q->queuedata = queuedata;
-
-	/*
-	 * this is a silly hack. We should probably just queue as many
-	 * command as is recvd to userspace. uspace can then make
-	 * sure we do not overload the HBA
-	 */
-	q->nr_requests = shost->can_queue;
-	/*
-	 * We currently only support software LLDs so this does
-	 * not matter for now. Do we need this for the cards we support?
-	 * If so we should make it a host template value.
-	 */
-	blk_queue_dma_alignment(q, 0);
-	shost->uspace_req_q = q;
-
-	for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++)
-		INIT_LIST_HEAD(&queuedata->cmd_hash[i]);
-	spin_lock_init(&queuedata->cmd_hash_lock);
-
-	return 0;
-
-cleanup_queue:
-	blk_cleanup_queue(q);
-	return err;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue);
-
-void scsi_tgt_free_queue(struct Scsi_Host *shost)
-{
-	int i;
-	unsigned long flags;
-	struct request_queue *q = shost->uspace_req_q;
-	struct scsi_cmnd *cmd;
-	struct scsi_tgt_queuedata *qdata = q->queuedata;
-	struct scsi_tgt_cmd *tcmd, *n;
-	LIST_HEAD(cmds);
-
-	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
-
-	for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) {
-		list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i],
-					 hash_list)
-			list_move(&tcmd->hash_list, &cmds);
-	}
-
-	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
-
-	while (!list_empty(&cmds)) {
-		tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list);
-		list_del(&tcmd->hash_list);
-		cmd = tcmd->rq->special;
-
-		shost->hostt->eh_abort_handler(cmd);
-		scsi_tgt_cmd_destroy(&tcmd->work);
-	}
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_free_queue);
-
-struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd)
-{
-	struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata;
-	return queue->shost;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host);
-
-/*
- * scsi_tgt_queue_command - queue command for userspace processing
- * @cmd:	scsi command
- * @scsilun:	scsi lun
- * @tag:	unique value to identify this command for tmf
- */
-int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id,
-			   struct scsi_lun *scsilun, u64 tag)
-{
-	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-	int err;
-
-	init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag);
-	err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag);
-	if (err)
-		cmd_hashlist_del(cmd);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_queue_command);
-
-/*
- * This is run from a interrupt handler normally and the unmap
- * needs process context so we must queue
- */
-static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
-{
-	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-
-	dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request));
-
-	scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
-
-	scsi_release_buffers(cmd);
-
-	queue_work(scsi_tgtd, &tcmd->work);
-}
-
-static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
-{
-	struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
-	int err;
-
-	dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request));
-
-	err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done);
-	switch (err) {
-	case SCSI_MLQUEUE_HOST_BUSY:
-	case SCSI_MLQUEUE_DEVICE_BUSY:
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-/* TODO: test this crap and replace bio_map_user with new interface maybe */
-static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
-			       unsigned long uaddr, unsigned int len, int rw)
-{
-	struct request_queue *q = cmd->request->q;
-	struct request *rq = cmd->request;
-	int err;
-
-	dprintk("%lx %u\n", uaddr, len);
-	err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL);
-	if (err) {
-		/*
-		 * TODO: need to fixup sg_tablesize, max_segment_size,
-		 * max_sectors, etc for modern HW and software drivers
-		 * where this value is bogus.
-		 *
-		 * TODO2: we can alloc a reserve buffer of max size
-		 * we can handle and do the slow copy path for really large
-		 * IO.
-		 */
-		eprintk("Could not handle request of size %u.\n", len);
-		return err;
-	}
-
-	tcmd->bio = rq->bio;
-	err = scsi_init_io(cmd, GFP_KERNEL);
-	if (err) {
-		scsi_release_buffers(cmd);
-		goto unmap_rq;
-	}
-	/*
-	 * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the
-	 * length for us.
-	 */
-	cmd->sdb.length = blk_rq_bytes(rq);
-
-	return 0;
-
-unmap_rq:
-	scsi_unmap_user_pages(tcmd);
-	return err;
-}
-
-static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,
-				unsigned len)
-{
-	char __user *p = (char __user *) uaddr;
-
-	if (copy_from_user(cmd->sense_buffer, p,
-			   min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) {
-		printk(KERN_ERR "Could not copy the sense buffer\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
-{
-	struct scsi_tgt_cmd *tcmd;
-	int err;
-
-	err = shost->hostt->eh_abort_handler(cmd);
-	if (err)
-		eprintk("fail to abort %p\n", cmd);
-
-	tcmd = cmd->request->end_io_data;
-	scsi_tgt_cmd_destroy(&tcmd->work);
-	return err;
-}
-
-static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag)
-{
-	struct scsi_tgt_queuedata *qdata = q->queuedata;
-	struct request *rq = NULL;
-	struct list_head *head;
-	struct scsi_tgt_cmd *tcmd;
-	unsigned long flags;
-
-	head = &qdata->cmd_hash[cmd_hashfn(tag)];
-	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
-	list_for_each_entry(tcmd, head, hash_list) {
-		if (tcmd->tag == tag) {
-			rq = tcmd->rq;
-			list_del(&tcmd->hash_list);
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
-
-	return rq;
-}
-
-int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag,
-			 unsigned long uaddr, u32 len, unsigned long sense_uaddr,
-			 u32 sense_len, u8 rw)
-{
-	struct Scsi_Host *shost;
-	struct scsi_cmnd *cmd;
-	struct request *rq;
-	struct scsi_tgt_cmd *tcmd;
-	int err = 0;
-
-	dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag,
-		result, len, uaddr, rw);
-
-	/* TODO: replace with a O(1) alg */
-	shost = scsi_host_lookup(host_no);
-	if (!shost) {
-		printk(KERN_ERR "Could not find host no %d\n", host_no);
-		return -EINVAL;
-	}
-
-	if (!shost->uspace_req_q) {
-		printk(KERN_ERR "Not target scsi host %d\n", host_no);
-		goto done;
-	}
-
-	rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag);
-	if (!rq) {
-		printk(KERN_ERR "Could not find tag %llu\n",
-		       (unsigned long long) tag);
-		err = -EINVAL;
-		goto done;
-	}
-	cmd = rq->special;
-
-	dprintk("cmd %p scb %x result %d len %d bufflen %u %u %x\n",
-		cmd, cmd->cmnd[0], result, len, scsi_bufflen(cmd),
-		rq_data_dir(rq), cmd->cmnd[0]);
-
-	if (result == TASK_ABORTED) {
-		scsi_tgt_abort_cmd(shost, cmd);
-		goto done;
-	}
-	/*
-	 * store the userspace values here, the working values are
-	 * in the request_* values
-	 */
-	tcmd = cmd->request->end_io_data;
-	cmd->result = result;
-
-	if (cmd->result == SAM_STAT_CHECK_CONDITION)
-		scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len);
-
-	if (len) {
-		err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
-		if (err) {
-			/*
-			 * user-space daemon bugs or OOM
-			 * TODO: we can do better for OOM.
-			 */
-			struct scsi_tgt_queuedata *qdata;
-			struct list_head *head;
-			unsigned long flags;
-
-			eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",
-				cmd, err, uaddr, len, rw);
-
-			qdata = shost->uspace_req_q->queuedata;
-			head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)];
-
-			spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
-			list_add(&tcmd->hash_list, head);
-			spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
-
-			goto done;
-		}
-	}
-	err = scsi_tgt_transfer_response(cmd);
-done:
-	scsi_host_put(shost);
-	return err;
-}
-
-int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id,
-			      int function, u64 tag, struct scsi_lun *scsilun,
-			      void *data)
-{
-	int err;
-
-	/* TODO: need to retry if this fails. */
-	err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id,
-					    function, tag, scsilun, data);
-	if (err < 0)
-		eprintk("The task management request lost!\n");
-	return err;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request);
-
-int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result)
-{
-	struct Scsi_Host *shost;
-	int err = -EINVAL;
-
-	dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
-
-	shost = scsi_host_lookup(host_no);
-	if (!shost) {
-		printk(KERN_ERR "Could not find host no %d\n", host_no);
-		return err;
-	}
-
-	if (!shost->uspace_req_q) {
-		printk(KERN_ERR "Not target scsi host %d\n", host_no);
-		goto done;
-	}
-
-	err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result);
-done:
-	scsi_host_put(shost);
-	return err;
-}
-
-int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
-			     char *initiator)
-{
-	int err;
-
-	/* TODO: need to retry if this fails. */
-	err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0,
-						    initiator);
-	if (err < 0)
-		eprintk("The i_t_neuxs request lost, %d %llx!\n",
-			shost->host_no, (unsigned long long)itn_id);
-	return err;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create);
-
-int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
-{
-	int err;
-
-	/* TODO: need to retry if this fails. */
-	err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no,
-						    itn_id, 1, NULL);
-	if (err < 0)
-		eprintk("The i_t_neuxs request lost, %d %llx!\n",
-			shost->host_no, (unsigned long long)itn_id);
-	return err;
-}
-EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy);
-
-int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result)
-{
-	struct Scsi_Host *shost;
-	int err = -EINVAL;
-
-	dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id);
-
-	shost = scsi_host_lookup(host_no);
-	if (!shost) {
-		printk(KERN_ERR "Could not find host no %d\n", host_no);
-		return err;
-	}
-
-	if (!shost->uspace_req_q) {
-		printk(KERN_ERR "Not target scsi host %d\n", host_no);
-		goto done;
-	}
-
-	err = shost->transportt->it_nexus_response(shost, itn_id, result);
-done:
-	scsi_host_put(shost);
-	return err;
-}
-
-static int __init scsi_tgt_init(void)
-{
-	int err;
-
-	scsi_tgt_cmd_cache =  KMEM_CACHE(scsi_tgt_cmd, 0);
-	if (!scsi_tgt_cmd_cache)
-		return -ENOMEM;
-
-	scsi_tgtd = alloc_workqueue("scsi_tgtd", 0, 1);
-	if (!scsi_tgtd) {
-		err = -ENOMEM;
-		goto free_kmemcache;
-	}
-
-	err = scsi_tgt_if_init();
-	if (err)
-		goto destroy_wq;
-
-	return 0;
-
-destroy_wq:
-	destroy_workqueue(scsi_tgtd);
-free_kmemcache:
-	kmem_cache_destroy(scsi_tgt_cmd_cache);
-	return err;
-}
-
-static void __exit scsi_tgt_exit(void)
-{
-	destroy_workqueue(scsi_tgtd);
-	scsi_tgt_if_exit();
-	kmem_cache_destroy(scsi_tgt_cmd_cache);
-}
-
-module_init(scsi_tgt_init);
-module_exit(scsi_tgt_exit);
-
-MODULE_DESCRIPTION("SCSI target core");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_priv.h linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_priv.h
--- linux-libre-3.16-gnu/drivers/scsi/scsi_tgt_priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_tgt_priv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-struct scsi_cmnd;
-struct scsi_lun;
-struct Scsi_Host;
-struct task_struct;
-
-/* tmp - will replace with SCSI logging stuff */
-#define eprintk(fmt, args...)					\
-do {								\
-	printk("%s(%d) " fmt, __func__, __LINE__, ##args);	\
-} while (0)
-
-#define dprintk(fmt, args...)
-/* #define dprintk eprintk */
-
-extern void scsi_tgt_if_exit(void);
-extern int scsi_tgt_if_init(void);
-
-extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id,
-				    struct scsi_lun *lun, u64 tag);
-extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id,
-				       u64 tag);
-extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag,
-				unsigned long uaddr, u32 len,
-				unsigned long sense_uaddr, u32 sense_len, u8 rw);
-extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id,
-					 int function, u64 tag,
-					 struct scsi_lun *scsilun, void *data);
-extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id,
-				    u64 mid, int result);
-extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id,
-						 int function, char *initiator);
-extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_trace.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_trace.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_trace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_trace.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@ scsi_trace_misc(struct trace_seq *, unsi
 static const char *
 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= ((cdb[1] & 0x1F) << 16);
@@ -46,7 +46,7 @@ scsi_trace_rw6(struct trace_seq *p, unsi
 static const char *
 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= (cdb[2] << 24);
@@ -71,7 +71,7 @@ scsi_trace_rw10(struct trace_seq *p, uns
 static const char *
 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= (cdb[2] << 24);
@@ -94,7 +94,7 @@ scsi_trace_rw12(struct trace_seq *p, uns
 static const char *
 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= ((u64)cdb[2] << 56);
@@ -125,7 +125,7 @@ scsi_trace_rw16(struct trace_seq *p, uns
 static const char *
 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len, *cmd;
+	const char *ret = trace_seq_buffer_ptr(p), *cmd;
 	sector_t lba = 0, txlen = 0;
 	u32 ei_lbrt = 0;
 
@@ -180,7 +180,7 @@ out:
 static const char *
 scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	unsigned int regions = cdb[7] << 8 | cdb[8];
 
 	trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
@@ -192,7 +192,7 @@ scsi_trace_unmap(struct trace_seq *p, un
 static const char *
 scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len, *cmd;
+	const char *ret = trace_seq_buffer_ptr(p), *cmd;
 	sector_t lba = 0;
 	u32 alloc_len = 0;
 
@@ -247,7 +247,7 @@ scsi_trace_varlen(struct trace_seq *p, u
 static const char *
 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	trace_seq_printf(p, "-");
 	trace_seq_putc(p, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_fc.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_fc.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_fc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_fc.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,6 @@
 #include <scsi/scsi_netlink_fc.h>
 #include <scsi/scsi_bsg_fc.h>
 #include "scsi_priv.h"
-#include "scsi_transport_fc_internal.h"
 
 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
 static void fc_vport_sched_delete(struct work_struct *work);
@@ -262,6 +261,10 @@ static const struct {
 	{ FC_PORTSPEED_8GBIT,		"8 Gbit" },
 	{ FC_PORTSPEED_16GBIT,		"16 Gbit" },
 	{ FC_PORTSPEED_32GBIT,		"32 Gbit" },
+	{ FC_PORTSPEED_20GBIT,		"20 Gbit" },
+	{ FC_PORTSPEED_40GBIT,		"40 Gbit" },
+	{ FC_PORTSPEED_50GBIT,		"50 Gbit" },
+	{ FC_PORTSPEED_100GBIT,		"100 Gbit" },
 	{ FC_PORTSPEED_NOT_NEGOTIATED,	"Not Negotiated" },
 };
 fc_bitfield_name_search(port_speed, fc_port_speed_names)
@@ -2089,7 +2092,7 @@ fc_timed_out(struct scsi_cmnd *scmd)
  * on the rport.
  */
 static void
-fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
+fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun)
 {
 	struct fc_rport *rport;
 	unsigned long flags;
@@ -2121,7 +2124,7 @@ fc_user_scan_tgt(struct Scsi_Host *shost
  * object as the parent.
  */
 static int
-fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun)
+fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun)
 {
 	uint chlo, chhi;
 	uint tgtlo, tgthi;
@@ -3008,10 +3011,6 @@ fc_remote_port_delete(struct fc_rport  *
 
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
-	if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR &&
-	    shost->active_mode & MODE_TARGET)
-		fc_tgt_it_nexus_destroy(shost, (unsigned long)rport);
-
 	scsi_target_block(&rport->dev);
 
 	/* see if we need to kill io faster than waiting for device loss */
@@ -3052,7 +3051,6 @@ fc_remote_port_rolechg(struct fc_rport
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	unsigned long flags;
 	int create = 0;
-	int ret;
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (roles & FC_PORT_ROLE_FCP_TARGET) {
@@ -3061,12 +3059,6 @@ fc_remote_port_rolechg(struct fc_rport
 			create = 1;
 		} else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
 			create = 1;
-	} else if (shost->active_mode & MODE_TARGET) {
-		ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport,
-					     (char *)&rport->node_name);
-		if (ret)
-			printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n",
-			       ret);
 	}
 
 	rport->roles = roles;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_fc_internal.h linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_fc_internal.h
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_fc_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_fc_internal.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-#include <scsi/scsi_tgt.h>
-
-#ifdef CONFIG_SCSI_FC_TGT_ATTRS
-static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
-					 char *initiator)
-{
-	return scsi_tgt_it_nexus_create(shost, itn_id, initiator);
-}
-
-static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
-{
-	return scsi_tgt_it_nexus_destroy(shost, itn_id);
-}
-#else
-static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
-					 char *initiator)
-{
-	return 0;
-}
-
-static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
-{
-	return 0;
-}
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_iscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_iscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_iscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_iscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1780,7 +1780,7 @@ EXPORT_SYMBOL_GPL(iscsi_scan_finished);
 struct iscsi_scan_data {
 	unsigned int channel;
 	unsigned int id;
-	unsigned int lun;
+	u64 lun;
 };
 
 static int iscsi_user_scan_session(struct device *dev, void *data)
@@ -1827,7 +1827,7 @@ user_scan_exit:
 }
 
 static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
-			   uint id, uint lun)
+			   uint id, u64 lun)
 {
 	struct iscsi_scan_data scan_data;
 
@@ -3059,7 +3059,7 @@ iscsi_get_chap(struct iscsi_transport *t
 		evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
 		evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
 		evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
-		buf = (char *) ((char *)evchap + sizeof(*evchap));
+		buf = (char *)evchap + sizeof(*evchap);
 		memset(buf, 0, chap_buf_size);
 
 		err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
@@ -3429,7 +3429,7 @@ iscsi_get_host_stats(struct iscsi_transp
 	char *buf;
 
 	if (!transport->get_host_stats)
-		return -EINVAL;
+		return -ENOSYS;
 
 	priv = iscsi_if_transport_lookup(transport);
 	if (!priv)
@@ -3463,10 +3463,14 @@ iscsi_get_host_stats(struct iscsi_transp
 		evhost_stats->type = nlh->nlmsg_type;
 		evhost_stats->u.get_host_stats.host_no =
 					ev->u.get_host_stats.host_no;
-		buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats));
+		buf = (char *)evhost_stats + sizeof(*evhost_stats);
 		memset(buf, 0, host_stats_size);
 
 		err = transport->get_host_stats(shost, buf, host_stats_size);
+		if (err) {
+			kfree_skb(skbhost_stats);
+			goto exit_host_stats;
+		}
 
 		actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
 		skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_sas.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_sas.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_sas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_sas.c	2014-09-28 17:29:07.000000000 -0400
@@ -1705,7 +1705,7 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
  */
 
 static int sas_user_scan(struct Scsi_Host *shost, uint channel,
-		uint id, uint lun)
+		uint id, u64 lun)
 {
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 	struct sas_rphy *rphy;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_srp.c linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_srp.c
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_srp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_srp.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_srp.h>
 #include "scsi_priv.h"
-#include "scsi_transport_srp_internal.h"
 
 struct srp_host_attrs {
 	atomic_t next_port_id;
@@ -473,7 +472,8 @@ static void __srp_start_tl_fail_timers(s
 	if (delay > 0)
 		queue_delayed_work(system_long_wq, &rport->reconnect_work,
 				   1UL * delay * HZ);
-	if (srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
+	if ((fast_io_fail_tmo >= 0 || dev_loss_tmo >= 0) &&
+	    srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
 		pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev),
 			 rport->state);
 		scsi_target_block(&shost->shost_gendev);
@@ -746,18 +746,6 @@ struct srp_rport *srp_rport_add(struct S
 		return ERR_PTR(ret);
 	}
 
-	if (shost->active_mode & MODE_TARGET &&
-	    ids->roles == SRP_RPORT_ROLE_INITIATOR) {
-		ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport,
-					      rport->port_id);
-		if (ret) {
-			device_del(&rport->dev);
-			transport_destroy_device(&rport->dev);
-			put_device(&rport->dev);
-			return ERR_PTR(ret);
-		}
-	}
-
 	transport_add_device(&rport->dev);
 	transport_configure_device(&rport->dev);
 
@@ -774,11 +762,6 @@ EXPORT_SYMBOL_GPL(srp_rport_add);
 void srp_rport_del(struct srp_rport *rport)
 {
 	struct device *dev = &rport->dev;
-	struct Scsi_Host *shost = dev_to_shost(dev->parent);
-
-	if (shost->active_mode & MODE_TARGET &&
-	    rport->roles == SRP_RPORT_ROLE_INITIATOR)
-		srp_tgt_it_nexus_destroy(shost, (unsigned long)rport);
 
 	transport_remove_device(dev);
 	device_del(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/scsi_transport_srp_internal.h linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_srp_internal.h
--- linux-libre-3.16-gnu/drivers/scsi/scsi_transport_srp_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/scsi_transport_srp_internal.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-#include <scsi/scsi_tgt.h>
-
-#ifdef CONFIG_SCSI_SRP_TGT_ATTRS
-static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
-					  char *initiator)
-{
-	return scsi_tgt_it_nexus_create(shost, itn_id, initiator);
-}
-
-static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
-{
-	return scsi_tgt_it_nexus_destroy(shost, itn_id);
-}
-
-#else
-static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
-					  char *initiator)
-{
-	return 0;
-}
-static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
-{
-	return 0;
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sd.c linux-libre-3.17-rc7-gnu/drivers/scsi/sd.c
--- linux-libre-3.16-gnu/drivers/scsi/sd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sd.c	2014-09-28 17:29:07.000000000 -0400
@@ -134,6 +134,19 @@ static const char *sd_cache_types[] = {
 	"write back, no read (daft)"
 };
 
+static void sd_set_flush_flag(struct scsi_disk *sdkp)
+{
+	unsigned flush = 0;
+
+	if (sdkp->WCE) {
+		flush |= REQ_FLUSH;
+		if (sdkp->DPOFUA)
+			flush |= REQ_FUA;
+	}
+
+	blk_queue_flush(sdkp->disk->queue, flush);
+}
+
 static ssize_t
 cache_type_store(struct device *dev, struct device_attribute *attr,
 		 const char *buf, size_t count)
@@ -177,6 +190,7 @@ cache_type_store(struct device *dev, str
 	if (sdkp->cache_override) {
 		sdkp->WCE = wce;
 		sdkp->RCD = rcd;
+		sd_set_flush_flag(sdkp);
 		return count;
 	}
 
@@ -677,8 +691,10 @@ static void sd_config_discard(struct scs
  * Will issue either UNMAP or WRITE SAME(16) depending on preference
  * indicated by target device.
  **/
-static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
 {
+	struct request *rq = cmd->request;
+	struct scsi_device *sdp = cmd->device;
 	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
 	sector_t sector = blk_rq_pos(rq);
 	unsigned int nr_sectors = blk_rq_sectors(rq);
@@ -690,9 +706,6 @@ static int sd_setup_discard_cmnd(struct
 
 	sector >>= ilog2(sdp->sector_size) - 9;
 	nr_sectors >>= ilog2(sdp->sector_size) - 9;
-	rq->timeout = SD_TIMEOUT;
-
-	memset(rq->cmd, 0, rq->cmd_len);
 
 	page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
 	if (!page)
@@ -702,9 +715,9 @@ static int sd_setup_discard_cmnd(struct
 	case SD_LBP_UNMAP:
 		buf = page_address(page);
 
-		rq->cmd_len = 10;
-		rq->cmd[0] = UNMAP;
-		rq->cmd[8] = 24;
+		cmd->cmd_len = 10;
+		cmd->cmnd[0] = UNMAP;
+		cmd->cmnd[8] = 24;
 
 		put_unaligned_be16(6 + 16, &buf[0]);
 		put_unaligned_be16(16, &buf[2]);
@@ -715,23 +728,23 @@ static int sd_setup_discard_cmnd(struct
 		break;
 
 	case SD_LBP_WS16:
-		rq->cmd_len = 16;
-		rq->cmd[0] = WRITE_SAME_16;
-		rq->cmd[1] = 0x8; /* UNMAP */
-		put_unaligned_be64(sector, &rq->cmd[2]);
-		put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+		cmd->cmd_len = 16;
+		cmd->cmnd[0] = WRITE_SAME_16;
+		cmd->cmnd[1] = 0x8; /* UNMAP */
+		put_unaligned_be64(sector, &cmd->cmnd[2]);
+		put_unaligned_be32(nr_sectors, &cmd->cmnd[10]);
 
 		len = sdkp->device->sector_size;
 		break;
 
 	case SD_LBP_WS10:
 	case SD_LBP_ZERO:
-		rq->cmd_len = 10;
-		rq->cmd[0] = WRITE_SAME;
+		cmd->cmd_len = 10;
+		cmd->cmnd[0] = WRITE_SAME;
 		if (sdkp->provisioning_mode == SD_LBP_WS10)
-			rq->cmd[1] = 0x8; /* UNMAP */
-		put_unaligned_be32(sector, &rq->cmd[2]);
-		put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+			cmd->cmnd[1] = 0x8; /* UNMAP */
+		put_unaligned_be32(sector, &cmd->cmnd[2]);
+		put_unaligned_be16(nr_sectors, &cmd->cmnd[7]);
 
 		len = sdkp->device->sector_size;
 		break;
@@ -742,8 +755,21 @@ static int sd_setup_discard_cmnd(struct
 	}
 
 	rq->completion_data = page;
+	rq->timeout = SD_TIMEOUT;
+
+	cmd->transfersize = len;
+	cmd->allowed = SD_MAX_RETRIES;
+
+	/*
+	 * Initially __data_len is set to the amount of data that needs to be
+	 * transferred to the target. This amount depends on whether WRITE SAME
+	 * or UNMAP is being used. After the scatterlist has been mapped by
+	 * scsi_init_io() we set __data_len to the size of the area to be
+	 * discarded on disk. This allows us to report completion on the full
+	 * amount of blocks described by the request.
+	 */
 	blk_add_request_payload(rq, page, len);
-	ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+	ret = scsi_init_io(cmd, GFP_ATOMIC);
 	rq->__data_len = nr_bytes;
 
 out:
@@ -785,14 +811,15 @@ out:
 
 /**
  * sd_setup_write_same_cmnd - write the same data to multiple blocks
- * @sdp: scsi device to operate one
- * @rq: Request to prepare
+ * @cmd: command to prepare
  *
  * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
  * preference indicated by target device.
  **/
-static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
 {
+	struct request *rq = cmd->request;
+	struct scsi_device *sdp = cmd->device;
 	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
 	struct bio *bio = rq->bio;
 	sector_t sector = blk_rq_pos(rq);
@@ -808,53 +835,56 @@ static int sd_setup_write_same_cmnd(stru
 	sector >>= ilog2(sdp->sector_size) - 9;
 	nr_sectors >>= ilog2(sdp->sector_size) - 9;
 
-	rq->__data_len = sdp->sector_size;
 	rq->timeout = SD_WRITE_SAME_TIMEOUT;
-	memset(rq->cmd, 0, rq->cmd_len);
 
 	if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
-		rq->cmd_len = 16;
-		rq->cmd[0] = WRITE_SAME_16;
-		put_unaligned_be64(sector, &rq->cmd[2]);
-		put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+		cmd->cmd_len = 16;
+		cmd->cmnd[0] = WRITE_SAME_16;
+		put_unaligned_be64(sector, &cmd->cmnd[2]);
+		put_unaligned_be32(nr_sectors, &cmd->cmnd[10]);
 	} else {
-		rq->cmd_len = 10;
-		rq->cmd[0] = WRITE_SAME;
-		put_unaligned_be32(sector, &rq->cmd[2]);
-		put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+		cmd->cmd_len = 10;
+		cmd->cmnd[0] = WRITE_SAME;
+		put_unaligned_be32(sector, &cmd->cmnd[2]);
+		put_unaligned_be16(nr_sectors, &cmd->cmnd[7]);
 	}
 
-	ret = scsi_setup_blk_pc_cmnd(sdp, rq);
-	rq->__data_len = nr_bytes;
+	cmd->transfersize = sdp->sector_size;
+	cmd->allowed = SD_MAX_RETRIES;
 
+	/*
+	 * For WRITE_SAME the data transferred in the DATA IN buffer is
+	 * different from the amount of data actually written to the target.
+	 *
+	 * We set up __data_len to the amount of data transferred from the
+	 * DATA IN buffer so that blk_rq_map_sg set up the proper S/G list
+	 * to transfer a single sector of data first, but then reset it to
+	 * the amount of data to be written right after so that the I/O path
+	 * knows how much to actually write.
+	 */
+	rq->__data_len = sdp->sector_size;
+	ret = scsi_init_io(cmd, GFP_ATOMIC);
+	rq->__data_len = nr_bytes;
 	return ret;
 }
 
-static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
 {
-	rq->timeout *= SD_FLUSH_TIMEOUT_MULTIPLIER;
-	rq->retries = SD_MAX_RETRIES;
-	rq->cmd[0] = SYNCHRONIZE_CACHE;
-	rq->cmd_len = 10;
-
-	return scsi_setup_blk_pc_cmnd(sdp, rq);
-}
+	struct request *rq = cmd->request;
 
-static void sd_uninit_command(struct scsi_cmnd *SCpnt)
-{
-	struct request *rq = SCpnt->request;
+	/* flush requests don't perform I/O, zero the S/G table */
+	memset(&cmd->sdb, 0, sizeof(cmd->sdb));
 
-	if (rq->cmd_flags & REQ_DISCARD)
-		__free_page(rq->completion_data);
+	cmd->cmnd[0] = SYNCHRONIZE_CACHE;
+	cmd->cmd_len = 10;
+	cmd->transfersize = 0;
+	cmd->allowed = SD_MAX_RETRIES;
 
-	if (SCpnt->cmnd != rq->cmd) {
-		mempool_free(SCpnt->cmnd, sd_cdb_pool);
-		SCpnt->cmnd = NULL;
-		SCpnt->cmd_len = 0;
-	}
+	rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER;
+	return BLKPREP_OK;
 }
 
-static int sd_init_command(struct scsi_cmnd *SCpnt)
+static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
 {
 	struct request *rq = SCpnt->request;
 	struct scsi_device *sdp = SCpnt->device;
@@ -866,21 +896,7 @@ static int sd_init_command(struct scsi_c
 	int ret, host_dif;
 	unsigned char protect;
 
-	/*
-	 * Discard request come in as REQ_TYPE_FS but we turn them into
-	 * block PC requests to make life easier.
-	 */
-	if (rq->cmd_flags & REQ_DISCARD) {
-		ret = sd_setup_discard_cmnd(sdp, rq);
-		goto out;
-	} else if (rq->cmd_flags & REQ_WRITE_SAME) {
-		ret = sd_setup_write_same_cmnd(sdp, rq);
-		goto out;
-	} else if (rq->cmd_flags & REQ_FLUSH) {
-		ret = scsi_setup_flush_cmnd(sdp, rq);
-		goto out;
-	}
-	ret = scsi_setup_fs_cmnd(sdp, rq);
+	ret = scsi_init_io(SCpnt, GFP_ATOMIC);
 	if (ret != BLKPREP_OK)
 		goto out;
 	SCpnt = rq->special;
@@ -976,18 +992,13 @@ static int sd_init_command(struct scsi_c
 		}
 	}
 	if (rq_data_dir(rq) == WRITE) {
-		if (!sdp->writeable) {
-			goto out;
-		}
 		SCpnt->cmnd[0] = WRITE_6;
-		SCpnt->sc_data_direction = DMA_TO_DEVICE;
 
 		if (blk_integrity_rq(rq))
 			sd_dif_prepare(rq, block, sdp->sector_size);
 
 	} else if (rq_data_dir(rq) == READ) {
 		SCpnt->cmnd[0] = READ_6;
-		SCpnt->sc_data_direction = DMA_FROM_DEVICE;
 	} else {
 		scmd_printk(KERN_ERR, SCpnt, "Unknown command %llx\n", (unsigned long long) rq->cmd_flags);
 		goto out;
@@ -1042,7 +1053,7 @@ static int sd_init_command(struct scsi_c
 		SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff;
 		SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff;
 		SCpnt->cmnd[31] = (unsigned char) this_count & 0xff;
-	} else if (sdp->use_16_for_rw) {
+	} else if (sdp->use_16_for_rw || (this_count > 0xffff)) {
 		SCpnt->cmnd[0] += READ_16 - READ_6;
 		SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0);
 		SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
@@ -1061,9 +1072,6 @@ static int sd_init_command(struct scsi_c
 	} else if ((this_count > 0xff) || (block > 0x1fffff) ||
 		   scsi_device_protection(SCpnt->device) ||
 		   SCpnt->device->use_10_for_rw) {
-		if (this_count > 0xffff)
-			this_count = 0xffff;
-
 		SCpnt->cmnd[0] += READ_10 - READ_6;
 		SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0);
 		SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
@@ -1116,6 +1124,34 @@ static int sd_init_command(struct scsi_c
 	return ret;
 }
 
+static int sd_init_command(struct scsi_cmnd *cmd)
+{
+	struct request *rq = cmd->request;
+
+	if (rq->cmd_flags & REQ_DISCARD)
+		return sd_setup_discard_cmnd(cmd);
+	else if (rq->cmd_flags & REQ_WRITE_SAME)
+		return sd_setup_write_same_cmnd(cmd);
+	else if (rq->cmd_flags & REQ_FLUSH)
+		return sd_setup_flush_cmnd(cmd);
+	else
+		return sd_setup_read_write_cmnd(cmd);
+}
+
+static void sd_uninit_command(struct scsi_cmnd *SCpnt)
+{
+	struct request *rq = SCpnt->request;
+
+	if (rq->cmd_flags & REQ_DISCARD)
+		__free_page(rq->completion_data);
+
+	if (SCpnt->cmnd != rq->cmd) {
+		mempool_free(SCpnt->cmnd, sd_cdb_pool);
+		SCpnt->cmnd = NULL;
+		SCpnt->cmd_len = 0;
+	}
+}
+
 /**
  *	sd_open - open a scsi disk device
  *	@inode: only i_rdev member may be used
@@ -2225,7 +2261,11 @@ got_data:
 		}
 	}
 
-	sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
+	if (sdkp->capacity > 0xffffffff) {
+		sdp->use_16_for_rw = 1;
+		sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
+	} else
+		sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
 
 	/* Rescale capacity to 512-byte units */
 	if (sector_size == 4096)
@@ -2540,6 +2580,7 @@ static void sd_read_block_limits(struct
 {
 	unsigned int sector_sz = sdkp->device->sector_size;
 	const int vpd_len = 64;
+	u32 max_xfer_length;
 	unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
 
 	if (!buffer ||
@@ -2547,6 +2588,10 @@ static void sd_read_block_limits(struct
 	    scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
 		goto out;
 
+	max_xfer_length = get_unaligned_be32(&buffer[8]);
+	if (max_xfer_length)
+		sdkp->max_xfer_blocks = max_xfer_length;
+
 	blk_queue_io_min(sdkp->disk->queue,
 			 get_unaligned_be16(&buffer[6]) * sector_sz);
 	blk_queue_io_opt(sdkp->disk->queue,
@@ -2681,6 +2726,11 @@ static void sd_read_write_same(struct sc
 
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
+	/* Attempt VPD inquiry if the device blacklist explicitly calls
+	 * for it.
+	 */
+	if (sdp->try_vpd_pages)
+		return 1;
 	/*
 	 * Although VPD inquiries can go to SCSI-2 type devices,
 	 * some USB ones crash on receiving them, and the pages
@@ -2701,7 +2751,7 @@ static int sd_revalidate_disk(struct gen
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
 	unsigned char *buffer;
-	unsigned flush = 0;
+	unsigned int max_xfer;
 
 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
 				      "sd_revalidate_disk\n"));
@@ -2747,14 +2797,12 @@ static int sd_revalidate_disk(struct gen
 	 * We now have all cache related info, determine how we deal
 	 * with flush requests.
 	 */
-	if (sdkp->WCE) {
-		flush |= REQ_FLUSH;
-		if (sdkp->DPOFUA)
-			flush |= REQ_FUA;
-	}
-
-	blk_queue_flush(sdkp->disk->queue, flush);
+	sd_set_flush_flag(sdkp);
 
+	max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
+				sdkp->max_xfer_blocks);
+	max_xfer <<= ilog2(sdp->sector_size) - 9;
+	blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
 	set_capacity(disk, sdkp->capacity);
 	sd_config_write_same(sdkp);
 	kfree(buffer);
@@ -3208,12 +3256,14 @@ static int __init init_sd(void)
 					 0, 0, NULL);
 	if (!sd_cdb_cache) {
 		printk(KERN_ERR "sd: can't init extended cdb cache\n");
+		err = -ENOMEM;
 		goto err_out_class;
 	}
 
 	sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache);
 	if (!sd_cdb_pool) {
 		printk(KERN_ERR "sd: can't init extended cdb pool\n");
+		err = -ENOMEM;
 		goto err_out_cache;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sd.h linux-libre-3.17-rc7-gnu/drivers/scsi/sd.h
--- linux-libre-3.16-gnu/drivers/scsi/sd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sd.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,8 @@ enum {
 };
 
 enum {
+	SD_DEF_XFER_BLOCKS = 0xffff,
+	SD_MAX_XFER_BLOCKS = 0xffffffff,
 	SD_MAX_WS10_BLOCKS = 0xffff,
 	SD_MAX_WS16_BLOCKS = 0x7fffff,
 };
@@ -64,6 +66,7 @@ struct scsi_disk {
 	struct gendisk	*disk;
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
+	u32		max_xfer_blocks;
 	u32		max_ws_blocks;
 	u32		max_unmap_blocks;
 	u32		unmap_granularity;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sg.c linux-libre-3.17-rc7-gnu/drivers/scsi/sg.c
--- linux-libre-3.16-gnu/drivers/scsi/sg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sg.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,9 +7,7 @@
  * Original driver (sg.c):
  *        Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *        Copyright (C) 1998 - 2005 Douglas Gilbert
- *
- *  Modified  19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Devfs support
+ *        Copyright (C) 1998 - 2014 Douglas Gilbert
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,11 +16,11 @@
  *
  */
 
-static int sg_version_num = 30534;	/* 2 digits for each component */
-#define SG_VERSION_STR "3.5.34"
+static int sg_version_num = 30536;	/* 2 digits for each component */
+#define SG_VERSION_STR "3.5.36"
 
 /*
- *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
+ *  D. P. Gilbert (dgilbert@interlog.com), notes:
  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
  *        the kernel/module needs to be built with CONFIG_SCSI_LOGGING
  *        (otherwise the macros compile to empty statements).
@@ -51,6 +49,7 @@ static int sg_version_num = 30534;	/* 2
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/mutex.h>
+#include <linux/atomic.h>
 #include <linux/ratelimit.h>
 
 #include "scsi.h"
@@ -64,7 +63,7 @@ static int sg_version_num = 30534;	/* 2
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20061027";
+static char *sg_version_date = "20140603";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -74,6 +73,12 @@ static void sg_proc_cleanup(void);
 
 #define SG_MAX_DEVS 32768
 
+/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
+ * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
+ * than 16 bytes are "variable length" whose length is a multiple of 4
+ */
+#define SG_MAX_CDB_SIZE 252
+
 /*
  * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
  * Then when using 32 bit integers x * m may overflow during the calculation.
@@ -102,18 +107,16 @@ static int scatter_elem_sz_prev = SG_SCA
 
 #define SG_SECTOR_SZ 512
 
-static int sg_add(struct device *, struct class_interface *);
-static void sg_remove(struct device *, struct class_interface *);
-
-static DEFINE_SPINLOCK(sg_open_exclusive_lock);
+static int sg_add_device(struct device *, struct class_interface *);
+static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
 							   file descriptor list for device */
 
 static struct class_interface sg_interface = {
-	.add_dev	= sg_add,
-	.remove_dev	= sg_remove,
+	.add_dev        = sg_add_device,
+	.remove_dev     = sg_remove_device,
 };
 
 typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
@@ -146,8 +149,7 @@ typedef struct sg_request {	/* SG_MAX_QU
 } Sg_request;
 
 typedef struct sg_fd {		/* holds the state of a file descriptor */
-	/* sfd_siblings is protected by sg_index_lock */
-	struct list_head sfd_siblings;
+	struct list_head sfd_siblings;  /* protected by device's sfd_lock */
 	struct sg_device *parentdp;	/* owning device */
 	wait_queue_head_t read_wait;	/* queue read until command done */
 	rwlock_t rq_list_lock;	/* protect access to list in req_arr */
@@ -161,7 +163,7 @@ typedef struct sg_fd {		/* holds the sta
 	char low_dma;		/* as in parent but possibly overridden to 1 */
 	char force_packid;	/* 1 -> pack_id input to read(), 0 -> ignored */
 	char cmd_q;		/* 1 -> allow command queuing, 0 -> don't */
-	char next_cmd_len;	/* 0 -> automatic (def), >0 -> use on next write() */
+	unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
 	char keep_orphan;	/* 0 -> drop orphan (def), 1 -> keep for read() */
 	char mmap_called;	/* 0 -> mmap() never called on this fd */
 	struct kref f_ref;
@@ -170,14 +172,15 @@ typedef struct sg_fd {		/* holds the sta
 
 typedef struct sg_device { /* holds the state of each scsi generic device */
 	struct scsi_device *device;
-	wait_queue_head_t o_excl_wait;	/* queue open() when O_EXCL in use */
+	wait_queue_head_t open_wait;    /* queue open() when O_EXCL present */
+	struct mutex open_rel_lock;     /* held when in open() or release() */
 	int sg_tablesize;	/* adapter's max scatter-gather table size */
 	u32 index;		/* device index number */
-	/* sfds is protected by sg_index_lock */
 	struct list_head sfds;
-	volatile char detached;	/* 0->attached, 1->detached pending removal */
-	/* exclude protected by sg_open_exclusive_lock */
-	char exclude;		/* opened for exclusive access */
+	rwlock_t sfd_lock;      /* protect access to sfd list */
+	atomic_t detaching;     /* 0->device usable, 1->device detaching */
+	bool exclude;		/* 1->open(O_EXCL) succeeded and is active */
+	int open_cnt;		/* count of opens (perhaps < num(sfds) ) */
 	char sgdebug;		/* 0->off, 1->sense, 9->dump dev, 10-> all devs */
 	struct gendisk *disk;
 	struct cdev * cdev;	/* char_dev [sysfs: /sys/cdev/major/sg<n>] */
@@ -197,24 +200,28 @@ static ssize_t sg_new_write(Sg_fd *sfp,
 static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
 			   unsigned char *cmnd, int timeout, int blocking);
 static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
-static void sg_remove_scat(Sg_scatter_hold * schp);
+static void sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp);
 static void sg_build_reserve(Sg_fd * sfp, int req_size);
 static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
-static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
+static Sg_fd *sg_add_sfp(Sg_device * sdp);
 static void sg_remove_sfp(struct kref *);
 static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
 static Sg_device *sg_get_dev(int dev);
-static void sg_put_dev(Sg_device *sdp);
+static void sg_device_destroy(struct kref *kref);
 
 #define SZ_SG_HEADER sizeof(struct sg_header)
 #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
 #define SZ_SG_IOVEC sizeof(sg_iovec_t)
 #define SZ_SG_REQ_INFO sizeof(sg_req_info_t)
 
+#define sg_printk(prefix, sdp, fmt, a...) \
+	sdev_printk(prefix, (sdp)->device, "[%s] " fmt, \
+		    (sdp)->disk->disk_name, ##a)
+
 static int sg_allow_access(struct file *filp, unsigned char *cmd)
 {
 	struct sg_fd *sfp = filp->private_data;
@@ -225,38 +232,43 @@ static int sg_allow_access(struct file *
 	return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
 }
 
-static int get_exclude(Sg_device *sdp)
+static int
+open_wait(Sg_device *sdp, int flags)
 {
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	ret = sdp->exclude;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return ret;
-}
+	int retval = 0;
 
-static int set_exclude(Sg_device *sdp, char val)
-{
-	unsigned long flags;
+	if (flags & O_EXCL) {
+		while (sdp->open_cnt > 0) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->open_cnt));
+			mutex_lock(&sdp->open_rel_lock);
 
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	sdp->exclude = val;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return val;
-}
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	} else {
+		while (sdp->exclude) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->exclude));
+			mutex_lock(&sdp->open_rel_lock);
 
-static int sfds_list_empty(Sg_device *sdp)
-{
-	unsigned long flags;
-	int ret;
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	}
 
-	read_lock_irqsave(&sg_index_lock, flags);
-	ret = list_empty(&sdp->sfds);
-	read_unlock_irqrestore(&sg_index_lock, flags);
-	return ret;
+	return retval;
 }
 
+/* Returns 0 on success, else a negated errno value */
 static int
 sg_open(struct inode *inode, struct file *filp)
 {
@@ -265,17 +277,17 @@ sg_open(struct inode *inode, struct file
 	struct request_queue *q;
 	Sg_device *sdp;
 	Sg_fd *sfp;
-	int res;
 	int retval;
 
 	nonseekable_open(inode, filp);
-	SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
+	if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE)))
+		return -EPERM; /* Can't lock it with read only access */
 	sdp = sg_get_dev(dev);
-	if (IS_ERR(sdp)) {
-		retval = PTR_ERR(sdp);
-		sdp = NULL;
-		goto sg_put;
-	}
+	if (IS_ERR(sdp))
+		return PTR_ERR(sdp);
+
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_open: flags=0x%x\n", flags));
 
 	/* This driver's module count bumped by fops_get in <linux/fs.h> */
 	/* Prevent the device driver from vanishing while we sleep */
@@ -287,6 +299,9 @@ sg_open(struct inode *inode, struct file
 	if (retval)
 		goto sdp_put;
 
+	/* scsi_block_when_processing_errors() may block so bypass
+	 * check if O_NONBLOCK. Permits SCSI commands to be issued
+	 * during error recovery. Tread carefully. */
 	if (!((flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device))) {
 		retval = -ENXIO;
@@ -294,65 +309,65 @@ sg_open(struct inode *inode, struct file
 		goto error_out;
 	}
 
-	if (flags & O_EXCL) {
-		if (O_RDONLY == (flags & O_ACCMODE)) {
-			retval = -EPERM; /* Can't lock it with read only access */
-			goto error_out;
-		}
-		if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait,
-					   ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1)));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
-		}
-	} else if (get_exclude(sdp)) {	/* some other fd has an exclusive lock on dev */
-		if (flags & O_NONBLOCK) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
+	mutex_lock(&sdp->open_rel_lock);
+	if (flags & O_NONBLOCK) {
+		if (flags & O_EXCL) {
+			if (sdp->open_cnt > 0) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
+		} else {
+			if (sdp->exclude) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
 		}
+	} else {
+		retval = open_wait(sdp, flags);
+		if (retval) /* -ERESTARTSYS or -ENODEV */
+			goto error_mutex_locked;
 	}
-	if (sdp->detached) {
-		retval = -ENODEV;
-		goto error_out;
-	}
-	if (sfds_list_empty(sdp)) {	/* no existing opens on this device */
+
+	/* N.B. at this point we are holding the open_rel_lock */
+	if (flags & O_EXCL)
+		sdp->exclude = true;
+
+	if (sdp->open_cnt < 1) {  /* no existing opens */
 		sdp->sgdebug = 0;
 		q = sdp->device->request_queue;
 		sdp->sg_tablesize = queue_max_segments(q);
 	}
-	if ((sfp = sg_add_sfp(sdp, dev)))
-		filp->private_data = sfp;
-	else {
-		if (flags & O_EXCL) {
-			set_exclude(sdp, 0);	/* undo if error */
-			wake_up_interruptible(&sdp->o_excl_wait);
-		}
-		retval = -ENOMEM;
-		goto error_out;
+	sfp = sg_add_sfp(sdp);
+	if (IS_ERR(sfp)) {
+		retval = PTR_ERR(sfp);
+		goto out_undo;
 	}
+
+	filp->private_data = sfp;
+	sdp->open_cnt++;
+	mutex_unlock(&sdp->open_rel_lock);
+
 	retval = 0;
-error_out:
-	if (retval) {
-		scsi_autopm_put_device(sdp->device);
-sdp_put:
-		scsi_device_put(sdp->device);
-	}
 sg_put:
-	if (sdp)
-		sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	return retval;
+
+out_undo:
+	if (flags & O_EXCL) {
+		sdp->exclude = false;   /* undo if error */
+		wake_up_interruptible(&sdp->open_wait);
+	}
+error_mutex_locked:
+	mutex_unlock(&sdp->open_rel_lock);
+error_out:
+	scsi_autopm_put_device(sdp->device);
+sdp_put:
+	scsi_device_put(sdp->device);
+	goto sg_put;
 }
 
-/* Following function was formerly called 'sg_close' */
+/* Release resources associated with a successful sg_open()
+ * Returns 0 on success, else a negated errno value */
 static int
 sg_release(struct inode *inode, struct file *filp)
 {
@@ -361,13 +376,22 @@ sg_release(struct inode *inode, struct f
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
-	SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
-
-	set_exclude(sdp, 0);
-	wake_up_interruptible(&sdp->o_excl_wait);
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n"));
 
+	mutex_lock(&sdp->open_rel_lock);
 	scsi_autopm_put_device(sdp->device);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
+	sdp->open_cnt--;
+
+	/* possibly many open()s waiting on exlude clearing, start many;
+	 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
+	if (sdp->exclude) {
+		sdp->exclude = false;
+		wake_up_interruptible_all(&sdp->open_wait);
+	} else if (0 == sdp->open_cnt) {
+		wake_up_interruptible(&sdp->open_wait);
+	}
+	mutex_unlock(&sdp->open_rel_lock);
 	return 0;
 }
 
@@ -384,8 +408,8 @@ sg_read(struct file *filp, char __user *
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
-	SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n",
-				   sdp->disk->disk_name, (int) count));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_read: count=%d\n", (int) count));
 
 	if (!access_ok(VERIFY_WRITE, buf, count))
 		return -EFAULT;
@@ -419,7 +443,7 @@ sg_read(struct file *filp, char __user *
 	}
 	srp = sg_get_rq_mark(sfp, req_pack_id);
 	if (!srp) {		/* now wait on packet to arrive */
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -428,9 +452,9 @@ sg_read(struct file *filp, char __user *
 			goto free_old_hdr;
 		}
 		retval = wait_event_interruptible(sfp->read_wait,
-			(sdp->detached ||
+			(atomic_read(&sdp->detaching) ||
 			(srp = sg_get_rq_mark(sfp, req_pack_id))));
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -566,13 +590,13 @@ sg_write(struct file *filp, const char _
 	Sg_request *srp;
 	struct sg_header old_hdr;
 	sg_io_hdr_t *hp;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char cmnd[SG_MAX_CDB_SIZE];
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
-	SCSI_LOG_TIMEOUT(3, printk("sg_write: %s, count=%d\n",
-				   sdp->disk->disk_name, (int) count));
-	if (sdp->detached)
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_write: count=%d\n", (int) count));
+	if (atomic_read(&sdp->detaching))
 		return -ENODEV;
 	if (!((filp->f_flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device)))
@@ -592,18 +616,13 @@ sg_write(struct file *filp, const char _
 		return -EIO;	/* The minimum scsi command length is 6 bytes. */
 
 	if (!(srp = sg_add_request(sfp))) {
-		SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n"));
+		SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sdp,
+					      "sg_write: queue full\n"));
 		return -EDOM;
 	}
 	buf += SZ_SG_HEADER;
 	__get_user(opcode, buf);
 	if (sfp->next_cmd_len > 0) {
-		if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
-			SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
-			sfp->next_cmd_len = 0;
-			sg_remove_request(sfp, srp);
-			return -EIO;
-		}
 		cmd_size = sfp->next_cmd_len;
 		sfp->next_cmd_len = 0;	/* reset so only this write() effected */
 	} else {
@@ -611,7 +630,7 @@ sg_write(struct file *filp, const char _
 		if ((opcode >= 0xc0) && old_hdr.twelve_byte)
 			cmd_size = 12;
 	}
-	SCSI_LOG_TIMEOUT(4, printk(
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp,
 		"sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size));
 /* Determine buffer size.  */
 	input_size = count - cmd_size;
@@ -675,7 +694,7 @@ sg_new_write(Sg_fd *sfp, struct file *fi
 	int k;
 	Sg_request *srp;
 	sg_io_hdr_t *hp;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char cmnd[SG_MAX_CDB_SIZE];
 	int timeout;
 	unsigned long ul_timeout;
 
@@ -686,7 +705,8 @@ sg_new_write(Sg_fd *sfp, struct file *fi
 
 	sfp->cmd_q = 1;	/* when sg_io_hdr seen, set command queuing on */
 	if (!(srp = sg_add_request(sfp))) {
-		SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));
+		SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp,
+					      "sg_new_write: queue full\n"));
 		return -EDOM;
 	}
 	srp->sg_io_owned = sg_io_owned;
@@ -743,7 +763,7 @@ static int
 sg_common_write(Sg_fd * sfp, Sg_request * srp,
 		unsigned char *cmnd, int timeout, int blocking)
 {
-	int k, data_dir;
+	int k, data_dir, at_head;
 	Sg_device *sdp = sfp->parentdp;
 	sg_io_hdr_t *hp = &srp->header;
 
@@ -755,16 +775,18 @@ sg_common_write(Sg_fd * sfp, Sg_request
 	hp->host_status = 0;
 	hp->driver_status = 0;
 	hp->resid = 0;
-	SCSI_LOG_TIMEOUT(4, printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
-			  (int) cmnd[0], (int) hp->cmd_len));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+			"sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
+			(int) cmnd[0], (int) hp->cmd_len));
 
 	k = sg_start_req(srp, cmnd);
 	if (k) {
-		SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));
+		SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp,
+			"sg_common_write: start_req err=%d\n", k));
 		sg_finish_rem_req(srp);
 		return k;	/* probably out of space --> ENOMEM */
 	}
-	if (sdp->detached) {
+	if (atomic_read(&sdp->detaching)) {
 		if (srp->bio)
 			blk_end_request_all(srp->rq, -EIO);
 		sg_finish_rem_req(srp);
@@ -787,11 +809,16 @@ sg_common_write(Sg_fd * sfp, Sg_request
 		break;
 	}
 	hp->duration = jiffies_to_msecs(jiffies);
+	if (hp->interface_id != '\0' &&	/* v3 (or later) interface */
+	    (SG_FLAG_Q_AT_TAIL & hp->flags))
+		at_head = 0;
+	else
+		at_head = 1;
 
 	srp->rq->timeout = timeout;
 	kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */
 	blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
-			      srp->rq, 1, sg_rq_end_io);
+			      srp->rq, at_head, sg_rq_end_io);
 	return 0;
 }
 
@@ -806,6 +833,15 @@ static int srp_done(Sg_fd *sfp, Sg_reque
 	return ret;
 }
 
+static int max_sectors_bytes(struct request_queue *q)
+{
+	unsigned int max_sectors = queue_max_sectors(q);
+
+	max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
+
+	return max_sectors << 9;
+}
+
 static long
 sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
@@ -820,13 +856,13 @@ sg_ioctl(struct file *filp, unsigned int
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
 
-	SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n",
-				   sdp->disk->disk_name, (int) cmd_in));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				   "sg_ioctl: cmd=0x%x\n", (int) cmd_in));
 	read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
 
 	switch (cmd_in) {
 	case SG_IO:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (!scsi_block_when_processing_errors(sdp->device))
 			return -ENXIO;
@@ -837,8 +873,8 @@ sg_ioctl(struct file *filp, unsigned int
 		if (result < 0)
 			return result;
 		result = wait_event_interruptible(sfp->read_wait,
-			(srp_done(sfp, srp) || sdp->detached));
-		if (sdp->detached)
+			(srp_done(sfp, srp) || atomic_read(&sdp->detaching)));
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		write_lock_irq(&sfp->rq_list_lock);
 		if (srp->done) {
@@ -873,11 +909,11 @@ sg_ioctl(struct file *filp, unsigned int
 			sfp->low_dma = 1;
 			if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
 				val = (int) sfp->reserve.bufflen;
-				sg_remove_scat(&sfp->reserve);
+				sg_remove_scat(sfp, &sfp->reserve);
 				sg_build_reserve(sfp, val);
 			}
 		} else {
-			if (sdp->detached)
+			if (atomic_read(&sdp->detaching))
 				return -ENODEV;
 			sfp->low_dma = sdp->device->host->unchecked_isa_dma;
 		}
@@ -890,7 +926,7 @@ sg_ioctl(struct file *filp, unsigned int
 		else {
 			sg_scsi_id_t __user *sg_idp = p;
 
-			if (sdp->detached)
+			if (atomic_read(&sdp->detaching))
 				return -ENODEV;
 			__put_user((int) sdp->device->host->host_no,
 				   &sg_idp->host_no);
@@ -945,17 +981,17 @@ sg_ioctl(struct file *filp, unsigned int
                 if (val < 0)
                         return -EINVAL;
 		val = min_t(int, val,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
 		if (val != sfp->reserve.bufflen) {
 			if (sg_res_in_use(sfp) || sfp->mmap_called)
 				return -EBUSY;
-			sg_remove_scat(&sfp->reserve);
+			sg_remove_scat(sfp, &sfp->reserve);
 			sg_build_reserve(sfp, val);
 		}
 		return 0;
 	case SG_GET_RESERVED_SIZE:
 		val = min_t(int, sfp->reserve.bufflen,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
 		return put_user(val, ip);
 	case SG_SET_COMMAND_Q:
 		result = get_user(val, ip);
@@ -1032,11 +1068,11 @@ sg_ioctl(struct file *filp, unsigned int
 			return result;
 		}
 	case SG_EMULATED_HOST:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return put_user(sdp->device->host->hostt->emulated, ip);
 	case SG_SCSI_RESET:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (filp->f_flags & O_NONBLOCK) {
 			if (scsi_host_in_recovery(sdp->device->host))
@@ -1069,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int
 		return (scsi_reset_provider(sdp->device, val) ==
 			SUCCESS) ? 0 : -EIO;
 	case SCSI_IOCTL_SEND_COMMAND:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (read_only) {
 			unsigned char opcode = WRITE_6;
@@ -1091,11 +1127,11 @@ sg_ioctl(struct file *filp, unsigned int
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 	case SCSI_IOCTL_PROBE_HOST:
 	case SG_GET_TRANSFORM:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return scsi_ioctl(sdp->device, cmd_in, p);
 	case BLKSECTGET:
-		return put_user(queue_max_sectors(sdp->device->request_queue) * 512,
+		return put_user(max_sectors_bytes(sdp->device->request_queue),
 				ip);
 	case BLKTRACESETUP:
 		return blk_trace_setup(sdp->device->request_queue,
@@ -1165,15 +1201,15 @@ sg_poll(struct file *filp, poll_table *
 	}
 	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 
-	if (sdp->detached)
+	if (atomic_read(&sdp->detaching))
 		res |= POLLHUP;
 	else if (!sfp->cmd_q) {
 		if (0 == count)
 			res |= POLLOUT | POLLWRNORM;
 	} else if (count < SG_MAX_QUEUE)
 		res |= POLLOUT | POLLWRNORM;
-	SCSI_LOG_TIMEOUT(3, printk("sg_poll: %s, res=0x%x\n",
-				   sdp->disk->disk_name, (int) res));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_poll: res=0x%x\n", (int) res));
 	return res;
 }
 
@@ -1185,8 +1221,8 @@ sg_fasync(int fd, struct file *filp, int
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
-	SCSI_LOG_TIMEOUT(3, printk("sg_fasync: %s, mode=%d\n",
-				   sdp->disk->disk_name, mode));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_fasync: mode=%d\n", mode));
 
 	return fasync_helper(fd, filp, mode, &sfp->async_qp);
 }
@@ -1205,8 +1241,9 @@ sg_vma_fault(struct vm_area_struct *vma,
 	offset = vmf->pgoff << PAGE_SHIFT;
 	if (offset >= rsv_schp->bufflen)
 		return VM_FAULT_SIGBUS;
-	SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n",
-				   offset, rsv_schp->k_use_sg));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp,
+				      "sg_vma_fault: offset=%lu, scatg=%d\n",
+				      offset, rsv_schp->k_use_sg));
 	sa = vma->vm_start;
 	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
 	for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) {
@@ -1241,8 +1278,9 @@ sg_mmap(struct file *filp, struct vm_are
 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
 		return -ENXIO;
 	req_sz = vma->vm_end - vma->vm_start;
-	SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n",
-				   (void *) vma->vm_start, (int) req_sz));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp,
+				      "sg_mmap starting, vm_start=%p, len=%d\n",
+				      (void *) vma->vm_start, (int) req_sz));
 	if (vma->vm_pgoff)
 		return -EINVAL;	/* want no offset */
 	rsv_schp = &sfp->reserve;
@@ -1264,7 +1302,8 @@ sg_mmap(struct file *filp, struct vm_are
 	return 0;
 }
 
-static void sg_rq_end_io_usercontext(struct work_struct *work)
+static void
+sg_rq_end_io_usercontext(struct work_struct *work)
 {
 	struct sg_request *srp = container_of(work, struct sg_request, ew.work);
 	struct sg_fd *sfp = srp->parentfp;
@@ -1277,7 +1316,8 @@ static void sg_rq_end_io_usercontext(str
  * This function is a "bottom half" handler that is called by the mid
  * level when a command is completed (or has failed).
  */
-static void sg_rq_end_io(struct request *rq, int uptodate)
+static void
+sg_rq_end_io(struct request *rq, int uptodate)
 {
 	struct sg_request *srp = rq->end_io_data;
 	Sg_device *sdp;
@@ -1295,15 +1335,16 @@ static void sg_rq_end_io(struct request
 		return;
 
 	sdp = sfp->parentdp;
-	if (unlikely(sdp->detached))
-		printk(KERN_INFO "sg_rq_end_io: device detached\n");
+	if (unlikely(atomic_read(&sdp->detaching)))
+		pr_info("%s: device detaching\n", __func__);
 
 	sense = rq->sense;
 	result = rq->errors;
 	resid = rq->resid_len;
 
-	SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
-		sdp->disk->disk_name, srp->header.pack_id, result));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp,
+				      "sg_cmd_done: pack_id=%d, res=0x%x\n",
+				      srp->header.pack_id, result));
 	srp->header.resid = resid;
 	ms = jiffies_to_msecs(jiffies);
 	srp->header.duration = (ms > srp->header.duration) ?
@@ -1319,7 +1360,7 @@ static void sg_rq_end_io(struct request
 		if ((sdp->sgdebug > 0) &&
 		    ((CHECK_CONDITION == srp->header.masked_status) ||
 		     (COMMAND_TERMINATED == srp->header.masked_status)))
-			__scsi_print_sense("sg_cmd_done", sense,
+			__scsi_print_sense(__func__, sense,
 					   SCSI_SENSE_BUFFERSIZE);
 
 		/* Following if statement is a patch supplied by Eric Youngdale */
@@ -1378,7 +1419,8 @@ static struct class *sg_sysfs_class;
 
 static int sg_sysfs_valid = 0;
 
-static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+static Sg_device *
+sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 {
 	struct request_queue *q = scsidp->request_queue;
 	Sg_device *sdp;
@@ -1388,7 +1430,8 @@ static Sg_device *sg_alloc(struct gendis
 
 	sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL);
 	if (!sdp) {
-		printk(KERN_WARNING "kmalloc Sg_device failure\n");
+		sdev_printk(KERN_WARNING, scsidp, "%s: kmalloc Sg_device "
+			    "failure\n", __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1403,20 +1446,25 @@ static Sg_device *sg_alloc(struct gendis
 				    scsidp->type, SG_MAX_DEVS - 1);
 			error = -ENODEV;
 		} else {
-			printk(KERN_WARNING
-			       "idr allocation Sg_device failure: %d\n", error);
+			sdev_printk(KERN_WARNING, scsidp, "%s: idr "
+				    "allocation Sg_device failure: %d\n",
+				    __func__, error);
 		}
 		goto out_unlock;
 	}
 	k = error;
 
-	SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k));
+	SCSI_LOG_TIMEOUT(3, sdev_printk(KERN_INFO, scsidp,
+					"sg_alloc: dev=%d \n", k));
 	sprintf(disk->disk_name, "sg%d", k);
 	disk->first_minor = k;
 	sdp->disk = disk;
 	sdp->device = scsidp;
+	mutex_init(&sdp->open_rel_lock);
 	INIT_LIST_HEAD(&sdp->sfds);
-	init_waitqueue_head(&sdp->o_excl_wait);
+	init_waitqueue_head(&sdp->open_wait);
+	atomic_set(&sdp->detaching, 0);
+	rwlock_init(&sdp->sfd_lock);
 	sdp->sg_tablesize = queue_max_segments(q);
 	sdp->index = k;
 	kref_init(&sdp->d_ref);
@@ -1434,7 +1482,7 @@ out_unlock:
 }
 
 static int
-sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+sg_add_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	struct gendisk *disk;
@@ -1445,7 +1493,7 @@ sg_add(struct device *cl_dev, struct cla
 
 	disk = alloc_disk(1);
 	if (!disk) {
-		printk(KERN_WARNING "alloc_disk failed\n");
+		pr_warn("%s: alloc_disk failed\n", __func__);
 		return -ENOMEM;
 	}
 	disk->major = SCSI_GENERIC_MAJOR;
@@ -1453,7 +1501,7 @@ sg_add(struct device *cl_dev, struct cla
 	error = -ENOMEM;
 	cdev = cdev_alloc();
 	if (!cdev) {
-		printk(KERN_WARNING "cdev_alloc failed\n");
+		pr_warn("%s: cdev_alloc failed\n", __func__);
 		goto out;
 	}
 	cdev->owner = THIS_MODULE;
@@ -1461,7 +1509,7 @@ sg_add(struct device *cl_dev, struct cla
 
 	sdp = sg_alloc(disk, scsidp);
 	if (IS_ERR(sdp)) {
-		printk(KERN_WARNING "sg_alloc failed\n");
+		pr_warn("%s: sg_alloc failed\n", __func__);
 		error = PTR_ERR(sdp);
 		goto out;
 	}
@@ -1479,22 +1527,20 @@ sg_add(struct device *cl_dev, struct cla
 						      sdp->index),
 						sdp, "%s", disk->disk_name);
 		if (IS_ERR(sg_class_member)) {
-			printk(KERN_ERR "sg_add: "
-			       "device_create failed\n");
+			pr_err("%s: device_create failed\n", __func__);
 			error = PTR_ERR(sg_class_member);
 			goto cdev_add_err;
 		}
 		error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
 					  &sg_class_member->kobj, "generic");
 		if (error)
-			printk(KERN_ERR "sg_add: unable to make symlink "
-					"'generic' back to sg%d\n", sdp->index);
+			pr_err("%s: unable to make symlink 'generic' back "
+			       "to sg%d\n", __func__, sdp->index);
 	} else
-		printk(KERN_WARNING "sg_add: sg_sys Invalid\n");
+		pr_warn("%s: sg_sys Invalid\n", __func__);
 
-	sdev_printk(KERN_NOTICE, scsidp,
-		    "Attached scsi generic sg%d type %d\n", sdp->index,
-		    scsidp->type);
+	sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d "
+		    "type %d\n", sdp->index, scsidp->type);
 
 	dev_set_drvdata(cl_dev, sdp);
 
@@ -1513,7 +1559,8 @@ out:
 	return error;
 }
 
-static void sg_device_destroy(struct kref *kref)
+static void
+sg_device_destroy(struct kref *kref)
 {
 	struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
 	unsigned long flags;
@@ -1528,40 +1575,45 @@ static void sg_device_destroy(struct kre
 	write_unlock_irqrestore(&sg_index_lock, flags);
 
 	SCSI_LOG_TIMEOUT(3,
-		printk("sg_device_destroy: %s\n",
-			sdp->disk->disk_name));
+		sg_printk(KERN_INFO, sdp, "sg_device_destroy\n"));
 
 	put_disk(sdp->disk);
 	kfree(sdp);
 }
 
-static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+static void
+sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	Sg_device *sdp = dev_get_drvdata(cl_dev);
 	unsigned long iflags;
 	Sg_fd *sfp;
+	int val;
 
-	if (!sdp || sdp->detached)
+	if (!sdp)
 		return;
+	/* want sdp->detaching non-zero as soon as possible */
+	val = atomic_inc_return(&sdp->detaching);
+	if (val > 1)
+		return; /* only want to do following once per device */
 
-	SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "%s\n", __func__));
 
-	/* Need a write lock to set sdp->detached. */
-	write_lock_irqsave(&sg_index_lock, iflags);
-	sdp->detached = 1;
+	read_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
-		wake_up_interruptible(&sfp->read_wait);
+		wake_up_interruptible_all(&sfp->read_wait);
 		kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
 	}
-	write_unlock_irqrestore(&sg_index_lock, iflags);
+	wake_up_interruptible_all(&sdp->open_wait);
+	read_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
 	device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
 	cdev_del(sdp->cdev);
 	sdp->cdev = NULL;
 
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 }
 
 module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
@@ -1631,7 +1683,8 @@ exit_sg(void)
 	idr_destroy(&sg_index_idr);
 }
 
-static int sg_start_req(Sg_request *srp, unsigned char *cmd)
+static int
+sg_start_req(Sg_request *srp, unsigned char *cmd)
 {
 	int res;
 	struct request *rq;
@@ -1645,15 +1698,28 @@ static int sg_start_req(Sg_request *srp,
 	struct request_queue *q = sfp->parentdp->device->request_queue;
 	struct rq_map_data *md, map_data;
 	int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
+	unsigned char *long_cmdp = NULL;
 
-	SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n",
-				   dxfer_len));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+				      "sg_start_req: dxfer_len=%d\n",
+				      dxfer_len));
+
+	if (hp->cmd_len > BLK_MAX_CDB) {
+		long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL);
+		if (!long_cmdp)
+			return -ENOMEM;
+	}
 
 	rq = blk_get_request(q, rw, GFP_ATOMIC);
-	if (!rq)
+	if (!rq) {
+		kfree(long_cmdp);
 		return -ENOMEM;
+	}
 
 	blk_rq_set_block_pc(rq);
+
+	if (hp->cmd_len > BLK_MAX_CDB)
+		rq->cmd = long_cmdp;
 	memcpy(rq->cmd, cmd, hp->cmd_len);
 	rq->cmd_len = hp->cmd_len;
 
@@ -1726,25 +1792,30 @@ static int sg_start_req(Sg_request *srp,
 	return res;
 }
 
-static int sg_finish_rem_req(Sg_request * srp)
+static int
+sg_finish_rem_req(Sg_request *srp)
 {
 	int ret = 0;
 
 	Sg_fd *sfp = srp->parentfp;
 	Sg_scatter_hold *req_schp = &srp->data;
 
-	SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+				      "sg_finish_rem_req: res_used=%d\n",
+				      (int) srp->res_used));
 	if (srp->rq) {
 		if (srp->bio)
 			ret = blk_rq_unmap_user(srp->bio);
 
+		if (srp->rq->cmd != srp->rq->__cmd)
+			kfree(srp->rq->cmd);
 		blk_put_request(srp->rq);
 	}
 
 	if (srp->res_used)
 		sg_unlink_reserve(sfp, srp);
 	else
-		sg_remove_scat(req_schp);
+		sg_remove_scat(sfp, req_schp);
 
 	sg_remove_request(sfp, srp);
 
@@ -1778,8 +1849,9 @@ sg_build_indirect(Sg_scatter_hold * schp
 		++blk_size;	/* don't know why */
 	/* round request up to next highest SG_SECTOR_SZ byte boundary */
 	blk_size = ALIGN(blk_size, SG_SECTOR_SZ);
-	SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n",
-				   buff_size, blk_size));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+		"sg_build_indirect: buff_size=%d, blk_size=%d\n",
+		buff_size, blk_size));
 
 	/* N.B. ret_sz carried into this block ... */
 	mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
@@ -1822,14 +1894,16 @@ retry:
 			}
 		}
 
-		SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, "
-				 "ret_sz=%d\n", k, num, ret_sz));
+		SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp,
+				 "sg_build_indirect: k=%d, num=%d, ret_sz=%d\n",
+				 k, num, ret_sz));
 	}		/* end of for loop */
 
 	schp->page_order = order;
 	schp->k_use_sg = k;
-	SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, "
-			 "rem_sz=%d\n", k, rem_sz));
+	SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp,
+			 "sg_build_indirect: k_use_sg=%d, rem_sz=%d\n",
+			 k, rem_sz));
 
 	schp->bufflen = blk_size;
 	if (rem_sz > 0)	/* must have failed */
@@ -1846,17 +1920,19 @@ out:
 }
 
 static void
-sg_remove_scat(Sg_scatter_hold * schp)
+sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp)
 {
-	SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+			 "sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg));
 	if (schp->pages && schp->sglist_len > 0) {
 		if (!schp->dio_in_use) {
 			int k;
 
 			for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) {
-				SCSI_LOG_TIMEOUT(5, printk(
-				    "sg_remove_scat: k=%d, pg=0x%p\n",
-				    k, schp->pages[k]));
+				SCSI_LOG_TIMEOUT(5,
+					sg_printk(KERN_INFO, sfp->parentdp,
+					"sg_remove_scat: k=%d, pg=0x%p\n",
+					k, schp->pages[k]));
 				__free_pages(schp->pages[k], schp->page_order);
 			}
 
@@ -1872,8 +1948,9 @@ sg_read_oxfer(Sg_request * srp, char __u
 	Sg_scatter_hold *schp = &srp->data;
 	int k, num;
 
-	SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n",
-				   num_read_xfer));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp,
+			 "sg_read_oxfer: num_read_xfer=%d\n",
+			 num_read_xfer));
 	if ((!outp) || (num_read_xfer <= 0))
 		return 0;
 
@@ -1903,14 +1980,15 @@ sg_build_reserve(Sg_fd * sfp, int req_si
 {
 	Sg_scatter_hold *schp = &sfp->reserve;
 
-	SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+			 "sg_build_reserve: req_size=%d\n", req_size));
 	do {
 		if (req_size < PAGE_SIZE)
 			req_size = PAGE_SIZE;
 		if (0 == sg_build_indirect(schp, sfp, req_size))
 			return;
 		else
-			sg_remove_scat(schp);
+			sg_remove_scat(sfp, schp);
 		req_size >>= 1;	/* divide by 2 */
 	} while (req_size > (PAGE_SIZE / 2));
 }
@@ -1923,7 +2001,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request
 	int k, num, rem;
 
 	srp->res_used = 1;
-	SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp,
+			 "sg_link_reserve: size=%d\n", size));
 	rem = size;
 
 	num = 1 << (PAGE_SHIFT + rsv_schp->page_order);
@@ -1941,7 +2020,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request
 	}
 
 	if (k >= rsv_schp->k_use_sg)
-		SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
+		SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp,
+				 "sg_link_reserve: BAD size\n"));
 }
 
 static void
@@ -1949,8 +2029,9 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_reques
 {
 	Sg_scatter_hold *req_schp = &srp->data;
 
-	SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
-				   (int) req_schp->k_use_sg));
+	SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp,
+				      "sg_unlink_reserve: req->k_use_sg=%d\n",
+				      (int) req_schp->k_use_sg));
 	req_schp->k_use_sg = 0;
 	req_schp->bufflen = 0;
 	req_schp->pages = NULL;
@@ -2055,7 +2136,7 @@ sg_remove_request(Sg_fd * sfp, Sg_reques
 }
 
 static Sg_fd *
-sg_add_sfp(Sg_device * sdp, int dev)
+sg_add_sfp(Sg_device * sdp)
 {
 	Sg_fd *sfp;
 	unsigned long iflags;
@@ -2063,7 +2144,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 
 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
@@ -2077,25 +2158,33 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	sfp->cmd_q = SG_DEF_COMMAND_Q;
 	sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
 	sfp->parentdp = sdp;
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
+	if (atomic_read(&sdp->detaching)) {
+		write_unlock_irqrestore(&sdp->sfd_lock, iflags);
+		return ERR_PTR(-ENODEV);
+	}
 	list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
-	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_add_sfp: sfp=0x%p\n", sfp));
 	if (unlikely(sg_big_buff != def_reserved_size))
 		sg_big_buff = def_reserved_size;
 
 	bufflen = min_t(int, sg_big_buff,
-			queue_max_sectors(sdp->device->request_queue) * 512);
+			max_sectors_bytes(sdp->device->request_queue));
 	sg_build_reserve(sfp, bufflen);
-	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
-			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
+				      "sg_add_sfp: bufflen=%d, k_use_sg=%d\n",
+				      sfp->reserve.bufflen,
+				      sfp->reserve.k_use_sg));
 
 	kref_get(&sdp->d_ref);
 	__module_get(THIS_MODULE);
 	return sfp;
 }
 
-static void sg_remove_sfp_usercontext(struct work_struct *work)
+static void
+sg_remove_sfp_usercontext(struct work_struct *work)
 {
 	struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
 	struct sg_device *sdp = sfp->parentdp;
@@ -2105,34 +2194,32 @@ static void sg_remove_sfp_usercontext(st
 		sg_finish_rem_req(sfp->headrp);
 
 	if (sfp->reserve.bufflen > 0) {
-		SCSI_LOG_TIMEOUT(6,
-			printk("sg_remove_sfp:    bufflen=%d, k_use_sg=%d\n",
+		SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp,
+				"sg_remove_sfp:    bufflen=%d, k_use_sg=%d\n",
 				(int) sfp->reserve.bufflen,
 				(int) sfp->reserve.k_use_sg));
-		sg_remove_scat(&sfp->reserve);
+		sg_remove_scat(sfp, &sfp->reserve);
 	}
 
-	SCSI_LOG_TIMEOUT(6,
-		printk("sg_remove_sfp: %s, sfp=0x%p\n",
-			sdp->disk->disk_name,
-			sfp));
+	SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp,
+			"sg_remove_sfp: sfp=0x%p\n", sfp));
 	kfree(sfp);
 
 	scsi_device_put(sdp->device);
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	module_put(THIS_MODULE);
 }
 
-static void sg_remove_sfp(struct kref *kref)
+static void
+sg_remove_sfp(struct kref *kref)
 {
 	struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
 	struct sg_device *sdp = sfp->parentdp;
 	unsigned long iflags;
 
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_del(&sfp->sfd_siblings);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
-	wake_up_interruptible(&sdp->o_excl_wait);
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
 	schedule_work(&sfp->ew.work);
@@ -2183,7 +2270,8 @@ static Sg_device *sg_lookup_dev(int dev)
 	return idr_find(&sg_index_idr, dev);
 }
 
-static Sg_device *sg_get_dev(int dev)
+static Sg_device *
+sg_get_dev(int dev)
 {
 	struct sg_device *sdp;
 	unsigned long flags;
@@ -2192,8 +2280,8 @@ static Sg_device *sg_get_dev(int dev)
 	sdp = sg_lookup_dev(dev);
 	if (!sdp)
 		sdp = ERR_PTR(-ENXIO);
-	else if (sdp->detached) {
-		/* If sdp->detached, then the refcount may already be 0, in
+	else if (atomic_read(&sdp->detaching)) {
+		/* If sdp->detaching, then the refcount may already be 0, in
 		 * which case it would be a bug to do kref_get().
 		 */
 		sdp = ERR_PTR(-ENODEV);
@@ -2204,11 +2292,6 @@ static Sg_device *sg_get_dev(int dev)
 	return sdp;
 }
 
-static void sg_put_dev(struct sg_device *sdp)
-{
-	kref_put(&sdp->d_ref, sg_device_destroy);
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 
 static struct proc_dir_entry *sg_proc_sgp = NULL;
@@ -2425,8 +2508,7 @@ static int sg_proc_single_open_version(s
 
 static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v)
 {
-	seq_printf(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\t"
-		   "online\n");
+	seq_puts(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n");
 	return 0;
 }
 
@@ -2482,16 +2564,19 @@ static int sg_proc_seq_show_dev(struct s
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
-		seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
+	if ((NULL == sdp) || (NULL == sdp->device) ||
+	    (atomic_read(&sdp->detaching)))
+		seq_puts(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	else {
+		scsidp = sdp->device;
+		seq_printf(s, "%d\t%d\t%d\t%llu\t%d\t%d\t%d\t%d\t%d\n",
 			      scsidp->host->host_no, scsidp->channel,
 			      scsidp->id, scsidp->lun, (int) scsidp->type,
 			      1,
 			      (int) scsidp->queue_depth,
-			      (int) scsidp->device_busy,
+			      (int) atomic_read(&scsidp->device_busy),
 			      (int) scsi_device_online(scsidp));
-	else
-		seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	}
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2510,11 +2595,12 @@ static int sg_proc_seq_show_devstrs(stru
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
+	scsidp = sdp ? sdp->device : NULL;
+	if (sdp && scsidp && (!atomic_read(&sdp->detaching)))
 		seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n",
 			   scsidp->vendor, scsidp->model, scsidp->rev);
 	else
-		seq_printf(s, "<no active device>\n");
+		seq_puts(s, "<no active device>\n");
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2559,12 +2645,12 @@ static void sg_proc_debug_helper(struct
 				else
 					cp = "     ";
 			}
-			seq_printf(s, cp);
+			seq_puts(s, cp);
 			blen = srp->data.bufflen;
 			usg = srp->data.k_use_sg;
-			seq_printf(s, srp->done ? 
-				   ((1 == srp->done) ?  "rcv:" : "fin:")
-				   : "act:");
+			seq_puts(s, srp->done ?
+				 ((1 == srp->done) ?  "rcv:" : "fin:")
+				  : "act:");
 			seq_printf(s, " id=%d blen=%d",
 				   srp->header.pack_id, blen);
 			if (srp->done)
@@ -2580,7 +2666,7 @@ static void sg_proc_debug_helper(struct
 				   (int) srp->data.cmd_opcode);
 		}
 		if (0 == m)
-			seq_printf(s, "     No requests active\n");
+			seq_puts(s, "     No requests active\n");
 		read_unlock(&fp->rq_list_lock);
 	}
 }
@@ -2596,31 +2682,34 @@ static int sg_proc_seq_show_debug(struct
 	Sg_device *sdp;
 	unsigned long iflags;
 
-	if (it && (0 == it->index)) {
-		seq_printf(s, "max_active_device=%d(origin 1)\n",
-			   (int)it->max);
-		seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
-	}
+	if (it && (0 == it->index))
+		seq_printf(s, "max_active_device=%d  def_reserved_size=%d\n",
+			   (int)it->max, sg_big_buff);
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && !list_empty(&sdp->sfds)) {
-		struct scsi_device *scsidp = sdp->device;
-
+	if (NULL == sdp)
+		goto skip;
+	read_lock(&sdp->sfd_lock);
+	if (!list_empty(&sdp->sfds)) {
 		seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
-		if (sdp->detached)
-			seq_printf(s, "detached pending close ");
-		else
-			seq_printf
-			    (s, "scsi%d chan=%d id=%d lun=%d   em=%d",
-			     scsidp->host->host_no,
-			     scsidp->channel, scsidp->id,
-			     scsidp->lun,
-			     scsidp->host->hostt->emulated);
-		seq_printf(s, " sg_tablesize=%d excl=%d\n",
-			   sdp->sg_tablesize, get_exclude(sdp));
+		if (atomic_read(&sdp->detaching))
+			seq_puts(s, "detaching pending close ");
+		else if (sdp->device) {
+			struct scsi_device *scsidp = sdp->device;
+
+			seq_printf(s, "%d:%d:%d:%llu   em=%d",
+				   scsidp->host->host_no,
+				   scsidp->channel, scsidp->id,
+				   scsidp->lun,
+				   scsidp->host->hostt->emulated);
+		}
+		seq_printf(s, " sg_tablesize=%d excl=%d open_cnt=%d\n",
+			   sdp->sg_tablesize, sdp->exclude, sdp->open_cnt);
 		sg_proc_debug_helper(s, sdp);
 	}
+	read_unlock(&sdp->sfd_lock);
+skip:
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sr.c linux-libre-3.17-rc7-gnu/drivers/scsi/sr.c
--- linux-libre-3.16-gnu/drivers/scsi/sr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sr.c	2014-09-28 17:29:07.000000000 -0400
@@ -292,8 +292,8 @@ do_tur:
 	if (!cd->tur_changed) {
 		if (cd->get_event_changed) {
 			if (cd->tur_mismatch++ > 8) {
-				sdev_printk(KERN_WARNING, cd->device,
-					    "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n");
+				sr_printk(KERN_WARNING, cd,
+					  "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n");
 				cd->ignore_get_event = true;
 			}
 		} else {
@@ -322,7 +322,7 @@ static int sr_done(struct scsi_cmnd *SCp
 	struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk);
 
 #ifdef DEBUG
-	printk("sr.c done: %x\n", result);
+	scmd_printk(KERN_INFO, SCpnt, "done: %x\n", result);
 #endif
 
 	/*
@@ -385,10 +385,9 @@ static int sr_init_command(struct scsi_c
 	int block = 0, this_count, s_size;
 	struct scsi_cd *cd;
 	struct request *rq = SCpnt->request;
-	struct scsi_device *sdp = SCpnt->device;
 	int ret;
 
-	ret = scsi_setup_fs_cmnd(sdp, rq);
+	ret = scsi_init_io(SCpnt, GFP_ATOMIC);
 	if (ret != BLKPREP_OK)
 		goto out;
 	SCpnt = rq->special;
@@ -398,13 +397,14 @@ static int sr_init_command(struct scsi_c
 	 * is used for a killable error condition */
 	ret = BLKPREP_KILL;
 
-	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n",
-				cd->disk->disk_name, block));
+	SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
+		"Doing sr request, block = %d\n", block));
 
 	if (!cd->device || !scsi_device_online(cd->device)) {
-		SCSI_LOG_HLQUEUE(2, printk("Finishing %u sectors\n",
-					   blk_rq_sectors(rq)));
-		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
+		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+			"Finishing %u sectors\n", blk_rq_sectors(rq)));
+		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+			"Retry with 0x%p\n", SCpnt));
 		goto out;
 	}
 
@@ -425,7 +425,8 @@ static int sr_init_command(struct scsi_c
 		if (!in_interrupt())
 			sr_set_blocklength(cd, 2048);
 		else
-			printk("sr: can't switch blocksize: in interrupt\n");
+			scmd_printk(KERN_INFO, SCpnt,
+				    "can't switch blocksize: in interrupt\n");
 	}
 
 	if (s_size != 512 && s_size != 1024 && s_size != 2048) {
@@ -434,14 +435,12 @@ static int sr_init_command(struct scsi_c
 	}
 
 	if (rq_data_dir(rq) == WRITE) {
-		if (!cd->device->writeable)
+		if (!cd->writeable)
 			goto out;
 		SCpnt->cmnd[0] = WRITE_10;
-		SCpnt->sc_data_direction = DMA_TO_DEVICE;
- 	 	cd->cdi.media_written = 1;
+		cd->cdi.media_written = 1;
 	} else if (rq_data_dir(rq) == READ) {
 		SCpnt->cmnd[0] = READ_10;
-		SCpnt->sc_data_direction = DMA_FROM_DEVICE;
 	} else {
 		blk_dump_rq_flags(rq, "Unknown sr command");
 		goto out;
@@ -475,11 +474,11 @@ static int sr_init_command(struct scsi_c
 	this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9);
 
 
-	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%u 512 byte blocks.\n",
-				cd->cdi.name,
-				(rq_data_dir(rq) == WRITE) ?
+	SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+					"%s %d/%u 512 byte blocks.\n",
+					(rq_data_dir(rq) == WRITE) ?
 					"writing" : "reading",
-				this_count, blk_rq_sectors(rq)));
+					this_count, blk_rq_sectors(rq)));
 
 	SCpnt->cmnd[1] = 0;
 	block = (unsigned int)blk_rq_pos(rq) / (s_size >> 9);
@@ -810,8 +809,8 @@ static void get_sectorsize(struct scsi_c
 		case 512:
 			break;
 		default:
-			printk("%s: unsupported sector size %d.\n",
-			       cd->cdi.name, sector_size);
+			sr_printk(KERN_INFO, cd,
+				  "unsupported sector size %d.", sector_size);
 			cd->capacity = 0;
 		}
 
@@ -853,7 +852,7 @@ static void get_capabilities(struct scsi
 	/* allocate transfer buffer */
 	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		printk(KERN_ERR "sr: out of memory.\n");
+		sr_printk(KERN_ERR, cd, "out of memory.\n");
 		return;
 	}
 
@@ -872,7 +871,7 @@ static void get_capabilities(struct scsi
 				 CDC_SELECT_DISC | CDC_SELECT_SPEED |
 				 CDC_MRW | CDC_MRW_W | CDC_RAM);
 		kfree(buffer);
-		printk("%s: scsi-1 drive\n", cd->cdi.name);
+		sr_printk(KERN_INFO, cd, "scsi-1 drive");
 		return;
 	}
 
@@ -881,22 +880,23 @@ static void get_capabilities(struct scsi
 	cd->readcd_known = 1;
 	cd->readcd_cdda = buffer[n + 5] & 0x01;
 	/* print some capability bits */
-	printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name,
-	       ((buffer[n + 14] << 8) + buffer[n + 15]) / 176,
-	       cd->cdi.speed,
-	       buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */
-	       buffer[n + 3] & 0x20 ? "dvd-ram " : "",
-	       buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */
-	       buffer[n + 4] & 0x20 ? "xa/form2 " : "",	/* can read xa/from2 */
-	       buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */
-	       loadmech[buffer[n + 6] >> 5]);
+	sr_printk(KERN_INFO, cd,
+		  "scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n",
+		  ((buffer[n + 14] << 8) + buffer[n + 15]) / 176,
+		  cd->cdi.speed,
+		  buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */
+		  buffer[n + 3] & 0x20 ? "dvd-ram " : "",
+		  buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */
+		  buffer[n + 4] & 0x20 ? "xa/form2 " : "",	/* can read xa/from2 */
+		  buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */
+		  loadmech[buffer[n + 6] >> 5]);
 	if ((buffer[n + 6] >> 5) == 0)
 		/* caddy drives can't close tray... */
 		cd->cdi.mask |= CDC_CLOSE_TRAY;
 	if ((buffer[n + 2] & 0x8) == 0)
 		/* not a DVD drive */
 		cd->cdi.mask |= CDC_DVD;
-	if ((buffer[n + 3] & 0x20) == 0) 
+	if ((buffer[n + 3] & 0x20) == 0)
 		/* can't write DVD-RAM media */
 		cd->cdi.mask |= CDC_DVD_RAM;
 	if ((buffer[n + 3] & 0x10) == 0)
@@ -927,7 +927,7 @@ static void get_capabilities(struct scsi
 	 */
 	if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) !=
 			(CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) {
-		cd->device->writeable = 1;
+		cd->writeable = 1;
 	}
 
 	kfree(buffer);
@@ -935,7 +935,7 @@ static void get_capabilities(struct scsi
 
 /*
  * sr_packet() is the entry point for the generic commands generated
- * by the Uniform CD-ROM layer. 
+ * by the Uniform CD-ROM layer.
  */
 static int sr_packet(struct cdrom_device_info *cdi,
 		struct packet_command *cgc)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sr.h linux-libre-3.17-rc7-gnu/drivers/scsi/sr.h
--- linux-libre-3.16-gnu/drivers/scsi/sr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sr.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@ typedef struct scsi_cd {
 	struct scsi_device *device;
 	unsigned int vendor;	/* vendor code, see sr_vendor.c         */
 	unsigned long ms_offset;	/* for reading multisession-CD's        */
+	unsigned writeable : 1;
 	unsigned use:1;		/* is this device still supportable     */
 	unsigned xa_flag:1;	/* CD has XA sectors ? */
 	unsigned readcd_known:1;	/* drive supports READ_CD (0xbe) */
@@ -55,6 +56,10 @@ typedef struct scsi_cd {
 	struct gendisk *disk;
 } Scsi_CD;
 
+#define sr_printk(prefix, cd, fmt, a...) \
+	sdev_printk(prefix, (cd)->device, "[%s] " fmt, \
+		    (cd)->cdi.name, ##a)
+
 int sr_do_ioctl(Scsi_CD *, struct packet_command *);
 
 int sr_lock_door(struct cdrom_device_info *, int);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sr_ioctl.c linux-libre-3.17-rc7-gnu/drivers/scsi/sr_ioctl.c
--- linux-libre-3.16-gnu/drivers/scsi/sr_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sr_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,6 @@ module_param(xa_test, int, S_IRUGO | S_I
  * the status of the unchecked_isa_dma flag in the host structure */
 #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
 
-
 static int sr_read_tochdr(struct cdrom_device_info *cdi,
 		struct cdrom_tochdr *tochdr)
 {
@@ -219,7 +218,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 		case UNIT_ATTENTION:
 			SDev->changed = 1;
 			if (!cgc->quiet)
-				printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name);
+				sr_printk(KERN_INFO, cd,
+					  "disc change detected.\n");
 			if (retries++ < 10)
 				goto retry;
 			err = -ENOMEDIUM;
@@ -229,7 +229,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 			    sshdr.ascq == 0x01) {
 				/* sense: Logical unit is in process of becoming ready */
 				if (!cgc->quiet)
-					printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
+					sr_printk(KERN_INFO, cd,
+						  "CDROM not ready yet.\n");
 				if (retries++ < 10) {
 					/* sleep 2 sec and try again */
 					ssleep(2);
@@ -241,7 +242,9 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 				}
 			}
 			if (!cgc->quiet)
-				printk(KERN_INFO "%s: CDROM not ready.  Make sure there is a disc in the drive.\n", cd->cdi.name);
+				sr_printk(KERN_INFO, cd,
+					  "CDROM not ready.  Make sure there "
+					  "is a disc in the drive.\n");
 #ifdef DEBUG
 			scsi_print_sense_hdr("sr", &sshdr);
 #endif
@@ -259,7 +262,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct pack
 #endif
 			break;
 		default:
-			printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
+			sr_printk(KERN_ERR, cd,
+				  "CDROM (ioctl) error, command: ");
 			__scsi_print_command(cgc->cmd);
 			scsi_print_sense_hdr("sr", &sshdr);
 			err = -EIO;
@@ -491,8 +495,8 @@ static int sr_read_cd(Scsi_CD *cd, unsig
 	struct packet_command cgc;
 
 #ifdef DEBUG
-	printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n",
-	       cd->cdi.name, lba, format, blksize);
+	sr_printk(KERN_INFO, cd, "sr_read_cd lba=%d format=%d blksize=%d\n",
+		  lba, format, blksize);
 #endif
 
 	memset(&cgc, 0, sizeof(struct packet_command));
@@ -539,7 +543,8 @@ static int sr_read_sector(Scsi_CD *cd, i
 		if (-EDRIVE_CANT_DO_THIS != rc)
 			return rc;
 		cd->readcd_known = 0;
-		printk("CDROM does'nt support READ CD (0xbe) command\n");
+		sr_printk(KERN_INFO, cd,
+			  "CDROM does'nt support READ CD (0xbe) command\n");
 		/* fall & retry the other way */
 	}
 	/* ... if this fails, we switch the blocksize using MODE SELECT */
@@ -548,7 +553,8 @@ static int sr_read_sector(Scsi_CD *cd, i
 			return rc;
 	}
 #ifdef DEBUG
-	printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize);
+	sr_printk(KERN_INFO, cd, "sr_read_sector lba=%d blksize=%d\n",
+		  lba, blksize);
 #endif
 
 	memset(&cgc, 0, sizeof(struct packet_command));
@@ -592,7 +598,7 @@ int sr_is_xa(Scsi_CD *cd)
 	}
 	kfree(raw_sector);
 #ifdef DEBUG
-	printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa);
+	sr_printk(KERN_INFO, cd, "sr_is_xa: %d\n", is_xa);
 #endif
 	return is_xa;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sr_vendor.c linux-libre-3.17-rc7-gnu/drivers/scsi/sr_vendor.c
--- linux-libre-3.16-gnu/drivers/scsi/sr_vendor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sr_vendor.c	2014-09-28 17:29:07.000000000 -0400
@@ -123,7 +123,7 @@ int sr_set_blocklength(Scsi_CD *cd, int
 		return -ENOMEM;
 
 #ifdef DEBUG
-	printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength);
+	sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength);
 #endif
 	memset(&cgc, 0, sizeof(struct packet_command));
 	cgc.cmd[0] = MODE_SELECT;
@@ -144,8 +144,9 @@ int sr_set_blocklength(Scsi_CD *cd, int
 	}
 #ifdef DEBUG
 	else
-		printk("%s: switching blocklength to %d bytes failed\n",
-		       cd->cdi.name, blocklength);
+		sr_printk(KERN_INFO, cd,
+			  "switching blocklength to %d bytes failed\n",
+			  blocklength);
 #endif
 	kfree(buffer);
 	return rc;
@@ -190,8 +191,8 @@ int sr_cd_check(struct cdrom_device_info
 		if (rc != 0)
 			break;
 		if ((buffer[0] << 8) + buffer[1] < 0x0a) {
-			printk(KERN_INFO "%s: Hmm, seems the drive "
-			   "doesn't support multisession CD's\n", cd->cdi.name);
+			sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
+			   "doesn't support multisession CD's\n");
 			no_multi = 1;
 			break;
 		}
@@ -218,9 +219,9 @@ int sr_cd_check(struct cdrom_device_info
 			if (rc != 0)
 				break;
 			if (buffer[14] != 0 && buffer[14] != 0xb0) {
-				printk(KERN_INFO "%s: Hmm, seems the cdrom "
-				       "doesn't support multisession CD's\n",
-				       cd->cdi.name);
+				sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom "
+					  "doesn't support multisession CD's\n");
+
 				no_multi = 1;
 				break;
 			}
@@ -245,9 +246,8 @@ int sr_cd_check(struct cdrom_device_info
 			cgc.timeout = VENDOR_TIMEOUT;
 			rc = sr_do_ioctl(cd, &cgc);
 			if (rc == -EINVAL) {
-				printk(KERN_INFO "%s: Hmm, seems the drive "
-				       "doesn't support multisession CD's\n",
-				       cd->cdi.name);
+				sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
+					  "doesn't support multisession CD's\n");
 				no_multi = 1;
 				break;
 			}
@@ -277,8 +277,8 @@ int sr_cd_check(struct cdrom_device_info
 			break;
 		}
 		if ((rc = buffer[2]) == 0) {
-			printk(KERN_WARNING
-			       "%s: No finished session\n", cd->cdi.name);
+			sr_printk(KERN_WARNING, cd,
+				  "No finished session\n");
 			break;
 		}
 		cgc.cmd[0] = READ_TOC;	/* Read TOC */
@@ -301,9 +301,9 @@ int sr_cd_check(struct cdrom_device_info
 
 	default:
 		/* should not happen */
-		printk(KERN_WARNING
-		   "%s: unknown vendor code (%i), not initialized ?\n",
-		       cd->cdi.name, cd->vendor);
+		sr_printk(KERN_WARNING, cd,
+			  "unknown vendor code (%i), not initialized ?\n",
+			  cd->vendor);
 		sector = 0;
 		no_multi = 1;
 		break;
@@ -321,8 +321,8 @@ int sr_cd_check(struct cdrom_device_info
 
 #ifdef DEBUG
 	if (sector)
-		printk(KERN_DEBUG "%s: multisession offset=%lu\n",
-		       cd->cdi.name, sector);
+		sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n",
+			  sector);
 #endif
 	kfree(buffer);
 	return rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/st.c linux-libre-3.17-rc7-gnu/drivers/scsi/st.c
--- linux-libre-3.16-gnu/drivers/scsi/st.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/st.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,11 +58,11 @@ static const char *verstr = "20101219";
    is defined and non-zero. */
 #define DEBUG 0
 
+#define ST_DEB_MSG  KERN_NOTICE
 #if DEBUG
 /* The message level for the debug messages is currently set to KERN_NOTICE
    so that people can easily see the messages. Later when the debugging messages
    in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
-#define ST_DEB_MSG  KERN_NOTICE
 #define DEB(a) a
 #define DEBC(a) if (debugging) { a ; }
 #else
@@ -305,6 +305,15 @@ static inline char *tape_name(struct scs
 	return tape->disk->disk_name;
 }
 
+#define st_printk(prefix, t, fmt, a...) \
+	sdev_printk(prefix, (t)->device, "%s: " fmt, \
+		    tape_name(t), ##a)
+#ifdef DEBUG
+#define DEBC_printk(t, fmt, a...) \
+	if (debugging) { st_printk(ST_DEB_MSG, t, fmt, ##a ); }
+#else
+#define DEBC_printk(t, fmt, a...)
+#endif
 
 static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
 {
@@ -358,21 +367,20 @@ static int st_chk_result(struct scsi_tap
 	else
 		scode = 0;
 
-        DEB(
-        if (debugging) {
-                printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
-		       name, result,
-		       SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
-		       SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
+	DEB(
+	if (debugging) {
+		st_printk(ST_DEB_MSG, STp,
+			    "Error: %x, cmd: %x %x %x %x %x %x\n", result,
+			    SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
+			    SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 		if (cmdstatp->have_sense)
 			 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 	} ) /* end DEB */
 	if (!debugging) { /* Abnormal conditions for tape */
 		if (!cmdstatp->have_sense)
-			printk(KERN_WARNING
-			       "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n",
-			       name, result, driver_byte(result),
-			       host_byte(result));
+			st_printk(KERN_WARNING, STp,
+			       "Error %x (driver bt 0x%x, host bt 0x%x).\n",
+			       result, driver_byte(result), host_byte(result));
 		else if (cmdstatp->have_sense &&
 			 scode != NO_SENSE &&
 			 scode != RECOVERED_ERROR &&
@@ -411,7 +419,7 @@ static int st_chk_result(struct scsi_tap
 		STp->recover_count++;
 		STp->recover_reg++;
 
-                DEB(
+		DEB(
 		if (debugging) {
 			if (SRpnt->cmd[0] == READ_6)
 				stp = "read";
@@ -419,8 +427,9 @@ static int st_chk_result(struct scsi_tap
 				stp = "write";
 			else
 				stp = "ioctl";
-			printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp,
-			       STp->recover_count);
+			st_printk(ST_DEB_MSG, STp,
+				  "Recovered %s error (%d).\n",
+				  stp, STp->recover_count);
 		} ) /* end DEB */
 
 		if (cmdstatp->flags == 0)
@@ -437,8 +446,8 @@ static struct st_request *st_allocate_re
 	if (streq)
 		streq->stp = stp;
 	else {
-		DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n",
-			    tape_name(stp)););
+		st_printk(KERN_ERR, stp,
+			  "Can't get SCSI request.\n");
 		if (signal_pending(current))
 			stp->buffer->syscall_result = -EINTR;
 		else
@@ -525,8 +534,8 @@ st_do_scsi(struct st_request * SRpnt, st
 
 	/* if async, make sure there's no command outstanding */
 	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
-		printk(KERN_ERR "%s: Async command already active.\n",
-		       tape_name(STp));
+		st_printk(KERN_ERR, STp,
+			  "Async command already active.\n");
 		if (signal_pending(current))
 			(STp->buffer)->syscall_result = (-EINTR);
 		else
@@ -597,12 +606,12 @@ static int write_behind_check(struct scs
 	if (!STbuffer->writing)
 		return 0;
 
-        DEB(
+	DEB(
 	if (STp->write_pending)
 		STp->nbr_waits++;
 	else
 		STp->nbr_finished++;
-        ) /* end DEB */
+	) /* end DEB */
 
 	wait_for_completion(&(STp->wait));
 	SRpnt = STbuffer->last_SRpnt;
@@ -639,8 +648,9 @@ static int write_behind_check(struct scs
 	STbuffer->writing = 0;
 
 	DEB(if (debugging && retval)
-	    printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
-		   tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
+		    st_printk(ST_DEB_MSG, STp,
+				"Async write error %x, return value %d.\n",
+				STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
 
 	return retval;
 }
@@ -662,8 +672,8 @@ static int cross_eof(struct scsi_tape *
 		cmd[2] = cmd[3] = cmd[4] = 0xff;	/* -1 filemarks */
 	cmd[5] = 0;
 
-        DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
-		   tape_name(STp), forward ? "forward" : "backward"));
+	DEBC_printk(STp, "Stepping over filemark %s.\n",
+		    forward ? "forward" : "backward");
 
 	SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
 			   STp->device->request_queue->rq_timeout,
@@ -675,8 +685,9 @@ static int cross_eof(struct scsi_tape *
 	SRpnt = NULL;
 
 	if ((STp->buffer)->cmdstat.midlevel_result != 0)
-		printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
-		   tape_name(STp), forward ? "forward" : "backward");
+		st_printk(KERN_ERR, STp,
+			  "Stepping over filemark %s failed.\n",
+			  forward ? "forward" : "backward");
 
 	return (STp->buffer)->syscall_result;
 }
@@ -699,8 +710,7 @@ static int st_flush_write_buffer(struct
 	if (STp->dirty == 1) {
 
 		transfer = STp->buffer->buffer_bytes;
-                DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
-                               tape_name(STp), transfer));
+		DEBC_printk(STp, "Flushing %d bytes.\n", transfer);
 
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = WRITE_6;
@@ -732,8 +742,7 @@ static int st_flush_write_buffer(struct
 					STps->drv_block += blks;
 				result = (-ENOSPC);
 			} else {
-				printk(KERN_ERR "%s: Error on flush.\n",
-                                       tape_name(STp));
+				st_printk(KERN_ERR, STp, "Error on flush.\n");
 				STps->drv_block = (-1);
 				result = (-EIO);
 			}
@@ -811,7 +820,6 @@ static int set_mode_densblk(struct scsi_
 {
 	int set_it = 0;
 	unsigned long arg;
-	char *name = tape_name(STp);
 
 	if (!STp->density_changed &&
 	    STm->default_density >= 0 &&
@@ -830,9 +838,10 @@ static int set_mode_densblk(struct scsi_
 		arg |= STp->block_size;
 	if (set_it &&
 	    st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
-		printk(KERN_WARNING
-		       "%s: Can't set default block size to %d bytes and density %x.\n",
-		       name, STm->default_blksize, STm->default_density);
+		st_printk(KERN_WARNING, STp,
+			  "Can't set default block size to %d bytes "
+			  "and density %x.\n",
+			  STm->default_blksize, STm->default_density);
 		if (modes_defined)
 			return (-EINVAL);
 	}
@@ -844,12 +853,9 @@ static int set_mode_densblk(struct scsi_
 static int do_door_lock(struct scsi_tape * STp, int do_lock)
 {
 	int retval, cmd;
-	DEB(char *name = tape_name(STp);)
-
 
 	cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
-	DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name,
-		    do_lock ? "L" : "Unl"));
+	DEBC_printk(STp, "%socking drive door.\n", do_lock ? "L" : "Unl");
 	retval = scsi_ioctl(STp->device, cmd, NULL);
 	if (!retval) {
 		STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
@@ -976,15 +982,14 @@ static int check_tape(struct scsi_tape *
 	struct st_request *SRpnt = NULL;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
-	char *name = tape_name(STp);
 	struct inode *inode = file_inode(filp);
 	int mode = TAPE_MODE(inode);
 
 	STp->ready = ST_READY;
 
 	if (mode != STp->current_mode) {
-                DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n",
-			       name, STp->current_mode, mode));
+		DEBC_printk(STp, "Mode change from %d to %d.\n",
+			    STp->current_mode, mode);
 		new_session = 1;
 		STp->current_mode = mode;
 	}
@@ -1055,13 +1060,12 @@ static int check_tape(struct scsi_tape *
 			STp->min_block = ((STp->buffer)->b_data[4] << 8) |
 			    (STp->buffer)->b_data[5];
 			if ( DEB( debugging || ) !STp->inited)
-				printk(KERN_INFO
-                                       "%s: Block limits %d - %d bytes.\n", name,
-                                       STp->min_block, STp->max_block);
+				st_printk(KERN_INFO, STp,
+					  "Block limits %d - %d bytes.\n",
+					  STp->min_block, STp->max_block);
 		} else {
 			STp->min_block = STp->max_block = (-1);
-                        DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
-                                       name));
+			DEBC_printk(STp, "Can't read block limits.\n");
 		}
 	}
 
@@ -1078,56 +1082,58 @@ static int check_tape(struct scsi_tape *
 	}
 
 	if ((STp->buffer)->syscall_result != 0) {
-                DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));
+		DEBC_printk(STp, "No Mode Sense.\n");
 		STp->block_size = ST_DEFAULT_BLOCK;	/* Educated guess (?) */
 		(STp->buffer)->syscall_result = 0;	/* Prevent error propagation */
 		STp->drv_write_prot = 0;
 	} else {
-                DEBC(printk(ST_DEB_MSG
-                            "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
-                            name,
-                            (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
-                            (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));
+		DEBC_printk(STp,"Mode sense. Length %d, "
+			    "medium %x, WBS %x, BLL %d\n",
+			    (STp->buffer)->b_data[0],
+			    (STp->buffer)->b_data[1],
+			    (STp->buffer)->b_data[2],
+			    (STp->buffer)->b_data[3]);
 
 		if ((STp->buffer)->b_data[3] >= 8) {
 			STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
 			STp->density = (STp->buffer)->b_data[4];
 			STp->block_size = (STp->buffer)->b_data[9] * 65536 +
 			    (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
-                        DEBC(printk(ST_DEB_MSG
-                                    "%s: Density %x, tape length: %x, drv buffer: %d\n",
-                                    name, STp->density, (STp->buffer)->b_data[5] * 65536 +
-                                    (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
-                                    STp->drv_buffer));
+			DEBC_printk(STp, "Density %x, tape length: %x, "
+				    "drv buffer: %d\n",
+				    STp->density,
+				    (STp->buffer)->b_data[5] * 65536 +
+				    (STp->buffer)->b_data[6] * 256 +
+				    (STp->buffer)->b_data[7],
+				    STp->drv_buffer);
 		}
 		STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
 		if (!STp->drv_buffer && STp->immediate_filemark) {
-			printk(KERN_WARNING
-			    "%s: non-buffered tape: disabling writing immediate filemarks\n",
-			    name);
+			st_printk(KERN_WARNING, STp,
+				  "non-buffered tape: disabling "
+				  "writing immediate filemarks\n");
 			STp->immediate_filemark = 0;
 		}
 	}
 	st_release_request(SRpnt);
 	SRpnt = NULL;
-        STp->inited = 1;
+	STp->inited = 1;
 
 	if (STp->block_size > 0)
 		(STp->buffer)->buffer_blocks =
-                        (STp->buffer)->buffer_size / STp->block_size;
+			(STp->buffer)->buffer_size / STp->block_size;
 	else
 		(STp->buffer)->buffer_blocks = 1;
 	(STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
 
-        DEBC(printk(ST_DEB_MSG
-                       "%s: Block size: %d, buffer size: %d (%d blocks).\n", name,
-		       STp->block_size, (STp->buffer)->buffer_size,
-		       (STp->buffer)->buffer_blocks));
+	DEBC_printk(STp, "Block size: %d, buffer size: %d (%d blocks).\n",
+		    STp->block_size, (STp->buffer)->buffer_size,
+		    (STp->buffer)->buffer_blocks);
 
 	if (STp->drv_write_prot) {
 		STp->write_prot = 1;
 
-                DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name));
+		DEBC_printk(STp, "Write protected\n");
 
 		if (do_wait &&
 		    ((st_flags & O_ACCMODE) == O_WRONLY ||
@@ -1141,8 +1147,7 @@ static int check_tape(struct scsi_tape *
 		/* This code is reached when the device is opened for the first time
 		   after the driver has been initialized with tape in the drive and the
 		   partition support has been enabled. */
-                DEBC(printk(ST_DEB_MSG
-                            "%s: Updating partition number in status.\n", name));
+		DEBC_printk(STp, "Updating partition number in status.\n");
 		if ((STp->partition = find_partition(STp)) < 0) {
 			retval = STp->partition;
 			goto err_out;
@@ -1160,9 +1165,10 @@ static int check_tape(struct scsi_tape *
 
 		if (STp->default_drvbuffer != 0xff) {
 			if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
-				printk(KERN_WARNING
-                                       "%s: Can't set default drive buffering to %d.\n",
-				       name, STp->default_drvbuffer);
+				st_printk(KERN_WARNING, STp,
+					  "Can't set default drive "
+					  "buffering to %d.\n",
+					  STp->default_drvbuffer);
 		}
 	}
 
@@ -1182,7 +1188,6 @@ static int st_open(struct inode *inode,
 	struct scsi_tape *STp;
 	struct st_partstat *STps;
 	int dev = TAPE_NR(inode);
-	char *name;
 
 	/*
 	 * We really want to do nonseekable_open(inode, filp); here, but some
@@ -1196,13 +1201,12 @@ static int st_open(struct inode *inode,
 	}
 
 	filp->private_data = STp;
-	name = tape_name(STp);
 
 	spin_lock(&st_use_lock);
 	if (STp->in_use) {
 		spin_unlock(&st_use_lock);
 		scsi_tape_put(STp);
-		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
+		DEBC_printk(STp, "Device already in use.\n");
 		return (-EBUSY);
 	}
 
@@ -1222,8 +1226,8 @@ static int st_open(struct inode *inode,
 
 	/* See that we have at least a one page buffer available */
 	if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) {
-		printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n",
-		       name);
+		st_printk(KERN_WARNING, STp,
+			  "Can't allocate one page tape buffer.\n");
 		retval = (-EOVERFLOW);
 		goto err_out;
 	}
@@ -1279,7 +1283,6 @@ static int st_flush(struct file *filp, f
 	struct scsi_tape *STp = filp->private_data;
 	struct st_modedef *STm = &(STp->modes[STp->current_mode]);
 	struct st_partstat *STps = &(STp->ps[STp->partition]);
-	char *name = tape_name(STp);
 
 	if (file_count(filp) > 1)
 		return 0;
@@ -1292,24 +1295,25 @@ static int st_flush(struct file *filp, f
 
 	if (STp->can_partitions &&
 	    (result2 = switch_partition(STp)) < 0) {
-                DEBC(printk(ST_DEB_MSG
-                               "%s: switch_partition at close failed.\n", name));
+		DEBC_printk(STp, "switch_partition at close failed.\n");
 		if (result == 0)
 			result = result2;
 		goto out;
 	}
 
 	DEBC( if (STp->nbr_requests)
-		printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n",
-		       name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages));
+		st_printk(KERN_DEBUG, STp,
+			  "Number of r/w requests %d, dio used in %d, "
+			  "pages %d.\n", STp->nbr_requests, STp->nbr_dio,
+			  STp->nbr_pages));
 
 	if (STps->rw == ST_WRITING && !STp->pos_unknown) {
 		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
-                DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
-                            name, STp->nbr_waits, STp->nbr_finished);
-		)
-
+#if DEBUG
+		DEBC_printk(STp, "Async write waits %d, finished %d.\n",
+			    STp->nbr_waits, STp->nbr_finished);
+#endif
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = WRITE_FILEMARKS;
 		if (STp->immediate_filemark)
@@ -1343,13 +1347,13 @@ static int st_flush(struct file *filp, f
 		else { /* Write error */
 			st_release_request(SRpnt);
 			SRpnt = NULL;
-			printk(KERN_ERR "%s: Error on write filemark.\n", name);
+			st_printk(KERN_ERR, STp,
+				  "Error on write filemark.\n");
 			if (result == 0)
 				result = (-EIO);
 		}
 
-                DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
-                            name, cmd[4]));
+		DEBC_printk(STp, "Buffer flushed, %d EOF(s) written\n", cmd[4]);
 	} else if (!STp->rew_at_close) {
 		STps = &(STp->ps[STp->partition]);
 		if (!STm->sysv || STps->rw != ST_READING) {
@@ -1447,9 +1451,10 @@ static ssize_t rw_checks(struct scsi_tap
 	if (count == 0)
 		goto out;
 
-        DEB(
+	DEB(
 	if (!STp->in_use) {
-		printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp));
+		st_printk(ST_DEB_MSG, STp,
+			  "Incorrect device.\n");
 		retval = (-EIO);
 		goto out;
 	} ) /* end DEB */
@@ -1519,8 +1524,9 @@ static int setup_buffering(struct scsi_t
 
 		if (bufsize > STbp->buffer_size &&
 		    !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
-			printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
-			       tape_name(STp), bufsize);
+			st_printk(KERN_WARNING, STp,
+				  "Can't allocate %d byte tape buffer.\n",
+				  bufsize);
 			retval = (-EOVERFLOW);
 			goto out;
 		}
@@ -1563,7 +1569,6 @@ st_write(struct file *filp, const char _
 	struct st_modedef *STm;
 	struct st_partstat *STps;
 	struct st_buffer *STbp;
-	char *name = tape_name(STp);
 
 	if (mutex_lock_interruptible(&STp->lock))
 		return -ERESTARTSYS;
@@ -1574,8 +1579,8 @@ st_write(struct file *filp, const char _
 
 	/* Write must be integral number of blocks */
 	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
-		printk(KERN_WARNING "%s: Write not multiple of tape block size.\n",
-		       name);
+		st_printk(KERN_WARNING, STp,
+			  "Write not multiple of tape block size.\n");
 		retval = (-EINVAL);
 		goto out;
 	}
@@ -1601,8 +1606,8 @@ st_write(struct file *filp, const char _
 		if (STm->default_compression != ST_DONT_TOUCH &&
 		    !(STp->compression_changed)) {
 			if (st_compression(STp, (STm->default_compression == ST_YES))) {
-				printk(KERN_WARNING "%s: Can't set default compression.\n",
-				       name);
+				st_printk(KERN_WARNING, STp,
+					  "Can't set default compression.\n");
 				if (modes_defined) {
 					retval = (-EINVAL);
 					goto out;
@@ -1723,7 +1728,7 @@ st_write(struct file *filp, const char _
 		if (STbp->syscall_result != 0) {
 			struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
-                        DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
+			DEBC_printk(STp, "Error on write:\n");
 			if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
 				scode = cmdstatp->sense_hdr.sense_key;
 				if (cmdstatp->remainder_valid)
@@ -1750,9 +1755,9 @@ st_write(struct file *filp, const char _
 					if (STp->block_size == 0 ||
 					    undone > 0 || count == 0)
 						retval = (-ENOSPC); /* EOM within current request */
-                                        DEBC(printk(ST_DEB_MSG
-                                                       "%s: EOM with %d bytes unwritten.\n",
-						       name, (int)count));
+					DEBC_printk(STp, "EOM with %d "
+						    "bytes unwritten.\n",
+						    (int)count);
 				} else {
 					/* EOT within data buffered earlier (possible only
 					   in fixed block mode without direct i/o) */
@@ -1765,9 +1770,10 @@ st_write(struct file *filp, const char _
 								STp->block_size;
 						}
 						STps->eof = ST_EOM_OK;
-						DEBC(printk(ST_DEB_MSG
-							    "%s: Retry write of %d bytes at EOM.\n",
-							    name, STp->buffer->buffer_bytes));
+						DEBC_printk(STp, "Retry "
+							    "write of %d "
+							    "bytes at EOM.\n",
+							    STp->buffer->buffer_bytes);
 						goto retry_write;
 					}
 					else {
@@ -1778,9 +1784,8 @@ st_write(struct file *filp, const char _
 						STps->eof = ST_EOM_ERROR;
 						STps->drv_block = (-1); /* Too cautious? */
 						retval = (-EIO);	/* EOM for old data */
-						DEBC(printk(ST_DEB_MSG
-							    "%s: EOM with lost data.\n",
-							    name));
+						DEBC_printk(STp, "EOM with "
+							    "lost data.\n");
 					}
 				}
 			} else {
@@ -1839,7 +1844,6 @@ static long read_tape(struct scsi_tape *
 	struct st_partstat *STps;
 	struct st_buffer *STbp;
 	int retval = 0;
-	char *name = tape_name(STp);
 
 	if (count == 0)
 		return 0;
@@ -1891,12 +1895,12 @@ static long read_tape(struct scsi_tape *
 		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
 		retval = 1;
-		DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
-                            name,
-                            SRpnt->sense[0], SRpnt->sense[1],
-                            SRpnt->sense[2], SRpnt->sense[3],
-                            SRpnt->sense[4], SRpnt->sense[5],
-                            SRpnt->sense[6], SRpnt->sense[7]));
+		DEBC_printk(STp,
+			    "Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+			    SRpnt->sense[0], SRpnt->sense[1],
+			    SRpnt->sense[2], SRpnt->sense[3],
+			    SRpnt->sense[4], SRpnt->sense[5],
+			    SRpnt->sense[6], SRpnt->sense[7]);
 		if (cmdstatp->have_sense) {
 
 			if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
@@ -1913,23 +1917,27 @@ static long read_tape(struct scsi_tape *
 					transfer = bytes;
 
 				if (cmdstatp->flags & SENSE_ILI) {	/* ILI */
-					if (STp->block_size == 0) {
-						if (transfer <= 0) {
-							if (transfer < 0)
-								printk(KERN_NOTICE
-								       "%s: Failed to read %d byte block with %d byte transfer.\n",
-								       name, bytes - transfer, bytes);
-							if (STps->drv_block >= 0)
-								STps->drv_block += 1;
-							STbp->buffer_bytes = 0;
-							return (-ENOMEM);
-						}
+					if (STp->block_size == 0 &&
+					    transfer < 0) {
+						st_printk(KERN_NOTICE, STp,
+							  "Failed to read %d "
+							  "byte block with %d "
+							  "byte transfer.\n",
+							  bytes - transfer,
+							  bytes);
+						if (STps->drv_block >= 0)
+							STps->drv_block += 1;
+						STbp->buffer_bytes = 0;
+						return (-ENOMEM);
+					} else if (STp->block_size == 0) {
 						STbp->buffer_bytes = bytes - transfer;
 					} else {
 						st_release_request(SRpnt);
 						SRpnt = *aSRpnt = NULL;
 						if (transfer == blks) {	/* We did not get anything, error */
-							printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
+							st_printk(KERN_NOTICE, STp,
+								  "Incorrect "
+								  "block size.\n");
 							if (STps->drv_block >= 0)
 								STps->drv_block += blks - transfer + 1;
 							st_int_ioctl(STp, MTBSR, 1);
@@ -1938,9 +1946,11 @@ static long read_tape(struct scsi_tape *
 						/* We have some data, deliver it */
 						STbp->buffer_bytes = (blks - transfer) *
 						    STp->block_size;
-                                                DEBC(printk(ST_DEB_MSG
-                                                            "%s: ILI but enough data received %ld %d.\n",
-                                                            name, count, STbp->buffer_bytes));
+						DEBC_printk(STp, "ILI but "
+							    "enough data "
+							    "received %ld "
+							    "%d.\n", count,
+							    STbp->buffer_bytes);
 						if (STps->drv_block >= 0)
 							STps->drv_block += 1;
 						if (st_int_ioctl(STp, MTBSR, 1))
@@ -1956,9 +1966,9 @@ static long read_tape(struct scsi_tape *
 					else
 						STbp->buffer_bytes =
 						    bytes - transfer * STp->block_size;
-                                        DEBC(printk(ST_DEB_MSG
-                                                    "%s: EOF detected (%d bytes read).\n",
-                                                    name, STbp->buffer_bytes));
+					DEBC_printk(STp, "EOF detected (%d "
+						    "bytes read).\n",
+						    STbp->buffer_bytes);
 				} else if (cmdstatp->flags & SENSE_EOM) {
 					if (STps->eof == ST_FM)
 						STps->eof = ST_EOD_1;
@@ -1970,20 +1980,20 @@ static long read_tape(struct scsi_tape *
 						STbp->buffer_bytes =
 						    bytes - transfer * STp->block_size;
 
-                                        DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n",
-                                                    name, STbp->buffer_bytes));
+					DEBC_printk(STp, "EOM detected (%d "
+						    "bytes read).\n",
+						    STbp->buffer_bytes);
 				}
 			}
-			/* end of EOF, EOM, ILI test */ 
+			/* end of EOF, EOM, ILI test */
 			else {	/* nonzero sense key */
-                                DEBC(printk(ST_DEB_MSG
-                                            "%s: Tape error while reading.\n", name));
+				DEBC_printk(STp, "Tape error while reading.\n");
 				STps->drv_block = (-1);
 				if (STps->eof == ST_FM &&
 				    cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
-                                        DEBC(printk(ST_DEB_MSG
-                                                    "%s: Zero returned for first BLANK CHECK after EOF.\n",
-                                                    name));
+					DEBC_printk(STp, "Zero returned for "
+						    "first BLANK CHECK "
+						    "after EOF.\n");
 					STps->eof = ST_EOD_2;	/* First BLANK_CHECK after FM */
 				} else	/* Some other extended sense code */
 					retval = (-EIO);
@@ -1992,13 +2002,13 @@ static long read_tape(struct scsi_tape *
 			if (STbp->buffer_bytes < 0)  /* Caused by bogus sense data */
 				STbp->buffer_bytes = 0;
 		}
-		/* End of extended sense test */ 
+		/* End of extended sense test */
 		else {		/* Non-extended sense */
 			retval = STbp->syscall_result;
 		}
 
 	}
-	/* End of error handling */ 
+	/* End of error handling */
 	else {			/* Read successful */
 		STbp->buffer_bytes = bytes;
 		if (STp->sili) /* In fixed block mode residual is always zero here */
@@ -2028,7 +2038,6 @@ st_read(struct file *filp, char __user *
 	struct st_modedef *STm;
 	struct st_partstat *STps;
 	struct st_buffer *STbp = STp->buffer;
-	DEB( char *name = tape_name(STp); )
 
 	if (mutex_lock_interruptible(&STp->lock))
 		return -ERESTARTSYS;
@@ -2053,11 +2062,12 @@ st_read(struct file *filp, char __user *
 			goto out;
 		STps->rw = ST_READING;
 	}
-        DEB(
+	DEB(
 	if (debugging && STps->eof != ST_NOEOF)
-		printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name,
-		       STps->eof, STbp->buffer_bytes);
-        ) /* end DEB */
+		st_printk(ST_DEB_MSG, STp,
+			  "EOF/EOM flag up (%d). Bytes %d\n",
+			  STps->eof, STbp->buffer_bytes);
+	) /* end DEB */
 
 	retval = setup_buffering(STp, buf, count, 1);
 	if (retval)
@@ -2104,13 +2114,13 @@ st_read(struct file *filp, char __user *
 
 		/* Move the data from driver buffer to user buffer */
 		if (STbp->buffer_bytes > 0) {
-                        DEB(
+			DEB(
 			if (debugging && STps->eof != ST_NOEOF)
-				printk(ST_DEB_MSG
-                                       "%s: EOF up (%d). Left %d, needed %d.\n", name,
-				       STps->eof, STbp->buffer_bytes,
-                                       (int)(count - total));
-                        ) /* end DEB */
+				st_printk(ST_DEB_MSG, STp,
+					  "EOF up (%d). Left %d, needed %d.\n",
+					  STps->eof, STbp->buffer_bytes,
+					  (int)(count - total));
+			) /* end DEB */
 			transfer = STbp->buffer_bytes < count - total ?
 			    STbp->buffer_bytes : count - total;
 			if (!do_dio) {
@@ -2166,26 +2176,30 @@ st_read(struct file *filp, char __user *
 
 DEB(
 /* Set the driver options */
-static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name)
+static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm)
 {
 	if (debugging) {
-		printk(KERN_INFO
-		       "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
-		       name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
-		       STm->do_read_ahead);
-		printk(KERN_INFO
-		       "%s:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
-		       name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
-		printk(KERN_INFO
-		       "%s:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
-		       name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
-		       STp->scsi2_logical);
-		printk(KERN_INFO
-		       "%s:    sysv: %d nowait: %d sili: %d nowait_filemark: %d\n",
-		       name, STm->sysv, STp->immediate, STp->sili,
-		       STp->immediate_filemark);
-		printk(KERN_INFO "%s:    debugging: %d\n",
-		       name, debugging);
+		st_printk(KERN_INFO, STp,
+			  "Mode %d options: buffer writes: %d, "
+			  "async writes: %d, read ahead: %d\n",
+			  STp->current_mode, STm->do_buffer_writes,
+			  STm->do_async_writes, STm->do_read_ahead);
+		st_printk(KERN_INFO, STp,
+			  "    can bsr: %d, two FMs: %d, "
+			  "fast mteom: %d, auto lock: %d,\n",
+			  STp->can_bsr, STp->two_fm, STp->fast_mteom,
+			  STp->do_auto_lock);
+		st_printk(KERN_INFO, STp,
+			  "    defs for wr: %d, no block limits: %d, "
+			  "partitions: %d, s2 log: %d\n",
+			  STm->defaults_for_writes, STp->omit_blklims,
+			  STp->can_partitions, STp->scsi2_logical);
+		st_printk(KERN_INFO, STp,
+			  "    sysv: %d nowait: %d sili: %d "
+			  "nowait_filemark: %d\n",
+			  STm->sysv, STp->immediate, STp->sili,
+			  STp->immediate_filemark);
+		st_printk(KERN_INFO, STp, "    debugging: %d\n", debugging);
 	}
 }
 	)
@@ -2196,7 +2210,6 @@ static int st_set_options(struct scsi_ta
 	int value;
 	long code;
 	struct st_modedef *STm;
-	char *name = tape_name(STp);
 	struct cdev *cd0, *cd1;
 	struct device *d0, *d1;
 
@@ -2212,9 +2225,8 @@ static int st_set_options(struct scsi_ta
 		STm->devs[0]  = d0;
 		STm->devs[1]  = d1;
 		modes_defined = 1;
-                DEBC(printk(ST_DEB_MSG
-                            "%s: Initialized mode %d definition from mode 0\n",
-                            name, STp->current_mode));
+		DEBC_printk(STp, "Initialized mode %d definition from mode 0\n",
+			    STp->current_mode);
 	}
 
 	code = options & MT_ST_OPTIONS;
@@ -2236,7 +2248,7 @@ static int st_set_options(struct scsi_ta
 		STm->sysv = (options & MT_ST_SYSV) != 0;
 		STp->sili = (options & MT_ST_SILI) != 0;
 		DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
-		     st_log_options(STp, STm, name); )
+		     st_log_options(STp, STm); )
 	} else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
 		value = (code == MT_ST_SETBOOLEANS);
 		if ((options & MT_ST_BUFFER_WRITES) != 0)
@@ -2270,21 +2282,21 @@ static int st_set_options(struct scsi_ta
 			STm->sysv = value;
 		if ((options & MT_ST_SILI) != 0)
 			STp->sili = value;
-                DEB(
+		DEB(
 		if ((options & MT_ST_DEBUGGING) != 0)
 			debugging = value;
-			st_log_options(STp, STm, name); )
+			st_log_options(STp, STm); )
 	} else if (code == MT_ST_WRITE_THRESHOLD) {
 		/* Retained for compatibility */
 	} else if (code == MT_ST_DEF_BLKSIZE) {
 		value = (options & ~MT_ST_OPTIONS);
 		if (value == ~MT_ST_OPTIONS) {
 			STm->default_blksize = (-1);
-			DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name));
+			DEBC_printk(STp, "Default block size disabled.\n");
 		} else {
 			STm->default_blksize = value;
-			DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n",
-			       name, STm->default_blksize));
+			DEBC_printk(STp,"Default block size set to "
+				    "%d bytes.\n", STm->default_blksize);
 			if (STp->ready == ST_READY) {
 				STp->blksize_changed = 0;
 				set_mode_densblk(STp, STm);
@@ -2294,13 +2306,13 @@ static int st_set_options(struct scsi_ta
 		value = (options & ~MT_ST_OPTIONS);
 		if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
 			STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
-			DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,
-			       (value & ~MT_ST_SET_LONG_TIMEOUT)));
+			DEBC_printk(STp, "Long timeout set to %d seconds.\n",
+				    (value & ~MT_ST_SET_LONG_TIMEOUT));
 		} else {
 			blk_queue_rq_timeout(STp->device->request_queue,
 					     value * HZ);
-			DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",
-				name, value) );
+			DEBC_printk(STp, "Normal timeout set to %d seconds.\n",
+				    value);
 		}
 	} else if (code == MT_ST_SET_CLN) {
 		value = (options & ~MT_ST_OPTIONS) & 0xff;
@@ -2311,21 +2323,21 @@ static int st_set_options(struct scsi_ta
 		STp->cln_mode = value;
 		STp->cln_sense_mask = (options >> 8) & 0xff;
 		STp->cln_sense_value = (options >> 16) & 0xff;
-		printk(KERN_INFO
-		       "%s: Cleaning request mode %d, mask %02x, value %02x\n",
-		       name, value, STp->cln_sense_mask, STp->cln_sense_value);
+		st_printk(KERN_INFO, STp,
+			  "Cleaning request mode %d, mask %02x, value %02x\n",
+			  value, STp->cln_sense_mask, STp->cln_sense_value);
 	} else if (code == MT_ST_DEF_OPTIONS) {
 		code = (options & ~MT_ST_CLEAR_DEFAULT);
 		value = (options & MT_ST_CLEAR_DEFAULT);
 		if (code == MT_ST_DEF_DENSITY) {
 			if (value == MT_ST_CLEAR_DEFAULT) {
 				STm->default_density = (-1);
-				DEBC( printk(KERN_INFO "%s: Density default disabled.\n",
-                                       name));
+				DEBC_printk(STp,
+					    "Density default disabled.\n");
 			} else {
 				STm->default_density = value & 0xff;
-				DEBC( printk(KERN_INFO "%s: Density default set to %x\n",
-				       name, STm->default_density));
+				DEBC_printk(STp, "Density default set to %x\n",
+					    STm->default_density);
 				if (STp->ready == ST_READY) {
 					STp->density_changed = 0;
 					set_mode_densblk(STp, STm);
@@ -2334,31 +2346,33 @@ static int st_set_options(struct scsi_ta
 		} else if (code == MT_ST_DEF_DRVBUFFER) {
 			if (value == MT_ST_CLEAR_DEFAULT) {
 				STp->default_drvbuffer = 0xff;
-				DEBC( printk(KERN_INFO
-                                       "%s: Drive buffer default disabled.\n", name));
+				DEBC_printk(STp,
+					    "Drive buffer default disabled.\n");
 			} else {
 				STp->default_drvbuffer = value & 7;
-				DEBC( printk(KERN_INFO
-                                       "%s: Drive buffer default set to %x\n",
-				       name, STp->default_drvbuffer));
+				DEBC_printk(STp,
+					    "Drive buffer default set to %x\n",
+					    STp->default_drvbuffer);
 				if (STp->ready == ST_READY)
 					st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);
 			}
 		} else if (code == MT_ST_DEF_COMPRESSION) {
 			if (value == MT_ST_CLEAR_DEFAULT) {
 				STm->default_compression = ST_DONT_TOUCH;
-				DEBC( printk(KERN_INFO
-                                       "%s: Compression default disabled.\n", name));
+				DEBC_printk(STp,
+					    "Compression default disabled.\n");
 			} else {
 				if ((value & 0xff00) != 0) {
 					STp->c_algo = (value & 0xff00) >> 8;
-					DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n",
-					       name, STp->c_algo));
+					DEBC_printk(STp, "Compression "
+						    "algorithm set to 0x%x.\n",
+						    STp->c_algo);
 				}
 				if ((value & 0xff) != 0xff) {
 					STm->default_compression = (value & 1 ? ST_YES : ST_NO);
-					DEBC( printk(KERN_INFO "%s: Compression default set to %x\n",
-					       name, (value & 1)));
+					DEBC_printk(STp, "Compression default "
+						    "set to %x\n",
+						    (value & 1));
 					if (STp->ready == ST_READY) {
 						STp->compression_changed = 0;
 						st_compression(STp, (STm->default_compression == ST_YES));
@@ -2473,7 +2487,6 @@ static int st_compression(struct scsi_ta
 	int retval;
 	int mpoffs;  /* Offset to mode page start */
 	unsigned char *b_data = (STp->buffer)->b_data;
-	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
@@ -2481,18 +2494,17 @@ static int st_compression(struct scsi_ta
 	/* Read the current page contents */
 	retval = read_mode_page(STp, COMPRESSION_PAGE, 0);
 	if (retval) {
-                DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n",
-                            name));
+		DEBC_printk(STp, "Compression mode page not supported.\n");
 		return (-EIO);
 	}
 
 	mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
-        DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name,
-                    (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
+	DEBC_printk(STp, "Compression state is %d.\n",
+		    (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0));
 
 	/* Check if compression can be changed */
 	if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
-                DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name));
+		DEBC_printk(STp, "Compression not supported.\n");
 		return (-EIO);
 	}
 
@@ -2510,11 +2522,10 @@ static int st_compression(struct scsi_ta
 
 	retval = write_mode_page(STp, COMPRESSION_PAGE, 0);
 	if (retval) {
-                DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name));
+		DEBC_printk(STp, "Compression change failed.\n");
 		return (-EIO);
 	}
-        DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n",
-		       name, state));
+	DEBC_printk(STp, "Compression state changed to %d.\n", state);
 
 	STp->compression_changed = 1;
 	return 0;
@@ -2525,7 +2536,6 @@ static int st_compression(struct scsi_ta
 static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code)
 {
 	int retval = (-EIO), timeout;
-	DEB( char *name = tape_name(STp); )
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	struct st_partstat *STps;
 	struct st_request *SRpnt;
@@ -2546,9 +2556,9 @@ static int do_load_unload(struct scsi_ta
 	 */
 	if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
 	    && load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
-		DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n",
-			    name, (cmd[4]) ? "" : "un",
-			    load_code - MT_ST_HPLOADER_OFFSET));
+		DEBC_printk(STp, " Enhanced %sload slot %2d.\n",
+			    (cmd[4]) ? "" : "un",
+			    load_code - MT_ST_HPLOADER_OFFSET);
 		cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
 	}
 	if (STp->immediate) {
@@ -2560,9 +2570,9 @@ static int do_load_unload(struct scsi_ta
 
 	DEBC(
 		if (!load_code)
-		printk(ST_DEB_MSG "%s: Unloading tape.\n", name);
+			st_printk(ST_DEB_MSG, STp, "Unloading tape.\n");
 		else
-		printk(ST_DEB_MSG "%s: Loading tape.\n", name);
+			st_printk(ST_DEB_MSG, STp, "Loading tape.\n");
 		);
 
 	SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
@@ -2597,17 +2607,24 @@ static int do_load_unload(struct scsi_ta
 #if DEBUG
 #define ST_DEB_FORWARD  0
 #define ST_DEB_BACKWARD 1
-static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd)
+static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd)
 {
 	s32 sc;
 
+	if (!debugging)
+		return;
+
 	sc = cmd[2] & 0x80 ? 0xff000000 : 0;
 	sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
 	if (direction)
 		sc = -sc;
-	printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name,
-	       direction ? "backward" : "forward", sc, units);
+	st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n",
+		  direction ? "backward" : "forward", sc, units);
 }
+#else
+#define ST_DEB_FORWARD  0
+#define ST_DEB_BACKWARD 1
+static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) {}
 #endif
 
 
@@ -2623,7 +2640,6 @@ static int st_int_ioctl(struct scsi_tape
 	struct st_partstat *STps;
 	int fileno, blkno, at_sm, undone;
 	int datalen = 0, direction = DMA_NONE;
-	char *name = tape_name(STp);
 
 	WARN_ON(STp->buffer->do_dio != 0);
 	if (STp->ready != ST_READY) {
@@ -2648,7 +2664,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
-                DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);)
+		deb_space_print(STp, ST_DEB_FORWARD, "filemarks", cmd);
 		if (fileno >= 0)
 			fileno += arg;
 		blkno = 0;
@@ -2663,7 +2679,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (ltmp >> 16);
 		cmd[3] = (ltmp >> 8);
 		cmd[4] = ltmp;
-                DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);)
+		deb_space_print(STp, ST_DEB_BACKWARD, "filemarks", cmd);
 		if (fileno >= 0)
 			fileno -= arg;
 		blkno = (-1);	/* We can't know the block number */
@@ -2675,7 +2691,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
-                DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);)
+		deb_space_print(STp, ST_DEB_FORWARD, "blocks", cmd);
 		if (blkno >= 0)
 			blkno += arg;
 		at_sm &= (arg == 0);
@@ -2687,7 +2703,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (ltmp >> 16);
 		cmd[3] = (ltmp >> 8);
 		cmd[4] = ltmp;
-                DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);)
+		deb_space_print(STp, ST_DEB_BACKWARD, "blocks", cmd);
 		if (blkno >= 0)
 			blkno -= arg;
 		at_sm &= (arg == 0);
@@ -2698,7 +2714,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
-                DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);)
+		deb_space_print(STp, ST_DEB_FORWARD, "setmarks", cmd);
 		if (arg != 0) {
 			blkno = fileno = (-1);
 			at_sm = 1;
@@ -2711,7 +2727,7 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[2] = (ltmp >> 16);
 		cmd[3] = (ltmp >> 8);
 		cmd[4] = ltmp;
-                DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);)
+		deb_space_print(STp, ST_DEB_BACKWARD, "setmarks", cmd);
 		if (arg != 0) {
 			blkno = fileno = (-1);
 			at_sm = 1;
@@ -2732,13 +2748,19 @@ static int st_int_ioctl(struct scsi_tape
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
 		timeout = STp->device->request_queue->rq_timeout;
-                DEBC(
-		     if (cmd_in != MTWSM)
-                               printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
-				 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
-                     else
-				printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name,
-				 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+		DEBC(
+			if (cmd_in != MTWSM)
+				st_printk(ST_DEB_MSG, STp,
+					  "Writing %d filemarks.\n",
+					  cmd[2] * 65536 +
+					  cmd[3] * 256 +
+					  cmd[4]);
+			else
+				st_printk(ST_DEB_MSG, STp,
+					  "Writing %d setmarks.\n",
+					  cmd[2] * 65536 +
+					  cmd[3] * 256 +
+					  cmd[4]);
 		)
 		if (fileno >= 0)
 			fileno += arg;
@@ -2751,11 +2773,11 @@ static int st_int_ioctl(struct scsi_tape
 			cmd[1] = 1;	/* Don't wait for completion */
 			timeout = STp->device->request_queue->rq_timeout;
 		}
-                DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name));
+		DEBC_printk(STp, "Rewinding tape.\n");
 		fileno = blkno = at_sm = 0;
 		break;
 	case MTNOP:
-                DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name));
+		DEBC_printk(STp, "No op on tape.\n");
 		return 0;	/* Should do something ? */
 		break;
 	case MTRETEN:
@@ -2765,7 +2787,7 @@ static int st_int_ioctl(struct scsi_tape
 			timeout = STp->device->request_queue->rq_timeout;
 		}
 		cmd[4] = 3;
-                DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name));
+		DEBC_printk(STp, "Retensioning tape.\n");
 		fileno = blkno = at_sm = 0;
 		break;
 	case MTEOM:
@@ -2783,8 +2805,7 @@ static int st_int_ioctl(struct scsi_tape
 			fileno = (-1);
 		cmd[0] = SPACE;
 		cmd[1] = 3;
-                DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n",
-                            name));
+		DEBC_printk(STp, "Spacing to end of recorded medium.\n");
 		blkno = -1;
 		at_sm = 0;
 		break;
@@ -2800,7 +2821,7 @@ static int st_int_ioctl(struct scsi_tape
 		else
 			timeout = STp->long_timeout * 8;
 
-                DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name));
+		DEBC_printk(STp, "Erasing tape.\n");
 		fileno = blkno = at_sm = 0;
 		break;
 	case MTSETBLK:		/* Set block length */
@@ -2815,7 +2836,7 @@ static int st_int_ioctl(struct scsi_tape
 		    STp->max_block > 0 &&
 		    ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
 		     (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) {
-			printk(KERN_WARNING "%s: Illegal block size.\n", name);
+			st_printk(KERN_WARNING, STp, "Illegal block size.\n");
 			return (-EINVAL);
 		}
 		cmd[0] = MODE_SELECT;
@@ -2848,21 +2869,21 @@ static int st_int_ioctl(struct scsi_tape
 		(STp->buffer)->b_data[10] = (ltmp >> 8);
 		(STp->buffer)->b_data[11] = ltmp;
 		timeout = STp->device->request_queue->rq_timeout;
-                DEBC(
+		DEBC(
 			if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
-				printk(ST_DEB_MSG
-                                       "%s: Setting block size to %d bytes.\n", name,
-				       (STp->buffer)->b_data[9] * 65536 +
-				       (STp->buffer)->b_data[10] * 256 +
-				       (STp->buffer)->b_data[11]);
+				st_printk(ST_DEB_MSG, STp,
+					  "Setting block size to %d bytes.\n",
+					  (STp->buffer)->b_data[9] * 65536 +
+					  (STp->buffer)->b_data[10] * 256 +
+					  (STp->buffer)->b_data[11]);
 			if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
-				printk(ST_DEB_MSG
-                                       "%s: Setting density code to %x.\n", name,
-				       (STp->buffer)->b_data[4]);
+				st_printk(ST_DEB_MSG, STp,
+					  "Setting density code to %x.\n",
+					  (STp->buffer)->b_data[4]);
 			if (cmd_in == MTSETDRVBUFFER)
-				printk(ST_DEB_MSG
-                                       "%s: Setting drive buffer code to %d.\n", name,
-				    ((STp->buffer)->b_data[2] >> 4) & 7);
+				st_printk(ST_DEB_MSG, STp,
+					  "Setting drive buffer code to %d.\n",
+					  ((STp->buffer)->b_data[2] >> 4) & 7);
 		)
 		break;
 	default:
@@ -3019,7 +3040,6 @@ static int get_location(struct scsi_tape
 	int result;
 	unsigned char scmd[MAX_COMMAND_SIZE];
 	struct st_request *SRpnt;
-	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
@@ -3043,7 +3063,7 @@ static int get_location(struct scsi_tape
 	    (STp->device->scsi_level >= SCSI_2 &&
 	     ((STp->buffer)->b_data[0] & 4) != 0)) {
 		*block = *partition = 0;
-                DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name));
+		DEBC_printk(STp, " Can't read tape position.\n");
 		result = (-EIO);
 	} else {
 		result = 0;
@@ -3062,8 +3082,8 @@ static int get_location(struct scsi_tape
 			    (STp->buffer)->b_data[1] == 0)	/* BOP of partition 0 */
 				STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
 		}
-                DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
-                            *block, *partition));
+		DEBC_printk(STp, "Got tape pos. blk %d part %d.\n",
+			    *block, *partition);
 	}
 	st_release_request(SRpnt);
 	SRpnt = NULL;
@@ -3083,15 +3103,14 @@ static int set_location(struct scsi_tape
 	int timeout;
 	unsigned char scmd[MAX_COMMAND_SIZE];
 	struct st_request *SRpnt;
-	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
 	timeout = STp->long_timeout;
 	STps = &(STp->ps[STp->partition]);
 
-        DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n",
-                    name, block, partition));
+	DEBC_printk(STp, "Setting block to %d and partition to %d.\n",
+		    block, partition);
 	DEB(if (partition < 0)
 		return (-EIO); )
 
@@ -3105,9 +3124,9 @@ static int set_location(struct scsi_tape
 		else {
 			STps->last_block_valid = 1;
 			STps->last_block_visited = blk;
-                        DEBC(printk(ST_DEB_MSG
-                                    "%s: Visited block %d for partition %d saved.\n",
-                                    name, blk, STp->partition));
+			DEBC_printk(STp, "Visited block %d for "
+				    "partition %d saved.\n",
+				    blk, STp->partition);
 		}
 	}
 
@@ -3129,9 +3148,9 @@ static int set_location(struct scsi_tape
 		if (STp->partition != partition) {
 			scmd[1] |= 2;
 			scmd[8] = partition;
-                        DEBC(printk(ST_DEB_MSG
-                                    "%s: Trying to change partition from %d to %d\n",
-                                    name, STp->partition, partition));
+			DEBC_printk(STp, "Trying to change partition "
+				    "from %d to %d\n", STp->partition,
+				    partition);
 		}
 	}
 	if (STp->immediate) {
@@ -3222,7 +3241,6 @@ static int switch_partition(struct scsi_
 static int nbr_partitions(struct scsi_tape *STp)
 {
 	int result;
-	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
@@ -3230,13 +3248,12 @@ static int nbr_partitions(struct scsi_ta
 	result = read_mode_page(STp, PART_PAGE, 1);
 
 	if (result) {
-                DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n",
-                            name));
+		DEBC_printk(STp, "Can't read medium partition page.\n");
 		result = (-EIO);
 	} else {
 		result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
 					      PP_OFF_NBR_ADD_PARTS] + 1;
-                DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result));
+		DEBC_printk(STp, "Number of partitions %d.\n", result);
 	}
 
 	return result;
@@ -3264,21 +3281,20 @@ static int nbr_partitions(struct scsi_ta
  */
 static int partition_tape(struct scsi_tape *STp, int size)
 {
-	char *name = tape_name(STp);
 	int result;
 	int pgo, psd_cnt, psdo;
 	unsigned char *bp;
 
 	result = read_mode_page(STp, PART_PAGE, 0);
 	if (result) {
-		DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name));
+		DEBC_printk(STp, "Can't read partition mode page.\n");
 		return result;
 	}
 	/* The mode page is in the buffer. Let's modify it and write it. */
 	bp = (STp->buffer)->b_data;
 	pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
-	DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n",
-		    name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
+	DEBC_printk(STp, "Partition page length is %d bytes.\n",
+		    bp[pgo + MP_OFF_PAGE_LENGTH] + 2);
 
 	psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
 	psdo = pgo + PART_PAGE_FIXED_LENGTH;
@@ -3288,25 +3304,23 @@ static int partition_tape(struct scsi_ta
 	}
 	memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
 
-	DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name,
+	DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
 		    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
-		    bp[pgo + PP_OFF_NBR_ADD_PARTS]));
+		    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
 
 	if (size <= 0) {
 		bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
 		if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
 		    bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
-                DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n",
-                            name));
+		DEBC_printk(STp, "Formatting tape with one partition.\n");
 	} else {
 		bp[psdo] = (size >> 8) & 0xff;
 		bp[psdo + 1] = size & 0xff;
 		bp[pgo + 3] = 1;
 		if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)
 		    bp[pgo + MP_OFF_PAGE_LENGTH] = 8;
-                DEBC(printk(ST_DEB_MSG
-                            "%s: Formatting tape with two partitions (1 = %d MB).\n",
-                            name, size));
+		DEBC_printk(STp, "Formatting tape with two partitions "
+			    "(1 = %d MB).\n", size);
 	}
 	bp[pgo + PP_OFF_PART_UNITS] = 0;
 	bp[pgo + PP_OFF_RESERVED] = 0;
@@ -3314,7 +3328,7 @@ static int partition_tape(struct scsi_ta
 
 	result = write_mode_page(STp, PART_PAGE, 1);
 	if (result) {
-		printk(KERN_INFO "%s: Partitioning of tape failed.\n", name);
+		st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n");
 		result = (-EIO);
 	}
 
@@ -3332,15 +3346,14 @@ static long st_ioctl(struct file *file,
 	struct scsi_tape *STp = file->private_data;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
-	char *name = tape_name(STp);
 	void __user *p = (void __user *)arg;
 
 	if (mutex_lock_interruptible(&STp->lock))
 		return -ERESTARTSYS;
 
-        DEB(
+	DEB(
 	if (debugging && !STp->in_use) {
-		printk(ST_DEB_MSG "%s: Incorrect device.\n", name);
+		st_printk(ST_DEB_MSG, STp, "Incorrect device.\n");
 		retval = (-EIO);
 		goto out;
 	} ) /* end DEB */
@@ -3378,8 +3391,8 @@ static long st_ioctl(struct file *file,
 		}
 
 		if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
-			printk(KERN_WARNING
-                               "%s: MTSETDRVBUFFER only allowed for root.\n", name);
+			st_printk(KERN_WARNING, STp,
+				  "MTSETDRVBUFFER only allowed for root.\n");
 			retval = (-EPERM);
 			goto out;
 		}
@@ -4087,7 +4100,8 @@ static int st_probe(struct device *dev)
 		return -ENODEV;
 	if ((stp = st_incompatible(SDp))) {
 		sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n");
-		printk(KERN_INFO "st: The suggested driver is %s.\n", stp);
+		sdev_printk(KERN_INFO, SDp,
+			    "st: The suggested driver is %s.\n", stp);
 		return -ENODEV;
 	}
 
@@ -4096,20 +4110,23 @@ static int st_probe(struct device *dev)
 		i = st_max_sg_segs;
 	buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i);
 	if (buffer == NULL) {
-		printk(KERN_ERR
-		       "st: Can't allocate new tape buffer. Device not attached.\n");
+		sdev_printk(KERN_ERR, SDp,
+			    "st: Can't allocate new tape buffer. "
+			    "Device not attached.\n");
 		goto out;
 	}
 
 	disk = alloc_disk(1);
 	if (!disk) {
-		printk(KERN_ERR "st: out of memory. Device not attached.\n");
+		sdev_printk(KERN_ERR, SDp,
+			    "st: out of memory. Device not attached.\n");
 		goto out_buffer_free;
 	}
 
 	tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
 	if (tpnt == NULL) {
-		printk(KERN_ERR "st: Can't allocate device descriptor.\n");
+		sdev_printk(KERN_ERR, SDp,
+			    "st: Can't allocate device descriptor.\n");
 		goto out_put_disk;
 	}
 	kref_init(&tpnt->kref);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/storvsc_drv.c linux-libre-3.17-rc7-gnu/drivers/scsi/storvsc_drv.c
--- linux-libre-3.16-gnu/drivers/scsi/storvsc_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/storvsc_drv.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/hyperv.h>
 #include <linux/mempool.h>
+#include <linux/blkdev.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -326,21 +327,23 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size
  */
 static int storvsc_timeout = 180;
 
+static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
+
 #define STORVSC_MAX_IO_REQUESTS				200
 
 static void storvsc_on_channel_callback(void *context);
 
-/*
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
- * reality, the path/target is not used (ie always set to 0) so our
- * scsi host adapter essentially has 1 bus with 1 target that contains
- * up to 256 luns.
- */
-#define STORVSC_MAX_LUNS_PER_TARGET			64
-#define STORVSC_MAX_TARGETS				1
-#define STORVSC_MAX_CHANNELS				1
+#define STORVSC_MAX_LUNS_PER_TARGET			255
+#define STORVSC_MAX_TARGETS				2
+#define STORVSC_MAX_CHANNELS				8
 
+#define STORVSC_FC_MAX_LUNS_PER_TARGET			255
+#define STORVSC_FC_MAX_TARGETS				128
+#define STORVSC_FC_MAX_CHANNELS				8
 
+#define STORVSC_IDE_MAX_LUNS_PER_TARGET			64
+#define STORVSC_IDE_MAX_TARGETS				1
+#define STORVSC_IDE_MAX_CHANNELS			1
 
 struct storvsc_cmd_request {
 	struct list_head entry;
@@ -1017,6 +1020,13 @@ static void storvsc_handle_error(struct
 		case ATA_12:
 			set_host_byte(scmnd, DID_PASSTHROUGH);
 			break;
+		/*
+		 * On Some Windows hosts TEST_UNIT_READY command can return
+		 * SRB_STATUS_ERROR, let the upper level code deal with it
+		 * based on the sense information.
+		 */
+		case TEST_UNIT_READY:
+			break;
 		default:
 			set_host_byte(scmnd, DID_TARGET_FAILURE);
 		}
@@ -1441,6 +1451,14 @@ static int storvsc_device_configure(stru
 
 	sdevice->no_write_same = 1;
 
+	/*
+	 * Add blist flags to permit the reading of the VPD pages even when
+	 * the target may claim SPC-2 compliance. MSFT targets currently
+	 * claim SPC-2 compliance while they implement post SPC-2 features.
+	 * With this patch we can correctly handle WRITE_SAME_16 issues.
+	 */
+	sdevice->sdev_bflags |= msft_blist_flags;
+
 	return 0;
 }
 
@@ -1518,6 +1536,16 @@ static int storvsc_host_reset_handler(st
 	return SUCCESS;
 }
 
+/*
+ * The host guarantees to respond to each command, although I/O latencies might
+ * be unbounded on Azure.  Reset the timer unconditionally to give the host a
+ * chance to perform EH.
+ */
+static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
+{
+	return BLK_EH_RESET_TIMER;
+}
+
 static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
 {
 	bool allowed = true;
@@ -1553,9 +1581,19 @@ static int storvsc_queuecommand(struct S
 	struct vmscsi_request *vm_srb;
 	struct stor_mem_pools *memp = scmnd->device->hostdata;
 
-	if (!storvsc_scsi_cmd_ok(scmnd)) {
-		scmnd->scsi_done(scmnd);
-		return 0;
+	if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) {
+		/*
+		 * On legacy hosts filter unimplemented commands.
+		 * Future hosts are expected to correctly handle
+		 * unsupported commands. Furthermore, it is
+		 * possible that some of the currently
+		 * unsupported commands maybe supported in
+		 * future versions of the host.
+		 */
+		if (!storvsc_scsi_cmd_ok(scmnd)) {
+			scmnd->scsi_done(scmnd);
+			return 0;
+		}
 	}
 
 	request_size = sizeof(struct storvsc_cmd_request);
@@ -1580,26 +1618,24 @@ static int storvsc_queuecommand(struct S
 	vm_srb = &cmd_request->vstor_packet.vm_srb;
 	vm_srb->win8_extension.time_out_value = 60;
 
+	vm_srb->win8_extension.srb_flags |=
+		(SRB_FLAGS_QUEUE_ACTION_ENABLE |
+		SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
 
 	/* Build the SRB */
 	switch (scmnd->sc_data_direction) {
 	case DMA_TO_DEVICE:
 		vm_srb->data_in = WRITE_TYPE;
 		vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT;
-		vm_srb->win8_extension.srb_flags |=
-			(SRB_FLAGS_QUEUE_ACTION_ENABLE |
-			SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
 		break;
 	case DMA_FROM_DEVICE:
 		vm_srb->data_in = READ_TYPE;
 		vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN;
-		vm_srb->win8_extension.srb_flags |=
-			(SRB_FLAGS_QUEUE_ACTION_ENABLE |
-			SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
 		break;
 	default:
 		vm_srb->data_in = UNKNOWN_TYPE;
-		vm_srb->win8_extension.srb_flags = 0;
+		vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN |
+						     SRB_FLAGS_DATA_OUT);
 		break;
 	}
 
@@ -1687,11 +1723,11 @@ static struct scsi_host_template scsi_dr
 	.bios_param =		storvsc_get_chs,
 	.queuecommand =		storvsc_queuecommand,
 	.eh_host_reset_handler =	storvsc_host_reset_handler,
+	.eh_timed_out =		storvsc_eh_timed_out,
 	.slave_alloc =		storvsc_device_alloc,
 	.slave_destroy =	storvsc_device_destroy,
 	.slave_configure =	storvsc_device_configure,
-	.cmd_per_lun =		1,
-	/* 64 max_queue * 1 target */
+	.cmd_per_lun =		255,
 	.can_queue =		STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
 	.this_id =		-1,
 	/* no use setting to 0 since ll_blk_rw reset it to 1 */
@@ -1743,19 +1779,25 @@ static int storvsc_probe(struct hv_devic
 	 * set state to properly communicate with the host.
 	 */
 
-	if (vmbus_proto_version == VERSION_WIN8) {
-		sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
-		vmscsi_size_delta = 0;
-		vmstor_current_major = VMSTOR_WIN8_MAJOR;
-		vmstor_current_minor = VMSTOR_WIN8_MINOR;
-	} else {
+	switch (vmbus_proto_version) {
+	case VERSION_WS2008:
+	case VERSION_WIN7:
 		sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
 		vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
 		vmstor_current_major = VMSTOR_WIN7_MAJOR;
 		vmstor_current_minor = VMSTOR_WIN7_MINOR;
+		break;
+	default:
+		sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
+		vmscsi_size_delta = 0;
+		vmstor_current_major = VMSTOR_WIN8_MAJOR;
+		vmstor_current_minor = VMSTOR_WIN8_MINOR;
+		break;
 	}
 
-
+	if (dev_id->driver_data == SFC_GUID)
+		scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS *
+					 STORVSC_FC_MAX_TARGETS);
 	host = scsi_host_alloc(&scsi_driver,
 			       sizeof(struct hv_host_device));
 	if (!host)
@@ -1789,12 +1831,25 @@ static int storvsc_probe(struct hv_devic
 	host_dev->path = stor_device->path_id;
 	host_dev->target = stor_device->target_id;
 
-	/* max # of devices per target */
-	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
-	/* max # of targets per channel */
-	host->max_id = STORVSC_MAX_TARGETS;
-	/* max # of channels */
-	host->max_channel = STORVSC_MAX_CHANNELS - 1;
+	switch (dev_id->driver_data) {
+	case SFC_GUID:
+		host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET;
+		host->max_id = STORVSC_FC_MAX_TARGETS;
+		host->max_channel = STORVSC_FC_MAX_CHANNELS - 1;
+		break;
+
+	case SCSI_GUID:
+		host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
+		host->max_id = STORVSC_MAX_TARGETS;
+		host->max_channel = STORVSC_MAX_CHANNELS - 1;
+		break;
+
+	default:
+		host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET;
+		host->max_id = STORVSC_IDE_MAX_TARGETS;
+		host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1;
+		break;
+	}
 	/* max cmd length */
 	host->max_cmd_len = STORVSC_MAX_CMD_LEN;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sun3_NCR5380.c linux-libre-3.17-rc7-gnu/drivers/scsi/sun3_NCR5380.c
--- linux-libre-3.16-gnu/drivers/scsi/sun3_NCR5380.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sun3_NCR5380.c	2014-09-28 17:29:07.000000000 -0400
@@ -355,17 +355,18 @@ static void __init init_tags( void )
 
 static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged)
 {
+    u8 lun = cmd->device->lun;
     SETUP_HOSTDATA(cmd->device->host);
 
-    if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+    if (hostdata->busy[cmd->device->id] & (1 << lun))
 	return( 1 );
     if (!should_be_tagged ||
 	!setup_use_tagged_queuing || !cmd->device->tagged_supported)
 	return( 0 );
-    if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
-	TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) {
+    if (TagAlloc[cmd->device->id][lun].nr_allocated >=
+	TagAlloc[cmd->device->id][lun].queue_size ) {
 	dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d: no free tags\n",
-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
+		    H_NO(cmd), cmd->device->id, lun );
 	return( 1 );
     }
     return( 0 );
@@ -379,6 +380,7 @@ static int is_lun_busy(struct scsi_cmnd
 
 static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged)
 {
+    u8 lun = cmd->device->lun;
     SETUP_HOSTDATA(cmd->device->host);
 
     /* If we or the target don't support tagged queuing, allocate the LUN for
@@ -387,19 +389,19 @@ static void cmd_get_tag(struct scsi_cmnd
     if (!should_be_tagged ||
 	!setup_use_tagged_queuing || !cmd->device->tagged_supported) {
 	cmd->tag = TAG_NONE;
-	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+	hostdata->busy[cmd->device->id] |= (1 << lun);
 	dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d now allocated by untagged "
-		    "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun );
+		    "command\n", H_NO(cmd), cmd->device->id, lun );
     }
     else {
-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
 
 	cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS );
 	set_bit( cmd->tag, &ta->allocated );
 	ta->nr_allocated++;
 	dprintk(NDEBUG_TAGS,  "scsi%d: using tag %d for target %d lun %d "
 		    "(now %d tags in use)\n",
-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun,
+		    H_NO(cmd), cmd->tag, cmd->device->id, lun,
 		    ta->nr_allocated );
     }
 }
@@ -411,23 +413,24 @@ static void cmd_get_tag(struct scsi_cmnd
 
 static void cmd_free_tag(struct scsi_cmnd *cmd)
 {
+    u8 lun = cmd->device->lun;
     SETUP_HOSTDATA(cmd->device->host);
 
     if (cmd->tag == TAG_NONE) {
-	hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+	hostdata->busy[cmd->device->id] &= ~(1 << lun);
 	dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d untagged cmd finished\n",
-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
+		    H_NO(cmd), cmd->device->id, lun );
     }
     else if (cmd->tag >= MAX_TAGS) {
 	printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
 		H_NO(cmd), cmd->tag );
     }
     else {
-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
 	clear_bit( cmd->tag, &ta->allocated );
 	ta->nr_allocated--;
 	dprintk(NDEBUG_TAGS,  "scsi%d: freed tag %d for target %d lun %d\n",
-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun );
+		    H_NO(cmd), cmd->tag, cmd->device->id, lun );
     }
 }
 
@@ -659,7 +662,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *
 {
 	int i, s;
 	unsigned char *command;
-	printk("scsi%d: destination target %d, lun %d\n",
+	printk("scsi%d: destination target %d, lun %llu\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
 	printk(KERN_CONT "        command = ");
 	command = cmd->cmnd;
@@ -705,7 +708,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cm
 {
 	int i, s;
 	unsigned char *command;
-	seq_printf(m, "scsi%d: destination target %d, lun %d\n",
+	seq_printf(m, "scsi%d: destination target %d, lun %llu\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
 	seq_printf(m, "        command = ");
 	command = cmd->cmnd;
@@ -1007,7 +1010,7 @@ static void NCR5380_main (struct work_st
 		 prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
 
 		if (prev != tmp)
-			dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
+			dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
 		/*  When we find one, remove it from the issue queue. */
 		/* ++guenther: possible race with Falcon locking */
 		if (
@@ -1038,7 +1041,7 @@ static void NCR5380_main (struct work_st
 		     *   issue queue so we can keep trying.	
 		     */
 		    dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d "
-				"lun %d removed from issue_queue\n",
+				"lun %llu removed from issue_queue\n",
 				HOSTNO, tmp->device->id, tmp->device->lun);
 		    /* 
 		     * REQUEST SENSE commands are issued without tagged
@@ -2020,7 +2023,7 @@ static void NCR5380_information_transfer
 			 * accesses to this device will use the
 			 * polled-IO. */ 
 			printk(KERN_NOTICE "scsi%d: switching target %d "
-			       "lun %d to slow handshake\n", HOSTNO,
+			       "lun %llu to slow handshake\n", HOSTNO,
 			       cmd->device->id, cmd->device->lun);
 			cmd->device->borken = 1;
 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
@@ -2078,7 +2081,7 @@ static void NCR5380_information_transfer
 		    /* Accept message by clearing ACK */
 		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		    
-		    dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command "
+		    dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command "
 			       "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
 
 		    /* Enable reselect interrupts */
@@ -2090,7 +2093,7 @@ static void NCR5380_information_transfer
 		     */
 
 		    if (!cmd->next_link) {
-			 printk(KERN_NOTICE "scsi%d: target %d lun %d "
+			 printk(KERN_NOTICE "scsi%d: target %d lun %llu "
 				"linked command complete, no next_link\n",
 				HOSTNO, cmd->device->id, cmd->device->lun);
 			    sink = 1;
@@ -2103,7 +2106,7 @@ static void NCR5380_information_transfer
 		     * and don't free it! */
 		    cmd->next_link->tag = cmd->tag;
 		    cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-		    dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request "
+		    dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
 			       "done, calling scsi_done().\n",
 			       HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef NCR5380_STATS
@@ -2118,7 +2121,7 @@ static void NCR5380_information_transfer
 		    /* Accept message by clearing ACK */
 		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		    hostdata->connected = NULL;
-		    dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d "
+		    dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
 			      "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef SUPPORT_TAGS
 		    cmd_free_tag( cmd );
@@ -2132,7 +2135,7 @@ static void NCR5380_information_transfer
 			/* ++Andreas: the mid level code knows about
 			   QUEUE_FULL now. */
 			TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-			dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned "
+			dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
 				   "QUEUE_FULL after %d commands\n",
 				   HOSTNO, cmd->device->id, cmd->device->lun,
 				   ta->nr_allocated);
@@ -2228,7 +2231,7 @@ static void NCR5380_information_transfer
 			cmd->device->tagged_supported = 0;
 			hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 			cmd->tag = TAG_NONE;
-			dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected "
+			dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected "
 				   "QUEUE_TAG message; tagged queuing "
 				   "disabled\n",
 				   HOSTNO, cmd->device->id, cmd->device->lun);
@@ -2245,7 +2248,7 @@ static void NCR5380_information_transfer
 		    hostdata->connected = NULL;
 		    hostdata->disconnected_queue = cmd;
 		    local_irq_restore(flags);
-		    dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was "
+		    dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was "
 			      "moved from connected to the "
 			      "disconnected_queue\n", HOSTNO, 
 			      cmd->device->id, cmd->device->lun);
@@ -2349,12 +2352,12 @@ static void NCR5380_information_transfer
 			printk("\n");
 		    } else if (tmp != EXTENDED_MESSAGE)
 			printk(KERN_DEBUG "scsi%d: rejecting unknown "
-			       "message %02x from target %d, lun %d\n",
+			       "message %02x from target %d, lun %llu\n",
 			       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
 		    else
 			printk(KERN_DEBUG "scsi%d: rejecting unknown "
 			       "extended message "
-			       "code %02x, length %d from target %d, lun %d\n",
+			       "code %02x, length %d from target %d, lun %llu\n",
 			       HOSTNO, extended_msg[1], extended_msg[0],
 			       cmd->device->id, cmd->device->lun);
    
@@ -2576,7 +2579,7 @@ static void NCR5380_reselect (struct Scs
 #endif
     
     hostdata->connected = tmp;
-    dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+    dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
 	       HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sym53c8xx_2/sym_glue.c linux-libre-3.17-rc7-gnu/drivers/scsi/sym53c8xx_2/sym_glue.c
--- linux-libre-3.16-gnu/drivers/scsi/sym53c8xx_2/sym_glue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sym53c8xx_2/sym_glue.c	2014-09-28 17:29:07.000000000 -0400
@@ -851,7 +851,7 @@ static void sym53c8xx_slave_destroy(stru
 		 * so let's try to stop all on-going I/O.
 		 */
 		starget_printk(KERN_WARNING, tp->starget,
-			       "Removing busy LCB (%d)\n", sdev->lun);
+			       "Removing busy LCB (%d)\n", (u8)sdev->lun);
 		sym_reset_scsi_bus(np, 1);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.h linux-libre-3.17-rc7-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.h
--- linux-libre-3.16-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.h	2014-09-28 17:29:07.000000000 -0400
@@ -581,7 +581,7 @@ struct sym_pmc {
 #define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL
 #else
 #define sym_lp(tp, lun) \
-	(!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL
+	(!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[((u8)lun)] : NULL
 #endif
 
 /*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/tmscsim.c linux-libre-3.17-rc7-gnu/drivers/scsi/tmscsim.c
--- linux-libre-3.16-gnu/drivers/scsi/tmscsim.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/tmscsim.c	2014-09-28 17:29:07.000000000 -0400
@@ -621,7 +621,7 @@ dc390_StartSCSI( struct dc390_acb* pACB,
     {
 	dc390_freetag (pDCB, pSRB);
 	DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n",
-		scmd->device->id, scmd->device->lun));
+		       scmd->device->id, (u8)scmd->device->lun));
 	pSRB->SRBState = SRB_READY;
 	//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 	pACB->SelLost++;
@@ -1726,7 +1726,7 @@ dc390_SRBdone( struct dc390_acb* pACB, s
 	    } else {
 		SET_RES_DRV(pcmd->result, DRIVER_SENSE);
 		//pSRB->ScsiCmdLen	 = (u8) (pSRB->Segment1[0] >> 8);
-		DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+		DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
 		pSRB->TotalXferredLen = 0;
 		SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
 	    }
@@ -1746,7 +1746,7 @@ dc390_SRBdone( struct dc390_acb* pACB, s
 	else if (status == SAM_STAT_TASK_SET_FULL)
 	{
 	    scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-	    DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+	    DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
 	    pSRB->TotalXferredLen = 0;
 	    SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/u14-34f.c linux-libre-3.17-rc7-gnu/drivers/scsi/u14-34f.c
--- linux-libre-3.16-gnu/drivers/scsi/u14-34f.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/u14-34f.c	2014-09-28 17:29:07.000000000 -0400
@@ -1006,7 +1006,7 @@ static int port_detect \
           sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
-      printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
+      printk("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n",
              BN(j), sh[j]->max_id, sh[j]->max_lun);
 
    for (i = 0; i <= sh[j]->max_channel; i++)
@@ -1285,14 +1285,14 @@ static int u14_34f_queuecommand_lck(stru
    cpp->cpp_index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
 
-   if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d.\n",
+   if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%u.\n",
                         BN(j), i, SCpnt->device->channel, SCpnt->device->id,
-                        SCpnt->device->lun);
+                        (u8)SCpnt->device->lun);
 
    cpp->opcode = OP_SCSI;
    cpp->channel = SCpnt->device->channel;
    cpp->target = SCpnt->device->id;
-   cpp->lun = SCpnt->device->lun;
+   cpp->lun = (u8)SCpnt->device->lun;
    cpp->SCpnt = SCpnt;
    cpp->cdb_len = SCpnt->cmd_len;
    memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
@@ -1663,10 +1663,10 @@ static int reorder(unsigned int j, unsig
    if (link_statistics && (overlap || !(flushcount % link_statistics)))
       for (n = 0; n < n_ready; n++) {
          k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
-         printk("%s %d.%d:%d mb %d fc %d nr %d sec %ld ns %u"\
+         printk("%s %d.%d:%llu mb %d fc %d nr %d sec %ld ns %u"\
                 " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
-                SCpnt->lun, k, flushcount, n_ready,
+                (u8)SCpnt->lun, k, flushcount, n_ready,
                 blk_rq_pos(SCpnt->request), blk_rq_sectors(SCpnt->request),
 		cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->xdir);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ufs/ufs.h linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufs.h
--- linux-libre-3.16-gnu/drivers/scsi/ufs/ufs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufs.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,8 @@
 
 #define MAX_CDB_SIZE	16
 #define GENERAL_UPIU_REQUEST_SIZE 32
-#define QUERY_DESC_MAX_SIZE       256
+#define QUERY_DESC_MAX_SIZE       255
+#define QUERY_DESC_MIN_SIZE       2
 #define QUERY_OSF_SIZE            (GENERAL_UPIU_REQUEST_SIZE - \
 					(sizeof(struct utp_upiu_header)))
 
@@ -117,6 +118,41 @@ enum attr_idn {
 	QUERY_ATTR_IDN_EE_STATUS	= 0x0E,
 };
 
+/* Descriptor idn for Query requests */
+enum desc_idn {
+	QUERY_DESC_IDN_DEVICE		= 0x0,
+	QUERY_DESC_IDN_CONFIGURAION	= 0x1,
+	QUERY_DESC_IDN_UNIT		= 0x2,
+	QUERY_DESC_IDN_RFU_0		= 0x3,
+	QUERY_DESC_IDN_INTERCONNECT	= 0x4,
+	QUERY_DESC_IDN_STRING		= 0x5,
+	QUERY_DESC_IDN_RFU_1		= 0x6,
+	QUERY_DESC_IDN_GEOMETRY		= 0x7,
+	QUERY_DESC_IDN_POWER		= 0x8,
+	QUERY_DESC_IDN_RFU_2		= 0x9,
+};
+
+#define UNIT_DESC_MAX_SIZE       0x22
+/* Unit descriptor parameters offsets in bytes*/
+enum unit_desc_param {
+	UNIT_DESC_PARAM_LEN			= 0x0,
+	UNIT_DESC_PARAM_TYPE			= 0x1,
+	UNIT_DESC_PARAM_UNIT_INDEX		= 0x2,
+	UNIT_DESC_PARAM_LU_ENABLE		= 0x3,
+	UNIT_DESC_PARAM_BOOT_LUN_ID		= 0x4,
+	UNIT_DESC_PARAM_LU_WR_PROTECT		= 0x5,
+	UNIT_DESC_PARAM_LU_Q_DEPTH		= 0x6,
+	UNIT_DESC_PARAM_MEM_TYPE		= 0x8,
+	UNIT_DESC_PARAM_DATA_RELIABILITY	= 0x9,
+	UNIT_DESC_PARAM_LOGICAL_BLK_SIZE	= 0xA,
+	UNIT_DESC_PARAM_LOGICAL_BLK_COUNT	= 0xB,
+	UNIT_DESC_PARAM_ERASE_BLK_SIZE		= 0x13,
+	UNIT_DESC_PARAM_PROVISIONING_TYPE	= 0x17,
+	UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT	= 0x18,
+	UNIT_DESC_PARAM_CTX_CAPABILITIES	= 0x20,
+	UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1	= 0x22,
+};
+
 /* Exception event mask values */
 enum {
 	MASK_EE_STATUS		= 0xFFFF,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ufs/ufshcd.c linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshcd.c
--- linux-libre-3.16-gnu/drivers/scsi/ufs/ufshcd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshcd.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,6 +110,8 @@ static void ufshcd_tmc_handler(struct uf
 static void ufshcd_async_scan(void *data, async_cookie_t cookie);
 static int ufshcd_reset_and_restore(struct ufs_hba *hba);
 static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
+static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
+					struct scsi_device *sdev);
 
 /*
  * ufshcd_wait_for_register - wait for register value to change
@@ -446,30 +448,35 @@ static inline void ufshcd_copy_sense_dat
  * @lrb - pointer to local reference block
  */
 static
-void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 {
 	struct ufs_query_res *query_res = &hba->dev_cmd.query.response;
 
-	/* Get the UPIU response */
-	query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >>
-			UPIU_RSP_CODE_OFFSET;
-
 	memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr, QUERY_OSF_SIZE);
 
-
 	/* Get the descriptor */
 	if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) {
-		u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr +
+		u8 *descp = (u8 *)lrbp->ucd_rsp_ptr +
 				GENERAL_UPIU_REQUEST_SIZE;
-		u16 len;
+		u16 resp_len;
+		u16 buf_len;
 
 		/* data segment length */
-		len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
+		resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
 						MASK_QUERY_DATA_SEG_LEN;
-
-		memcpy(hba->dev_cmd.query.descriptor, descp,
-				min_t(u16, len, QUERY_DESC_MAX_SIZE));
+		buf_len = be16_to_cpu(
+				hba->dev_cmd.query.request.upiu_req.length);
+		if (likely(buf_len >= resp_len)) {
+			memcpy(hba->dev_cmd.query.descriptor, descp, resp_len);
+		} else {
+			dev_warn(hba->dev,
+				"%s: Response size is bigger than buffer",
+				__func__);
+			return -EINVAL;
+		}
 	}
+
+	return 0;
 }
 
 /**
@@ -797,11 +804,9 @@ static void ufshcd_prepare_utp_query_req
 			QUERY_OSF_SIZE);
 
 	/* Copy the Descriptor */
-	if ((len > 0) && (query->request.upiu_req.opcode ==
-					UPIU_QUERY_OPCODE_WRITE_DESC)) {
-		memcpy(descp, query->descriptor,
-				min_t(u16, len, QUERY_DESC_MAX_SIZE));
-	}
+	if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
+		memcpy(descp, query->descriptor, len);
+
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
@@ -980,6 +985,17 @@ ufshcd_clear_cmd(struct ufs_hba *hba, in
 	return err;
 }
 
+static int
+ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+	struct ufs_query_res *query_res = &hba->dev_cmd.query.response;
+
+	/* Get the UPIU response */
+	query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >>
+				UPIU_RSP_CODE_OFFSET;
+	return query_res->response;
+}
+
 /**
  * ufshcd_dev_cmd_completion() - handles device management command responses
  * @hba: per adapter instance
@@ -1002,7 +1018,9 @@ ufshcd_dev_cmd_completion(struct ufs_hba
 		}
 		break;
 	case UPIU_TRANSACTION_QUERY_RSP:
-		ufshcd_copy_query_response(hba, lrbp);
+		err = ufshcd_check_query_response(hba, lrbp);
+		if (!err)
+			err = ufshcd_copy_query_response(hba, lrbp);
 		break;
 	case UPIU_TRANSACTION_REJECT_UPIU:
 		/* TODO: handle Reject UPIU Response */
@@ -1134,6 +1152,30 @@ out_put_tag:
 }
 
 /**
+ * ufshcd_init_query() - init the query response and request parameters
+ * @hba: per-adapter instance
+ * @request: address of the request pointer to be initialized
+ * @response: address of the response pointer to be initialized
+ * @opcode: operation to perform
+ * @idn: flag idn to access
+ * @index: LU number to access
+ * @selector: query/flag/descriptor further identification
+ */
+static inline void ufshcd_init_query(struct ufs_hba *hba,
+		struct ufs_query_req **request, struct ufs_query_res **response,
+		enum query_opcode opcode, u8 idn, u8 index, u8 selector)
+{
+	*request = &hba->dev_cmd.query.request;
+	*response = &hba->dev_cmd.query.response;
+	memset(*request, 0, sizeof(struct ufs_query_req));
+	memset(*response, 0, sizeof(struct ufs_query_res));
+	(*request)->upiu_req.opcode = opcode;
+	(*request)->upiu_req.idn = idn;
+	(*request)->upiu_req.index = index;
+	(*request)->upiu_req.selector = selector;
+}
+
+/**
  * ufshcd_query_flag() - API function for sending flag query requests
  * hba: per-adapter instance
  * query_opcode: flag query to perform
@@ -1145,17 +1187,15 @@ out_put_tag:
 static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
 			enum flag_idn idn, bool *flag_res)
 {
-	struct ufs_query_req *request;
-	struct ufs_query_res *response;
-	int err;
+	struct ufs_query_req *request = NULL;
+	struct ufs_query_res *response = NULL;
+	int err, index = 0, selector = 0;
 
 	BUG_ON(!hba);
 
 	mutex_lock(&hba->dev_cmd.lock);
-	request = &hba->dev_cmd.query.request;
-	response = &hba->dev_cmd.query.response;
-	memset(request, 0, sizeof(struct ufs_query_req));
-	memset(response, 0, sizeof(struct ufs_query_res));
+	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+			selector);
 
 	switch (opcode) {
 	case UPIU_QUERY_OPCODE_SET_FLAG:
@@ -1180,12 +1220,8 @@ static int ufshcd_query_flag(struct ufs_
 		err = -EINVAL;
 		goto out_unlock;
 	}
-	request->upiu_req.opcode = opcode;
-	request->upiu_req.idn = idn;
 
-	/* Send query request */
-	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
-			QUERY_REQ_TIMEOUT);
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
 
 	if (err) {
 		dev_err(hba->dev,
@@ -1217,8 +1253,8 @@ out_unlock:
 static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
 			enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
 {
-	struct ufs_query_req *request;
-	struct ufs_query_res *response;
+	struct ufs_query_req *request = NULL;
+	struct ufs_query_res *response = NULL;
 	int err;
 
 	BUG_ON(!hba);
@@ -1231,10 +1267,8 @@ static int ufshcd_query_attr(struct ufs_
 	}
 
 	mutex_lock(&hba->dev_cmd.lock);
-	request = &hba->dev_cmd.query.request;
-	response = &hba->dev_cmd.query.response;
-	memset(request, 0, sizeof(struct ufs_query_req));
-	memset(response, 0, sizeof(struct ufs_query_res));
+	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+			selector);
 
 	switch (opcode) {
 	case UPIU_QUERY_OPCODE_WRITE_ATTR:
@@ -1251,14 +1285,7 @@ static int ufshcd_query_attr(struct ufs_
 		goto out_unlock;
 	}
 
-	request->upiu_req.opcode = opcode;
-	request->upiu_req.idn = idn;
-	request->upiu_req.index = index;
-	request->upiu_req.selector = selector;
-
-	/* Send query request */
-	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
-						QUERY_REQ_TIMEOUT);
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
 
 	if (err) {
 		dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
@@ -1275,6 +1302,82 @@ out:
 }
 
 /**
+ * ufshcd_query_descriptor - API function for sending descriptor requests
+ * hba: per-adapter instance
+ * opcode: attribute opcode
+ * idn: attribute idn to access
+ * index: index field
+ * selector: selector field
+ * desc_buf: the buffer that contains the descriptor
+ * buf_len: length parameter passed to the device
+ *
+ * Returns 0 for success, non-zero in case of failure.
+ * The buf_len parameter will contain, on return, the length parameter
+ * received on the response.
+ */
+static int ufshcd_query_descriptor(struct ufs_hba *hba,
+			enum query_opcode opcode, enum desc_idn idn, u8 index,
+			u8 selector, u8 *desc_buf, int *buf_len)
+{
+	struct ufs_query_req *request = NULL;
+	struct ufs_query_res *response = NULL;
+	int err;
+
+	BUG_ON(!hba);
+
+	if (!desc_buf) {
+		dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n",
+				__func__, opcode);
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) {
+		dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n",
+				__func__, *buf_len);
+		err = -EINVAL;
+		goto out;
+	}
+
+	mutex_lock(&hba->dev_cmd.lock);
+	ufshcd_init_query(hba, &request, &response, opcode, idn, index,
+			selector);
+	hba->dev_cmd.query.descriptor = desc_buf;
+	request->upiu_req.length = cpu_to_be16(*buf_len);
+
+	switch (opcode) {
+	case UPIU_QUERY_OPCODE_WRITE_DESC:
+		request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
+		break;
+	case UPIU_QUERY_OPCODE_READ_DESC:
+		request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
+		break;
+	default:
+		dev_err(hba->dev,
+				"%s: Expected query descriptor opcode but got = 0x%.2x\n",
+				__func__, opcode);
+		err = -EINVAL;
+		goto out_unlock;
+	}
+
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+	if (err) {
+		dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
+				__func__, opcode, idn, err);
+		goto out_unlock;
+	}
+
+	hba->dev_cmd.query.descriptor = NULL;
+	*buf_len = be16_to_cpu(response->upiu_res.length);
+
+out_unlock:
+	mutex_unlock(&hba->dev_cmd.lock);
+out:
+	return err;
+}
+
+/**
  * ufshcd_memory_alloc - allocate memory for host memory space data structures
  * @hba: per adapter instance
  *
@@ -1878,6 +1981,7 @@ static int ufshcd_verify_dev_init(struct
 static int ufshcd_slave_alloc(struct scsi_device *sdev)
 {
 	struct ufs_hba *hba;
+	int lun_qdepth;
 
 	hba = shost_priv(sdev->host);
 	sdev->tagged_supported = 1;
@@ -1889,14 +1993,68 @@ static int ufshcd_slave_alloc(struct scs
 	/* allow SCSI layer to restart the device in case of errors */
 	sdev->allow_restart = 1;
 
-	/*
-	 * Inform SCSI Midlayer that the LUN queue depth is same as the
-	 * controller queue depth. If a LUN queue depth is less than the
-	 * controller queue depth and if the LUN reports
-	 * SAM_STAT_TASK_SET_FULL, the LUN queue depth will be adjusted
-	 * with scsi_adjust_queue_depth.
-	 */
-	scsi_activate_tcq(sdev, hba->nutrs);
+	/* REPORT SUPPORTED OPERATION CODES is not supported */
+	sdev->no_report_opcodes = 1;
+
+	lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev);
+	if (lun_qdepth <= 0)
+		/* eventually, we can figure out the real queue depth */
+		lun_qdepth = hba->nutrs;
+	else
+		lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
+
+	dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
+			__func__, lun_qdepth);
+	scsi_activate_tcq(sdev, lun_qdepth);
+
+	return 0;
+}
+
+/**
+ * ufshcd_change_queue_depth - change queue depth
+ * @sdev: pointer to SCSI device
+ * @depth: required depth to set
+ * @reason: reason for changing the depth
+ *
+ * Change queue depth according to the reason and make sure
+ * the max. limits are not crossed.
+ */
+static int ufshcd_change_queue_depth(struct scsi_device *sdev,
+		int depth, int reason)
+{
+	struct ufs_hba *hba = shost_priv(sdev->host);
+
+	if (depth > hba->nutrs)
+		depth = hba->nutrs;
+
+	switch (reason) {
+	case SCSI_QDEPTH_DEFAULT:
+	case SCSI_QDEPTH_RAMP_UP:
+		if (!sdev->tagged_supported)
+			depth = 1;
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+		break;
+	case SCSI_QDEPTH_QFULL:
+		scsi_track_queue_full(sdev, depth);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return depth;
+}
+
+/**
+ * ufshcd_slave_configure - adjust SCSI device configurations
+ * @sdev: pointer to SCSI device
+ */
+static int ufshcd_slave_configure(struct scsi_device *sdev)
+{
+	struct request_queue *q = sdev->request_queue;
+
+	blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
+	blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX);
+
 	return 0;
 }
 
@@ -1953,42 +2111,6 @@ static int ufshcd_task_req_compl(struct
 }
 
 /**
- * ufshcd_adjust_lun_qdepth - Update LUN queue depth if device responds with
- *			      SAM_STAT_TASK_SET_FULL SCSI command status.
- * @cmd: pointer to SCSI command
- */
-static void ufshcd_adjust_lun_qdepth(struct scsi_cmnd *cmd)
-{
-	struct ufs_hba *hba;
-	int i;
-	int lun_qdepth = 0;
-
-	hba = shost_priv(cmd->device->host);
-
-	/*
-	 * LUN queue depth can be obtained by counting outstanding commands
-	 * on the LUN.
-	 */
-	for (i = 0; i < hba->nutrs; i++) {
-		if (test_bit(i, &hba->outstanding_reqs)) {
-
-			/*
-			 * Check if the outstanding command belongs
-			 * to the LUN which reported SAM_STAT_TASK_SET_FULL.
-			 */
-			if (cmd->device->lun == hba->lrb[i].lun)
-				lun_qdepth++;
-		}
-	}
-
-	/*
-	 * LUN queue depth will be total outstanding commands, except the
-	 * command for which the LUN reported SAM_STAT_TASK_SET_FULL.
-	 */
-	scsi_adjust_queue_depth(cmd->device, MSG_SIMPLE_TAG, lun_qdepth - 1);
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrb: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -2009,12 +2131,6 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb
 			  scsi_status;
 		break;
 	case SAM_STAT_TASK_SET_FULL:
-		/*
-		 * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue
-		 * depth needs to be adjusted to the exact number of
-		 * outstanding commands the LUN can handle at any given time.
-		 */
-		ufshcd_adjust_lun_qdepth(lrbp->cmd);
 	case SAM_STAT_BUSY:
 	case SAM_STAT_TASK_ABORTED:
 		ufshcd_copy_sense_data(lrbp);
@@ -2134,47 +2250,42 @@ static void ufshcd_transfer_req_compl(st
 	u32 tr_doorbell;
 	int result;
 	int index;
-	bool int_aggr_reset = false;
+
+	/* Resetting interrupt aggregation counters first and reading the
+	 * DOOR_BELL afterward allows us to handle all the completed requests.
+	 * In order to prevent other interrupts starvation the DB is read once
+	 * after reset. The down side of this solution is the possibility of
+	 * false interrupt if device completes another request after resetting
+	 * aggregation and before reading the DB.
+	 */
+	ufshcd_reset_intr_aggr(hba);
 
 	tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
 
-	for (index = 0; index < hba->nutrs; index++) {
-		if (test_bit(index, &completed_reqs)) {
-			lrbp = &hba->lrb[index];
-			cmd = lrbp->cmd;
-			/*
-			 * Don't skip resetting interrupt aggregation counters
-			 * if a regular command is present.
-			 */
-			int_aggr_reset |= !lrbp->intr_cmd;
-
-			if (cmd) {
-				result = ufshcd_transfer_rsp_status(hba, lrbp);
-				scsi_dma_unmap(cmd);
-				cmd->result = result;
-				/* Mark completed command as NULL in LRB */
-				lrbp->cmd = NULL;
-				clear_bit_unlock(index, &hba->lrb_in_use);
-				/* Do not touch lrbp after scsi done */
-				cmd->scsi_done(cmd);
-			} else if (lrbp->command_type ==
-					UTP_CMD_TYPE_DEV_MANAGE) {
-				if (hba->dev_cmd.complete)
-					complete(hba->dev_cmd.complete);
-			}
-		} /* end of if */
-	} /* end of for */
+	for_each_set_bit(index, &completed_reqs, hba->nutrs) {
+		lrbp = &hba->lrb[index];
+		cmd = lrbp->cmd;
+		if (cmd) {
+			result = ufshcd_transfer_rsp_status(hba, lrbp);
+			scsi_dma_unmap(cmd);
+			cmd->result = result;
+			/* Mark completed command as NULL in LRB */
+			lrbp->cmd = NULL;
+			clear_bit_unlock(index, &hba->lrb_in_use);
+			/* Do not touch lrbp after scsi done */
+			cmd->scsi_done(cmd);
+		} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
+			if (hba->dev_cmd.complete)
+				complete(hba->dev_cmd.complete);
+		}
+	}
 
 	/* clear corresponding bits of completed commands */
 	hba->outstanding_reqs ^= completed_reqs;
 
 	/* we might have free'd some tags above */
 	wake_up(&hba->dev_cmd.tag_wq);
-
-	/* Reset interrupt aggregation counters */
-	if (int_aggr_reset)
-		ufshcd_reset_intr_aggr(hba);
 }
 
 /**
@@ -2779,6 +2890,7 @@ static int ufshcd_abort(struct scsi_cmnd
 	int poll_cnt;
 	u8 resp = 0xF;
 	struct ufshcd_lrb *lrbp;
+	u32 reg;
 
 	host = cmd->device->host;
 	hba = shost_priv(host);
@@ -2788,6 +2900,13 @@ static int ufshcd_abort(struct scsi_cmnd
 	if (!(test_bit(tag, &hba->outstanding_reqs)))
 		goto out;
 
+	reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+	if (!(reg & (1 << tag))) {
+		dev_err(hba->dev,
+		"%s: cmd was completed, but without a notifying intr, tag = %d",
+		__func__, tag);
+	}
+
 	lrbp = &hba->lrb[tag];
 	for (poll_cnt = 100; poll_cnt; poll_cnt--) {
 		err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
@@ -2796,8 +2915,6 @@ static int ufshcd_abort(struct scsi_cmnd
 			/* cmd pending in the device */
 			break;
 		} else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
-			u32 reg;
-
 			/*
 			 * cmd not pending in the device, check if it is
 			 * in transition.
@@ -2971,6 +3088,38 @@ static int ufshcd_eh_host_reset_handler(
 }
 
 /**
+ * ufshcd_read_sdev_qdepth - read the lun command queue depth
+ * @hba: Pointer to adapter instance
+ * @sdev: pointer to SCSI device
+ *
+ * Return in case of success the lun's queue depth else error.
+ */
+static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
+				struct scsi_device *sdev)
+{
+	int ret;
+	int buff_len = UNIT_DESC_MAX_SIZE;
+	u8 desc_buf[UNIT_DESC_MAX_SIZE];
+
+	ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
+			QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len);
+
+	if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) {
+		dev_err(hba->dev,
+			"%s:Failed reading unit descriptor. len = %d ret = %d"
+			, __func__, buff_len, ret);
+		if (!ret)
+			ret = -EINVAL;
+
+		goto out;
+	}
+
+	ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF;
+out:
+	return ret;
+}
+
+/**
  * ufshcd_async_scan - asynchronous execution for link startup
  * @data: data pointer to pass to this function
  * @cookie: cookie data
@@ -3012,7 +3161,9 @@ static struct scsi_host_template ufshcd_
 	.proc_name		= UFSHCD,
 	.queuecommand		= ufshcd_queuecommand,
 	.slave_alloc		= ufshcd_slave_alloc,
+	.slave_configure	= ufshcd_slave_configure,
 	.slave_destroy		= ufshcd_slave_destroy,
+	.change_queue_depth	= ufshcd_change_queue_depth,
 	.eh_abort_handler	= ufshcd_abort,
 	.eh_device_reset_handler = ufshcd_eh_device_reset_handler,
 	.eh_host_reset_handler   = ufshcd_eh_host_reset_handler,
@@ -3110,6 +3261,22 @@ void ufshcd_remove(struct ufs_hba *hba)
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
 /**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ *			 addressing capability
+ * @hba: per adapter instance
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct ufs_hba *hba)
+{
+	if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) {
+		if (!dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(64)))
+			return 0;
+	}
+	return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32));
+}
+
+/**
  * ufshcd_init - Driver initialization routine
  * @dev: pointer to device handle
  * @hba_handle: driver private handle
@@ -3160,6 +3327,12 @@ int ufshcd_init(struct device *dev, stru
 	/* Get Interrupt bit mask per version */
 	hba->intr_mask = ufshcd_get_intr_mask(hba);
 
+	err = ufshcd_set_dma_mask(hba);
+	if (err) {
+		dev_err(hba->dev, "set dma mask failed\n");
+		goto out_disable;
+	}
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ufs/ufshcd-pci.c linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshcd-pci.c
--- linux-libre-3.16-gnu/drivers/scsi/ufs/ufshcd-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshcd-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -135,26 +135,6 @@ static void ufshcd_pci_remove(struct pci
 }
 
 /**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- *			 addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct pci_dev *pdev)
-{
-	int err;
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
-		&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
-		return 0;
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	return err;
-}
-
-/**
  * ufshcd_pci_probe - probe routine of the driver
  * @pdev: pointer to PCI device handle
  * @id: PCI device id
@@ -184,12 +164,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, c
 
 	mmio_base = pcim_iomap_table(pdev)[0];
 
-	err = ufshcd_set_dma_mask(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "set dma mask failed\n");
-		return err;
-	}
-
 	err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
 	if (err) {
 		dev_err(&pdev->dev, "Initialization failed\n");
@@ -211,7 +185,7 @@ static const struct dev_pm_ops ufshcd_pc
 	.runtime_idle    = ufshcd_pci_runtime_idle,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
+static const struct pci_device_id ufshcd_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ }	/* terminate list */
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/ufs/ufshci.h linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshci.h
--- linux-libre-3.16-gnu/drivers/scsi/ufs/ufshci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/ufs/ufshci.h	2014-09-28 17:29:07.000000000 -0400
@@ -296,6 +296,11 @@ enum {
 	MASK_OCS			= 0x0F,
 };
 
+/* The maximum length of the data byte count field in the PRDT is 256KB */
+#define PRDT_DATA_BYTE_COUNT_MAX	(256 * 1024)
+/* The granularity of the data byte count field in the PRDT is 32-bit */
+#define PRDT_DATA_BYTE_COUNT_PAD	4
+
 /**
  * struct ufshcd_sg_entry - UFSHCI PRD Entry
  * @base_addr: Lower 32bit physical address DW-0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/virtio_scsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/virtio_scsi.c
--- linux-libre-3.16-gnu/drivers/scsi/virtio_scsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/virtio_scsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,6 +27,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_tcq.h>
+#include <linux/seqlock.h>
 
 #define VIRTIO_SCSI_MEMPOOL_SZ 64
 #define VIRTIO_SCSI_EVENT_LEN 8
@@ -75,18 +77,16 @@ struct virtio_scsi_vq {
  * queue, and also lets the driver optimize the IRQ affinity for the virtqueues
  * (each virtqueue's affinity is set to the CPU that "owns" the queue).
  *
- * tgt_lock is held to serialize reading and writing req_vq. Reading req_vq
- * could be done locklessly, but we do not do it yet.
+ * tgt_seq is held to serialize reading and writing req_vq.
  *
  * Decrements of reqs are never concurrent with writes of req_vq: before the
  * decrement reqs will be != 0; after the decrement the virtqueue completion
  * routine will not use the req_vq so it can be changed by a new request.
- * Thus they can happen outside the tgt_lock, provided of course we make reqs
+ * Thus they can happen outside the tgt_seq, provided of course we make reqs
  * an atomic_t.
  */
 struct virtio_scsi_target_state {
-	/* This spinlock never held at the same time as vq_lock. */
-	spinlock_t tgt_lock;
+	seqcount_t tgt_seq;
 
 	/* Count of outstanding requests. */
 	atomic_t reqs;
@@ -559,19 +559,33 @@ static struct virtio_scsi_vq *virtscsi_p
 	unsigned long flags;
 	u32 queue_num;
 
-	spin_lock_irqsave(&tgt->tgt_lock, flags);
+	local_irq_save(flags);
+	if (atomic_inc_return(&tgt->reqs) > 1) {
+		unsigned long seq;
+
+		do {
+			seq = read_seqcount_begin(&tgt->tgt_seq);
+			vq = tgt->req_vq;
+		} while (read_seqcount_retry(&tgt->tgt_seq, seq));
+	} else {
+		/* no writes can be concurrent because of atomic_t */
+		write_seqcount_begin(&tgt->tgt_seq);
+
+		/* keep previous req_vq if a reader just arrived */
+		if (unlikely(atomic_read(&tgt->reqs) > 1)) {
+			vq = tgt->req_vq;
+			goto unlock;
+		}
 
-	if (atomic_inc_return(&tgt->reqs) > 1)
-		vq = tgt->req_vq;
-	else {
 		queue_num = smp_processor_id();
 		while (unlikely(queue_num >= vscsi->num_queues))
 			queue_num -= vscsi->num_queues;
-
 		tgt->req_vq = vq = &vscsi->req_vqs[queue_num];
+ unlock:
+		write_seqcount_end(&tgt->tgt_seq);
 	}
+	local_irq_restore(flags);
 
-	spin_unlock_irqrestore(&tgt->tgt_lock, flags);
 	return vq;
 }
 
@@ -641,6 +655,36 @@ static int virtscsi_device_reset(struct
 	return virtscsi_tmf(vscsi, cmd);
 }
 
+/**
+ * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth
+ * @sdev:	Virtscsi target whose queue depth to change
+ * @qdepth:	New queue depth
+ * @reason:	Reason for the queue depth change.
+ */
+static int virtscsi_change_queue_depth(struct scsi_device *sdev,
+				       int qdepth,
+				       int reason)
+{
+	struct Scsi_Host *shost = sdev->host;
+	int max_depth = shost->cmd_per_lun;
+
+	switch (reason) {
+	case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */
+		scsi_track_queue_full(sdev, qdepth);
+		break;
+	case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */
+	case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */
+		scsi_adjust_queue_depth(sdev,
+					scsi_get_tag_type(sdev),
+					min(max_depth, qdepth));
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return sdev->queue_depth;
+}
+
 static int virtscsi_abort(struct scsi_cmnd *sc)
 {
 	struct virtio_scsi *vscsi = shost_priv(sc->device->host);
@@ -667,14 +711,17 @@ static int virtscsi_abort(struct scsi_cm
 
 static int virtscsi_target_alloc(struct scsi_target *starget)
 {
+	struct Scsi_Host *sh = dev_to_shost(starget->dev.parent);
+	struct virtio_scsi *vscsi = shost_priv(sh);
+
 	struct virtio_scsi_target_state *tgt =
 				kmalloc(sizeof(*tgt), GFP_KERNEL);
 	if (!tgt)
 		return -ENOMEM;
 
-	spin_lock_init(&tgt->tgt_lock);
+	seqcount_init(&tgt->tgt_seq);
 	atomic_set(&tgt->reqs, 0);
-	tgt->req_vq = NULL;
+	tgt->req_vq = &vscsi->req_vqs[0];
 
 	starget->hostdata = tgt;
 	return 0;
@@ -693,6 +740,7 @@ static struct scsi_host_template virtscs
 	.this_id = -1,
 	.cmd_size = sizeof(struct virtio_scsi_cmd),
 	.queuecommand = virtscsi_queuecommand_single,
+	.change_queue_depth = virtscsi_change_queue_depth,
 	.eh_abort_handler = virtscsi_abort,
 	.eh_device_reset_handler = virtscsi_device_reset,
 
@@ -710,6 +758,7 @@ static struct scsi_host_template virtscs
 	.this_id = -1,
 	.cmd_size = sizeof(struct virtio_scsi_cmd),
 	.queuecommand = virtscsi_queuecommand_multi,
+	.change_queue_depth = virtscsi_change_queue_depth,
 	.eh_abort_handler = virtscsi_abort,
 	.eh_device_reset_handler = virtscsi_device_reset,
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/vmw_pvscsi.c linux-libre-3.17-rc7-gnu/drivers/scsi/vmw_pvscsi.c
--- linux-libre-3.16-gnu/drivers/scsi/vmw_pvscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/vmw_pvscsi.c	2014-09-28 17:29:07.000000000 -0400
@@ -1194,7 +1194,7 @@ static int pvscsi_setup_msix(const struc
 	struct msix_entry entry = { 0, PVSCSI_VECTOR_COMPLETION };
 	int ret;
 
-	ret = pci_enable_msix(adapter->dev, &entry, 1);
+	ret = pci_enable_msix_exact(adapter->dev, &entry, 1);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/scsi/wd33c93.c linux-libre-3.17-rc7-gnu/drivers/scsi/wd33c93.c
--- linux-libre-3.16-gnu/drivers/scsi/wd33c93.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/scsi/wd33c93.c	2014-09-28 17:29:07.000000000 -0400
@@ -502,7 +502,8 @@ wd33c93_execute(struct Scsi_Host *instan
 	cmd = (struct scsi_cmnd *) hostdata->input_Q;
 	prev = NULL;
 	while (cmd) {
-		if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)))
+		if (!(hostdata->busy[cmd->device->id] &
+		      (1 << (cmd->device->lun & 0xff))))
 			break;
 		prev = cmd;
 		cmd = (struct scsi_cmnd *) cmd->host_scribble;
@@ -593,10 +594,10 @@ wd33c93_execute(struct Scsi_Host *instan
 
 	write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0));
 
-	write_wd33c93(regs, WD_TARGET_LUN, cmd->device->lun);
+	write_wd33c93(regs, WD_TARGET_LUN, (u8)cmd->device->lun);
 	write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
 		      hostdata->sync_xfer[cmd->device->id]);
-	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+	hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
 
 	if ((hostdata->level2 == L2_NONE) ||
 	    (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) {
@@ -862,7 +863,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 		}
 
 		cmd->result = DID_NO_CONNECT << 16;
-		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+		hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 		hostdata->state = S_UNCONNECTED;
 		cmd->scsi_done(cmd);
 
@@ -895,7 +896,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 
 		/* construct an IDENTIFY message with correct disconnect bit */
 
-		hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun);
+		hostdata->outgoing_msg[0] = IDENTIFY(0, cmd->device->lun);
 		if (cmd->SCp.phase)
 			hostdata->outgoing_msg[0] |= 0x40;
 
@@ -1179,7 +1180,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 			lun = read_wd33c93(regs, WD_TARGET_LUN);
 			DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
 			    hostdata->connected = NULL;
-			hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+			hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 			hostdata->state = S_UNCONNECTED;
 			if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)
 				cmd->SCp.Status = lun;
@@ -1268,7 +1269,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 		}
 		DB(DB_INTR, printk("UNEXP_DISC"))
 		    hostdata->connected = NULL;
-		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+		hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 		hostdata->state = S_UNCONNECTED;
 		if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
 			cmd->result =
@@ -1300,7 +1301,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 		switch (hostdata->state) {
 		case S_PRE_CMP_DISC:
 			hostdata->connected = NULL;
-			hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+			hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 			hostdata->state = S_UNCONNECTED;
 			DB(DB_INTR, printk(":%d", cmd->SCp.Status))
 			    if (cmd->cmnd[0] == REQUEST_SENSE
@@ -1353,7 +1354,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 			if (hostdata->selecting) {
 				cmd = (struct scsi_cmnd *) hostdata->selecting;
 				hostdata->selecting = NULL;
-				hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+				hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 				cmd->host_scribble =
 				    (uchar *) hostdata->input_Q;
 				hostdata->input_Q = cmd;
@@ -1365,7 +1366,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 			if (cmd) {
 				if (phs == 0x00) {
 					hostdata->busy[cmd->device->id] &=
-					    ~(1 << cmd->device->lun);
+						~(1 << (cmd->device->lun & 0xff));
 					cmd->host_scribble =
 					    (uchar *) hostdata->input_Q;
 					hostdata->input_Q = cmd;
@@ -1448,7 +1449,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 		cmd = (struct scsi_cmnd *) hostdata->disconnected_Q;
 		patch = NULL;
 		while (cmd) {
-			if (id == cmd->device->id && lun == cmd->device->lun)
+			if (id == cmd->device->id && lun == (u8)cmd->device->lun)
 				break;
 			patch = cmd;
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
@@ -1459,7 +1460,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 		if (!cmd) {
 			printk
 			    ("---TROUBLE: target %d.%d not in disconnect queue---",
-			     id, lun);
+			     id, (u8)lun);
 			spin_unlock_irqrestore(&hostdata->lock, flags);
 			return;
 		}
@@ -1705,7 +1706,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
 		sr = read_wd33c93(regs, WD_SCSI_STATUS);
 		printk("asr=%02x, sr=%02x.", asr, sr);
 
-		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+		hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
 		hostdata->connected = NULL;
 		hostdata->state = S_UNCONNECTED;
 		cmd->result = DID_ABORT << 16;
@@ -2169,7 +2170,7 @@ wd33c93_show_info(struct seq_file *m, st
 		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (struct scsi_cmnd *) hd->connected;
-			seq_printf(m, " %d:%d(%02x)",
+			seq_printf(m, " %d:%llu(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 		}
 	}
@@ -2177,7 +2178,7 @@ wd33c93_show_info(struct seq_file *m, st
 		seq_printf(m, "\ninput_Q:       ");
 		cmd = (struct scsi_cmnd *) hd->input_Q;
 		while (cmd) {
-			seq_printf(m, " %d:%d(%02x)",
+			seq_printf(m, " %d:%llu(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
@@ -2186,7 +2187,7 @@ wd33c93_show_info(struct seq_file *m, st
 		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (struct scsi_cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			seq_printf(m, " %d:%d(%02x)",
+			seq_printf(m, " %d:%llu(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/sh/intc/Kconfig linux-libre-3.17-rc7-gnu/drivers/sh/intc/Kconfig
--- linux-libre-3.16-gnu/drivers/sh/intc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/sh/intc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,9 @@
 config SH_INTC
-	def_bool y
+	bool
 	select IRQ_DOMAIN
 
+if SH_INTC
+
 comment "Interrupt controller options"
 
 config INTC_USERIMASK
@@ -37,3 +39,5 @@ config INTC_MAPPING_DEBUG
 	  between system IRQs and the per-controller id tables.
 
 	  If in doubt, say N.
+
+endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/sh/Makefile linux-libre-3.17-rc7-gnu/drivers/sh/Makefile
--- linux-libre-3.16-gnu/drivers/sh/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/sh/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,8 +1,7 @@
 #
 # Makefile for the SuperH specific drivers.
 #
-obj-$(CONFIG_SUPERH)			+= intc/
-obj-$(CONFIG_ARCH_SHMOBILE_LEGACY)	+= intc/
+obj-$(CONFIG_SH_INTC)			+= intc/
 ifneq ($(CONFIG_COMMON_CLK),y)
 obj-$(CONFIG_HAVE_CLK)			+= clk/
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/Makefile linux-libre-3.17-rc7-gnu/drivers/soc/Makefile
--- linux-libre-3.16-gnu/drivers/soc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/soc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
+obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/qcom/qcom_gsbi.c linux-libre-3.17-rc7-gnu/drivers/soc/qcom/qcom_gsbi.c
--- linux-libre-3.16-gnu/drivers/soc/qcom/qcom_gsbi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/soc/qcom/qcom_gsbi.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,44 +22,63 @@
 #define GSBI_CTRL_REG		0x0000
 #define GSBI_PROTOCOL_SHIFT	4
 
+struct gsbi_info {
+	struct clk *hclk;
+	u32 mode;
+	u32 crci;
+};
+
 static int gsbi_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct resource *res;
 	void __iomem *base;
-	struct clk *hclk;
-	u32 mode, crci = 0;
+	struct gsbi_info *gsbi;
+
+	gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
+
+	if (!gsbi)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	if (of_property_read_u32(node, "qcom,mode", &mode)) {
+	if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
 		dev_err(&pdev->dev, "missing mode configuration\n");
 		return -EINVAL;
 	}
 
 	/* not required, so default to 0 if not present */
-	of_property_read_u32(node, "qcom,crci", &crci);
-
-	dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n", mode, crci);
+	of_property_read_u32(node, "qcom,crci", &gsbi->crci);
 
-	hclk = devm_clk_get(&pdev->dev, "iface");
-	if (IS_ERR(hclk))
-		return PTR_ERR(hclk);
+	dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n",
+		 gsbi->mode, gsbi->crci);
+	gsbi->hclk = devm_clk_get(&pdev->dev, "iface");
+	if (IS_ERR(gsbi->hclk))
+		return PTR_ERR(gsbi->hclk);
 
-	clk_prepare_enable(hclk);
+	clk_prepare_enable(gsbi->hclk);
 
-	writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci,
+	writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
 				base + GSBI_CTRL_REG);
 
 	/* make sure the gsbi control write is not reordered */
 	wmb();
 
-	clk_disable_unprepare(hclk);
+	platform_set_drvdata(pdev, gsbi);
 
-	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	return of_platform_populate(node, NULL, NULL, &pdev->dev);
+}
+
+static int gsbi_remove(struct platform_device *pdev)
+{
+	struct gsbi_info *gsbi = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(gsbi->hclk);
+
+	return 0;
 }
 
 static const struct of_device_id gsbi_dt_match[] = {
@@ -76,6 +95,7 @@ static struct platform_driver gsbi_drive
 		.of_match_table	= gsbi_dt_match,
 	},
 	.probe = gsbi_probe,
+	.remove	= gsbi_remove,
 };
 
 module_platform_driver(gsbi_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/common.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/common.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/common.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of.h>
+
+#include <soc/tegra/common.h>
+
+static const struct of_device_id tegra_machine_match[] = {
+	{ .compatible = "nvidia,tegra20", },
+	{ .compatible = "nvidia,tegra30", },
+	{ .compatible = "nvidia,tegra114", },
+	{ .compatible = "nvidia,tegra124", },
+	{ }
+};
+
+bool soc_is_tegra(void)
+{
+	struct device_node *root;
+
+	root = of_find_node_by_path("/");
+	if (!root)
+		return false;
+
+	return of_match_node(tegra_machine_match, root) != NULL;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse.h linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse.h
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_MISC_TEGRA_FUSE_H
+#define __DRIVERS_MISC_TEGRA_FUSE_H
+
+#define TEGRA_FUSE_BASE	0x7000f800
+#define TEGRA_FUSE_SIZE	0x400
+
+int tegra_fuse_create_sysfs(struct device *dev, int size,
+		     u32 (*readl)(const unsigned int offset));
+
+bool tegra30_spare_fuse(int bit);
+u32 tegra30_fuse_readl(const unsigned int offset);
+void tegra30_init_fuse_early(void);
+void tegra_init_revision(void);
+void tegra_init_apbmisc(void);
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_init_speedo_data(struct tegra_sku_info *sku_info);
+bool tegra20_spare_fuse_early(int spare_bit);
+void tegra20_init_fuse_early(void);
+u32 tegra20_fuse_early(const unsigned int offset);
+#else
+static inline void tegra20_init_speedo_data(struct tegra_sku_info *sku_info) {}
+static inline bool tegra20_spare_fuse_early(int spare_bit)
+{
+	return false;
+}
+static inline void tegra20_init_fuse_early(void) {}
+static inline u32 tegra20_fuse_early(const unsigned int offset)
+{
+	return 0;
+}
+#endif
+
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+void tegra30_init_speedo_data(struct tegra_sku_info *sku_info);
+#else
+static inline void tegra30_init_speedo_data(struct tegra_sku_info *sku_info) {}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_init_speedo_data(struct tegra_sku_info *sku_info);
+#else
+static inline void tegra114_init_speedo_data(struct tegra_sku_info *sku_info) {}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+void tegra124_init_speedo_data(struct tegra_sku_info *sku_info);
+#else
+static inline void tegra124_init_speedo_data(struct tegra_sku_info *sku_info) {}
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra20.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra20.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra20.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra20.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on drivers/misc/eeprom/sunxi_sid.c
+ */
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define FUSE_BEGIN	0x100
+#define FUSE_SIZE	0x1f8
+#define FUSE_UID_LOW	0x08
+#define FUSE_UID_HIGH	0x0c
+
+static phys_addr_t fuse_phys;
+static struct clk *fuse_clk;
+static void __iomem __initdata *fuse_base;
+
+static DEFINE_MUTEX(apb_dma_lock);
+static DECLARE_COMPLETION(apb_dma_wait);
+static struct dma_chan *apb_dma_chan;
+static struct dma_slave_config dma_sconfig;
+static u32 *apb_buffer;
+static dma_addr_t apb_buffer_phys;
+
+static void apb_dma_complete(void *args)
+{
+	complete(&apb_dma_wait);
+}
+
+static u32 tegra20_fuse_readl(const unsigned int offset)
+{
+	int ret;
+	u32 val = 0;
+	struct dma_async_tx_descriptor *dma_desc;
+
+	mutex_lock(&apb_dma_lock);
+
+	dma_sconfig.src_addr = fuse_phys + FUSE_BEGIN + offset;
+	ret = dmaengine_slave_config(apb_dma_chan, &dma_sconfig);
+	if (ret)
+		goto out;
+
+	dma_desc = dmaengine_prep_slave_single(apb_dma_chan, apb_buffer_phys,
+			sizeof(u32), DMA_DEV_TO_MEM,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma_desc)
+		goto out;
+
+	dma_desc->callback = apb_dma_complete;
+	dma_desc->callback_param = NULL;
+
+	reinit_completion(&apb_dma_wait);
+
+	clk_prepare_enable(fuse_clk);
+
+	dmaengine_submit(dma_desc);
+	dma_async_issue_pending(apb_dma_chan);
+	ret = wait_for_completion_timeout(&apb_dma_wait, msecs_to_jiffies(50));
+
+	if (WARN(ret == 0, "apb read dma timed out"))
+		dmaengine_terminate_all(apb_dma_chan);
+	else
+		val = *apb_buffer;
+
+	clk_disable_unprepare(fuse_clk);
+out:
+	mutex_unlock(&apb_dma_lock);
+
+	return val;
+}
+
+static const struct of_device_id tegra20_fuse_of_match[] = {
+	{ .compatible = "nvidia,tegra20-efuse" },
+	{},
+};
+
+static int apb_dma_init(void)
+{
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	apb_dma_chan = dma_request_channel(mask, NULL, NULL);
+	if (!apb_dma_chan)
+		return -EPROBE_DEFER;
+
+	apb_buffer = dma_alloc_coherent(NULL, sizeof(u32), &apb_buffer_phys,
+					GFP_KERNEL);
+	if (!apb_buffer) {
+		dma_release_channel(apb_dma_chan);
+		return -ENOMEM;
+	}
+
+	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	dma_sconfig.src_maxburst = 1;
+	dma_sconfig.dst_maxburst = 1;
+
+	return 0;
+}
+
+static int tegra20_fuse_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int err;
+
+	fuse_clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(fuse_clk)) {
+		dev_err(&pdev->dev, "missing clock");
+		return PTR_ERR(fuse_clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	fuse_phys = res->start;
+
+	err = apb_dma_init();
+	if (err)
+		return err;
+
+	if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl))
+		return -ENODEV;
+
+	dev_dbg(&pdev->dev, "loaded\n");
+
+	return 0;
+}
+
+static struct platform_driver tegra20_fuse_driver = {
+	.probe = tegra20_fuse_probe,
+	.driver = {
+		.name = "tegra20_fuse",
+		.owner = THIS_MODULE,
+		.of_match_table = tegra20_fuse_of_match,
+	}
+};
+
+static int __init tegra20_fuse_init(void)
+{
+	return platform_driver_register(&tegra20_fuse_driver);
+}
+postcore_initcall(tegra20_fuse_init);
+
+/* Early boot code. This code is called before the devices are created */
+
+u32 __init tegra20_fuse_early(const unsigned int offset)
+{
+	return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
+}
+
+bool __init tegra20_spare_fuse_early(int spare_bit)
+{
+	u32 offset = spare_bit * 4;
+	bool value;
+
+	value = tegra20_fuse_early(offset + 0x100);
+
+	return value;
+}
+
+static void __init tegra20_fuse_add_randomness(void)
+{
+	u32 randomness[7];
+
+	randomness[0] = tegra_sku_info.sku_id;
+	randomness[1] = tegra_read_straps();
+	randomness[2] = tegra_read_chipid();
+	randomness[3] = tegra_sku_info.cpu_process_id << 16;
+	randomness[3] |= tegra_sku_info.core_process_id;
+	randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
+	randomness[4] |= tegra_sku_info.soc_speedo_id;
+	randomness[5] = tegra20_fuse_early(FUSE_UID_LOW);
+	randomness[6] = tegra20_fuse_early(FUSE_UID_HIGH);
+
+	add_device_randomness(randomness, sizeof(randomness));
+}
+
+void __init tegra20_init_fuse_early(void)
+{
+	fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
+
+	tegra_init_revision();
+	tegra20_init_speedo_data(&tegra_sku_info);
+	tegra20_fuse_add_randomness();
+
+	iounmap(fuse_base);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra30.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra30.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra30.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra30.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ *
+ * 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/device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define FUSE_BEGIN	0x100
+
+/* Tegra30 and later */
+#define FUSE_VENDOR_CODE	0x100
+#define FUSE_FAB_CODE		0x104
+#define FUSE_LOT_CODE_0		0x108
+#define FUSE_LOT_CODE_1		0x10c
+#define FUSE_WAFER_ID		0x110
+#define FUSE_X_COORDINATE	0x114
+#define FUSE_Y_COORDINATE	0x118
+
+#define FUSE_HAS_REVISION_INFO	BIT(0)
+
+enum speedo_idx {
+	SPEEDO_TEGRA30 = 0,
+	SPEEDO_TEGRA114,
+	SPEEDO_TEGRA124,
+};
+
+struct tegra_fuse_info {
+	int		size;
+	int		spare_bit;
+	enum speedo_idx	speedo_idx;
+};
+
+static void __iomem *fuse_base;
+static struct clk *fuse_clk;
+static struct tegra_fuse_info *fuse_info;
+
+u32 tegra30_fuse_readl(const unsigned int offset)
+{
+	u32 val;
+
+	/*
+	 * early in the boot, the fuse clock will be enabled by
+	 * tegra_init_fuse()
+	 */
+
+	if (fuse_clk)
+		clk_prepare_enable(fuse_clk);
+
+	val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);
+
+	if (fuse_clk)
+		clk_disable_unprepare(fuse_clk);
+
+	return val;
+}
+
+static struct tegra_fuse_info tegra30_info = {
+	.size			= 0x2a4,
+	.spare_bit		= 0x144,
+	.speedo_idx		= SPEEDO_TEGRA30,
+};
+
+static struct tegra_fuse_info tegra114_info = {
+	.size			= 0x2a0,
+	.speedo_idx		= SPEEDO_TEGRA114,
+};
+
+static struct tegra_fuse_info tegra124_info = {
+	.size			= 0x300,
+	.speedo_idx		= SPEEDO_TEGRA124,
+};
+
+static const struct of_device_id tegra30_fuse_of_match[] = {
+	{ .compatible = "nvidia,tegra30-efuse", .data = &tegra30_info },
+	{ .compatible = "nvidia,tegra114-efuse", .data = &tegra114_info },
+	{ .compatible = "nvidia,tegra124-efuse", .data = &tegra124_info },
+	{},
+};
+
+static int tegra30_fuse_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_dev_id;
+
+	of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev);
+	if (!of_dev_id)
+		return -ENODEV;
+
+	fuse_clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(fuse_clk)) {
+		dev_err(&pdev->dev, "missing clock");
+		return PTR_ERR(fuse_clk);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
+				    tegra30_fuse_readl))
+		return -ENODEV;
+
+	dev_dbg(&pdev->dev, "loaded\n");
+
+	return 0;
+}
+
+static struct platform_driver tegra30_fuse_driver = {
+	.probe = tegra30_fuse_probe,
+	.driver = {
+		.name = "tegra_fuse",
+		.owner = THIS_MODULE,
+		.of_match_table = tegra30_fuse_of_match,
+	}
+};
+
+static int __init tegra30_fuse_init(void)
+{
+	return platform_driver_register(&tegra30_fuse_driver);
+}
+postcore_initcall(tegra30_fuse_init);
+
+/* Early boot code. This code is called before the devices are created */
+
+typedef void (*speedo_f)(struct tegra_sku_info *sku_info);
+
+static speedo_f __initdata speedo_tbl[] = {
+	[SPEEDO_TEGRA30]	= tegra30_init_speedo_data,
+	[SPEEDO_TEGRA114]	= tegra114_init_speedo_data,
+	[SPEEDO_TEGRA124]	= tegra124_init_speedo_data,
+};
+
+static void __init tegra30_fuse_add_randomness(void)
+{
+	u32 randomness[12];
+
+	randomness[0] = tegra_sku_info.sku_id;
+	randomness[1] = tegra_read_straps();
+	randomness[2] = tegra_read_chipid();
+	randomness[3] = tegra_sku_info.cpu_process_id << 16;
+	randomness[3] |= tegra_sku_info.core_process_id;
+	randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
+	randomness[4] |= tegra_sku_info.soc_speedo_id;
+	randomness[5] = tegra30_fuse_readl(FUSE_VENDOR_CODE);
+	randomness[6] = tegra30_fuse_readl(FUSE_FAB_CODE);
+	randomness[7] = tegra30_fuse_readl(FUSE_LOT_CODE_0);
+	randomness[8] = tegra30_fuse_readl(FUSE_LOT_CODE_1);
+	randomness[9] = tegra30_fuse_readl(FUSE_WAFER_ID);
+	randomness[10] = tegra30_fuse_readl(FUSE_X_COORDINATE);
+	randomness[11] = tegra30_fuse_readl(FUSE_Y_COORDINATE);
+
+	add_device_randomness(randomness, sizeof(randomness));
+}
+
+static void __init legacy_fuse_init(void)
+{
+	switch (tegra_get_chip_id()) {
+	case TEGRA30:
+		fuse_info = &tegra30_info;
+		break;
+	case TEGRA114:
+		fuse_info = &tegra114_info;
+		break;
+	case TEGRA124:
+		fuse_info = &tegra124_info;
+		break;
+	default:
+		return;
+	}
+
+	fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
+}
+
+bool __init tegra30_spare_fuse(int spare_bit)
+{
+	u32 offset = fuse_info->spare_bit + spare_bit * 4;
+
+	return tegra30_fuse_readl(offset) & 1;
+}
+
+void __init tegra30_init_fuse_early(void)
+{
+	struct device_node *np;
+	const struct of_device_id *of_match;
+
+	np = of_find_matching_node_and_match(NULL, tegra30_fuse_of_match,
+						&of_match);
+	if (np) {
+		fuse_base = of_iomap(np, 0);
+		fuse_info = (struct tegra_fuse_info *)of_match->data;
+	} else
+		legacy_fuse_init();
+
+	if (!fuse_base) {
+		pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
+			tegra_get_chip_id());
+		return;
+	}
+
+	tegra_init_revision();
+	speedo_tbl[fuse_info->speedo_idx](&tegra_sku_info);
+	tegra30_fuse_add_randomness();
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/fuse-tegra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/fuse-tegra.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ *
+ * 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/device.h>
+#include <linux/kobject.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+static u32 (*fuse_readl)(const unsigned int offset);
+static int fuse_size;
+struct tegra_sku_info tegra_sku_info;
+
+static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
+	[TEGRA_REVISION_UNKNOWN] = "unknown",
+	[TEGRA_REVISION_A01]     = "A01",
+	[TEGRA_REVISION_A02]     = "A02",
+	[TEGRA_REVISION_A03]     = "A03",
+	[TEGRA_REVISION_A03p]    = "A03 prime",
+	[TEGRA_REVISION_A04]     = "A04",
+};
+
+static u8 fuse_readb(const unsigned int offset)
+{
+	u32 val;
+
+	val = fuse_readl(round_down(offset, 4));
+	val >>= (offset % 4) * 8;
+	val &= 0xff;
+
+	return val;
+}
+
+static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
+			struct bin_attribute *attr, char *buf,
+			loff_t pos, size_t size)
+{
+	int i;
+
+	if (pos < 0 || pos >= fuse_size)
+		return 0;
+
+	if (size > fuse_size - pos)
+		size = fuse_size - pos;
+
+	for (i = 0; i < size; i++)
+		buf[i] = fuse_readb(pos + i);
+
+	return i;
+}
+
+static struct bin_attribute fuse_bin_attr = {
+	.attr = { .name = "fuse", .mode = S_IRUGO, },
+	.read = fuse_read,
+};
+
+static const struct of_device_id car_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-car", },
+	{ .compatible = "nvidia,tegra30-car", },
+	{ .compatible = "nvidia,tegra114-car", },
+	{ .compatible = "nvidia,tegra124-car", },
+	{},
+};
+
+static void tegra_enable_fuse_clk(void __iomem *base)
+{
+	u32 reg;
+
+	reg = readl_relaxed(base + 0x48);
+	reg |= 1 << 28;
+	writel(reg, base + 0x48);
+
+	/*
+	 * Enable FUSE clock. This needs to be hardcoded because the clock
+	 * subsystem is not active during early boot.
+	 */
+	reg = readl(base + 0x14);
+	reg |= 1 << 7;
+	writel(reg, base + 0x14);
+}
+
+int tegra_fuse_readl(unsigned long offset, u32 *value)
+{
+	if (!fuse_readl)
+		return -EPROBE_DEFER;
+
+	*value = fuse_readl(offset);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_fuse_readl);
+
+int tegra_fuse_create_sysfs(struct device *dev, int size,
+		     u32 (*readl)(const unsigned int offset))
+{
+	if (fuse_size)
+		return -ENODEV;
+
+	fuse_bin_attr.size = size;
+	fuse_bin_attr.read = fuse_read;
+
+	fuse_size = size;
+	fuse_readl = readl;
+
+	return device_create_bin_file(dev, &fuse_bin_attr);
+}
+
+static int __init tegra_init_fuse(void)
+{
+	struct device_node *np;
+	void __iomem *car_base;
+
+	if (!soc_is_tegra())
+		return 0;
+
+	tegra_init_apbmisc();
+
+	np = of_find_matching_node(NULL, car_match);
+	car_base = of_iomap(np, 0);
+	if (car_base) {
+		tegra_enable_fuse_clk(car_base);
+		iounmap(car_base);
+	} else {
+		pr_err("Could not enable fuse clk. ioremap tegra car failed.\n");
+		return -ENXIO;
+	}
+
+	if (tegra_get_chip_id() == TEGRA20)
+		tegra20_init_fuse_early();
+	else
+		tegra30_init_fuse_early();
+
+	pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
+		tegra_revision_name[tegra_sku_info.revision],
+		tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
+		tegra_sku_info.core_process_id);
+	pr_debug("Tegra CPU Speedo ID %d, Soc Speedo ID %d\n",
+		tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
+
+	return 0;
+}
+early_initcall(tegra_init_fuse);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/Makefile linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/Makefile
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,8 @@
+obj-y					+= fuse-tegra.o
+obj-y					+= fuse-tegra30.o
+obj-y					+= tegra-apbmisc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= fuse-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= speedo-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= speedo-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= speedo-tegra114.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= speedo-tegra124.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra114.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra114.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra114.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra114.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ *
+ * 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/bug.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS	2
+#define CPU_PROCESS_CORNERS	2
+
+enum {
+	THRESHOLD_INDEX_0,
+	THRESHOLD_INDEX_1,
+	THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
+	{1123,     UINT_MAX},
+	{0,        UINT_MAX},
+};
+
+static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
+	{1695,     UINT_MAX},
+	{0,        UINT_MAX},
+};
+
+static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
+					 int *threshold)
+{
+	u32 tmp;
+	u32 sku = sku_info->sku_id;
+	enum tegra_revision rev = sku_info->revision;
+
+	switch (sku) {
+	case 0x00:
+	case 0x10:
+	case 0x05:
+	case 0x06:
+		sku_info->cpu_speedo_id = 1;
+		sku_info->soc_speedo_id = 0;
+		*threshold = THRESHOLD_INDEX_0;
+		break;
+
+	case 0x03:
+	case 0x04:
+		sku_info->cpu_speedo_id = 2;
+		sku_info->soc_speedo_id = 1;
+		*threshold = THRESHOLD_INDEX_1;
+		break;
+
+	default:
+		pr_err("Tegra Unknown SKU %d\n", sku);
+		sku_info->cpu_speedo_id = 0;
+		sku_info->soc_speedo_id = 0;
+		*threshold = THRESHOLD_INDEX_0;
+		break;
+	}
+
+	if (rev == TEGRA_REVISION_A01) {
+		tmp = tegra30_fuse_readl(0x270) << 1;
+		tmp |= tegra30_fuse_readl(0x26c);
+		if (!tmp)
+			sku_info->cpu_speedo_id = 0;
+	}
+}
+
+void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info)
+{
+	u32 cpu_speedo_val;
+	u32 core_speedo_val;
+	int threshold;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+
+	rev_sku_to_speedo_ids(sku_info, &threshold);
+
+	cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024;
+	core_speedo_val = tegra30_fuse_readl(0x134);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS; i++)
+		if (cpu_speedo_val < cpu_process_speedos[threshold][i])
+			break;
+	sku_info->cpu_process_id = i;
+
+	for (i = 0; i < CORE_PROCESS_CORNERS; i++)
+		if (core_speedo_val < core_process_speedos[threshold][i])
+			break;
+	sku_info->core_process_id = i;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra124.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra124.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra124.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra124.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ *
+ * 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/device.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define CPU_PROCESS_CORNERS	2
+#define GPU_PROCESS_CORNERS	2
+#define CORE_PROCESS_CORNERS	2
+
+#define FUSE_CPU_SPEEDO_0	0x14
+#define FUSE_CPU_SPEEDO_1	0x2c
+#define FUSE_CPU_SPEEDO_2	0x30
+#define FUSE_SOC_SPEEDO_0	0x34
+#define FUSE_SOC_SPEEDO_1	0x38
+#define FUSE_SOC_SPEEDO_2	0x3c
+#define FUSE_CPU_IDDQ		0x18
+#define FUSE_SOC_IDDQ		0x40
+#define FUSE_GPU_IDDQ		0x128
+#define FUSE_FT_REV		0x28
+
+enum {
+	THRESHOLD_INDEX_0,
+	THRESHOLD_INDEX_1,
+	THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
+	{2190,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
+	{1965,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
+	{2101,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
+					 int *threshold)
+{
+	int sku = sku_info->sku_id;
+
+	/* Assign to default */
+	sku_info->cpu_speedo_id = 0;
+	sku_info->soc_speedo_id = 0;
+	sku_info->gpu_speedo_id = 0;
+	*threshold = THRESHOLD_INDEX_0;
+
+	switch (sku) {
+	case 0x00: /* Eng sku */
+	case 0x0F:
+	case 0x23:
+		/* Using the default */
+		break;
+	case 0x83:
+		sku_info->cpu_speedo_id = 2;
+		break;
+
+	case 0x1F:
+	case 0x87:
+	case 0x27:
+		sku_info->cpu_speedo_id = 2;
+		sku_info->soc_speedo_id = 0;
+		sku_info->gpu_speedo_id = 1;
+		*threshold = THRESHOLD_INDEX_0;
+		break;
+	case 0x81:
+	case 0x21:
+	case 0x07:
+		sku_info->cpu_speedo_id = 1;
+		sku_info->soc_speedo_id = 1;
+		sku_info->gpu_speedo_id = 1;
+		*threshold = THRESHOLD_INDEX_1;
+		break;
+	case 0x49:
+	case 0x4A:
+	case 0x48:
+		sku_info->cpu_speedo_id = 4;
+		sku_info->soc_speedo_id = 2;
+		sku_info->gpu_speedo_id = 3;
+		*threshold = THRESHOLD_INDEX_1;
+		break;
+	default:
+		pr_err("Tegra Unknown SKU %d\n", sku);
+		/* Using the default for the error case */
+		break;
+	}
+}
+
+void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
+{
+	int i, threshold, cpu_speedo_0_value, soc_speedo_0_value;
+	int cpu_iddq_value, gpu_iddq_value, soc_iddq_value;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+
+	cpu_speedo_0_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_0);
+
+	/* GPU Speedo is stored in CPU_SPEEDO_2 */
+	sku_info->gpu_speedo_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_2);
+
+	soc_speedo_0_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_0);
+
+	cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ);
+	soc_iddq_value = tegra30_fuse_readl(FUSE_SOC_IDDQ);
+	gpu_iddq_value = tegra30_fuse_readl(FUSE_GPU_IDDQ);
+
+	sku_info->cpu_speedo_value = cpu_speedo_0_value;
+
+	if (sku_info->cpu_speedo_value == 0) {
+		pr_warn("Tegra Warning: Speedo value not fused.\n");
+		WARN_ON(1);
+		return;
+	}
+
+	rev_sku_to_speedo_ids(sku_info, &threshold);
+
+	sku_info->cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ);
+
+	for (i = 0; i < GPU_PROCESS_CORNERS; i++)
+		if (sku_info->gpu_speedo_value <
+			gpu_process_speedos[threshold][i])
+			break;
+	sku_info->gpu_process_id = i;
+
+	for (i = 0; i < CPU_PROCESS_CORNERS; i++)
+		if (sku_info->cpu_speedo_value <
+			cpu_process_speedos[threshold][i])
+				break;
+	sku_info->cpu_process_id = i;
+
+	for (i = 0; i < CORE_PROCESS_CORNERS; i++)
+		if (soc_speedo_0_value <
+			core_process_speedos[threshold][i])
+			break;
+	sku_info->core_process_id = i;
+
+	pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
+		 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra20.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra20.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra20.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra20.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012-2014, 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.
+ *
+ * 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/bug.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define CPU_SPEEDO_LSBIT		20
+#define CPU_SPEEDO_MSBIT		29
+#define CPU_SPEEDO_REDUND_LSBIT		30
+#define CPU_SPEEDO_REDUND_MSBIT		39
+#define CPU_SPEEDO_REDUND_OFFS	(CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
+
+#define CORE_SPEEDO_LSBIT		40
+#define CORE_SPEEDO_MSBIT		47
+#define CORE_SPEEDO_REDUND_LSBIT	48
+#define CORE_SPEEDO_REDUND_MSBIT	55
+#define CORE_SPEEDO_REDUND_OFFS	(CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
+
+#define SPEEDO_MULT			4
+
+#define PROCESS_CORNERS_NUM		4
+
+#define SPEEDO_ID_SELECT_0(rev)		((rev) <= 2)
+#define SPEEDO_ID_SELECT_1(sku)		\
+	(((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
+	 ((sku) != 27) && ((sku) != 28))
+
+enum {
+	SPEEDO_ID_0,
+	SPEEDO_ID_1,
+	SPEEDO_ID_2,
+	SPEEDO_ID_COUNT,
+};
+
+static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
+	{315, 366, 420, UINT_MAX},
+	{303, 368, 419, UINT_MAX},
+	{316, 331, 383, UINT_MAX},
+};
+
+static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = {
+	{165, 195, 224, UINT_MAX},
+	{165, 195, 224, UINT_MAX},
+	{165, 195, 224, UINT_MAX},
+};
+
+void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
+{
+	u32 reg;
+	u32 val;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
+
+	if (SPEEDO_ID_SELECT_0(sku_info->revision))
+		sku_info->soc_speedo_id = SPEEDO_ID_0;
+	else if (SPEEDO_ID_SELECT_1(sku_info->sku_id))
+		sku_info->soc_speedo_id = SPEEDO_ID_1;
+	else
+		sku_info->soc_speedo_id = SPEEDO_ID_2;
+
+	val = 0;
+	for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
+		reg = tegra20_spare_fuse_early(i) |
+			tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	pr_debug("Tegra CPU speedo value %u\n", val);
+
+	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+		if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i])
+			break;
+	}
+	sku_info->cpu_process_id = i;
+
+	val = 0;
+	for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
+		reg = tegra20_spare_fuse_early(i) |
+			tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	pr_debug("Core speedo value %u\n", val);
+
+	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+		if (val <= core_process_speedos[sku_info->soc_speedo_id][i])
+			break;
+	}
+	sku_info->core_process_id = i;
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra30.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra30.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/speedo-tegra30.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/speedo-tegra30.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2012-2014, 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.
+ *
+ * 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/bug.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS	1
+#define CPU_PROCESS_CORNERS	6
+
+#define FUSE_SPEEDO_CALIB_0	0x14
+#define FUSE_PACKAGE_INFO	0XFC
+#define FUSE_TEST_PROG_VER	0X28
+
+#define G_SPEEDO_BIT_MINUS1	58
+#define G_SPEEDO_BIT_MINUS1_R	59
+#define G_SPEEDO_BIT_MINUS2	60
+#define G_SPEEDO_BIT_MINUS2_R	61
+#define LP_SPEEDO_BIT_MINUS1	62
+#define LP_SPEEDO_BIT_MINUS1_R	63
+#define LP_SPEEDO_BIT_MINUS2	64
+#define LP_SPEEDO_BIT_MINUS2_R	65
+
+enum {
+	THRESHOLD_INDEX_0,
+	THRESHOLD_INDEX_1,
+	THRESHOLD_INDEX_2,
+	THRESHOLD_INDEX_3,
+	THRESHOLD_INDEX_4,
+	THRESHOLD_INDEX_5,
+	THRESHOLD_INDEX_6,
+	THRESHOLD_INDEX_7,
+	THRESHOLD_INDEX_8,
+	THRESHOLD_INDEX_9,
+	THRESHOLD_INDEX_10,
+	THRESHOLD_INDEX_11,
+	THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
+	{180},
+	{170},
+	{195},
+	{180},
+	{168},
+	{192},
+	{180},
+	{170},
+	{195},
+	{180},
+	{180},
+	{180},
+};
+
+static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
+	{306, 338, 360, 376, UINT_MAX},
+	{295, 336, 358, 375, UINT_MAX},
+	{325, 325, 358, 375, UINT_MAX},
+	{325, 325, 358, 375, UINT_MAX},
+	{292, 324, 348, 364, UINT_MAX},
+	{324, 324, 348, 364, UINT_MAX},
+	{324, 324, 348, 364, UINT_MAX},
+	{295, 336, 358, 375, UINT_MAX},
+	{358, 358, 358, 358, 397, UINT_MAX},
+	{364, 364, 364, 364, 397, UINT_MAX},
+	{295, 336, 358, 375, 391, UINT_MAX},
+	{295, 336, 358, 375, 391, UINT_MAX},
+};
+
+static int threshold_index __initdata;
+
+static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
+{
+	u32 reg;
+	int ate_ver;
+	int bit_minus1;
+	int bit_minus2;
+
+	reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0);
+
+	*speedo_lp = (reg & 0xFFFF) * 4;
+	*speedo_g = ((reg >> 16) & 0xFFFF) * 4;
+
+	ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER);
+	pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
+
+	if (ate_ver >= 26) {
+		bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1);
+		bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
+		bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2);
+		bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
+		*speedo_lp |= (bit_minus1 << 1) | bit_minus2;
+
+		bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1);
+		bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
+		bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2);
+		bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
+		*speedo_g |= (bit_minus1 << 1) | bit_minus2;
+	} else {
+		*speedo_lp |= 0x3;
+		*speedo_g |= 0x3;
+	}
+}
+
+static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
+{
+	int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
+
+	switch (sku_info->revision) {
+	case TEGRA_REVISION_A01:
+		sku_info->cpu_speedo_id = 0;
+		sku_info->soc_speedo_id = 0;
+		threshold_index = THRESHOLD_INDEX_0;
+		break;
+	case TEGRA_REVISION_A02:
+	case TEGRA_REVISION_A03:
+		switch (sku_info->sku_id) {
+		case 0x87:
+		case 0x82:
+			sku_info->cpu_speedo_id = 1;
+			sku_info->soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_1;
+			break;
+		case 0x81:
+			switch (package_id) {
+			case 1:
+				sku_info->cpu_speedo_id = 2;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_2;
+				break;
+			case 2:
+				sku_info->cpu_speedo_id = 4;
+				sku_info->soc_speedo_id = 1;
+				threshold_index = THRESHOLD_INDEX_7;
+				break;
+			default:
+				pr_err("Tegra Unknown pkg %d\n", package_id);
+				break;
+			}
+			break;
+		case 0x80:
+			switch (package_id) {
+			case 1:
+				sku_info->cpu_speedo_id = 5;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_8;
+				break;
+			case 2:
+				sku_info->cpu_speedo_id = 6;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_9;
+				break;
+			default:
+				pr_err("Tegra Unknown pkg %d\n", package_id);
+				break;
+			}
+			break;
+		case 0x83:
+			switch (package_id) {
+			case 1:
+				sku_info->cpu_speedo_id = 7;
+				sku_info->soc_speedo_id = 1;
+				threshold_index = THRESHOLD_INDEX_10;
+				break;
+			case 2:
+				sku_info->cpu_speedo_id = 3;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_3;
+				break;
+			default:
+				pr_err("Tegra Unknown pkg %d\n", package_id);
+				break;
+			}
+			break;
+		case 0x8F:
+			sku_info->cpu_speedo_id = 8;
+			sku_info->soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_11;
+			break;
+		case 0x08:
+			sku_info->cpu_speedo_id = 1;
+			sku_info->soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_4;
+			break;
+		case 0x02:
+			sku_info->cpu_speedo_id = 2;
+			sku_info->soc_speedo_id = 2;
+			threshold_index = THRESHOLD_INDEX_5;
+			break;
+		case 0x04:
+			sku_info->cpu_speedo_id = 3;
+			sku_info->soc_speedo_id = 2;
+			threshold_index = THRESHOLD_INDEX_6;
+			break;
+		case 0:
+			switch (package_id) {
+			case 1:
+				sku_info->cpu_speedo_id = 2;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_2;
+				break;
+			case 2:
+				sku_info->cpu_speedo_id = 3;
+				sku_info->soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_3;
+				break;
+			default:
+				pr_err("Tegra Unknown pkg %d\n", package_id);
+				break;
+			}
+			break;
+		default:
+			pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
+			sku_info->cpu_speedo_id = 0;
+			sku_info->soc_speedo_id = 0;
+			threshold_index = THRESHOLD_INDEX_0;
+			break;
+		}
+		break;
+	default:
+		pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
+		sku_info->cpu_speedo_id = 0;
+		sku_info->soc_speedo_id = 0;
+		threshold_index = THRESHOLD_INDEX_0;
+		break;
+	}
+}
+
+void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
+{
+	u32 cpu_speedo_val;
+	u32 core_speedo_val;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+
+
+	rev_sku_to_speedo_ids(sku_info);
+	fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
+	pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
+	pr_debug("Tegra Core speedo value %u\n", core_speedo_val);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
+		if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
+			break;
+	}
+	sku_info->cpu_process_id = i - 1;
+
+	if (sku_info->cpu_process_id == -1) {
+		pr_warn("Tegra CPU speedo value %3d out of range",
+			 cpu_speedo_val);
+		sku_info->cpu_process_id = 0;
+		sku_info->cpu_speedo_id = 1;
+	}
+
+	for (i = 0; i < CORE_PROCESS_CORNERS; i++) {
+		if (core_speedo_val < core_process_speedos[threshold_index][i])
+			break;
+	}
+	sku_info->core_process_id = i - 1;
+
+	if (sku_info->core_process_id == -1) {
+		pr_warn("Tegra CORE speedo value %3d out of range",
+				 core_speedo_val);
+		sku_info->core_process_id = 0;
+		sku_info->soc_speedo_id = 1;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/fuse/tegra-apbmisc.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/tegra-apbmisc.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/fuse/tegra-apbmisc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/fuse/tegra-apbmisc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, 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.
+ *
+ * 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/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
+#define APBMISC_BASE	0x70000800
+#define APBMISC_SIZE	0x64
+#define FUSE_SKU_INFO	0x10
+
+static void __iomem *apbmisc_base;
+static void __iomem *strapping_base;
+
+u32 tegra_read_chipid(void)
+{
+	return readl_relaxed(apbmisc_base + 4);
+}
+
+u8 tegra_get_chip_id(void)
+{
+	if (!apbmisc_base) {
+		WARN(1, "Tegra Chip ID not yet available\n");
+		return 0;
+	}
+
+	return (tegra_read_chipid() >> 8) & 0xff;
+}
+
+u32 tegra_read_straps(void)
+{
+	if (strapping_base)
+		return readl_relaxed(strapping_base);
+	else
+		return 0;
+}
+
+static const struct of_device_id apbmisc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-apbmisc", },
+	{},
+};
+
+void __init tegra_init_revision(void)
+{
+	u32 id, chip_id, minor_rev;
+	int rev;
+
+	id = tegra_read_chipid();
+	chip_id = (id >> 8) & 0xff;
+	minor_rev = (id >> 16) & 0xf;
+
+	switch (minor_rev) {
+	case 1:
+		rev = TEGRA_REVISION_A01;
+		break;
+	case 2:
+		rev = TEGRA_REVISION_A02;
+		break;
+	case 3:
+		if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) ||
+					   tegra20_spare_fuse_early(19)))
+			rev = TEGRA_REVISION_A03p;
+		else
+			rev = TEGRA_REVISION_A03;
+		break;
+	case 4:
+		rev = TEGRA_REVISION_A04;
+		break;
+	default:
+		rev = TEGRA_REVISION_UNKNOWN;
+	}
+
+	tegra_sku_info.revision = rev;
+
+	if (chip_id == TEGRA20)
+		tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO);
+	else
+		tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO);
+}
+
+void __init tegra_init_apbmisc(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, apbmisc_match);
+	apbmisc_base = of_iomap(np, 0);
+	if (!apbmisc_base) {
+		pr_warn("ioremap tegra apbmisc failed. using %08x instead\n",
+			APBMISC_BASE);
+		apbmisc_base = ioremap(APBMISC_BASE, APBMISC_SIZE);
+	}
+
+	strapping_base = of_iomap(np, 1);
+	if (!strapping_base)
+		pr_err("ioremap tegra strapping_base failed\n");
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/Makefile linux-libre-3.17-rc7-gnu/drivers/soc/tegra/Makefile
--- linux-libre-3.16-gnu/drivers/soc/tegra/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,4 @@
+obj-$(CONFIG_ARCH_TEGRA) += fuse/
+
+obj-$(CONFIG_ARCH_TEGRA) += common.o
+obj-$(CONFIG_ARCH_TEGRA) += pmc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/soc/tegra/pmc.c linux-libre-3.17-rc7-gnu/drivers/soc/tegra/pmc.c
--- linux-libre-3.16-gnu/drivers/soc/tegra/pmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/soc/tegra/pmc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,957 @@
+/*
+ * drivers/soc/tegra/pmc.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
+
+#define PMC_CNTRL			0x0
+#define  PMC_CNTRL_SYSCLK_POLARITY	(1 << 10)  /* sys clk polarity */
+#define  PMC_CNTRL_SYSCLK_OE		(1 << 11)  /* system clock enable */
+#define  PMC_CNTRL_SIDE_EFFECT_LP0	(1 << 14)  /* LP0 when CPU pwr gated */
+#define  PMC_CNTRL_CPU_PWRREQ_POLARITY	(1 << 15)  /* CPU pwr req polarity */
+#define  PMC_CNTRL_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
+#define  PMC_CNTRL_INTR_POLARITY	(1 << 17)  /* inverts INTR polarity */
+
+#define DPD_SAMPLE			0x020
+#define  DPD_SAMPLE_ENABLE		(1 << 0)
+#define  DPD_SAMPLE_DISABLE		(0 << 0)
+
+#define PWRGATE_TOGGLE			0x30
+#define  PWRGATE_TOGGLE_START		(1 << 8)
+
+#define REMOVE_CLAMPING			0x34
+
+#define PWRGATE_STATUS			0x38
+
+#define PMC_SCRATCH0			0x50
+#define  PMC_SCRATCH0_MODE_RECOVERY	(1 << 31)
+#define  PMC_SCRATCH0_MODE_BOOTLOADER	(1 << 30)
+#define  PMC_SCRATCH0_MODE_RCM		(1 << 1)
+#define  PMC_SCRATCH0_MODE_MASK		(PMC_SCRATCH0_MODE_RECOVERY | \
+					 PMC_SCRATCH0_MODE_BOOTLOADER | \
+					 PMC_SCRATCH0_MODE_RCM)
+
+#define PMC_CPUPWRGOOD_TIMER		0xc8
+#define PMC_CPUPWROFF_TIMER		0xcc
+
+#define PMC_SCRATCH41			0x140
+
+#define IO_DPD_REQ			0x1b8
+#define  IO_DPD_REQ_CODE_IDLE		(0 << 30)
+#define  IO_DPD_REQ_CODE_OFF		(1 << 30)
+#define  IO_DPD_REQ_CODE_ON		(2 << 30)
+#define  IO_DPD_REQ_CODE_MASK		(3 << 30)
+
+#define IO_DPD_STATUS			0x1bc
+#define IO_DPD2_REQ			0x1c0
+#define IO_DPD2_STATUS			0x1c4
+#define SEL_DPD_TIM			0x1c8
+
+#define GPU_RG_CNTRL			0x2d4
+
+struct tegra_pmc_soc {
+	unsigned int num_powergates;
+	const char *const *powergates;
+	unsigned int num_cpu_powergates;
+	const u8 *cpu_powergates;
+};
+
+/**
+ * struct tegra_pmc - NVIDIA Tegra PMC
+ * @base: pointer to I/O remapped register region
+ * @clk: pointer to pclk clock
+ * @rate: currently configured rate of pclk
+ * @suspend_mode: lowest suspend mode available
+ * @cpu_good_time: CPU power good time (in microseconds)
+ * @cpu_off_time: CPU power off time (in microsecends)
+ * @core_osc_time: core power good OSC time (in microseconds)
+ * @core_pmu_time: core power good PMU time (in microseconds)
+ * @core_off_time: core power off time (in microseconds)
+ * @corereq_high: core power request is active-high
+ * @sysclkreq_high: system clock request is active-high
+ * @combined_req: combined power request for CPU & core
+ * @cpu_pwr_good_en: CPU power good signal is enabled
+ * @lp0_vec_phys: physical base address of the LP0 warm boot code
+ * @lp0_vec_size: size of the LP0 warm boot code
+ * @powergates_lock: mutex for power gate register access
+ */
+struct tegra_pmc {
+	void __iomem *base;
+	struct clk *clk;
+
+	const struct tegra_pmc_soc *soc;
+
+	unsigned long rate;
+
+	enum tegra_suspend_mode suspend_mode;
+	u32 cpu_good_time;
+	u32 cpu_off_time;
+	u32 core_osc_time;
+	u32 core_pmu_time;
+	u32 core_off_time;
+	bool corereq_high;
+	bool sysclkreq_high;
+	bool combined_req;
+	bool cpu_pwr_good_en;
+	u32 lp0_vec_phys;
+	u32 lp0_vec_size;
+
+	struct mutex powergates_lock;
+};
+
+static struct tegra_pmc *pmc = &(struct tegra_pmc) {
+	.base = NULL,
+	.suspend_mode = TEGRA_SUSPEND_NONE,
+};
+
+static u32 tegra_pmc_readl(unsigned long offset)
+{
+	return readl(pmc->base + offset);
+}
+
+static void tegra_pmc_writel(u32 value, unsigned long offset)
+{
+	writel(value, pmc->base + offset);
+}
+
+/**
+ * tegra_powergate_set() - set the state of a partition
+ * @id: partition ID
+ * @new_state: new state of the partition
+ */
+static int tegra_powergate_set(int id, bool new_state)
+{
+	bool status;
+
+	mutex_lock(&pmc->powergates_lock);
+
+	status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
+
+	if (status == new_state) {
+		mutex_unlock(&pmc->powergates_lock);
+		return 0;
+	}
+
+	tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
+
+	mutex_unlock(&pmc->powergates_lock);
+
+	return 0;
+}
+
+/**
+ * tegra_powergate_power_on() - power on partition
+ * @id: partition ID
+ */
+int tegra_powergate_power_on(int id)
+{
+	if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, true);
+}
+
+/**
+ * tegra_powergate_power_off() - power off partition
+ * @id: partition ID
+ */
+int tegra_powergate_power_off(int id)
+{
+	if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, false);
+}
+EXPORT_SYMBOL(tegra_powergate_power_off);
+
+/**
+ * tegra_powergate_is_powered() - check if partition is powered
+ * @id: partition ID
+ */
+int tegra_powergate_is_powered(int id)
+{
+	u32 status;
+
+	if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
+		return -EINVAL;
+
+	status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
+	return !!status;
+}
+
+/**
+ * tegra_powergate_remove_clamping() - remove power clamps for partition
+ * @id: partition ID
+ */
+int tegra_powergate_remove_clamping(int id)
+{
+	u32 mask;
+
+	if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
+		return -EINVAL;
+
+	/*
+	 * The Tegra124 GPU has a separate register (with different semantics)
+	 * to remove clamps.
+	 */
+	if (tegra_get_chip_id() == TEGRA124) {
+		if (id == TEGRA_POWERGATE_3D) {
+			tegra_pmc_writel(0, GPU_RG_CNTRL);
+			return 0;
+		}
+	}
+
+	/*
+	 * Tegra 2 has a bug where PCIE and VDE clamping masks are
+	 * swapped relatively to the partition ids
+	 */
+	if (id == TEGRA_POWERGATE_VDEC)
+		mask = (1 << TEGRA_POWERGATE_PCIE);
+	else if (id == TEGRA_POWERGATE_PCIE)
+		mask = (1 << TEGRA_POWERGATE_VDEC);
+	else
+		mask = (1 << id);
+
+	tegra_pmc_writel(mask, REMOVE_CLAMPING);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_powergate_remove_clamping);
+
+/**
+ * tegra_powergate_sequence_power_up() - power up partition
+ * @id: partition ID
+ * @clk: clock for partition
+ * @rst: reset for partition
+ *
+ * Must be called with clk disabled, and returns with clk enabled.
+ */
+int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+				      struct reset_control *rst)
+{
+	int ret;
+
+	reset_control_assert(rst);
+
+	ret = tegra_powergate_power_on(id);
+	if (ret)
+		goto err_power;
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto err_clk;
+
+	usleep_range(10, 20);
+
+	ret = tegra_powergate_remove_clamping(id);
+	if (ret)
+		goto err_clamp;
+
+	usleep_range(10, 20);
+	reset_control_deassert(rst);
+
+	return 0;
+
+err_clamp:
+	clk_disable_unprepare(clk);
+err_clk:
+	tegra_powergate_power_off(id);
+err_power:
+	return ret;
+}
+EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
+
+#ifdef CONFIG_SMP
+/**
+ * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
+ * @cpuid: CPU partition ID
+ *
+ * Returns the partition ID corresponding to the CPU partition ID or a
+ * negative error code on failure.
+ */
+static int tegra_get_cpu_powergate_id(int cpuid)
+{
+	if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates)
+		return pmc->soc->cpu_powergates[cpuid];
+
+	return -EINVAL;
+}
+
+/**
+ * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
+ * @cpuid: CPU partition ID
+ */
+bool tegra_pmc_cpu_is_powered(int cpuid)
+{
+	int id;
+
+	id = tegra_get_cpu_powergate_id(cpuid);
+	if (id < 0)
+		return false;
+
+	return tegra_powergate_is_powered(id);
+}
+
+/**
+ * tegra_pmc_cpu_power_on() - power on CPU partition
+ * @cpuid: CPU partition ID
+ */
+int tegra_pmc_cpu_power_on(int cpuid)
+{
+	int id;
+
+	id = tegra_get_cpu_powergate_id(cpuid);
+	if (id < 0)
+		return id;
+
+	return tegra_powergate_set(id, true);
+}
+
+/**
+ * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
+ * @cpuid: CPU partition ID
+ */
+int tegra_pmc_cpu_remove_clamping(int cpuid)
+{
+	int id;
+
+	id = tegra_get_cpu_powergate_id(cpuid);
+	if (id < 0)
+		return id;
+
+	return tegra_powergate_remove_clamping(id);
+}
+#endif /* CONFIG_SMP */
+
+/**
+ * tegra_pmc_restart() - reboot the system
+ * @mode: which mode to reboot in
+ * @cmd: reboot command
+ */
+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
+{
+	u32 value;
+
+	value = tegra_pmc_readl(PMC_SCRATCH0);
+	value &= ~PMC_SCRATCH0_MODE_MASK;
+
+	if (cmd) {
+		if (strcmp(cmd, "recovery") == 0)
+			value |= PMC_SCRATCH0_MODE_RECOVERY;
+
+		if (strcmp(cmd, "bootloader") == 0)
+			value |= PMC_SCRATCH0_MODE_BOOTLOADER;
+
+		if (strcmp(cmd, "forced-recovery") == 0)
+			value |= PMC_SCRATCH0_MODE_RCM;
+	}
+
+	tegra_pmc_writel(value, PMC_SCRATCH0);
+
+	value = tegra_pmc_readl(0);
+	value |= 0x10;
+	tegra_pmc_writel(value, 0);
+}
+
+static int powergate_show(struct seq_file *s, void *data)
+{
+	unsigned int i;
+
+	seq_printf(s, " powergate powered\n");
+	seq_printf(s, "------------------\n");
+
+	for (i = 0; i < pmc->soc->num_powergates; i++) {
+		if (!pmc->soc->powergates[i])
+			continue;
+
+		seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
+			   tegra_powergate_is_powered(i) ? "yes" : "no");
+	}
+
+	return 0;
+}
+
+static int powergate_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, powergate_show, inode->i_private);
+}
+
+static const struct file_operations powergate_fops = {
+	.open = powergate_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int tegra_powergate_debugfs_init(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
+				&powergate_fops);
+	if (!d)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int tegra_io_rail_prepare(int id, unsigned long *request,
+				 unsigned long *status, unsigned int *bit)
+{
+	unsigned long rate, value;
+	struct clk *clk;
+
+	*bit = id % 32;
+
+	/*
+	 * There are two sets of 30 bits to select IO rails, but bits 30 and
+	 * 31 are control bits rather than IO rail selection bits.
+	 */
+	if (id > 63 || *bit == 30 || *bit == 31)
+		return -EINVAL;
+
+	if (id < 32) {
+		*status = IO_DPD_STATUS;
+		*request = IO_DPD_REQ;
+	} else {
+		*status = IO_DPD2_STATUS;
+		*request = IO_DPD2_REQ;
+	}
+
+	clk = clk_get_sys(NULL, "pclk");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+
+	tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
+
+	/* must be at least 200 ns, in APB (PCLK) clock cycles */
+	value = DIV_ROUND_UP(1000000000, rate);
+	value = DIV_ROUND_UP(200, value);
+	tegra_pmc_writel(value, SEL_DPD_TIM);
+
+	return 0;
+}
+
+static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
+			      unsigned long val, unsigned long timeout)
+{
+	unsigned long value;
+
+	timeout = jiffies + msecs_to_jiffies(timeout);
+
+	while (time_after(timeout, jiffies)) {
+		value = tegra_pmc_readl(offset);
+		if ((value & mask) == val)
+			return 0;
+
+		usleep_range(250, 1000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void tegra_io_rail_unprepare(void)
+{
+	tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
+}
+
+int tegra_io_rail_power_on(int id)
+{
+	unsigned long request, status, value;
+	unsigned int bit, mask;
+	int err;
+
+	err = tegra_io_rail_prepare(id, &request, &status, &bit);
+	if (err < 0)
+		return err;
+
+	mask = 1 << bit;
+
+	value = tegra_pmc_readl(request);
+	value |= mask;
+	value &= ~IO_DPD_REQ_CODE_MASK;
+	value |= IO_DPD_REQ_CODE_OFF;
+	tegra_pmc_writel(value, request);
+
+	err = tegra_io_rail_poll(status, mask, 0, 250);
+	if (err < 0)
+		return err;
+
+	tegra_io_rail_unprepare();
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_io_rail_power_on);
+
+int tegra_io_rail_power_off(int id)
+{
+	unsigned long request, status, value;
+	unsigned int bit, mask;
+	int err;
+
+	err = tegra_io_rail_prepare(id, &request, &status, &bit);
+	if (err < 0)
+		return err;
+
+	mask = 1 << bit;
+
+	value = tegra_pmc_readl(request);
+	value |= mask;
+	value &= ~IO_DPD_REQ_CODE_MASK;
+	value |= IO_DPD_REQ_CODE_ON;
+	tegra_pmc_writel(value, request);
+
+	err = tegra_io_rail_poll(status, mask, mask, 250);
+	if (err < 0)
+		return err;
+
+	tegra_io_rail_unprepare();
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_io_rail_power_off);
+
+#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+	return pmc->suspend_mode;
+}
+
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
+{
+	if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
+		return;
+
+	pmc->suspend_mode = mode;
+}
+
+void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
+{
+	unsigned long long rate = 0;
+	u32 value;
+
+	switch (mode) {
+	case TEGRA_SUSPEND_LP1:
+		rate = 32768;
+		break;
+
+	case TEGRA_SUSPEND_LP2:
+		rate = clk_get_rate(pmc->clk);
+		break;
+
+	default:
+		break;
+	}
+
+	if (WARN_ON_ONCE(rate == 0))
+		rate = 100000000;
+
+	if (rate != pmc->rate) {
+		u64 ticks;
+
+		ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
+		do_div(ticks, USEC_PER_SEC);
+		tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
+
+		ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
+		do_div(ticks, USEC_PER_SEC);
+		tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
+
+		wmb();
+
+		pmc->rate = rate;
+	}
+
+	value = tegra_pmc_readl(PMC_CNTRL);
+	value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
+	value |= PMC_CNTRL_CPU_PWRREQ_OE;
+	tegra_pmc_writel(value, PMC_CNTRL);
+}
+#endif
+
+static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
+{
+	u32 value, values[2];
+
+	if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
+	} else {
+		switch (value) {
+		case 0:
+			pmc->suspend_mode = TEGRA_SUSPEND_LP0;
+			break;
+
+		case 1:
+			pmc->suspend_mode = TEGRA_SUSPEND_LP1;
+			break;
+
+		case 2:
+			pmc->suspend_mode = TEGRA_SUSPEND_LP2;
+			break;
+
+		default:
+			pmc->suspend_mode = TEGRA_SUSPEND_NONE;
+			break;
+		}
+	}
+
+	pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
+
+	if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
+		pmc->suspend_mode = TEGRA_SUSPEND_NONE;
+
+	pmc->cpu_good_time = value;
+
+	if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
+		pmc->suspend_mode = TEGRA_SUSPEND_NONE;
+
+	pmc->cpu_off_time = value;
+
+	if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
+				       values, ARRAY_SIZE(values)))
+		pmc->suspend_mode = TEGRA_SUSPEND_NONE;
+
+	pmc->core_osc_time = values[0];
+	pmc->core_pmu_time = values[1];
+
+	if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
+		pmc->suspend_mode = TEGRA_SUSPEND_NONE;
+
+	pmc->core_off_time = value;
+
+	pmc->corereq_high = of_property_read_bool(np,
+				"nvidia,core-power-req-active-high");
+
+	pmc->sysclkreq_high = of_property_read_bool(np,
+				"nvidia,sys-clock-req-active-high");
+
+	pmc->combined_req = of_property_read_bool(np,
+				"nvidia,combined-power-req");
+
+	pmc->cpu_pwr_good_en = of_property_read_bool(np,
+				"nvidia,cpu-pwr-good-en");
+
+	if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
+				       ARRAY_SIZE(values)))
+		if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
+			pmc->suspend_mode = TEGRA_SUSPEND_LP1;
+
+	pmc->lp0_vec_phys = values[0];
+	pmc->lp0_vec_size = values[1];
+
+	return 0;
+}
+
+static void tegra_pmc_init(struct tegra_pmc *pmc)
+{
+	u32 value;
+
+	/* Always enable CPU power request */
+	value = tegra_pmc_readl(PMC_CNTRL);
+	value |= PMC_CNTRL_CPU_PWRREQ_OE;
+	tegra_pmc_writel(value, PMC_CNTRL);
+
+	value = tegra_pmc_readl(PMC_CNTRL);
+
+	if (pmc->sysclkreq_high)
+		value &= ~PMC_CNTRL_SYSCLK_POLARITY;
+	else
+		value |= PMC_CNTRL_SYSCLK_POLARITY;
+
+	/* configure the output polarity while the request is tristated */
+	tegra_pmc_writel(value, PMC_CNTRL);
+
+	/* now enable the request */
+	value = tegra_pmc_readl(PMC_CNTRL);
+	value |= PMC_CNTRL_SYSCLK_OE;
+	tegra_pmc_writel(value, PMC_CNTRL);
+}
+
+static int tegra_pmc_probe(struct platform_device *pdev)
+{
+	void __iomem *base = pmc->base;
+	struct resource *res;
+	int err;
+
+	err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
+	if (err < 0)
+		return err;
+
+	/* take over the memory region from the early initialization */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pmc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pmc->base))
+		return PTR_ERR(pmc->base);
+
+	iounmap(base);
+
+	pmc->clk = devm_clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pmc->clk)) {
+		err = PTR_ERR(pmc->clk);
+		dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
+		return err;
+	}
+
+	tegra_pmc_init(pmc);
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_powergate_debugfs_init();
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_pmc_suspend(struct device *dev)
+{
+	tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
+
+	return 0;
+}
+
+static int tegra_pmc_resume(struct device *dev)
+{
+	tegra_pmc_writel(0x0, PMC_SCRATCH41);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
+
+static const char * const tegra20_powergates[] = {
+	[TEGRA_POWERGATE_CPU] = "cpu",
+	[TEGRA_POWERGATE_3D] = "3d",
+	[TEGRA_POWERGATE_VENC] = "venc",
+	[TEGRA_POWERGATE_VDEC] = "vdec",
+	[TEGRA_POWERGATE_PCIE] = "pcie",
+	[TEGRA_POWERGATE_L2] = "l2",
+	[TEGRA_POWERGATE_MPE] = "mpe",
+};
+
+static const struct tegra_pmc_soc tegra20_pmc_soc = {
+	.num_powergates = ARRAY_SIZE(tegra20_powergates),
+	.powergates = tegra20_powergates,
+	.num_cpu_powergates = 0,
+	.cpu_powergates = NULL,
+};
+
+static const char * const tegra30_powergates[] = {
+	[TEGRA_POWERGATE_CPU] = "cpu0",
+	[TEGRA_POWERGATE_3D] = "3d0",
+	[TEGRA_POWERGATE_VENC] = "venc",
+	[TEGRA_POWERGATE_VDEC] = "vdec",
+	[TEGRA_POWERGATE_PCIE] = "pcie",
+	[TEGRA_POWERGATE_L2] = "l2",
+	[TEGRA_POWERGATE_MPE] = "mpe",
+	[TEGRA_POWERGATE_HEG] = "heg",
+	[TEGRA_POWERGATE_SATA] = "sata",
+	[TEGRA_POWERGATE_CPU1] = "cpu1",
+	[TEGRA_POWERGATE_CPU2] = "cpu2",
+	[TEGRA_POWERGATE_CPU3] = "cpu3",
+	[TEGRA_POWERGATE_CELP] = "celp",
+	[TEGRA_POWERGATE_3D1] = "3d1",
+};
+
+static const u8 tegra30_cpu_powergates[] = {
+	TEGRA_POWERGATE_CPU,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+};
+
+static const struct tegra_pmc_soc tegra30_pmc_soc = {
+	.num_powergates = ARRAY_SIZE(tegra30_powergates),
+	.powergates = tegra30_powergates,
+	.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
+	.cpu_powergates = tegra30_cpu_powergates,
+};
+
+static const char * const tegra114_powergates[] = {
+	[TEGRA_POWERGATE_CPU] = "crail",
+	[TEGRA_POWERGATE_3D] = "3d",
+	[TEGRA_POWERGATE_VENC] = "venc",
+	[TEGRA_POWERGATE_VDEC] = "vdec",
+	[TEGRA_POWERGATE_MPE] = "mpe",
+	[TEGRA_POWERGATE_HEG] = "heg",
+	[TEGRA_POWERGATE_CPU1] = "cpu1",
+	[TEGRA_POWERGATE_CPU2] = "cpu2",
+	[TEGRA_POWERGATE_CPU3] = "cpu3",
+	[TEGRA_POWERGATE_CELP] = "celp",
+	[TEGRA_POWERGATE_CPU0] = "cpu0",
+	[TEGRA_POWERGATE_C0NC] = "c0nc",
+	[TEGRA_POWERGATE_C1NC] = "c1nc",
+	[TEGRA_POWERGATE_DIS] = "dis",
+	[TEGRA_POWERGATE_DISB] = "disb",
+	[TEGRA_POWERGATE_XUSBA] = "xusba",
+	[TEGRA_POWERGATE_XUSBB] = "xusbb",
+	[TEGRA_POWERGATE_XUSBC] = "xusbc",
+};
+
+static const u8 tegra114_cpu_powergates[] = {
+	TEGRA_POWERGATE_CPU0,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+};
+
+static const struct tegra_pmc_soc tegra114_pmc_soc = {
+	.num_powergates = ARRAY_SIZE(tegra114_powergates),
+	.powergates = tegra114_powergates,
+	.num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
+	.cpu_powergates = tegra114_cpu_powergates,
+};
+
+static const char * const tegra124_powergates[] = {
+	[TEGRA_POWERGATE_CPU] = "crail",
+	[TEGRA_POWERGATE_3D] = "3d",
+	[TEGRA_POWERGATE_VENC] = "venc",
+	[TEGRA_POWERGATE_PCIE] = "pcie",
+	[TEGRA_POWERGATE_VDEC] = "vdec",
+	[TEGRA_POWERGATE_L2] = "l2",
+	[TEGRA_POWERGATE_MPE] = "mpe",
+	[TEGRA_POWERGATE_HEG] = "heg",
+	[TEGRA_POWERGATE_SATA] = "sata",
+	[TEGRA_POWERGATE_CPU1] = "cpu1",
+	[TEGRA_POWERGATE_CPU2] = "cpu2",
+	[TEGRA_POWERGATE_CPU3] = "cpu3",
+	[TEGRA_POWERGATE_CELP] = "celp",
+	[TEGRA_POWERGATE_CPU0] = "cpu0",
+	[TEGRA_POWERGATE_C0NC] = "c0nc",
+	[TEGRA_POWERGATE_C1NC] = "c1nc",
+	[TEGRA_POWERGATE_SOR] = "sor",
+	[TEGRA_POWERGATE_DIS] = "dis",
+	[TEGRA_POWERGATE_DISB] = "disb",
+	[TEGRA_POWERGATE_XUSBA] = "xusba",
+	[TEGRA_POWERGATE_XUSBB] = "xusbb",
+	[TEGRA_POWERGATE_XUSBC] = "xusbc",
+	[TEGRA_POWERGATE_VIC] = "vic",
+	[TEGRA_POWERGATE_IRAM] = "iram",
+};
+
+static const u8 tegra124_cpu_powergates[] = {
+	TEGRA_POWERGATE_CPU0,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+};
+
+static const struct tegra_pmc_soc tegra124_pmc_soc = {
+	.num_powergates = ARRAY_SIZE(tegra124_powergates),
+	.powergates = tegra124_powergates,
+	.num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
+	.cpu_powergates = tegra124_cpu_powergates,
+};
+
+static const struct of_device_id tegra_pmc_match[] = {
+	{ .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
+	{ .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
+	{ .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
+	{ .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
+	{ }
+};
+
+static struct platform_driver tegra_pmc_driver = {
+	.driver = {
+		.name = "tegra-pmc",
+		.suppress_bind_attrs = true,
+		.of_match_table = tegra_pmc_match,
+		.pm = &tegra_pmc_pm_ops,
+	},
+	.probe = tegra_pmc_probe,
+};
+module_platform_driver(tegra_pmc_driver);
+
+/*
+ * Early initialization to allow access to registers in the very early boot
+ * process.
+ */
+static int __init tegra_pmc_early_init(void)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	struct resource regs;
+	bool invert;
+	u32 value;
+
+	if (!soc_is_tegra())
+		return 0;
+
+	np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
+	if (!np) {
+		pr_warn("PMC device node not found, disabling powergating\n");
+
+		regs.start = 0x7000e400;
+		regs.end = 0x7000e7ff;
+		regs.flags = IORESOURCE_MEM;
+
+		pr_warn("Using memory region %pR\n", &regs);
+	} else {
+		pmc->soc = match->data;
+	}
+
+	if (of_address_to_resource(np, 0, &regs) < 0) {
+		pr_err("failed to get PMC registers\n");
+		return -ENXIO;
+	}
+
+	pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
+	if (!pmc->base) {
+		pr_err("failed to map PMC registers\n");
+		return -ENXIO;
+	}
+
+	mutex_init(&pmc->powergates_lock);
+
+	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
+
+	value = tegra_pmc_readl(PMC_CNTRL);
+
+	if (invert)
+		value |= PMC_CNTRL_INTR_POLARITY;
+	else
+		value &= ~PMC_CNTRL_INTR_POLARITY;
+
+	tegra_pmc_writel(value, PMC_CNTRL);
+
+	return 0;
+}
+early_initcall(tegra_pmc_early_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/Kconfig linux-libre-3.17-rc7-gnu/drivers/spi/Kconfig
--- linux-libre-3.16-gnu/drivers/spi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -382,9 +382,21 @@ config SPI_PXA2XX
 config SPI_PXA2XX_PCI
 	def_tristate SPI_PXA2XX && PCI
 
+config SPI_ROCKCHIP
+	tristate "Rockchip SPI controller driver"
+	depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
+	help
+	  This selects a driver for Rockchip SPI controller.
+
+	  If you say yes to this option, support will be included for
+	  RK3066, RK3188 and RK3288 families of SPI controller.
+	  Rockchip SPI controller support DMA transport and PIO mode.
+	  The main usecase of this controller is to use spi flash as boot
+	  device.
+
 config SPI_RSPI
 	tristate "Renesas RSPI/QSPI controller"
-	depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
+	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
 	help
 	  SPI driver for Renesas RSPI and QSPI blocks.
 
@@ -434,7 +446,7 @@ config SPI_SC18IS602
 
 config SPI_SH_MSIOF
 	tristate "SuperH MSIOF SPI controller"
-	depends on HAVE_CLK
+	depends on HAVE_CLK && HAS_DMA
 	depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
 	help
 	  SPI driver for SuperH and SH Mobile MSIOF blocks.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/Makefile linux-libre-3.17-rc7-gnu/drivers/spi/Makefile
--- linux-libre-3.16-gnu/drivers/spi/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_
 obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx-platform.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
 obj-$(CONFIG_SPI_QUP)			+= spi-qup.o
+obj-$(CONFIG_SPI_ROCKCHIP)		+= spi-rockchip.o
 obj-$(CONFIG_SPI_RSPI)			+= spi-rspi.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y			:= spi-s3c24xx.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-adi-v3.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-adi-v3.c
--- linux-libre-3.16-gnu/drivers/spi/spi-adi-v3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-adi-v3.c	2014-09-28 17:29:07.000000000 -0400
@@ -660,10 +660,9 @@ static int adi_spi_setup(struct spi_devi
 		struct adi_spi3_chip *chip_info = spi->controller_data;
 
 		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-		if (!chip) {
-			dev_err(&spi->dev, "can not allocate chip data\n");
+		if (!chip)
 			return -ENOMEM;
-		}
+
 		if (chip_info) {
 			if (chip_info->control & ~ctl_reg) {
 				dev_err(&spi->dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-atmel.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-atmel.c
--- linux-libre-3.16-gnu/drivers/spi/spi-atmel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-atmel.c	2014-09-28 17:29:07.000000000 -0400
@@ -597,21 +597,15 @@ static int atmel_spi_next_xfer_dma_submi
 		goto err_exit;
 
 	/* Send both scatterlists */
-	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
-					&as->dma.sgrx,
-					1,
-					DMA_FROM_DEVICE,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
-					NULL);
+	rxdesc = dmaengine_prep_slave_sg(rxchan, &as->dma.sgrx, 1,
+					 DMA_FROM_DEVICE,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!rxdesc)
 		goto err_dma;
 
-	txdesc = txchan->device->device_prep_slave_sg(txchan,
-					&as->dma.sgtx,
-					1,
-					DMA_TO_DEVICE,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
-					NULL);
+	txdesc = dmaengine_prep_slave_sg(txchan, &as->dma.sgtx, 1,
+					 DMA_TO_DEVICE,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!txdesc)
 		goto err_dma;
 
@@ -1018,7 +1012,7 @@ static int atmel_spi_setup(struct spi_de
 	csr |= SPI_BF(DLYBCT, 0);
 
 	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned int)spi->controller_data;
+	npcs_pin = (unsigned long)spi->controller_data;
 
 	if (gpio_is_valid(spi->cs_gpio))
 		npcs_pin = spi->cs_gpio;
@@ -1253,7 +1247,7 @@ msg_done:
 static void atmel_spi_cleanup(struct spi_device *spi)
 {
 	struct atmel_spi_device	*asd = spi->controller_state;
-	unsigned		gpio = (unsigned) spi->controller_data;
+	unsigned		gpio = (unsigned long) spi->controller_data;
 
 	if (!asd)
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-au1550.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-au1550.c
--- linux-libre-3.16-gnu/drivers/spi/spi-au1550.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-au1550.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,13 +141,13 @@ static inline void au1550_spi_mask_ack_a
 		  PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
 		| PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
 		| PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_spievent =
 		  PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
 		| PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
 		| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static void au1550_spi_reset_fifos(struct au1550_spi *hw)
@@ -155,10 +155,10 @@ static void au1550_spi_reset_fifos(struc
 	u32 pcr;
 
 	hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	do {
 		pcr = hw->regs->psc_spipcr;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while (pcr != 0);
 }
 
@@ -188,9 +188,9 @@ static void au1550_spi_chipsel(struct sp
 		au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
 		cfg = hw->regs->psc_spicfg;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		if (spi->mode & SPI_CPOL)
 			cfg |= PSC_SPICFG_BI;
@@ -218,10 +218,10 @@ static void au1550_spi_chipsel(struct sp
 		cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
 
 		hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		do {
 			stat = hw->regs->psc_spistat;
-			au_sync();
+			wmb(); /* drain writebuffer */
 		} while ((stat & PSC_SPISTAT_DR) == 0);
 
 		if (hw->pdata->activate_cs)
@@ -252,9 +252,9 @@ static int au1550_spi_setupxfer(struct s
 	au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
 	cfg = hw->regs->psc_spicfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (hw->usedma && bpw <= 8)
 		cfg &= ~PSC_SPICFG_DD_DISABLE;
@@ -268,12 +268,12 @@ static int au1550_spi_setupxfer(struct s
 	cfg |= au1550_spi_baudcfg(hw, hz);
 
 	hw->regs->psc_spicfg = cfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (cfg & PSC_SPICFG_DE_ENABLE) {
 		do {
 			stat = hw->regs->psc_spistat;
-			au_sync();
+			wmb(); /* drain writebuffer */
 		} while ((stat & PSC_SPISTAT_DR) == 0);
 	}
 
@@ -396,11 +396,11 @@ static int au1550_spi_dma_txrxb(struct s
 
 	/* by default enable nearly all events interrupt */
 	hw->regs->psc_spimsk = PSC_SPIMSK_SD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* start the transfer */
 	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	wait_for_completion(&hw->master_done);
 
@@ -429,7 +429,7 @@ static irqreturn_t au1550_spi_dma_irq_ca
 
 	stat = hw->regs->psc_spistat;
 	evnt = hw->regs->psc_spievent;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	if ((stat & PSC_SPISTAT_DI) == 0) {
 		dev_err(hw->dev, "Unexpected IRQ!\n");
 		return IRQ_NONE;
@@ -484,7 +484,7 @@ static irqreturn_t au1550_spi_dma_irq_ca
 static void au1550_spi_rx_word_##size(struct au1550_spi *hw)		\
 {									\
 	u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);		\
-	au_sync();							\
+	wmb(); /* drain writebuffer */					\
 	if (hw->rx) {							\
 		*(u##size *)hw->rx = (u##size)fifoword;			\
 		hw->rx += (size) / 8;					\
@@ -504,7 +504,7 @@ static void au1550_spi_tx_word_##size(st
 	if (hw->tx_count >= hw->len)					\
 		fifoword |= PSC_SPITXRX_LC;				\
 	hw->regs->psc_spitxrx = fifoword;				\
-	au_sync();							\
+	wmb(); /* drain writebuffer */					\
 }
 
 AU1550_SPI_RX_WORD(8,0xff)
@@ -539,18 +539,18 @@ static int au1550_spi_pio_txrxb(struct s
 		}
 
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		if (stat & PSC_SPISTAT_TF)
 			break;
 	}
 
 	/* enable event interrupts */
 	hw->regs->psc_spimsk = mask;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* start the transfer */
 	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	wait_for_completion(&hw->master_done);
 
@@ -564,7 +564,7 @@ static irqreturn_t au1550_spi_pio_irq_ca
 
 	stat = hw->regs->psc_spistat;
 	evnt = hw->regs->psc_spievent;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	if ((stat & PSC_SPISTAT_DI) == 0) {
 		dev_err(hw->dev, "Unexpected IRQ!\n");
 		return IRQ_NONE;
@@ -594,7 +594,7 @@ static irqreturn_t au1550_spi_pio_irq_ca
 	do {
 		busy = 0;
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/*
 		 * Take care to not let the Rx FIFO overflow.
@@ -615,7 +615,7 @@ static irqreturn_t au1550_spi_pio_irq_ca
 	} while (busy);
 
 	hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/*
 	 * Restart the SPI transmission in case of a transmit underflow.
@@ -634,9 +634,9 @@ static irqreturn_t au1550_spi_pio_irq_ca
 	 */
 	if (evnt & PSC_SPIEVNT_TU) {
 		hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 
 	if (hw->rx_count >= hw->len) {
@@ -690,19 +690,19 @@ static void au1550_spi_setup_psc_as_spi(
 
 	/* set up the PSC for SPI mode */
 	hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_spicfg = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	do {
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while ((stat & PSC_SPISTAT_SR) == 0);
 
 
@@ -717,16 +717,16 @@ static void au1550_spi_setup_psc_as_spi(
 #endif
 
 	hw->regs->psc_spicfg = cfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	au1550_spi_mask_ack_all(hw);
 
 	hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	do {
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while ((stat & PSC_SPISTAT_DR) == 0);
 
 	au1550_spi_reset_fifos(hw);
@@ -925,8 +925,7 @@ err_no_txdma:
 	iounmap((void __iomem *)hw->regs);
 
 err_ioremap:
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
+	release_mem_region(r->start, sizeof(psc_spi_t));
 
 err_no_iores:
 err_no_pdata:
@@ -946,8 +945,7 @@ static int au1550_spi_remove(struct plat
 	spi_bitbang_stop(&hw->bitbang);
 	free_irq(hw->irq, hw);
 	iounmap((void __iomem *)hw->regs);
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
+	release_mem_region(hw->ioarea->start, sizeof(psc_spi_t));
 
 	if (hw->usedma) {
 		au1550_spi_dma_rxtmp_free(hw);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi.c
--- linux-libre-3.16-gnu/drivers/spi/spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/clk/clk-conf.h>
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
@@ -259,6 +260,10 @@ static int spi_drv_probe(struct device *
 	const struct spi_driver		*sdrv = to_spi_driver(dev->driver);
 	int ret;
 
+	ret = of_clk_set_defaults(dev->of_node, false);
+	if (ret)
+		return ret;
+
 	acpi_dev_pm_attach(dev, true);
 	ret = sdrv->probe(to_spi_device(dev));
 	if (ret)
@@ -345,14 +350,12 @@ static DEFINE_MUTEX(board_lock);
 struct spi_device *spi_alloc_device(struct spi_master *master)
 {
 	struct spi_device	*spi;
-	struct device		*dev = master->dev.parent;
 
 	if (!spi_master_get(master))
 		return NULL;
 
 	spi = kzalloc(sizeof(*spi), GFP_KERNEL);
 	if (!spi) {
-		dev_err(dev, "cannot alloc spi_device\n");
 		spi_master_put(master);
 		return NULL;
 	}
@@ -619,6 +622,8 @@ static int spi_map_buf(struct spi_master
 	}
 
 	ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
+	if (!ret)
+		ret = -ENOMEM;
 	if (ret < 0) {
 		sg_free_table(sgt);
 		return ret;
@@ -647,8 +652,8 @@ static int __spi_map_msg(struct spi_mast
 	if (!master->can_dma)
 		return 0;
 
-	tx_dev = &master->dma_tx->dev->device;
-	rx_dev = &master->dma_rx->dev->device;
+	tx_dev = master->dma_tx->device->dev;
+	rx_dev = master->dma_rx->device->dev;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -687,8 +692,8 @@ static int spi_unmap_msg(struct spi_mast
 	if (!master->cur_msg_mapped || !master->can_dma)
 		return 0;
 
-	tx_dev = &master->dma_tx->dev->device;
-	rx_dev = &master->dma_rx->dev->device;
+	tx_dev = master->dma_tx->device->dev;
+	rx_dev = master->dma_rx->device->dev;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -843,6 +848,7 @@ out:
 
 /**
  * spi_finalize_current_transfer - report completion of a transfer
+ * @master: the master reporting completion
  *
  * Called by SPI drivers using the core transfer_one_message()
  * implementation to notify it that the current interrupt driven
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-cadence.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-cadence.c
--- linux-libre-3.16-gnu/drivers/spi/spi-cadence.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-cadence.c	2014-09-28 17:29:07.000000000 -0400
@@ -205,18 +205,30 @@ static void cdns_spi_chipselect(struct s
 static void cdns_spi_config_clock_mode(struct spi_device *spi)
 {
 	struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
-	u32 ctrl_reg;
+	u32 ctrl_reg, new_ctrl_reg;
 
-	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
+	new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
 
 	/* Set the SPI clock phase and clock polarity */
-	ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK);
+	new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK);
 	if (spi->mode & SPI_CPHA)
-		ctrl_reg |= CDNS_SPI_CR_CPHA_MASK;
+		new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK;
 	if (spi->mode & SPI_CPOL)
-		ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
+		new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
 
-	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
+	if (new_ctrl_reg != ctrl_reg) {
+		/*
+		 * Just writing the CR register does not seem to apply the clock
+		 * setting changes. This is problematic when changing the clock
+		 * polarity as it will cause the SPI slave to see spurious clock
+		 * transitions. To workaround the issue toggle the ER register.
+		 */
+		cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+				   CDNS_SPI_ER_DISABLE_MASK);
+		cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg);
+		cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+				   CDNS_SPI_ER_ENABLE_MASK);
+	}
 }
 
 /**
@@ -370,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq,
 
 	return status;
 }
+static int cdns_prepare_message(struct spi_master *master,
+				struct spi_message *msg)
+{
+	cdns_spi_config_clock_mode(msg->spi);
+	return 0;
+}
 
 /**
  * cdns_transfer_one - Initiates the SPI transfer
@@ -416,8 +434,6 @@ static int cdns_prepare_transfer_hardwar
 {
 	struct cdns_spi *xspi = spi_master_get_devdata(master);
 
-	cdns_spi_config_clock_mode(master->cur_msg->spi);
-
 	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
 		       CDNS_SPI_ER_ENABLE_MASK);
 
@@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platfor
 		xspi->is_decoded_cs = 0;
 
 	master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
+	master->prepare_message = cdns_prepare_message;
 	master->transfer_one = cdns_transfer_one;
 	master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
 	master->set_cs = cdns_spi_chipselect;
@@ -647,7 +664,7 @@ static int __maybe_unused cdns_spi_resum
 static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend,
 			 cdns_spi_resume);
 
-static struct of_device_id cdns_spi_of_match[] = {
+static const struct of_device_id cdns_spi_of_match[] = {
 	{ .compatible = "xlnx,zynq-spi-r1p6" },
 	{ .compatible = "cdns,spi-r1p6" },
 	{ /* end of table */ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-clps711x.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-clps711x.c
--- linux-libre-3.16-gnu/drivers/spi/spi-clps711x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-clps711x.c	2014-09-28 17:29:07.000000000 -0400
@@ -184,8 +184,6 @@ static int spi_clps711x_probe(struct pla
 	}
 	master->max_speed_hz = clk_get_rate(hw->spi_clk);
 
-	platform_set_drvdata(pdev, master);
-
 	hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3");
 	if (IS_ERR(hw->syscon)) {
 		ret = PTR_ERR(hw->syscon);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-davinci.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-davinci.c
--- linux-libre-3.16-gnu/drivers/spi/spi-davinci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-davinci.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/edma.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/slab.h>
@@ -38,8 +39,6 @@
 
 #define SPI_NO_RESOURCE		((resource_size_t)-1)
 
-#define SPI_MAX_CHIPSELECT	2
-
 #define CS_DEFAULT	0xFF
 
 #define SPIFMT_PHASE_MASK	BIT(16)
@@ -142,7 +141,7 @@ struct davinci_spi {
 	void			(*get_rx)(u32 rx_data, struct davinci_spi *);
 	u32			(*get_tx)(struct davinci_spi *);
 
-	u8			bytes_per_word[SPI_MAX_CHIPSELECT];
+	u8			*bytes_per_word;
 };
 
 static struct davinci_spi_config davinci_spi_default_cfg;
@@ -213,13 +212,16 @@ static void davinci_spi_chipselect(struc
 	u8 chip_sel = spi->chip_select;
 	u16 spidat1 = CS_DEFAULT;
 	bool gpio_chipsel = false;
+	int gpio;
 
 	dspi = spi_master_get_devdata(spi->master);
 	pdata = &dspi->pdata;
 
-	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
-				pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
+	if (spi->cs_gpio >= 0) {
+		/* SPI core parse and update master->cs_gpio */
 		gpio_chipsel = true;
+		gpio = spi->cs_gpio;
+	}
 
 	/*
 	 * Board specific chip select logic decides the polarity and cs
@@ -227,9 +229,9 @@ static void davinci_spi_chipselect(struc
 	 */
 	if (gpio_chipsel) {
 		if (value == BITBANG_CS_ACTIVE)
-			gpio_set_value(pdata->chip_sel[chip_sel], 0);
+			gpio_set_value(gpio, spi->mode & SPI_CS_HIGH);
 		else
-			gpio_set_value(pdata->chip_sel[chip_sel], 1);
+			gpio_set_value(gpio, !(spi->mode & SPI_CS_HIGH));
 	} else {
 		if (value == BITBANG_CS_ACTIVE) {
 			spidat1 |= SPIDAT1_CSHOLD_MASK;
@@ -392,15 +394,35 @@ static int davinci_spi_setup(struct spi_
 	int retval = 0;
 	struct davinci_spi *dspi;
 	struct davinci_spi_platform_data *pdata;
+	struct spi_master *master = spi->master;
+	struct device_node *np = spi->dev.of_node;
+	bool internal_cs = true;
 
 	dspi = spi_master_get_devdata(spi->master);
 	pdata = &dspi->pdata;
 
 	if (!(spi->mode & SPI_NO_CS)) {
-		if ((pdata->chip_sel == NULL) ||
-		    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
-			set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+		if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
+			retval = gpio_direction_output(
+				      spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+			internal_cs = false;
+		} else if (pdata->chip_sel &&
+			   spi->chip_select < pdata->num_chipselect &&
+			   pdata->chip_sel[spi->chip_select] != SPI_INTERN_CS) {
+			spi->cs_gpio = pdata->chip_sel[spi->chip_select];
+			retval = gpio_direction_output(
+				      spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+			internal_cs = false;
+		}
+
+		if (retval) {
+			dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
+				spi->cs_gpio, retval);
+			return retval;
+		}
 
+		if (internal_cs)
+			set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
 	}
 
 	if (spi->mode & SPI_READY)
@@ -812,6 +834,8 @@ static int spi_davinci_get_pdata(struct
 
 	/*
 	 * default num_cs is 1 and all chipsel are internal to the chip
+	 * indicated by chip_sel being NULL or cs_gpios being NULL or
+	 * set to -ENOENT. num-cs includes internal as well as gpios.
 	 * indicated by chip_sel being NULL. GPIO based CS is not
 	 * supported yet in DT bindings.
 	 */
@@ -850,7 +874,7 @@ static int davinci_spi_probe(struct plat
 	struct resource *r;
 	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
 	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
-	int i = 0, ret = 0;
+	int ret = 0;
 	u32 spipc0;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
@@ -876,6 +900,14 @@ static int davinci_spi_probe(struct plat
 	/* pdata in dspi is now updated and point pdata to that */
 	pdata = &dspi->pdata;
 
+	dspi->bytes_per_word = devm_kzalloc(&pdev->dev,
+					    sizeof(*dspi->bytes_per_word) *
+					    pdata->num_chipselect, GFP_KERNEL);
+	if (dspi->bytes_per_word == NULL) {
+		ret = -ENOMEM;
+		goto free_master;
+	}
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		ret = -ENOENT;
@@ -925,6 +957,27 @@ static int davinci_spi_probe(struct plat
 	if (dspi->version == SPI_VERSION_2)
 		dspi->bitbang.flags |= SPI_READY;
 
+	if (pdev->dev.of_node) {
+		int i;
+
+		for (i = 0; i < pdata->num_chipselect; i++) {
+			int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+							"cs-gpios", i);
+
+			if (cs_gpio == -EPROBE_DEFER) {
+				ret = cs_gpio;
+				goto free_clk;
+			}
+
+			if (gpio_is_valid(cs_gpio)) {
+				ret = devm_gpio_request(&pdev->dev, cs_gpio,
+							dev_name(&pdev->dev));
+				if (ret)
+					goto free_clk;
+			}
+		}
+	}
+
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (r)
 		dma_rx_chan = r->start;
@@ -962,14 +1015,6 @@ static int davinci_spi_probe(struct plat
 	spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
 	iowrite32(spipc0, dspi->base + SPIPC0);
 
-	/* initialize chip selects */
-	if (pdata->chip_sel) {
-		for (i = 0; i < pdata->num_chipselect; i++) {
-			if (pdata->chip_sel[i] != SPI_INTERN_CS)
-				gpio_direction_output(pdata->chip_sel[i], 1);
-		}
-	}
-
 	if (pdata->intr_line)
 		iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
 	else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-dw.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw.c
--- linux-libre-3.16-gnu/drivers/spi/spi-dw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw.c	2014-09-28 17:29:07.000000000 -0400
@@ -271,7 +271,7 @@ static void giveback(struct dw_spi *dws)
 					transfer_list);
 
 	if (!last_transfer->cs_change)
-		spi_chip_sel(dws, dws->cur_msg->spi, 0);
+		spi_chip_sel(dws, msg->spi, 0);
 
 	spi_finalize_current_message(dws->master);
 }
@@ -547,8 +547,7 @@ static int dw_spi_setup(struct spi_devic
 	/* Only alloc on first setup */
 	chip = spi_get_ctldata(spi);
 	if (!chip) {
-		chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
-				GFP_KERNEL);
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
 		if (!chip)
 			return -ENOMEM;
 		spi_set_ctldata(spi, chip);
@@ -606,6 +605,14 @@ static int dw_spi_setup(struct spi_devic
 	return 0;
 }
 
+static void dw_spi_cleanup(struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata(spi);
+
+	kfree(chip);
+	spi_set_ctldata(spi, NULL);
+}
+
 /* Restart the controller, disable all interrupts, clean rx fifo */
 static void spi_hw_init(struct dw_spi *dws)
 {
@@ -661,6 +668,7 @@ int dw_spi_add_host(struct device *dev,
 	master->bus_num = dws->bus_num;
 	master->num_chipselect = dws->num_cs;
 	master->setup = dw_spi_setup;
+	master->cleanup = dw_spi_cleanup;
 	master->transfer_one_message = dw_spi_transfer_one_message;
 	master->max_speed_hz = dws->max_freq;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-dw-mmio.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw-mmio.c
--- linux-libre-3.16-gnu/drivers/spi/spi-dw-mmio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw-mmio.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,7 +16,9 @@
 #include <linux/spi/spi.h>
 #include <linux/scatterlist.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/of_platform.h>
 
 #include "spi-dw.h"
 
@@ -33,6 +35,7 @@ static int dw_spi_mmio_probe(struct plat
 	struct dw_spi *dws;
 	struct resource *mem;
 	int ret;
+	int num_cs;
 
 	dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
 			GFP_KERNEL);
@@ -68,9 +71,16 @@ static int dw_spi_mmio_probe(struct plat
 		return ret;
 
 	dws->bus_num = pdev->id;
-	dws->num_cs = 4;
+
 	dws->max_freq = clk_get_rate(dwsmmio->clk);
 
+	num_cs = 4;
+
+	if (pdev->dev.of_node)
+		of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
+
+	dws->num_cs = num_cs;
+
 	if (pdev->dev.of_node) {
 		int i;
 
@@ -114,12 +124,19 @@ static int dw_spi_mmio_remove(struct pla
 	return 0;
 }
 
+static const struct of_device_id dw_spi_mmio_of_match[] = {
+	{ .compatible = "snps,dw-apb-ssi", },
+	{ /* end of table */}
+};
+MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
+
 static struct platform_driver dw_spi_mmio_driver = {
 	.probe		= dw_spi_mmio_probe,
 	.remove		= dw_spi_mmio_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = dw_spi_mmio_of_match,
 	},
 };
 module_platform_driver(dw_spi_mmio_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-dw-pci.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw-pci.c
--- linux-libre-3.16-gnu/drivers/spi/spi-dw-pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-dw-pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,6 +62,8 @@ static int spi_pci_probe(struct pci_dev
 	if (ret)
 		return ret;
 
+	dws->regs = pcim_iomap_table(pdev)[pci_bar];
+
 	dws->bus_num = 0;
 	dws->num_cs = 4;
 	dws->irq = pdev->irq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-efm32.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-efm32.c
--- linux-libre-3.16-gnu/drivers/spi/spi-efm32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-efm32.c	2014-09-28 17:29:07.000000000 -0400
@@ -294,10 +294,16 @@ static void efm32_spi_probe_dt(struct pl
 	u32 location;
 	int ret;
 
-	ret = of_property_read_u32(np, "efm32,location", &location);
+	ret = of_property_read_u32(np, "energymicro,location", &location);
+
+	if (ret)
+		/* fall back to wrongly namespaced property */
+		ret = of_property_read_u32(np, "efm32,location", &location);
+
 	if (ret)
 		/* fall back to old and (wrongly) generic property "location" */
 		ret = of_property_read_u32(np, "location", &location);
+
 	if (!ret) {
 		dev_dbg(&pdev->dev, "using location %u\n", location);
 	} else {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-falcon.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-falcon.c
--- linux-libre-3.16-gnu/drivers/spi/spi-falcon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-falcon.c	2014-09-28 17:29:07.000000000 -0400
@@ -425,8 +425,6 @@ static int falcon_sflash_probe(struct pl
 	master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer;
 	master->dev.of_node = pdev->dev.of_node;
 
-	platform_set_drvdata(pdev, priv);
-
 	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret)
 		spi_master_put(master);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-fsl-espi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-espi.c
--- linux-libre-3.16-gnu/drivers/spi/spi-fsl-espi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-espi.c	2014-09-28 17:29:07.000000000 -0400
@@ -452,16 +452,16 @@ static int fsl_espi_setup(struct spi_dev
 	int retval;
 	u32 hw_mode;
 	u32 loop_mode;
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
 
 	if (!spi->max_speed_hz)
 		return -EINVAL;
 
 	if (!cs) {
-		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
+		cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 		if (!cs)
 			return -ENOMEM;
-		spi->controller_state = cs;
+		spi_set_ctldata(spi, cs);
 	}
 
 	mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -496,6 +496,14 @@ static int fsl_espi_setup(struct spi_dev
 	return 0;
 }
 
+static void fsl_espi_cleanup(struct spi_device *spi)
+{
+	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
+
+	kfree(cs);
+	spi_set_ctldata(spi, NULL);
+}
+
 void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
 	struct fsl_espi_reg *reg_base = mspi->reg_base;
@@ -605,6 +613,7 @@ static struct spi_master * fsl_espi_prob
 
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
 	master->setup = fsl_espi_setup;
+	master->cleanup = fsl_espi_cleanup;
 
 	mpc8xxx_spi = spi_master_get_devdata(master);
 	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-fsl-lib.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-lib.c
--- linux-libre-3.16-gnu/drivers/spi/spi-fsl-lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,7 +196,7 @@ int of_mpc8xxx_spi_probe(struct platform
 
 	pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL);
 	if (!pinfo)
-		return -ENOMEM;
+		return ret;
 
 	pdata = &pinfo->pdata;
 	dev->platform_data = pdata;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-fsl-spi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-spi.c
--- linux-libre-3.16-gnu/drivers/spi/spi-fsl-spi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-fsl-spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -58,7 +58,7 @@ static struct fsl_spi_match_data of_fsl_
 	.type = TYPE_GRLIB,
 };
 
-static struct of_device_id of_fsl_spi_match[] = {
+static const struct of_device_id of_fsl_spi_match[] = {
 	{
 		.compatible = "fsl,spi",
 		.data = &of_fsl_spi_fsl_config,
@@ -425,16 +425,16 @@ static int fsl_spi_setup(struct spi_devi
 	struct fsl_spi_reg *reg_base;
 	int retval;
 	u32 hw_mode;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
 
 	if (!spi->max_speed_hz)
 		return -EINVAL;
 
 	if (!cs) {
-		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
+		cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 		if (!cs)
 			return -ENOMEM;
-		spi->controller_state = cs;
+		spi_set_ctldata(spi, cs);
 	}
 	mpc8xxx_spi = spi_master_get_devdata(spi->master);
 
@@ -496,9 +496,13 @@ static int fsl_spi_setup(struct spi_devi
 static void fsl_spi_cleanup(struct spi_device *spi)
 {
 	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
 
 	if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio))
 		gpio_free(spi->cs_gpio);
+
+	kfree(cs);
+	spi_set_ctldata(spi, NULL);
 }
 
 static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-omap-100k.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap-100k.c
--- linux-libre-3.16-gnu/drivers/spi/spi-omap-100k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap-100k.c	2014-09-28 17:29:07.000000000 -0400
@@ -420,8 +420,6 @@ static int omap1_spi100k_probe(struct pl
 	master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
 	master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
 
-	platform_set_drvdata(pdev, master);
-
 	spi100k = spi_master_get_devdata(master);
 
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-omap2-mcspi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap2-mcspi.c
--- linux-libre-3.16-gnu/drivers/spi/spi-omap2-mcspi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap2-mcspi.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,6 +149,7 @@ struct omap2_mcspi_cs {
 	void __iomem		*base;
 	unsigned long		phys;
 	int			word_len;
+	u16			mode;
 	struct list_head	node;
 	/* Context save and restore shadow register */
 	u32			chconf0, chctrl0;
@@ -328,7 +329,8 @@ static void omap2_mcspi_set_fifo(const s
 disable_fifo:
 	if (t->rx_buf != NULL)
 		chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
-	else
+
+	if (t->tx_buf != NULL)
 		chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
 
 	mcspi_write_chconf0(spi, chconf);
@@ -926,6 +928,8 @@ static int omap2_mcspi_setup_transfer(st
 
 	mcspi_write_chconf0(spi, l);
 
+	cs->mode = spi->mode;
+
 	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
 			speed_hz,
 			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
@@ -998,6 +1002,7 @@ static int omap2_mcspi_setup(struct spi_
 			return -ENOMEM;
 		cs->base = mcspi->base + spi->chip_select * 0x14;
 		cs->phys = mcspi->phys + spi->chip_select * 0x14;
+		cs->mode = 0;
 		cs->chconf0 = 0;
 		cs->chctrl0 = 0;
 		spi->controller_state = cs;
@@ -1079,6 +1084,16 @@ static void omap2_mcspi_work(struct omap
 	cs = spi->controller_state;
 	cd = spi->controller_data;
 
+	/*
+	 * The slave driver could have changed spi->mode in which case
+	 * it will be different from cs->mode (the current hardware setup).
+	 * If so, set par_override (even though its not a parity issue) so
+	 * omap2_mcspi_setup_transfer will be called to configure the hardware
+	 * with the correct mode on the first iteration of the loop below.
+	 */
+	if (spi->mode != cs->mode)
+		par_override = 1;
+
 	omap2_mcspi_set_enable(spi, 0);
 	list_for_each_entry(t, &m->transfers, transfer_list) {
 		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-omap-uwire.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap-uwire.c
--- linux-libre-3.16-gnu/drivers/spi/spi-omap-uwire.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-omap-uwire.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,14 +41,15 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/mach-types.h>
 
 #include <mach/mux.h>
@@ -447,7 +448,6 @@ static void uwire_off(struct uwire_spi *
 {
 	uwire_write_reg(UWIRE_SR3, 0);
 	clk_disable(uwire->ck);
-	clk_put(uwire->ck);
 	spi_master_put(uwire->bitbang.master);
 }
 
@@ -463,7 +463,7 @@ static int uwire_probe(struct platform_d
 
 	uwire = spi_master_get_devdata(master);
 
-	uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
+	uwire_base = devm_ioremap(&pdev->dev, UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
 	if (!uwire_base) {
 		dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
 		spi_master_put(master);
@@ -472,12 +472,11 @@ static int uwire_probe(struct platform_d
 
 	platform_set_drvdata(pdev, uwire);
 
-	uwire->ck = clk_get(&pdev->dev, "fck");
+	uwire->ck = devm_clk_get(&pdev->dev, "fck");
 	if (IS_ERR(uwire->ck)) {
 		status = PTR_ERR(uwire->ck);
 		dev_dbg(&pdev->dev, "no functional clock?\n");
 		spi_master_put(master);
-		iounmap(uwire_base);
 		return status;
 	}
 	clk_enable(uwire->ck);
@@ -507,7 +506,6 @@ static int uwire_probe(struct platform_d
 	status = spi_bitbang_start(&uwire->bitbang);
 	if (status < 0) {
 		uwire_off(uwire);
-		iounmap(uwire_base);
 	}
 	return status;
 }
@@ -520,7 +518,6 @@ static int uwire_remove(struct platform_
 
 	spi_bitbang_stop(&uwire->bitbang);
 	uwire_off(uwire);
-	iounmap(uwire_base);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-orion.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-orion.c
--- linux-libre-3.16-gnu/drivers/spi/spi-orion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-orion.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/spi/spi.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -23,6 +24,9 @@
 
 #define DRIVER_NAME			"orion_spi"
 
+/* Runtime PM autosuspend timeout: PM is fairly light on this driver */
+#define SPI_AUTOSUSPEND_TIMEOUT		200
+
 #define ORION_NUM_CHIPSELECTS		1 /* only one slave is supported*/
 #define ORION_SPI_WAIT_RDY_MAX_LOOP	2000 /* in usec */
 
@@ -277,7 +281,6 @@ out:
 	return xfer->len - count;
 }
 
-
 static int orion_spi_transfer_one_message(struct spi_master *master,
 					   struct spi_message *m)
 {
@@ -346,8 +349,6 @@ static int orion_spi_probe(struct platfo
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
-	const u32 *iprop;
-	int size;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -358,10 +359,10 @@ static int orion_spi_probe(struct platfo
 	if (pdev->id != -1)
 		master->bus_num = pdev->id;
 	if (pdev->dev.of_node) {
-		iprop = of_get_property(pdev->dev.of_node, "cell-index",
-					&size);
-		if (iprop && size == sizeof(*iprop))
-			master->bus_num = *iprop;
+		u32 cell_index;
+		if (!of_property_read_u32(pdev->dev.of_node, "cell-index",
+					  &cell_index))
+			master->bus_num = cell_index;
 	}
 
 	/* we support only mode 0, and no options */
@@ -370,6 +371,7 @@ static int orion_spi_probe(struct platfo
 	master->transfer_one_message = orion_spi_transfer_one_message;
 	master->num_chipselect = ORION_NUM_CHIPSELECTS;
 	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
+	master->auto_runtime_pm = true;
 
 	platform_set_drvdata(pdev, master);
 
@@ -382,8 +384,10 @@ static int orion_spi_probe(struct platfo
 		goto out;
 	}
 
-	clk_prepare(spi->clk);
-	clk_enable(spi->clk);
+	status = clk_prepare_enable(spi->clk);
+	if (status)
+		goto out;
+
 	tclk_hz = clk_get_rate(spi->clk);
 	master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
 	master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
@@ -395,16 +399,27 @@ static int orion_spi_probe(struct platfo
 		goto out_rel_clk;
 	}
 
-	if (orion_spi_reset(spi) < 0)
-		goto out_rel_clk;
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
+	pm_runtime_enable(&pdev->dev);
+
+	status = orion_spi_reset(spi);
+	if (status < 0)
+		goto out_rel_pm;
+
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(&pdev->dev);
 
 	master->dev.of_node = pdev->dev.of_node;
-	status = devm_spi_register_master(&pdev->dev, master);
+	status = spi_register_master(master);
 	if (status < 0)
-		goto out_rel_clk;
+		goto out_rel_pm;
 
 	return status;
 
+out_rel_pm:
+	pm_runtime_disable(&pdev->dev);
 out_rel_clk:
 	clk_disable_unprepare(spi->clk);
 out:
@@ -415,19 +430,45 @@ out:
 
 static int orion_spi_remove(struct platform_device *pdev)
 {
-	struct spi_master *master;
-	struct orion_spi *spi;
-
-	master = platform_get_drvdata(pdev);
-	spi = spi_master_get_devdata(master);
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct orion_spi *spi = spi_master_get_devdata(master);
 
+	pm_runtime_get_sync(&pdev->dev);
 	clk_disable_unprepare(spi->clk);
 
+	spi_unregister_master(master);
+	pm_runtime_disable(&pdev->dev);
+
 	return 0;
 }
 
 MODULE_ALIAS("platform:" DRIVER_NAME);
 
+#ifdef CONFIG_PM_RUNTIME
+static int orion_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct orion_spi *spi = spi_master_get_devdata(master);
+
+	clk_disable_unprepare(spi->clk);
+	return 0;
+}
+
+static int orion_spi_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct orion_spi *spi = spi_master_get_devdata(master);
+
+	return clk_prepare_enable(spi->clk);
+}
+#endif
+
+static const struct dev_pm_ops orion_spi_pm_ops = {
+	SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend,
+			   orion_spi_runtime_resume,
+			   NULL)
+};
+
 static const struct of_device_id orion_spi_of_match_table[] = {
 	{ .compatible = "marvell,orion-spi", },
 	{}
@@ -438,6 +479,7 @@ static struct platform_driver orion_spi_
 	.driver = {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.pm	= &orion_spi_pm_ops,
 		.of_match_table = of_match_ptr(orion_spi_of_match_table),
 	},
 	.probe		= orion_spi_probe,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-pl022.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-pl022.c
--- linux-libre-3.16-gnu/drivers/spi/spi-pl022.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-pl022.c	2014-09-28 17:29:07.000000000 -0400
@@ -1417,7 +1417,7 @@ static void do_interrupt_dma_transfer(st
 	 * Default is to enable all interrupts except RX -
 	 * this will be enabled once TX is complete
 	 */
-	u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM;
+	u32 irqflags = (u32)(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM);
 
 	/* Enable target chip, if not already active */
 	if (!pl022->next_msg_cs_active)
@@ -2136,7 +2136,7 @@ static int pl022_probe(struct amba_devic
 						cs_gpio);
 				else if (gpio_direction_output(cs_gpio, 1))
 					dev_err(&adev->dev,
-						"could set gpio %d as output\n",
+						"could not set gpio %d as output\n",
 						cs_gpio);
 			}
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-pxa2xx.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-pxa2xx.c
--- linux-libre-3.16-gnu/drivers/spi/spi-pxa2xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-pxa2xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1074,6 +1074,7 @@ static struct acpi_device_id pxa2xx_spi_
 	{ "INT3430", 0 },
 	{ "INT3431", 0 },
 	{ "80860F0E", 0 },
+	{ "8086228E", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-qup.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-qup.c
--- linux-libre-3.16-gnu/drivers/spi/spi-qup.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-qup.c	2014-09-28 17:29:07.000000000 -0400
@@ -142,6 +142,7 @@ struct spi_qup {
 	int			w_size;	/* bytes per SPI word */
 	int			tx_bytes;
 	int			rx_bytes;
+	int			qup_v1;
 };
 
 
@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_
 	config |= QUP_CONFIG_SPI_MODE;
 	writel_relaxed(config, controller->base + QUP_CONFIG);
 
-	writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
+	/* only write to OPERATIONAL_MASK when register is present */
+	if (!controller->qup_v1)
+		writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
 	return 0;
 }
 
@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform
 	struct resource *res;
 	struct device *dev;
 	void __iomem *base;
-	u32 data, max_freq, iomode;
+	u32 max_freq, iomode;
 	int ret, irq, size;
 
 	dev = &pdev->dev;
@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform
 		return ret;
 	}
 
-	data = readl_relaxed(base + QUP_HW_VERSION);
-
-	if (data < QUP_HW_VERSION_2_1_1) {
-		clk_disable_unprepare(cclk);
-		clk_disable_unprepare(iclk);
-		dev_err(dev, "v.%08x is not supported\n", data);
-		return -ENXIO;
-	}
-
 	master = spi_alloc_master(dev, sizeof(struct spi_qup));
 	if (!master) {
 		clk_disable_unprepare(cclk);
@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform
 	controller->cclk = cclk;
 	controller->irq = irq;
 
+	/* set v1 flag if device is version 1 */
+	if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
+		controller->qup_v1 = 1;
+
 	spin_lock_init(&controller->lock);
 	init_completion(&controller->done);
 
@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform
 	size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
 	controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
 
-	dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
-		 data, controller->in_blk_sz, controller->in_fifo_sz,
+	dev_info(dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
+		 controller->in_blk_sz, controller->in_fifo_sz,
 		 controller->out_blk_sz, controller->out_fifo_sz);
 
 	writel_relaxed(1, base + QUP_SW_RESET);
@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform
 
 	writel_relaxed(0, base + QUP_OPERATIONAL);
 	writel_relaxed(0, base + QUP_IO_M_MODES);
-	writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
+
+	if (!controller->qup_v1)
+		writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
+
 	writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
 		       base + SPI_ERROR_FLAGS_EN);
 
+	/* if earlier version of the QUP, disable INPUT_OVERRUN */
+	if (controller->qup_v1)
+		writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN |
+			QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN,
+			base + QUP_ERROR_FLAGS_EN);
+
 	writel_relaxed(0, base + SPI_CONFIG);
 	writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
 
@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platfor
 }
 
 static const struct of_device_id spi_qup_dt_match[] = {
+	{ .compatible = "qcom,spi-qup-v1.1.1", },
 	{ .compatible = "qcom,spi-qup-v2.1.1", },
 	{ .compatible = "qcom,spi-qup-v2.2.1", },
 	{ }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-rockchip.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-rockchip.c
--- linux-libre-3.16-gnu/drivers/spi/spi-rockchip.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-rockchip.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,838 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Addy Ke <addy.ke@rock-chips.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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/scatterlist.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/io.h>
+#include <linux/dmaengine.h>
+
+#define DRIVER_NAME "rockchip-spi"
+
+/* SPI register offsets */
+#define ROCKCHIP_SPI_CTRLR0			0x0000
+#define ROCKCHIP_SPI_CTRLR1			0x0004
+#define ROCKCHIP_SPI_SSIENR			0x0008
+#define ROCKCHIP_SPI_SER			0x000c
+#define ROCKCHIP_SPI_BAUDR			0x0010
+#define ROCKCHIP_SPI_TXFTLR			0x0014
+#define ROCKCHIP_SPI_RXFTLR			0x0018
+#define ROCKCHIP_SPI_TXFLR			0x001c
+#define ROCKCHIP_SPI_RXFLR			0x0020
+#define ROCKCHIP_SPI_SR				0x0024
+#define ROCKCHIP_SPI_IPR			0x0028
+#define ROCKCHIP_SPI_IMR			0x002c
+#define ROCKCHIP_SPI_ISR			0x0030
+#define ROCKCHIP_SPI_RISR			0x0034
+#define ROCKCHIP_SPI_ICR			0x0038
+#define ROCKCHIP_SPI_DMACR			0x003c
+#define ROCKCHIP_SPI_DMATDLR		0x0040
+#define ROCKCHIP_SPI_DMARDLR		0x0044
+#define ROCKCHIP_SPI_TXDR			0x0400
+#define ROCKCHIP_SPI_RXDR			0x0800
+
+/* Bit fields in CTRLR0 */
+#define CR0_DFS_OFFSET				0
+
+#define CR0_CFS_OFFSET				2
+
+#define CR0_SCPH_OFFSET				6
+
+#define CR0_SCPOL_OFFSET			7
+
+#define CR0_CSM_OFFSET				8
+#define CR0_CSM_KEEP				0x0
+/* ss_n be high for half sclk_out cycles */
+#define CR0_CSM_HALF				0X1
+/* ss_n be high for one sclk_out cycle */
+#define CR0_CSM_ONE					0x2
+
+/* ss_n to sclk_out delay */
+#define CR0_SSD_OFFSET				10
+/*
+ * The period between ss_n active and
+ * sclk_out active is half sclk_out cycles
+ */
+#define CR0_SSD_HALF				0x0
+/*
+ * The period between ss_n active and
+ * sclk_out active is one sclk_out cycle
+ */
+#define CR0_SSD_ONE					0x1
+
+#define CR0_EM_OFFSET				11
+#define CR0_EM_LITTLE				0x0
+#define CR0_EM_BIG					0x1
+
+#define CR0_FBM_OFFSET				12
+#define CR0_FBM_MSB					0x0
+#define CR0_FBM_LSB					0x1
+
+#define CR0_BHT_OFFSET				13
+#define CR0_BHT_16BIT				0x0
+#define CR0_BHT_8BIT				0x1
+
+#define CR0_RSD_OFFSET				14
+
+#define CR0_FRF_OFFSET				16
+#define CR0_FRF_SPI					0x0
+#define CR0_FRF_SSP					0x1
+#define CR0_FRF_MICROWIRE			0x2
+
+#define CR0_XFM_OFFSET				18
+#define CR0_XFM_MASK				(0x03 << SPI_XFM_OFFSET)
+#define CR0_XFM_TR					0x0
+#define CR0_XFM_TO					0x1
+#define CR0_XFM_RO					0x2
+
+#define CR0_OPM_OFFSET				20
+#define CR0_OPM_MASTER				0x0
+#define CR0_OPM_SLAVE				0x1
+
+#define CR0_MTM_OFFSET				0x21
+
+/* Bit fields in SER, 2bit */
+#define SER_MASK					0x3
+
+/* Bit fields in SR, 5bit */
+#define SR_MASK						0x1f
+#define SR_BUSY						(1 << 0)
+#define SR_TF_FULL					(1 << 1)
+#define SR_TF_EMPTY					(1 << 2)
+#define SR_RF_EMPTY					(1 << 3)
+#define SR_RF_FULL					(1 << 4)
+
+/* Bit fields in ISR, IMR, ISR, RISR, 5bit */
+#define INT_MASK					0x1f
+#define INT_TF_EMPTY				(1 << 0)
+#define INT_TF_OVERFLOW				(1 << 1)
+#define INT_RF_UNDERFLOW			(1 << 2)
+#define INT_RF_OVERFLOW				(1 << 3)
+#define INT_RF_FULL					(1 << 4)
+
+/* Bit fields in ICR, 4bit */
+#define ICR_MASK					0x0f
+#define ICR_ALL						(1 << 0)
+#define ICR_RF_UNDERFLOW			(1 << 1)
+#define ICR_RF_OVERFLOW				(1 << 2)
+#define ICR_TF_OVERFLOW				(1 << 3)
+
+/* Bit fields in DMACR */
+#define RF_DMA_EN					(1 << 0)
+#define TF_DMA_EN					(1 << 1)
+
+#define RXBUSY						(1 << 0)
+#define TXBUSY						(1 << 1)
+
+enum rockchip_ssi_type {
+	SSI_MOTO_SPI = 0,
+	SSI_TI_SSP,
+	SSI_NS_MICROWIRE,
+};
+
+struct rockchip_spi_dma_data {
+	struct dma_chan *ch;
+	enum dma_transfer_direction direction;
+	dma_addr_t addr;
+};
+
+struct rockchip_spi {
+	struct device *dev;
+	struct spi_master *master;
+
+	struct clk *spiclk;
+	struct clk *apb_pclk;
+
+	void __iomem *regs;
+	/*depth of the FIFO buffer */
+	u32 fifo_len;
+	/* max bus freq supported */
+	u32 max_freq;
+	/* supported slave numbers */
+	enum rockchip_ssi_type type;
+
+	u16 mode;
+	u8 tmode;
+	u8 bpw;
+	u8 n_bytes;
+	unsigned len;
+	u32 speed;
+
+	const void *tx;
+	const void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	u32 state;
+	/* protect state */
+	spinlock_t lock;
+
+	struct completion xfer_completion;
+
+	u32 use_dma;
+	struct sg_table tx_sg;
+	struct sg_table rx_sg;
+	struct rockchip_spi_dma_data dma_rx;
+	struct rockchip_spi_dma_data dma_tx;
+};
+
+static inline void spi_enable_chip(struct rockchip_spi *rs, int enable)
+{
+	writel_relaxed((enable ? 1 : 0), rs->regs + ROCKCHIP_SPI_SSIENR);
+}
+
+static inline void spi_set_clk(struct rockchip_spi *rs, u16 div)
+{
+	writel_relaxed(div, rs->regs + ROCKCHIP_SPI_BAUDR);
+}
+
+static inline void flush_fifo(struct rockchip_spi *rs)
+{
+	while (readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR))
+		readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+}
+
+static inline void wait_for_idle(struct rockchip_spi *rs)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+
+	do {
+		if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))
+			return;
+	} while (!time_after(jiffies, timeout));
+
+	dev_warn(rs->dev, "spi controller is in busy state!\n");
+}
+
+static u32 get_fifo_len(struct rockchip_spi *rs)
+{
+	u32 fifo;
+
+	for (fifo = 2; fifo < 32; fifo++) {
+		writel_relaxed(fifo, rs->regs + ROCKCHIP_SPI_TXFTLR);
+		if (fifo != readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFTLR))
+			break;
+	}
+
+	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_TXFTLR);
+
+	return (fifo == 31) ? 0 : fifo;
+}
+
+static inline u32 tx_max(struct rockchip_spi *rs)
+{
+	u32 tx_left, tx_room;
+
+	tx_left = (rs->tx_end - rs->tx) / rs->n_bytes;
+	tx_room = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
+
+	return min(tx_left, tx_room);
+}
+
+static inline u32 rx_max(struct rockchip_spi *rs)
+{
+	u32 rx_left = (rs->rx_end - rs->rx) / rs->n_bytes;
+	u32 rx_room = (u32)readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
+
+	return min(rx_left, rx_room);
+}
+
+static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	u32 ser;
+	struct rockchip_spi *rs = spi_master_get_devdata(spi->master);
+
+	ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK;
+
+	/*
+	 * drivers/spi/spi.c:
+	 * static void spi_set_cs(struct spi_device *spi, bool enable)
+	 * {
+	 *		if (spi->mode & SPI_CS_HIGH)
+	 *			enable = !enable;
+	 *
+	 *		if (spi->cs_gpio >= 0)
+	 *			gpio_set_value(spi->cs_gpio, !enable);
+	 *		else if (spi->master->set_cs)
+	 *		spi->master->set_cs(spi, !enable);
+	 * }
+	 *
+	 * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs)
+	 */
+	if (!enable)
+		ser |= 1 << spi->chip_select;
+	else
+		ser &= ~(1 << spi->chip_select);
+
+	writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER);
+}
+
+static int rockchip_spi_prepare_message(struct spi_master *master,
+					struct spi_message *msg)
+{
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+	struct spi_device *spi = msg->spi;
+
+	rs->mode = spi->mode;
+
+	return 0;
+}
+
+static int rockchip_spi_unprepare_message(struct spi_master *master,
+					  struct spi_message *msg)
+{
+	unsigned long flags;
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	spin_lock_irqsave(&rs->lock, flags);
+
+	/*
+	 * For DMA mode, we need terminate DMA channel and flush
+	 * fifo for the next transfer if DMA thansfer timeout.
+	 * unprepare_message() was called by core if transfer complete
+	 * or timeout. Maybe it is reasonable for error handling here.
+	 */
+	if (rs->use_dma) {
+		if (rs->state & RXBUSY) {
+			dmaengine_terminate_all(rs->dma_rx.ch);
+			flush_fifo(rs);
+		}
+
+		if (rs->state & TXBUSY)
+			dmaengine_terminate_all(rs->dma_tx.ch);
+	}
+
+	spin_unlock_irqrestore(&rs->lock, flags);
+
+	return 0;
+}
+
+static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
+{
+	u32 max = tx_max(rs);
+	u32 txw = 0;
+
+	while (max--) {
+		if (rs->n_bytes == 1)
+			txw = *(u8 *)(rs->tx);
+		else
+			txw = *(u16 *)(rs->tx);
+
+		writel_relaxed(txw, rs->regs + ROCKCHIP_SPI_TXDR);
+		rs->tx += rs->n_bytes;
+	}
+}
+
+static void rockchip_spi_pio_reader(struct rockchip_spi *rs)
+{
+	u32 max = rx_max(rs);
+	u32 rxw;
+
+	while (max--) {
+		rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+		if (rs->n_bytes == 1)
+			*(u8 *)(rs->rx) = (u8)rxw;
+		else
+			*(u16 *)(rs->rx) = (u16)rxw;
+		rs->rx += rs->n_bytes;
+	}
+}
+
+static int rockchip_spi_pio_transfer(struct rockchip_spi *rs)
+{
+	int remain = 0;
+
+	do {
+		if (rs->tx) {
+			remain = rs->tx_end - rs->tx;
+			rockchip_spi_pio_writer(rs);
+		}
+
+		if (rs->rx) {
+			remain = rs->rx_end - rs->rx;
+			rockchip_spi_pio_reader(rs);
+		}
+
+		cpu_relax();
+	} while (remain);
+
+	/* If tx, wait until the FIFO data completely. */
+	if (rs->tx)
+		wait_for_idle(rs);
+
+	return 0;
+}
+
+static void rockchip_spi_dma_rxcb(void *data)
+{
+	unsigned long flags;
+	struct rockchip_spi *rs = data;
+
+	spin_lock_irqsave(&rs->lock, flags);
+
+	rs->state &= ~RXBUSY;
+	if (!(rs->state & TXBUSY))
+		spi_finalize_current_transfer(rs->master);
+
+	spin_unlock_irqrestore(&rs->lock, flags);
+}
+
+static void rockchip_spi_dma_txcb(void *data)
+{
+	unsigned long flags;
+	struct rockchip_spi *rs = data;
+
+	/* Wait until the FIFO data completely. */
+	wait_for_idle(rs);
+
+	spin_lock_irqsave(&rs->lock, flags);
+
+	rs->state &= ~TXBUSY;
+	if (!(rs->state & RXBUSY))
+		spi_finalize_current_transfer(rs->master);
+
+	spin_unlock_irqrestore(&rs->lock, flags);
+}
+
+static int rockchip_spi_dma_transfer(struct rockchip_spi *rs)
+{
+	unsigned long flags;
+	struct dma_slave_config rxconf, txconf;
+	struct dma_async_tx_descriptor *rxdesc, *txdesc;
+
+	spin_lock_irqsave(&rs->lock, flags);
+	rs->state &= ~RXBUSY;
+	rs->state &= ~TXBUSY;
+	spin_unlock_irqrestore(&rs->lock, flags);
+
+	if (rs->rx) {
+		rxconf.direction = rs->dma_rx.direction;
+		rxconf.src_addr = rs->dma_rx.addr;
+		rxconf.src_addr_width = rs->n_bytes;
+		rxconf.src_maxburst = rs->n_bytes;
+		dmaengine_slave_config(rs->dma_rx.ch, &rxconf);
+
+		rxdesc = dmaengine_prep_slave_sg(
+				rs->dma_rx.ch,
+				rs->rx_sg.sgl, rs->rx_sg.nents,
+				rs->dma_rx.direction, DMA_PREP_INTERRUPT);
+
+		rxdesc->callback = rockchip_spi_dma_rxcb;
+		rxdesc->callback_param = rs;
+	}
+
+	if (rs->tx) {
+		txconf.direction = rs->dma_tx.direction;
+		txconf.dst_addr = rs->dma_tx.addr;
+		txconf.dst_addr_width = rs->n_bytes;
+		txconf.dst_maxburst = rs->n_bytes;
+		dmaengine_slave_config(rs->dma_tx.ch, &txconf);
+
+		txdesc = dmaengine_prep_slave_sg(
+				rs->dma_tx.ch,
+				rs->tx_sg.sgl, rs->tx_sg.nents,
+				rs->dma_tx.direction, DMA_PREP_INTERRUPT);
+
+		txdesc->callback = rockchip_spi_dma_txcb;
+		txdesc->callback_param = rs;
+	}
+
+	/* rx must be started before tx due to spi instinct */
+	if (rs->rx) {
+		spin_lock_irqsave(&rs->lock, flags);
+		rs->state |= RXBUSY;
+		spin_unlock_irqrestore(&rs->lock, flags);
+		dmaengine_submit(rxdesc);
+		dma_async_issue_pending(rs->dma_rx.ch);
+	}
+
+	if (rs->tx) {
+		spin_lock_irqsave(&rs->lock, flags);
+		rs->state |= TXBUSY;
+		spin_unlock_irqrestore(&rs->lock, flags);
+		dmaengine_submit(txdesc);
+		dma_async_issue_pending(rs->dma_tx.ch);
+	}
+
+	return 1;
+}
+
+static void rockchip_spi_config(struct rockchip_spi *rs)
+{
+	u32 div = 0;
+	u32 dmacr = 0;
+
+	u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET)
+		| (CR0_SSD_ONE << CR0_SSD_OFFSET);
+
+	cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
+	cr0 |= ((rs->mode & 0x3) << CR0_SCPH_OFFSET);
+	cr0 |= (rs->tmode << CR0_XFM_OFFSET);
+	cr0 |= (rs->type << CR0_FRF_OFFSET);
+
+	if (rs->use_dma) {
+		if (rs->tx)
+			dmacr |= TF_DMA_EN;
+		if (rs->rx)
+			dmacr |= RF_DMA_EN;
+	}
+
+	/* div doesn't support odd number */
+	div = max_t(u32, rs->max_freq / rs->speed, 1);
+	div = (div + 1) & 0xfffe;
+
+	spi_enable_chip(rs, 0);
+
+	writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+	writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
+	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);
+	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
+
+	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMATDLR);
+	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
+	writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
+
+	spi_set_clk(rs, div);
+
+	dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
+
+	spi_enable_chip(rs, 1);
+}
+
+static int rockchip_spi_transfer_one(
+		struct spi_master *master,
+		struct spi_device *spi,
+		struct spi_transfer *xfer)
+{
+	int ret = 0;
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
+		(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY));
+
+	if (!xfer->tx_buf && !xfer->rx_buf) {
+		dev_err(rs->dev, "No buffer for transfer\n");
+		return -EINVAL;
+	}
+
+	rs->speed = xfer->speed_hz;
+	rs->bpw = xfer->bits_per_word;
+	rs->n_bytes = rs->bpw >> 3;
+
+	rs->tx = xfer->tx_buf;
+	rs->tx_end = rs->tx + xfer->len;
+	rs->rx = xfer->rx_buf;
+	rs->rx_end = rs->rx + xfer->len;
+	rs->len = xfer->len;
+
+	rs->tx_sg = xfer->tx_sg;
+	rs->rx_sg = xfer->rx_sg;
+
+	if (rs->tx && rs->rx)
+		rs->tmode = CR0_XFM_TR;
+	else if (rs->tx)
+		rs->tmode = CR0_XFM_TO;
+	else if (rs->rx)
+		rs->tmode = CR0_XFM_RO;
+
+	if (master->can_dma && master->can_dma(master, spi, xfer))
+		rs->use_dma = 1;
+	else
+		rs->use_dma = 0;
+
+	rockchip_spi_config(rs);
+
+	if (rs->use_dma)
+		ret = rockchip_spi_dma_transfer(rs);
+	else
+		ret = rockchip_spi_pio_transfer(rs);
+
+	return ret;
+}
+
+static bool rockchip_spi_can_dma(struct spi_master *master,
+				 struct spi_device *spi,
+				 struct spi_transfer *xfer)
+{
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	return (xfer->len > rs->fifo_len);
+}
+
+static int rockchip_spi_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct rockchip_spi *rs;
+	struct spi_master *master;
+	struct resource *mem;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi));
+	if (!master)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, master);
+
+	rs = spi_master_get_devdata(master);
+	memset(rs, 0, sizeof(struct rockchip_spi));
+
+	/* Get basic io resource and map it */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rs->regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(rs->regs)) {
+		ret =  PTR_ERR(rs->regs);
+		goto err_ioremap_resource;
+	}
+
+	rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk");
+	if (IS_ERR(rs->apb_pclk)) {
+		dev_err(&pdev->dev, "Failed to get apb_pclk\n");
+		ret = PTR_ERR(rs->apb_pclk);
+		goto err_ioremap_resource;
+	}
+
+	rs->spiclk = devm_clk_get(&pdev->dev, "spiclk");
+	if (IS_ERR(rs->spiclk)) {
+		dev_err(&pdev->dev, "Failed to get spi_pclk\n");
+		ret = PTR_ERR(rs->spiclk);
+		goto err_ioremap_resource;
+	}
+
+	ret = clk_prepare_enable(rs->apb_pclk);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
+		goto err_ioremap_resource;
+	}
+
+	ret = clk_prepare_enable(rs->spiclk);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to enable spi_clk\n");
+		goto err_spiclk_enable;
+	}
+
+	spi_enable_chip(rs, 0);
+
+	rs->type = SSI_MOTO_SPI;
+	rs->master = master;
+	rs->dev = &pdev->dev;
+	rs->max_freq = clk_get_rate(rs->spiclk);
+
+	rs->fifo_len = get_fifo_len(rs);
+	if (!rs->fifo_len) {
+		dev_err(&pdev->dev, "Failed to get fifo length\n");
+		ret = -EINVAL;
+		goto err_get_fifo_len;
+	}
+
+	spin_lock_init(&rs->lock);
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	master->auto_runtime_pm = true;
+	master->bus_num = pdev->id;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
+	master->num_chipselect = 2;
+	master->dev.of_node = pdev->dev.of_node;
+	master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
+
+	master->set_cs = rockchip_spi_set_cs;
+	master->prepare_message = rockchip_spi_prepare_message;
+	master->unprepare_message = rockchip_spi_unprepare_message;
+	master->transfer_one = rockchip_spi_transfer_one;
+
+	rs->dma_tx.ch = dma_request_slave_channel(rs->dev, "tx");
+	if (!rs->dma_tx.ch)
+		dev_warn(rs->dev, "Failed to request TX DMA channel\n");
+
+	rs->dma_rx.ch = dma_request_slave_channel(rs->dev, "rx");
+	if (!rs->dma_rx.ch) {
+		if (rs->dma_tx.ch) {
+			dma_release_channel(rs->dma_tx.ch);
+			rs->dma_tx.ch = NULL;
+		}
+		dev_warn(rs->dev, "Failed to request RX DMA channel\n");
+	}
+
+	if (rs->dma_tx.ch && rs->dma_rx.ch) {
+		rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
+		rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
+		rs->dma_tx.direction = DMA_MEM_TO_DEV;
+		rs->dma_rx.direction = DMA_DEV_TO_MEM;
+
+		master->can_dma = rockchip_spi_can_dma;
+		master->dma_tx = rs->dma_tx.ch;
+		master->dma_rx = rs->dma_rx.ch;
+	}
+
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register master\n");
+		goto err_register_master;
+	}
+
+	return 0;
+
+err_register_master:
+	if (rs->dma_tx.ch)
+		dma_release_channel(rs->dma_tx.ch);
+	if (rs->dma_rx.ch)
+		dma_release_channel(rs->dma_rx.ch);
+err_get_fifo_len:
+	clk_disable_unprepare(rs->spiclk);
+err_spiclk_enable:
+	clk_disable_unprepare(rs->apb_pclk);
+err_ioremap_resource:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int rockchip_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	pm_runtime_disable(&pdev->dev);
+
+	clk_disable_unprepare(rs->spiclk);
+	clk_disable_unprepare(rs->apb_pclk);
+
+	if (rs->dma_tx.ch)
+		dma_release_channel(rs->dma_tx.ch);
+	if (rs->dma_rx.ch)
+		dma_release_channel(rs->dma_rx.ch);
+
+	spi_master_put(master);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_spi_suspend(struct device *dev)
+{
+	int ret = 0;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	ret = spi_master_suspend(rs->master);
+	if (ret)
+		return ret;
+
+	if (!pm_runtime_suspended(dev)) {
+		clk_disable_unprepare(rs->spiclk);
+		clk_disable_unprepare(rs->apb_pclk);
+	}
+
+	return ret;
+}
+
+static int rockchip_spi_resume(struct device *dev)
+{
+	int ret = 0;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	if (!pm_runtime_suspended(dev)) {
+		ret = clk_prepare_enable(rs->apb_pclk);
+		if (ret < 0)
+			return ret;
+
+		ret = clk_prepare_enable(rs->spiclk);
+		if (ret < 0) {
+			clk_disable_unprepare(rs->apb_pclk);
+			return ret;
+		}
+	}
+
+	ret = spi_master_resume(rs->master);
+	if (ret < 0) {
+		clk_disable_unprepare(rs->spiclk);
+		clk_disable_unprepare(rs->apb_pclk);
+	}
+
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int rockchip_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	clk_disable_unprepare(rs->spiclk);
+	clk_disable_unprepare(rs->apb_pclk);
+
+	return 0;
+}
+
+static int rockchip_spi_runtime_resume(struct device *dev)
+{
+	int ret;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+	ret = clk_prepare_enable(rs->apb_pclk);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(rs->spiclk);
+	if (ret)
+		clk_disable_unprepare(rs->apb_pclk);
+
+	return ret;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops rockchip_spi_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
+	SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,
+			   rockchip_spi_runtime_resume, NULL)
+};
+
+static const struct of_device_id rockchip_spi_dt_match[] = {
+	{ .compatible = "rockchip,rk3066-spi", },
+	{ .compatible = "rockchip,rk3188-spi", },
+	{ .compatible = "rockchip,rk3288-spi", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
+
+static struct platform_driver rockchip_spi_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = &rockchip_spi_pm,
+		.of_match_table = of_match_ptr(rockchip_spi_dt_match),
+	},
+	.probe = rockchip_spi_probe,
+	.remove = rockchip_spi_remove,
+};
+
+module_platform_driver(rockchip_spi_driver);
+
+MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>");
+MODULE_DESCRIPTION("ROCKCHIP SPI Controller Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-rspi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-rspi.c
--- linux-libre-3.16-gnu/drivers/spi/spi-rspi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-rspi.c	2014-09-28 17:29:07.000000000 -0400
@@ -472,25 +472,52 @@ static int rspi_dma_transfer(struct rspi
 	dma_cookie_t cookie;
 	int ret;
 
-	if (tx) {
-		desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
-					tx->sgl, tx->nents, DMA_TO_DEVICE,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		if (!desc_tx)
-			return -EIO;
-
-		irq_mask |= SPCR_SPTIE;
-	}
+	/* First prepare and submit the DMA request(s), as this may fail */
 	if (rx) {
 		desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
 					rx->sgl, rx->nents, DMA_FROM_DEVICE,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		if (!desc_rx)
-			return -EIO;
+		if (!desc_rx) {
+			ret = -EAGAIN;
+			goto no_dma_rx;
+		}
+
+		desc_rx->callback = rspi_dma_complete;
+		desc_rx->callback_param = rspi;
+		cookie = dmaengine_submit(desc_rx);
+		if (dma_submit_error(cookie)) {
+			ret = cookie;
+			goto no_dma_rx;
+		}
 
 		irq_mask |= SPCR_SPRIE;
 	}
 
+	if (tx) {
+		desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
+					tx->sgl, tx->nents, DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc_tx) {
+			ret = -EAGAIN;
+			goto no_dma_tx;
+		}
+
+		if (rx) {
+			/* No callback */
+			desc_tx->callback = NULL;
+		} else {
+			desc_tx->callback = rspi_dma_complete;
+			desc_tx->callback_param = rspi;
+		}
+		cookie = dmaengine_submit(desc_tx);
+		if (dma_submit_error(cookie)) {
+			ret = cookie;
+			goto no_dma_tx;
+		}
+
+		irq_mask |= SPCR_SPTIE;
+	}
+
 	/*
 	 * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
 	 * called. So, this driver disables the IRQ while DMA transfer.
@@ -503,34 +530,24 @@ static int rspi_dma_transfer(struct rspi
 	rspi_enable_irq(rspi, irq_mask);
 	rspi->dma_callbacked = 0;
 
-	if (rx) {
-		desc_rx->callback = rspi_dma_complete;
-		desc_rx->callback_param = rspi;
-		cookie = dmaengine_submit(desc_rx);
-		if (dma_submit_error(cookie))
-			return cookie;
+	/* Now start DMA */
+	if (rx)
 		dma_async_issue_pending(rspi->master->dma_rx);
-	}
-	if (tx) {
-		if (rx) {
-			/* No callback */
-			desc_tx->callback = NULL;
-		} else {
-			desc_tx->callback = rspi_dma_complete;
-			desc_tx->callback_param = rspi;
-		}
-		cookie = dmaengine_submit(desc_tx);
-		if (dma_submit_error(cookie))
-			return cookie;
+	if (tx)
 		dma_async_issue_pending(rspi->master->dma_tx);
-	}
 
 	ret = wait_event_interruptible_timeout(rspi->wait,
 					       rspi->dma_callbacked, HZ);
 	if (ret > 0 && rspi->dma_callbacked)
 		ret = 0;
-	else if (!ret)
+	else if (!ret) {
+		dev_err(&rspi->master->dev, "DMA timeout\n");
 		ret = -ETIMEDOUT;
+		if (tx)
+			dmaengine_terminate_all(rspi->master->dma_tx);
+		if (rx)
+			dmaengine_terminate_all(rspi->master->dma_rx);
+	}
 
 	rspi_disable_irq(rspi, irq_mask);
 
@@ -540,6 +557,17 @@ static int rspi_dma_transfer(struct rspi
 		enable_irq(rspi->rx_irq);
 
 	return ret;
+
+no_dma_tx:
+	if (rx)
+		dmaengine_terminate_all(rspi->master->dma_rx);
+no_dma_rx:
+	if (ret == -EAGAIN) {
+		pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
+			     dev_driver_string(&rspi->master->dev),
+			     dev_name(&rspi->master->dev));
+	}
+	return ret;
 }
 
 static void rspi_receive_init(const struct rspi_data *rspi)
@@ -593,8 +621,10 @@ static int rspi_common_transfer(struct r
 
 	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
 		/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
-		return rspi_dma_transfer(rspi, &xfer->tx_sg,
-					 xfer->rx_buf ? &xfer->rx_sg : NULL);
+		ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
+					xfer->rx_buf ? &xfer->rx_sg : NULL);
+		if (ret != -EAGAIN)
+			return ret;
 	}
 
 	ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
@@ -630,7 +660,6 @@ static int rspi_rz_transfer_one(struct s
 				struct spi_transfer *xfer)
 {
 	struct rspi_data *rspi = spi_master_get_devdata(master);
-	int ret;
 
 	rspi_rz_receive_init(rspi);
 
@@ -649,8 +678,11 @@ static int qspi_transfer_out(struct rspi
 {
 	int ret;
 
-	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
-		return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
+	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
+		ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
+		if (ret != -EAGAIN)
+			return ret;
+	}
 
 	ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
 	if (ret < 0)
@@ -664,8 +696,11 @@ static int qspi_transfer_out(struct rspi
 
 static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
 {
-	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
-		return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
+	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
+		int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
+		if (ret != -EAGAIN)
+			return ret;
+	}
 
 	return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
 }
@@ -927,19 +962,19 @@ static int rspi_request_dma(struct devic
 	return 0;
 }
 
-static void rspi_release_dma(struct rspi_data *rspi)
+static void rspi_release_dma(struct spi_master *master)
 {
-	if (rspi->master->dma_tx)
-		dma_release_channel(rspi->master->dma_tx);
-	if (rspi->master->dma_rx)
-		dma_release_channel(rspi->master->dma_rx);
+	if (master->dma_tx)
+		dma_release_channel(master->dma_tx);
+	if (master->dma_rx)
+		dma_release_channel(master->dma_rx);
 }
 
 static int rspi_remove(struct platform_device *pdev)
 {
 	struct rspi_data *rspi = platform_get_drvdata(pdev);
 
-	rspi_release_dma(rspi);
+	rspi_release_dma(rspi->master);
 	pm_runtime_disable(&pdev->dev);
 
 	return 0;
@@ -1141,7 +1176,7 @@ static int rspi_probe(struct platform_de
 	return 0;
 
 error3:
-	rspi_release_dma(rspi);
+	rspi_release_dma(master);
 error2:
 	pm_runtime_disable(&pdev->dev);
 error1:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-s3c64xx.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-s3c64xx.c
--- linux-libre-3.16-gnu/drivers/spi/spi-s3c64xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-s3c64xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -197,7 +197,6 @@ struct s3c64xx_spi_driver_data {
 	struct s3c64xx_spi_dma_data	tx_dma;
 	struct s3c64xx_spi_port_config	*port_conf;
 	unsigned int			port_id;
-	bool				cs_gpio;
 };
 
 static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
@@ -754,10 +753,8 @@ static struct s3c64xx_spi_csinfo *s3c64x
 {
 	struct s3c64xx_spi_csinfo *cs;
 	struct device_node *slave_np, *data_np = NULL;
-	struct s3c64xx_spi_driver_data *sdd;
 	u32 fb_delay = 0;
 
-	sdd = spi_master_get_devdata(spi->master);
 	slave_np = spi->dev.of_node;
 	if (!slave_np) {
 		dev_err(&spi->dev, "device node not found\n");
@@ -776,17 +773,6 @@ static struct s3c64xx_spi_csinfo *s3c64x
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/* The CS line is asserted/deasserted by the gpio pin */
-	if (sdd->cs_gpio)
-		cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
-
-	if (!gpio_is_valid(cs->line)) {
-		dev_err(&spi->dev, "chip select gpio is not specified or invalid\n");
-		kfree(cs);
-		of_node_put(data_np);
-		return ERR_PTR(-EINVAL);
-	}
-
 	of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
 	cs->fb_delay = fb_delay;
 	of_node_put(data_np);
@@ -807,9 +793,16 @@ static int s3c64xx_spi_setup(struct spi_
 	int err;
 
 	sdd = spi_master_get_devdata(spi->master);
-	if (!cs && spi->dev.of_node) {
+	if (spi->dev.of_node) {
 		cs = s3c64xx_get_slave_ctrldata(spi);
 		spi->controller_data = cs;
+	} else if (cs) {
+		/* On non-DT platforms the SPI core will set spi->cs_gpio
+		 * to -ENOENT. The GPIO pin used to drive the chip select
+		 * is defined by using platform data so spi->cs_gpio value
+		 * has to be override to have the proper GPIO pin number.
+		 */
+		spi->cs_gpio = cs->line;
 	}
 
 	if (IS_ERR_OR_NULL(cs)) {
@@ -818,18 +811,15 @@ static int s3c64xx_spi_setup(struct spi_
 	}
 
 	if (!spi_get_ctldata(spi)) {
-		/* Request gpio only if cs line is asserted by gpio pins */
-		if (sdd->cs_gpio) {
-			err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
-					dev_name(&spi->dev));
+		if (gpio_is_valid(spi->cs_gpio)) {
+			err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH,
+					       dev_name(&spi->dev));
 			if (err) {
 				dev_err(&spi->dev,
 					"Failed to get /CS gpio [%d]: %d\n",
-					cs->line, err);
+					spi->cs_gpio, err);
 				goto err_gpio_req;
 			}
-
-			spi->cs_gpio = cs->line;
 		}
 
 		spi_set_ctldata(spi, cs);
@@ -884,7 +874,8 @@ setup_exit:
 	/* setup() returns with device de-selected */
 	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
-	gpio_free(cs->line);
+	if (gpio_is_valid(spi->cs_gpio))
+		gpio_free(spi->cs_gpio);
 	spi_set_ctldata(spi, NULL);
 
 err_gpio_req:
@@ -897,14 +888,21 @@ err_gpio_req:
 static void s3c64xx_spi_cleanup(struct spi_device *spi)
 {
 	struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
-	struct s3c64xx_spi_driver_data *sdd;
 
-	sdd = spi_master_get_devdata(spi->master);
-	if (spi->cs_gpio) {
+	if (gpio_is_valid(spi->cs_gpio)) {
 		gpio_free(spi->cs_gpio);
 		if (spi->dev.of_node)
 			kfree(cs);
+		else {
+			/* On non-DT platforms, the SPI core sets
+			 * spi->cs_gpio to -ENOENT and .setup()
+			 * overrides it with the GPIO pin value
+			 * passed using platform data.
+			 */
+			spi->cs_gpio = -ENOENT;
+		}
 	}
+
 	spi_set_ctldata(spi, NULL);
 }
 
@@ -1075,11 +1073,7 @@ static int s3c64xx_spi_probe(struct plat
 	sdd->cntrlr_info = sci;
 	sdd->pdev = pdev;
 	sdd->sfr_start = mem_res->start;
-	sdd->cs_gpio = true;
 	if (pdev->dev.of_node) {
-		if (!of_find_property(pdev->dev.of_node, "cs-gpio", NULL))
-			sdd->cs_gpio = false;
-
 		ret = of_alias_get_id(pdev->dev.of_node, "spi");
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
@@ -1323,19 +1317,6 @@ static struct s3c64xx_spi_port_config s3
 	.tx_st_done	= 21,
 };
 
-static struct s3c64xx_spi_port_config s5p64x0_spi_port_config = {
-	.fifo_lvl_mask	= { 0x1ff, 0x7F },
-	.rx_lvl_offset	= 15,
-	.tx_st_done	= 25,
-};
-
-static struct s3c64xx_spi_port_config s5pc100_spi_port_config = {
-	.fifo_lvl_mask	= { 0x7f, 0x7F },
-	.rx_lvl_offset	= 13,
-	.tx_st_done	= 21,
-	.high_speed	= true,
-};
-
 static struct s3c64xx_spi_port_config s5pv210_spi_port_config = {
 	.fifo_lvl_mask	= { 0x1ff, 0x7F },
 	.rx_lvl_offset	= 15,
@@ -1368,12 +1349,6 @@ static struct platform_device_id s3c64xx
 		.name		= "s3c6410-spi",
 		.driver_data	= (kernel_ulong_t)&s3c6410_spi_port_config,
 	}, {
-		.name		= "s5p64x0-spi",
-		.driver_data	= (kernel_ulong_t)&s5p64x0_spi_port_config,
-	}, {
-		.name		= "s5pc100-spi",
-		.driver_data	= (kernel_ulong_t)&s5pc100_spi_port_config,
-	}, {
 		.name		= "s5pv210-spi",
 		.driver_data	= (kernel_ulong_t)&s5pv210_spi_port_config,
 	}, {
@@ -1390,9 +1365,6 @@ static const struct of_device_id s3c64xx
 	{ .compatible = "samsung,s3c6410-spi",
 			.data = (void *)&s3c6410_spi_port_config,
 	},
-	{ .compatible = "samsung,s5pc100-spi",
-			.data = (void *)&s5pc100_spi_port_config,
-	},
 	{ .compatible = "samsung,s5pv210-spi",
 			.data = (void *)&s5pv210_spi_port_config,
 	},
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-sh.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh.c
--- linux-libre-3.16-gnu/drivers/spi/spi-sh.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh.c	2014-09-28 17:29:07.000000000 -0400
@@ -432,7 +432,6 @@ static int spi_sh_remove(struct platform
 	spi_unregister_master(ss->master);
 	destroy_workqueue(ss->workqueue);
 	free_irq(ss->irq, ss);
-	iounmap(ss->addr);
 
 	return 0;
 }
@@ -480,7 +479,7 @@ static int spi_sh_probe(struct platform_
 	}
 	ss->irq = irq;
 	ss->master = master;
-	ss->addr = ioremap(res->start, resource_size(res));
+	ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (ss->addr == NULL) {
 		dev_err(&pdev->dev, "ioremap error.\n");
 		ret = -ENOMEM;
@@ -495,13 +494,13 @@ static int spi_sh_probe(struct platform_
 	if (ss->workqueue == NULL) {
 		dev_err(&pdev->dev, "create workqueue error\n");
 		ret = -EBUSY;
-		goto error2;
+		goto error1;
 	}
 
 	ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request_irq error\n");
-		goto error3;
+		goto error2;
 	}
 
 	master->num_chipselect = 2;
@@ -513,17 +512,15 @@ static int spi_sh_probe(struct platform_
 	ret = spi_register_master(master);
 	if (ret < 0) {
 		printk(KERN_ERR "spi_register_master error.\n");
-		goto error4;
+		goto error3;
 	}
 
 	return 0;
 
- error4:
-	free_irq(irq, ss);
  error3:
-	destroy_workqueue(ss->workqueue);
+	free_irq(irq, ss);
  error2:
-	iounmap(ss->addr);
+	destroy_workqueue(ss->workqueue);
  error1:
 	spi_master_put(master);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-sh-hspi.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh-hspi.c
--- linux-libre-3.16-gnu/drivers/spi/spi-sh-hspi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh-hspi.c	2014-09-28 17:29:07.000000000 -0400
@@ -304,7 +304,7 @@ static int hspi_remove(struct platform_d
 	return 0;
 }
 
-static struct of_device_id hspi_of_match[] = {
+static const struct of_device_id hspi_of_match[] = {
 	{ .compatible = "renesas,hspi", },
 	{ /* sentinel */ }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-sh-msiof.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh-msiof.c
--- linux-libre-3.16-gnu/drivers/spi/spi-sh-msiof.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-sh-msiof.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,7 @@
  * SuperH MSIOF SPI Master Interface
  *
  * Copyright (c) 2009 Magnus Damm
+ * Copyright (C) 2014 Glider bvba
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,6 +14,8 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
@@ -23,6 +26,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sh_dma.h>
 
 #include <linux/spi/sh_msiof.h>
 #include <linux/spi/spi.h>
@@ -37,6 +41,7 @@ struct sh_msiof_chipdata {
 };
 
 struct sh_msiof_spi_priv {
+	struct spi_master *master;
 	void __iomem *mapbase;
 	struct clk *clk;
 	struct platform_device *pdev;
@@ -45,6 +50,10 @@ struct sh_msiof_spi_priv {
 	struct completion done;
 	int tx_fifo_size;
 	int rx_fifo_size;
+	void *tx_dma_page;
+	void *rx_dma_page;
+	dma_addr_t tx_dma_addr;
+	dma_addr_t rx_dma_addr;
 };
 
 #define TMDR1	0x00	/* Transmit Mode Register 1 */
@@ -84,6 +93,8 @@ struct sh_msiof_spi_priv {
 #define MDR2_WDLEN1(i)	(((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
 #define MDR2_GRPMASK1	0x00000001 /* Group Output Mask 1 (SH, A1) */
 
+#define MAX_WDLEN	256U
+
 /* TSCR and RSCR */
 #define SCR_BRPS_MASK	    0x1f00 /* Prescaler Setting (1-32) */
 #define SCR_BRPS(i)	(((i) - 1) << 8)
@@ -113,9 +124,61 @@ struct sh_msiof_spi_priv {
 #define CTR_TXE		0x00000200 /* Transmit Enable */
 #define CTR_RXE		0x00000100 /* Receive Enable */
 
-/* STR and IER */
+/* FCTR */
+#define FCTR_TFWM_MASK	0xe0000000 /* Transmit FIFO Watermark */
+#define FCTR_TFWM_64	0x00000000 /*  Transfer Request when 64 empty stages */
+#define FCTR_TFWM_32	0x20000000 /*  Transfer Request when 32 empty stages */
+#define FCTR_TFWM_24	0x40000000 /*  Transfer Request when 24 empty stages */
+#define FCTR_TFWM_16	0x60000000 /*  Transfer Request when 16 empty stages */
+#define FCTR_TFWM_12	0x80000000 /*  Transfer Request when 12 empty stages */
+#define FCTR_TFWM_8	0xa0000000 /*  Transfer Request when 8 empty stages */
+#define FCTR_TFWM_4	0xc0000000 /*  Transfer Request when 4 empty stages */
+#define FCTR_TFWM_1	0xe0000000 /*  Transfer Request when 1 empty stage */
+#define FCTR_TFUA_MASK	0x07f00000 /* Transmit FIFO Usable Area */
+#define FCTR_TFUA_SHIFT		20
+#define FCTR_TFUA(i)	((i) << FCTR_TFUA_SHIFT)
+#define FCTR_RFWM_MASK	0x0000e000 /* Receive FIFO Watermark */
+#define FCTR_RFWM_1	0x00000000 /*  Transfer Request when 1 valid stages */
+#define FCTR_RFWM_4	0x00002000 /*  Transfer Request when 4 valid stages */
+#define FCTR_RFWM_8	0x00004000 /*  Transfer Request when 8 valid stages */
+#define FCTR_RFWM_16	0x00006000 /*  Transfer Request when 16 valid stages */
+#define FCTR_RFWM_32	0x00008000 /*  Transfer Request when 32 valid stages */
+#define FCTR_RFWM_64	0x0000a000 /*  Transfer Request when 64 valid stages */
+#define FCTR_RFWM_128	0x0000c000 /*  Transfer Request when 128 valid stages */
+#define FCTR_RFWM_256	0x0000e000 /*  Transfer Request when 256 valid stages */
+#define FCTR_RFUA_MASK	0x00001ff0 /* Receive FIFO Usable Area (0x40 = full) */
+#define FCTR_RFUA_SHIFT		 4
+#define FCTR_RFUA(i)	((i) << FCTR_RFUA_SHIFT)
+
+/* STR */
+#define STR_TFEMP	0x20000000 /* Transmit FIFO Empty */
+#define STR_TDREQ	0x10000000 /* Transmit Data Transfer Request */
 #define STR_TEOF	0x00800000 /* Frame Transmission End */
+#define STR_TFSERR	0x00200000 /* Transmit Frame Synchronization Error */
+#define STR_TFOVF	0x00100000 /* Transmit FIFO Overflow */
+#define STR_TFUDF	0x00080000 /* Transmit FIFO Underflow */
+#define STR_RFFUL	0x00002000 /* Receive FIFO Full */
+#define STR_RDREQ	0x00001000 /* Receive Data Transfer Request */
 #define STR_REOF	0x00000080 /* Frame Reception End */
+#define STR_RFSERR	0x00000020 /* Receive Frame Synchronization Error */
+#define STR_RFUDF	0x00000010 /* Receive FIFO Underflow */
+#define STR_RFOVF	0x00000008 /* Receive FIFO Overflow */
+
+/* IER */
+#define IER_TDMAE	0x80000000 /* Transmit Data DMA Transfer Req. Enable */
+#define IER_TFEMPE	0x20000000 /* Transmit FIFO Empty Enable */
+#define IER_TDREQE	0x10000000 /* Transmit Data Transfer Request Enable */
+#define IER_TEOFE	0x00800000 /* Frame Transmission End Enable */
+#define IER_TFSERRE	0x00200000 /* Transmit Frame Sync Error Enable */
+#define IER_TFOVFE	0x00100000 /* Transmit FIFO Overflow Enable */
+#define IER_TFUDFE	0x00080000 /* Transmit FIFO Underflow Enable */
+#define IER_RDMAE	0x00008000 /* Receive Data DMA Transfer Req. Enable */
+#define IER_RFFULE	0x00002000 /* Receive FIFO Full Enable */
+#define IER_RDREQE	0x00001000 /* Receive Data Transfer Request Enable */
+#define IER_REOFE	0x00000080 /* Frame Reception End Enable */
+#define IER_RFSERRE	0x00000020 /* Receive Frame Sync Error Enable */
+#define IER_RFUDFE	0x00000010 /* Receive FIFO Underflow Enable */
+#define IER_RFOVFE	0x00000008 /* Receive FIFO Overflow Enable */
 
 
 static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
@@ -230,8 +293,6 @@ static void sh_msiof_spi_set_pin_regs(st
 	 *    1    0         11     11    0    0
 	 *    1    1         11     11    1    1
 	 */
-	sh_msiof_write(p, FCTR, 0);
-
 	tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP;
 	tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
 	tmp |= lsb_first << MDR1_BITLSB_SHIFT;
@@ -267,8 +328,6 @@ static void sh_msiof_spi_set_mode_regs(s
 
 	if (rx_buf)
 		sh_msiof_write(p, RMDR2, dr2);
-
-	sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
 }
 
 static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
@@ -457,6 +516,40 @@ static int sh_msiof_prepare_message(stru
 	return 0;
 }
 
+static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf)
+{
+	int ret;
+
+	/* setup clock and rx/tx signals */
+	ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
+	if (rx_buf && !ret)
+		ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
+	if (!ret)
+		ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
+
+	/* start by setting frame bit */
+	if (!ret)
+		ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
+
+	return ret;
+}
+
+static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf)
+{
+	int ret;
+
+	/* shut down frame, rx/tx and clock signals */
+	ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
+	if (!ret)
+		ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
+	if (rx_buf && !ret)
+		ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
+	if (!ret)
+		ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
+
+	return ret;
+}
+
 static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
 				  void (*tx_fifo)(struct sh_msiof_spi_priv *,
 						  const void *, int, int),
@@ -477,29 +570,32 @@ static int sh_msiof_spi_txrx_once(struct
 	/* the fifo contents need shifting */
 	fifo_shift = 32 - bits;
 
+	/* default FIFO watermarks for PIO */
+	sh_msiof_write(p, FCTR, 0);
+
 	/* setup msiof transfer mode registers */
 	sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words);
+	sh_msiof_write(p, IER, IER_TEOFE | IER_REOFE);
 
 	/* write tx fifo */
 	if (tx_buf)
 		tx_fifo(p, tx_buf, words, fifo_shift);
 
-	/* setup clock and rx/tx signals */
-	ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
-	if (rx_buf)
-		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
-
-	/* start by setting frame bit */
 	reinit_completion(&p->done);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
+
+	ret = sh_msiof_spi_start(p, rx_buf);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to start hardware\n");
-		goto err;
+		goto stop_ier;
 	}
 
 	/* wait for tx fifo to be emptied / rx fifo to be filled */
-	wait_for_completion(&p->done);
+	ret = wait_for_completion_timeout(&p->done, HZ);
+	if (!ret) {
+		dev_err(&p->pdev->dev, "PIO timeout\n");
+		ret = -ETIMEDOUT;
+		goto stop_reset;
+	}
 
 	/* read rx fifo */
 	if (rx_buf)
@@ -508,41 +604,253 @@ static int sh_msiof_spi_txrx_once(struct
 	/* clear status bits */
 	sh_msiof_reset_str(p);
 
-	/* shut down frame, rx/tx and clock signals */
-	ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
-	if (rx_buf)
-		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
+	ret = sh_msiof_spi_stop(p, rx_buf);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to shut down hardware\n");
-		goto err;
+		return ret;
 	}
 
 	return words;
 
- err:
+stop_reset:
+	sh_msiof_reset_str(p);
+	sh_msiof_spi_stop(p, rx_buf);
+stop_ier:
+	sh_msiof_write(p, IER, 0);
+	return ret;
+}
+
+static void sh_msiof_dma_complete(void *arg)
+{
+	struct sh_msiof_spi_priv *p = arg;
+
+	sh_msiof_write(p, IER, 0);
+	complete(&p->done);
+}
+
+static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
+			     void *rx, unsigned int len)
+{
+	u32 ier_bits = 0;
+	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
+	dma_cookie_t cookie;
+	int ret;
+
+	/* First prepare and submit the DMA request(s), as this may fail */
+	if (rx) {
+		ier_bits |= IER_RDREQE | IER_RDMAE;
+		desc_rx = dmaengine_prep_slave_single(p->master->dma_rx,
+					p->rx_dma_addr, len, DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc_rx) {
+			ret = -EAGAIN;
+			goto no_dma_rx;
+		}
+
+		desc_rx->callback = sh_msiof_dma_complete;
+		desc_rx->callback_param = p;
+		cookie = dmaengine_submit(desc_rx);
+		if (dma_submit_error(cookie)) {
+			ret = cookie;
+			goto no_dma_rx;
+		}
+	}
+
+	if (tx) {
+		ier_bits |= IER_TDREQE | IER_TDMAE;
+		dma_sync_single_for_device(p->master->dma_tx->device->dev,
+					   p->tx_dma_addr, len, DMA_TO_DEVICE);
+		desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
+					p->tx_dma_addr, len, DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc_tx) {
+			ret = -EAGAIN;
+			goto no_dma_tx;
+		}
+
+		if (rx) {
+			/* No callback */
+			desc_tx->callback = NULL;
+		} else {
+			desc_tx->callback = sh_msiof_dma_complete;
+			desc_tx->callback_param = p;
+		}
+		cookie = dmaengine_submit(desc_tx);
+		if (dma_submit_error(cookie)) {
+			ret = cookie;
+			goto no_dma_tx;
+		}
+	}
+
+	/* 1 stage FIFO watermarks for DMA */
+	sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
+
+	/* setup msiof transfer mode registers (32-bit words) */
+	sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
+
+	sh_msiof_write(p, IER, ier_bits);
+
+	reinit_completion(&p->done);
+
+	/* Now start DMA */
+	if (rx)
+		dma_async_issue_pending(p->master->dma_rx);
+	if (tx)
+		dma_async_issue_pending(p->master->dma_tx);
+
+	ret = sh_msiof_spi_start(p, rx);
+	if (ret) {
+		dev_err(&p->pdev->dev, "failed to start hardware\n");
+		goto stop_dma;
+	}
+
+	/* wait for tx fifo to be emptied / rx fifo to be filled */
+	ret = wait_for_completion_timeout(&p->done, HZ);
+	if (!ret) {
+		dev_err(&p->pdev->dev, "DMA timeout\n");
+		ret = -ETIMEDOUT;
+		goto stop_reset;
+	}
+
+	/* clear status bits */
+	sh_msiof_reset_str(p);
+
+	ret = sh_msiof_spi_stop(p, rx);
+	if (ret) {
+		dev_err(&p->pdev->dev, "failed to shut down hardware\n");
+		return ret;
+	}
+
+	if (rx)
+		dma_sync_single_for_cpu(p->master->dma_rx->device->dev,
+					p->rx_dma_addr, len,
+					DMA_FROM_DEVICE);
+
+	return 0;
+
+stop_reset:
+	sh_msiof_reset_str(p);
+	sh_msiof_spi_stop(p, rx);
+stop_dma:
+	if (tx)
+		dmaengine_terminate_all(p->master->dma_tx);
+no_dma_tx:
+	if (rx)
+		dmaengine_terminate_all(p->master->dma_rx);
 	sh_msiof_write(p, IER, 0);
+no_dma_rx:
 	return ret;
 }
 
+static void copy_bswap32(u32 *dst, const u32 *src, unsigned int words)
+{
+	/* src or dst can be unaligned, but not both */
+	if ((unsigned long)src & 3) {
+		while (words--) {
+			*dst++ = swab32(get_unaligned(src));
+			src++;
+		}
+	} else if ((unsigned long)dst & 3) {
+		while (words--) {
+			put_unaligned(swab32(*src++), dst);
+			dst++;
+		}
+	} else {
+		while (words--)
+			*dst++ = swab32(*src++);
+	}
+}
+
+static void copy_wswap32(u32 *dst, const u32 *src, unsigned int words)
+{
+	/* src or dst can be unaligned, but not both */
+	if ((unsigned long)src & 3) {
+		while (words--) {
+			*dst++ = swahw32(get_unaligned(src));
+			src++;
+		}
+	} else if ((unsigned long)dst & 3) {
+		while (words--) {
+			put_unaligned(swahw32(*src++), dst);
+			dst++;
+		}
+	} else {
+		while (words--)
+			*dst++ = swahw32(*src++);
+	}
+}
+
+static void copy_plain32(u32 *dst, const u32 *src, unsigned int words)
+{
+	memcpy(dst, src, words * 4);
+}
+
 static int sh_msiof_transfer_one(struct spi_master *master,
 				 struct spi_device *spi,
 				 struct spi_transfer *t)
 {
 	struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+	void (*copy32)(u32 *, const u32 *, unsigned int);
 	void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
 	void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
-	int bits;
-	int bytes_per_word;
-	int bytes_done;
-	int words;
+	const void *tx_buf = t->tx_buf;
+	void *rx_buf = t->rx_buf;
+	unsigned int len = t->len;
+	unsigned int bits = t->bits_per_word;
+	unsigned int bytes_per_word;
+	unsigned int words;
 	int n;
 	bool swab;
+	int ret;
 
-	bits = t->bits_per_word;
+	/* setup clocks (clock already enabled in chipselect()) */
+	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
 
-	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
+	while (master->dma_tx && len > 15) {
+		/*
+		 *  DMA supports 32-bit words only, hence pack 8-bit and 16-bit
+		 *  words, with byte resp. word swapping.
+		 */
+		unsigned int l = min(len, MAX_WDLEN * 4);
+
+		if (bits <= 8) {
+			if (l & 3)
+				break;
+			copy32 = copy_bswap32;
+		} else if (bits <= 16) {
+			if (l & 1)
+				break;
+			copy32 = copy_wswap32;
+		} else {
+			copy32 = copy_plain32;
+		}
+
+		if (tx_buf)
+			copy32(p->tx_dma_page, tx_buf, l / 4);
+
+		ret = sh_msiof_dma_once(p, tx_buf, rx_buf, l);
+		if (ret == -EAGAIN) {
+			pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
+				     dev_driver_string(&p->pdev->dev),
+				     dev_name(&p->pdev->dev));
+			break;
+		}
+		if (ret)
+			return ret;
+
+		if (rx_buf) {
+			copy32(rx_buf, p->rx_dma_page, l / 4);
+			rx_buf += l;
+		}
+		if (tx_buf)
+			tx_buf += l;
+
+		len -= l;
+		if (!len)
+			return 0;
+	}
+
+	if (bits <= 8 && len > 15 && !(len & 3)) {
 		bits = 32;
 		swab = true;
 	} else {
@@ -556,57 +864,52 @@ static int sh_msiof_transfer_one(struct
 		rx_fifo = sh_msiof_spi_read_fifo_8;
 	} else if (bits <= 16) {
 		bytes_per_word = 2;
-		if ((unsigned long)t->tx_buf & 0x01)
+		if ((unsigned long)tx_buf & 0x01)
 			tx_fifo = sh_msiof_spi_write_fifo_16u;
 		else
 			tx_fifo = sh_msiof_spi_write_fifo_16;
 
-		if ((unsigned long)t->rx_buf & 0x01)
+		if ((unsigned long)rx_buf & 0x01)
 			rx_fifo = sh_msiof_spi_read_fifo_16u;
 		else
 			rx_fifo = sh_msiof_spi_read_fifo_16;
 	} else if (swab) {
 		bytes_per_word = 4;
-		if ((unsigned long)t->tx_buf & 0x03)
+		if ((unsigned long)tx_buf & 0x03)
 			tx_fifo = sh_msiof_spi_write_fifo_s32u;
 		else
 			tx_fifo = sh_msiof_spi_write_fifo_s32;
 
-		if ((unsigned long)t->rx_buf & 0x03)
+		if ((unsigned long)rx_buf & 0x03)
 			rx_fifo = sh_msiof_spi_read_fifo_s32u;
 		else
 			rx_fifo = sh_msiof_spi_read_fifo_s32;
 	} else {
 		bytes_per_word = 4;
-		if ((unsigned long)t->tx_buf & 0x03)
+		if ((unsigned long)tx_buf & 0x03)
 			tx_fifo = sh_msiof_spi_write_fifo_32u;
 		else
 			tx_fifo = sh_msiof_spi_write_fifo_32;
 
-		if ((unsigned long)t->rx_buf & 0x03)
+		if ((unsigned long)rx_buf & 0x03)
 			rx_fifo = sh_msiof_spi_read_fifo_32u;
 		else
 			rx_fifo = sh_msiof_spi_read_fifo_32;
 	}
 
-	/* setup clocks (clock already enabled in chipselect()) */
-	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
-
 	/* transfer in fifo sized chunks */
-	words = t->len / bytes_per_word;
-	bytes_done = 0;
+	words = len / bytes_per_word;
 
-	while (bytes_done < t->len) {
-		void *rx_buf = t->rx_buf ? t->rx_buf + bytes_done : NULL;
-		const void *tx_buf = t->tx_buf ? t->tx_buf + bytes_done : NULL;
-		n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo,
-					   tx_buf,
-					   rx_buf,
+	while (words > 0) {
+		n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo, tx_buf, rx_buf,
 					   words, bits);
 		if (n < 0)
-			break;
+			return n;
 
-		bytes_done += n * bytes_per_word;
+		if (tx_buf)
+			tx_buf += n * bytes_per_word;
+		if (rx_buf)
+			rx_buf += n * bytes_per_word;
 		words -= n;
 	}
 
@@ -663,6 +966,128 @@ static struct sh_msiof_spi_info *sh_msio
 }
 #endif
 
+static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev,
+	enum dma_transfer_direction dir, unsigned int id, dma_addr_t port_addr)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct dma_slave_config cfg;
+	int ret;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	chan = dma_request_channel(mask, shdma_chan_filter,
+				  (void *)(unsigned long)id);
+	if (!chan) {
+		dev_warn(dev, "dma_request_channel failed\n");
+		return NULL;
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.slave_id = id;
+	cfg.direction = dir;
+	if (dir == DMA_MEM_TO_DEV)
+		cfg.dst_addr = port_addr;
+	else
+		cfg.src_addr = port_addr;
+
+	ret = dmaengine_slave_config(chan, &cfg);
+	if (ret) {
+		dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
+		dma_release_channel(chan);
+		return NULL;
+	}
+
+	return chan;
+}
+
+static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
+{
+	struct platform_device *pdev = p->pdev;
+	struct device *dev = &pdev->dev;
+	const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
+	const struct resource *res;
+	struct spi_master *master;
+	struct device *tx_dev, *rx_dev;
+
+	if (!info || !info->dma_tx_id || !info->dma_rx_id)
+		return 0;	/* The driver assumes no error */
+
+	/* The DMA engine uses the second register set, if present */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	master = p->master;
+	master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV,
+						   info->dma_tx_id,
+						   res->start + TFDR);
+	if (!master->dma_tx)
+		return -ENODEV;
+
+	master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM,
+						   info->dma_rx_id,
+						   res->start + RFDR);
+	if (!master->dma_rx)
+		goto free_tx_chan;
+
+	p->tx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+	if (!p->tx_dma_page)
+		goto free_rx_chan;
+
+	p->rx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+	if (!p->rx_dma_page)
+		goto free_tx_page;
+
+	tx_dev = master->dma_tx->device->dev;
+	p->tx_dma_addr = dma_map_single(tx_dev, p->tx_dma_page, PAGE_SIZE,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(tx_dev, p->tx_dma_addr))
+		goto free_rx_page;
+
+	rx_dev = master->dma_rx->device->dev;
+	p->rx_dma_addr = dma_map_single(rx_dev, p->rx_dma_page, PAGE_SIZE,
+					DMA_FROM_DEVICE);
+	if (dma_mapping_error(rx_dev, p->rx_dma_addr))
+		goto unmap_tx_page;
+
+	dev_info(dev, "DMA available");
+	return 0;
+
+unmap_tx_page:
+	dma_unmap_single(tx_dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
+free_rx_page:
+	free_page((unsigned long)p->rx_dma_page);
+free_tx_page:
+	free_page((unsigned long)p->tx_dma_page);
+free_rx_chan:
+	dma_release_channel(master->dma_rx);
+free_tx_chan:
+	dma_release_channel(master->dma_tx);
+	master->dma_tx = NULL;
+	return -ENODEV;
+}
+
+static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
+{
+	struct spi_master *master = p->master;
+	struct device *dev;
+
+	if (!master->dma_tx)
+		return;
+
+	dev = &p->pdev->dev;
+	dma_unmap_single(master->dma_rx->device->dev, p->rx_dma_addr,
+			 PAGE_SIZE, DMA_FROM_DEVICE);
+	dma_unmap_single(master->dma_tx->device->dev, p->tx_dma_addr,
+			 PAGE_SIZE, DMA_TO_DEVICE);
+	free_page((unsigned long)p->rx_dma_page);
+	free_page((unsigned long)p->tx_dma_page);
+	dma_release_channel(master->dma_rx);
+	dma_release_channel(master->dma_tx);
+}
+
 static int sh_msiof_spi_probe(struct platform_device *pdev)
 {
 	struct resource	*r;
@@ -681,6 +1106,7 @@ static int sh_msiof_spi_probe(struct pla
 	p = spi_master_get_devdata(master);
 
 	platform_set_drvdata(pdev, p);
+	p->master = master;
 
 	of_id = of_match_device(sh_msiof_match, &pdev->dev);
 	if (of_id) {
@@ -751,6 +1177,10 @@ static int sh_msiof_spi_probe(struct pla
 	master->auto_runtime_pm = true;
 	master->transfer_one = sh_msiof_transfer_one;
 
+	ret = sh_msiof_request_dma(p);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "DMA not available, using PIO\n");
+
 	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "spi_register_master error.\n");
@@ -760,6 +1190,7 @@ static int sh_msiof_spi_probe(struct pla
 	return 0;
 
  err2:
+	sh_msiof_release_dma(p);
 	pm_runtime_disable(&pdev->dev);
  err1:
 	spi_master_put(master);
@@ -768,6 +1199,9 @@ static int sh_msiof_spi_probe(struct pla
 
 static int sh_msiof_spi_remove(struct platform_device *pdev)
 {
+	struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
+
+	sh_msiof_release_dma(p);
 	pm_runtime_disable(&pdev->dev);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-sirf.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-sirf.c
--- linux-libre-3.16-gnu/drivers/spi/spi-sirf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-sirf.c	2014-09-28 17:29:07.000000000 -0400
@@ -312,6 +312,8 @@ static int spi_sirfsoc_cmd_transfer(stru
 	u32 cmd;
 
 	sspi = spi_master_get_devdata(spi->master);
+	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
 	memcpy(&cmd, sspi->tx, t->len);
 	if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
 		cmd = cpu_to_be32(cmd) >>
@@ -438,7 +440,8 @@ static void spi_sirfsoc_pio_transfer(str
 			sspi->tx_word(sspi);
 		writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN |
 			SIRFSOC_SPI_TX_UFLOW_INT_EN |
-			SIRFSOC_SPI_RX_OFLOW_INT_EN,
+			SIRFSOC_SPI_RX_OFLOW_INT_EN |
+			SIRFSOC_SPI_RX_IO_DMA_INT_EN,
 			sspi->base + SIRFSOC_SPI_INT_EN);
 		writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
 			sspi->base + SIRFSOC_SPI_TX_RX_EN);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-topcliff-pch.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-topcliff-pch.c
--- linux-libre-3.16-gnu/drivers/spi/spi-topcliff-pch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-topcliff-pch.c	2014-09-28 17:29:07.000000000 -0400
@@ -874,8 +874,8 @@ static void pch_spi_request_dma(struct p
 	dma_cap_set(DMA_SLAVE, mask);
 
 	/* Get DMA's dev information */
-	dma_dev = pci_get_bus_and_slot(data->board_dat->pdev->bus->number,
-				       PCI_DEVFN(12, 0));
+	dma_dev = pci_get_slot(data->board_dat->pdev->bus,
+			PCI_DEVFN(PCI_SLOT(data->board_dat->pdev->devfn), 0));
 
 	/* Set Tx DMA */
 	param = &dma->param_tx;
@@ -1047,8 +1047,8 @@ static void pch_spi_handle_dma(struct pc
 					num, DMA_DEV_TO_MEM,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_rx) {
-		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
-			__func__);
+		dev_err(&data->master->dev,
+			"%s:dmaengine_prep_slave_sg Failed\n", __func__);
 		return;
 	}
 	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE);
@@ -1106,8 +1106,8 @@ static void pch_spi_handle_dma(struct pc
 					sg, num, DMA_MEM_TO_DEV,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_tx) {
-		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
-			__func__);
+		dev_err(&data->master->dev,
+			"%s:dmaengine_prep_slave_sg Failed\n", __func__);
 		return;
 	}
 	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spi/spi-xilinx.c linux-libre-3.17-rc7-gnu/drivers/spi/spi-xilinx.c
--- linux-libre-3.16-gnu/drivers/spi/spi-xilinx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spi/spi-xilinx.c	2014-09-28 17:29:07.000000000 -0400
@@ -369,7 +369,7 @@ static int xilinx_spi_probe(struct platf
 		goto put_master;
 	}
 
-	master->bus_num = pdev->dev.id;
+	master->bus_num = pdev->id;
 	master->num_chipselect = num_cs;
 	master->dev.of_node = pdev->dev.of_node;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/spmi/spmi.c linux-libre-3.17-rc7-gnu/drivers/spmi/spmi.c
--- linux-libre-3.16-gnu/drivers/spmi/spmi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/spmi/spmi.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/spmi.h>
-#include <linux/module.h>
 #include <linux/pm_runtime.h>
 
 #include <dt-bindings/spmi/spmi.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ssb/b43_pci_bridge.c linux-libre-3.17-rc7-gnu/drivers/ssb/b43_pci_bridge.c
--- linux-libre-3.16-gnu/drivers/ssb/b43_pci_bridge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ssb/b43_pci_bridge.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,6 +38,7 @@ static const struct pci_device_id b43_pc
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4351) },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/ssb/pci.c linux-libre-3.17-rc7-gnu/drivers/ssb/pci.c
--- linux-libre-3.16-gnu/drivers/ssb/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/ssb/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -326,13 +326,13 @@ err_ctlreg:
 	return err;
 }
 
-static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
-			       u16 mask, u16 shift)
+static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
+				u16 mask, u16 shift)
 {
 	u16 v;
 	u8 gain;
 
-	v = in[SPOFF(SSB_SPROM1_AGAIN)];
+	v = in[SPOFF(offset)];
 	gain = (v & mask) >> shift;
 	if (gain == 0xFF)
 		gain = 2; /* If unset use 2dBm */
@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ss
 	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
 
 	/* Extract the antenna gain values. */
-	out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
-						    SSB_SPROM1_AGAIN_BG,
-						    SSB_SPROM1_AGAIN_BG_SHIFT);
-	out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
-						    SSB_SPROM1_AGAIN_A,
-						    SSB_SPROM1_AGAIN_A_SHIFT);
+	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM1_AGAIN,
+						     SSB_SPROM1_AGAIN_BG,
+						     SSB_SPROM1_AGAIN_BG_SHIFT);
+	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM1_AGAIN,
+						     SSB_SPROM1_AGAIN_A,
+						     SSB_SPROM1_AGAIN_A_SHIFT);
 	if (out->revision >= 2)
 		sprom_extract_r23(out, in);
 }
@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ss
 
 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 {
+	static const u16 pwr_info_offset[] = {
+		SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
+		SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
+	};
 	u16 il0mac_offset;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
+		     ARRAY_SIZE(out->core_pwr_info));
 
 	if (out->revision == 4)
 		il0mac_offset = SSB_SPROM4_IL0MAC;
@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb
 	}
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
-	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
-	SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
-	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
-	SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
-	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
-	SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
-	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
+	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM4_AGAIN01,
+						     SSB_SPROM4_AGAIN0,
+						     SSB_SPROM4_AGAIN0_SHIFT);
+	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM4_AGAIN01,
+						     SSB_SPROM4_AGAIN1,
+						     SSB_SPROM4_AGAIN1_SHIFT);
+	out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM4_AGAIN23,
+						     SSB_SPROM4_AGAIN2,
+						     SSB_SPROM4_AGAIN2_SHIFT);
+	out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM4_AGAIN23,
+						     SSB_SPROM4_AGAIN3,
+						     SSB_SPROM4_AGAIN3_SHIFT);
+
+	/* Extract cores power info info */
+	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
+		u16 o = pwr_info_offset[i];
+
+		SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
+			SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
+			SSB_SPROM4_2G_MAXP, 0);
+
+		SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
+
+		SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
+			SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
+			SSB_SPROM4_5G_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
+			SSB_SPROM4_5GH_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
+			SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
+
+		SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
+	}
 
 	sprom_extract_r458(out, in);
 
@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_
 	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
-	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
-	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
-	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
-	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
-	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
-	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
-	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM8_AGAIN01,
+						     SSB_SPROM8_AGAIN0,
+						     SSB_SPROM8_AGAIN0_SHIFT);
+	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM8_AGAIN01,
+						     SSB_SPROM8_AGAIN1,
+						     SSB_SPROM8_AGAIN1_SHIFT);
+	out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM8_AGAIN23,
+						     SSB_SPROM8_AGAIN2,
+						     SSB_SPROM8_AGAIN2_SHIFT);
+	out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
+						     SSB_SPROM8_AGAIN23,
+						     SSB_SPROM8_AGAIN3,
+						     SSB_SPROM8_AGAIN3_SHIFT);
 
 	/* Extract cores power info info */
 	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/alarm-dev.c linux-libre-3.17-rc7-gnu/drivers/staging/android/alarm-dev.c
--- linux-libre-3.16-gnu/drivers/staging/android/alarm-dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/alarm-dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -443,4 +443,4 @@ static void  __exit alarm_dev_exit(void)
 
 module_init(alarm_dev_init);
 module_exit(alarm_dev_exit);
-
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/binder.c linux-libre-3.17-rc7-gnu/drivers/staging/android/binder.c
--- linux-libre-3.16-gnu/drivers/staging/android/binder.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/binder.c	2014-09-28 17:29:07.000000000 -0400
@@ -454,9 +454,8 @@ static size_t binder_buffer_size(struct
 {
 	if (list_is_last(&buffer->entry, &proc->buffers))
 		return proc->buffer + proc->buffer_size - (void *)buffer->data;
-	else
-		return (size_t)list_entry(buffer->entry.next,
-			struct binder_buffer, entry) - (size_t)buffer->data;
+	return (size_t)list_entry(buffer->entry.next,
+			  struct binder_buffer, entry) - (size_t)buffer->data;
 }
 
 static void binder_insert_free_buffer(struct binder_proc *proc,
@@ -586,7 +585,6 @@ static int binder_update_page_range(stru
 
 	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
 		int ret;
-		struct page **page_array_ptr;
 
 		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
@@ -599,8 +597,7 @@ static int binder_update_page_range(stru
 		}
 		tmp_area.addr = page_addr;
 		tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
-		page_array_ptr = page;
-		ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
+		ret = map_vm_area(&tmp_area, PAGE_KERNEL, page);
 		if (ret) {
 			pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n",
 			       proc->pid, page_addr);
@@ -1186,6 +1183,7 @@ static void binder_send_failed_reply(str
 				     uint32_t error_code)
 {
 	struct binder_thread *target_thread;
+	struct binder_transaction *next;
 
 	BUG_ON(t->flags & TF_ONE_WAY);
 	while (1) {
@@ -1213,24 +1211,23 @@ static void binder_send_failed_reply(str
 					target_thread->return_error);
 			}
 			return;
-		} else {
-			struct binder_transaction *next = t->from_parent;
+		}
+		next = t->from_parent;
 
-			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-				     "send failed reply for transaction %d, target dead\n",
-				     t->debug_id);
+		binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+			     "send failed reply for transaction %d, target dead\n",
+			     t->debug_id);
 
-			binder_pop_transaction(target_thread, t);
-			if (next == NULL) {
-				binder_debug(BINDER_DEBUG_DEAD_BINDER,
-					     "reply failed, no target thread at root\n");
-				return;
-			}
-			t = next;
+		binder_pop_transaction(target_thread, t);
+		if (next == NULL) {
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "reply failed, no target thread -- retry %d\n",
-				      t->debug_id);
+				     "reply failed, no target thread at root\n");
+			return;
 		}
+		t = next;
+		binder_debug(BINDER_DEBUG_DEAD_BINDER,
+			     "reply failed, no target thread -- retry %d\n",
+			      t->debug_id);
 	}
 }
 
@@ -2594,6 +2591,106 @@ static unsigned int binder_poll(struct f
 	return 0;
 }
 
+static int binder_ioctl_write_read(struct file *filp,
+				unsigned int cmd, unsigned long arg,
+				struct binder_thread *thread)
+{
+	int ret = 0;
+	struct binder_proc *proc = filp->private_data;
+	unsigned int size = _IOC_SIZE(cmd);
+	void __user *ubuf = (void __user *)arg;
+	struct binder_write_read bwr;
+
+	if (size != sizeof(struct binder_write_read)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
+		ret = -EFAULT;
+		goto out;
+	}
+	binder_debug(BINDER_DEBUG_READ_WRITE,
+		     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
+		     proc->pid, thread->pid,
+		     (u64)bwr.write_size, (u64)bwr.write_buffer,
+		     (u64)bwr.read_size, (u64)bwr.read_buffer);
+
+	if (bwr.write_size > 0) {
+		ret = binder_thread_write(proc, thread,
+					  bwr.write_buffer,
+					  bwr.write_size,
+					  &bwr.write_consumed);
+		trace_binder_write_done(ret);
+		if (ret < 0) {
+			bwr.read_consumed = 0;
+			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+				ret = -EFAULT;
+			goto out;
+		}
+	}
+	if (bwr.read_size > 0) {
+		ret = binder_thread_read(proc, thread, bwr.read_buffer,
+					 bwr.read_size,
+					 &bwr.read_consumed,
+					 filp->f_flags & O_NONBLOCK);
+		trace_binder_read_done(ret);
+		if (!list_empty(&proc->todo))
+			wake_up_interruptible(&proc->wait);
+		if (ret < 0) {
+			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+				ret = -EFAULT;
+			goto out;
+		}
+	}
+	binder_debug(BINDER_DEBUG_READ_WRITE,
+		     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
+		     proc->pid, thread->pid,
+		     (u64)bwr.write_consumed, (u64)bwr.write_size,
+		     (u64)bwr.read_consumed, (u64)bwr.read_size);
+	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
+		ret = -EFAULT;
+		goto out;
+	}
+out:
+	return ret;
+}
+
+static int binder_ioctl_set_ctx_mgr(struct file *filp)
+{
+	int ret = 0;
+	struct binder_proc *proc = filp->private_data;
+	kuid_t curr_euid = current_euid();
+
+	if (binder_context_mgr_node != NULL) {
+		pr_err("BINDER_SET_CONTEXT_MGR already set\n");
+		ret = -EBUSY;
+		goto out;
+	}
+	if (uid_valid(binder_context_mgr_uid)) {
+		if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
+			pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
+			       from_kuid(&init_user_ns, curr_euid),
+			       from_kuid(&init_user_ns,
+					binder_context_mgr_uid));
+			ret = -EPERM;
+			goto out;
+		}
+	} else {
+		binder_context_mgr_uid = curr_euid;
+	}
+	binder_context_mgr_node = binder_new_node(proc, 0, 0);
+	if (binder_context_mgr_node == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	binder_context_mgr_node->local_weak_refs++;
+	binder_context_mgr_node->local_strong_refs++;
+	binder_context_mgr_node->has_strong_ref = 1;
+	binder_context_mgr_node->has_weak_ref = 1;
+out:
+	return ret;
+}
+
 static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -2601,9 +2698,9 @@ static long binder_ioctl(struct file *fi
 	struct binder_thread *thread;
 	unsigned int size = _IOC_SIZE(cmd);
 	void __user *ubuf = (void __user *)arg;
-	kuid_t curr_euid = current_euid();
 
-	/*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
+	/*pr_info("binder_ioctl: %d:%d %x %lx\n",
+			proc->pid, current->pid, cmd, arg);*/
 
 	trace_binder_ioctl(cmd, arg);
 
@@ -2619,61 +2716,11 @@ static long binder_ioctl(struct file *fi
 	}
 
 	switch (cmd) {
-	case BINDER_WRITE_READ: {
-		struct binder_write_read bwr;
-
-		if (size != sizeof(struct binder_write_read)) {
-			ret = -EINVAL;
-			goto err;
-		}
-		if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
-			ret = -EFAULT;
-			goto err;
-		}
-		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
-			     proc->pid, thread->pid,
-			     (u64)bwr.write_size, (u64)bwr.write_buffer,
-			     (u64)bwr.read_size, (u64)bwr.read_buffer);
-
-		if (bwr.write_size > 0) {
-			ret = binder_thread_write(proc, thread,
-						  bwr.write_buffer,
-						  bwr.write_size,
-						  &bwr.write_consumed);
-			trace_binder_write_done(ret);
-			if (ret < 0) {
-				bwr.read_consumed = 0;
-				if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
-					ret = -EFAULT;
-				goto err;
-			}
-		}
-		if (bwr.read_size > 0) {
-			ret = binder_thread_read(proc, thread, bwr.read_buffer,
-						 bwr.read_size,
-						 &bwr.read_consumed,
-						 filp->f_flags & O_NONBLOCK);
-			trace_binder_read_done(ret);
-			if (!list_empty(&proc->todo))
-				wake_up_interruptible(&proc->wait);
-			if (ret < 0) {
-				if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
-					ret = -EFAULT;
-				goto err;
-			}
-		}
-		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
-			     proc->pid, thread->pid,
-			     (u64)bwr.write_consumed, (u64)bwr.write_size,
-			     (u64)bwr.read_consumed, (u64)bwr.read_size);
-		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
-			ret = -EFAULT;
+	case BINDER_WRITE_READ:
+		ret = binder_ioctl_write_read(filp, cmd, arg, thread);
+		if (ret)
 			goto err;
-		}
 		break;
-	}
 	case BINDER_SET_MAX_THREADS:
 		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
 			ret = -EINVAL;
@@ -2681,31 +2728,9 @@ static long binder_ioctl(struct file *fi
 		}
 		break;
 	case BINDER_SET_CONTEXT_MGR:
-		if (binder_context_mgr_node != NULL) {
-			pr_err("BINDER_SET_CONTEXT_MGR already set\n");
-			ret = -EBUSY;
-			goto err;
-		}
-		if (uid_valid(binder_context_mgr_uid)) {
-			if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
-				pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
-				       from_kuid(&init_user_ns, curr_euid),
-				       from_kuid(&init_user_ns, binder_context_mgr_uid));
-				ret = -EPERM;
-				goto err;
-			}
-		} else {
-			binder_context_mgr_uid = curr_euid;
-		}
-		binder_context_mgr_node = binder_new_node(proc, 0, 0);
-		if (binder_context_mgr_node == NULL) {
-			ret = -ENOMEM;
+		ret = binder_ioctl_set_ctx_mgr(filp);
+		if (ret)
 			goto err;
-		}
-		binder_context_mgr_node->local_weak_refs++;
-		binder_context_mgr_node->local_strong_refs++;
-		binder_context_mgr_node->has_strong_ref = 1;
-		binder_context_mgr_node->has_weak_ref = 1;
 		break;
 	case BINDER_THREAD_EXIT:
 		binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
@@ -2769,9 +2794,15 @@ static void binder_vma_close(struct vm_a
 	binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
 }
 
+static int binder_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
 static struct vm_operations_struct binder_vm_ops = {
 	.open = binder_vma_open,
 	.close = binder_vma_close,
+	.fault = binder_vm_fault,
 };
 
 static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/ion.c linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion.c
--- linux-libre-3.16-gnu/drivers/staging/android/ion/ion.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion.c	2014-09-28 17:29:07.000000000 -0400
@@ -1120,7 +1120,8 @@ struct dma_buf *ion_share_dma_buf(struct
 	ion_buffer_get(buffer);
 	mutex_unlock(&client->lock);
 
-	dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR);
+	dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR,
+				NULL);
 	if (IS_ERR(dmabuf)) {
 		ion_buffer_put(buffer);
 		return dmabuf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/ion_chunk_heap.c linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_chunk_heap.c
--- linux-libre-3.16-gnu/drivers/staging/android/ion/ion_chunk_heap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_chunk_heap.c	2014-09-28 17:29:07.000000000 -0400
@@ -106,7 +106,7 @@ static void ion_chunk_heap_free(struct i
 
 	if (ion_buffer_cached(buffer))
 		dma_sync_sg_for_device(NULL, table->sgl, table->nents,
-								DMA_BIDIRECTIONAL);
+							DMA_BIDIRECTIONAL);
 
 	for_each_sg(table->sgl, sg, table->nents, i) {
 		gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/ion_cma_heap.c linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_cma_heap.c
--- linux-libre-3.16-gnu/drivers/staging/android/ion/ion_cma_heap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_cma_heap.c	2014-09-28 17:29:07.000000000 -0400
@@ -76,10 +76,8 @@ static int ion_cma_allocate(struct ion_h
 		return -EINVAL;
 
 	info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL);
-	if (!info) {
-		dev_err(dev, "Can't allocate buffer info\n");
+	if (!info)
 		return ION_CMA_ALLOCATE_FAILED;
-	}
 
 	info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle),
 						GFP_HIGHUSER | __GFP_ZERO);
@@ -90,10 +88,8 @@ static int ion_cma_allocate(struct ion_h
 	}
 
 	info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-	if (!info->table) {
-		dev_err(dev, "Fail to allocate sg table\n");
+	if (!info->table)
 		goto free_mem;
-	}
 
 	if (ion_cma_get_sgtable
 	    (dev, info->table, info->cpu_addr, info->handle, len))
@@ -155,7 +151,6 @@ static struct sg_table *ion_cma_heap_map
 static void ion_cma_heap_unmap_dma(struct ion_heap *heap,
 				   struct ion_buffer *buffer)
 {
-	return;
 }
 
 static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/ion.h linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion.h
--- linux-libre-3.16-gnu/drivers/staging/android/ion/ion.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion.h	2014-09-28 17:29:07.000000000 -0400
@@ -84,7 +84,6 @@ void ion_reserve(struct ion_platform_dat
 /**
  * ion_client_create() -  allocate a client and returns it
  * @dev:		the global ion device
- * @heap_type_mask:	mask of heaps this client can allocate from
  * @name:		used for debugging
  */
 struct ion_client *ion_client_create(struct ion_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/ion_system_heap.c linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_system_heap.c
--- linux-libre-3.16-gnu/drivers/staging/android/ion/ion_system_heap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/ion_system_heap.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,13 +49,7 @@ static inline unsigned int order_to_size
 
 struct ion_system_heap {
 	struct ion_heap heap;
-	struct ion_page_pool **pools;
-};
-
-struct page_info {
-	struct page *page;
-	unsigned int order;
-	struct list_head list;
+	struct ion_page_pool *pools[0];
 };
 
 static struct page *alloc_buffer_page(struct ion_system_heap *heap,
@@ -84,9 +78,9 @@ static struct page *alloc_buffer_page(st
 }
 
 static void free_buffer_page(struct ion_system_heap *heap,
-			     struct ion_buffer *buffer, struct page *page,
-			     unsigned int order)
+			     struct ion_buffer *buffer, struct page *page)
 {
+	unsigned int order = compound_order(page);
 	bool cached = ion_buffer_cached(buffer);
 
 	if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) {
@@ -99,19 +93,14 @@ static void free_buffer_page(struct ion_
 }
 
 
-static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
-						 struct ion_buffer *buffer,
-						 unsigned long size,
-						 unsigned int max_order)
+static struct page *alloc_largest_available(struct ion_system_heap *heap,
+					    struct ion_buffer *buffer,
+					    unsigned long size,
+					    unsigned int max_order)
 {
 	struct page *page;
-	struct page_info *info;
 	int i;
 
-	info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
-	if (!info)
-		return NULL;
-
 	for (i = 0; i < num_orders; i++) {
 		if (size < order_to_size(orders[i]))
 			continue;
@@ -122,11 +111,8 @@ static struct page_info *alloc_largest_a
 		if (!page)
 			continue;
 
-		info->page = page;
-		info->order = orders[i];
-		return info;
+		return page;
 	}
-	kfree(info);
 
 	return NULL;
 }
@@ -142,7 +128,7 @@ static int ion_system_heap_allocate(stru
 	struct sg_table *table;
 	struct scatterlist *sg;
 	struct list_head pages;
-	struct page_info *info, *tmp_info;
+	struct page *page, *tmp_page;
 	int i = 0;
 	unsigned long size_remaining = PAGE_ALIGN(size);
 	unsigned int max_order = orders[0];
@@ -155,13 +141,13 @@ static int ion_system_heap_allocate(stru
 
 	INIT_LIST_HEAD(&pages);
 	while (size_remaining > 0) {
-		info = alloc_largest_available(sys_heap, buffer, size_remaining,
+		page = alloc_largest_available(sys_heap, buffer, size_remaining,
 						max_order);
-		if (!info)
+		if (!page)
 			goto free_pages;
-		list_add_tail(&info->list, &pages);
-		size_remaining -= PAGE_SIZE << info->order;
-		max_order = info->order;
+		list_add_tail(&page->lru, &pages);
+		size_remaining -= PAGE_SIZE << compound_order(page);
+		max_order = compound_order(page);
 		i++;
 	}
 	table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
@@ -172,12 +158,10 @@ static int ion_system_heap_allocate(stru
 		goto free_table;
 
 	sg = table->sgl;
-	list_for_each_entry_safe(info, tmp_info, &pages, list) {
-		struct page *page = info->page;
-		sg_set_page(sg, page, PAGE_SIZE << info->order, 0);
+	list_for_each_entry_safe(page, tmp_page, &pages, lru) {
+		sg_set_page(sg, page, PAGE_SIZE << compound_order(page), 0);
 		sg = sg_next(sg);
-		list_del(&info->list);
-		kfree(info);
+		list_del(&page->lru);
 	}
 
 	buffer->priv_virt = table;
@@ -186,10 +170,8 @@ static int ion_system_heap_allocate(stru
 free_table:
 	kfree(table);
 free_pages:
-	list_for_each_entry_safe(info, tmp_info, &pages, list) {
-		free_buffer_page(sys_heap, buffer, info->page, info->order);
-		kfree(info);
-	}
+	list_for_each_entry_safe(page, tmp_page, &pages, lru)
+		free_buffer_page(sys_heap, buffer, page);
 	return -ENOMEM;
 }
 
@@ -209,8 +191,7 @@ static void ion_system_heap_free(struct
 		ion_heap_buffer_zero(buffer);
 
 	for_each_sg(table->sgl, sg, table->nents, i)
-		free_buffer_page(sys_heap, buffer, sg_page(sg),
-				get_order(sg->length));
+		free_buffer_page(sys_heap, buffer, sg_page(sg));
 	sg_free_table(table);
 	kfree(table);
 }
@@ -283,16 +264,15 @@ struct ion_heap *ion_system_heap_create(
 	struct ion_system_heap *heap;
 	int i;
 
-	heap = kzalloc(sizeof(struct ion_system_heap), GFP_KERNEL);
+	heap = kzalloc(sizeof(struct ion_system_heap) +
+			sizeof(struct ion_page_pool *) * num_orders,
+			GFP_KERNEL);
 	if (!heap)
 		return ERR_PTR(-ENOMEM);
 	heap->heap.ops = &system_heap_ops;
 	heap->heap.type = ION_HEAP_TYPE_SYSTEM;
 	heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
-	heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders,
-			      GFP_KERNEL);
-	if (!heap->pools)
-		goto free_heap;
+
 	for (i = 0; i < num_orders; i++) {
 		struct ion_page_pool *pool;
 		gfp_t gfp_flags = low_order_gfp_flags;
@@ -311,8 +291,6 @@ struct ion_heap *ion_system_heap_create(
 destroy_pools:
 	while (i--)
 		ion_page_pool_destroy(heap->pools[i]);
-	kfree(heap->pools);
-free_heap:
 	kfree(heap);
 	return ERR_PTR(-ENOMEM);
 }
@@ -326,7 +304,6 @@ void ion_system_heap_destroy(struct ion_
 
 	for (i = 0; i < num_orders; i++)
 		ion_page_pool_destroy(sys_heap->pools[i]);
-	kfree(sys_heap->pools);
 	kfree(sys_heap);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/ion/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/android/ion/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/ion/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 menuconfig ION
 	bool "Ion Memory Manager"
-	depends on HAVE_MEMBLOCK
+	depends on HAVE_MEMBLOCK && HAS_DMA && MMU
 	select GENERIC_ALLOCATOR
 	select DMA_SHARED_BUFFER
 	---help---
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/android/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/android/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ config ANDROID_LOW_MEMORY_KILLER
 	  Registers processes to be killed when memory is low
 
 config ANDROID_INTF_ALARM_DEV
-	bool "Android alarm driver"
+	tristate "Android alarm driver"
 	depends on RTC_CLASS
 	default n
 	---help---
@@ -88,6 +88,7 @@ config SYNC
 	bool "Synchronization framework"
 	default n
 	select ANON_INODES
+	select DMA_SHARED_BUFFER
 	---help---
 	  This option enables the framework for synchronization between multiple
 	  drivers.  Sync implementations can take advantage of hardware
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/logger.c linux-libre-3.17-rc7-gnu/drivers/staging/android/logger.c
--- linux-libre-3.16-gnu/drivers/staging/android/logger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/logger.c	2014-09-28 17:29:07.000000000 -0400
@@ -110,8 +110,8 @@ static inline struct logger_log *file_ge
 		struct logger_reader *reader = file->private_data;
 
 		return reader->log;
-	} else
-		return file->private_data;
+	}
+	return file->private_data;
 }
 
 /*
@@ -159,8 +159,7 @@ static size_t get_user_hdr_len(int ver)
 {
 	if (ver < 2)
 		return sizeof(struct user_logger_entry_compat);
-	else
-		return sizeof(struct logger_entry);
+	return sizeof(struct logger_entry);
 }
 
 static ssize_t copy_header_to_user(int ver, struct logger_entry *entry,
@@ -791,7 +790,7 @@ static int __init create_log(char *log_n
 	if (unlikely(ret)) {
 		pr_err("failed to register misc device for log '%s'!\n",
 				log->misc.name);
-		goto out_free_log;
+		goto out_free_misc_name;
 	}
 
 	pr_info("created %luK log '%s'\n",
@@ -799,6 +798,9 @@ static int __init create_log(char *log_n
 
 	return 0;
 
+out_free_misc_name:
+	kfree(log->misc.name);
+
 out_free_log:
 	kfree(log);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/android/Makefile
--- linux-libre-3.16-gnu/drivers/staging/android/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,5 +9,5 @@ obj-$(CONFIG_ANDROID_TIMED_OUTPUT)	+= ti
 obj-$(CONFIG_ANDROID_TIMED_GPIO)	+= timed_gpio.o
 obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)	+= lowmemorykiller.o
 obj-$(CONFIG_ANDROID_INTF_ALARM_DEV)	+= alarm-dev.o
-obj-$(CONFIG_SYNC)			+= sync.o
+obj-$(CONFIG_SYNC)			+= sync.o sync_debug.o
 obj-$(CONFIG_SW_SYNC)			+= sw_sync.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/sw_sync.c linux-libre-3.17-rc7-gnu/drivers/staging/android/sw_sync.c
--- linux-libre-3.16-gnu/drivers/staging/android/sw_sync.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/sw_sync.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,7 +50,7 @@ static struct sync_pt *sw_sync_pt_dup(st
 {
 	struct sw_sync_pt *pt = (struct sw_sync_pt *) sync_pt;
 	struct sw_sync_timeline *obj =
-		(struct sw_sync_timeline *)sync_pt->parent;
+		(struct sw_sync_timeline *)sync_pt_parent(sync_pt);
 
 	return (struct sync_pt *) sw_sync_pt_create(obj, pt->value);
 }
@@ -59,7 +59,7 @@ static int sw_sync_pt_has_signaled(struc
 {
 	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
 	struct sw_sync_timeline *obj =
-		(struct sw_sync_timeline *)sync_pt->parent;
+		(struct sw_sync_timeline *)sync_pt_parent(sync_pt);
 
 	return sw_sync_cmp(obj->value, pt->value) >= 0;
 }
@@ -97,7 +97,6 @@ static void sw_sync_pt_value_str(struct
 				       char *str, int size)
 {
 	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
-
 	snprintf(str, size, "%d", pt->value);
 }
 
@@ -157,7 +156,6 @@ static int sw_sync_open(struct inode *in
 static int sw_sync_release(struct inode *inode, struct file *file)
 {
 	struct sw_sync_timeline *obj = file->private_data;
-
 	sync_timeline_destroy(&obj->obj);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/sync.c linux-libre-3.17-rc7-gnu/drivers/staging/android/sync.c
--- linux-libre-3.16-gnu/drivers/staging/android/sync.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/sync.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,22 +31,13 @@
 #define CREATE_TRACE_POINTS
 #include "trace/sync.h"
 
-static void sync_fence_signal_pt(struct sync_pt *pt);
-static int _sync_pt_has_signaled(struct sync_pt *pt);
-static void sync_fence_free(struct kref *kref);
-static void sync_dump(void);
-
-static LIST_HEAD(sync_timeline_list_head);
-static DEFINE_SPINLOCK(sync_timeline_list_lock);
-
-static LIST_HEAD(sync_fence_list_head);
-static DEFINE_SPINLOCK(sync_fence_list_lock);
+static const struct fence_ops android_fence_ops;
+static const struct file_operations sync_fence_fops;
 
 struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
 					   int size, const char *name)
 {
 	struct sync_timeline *obj;
-	unsigned long flags;
 
 	if (size < sizeof(struct sync_timeline))
 		return NULL;
@@ -57,17 +48,14 @@ struct sync_timeline *sync_timeline_crea
 
 	kref_init(&obj->kref);
 	obj->ops = ops;
+	obj->context = fence_context_alloc(1);
 	strlcpy(obj->name, name, sizeof(obj->name));
 
 	INIT_LIST_HEAD(&obj->child_list_head);
-	spin_lock_init(&obj->child_list_lock);
-
 	INIT_LIST_HEAD(&obj->active_list_head);
-	spin_lock_init(&obj->active_list_lock);
+	spin_lock_init(&obj->child_list_lock);
 
-	spin_lock_irqsave(&sync_timeline_list_lock, flags);
-	list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
-	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+	sync_timeline_debug_add(obj);
 
 	return obj;
 }
@@ -77,11 +65,8 @@ static void sync_timeline_free(struct kr
 {
 	struct sync_timeline *obj =
 		container_of(kref, struct sync_timeline, kref);
-	unsigned long flags;
 
-	spin_lock_irqsave(&sync_timeline_list_lock, flags);
-	list_del(&obj->sync_timeline_list);
-	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+	sync_timeline_debug_remove(obj);
 
 	if (obj->ops->release_obj)
 		obj->ops->release_obj(obj);
@@ -89,6 +74,16 @@ static void sync_timeline_free(struct kr
 	kfree(obj);
 }
 
+static void sync_timeline_get(struct sync_timeline *obj)
+{
+	kref_get(&obj->kref);
+}
+
+static void sync_timeline_put(struct sync_timeline *obj)
+{
+	kref_put(&obj->kref, sync_timeline_free);
+}
+
 void sync_timeline_destroy(struct sync_timeline *obj)
 {
 	obj->destroyed = true;
@@ -102,75 +97,33 @@ void sync_timeline_destroy(struct sync_t
 	 * signal any children that their parent is going away.
 	 */
 	sync_timeline_signal(obj);
-
-	kref_put(&obj->kref, sync_timeline_free);
+	sync_timeline_put(obj);
 }
 EXPORT_SYMBOL(sync_timeline_destroy);
 
-static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt)
-{
-	unsigned long flags;
-
-	pt->parent = obj;
-
-	spin_lock_irqsave(&obj->child_list_lock, flags);
-	list_add_tail(&pt->child_list, &obj->child_list_head);
-	spin_unlock_irqrestore(&obj->child_list_lock, flags);
-}
-
-static void sync_timeline_remove_pt(struct sync_pt *pt)
-{
-	struct sync_timeline *obj = pt->parent;
-	unsigned long flags;
-
-	spin_lock_irqsave(&obj->active_list_lock, flags);
-	if (!list_empty(&pt->active_list))
-		list_del_init(&pt->active_list);
-	spin_unlock_irqrestore(&obj->active_list_lock, flags);
-
-	spin_lock_irqsave(&obj->child_list_lock, flags);
-	if (!list_empty(&pt->child_list))
-		list_del_init(&pt->child_list);
-
-	spin_unlock_irqrestore(&obj->child_list_lock, flags);
-}
-
 void sync_timeline_signal(struct sync_timeline *obj)
 {
 	unsigned long flags;
 	LIST_HEAD(signaled_pts);
-	struct list_head *pos, *n;
+	struct sync_pt *pt, *next;
 
 	trace_sync_timeline(obj);
 
-	spin_lock_irqsave(&obj->active_list_lock, flags);
-
-	list_for_each_safe(pos, n, &obj->active_list_head) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, active_list);
+	spin_lock_irqsave(&obj->child_list_lock, flags);
 
-		if (_sync_pt_has_signaled(pt)) {
-			list_del_init(pos);
-			list_add(&pt->signaled_list, &signaled_pts);
-			kref_get(&pt->fence->kref);
-		}
+	list_for_each_entry_safe(pt, next, &obj->active_list_head,
+				 active_list) {
+		if (fence_is_signaled_locked(&pt->base))
+			list_del(&pt->active_list);
 	}
 
-	spin_unlock_irqrestore(&obj->active_list_lock, flags);
-
-	list_for_each_safe(pos, n, &signaled_pts) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, signaled_list);
-
-		list_del_init(pos);
-		sync_fence_signal_pt(pt);
-		kref_put(&pt->fence->kref, sync_fence_free);
-	}
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
 }
 EXPORT_SYMBOL(sync_timeline_signal);
 
-struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size)
+struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size)
 {
+	unsigned long flags;
 	struct sync_pt *pt;
 
 	if (size < sizeof(struct sync_pt))
@@ -180,87 +133,28 @@ struct sync_pt *sync_pt_create(struct sy
 	if (pt == NULL)
 		return NULL;
 
+	spin_lock_irqsave(&obj->child_list_lock, flags);
+	sync_timeline_get(obj);
+	fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock,
+		   obj->context, ++obj->value);
+	list_add_tail(&pt->child_list, &obj->child_list_head);
 	INIT_LIST_HEAD(&pt->active_list);
-	kref_get(&parent->kref);
-	sync_timeline_add_pt(parent, pt);
-
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
 	return pt;
 }
 EXPORT_SYMBOL(sync_pt_create);
 
 void sync_pt_free(struct sync_pt *pt)
 {
-	if (pt->parent->ops->free_pt)
-		pt->parent->ops->free_pt(pt);
-
-	sync_timeline_remove_pt(pt);
-
-	kref_put(&pt->parent->kref, sync_timeline_free);
-
-	kfree(pt);
+	fence_put(&pt->base);
 }
 EXPORT_SYMBOL(sync_pt_free);
 
-/* call with pt->parent->active_list_lock held */
-static int _sync_pt_has_signaled(struct sync_pt *pt)
-{
-	int old_status = pt->status;
-
-	if (!pt->status)
-		pt->status = pt->parent->ops->has_signaled(pt);
-
-	if (!pt->status && pt->parent->destroyed)
-		pt->status = -ENOENT;
-
-	if (pt->status != old_status)
-		pt->timestamp = ktime_get();
-
-	return pt->status;
-}
-
-static struct sync_pt *sync_pt_dup(struct sync_pt *pt)
-{
-	return pt->parent->ops->dup(pt);
-}
-
-/* Adds a sync pt to the active queue.  Called when added to a fence */
-static void sync_pt_activate(struct sync_pt *pt)
-{
-	struct sync_timeline *obj = pt->parent;
-	unsigned long flags;
-	int err;
-
-	spin_lock_irqsave(&obj->active_list_lock, flags);
-
-	err = _sync_pt_has_signaled(pt);
-	if (err != 0)
-		goto out;
-
-	list_add_tail(&pt->active_list, &obj->active_list_head);
-
-out:
-	spin_unlock_irqrestore(&obj->active_list_lock, flags);
-}
-
-static int sync_fence_release(struct inode *inode, struct file *file);
-static unsigned int sync_fence_poll(struct file *file, poll_table *wait);
-static long sync_fence_ioctl(struct file *file, unsigned int cmd,
-			     unsigned long arg);
-
-
-static const struct file_operations sync_fence_fops = {
-	.release = sync_fence_release,
-	.poll = sync_fence_poll,
-	.unlocked_ioctl = sync_fence_ioctl,
-	.compat_ioctl = sync_fence_ioctl,
-};
-
-static struct sync_fence *sync_fence_alloc(const char *name)
+static struct sync_fence *sync_fence_alloc(int size, const char *name)
 {
 	struct sync_fence *fence;
-	unsigned long flags;
 
-	fence = kzalloc(sizeof(struct sync_fence), GFP_KERNEL);
+	fence = kzalloc(size, GFP_KERNEL);
 	if (fence == NULL)
 		return NULL;
 
@@ -272,16 +166,8 @@ static struct sync_fence *sync_fence_all
 	kref_init(&fence->kref);
 	strlcpy(fence->name, name, sizeof(fence->name));
 
-	INIT_LIST_HEAD(&fence->pt_list_head);
-	INIT_LIST_HEAD(&fence->waiter_list_head);
-	spin_lock_init(&fence->waiter_list_lock);
-
 	init_waitqueue_head(&fence->wq);
 
-	spin_lock_irqsave(&sync_fence_list_lock, flags);
-	list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
-	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
-
 	return fence;
 
 err:
@@ -289,120 +175,41 @@ err:
 	return NULL;
 }
 
-/* TODO: implement a create which takes more that one sync_pt */
-struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
+static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
 {
+	struct sync_fence_cb *check;
 	struct sync_fence *fence;
 
-	if (pt->fence)
-		return NULL;
-
-	fence = sync_fence_alloc(name);
-	if (fence == NULL)
-		return NULL;
-
-	pt->fence = fence;
-	list_add(&pt->pt_list, &fence->pt_list_head);
-	sync_pt_activate(pt);
-
-	/*
-	 * signal the fence in case pt was activated before
-	 * sync_pt_activate(pt) was called
-	 */
-	sync_fence_signal_pt(pt);
-
-	return fence;
-}
-EXPORT_SYMBOL(sync_fence_create);
-
-static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src)
-{
-	struct list_head *pos;
-
-	list_for_each(pos, &src->pt_list_head) {
-		struct sync_pt *orig_pt =
-			container_of(pos, struct sync_pt, pt_list);
-		struct sync_pt *new_pt = sync_pt_dup(orig_pt);
-
-		if (new_pt == NULL)
-			return -ENOMEM;
-
-		new_pt->fence = dst;
-		list_add(&new_pt->pt_list, &dst->pt_list_head);
-	}
-
-	return 0;
-}
-
-static int sync_fence_merge_pts(struct sync_fence *dst, struct sync_fence *src)
-{
-	struct list_head *src_pos, *dst_pos, *n;
-
-	list_for_each(src_pos, &src->pt_list_head) {
-		struct sync_pt *src_pt =
-			container_of(src_pos, struct sync_pt, pt_list);
-		bool collapsed = false;
-
-		list_for_each_safe(dst_pos, n, &dst->pt_list_head) {
-			struct sync_pt *dst_pt =
-				container_of(dst_pos, struct sync_pt, pt_list);
-			/* collapse two sync_pts on the same timeline
-			 * to a single sync_pt that will signal at
-			 * the later of the two
-			 */
-			if (dst_pt->parent == src_pt->parent) {
-				if (dst_pt->parent->ops->compare(dst_pt, src_pt)
-						 == -1) {
-					struct sync_pt *new_pt =
-						sync_pt_dup(src_pt);
-					if (new_pt == NULL)
-						return -ENOMEM;
-
-					new_pt->fence = dst;
-					list_replace(&dst_pt->pt_list,
-						     &new_pt->pt_list);
-					sync_pt_free(dst_pt);
-				}
-				collapsed = true;
-				break;
-			}
-		}
-
-		if (!collapsed) {
-			struct sync_pt *new_pt = sync_pt_dup(src_pt);
-
-			if (new_pt == NULL)
-				return -ENOMEM;
-
-			new_pt->fence = dst;
-			list_add(&new_pt->pt_list, &dst->pt_list_head);
-		}
-	}
+	check = container_of(cb, struct sync_fence_cb, cb);
+	fence = check->fence;
 
-	return 0;
+	if (atomic_dec_and_test(&fence->status))
+		wake_up_all(&fence->wq);
 }
 
-static void sync_fence_detach_pts(struct sync_fence *fence)
+/* TODO: implement a create which takes more that one sync_pt */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
 {
-	struct list_head *pos, *n;
+	struct sync_fence *fence;
 
-	list_for_each_safe(pos, n, &fence->pt_list_head) {
-		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+	fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name);
+	if (fence == NULL)
+		return NULL;
 
-		sync_timeline_remove_pt(pt);
-	}
-}
+	fence->num_fences = 1;
+	atomic_set(&fence->status, 1);
 
-static void sync_fence_free_pts(struct sync_fence *fence)
-{
-	struct list_head *pos, *n;
+	fence->cbs[0].sync_pt = &pt->base;
+	fence->cbs[0].fence = fence;
+	if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
+			       fence_check_cb_func))
+		atomic_dec(&fence->status);
 
-	list_for_each_safe(pos, n, &fence->pt_list_head) {
-		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+	sync_fence_debug_add(fence);
 
-		sync_pt_free(pt);
-	}
+	return fence;
 }
+EXPORT_SYMBOL(sync_fence_create);
 
 struct sync_fence *sync_fence_fdget(int fd)
 {
@@ -434,197 +241,155 @@ void sync_fence_install(struct sync_fenc
 }
 EXPORT_SYMBOL(sync_fence_install);
 
-static int sync_fence_get_status(struct sync_fence *fence)
+static void sync_fence_add_pt(struct sync_fence *fence,
+			      int *i, struct fence *pt)
 {
-	struct list_head *pos;
-	int status = 1;
-
-	list_for_each(pos, &fence->pt_list_head) {
-		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
-		int pt_status = pt->status;
+	fence->cbs[*i].sync_pt = pt;
+	fence->cbs[*i].fence = fence;
 
-		if (pt_status < 0) {
-			status = pt_status;
-			break;
-		} else if (status == 1) {
-			status = pt_status;
-		}
+	if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) {
+		fence_get(pt);
+		(*i)++;
 	}
-
-	return status;
 }
 
 struct sync_fence *sync_fence_merge(const char *name,
 				    struct sync_fence *a, struct sync_fence *b)
 {
+	int num_fences = a->num_fences + b->num_fences;
 	struct sync_fence *fence;
-	struct list_head *pos;
-	int err;
+	int i, i_a, i_b;
+	unsigned long size = offsetof(struct sync_fence, cbs[num_fences]);
 
-	fence = sync_fence_alloc(name);
+	fence = sync_fence_alloc(size, name);
 	if (fence == NULL)
 		return NULL;
 
-	err = sync_fence_copy_pts(fence, a);
-	if (err < 0)
-		goto err;
+	atomic_set(&fence->status, num_fences);
 
-	err = sync_fence_merge_pts(fence, b);
-	if (err < 0)
-		goto err;
+	/*
+	 * Assume sync_fence a and b are both ordered and have no
+	 * duplicates with the same context.
+	 *
+	 * If a sync_fence can only be created with sync_fence_merge
+	 * and sync_fence_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->cbs[i_a].sync_pt;
+		struct fence *pt_b = b->cbs[i_b].sync_pt;
 
-	list_for_each(pos, &fence->pt_list_head) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, pt_list);
-		sync_pt_activate(pt);
+		if (pt_a->context < pt_b->context) {
+			sync_fence_add_pt(fence, &i, pt_a);
+
+			i_a++;
+		} else if (pt_a->context > pt_b->context) {
+			sync_fence_add_pt(fence, &i, pt_b);
+
+			i_b++;
+		} else {
+			if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+				sync_fence_add_pt(fence, &i, pt_a);
+			else
+				sync_fence_add_pt(fence, &i, pt_b);
+
+			i_a++;
+			i_b++;
+		}
 	}
 
-	/*
-	 * signal the fence in case one of it's pts were activated before
-	 * they were activated
-	 */
-	sync_fence_signal_pt(list_first_entry(&fence->pt_list_head,
-					      struct sync_pt,
-					      pt_list));
+	for (; i_a < a->num_fences; i_a++)
+		sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt);
+
+	for (; i_b < b->num_fences; i_b++)
+		sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt);
 
+	if (num_fences > i)
+		atomic_sub(num_fences - i, &fence->status);
+	fence->num_fences = i;
+
+	sync_fence_debug_add(fence);
 	return fence;
-err:
-	sync_fence_free_pts(fence);
-	kfree(fence);
-	return NULL;
 }
 EXPORT_SYMBOL(sync_fence_merge);
 
-static void sync_fence_signal_pt(struct sync_pt *pt)
+int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+				 int wake_flags, void *key)
 {
-	LIST_HEAD(signaled_waiters);
-	struct sync_fence *fence = pt->fence;
-	struct list_head *pos;
-	struct list_head *n;
-	unsigned long flags;
-	int status;
-
-	status = sync_fence_get_status(fence);
-
-	spin_lock_irqsave(&fence->waiter_list_lock, flags);
-	/*
-	 * this should protect against two threads racing on the signaled
-	 * false -> true transition
-	 */
-	if (status && !fence->status) {
-		list_for_each_safe(pos, n, &fence->waiter_list_head)
-			list_move(pos, &signaled_waiters);
-
-		fence->status = status;
-	} else {
-		status = 0;
-	}
-	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+	struct sync_fence_waiter *wait;
 
-	if (status) {
-		list_for_each_safe(pos, n, &signaled_waiters) {
-			struct sync_fence_waiter *waiter =
-				container_of(pos, struct sync_fence_waiter,
-					     waiter_list);
+	wait = container_of(curr, struct sync_fence_waiter, work);
+	list_del_init(&wait->work.task_list);
 
-			list_del(pos);
-			waiter->callback(fence, waiter);
-		}
-		wake_up(&fence->wq);
-	}
+	wait->callback(wait->work.private, wait);
+	return 1;
 }
 
 int sync_fence_wait_async(struct sync_fence *fence,
 			  struct sync_fence_waiter *waiter)
 {
+	int err = atomic_read(&fence->status);
 	unsigned long flags;
-	int err = 0;
 
-	spin_lock_irqsave(&fence->waiter_list_lock, flags);
+	if (err < 0)
+		return err;
 
-	if (fence->status) {
-		err = fence->status;
-		goto out;
-	}
+	if (!err)
+		return 1;
 
-	list_add_tail(&waiter->waiter_list, &fence->waiter_list_head);
-out:
-	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+	init_waitqueue_func_entry(&waiter->work, sync_fence_wake_up_wq);
+	waiter->work.private = fence;
 
-	return err;
+	spin_lock_irqsave(&fence->wq.lock, flags);
+	err = atomic_read(&fence->status);
+	if (err > 0)
+		__add_wait_queue_tail(&fence->wq, &waiter->work);
+	spin_unlock_irqrestore(&fence->wq.lock, flags);
+
+	if (err < 0)
+		return err;
+
+	return !err;
 }
 EXPORT_SYMBOL(sync_fence_wait_async);
 
 int sync_fence_cancel_async(struct sync_fence *fence,
 			     struct sync_fence_waiter *waiter)
 {
-	struct list_head *pos;
-	struct list_head *n;
 	unsigned long flags;
-	int ret = -ENOENT;
+	int ret = 0;
 
-	spin_lock_irqsave(&fence->waiter_list_lock, flags);
-	/*
-	 * Make sure waiter is still in waiter_list because it is possible for
-	 * the waiter to be removed from the list while the callback is still
-	 * pending.
-	 */
-	list_for_each_safe(pos, n, &fence->waiter_list_head) {
-		struct sync_fence_waiter *list_waiter =
-			container_of(pos, struct sync_fence_waiter,
-				     waiter_list);
-		if (list_waiter == waiter) {
-			list_del(pos);
-			ret = 0;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+	spin_lock_irqsave(&fence->wq.lock, flags);
+	if (!list_empty(&waiter->work.task_list))
+		list_del_init(&waiter->work.task_list);
+	else
+		ret = -ENOENT;
+	spin_unlock_irqrestore(&fence->wq.lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(sync_fence_cancel_async);
 
-static bool sync_fence_check(struct sync_fence *fence)
-{
-	/*
-	 * Make sure that reads to fence->status are ordered with the
-	 * wait queue event triggering
-	 */
-	smp_rmb();
-	return fence->status != 0;
-}
-
 int sync_fence_wait(struct sync_fence *fence, long timeout)
 {
-	int err = 0;
-	struct sync_pt *pt;
-
-	trace_sync_wait(fence, 1);
-	list_for_each_entry(pt, &fence->pt_list_head, pt_list)
-		trace_sync_pt(pt);
+	long ret;
+	int i;
 
-	if (timeout > 0) {
+	if (timeout < 0)
+		timeout = MAX_SCHEDULE_TIMEOUT;
+	else
 		timeout = msecs_to_jiffies(timeout);
-		err = wait_event_interruptible_timeout(fence->wq,
-						       sync_fence_check(fence),
-						       timeout);
-	} else if (timeout < 0) {
-		err = wait_event_interruptible(fence->wq,
-					       sync_fence_check(fence));
-	}
-	trace_sync_wait(fence, 0);
 
-	if (err < 0)
-		return err;
-
-	if (fence->status < 0) {
-		pr_info("fence error %d on [%p]\n", fence->status, fence);
-		sync_dump();
-		return fence->status;
-	}
+	trace_sync_wait(fence, 1);
+	for (i = 0; i < fence->num_fences; ++i)
+		trace_sync_pt(fence->cbs[i].sync_pt);
+	ret = wait_event_interruptible_timeout(fence->wq,
+					       atomic_read(&fence->status) <= 0,
+					       timeout);
+	trace_sync_wait(fence, 0);
 
-	if (fence->status == 0) {
-		if (timeout > 0) {
+	if (ret < 0)
+		return ret;
+	else if (ret == 0) {
+		if (timeout) {
 			pr_info("fence timeout on [%p] after %dms\n", fence,
 				jiffies_to_msecs(timeout));
 			sync_dump();
@@ -632,15 +397,136 @@ int sync_fence_wait(struct sync_fence *f
 		return -ETIME;
 	}
 
-	return 0;
+	ret = atomic_read(&fence->status);
+	if (ret) {
+		pr_info("fence error %ld on [%p]\n", ret, fence);
+		sync_dump();
+	}
+	return ret;
 }
 EXPORT_SYMBOL(sync_fence_wait);
 
+static const char *android_fence_get_driver_name(struct fence *fence)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	return parent->ops->driver_name;
+}
+
+static const char *android_fence_get_timeline_name(struct fence *fence)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	return parent->name;
+}
+
+static void android_fence_release(struct fence *fence)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+	unsigned long flags;
+
+	spin_lock_irqsave(fence->lock, flags);
+	list_del(&pt->child_list);
+	if (WARN_ON_ONCE(!list_empty(&pt->active_list)))
+		list_del(&pt->active_list);
+	spin_unlock_irqrestore(fence->lock, flags);
+
+	if (parent->ops->free_pt)
+		parent->ops->free_pt(pt);
+
+	sync_timeline_put(parent);
+	fence_free(&pt->base);
+}
+
+static bool android_fence_signaled(struct fence *fence)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+	int ret;
+
+	ret = parent->ops->has_signaled(pt);
+	if (ret < 0)
+		fence->status = ret;
+	return ret;
+}
+
+static bool android_fence_enable_signaling(struct fence *fence)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	if (android_fence_signaled(fence))
+		return false;
+
+	list_add_tail(&pt->active_list, &parent->active_list_head);
+	return true;
+}
+
+static int android_fence_fill_driver_data(struct fence *fence,
+					  void *data, int size)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	if (!parent->ops->fill_driver_data)
+		return 0;
+	return parent->ops->fill_driver_data(pt, data, size);
+}
+
+static void android_fence_value_str(struct fence *fence,
+				    char *str, int size)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	if (!parent->ops->pt_value_str) {
+		if (size)
+			*str = 0;
+		return;
+	}
+	parent->ops->pt_value_str(pt, str, size);
+}
+
+static void android_fence_timeline_value_str(struct fence *fence,
+					     char *str, int size)
+{
+	struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	if (!parent->ops->timeline_value_str) {
+		if (size)
+			*str = 0;
+		return;
+	}
+	parent->ops->timeline_value_str(parent, str, size);
+}
+
+static const struct fence_ops android_fence_ops = {
+	.get_driver_name = android_fence_get_driver_name,
+	.get_timeline_name = android_fence_get_timeline_name,
+	.enable_signaling = android_fence_enable_signaling,
+	.signaled = android_fence_signaled,
+	.wait = fence_default_wait,
+	.release = android_fence_release,
+	.fill_driver_data = android_fence_fill_driver_data,
+	.fence_value_str = android_fence_value_str,
+	.timeline_value_str = android_fence_timeline_value_str,
+};
+
 static void sync_fence_free(struct kref *kref)
 {
 	struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+	int i, status = atomic_read(&fence->status);
 
-	sync_fence_free_pts(fence);
+	for (i = 0; i < fence->num_fences; ++i) {
+		if (status)
+			fence_remove_callback(fence->cbs[i].sync_pt,
+					      &fence->cbs[i].cb);
+		fence_put(fence->cbs[i].sync_pt);
+	}
 
 	kfree(fence);
 }
@@ -648,47 +534,27 @@ static void sync_fence_free(struct kref
 static int sync_fence_release(struct inode *inode, struct file *file)
 {
 	struct sync_fence *fence = file->private_data;
-	unsigned long flags;
-
-	/*
-	 * We need to remove all ways to access this fence before droping
-	 * our ref.
-	 *
-	 * start with its membership in the global fence list
-	 */
-	spin_lock_irqsave(&sync_fence_list_lock, flags);
-	list_del(&fence->sync_fence_list);
-	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
 
-	/*
-	 * remove its pts from their parents so that sync_timeline_signal()
-	 * can't reference the fence.
-	 */
-	sync_fence_detach_pts(fence);
+	sync_fence_debug_remove(fence);
 
 	kref_put(&fence->kref, sync_fence_free);
-
 	return 0;
 }
 
 static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
 {
 	struct sync_fence *fence = file->private_data;
+	int status;
 
 	poll_wait(file, &fence->wq, wait);
 
-	/*
-	 * Make sure that reads to fence->status are ordered with the
-	 * wait queue event triggering
-	 */
-	smp_rmb();
+	status = atomic_read(&fence->status);
 
-	if (fence->status == 1)
+	if (!status)
 		return POLLIN;
-	else if (fence->status < 0)
+	else if (status < 0)
 		return POLLERR;
-	else
-		return 0;
+	return 0;
 }
 
 static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
@@ -750,7 +616,7 @@ err_put_fd:
 	return err;
 }
 
-static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size)
+static int sync_fill_pt_info(struct fence *fence, void *data, int size)
 {
 	struct sync_pt_info *info = data;
 	int ret;
@@ -760,20 +626,24 @@ static int sync_fill_pt_info(struct sync
 
 	info->len = sizeof(struct sync_pt_info);
 
-	if (pt->parent->ops->fill_driver_data) {
-		ret = pt->parent->ops->fill_driver_data(pt, info->driver_data,
-							size - sizeof(*info));
+	if (fence->ops->fill_driver_data) {
+		ret = fence->ops->fill_driver_data(fence, info->driver_data,
+						   size - sizeof(*info));
 		if (ret < 0)
 			return ret;
 
 		info->len += ret;
 	}
 
-	strlcpy(info->obj_name, pt->parent->name, sizeof(info->obj_name));
-	strlcpy(info->driver_name, pt->parent->ops->driver_name,
+	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));
-	info->status = pt->status;
-	info->timestamp_ns = ktime_to_ns(pt->timestamp);
+	if (fence_is_signaled(fence))
+		info->status = fence->status >= 0 ? 1 : fence->status;
+	else
+		info->status = 0;
+	info->timestamp_ns = ktime_to_ns(fence->timestamp);
 
 	return info->len;
 }
@@ -782,10 +652,9 @@ static long sync_fence_ioctl_fence_info(
 					unsigned long arg)
 {
 	struct sync_fence_info_data *data;
-	struct list_head *pos;
 	__u32 size;
 	__u32 len = 0;
-	int ret;
+	int ret, i;
 
 	if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
 		return -EFAULT;
@@ -801,12 +670,14 @@ static long sync_fence_ioctl_fence_info(
 		return -ENOMEM;
 
 	strlcpy(data->name, fence->name, sizeof(data->name));
-	data->status = fence->status;
+	data->status = atomic_read(&fence->status);
+	if (data->status >= 0)
+		data->status = !data->status;
+
 	len = sizeof(struct sync_fence_info_data);
 
-	list_for_each(pos, &fence->pt_list_head) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, pt_list);
+	for (i = 0; i < fence->num_fences; ++i) {
+		struct fence *pt = fence->cbs[i].sync_pt;
 
 		ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
 
@@ -833,7 +704,6 @@ static long sync_fence_ioctl(struct file
 			     unsigned long arg)
 {
 	struct sync_fence *fence = file->private_data;
-
 	switch (cmd) {
 	case SYNC_IOC_WAIT:
 		return sync_fence_ioctl_wait(fence, arg);
@@ -849,181 +719,10 @@ static long sync_fence_ioctl(struct file
 	}
 }
 
-#ifdef CONFIG_DEBUG_FS
-static const char *sync_status_str(int status)
-{
-	if (status > 0)
-		return "signaled";
-	else if (status == 0)
-		return "active";
-	else
-		return "error";
-}
-
-static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
-{
-	int status = pt->status;
-
-	seq_printf(s, "  %s%spt %s",
-		   fence ? pt->parent->name : "",
-		   fence ? "_" : "",
-		   sync_status_str(status));
-	if (pt->status) {
-		struct timeval tv = ktime_to_timeval(pt->timestamp);
-
-		seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
-	}
-
-	if (pt->parent->ops->timeline_value_str &&
-	    pt->parent->ops->pt_value_str) {
-		char value[64];
-
-		pt->parent->ops->pt_value_str(pt, value, sizeof(value));
-		seq_printf(s, ": %s", value);
-		if (fence) {
-			pt->parent->ops->timeline_value_str(pt->parent, value,
-						    sizeof(value));
-			seq_printf(s, " / %s", value);
-		}
-	} else if (pt->parent->ops->print_pt) {
-		seq_puts(s, ": ");
-		pt->parent->ops->print_pt(s, pt);
-	}
-
-	seq_puts(s, "\n");
-}
-
-static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
-{
-	struct list_head *pos;
-	unsigned long flags;
-
-	seq_printf(s, "%s %s", obj->name, obj->ops->driver_name);
-
-	if (obj->ops->timeline_value_str) {
-		char value[64];
-
-		obj->ops->timeline_value_str(obj, value, sizeof(value));
-		seq_printf(s, ": %s", value);
-	} else if (obj->ops->print_obj) {
-		seq_puts(s, ": ");
-		obj->ops->print_obj(s, obj);
-	}
-
-	seq_puts(s, "\n");
-
-	spin_lock_irqsave(&obj->child_list_lock, flags);
-	list_for_each(pos, &obj->child_list_head) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, child_list);
-		sync_print_pt(s, pt, false);
-	}
-	spin_unlock_irqrestore(&obj->child_list_lock, flags);
-}
-
-static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
-{
-	struct list_head *pos;
-	unsigned long flags;
-
-	seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
-		   sync_status_str(fence->status));
-
-	list_for_each(pos, &fence->pt_list_head) {
-		struct sync_pt *pt =
-			container_of(pos, struct sync_pt, pt_list);
-		sync_print_pt(s, pt, true);
-	}
-
-	spin_lock_irqsave(&fence->waiter_list_lock, flags);
-	list_for_each(pos, &fence->waiter_list_head) {
-		struct sync_fence_waiter *waiter =
-			container_of(pos, struct sync_fence_waiter,
-				     waiter_list);
-
-		seq_printf(s, "waiter %pF\n", waiter->callback);
-	}
-	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
-}
-
-static int sync_debugfs_show(struct seq_file *s, void *unused)
-{
-	unsigned long flags;
-	struct list_head *pos;
-
-	seq_puts(s, "objs:\n--------------\n");
-
-	spin_lock_irqsave(&sync_timeline_list_lock, flags);
-	list_for_each(pos, &sync_timeline_list_head) {
-		struct sync_timeline *obj =
-			container_of(pos, struct sync_timeline,
-				     sync_timeline_list);
-
-		sync_print_obj(s, obj);
-		seq_puts(s, "\n");
-	}
-	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
-
-	seq_puts(s, "fences:\n--------------\n");
-
-	spin_lock_irqsave(&sync_fence_list_lock, flags);
-	list_for_each(pos, &sync_fence_list_head) {
-		struct sync_fence *fence =
-			container_of(pos, struct sync_fence, sync_fence_list);
-
-		sync_print_fence(s, fence);
-		seq_puts(s, "\n");
-	}
-	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
-	return 0;
-}
-
-static int sync_debugfs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, sync_debugfs_show, inode->i_private);
-}
-
-static const struct file_operations sync_debugfs_fops = {
-	.open           = sync_debugfs_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
+static const struct file_operations sync_fence_fops = {
+	.release = sync_fence_release,
+	.poll = sync_fence_poll,
+	.unlocked_ioctl = sync_fence_ioctl,
+	.compat_ioctl = sync_fence_ioctl,
 };
 
-static __init int sync_debugfs_init(void)
-{
-	debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
-	return 0;
-}
-late_initcall(sync_debugfs_init);
-
-#define DUMP_CHUNK 256
-static char sync_dump_buf[64 * 1024];
-static void sync_dump(void)
-{
-	struct seq_file s = {
-		.buf = sync_dump_buf,
-		.size = sizeof(sync_dump_buf) - 1,
-	};
-	int i;
-
-	sync_debugfs_show(&s, NULL);
-
-	for (i = 0; i < s.count; i += DUMP_CHUNK) {
-		if ((s.count - i) > DUMP_CHUNK) {
-			char c = s.buf[i + DUMP_CHUNK];
-
-			s.buf[i + DUMP_CHUNK] = 0;
-			pr_cont("%s", s.buf + i);
-			s.buf[i + DUMP_CHUNK] = c;
-		} else {
-			s.buf[s.count] = 0;
-			pr_cont("%s", s.buf + i);
-		}
-	}
-}
-#else
-static void sync_dump(void)
-{
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/sync_debug.c linux-libre-3.17-rc7-gnu/drivers/staging/android/sync_debug.c
--- linux-libre-3.16-gnu/drivers/staging/android/sync_debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/sync_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,252 @@
+/*
+ * drivers/base/sync.c
+ *
+ * Copyright (C) 2012 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/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+#include "sync.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+static LIST_HEAD(sync_timeline_list_head);
+static DEFINE_SPINLOCK(sync_timeline_list_lock);
+static LIST_HEAD(sync_fence_list_head);
+static DEFINE_SPINLOCK(sync_fence_list_lock);
+
+void sync_timeline_debug_add(struct sync_timeline *obj)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+}
+
+void sync_timeline_debug_remove(struct sync_timeline *obj)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_del(&obj->sync_timeline_list);
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+}
+
+void sync_fence_debug_add(struct sync_fence *fence)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+}
+
+void sync_fence_debug_remove(struct sync_fence *fence)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_del(&fence->sync_fence_list);
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+}
+
+static const char *sync_status_str(int status)
+{
+	if (status == 0)
+		return "signaled";
+
+	if (status > 0)
+		return "active";
+
+	return "error";
+}
+
+static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
+{
+	int status = 1;
+	struct sync_timeline *parent = sync_pt_parent(pt);
+
+	if (fence_is_signaled_locked(&pt->base))
+		status = pt->base.status;
+
+	seq_printf(s, "  %s%spt %s",
+		   fence ? parent->name : "",
+		   fence ? "_" : "",
+		   sync_status_str(status));
+
+	if (status <= 0) {
+		struct timeval tv = ktime_to_timeval(pt->base.timestamp);
+
+		seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
+	}
+
+	if (parent->ops->timeline_value_str &&
+	    parent->ops->pt_value_str) {
+		char value[64];
+
+		parent->ops->pt_value_str(pt, value, sizeof(value));
+		seq_printf(s, ": %s", value);
+		if (fence) {
+			parent->ops->timeline_value_str(parent, value,
+						    sizeof(value));
+			seq_printf(s, " / %s", value);
+		}
+	}
+
+	seq_puts(s, "\n");
+}
+
+static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
+{
+	struct list_head *pos;
+	unsigned long flags;
+
+	seq_printf(s, "%s %s", obj->name, obj->ops->driver_name);
+
+	if (obj->ops->timeline_value_str) {
+		char value[64];
+
+		obj->ops->timeline_value_str(obj, value, sizeof(value));
+		seq_printf(s, ": %s", value);
+	}
+
+	seq_puts(s, "\n");
+
+	spin_lock_irqsave(&obj->child_list_lock, flags);
+	list_for_each(pos, &obj->child_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, child_list);
+		sync_print_pt(s, pt, false);
+	}
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
+{
+	wait_queue_t *pos;
+	unsigned long flags;
+	int i;
+
+	seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
+		   sync_status_str(atomic_read(&fence->status)));
+
+	for (i = 0; i < fence->num_fences; ++i) {
+		struct sync_pt *pt =
+			container_of(fence->cbs[i].sync_pt,
+				     struct sync_pt, base);
+
+		sync_print_pt(s, pt, true);
+	}
+
+	spin_lock_irqsave(&fence->wq.lock, flags);
+	list_for_each_entry(pos, &fence->wq.task_list, task_list) {
+		struct sync_fence_waiter *waiter;
+
+		if (pos->func != &sync_fence_wake_up_wq)
+			continue;
+
+		waiter = container_of(pos, struct sync_fence_waiter, work);
+
+		seq_printf(s, "waiter %pF\n", waiter->callback);
+	}
+	spin_unlock_irqrestore(&fence->wq.lock, flags);
+}
+
+static int sync_debugfs_show(struct seq_file *s, void *unused)
+{
+	unsigned long flags;
+	struct list_head *pos;
+
+	seq_puts(s, "objs:\n--------------\n");
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_for_each(pos, &sync_timeline_list_head) {
+		struct sync_timeline *obj =
+			container_of(pos, struct sync_timeline,
+				     sync_timeline_list);
+
+		sync_print_obj(s, obj);
+		seq_puts(s, "\n");
+	}
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+	seq_puts(s, "fences:\n--------------\n");
+
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_for_each(pos, &sync_fence_list_head) {
+		struct sync_fence *fence =
+			container_of(pos, struct sync_fence, sync_fence_list);
+
+		sync_print_fence(s, fence);
+		seq_puts(s, "\n");
+	}
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+	return 0;
+}
+
+static int sync_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sync_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations sync_debugfs_fops = {
+	.open           = sync_debugfs_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static __init int sync_debugfs_init(void)
+{
+	debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
+	return 0;
+}
+late_initcall(sync_debugfs_init);
+
+#define DUMP_CHUNK 256
+static char sync_dump_buf[64 * 1024];
+void sync_dump(void)
+{
+	struct seq_file s = {
+		.buf = sync_dump_buf,
+		.size = sizeof(sync_dump_buf) - 1,
+	};
+	int i;
+
+	sync_debugfs_show(&s, NULL);
+
+	for (i = 0; i < s.count; i += DUMP_CHUNK) {
+		if ((s.count - i) > DUMP_CHUNK) {
+			char c = s.buf[i + DUMP_CHUNK];
+
+			s.buf[i + DUMP_CHUNK] = 0;
+			pr_cont("%s", s.buf + i);
+			s.buf[i + DUMP_CHUNK] = c;
+		} else {
+			s.buf[s.count] = 0;
+			pr_cont("%s", s.buf + i);
+		}
+	}
+}
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/sync.h linux-libre-3.17-rc7-gnu/drivers/staging/android/sync.h
--- linux-libre-3.16-gnu/drivers/staging/android/sync.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/sync.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/fence.h>
 
 #include "uapi/sync.h"
 
@@ -40,8 +41,6 @@ struct sync_fence;
  *			 -1 if a will signal before b
  * @free_pt:		called before sync_pt is freed
  * @release_obj:	called before sync_timeline is freed
- * @print_obj:		deprecated
- * @print_pt:		deprecated
  * @fill_driver_data:	write implementation specific driver data to data.
  *			  should return an error if there is not enough room
  *			  as specified by size.  This information is returned
@@ -67,13 +66,6 @@ struct sync_timeline_ops {
 	/* optional */
 	void (*release_obj)(struct sync_timeline *sync_timeline);
 
-	/* deprecated */
-	void (*print_obj)(struct seq_file *s,
-			  struct sync_timeline *sync_timeline);
-
-	/* deprecated */
-	void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt);
-
 	/* optional */
 	int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
 
@@ -104,19 +96,21 @@ struct sync_timeline {
 
 	/* protected by child_list_lock */
 	bool			destroyed;
+	int			context, value;
 
 	struct list_head	child_list_head;
 	spinlock_t		child_list_lock;
 
 	struct list_head	active_list_head;
-	spinlock_t		active_list_lock;
 
+#ifdef CONFIG_DEBUG_FS
 	struct list_head	sync_timeline_list;
+#endif
 };
 
 /**
  * struct sync_pt - sync point
- * @parent:		sync_timeline to which this sync_pt belongs
+ * @fence:		base fence class
  * @child_list:		membership in sync_timeline.child_list_head
  * @active_list:	membership in sync_timeline.active_list_head
  * @signaled_list:	membership in temporary signaled_list on stack
@@ -127,19 +121,22 @@ struct sync_timeline {
  *			  signaled or error.
  */
 struct sync_pt {
-	struct sync_timeline		*parent;
-	struct list_head	child_list;
+	struct fence base;
 
+	struct list_head	child_list;
 	struct list_head	active_list;
-	struct list_head	signaled_list;
-
-	struct sync_fence	*fence;
-	struct list_head	pt_list;
+};
 
-	/* protected by parent->active_list_lock */
-	int			status;
+static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+{
+	return container_of(pt->base.lock, struct sync_timeline,
+			    child_list_lock);
+}
 
-	ktime_t			timestamp;
+struct sync_fence_cb {
+	struct fence_cb cb;
+	struct fence *sync_pt;
+	struct sync_fence *fence;
 };
 
 /**
@@ -149,9 +146,7 @@ struct sync_pt {
  * @name:		name of sync_fence.  Useful for debugging
  * @pt_list_head:	list of sync_pts in the fence.  immutable once fence
  *			  is created
- * @waiter_list_head:	list of asynchronous waiters on this fence
- * @waiter_list_lock:	lock protecting @waiter_list_head and @status
- * @status:		1: signaled, 0:active, <0: error
+ * @status:		0: signaled, >0:active, <0: error
  *
  * @wq:			wait queue for fence signaling
  * @sync_fence_list:	membership in global fence list
@@ -160,17 +155,15 @@ struct sync_fence {
 	struct file		*file;
 	struct kref		kref;
 	char			name[32];
-
-	/* this list is immutable once the fence is created */
-	struct list_head	pt_list_head;
-
-	struct list_head	waiter_list_head;
-	spinlock_t		waiter_list_lock; /* also protects status */
-	int			status;
+#ifdef CONFIG_DEBUG_FS
+	struct list_head	sync_fence_list;
+#endif
+	int num_fences;
 
 	wait_queue_head_t	wq;
+	atomic_t		status;
 
-	struct list_head	sync_fence_list;
+	struct sync_fence_cb	cbs[];
 };
 
 struct sync_fence_waiter;
@@ -184,14 +177,14 @@ typedef void (*sync_callback_t)(struct s
  * @callback_data:	pointer to pass to @callback
  */
 struct sync_fence_waiter {
-	struct list_head	waiter_list;
-
-	sync_callback_t		callback;
+	wait_queue_t work;
+	sync_callback_t callback;
 };
 
 static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
 					  sync_callback_t callback)
 {
+	INIT_LIST_HEAD(&waiter->work.task_list);
 	waiter->callback = callback;
 }
 
@@ -341,4 +334,22 @@ int sync_fence_cancel_async(struct sync_
  */
 int sync_fence_wait(struct sync_fence *fence, long timeout);
 
+#ifdef CONFIG_DEBUG_FS
+
+extern void sync_timeline_debug_add(struct sync_timeline *obj);
+extern void sync_timeline_debug_remove(struct sync_timeline *obj);
+extern void sync_fence_debug_add(struct sync_fence *fence);
+extern void sync_fence_debug_remove(struct sync_fence *fence);
+extern void sync_dump(void);
+
+#else
+# define sync_timeline_debug_add(obj)
+# define sync_timeline_debug_remove(obj)
+# define sync_fence_debug_add(fence)
+# define sync_fence_debug_remove(fence)
+# define sync_dump()
+#endif
+int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+				 int wake_flags, void *key);
+
 #endif /* _LINUX_SYNC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/timed_gpio.c linux-libre-3.17-rc7-gnu/drivers/staging/android/timed_gpio.c
--- linux-libre-3.16-gnu/drivers/staging/android/timed_gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/timed_gpio.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,16 +45,17 @@ static enum hrtimer_restart gpio_timer_f
 
 static int gpio_get_time(struct timed_output_dev *dev)
 {
-	struct timed_gpio_data	*data =
-		container_of(dev, struct timed_gpio_data, dev);
+	struct timed_gpio_data *data;
+	struct timeval t;
 
-	if (hrtimer_active(&data->timer)) {
-		ktime_t r = hrtimer_get_remaining(&data->timer);
-		struct timeval t = ktime_to_timeval(r);
+	data = container_of(dev, struct timed_gpio_data, dev);
 
-		return t.tv_sec * 1000 + t.tv_usec / 1000;
-	} else
+	if (!hrtimer_active(&data->timer))
 		return 0;
+
+	t = ktime_to_timeval(hrtimer_get_remaining(&data->timer));
+
+	return t.tv_sec * 1000 + t.tv_usec / 1000;
 }
 
 static void gpio_enable(struct timed_output_dev *dev, int value)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/timed_output.c linux-libre-3.17-rc7-gnu/drivers/staging/android/timed_output.c
--- linux-libre-3.16-gnu/drivers/staging/android/timed_output.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/timed_output.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,10 @@ static ssize_t enable_store(struct devic
 {
 	struct timed_output_dev *tdev = dev_get_drvdata(dev);
 	int value;
+	int rc;
 
-	if (sscanf(buf, "%d", &value) != 1)
+	rc = kstrtoint(buf, 0, &value);
+	if (rc != 0)
 		return -EINVAL;
 
 	tdev->enable(tdev, value);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/android/trace/sync.h linux-libre-3.17-rc7-gnu/drivers/staging/android/trace/sync.h
--- linux-libre-3.16-gnu/drivers/staging/android/trace/sync.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/android/trace/sync.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,7 @@ TRACE_EVENT(sync_wait,
 
 	TP_fast_assign(
 			__assign_str(name, fence->name);
-			__entry->status = fence->status;
+			__entry->status = atomic_read(&fence->status);
 			__entry->begin = begin;
 	),
 
@@ -54,19 +54,19 @@ TRACE_EVENT(sync_wait,
 );
 
 TRACE_EVENT(sync_pt,
-	TP_PROTO(struct sync_pt *pt),
+	TP_PROTO(struct fence *pt),
 
 	TP_ARGS(pt),
 
 	TP_STRUCT__entry(
-		__string(timeline, pt->parent->name)
+		__string(timeline, pt->ops->get_timeline_name(pt))
 		__array(char, value, 32)
 	),
 
 	TP_fast_assign(
-		__assign_str(timeline, pt->parent->name);
-		if (pt->parent->ops->pt_value_str) {
-			pt->parent->ops->pt_value_str(pt, __entry->value,
+		__assign_str(timeline, pt->ops->get_timeline_name(pt));
+		if (pt->ops->fence_value_str) {
+			pt->ops->fence_value_str(pt, __entry->value,
 							sizeof(__entry->value));
 		} else {
 			__entry->value[0] = '\0';
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Bcmchar.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Bcmchar.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/Bcmchar.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Bcmchar.c	2014-09-28 17:29:07.000000000 -0400
@@ -1648,7 +1648,7 @@ static int bcm_char_ioctl_flash2x_sectio
 
 	ReadOffset = sFlash2xRead.offset;
 	OutPutBuff = IoBuffer.OutputBuffer;
-	pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
+	pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
 
 	if (pReadBuff == NULL) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/CmHost.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/CmHost.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/CmHost.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/CmHost.c	2014-09-28 17:29:07.000000000 -0400
@@ -972,6 +972,7 @@ static VOID DumpCmControlPacket(PVOID pv
 		pstAddIndication->sfAuthorizedSet.bValid = 1;
 	for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) {
 		struct bcm_convergence_types *psfCSType = NULL;
+
 		psfCSType =  &pstAddIndication->sfAuthorizedSet.cConvergenceSLTypes[nIndex];
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType);
@@ -1418,7 +1419,7 @@ static inline ULONG RestoreSFParam(struc
 	ulAddrSFParamSet = ntohl(ulAddrSFParamSet);
 
 	/* Read out the SF Param Set At the indicated Location */
-	if (rdm(Adapter, ulAddrSFParamSet,(PUCHAR)pucDestBuffer, nBytesToRead) < 0)
+	if (rdm(Adapter, ulAddrSFParamSet, (PUCHAR)pucDestBuffer, nBytesToRead) < 0)
 		return STATUS_FAILURE;
 
 	return 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/DDRInit.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/DDRInit.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/DDRInit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/DDRInit.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,8 @@
 
 /* DDR INIT-133Mhz */
 #define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3_DDRSetting133MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3_DDRSetting133MHz[] = {
+	/* DPLL Clock Setting */
 	{0x0F000800, 0x00007212},
 	{0x0f000820, 0x07F13FFF},
 	{0x0f000810, 0x00000F95},
@@ -65,7 +66,8 @@ static struct bcm_ddr_setting asT3_DDRSe
 };
 /* 80Mhz */
 #define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3_DDRSetting80MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3_DDRSetting80MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00000F95},
 	{0x0f000820, 0x07f1ffff},
 	{0x0f000860, 0x00000000},
@@ -117,7 +119,8 @@ static struct bcm_ddr_setting asT3_DDRSe
 };
 /* 100Mhz */
 #define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3_DDRSetting100MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3_DDRSetting100MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0F000800, 0x00007008},
 	{0x0f000810, 0x00000F95},
 	{0x0f000820, 0x07F13E3F},
@@ -189,7 +192,8 @@ static struct bcm_ddr_setting asDPLL_266
 };
 
 #define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3B_DDRSetting133MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3B_DDRSetting133MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00000F95},
 	{0x0f000810, 0x00000F95},
 	{0x0f000810, 0x00000F95},
@@ -247,7 +251,8 @@ static struct bcm_ddr_setting asT3B_DDRS
 	};
 
 #define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3B_DDRSetting80MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3B_DDRSetting80MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00000F95},
 	{0x0f000820, 0x07F13FFF},
 	{0x0f000840, 0x0FFF1F00},
@@ -301,7 +306,8 @@ static struct bcm_ddr_setting asT3B_DDRS
 
 /* 100Mhz */
 #define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3B_DDRSetting100MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3B_DDRSetting100MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00000F95},
 	{0x0f000820, 0x07F1369B},
 	{0x0f000840, 0x0FFF0800},
@@ -356,7 +362,8 @@ static struct bcm_ddr_setting asT3B_DDRS
 
 
 #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000820, 0x03F1365B},
 	{0x0f000810, 0x00002F95},
 	{0x0f000880, 0x000003DD},
@@ -416,7 +423,8 @@ static struct bcm_ddr_setting asT3LP_DDR
 };
 
 #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00002F95},
 	{0x0f000820, 0x03F1369B},
 	{0x0f000840, 0x0fff0000},
@@ -476,7 +484,8 @@ static struct bcm_ddr_setting asT3LP_DDR
 };
 
 #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000820, 0x07F13FFF},
 	{0x0f000810, 0x00002F95},
 	{0x0f000860, 0x00000000},
@@ -536,7 +545,8 @@ static struct bcm_ddr_setting asT3LP_DDR
 /* T3 LP-B (UMA-B) */
 
 #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000820, 0x03F137DB},
 	{0x0f000810, 0x01842795},
 	{0x0f000860, 0x00000000},
@@ -544,7 +554,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 	{0x0f000840, 0x0FFF0400},
 	{0x0F00a044, 0x1fffffff},
 	{0x0F00a040, 0x1f000000},
-	{0x0f003050, 0x00000021},  /* this is flash/eeprom clock divisor which set the flash clock to 20 MHz */
+	{0x0f003050, 0x00000021},  /* this is flash/eeprom clock divisor which
+				    * set the flash clock to 20 MHz */
 	{0x0F00a084, 0x1Cffffff},  /* Now dump from her in internal memory */
 	{0x0F00a080, 0x1C000000},
 	{0x0F00A000, 0x00000016},
@@ -593,7 +604,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 
 
 #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000820, 0x03F1365B},
 	{0x0f000810, 0x00002F95},
 	{0x0f000880, 0x000003DD},
@@ -602,7 +614,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 	{0x0f000860, 0x00000000},
 	{0x0F00a044, 0x1fffffff},
 	{0x0F00a040, 0x1f000000},
-	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor which
+				    * set the flash clock to 20 MHz */
 	{0x0F00a084, 0x1Cffffff},  /* dump from here in internal memory */
 	{0x0F00a080, 0x1C000000},
 	{0x0F00A000, 0x00000016},
@@ -654,7 +667,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 };
 
 #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000810, 0x00002F95},
 	{0x0f000820, 0x03F1369B},
 	{0x0f000840, 0x0fff0000},
@@ -664,7 +678,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 	{0x0f000840, 0x0FFF0000},
 	{0x0F00a044, 0x1fffffff},
 	{0x0F00a040, 0x1f000000},
-	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor which
+				    * set the flash clock to 20 MHz */
 	{0x0F00a084, 0x1Cffffff},  /* dump from here in internal memory */
 	{0x0F00a080, 0x1C000000},
 	/* Memcontroller Default values */
@@ -715,7 +730,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 };
 
 #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7  /* index for 0x0F007000 */
-static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[] = {  /* DPLL Clock Setting */
+static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[] = {
+      /* DPLL Clock Setting */
 	{0x0f000820, 0x07F13FFF},
 	{0x0f000810, 0x00002F95},
 	{0x0f000860, 0x00000000},
@@ -723,7 +739,8 @@ static struct bcm_ddr_setting asT3LPB_DD
 	{0x0f000840, 0x0FFF1F00},
 	{0x0F00a044, 0x1fffffff},
 	{0x0F00a040, 0x1f000000},
-	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+	{0x0f003050, 0x00000021},  /* flash/eeprom clock divisor
+				    * which set the flash clock to 20 MHz */
 	{0x0F00a084, 0x1Cffffff},  /* dump from here in internal memory */
 	{0x0F00a080, 0x1C000000},
 	{0x0F00A000, 0x00000016},
@@ -776,7 +793,7 @@ int ddr_init(struct bcm_mini_adapter *Ad
 	struct bcm_ddr_setting *psDDRSetting = NULL;
 	ULONG RegCount = 0;
 	UINT value = 0;
-	UINT  uiResetValue = 0;
+	UINT uiResetValue = 0;
 	UINT uiClockSetting = 0;
 	int retval = STATUS_SUCCESS;
 
@@ -785,18 +802,18 @@ int ddr_init(struct bcm_mini_adapter *Ad
 		switch (Adapter->DDRSetting) {
 		case DDR_80_MHZ:
 			psDDRSetting = asT3LP_DDRSetting80MHz;
-			RegCount = (sizeof(asT3LP_DDRSetting80MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3LP_DDRSetting80MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_100_MHZ:
 			psDDRSetting = asT3LP_DDRSetting100MHz;
-			RegCount = (sizeof(asT3LP_DDRSetting100MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3LP_DDRSetting100MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_133_MHZ:
 			psDDRSetting = asT3LP_DDRSetting133MHz;
-			RegCount = (sizeof(asT3LP_DDRSetting133MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3LP_DDRSetting133MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			if (Adapter->bMipsConfig == MIPS_200_MHZ)
 				uiClockSetting = 0x03F13652;
 			else
@@ -818,15 +835,21 @@ int ddr_init(struct bcm_mini_adapter *Ad
 	if ((Adapter->chip_id !=  BCS220_2) &&
 		(Adapter->chip_id !=  BCS220_2BC) &&
 		(Adapter->chip_id != BCS220_3)) {
-		retval = rdmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+		retval = rdmalt(Adapter, (UINT)0x0f000830, &uiResetValue,
+				sizeof(uiResetValue));
 		if (retval < 0) {
-			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL,
+					"%s:%d RDM failed\n",
+					__func__, __LINE__);
 			return retval;
 		}
 		uiResetValue |= 0x44;
-		retval = wrmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+		retval = wrmalt(Adapter, (UINT)0x0f000830, &uiResetValue,
+				sizeof(uiResetValue));
 		if (retval < 0) {
-			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+			BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL,
+					"%s:%d RDM failed\n",
+					__func__, __LINE__);
 			return retval;
 		}
 	}
@@ -836,18 +859,18 @@ int ddr_init(struct bcm_mini_adapter *Ad
 
 		case DDR_80_MHZ:
 			psDDRSetting = asT3LPB_DDRSetting80MHz;
-			RegCount = (sizeof(asT3B_DDRSetting80MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3B_DDRSetting80MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_100_MHZ:
 			psDDRSetting = asT3LPB_DDRSetting100MHz;
-			RegCount = (sizeof(asT3B_DDRSetting100MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3B_DDRSetting100MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_133_MHZ:
 			psDDRSetting = asT3LPB_DDRSetting133MHz;
-			RegCount = (sizeof(asT3B_DDRSetting133MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3B_DDRSetting133MHz) /
+				    sizeof(struct bcm_ddr_setting));
 
 			if (Adapter->bMipsConfig == MIPS_200_MHZ)
 				uiClockSetting = 0x03F13652;
@@ -857,7 +880,8 @@ int ddr_init(struct bcm_mini_adapter *Ad
 
 		case DDR_160_MHZ:
 			psDDRSetting = asT3LPB_DDRSetting160MHz;
-			RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(struct bcm_ddr_setting);
+			RegCount = sizeof(asT3LPB_DDRSetting160MHz) /
+				   sizeof(struct bcm_ddr_setting);
 
 			if (Adapter->bMipsConfig == MIPS_200_MHZ)
 				uiClockSetting = 0x03F137D2;
@@ -871,22 +895,23 @@ int ddr_init(struct bcm_mini_adapter *Ad
 	case 0xbece0121:
 	case 0xbece0130:
 	case 0xbece0300:
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+			"DDR Setting: %x\n", Adapter->DDRSetting);
 		switch (Adapter->DDRSetting) {
 		case DDR_80_MHZ:
 			psDDRSetting = asT3_DDRSetting80MHz;
-			RegCount = (sizeof(asT3_DDRSetting80MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3_DDRSetting80MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_100_MHZ:
 			psDDRSetting = asT3_DDRSetting100MHz;
-			RegCount = (sizeof(asT3_DDRSetting100MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3_DDRSetting100MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_133_MHZ:
 			psDDRSetting = asT3_DDRSetting133MHz;
-			RegCount = (sizeof(asT3_DDRSetting133MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3_DDRSetting133MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		default:
 			return -EINVAL;
@@ -896,26 +921,27 @@ int ddr_init(struct bcm_mini_adapter *Ad
 		switch (Adapter->DDRSetting) {
 		case DDR_80_MHZ:
 			psDDRSetting = asT3B_DDRSetting80MHz;
-			RegCount = (sizeof(asT3B_DDRSetting80MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3B_DDRSetting80MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_100_MHZ:
 			psDDRSetting = asT3B_DDRSetting100MHz;
-			RegCount = (sizeof(asT3B_DDRSetting100MHz)/
-			sizeof(struct bcm_ddr_setting));
+			RegCount = (sizeof(asT3B_DDRSetting100MHz) /
+				    sizeof(struct bcm_ddr_setting));
 			break;
 		case DDR_133_MHZ:
 
-			if (Adapter->bDPLLConfig == PLL_266_MHZ) {  /* 266Mhz PLL selected. */
+			/* 266Mhz PLL selected. */
+			if (Adapter->bDPLLConfig == PLL_266_MHZ) {
 				memcpy(asT3B_DDRSetting133MHz, asDPLL_266MHZ,
-				sizeof(asDPLL_266MHZ));
+				       sizeof(asDPLL_266MHZ));
 				psDDRSetting = asT3B_DDRSetting133MHz;
-				RegCount = (sizeof(asT3B_DDRSetting133MHz)/
-				sizeof(struct bcm_ddr_setting));
+				RegCount = (sizeof(asT3B_DDRSetting133MHz) /
+					    sizeof(struct bcm_ddr_setting));
 			} else {
 				psDDRSetting = asT3B_DDRSetting133MHz;
-				RegCount = (sizeof(asT3B_DDRSetting133MHz)/
-				sizeof(struct bcm_ddr_setting));
+				RegCount = (sizeof(asT3B_DDRSetting133MHz) /
+					    sizeof(struct bcm_ddr_setting));
 				if (Adapter->bMipsConfig == MIPS_200_MHZ)
 					uiClockSetting = 0x07F13652;
 				else
@@ -933,15 +959,19 @@ int ddr_init(struct bcm_mini_adapter *Ad
 	}
 
 	value = 0;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+			"Register Count is =%lu\n", RegCount);
 	while (RegCount && !retval) {
-		if (uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG)
+		if (uiClockSetting
+				&& psDDRSetting->ulRegAddress == MIPS_CLOCK_REG)
 			value = uiClockSetting;
 		else
 			value = psDDRSetting->ulRegValue;
-		retval = wrmalt(Adapter, psDDRSetting->ulRegAddress, &value, sizeof(value));
+		retval = wrmalt(Adapter, psDDRSetting->ulRegAddress, &value,
+				sizeof(value));
 		if (STATUS_SUCCESS != retval) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"%s:%d\n", __func__, __LINE__);
 			break;
 		}
 
@@ -957,27 +987,47 @@ int ddr_init(struct bcm_mini_adapter *Ad
 			(Adapter->chip_id != BCS220_3)) {
 			/* drive MDDR to half in case of UMA-B:	*/
 			uiResetValue = 0x01010001;
-			retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0F007018,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x00040020;
-			retval = wrmalt(Adapter, (UINT)0x0F007094, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0F007094,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x01020101;
-			retval = wrmalt(Adapter, (UINT)0x0F00701c, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0F00701c,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x01010000;
-			retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0F007018,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 		}
@@ -986,74 +1036,135 @@ int ddr_init(struct bcm_mini_adapter *Ad
 		/* DC/DC standby change...
 		 * This is to be done only for Hybrid PMU mode.
 		 * with the current h/w there is no way to detect this.
-		 * and since we dont have internal PMU lets do it under UMA-B chip id.
-		 * we will change this when we will have internal PMU.
+		 * and since we dont have internal PMU lets do it under
+		 * UMA-B chip id. we will change this when we will have
+		 * internal PMU.
 		 */
 		if (Adapter->PmuMode == HYBRID_MODE_7C) {
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x1322a8;
-			retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0f000d1c,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x132296;
-			retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0f000d14,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 		} else if (Adapter->PmuMode == HYBRID_MODE_6) {
 
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x6003229a;
-			retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0f000d14,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
-			retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+			retval = rdmalt(Adapter, (UINT)0x0f000c00,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 			uiResetValue = 0x1322a8;
-			retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue));
+			retval = wrmalt(Adapter, (UINT)0x0f000d1c,
+					&uiResetValue, sizeof(uiResetValue));
 			if (retval < 0) {
-				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+				BCM_DEBUG_PRINT(Adapter, CMHOST, RDM,
+						DBG_LVL_ALL,
+						"%s:%d RDM failed\n",
+						__func__,
+						__LINE__);
 				return retval;
 			}
 		}
@@ -1067,8 +1178,9 @@ int download_ddr_settings(struct bcm_min
 {
 	struct bcm_ddr_setting *psDDRSetting = NULL;
 	ULONG RegCount = 0;
-	unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY;
-	UINT  value = 0;
+	unsigned long ul_ddr_setting_load_addr =
+		DDR_DUMP_INTERNAL_DEVICE_MEMORY;
+	UINT value = 0;
 	int retval = STATUS_SUCCESS;
 	bool bOverrideSelfRefresh = false;
 
@@ -1191,18 +1303,22 @@ int download_ddr_settings(struct bcm_min
 	}
 	/* total number of Register that has to be dumped */
 	value = RegCount;
-	retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+	retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value,
+			sizeof(value));
 	if (retval) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"%s:%d\n", __func__, __LINE__);
 
 		return retval;
 	}
 	ul_ddr_setting_load_addr += sizeof(ULONG);
 	/* signature */
 	value = (0x1d1e0dd0);
-	retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+	retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value,
+			sizeof(value));
 	if (retval) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"%s:%d\n", __func__, __LINE__);
 		return retval;
 	}
 
@@ -1211,29 +1327,29 @@ int download_ddr_settings(struct bcm_min
 
 	while (RegCount && !retval) {
 		value = psDDRSetting->ulRegAddress;
-		retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+		retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value,
+				sizeof(value));
 		ul_ddr_setting_load_addr += sizeof(ULONG);
 		if (!retval) {
-			if (bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) {
+			if (bOverrideSelfRefresh
+					&& (psDDRSetting->ulRegAddress
+						== 0x0F007018))
 				value = (psDDRSetting->ulRegValue | (1<<8));
-			if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr,
-				&value, sizeof(value))) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
-				break;
-			}
-			} else {
-				value =  psDDRSetting->ulRegValue;
+			else
+				value = psDDRSetting->ulRegValue;
 
-				if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr ,
-					&value, sizeof(value))) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
-					break;
-				}
+			if (STATUS_SUCCESS != wrmalt(Adapter,
+						     ul_ddr_setting_load_addr,
+						     &value,
+						     sizeof(value))) {
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+						"%s:%d\n", __func__, __LINE__);
+				break;
 			}
 		}
 		ul_ddr_setting_load_addr += sizeof(ULONG);
 		RegCount--;
 		psDDRSetting++;
 	}
-		return retval;
+	return retval;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/HandleControlPacket.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/HandleControlPacket.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/HandleControlPacket.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/HandleControlPacket.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,8 @@
  * Enqueue the control packet for Application.
  * @return None
  */
-static VOID handle_rx_control_packet(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
+static VOID handle_rx_control_packet(struct bcm_mini_adapter *Adapter,
+				     struct sk_buff *skb)
 {
 	struct bcm_tarang_data *pTarang = NULL;
 	bool HighPriorityMessage = false;
@@ -22,7 +23,7 @@ static VOID handle_rx_control_packet(str
 
 	if (netif_msg_pktdata(Adapter))
 		print_hex_dump(KERN_DEBUG, PFX "rx control: ", DUMP_PREFIX_NONE,
-				16, 1, skb->data, skb->len, 0);
+			       16, 1, skb->data, skb->len, 0);
 
 	switch (usStatus) {
 	case CM_RESPONSES:               /* 0xA0 */
@@ -106,30 +107,32 @@ static VOID handle_rx_control_packet(str
 			 *    the sum of all types of dropped pkt by that
 			 *    tarang only.
 			 */
+			struct bcm_mibs_dropped_cntrl_msg *msg =
+				&pTarang->stDroppedAppCntrlMsgs;
 			switch (*(PUSHORT)skb->data) {
 			case CM_RESPONSES:
-				pTarang->stDroppedAppCntrlMsgs.cm_responses++;
+				msg->cm_responses++;
 				break;
 			case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
-				pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
+				msg->cm_control_newdsx_multiclassifier_resp++;
 				break;
 			case LINK_CONTROL_RESP:
-				pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
+				msg->link_control_resp++;
 				break;
 			case STATUS_RSP:
-				pTarang->stDroppedAppCntrlMsgs.status_rsp++;
+				msg->status_rsp++;
 				break;
 			case STATS_POINTER_RESP:
-				pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
+				msg->stats_pointer_resp++;
 				break;
 			case IDLE_MODE_STATUS:
-				pTarang->stDroppedAppCntrlMsgs.idle_mode_status++;
+				msg->idle_mode_status++;
 				break;
 			case AUTH_SS_HOST_MSG:
-				pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++;
+				msg->auth_ss_host_msg++;
 				break;
 			default:
-				pTarang->stDroppedAppCntrlMsgs.low_priority_message++;
+				msg->low_priority_message++;
 				break;
 			}
 
@@ -216,6 +219,7 @@ INT flushAllAppQ(void)
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 	struct bcm_tarang_data *pTarang = NULL;
 	struct sk_buff *PacketToDrop = NULL;
+
 	for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
 		while (pTarang->RxAppControlHead != NULL) {
 			PacketToDrop = pTarang->RxAppControlHead;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/hostmibs.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/hostmibs.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/hostmibs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/hostmibs.c	2014-09-28 17:29:07.000000000 -0400
@@ -17,6 +17,7 @@ INT ProcessGetHostMibs(struct bcm_mini_a
 	struct bcm_phs_classifier_table *pstClassifierTable = NULL;
 	struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
 	struct bcm_phs_extension *pDeviceExtension = &Adapter->stBCMPhsContext;
+	struct bcm_mibs_host_info *host_info;
 	UINT nClassifierIndex = 0;
 	UINT nPhsTableIndex = 0;
 	UINT nSfIndex = 0;
@@ -83,18 +84,18 @@ INT ProcessGetHostMibs(struct bcm_mini_a
 	}
 
 	/* Copy other Host Statistics parameters */
-	pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets;
-	pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets;
-	pstHostMibs->stHostInfo.CurrNumFreeDesc =
-				atomic_read(&Adapter->CurrNumFreeTxDesc);
-	pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize;
-	pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize;
-	pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive;
-	pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD;
+	host_info = &pstHostMibs->stHostInfo;
+	host_info->GoodTransmits    = Adapter->dev->stats.tx_packets;
+	host_info->GoodReceives	    = Adapter->dev->stats.rx_packets;
+	host_info->CurrNumFreeDesc  = atomic_read(&Adapter->CurrNumFreeTxDesc);
+	host_info->BEBucketSize	    = Adapter->BEBucketSize;
+	host_info->rtPSBucketSize   = Adapter->rtPSBucketSize;
+	host_info->TimerActive	    = Adapter->TimerActive;
+	host_info->u32TotalDSD	    = Adapter->u32TotalDSD;
 
-	memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist,
+	memcpy(host_info->aTxPktSizeHist, Adapter->aTxPktSizeHist,
 	       sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
-	memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist,
+	memcpy(host_info->aRxPktSizeHist, Adapter->aRxPktSizeHist,
 	       sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
 
 	return STATUS_SUCCESS;
@@ -112,32 +113,45 @@ VOID CopyMIBSExtendedSFParameters(struct
 				  struct bcm_connect_mgr_params *psfLocalSet,
 				  UINT uiSearchRuleIndex)
 {
-	struct bcm_mibs_parameters *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
+	struct bcm_mibs_parameters *t =
+		&Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
 
 	t->wmanIfSfid = psfLocalSet->u32SFID;
-	t->wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate;
+	t->wmanIfCmnCpsMaxSustainedRate =
+		psfLocalSet->u32MaxSustainedTrafficRate;
 	t->wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst;
 	t->wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate;
 	t->wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter;
 	t->wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency;
-	t->wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator;
-	t->wmanIfCmnCpsFixedVsVariableSduInd = ntohl(t->wmanIfCmnCpsFixedVsVariableSduInd);
+	t->wmanIfCmnCpsFixedVsVariableSduInd =
+		psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator;
+	t->wmanIfCmnCpsFixedVsVariableSduInd =
+		ntohl(t->wmanIfCmnCpsFixedVsVariableSduInd);
 	t->wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize;
 	t->wmanIfCmnCpsSduSize = ntohl(t->wmanIfCmnCpsSduSize);
-	t->wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType;
-	t->wmanIfCmnCpsSfSchedulingType = ntohl(t->wmanIfCmnCpsSfSchedulingType);
+	t->wmanIfCmnCpsSfSchedulingType =
+		psfLocalSet->u8ServiceFlowSchedulingType;
+	t->wmanIfCmnCpsSfSchedulingType =
+		ntohl(t->wmanIfCmnCpsSfSchedulingType);
 	t->wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable;
 	t->wmanIfCmnCpsArqEnable = ntohl(t->wmanIfCmnCpsArqEnable);
 	t->wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize);
 	t->wmanIfCmnCpsArqWindowSize = ntohl(t->wmanIfCmnCpsArqWindowSize);
-	t->wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime);
-	t->wmanIfCmnCpsArqBlockLifetime = ntohl(t->wmanIfCmnCpsArqBlockLifetime);
-	t->wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut);
-	t->wmanIfCmnCpsArqSyncLossTimeout = ntohl(t->wmanIfCmnCpsArqSyncLossTimeout);
+	t->wmanIfCmnCpsArqBlockLifetime =
+		ntohs(psfLocalSet->u16ARQBlockLifeTime);
+	t->wmanIfCmnCpsArqBlockLifetime =
+		ntohl(t->wmanIfCmnCpsArqBlockLifetime);
+	t->wmanIfCmnCpsArqSyncLossTimeout =
+		ntohs(psfLocalSet->u16ARQSyncLossTimeOut);
+	t->wmanIfCmnCpsArqSyncLossTimeout =
+		ntohl(t->wmanIfCmnCpsArqSyncLossTimeout);
 	t->wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder;
-	t->wmanIfCmnCpsArqDeliverInOrder = ntohl(t->wmanIfCmnCpsArqDeliverInOrder);
-	t->wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut);
-	t->wmanIfCmnCpsArqRxPurgeTimeout = ntohl(t->wmanIfCmnCpsArqRxPurgeTimeout);
+	t->wmanIfCmnCpsArqDeliverInOrder =
+		ntohl(t->wmanIfCmnCpsArqDeliverInOrder);
+	t->wmanIfCmnCpsArqRxPurgeTimeout =
+		ntohs(psfLocalSet->u16ARQRxPurgeTimeOut);
+	t->wmanIfCmnCpsArqRxPurgeTimeout =
+		ntohl(t->wmanIfCmnCpsArqRxPurgeTimeout);
 	t->wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize);
 	t->wmanIfCmnCpsArqBlockSize = ntohl(t->wmanIfCmnCpsArqBlockSize);
 	t->wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceDld.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceDld.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceDld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceDld.c	2014-09-28 17:29:07.000000000 -0400
@@ -244,6 +244,7 @@ static INT buffDnld(struct bcm_mini_adap
 {
 	unsigned int len = 0;
 	int retval = STATUS_SUCCESS;
+
 	len = u32FirmwareLength;
 
 	while (u32FirmwareLength) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceInit.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceInit.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceInit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceInit.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,28 +28,28 @@ static int InterfaceAdapterInit(struct b
 static void InterfaceAdapterFree(struct bcm_interface_adapter *psIntfAdapter)
 {
 	int i = 0;
+	struct bcm_mini_adapter *ps_ad = psIntfAdapter->psAdapter;
 
 	/* Wake up the wait_queue... */
-	if (psIntfAdapter->psAdapter->LEDInfo.led_thread_running &
+	if (ps_ad->LEDInfo.led_thread_running &
 			BCM_LED_THREAD_RUNNING_ACTIVELY) {
-		psIntfAdapter->psAdapter->DriverState = DRIVER_HALT;
-		wake_up(&psIntfAdapter->psAdapter->LEDInfo.notify_led_event);
+		ps_ad->DriverState = DRIVER_HALT;
+		wake_up(&ps_ad->LEDInfo.notify_led_event);
 	}
-	reset_card_proc(psIntfAdapter->psAdapter);
+	reset_card_proc(ps_ad);
 
 	/*
 	 * worst case time taken by the RDM/WRM will be 5 sec. will check after
 	 * every 100 ms to accertain the device is not being accessed. After
 	 * this No RDM/WRM should be made.
 	 */
-	while (psIntfAdapter->psAdapter->DeviceAccess) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT,
-				DRV_ENTRY, DBG_LVL_ALL,
-				"Device is being accessed.\n");
+	while (ps_ad->DeviceAccess) {
+		BCM_DEBUG_PRINT(ps_ad, DBG_TYPE_INITEXIT, DRV_ENTRY,
+				DBG_LVL_ALL, "Device is being accessed.\n");
 		msleep(100);
 	}
 	/* Free interrupt URB */
-	/* psIntfAdapter->psAdapter->device_removed = TRUE; */
+	/* ps_ad->device_removed = TRUE; */
 	usb_free_urb(psIntfAdapter->psInterruptUrb);
 
 	/* Free transmit URBs */
@@ -67,10 +67,11 @@ static void InterfaceAdapterFree(struct
 			psIntfAdapter->asUsbRcb[i].urb = NULL;
 		}
 	}
-	AdapterFree(psIntfAdapter->psAdapter);
+	AdapterFree(ps_ad);
 }
 
-static void ConfigureEndPointTypesThroughEEPROM(struct bcm_mini_adapter *Adapter)
+static void ConfigureEndPointTypesThroughEEPROM(
+		struct bcm_mini_adapter *Adapter)
 {
 	u32 ulReg;
 	int bytes;
@@ -129,7 +130,10 @@ static void ConfigureEndPointTypesThroug
 	ulReg &= 0x0101FFFF;
 	BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1FC, 4, TRUE);
 
-	/* Update length field if required. Also make the string NULL terminated. */
+	/*
+	 * Update length field if required.
+	 * Also make the string NULL terminated.
+	 */
 
 	ReadBeceemEEPROM(Adapter, 0xA8, &ulReg);
 	if ((ulReg&0x00FF0000)>>16 > 0x30) {
@@ -147,7 +151,8 @@ static void ConfigureEndPointTypesThroug
 	BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE);
 }
 
-static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int usbbcm_device_probe(struct usb_interface *intf,
+			       const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
 	int retval;
@@ -338,16 +343,16 @@ static int device_run(struct bcm_interfa
 {
 	int value = 0;
 	UINT status = STATUS_SUCCESS;
+	struct bcm_mini_adapter *psAd = psIntfAdapter->psAdapter;
 
-	status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter);
+	status = InitCardAndDownloadFirmware(psAd);
 	if (status != STATUS_SUCCESS) {
 		pr_err(DRV_NAME "InitCardAndDownloadFirmware failed.\n");
 		return status;
 	}
-	if (psIntfAdapter->psAdapter->fw_download_done) {
+	if (psAd->fw_download_done) {
 		if (StartInterruptUrb(psIntfAdapter)) {
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-					DBG_TYPE_INITEXIT, DRV_ENTRY,
+			BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY,
 					DBG_LVL_ALL,
 					"Cannot send interrupt in URB\n");
 		}
@@ -356,17 +361,15 @@ static int device_run(struct bcm_interfa
 		 * now register the cntrl interface.  after downloading the f/w
 		 * waiting for 5 sec to get the mailbox interrupt.
 		 */
-		psIntfAdapter->psAdapter->waiting_to_fw_download_done = false;
-		value = wait_event_timeout(
-				psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
-				psIntfAdapter->psAdapter->waiting_to_fw_download_done,
-				5 * HZ);
+		psAd->waiting_to_fw_download_done = false;
+		value = wait_event_timeout(psAd->ioctl_fw_dnld_wait_queue,
+					   psAd->waiting_to_fw_download_done,
+					   5 * HZ);
 
 		if (value == 0)
 			pr_err(DRV_NAME ": Timeout waiting for mailbox interrupt.\n");
 
-		if (register_control_device_interface(
-					psIntfAdapter->psAdapter) < 0) {
+		if (register_control_device_interface(psAd) < 0) {
 			pr_err(DRV_NAME ": Register Control Device failed.\n");
 			return -EIO;
 		}
@@ -374,6 +377,110 @@ static int device_run(struct bcm_interfa
 	return 0;
 }
 
+static int select_alternate_setting_for_highspeed_modem(
+		struct bcm_interface_adapter *psIntfAdapter,
+		struct usb_endpoint_descriptor **endpoint,
+		const struct usb_host_interface *iface_desc,
+		int *usedIntOutForBulkTransfer)
+{
+	int retval = 0;
+	struct bcm_mini_adapter *psAd = psIntfAdapter->psAdapter;
+
+	/* selecting alternate setting one as a default setting
+	 * for High Speed  modem. */
+	if (psIntfAdapter->bHighSpeedDevice)
+		retval = usb_set_interface(psIntfAdapter->udev,
+					   DEFAULT_SETTING_0,
+					   ALTERNATE_SETTING_1);
+	BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+			"BCM16 is applicable on this dongle\n");
+	if (retval || !psIntfAdapter->bHighSpeedDevice) {
+		*usedIntOutForBulkTransfer = EP2;
+		*endpoint = &iface_desc->endpoint[EP2].desc;
+		BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+				"Interface altsetting failed or modem is configured to Full Speed, hence will work on default setting 0\n");
+		/*
+		 * If Modem is high speed device EP2 should be
+		 * INT OUT End point
+		 *
+		 * If Mode is FS then EP2 should be bulk end
+		 * point
+		 */
+		if ((psIntfAdapter->bHighSpeedDevice &&
+					!usb_endpoint_is_int_out(*endpoint)) ||
+				(!psIntfAdapter->bHighSpeedDevice &&
+				 !usb_endpoint_is_bulk_out(*endpoint))) {
+			BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY,
+					DBG_LVL_ALL,
+					"Configuring the EEPROM\n");
+			/* change the EP2, EP4 to INT OUT end point */
+			ConfigureEndPointTypesThroughEEPROM(
+					psAd);
+
+			/*
+			 * It resets the device and if any thing
+			 * gets changed in USB descriptor it
+			 * will show fail and re-enumerate the
+			 * device
+			 */
+			retval = usb_reset_device(psIntfAdapter->udev);
+			if (retval) {
+				BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT,
+						DRV_ENTRY, DBG_LVL_ALL,
+						"reset failed.  Re-enumerating the device.\n");
+				return retval;
+			}
+
+		}
+		if (!psIntfAdapter->bHighSpeedDevice &&
+		    usb_endpoint_is_bulk_out(*endpoint)) {
+			/*
+			 * Once BULK is selected in FS mode.
+			 * Revert it back to INT.
+			 * Else USB_IF will fail.
+			 */
+			UINT _uiData = ntohl(EP2_CFG_INT);
+
+			BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY,
+					DBG_LVL_ALL,
+					"Reverting Bulk to INT as it is in Full Speed mode.\n");
+			BeceemEEPROMBulkWrite(psAd, (PUCHAR) & _uiData, 0x136,
+					      4, TRUE);
+		}
+	} else {
+		*usedIntOutForBulkTransfer = EP4;
+		*endpoint = &iface_desc->endpoint[EP4].desc;
+		BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+				"Choosing AltSetting as a default setting.\n");
+		if (!usb_endpoint_is_int_out(*endpoint)) {
+			BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT, DRV_ENTRY,
+					DBG_LVL_ALL,
+					"Dongle does not have BCM16 Fix.\n");
+			/*
+			 * change the EP2, EP4 to INT OUT end point and use EP4
+			 * in altsetting
+			 */
+			ConfigureEndPointTypesThroughEEPROM(psAd);
+
+			/*
+			 * It resets the device and if any thing
+			 * gets changed in USB descriptor it
+			 * will show fail and re-enumerate the
+			 * device
+			 */
+			retval = usb_reset_device(psIntfAdapter->udev);
+			if (retval) {
+				BCM_DEBUG_PRINT(psAd, DBG_TYPE_INITEXIT,
+						DRV_ENTRY, DBG_LVL_ALL,
+						"reset failed.  Re-enumerating the device.\n");
+				return retval;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 {
 	struct usb_host_interface *iface_desc;
@@ -385,6 +492,7 @@ static int InterfaceAdapterInit(struct b
 	bool bBcm16 = false;
 	UINT uiData = 0;
 	int bytes;
+	struct bcm_mini_adapter *psAd = psIntfAdapter->psAdapter;
 
 	/* Store the usb dev into interface adapter */
 	psIntfAdapter->udev =
@@ -392,141 +500,43 @@ static int InterfaceAdapterInit(struct b
 
 	psIntfAdapter->bHighSpeedDevice =
 		(psIntfAdapter->udev->speed == USB_SPEED_HIGH);
-	psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
-	psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
+	psAd->interface_rdm = BcmRDM;
+	psAd->interface_wrm = BcmWRM;
 
-	bytes = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
-			(u32 *) &(psIntfAdapter->psAdapter->chip_id),
-			sizeof(u32));
+	bytes = rdmalt(psAd, CHIP_ID_REG, (u32 *) &(psAd->chip_id),
+		       sizeof(u32));
 	if (bytes < 0) {
 		retval = bytes;
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+		BCM_DEBUG_PRINT(psAd, DBG_TYPE_PRINTK, 0, 0,
 				"CHIP ID Read Failed\n");
 		return retval;
 	}
 
-	if (0xbece3200 == (psIntfAdapter->psAdapter->chip_id & ~(0xF0)))
-		psIntfAdapter->psAdapter->chip_id &= ~0xF0;
+	if (0xbece3200 == (psAd->chip_id & ~(0xF0)))
+		psAd->chip_id &= ~0xF0;
 
 	dev_info(&psIntfAdapter->udev->dev, "RDM Chip ID 0x%lx\n",
-			psIntfAdapter->psAdapter->chip_id);
+		 psAd->chip_id);
 
 	iface_desc = psIntfAdapter->interface->cur_altsetting;
 
-	if (psIntfAdapter->psAdapter->chip_id == T3B) {
+	if (psAd->chip_id == T3B) {
 		/* T3B device will have EEPROM, check if EEPROM is proper and
 		 * BCM16 can be done or not. */
-		BeceemEEPROMBulkRead(psIntfAdapter->psAdapter, &uiData, 0x0, 4);
+		BeceemEEPROMBulkRead(psAd, &uiData, 0x0, 4);
 		if (uiData == BECM)
 			bBcm16 = TRUE;
 
 		dev_info(&psIntfAdapter->udev->dev,
-				"number of alternate setting %d\n",
-				psIntfAdapter->interface->num_altsetting);
+			 "number of alternate setting %d\n",
+			 psIntfAdapter->interface->num_altsetting);
 
 		if (bBcm16 == TRUE) {
-			/* selecting alternate setting one as a default setting
-			 * for High Speed  modem. */
-			if (psIntfAdapter->bHighSpeedDevice)
-				retval = usb_set_interface(psIntfAdapter->udev,
-						DEFAULT_SETTING_0,
-						ALTERNATE_SETTING_1);
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-					DBG_TYPE_INITEXIT, DRV_ENTRY,
-					DBG_LVL_ALL,
-					"BCM16 is applicable on this dongle\n");
-			if (retval || !psIntfAdapter->bHighSpeedDevice) {
-				usedIntOutForBulkTransfer = EP2;
-				endpoint = &iface_desc->endpoint[EP2].desc;
-				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-						DBG_TYPE_INITEXIT, DRV_ENTRY,
-						DBG_LVL_ALL,
-						"Interface altsetting failed or modem is configured to Full Speed, hence will work on default setting 0\n");
-				/*
-				 * If Modem is high speed device EP2 should be
-				 * INT OUT End point
-				 *
-				 * If Mode is FS then EP2 should be bulk end
-				 * point
-				 */
-				if ((psIntfAdapter->bHighSpeedDevice &&
-							!usb_endpoint_is_int_out(endpoint)) ||
-						(!psIntfAdapter->bHighSpeedDevice &&
-						 !usb_endpoint_is_bulk_out(endpoint))) {
-					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-							DBG_TYPE_INITEXIT,
-							DRV_ENTRY, DBG_LVL_ALL,
-							"Configuring the EEPROM\n");
-					/* change the EP2, EP4 to INT OUT end point */
-					ConfigureEndPointTypesThroughEEPROM(
-							psIntfAdapter->psAdapter);
-
-					/*
-					 * It resets the device and if any thing
-					 * gets changed in USB descriptor it
-					 * will show fail and re-enumerate the
-					 * device
-					 */
-					retval = usb_reset_device(
-							psIntfAdapter->udev);
-					if (retval) {
-						BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-								DBG_TYPE_INITEXIT,
-								DRV_ENTRY,
-								DBG_LVL_ALL,
-								"reset failed.  Re-enumerating the device.\n");
-						return retval;
-					}
-
-				}
-				if (!psIntfAdapter->bHighSpeedDevice &&
-				    usb_endpoint_is_bulk_out(endpoint)) {
-					/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
-					UINT _uiData = ntohl(EP2_CFG_INT);
-					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-							DBG_TYPE_INITEXIT,
-							DRV_ENTRY, DBG_LVL_ALL,
-							"Reverting Bulk to INT as it is in Full Speed mode.\n");
-					BeceemEEPROMBulkWrite(
-							psIntfAdapter->psAdapter,
-							(PUCHAR) & _uiData,
-							0x136, 4, TRUE);
-				}
-			} else {
-				usedIntOutForBulkTransfer = EP4;
-				endpoint = &iface_desc->endpoint[EP4].desc;
-				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-						DBG_TYPE_INITEXIT, DRV_ENTRY,
-						DBG_LVL_ALL,
-						"Choosing AltSetting as a default setting.\n");
-				if (!usb_endpoint_is_int_out(endpoint)) {
-					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-							DBG_TYPE_INITEXIT,
-							DRV_ENTRY, DBG_LVL_ALL,
-							"Dongle does not have BCM16 Fix.\n");
-					/* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
-					ConfigureEndPointTypesThroughEEPROM(
-							psIntfAdapter->psAdapter);
-
-					/*
-					 * It resets the device and if any thing
-					 * gets changed in USB descriptor it
-					 * will show fail and re-enumerate the
-					 * device
-					 */
-					retval = usb_reset_device(
-							psIntfAdapter->udev);
-					if (retval) {
-						BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
-								DBG_TYPE_INITEXIT,
-								DRV_ENTRY,
-								DBG_LVL_ALL,
-								"reset failed.  Re-enumerating the device.\n");
-						return retval;
-					}
-
-				}
-			}
+			retval = select_alternate_setting_for_highspeed_modem(
+					psIntfAdapter, &endpoint, iface_desc,
+					&usedIntOutForBulkTransfer);
+			if (retval)
+				return retval;
 		}
 	}
 
@@ -572,9 +582,12 @@ static int InterfaceAdapterInit(struct b
 		if (!psIntfAdapter->sIntrOut.int_out_endpointAddr &&
 				usb_endpoint_is_int_out(endpoint)) {
 			if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
-					(psIntfAdapter->psAdapter->chip_id == T3B) &&
+					(psAd->chip_id == T3B) &&
 					(value == usedIntOutForBulkTransfer)) {
-				/* use first intout end point as a bulk out end point */
+				/*
+				 * use first intout end point as a bulk out end
+				 * point
+				 */
 				buffer_size =
 					le16_to_cpu(endpoint->wMaxPacketSize);
 				psIntfAdapter->sBulkOut.bulk_out_size =
@@ -606,15 +619,14 @@ static int InterfaceAdapterInit(struct b
 
 	usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter);
 
-	psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload;
-	psIntfAdapter->psAdapter->bcm_file_readback_from_chip =
-		InterfaceFileReadbackFromChip;
-	psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket;
+	psAd->bcm_file_download = InterfaceFileDownload;
+	psAd->bcm_file_readback_from_chip = InterfaceFileReadbackFromChip;
+	psAd->interface_transmit = InterfaceTransmitPacket;
 
 	retval = CreateInterruptUrb(psIntfAdapter);
 
 	if (retval) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+		BCM_DEBUG_PRINT(psAd, DBG_TYPE_PRINTK, 0, 0,
 				"Cannot create interrupt urb\n");
 		return retval;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceMisc.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceMisc.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceMisc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceMisc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,29 +1,46 @@
 #include "headers.h"
 
+static int adapter_err_occurred(const struct bcm_interface_adapter *ad)
+{
+	if (ad->psAdapter->device_removed == TRUE) {
+		BCM_DEBUG_PRINT(ad->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+				"Device got removed");
+		return -ENODEV;
+	}
+
+	if ((ad->psAdapter->StopAllXaction == TRUE) &&
+	    (ad->psAdapter->chip_id >= T3LPB)) {
+		BCM_DEBUG_PRINT(ad->psAdapter, DBG_TYPE_OTHERS, RDM,
+				DBG_LVL_ALL,
+				"Currently Xaction is not allowed on the bus");
+		return -EACCES;
+	}
+
+	if (ad->bSuspended == TRUE || ad->bPreparingForBusSuspend == TRUE) {
+		BCM_DEBUG_PRINT(ad->psAdapter, DBG_TYPE_OTHERS, RDM,
+				DBG_LVL_ALL,
+				"Bus is in suspended states hence RDM not allowed..");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
 int InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter,
 		unsigned int addr,
 		void *buff,
 		int len)
 {
 	int bytes;
+	int err = 0;
 
 	if (!psIntfAdapter)
 		return -EINVAL;
 
-	if (psIntfAdapter->psAdapter->device_removed == TRUE) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
-		return -ENODEV;
-	}
-
-	if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))	{
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
-		return -EACCES;
-	}
+	err = adapter_err_occurred(psIntfAdapter);
+	if (err)
+		return err;
 
-	if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
-		return -EACCES;
-	}
 	psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
 	bytes = usb_control_msg(psIntfAdapter->udev,
@@ -40,9 +57,11 @@ int InterfaceRDM(struct bcm_interface_ad
 		psIntfAdapter->psAdapter->device_removed = TRUE;
 
 	if (bytes < 0)
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM,
+				DBG_LVL_ALL, "RDM failed status :%d", bytes);
 	else
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM,
+				DBG_LVL_ALL, "RDM sent %d", bytes);
 
 	psIntfAdapter->psAdapter->DeviceAccess = false;
 	return bytes;
@@ -54,24 +73,14 @@ int InterfaceWRM(struct bcm_interface_ad
 		int len)
 {
 	int retval = 0;
+	int err = 0;
 
 	if (!psIntfAdapter)
 		return -EINVAL;
 
-	if (psIntfAdapter->psAdapter->device_removed == TRUE) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
-		return -ENODEV;
-	}
-
-	if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
-		return -EACCES;
-	}
-
-	if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
-		return -EACCES;
-	}
+	err = adapter_err_occurred(psIntfAdapter);
+	if (err)
+		return err;
 
 	psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
@@ -89,12 +98,14 @@ int InterfaceWRM(struct bcm_interface_ad
 		psIntfAdapter->psAdapter->device_removed = TRUE;
 
 	if (retval < 0)	{
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM,
+				DBG_LVL_ALL, "WRM failed status :%d", retval);
 		psIntfAdapter->psAdapter->DeviceAccess = false;
 		return retval;
 	} else {
 		psIntfAdapter->psAdapter->DeviceAccess = false;
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM,
+				DBG_LVL_ALL, "WRM sent %d", retval);
 		return STATUS_SUCCESS;
 	}
 }
@@ -104,7 +115,8 @@ int BcmRDM(void *arg,
 	void *buff,
 	int len)
 {
-	return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff, len);
+	return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff,
+			    len);
 }
 
 int BcmWRM(void *arg,
@@ -112,12 +124,14 @@ int BcmWRM(void *arg,
 	void *buff,
 	int len)
 {
-	return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff, len);
+	return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff,
+			    len);
 }
 
 int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
 {
-	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter);
+	struct bcm_interface_adapter *psIntfAdapter =
+		(struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter);
 	int status = STATUS_SUCCESS;
 
 	/*
@@ -126,12 +140,14 @@ int Bcm_clear_halt_of_endpoints(struct b
 	 * @pipe: endpoint "pipe" being cleared
 	 * @ Context: !in_interrupt ()
 	 *
-	 * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
-	 * This is used to clear halt conditions for bulk and interrupt endpoints only.
+	 * usb_clear_halt is the synchrnous call and returns 0 on success else
+	 * returns with error code.
+	 * This is used to clear halt conditions for bulk and interrupt
+	 * endpoints only.
 	 * Control and isochronous endpoints never halts.
 	 *
-	 * Any URBs  queued for such an endpoint should normally be unlinked by the driver
-	 * before clearing the halt condition.
+	 * Any URBs  queued for such an endpoint should normally be unlinked by
+	 * the driver before clearing the halt condition.
 	 *
 	 */
 
@@ -139,17 +155,29 @@ int Bcm_clear_halt_of_endpoints(struct b
 	Bcm_kill_all_URBs(psIntfAdapter);
 
 	/* clear the halted/stalled state for every end point */
-	status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
+	status = usb_clear_halt(psIntfAdapter->udev,
+				psIntfAdapter->sIntrIn.int_in_pipe);
 	if (status != STATUS_SUCCESS)
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+				DBG_LVL_ALL,
+				"Unable to Clear Halt of Interrupt IN end point. :%d ",
+				status);
 
-	status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe);
+	status = usb_clear_halt(psIntfAdapter->udev,
+				psIntfAdapter->sBulkIn.bulk_in_pipe);
 	if (status != STATUS_SUCCESS)
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+				DBG_LVL_ALL,
+				"Unable to Clear Halt of Bulk IN end point. :%d ",
+				status);
 
-	status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe);
+	status = usb_clear_halt(psIntfAdapter->udev,
+				psIntfAdapter->sBulkOut.bulk_out_pipe);
 	if (status != STATUS_SUCCESS)
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+				DBG_LVL_ALL,
+				"Unable to Clear Halt of Bulk OUT end point. :%d ",
+				status);
 
 	return status;
 }
@@ -168,9 +196,9 @@ void Bcm_kill_all_URBs(struct bcm_interf
 	 * upon return all completion handlers will have finished and the URB
 	 * will be totally idle and available for reuse
 	 *
-	 * This routine may not be used in an interrupt context (such as a bottom
-	 * half or a completion handler), or when holding a spinlock, or in other
-	 * situations where the caller can't schedule().
+	 * This routine may not be used in an interrupt context (such as a
+	 * bottom half or a completion handler), or when holding a spinlock, or
+	 * in other situations where the caller can't schedule().
 	 *
 	 */
 
@@ -208,7 +236,9 @@ void putUsbSuspend(struct work_struct *w
 {
 	struct bcm_interface_adapter *psIntfAdapter = NULL;
 	struct usb_interface *intf = NULL;
-	psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork);
+
+	psIntfAdapter = container_of(work, struct bcm_interface_adapter,
+				     usbSuspendWork);
 	intf = psIntfAdapter->interface;
 
 	if (psIntfAdapter->bSuspended == false)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceRx.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceRx.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceRx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceRx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,92 @@
 #include "headers.h"
 
+static void handle_control_packet(struct bcm_interface_adapter *interface,
+				  struct bcm_mini_adapter *ad,
+				  struct bcm_leader *leader,
+				  struct sk_buff *skb,
+				  struct urb *urb)
+{
+	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL,
+			"Received control pkt...");
+	*(PUSHORT)skb->data = leader->Status;
+	memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
+	       (sizeof(struct bcm_leader)), leader->PLength);
+	skb->len = leader->PLength + sizeof(USHORT);
+
+	spin_lock(&ad->control_queue_lock);
+	ENQUEUEPACKET(ad->RxControlHead, ad->RxControlTail, skb);
+	spin_unlock(&ad->control_queue_lock);
+
+	atomic_inc(&ad->cntrlpktCnt);
+	wake_up(&ad->process_rx_cntrlpkt);
+}
+
+static void format_eth_hdr_to_stack(struct bcm_interface_adapter *interface,
+				    struct bcm_mini_adapter *ad,
+				    struct bcm_leader *p_leader,
+				    struct sk_buff *skb,
+				    struct urb *urb,
+				    UINT ui_index,
+				    int queue_index,
+				    bool b_header_supression_endabled)
+{
+	/*
+	 * Data Packet, Format a proper Ethernet Header
+	 * and give it to the stack
+	 */
+	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
+			DBG_LVL_ALL, "Received Data pkt...");
+	skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
+	memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer +
+	       sizeof(struct bcm_leader), p_leader->PLength);
+	skb->dev = ad->dev;
+
+	/* currently skb->len has extra ETH_HLEN bytes in the beginning */
+	skb_put(skb, p_leader->PLength + ETH_HLEN);
+	ad->PackInfo[queue_index].uiTotalRxBytes += p_leader->PLength;
+	ad->PackInfo[queue_index].uiThisPeriodRxBytes += p_leader->PLength;
+	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
+			DBG_LVL_ALL, "Received Data pkt of len :0x%X",
+			p_leader->PLength);
+
+	if (netif_running(ad->dev)) {
+		/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
+		skb_pull(skb, ETH_HLEN);
+		PHSReceive(ad, p_leader->Vcid, skb, &skb->len,
+			   NULL, b_header_supression_endabled);
+
+		if (!ad->PackInfo[queue_index].bEthCSSupport) {
+			skb_push(skb, ETH_HLEN);
+
+			memcpy(skb->data, skb->dev->dev_addr, 6);
+			memcpy(skb->data+6, skb->dev->dev_addr, 6);
+			(*(skb->data+11))++;
+			*(skb->data+12) = 0x08;
+			*(skb->data+13) = 0x00;
+			p_leader->PLength += ETH_HLEN;
+		}
+
+		skb->protocol = eth_type_trans(skb, ad->dev);
+		netif_rx(skb);
+	} else {
+		BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX,
+				RX_DATA, DBG_LVL_ALL,
+				"i/f not up hance freeing SKB...");
+		dev_kfree_skb(skb);
+	}
+
+	++ad->dev->stats.rx_packets;
+	ad->dev->stats.rx_bytes += p_leader->PLength;
+
+	for (ui_index = 0; ui_index < MIBS_MAX_HIST_ENTRIES; ui_index++) {
+		if ((p_leader->PLength <=
+		    MIBS_PKTSIZEHIST_RANGE*(ui_index+1)) &&
+			(p_leader->PLength > MIBS_PKTSIZEHIST_RANGE*(ui_index)))
+
+			ad->aRxPktSizeHist[ui_index]++;
+	}
+}
+
 static int SearchVcid(struct bcm_mini_adapter *Adapter, unsigned short usVcid)
 {
 	int iIndex = 0;
@@ -24,8 +111,9 @@ GetBulkInRcb(struct bcm_interface_adapte
 		pRcb = &psIntfAdapter->asUsbRcb[index];
 		pRcb->bUsed = TRUE;
 		pRcb->psIntfAdapter = psIntfAdapter;
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d",
-				index, atomic_read(&psIntfAdapter->uNumRcbUsed));
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC,
+				DBG_LVL_ALL, "Got Rx desc %d used %d", index,
+				atomic_read(&psIntfAdapter->uNumRcbUsed));
 		index = (index + 1) % MAXIMUM_USB_RCB;
 		atomic_set(&psIntfAdapter->uCurrRcb, index);
 		atomic_inc(&psIntfAdapter->uNumRcbUsed);
@@ -40,7 +128,6 @@ static void read_bulk_callback(struct ur
 	bool bHeaderSupressionEnabled = false;
 	int QueueIndex = NO_OF_QUEUES + 1;
 	UINT uiIndex = 0;
-	int process_done = 1;
 	struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context;
 	struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter;
 	struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
@@ -63,7 +150,10 @@ static void read_bulk_callback(struct ur
 			Adapter->bEndPointHalted = TRUE;
 			wake_up(&Adapter->tx_packet_wait_queue);
 		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Rx URB has got cancelled. status :%d", urb->status);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC,
+					DBG_LVL_ALL,
+					"Rx URB has got cancelled. status :%d",
+					urb->status);
 		}
 		pRcb->bUsed = false;
 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
@@ -72,17 +162,22 @@ static void read_bulk_callback(struct ur
 	}
 
 	if (Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "device is going in low power mode while PMU option selected..hence rx packet should not be process");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
+				"device is going in low power mode while PMU option selected..hence rx packet should not be process");
 		return;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
+			"Read back done len %d\n", pLeader->PLength);
 	if (!pLeader->PLength) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
+				"Leader Length 0");
 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
 		return;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status, pLeader->PLength, pLeader->Vcid);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
+			"Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX",
+			pLeader->Status, pLeader->PLength, pLeader->Vcid);
 	if (MAX_CNTL_PKT_SIZE < pLeader->PLength) {
 		if (netif_msg_rx_err(Adapter))
 			pr_info(PFX "%s: corrupted leader length...%d\n",
@@ -100,95 +195,52 @@ static void read_bulk_callback(struct ur
 			bHeaderSupressionEnabled & Adapter->bPHSEnabled;
 	}
 
-	skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER);
+	skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES +
+			    SKB_RESERVE_ETHERNET_HEADER);
 	if (!skb) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"NO SKBUFF!!! Dropping the Packet");
 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
 		return;
 	}
 	/* If it is a control Packet, then call handle_bcm_packet ()*/
 	if ((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
 	    (!(pLeader->Status >= 0x20  &&  pLeader->Status <= 0x3F))) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt...");
-		*(PUSHORT)skb->data = pLeader->Status;
-		memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
-		       (sizeof(struct bcm_leader)), pLeader->PLength);
-		skb->len = pLeader->PLength + sizeof(USHORT);
-
-		spin_lock(&Adapter->control_queue_lock);
-		ENQUEUEPACKET(Adapter->RxControlHead, Adapter->RxControlTail, skb);
-		spin_unlock(&Adapter->control_queue_lock);
-
-		atomic_inc(&Adapter->cntrlpktCnt);
-		wake_up(&Adapter->process_rx_cntrlpkt);
+		handle_control_packet(psIntfAdapter, Adapter, pLeader, skb,
+				      urb);
 	} else {
-		/*
-		 * Data Packet, Format a proper Ethernet Header
-		 * and give it to the stack
-		 */
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt...");
-		skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
-		memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_leader), pLeader->PLength);
-		skb->dev = Adapter->dev;
-
-		/* currently skb->len has extra ETH_HLEN bytes in the beginning */
-		skb_put(skb, pLeader->PLength + ETH_HLEN);
-		Adapter->PackInfo[QueueIndex].uiTotalRxBytes += pLeader->PLength;
-		Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes += pLeader->PLength;
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength);
-
-		if (netif_running(Adapter->dev)) {
-			/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
-			skb_pull(skb, ETH_HLEN);
-			PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
-				   NULL, bHeaderSupressionEnabled);
-
-			if (!Adapter->PackInfo[QueueIndex].bEthCSSupport) {
-				skb_push(skb, ETH_HLEN);
-
-				memcpy(skb->data, skb->dev->dev_addr, 6);
-				memcpy(skb->data+6, skb->dev->dev_addr, 6);
-				(*(skb->data+11))++;
-				*(skb->data+12) = 0x08;
-				*(skb->data+13) = 0x00;
-				pLeader->PLength += ETH_HLEN;
-			}
-
-			skb->protocol = eth_type_trans(skb, Adapter->dev);
-			process_done = netif_rx(skb);
-		} else {
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB...");
-			dev_kfree_skb(skb);
-		}
-
-		++Adapter->dev->stats.rx_packets;
-		Adapter->dev->stats.rx_bytes += pLeader->PLength;
-
-		for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
-			if ((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
-			    (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
-				Adapter->aRxPktSizeHist[uiIndex]++;
-		}
+		format_eth_hdr_to_stack(psIntfAdapter, Adapter, pLeader, skb,
+					urb, uiIndex, QueueIndex,
+					bHeaderSupressionEnabled);
 	}
 	Adapter->PrevNumRecvDescs++;
 	pRcb->bUsed = false;
 	atomic_dec(&psIntfAdapter->uNumRcbUsed);
 }
 
-static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb)
+static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter,
+		      struct bcm_usb_rcb *pRcb)
 {
 	struct urb *urb = pRcb->urb;
 	int retval = 0;
 
-	usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
-			  urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback, pRcb);
+	usb_fill_bulk_urb(urb, psIntfAdapter->udev,
+			  usb_rcvbulkpipe(psIntfAdapter->udev,
+					  psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
+			  urb->transfer_buffer,
+			  BCM_USB_MAX_READ_LENGTH,
+			  read_bulk_callback, pRcb);
+
 	if (false == psIntfAdapter->psAdapter->device_removed &&
 	    false == psIntfAdapter->psAdapter->bEndPointHalted &&
 	    false == psIntfAdapter->bSuspended &&
 	    false == psIntfAdapter->bPreparingForBusSuspend) {
 		retval = usb_submit_urb(urb, GFP_ATOMIC);
 		if (retval) {
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval);
+			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX,
+					RX_DPC, DBG_LVL_ALL,
+					"failed submitting read urb, error %d",
+					retval);
 			/* if this return value is because of pipe halt. need to clear this. */
 			if (retval == -EPIPE) {
 				psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
@@ -216,13 +268,17 @@ Return:				TRUE  - If Rx was successful.
 
 bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter)
 {
-	USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
+	USHORT RxDescCount = NUM_RX_DESC -
+		atomic_read(&psIntfAdapter->uNumRcbUsed);
+
 	struct bcm_usb_rcb *pRcb = NULL;
 
 	while (RxDescCount) {
 		pRcb = GetBulkInRcb(psIntfAdapter);
 		if (pRcb == NULL) {
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer");
+			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+					DBG_TYPE_PRINTK, 0, 0,
+					"Unable to get Rcb pointer");
 			return false;
 		}
 		ReceiveRcb(psIntfAdapter, pRcb);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceTx.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceTx.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/InterfaceTx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/InterfaceTx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,93 +1,122 @@
 #include "headers.h"
 
+static void prepare_low_power_mode(struct urb *urb,
+				   struct bcm_interface_adapter *interface,
+				   struct bcm_mini_adapter *ps_adapter,
+				   struct bcm_mini_adapter *ad,
+				   struct bcm_link_request *p_control_msg,
+				   bool *b_power_down_msg)
+{
+	if (((p_control_msg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
+		(p_control_msg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
+
+		*b_power_down_msg = TRUE;
+		/*
+		 * This covers the bus err while Idle Request msg
+		 * sent down.
+		 */
+		if (urb->status != STATUS_SUCCESS) {
+			ps_adapter->bPreparingForLowPowerMode = false;
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
+					DBG_LVL_ALL,
+					"Idle Mode Request msg failed to reach to Modem");
+			/* Signalling the cntrl pkt path in Ioctl */
+			wake_up(&ps_adapter->lowpower_mode_wait_queue);
+			StartInterruptUrb(interface);
+			return;
+		}
+
+		if (ps_adapter->bDoSuspend == false) {
+			ps_adapter->IdleMode = TRUE;
+			/* since going in Idle mode completed hence making this var false */
+			ps_adapter->bPreparingForLowPowerMode = false;
+
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
+					DBG_LVL_ALL,
+					"Host Entered in Idle Mode State...");
+			/* Signalling the cntrl pkt path in Ioctl*/
+			wake_up(&ps_adapter->lowpower_mode_wait_queue);
+		}
+
+	} else if ((p_control_msg->Leader.Status == LINK_UP_CONTROL_REQ) &&
+		(p_control_msg->szData[0] == LINK_UP_ACK) &&
+		(p_control_msg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
+		(p_control_msg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
+		/*
+		 * This covers the bus err while shutdown Request
+		 * msg sent down.
+		 */
+		if (urb->status != STATUS_SUCCESS) {
+			ps_adapter->bPreparingForLowPowerMode = false;
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
+					DBG_LVL_ALL,
+					"Shutdown Request Msg failed to reach to Modem");
+			/* Signalling the cntrl pkt path in Ioctl */
+			wake_up(&ps_adapter->lowpower_mode_wait_queue);
+			StartInterruptUrb(interface);
+			return;
+		}
+
+		*b_power_down_msg = TRUE;
+		if (ps_adapter->bDoSuspend == false) {
+			ps_adapter->bShutStatus = TRUE;
+			/*
+			 * since going in shutdown mode completed hence
+			 * making this var false
+			 */
+			ps_adapter->bPreparingForLowPowerMode = false;
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
+					DBG_LVL_ALL,
+					"Host Entered in shutdown Mode State...");
+			/* Signalling the cntrl pkt path in Ioctl */
+			wake_up(&ps_adapter->lowpower_mode_wait_queue);
+		}
+	}
+
+	if (ps_adapter->bDoSuspend && *b_power_down_msg) {
+		/* issuing bus suspend request */
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
+				"Issuing the Bus suspend request to USB stack");
+		interface->bPreparingForBusSuspend = TRUE;
+		schedule_work(&interface->usbSuspendWork);
+	}
+}
+
 /*this is transmit call-back(BULK OUT)*/
 static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
 {
 	struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
 	struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
-	struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer;
+	struct bcm_link_request *pControlMsg =
+		(struct bcm_link_request *)urb->transfer_buffer;
 	struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
 	bool bpowerDownMsg = false;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
 	if (unlikely(netif_msg_tx_done(Adapter)))
-		pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status);
+		pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name,
+			urb->status);
 
 	if (urb->status != STATUS_SUCCESS) {
 		if (urb->status == -EPIPE) {
 			psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
 			wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
 		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx URB has got cancelled. status :%d", urb->status);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND,
+					DBG_LVL_ALL,
+					"Tx URB has got cancelled. status :%d",
+					urb->status);
 		}
 	}
 
 	pTcb->bUsed = false;
 	atomic_dec(&psIntfAdapter->uNumTcbUsed);
 
-
-
 	if (TRUE == psAdapter->bPreparingForLowPowerMode) {
-
-		if (((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
-			(pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
-			bpowerDownMsg = TRUE;
-			/* This covers the bus err while Idle Request msg sent down. */
-			if (urb->status != STATUS_SUCCESS) {
-				psAdapter->bPreparingForLowPowerMode = false;
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Request msg failed to reach to Modem");
-				/* Signalling the cntrl pkt path in Ioctl */
-				wake_up(&psAdapter->lowpower_mode_wait_queue);
-				StartInterruptUrb(psIntfAdapter);
-				goto err_exit;
-			}
-
-			if (psAdapter->bDoSuspend == false) {
-				psAdapter->IdleMode = TRUE;
-				/* since going in Idle mode completed hence making this var false */
-				psAdapter->bPreparingForLowPowerMode = false;
-
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
-				/* Signalling the cntrl pkt path in Ioctl*/
-				wake_up(&psAdapter->lowpower_mode_wait_queue);
-			}
-
-		} else if ((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) &&
-			(pControlMsg->szData[0] == LINK_UP_ACK) &&
-			(pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
-			(pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
-			/* This covers the bus err while shutdown Request msg sent down. */
-			if (urb->status != STATUS_SUCCESS) {
-				psAdapter->bPreparingForLowPowerMode = false;
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Shutdown Request Msg failed to reach to Modem");
-				/* Signalling the cntrl pkt path in Ioctl */
-				wake_up(&psAdapter->lowpower_mode_wait_queue);
-				StartInterruptUrb(psIntfAdapter);
-				goto err_exit;
-			}
-
-			bpowerDownMsg = TRUE;
-			if (psAdapter->bDoSuspend == false) {
-				psAdapter->bShutStatus = TRUE;
-				/* since going in shutdown mode completed hence making this var false */
-				psAdapter->bPreparingForLowPowerMode = false;
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in shutdown Mode State...");
-				/* Signalling the cntrl pkt path in Ioctl */
-				wake_up(&psAdapter->lowpower_mode_wait_queue);
-			}
-		}
-
-		if (psAdapter->bDoSuspend && bpowerDownMsg) {
-			/* issuing bus suspend request */
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Issuing the Bus suspend request to USB stack");
-			psIntfAdapter->bPreparingForBusSuspend = TRUE;
-			schedule_work(&psIntfAdapter->usbSuspendWork);
-
-		}
-
+		prepare_low_power_mode(urb, psIntfAdapter, psAdapter, Adapter,
+				       pControlMsg, &bpowerDownMsg);
 	}
 
-err_exit:
 	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
 			urb->transfer_buffer, urb->transfer_dma);
 }
@@ -104,8 +133,11 @@ static struct bcm_usb_tcb *GetBulkOutTcb
 		pTcb = &psIntfAdapter->asUsbTcb[index];
 		pTcb->bUsed = TRUE;
 		pTcb->psIntfAdapter = psIntfAdapter;
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d",
-			index, atomic_read(&psIntfAdapter->uNumTcbUsed));
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
+				NEXT_SEND, DBG_LVL_ALL,
+				"Got Tx desc %d used %d",
+				index,
+				atomic_read(&psIntfAdapter->uNumTcbUsed));
 		index = (index + 1) % MAXIMUM_USB_TCB;
 		atomic_set(&psIntfAdapter->uCurrTcb, index);
 		atomic_inc(&psIntfAdapter->uNumTcbUsed);
@@ -113,7 +145,8 @@ static struct bcm_usb_tcb *GetBulkOutTcb
 	return pTcb;
 }
 
-static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
+static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter,
+		       struct bcm_usb_tcb *pTcb, PVOID data, int len)
 {
 
 	struct urb *urb = pTcb->urb;
@@ -122,15 +155,18 @@ static int TransmitTcb(struct bcm_interf
 	urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
 						GFP_ATOMIC, &urb->transfer_dma);
 	if (!urb->transfer_buffer) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n");
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+				"Error allocating memory\n");
 		return  -ENOMEM;
 	}
 	memcpy(urb->transfer_buffer, data, len);
 	urb->transfer_buffer_length = len;
 
-	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n");
+	BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND,
+			DBG_LVL_ALL, "Sending Bulk out packet\n");
 	/* For T3B,INT OUT end point will be used as bulk out end point */
-	if ((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) {
+	if ((psIntfAdapter->psAdapter->chip_id == T3B) &&
+			(psIntfAdapter->bHighSpeedDevice == TRUE)) {
 		usb_fill_int_urb(urb, psIntfAdapter->udev,
 			psIntfAdapter->sBulkOut.bulk_out_pipe,
 			urb->transfer_buffer, len, write_bulk_callback, pTcb,
@@ -148,7 +184,10 @@ static int TransmitTcb(struct bcm_interf
 	   false == psIntfAdapter->bPreparingForBusSuspend) {
 		retval = usb_submit_urb(urb, GFP_ATOMIC);
 		if (retval) {
-			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval);
+			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
+					NEXT_SEND, DBG_LVL_ALL,
+					"failed submitting write urb, error %d",
+					retval);
 			if (retval == -EPIPE) {
 				psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
 				wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
@@ -161,14 +200,14 @@ static int TransmitTcb(struct bcm_interf
 int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
 {
 	struct bcm_usb_tcb *pTcb = NULL;
-
 	struct bcm_interface_adapter *psIntfAdapter = arg;
+
 	pTcb = GetBulkOutTcb(psIntfAdapter);
 	if (pTcb == NULL) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet");
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+				"No URB to transmit packet, dropping packet");
 		return -EFAULT;
 	}
 	return TransmitTcb(psIntfAdapter, pTcb, data, len);
 }
 
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/IPv6Protocol.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/IPv6Protocol.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/IPv6Protocol.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/IPv6Protocol.c	2014-09-28 17:29:07.000000000 -0400
@@ -11,7 +11,7 @@ static UCHAR *GetNextIPV6ChainedHeader(U
 {
 	UCHAR *pucRetHeaderPtr = NULL;
 	UCHAR *pucPayloadPtr = NULL;
-	USHORT  usNextHeaderOffset = 0 ;
+	USHORT  usNextHeaderOffset = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
 	if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
@@ -34,94 +34,89 @@ static UCHAR *GetNextIPV6ChainedHeader(U
 
 	switch (*pucNextHeader) {
 	case IPV6HDR_TYPE_HOPBYHOP:
-		{
-
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nIPv6 HopByHop Header");
-			usNextHeaderOffset += sizeof(struct bcm_ipv6_options_hdr);
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL, "\nIPv6 HopByHop Header");
+		usNextHeaderOffset += sizeof(struct bcm_ipv6_options_hdr);
 		break;
 
 	case IPV6HDR_TYPE_ROUTING:
 		{
 			struct bcm_ipv6_routing_hdr *pstIpv6RoutingHeader;
+
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
 					DBG_LVL_ALL, "\nIPv6 Routing Header");
-			pstIpv6RoutingHeader = (struct bcm_ipv6_routing_hdr *)pucPayloadPtr;
+			pstIpv6RoutingHeader =
+				(struct bcm_ipv6_routing_hdr *)pucPayloadPtr;
 			usNextHeaderOffset += sizeof(struct bcm_ipv6_routing_hdr);
-			usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
-
+			usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses *
+					      IPV6_ADDRESS_SIZEINBYTES;
 		}
 		break;
-	case IPV6HDR_TYPE_FRAGMENTATION:
-		{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL,
-					"\nIPv6 Fragmentation Header");
-			usNextHeaderOffset += sizeof(struct bcm_ipv6_fragment_hdr);
 
-		}
+	case IPV6HDR_TYPE_FRAGMENTATION:
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL,
+				"\nIPv6 Fragmentation Header");
+		usNextHeaderOffset += sizeof(struct bcm_ipv6_fragment_hdr);
 		break;
+
 	case IPV6HDR_TYPE_DESTOPTS:
 		{
-			struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr = (struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr;
+			struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr =
+				(struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr;
 			int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
+
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
 					DBG_LVL_ALL,
 					"\nIPv6 DestOpts Header Header");
 			usNextHeaderOffset += sizeof(struct bcm_ipv6_dest_options_hdr);
-			usNextHeaderOffset += nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
-
+			usNextHeaderOffset += nTotalOptions *
+					      IPV6_DESTOPTS_HDR_OPTIONSIZE;
 		}
 		break;
+
+
 	case IPV6HDR_TYPE_AUTHENTICATION:
 		{
-			struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr = (struct bcm_ipv6_authentication_hdr *)pucPayloadPtr;
+			struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr =
+				(struct bcm_ipv6_authentication_hdr *)pucPayloadPtr;
 			int nHdrLen = pstIpv6AuthHdr->ucLength;
+
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
 					DBG_LVL_ALL,
 					"\nIPv6 Authentication Header");
 			usNextHeaderOffset += nHdrLen * 4;
 		}
 		break;
-	case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
-		{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL,
-					"\nIPv6 Encrypted Security Payload Header");
-			*bParseDone = TRUE;
 
-		}
+	case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL,
+				"\nIPv6 Encrypted Security Payload Header");
+		*bParseDone = TRUE;
 		break;
+
 	case IPV6_ICMP_HDR_TYPE:
-		{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nICMP Header");
-			*bParseDone = TRUE;
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL, "\nICMP Header");
+		*bParseDone = TRUE;
 		break;
+
 	case TCP_HEADER_TYPE:
-		{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nTCP Header");
-			*bParseDone = TRUE;
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL, "\nTCP Header");
+		*bParseDone = TRUE;
 		break;
+
 	case UDP_HEADER_TYPE:
-		{
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nUDP Header");
-			*bParseDone = TRUE;
-		}
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+				DBG_LVL_ALL, "\nUDP Header");
+		*bParseDone = TRUE;
 		break;
-	default:
-		{
-			*bParseDone = TRUE;
 
-		}
+	default:
+		*bParseDone = TRUE;
 		break;
-
-
 	}
 
 	if (*bParseDone == false) {
@@ -156,7 +151,9 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR
 	ucHeaderType = ucNextHeader;
 	while (!bDone) {
 		pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
-					&ucHeaderType, &bDone, &usPayloadLength);
+							 &ucHeaderType,
+							 &bDone,
+							 &usPayloadLength);
 		if (bDone) {
 			if ((ucHeaderType == TCP_HEADER_TYPE) ||
 				(ucHeaderType == UDP_HEADER_TYPE)) {
@@ -177,11 +174,12 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR
 
 
 /*
- * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver contorl structure
+ * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver control
+ * structure
  * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
  */
 USHORT	IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader,
-					struct bcm_classifier_rule *pstClassifierRule)
+		   struct bcm_classifier_rule *pstClassifierRule)
 {
 	USHORT	ushDestPort = 0;
 	USHORT	ushSrcPort = 0;
@@ -200,11 +198,12 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 	 * Try to get the next higher layer protocol
 	 * and the Ports Nos if TCP or UDP
 	 */
-	ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(struct bcm_ipv6_hdr)),
-							&ushSrcPort,
-							&ushDestPort,
-							pstIpv6Header->usPayloadLength,
-							pstIpv6Header->ucNextHeader);
+	ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader +
+						     sizeof(struct bcm_ipv6_hdr)),
+						     &ushSrcPort,
+						     &ushDestPort,
+						     pstIpv6Header->usPayloadLength,
+						     pstIpv6Header->ucNextHeader);
 
 	do {
 		if (pstClassifierRule->ucDirection == 0) {
@@ -224,12 +223,12 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 		}
 
 		bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
-								pstIpv6Header);
+							     pstIpv6Header);
 		if (!bClassificationSucceed)
 			break;
 
 		bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
-								pstIpv6Header);
+							      pstIpv6Header);
 		if (!bClassificationSucceed)
 			break;
 
@@ -239,7 +238,7 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 		 * Chain of IPv6 prot headers
 		 */
 		bClassificationSucceed = MatchProtocol(pstClassifierRule,
-							ucNextProtocolAboveIP);
+						       ucNextProtocolAboveIP);
 		if (!bClassificationSucceed)
 			break;
 
@@ -253,7 +252,7 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 					DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
 					ntohs(ushSrcPort));
 			bClassificationSucceed = MatchSrcPort(pstClassifierRule,
-							ntohs(ushSrcPort));
+							      ntohs(ushSrcPort));
 			if (!bClassificationSucceed)
 				break;
 
@@ -262,26 +261,27 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 
 			/* Match Dest Port */
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",
+					DBG_LVL_ALL,
+					"\nIPv6 Destination Port:%x\n",
 					ntohs(ushDestPort));
 			bClassificationSucceed = MatchDestPort(pstClassifierRule,
-							ntohs(ushDestPort));
+							       ntohs(ushDestPort));
 			if (!bClassificationSucceed)
 				break;
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
-					DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
+					DBG_LVL_ALL,
+					"\nIPv6 Dest Port Matched");
 		}
 	} while (0);
 
 	if (bClassificationSucceed == TRUE) {
 		INT iMatchedSFQueueIndex = 0;
-		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
-		if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
+
+		iMatchedSFQueueIndex = SearchSfid(Adapter,
+						  pstClassifierRule->ulSFID);
+		if ((iMatchedSFQueueIndex >= NO_OF_QUEUES) ||
+		    (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false))
 			bClassificationSucceed = false;
-		} else {
-			if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false)
-				bClassificationSucceed = false;
-		}
 	}
 
 	return bClassificationSucceed;
@@ -289,18 +289,21 @@ USHORT	IpVersion6(struct bcm_mini_adapte
 
 
 static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
-	struct bcm_ipv6_hdr *pstIpv6Header)
+				struct bcm_ipv6_hdr *pstIpv6Header)
 {
 	UINT uiLoopIndex = 0;
 	UINT uiIpv6AddIndex = 0;
 	UINT uiIpv6AddrNoLongWords = 4;
 	ULONG aulSrcIP[4];
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	union u_ip_address *src_addr = &pstClassifierRule->stSrcIpAddress;
+
 	/*
 	 * This is the no. of Src Addresses ie Range of IP Addresses contained
 	 * in the classifier rule for which we need to match
 	 */
-	UINT  uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
+	UINT  uiCountIPSrcAddresses =
+		(UINT)pstClassifierRule->ucIPSourceAddressLength;
 
 
 	if (uiCountIPSrcAddresses == 0)
@@ -308,23 +311,31 @@ static bool MatchSrcIpv6Address(struct b
 
 
 	/* First Convert the Ip Address in the packet to Host Endian order */
-	for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
-		aulSrcIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
+	for (uiIpv6AddIndex = 0;
+	     uiIpv6AddIndex < uiIpv6AddrNoLongWords;
+	     uiIpv6AddIndex++)
+		aulSrcIP[uiIpv6AddIndex] =
+			ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
 
-	for (uiLoopIndex = 0; uiLoopIndex < uiCountIPSrcAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+	for (uiLoopIndex = 0;
+	     uiLoopIndex < uiCountIPSrcAddresses;
+	     uiLoopIndex += uiIpv6AddrNoLongWords) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Src Ipv6 Address In Received Packet :\n ");
 		DumpIpv6Address(aulSrcIP);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Src Ipv6 Mask In Classifier Rule:\n");
-		DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
+		DumpIpv6Address(&src_addr->ulIpv6Mask[uiLoopIndex]);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Src Ipv6 Address In Classifier Rule :\n");
-		DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
+		DumpIpv6Address(&src_addr->ulIpv6Addr[uiLoopIndex]);
 
-		for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
-			if ((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
-				!= pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+		for (uiIpv6AddIndex = 0;
+		     uiIpv6AddIndex < uiIpv6AddrNoLongWords;
+		     uiIpv6AddIndex++) {
+			if ((src_addr->ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] &
+				aulSrcIP[uiIpv6AddIndex]) !=
+			    src_addr->ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
 				/*
 				 * Match failed for current Ipv6 Address
 				 * Try next Ipv6 Address
@@ -345,43 +356,53 @@ static bool MatchSrcIpv6Address(struct b
 }
 
 static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
-	struct bcm_ipv6_hdr *pstIpv6Header)
+				 struct bcm_ipv6_hdr *pstIpv6Header)
 {
 	UINT uiLoopIndex = 0;
 	UINT uiIpv6AddIndex = 0;
 	UINT uiIpv6AddrNoLongWords = 4;
 	ULONG aulDestIP[4];
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	union u_ip_address *dest_addr = &pstClassifierRule->stDestIpAddress;
+
 	/*
 	 * This is the no. of Destination Addresses
 	 * ie Range of IP Addresses contained in the classifier rule
 	 * for which we need to match
 	 */
-	UINT  uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
-
+	UINT uiCountIPDestinationAddresses =
+		(UINT)pstClassifierRule->ucIPDestinationAddressLength;
 
 	if (uiCountIPDestinationAddresses == 0)
 		return TRUE;
 
 
 	/* First Convert the Ip Address in the packet to Host Endian order */
-	for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
-		aulDestIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
+	for (uiIpv6AddIndex = 0;
+	     uiIpv6AddIndex < uiIpv6AddrNoLongWords;
+	     uiIpv6AddIndex++)
+		aulDestIP[uiIpv6AddIndex] =
+			ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
 
-	for (uiLoopIndex = 0; uiLoopIndex < uiCountIPDestinationAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+	for (uiLoopIndex = 0;
+	     uiLoopIndex < uiCountIPDestinationAddresses;
+	     uiLoopIndex += uiIpv6AddrNoLongWords) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Destination Ipv6 Address In Received Packet :\n ");
 		DumpIpv6Address(aulDestIP);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Destination Ipv6 Mask In Classifier Rule :\n");
-		DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
+		DumpIpv6Address(&dest_addr->ulIpv6Mask[uiLoopIndex]);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				"\n Destination Ipv6 Address In Classifier Rule :\n");
-		DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
+		DumpIpv6Address(&dest_addr->ulIpv6Addr[uiLoopIndex]);
 
-		for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
-			if ((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
-				!= pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+		for (uiIpv6AddIndex = 0;
+		     uiIpv6AddIndex < uiIpv6AddrNoLongWords;
+		     uiIpv6AddIndex++) {
+			if ((dest_addr->ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] &
+				aulDestIP[uiIpv6AddIndex]) !=
+			    dest_addr->ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
 				/*
 				 * Match failed for current Ipv6 Address.
 				 * Try next Ipv6 Address
@@ -407,7 +428,10 @@ VOID DumpIpv6Address(ULONG *puIpv6Addres
 	UINT uiIpv6AddrNoLongWords = 4;
 	UINT uiIpv6AddIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+
+	for (uiIpv6AddIndex = 0;
+	     uiIpv6AddIndex < uiIpv6AddrNoLongWords;
+	     uiIpv6AddIndex++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 				":%lx", puIpv6Address[uiIpv6AddIndex]);
 	}
@@ -419,6 +443,7 @@ static VOID DumpIpv6Header(struct bcm_ip
 	UCHAR ucVersion;
 	UCHAR ucPrio;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
 			"----Ipv6 Header---");
 	ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/LeakyBucket.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/LeakyBucket.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/LeakyBucket.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/LeakyBucket.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,7 @@ static VOID UpdateTokenCount(register st
 	ULONG liCurrentTime;
 	INT i = 0;
 	struct timeval tv;
+	struct bcm_packet_info *curr_pi;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
 			"=====>\n");
@@ -31,30 +32,30 @@ static VOID UpdateTokenCount(register st
 
 	do_gettimeofday(&tv);
 	for (i = 0; i < NO_OF_QUEUES; i++) {
-		if (TRUE == Adapter->PackInfo[i].bValid &&
-		    (1 == Adapter->PackInfo[i].ucDirection)) {
-			liCurrentTime = ((tv.tv_sec-
-				Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
-				(tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
+		curr_pi = &Adapter->PackInfo[i];
+
+		if (TRUE == curr_pi->bValid && (1 == curr_pi->ucDirection)) {
+			liCurrentTime = ((tv.tv_sec -
+				curr_pi->stLastUpdateTokenAt.tv_sec)*1000 +
+				(tv.tv_usec - curr_pi->stLastUpdateTokenAt.tv_usec) /
 				1000);
 			if (0 != liCurrentTime) {
-				Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
-					((Adapter->PackInfo[i].uiMaxAllowedRate) *
+				curr_pi->uiCurrentTokenCount += (ULONG)
+					((curr_pi->uiMaxAllowedRate) *
 					((ULONG)((liCurrentTime)))/1000);
-				memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
-					&tv, sizeof(struct timeval));
-				Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
-				if (Adapter->PackInfo[i].uiCurrentTokenCount >=
-				    Adapter->PackInfo[i].uiMaxBucketSize) {
-					Adapter->PackInfo[i].uiCurrentTokenCount =
-						Adapter->PackInfo[i].uiMaxBucketSize;
+				memcpy(&curr_pi->stLastUpdateTokenAt, &tv,
+				       sizeof(struct timeval));
+				curr_pi->liLastUpdateTokenAt = liCurrentTime;
+				if (curr_pi->uiCurrentTokenCount >=
+				    curr_pi->uiMaxBucketSize) {
+					curr_pi->uiCurrentTokenCount =
+						curr_pi->uiMaxBucketSize;
 				}
 			}
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
-	return;
-
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+			"<=====\n");
 }
 
 
@@ -74,26 +75,35 @@ static VOID UpdateTokenCount(register st
 ***********************************************************************/
 static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
 {
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+			"IsPacketAllowedForFlow ===>");
+
 	/* Validate the parameters */
 	if (NULL == Adapter || (psSF < Adapter->PackInfo &&
 	    (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo));
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+				"IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n",
+				Adapter, (psSF-Adapter->PackInfo));
 		return 0;
 	}
 
 	if (false != psSF->bValid && psSF->ucDirection) {
 		if (0 != psSF->uiCurrentTokenCount) {
-				return psSF->uiCurrentTokenCount;
+			return psSF->uiCurrentTokenCount;
 		} else {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
-				psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
+					DBG_LVL_ALL,
+					"Not enough tokens in queue %zd Available %u\n",
+					psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
 			psSF->uiPendedLast = 1;
 		}
 	} else {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+				"IPAFF: Queue %zd not valid\n",
+				psSF-Adapter->PackInfo);
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+			"IsPacketAllowedForFlow <===");
 	return 0;
 }
 
@@ -103,15 +113,17 @@ This function despatches packet from the
 @return Zero(success) or Negative value(failure)
 */
 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
-			struct bcm_packet_info *psSF, /**<Queue identifier*/
+			       struct bcm_packet_info *psSF, /**<Queue identifier*/
 			       struct sk_buff *Packet)	/**<Pointer to the packet to be sent*/
 {
 	INT Status = STATUS_FAILURE;
 	UINT uiIndex = 0, PktLen = 0;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
+			"=====>");
 	if (!Adapter || !Packet || !psSF) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
+				"Got NULL Adapter or Packet");
 		return -EINVAL;
 	}
 
@@ -122,118 +134,155 @@ static INT SendPacketFromQueue(struct bc
 	Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
 	if (Status == 0) {
 		for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
-			if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
+			if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
+			    (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
 				Adapter->aTxPktSizeHist[uiIndex]++;
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
+			"<=====");
 	return Status;
 }
 
-/************************************************************************
-* Function    - CheckAndSendPacketFromIndex()
-*
-* Description - This function dequeues the data/control packet from the
-*				specified queue for transmission.
-*
-* Parameters  - Adapter : Pointer to the driver control structure.
-* 			  - iQIndex : The queue Identifier.
-*
-* Returns     - None.
-*
-****************************************************************************/
-static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
+static void get_data_packet(struct bcm_mini_adapter *ad,
+			    struct bcm_packet_info *ps_sf)
 {
-	struct sk_buff *QueuePacket = NULL;
-	char *pControlPacket = NULL;
-	INT Status = 0;
-	int iPacketLen = 0;
-
+	int packet_len;
+	struct sk_buff *qpacket;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
-	if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
-		if (!psSF->ucDirection)
-			return;
+	if (!ps_sf->ucDirection)
+		return;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
-		if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
-			return;	/* in idle mode */
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"UpdateTokenCount ");
+	if (ad->IdleMode || ad->bPreparingForLowPowerMode)
+		return; /* in idle mode */
 
-		/* Check for Free Descriptors */
-		if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc));
-			return;
-		}
+	/* Check for Free Descriptors */
+	if (atomic_read(&ad->CurrNumFreeTxDesc) <=
+	    MINIMUM_PENDING_DESCRIPTORS) {
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+				" No Free Tx Descriptor(%d) is available for Data pkt..",
+				atomic_read(&ad->CurrNumFreeTxDesc));
+		return;
+	}
 
-		spin_lock_bh(&psSF->SFQueueLock);
-		QueuePacket = psSF->FirstTxQueue;
+	spin_lock_bh(&ps_sf->SFQueueLock);
+	qpacket = ps_sf->FirstTxQueue;
 
-		if (QueuePacket) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
+	if (qpacket) {
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+				"Dequeuing Data Packet");
 
-			if (psSF->bEthCSSupport)
-				iPacketLen = QueuePacket->len;
-			else
-				iPacketLen = QueuePacket->len-ETH_HLEN;
+		if (ps_sf->bEthCSSupport)
+			packet_len = qpacket->len;
+		else
+			packet_len = qpacket->len - ETH_HLEN;
 
-			iPacketLen <<= 3;
-			if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
-					(iPacketLen >> 3));
+		packet_len <<= 3;
+		if (packet_len <= GetSFTokenCount(ad, ps_sf)) {
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL, "Allowed bytes %d",
+					(packet_len >> 3));
 
-				DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue);
-				psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
-				psSF->uiCurrentPacketsOnHost--;
-				atomic_dec(&Adapter->TotalPacketCount);
-				spin_unlock_bh(&psSF->SFQueueLock);
+			DEQUEUEPACKET(ps_sf->FirstTxQueue, ps_sf->LastTxQueue);
+			ps_sf->uiCurrentBytesOnHost -= (qpacket->len);
+			ps_sf->uiCurrentPacketsOnHost--;
+				atomic_dec(&ad->TotalPacketCount);
+			spin_unlock_bh(&ps_sf->SFQueueLock);
 
-				Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
-				psSF->uiPendedLast = false;
-			} else {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
-					psSF->uiCurrentTokenCount, iPacketLen);
-				/*
-				this part indicates that because of non-availability of the tokens
-				pkt has not been send out hence setting the pending flag indicating the host to send it out
-				first next iteration.
-				*/
-				psSF->uiPendedLast = TRUE;
-				spin_unlock_bh(&psSF->SFQueueLock);
-			}
+			SendPacketFromQueue(ad, ps_sf, qpacket);
+			ps_sf->uiPendedLast = false;
 		} else {
-			spin_unlock_bh(&psSF->SFQueueLock);
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL, "For Queue: %zd\n",
+					ps_sf - ad->PackInfo);
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL,
+					"\nAvailable Tokens = %d required = %d\n",
+					ps_sf->uiCurrentTokenCount,
+					packet_len);
+			/*
+			this part indicates that because of
+			non-availability of the tokens
+			pkt has not been send out hence setting the
+			pending flag indicating the host to send it out
+			first next iteration.
+			*/
+			ps_sf->uiPendedLast = TRUE;
+			spin_unlock_bh(&ps_sf->SFQueueLock);
 		}
 	} else {
+		spin_unlock_bh(&ps_sf->SFQueueLock);
+	}
+}
 
-		if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) &&
-		    (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
-		     atomic_read(&Adapter->index_wr_txcntrlpkt))) {
-			pControlPacket = Adapter->txctlpacket
-			[(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
-			if (pControlPacket) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
-				Status = SendControlPacket(Adapter, pControlPacket);
-				if (STATUS_SUCCESS == Status) {
-					spin_lock_bh(&psSF->SFQueueLock);
-					psSF->NumOfPacketsSent++;
-					psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength;
-					psSF->uiSentPackets++;
-					atomic_dec(&Adapter->TotalPacketCount);
-					psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
-					psSF->uiCurrentPacketsOnHost--;
-					atomic_inc(&Adapter->index_rd_txcntrlpkt);
-					spin_unlock_bh(&psSF->SFQueueLock);
-				} else {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
-				}
+static void send_control_packet(struct bcm_mini_adapter *ad,
+				struct bcm_packet_info *ps_sf)
+{
+	char *ctrl_packet = NULL;
+	INT status = 0;
+
+	if ((atomic_read(&ad->CurrNumFreeTxDesc) > 0) &&
+	    (atomic_read(&ad->index_rd_txcntrlpkt) !=
+	     atomic_read(&ad->index_wr_txcntrlpkt))) {
+		ctrl_packet = ad->txctlpacket
+		[(atomic_read(&ad->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
+		if (ctrl_packet) {
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL,
+					"Sending Control packet");
+			status = SendControlPacket(ad, ctrl_packet);
+			if (STATUS_SUCCESS == status) {
+				spin_lock_bh(&ps_sf->SFQueueLock);
+				ps_sf->NumOfPacketsSent++;
+				ps_sf->uiSentBytes += ((struct bcm_leader *)ctrl_packet)->PLength;
+				ps_sf->uiSentPackets++;
+				atomic_dec(&ad->TotalPacketCount);
+				ps_sf->uiCurrentBytesOnHost -= ((struct bcm_leader *)ctrl_packet)->PLength;
+				ps_sf->uiCurrentPacketsOnHost--;
+				atomic_inc(&ad->index_rd_txcntrlpkt);
+				spin_unlock_bh(&ps_sf->SFQueueLock);
 			} else {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
+				BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+						DBG_LVL_ALL,
+						"SendControlPacket Failed\n");
 			}
+		} else {
+			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL,
+					" Control Pkt is not available, Indexing is wrong....");
 		}
 	}
 }
 
+/************************************************************************
+* Function    - CheckAndSendPacketFromIndex()
+*
+* Description - This function dequeues the data/control packet from the
+*				specified queue for transmission.
+*
+* Parameters  - Adapter : Pointer to the driver control structure.
+* 			  - iQIndex : The queue Identifier.
+*
+* Returns     - None.
+*
+****************************************************************************/
+static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter,
+					struct bcm_packet_info *psSF)
+{
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"%zd ====>", (psSF-Adapter->PackInfo));
+	if ((psSF != &Adapter->PackInfo[HiPriority]) &&
+	    Adapter->LinkUpStatus &&
+	    atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
+
+		get_data_packet(Adapter, psSF);
+	} else {
+		send_control_packet(Adapter, psSF);
+	}
+}
+
 
 /*******************************************************************
 * Function    - transmit_packets()
@@ -252,22 +301,27 @@ VOID transmit_packets(struct bcm_mini_ad
 
 	bool exit_flag = TRUE;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"=====>");
 
 	if (NULL == Adapter) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+				"Got NULL Adapter");
 		return;
 	}
 	if (Adapter->device_removed == TRUE) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+				"Device removed");
 		return;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"\nUpdateTokenCount ====>\n");
 
 	UpdateTokenCount(Adapter);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"\nPruneQueueAllSF ====>\n");
 
 	PruneQueueAllSF(Adapter);
 
@@ -280,8 +334,11 @@ VOID transmit_packets(struct bcm_mini_ad
 		if (Adapter->PackInfo[iIndex].bValid &&
 		    Adapter->PackInfo[iIndex].uiPendedLast &&
 		    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
-			CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL,
+					"Calling CheckAndSendPacketFromIndex..");
+			CheckAndSendPacketFromIndex(Adapter,
+						    &Adapter->PackInfo[iIndex]);
 			uiPrevTotalCount--;
 		}
 	}
@@ -290,13 +347,16 @@ VOID transmit_packets(struct bcm_mini_ad
 		exit_flag = TRUE;
 		/* second iteration to parse non-pending queues */
 		for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
-			if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
+			if (!uiPrevTotalCount ||
+			    (TRUE == Adapter->device_removed))
 				break;
 
 			if (Adapter->PackInfo[iIndex].bValid &&
 			    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
 			    !Adapter->PackInfo[iIndex].uiPendedLast) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
+						TX_PACKETS, DBG_LVL_ALL,
+						"Calling CheckAndSendPacketFromIndex..");
 				CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 				uiPrevTotalCount--;
 				exit_flag = false;
@@ -304,7 +364,8 @@ VOID transmit_packets(struct bcm_mini_ad
 		}
 
 		if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
+					DBG_LVL_ALL, "In Idle Mode\n");
 			break;
 		}
 		if (exit_flag == TRUE)
@@ -313,5 +374,6 @@ VOID transmit_packets(struct bcm_mini_ad
 
 	update_per_cid_rx(Adapter);
 	Adapter->txtransmit_running = 0;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+			"<======");
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/led_control.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/led_control.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/led_control.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/led_control.c	2014-09-28 17:29:07.000000000 -0400
@@ -6,6 +6,7 @@
 static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
 {
 	B_UINT16 u16CheckSum = 0;
+
 	while (u32Size--) {
 		u16CheckSum += (B_UINT8)~(*pu8Buffer);
 		pu8Buffer++;
@@ -16,6 +17,7 @@ static B_UINT16 CFG_CalculateChecksum(B_
 bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios)
 {
 	INT Status;
+
 	Status = (Adapter->gpioBitMap & gpios) ^ gpios;
 	if (Status)
 		return false;
@@ -23,8 +25,12 @@ bool IsReqGpioIsLedInNVM(struct bcm_mini
 		return TRUE;
 }
 
-static INT LED_Blink(struct bcm_mini_adapter *Adapter, UINT GPIO_Num, UCHAR uiLedIndex,
-		ULONG timeout, INT num_of_time, enum bcm_led_events currdriverstate)
+static INT LED_Blink(struct bcm_mini_adapter *Adapter,
+		     UINT GPIO_Num,
+		     UCHAR uiLedIndex,
+		     ULONG timeout,
+		     INT num_of_time,
+		     enum bcm_led_events currdriverstate)
 {
 	int Status = STATUS_SUCCESS;
 	bool bInfinite = false;
@@ -36,7 +42,7 @@ static INT LED_Blink(struct bcm_mini_ada
 	}
 	while (num_of_time) {
 		if (currdriverstate == Adapter->DriverState)
-			TURN_ON_LED(GPIO_Num, uiLedIndex);
+			TURN_ON_LED(Adapter, GPIO_Num, uiLedIndex);
 
 		/* Wait for timeout after setting on the LED */
 		Status = wait_event_interruptible_timeout(
@@ -51,17 +57,17 @@ static INT LED_Blink(struct bcm_mini_ada
 				"Led thread got signal to exit..hence exiting");
 			Adapter->LEDInfo.led_thread_running =
 					BCM_LED_THREAD_DISABLED;
-			TURN_OFF_LED(GPIO_Num, uiLedIndex);
+			TURN_OFF_LED(Adapter, GPIO_Num, uiLedIndex);
 			Status = EVENT_SIGNALED;
 			break;
 		}
 		if (Status) {
-			TURN_OFF_LED(GPIO_Num, uiLedIndex);
+			TURN_OFF_LED(Adapter, GPIO_Num, uiLedIndex);
 			Status = EVENT_SIGNALED;
 			break;
 		}
 
-		TURN_OFF_LED(GPIO_Num, uiLedIndex);
+		TURN_OFF_LED(Adapter, GPIO_Num, uiLedIndex);
 		Status = wait_event_interruptible_timeout(
 				Adapter->LEDInfo.notify_led_event,
 				currdriverstate != Adapter->DriverState ||
@@ -93,11 +99,59 @@ static INT ScaleRateofTransfer(ULONG rat
 		return MAX_NUM_OF_BLINKS;
 }
 
+static INT blink_in_normal_bandwidth(struct bcm_mini_adapter *ad,
+				     INT *time,
+				     INT *time_tx,
+				     INT *time_rx,
+				     UCHAR GPIO_Num_tx,
+				     UCHAR uiTxLedIndex,
+				     UCHAR GPIO_Num_rx,
+				     UCHAR uiRxLedIndex,
+				     enum bcm_led_events currdriverstate,
+				     ulong *timeout)
+{
+	/*
+	 * Assign minimum number of blinks of
+	 * either Tx or Rx.
+	 */
+	*time = (*time_tx > *time_rx ? *time_rx : *time_tx);
+
+	if (*time > 0) {
+		/* Blink both Tx and Rx LEDs */
+		if ((LED_Blink(ad, 1 << GPIO_Num_tx, uiTxLedIndex, *timeout,
+			      *time, currdriverstate) == EVENT_SIGNALED) ||
+		    (LED_Blink(ad, 1 << GPIO_Num_rx, uiRxLedIndex, *timeout,
+			      *time, currdriverstate) == EVENT_SIGNALED))
+			return EVENT_SIGNALED;
+	}
+
+	if (*time == *time_tx) {
+		/* Blink pending rate of Rx */
+		if (LED_Blink(ad, (1 << GPIO_Num_rx), uiRxLedIndex, *timeout,
+			      *time_rx - *time,
+			      currdriverstate) == EVENT_SIGNALED)
+			return EVENT_SIGNALED;
 
+		*time = *time_rx;
+	} else {
+		/* Blink pending rate of Tx */
+		if (LED_Blink(ad, 1 << GPIO_Num_tx, uiTxLedIndex, *timeout,
+			      *time_tx - *time,
+			      currdriverstate) == EVENT_SIGNALED)
+			return EVENT_SIGNALED;
 
-static INT LED_Proportional_Blink(struct bcm_mini_adapter *Adapter, UCHAR GPIO_Num_tx,
-		UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex,
-		enum bcm_led_events currdriverstate)
+		*time = *time_tx;
+	}
+
+	return 0;
+}
+
+static INT LED_Proportional_Blink(struct bcm_mini_adapter *Adapter,
+				  UCHAR GPIO_Num_tx,
+				  UCHAR uiTxLedIndex,
+				  UCHAR GPIO_Num_rx,
+				  UCHAR uiRxLedIndex,
+				  enum bcm_led_events currdriverstate)
 {
 	/* Initial values of TX and RX packets */
 	ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
@@ -108,7 +162,6 @@ static INT LED_Proportional_Blink(struct
 	int Status = STATUS_SUCCESS;
 	INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
 	UINT remDelay = 0;
-	bool bBlinkBothLED = TRUE;
 	/* UINT GPIO_num = DISABLE_GPIO_NUM; */
 	ulong timeout = 0;
 
@@ -122,73 +175,19 @@ static INT LED_Proportional_Blink(struct
 
 	while ((Adapter->device_removed == false)) {
 		timeout = 50;
-		/*
-		 * Blink Tx and Rx LED when both Tx and Rx is
-		 * in normal bandwidth
-		 */
-		if (bBlinkBothLED) {
-			/*
-			 * Assign minimum number of blinks of
-			 * either Tx or Rx.
-			 */
-			if (num_of_time_tx > num_of_time_rx)
-				num_of_time = num_of_time_rx;
-			else
-				num_of_time = num_of_time_tx;
-			if (num_of_time > 0) {
-				/* Blink both Tx and Rx LEDs */
-				if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
-						uiTxLedIndex, timeout,
-						num_of_time, currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
-
-				if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
-						uiRxLedIndex, timeout,
-						num_of_time, currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
-
-			}
-
-			if (num_of_time == num_of_time_tx) {
-				/* Blink pending rate of Rx */
-				if (LED_Blink(Adapter, (1 << GPIO_Num_rx),
-						uiRxLedIndex, timeout,
-						num_of_time_rx-num_of_time,
-						currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
 
-				num_of_time = num_of_time_rx;
-			} else {
-				/* Blink pending rate of Tx */
-				if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
-						uiTxLedIndex, timeout,
-						num_of_time_tx-num_of_time,
-						currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
+		if (EVENT_SIGNALED == blink_in_normal_bandwidth(Adapter,
+								&num_of_time,
+								&num_of_time_tx,
+								&num_of_time_rx,
+								GPIO_Num_tx,
+								uiTxLedIndex,
+								GPIO_Num_rx,
+								uiRxLedIndex,
+								currdriverstate,
+								&timeout))
+			return EVENT_SIGNALED;
 
-				num_of_time = num_of_time_tx;
-			}
-		} else {
-			if (num_of_time == num_of_time_tx) {
-				/* Blink pending rate of Rx */
-				if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
-						uiTxLedIndex, timeout,
-						num_of_time, currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
-			} else {
-				/* Blink pending rate of Tx */
-				if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
-						uiRxLedIndex, timeout,
-						num_of_time, currdriverstate)
-							== EVENT_SIGNALED)
-					return EVENT_SIGNALED;
-			}
-		}
 
 		/*
 		 * If Tx/Rx rate is less than maximum blinks per second,
@@ -216,8 +215,8 @@ static INT LED_Proportional_Blink(struct
 		}
 
 		/* Turn off both Tx and Rx LEDs before next second */
-		TURN_OFF_LED(1 << GPIO_Num_tx, uiTxLedIndex);
-		TURN_OFF_LED(1 << GPIO_Num_rx, uiTxLedIndex);
+		TURN_OFF_LED(Adapter, 1 << GPIO_Num_tx, uiTxLedIndex);
+		TURN_OFF_LED(Adapter, 1 << GPIO_Num_rx, uiTxLedIndex);
 
 		/*
 		 * Read the Tx & Rx packets transmission after 1 second and
@@ -261,8 +260,9 @@ static INT LED_Proportional_Blink(struct
  *  <OSAL_STATUS_CODE>
  * -----------------------------------------------------------------------------
  */
-static INT ValidateDSDParamsChecksum(struct bcm_mini_adapter *Adapter, ULONG ulParamOffset,
-					USHORT usParamLen)
+static INT ValidateDSDParamsChecksum(struct bcm_mini_adapter *Adapter,
+				     ULONG ulParamOffset,
+				     USHORT usParamLen)
 {
 	INT Status = STATUS_SUCCESS;
 	PUCHAR puBuffer = NULL;
@@ -270,24 +270,24 @@ static INT ValidateDSDParamsChecksum(str
 	USHORT usChecksumCalculated = 0;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
-		ulParamOffset, usParamLen);
+			"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
+			ulParamOffset, usParamLen);
 
 	puBuffer = kmalloc(usParamLen, GFP_KERNEL);
 	if (!puBuffer) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL,
-			"LED Thread: ValidateDSDParamsChecksum Allocation failed");
+				DBG_LVL_ALL,
+				"LED Thread: ValidateDSDParamsChecksum Allocation failed");
 		return -ENOMEM;
 
 	}
 
 	/* Read the DSD data from the parameter offset. */
 	if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)puBuffer,
-			ulParamOffset, usParamLen)) {
+					    ulParamOffset, usParamLen)) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL,
-			"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+				DBG_LVL_ALL,
+				"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
 		Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
 		goto exit;
 	}
@@ -295,24 +295,24 @@ static INT ValidateDSDParamsChecksum(str
 	/* Calculate the checksum of the data read from the DSD parameter. */
 	usChecksumCalculated = CFG_CalculateChecksum(puBuffer, usParamLen);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread: usCheckSumCalculated = 0x%x\n",
-		usChecksumCalculated);
+			"LED Thread: usCheckSumCalculated = 0x%x\n",
+			usChecksumCalculated);
 
 	/*
 	 * End of the DSD parameter will have a TWO bytes checksum stored in it.
 	 * Read it and compare with the calculated Checksum.
 	 */
 	if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)&usChksmOrg,
-			ulParamOffset+usParamLen, 2)) {
+					    ulParamOffset+usParamLen, 2)) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL,
-			"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+				DBG_LVL_ALL,
+				"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
 		Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
 		goto exit;
 	}
 	usChksmOrg = ntohs(usChksmOrg);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread: usChksmOrg = 0x%x", usChksmOrg);
+			"LED Thread: usChksmOrg = 0x%x", usChksmOrg);
 
 	/*
 	 * Compare the checksum calculated with the checksum read
@@ -320,8 +320,8 @@ static INT ValidateDSDParamsChecksum(str
 	 */
 	if (usChecksumCalculated ^ usChksmOrg) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL,
-			"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
+				DBG_LVL_ALL,
+				"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
 		Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
 		goto exit;
 	}
@@ -347,7 +347,8 @@ exit:
  *  <OSAL_STATUS_CODE>
  * -----------------------------------------------------------------------------
  */
-static INT ValidateHWParmStructure(struct bcm_mini_adapter *Adapter, ULONG ulHwParamOffset)
+static INT ValidateHWParmStructure(struct bcm_mini_adapter *Adapter,
+				   ULONG ulHwParamOffset)
 {
 
 	INT Status = STATUS_SUCCESS;
@@ -365,9 +366,9 @@ static INT ValidateHWParmStructure(struc
 		return STATUS_IMAGE_CHECKSUM_MISMATCH;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread:HwParamLen = 0x%x", HwParamLen);
+			"LED Thread:HwParamLen = 0x%x", HwParamLen);
 	Status = ValidateDSDParamsChecksum(Adapter, ulHwParamOffset,
-						HwParamLen);
+					   HwParamLen);
 	return Status;
 } /* ValidateHWParmStructure() */
 
@@ -383,16 +384,17 @@ static int ReadLEDInformationFromEEPROM(
 	UCHAR  ucGPIOInfo[32]	= {0};
 
 	BeceemNVMRead(Adapter, (PUINT)&usEEPROMVersion,
-			EEPROM_VERSION_OFFSET, 2);
+		      EEPROM_VERSION_OFFSET, 2);
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"usEEPROMVersion: Minor:0x%X Major:0x%x",
-		usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
+			"usEEPROMVersion: Minor:0x%X Major:0x%x",
+			usEEPROMVersion & 0xFF,
+			((usEEPROMVersion >> 8) & 0xFF));
 
 
 	if (((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) {
 		BeceemNVMRead(Adapter, (PUINT)&usHwParamData,
-			EEPROM_HW_PARAM_POINTER_ADDRESS, 2);
+			      EEPROM_HW_PARAM_POINTER_ADDRESS, 2);
 		usHwParamData = ntohs(usHwParamData);
 		dwReadValue   = usHwParamData;
 	} else {
@@ -401,21 +403,21 @@ static int ReadLEDInformationFromEEPROM(
 		 * if compatibility section is valid.
 		 */
 		Status = ValidateDSDParamsChecksum(Adapter,
-				DSD_START_OFFSET,
-				COMPATIBILITY_SECTION_LENGTH_MAP5);
+						   DSD_START_OFFSET,
+						   COMPATIBILITY_SECTION_LENGTH_MAP5);
 
 		if (Status != STATUS_SUCCESS)
 			return Status;
 
 		BeceemNVMRead(Adapter, (PUINT)&dwReadValue,
-			EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5, 4);
+			      EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5, 4);
 		dwReadValue = ntohl(dwReadValue);
 	}
 
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread: Start address of HW_PARAM structure = 0x%lx",
-		dwReadValue);
+			"LED Thread: Start address of HW_PARAM structure = 0x%lx",
+			dwReadValue);
 
 	/*
 	 * Validate if the address read out is within the DSD.
@@ -437,8 +439,8 @@ static int ReadLEDInformationFromEEPROM(
 	 * To read GPIO section, add GPIO offset further.
 	 */
 
-	dwReadValue +=
-		DSD_START_OFFSET; /* = start address of hw param section. */
+	dwReadValue += DSD_START_OFFSET;
+			/* = start address of hw param section. */
 	dwReadValue += GPIO_SECTION_START_OFFSET;
 			/* = GPIO start offset within HW Param section. */
 
@@ -472,13 +474,14 @@ static int ReadLEDInformationFromEEPROM(
 
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"GPIO's bit map correspond to LED :0x%X", Adapter->gpioBitMap);
+			"GPIO's bit map correspond to LED :0x%X",
+			Adapter->gpioBitMap);
 	return Status;
 }
 
 
 static int ReadConfigFileStructure(struct bcm_mini_adapter *Adapter,
-					bool *bEnableThread)
+				   bool *bEnableThread)
 {
 	int Status = STATUS_SUCCESS;
 	/* Array to store GPIO numbers from EEPROM */
@@ -487,11 +490,13 @@ static int ReadConfigFileStructure(struc
 	UINT uiNum_of_LED_Type = 0;
 	PUCHAR puCFGData	= NULL;
 	UCHAR bData = 0;
+	struct bcm_led_state_info *curr_led_state;
+
 	memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
 
 	if (!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) {
-		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL, "Target Params not Avail.\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+				DBG_LVL_ALL, "Target Params not Avail.\n");
 		return -ENOENT;
 	}
 
@@ -511,7 +516,7 @@ static int ReadConfigFileStructure(struc
 	 * uiFileNameBufferSize
 	 */
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
-		"LED Thread: Config file read successfully\n");
+			"LED Thread: Config file read successfully\n");
 	puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
 
 	/*
@@ -522,31 +527,30 @@ static int ReadConfigFileStructure(struc
 
 	for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
 		bData = *puCFGData;
+		curr_led_state = &Adapter->LEDInfo.LEDState[uiIndex];
 
 		/*
 		 * Check Bit 8 for polarity. If it is set,
 		 * polarity is reverse polarity
 		 */
 		if (bData & 0x80) {
-			Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
+			curr_led_state->BitPolarity = 0;
 			/* unset the bit 8 */
 			bData = bData & 0x7f;
 		}
 
-		Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
+		curr_led_state->LED_Type = bData;
 		if (bData <= NUM_OF_LEDS)
-			Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
-							GPIO_Array[bData];
+			curr_led_state->GPIO_Num = GPIO_Array[bData];
 		else
-			Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
-							DISABLE_GPIO_NUM;
+			curr_led_state->GPIO_Num = DISABLE_GPIO_NUM;
 
 		puCFGData++;
 		bData = *puCFGData;
-		Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
+		curr_led_state->LED_On_State = bData;
 		puCFGData++;
 		bData = *puCFGData;
-		Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State = bData;
+		curr_led_state->LED_Blink_State = bData;
 		puCFGData++;
 	}
 
@@ -555,9 +559,11 @@ static int ReadConfigFileStructure(struc
 	 * dont launch the LED control thread.
 	 */
 	for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
-		if ((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
-			(Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
-			(Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
+		curr_led_state = &Adapter->LEDInfo.LEDState[uiIndex];
+
+		if ((curr_led_state->LED_Type == DISABLE_GPIO_NUM) ||
+			(curr_led_state->LED_Type == 0x7f) ||
+			(curr_led_state->LED_Type == 0))
 			uiNum_of_LED_Type++;
 	}
 	if (uiNum_of_LED_Type >= NUM_OF_LEDS)
@@ -584,67 +590,237 @@ static VOID LedGpioInit(struct bcm_mini_
 {
 	UINT uiResetValue = 0;
 	UINT uiIndex      = 0;
+	struct bcm_led_state_info *curr_led_state;
 
 	/* Set all LED GPIO Mode to output mode */
 	if (rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
-			sizeof(uiResetValue)) < 0)
+		   sizeof(uiResetValue)) < 0)
 		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
 			DBG_LVL_ALL, "LED Thread: RDM Failed\n");
 	for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
-		if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
-				DISABLE_GPIO_NUM)
-			uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
-		TURN_OFF_LED(1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,
-				uiIndex);
+		curr_led_state = &Adapter->LEDInfo.LEDState[uiIndex];
+
+		if (curr_led_state->GPIO_Num != DISABLE_GPIO_NUM)
+			uiResetValue |= (1 << curr_led_state->GPIO_Num);
+
+		TURN_OFF_LED(Adapter, 1 << curr_led_state->GPIO_Num, uiIndex);
+
 	}
 	if (wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
-			sizeof(uiResetValue)) < 0)
-		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL, "LED Thread: WRM Failed\n");
+		   sizeof(uiResetValue)) < 0)
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+				DBG_LVL_ALL, "LED Thread: WRM Failed\n");
 
 	Adapter->LEDInfo.bIdle_led_off = false;
 }
 
-static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter, UCHAR *GPIO_num_tx,
-		UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,
-		enum bcm_led_events currdriverstate)
+static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter,
+			     UCHAR *GPIO_num_tx,
+			     UCHAR *GPIO_num_rx,
+			     UCHAR *uiLedTxIndex,
+			     UCHAR *uiLedRxIndex,
+			     enum bcm_led_events currdriverstate)
 {
 	UINT uiIndex = 0;
+	struct bcm_led_state_info *led_state_info;
 
 	*GPIO_num_tx = DISABLE_GPIO_NUM;
 	*GPIO_num_rx = DISABLE_GPIO_NUM;
 
 	for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+		led_state_info = &Adapter->LEDInfo.LEDState[uiIndex];
 
-		if ((currdriverstate == NORMAL_OPERATION) ||
-				(currdriverstate == IDLEMODE_EXIT) ||
-				(currdriverstate == FW_DOWNLOAD)) {
-			if (Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State &
-					currdriverstate) {
-				if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
-						!= DISABLE_GPIO_NUM) {
-					if (*GPIO_num_tx == DISABLE_GPIO_NUM) {
-						*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
-						*uiLedTxIndex = uiIndex;
-					} else {
-						*GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
-						*uiLedRxIndex = uiIndex;
-					}
-				}
+		if (((currdriverstate == NORMAL_OPERATION) ||
+			(currdriverstate == IDLEMODE_EXIT) ||
+			(currdriverstate == FW_DOWNLOAD)) &&
+		    (led_state_info->LED_Blink_State & currdriverstate) &&
+		    (led_state_info->GPIO_Num != DISABLE_GPIO_NUM)) {
+			if (*GPIO_num_tx == DISABLE_GPIO_NUM) {
+				*GPIO_num_tx = led_state_info->GPIO_Num;
+				*uiLedTxIndex = uiIndex;
+			} else {
+				*GPIO_num_rx = led_state_info->GPIO_Num;
+				*uiLedRxIndex = uiIndex;
 			}
 		} else {
-			if (Adapter->LEDInfo.LEDState[uiIndex].LED_On_State
-					& currdriverstate) {
-				if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
-						!= DISABLE_GPIO_NUM) {
-					*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
-					*uiLedTxIndex = uiIndex;
-				}
+			if ((led_state_info->LED_On_State & currdriverstate) &&
+			    (led_state_info->GPIO_Num != DISABLE_GPIO_NUM)) {
+				*GPIO_num_tx = led_state_info->GPIO_Num;
+				*uiLedTxIndex = uiIndex;
 			}
 		}
 	}
 	return STATUS_SUCCESS;
 }
+
+static void handle_adapter_driver_state(struct bcm_mini_adapter *ad,
+					enum bcm_led_events currdriverstate,
+					UCHAR GPIO_num,
+					UCHAR dummyGPIONum,
+					UCHAR uiLedIndex,
+					UCHAR dummyIndex,
+					ulong timeout,
+					UINT uiResetValue,
+					UINT uiIndex)
+{
+	switch (ad->DriverState) {
+	case DRIVER_INIT:
+		currdriverstate = DRIVER_INIT;
+				/* ad->DriverState; */
+		BcmGetGPIOPinInfo(ad, &GPIO_num, &dummyGPIONum,
+				  &uiLedIndex, &dummyIndex,
+				  currdriverstate);
+
+		if (GPIO_num != DISABLE_GPIO_NUM)
+			TURN_ON_LED(ad, 1 << GPIO_num, uiLedIndex);
+
+		break;
+	case FW_DOWNLOAD:
+		/*
+		 * BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
+		 *	LED_DUMP_INFO, DBG_LVL_ALL,
+		 *	"LED Thread: FW_DN_DONE called\n");
+		 */
+		currdriverstate = FW_DOWNLOAD;
+		BcmGetGPIOPinInfo(ad, &GPIO_num, &dummyGPIONum,
+				  &uiLedIndex, &dummyIndex,
+				  currdriverstate);
+
+		if (GPIO_num != DISABLE_GPIO_NUM) {
+			timeout = 50;
+			LED_Blink(ad, 1 << GPIO_num, uiLedIndex, timeout,
+				  -1, currdriverstate);
+		}
+		break;
+	case FW_DOWNLOAD_DONE:
+		currdriverstate = FW_DOWNLOAD_DONE;
+		BcmGetGPIOPinInfo(ad, &GPIO_num, &dummyGPIONum,
+				  &uiLedIndex, &dummyIndex, currdriverstate);
+		if (GPIO_num != DISABLE_GPIO_NUM)
+			TURN_ON_LED(ad, 1 << GPIO_num, uiLedIndex);
+		break;
+
+	case SHUTDOWN_EXIT:
+		/*
+		 * no break, continue to NO_NETWORK_ENTRY
+		 * state as well.
+		 */
+	case NO_NETWORK_ENTRY:
+		currdriverstate = NO_NETWORK_ENTRY;
+		BcmGetGPIOPinInfo(ad, &GPIO_num, &dummyGPIONum,
+				  &uiLedIndex, &dummyGPIONum, currdriverstate);
+		if (GPIO_num != DISABLE_GPIO_NUM)
+			TURN_ON_LED(ad, 1 << GPIO_num, uiLedIndex);
+		break;
+	case NORMAL_OPERATION:
+		{
+			UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
+			UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
+			UCHAR uiLEDTx = 0;
+			UCHAR uiLEDRx = 0;
+
+			currdriverstate = NORMAL_OPERATION;
+			ad->LEDInfo.bIdle_led_off = false;
+
+			BcmGetGPIOPinInfo(ad, &GPIO_num_tx, &GPIO_num_rx,
+					  &uiLEDTx, &uiLEDRx, currdriverstate);
+			if ((GPIO_num_tx == DISABLE_GPIO_NUM) &&
+					(GPIO_num_rx == DISABLE_GPIO_NUM)) {
+				GPIO_num = DISABLE_GPIO_NUM;
+			} else {
+				/*
+				 * If single LED is selected, use same
+				 * for both Tx and Rx
+				 */
+				if (GPIO_num_tx == DISABLE_GPIO_NUM) {
+					GPIO_num_tx = GPIO_num_rx;
+					uiLEDTx = uiLEDRx;
+				} else if (GPIO_num_rx == DISABLE_GPIO_NUM) {
+					GPIO_num_rx = GPIO_num_tx;
+					uiLEDRx = uiLEDTx;
+				}
+				/*
+				 * Blink the LED in proportionate
+				 * to Tx and Rx transmissions.
+				 */
+				LED_Proportional_Blink(ad,
+						       GPIO_num_tx, uiLEDTx,
+						       GPIO_num_rx, uiLEDRx,
+						       currdriverstate);
+			}
+		}
+		break;
+	case LOWPOWER_MODE_ENTER:
+		currdriverstate = LOWPOWER_MODE_ENTER;
+		if (DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING ==
+				ad->ulPowerSaveMode) {
+			/* Turn OFF all the LED */
+			uiResetValue = 0;
+			for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+				if (ad->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
+					TURN_OFF_LED(ad,
+						     (1 << ad->LEDInfo.LEDState[uiIndex].GPIO_Num),
+						     uiIndex);
+			}
+
+		}
+		/* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
+		ad->LEDInfo.bLedInitDone = false;
+		ad->LEDInfo.bIdle_led_off = TRUE;
+		wake_up(&ad->LEDInfo.idleModeSyncEvent);
+		GPIO_num = DISABLE_GPIO_NUM;
+		break;
+	case IDLEMODE_CONTINUE:
+		currdriverstate = IDLEMODE_CONTINUE;
+		GPIO_num = DISABLE_GPIO_NUM;
+		break;
+	case IDLEMODE_EXIT:
+		break;
+	case DRIVER_HALT:
+		currdriverstate = DRIVER_HALT;
+		GPIO_num = DISABLE_GPIO_NUM;
+		for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+			if (ad->LEDInfo.LEDState[uiIndex].GPIO_Num !=
+					DISABLE_GPIO_NUM)
+				TURN_OFF_LED(ad,
+					     (1 << ad->LEDInfo.LEDState[uiIndex].GPIO_Num),
+					     uiIndex);
+		}
+		/* ad->DriverState = DRIVER_INIT; */
+		break;
+	case LED_THREAD_INACTIVE:
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+				DBG_LVL_ALL, "InActivating LED thread...");
+		currdriverstate = LED_THREAD_INACTIVE;
+		ad->LEDInfo.led_thread_running =
+				BCM_LED_THREAD_RUNNING_INACTIVELY;
+		ad->LEDInfo.bLedInitDone = false;
+		/* disable ALL LED */
+		for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+			if (ad->LEDInfo.LEDState[uiIndex].GPIO_Num !=
+					DISABLE_GPIO_NUM)
+				TURN_OFF_LED(ad,
+					     (1 << ad->LEDInfo.LEDState[uiIndex].GPIO_Num),
+					     uiIndex);
+		}
+		break;
+	case LED_THREAD_ACTIVE:
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+				DBG_LVL_ALL, "Activating LED thread again...");
+		if (ad->LinkUpStatus == false)
+			ad->DriverState = NO_NETWORK_ENTRY;
+		else
+			ad->DriverState = NORMAL_OPERATION;
+
+		ad->LEDInfo.led_thread_running =
+				BCM_LED_THREAD_RUNNING_ACTIVELY;
+		break;
+		/* return; */
+	default:
+		break;
+	}
+}
+
 static VOID LEDControlThread(struct bcm_mini_adapter *Adapter)
 {
 	UINT uiIndex = 0;
@@ -691,168 +867,28 @@ static VOID LEDControlThread(struct bcm_
 				"Led thread got signal to exit..hence exiting");
 			Adapter->LEDInfo.led_thread_running =
 						BCM_LED_THREAD_DISABLED;
-			TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
+			TURN_OFF_LED(Adapter, 1 << GPIO_num, uiLedIndex);
 			return; /* STATUS_FAILURE; */
 		}
 
 		if (GPIO_num != DISABLE_GPIO_NUM)
-			TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
+			TURN_OFF_LED(Adapter, 1 << GPIO_num, uiLedIndex);
 
 		if (Adapter->LEDInfo.bLedInitDone == false) {
 			LedGpioInit(Adapter);
 			Adapter->LEDInfo.bLedInitDone = TRUE;
 		}
 
-		switch (Adapter->DriverState) {
-		case DRIVER_INIT:
-			currdriverstate = DRIVER_INIT;
-					/* Adapter->DriverState; */
-			BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
-				&uiLedIndex, &dummyIndex, currdriverstate);
-
-			if (GPIO_num != DISABLE_GPIO_NUM)
-				TURN_ON_LED(1 << GPIO_num, uiLedIndex);
-
-			break;
-		case FW_DOWNLOAD:
-			/*
-			 * BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
-			 *	LED_DUMP_INFO, DBG_LVL_ALL,
-			 *	"LED Thread: FW_DN_DONE called\n");
-			 */
-			currdriverstate = FW_DOWNLOAD;
-			BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
-				&uiLedIndex, &dummyIndex, currdriverstate);
-
-			if (GPIO_num != DISABLE_GPIO_NUM) {
-				timeout = 50;
-				LED_Blink(Adapter, 1 << GPIO_num, uiLedIndex,
-					timeout, -1, currdriverstate);
-			}
-			break;
-		case FW_DOWNLOAD_DONE:
-			currdriverstate = FW_DOWNLOAD_DONE;
-			BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
-				&uiLedIndex, &dummyIndex, currdriverstate);
-			if (GPIO_num != DISABLE_GPIO_NUM)
-				TURN_ON_LED(1 << GPIO_num, uiLedIndex);
-			break;
-
-		case SHUTDOWN_EXIT:
-			/*
-			 * no break, continue to NO_NETWORK_ENTRY
-			 * state as well.
-			 */
-		case NO_NETWORK_ENTRY:
-			currdriverstate = NO_NETWORK_ENTRY;
-			BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
-				&uiLedIndex, &dummyGPIONum, currdriverstate);
-			if (GPIO_num != DISABLE_GPIO_NUM)
-				TURN_ON_LED(1 << GPIO_num, uiLedIndex);
-			break;
-		case NORMAL_OPERATION:
-			{
-				UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
-				UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
-				UCHAR uiLEDTx = 0;
-				UCHAR uiLEDRx = 0;
-				currdriverstate = NORMAL_OPERATION;
-				Adapter->LEDInfo.bIdle_led_off = false;
-
-				BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx,
-					&GPIO_num_rx, &uiLEDTx, &uiLEDRx,
-					currdriverstate);
-				if ((GPIO_num_tx == DISABLE_GPIO_NUM) &&
-						(GPIO_num_rx ==
-						 DISABLE_GPIO_NUM)) {
-					GPIO_num = DISABLE_GPIO_NUM;
-				} else {
-					/*
-					 * If single LED is selected, use same
-					 * for both Tx and Rx
-					 */
-					if (GPIO_num_tx == DISABLE_GPIO_NUM) {
-						GPIO_num_tx = GPIO_num_rx;
-						uiLEDTx = uiLEDRx;
-					} else if (GPIO_num_rx ==
-							DISABLE_GPIO_NUM) {
-						GPIO_num_rx = GPIO_num_tx;
-						uiLEDRx = uiLEDTx;
-					}
-					/*
-					 * Blink the LED in proportionate
-					 * to Tx and Rx transmissions.
-					 */
-					LED_Proportional_Blink(Adapter,
-						GPIO_num_tx, uiLEDTx,
-						GPIO_num_rx, uiLEDRx,
-						currdriverstate);
-				}
-			}
-			break;
-		case LOWPOWER_MODE_ENTER:
-			currdriverstate = LOWPOWER_MODE_ENTER;
-			if (DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING ==
-					Adapter->ulPowerSaveMode) {
-				/* Turn OFF all the LED */
-				uiResetValue = 0;
-				for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
-					if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
-						TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
-				}
-
-			}
-			/* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
-			Adapter->LEDInfo.bLedInitDone = false;
-			Adapter->LEDInfo.bIdle_led_off = TRUE;
-			wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
-			GPIO_num = DISABLE_GPIO_NUM;
-			break;
-		case IDLEMODE_CONTINUE:
-			currdriverstate = IDLEMODE_CONTINUE;
-			GPIO_num = DISABLE_GPIO_NUM;
-			break;
-		case IDLEMODE_EXIT:
-			break;
-		case DRIVER_HALT:
-			currdriverstate = DRIVER_HALT;
-			GPIO_num = DISABLE_GPIO_NUM;
-			for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
-				if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
-						!= DISABLE_GPIO_NUM)
-					TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
-			}
-			/* Adapter->DriverState = DRIVER_INIT; */
-			break;
-		case LED_THREAD_INACTIVE:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-				DBG_LVL_ALL, "InActivating LED thread...");
-			currdriverstate = LED_THREAD_INACTIVE;
-			Adapter->LEDInfo.led_thread_running =
-					BCM_LED_THREAD_RUNNING_INACTIVELY;
-			Adapter->LEDInfo.bLedInitDone = false;
-			/* disable ALL LED */
-			for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
-				if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
-						!= DISABLE_GPIO_NUM)
-					TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
-			}
-			break;
-		case LED_THREAD_ACTIVE:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-				DBG_LVL_ALL, "Activating LED thread again...");
-			if (Adapter->LinkUpStatus == false)
-				Adapter->DriverState = NO_NETWORK_ENTRY;
-			else
-				Adapter->DriverState = NORMAL_OPERATION;
-
-			Adapter->LEDInfo.led_thread_running =
-					BCM_LED_THREAD_RUNNING_ACTIVELY;
-			break;
-			/* return; */
-		default:
-			break;
-		}
+		handle_adapter_driver_state(Adapter,
+					    currdriverstate,
+					    GPIO_num,
+					    dummyGPIONum,
+					    uiLedIndex,
+					    dummyIndex,
+					    timeout,
+					    uiResetValue,
+					    uiIndex
+					    );
 	}
 	Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
 }
@@ -878,8 +914,8 @@ int InitLedSettings(struct bcm_mini_adap
 	Status = ReadConfigFileStructure(Adapter, &bEnableThread);
 	if (STATUS_SUCCESS != Status) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-			DBG_LVL_ALL,
-			"LED Thread: FAILED in ReadConfigFileStructure\n");
+				DBG_LVL_ALL,
+				"LED Thread: FAILED in ReadConfigFileStructure\n");
 		return Status;
 	}
 
@@ -902,11 +938,11 @@ int InitLedSettings(struct bcm_mini_adap
 		Adapter->LEDInfo.bIdle_led_off = false;
 		Adapter->LEDInfo.led_cntrl_threadid =
 			kthread_run((int (*)(void *)) LEDControlThread,
-			Adapter, "led_control_thread");
+				    Adapter, "led_control_thread");
 		if (IS_ERR(Adapter->LEDInfo.led_cntrl_threadid)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
-				DBG_LVL_ALL,
-				"Not able to spawn Kernel Thread\n");
+					DBG_LVL_ALL,
+					"Not able to spawn Kernel Thread\n");
 			Adapter->LEDInfo.led_thread_running =
 				BCM_LED_THREAD_DISABLED;
 			return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/led_control.h linux-libre-3.17-rc7-gnu/drivers/staging/bcm/led_control.h
--- linux-libre-3.16-gnu/drivers/staging/bcm/led_control.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/led_control.h	2014-09-28 17:29:07.000000000 -0400
@@ -17,18 +17,18 @@
 #define EVENT_SIGNALED				1
 #define MAX_FILE_NAME_BUFFER_SIZE		100
 
-#define TURN_ON_LED(GPIO, index) do {					\
+#define TURN_ON_LED(ad, GPIO, index) do {					\
 		unsigned int gpio_val = GPIO;					\
-		(Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ?	\
-			wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)) : \
-			wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \
+		(ad->LEDInfo.LEDState[index].BitPolarity == 1) ?	\
+			wrmaltWithLock(ad, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)) : \
+			wrmaltWithLock(ad, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \
 	} while (0)
 
-#define TURN_OFF_LED(GPIO, index)  do {					\
+#define TURN_OFF_LED(ad, GPIO, index)  do {					\
 		unsigned int gpio_val = GPIO;					\
-		(Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ?	\
-			wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)) : \
-			wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)); \
+		(ad->LEDInfo.LEDState[index].BitPolarity == 1) ?	\
+			wrmaltWithLock(ad, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)) : \
+			wrmaltWithLock(ad, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)); \
 	} while (0)
 
 enum bcm_led_colors {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Misc.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Misc.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/Misc.c	2014-08-07 04:58:12.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Misc.c	2014-09-28 21:40:42.000000000 -0400
@@ -21,13 +21,13 @@ static void default_wimax_protocol_initi
 	Adapter->LinkStatus = SYNC_UP_REQUEST;
 	Adapter->TransferMode = IP_PACKET_ONLY_MODE;
 	Adapter->usBestEffortQueueIndex = -1;
-	return;
 }
 
 int InitAdapter(struct bcm_mini_adapter *psAdapter)
 {
 	int i = 0;
 	int Status = STATUS_SUCCESS;
+
 	BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
 
 	if (psAdapter == NULL) {
@@ -96,6 +96,7 @@ int InitAdapter(struct bcm_mini_adapter
 void AdapterFree(struct bcm_mini_adapter *Adapter)
 {
 	int count;
+
 	beceem_protocol_reset(Adapter);
 	vendorextnExit(Adapter);
 
@@ -158,6 +159,7 @@ static int create_worker_threads(struct
 static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path)
 {
 	struct file *flp = /*(DEBLOBBED)*/(void*)-ENOENT;
+
 	if (IS_ERR(flp)) {
 		pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp));
 		flp = NULL;
@@ -281,7 +283,7 @@ int CopyBufferToControlPacket(struct bcm
 			pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
 
 			if ((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD))	{
-				if ((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) {
+				if (pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
 					Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN; /* LINK DOWN sent in Idle Mode */
 				} else {
@@ -402,6 +404,7 @@ int CopyBufferToControlPacket(struct bcm
 void LinkMessage(struct bcm_mini_adapter *Adapter)
 {
 	struct bcm_link_request *pstLinkRequest = NULL;
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
 	if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) {
 		pstLinkRequest = kzalloc(sizeof(struct bcm_link_request), GFP_ATOMIC);
@@ -456,7 +459,6 @@ void StatisticsResponse(struct bcm_mini_
 	Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (unsigned int)Adapter->StatisticsPointer);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
-	return;
 }
 
 /**********************************************************************
@@ -534,13 +536,13 @@ void LinkControlResponseMessage(struct b
 		}
 	} else if (SET_MAC_ADDRESS_RESPONSE == *pucBuffer) {
 		PUCHAR puMacAddr = (pucBuffer + 1);
+
 		Adapter->LinkStatus = SYNC_UP_REQUEST;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
 		LinkMessage(Adapter);
 		memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====", __func__);
-	return;
 }
 
 void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
@@ -548,6 +550,7 @@ void SendIdleModeResponse(struct bcm_min
 	int status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
 	struct timeval tv;
 	struct bcm_link_request stIdleResponse = {{0} };
+
 	memset(&tv, 0, sizeof(tv));
 	stIdleResponse.Leader.Status = IDLE_MESSAGE;
 	stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH;
@@ -624,7 +627,7 @@ void SendIdleModeResponse(struct bcm_min
 	}
 
 	status = CopyBufferToControlPacket(Adapter, &stIdleResponse);
-	if ((status != STATUS_SUCCESS)) {
+	if (status != STATUS_SUCCESS) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
 		Adapter->bPreparingForLowPowerMode = false;
 		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
@@ -770,8 +773,6 @@ void DumpPackInfo(struct bcm_mini_adapte
 
 	for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aTxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aTxPktSizeHist[uiLoopIndex]);
-
-	return;
 }
 
 int reset_card_proc(struct bcm_mini_adapter *ps_adapter)
@@ -1153,7 +1154,7 @@ static void doPowerAutoCorrection(struct
 	reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
 	psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
 
-	if (reporting_mode == TRUE) {
+	if (reporting_mode) {
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable");
 		psAdapter->bDoSuspend = false;
 	}
@@ -1224,6 +1225,7 @@ int rdmalt(struct bcm_mini_adapter *Adap
 int wrmWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
 	int status = STATUS_SUCCESS;
+
 	down(&Adapter->rdmwrmsync);
 
 	if ((Adapter->IdleMode == TRUE) ||
@@ -1282,6 +1284,7 @@ exit:
 static void HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
 {
 	int clear_abort_pattern = 0, Status = 0;
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
 	/* target has woken up From Shut Down */
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
@@ -1385,7 +1388,7 @@ static void SendShutModeResponse(struct
 	}
 
 	Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse);
-	if ((Status != STATUS_SUCCESS)) {
+	if (Status != STATUS_SUCCESS) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n");
 		Adapter->bPreparingForLowPowerMode = false;
 		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
@@ -1418,7 +1421,6 @@ static void HandleShutDownModeRequest(st
 	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
-	return;
 }
 
 void ResetCounters(struct bcm_mini_adapter *Adapter)
@@ -1440,6 +1442,7 @@ void ResetCounters(struct bcm_mini_adapt
 struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP)
 {
 	unsigned int uiIndex = 0;
+
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
 			(Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1454,6 +1457,7 @@ struct bcm_classifier_rule *GetFragIPCls
 void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo)
 {
 	unsigned int uiIndex = 0;
+
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
 			memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(struct bcm_fragmented_packet_info));
@@ -1465,6 +1469,7 @@ void AddFragIPClsEntry(struct bcm_mini_a
 void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp)
 {
 	unsigned int uiIndex = 0;
+
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
 			(Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1528,6 +1533,7 @@ void flush_queue(struct bcm_mini_adapter
 {
 	struct sk_buff *PacketToDrop = NULL;
 	struct net_device_stats *netstats = &Adapter->dev->stats;
+
 	spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
 
 	while (Adapter->PackInfo[iQIndex].FirstTxQueue && atomic_read(&Adapter->TotalPacketCount)) {
@@ -1551,6 +1557,7 @@ void flush_queue(struct bcm_mini_adapter
 static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter)
 {
 	int i;
+
 	if (netif_msg_link(Adapter))
 		pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/nvm.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/nvm.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/nvm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/nvm.c	2014-09-28 17:29:07.000000000 -0400
@@ -2,35 +2,52 @@
 
 #define DWORD unsigned int
 
-static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset);
+static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter,
+			   unsigned int offset);
 static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter);
 static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter);
 static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter);
 static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter);
-static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize);
+static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter,
+					  unsigned int FlashSectorSizeSig,
+					  unsigned int FlashSectorSize);
 
 static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter);
 static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter);
 static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter);
 static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter);
 
-static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter,
+				     enum bcm_flash2x_section_val eFlash2xSectionVal);
 
-static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset);
-static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section);
-static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
+static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter,
+				unsigned int uiOffset);
+static int IsSectionWritable(struct bcm_mini_adapter *Adapter,
+			     enum bcm_flash2x_section_val Section);
+static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter,
+				      enum bcm_flash2x_section_val section);
 
-static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
-static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
-static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
-static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
+static int ReadDSDPriority(struct bcm_mini_adapter *Adapter,
+			   enum bcm_flash2x_section_val dsd);
+static int ReadDSDSignature(struct bcm_mini_adapter *Adapter,
+			    enum bcm_flash2x_section_val dsd);
+static int ReadISOPriority(struct bcm_mini_adapter *Adapter,
+			   enum bcm_flash2x_section_val iso);
+static int ReadISOSignature(struct bcm_mini_adapter *Adapter,
+			    enum bcm_flash2x_section_val iso);
 
-static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
-static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
-static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiSectAlignAddr);
-static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff,
-					enum bcm_flash2x_section_val eFlash2xSectionVal,
-					unsigned int uiOffset, unsigned int uiNumBytes);
+static int CorruptDSDSig(struct bcm_mini_adapter *Adapter,
+			 enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int CorruptISOSig(struct bcm_mini_adapter *Adapter,
+			 enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter,
+			       PUCHAR pBuff,
+			       unsigned int uiSectAlignAddr);
+static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
+					  PUINT pBuff,
+					  enum bcm_flash2x_section_val eFlash2xSectionVal,
+					  unsigned int uiOffset,
+					  unsigned int uiNumBytes);
 static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter);
 static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter);
 
@@ -361,6 +378,7 @@ int BeceemEEPROMBulkRead(struct bcm_mini
 		} else {
 			/* Handle the reads less than 4 bytes... */
 			PUCHAR pCharBuff = (PUCHAR)pBuffer;
+
 			pCharBuff += uiIndex;
 			if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) {
 				memcpy(pCharBuff, &uiData[0], uiBytesRemaining); /* copy only bytes requested. */
@@ -914,6 +932,7 @@ static int flashWriteStatus(struct bcm_m
 static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus)
 {
 	unsigned int value;
+
 	value = (FLASH_CMD_WRITE_ENABLE << 24);
 	wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
 
@@ -1014,6 +1033,45 @@ static ULONG BcmFlashUnProtectBlock(stru
 	return ulStatus;
 }
 
+static int bulk_read_complete_sector(struct bcm_mini_adapter *ad,
+				     UCHAR read_bk[],
+				     PCHAR tmpbuff,
+				     unsigned int offset,
+				     unsigned int partoff)
+{
+	unsigned int i;
+	int j;
+	int bulk_read_stat;
+	FP_FLASH_WRITE_STATUS writef =
+		ad->fpFlashWriteWithStatusCheck;
+
+	for (i = 0; i < ad->uiSectorSize; i += MAX_RW_SIZE) {
+		bulk_read_stat = BeceemFlashBulkRead(ad,
+						     (PUINT)read_bk,
+						     offset + i,
+						     MAX_RW_SIZE);
+
+		if (bulk_read_stat != STATUS_SUCCESS)
+			continue;
+
+		if (ad->ulFlashWriteSize == 1) {
+			for (j = 0; j < 16; j++) {
+				if ((read_bk[j] != tmpbuff[i + j]) &&
+				    (STATUS_SUCCESS != (*writef)(ad, partoff + i + j, &tmpbuff[i + j]))) {
+					return STATUS_FAILURE;
+				}
+			}
+		} else {
+			if ((memcmp(read_bk, &tmpbuff[i], MAX_RW_SIZE)) &&
+			    (STATUS_SUCCESS != (*writef)(ad, partoff + i, &tmpbuff[i]))) {
+				return STATUS_FAILURE;
+			}
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
 /*
  * Procedure:	BeceemFlashBulkWrite
  *
@@ -1150,28 +1208,16 @@ static int BeceemFlashBulkWrite(struct b
 		/* do_gettimeofday(&tw);
 		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write  to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000));
 		 */
-		for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) {
-			if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) {
-				if (Adapter->ulFlashWriteSize == 1) {
-					unsigned int uiReadIndex = 0;
-					for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) {
-						if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) {
-							if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) {
-								Status = STATUS_FAILURE;
-								goto BeceemFlashBulkWrite_EXIT;
-							}
-						}
-					}
-				} else {
-					if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) {
-						if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) {
-							Status = STATUS_FAILURE;
-							goto BeceemFlashBulkWrite_EXIT;
-						}
-					}
-				}
-			}
+
+		if (STATUS_FAILURE == bulk_read_complete_sector(Adapter,
+								ucReadBk,
+								pTempBuff,
+								uiOffsetFromSectStart,
+								uiPartOffset)) {
+			Status = STATUS_FAILURE;
+			goto BeceemFlashBulkWrite_EXIT;
 		}
+
 		/* do_gettimeofday(&twv);
 		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write  to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000));
 		 */
@@ -1868,6 +1914,7 @@ int BeceemNVMWrite(struct bcm_mini_adapt
 			if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) {
 				ULONG ulBytesTobeSkipped = 0;
 				PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */
+
 				uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset);
 				ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset);
 				uiOffset += (EEPROM_CALPARAM_START - uiOffset);
@@ -2455,6 +2502,7 @@ static int BcmGetFlashCSInfo(struct bcm_
 	#endif
 
 	unsigned int uiFlashLayoutMajorVersion;
+
 	Adapter->uiFlashLayoutMinorVersion = 0;
 	Adapter->uiFlashLayoutMajorVersion = 0;
 	Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR;
@@ -3321,7 +3369,7 @@ int BcmSetActiveSection(struct bcm_mini_
 
 			SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1;
 
-			if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) {
+			if ((SectImagePriority == 0) && IsSectionWritable(Adapter, HighestPriISO)) {
 				/* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF.
 				 * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO
 				 * by user
@@ -3381,7 +3429,7 @@ int BcmSetActiveSection(struct bcm_mini_
 			}
 
 			SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1;
-			if (SectImagePriority <= 0) {
+			if (SectImagePriority == 0) {
 				/* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF.
 				 * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD
 				 * by user
@@ -3487,11 +3535,10 @@ int BcmCopyISO(struct bcm_mini_adapter *
 		return STATUS_FAILURE;
 	}
 
-	Status = BcmFlash2xBulkRead(Adapter,
-				&ISOLength,
-				sCopySectStrut.SrcSection,
-				0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageSize),
-				4);
+	Status = BcmFlash2xBulkRead(Adapter, &ISOLength,
+				    sCopySectStrut.SrcSection,
+				    0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageSize),
+				    4);
 	if (Status) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n");
 		return Status;
@@ -3591,7 +3638,7 @@ int BcmCopyISO(struct bcm_mini_adapter *
 
 			if (IsThisHeaderSector == TRUE) {
 				/* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
-				memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
+				memcpy(SigBuff, Buff + sigOffset, sizeof(SigBuff));
 
 				for (i = 0; i < MAX_RW_SIZE; i++)
 					*(Buff + sigOffset + i) = 0xFF;
@@ -3704,7 +3751,7 @@ int BcmCopyISO(struct bcm_mini_adapter *
 
 			if (IsThisHeaderSector == TRUE) {
 				/* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
-				memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
+				memcpy(SigBuff, Buff + sigOffset, sizeof(SigBuff));
 
 				for (i = 0; i < MAX_RW_SIZE; i++)
 					*(Buff + sigOffset + i) = 0xFF;
@@ -4319,6 +4366,7 @@ static int ReadISOSignature(struct bcm_m
 static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
 {
 	unsigned int ISOPri = STATUS_FAILURE;
+
 	if (IsSectionWritable(Adapter, iso)) {
 		if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) {
 			BcmFlash2xBulkRead(Adapter,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/PHSModule.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/PHSModule.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/PHSModule.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/PHSModule.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,46 +1,80 @@
 #include "headers.h"
 
-static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,
+					    B_UINT16 uiClsId,
+					    struct bcm_phs_table *psServiceFlowTable,
+					    struct bcm_phs_rule *psPhsRule,
+					    B_UINT8 u8AssociatedPHSI);
 
-static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid, B_UINT16  uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,
+					    B_UINT16  uiClsId,
+					    struct bcm_phs_entry *pstServiceFlowEntry,
+					    struct bcm_phs_rule *psPhsRule,
+					    B_UINT8 u8AssociatedPHSI);
 
-static UINT CreateClassifierPHSRule(B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext, B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,
+				    struct bcm_phs_classifier_table *psaClassifiertable,
+				    struct bcm_phs_rule *psPhsRule,
+				    enum bcm_phs_classifier_context eClsContext,
+				    B_UINT8 u8AssociatedPHSI);
 
-static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,
+				    struct bcm_phs_classifier_entry *pstClassifierEntry,
+				    struct bcm_phs_classifier_table *psaClassifiertable,
+				    struct bcm_phs_rule *psPhsRule,
+				    B_UINT8 u8AssociatedPHSI);
 
-static bool ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
+static bool ValidatePHSRuleComplete(const struct bcm_phs_rule *psPhsRule);
 
-static bool DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
+static bool DerefPhsRule(B_UINT16 uiClsId,
+			 struct bcm_phs_classifier_table *psaClassifiertable,
+			 struct bcm_phs_rule *pstPhsRule);
 
-static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
+static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,
+			       B_UINT32 uiClsid,
+			       enum bcm_phs_classifier_context eClsContext,
+			       struct bcm_phs_classifier_entry **ppstClassifierEntry);
 
-static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
+static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,
+			    B_UINT32 uiPHSI,
+			    enum bcm_phs_classifier_context eClsContext,
+			    struct bcm_phs_rule **ppstPhsRule);
 
 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
 
-static int phs_compress(struct bcm_phs_rule *phs_members, unsigned char *in_buf,
-			unsigned char *out_buf, unsigned int *header_size, UINT *new_header_size);
+static int phs_compress(struct bcm_phs_rule *phs_members,
+			unsigned char *in_buf,
+			unsigned char *out_buf,
+			unsigned int *header_size,
+			UINT *new_header_size);
 
-static int verify_suppress_phsf(unsigned char *in_buffer, unsigned char *out_buffer,
-				unsigned char *phsf, unsigned char *phsm, unsigned int phss, unsigned int phsv, UINT *new_header_size);
+static int verify_suppress_phsf(unsigned char *in_buffer,
+				unsigned char *out_buffer,
+				unsigned char *phsf,
+				unsigned char *phsm,
+				unsigned int phss,
+				unsigned int phsv,
+				UINT *new_header_size);
 
-static int phs_decompress(unsigned char *in_buf, unsigned char *out_buf,
-			struct bcm_phs_rule *phs_rules, UINT *header_size);
+static int phs_decompress(unsigned char *in_buf,
+			  unsigned char *out_buf,
+			  struct bcm_phs_rule *phs_rules,
+			  UINT *header_size);
 
 static ULONG PhsCompress(void *pvContext,
-			B_UINT16 uiVcid,
-			B_UINT16 uiClsId,
-			void *pvInputBuffer,
-			void *pvOutputBuffer,
-			UINT *pOldHeaderSize,
-			UINT *pNewHeaderSize);
+			 B_UINT16 uiVcid,
+			 B_UINT16 uiClsId,
+			 void *pvInputBuffer,
+			 void *pvOutputBuffer,
+			 UINT *pOldHeaderSize,
+			 UINT *pNewHeaderSize);
 
 static ULONG PhsDeCompress(void *pvContext,
-			B_UINT16 uiVcid,
-			void *pvInputBuffer,
-			void *pvOutputBuffer,
-			UINT *pInHeaderSize,
-			UINT *pOutHeaderSize);
+			   B_UINT16 uiVcid,
+			   void *pvInputBuffer,
+			   void *pvOutputBuffer,
+			   UINT *pInHeaderSize,
+			   UINT *pOutHeaderSize);
 
 #define IN
 #define OUT
@@ -76,9 +110,11 @@ int PHSTransmit(struct bcm_mini_adapter
 	UINT unPhsOldHdrSize = 0;
 	UINT unPHSNewPktHeaderLen = 0;
 	/* Pointer to PHS IN Hdr Buffer */
-	PUCHAR pucPHSPktHdrInBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
+	PUCHAR pucPHSPktHdrInBuf =
+		Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
 	/* Pointer to PHS OUT Hdr Buffer */
-	PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
+	PUCHAR pucPHSPktHdrOutBuf =
+		Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
 	UINT usPacketType;
 	UINT BytesToRemove = 0;
 	bool bPHSI = 0;
@@ -87,7 +123,8 @@ int PHSTransmit(struct bcm_mini_adapter
 	struct sk_buff *newPacket = NULL;
 	struct sk_buff *Packet = *pPacket;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+			"In PHSTransmit");
 
 	if (!bEthCSSupport)
 		BytesToRemove = ETH_HLEN;
@@ -109,23 +146,31 @@ int PHSTransmit(struct bcm_mini_adapter
 		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
 
 		/*
-		 * Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
-		 * Suppress only if IP Header and PHS Enabled For the Service Flow
+		 * Step 2 Suppress Header using PHS and fill into intermediate
+		 * ucaPHSPktHdrOutBuf.
+		 * Suppress only if IP Header and PHS Enabled For the
+		 * Service Flow
 		 */
 		if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
 				(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
 			(bHeaderSuppressionEnabled)) {
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nTrying to PHS Compress Using Classifier rule 0x%X", uiClassifierRuleID);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
+					DBG_LVL_ALL,
+					"\nTrying to PHS Compress Using Classifier rule 0x%X",
+					uiClassifierRuleID);
 			unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
 			ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
-						Vcid,
-						uiClassifierRuleID,
-						pucPHSPktHdrInBuf,
-						pucPHSPktHdrOutBuf,
-						&unPhsOldHdrSize,
-						&unPHSNewPktHeaderLen);
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nPHS Old header Size : %d New Header Size  %d\n", unPhsOldHdrSize, unPHSNewPktHeaderLen);
+						  Vcid,
+						  uiClassifierRuleID,
+						  pucPHSPktHdrInBuf,
+						  pucPHSPktHdrOutBuf,
+						  &unPhsOldHdrSize,
+						  &unPHSNewPktHeaderLen);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
+					DBG_LVL_ALL,
+					"\nPHS Old header Size : %d New Header Size  %d\n",
+					unPhsOldHdrSize, unPHSNewPktHeaderLen);
 
 			if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
 
@@ -137,32 +182,45 @@ int PHSTransmit(struct bcm_mini_adapter
 
 			if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
 
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "PHS Sending packet Compressed");
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+						PHS_SEND, DBG_LVL_ALL,
+						"PHS Sending packet Compressed");
 
 				if (skb_cloned(Packet)) {
-					newPacket = skb_copy(Packet, GFP_ATOMIC);
+					newPacket =
+						skb_copy(Packet, GFP_ATOMIC);
 
 					if (newPacket == NULL)
 						return STATUS_FAILURE;
 
 					dev_kfree_skb(Packet);
 					*pPacket = Packet = newPacket;
-					pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;
+					pucPHSPktHdrInBuf =
+						Packet->data + BytesToRemove;
 				}
 
-				numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen + PHSI_LEN);
+				numBytesCompressed = unPhsOldHdrSize -
+					(unPHSNewPktHeaderLen + PHSI_LEN);
 
-				memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
-				memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
+				memcpy(pucPHSPktHdrInBuf + numBytesCompressed,
+				       pucPHSPktHdrOutBuf,
+				       unPHSNewPktHeaderLen + PHSI_LEN);
+				memcpy(Packet->data + numBytesCompressed,
+				       Packet->data, BytesToRemove);
 				skb_pull(Packet, numBytesCompressed);
 
 				return STATUS_SUCCESS;
 			} else {
-				/* if one byte headroom is not available, increase it through skb_cow */
+				/* if one byte headroom is not available,
+				 * increase it through skb_cow
+				 */
 				if (!(skb_headroom(Packet) > 0)) {
 
 					if (skb_cow(Packet, 1)) {
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
+						BCM_DEBUG_PRINT(Adapter,
+								DBG_TYPE_PRINTK,
+								0, 0,
+								"SKB Cow Failed\n");
 						return STATUS_FAILURE;
 					}
 				}
@@ -179,22 +237,25 @@ int PHSTransmit(struct bcm_mini_adapter
 		} else {
 
 			if (!bHeaderSuppressionEnabled)
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nHeader Suppression Disabled For SF: No PHS\n");
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+						PHS_SEND, DBG_LVL_ALL,
+						"\nHeader Suppression Disabled For SF: No PHS\n");
 
 			return STATUS_SUCCESS;
 		}
 	}
 
-	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); */
+	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+	 * "PHSTransmit : Dumping data packet After PHS"); */
 	return STATUS_SUCCESS;
 }
 
 int PHSReceive(struct bcm_mini_adapter *Adapter,
-	USHORT usVcid,
-	struct sk_buff *packet,
-	UINT *punPacketLen,
-	UCHAR *pucEthernetHdr,
-	UINT bHeaderSuppressionEnabled)
+	       USHORT usVcid,
+	       struct sk_buff *packet,
+	       UINT *punPacketLen,
+	       UCHAR *pucEthernetHdr,
+	       UINT bHeaderSuppressionEnabled)
 {
 	u32 nStandardPktHdrLen = 0;
 	u32 nTotalsuppressedPktHdrBytes = 0;
@@ -203,7 +264,9 @@ int PHSReceive(struct bcm_mini_adapter *
 	UINT TotalBytesAdded = 0;
 
 	if (!bHeaderSuppressionEnabled) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nPhs Disabled for incoming packet");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
+				DBG_LVL_ALL,
+				"\nPhs Disabled for incoming packet");
 		return ulPhsStatus;
 	}
 
@@ -212,27 +275,31 @@ int PHSReceive(struct bcm_mini_adapter *
 	/* Restore PHS suppressed header */
 	nStandardPktHdrLen = packet->len;
 	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
-				usVcid,
-				pucInBuff,
-				Adapter->ucaPHSPktRestoreBuf,
-				&nTotalsuppressedPktHdrBytes,
-				&nStandardPktHdrLen);
+				    usVcid,
+				    pucInBuff,
+				    Adapter->ucaPHSPktRestoreBuf,
+				    &nTotalsuppressedPktHdrBytes,
+				    &nStandardPktHdrLen);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
+			"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
 			nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
 
 	if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
 		skb_pull(packet, 1);
 		return STATUS_SUCCESS;
 	} else {
-		TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN;
+		TotalBytesAdded = nStandardPktHdrLen -
+			nTotalsuppressedPktHdrBytes - PHSI_LEN;
 
 		if (TotalBytesAdded) {
 			if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
 				skb_push(packet, TotalBytesAdded);
 			else {
 				if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
+					BCM_DEBUG_PRINT(Adapter,
+							DBG_TYPE_PRINTK, 0, 0,
+							"cow failed in receive\n");
 					return STATUS_FAILURE;
 				}
 
@@ -240,7 +307,8 @@ int PHSReceive(struct bcm_mini_adapter *
 			}
 		}
 
-		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
+		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf,
+		       nStandardPktHdrLen);
 	}
 
 	return STATUS_SUCCESS;
@@ -250,46 +318,58 @@ void DumpFullPacket(UCHAR *pBuf, UINT nP
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dumping Data Packet");
-	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, pBuf, nPktLen);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
+			"Dumping Data Packet");
+	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
+			       pBuf, nPktLen);
 }
 
 /*
  * Procedure:   phs_init
  *
- * Description: This routine is responsible for allocating memory for classifier and
- * PHS rules.
+ * Description: This routine is responsible for allocating memory for classifier
+ * and PHS rules.
  *
  * Arguments:
- * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
+ * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules
+ * and PHS Rules , RX, TX buffer etc
  *
  * Returns:
  * TRUE(1)	-If allocation of memory was successful.
  * FALSE	-If allocation of memory fails.
  */
-int phs_init(struct bcm_phs_extension *pPhsdeviceExtension, struct bcm_mini_adapter *Adapter)
+int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,
+	     struct bcm_mini_adapter *Adapter)
 {
 	int i;
 	struct bcm_phs_table *pstServiceFlowTable;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"\nPHS:phs_init function");
 
 	if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
 		return -EINVAL;
 
-	pPhsdeviceExtension->pstServiceFlowPhsRulesTable = kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
+	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
+		kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
 
 	if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL,
+				"\nAllocation ServiceFlowPhsRulesTable failed");
 		return -ENOMEM;
 	}
 
 	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
-		struct bcm_phs_entry sServiceFlow = pstServiceFlowTable->stSFList[i];
-		sServiceFlow.pstClassifierTable = kzalloc(sizeof(struct bcm_phs_classifier_table), GFP_KERNEL);
+		struct bcm_phs_entry sServiceFlow =
+			pstServiceFlowTable->stSFList[i];
+		sServiceFlow.pstClassifierTable =
+			kzalloc(sizeof(struct bcm_phs_classifier_table),
+				GFP_KERNEL);
 		if (!sServiceFlow.pstClassifierTable) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+					DBG_LVL_ALL, "\nAllocation failed");
 			free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 			return -ENOMEM;
@@ -298,22 +378,26 @@ int phs_init(struct bcm_phs_extension *p
 
 	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
 	if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL, "\nAllocation failed");
 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 		return -ENOMEM;
 	}
 
-	pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
+	pPhsdeviceExtension->UnCompressedRxBuffer =
+		kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
 	if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL, "\nAllocation failed");
 		kfree(pPhsdeviceExtension->CompressedTxBuffer);
 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 		return -ENOMEM;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"\n phs_init Successful");
 	return STATUS_SUCCESS;
 }
 
@@ -352,21 +436,24 @@ int PhsCleanup(IN struct bcm_phs_extensi
  * >0 Error.
  */
 ULONG PhsUpdateClassifierRule(IN void *pvContext,
-			IN B_UINT16 uiVcid ,
-			IN B_UINT16 uiClsId   ,
-			IN struct bcm_phs_rule *psPhsRule,
-			IN B_UINT8 u8AssociatedPHSI)
+			      IN B_UINT16 uiVcid ,
+			      IN B_UINT16 uiClsId   ,
+			      IN struct bcm_phs_rule *psPhsRule,
+			      IN B_UINT8 u8AssociatedPHSI)
 {
 	ULONG lStatus = 0;
 	UINT nSFIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension =
+		(struct bcm_phs_extension *)pvContext;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS With Corr2 Changes\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"PHS With Corr2 Changes\n");
 
 	if (pDeviceExtension == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Invalid Device Extension\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL, "Invalid Device Extension\n");
 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
 	}
 
@@ -375,18 +462,22 @@ ULONG PhsUpdateClassifierRule(IN void *p
 
 	/* Retrieve the SFID Entry Index for requested Service Flow */
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-				uiVcid, &pstServiceFlowEntry);
+				       uiVcid, &pstServiceFlowEntry);
 
 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
 		/* This is a new SF. Create a mapping entry for this */
 		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
-							pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
+							  pDeviceExtension->pstServiceFlowPhsRulesTable,
+							  psPhsRule,
+							  u8AssociatedPHSI);
 		return lStatus;
 	}
 
 	/* SF already Exists Add PHS Rule to existing SF */
 	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
-						pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
+						  pstServiceFlowEntry,
+						  psPhsRule,
+						  u8AssociatedPHSI);
 
 	return lStatus;
 }
@@ -407,40 +498,48 @@ ULONG PhsUpdateClassifierRule(IN void *p
  * 0 if successful,
  * >0 Error.
  */
-ULONG PhsDeletePHSRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT8 u8PHSI)
+ULONG PhsDeletePHSRule(IN void *pvContext,
+		       IN B_UINT16 uiVcid,
+		       IN B_UINT8 u8PHSI)
 {
 	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_classifier_entry *curr_entry;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"======>\n");
 
 	if (pDeviceExtension) {
 		/* Retrieve the SFID Entry Index for requested Service Flow */
-		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
+		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+					       uiVcid, &pstServiceFlowEntry);
 
 		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+					DBG_LVL_ALL, "SFID Match Failed\n");
 			return ERR_SF_MATCH_FAIL;
 		}
 
 		pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
 		if (pstClassifierRulesTable) {
 			for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
-				if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
-					if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
+				curr_entry = &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
+				if (curr_entry->bUsed &&
+				    curr_entry->pstPhsRule &&
+				    (curr_entry->pstPhsRule->u8PHSI == u8PHSI)) {
 
-						if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-							pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+					if (curr_entry->pstPhsRule->u8RefCnt)
+						curr_entry->pstPhsRule->u8RefCnt--;
 
-						if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-							kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+					if (0 == curr_entry->pstPhsRule->u8RefCnt)
+						kfree(curr_entry->pstPhsRule);
 
-						memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
-							sizeof(struct bcm_phs_classifier_entry));
-					}
+					memset(curr_entry,
+					       0,
+					       sizeof(struct bcm_phs_classifier_entry));
 				}
 			}
 		}
@@ -464,44 +563,62 @@ ULONG PhsDeletePHSRule(IN void *pvContex
  * 0 if successful,
  * >0 Error.
  */
-ULONG PhsDeleteClassifierRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT16 uiClsId)
+ULONG PhsDeleteClassifierRule(IN void *pvContext,
+			      IN B_UINT16 uiVcid,
+			      IN B_UINT16 uiClsId)
 {
 	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension =
+		(struct bcm_phs_extension *)pvContext;
 
-	if (pDeviceExtension) {
-		/* Retrieve the SFID Entry Index for requested Service Flow */
-		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
-		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
-			return ERR_SF_MATCH_FAIL;
-		}
+	if (!pDeviceExtension)
+		goto out;
 
-		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-						uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
+	/* Retrieve the SFID Entry Index for requested Service Flow */
+	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+				       uiVcid, &pstServiceFlowEntry);
+	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL, "SFID Match Failed\n");
+		return ERR_SF_MATCH_FAIL;
+	}
 
-		if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
-			if (pstClassifierEntry->pstPhsRule) {
-				if (pstClassifierEntry->pstPhsRule->u8RefCnt)
-					pstClassifierEntry->pstPhsRule->u8RefCnt--;
+	nClsidIndex =
+		GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+				   uiClsId,
+				   eActiveClassifierRuleContext,
+				   &pstClassifierEntry);
 
-				if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
-					kfree(pstClassifierEntry->pstPhsRule);
-			}
-			memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
+	if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
+			(!pstClassifierEntry->bUnclassifiedPHSRule)) {
+		if (pstClassifierEntry->pstPhsRule) {
+			if (pstClassifierEntry->pstPhsRule->u8RefCnt)
+				pstClassifierEntry->pstPhsRule->u8RefCnt--;
+
+			if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
+				kfree(pstClassifierEntry->pstPhsRule);
 		}
+		memset(pstClassifierEntry, 0,
+		       sizeof(struct bcm_phs_classifier_entry));
+	}
 
-		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-						uiClsId, eOldClassifierRuleContext, &pstClassifierEntry);
+	nClsidIndex =
+		GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+				   uiClsId,
+				   eOldClassifierRuleContext,
+				   &pstClassifierEntry);
 
-		if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
-			kfree(pstClassifierEntry->pstPhsRule);
-			memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
-		}
+	if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
+			(!pstClassifierEntry->bUnclassifiedPHSRule)) {
+		kfree(pstClassifierEntry->pstPhsRule);
+		memset(pstClassifierEntry, 0,
+		       sizeof(struct bcm_phs_classifier_entry));
 	}
+
+out:
 	return 0;
 }
 
@@ -526,50 +643,65 @@ ULONG PhsDeleteSFRules(IN void *pvContex
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension =
+		(struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_classifier_entry *curr_clsf_entry;
+	struct bcm_phs_classifier_entry *curr_rules_list;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"====>\n");
 
-	if (pDeviceExtension) {
-		/* Retrieve the SFID Entry Index for requested Service Flow */
-		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-					uiVcid, &pstServiceFlowEntry);
-		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
-			return ERR_SF_MATCH_FAIL;
-		}
+	if (!pDeviceExtension)
+		goto out;
 
-		pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
-		if (pstClassifierRulesTable) {
-			for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
-				if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+	/* Retrieve the SFID Entry Index for requested Service Flow */
+	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+				       uiVcid, &pstServiceFlowEntry);
+	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL, "SFID Match Failed\n");
+		return ERR_SF_MATCH_FAIL;
+	}
 
-					if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-						pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+	pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+	if (pstClassifierRulesTable) {
+		for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+			curr_clsf_entry =
+				&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
 
-					if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-						kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+			curr_rules_list =
+				&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex];
 
-					pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule = NULL;
-				}
-				memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
-				if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) {
+			if (curr_clsf_entry->pstPhsRule) {
 
-					if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-						pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+				if (curr_clsf_entry->pstPhsRule->u8RefCnt)
+					curr_clsf_entry->pstPhsRule->u8RefCnt--;
 
-					if (0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
-						kfree(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule);
+				if (0 == curr_clsf_entry->pstPhsRule->u8RefCnt)
+					kfree(curr_clsf_entry->pstPhsRule);
 
-					pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule = NULL;
-				}
-				memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
+				curr_clsf_entry->pstPhsRule = NULL;
+			}
+			memset(curr_clsf_entry, 0,
+			       sizeof(struct bcm_phs_classifier_entry));
+			if (curr_rules_list->pstPhsRule) {
+
+				if (curr_rules_list->pstPhsRule->u8RefCnt)
+					curr_rules_list->pstPhsRule->u8RefCnt--;
+
+				if (0 == curr_rules_list->pstPhsRule->u8RefCnt)
+					kfree(curr_rules_list->pstPhsRule);
+
+				curr_rules_list->pstPhsRule = NULL;
 			}
+			memset(curr_rules_list, 0,
+			       sizeof(struct bcm_phs_classifier_entry));
 		}
-		pstServiceFlowEntry->bUsed = false;
-		pstServiceFlowEntry->uiVcid = 0;
 	}
+	pstServiceFlowEntry->bUsed = false;
+	pstServiceFlowEntry->uiVcid = 0;
 
+out:
 	return 0;
 }
 
@@ -580,13 +712,18 @@ ULONG PhsDeleteSFRules(IN void *pvContex
  *    Exported function to compress the data using PHS.
  *
  * Arguments:
- *	IN void* pvContext - PHS Driver Specific Context.
- *	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header compression applies.
- *	IN UINT  uiClsId   - The Classifier ID to which current packet header compression applies.
- *	IN void *pvInputBuffer - The Input buffer containg packet header data
- *	IN void *pvOutputBuffer - The output buffer returned by this function after PHS
- *	IN UINT *pOldHeaderSize  - The actual size of the header before PHS
- *	IN UINT *pNewHeaderSize - The new size of the header after applying PHS
+ *	IN void* pvContext	    - PHS Driver Specific Context.
+ *	IN B_UINT16 uiVcid	    - The Service Flow ID to which current
+ *				      packet header compression applies.
+ *	IN UINT  uiClsId	    - The Classifier ID to which current packet
+ *				      header compression applies.
+ *	IN void *pvInputBuffer	    - The Input buffer containg packet header
+ *				      data
+ *	IN void *pvOutputBuffer     - The output buffer returned by this
+ *				      function after PHS
+ *	IN UINT *pOldHeaderSize	    - The actual size of the header before PHS
+ *	IN UINT *pNewHeaderSize	    - The new size of the header after applying
+ *				      PHS
  *
  * Return Value:
  *
@@ -594,12 +731,12 @@ ULONG PhsDeleteSFRules(IN void *pvContex
  * >0 Error.
  */
 static ULONG PhsCompress(IN void *pvContext,
-		IN B_UINT16 uiVcid,
-		IN B_UINT16 uiClsId,
-		IN void *pvInputBuffer,
-		OUT void *pvOutputBuffer,
-		OUT UINT *pOldHeaderSize,
-		OUT UINT *pNewHeaderSize)
+			 IN B_UINT16 uiVcid,
+			 IN B_UINT16 uiClsId,
+			 IN void *pvInputBuffer,
+			 OUT void *pvOutputBuffer,
+			 OUT UINT *pOldHeaderSize,
+			 OUT UINT *pNewHeaderSize)
 {
 	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
@@ -607,30 +744,36 @@ static ULONG PhsCompress(IN void *pvCont
 	struct bcm_phs_rule *pstPhsRule = NULL;
 	ULONG lStatus = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension =
+		(struct bcm_phs_extension *)pvContext;
 
 	if (pDeviceExtension == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Invalid Device Extension\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"Invalid Device Extension\n");
 		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Suppressing header\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+			"Suppressing header\n");
 
 	/* Retrieve the SFID Entry Index for requested Service Flow */
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-				uiVcid, &pstServiceFlowEntry);
+				       uiVcid, &pstServiceFlowEntry);
 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "SFID Match Failed\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"SFID Match Failed\n");
 		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
 	nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-					uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
+					 uiClsId, eActiveClassifierRuleContext,
+					 &pstClassifierEntry);
 
 	if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "No PHS Rule Defined For Classifier\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"No PHS Rule Defined For Classifier\n");
 		lStatus =  STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
@@ -638,20 +781,26 @@ static ULONG PhsCompress(IN void *pvCont
 	/* get rule from SF id,Cls ID pair and proceed */
 	pstPhsRule = pstClassifierEntry->pstPhsRule;
 	if (!ValidatePHSRuleComplete(pstPhsRule)) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS Rule Defined For Classifier But Not Complete\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+				"PHS Rule Defined For Classifier But Not Complete\n");
 		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
 	/* Compress Packet */
-	lStatus = phs_compress(pstPhsRule, (PUCHAR)pvInputBuffer,
-			(PUCHAR)pvOutputBuffer, pOldHeaderSize, pNewHeaderSize);
+	lStatus = phs_compress(pstPhsRule,
+			       (PUCHAR)pvInputBuffer,
+			       (PUCHAR)pvOutputBuffer,
+			       pOldHeaderSize,
+			       pNewHeaderSize);
 
 	if (lStatus == STATUS_PHS_COMPRESSED) {
-		pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
+		pstPhsRule->PHSModifiedBytes +=
+			*pOldHeaderSize - *pNewHeaderSize - 1;
 		pstPhsRule->PHSModifiedNumPackets++;
-	} else
+	} else {
 		pstPhsRule->PHSErrorNumPackets++;
+	}
 
 	return lStatus;
 }
@@ -663,11 +812,15 @@ static ULONG PhsCompress(IN void *pvCont
  *    Exported function to restore the packet header in Rx path.
  *
  * Arguments:
- *	IN void* pvContext - PHS Driver Specific Context.
- *	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header restoration applies.
- *	IN  void *pvInputBuffer - The Input buffer containg suppressed packet header data
- *	OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
- *	OUT UINT *pHeaderSize   - The packet header size after restoration is returned in this parameter.
+ *	IN void* pvContext	    - PHS Driver Specific Context.
+ *	IN B_UINT16 uiVcid	    - The Service Flow ID to which current
+ *				      packet header restoration applies.
+ *	IN  void *pvInputBuffer	    - The Input buffer containg suppressed
+ *				      packet header data
+ *	OUT void *pvOutputBuffer    - The output buffer returned by this
+ *				      function after restoration
+ *	OUT UINT *pHeaderSize	    - The packet header size after restoration
+ *				      is returned in this parameter.
  *
  * Return Value:
  *
@@ -675,52 +828,65 @@ static ULONG PhsCompress(IN void *pvCont
  * >0 Error.
  */
 static ULONG PhsDeCompress(IN void *pvContext,
-		IN B_UINT16 uiVcid,
-		IN void *pvInputBuffer,
-		OUT void *pvOutputBuffer,
-		OUT UINT *pInHeaderSize,
-		OUT UINT *pOutHeaderSize)
+			   IN B_UINT16 uiVcid,
+			   IN void *pvInputBuffer,
+			   OUT void *pvOutputBuffer,
+			   OUT UINT *pInHeaderSize,
+			   OUT UINT *pOutHeaderSize)
 {
 	UINT nSFIndex = 0, nPhsRuleIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_rule *pstPhsRule = NULL;
 	UINT phsi;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension =
+		(struct bcm_phs_extension *)pvContext;
 
 	*pInHeaderSize = 0;
 	if (pDeviceExtension == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Invalid Device Extension\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
+				DBG_LVL_ALL, "Invalid Device Extension\n");
 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Restoring header\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
+			"Restoring header\n");
 
 	phsi = *((unsigned char *)(pvInputBuffer));
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "PHSI To Be Used For restore : %x\n", phsi);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
+			"PHSI To Be Used For restore : %x\n", phsi);
 	if (phsi == UNCOMPRESSED_PACKET)
 		return STATUS_PHS_NOCOMPRESSION;
 
 	/* Retrieve the SFID Entry Index for requested Service Flow */
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-				uiVcid, &pstServiceFlowEntry);
+				       uiVcid, &pstServiceFlowEntry);
 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "SFID Match Failed During Lookup\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
+				DBG_LVL_ALL,
+				"SFID Match Failed During Lookup\n");
 		return ERR_SF_MATCH_FAIL;
 	}
 
-	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, phsi,
-					eActiveClassifierRuleContext, &pstPhsRule);
+	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
+					phsi,
+					eActiveClassifierRuleContext,
+					&pstPhsRule);
 	if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
-		/* Phs Rule does not exist in  active rules table. Lets try in the old rules table. */
+		/* Phs Rule does not exist in  active rules table. Lets try
+		 * in the old rules table. */
 		nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
-						phsi, eOldClassifierRuleContext, &pstPhsRule);
+						phsi,
+						eOldClassifierRuleContext,
+						&pstPhsRule);
 		if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
 			return ERR_PHSRULE_MATCH_FAIL;
 	}
 
 	*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
-					(PUCHAR)pvOutputBuffer, pstPhsRule, pOutHeaderSize);
+					(PUCHAR)pvOutputBuffer,
+					pstPhsRule,
+					pOutHeaderSize);
 
 	pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
 
@@ -731,7 +897,8 @@ static ULONG PhsDeCompress(IN void *pvCo
 /*
  * Procedure:   free_phs_serviceflow_rules
  *
- * Description: This routine is responsible for freeing memory allocated for PHS rules.
+ * Description: This routine is responsible for freeing memory allocated for
+ * PHS rules.
  *
  * Arguments:
  * rules	- ptr to S_SERVICEFLOW_TABLE structure.
@@ -743,82 +910,83 @@ static void free_phs_serviceflow_rules(s
 {
 	int i, j;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	struct bcm_phs_classifier_entry *curr_act_rules_list;
+	struct bcm_phs_classifier_entry *curr_old_rules_list;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"=======>\n");
 
-	if (psServiceFlowRulesTable) {
-		for (i = 0; i < MAX_SERVICEFLOWS; i++) {
-			struct bcm_phs_entry stServiceFlowEntry = psServiceFlowRulesTable->stSFList[i];
-			struct bcm_phs_classifier_table *pstClassifierRulesTable = stServiceFlowEntry.pstClassifierTable;
+	if (!psServiceFlowRulesTable)
+		goto out;
 
-			if (pstClassifierRulesTable) {
-				for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
-					if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) {
+	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+		struct bcm_phs_entry stServiceFlowEntry =
+			psServiceFlowRulesTable->stSFList[i];
+		struct bcm_phs_classifier_table *pstClassifierRulesTable =
+			stServiceFlowEntry.pstClassifierTable;
 
-						if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
-							pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt--;
+		if (pstClassifierRulesTable) {
+			for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+				curr_act_rules_list =
+					&pstClassifierRulesTable->stActivePhsRulesList[j];
 
-						if (0 == pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
-							kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
+				curr_old_rules_list =
+					&pstClassifierRulesTable->stOldPhsRulesList[j];
 
-						pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
-					}
+				if (curr_act_rules_list->pstPhsRule) {
 
-					if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) {
+					if (curr_act_rules_list->pstPhsRule->u8RefCnt)
+						curr_act_rules_list->pstPhsRule->u8RefCnt--;
 
-						if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
-							pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt--;
+					if (0 == curr_act_rules_list->pstPhsRule->u8RefCnt)
+						kfree(curr_act_rules_list->pstPhsRule);
 
-						if (0 == pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
-							kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
+					curr_act_rules_list->pstPhsRule = NULL;
+				}
 
-						pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
-					}
+				if (curr_old_rules_list->pstPhsRule) {
+
+					if (curr_old_rules_list->pstPhsRule->u8RefCnt)
+						curr_old_rules_list->pstPhsRule->u8RefCnt--;
+
+					if (0 == curr_old_rules_list->pstPhsRule->u8RefCnt)
+						kfree(curr_old_rules_list->pstPhsRule);
+
+					curr_old_rules_list->pstPhsRule = NULL;
 				}
-				kfree(pstClassifierRulesTable);
-				stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
 			}
+			kfree(pstClassifierRulesTable);
+			stServiceFlowEntry.pstClassifierTable =
+				pstClassifierRulesTable = NULL;
 		}
 	}
 
+out:
+
 	kfree(psServiceFlowRulesTable);
 	psServiceFlowRulesTable = NULL;
 }
 
-static bool ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
+static bool ValidatePHSRuleComplete(IN const struct bcm_phs_rule *psPhsRule)
 {
-	if (psPhsRule) {
-		if (!psPhsRule->u8PHSI) {
-			/* PHSI is not valid */
-			return false;
-		}
-
-		if (!psPhsRule->u8PHSS) {
-			/* PHSS Is Undefined */
-			return false;
-		}
-
-		/* Check if PHSF is defines for the PHS Rule */
-		if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */
-			return false;
-
-		return TRUE;
-	} else
-		return false;
+	return (psPhsRule &&
+		psPhsRule->u8PHSI &&
+		psPhsRule->u8PHSS &&
+		psPhsRule->u8PHSFLength);
 }
 
 UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
-			IN B_UINT16 uiVcid,
-			struct bcm_phs_entry **ppstServiceFlowEntry)
+			 IN B_UINT16 uiVcid,
+			 struct bcm_phs_entry **ppstServiceFlowEntry)
 {
 	int i;
+	struct bcm_phs_entry *curr_sf_list;
 
 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
-		if (psServiceFlowTable->stSFList[i].bUsed) {
-			if (psServiceFlowTable->stSFList[i].uiVcid == uiVcid) {
-				*ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
-				return i;
-			}
+		curr_sf_list = &psServiceFlowTable->stSFList[i];
+		if (curr_sf_list->bUsed && (curr_sf_list->uiVcid == uiVcid)) {
+			*ppstServiceFlowEntry = curr_sf_list;
+			return i;
 		}
 	}
 
@@ -827,8 +995,9 @@ UINT GetServiceFlowEntry(IN struct bcm_p
 }
 
 static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
-			IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
-			OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
+			       IN B_UINT32 uiClsid,
+			       enum bcm_phs_classifier_context eClsContext,
+			       OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
 {
 	int  i;
 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
@@ -836,15 +1005,16 @@ static UINT GetClassifierEntry(IN struct
 	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
 
 		if (eClsContext == eActiveClassifierRuleContext)
-			psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
+			psClassifierRules =
+				&pstClassifierTable->stActivePhsRulesList[i];
 		else
-			psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
+			psClassifierRules =
+				&pstClassifierTable->stOldPhsRulesList[i];
 
-		if (psClassifierRules->bUsed) {
-			if (psClassifierRules->uiClassifierRuleId == uiClsid) {
-				*ppstClassifierEntry = psClassifierRules;
-				return i;
-			}
+		if (psClassifierRules->bUsed &&
+		   (psClassifierRules->uiClassifierRuleId == uiClsid)) {
+			*ppstClassifierEntry = psClassifierRules;
+			return i;
 		}
 	}
 
@@ -853,23 +1023,25 @@ static UINT GetClassifierEntry(IN struct
 }
 
 static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
-			IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
-			OUT struct bcm_phs_rule **ppstPhsRule)
+			    IN B_UINT32 uiPHSI,
+			    enum bcm_phs_classifier_context eClsContext,
+			    OUT struct bcm_phs_rule **ppstPhsRule)
 {
 	int  i;
 	struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
 
 	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
 		if (eClsContext == eActiveClassifierRuleContext)
-			pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
+			pstClassifierRule =
+				&pstClassifierTable->stActivePhsRulesList[i];
 		else
-			pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
+			pstClassifierRule =
+				&pstClassifierTable->stOldPhsRulesList[i];
 
-		if (pstClassifierRule->bUsed) {
-			if (pstClassifierRule->u8PHSI == uiPHSI) {
-				*ppstPhsRule = pstClassifierRule->pstPhsRule;
-				return i;
-			}
+		if (pstClassifierRule->bUsed &&
+		   (pstClassifierRule->u8PHSI == uiPHSI)) {
+			*ppstPhsRule = pstClassifierRule->pstPhsRule;
+			return i;
 		}
 	}
 
@@ -877,19 +1049,22 @@ static UINT GetPhsRuleEntry(IN struct bc
 	return PHS_INVALID_TABLE_INDEX;
 }
 
-static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16  uiClsId,
-				IN struct bcm_phs_table *psServiceFlowTable,
-				struct bcm_phs_rule *psPhsRule,
-				B_UINT8 u8AssociatedPHSI)
+static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,
+					    IN B_UINT16  uiClsId,
+					    IN struct bcm_phs_table *psServiceFlowTable,
+					    struct bcm_phs_rule *psPhsRule,
+					    B_UINT8 u8AssociatedPHSI)
 {
 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
 	UINT uiStatus = 0;
 	int iSfIndex;
 	bool bFreeEntryFound = false;
+	struct bcm_phs_entry *curr_list;
 
 	/* Check for a free entry in SFID table */
 	for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
-		if (!psServiceFlowTable->stSFList[iSfIndex].bUsed) {
+		curr_list = &psServiceFlowTable->stSFList[iSfIndex];
+		if (!curr_list->bUsed) {
 			bFreeEntryFound = TRUE;
 			break;
 		}
@@ -898,23 +1073,26 @@ static UINT CreateSFToClassifierRuleMapp
 	if (!bFreeEntryFound)
 		return ERR_SFTABLE_FULL;
 
-	psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
-	uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, psPhsRule,
-					eActiveClassifierRuleContext, u8AssociatedPHSI);
+	psaClassifiertable = curr_list->pstClassifierTable;
+	uiStatus = CreateClassifierPHSRule(uiClsId,
+					   psaClassifiertable,
+					   psPhsRule,
+					   eActiveClassifierRuleContext,
+					   u8AssociatedPHSI);
 	if (uiStatus == PHS_SUCCESS) {
 		/* Add entry at free index to the SF */
-		psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
-		psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
+		curr_list->bUsed = TRUE;
+		curr_list->uiVcid = uiVcid;
 	}
 
 	return uiStatus;
 }
 
 static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
-				IN B_UINT16 uiClsId,
-				IN struct bcm_phs_entry *pstServiceFlowEntry,
-				struct bcm_phs_rule *psPhsRule,
-				B_UINT8 u8AssociatedPHSI)
+					    IN B_UINT16 uiClsId,
+					    IN struct bcm_phs_entry *pstServiceFlowEntry,
+					    struct bcm_phs_rule *psPhsRule,
+					    B_UINT8 u8AssociatedPHSI)
 {
 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
 	UINT uiStatus = PHS_SUCCESS;
@@ -924,7 +1102,8 @@ static UINT CreateClassiferToPHSRuleMapp
 
 	psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"==>");
 
 	/* Check if the supplied Classifier already exists */
 	nClassifierIndex = GetClassifierEntry(
@@ -935,14 +1114,15 @@ static UINT CreateClassiferToPHSRuleMapp
 
 	if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
 		/*
-		 * The Classifier doesn't exist. So its a new classifier being added.
+		 * The Classifier doesn't exist. So its a new classifier being
+		 * added.
 		 * Add new entry to associate PHS Rule to the Classifier
 		 */
 
 		uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
-						psPhsRule,
-						eActiveClassifierRuleContext,
-						u8AssociatedPHSI);
+						   psPhsRule,
+						   eActiveClassifierRuleContext,
+						   u8AssociatedPHSI);
 		return uiStatus;
 	}
 
@@ -956,25 +1136,28 @@ static UINT CreateClassiferToPHSRuleMapp
 			return ERR_PHS_INVALID_PHS_RULE;
 
 		/*
-		 * This rule already exists if any fields are changed for this PHS
-		 * rule update them.
+		 * This rule already exists if any fields are changed for this
+		 * PHS rule update them.
 		 */
 		/* If any part of PHSF is valid then we update PHSF */
 		if (psPhsRule->u8PHSFLength) {
 			/* update PHSF */
 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
-				psPhsRule->u8PHSF, MAX_PHS_LENGTHS);
+			       psPhsRule->u8PHSF,
+			       MAX_PHS_LENGTHS);
 		}
 
 		if (psPhsRule->u8PHSFLength) {
 			/* update PHSFLen */
-			pstClassifierEntry->pstPhsRule->u8PHSFLength = psPhsRule->u8PHSFLength;
+			pstClassifierEntry->pstPhsRule->u8PHSFLength =
+				psPhsRule->u8PHSFLength;
 		}
 
 		if (psPhsRule->u8PHSMLength) {
 			/* update PHSM */
 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
-				psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+			       psPhsRule->u8PHSM,
+			       MAX_PHS_LENGTHS);
 		}
 
 		if (psPhsRule->u8PHSMLength) {
@@ -985,25 +1168,29 @@ static UINT CreateClassiferToPHSRuleMapp
 
 		if (psPhsRule->u8PHSS) {
 			/* update PHSS */
-			pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
+			pstClassifierEntry->pstPhsRule->u8PHSS =
+				psPhsRule->u8PHSS;
 		}
 
 		/* update PHSV */
 		pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
 	} else {
 		/* A new rule is being set for this classifier. */
-		uiStatus = UpdateClassifierPHSRule(uiClsId, pstClassifierEntry,
-						psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+		uiStatus = UpdateClassifierPHSRule(uiClsId,
+						   pstClassifierEntry,
+						   psaClassifiertable,
+						   psPhsRule,
+						   u8AssociatedPHSI);
 	}
 
 	return uiStatus;
 }
 
 static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
-				struct bcm_phs_classifier_table *psaClassifiertable,
-				struct bcm_phs_rule *psPhsRule,
-				enum bcm_phs_classifier_context eClsContext,
-				B_UINT8 u8AssociatedPHSI)
+				    struct bcm_phs_classifier_table *psaClassifiertable,
+				    struct bcm_phs_rule *psPhsRule,
+				    enum bcm_phs_classifier_context eClsContext,
+				    B_UINT8 u8AssociatedPHSI)
 {
 	UINT iClassifierIndex = 0;
 	bool bFreeEntryFound = false;
@@ -1011,7 +1198,8 @@ static UINT CreateClassifierPHSRule(IN B
 	UINT nStatus = PHS_SUCCESS;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Inside CreateClassifierPHSRule");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
+			"Inside CreateClassifierPHSRule");
 
 	if (psaClassifiertable == NULL)
 		return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
@@ -1022,9 +1210,10 @@ static UINT CreateClassifierPHSRule(IN B
 		 * old rules table replace it.
 		 */
 
-		iClassifierIndex =
-			GetClassifierEntry(psaClassifiertable, uiClsId,
-					eClsContext, &psClassifierRules);
+		iClassifierIndex = GetClassifierEntry(psaClassifiertable,
+						      uiClsId,
+						      eClsContext,
+						      &psClassifierRules);
 
 		if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
 			/*
@@ -1056,12 +1245,15 @@ static UINT CreateClassifierPHSRule(IN B
 		if (eClsContext == eActiveClassifierRuleContext)
 			return ERR_CLSASSIFIER_TABLE_FULL;
 		else {
-			/* Lets replace the oldest rule if we are looking in old Rule table */
+			/* Lets replace the oldest rule if we are looking in
+			 * old Rule table */
 			if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
 				psaClassifiertable->uiOldestPhsRuleIndex = 0;
 
-			iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
-			psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
+			iClassifierIndex =
+				psaClassifiertable->uiOldestPhsRuleIndex;
+			psClassifierRules =
+				&psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
 
 			(psaClassifiertable->uiOldestPhsRuleIndex)++;
 		}
@@ -1071,7 +1263,9 @@ static UINT CreateClassifierPHSRule(IN B
 
 		if (psClassifierRules->pstPhsRule == NULL) {
 
-			psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+			psClassifierRules->pstPhsRule =
+				kmalloc(sizeof(struct bcm_phs_rule),
+					GFP_KERNEL);
 
 			if (NULL == psClassifierRules->pstPhsRule)
 				return ERR_PHSRULE_MEMALLOC_FAIL;
@@ -1080,22 +1274,27 @@ static UINT CreateClassifierPHSRule(IN B
 		psClassifierRules->bUsed = TRUE;
 		psClassifierRules->uiClassifierRuleId = uiClsId;
 		psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
-		psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
+		psClassifierRules->bUnclassifiedPHSRule =
+			psPhsRule->bUnclassifiedPHSRule;
 
 		/* Update The PHS rule */
-		memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+		memcpy(psClassifierRules->pstPhsRule, psPhsRule,
+		       sizeof(struct bcm_phs_rule));
 	} else
-		nStatus = UpdateClassifierPHSRule(uiClsId, psClassifierRules,
-						psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+		nStatus = UpdateClassifierPHSRule(uiClsId,
+						  psClassifierRules,
+						  psaClassifiertable,
+						  psPhsRule,
+						  u8AssociatedPHSI);
 
 	return nStatus;
 }
 
 static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
-				IN struct bcm_phs_classifier_entry *pstClassifierEntry,
-				struct bcm_phs_classifier_table *psaClassifiertable,
-				struct bcm_phs_rule *psPhsRule,
-				B_UINT8 u8AssociatedPHSI)
+				    IN struct bcm_phs_classifier_entry *pstClassifierEntry,
+				    struct bcm_phs_classifier_table *psaClassifiertable,
+				    struct bcm_phs_rule *psPhsRule,
+				    B_UINT8 u8AssociatedPHSI)
 {
 	struct bcm_phs_rule *pstAddPhsRule = NULL;
 	UINT nPhsRuleIndex = 0;
@@ -1108,29 +1307,41 @@ static UINT UpdateClassifierPHSRule(IN B
 	bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
 					pstClassifierEntry->pstPhsRule);
 
-	/* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */
+	/* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in
+	 * Classifier table for this SF */
 	nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
-					eActiveClassifierRuleContext, &pstAddPhsRule);
+					eActiveClassifierRuleContext,
+					&pstAddPhsRule);
 	if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL,
+				"\nAdding New PHSRuleEntry For Classifier");
 
 		if (psPhsRule->u8PHSI == 0) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+					DBG_LVL_ALL, "\nError PHSI is Zero\n");
 			return ERR_PHS_INVALID_PHS_RULE;
 		}
 
-		/* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
+		/* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for
+		 * uiClsId */
 		if (false == bPHSRuleOrphaned) {
 
-			pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+			pstClassifierEntry->pstPhsRule =
+				kmalloc(sizeof(struct bcm_phs_rule),
+					GFP_KERNEL);
 			if (NULL == pstClassifierEntry->pstPhsRule)
 				return ERR_PHSRULE_MEMALLOC_FAIL;
 		}
-		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule,
+		       sizeof(struct bcm_phs_rule));
 	} else {
-		/* Step 2.b PHS Rule  Exists Tie uiClsId with the existing PHS Rule */
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
+		/* Step 2.b PHS Rule  Exists Tie uiClsId with the existing
+		 * PHS Rule */
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
+				DBG_LVL_ALL,
+				"\nTying Classifier to Existing PHS Rule");
 		if (bPHSRuleOrphaned) {
 			kfree(pstClassifierEntry->pstPhsRule);
 			pstClassifierEntry->pstPhsRule = NULL;
@@ -1142,12 +1353,15 @@ static UINT UpdateClassifierPHSRule(IN B
 	pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
 	pstClassifierEntry->uiClassifierRuleId = uiClsId;
 	pstClassifierEntry->pstPhsRule->u8RefCnt++;
-	pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
+	pstClassifierEntry->bUnclassifiedPHSRule =
+		pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
 
 	return PHS_SUCCESS;
 }
 
-static bool DerefPhsRule(IN B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
+static bool DerefPhsRule(IN B_UINT16  uiClsId,
+			 struct bcm_phs_classifier_table *psaClassifiertable,
+			 struct bcm_phs_rule *pstPhsRule)
 {
 	if (pstPhsRule == NULL)
 		return false;
@@ -1155,71 +1369,92 @@ static bool DerefPhsRule(IN B_UINT16  ui
 	if (pstPhsRule->u8RefCnt)
 		pstPhsRule->u8RefCnt--;
 
-	if (0 == pstPhsRule->u8RefCnt) {
-		/*
-		 * if(pstPhsRule->u8PHSI)
-		 * Store the currently active rule into the old rules list
-		 * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);
-		 */
-		return TRUE;
-	} else
-		return false;
+	return (0 == pstPhsRule->u8RefCnt);
 }
 
-void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
+static void dbg_print_st_cls_entry(struct bcm_mini_adapter *ad,
+				   struct bcm_phs_entry *st_serv_flow_entry,
+				   struct bcm_phs_classifier_entry *st_cls_entry)
 {
-	int i, j, k, l;
-	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules :\n");
+	int k;
 
-	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X", st_serv_flow_entry->uiVcid);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X", st_cls_entry->uiClassifierRuleId);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X", st_cls_entry->u8PHSI);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X", st_cls_entry->pstPhsRule->u8PHSI);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", st_cls_entry->pstPhsRule->u8PHSFLength);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
 
-		struct bcm_phs_entry stServFlowEntry =
-			pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
-		if (stServFlowEntry.bUsed) {
+	for (k = 0 ; k < st_cls_entry->pstPhsRule->u8PHSFLength; k++)
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", st_cls_entry->pstPhsRule->u8PHSF[k]);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X", st_cls_entry->pstPhsRule->u8PHSMLength);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
 
-			for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+	for (k = 0; k < st_cls_entry->pstPhsRule->u8PHSMLength; k++)
+		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", st_cls_entry->pstPhsRule->u8PHSM[k]);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", st_cls_entry->pstPhsRule->u8PHSS);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X", st_cls_entry->pstPhsRule->u8PHSV);
+	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
+}
 
-				for (l = 0; l < 2; l++) {
-					struct bcm_phs_classifier_entry stClsEntry;
+static void phsrules_per_sf_dbg_print(struct bcm_mini_adapter *ad,
+				      struct bcm_phs_entry *st_serv_flow_entry)
+{
+	int j, l;
+	struct bcm_phs_classifier_entry st_cls_entry;
 
-					if (l == 0) {
-						stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
-						if (stClsEntry.bUsed)
-							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule :\n");
-					} else {
-						stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
-						if (stClsEntry.bUsed)
-							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule :\n");
-					}
+	for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
 
-					if (stClsEntry.bUsed) {
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X", stServFlowEntry.uiVcid);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X", stClsEntry.uiClassifierRuleId);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X", stClsEntry.u8PHSI);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X", stClsEntry.pstPhsRule->u8PHSI);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", stClsEntry.pstPhsRule->u8PHSFLength);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
+		for (l = 0; l < 2; l++) {
 
-						for (k = 0 ; k < stClsEntry.pstPhsRule->u8PHSFLength; k++)
-							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", stClsEntry.pstPhsRule->u8PHSF[k]);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X", stClsEntry.pstPhsRule->u8PHSMLength);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
+			if (l == 0) {
+				st_cls_entry = st_serv_flow_entry->pstClassifierTable->stActivePhsRulesList[j];
+				if (st_cls_entry.bUsed)
+					BCM_DEBUG_PRINT(ad,
+							DBG_TYPE_OTHERS,
+							DUMP_INFO,
+							(DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
+							"\n Active PHS Rule :\n");
+			} else {
+				st_cls_entry = st_serv_flow_entry->pstClassifierTable->stOldPhsRulesList[j];
+				if (st_cls_entry.bUsed)
+					BCM_DEBUG_PRINT(ad,
+							DBG_TYPE_OTHERS,
+							DUMP_INFO,
+							(DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
+							"\n Old PHS Rule :\n");
+			}
 
-						for (k = 0; k < stClsEntry.pstPhsRule->u8PHSMLength; k++)
-							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", stClsEntry.pstPhsRule->u8PHSM[k]);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", stClsEntry.pstPhsRule->u8PHSS);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X", stClsEntry.pstPhsRule->u8PHSV);
-						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
-					}
-				}
+			if (st_cls_entry.bUsed) {
+				dbg_print_st_cls_entry(ad,
+						       st_serv_flow_entry,
+						       &st_cls_entry);
 			}
 		}
 	}
 }
 
+void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
+{
+	int i;
+	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,
+			"\n Dumping PHS Rules :\n");
+
+	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+
+		struct bcm_phs_entry stServFlowEntry =
+			pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
+
+		if (!stServFlowEntry.bUsed)
+			continue;
+
+		phsrules_per_sf_dbg_print(Adapter, &stServFlowEntry);
+	}
+}
+
 /*
  * Procedure:   phs_decompress
  *
@@ -1227,19 +1462,22 @@ void DumpPhsRules(struct bcm_phs_extensi
  *
  * Arguments:
  *	in_buf			- ptr to incoming packet buffer.
- *	out_buf			- ptr to output buffer where the suppressed header is copied.
- *	decomp_phs_rules - ptr to PHS rule.
- *	header_size		- ptr to field which holds the phss or phsf_length.
+ *	out_buf			- ptr to output buffer where the suppressed
+ *				  header is copied.
+ *	decomp_phs_rules	- ptr to PHS rule.
+ *	header_size		- ptr to field which holds the phss or
+ *				  phsf_length.
  *
  * Returns:
- *	size -The number of bytes of dynamic fields present with in the incoming packet
- *			header.
- *	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
+ *	size	- The number of bytes of dynamic fields present with in the
+ *		  incoming packet header.
+ *	0	- If PHS rule is NULL.If PHSI is 0 indicateing packet as
+ *		  uncompressed.
  */
 static int phs_decompress(unsigned char *in_buf,
-		unsigned char *out_buf,
-		struct bcm_phs_rule *decomp_phs_rules,
-		UINT *header_size)
+			  unsigned char *out_buf,
+			  struct bcm_phs_rule *decomp_phs_rules,
+			  UINT *header_size)
 {
 	int phss, size = 0;
 	struct bcm_phs_rule *tmp_memb;
@@ -1250,15 +1488,17 @@ static int phs_decompress(unsigned char
 
 	in_buf++;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
+			"====>\n");
 	*header_size = 0;
 
-	if ((decomp_phs_rules == NULL))
+	if (decomp_phs_rules == NULL)
 		return 0;
 
 	tmp_memb = decomp_phs_rules;
 	/*
-	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
+	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
+	 * "\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
 	 * header_size = tmp_memb->u8PHSFLength;
 	 */
 	phss = tmp_memb->u8PHSS;
@@ -1269,7 +1509,8 @@ static int phs_decompress(unsigned char
 		phss = MAX_PHS_LENGTHS;
 
 	/*
-	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:
+	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
+	 * "\nDECOMP:
 	 * In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
 	 */
 	while ((phss > 0) && (size < in_buf_len)) {
@@ -1277,11 +1518,15 @@ static int phs_decompress(unsigned char
 
 		if (bit == SUPPRESS) {
 			*out_buf = *phsf;
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss  %d phsf %d output %d",
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
+					DBG_LVL_ALL,
+					"\nDECOMP:In phss  %d phsf %d output %d",
 					phss, *phsf, *out_buf);
 		} else {
 			*out_buf = *in_buf;
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss  %d input %d output %d",
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
+					DBG_LVL_ALL,
+					"\nDECOMP:In phss  %d input %d output %d",
 					phss, *in_buf, *out_buf);
 			in_buf++;
 			size++;
@@ -1304,22 +1549,25 @@ static int phs_decompress(unsigned char
 /*
  * Procedure:   phs_compress
  *
- * Description: This routine suppresses the static fields within the packet.Before
- * that it will verify the fields to be suppressed with the corresponding fields in the
- * phsf. For verification it checks the phsv field of PHS rule. If set and verification
- * succeeds it suppresses the field.If any one static field is found different none of
- * the static fields are suppressed then the packet is sent as uncompressed packet with
- * phsi=0.
+ * Description: This routine suppresses the static fields within the packet.
+ * Before that it will verify the fields to be suppressed with the corresponding
+ * fields in the phsf. For verification it checks the phsv field of PHS rule.
+ * If set and verification succeeds it suppresses the field.If any one static
+ * field is found different none of the static fields are suppressed then the
+ * packet is sent as uncompressed packet with phsi=0.
  *
  * Arguments:
  *	phs_rule - ptr to PHS rule.
  *	in_buf		- ptr to incoming packet buffer.
- *	out_buf		- ptr to output buffer where the suppressed header is copied.
+ *	out_buf		- ptr to output buffer where the suppressed header is
+ *			  copied.
  *	header_size	- ptr to field which holds the phss.
  *
  * Returns:
- *	size-The number of bytes copied into the output buffer i.e dynamic fields
- *	0	-If PHS rule is NULL.If PHSV field is not set.If the verification fails.
+ *	size	- The number of bytes copied into the output buffer i.e
+ *		  dynamic fields
+ *	0	- If PHS rule is NULL.If PHSV field is not set. If the
+ *		  verification fails.
  */
 static int phs_compress(struct bcm_phs_rule *phs_rule,
 			unsigned char *in_buf,
@@ -1332,7 +1580,8 @@ static int phs_compress(struct bcm_phs_r
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
 	if (phs_rule == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nphs_compress(): phs_rule null!");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"\nphs_compress(): phs_rule null!");
 		*out_buf = ZERO_PHSI;
 		return STATUS_PHS_NOCOMPRESSION;
 	}
@@ -1350,10 +1599,13 @@ static int phs_compress(struct bcm_phs_r
 
 	if (suppress == STATUS_PHS_COMPRESSED) {
 		*old_addr = (unsigned char)phs_rule->u8PHSI;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress phsi %d", phs_rule->u8PHSI);
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"\nCOMP:In phs_compress phsi %d",
+				phs_rule->u8PHSI);
 	} else {
 		*old_addr = ZERO_PHSI;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress PHSV Verification failed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+				"\nCOMP:In phs_compress PHSV Verification failed");
 	}
 
 	return suppress;
@@ -1370,13 +1622,14 @@ static int phs_compress(struct bcm_phs_r
  * rules_set	- ptr to classifier_rules.
  * in_buffer	- ptr to incoming packet buffer.
  * out_buffer	- ptr to output buffer where the suppressed header is copied.
- * phsf			- ptr to phsf.
- * phsm			- ptr to phsm.
- * phss			- variable holding phss.
+ * phsf		- ptr to phsf.
+ * phsm		- ptr to phsm.
+ * phss		- variable holding phss.
  *
  * Returns:
- *	size-The number of bytes copied into the output buffer i.e dynamic fields.
- *	0	-Packet has failed the verification.
+ *	size    - The number of bytes copied into the output buffer i.e dynamic
+ *		  fields.
+ *	0	- Packet has failed the verification.
  */
 static int verify_suppress_phsf(unsigned char *in_buffer,
 				unsigned char *out_buffer,
@@ -1390,7 +1643,8 @@ static int verify_suppress_phsf(unsigned
 	int bit, i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+			"\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
 
 	if (phss > (*new_header_size))
 		phss = *new_header_size;
@@ -1442,7 +1696,8 @@ static int verify_suppress_phsf(unsigned
 			phsm++;
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf success");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
+			"\nCOMP:In verify_phsf success");
 	*new_header_size = size;
 	return STATUS_PHS_COMPRESSED;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/PHSModule.h linux-libre-3.17-rc7-gnu/drivers/staging/bcm/PHSModule.h
--- linux-libre-3.16-gnu/drivers/staging/bcm/PHSModule.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/PHSModule.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,28 +20,37 @@ int PHSReceive(struct bcm_mini_adapter *
 
 void DumpDataPacketHeader(PUCHAR pPkt);
 
-void DumpFullPacket(UCHAR *pBuf,UINT nPktLen);
+void DumpFullPacket(UCHAR *pBuf, UINT nPktLen);
 
 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension);
 
 
-int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,struct bcm_mini_adapter *Adapter);
+int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,
+	     struct bcm_mini_adapter *Adapter);
 
 int PhsCleanup(struct bcm_phs_extension *pPHSDeviceExt);
 
-//Utility Functions
-ULONG PhsUpdateClassifierRule(void* pvContext,B_UINT16 uiVcid,B_UINT16 uiClsId, struct bcm_phs_rule *psPhsRule,B_UINT8  u8AssociatedPHSI );
+/* Utility Functions */
+ULONG PhsUpdateClassifierRule(void *pvContext,
+			      B_UINT16 uiVcid,
+			      B_UINT16 uiClsId,
+			      struct bcm_phs_rule *psPhsRule,
+			      B_UINT8  u8AssociatedPHSI);
 
-ULONG PhsDeletePHSRule(void* pvContext,B_UINT16 uiVcid,B_UINT8 u8PHSI);
+ULONG PhsDeletePHSRule(void *pvContext, B_UINT16 uiVcid, B_UINT8 u8PHSI);
 
-ULONG PhsDeleteClassifierRule(void* pvContext, B_UINT16 uiVcid ,B_UINT16  uiClsId);
+ULONG PhsDeleteClassifierRule(void *pvContext,
+			      B_UINT16 uiVcid,
+			      B_UINT16  uiClsId);
 
-ULONG PhsDeleteSFRules(void* pvContext,B_UINT16 uiVcid) ;
+ULONG PhsDeleteSFRules(void *pvContext, B_UINT16 uiVcid);
 
 
 bool ValidatePHSRule(struct bcm_phs_rule *psPhsRule);
 
-UINT GetServiceFlowEntry(struct bcm_phs_table *psServiceFlowTable,B_UINT16 uiVcid, struct bcm_phs_entry **ppstServiceFlowEntry);
+UINT GetServiceFlowEntry(struct bcm_phs_table *psServiceFlowTable,
+			 B_UINT16 uiVcid,
+			 struct bcm_phs_entry **ppstServiceFlowEntry);
 
 
 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Prototypes.h linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Prototypes.h
--- linux-libre-3.16-gnu/drivers/staging/bcm/Prototypes.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Prototypes.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,13 +3,13 @@
 
 VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer);
 
-VOID StatisticsResponse(struct bcm_mini_adapter *Adapter,PVOID pvBuffer);
+VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer);
 
-VOID IdleModeResponse(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
+VOID IdleModeResponse(struct bcm_mini_adapter *Adapter, PUINT puiBuffer);
 
-int control_packet_handler	(struct bcm_mini_adapter *Adapter);
+int control_packet_handler(struct bcm_mini_adapter *Adapter);
 
-VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter,UINT uiSearchRuleIndex);
+VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIndex);
 
 VOID flush_all_queues(struct bcm_mini_adapter *Adapter);
 
@@ -29,18 +29,19 @@ VOID flush_all_queues(struct bcm_mini_ad
 
 VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter);
 
-INT SearchSfid(struct bcm_mini_adapter *Adapter,UINT uiSfid);
+INT SearchSfid(struct bcm_mini_adapter *Adapter, UINT uiSfid);
 
-USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb);
+USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff *skb);
 
-bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort);
-bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort);
-bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol);
+bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort);
 
+bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort);
+
+bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtocol);
 
 INT SetupNextSend(struct bcm_mini_adapter *Adapter, /**<Logical Adapter*/
 					struct sk_buff *Packet, /**<data buffer*/
-					USHORT Vcid)	;
+					USHORT Vcid);
 
 VOID LinkMessage(struct bcm_mini_adapter *Adapter);
 
@@ -50,8 +51,8 @@ INT SendControlPacket(struct bcm_mini_ad
 							char *pControlPacket/**<Control Packet*/
 							);
 
-
 int register_networkdev(struct bcm_mini_adapter *Adapter);
+
 void unregister_networkdev(struct bcm_mini_adapter *Adapter);
 
 INT AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
@@ -62,13 +63,12 @@ INT FreeAdapterDsxBuffer(struct bcm_mini
 
 int tx_pkt_handler(struct bcm_mini_adapter *Adapter);
 
-int  reset_card_proc(struct bcm_mini_adapter *Adapter );
+int reset_card_proc(struct bcm_mini_adapter *Adapter);
 
-int run_card_proc(struct bcm_mini_adapter *Adapter );
+int run_card_proc(struct bcm_mini_adapter *Adapter);
 
 int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter);
 
-
 INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter);
 
 int register_control_device_interface(struct bcm_mini_adapter *ps_adapter);
@@ -79,17 +79,18 @@ int rdm(struct bcm_mini_adapter *Adapter
 
 int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
 
-int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int wrmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
-int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int rdmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
-int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId, void __user * user_buffer);
+int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId, void __user *user_buffer);
 
 void SendIdleModeResponse(struct bcm_mini_adapter *Adapter);
 
+int ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *buf);
 
-int  ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *buf);
 void GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *ioBuffer, struct bcm_tarang_data *pTarang);
+
 void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter);
 
 int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo);
@@ -101,38 +102,32 @@ VOID ResetCounters(struct bcm_mini_adapt
 
 int InitLedSettings(struct bcm_mini_adapter *Adapter);
 
-struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter,USHORT usIpIdentification,ULONG SrcIP);
+struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP);
 
 void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo);
 
-void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter,USHORT usIpIdentification,ULONG SrcIp);
-
-void update_per_cid_rx (struct bcm_mini_adapter *Adapter);
+void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp);
 
-void update_per_sf_desc_cnts( struct bcm_mini_adapter *Adapter);
+void update_per_cid_rx(struct bcm_mini_adapter *Adapter);
 
-void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter,B_UINT16 TID,bool bFreeAll);
+void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter);
 
+void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, bool bFreeAll);
 
 void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex);
 
-
 INT flushAllAppQ(VOID);
 
-
 INT BeceemEEPROMBulkRead(
 	struct bcm_mini_adapter *Adapter,
 	PUINT pBuffer,
 	UINT uiOffset,
 	UINT uiNumBytes);
 
-
-
-INT WriteBeceemEEPROM(struct bcm_mini_adapter *Adapter,UINT uiEEPROMOffset, UINT uiData);
+INT WriteBeceemEEPROM(struct bcm_mini_adapter *Adapter, UINT uiEEPROMOffset, UINT uiData);
 
 INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter);
 
-
 INT BeceemEEPROMBulkWrite(
 	struct bcm_mini_adapter *Adapter,
 	PUCHAR pBuffer,
@@ -140,9 +135,7 @@ INT BeceemEEPROMBulkWrite(
 	UINT uiNumBytes,
 	bool bVerify);
 
-
-INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter,UINT dwAddress, UINT *pdwData);
-
+INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, UINT dwAddress, UINT *pdwData);
 
 INT BeceemNVMRead(
 	struct bcm_mini_adapter *Adapter,
@@ -157,10 +150,10 @@ INT BeceemNVMWrite(
 	UINT uiNumBytes,
 	bool bVerify);
 
-
 INT BcmInitNVM(struct bcm_mini_adapter *Adapter);
 
-INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize);
+INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, UINT uiSectorSize);
+
 bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
 
 INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap);
@@ -183,40 +176,42 @@ INT BcmFlash2xBulkRead(
 INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
 
 INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal);
+
 INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
+
 INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
 
 INT BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut);
+
 INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+
 INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
-INT	validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite);
+
+INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite);
+
 INT IsFlash2x(struct bcm_mini_adapter *Adapter);
-INT	BcmCopySection(struct bcm_mini_adapter *Adapter,
+
+INT BcmCopySection(struct bcm_mini_adapter *Adapter,
 						enum bcm_flash2x_section_val SrcSection,
 						enum bcm_flash2x_section_val DstSection,
 						UINT offset,
 						UINT numOfBytes);
 
-
 bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
 
+VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter, PUINT puiBuffer);
 
-VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
+int wrmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
-int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
-int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int rdmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
 int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
+
 INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
 		unsigned long u32StartingAddress);
 
-
 VOID putUsbSuspend(struct work_struct *work);
-bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios);
 
+bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios);
 
 #endif
-
-
-
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Qos.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Qos.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/Qos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Qos.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,6 @@
 /**
-@file Qos.C
-This file contains the routines related to Quality of Service.
+ * @file Qos.C
+ * This file contains the routines related to Quality of Service.
 */
 #include "headers.h"
 
@@ -31,22 +31,40 @@ static VOID PruneQueue(struct bcm_mini_a
 *
 * Returns     - TRUE(If address matches) else FAIL .
 *********************************************************************/
-static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP)
+static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,
+			      ULONG ulSrcIP)
 {
 	UCHAR ucLoopIndex = 0;
 
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	union u_ip_address	*src_addr;
 
 	ulSrcIP = ntohl(ulSrcIP);
 	if (0 == pstClassifierRule->ucIPSourceAddressLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]);
-		if ((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
-				(pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]))
+	for (ucLoopIndex = 0;
+	     ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);
+	     ucLoopIndex++) {
+		src_addr = &pstClassifierRule->stSrcIpAddress;
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x",
+				(UINT)src_addr->ulIpv4Mask[ucLoopIndex],
+				(UINT)ulSrcIP,
+				(UINT)src_addr->ulIpv6Addr[ucLoopIndex]);
+
+		if ((src_addr->ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
+				(src_addr->ulIpv4Addr[ucLoopIndex] &
+				 src_addr->ulIpv4Mask[ucLoopIndex]))
 			return TRUE;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Src Ip Address Not Matched");
 	return false;
 }
 
@@ -66,18 +84,33 @@ static bool MatchDestIpAddress(struct bc
 {
 	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	union u_ip_address	*dest_addr = &pstClassifierRule->stDestIpAddress;
 
 	ulDestIP = ntohl(ulDestIP);
 	if (0 == pstClassifierRule->ucIPDestinationAddressLength)
 		return TRUE;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x  ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Destination Ip Address 0x%x 0x%x 0x%x  ",
+			(UINT)ulDestIP,
+			(UINT)dest_addr->ulIpv4Mask[ucLoopIndex],
+			(UINT)dest_addr->ulIpv4Addr[ucLoopIndex]);
 
-	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++) {
-		if ((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
-				(pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
+	for (ucLoopIndex = 0;
+	     ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength);
+	     ucLoopIndex++) {
+		if ((dest_addr->ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
+				(dest_addr->ulIpv4Addr[ucLoopIndex] &
+				 dest_addr->ulIpv4Mask[ucLoopIndex]))
 			return TRUE;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Destination Ip Address Not Matched");
 	return false;
 }
 
@@ -92,17 +125,25 @@ static bool MatchDestIpAddress(struct bc
 *
 * Returns     - TRUE(If address matches) else FAIL.
 **************************************************************************/
-static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService)
+static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule,
+		     UCHAR ucTypeOfService)
 {
-
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	if (3 != pstClassifierRule->ucIPTypeOfServiceLength)
 		return TRUE;
 
-	if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService) >= pstClassifierRule->ucTosLow))
+	if (((pstClassifierRule->ucTosMask & ucTypeOfService) <=
+				pstClassifierRule->ucTosHigh) &&
+			((pstClassifierRule->ucTosMask & ucTypeOfService) >=
+				pstClassifierRule->ucTosLow))
 		return TRUE;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Type Of Service Not Matched");
 	return false;
 }
 
@@ -117,18 +158,32 @@ static bool MatchTos(struct bcm_classifi
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ****************************************************************************/
-bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtocol)
+bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,
+		   UCHAR ucProtocol)
 {
 	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	if (0 == pstClassifierRule->ucProtocolLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol, pstClassifierRule->ucProtocol[ucLoopIndex]);
+	for (ucLoopIndex = 0;
+	     ucLoopIndex < pstClassifierRule->ucProtocolLength;
+	     ucLoopIndex++) {
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"Protocol:0x%X Classification Protocol:0x%X",
+				ucProtocol,
+				pstClassifierRule->ucProtocol[ucLoopIndex]);
 		if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol)
 			return TRUE;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Protocol Not Matched");
 	return false;
 }
 
@@ -143,7 +198,8 @@ bool MatchProtocol(struct bcm_classifier
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ***************************************************************************/
-bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort)
+bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,
+		  USHORT ushSrcPort)
 {
 	UCHAR ucLoopIndex = 0;
 
@@ -152,12 +208,19 @@ bool MatchSrcPort(struct bcm_classifier_
 
 	if (0 == pstClassifierRule->ucSrcPortRangeLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++) {
+	for (ucLoopIndex = 0;
+	     ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength;
+	     ucLoopIndex++) {
 		if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
 			ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
 			return TRUE;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Src Port: %x Not Matched ",
+			ushSrcPort);
 	return false;
 }
 
@@ -172,7 +235,8 @@ bool MatchSrcPort(struct bcm_classifier_
 *
 * Returns     - TRUE(If address matches) else FAIL.
 ***************************************************************************/
-bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushDestPort)
+bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,
+		   USHORT ushDestPort)
 {
 	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -180,20 +244,34 @@ bool MatchDestPort(struct bcm_classifier
 	if (0 == pstClassifierRule->ucDestPortRangeLength)
 		return TRUE;
 
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X   0x%X  0x%X", ushDestPort, pstClassifierRule->usDestPortRangeLo[ucLoopIndex], pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
+	for (ucLoopIndex = 0;
+	     ucLoopIndex < pstClassifierRule->ucDestPortRangeLength;
+	     ucLoopIndex++) {
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"Matching Port:0x%X   0x%X  0x%X",
+				ushDestPort,
+				pstClassifierRule->usDestPortRangeLo[ucLoopIndex],
+				pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
 
 		if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
 			ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
 			return TRUE;
 	}
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Dest Port: %x Not Matched",
+			ushDestPort);
 	return false;
 }
 /**
-@ingroup tx_functions
-Compares IPV4 Ip address and port number
-@return Queue Index.
+ * @ingroup tx_functions
+ * Compares IPV4 Ip address and port number
+ * @return Queue Index.
 */
 static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter,
 			   struct iphdr *iphd,
@@ -202,78 +280,136 @@ static USHORT	IpVersion4(struct bcm_mini
 	struct bcm_transport_header *xprt_hdr = NULL;
 	bool	bClassificationSucceed = false;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"========>");
 
 	xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
 
-	do {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d",
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Trying to see Direction = %d %d",
 			pstClassifierRule->ucDirection,
 			pstClassifierRule->usVCID_Value);
 
-		//Checking classifier validity
-		if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
-			break;
+	/* Checking classifier validity */
+	if (!pstClassifierRule->bUsed ||
+			pstClassifierRule->ucDirection == DOWNLINK_DIR)
+		goto out;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
-		if (pstClassifierRule->bIpv6Protocol)
-			break;
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"is IPv6 check!");
+	if (pstClassifierRule->bIpv6Protocol)
+		goto out;
 
-		//**************Checking IP header parameter**************************//
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-		if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
-			break;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
+	/* Checking IP header parameter */
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Trying to match Source IP Address");
+	if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
+		goto out;
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Source IP Address Matched");
 
-		if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
-			break;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
+	if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
+		goto out;
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Destination IP Address Matched");
 
-		if (!MatchTos(pstClassifierRule, iphd->tos)) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
-			break;
-		}
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
+	if (!MatchTos(pstClassifierRule, iphd->tos)) {
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"TOS Match failed\n");
+		goto out;
+	}
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"TOS Matched");
 
-		if (!MatchProtocol(pstClassifierRule, iphd->protocol))
-			break;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
+	if (!MatchProtocol(pstClassifierRule, iphd->protocol))
+		goto out;
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Protocol Matched");
 
-		//if protocol is not TCP or UDP then no need of comparing source port and destination port
-		if (iphd->protocol != TCP && iphd->protocol != UDP) {
-			bClassificationSucceed = TRUE;
-			break;
-		}
-		//******************Checking Transport Layer Header field if present *****************//
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
+	/*
+	 * if protocol is not TCP or UDP then no
+	 * need of comparing source port and destination port
+	 */
+	if (iphd->protocol != TCP && iphd->protocol != UDP) {
+		bClassificationSucceed = TRUE;
+		goto out;
+	}
+	/* Checking Transport Layer Header field if present */
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Source Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-		if (!MatchSrcPort(pstClassifierRule,
-				  ntohs((iphd->protocol == UDP) ?
-				  xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
-			break;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
+	if (!MatchSrcPort(pstClassifierRule,
+			  ntohs((iphd->protocol == UDP) ?
+			  xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
+		goto out;
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Src Port Matched");
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"Destination Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
-			xprt_hdr->thdr.dest);
-		if (!MatchDestPort(pstClassifierRule,
-				   ntohs((iphd->protocol == UDP) ?
-				   xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
-			break;
-		bClassificationSucceed = TRUE;
-	} while (0);
+				xprt_hdr->thdr.dest);
+
+	if (!MatchDestPort(pstClassifierRule,
+			   ntohs((iphd->protocol == UDP) ?
+			   xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
+		goto out;
+	bClassificationSucceed = TRUE;
 
+out:
 	if (TRUE == bClassificationSucceed) {
 		INT iMatchedSFQueueIndex = 0;
-		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+
+		iMatchedSFQueueIndex =
+			SearchSfid(Adapter, pstClassifierRule->ulSFID);
 		if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
 			bClassificationSucceed = false;
 		else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
 			bClassificationSucceed = false;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"IpVersion4 <==========");
 
 	return bClassificationSucceed;
 }
@@ -292,18 +428,24 @@ VOID PruneQueueAllSF(struct bcm_mini_ada
 
 
 /**
-@ingroup tx_functions
-This function checks if the max queue size for a queue
-is less than number of bytes in the queue. If so -
-drops packets from the Head till the number of bytes is
-less than or equal to max queue size for the queue.
-*/
+ * @ingroup tx_functions
+ * This function checks if the max queue size for a queue
+ * is less than number of bytes in the queue. If so -
+ * drops packets from the Head till the number of bytes is
+ * less than or equal to max queue size for the queue.
+ */
 static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 {
-	struct sk_buff* PacketToDrop = NULL;
+	struct sk_buff *PacketToDrop = NULL;
 	struct net_device_stats *netstats;
+	struct bcm_packet_info	*curr_pack_info = &Adapter->PackInfo[iIndex];
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d", iIndex);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			PRUNE_QUEUE,
+			DBG_LVL_ALL,
+			"=====> Index %d",
+			iIndex);
 
 	if (iIndex == HiPriority)
 		return;
@@ -314,22 +456,29 @@ static VOID PruneQueue(struct bcm_mini_a
 	/* To Store the netdevice statistic */
 	netstats = &Adapter->dev->stats;
 
-	spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
+	spin_lock_bh(&curr_pack_info->SFQueueLock);
 
 	while (1) {
-//	while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
-//		SF_MAX_ALLOWED_PACKETS_TO_BACKUP) {
+/*	while((UINT)curr_pack_info->uiCurrentPacketsOnHost >
+		SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { */
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
-		Adapter->PackInfo[iIndex].uiCurrentBytesOnHost,
-		Adapter->PackInfo[iIndex].uiMaxBucketSize);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				PRUNE_QUEUE,
+				DBG_LVL_ALL,
+				"uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
+				curr_pack_info->uiCurrentBytesOnHost,
+				curr_pack_info->uiMaxBucketSize);
 
-		PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue;
+		PacketToDrop = curr_pack_info->FirstTxQueue;
 
 		if (PacketToDrop == NULL)
 			break;
-		if ((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
-			((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency))
+		if ((curr_pack_info->uiCurrentPacketsOnHost <
+					SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
+			((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb) +
+					    SKB_CB_LATENCY_OFFSET))/HZ) <=
+				curr_pack_info->uiMaxLatency))
 			break;
 
 		if (PacketToDrop) {
@@ -339,120 +488,168 @@ static VOID PruneQueue(struct bcm_mini_a
 
 			netstats->tx_dropped++;
 
-			DEQUEUEPACKET(Adapter->PackInfo[iIndex].FirstTxQueue,
-						Adapter->PackInfo[iIndex].LastTxQueue);
-			/// update current bytes and packets count
-			Adapter->PackInfo[iIndex].uiCurrentBytesOnHost -=
+			DEQUEUEPACKET(curr_pack_info->FirstTxQueue,
+				      curr_pack_info->LastTxQueue);
+			/* update current bytes and packets count */
+			curr_pack_info->uiCurrentBytesOnHost -=
 				PacketToDrop->len;
-			Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost--;
-			/// update dropped bytes and packets counts
-			Adapter->PackInfo[iIndex].uiDroppedCountBytes += PacketToDrop->len;
-			Adapter->PackInfo[iIndex].uiDroppedCountPackets++;
+			curr_pack_info->uiCurrentPacketsOnHost--;
+			/* update dropped bytes and packets counts */
+			curr_pack_info->uiDroppedCountBytes += PacketToDrop->len;
+			curr_pack_info->uiDroppedCountPackets++;
 			dev_kfree_skb(PacketToDrop);
 
 		}
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
-			Adapter->PackInfo[iIndex].uiDroppedCountBytes,
-			Adapter->PackInfo[iIndex].uiDroppedCountPackets);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				PRUNE_QUEUE,
+				DBG_LVL_ALL,
+				"Dropped Bytes:%x Dropped Packets:%x",
+				curr_pack_info->uiDroppedCountBytes,
+				curr_pack_info->uiDroppedCountPackets);
 
 		atomic_dec(&Adapter->TotalPacketCount);
 	}
 
-	spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
+	spin_unlock_bh(&curr_pack_info->SFQueueLock);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x",
-		atomic_read(&Adapter->TotalPacketCount));
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<=====");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			PRUNE_QUEUE,
+			DBG_LVL_ALL,
+			"TotalPacketCount:%x",
+			atomic_read(&Adapter->TotalPacketCount));
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			PRUNE_QUEUE,
+			DBG_LVL_ALL,
+			"<=====");
 }
 
 VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
 {
-	INT		iQIndex;
-	UINT	uiTotalPacketLength;
-	struct sk_buff*			PacketToDrop = NULL;
+	INT	iQIndex;
+	UINT uiTotalPacketLength;
+	struct sk_buff *PacketToDrop = NULL;
+	struct bcm_packet_info *curr_packet_info;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_OTHERS,
+			DUMP_INFO,
+			DBG_LVL_ALL,
+			"=====>");
 
-//	down(&Adapter->data_packet_queue_lock);
+	/* down(&Adapter->data_packet_queue_lock); */
 	for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) {
 		struct net_device_stats *netstats = &Adapter->dev->stats;
 
-		spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
-		while (Adapter->PackInfo[iQIndex].FirstTxQueue) {
-			PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
+		curr_packet_info = &Adapter->PackInfo[iQIndex];
+
+		spin_lock_bh(&curr_packet_info->SFQueueLock);
+		while (curr_packet_info->FirstTxQueue) {
+			PacketToDrop = curr_packet_info->FirstTxQueue;
 			if (PacketToDrop) {
 				uiTotalPacketLength = PacketToDrop->len;
 				netstats->tx_dropped++;
 			} else
 				uiTotalPacketLength = 0;
 
-			DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue,
-						Adapter->PackInfo[iQIndex].LastTxQueue);
+			DEQUEUEPACKET(curr_packet_info->FirstTxQueue,
+				      curr_packet_info->LastTxQueue);
 
 			/* Free the skb */
 			dev_kfree_skb(PacketToDrop);
 
-			/// update current bytes and packets count
-			Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength;
-			Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
+			/* update current bytes and packets count */
+			curr_packet_info->uiCurrentBytesOnHost -= uiTotalPacketLength;
+			curr_packet_info->uiCurrentPacketsOnHost--;
 
-			/// update dropped bytes and packets counts
-			Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength;
-			Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
+			/* update dropped bytes and packets counts */
+			curr_packet_info->uiDroppedCountBytes += uiTotalPacketLength;
+			curr_packet_info->uiDroppedCountPackets++;
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
-					Adapter->PackInfo[iQIndex].uiDroppedCountBytes,
-					Adapter->PackInfo[iQIndex].uiDroppedCountPackets);
+			BCM_DEBUG_PRINT(Adapter,
+					DBG_TYPE_OTHERS,
+					DUMP_INFO,
+					DBG_LVL_ALL,
+					"Dropped Bytes:%x Dropped Packets:%x",
+					curr_packet_info->uiDroppedCountBytes,
+					curr_packet_info->uiDroppedCountPackets);
 			atomic_dec(&Adapter->TotalPacketCount);
 		}
-		spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
+		spin_unlock_bh(&curr_packet_info->SFQueueLock);
 	}
-//	up(&Adapter->data_packet_queue_lock);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<=====");
+	/* up(&Adapter->data_packet_queue_lock); */
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_OTHERS,
+			DUMP_INFO,
+			DBG_LVL_ALL,
+			"<=====");
 }
 
-USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
+USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
 {
-	INT			uiLoopIndex = 0;
+	INT uiLoopIndex = 0;
 	struct bcm_classifier_rule *pstClassifierRule = NULL;
 	struct bcm_eth_packet_info stEthCsPktInfo;
 	PVOID pvEThPayload = NULL;
 	struct iphdr *pIpHeader = NULL;
-	INT	  uiSfIndex = 0;
-	USHORT	usIndex = Adapter->usBestEffortQueueIndex;
-	bool	bFragmentedPkt = false, bClassificationSucceed = false;
-	USHORT	usCurrFragment = 0;
+	INT uiSfIndex = 0;
+	USHORT usIndex = Adapter->usBestEffortQueueIndex;
+	bool bFragmentedPkt = false, bClassificationSucceed = false;
+	USHORT usCurrFragment = 0;
 
 	struct bcm_tcp_header *pTcpHeader;
 	UCHAR IpHeaderLength;
 	UCHAR TcpHeaderLength;
 
 	pvEThPayload = skb->data;
-	*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET) = 0;
+	*((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) = 0;
 	EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
 
 	switch (stEthCsPktInfo.eNwpktEthFrameType) {
-		case eEth802LLCFrame:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n");
-			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
-			break;
-		case eEth802LLCSNAPFrame:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n");
-			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_snap_frame);
-			break;
-		case eEth802QVLANFrame:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n");
-			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
-			break;
-		case eEthOtherFrame:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n");
-			pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
-			break;
-		default:
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n");
-			pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
-			break;
+	case eEth802LLCFrame:
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"ClassifyPacket : 802LLCFrame\n");
+		pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
+		break;
+	case eEth802LLCSNAPFrame:
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"ClassifyPacket : 802LLC SNAP Frame\n");
+		pIpHeader = pvEThPayload +
+			sizeof(struct bcm_eth_llc_snap_frame);
+		break;
+	case eEth802QVLANFrame:
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"ClassifyPacket : 802.1Q VLANFrame\n");
+		pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
+		break;
+	case eEthOtherFrame:
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"ClassifyPacket : ETH Other Frame\n");
+		pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
+		break;
+	default:
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"ClassifyPacket : Unrecognized ETH Frame\n");
+		pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
+		break;
 	}
 
 	if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) {
@@ -461,16 +658,28 @@ USHORT ClassifyPacket(struct bcm_mini_ad
 			bFragmentedPkt = TRUE;
 
 		if (bFragmentedPkt) {
-				//Fragmented  Packet. Get Frag Classifier Entry.
-			pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
+			/* Fragmented  Packet. Get Frag Classifier Entry. */
+			pstClassifierRule = GetFragIPClsEntry(Adapter,
+							      pIpHeader->id,
+							      pIpHeader->saddr);
 			if (pstClassifierRule) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt");
+					BCM_DEBUG_PRINT(Adapter,
+							DBG_TYPE_TX,
+							IPV4_DBG,
+							DBG_LVL_ALL,
+							"It is next Fragmented pkt");
 					bClassificationSucceed = TRUE;
 			}
 			if (!(ntohs(pIpHeader->frag_off) & IP_MF)) {
-				//Fragmented Last packet . Remove Frag Classifier Entry
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt");
-				DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
+				/* Fragmented Last packet . Remove Frag Classifier Entry */
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_TX,
+						IPV4_DBG,
+						DBG_LVL_ALL,
+						"This is the last fragmented Pkt");
+				DelFragIPClsEntry(Adapter,
+						  pIpHeader->id,
+						  pIpHeader->saddr);
 			}
 		}
 	}
@@ -478,100 +687,173 @@ USHORT ClassifyPacket(struct bcm_mini_ad
 	for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) {
 		if (bClassificationSucceed)
 			break;
-		//Iterate through all classifiers which are already in order of priority
-		//to classify the packet until match found
-		do {
-			if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
-				bClassificationSucceed = false;
-				break;
-			}
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
+		/*
+		 * Iterate through all classifiers which are already in order of priority
+		 * to classify the packet until match found
+		 */
+		if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
+			bClassificationSucceed = false;
+			continue;
+		}
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"Adapter->PackInfo[%d].bvalid=True\n",
+				uiLoopIndex);
 
-			if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
-				bClassificationSucceed = false;//cannot be processed for classification.
-				break;						// it is a down link connection
-			}
+		if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
+			bClassificationSucceed = false; /* cannot be processed for classification. */
+			continue;	/* it is a down link connection */
+		}
 
-			pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
+		pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
 
-			uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
-			if (uiSfIndex >= NO_OF_QUEUES) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Queue Not Valid. SearchSfid for this classifier Failed\n");
-				break;
-			}
+		uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+		if (uiSfIndex >= NO_OF_QUEUES) {
+			BCM_DEBUG_PRINT(Adapter,
+					DBG_TYPE_TX,
+					IPV4_DBG,
+					DBG_LVL_ALL,
+					"Queue Not Valid. SearchSfid for this classifier Failed\n");
+			continue;
+		}
 
-			if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
+		if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
 
-				if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
-					bClassificationSucceed = false;
-					break;
-				}
+			if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_TX,
+						IPV4_DBG,
+						DBG_LVL_ALL,
+						" ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
+				bClassificationSucceed = false;
+				continue;
+			}
 
 
 
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID);
-				bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
+			BCM_DEBUG_PRINT(Adapter,
+					DBG_TYPE_TX,
+					IPV4_DBG,
+					DBG_LVL_ALL,
+					"Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",
+					pstClassifierRule->uiClassifierRuleIndex,
+					Adapter->PackInfo[uiSfIndex].ulSFID);
+			bClassificationSucceed = EThCSClassifyPkt(Adapter,
+								  skb,
+								  &stEthCsPktInfo,
+								  pstClassifierRule,
+								  Adapter->PackInfo[uiSfIndex].bEthCSSupport);
 
-				if (!bClassificationSucceed) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ClassifyPacket : Ethernet CS Classification Failed\n");
-					break;
-				}
-			} else {	// No ETH Supported on this SF
-				if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
-					bClassificationSucceed = false;
-					break;
-				}
+			if (!bClassificationSucceed) {
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_TX,
+						IPV4_DBG,
+						DBG_LVL_ALL,
+						"ClassifyPacket : Ethernet CS Classification Failed\n");
+				continue;
 			}
+		} else { /* No ETH Supported on this SF */
+			if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_TX,
+						IPV4_DBG,
+						DBG_LVL_ALL,
+						" ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
+				bClassificationSucceed = false;
+				continue;
+			}
+		}
 
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Proceeding to IP CS Clasification");
-
-			if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"Proceeding to IP CS Clasification");
 
-				if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
-					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
-					bClassificationSucceed = false;
-					break;
-				}
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n");
-				DumpFullPacket((PUCHAR)pIpHeader, 20);
+		if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
 
-				if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
-					bClassificationSucceed = IpVersion4(Adapter, pIpHeader, pstClassifierRule);
-				else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
-					bClassificationSucceed = IpVersion6(Adapter, pIpHeader, pstClassifierRule);
+			if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_TX,
+						IPV4_DBG,
+						DBG_LVL_ALL,
+						" ClassifyPacket : Packet is Not an IP Packet\n");
+				bClassificationSucceed = false;
+				continue;
 			}
+			BCM_DEBUG_PRINT(Adapter,
+					DBG_TYPE_TX,
+					IPV4_DBG,
+					DBG_LVL_ALL,
+					"Dump IP Header :\n");
+			DumpFullPacket((PUCHAR)pIpHeader, 20);
 
-		} while (0);
+			if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
+				bClassificationSucceed = IpVersion4(Adapter,
+								    pIpHeader,
+								    pstClassifierRule);
+			else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
+				bClassificationSucceed = IpVersion6(Adapter,
+								    pIpHeader,
+								    pstClassifierRule);
+		}
 	}
 
 	if (bClassificationSucceed == TRUE) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"CF id : %d, SF ID is =%lu",
+				pstClassifierRule->uiClassifierRuleIndex,
+				pstClassifierRule->ulSFID);
 
-		//Store The matched Classifier in SKB
-		*((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex;
-		if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len)) {
-			 IpHeaderLength   = pIpHeader->ihl;
-			 pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
-			 TcpHeaderLength  = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
+		/* Store The matched Classifier in SKB */
+		*((UINT32 *)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) =
+			pstClassifierRule->uiClassifierRuleIndex;
+		if ((TCP == pIpHeader->protocol) && !bFragmentedPkt &&
+				(ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <=
+					skb->len)) {
+			IpHeaderLength = pIpHeader->ihl;
+			pTcpHeader =
+				(struct bcm_tcp_header *)(((PUCHAR)pIpHeader) +
+						(IpHeaderLength*4));
+			TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
 
 			if ((pTcpHeader->ucFlags & TCP_ACK) &&
-			   (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
-				*((UINT32*) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK;
+				   (ntohs(pIpHeader->tot_len) ==
+				    (IpHeaderLength*4)+(TcpHeaderLength*4)))
+				*((UINT32 *) (skb->cb) + SKB_CB_TCPACK_OFFSET) =
+					TCP_ACK;
 		}
 
 		usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is	=%d", usIndex);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"index is =%d",
+				usIndex);
 
-		//If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt.
+		/*
+		 * If this is the first fragment of a Fragmented pkt,
+		 * add this CF. Only This CF should be used for all other
+		 * fragment of this Pkt.
+		 */
 		if (bFragmentedPkt && (usCurrFragment == 0)) {
-			//First Fragment of Fragmented Packet. Create Frag CLS Entry
+			/*
+			 * First Fragment of Fragmented Packet.
+			 * Create Frag CLS Entry
+			 */
 			struct bcm_fragmented_packet_info stFragPktInfo;
+
 			stFragPktInfo.bUsed = TRUE;
 			stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr;
 			stFragPktInfo.usIpIdentification = pIpHeader->id;
-			stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule;
+			stFragPktInfo.pstMatchedClassifierEntry =
+				pstClassifierRule;
 			stFragPktInfo.bOutOfOrderFragment = false;
 			AddFragIPClsEntry(Adapter, &stFragPktInfo);
 		}
@@ -579,56 +861,103 @@ USHORT ClassifyPacket(struct bcm_mini_ad
 
 	}
 
-	if (bClassificationSucceed)
-		return usIndex;
-	else
-		return INVALID_QUEUE_INDEX;
+	return bClassificationSucceed ? usIndex : INVALID_QUEUE_INDEX;
 }
 
-static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,
+				    PUCHAR Mac)
 {
 	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	if (pstClassifierRule->ucEthCSSrcMACLen == 0)
 		return TRUE;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s\n", __func__);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"%s\n", __func__);
 	for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
-		if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
-			(Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",
+				i,
+				Mac[i],
+				pstClassifierRule->au8EThCSSrcMAC[i],
+				pstClassifierRule->au8EThCSSrcMACMask[i]);
+		if ((pstClassifierRule->au8EThCSSrcMAC[i] &
+					pstClassifierRule->au8EThCSSrcMACMask[i]) !=
+				(Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
 			return false;
 	}
 	return TRUE;
 }
 
-static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,
+				     PUCHAR Mac)
 {
 	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	if (pstClassifierRule->ucEthCSDestMACLen == 0)
 		return TRUE;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __func__);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"%s\n",
+			__func__);
 	for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
-		if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
-			(Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n",
+				i,
+				Mac[i],
+				pstClassifierRule->au8EThCSDestMAC[i],
+				pstClassifierRule->au8EThCSDestMACMask[i]);
+		if ((pstClassifierRule->au8EThCSDestMAC[i] &
+					pstClassifierRule->au8EThCSDestMACMask[i]) !=
+				(Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
 			return false;
 	}
 	return TRUE;
 }
 
-static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,
+				 struct sk_buff *skb,
+				 struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	if ((pstClassifierRule->ucEtherTypeLen == 0) ||
 		(pstClassifierRule->au8EthCSEtherType[0] == 0))
 		return TRUE;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __func__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"%s SrcEtherType:%x CLS EtherType[0]:%x\n",
+			__func__,
+			pstEthCsPktInfo->usEtherType,
+			pstClassifierRule->au8EthCSEtherType[0]);
 	if (pstClassifierRule->au8EthCSEtherType[0] == 1) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS EtherType[1]:%x EtherType[2]:%x\n", __func__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"%s  CLS EtherType[1]:%x EtherType[2]:%x\n",
+				__func__,
+				pstClassifierRule->au8EthCSEtherType[1],
+				pstClassifierRule->au8EthCSEtherType[2]);
 
-		if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
+		if (memcmp(&pstEthCsPktInfo->usEtherType,
+			   &pstClassifierRule->au8EthCSEtherType[1],
+			   2) == 0)
 			return TRUE;
 		else
 			return false;
@@ -638,8 +967,16 @@ static bool EthCSMatchEThTypeSAP(struct
 		if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
 			return false;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  EthCS DSAP:%x EtherType[2]:%x\n", __func__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]);
-		if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"%s  EthCS DSAP:%x EtherType[2]:%x\n",
+				__func__,
+				pstEthCsPktInfo->ucDSAP,
+				pstClassifierRule->au8EthCSEtherType[2]);
+		if (pstEthCsPktInfo->ucDSAP ==
+				pstClassifierRule->au8EthCSEtherType[2])
 			return TRUE;
 		else
 			return false;
@@ -650,40 +987,70 @@ static bool EthCSMatchEThTypeSAP(struct
 
 }
 
-static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,
+				struct sk_buff *skb,
+				struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	bool bClassificationSucceed = false;
 	USHORT usVLANID;
 	B_UINT8 uPriority = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS UserPrio:%x CLS VLANID:%x\n", __func__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"%s  CLS UserPrio:%x CLS VLANID:%x\n",
+			__func__,
+			ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),
+			pstClassifierRule->usVLANID);
 
-	/* In case FW didn't receive the TLV, the priority field should be ignored */
-	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
+	/*
+	 * In case FW didn't receive the TLV,
+	 * the priority field should be ignored
+	 */
+	if (pstClassifierRule->usValidityBitMap &
+			(1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return false;
 
-		uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13;
+		uPriority = (ntohs(*(USHORT *)(skb->data +
+				   sizeof(struct bcm_eth_header))) &
+				   0xF000) >> 13;
 
-		if ((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
-				bClassificationSucceed = TRUE;
+		if ((uPriority >= pstClassifierRule->usUserPriority[0]) &&
+				(uPriority <=
+				 pstClassifierRule->usUserPriority[1]))
+			bClassificationSucceed = TRUE;
 
 		if (!bClassificationSucceed)
 			return false;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 D  User Priority Rule Matched\n");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS 802.1 D  User Priority Rule Matched\n");
 
 	bClassificationSucceed = false;
 
-	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID)) {
+	if (pstClassifierRule->usValidityBitMap &
+			(1<<PKT_CLASSIFICATION_VLANID_VALID)) {
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return false;
 
-		usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF;
+		usVLANID = ntohs(*(USHORT *)(skb->data +
+					sizeof(struct bcm_eth_header))) & 0xFFF;
 
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  Pkt VLANID %x Priority: %d\n", __func__, usVLANID, uPriority);
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"%s  Pkt VLANID %x Priority: %d\n",
+				__func__,
+				usVLANID,
+				uPriority);
 
 		if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
 			bClassificationSucceed = TRUE;
@@ -692,70 +1059,113 @@ static bool EthCSMatchVLANRules(struct b
 			return false;
 	}
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 Q VLAN ID Rule Matched\n");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS 802.1 Q VLAN ID Rule Matched\n");
 
 	return TRUE;
 }
 
 
-static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb,
-				struct bcm_eth_packet_info *pstEthCsPktInfo,
-				struct bcm_classifier_rule *pstClassifierRule,
-				B_UINT8 EthCSCupport)
+static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,
+			     struct sk_buff *skb,
+			     struct bcm_eth_packet_info *pstEthCsPktInfo,
+			     struct bcm_classifier_rule *pstClassifierRule,
+			     B_UINT8 EthCSCupport)
 {
 	bool bClassificationSucceed = false;
-	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
+
+	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,
+			((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
 	if (!bClassificationSucceed)
 		return false;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS SrcMAC Matched\n");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS SrcMAC Matched\n");
 
-	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
+	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,
+			((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
 	if (!bClassificationSucceed)
 		return false;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS DestMAC Matched\n");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS DestMAC Matched\n");
 
-	//classify on ETHType/802.2SAP TLV
-	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo);
+	/* classify on ETHType/802.2SAP TLV */
+	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,
+						      skb,
+						      pstEthCsPktInfo);
 	if (!bClassificationSucceed)
 		return false;
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS EthType/802.2SAP Matched\n");
-
-	//classify on 802.1VLAN Header Parameters
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS EthType/802.2SAP Matched\n");
 
-	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo);
+	/* classify on 802.1VLAN Header Parameters */
+	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,
+						     skb,
+						     pstEthCsPktInfo);
 	if (!bClassificationSucceed)
 		return false;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 VLAN Rules Matched\n");
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"ETH CS 802.1 VLAN Rules Matched\n");
 
 	return bClassificationSucceed;
 }
 
-static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload,
+static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,
+			    PVOID pvEthPayload,
 			    struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
-	USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype);
+	USHORT u16Etype = ntohs(
+			((struct bcm_eth_header *)pvEthPayload)->u16Etype);
 
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"EthCSGetPktInfo : Eth Hdr Type : %X\n",
+			u16Etype);
 	if (u16Etype > 0x5dc) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n");
-		//ETH2 Frame
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"EthCSGetPktInfo : ETH2 Frame\n");
+		/* ETH2 Frame */
 		if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) {
-			//802.1Q VLAN Header
+			/* 802.1Q VLAN Header */
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
 			u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType;
-			//((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
+			/* ((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority */
 		} else {
 			pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
 			u16Etype = ntohs(u16Etype);
 		}
 	} else {
-		//802.2 LLC
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n");
+		/* 802.2 LLC */
+		BCM_DEBUG_PRINT(Adapter,
+				DBG_TYPE_TX,
+				IPV4_DBG,
+				DBG_LVL_ALL,
+				"802.2 LLC Frame\n");
 		pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
-		pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
+		pstEthCsPktInfo->ucDSAP =
+			((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
 		if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) {
-			//SNAP Frame
+			/* SNAP Frame */
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
 			u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
 		}
@@ -768,10 +1178,23 @@ static void EThCSGetPktInfo(struct bcm_m
 		pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
 
 	pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo->eNwpktIPFrameType);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo->eNwpktEthFrameType);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo->usEtherType);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"EthCsPktInfo->eNwpktIPFrameType : %x\n",
+			pstEthCsPktInfo->eNwpktIPFrameType);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"EthCsPktInfo->eNwpktEthFrameType : %x\n",
+			pstEthCsPktInfo->eNwpktEthFrameType);
+	BCM_DEBUG_PRINT(Adapter,
+			DBG_TYPE_TX,
+			IPV4_DBG,
+			DBG_LVL_ALL,
+			"EthCsPktInfo->usEtherType : %x\n",
+			pstEthCsPktInfo->usEtherType);
 }
 
-
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Queue.h linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Queue.h
--- linux-libre-3.16-gnu/drivers/staging/bcm/Queue.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Queue.h	2014-09-28 17:29:07.000000000 -0400
@@ -1,31 +1,29 @@
 /*************************************
-* 	Queue.h
+* Queue.h
 **************************************/
 #ifndef	__QUEUE_H__
 #define	__QUEUE_H__
 
 
 
-#define ENQUEUEPACKET(_Head, _Tail,_Packet)	\
-do						\
-{                                               \
-    if (!_Head) {                           \
-        	_Head = _Packet;                \
-        } 					\
-	else {                                  \
-        	(_Tail)->next = _Packet; 	\
-        }                                       \
-   	(_Packet)->next = NULL;  		\
-    _Tail = _Packet;                        \
-}while(0)
-#define DEQUEUEPACKET(Head, Tail )            	\
-do						\
-{   if(Head)			\
-	{                                            \
-        if (!Head->next) {                      \
-        	Tail = NULL;                    \
-        }                                       \
-        Head = Head->next;                      \
-	}		\
-}while(0)
-#endif	//__QUEUE_H__
+#define ENQUEUEPACKET(_Head, _Tail, _Packet)	\
+do {						\
+	if (!_Head) {				\
+		_Head = _Packet;		\
+	}					\
+	else {					\
+		(_Tail)->next = _Packet;	\
+	}					\
+	(_Packet)->next = NULL;			\
+	_Tail = _Packet;			\
+} while (0)
+#define DEQUEUEPACKET(Head, Tail)		\
+do {						\
+	if (Head) {				\
+		if (!Head->next) {		\
+			Tail = NULL;		\
+		}				\
+		Head = Head->next;		\
+	}					\
+} while (0)
+#endif /* __QUEUE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/TODO linux-libre-3.17-rc7-gnu/drivers/staging/bcm/TODO
--- linux-libre-3.16-gnu/drivers/staging/bcm/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,9 @@
 This driver is barely functional in its current state.
 
+Kevin McKinney(klmckinney1@gmail.com) and Matthias Beyer(mail@beyermatthias.de)
+are currently maintaining/cleaning up this driver.  Please copy us on all
+patches.  More maintainers are aways welcomed.
+
 BIG:
 	- existing API is (/dev/tarang) should be replaced
 	  Is it possible to use same API as Intel Wimax stack and
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/bcm/Transmit.c linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Transmit.c
--- linux-libre-3.16-gnu/drivers/staging/bcm/Transmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/bcm/Transmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,21 +59,27 @@ int SendControlPacket(struct bcm_mini_ad
 
 	/* Update the netdevice statistics */
 	/* Dump Packet  */
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x", PLeader->Vcid);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x", PLeader->PLength);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+			"Leader Status: %x", PLeader->Status);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+			"Leader VCID: %x", PLeader->Vcid);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+			"Leader Length: %x", PLeader->PLength);
 	if (Adapter->device_removed)
 		return 0;
 
 	if (netif_msg_pktdata(Adapter))
 		print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
-			16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);
+			       16, 1, pControlPacket,
+			       PLeader->PLength + LEADER_SIZE, 0);
 
 	Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
-				pControlPacket, (PLeader->PLength + LEADER_SIZE));
+				    pControlPacket,
+				    (PLeader->PLength + LEADER_SIZE));
 
 	atomic_dec(&Adapter->CurrNumFreeTxDesc);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+			"<=========");
 	return STATUS_SUCCESS;
 }
 
@@ -83,12 +89,15 @@ int SendControlPacket(struct bcm_mini_ad
  * to the target via the host h/w interface.
  * @return  zero(success) or -ve value(failure)
  */
-int SetupNextSend(struct bcm_mini_adapter *Adapter,  struct sk_buff *Packet, USHORT Vcid)
+int SetupNextSend(struct bcm_mini_adapter *Adapter,
+		struct sk_buff *Packet, USHORT Vcid)
 {
 	int	status = 0;
 	bool	bHeaderSupressionEnabled = false;
 	B_UINT16 uiClassifierRuleID;
 	u16	QueueIndex = skb_get_queue_mapping(Packet);
+	struct bcm_packet_info *curr_packet_info =
+		&Adapter->PackInfo[QueueIndex];
 	struct bcm_leader Leader = {0};
 
 	if (Packet->len > MAX_DEVICE_DESC_SIZE) {
@@ -97,18 +106,21 @@ int SetupNextSend(struct bcm_mini_adapte
 	}
 
 	/* Get the Classifier Rule ID */
-	uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET);
+	uiClassifierRuleID = *((UINT32 *) (Packet->cb) +
+			       SKB_CB_CLASSIFICATION_OFFSET);
 
-	bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
-		& Adapter->bPHSEnabled;
+	bHeaderSupressionEnabled = curr_packet_info->bHeaderSuppressionEnabled &
+		Adapter->bPHSEnabled;
 
 	if (Adapter->device_removed) {
 		status = STATUS_FAILURE;
 		goto errExit;
 	}
 
-	status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
-			(UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
+	status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID,
+			     bHeaderSupressionEnabled,
+			     (UINT *)&Packet->len,
+			     curr_packet_info->bEthCSSupport);
 
 	if (status != STATUS_SUCCESS) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
@@ -123,12 +135,14 @@ int SetupNextSend(struct bcm_mini_adapte
 	else
 		Leader.Status = LEADER_STATUS;
 
-	if (Adapter->PackInfo[QueueIndex].bEthCSSupport) {
+	if (curr_packet_info->bEthCSSupport) {
 		Leader.PLength = Packet->len;
 		if (skb_headroom(Packet) < LEADER_SIZE) {
 			status = skb_cow(Packet, LEADER_SIZE);
 			if (status) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n");
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND,
+						DBG_LVL_ALL,
+						"bcm_transmit : Failed To Increase headRoom\n");
 				goto errExit;
 			}
 		}
@@ -136,30 +150,36 @@ int SetupNextSend(struct bcm_mini_adapte
 		memcpy(Packet->data, &Leader, LEADER_SIZE);
 	} else {
 		Leader.PLength = Packet->len - ETH_HLEN;
-		memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
+		memcpy((struct bcm_leader *)skb_pull(Packet,
+						     (ETH_HLEN - LEADER_SIZE)),
+			&Leader,
+			LEADER_SIZE);
 	}
 
 	status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
-					Packet->data, (Leader.PLength + LEADER_SIZE));
+					     Packet->data,
+					     (Leader.PLength + LEADER_SIZE));
 	if (status) {
 		++Adapter->dev->stats.tx_errors;
 		if (netif_msg_tx_err(Adapter))
-			pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
+			pr_info(PFX "%s: transmit error %d\n",
+				Adapter->dev->name,
 				status);
 	} else {
 		struct net_device_stats *netstats = &Adapter->dev->stats;
-		Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
+
+		curr_packet_info->uiTotalTxBytes += Leader.PLength;
 
 		netstats->tx_bytes += Leader.PLength;
 		++netstats->tx_packets;
 
-		Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
-		Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
-		Adapter->PackInfo[QueueIndex].uiSentPackets++;
-		Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
+		curr_packet_info->uiCurrentTokenCount -= Leader.PLength << 3;
+		curr_packet_info->uiSentBytes += (Packet->len);
+		curr_packet_info->uiSentPackets++;
+		curr_packet_info->NumOfPacketsSent++;
 
-		atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
-		Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
+		atomic_dec(&curr_packet_info->uiPerSFTxResourceCount);
+		curr_packet_info->uiThisPeriodSentBytes += Leader.PLength;
 	}
 
 	atomic_dec(&Adapter->CurrNumFreeTxDesc);
@@ -172,7 +192,8 @@ errExit:
 static int tx_pending(struct bcm_mini_adapter *Adapter)
 {
 	return (atomic_read(&Adapter->TxPktAvail)
-		&& MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
+		&& MINIMUM_PENDING_DESCRIPTORS <
+			atomic_read(&Adapter->CurrNumFreeTxDesc))
 		|| Adapter->device_removed || (1 == Adapter->downloadDDR);
 }
 
@@ -180,18 +201,21 @@ static int tx_pending(struct bcm_mini_ad
  * @ingroup tx_functions
  * Transmit thread
  */
-int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/)
+int tx_pkt_handler(struct bcm_mini_adapter *Adapter)
 {
 	int status = 0;
 
 	while (!kthread_should_stop()) {
-		/* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
+		/* FIXME - the timeout looks like workaround
+		 *  for racey usage of TxPktAvail
+		*/
 		if (Adapter->LinkUpStatus)
 			wait_event_timeout(Adapter->tx_packet_wait_queue,
-					tx_pending(Adapter), msecs_to_jiffies(10));
+					   tx_pending(Adapter),
+					   msecs_to_jiffies(10));
 		else
 			wait_event_interruptible(Adapter->tx_packet_wait_queue,
-						tx_pending(Adapter));
+						 tx_pending(Adapter));
 
 		if (Adapter->device_removed)
 			break;
@@ -208,7 +232,8 @@ int tx_pkt_handler(struct bcm_mini_adapt
 		if (Adapter->bEndPointHalted == TRUE) {
 			Bcm_clear_halt_of_endpoints(Adapter);
 			Adapter->bEndPointHalted = false;
-			StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+			StartInterruptUrb((struct bcm_interface_adapter *)
+					(Adapter->pvInterfaceAdapter));
 		}
 
 		if (Adapter->LinkUpStatus && !Adapter->IdleMode) {
@@ -225,7 +250,8 @@ int tx_pkt_handler(struct bcm_mini_adapt
 			LinkMessage(Adapter);
 		}
 
-		if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) {
+		if ((Adapter->IdleMode || Adapter->bShutStatus) &&
+				atomic_read(&Adapter->TotalPacketCount)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
 					TX_PACKETS, DBG_LVL_ALL,
 					"Device in Low Power mode...waking up");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/board.c linux-libre-3.17-rc7-gnu/drivers/staging/board/board.c
--- linux-libre-3.16-gnu/drivers/staging/board/board.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/board.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,41 @@
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include "board.h"
+
+static bool find_by_address(u64 base_address)
+{
+	struct device_node *dn = of_find_all_nodes(NULL);
+	struct resource res;
+
+	while (dn) {
+		if (of_can_translate_address(dn)
+		    && !of_address_to_resource(dn, 0, &res)) {
+			if (res.start == base_address) {
+				of_node_put(dn);
+				return true;
+			}
+		}
+		dn = of_find_all_nodes(dn);
+	}
+
+	return false;
+}
+
+bool __init board_staging_dt_node_available(const struct resource *resource,
+					    unsigned int num_resources)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_resources; i++) {
+		const struct resource *r = resource + i;
+
+		if (resource_type(r) == IORESOURCE_MEM)
+			if (find_by_address(r->start))
+				return true; /* DT node available */
+	}
+
+	return false; /* Nothing found */
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/board.h linux-libre-3.17-rc7-gnu/drivers/staging/board/board.h
--- linux-libre-3.16-gnu/drivers/staging/board/board.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/board.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,20 @@
+#ifndef __BOARD_H__
+#define __BOARD_H__
+#include <linux/init.h>
+#include <linux/of.h>
+
+bool board_staging_dt_node_available(const struct resource *resource,
+				     unsigned int num_resources);
+
+#define board_staging(str, fn)			\
+static int __init runtime_board_check(void)	\
+{						\
+	if (of_machine_is_compatible(str))	\
+		fn();				\
+						\
+	return 0;				\
+}						\
+						\
+late_initcall(runtime_board_check)
+
+#endif /* __BOARD_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/board/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/board/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,9 @@
+config STAGING_BOARD
+	boolean "Staging Board Support"
+	depends on OF_ADDRESS
+	depends on BROKEN
+	help
+	  Select to enable per-board staging support code.
+
+	  If in doubt, say N here.
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/kzm9d.c linux-libre-3.17-rc7-gnu/drivers/staging/board/kzm9d.c
--- linux-libre-3.16-gnu/drivers/staging/board/kzm9d.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/kzm9d.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,19 @@
+/* Staging board support for KZM9D. Enable not-yet-DT-capable devices here. */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include "board.h"
+
+static const struct resource usbs1_res[] __initconst = {
+	DEFINE_RES_MEM(0xe2800000, 0x2000),
+	DEFINE_RES_IRQ(159),
+};
+
+static void __init kzm9d_init(void)
+{
+	if (!board_staging_dt_node_available(usbs1_res, ARRAY_SIZE(usbs1_res)))
+		platform_device_register_simple("emxx_udc", -1, usbs1_res,
+						ARRAY_SIZE(usbs1_res));
+}
+
+board_staging("renesas,kzm9d", kzm9d_init);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/board/Makefile
--- linux-libre-3.16-gnu/drivers/staging/board/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2 @@
+obj-y	:= board.o
+obj-$(CONFIG_ARCH_EMEV2)      += kzm9d.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/board/TODO linux-libre-3.17-rc7-gnu/drivers/staging/board/TODO
--- linux-libre-3.16-gnu/drivers/staging/board/TODO	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/board/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,2 @@
+* replace platform device code with DT nodes once the driver supports DT
+* remove staging board code when no more platform devices are needed
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/ced_ioc.c linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/ced_ioc.c
--- linux-libre-3.16-gnu/drivers/staging/ced1401/ced_ioc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/ced_ioc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1494 +0,0 @@
-/* ced_ioc.c
- ioctl part of the 1401 usb device driver for linux.
- Copyright (C) 2010 Cambridge Electronic Design Ltd
- Author Greg P Smith (greg@ced.co.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/page-flags.h>
-#include <linux/pagemap.h>
-#include <linux/jiffies.h>
-
-#include "usb1401.h"
-
-/****************************************************************************
-** FlushOutBuff
-**
-** Empties the Output buffer and sets int lines. Used from user level only
-****************************************************************************/
-static void FlushOutBuff(DEVICE_EXTENSION *pdx)
-{
-	dev_dbg(&pdx->interface->dev, "%s: currentState=%d\n",
-		__func__, pdx->sCurrentState);
-	if (pdx->sCurrentState == U14ERR_TIME)	/* Do nothing if hardware in trouble */
-		return;
-	/* Kill off any pending I/O */
-	/* CharSend_Cancel(pdx);  */
-	spin_lock_irq(&pdx->charOutLock);
-	pdx->dwNumOutput = 0;
-	pdx->dwOutBuffGet = 0;
-	pdx->dwOutBuffPut = 0;
-	spin_unlock_irq(&pdx->charOutLock);
-}
-
-/****************************************************************************
-**
-** FlushInBuff
-**
-** Empties the input buffer and sets int lines
-****************************************************************************/
-static void FlushInBuff(DEVICE_EXTENSION *pdx)
-{
-	dev_dbg(&pdx->interface->dev, "%s: currentState=%d\n",
-		__func__, pdx->sCurrentState);
-	if (pdx->sCurrentState == U14ERR_TIME)	/* Do nothing if hardware in trouble */
-		return;
-	/* Kill off any pending I/O */
-	/*     CharRead_Cancel(pDevObject);  */
-	spin_lock_irq(&pdx->charInLock);
-	pdx->dwNumInput = 0;
-	pdx->dwInBuffGet = 0;
-	pdx->dwInBuffPut = 0;
-	spin_unlock_irq(&pdx->charInLock);
-}
-
-/****************************************************************************
-** PutChars
-**
-** Utility routine to copy chars into the output buffer and fire them off.
-** called from user mode, holds charOutLock.
-****************************************************************************/
-static int PutChars(DEVICE_EXTENSION *pdx, const char *pCh,
-		    unsigned int uCount)
-{
-	int iReturn;
-	spin_lock_irq(&pdx->charOutLock);	/*  get the output spin lock */
-	if ((OUTBUF_SZ - pdx->dwNumOutput) >= uCount) {
-		unsigned int u;
-		for (u = 0; u < uCount; u++) {
-			pdx->outputBuffer[pdx->dwOutBuffPut++] = pCh[u];
-			if (pdx->dwOutBuffPut >= OUTBUF_SZ)
-				pdx->dwOutBuffPut = 0;
-		}
-		pdx->dwNumOutput += uCount;
-		spin_unlock_irq(&pdx->charOutLock);
-		iReturn = SendChars(pdx);	/*  ...give a chance to transmit data */
-	} else {
-		iReturn = U14ERR_NOOUT;	/*  no room at the out (ha-ha) */
-		spin_unlock_irq(&pdx->charOutLock);
-	}
-	return iReturn;
-}
-
-/*****************************************************************************
-** Add the data in pData (local pointer) of length n to the output buffer, and
-** trigger an output transfer if this is appropriate. User mode.
-** Holds the io_mutex
-*****************************************************************************/
-int SendString(DEVICE_EXTENSION *pdx, const char __user *pData,
-	       unsigned int n)
-{
-	int iReturn = U14ERR_NOERROR;	/*  assume all will be well */
-	char buffer[OUTBUF_SZ + 1];	/*  space in our address space for characters */
-	if (n > OUTBUF_SZ)	/*  check space in local buffer... */
-		return U14ERR_NOOUT;	/*  ...too many characters */
-	if (copy_from_user(buffer, pData, n))
-		return -EFAULT;
-	buffer[n] = 0;		/*  terminate for debug purposes */
-
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	if (n > 0) {		/*  do nothing if nowt to do! */
-		dev_dbg(&pdx->interface->dev, "%s: n=%d>%s<\n",
-			__func__, n, buffer);
-		iReturn = PutChars(pdx, buffer, n);
-	}
-
-	Allowi(pdx);		/*  make sure we have input int */
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** SendChar
-**
-** Sends a single character to the 1401. User mode, holds io_mutex.
-****************************************************************************/
-int SendChar(DEVICE_EXTENSION *pdx, char c)
-{
-	int iReturn;
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	iReturn = PutChars(pdx, &c, 1);
-	dev_dbg(&pdx->interface->dev, "SendChar >%c< (0x%02x)\n", c, c);
-	Allowi(pdx);	/*  Make sure char reads are running */
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/***************************************************************************
-**
-** Get1401State
-**
-**  Retrieves state information from the 1401, adjusts the 1401 state held
-**  in the device extension to indicate the current 1401 type.
-**
-**  *state is updated with information about the 1401 state as returned by the
-**         1401. The low byte is a code for what 1401 is doing:
-**
-**  0       normal 1401 operation
-**  1       sending chars to host
-**  2       sending block data to host
-**  3       reading block data from host
-**  4       sending an escape sequence to the host
-**  0x80    1401 is executing self-test, in which case the upper word
-**          is the last error code seen (or zero for no new error).
-**
-** *error is updated with error information if a self-test error code
-**          is returned in the upper word of state.
-**
-**  both state and error are set to -1 if there are comms problems, and
-**  to zero if there is a simple failure.
-**
-** return error code (U14ERR_NOERROR for OK)
-*/
-int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error)
-{
-	int nGot;
-	dev_dbg(&pdx->interface->dev, "%s: entry\n", __func__);
-
-	*state = 0xFFFFFFFF;	/*  Start off with invalid state */
-	nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
-			       GET_STATUS, (D_TO_H | VENDOR | DEVREQ), 0, 0,
-			       pdx->statBuf, sizeof(pdx->statBuf), HZ);
-	if (nGot != sizeof(pdx->statBuf)) {
-		dev_err(&pdx->interface->dev,
-			"%s: FAILED, return code %d\n", __func__, nGot);
-		pdx->sCurrentState = U14ERR_TIME;	/*  Indicate that things are very wrong indeed */
-		*state = 0;	/*  Force status values to a known state */
-		*error = 0;
-	} else {
-		int nDevice;
-		dev_dbg(&pdx->interface->dev,
-			"%s: Success, state: 0x%x, 0x%x\n",
-			__func__, pdx->statBuf[0], pdx->statBuf[1]);
-
-		*state = pdx->statBuf[0];	/*  Return the state values to the calling code */
-		*error = pdx->statBuf[1];
-
-		nDevice = pdx->udev->descriptor.bcdDevice >> 8;	/*  1401 type code value */
-		switch (nDevice) {	/*  so we can clean up current state */
-		case 0:
-			pdx->sCurrentState = U14ERR_U1401;
-			break;
-
-		default:	/*  allow lots of device codes for future 1401s */
-			if ((nDevice >= 1) && (nDevice <= 23))
-				pdx->sCurrentState = (short)(nDevice + 6);
-			else
-				pdx->sCurrentState = U14ERR_ILL;
-			break;
-		}
-	}
-
-	return pdx->sCurrentState >= 0 ? U14ERR_NOERROR : pdx->sCurrentState;
-}
-
-/****************************************************************************
-** ReadWrite_Cancel
-**
-** Kills off staged read\write request from the USB if one is pending.
-****************************************************************************/
-int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
-{
-	dev_dbg(&pdx->interface->dev, "%s: entry %d\n",
-		__func__, pdx->bStagedUrbPending);
-#ifdef NOT_WRITTEN_YET
-	int ntStatus = STATUS_SUCCESS;
-	bool bResult = false;
-	unsigned int i;
-	/*  We can fill this in when we know how we will implement the staged transfer stuff */
-	spin_lock_irq(&pdx->stagedLock);
-
-	if (pdx->bStagedUrbPending) {	/*  anything to be cancelled? May need more... */
-		dev_info(&pdx->interface - dev,
-			 "ReadWrite_Cancel about to cancel Urb\n");
-		/* Clear the staging done flag */
-		/* KeClearEvent(&pdx->StagingDoneEvent); */
-		USB_ASSERT(pdx->pStagedIrp != NULL);
-
-		/*  Release the spinlock first otherwise the completion routine may hang */
-		/*   on the spinlock while this function hands waiting for the event. */
-		spin_unlock_irq(&pdx->stagedLock);
-		bResult = IoCancelIrp(pdx->pStagedIrp);	/*  Actually do the cancel */
-		if (bResult) {
-			LARGE_INTEGER timeout;
-			timeout.QuadPart = -10000000;	/*  Use a timeout of 1 second */
-			dev_info(&pdx->interface - dev,
-				 "%s: about to wait till done\n", __func__);
-			ntStatus =
-			    KeWaitForSingleObject(&pdx->StagingDoneEvent,
-						  Executive, KernelMode, FALSE,
-						  &timeout);
-		} else {
-			dev_info(&pdx->interface - dev,
-				 "%s: cancellation failed\n", __func__);
-			ntStatus = U14ERR_FAIL;
-		}
-		USB_KdPrint(DBGLVL_DEFAULT,
-			    ("ReadWrite_Cancel ntStatus = 0x%x decimal %d\n",
-			     ntStatus, ntStatus));
-	} else
-		spin_unlock_irq(&pdx->stagedLock);
-
-	dev_info(&pdx->interface - dev, "%s: done\n", __func__);
-	return ntStatus;
-#else
-	return U14ERR_NOERROR;
-#endif
-
-}
-
-/***************************************************************************
-** InSelfTest - utility to check in self test. Return 1 for ST, 0 for not or
-** a -ve error code if we failed for some reason.
-***************************************************************************/
-static int InSelfTest(DEVICE_EXTENSION *pdx, unsigned int *pState)
-{
-	unsigned int state, error;
-	int iReturn = Get1401State(pdx, &state, &error);	/*  see if in self-test */
-	if (iReturn == U14ERR_NOERROR)	/*  if all still OK */
-		iReturn = (state == (unsigned int)-1) ||	/*  TX problem or... */
-		    ((state & 0xff) == 0x80);	/*  ...self test */
-	*pState = state;	/*  return actual state */
-	return iReturn;
-}
-
-/***************************************************************************
-** Is1401 - ALWAYS CALLED HOLDING THE io_mutex
-**
-** Tests for the current state of the 1401. Sets sCurrentState:
-**
-**  U14ERR_NOIF  1401  i/f card not installed (not done here)
-**  U14ERR_OFF   1401  apparently not switched on
-**  U14ERR_NC    1401  appears to be not connected
-**  U14ERR_ILL   1401  if it is there its not very well at all
-**  U14ERR_TIME  1401  appears OK, but doesn't communicate - very bad
-**  U14ERR_STD   1401  OK and ready for use
-**  U14ERR_PLUS  1401+ OK and ready for use
-**  U14ERR_U1401 Micro1401 OK and ready for use
-**  U14ERR_POWER Power1401 OK and ready for use
-**  U14ERR_U14012 Micro1401 mkII OK and ready for use
-**
-**  Returns TRUE if a 1401 detected and OK, else FALSE
-****************************************************************************/
-bool Is1401(DEVICE_EXTENSION *pdx)
-{
-	int iReturn;
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	ced_draw_down(pdx);	/*  wait for, then kill outstanding Urbs */
-	FlushInBuff(pdx);	/*  Clear out input buffer & pipe */
-	FlushOutBuff(pdx);	/*  Clear output buffer & pipe */
-
-	/*  The next call returns 0 if OK, but has returned 1 in the past, meaning that */
-	/*  usb_unlock_device() is needed... now it always is */
-	iReturn = usb_lock_device_for_reset(pdx->udev, pdx->interface);
-
-	/*  release the io_mutex because if we don't, we will deadlock due to system */
-	/*  calls back into the driver. */
-	mutex_unlock(&pdx->io_mutex);	/*  locked, so we will not get system calls */
-	if (iReturn >= 0) {	/*  if we failed */
-		iReturn = usb_reset_device(pdx->udev);	/*  try to do the reset */
-		usb_unlock_device(pdx->udev);	/*  undo the lock */
-	}
-
-	mutex_lock(&pdx->io_mutex);	/*  hold stuff off while we wait */
-	pdx->dwDMAFlag = MODE_CHAR;	/*  Clear DMA mode flag regardless! */
-	if (iReturn == 0) {	/*  if all is OK still */
-		unsigned int state;
-		iReturn = InSelfTest(pdx, &state);	/*  see if likely in self test */
-		if (iReturn > 0) {	/*  do we need to wait for self-test? */
-			unsigned long ulTimeOut = jiffies + 30 * HZ;	/*  when to give up */
-			while ((iReturn > 0) && time_before(jiffies, ulTimeOut)) {
-				schedule();	/*  let other stuff run */
-				iReturn = InSelfTest(pdx, &state);	/*  see if done yet */
-			}
-		}
-
-		if (iReturn == 0)	/*  if all is OK... */
-			iReturn = state == 0;	/*  then success is that the state is 0 */
-	} else
-		iReturn = 0;	/*  we failed */
-	pdx->bForceReset = false;	/*  Clear forced reset flag now */
-
-	return iReturn > 0;
-}
-
-/****************************************************************************
-** QuickCheck  - ALWAYS CALLED HOLDING THE io_mutex
-** This is used to test for a 1401. It will try to do a quick check if all is
-**  OK, that is the 1401 was OK the last time it was asked, and there is no DMA
-**  in progress, and if the bTestBuff flag is set, the character buffers must be
-**  empty too. If the quick check shows that the state is still the same, then
-**  all is OK.
-**
-** If any of the above conditions are not met, or if the state or type of the
-**  1401 has changed since the previous test, the full Is1401 test is done, but
-**  only if bCanReset is also TRUE.
-**
-** The return value is TRUE if a useable 1401 is found, FALSE if not
-*/
-bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset)
-{
-	bool bRet = false;	/*  assume it will fail and we will reset */
-	bool bShortTest;
-
-	bShortTest = ((pdx->dwDMAFlag == MODE_CHAR) &&	/*  no DMA running */
-		      (!pdx->bForceReset) &&	/*  Not had a real reset forced */
-		      (pdx->sCurrentState >= U14ERR_STD));	/*  No 1401 errors stored */
-
-	dev_dbg(&pdx->interface->dev,
-		"%s: DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d\n",
-		__func__, pdx->dwDMAFlag, pdx->sCurrentState, pdx->bForceReset,
-		bTestBuff, bShortTest);
-
-	if ((bTestBuff) &&	/*  Buffer check requested, and... */
-	    (pdx->dwNumInput || pdx->dwNumOutput)) {	/*  ...characters were in the buffer? */
-		bShortTest = false;	/*  Then do the full test */
-		dev_dbg(&pdx->interface->dev,
-			"%s: will reset as buffers not empty\n", __func__);
-	}
-
-	if (bShortTest || !bCanReset) {	/*  Still OK to try the short test? */
-				/*  Always test if no reset - we want state update */
-		unsigned int state, error;
-		dev_dbg(&pdx->interface->dev, "%s: Get1401State\n", __func__);
-		if (Get1401State(pdx, &state, &error) == U14ERR_NOERROR) {	/*  Check on the 1401 state */
-			if ((state & 0xFF) == 0)	/*  If call worked, check the status value */
-				bRet = true;	/*  If that was zero, all is OK, no reset needed */
-		}
-	}
-
-	if (!bRet && bCanReset)	{ /*  If all not OK, then */
-		dev_info(&pdx->interface->dev, "%s: Is1401 %d %d %d %d\n",
-			 __func__, bShortTest, pdx->sCurrentState, bTestBuff,
-			 pdx->bForceReset);
-		bRet = Is1401(pdx);	/*   do full test */
-	}
-
-	return bRet;
-}
-
-/****************************************************************************
-** Reset1401
-**
-** Resets the 1401 and empties the i/o buffers
-*****************************************************************************/
-int Reset1401(DEVICE_EXTENSION *pdx)
-{
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	dev_dbg(&pdx->interface->dev, "%s: About to call QuickCheck\n",
-		__func__);
-	QuickCheck(pdx, true, true);	/*  Check 1401, reset if not OK */
-	mutex_unlock(&pdx->io_mutex);
-	return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** GetChar
-**
-** Gets a single character from the 1401
-****************************************************************************/
-int GetChar(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = U14ERR_NOIN;	/*  assume we will get  nothing */
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	Allowi(pdx);	/*  Make sure char reads are running */
-	SendChars(pdx);	/*  and send any buffered chars */
-
-	spin_lock_irq(&pdx->charInLock);
-	if (pdx->dwNumInput > 0) {	/*  worth looking */
-		iReturn = pdx->inputBuffer[pdx->dwInBuffGet++];
-		if (pdx->dwInBuffGet >= INBUF_SZ)
-			pdx->dwInBuffGet = 0;
-		pdx->dwNumInput--;
-	} else
-		iReturn = U14ERR_NOIN;	/*  no input data to read */
-	spin_unlock_irq(&pdx->charInLock);
-
-	Allowi(pdx);	/*  Make sure char reads are running */
-
-	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	return iReturn;
-}
-
-/****************************************************************************
-** GetString
-**
-** Gets a string from the 1401. Returns chars up to the next CR or when
-** there are no more to read or nowhere to put them. CR is translated to
-** 0 and counted as a character. If the string does not end in a 0, we will
-** add one, if there is room, but it is not counted as a character.
-**
-** returns the count of characters (including the terminator, or 0 if none
-** or a negative error code.
-****************************************************************************/
-int GetString(DEVICE_EXTENSION *pdx, char __user *pUser, int n)
-{
-	int nAvailable;		/*  character in the buffer */
-	int iReturn = U14ERR_NOIN;
-	if (n <= 0)
-		return -ENOMEM;
-
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	Allowi(pdx);	/*  Make sure char reads are running */
-	SendChars(pdx);		/*  and send any buffered chars */
-
-	spin_lock_irq(&pdx->charInLock);
-	nAvailable = pdx->dwNumInput;	/*  characters available now */
-	if (nAvailable > n)	/*  read max of space in pUser... */
-		nAvailable = n;	/*  ...or input characters */
-
-	if (nAvailable > 0) {	/*  worth looking? */
-		char buffer[INBUF_SZ + 1];	/*  space for a linear copy of data */
-		int nGot = 0;
-		int nCopyToUser;	/*  number to copy to user */
-		char cData;
-		do {
-			cData = pdx->inputBuffer[pdx->dwInBuffGet++];
-			if (cData == CR_CHAR)	/*  replace CR with zero */
-				cData = (char)0;
-
-			if (pdx->dwInBuffGet >= INBUF_SZ)
-				pdx->dwInBuffGet = 0;	/*  wrap buffer pointer */
-
-			buffer[nGot++] = cData;	/*  save the output */
-		} while ((nGot < nAvailable) && cData);
-
-		nCopyToUser = nGot;	/*  what to copy... */
-		if (cData) {	/*  do we need null */
-			buffer[nGot] = (char)0;	/*  make it tidy */
-			if (nGot < n)	/*  if space in user buffer... */
-				++nCopyToUser;	/*  ...copy the 0 as well. */
-		}
-
-		pdx->dwNumInput -= nGot;
-		spin_unlock_irq(&pdx->charInLock);
-
-		dev_dbg(&pdx->interface->dev, "%s: read %d characters >%s<\n",
-			__func__, nGot, buffer);
-		if (copy_to_user(pUser, buffer, nCopyToUser))
-			iReturn = -EFAULT;
-		else
-			iReturn = nGot;		/*  report characters read */
-	} else
-		spin_unlock_irq(&pdx->charInLock);
-
-	Allowi(pdx);	/*  Make sure char reads are running */
-	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-
-	return iReturn;
-}
-
-/*******************************************************************************
-** Get count of characters in the inout buffer.
-*******************************************************************************/
-int Stat1401(DEVICE_EXTENSION *pdx)
-{
-	int iReturn;
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	Allowi(pdx);		/*  make sure we allow pending chars */
-	SendChars(pdx);		/*  in both directions */
-	iReturn = pdx->dwNumInput;	/*  no lock as single read */
-	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	return iReturn;
-}
-
-/****************************************************************************
-** LineCount
-**
-** Returns the number of newline chars in the buffer. There is no need for
-** any fancy interlocks as we only read the interrupt routine data, and the
-** system is arranged so nothing can be destroyed.
-****************************************************************************/
-int LineCount(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = 0;	/*  will be count of line ends */
-
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	Allowi(pdx);		/*  Make sure char reads are running */
-	SendChars(pdx);		/*  and send any buffered chars */
-	spin_lock_irq(&pdx->charInLock);	/*  Get protection */
-
-	if (pdx->dwNumInput > 0) {	/*  worth looking? */
-		unsigned int dwIndex = pdx->dwInBuffGet;	/*  start at first available */
-		unsigned int dwEnd = pdx->dwInBuffPut;	/*  Position for search end */
-		do {
-			if (pdx->inputBuffer[dwIndex++] == CR_CHAR)
-				++iReturn;	/*  inc count if CR */
-
-			if (dwIndex >= INBUF_SZ)	/*  see if we fall off buff */
-				dwIndex = 0;
-		} while (dwIndex != dwEnd);	/*  go to last available */
-	}
-
-	spin_unlock_irq(&pdx->charInLock);
-	dev_dbg(&pdx->interface->dev, "%s: returned %d\n", __func__, iReturn);
-	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	return iReturn;
-}
-
-/****************************************************************************
-** GetOutBufSpace
-**
-** Gets the space in the output buffer. Called from user code.
-*****************************************************************************/
-int GetOutBufSpace(DEVICE_EXTENSION *pdx)
-{
-	int iReturn;
-	mutex_lock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	SendChars(pdx);		/*  send any buffered chars */
-	iReturn = (int)(OUTBUF_SZ - pdx->dwNumOutput);	/*  no lock needed for single read */
-	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
-	mutex_unlock(&pdx->io_mutex);	/*  Protect disconnect from new i/o */
-	return iReturn;
-}
-
-/****************************************************************************
-**
-** ClearArea
-**
-** Clears up a transfer area. This is always called in the context of a user
-** request, never from a call-back.
-****************************************************************************/
-int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
-{
-	int iReturn = U14ERR_NOERROR;
-
-	if ((nArea < 0) || (nArea >= MAX_TRANSAREAS)) {
-		iReturn = U14ERR_BADAREA;
-		dev_err(&pdx->interface->dev, "%s: Attempt to clear area %d\n",
-			__func__, nArea);
-	} else {
-		TRANSAREA *pTA = &pdx->rTransDef[nArea];	/*  to save typing */
-		if (!pTA->bUsed)	/*  if not used... */
-			iReturn = U14ERR_NOTSET;	/*  ...nothing to be done */
-		else {
-			/*  We must save the memory we return as we shouldn't mess with memory while */
-			/*  holding a spin lock. */
-			struct page **pPages = NULL; /*save page address list*/
-			int nPages = 0;	/*  and number of pages */
-			int np;
-
-			dev_dbg(&pdx->interface->dev, "%s: area %d\n",
-				__func__, nArea);
-			spin_lock_irq(&pdx->stagedLock);
-			if ((pdx->StagedId == nArea)
-			    && (pdx->dwDMAFlag > MODE_CHAR)) {
-				iReturn = U14ERR_UNLOCKFAIL;	/*  cannot delete as in use */
-				dev_err(&pdx->interface->dev,
-					"%s: call on area %d while active\n",
-					__func__, nArea);
-			} else {
-				pPages = pTA->pPages;	/*  save page address list */
-				nPages = pTA->nPages;	/*  and page count */
-				if (pTA->dwEventSz)	/*  if events flagging in use */
-					wake_up_interruptible(&pTA->wqEvent);	/*  release anything that was waiting */
-
-				if (pdx->bXFerWaiting
-				    && (pdx->rDMAInfo.wIdent == nArea))
-					pdx->bXFerWaiting = false;	/*  Cannot have pending xfer if area cleared */
-
-				/*  Clean out the TRANSAREA except for the wait queue, which is at the end */
-				/*  This sets bUsed to false and dwEventSz to 0 to say area not used and no events. */
-				memset(pTA, 0,
-				       sizeof(TRANSAREA) -
-				       sizeof(wait_queue_head_t));
-			}
-			spin_unlock_irq(&pdx->stagedLock);
-
-			if (pPages) {	/*  if we decided to release the memory */
-				/*  Now we must undo the pinning down of the pages. We will assume the worst and mark */
-				/*  all the pages as dirty. Don't be tempted to move this up above as you must not be */
-				/*  holding a spin lock to do this stuff as it is not atomic. */
-				dev_dbg(&pdx->interface->dev, "%s: nPages=%d\n",
-					__func__, nPages);
-
-				for (np = 0; np < nPages; ++np) {
-					if (pPages[np]) {
-						SetPageDirty(pPages[np]);
-						page_cache_release(pPages[np]);
-					}
-				}
-
-				kfree(pPages);
-				dev_dbg(&pdx->interface->dev,
-					"%s: kfree(pPages) done\n", __func__);
-			}
-		}
-	}
-
-	return iReturn;
-}
-
-/****************************************************************************
-** SetArea
-**
-** Sets up a transfer area - the functional part. Called by both
-** SetTransfer and SetCircular.
-****************************************************************************/
-static int SetArea(DEVICE_EXTENSION *pdx, int nArea, char __user *puBuf,
-		   unsigned int dwLength, bool bCircular, bool bCircToHost)
-{
-	/*  Start by working out the page aligned start of the area and the size */
-	/*  of the area in pages, allowing for the start not being aligned and the */
-	/*  end needing to be rounded up to a page boundary. */
-	unsigned long ulStart = ((unsigned long)puBuf) & PAGE_MASK;
-	unsigned int ulOffset = ((unsigned long)puBuf) & (PAGE_SIZE - 1);
-	int len = (dwLength + ulOffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	TRANSAREA *pTA = &pdx->rTransDef[nArea];	/*  to save typing */
-	struct page **pPages = NULL;	/*  space for page tables */
-	int nPages = 0;		/*  and number of pages */
-
-	int iReturn = ClearArea(pdx, nArea);	/*  see if OK to use this area */
-	if ((iReturn != U14ERR_NOTSET) &&	/*  if not area unused and... */
-	    (iReturn != U14ERR_NOERROR))	/*  ...not all OK, then... */
-		return iReturn;	/*  ...we cannot use this area */
-
-	if (!access_ok(VERIFY_WRITE, puBuf, dwLength))	/*  if we cannot access the memory... */
-		return -EFAULT;	/*  ...then we are done */
-
-	/*  Now allocate space to hold the page pointer and virtual address pointer tables */
-	pPages = kmalloc(len * sizeof(struct page *), GFP_KERNEL);
-	if (!pPages) {
-		iReturn = U14ERR_NOMEMORY;
-		goto error;
-	}
-	dev_dbg(&pdx->interface->dev, "%s: %p, length=%06x, circular %d\n",
-		__func__, puBuf, dwLength, bCircular);
-
-	/*  To pin down user pages we must first acquire the mapping semaphore. */
-	nPages = get_user_pages_fast(ulStart, len, 1, pPages);
-	dev_dbg(&pdx->interface->dev, "%s: nPages = %d\n", __func__, nPages);
-
-	if (nPages > 0) {		/*  if we succeeded */
-		/*  If you are tempted to use page_address (form LDD3), forget it. You MUST use */
-		/*  kmap() or kmap_atomic() to get a virtual address. page_address will give you */
-		/*  (null) or at least it does in this context with an x86 machine. */
-		spin_lock_irq(&pdx->stagedLock);
-		pTA->lpvBuff = puBuf;	/*  keep start of region (user address) */
-		pTA->dwBaseOffset = ulOffset;	/*  save offset in first page to start of xfer */
-		pTA->dwLength = dwLength;	/*  Size if the region in bytes */
-		pTA->pPages = pPages;	/*  list of pages that are used by buffer */
-		pTA->nPages = nPages;	/*  number of pages */
-
-		pTA->bCircular = bCircular;
-		pTA->bCircToHost = bCircToHost;
-
-		pTA->aBlocks[0].dwOffset = 0;
-		pTA->aBlocks[0].dwSize = 0;
-		pTA->aBlocks[1].dwOffset = 0;
-		pTA->aBlocks[1].dwSize = 0;
-		pTA->bUsed = true;	/*  This is now a used block */
-
-		spin_unlock_irq(&pdx->stagedLock);
-		iReturn = U14ERR_NOERROR;	/*  say all was well */
-	} else {
-		iReturn = U14ERR_LOCKFAIL;
-		goto error;
-	}
-
-	return iReturn;
-
-error:
-	kfree(pPages);
-	return iReturn;
-}
-
-/****************************************************************************
-** SetTransfer
-**
-** Sets up a transfer area record. If the area is already set, we attempt to
-** unset it. Unsetting will fail if the area is booked, and a transfer to that
-** area is in progress. Otherwise, we will release the area and re-assign it.
-****************************************************************************/
-int SetTransfer(DEVICE_EXTENSION *pdx, struct transfer_area_desc __user *pTD)
-{
-	int iReturn;
-	struct transfer_area_desc td;
-
-	if (copy_from_user(&td, pTD, sizeof(td)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: area:%d, size:%08x\n",
-		__func__, td.wAreaNum, td.dwLength);
-	/*  The strange cast is done so that we don't get warnings in 32-bit linux about the size of the */
-	/*  pointer. The pointer is always passed as a 64-bit object so that we don't have problems using */
-	/*  a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system. */
-	iReturn =
-	    SetArea(pdx, td.wAreaNum,
-		    (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
-		    false, false);
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/****************************************************************************
-** UnSetTransfer
-** Erases a transfer area record
-****************************************************************************/
-int UnsetTransfer(DEVICE_EXTENSION *pdx, int nArea)
-{
-	int iReturn;
-	mutex_lock(&pdx->io_mutex);
-	iReturn = ClearArea(pdx, nArea);
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/****************************************************************************
-** SetEvent
-** Creates an event that we can test for based on a transfer to/from an area.
-** The area must be setup for a transfer. We attempt to simulate the Windows
-** driver behavior for events (as we don't actually use them), which is to
-** pretend that whatever the user asked for was achieved, so we return 1 if
-** try to create one, and 0 if they ask to remove (assuming all else was OK).
-****************************************************************************/
-int SetEvent(DEVICE_EXTENSION *pdx, struct transfer_event __user *pTE)
-{
-	int iReturn = U14ERR_NOERROR;
-	struct transfer_event te;
-
-	/*  get a local copy of the data */
-	if (copy_from_user(&te, pTE, sizeof(te)))
-		return -EFAULT;
-
-	if (te.wAreaNum >= MAX_TRANSAREAS)	/*  the area must exist */
-		return U14ERR_BADAREA;
-	else {
-		TRANSAREA *pTA = &pdx->rTransDef[te.wAreaNum];
-		mutex_lock(&pdx->io_mutex);	/*  make sure we have no competitor */
-		spin_lock_irq(&pdx->stagedLock);
-		if (pTA->bUsed) {	/*  area must be in use */
-			pTA->dwEventSt = te.dwStart;	/*  set area regions */
-			pTA->dwEventSz = te.dwLength;	/*  set size (0 cancels it) */
-			pTA->bEventToHost = te.wFlags & 1;	/*  set the direction */
-			pTA->iWakeUp = 0;	/*  zero the wake up count */
-		} else
-			iReturn = U14ERR_NOTSET;
-		spin_unlock_irq(&pdx->stagedLock);
-		mutex_unlock(&pdx->io_mutex);
-	}
-	return iReturn ==
-	    U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : iReturn;
-}
-
-/****************************************************************************
-** WaitEvent
-** Sleep the process with a timeout waiting for an event. Returns the number
-** of times that a block met the event condition since we last cleared it or
-** 0 if timed out, or -ve error (bad area or not set, or signal).
-****************************************************************************/
-int WaitEvent(DEVICE_EXTENSION *pdx, int nArea, int msTimeOut)
-{
-	int iReturn;
-	if ((unsigned)nArea >= MAX_TRANSAREAS)
-		return U14ERR_BADAREA;
-	else {
-		int iWait;
-		TRANSAREA *pTA = &pdx->rTransDef[nArea];
-		msTimeOut = (msTimeOut * HZ + 999) / 1000;	/*  convert timeout to jiffies */
-
-		/*  We cannot wait holding the mutex, but we check the flags while holding */
-		/*  it. This may well be pointless as another thread could get in between */
-		/*  releasing it and the wait call. However, this would have to clear the */
-		/*  iWakeUp flag. However, the !pTA-bUsed may help us in this case. */
-		mutex_lock(&pdx->io_mutex);	/*  make sure we have no competitor */
-		if (!pTA->bUsed || !pTA->dwEventSz)	/*  check something to wait for... */
-			return U14ERR_NOTSET;	/*  ...else we do nothing */
-		mutex_unlock(&pdx->io_mutex);
-
-		if (msTimeOut)
-			iWait =
-			    wait_event_interruptible_timeout(pTA->wqEvent,
-							     pTA->iWakeUp
-							     || !pTA->bUsed,
-							     msTimeOut);
-		else
-			iWait =
-			    wait_event_interruptible(pTA->wqEvent, pTA->iWakeUp
-						     || !pTA->bUsed);
-		if (iWait)
-			iReturn = -ERESTARTSYS;	/*  oops - we have had a SIGNAL */
-		else
-			iReturn = pTA->iWakeUp;	/*  else the wakeup count */
-
-		spin_lock_irq(&pdx->stagedLock);
-		pTA->iWakeUp = 0;	/*  clear the flag */
-		spin_unlock_irq(&pdx->stagedLock);
-	}
-	return iReturn;
-}
-
-/****************************************************************************
-** TestEvent
-** Test the event to see if a WaitEvent would return immediately. Returns the
-** number of times a block completed since the last call, or 0 if none or a
-** negative error.
-****************************************************************************/
-int TestEvent(DEVICE_EXTENSION *pdx, int nArea)
-{
-	int iReturn;
-	if ((unsigned)nArea >= MAX_TRANSAREAS)
-		iReturn = U14ERR_BADAREA;
-	else {
-		TRANSAREA *pTA = &pdx->rTransDef[nArea];
-		mutex_lock(&pdx->io_mutex);	/*  make sure we have no competitor */
-		spin_lock_irq(&pdx->stagedLock);
-		iReturn = pTA->iWakeUp;	/*  get wakeup count since last call */
-		pTA->iWakeUp = 0;	/*  clear the count */
-		spin_unlock_irq(&pdx->stagedLock);
-		mutex_unlock(&pdx->io_mutex);
-	}
-	return iReturn;
-}
-
-/****************************************************************************
-** GetTransferInfo
-** Puts the current state of the 1401 in a TGET_TX_BLOCK.
-*****************************************************************************/
-int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pTX)
-{
-	int iReturn = U14ERR_NOERROR;
-	unsigned int dwIdent;
-
-	mutex_lock(&pdx->io_mutex);
-	dwIdent = pdx->StagedId;	/*  area ident for last xfer */
-	if (dwIdent >= MAX_TRANSAREAS)
-		iReturn = U14ERR_BADAREA;
-	else {
-		/*  Return the best information we have - we don't have physical addresses */
-		TGET_TX_BLOCK *tx;
-
-		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
-		if (!tx) {
-			mutex_unlock(&pdx->io_mutex);
-			return -ENOMEM;
-		}
-		tx->size = pdx->rTransDef[dwIdent].dwLength;
-		tx->linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
-		tx->avail = GET_TX_MAXENTRIES;	/*  how many blocks we could return */
-		tx->used = 1;	/*  number we actually return */
-		tx->entries[0].physical =
-		    (long long)(tx->linear + pdx->StagedOffset);
-		tx->entries[0].size = tx->size;
-
-		if (copy_to_user(pTX, tx, sizeof(*tx)))
-			iReturn = -EFAULT;
-		kfree(tx);
-	}
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/****************************************************************************
-** KillIO1401
-**
-** Empties the host i/o buffers
-****************************************************************************/
-int KillIO1401(DEVICE_EXTENSION *pdx)
-{
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-	mutex_lock(&pdx->io_mutex);
-	FlushOutBuff(pdx);
-	FlushInBuff(pdx);
-	mutex_unlock(&pdx->io_mutex);
-	return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** BlkTransState
-** Returns a 0 or a 1 for whether DMA is happening. No point holding a mutex
-** for this as it only does one read.
-*****************************************************************************/
-int BlkTransState(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = pdx->dwDMAFlag != MODE_CHAR;
-	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
-	return iReturn;
-}
-
-/****************************************************************************
-** StateOf1401
-**
-** Puts the current state of the 1401 in the Irp return buffer.
-*****************************************************************************/
-int StateOf1401(DEVICE_EXTENSION *pdx)
-{
-	int iReturn;
-	mutex_lock(&pdx->io_mutex);
-
-	QuickCheck(pdx, false, false);	/*  get state up to date, no reset */
-	iReturn = pdx->sCurrentState;
-
-	mutex_unlock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: %d\n", __func__, iReturn);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** StartSelfTest
-**
-** Initiates a self-test cycle. The assumption is that we have no interrupts
-** active, so we should make sure that this is the case.
-*****************************************************************************/
-int StartSelfTest(DEVICE_EXTENSION *pdx)
-{
-	int nGot;
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	ced_draw_down(pdx);	/*  wait for, then kill outstanding Urbs */
-	FlushInBuff(pdx);	/*  Clear out input buffer & pipe */
-	FlushOutBuff(pdx);	/*  Clear output buffer & pipe */
-	/* so things stay tidy */
-	/* ReadWrite_Cancel(pDeviceObject); */
-	pdx->dwDMAFlag = MODE_CHAR;	/* Clear DMA mode flags here */
-
-	nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
-			       DB_SELFTEST, (H_TO_D | VENDOR | DEVREQ),
-			       0, 0, NULL, 0, HZ); /* allow 1 second timeout */
-	pdx->ulSelfTestTime = jiffies + HZ * 30;	/*  30 seconds into the future */
-
-	mutex_unlock(&pdx->io_mutex);
-	if (nGot < 0)
-		dev_err(&pdx->interface->dev, "%s: err=%d\n", __func__, nGot);
-	return nGot < 0 ? U14ERR_FAIL : U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** CheckSelfTest
-**
-** Check progress of a self-test cycle
-****************************************************************************/
-int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
-{
-	unsigned int state, error;
-	int iReturn;
-	TGET_SELFTEST gst;	/*  local work space */
-	memset(&gst, 0, sizeof(gst));	/*  clear out the space (sets code 0) */
-
-	mutex_lock(&pdx->io_mutex);
-
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-	iReturn = Get1401State(pdx, &state, &error);
-	if (iReturn == U14ERR_NOERROR)	/*  Only accept zero if it happens twice */
-		iReturn = Get1401State(pdx, &state, &error);
-
-	if (iReturn != U14ERR_NOERROR) {	/*  Self-test can cause comms errors */
-				/*  so we assume still testing */
-		dev_err(&pdx->interface->dev,
-			"%s: Get1401State=%d, assuming still testing\n",
-			__func__, iReturn);
-		state = 0x80;	/*  Force still-testing, no error */
-		error = 0;
-		iReturn = U14ERR_NOERROR;
-	}
-
-	if ((state == -1) && (error == -1)) {	/*  If Get1401State had problems */
-		dev_err(&pdx->interface->dev,
-			"%s: Get1401State failed, assuming still testing\n",
-			__func__);
-		state = 0x80;	/*  Force still-testing, no error */
-		error = 0;
-	}
-
-	if ((state & 0xFF) == 0x80) {	/*  If we are still in self-test */
-		if (state & 0x00FF0000)	{ /*  Have we got an error? */
-			gst.code = (state & 0x00FF0000) >> 16;	/*  read the error code */
-			gst.x = error & 0x0000FFFF;	/*  Error data X */
-			gst.y = (error & 0xFFFF0000) >> 16;	/*  and data Y */
-			dev_dbg(&pdx->interface->dev,
-				"Self-test error code %d\n", gst.code);
-		} else {		/*  No error, check for timeout */
-			unsigned long ulNow = jiffies;	/*  get current time */
-			if (time_after(ulNow, pdx->ulSelfTestTime)) {
-				gst.code = -2;	/*  Flag the timeout */
-				dev_dbg(&pdx->interface->dev,
-					"Self-test timed-out\n");
-			} else
-				dev_dbg(&pdx->interface->dev,
-					"Self-test on-going\n");
-		}
-	} else {
-		gst.code = -1;	/*  Flag the test is done */
-		dev_dbg(&pdx->interface->dev, "Self-test done\n");
-	}
-
-	if (gst.code < 0) {	/*  If we have a problem or finished */
-				/*  If using the 2890 we should reset properly */
-		if ((pdx->nPipes == 4) && (pdx->s1401Type <= TYPEPOWER))
-			Is1401(pdx);	/*  Get 1401 reset and OK */
-		else
-			QuickCheck(pdx, true, true);	/*  Otherwise check without reset unless problems */
-	}
-	mutex_unlock(&pdx->io_mutex);
-
-	if (copy_to_user(pGST, &gst, sizeof(gst)))
-		return -EFAULT;
-
-	return iReturn;
-}
-
-/****************************************************************************
-** TypeOf1401
-**
-** Returns code for standard, plus, micro1401, power1401 or none
-****************************************************************************/
-int TypeOf1401(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = TYPEUNKNOWN;
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	switch (pdx->s1401Type) {
-	case TYPE1401:
-		iReturn = U14ERR_STD;
-		break;		/*  Handle these types directly */
-	case TYPEPLUS:
-		iReturn = U14ERR_PLUS;
-		break;
-	case TYPEU1401:
-		iReturn = U14ERR_U1401;
-		break;
-	default:
-		if ((pdx->s1401Type >= TYPEPOWER) && (pdx->s1401Type <= 25))
-			iReturn = pdx->s1401Type + 4;	/*  We can calculate types */
-		else		/*   for up-coming 1401 designs */
-			iReturn = TYPEUNKNOWN;	/*  Don't know or not there */
-	}
-	dev_dbg(&pdx->interface->dev, "%s %d\n", __func__, iReturn);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** TransferFlags
-**
-** Returns flags on block transfer abilities
-****************************************************************************/
-int TransferFlags(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = U14TF_MULTIA | U14TF_DIAG |	/*  we always have multiple DMA area */
-	    U14TF_NOTIFY | U14TF_CIRCTH;	/*  diagnostics, notify and circular */
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-	mutex_lock(&pdx->io_mutex);
-	if (pdx->bIsUSB2)	/*  Set flag for USB2 if appropriate */
-		iReturn |= U14TF_USB2;
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/***************************************************************************
-** DbgCmd1401
-** Issues a debug\diagnostic command to the 1401 along with a 32-bit datum
-** This is a utility command used for dbg operations.
-*/
-static int DbgCmd1401(DEVICE_EXTENSION *pdx, unsigned char cmd,
-		      unsigned int data)
-{
-	int iReturn;
-	dev_dbg(&pdx->interface->dev, "%s: entry\n", __func__);
-	iReturn = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0), cmd,
-				  (H_TO_D | VENDOR | DEVREQ),
-				  (unsigned short)data,
-				  (unsigned short)(data >> 16), NULL, 0, HZ);
-						/* allow 1 second timeout */
-	if (iReturn < 0)
-		dev_err(&pdx->interface->dev, "%s: fail code=%d\n",
-			__func__, iReturn);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgPeek
-**
-** Execute the diagnostic peek operation. Uses address, width and repeats.
-****************************************************************************/
-int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
-{
-	int iReturn;
-	TDBGBLOCK db;
-
-	if (copy_from_user(&db, pDB, sizeof(db)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
-	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_PEEK, 0);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgPoke
-**
-** Execute the diagnostic poke operation. Parameters are in the CSBLOCK struct
-** in order address, size, repeats and value to poke.
-****************************************************************************/
-int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
-{
-	int iReturn;
-	TDBGBLOCK db;
-
-	if (copy_from_user(&db, pDB, sizeof(db)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
-	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_POKE, db.iData);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgRampData
-**
-** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK struct
-** in order address, default, enable mask, size and repeats.
-****************************************************************************/
-int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
-{
-	int iReturn;
-	TDBGBLOCK db;
-
-	if (copy_from_user(&db, pDB, sizeof(db)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
-	iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_RAMPD, 0);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgRampAddr
-**
-** Execute the diagnostic ramp address operation
-****************************************************************************/
-int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
-{
-	int iReturn;
-	TDBGBLOCK db;
-
-	if (copy_from_user(&db, pDB, sizeof(db)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
-	if (iReturn == U14ERR_NOERROR)
-		iReturn = DbgCmd1401(pdx, DB_RAMPA, 0);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgGetData
-**
-** Retrieve the data resulting from the last debug Peek operation
-****************************************************************************/
-int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
-{
-	int iReturn;
-	TDBGBLOCK db;
-	memset(&db, 0, sizeof(db));	/*  fill returned block with 0s */
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	/*  Read back the last peeked value from the 1401. */
-	iReturn = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
-				  DB_DATA, (D_TO_H | VENDOR | DEVREQ), 0, 0,
-				  &db.iData, sizeof(db.iData), HZ);
-	if (iReturn == sizeof(db.iData)) {
-		if (copy_to_user(pDB, &db, sizeof(db)))
-			iReturn = -EFAULT;
-		else
-			iReturn = U14ERR_NOERROR;
-	} else
-		dev_err(&pdx->interface->dev, "%s: failed, code %d\n",
-			__func__, iReturn);
-
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** DbgStopLoop
-**
-** Stop any never-ending debug loop, we just call Get1401State for USB
-**
-****************************************************************************/
-int DbgStopLoop(DEVICE_EXTENSION *pdx)
-{
-	int iReturn;
-	unsigned int uState, uErr;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-	iReturn = Get1401State(pdx, &uState, &uErr);
-	mutex_unlock(&pdx->io_mutex);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** SetCircular
-**
-** Sets up a transfer area record for circular transfers. If the area is
-** already set, we attempt to unset it. Unsetting will fail if the area is
-** booked and a transfer to that area is in progress. Otherwise, we will
-** release the area and re-assign it.
-****************************************************************************/
-int SetCircular(DEVICE_EXTENSION *pdx, struct transfer_area_desc __user *pTD)
-{
-	int iReturn;
-	bool bToHost;
-	struct transfer_area_desc td;
-
-	if (copy_from_user(&td, pTD, sizeof(td)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: area:%d, size:%08x\n",
-		__func__, td.wAreaNum, td.dwLength);
-	bToHost = td.eSize != 0;	/*  this is used as the tohost flag */
-
-	/*  The strange cast is done so that we don't get warnings in 32-bit linux about the size of the */
-	/*  pointer. The pointer is always passed as a 64-bit object so that we don't have problems using */
-	/*  a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system. */
-	iReturn =
-	    SetArea(pdx, td.wAreaNum,
-		    (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
-		    true, bToHost);
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/****************************************************************************
-** GetCircBlock
-**
-** Return the next available block of circularly-transferred data.
-****************************************************************************/
-int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
-{
-	int iReturn = U14ERR_NOERROR;
-	unsigned int nArea;
-	TCIRCBLOCK cb;
-
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	if (copy_from_user(&cb, pCB, sizeof(cb)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-
-	nArea = cb.nArea;	/*  Retrieve parameters first */
-	cb.dwOffset = 0;	/*  set default result (nothing) */
-	cb.dwSize = 0;
-
-	if (nArea < MAX_TRANSAREAS) {	/*  The area number must be OK */
-		TRANSAREA *pArea = &pdx->rTransDef[nArea];	/*  Pointer to relevant info */
-		spin_lock_irq(&pdx->stagedLock);	/*  Lock others out */
-
-		if ((pArea->bUsed) && (pArea->bCircular) &&	/*  Must be circular area */
-		    (pArea->bCircToHost)) {	/*  For now at least must be to host */
-			if (pArea->aBlocks[0].dwSize > 0) {	/*  Got anything? */
-				cb.dwOffset = pArea->aBlocks[0].dwOffset;
-				cb.dwSize = pArea->aBlocks[0].dwSize;
-				dev_dbg(&pdx->interface->dev,
-					"%s: return block 0: %d bytes at %d\n",
-					__func__, cb.dwSize, cb.dwOffset);
-			}
-		} else
-			iReturn = U14ERR_NOTSET;
-
-		spin_unlock_irq(&pdx->stagedLock);
-	} else
-		iReturn = U14ERR_BADAREA;
-
-	if (copy_to_user(pCB, &cb, sizeof(cb)))
-		iReturn = -EFAULT;
-
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
-
-/****************************************************************************
-** FreeCircBlock
-**
-** Frees a block of circularly-transferred data and returns the next one.
-****************************************************************************/
-int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB)
-{
-	int iReturn = U14ERR_NOERROR;
-	unsigned int nArea, uStart, uSize;
-	TCIRCBLOCK cb;
-
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	if (copy_from_user(&cb, pCB, sizeof(cb)))
-		return -EFAULT;
-
-	mutex_lock(&pdx->io_mutex);
-
-	nArea = cb.nArea;	/*  Retrieve parameters first */
-	uStart = cb.dwOffset;
-	uSize = cb.dwSize;
-	cb.dwOffset = 0;	/*  then set default result (nothing) */
-	cb.dwSize = 0;
-
-	if (nArea < MAX_TRANSAREAS) {	/*  The area number must be OK */
-		TRANSAREA *pArea = &pdx->rTransDef[nArea];	/*  Pointer to relevant info */
-		spin_lock_irq(&pdx->stagedLock);	/*  Lock others out */
-
-		if ((pArea->bUsed) && (pArea->bCircular) &&	/*  Must be circular area */
-		    (pArea->bCircToHost)) {	/*  For now at least must be to host */
-			bool bWaiting = false;
-
-			if ((pArea->aBlocks[0].dwSize >= uSize) &&	/*  Got anything? */
-			    (pArea->aBlocks[0].dwOffset == uStart)) {	/*  Must be legal data */
-				pArea->aBlocks[0].dwSize -= uSize;
-				pArea->aBlocks[0].dwOffset += uSize;
-				if (pArea->aBlocks[0].dwSize == 0) {	/*  Have we emptied this block? */
-					if (pArea->aBlocks[1].dwSize) {	/*  Is there a second block? */
-						pArea->aBlocks[0] = pArea->aBlocks[1];	/*  Copy down block 2 data */
-						pArea->aBlocks[1].dwSize = 0;	/*  and mark the second block as unused */
-						pArea->aBlocks[1].dwOffset = 0;
-					} else
-						pArea->aBlocks[0].dwOffset = 0;
-				}
-
-				dev_dbg(&pdx->interface->dev,
-					"%s: free %d bytes at %d, return %d bytes at %d, wait=%d\n",
-					__func__, uSize, uStart,
-					pArea->aBlocks[0].dwSize,
-					pArea->aBlocks[0].dwOffset,
-					pdx->bXFerWaiting);
-
-				/*  Return the next available block of memory as well */
-				if (pArea->aBlocks[0].dwSize > 0) {	/*  Got anything? */
-					cb.dwOffset =
-					    pArea->aBlocks[0].dwOffset;
-					cb.dwSize = pArea->aBlocks[0].dwSize;
-				}
-
-				bWaiting = pdx->bXFerWaiting;
-				if (bWaiting && pdx->bStagedUrbPending) {
-					dev_err(&pdx->interface->dev,
-						"%s: ERROR: waiting xfer and staged Urb pending!\n",
-						__func__);
-					bWaiting = false;
-				}
-			} else {
-				dev_err(&pdx->interface->dev,
-					"%s: ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d\n",
-					__func__, uSize, uStart,
-					pArea->aBlocks[0].dwSize,
-					pArea->aBlocks[0].dwOffset);
-				iReturn = U14ERR_NOMEMORY;
-			}
-
-			/*  If we have one, kick off pending transfer */
-			if (bWaiting) {	/*  Got a block xfer waiting? */
-				int RWMStat =
-				    ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
-						 pdx->rDMAInfo.wIdent,
-						 pdx->rDMAInfo.dwOffset,
-						 pdx->rDMAInfo.dwSize);
-				if (RWMStat != U14ERR_NOERROR)
-					dev_err(&pdx->interface->dev,
-						"%s: rw setup failed %d\n",
-						__func__, RWMStat);
-			}
-		} else
-			iReturn = U14ERR_NOTSET;
-
-		spin_unlock_irq(&pdx->stagedLock);
-	} else
-		iReturn = U14ERR_BADAREA;
-
-	if (copy_to_user(pCB, &cb, sizeof(cb)))
-		iReturn = -EFAULT;
-
-	mutex_unlock(&pdx->io_mutex);
-	return iReturn;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/ced_ioctl.h linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/ced_ioctl.h
--- linux-libre-3.16-gnu/drivers/staging/ced1401/ced_ioctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/ced_ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,336 +0,0 @@
-/*
- * IOCTL calls for the CED1401 driver
- * Copyright (C) 2010 Cambridge Electronic Design Ltd
- * Author Greg P Smith (greg@ced.co.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.
- */
-#ifndef __CED_IOCTL_H__
-#define __CED_IOCTL_H__
-
-#include <linux/ioctl.h>
-
-/* dma modes, only MODE_CHAR and MODE_LINEAR are used in this driver */
-#define MODE_CHAR		0
-#define MODE_LINEAR		1
-
-/****************************************************************************
-** TypeDefs
-*****************************************************************************/
-
-struct transfer_area_desc {
-	long long lpvBuff;	/* address of transfer area (for 64 or 32 bit) */
-	unsigned int dwLength;	/* length of the area */
-	unsigned short wAreaNum;	/* number of transfer area to set up */
-	short eSize;		/* element size - is tohost flag for circular */
-};
-
-
-struct transfer_event {
-	unsigned int dwStart;		/* offset into the area */
-	unsigned int dwLength;		/* length of the region */
-	unsigned short wAreaNum;	/* the area number */
-	unsigned short wFlags;		/* bit 0 set for toHost */
-	int iSetEvent;			/* could be dummy in LINUX */
-};
-
-#define MAX_TRANSFER_SIZE	0x4000		/* Maximum data bytes per IRP */
-#define MAX_AREA_LENGTH		0x100000	/* Maximum size of transfer area */
-#define MAX_TRANSAREAS		8		/* definitions for dma set up  */
-
-typedef struct TGetSelfTest {
-	int code;			/* self-test error code */
-	int x, y;			/* additional information */
-} TGET_SELFTEST;
-
-/* Debug block used for several commands. Not all fields are used for all commands. */
-typedef struct TDbgBlock {
-	int iAddr;			/* the address in the 1401 */
-	int iRepeats;			/* number of repeats */
-	int iWidth;			/* width in bytes 1, 2, 4 */
-	int iDefault;			/* default value */
-	int iMask;			/* mask to apply */
-	int iData;			/* data for poke, result for peek */
-} TDBGBLOCK;
-
-/* Used to collect information about a circular block from the device driver */
-typedef struct TCircBlock {
-	unsigned int nArea;		/* the area to collect information from */
-	unsigned int dwOffset;		/* offset into the area to the available block */
-	unsigned int dwSize;		/* size of the area */
-} TCIRCBLOCK;
-
-/* Used to clollect the 1401 status */
-typedef struct TCSBlock {
-	unsigned int uiState;
-	unsigned int uiError;
-} TCSBLOCK;
-
-/*
- * As seen by the user, an ioctl call looks like: int ioctl(int fd, unsigned
- * long cmd, char* argp); We will then have all sorts of variants on this that
- * can be used to pass stuff to our driver. We will generate macros for each
- * type of call so as to provide some sort of type safety in the calling:
- */
-#define CED_MAGIC_IOC 0xce
-
-#define IOCTL_CED_SENDSTRING(n)		_IOC(_IOC_WRITE, CED_MAGIC_IOC, 2, n)
-
-#define IOCTL_CED_RESET1401		_IO(CED_MAGIC_IOC, 3)
-#define IOCTL_CED_GETCHAR		_IO(CED_MAGIC_IOC, 4)
-#define IOCTL_CED_SENDCHAR		_IO(CED_MAGIC_IOC, 5)
-#define IOCTL_CED_STAT1401		_IO(CED_MAGIC_IOC, 6)
-#define IOCTL_CED_LINECOUNT		_IO(CED_MAGIC_IOC, 7)
-#define IOCTL_CED_GETSTRING(nMax)	_IOC(_IOC_READ, CED_MAGIC_IOC, 8, nMax)
-
-#define IOCTL_CED_SETTRANSFER		_IOW(CED_MAGIC_IOC, 11, struct transfer_area_desc)
-#define IOCTL_CED_UNSETTRANSFER		_IO(CED_MAGIC_IOC, 12)
-#define IOCTL_CED_SETEVENT		_IOW(CED_MAGIC_IOC, 13, struct transfer_event)
-#define IOCTL_CED_GETOUTBUFSPACE	_IO(CED_MAGIC_IOC, 14)
-#define IOCTL_CED_GETBASEADDRESS	_IO(CED_MAGIC_IOC, 15)
-#define IOCTL_CED_GETDRIVERREVISION	_IO(CED_MAGIC_IOC, 16)
-
-#define IOCTL_CED_GETTRANSFER		_IOR(CED_MAGIC_IOC, 17, TGET_TX_BLOCK)
-#define IOCTL_CED_KILLIO1401		_IO(CED_MAGIC_IOC, 18)
-#define IOCTL_CED_BLKTRANSSTATE		_IO(CED_MAGIC_IOC, 19)
-
-#define IOCTL_CED_STATEOF1401		_IO(CED_MAGIC_IOC, 23)
-#define IOCTL_CED_GRAB1401		_IO(CED_MAGIC_IOC, 25)
-#define IOCTL_CED_FREE1401		_IO(CED_MAGIC_IOC, 26)
-#define IOCTL_CED_STARTSELFTEST		_IO(CED_MAGIC_IOC, 31)
-#define IOCTL_CED_CHECKSELFTEST		_IOR(CED_MAGIC_IOC, 32, TGET_SELFTEST)
-#define IOCTL_CED_TYPEOF1401		_IO(CED_MAGIC_IOC, 33)
-#define IOCTL_CED_TRANSFERFLAGS		_IO(CED_MAGIC_IOC, 34)
-
-#define IOCTL_CED_DBGPEEK		_IOW(CED_MAGIC_IOC, 35, TDBGBLOCK)
-#define IOCTL_CED_DBGPOKE		_IOW(CED_MAGIC_IOC, 36, TDBGBLOCK)
-#define IOCTL_CED_DBGRAMPDATA		_IOW(CED_MAGIC_IOC, 37, TDBGBLOCK)
-#define IOCTL_CED_DBGRAMPADDR		_IOW(CED_MAGIC_IOC, 38, TDBGBLOCK)
-#define IOCTL_CED_DBGGETDATA		_IOR(CED_MAGIC_IOC, 39, TDBGBLOCK)
-#define IOCTL_CED_DBGSTOPLOOP		_IO(CED_MAGIC_IOC, 40)
-#define IOCTL_CED_FULLRESET		_IO(CED_MAGIC_IOC, 41)
-#define IOCTL_CED_SETCIRCULAR		_IOW(CED_MAGIC_IOC, 42, struct transfer_area_desc)
-#define IOCTL_CED_GETCIRCBLOCK		_IOWR(CED_MAGIC_IOC, 43, TCIRCBLOCK)
-#define IOCTL_CED_FREECIRCBLOCK		_IOWR(CED_MAGIC_IOC, 44, TCIRCBLOCK)
-#define IOCTL_CED_WAITEVENT		_IO(CED_MAGIC_IOC, 45)
-#define IOCTL_CED_TESTEVENT		_IO(CED_MAGIC_IOC, 46)
-
-#ifndef __KERNEL__
-/*
- * If nothing said about return value, it is a U14ERR_... error code
- * (U14ERR_NOERROR for none)
- */
-inline int CED_SendString(int fh, const char *szText, int n)
-{
-	return ioctl(fh, IOCTL_CED_SENDSTRING(n), szText);
-}
-
-inline int CED_Reset1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_RESET1401);
-}
-
-/* Return the singe character or a -ve error code. */
-inline int CED_GetChar(int fh)
-{
-	return ioctl(fh, IOCTL_CED_GETCHAR);
-}
-
-/* Return character count in input buffer */
-inline int CED_Stat1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_STAT1401);
-}
-
-inline int CED_SendChar(int fh, char c)
-{
-	return ioctl(fh, IOCTL_CED_SENDCHAR, c);
-}
-
-inline int CED_LineCount(int fh)
-{
-	return ioctl(fh, IOCTL_CED_LINECOUNT);
-}
-
-/*
- * return the count of characters returned. If the string was terminated by CR
- * or 0, then the 0 is part of the count. Otherwise, we will add a zero if
- * there is room, but it is not included in the count.  The return value is 0
- * if there was nothing to read.
- */
-inline int CED_GetString(int fh, char *szText, int nMax)
-{
-	return ioctl(fh, IOCTL_CED_GETSTRING(nMax), szText);
-}
-
-/* returns space in the output buffer. */
-inline int CED_GetOutBufSpace(int fh)
-{
-	return ioctl(fh, IOCTL_CED_GETOUTBUFSPACE);
-}
-
-/* This always returns -1 as not implemented. */
-inline int CED_GetBaseAddress(int fh)
-{
-	return ioctl(fh, IOCTL_CED_GETBASEADDRESS);
-}
-
-/* returns the major revision <<16 | minor revision. */
-inline int CED_GetDriverRevision(int fh)
-{
-	return ioctl(fh, IOCTL_CED_GETDRIVERREVISION);
-}
-
-inline int CED_SetTransfer(int fh, struct transfer_area_desc *pTD)
-{
-	return ioctl(fh, IOCTL_CED_SETTRANSFER, pTD);
-}
-
-inline int CED_UnsetTransfer(int fh, int nArea)
-{
-	return ioctl(fh, IOCTL_CED_UNSETTRANSFER, nArea);
-}
-
-inline int CED_SetEvent(int fh, struct transfer_event *pTE)
-{
-	return ioctl(fh, IOCTL_CED_SETEVENT, pTE);
-}
-
-inline int CED_GetTransfer(int fh, TGET_TX_BLOCK *pTX)
-{
-	return ioctl(fh, IOCTL_CED_GETTRANSFER, pTX);
-}
-
-inline int CED_KillIO1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_KILLIO1401);
-}
-
-/* returns 0 if no active DMA, 1 if active */
-inline int CED_BlkTransState(int fh)
-{
-	return ioctl(fh, IOCTL_CED_BLKTRANSSTATE);
-}
-
-inline int CED_StateOf1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_STATEOF1401);
-}
-
-inline int CED_Grab1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_GRAB1401);
-}
-
-inline int CED_Free1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_FREE1401);
-}
-
-inline int CED_StartSelfTest(int fh)
-{
-	return ioctl(fh, IOCTL_CED_STARTSELFTEST);
-}
-
-inline int CED_CheckSelfTest(int fh, TGET_SELFTEST *pGST)
-{
-	return ioctl(fh, IOCTL_CED_CHECKSELFTEST, pGST);
-}
-
-inline int CED_TypeOf1401(int fh)
-{
-	return ioctl(fh, IOCTL_CED_TYPEOF1401);
-}
-
-inline int CED_TransferFlags(int fh)
-{
-	return ioctl(fh, IOCTL_CED_TRANSFERFLAGS);
-}
-
-inline int CED_DbgPeek(int fh, TDBGBLOCK *pDB)
-{
-	return ioctl(fh, IOCTL_CED_DBGPEEK, pDB);
-}
-
-inline int CED_DbgPoke(int fh, TDBGBLOCK *pDB)
-{
-	return ioctl(fh, IOCTL_CED_DBGPOKE, pDB);
-}
-
-inline int CED_DbgRampData(int fh, TDBGBLOCK *pDB)
-{
-	return ioctl(fh, IOCTL_CED_DBGRAMPDATA, pDB);
-}
-
-inline int CED_DbgRampAddr(int fh, TDBGBLOCK *pDB)
-{
-	return ioctl(fh, IOCTL_CED_DBGRAMPADDR, pDB);
-}
-
-inline int CED_DbgGetData(int fh, TDBGBLOCK *pDB)
-{
-	return ioctl(fh, IOCTL_CED_DBGGETDATA, pDB);
-}
-
-inline int CED_DbgStopLoop(int fh)
-{
-	return ioctl(fh, IOCTL_CED_DBGSTOPLOOP);
-}
-
-inline int CED_FullReset(int fh)
-{
-	return ioctl(fh, IOCTL_CED_FULLRESET);
-}
-
-inline int CED_SetCircular(int fh, struct transfer_area_desc *pTD)
-{
-	return ioctl(fh, IOCTL_CED_SETCIRCULAR, pTD);
-}
-
-inline int CED_GetCircBlock(int fh, TCIRCBLOCK *pCB)
-{
-	return ioctl(fh, IOCTL_CED_GETCIRCBLOCK, pCB);
-}
-
-inline int CED_FreeCircBlock(int fh, TCIRCBLOCK *pCB)
-{
-	return ioctl(fh, IOCTL_CED_FREECIRCBLOCK, pCB);
-}
-
-inline int CED_WaitEvent(int fh, int nArea, int msTimeOut)
-{
-	return ioctl(fh, IOCTL_CED_WAITEVENT, (nArea & 0xff)|(msTimeOut << 8));
-}
-
-inline int CED_TestEvent(int fh, int nArea)
-{
-	return ioctl(fh, IOCTL_CED_TESTEVENT, nArea);
-}
-#endif
-
-#ifdef NOTWANTEDYET
-#define IOCTL_CED_REGCALLBACK		_IO(CED_MAGIC_IOC, 9)	/* Not used */
-#define IOCTL_CED_GETMONITORBUF		_IO(CED_MAGIC_IOC, 10)	/* Not used */
-
-#define IOCTL_CED_BYTECOUNT		_IO(CED_MAGIC_IOC, 20)	/* Not used */
-#define IOCTL_CED_ZEROBLOCKCOUNT	_IO(CED_MAGIC_IOC, 21)	/* Not used */
-#define IOCTL_CED_STOPCIRCULAR		_IO(CED_MAGIC_IOC, 22)	/* Not used */
-
-#define IOCTL_CED_REGISTERS1401		_IO(CED_MAGIC_IOC, 24)	/* Not used */
-#define IOCTL_CED_STEP1401		_IO(CED_MAGIC_IOC, 27)	/* Not used */
-#define IOCTL_CED_SET1401REGISTERS	_IO(CED_MAGIC_IOC, 28)	/* Not used */
-#define IOCTL_CED_STEPTILL1401		_IO(CED_MAGIC_IOC, 29)	/* Not used */
-#define IOCTL_CED_SETORIN		_IO(CED_MAGIC_IOC, 30)	/* Not used */
-
-#endif
-
-/* __CED_IOCTL_H__ */
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/ced1401/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-config CED1401
-	tristate "Cambridge Electronic Design 1401 USB support"
-	depends on USB
-	help
-	  This driver supports the Cambridge Electronic Design 1401 USB device
-	  (whatever that is.)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/machine.h linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/machine.h
--- linux-libre-3.16-gnu/drivers/staging/ced1401/machine.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/machine.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-/*****************************************************************************
-**
-** machine.h
-**
-** Copyright (c) Cambridge Electronic Design Limited 1991,1992,2010
-**
-** This program is free software; you can redistribute it and/or
-** modify it under the terms of the GNU General Public License
-** as published by the Free Software Foundation; either version 2
-** of the License, or (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU 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.
-**
-** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road
-**              Cambridge, CB6 0FE.
-**              www.ced.co.uk
-**              greg@ced.co.uk
-**
-** This file is included at the start of 'C' or 'C++' source file to define
-** things for cross-platform/compiler interoperability. This used to deal with
-** MSDOS/16-bit stuff, but this was all removed in Decemeber 2010. There are
-** three things to consider: Windows, LINUX, mac OSX (BSD Unix) and 32 vs 64
-** bit. At the time of writing (DEC 2010) there is a consensus on the following
-** and their unsigned equivalents:
-**
-** type       bits
-** char         8
-** short       16
-** int         32
-** long long   64
-**
-** long is a problem as it is always 64 bits on linux/unix and is always 32 bits
-** on windows.
-** On windows, we define _IS_WINDOWS_ and one of WIN32 or WIN64.
-** On linux we define LINUX
-** On Max OSX we define MACOSX
-**
-*/
-
-#ifndef __MACHINE_H__
-#define __MACHINE_H__
-#ifndef __KERNEL__
-#include <float.h>
-#include <limits.h>
-#endif
-
-/*
-** The initial section is to identify the operating system
-*/
-#if (defined(__linux__) || defined(_linux) || defined(__linux)) && !defined(LINUX)
-#define LINUX 1
-#endif
-
-#if (defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32)
-#define WIN32 1
-#endif
-
-#if defined(__APPLE__)
-#define MACOSX
-#endif
-
-#if defined(_WIN64)
-#undef WIN32
-#undef WIN64
-#define WIN64 1
-#endif
-
-#if defined(WIN32) || defined(WIN64)
-#define _IS_WINDOWS_ 1
-#endif
-
-#if defined(LINUX) || defined(MAXOSX)
-	#define FAR
-
-	typedef int BOOL;       /*  To match Windows */
-	typedef unsigned char  BYTE;
-	#define __packed __attribute__((packed))
-	#define HIWORD(x) (unsigned short)(((x)>>16) & 0xffff)
-	#define LOWORD(x) (unsigned short)((x) & 0xffff)
-#endif
-
-#ifdef _IS_WINDOWS_
-#include <windows.h>
-#define __packed
-#endif
-
-/*
-** Sort out the DllExport and DllImport macros. The GCC compiler has its own
-** syntax for this, though it also supports the MS specific __declspec() as
-** a synonym.
-*/
-#ifdef GNUC
-	#define DllExport __attribute__((dllexport))
-	#define DllImport __attribute__((dllimport))
-#endif
-
-#ifndef DllExport
-#ifdef _IS_WINDOWS_
-	#define DllExport __declspec(dllexport)
-	#define DllImport __declspec(dllimport)
-#else
-	#define DllExport
-	#define DllImport
-#endif
-#endif /* _IS_WINDOWS_ */
-
-#ifndef TRUE
-   #define TRUE 1
-   #define FALSE 0
-#endif
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/Makefile
--- linux-libre-3.16-gnu/drivers/staging/ced1401/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-
-obj-$(CONFIG_CED1401)	:= cedusb.o
-cedusb-objs	:= usb1401.o ced_ioc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/TODO linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/TODO
--- linux-libre-3.16-gnu/drivers/staging/ced1401/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-TODO:
-	- coding syle fixes
-	- build warning fixups
-	- ioctl auditing
-	- usb api auditing
-	- proper USB minor number (it's stomping on an existing one right now.)
-
-Please send patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org> and Cc:
-Alois SchlÃ¶gl <alois.schloegl@ist.ac.at>
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/usb1401.c linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/usb1401.c
--- linux-libre-3.16-gnu/drivers/staging/ced1401/usb1401.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/usb1401.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1582 +0,0 @@
-/***********************************************************************************
- CED1401 usb driver. This basic loading is based on the usb-skeleton.c code that is:
- Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- Copyright (C) 2012 Alois Schloegl <alois.schloegl@ist.ac.at>
- There is not a great deal of the skeleton left.
-
- All the remainder dealing specifically with the CED1401 is based on drivers written
- by CED for other systems (mainly Windows) and is:
- Copyright (C) 2010 Cambridge Electronic Design Ltd
- Author Greg P Smith (greg@ced.co.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-Endpoints
-*********
-There are 4 endpoints plus the control endpoint in the standard interface
-provided by most 1401s. The control endpoint is used for standard USB requests,
-plus various CED-specific transactions such as start self test, debug and get
-the 1401 status. The other endpoints are:
-
- 1 Characters to the 1401
- 2 Characters from the 1401
- 3 Block data to the 1401
- 4 Block data to the host.
-
-inside the driver these are indexed as an array from 0 to 3, transactions
-over the control endpoint are carried out using a separate mechanism. The
-use of the endpoints is mostly straightforward, with the driver issuing
-IO request packets (IRPs) as required to transfer data to and from the 1401.
-The handling of endpoint 2 is different because it is used for characters
-from the 1401, which can appear spontaneously and without any other driver
-activity - for example to repeatedly request DMA transfers in Spike2. The
-desired effect is achieved by using an interrupt endpoint which can be
-polled to see if it has data available, and writing the driver so that it
-always maintains a pending read IRP from that endpoint which will read the
-character data and terminate as soon as the 1401 makes data available. This
-works very well, some care is taken with when you kick off this character
-read IRP to avoid it being active when it is not wanted but generally it
-is running all the time.
-
-In the 2270, there are only three endpoints plus the control endpoint. In
-addition to the transactions mentioned above, the control endpoint is used
-to transfer character data to the 1401. The other endpoints are used as:
-
- 1 Characters from the 1401
- 2 Block data to the 1401
- 3 Block data to the host.
-
-The type of interface available is specified by the interface subclass field
-in the interface descriptor provided by the 1401. See the USB_INT_ constants
-for the values that this field can hold.
-
-****************************************************************************
-Linux implementation
-
-Although Linux Device Drivers (3rd Edition) was a major source of information,
-it is very out of date. A lot of information was gleaned from the latest
-usb_skeleton.c code (you need to download the kernel sources to get this).
-
-To match the Windows version, everything is done using ioctl calls. All the
-device state is held in the DEVICE_EXTENSION (named to match Windows use).
-Block transfers are done by using get_user_pages() to pin down a list of
-pages that we hold a pointer to in the device driver. We also allocate a
-coherent transfer buffer of size STAGED_SZ (this must be a multiple of the
-bulk endpoint size so that the 1401 does not realise that we break large
-transfers down into smaller pieces). We use kmap_atomic() to get a kernel
-va for each page, as it is required, for copying; see CopyUserSpace().
-
-All character and data transfers are done using asynchronous IO. All Urbs are
-tracked by anchoring them. Status and debug ioctls are implemented with the
-synchronous non-Urb based transfers.
-*/
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/uaccess.h>
-
-#include "usb1401.h"
-
-/* Define these values to match your devices */
-#define USB_CED_VENDOR_ID	0x0525
-#define USB_CED_PRODUCT_ID	0xa0f0
-
-/* table of devices that work with this driver */
-static const struct usb_device_id ced_table[] = {
-	{USB_DEVICE(USB_CED_VENDOR_ID, USB_CED_PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, ced_table);
-
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_CED_MINOR_BASE	192
-
-/* our private defines. if this grows any larger, use your own .h file */
-#define MAX_TRANSFER		(PAGE_SIZE - 512)
-/* MAX_TRANSFER is chosen so that the VM is not stressed by
-   allocations > PAGE_SIZE and the number of packets in a page
-   is an integer 512 is the largest possible packet on EHCI */
-#define WRITES_IN_FLIGHT	8
-/* arbitrarily chosen */
-
-static struct usb_driver ced_driver;
-
-static void ced_delete(struct kref *kref)
-{
-	DEVICE_EXTENSION *pdx = to_DEVICE_EXTENSION(kref);
-
-	/*  Free up the output buffer, then free the output urb. Note that the interface member */
-	/*  of pdx will probably be NULL, so cannot be used to get to dev. */
-	usb_free_coherent(pdx->udev, OUTBUF_SZ, pdx->pCoherCharOut,
-			  pdx->pUrbCharOut->transfer_dma);
-	usb_free_urb(pdx->pUrbCharOut);
-
-	/*  Do the same for chan input */
-	usb_free_coherent(pdx->udev, INBUF_SZ, pdx->pCoherCharIn,
-			  pdx->pUrbCharIn->transfer_dma);
-	usb_free_urb(pdx->pUrbCharIn);
-
-	/*  Do the same for the block transfers */
-	usb_free_coherent(pdx->udev, STAGED_SZ, pdx->pCoherStagedIO,
-			  pdx->pStagedUrb->transfer_dma);
-	usb_free_urb(pdx->pStagedUrb);
-
-	usb_put_dev(pdx->udev);
-	kfree(pdx);
-}
-
-/*  This is the driver end of the open() call from user space. */
-static int ced_open(struct inode *inode, struct file *file)
-{
-	DEVICE_EXTENSION *pdx;
-	int retval = 0;
-	int subminor = iminor(inode);
-	struct usb_interface *interface =
-	    usb_find_interface(&ced_driver, subminor);
-	if (!interface) {
-		pr_err("%s - error, can't find device for minor %d", __func__,
-		       subminor);
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	pdx = usb_get_intfdata(interface);
-	if (!pdx) {
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	dev_dbg(&interface->dev, "%s: got pdx\n", __func__);
-
-	/* increment our usage count for the device */
-	kref_get(&pdx->kref);
-
-	/* lock the device to allow correctly handling errors
-	 * in resumption */
-	mutex_lock(&pdx->io_mutex);
-
-	if (!pdx->open_count++) {
-		retval = usb_autopm_get_interface(interface);
-		if (retval) {
-			pdx->open_count--;
-			mutex_unlock(&pdx->io_mutex);
-			kref_put(&pdx->kref, ced_delete);
-			goto exit;
-		}
-	} else {		/* uncomment this block if you want exclusive open */
-		dev_err(&interface->dev, "%s: fail: already open\n", __func__);
-		retval = -EBUSY;
-		pdx->open_count--;
-		mutex_unlock(&pdx->io_mutex);
-		kref_put(&pdx->kref, ced_delete);
-		goto exit;
-	}
-	/* prevent the device from being autosuspended */
-
-	/* save our object in the file's private structure */
-	file->private_data = pdx;
-	mutex_unlock(&pdx->io_mutex);
-
-exit:
-	return retval;
-}
-
-static int ced_release(struct inode *inode, struct file *file)
-{
-	DEVICE_EXTENSION *pdx = file->private_data;
-	if (pdx == NULL)
-		return -ENODEV;
-
-	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
-	mutex_lock(&pdx->io_mutex);
-	if (!--pdx->open_count && pdx->interface)	/*  Allow autosuspend */
-		usb_autopm_put_interface(pdx->interface);
-	mutex_unlock(&pdx->io_mutex);
-
-	kref_put(&pdx->kref, ced_delete);	/*  decrement the count on our device */
-	return 0;
-}
-
-static int ced_flush(struct file *file, fl_owner_t id)
-{
-	int res;
-	DEVICE_EXTENSION *pdx = file->private_data;
-	if (pdx == NULL)
-		return -ENODEV;
-
-	dev_dbg(&pdx->interface->dev, "%s: char in pend=%d\n",
-		__func__, pdx->bReadCharsPending);
-
-	/* wait for io to stop */
-	mutex_lock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: got io_mutex\n", __func__);
-	ced_draw_down(pdx);
-
-	/* read out errors, leave subsequent opens a clean slate */
-	spin_lock_irq(&pdx->err_lock);
-	res = pdx->errors ? (pdx->errors == -EPIPE ? -EPIPE : -EIO) : 0;
-	pdx->errors = 0;
-	spin_unlock_irq(&pdx->err_lock);
-
-	mutex_unlock(&pdx->io_mutex);
-	dev_dbg(&pdx->interface->dev, "%s: exit reached\n", __func__);
-
-	return res;
-}
-
-/***************************************************************************
-** CanAcceptIoRequests
-** If the device is removed, interface is set NULL. We also clear our pointer
-** from the interface, so we should make sure that pdx is not NULL. This will
-** not help with a device extension held by a file.
-** return true if can accept new io requests, else false
-*/
-static bool CanAcceptIoRequests(DEVICE_EXTENSION *pdx)
-{
-	return pdx && pdx->interface;	/*  Can we accept IO requests */
-}
-
-/****************************************************************************
-** Callback routine to complete writes. This may need to fire off another
-** urb to complete the transfer.
-****************************************************************************/
-static void ced_writechar_callback(struct urb *pUrb)
-{
-	DEVICE_EXTENSION *pdx = pUrb->context;
-	int nGot = pUrb->actual_length;	/*  what we transferred */
-
-	if (pUrb->status) {	/*  sync/async unlink faults aren't errors */
-		if (!
-		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
-		     || pUrb->status == -ESHUTDOWN)) {
-			dev_err(&pdx->interface->dev,
-				"%s: nonzero write bulk status received: %d\n",
-				__func__, pUrb->status);
-		}
-
-		spin_lock(&pdx->err_lock);
-		pdx->errors = pUrb->status;
-		spin_unlock(&pdx->err_lock);
-		nGot = 0;	/*   and tidy up again if so */
-
-		spin_lock(&pdx->charOutLock);	/*  already at irq level */
-		pdx->dwOutBuffGet = 0;	/*  Reset the output buffer */
-		pdx->dwOutBuffPut = 0;
-		pdx->dwNumOutput = 0;	/*  Clear the char count */
-		pdx->bPipeError[0] = 1;	/*  Flag an error for later */
-		pdx->bSendCharsPending = false;	/*  Allow other threads again */
-		spin_unlock(&pdx->charOutLock);	/*  already at irq level */
-		dev_dbg(&pdx->interface->dev,
-			"%s: char out done, 0 chars sent\n", __func__);
-	} else {
-		dev_dbg(&pdx->interface->dev,
-			"%s: char out done, %d chars sent\n", __func__, nGot);
-		spin_lock(&pdx->charOutLock);	/*  already at irq level */
-		pdx->dwNumOutput -= nGot;	/*  Now adjust the char send buffer */
-		pdx->dwOutBuffGet += nGot;	/*  to match what we did */
-		if (pdx->dwOutBuffGet >= OUTBUF_SZ)	/*  Can't do this any earlier as data could be overwritten */
-			pdx->dwOutBuffGet = 0;
-
-		if (pdx->dwNumOutput > 0) {	/*  if more to be done... */
-			int nPipe = 0;	/*  The pipe number to use */
-			int iReturn;
-			char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
-			unsigned int dwCount = pdx->dwNumOutput;	/*  maximum to send */
-			if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ)	/*  does it cross buffer end? */
-				dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
-			spin_unlock(&pdx->charOutLock);	/*  we are done with stuff that changes */
-			memcpy(pdx->pCoherCharOut, pDat, dwCount);	/*  copy output data to the buffer */
-			usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
-					  usb_sndbulkpipe(pdx->udev,
-							  pdx->epAddr[0]),
-					  pdx->pCoherCharOut, dwCount,
-					  ced_writechar_callback, pdx);
-			pdx->pUrbCharOut->transfer_flags |=
-			    URB_NO_TRANSFER_DMA_MAP;
-			usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted);	/*  in case we need to kill it */
-			iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC);
-			dev_dbg(&pdx->interface->dev, "%s: n=%d>%s<\n",
-				__func__, dwCount, pDat);
-			spin_lock(&pdx->charOutLock);	/*  grab lock for errors */
-			if (iReturn) {
-				pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
-				pdx->bSendCharsPending = false;	/*  Allow other threads again */
-				usb_unanchor_urb(pdx->pUrbCharOut);
-				dev_err(&pdx->interface->dev,
-					"%s: usb_submit_urb() returned %d\n",
-					__func__, iReturn);
-			}
-		} else
-			pdx->bSendCharsPending = false;	/*  Allow other threads again */
-		spin_unlock(&pdx->charOutLock);	/*  already at irq level */
-	}
-}
-
-/****************************************************************************
-** SendChars
-** Transmit the characters in the output buffer to the 1401. This may need
-** breaking down into multiple transfers.
-****************************************************************************/
-int SendChars(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = U14ERR_NOERROR;
-
-	spin_lock_irq(&pdx->charOutLock);	/*  Protect ourselves */
-
-	if ((!pdx->bSendCharsPending) &&	/*  Not currently sending */
-	    (pdx->dwNumOutput > 0) &&	/*   has characters to output */
-	    (CanAcceptIoRequests(pdx)))	{ /*   and current activity is OK */
-		unsigned int dwCount = pdx->dwNumOutput;	/*  Get a copy of the character count */
-		pdx->bSendCharsPending = true;	/*  Set flag to lock out other threads */
-
-		dev_dbg(&pdx->interface->dev,
-			"Send %d chars to 1401, EP0 flag %d\n",
-			dwCount, pdx->nPipes == 3);
-		/*  If we have only 3 end points we must send the characters to the 1401 using EP0. */
-		if (pdx->nPipes == 3) {
-			/*  For EP0 character transmissions to the 1401, we have to hang about until they */
-			/*  are gone, as otherwise without more character IO activity they will never go. */
-			unsigned int count = dwCount;	/*  Local char counter */
-			unsigned int index = 0;	/*  The index into the char buffer */
-
-			spin_unlock_irq(&pdx->charOutLock);	/*  Free spinlock as we call USBD */
-
-			while ((count > 0) && (iReturn == U14ERR_NOERROR)) {
-				/*  We have to break the transfer up into 64-byte chunks because of a 2270 problem */
-				int n = count > 64 ? 64 : count;	/*  Chars for this xfer, max of 64 */
-				int nSent = usb_control_msg(pdx->udev,
-							    usb_sndctrlpipe(pdx->udev, 0),	/*  use end point 0 */
-							    DB_CHARS,	/*  bRequest */
-							    (H_TO_D | VENDOR | DEVREQ),	/*  to the device, vendor request to the device */
-							    0, 0,	/*  value and index are both 0 */
-							    &pdx->outputBuffer[index],	/*  where to send from */
-							    n,	/*  how much to send */
-							    1000);	/*  timeout in jiffies */
-				if (nSent <= 0) {
-					iReturn = nSent ? nSent : -ETIMEDOUT;	/*  if 0 chars says we timed out */
-					dev_err(&pdx->interface->dev,
-						"Send %d chars by EP0 failed: %d\n",
-						n, iReturn);
-				} else {
-					dev_dbg(&pdx->interface->dev,
-						"Sent %d chars by EP0\n", n);
-					count -= nSent;
-					index += nSent;
-				}
-			}
-
-			spin_lock_irq(&pdx->charOutLock);	/*  Protect pdx changes, released by general code */
-			pdx->dwOutBuffGet = 0;	/*  so reset the output buffer */
-			pdx->dwOutBuffPut = 0;
-			pdx->dwNumOutput = 0;	/*  and clear the buffer count */
-			pdx->bSendCharsPending = false;	/*  Allow other threads again */
-		} else {	/*  Here for sending chars normally - we hold the spin lock */
-			int nPipe = 0;	/*  The pipe number to use */
-			char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
-
-			if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ)	/*  does it cross buffer end? */
-				dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
-			spin_unlock_irq(&pdx->charOutLock);	/*  we are done with stuff that changes */
-			memcpy(pdx->pCoherCharOut, pDat, dwCount);	/*  copy output data to the buffer */
-			usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
-					  usb_sndbulkpipe(pdx->udev,
-							  pdx->epAddr[0]),
-					  pdx->pCoherCharOut, dwCount,
-					  ced_writechar_callback, pdx);
-			pdx->pUrbCharOut->transfer_flags |=
-			    URB_NO_TRANSFER_DMA_MAP;
-			usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted);
-			iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_KERNEL);
-			spin_lock_irq(&pdx->charOutLock);	/*  grab lock for errors */
-			if (iReturn) {
-				pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
-				pdx->bSendCharsPending = false;	/*  Allow other threads again */
-				usb_unanchor_urb(pdx->pUrbCharOut);	/*  remove from list of active urbs */
-			}
-		}
-	} else if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0))
-		dev_dbg(&pdx->interface->dev,
-			"%s: bSendCharsPending:true\n", __func__);
-
-	dev_dbg(&pdx->interface->dev, "%s: exit code: %d\n", __func__, iReturn);
-	spin_unlock_irq(&pdx->charOutLock);	/*  Now let go of the spinlock */
-	return iReturn;
-}
-
-/***************************************************************************
-** CopyUserSpace
-** This moves memory between pinned down user space and the pCoherStagedIO
-** memory buffer we use for transfers. Copy n bytes in the directions that
-** is defined by pdx->StagedRead. The user space is determined by the area
-** in pdx->StagedId and the offset in pdx->StagedDone. The user
-** area may well not start on a page boundary, so allow for that.
-**
-** We have a table of physical pages that describe the area, so we can use
-** this to get a virtual address that the kernel can use.
-**
-** pdx  Is our device extension which holds all we know about the transfer.
-** n    The number of bytes to move one way or the other.
-***************************************************************************/
-static void CopyUserSpace(DEVICE_EXTENSION *pdx, int n)
-{
-	unsigned int nArea = pdx->StagedId;
-	if (nArea < MAX_TRANSAREAS) {
-		TRANSAREA *pArea = &pdx->rTransDef[nArea];	/*  area to be used */
-		unsigned int dwOffset =
-		    pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset;
-		char *pCoherBuf = pdx->pCoherStagedIO;	/*  coherent buffer */
-		if (!pArea->bUsed) {
-			dev_err(&pdx->interface->dev, "%s: area %d unused\n",
-				__func__, nArea);
-			return;
-		}
-
-		while (n) {
-			int nPage = dwOffset >> PAGE_SHIFT;	/*  page number in table */
-			if (nPage < pArea->nPages) {
-				char *pvAddress =
-				    (char *)kmap_atomic(pArea->pPages[nPage]);
-				if (pvAddress) {
-					unsigned int uiPageOff = dwOffset & (PAGE_SIZE - 1);	/*  offset into the page */
-					size_t uiXfer = PAGE_SIZE - uiPageOff;	/*  max to transfer on this page */
-					if (uiXfer > n)	/*  limit byte count if too much */
-						uiXfer = n;	/*  for the page */
-					if (pdx->StagedRead)
-						memcpy(pvAddress + uiPageOff,
-						       pCoherBuf, uiXfer);
-					else
-						memcpy(pCoherBuf,
-						       pvAddress + uiPageOff,
-						       uiXfer);
-					kunmap_atomic(pvAddress);
-					dwOffset += uiXfer;
-					pCoherBuf += uiXfer;
-					n -= uiXfer;
-				} else {
-					dev_err(&pdx->interface->dev,
-						"%s: did not map page %d\n",
-						__func__, nPage);
-					return;
-				}
-
-			} else {
-				dev_err(&pdx->interface->dev,
-					"%s: exceeded pages %d\n",
-					__func__, nPage);
-				return;
-			}
-		}
-	} else
-		dev_err(&pdx->interface->dev, "%s: bad area %d\n",
-			__func__, nArea);
-}
-
-/*  Forward declarations for stuff used circularly */
-static int StageChunk(DEVICE_EXTENSION *pdx);
-/***************************************************************************
-** ReadWrite_Complete
-**
-**  Completion routine for our staged read/write Irps
-*/
-static void staged_callback(struct urb *pUrb)
-{
-	DEVICE_EXTENSION *pdx = pUrb->context;
-	unsigned int nGot = pUrb->actual_length;	/*  what we transferred */
-	bool bCancel = false;
-	bool bRestartCharInput;	/*  used at the end */
-
-	spin_lock(&pdx->stagedLock);	/*  stop ReadWriteMem() action while this routine is running */
-	pdx->bStagedUrbPending = false;	/*  clear the flag for staged IRP pending */
-
-	if (pUrb->status) {	/*  sync/async unlink faults aren't errors */
-		if (!
-		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
-		     || pUrb->status == -ESHUTDOWN)) {
-			dev_err(&pdx->interface->dev,
-				"%s: nonzero write bulk status received: %d\n",
-				__func__, pUrb->status);
-		} else
-			dev_info(&pdx->interface->dev,
-				 "%s: staged xfer cancelled\n", __func__);
-
-		spin_lock(&pdx->err_lock);
-		pdx->errors = pUrb->status;
-		spin_unlock(&pdx->err_lock);
-		nGot = 0;	/*   and tidy up again if so */
-		bCancel = true;
-	} else {
-		dev_dbg(&pdx->interface->dev, "%s: %d chars xferred\n",
-			__func__, nGot);
-		if (pdx->StagedRead)	/*  if reading, save to user space */
-			CopyUserSpace(pdx, nGot);	/*  copy from buffer to user */
-		if (nGot == 0)
-			dev_dbg(&pdx->interface->dev, "%s: ZLP\n", __func__);
-	}
-
-	/*  Update the transfer length based on the TransferBufferLength value in the URB */
-	pdx->StagedDone += nGot;
-
-	dev_dbg(&pdx->interface->dev, "%s: done %d bytes of %d\n",
-		__func__, pdx->StagedDone, pdx->StagedLength);
-
-	if ((pdx->StagedDone == pdx->StagedLength) ||	/*  If no more to do */
-	    (bCancel)) {		/*  or this IRP was cancelled */
-		TRANSAREA *pArea = &pdx->rTransDef[pdx->StagedId];	/*  Transfer area info */
-		dev_dbg(&pdx->interface->dev,
-			"%s: transfer done, bytes %d, cancel %d\n",
-			__func__, pdx->StagedDone, bCancel);
-
-		/*  Here is where we sort out what to do with this transfer if using a circular buffer. We have */
-		/*   a completed transfer that can be assumed to fit into the transfer area. We should be able to */
-		/*   add this to the end of a growing block or to use it to start a new block unless the code */
-		/*   that calculates the offset to use (in ReadWriteMem) is totally duff. */
-		if ((pArea->bCircular) && (pArea->bCircToHost) && (!bCancel) &&	/*  Time to sort out circular buffer info? */
-		    (pdx->StagedRead)) {	/*  Only for tohost transfers for now */
-			if (pArea->aBlocks[1].dwSize > 0) {	/*  If block 1 is in use we must append to it */
-				if (pdx->StagedOffset ==
-				    (pArea->aBlocks[1].dwOffset +
-				     pArea->aBlocks[1].dwSize)) {
-					pArea->aBlocks[1].dwSize +=
-					    pdx->StagedLength;
-					dev_dbg(&pdx->interface->dev,
-						"RWM_Complete, circ block 1 now %d bytes at %d\n",
-						pArea->aBlocks[1].dwSize,
-						pArea->aBlocks[1].dwOffset);
-				} else {
-					/*  Here things have gone very, very, wrong, but I cannot see how this can actually be achieved */
-					pArea->aBlocks[1].dwOffset =
-					    pdx->StagedOffset;
-					pArea->aBlocks[1].dwSize =
-					    pdx->StagedLength;
-					dev_err(&pdx->interface->dev,
-						"%s: ERROR, circ block 1 re-started %d bytes at %d\n",
-						__func__,
-						pArea->aBlocks[1].dwSize,
-						pArea->aBlocks[1].dwOffset);
-				}
-			} else {	/*  If block 1 is not used, we try to add to block 0 */
-				if (pArea->aBlocks[0].dwSize > 0) {	/*  Got stored block 0 information? */
-					/*  Must append onto the existing block 0 */
-					if (pdx->StagedOffset ==
-					    (pArea->aBlocks[0].dwOffset +
-					     pArea->aBlocks[0].dwSize)) {
-						pArea->aBlocks[0].dwSize += pdx->StagedLength;	/*  Just add this transfer in */
-						dev_dbg(&pdx->interface->dev,
-							"RWM_Complete, circ block 0 now %d bytes at %d\n",
-							pArea->aBlocks[0].
-							dwSize,
-							pArea->aBlocks[0].
-							dwOffset);
-					} else {	/*  If it doesn't append, put into new block 1 */
-						pArea->aBlocks[1].dwOffset =
-						    pdx->StagedOffset;
-						pArea->aBlocks[1].dwSize =
-						    pdx->StagedLength;
-						dev_dbg(&pdx->interface->dev,
-							"RWM_Complete, circ block 1 started %d bytes at %d\n",
-							pArea->aBlocks[1].
-							dwSize,
-							pArea->aBlocks[1].
-							dwOffset);
-					}
-				} else	{ /*  No info stored yet, just save in block 0 */
-					pArea->aBlocks[0].dwOffset =
-					    pdx->StagedOffset;
-					pArea->aBlocks[0].dwSize =
-					    pdx->StagedLength;
-					dev_dbg(&pdx->interface->dev,
-						"RWM_Complete, circ block 0 started %d bytes at %d\n",
-						pArea->aBlocks[0].dwSize,
-						pArea->aBlocks[0].dwOffset);
-				}
-			}
-		}
-
-		if (!bCancel) { /*  Don't generate an event if cancelled */
-			dev_dbg(&pdx->interface->dev,
-				"RWM_Complete,  bCircular %d, bToHost %d, eStart %d, eSize %d\n",
-				pArea->bCircular, pArea->bEventToHost,
-				pArea->dwEventSt, pArea->dwEventSz);
-			if ((pArea->dwEventSz) &&	/*  Set a user-mode event... */
-			    (pdx->StagedRead == pArea->bEventToHost)) {	/*  ...on transfers in this direction? */
-				int iWakeUp = 0;	/*  assume */
-				/*  If we have completed the right sort of DMA transfer then set the event to notify */
-				/*    the user code to wake up anyone that is waiting. */
-				if ((pArea->bCircular) &&	/*  Circular areas use a simpler test */
-				    (pArea->bCircToHost)) {	/*  only in supported direction */
-					/*  Is total data waiting up to size limit? */
-					unsigned int dwTotal =
-					    pArea->aBlocks[0].dwSize +
-					    pArea->aBlocks[1].dwSize;
-					iWakeUp = (dwTotal >= pArea->dwEventSz);
-				} else {
-					unsigned int transEnd =
-					    pdx->StagedOffset +
-					    pdx->StagedLength;
-					unsigned int eventEnd =
-					    pArea->dwEventSt + pArea->dwEventSz;
-					iWakeUp = (pdx->StagedOffset < eventEnd)
-					    && (transEnd > pArea->dwEventSt);
-				}
-
-				if (iWakeUp) {
-					dev_dbg(&pdx->interface->dev,
-						"About to set event to notify app\n");
-					wake_up_interruptible(&pArea->wqEvent);	/*  wake up waiting processes */
-					++pArea->iWakeUp;	/*  increment wakeup count */
-				}
-			}
-		}
-
-		pdx->dwDMAFlag = MODE_CHAR;	/*  Switch back to char mode before ReadWriteMem call */
-
-		if (!bCancel) {	/*  Don't look for waiting transfer if cancelled */
-			/*  If we have a transfer waiting, kick it off */
-			if (pdx->bXFerWaiting) {	/*  Got a block xfer waiting? */
-				int iReturn;
-				dev_info(&pdx->interface->dev,
-					 "*** RWM_Complete *** pending transfer will now be set up!!!\n");
-				iReturn =
-				    ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
-						 pdx->rDMAInfo.wIdent,
-						 pdx->rDMAInfo.dwOffset,
-						 pdx->rDMAInfo.dwSize);
-
-				if (iReturn)
-					dev_err(&pdx->interface->dev,
-						"RWM_Complete rw setup failed %d\n",
-						iReturn);
-			}
-		}
-
-	} else			/*  Here for more to do */
-		StageChunk(pdx);	/*  fire off the next bit */
-
-	/*  While we hold the stagedLock, see if we should reallow character input ints */
-	/*  Don't allow if cancelled, or if a new block has started or if there is a waiting block. */
-	/*  This feels wrong as we should ask which spin lock protects dwDMAFlag. */
-	bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR)
-	    && !pdx->bXFerWaiting;
-
-	spin_unlock(&pdx->stagedLock);	/*  Finally release the lock again */
-
-	/*  This is not correct as dwDMAFlag is protected by the staged lock, but it is treated */
-	/*  in Allowi as if it were protected by the char lock. In any case, most systems will */
-	/*  not be upset by char input during DMA... sigh. Needs sorting out. */
-	if (bRestartCharInput)	/*  may be out of date, but... */
-		Allowi(pdx);	/*  ...Allowi tests a lock too. */
-	dev_dbg(&pdx->interface->dev, "%s: done\n", __func__);
-}
-
-/****************************************************************************
-** StageChunk
-**
-** Generates the next chunk of data making up a staged transfer.
-**
-** The calling code must have acquired the staging spinlock before calling
-**  this function, and is responsible for releasing it. We are at callback level.
-****************************************************************************/
-static int StageChunk(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = U14ERR_NOERROR;
-	unsigned int ChunkSize;
-	int nPipe = pdx->StagedRead ? 3 : 2;	/*  The pipe number to use for reads or writes */
-	if (pdx->nPipes == 3)
-		nPipe--;	/*  Adjust for the 3-pipe case */
-	if (nPipe < 0)		/*  and trap case that should never happen */
-		return U14ERR_FAIL;
-
-	if (!CanAcceptIoRequests(pdx)) {	/*  got sudden remove? */
-		dev_info(&pdx->interface->dev, "%s: sudden remove, giving up\n",
-			 __func__);
-		return U14ERR_FAIL;	/*  could do with a better error */
-	}
-
-	ChunkSize = (pdx->StagedLength - pdx->StagedDone);	/*  transfer length remaining */
-	if (ChunkSize > STAGED_SZ)	/*  make sure to keep legal */
-		ChunkSize = STAGED_SZ;	/*   limit to max allowed */
-
-	if (!pdx->StagedRead)	/*  if writing... */
-		CopyUserSpace(pdx, ChunkSize);	/*  ...copy data into the buffer */
-
-	usb_fill_bulk_urb(pdx->pStagedUrb, pdx->udev,
-			  pdx->StagedRead ? usb_rcvbulkpipe(pdx->udev,
-							    pdx->
-							    epAddr[nPipe]) :
-			  usb_sndbulkpipe(pdx->udev, pdx->epAddr[nPipe]),
-			  pdx->pCoherStagedIO, ChunkSize, staged_callback, pdx);
-	pdx->pStagedUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	usb_anchor_urb(pdx->pStagedUrb, &pdx->submitted);	/*  in case we need to kill it */
-	iReturn = usb_submit_urb(pdx->pStagedUrb, GFP_ATOMIC);
-	if (iReturn) {
-		usb_unanchor_urb(pdx->pStagedUrb);	/*  kill it */
-		pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
-		dev_err(&pdx->interface->dev, "%s: submit urb failed, code %d\n",
-			__func__, iReturn);
-	} else
-		pdx->bStagedUrbPending = true;	/*  Set the flag for staged URB pending */
-	dev_dbg(&pdx->interface->dev, "%s: done so far:%d, this size:%d\n",
-		__func__, pdx->StagedDone, ChunkSize);
-
-	return iReturn;
-}
-
-/***************************************************************************
-** ReadWriteMem
-**
-** This routine is used generally for block read and write operations.
-** Breaks up a read or write in to specified sized chunks, as specified by pipe
-** information on maximum transfer size.
-**
-** Any code that calls this must be holding the stagedLock
-**
-** Arguments:
-**    DeviceObject - pointer to our FDO (Functional Device Object)
-**    Read - TRUE for read, FALSE for write. This is from POV of the driver
-**    wIdent - the transfer area number - defines memory area and more.
-**    dwOffs - the start offset within the transfer area of the start of this
-**             transfer.
-**    dwLen - the number of bytes to transfer.
-*/
-int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
-		 unsigned int dwOffs, unsigned int dwLen)
-{
-	TRANSAREA *pArea = &pdx->rTransDef[wIdent];	/*  Transfer area info */
-
-	if (!CanAcceptIoRequests(pdx)) {	/*  Are we in a state to accept new requests? */
-		dev_err(&pdx->interface->dev, "%s: can't accept requests\n",
-			__func__);
-		return U14ERR_FAIL;
-	}
-
-	dev_dbg(&pdx->interface->dev,
-		"%s: xfer %d bytes to %s, offset %d, area %d\n",
-		__func__, dwLen, Read ? "host" : "1401", dwOffs, wIdent);
-
-	/*  Amazingly, we can get an escape sequence back before the current staged Urb is done, so we */
-	/*   have to check for this situation and, if so, wait until all is OK. */
-	if (pdx->bStagedUrbPending) {
-		pdx->bXFerWaiting = true;	/*  Flag we are waiting */
-		dev_info(&pdx->interface->dev,
-			 "%s: xfer is waiting, as previous staged pending\n",
-			 __func__);
-		return U14ERR_NOERROR;
-	}
-
-	if (dwLen == 0) {		/*  allow 0-len read or write; just return success */
-		dev_dbg(&pdx->interface->dev,
-			"%s: OK; zero-len read/write request\n", __func__);
-		return U14ERR_NOERROR;
-	}
-
-	if ((pArea->bCircular) &&	/*  Circular transfer? */
-	    (pArea->bCircToHost) && (Read)) {	/*  In a supported direction */
-				/*  If so, we sort out offset ourself */
-		bool bWait = false;	/*  Flag for transfer having to wait */
-
-		dev_dbg(&pdx->interface->dev,
-			"Circular buffers are %d at %d and %d at %d\n",
-			pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset,
-			pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
-		if (pArea->aBlocks[1].dwSize > 0) {	/*  Using the second block already? */
-			dwOffs = pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize;	/*  take offset from that */
-			bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset;	/*  Wait if will overwrite block 0? */
-			bWait |= (dwOffs + dwLen) > pArea->dwLength;	/*  or if it overflows the buffer */
-		} else {		/*  Area 1 not in use, try to use area 0 */
-			if (pArea->aBlocks[0].dwSize == 0)	/*  Reset block 0 if not in use */
-				pArea->aBlocks[0].dwOffset = 0;
-			dwOffs =
-			    pArea->aBlocks[0].dwOffset +
-			    pArea->aBlocks[0].dwSize;
-			if ((dwOffs + dwLen) > pArea->dwLength) {	/*  Off the end of the buffer? */
-				pArea->aBlocks[1].dwOffset = 0;	/*  Set up to use second block */
-				dwOffs = 0;
-				bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset;	/*  Wait if will overwrite block 0? */
-				bWait |= (dwOffs + dwLen) > pArea->dwLength;	/*  or if it overflows the buffer */
-			}
-		}
-
-		if (bWait) {	/*  This transfer will have to wait? */
-			pdx->bXFerWaiting = true;	/*  Flag we are waiting */
-			dev_dbg(&pdx->interface->dev,
-				"%s: xfer waiting for circular buffer space\n",
-				__func__);
-			return U14ERR_NOERROR;
-		}
-
-		dev_dbg(&pdx->interface->dev,
-			"%s: circular xfer, %d bytes starting at %d\n",
-			__func__, dwLen, dwOffs);
-	}
-	/*  Save the parameters for the read\write transfer */
-	pdx->StagedRead = Read;	/*  Save the parameters for this read */
-	pdx->StagedId = wIdent;	/*  ID allows us to get transfer area info */
-	pdx->StagedOffset = dwOffs;	/*  The area within the transfer area */
-	pdx->StagedLength = dwLen;
-	pdx->StagedDone = 0;	/*  Initialise the byte count */
-	pdx->dwDMAFlag = MODE_LINEAR;	/*  Set DMA mode flag at this point */
-	pdx->bXFerWaiting = false;	/*  Clearly not a transfer waiting now */
-
-/*     KeClearEvent(&pdx->StagingDoneEvent);           // Clear the transfer done event */
-	StageChunk(pdx);	/*  fire off the first chunk */
-
-	return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-**
-** ReadChar
-**
-** Reads a character a buffer. If there is no more
-**  data we return FALSE. Used as part of decoding a DMA request.
-**
-****************************************************************************/
-static bool ReadChar(unsigned char *pChar, char *pBuf, unsigned int *pdDone,
-		     unsigned int dGot)
-{
-	bool bRead = false;
-	unsigned int dDone = *pdDone;
-
-	if (dDone < dGot) {	/*  If there is more data */
-		*pChar = (unsigned char)pBuf[dDone];	/*  Extract the next char */
-		dDone++;	/*  Increment the done count */
-		*pdDone = dDone;
-		bRead = true;	/*  and flag success */
-	}
-
-	return bRead;
-}
-
-#ifdef NOTUSED
-/****************************************************************************
-**
-** ReadWord
-**
-** Reads a word from the 1401, just uses ReadChar twice; passes on any error
-**
-*****************************************************************************/
-static bool ReadWord(unsigned short *pWord, char *pBuf, unsigned int *pdDone,
-		     unsigned int dGot)
-{
-	if (ReadChar((unsigned char *)pWord, pBuf, pdDone, dGot))
-		return ReadChar(((unsigned char *)pWord) + 1, pBuf, pdDone,
-				dGot);
-	else
-		return false;
-}
-#endif
-
-/****************************************************************************
-** ReadHuff
-**
-** Reads a coded number in and returns it, Code is:
-** If data is in range 0..127 we receive 1 byte. If data in range 128-16383
-** we receive two bytes, top bit of first indicates another on its way. If
-** data in range 16384-4194303 we get three bytes, top two bits of first set
-** to indicate three byte total.
-**
-*****************************************************************************/
-static bool ReadHuff(volatile unsigned int *pDWord, char *pBuf,
-		     unsigned int *pdDone, unsigned int dGot)
-{
-	unsigned char ucData;	/* for each read to ReadChar */
-	bool bReturn = true;	/* assume we will succeed */
-	unsigned int dwData = 0;	/* Accumulator for the data */
-
-	if (ReadChar(&ucData, pBuf, pdDone, dGot)) {
-		dwData = ucData;	/* copy the data */
-		if ((dwData & 0x00000080) != 0) {	/* Bit set for more data ? */
-			dwData &= 0x0000007F;	/* Clear the relevant bit */
-			if (ReadChar(&ucData, pBuf, pdDone, dGot)) {
-				dwData = (dwData << 8) | ucData;
-				if ((dwData & 0x00004000) != 0) {	/* three byte sequence ? */
-					dwData &= 0x00003FFF;	/* Clear the relevant bit */
-					if (ReadChar
-					    (&ucData, pBuf, pdDone, dGot))
-						dwData = (dwData << 8) | ucData;
-					else
-						bReturn = false;
-				}
-			} else
-				bReturn = false;	/* couldn't read data */
-		}
-	} else
-		bReturn = false;
-
-	*pDWord = dwData;	/* return the data */
-	return bReturn;
-}
-
-/***************************************************************************
-**
-** ReadDMAInfo
-**
-** Tries to read info about the dma request from the 1401 and decode it into
-** the dma descriptor block. We have at this point had the escape character
-** from the 1401 and now we must read in the rest of the information about
-** the transfer request. Returns FALSE if 1401 fails to respond or obselete
-** code from 1401 or bad parameters.
-**
-** The pBuf char pointer does not include the initial escape character, so
-**  we start handling the data at offset zero.
-**
-*****************************************************************************/
-static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx,
-			char *pBuf, unsigned int dwCount)
-{
-	bool bResult = false;	/*  assume we won't succeed */
-	unsigned char ucData;
-	unsigned int dDone = 0;	/*  We haven't parsed anything so far */
-
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	if (ReadChar(&ucData, pBuf, &dDone, dwCount)) {
-		unsigned char ucTransCode = (ucData & 0x0F);	/*  get code for transfer type */
-		unsigned short wIdent = ((ucData >> 4) & 0x07);	/*  and area identifier */
-
-		/*  fill in the structure we were given */
-		pDmaDesc->wTransType = ucTransCode;	/*  type of transfer */
-		pDmaDesc->wIdent = wIdent;	/*  area to use */
-		pDmaDesc->dwSize = 0;	/*  initialise other bits */
-		pDmaDesc->dwOffset = 0;
-
-		dev_dbg(&pdx->interface->dev, "%s: type: %d ident: %d\n",
-			__func__, pDmaDesc->wTransType, pDmaDesc->wIdent);
-
-		pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST);	/*  set transfer direction */
-
-		switch (ucTransCode) {
-		case TM_EXTTOHOST:	/*  Extended linear transfer modes (the only ones!) */
-		case TM_EXTTO1401:
-			{
-				bResult =
-				    ReadHuff(&(pDmaDesc->dwOffset), pBuf,
-					     &dDone, dwCount)
-				    && ReadHuff(&(pDmaDesc->dwSize), pBuf,
-						&dDone, dwCount);
-				if (bResult) {
-					dev_dbg(&pdx->interface->dev,
-						"%s: xfer offset & size %d %d\n",
-						__func__, pDmaDesc->dwOffset,
-						pDmaDesc->dwSize);
-
-					if ((wIdent >= MAX_TRANSAREAS) ||	/*  Illegal area number, or... */
-					    (!pdx->rTransDef[wIdent].bUsed) ||	/*  area not set up, or... */
-					    (pDmaDesc->dwOffset > pdx->rTransDef[wIdent].dwLength) ||	/*  range/size */
-					    ((pDmaDesc->dwOffset +
-					      pDmaDesc->dwSize) >
-					     (pdx->rTransDef[wIdent].
-					      dwLength))) {
-						bResult = false;	/*  bad parameter(s) */
-						dev_dbg(&pdx->interface->dev,
-							"%s: bad param - id %d, bUsed %d, offset %d, size %d, area length %d\n",
-							__func__, wIdent,
-							pdx->rTransDef[wIdent].
-							bUsed,
-							pDmaDesc->dwOffset,
-							pDmaDesc->dwSize,
-							pdx->rTransDef[wIdent].
-							dwLength);
-					}
-				}
-				break;
-			}
-		default:
-			break;
-		}
-	} else
-		bResult = false;
-
-	if (!bResult)		/*  now check parameters for validity */
-		dev_err(&pdx->interface->dev, "%s: error reading Esc sequence\n",
-			__func__);
-
-	return bResult;
-}
-
-/****************************************************************************
-**
-** Handle1401Esc
-**
-** Deals with an escape sequence coming from the 1401. This can either be
-**  a DMA transfer request of various types or a response to an escape sequence
-**  sent to the 1401. This is called from a callback.
-**
-** Parameters are
-**
-** dwCount - the number of characters in the device extension char in buffer,
-**           this is known to be at least 2 or we will not be called.
-**
-****************************************************************************/
-static int Handle1401Esc(DEVICE_EXTENSION *pdx, char *pCh,
-			 unsigned int dwCount)
-{
-	int iReturn = U14ERR_FAIL;
-
-	/*  I have no idea what this next test is about. '?' is 0x3f, which is area 3, code */
-	/*  15. At the moment, this is not used, so it does no harm, but unless someone can */
-	/*  tell me what this is for, it should be removed from this and the Windows driver. */
-	if (pCh[0] == '?') {	/*  Is this an information response */
-				/*  Parse and save the information */
-	} else {
-		spin_lock(&pdx->stagedLock);	/*  Lock others out */
-
-		if (ReadDMAInfo(&pdx->rDMAInfo, pdx, pCh, dwCount)) {	/*  Get DMA parameters */
-			unsigned short wTransType = pdx->rDMAInfo.wTransType;	/*  check transfer type */
-
-			dev_dbg(&pdx->interface->dev,
-				"%s: xfer to %s, offset %d, length %d\n",
-				__func__,
-				pdx->rDMAInfo.bOutWard ? "1401" : "host",
-				pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
-
-			if (pdx->bXFerWaiting) { /*  Check here for badly out of kilter... */
-				/*  This can never happen, really */
-				dev_err(&pdx->interface->dev,
-					"ERROR: DMA setup while transfer still waiting\n");
-			} else {
-				if ((wTransType == TM_EXTTOHOST)
-				    || (wTransType == TM_EXTTO1401)) {
-					iReturn =
-					    ReadWriteMem(pdx,
-							 !pdx->rDMAInfo.
-							 bOutWard,
-							 pdx->rDMAInfo.wIdent,
-							 pdx->rDMAInfo.dwOffset,
-							 pdx->rDMAInfo.dwSize);
-					if (iReturn != U14ERR_NOERROR)
-						dev_err(&pdx->interface->dev,
-							"%s: ReadWriteMem() failed %d\n",
-							__func__, iReturn);
-				} else	/*  This covers non-linear transfer setup */
-					dev_err(&pdx->interface->dev,
-						"%s: Unknown block xfer type %d\n",
-						__func__, wTransType);
-			}
-		} else		/*  Failed to read parameters */
-			dev_err(&pdx->interface->dev, "%s: ReadDMAInfo() fail\n",
-				__func__);
-
-		spin_unlock(&pdx->stagedLock);	/*  OK here */
-	}
-
-	dev_dbg(&pdx->interface->dev, "%s: returns %d\n", __func__, iReturn);
-
-	return iReturn;
-}
-
-/****************************************************************************
-** Callback for the character read complete or error
-****************************************************************************/
-static void ced_readchar_callback(struct urb *pUrb)
-{
-	DEVICE_EXTENSION *pdx = pUrb->context;
-	int nGot = pUrb->actual_length;	/*  what we transferred */
-
-	if (pUrb->status) {	/*  Do we have a problem to handle? */
-		int nPipe = pdx->nPipes == 4 ? 1 : 0;	/*  The pipe number to use for error */
-		/*  sync/async unlink faults aren't errors... just saying device removed or stopped */
-		if (!
-		    (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
-		     || pUrb->status == -ESHUTDOWN)) {
-			dev_err(&pdx->interface->dev,
-				"%s: nonzero write bulk status received: %d\n",
-				__func__, pUrb->status);
-		} else
-			dev_dbg(&pdx->interface->dev,
-				"%s: 0 chars pUrb->status=%d (shutdown?)\n",
-				__func__, pUrb->status);
-
-		spin_lock(&pdx->err_lock);
-		pdx->errors = pUrb->status;
-		spin_unlock(&pdx->err_lock);
-		nGot = 0;	/*   and tidy up again if so */
-
-		spin_lock(&pdx->charInLock);	/*  already at irq level */
-		pdx->bPipeError[nPipe] = 1;	/*  Flag an error for later */
-	} else {
-		if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) {	/*  Esc sequence? */
-			Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot - 1);	/*  handle it */
-			spin_lock(&pdx->charInLock);	/*  already at irq level */
-		} else {
-			spin_lock(&pdx->charInLock);	/*  already at irq level */
-			if (nGot > 0) {
-				unsigned int i;
-				if (nGot < INBUF_SZ) {
-					pdx->pCoherCharIn[nGot] = 0;	/*  tidy the string */
-					dev_dbg(&pdx->interface->dev,
-						"%s: got %d chars >%s<\n",
-						__func__, nGot,
-						pdx->pCoherCharIn);
-				}
-				/*  We know that whatever we read must fit in the input buffer */
-				for (i = 0; i < nGot; i++) {
-					pdx->inputBuffer[pdx->dwInBuffPut++] =
-					    pdx->pCoherCharIn[i] & 0x7F;
-					if (pdx->dwInBuffPut >= INBUF_SZ)
-						pdx->dwInBuffPut = 0;
-				}
-
-				if ((pdx->dwNumInput + nGot) <= INBUF_SZ)
-					pdx->dwNumInput += nGot;	/*  Adjust the buffer count accordingly */
-			} else
-				dev_dbg(&pdx->interface->dev, "%s: read ZLP\n",
-					__func__);
-		}
-	}
-
-	pdx->bReadCharsPending = false;	/*  No longer have a pending read */
-	spin_unlock(&pdx->charInLock);	/*  already at irq level */
-
-	Allowi(pdx);	/*  see if we can do the next one */
-}
-
-/****************************************************************************
-** Allowi
-**
-** This is used to make sure that there is always a pending input transfer so
-** we can pick up any inward transfers. This can be called in multiple contexts
-** so we use the irqsave version of the spinlock.
-****************************************************************************/
-int Allowi(DEVICE_EXTENSION *pdx)
-{
-	int iReturn = U14ERR_NOERROR;
-	unsigned long flags;
-	spin_lock_irqsave(&pdx->charInLock, flags);	/*  can be called in multiple contexts */
-
-	/*  We don't want char input running while DMA is in progress as we know that this */
-	/*   can cause sequencing problems for the 2270. So don't. It will also allow the */
-	/*   ERR response to get back to the host code too early on some PCs, even if there */
-	/*   is no actual driver failure, so we don't allow this at all. */
-	if (!pdx->bInDrawDown &&	/*  stop input if */
-	    !pdx->bReadCharsPending &&	/*  If no read request outstanding */
-	    (pdx->dwNumInput < (INBUF_SZ / 2)) &&	/*   and there is some space */
-	    (pdx->dwDMAFlag == MODE_CHAR) &&	/*   not doing any DMA */
-	    (!pdx->bXFerWaiting) &&	/*   no xfer waiting to start */
-	    (CanAcceptIoRequests(pdx)))	{ /*   and activity is generally OK */
-				/*   then off we go */
-		unsigned int nMax = INBUF_SZ - pdx->dwNumInput;	/*  max we could read */
-		int nPipe = pdx->nPipes == 4 ? 1 : 0;	/*  The pipe number to use */
-
-		dev_dbg(&pdx->interface->dev, "%s: %d chars in input buffer\n",
-			__func__, pdx->dwNumInput);
-
-		usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev,
-				 usb_rcvintpipe(pdx->udev, pdx->epAddr[nPipe]),
-				 pdx->pCoherCharIn, nMax, ced_readchar_callback,
-				 pdx, pdx->bInterval);
-		pdx->pUrbCharIn->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	/*  short xfers are OK by default */
-		usb_anchor_urb(pdx->pUrbCharIn, &pdx->submitted);	/*  in case we need to kill it */
-		iReturn = usb_submit_urb(pdx->pUrbCharIn, GFP_ATOMIC);
-		if (iReturn) {
-			usb_unanchor_urb(pdx->pUrbCharIn);	/*  remove from list of active Urbs */
-			pdx->bPipeError[nPipe] = 1;	/*  Flag an error to be handled later */
-			dev_err(&pdx->interface->dev,
-				"%s: submit urb failed: %d\n",
-				__func__, iReturn);
-		} else
-			pdx->bReadCharsPending = true;	/*  Flag that we are active here */
-	}
-
-	spin_unlock_irqrestore(&pdx->charInLock, flags);
-
-	return iReturn;
-
-}
-
-/*****************************************************************************
-** The ioctl entry point to the driver that is used by us to talk to it.
-** inode    The device node (no longer in 3.0.0 kernels)
-** file     The file that is open, which holds our pdx pointer
-** ulArg    The argument passed in. Note that long is 64-bits in 64-bit system, i.e. it is big
-**          enough for a 64-bit pointer.
-*****************************************************************************/
-static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg)
-{
-	int err = 0;
-	DEVICE_EXTENSION *pdx = file->private_data;
-	if (!CanAcceptIoRequests(pdx))	/*  check we still exist */
-		return -ENODEV;
-
-	/*  Check that access is allowed, where is is needed. Anything that would have an indeterminate */
-	/*  size will be checked by the specific command. */
-	if (_IOC_DIR(cmd) & _IOC_READ)	/*  read from point of view of user... */
-		err = !access_ok(VERIFY_WRITE, (void __user *)ulArg, _IOC_SIZE(cmd));	/*  is kernel write */
-	else if (_IOC_DIR(cmd) & _IOC_WRITE)	/*  and write from point of view of user... */
-		err = !access_ok(VERIFY_READ, (void __user *)ulArg, _IOC_SIZE(cmd));	/*  is kernel read */
-	if (err)
-		return -EFAULT;
-
-	switch (_IOC_NR(cmd)) {
-	case _IOC_NR(IOCTL_CED_SENDSTRING(0)):
-		return SendString(pdx, (const char __user *)ulArg,
-				  _IOC_SIZE(cmd));
-
-	case _IOC_NR(IOCTL_CED_RESET1401):
-		return Reset1401(pdx);
-
-	case _IOC_NR(IOCTL_CED_GETCHAR):
-		return GetChar(pdx);
-
-	case _IOC_NR(IOCTL_CED_SENDCHAR):
-		return SendChar(pdx, (char)ulArg);
-
-	case _IOC_NR(IOCTL_CED_STAT1401):
-		return Stat1401(pdx);
-
-	case _IOC_NR(IOCTL_CED_LINECOUNT):
-		return LineCount(pdx);
-
-	case _IOC_NR(IOCTL_CED_GETSTRING(0)):
-		return GetString(pdx, (char __user *)ulArg, _IOC_SIZE(cmd));
-
-	case _IOC_NR(IOCTL_CED_SETTRANSFER):
-		return SetTransfer(pdx, (struct transfer_area_desc __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_UNSETTRANSFER):
-		return UnsetTransfer(pdx, (int)ulArg);
-
-	case _IOC_NR(IOCTL_CED_SETEVENT):
-		return SetEvent(pdx, (struct transfer_event __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE):
-		return GetOutBufSpace(pdx);
-
-	case _IOC_NR(IOCTL_CED_GETBASEADDRESS):
-		return -1;
-
-	case _IOC_NR(IOCTL_CED_GETDRIVERREVISION):
-		return (2 << 24) | (DRIVERMAJREV << 16) | DRIVERMINREV;	/*  USB | MAJOR | MINOR */
-
-	case _IOC_NR(IOCTL_CED_GETTRANSFER):
-		return GetTransfer(pdx, (TGET_TX_BLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_KILLIO1401):
-		return KillIO1401(pdx);
-
-	case _IOC_NR(IOCTL_CED_STATEOF1401):
-		return StateOf1401(pdx);
-
-	case _IOC_NR(IOCTL_CED_GRAB1401):
-	case _IOC_NR(IOCTL_CED_FREE1401):
-		return U14ERR_NOERROR;
-
-	case _IOC_NR(IOCTL_CED_STARTSELFTEST):
-		return StartSelfTest(pdx);
-
-	case _IOC_NR(IOCTL_CED_CHECKSELFTEST):
-		return CheckSelfTest(pdx, (TGET_SELFTEST __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_TYPEOF1401):
-		return TypeOf1401(pdx);
-
-	case _IOC_NR(IOCTL_CED_TRANSFERFLAGS):
-		return TransferFlags(pdx);
-
-	case _IOC_NR(IOCTL_CED_DBGPEEK):
-		return DbgPeek(pdx, (TDBGBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_DBGPOKE):
-		return DbgPoke(pdx, (TDBGBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_DBGRAMPDATA):
-		return DbgRampData(pdx, (TDBGBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_DBGRAMPADDR):
-		return DbgRampAddr(pdx, (TDBGBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_DBGGETDATA):
-		return DbgGetData(pdx, (TDBGBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_DBGSTOPLOOP):
-		return DbgStopLoop(pdx);
-
-	case _IOC_NR(IOCTL_CED_FULLRESET):
-		pdx->bForceReset = true;	/*  Set a flag for a full reset */
-		break;
-
-	case _IOC_NR(IOCTL_CED_SETCIRCULAR):
-		return SetCircular(pdx, (struct transfer_area_desc __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_GETCIRCBLOCK):
-		return GetCircBlock(pdx, (TCIRCBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_FREECIRCBLOCK):
-		return FreeCircBlock(pdx, (TCIRCBLOCK __user *) ulArg);
-
-	case _IOC_NR(IOCTL_CED_WAITEVENT):
-		return WaitEvent(pdx, (int)(ulArg & 0xff), (int)(ulArg >> 8));
-
-	case _IOC_NR(IOCTL_CED_TESTEVENT):
-		return TestEvent(pdx, (int)ulArg);
-
-	default:
-		return U14ERR_NO_SUCH_FN;
-	}
-	return U14ERR_NOERROR;
-}
-
-static const struct file_operations ced_fops = {
-	.owner = THIS_MODULE,
-	.open = ced_open,
-	.release = ced_release,
-	.flush = ced_flush,
-	.llseek = noop_llseek,
-	.unlocked_ioctl = ced_ioctl,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with the driver core
- */
-static struct usb_class_driver ced_class = {
-	.name = "cedusb%d",
-	.fops = &ced_fops,
-	.minor_base = USB_CED_MINOR_BASE,
-};
-
-/*  Check that the device that matches a 1401 vendor and product ID is OK to use and */
-/*  initialise our DEVICE_EXTENSION. */
-static int ced_probe(struct usb_interface *interface,
-		     const struct usb_device_id *id)
-{
-	DEVICE_EXTENSION *pdx;
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *endpoint;
-	int i, bcdDevice;
-	int retval = -ENOMEM;
-
-	/*  allocate memory for our device extension and initialize it */
-	pdx = kzalloc(sizeof(*pdx), GFP_KERNEL);
-	if (!pdx)
-		goto error;
-
-	for (i = 0; i < MAX_TRANSAREAS; ++i) {	/*  Initialise the wait queues */
-		init_waitqueue_head(&pdx->rTransDef[i].wqEvent);
-	}
-
-	/*  Put initialises for our stuff here. Note that all of *pdx is zero, so */
-	/*  no need to explicitly zero it. */
-	spin_lock_init(&pdx->charOutLock);
-	spin_lock_init(&pdx->charInLock);
-	spin_lock_init(&pdx->stagedLock);
-
-	/*  Initialises from the skeleton stuff */
-	kref_init(&pdx->kref);
-	mutex_init(&pdx->io_mutex);
-	spin_lock_init(&pdx->err_lock);
-	init_usb_anchor(&pdx->submitted);
-
-	pdx->udev = usb_get_dev(interface_to_usbdev(interface));
-	pdx->interface = interface;
-
-	/*  Attempt to identify the device */
-	bcdDevice = pdx->udev->descriptor.bcdDevice;
-	i = (bcdDevice >> 8);
-	if (i == 0)
-		pdx->s1401Type = TYPEU1401;
-	else if ((i >= 1) && (i <= 23))
-		pdx->s1401Type = i + 2;
-	else {
-		dev_err(&interface->dev, "%s: Unknown device. bcdDevice = %d\n",
-			__func__, bcdDevice);
-		goto error;
-	}
-	/*  set up the endpoint information. We only care about the number of EP as */
-	/*  we know that we are dealing with a 1401 device. */
-	iface_desc = interface->cur_altsetting;
-	pdx->nPipes = iface_desc->desc.bNumEndpoints;
-	dev_info(&interface->dev, "1401Type=%d with %d End Points\n",
-		 pdx->s1401Type, pdx->nPipes);
-	if ((pdx->nPipes < 3) || (pdx->nPipes > 4))
-		goto error;
-
-	/*  Allocate the URBs we hold for performing transfers */
-	pdx->pUrbCharOut = usb_alloc_urb(0, GFP_KERNEL);	/*  character output URB */
-	pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL);	/*  character input URB */
-	pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL);	/*  block transfer URB */
-	if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb) {
-		dev_err(&interface->dev, "%s: URB alloc failed\n", __func__);
-		goto error;
-	}
-
-	pdx->pCoherStagedIO =
-	    usb_alloc_coherent(pdx->udev, STAGED_SZ, GFP_KERNEL,
-			       &pdx->pStagedUrb->transfer_dma);
-	pdx->pCoherCharOut =
-	    usb_alloc_coherent(pdx->udev, OUTBUF_SZ, GFP_KERNEL,
-			       &pdx->pUrbCharOut->transfer_dma);
-	pdx->pCoherCharIn =
-	    usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL,
-			       &pdx->pUrbCharIn->transfer_dma);
-	if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO) {
-		dev_err(&interface->dev, "%s: Coherent buffer alloc failed\n",
-			__func__);
-		goto error;
-	}
-
-	for (i = 0; i < pdx->nPipes; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-		pdx->epAddr[i] = endpoint->bEndpointAddress;
-		dev_info(&interface->dev, "Pipe %d, ep address %02x\n",
-			 i, pdx->epAddr[i]);
-		if (((pdx->nPipes == 3) && (i == 0)) ||	/*  if char input end point */
-		    ((pdx->nPipes == 4) && (i == 1))) {
-			pdx->bInterval = endpoint->bInterval;	/*  save the endpoint interrupt interval */
-			dev_info(&interface->dev, "Pipe %d, bInterval = %d\n",
-				 i, pdx->bInterval);
-		}
-		/*  Detect USB2 by checking last ep size (64 if USB1) */
-		if (i == pdx->nPipes - 1) {	/*  if this is the last ep (bulk) */
-			pdx->bIsUSB2 =
-			    le16_to_cpu(endpoint->wMaxPacketSize) > 64;
-			dev_info(&pdx->interface->dev, "USB%d\n",
-				 pdx->bIsUSB2 + 1);
-		}
-	}
-
-	/* save our data pointer in this interface device */
-	usb_set_intfdata(interface, pdx);
-
-	/* we can register the device now, as it is ready */
-	retval = usb_register_dev(interface, &ced_class);
-	if (retval) {
-		/* something prevented us from registering this driver */
-		dev_err(&interface->dev,
-			"Not able to get a minor for this device\n");
-		usb_set_intfdata(interface, NULL);
-		goto error;
-	}
-
-	/* let the user know what node this device is now attached to */
-	dev_info(&interface->dev,
-		 "USB CEDUSB device now attached to cedusb #%d\n",
-		 interface->minor);
-	return 0;
-
-error:
-	if (pdx)
-		kref_put(&pdx->kref, ced_delete);	/*  frees allocated memory */
-	return retval;
-}
-
-static void ced_disconnect(struct usb_interface *interface)
-{
-	DEVICE_EXTENSION *pdx = usb_get_intfdata(interface);
-	int minor = interface->minor;
-	int i;
-
-	usb_set_intfdata(interface, NULL);	/*  remove the pdx from the interface */
-	usb_deregister_dev(interface, &ced_class);	/*  give back our minor device number */
-
-	mutex_lock(&pdx->io_mutex);	/*  stop more I/O starting while... */
-	ced_draw_down(pdx);	/*  ...wait for then kill any io */
-	for (i = 0; i < MAX_TRANSAREAS; ++i) {
-		int iErr = ClearArea(pdx, i);	/*  ...release any used memory */
-		if (iErr == U14ERR_UNLOCKFAIL)
-			dev_err(&pdx->interface->dev, "%s: Area %d was in used\n",
-				__func__, i);
-	}
-	pdx->interface = NULL;	/*  ...we kill off link to interface */
-	mutex_unlock(&pdx->io_mutex);
-
-	usb_kill_anchored_urbs(&pdx->submitted);
-
-	kref_put(&pdx->kref, ced_delete);	/*  decrement our usage count */
-
-	dev_info(&interface->dev, "USB cedusb #%d now disconnected\n", minor);
-}
-
-/*  Wait for all the urbs we know of to be done with, then kill off any that */
-/*  are left. NBNB we will need to have a mechanism to stop circular xfers */
-/*  from trying to fire off more urbs. We will wait up to 3 seconds for Urbs */
-/*  to be done. */
-void ced_draw_down(DEVICE_EXTENSION *pdx)
-{
-	int time;
-	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
-
-	pdx->bInDrawDown = true;
-	time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
-	if (!time) {		/*  if we timed out we kill the urbs */
-		usb_kill_anchored_urbs(&pdx->submitted);
-		dev_err(&pdx->interface->dev, "%s: timed out\n", __func__);
-	}
-	pdx->bInDrawDown = false;
-}
-
-static int ced_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	if (!pdx)
-		return 0;
-	ced_draw_down(pdx);
-
-	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
-	return 0;
-}
-
-static int ced_resume(struct usb_interface *intf)
-{
-	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	if (!pdx)
-		return 0;
-	dev_dbg(&pdx->interface->dev, "%s: called\n", __func__);
-	return 0;
-}
-
-static int ced_pre_reset(struct usb_interface *intf)
-{
-	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-	mutex_lock(&pdx->io_mutex);
-	ced_draw_down(pdx);
-	return 0;
-}
-
-static int ced_post_reset(struct usb_interface *intf)
-{
-	DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
-	dev_dbg(&pdx->interface->dev, "%s\n", __func__);
-
-	/* we are sure no URBs are active - no locking needed */
-	pdx->errors = -EPIPE;
-	mutex_unlock(&pdx->io_mutex);
-
-	return 0;
-}
-
-static struct usb_driver ced_driver = {
-	.name = "cedusb",
-	.probe = ced_probe,
-	.disconnect = ced_disconnect,
-	.suspend = ced_suspend,
-	.resume = ced_resume,
-	.pre_reset = ced_pre_reset,
-	.post_reset = ced_post_reset,
-	.id_table = ced_table,
-	.supports_autosuspend = 1,
-};
-
-module_usb_driver(ced_driver);
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/usb1401.h linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/usb1401.h
--- linux-libre-3.16-gnu/drivers/staging/ced1401/usb1401.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/usb1401.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/* usb1401.h
- Header file for the CED 1401 USB device driver for Linux
- Copyright (C) 2010 Cambridge Electronic Design Ltd
- Author Greg P Smith (greg@ced.co.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*/
-#ifndef __USB1401_H__
-#define __USB1401_H__
-#include "use1401.h"
-#include "ced_ioctl.h"
-
-#ifndef UINT
-#define UINT unsigned int
-#endif
-
-/** Device type codes, but these don't need to be extended - a succession is assumed
-** These are set for usb from the bcdDevice field (suitably mangled). Future devices
-** will be added in order of device creation to the list, so the names here are just
-** to help use remember which device is which. The U14ERR_... values follow the same
-** pattern for modern devices.a
-**/
-#define TYPEUNKNOWN        -1             /*  dont know */
-#define TYPE1401           0              /*  standard 1401 */
-#define TYPEPLUS           1              /*  1401 plus */
-#define TYPEU1401          2              /*  u1401 */
-#define TYPEPOWER          3              /*  Power1401 */
-#define TYPEU14012         4              /*  u1401 mkII */
-#define TYPEPOWER2         5              /*  Power1401 mk II */
-#define TYPEMICRO3         6              /*  Micro1401-3 */
-#define TYPEPOWER3         7              /*  Power1401-3 */
-
-/*  Some useful defines of constants. DONT FORGET to change the version in the */
-/*  resources whenever you change it here!. */
-#define DRIVERMAJREV      2             /*  driver revision level major (match windows) */
-#define DRIVERMINREV      0             /*  driver revision level minor */
-
-/*  Definitions of the various block transfer command codes */
-#define TM_EXTTOHOST    8               /*  extended tohost */
-#define TM_EXTTO1401    9               /*  extended to1401 */
-
-/*  Definitions of values in usbReqtype. Used in sorting out setup actions */
-#define H_TO_D 0x00
-#define D_TO_H 0x80
-#define VENDOR 0x40
-#define DEVREQ 0x00
-#define INTREQ 0x01
-#define ENDREQ 0x02
-
-/*  Definition of values in usbRequest, again used to sort out setup */
-#define GET_STATUS      0x00
-#define CLEAR_FEATURE   0x01
-#define SET_FEATURE     0x03
-#define SET_ADDRESS     0x05
-#define GET_DESC        0x06
-#define SET_DESC        0x07
-#define GET_CONF        0x08
-#define SET_CONF        0x09
-#define GET_INTERFACE   0x0a
-#define SET_INTERFACE   0x0b
-#define SYNCH_FRAME     0x0c
-
-/*  Definitions of the various debug command codes understood by the 1401. These */
-/*  are used in various vendor-specific commands to achieve the desired effect */
-#define DB_GRAB         0x50            /* Grab is a NOP for USB */
-#define DB_FREE         0x51            /* Free is a NOP for the USB */
-#define DB_SETADD       0x52            /* Set debug address (double) */
-#define DB_SELFTEST     0x53            /* Start self test */
-#define DB_SETMASK      0x54            /* Set enable mask (double) */
-#define DB_SETDEF       0x55            /* Set default mask (double) */
-#define DB_PEEK         0x56            /* Peek address, save result */
-#define DB_POKE         0x57            /* Poke address with data (double) */
-#define DB_RAMPD        0x58            /* Ramp data at debug address */
-#define DB_RAMPA        0x59            /* Ramp address bus */
-#define DB_REPEATS      0x5A            /* Set repeats for operations (double) */
-#define DB_WIDTH        0x5B            /* Set width for operations (byte) */
-#define DB_DATA         0x5C            /* Get 4-byte data read by PEEK */
-#define DB_CHARS        0x5D            /* Send chars via EP0 control write */
-
-#define CR_CHAR          0x0D           /* The carriage return character */
-#define CR_CHAR_80       0x8d           /*  and with bit 7 set */
-
-/*  A structure holding information about a block of memory for use in circular transfers */
-typedef struct circBlk {
-	volatile UINT dwOffset;             /* Offset within area of block start */
-	volatile UINT dwSize;               /* Size of the block, in bytes (0 = unused) */
-} CIRCBLK;
-
-/*  A structure holding all of the information about a transfer area - an area of */
-/*   memory set up for use either as a source or destination in DMA transfers. */
-typedef struct transarea {
-	void	*lpvBuff;                /*  User address of xfer area saved for completeness */
-	UINT        dwBaseOffset;           /*  offset to start of xfer area in first page */
-	UINT        dwLength;               /*  Length of xfer area, in bytes */
-	struct page **pPages;               /*  Points at array of locked down pages */
-	int         nPages;                 /*  number of pages that are locked down */
-	bool        bUsed;                  /*  Is this structure in use? */
-	bool        bCircular;              /*  Is this area for circular transfers? */
-	bool        bCircToHost;            /*  Flag for direction of circular transfer */
-	bool        bEventToHost;           /*  Set event on transfer to host? */
-	int         iWakeUp;                /*  Set 1 on event, cleared by TestEvent() */
-	UINT        dwEventSt;              /*  Defines section within xfer area for... */
-	UINT        dwEventSz;              /*  ...notification by the event SZ is 0 if unset */
-	CIRCBLK     aBlocks[2];             /*  Info on a pair of circular blocks */
-	wait_queue_head_t wqEvent;          /*  The wait queue for events in this area MUST BE LAST */
-} TRANSAREA;
-
-/*  The DMADESC structure is used to hold information on the transfer in progress. It */
-/*  is set up by ReadDMAInfo, using information sent by the 1401 in an escape sequence. */
-typedef struct dmadesc {
-	unsigned short wTransType;          /* transfer type as TM_xxx above        */
-	unsigned short wIdent;              /* identifier word                      */
-	unsigned int   dwSize;              /* bytes to transfer                    */
-	unsigned int   dwOffset;            /* offset into transfer area for trans  */
-	bool           bOutWard;            /* true when data is going TO 1401      */
-} DMADESC;
-
-#define INBUF_SZ         256            /* input buffer size */
-#define OUTBUF_SZ        256            /* output buffer size */
-#define STAGED_SZ 0x10000               /*  size of coherent buffer for staged transfers */
-
-/*  Structure to hold all of our device specific stuff. We are making this as similar as we */
-/*  can to the Windows driver to help in our understanding of what is going on. */
-typedef struct _DEVICE_EXTENSION {
-	char inputBuffer[INBUF_SZ];         /* The two buffers */
-	char outputBuffer[OUTBUF_SZ];       /* accessed by the host functions */
-	volatile unsigned int dwNumInput;   /* num of chars in input buffer   */
-	volatile unsigned int dwInBuffGet;  /* where to get from input buffer */
-	volatile unsigned int dwInBuffPut;  /* where to put into input buffer */
-	volatile unsigned int dwNumOutput;  /* num of chars in output buffer  */
-	volatile unsigned int dwOutBuffGet; /* where to get from output buffer*/
-	volatile unsigned int dwOutBuffPut; /* where to put into output buffer*/
-
-	volatile bool bSendCharsPending;    /* Flag to indicate sendchar active */
-	volatile bool bReadCharsPending;    /* Flag to indicate a read is primed */
-	char *pCoherCharOut;                /* special aligned buffer for chars to 1401 */
-	struct urb *pUrbCharOut;            /* urb used for chars to 1401 */
-	char *pCoherCharIn;                 /* special aligned buffer for chars to host */
-	struct urb *pUrbCharIn;             /* urb used for chars to host */
-
-	spinlock_t charOutLock;             /* to protect the outputBuffer and outputting */
-	spinlock_t charInLock;              /* to protect the inputBuffer and char reads */
-	__u8 bInterval;                     /* Interrupt end point interval */
-
-	volatile unsigned int dwDMAFlag;    /* state of DMA */
-	TRANSAREA rTransDef[MAX_TRANSAREAS];/* transfer area info */
-	volatile DMADESC rDMAInfo;          /*  info on current DMA transfer */
-	volatile bool bXFerWaiting;         /*  Flag set if DMA transfer stalled */
-	volatile bool bInDrawDown;          /*  Flag that we want to halt transfers */
-
-	/*  Parameters relating to a block read\write that is in progress. Some of these values */
-	/*   are equivalent to values in rDMAInfo. The values here are those in use, while those */
-	/*   in rDMAInfo are those received from the 1401 via an escape sequence. If another */
-	/*   escape sequence arrives before the previous xfer ends, rDMAInfo values are updated while these */
-	/*   are used to finish off the current transfer. */
-	volatile short StagedId;            /*  The transfer area id for this transfer */
-	volatile bool StagedRead;           /*  Flag TRUE for read from 1401, FALSE for write */
-	volatile unsigned int StagedLength; /*  Total length of this transfer */
-	volatile unsigned int StagedOffset; /*  Offset within memory area for transfer start */
-	volatile unsigned int StagedDone;   /*  Bytes transferred so far */
-	volatile bool bStagedUrbPending;    /*  Flag to indicate active */
-	char *pCoherStagedIO;               /*  buffer used for block transfers */
-	struct urb *pStagedUrb;             /*  The URB to use */
-	spinlock_t stagedLock;              /*  protects ReadWriteMem() and circular buffer stuff */
-
-	short s1401Type;                    /*  type of 1401 attached */
-	short sCurrentState;                /*  current error state */
-	bool bIsUSB2;                       /*  type of the interface we connect to */
-	bool bForceReset;                   /*  Flag to make sure we get a real reset */
-	__u32 statBuf[2];                   /*  buffer for 1401 state info */
-
-	unsigned long ulSelfTestTime;       /*  used to timeout self test */
-
-	int nPipes;                         /*  Should be 3 or 4 depending on 1401 usb chip */
-	int bPipeError[4];                  /*  set non-zero if an error on one of the pipe */
-	__u8 epAddr[4];                     /*  addresses of the 3/4 end points */
-
-	struct usb_device *udev;            /*  the usb device for this device */
-	struct usb_interface *interface;    /*  the interface for this device, NULL if removed */
-	struct usb_anchor submitted;        /*  in case we need to retract our submissions */
-	struct mutex io_mutex;              /*  synchronize I/O with disconnect, one user-mode caller at a time */
-
-	int    errors;                      /*  the last request tanked */
-	int    open_count;                  /*  count the number of openers */
-	spinlock_t err_lock;                /*  lock for errors */
-	struct kref kref;
-} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
-#define to_DEVICE_EXTENSION(d) container_of(d, DEVICE_EXTENSION, kref)
-
-/*  Definitions of routimes used between compilation object files */
-/*  in usb1401.c */
-extern int Allowi(DEVICE_EXTENSION *pdx);
-extern int SendChars(DEVICE_EXTENSION *pdx);
-extern void ced_draw_down(DEVICE_EXTENSION *pdx);
-extern int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
-				unsigned int dwOffs, unsigned int dwLen);
-
-/*  in ced_ioc.c */
-extern int ClearArea(DEVICE_EXTENSION *pdx, int nArea);
-extern int SendString(DEVICE_EXTENSION *pdx, const char __user *pData, unsigned int n);
-extern int SendChar(DEVICE_EXTENSION *pdx, char c);
-extern int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error);
-extern int ReadWrite_Cancel(DEVICE_EXTENSION *pdx);
-extern bool Is1401(DEVICE_EXTENSION *pdx);
-extern bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset);
-extern int Reset1401(DEVICE_EXTENSION *pdx);
-extern int GetChar(DEVICE_EXTENSION *pdx);
-extern int GetString(DEVICE_EXTENSION *pdx, char __user *pUser, int n);
-extern int SetTransfer(DEVICE_EXTENSION *pdx, struct transfer_area_desc __user *pTD);
-extern int UnsetTransfer(DEVICE_EXTENSION *pdx, int nArea);
-extern int SetEvent(DEVICE_EXTENSION *pdx, struct transfer_event __user *pTE);
-extern int Stat1401(DEVICE_EXTENSION *pdx);
-extern int LineCount(DEVICE_EXTENSION *pdx);
-extern int GetOutBufSpace(DEVICE_EXTENSION *pdx);
-extern int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pGTB);
-extern int KillIO1401(DEVICE_EXTENSION *pdx);
-extern int BlkTransState(DEVICE_EXTENSION *pdx);
-extern int StateOf1401(DEVICE_EXTENSION *pdx);
-extern int StartSelfTest(DEVICE_EXTENSION *pdx);
-extern int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST);
-extern int TypeOf1401(DEVICE_EXTENSION *pdx);
-extern int TransferFlags(DEVICE_EXTENSION *pdx);
-extern int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
-extern int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
-extern int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
-extern int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
-extern int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
-extern int DbgStopLoop(DEVICE_EXTENSION *pdx);
-extern int SetCircular(DEVICE_EXTENSION *pdx, struct transfer_area_desc __user *pTD);
-extern int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB);
-extern int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB);
-extern int WaitEvent(DEVICE_EXTENSION *pdx, int nArea, int msTimeOut);
-extern int TestEvent(DEVICE_EXTENSION *pdx, int nArea);
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/use1401.h linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/use1401.h
--- linux-libre-3.16-gnu/drivers/staging/ced1401/use1401.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/use1401.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,288 +0,0 @@
-/****************************************************************************
-** use1401.h
-** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010
-** Authors: Paul Cox, Tim Bergel, Greg Smith
-** See CVS for revisions.
-**
-** Because the size of a long is different between 32-bit and 64-bit on some
-** systems, we avoid this in this interface.
-****************************************************************************/
-#ifndef __USE1401_H__
-#define __USE1401_H__
-#include "machine.h"
-
-/*  Some definitions to make things compatible. If you want to use Use1401 directly */
-/*   from a Windows program you should define U14_NOT_DLL, in which case you also */
-/*   MUST make sure that your application startup code calls U14InitLib(). */
-/*  DLL_USE1401 is defined when you are building the Use1401 dll, not otherwise. */
-#ifdef _IS_WINDOWS_
-#ifndef U14_NOT_DLL
-#ifdef DLL_USE1401
-#define U14API(retType) (retType DllExport __stdcall)
-#else
-#define U14API(retType) (retType DllImport __stdcall)
-#endif
-#endif
-
-#define U14ERRBASE -500
-#define U14LONG long
-#endif
-
-#ifdef LINUX
-#define U14ERRBASE -1000
-#define U14LONG int
-#endif
-
-#ifdef _QT
-#ifndef U14_NOT_DLL
-#undef U14API
-#define U14API(retType) (retType __declspec(dllimport) __stdcall)
-#endif
-#undef U14LONG
-#define U14LONG int
-#endif
-
-#ifndef U14API
-#define U14API(retType) retType
-#endif
-
-#ifndef U14LONG
-#define U14LONG long
-#endif
-
-/* Error codes: We need them here as user space can see them. */
-#define U14ERR_NOERROR        0             /*  no problems */
-
-/* Device error codes, but these don't need to be extended - a succession is assumed */
-#define U14ERR_STD            4              /*  standard 1401 connected */
-#define U14ERR_U1401          5              /*  u1401 connected */
-#define U14ERR_PLUS           6              /*  1401 plus connected */
-#define U14ERR_POWER          7              /*  Power1401 connected */
-#define U14ERR_U14012         8              /*  u1401 mkII connected */
-#define U14ERR_POWER2         9
-#define U14ERR_U14013        10
-#define U14ERR_POWER3        11
-
-/* NBNB Error numbers need shifting as some linux error codes start at 512 */
-#define U14ERR(n)             (n+U14ERRBASE)
-#define U14ERR_OFF            U14ERR(0)      /* 1401 there but switched off    */
-#define U14ERR_NC             U14ERR(-1)     /* 1401 not connected             */
-#define U14ERR_ILL            U14ERR(-2)     /* if present it is ill           */
-#define U14ERR_NOIF           U14ERR(-3)     /* I/F card missing               */
-#define U14ERR_TIME           U14ERR(-4)     /* 1401 failed to come ready      */
-#define U14ERR_BADSW          U14ERR(-5)     /* I/F card bad switches          */
-#define U14ERR_PTIME          U14ERR(-6)     /* 1401plus failed to come ready  */
-#define U14ERR_NOINT          U14ERR(-7)     /* couldn't grab the int vector   */
-#define U14ERR_INUSE          U14ERR(-8)     /* 1401 is already in use         */
-#define U14ERR_NODMA          U14ERR(-9)     /* couldn't get DMA channel       */
-#define U14ERR_BADHAND        U14ERR(-10)    /* handle provided was bad        */
-#define U14ERR_BAD1401NUM     U14ERR(-11)    /* 1401 number provided was bad   */
-
-#define U14ERR_NO_SUCH_FN     U14ERR(-20)    /* no such function               */
-#define U14ERR_NO_SUCH_SUBFN  U14ERR(-21)    /* no such sub function           */
-#define U14ERR_NOOUT          U14ERR(-22)    /* no room in output buffer       */
-#define U14ERR_NOIN           U14ERR(-23)    /* no input in buffer             */
-#define U14ERR_STRLEN         U14ERR(-24)    /* string longer than buffer      */
-#define U14ERR_ERR_STRLEN     U14ERR(-24)    /* string longer than buffer      */
-#define U14ERR_LOCKFAIL       U14ERR(-25)    /* failed to lock memory          */
-#define U14ERR_UNLOCKFAIL     U14ERR(-26)    /* failed to unlock memory        */
-#define U14ERR_ALREADYSET     U14ERR(-27)    /* area already set up            */
-#define U14ERR_NOTSET         U14ERR(-28)    /* area not set up                */
-#define U14ERR_BADAREA        U14ERR(-29)    /* illegal area number            */
-#define U14ERR_FAIL           U14ERR(-30)    /* we failed for some other reason*/
-
-#define U14ERR_NOFILE         U14ERR(-40)    /* command file not found         */
-#define U14ERR_READERR        U14ERR(-41)    /* error reading command file     */
-#define U14ERR_UNKNOWN        U14ERR(-42)    /* unknown command                */
-#define U14ERR_HOSTSPACE      U14ERR(-43)    /* not enough host space to load  */
-#define U14ERR_LOCKERR        U14ERR(-44)    /* could not lock resource/command*/
-#define U14ERR_CLOADERR       U14ERR(-45)    /* CLOAD command failed           */
-
-#define U14ERR_TOXXXERR       U14ERR(-60)    /* tohost/1401 failed             */
-#define U14ERR_NO386ENH       U14ERR(-80)    /* not 386 enhanced mode          */
-#define U14ERR_NO1401DRIV     U14ERR(-81)    /* no device driver               */
-#define U14ERR_DRIVTOOOLD     U14ERR(-82)    /* device driver too old          */
-
-#define U14ERR_TIMEOUT        U14ERR(-90)    /* timeout occurred               */
-
-#define U14ERR_BUFF_SMALL     U14ERR(-100)   /* buffer for getstring too small */
-#define U14ERR_CBALREADY      U14ERR(-101)   /* there is already a callback    */
-#define U14ERR_BADDEREG       U14ERR(-102)   /* bad parameter to deregcallback */
-#define U14ERR_NOMEMORY       U14ERR(-103)   /* no memory for allocation       */
-
-#define U14ERR_DRIVCOMMS      U14ERR(-110)   /* failed talking to driver       */
-#define U14ERR_OUTOFMEMORY    U14ERR(-111)   /* needed memory and couldnt get it*/
-
-/* / 1401 type codes. */
-#define U14TYPE1401           0           /* standard 1401                  */
-#define U14TYPEPLUS           1           /* 1401 plus                      */
-#define U14TYPEU1401          2           /* u1401                          */
-#define U14TYPEPOWER          3           /* power1401                      */
-#define U14TYPEU14012         4           /* u1401 mk II                    */
-#define U14TYPEPOWER2         5           /* power1401 mk II                */
-#define U14TYPEU14013         6           /* u1401-3                        */
-#define U14TYPEPOWER3         7           /* power1401-3                    */
-#define U14TYPEUNKNOWN        -1          /* dont know                      */
-
-/* Transfer flags to allow driver capabilities to be interrogated */
-
-/* Constants for transfer flags */
-#define U14TF_USEDMA          1           /* Transfer flag for use DMA      */
-#define U14TF_MULTIA          2           /* Transfer flag for multi areas  */
-#define U14TF_FIFO            4           /* for FIFO interface card        */
-#define U14TF_USB2            8           /* for USB2 interface and 1401    */
-#define U14TF_NOTIFY          16          /* for event notifications        */
-#define U14TF_SHORT           32          /* for PCI can short cycle        */
-#define U14TF_PCI2            64          /* for new PCI card 1401-70       */
-#define U14TF_CIRCTH          128         /* Circular-mode to host          */
-#define U14TF_DIAG            256         /* Diagnostics/debug functions    */
-#define U14TF_CIRC14          512         /* Circular-mode to 1401          */
-
-/* Definitions of element sizes for DMA transfers - to allow byte-swapping */
-#define ESZBYTES              0           /* BYTE element size value        */
-#define ESZWORDS              1           /* unsigned short element size value        */
-#define ESZLONGS              2           /* long element size value        */
-#define ESZUNKNOWN            0           /* unknown element size value     */
-
-/* These define required access types for the debug/diagnostics function */
-#define BYTE_SIZE             1           /* 8-bit access                   */
-#define WORD_SIZE             2           /* 16-bit access                  */
-#define LONG_SIZE             3           /* 32-bit access                  */
-
-/* Stuff used by U14_GetTransfer */
-#define GET_TX_MAXENTRIES  257          /* (max length / page size + 1) */
-
-#ifdef _IS_WINDOWS_
-#pragma pack(1)
-
-typedef struct                          /* used for U14_GetTransfer results */
-{                                          /* Info on a single mapped block */
-	U14LONG physical;
-	U14LONG size;
-} TXENTRY;
-
-typedef struct TGetTxBlock              /* used for U14_GetTransfer results */
-{                                               /* matches structure in VXD */
-	U14LONG size;
-	U14LONG linear;
-	short   seg;
-	short   reserved;
-	short   avail;                      /* number of available entries */
-	short   used;                       /* number of used entries */
-	TXENTRY entries[GET_TX_MAXENTRIES];       /* Array of mapped block info */
-} TGET_TX_BLOCK;
-
-typedef TGET_TX_BLOCK *LPGET_TX_BLOCK;
-
-#pragma pack()
-#endif
-
-#ifdef LINUX
-typedef struct                          /* used for U14_GetTransfer results */
-{                                       /* Info on a single mapped block */
-	long long physical;
-	long     size;
-} TXENTRY;
-
-typedef struct TGetTxBlock              /* used for U14_GetTransfer results */
-{                                       /* matches structure in VXD */
-	long long linear;                    /* linear address */
-	long     size;                       /* total size of the mapped area, holds id when called */
-	short    seg;                        /* segment of the address for Win16 */
-	short    reserved;
-	short    avail;                      /* number of available entries */
-	short    used;                       /* number of used entries */
-	TXENTRY  entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
-} TGET_TX_BLOCK;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-U14API(int)   U14WhenToTimeOut(short hand);         /*  when to timeout in ms */
-U14API(short)	U14PassedTime(int iTime);             /*  non-zero if iTime passed */
-
-U14API(short)	U14LastErrCode(short hand);
-
-U14API(short)	U14Open1401(short n1401);
-U14API(short)	U14Close1401(short hand);
-U14API(short)	U14Reset1401(short hand);
-U14API(short)	U14ForceReset(short hand);
-U14API(short)	U14TypeOf1401(short hand);
-U14API(short)	U14NameOf1401(short hand, char *pBuf, unsigned short wMax);
-
-U14API(short)	U14Stat1401(short hand);
-U14API(short)	U14CharCount(short hand);
-U14API(short)	U14LineCount(short hand);
-
-U14API(short)	U14SendString(short hand, const char *pString);
-U14API(short)	U14GetString(short hand, char *pBuffer, unsigned short wMaxLen);
-U14API(short)	U14SendChar(short hand, char cChar);
-U14API(short)	U14GetChar(short hand, char *pcChar);
-
-U14API(short)	U14LdCmd(short hand, const char *command);
-U14API(unsigned int) U14Ld(short hand, const char *vl, const char *str);
-
-U14API(short)	U14SetTransArea(short hand, unsigned short wArea, void *pvBuff,
-					unsigned int dwLength, short eSz);
-U14API(short)	U14UnSetTransfer(short hand, unsigned short wArea);
-U14API(short)	U14SetTransferEvent(short hand, unsigned short wArea, BOOL bEvent,
-					BOOL bToHost, unsigned int dwStart, unsigned int dwLength);
-U14API(int)   U14TestTransferEvent(short hand, unsigned short wArea);
-U14API(int)   U14WaitTransferEvent(short hand, unsigned short wArea, int msTimeOut);
-U14API(short)	U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock);
-
-U14API(short)	U14ToHost(short hand, char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
-								short eSz);
-U14API(short)	U14To1401(short hand, const char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
-								short eSz);
-
-U14API(short)	U14SetCircular(short hand, unsigned short wArea, BOOL bToHost, void *pvBuff,
-							unsigned int dwLength);
-
-U14API(int)   U14GetCircBlk(short hand, unsigned short wArea, unsigned int *pdwOffs);
-U14API(int)   U14FreeCircBlk(short hand, unsigned short wArea, unsigned int dwOffs, unsigned int dwSize,
-							unsigned int *pdwOffs);
-
-U14API(short)	U14StrToLongs(const char *pszBuff, U14LONG *palNums, short sMaxLongs);
-U14API(short)	U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs);
-
-U14API(void)  U14SetTimeout(short hand, int lTimeout);
-U14API(int)   U14GetTimeout(short hand);
-U14API(short)	U14OutBufSpace(short hand);
-U14API(int)   U14BaseAddr1401(short hand);
-U14API(int)   U14DriverVersion(short hand);
-U14API(int)   U14DriverType(short hand);
-U14API(short)	U14DriverName(short hand, char *pBuf, unsigned short wMax);
-U14API(short)	U14GetUserMemorySize(short hand, unsigned int *pMemorySize);
-U14API(short)	U14KillIO1401(short hand);
-
-U14API(short)	U14BlkTransState(short hand);
-U14API(short)	U14StateOf1401(short hand);
-
-U14API(short)	U14Grab1401(short hand);
-U14API(short)	U14Free1401(short hand);
-U14API(short)	U14Peek1401(short hand, unsigned int dwAddr, int nSize, int nRepeats);
-U14API(short)	U14Poke1401(short hand, unsigned int dwAddr, unsigned int dwValue, int nSize, int nRepeats);
-U14API(short)	U14Ramp1401(short hand, unsigned int dwAddr, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
-U14API(short)	U14RampAddr(short hand, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
-U14API(short)	U14StopDebugLoop(short hand);
-U14API(short)	U14GetDebugData(short hand, U14LONG *plValue);
-
-U14API(short)	U14StartSelfTest(short hand);
-U14API(short)	U14CheckSelfTest(short hand, U14LONG *pData);
-U14API(short)	U14TransferFlags(short hand);
-U14API(void)  U14GetErrorString(short nErr, char *pStr, unsigned short wMax);
-U14API(int)   U14MonitorRev(short hand);
-U14API(void)  U14CloseAll(void);
-
-U14API(short)	U14WorkingSet(unsigned int dwMinKb, unsigned int dwMaxKb);
-U14API(int)   U14InitLib(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* End of ifndef __USE1401_H__ */
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/use14_ioc.h linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/use14_ioc.h
--- linux-libre-3.16-gnu/drivers/staging/ced1401/use14_ioc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/use14_ioc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,299 +0,0 @@
-/* use14_ioc.h
-** definitions of use1401 module stuff that is shared between use1401 and the driver.
-** Copyright (C) Cambridge Electronic Design Limited 2010
-** Author Greg P Smith
-************************************************************************************/
-#ifndef __USE14_IOC_H__
-#define __USE14_IOC_H__
-
-#define  MAX_TRANSAREAS   8   /* The number of transfer areas supported by driver */
-
-#define i386
-#include "winioctl.h"                   /* needed so we can access driver   */
-
-/*
-** Defines for IOCTL functions to ask driver to perform. These must be matched
-** in both use1401 and in the driver. The IOCTL code contains a command
-** identifier, plus other information about the device, the type of access
-** with which the file must have been opened, and the type of buffering.
-** The IOCTL function codes from 0x80 to 0xFF are for developer use.
-*/
-#define  FILE_DEVICE_CED1401    0x8001
-						FNNUMBASE              0x800
-
-#define  U14_OPEN1401            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE,               \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_CLOSE1401           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+1,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SENDSTRING          CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+2,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_RESET1401           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+3,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETCHAR             CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+4,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SENDCHAR            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+5,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STAT1401            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+6,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_LINECOUNT           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+7,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETSTRING           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+8,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_REGCALLBACK         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+9,             \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETMONITORBUF       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+10,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SETTRANSFER         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+11,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_UNSETTRANSFER       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+12,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SETTRANSEVENT       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+13,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETOUTBUFSPACE      CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+14,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETBASEADDRESS      CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+15,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETDRIVERREVISION   CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+16,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETTRANSFER         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+17,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_KILLIO1401          CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+18,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_BLKTRANSSTATE       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+19,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_BYTECOUNT           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+20,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_ZEROBLOCKCOUNT      CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+21,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STOPCIRCULAR        CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+22,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STATEOF1401         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+23,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_REGISTERS1401       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+24,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GRAB1401            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+25,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_FREE1401            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+26,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STEP1401            CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+27,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SET1401REGISTERS    CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+28,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STEPTILL1401        CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+29,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SETORIN             CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+30,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_STARTSELFTEST       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+31,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_CHECKSELFTEST       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+32,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_TYPEOF1401          CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+33,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_TRANSFERFLAGS       CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+34,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGPEEK             CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+35,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGPOKE             CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+36,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGRAMPDATA         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+37,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGRAMPADDR         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+38,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGGETDATA          CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+39,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_DBGSTOPLOOP         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+40,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_FULLRESET           CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+41,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_SETCIRCULAR         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+42,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_GETCIRCBLK          CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+43,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-#define  U14_FREECIRCBLK         CTL_CODE(FILE_DEVICE_CED1401,     \
-						FNNUMBASE+44,            \
-						METHOD_BUFFERED,         \
-						FILE_ANY_ACCESS)
-
-/*--------------- Structures that are shared with the driver ------------- */
-#pragma pack(1)
-
-typedef struct                  /* used for get/set standard 1401 registers */
-{
-	short   sPC;
-	char    A;
-	char    X;
-	char    Y;
-	char    stat;
-	char    rubbish;
-} T1401REGISTERS;
-
-typedef union     /* to communicate with 1401 driver status & control funcs */
-{
-	char           chrs[22];
-	short          ints[11];
-	long           longs[5];
-	T1401REGISTERS registers;
-} TCSBLOCK;
-
-typedef TCSBLOCK*  LPTCSBLOCK;
-
-typedef struct paramBlk {
-	 short       sState;
-	 TCSBLOCK    csBlock;
-} PARAMBLK;
-
-typedef PARAMBLK*   PPARAMBLK;
-
-struct transfer_area_desc          /* Structure and type for SetTransArea */
-{
-	unsigned short        wArea;            /* number of transfer area to set up       */
-	void FAR *lpvBuff;          /* address of transfer area                */
-	unsigned int       dwLength;         /* length of area to set up                */
-	short       eSize;            /* size to move (for swapping on MAC)      */
-};
-
-
-/* This is the structure used to set up a transfer area */
-typedef struct VXTransferDesc    /* use1401.c and use1432x.x use only       */
-{
-	unsigned short        wArea;            /* number of transfer area to set up       */
-	unsigned short        wAddrSel;         /* 16 bit selector for area                */
-	unsigned int       dwAddrOfs;        /* 32 bit offset for area start            */
-	unsigned int       dwLength;         /* length of area to set up                */
-} VXTRANSFERDESC;
-
-#pragma pack()
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ced1401/userspace/use1401.c linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/userspace/use1401.c
--- linux-libre-3.16-gnu/drivers/staging/ced1401/userspace/use1401.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ced1401/userspace/use1401.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3035 +0,0 @@
-/****************************************************************************
-** use1401.c
-** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010
-**
-** This program is free software; you can redistribute it and/or
-** modify it under the terms of the GNU General Public License
-** as published by the Free Software Foundation; either version 2
-** of the License, or (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU 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.
-**
-** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road
-**              Cambridge, CB6 0FE.
-**              www.ced.co.uk
-**              greg@ced.co.uk
-**
-**  Title:      USE1401.C
-**  Version:    4.00
-**  Author:     Paul Cox, Tim Bergel, Greg Smith
-**
-** The code was vigorously pruned in DEC 2010 to remove the macintosh options
-** and to get rid of the 16-bit support. It has also been aligned with the
-** Linux version. See CVS for revisions. This will work for Win 9x onwards.
-****************************************************************************
-**
-** Notes on Windows interface to driver
-** ************************************
-**
-** Under Windows 9x and NT, Use1401 uses DeviceIoControl to get access to
-** the 1401 driver. This has parameters for the device handle, the function
-** code, an input pointer and byte count, an output pointer and byte count
-** and a pointer to a unsigned int to hold the output byte count. Note that input
-** and output are from the point-of-view of the driver, so the output stuff
-** is used to read values from the 1401, not send to the 1401. The use of
-** these parameters varies with the function in use and the operating
-** system; there are five separate DIOC calls SendString, GetString and
-** SetTransferArea all have their own specialised calls, the rest use the
-** Status1401 or Control1401 functions.
-**
-** There are two basic styles of DIOC call used, one for Win9x VxD drivers
-** and one for NT Kernel-mode and WDM drivers (see below for tables showing
-** the different parameters used. The array bUseNTDIOC[] selects between
-** these two calling styles.
-**
-** Function codes
-** In Win3.x, simple function codes from 0 to 40 were used, shifted left 8
-** bits with a sub-function code in the lower 8 bits. These were also used
-** in the Windows 95 driver, though we had to add 1 to the code value to
-** avoid problems (Open from CreateFile is zero), and the sub-function code
-** is now unused. We found that this gave some problems with Windows 98
-** as the function code values are reserved by microsoft, so we switched to
-** using the NT function codes instead. The NT codes are generated using the
-** CTL_CODE macro, essentially this gives 0x80012000 | (func << 2), where
-** func is the original 0 to 34 value. The driver will handle both types of
-** code and Use1432 only uses the NT codes if it knows the driver is new
-** enough. The array bUseNTCodes[] holds flags on the type of codes required.
-** GPS/TDB Dec 2010: we removed the bUseNTCodes array as this is always true
-** as we no longer support ancient versions.
-**
-** The CreateFile and CloseFile function calls are also handled
-** by DIOC, using the special function codes 0 and -1 respectively.
-**
-** Input pointer and buffer size
-** These are intended for data sent to the device driver. In nearly all cases
-** they are unused in calls to the Win95 driver, the NT driver uses them
-** for all information sent to the driver. The table below shows the pointer
-** and byte count used for the various calls:
-**
-**                      Win 95                  Win NT
-** SendString           NULL, 0                 pStr, nStr
-** GetString            NULL, 0                 NULL, 0
-** SetTransferArea      pBuf, nBuf (unused?)    pDesc, nDesc
-** GetTransfer          NULL, 0                 NULL, 0
-** Status1401           NULL, 0                 NULL, 0
-** Control1401          NULL, 0                 pBlk, nBlk
-**
-** pStr and nStr are pointers to a char buffer and the buffer length for
-** string I/O, note that these are temporary buffers owned by the DLL, not
-** application memory, pBuf and nBuf are the transfer area buffer (I think
-** these are unused), pDesc and nDesc are the TRANSFERDESC structure, pBlk
-** and nBlk are the TCSBLOCK structure.
-**
-**
-** Output pointer and buffer size
-** These are intended for data read from the device driver. These are used
-** for almost all information sent to the Win95 driver, the NT driver uses
-** them for information read from the driver, chiefly the error code. The
-** table below shows the pointer and byte count used for the various calls:
-**
-**                      Win 95                  Win NT
-** SendString           pStr, nStr              pPar, nPar
-** GetString            pStr, nStr+2            pStr, nStr+2
-** SetTransferArea      pDesc, nDesc            pPar, nPar
-** GetTransfer          pGet, nGet              pGet, nGet
-** Status1401           pBlk, nBlk              pPar, nPar
-** Control1401          pBlk, nBlk              pPar, nPar
-**
-** pStr and nStr are pointers to a char buffer and the buffer length for
-** string I/O, the +2 for GetString refers to two spare bytes at the start
-** used to hold the string length and returning an error code for NT. Note
-** again that these are (and must be) DLL-owned temporary buffers. pPar
-** and nPar are a PARAM structure used in NT (it holds an error code and a 
-** TCSBLOCK structure). pDesc and nDesc are the VXTRANSFERDESC structure,
-** pBlk and nBlk are the TCSBLOCK structure. pGet and nGet indicate the
-** TGET_TX_BLOCK structure used for GetTransfer.
-**
-**
-** The output byte count
-** Both drivers return the output buffer size here, regardless of the actual
-** bytes output. This is used to check that we did get through to the driver.
-**
-** Multiple 1401s
-** **************
-**
-** We have code that tries to support the use of multiple 1401s, but there
-** are problems: The lDriverVersion and lDriverType variables are global, not
-** per-1401 (a particular problem as the U14 functions that use them don't
-** have a hand parameter). In addition, the mechansim for finding a free
-** 1401 depends upon the 1401 device driver open operation failing if it's
-** already in use, which doesn't always happen, particularly with the VxDs.
-** The code in TryToOpen tries to fix this by relying on TYPEOF1401 to detect
-** the 1401-in-use state - the VxDs contain special code to help this. This is
-** working OK but multiple 1401 support works better with the Win2000 drivers.
-**
-** USB driver
-** **********
-**
-** The USB driver, which runs on both Win98 and NT2000, uses the NT-style
-** calling convention, both for the DIOC codes and the DIOC parameters. The
-** TryToOpen function has been altered to look for an NT driver first in
-** the appropriate circumstances, and to set the driver DIOC flags up in
-** the correct state.
-**
-** Adding a new 1401 type - now almost nothing to do
-** *************************************************
-**
-** The 1401 types are defined by a set of U14TYPExxxx codes in USE1401.H.
-** You should add a new one of these to keep things tidy for applications.
-**
-** DRIVERET_MAX (below) specifies the maximum allowed type code from the
-** 1401 driver; I have set this high to accommodate as yet undesigned 1401
-** types. Similarly, as long as the command file names follow the ARM,
-** ARN, ARO sequence, these are calculated by the ExtForType function, so
-** you don't need to do anything here either.
-**
-** Version number
-** **************
-** The new U14InitLib() function returns 0 if the OS is incapable of use,
-** otherwise is returns the version of the USE1401 library. This is done
-** in three parts: Major(31-24).Minor(23-16).Revision.(15-0) (brackets are
-** the bits used). The Major number starts at 2 for the first revision with
-** the U14InitLib() function. Changes to the Major version means that we
-** have broken backwards compatibility. Minor number changes mean that we
-** have added new functionality that does not break backwards compatibility.
-** we starts at 0. Revision changes mean we have fixed something. Each index
-** returns to 0 when a higher one changes.
-*/
-#define U14LIB_MAJOR 4
-#define U14LIB_MINOR 0
-#define U14LIB_REVISION 0
-#define U14LIB_VERSION ((U14LIB_MAJOR<<24) | (U14LIB_MINOR<<16) | U14LIB_REVISION)
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "USE1401.H"
-
-#ifdef _IS_WINDOWS_
-#include <io.h>
-#include <windows.h>
-#pragma warning(disable: 4100) /* Disable "Unused formal parameter" warning */
-#include <assert.h>
-#include "process.h"
-
-
-#define sprintf wsprintf
-#define PATHSEP '\\'
-#define PATHSEPSTR "\\"
-#define DEFCMDPATH "\\1401\\"   // default command path if all else fails
-#define MINDRIVERMAJREV 1       // minimum driver revision level we need
-#define __packed                // does nothing in Windows
-
-#include "use14_ioc.h"          // links to device driver stuff
-#endif
-
-#ifdef LINUX
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sched.h>
-#include <libgen.h>
-#define PATHSEP '/'
-#define PATHSEPSTR "/"
-#define DEFCMDPATH "/var/1401/" // default command path if all else fails
-#define MINDRIVERMAJREV 2       // minimum driver revision level we need
-
-#include "ced_ioctl.h"          // links to device driver stuff
-#endif
-
-#define MAX1401         8       // The number of 1401s that can be supported
-
-/*
-** These are the 1401 type codes returned by the driver, they are a slightly
-** odd sequence & start for reasons of compatibility with the DOS driver.
-** The maximum code value is the upper limit of 1401 device types.
-*/
-#define DRIVRET_STD     4       // Codes for 1401 types matching driver values
-#define DRIVRET_U1401   5       // This table does not need extending, as
-#define DRIVRET_PLUS    6       // we can calculate values now.
-#define DRIVRET_POWER   7       // but we need all of these values still
-#define DRIVRET_MAX     26      // Maximum tolerated code - future designs
-
-/*
-** These variables store data that will be used to generate the last
-** error string. For now, a string will hold the 1401 command file name.
-*/
-static char szLastName[20];     // additional text information
-
-/*
-** Information stored per handle. NBNB, driverType and DriverVersion used to be
-** only stored once for all handles... i.e. nonsensical. This change means that
-** three U14...() calls now include handles that were previously void. We have
-** set a constructor and a destructor call for the library (see the end) to
-** initialise important structures, or call use1401_load().
-*/
-static short asDriverType[MAX1401] = {0};
-static int lLastDriverVersion = U14ERR_NO1401DRIV;
-static int lLastDriverType = U14TYPEUNKNOWN;
-static int alDriverVersion[MAX1401];            // version/type of each driver
-static int alTimeOutPeriod[MAX1401];            // timeout time in milliseconds
-static short asLastRetCode[MAX1401];            // last code from a fn call
-static short asType1401[MAX1401] = {0};         // The type of the 1401
-static BOOL abGrabbed[MAX1401] = {0};           // Flag for grabbed, set true by grab1401
-static int iAttached = 0;                       // counts process attaches so can let go
-
-#ifdef _IS_WINDOWS_
-/****************************************************************************
-** Windows NT Specific Variables and internal types
-****************************************************************************/
-static HANDLE aHand1401[MAX1401] = {0};         // handles for 1401s
-static HANDLE aXferEvent[MAX1401] = {0};        // transfer events for the 1401s
-static LPVOID apAreas[MAX1401][MAX_TRANSAREAS]; // Locked areas
-static unsigned int  auAreas[MAX1401][MAX_TRANSAREAS]; // Size of locked areas
-static BOOL   bWindows9x = FALSE;               // if we are Windows 95 or better
-#ifdef _WIN64
-#define USE_NT_DIOC(ind) TRUE
-#else
-static BOOL   abUseNTDIOC[MAX1401];             // Use NT-style DIOC parameters */
-#define USE_NT_DIOC(ind) abUseNTDIOC[ind]
-#endif
-
-#endif
-
-#ifdef LINUX
-static int aHand1401[MAX1401] = {0};    // handles for 1401s
-#define INVALID_HANDLE_VALUE 0          // to avoid code differences
-#endif
-
-
-/*
-** The CmdHead relates to backwards compatibility with ancient Microsoft (and Sperry!)
-** versions of BASIC, where this header was needed so we could load a command into
-** memory.
-*/
-#pragma pack(1)                 // pack our structure
-typedef struct CmdHead          // defines header block on command
-{                               // for PC commands
-   char   acBasic[5];           // BASIC information - needed to align things
-   unsigned short   wBasicSz;             // size as seen by BASIC
-   unsigned short   wCmdSize;             // size of the following info
-} __packed CMDHEAD;
-#pragma pack()                  // back to normal
-
-/*
-** The rest of the header looks like this...
-**  int    iRelPnt;             relocation pointer... actual start
-**  char   acName[8];           string holding the command name
-**  BYTE   bMonRev;             monitor revision level
-**  BYTE   bCmdRev;             command revision level
-*/
-
-typedef CMDHEAD *LPCMDHEAD;     // pointer to a command header
-
-#define  MAXSTRLEN   255        // maximum string length we use
-#define  TOHOST      FALSE
-#define  TO1401      TRUE
-
-static short CheckHandle(short h)
-{
-    if ((h < 0) || (h >= MAX1401))  // must be legal range...
-        return U14ERR_BADHAND;
-    if (aHand1401[h] <= 0)          // must be open
-        return U14ERR_BADHAND;
-    return U14ERR_NOERROR;
-}
-
-#ifdef _IS_WINDOWS_
-/****************************************************************************
-** U14Status1401    Used for functions which do not pass any data in but
-**                  get data back
-****************************************************************************/
-static short U14Status1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
-{
-    unsigned int dwBytes = 0;
-
-    if ((sHand < 0) || (sHand >= MAX1401))  /* Check parameters */
-        return U14ERR_BADHAND;
-#ifndef _WIN64
-    if (!USE_NT_DIOC(sHand)) 
-    {   /* Windows 9x DIOC methods? */
-        if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk,sizeof(TCSBLOCK),&dwBytes,NULL))
-            return (short)((dwBytes>=sizeof(TCSBLOCK)) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
-        else
-            return (short)GetLastError();
-    }
-    else
-#endif
-    {                                       /* Windows NT or USB driver */
-        PARAMBLK rWork;
-        rWork.sState = U14ERR_DRIVCOMMS;
-        if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, &rWork,sizeof(PARAMBLK),&dwBytes,NULL) &&
-            (dwBytes >= sizeof(PARAMBLK)))
-        {
-            *pBlk = rWork.csBlock;
-            return rWork.sState;
-        }
-    }
-
-    return U14ERR_DRIVCOMMS;
-}
-
-/****************************************************************************
-** U14Control1401   Used for functions which pass data in and only expect
-**                  an error code back
-****************************************************************************/
-static short U14Control1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
-{
-    unsigned int dwBytes = 0;
-
-    if ((sHand < 0) || (sHand >= MAX1401))              /* Check parameters */
-        return U14ERR_BADHAND;
-
-#ifndef _WIN64
-    if (!USE_NT_DIOC(sHand))                    
-    {                            /* Windows 9x DIOC methods */
-        if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk, sizeof(TCSBLOCK), &dwBytes, NULL))
-            return (short)(dwBytes >= sizeof(TCSBLOCK) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
-        else
-            return (short)GetLastError();
-    }
-    else
-#endif
-    {                            /* Windows NT or later */
-        PARAMBLK rWork;
-        rWork.sState = U14ERR_DRIVCOMMS;
-        if (DeviceIoControl(aHand1401[sHand], lCode, pBlk, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
-            (dwBytes >= sizeof(PARAMBLK)))
-            return rWork.sState;
-    }
-
-    return U14ERR_DRIVCOMMS;
-}
-#endif
-
-/****************************************************************************
-** SafeTickCount
-** Gets time in approximately units of a millisecond.
-*****************************************************************************/
-static long SafeTickCount()
-{
-#ifdef _IS_WINDOWS_
-    return GetTickCount();
-#endif
-#ifdef LINUX
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return (tv.tv_sec*1000 + tv.tv_usec/1000);
-#endif
-}
-
-/****************************************************************************
-** A utility routine to get the command file extension for a given type
-** of 1401. We assume the type code is vaguely legal.
-****************************************************************************/
-static int ExtForType(short sType, char* szExt)
-{
-    szExt[0] = 0;                       /* Default return is a blank string */
-    switch (sType)
-    {
-    case U14TYPE1401: strcpy(szExt, ".CMD");  break;    // Standard 1401
-    case U14TYPEPLUS: strcpy(szExt, ".GXC");  break;    // 1401 plus
-    default:               // All others are in a predictable sequence
-        strcpy(szExt, ".ARM");
-            szExt[3] = (char)('M' + sType - U14TYPEU1401);
-        if (szExt[3] > 'Z')             // Wrap round to ARA after ARZ
-                szExt[3] = (char)(szExt[3] - 26);
-    }
-    return 0;
-}
-
-/****************************************************************************
-**   U14WhenToTimeOut
-**       Returns the time to time out in time units suitable for the machine
-** we are running on  ie millsecs for pc/linux, or Mac/
-****************************************************************************/
-U14API(int) U14WhenToTimeOut(short hand)
-{
-    int iNow = SafeTickCount();
-    if ((hand >= 0) && (hand < MAX1401))
-        iNow += alTimeOutPeriod[hand];
-    return iNow;
-}
-
-/****************************************************************************
-** U14PassedTime
-** Returns non zero if the timed passed in has been passed 0 if not
-****************************************************************************/
-U14API(short) U14PassedTime(int lCheckTime)
-{
-    return (short)((SafeTickCount()-lCheckTime) > 0);
-}
-
-/****************************************************************************
-** TranslateString
-** Tidies up string that U14GetString returns. Converts all the commas in a
-** string to spaces. Removes terminating CR character. May do more in future.
-****************************************************************************/
-static void TranslateString(char* pStr)
-{
-    int i = 0;
-    while (pStr[i])
-    {
-        if (pStr[i] == ',')
-            pStr[i] = ' ';              /* convert comma to space */
-        ++i;
-    }
-
-    if ((i > 0) && (pStr[i-1] == '\n'))  /* kill terminating LF */
-        pStr[i-1] = (char)0;
-}
-
-/****************************************************************************
-** U14StrToLongs
-** Converts a string to an array of longs and returns the number of values
-****************************************************************************/
-U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs)
-{
-    unsigned short wChInd = 0;                // index into source
-    short sLgInd = 0;               // index into result longs
-
-    while (pszBuff[wChInd] &&       // until we get to end of string...
-           (sLgInd < sMaxLongs))    // ...or filled the buffer
-    {
-        // Why not use a C Library converter?
-        switch (pszBuff[wChInd])
-        {
-        case '-':
-        case '0': case '1':   case '2': case '3':   case '4':
-        case '5': case '6':   case '7': case '8':   case '9':
-            {
-                BOOL bDone = FALSE; // true at end of number
-                int iSign = 1;      // sign of number
-                long lValue = 0;
-
-                while ((!bDone) && pszBuff[wChInd])
-                {
-                    switch (pszBuff[wChInd])
-                    {
-                    case '-':
-                        iSign = -1; // swap sign
-                        break;
-
-                    case '0': case '1':   case '2': case '3':   case '4':
-                    case '5': case '6':   case '7': case '8':   case '9':
-                        lValue *= 10;   // move to next digit base 10
-                        lValue += ((int)pszBuff[wChInd]-(int)'0');
-                        break;
-
-                    default:        // end of number
-                        bDone = TRUE;
-                        break;
-                    }
-                    wChInd++;       // move onto next character
-                }
-                palNums[sLgInd] = lValue * iSign;
-                sLgInd++;
-            }
-            break;
-
-        default:
-            wChInd++;               // look at next char
-            break;
-        }
-    }
-    return (sLgInd);
-}
-
-
-/****************************************************************************
-** U14LongsFrom1401
-** Gets the next waiting line from the 1401 and converts it longs
-** Returns the number of numbers read or an error.
-****************************************************************************/
-U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs)
-{
-    char szWork[MAXSTRLEN];
-    short sResult = U14GetString(hand, szWork, MAXSTRLEN);/* get reply from 1401   */
-    if (sResult == U14ERR_NOERROR)                  /* if no error convert   */
-        sResult = U14StrToLongs(szWork, palBuff, sMaxLongs);
-    return sResult;
-}
-
-/****************************************************************************
-**   U14CheckErr
-**   Sends the ERR command to the 1401 and gets the result. Returns 0, a
-**   negative error code, or the first error value.
-****************************************************************************/
-U14API(short) U14CheckErr(short hand)
-{
-    short sResult = U14SendString(hand, ";ERR;");
-    if (sResult == U14ERR_NOERROR)
-    {
-        U14LONG er[3];
-        sResult = U14LongsFrom1401(hand, er, 3);
-        if (sResult > 0)
-        {
-            sResult = (short)er[0];        /* Either zero or an error value */
-#ifdef _DEBUG
-            if (er[0] != 0)
-            {
-                char szMsg[50];
-                sprintf(szMsg, "U14CheckErr returned %d,%d\n", er[0], er[1]);
-                OutputDebugString(szMsg);
-            }
-#endif
-        }
-        else
-        {
-            if (sResult == 0)
-                sResult = U14ERR_TIMEOUT;      /* No numbers equals timeout */
-        }
-    }
-
-    return sResult;
-}
-
-/****************************************************************************
-** U14LastErrCode
-** Returns the last code from the driver. This is for Windows where all calls
-** go through the Control and Status routines, so we can save any error.
-****************************************************************************/
-U14API(short) U14LastErrCode(short hand)
-{
-    if ((hand < 0) || (hand >= MAX1401))
-        return U14ERR_BADHAND;
-    return asLastRetCode[hand];
-}
-
-/****************************************************************************
-** U14SetTimeout
-** Set the timeout period for 1401 comms in milliseconds
-****************************************************************************/
-U14API(void) U14SetTimeout(short hand, int lTimeOut)
-{
-    if ((hand < 0) || (hand >= MAX1401))
-        return;
-    alTimeOutPeriod[hand] = lTimeOut;
-}
-
-/****************************************************************************
-** U14GetTimeout
-** Get the timeout period for 1401 comms in milliseconds
-****************************************************************************/
-U14API(int) U14GetTimeout(short hand)
-{
-    if ((hand < 0) || (hand >= MAX1401))
-        return U14ERR_BADHAND;
-    return alTimeOutPeriod[hand];
-}
-
-/****************************************************************************
-** U14OutBufSpace
-** Return the space in the output buffer, or an error.
-****************************************************************************/
-U14API(short) U14OutBufSpace(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_GETOUTBUFSPACE,&csBlock);
-    if (sErr == U14ERR_NOERROR)
-        sErr = csBlock.ints[0];
-    return sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_GetOutBufSpace(aHand1401[hand]) : sErr;
-#endif
-}
-
-
-/****************************************************************************
-** U14BaseAddr1401
-** Returns the 1401 base address or an error code. Meaningless nowadays
-****************************************************************************/
-U14API(int) U14BaseAddr1401(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    int iError = U14Status1401(hand, U14_GETBASEADDRESS,&csBlock);
-    if (iError == U14ERR_NOERROR)
-        iError = csBlock.longs[0];
-    return iError;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_GetBaseAddress(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14StateOf1401
-** Return error state, either NOERROR or a negative code.
-****************************************************************************/
-U14API(short) U14StateOf1401(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_STATEOF1401, &csBlock);
-    if (sErr == U14ERR_NOERROR)
-    {
-        sErr = csBlock.ints[0];      // returned 1401 state
-        if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
-            sErr = U14ERR_NOERROR;
-    }
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        sErr = (short)CED_StateOf1401(aHand1401[hand]);
-        if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
-            sErr = U14ERR_NOERROR;
-    }
-#endif
-    return sErr;
-}
-
-/****************************************************************************
-** U14DriverVersion
-** Returns the driver version. Hi word is major revision, low word is minor.
-** If you pass in a silly handle (like -1), we return the version of the last
-** driver we know of (to cope with PCI and no 1401 attached).
-****************************************************************************/
-U14API(int) U14DriverVersion(short hand)
-{
-    return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverVersion : alDriverVersion[hand];
-}
-
-/****************************************************************************
-** U14DriverType
-** Returns the driver type. The type, 0=ISA/NU-Bus, 1=PCI, 2=USB, 3=HSS
-** If you pass in a silly handle (like -1), we return the type of the last
-** driver we know of (to cope with PCI and no 1401 attached).
-****************************************************************************/
-U14API(int) U14DriverType(short hand)
-{
-    return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverType : asDriverType[hand];
-}
-
-/****************************************************************************
-** U14DriverName
-** Returns the driver type as 3 character (ISA, PCI, USB or HSS))
-****************************************************************************/
-U14API(short) U14DriverName(short hand, char* pBuf, unsigned short wMax)
-{
-    char* pName;
-    *pBuf = 0;                             // Start off with a blank string
-    switch (U14DriverType(hand))           // Results according to type
-    {
-    case 0:  pName = "ISA"; break;
-    case 1:  pName = "PCI"; break;
-    case 2:  pName = "USB"; break;
-    case 3:  pName = "HSS"; break;
-    default: pName = "???"; break;
-    }
-    strncpy(pBuf, pName, wMax);            // Copy the correct name to return
-
-    return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** U14BlkTransState
-** Returns 0 no transfer in progress, 1 transfer in progress or an error code
-****************************************************************************/
-U14API(short) U14BlkTransState(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_BLKTRANSSTATE, &csBlock);
-    if (sErr == U14ERR_NOERROR)
-        sErr = csBlock.ints[0];
-    return sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_BlkTransState(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14Grab1401
-** Take control of the 1401 for diagnostics purposes. USB does nothing.
-****************************************************************************/
-U14API(short) U14Grab1401(short hand)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-#ifdef _IS_WINDOWS_
-        if (abGrabbed[hand])            // 1401 should not have been grabbed
-            sErr = U14ERR_ALREADYSET;   // Error code defined for this
-        else
-        {
-            TCSBLOCK csBlock;
-            sErr = U14Control1401(hand, U14_GRAB1401, &csBlock);
-        }
-#endif
-#ifdef LINUX
-        // 1401 should not have been grabbed
-        sErr = abGrabbed[hand] ? U14ERR_ALREADYSET : CED_Grab1401(aHand1401[hand]);
-#endif
-        if (sErr == U14ERR_NOERROR)
-            abGrabbed[hand] = TRUE;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14Free1401
-****************************************************************************/
-U14API(short)  U14Free1401(short hand)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-#ifdef _IS_WINDOWS_
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-            TCSBLOCK csBlock;
-            sErr = U14Control1401(hand, U14_FREE1401, &csBlock);
-        }
-        else
-            sErr = U14ERR_NOTSET;
-#endif
-#ifdef LINUX
-        // 1401 should not have been grabbed
-        sErr = abGrabbed[hand] ? CED_Free1401(aHand1401[hand]) : U14ERR_NOTSET;
-#endif
-        if (sErr == U14ERR_NOERROR)
-            abGrabbed[hand] = FALSE;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14Peek1401
-** DESCRIPTION  Cause the 1401 to do one or more peek operations.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-** is called. After the peek is done, use U14GetDebugData to retrieve
-** the results of the peek.
-****************************************************************************/
-U14API(short) U14Peek1401(short hand, unsigned int dwAddr, int nSize, int nRepeats)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-#ifdef _IS_WINDOWS_
-            TCSBLOCK csBlock;
-            csBlock.longs[0] = (long)dwAddr;
-            csBlock.longs[1] = nSize;
-            csBlock.longs[2] = nRepeats;
-            sErr = U14Control1401(hand, U14_DBGPEEK, &csBlock);
-#endif
-#ifdef LINUX
-            TDBGBLOCK dbb;
-            dbb.iAddr = (int)dwAddr;
-            dbb.iWidth = nSize;
-            dbb.iRepeats = nRepeats;
-            sErr = CED_DbgPeek(aHand1401[hand], &dbb);
-#endif
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14Poke1401
-** DESCRIPTION  Cause the 1401 to do one or more poke operations.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-** is called.
-****************************************************************************/
-U14API(short) U14Poke1401(short hand, unsigned int dwAddr, unsigned int dwValue,
-                                      int nSize, int nRepeats)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-#ifdef _IS_WINDOWS_
-            TCSBLOCK csBlock;
-            csBlock.longs[0] = (long)dwAddr;
-            csBlock.longs[1] = nSize;
-            csBlock.longs[2] = nRepeats;
-            csBlock.longs[3] = (long)dwValue;
-            sErr = U14Control1401(hand, U14_DBGPOKE, &csBlock);
-#endif
-#ifdef LINUX
-            TDBGBLOCK dbb;
-            dbb.iAddr = (int)dwAddr;
-            dbb.iWidth = nSize;
-            dbb.iRepeats= nRepeats;
-            dbb.iData = (int)dwValue;
-            sErr = CED_DbgPoke(aHand1401[hand], &dbb);
-#endif
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14Ramp1401
-** DESCRIPTION  Cause the 1401 to loop, writing a ramp to a location.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop.
-****************************************************************************/
-U14API(short) U14Ramp1401(short hand, unsigned int dwAddr, unsigned int dwDef, unsigned int dwEnable,
-                                      int nSize, int nRepeats)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-#ifdef _IS_WINDOWS_
-            TCSBLOCK csBlock;
-            csBlock.longs[0] = (long)dwAddr;
-            csBlock.longs[1] = (long)dwDef;
-            csBlock.longs[2] = (long)dwEnable;
-            csBlock.longs[3] = nSize;
-            csBlock.longs[4] = nRepeats;
-            sErr = U14Control1401(hand, U14_DBGRAMPDATA, &csBlock);
-#endif
-#ifdef LINUX
-            TDBGBLOCK dbb;
-            dbb.iAddr = (int)dwAddr;
-            dbb.iDefault = (int)dwDef;
-            dbb.iMask = (int)dwEnable;
-            dbb.iWidth = nSize;
-            dbb.iRepeats = nRepeats;
-            sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
-#endif
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14RampAddr
-** DESCRIPTION  Cause the 1401 to loop, reading from a ramping location.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-****************************************************************************/
-U14API(short) U14RampAddr(short hand, unsigned int dwDef, unsigned int dwEnable,
-                                      int nSize, int nRepeats)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-#ifdef _IS_WINDOWS_
-            TCSBLOCK csBlock;
-            csBlock.longs[0] = (long)dwDef;
-            csBlock.longs[1] = (long)dwEnable;
-            csBlock.longs[2] = nSize;
-            csBlock.longs[3] = nRepeats;
-            sErr = U14Control1401(hand, U14_DBGRAMPADDR, &csBlock);
-#endif
-#ifdef LINUX
-            TDBGBLOCK dbb;
-            dbb.iDefault = (int)dwDef;
-            dbb.iMask = (int)dwEnable;
-            dbb.iWidth = nSize;
-            dbb.iRepeats = nRepeats;
-            sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
-#endif
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-**    U14StopDebugLoop
-**    DESCRIPTION Stops a peek\poke\ramp that, with repeats set to zero,
-**    will otherwise continue forever.
-****************************************************************************/
-U14API(short) U14StopDebugLoop(short hand)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-#ifdef _IS_WINDOWS_
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-            TCSBLOCK csBlock;
-            sErr = U14Control1401(hand, U14_DBGSTOPLOOP, &csBlock);
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-#endif
-#ifdef LINUX
-        sErr = abGrabbed[hand] ? CED_DbgStopLoop(aHand1401[hand]) : U14ERR_NOTSET;
-#endif
-    return sErr;
-}
-
-/****************************************************************************
-** U14GetDebugData
-** DESCRIPTION Returns the result from a previous peek operation.
-****************************************************************************/
-U14API(short) U14GetDebugData(short hand, U14LONG* plValue)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        if (abGrabbed[hand])    // 1401 should have been grabbed
-        {
-#ifdef _IS_WINDOWS_
-            TCSBLOCK csBlock;
-            sErr = U14Status1401(hand, U14_DBGGETDATA, &csBlock);
-            if (sErr == U14ERR_NOERROR)
-                *plValue = csBlock.longs[0];    // Return the data
-#endif
-#ifdef LINUX
-            TDBGBLOCK dbb;
-            sErr = CED_DbgGetData(aHand1401[hand], &dbb);
-            if (sErr == U14ERR_NOERROR)
-                *plValue = dbb.iData;                     /* Return the data */
-#endif
-        }
-        else
-            sErr = U14ERR_NOTSET;
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14StartSelfTest
-****************************************************************************/
-U14API(short) U14StartSelfTest(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    return U14Control1401(hand, U14_STARTSELFTEST, &csBlock);
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_StartSelfTest(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14CheckSelfTest
-****************************************************************************/
-U14API(short) U14CheckSelfTest(short hand, U14LONG *pData)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_CHECKSELFTEST, &csBlock);
-    if (sErr == U14ERR_NOERROR)
-    {
-        pData[0] = csBlock.longs[0];        /* Return the results to user */
-        pData[1] = csBlock.longs[1];
-        pData[2] = csBlock.longs[2];
-    }
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)                /* Check parameters */
-    {
-        TGET_SELFTEST gst;
-        sErr = CED_CheckSelfTest(aHand1401[hand], &gst);
-        if (sErr == U14ERR_NOERROR)
-        {
-            pData[0] = gst.code;        /* Return the results to user */
-            pData[1] = gst.x;
-            pData[2] = gst.y;
-        }
-    }
-#endif
-    return sErr;
-}
-
-/****************************************************************************
-** U14GetUserMemorySize
-****************************************************************************/
-U14API(short) U14GetUserMemorySize(short hand, unsigned int *pMemorySize)
-{
-    // The original 1401 used a different command for getting the size
-    short sErr = U14SendString(hand, (asType1401[hand] == U14TYPE1401) ? "MEMTOP;" : "MEMTOP,?;");
-    *pMemorySize = 0;         /* if we get error then leave size set at 0  */
-    if (sErr == U14ERR_NOERROR)
-    {
-        U14LONG alLimits[4];
-        sErr = U14LongsFrom1401(hand, alLimits, 4);
-        if (sErr > 0)              /* +ve sErr is the number of values read */
-        {
-            sErr = U14ERR_NOERROR;                  /* All OK, flag success */
-            if (asType1401[hand] == U14TYPE1401)    /* result for standard  */
-                *pMemorySize = alLimits[0] - alLimits[1]; /* memtop-membot */
-            else
-                *pMemorySize = alLimits[0];   /* result for plus or u1401  */
-        }
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14TypeOf1401
-** Returns the type of the 1401, maybe unknown
-****************************************************************************/
-U14API(short) U14TypeOf1401(short hand)
-{
-    if ((hand < 0) || (hand >= MAX1401))                /* Check parameters */
-        return U14ERR_BADHAND;
-    else
-        return asType1401[hand];
-}
-
-/****************************************************************************
-** U14NameOf1401
-** Returns the type of the 1401 as a string, blank if unknown
-****************************************************************************/
-U14API(short) U14NameOf1401(short hand, char* pBuf, unsigned short wMax)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-    char* pName;
-    switch (asType1401[hand])               // Results according to type
-    {
-    case U14TYPE1401:  pName = "Std 1401"; break;
-    case U14TYPEPLUS:  pName = "1401plus"; break;
-    case U14TYPEU1401: pName = "micro1401"; break;
-    case U14TYPEPOWER: pName = "Power1401"; break;
-    case U14TYPEU14012:pName = "Micro1401 mk II"; break;
-    case U14TYPEPOWER2:pName = "Power1401 mk II"; break;
-    case U14TYPEU14013:pName = "Micro1401-3"; break;
-    case U14TYPEPOWER3:pName = "Power1401-3"; break;
-    default:           pName = "Unknown";
-    }
-        strncpy(pBuf, pName, wMax);
-    }
-    return sErr;
-}
-
-/****************************************************************************
-** U14TransferFlags
-**  Returns the driver block transfer flags.
-**  Bits can be set - see U14TF_ constants in use1401.h
-*****************************************************************************/
-U14API(short) U14TransferFlags(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_TRANSFERFLAGS, &csBlock);
-    return (sErr == U14ERR_NOERROR) ? (short)csBlock.ints[0] : sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_TransferFlags(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** GetDriverVersion
-** Actually reads driver version from the device driver.
-** Hi word is major revision, low word is minor revision.
-** Assumes that hand has been checked. Also codes driver type in bits 24 up.
-*****************************************************************************/
-static int GetDriverVersion(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    int iErr = U14Status1401(hand, U14_GETDRIVERREVISION, &csBlock);
-    if (iErr == U14ERR_NOERROR)
-        iErr = csBlock.longs[0];
-    return iErr;
-#endif
-#ifdef LINUX
-    return CED_GetDriverRevision(aHand1401[hand]);
-#endif
-}
-
-/****************************************************************************
-** U14MonitorRev
-** Returns the 1401 monitor revision number.
-** The number returned is the minor revision - the part after the
-** decimal point - plus the major revision times 1000.
-*****************************************************************************/
-U14API(int) U14MonitorRev(short hand)
-{
-    int iRev = 0;
-    int iErr = CheckHandle(hand);
-    if (iErr != U14ERR_NOERROR)                 // Check open and in use
-        return iErr;
-
-    if (asType1401[hand] >= U14TYPEPOWER2)      // The Power2 onwards can give us the monitor
-    {                                           //  revision directly for all versions
-        iErr = U14SendString(hand, "INFO,S,28;");
-        if (iErr == U14ERR_NOERROR)
-        {
-            U14LONG lVals[2];                   // Read a single number being the revision
-            iErr = U14LongsFrom1401(hand, lVals, 1);
-            if (iErr > 0)
-            {
-                iErr = U14ERR_NOERROR;
-                iRev = lVals[0];                // This is the minor part of the revision
-                iRev += asType1401[hand] * 10000;
-            }
-        }
-    }
-    else
-    {                                           /* Do it the hard way for older hardware */
-        iErr = U14SendString(hand, ";CLIST;");     /* ask for command levels */
-        if (iErr == U14ERR_NOERROR)
-        {     
-            while (iErr == U14ERR_NOERROR)
-            {
-                char wstr[50];
-                iErr = U14GetString(hand, wstr, 45);
-                if (iErr == U14ERR_NOERROR)
-                {
-                    char *pstr = strstr(wstr,"RESET");  /* Is this the RESET command? */
-                    if ((pstr == wstr) && (wstr[5] == ' '))
-                    {
-                        char *pstr2;
-                        size_t l;
-                        pstr += 6;       /* Move past RESET and followinmg char */
-                        l = strlen(pstr);       /* The length of text remaining */
-                        while (((pstr[l-1] == ' ') || (pstr[l-1] == 13)) && (l > 0))
-                        {
-                            pstr[l-1] = 0;         /* Tidy up string at the end */
-                            l--;                  /* by removing spaces and CRs */
-                        }
-                        pstr2 = strchr(pstr, '.');    /* Find the decimal point */
-                        if (pstr2 != NULL)                /* If we found the DP */
-                        {
-                            *pstr2 = 0;                /* End pstr string at DP */
-                            pstr2++;              /* Now past the decimal point */
-                            iRev = atoi(pstr2);   /* Get the number after point */
-                        }
-                        iRev += (atoi(pstr) * 1000);    /* Add first bit * 1000 */
-                    }
-                    if ((strlen(wstr) < 3) && (wstr[0] == ' '))
-                        break;              /* Spot the last line of results */
-                }
-            }
-        }
-    }
-    if (iErr == U14ERR_NOERROR)            /* Return revision if no error */
-        iErr = iRev;
-
-    return iErr;
-}
-
-/****************************************************************************
-** U14TryToOpen     Tries to open the 1401 number passed
-**  Note : This will succeed with NT driver even if no I/F card or
-**         1401 switched off, so we check state and close the driver
-**         if the state is unsatisfactory in U14Open1401.
-****************************************************************************/
-#ifdef _IS_WINDOWS_
-#define U14NAMEOLD "\\\\.\\CED_140%d"
-#define U14NAMENEW "\\\\.\\CED%d"
-static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
-{
-    short sErr = U14ERR_NOERROR;
-    HANDLE hDevice = INVALID_HANDLE_VALUE;
-    unsigned int dwErr = 0;
-    int nFirst, nLast, nDev = 0;        /* Used for the search for a 1401 */
-    BOOL bOldName = FALSE;               /* start by looking for a modern driver */
-
-    if (n1401 == 0)                             /* If we need to look for a 1401 */
-    {
-        nFirst = 1;                             /* Set the search range */
-        nLast = MAX1401;                        /* through all the possible 1401s */
-    }
-    else
-        nFirst = nLast = n1401;                 /* Otherwise just one 1401 */
-
-    while (hDevice == INVALID_HANDLE_VALUE)     /* Loop to try for a 1401 */
-    {
-        for (nDev = nFirst; nDev <= nLast; nDev++)
-        {
-            char szDevName[40];                 /* name of the device to open */
-            sprintf(szDevName, bOldName ? U14NAMEOLD : U14NAMENEW, nDev);
-            hDevice = CreateFile(szDevName, GENERIC_WRITE | GENERIC_READ,
-                                 0, 0,          /* Unshared mode does nothing as this is a device */
-                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
-            if (hDevice != INVALID_HANDLE_VALUE)/* Check 1401 if opened */
-            {
-                TCSBLOCK csBlock;
-                assert(aHand1401[nDev-1] == INVALID_HANDLE_VALUE);  // assert if already open
-                aHand1401[nDev-1] = hDevice;    /* Save handle for now */
-
-#ifndef _WIN64
-                // Use DIOC method if not windows 9x or if using new device name
-                abUseNTDIOC[nDev-1] = (BOOL)(!bWindows9x || !bOldName);
-#endif
-                sErr = U14Status1401((short)(nDev-1), U14_TYPEOF1401, &csBlock);
-                if (sErr == U14ERR_NOERROR)
-                {
-                    *plRetVal = csBlock.ints[0];
-                    if (csBlock.ints[0] == U14ERR_INUSE)/* Prevent multi opens */
-                    {
-                        CloseHandle(hDevice);   /* treat as open failure */
-                        hDevice = INVALID_HANDLE_VALUE;
-                        aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
-                        sErr = U14ERR_INUSE;
-                    }
-                    else
-                        break;                  /* Exit from for loop on success */
-                }
-                else
-                {
-                    CloseHandle(hDevice);       /* Give up if func fails */
-                    hDevice = INVALID_HANDLE_VALUE;
-                    aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
-                }
-            }
-            else
-            {
-                unsigned int dwe = GetLastError();     /* Get error code otherwise */
-                if ((dwe != ERROR_FILE_NOT_FOUND) || (dwErr == 0))
-                    dwErr = dwe;                /* Ignore repeats of 'not found' */
-            }
-        }
-
-        if ((hDevice == INVALID_HANDLE_VALUE) &&/* No device found, and... */
-            (bWindows9x) &&                     /* ...old names are allowed, and... */
-            (bOldName == FALSE))                /* ...not tried old names yet */
-            bOldName = TRUE;                    /* Set flag and go round again */
-        else
-            break;                              /* otherwise that's all folks */
-    }
-
-    if (hDevice != INVALID_HANDLE_VALUE)        /* If we got our device open */
-        *psHandle = (short)(nDev-1);            /* return 1401 number opened */
-    else
-    {
-        if (dwErr == ERROR_FILE_NOT_FOUND)      /* Sort out the error codes */
-            sErr = U14ERR_NO1401DRIV;           /* if file not found */
-        else if (dwErr == ERROR_NOT_SUPPORTED)
-            sErr = U14ERR_DRIVTOOOLD;           /* if DIOC not supported */
-        else if (dwErr == ERROR_ACCESS_DENIED)
-            sErr = U14ERR_INUSE;
-        else
-            sErr = U14ERR_DRIVCOMMS;            /* otherwise assume comms problem */
-    }
-    return sErr;
-}
-#endif
-#ifdef LINUX
-static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
-{
-    short sErr = U14ERR_NOERROR;
-    int fh = 0;                             // will be 1401 handle
-    int iErr = 0;
-    int nFirst, nLast, nDev = 0;            // Used for the search for a 1401
-
-    if (n1401 == 0)                         // If we need to look for a 1401
-    {
-        nFirst = 1;                             /* Set the search range */
-        nLast = MAX1401;                        /* through all the possible 1401s */
-    }
-    else
-        nFirst = nLast = n1401;                 /* Otherwise just one 1401 */
-
-    for (nDev = nFirst; nDev <= nLast; nDev++)
-    {
-        char szDevName[40];                 // name of the device to open
-        sprintf(szDevName,"/dev/cedusb/%d", nDev-1);
-        fh = open(szDevName, O_RDWR);       // can only be opened once at a time
-        if (fh > 0)                         // Check 1401 if opened
-        {
-            int iType1401 = CED_TypeOf1401(fh); // get 1401 type
-            aHand1401[nDev-1] = fh;         // Save handle for now
-            if (iType1401 >= 0)
-            {
-                *plRetVal = iType1401;
-                 break;                     // Exit from for loop on success
-            }
-            else
-            {
-                close(fh);                  // Give up if func fails
-                fh = 0;
-                aHand1401[nDev-1] = 0;
-            }
-        }
-        else
-        {
-            if (((errno != ENODEV) && (errno != ENOENT)) || (iErr == 0))
-                iErr = errno;                // Ignore repeats of 'not found'
-        }
-    }
-
-
-    if (fh)                                 // If we got our device open
-        *psHandle = (short)(nDev-1);        // return 1401 number opened
-    else
-    {
-        if ((iErr == ENODEV) || (iErr == ENOENT)) // Sort out the error codes
-            sErr = U14ERR_NO1401DRIV;       // if file not found
-        else if (iErr == EBUSY)
-            sErr = U14ERR_INUSE;
-        else
-            sErr = U14ERR_DRIVCOMMS;        // otherwise assume comms problem
-    }
-
-    return sErr;
-}
-#endif
-/****************************************************************************
-** U14Open1401
-** Tries to get the 1401 for use by this application
-*****************************************************************************/
-U14API(short) U14Open1401(short n1401)
-{
-    long     lRetVal = -1;
-    short    sErr;
-    short    hand = 0;
-    
-    if ((n1401 < 0) || (n1401 > MAX1401))       // must check the 1401 number
-        return U14ERR_BAD1401NUM;
-
-    szLastName[0] = 0;          /* initialise the error info string */
-
-    sErr = U14TryToOpen(n1401, &lRetVal, &hand);
-    if (sErr == U14ERR_NOERROR)
-    {
-        long lDriverVersion = GetDriverVersion(hand);   /* get driver revision */
-        long lDriverRev = -1;
-		if (lDriverVersion >= 0)                    /* can use it if all OK */
-        {
-            lLastDriverType = (lDriverVersion >> 24) & 0x000000FF;
-            asDriverType[hand] = (short)lLastDriverType;    /* Drv type */
-            lLastDriverVersion = lDriverVersion & 0x00FFFFFF;
-            alDriverVersion[hand] = lLastDriverVersion;     /* Actual version */
-            lDriverRev = ((lDriverVersion>>16) & 0x00FF);    /* use hi word */
-        }
-        else
-        {
-            U14Close1401(hand);    /* If there is a problem we should close */
-            return (short)lDriverVersion;      /* and return the error code */
-        }
-    
-        if (lDriverRev < MINDRIVERMAJREV)       /* late enough version?     */
-        {
-            U14Close1401(hand);    /* If there is a problem we should close */
-            return U14ERR_DRIVTOOOLD;           /* too old                  */
-        }
-    
-        asLastRetCode[hand] = U14ERR_NOERROR; /* Initialise this 1401s info */
-        abGrabbed[hand] = FALSE;          /* we are not in single step mode */
-        U14SetTimeout(hand, 3000);      /* set 3 seconds as default timeout */
-
-        switch (lRetVal)
-        {
-        case DRIVRET_STD:  asType1401[hand] = U14TYPE1401; break;      /* Some we do by hand */
-        case DRIVRET_U1401:asType1401[hand] = U14TYPEU1401; break;
-        case DRIVRET_PLUS: asType1401[hand] = U14TYPEPLUS; break;
-        default:  // For the power upwards, we can calculate the codes
-                if ((lRetVal >= DRIVRET_POWER) && (lRetVal <= DRIVRET_MAX))
-                    asType1401[hand] = (short)(lRetVal - (DRIVRET_POWER - U14TYPEPOWER));
-                else
-                    asType1401[hand] = U14TYPEUNKNOWN;
-                break;
-            }
-        U14KillIO1401(hand);                     /* resets the 1401 buffers */
-
-        if (asType1401[hand] != U14TYPEUNKNOWN)   /* If all seems OK so far */
-        {
-            sErr = U14CheckErr(hand);        /* we can check 1401 comms now */
-            if (sErr != 0)                       /* If this failed to go OK */
-                U14Reset1401(hand); /* Reset the 1401 to try to sort it out */
-        }
-
-        sErr = U14StateOf1401(hand);/* Get the state of the 1401 for return */
-        if (sErr == U14ERR_NOERROR)
-            sErr = hand;                 /* return the handle if no problem */
-        else
-            U14Close1401(hand);    /* If there is a problem we should close */
-    }
-
-    return sErr;
-}
-
-
-/****************************************************************************
-** U14Close1401
-** Closes the 1401 so someone else can use it.
-****************************************************************************/
-U14API(short) U14Close1401(short hand)
-{
-    int j;
-    int iAreaMask = 0;                          // Mask for active areas
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)                 // Check open and in use
-        return sErr;
-
-    for (j = 0; j<MAX_TRANSAREAS; ++j)
-    {
-        TGET_TX_BLOCK gtb;
-        int iReturn = U14GetTransfer(hand, &gtb);   // get area information
-        if (iReturn == U14ERR_NOERROR)          // ignore if any problem
-            if (gtb.used)
-                iAreaMask |= (1 << j);          // set a bit for each used area
-    }
-
-    if (iAreaMask)                              // if any areas are in use
-    {
-        U14Reset1401(hand);                     // in case an active transfer running
-        for (j = 0; j < MAX_TRANSAREAS; ++j)    // Locate locked areas
-            if (iAreaMask & (1 << j))           // And kill off any transfers
-                U14UnSetTransfer(hand, (unsigned short)j);
-    }
-
-#ifdef _IS_WINDOWS_
-    if (aXferEvent[hand])                       // if this 1401 has an open event handle
-    {
-        CloseHandle(aXferEvent[hand]);          // close down the handle
-        aXferEvent[hand] = NULL;                // and mark it as gone
-    }
-
-    if (CloseHandle(aHand1401[hand]))
-#endif
-#ifdef LINUX
-    if (close(aHand1401[hand]) == 0)            // make sure that close works
-#endif
-    {
-        aHand1401[hand] = INVALID_HANDLE_VALUE;
-        asType1401[hand] = U14TYPEUNKNOWN;
-        return U14ERR_NOERROR;
-    }
-    else
-        return U14ERR_BADHAND;     /* BUGBUG GetLastError() ? */
-}
-
-/**************************************************************************
-**
-** Look for open 1401s and attempt to close them down. 32-bit windows only.
-**************************************************************************/
-U14API(void) U14CloseAll(void)
-{
-    int i;
-    for (i = 0; i < MAX1401; i++)       // Tidy up and make safe
-        if (aHand1401[i] != INVALID_HANDLE_VALUE)
-            U14Close1401((short)i);     // Last ditch close 1401
-}
-
-/****************************************************************************
-** U14Reset1401
-** Resets the 1401
-****************************************************************************/
-U14API(short) U14Reset1401(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    return U14Control1401(hand, U14_RESET1401, &csBlock);
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_Reset1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14ForceReset
-**    Sets the 1401 full reset flag, so that next call to Reset1401 will
-**     always cause a genuine reset.
-*****************************************************************************/
-U14API(short) U14ForceReset(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    return U14Control1401(hand, U14_FULLRESET, &csBlock);
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_FullReset(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14KillIO1401
-**    Removes any pending IO from the buffers.
-*****************************************************************************/
-U14API(short) U14KillIO1401(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    return U14Control1401(hand, U14_KILLIO1401, &csBlock);
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_KillIO1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-
-/****************************************************************************
-** U14SendString
-** Send characters to the 1401
-*****************************************************************************/
-U14API(short) U14SendString(short hand, const char* pString)
-{
-    int nChars;                     // length we are sending
-    long lTimeOutTicks;             // when to time out
-    BOOL bSpaceToSend;              // space to send yet
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-
-    nChars = (int)strlen(pString);  // get string length we want to send
-    if (nChars > MAXSTRLEN)
-        return U14ERR_STRLEN;       // String too long
-
-#ifdef _IS_WINDOWS_
-    // To get here we must wait for the buffer to have some space
-    lTimeOutTicks = U14WhenToTimeOut(hand);
-    do
-    {
-        bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
-    }
-    while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
-
-    if (!bSpaceToSend)             /* Last-ditch attempt to avoid timeout */
-    {           /* This can happen with anti-virus or network activity! */
-        int i;
-        for (i = 0; (i < 4) && (!bSpaceToSend); ++i)
-        {
-            Sleep(25);       /* Give other threads a chance for a while */
-            bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
-        }
-    }
-
-    if (asLastRetCode[hand] == U14ERR_NOERROR)      /* no errors? */
-    {
-        if (bSpaceToSend)
-        {
-            PARAMBLK    rData;
-            unsigned int       dwBytes;
-            char        tstr[MAXSTRLEN+5];          /* Buffer for chars */
-
-            if ((hand < 0) || (hand >= MAX1401))
-                sErr = U14ERR_BADHAND;
-            else
-            {
-                strcpy(tstr, pString);              /* Into local buf */
-#ifndef _WIN64
-                if (!USE_NT_DIOC(hand))             /* Using WIN 95 driver access? */
-                {
-                    int iOK = DeviceIoControl(aHand1401[hand], (unsigned int)U14_SENDSTRING,
-                                    NULL, 0, tstr, nChars,
-                                    &dwBytes, NULL);
-                    if (iOK)
-                        sErr = (dwBytes >= (unsigned int)nChars) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS;
-                    else
-                        sErr = (short)GetLastError();
-                }
-                else
-#endif
-                {
-                    int iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_SENDSTRING,
-                                    tstr, nChars,
-                                    &rData,sizeof(PARAMBLK),&dwBytes,NULL);
-                    if (iOK && (dwBytes >= sizeof(PARAMBLK)))
-                        sErr = rData.sState;
-                    else
-                        sErr = U14ERR_DRIVCOMMS;
-                }
-
-                if (sErr != U14ERR_NOERROR) // If we have had a comms error
-                    U14ForceReset(hand);    //  make sure we get real reset
-            }
-
-            return sErr;
-
-        }
-        else
-        {
-            U14ForceReset(hand);                //  make sure we get real reset
-            return U14ERR_TIMEOUT;
-        }
-    }
-    else
-        return asLastRetCode[hand];
-#endif
-#ifdef LINUX
-    // Just try to send it and see what happens!
-    sErr = CED_SendString(aHand1401[hand], pString, nChars);
-    if (sErr != U14ERR_NOOUT)       // if any result except "no room in output"...
-    {
-        if (sErr != U14ERR_NOERROR) // if a problem...
-             U14ForceReset(hand);   // ...make sure we get real reset next time
-        return sErr;                // ... we are done as nothing we can do
-    }
-
-    // To get here we must wait for the buffer to have some space
-    lTimeOutTicks = U14WhenToTimeOut(hand);
-    do
-    {
-        bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
-        if (!bSpaceToSend)
-            sched_yield();          // let others have fun while we wait
-    }
-    while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
-
-    if (asLastRetCode[hand] == U14ERR_NOERROR)                /* no errors? */
-    {
-        if (bSpaceToSend)
-        {
-            sErr = CED_SendString(aHand1401[hand], pString, nChars);
-            if (sErr != U14ERR_NOERROR) // If we have had a comms error
-                U14ForceReset(hand);    //  make sure we get real reset
-            return sErr;
-        }
-        else
-        {
-            U14ForceReset(hand);                //  make sure we get real reset
-            return U14ERR_TIMEOUT;
-        }
-    }
-    else
-        return asLastRetCode[hand];
-#endif
-}
-
-/****************************************************************************
-** U14SendChar
-** Send character to the 1401
-*****************************************************************************/
-U14API(short) U14SendChar(short hand, char cChar)
-{
-#ifdef _IS_WINDOWS_
-    char sz[2]=" ";                         // convert to a string and send
-    sz[0] = cChar;
-    sz[1] = 0;
-    return(U14SendString(hand, sz));        // String routines are better
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_SendChar(aHand1401[hand], cChar) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetString
-** Get a string from the 1401. Returns a null terminated string.
-** The string is all the characters up to the next CR in the buffer
-** or the end of the buffer if that comes first. This only returns text
-** if there is a CR in the buffer. The terminating CR character is removed.
-** wMaxLen  Is the size of the buffer and must be at least 2 or an error.
-** Returns  U14ERR_NOERR if OK with the result in the string or a negative
-**          error code. Any error from the device causes us to set up for
-**          a full reset.
-****************************************************************************/
-U14API(short) U14GetString(short hand, char* pBuffer, unsigned short wMaxLen)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)             // If an error...
-        return sErr;                        // ...bail out!
-
-#ifdef _IS_WINDOWS_
-    if (wMaxLen>1)                          // we need space for terminating 0
-    {
-        BOOL bLineToGet;                    // true when a line to get
-        long lTimeOutTicks = U14WhenToTimeOut(hand);
-        do
-            bLineToGet = (BOOL)(U14LineCount(hand) != 0);
-        while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
-
-        if (!bLineToGet)             /* Last-ditch attempt to avoid timeout */
-        {           /* This can happen with anti-virus or network activity! */
-            int i;
-            for (i = 0; (i < 4) && (!bLineToGet); ++i)
-            {
-                Sleep(25);       /* Give other threads a chance for a while */
-                bLineToGet = (BOOL)(U14LineCount(hand) != 0);
-            }
-        }
-
-        if (bLineToGet)
-        {
-            if (asLastRetCode[hand] == U14ERR_NOERROR)     /* all ok so far */
-            {
-                unsigned int       dwBytes = 0;
-                *((unsigned short *)pBuffer) = wMaxLen;       /* set up length */
-#ifndef _WIN64
-                if (!USE_NT_DIOC(hand))             /* Win 95 DIOC here ? */
-                {
-                    char tstr[MAXSTRLEN+5];         /* Buffer for Win95 chars */
-                    int iOK;
-
-                    if (wMaxLen > MAXSTRLEN)        /* Truncate length */
-                        wMaxLen = MAXSTRLEN;    
-
-                    *((unsigned short *)tstr) = wMaxLen;      /* set len */
-
-                    iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_GETSTRING,
-                                    NULL, 0, tstr, wMaxLen+sizeof(short),
-                                    &dwBytes, NULL);
-                    if (iOK)                        /* Device IO control OK ? */
-                    {
-                        if (dwBytes >= 0)           /* If driver OK */
-                        {
-                            strcpy(pBuffer, tstr);
-                            sErr = U14ERR_NOERROR;
-                        }
-                        else
-                            sErr = U14ERR_DRIVCOMMS;
-                    }
-                    else
-                    {
-                        sErr = (short)GetLastError();
-                        if (sErr > 0)               /* Errors are -ve */
-                            sErr = (short)-sErr;
-                    }
-                }
-                else
-#endif
-                {       /* Here for NT, the DLL must own the buffer */
-                    HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE,wMaxLen+sizeof(short));
-                    if (hMem)
-                    {
-                        char* pMem = (char*)GlobalLock(hMem);
-                        if (pMem)
-                        {
-                            int iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_GETSTRING,
-                                            NULL, 0, pMem, wMaxLen+sizeof(short),
-                                            &dwBytes, NULL);
-                            if (iOK)                /* Device IO control OK ? */
-                            {
-                                if (dwBytes >= wMaxLen)
-                                {
-                                    strcpy(pBuffer, pMem+sizeof(short));
-                                    sErr = *((SHORT*)pMem);
-                                }
-                                else
-                                    sErr = U14ERR_DRIVCOMMS;
-                            }
-                            else
-                                sErr = U14ERR_DRIVCOMMS;
-
-                            GlobalUnlock(hMem);
-                        }
-                        else
-                            sErr = U14ERR_OUTOFMEMORY;
-
-                        GlobalFree(hMem);
-                    }
-                    else
-                        sErr = U14ERR_OUTOFMEMORY;
-                }
-
-                if (sErr == U14ERR_NOERROR)     // If all OK...
-                    TranslateString(pBuffer);   // ...convert any commas to spaces
-                else                            // If we have had a comms error...
-                    U14ForceReset(hand);        // ...make sure we get real reset
-
-            }
-            else
-                sErr = asLastRetCode[hand];
-        }
-        else
-        {
-            sErr = U14ERR_TIMEOUT;
-            U14ForceReset(hand);            //  make sure we get real reset
-        }
-    }
-    else
-        sErr = U14ERR_BUFF_SMALL;
-    return sErr;
-#endif
-#ifdef LINUX
-    if (wMaxLen>1)                          // we need space for terminating 0
-    {
-        BOOL bLineToGet;                    // true when a line to get
-        long lTimeOutTicks = U14WhenToTimeOut(hand);
-        do
-        {
-            bLineToGet = (BOOL)(U14LineCount(hand) != 0);
-            if (!bLineToGet)
-                sched_yield();
-
-        }
-        while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
-
-        if (bLineToGet)
-        {
-            sErr = CED_GetString(aHand1401[hand], pBuffer, wMaxLen-1);   // space for terminator
-            if (sErr >=0)                    // if we were OK...
-            {
-                if (sErr >= wMaxLen)         // this should NOT happen unless
-                    sErr = U14ERR_DRIVCOMMS; // ...driver Comms are very bad
-                else
-                {
-                    pBuffer[sErr] = 0;      // OK, so terminate the string...
-                    TranslateString(pBuffer);  // ...and convert commas to spaces.
-                }
-            }
-
-            if (sErr < U14ERR_NOERROR)       // If we have had a comms error
-                U14ForceReset(hand);            //  make sure we get real reset
-        }
-        else
-        {
-            sErr = U14ERR_TIMEOUT;
-            U14ForceReset(hand);            //  make sure we get real reset
-        }
-    }
-    else
-        sErr = U14ERR_BUFF_SMALL;
-
-    return sErr >= U14ERR_NOERROR ? U14ERR_NOERROR : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetChar
-** Get a character from the 1401. CR returned as CR.
-*****************************************************************************/
-U14API(short) U14GetChar(short hand, char* pcChar)
-{
-#ifdef _IS_WINDOWS_
-    char sz[2];                             // read a very short string
-    short sErr = U14GetString(hand, sz, 2); // read one char and nul terminate it
-    *pcChar = sz[0];    // copy to result, NB char translate done by GetString
-    if (sErr == U14ERR_NOERROR)
-    {                                       // undo translate of CR to zero
-        if (*pcChar == '\0')                // by converting back
-            *pcChar = '\n';                 // What a nasty thing to have to do
-    }
-    return sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)             // Check parameters
-        return sErr;
-    sErr = CED_GetChar(aHand1401[hand]);    // get one char, if available
-    if (sErr >= 0)
-    {
-        *pcChar = (char)sErr;              // return if it we have one
-        return U14ERR_NOERROR;              // say all OK
-    }
-    else
-        return sErr;
-#endif
-}
-
-/****************************************************************************
-** U14Stat1401
-** Returns 0 for no lines or error or non zero for something waiting
-****************************************************************************/
-U14API(short) U14Stat1401(short hand)
-{
-    return ((short)(U14LineCount(hand) > 0));
-}
-
-/****************************************************************************
-** U14CharCount
-** Returns the number of characters in the input buffer
-*****************************************************************************/
-U14API(short) U14CharCount(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_STAT1401, &csBlock);
-    if (sErr == U14ERR_NOERROR)
-        sErr = csBlock.ints[0];
-    return sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_Stat1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14LineCount
-** Returns the number of CR characters in the input buffer
-*****************************************************************************/
-U14API(short) U14LineCount(short hand)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14Status1401(hand, U14_LINECOUNT, &csBlock);
-    if (sErr == U14ERR_NOERROR)
-        sErr = csBlock.ints[0];
-    return sErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_LineCount(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetErrorString
-** Converts error code supplied to a decent descriptive string.
-** NOTE: This function may use some extra information stored
-**       internally in the DLL. This information is stored on a
-**       per-process basis, but it might be altered if you call
-**       other functions after getting an error and before using
-**       this function.
-****************************************************************************/
-U14API(void)  U14GetErrorString(short nErr, char* pStr, unsigned short wMax)
-{
-    char    wstr[150];
-
-    switch (nErr)              /* Basically, we do this with a switch block */
-    {
-    case U14ERR_OFF:
-        sprintf(wstr, "The 1401 is apparently switched off (code %d)", nErr);
-        break;
-
-    case U14ERR_NC:
-        sprintf(wstr, "The 1401 is not connected to the interface card (code %d)", nErr);
-        break;
-
-    case U14ERR_ILL:
-        sprintf(wstr, "The 1401 is not working correctly (code %d)", nErr);
-        break;
-
-    case U14ERR_NOIF:
-        sprintf(wstr, "The 1401 interface card was not detected (code %d)", nErr);
-        break;
-
-    case U14ERR_TIME:
-        sprintf(wstr, "The 1401 fails to become ready for use (code %d)", nErr);
-        break;
-
-    case U14ERR_BADSW:
-        sprintf(wstr, "The 1401 interface card jumpers are incorrect (code %d)", nErr);
-        break;
-
-    case U14ERR_NOINT:
-        sprintf(wstr, "The 1401 interrupt is not available for use (code %d)", nErr);
-        break;
-
-    case U14ERR_INUSE:
-        sprintf(wstr, "The 1401 is already in use by another program (code %d)", nErr);
-        break;
-
-    case U14ERR_NODMA:
-        sprintf(wstr, "The 1401 DMA channel is not available for use (code %d)", nErr);
-        break;
-
-    case U14ERR_BADHAND:
-        sprintf(wstr, "The application supplied an incorrect 1401 handle (code %d)", nErr);
-        break;
-
-    case U14ERR_BAD1401NUM:
-        sprintf(wstr, "The application used an incorrect 1401 number (code %d)", nErr);
-        break;
-
-    case U14ERR_NO_SUCH_FN:
-        sprintf(wstr, "The code passed to the 1401 driver is invalid (code %d)", nErr);
-        break;
-
-    case U14ERR_NO_SUCH_SUBFN:
-        sprintf(wstr, "The sub-code passed to the 1401 driver is invalid (code %d)", nErr);
-        break;
-
-    case U14ERR_NOOUT:
-        sprintf(wstr, "No room in buffer for characters for the 1401 (code %d)", nErr);
-        break;
-
-    case U14ERR_NOIN:
-        sprintf(wstr, "No characters from the 1401 are available (code %d)", nErr);
-        break;
-
-    case U14ERR_STRLEN:
-        sprintf(wstr, "A string sent to or read from the 1401 was too long (code %d)", nErr);
-        break;
-
-    case U14ERR_LOCKFAIL:
-        sprintf(wstr, "Failed to lock host memory for data transfer (code %d)", nErr);
-        break;
-
-    case U14ERR_UNLOCKFAIL:
-        sprintf(wstr, "Failed to unlock host memory after data transfer (code %d)", nErr);
-        break;
-
-    case U14ERR_ALREADYSET:
-        sprintf(wstr, "The transfer area used is already set up (code %d)", nErr);
-        break;
-
-    case U14ERR_NOTSET:
-        sprintf(wstr, "The transfer area used has not been set up (code %d)", nErr);
-        break;
-
-    case U14ERR_BADAREA:
-        sprintf(wstr, "The transfer area number is incorrect (code %d)", nErr);
-        break;
-
-    case U14ERR_NOFILE:
-        sprintf(wstr, "The command file %s could not be opened (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_READERR:
-        sprintf(wstr, "The command file %s could not be read (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_UNKNOWN:
-        sprintf(wstr, "The %s command resource could not be found (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_HOSTSPACE:
-        sprintf(wstr, "Unable to allocate memory for loading command %s (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_LOCKERR:
-        sprintf(wstr, "Unable to lock memory for loading command %s (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_CLOADERR:
-        sprintf(wstr, "Error in loading command %s, bad command format (code %d)", szLastName, nErr);
-        break;
-
-    case U14ERR_TOXXXERR:
-        sprintf(wstr, "Error detected after data transfer to or from the 1401 (code %d)", nErr);
-        break;
-
-    case U14ERR_NO386ENH:
-        sprintf(wstr, "Windows 3.1 is not running in 386 enhanced mode (code %d)", nErr);
-        break;
-
-    case U14ERR_NO1401DRIV:
-        sprintf(wstr, "The 1401 device driver cannot be found (code %d)\nUSB:   check plugged in and powered\nOther: not installed?", nErr);
-        break;
-
-    case U14ERR_DRIVTOOOLD:
-        sprintf(wstr, "The 1401 device driver is too old for use (code %d)", nErr);
-        break;
-
-    case U14ERR_TIMEOUT:
-        sprintf(wstr, "Character transmissions to the 1401 timed-out (code %d)", nErr);
-        break;
-
-    case U14ERR_BUFF_SMALL:
-        sprintf(wstr, "Buffer for text from the 1401 was too small (code %d)", nErr);
-        break;
-
-    case U14ERR_CBALREADY:
-        sprintf(wstr, "1401 monitor callback already set up (code %d)", nErr);
-        break;
-
-    case U14ERR_BADDEREG:
-        sprintf(wstr, "1401 monitor callback deregister invalid (code %d)", nErr);
-        break;
-
-    case U14ERR_DRIVCOMMS:
-        sprintf(wstr, "1401 device driver communications failed (code %d)", nErr);
-        break;
-
-    case U14ERR_OUTOFMEMORY:
-        sprintf(wstr, "Failed to allocate or lock memory for text from the 1401 (code %d)", nErr);
-        break;
-
-    default:
-        sprintf(wstr, "1401 error code %d returned; this code is unknown", nErr);
-        break;
-
-    }
-    if ((unsigned short)strlen(wstr) >= wMax-1)  /* Check for string being too long */
-        wstr[wMax-1] = 0;                          /* and truncate it if so */
-    strcpy(pStr, wstr);                       /* Return the error string */
-}
-
-/***************************************************************************
-** U14GetTransfer
-** Get a TGET_TX_BLOCK describing a transfer area (held in the block)
-***************************************************************************/
-U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock)
-{
-    short sErr = CheckHandle(hand);
-#ifdef _IS_WINDOWS_
-    if (sErr == U14ERR_NOERROR)
-    { 
-        unsigned int dwBytes = 0;
-        BOOL bOK = DeviceIoControl(aHand1401[hand], (unsigned int)U14_GETTRANSFER, NULL, 0, pTransBlock,
-                              sizeof(TGET_TX_BLOCK), &dwBytes, NULL);
-    
-        if (bOK && (dwBytes >= sizeof(TGET_TX_BLOCK)))
-            sErr = U14ERR_NOERROR;
-        else
-            sErr = U14ERR_DRIVCOMMS;
-    }
-    return sErr;
-#endif
-#ifdef LINUX
-    return (sErr == U14ERR_NOERROR) ? CED_GetTransfer(aHand1401[hand], pTransBlock) : sErr;
-#endif
-}
-/////////////////////////////////////////////////////////////////////////////
-// U14WorkingSet
-// For Win32 only, adjusts process working set so that minimum is at least
-//  dwMinKb and maximum is at least dwMaxKb.
-// Return value is zero if all went OK, or a code from 1 to 3 indicating the
-//  cause of the failure:
-//
-//     1 unable to access process (insufficient rights?)
-//     2 unable to read process working set
-//     3 unable to set process working set - bad parameters?
-U14API(short) U14WorkingSet(unsigned int dwMinKb, unsigned int dwMaxKb)
-{
-#ifdef _IS_WINDOWS_
-    short sRetVal = 0;                      // 0 means all is OK
-    HANDLE hProcess;
-    unsigned int dwVer = GetVersion();
-	if (dwVer & 0x80000000)                 // is this not NT?
-        return 0;                           // then give up right now
-
-    // Now attempt to get information on working set size
-    hProcess = OpenProcess(STANDARD_RIGHTS_REQUIRED |
-                                  PROCESS_QUERY_INFORMATION |
-                                  PROCESS_SET_QUOTA,
-                                  FALSE, _getpid());
-    if (hProcess)
-    {
-        SIZE_T dwMinSize,dwMaxSize;
-        if (GetProcessWorkingSetSize(hProcess, &dwMinSize, &dwMaxSize))
-        {
-            unsigned int dwMin = dwMinKb << 10;    // convert from kb to bytes
-            unsigned int dwMax = dwMaxKb << 10;
-
-            // if we get here, we have managed to read the current size
-            if (dwMin > dwMinSize)          // need to change sizes?
-                dwMinSize = dwMin;
-
-            if (dwMax > dwMaxSize)
-                dwMaxSize = dwMax;
-
-            if (!SetProcessWorkingSetSize(hProcess, dwMinSize, dwMaxSize))
-                sRetVal = 3;                // failed to change size
-        }
-        else
-            sRetVal = 2;                    // failed to read original size
-
-        CloseHandle(hProcess);
-    }
-    else
-        sRetVal = 1;            // failed to get handle
-
-    return sRetVal;
-#endif
-#ifdef LINUX
-    if (dwMinKb | dwMaxKb)
-    {
-        // to stop compiler moaning
-    }
-    return U14ERR_NOERROR;
-#endif
-}
-
-/****************************************************************************
-** U14UnSetTransfer  Cancels a transfer area
-** wArea    The index of a block previously used in by SetTransfer
-*****************************************************************************/
-U14API(short) U14UnSetTransfer(short hand, unsigned short wArea)
-{
-    short sErr = CheckHandle(hand);
-#ifdef _IS_WINDOWS_
-    if (sErr == U14ERR_NOERROR)
-    {
-       TCSBLOCK csBlock;
-       csBlock.ints[0] = (short)wArea;       /* Area number into control block */
-       sErr = U14Control1401(hand, U14_UNSETTRANSFER, &csBlock);  /* Free area */
-   
-       VirtualUnlock(apAreas[hand][wArea], auAreas[hand][wArea]);/* Unlock */
-       apAreas[hand][wArea] = NULL;                         /* Clear locations */
-       auAreas[hand][wArea] = 0;
-    }
-    return sErr;
-#endif
-#ifdef LINUX
-    return (sErr == U14ERR_NOERROR) ? CED_UnsetTransfer(aHand1401[hand], wArea) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14SetTransArea      Sets an area up to be used for transfers
-** unsigned short  wArea     The area number to set up
-** void *pvBuff    The address of the buffer for the data.
-** unsigned int dwLength  The length of the buffer for the data
-** short eSz       The element size (used for byte swapping on the Mac)
-****************************************************************************/
-U14API(short) U14SetTransArea(short hand, unsigned short wArea, void *pvBuff,
-                                          unsigned int dwLength, short eSz)
-{
-    struct transfer_area_desc td;
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-    if (wArea >= MAX_TRANSAREAS)                    // Is this a valid area number
-        return U14ERR_BADAREA;
-
-#ifdef _IS_WINDOWS_
-    assert(apAreas[hand][wArea] == NULL);
-    assert(auAreas[hand][wArea] == 0);
-
-    apAreas[hand][wArea] = pvBuff;                  /* Save data for later */
-    auAreas[hand][wArea] = dwLength;
-
-    if (!VirtualLock(pvBuff, dwLength))             /* Lock using WIN32 calls */
-    {
-        apAreas[hand][wArea] = NULL;                /* Clear locations */
-        auAreas[hand][wArea] = 0;
-        return U14ERR_LOCKERR;                      /* VirtualLock failed */
-    }
-#ifndef _WIN64
-    if (!USE_NT_DIOC(hand))                         /* Use Win 9x DIOC? */
-    {
-        unsigned int dwBytes;
-        VXTRANSFERDESC vxDesc;                      /* Structure to pass to VXD */
-        vxDesc.wArea = wArea;                       /* Copy across simple params */
-        vxDesc.dwLength = dwLength;
-
-        // Check we are not asking an old driver for more than area 0
-        if ((wArea != 0) && (U14DriverVersion(hand) < 0x00010002L))
-            sErr = U14ERR_DRIVTOOOLD;
-        else
-        {
-            vxDesc.dwAddrOfs = (unsigned int)pvBuff;       /* 32 bit offset */
-            vxDesc.wAddrSel  = 0;
-
-            if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_SETTRANSFER,
-                                pvBuff,dwLength,    /* Will translate pointer */
-                                &vxDesc,sizeof(VXTRANSFERDESC),
-                                &dwBytes,NULL))
-            {
-                if (dwBytes >= sizeof(VXTRANSFERDESC)) /* Driver OK ? */
-                    sErr = U14ERR_NOERROR;
-                else
-                    sErr = U14ERR_DRIVCOMMS;        /* Else never got there */
-            }
-            else
-                sErr = (short)GetLastError();
-        }
-    }
-    else
-#endif
-    {
-        PARAMBLK rWork;
-        unsigned int dwBytes;
-        td.wArea = wArea;     /* Pure NT - put data into struct */
-        td.lpvBuff = pvBuff;
-        td.dwLength = dwLength;
-        td.eSize = 0;                // Dummy element size
-
-        if (DeviceIoControl(aHand1401[hand],(unsigned int)U14_SETTRANSFER,
-                            &td,sizeof(struct transfer_area_desc),
-                            &rWork,sizeof(PARAMBLK),&dwBytes,NULL))
-        {
-            if (dwBytes >= sizeof(PARAMBLK))    // maybe error from driver?
-                sErr = rWork.sState;            // will report any error
-            else
-                sErr = U14ERR_DRIVCOMMS;        // Else never got there
-        }
-        else
-            sErr = U14ERR_DRIVCOMMS;
-    }
-
-    if (sErr != U14ERR_NOERROR)
-    {
-        if (sErr != U14ERR_LOCKERR)             // unless lock failed...
-            VirtualUnlock(pvBuff, dwLength);    // ...release the lock
-        apAreas[hand][wArea] = NULL;            // Clear locations
-        auAreas[hand][wArea] = 0;
-    }
-
-    return sErr;
-#endif
-#ifdef LINUX
-    // The strange cast is so that it works in 64 and 32-bit linux as long is 64-bits
-    // in the 64 bit version.
-    td.lpvBuff = (long long)((unsigned long)pvBuff);
-    td.wAreaNum = wArea;
-    td.dwLength = dwLength;
-    td.eSize = eSz;                // Dummy element size
-    return CED_SetTransfer(aHand1401[hand], &td);
-#endif
-}
-
-/****************************************************************************
-** U14SetTransferEvent  Sets an event for notification of application
-** wArea       The transfer area index, from 0 to MAXAREAS-1
-**    bEvent      True to create an event, false to remove it
-**    bToHost     Set 0 for notification on to1401 tranfers, 1 for
-**                notification of transfers to the host PC
-**    dwStart     The offset of the sub-area of interest
-**    dwLength    The size of the sub-area of interest
-**
-** The device driver will set the event supplied to the signalled state
-** whenever a DMA transfer to/from the specified area is completed. The
-** transfer has to be in the direction specified by bToHost, and overlap
-** that part of the whole transfer area specified by dwStart and dwLength.
-** It is important that this function is called with bEvent false to release
-** the event once 1401 activity is finished.
-**
-** Returns 1 if an event handle exists, 0 if all OK and no event handle or
-** a negative code for an error.
-****************************************************************************/
-U14API(short) U14SetTransferEvent(short hand, unsigned short wArea, BOOL bEvent,
-                                  BOOL bToHost, unsigned int dwStart, unsigned int dwLength)
-{
-#ifdef _IS_WINDOWS_
-    TCSBLOCK csBlock;
-    short sErr = U14TransferFlags(hand);        // see if we can handle events
-    if (sErr >= U14ERR_NOERROR)                 // check handle is OK
-    {
-        bEvent = bEvent && ((sErr & U14TF_NOTIFY) != 0); // remove request if we cannot do events
-        if (wArea >= MAX_TRANSAREAS)            // Check a valid area...
-            return U14ERR_BADAREA;              // ...and bail of not
-
-        // We can hold an event for each area, so see if we need to change the
-        // state of the event.
-        if ((bEvent != 0) != (aXferEvent[hand] != 0))    // change of event state?
-        {
-            if (bEvent)                         // want one and none present
-                aXferEvent[hand] = CreateEvent(NULL, FALSE, FALSE, NULL);
-            else
-            {
-                CloseHandle(aXferEvent[hand]);  // clear the existing event
-                aXferEvent[hand] = NULL;        // and clear handle
-            }
-        }
-
-        // We have to store the parameters differently for 64-bit operations
-        //  because a handle is 64 bits long. The drivers know of this and
-        //  handle the information appropriately.
-#ifdef _WIN64
-        csBlock.longs[0] = wArea;               // Pass paramaters into the driver...
-        if (bToHost != 0)                       // The direction flag is held in the
-            csBlock.longs[0] |= 0x10000;        //  upper word of the transfer area value
-        *((HANDLE*)&csBlock.longs[1]) = aXferEvent[hand];  // The event handle is 64-bits
-        csBlock.longs[3] = dwStart;             // Thankfully these two remain
-        csBlock.longs[4] = dwLength;            //  as unsigned 32-bit values
-#else
-        csBlock.longs[0] = wArea;               // pass paramaters into the driver...
-        csBlock.longs[1] = (long)aXferEvent[hand];    // ...especially the event handle
-        csBlock.longs[2] = bToHost;
-        csBlock.longs[3] = dwStart;
-        csBlock.longs[4] = dwLength;
-#endif
-        sErr = U14Control1401(hand, U14_SETTRANSEVENT, &csBlock);
-        if (sErr == U14ERR_NOERROR)
-            sErr = (short)(aXferEvent[hand] != NULL);    // report if we have a flag
-    }
-
-    return sErr;
-#endif
-#ifdef LINUX
-    TRANSFEREVENT te;
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-
-    if (wArea >= MAX_TRANSAREAS)            // Is this a valid area number
-        return U14ERR_BADAREA;
-
-    te.wAreaNum = wArea;                    // copy parameters to the control block
-    te.wFlags = bToHost ? 1 : 0;            // bit 0 sets the direction
-    te.dwStart = dwStart;                   // start offset of the event area
-    te.dwLength = dwLength;                 // size of the event area
-    te.iSetEvent = bEvent;                  // in Windows, this creates/destroys the event
-    return CED_SetEvent(aHand1401[hand], &te);
-#endif
-}
-
-/****************************************************************************
-** U14TestTransferEvent
-** Would a U14WaitTransferEvent() call return immediately? return 1 if so,
-** 0 if not or a negative code if a problem.
-****************************************************************************/
-U14API(int) U14TestTransferEvent(short hand, unsigned short wArea)
-{
-#ifdef _IS_WINDOWS_
-    int iErr = CheckHandle(hand);
-    if (iErr == U14ERR_NOERROR)
-    {
-        if (aXferEvent[hand])           // if a handle is set...
-            iErr = WaitForSingleObject(aXferEvent[hand], 0) == WAIT_OBJECT_0;
-    }
-    return iErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_TestEvent(aHand1401[hand], wArea) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14WaitTransferEvent
-** Wait for a transfer event with a timeout.
-** msTimeOut is 0 for an infinite wait, else it is the maximum time to wait
-**           in milliseconds in range 0-0x00ffffff.
-** Returns   If no event handle then return immediately. Else return 1 if
-**           timed out or 0=event, and a negative code if a problem.
-****************************************************************************/
-U14API(int) U14WaitTransferEvent(short hand, unsigned short wArea, int msTimeOut)
-{
-#ifdef _IS_WINDOWS_
-    int iErr = CheckHandle(hand);
-    if (iErr == U14ERR_NOERROR)
-    {
-        if (aXferEvent[hand])
-        {
-            if (msTimeOut == 0)
-                msTimeOut = INFINITE;
-            iErr = WaitForSingleObject(aXferEvent[hand], msTimeOut) != WAIT_OBJECT_0;
-        }
-        else
-            iErr = TRUE;                // say we timed out if no event
-    }
-    return iErr;
-#endif
-#ifdef LINUX
-    short sErr = CheckHandle(hand);
-    return (sErr == U14ERR_NOERROR) ? CED_WaitEvent(aHand1401[hand], wArea, msTimeOut) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14SetCircular    Sets an area up for circular DMA transfers
-** unsigned short  wArea          The area number to set up
-** BOOL  bToHost        Sets the direction of data transfer
-** void *pvBuff        The address of the buffer for the data
-** unsigned int dwLength       The length of the buffer for the data
-****************************************************************************/
-U14API(short) U14SetCircular(short hand, unsigned short wArea, BOOL bToHost,
-									void *pvBuff, unsigned int dwLength)
-{
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-
-    if (wArea >= MAX_TRANSAREAS)         /* Is this a valid area number */
-        return U14ERR_BADAREA;
-
-	if (!bToHost)             /* For now, support tohost transfers only */
-        return U14ERR_BADAREA;            /* best error code I can find */
-#ifdef _IS_WINDOWS_
-    assert(apAreas[hand][wArea] == NULL);
-    assert(auAreas[hand][wArea] == 0);
-
-    apAreas[hand][wArea] = pvBuff;              /* Save data for later */
-    auAreas[hand][wArea] = dwLength;
-
-    if (!VirtualLock(pvBuff, dwLength))      /* Lock using WIN32 calls */
-        sErr = U14ERR_LOCKERR;                    /* VirtualLock failed */
-    else
-    {
-        PARAMBLK rWork;
-        unsigned int dwBytes;
-        struct transfer_area_desc txDesc;
-        txDesc.wArea = wArea;             /* Pure NT - put data into struct */
-        txDesc.lpvBuff = pvBuff;
-        txDesc.dwLength = dwLength;
-        txDesc.eSize = (short)bToHost;       /* Use this for direction flag */
-   
-        if (DeviceIoControl(aHand1401[hand],(unsigned int)U14_SETCIRCULAR,
-                           &txDesc, sizeof(struct transfer_area_desc),
-                           &rWork, sizeof(PARAMBLK),&dwBytes,NULL))
-        {
-           if (dwBytes >= sizeof(PARAMBLK))          /* error from driver? */
-               sErr = rWork.sState;         /* No, just return driver data */
-           else
-               sErr = U14ERR_DRIVCOMMS;            /* Else never got there */
-        }
-        else
-            sErr = U14ERR_DRIVCOMMS;
-    }
-
-    if (sErr != U14ERR_NOERROR)
-    {
-        if (sErr != U14ERR_LOCKERR)
-            VirtualUnlock(pvBuff, dwLength);         /* Release NT lock */
-        apAreas[hand][wArea] = NULL;                 /* Clear locations */
-        auAreas[hand][wArea] = 0;
-    }
-
-    return sErr;
-#endif
-#ifdef LINUX
-    else
-    {
-        struct transfer_area_desc td;
-        td.lpvBuff = (long long)((unsigned long)pvBuff);
-        td.wAreaNum = wArea;
-        td.dwLength = dwLength;
-        td.eSize = (short)bToHost;       /* Use this for direction flag */
-        return CED_SetCircular(aHand1401[hand], &td);
-    }
-#endif
-}
-
-/****************************************************************************
-** Function  GetCircBlk returns the size (& start offset) of the next
-**           available block of circular data.
-****************************************************************************/
-U14API(int) U14GetCircBlk(short hand, unsigned short wArea, unsigned int *pdwOffs)
-{
-    int lErr = CheckHandle(hand);
-    if (lErr != U14ERR_NOERROR)
-        return lErr;
-
-    if (wArea >= MAX_TRANSAREAS)            // Is this a valid area number?
-        return U14ERR_BADAREA;
-    else
-    {
-#ifdef _IS_WINDOWS_
-        PARAMBLK rWork;
-        TCSBLOCK csBlock;
-        unsigned int dwBytes;
-        csBlock.longs[0] = wArea;               // Area number into control block
-        rWork.sState = U14ERR_DRIVCOMMS;
-        if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_GETCIRCBLK, &csBlock, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
-           (dwBytes >= sizeof(PARAMBLK)))
-            lErr = rWork.sState;
-        else
-            lErr = U14ERR_DRIVCOMMS;
-   
-        if (lErr == U14ERR_NOERROR)             // Did everything go OK?
-        {                                       // Yes, we can pass the results back
-            lErr = rWork.csBlock.longs[1];      // Return the block information
-            *pdwOffs = rWork.csBlock.longs[0];  // Offset is first in array
-        }
-#endif
-#ifdef LINUX
-        TCIRCBLOCK cb;
-        cb.nArea = wArea;                       // Area number into control block
-        cb.dwOffset = 0;
-        cb.dwSize = 0;
-        lErr = CED_GetCircBlock(aHand1401[hand], &cb);
-        if (lErr == U14ERR_NOERROR)             // Did everything go OK?
-        {                                       // Yes, we can pass the results back
-            lErr = cb.dwSize;                   // return the size
-            *pdwOffs = cb.dwOffset;             // and the offset
-        }
-#endif
-    }
-    return lErr;
-}
-
-/****************************************************************************
-** Function  FreeCircBlk marks the specified area of memory as free for
-**           resuse for circular transfers and returns the size (& start
-**           offset) of the next available block of circular data.
-****************************************************************************/
-U14API(int) U14FreeCircBlk(short hand, unsigned short wArea, unsigned int dwOffs, unsigned int dwSize,
-                                        unsigned int *pdwOffs)
-{
-    int lErr = CheckHandle(hand);
-    if (lErr != U14ERR_NOERROR)
-        return lErr;
-
-    if (wArea < MAX_TRANSAREAS)                 // Is this a valid area number
-    {
-#ifdef _IS_WINDOWS_
-        PARAMBLK rWork;
-        TCSBLOCK csBlock;
-        unsigned int dwBytes;
-        csBlock.longs[0] = wArea;               // Area number into control block
-        csBlock.longs[1] = dwOffs;
-        csBlock.longs[2] = dwSize;
-        rWork.sState = U14ERR_DRIVCOMMS;
-        if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_FREECIRCBLK, &csBlock, sizeof(TCSBLOCK),
-                           &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
-           (dwBytes >= sizeof(PARAMBLK)))
-           lErr = rWork.sState;
-        else
-           lErr = U14ERR_DRIVCOMMS;
-       if (lErr == U14ERR_NOERROR)             // Did everything work OK?
-       {                                       // Yes, we can pass the results back
-           lErr = rWork.csBlock.longs[1];      // Return the block information
-           *pdwOffs = rWork.csBlock.longs[0];  // Offset is first in array
-       }
-#endif
-#ifdef LINUX
-        TCIRCBLOCK cb;
-        cb.nArea = wArea;                       // Area number into control block
-        cb.dwOffset = dwOffs;
-        cb.dwSize = dwSize;
-    
-        lErr = CED_FreeCircBlock(aHand1401[hand], &cb);
-        if (lErr == U14ERR_NOERROR)             // Did everything work OK?
-        {                                       // Yes, we can pass the results back
-            lErr = cb.dwSize;                   // Return the block information
-            *pdwOffs = cb.dwOffset;             // Offset is first in array
-        }
-#endif
-    }
-    else
-        lErr = U14ERR_BADAREA;
-
-    return lErr;
-}
-
-/****************************************************************************
-** Transfer
-** Transfer moves data to 1401 or to host
-** Assumes memory is allocated and locked,
-** which it should be to get a pointer
-*****************************************************************************/
-static short Transfer(short hand, BOOL bTo1401, char* pData,
-                       unsigned int dwSize, unsigned int dw1401, short eSz)
-{
-    char strcopy[MAXSTRLEN+1];          // to hold copy of work string
-    short sResult = U14SetTransArea(hand, 0, (void *)pData, dwSize, eSz);
-    if (sResult == U14ERR_NOERROR)      // no error
-    {
-        sprintf(strcopy,                // data offset is always 0
-                "TO%s,$%X,$%X,0;", bTo1401 ? "1401" : "HOST", dw1401, dwSize);
-
-        U14SendString(hand, strcopy);   // send transfer string
-
-        sResult = U14CheckErr(hand);    // Use ERR command to check for done
-        if (sResult > 0)
-            sResult = U14ERR_TOXXXERR;  // If a 1401 error, use this code
-
-        U14UnSetTransfer(hand, 0);
-    }
-    return sResult;
-}
-
-/****************************************************************************
-** Function  ToHost transfers data into the host from the 1401
-****************************************************************************/
-U14API(short) U14ToHost(short hand, char* pAddrHost, unsigned int dwSize,
-                                            unsigned int dw1401, short eSz)
-{
-    short sErr = CheckHandle(hand);
-    if ((sErr == U14ERR_NOERROR) && dwSize) // TOHOST is a constant
-        sErr = Transfer(hand, TOHOST, pAddrHost, dwSize, dw1401, eSz);
-    return sErr;
-}
-
-/****************************************************************************
-** Function  To1401 transfers data into the 1401 from the host
-****************************************************************************/
-U14API(short) U14To1401(short hand, const char* pAddrHost,unsigned int dwSize,
-                                    unsigned int dw1401, short eSz)
-{
-    short sErr = CheckHandle(hand);
-    if ((sErr == U14ERR_NOERROR) && dwSize) // TO1401 is a constant
-        sErr = Transfer(hand, TO1401, (char*)pAddrHost, dwSize, dw1401, eSz);
-    return sErr;
-}
-
-/****************************************************************************
-** Function  LdCmd    Loads a command from a full path or just a file
-*****************************************************************************/
-#ifdef _IS_WINDOWS_
-#define file_exist(name) (_access(name, 0) != -1)
-#define file_open(name) _lopen(name, OF_READ)
-#define file_close(h)   _lclose(h)
-#define file_seek(h, pos) _llseek(h, pos, FILE_BEGIN) 
-#define file_read(h, buffer, size) (_lread(h, buffer, size) == size)
-#endif
-#ifdef LINUX
-#define file_exist(name) (access(name, F_OK) != -1)
-#define file_open(name) open(name, O_RDONLY)
-#define file_close(h)   close(h)
-#define file_seek(h, pos) lseek(h, pos, SEEK_SET) 
-#define file_read(h, buffer, size) (read(h, buffer, size) == (ssize_t)size)
-static unsigned int GetModuleFileName(void* dummy, char* buffer, int max)
-{
-    // The following works for Linux systems with a /proc file system.
-    char szProcPath[32];
-    sprintf(szProcPath, "/proc/%d/exe", getpid());  // attempt to read link
-    if (readlink(szProcPath, buffer, max) != -1)
-    {
-        dirname (buffer);
-        strcat  (buffer, "/");
-        return strlen(buffer);
-    }
-    return 0;
-}
-#endif
-
-U14API(short) U14LdCmd(short hand, const char* command)
-{
-    char strcopy[MAXSTRLEN+1];      // to hold copy of work string
-    BOOL bGotIt = FALSE;            // have we found the command file?
-    int iFHandle;                   // file handle of command
-#define FNSZ 260
-    char filnam[FNSZ];              // space to build name in
-    char szCmd[25];                 // just the command name with extension
-
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-
-    if (strchr(command, '.') != NULL)       // see if we have full name
-    {
-        if (file_exist(command))            // If the file exists
-        {
-            strcpy(filnam, command);        // use name as is
-            bGotIt = TRUE;                  // Flag no more searching
-        }
-        else                                // not found, get file name for search
-        {
-            char* pStr = strrchr(command, PATHSEP);  // Point to last separator
-            if (pStr != NULL)               // Check we got it
-            {
-                pStr++;                     // move past the backslash
-                strcpy(szCmd, pStr);        // copy file name as is
-            }
-            else
-                strcpy(szCmd, command);     // use as is
-        }
-    }
-    else    // File extension not supplied, so build the command file name
-    {
-        char szExt[8];
-        strcpy(szCmd, command);             // Build command file name
-        ExtForType(asType1401[hand], szExt);// File extension string
-        strcat(szCmd, szExt);               // add it to the end
-    }
-
-    // Next place to look is in the 1401 folder in the same place as the
-    // application was run from.
-    if (!bGotIt)                            // Still not got it?
-    {
-        unsigned int dwLen = GetModuleFileName(NULL, filnam, FNSZ); // Get app path
-        if (dwLen > 0)                      // and use it as path if found
-        {
-            char* pStr = strrchr(filnam, PATHSEP);    // Point to last separator
-            if (pStr != NULL)
-            {
-                *(++pStr) = 0;                  // Terminate string there
-                if (strlen(filnam) < FNSZ-6)    // make sure we have space
-                {
-                    strcat(filnam, "1401" PATHSEPSTR);  // add in 1401 subdir
-                    strcat(filnam,szCmd);
-                    bGotIt = (BOOL)file_exist(filnam);  // See if file exists
-                }
-            }
-        }
-    }
-
-    // Next place to look is in whatever path is set by the 1401DIR environment
-    // variable, if it exists.
-    if (!bGotIt)                            // Need to do more searches?/
-    {
-        char* pStr = getenv("1401DIR");     // Try to find environment var
-        if (pStr != NULL)                   // and use it as path if found
-        {
-            strcpy(filnam, pStr);                   // Use path in environment
-            if (filnam[strlen(filnam)-1] != PATHSEP)// We need separator
-                strcat(filnam, PATHSEPSTR);
-            strcat(filnam, szCmd);
-            bGotIt = (BOOL)file_exist(filnam); // Got this one?
-        }
-    }
-
-    // Last place to look is the default location.
-    if (!bGotIt)                        // Need to do more searches?
-    {
-        strcpy(filnam, DEFCMDPATH);     // Use default path
-        strcat(filnam, szCmd);
-        bGotIt = file_exist(filnam);    // Got this one?
-    }
-
-    iFHandle = file_open(filnam);
-    if (iFHandle == -1)
-        sErr = U14ERR_NOFILE;
-    else
-    {                                   // first read in the header block
-        CMDHEAD rCmdHead;               // to hold the command header
-        if (file_read(iFHandle, &rCmdHead, sizeof(CMDHEAD)))
-        {
-            size_t nComSize = rCmdHead.wCmdSize;
-            char* pMem = malloc(nComSize);
-            if (pMem != NULL)
-            {
-                file_seek(iFHandle, sizeof(CMDHEAD));
-                if (file_read(iFHandle, pMem, (UINT)nComSize))
-                {
-                    sErr = U14SetTransArea(hand, 0, (void *)pMem, (unsigned int)nComSize, ESZBYTES);
-                    if (sErr == U14ERR_NOERROR)
-                    {
-                        sprintf(strcopy, "CLOAD,0,$%X;", (int)nComSize);
-                        sErr = U14SendString(hand, strcopy);
-                        if (sErr == U14ERR_NOERROR)
-                        {
-                            sErr = U14CheckErr(hand);     // Use ERR to check for done
-                            if (sErr > 0)
-                                sErr = U14ERR_CLOADERR;   // If an error, this code
-                        }
-                        U14UnSetTransfer(hand, 0);  // release transfer area
-                    }
-                }
-                else
-                    sErr = U14ERR_READERR;
-                free(pMem);
-            }
-            else
-                sErr = U14ERR_HOSTSPACE;    // memory allocate failed
-        }
-        else
-            sErr = U14ERR_READERR;
-
-        file_close(iFHandle);               // close the file
-    }
-
-    return sErr;
-}
-
-
-/****************************************************************************
-** Ld
-** Loads a command into the 1401
-** Returns NOERROR code or a long with error in lo word and index of
-** command that failed in high word
-****************************************************************************/
-U14API(unsigned int) U14Ld(short hand, const char* vl, const char* str)
-{
-    unsigned int dwIndex = 0;              // index to current command
-    long lErr = U14ERR_NOERROR;     // what the error was that went wrong
-    char strcopy[MAXSTRLEN+1];      // stores unmodified str parameter
-    char szFExt[8];                 // The command file extension
-    short sErr = CheckHandle(hand);
-    if (sErr != U14ERR_NOERROR)
-        return sErr;
-
-    ExtForType(asType1401[hand], szFExt);   // File extension string
-    strcpy(strcopy, str);               // to avoid changing original
-
-    // now break out one command at a time and see if loaded
-    if (*str)                           // if anything there
-    {
-        BOOL bDone = FALSE;             // true when finished all commands
-        int iLoop1 = 0;                 // Point at start of string for command name
-        int iLoop2 = 0;                 // and at start of str parameter
-        do                              // repeat until end of str
-        {
-            char filnam[MAXSTRLEN+1];   // filename to use
-            char szFName[MAXSTRLEN+1];  // filename work string
-
-            if (!strcopy[iLoop1])       // at the end of the string?
-                bDone = TRUE;           // set the finish flag
-
-            if (bDone || (strcopy[iLoop1] == ','))  // end of cmd?
-            {
-                U14LONG er[5];                  // Used to read back error results
-                ++dwIndex;                      // Keep count of command number, first is 1
-                szFName[iLoop2]=(char)0;        // null terminate name of command
-
-                strncpy(szLastName, szFName, sizeof(szLastName));    // Save for error info
-                szLastName[sizeof(szLastName)-1] = 0;
-                strncat(szLastName, szFExt, sizeof(szLastName));     // with extension included
-                szLastName[sizeof(szLastName)-1] = 0;
-
-                U14SendString(hand, szFName);   // ask if loaded
-                U14SendString(hand, ";ERR;");   // add err return
-
-                lErr = U14LongsFrom1401(hand, er, 5);
-                if (lErr > 0)
-                {
-                    lErr = U14ERR_NOERROR;
-                    if (er[0] == 255)           // if command not loaded at all
-                    {
-                        if (vl && *vl)          // if we have a path name
-                        {
-                            strcpy(filnam, vl);
-                            if (strchr("\\/:", filnam[strlen(filnam)-1]) == NULL)
-                                strcat(filnam, PATHSEPSTR); // add separator if none found
-                            strcat(filnam, szFName);    // add the file name
-                            strcat(filnam, szFExt);     // and extension
-                        }
-                        else
-                            strcpy(filnam, szFName);    // simple name
-
-                        lErr = U14LdCmd(hand, filnam);  // load cmd
-                        if (lErr != U14ERR_NOERROR)     // spot any errors
-                            bDone = TRUE;               // give up if an error
-                    }
-                }
-                else
-                    bDone = TRUE;       // give up if an error
-
-                iLoop2 = 0;             // Reset pointer to command name string
-                ++iLoop1;               // and move on through str parameter
-            }
-            else
-                szFName[iLoop2++] = strcopy[iLoop1++];  // no command end, so copy 1 char
-        }
-        while (!bDone);
-    }
-
-    if (lErr == U14ERR_NOERROR)
-    {
-        szLastName[0] = 0;      // No error, so clean out command name here
-        return lErr;
-    }
-    else
-        return ((dwIndex<<16) | ((unsigned int)lErr & 0x0000FFFF));
-}
-
-// Initialise the library (if not initialised) and return the library version
-U14API(int) U14InitLib(void)
-{
-    int iRetVal = U14LIB_VERSION;
-    if (iAttached == 0)         // only do this the first time please
-    {
-        int i;
-#ifdef _IS_WINDOWS_
-        int j;
-        unsigned int   dwVersion = GetVersion();
-        bWindows9x = FALSE;                  // Assume not Win9x
-
-        if (dwVersion & 0x80000000)                 // if not windows NT
-        {
-            if ((LOBYTE(LOWORD(dwVersion)) < 4) &&  // if Win32s or...
-                 (HIBYTE(LOWORD(dwVersion)) < 95))  // ...below Windows 95
-            iRetVal = 0;                            // We do not support this
-        else
-            bWindows9x = TRUE;                      // Flag we have Win9x
-        }
-#endif
-        
-        for (i = 0; i < MAX1401; i++)               // initialise the device area
-        {
-            aHand1401[i] = INVALID_HANDLE_VALUE;    // Clear handle values
-            asType1401[i] = U14TYPEUNKNOWN;         // and 1401 type codes
-            alTimeOutPeriod[i] = 3000;              // 3 second timeouts
-#ifdef _IS_WINDOWS_
-#ifndef _WIN64
-            abUseNTDIOC[i] = (BOOL)!bWindows9x;
-#endif
-            aXferEvent[i] = NULL;                   // there are no Xfer events
-            for (j = 0; j < MAX_TRANSAREAS; j++)    // Clear out locked area info
-            {
-                apAreas[i][j] = NULL;
-                auAreas[i][j] = 0;
-            }
-#endif
-        }
-    }
-    return iRetVal;
-}
-
-///--------------------------------------------------------------------------------
-/// Functions called when the library is loaded and unloaded to give us a chance to
-/// setup the library.
-
-
-#ifdef _IS_WINDOWS_
-#ifndef U14_NOT_DLL
-/****************************************************************************
-** FUNCTION: DllMain(HANDLE, unsigned int, LPVOID)
-** LibMain is called by Windows when the DLL is initialized, Thread Attached,
-** and other times. Refer to SDK documentation, as to the different ways this
-** may be called.
-****************************************************************************/
-INT APIENTRY DllMain(HANDLE hInst, unsigned int ul_reason_being_called, LPVOID lpReserved)
-{
-    int iRetVal = 1;
-
-    switch (ul_reason_being_called)
-    {
-    case DLL_PROCESS_ATTACH:
-        iRetVal = U14InitLib() > 0;         // does nothing if iAttached != 0
-        ++iAttached;                        // count times attached
-        break;
-
-    case DLL_PROCESS_DETACH:
-        if (--iAttached == 0)               // last man out?
-            U14CloseAll();                  // release all open handles
-        break;
-    }
-    return iRetVal;
-
-    UNREFERENCED_PARAMETER(lpReserved);
-}
-#endif
-#endif
-#ifdef LINUX
-void __attribute__((constructor)) use1401_load(void)
-{
-    U14InitLib();
-    ++iAttached;
-}
-
-void __attribute__((destructor)) use1401_unload(void)
-{
-        if (--iAttached == 0)               // last man out?
-            U14CloseAll();                  // release all open handles
-}
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedi_compat32.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_compat32.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedi_compat32.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_compat32.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,10 +107,10 @@ static int compat_chaninfo(struct file *
 	chaninfo = compat_alloc_user_space(sizeof(*chaninfo));
 
 	/* Copy chaninfo structure.  Ignore unused members. */
-	if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32))
-	    || !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo))) {
+	if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32)) ||
+	    !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo)))
 		return -EFAULT;
-	}
+
 	err = 0;
 	err |= __get_user(temp.uint, &chaninfo32->subdev);
 	err |= __put_user(temp.uint, &chaninfo->subdev);
@@ -141,10 +141,10 @@ static int compat_rangeinfo(struct file
 	rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo));
 
 	/* Copy rangeinfo structure. */
-	if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32))
-	    || !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo))) {
+	if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32)) ||
+	    !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo)))
 		return -EFAULT;
-	}
+
 	err = 0;
 	err |= __get_user(temp.uint, &rangeinfo32->range_type);
 	err |= __put_user(temp.uint, &rangeinfo->range_type);
@@ -168,10 +168,10 @@ static int get_compat_cmd(struct comedi_
 	} temp;
 
 	/* Copy cmd structure. */
-	if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32))
-	    || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) {
+	if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) ||
+	    !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd)))
 		return -EFAULT;
-	}
+
 	err = 0;
 	err |= __get_user(temp.uint, &cmd32->subdev);
 	err |= __put_user(temp.uint, &cmd->subdev);
@@ -219,10 +219,10 @@ static int put_compat_cmd(struct comedi3
 	/* Assume the pointer values are already valid. */
 	/* (Could use ptr_to_compat() to set them, but that wasn't implemented
 	 * until kernel version 2.6.11.) */
-	if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd))
-	    || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) {
+	if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) ||
+	    !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32)))
 		return -EFAULT;
-	}
+
 	err = 0;
 	err |= __get_user(temp, &cmd->subdev);
 	err |= __put_user(temp, &cmd32->subdev);
@@ -311,8 +311,8 @@ static int get_compat_insn(struct comedi
 
 	/* Copy insn structure.  Ignore the unused members. */
 	err = 0;
-	if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
-	    || !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
+	if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) ||
+	    !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
 		return -EFAULT;
 
 	err |= __get_user(temp.uint, &insn32->insn);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedi_compat32.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_compat32.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedi_compat32.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_compat32.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,8 +25,7 @@
 #ifdef CONFIG_COMPAT
 
 struct file;
-extern long comedi_compat_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg);
+long comedi_compat_ioctl(struct file *, unsigned int cmd, unsigned long arg);
 
 #else /* CONFIG_COMPAT */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedidev.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedidev.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedidev.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedidev.h	2014-09-28 17:29:07.000000000 -0400
@@ -75,13 +75,9 @@ struct comedi_subdevice {
 			  struct comedi_cmd *);
 	int (*poll)(struct comedi_device *, struct comedi_subdevice *);
 	int (*cancel)(struct comedi_device *, struct comedi_subdevice *);
-	/* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */
-	/* int (*do_unlock)(struct comedi_device *, \
-			struct comedi_subdevice *); */
 
 	/* called when the buffer changes */
-	int (*buf_change)(struct comedi_device *dev,
-			  struct comedi_subdevice *s, unsigned long new_size);
+	int (*buf_change)(struct comedi_device *, struct comedi_subdevice *);
 
 	void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
 		      void *data, unsigned int num_bytes,
@@ -107,43 +103,110 @@ struct comedi_buf_map {
 	struct kref refcount;
 };
 
+/**
+ * struct comedi_async - control data for asynchronous comedi commands
+ * @prealloc_buf:	preallocated buffer
+ * @prealloc_bufsz:	buffer size (in bytes)
+ * @buf_map:		map of buffer pages
+ * @max_bufsize:	maximum buffer size (in bytes)
+ * @buf_write_count:	"write completed" count (in bytes, modulo 2**32)
+ * @buf_write_alloc_count: "allocated for writing" count (in bytes,
+ *			modulo 2**32)
+ * @buf_read_count:	"read completed" count (in bytes, modulo 2**32)
+ * @buf_read_alloc_count: "allocated for reading" count (in bytes,
+ *			modulo 2**32)
+ * @buf_write_ptr:	buffer position for writer
+ * @buf_read_ptr:	buffer position for reader
+ * @cur_chan:		current position in chanlist for scan (for those
+ *			drivers that use it)
+ * @scan_progress:	amount received or sent for current scan (in bytes)
+ * @munge_chan:		current position in chanlist for "munging"
+ * @munge_count:	"munge" count (in bytes, modulo 2**32)
+ * @munge_ptr:		buffer position for "munging"
+ * @events:		bit-vector of events that have occurred
+ * @cmd:		details of comedi command in progress
+ * @wait_head:		task wait queue for file reader or writer
+ * @cb_mask:		bit-vector of events that should wake waiting tasks
+ * @inttrig:		software trigger function for command, or NULL
+ *
+ * Note about the ..._count and ..._ptr members:
+ *
+ * Think of the _Count values being integers of unlimited size, indexing
+ * into a buffer of infinite length (though only an advancing portion
+ * of the buffer of fixed length prealloc_bufsz is accessible at any time).
+ * Then:
+ *
+ *   Buf_Read_Count <= Buf_Read_Alloc_Count <= Munge_Count <=
+ *   Buf_Write_Count <= Buf_Write_Alloc_Count <=
+ *   (Buf_Read_Count + prealloc_bufsz)
+ *
+ * (Those aren't the actual members, apart from prealloc_bufsz.) When
+ * the buffer is reset, those _Count values start at 0 and only increase
+ * in value, maintaining the above inequalities until the next time the
+ * buffer is reset.  The buffer is divided into the following regions by
+ * the inequalities:
+ *
+ *   [0, Buf_Read_Count):
+ *     old region no longer accessible
+ *   [Buf_Read_Count, Buf_Read_Alloc_Count):
+ *     filled and munged region allocated for reading but not yet read
+ *   [Buf_Read_Alloc_Count, Munge_Count):
+ *     filled and munged region not yet allocated for reading
+ *   [Munge_Count, Buf_Write_Count):
+ *     filled region not yet munged
+ *   [Buf_Write_Count, Buf_Write_Alloc_Count):
+ *     unfilled region allocated for writing but not yet written
+ *   [Buf_Write_Alloc_Count, Buf_Read_Count + prealloc_bufsz):
+ *     unfilled region not yet allocated for writing
+ *   [Buf_Read_Count + prealloc_bufsz, infinity):
+ *     unfilled region not yet accessible
+ *
+ * Data needs to be written into the buffer before it can be read out,
+ * and may need to be converted (or "munged") between the two
+ * operations.  Extra unfilled buffer space may need to allocated for
+ * writing (advancing Buf_Write_Alloc_Count) before new data is written.
+ * After writing new data, the newly filled space needs to be released
+ * (advancing Buf_Write_Count).  This also results in the new data being
+ * "munged" (advancing Munge_Count).  Before data is read out of the
+ * buffer, extra space may need to be allocated for reading (advancing
+ * Buf_Read_Alloc_Count).  After the data has been read out, the space
+ * needs to be released (advancing Buf_Read_Count).
+ *
+ * The actual members, buf_read_count, buf_read_alloc_count,
+ * munge_count, buf_write_count, and buf_write_alloc_count take the
+ * value of the corresponding capitalized _Count values modulo 2^32
+ * (UINT_MAX+1).  Subtracting a "higher" _count value from a "lower"
+ * _count value gives the same answer as subtracting a "higher" _Count
+ * value from a lower _Count value because prealloc_bufsz < UINT_MAX+1.
+ * The modulo operation is done implicitly.
+ *
+ * The buf_read_ptr, munge_ptr, and buf_write_ptr members take the value
+ * of the corresponding capitalized _Count values modulo prealloc_bufsz.
+ * These correspond to byte indices in the physical buffer.  The modulo
+ * operation is done by subtracting prealloc_bufsz when the value
+ * exceeds prealloc_bufsz (assuming prealloc_bufsz plus the increment is
+ * less than or equal to UINT_MAX).
+ */
 struct comedi_async {
-	void *prealloc_buf;	/* pre-allocated buffer */
-	unsigned int prealloc_bufsz;	/* buffer size, in bytes */
-	struct comedi_buf_map *buf_map;	/* map of buffer pages */
-
-	unsigned int max_bufsize;	/* maximum buffer size, bytes */
-
-	/* byte count for writer (write completed) */
+	void *prealloc_buf;
+	unsigned int prealloc_bufsz;
+	struct comedi_buf_map *buf_map;
+	unsigned int max_bufsize;
 	unsigned int buf_write_count;
-	/* byte count for writer (allocated for writing) */
 	unsigned int buf_write_alloc_count;
-	/* byte count for reader (read completed) */
 	unsigned int buf_read_count;
-	/* byte count for reader (allocated for reading) */
 	unsigned int buf_read_alloc_count;
-
-	unsigned int buf_write_ptr;	/* buffer marker for writer */
-	unsigned int buf_read_ptr;	/* buffer marker for reader */
-
-	unsigned int cur_chan;	/* useless channel marker for interrupt */
-	/* number of bytes that have been received for current scan */
+	unsigned int buf_write_ptr;
+	unsigned int buf_read_ptr;
+	unsigned int cur_chan;
 	unsigned int scan_progress;
-	/* keeps track of where we are in chanlist as for munging */
 	unsigned int munge_chan;
-	/* number of bytes that have been munged */
 	unsigned int munge_count;
-	/* buffer marker for munging */
 	unsigned int munge_ptr;
-
-	unsigned int events;	/* events that have occurred */
-
+	unsigned int events;
 	struct comedi_cmd cmd;
-
 	wait_queue_head_t wait_head;
-
 	unsigned int cb_mask;
-
 	int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
 		       unsigned int x);
 };
@@ -190,6 +253,7 @@ struct comedi_device {
 	struct comedi_subdevice *subdevices;
 
 	/* dumb */
+	void __iomem *mmio;
 	unsigned long iobase;
 	unsigned long iolen;
 	unsigned int irq;
@@ -213,7 +277,6 @@ static inline const void *comedi_board(c
  */
 
 void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
-void comedi_error(const struct comedi_device *dev, const char *s);
 
 /* we can expand the number of bits used to encode devices/subdevices into
  the minor number soon, after more distros support > 8 bit minor numbers
@@ -222,6 +285,7 @@ enum comedi_minor_bits {
 	COMEDI_DEVICE_MINOR_MASK = 0xf,
 	COMEDI_SUBDEVICE_MINOR_MASK = 0xf0
 };
+
 static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4;
 static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
 
@@ -296,6 +360,12 @@ static inline bool comedi_range_is_unipo
 	return s->range_table->range[range].min >= 0;
 }
 
+static inline bool comedi_range_is_external(struct comedi_subdevice *s,
+					    unsigned int range)
+{
+	return !!(s->range_table->range[range].flags & RF_EXTERNAL);
+}
+
 static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s,
 						unsigned int chan,
 						unsigned int range)
@@ -310,6 +380,13 @@ static inline bool comedi_chan_range_is_
 	return s->range_table_list[chan]->range[range].min >= 0;
 }
 
+static inline bool comedi_chan_range_is_external(struct comedi_subdevice *s,
+						 unsigned int chan,
+						 unsigned int range)
+{
+	return !!(s->range_table_list[chan]->range[range].flags & RF_EXTERNAL);
+}
+
 /* munge between offset binary and two's complement values */
 static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s,
 					       unsigned int val)
@@ -321,8 +398,8 @@ static inline unsigned int bytes_per_sam
 {
 	if (subd->subdev_flags & SDF_LSAMPL)
 		return sizeof(unsigned int);
-	else
-		return sizeof(short);
+
+	return sizeof(short);
 }
 
 /*
@@ -333,6 +410,11 @@ static inline unsigned int bytes_per_sam
  */
 int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev);
 
+static inline unsigned int comedi_buf_n_bytes_ready(struct comedi_subdevice *s)
+{
+	return s->async->buf_write_count - s->async->buf_read_count;
+}
+
 unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int n);
 unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int n);
 
@@ -484,9 +566,9 @@ int comedi_pcmcia_auto_config(struct pcm
 void comedi_pcmcia_auto_unconfig(struct pcmcia_device *);
 
 int comedi_pcmcia_driver_register(struct comedi_driver *,
-					struct pcmcia_driver *);
+				  struct pcmcia_driver *);
 void comedi_pcmcia_driver_unregister(struct comedi_driver *,
-					struct pcmcia_driver *);
+				     struct pcmcia_driver *);
 
 /**
  * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedi_fops.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_fops.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedi_fops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_fops.c	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,8 @@
     GNU General Public License for more details.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "comedi_compat32.h"
 
 #include <linux/module.h>
@@ -206,8 +208,8 @@ struct comedi_device *comedi_dev_get_fro
 {
 	if (minor < COMEDI_NUM_BOARD_MINORS)
 		return comedi_dev_get_from_board_minor(minor);
-	else
-		return comedi_dev_get_from_subdevice_minor(minor);
+
+	return comedi_dev_get_from_subdevice_minor(minor);
 }
 EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor);
 
@@ -266,7 +268,7 @@ static int resize_async_buffer(struct co
 		return retval;
 
 	if (s->buf_change) {
-		retval = s->buf_change(dev, s, new_size);
+		retval = s->buf_change(dev, s);
 		if (retval < 0)
 			return retval;
 	}
@@ -968,9 +970,6 @@ static int do_bufinfo_ioctl(struct comed
 
 	s = &dev->subdevices[bi.subdevice];
 
-	if (s->lock && s->lock != file)
-		return -EACCES;
-
 	async = s->async;
 
 	if (!async) {
@@ -997,7 +996,7 @@ static int do_bufinfo_ioctl(struct comed
 		comedi_buf_read_free(s, bi.bytes_read);
 
 		if (comedi_is_subdevice_idle(s) &&
-		    async->buf_write_count == async->buf_read_count) {
+		    comedi_buf_n_bytes_ready(s) == 0) {
 			do_become_nonbusy(dev, s);
 		}
 	}
@@ -1076,11 +1075,10 @@ static int check_insn_config_length(stru
 		/* by default we allow the insn since we don't have checks for
 		 * all possible cases yet */
 	default:
-		pr_warn("comedi: No check for data length of config insn id %i is implemented.\n",
+		pr_warn("No check for data length of config insn id %i is implemented\n",
 			data[0]);
-		pr_warn("comedi: Add a check to %s in %s.\n",
-			__func__, __FILE__);
-		pr_warn("comedi: Assuming n=%i is correct.\n", insn->n);
+		pr_warn("Add a check to %s in %s\n", __func__, __FILE__);
+		pr_warn("Assuming n=%i is correct\n", insn->n);
 		return 0;
 	}
 	return -EINVAL;
@@ -1229,10 +1227,9 @@ static int parse_insn(struct comedi_devi
 				/* Most drivers ignore the base channel in
 				 * insn->chanspec.  Fix this here if
 				 * the subdevice has <= 32 channels.  */
-				unsigned int shift;
-				unsigned int orig_mask;
+				unsigned int orig_mask = data[0];
+				unsigned int shift = 0;
 
-				orig_mask = data[0];
 				if (s->n_chan <= 32) {
 					shift = CR_CHAN(insn->chanspec);
 					if (shift > 0) {
@@ -1240,8 +1237,7 @@ static int parse_insn(struct comedi_devi
 						data[0] <<= shift;
 						data[1] <<= shift;
 					}
-				} else
-					shift = 0;
+				}
 				ret = s->insn_bits(dev, s, insn, data);
 				data[0] = orig_mask;
 				if (shift > 0)
@@ -1295,7 +1291,7 @@ static int do_insnlist_ioctl(struct come
 	if (copy_from_user(&insnlist, arg, sizeof(insnlist)))
 		return -EFAULT;
 
-	data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
+	data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
 	if (!data) {
 		ret = -ENOMEM;
 		goto error;
@@ -1376,7 +1372,7 @@ static int do_insn_ioctl(struct comedi_d
 	unsigned int *data = NULL;
 	int ret = 0;
 
-	data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
+	data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
 	if (!data) {
 		ret = -ENOMEM;
 		goto error;
@@ -1664,14 +1660,6 @@ static int do_lock_ioctl(struct comedi_d
 		s->lock = file;
 	spin_unlock_irqrestore(&s->spin_lock, flags);
 
-#if 0
-	if (ret < 0)
-		return ret;
-
-	if (s->lock_f)
-		ret = s->lock_f(dev, s);
-#endif
-
 	return ret;
 }
 
@@ -1706,14 +1694,8 @@ static int do_unlock_ioctl(struct comedi
 	if (s->lock && s->lock != file)
 		return -EACCES;
 
-	if (s->lock == file) {
-#if 0
-		if (s->unlock)
-			s->unlock(dev, s);
-#endif
-
+	if (s->lock == file)
 		s->lock = NULL;
-	}
 
 	return 0;
 }
@@ -1744,9 +1726,6 @@ static int do_cancel_ioctl(struct comedi
 	if (s->async == NULL)
 		return -EINVAL;
 
-	if (s->lock && s->lock != file)
-		return -EACCES;
-
 	if (!s->busy)
 		return 0;
 
@@ -1781,9 +1760,6 @@ static int do_poll_ioctl(struct comedi_d
 		return -EINVAL;
 	s = &dev->subdevices[arg];
 
-	if (s->lock && s->lock != file)
-		return -EACCES;
-
 	if (!s->busy)
 		return 0;
 
@@ -2186,7 +2162,7 @@ out:
 }
 
 static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
-				loff_t *offset)
+			   loff_t *offset)
 {
 	struct comedi_subdevice *s;
 	struct comedi_async *async;
@@ -2230,10 +2206,8 @@ static ssize_t comedi_read(struct file *
 		n = nbytes;
 
 		m = comedi_buf_read_n_available(s);
-		/* printk("%d available\n",m); */
 		if (async->buf_read_ptr + m > async->prealloc_bufsz)
 			m = async->prealloc_bufsz - async->buf_read_ptr;
-		/* printk("%d contiguous\n",m); */
 		if (m < n)
 			n = m;
 
@@ -2303,8 +2277,7 @@ static ssize_t comedi_read(struct file *
 		new_s = comedi_read_subdevice(dev, minor);
 		if (dev->attached && old_detach_count == dev->detach_count &&
 		    s == new_s && new_s->async == async) {
-			if (become_nonbusy ||
-			    async->buf_read_count - async->buf_write_count == 0)
+			if (become_nonbusy || comedi_buf_n_bytes_ready(s) == 0)
 				do_become_nonbusy(dev, s);
 		}
 		mutex_unlock(&dev->mutex);
@@ -2411,12 +2384,6 @@ static const struct file_operations come
 	.llseek = noop_llseek,
 };
 
-void comedi_error(const struct comedi_device *dev, const char *s)
-{
-	dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s);
-}
-EXPORT_SYMBOL_GPL(comedi_error);
-
 void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct comedi_async *async = s->async;
@@ -2460,7 +2427,7 @@ struct comedi_device *comedi_alloc_board
 	struct device *csdev;
 	unsigned i;
 
-	dev = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return ERR_PTR(-ENOMEM);
 	comedi_device_init(dev);
@@ -2479,7 +2446,7 @@ struct comedi_device *comedi_alloc_board
 		mutex_unlock(&dev->mutex);
 		comedi_device_cleanup(dev);
 		comedi_dev_put(dev);
-		pr_err("comedi: error: ran out of minor numbers for board device files.\n");
+		pr_err("ran out of minor numbers for board device files\n");
 		return ERR_PTR(-EBUSY);
 	}
 	dev->minor = i;
@@ -2532,7 +2499,7 @@ int comedi_alloc_subdevice_minor(struct
 	}
 	mutex_unlock(&comedi_subdevice_minor_table_lock);
 	if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
-		pr_err("comedi: error: ran out of minor numbers for subdevice files.\n");
+		pr_err("ran out of minor numbers for subdevice files\n");
 		return -EBUSY;
 	}
 	i += COMEDI_NUM_BOARD_MINORS;
@@ -2582,11 +2549,11 @@ static int __init comedi_init(void)
 	int i;
 	int retval;
 
-	pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n");
+	pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n");
 
 	if (comedi_num_legacy_minors < 0 ||
 	    comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
-		pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\".  Valid values are 0 through %i.\n",
+		pr_err("invalid value for module parameter \"comedi_num_legacy_minors\".  Valid values are 0 through %i.\n",
 		       COMEDI_NUM_BOARD_MINORS);
 		return -EINVAL;
 	}
@@ -2597,7 +2564,14 @@ static int __init comedi_init(void)
 		return -EIO;
 	cdev_init(&comedi_cdev, &comedi_fops);
 	comedi_cdev.owner = THIS_MODULE;
-	kobject_set_name(&comedi_cdev.kobj, "comedi");
+
+	retval = kobject_set_name(&comedi_cdev.kobj, "comedi");
+	if (retval) {
+		unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+					 COMEDI_NUM_MINORS);
+		return retval;
+	}
+
 	if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
 		unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
 					 COMEDI_NUM_MINORS);
@@ -2605,7 +2579,7 @@ static int __init comedi_init(void)
 	}
 	comedi_class = class_create(THIS_MODULE, "comedi");
 	if (IS_ERR(comedi_class)) {
-		pr_err("comedi: failed to create class\n");
+		pr_err("failed to create class\n");
 		cdev_del(&comedi_cdev);
 		unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
 					 COMEDI_NUM_MINORS);
@@ -2628,10 +2602,9 @@ static int __init comedi_init(void)
 			unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
 						 COMEDI_NUM_MINORS);
 			return PTR_ERR(dev);
-		} else {
-			/* comedi_alloc_board_minor() locked the mutex */
-			mutex_unlock(&dev->mutex);
 		}
+		/* comedi_alloc_board_minor() locked the mutex */
+		mutex_unlock(&dev->mutex);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedi.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi.h	2014-09-28 17:29:07.000000000 -0400
@@ -551,21 +551,8 @@ enum i8254_mode {
 	I8254_BINARY = 0
 };
 
-static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel)
-{
-	if (pfi_channel < 10)
-		return 0x1 + pfi_channel;
-	else
-		return 0xb + pfi_channel;
-}
-
-static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel)
-{
-	if (rtsi_channel < 7)
-		return 0xb + rtsi_channel;
-	else
-		return 0x1b;
-}
+#define NI_USUAL_PFI_SELECT(x)	(((x) < 10) ? (0x1 + (x)) : (0xb + (x)))
+#define NI_USUAL_RTSI_SELECT(x)	(((x) < 7) ? (0xb + (x)) : 0x1b)
 
 /* mode bits for NI general-purpose counters, set with
  * INSN_CONFIG_SET_COUNTER_MODE */
@@ -659,20 +646,14 @@ enum ni_gpct_clock_source_bits {
 	NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000,
 	NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000
 };
-static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n)
-{
-	/* NI 660x-specific */
-	return 0x10 + n;
-}
-static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n)
-{
-	return 0x18 + n;
-}
-static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n)
-{
-	/* no pfi on NI 660x */
-	return 0x20 + n;
-}
+
+/* NI 660x-specific */
+#define NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(x)	(0x10 + (x))
+
+#define NI_GPCT_RTSI_CLOCK_SRC_BITS(x)		(0x18 + (x))
+
+/* no pfi on NI 660x */
+#define NI_GPCT_PFI_CLOCK_SRC_BITS(x)		(0x20 + (x))
 
 /* Possibilities for setting a gate source with
 INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters.
@@ -698,22 +679,11 @@ enum ni_gpct_gate_select {
 	 * known. */
 	NI_GPCT_DISABLED_GATE_SELECT = 0x8000,
 };
-static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n)
-{
-	return 0x102 + n;
-}
-static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n)
-{
-	return NI_USUAL_RTSI_SELECT(n);
-}
-static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n)
-{
-	return NI_USUAL_PFI_SELECT(n);
-}
-static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n)
-{
-	return 0x202 + n;
-}
+
+#define NI_GPCT_GATE_PIN_GATE_SELECT(x)		(0x102 + (x))
+#define NI_GPCT_RTSI_GATE_SELECT(x)		NI_USUAL_RTSI_SELECT(x)
+#define NI_GPCT_PFI_GATE_SELECT(x)		NI_USUAL_PFI_SELECT(x)
+#define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x)	(0x202 + (x))
 
 /* Possibilities for setting a source with
 INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */
@@ -722,15 +692,14 @@ enum ni_gpct_other_index {
 	NI_GPCT_SOURCE_ENCODER_B,
 	NI_GPCT_SOURCE_ENCODER_Z
 };
+
 enum ni_gpct_other_select {
 	/* m-series gates */
 	/* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */
 	NI_GPCT_DISABLED_OTHER_SELECT = 0x8000,
 };
-static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n)
-{
-	return NI_USUAL_PFI_SELECT(n);
-}
+
+#define NI_GPCT_PFI_OTHER_SELECT(x)	NI_USUAL_PFI_SELECT(x)
 
 /* start sources for ni general-purpose counters for use with
 INSN_CONFIG_ARM */
@@ -777,10 +746,8 @@ enum ni_mio_clock_source {
 	NI_MIO_PLL_PXI10_CLOCK = 3,
 	NI_MIO_PLL_RTSI0_CLOCK = 4
 };
-static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel)
-{
-	return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel;
-}
+
+#define NI_MIO_PLL_RTSI_CLOCK(x)	(NI_MIO_PLL_RTSI0_CLOCK + (x))
 
 /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING.
  The numbers assigned are not arbitrary, they correspond to the bits required
@@ -798,10 +765,8 @@ enum ni_rtsi_routing {
 	NI_RTSI_OUTPUT_RTSI_OSC = 12	/* pre-m-series always have RTSI
 					 * clock on line 7 */
 };
-static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n)
-{
-	return NI_RTSI_OUTPUT_RTSI_BRD_0 + n;
-}
+
+#define NI_RTSI_OUTPUT_RTSI_BRD(x)	(NI_RTSI_OUTPUT_RTSI_BRD_0 + (x))
 
 /* Signals which can be routed to an NI PFI pin on an m-series board with
  * INSN_CONFIG_SET_ROUTING.  These numbers are also returned by
@@ -834,10 +799,8 @@ enum ni_pfi_routing {
 	NI_PFI_OUTPUT_CDI_SAMPLE = 29,
 	NI_PFI_OUTPUT_CDO_UPDATE = 30
 };
-static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel)
-{
-	return NI_PFI_OUTPUT_RTSI0 + rtsi_channel;
-}
+
+#define NI_PFI_OUTPUT_RTSI(x)		(NI_PFI_OUTPUT_RTSI0 + (x))
 
 /* Signals which can be routed to output on a NI PFI pin on a 660x board
  with INSN_CONFIG_SET_ROUTING.  The numbers assigned are
@@ -853,14 +816,8 @@ enum ni_660x_pfi_routing {
 /* NI External Trigger lines.  These values are not arbitrary, but are related
  * to the bits required to program the board (offset by 1 for historical
  * reasons). */
-static inline unsigned NI_EXT_PFI(unsigned pfi_channel)
-{
-	return NI_USUAL_PFI_SELECT(pfi_channel) - 1;
-}
-static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel)
-{
-	return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1;
-}
+#define NI_EXT_PFI(x)			(NI_USUAL_PFI_SELECT(x) - 1)
+#define NI_EXT_RTSI(x)			(NI_USUAL_RTSI_SELECT(x) - 1)
 
 /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */
 enum comedi_counter_status_flags {
@@ -884,26 +841,15 @@ enum ni_m_series_cdio_scan_begin_src {
 	NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32,
 	NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33
 };
-static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
-{
-	return NI_USUAL_PFI_SELECT(pfi_channel);
-}
-static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
-{
-	return NI_USUAL_RTSI_SELECT(rtsi_channel);
-}
+
+#define NI_CDIO_SCAN_BEGIN_SRC_PFI(x)	NI_USUAL_PFI_SELECT(x)
+#define NI_CDIO_SCAN_BEGIN_SRC_RTSI(x)	NI_USUAL_RTSI_SELECT(x)
 
 /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI
  * boards.  These scan begin sources can also be bitwise-or'd with CR_INVERT to
  * change polarity. */
-static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
-{
-	return NI_USUAL_PFI_SELECT(pfi_channel);
-}
-static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
-{
-	return NI_USUAL_RTSI_SELECT(rtsi_channel);
-}
+#define NI_AO_SCAN_BEGIN_SRC_PFI(x)	NI_USUAL_PFI_SELECT(x)
+#define NI_AO_SCAN_BEGIN_SRC_RTSI(x)	NI_USUAL_RTSI_SELECT(x)
 
 /* Bits for setting a clock source with
  * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */
@@ -976,4 +922,15 @@ enum amplc_dio_gate_source {
 	AMPLC_DIO_GAT_NPAT_GONE	/* negated "pattern gone away" */
 };
 
+/*
+ * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for
+ * the counter subdevice on the Kolter Electronic PCI-Counter board
+ * (ke_counter driver).
+ */
+enum ke_counter_clock_source {
+	KE_CLK_20MHZ,	/* internal 20MHz (default) */
+	KE_CLK_4MHZ,	/* internal 4MHz (option) */
+	KE_CLK_EXT	/* external clock on pin 21 of D-Sub */
+};
+
 #endif /* _COMEDI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/comedi_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_internal.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/comedi_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/comedi_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,6 +48,7 @@ void comedi_proc_cleanup(void);
 static inline void comedi_proc_init(void)
 {
 }
+
 static inline void comedi_proc_cleanup(void)
 {
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8253.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8253.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8253.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8253.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,7 +34,7 @@ static inline void i8253_cascade_ns_to_t
 					     unsigned int *d1,
 					     unsigned int *d2,
 					     unsigned int *nanosec,
-					     int round_mode)
+					     unsigned int flags)
 {
 	unsigned int divider;
 	unsigned int div1, div2;
@@ -90,8 +90,7 @@ static inline void i8253_cascade_ns_to_t
 		}
 	}
 
-	round_mode &= TRIG_ROUND_MASK;
-	switch (round_mode) {
+	switch (flags & TRIG_ROUND_MASK) {
 	case TRIG_ROUND_NEAREST:
 	default:
 		ns_high = div1_lub * div2_lub * i8253_osc_base;
@@ -118,7 +117,6 @@ static inline void i8253_cascade_ns_to_t
 	/*  masking is done since counter maps zero to 0x10000 */
 	*d1 = div1 & 0xffff;
 	*d2 = div2 & 0xffff;
-	return;
 }
 
 #ifndef CMDTEST
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8255.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8255.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8255.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8255.c	2014-09-28 17:29:07.000000000 -0400
@@ -102,9 +102,8 @@ static int subdev_8255_io(int dir, int p
 	if (dir) {
 		outb(data, iobase + port);
 		return 0;
-	} else {
-		return inb(iobase + port);
 	}
+	return inb(iobase + port);
 }
 
 void subdev_8255_interrupt(struct comedi_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8255_pci.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8255_pci.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/8255_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/8255_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,6 @@ Configuration Options: not applicable, u
 #include "../comedidev.h"
 
 #include "8255.h"
-#include "mite.h"
 
 enum pci_8255_boardid {
 	BOARD_ADLINK_PCI7224,
@@ -168,9 +167,9 @@ static const struct pci_8255_boardinfo p
 	},
 };
 
-struct pci_8255_private {
-	void __iomem *mmio_base;
-};
+/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+#define MITE_IODWBSR	0xc0	 /* IO Device Window Base Size Register */
+#define WENAB		(1 << 7) /* window enable */
 
 static int pci_8255_mite_init(struct pci_dev *pcidev)
 {
@@ -198,9 +197,8 @@ static int pci_8255_mmio(int dir, int po
 	if (dir) {
 		writeb(data, mmio_base + port);
 		return 0;
-	} else {
-		return readb(mmio_base  + port);
 	}
+	return readb(mmio_base  + port);
 }
 
 static int pci_8255_auto_attach(struct comedi_device *dev,
@@ -208,7 +206,6 @@ static int pci_8255_auto_attach(struct c
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct pci_8255_boardinfo *board = NULL;
-	struct pci_8255_private *devpriv;
 	struct comedi_subdevice *s;
 	bool is_mmio;
 	int ret;
@@ -221,10 +218,6 @@ static int pci_8255_auto_attach(struct c
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
-
 	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
@@ -238,8 +231,8 @@ static int pci_8255_auto_attach(struct c
 	is_mmio = (pci_resource_flags(pcidev, board->dio_badr) &
 		   IORESOURCE_MEM) != 0;
 	if (is_mmio) {
-		devpriv->mmio_base = pci_ioremap_bar(pcidev, board->dio_badr);
-		if (!devpriv->mmio_base)
+		dev->mmio = pci_ioremap_bar(pcidev, board->dio_badr);
+		if (!dev->mmio)
 			return -ENOMEM;
 	} else {
 		dev->iobase = pci_resource_start(pcidev, board->dio_badr);
@@ -259,7 +252,7 @@ static int pci_8255_auto_attach(struct c
 
 		s = &dev->subdevices[i];
 		if (is_mmio) {
-			iobase = (unsigned long)(devpriv->mmio_base + (i * 4));
+			iobase = (unsigned long)(dev->mmio + (i * 4));
 			ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase);
 		} else {
 			iobase = dev->iobase + (i * 4);
@@ -274,10 +267,8 @@ static int pci_8255_auto_attach(struct c
 
 static void pci_8255_detach(struct comedi_device *dev)
 {
-	struct pci_8255_private *devpriv = dev->private;
-
-	if (devpriv && devpriv->mmio_base)
-		iounmap(devpriv->mmio_base);
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_035.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_035.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_035.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_035.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,7 @@ static const struct addi_board apci035_b
 		.pc_DriverName		= "apci035",
 		.i_IorangeBase1		= APCI035_ADDRESS_RANGE,
 		.i_PCIEeprom		= 1,
-		.pc_EepromChip		= ADDIDATA_S5920,
+		.pc_EepromChip		= "S5920",
 		.i_NbrAiChannel		= 16,
 		.i_NbrAiChannelDiff	= 8,
 		.i_AiChannelList	= 16,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_1500.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_1500.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_1500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_1500.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,7 +15,7 @@ static const struct addi_board apci1500_
 	{
 		.pc_DriverName		= "apci1500",
 		.i_IorangeBase1		= APCI1500_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.i_PCIEeprom		= 0,
 		.i_NbrDiChannel		= 16,
 		.i_NbrDoChannel		= 16,
 		.i_DoMaxdata		= 0xffff,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_1564.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_1564.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_1564.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_1564.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,17 +1,114 @@
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include "../comedidev.h"
 #include "comedi_fc.h"
+#include "amcc_s5933.h"
+#include "addi_watchdog.h"
 
-#include "addi-data/addi_common.h"
+struct apci1564_private {
+	unsigned int amcc_iobase;	/* base of AMCC I/O registers */
+	unsigned int mode1;		/* riding-edge/high level channels */
+	unsigned int mode2;		/* falling-edge/low level channels */
+	unsigned int ctrl;		/* interrupt mode OR (edge) . AND (level) */
+	unsigned char timer_select_mode;
+	unsigned char mode_select_register;
+	struct task_struct *tsk_current;
+};
 
 #include "addi-data/hwdrv_apci1564.c"
 
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+static int apci1564_reset(struct comedi_device *dev)
 {
-	apci1564_interrupt(irq, d);
-	return IRQ_RETVAL(1);
+	struct apci1564_private *devpriv = dev->private;
+
+	/* Disable the input interrupts and reset status register */
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+	inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+
+	/* Reset the output channels and disable interrupts */
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DO_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
+
+	/* Reset the watchdog registers */
+	addi_watchdog_reset(devpriv->amcc_iobase + APCI1564_WDOG_REG);
+
+	/* Reset the timer registers */
+	outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
+
+	/* Reset the counter registers */
+	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
+	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
+	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
+	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
+
+	return 0;
+}
+
+static irqreturn_t apci1564_interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct apci1564_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	unsigned int status;
+	unsigned int ctrl;
+	unsigned int chan;
+
+	/* check interrupt is from this device */
+	if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
+	     INTCSR_INTR_ASSERTED) == 0)
+		return IRQ_NONE;
+
+	status = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+	if (status & APCI1564_DI_INT_ENABLE) {
+		/* disable the interrupt */
+		outl(status & APCI1564_DI_INT_DISABLE,
+		     devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+
+		s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG)
+			       & 0xffff;
+		comedi_buf_put(s, s->state);
+		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+		comedi_event(dev, s);
+
+		/* enable the interrupt */
+		outl(status, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+	}
+
+	status = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG);
+	if (status & 0x01) {
+		/*  Disable Timer Interrupt */
+		ctrl = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+		outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+
+		/* Send a signal to from kernel to user space */
+		send_sig(SIGIO, devpriv->tsk_current, 0);
+
+		/*  Enable Timer Interrupt */
+		outl(ctrl, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+	}
+
+	for (chan = 0; chan < 4; chan++) {
+		status = inl(dev->iobase + APCI1564_TCW_IRQ_REG(chan));
+		if (status & 0x01) {
+			/*  Disable Counter Interrupt */
+			ctrl = inl(dev->iobase + APCI1564_TCW_CTRL_REG(chan));
+			outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(chan));
+
+			/* Send a signal to from kernel to user space */
+			send_sig(SIGIO, devpriv->tsk_current, 0);
+
+			/*  Enable Counter Interrupt */
+			outl(ctrl, dev->iobase + APCI1564_TCW_CTRL_REG(chan));
+		}
+	}
+
+	return IRQ_HANDLED;
 }
 
 static int apci1564_di_insn_bits(struct comedi_device *dev,
@@ -19,9 +116,9 @@ static int apci1564_di_insn_bits(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 
-	data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_DI_REG);
+	data[1] = inl(devpriv->amcc_iobase + APCI1564_DI_REG);
 
 	return insn->n;
 }
@@ -31,46 +128,214 @@ static int apci1564_do_insn_bits(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 
-	s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DO_REG);
+	s->state = inl(devpriv->amcc_iobase + APCI1564_DO_REG);
 
 	if (comedi_dio_update_state(s, data))
-		outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DO_REG);
+		outl(s->state, devpriv->amcc_iobase + APCI1564_DO_REG);
 
 	data[1] = s->state;
 
 	return insn->n;
 }
 
-static int apci1564_reset(struct comedi_device *dev)
+static int apci1564_diag_insn_bits(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 
-	ui_Type = 0;
+	data[1] = inl(devpriv->amcc_iobase + APCI1564_DO_INT_STATUS_REG) & 3;
 
-	/* Disable the input interrupts and reset status register */
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-	inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG);
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG);
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG);
+	return insn->n;
+}
 
-	/* Reset the output channels and disable interrupts */
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_REG);
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG);
+/*
+ * Change-Of-State (COS) interrupt configuration
+ *
+ * Channels 0 to 15 are interruptible. These channels can be configured
+ * to generate interrupts based on AND/OR logic for the desired channels.
+ *
+ *	OR logic
+ *		- reacts to rising or falling edges
+ *		- interrupt is generated when any enabled channel
+ *		  meet the desired interrupt condition
+ *
+ *	AND logic
+ *		- reacts to changes in level of the selected inputs
+ *		- interrupt is generated when all enabled channels
+ *		  meet the desired interrupt condition
+ *		- after an interrupt, a change in level must occur on
+ *		  the selected inputs to release the IRQ logic
+ *
+ * The COS interrupt must be configured before it can be enabled.
+ *
+ *	data[0] : INSN_CONFIG_DIGITAL_TRIG
+ *	data[1] : trigger number (= 0)
+ *	data[2] : configuration operation:
+ *	          COMEDI_DIGITAL_TRIG_DISABLE = no interrupts
+ *	          COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts
+ *	          COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts
+ *	data[3] : left-shift for data[4] and data[5]
+ *	data[4] : rising-edge/high level channels
+ *	data[5] : falling-edge/low level channels
+ */
+static int apci1564_cos_insn_config(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	struct apci1564_private *devpriv = dev->private;
+	unsigned int shift, oldmask;
 
-	/* Reset the watchdog registers */
-	addi_watchdog_reset(devpriv->i_IobaseAmcc + APCI1564_WDOG_REG);
+	switch (data[0]) {
+	case INSN_CONFIG_DIGITAL_TRIG:
+		if (data[1] != 0)
+			return -EINVAL;
+		shift = data[3];
+		oldmask = (1U << shift) - 1;
+		switch (data[2]) {
+		case COMEDI_DIGITAL_TRIG_DISABLE:
+			devpriv->ctrl = 0;
+			devpriv->mode1 = 0;
+			devpriv->mode2 = 0;
+			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+			inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+			if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
+					      APCI1564_DI_INT_OR)) {
+				/* switching to 'OR' mode */
+				devpriv->ctrl = APCI1564_DI_INT_ENABLE |
+						APCI1564_DI_INT_OR;
+				/* wipe old channels */
+				devpriv->mode1 = 0;
+				devpriv->mode2 = 0;
+			} else {
+				/* preserve unspecified channels */
+				devpriv->mode1 &= oldmask;
+				devpriv->mode2 &= oldmask;
+			}
+			/* configure specified channels */
+			devpriv->mode1 |= data[4] << shift;
+			devpriv->mode2 |= data[5] << shift;
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
+			if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
+					      APCI1564_DI_INT_AND)) {
+				/* switching to 'AND' mode */
+				devpriv->ctrl = APCI1564_DI_INT_ENABLE |
+						APCI1564_DI_INT_AND;
+				/* wipe old channels */
+				devpriv->mode1 = 0;
+				devpriv->mode2 = 0;
+			} else {
+				/* preserve unspecified channels */
+				devpriv->mode1 &= oldmask;
+				devpriv->mode2 &= oldmask;
+			}
+			/* configure specified channels */
+			devpriv->mode1 |= data[4] << shift;
+			devpriv->mode2 |= data[5] << shift;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return insn->n;
+}
 
-	/* Reset the timer registers */
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_RELOAD_REG);
+static int apci1564_cos_insn_bits(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
+{
+	data[1] = s->state;
 
-	/* Reset the counter registers */
-	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
-	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
-	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
-	outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
+	return 0;
+}
+
+static int apci1564_cos_cmdtest(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_cmd *cmd)
+{
+	int err = 0;
+
+	/* Step 1 : check if triggers are trivially valid */
+
+	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+
+	if (err)
+		return 1;
+
+	/* Step 2a : make sure trigger sources are unique */
+	/* Step 2b : and mutually compatible */
+
+	if (err)
+		return 2;
+
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+	if (err)
+		return 3;
+
+	/* step 4: ignored */
+
+	if (err)
+		return 4;
+
+	return 0;
+}
+
+/*
+ * Change-Of-State (COS) 'do_cmd' operation
+ *
+ * Enable the COS interrupt as configured by apci1564_cos_insn_config().
+ */
+static int apci1564_cos_cmd(struct comedi_device *dev,
+			    struct comedi_subdevice *s)
+{
+	struct apci1564_private *devpriv = dev->private;
+
+	if (!devpriv->ctrl) {
+		dev_warn(dev->class_dev,
+			"Interrupts disabled due to mode configuration!\n");
+		return -EINVAL;
+	}
+
+	outl(devpriv->mode1, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+	outl(devpriv->mode2, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+	outl(devpriv->ctrl, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+
+	return 0;
+}
+
+static int apci1564_cos_cancel(struct comedi_device *dev,
+			       struct comedi_subdevice *s)
+{
+	struct apci1564_private *devpriv = dev->private;
+
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+	inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+	outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
 
 	return 0;
 }
@@ -79,12 +344,10 @@ static int apci1564_auto_attach(struct c
 				      unsigned long context_unused)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	struct addi_private *devpriv;
+	struct apci1564_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	dev->board_name = dev->driver->driver_name;
-
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
@@ -94,18 +357,18 @@ static int apci1564_auto_attach(struct c
 		return ret;
 
 	dev->iobase = pci_resource_start(pcidev, 1);
-	devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+	devpriv->amcc_iobase = pci_resource_start(pcidev, 0);
 
 	apci1564_reset(dev);
 
 	if (pcidev->irq > 0) {
-		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+		ret = request_irq(pcidev->irq, apci1564_interrupt, IRQF_SHARED,
 				  dev->board_name, dev);
 		if (ret == 0)
 			dev->irq = pcidev->irq;
 	}
 
-	ret = comedi_alloc_subdevices(dev, 3);
+	ret = comedi_alloc_subdevices(dev, 6);
 	if (ret)
 		return ret;
 
@@ -115,9 +378,7 @@ static int apci1564_auto_attach(struct c
 	s->subdev_flags = SDF_READABLE;
 	s->n_chan = 32;
 	s->maxdata = 1;
-	s->len_chanlist = 32;
 	s->range_table = &range_digital;
-	s->insn_config = apci1564_di_config;
 	s->insn_bits = apci1564_di_insn_bits;
 
 	/*  Allocate and Initialise DO Subdevice Structures */
@@ -125,15 +386,32 @@ static int apci1564_auto_attach(struct c
 	s->type = COMEDI_SUBD_DO;
 	s->subdev_flags = SDF_WRITEABLE;
 	s->n_chan = 32;
-	s->maxdata = 0xffffffff;
-	s->len_chanlist = 32;
+	s->maxdata = 1;
 	s->range_table = &range_digital;
 	s->insn_config = apci1564_do_config;
 	s->insn_bits = apci1564_do_insn_bits;
-	s->insn_read = apci1564_do_read;
 
-	/*  Allocate and Initialise Timer Subdevice Structures */
+	/* Change-Of-State (COS) interrupt subdevice */
 	s = &dev->subdevices[2];
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->type = COMEDI_SUBD_DI;
+		s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+		s->n_chan = 1;
+		s->maxdata = 1;
+		s->range_table = &range_digital;
+		s->len_chanlist = 1;
+		s->insn_config = apci1564_cos_insn_config;
+		s->insn_bits = apci1564_cos_insn_bits;
+		s->do_cmdtest = apci1564_cos_cmdtest;
+		s->do_cmd = apci1564_cos_cmd;
+		s->cancel = apci1564_cos_cancel;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+
+	/*  Allocate and Initialise Timer Subdevice Structures */
+	s = &dev->subdevices[3];
 	s->type = COMEDI_SUBD_TIMER;
 	s->subdev_flags = SDF_WRITEABLE;
 	s->n_chan = 1;
@@ -144,19 +422,30 @@ static int apci1564_auto_attach(struct c
 	s->insn_read = apci1564_timer_read;
 	s->insn_config = apci1564_timer_config;
 
+	/* Initialize the watchdog subdevice */
+	s = &dev->subdevices[4];
+	ret = addi_watchdog_init(s, devpriv->amcc_iobase + APCI1564_WDOG_REG);
+	if (ret)
+		return ret;
+
+	/* Initialize the diagnostic status subdevice */
+	s = &dev->subdevices[5];
+	s->type = COMEDI_SUBD_DI;
+	s->subdev_flags = SDF_READABLE;
+	s->n_chan = 2;
+	s->maxdata = 1;
+	s->range_table = &range_digital;
+	s->insn_bits = apci1564_diag_insn_bits;
+
 	return 0;
 }
 
 static void apci1564_detach(struct comedi_device *dev)
 {
-	struct addi_private *devpriv = dev->private;
-
-	if (devpriv) {
-		if (dev->iobase)
-			apci1564_reset(dev);
-		if (dev->irq)
-			free_irq(dev->irq, dev);
-	}
+	if (dev->iobase)
+		apci1564_reset(dev);
+	if (dev->irq)
+		free_irq(dev->irq, dev);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3120.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3120.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3120.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3120.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,7 +88,7 @@ static int apci3120_auto_attach(struct c
 			dev->irq = pcidev->irq;
 	}
 
-	devpriv->us_UseDma = ADDI_ENABLE;
+	devpriv->us_UseDma = 1;
 
 	/* Allocate DMA buffers */
 	devpriv->b_DmaDoubleBuffer = 0;
@@ -109,7 +109,7 @@ static int apci3120_auto_attach(struct c
 		}
 	}
 	if (!devpriv->ul_DmaBufferVirtual[0])
-		devpriv->us_UseDma = ADDI_DISABLE;
+		devpriv->us_UseDma = 0;
 
 	if (devpriv->ul_DmaBufferVirtual[1])
 		devpriv->b_DmaDoubleBuffer = 1;
@@ -125,13 +125,10 @@ static int apci3120_auto_attach(struct c
 	s->subdev_flags =
 		SDF_READABLE | SDF_COMMON | SDF_GROUND
 		| SDF_DIFF;
-	if (this_board->i_NbrAiChannel) {
+	if (this_board->i_NbrAiChannel)
 		s->n_chan = this_board->i_NbrAiChannel;
-		devpriv->b_SingelDiff = 0;
-	} else {
+	else
 		s->n_chan = this_board->i_NbrAiChannelDiff;
-		devpriv->b_SingelDiff = 1;
-	}
 	s->maxdata = this_board->i_AiMaxdata;
 	s->len_chanlist = this_board->i_AiChannelList;
 	s->range_table = &range_apci3120_ai;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3200.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3200.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3200.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,8 +32,8 @@ static const struct addi_board apci3200_
 	[BOARD_APCI3200] = {
 		.pc_DriverName		= "apci3200",
 		.i_IorangeBase1		= 256,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
+		.i_PCIEeprom		= 1,
+		.pc_EepromChip		= "S5920",
 		.i_NbrAiChannel		= 16,
 		.i_NbrAiChannelDiff	= 8,
 		.i_AiChannelList	= 16,
@@ -58,8 +58,8 @@ static const struct addi_board apci3200_
 	[BOARD_APCI3300] = {
 		.pc_DriverName		= "apci3300",
 		.i_IorangeBase1		= 256,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
+		.i_PCIEeprom		= 1,
+		.pc_EepromChip		= "S5920",
 		.i_NbrAiChannelDiff	= 8,
 		.i_AiChannelList	= 8,
 		.i_AiMaxdata		= 0x3ffff,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3501.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3501.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3501.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3501.c	2014-09-28 17:29:07.000000000 -0400
@@ -274,7 +274,7 @@ static irqreturn_t apci3501_interrupt(in
 
 	ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
 	if ((!ui_Timer_AOWatchdog)) {
-		comedi_error(dev, "IRQ from unknown source");
+		dev_err(dev->class_dev, "IRQ from unknown source\n");
 		return IRQ_NONE;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3xxx.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3xxx.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi_apci_3xxx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi_apci_3xxx.c	2014-09-28 17:29:07.000000000 -0400
@@ -353,7 +353,6 @@ static const struct apci3xxx_boardinfo a
 };
 
 struct apci3xxx_private {
-	void __iomem *mmio;
 	unsigned int ai_timer;
 	unsigned char ai_time_base;
 };
@@ -361,18 +360,17 @@ struct apci3xxx_private {
 static irqreturn_t apci3xxx_irq_handler(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct apci3xxx_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned int status;
 	unsigned int val;
 
 	/* Test if interrupt occur */
-	status = readl(devpriv->mmio + 16);
+	status = readl(dev->mmio + 16);
 	if ((status & 0x2) == 0x2) {
 		/* Reset the interrupt */
-		writel(status, devpriv->mmio + 16);
+		writel(status, dev->mmio + 16);
 
-		val = readl(devpriv->mmio + 28);
+		val = readl(dev->mmio + 28);
 		comedi_buf_put(s, val);
 
 		s->async->events |= COMEDI_CB_EOA;
@@ -385,18 +383,14 @@ static irqreturn_t apci3xxx_irq_handler(
 
 static int apci3xxx_ai_started(struct comedi_device *dev)
 {
-	struct apci3xxx_private *devpriv = dev->private;
-
-	if ((readl(devpriv->mmio + 8) & 0x80000) == 0x80000)
+	if ((readl(dev->mmio + 8) & 0x80000) == 0x80000)
 		return 1;
-	else
-		return 0;
 
+	return 0;
 }
 
 static int apci3xxx_ai_setup(struct comedi_device *dev, unsigned int chanspec)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(chanspec);
 	unsigned int range = CR_RANGE(chanspec);
 	unsigned int aref = CR_AREF(chanspec);
@@ -407,29 +401,29 @@ static int apci3xxx_ai_setup(struct come
 		return -EBUSY;
 
 	/* Clear the FIFO */
-	writel(0x10000, devpriv->mmio + 12);
+	writel(0x10000, dev->mmio + 12);
 
 	/* Get and save the delay mode */
-	delay_mode = readl(devpriv->mmio + 4);
+	delay_mode = readl(dev->mmio + 4);
 	delay_mode &= 0xfffffef0;
 
 	/* Channel configuration selection */
-	writel(delay_mode, devpriv->mmio + 4);
+	writel(delay_mode, dev->mmio + 4);
 
 	/* Make the configuration */
 	val = (range & 3) | ((range >> 2) << 6) |
 	      ((aref == AREF_DIFF) << 7);
-	writel(val, devpriv->mmio + 0);
+	writel(val, dev->mmio + 0);
 
 	/* Channel selection */
-	writel(delay_mode | 0x100, devpriv->mmio + 4);
-	writel(chan, devpriv->mmio + 0);
+	writel(delay_mode | 0x100, dev->mmio + 4);
+	writel(chan, dev->mmio + 0);
 
 	/* Restore delay mode */
-	writel(delay_mode, devpriv->mmio + 4);
+	writel(delay_mode, dev->mmio + 4);
 
 	/* Set the number of sequence to 1 */
-	writel(1, devpriv->mmio + 48);
+	writel(1, dev->mmio + 48);
 
 	return 0;
 }
@@ -439,10 +433,9 @@ static int apci3xxx_ai_eoc(struct comedi
 			   struct comedi_insn *insn,
 			   unsigned long context)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readl(devpriv->mmio + 20);
+	status = readl(dev->mmio + 20);
 	if (status & 0x1)
 		return 0;
 	return -EBUSY;
@@ -453,7 +446,6 @@ static int apci3xxx_ai_insn_read(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	int ret;
 	int i;
 
@@ -463,7 +455,7 @@ static int apci3xxx_ai_insn_read(struct
 
 	for (i = 0; i < insn->n; i++) {
 		/* Start the conversion */
-		writel(0x80000, devpriv->mmio + 8);
+		writel(0x80000, dev->mmio + 8);
 
 		/* Wait the EOS */
 		ret = comedi_timeout(dev, s, insn, apci3xxx_ai_eoc, 0);
@@ -471,14 +463,14 @@ static int apci3xxx_ai_insn_read(struct
 			return ret;
 
 		/* Read the analog value */
-		data[i] = readl(devpriv->mmio + 28);
+		data[i] = readl(dev->mmio + 28);
 	}
 
 	return insn->n;
 }
 
 static int apci3xxx_ai_ns_to_timer(struct comedi_device *dev,
-				   unsigned int *ns, int round_mode)
+				   unsigned int *ns, unsigned int flags)
 {
 	const struct apci3xxx_boardinfo *board = comedi_board(dev);
 	struct apci3xxx_private *devpriv = dev->private;
@@ -504,7 +496,7 @@ static int apci3xxx_ai_ns_to_timer(struc
 			break;
 		}
 
-		switch (round_mode) {
+		switch (flags & TRIG_ROUND_MASK) {
 		case TRIG_ROUND_NEAREST:
 		default:
 			timer = (*ns + base / 2) / base;
@@ -574,7 +566,7 @@ static int apci3xxx_ai_cmdtest(struct co
 	/* step 4: fix up any arguments */
 
 	arg = cmd->convert_arg;
-	err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags & TRIG_ROUND_MASK);
+	err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags);
 	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 	if (err)
@@ -595,13 +587,13 @@ static int apci3xxx_ai_cmd(struct comedi
 		return ret;
 
 	/* Set the convert timing unit */
-	writel(devpriv->ai_time_base, devpriv->mmio + 36);
+	writel(devpriv->ai_time_base, dev->mmio + 36);
 
 	/* Set the convert timing */
-	writel(devpriv->ai_timer, devpriv->mmio + 32);
+	writel(devpriv->ai_timer, dev->mmio + 32);
 
 	/* Start the conversion */
-	writel(0x180000, devpriv->mmio + 8);
+	writel(0x180000, dev->mmio + 8);
 
 	return 0;
 }
@@ -617,10 +609,9 @@ static int apci3xxx_ao_eoc(struct comedi
 			   struct comedi_insn *insn,
 			   unsigned long context)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readl(devpriv->mmio + 96);
+	status = readl(dev->mmio + 96);
 	if (status & 0x100)
 		return 0;
 	return -EBUSY;
@@ -631,7 +622,6 @@ static int apci3xxx_ao_insn_write(struct
 				  struct comedi_insn *insn,
 				  unsigned int *data)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int range = CR_RANGE(insn->chanspec);
 	int ret;
@@ -639,10 +629,10 @@ static int apci3xxx_ao_insn_write(struct
 
 	for (i = 0; i < insn->n; i++) {
 		/* Set the range selection */
-		writel(range, devpriv->mmio + 96);
+		writel(range, dev->mmio + 96);
 
 		/* Write the analog value to the selected channel */
-		writel((data[i] << 8) | chan, devpriv->mmio + 100);
+		writel((data[i] << 8) | chan, dev->mmio + 100);
 
 		/* Wait the end of transfer */
 		ret = comedi_timeout(dev, s, insn, apci3xxx_ao_eoc, 0);
@@ -696,10 +686,9 @@ static int apci3xxx_dio_insn_config(stru
 		/* ignore all other instructions for ports 0 and 1 */
 		if (chan < 16)
 			return -EINVAL;
-		else
-			/* changing any channel in port 2 */
-			/* changes the entire port        */
-			mask = 0xff0000;
+
+		/* changing any channel in port 2 changes the entire port */
+		mask = 0xff0000;
 	}
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
@@ -742,7 +731,6 @@ static int apci3xxx_dio_insn_bits(struct
 
 static int apci3xxx_reset(struct comedi_device *dev)
 {
-	struct apci3xxx_private *devpriv = dev->private;
 	unsigned int val;
 	int i;
 
@@ -750,18 +738,18 @@ static int apci3xxx_reset(struct comedi_
 	disable_irq(dev->irq);
 
 	/* Clear the start command */
-	writel(0, devpriv->mmio + 8);
+	writel(0, dev->mmio + 8);
 
 	/* Reset the interrupt flags */
-	val = readl(devpriv->mmio + 16);
-	writel(val, devpriv->mmio + 16);
+	val = readl(dev->mmio + 16);
+	writel(val, dev->mmio + 16);
 
 	/* clear the EOS */
-	readl(devpriv->mmio + 20);
+	readl(dev->mmio + 20);
 
 	/* Clear the FIFO */
 	for (i = 0; i < 16; i++)
-		val = readl(devpriv->mmio + 28);
+		val = readl(dev->mmio + 28);
 
 	/* Enable the interrupt */
 	enable_irq(dev->irq);
@@ -796,7 +784,7 @@ static int apci3xxx_auto_attach(struct c
 		return ret;
 
 	dev->iobase = pci_resource_start(pcidev, 2);
-	devpriv->mmio = pci_ioremap_bar(pcidev, 3);
+	dev->mmio = pci_ioremap_bar(pcidev, 3);
 
 	if (pcidev->irq > 0) {
 		ret = request_irq(pcidev->irq, apci3xxx_irq_handler,
@@ -920,8 +908,8 @@ static void apci3xxx_detach(struct comed
 			apci3xxx_reset(dev);
 		if (dev->irq)
 			free_irq(dev->irq, dev);
-		if (devpriv->mmio)
-			iounmap(devpriv->mmio);
+		if (dev->mmio)
+			iounmap(dev->mmio);
 	}
 	comedi_pci_disable(dev);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -157,14 +157,10 @@ static int addi_auto_attach(struct comed
 		s->subdev_flags =
 			SDF_READABLE | SDF_COMMON | SDF_GROUND
 			| SDF_DIFF;
-		if (devpriv->s_EeParameters.i_NbrAiChannel) {
-			s->n_chan =
-				devpriv->s_EeParameters.i_NbrAiChannel;
-			devpriv->b_SingelDiff = 0;
-		} else {
+		if (devpriv->s_EeParameters.i_NbrAiChannel)
+			s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel;
+		else
 			s->n_chan = this_board->i_NbrAiChannelDiff;
-			devpriv->b_SingelDiff = 1;
-		}
 		s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
 		s->len_chanlist = this_board->i_AiChannelList;
 		s->range_table = this_board->pr_AiRangelist;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/addi_common.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,25 +18,6 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 
-#define LOWORD(W)	(unsigned short)((W) & 0xFFFF)
-#define HIWORD(W)	(unsigned short)(((W) >> 16) & 0xFFFF)
-
-#define ADDI_ENABLE		1
-#define ADDI_DISABLE		0
-#define APCI1710_SAVE_INTERRUPT	1
-
-#define ADDIDATA_EEPROM		1
-#define ADDIDATA_NO_EEPROM	0
-#define ADDIDATA_93C76		"93C76"
-#define ADDIDATA_S5920		"S5920"
-
-/* ADDIDATA Enable Disable */
-#define ADDIDATA_ENABLE		1
-#define ADDIDATA_DISABLE	0
-
-/* Structures */
-
-/* structure for the boardtype */
 struct addi_board {
 	const char *pc_DriverName;	/*  driver name */
 	int i_IorangeBase1;
@@ -141,7 +122,6 @@ struct addi_private {
 	unsigned char b_InterruptMode;	/*  eoc eos or dma */
 	unsigned char b_EocEosInterrupt;	/*  Enable disable eoc eos interrupt */
 	unsigned int ui_EocEosConversionTime;
-	unsigned char b_SingelDiff;
 	unsigned char b_ExttrigEnable;	/* To enable or disable external trigger */
 
 	/* Pointer to the current process */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c	2014-09-28 17:29:07.000000000 -0400
@@ -177,8 +177,7 @@ static int apci035_timer_config(struct c
 
 	/* Disable the hardware trigger */
 	ui_Command = ui_Command & 0xFFFFF89FUL;
-	if (data[4] == ADDIDATA_ENABLE) {
-
+	if (data[4] == 1) {
 		/* Set the hardware trigger level */
 		ui_Command = ui_Command | (data[5] << 5);
 	}
@@ -188,8 +187,7 @@ static int apci035_timer_config(struct c
 
 	/* Disable the hardware gate */
 	ui_Command = ui_Command & 0xFFFFF87FUL;
-	if (data[6] == ADDIDATA_ENABLE) {
-
+	if (data[6] == 1) {
 		/* Set the hardware gate level */
 		ui_Command = ui_Command | (data[7] << 7);
 	}
@@ -203,8 +201,7 @@ static int apci035_timer_config(struct c
 	/* Set the hardware output level */
 	ui_Command = ui_Command | (data[8] << 2);
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	if (data[9] == ADDIDATA_ENABLE) {
-
+	if (data[9] == 1) {
 		/* Set the reload value */
 		outl(data[11],
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c	2014-09-28 17:29:07.000000000 -0400
@@ -872,7 +872,8 @@ static int apci1500_do_write(struct come
 					break;
 
 				default:
-					comedi_error(dev, " chan spec wrong");
+					dev_err(dev->class_dev,
+						"chan spec wrong\n");
 					return -EINVAL;	/*  "sorry channel spec wrong " */
 
 				}	/* switch(ui_NoOfChannels) */
@@ -950,8 +951,8 @@ static int apci1500_do_write(struct come
 						break;
 
 					default:
-						comedi_error(dev,
-							" chan spec wrong");
+						dev_err(dev->class_dev,
+							"chan spec wrong\n");
 						return -EINVAL;	/*  "sorry channel spec wrong " */
 
 					}	/* switch(ui_NoOfChannels) */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,17 +21,15 @@
  *
  */
 
-#include "../addi_watchdog.h"
-
 #define APCI1564_ADDRESS_RANGE				128
 
 /* Digital Input IRQ Function Selection */
-#define ADDIDATA_OR					0
-#define ADDIDATA_AND					1
+#define APCI1564_DI_INT_OR				(0 << 1)
+#define APCI1564_DI_INT_AND				(1 << 1)
 
 /* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE		0x4
-#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE		0xfffffffb
+#define APCI1564_DI_INT_ENABLE				0x4
+#define APCI1564_DI_INT_DISABLE				0xfffffffb
 
 /* Digital Output Interrupt Enable Disable. */
 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE	0x1
@@ -49,7 +47,7 @@
 #define APCI1564_COUNTER4				3
 
 /*
- * devpriv->i_IobaseAmcc Register Map
+ * devpriv->amcc_iobase Register Map
  */
 #define APCI1564_DI_REG					0x04
 #define APCI1564_DI_INT_MODE1_REG			0x08
@@ -89,46 +87,6 @@
 #define APCI1564_TCW_WARN_TIMEVAL_REG(x)		(0x18 + ((x) * 0x20))
 #define APCI1564_TCW_WARN_TIMEBASE_REG(x)		(0x1c + ((x) * 0x20))
 
-/* Global variables */
-static unsigned int ui_InterruptStatus_1564;
-static unsigned int ui_InterruptData, ui_Type;
-
-/*
- * Configures the digital input Subdevice
- *
- * data[0] 1 = Enable interrupt, 0 = Disable interrupt
- * data[1] 0 = ADDIDATA Interrupt OR LOGIC, 1 = ADDIDATA Interrupt AND LOGIC
- * data[2] Interrupt mask for the mode 1
- * data[3] Interrupt mask for the mode 2
- */
-static int apci1564_di_config(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn,
-			      unsigned int *data)
-{
-	struct addi_private *devpriv = dev->private;
-
-	devpriv->tsk_Current = current;
-
-	/* Set the digital input logic */
-	if (data[0] == ADDIDATA_ENABLE) {
-		data[2] = data[2] << 4;
-		data[3] = data[3] << 4;
-		outl(data[2], devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG);
-		outl(data[3], devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG);
-		if (data[1] == ADDIDATA_OR)
-			outl(0x4, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-		else
-			outl(0x6, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-	} else {
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG);
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG);
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-	}
-
-	return insn->n;
-}
-
 /*
  * Configures The Digital Output Subdevice.
  *
@@ -140,33 +98,26 @@ static int apci1564_do_config(struct com
 			      struct comedi_insn *insn,
 			      unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 	unsigned int ul_Command = 0;
 
 	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
+		dev_err(dev->class_dev, "Data should be 1 or 0\n");
 		return -EINVAL;
 	}
 
-	if (data[0])
-		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
-	else
-		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
-
-	if (data[1] == ADDIDATA_ENABLE)
+	if (data[1] == 1)
 		ul_Command = ul_Command | 0x1;
 	else
 		ul_Command = ul_Command & 0xFFFFFFFE;
 
-	if (data[2] == ADDIDATA_ENABLE)
+	if (data[2] == 1)
 		ul_Command = ul_Command | 0x2;
 	else
 		ul_Command = ul_Command & 0xFFFFFFFD;
 
-	outl(ul_Command, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG);
-	ui_InterruptData = inl(devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG);
-	devpriv->tsk_Current = current;
+	outl(ul_Command, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
+	devpriv->tsk_current = current;
 	return insn->n;
 }
 
@@ -186,31 +137,31 @@ static int apci1564_timer_config(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
 
-	devpriv->tsk_Current = current;
+	devpriv->tsk_current = current;
 	if (data[0] == ADDIDATA_WATCHDOG) {
-		devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+		devpriv->timer_select_mode = ADDIDATA_WATCHDOG;
 
 		/* Disable the watchdog */
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG);
+		outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG);
 		/* Loading the Reload value */
-		outl(data[3], devpriv->i_IobaseAmcc + APCI1564_WDOG_RELOAD_REG);
+		outl(data[3], devpriv->amcc_iobase + APCI1564_WDOG_RELOAD_REG);
 	} else if (data[0] == ADDIDATA_TIMER) {
 		/* First Stop The Timer */
-		ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+		ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
 		/* Stop The Timer */
-		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+		outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 
-		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+		devpriv->timer_select_mode = ADDIDATA_TIMER;
 		if (data[1] == 1) {
 			/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
-			outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG);
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_IRQ_REG);
+			outl(0x02, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_DO_IRQ_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_IRQ_REG);
 			outl(0x0,
 			     dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1));
 			outl(0x0,
@@ -221,22 +172,22 @@ static int apci1564_timer_config(struct
 			     dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4));
 		} else {
 			/* disable Timer interrupt */
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 		}
 
 		/*  Loading Timebase */
-		outl(data[2], devpriv->i_IobaseAmcc + APCI1564_TIMER_TIMEBASE_REG);
+		outl(data[2], devpriv->amcc_iobase + APCI1564_TIMER_TIMEBASE_REG);
 
 		/* Loading the Reload value */
-		outl(data[3], devpriv->i_IobaseAmcc + APCI1564_TIMER_RELOAD_REG);
+		outl(data[3], devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
 
-		ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+		ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 		ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
 		/* mode 2 */
-		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+		outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 	} else if (data[0] == ADDIDATA_COUNTER) {
-		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
-		devpriv->b_ModeSelectRegister = data[5];
+		devpriv->timer_select_mode = ADDIDATA_COUNTER;
+		devpriv->mode_select_register = data[5];
 
 		/* First Stop The Counter */
 		ul_Command1 = inl(dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1));
@@ -285,45 +236,45 @@ static int apci1564_timer_write(struct c
 				struct comedi_insn *insn,
 				unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
 
-	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+	if (devpriv->timer_select_mode == ADDIDATA_WATCHDOG) {
 		switch (data[1]) {
 		case 0:	/* stop the watchdog */
 			/* disable the watchdog */
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG);
+			outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG);
 			break;
 		case 1:	/* start the watchdog */
-			outl(0x0001, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG);
+			outl(0x0001, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG);
 			break;
 		case 2:	/* Software trigger */
-			outl(0x0201, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG);
+			outl(0x0201, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG);
 			break;
 		default:
 			dev_err(dev->class_dev, "Specified functionality does not exist.\n");
 			return -EINVAL;
 		}
 	}
-	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+	if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
 		if (data[1] == 1) {
-			ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+			ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
 
 			/* Enable the Timer */
-			outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+			outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 		} else if (data[1] == 0) {
 			/* Stop The Timer */
 
-			ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+			ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 			ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
-			outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
+			outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
 		}
 	}
-	if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+	if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
 		ul_Command1 =
 			inl(dev->iobase +
-			    APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1));
+			    APCI1564_TCW_CTRL_REG(devpriv->mode_select_register - 1));
 		if (data[1] == 1) {
 			/* Start the Counter subdevice */
 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
@@ -336,7 +287,7 @@ static int apci1564_timer_write(struct c
 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
 		}
 		outl(ul_Command1, dev->iobase +
-		     APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1));
+		     APCI1564_TCW_CTRL_REG(devpriv->mode_select_register - 1));
 	}
 	return insn->n;
 }
@@ -349,27 +300,27 @@ static int apci1564_timer_read(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct addi_private *devpriv = dev->private;
+	struct apci1564_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
 
-	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+	if (devpriv->timer_select_mode == ADDIDATA_WATCHDOG) {
 		/*  Stores the status of the Watchdog */
-		data[0] = inl(devpriv->i_IobaseAmcc + APCI1564_WDOG_STATUS_REG) & 0x1;
-		data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_WDOG_REG);
-	} else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+		data[0] = inl(devpriv->amcc_iobase + APCI1564_WDOG_STATUS_REG) & 0x1;
+		data[1] = inl(devpriv->amcc_iobase + APCI1564_WDOG_REG);
+	} else if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
 		/*  Stores the status of the Timer */
-		data[0] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_STATUS_REG) & 0x1;
+		data[0] = inl(devpriv->amcc_iobase + APCI1564_TIMER_STATUS_REG) & 0x1;
 
 		/*  Stores the Actual value of the Timer */
-		data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_REG);
-	} else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+		data[1] = inl(devpriv->amcc_iobase + APCI1564_TIMER_REG);
+	} else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
 		/*  Read the Counter Actual Value. */
 		data[0] =
 			inl(dev->iobase +
-			    APCI1564_TCW_REG(devpriv->b_ModeSelectRegister - 1));
+			    APCI1564_TCW_REG(devpriv->mode_select_register - 1));
 		ul_Command1 =
 			inl(dev->iobase +
-			    APCI1564_TCW_STATUS_REG(devpriv->b_ModeSelectRegister - 1));
+			    APCI1564_TCW_STATUS_REG(devpriv->mode_select_register - 1));
 
 		/* Get the software trigger status */
 		data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
@@ -382,170 +333,10 @@ static int apci1564_timer_read(struct co
 
 		/* Get the overflow status */
 		data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
-	} else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
-		&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
-		&& (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
+	} else if ((devpriv->timer_select_mode != ADDIDATA_TIMER)
+		&& (devpriv->timer_select_mode != ADDIDATA_WATCHDOG)
+		&& (devpriv->timer_select_mode != ADDIDATA_COUNTER)) {
 		dev_err(dev->class_dev, "Invalid Subdevice!\n");
 	}
 	return insn->n;
 }
-
-/*
- * Reads the interrupt status register
- */
-static int apci1564_do_read(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn,
-			    unsigned int *data)
-{
-	*data = ui_Type;
-	return insn->n;
-}
-
-/*
- * Interrupt handler for the interruptible digital inputs
- */
-static void apci1564_interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct addi_private *devpriv = dev->private;
-	unsigned int ui_DO, ui_DI;
-	unsigned int ui_Timer;
-	unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
-	unsigned int ul_Command2 = 0;
-
-	ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG) & 0x01;
-	ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG) & 0x01;
-	ui_Timer = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_IRQ_REG) & 0x01;
-	ui_C1 =
-		inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1;
-	ui_C2 =
-		inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1;
-	ui_C3 =
-		inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1;
-	ui_C4 =
-		inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1;
-	if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
-		&& ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
-		dev_err(dev->class_dev, "Interrupt from unknown source.\n");
-	}
-
-	if (ui_DI == 1) {
-		ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-		ui_InterruptStatus_1564 =
-			inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG);
-		ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
-		/* send signal to the sample */
-		send_sig(SIGIO, devpriv->tsk_Current, 0);
-		/* enable the interrupt */
-		outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG);
-		return;
-	}
-
-	if (ui_DO == 1) {
-		/* Check for Digital Output interrupt Type */
-		/* 1: VCC interrupt			   */
-		/* 2: CC interrupt			   */
-		ui_Type = inl(devpriv->i_IobaseAmcc + APCI1564_DO_INT_STATUS_REG) & 0x3;
-		/* Disable the  Interrupt */
-		outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG);
-
-		/* Sends signal to user space */
-		send_sig(SIGIO, devpriv->tsk_Current, 0);
-	}
-
-	if (ui_Timer == 1) {
-		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
-		if (devpriv->b_TimerSelectMode) {
-
-			/*  Disable Timer Interrupt */
-			ul_Command2 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
-
-			/* Send a signal to from kernel to user space */
-			send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			/*  Enable Timer Interrupt */
-
-			outl(ul_Command2, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG);
-		}
-	}
-
-	if (ui_C1 == 1) {
-		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
-		if (devpriv->b_TimerSelectMode) {
-
-			/*  Disable Counter Interrupt */
-			ul_Command2 =
-				inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
-			outl(0x0,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
-
-			/* Send a signal to from kernel to user space */
-			send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			/*  Enable Counter Interrupt */
-			outl(ul_Command2,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
-		}
-	}
-
-	if (ui_C2 == 1) {
-		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
-		if (devpriv->b_TimerSelectMode) {
-
-			/*  Disable Counter Interrupt */
-			ul_Command2 =
-				inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
-			outl(0x0,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
-
-			/* Send a signal to from kernel to user space */
-			send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			/*  Enable Counter Interrupt */
-			outl(ul_Command2,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
-		}
-	}
-
-	if (ui_C3 == 1) {
-		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
-		if (devpriv->b_TimerSelectMode) {
-
-			/*  Disable Counter Interrupt */
-			ul_Command2 =
-				inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
-			outl(0x0,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
-
-			/* Send a signal to from kernel to user space */
-			send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			/*  Enable Counter Interrupt */
-			outl(ul_Command2,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
-		}
-	}
-
-	if (ui_C4 == 1) {
-		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
-		if (devpriv->b_TimerSelectMode) {
-
-			/*  Disable Counter Interrupt */
-			ul_Command2 =
-				inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
-			outl(0x0,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
-
-			/* Send a signal to from kernel to user space */
-			send_sig(SIGIO, devpriv->tsk_Current, 0);
-
-			/*  Enable Counter Interrupt */
-			outl(ul_Command2,
-			     dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
-		}
-	}
-	return;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c	2014-09-28 17:29:07.000000000 -0400
@@ -270,7 +270,7 @@ static int apci3120_ai_insn_config(struc
 
 			if (CR_CHAN(data[4 + i]) >=
 				this_board->i_NbrAiChannel) {
-				printk("bad channel list\n");
+				dev_err(dev->class_dev, "bad channel list\n");
 				return -2;
 			}
 		}
@@ -318,7 +318,8 @@ static int apci3120_setup_chan_list(stru
 	/* correct channel and range number check itself comedi/range.c */
 	if (n_chan < 1) {
 		if (!check)
-			comedi_error(dev, "range/channel list is empty!");
+			dev_err(dev->class_dev,
+				"range/channel list is empty!\n");
 		return 0;
 	}
 	/*  All is ok, so we can setup channel/range list */
@@ -344,11 +345,6 @@ static int apci3120_setup_chan_list(stru
 		us_TmpValue |= ((gain & 0x03) << 4);	/* <<4 for G0 and G1 bit in RAM */
 		us_TmpValue |= i << 8;	/* To select the RAM LOCATION.... */
 		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
-
-		printk("\n Gain = %i",
-			(((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
-		printk("\n Channel = %i", CR_CHAN(chanlist[i]));
-		printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
 	}
 	return 1;		/*  we can serve this with scan logic */
 }
@@ -369,10 +365,9 @@ static int apci3120_ai_insn_read(struct
 	unsigned char b_Tmp;
 
 	/*  fix conversion time to 10 us */
-	if (!devpriv->ui_EocEosConversionTime) {
-		printk("No timer0 Value using 10 us\n");
+	if (!devpriv->ui_EocEosConversionTime)
 		us_ConvertTiming = 10;
-	} else
+	else
 		us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000);	/*  nano to useconds */
 
 	/*  this_board->ai_read(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
@@ -593,7 +588,7 @@ static int apci3120_ai_insn_read(struct
 			break;
 
 		default:
-			printk("inputs wrong\n");
+			dev_err(dev->class_dev, "inputs wrong\n");
 
 		}
 		devpriv->ui_EocEosConversionTime = 0;	/*  re initializing the variable; */
@@ -1051,7 +1046,7 @@ static int apci3120_cyclic_ai(int mode,
 					b_DigitalOutputRegister) & 0xF0) |
 				APCI3120_SELECT_TIMER_2_LOW_WORD;
 			outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
-			outw(LOWORD(ui_TimerValue2),
+			outw(ui_TimerValue2 & 0xffff,
 				dev->iobase + APCI3120_TIMER_VALUE);
 
 			/* Writing HIGH unsigned short */
@@ -1059,7 +1054,7 @@ static int apci3120_cyclic_ai(int mode,
 					b_DigitalOutputRegister) & 0xF0) |
 				APCI3120_SELECT_TIMER_2_HIGH_WORD;
 			outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
-			outw(HIWORD(ui_TimerValue2),
+			outw((ui_TimerValue2 >> 16) & 0xffff,
 				dev->iobase + APCI3120_TIMER_VALUE);
 
 			/* (2) Reset FC_TIMER BIT  Clearing timer status register */
@@ -1373,10 +1368,10 @@ static void apci3120_interrupt_dma(int i
 
 	if (samplesinbuf <
 		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
-		comedi_error(dev, "Interrupted DMA transfer!");
+		dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
 	}
 	if (samplesinbuf & 1) {
-		comedi_error(dev, "Odd count of bytes in DMA ring!");
+		dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
 		apci3120_cancel(dev, s);
 		return;
 	}
@@ -1548,7 +1543,7 @@ static void apci3120_interrupt(int irq,
 	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	/*  get AMCC int register */
 
 	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
-		comedi_error(dev, "IRQ from unknown source");
+		dev_err(dev->class_dev, "IRQ from unknown source\n");
 		return;
 	}
 
@@ -1565,9 +1560,9 @@ static void apci3120_interrupt(int irq,
 	inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
 
 	if (int_amcc & MASTER_ABORT_INT)
-		comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
+		dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
 	if (int_amcc & TARGET_ABORT_INT)
-		comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
+		dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
 
 	/*  Ckeck if EOC interrupt */
 	if (((int_daq & 0x8) == 0)
@@ -1740,7 +1735,7 @@ static int apci3120_config_insn_timer(st
 	unsigned char b_Tmp;
 
 	if (!data[1])
-		comedi_error(dev, "config:No timer constant !");
+		dev_err(dev->class_dev, "No timer constant!\n");
 
 	devpriv->b_Timer2Interrupt = (unsigned char) data[2];	/*  save info whether to enable or disable interrupt */
 
@@ -1805,7 +1800,7 @@ static int apci3120_config_insn_timer(st
 				b_DigitalOutputRegister) & 0xF0) |
 			APCI3120_SELECT_TIMER_2_LOW_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-		outw(LOWORD(ui_Timervalue2),
+		outw(ui_Timervalue2 & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 
 		/* Writing HIGH unsigned short */
@@ -1813,7 +1808,7 @@ static int apci3120_config_insn_timer(st
 				b_DigitalOutputRegister) & 0xF0) |
 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-		outw(HIWORD(ui_Timervalue2),
+		outw((ui_Timervalue2 >> 16) & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 		/*  timer2 in Timer mode enabled */
 		devpriv->b_Timer2Mode = APCI3120_TIMER;
@@ -1841,7 +1836,7 @@ static int apci3120_config_insn_timer(st
 				b_DigitalOutputRegister) & 0xF0) |
 			APCI3120_SELECT_TIMER_2_LOW_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-		outw(LOWORD(ui_Timervalue2),
+		outw(ui_Timervalue2 & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 
 		/* Writing HIGH unsigned short */
@@ -1850,7 +1845,7 @@ static int apci3120_config_insn_timer(st
 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
 
-		outw(HIWORD(ui_Timervalue2),
+		outw((ui_Timervalue2 >> 16) & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 		/* watchdog enabled */
 		devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
@@ -1886,14 +1881,14 @@ static int apci3120_write_insn_timer(str
 
 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
 		&& (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
-		comedi_error(dev, "\nwrite:timer2  not configured ");
+		dev_err(dev->class_dev, "timer2 not configured\n");
 		return -EINVAL;
 	}
 
 	if (data[0] == 2) {	/*  write new value */
 		if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
-			comedi_error(dev,
-				"write :timer2  not configured  in TIMER MODE");
+			dev_err(dev->class_dev,
+				"timer2 not configured in TIMER MODE\n");
 			return -EINVAL;
 		}
 
@@ -1991,8 +1986,8 @@ static int apci3120_write_insn_timer(str
 
 	case 2:		/* write new value to Timer */
 		if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
-			comedi_error(dev,
-				"write :timer2  not configured  in TIMER MODE");
+			dev_err(dev->class_dev,
+				"timer2 not configured in TIMER MODE\n");
 			return -EINVAL;
 		}
 		/*  ui_Timervalue2=data[1]; // passed as argument */
@@ -2017,7 +2012,7 @@ static int apci3120_write_insn_timer(str
 			APCI3120_SELECT_TIMER_2_LOW_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
 
-		outw(LOWORD(ui_Timervalue2),
+		outw(ui_Timervalue2 & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 
 		/* Writing HIGH unsigned short */
@@ -2026,7 +2021,7 @@ static int apci3120_write_insn_timer(str
 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
 
-		outw(HIWORD(ui_Timervalue2),
+		outw((ui_Timervalue2 >> 16) & 0xffff,
 			devpriv->iobase + APCI3120_TIMER_VALUE);
 
 		break;
@@ -2056,7 +2051,7 @@ static int apci3120_read_insn_timer(stru
 
 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
 		&& (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
-		comedi_error(dev, "\nread:timer2  not configured ");
+		dev_err(dev->class_dev, "timer2 not configured\n");
 	}
 
 	/* this_board->timer_read(dev,data); */
@@ -2161,10 +2156,6 @@ static int apci3120_ao_insn_write(struct
 
 	}
 
-/*
- * out put n values at the given channel. printk("\nwaiting for
- * DA_READY BIT");
- */
 	do {			/* Waiting of DA_READY BIT */
 		us_TmpValue =
 			((unsigned short) inw(devpriv->iobase +
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,8 +47,6 @@ This program is distributed in the hope
   +----------+-----------+------------------------------------------------+
 */
 
-/* #define PRINT_INFO */
-
 /* Card Specific information */
 /* #define APCI3200_ADDRESS_RANGE	264 */
 
@@ -455,12 +453,6 @@ static void v_GetAPCI3200EepromCalibrati
 			BoardInformations->s_Module[w_ModulCounter].
 				w_GainValue[w_GainIndex] = w_GainValue;
 
-#             ifdef PRINT_INFO
-			printk("\n Gain value = %d",
-				BoardInformations->s_Module[w_ModulCounter].
-				w_GainValue[w_GainIndex]);
-#             endif
-
 	  /*************************************/
 	  /** Read gain factor for the module **/
 	  /*************************************/
@@ -472,12 +464,6 @@ static void v_GetAPCI3200EepromCalibrati
 				ul_GainFactor[w_GainIndex] =
 				(w_GainFactorValue[1] << 16) +
 				w_GainFactorValue[0];
-
-#             ifdef PRINT_INFO
-			printk("\n w_GainFactorValue [%d] = %lu", w_GainIndex,
-				BoardInformations->s_Module[w_ModulCounter].
-				ul_GainFactor[w_GainIndex]);
-#             endif
 		}
 
       /***************************************************************/
@@ -499,12 +485,6 @@ static void v_GetAPCI3200EepromCalibrati
 				ul_CurrentSource[w_Input] =
 				(w_CurrentSources[0] +
 				((w_CurrentSources[1] & 0xFFF) << 16));
-
-#             ifdef PRINT_INFO
-			printk("\n Current sources [%d] = %lu", w_Input,
-				BoardInformations->s_Module[w_ModulCounter].
-				ul_CurrentSource[w_Input]);
-#             endif
 		}
 
       /***************************************/
@@ -522,12 +502,6 @@ static void v_GetAPCI3200EepromCalibrati
 			ul_CurrentSourceCJC =
 			(w_CurrentSources[0] +
 			((w_CurrentSources[1] & 0xFFF) << 16));
-
-#          ifdef PRINT_INFO
-		printk("\n Current sources CJC = %lu",
-			BoardInformations->s_Module[w_ModulCounter].
-			ul_CurrentSourceCJC);
-#          endif
 	}
 }
 
@@ -540,10 +514,6 @@ static int i_APCI3200_GetChannelCalibrat
 	int i_DiffChannel = 0;
 	int i_Module = 0;
 
-#ifdef PRINT_INFO
-	printk("\n Channel = %u", ui_Channel_num);
-#endif
-
 	/* Test if single or differential mode */
 	if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
 		/* if diff */
@@ -580,16 +550,10 @@ static int i_APCI3200_GetChannelCalibrat
 	/* Test if thermocouple or RTD mode */
 	*CJCCurrentSource =
 		s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC;
-#ifdef PRINT_INFO
-	printk("\n CJCCurrentSource = %lu", *CJCCurrentSource);
-#endif
 
 	*ChannelCurrentSource =
 		s_BoardInfos[dev->minor].s_Module[i_Module].
 		ul_CurrentSource[i_DiffChannel];
-#ifdef PRINT_INFO
-	printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource);
-#endif
 	/*       } */
 	/*    } */
 
@@ -597,9 +561,6 @@ static int i_APCI3200_GetChannelCalibrat
 	*ChannelGainFactor =
 		s_BoardInfos[dev->minor].s_Module[i_Module].
 		ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain];
-#ifdef PRINT_INFO
-	printk("\n ChannelGainFactor = %lu", *ChannelGainFactor);
-#endif
 	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
 
 	return 0;
@@ -689,17 +650,11 @@ static int i_APCI3200_Read1AnalogInputCh
 
 	ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
 
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /************************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/* Enable the interrupt */
-      /************************/
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	}
 
   /******************************/
 	/* Write the command register */
@@ -712,11 +667,8 @@ static int i_APCI3200_Read1AnalogInputCh
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-  /*****************************/
 	/*Test if interrupt is enable */
-  /*****************************/
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 	  /*************************/
 			/*Read the EOC Status bit */
@@ -738,7 +690,7 @@ static int i_APCI3200_Read1AnalogInputCh
 			s_BoardInfos[dev->minor].i_Offset + 28);
 		/* END JK 06.07.04: Management of sevrals boards */
 
-	}			/*  if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -800,20 +752,11 @@ static int i_APCI3200_ReadCalibrationOff
 
 	ui_CommandRegister = 0;
 
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-
-      /**********************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/*Enable the interrupt */
-      /**********************/
-
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	}
 
   /**********************/
 	/*Start the conversion */
@@ -830,13 +773,8 @@ static int i_APCI3200_ReadCalibrationOff
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-  /*****************************/
 	/*Test if interrupt is enable */
-  /*****************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 	  /*******************/
 			/*Read the EOC flag */
@@ -856,7 +794,7 @@ static int i_APCI3200_ReadCalibrationOff
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -915,20 +853,11 @@ static int i_APCI3200_ReadCalibrationGai
 
 	ui_CommandRegister = 0;
 
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-
-      /**********************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/*Enable the interrupt */
-      /**********************/
-
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	}
 
   /**********************/
 	/*Start the conversion */
@@ -945,13 +874,8 @@ static int i_APCI3200_ReadCalibrationGai
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-  /*****************************/
 	/*Test if interrupt is enable */
-  /*****************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 
 	  /*******************/
@@ -973,7 +897,7 @@ static int i_APCI3200_ReadCalibrationGai
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
 
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -1020,14 +944,9 @@ static int i_APCI3200_ReadCJCValue(struc
 	/*Initialise dw_CommandRegister */
   /*******************************/
 	ui_CommandRegister = 0;
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/*Enable the interrupt */
-      /**********************/
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
 	}
 
@@ -1047,12 +966,8 @@ static int i_APCI3200_ReadCJCValue(struc
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-  /*****************************/
 	/*Test if interrupt is enable */
-  /*****************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 
 	  /*******************/
@@ -1073,8 +988,7 @@ static int i_APCI3200_ReadCJCValue(struc
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -1128,17 +1042,10 @@ static int i_APCI3200_ReadCJCCalOffset(s
 	/*Initialise ui_CommandRegister */
   /*******************************/
 	ui_CommandRegister = 0;
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/*Enable the interrupt */
-      /**********************/
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-
 	}
 
   /**********************/
@@ -1154,8 +1061,7 @@ static int i_APCI3200_ReadCJCCalOffset(s
 	/* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 	  /*******************/
 			/*Read the EOC flag */
@@ -1172,7 +1078,7 @@ static int i_APCI3200_ReadCJCCalOffset(s
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -1224,14 +1130,9 @@ static int i_APCI3200_ReadCJCCalGain(str
 	/*Initialise dw_CommandRegister */
   /*******************************/
 	ui_CommandRegister = 0;
-  /*********************************/
 	/*Test if the interrupt is enable */
-  /*********************************/
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
 		/*Enable the interrupt */
-      /**********************/
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
 	}
   /**********************/
@@ -1247,8 +1148,7 @@ static int i_APCI3200_ReadCJCCalGain(str
 	/* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
 		do {
 	  /*******************/
 			/*Read the EOC flag */
@@ -1264,7 +1164,7 @@ static int i_APCI3200_ReadCJCCalGain(str
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}
 	return 0;
 }
 
@@ -1340,10 +1240,6 @@ static int apci3200_ai_read(struct comed
 		return -EINVAL;
 	}			/* if(i_Initialised==0); */
 
-#ifdef PRINT_INFO
-	printk("\n insn->unused[0] = %i", insn->unused[0]);
-#endif
-
 	switch (insn->unused[0]) {
 	case 0:
 
@@ -1368,15 +1264,6 @@ static int apci3200_ai_read(struct comed
 			&s_BoardInfos[dev->minor].
 			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
 				i_Count + 8]);
-
-#ifdef PRINT_INFO
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]);
-
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]);
-
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
-#endif
-
 		/* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
 
 		/* BEGIN JK 06.07.04: Management of sevrals boards */
@@ -1532,9 +1419,6 @@ static int apci3200_ai_read(struct comed
 			   data[4]= ui_InterruptChannelValue[4];
 			   data[5]= ui_InterruptChannelValue[5];
 			 */
-#ifdef PRINT_INFO
-			printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];");
-#endif
 			data[0] =
 				s_BoardInfos[dev->minor].
 				ui_InterruptChannelValue[0];
@@ -1555,7 +1439,6 @@ static int apci3200_ai_read(struct comed
 				ui_InterruptChannelValue[5];
 
 			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-			/* printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); */
 			i_APCI3200_GetChannelCalibrationValue(dev,
 				s_BoardInfos[dev->minor].ui_Channel_num,
 				&data[6], &data[7], &data[8]);
@@ -1637,13 +1520,6 @@ static int apci3200_ai_config(struct com
 	unsigned int ui_Dummy = 0;
 	int i_err = 0;
 
-	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
-#ifdef PRINT_INFO
-	int i = 0, i2 = 0;
-#endif
-	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
 	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/*  Initialize the structure */
 	if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
@@ -1669,29 +1545,6 @@ static int apci3200_ai_config(struct com
 
 		v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
 			&s_BoardInfos[dev->minor]);
-
-#ifdef PRINT_INFO
-		for (i = 0; i < MAX_MODULE; i++) {
-			printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i,
-				s_BoardInfos[dev->minor].s_Module[i].
-				ul_CurrentSourceCJC);
-
-			for (i2 = 0; i2 < 5; i2++) {
-				printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]);
-			}
-
-			for (i2 = 0; i2 < 8; i2++) {
-				printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]);
-			}
-
-			for (i2 = 0; i2 < 8; i2++) {
-				printk("\n s_Module[%i].w_GainValue [%i] = %u",
-					i, i2,
-					s_BoardInfos[dev->minor].s_Module[i].
-					w_GainValue[i2]);
-			}
-		}
-#endif
 		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
 	}
 
@@ -1811,34 +1664,34 @@ static int apci3200_ai_config(struct com
 	/* END JK 06.07.04: Management of sevrals boards */
 
 	if (data[5] == 0) {
-		if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
+		if (ui_ChannelNo > 15) {
 			printk("\nThe Selection of the channel is in error\n");
 			i_err++;
-		}		/*  if(ui_ChannelNo<0 || ui_ChannelNo>15) */
+		}		/*  if(ui_ChannelNo>15) */
 	}			/* if(data[5]==0) */
 	else {
 		if (data[14] == 2) {
-			if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
+			if (ui_ChannelNo > 3) {
 				printk("\nThe Selection of the channel is in error\n");
 				i_err++;
-			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>3) */
+			}	/*  if(ui_ChannelNo>3) */
 		}		/* if(data[14]==2) */
 		else {
-			if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
+			if (ui_ChannelNo > 7) {
 				printk("\nThe Selection of the channel is in error\n");
 				i_err++;
-			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>7) */
+			}	/*  if(ui_ChannelNo>7) */
 		}		/* elseif(data[14]==2) */
 	}			/* elseif(data[5]==0) */
 	if (data[12] == 0 || data[12] == 1) {
 		switch (data[5]) {
 		case 0:
-			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
+			if (ui_ChannelNo <= 3) {
 				/* BEGIN JK 06.07.04: Management of sevrals boards */
 				/* i_Offset=0; */
 				s_BoardInfos[dev->minor].i_Offset = 0;
 				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=3) */
+			}	/* if(ui_ChannelNo <=3) */
 			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
 				/* BEGIN JK 06.07.04: Management of sevrals boards */
 				/* i_Offset=64; */
@@ -1892,12 +1745,12 @@ static int apci3200_ai_config(struct com
 				ui_ChannelNo = 0;
 				break;
 			}	/* if(data[14]==2) */
-			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
+			if (ui_ChannelNo <= 1) {
 				/* BEGIN JK 06.07.04: Management of sevrals boards */
 				/* i_Offset=0; */
 				s_BoardInfos[dev->minor].i_Offset = 0;
 				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=1) */
+			}	/* if(ui_ChannelNo <=1) */
 			if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
 				/* BEGIN JK 06.07.04: Management of sevrals boards */
 				/* i_ChannelNo=i_ChannelNo-2; */
@@ -2136,8 +1989,7 @@ static int apci3200_ai_bits_test(struct
 		   i_ADDIDATAConversionTimeUnit= 1; */
 		/* i_Temp= i_InterruptFlag ; */
 		i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
-		/* i_InterruptFlag = ADDIDATA_DISABLE; */
-		s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
 		i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
 		/* if(i_AutoCalibration == FALSE) */
 		if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
@@ -2176,8 +2028,7 @@ static int apci3200_ai_bits_test(struct
 		   i_ADDIDATAConversionTimeUnit= 1; */
 		/* i_Temp= i_InterruptFlag ; */
 		i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
-		/* i_InterruptFlag = ADDIDATA_DISABLE; */
-		s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
 		i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
 		/* if(i_AutoCalibration == FALSE) */
 		if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
@@ -2198,7 +2049,6 @@ static int apci3200_ai_bits_test(struct
 	}
 	/* i_InterruptFlag=i_Temp ; */
 	s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp;
-	/* printk("\ni_InterruptFlag=%d\n",i_InterruptFlag); */
 	return insn->n;
 }
 
@@ -2470,8 +2320,6 @@ static int apci3200_ai_cmd(struct comedi
 		ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
 		ui_DelayMode = 1;
 	}			/* else if(cmd->scan_begin_src==TRIG_FOLLOW) */
-	/*         printk("\nui_DelayTime=%u\n",ui_DelayTime); */
-	/*         printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase); */
 	if (cmd->convert_src == TRIG_TIMER) {
 		ui_ConvertTime = cmd->convert_arg & 0xFFFF;
 		ui_ConvertTimeBase = cmd->convert_arg >> 16;
@@ -2499,13 +2347,6 @@ static int apci3200_ai_cmd(struct comedi
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
 	/*  } */
 	ui_Configuration = 0;
-	/*      printk("\nfirstchannel=%u\n",i_FirstChannel); */
-	/*      printk("\nlastchannel=%u\n",i_LastChannel); */
-	/*      printk("\nui_Trigger=%u\n",ui_Trigger); */
-	/*      printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge); */
-	/*      printk("\nui_Triggermode=%u\n",ui_Triggermode); */
-	/*       printk("\nui_DelayMode=%u\n",ui_DelayMode); */
-	/*      printk("\nui_ScanMode=%u\n",ui_ScanMode); */
 
 	/* ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | */
 	ui_Configuration =
@@ -2757,8 +2598,6 @@ static void apci3200_interrupt(int irq,
 	int i_ReturnValue = 0;
 	/* END JK TEST */
 
-	/* printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType); */
-
 	/* switch(i_ScanType) */
 	switch (s_BoardInfos[dev->minor].i_ScanType) {
 	case 0:
@@ -2809,7 +2648,6 @@ static void apci3200_interrupt(int irq,
 
 					/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
 					/*
-					   printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber);
 					   i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num,
 					   &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6],
 					   &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7],
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adl_pci9111.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adl_pci9111.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adl_pci9111.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adl_pci9111.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,9 +75,6 @@ TODO:
 #include "plx9052.h"
 #include "comedi_fc.h"
 
-#define PCI9111_DRIVER_NAME	"adl_pci9111"
-#define PCI9111_HR_DEVICE_ID	0x9111
-
 #define PCI9111_FIFO_HALF_SIZE	512
 
 #define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
@@ -189,68 +186,6 @@ static void pci9111_timer_set(struct com
 	i8254_write(timer_base, 1, 1, dev_private->div1);
 }
 
-enum pci9111_trigger_sources {
-	software,
-	timer_pacer,
-	external
-};
-
-static void pci9111_trigger_source_set(struct comedi_device *dev,
-				       enum pci9111_trigger_sources source)
-{
-	int flags;
-
-	/* Read the current trigger mode control bits */
-	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-	/* Mask off the EITS and TPST bits */
-	flags &= 0x9;
-
-	switch (source) {
-	case software:
-		break;
-
-	case timer_pacer:
-		flags |= PCI9111_AI_TRIG_CTRL_TPST;
-		break;
-
-	case external:
-		flags |= PCI9111_AI_TRIG_CTRL_ETIS;
-		break;
-	}
-
-	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-}
-
-static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
-{
-	int flags;
-
-	/* Read the current trigger mode control bits */
-	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-	/* Mask off the PTRG bit */
-	flags &= 0x7;
-
-	if (pretrigger)
-		flags |= PCI9111_AI_TRIG_CTRL_PTRG;
-
-	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-}
-
-static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
-{
-	int flags;
-
-	/* Read the current trigger mode control bits */
-	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-	/* Mask off the ASCAN bit */
-	flags &= 0xe;
-
-	if (autoscan)
-		flags |= PCI9111_AI_TRIG_CTRL_ASCAN;
-
-	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
-}
-
 enum pci9111_ISC0_sources {
 	irq_on_eoc,
 	irq_on_fifo_half_full
@@ -303,9 +238,8 @@ static int pci9111_ai_cancel(struct come
 	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
 				  true, false);
 
-	pci9111_trigger_source_set(dev, software);
-
-	pci9111_autoscan_set(dev, false);
+	/* disable A/D triggers (software trigger mode) and auto scan off */
+	outb(0, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 
 	pci9111_fifo_reset(dev);
 
@@ -454,20 +388,17 @@ static int pci9111_ai_do_cmd(struct come
 {
 	struct pci9111_private_data *dev_private = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
+	unsigned int trig = 0;
 
 	/*  Set channel scan limit */
 	/*  PCI9111 allows only scanning from channel 0 to channel n */
 	/*  TODO: handle the case of an external multiplexer */
 
-	if (cmd->chanlist_len > 1) {
-		outb(cmd->chanlist_len - 1,
-			dev->iobase + PCI9111_AI_CHANNEL_REG);
-		pci9111_autoscan_set(dev, true);
-	} else {
-		outb(CR_CHAN(cmd->chanlist[0]),
-			dev->iobase + PCI9111_AI_CHANNEL_REG);
-		pci9111_autoscan_set(dev, false);
-	}
+	if (cmd->chanlist_len > 1)
+		trig |= PCI9111_AI_TRIG_CTRL_ASCAN;
+
+	outb(last_chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
 
 	/*  Set gain */
 	/*  This is the same gain on every channel */
@@ -484,12 +415,11 @@ static int pci9111_ai_do_cmd(struct come
 	/*  Set timer pacer */
 	dev_private->scan_delay = 0;
 	if (cmd->convert_src == TRIG_TIMER) {
-		pci9111_trigger_source_set(dev, software);
+		trig |= PCI9111_AI_TRIG_CTRL_TPST;
 		pci9111_timer_set(dev);
 		pci9111_fifo_reset(dev);
 		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
 					     irq_on_timer_tick);
-		pci9111_trigger_source_set(dev, timer_pacer);
 		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
 					  false, true, true);
 
@@ -498,14 +428,14 @@ static int pci9111_ai_do_cmd(struct come
 				(cmd->convert_arg * cmd->chanlist_len)) - 1;
 		}
 	} else {	/* TRIG_EXT */
-		pci9111_trigger_source_set(dev, external);
+		trig |= PCI9111_AI_TRIG_CTRL_ETIS;
 		pci9111_fifo_reset(dev);
 		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
 					     irq_on_timer_tick);
 		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
 					  false, true, true);
-
 	}
+	outb(trig, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 
 	dev_private->stop_counter *= (1 + dev_private->scan_delay);
 	dev_private->chunk_counter = 0;
@@ -630,7 +560,7 @@ static irqreturn_t pci9111_interrupt(int
 		/* '0' means FIFO is full, data may have been lost */
 		if (!(status & PCI9111_AI_STAT_FF_FF)) {
 			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
-			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
+			dev_dbg(dev->class_dev, "fifo overflow\n");
 			outb(0, dev->iobase + PCI9111_INT_CLR_REG);
 			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 			cfc_handle_events(dev, s);
@@ -771,9 +701,8 @@ static int pci9111_reset(struct comedi_d
 	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
 				  true, false);
 
-	pci9111_trigger_source_set(dev, software);
-	pci9111_pretrigger_set(dev, false);
-	pci9111_autoscan_set(dev, false);
+	/* disable A/D triggers (software trigger mode) and auto scan off */
+	outb(0, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 
 	/* Reset 8254 chip */
 	dev_private->div1 = 0;
@@ -884,7 +813,7 @@ static int pci9111_pci_probe(struct pci_
 }
 
 static const struct pci_device_id pci9111_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x9111) },
 	/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
 	{ 0 }
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adl_pci9118.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adl_pci9118.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adl_pci9118.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adl_pci9118.c	2014-09-28 17:29:07.000000000 -0400
@@ -7,61 +7,62 @@
  *
  * Author: Michal Dobes <dobes@tesnet.cz>
  *
-*/
-/*
-Driver: adl_pci9118
-Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
-Author: Michal Dobes <dobes@tesnet.cz>
-Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
-  PCI-9118HR (pci9118hr)
-Status: works
-
-This driver supports AI, AO, DI and DO subdevices.
-AI subdevice supports cmd and insn interface,
-other subdevices support only insn interface.
-For AI:
-- If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
-- If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
-- If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
-- It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
-  cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
-- If return value of cmdtest is 5 then you've bad channel list
-  (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
-  ranges).
-
-There are some hardware limitations:
-a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
-   ended inputs.
-b) DMA transfers must have the length aligned to two samples (32 bit),
-   so there is some problems if cmd->chanlist_len is odd. This driver tries
-   bypass this with adding one sample to the end of the every scan and discard
-   it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
-   and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
-   with interrupt after every sample.
-c) If isn't used DMA then you can use only mode where
-   cmd->scan_begin_src=TRIG_FOLLOW.
-
-Configuration options:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-	If bus/slot is not specified, then first available PCI
-	card will be used.
-  [2] - 0= standard 8 DIFF/16 SE channels configuration
-	n = external multiplexer connected, 1 <= n <= 256
-  [3] - 0=autoselect DMA or EOC interrupts operation
-	1 = disable DMA mode
-	3 = disable DMA and INT, only insn interface will work
-  [4] - sample&hold signal - card can generate signal for external S&H board
-	0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
-	0 != use ADCHN7(pin 23) signal is generated from driver, number say how
-		long delay is requested in ns and sign polarity of the hold
-		(in this case external multiplexor can serve only 128 channels)
-  [5] - 0=stop measure on all hardware errors
-	2 | = ignore ADOR - A/D Overrun status
-	8|=ignore Bover - A/D Burst Mode Overrun status
-	256|=ignore nFull - A/D FIFO Full status
+ */
 
-*/
+/*
+ * Driver: adl_pci9118
+ * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
+ * Author: Michal Dobes <dobes@tesnet.cz>
+ * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
+ * PCI-9118HR (pci9118hr)
+ * Status: works
+ *
+ * This driver supports AI, AO, DI and DO subdevices.
+ * AI subdevice supports cmd and insn interface,
+ * other subdevices support only insn interface.
+ * For AI:
+ * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
+ * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
+ * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
+ * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
+ * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
+ * - If return value of cmdtest is 5 then you've bad channel list
+ * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
+ * ranges).
+ *
+ * There are some hardware limitations:
+ * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
+ *  ended inputs.
+ * b) DMA transfers must have the length aligned to two samples (32 bit),
+ *  so there is some problems if cmd->chanlist_len is odd. This driver tries
+ *  bypass this with adding one sample to the end of the every scan and discard
+ *  it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
+ *  and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
+ *  with interrupt after every sample.
+ * c) If isn't used DMA then you can use only mode where
+ *  cmd->scan_begin_src=TRIG_FOLLOW.
+ *
+ * Configuration options:
+ * [0] - PCI bus of device (optional)
+ * [1] - PCI slot of device (optional)
+ *	 If bus/slot is not specified, then first available PCI
+ *	 card will be used.
+ * [2] - 0= standard 8 DIFF/16 SE channels configuration
+ *	 n = external multiplexer connected, 1 <= n <= 256
+ * [3] - 0=autoselect DMA or EOC interrupts operation
+ *	 1 = disable DMA mode
+ *	 3 = disable DMA and INT, only insn interface will work
+ * [4] - sample&hold signal - card can generate signal for external S&H board
+ *	 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
+ *	 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
+ *		long delay is requested in ns and sign polarity of the hold
+ *		(in this case external multiplexor can serve only 128 channels)
+ * [5] - 0=stop measure on all hardware errors
+ *	 2 | = ignore ADOR - A/D Overrun status
+ *	 8|=ignore Bover - A/D Burst Mode Overrun status
+ *	 256|=ignore nFull - A/D FIFO Full status
+ *
+ */
 
 /*
  * FIXME
@@ -346,7 +347,7 @@ struct pci9118_private {
 						 * on external start
 						 */
 	unsigned short ao_data[2];		/* data output buffer */
-	char dma_doublebuf;			/* we can use double buffering */
+	char dma_doublebuf;			/* use double buffering */
 	unsigned int dma_actbuf;		/* which buffer is used now */
 	unsigned short *dmabuf_virt[2];		/*
 						 * pointers to begin of
@@ -394,12 +395,12 @@ static int check_channel_list(struct com
 
 	/* correct channel and range number check itself comedi/range.c */
 	if (n_chan < 1) {
-		comedi_error(dev, "range/channel list is empty!");
+		dev_err(dev->class_dev, "range/channel list is empty!\n");
 		return 0;
 	}
 	if ((frontadd + n_chan + backadd) > s->len_chanlist) {
-		comedi_error(dev,
-			    "range/channel list is too long for actual configuration!\n");
+		dev_err(dev->class_dev,
+			"range/channel list is too long for actual configuration!\n");
 		return 0;
 	}
 
@@ -411,23 +412,20 @@ static int check_channel_list(struct com
 		for (i = 1; i < n_chan; i++) {	/* check S.E/diff */
 			if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
 			    (differencial)) {
-				comedi_error(dev,
-					     "Differencial and single ended "
-						"inputs can't be mixtured!");
+				dev_err(dev->class_dev,
+					"Differential and single ended inputs can't be mixed!\n");
 				return 0;
 			}
 			if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
 			    (bipolar)) {
-				comedi_error(dev,
-					     "Bipolar and unipolar ranges "
-							"can't be mixtured!");
+				dev_err(dev->class_dev,
+					"Bipolar and unipolar ranges can't be mixed!\n");
 				return 0;
 			}
 			if (!devpriv->usemux && differencial &&
 			    (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
-				comedi_error(dev,
-					     "If AREF_DIFF is used then is "
-					"available only first 8 channels!");
+				dev_err(dev->class_dev,
+					"AREF_DIFF is only available for the first 8 channels!\n");
 				return 0;
 			}
 		}
@@ -864,20 +862,21 @@ static char pci9118_decode_error_status(
 	struct pci9118_private *devpriv = dev->private;
 
 	if (m & 0x100) {
-		comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
+		dev_err(dev->class_dev,
+			"A/D FIFO Full status (Fatal Error!)\n");
 		devpriv->ai_maskerr &= ~0x100L;
 	}
 	if (m & 0x008) {
-		comedi_error(dev,
-			     "A/D Burst Mode Overrun Status (Fatal Error!)");
+		dev_err(dev->class_dev,
+			"A/D Burst Mode Overrun Status (Fatal Error!)\n");
 		devpriv->ai_maskerr &= ~0x008L;
 	}
 	if (m & 0x004) {
-		comedi_error(dev, "A/D Over Speed Status (Warning!)");
+		dev_err(dev->class_dev, "A/D Over Speed Status (Warning!)\n");
 		devpriv->ai_maskerr &= ~0x004L;
 	}
 	if (m & 0x002) {
-		comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
+		dev_err(dev->class_dev, "A/D Overrun Status (Fatal Error!)\n");
 		devpriv->ai_maskerr &= ~0x002L;
 	}
 	if (m & devpriv->ai_maskharderr) {
@@ -966,14 +965,14 @@ static void interrupt_pci9118_ai_dma(str
 	unsigned int next_dma_buf, samplesinbuf, sampls, m;
 
 	if (int_amcc & MASTER_ABORT_INT) {
-		comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
+		dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
 		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
 		return;
 	}
 
 	if (int_amcc & TARGET_ABORT_INT) {
-		comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
+		dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
 		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
 		return;
@@ -1427,17 +1426,16 @@ static int pci9118_ai_docmd_sampl(struct
 		devpriv->AdControlReg |= AdControl_TmrTr;
 		break;
 	case 2:
-		comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
+		dev_err(dev->class_dev, "%s mode 2 bug!\n", __func__);
 		return -EIO;
 	case 3:
 		devpriv->AdControlReg |= AdControl_ExtM;
 		break;
 	case 4:
-		comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
+		dev_err(dev->class_dev, "%s mode 4 bug!\n", __func__);
 		return -EIO;
 	default:
-		comedi_error(dev,
-			     "pci9118_ai_docmd_sampl() mode number bug!\n");
+		dev_err(dev->class_dev, "%s mode number bug!\n", __func__);
 		return -EIO;
 	}
 
@@ -1509,7 +1507,7 @@ static int pci9118_ai_docmd_dma(struct c
 		devpriv->AdFunctionReg |= AdFunction_Start;
 		break;
 	default:
-		comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
+		dev_err(dev->class_dev, "%s mode number bug!\n", __func__);
 		return -EIO;
 	}
 
@@ -1677,9 +1675,8 @@ static int pci9118_ai_cmd(struct comedi_
 		(cmd->convert_src == TRIG_NOW))) {
 						/* double timed action */
 		if (!devpriv->usedma) {
-			comedi_error(dev,
-				     "cmd->scan_begin_src=TRIG_TIMER works "
-						"only with bus mastering!");
+			dev_err(dev->class_dev,
+				"cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n");
 			return -EIO;
 		}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adq12b.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adq12b.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adq12b.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adq12b.c	2014-09-28 17:29:07.000000000 -0400
@@ -79,20 +79,20 @@ If you do not specify any options, they
 #include "../comedidev.h"
 
 /* address scheme (page 2.17 of the manual) */
-#define ADQ12B_SIZE     16
-
-#define ADQ12B_CTREG    0x00
-#define ADQ12B_STINR    0x00
-#define ADQ12B_OUTBR    0x04
-#define ADQ12B_ADLOW    0x08
-#define ADQ12B_ADHIG    0x09
-#define ADQ12B_CONT0    0x0c
-#define ADQ12B_CONT1    0x0d
-#define ADQ12B_CONT2    0x0e
-#define ADQ12B_COWORD   0x0f
-
-/* mask of the bit at STINR to check end of conversion */
-#define ADQ12B_EOC     0x20
+#define ADQ12B_CTREG		0x00
+#define ADQ12B_CTREG_MSKP	(1 << 7)	/* enable pacer interrupt */
+#define ADQ12B_CTREG_GTP	(1 << 6)	/* enable pacer */
+#define ADQ12B_CTREG_RANGE(x)	((x) << 4)
+#define ADQ12B_CTREG_CHAN(x)	((x) << 0)
+#define ADQ12B_STINR		0x00
+#define ADQ12B_STINR_OUT2	(1 << 7)	/* timer 2 output state */
+#define ADQ12B_STINR_OUTP	(1 << 6)	/* pacer output state */
+#define ADQ12B_STINR_EOC	(1 << 5)	/* A/D end-of-conversion */
+#define ADQ12B_STINR_IN_MASK	(0x1f << 0)
+#define ADQ12B_OUTBR		0x04
+#define ADQ12B_ADLOW		0x08
+#define ADQ12B_ADHIG		0x09
+#define ADQ12B_TIMER_BASE	0x0c
 
 /* available ranges through the PGA gains */
 static const struct comedi_lrange range_adq12b_ai_bipolar = {
@@ -114,10 +114,7 @@ static const struct comedi_lrange range_
 };
 
 struct adq12b_private {
-	int unipolar;		/* option 2 of comedi_config (1 is iobase) */
-	int differential;	/* option 3 of comedi_config */
-	int last_channel;
-	int last_range;
+	unsigned int last_ctreg;
 };
 
 static int adq12b_ai_eoc(struct comedi_device *dev,
@@ -128,50 +125,45 @@ static int adq12b_ai_eoc(struct comedi_d
 	unsigned char status;
 
 	status = inb(dev->iobase + ADQ12B_STINR);
-	if (status & ADQ12B_EOC)
+	if (status & ADQ12B_STINR_EOC)
 		return 0;
 	return -EBUSY;
 }
 
-static int adq12b_ai_rinsn(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
-			   unsigned int *data)
+static int adq12b_ai_insn_read(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct adq12b_private *devpriv = dev->private;
-	int n;
-	int range, channel;
-	unsigned char hi, lo, status;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int val;
 	int ret;
+	int i;
 
 	/* change channel and range only if it is different from the previous */
-	range = CR_RANGE(insn->chanspec);
-	channel = CR_CHAN(insn->chanspec);
-	if (channel != devpriv->last_channel || range != devpriv->last_range) {
-		outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
+	val = ADQ12B_CTREG_RANGE(range) | ADQ12B_CTREG_CHAN(chan);
+	if (val != devpriv->last_ctreg) {
+		outb(val, dev->iobase + ADQ12B_CTREG);
+		devpriv->last_ctreg = val;
 		udelay(50);	/* wait for the mux to settle */
 	}
 
-	/* trigger conversion */
-	status = inb(dev->iobase + ADQ12B_ADLOW);
-
-	/* convert n samples */
-	for (n = 0; n < insn->n; n++) {
+	val = inb(dev->iobase + ADQ12B_ADLOW);	/* trigger A/D */
 
-		/* wait for end of conversion */
+	for (i = 0; i < insn->n; i++) {
 		ret = comedi_timeout(dev, s, insn, adq12b_ai_eoc, 0);
 		if (ret)
 			return ret;
 
-		/* read data */
-		hi = inb(dev->iobase + ADQ12B_ADHIG);
-		lo = inb(dev->iobase + ADQ12B_ADLOW);
-
-		data[n] = (hi << 8) | lo;
+		val = inb(dev->iobase + ADQ12B_ADHIG) << 8;
+		val |= inb(dev->iobase + ADQ12B_ADLOW);	/* retriggers A/D */
 
+		data[i] = val;
 	}
 
-	/* return the number of samples read/written */
-	return n;
+	return insn->n;
 }
 
 static int adq12b_di_insn_bits(struct comedi_device *dev,
@@ -180,7 +172,7 @@ static int adq12b_di_insn_bits(struct co
 {
 
 	/* only bits 0-4 have information about digital inputs */
-	data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f));
+	data[1] = (inb(dev->iobase + ADQ12B_STINR) & ADQ12B_STINR_IN_MASK);
 
 	return insn->n;
 }
@@ -216,7 +208,7 @@ static int adq12b_attach(struct comedi_d
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], ADQ12B_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
@@ -224,58 +216,44 @@ static int adq12b_attach(struct comedi_d
 	if (!devpriv)
 		return -ENOMEM;
 
-	devpriv->unipolar = it->options[1];
-	devpriv->differential = it->options[2];
-	/*
-	 * initialize channel and range to -1 so we make sure we
-	 * always write at least once to the CTREG in the instruction
-	 */
-	devpriv->last_channel = -1;
-	devpriv->last_range = -1;
+	devpriv->last_ctreg = -1;	/* force ctreg update */
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
 		return ret;
 
+	/* Analog Input subdevice */
 	s = &dev->subdevices[0];
-	/* analog input subdevice */
-	s->type = COMEDI_SUBD_AI;
-	if (devpriv->differential) {
-		s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
-		s->n_chan = 8;
+	s->type		= COMEDI_SUBD_AI;
+	if (it->options[2]) {
+		s->subdev_flags	= SDF_READABLE | SDF_DIFF;
+		s->n_chan	= 8;
 	} else {
-		s->subdev_flags = SDF_READABLE | SDF_GROUND;
-		s->n_chan = 16;
+		s->subdev_flags	= SDF_READABLE | SDF_GROUND;
+		s->n_chan	= 16;
 	}
+	s->maxdata	= 0xfff;
+	s->range_table	= it->options[1] ? &range_adq12b_ai_unipolar
+					 : &range_adq12b_ai_bipolar;
+	s->insn_read	= adq12b_ai_insn_read;
 
-	if (devpriv->unipolar)
-		s->range_table = &range_adq12b_ai_unipolar;
-	else
-		s->range_table = &range_adq12b_ai_bipolar;
-
-	s->maxdata = 0xfff;
-
-	s->len_chanlist = 4;	/* This is the maximum chanlist length that
-				   the board can handle */
-	s->insn_read = adq12b_ai_rinsn;
-
+	/* Digital Input subdevice */
 	s = &dev->subdevices[1];
-	/* digital input subdevice */
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = 5;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = adq12b_di_insn_bits;
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 5;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= adq12b_di_insn_bits;
 
+	/* Digital Output subdevice */
 	s = &dev->subdevices[2];
-	/* digital output subdevice */
-	s->type = COMEDI_SUBD_DO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = adq12b_do_insn_bits;
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= adq12b_do_insn_bits;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1710.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1710.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1710.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1710.c	2014-09-28 17:29:07.000000000 -0400
@@ -722,8 +722,8 @@ static int pci171x_ai_cancel(struct come
 	default:
 		devpriv->CntrlReg &= Control_CNT0;
 		devpriv->CntrlReg |= Control_SW;
-
-		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	/*  reset any operations */
+		/* reset any operations */
+		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
 		pci171x_start_pacer(dev, false);
 		outb(0, dev->iobase + PCI171x_CLRFIFO);
 		outb(0, dev->iobase + PCI171x_CLRINT);
@@ -1049,15 +1049,18 @@ static int pci171x_reset(struct comedi_d
 	struct pci1710_private *devpriv = dev->private;
 
 	outw(0x30, dev->iobase + PCI171x_CNTCTRL);
-	devpriv->CntrlReg = Control_SW | Control_CNT0;	/*  Software trigger, CNT0=external */
-	outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	/*  reset any operations */
+	/* Software trigger, CNT0=external */
+	devpriv->CntrlReg = Control_SW | Control_CNT0;
+	/* reset any operations */
+	outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
 	outb(0, dev->iobase + PCI171x_CLRFIFO);	/*  clear FIFO */
 	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear INT request */
 	pci171x_start_pacer(dev, false);
 	devpriv->da_ranges = 0;
 	if (this_board->n_aochan) {
-		outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);	/*  set DACs to 0..5V */
-		outw(0, dev->iobase + PCI171x_DA1);	/*  set DA outputs to 0V */
+		/* set DACs to 0..5V */
+		outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
+		outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */
 		devpriv->ao_data[0] = 0x0000;
 		if (this_board->n_aochan > 1) {
 			outw(0, dev->iobase + PCI171x_DA2);
@@ -1077,10 +1080,11 @@ static int pci171x_reset(struct comedi_d
 static int pci1720_reset(struct comedi_device *dev)
 {
 	struct pci1710_private *devpriv = dev->private;
-
-	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);	/*  set synchronous output mode */
+	/* set synchronous output mode */
+	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);
 	devpriv->da_ranges = 0xAA;
-	outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE);	/*  set all ranges to +/-5V */
+	/* set all ranges to +/-5V */
+	outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE);
 	outw(0x0800, dev->iobase + PCI1720_DA0);	/*  set outputs to 0V */
 	outw(0x0800, dev->iobase + PCI1720_DA1);
 	outw(0x0800, dev->iobase + PCI1720_DA2);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1723.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1723.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1723.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1723.c	2014-09-28 17:29:07.000000000 -0400
@@ -161,11 +161,10 @@ static int pci1723_ao_write_winsn(struct
 				  struct comedi_insn *insn, unsigned int *data)
 {
 	struct pci1723_private *devpriv = dev->private;
-	int n, chan;
-	chan = CR_CHAN(insn->chanspec);
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int n;
 
 	for (n = 0; n < insn->n; n++) {
-
 		devpriv->ao_data[chan] = data[n];
 		outw(data[n], dev->iobase + PCI1723_DA(chan));
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1724.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1724.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci1724.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci1724.c	2014-09-28 17:29:07.000000000 -0400
@@ -143,7 +143,8 @@ static int wait_for_dac_idle(struct come
 		udelay(1);
 	}
 	if (i == timeout) {
-		comedi_error(dev, "Timed out waiting for dac to become idle.");
+		dev_err(dev->class_dev,
+			"Timed out waiting for dac to become idle\n");
 		return -EIO;
 	}
 	return 0;
@@ -195,8 +196,8 @@ static int ao_readback_insn(struct comed
 	int i;
 
 	if (devpriv->ao_value[channel] < 0) {
-		comedi_error(dev,
-			     "Cannot read back channels which have not yet been written to.");
+		dev_err(dev->class_dev,
+			"Cannot read back channels which have not yet been written to\n");
 		return -EIO;
 	}
 	for (i = 0; i < insn->n; i++)
@@ -236,8 +237,8 @@ static int offset_read_insn(struct comed
 	int i;
 
 	if (devpriv->offset_value[channel] < 0) {
-		comedi_error(dev,
-			     "Cannot read back channels which have not yet been written to.");
+		dev_err(dev->class_dev,
+			"Cannot read back channels which have not yet been written to\n");
 		return -EIO;
 	}
 	for (i = 0; i < insn->n; i++)
@@ -277,8 +278,8 @@ static int gain_read_insn(struct comedi_
 	int i;
 
 	if (devpriv->gain_value[channel] < 0) {
-		comedi_error(dev,
-			     "Cannot read back channels which have not yet been written to.");
+		dev_err(dev->class_dev,
+			"Cannot read back channels which have not yet been written to\n");
 		return -EIO;
 	}
 	for (i = 0; i < insn->n; i++)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci_dio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci_dio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/adv_pci_dio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/adv_pci_dio.c	2014-09-28 17:29:07.000000000 -0400
@@ -592,7 +592,7 @@ static int pci1760_unchecked_mbxrequest(
 			return 0;
 	}
 
-	comedi_error(dev, "PCI-1760 mailbox request timeout!");
+	dev_err(dev->class_dev, "PCI-1760 mailbox request timeout!\n");
 	return -ETIME;
 }
 
@@ -610,12 +610,13 @@ static int pci1760_mbxrequest(struct com
 			      unsigned char *omb, unsigned char *imb)
 {
 	if (omb[2] == CMD_ClearIMB2) {
-		comedi_error(dev,
-			     "bug! this function should not be used for CMD_ClearIMB2 command");
+		dev_err(dev->class_dev,
+			"bug! this function should not be used for CMD_ClearIMB2 command\n");
 		return -EINVAL;
 	}
 	if (inb(dev->iobase + IMB2) == omb[2]) {
 		int retval;
+
 		retval = pci1760_clear_imb2(dev);
 		if (retval < 0)
 			return retval;
@@ -826,7 +827,7 @@ static int pci_dio_reset(struct comedi_d
 		outb(0, dev->iobase + PCI1730_DO + 1);
 		outb(0, dev->iobase + PCI1730_IDO);
 		outb(0, dev->iobase + PCI1730_IDO + 1);
-		/* NO break there! */
+		/* fallthrough */
 	case TYPE_PCI1733:
 		/* disable interrupts */
 		outb(0, dev->iobase + PCI1730_3_INT_EN);
@@ -886,7 +887,7 @@ static int pci_dio_reset(struct comedi_d
 		outb(0x80, dev->iobase + PCI1753E_ICR1);
 		outb(0x80, dev->iobase + PCI1753E_ICR2);
 		outb(0x80, dev->iobase + PCI1753E_ICR3);
-		/* NO break there! */
+		/* fallthrough */
 	case TYPE_PCI1753:
 		outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear
 							 * interrupts */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/aio_iiro_16.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/aio_iiro_16.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/aio_iiro_16.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/aio_iiro_16.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ Configuration Options:
 #include <linux/module.h>
 #include "../comedidev.h"
 
-#define AIO_IIRO_16_SIZE	0x08
 #define AIO_IIRO_16_RELAY_0_7	0x00
 #define AIO_IIRO_16_INPUT_0_7	0x01
 #define AIO_IIRO_16_IRQ		0x02
@@ -74,7 +73,7 @@ static int aio_iiro_16_attach(struct com
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], AIO_IIRO_16_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x8);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amcc_s5933.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amcc_s5933.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amcc_s5933.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amcc_s5933.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 #define  AMCC_OP_REG_MCSR_NVCMD  (AMCC_OP_REG_MCSR + 3)	/* Command in byte 3 */
 
 #define AMCC_FIFO_DEPTH_DWORD	8
-#define AMCC_FIFO_DEPTH_BYTES	(8 * sizeof (u32))
+#define AMCC_FIFO_DEPTH_BYTES	(8 * sizeof(u32))
 
 /****************************************************************************/
 /* AMCC - PCI Interrupt Control/Status Register                            */
@@ -52,8 +52,10 @@
 #define INTCSR_INBOX_BYTE(x)	(((x) & 0x3) << 8)
 #define INTCSR_INBOX_SELECT(x)	(((x) & 0x3) << 10)
 #define INTCSR_INBOX_FULL_INT	0x1000	/*  enable inbox full interrupt */
-#define INTCSR_INBOX_INTR_STATUS	0x20000	/*  read, or write clear inbox full interrupt */
-#define INTCSR_INTR_ASSERTED	0x800000	/*  read only, interrupt asserted */
+/* read, or write clear inbox full interrupt */
+#define INTCSR_INBOX_INTR_STATUS	0x20000
+/* read only, interrupt asserted */
+#define INTCSR_INTR_ASSERTED	0x800000
 
 /****************************************************************************/
 /* AMCC - PCI non-volatile ram command register (byte 3 of master control/status register) */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200.c	2014-09-28 17:29:07.000000000 -0400
@@ -278,8 +278,7 @@ static int dio200_attach(struct comedi_d
 	ret = comedi_request_region(dev, it->options[0], thisboard->mainsize);
 	if (ret)
 		return ret;
-	devpriv->io.u.iobase = dev->iobase;
-	devpriv->io.regtype = io_regtype;
+
 	return amplc_dio200_common_attach(dev, irq, 0);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200_common.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200_common.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -151,13 +151,12 @@ static unsigned char dio200_read8(struct
 				  unsigned int offset)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
 
 	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		return inb(devpriv->io.u.iobase + offset);
-	else
-		return readb(devpriv->io.u.membase + offset);
+
+	if (dev->mmio)
+		return readb(dev->mmio + offset);
+	return inb(dev->iobase + offset);
 }
 
 /*
@@ -167,13 +166,13 @@ static void dio200_write8(struct comedi_
 			  unsigned char val)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
 
 	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		outb(val, devpriv->io.u.iobase + offset);
+
+	if (dev->mmio)
+		writeb(val, dev->mmio + offset);
 	else
-		writeb(val, devpriv->io.u.membase + offset);
+		outb(val, dev->iobase + offset);
 }
 
 /*
@@ -183,13 +182,12 @@ static unsigned int dio200_read32(struct
 				  unsigned int offset)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
 
 	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		return inl(devpriv->io.u.iobase + offset);
-	else
-		return readl(devpriv->io.u.membase + offset);
+
+	if (dev->mmio)
+		return readl(dev->mmio + offset);
+	return inl(dev->iobase + offset);
 }
 
 /*
@@ -199,13 +197,13 @@ static void dio200_write32(struct comedi
 			   unsigned int val)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
 
 	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		outl(val, devpriv->io.u.iobase + offset);
+
+	if (dev->mmio)
+		writel(val, dev->mmio + offset);
 	else
-		writel(val, devpriv->io.u.membase + offset);
+		outl(val, dev->iobase + offset);
 }
 
 /*
@@ -327,7 +325,7 @@ static void dio200_read_scan_intr(struct
 		/* Error!  Stop acquisition.  */
 		dio200_stop_intr(dev, s);
 		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
-		comedi_error(dev, "buffer overflow");
+		dev_err(dev->class_dev, "buffer overflow\n");
 	}
 
 	/* Check for end of acquisition. */
@@ -1197,13 +1195,10 @@ EXPORT_SYMBOL_GPL(amplc_dio200_common_at
 
 void amplc_dio200_common_detach(struct comedi_device *dev)
 {
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	if (!thisboard || !devpriv)
-		return;
-	if (dev->irq)
+	if (dev->irq) {
 		free_irq(dev->irq, dev);
+		dev->irq = 0;
+	}
 }
 EXPORT_SYMBOL_GPL(amplc_dio200_common_detach);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200.h	2014-09-28 17:29:07.000000000 -0400
@@ -28,18 +28,6 @@
 #define DIO200_PCIE_IO_SIZE	0x4000
 
 /*
- * Register region.
- */
-enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype };
-struct dio200_region {
-	union {
-		unsigned long iobase;		/* I/O base address */
-		unsigned char __iomem *membase;	/* mapped MMIO base address */
-	} u;
-	enum dio200_regtype regtype;
-};
-
-/*
  * Subdevice types.
  */
 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
@@ -75,7 +63,6 @@ struct dio200_board {
  * Comedi device private data.
  */
 struct dio200_private {
-	struct dio200_region io;	/* Register region */
 	int intr_sd;
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200_pci.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200_pci.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_dio200_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_dio200_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -228,13 +228,6 @@
 
 #include "amplc_dio200.h"
 
-/* PCI IDs */
-#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
-#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
-#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
-#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
-#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
-
 /*
  * Board descriptions.
  */
@@ -394,16 +387,14 @@ static int dio200_pci_auto_attach(struct
 		return -EINVAL;
 	}
 	if (pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) {
-		devpriv->io.u.membase = pci_ioremap_bar(pci_dev, bar);
-		if (!devpriv->io.u.membase) {
+		dev->mmio = pci_ioremap_bar(pci_dev, bar);
+		if (!dev->mmio) {
 			dev_err(dev->class_dev,
 				"error! cannot remap registers\n");
 			return -ENOMEM;
 		}
-		devpriv->io.regtype = mmio_regtype;
 	} else {
-		devpriv->io.u.iobase = pci_resource_start(pci_dev, bar);
-		devpriv->io.regtype = io_regtype;
+		dev->iobase = pci_resource_start(pci_dev, bar);
 	}
 	switch (context_model) {
 	case pcie215_model:
@@ -421,14 +412,9 @@ static int dio200_pci_auto_attach(struct
 
 static void dio200_pci_detach(struct comedi_device *dev)
 {
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	if (!thisboard || !devpriv)
-		return;
 	amplc_dio200_common_detach(dev);
-	if (devpriv->io.regtype == mmio_regtype)
-		iounmap(devpriv->io.u.membase);
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
@@ -440,22 +426,11 @@ static struct comedi_driver dio200_pci_c
 };
 
 static const struct pci_device_id dio200_pci_table[] = {
-	{
-		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215),
-		pci215_model
-	}, {
-		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272),
-		pci272_model
-	}, {
-		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236),
-		pcie236_model
-	}, {
-		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215),
-		pcie215_model
-	}, {
-		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296),
-		pcie296_model
-	},
+	{ PCI_VDEVICE(AMPLICON, 0x000b), pci215_model },
+	{ PCI_VDEVICE(AMPLICON, 0x000a), pci272_model },
+	{ PCI_VDEVICE(AMPLICON, 0x0011), pcie236_model },
+	{ PCI_VDEVICE(AMPLICON, 0x0012), pcie215_model },
+	{ PCI_VDEVICE(AMPLICON, 0x0014), pcie296_model },
 	{0}
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,444 +1,53 @@
 /*
-    comedi/drivers/amplc_pc236.c
-    Driver for Amplicon PC36AT and PCI236 DIO boards.
-
-    Copyright (C) 2002 MEV Ltd. <http://www.mev.co.uk/>
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.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.
-*/
-/*
-Driver: amplc_pc236
-Description: Amplicon PC36AT, PCI236
-Author: Ian Abbott <abbotti@mev.co.uk>
-Devices: [Amplicon] PC36AT (pc36at), PCI236 (pci236 or amplc_pc236)
-Updated: Wed, 01 Apr 2009 15:41:25 +0100
-Status: works
-
-Configuration options - PC36AT:
-  [0] - I/O port base address
-  [1] - IRQ (optional)
-
-Configuration options - PCI236:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first available PCI device will be
-  used.
-
-The PC36AT ISA board and PCI236 PCI board have a single 8255 appearing
-as subdevice 0.
-
-Subdevice 1 pretends to be a digital input device, but it always returns
-0 when read. However, if you run a command with scan_begin_src=TRIG_EXT,
-a rising edge on port C bit 3 acts as an external trigger, which can be
-used to wake up tasks.  This is like the comedi_parport device, but the
-only way to physically disable the interrupt on the PC36AT is to remove
-the IRQ jumper.  If no interrupt is connected, then subdevice 1 is
-unused.
-*/
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
-#include "8255.h"
-#include "plx9052.h"
-
-#define PC236_DRIVER_NAME	"amplc_pc236"
-
-#define DO_ISA	IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)
-#define DO_PCI	IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
-
-/* PCI236 PCI configuration register information */
-#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
-#define PCI_DEVICE_ID_INVALID 0xffff
-
-/* PC36AT / PCI236 registers */
-
-#define PC236_IO_SIZE		4
-#define PC236_LCR_IO_SIZE	128
-
-/* Disable, and clear, interrupts */
-#define PCI236_INTR_DISABLE	(PLX9052_INTCSR_LI1POL |	\
-				 PLX9052_INTCSR_LI2POL |	\
-				 PLX9052_INTCSR_LI1SEL |	\
-				 PLX9052_INTCSR_LI1CLRINT)
-
-/* Enable, and clear, interrupts */
-#define PCI236_INTR_ENABLE	(PLX9052_INTCSR_LI1ENAB |	\
-				 PLX9052_INTCSR_LI1POL |	\
-				 PLX9052_INTCSR_LI2POL |	\
-				 PLX9052_INTCSR_PCIENAB |	\
-				 PLX9052_INTCSR_LI1SEL |	\
-				 PLX9052_INTCSR_LI1CLRINT)
-
-/*
- * Board descriptions for Amplicon PC36AT and PCI236.
- */
-
-enum pc236_bustype { isa_bustype, pci_bustype };
-enum pc236_model { pc36at_model, pci236_model, anypci_model };
-
-struct pc236_board {
-	const char *name;
-	unsigned short devid;
-	enum pc236_bustype bustype;
-	enum pc236_model model;
-};
-static const struct pc236_board pc236_boards[] = {
-#if DO_ISA
-	{
-		.name = "pc36at",
-		.bustype = isa_bustype,
-		.model = pc36at_model,
-	},
-#endif
-#if DO_PCI
-	{
-		.name = "pci236",
-		.devid = PCI_DEVICE_ID_AMPLICON_PCI236,
-		.bustype = pci_bustype,
-		.model = pci236_model,
-	},
-	{
-		.name = PC236_DRIVER_NAME,
-		.devid = PCI_DEVICE_ID_INVALID,
-		.bustype = pci_bustype,
-		.model = anypci_model,	/* wildcard */
-	},
-#endif
-};
-
-/* this structure is for data unique to this hardware driver.  If
-   several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.
- */
-struct pc236_private {
-	unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
-	int enable_irq;
-};
-
-/* test if ISA supported and this is an ISA board */
-static inline bool is_isa_board(const struct pc236_board *board)
-{
-	return DO_ISA && board->bustype == isa_bustype;
-}
-
-/* test if PCI supported and this is a PCI board */
-static inline bool is_pci_board(const struct pc236_board *board)
-{
-	return DO_PCI && board->bustype == pci_bustype;
-}
-
-/*
- * This function looks for a board matching the supplied PCI device.
- */
-static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(pc236_boards); i++)
-		if (is_pci_board(&pc236_boards[i]) &&
-		    pci_dev->device == pc236_boards[i].devid)
-			return &pc236_boards[i];
-	return NULL;
-}
-
-/*
- * This function looks for a PCI device matching the requested board name,
- * bus and slot.
- */
-static struct pci_dev *pc236_find_pci_dev(struct comedi_device *dev,
-					  struct comedi_devconfig *it)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct pci_dev *pci_dev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
-
-	for_each_pci_dev(pci_dev) {
-		if (bus || slot) {
-			if (bus != pci_dev->bus->number ||
-			    slot != PCI_SLOT(pci_dev->devfn))
-				continue;
-		}
-		if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
-			continue;
-
-		if (thisboard->model == anypci_model) {
-			/* Wildcard board matches any supported PCI board. */
-			const struct pc236_board *foundboard;
-
-			foundboard = pc236_find_pci_board(pci_dev);
-			if (foundboard == NULL)
-				continue;
-			/* Replace wildcard board_ptr. */
-			dev->board_ptr = foundboard;
-		} else {
-			/* Match specific model name. */
-			if (pci_dev->device != thisboard->devid)
-				continue;
-		}
-		return pci_dev;
-	}
-	dev_err(dev->class_dev,
-		"No supported board found! (req. bus %d, slot %d)\n",
-		bus, slot);
-	return NULL;
-}
-
-/*
- * This function is called to mark the interrupt as disabled (no command
- * configured on subdevice 1) and to physically disable the interrupt
- * (not possible on the PC36AT, except by removing the IRQ jumper!).
- */
-static void pc236_intr_disable(struct comedi_device *dev)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct pc236_private *devpriv = dev->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->enable_irq = 0;
-	if (is_pci_board(thisboard))
-		outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-}
-
-/*
- * This function is called to mark the interrupt as enabled (a command
- * configured on subdevice 1) and to physically enable the interrupt
- * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!).
- */
-static void pc236_intr_enable(struct comedi_device *dev)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct pc236_private *devpriv = dev->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->enable_irq = 1;
-	if (is_pci_board(thisboard))
-		outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-}
-
-/*
- * This function is called when an interrupt occurs to check whether
- * the interrupt has been marked as enabled and was generated by the
- * board.  If so, the function prepares the hardware for the next
- * interrupt.
- * Returns 0 if the interrupt should be ignored.
- */
-static int pc236_intr_check(struct comedi_device *dev)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct pc236_private *devpriv = dev->private;
-	int retval = 0;
-	unsigned long flags;
-	unsigned int intcsr;
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	if (devpriv->enable_irq) {
-		retval = 1;
-		if (is_pci_board(thisboard)) {
-			intcsr = inl(devpriv->lcr_iobase + PLX9052_INTCSR);
-			if (!(intcsr & PLX9052_INTCSR_LI1STAT)) {
-				retval = 0;
-			} else {
-				/* Clear interrupt and keep it enabled. */
-				outl(PCI236_INTR_ENABLE,
-				     devpriv->lcr_iobase + PLX9052_INTCSR);
-			}
-		}
-	}
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	return retval;
-}
-
-/*
- * Input from subdevice 1.
- * Copied from the comedi_parport driver.
- */
-static int pc236_intr_insn(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
-			   unsigned int *data)
-{
-	data[1] = 0;
-	return insn->n;
-}
-
-/*
- * Subdevice 1 command test.
- * Copied from the comedi_parport driver.
- */
-static int pc236_intr_cmdtest(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_cmd *cmd)
-{
-	int err = 0;
-
-	/* Step 1 : check if triggers are trivially valid */
-
-	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
-
-	if (err)
-		return 1;
-
-	/* Step 2a : make sure trigger sources are unique */
-	/* Step 2b : and mutually compatible */
-
-	if (err)
-		return 2;
-
-	/* Step 3: check it arguments are trivially valid */
-
-	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
-
-	if (err)
-		return 3;
-
-	/* step 4: ignored */
-
-	if (err)
-		return 4;
-
-	return 0;
-}
-
-/*
- * Subdevice 1 command.
- */
-static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	pc236_intr_enable(dev);
-
-	return 0;
-}
-
-/*
- * Subdevice 1 cancel command.
+ * comedi/drivers/amplc_pc236.c
+ * Driver for Amplicon PC36AT DIO boards.
+ *
+ * Copyright (C) 2002 MEV Ltd. <http://www.mev.co.uk/>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
  */
-static int pc236_intr_cancel(struct comedi_device *dev,
-			     struct comedi_subdevice *s)
-{
-	pc236_intr_disable(dev);
-
-	return 0;
-}
-
 /*
- * Interrupt service routine.
- * Based on the comedi_parport driver.
+ * Driver: amplc_pc236
+ * Description: Amplicon PC36AT
+ * Author: Ian Abbott <abbotti@mev.co.uk>
+ * Devices: [Amplicon] PC36AT (pc36at)
+ * Updated: Fri, 25 Jul 2014 15:32:40 +0000
+ * Status: works
+ *
+ * Configuration options - PC36AT:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (optional)
+ *
+ * The PC36AT board has a single 8255 appearing as subdevice 0.
+ *
+ * Subdevice 1 pretends to be a digital input device, but it always returns
+ * 0 when read. However, if you run a command with scan_begin_src=TRIG_EXT,
+ * a rising edge on port C bit 3 acts as an external trigger, which can be
+ * used to wake up tasks.  This is like the comedi_parport device, but the
+ * only way to physically disable the interrupt on the PC36AT is to remove
+ * the IRQ jumper.  If no interrupt is connected, then subdevice 1 is
+ * unused.
  */
-static irqreturn_t pc236_interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct comedi_subdevice *s = dev->read_subdev;
-	int handled;
-
-	handled = pc236_intr_check(dev);
-	if (dev->attached && handled) {
-		comedi_buf_put(s, 0);
-		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
-		comedi_event(dev, s);
-	}
-	return IRQ_RETVAL(handled);
-}
-
-static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
-			       unsigned int irq, unsigned long req_irq_flags)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-	struct comedi_subdevice *s;
-	int ret;
-
-	dev->board_name = thisboard->name;
-	dev->iobase = iobase;
 
-	ret = comedi_alloc_subdevices(dev, 2);
-	if (ret)
-		return ret;
-
-	s = &dev->subdevices[0];
-	/* digital i/o subdevice (8255) */
-	ret = subdev_8255_init(dev, s, NULL, iobase);
-	if (ret)
-		return ret;
-
-	s = &dev->subdevices[1];
-	dev->read_subdev = s;
-	s->type = COMEDI_SUBD_UNUSED;
-	pc236_intr_disable(dev);
-	if (irq) {
-		if (request_irq(irq, pc236_interrupt, req_irq_flags,
-				PC236_DRIVER_NAME, dev) >= 0) {
-			dev->irq = irq;
-			s->type = COMEDI_SUBD_DI;
-			s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-			s->n_chan = 1;
-			s->maxdata = 1;
-			s->range_table = &range_digital;
-			s->insn_bits = pc236_intr_insn;
-			s->len_chanlist	= 1;
-			s->do_cmdtest = pc236_intr_cmdtest;
-			s->do_cmd = pc236_intr_cmd;
-			s->cancel = pc236_intr_cancel;
-		}
-	}
-
-	return 0;
-}
-
-static int pc236_pci_common_attach(struct comedi_device *dev,
-				   struct pci_dev *pci_dev)
-{
-	struct pc236_private *devpriv = dev->private;
-	unsigned long iobase;
-	int ret;
-
-	comedi_set_hw_dev(dev, &pci_dev->dev);
+#include <linux/module.h>
 
-	ret = comedi_pci_enable(dev);
-	if (ret)
-		return ret;
+#include "../comedidev.h"
 
-	devpriv->lcr_iobase = pci_resource_start(pci_dev, 1);
-	iobase = pci_resource_start(pci_dev, 2);
-	return pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
-}
+#include "amplc_pc236.h"
 
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.  If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
 static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-	const struct pc236_board *thisboard = comedi_board(dev);
 	struct pc236_private *devpriv;
 	int ret;
 
@@ -446,127 +55,31 @@ static int pc236_attach(struct comedi_de
 	if (!devpriv)
 		return -ENOMEM;
 
-	/* Process options according to bus type. */
-	if (is_isa_board(thisboard)) {
-		ret = comedi_request_region(dev, it->options[0], PC236_IO_SIZE);
-		if (ret)
-			return ret;
-
-		return pc236_common_attach(dev, dev->iobase, it->options[1], 0);
-	} else if (is_pci_board(thisboard)) {
-		struct pci_dev *pci_dev;
-
-		pci_dev = pc236_find_pci_dev(dev, it);
-		if (!pci_dev)
-			return -EIO;
-		return pc236_pci_common_attach(dev, pci_dev);
-	} else {
-		dev_err(dev->class_dev, PC236_DRIVER_NAME
-			": BUG! cannot determine board type!\n");
-		return -EINVAL;
-	}
-}
-
-/*
- * The auto_attach hook is called at PCI probe time via
- * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
- * There should be a board entry matching the supplied PCI device.
- */
-static int pc236_auto_attach(struct comedi_device *dev,
-				       unsigned long context_unused)
-{
-	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
-	struct pc236_private *devpriv;
-
-	if (!DO_PCI)
-		return -EINVAL;
-
-	dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
-		 pci_name(pci_dev));
-
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
+	ret = comedi_request_region(dev, it->options[0], 0x4);
+	if (ret)
+		return ret;
 
-	dev->board_ptr = pc236_find_pci_board(pci_dev);
-	if (dev->board_ptr == NULL) {
-		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
-		return -EINVAL;
-	}
-	/*
-	 * Need to 'get' the PCI device to match the 'put' in pc236_detach().
-	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
-	 * support for manual attachment of PCI devices via pc236_attach()
-	 * has been removed.
-	 */
-	pci_dev_get(pci_dev);
-	return pc236_pci_common_attach(dev, pci_dev);
+	return amplc_pc236_common_attach(dev, dev->iobase, it->options[1], 0);
 }
 
-static void pc236_detach(struct comedi_device *dev)
-{
-	const struct pc236_board *thisboard = comedi_board(dev);
-
-	if (!thisboard)
-		return;
-	if (dev->iobase)
-		pc236_intr_disable(dev);
-	if (is_isa_board(thisboard)) {
-		comedi_legacy_detach(dev);
-	} else if (is_pci_board(thisboard)) {
-		struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-		if (dev->irq)
-			free_irq(dev->irq, dev);
-		comedi_pci_disable(dev);
-		if (pcidev)
-			pci_dev_put(pcidev);
-	}
-}
+static const struct pc236_board pc236_boards[] = {
+	{
+		.name = "pc36at",
+	},
+};
 
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
 static struct comedi_driver amplc_pc236_driver = {
-	.driver_name = PC236_DRIVER_NAME,
+	.driver_name = "amplc_pc236",
 	.module = THIS_MODULE,
 	.attach = pc236_attach,
-	.auto_attach = pc236_auto_attach,
-	.detach = pc236_detach,
+	.detach = comedi_legacy_detach,
 	.board_name = &pc236_boards[0].name,
 	.offset = sizeof(struct pc236_board),
 	.num_names = ARRAY_SIZE(pc236_boards),
 };
 
-#if DO_PCI
-static const struct pci_device_id pc236_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, pc236_pci_table);
-
-static int amplc_pc236_pci_probe(struct pci_dev *dev,
-				 const struct pci_device_id *id)
-{
-	return comedi_pci_auto_config(dev, &amplc_pc236_driver,
-				      id->driver_data);
-}
-
-static struct pci_driver amplc_pc236_pci_driver = {
-	.name = PC236_DRIVER_NAME,
-	.id_table = pc236_pci_table,
-	.probe = &amplc_pc236_pci_probe,
-	.remove		= comedi_pci_auto_unconfig,
-};
-
-module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver);
-#else
 module_comedi_driver(amplc_pc236_driver);
-#endif
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Amplicon PC36AT DIO boards");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236_common.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236_common.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ * comedi/drivers/amplc_pc236_common.c
+ * Common support code for "amplc_pc236" and "amplc_pci236".
+ *
+ * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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/module.h>
+#include <linux/interrupt.h>
+
+#include "../comedidev.h"
+
+#include "amplc_pc236.h"
+#include "comedi_fc.h"
+#include "8255.h"
+
+static void pc236_intr_update(struct comedi_device *dev, bool enable)
+{
+	const struct pc236_board *thisboard = comedi_board(dev);
+	struct pc236_private *devpriv = dev->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->spinlock, flags);
+	devpriv->enable_irq = enable;
+	if (thisboard->intr_update_cb)
+		thisboard->intr_update_cb(dev, enable);
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+}
+
+/*
+ * This function is called when an interrupt occurs to check whether
+ * the interrupt has been marked as enabled and was generated by the
+ * board.  If so, the function prepares the hardware for the next
+ * interrupt.
+ * Returns false if the interrupt should be ignored.
+ */
+static bool pc236_intr_check(struct comedi_device *dev)
+{
+	const struct pc236_board *thisboard = comedi_board(dev);
+	struct pc236_private *devpriv = dev->private;
+	bool retval = false;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->spinlock, flags);
+	if (devpriv->enable_irq) {
+		if (thisboard->intr_chk_clr_cb)
+			retval = thisboard->intr_chk_clr_cb(dev);
+		else
+			retval = true;
+	}
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+
+	return retval;
+}
+
+static int pc236_intr_insn(struct comedi_device *dev,
+			   struct comedi_subdevice *s, struct comedi_insn *insn,
+			   unsigned int *data)
+{
+	data[1] = 0;
+	return insn->n;
+}
+
+static int pc236_intr_cmdtest(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_cmd *cmd)
+{
+	int err = 0;
+
+	/* Step 1 : check if triggers are trivially valid */
+
+	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+
+	if (err)
+		return 1;
+
+	/* Step 2a : make sure trigger sources are unique */
+	/* Step 2b : and mutually compatible */
+
+	if (err)
+		return 2;
+
+	/* Step 3: check it arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+	if (err)
+		return 3;
+
+	/* step 4: ignored */
+
+	if (err)
+		return 4;
+
+	return 0;
+}
+
+static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	pc236_intr_update(dev, true);
+
+	return 0;
+}
+
+static int pc236_intr_cancel(struct comedi_device *dev,
+			     struct comedi_subdevice *s)
+{
+	pc236_intr_update(dev, false);
+
+	return 0;
+}
+
+static irqreturn_t pc236_interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct comedi_subdevice *s = dev->read_subdev;
+	bool handled;
+
+	handled = pc236_intr_check(dev);
+	if (dev->attached && handled) {
+		comedi_buf_put(s, 0);
+		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+		comedi_event(dev, s);
+	}
+	return IRQ_RETVAL(handled);
+}
+
+int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
+			      unsigned int irq, unsigned long req_irq_flags)
+{
+	struct comedi_subdevice *s;
+	int ret;
+
+	dev->iobase = iobase;
+
+	ret = comedi_alloc_subdevices(dev, 2);
+	if (ret)
+		return ret;
+
+	s = &dev->subdevices[0];
+	/* digital i/o subdevice (8255) */
+	ret = subdev_8255_init(dev, s, NULL, iobase);
+	if (ret)
+		return ret;
+
+	s = &dev->subdevices[1];
+	dev->read_subdev = s;
+	s->type = COMEDI_SUBD_UNUSED;
+	pc236_intr_update(dev, false);
+	if (irq) {
+		if (request_irq(irq, pc236_interrupt, req_irq_flags,
+				dev->board_name, dev) >= 0) {
+			dev->irq = irq;
+			s->type = COMEDI_SUBD_DI;
+			s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+			s->n_chan = 1;
+			s->maxdata = 1;
+			s->range_table = &range_digital;
+			s->insn_bits = pc236_intr_insn;
+			s->len_chanlist	= 1;
+			s->do_cmdtest = pc236_intr_cmdtest;
+			s->do_cmd = pc236_intr_cmd;
+			s->cancel = pc236_intr_cancel;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amplc_pc236_common_attach);
+
+static int __init amplc_pc236_common_init(void)
+{
+	return 0;
+}
+module_init(amplc_pc236_common_init);
+
+static void __exit amplc_pc236_common_exit(void)
+{
+}
+module_exit(amplc_pc236_common_exit);
+
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi helper for amplc_pc236 and amplc_pci236");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc236.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc236.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * comedi/drivers/amplc_pc236.h
+ * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common".
+ *
+ * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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 AMPLC_PC236_H_INCLUDED
+#define AMPLC_PC236_H_INCLUDED
+
+#include <linux/types.h>
+
+struct comedi_device;
+
+struct pc236_board {
+	const char *name;
+	void (*intr_update_cb)(struct comedi_device *dev, bool enable);
+	bool (*intr_chk_clr_cb)(struct comedi_device *dev);
+};
+
+struct pc236_private {
+	unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
+	bool enable_irq;
+};
+
+int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
+			      unsigned int irq, unsigned long req_irq_flags);
+
+#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc263.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc263.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pc263.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pc263.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,10 +36,7 @@ The state of the outputs can be read.
 #include <linux/module.h>
 #include "../comedidev.h"
 
-#define PC263_DRIVER_NAME	"amplc_pc263"
-
 /* PC263 registers */
-#define PC263_IO_SIZE	2
 
 /*
  * Board descriptions for Amplicon PC263.
@@ -75,7 +72,7 @@ static int pc263_attach(struct comedi_de
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], PC263_IO_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x2);
 	if (ret)
 		return ret;
 
@@ -98,7 +95,7 @@ static int pc263_attach(struct comedi_de
 }
 
 static struct comedi_driver amplc_pc263_driver = {
-	.driver_name = PC263_DRIVER_NAME,
+	.driver_name = "amplc_pc263",
 	.module = THIS_MODULE,
 	.attach = pc263_attach,
 	.detach = comedi_legacy_detach,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci224.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci224.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci224.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci224.c	2014-09-28 17:29:07.000000000 -0400
@@ -108,8 +108,6 @@ Caveats:
 #include "comedi_fc.h"
 #include "8253.h"
 
-#define DRIVER_NAME	"amplc_pci224"
-
 /*
  * PCI IDs.
  */
@@ -120,7 +118,6 @@ Caveats:
 /*
  * PCI224/234 i/o space 1 (PCIBAR2) registers.
  */
-#define PCI224_IO1_SIZE	0x20	/* Size of i/o space 1 (8-bit registers) */
 #define PCI224_Z2_CT0	0x14	/* 82C54 counter/timer 0 */
 #define PCI224_Z2_CT1	0x15	/* 82C54 counter/timer 1 */
 #define PCI224_Z2_CT2	0x16	/* 82C54 counter/timer 2 */
@@ -133,7 +130,6 @@ Caveats:
 /*
  * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
  */
-#define PCI224_IO2_SIZE	0x10	/* Size of i/o space 2 (16-bit registers). */
 #define PCI224_DACDATA	0x00	/* (w-o) DAC FIFO data. */
 #define PCI224_SOFTTRIG	0x00	/* (r-o) DAC software scan trigger. */
 #define PCI224_DACCON	0x02	/* (r/w) DAC status/configuration. */
@@ -354,7 +350,7 @@ static const struct pci224_board pci224_
 	 .ao_bits = 16,
 	 },
 	{
-	 .name = DRIVER_NAME,
+	 .name = "amplc_pci224",
 	 .devid = PCI_DEVICE_ID_INVALID,
 	 .model = any_model,	/* wildcard */
 	 },
@@ -1206,8 +1202,8 @@ static int pci224_attach_common(struct c
 		if (options) {
 			for (n = 2; n < 3 + s->n_chan; n++) {
 				if (options[n] < 0 || options[n] > 1) {
-					dev_warn(dev->class_dev, DRIVER_NAME
-						 ": warning! bad options[%u]=%d\n",
+					dev_warn(dev->class_dev,
+						 "warning! bad options[%u]=%d\n",
 						 n, options[n]);
 				}
 			}
@@ -1237,8 +1233,8 @@ static int pci224_attach_common(struct c
 			devpriv->hwrange = hwrange_pci224_external;
 		} else {
 			if (options && options[2] != 0) {
-				dev_warn(dev->class_dev, DRIVER_NAME
-					 ": warning! bad options[2]=%d\n",
+				dev_warn(dev->class_dev,
+					 "warning! bad options[2]=%d\n",
 					 options[2]);
 			}
 			s->range_table = &range_pci224_internal;
@@ -1250,14 +1246,13 @@ static int pci224_attach_common(struct c
 
 	if (irq) {
 		ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
-				  DRIVER_NAME, dev);
+				  dev->board_name, dev);
 		if (ret < 0) {
 			dev_err(dev->class_dev,
 				"error! unable to allocate irq %u\n", irq);
 			return ret;
-		} else {
-			dev->irq = irq;
 		}
+		dev->irq = irq;
 	}
 
 	return 0;
@@ -1268,7 +1263,7 @@ static int pci224_attach(struct comedi_d
 	struct pci224_private *devpriv;
 	struct pci_dev *pci_dev;
 
-	dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
+	dev_info(dev->class_dev, "attach\n");
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
@@ -1287,8 +1282,7 @@ pci224_auto_attach(struct comedi_device
 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
 	struct pci224_private *devpriv;
 
-	dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n",
-		 pci_name(pci_dev));
+	dev_info(dev->class_dev, "attach pci %s\n", pci_name(pci_dev));
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
@@ -1297,7 +1291,7 @@ pci224_auto_attach(struct comedi_device
 	dev->board_ptr = pci224_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
 		dev_err(dev->class_dev,
-			DRIVER_NAME ": BUG! cannot determine board type!\n");
+			"BUG! cannot determine board type!\n");
 		return -EINVAL;
 	}
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci230.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci230.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci230.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci230.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,188 +1,189 @@
- /*
-    comedi/drivers/amplc_pci230.c
-    Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
-
-    Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.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.
-  */
 /*
-Driver: amplc_pci230
-Description: Amplicon PCI230, PCI260 Multifunction I/O boards
-Author: Allan Willcox <allanwillcox@ozemail.com.au>,
-  Steve D Sharples <steve.sharples@nottingham.ac.uk>,
-  Ian Abbott <abbotti@mev.co.uk>
-Updated: Wed, 22 Oct 2008 12:34:49 +0100
-Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
-  PCI230+ (pci230+ or amplc_pci230),
-  PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
-Status: works
-
-Configuration options:
-  [0] - PCI bus of device (optional).
-  [1] - PCI slot of device (optional).
-          If bus/slot is not specified, the first available PCI device
-          will be used.
-
-Configuring a "amplc_pci230" will match any supported card and it will
-choose the best match, picking the "+" models if possible.  Configuring
-a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
-a PCI230.  Configuring a "pci260" will match a PCI260 or PCI260+ card
-and it will be treated as a PCI260.  Configuring a "pci230+" will match
-a PCI230+ card.  Configuring a "pci260+" will match a PCI260+ card.
-
-Subdevices:
-
-                PCI230(+)    PCI260(+)
-                ---------    ---------
-  Subdevices       3            1
-        0          AI           AI
-	1          AO
-	2          DIO
-
-AI Subdevice:
-
-  The AI subdevice has 16 single-ended channels or 8 differential
-  channels.
-
-  The PCI230 and PCI260 cards have 12-bit resolution.  The PCI230+ and
-  PCI260+ cards have 16-bit resolution.
-
-  For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
-  inputs 14 and 15 for channel 7).  If the card is physically a PCI230
-  or PCI260 then it actually uses a "pseudo-differential" mode where the
-  inputs are sampled a few microseconds apart.  The PCI230+ and PCI260+
-  use true differential sampling.  Another difference is that if the
-  card is physically a PCI230 or PCI260, the inverting input is 2N,
-  whereas for a PCI230+ or PCI260+ the inverting input is 2N+1.  So if a
-  PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
-  PCI260+) and differential mode is used, the differential inputs need
-  to be physically swapped on the connector.
-
-  The following input ranges are supported:
-
-    0 => [-10, +10] V
-    1 => [-5, +5] V
-    2 => [-2.5, +2.5] V
-    3 => [-1.25, +1.25] V
-    4 => [0, 10] V
-    5 => [0, 5] V
-    6 => [0, 2.5] V
-
-AI Commands:
-
-  +=========+==============+===========+============+==========+
-  |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
-  +=========+==============+===========+============+==========+
-  |TRIG_NOW | TRIG_FOLLOW  |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
-  |TRIG_INT |              |TRIG_EXT(3)|            |TRIG_COUNT|
-  |         |              |TRIG_INT   |            |          |
-  |         |--------------|-----------|            |          |
-  |         | TRIG_TIMER(1)|TRIG_TIMER |            |          |
-  |         | TRIG_EXT(2)  |           |            |          |
-  |         | TRIG_INT     |           |            |          |
-  +---------+--------------+-----------+------------+----------+
-
-  Note 1: If AI command and AO command are used simultaneously, only
-          one may have scan_begin_src == TRIG_TIMER.
-
-  Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
-          DIO channel 16 (pin 49) which will need to be configured as
-          a digital input.  For PCI260+, the EXTTRIG/EXTCONVCLK input
-          (pin 17) is used instead.  For PCI230, scan_begin_src ==
-          TRIG_EXT is not supported.  The trigger is a rising edge
-          on the input.
-
-  Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
-          (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used.  The
-          convert_arg value is interpreted as follows:
-
-            convert_arg == (CR_EDGE | 0) => rising edge
-            convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
-            convert_arg == 0 => falling edge (backwards compatibility)
-            convert_arg == 1 => rising edge (backwards compatibility)
-
-  All entries in the channel list must use the same analogue reference.
-  If the analogue reference is not AREF_DIFF (not differential) each
-  pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
-  input range.  The input ranges used in the sequence must be all
-  bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6).  The channel
-  sequence must consist of 1 or more identical subsequences.  Within the
-  subsequence, channels must be in ascending order with no repeated
-  channels.  For example, the following sequences are valid: 0 1 2 3
-  (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
-  subsequence), 1 1 1 1 (repeated valid subsequence).  The following
-  sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
-  (incompletely repeated subsequence).  Some versions of the PCI230+ and
-  PCI260+ have a bug that requires a subsequence longer than one entry
-  long to include channel 0.
-
-AO Subdevice:
-
-  The AO subdevice has 2 channels with 12-bit resolution.
-
-  The following output ranges are supported:
-
-    0 => [0, 10] V
-    1 => [-10, +10] V
-
-AO Commands:
-
-  +=========+==============+===========+============+==========+
-  |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
-  +=========+==============+===========+============+==========+
-  |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW  | TRIG_COUNT |TRIG_NONE |
-  |         | TRIG_EXT(2)  |           |            |TRIG_COUNT|
-  |         | TRIG_INT     |           |            |          |
-  +---------+--------------+-----------+------------+----------+
-
-  Note 1: If AI command and AO command are used simultaneously, only
-          one may have scan_begin_src == TRIG_TIMER.
-
-  Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
-          configured as a PCI230+ and is only supported on later
-          versions of the card.  As a card configured as a PCI230+ is
-          not guaranteed to support external triggering, please consider
-          this support to be a bonus.  It uses the EXTTRIG/ EXTCONVCLK
-          input (PCI230+ pin 25).  Triggering will be on the rising edge
-          unless the CR_INVERT flag is set in scan_begin_arg.
-
-  The channels in the channel sequence must be in ascending order with
-  no repeats.  All entries in the channel sequence must use the same
-  output range.
-
-DIO Subdevice:
-
-  The DIO subdevice is a 8255 chip providing 24 DIO channels.  The DIO
-  channels are configurable as inputs or outputs in four groups:
-
-    Port A  - channels  0 to  7
-    Port B  - channels  8 to 15
-    Port CL - channels 16 to 19
-    Port CH - channels 20 to 23
+ * comedi/drivers/amplc_pci230.c
+ * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
+ *
+ * Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
+ */
 
-  Only mode 0 of the 8255 chip is supported.
+/*
+ * Driver: amplc_pci230
+ * Description: Amplicon PCI230, PCI260 Multifunction I/O boards
+ * Author: Allan Willcox <allanwillcox@ozemail.com.au>,
+ *   Steve D Sharples <steve.sharples@nottingham.ac.uk>,
+ *   Ian Abbott <abbotti@mev.co.uk>
+ * Updated: Wed, 22 Oct 2008 12:34:49 +0100
+ * Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
+ *   PCI230+ (pci230+ or amplc_pci230),
+ *   PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
+ * Status: works
+ *
+ * Configuration options:
+ *   [0] - PCI bus of device (optional).
+ *   [1] - PCI slot of device (optional).
+ *           If bus/slot is not specified, the first available PCI device
+ *           will be used.
+ *
+ * Configuring a "amplc_pci230" will match any supported card and it will
+ * choose the best match, picking the "+" models if possible.  Configuring
+ * a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
+ * a PCI230.  Configuring a "pci260" will match a PCI260 or PCI260+ card
+ * and it will be treated as a PCI260.  Configuring a "pci230+" will match
+ * a PCI230+ card.  Configuring a "pci260+" will match a PCI260+ card.
+ *
+ * Subdevices:
+ *
+ *                 PCI230(+)    PCI260(+)
+ *                 ---------    ---------
+ *   Subdevices       3            1
+ *         0          AI           AI
+ *         1          AO
+ *         2          DIO
+ *
+ * AI Subdevice:
+ *
+ *   The AI subdevice has 16 single-ended channels or 8 differential
+ *   channels.
+ *
+ *   The PCI230 and PCI260 cards have 12-bit resolution.  The PCI230+ and
+ *   PCI260+ cards have 16-bit resolution.
+ *
+ *   For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
+ *   inputs 14 and 15 for channel 7).  If the card is physically a PCI230
+ *   or PCI260 then it actually uses a "pseudo-differential" mode where the
+ *   inputs are sampled a few microseconds apart.  The PCI230+ and PCI260+
+ *   use true differential sampling.  Another difference is that if the
+ *   card is physically a PCI230 or PCI260, the inverting input is 2N,
+ *   whereas for a PCI230+ or PCI260+ the inverting input is 2N+1.  So if a
+ *   PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
+ *   PCI260+) and differential mode is used, the differential inputs need
+ *   to be physically swapped on the connector.
+ *
+ *   The following input ranges are supported:
+ *
+ *     0 => [-10, +10] V
+ *     1 => [-5, +5] V
+ *     2 => [-2.5, +2.5] V
+ *     3 => [-1.25, +1.25] V
+ *     4 => [0, 10] V
+ *     5 => [0, 5] V
+ *     6 => [0, 2.5] V
+ *
+ * AI Commands:
+ *
+ *   +=========+==============+===========+============+==========+
+ *   |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
+ *   +=========+==============+===========+============+==========+
+ *   |TRIG_NOW | TRIG_FOLLOW  |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
+ *   |TRIG_INT |              |TRIG_EXT(3)|            |TRIG_COUNT|
+ *   |         |              |TRIG_INT   |            |          |
+ *   |         |--------------|-----------|            |          |
+ *   |         | TRIG_TIMER(1)|TRIG_TIMER |            |          |
+ *   |         | TRIG_EXT(2)  |           |            |          |
+ *   |         | TRIG_INT     |           |            |          |
+ *   +---------+--------------+-----------+------------+----------+
+ *
+ *   Note 1: If AI command and AO command are used simultaneously, only
+ *           one may have scan_begin_src == TRIG_TIMER.
+ *
+ *   Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
+ *           DIO channel 16 (pin 49) which will need to be configured as
+ *           a digital input.  For PCI260+, the EXTTRIG/EXTCONVCLK input
+ *           (pin 17) is used instead.  For PCI230, scan_begin_src ==
+ *           TRIG_EXT is not supported.  The trigger is a rising edge
+ *           on the input.
+ *
+ *   Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
+ *           (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used.  The
+ *           convert_arg value is interpreted as follows:
+ *
+ *             convert_arg == (CR_EDGE | 0) => rising edge
+ *             convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
+ *             convert_arg == 0 => falling edge (backwards compatibility)
+ *             convert_arg == 1 => rising edge (backwards compatibility)
+ *
+ *   All entries in the channel list must use the same analogue reference.
+ *   If the analogue reference is not AREF_DIFF (not differential) each
+ *   pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
+ *   input range.  The input ranges used in the sequence must be all
+ *   bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6).  The channel
+ *   sequence must consist of 1 or more identical subsequences.  Within the
+ *   subsequence, channels must be in ascending order with no repeated
+ *   channels.  For example, the following sequences are valid: 0 1 2 3
+ *   (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
+ *   subsequence), 1 1 1 1 (repeated valid subsequence).  The following
+ *   sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
+ *   (incompletely repeated subsequence).  Some versions of the PCI230+ and
+ *   PCI260+ have a bug that requires a subsequence longer than one entry
+ *   long to include channel 0.
+ *
+ * AO Subdevice:
+ *
+ *   The AO subdevice has 2 channels with 12-bit resolution.
+ *   The following output ranges are supported:
+ *     0 => [0, 10] V
+ *     1 => [-10, +10] V
+ *
+ * AO Commands:
+ *
+ *   +=========+==============+===========+============+==========+
+ *   |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
+ *   +=========+==============+===========+============+==========+
+ *   |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW  | TRIG_COUNT |TRIG_NONE |
+ *   |         | TRIG_EXT(2)  |           |            |TRIG_COUNT|
+ *   |         | TRIG_INT     |           |            |          |
+ *   +---------+--------------+-----------+------------+----------+
+ *
+ *   Note 1: If AI command and AO command are used simultaneously, only
+ *           one may have scan_begin_src == TRIG_TIMER.
+ *
+ *   Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
+ *           configured as a PCI230+ and is only supported on later
+ *           versions of the card.  As a card configured as a PCI230+ is
+ *           not guaranteed to support external triggering, please consider
+ *           this support to be a bonus.  It uses the EXTTRIG/ EXTCONVCLK
+ *           input (PCI230+ pin 25).  Triggering will be on the rising edge
+ *           unless the CR_INVERT flag is set in scan_begin_arg.
+ *
+ *   The channels in the channel sequence must be in ascending order with
+ *   no repeats.  All entries in the channel sequence must use the same
+ *   output range.
+ *
+ * DIO Subdevice:
+ *
+ *   The DIO subdevice is a 8255 chip providing 24 DIO channels.  The DIO
+ *   channels are configurable as inputs or outputs in four groups:
+ *
+ *     Port A  - channels  0 to  7
+ *     Port B  - channels  8 to 15
+ *     Port CL - channels 16 to 19
+ *     Port CH - channels 20 to 23
+ *
+ *   Only mode 0 of the 8255 chip is supported.
+ *
+ *   Bit 0 of port C (DIO channel 16) is also used as an external scan
+ *   trigger input for AI commands on PCI230 and PCI230+, so would need to
+ *   be configured as an input to use it for that purpose.
+ */
 
-  Bit 0 of port C (DIO channel 16) is also used as an external scan
-  trigger input for AI commands on PCI230 and PCI230+, so would need to
-  be configured as an input to use it for that purpose.
-*/
 /*
-Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
-Support for PCI230+/260+, more triggered scan functionality, and workarounds
-for (or detection of) various hardware problems added by Ian Abbott.
-*/
+ * Extra triggered scan functionality, interrupt bug-fix added by Steve
+ * Sharples.  Support for PCI230+/260+, more triggered scan functionality,
+ * and workarounds for (or detection of) various hardware problems added
+ * by Ian Abbott.
+ */
 
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -195,15 +196,16 @@ for (or detection of) various hardware p
 #include "8253.h"
 #include "8255.h"
 
-/* PCI230 PCI configuration register information */
+/*
+ * PCI230 PCI configuration register information
+ */
 #define PCI_DEVICE_ID_PCI230 0x0000
 #define PCI_DEVICE_ID_PCI260 0x0006
 #define PCI_DEVICE_ID_INVALID 0xffff
 
-#define PCI230_IO1_SIZE 32	/* Size of I/O space 1 */
-#define PCI230_IO2_SIZE 16	/* Size of I/O space 2 */
-
-/* PCI230 i/o space 1 registers. */
+/*
+ * PCI230 i/o space 1 registers.
+ */
 #define PCI230_PPI_X_BASE	0x00	/* User PPI (82C55) base */
 #define PCI230_PPI_X_A		0x00	/* User PPI (82C55) port A */
 #define PCI230_PPI_X_B		0x01	/* User PPI (82C55) port B */
@@ -219,7 +221,9 @@ for (or detection of) various hardware p
 #define PCI230_INT_SCE		0x1E	/* Interrupt source mask (w) */
 #define PCI230_INT_STAT		0x1E	/* Interrupt status (r) */
 
-/* PCI230 i/o space 2 registers. */
+/*
+ * PCI230 i/o space 2 registers.
+ */
 #define PCI230_DACCON		0x00	/* DAC control */
 #define PCI230_DACOUT1		0x02	/* DAC channel 0 (w) */
 #define PCI230_DACOUT2		0x04	/* DAC channel 1 (w) (not FIFO mode) */
@@ -242,57 +246,64 @@ for (or detection of) various hardware p
 #define PCI230P2_DACSWTRIG	0x02	/* DAC soft trigger (FIFO mode) (r) */
 #define PCI230P2_DACEN		0x06	/* DAC channel enable (FIFO mode) */
 
-/* Convertor related constants. */
-#define PCI230_DAC_SETTLE 5	/* Analogue output settling time in Âµs */
-				/* (DAC itself is 1Âµs nominally). */
-#define PCI230_ADC_SETTLE 1	/* Analogue input settling time in Âµs */
-				/* (ADC itself is 1.6Âµs nominally but we poll
-				 * anyway). */
-#define PCI230_MUX_SETTLE 10	/* ADC MUX settling time in ÂµS */
-				/* - 10Âµs for se, 20Âµs de. */
-
-/* DACCON read-write values. */
-#define PCI230_DAC_OR_UNI		(0<<0)	/* Output range unipolar */
-#define PCI230_DAC_OR_BIP		(1<<0)	/* Output range bipolar */
-#define PCI230_DAC_OR_MASK		(1<<0)
-/* The following applies only if DAC FIFO support is enabled in the EXTFUNC
- * register (and only for PCI230+ hardware version 2 onwards). */
-#define PCI230P2_DAC_FIFO_EN		(1<<8)	/* FIFO enable */
-/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
- * hardware version 2 onwards). */
-#define PCI230P2_DAC_TRIG_NONE		(0<<2)	/* No trigger */
-#define PCI230P2_DAC_TRIG_SW		(1<<2)	/* Software trigger trigger */
-#define PCI230P2_DAC_TRIG_EXTP		(2<<2)	/* EXTTRIG +ve edge trigger */
-#define PCI230P2_DAC_TRIG_EXTN		(3<<2)	/* EXTTRIG -ve edge trigger */
-#define PCI230P2_DAC_TRIG_Z2CT0		(4<<2)	/* CT0-OUT +ve edge trigger */
-#define PCI230P2_DAC_TRIG_Z2CT1		(5<<2)	/* CT1-OUT +ve edge trigger */
-#define PCI230P2_DAC_TRIG_Z2CT2		(6<<2)	/* CT2-OUT +ve edge trigger */
-#define PCI230P2_DAC_TRIG_MASK		(7<<2)
-#define PCI230P2_DAC_FIFO_WRAP		(1<<7)	/* FIFO wraparound mode */
-#define PCI230P2_DAC_INT_FIFO_EMPTY	(0<<9)	/* FIFO interrupt empty */
-#define PCI230P2_DAC_INT_FIFO_NEMPTY	(1<<9)
-#define PCI230P2_DAC_INT_FIFO_NHALF	(2<<9)	/* FIFO intr not half full */
-#define PCI230P2_DAC_INT_FIFO_HALF	(3<<9)
-#define PCI230P2_DAC_INT_FIFO_NFULL	(4<<9)	/* FIFO interrupt not full */
-#define PCI230P2_DAC_INT_FIFO_FULL	(5<<9)
-#define PCI230P2_DAC_INT_FIFO_MASK	(7<<9)
+/*
+ * DACCON read-write values.
+ */
+#define PCI230_DAC_OR_UNI		(0 << 0) /* Output range unipolar */
+#define PCI230_DAC_OR_BIP		(1 << 0) /* Output range bipolar */
+#define PCI230_DAC_OR_MASK		(1 << 0)
+/*
+ * The following applies only if DAC FIFO support is enabled in the EXTFUNC
+ * register (and only for PCI230+ hardware version 2 onwards).
+ */
+#define PCI230P2_DAC_FIFO_EN		(1 << 8) /* FIFO enable */
+/*
+ * The following apply only if the DAC FIFO is enabled (and only for PCI230+
+ * hardware version 2 onwards).
+ */
+#define PCI230P2_DAC_TRIG_NONE		(0 << 2) /* No trigger */
+#define PCI230P2_DAC_TRIG_SW		(1 << 2) /* Software trigger trigger */
+#define PCI230P2_DAC_TRIG_EXTP		(2 << 2) /* EXTTRIG +ve edge trigger */
+#define PCI230P2_DAC_TRIG_EXTN		(3 << 2) /* EXTTRIG -ve edge trigger */
+#define PCI230P2_DAC_TRIG_Z2CT0		(4 << 2) /* CT0-OUT +ve edge trigger */
+#define PCI230P2_DAC_TRIG_Z2CT1		(5 << 2) /* CT1-OUT +ve edge trigger */
+#define PCI230P2_DAC_TRIG_Z2CT2		(6 << 2) /* CT2-OUT +ve edge trigger */
+#define PCI230P2_DAC_TRIG_MASK		(7 << 2)
+#define PCI230P2_DAC_FIFO_WRAP		(1 << 7) /* FIFO wraparound mode */
+#define PCI230P2_DAC_INT_FIFO_EMPTY	(0 << 9) /* FIFO interrupt empty */
+#define PCI230P2_DAC_INT_FIFO_NEMPTY	(1 << 9)
+#define PCI230P2_DAC_INT_FIFO_NHALF	(2 << 9) /* FIFO intr not half full */
+#define PCI230P2_DAC_INT_FIFO_HALF	(3 << 9)
+#define PCI230P2_DAC_INT_FIFO_NFULL	(4 << 9) /* FIFO interrupt not full */
+#define PCI230P2_DAC_INT_FIFO_FULL	(5 << 9)
+#define PCI230P2_DAC_INT_FIFO_MASK	(7 << 9)
 
-/* DACCON read-only values. */
-#define PCI230_DAC_BUSY			(1<<1)	/* DAC busy. */
-/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
- * hardware version 2 onwards). */
-#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED	(1<<5)	/* Underrun error */
-#define PCI230P2_DAC_FIFO_EMPTY		(1<<13)	/* FIFO empty */
-#define PCI230P2_DAC_FIFO_FULL		(1<<14)	/* FIFO full */
-#define PCI230P2_DAC_FIFO_HALF		(1<<15)	/* FIFO half full */
+/*
+ * DACCON read-only values.
+ */
+#define PCI230_DAC_BUSY			(1 << 1) /* DAC busy. */
+/*
+ * The following apply only if the DAC FIFO is enabled (and only for PCI230+
+ * hardware version 2 onwards).
+ */
+#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED	(1 << 5) /* Underrun error */
+#define PCI230P2_DAC_FIFO_EMPTY		(1 << 13) /* FIFO empty */
+#define PCI230P2_DAC_FIFO_FULL		(1 << 14) /* FIFO full */
+#define PCI230P2_DAC_FIFO_HALF		(1 << 15) /* FIFO half full */
 
-/* DACCON write-only, transient values. */
-/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
- * hardware version 2 onwards). */
-#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR	(1<<5)	/* Clear underrun */
-#define PCI230P2_DAC_FIFO_RESET		(1<<12)	/* FIFO reset */
+/*
+ * DACCON write-only, transient values.
+ */
+/*
+ * The following apply only if the DAC FIFO is enabled (and only for PCI230+
+ * hardware version 2 onwards).
+ */
+#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR	(1 << 5) /* Clear underrun */
+#define PCI230P2_DAC_FIFO_RESET		(1 << 12) /* FIFO reset */
 
-/* PCI230+ hardware version 2 DAC FIFO levels. */
+/*
+ * PCI230+ hardware version 2 DAC FIFO levels.
+ */
 #define PCI230P2_DAC_FIFOLEVEL_HALF	512
 #define PCI230P2_DAC_FIFOLEVEL_FULL	1024
 /* Free space in DAC FIFO. */
@@ -302,56 +313,62 @@ for (or detection of) various hardware p
 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL	1
 #define PCI230P2_DAC_FIFOROOM_FULL		0
 
-/* ADCCON read/write values. */
-#define PCI230_ADC_TRIG_NONE		(0<<0)	/* No trigger */
-#define PCI230_ADC_TRIG_SW		(1<<0)	/* Software trigger trigger */
-#define PCI230_ADC_TRIG_EXTP		(2<<0)	/* EXTTRIG +ve edge trigger */
-#define PCI230_ADC_TRIG_EXTN		(3<<0)	/* EXTTRIG -ve edge trigger */
-#define PCI230_ADC_TRIG_Z2CT0		(4<<0)	/* CT0-OUT +ve edge trigger */
-#define PCI230_ADC_TRIG_Z2CT1		(5<<0)	/* CT1-OUT +ve edge trigger */
-#define PCI230_ADC_TRIG_Z2CT2		(6<<0)	/* CT2-OUT +ve edge trigger */
-#define PCI230_ADC_TRIG_MASK		(7<<0)
-#define PCI230_ADC_IR_UNI		(0<<3)	/* Input range unipolar */
-#define PCI230_ADC_IR_BIP		(1<<3)	/* Input range bipolar */
-#define PCI230_ADC_IR_MASK		(1<<3)
-#define PCI230_ADC_IM_SE		(0<<4)	/* Input mode single ended */
-#define PCI230_ADC_IM_DIF		(1<<4)	/* Input mode differential */
-#define PCI230_ADC_IM_MASK		(1<<4)
-#define PCI230_ADC_FIFO_EN		(1<<8)	/* FIFO enable */
-#define PCI230_ADC_INT_FIFO_EMPTY	(0<<9)
-#define PCI230_ADC_INT_FIFO_NEMPTY	(1<<9)	/* FIFO interrupt not empty */
-#define PCI230_ADC_INT_FIFO_NHALF	(2<<9)
-#define PCI230_ADC_INT_FIFO_HALF	(3<<9)	/* FIFO interrupt half full */
-#define PCI230_ADC_INT_FIFO_NFULL	(4<<9)
-#define PCI230_ADC_INT_FIFO_FULL	(5<<9)	/* FIFO interrupt full */
-#define PCI230P_ADC_INT_FIFO_THRESH	(7<<9)	/* FIFO interrupt threshold */
-#define PCI230_ADC_INT_FIFO_MASK	(7<<9)
+/*
+ * ADCCON read/write values.
+ */
+#define PCI230_ADC_TRIG_NONE		(0 << 0) /* No trigger */
+#define PCI230_ADC_TRIG_SW		(1 << 0) /* Software trigger trigger */
+#define PCI230_ADC_TRIG_EXTP		(2 << 0) /* EXTTRIG +ve edge trigger */
+#define PCI230_ADC_TRIG_EXTN		(3 << 0) /* EXTTRIG -ve edge trigger */
+#define PCI230_ADC_TRIG_Z2CT0		(4 << 0) /* CT0-OUT +ve edge trigger */
+#define PCI230_ADC_TRIG_Z2CT1		(5 << 0) /* CT1-OUT +ve edge trigger */
+#define PCI230_ADC_TRIG_Z2CT2		(6 << 0) /* CT2-OUT +ve edge trigger */
+#define PCI230_ADC_TRIG_MASK		(7 << 0)
+#define PCI230_ADC_IR_UNI		(0 << 3) /* Input range unipolar */
+#define PCI230_ADC_IR_BIP		(1 << 3) /* Input range bipolar */
+#define PCI230_ADC_IR_MASK		(1 << 3)
+#define PCI230_ADC_IM_SE		(0 << 4) /* Input mode single ended */
+#define PCI230_ADC_IM_DIF		(1 << 4) /* Input mode differential */
+#define PCI230_ADC_IM_MASK		(1 << 4)
+#define PCI230_ADC_FIFO_EN		(1 << 8) /* FIFO enable */
+#define PCI230_ADC_INT_FIFO_EMPTY	(0 << 9)
+#define PCI230_ADC_INT_FIFO_NEMPTY	(1 << 9) /* FIFO interrupt not empty */
+#define PCI230_ADC_INT_FIFO_NHALF	(2 << 9)
+#define PCI230_ADC_INT_FIFO_HALF	(3 << 9) /* FIFO interrupt half full */
+#define PCI230_ADC_INT_FIFO_NFULL	(4 << 9)
+#define PCI230_ADC_INT_FIFO_FULL	(5 << 9) /* FIFO interrupt full */
+#define PCI230P_ADC_INT_FIFO_THRESH	(7 << 9) /* FIFO interrupt threshold */
+#define PCI230_ADC_INT_FIFO_MASK	(7 << 9)
 
-/* ADCCON write-only, transient values. */
-#define PCI230_ADC_FIFO_RESET		(1<<12)	/* FIFO reset */
-#define PCI230_ADC_GLOB_RESET		(1<<13)	/* Global reset */
+/*
+ * ADCCON write-only, transient values.
+ */
+#define PCI230_ADC_FIFO_RESET		(1 << 12) /* FIFO reset */
+#define PCI230_ADC_GLOB_RESET		(1 << 13) /* Global reset */
 
-/* ADCCON read-only values. */
-#define PCI230_ADC_BUSY			(1<<15)	/* ADC busy */
-#define PCI230_ADC_FIFO_EMPTY		(1<<12)	/* FIFO empty */
-#define PCI230_ADC_FIFO_FULL		(1<<13)	/* FIFO full */
-#define PCI230_ADC_FIFO_HALF		(1<<14)	/* FIFO half full */
-#define PCI230_ADC_FIFO_FULL_LATCHED	(1<<5)	/* Indicates overrun occurred */
+/*
+ * ADCCON read-only values.
+ */
+#define PCI230_ADC_BUSY			(1 << 15) /* ADC busy */
+#define PCI230_ADC_FIFO_EMPTY		(1 << 12) /* FIFO empty */
+#define PCI230_ADC_FIFO_FULL		(1 << 13) /* FIFO full */
+#define PCI230_ADC_FIFO_HALF		(1 << 14) /* FIFO half full */
+#define PCI230_ADC_FIFO_FULL_LATCHED	(1 << 5)  /* FIFO overrun occurred */
 
-/* PCI230 ADC FIFO levels. */
+/*
+ * PCI230 ADC FIFO levels.
+ */
 #define PCI230_ADC_FIFOLEVEL_HALFFULL	2049	/* Value for FIFO half full */
 #define PCI230_ADC_FIFOLEVEL_FULL	4096	/* FIFO size */
 
-/* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
- * mode.  Can be anything.  */
-#define PCI230_ADC_CONV			0xffff
-
-/* PCI230+ EXTFUNC values. */
-#define PCI230P_EXTFUNC_GAT_EXTTRIG	(1<<0)
-			/* Route EXTTRIG pin to external gate inputs. */
+/*
+ * PCI230+ EXTFUNC values.
+ */
+/* Route EXTTRIG pin to external gate inputs. */
+#define PCI230P_EXTFUNC_GAT_EXTTRIG	(1 << 0)
 /* PCI230+ hardware version 2 values. */
-#define PCI230P2_EXTFUNC_DACFIFO	(1<<1)
-			/* Allow DAC FIFO to be enabled. */
+/* Allow DAC FIFO to be enabled. */
+#define PCI230P2_EXTFUNC_DACFIFO	(1 << 1)
 
 /*
  * Counter/timer clock input configuration sources.
@@ -395,19 +412,20 @@ for (or detection of) various hardware p
  * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
  */
 
-/* Interrupt enables/status register values. */
+/*
+ * Interrupt enables/status register values.
+ */
 #define PCI230_INT_DISABLE		0
-#define PCI230_INT_PPI_C0		(1<<0)
-#define PCI230_INT_PPI_C3		(1<<1)
-#define PCI230_INT_ADC			(1<<2)
-#define PCI230_INT_ZCLK_CT1		(1<<5)
+#define PCI230_INT_PPI_C0		(1 << 0)
+#define PCI230_INT_PPI_C3		(1 << 1)
+#define PCI230_INT_ADC			(1 << 2)
+#define PCI230_INT_ZCLK_CT1		(1 << 5)
 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
-#define PCI230P2_INT_DAC		(1<<4)
-
-#define PCI230_TEST_BIT(val, n)	((val>>n)&1)
-			/* Assumes bits numbered with zero offset, ie. 0-15 */
+#define PCI230P2_INT_DAC		(1 << 4)
 
-/* (Potentially) shared resources and their owners */
+/*
+ * (Potentially) shared resources and their owners
+ */
 enum {
 	RES_Z2CT0,		/* Z2-CT0 */
 	RES_Z2CT1,		/* Z2-CT1 */
@@ -449,83 +467,70 @@ struct pci230_board {
 	int have_dio;
 	unsigned int min_hwver;	/* Minimum hardware version supported. */
 };
+
 static const struct pci230_board pci230_boards[] = {
 	{
-	 .name = "pci230+",
-	 .id = PCI_DEVICE_ID_PCI230,
-	 .ai_chans = 16,
-	 .ai_bits = 16,
-	 .ao_chans = 2,
-	 .ao_bits = 12,
-	 .have_dio = 1,
-	 .min_hwver = 1,
-	 },
+		.name		= "pci230+",
+		.id		= PCI_DEVICE_ID_PCI230,
+		.ai_chans	= 16,
+		.ai_bits	= 16,
+		.ao_chans	= 2,
+		.ao_bits	= 12,
+		.have_dio	= 1,
+		.min_hwver	= 1,
+	},
 	{
-	 .name = "pci260+",
-	 .id = PCI_DEVICE_ID_PCI260,
-	 .ai_chans = 16,
-	 .ai_bits = 16,
-	 .ao_chans = 0,
-	 .ao_bits = 0,
-	 .have_dio = 0,
-	 .min_hwver = 1,
-	 },
+		.name		= "pci260+",
+		.id		= PCI_DEVICE_ID_PCI260,
+		.ai_chans	= 16,
+		.ai_bits	= 16,
+		.min_hwver	= 1,
+	},
 	{
-	 .name = "pci230",
-	 .id = PCI_DEVICE_ID_PCI230,
-	 .ai_chans = 16,
-	 .ai_bits = 12,
-	 .ao_chans = 2,
-	 .ao_bits = 12,
-	 .have_dio = 1,
-	 },
+		.name		= "pci230",
+		.id		= PCI_DEVICE_ID_PCI230,
+		.ai_chans	= 16,
+		.ai_bits	= 12,
+		.ao_chans	= 2,
+		.ao_bits	= 12,
+		.have_dio	= 1,
+	},
 	{
-	 .name = "pci260",
-	 .id = PCI_DEVICE_ID_PCI260,
-	 .ai_chans = 16,
-	 .ai_bits = 12,
-	 .ao_chans = 0,
-	 .ao_bits = 0,
-	 .have_dio = 0,
-	 },
+		.name		= "pci260",
+		.id		= PCI_DEVICE_ID_PCI260,
+		.ai_chans	= 16,
+		.ai_bits	= 12,
+	},
 	{
-	 .name = "amplc_pci230",	/* Wildcard matches any above */
-	 .id = PCI_DEVICE_ID_INVALID,
-	 },
+		/* Wildcard matches any above */
+		.name		= "amplc_pci230",
+		.id		= PCI_DEVICE_ID_INVALID,
+	},
 };
 
-/* this structure is for data unique to this hardware driver.  If
-   several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.  */
 struct pci230_private {
 	spinlock_t isr_spinlock;	/* Interrupt spin lock */
 	spinlock_t res_spinlock;	/* Shared resources spin lock */
 	spinlock_t ai_stop_spinlock;	/* Spin lock for stopping AI command */
 	spinlock_t ao_stop_spinlock;	/* Spin lock for stopping AO command */
-	unsigned long state;	/* State flags */
-	unsigned long iobase1;	/* PCI230's I/O space 1 */
+	unsigned long state;		/* State flags */
+	unsigned long iobase1;		/* PCI230's I/O space 1 */
 	unsigned int ao_readback[2];	/* Used for AO readback */
-	unsigned int ai_scan_count;	/* Number of analogue input scans
-					 * remaining.  */
-	unsigned int ai_scan_pos;	/* Current position within analogue
-					 * input scan */
-	unsigned int ao_scan_count;	/* Number of analogue output scans
-					 * remaining.  */
-	int intr_cpuid;		/* ID of CPU running interrupt routine. */
-	unsigned short hwver;	/* Hardware version (for '+' models). */
-	unsigned short adccon;	/* ADCCON register value. */
-	unsigned short daccon;	/* DACCON register value. */
-	unsigned short adcfifothresh;	/* ADC FIFO programmable interrupt
-					 * level threshold (PCI230+/260+). */
-	unsigned short adcg;	/* ADCG register value. */
-	unsigned char int_en;	/* Interrupt enables bits. */
-	unsigned char ai_bipolar;	/* Set if bipolar input range so we
-					 * know to mangle it. */
-	unsigned char ao_bipolar;	/* Set if bipolar output range so we
-					 * know to mangle it. */
-	unsigned char ier;	/* Copy of interrupt enables/status register. */
-	unsigned char intr_running;	/* Flag set in interrupt routine. */
-	unsigned char res_owner[NUM_RESOURCES];	/* Shared resource owners. */
+	unsigned int ai_scan_count;	/* Number of AI scans remaining */
+	unsigned int ai_scan_pos;	/* Current position within AI scan */
+	unsigned int ao_scan_count;	/* Number of AO scans remaining.  */
+	int intr_cpuid;			/* ID of CPU running ISR */
+	unsigned short hwver;		/* Hardware version (for '+' models) */
+	unsigned short adccon;		/* ADCCON register value */
+	unsigned short daccon;		/* DACCON register value */
+	unsigned short adcfifothresh;	/* ADC FIFO threshold (PCI230+/260+) */
+	unsigned short adcg;		/* ADCG register value */
+	unsigned char int_en;		/* Interrupt enable bits */
+	unsigned char ai_bipolar;	/* Flag AI range is bipolar */
+	unsigned char ao_bipolar;	/* Flag AO range is bipolar */
+	unsigned char ier;		/* Copy of interrupt enable register */
+	unsigned char intr_running;	/* Flag set in interrupt routine */
+	unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners */
 };
 
 /* PCI230 clock source periods in ns */
@@ -575,13 +580,16 @@ static unsigned short pci230_ai_read(str
 
 	/* Read sample. */
 	data = inw(dev->iobase + PCI230_ADCDATA);
-	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
-	 * four bits reserved for expansion). */
-	/* PCI230+ is 16 bit AI. */
+	/*
+	 * PCI230 is 12 bit - stored in upper bits of 16 bit register
+	 * (lower four bits reserved for expansion).  PCI230+ is 16 bit AI.
+	 */
 	data = data >> (16 - thisboard->ai_bits);
 
-	/* If a bipolar range was specified, mangle it (twos
-	 * complement->straight binary). */
+	/*
+	 * If a bipolar range was specified, mangle it
+	 * (twos complement->straight binary).
+	 */
 	if (devpriv->ai_bipolar)
 		data ^= 1 << (thisboard->ai_bits - 1);
 
@@ -594,14 +602,17 @@ static inline unsigned short pci230_ao_m
 	const struct pci230_board *thisboard = comedi_board(dev);
 	struct pci230_private *devpriv = dev->private;
 
-	/* If a bipolar range was specified, mangle it (straight binary->twos
-	 * complement). */
+	/*
+	 * If a bipolar range was specified, mangle it
+	 * (straight binary->twos complement).
+	 */
 	if (devpriv->ao_bipolar)
 		datum ^= 1 << (thisboard->ao_bits - 1);
 
-	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
-	 * four bits reserved for expansion). */
-	/* PCI230+ is also 12 bit AO. */
+	/*
+	 * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
+	 * four bits reserved for expansion).  PCI230+ is also 12 bit AO.
+	 */
 	datum <<= (16 - thisboard->ao_bits);
 	return datum;
 }
@@ -616,10 +627,8 @@ static inline void pci230_ao_write_nofif
 	devpriv->ao_readback[chan] = datum;
 
 	/* Write mangled datum to appropriate DACOUT register. */
-	outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
-								? PCI230_DACOUT1
-								:
-								PCI230_DACOUT2));
+	outw(pci230_ao_mangle_datum(dev, datum),
+	     dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
 }
 
 static inline void pci230_ao_write_fifo(struct comedi_device *dev,
@@ -648,18 +657,17 @@ static int get_resources(struct comedi_d
 	ok = 1;
 	claimed = 0;
 	spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
-	for (b = 1, i = 0; (i < NUM_RESOURCES)
-	     && (res_mask != 0); b <<= 1, i++) {
-		if ((res_mask & b) != 0) {
+	for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) {
+		if (res_mask & b) {
 			res_mask &= ~b;
 			if (devpriv->res_owner[i] == OWNER_NONE) {
 				devpriv->res_owner[i] = owner;
 				claimed |= b;
 			} else if (devpriv->res_owner[i] != owner) {
-				for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
-					if ((claimed & b) != 0) {
-						devpriv->res_owner[i]
-						    = OWNER_NONE;
+				for (b = 1, i = 0; claimed; b <<= 1, i++) {
+					if (claimed & b) {
+						devpriv->res_owner[i] =
+						    OWNER_NONE;
 						claimed &= ~b;
 					}
 				}
@@ -687,13 +695,11 @@ static void put_resources(struct comedi_
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
-	for (b = 1, i = 0; (i < NUM_RESOURCES)
-	     && (res_mask != 0); b <<= 1, i++) {
-		if ((res_mask & b) != 0) {
+	for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) {
+		if (res_mask & b) {
 			res_mask &= ~b;
 			if (devpriv->res_owner[i] == owner)
 				devpriv->res_owner[i] = OWNER_NONE;
-
 		}
 	}
 	spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
@@ -712,15 +718,14 @@ static inline void put_all_resources(str
 }
 
 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
-			      unsigned int round_mode)
+			      unsigned int flags)
 {
 	uint64_t div;
 	unsigned int rem;
 
 	div = ns;
 	rem = do_div(div, timebase);
-	round_mode &= TRIG_ROUND_MASK;
-	switch (round_mode) {
+	switch (flags & TRIG_ROUND_MASK) {
 	default:
 	case TRIG_ROUND_NEAREST:
 		div += (rem + (timebase / 2)) / timebase;
@@ -734,36 +739,36 @@ static unsigned int divide_ns(uint64_t n
 	return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
 }
 
-/* Given desired period in ns, returns the required internal clock source
- * and gets the initial count. */
+/*
+ * Given desired period in ns, returns the required internal clock source
+ * and gets the initial count.
+ */
 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
-					    unsigned int round_mode)
+					    unsigned int flags)
 {
 	unsigned int clk_src, cnt;
 
 	for (clk_src = CLK_10MHZ;; clk_src++) {
-		cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
+		cnt = divide_ns(ns, pci230_timebase[clk_src], flags);
 		if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
 			break;
-
 	}
 	*count = cnt;
 	return clk_src;
 }
 
-static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
+static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags)
 {
 	unsigned int count;
 	unsigned int clk_src;
 
-	clk_src = pci230_choose_clk_count(*ns, &count, round);
+	clk_src = pci230_choose_clk_count(*ns, &count, flags);
 	*ns = count * pci230_timebase[clk_src];
-	return;
 }
 
 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
 				    unsigned int mode, uint64_t ns,
-				    unsigned int round)
+				    unsigned int flags)
 {
 	struct pci230_private *devpriv = dev->private;
 	unsigned int clk_src;
@@ -772,7 +777,7 @@ static void pci230_ct_setup_ns_mode(stru
 	/* Set mode. */
 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
 	/* Determine clock source and count. */
-	clk_src = pci230_choose_clk_count(ns, &count, round);
+	clk_src = pci230_choose_clk_count(ns, &count, flags);
 	/* Program clock source. */
 	outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
 	/* Set initial count. */
@@ -829,7 +834,8 @@ static int pci230_ai_rinsn(struct comedi
 		}
 	}
 
-	/* Use Z2-CT2 as a conversion trigger instead of the built-in
+	/*
+	 * Use Z2-CT2 as a conversion trigger instead of the built-in
 	 * software trigger, as otherwise triggering of differential channels
 	 * doesn't work properly for some versions of PCI230/260.  Also set
 	 * FIFO mode because the ADC busy bit only works for software triggers.
@@ -842,12 +848,16 @@ static int pci230_ai_rinsn(struct comedi
 		/* Differential. */
 		gainshift = chan * 2;
 		if (devpriv->hwver == 0) {
-			/* Original PCI230/260 expects both inputs of the
-			 * differential channel to be enabled. */
+			/*
+			 * Original PCI230/260 expects both inputs of the
+			 * differential channel to be enabled.
+			 */
 			adcen = 3 << gainshift;
 		} else {
-			/* PCI230+/260+ expects only one input of the
-			 * differential channel to be enabled. */
+			/*
+			 * PCI230+/260+ expects only one input of the
+			 * differential channel to be enabled.
+			 */
 			adcen = 1 << gainshift;
 		}
 		adccon |= PCI230_ADC_IM_DIF;
@@ -857,16 +867,18 @@ static int pci230_ai_rinsn(struct comedi
 		gainshift = chan & ~1;
 		adccon |= PCI230_ADC_IM_SE;
 	}
-	devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
-	    | (pci230_ai_gain[range] << gainshift);
+	devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
+			(pci230_ai_gain[range] << gainshift);
 	if (devpriv->ai_bipolar)
 		adccon |= PCI230_ADC_IR_BIP;
 	else
 		adccon |= PCI230_ADC_IR_UNI;
 
 
-	/* Enable only this channel in the scan list - otherwise by default
-	 * we'll get one sample from each channel. */
+	/*
+	 * Enable only this channel in the scan list - otherwise by default
+	 * we'll get one sample from each channel.
+	 */
 	outw(adcen, dev->iobase + PCI230_ADCEN);
 
 	/* Set gain for channel. */
@@ -878,8 +890,10 @@ static int pci230_ai_rinsn(struct comedi
 
 	/* Convert n samples */
 	for (n = 0; n < insn->n; n++) {
-		/* Trigger conversion by toggling Z2-CT2 output (finish with
-		 * output high). */
+		/*
+		 * Trigger conversion by toggling Z2-CT2 output
+		 * (finish with output high).
+		 */
 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
 			       I8254_MODE0);
 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
@@ -913,13 +927,17 @@ static int pci230_ao_winsn(struct comedi
 	chan = CR_CHAN(insn->chanspec);
 	range = CR_RANGE(insn->chanspec);
 
-	/* Set range - see analogue output range table; 0 => unipolar 10V,
-	 * 1 => bipolar +/-10V range scale */
+	/*
+	 * Set range - see analogue output range table; 0 => unipolar 10V,
+	 * 1 => bipolar +/-10V range scale
+	 */
 	devpriv->ao_bipolar = pci230_ao_bipolar[range];
 	outw(range, dev->iobase + PCI230_DACCON);
 
-	/* Writing a list of values to an AO channel is probably not
-	 * very useful, but that's how the interface is defined. */
+	/*
+	 * Writing a list of values to an AO channel is probably not
+	 * very useful, but that's how the interface is defined.
+	 */
 	for (i = 0; i < insn->n; i++) {
 		/* Write value to DAC and store it. */
 		pci230_ao_write_nofifo(dev, data[i], chan);
@@ -929,8 +947,10 @@ static int pci230_ao_winsn(struct comedi
 	return i;
 }
 
-/* AO subdevices should have a read insn as well as a write insn.
- * Usually this means copying a value stored in devpriv. */
+/*
+ * AO subdevices should have a read insn as well as a write insn.
+ * Usually this means copying a value stored in devpriv.
+ */
 static int pci230_ao_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
@@ -1031,10 +1051,11 @@ static int pci230_ao_cmdtest(struct come
 	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 #define MAX_SPEED_AO	8000	/* 8000 ns => 125 kHz */
+/*
+ * Comedi limit due to unsigned int cmd.  Driver limit =
+ * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
+ */
 #define MIN_SPEED_AO	4294967295u	/* 4294967295ns = 4.29s */
-			/*- Comedi limit due to unsigned int cmd.  Driver limit
-			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
-			 * clock) = 65.536s */
 
 	switch (cmd->scan_begin_src) {
 	case TRIG_TIMER:
@@ -1044,17 +1065,21 @@ static int pci230_ao_cmdtest(struct come
 						 MIN_SPEED_AO);
 		break;
 	case TRIG_EXT:
-		/* External trigger - for PCI230+ hardware version 2 onwards. */
+		/*
+		 * External trigger - for PCI230+ hardware version 2 onwards.
+		 */
 		/* Trigger number must be 0. */
-		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
+		if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      ~CR_FLAGS_MASK);
 			err |= -EINVAL;
 		}
-		/* The only flags allowed are CR_EDGE and CR_INVERT.  The
-		 * CR_EDGE flag is ignored. */
-		if ((cmd->scan_begin_arg
-		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
+		/*
+		 * The only flags allowed are CR_EDGE and CR_INVERT.
+		 * The CR_EDGE flag is ignored.
+		 */
+		if (cmd->scan_begin_arg &
+		    (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      CR_FLAGS_MASK &
 						      ~(CR_EDGE | CR_INVERT));
@@ -1074,14 +1099,11 @@ static int pci230_ao_cmdtest(struct come
 	if (err)
 		return 3;
 
-	/* Step 4: fix up any arguments.
-	 * "argument conflict" returned by comedilib to user mode process
-	 * if this fails. */
+	/* Step 4: fix up any arguments */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp = cmd->scan_begin_arg;
-		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
@@ -1126,8 +1148,10 @@ static void pci230_ao_stop(struct comedi
 		/* Using DAC FIFO interrupt. */
 		intsrc = PCI230P2_INT_DAC;
 	}
-	/* Disable interrupt and wait for interrupt routine to finish running
-	 * unless we are called from the interrupt routine. */
+	/*
+	 * Disable interrupt and wait for interrupt routine to finish running
+	 * unless we are called from the interrupt routine.
+	 */
 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
 	devpriv->int_en &= ~intsrc;
 	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
@@ -1140,11 +1164,13 @@ static void pci230_ao_stop(struct comedi
 	}
 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
 	if (devpriv->hwver >= 2) {
-		/* Using DAC FIFO.  Reset FIFO, clear underrun error,
-		 * disable FIFO. */
+		/*
+		 * Using DAC FIFO.  Reset FIFO, clear underrun error,
+		 * disable FIFO.
+		 */
 		devpriv->daccon &= PCI230_DAC_OR_MASK;
-		outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
-		     | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
+		outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET |
+		     PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
 		     dev->iobase + PCI230_DACCON);
 	}
 	/* Release resources. */
@@ -1168,7 +1194,7 @@ static void pci230_handle_ao_nofifo(stru
 		if (ret == 0) {
 			s->async->events |= COMEDI_CB_OVERFLOW;
 			pci230_ao_stop(dev, s);
-			comedi_error(dev, "AO buffer underrun");
+			dev_err(dev->class_dev, "AO buffer underrun\n");
 			return;
 		}
 		/* Write value to DAC. */
@@ -1215,26 +1241,28 @@ static int pci230_handle_ao_fifo(struct
 	}
 	if (events == 0) {
 		/* Check for FIFO underrun. */
-		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
-			comedi_error(dev, "AO FIFO underrun");
+		if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
+			dev_err(dev->class_dev, "AO FIFO underrun\n");
 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
 		}
-		/* Check for buffer underrun if FIFO less than half full
+		/*
+		 * Check for buffer underrun if FIFO less than half full
 		 * (otherwise there will be loads of "DAC FIFO not half full"
-		 * interrupts). */
-		if ((num_scans == 0)
-		    && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
-			comedi_error(dev, "AO buffer underrun");
+		 * interrupts).
+		 */
+		if ((num_scans == 0) &&
+		    ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
+			dev_err(dev->class_dev, "AO buffer underrun\n");
 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
 		}
 	}
 	if (events == 0) {
 		/* Determine how much room is in the FIFO (in samples). */
-		if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
+		if (dacstat & PCI230P2_DAC_FIFO_FULL)
 			room = PCI230P2_DAC_FIFOROOM_FULL;
-		else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
+		else if (dacstat & PCI230P2_DAC_FIFO_HALF)
 			room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
-		else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
+		else if (dacstat & PCI230P2_DAC_FIFO_EMPTY)
 			room = PCI230P2_DAC_FIFOROOM_EMPTY;
 		else
 			room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
@@ -1257,26 +1285,27 @@ static int pci230_handle_ao_fifo(struct
 		if (cmd->stop_src == TRIG_COUNT) {
 			devpriv->ao_scan_count -= num_scans;
 			if (devpriv->ao_scan_count == 0) {
-				/* All data for the command has been written
+				/*
+				 * All data for the command has been written
 				 * to FIFO.  Set FIFO interrupt trigger level
-				 * to 'empty'. */
-				devpriv->daccon = (devpriv->daccon
-						   &
-						   ~PCI230P2_DAC_INT_FIFO_MASK)
-				    | PCI230P2_DAC_INT_FIFO_EMPTY;
+				 * to 'empty'.
+				 */
+				devpriv->daccon =
+				    (devpriv->daccon &
+				     ~PCI230P2_DAC_INT_FIFO_MASK) |
+				    PCI230P2_DAC_INT_FIFO_EMPTY;
 				outw(devpriv->daccon,
 				     dev->iobase + PCI230_DACCON);
 			}
 		}
 		/* Check if FIFO underrun occurred while writing to FIFO. */
 		dacstat = inw(dev->iobase + PCI230_DACCON);
-		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
-			comedi_error(dev, "AO FIFO underrun");
+		if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
+			dev_err(dev->class_dev, "AO FIFO underrun\n");
 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
 		}
 	}
-	if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
-	    != 0) {
+	if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
 		/* Stopping AO due to completion or error. */
 		pci230_ao_stop(dev, s);
 		running = 0;
@@ -1294,7 +1323,7 @@ static int pci230_ao_inttrig_scan_begin(
 	struct pci230_private *devpriv = dev->private;
 	unsigned long irqflags;
 
-	if (trig_num != 0)
+	if (trig_num)
 		return -EINVAL;
 
 	spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
@@ -1373,11 +1402,10 @@ static void pci230_ao_start(struct comed
 				scantrig = PCI230P2_DAC_TRIG_NONE;
 				break;
 			}
-			devpriv->daccon = (devpriv->daccon
-					   & ~PCI230P2_DAC_TRIG_MASK) |
+			devpriv->daccon =
+			    (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) |
 			    scantrig;
 			outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
-
 		}
 		switch (cmd->scan_begin_src) {
 		case TRIG_TIMER:
@@ -1441,7 +1469,6 @@ static int pci230_ao_cmd(struct comedi_d
 		/* Claim Z2-CT1. */
 		if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
 			return -EBUSY;
-
 	}
 
 	/* Get number of scans required. */
@@ -1450,8 +1477,10 @@ static int pci230_ao_cmd(struct comedi_d
 	else	/* TRIG_NONE, user calls cancel */
 		devpriv->ao_scan_count = 0;
 
-	/* Set range - see analogue output range table; 0 => unipolar 10V,
-	 * 1 => bipolar +/-10V range scale */
+	/*
+	 * Set range - see analogue output range table; 0 => unipolar 10V,
+	 * 1 => bipolar +/-10V range scale
+	 */
 	range = CR_RANGE(cmd->chanlist[0]);
 	devpriv->ao_bipolar = pci230_ao_bipolar[range];
 	daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
@@ -1474,26 +1503,28 @@ static int pci230_ao_cmd(struct comedi_d
 		 *
 		 * N.B. DAC FIFO interrupts are currently disabled.
 		 */
-		daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
-		    | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
-		    | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
+		daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET |
+			  PCI230P2_DAC_FIFO_UNDERRUN_CLEAR |
+			  PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
 	}
 
 	/* Set DACCON. */
 	outw(daccon, dev->iobase + PCI230_DACCON);
 	/* Preserve most of DACCON apart from write-only, transient bits. */
-	devpriv->daccon = daccon
-	    & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
+	devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET |
+				     PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		/* Set the counter timer 1 to the specified scan frequency. */
-		/* cmd->scan_begin_arg is sampling period in ns */
-		/* gate it off for now. */
+		/*
+		 * Set the counter timer 1 to the specified scan frequency.
+		 * cmd->scan_begin_arg is sampling period in ns.
+		 * Gate it off for now.
+		 */
 		outb(GAT_CONFIG(1, GAT_GND),
 		     devpriv->iobase1 + PCI230_ZGAT_SCE);
 		pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
 					cmd->scan_begin_arg,
-					cmd->flags & TRIG_ROUND_MASK);
+					cmd->flags);
 	}
 
 	/* N.B. cmd->start_src == TRIG_INT */
@@ -1519,8 +1550,8 @@ static int pci230_ai_check_scan_period(s
 		chanlist_len = 1;
 
 	min_scan_period = chanlist_len * cmd->convert_arg;
-	if ((min_scan_period < chanlist_len)
-	    || (min_scan_period < cmd->convert_arg)) {
+	if ((min_scan_period < chanlist_len) ||
+	    (min_scan_period < cmd->convert_arg)) {
 		/* Arithmetic overflow. */
 		min_scan_period = UINT_MAX;
 		err++;
@@ -1570,10 +1601,10 @@ static int pci230_ai_check_chanlist(stru
 
 			if (subseq_len > 0 &&
 			    cmd->chanlist[i % subseq_len] != chanspec) {
-					dev_dbg(dev->class_dev,
-						"%s: channel numbers must increase or sequence must repeat exactly\n",
-						__func__);
-					return -EINVAL;
+				dev_dbg(dev->class_dev,
+					"%s: channel numbers must increase or sequence must repeat exactly\n",
+					__func__);
+				return -EINVAL;
 			}
 
 			if (aref != prev_aref) {
@@ -1607,7 +1638,7 @@ static int pci230_ai_check_chanlist(stru
 	if (subseq_len == 0)
 		subseq_len = cmd->chanlist_len;
 
-	if ((cmd->chanlist_len % subseq_len) != 0) {
+	if (cmd->chanlist_len % subseq_len) {
 		dev_dbg(dev->class_dev,
 			"%s: sequence must repeat exactly\n", __func__);
 		return -EINVAL;
@@ -1625,7 +1656,7 @@ static int pci230_ai_check_chanlist(stru
 	 * the bug, but the second one does, and we can't tell them apart!
 	 */
 	if (devpriv->hwver > 0 && devpriv->hwver < 4) {
-		if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0]) != 0) {
+		if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0])) {
 			dev_info(dev->class_dev,
 				 "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n",
 				 devpriv->hwver);
@@ -1680,8 +1711,8 @@ static int pci230_ai_cmdtest(struct come
 	 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
 	 * set up to generate a fixed number of timed conversion pulses.
 	 */
-	if ((cmd->scan_begin_src != TRIG_FOLLOW)
-	    && (cmd->convert_src != TRIG_TIMER))
+	if ((cmd->scan_begin_src != TRIG_FOLLOW) &&
+	    (cmd->convert_src != TRIG_TIMER))
 		err |= -EINVAL;
 
 	if (err)
@@ -1694,17 +1725,20 @@ static int pci230_ai_cmdtest(struct come
 #define MAX_SPEED_AI_SE		3200	/* PCI230 SE:   3200 ns => 312.5 kHz */
 #define MAX_SPEED_AI_DIFF	8000	/* PCI230 DIFF: 8000 ns => 125 kHz */
 #define MAX_SPEED_AI_PLUS	4000	/* PCI230+:     4000 ns => 250 kHz */
+/*
+ * Comedi limit due to unsigned int cmd.  Driver limit =
+ * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
+ */
 #define MIN_SPEED_AI	4294967295u	/* 4294967295ns = 4.29s */
-			/*- Comedi limit due to unsigned int cmd.  Driver limit
-			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
-			 * clock) = 65.536s */
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		unsigned int max_speed_ai;
 
 		if (devpriv->hwver == 0) {
-			/* PCI230 or PCI260.  Max speed depends whether
-			 * single-ended or pseudo-differential. */
+			/*
+			 * PCI230 or PCI260.  Max speed depends whether
+			 * single-ended or pseudo-differential.
+			 */
 			if (cmd->chanlist && (cmd->chanlist_len > 0)) {
 				/* Peek analogue reference of first channel. */
 				if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
@@ -1734,17 +1768,19 @@ static int pci230_ai_cmdtest(struct come
 		 * convert_arg == (CR_EDGE | CR_INVERT | 0)
 		 *                => trigger on -ve edge.
 		 */
-		if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
+		if (cmd->convert_arg & CR_FLAGS_MASK) {
 			/* Trigger number must be 0. */
-			if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
+			if (cmd->convert_arg & ~CR_FLAGS_MASK) {
 				cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
 							   ~CR_FLAGS_MASK);
 				err |= -EINVAL;
 			}
-			/* The only flags allowed are CR_INVERT and CR_EDGE.
-			 * CR_EDGE is required. */
-			if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
-			    != CR_EDGE) {
+			/*
+			 * The only flags allowed are CR_INVERT and CR_EDGE.
+			 * CR_EDGE is required.
+			 */
+			if ((cmd->convert_arg &
+			     (CR_FLAGS_MASK & ~CR_INVERT)) != CR_EDGE) {
 				/* Set CR_EDGE, preserve CR_INVERT. */
 				cmd->convert_arg = COMBINE(cmd->start_arg,
 							   (CR_EDGE | 0),
@@ -1753,9 +1789,11 @@ static int pci230_ai_cmdtest(struct come
 				err |= -EINVAL;
 			}
 		} else {
-			/* Backwards compatibility with previous versions. */
-			/* convert_arg == 0 => trigger on -ve edge. */
-			/* convert_arg == 1 => trigger on +ve edge. */
+			/*
+			 * Backwards compatibility with previous versions:
+			 * convert_arg == 0 => trigger on -ve edge.
+			 * convert_arg == 1 => trigger on +ve edge.
+			 */
 			err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
 		}
 	} else {
@@ -1768,16 +1806,18 @@ static int pci230_ai_cmdtest(struct come
 		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_EXT) {
-		/* external "trigger" to begin each scan
+		/*
+		 * external "trigger" to begin each scan:
 		 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
-		 * of CT2 (sample convert trigger is CT2) */
-		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
+		 * of CT2 (sample convert trigger is CT2)
+		 */
+		if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      ~CR_FLAGS_MASK);
 			err |= -EINVAL;
 		}
 		/* The only flag allowed is CR_EDGE, which is ignored. */
-		if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
+		if (cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      CR_FLAGS_MASK & ~CR_EDGE);
 			err |= -EINVAL;
@@ -1794,14 +1834,11 @@ static int pci230_ai_cmdtest(struct come
 	if (err)
 		return 3;
 
-	/* Step 4: fix up any arguments.
-	 * "argument conflict" returned by comedilib to user mode process
-	 * if this fails. */
+	/* Step 4: fix up any arguments */
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		pci230_ns_to_single_timer(&cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		pci230_ns_to_single_timer(&cmd->convert_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			err++;
 	}
@@ -1809,8 +1846,7 @@ static int pci230_ai_cmdtest(struct come
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		/* N.B. cmd->convert_arg is also TRIG_TIMER */
 		tmp = cmd->scan_begin_arg;
-		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
 		if (!pci230_ai_check_scan_period(cmd)) {
 			/* Was below minimum required.  Round up. */
 			pci230_ns_to_single_timer(&cmd->scan_begin_arg,
@@ -1844,7 +1880,7 @@ static void pci230_ai_update_fifo_trigge
 	unsigned short triglev;
 	unsigned short adccon;
 
-	if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
+	if (cmd->flags & TRIG_WAKE_EOS) {
 		/* Wake at end of scan. */
 		wake = scanlen - devpriv->ai_scan_pos;
 	} else {
@@ -1853,8 +1889,8 @@ static void pci230_ai_update_fifo_trigge
 		    scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
 			wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
 		} else {
-			wake = (devpriv->ai_scan_count * scanlen)
-			    - devpriv->ai_scan_pos;
+			wake = (devpriv->ai_scan_count * scanlen) -
+			       devpriv->ai_scan_pos;
 		}
 	}
 	if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
@@ -1885,27 +1921,30 @@ static int pci230_ai_inttrig_convert(str
 	struct pci230_private *devpriv = dev->private;
 	unsigned long irqflags;
 
-	if (trig_num != 0)
+	if (trig_num)
 		return -EINVAL;
 
 	spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
 	if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
 		unsigned int delayus;
 
-		/* Trigger conversion by toggling Z2-CT2 output.  Finish
-		 * with output high. */
+		/*
+		 * Trigger conversion by toggling Z2-CT2 output.
+		 * Finish with output high.
+		 */
 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
 			       I8254_MODE0);
 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
 			       I8254_MODE1);
-		/* Delay.  Should driver be responsible for this?  An
+		/*
+		 * Delay.  Should driver be responsible for this?  An
 		 * alternative would be to wait until conversion is complete,
 		 * but we can't tell when it's complete because the ADC busy
 		 * bit has a different meaning when FIFO enabled (and when
-		 * FIFO not enabled, it only works for software triggers). */
-		if (((devpriv->adccon & PCI230_ADC_IM_MASK)
-		     == PCI230_ADC_IM_DIF)
-		    && (devpriv->hwver == 0)) {
+		 * FIFO not enabled, it only works for software triggers).
+		 */
+		if (((devpriv->adccon & PCI230_ADC_IM_MASK) ==
+		     PCI230_ADC_IM_DIF) && (devpriv->hwver == 0)) {
 			/* PCI230/260 in differential mode */
 			delayus = 8;
 		} else {
@@ -1929,7 +1968,7 @@ static int pci230_ai_inttrig_scan_begin(
 	unsigned long irqflags;
 	unsigned char zgat;
 
-	if (trig_num != 0)
+	if (trig_num)
 		return -EINVAL;
 
 	spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
@@ -1968,8 +2007,10 @@ static void pci230_ai_stop(struct comedi
 		pci230_cancel_ct(dev, 0);
 	}
 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
-	/* Disable ADC interrupt and wait for interrupt routine to finish
-	 * running unless we are called from the interrupt routine. */
+	/*
+	 * Disable ADC interrupt and wait for interrupt routine to finish
+	 * running unless we are called from the interrupt routine.
+	 */
 	devpriv->int_en &= ~PCI230_INT_ADC;
 	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
 		spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
@@ -1980,10 +2021,12 @@ static void pci230_ai_stop(struct comedi
 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
 	}
 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
-	/* Reset FIFO, disable FIFO and set start conversion source to none.
-	 * Keep se/diff and bip/uni settings */
-	devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
-					      | PCI230_ADC_IM_MASK)) |
+	/*
+	 * Reset FIFO, disable FIFO and set start conversion source to none.
+	 * Keep se/diff and bip/uni settings.
+	 */
+	devpriv->adccon =
+	    (devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) |
 	    PCI230_ADC_TRIG_NONE;
 	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
 	     dev->iobase + PCI230_ADCCON);
@@ -2014,8 +2057,10 @@ static void pci230_ai_start(struct comed
 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
 		spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
 
-		/* Update conversion trigger source which is currently set
-		 * to CT2 output, which is currently stuck high. */
+		/*
+		 * Update conversion trigger source which is currently set
+		 * to CT2 output, which is currently stuck high.
+		 */
 		switch (cmd->convert_src) {
 		default:
 			conv = PCI230_ADC_TRIG_NONE;
@@ -2025,7 +2070,7 @@ static void pci230_ai_start(struct comed
 			conv = PCI230_ADC_TRIG_Z2CT2;
 			break;
 		case TRIG_EXT:
-			if ((cmd->convert_arg & CR_EDGE) != 0) {
+			if (cmd->convert_arg & CR_EDGE) {
 				if ((cmd->convert_arg & CR_INVERT) == 0) {
 					/* Trigger on +ve edge. */
 					conv = PCI230_ADC_TRIG_EXTP;
@@ -2035,7 +2080,7 @@ static void pci230_ai_start(struct comed
 				}
 			} else {
 				/* Backwards compatibility. */
-				if (cmd->convert_arg != 0) {
+				if (cmd->convert_arg) {
 					/* Trigger on +ve edge. */
 					conv = PCI230_ADC_TRIG_EXTP;
 				} else {
@@ -2045,31 +2090,39 @@ static void pci230_ai_start(struct comed
 			}
 			break;
 		case TRIG_INT:
-			/* Use CT2 output for software trigger due to problems
-			 * in differential mode on PCI230/260. */
+			/*
+			 * Use CT2 output for software trigger due to problems
+			 * in differential mode on PCI230/260.
+			 */
 			conv = PCI230_ADC_TRIG_Z2CT2;
 			break;
 		}
-		devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
-		    | conv;
+		devpriv->adccon =
+		    (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv;
 		outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
 		if (cmd->convert_src == TRIG_INT)
 			async->inttrig = pci230_ai_inttrig_convert;
 
-		/* Update FIFO interrupt trigger level, which is currently
-		 * set to "full".  */
+		/*
+		 * Update FIFO interrupt trigger level, which is currently
+		 * set to "full".
+		 */
 		pci230_ai_update_fifo_trigger_level(dev, s);
 		if (cmd->convert_src == TRIG_TIMER) {
 			/* Update timer gates. */
 			unsigned char zgat;
 
 			if (cmd->scan_begin_src != TRIG_FOLLOW) {
-				/* Conversion timer CT2 needs to be gated by
-				 * inverted output of monostable CT2. */
+				/*
+				 * Conversion timer CT2 needs to be gated by
+				 * inverted output of monostable CT2.
+				 */
 				zgat = GAT_CONFIG(2, GAT_NOUTNM2);
 			} else {
-				/* Conversion timer CT2 needs to be gated on
-				 * continuously. */
+				/*
+				 * Conversion timer CT2 needs to be gated on
+				 * continuously.
+				 */
 				zgat = GAT_CONFIG(2, GAT_VCC);
 			}
 			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
@@ -2111,11 +2164,13 @@ static void pci230_ai_start(struct comed
 				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
 				switch (cmd->scan_begin_src) {
 				case TRIG_TIMER:
-					/* Scan period timer CT1 needs to be
-					 * gated on to start counting. */
+					/*
+					 * Scan period timer CT1 needs to be
+					 * gated on to start counting.
+					 */
 					zgat = GAT_CONFIG(1, GAT_VCC);
-					outb(zgat, devpriv->iobase1
-					     + PCI230_ZGAT_SCE);
+					outb(zgat, devpriv->iobase1 +
+						   PCI230_ZGAT_SCE);
 					break;
 				case TRIG_INT:
 					async->inttrig =
@@ -2163,12 +2218,12 @@ static void pci230_handle_ai(struct come
 		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
 	} else if (devpriv->ai_scan_count == 0) {
 		todo = 0;
-	} else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
-		   || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
+	} else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) ||
+		   (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
 		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
 	} else {
-		todo = (devpriv->ai_scan_count * scanlen)
-		    - devpriv->ai_scan_pos;
+		todo = (devpriv->ai_scan_count * scanlen) -
+		       devpriv->ai_scan_pos;
 		if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
 			todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
 	}
@@ -2179,24 +2234,26 @@ static void pci230_handle_ai(struct come
 		if (fifoamount == 0) {
 			/* Read FIFO state. */
 			status_fifo = inw(dev->iobase + PCI230_ADCCON);
-			if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
-				/* Report error otherwise FIFO overruns will go
-				 * unnoticed by the caller. */
-				comedi_error(dev, "AI FIFO overrun");
+			if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) {
+				/*
+				 * Report error otherwise FIFO overruns will go
+				 * unnoticed by the caller.
+				 */
+				dev_err(dev->class_dev, "AI FIFO overrun\n");
 				events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
 				break;
-			} else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
+			} else if (status_fifo & PCI230_ADC_FIFO_EMPTY) {
 				/* FIFO empty. */
 				break;
-			} else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
+			} else if (status_fifo & PCI230_ADC_FIFO_HALF) {
 				/* FIFO half full. */
 				fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
 			} else {
 				/* FIFO not empty. */
 				if (devpriv->hwver > 0) {
 					/* Read PCI230+/260+ ADC FIFO level. */
-					fifoamount = inw(dev->iobase
-							 + PCI230P_ADCFFLEV);
+					fifoamount =
+					    inw(dev->iobase + PCI230P_ADCFFLEV);
 					if (fifoamount == 0) {
 						/* Shouldn't happen. */
 						break;
@@ -2209,7 +2266,7 @@ static void pci230_handle_ai(struct come
 		/* Read sample and store in Comedi's circular buffer. */
 		if (comedi_buf_put(s, pci230_ai_read(dev)) == 0) {
 			events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
-			comedi_error(dev, "AI buffer overflow");
+			dev_err(dev->class_dev, "AI buffer overflow\n");
 			break;
 		}
 		fifoamount--;
@@ -2229,8 +2286,8 @@ static void pci230_handle_ai(struct come
 		events |= COMEDI_CB_BLOCK;
 	}
 	async->events |= events;
-	if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
-			      COMEDI_CB_OVERFLOW)) != 0) {
+	if (async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
+			     COMEDI_CB_OVERFLOW)) {
 		/* disable hardware conversions */
 		pci230_ai_stop(dev, s);
 	} else {
@@ -2255,8 +2312,10 @@ static int pci230_ai_cmd(struct comedi_d
 	 * Determine which shared resources are needed.
 	 */
 	res_mask = 0;
-	/* Need Z2-CT2 to supply a conversion trigger source at a high
-	 * logic level, even if not doing timed conversions. */
+	/*
+	 * Need Z2-CT2 to supply a conversion trigger source at a high
+	 * logic level, even if not doing timed conversions.
+	 */
 	res_mask |= (1U << RES_Z2CT2);
 	if (cmd->scan_begin_src != TRIG_FOLLOW) {
 		/* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
@@ -2278,7 +2337,8 @@ static int pci230_ai_cmd(struct comedi_d
 		devpriv->ai_scan_count = 0;
 	devpriv->ai_scan_pos = 0;	/* Position within scan. */
 
-	/* Steps;
+	/*
+	 * Steps:
 	 * - Set channel scan list.
 	 * - Set channel gains.
 	 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
@@ -2323,20 +2383,24 @@ static int pci230_ai_cmd(struct comedi_d
 		if (diff) {
 			gainshift = 2 * chan;
 			if (devpriv->hwver == 0) {
-				/* Original PCI230/260 expects both inputs of
-				 * the differential channel to be enabled. */
+				/*
+				 * Original PCI230/260 expects both inputs of
+				 * the differential channel to be enabled.
+				 */
 				adcen |= 3 << gainshift;
 			} else {
-				/* PCI230+/260+ expects only one input of the
-				 * differential channel to be enabled. */
+				/*
+				 * PCI230+/260+ expects only one input of the
+				 * differential channel to be enabled.
+				 */
 				adcen |= 1 << gainshift;
 			}
 		} else {
 			gainshift = (chan & ~1);
 			adcen |= 1 << chan;
 		}
-		devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
-		    | (pci230_ai_gain[range] << gainshift);
+		devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
+				(pci230_ai_gain[range] << gainshift);
 	}
 
 	/* Set channel scan list. */
@@ -2345,43 +2409,53 @@ static int pci230_ai_cmd(struct comedi_d
 	/* Set channel gains. */
 	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
 
-	/* Set counter/timer 2 output high for use as the initial start
-	 * conversion source. */
+	/*
+	 * Set counter/timer 2 output high for use as the initial start
+	 * conversion source.
+	 */
 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
 
-	/* Temporarily use CT2 output as conversion trigger source and
-	 * temporarily set FIFO interrupt trigger level to 'full'. */
+	/*
+	 * Temporarily use CT2 output as conversion trigger source and
+	 * temporarily set FIFO interrupt trigger level to 'full'.
+	 */
 	adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
 
-	/* Enable and reset FIFO, specify FIFO trigger level full, specify
+	/*
+	 * Enable and reset FIFO, specify FIFO trigger level full, specify
 	 * uni/bip, se/diff, and temporarily set the start conversion source
 	 * to CT2 output.  Note that CT2 output is currently high, and this
 	 * will produce a false conversion trigger on some versions of the
-	 * PCI230/260, but that will be dealt with later. */
+	 * PCI230/260, but that will be dealt with later.
+	 */
 	devpriv->adccon = adccon;
 	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
 
-	/* Delay */
-	/* Failure to include this will result in the first few channels'-worth
+	/*
+	 * Delay -
+	 * Failure to include this will result in the first few channels'-worth
 	 * of data being corrupt, normally manifesting itself by large negative
 	 * voltages. It seems the board needs time to settle between the first
 	 * FIFO reset (above) and the second FIFO reset (below). Setting the
 	 * channel gains and scan list _before_ the first FIFO reset also
-	 * helps, though only slightly. */
-	udelay(25);
+	 * helps, though only slightly.
+	 */
+	usleep_range(25, 100);
 
 	/* Reset FIFO again. */
 	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		/* Set up CT2 as conversion timer, but gate it off for now.
+		/*
+		 * Set up CT2 as conversion timer, but gate it off for now.
 		 * Note, counter/timer output 2 can be monitored on the
-		 * connector: PCI230 pin 21, PCI260 pin 18. */
+		 * connector: PCI230 pin 21, PCI260 pin 18.
+		 */
 		zgat = GAT_CONFIG(2, GAT_GND);
 		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
 		/* Set counter/timer 2 to the specified conversion period. */
 		pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
-					cmd->flags & TRIG_ROUND_MASK);
+					cmd->flags);
 		if (cmd->scan_begin_src != TRIG_FOLLOW) {
 			/*
 			 * Set up monostable on CT0 output for scan timing.  A
@@ -2398,8 +2472,8 @@ static int pci230_ai_cmd(struct comedi_d
 			zgat = GAT_CONFIG(0, GAT_VCC);
 			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
 			pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
-						((uint64_t) cmd->convert_arg
-						 * cmd->scan_end_arg),
+						((uint64_t)cmd->convert_arg *
+						 cmd->scan_end_arg),
 						TRIG_ROUND_UP);
 			if (cmd->scan_begin_src == TRIG_TIMER) {
 				/*
@@ -2412,9 +2486,7 @@ static int pci230_ai_cmd(struct comedi_d
 				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
 				pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
 							cmd->scan_begin_arg,
-							cmd->
-							flags &
-							TRIG_ROUND_MASK);
+							cmd->flags);
 			}
 		}
 	}
@@ -2452,9 +2524,11 @@ static irqreturn_t pci230_interrupt(int
 
 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
 	valid_status_int = devpriv->int_en & status_int;
-	/* Disable triggered interrupts.
+	/*
+	 * Disable triggered interrupts.
 	 * (Only those interrupts that need re-enabling, are, later in the
-	 * handler).  */
+	 * handler).
+	 */
 	devpriv->ier = devpriv->int_en & ~status_int;
 	outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
 	devpriv->intr_running = 1;
@@ -2469,19 +2543,19 @@ static irqreturn_t pci230_interrupt(int
 	 * two.
 	 */
 
-	if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
+	if (valid_status_int & PCI230_INT_ZCLK_CT1) {
 		s = dev->write_subdev;
 		pci230_handle_ao_nofifo(dev, s);
 		comedi_event(dev, s);
 	}
 
-	if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
+	if (valid_status_int & PCI230P2_INT_DAC) {
 		s = dev->write_subdev;
 		pci230_handle_ao_fifo(dev, s);
 		comedi_event(dev, s);
 	}
 
-	if ((valid_status_int & PCI230_INT_ADC) != 0) {
+	if (valid_status_int & PCI230_INT_ADC) {
 		s = dev->read_subdev;
 		pci230_handle_ai(dev, s);
 		comedi_event(dev, s);
@@ -2511,8 +2585,10 @@ static bool pci230_match_pci_board(const
 	/* Looking for a '+' model.  First check length of registers. */
 	if (pci_resource_len(pci_dev, 3) < 32)
 		return false;	/* Not a '+' model. */
-	/* TODO: temporarily enable PCI device and read the hardware version
-	 * register.  For now, assume it's okay. */
+	/*
+	 * TODO: temporarily enable PCI device and read the hardware version
+	 * register.  For now, assume it's okay.
+	 */
 	return true;
 }
 
@@ -2601,8 +2677,10 @@ static int pci230_attach_common(struct c
 	if (rc)
 		return rc;
 
-	/* Read base addresses of the PCI230's two I/O regions from PCI
-	 * configuration register. */
+	/*
+	 * Read base addresses of the PCI230's two I/O regions from PCI
+	 * configuration register.
+	 */
 	iobase1 = pci_resource_start(pci_dev, 2);
 	iobase2 = pci_resource_start(pci_dev, 3);
 	dev_dbg(dev->class_dev,
@@ -2612,8 +2690,10 @@ static int pci230_attach_common(struct c
 	dev->iobase = iobase2;
 	/* Read bits of DACCON register - only the output range. */
 	devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
-	/* Read hardware version register and set extended function register
-	 * if they exist. */
+	/*
+	 * Read hardware version register and set extended function register
+	 * if they exist.
+	 */
 	if (pci_resource_len(pci_dev, 3) >= 32) {
 		unsigned short extfunc = 0;
 
@@ -2627,25 +2707,29 @@ static int pci230_attach_common(struct c
 		}
 		if (devpriv->hwver > 0) {
 			if (!thisboard->have_dio) {
-				/* No DIO ports.  Route counters' external gates
+				/*
+				 * No DIO ports.  Route counters' external gates
 				 * to the EXTTRIG signal (PCI260+ pin 17).
 				 * (Otherwise, they would be routed to DIO
 				 * inputs PC0, PC1 and PC2 which don't exist
-				 * on PCI260[+].) */
+				 * on PCI260[+].)
+				 */
 				extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
 			}
-			if ((thisboard->ao_chans > 0)
-			    && (devpriv->hwver >= 2)) {
+			if ((thisboard->ao_chans > 0) &&
+			    (devpriv->hwver >= 2)) {
 				/* Enable DAC FIFO functionality. */
 				extfunc |= PCI230P2_EXTFUNC_DACFIFO;
 			}
 		}
 		outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
-		if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
-			/* Temporarily enable DAC FIFO, reset it and disable
-			 * FIFO wraparound. */
-			outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
-			     | PCI230P2_DAC_FIFO_RESET,
+		if (extfunc & PCI230P2_EXTFUNC_DACFIFO) {
+			/*
+			 * Temporarily enable DAC FIFO, reset it and disable
+			 * FIFO wraparound.
+			 */
+			outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN |
+			     PCI230P2_DAC_FIFO_RESET,
 			     dev->iobase + PCI230_DACCON);
 			/* Clear DAC FIFO channel enable register. */
 			outw(0, dev->iobase + PCI230P2_DACEN);
@@ -2657,8 +2741,8 @@ static int pci230_attach_common(struct c
 	outb(0, devpriv->iobase1 + PCI230_INT_SCE);
 	/* Set ADC to a reasonable state. */
 	devpriv->adcg = 0;
-	devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
-	    | PCI230_ADC_IR_BIP;
+	devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE |
+			  PCI230_ADC_IR_BIP;
 	outw(1 << 0, dev->iobase + PCI230_ADCEN);
 	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
 	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
@@ -2682,13 +2766,13 @@ static int pci230_attach_common(struct c
 	s->n_chan = thisboard->ai_chans;
 	s->maxdata = (1 << thisboard->ai_bits) - 1;
 	s->range_table = &pci230_ai_range;
-	s->insn_read = &pci230_ai_rinsn;
+	s->insn_read = pci230_ai_rinsn;
 	s->len_chanlist = 256;	/* but there are restrictions. */
 	if (dev->irq) {
 		dev->read_subdev = s;
 		s->subdev_flags |= SDF_CMD_READ;
-		s->do_cmd = &pci230_ai_cmd;
-		s->do_cmdtest = &pci230_ai_cmdtest;
+		s->do_cmd = pci230_ai_cmd;
+		s->do_cmdtest = pci230_ai_cmdtest;
 		s->cancel = pci230_ai_cancel;
 	}
 
@@ -2700,14 +2784,14 @@ static int pci230_attach_common(struct c
 		s->n_chan = thisboard->ao_chans;
 		s->maxdata = (1 << thisboard->ao_bits) - 1;
 		s->range_table = &pci230_ao_range;
-		s->insn_write = &pci230_ao_winsn;
-		s->insn_read = &pci230_ao_rinsn;
+		s->insn_write = pci230_ao_winsn;
+		s->insn_read = pci230_ao_rinsn;
 		s->len_chanlist = thisboard->ao_chans;
 		if (dev->irq) {
 			dev->write_subdev = s;
 			s->subdev_flags |= SDF_CMD_WRITE;
-			s->do_cmd = &pci230_ao_cmd;
-			s->do_cmdtest = &pci230_ao_cmdtest;
+			s->do_cmd = pci230_ao_cmd;
+			s->do_cmdtest = pci230_ao_cmdtest;
 			s->cancel = pci230_ao_cancel;
 		}
 	} else {
@@ -2748,7 +2832,7 @@ static int pci230_attach(struct comedi_d
 }
 
 static int pci230_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
+			      unsigned long context_unused)
 {
 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
 	int rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci236.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci236.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci236.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci236.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * comedi/drivers/amplc_pci236.c
+ * Driver for Amplicon PCI236 DIO boards.
+ *
+ * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.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.
+ */
+/*
+ * Driver: amplc_pci236
+ * Description: Amplicon PCI236
+ * Author: Ian Abbott <abbotti@mev.co.uk>
+ * Devices: [Amplicon] PCI236 (amplc_pci236)
+ * Updated: Fri, 25 Jul 2014 15:32:40 +0000
+ * Status: works
+ *
+ * Configuration options:
+ *   none
+ *
+ * Manual configuration of PCI board (PCI236) is not supported; it is
+ * configured automatically.
+ *
+ * The PCI236 board has a single 8255 appearing as subdevice 0.
+ *
+ * Subdevice 1 pretends to be a digital input device, but it always
+ * returns 0 when read. However, if you run a command with
+ * scan_begin_src=TRIG_EXT, a rising edge on port C bit 3 acts as an
+ * external trigger, which can be used to wake up tasks.  This is like
+ * the comedi_parport device.  If no interrupt is connected, then
+ * subdevice 1 is unused.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include "../comedidev.h"
+
+#include "amplc_pc236.h"
+#include "plx9052.h"
+
+/* Disable, and clear, interrupts */
+#define PCI236_INTR_DISABLE	(PLX9052_INTCSR_LI1POL |	\
+				 PLX9052_INTCSR_LI2POL |	\
+				 PLX9052_INTCSR_LI1SEL |	\
+				 PLX9052_INTCSR_LI1CLRINT)
+
+/* Enable, and clear, interrupts */
+#define PCI236_INTR_ENABLE	(PLX9052_INTCSR_LI1ENAB |	\
+				 PLX9052_INTCSR_LI1POL |	\
+				 PLX9052_INTCSR_LI2POL |	\
+				 PLX9052_INTCSR_PCIENAB |	\
+				 PLX9052_INTCSR_LI1SEL |	\
+				 PLX9052_INTCSR_LI1CLRINT)
+
+static void pci236_intr_update_cb(struct comedi_device *dev, bool enable)
+{
+	struct pc236_private *devpriv = dev->private;
+
+	/* this will also clear the "local interrupt 1" latch */
+	outl(enable ? PCI236_INTR_ENABLE : PCI236_INTR_DISABLE,
+	     devpriv->lcr_iobase + PLX9052_INTCSR);
+}
+
+static bool pci236_intr_chk_clr_cb(struct comedi_device *dev)
+{
+	struct pc236_private *devpriv = dev->private;
+
+	/* check if interrupt occurred */
+	if (!(inl(devpriv->lcr_iobase + PLX9052_INTCSR) &
+	      PLX9052_INTCSR_LI1STAT))
+		return false;
+	/* clear the interrupt */
+	pci236_intr_update_cb(dev, devpriv->enable_irq);
+	return true;
+}
+
+static const struct pc236_board pc236_pci_board = {
+	.name = "pci236",
+	.intr_update_cb = pci236_intr_update_cb,
+	.intr_chk_clr_cb = pci236_intr_chk_clr_cb,
+};
+
+static int pci236_auto_attach(struct comedi_device *dev,
+			      unsigned long context_unused)
+{
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+	struct pc236_private *devpriv;
+	unsigned long iobase;
+	int ret;
+
+	dev_info(dev->class_dev, "amplc_pci236: attach pci %s\n",
+		 pci_name(pci_dev));
+
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+	if (!devpriv)
+		return -ENOMEM;
+
+	dev->board_ptr = &pc236_pci_board;
+	dev->board_name = pc236_pci_board.name;
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
+	devpriv->lcr_iobase = pci_resource_start(pci_dev, 1);
+	iobase = pci_resource_start(pci_dev, 2);
+	return amplc_pc236_common_attach(dev, iobase, pci_dev->irq,
+					 IRQF_SHARED);
+}
+
+static void pci236_detach(struct comedi_device *dev)
+{
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	comedi_pci_disable(dev);
+}
+
+static struct comedi_driver amplc_pci236_driver = {
+	.driver_name = "amplc_pci236",
+	.module = THIS_MODULE,
+	.auto_attach = pci236_auto_attach,
+	.detach = pci236_detach,
+};
+
+static const struct pci_device_id pci236_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x0009) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, pci236_pci_table);
+
+static int amplc_pci236_pci_probe(struct pci_dev *dev,
+				  const struct pci_device_id *id)
+{
+	return comedi_pci_auto_config(dev, &amplc_pci236_driver,
+				      id->driver_data);
+}
+
+static struct pci_driver amplc_pci236_pci_driver = {
+	.name		= "amplc_pci236",
+	.id_table	= pci236_pci_table,
+	.probe		= &amplc_pci236_pci_probe,
+	.remove		= comedi_pci_auto_unconfig,
+};
+
+module_comedi_pci_driver(amplc_pci236_driver, amplc_pci236_pci_driver);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi driver for Amplicon PCI236 DIO boards");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci263.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci263.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/amplc_pci263.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/amplc_pci263.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,11 +37,6 @@ The state of the outputs can be read.
 
 #include "../comedidev.h"
 
-#define PCI263_DRIVER_NAME	"amplc_pci263"
-
-/* PCI263 PCI configuration register information */
-#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
-
 static int pci263_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn,
@@ -88,14 +83,14 @@ static int pci263_auto_attach(struct com
 }
 
 static struct comedi_driver amplc_pci263_driver = {
-	.driver_name	= PCI263_DRIVER_NAME,
+	.driver_name	= "amplc_pci263",
 	.module		= THIS_MODULE,
 	.auto_attach	= pci263_auto_attach,
 	.detach		= comedi_pci_disable,
 };
 
 static const struct pci_device_id pci263_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x000c) },
 	{0}
 };
 MODULE_DEVICE_TABLE(pci, pci263_pci_table);
@@ -108,7 +103,7 @@ static int amplc_pci263_pci_probe(struct
 }
 
 static struct pci_driver amplc_pci263_pci_driver = {
-	.name		= PCI263_DRIVER_NAME,
+	.name		= "amplc_pci263",
 	.id_table	= pci263_pci_table,
 	.probe		= &amplc_pci263_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_das16_cs.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_das16_cs.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_das16_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_das16_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,6 @@ Status: experimental
 #include "comedi_fc.h"
 #include "8253.h"
 
-#define DAS16CS_SIZE			18
-
 #define DAS16CS_ADC_DATA		0
 #define DAS16CS_DIO_MUX			2
 #define DAS16CS_MISC1			4
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcidas64.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcidas64.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcidas64.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcidas64.c	2014-09-28 17:29:07.000000000 -0400
@@ -80,8 +80,6 @@ TODO:
 	make ao fifo size adjustable like ai fifo
 */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -179,7 +177,7 @@ enum read_write_registers {
 	DAC_FIFO_REG = 0x300,
 };
 
-/* devpriv->dio_counter_iobase registers */
+/* dev->mmio registers */
 enum dio_counter_registers {
 	DIO_8255_OFFSET = 0x0,
 	DO_REG = 0x20,
@@ -636,8 +634,8 @@ static inline unsigned int ai_dma_ring_c
 {
 	if (board->layout == LAYOUT_4020)
 		return MAX_AI_DMA_RING_COUNT;
-	else
-		return MIN_AI_DMA_RING_COUNT;
+
+	return MIN_AI_DMA_RING_COUNT;
 }
 
 static const int bytes_in_sample = 2;
@@ -1045,9 +1043,9 @@ static inline unsigned short se_diff_bit
 	if ((thisboard->layout == LAYOUT_64XX && !use_differential) ||
 	    (thisboard->layout == LAYOUT_60XX && use_differential))
 		return ADC_SE_DIFF_BIT;
-	else
-		return 0;
-};
+
+	return 0;
+}
 
 struct ext_clock_info {
 	/*  master clock divisor to use for scans with external master clock */
@@ -1064,12 +1062,11 @@ struct pcidas64_private {
 	/*  base addresses (ioremapped) */
 	void __iomem *plx9080_iobase;
 	void __iomem *main_iobase;
-	void __iomem *dio_counter_iobase;
 	/*  local address (used by dma controller) */
 	uint32_t local0_iobase;
 	uint32_t local1_iobase;
 	/*  number of analog input samples remaining */
-	volatile unsigned int ai_count;
+	unsigned int ai_count;
 	/*  dma buffers for analog input */
 	uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];
 	/*  physical addresses of ai dma buffers */
@@ -1081,7 +1078,7 @@ struct pcidas64_private {
 	dma_addr_t ai_dma_desc_bus_addr;
 	/*  index of the ai dma descriptor/buffer
 	 *  that is currently being used */
-	volatile unsigned int ai_dma_index;
+	unsigned int ai_dma_index;
 	/*  dma buffers for analog output */
 	uint16_t *ao_buffer[AO_DMA_RING_COUNT];
 	/*  physical addresses of ao dma buffers */
@@ -1089,35 +1086,35 @@ struct pcidas64_private {
 	struct plx_dma_desc *ao_dma_desc;
 	dma_addr_t ao_dma_desc_bus_addr;
 	/*  keeps track of buffer where the next ao sample should go */
-	volatile unsigned int ao_dma_index;
+	unsigned int ao_dma_index;
 	/*  number of analog output samples remaining */
-	volatile unsigned long ao_count;
+	unsigned long ao_count;
 	/*  remember what the analog outputs are set to, to allow readback */
-	volatile unsigned int ao_value[2];
+	unsigned int ao_value[2];
 	unsigned int hw_revision;	/*  stc chip hardware revision number */
 	/*  last bits sent to INTR_ENABLE_REG register */
-	volatile unsigned int intr_enable_bits;
+	unsigned int intr_enable_bits;
 	/*  last bits sent to ADC_CONTROL1_REG register */
-	volatile uint16_t adc_control1_bits;
+	uint16_t adc_control1_bits;
 	/*  last bits sent to FIFO_SIZE_REG register */
-	volatile uint16_t fifo_size_bits;
+	uint16_t fifo_size_bits;
 	/*  last bits sent to HW_CONFIG_REG register */
-	volatile uint16_t hw_config_bits;
-	volatile uint16_t dac_control1_bits;
+	uint16_t hw_config_bits;
+	uint16_t dac_control1_bits;
 	/*  last bits written to plx9080 control register */
-	volatile uint32_t plx_control_bits;
+	uint32_t plx_control_bits;
 	/*  last bits written to plx interrupt control and status register */
-	volatile uint32_t plx_intcsr_bits;
+	uint32_t plx_intcsr_bits;
 	/*  index of calibration source readable through ai ch0 */
-	volatile int calibration_source;
+	int calibration_source;
 	/*  bits written to i2c calibration/range register */
-	volatile uint8_t i2c_cal_range_bits;
+	uint8_t i2c_cal_range_bits;
 	/*  configure digital triggers to trigger on falling edge */
-	volatile unsigned int ext_trig_falling;
+	unsigned int ext_trig_falling;
 	/*  states of various devices stored to enable read-back */
 	unsigned int ad8402_state[2];
 	unsigned int caldac_state[8];
-	volatile short ai_cmd_running;
+	short ai_cmd_running;
 	unsigned int ai_fifo_segment_length;
 	struct ext_clock_info ext_clock;
 	unsigned short ao_bounce_buffer[DAC_FIFO_SIZE];
@@ -1160,7 +1157,7 @@ static unsigned int ai_range_bits_6xxx(c
 		bits = 0x700;
 		break;
 	default:
-		comedi_error(dev, "bug! in ai_range_bits_6xxx");
+		dev_err(dev->class_dev, "bug! in %s\n", __func__);
 		break;
 	}
 	if (range->min == 0)
@@ -1180,16 +1177,16 @@ static unsigned int hw_revision(const st
 }
 
 static void set_dac_range_bits(struct comedi_device *dev,
-			       volatile uint16_t *bits, unsigned int channel,
+			       uint16_t *bits, unsigned int channel,
 			       unsigned int range)
 {
 	const struct pcidas64_board *thisboard = comedi_board(dev);
 	unsigned int code = thisboard->ao_range_code[range];
 
 	if (channel > 1)
-		comedi_error(dev, "bug! bad channel?");
+		dev_err(dev->class_dev, "bug! bad channel?\n");
 	if (code & ~0x3)
-		comedi_error(dev, "bug! bad range code?");
+		dev_err(dev->class_dev, "bug! bad range code?\n");
 
 	*bits &= ~(0x3 << (2 * channel));
 	*bits |= code << (2 * channel);
@@ -1531,10 +1528,10 @@ static int alloc_and_init_dma_members(st
 
 static inline void warn_external_queue(struct comedi_device *dev)
 {
-	comedi_error(dev,
-		     "AO command and AI external channel queue cannot be used simultaneously.");
-	comedi_error(dev,
-		     "Use internal AI channel queue (channels must be consecutive and use same range/aref)");
+	dev_err(dev->class_dev,
+		"AO command and AI external channel queue cannot be used simultaneously\n");
+	dev_err(dev->class_dev,
+		"Use internal AI channel queue (channels must be consecutive and use same range/aref)\n");
 }
 
 /* Their i2c requires a huge delay on setting clock or data high for some reason */
@@ -1648,7 +1645,8 @@ static void i2c_write(struct comedi_devi
 
 	/*  get acknowledge */
 	if (i2c_read_ack(dev) != 0) {
-		comedi_error(dev, "i2c write failed: no acknowledge");
+		dev_err(dev->class_dev, "%s failed: no acknowledge\n",
+			__func__);
 		i2c_stop(dev);
 		return;
 	}
@@ -1656,7 +1654,8 @@ static void i2c_write(struct comedi_devi
 	for (i = 0; i < length; i++) {
 		i2c_write_byte(dev, data[i]);
 		if (i2c_read_ack(dev) != 0) {
-			comedi_error(dev, "i2c write failed: no acknowledge");
+			dev_err(dev->class_dev, "%s failed: no acknowledge\n",
+				__func__);
 			i2c_stop(dev);
 			return;
 		}
@@ -1769,6 +1768,7 @@ static int ai_rinsn(struct comedi_device
 		 *  as it is very slow */
 		if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
 			uint8_t i2c_data = devpriv->i2c_cal_range_bits;
+
 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
 				  sizeof(i2c_data));
 		}
@@ -1796,8 +1796,7 @@ static int ai_rinsn(struct comedi_device
 			return ret;
 
 		if (thisboard->layout == LAYOUT_4020)
-			data[n] = readl(devpriv->dio_counter_iobase +
-					ADC_FIFO_REG) & 0xffff;
+			data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff;
 		else
 			data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG);
 	}
@@ -1874,7 +1873,6 @@ static int ai_config_master_clock_4020(s
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	data[4] = divisor;
@@ -1890,10 +1888,8 @@ static int ai_config_master_clock(struct
 	switch (thisboard->layout) {
 	case LAYOUT_4020:
 		return ai_config_master_clock_4020(dev, data);
-		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	return -EINVAL;
@@ -1907,16 +1903,12 @@ static int ai_config_insn(struct comedi_
 	switch (id) {
 	case INSN_CONFIG_ALT_SOURCE:
 		return ai_config_calibration_source(dev, data);
-		break;
 	case INSN_CONFIG_BLOCK_SIZE:
 		return ai_config_block_size(dev, data);
-		break;
 	case INSN_CONFIG_TIMER_1:
 		return ai_config_master_clock(dev, data);
-		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return -EINVAL;
 }
@@ -1991,8 +1983,6 @@ static void check_adc_timing(struct come
 			scan_divisor = min_scan_divisor;
 		cmd->scan_begin_arg = scan_divisor * TIMER_BASE;
 	}
-
-	return;
 }
 
 static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev,
@@ -2162,8 +2152,8 @@ static int use_hw_sample_counter(struct
 
 	if (cmd->stop_src == TRIG_COUNT && cmd->stop_arg <= max_counter_value)
 		return 1;
-	else
-		return 0;
+
+	return 0;
 }
 
 static void setup_sample_counters(struct comedi_device *dev,
@@ -2224,7 +2214,6 @@ static uint32_t ai_scan_counter_6xxx(str
 		break;
 	default:
 		return 0;
-		break;
 	}
 	return count - 3;
 }
@@ -2243,7 +2232,7 @@ static uint32_t ai_convert_counter_4020(
 		divisor = devpriv->ext_clock.divisor;
 		break;
 	default:		/*  should never happen */
-		comedi_error(dev, "bug! failed to set ai pacing!");
+		dev_err(dev->class_dev, "bug! failed to set ai pacing!\n");
 		divisor = 1000;
 		break;
 	}
@@ -2454,6 +2443,7 @@ static int setup_channel_queue(struct co
 		 *  as it is very slow */
 		if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
 			uint8_t i2c_data = devpriv->i2c_cal_range_bits;
+
 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
 				  sizeof(i2c_data));
 		}
@@ -2694,7 +2684,7 @@ static void pio_drain_ai_fifo_32(struct
 
 	}
 	for (i = 0; read_code != write_code && i < max_transfer;) {
-		fifo_data = readl(devpriv->dio_counter_iobase + ADC_FIFO_REG);
+		fifo_data = readl(dev->mmio + ADC_FIFO_REG);
 		cfc_write_to_buffer(s, fifo_data & 0xffff);
 		i++;
 		if (i < max_transfer) {
@@ -2775,7 +2765,7 @@ static void handle_ai_interrupt(struct c
 
 	/*  check for fifo overrun */
 	if (status & ADC_OVERRUN_BIT) {
-		comedi_error(dev, "fifo overrun");
+		dev_err(dev->class_dev, "fifo overrun\n");
 		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 	}
 	/*  spin lock makes sure no one else changes plx dma control reg */
@@ -3138,7 +3128,8 @@ static void set_dac_select_reg(struct co
 	first_channel = CR_CHAN(cmd->chanlist[0]);
 	last_channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
 	if (last_channel < first_channel)
-		comedi_error(dev, "bug! last ao channel < first ao channel");
+		dev_err(dev->class_dev,
+			"bug! last ao channel < first ao channel\n");
 
 	bits = (first_channel & 0x7) | (last_channel & 0x7) << 3;
 
@@ -3161,7 +3152,7 @@ static void set_dac_interval_regs(struct
 
 	divisor = get_ao_divisor(cmd->scan_begin_arg, cmd->flags);
 	if (divisor > max_counter_value) {
-		comedi_error(dev, "bug! ao divisor too big");
+		dev_err(dev->class_dev, "bug! ao divisor too big\n");
 		divisor = max_counter_value;
 	}
 	writew(divisor & 0xffff,
@@ -3381,32 +3372,31 @@ static int ao_cancel(struct comedi_devic
 static int dio_callback(int dir, int port, int data, unsigned long arg)
 {
 	void __iomem *iobase = (void __iomem *)arg;
+
 	if (dir) {
 		writeb(data, iobase + port);
 		return 0;
-	} else {
-		return readb(iobase + port);
 	}
+	return readb(iobase + port);
 }
 
 static int dio_callback_4020(int dir, int port, int data, unsigned long arg)
 {
 	void __iomem *iobase = (void __iomem *)arg;
+
 	if (dir) {
 		writew(data, iobase + 2 * port);
 		return 0;
-	} else {
-		return readw(iobase + 2 * port);
 	}
+	return readw(iobase + 2 * port);
 }
 
 static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
-	struct pcidas64_private *devpriv = dev->private;
 	unsigned int bits;
 
-	bits = readb(devpriv->dio_counter_iobase + DI_REG);
+	bits = readb(dev->mmio + DI_REG);
 	bits &= 0xf;
 	data[1] = bits;
 	data[0] = 0;
@@ -3419,10 +3409,8 @@ static int do_wbits(struct comedi_device
 		    struct comedi_insn *insn,
 		    unsigned int *data)
 {
-	struct pcidas64_private *devpriv = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
+		writeb(s->state, dev->mmio + DO_REG);
 
 	data[1] = s->state;
 
@@ -3434,15 +3422,13 @@ static int dio_60xx_config_insn(struct c
 				struct comedi_insn *insn,
 				unsigned int *data)
 {
-	struct pcidas64_private *devpriv = dev->private;
 	int ret;
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 	if (ret)
 		return ret;
 
-	writeb(s->io_bits,
-	       devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
+	writeb(s->io_bits, dev->mmio + DIO_DIRECTION_60XX_REG);
 
 	return insn->n;
 }
@@ -3452,14 +3438,10 @@ static int dio_60xx_wbits(struct comedi_
 			  struct comedi_insn *insn,
 			  unsigned int *data)
 {
-	struct pcidas64_private *devpriv = dev->private;
-
-	if (comedi_dio_update_state(s, data)) {
-		writeb(s->state,
-		       devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
-	}
+	if (comedi_dio_update_state(s, data))
+		writeb(s->state, dev->mmio + DIO_DATA_60XX_REG);
 
-	data[1] = readb(devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
+	data[1] = readb(dev->mmio + DIO_DATA_60XX_REG);
 
 	return insn->n;
 }
@@ -3496,7 +3478,7 @@ static int caldac_8800_write(struct come
 	static const int caldac_8800_udelay = 1;
 
 	if (address >= num_caldac_channels) {
-		comedi_error(dev, "illegal caldac channel");
+		dev_err(dev->class_dev, "illegal caldac channel\n");
 		return -1;
 	}
 	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
@@ -3568,9 +3550,8 @@ static int caldac_i2c_write(struct comed
 		serial_bytes[0] = GAIN_1_3;
 		break;
 	default:
-		comedi_error(dev, "invalid caldac channel\n");
+		dev_err(dev->class_dev, "invalid caldac channel\n");
 		return -1;
-		break;
 	}
 	serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf);
 	serial_bytes[2] = value & 0xff;
@@ -3863,8 +3844,7 @@ static int setup_subdevices(struct comed
 			ret = subdev_8255_init(dev, s, dio_callback_4020,
 					       (unsigned long)dio_8255_iobase);
 		} else {
-			dio_8255_iobase =
-				devpriv->dio_counter_iobase + DIO_8255_OFFSET;
+			dio_8255_iobase = dev->mmio + DIO_8255_OFFSET;
 			ret = subdev_8255_init(dev, s, dio_callback,
 					       (unsigned long)dio_8255_iobase);
 		}
@@ -3965,10 +3945,9 @@ static int auto_attach(struct comedi_dev
 
 	devpriv->plx9080_iobase = pci_ioremap_bar(pcidev, 0);
 	devpriv->main_iobase = pci_ioremap_bar(pcidev, 2);
-	devpriv->dio_counter_iobase = pci_ioremap_bar(pcidev, 3);
+	dev->mmio = pci_ioremap_bar(pcidev, 3);
 
-	if (!devpriv->plx9080_iobase || !devpriv->main_iobase
-	    || !devpriv->dio_counter_iobase) {
+	if (!devpriv->plx9080_iobase || !devpriv->main_iobase || !dev->mmio) {
 		dev_warn(dev->class_dev, "failed to remap io memory\n");
 		return -ENOMEM;
 	}
@@ -3997,12 +3976,13 @@ static int auto_attach(struct comedi_dev
 		devpriv->hw_revision);
 	init_plx9080(dev);
 	init_stc_registers(dev);
-	/*  get irq */
-	if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
-			"cb_pcidas64", dev)) {
+
+	retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
+			     dev->board_name, dev);
+	if (retval) {
 		dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
 			pcidev->irq);
-		return -EINVAL;
+		return retval;
 	}
 	dev->irq = pcidev->irq;
 	dev_dbg(dev->class_dev, "irq %u\n", dev->irq);
@@ -4031,8 +4011,8 @@ static void detach(struct comedi_device
 			}
 			if (devpriv->main_iobase)
 				iounmap(devpriv->main_iobase);
-			if (devpriv->dio_counter_iobase)
-				iounmap(devpriv->dio_counter_iobase);
+			if (dev->mmio)
+				iounmap(dev->mmio);
 			/*  free pci dma buffers */
 			for (i = 0; i < ai_dma_ring_count(thisboard); i++) {
 				if (devpriv->ai_buffer[i])
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcidas.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcidas.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcidas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcidas.c	2014-09-28 17:29:07.000000000 -0400
@@ -461,7 +461,6 @@ static int ai_config_insn(struct comedi_
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return insn->n;
 }
@@ -622,7 +621,7 @@ static int caldac_8800_write(struct come
 	static const int caldac_8800_udelay = 1;
 
 	if (address >= num_caldac_channels) {
-		comedi_error(dev, "illegal caldac channel");
+		dev_err(dev->class_dev, "illegal caldac channel\n");
 		return -1;
 	}
 
@@ -774,9 +773,8 @@ static int cb_pcidas_trimpot_write(struc
 		trimpot_8402_write(dev, channel, value);
 		break;
 	default:
-		comedi_error(dev, "driver bug?");
+		dev_err(dev->class_dev, "driver bug?\n");
 		return -1;
-		break;
 	}
 
 	return 1;
@@ -1251,9 +1249,8 @@ static int cb_pcidas_ao_cmd(struct comed
 		break;
 	default:
 		spin_unlock_irqrestore(&dev->spinlock, flags);
-		comedi_error(dev, "error setting dac pacer source");
+		dev_err(dev->class_dev, "error setting dac pacer source\n");
 		return -1;
-		break;
 	}
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
@@ -1303,7 +1300,7 @@ static void handle_ao_interrupt(struct c
 			if (cmd->stop_src == TRIG_NONE ||
 			    (cmd->stop_src == TRIG_COUNT
 			     && devpriv->ao_count)) {
-				comedi_error(dev, "dac fifo underflow");
+				dev_err(dev->class_dev, "dac fifo underflow\n");
 				async->events |= COMEDI_CB_ERROR;
 			}
 			async->events |= COMEDI_CB_EOA;
@@ -1414,8 +1411,8 @@ static irqreturn_t cb_pcidas_interrupt(i
 		     devpriv->control_status + INT_ADCFIFO);
 		spin_unlock_irqrestore(&dev->spinlock, flags);
 	} else if (status & EOAI) {
-		comedi_error(dev,
-			     "bug! encountered end of acquisition interrupt?");
+		dev_err(dev->class_dev,
+			"bug! encountered end of acquisition interrupt?\n");
 		/*  clear EOA interrupt latch */
 		spin_lock_irqsave(&dev->spinlock, flags);
 		outw(devpriv->adc_fifo_bits | EOAI,
@@ -1424,7 +1421,7 @@ static irqreturn_t cb_pcidas_interrupt(i
 	}
 	/* check for fifo overflow */
 	if (status & LADFUL) {
-		comedi_error(dev, "fifo overflow");
+		dev_err(dev->class_dev, "fifo overflow\n");
 		/*  clear overflow interrupt latch */
 		spin_lock_irqsave(&dev->spinlock, flags);
 		outw(devpriv->adc_fifo_bits | LADFUL,
@@ -1474,11 +1471,12 @@ static int cb_pcidas_auto_attach(struct
 	outl(INTCSR_INBOX_INTR_STATUS,
 	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
 
-	if (request_irq(pcidev->irq, cb_pcidas_interrupt,
-			IRQF_SHARED, dev->driver->driver_name, dev)) {
+	ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
+			  dev->board_name, dev);
+	if (ret) {
 		dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
 			pcidev->irq);
-		return -EINVAL;
+		return ret;
 	}
 	dev->irq = pcidev->irq;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcimdas.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcimdas.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/cb_pcimdas.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/cb_pcimdas.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,9 +47,6 @@ See http://www.mccdaq.com/PDFs/Manuals/p
 
 /* Registers for the PCIM-DAS1602/16 */
 
-/* sizes of io regions (bytes) */
-#define BADR3_SIZE 16
-
 /* DAC Offsets */
 #define ADC_TRIG 0
 #define DAC0_OFFSET 2
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/comedi_test.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/comedi_test.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/comedi_test.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/comedi_test.c	2014-09-28 17:29:07.000000000 -0400
@@ -146,10 +146,8 @@ static unsigned short fake_waveform(stru
 	switch (channel) {
 	case SAWTOOTH_CHAN:
 		return fake_sawtooth(dev, range, current_time);
-		break;
 	case SQUARE_CHAN:
 		return fake_squarewave(dev, range, current_time);
-		break;
 	default:
 		break;
 	}
@@ -305,8 +303,8 @@ static int waveform_ai_cmd(struct comedi
 	struct comedi_cmd *cmd = &s->async->cmd;
 
 	if (cmd->flags & TRIG_RT) {
-		comedi_error(dev,
-			     "commands at RT priority not supported in this driver");
+		dev_err(dev->class_dev,
+			"commands at RT priority not supported in this driver\n");
 		return -1;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/contec_pci_dio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/contec_pci_dio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/contec_pci_dio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/contec_pci_dio.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,8 +30,6 @@ Configuration Options: not applicable, u
 
 #include "../comedidev.h"
 
-#define PCI_DEVICE_ID_PIO1616L 0x8172
-
 /*
  * Register map
  */
@@ -110,7 +108,7 @@ static int contec_pci_dio_pci_probe(stru
 }
 
 static const struct pci_device_id contec_pci_dio_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CONTEC, 0x8172) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/daqboard2000.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/daqboard2000.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/daqboard2000.c	2014-08-07 04:58:55.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/daqboard2000.c	2014-09-28 21:41:31.000000000 -0400
@@ -113,8 +113,8 @@ Configuration options: not applicable, u
 
 #define DAQBOARD2000_FIRMWARE		"/*(DEBLOBBED)*/"
 
-#define DAQBOARD2000_SUBSYSTEM_IDS2 	0x0002	/* Daqboard/2000 - 2 Dacs */
-#define DAQBOARD2000_SUBSYSTEM_IDS4 	0x0004	/* Daqboard/2000 - 4 Dacs */
+#define DAQBOARD2000_SUBSYSTEM_IDS2	0x0002	/* Daqboard/2000 - 2 Dacs */
+#define DAQBOARD2000_SUBSYSTEM_IDS4	0x0004	/* Daqboard/2000 - 4 Dacs */
 
 /* Initialization bits for the Serial EEPROM Control Register */
 #define DAQBOARD2000_SECRProgPinHi      0x8001767e
@@ -128,8 +128,8 @@ Configuration options: not applicable, u
 #define DAQBOARD2000_EEPROM_PRESENT     0x10000000
 
 /* CPLD status bits */
-#define DAQBOARD2000_CPLD_INIT 		0x0002
-#define DAQBOARD2000_CPLD_DONE 		0x0004
+#define DAQBOARD2000_CPLD_INIT		0x0002
+#define DAQBOARD2000_CPLD_DONE		0x0004
 
 static const struct comedi_lrange range_daqboard2000_ai = {
 	13, {
@@ -274,19 +274,16 @@ struct daqboard2000_private {
 	enum {
 		card_daqboard_2000
 	} card;
-	void __iomem *daq;
 	void __iomem *plx;
 	unsigned int ao_readback[2];
 };
 
 static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry)
 {
-	struct daqboard2000_private *devpriv = dev->private;
-
 	/* udelay(4); */
-	writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO);
+	writew(entry & 0x00ff, dev->mmio + acqScanListFIFO);
 	/* udelay(4); */
-	writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO);
+	writew((entry >> 8) & 0x00ff, dev->mmio + acqScanListFIFO);
 }
 
 static void setup_sampling(struct comedi_device *dev, int chan, int gain)
@@ -338,10 +335,9 @@ static int daqboard2000_ai_status(struct
 				  struct comedi_insn *insn,
 				  unsigned long context)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readw(devpriv->daq + acqControl);
+	status = readw(dev->mmio + acqControl);
 	if (status & context)
 		return 0;
 	return -EBUSY;
@@ -352,22 +348,21 @@ static int daqboard2000_ai_insn_read(str
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	int gain, chan;
 	int ret;
 	int i;
 
 	writew(DAQBOARD2000_AcqResetScanListFifo |
 	       DAQBOARD2000_AcqResetResultsFifo |
-	       DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl);
+	       DAQBOARD2000_AcqResetConfigPipe, dev->mmio + acqControl);
 
 	/*
 	 * If pacer clock is not set to some high value (> 10 us), we
 	 * risk multiple samples to be put into the result FIFO.
 	 */
 	/* 1 second, should be long enough */
-	writel(1000000, devpriv->daq + acqPacerClockDivLow);
-	writew(0, devpriv->daq + acqPacerClockDivHigh);
+	writel(1000000, dev->mmio + acqPacerClockDivLow);
+	writew(0, dev->mmio + acqPacerClockDivHigh);
 
 	gain = CR_RANGE(insn->chanspec);
 	chan = CR_CHAN(insn->chanspec);
@@ -379,15 +374,14 @@ static int daqboard2000_ai_insn_read(str
 	for (i = 0; i < insn->n; i++) {
 		setup_sampling(dev, chan, gain);
 		/* Enable reading from the scanlist FIFO */
-		writew(DAQBOARD2000_SeqStartScanList,
-		       devpriv->daq + acqControl);
+		writew(DAQBOARD2000_SeqStartScanList, dev->mmio + acqControl);
 
 		ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status,
 				     DAQBOARD2000_AcqConfigPipeFull);
 		if (ret)
 			return ret;
 
-		writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl);
+		writew(DAQBOARD2000_AdcPacerEnable, dev->mmio + acqControl);
 
 		ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status,
 				     DAQBOARD2000_AcqLogicScanning);
@@ -399,9 +393,9 @@ static int daqboard2000_ai_insn_read(str
 		if (ret)
 			return ret;
 
-		data[i] = readw(devpriv->daq + acqResultsFIFO);
-		writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl);
-		writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl);
+		data[i] = readw(dev->mmio + acqResultsFIFO);
+		writew(DAQBOARD2000_AdcPacerDisable, dev->mmio + acqControl);
+		writew(DAQBOARD2000_SeqStopScanList, dev->mmio + acqControl);
 	}
 
 	return i;
@@ -427,11 +421,10 @@ static int daqboard2000_ao_eoc(struct co
 			       struct comedi_insn *insn,
 			       unsigned long context)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int status;
 
-	status = readw(devpriv->daq + dacControl);
+	status = readw(dev->mmio + dacControl);
 	if ((status & ((chan + 1) * 0x0010)) == 0)
 		return 0;
 	return -EBUSY;
@@ -453,11 +446,10 @@ static int daqboard2000_ao_insn_write(st
 		 * OK, since it works OK without enabling the DAC's,
 		 * let's keep it as simple as possible...
 		 */
-		writew((chan + 2) * 0x0010 | 0x0001,
-		       devpriv->daq + dacControl);
+		writew((chan + 2) * 0x0010 | 0x0001, dev->mmio + dacControl);
 		udelay(1000);
 #endif
-		writew(data[i], devpriv->daq + dacSetting(chan));
+		writew(data[i], dev->mmio + dacSetting(chan));
 
 		ret = comedi_timeout(dev, s, insn, daqboard2000_ao_eoc, 0);
 		if (ret)
@@ -469,8 +461,7 @@ static int daqboard2000_ao_insn_write(st
 		 * Since we never enabled the DAC's, we don't need
 		 * to disable it...
 		 */
-		writew((chan + 2) * 0x0010 | 0x0000,
-		       devpriv->daq + dacControl);
+		writew((chan + 2) * 0x0010 | 0x0000, dev->mmio + dacControl);
 		udelay(1000);
 #endif
 	}
@@ -512,14 +503,13 @@ static void daqboard2000_pulseProgPin(st
 
 static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	int result = 0;
 	int i;
 	int cpld;
 
 	/* timeout after 50 tries -> 5ms */
 	for (i = 0; i < 50; i++) {
-		cpld = readw(devpriv->daq + 0x1000);
+		cpld = readw(dev->mmio + 0x1000);
 		if ((cpld & mask) == mask) {
 			result = 1;
 			break;
@@ -532,12 +522,11 @@ static int daqboard2000_pollCPLD(struct
 
 static int daqboard2000_writeCPLD(struct comedi_device *dev, int data)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	int result = 0;
 
 	udelay(10);
-	writew(data, devpriv->daq + 0x1000);
-	if ((readw(devpriv->daq + 0x1000) & DAQBOARD2000_CPLD_INIT) ==
+	writew(data, dev->mmio + 0x1000);
+	if ((readw(dev->mmio + 0x1000) & DAQBOARD2000_CPLD_INIT) ==
 	    DAQBOARD2000_CPLD_INIT) {
 		result = 1;
 	}
@@ -593,23 +582,21 @@ static void daqboard2000_adcStopDmaTrans
 
 static void daqboard2000_adcDisarm(struct comedi_device *dev)
 {
-	struct daqboard2000_private *devpriv = dev->private;
-
 	/* Disable hardware triggers */
 	udelay(2);
 	writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable,
-	       devpriv->daq + trigControl);
+	       dev->mmio + trigControl);
 	udelay(2);
 	writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable,
-	       devpriv->daq + trigControl);
+	       dev->mmio + trigControl);
 
 	/* Stop the scan list FIFO from loading the configuration pipe */
 	udelay(2);
-	writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl);
+	writew(DAQBOARD2000_SeqStopScanList, dev->mmio + acqControl);
 
 	/* Stop the pacer clock */
 	udelay(2);
-	writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl);
+	writew(DAQBOARD2000_AdcPacerDisable, dev->mmio + acqControl);
 
 	/* Stop the input dma (abort channel 1) */
 	daqboard2000_adcStopDmaTransfer(dev);
@@ -617,23 +604,22 @@ static void daqboard2000_adcDisarm(struc
 
 static void daqboard2000_activateReferenceDacs(struct comedi_device *dev)
 {
-	struct daqboard2000_private *devpriv = dev->private;
 	unsigned int val;
 	int timeout;
 
 	/*  Set the + reference dac value in the FPGA */
-	writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs);
+	writew(0x80 | DAQBOARD2000_PosRefDacSelect, dev->mmio + refDacs);
 	for (timeout = 0; timeout < 20; timeout++) {
-		val = readw(devpriv->daq + dacControl);
+		val = readw(dev->mmio + dacControl);
 		if ((val & DAQBOARD2000_RefBusy) == 0)
 			break;
 		udelay(2);
 	}
 
 	/*  Set the - reference dac value in the FPGA */
-	writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs);
+	writew(0x80 | DAQBOARD2000_NegRefDacSelect, dev->mmio + refDacs);
 	for (timeout = 0; timeout < 20; timeout++) {
-		val = readw(devpriv->daq + dacControl);
+		val = readw(dev->mmio + dacControl);
 		if ((val & DAQBOARD2000_RefBusy) == 0)
 			break;
 		udelay(2);
@@ -673,9 +659,8 @@ static int daqboard2000_8255_cb(int dir,
 	if (dir) {
 		writew(data, mmio_base + port * 2);
 		return 0;
-	} else {
-		return readw(mmio_base + port * 2);
 	}
+	return readw(mmio_base + port * 2);
 }
 
 static const void *daqboard2000_find_boardinfo(struct comedi_device *dev,
@@ -719,8 +704,8 @@ static int daqboard2000_auto_attach(stru
 		return result;
 
 	devpriv->plx = pci_ioremap_bar(pcidev, 0);
-	devpriv->daq = pci_ioremap_bar(pcidev, 2);
-	if (!devpriv->plx || !devpriv->daq)
+	dev->mmio = pci_ioremap_bar(pcidev, 2);
+	if (!devpriv->plx || !dev->mmio)
 		return -ENOMEM;
 
 	result = comedi_alloc_subdevices(dev, 3);
@@ -759,7 +744,7 @@ static int daqboard2000_auto_attach(stru
 
 	s = &dev->subdevices[2];
 	result = subdev_8255_init(dev, s, daqboard2000_8255_cb,
-			(unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit));
+			(unsigned long)(dev->mmio + dioP2ExpansionIO8Bit));
 	if (result)
 		return result;
 
@@ -773,8 +758,8 @@ static void daqboard2000_detach(struct c
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (devpriv) {
-		if (devpriv->daq)
-			iounmap(devpriv->daq);
+		if (dev->mmio)
+			iounmap(dev->mmio);
 		if (devpriv->plx)
 			iounmap(devpriv->plx);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das08.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das08.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das08.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das08.c	2014-09-28 17:29:07.000000000 -0400
@@ -273,7 +273,7 @@ static int das08_ai_rinsn(struct comedi_
 			else
 				data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8);
 		} else {
-			comedi_error(dev, "bug! unknown ai encoding");
+			dev_err(dev->class_dev, "bug! unknown ai encoding\n");
 			return -1;
 		}
 	}
@@ -452,7 +452,6 @@ static int das08_counter_config(struct c
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 2;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das08_pci.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das08_pci.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das08_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das08_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,8 +38,6 @@
 
 #include "das08.h"
 
-#define PCI_DEVICE_ID_PCIDAS08		0x0029
-
 static const struct das08_board_struct das08_pci_boards[] = {
 	{
 		.name		= "pci-das08",
@@ -90,7 +88,7 @@ static int das08_pci_probe(struct pci_de
 }
 
 static const struct pci_device_id das08_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0029) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, das08_pci_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das16.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das16.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das16.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das16.c	2014-09-28 17:29:07.000000000 -0400
@@ -506,18 +506,18 @@ static void das16_ai_disable(struct come
 static int disable_dma_on_even(struct comedi_device *dev)
 {
 	struct das16_private_struct *devpriv = dev->private;
-	int residue;
-	int i;
 	static const int disable_limit = 100;
 	static const int enable_timeout = 100;
+	int residue;
+	int new_residue;
+	int i;
+	int j;
 
 	disable_dma(devpriv->dma_chan);
 	residue = get_dma_residue(devpriv->dma_chan);
 	for (i = 0; i < disable_limit && (residue % 2); ++i) {
-		int j;
 		enable_dma(devpriv->dma_chan);
 		for (j = 0; j < enable_timeout; ++j) {
-			int new_residue;
 			udelay(2);
 			new_residue = get_dma_residue(devpriv->dma_chan);
 			if (new_residue != residue)
@@ -729,14 +729,14 @@ static int das16_cmd_test(struct comedi_
 }
 
 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
-				    int rounding_flags)
+				    unsigned int flags)
 {
 	struct das16_private_struct *devpriv = dev->private;
 	unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
 
 	i8253_cascade_ns_to_timer(devpriv->clockbase,
 				  &devpriv->divisor1, &devpriv->divisor2,
-				  &ns, rounding_flags);
+				  &ns, flags);
 
 	i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
 	i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
@@ -782,9 +782,7 @@ static int das16_cmd_exec(struct comedi_
 	}
 
 	/* set counter mode and counts */
-	cmd->convert_arg =
-	    das16_set_pacer(dev, cmd->convert_arg,
-			    cmd->flags & TRIG_ROUND_MASK);
+	cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
 
 	/* enable counters */
 	byte = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das16m1.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das16m1.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das16m1.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das16m1.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,6 @@ irq can be omitted, although the cmd int
 #include "8253.h"
 #include "comedi_fc.h"
 
-#define DAS16M1_SIZE 16
 #define DAS16M1_SIZE2 8
 
 #define FIFO_SIZE 1024		/*  1024 sample fifo */
@@ -126,7 +125,7 @@ static const struct comedi_lrange range_
 
 struct das16m1_private_struct {
 	unsigned int control_state;
-	volatile unsigned int adc_count;	/*  number of samples completed */
+	unsigned int adc_count;	/*  number of samples completed */
 	/* initial value in lower half of hardware conversion counter,
 	 * needed to keep track of whether new count has been loaded into
 	 * counter yet (loaded by first sample conversion) */
@@ -460,7 +459,7 @@ static void das16m1_handler(struct comed
 	 * overrun interrupts, but we might as well try */
 	if (status & OVRUN) {
 		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
-		comedi_error(dev, "fifo overflow");
+		dev_err(dev->class_dev, "fifo overflow\n");
 	}
 
 	cfc_handle_events(dev, s);
@@ -477,7 +476,7 @@ static int das16m1_poll(struct comedi_de
 	das16m1_handler(dev, status);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	return s->async->buf_write_count - s->async->buf_read_count;
+	return comedi_buf_n_bytes_ready(s);
 }
 
 static irqreturn_t das16m1_interrupt(int irq, void *d)
@@ -486,7 +485,7 @@ static irqreturn_t das16m1_interrupt(int
 	struct comedi_device *dev = d;
 
 	if (!dev->attached) {
-		comedi_error(dev, "premature interrupt");
+		dev_err(dev->class_dev, "premature interrupt\n");
 		return IRQ_HANDLED;
 	}
 	/*  prevent race with comedi_poll() */
@@ -495,7 +494,7 @@ static irqreturn_t das16m1_interrupt(int
 	status = inb(dev->iobase + DAS16M1_CS);
 
 	if ((status & (IRQDATA | OVRUN)) == 0) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		spin_unlock(&dev->spinlock);
 		return IRQ_NONE;
 	}
@@ -549,7 +548,7 @@ static int das16m1_attach(struct comedi_
 	if (!devpriv)
 		return -ENOMEM;
 
-	ret = comedi_request_region(dev, it->options[0], DAS16M1_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 	/* Request an additional region for the 8255 */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das1800.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das1800.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das1800.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das1800.c	2014-09-28 17:29:07.000000000 -0400
@@ -421,7 +421,7 @@ static const struct das1800_board das180
 };
 
 struct das1800_private {
-	volatile unsigned int count;	/* number of data points left to be taken */
+	unsigned int count;	/* number of data points left to be taken */
 	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
 	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
 	int irq_dma_bits;	/* bits for control register b */
@@ -430,7 +430,7 @@ struct das1800_private {
 	int dma_bits;
 	unsigned int dma0;	/* dma channels used */
 	unsigned int dma1;
-	volatile unsigned int dma_current;	/* dma channel currently in use */
+	unsigned int dma_current;	/* dma channel currently in use */
 	uint16_t *ai_buf0;	/* pointers to dma buffers */
 	uint16_t *ai_buf1;
 	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
@@ -492,7 +492,6 @@ static void das1800_handle_fifo_half_ful
 				  numPoints * sizeof(devpriv->ai_buf0[0]));
 	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->count -= numPoints;
-	return;
 }
 
 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
@@ -517,8 +516,6 @@ static void das1800_handle_fifo_not_empt
 		if (cmd->stop_src == TRIG_COUNT)
 			devpriv->count--;
 	}
-
-	return;
 }
 
 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
@@ -549,8 +546,6 @@ static void das1800_flush_dma_channel(st
 	cfc_write_array_to_buffer(s, buffer, num_bytes);
 	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->count -= num_samples;
-
-	return;
 }
 
 /* flushes remaining data from board when external trigger has stopped acquisition
@@ -583,8 +578,6 @@ static void das1800_flush_dma(struct com
 
 	/*  get any remaining samples in fifo */
 	das1800_handle_fifo_not_empty(dev, s);
-
-	return;
 }
 
 static void das1800_handle_dma(struct comedi_device *dev,
@@ -619,8 +612,6 @@ static void das1800_handle_dma(struct co
 			}
 		}
 	}
-
-	return;
 }
 
 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -663,7 +654,7 @@ static void das1800_ai_handler(struct co
 	if (status & OVF) {
 		/*  clear OVF interrupt bit */
 		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
-		comedi_error(dev, "DAS1800 FIFO overflow");
+		dev_err(dev->class_dev, "FIFO overflow\n");
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
 		return;
@@ -696,7 +687,7 @@ static int das1800_ai_poll(struct comedi
 	das1800_ai_handler(dev);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	return s->async->buf_write_count - s->async->buf_read_count;
+	return comedi_buf_n_bytes_ready(s);
 }
 
 static irqreturn_t das1800_interrupt(int irq, void *d)
@@ -705,7 +696,7 @@ static irqreturn_t das1800_interrupt(int
 	unsigned int status;
 
 	if (!dev->attached) {
-		comedi_error(dev, "premature interrupt");
+		dev_err(dev->class_dev, "premature interrupt\n");
 		return IRQ_HANDLED;
 	}
 
@@ -1060,8 +1051,6 @@ static void setup_dma(struct comedi_devi
 		enable_dma(devpriv->dma1);
 	}
 	release_dma_lock(lock_flags);
-
-	return;
 }
 
 /* programs channel/gain list into card */
@@ -1088,8 +1077,6 @@ static void program_chanlist(struct come
 	}
 	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
 	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
-
-	return;
 }
 
 /* analog input do_cmd */
@@ -1192,7 +1179,7 @@ static int das1800_ai_rinsn(struct comed
 				break;
 		}
 		if (i == timeout) {
-			comedi_error(dev, "timeout");
+			dev_err(dev->class_dev, "timeout\n");
 			n = -ETIME;
 			goto exit;
 		}
@@ -1301,7 +1288,6 @@ static int das1800_init_dma(struct comed
 			dev_err(dev->class_dev,
 				"dma 5,6 / 6,7 / or 7,5\n");
 			return -EINVAL;
-			break;
 		}
 		if (request_dma(dma0, dev->driver->driver_name)) {
 			dev_err(dev->class_dev,
@@ -1343,84 +1329,60 @@ static int das1800_init_dma(struct comed
 
 static int das1800_probe(struct comedi_device *dev)
 {
+	const struct das1800_board *board = comedi_board(dev);
+	int index;
 	int id;
-	int board;
 
-	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
-	board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
+	/* calc the offset to the boardinfo that was found by the core */
+	index = board - das1800_boards;
 
+	/* verify that the board id matches the boardinfo */
+	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
 	switch (id) {
 	case 0x3:
-		if (board == das1801st_da || board == das1802st_da ||
-		    board == das1701st_da || board == das1702st_da) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1800st-da series\n");
-		return das1801st;
+		if (index == das1801st_da || index == das1802st_da ||
+		    index == das1701st_da || index == das1702st_da)
+			return index;
+		index = das1801st;
 		break;
 	case 0x4:
-		if (board == das1802hr_da || board == das1702hr_da) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1802hr-da\n");
-		return das1802hr;
+		if (index == das1802hr_da || index == das1702hr_da)
+			return index;
+		index = das1802hr;
 		break;
 	case 0x5:
-		if (board == das1801ao || board == das1802ao ||
-		    board == das1701ao || board == das1702ao) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1800ao series\n");
-		return das1801ao;
+		if (index == das1801ao || index == das1802ao ||
+		    index == das1701ao || index == das1702ao)
+			return index;
+		index = das1801ao;
 		break;
 	case 0x6:
-		if (board == das1802hr || board == das1702hr) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1802hr\n");
-		return das1802hr;
+		if (index == das1802hr || index == das1702hr)
+			return index;
+		index = das1802hr;
 		break;
 	case 0x7:
-		if (board == das1801st || board == das1802st ||
-		    board == das1701st || board == das1702st) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1800st series\n");
-		return das1801st;
+		if (index == das1801st || index == das1802st ||
+		    index == das1701st || index == das1702st)
+			return index;
+		index = das1801st;
 		break;
 	case 0x8:
-		if (board == das1801hc || board == das1802hc) {
-			dev_dbg(dev->class_dev, "Board model: %s\n",
-				das1800_boards[board].name);
-			return board;
-		}
-		printk
-		    (" Board model (probed, not recommended): das-1800hc series\n");
-		return das1801hc;
+		if (index == das1801hc || index == das1802hc)
+			return index;
+		index = das1801hc;
 		break;
 	default:
-		printk
-		    (" Board model: probe returned 0x%x (unknown, please report)\n",
-		     id);
-		return board;
+		dev_err(dev->class_dev,
+			"Board model: probe returned 0x%x (unknown, please report)\n",
+			id);
 		break;
 	}
-	return -1;
+	dev_err(dev->class_dev,
+		"Board model (probed, not recommended): %s series\n",
+		das1800_boards[index].name);
+
+	return index;
 }
 
 static int das1800_attach(struct comedi_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das800.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das800.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/das800.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/das800.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,7 +65,6 @@ cmd triggers supported:
 #include "8253.h"
 #include "comedi_fc.h"
 
-#define DAS800_SIZE           8
 #define N_CHAN_AI             8	/*  number of analog input channels */
 
 /* Registers for the das800 */
@@ -686,7 +685,7 @@ static int das800_attach(struct comedi_d
 	if (!devpriv)
 		return -ENOMEM;
 
-	ret = comedi_request_region(dev, it->options[0], DAS800_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x8);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dmm32at.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dmm32at.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dmm32at.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dmm32at.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,6 @@ Configuration Options:
 #include "comedi_fc.h"
 
 /* Board register addresses */
-
-#define DMM32AT_MEMSIZE 0x10
-
 #define DMM32AT_CONV 0x00
 #define DMM32AT_AILSB 0x00
 #define DMM32AT_AUXDOUT 0x01
@@ -237,7 +234,7 @@ static int dmm32at_ai_rinsn(struct comed
 	return n;
 }
 
-static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+static int dmm32at_ns_to_timer(unsigned int *ns, unsigned int flags)
 {
 	/* trivial timer */
 	return *ns;
@@ -352,12 +349,12 @@ static int dmm32at_ai_cmdtest(struct com
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		dmm32at_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		dmm32at_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -491,7 +488,7 @@ static irqreturn_t dmm32at_isr(int irq,
 	int i;
 
 	if (!dev->attached) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		return IRQ_HANDLED;
 	}
 
@@ -684,7 +681,7 @@ static int dmm32at_attach(struct comedi_
 	struct comedi_subdevice *s;
 	unsigned char aihi, ailo, fifostat, aistat, intstat, airback;
 
-	ret = comedi_request_region(dev, it->options[0], DMM32AT_MEMSIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2801.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2801.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2801.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2801.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,6 @@ Configuration options:
 
 #define DT2801_MAX_DMA_SIZE (64 * 1024)
 
-/* Ports */
-#define DT2801_IOSIZE 2
-
 /* define's */
 /* ====================== */
 
@@ -552,7 +549,7 @@ static int dt2801_attach(struct comedi_d
 	int ret = 0;
 	int n_ai_chans;
 
-	ret = comedi_request_region(dev, it->options[0], DT2801_IOSIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x2);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2811.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2811.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2811.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2811.c	2014-09-28 17:29:07.000000000 -0400
@@ -169,8 +169,6 @@ static const struct comedi_lrange range_
 
 #define TIMEOUT 10000
 
-#define DT2811_SIZE 8
-
 #define DT2811_ADCSR 0
 #define DT2811_ADGCR 1
 #define DT2811_ADDATLO 2
@@ -344,7 +342,7 @@ static int dt2811_attach(struct comedi_d
 	int ret;
 	struct comedi_subdevice *s;
 
-	ret = comedi_request_region(dev, it->options[0], DT2811_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x8);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2814.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2814.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2814.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2814.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,6 @@ addition, the clock does not seem to be
 
 #include "comedi_fc.h"
 
-#define DT2814_SIZE 2
-
 #define DT2814_CSR 0
 #define DT2814_DATA 1
 
@@ -171,7 +169,7 @@ static int dt2814_ai_cmdtest(struct come
 	/* step 4: fix up any arguments */
 
 	arg = cmd->scan_begin_arg;
-	dt2814_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+	dt2814_ns_to_timer(&arg, cmd->flags);
 	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 
 	if (err)
@@ -187,9 +185,7 @@ static int dt2814_ai_cmd(struct comedi_d
 	int chan;
 	int trigvar;
 
-	trigvar =
-	    dt2814_ns_to_timer(&cmd->scan_begin_arg,
-			       cmd->flags & TRIG_ROUND_MASK);
+	trigvar = dt2814_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
 
 	chan = CR_CHAN(cmd->chanlist[0]);
 
@@ -209,7 +205,7 @@ static irqreturn_t dt2814_interrupt(int
 	int data;
 
 	if (!dev->attached) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		return IRQ_HANDLED;
 	}
 
@@ -245,7 +241,7 @@ static int dt2814_attach(struct comedi_d
 	int ret;
 	int i;
 
-	ret = comedi_request_region(dev, it->options[0], DT2814_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x2);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2815.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2815.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2815.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2815.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,8 +56,6 @@ Configuration options:
 
 #include <linux/delay.h>
 
-#define DT2815_SIZE 2
-
 #define DT2815_DATA 0
 #define DT2815_STATUS 1
 
@@ -154,7 +152,7 @@ static int dt2815_attach(struct comedi_d
 	const struct comedi_lrange *current_range_type, *voltage_range_type;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], DT2815_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x2);
 	if (ret)
 		return ret;
 
@@ -195,6 +193,7 @@ static int dt2815_attach(struct comedi_d
 		status = inb(dev->iobase + DT2815_STATUS);
 		if (status == 4) {
 			unsigned int program;
+
 			program = (it->options[4] & 0x3) << 3 | 0x7;
 			outb(program, dev->iobase + DT2815_DATA);
 			dev_dbg(dev->class_dev, "program: 0x%x (@t=%d)\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2817.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2817.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt2817.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt2817.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,6 @@ Configuration options:
 #include <linux/module.h>
 #include "../comedidev.h"
 
-#define DT2817_SIZE 5
-
 #define DT2817_CR 0
 #define DT2817_DATA 1
 
@@ -114,7 +112,7 @@ static int dt2817_attach(struct comedi_d
 	int ret;
 	struct comedi_subdevice *s;
 
-	ret = comedi_request_region(dev, it->options[0], DT2817_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x5);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt282x.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt282x.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt282x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt282x.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,55 +1,69 @@
 /*
-   comedi/drivers/dt282x.c
-   Hardware driver for Data Translation DT2821 series
-
-   COMEDI - Linux Control and Measurement Device Interface
-   Copyright (C) 1997-8 David A. Schleef <ds@schleef.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.
+ * dt282x.c
+ * Comedi driver for Data Translation DT2821 series
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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.
  */
-/*
-Driver: dt282x
-Description: Data Translation DT2821 series (including DT-EZ)
-Author: ds
-Devices: [Data Translation] DT2821 (dt2821),
-  DT2821-F-16SE (dt2821-f), DT2821-F-8DI (dt2821-f),
-  DT2821-G-16SE (dt2821-f), DT2821-G-8DI (dt2821-g),
-  DT2823 (dt2823),
-  DT2824-PGH (dt2824-pgh), DT2824-PGL (dt2824-pgl), DT2825 (dt2825),
-  DT2827 (dt2827), DT2828 (dt2828), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez),
-  DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl)
-Status: complete
-Updated: Wed, 22 Aug 2001 17:11:34 -0700
 
-Configuration options:
-  [0] - I/O port base address
-  [1] - IRQ
-  [2] - DMA 1
-  [3] - DMA 2
-  [4] - AI jumpered for 0=single ended, 1=differential
-  [5] - AI jumpered for 0=straight binary, 1=2's complement
-  [6] - AO 0 jumpered for 0=straight binary, 1=2's complement
-  [7] - AO 1 jumpered for 0=straight binary, 1=2's complement
-  [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5]
-  [9] - AO 0 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5],
-	4=[-2.5,2.5]
-  [10]- A0 1 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5],
-	4=[-2.5,2.5]
-
-Notes:
-  - AO commands might be broken.
-  - If you try to run a command on both the AI and AO subdevices
-    simultaneously, bad things will happen.  The driver needs to
-    be fixed to check for this situation and return an error.
-*/
+/*
+ * Driver: dt282x
+ * Description: Data Translation DT2821 series (including DT-EZ)
+ * Author: ds
+ * Devices: (Data Translation) DT2821 [dt2821]
+ *	    (Data Translation) DT2821-F-16SE [dt2821-f]
+ *	    (Data Translation) DT2821-F-8DI [dt2821-f]
+ *	    (Data Translation) DT2821-G-16SE [dt2821-g]
+ *	    (Data Translation) DT2821-G-8DI [dt2821-g]
+ *	    (Data Translation) DT2823 [dt2823]
+ *	    (Data Translation) DT2824-PGH [dt2824-pgh]
+ *	    (Data Translation) DT2824-PGL [dt2824-pgl]
+ *	    (Data Translation) DT2825 [dt2825]
+ *	    (Data Translation) DT2827 [dt2827]
+ *	    (Data Translation) DT2828 [dt2828]
+ *	    (Data Translation) DT2928 [dt2829]
+ *	    (Data Translation) DT21-EZ [dt21-ez]
+ *	    (Data Translation) DT23-EZ [dt23-ez]
+ *	    (Data Translation) DT24-EZ [dt24-ez]
+ *	    (Data Translation) DT24-EZ-PGL [dt24-ez-pgl]
+ * Status: complete
+ * Updated: Wed, 22 Aug 2001 17:11:34 -0700
+ *
+ * Configuration options:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (optional, required for async command support)
+ *   [2] - DMA 1 (optional, required for async command support)
+ *   [3] - DMA 2 (optional, required for async command support)
+ *   [4] - AI jumpered for 0=single ended, 1=differential
+ *   [5] - AI jumpered for 0=straight binary, 1=2's complement
+ *   [6] - AO 0 data format (deprecated, see below)
+ *   [7] - AO 1 data format (deprecated, see below)
+ *   [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5]
+ *   [9] - AO channel 0 range (deprecated, see below)
+ *   [10]- AO channel 1 range (deprecated, see below)
+ *
+ * Notes:
+ *   - AO commands might be broken.
+ *   - If you try to run a command on both the AI and AO subdevices
+ *     simultaneously, bad things will happen.  The driver needs to
+ *     be fixed to check for this situation and return an error.
+ *   - AO range is not programmable. The AO subdevice has a range_table
+ *     containing all the possible analog output ranges. Use the range
+ *     that matches your board configuration to convert between data
+ *     values and physical units. The format of the data written to the
+ *     board is handled automatically based on the unipolar/bipolar
+ *     range that is selected.
+ */
 
 #include <linux/module.h>
 #include "../comedidev.h"
@@ -63,93 +77,53 @@ Notes:
 
 #include "comedi_fc.h"
 
-#define DT2821_SIZE 0x10
-
-/*
- *    Registers in the DT282x
- */
-
-#define DT2821_ADCSR	0x00	/* A/D Control/Status             */
-#define DT2821_CHANCSR	0x02	/* Channel Control/Status */
-#define DT2821_ADDAT	0x04	/* A/D data                       */
-#define DT2821_DACSR	0x06	/* D/A Control/Status             */
-#define DT2821_DADAT	0x08	/* D/A data                       */
-#define DT2821_DIODAT	0x0a	/* digital data                   */
-#define DT2821_SUPCSR	0x0c	/* Supervisor Control/Status      */
-#define DT2821_TMRCTR	0x0e	/* Timer/Counter          */
-
 /*
- *  At power up, some registers are in a well-known state.  The
- *  masks and values are as follows:
- */
-
-#define DT2821_ADCSR_MASK 0xfff0
-#define DT2821_ADCSR_VAL 0x7c00
-
-#define DT2821_CHANCSR_MASK 0xf0f0
-#define DT2821_CHANCSR_VAL 0x70f0
-
-#define DT2821_DACSR_MASK 0x7c93
-#define DT2821_DACSR_VAL 0x7c90
-
-#define DT2821_SUPCSR_MASK 0xf8ff
-#define DT2821_SUPCSR_VAL 0x0000
-
-#define DT2821_TMRCTR_MASK 0xff00
-#define DT2821_TMRCTR_VAL 0xf000
-
-/*
- *    Bit fields of each register
+ * Register map
  */
-
-/* ADCSR */
-
-#define DT2821_ADERR	0x8000	/* (R)   1 for A/D error  */
-#define DT2821_ADCLK	0x0200	/* (R/W) A/D clock enable */
-		/*      0x7c00           read as 1's            */
-#define DT2821_MUXBUSY	0x0100	/* (R)   multiplexer busy */
-#define DT2821_ADDONE	0x0080	/* (R)   A/D done         */
-#define DT2821_IADDONE	0x0040	/* (R/W) interrupt on A/D done    */
-		/*      0x0030           gain select            */
-		/*      0x000f           channel select         */
-
-/* CHANCSR */
-
-#define DT2821_LLE	0x8000	/* (R/W) Load List Enable */
-		/*      0x7000           read as 1's            */
-		/*      0x0f00     (R)   present address        */
-		/*      0x00f0           read as 1's            */
-		/*      0x000f     (R)   number of entries - 1  */
-
-/* DACSR */
-
-#define DT2821_DAERR	0x8000	/* (R)   D/A error                */
-#define DT2821_YSEL	0x0200	/* (R/W) DAC 1 select             */
-#define DT2821_SSEL	0x0100	/* (R/W) single channel select    */
-#define DT2821_DACRDY	0x0080	/* (R)   DAC ready                */
-#define DT2821_IDARDY	0x0040	/* (R/W) interrupt on DAC ready   */
-#define DT2821_DACLK	0x0020	/* (R/W) D/A clock enable */
-#define DT2821_HBOE	0x0002	/* (R/W) DIO high byte output enable      */
-#define DT2821_LBOE	0x0001	/* (R/W) DIO low byte output enable       */
-
-/* SUPCSR */
-
-#define DT2821_DMAD	0x8000	/* (R)   DMA done                 */
-#define DT2821_ERRINTEN	0x4000	/* (R/W) interrupt on error               */
-#define DT2821_CLRDMADNE 0x2000	/* (W)   clear DMA done                   */
-#define DT2821_DDMA	0x1000	/* (R/W) dual DMA                 */
-#define DT2821_DS1	0x0800	/* (R/W) DMA select 1                     */
-#define DT2821_DS0	0x0400	/* (R/W) DMA select 0                     */
-#define DT2821_BUFFB	0x0200	/* (R/W) buffer B selected                */
-#define DT2821_SCDN	0x0100	/* (R)   scan done                        */
-#define DT2821_DACON	0x0080	/* (W)   DAC single conversion            */
-#define DT2821_ADCINIT	0x0040	/* (W)   A/D initialize                   */
-#define DT2821_DACINIT	0x0020	/* (W)   D/A initialize                   */
-#define DT2821_PRLD	0x0010	/* (W)   preload multiplexer              */
-#define DT2821_STRIG	0x0008	/* (W)   software trigger         */
-#define DT2821_XTRIG	0x0004	/* (R/W) external trigger enable  */
-#define DT2821_XCLK	0x0002	/* (R/W) external clock enable            */
-#define DT2821_BDINIT	0x0001	/* (W)   initialize board         */
+#define DT2821_ADCSR_REG		0x00
+#define DT2821_ADCSR_ADERR		(1 << 15)
+#define DT2821_ADCSR_ADCLK		(1 << 9)
+#define DT2821_ADCSR_MUXBUSY		(1 << 8)
+#define DT2821_ADCSR_ADDONE		(1 << 7)
+#define DT2821_ADCSR_IADDONE		(1 << 6)
+#define DT2821_ADCSR_GS(x)		(((x) & 0x3) << 4)
+#define DT2821_ADCSR_CHAN(x)		(((x) & 0xf) << 0)
+#define DT2821_CHANCSR_REG		0x02
+#define DT2821_CHANCSR_LLE		(1 << 15)
+#define DT2821_CHANCSR_PRESLA(x)	(((x) & 0xf) >> 8)
+#define DT2821_CHANCSR_NUMB(x)		((((x) - 1) & 0xf) << 0)
+#define DT2821_ADDAT_REG		0x04
+#define DT2821_DACSR_REG		0x06
+#define DT2821_DACSR_DAERR		(1 << 15)
+#define DT2821_DACSR_YSEL(x)		((x) << 9)
+#define DT2821_DACSR_SSEL		(1 << 8)
+#define DT2821_DACSR_DACRDY		(1 << 7)
+#define DT2821_DACSR_IDARDY		(1 << 6)
+#define DT2821_DACSR_DACLK		(1 << 5)
+#define DT2821_DACSR_HBOE		(1 << 1)
+#define DT2821_DACSR_LBOE		(1 << 0)
+#define DT2821_DADAT_REG		0x08
+#define DT2821_DIODAT_REG		0x0a
+#define DT2821_SUPCSR_REG		0x0c
+#define DT2821_SUPCSR_DMAD		(1 << 15)
+#define DT2821_SUPCSR_ERRINTEN		(1 << 14)
+#define DT2821_SUPCSR_CLRDMADNE		(1 << 13)
+#define DT2821_SUPCSR_DDMA		(1 << 12)
+#define DT2821_SUPCSR_DS_PIO		(0 << 10)
+#define DT2821_SUPCSR_DS_AD_CLK		(1 << 10)
+#define DT2821_SUPCSR_DS_DA_CLK		(2 << 10)
+#define DT2821_SUPCSR_DS_AD_TRIG	(3 << 10)
+#define DT2821_SUPCSR_BUFFB		(1 << 9)
+#define DT2821_SUPCSR_SCDN		(1 << 8)
+#define DT2821_SUPCSR_DACON		(1 << 7)
+#define DT2821_SUPCSR_ADCINIT		(1 << 6)
+#define DT2821_SUPCSR_DACINIT		(1 << 5)
+#define DT2821_SUPCSR_PRLD		(1 << 4)
+#define DT2821_SUPCSR_STRIG		(1 << 3)
+#define DT2821_SUPCSR_XTRIG		(1 << 2)
+#define DT2821_SUPCSR_XCLK		(1 << 1)
+#define DT2821_SUPCSR_BDINIT		(1 << 0)
+#define DT2821_TMRCTR_REG		0x0e
 
 static const struct comedi_lrange range_dt282x_ai_lo_bipolar = {
 	4, {
@@ -205,146 +179,326 @@ static const struct comedi_lrange range_
 	}
 };
 
+/*
+ * The Analog Output range is set per-channel using jumpers on the board.
+ * All of these ranges may not be available on some DT2821 series boards.
+ * The default jumper setting has both channels set for +/-10V output.
+ */
+static const struct comedi_lrange dt282x_ao_range = {
+	5, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+	}
+};
+
 struct dt282x_board {
 	const char *name;
-	int adbits;
+	unsigned int ai_maxdata;
 	int adchan_se;
 	int adchan_di;
 	int ai_speed;
 	int ispgl;
 	int dachan;
-	int dabits;
+	unsigned int ao_maxdata;
+};
+
+static const struct dt282x_board boardtypes[] = {
+	{
+		.name		= "dt2821",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 20000,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2821-f",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 6500,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2821-g",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 4000,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2823",
+		.ai_maxdata	= 0xffff,
+		.adchan_di	= 4,
+		.ai_speed	= 10000,
+		.dachan		= 2,
+		.ao_maxdata	= 0xffff,
+	}, {
+		.name		= "dt2824-pgh",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 20000,
+	}, {
+		.name		= "dt2824-pgl",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 20000,
+		.ispgl		= 1,
+	}, {
+		.name		= "dt2825",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 20000,
+		.ispgl		= 1,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2827",
+		.ai_maxdata	= 0xffff,
+		.adchan_di	= 4,
+		.ai_speed	= 10000,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2828",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 4,
+		.ai_speed	= 10000,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt2829",
+		.ai_maxdata	= 0xffff,
+		.adchan_se	= 8,
+		.ai_speed	= 33250,
+		.dachan		= 2,
+		.ao_maxdata	= 0xffff,
+	}, {
+		.name		= "dt21-ez",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 10000,
+		.dachan		= 2,
+		.ao_maxdata	= 0x0fff,
+	}, {
+		.name		= "dt23-ez",
+		.ai_maxdata	= 0xffff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 10000,
+	}, {
+		.name		= "dt24-ez",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 10000,
+	}, {
+		.name		= "dt24-ez-pgl",
+		.ai_maxdata	= 0x0fff,
+		.adchan_se	= 16,
+		.adchan_di	= 8,
+		.ai_speed	= 10000,
+		.ispgl		= 1,
+	},
 };
 
 struct dt282x_private {
-	int ad_2scomp;		/* we have 2's comp jumper set  */
-	int da0_2scomp;		/* same, for DAC0               */
-	int da1_2scomp;		/* same, for DAC1               */
+	unsigned int ad_2scomp:1;
 
-	const struct comedi_lrange *darangelist[2];
+	unsigned int divisor;
 
-	unsigned short ao[2];
+	unsigned short ao_readback[2];
 
-	volatile int dacsr;	/* software copies of registers */
-	volatile int adcsr;
-	volatile int supcsr;
+	int dacsr;	/* software copies of registers */
+	int adcsr;
+	int supcsr;
 
-	volatile int ntrig;
-	volatile int nread;
+	int ntrig;
+	int nread;
 
 	struct {
 		int chan;
 		unsigned short *buf;	/* DMA buffer */
-		volatile int size;	/* size of current transfer */
+		int size;	/* size of current transfer */
 	} dma[2];
 	int dma_maxsize;	/* max size of DMA transfer (in bytes) */
-	int usedma;		/* driver uses DMA              */
-	volatile int current_dma_index;
+	int current_dma_index;
 	int dma_dir;
 };
 
-/*
- *    Some useless abstractions
- */
-#define chan_to_DAC(a)	((a)&1)
+static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
+{
+	struct dt282x_private *devpriv = dev->private;
+	int dma_chan;
+	unsigned long dma_ptr;
+	unsigned long flags;
 
-static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
-static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
-static int dt282x_ai_cancel(struct comedi_device *dev,
-			    struct comedi_subdevice *s);
-static int dt282x_ao_cancel(struct comedi_device *dev,
-			    struct comedi_subdevice *s);
-static int dt282x_ns_to_timer(int *nanosec, int round_mode);
-static void dt282x_disable_dma(struct comedi_device *dev);
+	if (!devpriv->ntrig)
+		return 0;
 
-static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2);
+	if (n == 0)
+		n = devpriv->dma_maxsize;
+	if (n > devpriv->ntrig * 2)
+		n = devpriv->ntrig * 2;
+	devpriv->ntrig -= n / 2;
 
-static void dt282x_munge(struct comedi_device *dev, unsigned short *buf,
-			 unsigned int nbytes)
+	devpriv->dma[dma_index].size = n;
+	dma_chan = devpriv->dma[dma_index].chan;
+	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
+
+	set_dma_mode(dma_chan, DMA_MODE_READ);
+	flags = claim_dma_lock();
+	clear_dma_ff(dma_chan);
+	set_dma_addr(dma_chan, dma_ptr);
+	set_dma_count(dma_chan, n);
+	release_dma_lock(flags);
+
+	enable_dma(dma_chan);
+
+	return n;
+}
+
+static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
 {
-	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
-	unsigned int i;
-	unsigned short mask = (1 << board->adbits) - 1;
-	unsigned short sign = 1 << (board->adbits - 1);
-	int n;
+	int dma_chan;
+	unsigned long dma_ptr;
+	unsigned long flags;
 
-	if (devpriv->ad_2scomp)
-		sign = 1 << (board->adbits - 1);
-	else
-		sign = 0;
+	devpriv->dma[dma_index].size = n;
+	dma_chan = devpriv->dma[dma_index].chan;
+	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
 
-	if (nbytes % 2)
-		comedi_error(dev, "bug! odd number of bytes from dma xfer");
-	n = nbytes / 2;
-	for (i = 0; i < n; i++)
-		buf[i] = (buf[i] & mask) ^ sign;
+	set_dma_mode(dma_chan, DMA_MODE_WRITE);
+	flags = claim_dma_lock();
+	clear_dma_ff(dma_chan);
+	set_dma_addr(dma_chan, dma_ptr);
+	set_dma_count(dma_chan, n);
+	release_dma_lock(flags);
+
+	enable_dma(dma_chan);
+
+	return n;
 }
 
-static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
+static void dt282x_disable_dma(struct comedi_device *dev)
 {
 	struct dt282x_private *devpriv = dev->private;
-	struct comedi_subdevice *s = dev->write_subdev;
-	void *ptr;
-	int size;
+
+	disable_dma(devpriv->dma[0].chan);
+	disable_dma(devpriv->dma[1].chan);
+}
+
+static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
+{
+	unsigned int prescale, base, divider;
+
+	for (prescale = 0; prescale < 16; prescale++) {
+		if (prescale == 1)
+			continue;
+		base = 250 * (1 << prescale);
+		switch (flags & TRIG_ROUND_MASK) {
+		case TRIG_ROUND_NEAREST:
+		default:
+			divider = (*ns + base / 2) / base;
+			break;
+		case TRIG_ROUND_DOWN:
+			divider = (*ns) / base;
+			break;
+		case TRIG_ROUND_UP:
+			divider = (*ns + base - 1) / base;
+			break;
+		}
+		if (divider < 256) {
+			*ns = divider * base;
+			return (prescale << 8) | (255 - divider);
+		}
+	}
+	base = 250 * (1 << 15);
+	divider = 255;
+	*ns = divider * base;
+	return (15 << 8) | (255 - divider);
+}
+
+static void dt282x_munge(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 unsigned short *buf,
+			 unsigned int nbytes)
+{
+	struct dt282x_private *devpriv = dev->private;
+	unsigned int val;
 	int i;
 
-	outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR);
+	if (nbytes % 2)
+		dev_err(dev->class_dev,
+			"bug! odd number of bytes from dma xfer\n");
 
-	if (!s->async->prealloc_buf) {
-		dev_err(dev->class_dev, "no buffer in %s\n", __func__);
-		return;
+	for (i = 0; i < nbytes / 2; i++) {
+		val = buf[i];
+		val &= s->maxdata;
+		if (devpriv->ad_2scomp)
+			val = comedi_offset_munge(s, val);
+
+		buf[i] = val;
 	}
+}
 
-	i = devpriv->current_dma_index;
-	ptr = devpriv->dma[i].buf;
+static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
+				    struct comedi_subdevice *s)
+{
+	struct dt282x_private *devpriv = dev->private;
+	int cur_dma = devpriv->current_dma_index;
+	void *ptr = devpriv->dma[cur_dma].buf;
+	int size;
 
-	disable_dma(devpriv->dma[i].chan);
+	outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
-	devpriv->current_dma_index = 1 - i;
+	disable_dma(devpriv->dma[cur_dma].chan);
+
+	devpriv->current_dma_index = 1 - cur_dma;
 
 	size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize);
 	if (size == 0) {
 		dev_err(dev->class_dev, "AO underrun\n");
 		s->async->events |= COMEDI_CB_OVERFLOW;
-		return;
+	} else {
+		dt282x_prep_ao_dma(dev, cur_dma, size);
 	}
-	prep_ao_dma(dev, i, size);
-	return;
 }
 
-static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
+static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
+				    struct comedi_subdevice *s)
 {
 	struct dt282x_private *devpriv = dev->private;
-	struct comedi_subdevice *s = dev->read_subdev;
-	void *ptr;
-	int size;
-	int i;
+	int cur_dma = devpriv->current_dma_index;
+	void *ptr = devpriv->dma[cur_dma].buf;
+	int size = devpriv->dma[cur_dma].size;
 	int ret;
 
-	outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR);
-
-	if (!s->async->prealloc_buf) {
-		dev_err(dev->class_dev, "no buffer in %s\n", __func__);
-		return;
-	}
-
-	i = devpriv->current_dma_index;
-	ptr = devpriv->dma[i].buf;
-	size = devpriv->dma[i].size;
+	outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
-	disable_dma(devpriv->dma[i].chan);
+	disable_dma(devpriv->dma[cur_dma].chan);
 
-	devpriv->current_dma_index = 1 - i;
+	devpriv->current_dma_index = 1 - cur_dma;
 
-	dt282x_munge(dev, ptr, size);
+	dt282x_munge(dev, s, ptr, size);
 	ret = cfc_write_array_to_buffer(s, ptr, size);
 	if (ret != size) {
 		s->async->events |= COMEDI_CB_OVERFLOW;
 		return;
 	}
-	devpriv->nread -= size / 2;
 
+	devpriv->nread -= size / 2;
 	if (devpriv->nread < 0) {
 		dev_info(dev->class_dev, "nread off by one\n");
 		devpriv->nread = 0;
@@ -357,67 +511,12 @@ static void dt282x_ai_dma_interrupt(stru
 	/* clear the dual dma flag, making this the last dma segment */
 	/* XXX probably wrong */
 	if (!devpriv->ntrig) {
-		devpriv->supcsr &= ~(DT2821_DDMA);
-		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR);
+		devpriv->supcsr &= ~DT2821_SUPCSR_DDMA;
+		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
 	}
 #endif
 	/* restart the channel */
-	prep_ai_dma(dev, i, 0);
-}
-
-static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
-{
-	struct dt282x_private *devpriv = dev->private;
-	int dma_chan;
-	unsigned long dma_ptr;
-	unsigned long flags;
-
-	if (!devpriv->ntrig)
-		return 0;
-
-	if (n == 0)
-		n = devpriv->dma_maxsize;
-	if (n > devpriv->ntrig * 2)
-		n = devpriv->ntrig * 2;
-	devpriv->ntrig -= n / 2;
-
-	devpriv->dma[dma_index].size = n;
-	dma_chan = devpriv->dma[dma_index].chan;
-	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
-
-	set_dma_mode(dma_chan, DMA_MODE_READ);
-	flags = claim_dma_lock();
-	clear_dma_ff(dma_chan);
-	set_dma_addr(dma_chan, dma_ptr);
-	set_dma_count(dma_chan, n);
-	release_dma_lock(flags);
-
-	enable_dma(dma_chan);
-
-	return n;
-}
-
-static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
-{
-	struct dt282x_private *devpriv = dev->private;
-	int dma_chan;
-	unsigned long dma_ptr;
-	unsigned long flags;
-
-	devpriv->dma[dma_index].size = n;
-	dma_chan = devpriv->dma[dma_index].chan;
-	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
-
-	set_dma_mode(dma_chan, DMA_MODE_WRITE);
-	flags = claim_dma_lock();
-	clear_dma_ff(dma_chan);
-	set_dma_addr(dma_chan, dma_ptr);
-	set_dma_count(dma_chan, n);
-	release_dma_lock(flags);
-
-	enable_dma(dma_chan);
-
-	return n;
+	dt282x_prep_ai_dma(dev, cur_dma, 0);
 }
 
 static irqreturn_t dt282x_interrupt(int irq, void *d)
@@ -430,42 +529,42 @@ static irqreturn_t dt282x_interrupt(int
 	int handled = 0;
 
 	if (!dev->attached) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		return IRQ_HANDLED;
 	}
 
-	adcsr = inw(dev->iobase + DT2821_ADCSR);
-	dacsr = inw(dev->iobase + DT2821_DACSR);
-	supcsr = inw(dev->iobase + DT2821_SUPCSR);
-	if (supcsr & DT2821_DMAD) {
+	adcsr = inw(dev->iobase + DT2821_ADCSR_REG);
+	dacsr = inw(dev->iobase + DT2821_DACSR_REG);
+	supcsr = inw(dev->iobase + DT2821_SUPCSR_REG);
+	if (supcsr & DT2821_SUPCSR_DMAD) {
 		if (devpriv->dma_dir == DMA_MODE_READ)
-			dt282x_ai_dma_interrupt(dev);
+			dt282x_ai_dma_interrupt(dev, s);
 		else
-			dt282x_ao_dma_interrupt(dev);
+			dt282x_ao_dma_interrupt(dev, s_ao);
 		handled = 1;
 	}
-	if (adcsr & DT2821_ADERR) {
+	if (adcsr & DT2821_ADCSR_ADERR) {
 		if (devpriv->nread != 0) {
-			comedi_error(dev, "A/D error");
+			dev_err(dev->class_dev, "A/D error\n");
 			s->async->events |= COMEDI_CB_ERROR;
 		}
 		handled = 1;
 	}
-	if (dacsr & DT2821_DAERR) {
-		comedi_error(dev, "D/A error");
+	if (dacsr & DT2821_DACSR_DAERR) {
+		dev_err(dev->class_dev, "D/A error\n");
 		s_ao->async->events |= COMEDI_CB_ERROR;
 		handled = 1;
 	}
 #if 0
-	if (adcsr & DT2821_ADDONE) {
+	if (adcsr & DT2821_ADCSR_ADDONE) {
 		int ret;
 		unsigned short data;
 
-		data = inw(dev->iobase + DT2821_ADDAT);
-		data &= (1 << board->adbits) - 1;
-
+		data = inw(dev->iobase + DT2821_ADDAT_REG);
+		data &= s->maxdata;
 		if (devpriv->ad_2scomp)
-			data ^= 1 << (board->adbits - 1);
+			data = comedi_offset_munge(s, data);
+
 		ret = comedi_buf_put(s, data);
 
 		if (ret == 0)
@@ -475,9 +574,9 @@ static irqreturn_t dt282x_interrupt(int
 		if (!devpriv->nread) {
 			s->async->events |= COMEDI_CB_EOA;
 		} else {
-			if (supcsr & DT2821_SCDN)
-				outw(devpriv->supcsr | DT2821_STRIG,
-					dev->iobase + DT2821_SUPCSR);
+			if (supcsr & DT2821_SUPCSR_SCDN)
+				outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
+				     dev->iobase + DT2821_SUPCSR_REG);
 		}
 		handled = 1;
 	}
@@ -492,17 +591,20 @@ static void dt282x_load_changain(struct
 				 unsigned int *chanlist)
 {
 	struct dt282x_private *devpriv = dev->private;
-	unsigned int i;
-	unsigned int chan, range;
+	int i;
 
-	outw(DT2821_LLE | (n - 1), dev->iobase + DT2821_CHANCSR);
+	outw(DT2821_CHANCSR_LLE | DT2821_CHANCSR_NUMB(n),
+	     dev->iobase + DT2821_CHANCSR_REG);
 	for (i = 0; i < n; i++) {
-		chan = CR_CHAN(chanlist[i]);
-		range = CR_RANGE(chanlist[i]);
-		outw(devpriv->adcsr | (range << 4) | chan,
-			dev->iobase + DT2821_ADCSR);
+		unsigned int chan = CR_CHAN(chanlist[i]);
+		unsigned int range = CR_RANGE(chanlist[i]);
+
+		outw(devpriv->adcsr |
+		     DT2821_ADCSR_GS(range) |
+		     DT2821_ADCSR_CHAN(chan),
+		     dev->iobase + DT2821_ADCSR_REG);
 	}
-	outw(n - 1, dev->iobase + DT2821_CHANCSR);
+	outw(DT2821_CHANCSR_NUMB(n), dev->iobase + DT2821_CHANCSR_REG);
 }
 
 static int dt282x_ai_timeout(struct comedi_device *dev,
@@ -512,14 +614,14 @@ static int dt282x_ai_timeout(struct come
 {
 	unsigned int status;
 
-	status = inw(dev->iobase + DT2821_ADCSR);
+	status = inw(dev->iobase + DT2821_ADCSR_REG);
 	switch (context) {
-	case DT2821_MUXBUSY:
-		if ((status & DT2821_MUXBUSY) == 0)
+	case DT2821_ADCSR_MUXBUSY:
+		if ((status & DT2821_ADCSR_MUXBUSY) == 0)
 			return 0;
 		break;
-	case DT2821_ADDONE:
-		if (status & DT2821_ADDONE)
+	case DT2821_ADCSR_ADDONE:
+		if (status & DT2821_ADCSR_ADDONE)
 			return 0;
 		break;
 	default:
@@ -536,47 +638,53 @@ static int dt282x_ai_timeout(struct come
  */
 static int dt282x_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
+	unsigned int val;
 	int ret;
 	int i;
 
 	/* XXX should we really be enabling the ad clock here? */
-	devpriv->adcsr = DT2821_ADCLK;
-	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
+	devpriv->adcsr = DT2821_ADCSR_ADCLK;
+	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
 
 	dt282x_load_changain(dev, 1, &insn->chanspec);
 
-	outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
-	ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, DT2821_MUXBUSY);
+	outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
+	     dev->iobase + DT2821_SUPCSR_REG);
+	ret = comedi_timeout(dev, s, insn,
+			     dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
 	if (ret)
 		return ret;
 
 	for (i = 0; i < insn->n; i++) {
-		outw(devpriv->supcsr | DT2821_STRIG,
-			dev->iobase + DT2821_SUPCSR);
+		outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
+		     dev->iobase + DT2821_SUPCSR_REG);
 
-		ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout,
-				     DT2821_ADDONE);
+		ret = comedi_timeout(dev, s, insn,
+				     dt282x_ai_timeout, DT2821_ADCSR_ADDONE);
 		if (ret)
 			return ret;
 
-		data[i] =
-		    inw(dev->iobase +
-			DT2821_ADDAT) & ((1 << board->adbits) - 1);
+		val = inw(dev->iobase + DT2821_ADDAT_REG);
+		val &= s->maxdata;
 		if (devpriv->ad_2scomp)
-			data[i] ^= (1 << (board->adbits - 1));
+			val = comedi_offset_munge(s, val);
+
+		data[i] = val;
 	}
 
 	return i;
 }
 
 static int dt282x_ai_cmdtest(struct comedi_device *dev,
-			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
+			     struct comedi_subdevice *s,
+			     struct comedi_cmd *cmd)
 {
 	const struct dt282x_board *board = comedi_board(dev);
+	struct dt282x_private *devpriv = dev->private;
 	int err = 0;
 	unsigned int arg;
 
@@ -634,7 +742,7 @@ static int dt282x_ai_cmdtest(struct come
 	/* step 4: fix up any arguments */
 
 	arg = cmd->convert_arg;
-	dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+	devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
 	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 	if (err)
@@ -645,81 +753,62 @@ static int dt282x_ai_cmdtest(struct come
 
 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
-	int timer;
 	int ret;
 
-	if (devpriv->usedma == 0) {
-		comedi_error(dev,
-			     "driver requires 2 dma channels"
-						" to execute command");
-		return -EIO;
-	}
-
 	dt282x_disable_dma(dev);
 
-	if (cmd->convert_arg < board->ai_speed)
-		cmd->convert_arg = board->ai_speed;
-	timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST);
-	outw(timer, dev->iobase + DT2821_TMRCTR);
+	outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0;
-	} else {
-		/* external trigger */
-		devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1;
-	}
-	outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT,
-		dev->iobase + DT2821_SUPCSR);
+	devpriv->supcsr = DT2821_SUPCSR_ERRINTEN;
+	if (cmd->scan_begin_src == TRIG_FOLLOW)
+		devpriv->supcsr = DT2821_SUPCSR_DS_AD_CLK;
+	else
+		devpriv->supcsr = DT2821_SUPCSR_DS_AD_TRIG;
+	outw(devpriv->supcsr |
+	     DT2821_SUPCSR_CLRDMADNE |
+	     DT2821_SUPCSR_BUFFB |
+	     DT2821_SUPCSR_ADCINIT,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
 	devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg;
 	devpriv->nread = devpriv->ntrig;
 
 	devpriv->dma_dir = DMA_MODE_READ;
 	devpriv->current_dma_index = 0;
-	prep_ai_dma(dev, 0, 0);
+	dt282x_prep_ai_dma(dev, 0, 0);
 	if (devpriv->ntrig) {
-		prep_ai_dma(dev, 1, 0);
-		devpriv->supcsr |= DT2821_DDMA;
-		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR);
+		dt282x_prep_ai_dma(dev, 1, 0);
+		devpriv->supcsr |= DT2821_SUPCSR_DDMA;
+		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
 	}
 
 	devpriv->adcsr = 0;
 
 	dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist);
 
-	devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE;
-	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
+	devpriv->adcsr = DT2821_ADCSR_ADCLK | DT2821_ADCSR_IADDONE;
+	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
 
-	outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
-	ret = comedi_timeout(dev, s, NULL, dt282x_ai_timeout, DT2821_MUXBUSY);
+	outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
+	     dev->iobase + DT2821_SUPCSR_REG);
+	ret = comedi_timeout(dev, s, NULL,
+			     dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
 	if (ret)
 		return ret;
 
 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		outw(devpriv->supcsr | DT2821_STRIG,
-			dev->iobase + DT2821_SUPCSR);
+		outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
+			dev->iobase + DT2821_SUPCSR_REG);
 	} else {
-		devpriv->supcsr |= DT2821_XTRIG;
-		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR);
+		devpriv->supcsr |= DT2821_SUPCSR_XTRIG;
+		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
 	}
 
 	return 0;
 }
 
-static void dt282x_disable_dma(struct comedi_device *dev)
-{
-	struct dt282x_private *devpriv = dev->private;
-
-	if (devpriv->usedma) {
-		disable_dma(devpriv->dma[0].chan);
-		disable_dma(devpriv->dma[1].chan);
-	}
-}
-
 static int dt282x_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
@@ -728,101 +817,66 @@ static int dt282x_ai_cancel(struct comed
 	dt282x_disable_dma(dev);
 
 	devpriv->adcsr = 0;
-	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
+	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
 
 	devpriv->supcsr = 0;
-	outw(devpriv->supcsr | DT2821_ADCINIT, dev->iobase + DT2821_SUPCSR);
+	outw(devpriv->supcsr | DT2821_SUPCSR_ADCINIT,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
 	return 0;
 }
 
-static int dt282x_ns_to_timer(int *nanosec, int round_mode)
-{
-	int prescale, base, divider;
-
-	for (prescale = 0; prescale < 16; prescale++) {
-		if (prescale == 1)
-			continue;
-		base = 250 * (1 << prescale);
-		switch (round_mode) {
-		case TRIG_ROUND_NEAREST:
-		default:
-			divider = (*nanosec + base / 2) / base;
-			break;
-		case TRIG_ROUND_DOWN:
-			divider = (*nanosec) / base;
-			break;
-		case TRIG_ROUND_UP:
-			divider = (*nanosec + base - 1) / base;
-			break;
-		}
-		if (divider < 256) {
-			*nanosec = divider * base;
-			return (prescale << 8) | (255 - divider);
-		}
-	}
-	base = 250 * (1 << 15);
-	divider = 255;
-	*nanosec = divider * base;
-	return (15 << 8) | (255 - divider);
-}
-
-/*
- *    Analog output routine.  Selects single channel conversion,
- *      selects correct channel, converts from 2's compliment to
- *      offset binary if necessary, loads the data into the DAC
- *      data register, and performs the conversion.
- */
 static int dt282x_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct dt282x_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->ao_readback[chan];
 
-	return 1;
+	return insn->n;
 }
 
 static int dt282x_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
-	unsigned short d;
-	unsigned int chan;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int val;
+	int i;
 
-	chan = CR_CHAN(insn->chanspec);
-	d = data[0];
-	d &= (1 << board->dabits) - 1;
-	devpriv->ao[chan] = d;
+	devpriv->dacsr |= DT2821_DACSR_SSEL | DT2821_DACSR_YSEL(chan);
 
-	devpriv->dacsr |= DT2821_SSEL;
+	for (i = 0; i < insn->n; i++) {
+		val = data[i];
+		devpriv->ao_readback[chan] = val;
 
-	if (chan) {
-		/* select channel */
-		devpriv->dacsr |= DT2821_YSEL;
-		if (devpriv->da0_2scomp)
-			d ^= (1 << (board->dabits - 1));
-	} else {
-		devpriv->dacsr &= ~DT2821_YSEL;
-		if (devpriv->da1_2scomp)
-			d ^= (1 << (board->dabits - 1));
-	}
+		if (comedi_range_is_bipolar(s, range))
+			val = comedi_offset_munge(s, val);
 
-	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
+		outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
 
-	outw(d, dev->iobase + DT2821_DADAT);
+		outw(val, dev->iobase + DT2821_DADAT_REG);
 
-	outw(devpriv->supcsr | DT2821_DACON, dev->iobase + DT2821_SUPCSR);
+		outw(devpriv->supcsr | DT2821_SUPCSR_DACON,
+		     dev->iobase + DT2821_SUPCSR_REG);
+	}
 
-	return 1;
+	return insn->n;
 }
 
 static int dt282x_ao_cmdtest(struct comedi_device *dev,
-			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
+			     struct comedi_subdevice *s,
+			     struct comedi_cmd *cmd)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int err = 0;
 	unsigned int arg;
 
@@ -865,7 +919,7 @@ static int dt282x_ao_cmdtest(struct come
 	/* step 4: fix up any arguments */
 
 	arg = cmd->scan_begin_arg;
-	dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+	devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
 	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 
 	if (err)
@@ -892,7 +946,7 @@ static int dt282x_ao_inttrig(struct come
 		dev_err(dev->class_dev, "AO underrun\n");
 		return -EPIPE;
 	}
-	prep_ao_dma(dev, 0, size);
+	dt282x_prep_ao_dma(dev, 0, size);
 
 	size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf,
 					  devpriv->dma_maxsize);
@@ -900,9 +954,10 @@ static int dt282x_ao_inttrig(struct come
 		dev_err(dev->class_dev, "AO underrun\n");
 		return -EPIPE;
 	}
-	prep_ao_dma(dev, 1, size);
+	dt282x_prep_ao_dma(dev, 1, size);
 
-	outw(devpriv->supcsr | DT2821_STRIG, dev->iobase + DT2821_SUPCSR);
+	outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
+	     dev->iobase + DT2821_SUPCSR_REG);
 	s->async->inttrig = NULL;
 
 	return 1;
@@ -911,21 +966,18 @@ static int dt282x_ao_inttrig(struct come
 static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct dt282x_private *devpriv = dev->private;
-	int timer;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
-	if (devpriv->usedma == 0) {
-		comedi_error(dev,
-			     "driver requires 2 dma channels"
-						" to execute command");
-		return -EIO;
-	}
-
 	dt282x_disable_dma(dev);
 
-	devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA;
-	outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT,
-		dev->iobase + DT2821_SUPCSR);
+	devpriv->supcsr = DT2821_SUPCSR_ERRINTEN |
+			  DT2821_SUPCSR_DS_DA_CLK |
+			  DT2821_SUPCSR_DDMA;
+	outw(devpriv->supcsr |
+	     DT2821_SUPCSR_CLRDMADNE |
+	     DT2821_SUPCSR_BUFFB |
+	     DT2821_SUPCSR_DACINIT,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
 	devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len;
 	devpriv->nread = devpriv->ntrig;
@@ -933,11 +985,15 @@ static int dt282x_ao_cmd(struct comedi_d
 	devpriv->dma_dir = DMA_MODE_WRITE;
 	devpriv->current_dma_index = 0;
 
-	timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST);
-	outw(timer, dev->iobase + DT2821_TMRCTR);
+	outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
 
-	devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY;
-	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
+	/* clear all bits but the DIO direction bits */
+	devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
+
+	devpriv->dacsr |= (DT2821_DACSR_SSEL |
+			   DT2821_DACSR_DACLK |
+			   DT2821_DACSR_IDARDY);
+	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
 
 	s->async->inttrig = dt282x_ao_inttrig;
 
@@ -951,11 +1007,14 @@ static int dt282x_ao_cancel(struct comed
 
 	dt282x_disable_dma(dev);
 
-	devpriv->dacsr = 0;
-	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
+	/* clear all bits but the DIO direction bits */
+	devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
+
+	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
 
 	devpriv->supcsr = 0;
-	outw(devpriv->supcsr | DT2821_DACINIT, dev->iobase + DT2821_SUPCSR);
+	outw(devpriv->supcsr | DT2821_SUPCSR_DACINIT,
+	     dev->iobase + DT2821_SUPCSR_REG);
 
 	return 0;
 }
@@ -966,9 +1025,9 @@ static int dt282x_dio_insn_bits(struct c
 				unsigned int *data)
 {
 	if (comedi_dio_update_state(s, data))
-		outw(s->state, dev->iobase + DT2821_DIODAT);
+		outw(s->state, dev->iobase + DT2821_DIODAT_REG);
 
-	data[1] = inw(dev->iobase + DT2821_DIODAT);
+	data[1] = inw(dev->iobase + DT2821_DIODAT_REG);
 
 	return insn->n;
 }
@@ -992,13 +1051,13 @@ static int dt282x_dio_insn_config(struct
 	if (ret)
 		return ret;
 
-	devpriv->dacsr &= ~(DT2821_LBOE | DT2821_HBOE);
+	devpriv->dacsr &= ~(DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
 	if (s->io_bits & 0x00ff)
-		devpriv->dacsr |= DT2821_LBOE;
+		devpriv->dacsr |= DT2821_DACSR_LBOE;
 	if (s->io_bits & 0xff00)
-		devpriv->dacsr |= DT2821_HBOE;
+		devpriv->dacsr |= DT2821_DACSR_HBOE;
 
-	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);
+	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
 
 	return insn->n;
 }
@@ -1021,55 +1080,18 @@ static const struct comedi_lrange *opt_a
 		if (x < 0 || x >= 2)
 			x = 0;
 		return ai_range_pgl_table[x];
-	} else {
-		if (x < 0 || x >= 4)
-			x = 0;
-		return ai_range_table[x];
 	}
-}
 
-static const struct comedi_lrange *const ao_range_table[] = {
-	&range_bipolar10,
-	&range_unipolar10,
-	&range_bipolar5,
-	&range_unipolar5,
-	&range_bipolar2_5
-};
-
-static const struct comedi_lrange *opt_ao_range_lkup(int x)
-{
-	if (x < 0 || x >= 5)
+	if (x < 0 || x >= 4)
 		x = 0;
-	return ao_range_table[x];
+	return ai_range_table[x];
 }
 
-enum {  /* i/o base, irq, dma channels */
-	opt_iobase = 0, opt_irq, opt_dma1, opt_dma2,
-	opt_diff,		/* differential */
-	opt_ai_twos, opt_ao0_twos, opt_ao1_twos,	/* twos comp */
-	opt_ai_range, opt_ao0_range, opt_ao1_range,	/* range */
-};
-
 static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
 {
 	struct dt282x_private *devpriv = dev->private;
 	int ret;
 
-	devpriv->usedma = 0;
-
-	if (!dma1 && !dma2)
-		return 0;
-
-	if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7)
-		return -EINVAL;
-
-	if (dma2 < dma1) {
-		int i;
-		i = dma1;
-		dma1 = dma2;
-		dma2 = i;
-	}
-
 	ret = request_dma(dma1, "dt282x A");
 	if (ret)
 		return -EBUSY;
@@ -1086,8 +1108,45 @@ static int dt282x_grab_dma(struct comedi
 	if (!devpriv->dma[0].buf || !devpriv->dma[1].buf)
 		return -ENOMEM;
 
-	devpriv->usedma = 1;
+	return 0;
+}
+
+static void dt282x_free_dma(struct comedi_device *dev)
+{
+	struct dt282x_private *devpriv = dev->private;
+	int i;
+
+	if (!devpriv)
+		return;
+
+	for (i = 0; i < 2; i++) {
+		if (devpriv->dma[i].chan)
+			free_dma(devpriv->dma[i].chan);
+		if (devpriv->dma[i].buf)
+			free_page((unsigned long)devpriv->dma[i].buf);
+		devpriv->dma[i].chan = 0;
+		devpriv->dma[i].buf = NULL;
+	}
+}
 
+static int dt282x_initialize(struct comedi_device *dev)
+{
+	/* Initialize board */
+	outw(DT2821_SUPCSR_BDINIT, dev->iobase + DT2821_SUPCSR_REG);
+	inw(dev->iobase + DT2821_ADCSR_REG);
+
+	/*
+	 * At power up, some registers are in a well-known state.
+	 * Check them to see if a DT2821 series board is present.
+	 */
+	if (((inw(dev->iobase + DT2821_ADCSR_REG) & 0xfff0) != 0x7c00) ||
+	    ((inw(dev->iobase + DT2821_CHANCSR_REG) & 0xf0f0) != 0x70f0) ||
+	    ((inw(dev->iobase + DT2821_DACSR_REG) & 0x7c93) != 0x7c90) ||
+	    ((inw(dev->iobase + DT2821_SUPCSR_REG) & 0xf8ff) != 0x0000) ||
+	    ((inw(dev->iobase + DT2821_TMRCTR_REG) & 0xff00) != 0xf000)) {
+		dev_err(dev->class_dev, "board not found\n");
+		return -EIO;
+	}
 	return 0;
 }
 
@@ -1111,263 +1170,125 @@ static int dt282x_attach(struct comedi_d
 	struct dt282x_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
-	int i;
 
-	ret = comedi_request_region(dev, it->options[0], DT2821_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
-	outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR);
-	i = inw(dev->iobase + DT2821_ADCSR);
-
-	if (((inw(dev->iobase + DT2821_ADCSR) & DT2821_ADCSR_MASK)
-	     != DT2821_ADCSR_VAL) ||
-	    ((inw(dev->iobase + DT2821_CHANCSR) & DT2821_CHANCSR_MASK)
-	     != DT2821_CHANCSR_VAL) ||
-	    ((inw(dev->iobase + DT2821_DACSR) & DT2821_DACSR_MASK)
-	     != DT2821_DACSR_VAL) ||
-	    ((inw(dev->iobase + DT2821_SUPCSR) & DT2821_SUPCSR_MASK)
-	     != DT2821_SUPCSR_VAL) ||
-	    ((inw(dev->iobase + DT2821_TMRCTR) & DT2821_TMRCTR_MASK)
-	     != DT2821_TMRCTR_VAL)) {
-		dev_err(dev->class_dev, "board not found\n");
-		return -EIO;
-	}
-	/* should do board test */
-
-	if (it->options[opt_irq] > 0) {
-		ret = request_irq(it->options[opt_irq], dt282x_interrupt, 0,
-				  dev->board_name, dev);
-		if (ret == 0)
-			dev->irq = it->options[opt_irq];
-	}
+	ret = dt282x_initialize(dev);
+	if (ret)
+		return ret;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
-	if (dev->irq) {
-		ret = dt282x_grab_dma(dev, it->options[opt_dma1],
-				      it->options[opt_dma2]);
-		if (ret < 0)
-			return ret;
+	/* an IRQ and 2 DMA channels are required for async command support */
+	if (it->options[1] && it->options[2] && it->options[3]) {
+		unsigned int irq = it->options[1];
+		unsigned int dma1 = it->options[2];
+		unsigned int dma2 = it->options[3];
+
+		if (dma2 < dma1) {
+			unsigned int swap;
+
+			swap = dma1;
+			dma1 = dma2;
+			dma2 = swap;
+		}
+
+		if (dma1 != dma2 &&
+		    dma1 >= 5 && dma1 <= 7 &&
+		    dma2 >= 5 && dma2 <= 7) {
+			ret = request_irq(irq, dt282x_interrupt, 0,
+					  dev->board_name, dev);
+			if (ret == 0) {
+				dev->irq = irq;
+
+				ret = dt282x_grab_dma(dev, dma1, dma2);
+				if (ret < 0) {
+					dt282x_free_dma(dev);
+					free_irq(dev->irq, dev);
+					dev->irq = 0;
+				}
+			}
+		}
 	}
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
 		return ret;
 
+	/* Analog Input subdevice */
 	s = &dev->subdevices[0];
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE;
+	if ((it->options[4] && board->adchan_di) || board->adchan_se == 0) {
+		s->subdev_flags	|= SDF_DIFF;
+		s->n_chan	= board->adchan_di;
+	} else {
+		s->subdev_flags	|= SDF_COMMON;
+		s->n_chan	= board->adchan_se;
+	}
+	s->maxdata	= board->ai_maxdata;
 
-	/* ai subdevice */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE |
-	    ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON);
-	s->n_chan =
-	    (it->options[opt_diff]) ? board->adchan_di : board->adchan_se;
-	s->insn_read = dt282x_ai_insn_read;
-	s->maxdata = (1 << board->adbits) - 1;
-	s->range_table =
-	    opt_ai_range_lkup(board->ispgl, it->options[opt_ai_range]);
-	devpriv->ad_2scomp = it->options[opt_ai_twos];
+	s->range_table = opt_ai_range_lkup(board->ispgl, it->options[8]);
+	devpriv->ad_2scomp = it->options[5] ? 1 : 0;
+
+	s->insn_read	= dt282x_ai_insn_read;
 	if (dev->irq) {
 		dev->read_subdev = s;
-		s->subdev_flags |= SDF_CMD_READ;
-		s->len_chanlist = 16;
-		s->do_cmdtest = dt282x_ai_cmdtest;
-		s->do_cmd = dt282x_ai_cmd;
-		s->cancel = dt282x_ai_cancel;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= s->n_chan;
+		s->do_cmdtest	= dt282x_ai_cmdtest;
+		s->do_cmd	= dt282x_ai_cmd;
+		s->cancel	= dt282x_ai_cancel;
 	}
 
+	/* Analog Output subdevice */
 	s = &dev->subdevices[1];
+	if (board->dachan) {
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_WRITABLE;
+		s->n_chan	= board->dachan;
+		s->maxdata	= board->ao_maxdata;
 
-	s->n_chan = board->dachan;
-	if (s->n_chan) {
-		/* ao subsystem */
-		s->type = COMEDI_SUBD_AO;
-		s->subdev_flags = SDF_WRITABLE;
-		s->insn_read = dt282x_ao_insn_read;
-		s->insn_write = dt282x_ao_insn_write;
-		s->maxdata = (1 << board->dabits) - 1;
-		s->range_table_list = devpriv->darangelist;
-		devpriv->darangelist[0] =
-		    opt_ao_range_lkup(it->options[opt_ao0_range]);
-		devpriv->darangelist[1] =
-		    opt_ao_range_lkup(it->options[opt_ao1_range]);
-		devpriv->da0_2scomp = it->options[opt_ao0_twos];
-		devpriv->da1_2scomp = it->options[opt_ao1_twos];
+		/* ranges are per-channel, set by jumpers on the board */
+		s->range_table	= &dt282x_ao_range;
+
+		s->insn_read	= dt282x_ao_insn_read;
+		s->insn_write	= dt282x_ao_insn_write;
 		if (dev->irq) {
 			dev->write_subdev = s;
-			s->subdev_flags |= SDF_CMD_WRITE;
-			s->len_chanlist = 2;
-			s->do_cmdtest = dt282x_ao_cmdtest;
-			s->do_cmd = dt282x_ao_cmd;
-			s->cancel = dt282x_ao_cancel;
+			s->subdev_flags	|= SDF_CMD_WRITE;
+			s->len_chanlist	= s->n_chan;
+			s->do_cmdtest	= dt282x_ao_cmdtest;
+			s->do_cmd	= dt282x_ao_cmd;
+			s->cancel	= dt282x_ao_cancel;
 		}
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
 
+	/* Digital I/O subdevice */
 	s = &dev->subdevices[2];
-	/* dio subsystem */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 16;
-	s->insn_bits = dt282x_dio_insn_bits;
-	s->insn_config = dt282x_dio_insn_config;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= dt282x_dio_insn_bits;
+	s->insn_config	= dt282x_dio_insn_config;
 
 	return 0;
 }
 
 static void dt282x_detach(struct comedi_device *dev)
 {
-	struct dt282x_private *devpriv = dev->private;
-
-	if (dev->private) {
-		if (devpriv->dma[0].chan)
-			free_dma(devpriv->dma[0].chan);
-		if (devpriv->dma[1].chan)
-			free_dma(devpriv->dma[1].chan);
-		if (devpriv->dma[0].buf)
-			free_page((unsigned long)devpriv->dma[0].buf);
-		if (devpriv->dma[1].buf)
-			free_page((unsigned long)devpriv->dma[1].buf);
-	}
+	dt282x_free_dma(dev);
 	comedi_legacy_detach(dev);
 }
 
-static const struct dt282x_board boardtypes[] = {
-	{
-		.name		= "dt2821",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 20000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2821-f",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 6500,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2821-g",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 4000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2823",
-		.adbits		= 16,
-		.adchan_se	= 0,
-		.adchan_di	= 4,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 16,
-	}, {
-		.name		= "dt2824-pgh",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 20000,
-		.ispgl		= 0,
-		.dachan		= 0,
-		.dabits		= 0,
-	}, {
-		.name		= "dt2824-pgl",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 20000,
-		.ispgl		= 1,
-		.dachan		= 0,
-		.dabits		= 0,
-	}, {
-		.name		= "dt2825",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 20000,
-		.ispgl		= 1,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2827",
-		.adbits		= 16,
-		.adchan_se	= 0,
-		.adchan_di	= 4,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2828",
-		.adbits		= 12,
-		.adchan_se	= 4,
-		.adchan_di	= 0,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt2829",
-		.adbits		= 16,
-		.adchan_se	= 8,
-		.adchan_di	= 0,
-		.ai_speed	= 33250,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 16,
-	}, {
-		.name		= "dt21-ez",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 2,
-		.dabits		= 12,
-	}, {
-		.name		= "dt23-ez",
-		.adbits		= 16,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 0,
-		.dabits		= 0,
-	}, {
-		.name		= "dt24-ez",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 10000,
-		.ispgl		= 0,
-		.dachan		= 0,
-		.dabits		= 0,
-	}, {
-		.name		= "dt24-ez-pgl",
-		.adbits		= 12,
-		.adchan_se	= 16,
-		.adchan_di	= 8,
-		.ai_speed	= 10000,
-		.ispgl		= 1,
-		.dachan		= 0,
-		.dabits		= 0,
-	},
-};
-
 static struct comedi_driver dt282x_driver = {
 	.driver_name	= "dt282x",
 	.module		= THIS_MODULE,
@@ -1380,5 +1301,5 @@ static struct comedi_driver dt282x_drive
 module_comedi_driver(dt282x_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt3000.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt3000.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt3000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt3000.c	2014-09-28 17:29:07.000000000 -0400
@@ -244,7 +244,6 @@ static const struct dt3k_boardtype dt3k_
 #define DT3000_CHANNEL_MODE_DI		1
 
 struct dt3k_private {
-	void __iomem *io_addr;
 	unsigned int lock;
 	unsigned int ao_readback[2];
 	unsigned int ai_front;
@@ -255,14 +254,13 @@ struct dt3k_private {
 
 static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
 {
-	struct dt3k_private *devpriv = dev->private;
 	int i;
 	unsigned int status = 0;
 
-	writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
+	writew(cmd, dev->mmio + DPR_Command_Mbx);
 
 	for (i = 0; i < TIMEOUT; i++) {
-		status = readw(devpriv->io_addr + DPR_Command_Mbx);
+		status = readw(dev->mmio + DPR_Command_Mbx);
 		if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
 			break;
 		udelay(1);
@@ -277,28 +275,24 @@ static unsigned int dt3k_readsingle(stru
 				    unsigned int subsys, unsigned int chan,
 				    unsigned int gain)
 {
-	struct dt3k_private *devpriv = dev->private;
-
-	writew(subsys, devpriv->io_addr + DPR_SubSys);
+	writew(subsys, dev->mmio + DPR_SubSys);
 
-	writew(chan, devpriv->io_addr + DPR_Params(0));
-	writew(gain, devpriv->io_addr + DPR_Params(1));
+	writew(chan, dev->mmio + DPR_Params(0));
+	writew(gain, dev->mmio + DPR_Params(1));
 
 	dt3k_send_cmd(dev, CMD_READSINGLE);
 
-	return readw(devpriv->io_addr + DPR_Params(2));
+	return readw(dev->mmio + DPR_Params(2));
 }
 
 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
 			     unsigned int chan, unsigned int data)
 {
-	struct dt3k_private *devpriv = dev->private;
-
-	writew(subsys, devpriv->io_addr + DPR_SubSys);
+	writew(subsys, dev->mmio + DPR_SubSys);
 
-	writew(chan, devpriv->io_addr + DPR_Params(0));
-	writew(0, devpriv->io_addr + DPR_Params(1));
-	writew(data, devpriv->io_addr + DPR_Params(2));
+	writew(chan, dev->mmio + DPR_Params(0));
+	writew(0, dev->mmio + DPR_Params(1));
+	writew(data, dev->mmio + DPR_Params(2));
 
 	dt3k_send_cmd(dev, CMD_WRITESINGLE);
 }
@@ -313,7 +307,7 @@ static void dt3k_ai_empty_fifo(struct co
 	int i;
 	unsigned short data;
 
-	front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
+	front = readw(dev->mmio + DPR_AD_Buf_Front);
 	count = front - devpriv->ai_front;
 	if (count < 0)
 		count += AI_FIFO_DEPTH;
@@ -321,7 +315,7 @@ static void dt3k_ai_empty_fifo(struct co
 	rear = devpriv->ai_rear;
 
 	for (i = 0; i < count; i++) {
-		data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
+		data = readw(dev->mmio + DPR_ADC_buffer + rear);
 		comedi_buf_put(s, data);
 		rear++;
 		if (rear >= AI_FIFO_DEPTH)
@@ -329,17 +323,16 @@ static void dt3k_ai_empty_fifo(struct co
 	}
 
 	devpriv->ai_rear = rear;
-	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+	writew(rear, dev->mmio + DPR_AD_Buf_Rear);
 }
 
-static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+static int dt3k_ai_cancel(struct comedi_device *dev,
+			  struct comedi_subdevice *s)
 {
-	struct dt3k_private *devpriv = dev->private;
-
-	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
+	writew(SUBS_AI, dev->mmio + DPR_SubSys);
 	dt3k_send_cmd(dev, CMD_STOP);
 
-	writew(0, devpriv->io_addr + DPR_Int_Mask);
+	writew(0, dev->mmio + DPR_Int_Mask);
 
 	return 0;
 }
@@ -351,14 +344,13 @@ static int debug_n_ints;
 static irqreturn_t dt3k_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct dt3k_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned int status;
 
 	if (!dev->attached)
 		return IRQ_NONE;
 
-	status = readw(devpriv->io_addr + DPR_Intr_Flag);
+	status = readw(dev->mmio + DPR_Intr_Flag);
 
 	if (status & DT3000_ADFULL) {
 		dt3k_ai_empty_fifo(dev, s);
@@ -377,7 +369,7 @@ static irqreturn_t dt3k_interrupt(int ir
 }
 
 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
-			    unsigned int round_mode)
+			    unsigned int flags)
 {
 	int divider, base, prescale;
 
@@ -386,7 +378,7 @@ static int dt3k_ns_to_timer(unsigned int
 
 	for (prescale = 0; prescale < 16; prescale++) {
 		base = timer_base * (prescale + 1);
-		switch (round_mode) {
+		switch (flags & TRIG_ROUND_MASK) {
 		case TRIG_ROUND_NEAREST:
 		default:
 			divider = (*nanosec + base / 2) / base;
@@ -467,13 +459,13 @@ static int dt3k_ai_cmdtest(struct comedi
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		dt3k_ns_to_timer(100, &arg, cmd->flags & TRIG_ROUND_MASK);
+		dt3k_ns_to_timer(100, &arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		dt3k_ns_to_timer(50, &arg, cmd->flags & TRIG_ROUND_MASK);
+		dt3k_ns_to_timer(50, &arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -491,7 +483,6 @@ static int dt3k_ai_cmdtest(struct comedi
 
 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct dt3k_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int i;
 	unsigned int chan, range, aref;
@@ -503,42 +494,40 @@ static int dt3k_ai_cmd(struct comedi_dev
 		chan = CR_CHAN(cmd->chanlist[i]);
 		range = CR_RANGE(cmd->chanlist[i]);
 
-		writew((range << 6) | chan,
-		       devpriv->io_addr + DPR_ADC_buffer + i);
+		writew((range << 6) | chan, dev->mmio + DPR_ADC_buffer + i);
 	}
 	aref = CR_AREF(cmd->chanlist[0]);
 
-	writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
+	writew(cmd->scan_end_arg, dev->mmio + DPR_Params(0));
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
-					   cmd->flags & TRIG_ROUND_MASK);
-		writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
-		writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
+		divider = dt3k_ns_to_timer(50, &cmd->convert_arg, cmd->flags);
+		writew((divider >> 16), dev->mmio + DPR_Params(1));
+		writew((divider & 0xffff), dev->mmio + DPR_Params(2));
 	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
-					    cmd->flags & TRIG_ROUND_MASK);
-		writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
-		writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
+					    cmd->flags);
+		writew((tscandiv >> 16), dev->mmio + DPR_Params(3));
+		writew((tscandiv & 0xffff), dev->mmio + DPR_Params(4));
 	}
 
 	mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
-	writew(mode, devpriv->io_addr + DPR_Params(5));
-	writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
+	writew(mode, dev->mmio + DPR_Params(5));
+	writew(aref == AREF_DIFF, dev->mmio + DPR_Params(6));
 
-	writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
+	writew(AI_FIFO_DEPTH / 2, dev->mmio + DPR_Params(7));
 
-	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
+	writew(SUBS_AI, dev->mmio + DPR_SubSys);
 	dt3k_send_cmd(dev, CMD_CONFIG);
 
 	writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
-	       devpriv->io_addr + DPR_Int_Mask);
+	       dev->mmio + DPR_Int_Mask);
 
 	debug_n_ints = 0;
 
-	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
+	writew(SUBS_AI, dev->mmio + DPR_SubSys);
 	dt3k_send_cmd(dev, CMD_START);
 
 	return 0;
@@ -594,16 +583,14 @@ static int dt3k_ao_insn_read(struct come
 
 static void dt3k_dio_config(struct comedi_device *dev, int bits)
 {
-	struct dt3k_private *devpriv = dev->private;
-
 	/* XXX */
-	writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
+	writew(SUBS_DOUT, dev->mmio + DPR_SubSys);
 
-	writew(bits, devpriv->io_addr + DPR_Params(0));
+	writew(bits, dev->mmio + DPR_Params(0));
 #if 0
 	/* don't know */
-	writew(0, devpriv->io_addr + DPR_Params(1));
-	writew(0, devpriv->io_addr + DPR_Params(2));
+	writew(0, dev->mmio + DPR_Params(1));
+	writew(0, dev->mmio + DPR_Params(2));
 #endif
 
 	dt3k_send_cmd(dev, CMD_CONFIG);
@@ -647,20 +634,20 @@ static int dt3k_dio_insn_bits(struct com
 
 static int dt3k_mem_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	struct dt3k_private *devpriv = dev->private;
 	unsigned int addr = CR_CHAN(insn->chanspec);
 	int i;
 
 	for (i = 0; i < insn->n; i++) {
-		writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
-		writew(addr, devpriv->io_addr + DPR_Params(0));
-		writew(1, devpriv->io_addr + DPR_Params(1));
+		writew(SUBS_MEM, dev->mmio + DPR_SubSys);
+		writew(addr, dev->mmio + DPR_Params(0));
+		writew(1, dev->mmio + DPR_Params(1));
 
 		dt3k_send_cmd(dev, CMD_READCODE);
 
-		data[i] = readw(devpriv->io_addr + DPR_Params(2));
+		data[i] = readw(dev->mmio + DPR_Params(2));
 	}
 
 	return i;
@@ -690,8 +677,8 @@ static int dt3000_auto_attach(struct com
 	if (ret < 0)
 		return ret;
 
-	devpriv->io_addr = pci_ioremap_bar(pcidev, 0);
-	if (!devpriv->io_addr)
+	dev->mmio = pci_ioremap_bar(pcidev, 0);
+	if (!dev->mmio)
 		return -ENOMEM;
 
 	if (pcidev->irq) {
@@ -765,14 +752,10 @@ static int dt3000_auto_attach(struct com
 
 static void dt3000_detach(struct comedi_device *dev)
 {
-	struct dt3k_private *devpriv = dev->private;
-
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (devpriv) {
-		if (devpriv->io_addr)
-			iounmap(devpriv->io_addr);
-	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt9812.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt9812.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/dt9812.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/dt9812.c	2014-09-28 17:29:07.000000000 -0400
@@ -653,6 +653,7 @@ static int dt9812_find_endpoints(struct
 
 	for (i = 0; i < host->desc.bNumEndpoints; ++i) {
 		int dir = -1;
+
 		ep = &host->endpoint[i].desc;
 		switch (i) {
 		case 0:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/gsc_hpdi.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/gsc_hpdi.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/gsc_hpdi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/gsc_hpdi.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,7 +51,7 @@
 #include "comedi_fc.h"
 
 /*
- * PCI BAR2 Register map (devpriv->mmio)
+ * PCI BAR2 Register map (dev->mmio)
  */
 #define FIRMWARE_REV_REG			0x00
 #define FEATURES_REG_PRESENT_BIT		(1 << 15)
@@ -148,7 +148,6 @@ static const struct hpdi_board hpdi_boar
 
 struct hpdi_private {
 	void __iomem *plx9080_mmio;
-	void __iomem *mmio;
 	uint32_t *dio_buffer[NUM_DMA_BUFFERS];	/*  dma buffers */
 	/* physical addresses of dma buffers */
 	dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS];
@@ -227,11 +226,11 @@ static irqreturn_t gsc_hpdi_interrupt(in
 	if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0)
 		return IRQ_NONE;
 
-	hpdi_intr_status = readl(devpriv->mmio + INTERRUPT_STATUS_REG);
-	hpdi_board_status = readl(devpriv->mmio + BOARD_STATUS_REG);
+	hpdi_intr_status = readl(dev->mmio + INTERRUPT_STATUS_REG);
+	hpdi_board_status = readl(dev->mmio + BOARD_STATUS_REG);
 
 	if (hpdi_intr_status)
-		writel(hpdi_intr_status, devpriv->mmio + INTERRUPT_STATUS_REG);
+		writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG);
 
 	/*  spin lock makes sure no one else changes plx dma control reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -294,10 +293,8 @@ static void gsc_hpdi_abort_dma(struct co
 static int gsc_hpdi_cancel(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
-	struct hpdi_private *devpriv = dev->private;
-
-	writel(0, devpriv->mmio + BOARD_CONTROL_REG);
-	writel(0, devpriv->mmio + INTERRUPT_CONTROL_REG);
+	writel(0, dev->mmio + BOARD_CONTROL_REG);
+	writel(0, dev->mmio + INTERRUPT_CONTROL_REG);
 
 	gsc_hpdi_abort_dma(dev, 0);
 
@@ -316,7 +313,7 @@ static int gsc_hpdi_cmd(struct comedi_de
 	if (s->io_bits)
 		return -EINVAL;
 
-	writel(RX_FIFO_RESET_BIT, devpriv->mmio + BOARD_CONTROL_REG);
+	writel(RX_FIFO_RESET_BIT, dev->mmio + BOARD_CONTROL_REG);
 
 	gsc_hpdi_abort_dma(dev, 0);
 
@@ -349,13 +346,12 @@ static int gsc_hpdi_cmd(struct comedi_de
 		devpriv->dio_count = 1;
 
 	/* clear over/under run status flags */
-	writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT,
-	       devpriv->mmio + BOARD_STATUS_REG);
+	writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT, dev->mmio + BOARD_STATUS_REG);
 
 	/* enable interrupts */
-	writel(RX_FULL_INTR, devpriv->mmio + INTERRUPT_CONTROL_REG);
+	writel(RX_FULL_INTR, dev->mmio + INTERRUPT_CONTROL_REG);
 
-	writel(RX_ENABLE_BIT, devpriv->mmio + BOARD_CONTROL_REG);
+	writel(RX_ENABLE_BIT, dev->mmio + BOARD_CONTROL_REG);
 
 	return 0;
 }
@@ -517,20 +513,20 @@ static int gsc_hpdi_init(struct comedi_d
 	uint32_t plx_intcsr_bits;
 
 	/* wait 10usec after reset before accessing fifos */
-	writel(BOARD_RESET_BIT, devpriv->mmio + BOARD_CONTROL_REG);
+	writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG);
 	udelay(10);
 
 	writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32),
-	       devpriv->mmio + RX_PROG_ALMOST_REG);
+	       dev->mmio + RX_PROG_ALMOST_REG);
 	writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32),
-	       devpriv->mmio + TX_PROG_ALMOST_REG);
+	       dev->mmio + TX_PROG_ALMOST_REG);
 
-	devpriv->tx_fifo_size = readl(devpriv->mmio + TX_FIFO_SIZE_REG) &
+	devpriv->tx_fifo_size = readl(dev->mmio + TX_FIFO_SIZE_REG) &
 				FIFO_SIZE_MASK;
-	devpriv->rx_fifo_size = readl(devpriv->mmio + RX_FIFO_SIZE_REG) &
+	devpriv->rx_fifo_size = readl(dev->mmio + RX_FIFO_SIZE_REG) &
 				FIFO_SIZE_MASK;
 
-	writel(0, devpriv->mmio + INTERRUPT_CONTROL_REG);
+	writel(0, dev->mmio + INTERRUPT_CONTROL_REG);
 
 	/*  enable interrupts */
 	plx_intcsr_bits =
@@ -621,8 +617,8 @@ static int gsc_hpdi_auto_attach(struct c
 	pci_set_master(pcidev);
 
 	devpriv->plx9080_mmio = pci_ioremap_bar(pcidev, 0);
-	devpriv->mmio = pci_ioremap_bar(pcidev, 2);
-	if (!devpriv->plx9080_mmio || !devpriv->mmio) {
+	dev->mmio = pci_ioremap_bar(pcidev, 2);
+	if (!devpriv->plx9080_mmio || !dev->mmio) {
 		dev_warn(dev->class_dev, "failed to remap io memory\n");
 		return -ENOMEM;
 	}
@@ -696,8 +692,8 @@ static void gsc_hpdi_detach(struct comed
 			writel(0, devpriv->plx9080_mmio + PLX_INTRCS_REG);
 			iounmap(devpriv->plx9080_mmio);
 		}
-		if (devpriv->mmio)
-			iounmap(devpriv->mmio);
+		if (dev->mmio)
+			iounmap(dev->mmio);
 		/*  free pci dma buffers */
 		for (i = 0; i < NUM_DMA_BUFFERS; i++) {
 			if (devpriv->dio_buffer[i])
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/icp_multi.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/icp_multi.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/icp_multi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/icp_multi.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,8 +49,6 @@ Configuration options: not applicable, u
 
 #include "../comedidev.h"
 
-#define PCI_DEVICE_ID_ICP_MULTI	0x8000
-
 #define ICP_MULTI_ADC_CSR	0	/* R/W: ADC command/status register */
 #define ICP_MULTI_AI		2	/* R:   Analogue input data */
 #define ICP_MULTI_DAC_CSR	4	/* R/W: DAC command/status register */
@@ -110,7 +108,6 @@ static const char range_codes_analog[] =
 
 struct icp_multi_private {
 	char valid;		/*  card is usable */
-	void __iomem *io_addr;		/*  Pointer to mapped io address */
 	unsigned int AdcCmdStatus;	/*  ADC Command/Status register */
 	unsigned int DacCmdStatus;	/*  DAC Command/Status register */
 	unsigned int IntEnable;	/*  Interrupt Enable register */
@@ -166,8 +163,7 @@ static void setup_channel_list(struct co
 		devpriv->AdcCmdStatus |= range;
 
 		/* Output channel, range, mode to ICP Multi */
-		writew(devpriv->AdcCmdStatus,
-		       devpriv->io_addr + ICP_MULTI_ADC_CSR);
+		writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR);
 	}
 }
 
@@ -176,10 +172,9 @@ static int icp_multi_ai_eoc(struct comed
 			    struct comedi_insn *insn,
 			    unsigned long context)
 {
-	struct icp_multi_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readw(devpriv->io_addr + ICP_MULTI_ADC_CSR);
+	status = readw(dev->mmio + ICP_MULTI_ADC_CSR);
 	if ((status & ADC_BSY) == 0)
 		return 0;
 	return -EBUSY;
@@ -187,7 +182,8 @@ static int icp_multi_ai_eoc(struct comed
 
 static int icp_multi_insn_read_ai(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	struct icp_multi_private *devpriv = dev->private;
 	int ret = 0;
@@ -195,11 +191,11 @@ static int icp_multi_insn_read_ai(struct
 
 	/*  Disable A/D conversion ready interrupt */
 	devpriv->IntEnable &= ~ADC_READY;
-	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
 
 	/*  Clear interrupt status */
 	devpriv->IntStatus |= ADC_READY;
-	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
 
 	/*  Set up appropriate channel, mode and range data, for specified ch */
 	setup_channel_list(dev, s, &insn->chanspec, 1);
@@ -207,8 +203,7 @@ static int icp_multi_insn_read_ai(struct
 	for (n = 0; n < insn->n; n++) {
 		/*  Set start ADC bit */
 		devpriv->AdcCmdStatus |= ADC_ST;
-		writew(devpriv->AdcCmdStatus,
-		       devpriv->io_addr + ICP_MULTI_ADC_CSR);
+		writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR);
 		devpriv->AdcCmdStatus &= ~ADC_ST;
 
 		udelay(1);
@@ -218,17 +213,16 @@ static int icp_multi_insn_read_ai(struct
 		if (ret)
 			break;
 
-		data[n] =
-		    (readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff;
+		data[n] = (readw(dev->mmio + ICP_MULTI_AI) >> 4) & 0x0fff;
 	}
 
 	/*  Disable interrupt */
 	devpriv->IntEnable &= ~ADC_READY;
-	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
 
 	/*  Clear interrupt status */
 	devpriv->IntStatus |= ADC_READY;
-	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
 
 	return ret ? ret : n;
 }
@@ -238,10 +232,9 @@ static int icp_multi_ao_eoc(struct comed
 			    struct comedi_insn *insn,
 			    unsigned long context)
 {
-	struct icp_multi_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readw(devpriv->io_addr + ICP_MULTI_DAC_CSR);
+	status = readw(dev->mmio + ICP_MULTI_DAC_CSR);
 	if ((status & DAC_BSY) == 0)
 		return 0;
 	return -EBUSY;
@@ -249,7 +242,8 @@ static int icp_multi_ao_eoc(struct comed
 
 static int icp_multi_insn_write_ao(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
 	struct icp_multi_private *devpriv = dev->private;
 	int n, chan, range;
@@ -257,11 +251,11 @@ static int icp_multi_insn_write_ao(struc
 
 	/*  Disable D/A conversion ready interrupt */
 	devpriv->IntEnable &= ~DAC_READY;
-	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
 
 	/*  Clear interrupt status */
 	devpriv->IntStatus |= DAC_READY;
-	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
 
 	/*  Get channel number and range */
 	chan = CR_CHAN(insn->chanspec);
@@ -276,7 +270,7 @@ static int icp_multi_insn_write_ao(struc
 	devpriv->DacCmdStatus |= range_codes_analog[range];
 	devpriv->DacCmdStatus |= (chan << 8);
 
-	writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR);
+	writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
 
 	for (n = 0; n < insn->n; n++) {
 		/*  Wait for analogue output data register to be
@@ -286,12 +280,12 @@ static int icp_multi_insn_write_ao(struc
 			/*  Disable interrupt */
 			devpriv->IntEnable &= ~DAC_READY;
 			writew(devpriv->IntEnable,
-			       devpriv->io_addr + ICP_MULTI_INT_EN);
+			       dev->mmio + ICP_MULTI_INT_EN);
 
 			/*  Clear interrupt status */
 			devpriv->IntStatus |= DAC_READY;
 			writew(devpriv->IntStatus,
-			       devpriv->io_addr + ICP_MULTI_INT_STAT);
+			       dev->mmio + ICP_MULTI_INT_STAT);
 
 			/*  Clear data received */
 			devpriv->ao_data[chan] = 0;
@@ -300,12 +294,11 @@ static int icp_multi_insn_write_ao(struc
 		}
 
 		/*  Write data to analogue output data register */
-		writew(data[n], devpriv->io_addr + ICP_MULTI_AO);
+		writew(data[n], dev->mmio + ICP_MULTI_AO);
 
 		/*  Set DAC_ST bit to write the data to selected channel */
 		devpriv->DacCmdStatus |= DAC_ST;
-		writew(devpriv->DacCmdStatus,
-		       devpriv->io_addr + ICP_MULTI_DAC_CSR);
+		writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
 		devpriv->DacCmdStatus &= ~DAC_ST;
 
 		/*  Save analogue output data */
@@ -334,11 +327,10 @@ static int icp_multi_insn_read_ao(struct
 
 static int icp_multi_insn_bits_di(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
-	struct icp_multi_private *devpriv = dev->private;
-
-	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+	data[1] = readw(dev->mmio + ICP_MULTI_DI);
 
 	return insn->n;
 }
@@ -348,12 +340,10 @@ static int icp_multi_insn_bits_do(struct
 				  struct comedi_insn *insn,
 				  unsigned int *data)
 {
-	struct icp_multi_private *devpriv = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		writew(s->state, devpriv->io_addr + ICP_MULTI_DO);
+		writew(s->state, dev->mmio + ICP_MULTI_DO);
 
-	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+	data[1] = readw(dev->mmio + ICP_MULTI_DI);
 
 	return insn->n;
 }
@@ -376,11 +366,10 @@ static int icp_multi_insn_write_ctr(stru
 static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct icp_multi_private *devpriv = dev->private;
 	int int_no;
 
 	/*  Is this interrupt from our board? */
-	int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ;
+	int_no = readw(dev->mmio + ICP_MULTI_INT_STAT) & Status_IRQ;
 	if (!int_no)
 		/*  No, exit */
 		return IRQ_NONE;
@@ -420,7 +409,7 @@ static int check_channel_list(struct com
 
 	/*  Check that we at least have one channel to check */
 	if (n_chan < 1) {
-		comedi_error(dev, "range/channel list is empty!");
+		dev_err(dev->class_dev, "range/channel list is empty!\n");
 		return 0;
 	}
 	/*  Check all channels */
@@ -428,14 +417,14 @@ static int check_channel_list(struct com
 		/*  Check that channel number is < maximum */
 		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
 			if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) {
-				comedi_error(dev,
-					     "Incorrect differential ai ch-nr");
+				dev_err(dev->class_dev,
+					"Incorrect differential ai ch-nr\n");
 				return 0;
 			}
 		} else {
 			if (CR_CHAN(chanlist[i]) > s->n_chan) {
-				comedi_error(dev,
-					     "Incorrect ai channel number");
+				dev_err(dev->class_dev,
+					"Incorrect ai channel number\n");
 				return 0;
 			}
 		}
@@ -450,8 +439,8 @@ static int icp_multi_reset(struct comedi
 	unsigned int i;
 
 	/*  Clear INT enables and requests */
-	writew(0, devpriv->io_addr + ICP_MULTI_INT_EN);
-	writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT);
+	writew(0, dev->mmio + ICP_MULTI_INT_EN);
+	writew(0x00ff, dev->mmio + ICP_MULTI_INT_STAT);
 
 	/* Set DACs to 0..5V range and 0V output */
 	for (i = 0; i < 4; i++) {
@@ -461,21 +450,20 @@ static int icp_multi_reset(struct comedi
 		devpriv->DacCmdStatus |= (i << 8);
 
 		/*  Output 0V */
-		writew(0, devpriv->io_addr + ICP_MULTI_AO);
+		writew(0, dev->mmio + ICP_MULTI_AO);
 
 		/*  Set start conversion bit */
 		devpriv->DacCmdStatus |= DAC_ST;
 
 		/*  Output to command / status register */
-		writew(devpriv->DacCmdStatus,
-			devpriv->io_addr + ICP_MULTI_DAC_CSR);
+		writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
 
 		/*  Delay to allow DAC time to recover */
 		udelay(1);
 	}
 
 	/* Digital outputs to 0 */
-	writew(0, devpriv->io_addr + ICP_MULTI_DO);
+	writew(0, dev->mmio + ICP_MULTI_DO);
 
 	return 0;
 }
@@ -496,8 +484,8 @@ static int icp_multi_auto_attach(struct
 	if (ret)
 		return ret;
 
-	devpriv->io_addr = pci_ioremap_bar(pcidev, 2);
-	if (!devpriv->io_addr)
+	dev->mmio = pci_ioremap_bar(pcidev, 2);
+	if (!dev->mmio)
 		return -ENOMEM;
 
 	ret = comedi_alloc_subdevices(dev, 5);
@@ -575,8 +563,8 @@ static void icp_multi_detach(struct come
 			icp_multi_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (devpriv && devpriv->io_addr)
-		iounmap(devpriv->io_addr);
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
@@ -594,7 +582,7 @@ static int icp_multi_pci_probe(struct pc
 }
 
 static const struct pci_device_id icp_multi_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ICP, PCI_DEVICE_ID_ICP_MULTI) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ICP, 0x8000) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, icp_multi_pci_table);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ii_pci20kc.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ii_pci20kc.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ii_pci20kc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ii_pci20kc.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,6 +33,7 @@
 /*
  * Register I/O map
  */
+#define II20K_SIZE			0x400
 #define II20K_MOD_OFFSET		0x100
 #define II20K_ID_REG			0x00
 #define II20K_ID_MOD1_EMPTY		(1 << 7)
@@ -135,16 +136,10 @@ struct ii20k_ao_private {
 	unsigned int last_data[2];
 };
 
-struct ii20k_private {
-	void __iomem *ioaddr;
-};
-
 static void __iomem *ii20k_module_iobase(struct comedi_device *dev,
 					 struct comedi_subdevice *s)
 {
-	struct ii20k_private *devpriv = dev->private;
-
-	return devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET;
+	return dev->mmio + (s->index + 1) * II20K_MOD_OFFSET;
 }
 
 static int ii20k_ao_insn_read(struct comedi_device *dev,
@@ -281,7 +276,6 @@ static int ii20k_ai_insn_read(struct com
 static void ii20k_dio_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
-	struct ii20k_private *devpriv = dev->private;
 	unsigned char ctrl01 = 0;
 	unsigned char ctrl23 = 0;
 	unsigned char dir_ena = 0;
@@ -338,9 +332,9 @@ static void ii20k_dio_config(struct come
 	ctrl23 |= II20K_CTRL23_SET;
 
 	/* order is important */
-	writeb(ctrl01, devpriv->ioaddr + II20K_CTRL01_REG);
-	writeb(ctrl23, devpriv->ioaddr + II20K_CTRL23_REG);
-	writeb(dir_ena, devpriv->ioaddr + II20K_DIR_ENA_REG);
+	writeb(ctrl01, dev->mmio + II20K_CTRL01_REG);
+	writeb(ctrl23, dev->mmio + II20K_CTRL23_REG);
+	writeb(dir_ena, dev->mmio + II20K_DIR_ENA_REG);
 }
 
 static int ii20k_dio_insn_config(struct comedi_device *dev,
@@ -375,29 +369,28 @@ static int ii20k_dio_insn_bits(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct ii20k_private *devpriv = dev->private;
 	unsigned int mask;
 
 	mask = comedi_dio_update_state(s, data);
 	if (mask) {
 		if (mask & 0x000000ff)
 			writeb((s->state >> 0) & 0xff,
-			       devpriv->ioaddr + II20K_DIO0_REG);
+			       dev->mmio + II20K_DIO0_REG);
 		if (mask & 0x0000ff00)
 			writeb((s->state >> 8) & 0xff,
-			       devpriv->ioaddr + II20K_DIO1_REG);
+			       dev->mmio + II20K_DIO1_REG);
 		if (mask & 0x00ff0000)
 			writeb((s->state >> 16) & 0xff,
-			       devpriv->ioaddr + II20K_DIO2_REG);
+			       dev->mmio + II20K_DIO2_REG);
 		if (mask & 0xff000000)
 			writeb((s->state >> 24) & 0xff,
-			       devpriv->ioaddr + II20K_DIO3_REG);
+			       dev->mmio + II20K_DIO3_REG);
 	}
 
-	data[1] = readb(devpriv->ioaddr + II20K_DIO0_REG);
-	data[1] |= readb(devpriv->ioaddr + II20K_DIO1_REG) << 8;
-	data[1] |= readb(devpriv->ioaddr + II20K_DIO2_REG) << 16;
-	data[1] |= readb(devpriv->ioaddr + II20K_DIO3_REG) << 24;
+	data[1] = readb(dev->mmio + II20K_DIO0_REG);
+	data[1] |= readb(dev->mmio + II20K_DIO1_REG) << 8;
+	data[1] |= readb(dev->mmio + II20K_DIO2_REG) << 16;
+	data[1] |= readb(dev->mmio + II20K_DIO3_REG) << 24;
 
 	return insn->n;
 }
@@ -446,19 +439,32 @@ static int ii20k_init_module(struct come
 static int ii20k_attach(struct comedi_device *dev,
 			struct comedi_devconfig *it)
 {
-	struct ii20k_private *devpriv;
 	struct comedi_subdevice *s;
+	unsigned int membase;
 	unsigned char id;
 	bool has_dio;
 	int ret;
 
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
+	membase = it->options[0];
+	if (!membase || (membase & ~(0x100000 - II20K_SIZE))) {
+		dev_warn(dev->class_dev,
+			 "%s: invalid memory address specified\n",
+			 dev->board_name);
+		return -EINVAL;
+	}
 
-	devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0];
+	if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) {
+		dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n",
+			 dev->board_name, membase, II20K_SIZE);
+		return -EIO;
+	}
+	dev->iobase = membase;	/* actually, a memory address */
 
-	id = readb(devpriv->ioaddr + II20K_ID_REG);
+	dev->mmio = ioremap(membase, II20K_SIZE);
+	if (!dev->mmio)
+		return -ENOMEM;
+
+	id = readb(dev->mmio + II20K_ID_REG);
 	switch (id & II20K_ID_MASK) {
 	case II20K_ID_PCI20001C_1A:
 		has_dio = false;
@@ -521,11 +527,19 @@ static int ii20k_attach(struct comedi_de
 	return 0;
 }
 
+static void ii20k_detach(struct comedi_device *dev)
+{
+	if (dev->mmio)
+		iounmap(dev->mmio);
+	if (dev->iobase)	/* actually, a memory address */
+		release_mem_region(dev->iobase, II20K_SIZE);
+}
+
 static struct comedi_driver ii20k_driver = {
 	.driver_name	= "ii_pci20kc",
 	.module		= THIS_MODULE,
 	.attach		= ii20k_attach,
-	.detach		= comedi_legacy_detach,
+	.detach		= ii20k_detach,
 };
 module_comedi_driver(ii20k_driver);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/jr3_pci.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/jr3_pci.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2014-08-07 04:58:57.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2014-09-28 21:41:33.000000000 -0400
@@ -195,6 +195,7 @@ static struct six_axis_t get_min_full_sc
 					     *channel)
 {
 	struct six_axis_t result;
+
 	result.fx = get_s16(&channel->min_full_scale.fx);
 	result.fy = get_s16(&channel->min_full_scale.fy);
 	result.fz = get_s16(&channel->min_full_scale.fz);
@@ -208,6 +209,7 @@ static struct six_axis_t get_max_full_sc
 					     *channel)
 {
 	struct six_axis_t result;
+
 	result.fx = get_s16(&channel->max_full_scale.fx);
 	result.fy = get_s16(&channel->max_full_scale.fy);
 	result.fz = get_s16(&channel->max_full_scale.fz);
@@ -318,6 +320,8 @@ static int read_idm_word(const u8 *data,
 			 unsigned int *val)
 {
 	int result = 0;
+	int value;
+
 	if (pos && val) {
 		/*  Skip over non hex */
 		for (; *pos < size && !isxdigit(data[*pos]); (*pos)++)
@@ -325,7 +329,6 @@ static int read_idm_word(const u8 *data,
 		/*  Collect value */
 		*val = 0;
 		for (; *pos < size; (*pos)++) {
-			int value;
 			value = hex_to_bin(data[*pos]);
 			if (value >= 0) {
 				result = 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ke_counter.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ke_counter.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ke_counter.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ke_counter.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,6 +93,67 @@ static int ke_counter_insn_read(struct c
 	return insn->n;
 }
 
+static void ke_counter_reset(struct comedi_device *dev)
+{
+	unsigned int chan;
+
+	for (chan = 0; chan < 3; chan++)
+		outb(0, dev->iobase + KE_RESET_REG(chan));
+}
+
+static int ke_counter_insn_config(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
+{
+	unsigned char src;
+
+	switch (data[0]) {
+	case INSN_CONFIG_SET_CLOCK_SRC:
+		switch (data[1]) {
+		case KE_CLK_20MHZ:	/* default */
+			src = KE_OSC_SEL_20MHZ;
+			break;
+		case KE_CLK_4MHZ:	/* option */
+			src = KE_OSC_SEL_4MHZ;
+			break;
+		case KE_CLK_EXT:	/* Pin 21 on D-sub */
+			src = KE_OSC_SEL_EXT;
+			break;
+		default:
+			return -EINVAL;
+		}
+		outb(src, dev->iobase + KE_OSC_SEL_REG);
+		break;
+	case INSN_CONFIG_GET_CLOCK_SRC:
+		src = inb(dev->iobase + KE_OSC_SEL_REG);
+		switch (src) {
+		case KE_OSC_SEL_20MHZ:
+			data[1] = KE_CLK_20MHZ;
+			data[2] = 50;	/* 50ns */
+			break;
+		case KE_OSC_SEL_4MHZ:
+			data[1] = KE_CLK_4MHZ;
+			data[2] = 250;	/* 250ns */
+			break;
+		case KE_OSC_SEL_EXT:
+			data[1] = KE_CLK_EXT;
+			data[2] = 0;	/* Unknown */
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case INSN_CONFIG_RESET:
+		ke_counter_reset(dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return insn->n;
+}
+
 static int ke_counter_do_insn_bits(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn,
@@ -130,6 +191,7 @@ static int ke_counter_auto_attach(struct
 	s->range_table	= &range_unknown;
 	s->insn_read	= ke_counter_insn_read;
 	s->insn_write	= ke_counter_insn_write;
+	s->insn_config	= ke_counter_insn_config;
 
 	s = &dev->subdevices[1];
 	s->type		= COMEDI_SUBD_DO;
@@ -141,9 +203,7 @@ static int ke_counter_auto_attach(struct
 
 	outb(KE_OSC_SEL_20MHZ, dev->iobase + KE_OSC_SEL_REG);
 
-	outb(0, dev->iobase + KE_RESET_REG(0));
-	outb(0, dev->iobase + KE_RESET_REG(1));
-	outb(0, dev->iobase + KE_RESET_REG(2));
+	ke_counter_reset(dev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/Makefile
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -13,6 +13,7 @@ obj-$(CONFIG_COMEDI_SKEL)		+= skel.o
 
 # Comedi ISA drivers
 obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA)	+= amplc_dio200.o
+obj-$(CONFIG_COMEDI_AMPLC_PC236_ISA)	+= amplc_pc236.o
 obj-$(CONFIG_COMEDI_AMPLC_PC263_ISA)	+= amplc_pc263.o
 obj-$(CONFIG_COMEDI_PCL711)		+= pcl711.o
 obj-$(CONFIG_COMEDI_PCL724)		+= pcl724.o
@@ -80,7 +81,7 @@ obj-$(CONFIG_COMEDI_ADV_PCI1723)	+= adv_
 obj-$(CONFIG_COMEDI_ADV_PCI1724)	+= adv_pci1724.o
 obj-$(CONFIG_COMEDI_ADV_PCI_DIO)	+= adv_pci_dio.o
 obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI)	+= amplc_dio200_pci.o
-obj-$(CONFIG_COMEDI_AMPLC_PC236)	+= amplc_pc236.o
+obj-$(CONFIG_COMEDI_AMPLC_PC236_PCI)	+= amplc_pci236.o
 obj-$(CONFIG_COMEDI_AMPLC_PC263_PCI)	+= amplc_pci263.o
 obj-$(CONFIG_COMEDI_AMPLC_PCI224)	+= amplc_pci224.o
 obj-$(CONFIG_COMEDI_AMPLC_PCI230)	+= amplc_pci230.o
@@ -138,5 +139,6 @@ obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA)	+=
 
 obj-$(CONFIG_COMEDI_8255)		+= 8255.o
 obj-$(CONFIG_COMEDI_AMPLC_DIO200)	+= amplc_dio200_common.o
+obj-$(CONFIG_COMEDI_AMPLC_PC236)	+= amplc_pc236_common.o
 obj-$(CONFIG_COMEDI_DAS08)		+= das08.o
 obj-$(CONFIG_COMEDI_FC)			+= comedi_fc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/me4000.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/me4000.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/me4000.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/me4000.c	2014-09-28 17:29:07.000000000 -0400
@@ -170,7 +170,6 @@ broken.
 
 #define ME4000_AI_MIN_TICKS			66
 #define ME4000_AI_MIN_SAMPLE_TIME		2000
-#define ME4000_AI_BASE_FREQUENCY		(unsigned int) 33E6
 
 #define ME4000_AI_CHANNEL_LIST_COUNT		1024
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/me_daq.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/me_daq.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/me_daq.c	2014-08-07 04:58:59.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/me_daq.c	2014-09-28 21:41:36.000000000 -0400
@@ -167,7 +167,6 @@ static const struct me_board me_boards[]
 
 struct me_private_data {
 	void __iomem *plx_regbase;	/* PLX configuration base address */
-	void __iomem *me_regbase;	/* Base address of the Meilhaus card */
 
 	unsigned short control_1;	/* Mirror of CONTROL_1 register */
 	unsigned short control_2;	/* Mirror of CONTROL_2 register */
@@ -209,7 +208,7 @@ static int me_dio_insn_config(struct com
 	else
 		devpriv->control_2 &= ~ENABLE_PORT_B;
 
-	writew(devpriv->control_2, devpriv->me_regbase + ME_CONTROL_2);
+	writew(devpriv->control_2, dev->mmio + ME_CONTROL_2);
 
 	return insn->n;
 }
@@ -219,9 +218,8 @@ static int me_dio_insn_bits(struct comed
 			    struct comedi_insn *insn,
 			    unsigned int *data)
 {
-	struct me_private_data *dev_private = dev->private;
-	void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A;
-	void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B;
+	void __iomem *mmio_porta = dev->mmio + ME_DIO_PORT_A;
+	void __iomem *mmio_portb = dev->mmio + ME_DIO_PORT_B;
 	unsigned int mask;
 	unsigned int val;
 
@@ -253,10 +251,9 @@ static int me_ai_eoc(struct comedi_devic
 		     struct comedi_insn *insn,
 		     unsigned long context)
 {
-	struct me_private_data *dev_private = dev->private;
 	unsigned int status;
 
-	status = readw(dev_private->me_regbase + ME_STATUS);
+	status = readw(dev->mmio + ME_STATUS);
 	if ((status & 0x0004) == 0)
 		return 0;
 	return -EBUSY;
@@ -276,32 +273,32 @@ static int me_ai_insn_read(struct comedi
 
 	/* stop any running conversion */
 	dev_private->control_1 &= 0xFFFC;
-	writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+	writew(dev_private->control_1, dev->mmio + ME_CONTROL_1);
 
 	/* clear chanlist and ad fifo */
 	dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST);
-	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+	writew(dev_private->control_2, dev->mmio + ME_CONTROL_2);
 
 	/* reset any pending interrupt */
-	writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
+	writew(0x00, dev->mmio + ME_RESET_INTERRUPT);
 
 	/* enable the chanlist and ADC fifo */
 	dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST);
-	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+	writew(dev_private->control_2, dev->mmio + ME_CONTROL_2);
 
 	/* write to channel list fifo */
 	val = chan & 0x0f;			/* b3:b0 channel */
 	val |= (rang & 0x03) << 4;		/* b5:b4 gain */
 	val |= (rang & 0x04) << 4;		/* b6 polarity */
 	val |= ((aref & AREF_DIFF) ? 0x80 : 0);	/* b7 differential */
-	writew(val & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
+	writew(val & 0xff, dev->mmio + ME_CHANNEL_LIST);
 
 	/* set ADC mode to software trigger */
 	dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;
-	writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+	writew(dev_private->control_1, dev->mmio + ME_CONTROL_1);
 
 	/* start conversion by reading from ADC_START */
-	readw(dev_private->me_regbase + ME_ADC_START);
+	readw(dev->mmio + ME_ADC_START);
 
 	/* wait for ADC fifo not empty flag */
 	ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0);
@@ -309,13 +306,13 @@ static int me_ai_insn_read(struct comedi
 		return ret;
 
 	/* get value from ADC fifo */
-	val = readw(dev_private->me_regbase + ME_READ_AD_FIFO);
+	val = readw(dev->mmio + ME_READ_AD_FIFO);
 	val = (val ^ 0x800) & 0x0fff;
 	data[0] = val;
 
 	/* stop any running conversion */
 	dev_private->control_1 &= 0xFFFC;
-	writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+	writew(dev_private->control_1, dev->mmio + ME_CONTROL_1);
 
 	return 1;
 }
@@ -332,11 +329,11 @@ static int me_ao_insn_write(struct comed
 
 	/* Enable all DAC */
 	dev_private->control_2 |= ENABLE_DAC;
-	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+	writew(dev_private->control_2, dev->mmio + ME_CONTROL_2);
 
 	/* and set DAC to "buffered" mode */
 	dev_private->control_2 |= BUFFERED_DAC;
-	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+	writew(dev_private->control_2, dev->mmio + ME_CONTROL_2);
 
 	/* Set dac-control register */
 	for (i = 0; i < insn->n; i++) {
@@ -349,21 +346,20 @@ static int me_ao_insn_write(struct comed
 			dev_private->dac_control |=
 			    ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan);
 	}
-	writew(dev_private->dac_control,
-	       dev_private->me_regbase + ME_DAC_CONTROL);
+	writew(dev_private->dac_control, dev->mmio + ME_DAC_CONTROL);
 
 	/* Update dac-control register */
-	readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE);
+	readw(dev->mmio + ME_DAC_CONTROL_UPDATE);
 
 	/* Set data register */
 	for (i = 0; i < insn->n; i++) {
 		writew((data[0] & s->maxdata),
-		       dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1));
+		       dev->mmio + ME_DAC_DATA_A + (chan << 1));
 		dev_private->ao_readback[chan] = (data[0] & s->maxdata);
 	}
 
 	/* Update dac with data registers */
-	readw(dev_private->me_regbase + ME_DAC_UPDATE);
+	readw(dev->mmio + ME_DAC_UPDATE);
 
 	return insn->n;
 }
@@ -396,13 +392,13 @@ static int me2600_xilinx_download(struct
 	writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR);
 
 	/* First, make a dummy read to reset xilinx */
-	value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET);
+	value = readw(dev->mmio + XILINX_DOWNLOAD_RESET);
 
 	/* Wait until reset is over */
 	sleep(1);
 
 	/* Write a dummy value to Xilinx */
-	writeb(0x00, dev_private->me_regbase + 0x0);
+	writeb(0x00, dev->mmio + 0x0);
 	sleep(1);
 
 	/*
@@ -426,12 +422,11 @@ static int me2600_xilinx_download(struct
 	 * Firmware data start at offset 16
 	 */
 	for (i = 0; i < file_length; i++)
-		writeb((data[16 + i] & 0xff),
-		       dev_private->me_regbase + 0x0);
+		writeb((data[16 + i] & 0xff), dev->mmio + 0x0);
 
 	/* Write 5 dummy values to xilinx */
 	for (i = 0; i < 5; i++)
-		writeb(0x00, dev_private->me_regbase + 0x0);
+		writeb(0x00, dev->mmio + 0x0);
 
 	/* Test if there was an error during download -> INTB was thrown */
 	value = readl(dev_private->plx_regbase + PLX9052_INTCSR);
@@ -459,10 +454,10 @@ static int me_reset(struct comedi_device
 	struct me_private_data *dev_private = dev->private;
 
 	/* Reset board */
-	writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
-	writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
-	writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
-	writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL);
+	writew(0x00, dev->mmio + ME_CONTROL_1);
+	writew(0x00, dev->mmio + ME_CONTROL_2);
+	writew(0x00, dev->mmio + ME_RESET_INTERRUPT);
+	writew(0x00, dev->mmio + ME_DAC_CONTROL);
 
 	/* Save values in the board context */
 	dev_private->dac_control = 0;
@@ -500,8 +495,8 @@ static int me_auto_attach(struct comedi_
 	if (!dev_private->plx_regbase)
 		return -ENOMEM;
 
-	dev_private->me_regbase = pci_ioremap_bar(pcidev, 2);
-	if (!dev_private->me_regbase)
+	dev->mmio = pci_ioremap_bar(pcidev, 2);
+	if (!dev->mmio)
 		return -ENOMEM;
 
 	/* Download firmware and reset card */
@@ -559,9 +554,9 @@ static void me_detach(struct comedi_devi
 	struct me_private_data *dev_private = dev->private;
 
 	if (dev_private) {
-		if (dev_private->me_regbase) {
+		if (dev->mmio) {
 			me_reset(dev);
-			iounmap(dev_private->me_regbase);
+			iounmap(dev->mmio);
 		}
 		if (dev_private->plx_regbase)
 			iounmap(dev_private->plx_regbase);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mf6x4.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mf6x4.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mf6x4.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mf6x4.c	2014-09-28 17:29:07.000000000 -0400
@@ -93,7 +93,6 @@ struct mf6x4_private {
 	 * and MF634 yet we will call them 0, 1, 2
 	 */
 	void __iomem *bar0_mem;
-	void __iomem *bar1_mem;
 	void __iomem *bar2_mem;
 
 	/*
@@ -108,25 +107,22 @@ struct mf6x4_private {
 };
 
 static int mf6x4_di_insn_bits(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	struct mf6x4_private *devpriv = dev->private;
-
-	data[1] = ioread16(devpriv->bar1_mem + MF6X4_DIN_R) & MF6X4_DIN_M;
+	data[1] = ioread16(dev->mmio + MF6X4_DIN_R) & MF6X4_DIN_M;
 
 	return insn->n;
 }
 
 static int mf6x4_do_insn_bits(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	struct mf6x4_private *devpriv = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		iowrite16(s->state & MF6X4_DOUT_M,
-			  devpriv->bar1_mem + MF6X4_DOUT_R);
+		iowrite16(s->state & MF6X4_DOUT_M, dev->mmio + MF6X4_DOUT_R);
 
 	data[1] = s->state;
 
@@ -149,40 +145,40 @@ static int mf6x4_ai_eoc(struct comedi_de
 
 static int mf6x4_ai_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	struct mf6x4_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int ret;
 	int i;
 	int d;
 
 	/* Set the ADC channel number in the scan list */
-	iowrite16((1 << chan) & MF6X4_ADCTRL_M,
-		  devpriv->bar1_mem + MF6X4_ADCTRL_R);
+	iowrite16((1 << chan) & MF6X4_ADCTRL_M, dev->mmio + MF6X4_ADCTRL_R);
 
 	for (i = 0; i < insn->n; i++) {
 		/* Trigger ADC conversion by reading ADSTART */
-		ioread16(devpriv->bar1_mem + MF6X4_ADSTART_R);
+		ioread16(dev->mmio + MF6X4_ADSTART_R);
 
 		ret = comedi_timeout(dev, s, insn, mf6x4_ai_eoc, 0);
 		if (ret)
 			return ret;
 
 		/* Read the actual value */
-		d = ioread16(devpriv->bar1_mem + MF6X4_ADDATA_R);
+		d = ioread16(dev->mmio + MF6X4_ADDATA_R);
 		d &= s->maxdata;
 		data[i] = d;
 	}
 
-	iowrite16(0x0, devpriv->bar1_mem + MF6X4_ADCTRL_R);
+	iowrite16(0x0, dev->mmio + MF6X4_ADCTRL_R);
 
 	return insn->n;
 }
 
 static int mf6x4_ao_insn_write(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct mf6x4_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
@@ -195,8 +191,7 @@ static int mf6x4_ao_insn_write(struct co
 		  devpriv->gpioc_R);
 
 	for (i = 0; i < insn->n; i++) {
-		iowrite16(data[i] & MF6X4_DA_M,
-			  devpriv->bar1_mem + MF6X4_DAC_R(chan));
+		iowrite16(data[i] & MF6X4_DA_M, dev->mmio + MF6X4_DAC_R(chan));
 
 		devpriv->ao_readback[chan] = data[i];
 	}
@@ -246,8 +241,8 @@ static int mf6x4_auto_attach(struct come
 	if (!devpriv->bar0_mem)
 		return -ENODEV;
 
-	devpriv->bar1_mem = pci_ioremap_bar(pcidev, board->bar_nums[1]);
-	if (!devpriv->bar1_mem)
+	dev->mmio = pci_ioremap_bar(pcidev, board->bar_nums[1]);
+	if (!dev->mmio)
 		return -ENODEV;
 
 	devpriv->bar2_mem = pci_ioremap_bar(pcidev, board->bar_nums[2]);
@@ -310,8 +305,8 @@ static void mf6x4_detach(struct comedi_d
 
 	if (devpriv->bar0_mem)
 		iounmap(devpriv->bar0_mem);
-	if (devpriv->bar1_mem)
-		iounmap(devpriv->bar1_mem);
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	if (devpriv->bar2_mem)
 		iounmap(devpriv->bar2_mem);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mite.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mite.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mite.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,10 +90,12 @@ static unsigned mite_fifo_size(struct mi
 	unsigned fcr_bits = readl(mite->mite_io_addr + MITE_FCR(channel));
 	unsigned empty_count = (fcr_bits >> 16) & 0xff;
 	unsigned full_count = fcr_bits & 0xff;
+
 	return empty_count + full_count;
 }
 
-int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
+int mite_setup2(struct comedi_device *dev,
+		struct mite_struct *mite, bool use_win1)
 {
 	unsigned long length;
 	int i;
@@ -104,24 +106,24 @@ int mite_setup2(struct mite_struct *mite
 
 	mite->mite_io_addr = pci_ioremap_bar(mite->pcidev, 0);
 	if (!mite->mite_io_addr) {
-		dev_err(&mite->pcidev->dev,
+		dev_err(dev->class_dev,
 			"Failed to remap mite io memory address\n");
 		return -ENOMEM;
 	}
 	mite->mite_phys_addr = pci_resource_start(mite->pcidev, 0);
 
-	mite->daq_io_addr = pci_ioremap_bar(mite->pcidev, 1);
-	if (!mite->daq_io_addr) {
-		dev_err(&mite->pcidev->dev,
+	dev->mmio = pci_ioremap_bar(mite->pcidev, 1);
+	if (!dev->mmio) {
+		dev_err(dev->class_dev,
 			"Failed to remap daq io memory address\n");
 		return -ENOMEM;
 	}
 	mite->daq_phys_addr = pci_resource_start(mite->pcidev, 1);
 	length = pci_resource_len(mite->pcidev, 1);
 
-	if (use_iodwbsr_1) {
+	if (use_win1) {
 		writel(0, mite->mite_io_addr + MITE_IODWBSR);
-		dev_info(&mite->pcidev->dev,
+		dev_info(dev->class_dev,
 			 "using I/O Window Base Size register 1\n");
 		writel(mite->daq_phys_addr | WENAB |
 		       MITE_IODWBSR_1_WSIZE_bits(length),
@@ -147,7 +149,7 @@ int mite_setup2(struct mite_struct *mite
 	csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR);
 	mite->num_channels = mite_csigr_dmac(csigr_bits);
 	if (mite->num_channels > MAX_MITE_DMA_CHANNELS) {
-		dev_warn(&mite->pcidev->dev,
+		dev_warn(dev->class_dev,
 			 "mite: bug? chip claims to have %i dma channels. Setting to %i.\n",
 			 mite->num_channels, MAX_MITE_DMA_CHANNELS);
 		mite->num_channels = MAX_MITE_DMA_CHANNELS;
@@ -162,36 +164,22 @@ int mite_setup2(struct mite_struct *mite
 		       mite->mite_io_addr + MITE_CHCR(i));
 	}
 	mite->fifo_size = mite_fifo_size(mite, 0);
-	dev_info(&mite->pcidev->dev, "fifo size is %i.\n", mite->fifo_size);
+	dev_info(dev->class_dev, "fifo size is %i.\n", mite->fifo_size);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mite_setup2);
 
-int mite_setup(struct mite_struct *mite)
-{
-	return mite_setup2(mite, 0);
-}
-EXPORT_SYMBOL_GPL(mite_setup);
-
-void mite_unsetup(struct mite_struct *mite)
+void mite_detach(struct mite_struct *mite)
 {
-	/* unsigned long offset, start, length; */
-
 	if (!mite)
 		return;
 
-	if (mite->mite_io_addr) {
+	if (mite->mite_io_addr)
 		iounmap(mite->mite_io_addr);
-		mite->mite_io_addr = NULL;
-	}
-	if (mite->daq_io_addr) {
-		iounmap(mite->daq_io_addr);
-		mite->daq_io_addr = NULL;
-	}
-	if (mite->mite_phys_addr)
-		mite->mite_phys_addr = 0;
+
+	kfree(mite);
 }
-EXPORT_SYMBOL_GPL(mite_unsetup);
+EXPORT_SYMBOL_GPL(mite_detach);
 
 struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite)
 {
@@ -450,12 +438,14 @@ EXPORT_SYMBOL_GPL(mite_prep_dma);
 static u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
 {
 	struct mite_struct *mite = mite_chan->mite;
+
 	return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
 }
 
 u32 mite_bytes_in_transit(struct mite_channel *mite_chan)
 {
 	struct mite_struct *mite = mite_chan->mite;
+
 	return readl(mite->mite_io_addr +
 		     MITE_FCR(mite_chan->channel)) & 0x000000FF;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mite.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mite.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mite.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mite.h	2014-09-28 17:29:07.000000000 -0400
@@ -55,7 +55,6 @@ struct mite_struct {
 	resource_size_t mite_phys_addr;
 	void __iomem *mite_io_addr;
 	resource_size_t daq_phys_addr;
-	void __iomem *daq_io_addr;
 	struct mite_channel channels[MAX_MITE_DMA_CHANNELS];
 	short channel_allocated[MAX_MITE_DMA_CHANNELS];
 	int num_channels;
@@ -65,24 +64,15 @@ struct mite_struct {
 
 struct mite_struct *mite_alloc(struct pci_dev *pcidev);
 
-static inline void mite_free(struct mite_struct *mite)
-{
-	kfree(mite);
-}
-
-static inline unsigned int mite_irq(struct mite_struct *mite)
-{
-	return mite->pcidev->irq;
-};
+int mite_setup2(struct comedi_device *, struct mite_struct *, bool use_win1);
 
-static inline unsigned int mite_device_id(struct mite_struct *mite)
+static inline int mite_setup(struct comedi_device *dev,
+			     struct mite_struct *mite)
 {
-	return mite->pcidev->device;
-};
+	return mite_setup2(dev, mite, false);
+}
 
-int mite_setup(struct mite_struct *mite);
-int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1);
-void mite_unsetup(struct mite_struct *mite);
+void mite_detach(struct mite_struct *mite);
 struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite);
 void mite_free_ring(struct mite_dma_descriptor_ring *ring);
 struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
@@ -122,11 +112,6 @@ void mite_prep_dma(struct mite_channel *
 int mite_buf_change(struct mite_dma_descriptor_ring *ring,
 		    struct comedi_subdevice *s);
 
-static inline int CHAN_OFFSET(int channel)
-{
-	return 0x500 + 0x100 * channel;
-};
-
 enum mite_registers {
 	/* The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be
 	   written and read back.  The bits 0x1f always read as 1.
@@ -138,90 +123,25 @@ enum mite_registers {
 	MITE_PCI_CONFIG_OFFSET = 0x300,
 	MITE_CSIGR = 0x460	/* chip signature */
 };
-static inline int MITE_CHOR(int channel)
-{				/*  channel operation */
-	return CHAN_OFFSET(channel) + 0x0;
-};
-
-static inline int MITE_CHCR(int channel)
-{				/*  channel control */
-	return CHAN_OFFSET(channel) + 0x4;
-};
-
-static inline int MITE_TCR(int channel)
-{				/*  transfer count */
-	return CHAN_OFFSET(channel) + 0x8;
-};
-
-static inline int MITE_MCR(int channel)
-{				/*  memory configuration */
-	return CHAN_OFFSET(channel) + 0xc;
-};
-
-static inline int MITE_MAR(int channel)
-{				/*  memory address */
-	return CHAN_OFFSET(channel) + 0x10;
-};
-
-static inline int MITE_DCR(int channel)
-{				/*  device configuration */
-	return CHAN_OFFSET(channel) + 0x14;
-};
-
-static inline int MITE_DAR(int channel)
-{				/*  device address */
-	return CHAN_OFFSET(channel) + 0x18;
-};
-
-static inline int MITE_LKCR(int channel)
-{				/*  link configuration */
-	return CHAN_OFFSET(channel) + 0x1c;
-};
-
-static inline int MITE_LKAR(int channel)
-{				/*  link address */
-	return CHAN_OFFSET(channel) + 0x20;
-};
-
-static inline int MITE_LLKAR(int channel)
-{				/*  see mite section of tnt5002 manual */
-	return CHAN_OFFSET(channel) + 0x24;
-};
-
-static inline int MITE_BAR(int channel)
-{				/*  base address */
-	return CHAN_OFFSET(channel) + 0x28;
-};
-
-static inline int MITE_BCR(int channel)
-{				/*  base count */
-	return CHAN_OFFSET(channel) + 0x2c;
-};
-
-static inline int MITE_SAR(int channel)
-{				/*  ? address */
-	return CHAN_OFFSET(channel) + 0x30;
-};
-
-static inline int MITE_WSCR(int channel)
-{				/*  ? */
-	return CHAN_OFFSET(channel) + 0x34;
-};
-
-static inline int MITE_WSER(int channel)
-{				/*  ? */
-	return CHAN_OFFSET(channel) + 0x38;
-};
-
-static inline int MITE_CHSR(int channel)
-{				/*  channel status */
-	return CHAN_OFFSET(channel) + 0x3c;
-};
 
-static inline int MITE_FCR(int channel)
-{				/*  fifo count */
-	return CHAN_OFFSET(channel) + 0x40;
-};
+#define MITE_CHAN(x)	(0x500 + 0x100 * (x))
+#define MITE_CHOR(x)	(0x00 + MITE_CHAN(x))	/* channel operation */
+#define MITE_CHCR(x)	(0x04 + MITE_CHAN(x))	/* channel control */
+#define MITE_TCR(x)	(0x08 + MITE_CHAN(x))	/* transfer count */
+#define MITE_MCR(x)	(0x0c + MITE_CHAN(x))	/* memory configuration */
+#define MITE_MAR(x)	(0x10 + MITE_CHAN(x))	/* memory address */
+#define MITE_DCR(x)	(0x14 + MITE_CHAN(x))	/* device configuration */
+#define MITE_DAR(x)	(0x18 + MITE_CHAN(x))	/* device address */
+#define MITE_LKCR(x)	(0x1c + MITE_CHAN(x))	/* link configuration */
+#define MITE_LKAR(x)	(0x20 + MITE_CHAN(x))	/* link address */
+#define MITE_LLKAR(x)	(0x24 + MITE_CHAN(x))	/* see tnt5002 manual */
+#define MITE_BAR(x)	(0x28 + MITE_CHAN(x))	/* base address */
+#define MITE_BCR(x)	(0x2c + MITE_CHAN(x))	/* base count */
+#define MITE_SAR(x)	(0x30 + MITE_CHAN(x))	/* ? address */
+#define MITE_WSCR(x)	(0x34 + MITE_CHAN(x))	/* ? */
+#define MITE_WSER(x)	(0x38 + MITE_CHAN(x))	/* ? */
+#define MITE_CHSR(x)	(0x3c + MITE_CHAN(x))	/* channel status */
+#define MITE_FCR(x)	(0x40 + MITE_CHAN(x))	/* fifo count */
 
 enum MITE_IODWBSR_bits {
 	WENAB = 0x80,		/*  window enable */
@@ -269,11 +189,9 @@ static inline int mite_csigr_dmac(u32 cs
 static inline int mite_csigr_wpdep(u32 csigr_bits)
 {				/*  write post fifo depth */
 	unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7;
-	if (wpdep_bits == 0)
-		return 0;
-	else
-		return 1 << (wpdep_bits - 1);
-};
+
+	return (wpdep_bits) ? (1 << (wpdep_bits - 1)) : 0;
+}
 
 static inline int mite_csigr_wins(u32 csigr_bits)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mpc624.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mpc624.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/mpc624.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/mpc624.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,9 +56,6 @@ Configuration Options:
 
 #include <linux/delay.h>
 
-/* Consecutive I/O port addresses */
-#define MPC624_SIZE             16
-
 /* Offsets of different ports */
 #define MPC624_MASTER_CONTROL	0 /* not used */
 #define MPC624_GNMUXCH          1 /* Gain, Mux, Channel of ADC */
@@ -279,7 +276,7 @@ static int mpc624_attach(struct comedi_d
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], MPC624_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/multiq3.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/multiq3.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/multiq3.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/multiq3.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,8 +28,6 @@ Devices: [Quanser Consulting] MultiQ-3 (
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#define MULTIQ3_SIZE 16
-
 /*
  * MULTIQ-3 port offsets
  */
@@ -189,12 +187,12 @@ static int multiq3_encoder_insn_read(str
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
-	int n;
 	int chan = CR_CHAN(insn->chanspec);
 	int control = MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3);
+	int value;
+	int n;
 
 	for (n = 0; n < insn->n; n++) {
-		int value;
 		outw(control, dev->iobase + MULTIQ3_CONTROL);
 		outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL);
 		outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase + MULTIQ3_ENC_CONTROL);
@@ -233,7 +231,7 @@ static int multiq3_attach(struct comedi_
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], MULTIQ3_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_6527.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_6527.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_6527.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_6527.c	2014-09-28 17:29:07.000000000 -0400
@@ -90,7 +90,6 @@ static const struct ni6527_board ni6527_
 };
 
 struct ni6527_private {
-	void __iomem *mmio_base;
 	unsigned int filter_interval;
 	unsigned int filter_enable;
 };
@@ -99,14 +98,15 @@ static void ni6527_set_filter_interval(s
 				       unsigned int val)
 {
 	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
 
 	if (val != devpriv->filter_interval) {
-		writeb(val & 0xff, mmio + NI6527_FILT_INTERVAL_REG(0));
-		writeb((val >> 8) & 0xff, mmio + NI6527_FILT_INTERVAL_REG(1));
-		writeb((val >> 16) & 0x0f, mmio + NI6527_FILT_INTERVAL_REG(2));
+		writeb(val & 0xff, dev->mmio + NI6527_FILT_INTERVAL_REG(0));
+		writeb((val >> 8) & 0xff,
+		       dev->mmio + NI6527_FILT_INTERVAL_REG(1));
+		writeb((val >> 16) & 0x0f,
+		       dev->mmio + NI6527_FILT_INTERVAL_REG(2));
 
-		writeb(NI6527_CLR_INTERVAL, mmio + NI6527_CLR_REG);
+		writeb(NI6527_CLR_INTERVAL, dev->mmio + NI6527_CLR_REG);
 
 		devpriv->filter_interval = val;
 	}
@@ -115,12 +115,9 @@ static void ni6527_set_filter_interval(s
 static void ni6527_set_filter_enable(struct comedi_device *dev,
 				     unsigned int val)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
-
-	writeb(val & 0xff, mmio + NI6527_FILT_ENA_REG(0));
-	writeb((val >> 8) & 0xff, mmio + NI6527_FILT_ENA_REG(1));
-	writeb((val >> 16) & 0xff, mmio + NI6527_FILT_ENA_REG(2));
+	writeb(val & 0xff, dev->mmio + NI6527_FILT_ENA_REG(0));
+	writeb((val >> 8) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(1));
+	writeb((val >> 16) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(2));
 }
 
 static int ni6527_di_insn_config(struct comedi_device *dev,
@@ -162,13 +159,11 @@ static int ni6527_di_insn_bits(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
 	unsigned int val;
 
-	val = readb(mmio + NI6527_DI_REG(0));
-	val |= (readb(mmio + NI6527_DI_REG(1)) << 8);
-	val |= (readb(mmio + NI6527_DI_REG(2)) << 16);
+	val = readb(dev->mmio + NI6527_DI_REG(0));
+	val |= (readb(dev->mmio + NI6527_DI_REG(1)) << 8);
+	val |= (readb(dev->mmio + NI6527_DI_REG(2)) << 16);
 
 	data[1] = val;
 
@@ -180,8 +175,6 @@ static int ni6527_do_insn_bits(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
 	unsigned int mask;
 
 	mask = comedi_dio_update_state(s, data);
@@ -190,11 +183,13 @@ static int ni6527_do_insn_bits(struct co
 		unsigned int val = s->state ^ 0xffffff;
 
 		if (mask & 0x0000ff)
-			writeb(val & 0xff, mmio + NI6527_DO_REG(0));
+			writeb(val & 0xff, dev->mmio + NI6527_DO_REG(0));
 		if (mask & 0x00ff00)
-			writeb((val >> 8) & 0xff, mmio + NI6527_DO_REG(1));
+			writeb((val >> 8) & 0xff,
+			       dev->mmio + NI6527_DO_REG(1));
 		if (mask & 0xff0000)
-			writeb((val >> 16) & 0xff, mmio + NI6527_DO_REG(2));
+			writeb((val >> 16) & 0xff,
+			       dev->mmio + NI6527_DO_REG(2));
 	}
 
 	data[1] = s->state;
@@ -205,12 +200,10 @@ static int ni6527_do_insn_bits(struct co
 static irqreturn_t ni6527_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct ni6527_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
-	void __iomem *mmio = devpriv->mmio_base;
 	unsigned int status;
 
-	status = readb(mmio + NI6527_STATUS_REG);
+	status = readb(dev->mmio + NI6527_STATUS_REG);
 	if (!(status & NI6527_STATUS_IRQ))
 		return IRQ_NONE;
 
@@ -220,7 +213,7 @@ static irqreturn_t ni6527_interrupt(int
 		comedi_event(dev, s);
 	}
 
-	writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
+	writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG);
 
 	return IRQ_HANDLED;
 }
@@ -270,11 +263,8 @@ static int ni6527_intr_cmdtest(struct co
 static int ni6527_intr_cmd(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
-
-	writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
-	writeb(NI6527_CTRL_ENABLE_IRQS, mmio + NI6527_CTRL_REG);
+	writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG);
+	writeb(NI6527_CTRL_ENABLE_IRQS, dev->mmio + NI6527_CTRL_REG);
 
 	return 0;
 }
@@ -282,10 +272,7 @@ static int ni6527_intr_cmd(struct comedi
 static int ni6527_intr_cancel(struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
-
-	writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
+	writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG);
 
 	return 0;
 }
@@ -299,21 +286,37 @@ static int ni6527_intr_insn_bits(struct
 }
 
 static void ni6527_set_edge_detection(struct comedi_device *dev,
+				      unsigned int mask,
 				      unsigned int rising,
 				      unsigned int falling)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
-
-	/* enable rising-edge detection channels */
-	writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0));
-	writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1));
-	writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2));
+	unsigned int i;
 
-	/* enable falling-edge detection channels */
-	writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0));
-	writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1));
-	writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2));
+	rising &= mask;
+	falling &= mask;
+	for (i = 0; i < 2; i++) {
+		if (mask & 0xff) {
+			if (~mask & 0xff) {
+				/* preserve rising-edge detection channels */
+				rising |= readb(dev->mmio +
+						NI6527_RISING_EDGE_REG(i)) &
+					  (~mask & 0xff);
+				/* preserve falling-edge detection channels */
+				falling |= readb(dev->mmio +
+						 NI6527_FALLING_EDGE_REG(i)) &
+					   (~mask & 0xff);
+			}
+			/* update rising-edge detection channels */
+			writeb(rising & 0xff,
+			       dev->mmio + NI6527_RISING_EDGE_REG(i));
+			/* update falling-edge detection channels */
+			writeb(falling & 0xff,
+			       dev->mmio + NI6527_FALLING_EDGE_REG(i));
+		}
+		rising >>= 8;
+		falling >>= 8;
+		mask >>= 8;
+	}
 }
 
 static int ni6527_intr_insn_config(struct comedi_device *dev,
@@ -321,12 +324,45 @@ static int ni6527_intr_insn_config(struc
 				   struct comedi_insn *insn,
 				   unsigned int *data)
 {
+	unsigned int mask = 0xffffffff;
+	unsigned int rising, falling, shift;
+
 	switch (data[0]) {
 	case INSN_CONFIG_CHANGE_NOTIFY:
 		/* check_insn_config_length() does not check this instruction */
 		if (insn->n != 3)
 			return -EINVAL;
-		ni6527_set_edge_detection(dev, data[1], data[2]);
+		rising = data[1];
+		falling = data[2];
+		ni6527_set_edge_detection(dev, mask, rising, falling);
+		break;
+	case INSN_CONFIG_DIGITAL_TRIG:
+		/* check trigger number */
+		if (data[1] != 0)
+			return -EINVAL;
+		/* check digital trigger operation */
+		switch (data[2]) {
+		case COMEDI_DIGITAL_TRIG_DISABLE:
+			rising = 0;
+			falling = 0;
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+			/* check shift amount */
+			shift = data[3];
+			if (shift >= s->n_chan) {
+				mask = 0;
+				rising = 0;
+				falling = 0;
+			} else {
+				mask <<= shift;
+				rising = data[4] << shift;
+				falling = data[5] << shift;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+		ni6527_set_edge_detection(dev, mask, rising, falling);
 		break;
 	default:
 		return -EINVAL;
@@ -337,15 +373,15 @@ static int ni6527_intr_insn_config(struc
 
 static void ni6527_reset(struct comedi_device *dev)
 {
-	struct ni6527_private *devpriv = dev->private;
-	void __iomem *mmio = devpriv->mmio_base;
-
 	/* disable deglitch filters on all channels */
 	ni6527_set_filter_enable(dev, 0);
 
+	/* disable edge detection */
+	ni6527_set_edge_detection(dev, 0xffffffff, 0, 0);
+
 	writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT,
-	       mmio + NI6527_CLR_REG);
-	writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
+	       dev->mmio + NI6527_CLR_REG);
+	writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG);
 }
 
 static int ni6527_auto_attach(struct comedi_device *dev,
@@ -372,12 +408,12 @@ static int ni6527_auto_attach(struct com
 	if (ret)
 		return ret;
 
-	devpriv->mmio_base = pci_ioremap_bar(pcidev, 1);
-	if (!devpriv->mmio_base)
+	dev->mmio = pci_ioremap_bar(pcidev, 1);
+	if (!dev->mmio)
 		return -ENOMEM;
 
 	/* make sure this is actually a 6527 device */
-	if (readb(devpriv->mmio_base + NI6527_ID_REG) != 0x27)
+	if (readb(dev->mmio + NI6527_ID_REG) != 0x27)
 		return -ENODEV;
 
 	ni6527_reset(dev);
@@ -434,12 +470,12 @@ static int ni6527_auto_attach(struct com
 
 static void ni6527_detach(struct comedi_device *dev)
 {
-	struct ni6527_private *devpriv = dev->private;
-
-	if (devpriv && devpriv->mmio_base)
+	if (dev->mmio)
 		ni6527_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_65xx.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_65xx.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_65xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_65xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,46 +1,73 @@
 /*
-    comedi/drivers/ni_6514.c
-    driver for National Instruments PCI-6514
-
-    Copyright (C) 2006 Jon Grierson <jd@renko.co.uk>
-    Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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.
+ * ni_65xx.c
+ * Comedi driver for National Instruments PCI-65xx static dio boards
+ *
+ * Copyright (C) 2006 Jon Grierson <jd@renko.co.uk>
+ * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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.
+ */
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
 /*
-Driver: ni_65xx
-Description: National Instruments 65xx static dio boards
-Author: Jon Grierson <jd@renko.co.uk>,
-	Frank Mori Hess <fmhess@users.sourceforge.net>
-Status: testing
-Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510,
-  PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514,
-  PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519,
-  PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528
-Updated: Wed Oct 18 08:59:11 EDT 2006
-
-Based on the PCI-6527 driver by ds.
-The interrupt subdevice (subdevice 3) is probably broken for all boards
-except maybe the 6514.
-
-*/
+ * Driver: ni_65xx
+ * Description: National Instruments 65xx static dio boards
+ * Author: Jon Grierson <jd@renko.co.uk>,
+ *	   Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Status: testing
+ * Devices: (National Instruments) PCI-6509 [ni_65xx]
+ *	    (National Instruments) PXI-6509 [ni_65xx]
+ *	    (National Instruments) PCI-6510 [ni_65xx]
+ *	    (National Instruments) PCI-6511 [ni_65xx]
+ *	    (National Instruments) PXI-6511 [ni_65xx]
+ *	    (National Instruments) PCI-6512 [ni_65xx]
+ *	    (National Instruments) PXI-6512 [ni_65xx]
+ *	    (National Instruments) PCI-6513 [ni_65xx]
+ *	    (National Instruments) PXI-6513 [ni_65xx]
+ *	    (National Instruments) PCI-6514 [ni_65xx]
+ *	    (National Instruments) PXI-6514 [ni_65xx]
+ *	    (National Instruments) PCI-6515 [ni_65xx]
+ *	    (National Instruments) PXI-6515 [ni_65xx]
+ *	    (National Instruments) PCI-6516 [ni_65xx]
+ *	    (National Instruments) PCI-6517 [ni_65xx]
+ *	    (National Instruments) PCI-6518 [ni_65xx]
+ *	    (National Instruments) PCI-6519 [ni_65xx]
+ *	    (National Instruments) PCI-6520 [ni_65xx]
+ *	    (National Instruments) PCI-6521 [ni_65xx]
+ *	    (National Instruments) PXI-6521 [ni_65xx]
+ *	    (National Instruments) PCI-6528 [ni_65xx]
+ *	    (National Instruments) PXI-6528 [ni_65xx]
+ * Updated: Mon, 21 Jul 2014 12:49:58 +0000
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ *
+ * Based on the PCI-6527 driver by ds.
+ * The interrupt subdevice (subdevice 3) is probably broken for all
+ * boards except maybe the 6514.
+ *
+ * This driver previously inverted the outputs on PCI-6513 through to
+ * PCI-6519 and on PXI-6513 through to PXI-6515.  It no longer inverts
+ * outputs on those cards by default as it didn't make much sense.  If
+ * you require the outputs to be inverted on those cards for legacy
+ * reasons, set the module parameter "legacy_invert_outputs=true" when
+ * loading the module, or set "ni_65xx.legacy_invert_outputs=true" on
+ * the kernel command line if the driver is built in to the kernel.
+ */
 
 /*
-   Manuals (available from ftp://ftp.natinst.com/support/manuals)
-
-	370106b.pdf	6514 Register Level Programmer Manual
-
+ * Manuals (available from ftp://ftp.natinst.com/support/manuals)
+ *
+ *	370106b.pdf	6514 Register Level Programmer Manual
  */
 
 #include <linux/module.h>
@@ -50,59 +77,69 @@ except maybe the 6514.
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-#include "mite.h"
 
-#define NI6514_DIO_SIZE 4096
-#define NI6514_MITE_SIZE 4096
-
-#define NI_65XX_MAX_NUM_PORTS 12
-static const unsigned ni_65xx_channels_per_port = 8;
-static const unsigned ni_65xx_port_offset = 0x10;
-
-static inline unsigned Port_Data(unsigned port)
-{
-	return 0x40 + port * ni_65xx_port_offset;
-}
-
-static inline unsigned Port_Select(unsigned port)
-{
-	return 0x41 + port * ni_65xx_port_offset;
-}
-
-static inline unsigned Rising_Edge_Detection_Enable(unsigned port)
-{
-	return 0x42 + port * ni_65xx_port_offset;
-}
-
-static inline unsigned Falling_Edge_Detection_Enable(unsigned port)
-{
-	return 0x43 + port * ni_65xx_port_offset;
-}
-
-static inline unsigned Filter_Enable(unsigned port)
-{
-	return 0x44 + port * ni_65xx_port_offset;
-}
-
-#define ID_Register				0x00
-
-#define Clear_Register				0x01
-#define ClrEdge				0x08
-#define ClrOverflow			0x04
+/*
+ * PCI BAR1 Register Map
+ */
 
-#define Filter_Interval			0x08
+/* Non-recurring Registers (8-bit except where noted) */
+#define NI_65XX_ID_REG			0x00
+#define NI_65XX_CLR_REG			0x01
+#define NI_65XX_CLR_WDOG_INT		(1 << 6)
+#define NI_65XX_CLR_WDOG_PING		(1 << 5)
+#define NI_65XX_CLR_WDOG_EXP		(1 << 4)
+#define NI_65XX_CLR_EDGE_INT		(1 << 3)
+#define NI_65XX_CLR_OVERFLOW_INT	(1 << 2)
+#define NI_65XX_STATUS_REG		0x02
+#define NI_65XX_STATUS_WDOG_INT		(1 << 5)
+#define NI_65XX_STATUS_FALL_EDGE	(1 << 4)
+#define NI_65XX_STATUS_RISE_EDGE	(1 << 3)
+#define NI_65XX_STATUS_INT		(1 << 2)
+#define NI_65XX_STATUS_OVERFLOW_INT	(1 << 1)
+#define NI_65XX_STATUS_EDGE_INT		(1 << 0)
+#define NI_65XX_CTRL_REG		0x03
+#define NI_65XX_CTRL_WDOG_ENA		(1 << 5)
+#define NI_65XX_CTRL_FALL_EDGE_ENA	(1 << 4)
+#define NI_65XX_CTRL_RISE_EDGE_ENA	(1 << 3)
+#define NI_65XX_CTRL_INT_ENA		(1 << 2)
+#define NI_65XX_CTRL_OVERFLOW_ENA	(1 << 1)
+#define NI_65XX_CTRL_EDGE_ENA		(1 << 0)
+#define NI_65XX_REV_REG			0x04 /* 32-bit */
+#define NI_65XX_FILTER_REG		0x08 /* 32-bit */
+#define NI_65XX_RTSI_ROUTE_REG		0x0c /* 16-bit */
+#define NI_65XX_RTSI_EDGE_REG		0x0e /* 16-bit */
+#define NI_65XX_RTSI_WDOG_REG		0x10 /* 16-bit */
+#define NI_65XX_RTSI_TRIG_REG		0x12 /* 16-bit */
+#define NI_65XX_AUTO_CLK_SEL_REG	0x14 /* PXI-6528 only */
+#define NI_65XX_AUTO_CLK_SEL_STATUS	(1 << 1)
+#define NI_65XX_AUTO_CLK_SEL_DISABLE	(1 << 0)
+#define NI_65XX_WDOG_CTRL_REG		0x15
+#define NI_65XX_WDOG_CTRL_ENA		(1 << 0)
+#define NI_65XX_RTSI_CFG_REG		0x16
+#define NI_65XX_RTSI_CFG_RISE_SENSE	(1 << 2)
+#define NI_65XX_RTSI_CFG_FALL_SENSE	(1 << 1)
+#define NI_65XX_RTSI_CFG_SYNC_DETECT	(1 << 0)
+#define NI_65XX_WDOG_STATUS_REG		0x17
+#define NI_65XX_WDOG_STATUS_EXP		(1 << 0)
+#define NI_65XX_WDOG_INTERVAL_REG	0x18 /* 32-bit */
 
-#define Change_Status				0x02
-#define MasterInterruptStatus		0x04
-#define Overflow			0x02
-#define EdgeStatus			0x01
+/* Recurring port registers (8-bit) */
+#define NI_65XX_PORT(x)			((x) * 0x10)
+#define NI_65XX_IO_DATA_REG(x)		(0x40 + NI_65XX_PORT(x))
+#define NI_65XX_IO_SEL_REG(x)		(0x41 + NI_65XX_PORT(x))
+#define NI_65XX_IO_SEL_OUTPUT		(0 << 0)
+#define NI_65XX_IO_SEL_INPUT		(1 << 0)
+#define NI_65XX_RISE_EDGE_ENA_REG(x)	(0x42 + NI_65XX_PORT(x))
+#define NI_65XX_FALL_EDGE_ENA_REG(x)	(0x43 + NI_65XX_PORT(x))
+#define NI_65XX_FILTER_ENA(x)		(0x44 + NI_65XX_PORT(x))
+#define NI_65XX_WDOG_HIZ_REG(x)		(0x46 + NI_65XX_PORT(x))
+#define NI_65XX_WDOG_ENA(x)		(0x47 + NI_65XX_PORT(x))
+#define NI_65XX_WDOG_HI_LO_REG(x)	(0x48 + NI_65XX_PORT(x))
+#define NI_65XX_RTSI_ENA(x)		(0x49 + NI_65XX_PORT(x))
 
-#define Master_Interrupt_Control		0x03
-#define FallingEdgeIntEnable		0x10
-#define RisingEdgeIntEnable		0x08
-#define MasterInterruptEnable		0x04
-#define OverflowIntEnable		0x02
-#define EdgeIntEnable			0x01
+#define NI_65XX_PORT_TO_CHAN(x)		((x) * 8)
+#define NI_65XX_CHAN_TO_PORT(x)		((x) / 8)
+#define NI_65XX_CHAN_TO_MASK(x)		(1 << ((x) % 8))
 
 enum ni_65xx_boardid {
 	BOARD_PCI6509,
@@ -134,7 +171,7 @@ struct ni_65xx_board {
 	unsigned num_dio_ports;
 	unsigned num_di_ports;
 	unsigned num_do_ports;
-	unsigned invert_outputs:1;
+	unsigned legacy_invert:1;
 };
 
 static const struct ni_65xx_board ni_65xx_boards[] = {
@@ -169,58 +206,58 @@ static const struct ni_65xx_board ni_65x
 	[BOARD_PCI6513] = {
 		.name		= "pci-6513",
 		.num_do_ports	= 8,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PXI6513] = {
 		.name		= "pxi-6513",
 		.num_do_ports	= 8,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6514] = {
 		.name		= "pci-6514",
 		.num_di_ports	= 4,
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PXI6514] = {
 		.name		= "pxi-6514",
 		.num_di_ports	= 4,
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6515] = {
 		.name		= "pci-6515",
 		.num_di_ports	= 4,
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PXI6515] = {
 		.name		= "pxi-6515",
 		.num_di_ports	= 4,
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6516] = {
 		.name		= "pci-6516",
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6517] = {
 		.name		= "pci-6517",
 		.num_do_ports	= 4,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6518] = {
 		.name		= "pci-6518",
 		.num_di_ports	= 2,
 		.num_do_ports	= 2,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6519] = {
 		.name		= "pci-6519",
 		.num_di_ports	= 2,
 		.num_do_ports	= 2,
-		.invert_outputs	= 1,
+		.legacy_invert	= 1,
 	},
 	[BOARD_PCI6520] = {
 		.name		= "pci-6520",
@@ -249,135 +286,174 @@ static const struct ni_65xx_board ni_65x
 	},
 };
 
-static inline unsigned ni_65xx_port_by_channel(unsigned channel)
-{
-	return channel / ni_65xx_channels_per_port;
-}
+static bool ni_65xx_legacy_invert_outputs;
+module_param_named(legacy_invert_outputs, ni_65xx_legacy_invert_outputs,
+		   bool, 0444);
+MODULE_PARM_DESC(legacy_invert_outputs,
+		 "invert outputs of PCI/PXI-6513/6514/6515/6516/6517/6518/6519 for compatibility with old user code");
 
-static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board
-					       *board)
+static unsigned int ni_65xx_num_ports(struct comedi_device *dev)
 {
+	const struct ni_65xx_board *board = comedi_board(dev);
+
 	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
 }
 
-struct ni_65xx_private {
-	struct mite_struct *mite;
-	unsigned int filter_interval;
-	unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS];
-	unsigned short output_bits[NI_65XX_MAX_NUM_PORTS];
-	unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
-};
+static void ni_65xx_disable_input_filters(struct comedi_device *dev)
+{
+	unsigned int num_ports = ni_65xx_num_ports(dev);
+	int i;
 
-struct ni_65xx_subdevice_private {
-	unsigned base_port;
-};
+	/* disable input filtering on all ports */
+	for (i = 0; i < num_ports; ++i)
+		writeb(0x00, dev->mmio + NI_65XX_FILTER_ENA(i));
 
-static inline struct ni_65xx_subdevice_private *sprivate(struct comedi_subdevice
-							 *subdev)
-{
-	return subdev->private;
+	/* set filter interval to 0 (32bit reg) */
+	writel(0x00000000, dev->mmio + NI_65XX_FILTER_REG);
 }
 
-static int ni_65xx_config_filter(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+/* updates edge detection for base_chan to base_chan+31 */
+static void ni_65xx_update_edge_detection(struct comedi_device *dev,
+					  unsigned int base_chan,
+					  unsigned int rising,
+					  unsigned int falling)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-	const unsigned chan = CR_CHAN(insn->chanspec);
-	const unsigned port =
-	    sprivate(s)->base_port + ni_65xx_port_by_channel(chan);
+	unsigned int num_ports = ni_65xx_num_ports(dev);
+	unsigned int port;
 
-	if (data[0] != INSN_CONFIG_FILTER)
-		return -EINVAL;
-	if (data[1]) {
-		static const unsigned filter_resolution_ns = 200;
-		static const unsigned max_filter_interval = 0xfffff;
-		unsigned interval =
-		    (data[1] +
-		     (filter_resolution_ns / 2)) / filter_resolution_ns;
-		if (interval > max_filter_interval)
-			interval = max_filter_interval;
-		data[1] = interval * filter_resolution_ns;
+	if (base_chan >= NI_65XX_PORT_TO_CHAN(num_ports))
+		return;
 
-		if (interval != devpriv->filter_interval) {
-			writeb(interval,
-			       devpriv->mite->daq_io_addr +
-			       Filter_Interval);
-			devpriv->filter_interval = interval;
-		}
+	for (port = NI_65XX_CHAN_TO_PORT(base_chan); port < num_ports; port++) {
+		int bitshift = (int)(NI_65XX_PORT_TO_CHAN(port) - base_chan);
+		unsigned int port_mask, port_rising, port_falling;
 
-		devpriv->filter_enable[port] |=
-		    1 << (chan % ni_65xx_channels_per_port);
-	} else {
-		devpriv->filter_enable[port] &=
-		    ~(1 << (chan % ni_65xx_channels_per_port));
-	}
+		if (bitshift >= 32)
+			break;
 
-	writeb(devpriv->filter_enable[port],
-	       devpriv->mite->daq_io_addr + Filter_Enable(port));
+		if (bitshift >= 0) {
+			port_mask = ~0U >> bitshift;
+			port_rising = rising >> bitshift;
+			port_falling = falling >> bitshift;
+		} else {
+			port_mask = ~0U << -bitshift;
+			port_rising = rising << -bitshift;
+			port_falling = falling << -bitshift;
+		}
+		if (port_mask & 0xff) {
+			if (~port_mask & 0xff) {
+				port_rising |=
+				    readb(dev->mmio +
+					  NI_65XX_RISE_EDGE_ENA_REG(port)) &
+				    ~port_mask;
+				port_falling |=
+				    readb(dev->mmio +
+					  NI_65XX_FALL_EDGE_ENA_REG(port)) &
+				    ~port_mask;
+			}
+			writeb(port_rising & 0xff,
+			       dev->mmio + NI_65XX_RISE_EDGE_ENA_REG(port));
+			writeb(port_falling & 0xff,
+			       dev->mmio + NI_65XX_FALL_EDGE_ENA_REG(port));
+		}
+	}
+}
 
-	return 2;
+static void ni_65xx_disable_edge_detection(struct comedi_device *dev)
+{
+	/* clear edge detection for channels 0 to 31 */
+	ni_65xx_update_edge_detection(dev, 0, 0, 0);
+	/* clear edge detection for channels 32 to 63 */
+	ni_65xx_update_edge_detection(dev, 32, 0, 0);
+	/* clear edge detection for channels 64 to 95 */
+	ni_65xx_update_edge_detection(dev, 64, 0, 0);
 }
 
 static int ni_65xx_dio_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-	unsigned port;
+	unsigned long base_port = (unsigned long)s->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int chan_mask = NI_65XX_CHAN_TO_MASK(chan);
+	unsigned port = base_port + NI_65XX_CHAN_TO_PORT(chan);
+	unsigned int interval;
+	unsigned int val;
 
-	if (insn->n < 1)
-		return -EINVAL;
-	port = sprivate(s)->base_port +
-	    ni_65xx_port_by_channel(CR_CHAN(insn->chanspec));
 	switch (data[0]) {
 	case INSN_CONFIG_FILTER:
-		return ni_65xx_config_filter(dev, s, insn, data);
+		/*
+		 * The deglitch filter interval is specified in nanoseconds.
+		 * The hardware supports intervals in 200ns increments. Round
+		 * the user values up and return the actual interval.
+		 */
+		interval = (data[1] + 100) / 200;
+		if (interval > 0xfffff)
+			interval = 0xfffff;
+		data[1] = interval * 200;
+
+		/*
+		 * Enable/disable the channel for deglitch filtering. Note
+		 * that the filter interval is never set to '0'. This is done
+		 * because other channels might still be enabled for filtering.
+		 */
+		val = readb(dev->mmio + NI_65XX_FILTER_ENA(port));
+		if (interval) {
+			writel(interval, dev->mmio + NI_65XX_FILTER_REG);
+			val |= chan_mask;
+		} else {
+			val &= ~chan_mask;
+		}
+		writeb(val, dev->mmio + NI_65XX_FILTER_ENA(port));
 		break;
+
 	case INSN_CONFIG_DIO_OUTPUT:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		devpriv->dio_direction[port] = COMEDI_OUTPUT;
-		writeb(0, devpriv->mite->daq_io_addr + Port_Select(port));
-		return 1;
+		writeb(NI_65XX_IO_SEL_OUTPUT,
+		       dev->mmio + NI_65XX_IO_SEL_REG(port));
 		break;
+
 	case INSN_CONFIG_DIO_INPUT:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		devpriv->dio_direction[port] = COMEDI_INPUT;
-		writeb(1, devpriv->mite->daq_io_addr + Port_Select(port));
-		return 1;
+		writeb(NI_65XX_IO_SEL_INPUT,
+		       dev->mmio + NI_65XX_IO_SEL_REG(port));
 		break;
+
 	case INSN_CONFIG_DIO_QUERY:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		data[1] = devpriv->dio_direction[port];
-		return insn->n;
+		val = readb(dev->mmio + NI_65XX_IO_SEL_REG(port));
+		data[1] = (val == NI_65XX_IO_SEL_INPUT) ? COMEDI_INPUT
+							: COMEDI_OUTPUT;
 		break;
+
 	default:
-		break;
+		return -EINVAL;
 	}
-	return -EINVAL;
+
+	return insn->n;
 }
 
 static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	const struct ni_65xx_board *board = comedi_board(dev);
-	struct ni_65xx_private *devpriv = dev->private;
-	int base_bitfield_channel;
+	unsigned long base_port = (unsigned long)s->private;
+	unsigned int base_chan = CR_CHAN(insn->chanspec);
+	int last_port_offset = NI_65XX_CHAN_TO_PORT(s->n_chan - 1);
 	unsigned read_bits = 0;
-	int last_port_offset = ni_65xx_port_by_channel(s->n_chan - 1);
 	int port_offset;
 
-	base_bitfield_channel = CR_CHAN(insn->chanspec);
-	for (port_offset = ni_65xx_port_by_channel(base_bitfield_channel);
+	for (port_offset = NI_65XX_CHAN_TO_PORT(base_chan);
 	     port_offset <= last_port_offset; port_offset++) {
-		unsigned port = sprivate(s)->base_port + port_offset;
-		int base_port_channel = port_offset * ni_65xx_channels_per_port;
-		unsigned port_mask, port_data, port_read_bits;
-		int bitshift = base_port_channel - base_bitfield_channel;
+		unsigned port = base_port + port_offset;
+		int base_port_channel = NI_65XX_PORT_TO_CHAN(port_offset);
+		unsigned port_mask, port_data, bits;
+		int bitshift = base_port_channel - base_chan;
 
 		if (bitshift >= 32)
 			break;
@@ -392,32 +468,26 @@ static int ni_65xx_dio_insn_bits(struct
 		}
 		port_mask &= 0xff;
 		port_data &= 0xff;
+
+		/* update the outputs */
 		if (port_mask) {
-			unsigned bits;
-			devpriv->output_bits[port] &= ~port_mask;
-			devpriv->output_bits[port] |=
-			    port_data & port_mask;
-			bits = devpriv->output_bits[port];
-			if (board->invert_outputs)
-				bits = ~bits;
-			writeb(bits,
-			       devpriv->mite->daq_io_addr +
-			       Port_Data(port));
-		}
-		port_read_bits =
-		    readb(devpriv->mite->daq_io_addr + Port_Data(port));
-		if (s->type == COMEDI_SUBD_DO && board->invert_outputs) {
-			/* Outputs inverted, so invert value read back from
-			 * DO subdevice.  (Does not apply to boards with DIO
-			 * subdevice.) */
-			port_read_bits ^= 0xFF;
+			bits = readb(dev->mmio + NI_65XX_IO_DATA_REG(port));
+			bits ^= s->io_bits;	/* invert if necessary */
+			bits &= ~port_mask;
+			bits |= (port_data & port_mask);
+			bits ^= s->io_bits;	/* invert back */
+			writeb(bits, dev->mmio + NI_65XX_IO_DATA_REG(port));
 		}
+
+		/* read back the actual state */
+		bits = readb(dev->mmio + NI_65XX_IO_DATA_REG(port));
+		bits ^= s->io_bits;	/* invert if necessary */
 		if (bitshift > 0)
-			port_read_bits <<= bitshift;
+			bits <<= bitshift;
 		else
-			port_read_bits >>= -bitshift;
+			bits >>= -bitshift;
 
-		read_bits |= port_read_bits;
+		read_bits |= bits;
 	}
 	data[1] = read_bits;
 	return insn->n;
@@ -426,18 +496,17 @@ static int ni_65xx_dio_insn_bits(struct
 static irqreturn_t ni_65xx_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct ni_65xx_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned int status;
 
-	status = readb(devpriv->mite->daq_io_addr + Change_Status);
-	if ((status & MasterInterruptStatus) == 0)
+	status = readb(dev->mmio + NI_65XX_STATUS_REG);
+	if ((status & NI_65XX_STATUS_INT) == 0)
 		return IRQ_NONE;
-	if ((status & EdgeStatus) == 0)
+	if ((status & NI_65XX_STATUS_EDGE_INT) == 0)
 		return IRQ_NONE;
 
-	writeb(ClrEdge | ClrOverflow,
-	       devpriv->mite->daq_io_addr + Clear_Register);
+	writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT,
+	       dev->mmio + NI_65XX_CLR_REG);
 
 	comedi_buf_put(s, 0);
 	s->async->events |= COMEDI_CB_EOS;
@@ -490,13 +559,11 @@ static int ni_65xx_intr_cmdtest(struct c
 static int ni_65xx_intr_cmd(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-
-	writeb(ClrEdge | ClrOverflow,
-	       devpriv->mite->daq_io_addr + Clear_Register);
-	writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
-	       MasterInterruptEnable | EdgeIntEnable,
-	       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+	writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT,
+	       dev->mmio + NI_65XX_CLR_REG);
+	writeb(NI_65XX_CTRL_FALL_EDGE_ENA | NI_65XX_CTRL_RISE_EDGE_ENA |
+	       NI_65XX_CTRL_INT_ENA | NI_65XX_CTRL_EDGE_ENA,
+	       dev->mmio + NI_65XX_CTRL_REG);
 
 	return 0;
 }
@@ -504,16 +571,15 @@ static int ni_65xx_intr_cmd(struct comed
 static int ni_65xx_intr_cancel(struct comedi_device *dev,
 			       struct comedi_subdevice *s)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-
-	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+	writeb(0x00, dev->mmio + NI_65XX_CTRL_REG);
 
 	return 0;
 }
 
 static int ni_65xx_intr_insn_bits(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	data[1] = 0;
 	return insn->n;
@@ -524,40 +590,68 @@ static int ni_65xx_intr_insn_config(stru
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
-	struct ni_65xx_private *devpriv = dev->private;
+	switch (data[0]) {
+	case INSN_CONFIG_CHANGE_NOTIFY:
+		/* add instruction to check_insn_config_length() */
+		if (insn->n != 3)
+			return -EINVAL;
 
-	if (insn->n < 1)
-		return -EINVAL;
-	if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
+		/* update edge detection for channels 0 to 31 */
+		ni_65xx_update_edge_detection(dev, 0, data[1], data[2]);
+		/* clear edge detection for channels 32 to 63 */
+		ni_65xx_update_edge_detection(dev, 32, 0, 0);
+		/* clear edge detection for channels 64 to 95 */
+		ni_65xx_update_edge_detection(dev, 64, 0, 0);
+		break;
+	case INSN_CONFIG_DIGITAL_TRIG:
+		/* check trigger number */
+		if (data[1] != 0)
+			return -EINVAL;
+		/* check digital trigger operation */
+		switch (data[2]) {
+		case COMEDI_DIGITAL_TRIG_DISABLE:
+			ni_65xx_disable_edge_detection(dev);
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+			/*
+			 * update edge detection for channels data[3]
+			 * to (data[3] + 31)
+			 */
+			ni_65xx_update_edge_detection(dev, data[3],
+						      data[4], data[5]);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
 		return -EINVAL;
+	}
 
-	writeb(data[1],
-	       devpriv->mite->daq_io_addr +
-	       Rising_Edge_Detection_Enable(0));
-	writeb(data[1] >> 8,
-	       devpriv->mite->daq_io_addr +
-	       Rising_Edge_Detection_Enable(0x10));
-	writeb(data[1] >> 16,
-	       devpriv->mite->daq_io_addr +
-	       Rising_Edge_Detection_Enable(0x20));
-	writeb(data[1] >> 24,
-	       devpriv->mite->daq_io_addr +
-	       Rising_Edge_Detection_Enable(0x30));
+	return insn->n;
+}
 
-	writeb(data[2],
-	       devpriv->mite->daq_io_addr +
-	       Falling_Edge_Detection_Enable(0));
-	writeb(data[2] >> 8,
-	       devpriv->mite->daq_io_addr +
-	       Falling_Edge_Detection_Enable(0x10));
-	writeb(data[2] >> 16,
-	       devpriv->mite->daq_io_addr +
-	       Falling_Edge_Detection_Enable(0x20));
-	writeb(data[2] >> 24,
-	       devpriv->mite->daq_io_addr +
-	       Falling_Edge_Detection_Enable(0x30));
+/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+#define MITE_IODWBSR	0xc0	 /* IO Device Window Base Size Register */
+#define WENAB		(1 << 7) /* window enable */
 
-	return 2;
+static int ni_65xx_mite_init(struct pci_dev *pcidev)
+{
+	void __iomem *mite_base;
+	u32 main_phys_addr;
+
+	/* ioremap the MITE registers (BAR 0) temporarily */
+	mite_base = pci_ioremap_bar(pcidev, 0);
+	if (!mite_base)
+		return -ENOMEM;
+
+	/* set data window to main registers (BAR 1) */
+	main_phys_addr = pci_resource_start(pcidev, 1);
+	writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR);
+
+	/* finished with MITE registers */
+	iounmap(mite_base);
+	return 0;
 }
 
 static int ni_65xx_auto_attach(struct comedi_device *dev,
@@ -565,8 +659,6 @@ static int ni_65xx_auto_attach(struct co
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct ni_65xx_board *board = NULL;
-	struct ni_65xx_private *devpriv;
-	struct ni_65xx_subdevice_private *spriv;
 	struct comedi_subdevice *s;
 	unsigned i;
 	int ret;
@@ -582,23 +674,27 @@ static int ni_65xx_auto_attach(struct co
 	if (ret)
 		return ret;
 
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
+	ret = ni_65xx_mite_init(pcidev);
+	if (ret)
+		return ret;
 
-	devpriv->mite = mite_alloc(pcidev);
-	if (!devpriv->mite)
+	dev->mmio = pci_ioremap_bar(pcidev, 1);
+	if (!dev->mmio)
 		return -ENOMEM;
 
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, "error setting up mite\n");
-		return ret;
+	writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT,
+	       dev->mmio + NI_65XX_CLR_REG);
+	writeb(0x00, dev->mmio + NI_65XX_CTRL_REG);
+
+	if (pcidev->irq) {
+		ret = request_irq(pcidev->irq, ni_65xx_interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
 	}
 
-	dev->irq = mite_irq(devpriv->mite);
 	dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
-	       readb(devpriv->mite->daq_io_addr + ID_Register));
+	       readb(dev->mmio + NI_65XX_ID_REG));
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
@@ -606,130 +702,111 @@ static int ni_65xx_auto_attach(struct co
 
 	s = &dev->subdevices[0];
 	if (board->num_di_ports) {
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE;
-		s->n_chan =
-		    board->num_di_ports * ni_65xx_channels_per_port;
-		s->range_table = &range_digital;
-		s->maxdata = 1;
-		s->insn_config = ni_65xx_dio_insn_config;
-		s->insn_bits = ni_65xx_dio_insn_bits;
-		spriv = comedi_alloc_spriv(s, sizeof(*spriv));
-		if (!spriv)
-			return -ENOMEM;
-		spriv->base_port = 0;
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE;
+		s->n_chan	= NI_65XX_PORT_TO_CHAN(board->num_di_ports);
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= ni_65xx_dio_insn_bits;
+		s->insn_config	= ni_65xx_dio_insn_config;
+
+		/* the input ports always start at port 0 */
+		s->private = (void *)0;
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
 
 	s = &dev->subdevices[1];
 	if (board->num_do_ports) {
-		s->type = COMEDI_SUBD_DO;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-		s->n_chan =
-		    board->num_do_ports * ni_65xx_channels_per_port;
-		s->range_table = &range_digital;
-		s->maxdata = 1;
-		s->insn_bits = ni_65xx_dio_insn_bits;
-		spriv = comedi_alloc_spriv(s, sizeof(*spriv));
-		if (!spriv)
-			return -ENOMEM;
-		spriv->base_port = board->num_di_ports;
+		s->type		= COMEDI_SUBD_DO;
+		s->subdev_flags	= SDF_WRITABLE;
+		s->n_chan	= NI_65XX_PORT_TO_CHAN(board->num_do_ports);
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= ni_65xx_dio_insn_bits;
+
+		/* the output ports always start after the input ports */
+		s->private = (void *)(unsigned long)board->num_di_ports;
+
+		/*
+		 * Use the io_bits to handle the inverted outputs.  Inverted
+		 * outputs are only supported if the "legacy_invert_outputs"
+		 * module parameter is set to "true".
+		 */
+		if (ni_65xx_legacy_invert_outputs && board->legacy_invert)
+			s->io_bits = 0xff;
+
+		/* reset all output ports to comedi '0' */
+		for (i = 0; i < board->num_do_ports; ++i) {
+			writeb(s->io_bits,	/* inverted if necessary */
+			       dev->mmio +
+			       NI_65XX_IO_DATA_REG(board->num_di_ports + i));
+		}
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
 
 	s = &dev->subdevices[2];
 	if (board->num_dio_ports) {
-		s->type = COMEDI_SUBD_DIO;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-		s->n_chan =
-		    board->num_dio_ports * ni_65xx_channels_per_port;
-		s->range_table = &range_digital;
-		s->maxdata = 1;
-		s->insn_config = ni_65xx_dio_insn_config;
-		s->insn_bits = ni_65xx_dio_insn_bits;
-		spriv = comedi_alloc_spriv(s, sizeof(*spriv));
-		if (!spriv)
-			return -ENOMEM;
-		spriv->base_port = 0;
+		s->type		= COMEDI_SUBD_DIO;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+		s->n_chan	= NI_65XX_PORT_TO_CHAN(board->num_dio_ports);
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= ni_65xx_dio_insn_bits;
+		s->insn_config	= ni_65xx_dio_insn_config;
+
+		/* the input/output ports always start at port 0 */
+		s->private = (void *)0;
+
+		/* configure all ports for input */
 		for (i = 0; i < board->num_dio_ports; ++i) {
-			/*  configure all ports for input */
-			writeb(0x1,
-			       devpriv->mite->daq_io_addr +
-			       Port_Select(i));
+			writeb(NI_65XX_IO_SEL_INPUT,
+			       dev->mmio + NI_65XX_IO_SEL_REG(i));
 		}
 	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
 
 	s = &dev->subdevices[3];
-	dev->read_subdev = s;
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-	s->n_chan = 1;
-	s->range_table = &range_unknown;
-	s->maxdata = 1;
-	s->len_chanlist	= 1;
-	s->do_cmdtest = ni_65xx_intr_cmdtest;
-	s->do_cmd = ni_65xx_intr_cmd;
-	s->cancel = ni_65xx_intr_cancel;
-	s->insn_bits = ni_65xx_intr_insn_bits;
-	s->insn_config = ni_65xx_intr_insn_config;
-
-	for (i = 0; i < ni_65xx_total_num_ports(board); ++i) {
-		writeb(0x00,
-		       devpriv->mite->daq_io_addr + Filter_Enable(i));
-		if (board->invert_outputs)
-			writeb(0x01,
-			       devpriv->mite->daq_io_addr + Port_Data(i));
-		else
-			writeb(0x00,
-			       devpriv->mite->daq_io_addr + Port_Data(i));
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 1;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= ni_65xx_intr_insn_bits;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= 1;
+		s->insn_config	= ni_65xx_intr_insn_config;
+		s->do_cmdtest	= ni_65xx_intr_cmdtest;
+		s->do_cmd	= ni_65xx_intr_cmd;
+		s->cancel	= ni_65xx_intr_cancel;
 	}
-	writeb(ClrEdge | ClrOverflow,
-	       devpriv->mite->daq_io_addr + Clear_Register);
-	writeb(0x00,
-	       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
-	/* Set filter interval to 0  (32bit reg) */
-	writeb(0x00000000, devpriv->mite->daq_io_addr + Filter_Interval);
-
-	ret = request_irq(dev->irq, ni_65xx_interrupt, IRQF_SHARED,
-			  "ni_65xx", dev);
-	if (ret < 0) {
-		dev->irq = 0;
-		dev_warn(dev->class_dev, "irq not available\n");
-	}
+	ni_65xx_disable_input_filters(dev);
+	ni_65xx_disable_edge_detection(dev);
 
 	return 0;
 }
 
 static void ni_65xx_detach(struct comedi_device *dev)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-
-	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
-		writeb(0x00,
-		       devpriv->mite->daq_io_addr +
-		       Master_Interrupt_Control);
+	if (dev->mmio) {
+		writeb(0x00, dev->mmio + NI_65XX_CTRL_REG);
+		iounmap(dev->mmio);
 	}
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (devpriv) {
-		if (devpriv->mite) {
-			mite_unsetup(devpriv->mite);
-			mite_free(devpriv->mite);
-		}
-	}
 	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni_65xx_driver = {
-	.driver_name = "ni_65xx",
-	.module = THIS_MODULE,
-	.auto_attach = ni_65xx_auto_attach,
-	.detach = ni_65xx_detach,
+	.driver_name	= "ni_65xx",
+	.module		= THIS_MODULE,
+	.auto_attach	= ni_65xx_auto_attach,
+	.detach		= ni_65xx_detach,
 };
 
 static int ni_65xx_pci_probe(struct pci_dev *dev,
@@ -774,5 +851,5 @@ static struct pci_driver ni_65xx_pci_dri
 module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for NI PCI-65xx static dio boards");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_660x.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_660x.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_660x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_660x.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
  *
  * Encoders work.  PulseGeneration (both single pulse and pulse train)
  * works.  Buffered commands work for input but not output.
- * 
+ *
  * References:
  * DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
  * DAQ 6601/6602 User Manual (NI 322137B-01)
@@ -161,6 +161,7 @@ enum ni_660x_register {
 static inline unsigned IOConfigReg(unsigned pfi_channel)
 {
 	unsigned reg = NI660X_IO_CFG_0_1 + pfi_channel / 2;
+
 	BUG_ON(reg > NI660X_IO_CFG_38_39);
 	return reg;
 }
@@ -310,10 +311,7 @@ enum clock_config_register_bits {
 /* ioconfigreg */
 static inline unsigned ioconfig_bitshift(unsigned pfi_channel)
 {
-	if (pfi_channel % 2)
-		return 0;
-	else
-		return 8;
+	return (pfi_channel % 2) ? 0 : 8;
 }
 
 static inline unsigned pfi_output_select_mask(unsigned pfi_channel)
@@ -589,17 +587,14 @@ static inline void ni_660x_write_registe
 					  unsigned chip, unsigned bits,
 					  enum ni_660x_register reg)
 {
-	struct ni_660x_private *devpriv = dev->private;
-	void __iomem *write_address =
-	    devpriv->mite->daq_io_addr + GPCT_OFFSET[chip] +
-	    registerData[reg].offset;
+	unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset;
 
 	switch (registerData[reg].size) {
 	case DATA_2B:
-		writew(bits, write_address);
+		writew(bits, dev->mmio + addr);
 		break;
 	case DATA_4B:
-		writel(bits, write_address);
+		writel(bits, dev->mmio + addr);
 		break;
 	default:
 		BUG();
@@ -611,18 +606,13 @@ static inline unsigned ni_660x_read_regi
 					     unsigned chip,
 					     enum ni_660x_register reg)
 {
-	struct ni_660x_private *devpriv = dev->private;
-	void __iomem *read_address =
-	    devpriv->mite->daq_io_addr + GPCT_OFFSET[chip] +
-	    registerData[reg].offset;
+	unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset;
 
 	switch (registerData[reg].size) {
 	case DATA_2B:
-		return readw(read_address);
-		break;
+		return readw(dev->mmio + addr);
 	case DATA_4B:
-		return readl(read_address);
-		break;
+		return readl(dev->mmio + addr);
 	default:
 		BUG();
 		break;
@@ -714,8 +704,8 @@ static int ni_660x_request_mite_channel(
 					 mite_ring(devpriv, counter));
 	if (mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev,
-			     "failed to reserve mite dma channel for counter.");
+		dev_err(dev->class_dev,
+			"failed to reserve mite dma channel for counter\n");
 		return -EBUSY;
 	}
 	mite_chan->dir = direction;
@@ -749,11 +739,11 @@ static int ni_660x_cmd(struct comedi_dev
 
 	retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT);
 	if (retval) {
-		comedi_error(dev,
-			     "no dma channel available for use by counter");
+		dev_err(dev->class_dev,
+			"no dma channel available for use by counter\n");
 		return retval;
 	}
-	ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
+	ni_tio_acknowledge(counter);
 
 	return ni_tio_cmd(dev, s);
 }
@@ -829,8 +819,7 @@ static int ni_660x_input_poll(struct com
 }
 
 static int ni_660x_buf_change(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      unsigned long new_size)
+			      struct comedi_subdevice *s)
 {
 	struct ni_660x_private *devpriv = dev->private;
 	struct ni_gpct *counter = s->private;
@@ -1083,11 +1072,9 @@ static int ni_660x_auto_attach(struct co
 	if (!devpriv->mite)
 		return -ENOMEM;
 
-	ret = mite_setup2(devpriv->mite, 1);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, "error setting up mite\n");
+	ret = mite_setup2(dev, devpriv->mite, true);
+	if (ret < 0)
 		return ret;
-	}
 
 	ret = ni_660x_alloc_mite_rings(dev);
 	if (ret < 0)
@@ -1126,9 +1113,8 @@ static int ni_660x_auto_attach(struct co
 		s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
 		if (i < ni_660x_num_counters(dev)) {
 			s->type = COMEDI_SUBD_COUNTER;
-			s->subdev_flags =
-			    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
-			    SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
+			s->subdev_flags = SDF_READABLE | SDF_WRITABLE |
+					  SDF_LSAMPL | SDF_CMD_READ;
 			s->n_chan = 3;
 			s->maxdata = 0xffffffff;
 			s->insn_read = ni_tio_insn_read;
@@ -1170,13 +1156,13 @@ static int ni_660x_auto_attach(struct co
 	for (i = 0; i < board->n_chips; ++i)
 		set_tio_counterswap(dev, i);
 
-	ret = request_irq(mite_irq(devpriv->mite), ni_660x_interrupt,
-			  IRQF_SHARED, "ni_660x", dev);
+	ret = request_irq(pcidev->irq, ni_660x_interrupt, IRQF_SHARED,
+			  dev->board_name, dev);
 	if (ret < 0) {
 		dev_warn(dev->class_dev, " irq not available\n");
 		return ret;
 	}
-	dev->irq = mite_irq(devpriv->mite);
+	dev->irq = pcidev->irq;
 	global_interrupt_config_bits = Global_Int_Enable_Bit;
 	if (board->n_chips > 1)
 		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
@@ -1195,12 +1181,11 @@ static void ni_660x_detach(struct comedi
 	if (devpriv) {
 		if (devpriv->counter_dev)
 			ni_gpct_device_destroy(devpriv->counter_dev);
-		if (devpriv->mite) {
-			ni_660x_free_mite_rings(dev);
-			mite_unsetup(devpriv->mite);
-			mite_free(devpriv->mite);
-		}
+		ni_660x_free_mite_rings(dev);
+		mite_detach(devpriv->mite);
 	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_670x.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_670x.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_670x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_670x.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,11 +39,10 @@ Commands are not supported.
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 
 #include "../comedidev.h"
 
-#include "mite.h"
-
 #define AO_VALUE_OFFSET			0x00
 #define	AO_CHAN_OFFSET			0x0c
 #define	AO_STATUS_OFFSET		0x10
@@ -82,8 +81,6 @@ static const struct ni_670x_board ni_670
 };
 
 struct ni_670x_private {
-
-	struct mite_struct *mite;
 	int boardtype;
 	int dio;
 	unsigned int ao_readback[32];
@@ -111,9 +108,9 @@ static int ni_670x_ao_winsn(struct comed
 	for (i = 0; i < insn->n; i++) {
 		/* First write in channel register which channel to use */
 		writel(((chan & 15) << 1) | ((chan & 16) >> 4),
-		       devpriv->mite->daq_io_addr + AO_CHAN_OFFSET);
+		       dev->mmio + AO_CHAN_OFFSET);
 		/* write channel value */
-		writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET);
+		writel(data[i], dev->mmio + AO_VALUE_OFFSET);
 		devpriv->ao_readback[chan] = data[i];
 	}
 
@@ -139,14 +136,10 @@ static int ni_670x_dio_insn_bits(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct ni_670x_private *devpriv = dev->private;
-	void __iomem *io_addr = devpriv->mite->daq_io_addr +
-					DIO_PORT0_DATA_OFFSET;
-
 	if (comedi_dio_update_state(s, data))
-		writel(s->state, io_addr);
+		writel(s->state, dev->mmio + DIO_PORT0_DATA_OFFSET);
 
-	data[1] = readl(io_addr);
+	data[1] = readl(dev->mmio + DIO_PORT0_DATA_OFFSET);
 
 	return insn->n;
 }
@@ -156,18 +149,40 @@ static int ni_670x_dio_insn_config(struc
 				   struct comedi_insn *insn,
 				   unsigned int *data)
 {
-	struct ni_670x_private *devpriv = dev->private;
 	int ret;
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 	if (ret)
 		return ret;
 
-	writel(s->io_bits, devpriv->mite->daq_io_addr + DIO_PORT0_DIR_OFFSET);
+	writel(s->io_bits, dev->mmio + DIO_PORT0_DIR_OFFSET);
 
 	return insn->n;
 }
 
+/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+#define MITE_IODWBSR	0xc0	 /* IO Device Window Base Size Register */
+#define WENAB		(1 << 7) /* window enable */
+
+static int ni_670x_mite_init(struct pci_dev *pcidev)
+{
+	void __iomem *mite_base;
+	u32 main_phys_addr;
+
+	/* ioremap the MITE registers (BAR 0) temporarily */
+	mite_base = pci_ioremap_bar(pcidev, 0);
+	if (!mite_base)
+		return -ENOMEM;
+
+	/* set data window to main registers (BAR 1) */
+	main_phys_addr = pci_resource_start(pcidev, 1);
+	writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR);
+
+	/* finished with MITE registers */
+	iounmap(mite_base);
+	return 0;
+}
+
 static int ni_670x_auto_attach(struct comedi_device *dev,
 			       unsigned long context)
 {
@@ -193,15 +208,13 @@ static int ni_670x_auto_attach(struct co
 	if (!devpriv)
 		return -ENOMEM;
 
-	devpriv->mite = mite_alloc(pcidev);
-	if (!devpriv->mite)
-		return -ENOMEM;
-
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, "error setting up mite\n");
+	ret = ni_670x_mite_init(pcidev);
+	if (ret)
 		return ret;
-	}
+
+	dev->mmio = pci_ioremap_bar(pcidev, 1);
+	if (!dev->mmio)
+		return -ENOMEM;
 
 	ret = comedi_alloc_subdevices(dev, 2);
 	if (ret)
@@ -242,16 +255,15 @@ static int ni_670x_auto_attach(struct co
 	s->insn_config = ni_670x_dio_insn_config;
 
 	/* Config of misc registers */
-	writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET);
+	writel(0x10, dev->mmio + MISC_CONTROL_OFFSET);
 	/* Config of ao registers */
-	writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET);
+	writel(0x00, dev->mmio + AO_CONTROL_OFFSET);
 
 	return 0;
 }
 
 static void ni_670x_detach(struct comedi_device *dev)
 {
-	struct ni_670x_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 
 	if (dev->n_subdevices) {
@@ -259,10 +271,8 @@ static void ni_670x_detach(struct comedi
 		if (s)
 			kfree(s->range_table_list);
 	}
-	if (devpriv && devpriv->mite) {
-		mite_unsetup(devpriv->mite);
-		mite_free(devpriv->mite);
-	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_at_a2150.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_at_a2150.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_at_a2150.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_at_a2150.c	2014-09-28 17:29:07.000000000 -0400
@@ -71,7 +71,6 @@ TRIG_WAKE_EOS
 #include "8253.h"
 #include "comedi_fc.h"
 
-#define A2150_SIZE           28
 #define A2150_DMA_BUFFER_SIZE	0xff00	/*  size in bytes of dma buffer */
 
 /* Registers and bits */
@@ -156,13 +155,6 @@ struct a2150_private {
 	int config_bits;	/*  config register bits */
 };
 
-static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-
-static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
-			    int flags);
-static int a2150_set_chanlist(struct comedi_device *dev,
-			      unsigned int start_channel,
-			      unsigned int num_channels);
 /* interrupt service routine */
 static irqreturn_t a2150_interrupt(int irq, void *d)
 {
@@ -179,7 +171,7 @@ static irqreturn_t a2150_interrupt(int i
 	static const int sample_size = sizeof(devpriv->dma_buffer[0]);
 
 	if (!dev->attached) {
-		comedi_error(dev, "premature interrupt");
+		dev_err(dev->class_dev, "premature interrupt\n");
 		return IRQ_HANDLED;
 	}
 	/*  initialize async here to make sure s is not NULL */
@@ -189,18 +181,19 @@ static irqreturn_t a2150_interrupt(int i
 	status = inw(dev->iobase + STATUS_REG);
 
 	if ((status & INTR_BIT) == 0) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		return IRQ_NONE;
 	}
 
 	if (status & OVFL_BIT) {
-		comedi_error(dev, "fifo overflow");
+		dev_err(dev->class_dev, "fifo overflow\n");
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
 	}
 
 	if ((status & DMA_TC_BIT) == 0) {
-		comedi_error(dev, "caught non-dma interrupt?  Aborting.");
+		dev_err(dev->class_dev,
+			"caught non-dma interrupt?  Aborting.\n");
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
 		return IRQ_HANDLED;
@@ -287,6 +280,117 @@ static int a2150_cancel(struct comedi_de
 	return 0;
 }
 
+/*
+ * sets bits in devpriv->clock_bits to nearest approximation of requested
+ * period, adjusts requested period to actual timing.
+ */
+static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
+			    unsigned int flags)
+{
+	const struct a2150_board *thisboard = comedi_board(dev);
+	struct a2150_private *devpriv = dev->private;
+	int lub, glb, temp;
+	int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
+	int i, j;
+
+	/*  initialize greatest lower and least upper bounds */
+	lub_divisor_shift = 3;
+	lub_index = 0;
+	lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
+	glb_divisor_shift = 0;
+	glb_index = thisboard->num_clocks - 1;
+	glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
+
+	/*  make sure period is in available range */
+	if (*period < glb)
+		*period = glb;
+	if (*period > lub)
+		*period = lub;
+
+	/*  we can multiply period by 1, 2, 4, or 8, using (1 << i) */
+	for (i = 0; i < 4; i++) {
+		/*  there are a maximum of 4 master clocks */
+		for (j = 0; j < thisboard->num_clocks; j++) {
+			/*  temp is the period in nanosec we are evaluating */
+			temp = thisboard->clock[j] * (1 << i);
+			/*  if it is the best match yet */
+			if (temp < lub && temp >= *period) {
+				lub_divisor_shift = i;
+				lub_index = j;
+				lub = temp;
+			}
+			if (temp > glb && temp <= *period) {
+				glb_divisor_shift = i;
+				glb_index = j;
+				glb = temp;
+			}
+		}
+	}
+	switch (flags & TRIG_ROUND_MASK) {
+	case TRIG_ROUND_NEAREST:
+	default:
+		/*  if least upper bound is better approximation */
+		if (lub - *period < *period - glb)
+			*period = lub;
+		else
+			*period = glb;
+		break;
+	case TRIG_ROUND_UP:
+		*period = lub;
+		break;
+	case TRIG_ROUND_DOWN:
+		*period = glb;
+		break;
+	}
+
+	/*  set clock bits for config register appropriately */
+	devpriv->config_bits &= ~CLOCK_MASK;
+	if (*period == lub) {
+		devpriv->config_bits |=
+		    CLOCK_SELECT_BITS(lub_index) |
+		    CLOCK_DIVISOR_BITS(lub_divisor_shift);
+	} else {
+		devpriv->config_bits |=
+		    CLOCK_SELECT_BITS(glb_index) |
+		    CLOCK_DIVISOR_BITS(glb_divisor_shift);
+	}
+
+	return 0;
+}
+
+static int a2150_set_chanlist(struct comedi_device *dev,
+			      unsigned int start_channel,
+			      unsigned int num_channels)
+{
+	struct a2150_private *devpriv = dev->private;
+
+	if (start_channel + num_channels > 4)
+		return -1;
+
+	devpriv->config_bits &= ~CHANNEL_MASK;
+
+	switch (num_channels) {
+	case 1:
+		devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
+		break;
+	case 2:
+		if (start_channel == 0)
+			devpriv->config_bits |= CHANNEL_BITS(0x2);
+		else if (start_channel == 2)
+			devpriv->config_bits |= CHANNEL_BITS(0x3);
+		else
+			return -1;
+		break;
+	case 4:
+		devpriv->config_bits |= CHANNEL_BITS(0x1);
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 static int a2150_ai_check_chanlist(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_cmd *cmd)
@@ -408,8 +512,8 @@ static int a2150_ai_cmd(struct comedi_de
 	unsigned int trigger_bits;
 
 	if (cmd->flags & TRIG_RT) {
-		comedi_error(dev,
-			     " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
+		dev_err(dev->class_dev,
+			"dma incompatible with hard real-time interrupt (TRIG_RT), aborting\n");
 		return -1;
 	}
 	/*  clear fifo and reset triggering circuitry */
@@ -490,7 +594,7 @@ static int a2150_ai_cmd(struct comedi_de
 		trigger_bits |= HW_TRIG_EN;
 	} else if (cmd->start_src == TRIG_OTHER) {
 		/*  XXX add support for level/slope start trigger using TRIG_OTHER */
-		comedi_error(dev, "you shouldn't see this?");
+		dev_err(dev->class_dev, "you shouldn't see this?\n");
 	}
 	/*  send trigger config bits */
 	outw(trigger_bits, dev->iobase + TRIGGER_REG);
@@ -574,123 +678,11 @@ static int a2150_ai_rinsn(struct comedi_
 	return n;
 }
 
-/*
- * sets bits in devpriv->clock_bits to nearest approximation of requested
- * period, adjusts requested period to actual timing.
- */
-static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
-			    int flags)
-{
-	const struct a2150_board *thisboard = comedi_board(dev);
-	struct a2150_private *devpriv = dev->private;
-	int lub, glb, temp;
-	int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
-	int i, j;
-
-	/*  initialize greatest lower and least upper bounds */
-	lub_divisor_shift = 3;
-	lub_index = 0;
-	lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
-	glb_divisor_shift = 0;
-	glb_index = thisboard->num_clocks - 1;
-	glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
-
-	/*  make sure period is in available range */
-	if (*period < glb)
-		*period = glb;
-	if (*period > lub)
-		*period = lub;
-
-	/*  we can multiply period by 1, 2, 4, or 8, using (1 << i) */
-	for (i = 0; i < 4; i++) {
-		/*  there are a maximum of 4 master clocks */
-		for (j = 0; j < thisboard->num_clocks; j++) {
-			/*  temp is the period in nanosec we are evaluating */
-			temp = thisboard->clock[j] * (1 << i);
-			/*  if it is the best match yet */
-			if (temp < lub && temp >= *period) {
-				lub_divisor_shift = i;
-				lub_index = j;
-				lub = temp;
-			}
-			if (temp > glb && temp <= *period) {
-				glb_divisor_shift = i;
-				glb_index = j;
-				glb = temp;
-			}
-		}
-	}
-	flags &= TRIG_ROUND_MASK;
-	switch (flags) {
-	case TRIG_ROUND_NEAREST:
-	default:
-		/*  if least upper bound is better approximation */
-		if (lub - *period < *period - glb)
-			*period = lub;
-		else
-			*period = glb;
-		break;
-	case TRIG_ROUND_UP:
-		*period = lub;
-		break;
-	case TRIG_ROUND_DOWN:
-		*period = glb;
-		break;
-	}
-
-	/*  set clock bits for config register appropriately */
-	devpriv->config_bits &= ~CLOCK_MASK;
-	if (*period == lub) {
-		devpriv->config_bits |=
-		    CLOCK_SELECT_BITS(lub_index) |
-		    CLOCK_DIVISOR_BITS(lub_divisor_shift);
-	} else {
-		devpriv->config_bits |=
-		    CLOCK_SELECT_BITS(glb_index) |
-		    CLOCK_DIVISOR_BITS(glb_divisor_shift);
-	}
-
-	return 0;
-}
-
-static int a2150_set_chanlist(struct comedi_device *dev,
-			      unsigned int start_channel,
-			      unsigned int num_channels)
-{
-	struct a2150_private *devpriv = dev->private;
-
-	if (start_channel + num_channels > 4)
-		return -1;
-
-	devpriv->config_bits &= ~CHANNEL_MASK;
-
-	switch (num_channels) {
-	case 1:
-		devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
-		break;
-	case 2:
-		if (start_channel == 0)
-			devpriv->config_bits |= CHANNEL_BITS(0x2);
-		else if (start_channel == 2)
-			devpriv->config_bits |= CHANNEL_BITS(0x3);
-		else
-			return -1;
-		break;
-	case 4:
-		devpriv->config_bits |= CHANNEL_BITS(0x1);
-		break;
-	default:
-		return -1;
-		break;
-	}
-
-	return 0;
-}
-
 /* probes board type, returns offset */
 static int a2150_probe(struct comedi_device *dev)
 {
 	int status = inw(dev->iobase + STATUS_REG);
+
 	return ID_BITS(status);
 }
 
@@ -709,7 +701,7 @@ static int a2150_attach(struct comedi_de
 	if (!devpriv)
 		return -ENOMEM;
 
-	ret = comedi_request_region(dev, it->options[0], A2150_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x1c);
 	if (ret)
 		return ret;
 
@@ -784,8 +776,8 @@ static int a2150_attach(struct comedi_de
 		udelay(1000);
 	}
 	if (i == timeout) {
-		printk
-		    (" timed out waiting for offset calibration to complete\n");
+		dev_err(dev->class_dev,
+			"timed out waiting for offset calibration to complete\n");
 		return -ETIME;
 	}
 	devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_atmio16d.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_atmio16d.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_atmio16d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_atmio16d.c	2014-09-28 17:29:07.000000000 -0400
@@ -94,8 +94,6 @@ Devices: [National Instruments] AT-MIO-1
 #define CLOCK_10_KHZ	0x8D25
 #define CLOCK_1_KHZ		0x8E25
 #define CLOCK_100_HZ	0x8F25
-/* Other miscellaneous defines */
-#define ATMIO16D_SIZE	32	/* bus address range */
 
 struct atmio16_board_t {
 
@@ -335,12 +333,9 @@ static int atmio16d_ai_cmd(struct comedi
 	} else if (cmd->convert_arg < 655360000) {
 		base_clock = CLOCK_100_KHZ;
 		timer = cmd->convert_arg / 10000;
-	} else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */) {
+	} else /* cmd->convert_arg < 6553600000 */ {
 		base_clock = CLOCK_10_KHZ;
 		timer = cmd->convert_arg / 100000;
-	} else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */) {
-		base_clock = CLOCK_1_KHZ;
-		timer = cmd->convert_arg / 1000000;
 	}
 	outw(0xFF03, dev->iobase + AM9513A_COM_REG);
 	outw(base_clock, dev->iobase + AM9513A_DATA_REG);
@@ -403,12 +398,9 @@ static int atmio16d_ai_cmd(struct comedi
 		} else if (cmd->scan_begin_arg < 655360000) {
 			base_clock = CLOCK_100_KHZ;
 			timer = cmd->scan_begin_arg / 10000;
-		} else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */) {
+		} else /* cmd->scan_begin_arg < 6553600000 */ {
 			base_clock = CLOCK_10_KHZ;
 			timer = cmd->scan_begin_arg / 100000;
-		} else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */) {
-			base_clock = CLOCK_1_KHZ;
-			timer = cmd->scan_begin_arg / 1000000;
 		}
 		outw(0xFF02, dev->iobase + AM9513A_COM_REG);
 		outw(base_clock, dev->iobase + AM9513A_DATA_REG);
@@ -630,7 +622,7 @@ static int atmio16d_attach(struct comedi
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], ATMIO16D_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x20);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_atmio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_atmio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_atmio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_atmio.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,233 +98,135 @@ are not supported.
 #include "ni_stc.h"
 #include "8255.h"
 
-#define ATMIO 1
-#undef PCIMIO
-
 /*
  *  AT specific setup
  */
 
-#define NI_SIZE 0x20
-
-#define MAX_N_CALDACS 32
-
 static const struct ni_board_struct ni_boards[] = {
-	{.device_id = 44,
-	 .isapnp_id = 0x0000,	/* XXX unknown */
-	 .name = "at-mio-16e-1",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 8192,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .has_8255 = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {mb88341},
-	 },
-	{.device_id = 25,
-	 .isapnp_id = 0x1900,
-	 .name = "at-mio-16e-2",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 2048,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 2000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .has_8255 = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {mb88341},
-	 },
-	{.device_id = 36,
-	 .isapnp_id = 0x2400,
-	 .name = "at-mio-16e-10",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{.device_id = 37,
-	 .isapnp_id = 0x2500,
-	 .name = "at-mio-16de-10",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 1,
-	 },
-	{.device_id = 38,
-	 .isapnp_id = 0x2600,
-	 .name = "at-mio-64e-3",
-	 .n_adchan = 64,
-	 .adbits = 12,
-	 .ai_fifo_depth = 2048,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 2000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .has_8255 = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 },
-	{.device_id = 39,
-	 .isapnp_id = 0x2700,
-	 .name = "at-mio-16xe-50",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_8,
-	 .ai_speed = 50000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 50000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043},
-	 .has_8255 = 0,
-	 },
-	{.device_id = 50,
-	 .isapnp_id = 0x0000,	/* XXX unknown */
-	 .name = "at-mio-16xe-10",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{.device_id = 51,
-	 .isapnp_id = 0x0000,	/* XXX unknown */
-	 .name = "at-ai-16xe-10",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,	/* unknown */
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 }
+	{
+		.name		= "at-mio-16e-1",
+		.device_id	= 44,
+		.isapnp_id	= 0x0000,	/* XXX unknown */
+		.n_adchan	= 16,
+		.ai_maxdata	= 0x0fff,
+		.ai_fifo_depth	= 8192,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 1000,
+		.caldac		= { mb88341 },
+	}, {
+		.name		= "at-mio-16e-2",
+		.device_id	= 25,
+		.isapnp_id	= 0x1900,
+		.n_adchan	= 16,
+		.ai_maxdata	= 0x0fff,
+		.ai_fifo_depth	= 2048,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 2000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 1000,
+		.caldac		= { mb88341 },
+	}, {
+		.name		= "at-mio-16e-10",
+		.device_id	= 36,
+		.isapnp_id	= 0x2400,
+		.n_adchan	= 16,
+		.ai_maxdata	= 0x0fff,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 10000,
+		.caldac		= { ad8804_debug },
+	}, {
+		.name		= "at-mio-16de-10",
+		.device_id	= 37,
+		.isapnp_id	= 0x2500,
+		.n_adchan	= 16,
+		.ai_maxdata	= 0x0fff,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 10000,
+		.caldac		= { ad8804_debug },
+		.has_8255	= 1,
+	}, {
+		.name		= "at-mio-64e-3",
+		.device_id	= 38,
+		.isapnp_id	= 0x2600,
+		.n_adchan	= 64,
+		.ai_maxdata	= 0x0fff,
+		.ai_fifo_depth	= 2048,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 2000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 1000,
+		.caldac		= { ad8804_debug },
+	}, {
+		.name		= "at-mio-16xe-50",
+		.device_id	= 39,
+		.isapnp_id	= 0x2700,
+		.n_adchan	= 16,
+		.ai_maxdata	= 0xffff,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_8,
+		.ai_speed	= 50000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0x0fff,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 50000,
+		.caldac		= { dac8800, dac8043 },
+	}, {
+		.name		= "at-mio-16xe-10",
+		.device_id	= 50,
+		.isapnp_id	= 0x0000,	/* XXX unknown */
+		.n_adchan	= 16,
+		.ai_maxdata	= 0xffff,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.ao_maxdata	= 0xffff,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 1000,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	}, {
+		.name		= "at-ai-16xe-10",
+		.device_id	= 51,
+		.isapnp_id	= 0x0000,	/* XXX unknown */
+		.n_adchan	= 16,
+		.ai_maxdata	= 0xffff,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,	/* unknown */
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
 };
 
 static const int ni_irqpin[] = {
 	-1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
 };
 
-#define interrupt_pin(a)	(ni_irqpin[(a)])
-
-#define IRQ_POLARITY 0
-
-#define NI_E_IRQ_FLAGS		0
-
-struct ni_private {
-	struct pnp_dev *isapnp_dev;
-	NI_PRIVATE_COMMON
-
-};
-
-/* How we access registers */
-
-#define ni_writel(a, b)		(outl((a), (b)+dev->iobase))
-#define ni_readl(a)		(inl((a)+dev->iobase))
-#define ni_writew(a, b)		(outw((a), (b)+dev->iobase))
-#define ni_readw(a)		(inw((a)+dev->iobase))
-#define ni_writeb(a, b)		(outb((a), (b)+dev->iobase))
-#define ni_readb(a)		(inb((a)+dev->iobase))
-
-/* How we access windowed registers */
-
-/* We automatically take advantage of STC registers that can be
- * read/written directly in the I/O space of the board.  The
- * AT-MIO devices map the low 8 STC registers to iobase+addr*2. */
-
-static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	if ((addr) < 8) {
-		ni_writew(data, addr * 2);
-	} else {
-		ni_writew(addr, Window_Address);
-		ni_writew(data, Window_Data);
-	}
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
-}
-
-static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
-	uint16_t ret;
-
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	if (addr < 8) {
-		ret = ni_readw(addr * 2);
-	} else {
-		ni_writew(addr, Window_Address);
-		ret = ni_readw(Window_Data);
-	}
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
-
-	return ret;
-}
+#include "ni_mio_common.c"
 
 static struct pnp_device_id device_ids[] = {
 	{.id = "NIC1900", .driver_data = 0},
@@ -337,8 +239,6 @@ static struct pnp_device_id device_ids[]
 
 MODULE_DEVICE_TABLE(pnp, device_ids);
 
-#include "ni_mio_common.c"
-
 static int ni_isapnp_find_board(struct pnp_dev **dev)
 {
 	struct pnp_dev *isapnp_dev = NULL;
@@ -353,20 +253,17 @@ static int ni_isapnp_find_board(struct p
 		if (isapnp_dev == NULL || isapnp_dev->card == NULL)
 			continue;
 
-		if (pnp_device_attach(isapnp_dev) < 0) {
-			printk
-			 ("ni_atmio: %s found but already active, skipping.\n",
-			  ni_boards[i].name);
+		if (pnp_device_attach(isapnp_dev) < 0)
 			continue;
-		}
+
 		if (pnp_activate_dev(isapnp_dev) < 0) {
 			pnp_device_detach(isapnp_dev);
 			return -EAGAIN;
 		}
-		if (!pnp_port_valid(isapnp_dev, 0)
-		    || !pnp_irq_valid(isapnp_dev, 0)) {
+
+		if (!pnp_port_valid(isapnp_dev, 0) ||
+		    !pnp_irq_valid(isapnp_dev, 0)) {
 			pnp_device_detach(isapnp_dev);
-			printk("ni_atmio: pnp invalid port or irq, aborting\n");
 			return -ENOMEM;
 		}
 		break;
@@ -388,11 +285,13 @@ static int ni_getboardtype(struct comedi
 
 	}
 	if (device_id == 255)
-		printk(" can't find board\n");
+		dev_err(dev->class_dev, "can't find board\n");
 	 else if (device_id == 0)
-		printk(" EEPROM read error (?) or device not found\n");
+		dev_err(dev->class_dev,
+			"EEPROM read error (?) or device not found\n");
 	 else
-		printk(" unknown device ID %d -- contact author\n", device_id);
+		dev_err(dev->class_dev,
+			"unknown device ID %d -- contact author\n", device_id);
 
 	return -1;
 }
@@ -413,11 +312,6 @@ static int ni_atmio_attach(struct comedi
 		return ret;
 	devpriv = dev->private;
 
-	devpriv->stc_writew = &ni_atmio_win_out;
-	devpriv->stc_readw = &ni_atmio_win_in;
-	devpriv->stc_writel = &win_out2;
-	devpriv->stc_readl = &win_in2;
-
 	iobase = it->options[0];
 	irq = it->options[1];
 	isapnp_dev = NULL;
@@ -428,10 +322,10 @@ static int ni_atmio_attach(struct comedi
 
 		iobase = pnp_port_start(isapnp_dev, 0);
 		irq = pnp_irq(isapnp_dev, 0);
-		devpriv->isapnp_dev = isapnp_dev;
+		comedi_set_hw_dev(dev, &isapnp_dev->dev);
 	}
 
-	ret = comedi_request_region(dev, iobase, NI_SIZE);
+	ret = comedi_request_region(dev, iobase, 0x20);
 	if (ret)
 		return ret;
 
@@ -443,31 +337,23 @@ static int ni_atmio_attach(struct comedi
 
 	dev->board_ptr = ni_boards + board;
 	boardtype = comedi_board(dev);
-
-	printk(" %s", boardtype->name);
 	dev->board_name = boardtype->name;
 
 	/* irq stuff */
 
 	if (irq != 0) {
-		if (irq > 15 || ni_irqpin[irq] == -1) {
-			printk(" invalid irq %u\n", irq);
+		if (irq > 15 || ni_irqpin[irq] == -1)
 			return -EINVAL;
-		}
-		printk(" ( irq = %u )", irq);
-		ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
-				  "ni_atmio", dev);
-
-		if (ret < 0) {
-			printk(" irq not available\n");
+		ret = request_irq(irq, ni_E_interrupt, 0,
+				  dev->board_name, dev);
+		if (ret < 0)
 			return -EINVAL;
-		}
 		dev->irq = irq;
 	}
 
 	/* generic E series stuff in ni_mio_common.c */
 
-	ret = ni_E_init(dev);
+	ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
 	if (ret < 0)
 		return ret;
 
@@ -477,12 +363,14 @@ static int ni_atmio_attach(struct comedi
 
 static void ni_atmio_detach(struct comedi_device *dev)
 {
-	struct ni_private *devpriv = dev->private;
+	struct pnp_dev *isapnp_dev;
 
 	mio_common_detach(dev);
 	comedi_legacy_detach(dev);
-	if (devpriv->isapnp_dev)
-		pnp_device_detach(devpriv->isapnp_dev);
+
+	isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
+	if (isapnp_dev)
+		pnp_device_detach(isapnp_dev);
 }
 
 static struct comedi_driver ni_atmio_driver = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_daq_700.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_daq_700.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_daq_700.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_daq_700.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,32 +18,34 @@
  */
 
 /*
-Driver: ni_daq_700
-Description: National Instruments PCMCIA DAQCard-700 DIO only
-Author: Fred Brooks <nsaspook@nsaspook.com>,
-  based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
-Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
-Status: works
-Updated: Wed, 19 Sep 2012 12:07:20 +0000
-
-The daqcard-700 appears in Comedi as a  digital I/O subdevice (0) with
-16 channels and a analog input subdevice (1) with 16 single-ended channels.
-
-Digital:  The channel 0 corresponds to the daqcard-700's output
-port, bit 0; channel 8 corresponds to the input port, bit 0.
-
-Digital direction configuration: channels 0-7 output, 8-15 input (8225 device
-emu as port A output, port B input, port C N/A).
-
-Analog: The input  range is 0 to 4095 for -10 to +10 volts
-IRQ is assigned but not used.
-
-Version 0.1	Original DIO only driver
-Version 0.2	DIO and basic AI analog input support on 16 se channels
-
-Manuals:	Register level:	http://www.ni.com/pdf/manuals/340698.pdf
-		User Manual:	http://www.ni.com/pdf/manuals/320676d.pdf
-*/
+ * Driver: ni_daq_700
+ * Description: National Instruments PCMCIA DAQCard-700
+ * Author: Fred Brooks <nsaspook@nsaspook.com>,
+ *   based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
+ * Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
+ * Status: works
+ * Updated: Wed, 21 May 2014 12:07:20 +0000
+ *
+ * The daqcard-700 appears in Comedi as a  digital I/O subdevice (0) with
+ * 16 channels and a analog input subdevice (1) with 16 single-ended channels
+ * or 8 differential channels, and three input ranges.
+ *
+ * Digital:  The channel 0 corresponds to the daqcard-700's output
+ * port, bit 0; channel 8 corresponds to the input port, bit 0.
+ *
+ * Digital direction configuration: channels 0-7 output, 8-15 input.
+ *
+ * Analog: The input  range is 0 to 4095 with a default of -10 to +10 volts.
+ * Valid ranges:
+ *       0 for -10 to 10V bipolar
+ *       1 for -5 to 5V bipolar
+ *       2 for -2.5 to 2.5V bipolar
+ *
+ * IRQ is assigned but not used.
+ *
+ * Manuals:	Register level:	http://www.ni.com/pdf/manuals/340698.pdf
+ *		User Manual:	http://www.ni.com/pdf/manuals/320676d.pdf
+ */
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -69,6 +71,17 @@ Manuals:	Register level:	http://www.ni.c
 #define CDA_R2		0x0A	/* RW 8bit */
 #define CMO_R		0x0B	/* RO 8bit */
 #define TIC_R		0x06	/* WO 8bit */
+/* daqcard700 modes */
+#define CMD_R3_DIFF     0x04    /* diff mode */
+
+static const struct comedi_lrange range_daq700_ai = {
+	3,
+	{
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5)
+	}
+};
 
 static int daq700_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
@@ -131,11 +144,22 @@ static int daq700_ai_rinsn(struct comedi
 			   struct comedi_subdevice *s,
 			   struct comedi_insn *insn, unsigned int *data)
 {
-	int n, chan;
+	int n;
 	int d;
 	int ret;
+	unsigned int chan	= CR_CHAN(insn->chanspec);
+	unsigned int aref	= CR_AREF(insn->chanspec);
+	unsigned int range	= CR_RANGE(insn->chanspec);
+	unsigned int r3_bits	= 0;
+
+	/* set channel input modes */
+	if (aref == AREF_DIFF)
+		r3_bits |= CMD_R3_DIFF;
+	/* write channel mode/range */
+	if (range >= 1)
+		range++;        /* convert range to hardware value */
+	outb(r3_bits | (range & 0x03), dev->iobase + CMD_R3);
 
-	chan = CR_CHAN(insn->chanspec);
 	/* write channel to multiplexer */
 	/* set mask scan bit high to disable scanning */
 	outb(chan | 0x80, dev->iobase + CMD_R1);
@@ -147,6 +171,9 @@ static int daq700_ai_rinsn(struct comedi
 		/* trigger conversion with out0 L to H */
 		outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */
 		outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */
+		outb(0x00, dev->iobase + ADCLEAR_R);	/* clear the ADC FIFO */
+		/* read 16bit junk from FIFO to clear */
+		inw(dev->iobase + ADFIFO_R);
 		/* mode 1 out0 H, L to H, start conversion */
 		outb(0x32, dev->iobase + CMO_R);
 
@@ -222,11 +249,10 @@ static int daq700_auto_attach(struct com
 	/* DAQCard-700 ai */
 	s = &dev->subdevices[1];
 	s->type = COMEDI_SUBD_AI;
-	/* we support single-ended (ground)  */
-	s->subdev_flags = SDF_READABLE | SDF_GROUND;
+	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
 	s->n_chan = 16;
 	s->maxdata = (1 << 12) - 1;
-	s->range_table = &range_bipolar10;
+	s->range_table = &range_daq700_ai;
 	s->insn_read = daq700_ai_rinsn;
 	daq700_ai_config(dev, s);
 
@@ -263,5 +289,4 @@ module_comedi_pcmcia_driver(daq700_drive
 MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
 MODULE_DESCRIPTION(
 	"Comedi driver for National Instruments PCMCIA DAQCard-700 DIO/AI");
-MODULE_VERSION("0.2.00");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -72,8 +72,6 @@
 #include "ni_labpc_regs.h"
 #include "ni_labpc_isadma.h"
 
-#define LABPC_SIZE		0x20	/* size of ISA io region */
-
 enum scan_mode {
 	MODE_SINGLE_CHAN,
 	MODE_SINGLE_CHAN_INTERVAL,
@@ -130,24 +128,26 @@ static const struct comedi_lrange range_
 
 /* functions that do inb/outb and readb/writeb so we can use
  * function pointers to decide which to use */
-static inline unsigned int labpc_inb(unsigned long address)
+static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg)
 {
-	return inb(address);
+	return inb(dev->iobase + reg);
 }
 
-static inline void labpc_outb(unsigned int byte, unsigned long address)
+static void labpc_outb(struct comedi_device *dev,
+		       unsigned int byte, unsigned long reg)
 {
-	outb(byte, address);
+	outb(byte, dev->iobase + reg);
 }
 
-static inline unsigned int labpc_readb(unsigned long address)
+static unsigned int labpc_readb(struct comedi_device *dev, unsigned long reg)
 {
-	return readb((void __iomem *)address);
+	return readb(dev->mmio + reg);
 }
 
-static inline void labpc_writeb(unsigned int byte, unsigned long address)
+static void labpc_writeb(struct comedi_device *dev,
+			 unsigned int byte, unsigned long reg)
 {
-	writeb(byte, (void __iomem *)address);
+	writeb(byte, dev->mmio + reg);
 }
 
 #if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISA)
@@ -172,38 +172,29 @@ static const struct labpc_boardinfo labp
 #endif
 
 static void labpc_counter_load(struct comedi_device *dev,
-			       unsigned long base_address,
+			       unsigned long reg,
 			       unsigned int counter_number,
 			       unsigned int count,
 			       unsigned int mode)
 {
-	const struct labpc_boardinfo *board = comedi_board(dev);
-
-	if (board->has_mmio) {
-		void __iomem *mmio_base = (void __iomem *)base_address;
-
-		i8254_mm_set_mode(mmio_base, 0, counter_number, mode);
-		i8254_mm_write(mmio_base, 0, counter_number, count);
+	if (dev->mmio) {
+		i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode);
+		i8254_mm_write(dev->mmio + reg, 0, counter_number, count);
 	} else {
-		i8254_set_mode(base_address, 0, counter_number, mode);
-		i8254_write(base_address, 0, counter_number, count);
+		i8254_set_mode(dev->iobase + reg, 0, counter_number, mode);
+		i8254_write(dev->iobase + reg, 0, counter_number, count);
 	}
 }
 
 static void labpc_counter_set_mode(struct comedi_device *dev,
-				   unsigned long base_address,
+				   unsigned long reg,
 				   unsigned int counter_number,
 				   unsigned int mode)
 {
-	const struct labpc_boardinfo *board = comedi_board(dev);
-
-	if (board->has_mmio) {
-		void __iomem *mmio_base = (void __iomem *)base_address;
-
-		i8254_mm_set_mode(mmio_base, 0, counter_number, mode);
-	} else {
-		i8254_set_mode(base_address, 0, counter_number, mode);
-	}
+	if (dev->mmio)
+		i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode);
+	else
+		i8254_set_mode(dev->iobase + reg, 0, counter_number, mode);
 }
 
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -213,11 +204,11 @@ static int labpc_cancel(struct comedi_de
 
 	spin_lock_irqsave(&dev->spinlock, flags);
 	devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
-	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
+	devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	devpriv->cmd3 = 0;
-	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
+	devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
 
 	return 0;
 }
@@ -247,7 +238,7 @@ static void labpc_ai_set_chan_and_gain(s
 	devpriv->cmd1 = CMD1_MA(chan);
 	devpriv->cmd1 |= CMD1_GAIN(range);
 
-	devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
+	devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
 }
 
 static void labpc_setup_cmd6_reg(struct comedi_device *dev,
@@ -294,14 +285,14 @@ static void labpc_setup_cmd6_reg(struct
 	else
 		devpriv->cmd6 &= ~CMD6_SCANUP;
 
-	devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
+	devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
 }
 
 static unsigned int labpc_read_adc_fifo(struct comedi_device *dev)
 {
 	struct labpc_private *devpriv = dev->private;
-	unsigned int lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-	unsigned int msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+	unsigned int lsb = devpriv->read_byte(dev, ADC_FIFO_REG);
+	unsigned int msb = devpriv->read_byte(dev, ADC_FIFO_REG);
 
 	return (msb << 8) | lsb;
 }
@@ -310,7 +301,7 @@ static void labpc_clear_adc_fifo(struct
 {
 	struct labpc_private *devpriv = dev->private;
 
-	devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+	devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 	labpc_read_adc_fifo(dev);
 }
 
@@ -321,7 +312,7 @@ static int labpc_ai_eoc(struct comedi_de
 {
 	struct labpc_private *devpriv = dev->private;
 
-	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 	if (devpriv->stat1 & STAT1_DAVAIL)
 		return 0;
 	return -EBUSY;
@@ -353,17 +344,16 @@ static int labpc_ai_insn_read(struct com
 	/* single-ended/differential */
 	if (aref == AREF_DIFF)
 		devpriv->cmd4 |= CMD4_SEDIFF;
-	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
+	devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 
 	/* initialize pacer counter to prevent any problems */
-	labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG,
-			       0, I8254_MODE2);
+	labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2);
 
 	labpc_clear_adc_fifo(dev);
 
 	for (i = 0; i < insn->n; i++) {
 		/* trigger conversion */
-		devpriv->write_byte(0x1, dev->iobase + ADC_START_CONVERT_REG);
+		devpriv->write_byte(dev, 0x1, ADC_START_CONVERT_REG);
 
 		ret = comedi_timeout(dev, s, insn, labpc_ai_eoc, 0);
 		if (ret)
@@ -531,24 +521,26 @@ static void labpc_adc_timing(struct come
 
 static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
 {
+	unsigned int chan0;
+	unsigned int chan1;
+
 	if (cmd->chanlist_len == 1)
 		return MODE_SINGLE_CHAN;
 
-	/* chanlist may be NULL during cmdtest. */
+	/* chanlist may be NULL during cmdtest */
 	if (cmd->chanlist == NULL)
 		return MODE_MULT_CHAN_UP;
 
-	if (CR_CHAN(cmd->chanlist[0]) == CR_CHAN(cmd->chanlist[1]))
-		return MODE_SINGLE_CHAN_INTERVAL;
+	chan0 = CR_CHAN(cmd->chanlist[0]);
+	chan1 = CR_CHAN(cmd->chanlist[1]);
 
-	if (CR_CHAN(cmd->chanlist[0]) < CR_CHAN(cmd->chanlist[1]))
+	if (chan0 < chan1)
 		return MODE_MULT_CHAN_UP;
 
-	if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1]))
+	if (chan0 > chan1)
 		return MODE_MULT_CHAN_DOWN;
 
-	pr_err("ni_labpc: bug! cannot determine AI scan mode\n");
-	return 0;
+	return MODE_SINGLE_CHAN_INTERVAL;
 }
 
 static int labpc_ai_check_chanlist(struct comedi_device *dev,
@@ -749,12 +741,11 @@ static int labpc_ai_cmd(struct comedi_de
 		 * load counter a1 with count of 3
 		 * (pc+ manual says this is minimum allowed) using mode 0
 		 */
-		labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
+		labpc_counter_load(dev, COUNTER_A_BASE_REG,
 				   1, 3, I8254_MODE0);
 	} else	{
 		/* just put counter a1 in mode 0 to set its output low */
-		labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG,
-				       1, I8254_MODE0);
+		labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 1, I8254_MODE0);
 	}
 
 	/* figure out what method we will use to transfer data */
@@ -786,37 +777,35 @@ static int labpc_ai_cmd(struct comedi_de
 		 * list will get screwed when you switch
 		 * between scan up to scan down mode - dunno why */
 		udelay(1);
-		devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
+		devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
 	}
 
-	devpriv->write_byte(cmd->chanlist_len,
-			    dev->iobase + INTERVAL_COUNT_REG);
+	devpriv->write_byte(dev, cmd->chanlist_len, INTERVAL_COUNT_REG);
 	/*  load count */
-	devpriv->write_byte(0x1, dev->iobase + INTERVAL_STROBE_REG);
+	devpriv->write_byte(dev, 0x1, INTERVAL_STROBE_REG);
 
 	if (cmd->convert_src == TRIG_TIMER ||
 	    cmd->scan_begin_src == TRIG_TIMER) {
 		/*  set up pacing */
 		labpc_adc_timing(dev, cmd, mode);
 		/*  load counter b0 in mode 3 */
-		labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
+		labpc_counter_load(dev, COUNTER_B_BASE_REG,
 				   0, devpriv->divisor_b0, I8254_MODE3);
 	}
 	/*  set up conversion pacing */
 	if (labpc_ai_convert_period(cmd, mode)) {
 		/*  load counter a0 in mode 2 */
-		labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
+		labpc_counter_load(dev, COUNTER_A_BASE_REG,
 				   0, devpriv->divisor_a0, I8254_MODE2);
 	} else {
 		/* initialize pacer counter to prevent any problems */
-		labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG,
-				       0, I8254_MODE2);
+		labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2);
 	}
 
 	/*  set up scan pacing */
 	if (labpc_ai_scan_period(cmd, mode)) {
 		/*  load counter b1 in mode 2 */
-		labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
+		labpc_counter_load(dev, COUNTER_B_BASE_REG,
 				   1, devpriv->divisor_b1, I8254_MODE2);
 	}
 
@@ -830,7 +819,7 @@ static int labpc_ai_cmd(struct comedi_de
 	/*  enable fifo not empty interrupt? */
 	if (xfer == fifo_not_empty_transfer)
 		devpriv->cmd3 |= CMD3_FIFOINTEN;
-	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
+	devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
 
 	/*  setup any external triggering/pacing (cmd4 register) */
 	devpriv->cmd4 = 0;
@@ -846,7 +835,7 @@ static int labpc_ai_cmd(struct comedi_de
 	/*  single-ended/differential */
 	if (aref == AREF_DIFF)
 		devpriv->cmd4 |= CMD4_SEDIFF;
-	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
+	devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 
 	/*  startup acquisition */
 
@@ -863,7 +852,7 @@ static int labpc_ai_cmd(struct comedi_de
 	if (cmd->stop_src == TRIG_EXT)
 		devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG);
 
-	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
+	devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
@@ -880,7 +869,7 @@ static int labpc_drain_fifo(struct comed
 	const int timeout = 10000;
 	unsigned int i;
 
-	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 
 	for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout;
 	     i++) {
@@ -892,10 +881,10 @@ static int labpc_drain_fifo(struct comed
 		}
 		data = labpc_read_adc_fifo(dev);
 		cfc_write_to_buffer(dev->read_subdev, data);
-		devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+		devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 	}
 	if (i == timeout) {
-		comedi_error(dev, "ai timeout, fifo never empties");
+		dev_err(dev->class_dev, "ai timeout, fifo never empties\n");
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		return -1;
 	}
@@ -926,7 +915,7 @@ static irqreturn_t labpc_interrupt(int i
 	struct comedi_cmd *cmd;
 
 	if (!dev->attached) {
-		comedi_error(dev, "premature interrupt");
+		dev_err(dev->class_dev, "premature interrupt\n");
 		return IRQ_HANDLED;
 	}
 
@@ -934,9 +923,9 @@ static irqreturn_t labpc_interrupt(int i
 	cmd = &async->cmd;
 
 	/* read board status */
-	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 	if (board->is_labpc1200)
-		devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG);
+		devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
 
 	if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW |
 			       STAT1_OVERRUN | STAT1_DAVAIL)) == 0
@@ -947,10 +936,10 @@ static irqreturn_t labpc_interrupt(int i
 
 	if (devpriv->stat1 & STAT1_OVERRUN) {
 		/* clear error interrupt */
-		devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+		devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
-		comedi_error(dev, "overrun");
+		dev_err(dev->class_dev, "overrun\n");
 		return IRQ_HANDLED;
 	}
 
@@ -960,17 +949,17 @@ static irqreturn_t labpc_interrupt(int i
 		labpc_drain_fifo(dev);
 
 	if (devpriv->stat1 & STAT1_CNTINT) {
-		comedi_error(dev, "handled timer interrupt?");
+		dev_err(dev->class_dev, "handled timer interrupt?\n");
 		/*  clear it */
-		devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG);
+		devpriv->write_byte(dev, 0x1, TIMER_CLEAR_REG);
 	}
 
 	if (devpriv->stat1 & STAT1_OVERFLOW) {
 		/*  clear error interrupt */
-		devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+		devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		cfc_handle_events(dev, s);
-		comedi_error(dev, "overflow");
+		dev_err(dev->class_dev, "overflow\n");
 		return IRQ_HANDLED;
 	}
 	/*  handle external stop trigger */
@@ -1009,7 +998,7 @@ static int labpc_ao_insn_write(struct co
 	 * be independently enabled/disabled for its the two channels */
 	spin_lock_irqsave(&dev->spinlock, flags);
 	devpriv->cmd2 &= ~CMD2_LDAC(channel);
-	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
+	devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	/* set range */
@@ -1020,13 +1009,13 @@ static int labpc_ao_insn_write(struct co
 		else
 			devpriv->cmd6 &= ~CMD6_DACUNI(channel);
 		/*  write to register */
-		devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
+		devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
 	}
 	/* send data */
 	lsb = data[0] & 0xff;
 	msb = (data[0] >> 8) & 0xff;
-	devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel));
-	devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel));
+	devpriv->write_byte(dev, lsb, DAC_LSB_REG(channel));
+	devpriv->write_byte(dev, msb, DAC_MSB_REG(channel));
 
 	/* remember value for readback */
 	devpriv->ao_value[channel] = data[0];
@@ -1046,14 +1035,16 @@ static int labpc_ao_insn_read(struct com
 	return 1;
 }
 
-static int labpc_8255_mmio(int dir, int port, int data, unsigned long iobase)
+static int labpc_8255_mmio(int dir, int port, int data, unsigned long arg)
 {
+	struct comedi_device *dev = (struct comedi_device *)arg;
+
 	if (dir) {
-		writeb(data, (void __iomem *)(iobase + port));
+		writeb(data, dev->mmio + DIO_BASE_REG + port);
 		return 0;
-	} else {
-		return readb((void __iomem *)(iobase + port));
 	}
+
+	return readb(dev->mmio + DIO_BASE_REG + port);
 }
 
 /* lowlevel write to eeprom/dac */
@@ -1072,11 +1063,11 @@ static void labpc_serial_out(struct come
 		else
 			devpriv->cmd5 &= ~CMD5_SDATA;
 		udelay(1);
-		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+		devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 		/*  set clock to load bit */
 		devpriv->cmd5 |= CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+		devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	}
 }
 
@@ -1092,14 +1083,14 @@ static unsigned int labpc_serial_in(stru
 		/*  set serial clock */
 		devpriv->cmd5 |= CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+		devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 		/*  clear clock bit */
 		devpriv->cmd5 &= ~CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+		devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 		/*  read bits most significant bit first */
 		udelay(1);
-		devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG);
+		devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
 		if (devpriv->stat2 & STAT2_PROMOUT)
 			value |= 1 << (value_width - i);
 	}
@@ -1120,10 +1111,10 @@ static unsigned int labpc_eeprom_read(st
 	/*  enable read/write to eeprom */
 	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  send read instruction */
 	labpc_serial_out(dev, read_instruction, write_length);
@@ -1135,7 +1126,7 @@ static unsigned int labpc_eeprom_read(st
 	/*  disable read/write to eeprom */
 	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	return value;
 }
@@ -1150,10 +1141,10 @@ static unsigned int labpc_eeprom_read_st
 	/*  enable read/write to eeprom */
 	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  send read status instruction */
 	labpc_serial_out(dev, read_status_instruction, write_length);
@@ -1163,7 +1154,7 @@ static unsigned int labpc_eeprom_read_st
 	/*  disable read/write to eeprom */
 	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	return value;
 }
@@ -1186,7 +1177,7 @@ static int labpc_eeprom_write(struct com
 			break;
 	}
 	if (i == timeout) {
-		comedi_error(dev, "eeprom write timed out");
+		dev_err(dev->class_dev, "eeprom write timed out\n");
 		return -ETIME;
 	}
 	/*  update software copy of eeprom */
@@ -1195,21 +1186,21 @@ static int labpc_eeprom_write(struct com
 	/*  enable read/write to eeprom */
 	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  send write_enable instruction */
 	labpc_serial_out(dev, write_enable_instruction, write_length);
 	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  send write instruction */
 	devpriv->cmd5 |= CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	labpc_serial_out(dev, write_instruction, write_length);
 	/*  send 8 bit address to write to */
 	labpc_serial_out(dev, address, write_length);
@@ -1217,12 +1208,12 @@ static int labpc_eeprom_write(struct com
 	labpc_serial_out(dev, value, write_length);
 	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  disable read/write to eeprom */
 	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	return 0;
 }
@@ -1240,7 +1231,7 @@ static void write_caldac(struct comedi_d
 	/*  clear caldac load bit and make sure we don't write to eeprom */
 	devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 
 	/*  write 4 bit channel */
 	labpc_serial_out(dev, channel, 4);
@@ -1250,10 +1241,10 @@ static void write_caldac(struct comedi_d
 	/*  set and clear caldac bit to load caldac value */
 	devpriv->cmd5 |= CMD5_CALDACLD;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 	devpriv->cmd5 &= ~CMD5_CALDACLD;
 	udelay(1);
-	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 }
 
 static int labpc_calib_insn_write(struct comedi_device *dev,
@@ -1337,7 +1328,7 @@ int labpc_common_attach(struct comedi_de
 	int ret;
 	int i;
 
-	if (board->has_mmio) {
+	if (dev->mmio) {
 		devpriv->read_byte = labpc_readb;
 		devpriv->write_byte = labpc_writeb;
 	} else {
@@ -1346,13 +1337,13 @@ int labpc_common_attach(struct comedi_de
 	}
 
 	/* initialize board's command registers */
-	devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
-	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
-	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
-	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
+	devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
+	devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
+	devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
+	devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 	if (board->is_labpc1200) {
-		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
-		devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
+		devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
+		devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
 	}
 
 	if (irq) {
@@ -1402,8 +1393,8 @@ int labpc_common_attach(struct comedi_de
 			devpriv->ao_value[i] = s->maxdata / 2;
 			lsb = devpriv->ao_value[i] & 0xff;
 			msb = (devpriv->ao_value[i] >> 8) & 0xff;
-			devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i));
-			devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i));
+			devpriv->write_byte(dev, lsb, DAC_LSB_REG(i));
+			devpriv->write_byte(dev, msb, DAC_MSB_REG(i));
 		}
 	} else {
 		s->type		= COMEDI_SUBD_UNUSED;
@@ -1411,9 +1402,13 @@ int labpc_common_attach(struct comedi_de
 
 	/* 8255 dio */
 	s = &dev->subdevices[2];
-	ret = subdev_8255_init(dev, s,
-			       (board->has_mmio) ? labpc_8255_mmio : NULL,
-			       dev->iobase + DIO_BASE_REG);
+	if (dev->mmio) {
+		ret = subdev_8255_init(dev, s, labpc_8255_mmio,
+				       (unsigned long)dev);
+	} else {
+		ret = subdev_8255_init(dev, s, NULL,
+				       dev->iobase + DIO_BASE_REG);
+	}
 	if (ret)
 		return ret;
 
@@ -1463,7 +1458,7 @@ static int labpc_attach(struct comedi_de
 	if (!devpriv)
 		return -ENOMEM;
 
-	ret = comedi_request_region(dev, it->options[0], LABPC_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x20);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,11 +32,9 @@ struct labpc_boardinfo {
 	unsigned ai_scan_up:1;		/* can auto scan up in ai channels */
 	unsigned has_ao:1;		/* has analog outputs */
 	unsigned is_labpc1200:1;	/* has extra regs compared to pc+ */
-	unsigned has_mmio:1;		/* uses memory mapped io */
 };
 
 struct labpc_private {
-	struct mite_struct *mite;	/*  for mite chip on pci-1200 */
 	/*  number of data points left to be taken */
 	unsigned long long count;
 	/*  software copy of analog output values */
@@ -80,8 +78,9 @@ struct labpc_private {
 	 * function pointers so we can use inb/outb or readb/writeb as
 	 * appropriate
 	 */
-	unsigned int (*read_byte) (unsigned long address);
-	void (*write_byte) (unsigned int byte, unsigned long address);
+	unsigned int (*read_byte)(struct comedi_device *, unsigned long reg);
+	void (*write_byte)(struct comedi_device *,
+			   unsigned int byte, unsigned long reg);
 };
 
 int labpc_common_attach(struct comedi_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc_isadma.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc_isadma.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc_isadma.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc_isadma.c	2014-09-28 17:29:07.000000000 -0400
@@ -147,7 +147,7 @@ static void handle_isa_dma(struct comedi
 	enable_dma(devpriv->dma_chan);
 
 	/* clear dma tc interrupt */
-	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
+	devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG);
 }
 
 void labpc_handle_dma_status(struct comedi_device *dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc_pci.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc_pci.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_labpc_pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_labpc_pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,6 @@
 
 #include "../comedidev.h"
 
-#include "mite.h"
 #include "ni_labpc.h"
 
 enum labpc_pci_boardid {
@@ -49,10 +48,32 @@ static const struct labpc_boardinfo labp
 		.ai_scan_up		= 1,
 		.has_ao			= 1,
 		.is_labpc1200		= 1,
-		.has_mmio		= 1,
 	},
 };
 
+/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+#define MITE_IODWBSR	0xc0	 /* IO Device Window Base Size Register */
+#define WENAB		(1 << 7) /* window enable */
+
+static int labpc_pci_mite_init(struct pci_dev *pcidev)
+{
+	void __iomem *mite_base;
+	u32 main_phys_addr;
+
+	/* ioremap the MITE registers (BAR 0) temporarily */
+	mite_base = pci_ioremap_bar(pcidev, 0);
+	if (!mite_base)
+		return -ENOMEM;
+
+	/* set data window to main registers (BAR 1) */
+	main_phys_addr = pci_resource_start(pcidev, 1);
+	writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR);
+
+	/* finished with MITE registers */
+	iounmap(mite_base);
+	return 0;
+}
+
 static int labpc_pci_auto_attach(struct comedi_device *dev,
 				 unsigned long context)
 {
@@ -72,29 +93,25 @@ static int labpc_pci_auto_attach(struct
 	if (ret)
 		return ret;
 
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
+	ret = labpc_pci_mite_init(pcidev);
+	if (ret)
+		return ret;
+
+	dev->mmio = pci_ioremap_bar(pcidev, 1);
+	if (!dev->mmio)
 		return -ENOMEM;
 
-	devpriv->mite = mite_alloc(pcidev);
-	if (!devpriv->mite)
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+	if (!devpriv)
 		return -ENOMEM;
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0)
-		return ret;
-	dev->iobase = (unsigned long)devpriv->mite->daq_io_addr;
 
-	return labpc_common_attach(dev, mite_irq(devpriv->mite), IRQF_SHARED);
+	return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED);
 }
 
 static void labpc_pci_detach(struct comedi_device *dev)
 {
-	struct labpc_private *devpriv = dev->private;
-
-	if (devpriv && devpriv->mite) {
-		mite_unsetup(devpriv->mite);
-		mite_free(devpriv->mite);
-	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	comedi_pci_disable(dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_mio_common.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_mio_common.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_mio_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_mio_common.c	2014-09-28 17:29:07.000000000 -0400
@@ -194,113 +194,6 @@ static const struct comedi_lrange *const
 	[ai_gain_6143] = &range_bipolar5
 };
 
-static int ni_dio_insn_config(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static int ni_dio_insn_bits(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static int ni_cdio_cmdtest(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_cmd *cmd);
-static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ni_cdio_cancel(struct comedi_device *dev,
-			  struct comedi_subdevice *s);
-static void handle_cdio_interrupt(struct comedi_device *dev);
-static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
-			  unsigned int trignum);
-
-static int ni_serial_insn_config(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-static int ni_serial_hw_readwrite8(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   unsigned char data_out,
-				   unsigned char *data_in);
-static int ni_serial_sw_readwrite8(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   unsigned char data_out,
-				   unsigned char *data_in);
-
-static int ni_calib_insn_read(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static int ni_calib_insn_write(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-
-static int ni_eeprom_insn_read(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn,
-					unsigned int *data);
-
-static int ni_pfi_insn_bits(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static int ni_pfi_insn_config(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static unsigned ni_old_get_pfi_routing(struct comedi_device *dev,
-				       unsigned chan);
-
-static void ni_rtsi_init(struct comedi_device *dev);
-static int ni_rtsi_insn_bits(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data);
-static int ni_rtsi_insn_config(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-
-static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ni_read_eeprom(struct comedi_device *dev, int addr);
-
-#ifndef PCIDMA
-static void ni_handle_fifo_half_full(struct comedi_device *dev);
-static int ni_ao_fifo_half_empty(struct comedi_device *dev,
-				 struct comedi_subdevice *s);
-#endif
-static void ni_handle_fifo_dregs(struct comedi_device *dev);
-static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
-			 unsigned int trignum);
-static void ni_load_channelgain_list(struct comedi_device *dev,
-				     unsigned int n_chan, unsigned int *list);
-static void shutdown_ai_command(struct comedi_device *dev);
-
-static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
-			 unsigned int trignum);
-
-static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
-
-#ifdef PCIDMA
-static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-#endif
-static void handle_gpct_interrupt(struct comedi_device *dev,
-				  unsigned short counter_index);
-
-static int init_cs5529(struct comedi_device *dev);
-static int cs5529_do_conversion(struct comedi_device *dev,
-				unsigned short *data);
-static int cs5529_ai_insn_read(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
-				unsigned int reg_select_bits);
-
-static int ni_m_series_pwm_config(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-static int ni_6143_pwm_config(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-
-static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
-			       unsigned period_ns);
-static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status);
-static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status);
-
 enum aimodes {
 	AIMODE_NONE = 0,
 	AIMODE_HALF_FULL = 1,
@@ -330,10 +223,8 @@ static inline unsigned NI_GPCT_SUBDEV(un
 	switch (counter_index) {
 	case 0:
 		return NI_GPCT0_SUBDEV;
-		break;
 	case 1:
 		return NI_GPCT1_SUBDEV;
-		break;
 	default:
 		break;
 	}
@@ -353,12 +244,394 @@ enum timebase_nanoseconds {
 
 static const int num_adc_stages_611x = 3;
 
-static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
-			       unsigned ai_mite_status);
-static void handle_b_interrupt(struct comedi_device *dev, unsigned short status,
-			       unsigned ao_mite_status);
-static void get_last_sample_611x(struct comedi_device *dev);
-static void get_last_sample_6143(struct comedi_device *dev);
+static void ni_writel(struct comedi_device *dev, uint32_t data, int reg)
+{
+	if (dev->mmio)
+		writel(data, dev->mmio + reg);
+
+	outl(data, dev->iobase + reg);
+}
+
+static void ni_writew(struct comedi_device *dev, uint16_t data, int reg)
+{
+	if (dev->mmio)
+		writew(data, dev->mmio + reg);
+
+	outw(data, dev->iobase + reg);
+}
+
+static void ni_writeb(struct comedi_device *dev, uint8_t data, int reg)
+{
+	if (dev->mmio)
+		writeb(data, dev->mmio + reg);
+
+	outb(data, dev->iobase + reg);
+}
+
+static uint32_t ni_readl(struct comedi_device *dev, int reg)
+{
+	if (dev->mmio)
+		return readl(dev->mmio + reg);
+
+	return inl(dev->iobase + reg);
+}
+
+static uint16_t ni_readw(struct comedi_device *dev, int reg)
+{
+	if (dev->mmio)
+		return readw(dev->mmio + reg);
+
+	return inw(dev->iobase + reg);
+}
+
+static uint8_t ni_readb(struct comedi_device *dev, int reg)
+{
+	if (dev->mmio)
+		return readb(dev->mmio + reg);
+
+	return inb(dev->iobase + reg);
+}
+
+/*
+ * We automatically take advantage of STC registers that can be
+ * read/written directly in the I/O space of the board.
+ *
+ * The AT-MIO and DAQCard devices map the low 8 STC registers to
+ * iobase+reg*2.
+ *
+ * Most PCIMIO devices also map the low 8 STC registers but the
+ * 611x devices map the read registers to iobase+(addr-1)*2.
+ * For now non-windowed STC access is disabled if a PCIMIO device
+ * is detected (devpriv->mite has been initialized).
+ *
+ * The M series devices do not used windowed registers for the
+ * STC registers. The functions below handle the mapping of the
+ * windowed STC registers to the m series register offsets.
+ */
+
+static void m_series_stc_writel(struct comedi_device *dev,
+				uint32_t data, int reg)
+{
+	unsigned offset;
+
+	switch (reg) {
+	case AI_SC_Load_A_Registers:
+		offset = M_Offset_AI_SC_Load_A;
+		break;
+	case AI_SI_Load_A_Registers:
+		offset = M_Offset_AI_SI_Load_A;
+		break;
+	case AO_BC_Load_A_Register:
+		offset = M_Offset_AO_BC_Load_A;
+		break;
+	case AO_UC_Load_A_Register:
+		offset = M_Offset_AO_UC_Load_A;
+		break;
+	case AO_UI_Load_A_Register:
+		offset = M_Offset_AO_UI_Load_A;
+		break;
+	case G_Load_A_Register(0):
+		offset = M_Offset_G0_Load_A;
+		break;
+	case G_Load_A_Register(1):
+		offset = M_Offset_G1_Load_A;
+		break;
+	case G_Load_B_Register(0):
+		offset = M_Offset_G0_Load_B;
+		break;
+	case G_Load_B_Register(1):
+		offset = M_Offset_G1_Load_B;
+		break;
+	default:
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch\n",
+			 __func__, reg);
+		return;
+	}
+	ni_writel(dev, data, offset);
+}
+
+static void m_series_stc_writew(struct comedi_device *dev,
+				uint16_t data, int reg)
+{
+	unsigned offset;
+
+	switch (reg) {
+	case ADC_FIFO_Clear:
+		offset = M_Offset_AI_FIFO_Clear;
+		break;
+	case AI_Command_1_Register:
+		offset = M_Offset_AI_Command_1;
+		break;
+	case AI_Command_2_Register:
+		offset = M_Offset_AI_Command_2;
+		break;
+	case AI_Mode_1_Register:
+		offset = M_Offset_AI_Mode_1;
+		break;
+	case AI_Mode_2_Register:
+		offset = M_Offset_AI_Mode_2;
+		break;
+	case AI_Mode_3_Register:
+		offset = M_Offset_AI_Mode_3;
+		break;
+	case AI_Output_Control_Register:
+		offset = M_Offset_AI_Output_Control;
+		break;
+	case AI_Personal_Register:
+		offset = M_Offset_AI_Personal;
+		break;
+	case AI_SI2_Load_A_Register:
+		/* this is a 32 bit register on m series boards */
+		ni_writel(dev, data, M_Offset_AI_SI2_Load_A);
+		return;
+	case AI_SI2_Load_B_Register:
+		/* this is a 32 bit register on m series boards */
+		ni_writel(dev, data, M_Offset_AI_SI2_Load_B);
+		return;
+	case AI_START_STOP_Select_Register:
+		offset = M_Offset_AI_START_STOP_Select;
+		break;
+	case AI_Trigger_Select_Register:
+		offset = M_Offset_AI_Trigger_Select;
+		break;
+	case Analog_Trigger_Etc_Register:
+		offset = M_Offset_Analog_Trigger_Etc;
+		break;
+	case AO_Command_1_Register:
+		offset = M_Offset_AO_Command_1;
+		break;
+	case AO_Command_2_Register:
+		offset = M_Offset_AO_Command_2;
+		break;
+	case AO_Mode_1_Register:
+		offset = M_Offset_AO_Mode_1;
+		break;
+	case AO_Mode_2_Register:
+		offset = M_Offset_AO_Mode_2;
+		break;
+	case AO_Mode_3_Register:
+		offset = M_Offset_AO_Mode_3;
+		break;
+	case AO_Output_Control_Register:
+		offset = M_Offset_AO_Output_Control;
+		break;
+	case AO_Personal_Register:
+		offset = M_Offset_AO_Personal;
+		break;
+	case AO_Start_Select_Register:
+		offset = M_Offset_AO_Start_Select;
+		break;
+	case AO_Trigger_Select_Register:
+		offset = M_Offset_AO_Trigger_Select;
+		break;
+	case Clock_and_FOUT_Register:
+		offset = M_Offset_Clock_and_FOUT;
+		break;
+	case Configuration_Memory_Clear:
+		offset = M_Offset_Configuration_Memory_Clear;
+		break;
+	case DAC_FIFO_Clear:
+		offset = M_Offset_AO_FIFO_Clear;
+		break;
+	case DIO_Control_Register:
+		dev_dbg(dev->class_dev,
+			"%s: FIXME: register 0x%x does not map cleanly on to m-series boards\n",
+			__func__, reg);
+		return;
+	case G_Autoincrement_Register(0):
+		offset = M_Offset_G0_Autoincrement;
+		break;
+	case G_Autoincrement_Register(1):
+		offset = M_Offset_G1_Autoincrement;
+		break;
+	case G_Command_Register(0):
+		offset = M_Offset_G0_Command;
+		break;
+	case G_Command_Register(1):
+		offset = M_Offset_G1_Command;
+		break;
+	case G_Input_Select_Register(0):
+		offset = M_Offset_G0_Input_Select;
+		break;
+	case G_Input_Select_Register(1):
+		offset = M_Offset_G1_Input_Select;
+		break;
+	case G_Mode_Register(0):
+		offset = M_Offset_G0_Mode;
+		break;
+	case G_Mode_Register(1):
+		offset = M_Offset_G1_Mode;
+		break;
+	case Interrupt_A_Ack_Register:
+		offset = M_Offset_Interrupt_A_Ack;
+		break;
+	case Interrupt_A_Enable_Register:
+		offset = M_Offset_Interrupt_A_Enable;
+		break;
+	case Interrupt_B_Ack_Register:
+		offset = M_Offset_Interrupt_B_Ack;
+		break;
+	case Interrupt_B_Enable_Register:
+		offset = M_Offset_Interrupt_B_Enable;
+		break;
+	case Interrupt_Control_Register:
+		offset = M_Offset_Interrupt_Control;
+		break;
+	case IO_Bidirection_Pin_Register:
+		offset = M_Offset_IO_Bidirection_Pin;
+		break;
+	case Joint_Reset_Register:
+		offset = M_Offset_Joint_Reset;
+		break;
+	case RTSI_Trig_A_Output_Register:
+		offset = M_Offset_RTSI_Trig_A_Output;
+		break;
+	case RTSI_Trig_B_Output_Register:
+		offset = M_Offset_RTSI_Trig_B_Output;
+		break;
+	case RTSI_Trig_Direction_Register:
+		offset = M_Offset_RTSI_Trig_Direction;
+		break;
+	/*
+	 * FIXME: DIO_Output_Register (16 bit reg) is replaced by
+	 * M_Offset_Static_Digital_Output (32 bit) and
+	 * M_Offset_SCXI_Serial_Data_Out (8 bit)
+	 */
+	default:
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch\n",
+			 __func__, reg);
+		return;
+	}
+	ni_writew(dev, data, offset);
+}
+
+static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
+{
+	unsigned offset;
+
+	switch (reg) {
+	case G_HW_Save_Register(0):
+		offset = M_Offset_G0_HW_Save;
+		break;
+	case G_HW_Save_Register(1):
+		offset = M_Offset_G1_HW_Save;
+		break;
+	case G_Save_Register(0):
+		offset = M_Offset_G0_Save;
+		break;
+	case G_Save_Register(1):
+		offset = M_Offset_G1_Save;
+		break;
+	default:
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch\n",
+			 __func__, reg);
+		return 0;
+	}
+	return ni_readl(dev, offset);
+}
+
+static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
+{
+	unsigned offset;
+
+	switch (reg) {
+	case AI_Status_1_Register:
+		offset = M_Offset_AI_Status_1;
+		break;
+	case AO_Status_1_Register:
+		offset = M_Offset_AO_Status_1;
+		break;
+	case AO_Status_2_Register:
+		offset = M_Offset_AO_Status_2;
+		break;
+	case DIO_Serial_Input_Register:
+		return ni_readb(dev, M_Offset_SCXI_Serial_Data_In);
+	case Joint_Status_1_Register:
+		offset = M_Offset_Joint_Status_1;
+		break;
+	case Joint_Status_2_Register:
+		offset = M_Offset_Joint_Status_2;
+		break;
+	case G_Status_Register:
+		offset = M_Offset_G01_Status;
+		break;
+	default:
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch\n",
+			 __func__, reg);
+		return 0;
+	}
+	return ni_readw(dev, offset);
+}
+
+static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg)
+{
+	struct ni_private *devpriv = dev->private;
+	unsigned long flags;
+
+	if (devpriv->is_m_series) {
+		m_series_stc_writew(dev, data, reg);
+	} else {
+		spin_lock_irqsave(&devpriv->window_lock, flags);
+		if (!devpriv->mite && reg < 8) {
+			ni_writew(dev, data, reg * 2);
+		} else {
+			ni_writew(dev, reg, Window_Address);
+			ni_writew(dev, data, Window_Data);
+		}
+		spin_unlock_irqrestore(&devpriv->window_lock, flags);
+	}
+}
+
+static void ni_stc_writel(struct comedi_device *dev, uint32_t data, int reg)
+{
+	struct ni_private *devpriv = dev->private;
+
+	if (devpriv->is_m_series) {
+		m_series_stc_writel(dev, data, reg);
+	} else {
+		ni_stc_writew(dev, data >> 16, reg);
+		ni_stc_writew(dev, data & 0xffff, reg + 1);
+	}
+}
+
+static uint16_t ni_stc_readw(struct comedi_device *dev, int reg)
+{
+	struct ni_private *devpriv = dev->private;
+	unsigned long flags;
+	uint16_t val;
+
+	if (devpriv->is_m_series) {
+		val = m_series_stc_readw(dev, reg);
+	} else {
+		spin_lock_irqsave(&devpriv->window_lock, flags);
+		if (!devpriv->mite && reg < 8) {
+			val = ni_readw(dev, reg * 2);
+		} else {
+			ni_writew(dev, reg, Window_Address);
+			val = ni_readw(dev, Window_Data);
+		}
+		spin_unlock_irqrestore(&devpriv->window_lock, flags);
+	}
+	return val;
+}
+
+static uint32_t ni_stc_readl(struct comedi_device *dev, int reg)
+{
+	struct ni_private *devpriv = dev->private;
+	uint32_t val;
+
+	if (devpriv->is_m_series) {
+		val = m_series_stc_readl(dev, reg);
+	} else {
+		val = ni_stc_readw(dev, reg) << 16;
+		val |= ni_stc_readw(dev, reg + 1);
+	}
+	return val;
+}
 
 static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
 				   unsigned bit_mask, unsigned bit_values)
@@ -371,34 +644,34 @@ static inline void ni_set_bitfield(struc
 	case Interrupt_A_Enable_Register:
 		devpriv->int_a_enable_reg &= ~bit_mask;
 		devpriv->int_a_enable_reg |= bit_values & bit_mask;
-		devpriv->stc_writew(dev, devpriv->int_a_enable_reg,
-				    Interrupt_A_Enable_Register);
+		ni_stc_writew(dev, devpriv->int_a_enable_reg,
+			      Interrupt_A_Enable_Register);
 		break;
 	case Interrupt_B_Enable_Register:
 		devpriv->int_b_enable_reg &= ~bit_mask;
 		devpriv->int_b_enable_reg |= bit_values & bit_mask;
-		devpriv->stc_writew(dev, devpriv->int_b_enable_reg,
-				    Interrupt_B_Enable_Register);
+		ni_stc_writew(dev, devpriv->int_b_enable_reg,
+			      Interrupt_B_Enable_Register);
 		break;
 	case IO_Bidirection_Pin_Register:
 		devpriv->io_bidirection_pin_reg &= ~bit_mask;
 		devpriv->io_bidirection_pin_reg |= bit_values & bit_mask;
-		devpriv->stc_writew(dev, devpriv->io_bidirection_pin_reg,
-				    IO_Bidirection_Pin_Register);
+		ni_stc_writew(dev, devpriv->io_bidirection_pin_reg,
+			      IO_Bidirection_Pin_Register);
 		break;
 	case AI_AO_Select:
 		devpriv->ai_ao_select_reg &= ~bit_mask;
 		devpriv->ai_ao_select_reg |= bit_values & bit_mask;
-		ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
+		ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select);
 		break;
 	case G0_G1_Select:
 		devpriv->g0_g1_select_reg &= ~bit_mask;
 		devpriv->g0_g1_select_reg |= bit_values & bit_mask;
-		ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select);
+		ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select);
 		break;
 	default:
-		printk("Warning %s() called with invalid register\n", __func__);
-		printk("reg is %d\n", reg);
+		dev_err(dev->class_dev,
+			"%s called with invalid register %d\n", __func__, reg);
 		break;
 	}
 	mmiowb();
@@ -406,8 +679,6 @@ static inline void ni_set_bitfield(struc
 }
 
 #ifdef PCIDMA
-static int ni_ai_drain_dma(struct comedi_device *dev);
-
 /* DMA channel setup */
 
 /* negative channel means no channel */
@@ -472,7 +743,7 @@ static inline void ni_set_cdo_dma_channe
 		    (ni_stc_dma_channel_select_bitfield(mite_channel) <<
 		     CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask;
 	}
-	ni_writeb(devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select);
+	ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select);
 	mmiowb();
 	spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
 }
@@ -488,8 +759,8 @@ static int ni_request_ai_mite_channel(st
 	    mite_request_channel(devpriv->mite, devpriv->ai_mite_ring);
 	if (devpriv->ai_mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev,
-			     "failed to reserve mite dma channel for analog input.");
+		dev_err(dev->class_dev,
+			"failed to reserve mite dma channel for analog input\n");
 		return -EBUSY;
 	}
 	devpriv->ai_mite_chan->dir = COMEDI_INPUT;
@@ -509,8 +780,8 @@ static int ni_request_ao_mite_channel(st
 	    mite_request_channel(devpriv->mite, devpriv->ao_mite_ring);
 	if (devpriv->ao_mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev,
-			     "failed to reserve mite dma channel for analog outut.");
+		dev_err(dev->class_dev,
+			"failed to reserve mite dma channel for analog outut\n");
 		return -EBUSY;
 	}
 	devpriv->ao_mite_chan->dir = COMEDI_OUTPUT;
@@ -535,8 +806,8 @@ static int ni_request_gpct_mite_channel(
 				 devpriv->gpct_mite_ring[gpct_index]);
 	if (mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev,
-			     "failed to reserve mite dma channel for counter.");
+		dev_err(dev->class_dev,
+			"failed to reserve mite dma channel for counter\n");
 		return -EBUSY;
 	}
 	mite_chan->dir = direction;
@@ -561,8 +832,8 @@ static int ni_request_cdo_mite_channel(s
 	    mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring);
 	if (devpriv->cdo_mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev,
-			     "failed to reserve mite dma channel for correlated digital outut.");
+		dev_err(dev->class_dev,
+			"failed to reserve mite dma channel for correlated digital output\n");
 		return -EBUSY;
 	}
 	devpriv->cdo_mite_chan->dir = COMEDI_OUTPUT;
@@ -643,100 +914,71 @@ static void ni_release_cdo_mite_channel(
 #endif /*  PCIDMA */
 }
 
-/* e-series boards use the second irq signals to generate dma requests for their counters */
 #ifdef PCIDMA
 static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 					  unsigned gpct_index, short enable)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
+	uint16_t val = 0;
+	int reg;
 
-	if (board->reg_type & ni_reg_m_series_mask)
+	if (devpriv->is_m_series || gpct_index > 1)
 		return;
-	switch (gpct_index) {
-	case 0:
-		if (enable) {
-			devpriv->stc_writew(dev, G0_Gate_Second_Irq_Enable,
-					    Second_IRQ_A_Enable_Register);
-		} else {
-			devpriv->stc_writew(dev, 0,
-					    Second_IRQ_A_Enable_Register);
-		}
-		break;
-	case 1:
-		if (enable) {
-			devpriv->stc_writew(dev, G1_Gate_Second_Irq_Enable,
-					    Second_IRQ_B_Enable_Register);
-		} else {
-			devpriv->stc_writew(dev, 0,
-					    Second_IRQ_B_Enable_Register);
-		}
-		break;
-	default:
-		BUG();
-		break;
+
+	/*
+	 * e-series boards use the second irq signals to generate
+	 * dma requests for their counters
+	 */
+	if (gpct_index == 0) {
+		reg = Second_IRQ_A_Enable_Register;
+		if (enable)
+			val = G0_Gate_Second_Irq_Enable;
+	} else {
+		reg = Second_IRQ_B_Enable_Register;
+		if (enable)
+			val = G1_Gate_Second_Irq_Enable;
 	}
+	ni_stc_writew(dev, val, reg);
 }
 #endif /*  PCIDMA */
 
 static void ni_clear_ai_fifo(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	static const int timeout = 10000;
 	int i;
 
-	if (board->reg_type == ni_reg_6143) {
+	if (devpriv->is_6143) {
 		/*  Flush the 6143 data FIFO */
-		ni_writel(0x10, AIFIFO_Control_6143);	/*  Flush fifo */
-		ni_writel(0x00, AIFIFO_Control_6143);	/*  Flush fifo */
+		ni_writel(dev, 0x10, AIFIFO_Control_6143);
+		ni_writel(dev, 0x00, AIFIFO_Control_6143);
 		/*  Wait for complete */
 		for (i = 0; i < timeout; i++) {
-			if (!(ni_readl(AIFIFO_Status_6143) & 0x10))
+			if (!(ni_readl(dev, AIFIFO_Status_6143) & 0x10))
 				break;
 			udelay(1);
 		}
-		if (i == timeout) {
-			comedi_error(dev, "FIFO flush timeout.");
-		}
+		if (i == timeout)
+			dev_err(dev->class_dev, "FIFO flush timeout\n");
 	} else {
-		devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
-		if (board->reg_type == ni_reg_625x) {
-			ni_writeb(0, M_Offset_Static_AI_Control(0));
-			ni_writeb(1, M_Offset_Static_AI_Control(0));
+		ni_stc_writew(dev, 1, ADC_FIFO_Clear);
+		if (devpriv->is_625x) {
+			ni_writeb(dev, 0, M_Offset_Static_AI_Control(0));
+			ni_writeb(dev, 1, M_Offset_Static_AI_Control(0));
 #if 0
 			/* the NI example code does 3 convert pulses for 625x boards,
 			   but that appears to be wrong in practice. */
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
 #endif
 		}
 	}
 }
 
-static void win_out2(struct comedi_device *dev, uint32_t data, int reg)
-{
-	struct ni_private *devpriv = dev->private;
-
-	devpriv->stc_writew(dev, data >> 16, reg);
-	devpriv->stc_writew(dev, data & 0xffff, reg + 1);
-}
-
-static uint32_t win_in2(struct comedi_device *dev, int reg)
-{
-	struct ni_private *devpriv = dev->private;
-	uint32_t bits;
-
-	bits = devpriv->stc_readw(dev, reg) << 16;
-	bits |= devpriv->stc_readw(dev, reg + 1);
-	return bits;
-}
-
-#define ao_win_out(data, addr) ni_ao_win_outw(dev, data, addr)
 static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data,
 				  int addr)
 {
@@ -744,8 +986,8 @@ static inline void ni_ao_win_outw(struct
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
-	ni_writew(addr, AO_Window_Address_611x);
-	ni_writew(data, AO_Window_Data_611x);
+	ni_writew(dev, addr, AO_Window_Address_611x);
+	ni_writew(dev, data, AO_Window_Data_611x);
 	spin_unlock_irqrestore(&devpriv->window_lock, flags);
 }
 
@@ -756,8 +998,8 @@ static inline void ni_ao_win_outl(struct
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
-	ni_writew(addr, AO_Window_Address_611x);
-	ni_writel(data, AO_Window_Data_611x);
+	ni_writew(dev, addr, AO_Window_Address_611x);
+	ni_writel(dev, data, AO_Window_Data_611x);
 	spin_unlock_irqrestore(&devpriv->window_lock, flags);
 }
 
@@ -768,8 +1010,8 @@ static inline unsigned short ni_ao_win_i
 	unsigned short data;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
-	ni_writew(addr, AO_Window_Address_611x);
-	data = ni_readw(AO_Window_Data_611x);
+	ni_writew(dev, addr, AO_Window_Address_611x);
+	data = ni_readw(dev, AO_Window_Data_611x);
 	spin_unlock_irqrestore(&devpriv->window_lock, flags);
 	return data;
 }
@@ -796,83 +1038,58 @@ static inline void ni_set_bits(struct co
 	ni_set_bitfield(dev, reg, bits, bit_values);
 }
 
-static irqreturn_t ni_E_interrupt(int irq, void *d)
+#ifdef PCIDMA
+static void ni_sync_ai_dma(struct comedi_device *dev)
 {
-	struct comedi_device *dev = d;
 	struct ni_private *devpriv = dev->private;
-	unsigned short a_status;
-	unsigned short b_status;
-	unsigned int ai_mite_status = 0;
-	unsigned int ao_mite_status = 0;
+	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned long flags;
-#ifdef PCIDMA
-	struct mite_struct *mite = devpriv->mite;
-#endif
-
-	if (!dev->attached)
-		return IRQ_NONE;
-	smp_mb();		/*  make sure dev->attached is checked before handler does anything else. */
-
-	/*  lock to avoid race with comedi_poll */
-	spin_lock_irqsave(&dev->spinlock, flags);
-	a_status = devpriv->stc_readw(dev, AI_Status_1_Register);
-	b_status = devpriv->stc_readw(dev, AO_Status_1_Register);
-#ifdef PCIDMA
-	if (mite) {
-		unsigned long flags_too;
-
-		spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
-		if (devpriv->ai_mite_chan) {
-			ai_mite_status = mite_get_status(devpriv->ai_mite_chan);
-			if (ai_mite_status & CHSR_LINKC)
-				writel(CHOR_CLRLC,
-				       devpriv->mite->mite_io_addr +
-				       MITE_CHOR(devpriv->
-						 ai_mite_chan->channel));
-		}
-		if (devpriv->ao_mite_chan) {
-			ao_mite_status = mite_get_status(devpriv->ao_mite_chan);
-			if (ao_mite_status & CHSR_LINKC)
-				writel(CHOR_CLRLC,
-				       mite->mite_io_addr +
-				       MITE_CHOR(devpriv->
-						 ao_mite_chan->channel));
-		}
-		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too);
-	}
-#endif
-	ack_a_interrupt(dev, a_status);
-	ack_b_interrupt(dev, b_status);
-	if ((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT))
-		handle_a_interrupt(dev, a_status, ai_mite_status);
-	if ((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT))
-		handle_b_interrupt(dev, b_status, ao_mite_status);
-	handle_gpct_interrupt(dev, 0);
-	handle_gpct_interrupt(dev, 1);
-	handle_cdio_interrupt(dev);
 
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-	return IRQ_HANDLED;
+	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+	if (devpriv->ai_mite_chan)
+		mite_sync_input_dma(devpriv->ai_mite_chan, s);
+	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 }
 
-#ifdef PCIDMA
-static void ni_sync_ai_dma(struct comedi_device *dev)
+static int ni_ai_drain_dma(struct comedi_device *dev)
 {
 	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	int i;
+	static const int timeout = 10000;
 	unsigned long flags;
+	int retval = 0;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
-	if (devpriv->ai_mite_chan)
-		mite_sync_input_dma(devpriv->ai_mite_chan, s);
+	if (devpriv->ai_mite_chan) {
+		for (i = 0; i < timeout; i++) {
+			if ((ni_stc_readw(dev, AI_Status_1_Register) &
+			     AI_FIFO_Empty_St)
+			    && mite_bytes_in_transit(devpriv->ai_mite_chan) ==
+			    0)
+				break;
+			udelay(5);
+		}
+		if (i == timeout) {
+			dev_err(dev->class_dev, "%s timed out\n", __func__);
+			dev_err(dev->class_dev,
+				"mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
+				mite_bytes_in_transit(devpriv->ai_mite_chan),
+				ni_stc_readw(dev, AI_Status_1_Register));
+			retval = -1;
+		}
+	}
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+
+	ni_sync_ai_dma(dev);
+
+	return retval;
 }
 
 static void mite_handle_b_linkc(struct mite_struct *mite,
 				struct comedi_device *dev)
 {
 	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
+	struct comedi_subdevice *s = dev->write_subdev;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -883,13 +1100,13 @@ static void mite_handle_b_linkc(struct m
 
 static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
 {
-	struct ni_private *devpriv = dev->private;
 	static const int timeout = 10000;
 	int i;
+
 	for (i = 0; i < timeout; i++) {
 		unsigned short b_status;
 
-		b_status = devpriv->stc_readw(dev, AO_Status_1_Register);
+		b_status = ni_stc_readw(dev, AO_Status_1_Register);
 		if (b_status & AO_FIFO_Half_Full_St)
 			break;
 		/* if we poll too often, the pci bus activity seems
@@ -897,247 +1114,19 @@ static int ni_ao_wait_for_dma_load(struc
 		udelay(10);
 	}
 	if (i == timeout) {
-		comedi_error(dev, "timed out waiting for dma load");
+		dev_err(dev->class_dev, "timed out waiting for dma load\n");
 		return -EPIPE;
 	}
 	return 0;
 }
-
 #endif /* PCIDMA */
-static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct ni_private *devpriv = dev->private;
-
-	if (devpriv->aimode == AIMODE_SCAN) {
-#ifdef PCIDMA
-		static const int timeout = 10;
-		int i;
-
-		for (i = 0; i < timeout; i++) {
-			ni_sync_ai_dma(dev);
-			if ((s->async->events & COMEDI_CB_EOS))
-				break;
-			udelay(1);
-		}
-#else
-		ni_handle_fifo_dregs(dev);
-		s->async->events |= COMEDI_CB_EOS;
-#endif
-	}
-	/* handle special case of single scan using AI_End_On_End_Of_Scan */
-	if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan))
-		shutdown_ai_command(dev);
-}
-
-static void shutdown_ai_command(struct comedi_device *dev)
-{
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
-
-#ifdef PCIDMA
-	ni_ai_drain_dma(dev);
-#endif
-	ni_handle_fifo_dregs(dev);
-	get_last_sample_611x(dev);
-	get_last_sample_6143(dev);
-
-	s->async->events |= COMEDI_CB_EOA;
-}
-
-static void handle_gpct_interrupt(struct comedi_device *dev,
-				  unsigned short counter_index)
-{
-#ifdef PCIDMA
-	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-
-	s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)];
-
-	ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index],
-				s);
-	cfc_handle_events(dev, s);
-#endif
-}
-
-static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned short ack = 0;
-
-	if (a_status & AI_SC_TC_St)
-		ack |= AI_SC_TC_Interrupt_Ack;
-	if (a_status & AI_START1_St)
-		ack |= AI_START1_Interrupt_Ack;
-	if (a_status & AI_START_St)
-		ack |= AI_START_Interrupt_Ack;
-	if (a_status & AI_STOP_St)
-		/* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */
-		ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */;
-	if (ack)
-		devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register);
-}
-
-static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
-			       unsigned ai_mite_status)
-{
-	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
-
-	/* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
-	if (s->type == COMEDI_SUBD_UNUSED)
-		return;
-
-#ifdef PCIDMA
-	if (ai_mite_status & CHSR_LINKC)
-		ni_sync_ai_dma(dev);
-
-	if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
-			       CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
-			       CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) {
-		printk
-		    ("unknown mite interrupt, ack! (ai_mite_status=%08x)\n",
-		     ai_mite_status);
-		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
-		/* disable_irq(dev->irq); */
-	}
-#endif
-
-	/* test for all uncommon interrupt events at the same time */
-	if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St |
-		      AI_SC_TC_St | AI_START1_St)) {
-		if (status == 0xffff) {
-			printk
-			    ("ni_mio_common: a_status=0xffff.  Card removed?\n");
-			/* we probably aren't even running a command now,
-			 * so it's a good idea to be careful. */
-			if (comedi_is_subdevice_running(s)) {
-				s->async->events |=
-				    COMEDI_CB_ERROR | COMEDI_CB_EOA;
-				cfc_handle_events(dev, s);
-			}
-			return;
-		}
-		if (status & (AI_Overrun_St | AI_Overflow_St |
-			      AI_SC_TC_Error_St)) {
-			printk("ni_mio_common: ai error a_status=%04x\n",
-			       status);
-
-			shutdown_ai_command(dev);
-
-			s->async->events |= COMEDI_CB_ERROR;
-			if (status & (AI_Overrun_St | AI_Overflow_St))
-				s->async->events |= COMEDI_CB_OVERFLOW;
-
-			cfc_handle_events(dev, s);
-			return;
-		}
-		if (status & AI_SC_TC_St) {
-			if (!devpriv->ai_continuous)
-				shutdown_ai_command(dev);
-		}
-	}
-#ifndef PCIDMA
-	if (status & AI_FIFO_Half_Full_St) {
-		int i;
-		static const int timeout = 10;
-		/* pcmcia cards (at least 6036) seem to stop producing interrupts if we
-		 *fail to get the fifo less than half full, so loop to be sure.*/
-		for (i = 0; i < timeout; ++i) {
-			ni_handle_fifo_half_full(dev);
-			if ((devpriv->stc_readw(dev,
-						AI_Status_1_Register) &
-			     AI_FIFO_Half_Full_St) == 0)
-				break;
-		}
-	}
-#endif /*  !PCIDMA */
-
-	if ((status & AI_STOP_St))
-		ni_handle_eos(dev, s);
-
-	cfc_handle_events(dev, s);
-}
-
-static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned short ack = 0;
-
-	if (b_status & AO_BC_TC_St)
-		ack |= AO_BC_TC_Interrupt_Ack;
-	if (b_status & AO_Overrun_St)
-		ack |= AO_Error_Interrupt_Ack;
-	if (b_status & AO_START_St)
-		ack |= AO_START_Interrupt_Ack;
-	if (b_status & AO_START1_St)
-		ack |= AO_START1_Interrupt_Ack;
-	if (b_status & AO_UC_TC_St)
-		ack |= AO_UC_TC_Interrupt_Ack;
-	if (b_status & AO_UI2_TC_St)
-		ack |= AO_UI2_TC_Interrupt_Ack;
-	if (b_status & AO_UPDATE_St)
-		ack |= AO_UPDATE_Interrupt_Ack;
-	if (ack)
-		devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register);
-}
-
-static void handle_b_interrupt(struct comedi_device *dev,
-			       unsigned short b_status, unsigned ao_mite_status)
-{
-	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
-	/* unsigned short ack=0; */
-
-#ifdef PCIDMA
-	/* Currently, mite.c requires us to handle LINKC */
-	if (ao_mite_status & CHSR_LINKC)
-		mite_handle_b_linkc(devpriv->mite, dev);
-
-	if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
-			       CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
-			       CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) {
-		printk
-		    ("unknown mite interrupt, ack! (ao_mite_status=%08x)\n",
-		     ao_mite_status);
-		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
-	}
-#endif
-
-	if (b_status == 0xffff)
-		return;
-	if (b_status & AO_Overrun_St) {
-		printk
-		    ("ni_mio_common: AO FIFO underrun status=0x%04x status2=0x%04x\n",
-		     b_status, devpriv->stc_readw(dev, AO_Status_2_Register));
-		s->async->events |= COMEDI_CB_OVERFLOW;
-	}
-
-	if (b_status & AO_BC_TC_St)
-		s->async->events |= COMEDI_CB_EOA;
-
-#ifndef PCIDMA
-	if (b_status & AO_FIFO_Request_St) {
-		int ret;
-
-		ret = ni_ao_fifo_half_empty(dev, s);
-		if (!ret) {
-			printk("ni_mio_common: AO buffer underrun\n");
-			ni_set_bits(dev, Interrupt_B_Enable_Register,
-				    AO_FIFO_Interrupt_Enable |
-				    AO_Error_Interrupt_Enable, 0);
-			s->async->events |= COMEDI_CB_OVERFLOW;
-		}
-	}
-#endif
-
-	cfc_handle_events(dev, s);
-}
 
 #ifndef PCIDMA
 
 static void ni_ao_fifo_load(struct comedi_device *dev,
 			    struct comedi_subdevice *s, int n)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	int chan;
@@ -1155,10 +1144,10 @@ static void ni_ao_fifo_load(struct comed
 
 		range = CR_RANGE(cmd->chanlist[chan]);
 
-		if (board->reg_type & ni_reg_6xxx_mask) {
+		if (devpriv->is_6xxx) {
 			packed_data = d & 0xffff;
 			/* 6711 only has 16 bit wide ao fifo */
-			if (board->reg_type != ni_reg_6711) {
+			if (!devpriv->is_6711) {
 				err &= comedi_buf_get(s, &d);
 				if (err == 0)
 					break;
@@ -1166,9 +1155,9 @@ static void ni_ao_fifo_load(struct comed
 				i++;
 				packed_data |= (d << 16) & 0xffff0000;
 			}
-			ni_writel(packed_data, DAC_FIFO_Data_611x);
+			ni_writel(dev, packed_data, DAC_FIFO_Data_611x);
 		} else {
-			ni_writew(d, DAC_FIFO_Data);
+			ni_writew(dev, d, DAC_FIFO_Data);
 		}
 		chan++;
 		chan %= cmd->chanlist_len;
@@ -1225,8 +1214,8 @@ static int ni_ao_prep_fifo(struct comedi
 	int n;
 
 	/* reset fifo */
-	devpriv->stc_writew(dev, 1, DAC_FIFO_Clear);
-	if (board->reg_type & ni_reg_6xxx_mask)
+	ni_stc_writew(dev, 1, DAC_FIFO_Clear);
+	if (devpriv->is_6xxx)
 		ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
 
 	/* load some data */
@@ -1246,17 +1235,16 @@ static int ni_ao_prep_fifo(struct comedi
 static void ni_ai_fifo_read(struct comedi_device *dev,
 			    struct comedi_subdevice *s, int n)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	int i;
 
-	if (board->reg_type == ni_reg_611x) {
+	if (devpriv->is_611x) {
 		unsigned short data[2];
 		u32 dl;
 
 		for (i = 0; i < n / 2; i++) {
-			dl = ni_readl(ADC_FIFO_Data_611x);
+			dl = ni_readl(dev, ADC_FIFO_Data_611x);
 			/* This may get the hi/lo data in the wrong order */
 			data[0] = (dl >> 16) & 0xffff;
 			data[1] = dl & 0xffff;
@@ -1264,17 +1252,17 @@ static void ni_ai_fifo_read(struct comed
 		}
 		/* Check if there's a single sample stuck in the FIFO */
 		if (n % 2) {
-			dl = ni_readl(ADC_FIFO_Data_611x);
+			dl = ni_readl(dev, ADC_FIFO_Data_611x);
 			data[0] = dl & 0xffff;
 			cfc_write_to_buffer(s, data[0]);
 		}
-	} else if (board->reg_type == ni_reg_6143) {
+	} else if (devpriv->is_6143) {
 		unsigned short data[2];
 		u32 dl;
 
 		/*  This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */
 		for (i = 0; i < n / 2; i++) {
-			dl = ni_readl(AIFIFO_Data_6143);
+			dl = ni_readl(dev, AIFIFO_Data_6143);
 
 			data[0] = (dl >> 16) & 0xffff;
 			data[1] = dl & 0xffff;
@@ -1282,21 +1270,23 @@ static void ni_ai_fifo_read(struct comed
 		}
 		if (n % 2) {
 			/* Assume there is a single sample stuck in the FIFO */
-			ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
-			dl = ni_readl(AIFIFO_Data_6143);
+			/* Get stranded sample into FIFO */
+			ni_writel(dev, 0x01, AIFIFO_Control_6143);
+			dl = ni_readl(dev, AIFIFO_Data_6143);
 			data[0] = (dl >> 16) & 0xffff;
 			cfc_write_to_buffer(s, data[0]);
 		}
 	} else {
 		if (n > sizeof(devpriv->ai_fifo_buffer) /
 		    sizeof(devpriv->ai_fifo_buffer[0])) {
-			comedi_error(dev, "bug! ai_fifo_buffer too small");
+			dev_err(dev->class_dev,
+				"bug! ai_fifo_buffer too small\n");
 			async->events |= COMEDI_CB_ERROR;
 			return;
 		}
 		for (i = 0; i < n; i++) {
 			devpriv->ai_fifo_buffer[i] =
-			    ni_readw(ADC_FIFO_Data_Register);
+			    ni_readw(dev, ADC_FIFO_Data_Register);
 		}
 		cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer,
 					  n *
@@ -1307,7 +1297,7 @@ static void ni_ai_fifo_read(struct comed
 static void ni_handle_fifo_half_full(struct comedi_device *dev)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	struct comedi_subdevice *s = dev->read_subdev;
 	int n;
 
 	n = board->ai_fifo_depth / 2;
@@ -1316,70 +1306,32 @@ static void ni_handle_fifo_half_full(str
 }
 #endif
 
-#ifdef PCIDMA
-static int ni_ai_drain_dma(struct comedi_device *dev)
-{
-	struct ni_private *devpriv = dev->private;
-	int i;
-	static const int timeout = 10000;
-	unsigned long flags;
-	int retval = 0;
-
-	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
-	if (devpriv->ai_mite_chan) {
-		for (i = 0; i < timeout; i++) {
-			if ((devpriv->stc_readw(dev,
-						AI_Status_1_Register) &
-			     AI_FIFO_Empty_St)
-			    && mite_bytes_in_transit(devpriv->ai_mite_chan) ==
-			    0)
-				break;
-			udelay(5);
-		}
-		if (i == timeout) {
-			printk("ni_mio_common: wait for dma drain timed out\n");
-			printk
-			    ("mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
-			     mite_bytes_in_transit(devpriv->ai_mite_chan),
-			     devpriv->stc_readw(dev, AI_Status_1_Register));
-			retval = -1;
-		}
-	}
-	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-
-	ni_sync_ai_dma(dev);
-
-	return retval;
-}
-#endif
 /*
    Empties the AI fifo
 */
 static void ni_handle_fifo_dregs(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned short data[2];
 	u32 dl;
 	unsigned short fifo_empty;
 	int i;
 
-	if (board->reg_type == ni_reg_611x) {
-		while ((devpriv->stc_readw(dev,
-					   AI_Status_1_Register) &
+	if (devpriv->is_611x) {
+		while ((ni_stc_readw(dev, AI_Status_1_Register) &
 			AI_FIFO_Empty_St) == 0) {
-			dl = ni_readl(ADC_FIFO_Data_611x);
+			dl = ni_readl(dev, ADC_FIFO_Data_611x);
 
 			/* This may get the hi/lo data in the wrong order */
 			data[0] = (dl >> 16);
 			data[1] = (dl & 0xffff);
 			cfc_write_array_to_buffer(s, data, sizeof(data));
 		}
-	} else if (board->reg_type == ni_reg_6143) {
+	} else if (devpriv->is_6143) {
 		i = 0;
-		while (ni_readl(AIFIFO_Status_6143) & 0x04) {
-			dl = ni_readl(AIFIFO_Data_6143);
+		while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) {
+			dl = ni_readl(dev, AIFIFO_Data_6143);
 
 			/* This may get the hi/lo data in the wrong order */
 			data[0] = (dl >> 16);
@@ -1388,30 +1340,29 @@ static void ni_handle_fifo_dregs(struct
 			i += 2;
 		}
 		/*  Check if stranded sample is present */
-		if (ni_readl(AIFIFO_Status_6143) & 0x01) {
-			ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
-			dl = ni_readl(AIFIFO_Data_6143);
+		if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+			/* Get stranded sample into FIFO */
+			ni_writel(dev, 0x01, AIFIFO_Control_6143);
+			dl = ni_readl(dev, AIFIFO_Data_6143);
 			data[0] = (dl >> 16) & 0xffff;
 			cfc_write_to_buffer(s, data[0]);
 		}
 
 	} else {
-		fifo_empty =
-		    devpriv->stc_readw(dev,
-				       AI_Status_1_Register) & AI_FIFO_Empty_St;
+		fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) &
+			     AI_FIFO_Empty_St;
 		while (fifo_empty == 0) {
 			for (i = 0;
 			     i <
 			     sizeof(devpriv->ai_fifo_buffer) /
 			     sizeof(devpriv->ai_fifo_buffer[0]); i++) {
-				fifo_empty =
-				    devpriv->stc_readw(dev,
-						       AI_Status_1_Register) &
-				    AI_FIFO_Empty_St;
+				fifo_empty = ni_stc_readw(dev,
+							  AI_Status_1_Register) &
+						AI_FIFO_Empty_St;
 				if (fifo_empty)
 					break;
 				devpriv->ai_fifo_buffer[i] =
-				    ni_readw(ADC_FIFO_Data_Register);
+				    ni_readw(dev, ADC_FIFO_Data_Register);
 			}
 			cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer,
 						  i *
@@ -1423,18 +1374,17 @@ static void ni_handle_fifo_dregs(struct
 
 static void get_last_sample_611x(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv __maybe_unused = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	struct ni_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned short data;
 	u32 dl;
 
-	if (board->reg_type != ni_reg_611x)
+	if (!devpriv->is_611x)
 		return;
 
 	/* Check if there's a single sample stuck in the FIFO */
-	if (ni_readb(XXX_Status) & 0x80) {
-		dl = ni_readl(ADC_FIFO_Data_611x);
+	if (ni_readb(dev, XXX_Status) & 0x80) {
+		dl = ni_readl(dev, ADC_FIFO_Data_611x);
 		data = (dl & 0xffff);
 		cfc_write_to_buffer(s, data);
 	}
@@ -1442,19 +1392,19 @@ static void get_last_sample_611x(struct
 
 static void get_last_sample_6143(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv __maybe_unused = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	struct ni_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned short data;
 	u32 dl;
 
-	if (board->reg_type != ni_reg_6143)
+	if (!devpriv->is_6143)
 		return;
 
 	/* Check if there's a single sample stuck in the FIFO */
-	if (ni_readl(AIFIFO_Status_6143) & 0x01) {
-		ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
-		dl = ni_readl(AIFIFO_Data_6143);
+	if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+		/* Get stranded sample into FIFO */
+		ni_writel(dev, 0x01, AIFIFO_Control_6143);
+		dl = ni_readl(dev, AIFIFO_Data_6143);
 
 		/* This may get the hi/lo data in the wrong order */
 		data = (dl >> 16) & 0xffff;
@@ -1462,6 +1412,232 @@ static void get_last_sample_6143(struct
 	}
 }
 
+static void shutdown_ai_command(struct comedi_device *dev)
+{
+	struct comedi_subdevice *s = dev->read_subdev;
+
+#ifdef PCIDMA
+	ni_ai_drain_dma(dev);
+#endif
+	ni_handle_fifo_dregs(dev);
+	get_last_sample_611x(dev);
+	get_last_sample_6143(dev);
+
+	s->async->events |= COMEDI_CB_EOA;
+}
+
+static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct ni_private *devpriv = dev->private;
+
+	if (devpriv->aimode == AIMODE_SCAN) {
+#ifdef PCIDMA
+		static const int timeout = 10;
+		int i;
+
+		for (i = 0; i < timeout; i++) {
+			ni_sync_ai_dma(dev);
+			if ((s->async->events & COMEDI_CB_EOS))
+				break;
+			udelay(1);
+		}
+#else
+		ni_handle_fifo_dregs(dev);
+		s->async->events |= COMEDI_CB_EOS;
+#endif
+	}
+	/* handle special case of single scan using AI_End_On_End_Of_Scan */
+	if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan))
+		shutdown_ai_command(dev);
+}
+
+static void handle_gpct_interrupt(struct comedi_device *dev,
+				  unsigned short counter_index)
+{
+#ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+
+	s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)];
+
+	ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index],
+				s);
+	cfc_handle_events(dev, s);
+#endif
+}
+
+static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
+{
+	unsigned short ack = 0;
+
+	if (a_status & AI_SC_TC_St)
+		ack |= AI_SC_TC_Interrupt_Ack;
+	if (a_status & AI_START1_St)
+		ack |= AI_START1_Interrupt_Ack;
+	if (a_status & AI_START_St)
+		ack |= AI_START_Interrupt_Ack;
+	if (a_status & AI_STOP_St)
+		/* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */
+		ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */;
+	if (ack)
+		ni_stc_writew(dev, ack, Interrupt_A_Ack_Register);
+}
+
+static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
+			       unsigned ai_mite_status)
+{
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_cmd *cmd = &s->async->cmd;
+
+	/* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
+	if (s->type == COMEDI_SUBD_UNUSED)
+		return;
+
+#ifdef PCIDMA
+	if (ai_mite_status & CHSR_LINKC)
+		ni_sync_ai_dma(dev);
+
+	if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
+			       CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
+			       CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) {
+		dev_err(dev->class_dev,
+			"unknown mite interrupt (ai_mite_status=%08x)\n",
+			ai_mite_status);
+		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+		/* disable_irq(dev->irq); */
+	}
+#endif
+
+	/* test for all uncommon interrupt events at the same time */
+	if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St |
+		      AI_SC_TC_St | AI_START1_St)) {
+		if (status == 0xffff) {
+			dev_err(dev->class_dev, "Card removed?\n");
+			/* we probably aren't even running a command now,
+			 * so it's a good idea to be careful. */
+			if (comedi_is_subdevice_running(s)) {
+				s->async->events |=
+				    COMEDI_CB_ERROR | COMEDI_CB_EOA;
+				cfc_handle_events(dev, s);
+			}
+			return;
+		}
+		if (status & (AI_Overrun_St | AI_Overflow_St |
+			      AI_SC_TC_Error_St)) {
+			dev_err(dev->class_dev, "ai error a_status=%04x\n",
+				status);
+
+			shutdown_ai_command(dev);
+
+			s->async->events |= COMEDI_CB_ERROR;
+			if (status & (AI_Overrun_St | AI_Overflow_St))
+				s->async->events |= COMEDI_CB_OVERFLOW;
+
+			cfc_handle_events(dev, s);
+			return;
+		}
+		if (status & AI_SC_TC_St) {
+			if (cmd->stop_src == TRIG_COUNT)
+				shutdown_ai_command(dev);
+		}
+	}
+#ifndef PCIDMA
+	if (status & AI_FIFO_Half_Full_St) {
+		int i;
+		static const int timeout = 10;
+		/* pcmcia cards (at least 6036) seem to stop producing interrupts if we
+		 *fail to get the fifo less than half full, so loop to be sure.*/
+		for (i = 0; i < timeout; ++i) {
+			ni_handle_fifo_half_full(dev);
+			if ((ni_stc_readw(dev, AI_Status_1_Register) &
+			     AI_FIFO_Half_Full_St) == 0)
+				break;
+		}
+	}
+#endif /*  !PCIDMA */
+
+	if ((status & AI_STOP_St))
+		ni_handle_eos(dev, s);
+
+	cfc_handle_events(dev, s);
+}
+
+static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
+{
+	unsigned short ack = 0;
+
+	if (b_status & AO_BC_TC_St)
+		ack |= AO_BC_TC_Interrupt_Ack;
+	if (b_status & AO_Overrun_St)
+		ack |= AO_Error_Interrupt_Ack;
+	if (b_status & AO_START_St)
+		ack |= AO_START_Interrupt_Ack;
+	if (b_status & AO_START1_St)
+		ack |= AO_START1_Interrupt_Ack;
+	if (b_status & AO_UC_TC_St)
+		ack |= AO_UC_TC_Interrupt_Ack;
+	if (b_status & AO_UI2_TC_St)
+		ack |= AO_UI2_TC_Interrupt_Ack;
+	if (b_status & AO_UPDATE_St)
+		ack |= AO_UPDATE_Interrupt_Ack;
+	if (ack)
+		ni_stc_writew(dev, ack, Interrupt_B_Ack_Register);
+}
+
+static void handle_b_interrupt(struct comedi_device *dev,
+			       unsigned short b_status, unsigned ao_mite_status)
+{
+	struct comedi_subdevice *s = dev->write_subdev;
+	/* unsigned short ack=0; */
+
+#ifdef PCIDMA
+	/* Currently, mite.c requires us to handle LINKC */
+	if (ao_mite_status & CHSR_LINKC) {
+		struct ni_private *devpriv = dev->private;
+
+		mite_handle_b_linkc(devpriv->mite, dev);
+	}
+
+	if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
+			       CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
+			       CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) {
+		dev_err(dev->class_dev,
+			"unknown mite interrupt (ao_mite_status=%08x)\n",
+			ao_mite_status);
+		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
+	}
+#endif
+
+	if (b_status == 0xffff)
+		return;
+	if (b_status & AO_Overrun_St) {
+		dev_err(dev->class_dev,
+			"AO FIFO underrun status=0x%04x status2=0x%04x\n",
+			b_status, ni_stc_readw(dev, AO_Status_2_Register));
+		s->async->events |= COMEDI_CB_OVERFLOW;
+	}
+
+	if (b_status & AO_BC_TC_St)
+		s->async->events |= COMEDI_CB_EOA;
+
+#ifndef PCIDMA
+	if (b_status & AO_FIFO_Request_St) {
+		int ret;
+
+		ret = ni_ao_fifo_half_empty(dev, s);
+		if (!ret) {
+			dev_err(dev->class_dev, "AO buffer underrun\n");
+			ni_set_bits(dev, Interrupt_B_Enable_Register,
+				    AO_FIFO_Interrupt_Enable |
+				    AO_Error_Interrupt_Enable, 0);
+			s->async->events |= COMEDI_CB_OVERFLOW;
+		}
+	}
+#endif
+
+	cfc_handle_events(dev, s);
+}
+
 static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 			void *data, unsigned int num_bytes,
 			unsigned int chan_index)
@@ -1494,16 +1670,14 @@ static void ni_ai_munge(struct comedi_de
 
 static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	struct comedi_subdevice *s = dev->read_subdev;
 	int retval;
 	unsigned long flags;
 
 	retval = ni_request_ai_mite_channel(dev);
 	if (retval)
 		return retval;
-/* printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel); */
 
 	/* write alloc the entire buffer */
 	comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
@@ -1514,18 +1688,13 @@ static int ni_ai_setup_MITE_dma(struct c
 		return -EIO;
 	}
 
-	switch (board->reg_type) {
-	case ni_reg_611x:
-	case ni_reg_6143:
+	if (devpriv->is_611x || devpriv->is_6143)
 		mite_prep_dma(devpriv->ai_mite_chan, 32, 16);
-		break;
-	case ni_reg_628x:
+	else if (devpriv->is_628x)
 		mite_prep_dma(devpriv->ai_mite_chan, 32, 32);
-		break;
-	default:
+	else
 		mite_prep_dma(devpriv->ai_mite_chan, 16, 16);
-		break;
-	}
+
 	/*start the MITE */
 	mite_dma_arm(devpriv->ai_mite_chan);
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
@@ -1535,9 +1704,8 @@ static int ni_ai_setup_MITE_dma(struct c
 
 static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
+	struct comedi_subdevice *s = dev->write_subdev;
 	int retval;
 	unsigned long flags;
 
@@ -1550,7 +1718,7 @@ static int ni_ao_setup_MITE_dma(struct c
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 	if (devpriv->ao_mite_chan) {
-		if (board->reg_type & (ni_reg_611x | ni_reg_6713)) {
+		if (devpriv->is_611x || devpriv->is_6713) {
 			mite_prep_dma(devpriv->ao_mite_chan, 32, 32);
 		} else {
 			/* doing 32 instead of 16 bit wide transfers from memory
@@ -1575,13 +1743,12 @@ static int ni_ao_setup_MITE_dma(struct c
 
 static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	ni_release_ai_mite_channel(dev);
 	/* ai configuration */
-	devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset,
-			    Joint_Reset_Register);
+	ni_stc_writew(dev, AI_Configuration_Start | AI_Reset,
+		      Joint_Reset_Register);
 
 	ni_set_bits(dev, Interrupt_A_Enable_Register,
 		    AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable |
@@ -1591,56 +1758,58 @@ static int ni_ai_reset(struct comedi_dev
 
 	ni_clear_ai_fifo(dev);
 
-	if (board->reg_type != ni_reg_6143)
-		ni_writeb(0, Misc_Command);
+	if (!devpriv->is_6143)
+		ni_writeb(dev, 0, Misc_Command);
 
-	devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register);	/* reset pulses */
-	devpriv->stc_writew(dev,
-			    AI_Start_Stop | AI_Mode_1_Reserved
-			    /*| AI_Trigger_Once */ ,
-			    AI_Mode_1_Register);
-	devpriv->stc_writew(dev, 0x0000, AI_Mode_2_Register);
+	ni_stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */
+	ni_stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved
+			    /*| AI_Trigger_Once */,
+		      AI_Mode_1_Register);
+	ni_stc_writew(dev, 0x0000, AI_Mode_2_Register);
 	/* generate FIFO interrupts on non-empty */
-	devpriv->stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register);
-	if (board->reg_type == ni_reg_611x) {
-		devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width |
-				    AI_SOC_Polarity |
-				    AI_LOCALMUX_CLK_Pulse_Width,
-				    AI_Personal_Register);
-		devpriv->stc_writew(dev,
-				    AI_SCAN_IN_PROG_Output_Select(3) |
-				    AI_EXTMUX_CLK_Output_Select(0) |
-				    AI_LOCALMUX_CLK_Output_Select(2) |
-				    AI_SC_TC_Output_Select(3) |
-				    AI_CONVERT_Output_Select
-				    (AI_CONVERT_Output_Enable_High),
-				    AI_Output_Control_Register);
-	} else if (board->reg_type == ni_reg_6143) {
-		devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width |
-				    AI_SOC_Polarity |
-				    AI_LOCALMUX_CLK_Pulse_Width,
-				    AI_Personal_Register);
-		devpriv->stc_writew(dev,
-				    AI_SCAN_IN_PROG_Output_Select(3) |
-				    AI_EXTMUX_CLK_Output_Select(0) |
-				    AI_LOCALMUX_CLK_Output_Select(2) |
-				    AI_SC_TC_Output_Select(3) |
-				    AI_CONVERT_Output_Select
-				    (AI_CONVERT_Output_Enable_Low),
-				    AI_Output_Control_Register);
+	ni_stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register);
+	if (devpriv->is_611x) {
+		ni_stc_writew(dev,
+			      AI_SHIFTIN_Pulse_Width |
+			      AI_SOC_Polarity |
+			      AI_LOCALMUX_CLK_Pulse_Width,
+			      AI_Personal_Register);
+		ni_stc_writew(dev,
+			      AI_SCAN_IN_PROG_Output_Select(3) |
+			      AI_EXTMUX_CLK_Output_Select(0) |
+			      AI_LOCALMUX_CLK_Output_Select(2) |
+			      AI_SC_TC_Output_Select(3) |
+			      AI_CONVERT_Output_Select
+			      (AI_CONVERT_Output_Enable_High),
+			      AI_Output_Control_Register);
+	} else if (devpriv->is_6143) {
+		ni_stc_writew(dev, AI_SHIFTIN_Pulse_Width |
+				   AI_SOC_Polarity |
+				   AI_LOCALMUX_CLK_Pulse_Width,
+			      AI_Personal_Register);
+		ni_stc_writew(dev,
+			      AI_SCAN_IN_PROG_Output_Select(3) |
+			      AI_EXTMUX_CLK_Output_Select(0) |
+			      AI_LOCALMUX_CLK_Output_Select(2) |
+			      AI_SC_TC_Output_Select(3) |
+			      AI_CONVERT_Output_Select
+			      (AI_CONVERT_Output_Enable_Low),
+			      AI_Output_Control_Register);
 	} else {
 		unsigned ai_output_control_bits;
-		devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width |
-				    AI_SOC_Polarity |
-				    AI_CONVERT_Pulse_Width |
-				    AI_LOCALMUX_CLK_Pulse_Width,
-				    AI_Personal_Register);
+
+		ni_stc_writew(dev,
+			      AI_SHIFTIN_Pulse_Width |
+			      AI_SOC_Polarity |
+			      AI_CONVERT_Pulse_Width |
+			      AI_LOCALMUX_CLK_Pulse_Width,
+			      AI_Personal_Register);
 		ai_output_control_bits =
 		    AI_SCAN_IN_PROG_Output_Select(3) |
 		    AI_EXTMUX_CLK_Output_Select(0) |
 		    AI_LOCALMUX_CLK_Output_Select(2) |
 		    AI_SC_TC_Output_Select(3);
-		if (board->reg_type == ni_reg_622x)
+		if (devpriv->is_622x)
 			ai_output_control_bits |=
 			    AI_CONVERT_Output_Select
 			    (AI_CONVERT_Output_Enable_High);
@@ -1648,8 +1817,8 @@ static int ni_ai_reset(struct comedi_dev
 			ai_output_control_bits |=
 			    AI_CONVERT_Output_Select
 			    (AI_CONVERT_Output_Enable_Low);
-		devpriv->stc_writew(dev, ai_output_control_bits,
-				    AI_Output_Control_Register);
+		ni_stc_writew(dev, ai_output_control_bits,
+			      AI_Output_Control_Register);
 	}
 	/* the following registers should not be changed, because there
 	 * are no backup registers in devpriv.  If you want to change
@@ -1659,9 +1828,17 @@ static int ni_ai_reset(struct comedi_dev
 	 *      AI_Personal_Register
 	 *      AI_Output_Control_Register
 	 */
-	devpriv->stc_writew(dev, AI_SC_TC_Error_Confirm | AI_START_Interrupt_Ack | AI_START2_Interrupt_Ack | AI_START1_Interrupt_Ack | AI_SC_TC_Interrupt_Ack | AI_Error_Interrupt_Ack | AI_STOP_Interrupt_Ack, Interrupt_A_Ack_Register);	/* clear interrupts */
+	ni_stc_writew(dev,
+		      AI_SC_TC_Error_Confirm |
+		      AI_START_Interrupt_Ack |
+		      AI_START2_Interrupt_Ack |
+		      AI_START1_Interrupt_Ack |
+		      AI_SC_TC_Interrupt_Ack |
+		      AI_Error_Interrupt_Ack |
+		      AI_STOP_Interrupt_Ack,
+		      Interrupt_A_Ack_Register);	/* clear interrupts */
 
-	devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
+	ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
 
 	return 0;
 }
@@ -1678,127 +1855,26 @@ static int ni_ai_poll(struct comedi_devi
 #else
 	ni_sync_ai_dma(dev);
 #endif
-	count = s->async->buf_write_count - s->async->buf_read_count;
+	count = comedi_buf_n_bytes_ready(s);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	return count;
 }
 
-static int ni_ai_insn_read(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
-			   unsigned int *data)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv = dev->private;
-	int i, n;
-	const unsigned int mask = (1 << board->adbits) - 1;
-	unsigned signbits;
-	unsigned short d;
-	unsigned long dl;
-
-	ni_load_channelgain_list(dev, 1, &insn->chanspec);
-
-	ni_clear_ai_fifo(dev);
-
-	signbits = devpriv->ai_offset[0];
-	if (board->reg_type == ni_reg_611x) {
-		for (n = 0; n < num_adc_stages_611x; n++) {
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-			udelay(1);
-		}
-		for (n = 0; n < insn->n; n++) {
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-			/* The 611x has screwy 32-bit FIFOs. */
-			d = 0;
-			for (i = 0; i < NI_TIMEOUT; i++) {
-				if (ni_readb(XXX_Status) & 0x80) {
-					d = (ni_readl(ADC_FIFO_Data_611x) >> 16)
-					    & 0xffff;
-					break;
-				}
-				if (!(devpriv->stc_readw(dev,
-							 AI_Status_1_Register) &
-				      AI_FIFO_Empty_St)) {
-					d = ni_readl(ADC_FIFO_Data_611x) &
-					    0xffff;
-					break;
-				}
-			}
-			if (i == NI_TIMEOUT) {
-				printk
-				    ("ni_mio_common: timeout in 611x ni_ai_insn_read\n");
-				return -ETIME;
-			}
-			d += signbits;
-			data[n] = d;
-		}
-	} else if (board->reg_type == ni_reg_6143) {
-		for (n = 0; n < insn->n; n++) {
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-
-			/* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */
-			dl = 0;
-			for (i = 0; i < NI_TIMEOUT; i++) {
-				if (ni_readl(AIFIFO_Status_6143) & 0x01) {
-					ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
-					dl = ni_readl(AIFIFO_Data_6143);
-					break;
-				}
-			}
-			if (i == NI_TIMEOUT) {
-				printk
-				    ("ni_mio_common: timeout in 6143 ni_ai_insn_read\n");
-				return -ETIME;
-			}
-			data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF;
-		}
-	} else {
-		for (n = 0; n < insn->n; n++) {
-			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
-					    AI_Command_1_Register);
-			for (i = 0; i < NI_TIMEOUT; i++) {
-				if (!(devpriv->stc_readw(dev,
-							 AI_Status_1_Register) &
-				      AI_FIFO_Empty_St))
-					break;
-			}
-			if (i == NI_TIMEOUT) {
-				printk
-				    ("ni_mio_common: timeout in ni_ai_insn_read\n");
-				return -ETIME;
-			}
-			if (board->reg_type & ni_reg_m_series_mask) {
-				data[n] =
-				    ni_readl(M_Offset_AI_FIFO_Data) & mask;
-			} else {
-				d = ni_readw(ADC_FIFO_Data_Register);
-				d += signbits;	/* subtle: needs to be short addition */
-				data[n] = d;
-			}
-		}
-	}
-	return insn->n;
-}
-
 static void ni_prime_channelgain_list(struct comedi_device *dev)
 {
-	struct ni_private *devpriv = dev->private;
 	int i;
 
-	devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
+	ni_stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
 	for (i = 0; i < NI_TIMEOUT; ++i) {
-		if (!(devpriv->stc_readw(dev,
-					 AI_Status_1_Register) &
+		if (!(ni_stc_readw(dev, AI_Status_1_Register) &
 		      AI_FIFO_Empty_St)) {
-			devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
+			ni_stc_writew(dev, 1, ADC_FIFO_Clear);
 			return;
 		}
 		udelay(1);
 	}
-	printk("ni_mio_common: timeout loading channel/gain list\n");
+	dev_err(dev->class_dev, "timeout loading channel/gain list\n");
 }
 
 static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
@@ -1809,15 +1885,14 @@ static void ni_m_series_load_channelgain
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan, range, aref;
 	unsigned int i;
-	unsigned offset;
 	unsigned int dither;
 	unsigned range_code;
 
-	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
+	ni_stc_writew(dev, 1, Configuration_Memory_Clear);
 
-/* offset = 1 << (board->adbits - 1); */
 	if ((list[0] & CR_ALT_SOURCE)) {
 		unsigned bypass_bits;
+
 		chan = CR_CHAN(list[0]);
 		range = CR_RANGE(list[0]);
 		range_code = ni_gainlkup[board->gainlkup][range];
@@ -1835,20 +1910,20 @@ static void ni_m_series_load_channelgain
 			bypass_bits |= MSeries_AI_Bypass_Dither_Bit;
 		/*  don't use 2's complement encoding */
 		bypass_bits |= MSeries_AI_Bypass_Polarity_Bit;
-		ni_writel(bypass_bits, M_Offset_AI_Config_FIFO_Bypass);
+		ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass);
 	} else {
-		ni_writel(0, M_Offset_AI_Config_FIFO_Bypass);
+		ni_writel(dev, 0, M_Offset_AI_Config_FIFO_Bypass);
 	}
-	offset = 0;
 	for (i = 0; i < n_chan; i++) {
 		unsigned config_bits = 0;
+
 		chan = CR_CHAN(list[i]);
 		aref = CR_AREF(list[i]);
 		range = CR_RANGE(list[i]);
 		dither = ((list[i] & CR_ALT_FILTER) != 0);
 
 		range_code = ni_gainlkup[board->gainlkup][range];
-		devpriv->ai_offset[i] = offset;
+		devpriv->ai_offset[i] = 0;
 		switch (aref) {
 		case AREF_DIFF:
 			config_bits |=
@@ -1875,7 +1950,7 @@ static void ni_m_series_load_channelgain
 			config_bits |= MSeries_AI_Config_Dither_Bit;
 		/*  don't use 2's complement encoding */
 		config_bits |= MSeries_AI_Config_Polarity_Bit;
-		ni_writew(config_bits, M_Offset_AI_Config_FIFO_Data);
+		ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data);
 	}
 	ni_prime_channelgain_list(dev);
 }
@@ -1910,22 +1985,22 @@ static void ni_m_series_load_channelgain
  *       valid channels are 0-3
  */
 static void ni_load_channelgain_list(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
 				     unsigned int n_chan, unsigned int *list)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
+	unsigned int offset = (s->maxdata + 1) >> 1;
 	unsigned int chan, range, aref;
 	unsigned int i;
 	unsigned int hi, lo;
-	unsigned offset;
 	unsigned int dither;
 
-	if (board->reg_type & ni_reg_m_series_mask) {
+	if (devpriv->is_m_series) {
 		ni_m_series_load_channelgain_list(dev, n_chan, list);
 		return;
 	}
-	if (n_chan == 1 && (board->reg_type != ni_reg_611x)
-	    && (board->reg_type != ni_reg_6143)) {
+	if (n_chan == 1 && !devpriv->is_611x && !devpriv->is_6143) {
 		if (devpriv->changain_state
 		    && devpriv->changain_spec == list[0]) {
 			/*  ready to go. */
@@ -1937,61 +2012,58 @@ static void ni_load_channelgain_list(str
 		devpriv->changain_state = 0;
 	}
 
-	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
+	ni_stc_writew(dev, 1, Configuration_Memory_Clear);
 
 	/*  Set up Calibration mode if required */
-	if (board->reg_type == ni_reg_6143) {
+	if (devpriv->is_6143) {
 		if ((list[0] & CR_ALT_SOURCE)
 		    && !devpriv->ai_calib_source_enabled) {
 			/*  Strobe Relay enable bit */
-			ni_writew(devpriv->ai_calib_source |
-				  Calibration_Channel_6143_RelayOn,
+			ni_writew(dev, devpriv->ai_calib_source |
+				       Calibration_Channel_6143_RelayOn,
 				  Calibration_Channel_6143);
-			ni_writew(devpriv->ai_calib_source,
+			ni_writew(dev, devpriv->ai_calib_source,
 				  Calibration_Channel_6143);
 			devpriv->ai_calib_source_enabled = 1;
 			msleep_interruptible(100);	/*  Allow relays to change */
 		} else if (!(list[0] & CR_ALT_SOURCE)
 			   && devpriv->ai_calib_source_enabled) {
 			/*  Strobe Relay disable bit */
-			ni_writew(devpriv->ai_calib_source |
-				  Calibration_Channel_6143_RelayOff,
+			ni_writew(dev, devpriv->ai_calib_source |
+				       Calibration_Channel_6143_RelayOff,
 				  Calibration_Channel_6143);
-			ni_writew(devpriv->ai_calib_source,
+			ni_writew(dev, devpriv->ai_calib_source,
 				  Calibration_Channel_6143);
 			devpriv->ai_calib_source_enabled = 0;
 			msleep_interruptible(100);	/*  Allow relays to change */
 		}
 	}
 
-	offset = 1 << (board->adbits - 1);
 	for (i = 0; i < n_chan; i++) {
-		if ((board->reg_type != ni_reg_6143)
-		    && (list[i] & CR_ALT_SOURCE)) {
+		if (!devpriv->is_6143 && (list[i] & CR_ALT_SOURCE))
 			chan = devpriv->ai_calib_source;
-		} else {
+		else
 			chan = CR_CHAN(list[i]);
-		}
 		aref = CR_AREF(list[i]);
 		range = CR_RANGE(list[i]);
 		dither = ((list[i] & CR_ALT_FILTER) != 0);
 
 		/* fix the external/internal range differences */
 		range = ni_gainlkup[board->gainlkup][range];
-		if (board->reg_type == ni_reg_611x)
+		if (devpriv->is_611x)
 			devpriv->ai_offset[i] = offset;
 		else
 			devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset;
 
 		hi = 0;
 		if ((list[i] & CR_ALT_SOURCE)) {
-			if (board->reg_type == ni_reg_611x)
-				ni_writew(CR_CHAN(list[i]) & 0x0003,
+			if (devpriv->is_611x)
+				ni_writew(dev, CR_CHAN(list[i]) & 0x0003,
 					  Calibration_Channel_Select_611x);
 		} else {
-			if (board->reg_type == ni_reg_611x)
+			if (devpriv->is_611x)
 				aref = AREF_DIFF;
-			else if (board->reg_type == ni_reg_6143)
+			else if (devpriv->is_6143)
 				aref = AREF_OTHER;
 			switch (aref) {
 			case AREF_DIFF:
@@ -2009,33 +2081,132 @@ static void ni_load_channelgain_list(str
 		}
 		hi |= AI_CONFIG_CHANNEL(chan);
 
-		ni_writew(hi, Configuration_Memory_High);
+		ni_writew(dev, hi, Configuration_Memory_High);
 
-		if (board->reg_type != ni_reg_6143) {
+		if (!devpriv->is_6143) {
 			lo = range;
 			if (i == n_chan - 1)
 				lo |= AI_LAST_CHANNEL;
 			if (dither)
 				lo |= AI_DITHER;
 
-			ni_writew(lo, Configuration_Memory_Low);
+			ni_writew(dev, lo, Configuration_Memory_Low);
 		}
 	}
 
 	/* prime the channel/gain list */
-	if ((board->reg_type != ni_reg_611x)
-	    && (board->reg_type != ni_reg_6143)) {
+	if (!devpriv->is_611x && !devpriv->is_6143)
 		ni_prime_channelgain_list(dev);
+}
+
+static int ni_ai_insn_read(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
+			   unsigned int *data)
+{
+	struct ni_private *devpriv = dev->private;
+	unsigned int mask = (s->maxdata + 1) >> 1;
+	int i, n;
+	unsigned signbits;
+	unsigned short d;
+	unsigned long dl;
+
+	ni_load_channelgain_list(dev, s, 1, &insn->chanspec);
+
+	ni_clear_ai_fifo(dev);
+
+	signbits = devpriv->ai_offset[0];
+	if (devpriv->is_611x) {
+		for (n = 0; n < num_adc_stages_611x; n++) {
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+			udelay(1);
+		}
+		for (n = 0; n < insn->n; n++) {
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+			/* The 611x has screwy 32-bit FIFOs. */
+			d = 0;
+			for (i = 0; i < NI_TIMEOUT; i++) {
+				if (ni_readb(dev, XXX_Status) & 0x80) {
+					d = ni_readl(dev, ADC_FIFO_Data_611x);
+					d >>= 16;
+					d &= 0xffff;
+					break;
+				}
+				if (!(ni_stc_readw(dev, AI_Status_1_Register) &
+				      AI_FIFO_Empty_St)) {
+					d = ni_readl(dev, ADC_FIFO_Data_611x);
+					d &= 0xffff;
+					break;
+				}
+			}
+			if (i == NI_TIMEOUT) {
+				dev_err(dev->class_dev, "%s timeout\n",
+					__func__);
+				return -ETIME;
+			}
+			d += signbits;
+			data[n] = d;
+		}
+	} else if (devpriv->is_6143) {
+		for (n = 0; n < insn->n; n++) {
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+
+			/* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */
+			dl = 0;
+			for (i = 0; i < NI_TIMEOUT; i++) {
+				if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+					/* Get stranded sample into FIFO */
+					ni_writel(dev, 0x01,
+						  AIFIFO_Control_6143);
+					dl = ni_readl(dev, AIFIFO_Data_6143);
+					break;
+				}
+			}
+			if (i == NI_TIMEOUT) {
+				dev_err(dev->class_dev, "%s timeout\n",
+					__func__);
+				return -ETIME;
+			}
+			data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF;
+		}
+	} else {
+		for (n = 0; n < insn->n; n++) {
+			ni_stc_writew(dev, AI_CONVERT_Pulse,
+				      AI_Command_1_Register);
+			for (i = 0; i < NI_TIMEOUT; i++) {
+				if (!(ni_stc_readw(dev, AI_Status_1_Register) &
+				      AI_FIFO_Empty_St))
+					break;
+			}
+			if (i == NI_TIMEOUT) {
+				dev_err(dev->class_dev, "%s timeout\n",
+					__func__);
+				return -ETIME;
+			}
+			if (devpriv->is_m_series) {
+				dl = ni_readl(dev, M_Offset_AI_FIFO_Data);
+				dl &= mask;
+				data[n] = dl;
+			} else {
+				d = ni_readw(dev, ADC_FIFO_Data_Register);
+				d += signbits;	/* subtle: needs to be short addition */
+				data[n] = d;
+			}
+		}
 	}
+	return insn->n;
 }
 
 static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
-			  int round_mode)
+			  unsigned int flags)
 {
 	struct ni_private *devpriv = dev->private;
 	int divider;
 
-	switch (round_mode) {
+	switch (flags & TRIG_ROUND_MASK) {
 	case TRIG_ROUND_NEAREST:
 	default:
 		divider = (nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns;
@@ -2061,17 +2232,13 @@ static unsigned ni_min_ai_scan_period_ns
 					 unsigned num_channels)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
 
-	switch (board->reg_type) {
-	case ni_reg_611x:
-	case ni_reg_6143:
-		/*  simultaneously-sampled inputs */
+	/* simultaneously-sampled inputs */
+	if (devpriv->is_611x || devpriv->is_6143)
 		return board->ai_speed;
-		break;
-	default:
-		/*  multiplexed inputs */
-		break;
-	}
+
+	/* multiplexed inputs */
 	return board->ai_speed * num_channels;
 }
 
@@ -2095,8 +2262,7 @@ static int ni_ai_cmdtest(struct comedi_d
 					TRIG_TIMER | TRIG_EXT);
 
 	sources = TRIG_TIMER | TRIG_EXT;
-	if (board->reg_type == ni_reg_611x ||
-	    board->reg_type == ni_reg_6143)
+	if (devpriv->is_611x || devpriv->is_6143)
 		sources |= TRIG_NOW;
 	err |= cfc_check_trigger_src(&cmd->convert_src, sources);
 
@@ -2153,8 +2319,7 @@ static int ni_ai_cmdtest(struct comedi_d
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		if ((board->reg_type == ni_reg_611x)
-		    || (board->reg_type == ni_reg_6143)) {
+		if (devpriv->is_611x || devpriv->is_6143) {
 			err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 		} else {
 			err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
@@ -2179,7 +2344,7 @@ static int ni_ai_cmdtest(struct comedi_d
 	if (cmd->stop_src == TRIG_COUNT) {
 		unsigned int max_count = 0x01000000;
 
-		if (board->reg_type == ni_reg_611x)
+		if (devpriv->is_611x)
 			max_count -= num_adc_stages_611x;
 		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count);
 		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
@@ -2198,22 +2363,17 @@ static int ni_ai_cmdtest(struct comedi_d
 		cmd->scan_begin_arg =
 		    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
 						       cmd->scan_begin_arg,
-						       cmd->
-						       flags &
-						       TRIG_ROUND_MASK));
+						       cmd->flags));
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		if ((board->reg_type != ni_reg_611x)
-		    && (board->reg_type != ni_reg_6143)) {
+		if (!devpriv->is_611x && !devpriv->is_6143) {
 			tmp = cmd->convert_arg;
 			cmd->convert_arg =
 			    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
 							       cmd->convert_arg,
-							       cmd->
-							       flags &
-							       TRIG_ROUND_MASK));
+							       cmd->flags));
 			if (tmp != cmd->convert_arg)
 				err++;
 			if (cmd->scan_begin_src == TRIG_TIMER &&
@@ -2232,9 +2392,25 @@ static int ni_ai_cmdtest(struct comedi_d
 	return 0;
 }
 
+static int ni_ai_inttrig(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 unsigned int trig_num)
+{
+	struct ni_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
+
+	if (trig_num != cmd->start_arg)
+		return -EINVAL;
+
+	ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
+		      AI_Command_2_Register);
+	s->async->inttrig = NULL;
+
+	return 1;
+}
+
 static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
@@ -2245,29 +2421,30 @@ static int ni_ai_cmd(struct comedi_devic
 	int interrupt_a_enable = 0;
 
 	if (dev->irq == 0) {
-		comedi_error(dev, "cannot run command without an irq");
+		dev_err(dev->class_dev, "cannot run command without an irq\n");
 		return -EIO;
 	}
 	ni_clear_ai_fifo(dev);
 
-	ni_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
+	ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist);
 
 	/* start configuration */
-	devpriv->stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register);
+	ni_stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register);
 
 	/* disable analog triggering for now, since it
 	 * interferes with the use of pfi0 */
 	devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable;
-	devpriv->stc_writew(dev, devpriv->an_trig_etc_reg,
-			    Analog_Trigger_Etc_Register);
+	ni_stc_writew(dev, devpriv->an_trig_etc_reg,
+		      Analog_Trigger_Etc_Register);
 
 	switch (cmd->start_src) {
 	case TRIG_INT:
 	case TRIG_NOW:
-		devpriv->stc_writew(dev, AI_START2_Select(0) |
-				    AI_START1_Sync | AI_START1_Edge |
-				    AI_START1_Select(0),
-				    AI_Trigger_Select_Register);
+		ni_stc_writew(dev,
+			      AI_START2_Select(0) |
+			      AI_START1_Sync | AI_START1_Edge |
+			      AI_START1_Select(0),
+			      AI_Trigger_Select_Register);
 		break;
 	case TRIG_EXT:
 		{
@@ -2279,8 +2456,7 @@ static int ni_ai_cmd(struct comedi_devic
 				bits |= AI_START1_Polarity;
 			if (cmd->start_arg & CR_EDGE)
 				bits |= AI_START1_Edge;
-			devpriv->stc_writew(dev, bits,
-					    AI_Trigger_Select_Register);
+			ni_stc_writew(dev, bits, AI_Trigger_Select_Register);
 			break;
 		}
 	}
@@ -2288,37 +2464,34 @@ static int ni_ai_cmd(struct comedi_devic
 	mode2 &= ~AI_Pre_Trigger;
 	mode2 &= ~AI_SC_Initial_Load_Source;
 	mode2 &= ~AI_SC_Reload_Mode;
-	devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+	ni_stc_writew(dev, mode2, AI_Mode_2_Register);
 
-	if (cmd->chanlist_len == 1 || (board->reg_type == ni_reg_611x)
-	    || (board->reg_type == ni_reg_6143)) {
+	if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) {
 		start_stop_select |= AI_STOP_Polarity;
 		start_stop_select |= AI_STOP_Select(31);	/*  logic low */
 		start_stop_select |= AI_STOP_Sync;
 	} else {
 		start_stop_select |= AI_STOP_Select(19);	/*  ai configuration memory */
 	}
-	devpriv->stc_writew(dev, start_stop_select,
-			    AI_START_STOP_Select_Register);
+	ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register);
 
 	devpriv->ai_cmd2 = 0;
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
 		stop_count = cmd->stop_arg - 1;
 
-		if (board->reg_type == ni_reg_611x) {
+		if (devpriv->is_611x) {
 			/*  have to take 3 stage adc pipeline into account */
 			stop_count += num_adc_stages_611x;
 		}
 		/* stage number of scans */
-		devpriv->stc_writel(dev, stop_count, AI_SC_Load_A_Registers);
+		ni_stc_writel(dev, stop_count, AI_SC_Load_A_Registers);
 
 		mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once;
-		devpriv->stc_writew(dev, mode1, AI_Mode_1_Register);
+		ni_stc_writew(dev, mode1, AI_Mode_1_Register);
 		/* load SC (Scan Count) */
-		devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
+		ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
 
-		devpriv->ai_continuous = 0;
 		if (stop_count == 0) {
 			devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan;
 			interrupt_a_enable |= AI_STOP_Interrupt_Enable;
@@ -2330,16 +2503,13 @@ static int ni_ai_cmd(struct comedi_devic
 		break;
 	case TRIG_NONE:
 		/* stage number of scans */
-		devpriv->stc_writel(dev, 0, AI_SC_Load_A_Registers);
+		ni_stc_writel(dev, 0, AI_SC_Load_A_Registers);
 
 		mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous;
-		devpriv->stc_writew(dev, mode1, AI_Mode_1_Register);
+		ni_stc_writew(dev, mode1, AI_Mode_1_Register);
 
 		/* load SC (Scan Count) */
-		devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
-
-		devpriv->ai_continuous = 1;
-
+		ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
 		break;
 	}
 
@@ -2360,20 +2530,20 @@ static int ni_ai_cmd(struct comedi_devic
 		   AI_STOP_Select=19            external pin (configuration mem)
 		 */
 		start_stop_select |= AI_START_Edge | AI_START_Sync;
-		devpriv->stc_writew(dev, start_stop_select,
-				    AI_START_STOP_Select_Register);
+		ni_stc_writew(dev, start_stop_select,
+			      AI_START_STOP_Select_Register);
 
 		mode2 |= AI_SI_Reload_Mode(0);
 		/* AI_SI_Initial_Load_Source=A */
 		mode2 &= ~AI_SI_Initial_Load_Source;
 		/* mode2 |= AI_SC_Reload_Mode; */
-		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+		ni_stc_writew(dev, mode2, AI_Mode_2_Register);
 
 		/* load SI */
 		timer = ni_ns_to_timer(dev, cmd->scan_begin_arg,
 				       TRIG_ROUND_NEAREST);
-		devpriv->stc_writel(dev, timer, AI_SI_Load_A_Registers);
-		devpriv->stc_writew(dev, AI_SI_Load, AI_Command_1_Register);
+		ni_stc_writel(dev, timer, AI_SI_Load_A_Registers);
+		ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register);
 		break;
 	case TRIG_EXT:
 		if (cmd->scan_begin_arg & CR_EDGE)
@@ -2387,7 +2557,7 @@ static int ni_ai_cmd(struct comedi_devic
 			start_stop_select |= AI_START_Sync;
 		start_stop_select |=
 		    AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg));
-		devpriv->stc_writew(dev, start_stop_select,
+		ni_stc_writew(dev, start_stop_select,
 				    AI_START_STOP_Select_Register);
 		break;
 	}
@@ -2400,31 +2570,32 @@ static int ni_ai_cmd(struct comedi_devic
 		else
 			timer = ni_ns_to_timer(dev, cmd->convert_arg,
 					       TRIG_ROUND_NEAREST);
-		devpriv->stc_writew(dev, 1, AI_SI2_Load_A_Register);	/* 0,0 does not work. */
-		devpriv->stc_writew(dev, timer, AI_SI2_Load_B_Register);
+		/* 0,0 does not work */
+		ni_stc_writew(dev, 1, AI_SI2_Load_A_Register);
+		ni_stc_writew(dev, timer, AI_SI2_Load_B_Register);
 
 		/* AI_SI2_Reload_Mode = alternate */
 		/* AI_SI2_Initial_Load_Source = A */
 		mode2 &= ~AI_SI2_Initial_Load_Source;
 		mode2 |= AI_SI2_Reload_Mode;
-		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+		ni_stc_writew(dev, mode2, AI_Mode_2_Register);
 
 		/* AI_SI2_Load */
-		devpriv->stc_writew(dev, AI_SI2_Load, AI_Command_1_Register);
+		ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register);
 
 		mode2 |= AI_SI2_Reload_Mode;	/*  alternate */
 		mode2 |= AI_SI2_Initial_Load_Source;	/*  B */
 
-		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+		ni_stc_writew(dev, mode2, AI_Mode_2_Register);
 		break;
 	case TRIG_EXT:
 		mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg);
 		if ((cmd->convert_arg & CR_INVERT) == 0)
 			mode1 |= AI_CONVERT_Source_Polarity;
-		devpriv->stc_writew(dev, mode1, AI_Mode_1_Register);
+		ni_stc_writew(dev, mode1, AI_Mode_1_Register);
 
 		mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable;
-		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+		ni_stc_writew(dev, mode2, AI_Mode_2_Register);
 
 		break;
 	}
@@ -2451,25 +2622,25 @@ static int ni_ai_cmd(struct comedi_devic
 		case AIMODE_HALF_FULL:
 			/*generate FIFO interrupts and DMA requests on half-full */
 #ifdef PCIDMA
-			devpriv->stc_writew(dev, AI_FIFO_Mode_HF_to_E,
-					    AI_Mode_3_Register);
+			ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E,
+				      AI_Mode_3_Register);
 #else
-			devpriv->stc_writew(dev, AI_FIFO_Mode_HF,
-					    AI_Mode_3_Register);
+			ni_stc_writew(dev, AI_FIFO_Mode_HF,
+				      AI_Mode_3_Register);
 #endif
 			break;
 		case AIMODE_SAMPLE:
 			/*generate FIFO interrupts on non-empty */
-			devpriv->stc_writew(dev, AI_FIFO_Mode_NE,
-					    AI_Mode_3_Register);
+			ni_stc_writew(dev, AI_FIFO_Mode_NE,
+				      AI_Mode_3_Register);
 			break;
 		case AIMODE_SCAN:
 #ifdef PCIDMA
-			devpriv->stc_writew(dev, AI_FIFO_Mode_NE,
-					    AI_Mode_3_Register);
+			ni_stc_writew(dev, AI_FIFO_Mode_NE,
+				      AI_Mode_3_Register);
 #else
-			devpriv->stc_writew(dev, AI_FIFO_Mode_HF,
-					    AI_Mode_3_Register);
+			ni_stc_writew(dev, AI_FIFO_Mode_HF,
+				      AI_Mode_3_Register);
 #endif
 			interrupt_a_enable |= AI_STOP_Interrupt_Enable;
 			break;
@@ -2477,7 +2648,16 @@ static int ni_ai_cmd(struct comedi_devic
 			break;
 		}
 
-		devpriv->stc_writew(dev, AI_Error_Interrupt_Ack | AI_STOP_Interrupt_Ack | AI_START_Interrupt_Ack | AI_START2_Interrupt_Ack | AI_START1_Interrupt_Ack | AI_SC_TC_Interrupt_Ack | AI_SC_TC_Error_Confirm, Interrupt_A_Ack_Register);	/* clear interrupts */
+		/* clear interrupts */
+		ni_stc_writew(dev,
+			      AI_Error_Interrupt_Ack |
+			      AI_STOP_Interrupt_Ack |
+			      AI_START_Interrupt_Ack |
+			      AI_START2_Interrupt_Ack |
+			      AI_START1_Interrupt_Ack |
+			      AI_SC_TC_Interrupt_Ack |
+			      AI_SC_TC_Error_Confirm,
+			      Interrupt_A_Ack_Register);
 
 		ni_set_bits(dev, Interrupt_A_Enable_Register,
 			    interrupt_a_enable, 1);
@@ -2489,25 +2669,26 @@ static int ni_ai_cmd(struct comedi_devic
 	}
 
 	/* end configuration */
-	devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
+	ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
 
 	switch (cmd->scan_begin_src) {
 	case TRIG_TIMER:
-		devpriv->stc_writew(dev,
-				    AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm |
-				    AI_SC_Arm, AI_Command_1_Register);
+		ni_stc_writew(dev,
+			      AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,
+			      AI_Command_1_Register);
 		break;
 	case TRIG_EXT:
 		/* XXX AI_SI_Arm? */
-		devpriv->stc_writew(dev,
-				    AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm |
-				    AI_SC_Arm, AI_Command_1_Register);
+		ni_stc_writew(dev,
+			      AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,
+			      AI_Command_1_Register);
 		break;
 	}
 
 #ifdef PCIDMA
 	{
 		int retval = ni_ai_setup_MITE_dma(dev);
+
 		if (retval)
 			return retval;
 	}
@@ -2515,8 +2696,8 @@ static int ni_ai_cmd(struct comedi_devic
 
 	if (cmd->start_src == TRIG_NOW) {
 		/* AI_START1_Pulse */
-		devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
-				    AI_Command_2_Register);
+		ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
+			      AI_Command_2_Register);
 		s->async->inttrig = NULL;
 	} else if (cmd->start_src == TRIG_EXT) {
 		s->async->inttrig = NULL;
@@ -2527,43 +2708,18 @@ static int ni_ai_cmd(struct comedi_devic
 	return 0;
 }
 
-static int ni_ai_inttrig(struct comedi_device *dev,
-			 struct comedi_subdevice *s,
-			 unsigned int trig_num)
-{
-	struct ni_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
-
-	if (trig_num != cmd->start_arg)
-		return -EINVAL;
-
-	devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
-			    AI_Command_2_Register);
-	s->async->inttrig = NULL;
-
-	return 1;
-}
-
-static int ni_ai_config_analog_trig(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data);
-
 static int ni_ai_insn_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	if (insn->n < 1)
 		return -EINVAL;
 
 	switch (data[0]) {
-	case INSN_CONFIG_ANALOG_TRIG:
-		return ni_ai_config_analog_trig(dev, s, insn, data);
 	case INSN_CONFIG_ALT_SOURCE:
-		if (board->reg_type & ni_reg_m_series_mask) {
+		if (devpriv->is_m_series) {
 			if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask |
 					MSeries_AI_Bypass_Cal_Sel_Neg_Mask |
 					MSeries_AI_Bypass_Mode_Mux_Mask |
@@ -2571,7 +2727,7 @@ static int ni_ai_insn_config(struct come
 				return -EINVAL;
 			}
 			devpriv->ai_calib_source = data[1];
-		} else if (board->reg_type == ni_reg_6143) {
+		} else if (devpriv->is_6143) {
 			unsigned int calib_source;
 
 			calib_source = data[1] & 0xf;
@@ -2580,7 +2736,7 @@ static int ni_ai_insn_config(struct come
 				return -EINVAL;
 
 			devpriv->ai_calib_source = calib_source;
-			ni_writew(calib_source, Calibration_Channel_6143);
+			ni_writew(dev, calib_source, Calibration_Channel_6143);
 		} else {
 			unsigned int calib_source;
 			unsigned int calib_source_adjust;
@@ -2591,8 +2747,8 @@ static int ni_ai_insn_config(struct come
 			if (calib_source >= 8)
 				return -EINVAL;
 			devpriv->ai_calib_source = calib_source;
-			if (board->reg_type == ni_reg_611x) {
-				ni_writeb(calib_source_adjust,
+			if (devpriv->is_611x) {
+				ni_writeb(dev, calib_source_adjust,
 					  Cal_Gain_Select_611x);
 			}
 		}
@@ -2604,127 +2760,30 @@ static int ni_ai_insn_config(struct come
 	return -EINVAL;
 }
 
-static int ni_ai_config_analog_trig(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv = dev->private;
-	unsigned int a, b, modebits;
-	int err = 0;
-
-	/* data[1] is flags
-	 * data[2] is analog line
-	 * data[3] is set level
-	 * data[4] is reset level */
-	if (!board->has_analog_trig)
-		return -EINVAL;
-	if ((data[1] & 0xffff0000) != COMEDI_EV_SCAN_BEGIN) {
-		data[1] &= (COMEDI_EV_SCAN_BEGIN | 0xffff);
-		err++;
-	}
-	if (data[2] >= board->n_adchan) {
-		data[2] = board->n_adchan - 1;
-		err++;
-	}
-	if (data[3] > 255) {	/* a */
-		data[3] = 255;
-		err++;
-	}
-	if (data[4] > 255) {	/* b */
-		data[4] = 255;
-		err++;
-	}
-	/*
-	 * 00 ignore
-	 * 01 set
-	 * 10 reset
-	 *
-	 * modes:
-	 *   1 level:                    +b-   +a-
-	 *     high mode                00 00 01 10
-	 *     low mode                 00 00 10 01
-	 *   2 level: (a<b)
-	 *     hysteresis low mode      10 00 00 01
-	 *     hysteresis high mode     01 00 00 10
-	 *     middle mode              10 01 01 10
-	 */
-
-	a = data[3];
-	b = data[4];
-	modebits = data[1] & 0xff;
-	if (modebits & 0xf0) {
-		/* two level mode */
-		if (b < a) {
-			/* swap order */
-			a = data[4];
-			b = data[3];
-			modebits =
-			    ((data[1] & 0xf) << 4) | ((data[1] & 0xf0) >> 4);
-		}
-		devpriv->atrig_low = a;
-		devpriv->atrig_high = b;
-		switch (modebits) {
-		case 0x81:	/* low hysteresis mode */
-			devpriv->atrig_mode = 6;
-			break;
-		case 0x42:	/* high hysteresis mode */
-			devpriv->atrig_mode = 3;
-			break;
-		case 0x96:	/* middle window mode */
-			devpriv->atrig_mode = 2;
-			break;
-		default:
-			data[1] &= ~0xff;
-			err++;
-		}
-	} else {
-		/* one level mode */
-		if (b != 0) {
-			data[4] = 0;
-			err++;
-		}
-		switch (modebits) {
-		case 0x06:	/* high window mode */
-			devpriv->atrig_high = a;
-			devpriv->atrig_mode = 0;
-			break;
-		case 0x09:	/* low window mode */
-			devpriv->atrig_low = a;
-			devpriv->atrig_mode = 1;
-			break;
-		default:
-			data[1] &= ~0xff;
-			err++;
-		}
-	}
-	if (err)
-		return -EAGAIN;
-	return 5;
-}
-
-/* munge data from unsigned to 2's complement for analog output bipolar modes */
 static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 			void *data, unsigned int num_bytes,
 			unsigned int chan_index)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct comedi_async *async = s->async;
-	struct comedi_cmd *cmd = &async->cmd;
-	unsigned int length = num_bytes / sizeof(short);
-	unsigned int offset = 1 << (board->aobits - 1);
+	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int length = num_bytes / bytes_per_sample(s);
 	unsigned short *array = data;
-	unsigned int range;
 	unsigned int i;
 
 	for (i = 0; i < length; i++) {
-		range = CR_RANGE(cmd->chanlist[chan_index]);
-		if (board->ao_unipolar == 0 || (range & 1) == 0)
-			array[i] -= offset;
+		unsigned int range = CR_RANGE(cmd->chanlist[chan_index]);
+		unsigned short val = array[i];
+
+		/*
+		 * Munge data from unsigned to two's complement for
+		 * bipolar ranges.
+		 */
+		if (comedi_range_is_bipolar(s, range))
+			val = comedi_offset_munge(s, val);
 #ifdef PCIDMA
-		array[i] = cpu_to_le16(array[i]);
+		val = cpu_to_le16(val);
 #endif
+		array[i] = val;
+
 		chan_index++;
 		chan_index %= cmd->chanlist_len;
 	}
@@ -2735,7 +2794,6 @@ static int ni_m_series_ao_config_chanlis
 					  unsigned int chanspec[],
 					  unsigned int n_chans, int timed)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
@@ -2744,15 +2802,16 @@ static int ni_m_series_ao_config_chanlis
 	int invert = 0;
 
 	if (timed) {
-		for (i = 0; i < board->n_aochan; ++i) {
+		for (i = 0; i < s->n_chan; ++i) {
 			devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit;
-			ni_writeb(devpriv->ao_conf[i],
+			ni_writeb(dev, devpriv->ao_conf[i],
 				  M_Offset_AO_Config_Bank(i));
-			ni_writeb(0xf, M_Offset_AO_Waveform_Order(i));
+			ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i));
 		}
 	}
 	for (i = 0; i < n_chans; i++) {
 		const struct comedi_krange *krange;
+
 		chan = CR_CHAN(chanspec[i]);
 		range = CR_RANGE(chanspec[i]);
 		krange = s->range_table->range + range;
@@ -2761,25 +2820,28 @@ static int ni_m_series_ao_config_chanlis
 		switch (krange->max - krange->min) {
 		case 20000000:
 			conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits;
-			ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan));
+			ni_writeb(dev, 0,
+				  M_Offset_AO_Reference_Attenuation(chan));
 			break;
 		case 10000000:
 			conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits;
-			ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan));
+			ni_writeb(dev, 0,
+				  M_Offset_AO_Reference_Attenuation(chan));
 			break;
 		case 4000000:
 			conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits;
-			ni_writeb(MSeries_Attenuate_x5_Bit,
+			ni_writeb(dev, MSeries_Attenuate_x5_Bit,
 				  M_Offset_AO_Reference_Attenuation(chan));
 			break;
 		case 2000000:
 			conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits;
-			ni_writeb(MSeries_Attenuate_x5_Bit,
+			ni_writeb(dev, MSeries_Attenuate_x5_Bit,
 				  M_Offset_AO_Reference_Attenuation(chan));
 			break;
 		default:
-			printk("%s: bug! unhandled ao reference voltage\n",
-			       __func__);
+			dev_err(dev->class_dev,
+				"%s: bug! unhandled ao reference voltage\n",
+				__func__);
 			break;
 		}
 		switch (krange->max + krange->min) {
@@ -2790,15 +2852,16 @@ static int ni_m_series_ao_config_chanlis
 			conf |= MSeries_AO_DAC_Offset_5V_Bits;
 			break;
 		default:
-			printk("%s: bug! unhandled ao offset voltage\n",
-			       __func__);
+			dev_err(dev->class_dev,
+				"%s: bug! unhandled ao offset voltage\n",
+				__func__);
 			break;
 		}
 		if (timed)
 			conf |= MSeries_AO_Update_Timed_Bit;
-		ni_writeb(conf, M_Offset_AO_Config_Bank(chan));
+		ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan));
 		devpriv->ao_conf[chan] = conf;
-		ni_writeb(i, M_Offset_AO_Waveform_Order(chan));
+		ni_writeb(dev, i, M_Offset_AO_Waveform_Order(chan));
 	}
 	return invert;
 }
@@ -2808,7 +2871,6 @@ static int ni_old_ao_config_chanlist(str
 				     unsigned int chanspec[],
 				     unsigned int n_chans)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
@@ -2821,19 +2883,14 @@ static int ni_old_ao_config_chanlist(str
 		range = CR_RANGE(chanspec[i]);
 		conf = AO_Channel(chan);
 
-		if (board->ao_unipolar) {
-			if ((range & 1) == 0) {
-				conf |= AO_Bipolar;
-				invert = (1 << (board->aobits - 1));
-			} else {
-				invert = 0;
-			}
-			if (range & 2)
-				conf |= AO_Ext_Ref;
-		} else {
+		if (comedi_range_is_bipolar(s, range)) {
 			conf |= AO_Bipolar;
-			invert = (1 << (board->aobits - 1));
+			invert = (s->maxdata + 1) >> 1;
+		} else {
+			invert = 0;
 		}
+		if (comedi_range_is_external(s, range))
+			conf |= AO_Ext_Ref;
 
 		/* not all boards can deglitch, but this shouldn't hurt */
 		if (chanspec[i] & CR_DEGLITCH)
@@ -2844,7 +2901,7 @@ static int ni_old_ao_config_chanlist(str
 		conf |= (CR_AREF(chanspec[i]) ==
 			 AREF_OTHER) ? AO_Ground_Ref : 0;
 
-		ni_writew(conf, AO_Configuration);
+		ni_writew(dev, conf, AO_Configuration);
 		devpriv->ao_conf[chan] = conf;
 	}
 	return invert;
@@ -2855,9 +2912,9 @@ static int ni_ao_config_chanlist(struct
 				 unsigned int chanspec[], unsigned int n_chans,
 				 int timed)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
 
-	if (board->reg_type & ni_reg_m_series_mask)
+	if (devpriv->is_m_series)
 		return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans,
 						      timed);
 	else
@@ -2865,56 +2922,75 @@ static int ni_ao_config_chanlist(struct
 }
 
 static int ni_ao_insn_read(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
 			   unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->ao[chan];
 
-	return 1;
+	return insn->n;
 }
 
 static int ni_ao_insn_write(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned int invert;
+	unsigned int range = CR_RANGE(insn->chanspec);
+	int reg;
+	int i;
 
-	invert = ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0);
+	if (devpriv->is_6xxx) {
+		ni_ao_win_outw(dev, 1 << chan, AO_Immediate_671x);
 
-	devpriv->ao[chan] = data[0];
+		reg = DACx_Direct_Data_671x(chan);
+	} else if (devpriv->is_m_series) {
+		reg = M_Offset_DAC_Direct_Data(chan);
+	} else {
+		reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data;
+	}
 
-	if (board->reg_type & ni_reg_m_series_mask) {
-		ni_writew(data[0], M_Offset_DAC_Direct_Data(chan));
-	} else
-		ni_writew(data[0] ^ invert,
-			  (chan) ? DAC1_Direct_Data : DAC0_Direct_Data);
+	ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0);
 
-	return 1;
-}
+	for (i = 0; i < insn->n; i++) {
+		unsigned int val = data[i];
 
-static int ni_ao_insn_write_671x(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv = dev->private;
-	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned int invert;
+		devpriv->ao[chan] = val;
 
-	ao_win_out(1 << chan, AO_Immediate_671x);
-	invert = 1 << (board->aobits - 1);
+		if (devpriv->is_6xxx) {
+			/*
+			 * 6xxx boards have bipolar outputs, munge the
+			 * unsigned comedi values to 2's complement
+			 */
+			val = comedi_offset_munge(s, val);
 
-	ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0);
+			ni_ao_win_outw(dev, val, reg);
+		} else if (devpriv->is_m_series) {
+			/*
+			 * M-series boards use offset binary values for
+			 * bipolar and uinpolar outputs
+			 */
+			ni_writew(dev, val, reg);
+		} else {
+			/*
+			 * Non-M series boards need two's complement values
+			 * for bipolar ranges.
+			 */
+			if (comedi_range_is_bipolar(s, range))
+				val = comedi_offset_munge(s, val);
 
-	devpriv->ao[chan] = data[0];
-	ao_win_out(data[0] ^ invert, DACx_Direct_Data_671x(chan));
+			ni_writew(dev, val, reg);
+		}
+	}
 
-	return 1;
+	return insn->n;
 }
 
 static int ni_ao_insn_config(struct comedi_device *dev,
@@ -2937,7 +3013,6 @@ static int ni_ao_insn_config(struct come
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		return 0;
 	default:
@@ -2951,7 +3026,6 @@ static int ni_ao_inttrig(struct comedi_d
 			 struct comedi_subdevice *s,
 			 unsigned int trig_num)
 {
-	const struct ni_board_struct *board __maybe_unused = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int ret;
@@ -2971,8 +3045,8 @@ static int ni_ao_inttrig(struct comedi_d
 		    AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0);
 	interrupt_b_bits = AO_Error_Interrupt_Enable;
 #ifdef PCIDMA
-	devpriv->stc_writew(dev, 1, DAC_FIFO_Clear);
-	if (board->reg_type & ni_reg_6xxx_mask)
+	ni_stc_writew(dev, 1, DAC_FIFO_Clear);
+	if (devpriv->is_6xxx)
 		ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
 	ret = ni_ao_setup_MITE_dma(dev);
 	if (ret)
@@ -2988,35 +3062,36 @@ static int ni_ao_inttrig(struct comedi_d
 	interrupt_b_bits |= AO_FIFO_Interrupt_Enable;
 #endif
 
-	devpriv->stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE,
-			    AO_Mode_3_Register);
-	devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+	ni_stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE,
+		      AO_Mode_3_Register);
+	ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
 	/* wait for DACs to be loaded */
 	for (i = 0; i < timeout; i++) {
 		udelay(1);
-		if ((devpriv->stc_readw(dev,
-					Joint_Status_2_Register) &
+		if ((ni_stc_readw(dev, Joint_Status_2_Register) &
 		     AO_TMRDACWRs_In_Progress_St) == 0)
 			break;
 	}
 	if (i == timeout) {
-		comedi_error(dev,
-			     "timed out waiting for AO_TMRDACWRs_In_Progress_St to clear");
+		dev_err(dev->class_dev,
+			"timed out waiting for AO_TMRDACWRs_In_Progress_St to clear\n");
 		return -EIO;
 	}
-	/*  stc manual says we are need to clear error interrupt after AO_TMRDACWRs_In_Progress_St clears */
-	devpriv->stc_writew(dev, AO_Error_Interrupt_Ack,
-			    Interrupt_B_Ack_Register);
+	/*
+	 * stc manual says we are need to clear error interrupt after
+	 * AO_TMRDACWRs_In_Progress_St clears
+	 */
+	ni_stc_writew(dev, AO_Error_Interrupt_Ack, Interrupt_B_Ack_Register);
 
 	ni_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1);
 
-	devpriv->stc_writew(dev,
-			    devpriv->ao_cmd1 | AO_UI_Arm | AO_UC_Arm | AO_BC_Arm
-			    | AO_DAC1_Update_Mode | AO_DAC0_Update_Mode,
-			    AO_Command_1_Register);
+	ni_stc_writew(dev, devpriv->ao_cmd1 |
+		      AO_UI_Arm | AO_UC_Arm | AO_BC_Arm |
+		      AO_DAC1_Update_Mode | AO_DAC0_Update_Mode,
+		      AO_Command_1_Register);
 
-	devpriv->stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse,
-			    AO_Command_2_Register);
+	ni_stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse,
+		      AO_Command_2_Register);
 
 	return 0;
 }
@@ -3031,16 +3106,16 @@ static int ni_ao_cmd(struct comedi_devic
 	unsigned trigvar;
 
 	if (dev->irq == 0) {
-		comedi_error(dev, "cannot run command without an irq");
+		dev_err(dev->class_dev, "cannot run command without an irq\n");
 		return -EIO;
 	}
 
-	devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
+	ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
 
-	devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register);
+	ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register);
 
-	if (board->reg_type & ni_reg_6xxx_mask) {
-		ao_win_out(CLEAR_WG, AO_Misc_611x);
+	if (devpriv->is_6xxx) {
+		ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x);
 
 		bits = 0;
 		for (i = 0; i < cmd->chanlist_len; i++) {
@@ -3048,9 +3123,9 @@ static int ni_ao_cmd(struct comedi_devic
 
 			chan = CR_CHAN(cmd->chanlist[i]);
 			bits |= 1 << chan;
-			ao_win_out(chan, AO_Waveform_Generation_611x);
+			ni_ao_win_outw(dev, chan, AO_Waveform_Generation_611x);
 		}
-		ao_win_out(bits, AO_Timed_611x);
+		ni_ao_win_outw(dev, bits, AO_Timed_611x);
 	}
 
 	ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
@@ -3062,15 +3137,15 @@ static int ni_ao_cmd(struct comedi_devic
 		devpriv->ao_mode1 &= ~AO_Continuous;
 		devpriv->ao_mode1 |= AO_Trigger_Once;
 	}
-	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+	ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 	switch (cmd->start_src) {
 	case TRIG_INT:
 	case TRIG_NOW:
 		devpriv->ao_trigger_select &=
 		    ~(AO_START1_Polarity | AO_START1_Select(-1));
 		devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync;
-		devpriv->stc_writew(dev, devpriv->ao_trigger_select,
-				    AO_Trigger_Select_Register);
+		ni_stc_writew(dev, devpriv->ao_trigger_select,
+			      AO_Trigger_Select_Register);
 		break;
 	case TRIG_EXT:
 		devpriv->ao_trigger_select =
@@ -3079,52 +3154,50 @@ static int ni_ao_cmd(struct comedi_devic
 			devpriv->ao_trigger_select |= AO_START1_Polarity;	/*  0=active high, 1=active low. see daq-stc 3-24 (p186) */
 		if (cmd->start_arg & CR_EDGE)
 			devpriv->ao_trigger_select |= AO_START1_Edge;	/*  0=edge detection disabled, 1=enabled */
-		devpriv->stc_writew(dev, devpriv->ao_trigger_select,
-				    AO_Trigger_Select_Register);
+		ni_stc_writew(dev, devpriv->ao_trigger_select,
+			      AO_Trigger_Select_Register);
 		break;
 	default:
 		BUG();
 		break;
 	}
 	devpriv->ao_mode3 &= ~AO_Trigger_Length;
-	devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+	ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
 
-	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+	ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 	devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source;
-	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+	ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
 	if (cmd->stop_src == TRIG_NONE)
-		devpriv->stc_writel(dev, 0xffffff, AO_BC_Load_A_Register);
+		ni_stc_writel(dev, 0xffffff, AO_BC_Load_A_Register);
 	else
-		devpriv->stc_writel(dev, 0, AO_BC_Load_A_Register);
-	devpriv->stc_writew(dev, AO_BC_Load, AO_Command_1_Register);
+		ni_stc_writel(dev, 0, AO_BC_Load_A_Register);
+	ni_stc_writew(dev, AO_BC_Load, AO_Command_1_Register);
 	devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source;
-	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+	ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (board->reg_type & ni_reg_m_series_mask) {
+		if (devpriv->is_m_series) {
 			/*  this is how the NI example code does it for m-series boards, verified correct with 6259 */
-			devpriv->stc_writel(dev, cmd->stop_arg - 1,
-					    AO_UC_Load_A_Register);
-			devpriv->stc_writew(dev, AO_UC_Load,
-					    AO_Command_1_Register);
+			ni_stc_writel(dev, cmd->stop_arg - 1,
+				      AO_UC_Load_A_Register);
+			ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
 		} else {
-			devpriv->stc_writel(dev, cmd->stop_arg,
-					    AO_UC_Load_A_Register);
-			devpriv->stc_writew(dev, AO_UC_Load,
-					    AO_Command_1_Register);
-			devpriv->stc_writel(dev, cmd->stop_arg - 1,
-					    AO_UC_Load_A_Register);
+			ni_stc_writel(dev, cmd->stop_arg,
+				      AO_UC_Load_A_Register);
+			ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+			ni_stc_writel(dev, cmd->stop_arg - 1,
+				      AO_UC_Load_A_Register);
 		}
 		break;
 	case TRIG_NONE:
-		devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
-		devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
-		devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
+		ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
+		ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+		ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
 		break;
 	default:
-		devpriv->stc_writel(dev, 0, AO_UC_Load_A_Register);
-		devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
-		devpriv->stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register);
+		ni_stc_writel(dev, 0, AO_UC_Load_A_Register);
+		ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+		ni_stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register);
 	}
 
 	devpriv->ao_mode1 &=
@@ -3136,9 +3209,9 @@ static int ni_ao_cmd(struct comedi_devic
 		trigvar =
 		    ni_ns_to_timer(dev, cmd->scan_begin_arg,
 				   TRIG_ROUND_NEAREST);
-		devpriv->stc_writel(dev, 1, AO_UI_Load_A_Register);
-		devpriv->stc_writew(dev, AO_UI_Load, AO_Command_1_Register);
-		devpriv->stc_writel(dev, trigvar, AO_UI_Load_A_Register);
+		ni_stc_writel(dev, 1, AO_UI_Load_A_Register);
+		ni_stc_writew(dev, AO_UI_Load, AO_Command_1_Register);
+		ni_stc_writel(dev, trigvar, AO_UI_Load_A_Register);
 		break;
 	case TRIG_EXT:
 		devpriv->ao_mode1 |=
@@ -3151,40 +3224,38 @@ static int ni_ao_cmd(struct comedi_devic
 		BUG();
 		break;
 	}
-	devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
-	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+	ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
+	ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 	devpriv->ao_mode2 &=
 	    ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source);
-	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+	ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
 
 	if (cmd->scan_end_arg > 1) {
 		devpriv->ao_mode1 |= AO_Multiple_Channels;
-		devpriv->stc_writew(dev,
-				    AO_Number_Of_Channels(cmd->scan_end_arg -
-							  1) |
-				    AO_UPDATE_Output_Select
-				    (AO_Update_Output_High_Z),
-				    AO_Output_Control_Register);
+		ni_stc_writew(dev,
+			      AO_Number_Of_Channels(cmd->scan_end_arg - 1) |
+			      AO_UPDATE_Output_Select(AO_Update_Output_High_Z),
+			      AO_Output_Control_Register);
 	} else {
 		unsigned bits;
+
 		devpriv->ao_mode1 &= ~AO_Multiple_Channels;
 		bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z);
-		if (board->reg_type &
-		    (ni_reg_m_series_mask | ni_reg_6xxx_mask)) {
+		if (devpriv->is_m_series || devpriv->is_6xxx) {
 			bits |= AO_Number_Of_Channels(0);
 		} else {
 			bits |=
 			    AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0]));
 		}
-		devpriv->stc_writew(dev, bits, AO_Output_Control_Register);
+		ni_stc_writew(dev, bits, AO_Output_Control_Register);
 	}
-	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+	ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 
-	devpriv->stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode,
-			    AO_Command_1_Register);
+	ni_stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode,
+		      AO_Command_1_Register);
 
 	devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error;
-	devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+	ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
 
 	devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask;
 #ifdef PCIDMA
@@ -3193,7 +3264,7 @@ static int ni_ao_cmd(struct comedi_devic
 	devpriv->ao_mode2 |= AO_FIFO_Mode_HF;
 #endif
 	devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable;
-	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+	ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
 
 	bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
 	    AO_TMRDACWR_Pulse_Width;
@@ -3204,18 +3275,18 @@ static int ni_ao_cmd(struct comedi_devic
 #if 0
 	/* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281,
 	   verified with bus analyzer. */
-	if (board->reg_type & ni_reg_m_series_mask)
+	if (devpriv->is_m_series)
 		bits |= AO_Number_Of_DAC_Packages;
 #endif
-	devpriv->stc_writew(dev, bits, AO_Personal_Register);
+	ni_stc_writew(dev, bits, AO_Personal_Register);
 	/*  enable sending of ao dma requests */
-	devpriv->stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register);
+	ni_stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register);
 
-	devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
+	ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
 
 	if (cmd->stop_src == TRIG_COUNT) {
-		devpriv->stc_writew(dev, AO_BC_TC_Interrupt_Ack,
-				    Interrupt_B_Ack_Register);
+		ni_stc_writew(dev, AO_BC_TC_Interrupt_Ack,
+			      Interrupt_B_Ack_Register);
 		ni_set_bits(dev, Interrupt_B_Enable_Register,
 			    AO_BC_TC_Interrupt_Enable, 1);
 	}
@@ -3299,9 +3370,7 @@ static int ni_ao_cmdtest(struct comedi_d
 		cmd->scan_begin_arg =
 		    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
 						       cmd->scan_begin_arg,
-						       cmd->
-						       flags &
-						       TRIG_ROUND_MASK));
+						       cmd->flags));
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
@@ -3313,51 +3382,45 @@ static int ni_ao_cmdtest(struct comedi_d
 
 static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
-	/* devpriv->ao0p=0x0000; */
-	/* ni_writew(devpriv->ao0p,AO_Configuration); */
-
-	/* devpriv->ao1p=AO_Channel(1); */
-	/* ni_writew(devpriv->ao1p,AO_Configuration); */
-
 	ni_release_ao_mite_channel(dev);
 
-	devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
-	devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register);
+	ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
+	ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register);
 	ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0);
-	devpriv->stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register);
-	devpriv->stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register);
-	devpriv->stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
-			    AO_TMRDACWR_Pulse_Width, AO_Personal_Register);
-	devpriv->stc_writew(dev, 0, AO_Output_Control_Register);
-	devpriv->stc_writew(dev, 0, AO_Start_Select_Register);
+	ni_stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register);
+	ni_stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register);
+	ni_stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
+		      AO_TMRDACWR_Pulse_Width, AO_Personal_Register);
+	ni_stc_writew(dev, 0, AO_Output_Control_Register);
+	ni_stc_writew(dev, 0, AO_Start_Select_Register);
 	devpriv->ao_cmd1 = 0;
-	devpriv->stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register);
+	ni_stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register);
 	devpriv->ao_cmd2 = 0;
-	devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
+	ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
 	devpriv->ao_mode1 = 0;
-	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+	ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 	devpriv->ao_mode2 = 0;
-	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
-	if (board->reg_type & ni_reg_m_series_mask)
+	ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+	if (devpriv->is_m_series)
 		devpriv->ao_mode3 = AO_Last_Gate_Disable;
 	else
 		devpriv->ao_mode3 = 0;
-	devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+	ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
 	devpriv->ao_trigger_select = 0;
-	devpriv->stc_writew(dev, devpriv->ao_trigger_select,
-			    AO_Trigger_Select_Register);
-	if (board->reg_type & ni_reg_6xxx_mask) {
+	ni_stc_writew(dev, devpriv->ao_trigger_select,
+		      AO_Trigger_Select_Register);
+	if (devpriv->is_6xxx) {
 		unsigned immediate_bits = 0;
 		unsigned i;
+
 		for (i = 0; i < s->n_chan; ++i)
 			immediate_bits |= 1 << i;
-		ao_win_out(immediate_bits, AO_Immediate_671x);
-		ao_win_out(CLEAR_WG, AO_Misc_611x);
+		ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x);
+		ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x);
 	}
-	devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
+	ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
 
 	return 0;
 }
@@ -3378,7 +3441,7 @@ static int ni_dio_insn_config(struct com
 
 	devpriv->dio_control &= ~DIO_Pins_Dir_Mask;
 	devpriv->dio_control |= DIO_Pins_Dir(s->io_bits);
-	devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+	ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
 
 	return insn->n;
 }
@@ -3397,11 +3460,10 @@ static int ni_dio_insn_bits(struct comed
 	if (comedi_dio_update_state(s, data)) {
 		devpriv->dio_output &= ~DIO_Parallel_Data_Mask;
 		devpriv->dio_output |= DIO_Parallel_Data_Out(s->state);
-		devpriv->stc_writew(dev, devpriv->dio_output,
-				    DIO_Output_Register);
+		ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
 	}
 
-	data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register);
+	data[1] = ni_stc_readw(dev, DIO_Parallel_Input_Register);
 
 	return insn->n;
 }
@@ -3411,14 +3473,13 @@ static int ni_m_series_dio_insn_config(s
 				       struct comedi_insn *insn,
 				       unsigned int *data)
 {
-	struct ni_private *devpriv __maybe_unused = dev->private;
 	int ret;
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 	if (ret)
 		return ret;
 
-	ni_writel(s->io_bits, M_Offset_DIO_Direction);
+	ni_writel(dev, s->io_bits, M_Offset_DIO_Direction);
 
 	return insn->n;
 }
@@ -3428,12 +3489,10 @@ static int ni_m_series_dio_insn_bits(str
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
-	struct ni_private *devpriv __maybe_unused = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		ni_writel(s->state, M_Offset_Static_Digital_Output);
+		ni_writel(dev, s->state, M_Offset_Static_Digital_Output);
 
-	data[1] = ni_readl(M_Offset_Static_Digital_Input);
+	data[1] = ni_readl(dev, M_Offset_Static_Digital_Input);
 
 	return insn->n;
 }
@@ -3508,57 +3567,18 @@ static int ni_cdio_cmdtest(struct comedi
 	return 0;
 }
 
-static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct ni_private *devpriv __maybe_unused = dev->private;
-	const struct comedi_cmd *cmd = &s->async->cmd;
-	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
-	int retval;
-
-	ni_writel(CDO_Reset_Bit, M_Offset_CDIO_Command);
-	switch (cmd->scan_begin_src) {
-	case TRIG_EXT:
-		cdo_mode_bits |=
-		    CR_CHAN(cmd->scan_begin_arg) &
-		    CDO_Sample_Source_Select_Mask;
-		break;
-	default:
-		BUG();
-		break;
-	}
-	if (cmd->scan_begin_arg & CR_INVERT)
-		cdo_mode_bits |= CDO_Polarity_Bit;
-	ni_writel(cdo_mode_bits, M_Offset_CDO_Mode);
-	if (s->io_bits) {
-		ni_writel(s->state, M_Offset_CDO_FIFO_Data);
-		ni_writel(CDO_SW_Update_Bit, M_Offset_CDIO_Command);
-		ni_writel(s->io_bits, M_Offset_CDO_Mask_Enable);
-	} else {
-		comedi_error(dev,
-			     "attempted to run digital output command with no lines configured as outputs");
-		return -EIO;
-	}
-	retval = ni_request_cdo_mite_channel(dev);
-	if (retval < 0)
-		return retval;
-
-	s->async->inttrig = ni_cdo_inttrig;
-
-	return 0;
-}
-
 static int ni_cdo_inttrig(struct comedi_device *dev,
 			  struct comedi_subdevice *s,
 			  unsigned int trig_num)
 {
+	struct comedi_cmd *cmd = &s->async->cmd;
+	const unsigned timeout = 1000;
+	int retval = 0;
+	unsigned i;
 #ifdef PCIDMA
 	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 #endif
-	struct comedi_cmd *cmd = &s->async->cmd;
-	int retval = 0;
-	unsigned i;
-	const unsigned timeout = 1000;
 
 	if (trig_num != cmd->start_arg)
 		return -EINVAL;
@@ -3574,7 +3594,7 @@ static int ni_cdo_inttrig(struct comedi_
 		mite_prep_dma(devpriv->cdo_mite_chan, 32, 32);
 		mite_dma_arm(devpriv->cdo_mite_chan);
 	} else {
-		comedi_error(dev, "BUG: no cdo mite channel?");
+		dev_err(dev->class_dev, "BUG: no cdo mite channel?\n");
 		retval = -EIO;
 	}
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
@@ -3583,53 +3603,88 @@ static int ni_cdo_inttrig(struct comedi_
 #endif
 /*
 * XXX not sure what interrupt C group does
-* ni_writeb(Interrupt_Group_C_Enable_Bit,
+* ni_writeb(dev, Interrupt_Group_C_Enable_Bit,
 * M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo
 */
 	for (i = 0; i < timeout; ++i) {
-		if (ni_readl(M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit)
+		if (ni_readl(dev, M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit)
 			break;
 		udelay(10);
 	}
 	if (i == timeout) {
-		comedi_error(dev, "dma failed to fill cdo fifo!");
-		ni_cdio_cancel(dev, s);
+		dev_err(dev->class_dev, "dma failed to fill cdo fifo!\n");
+		s->cancel(dev, s);
 		return -EIO;
 	}
-	ni_writel(CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit |
-		  CDO_Empty_FIFO_Interrupt_Enable_Set_Bit,
+	ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit |
+		       CDO_Empty_FIFO_Interrupt_Enable_Set_Bit,
 		  M_Offset_CDIO_Command);
 	return retval;
 }
 
-static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct ni_private *devpriv __maybe_unused = dev->private;
+	const struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+	int retval;
 
-	ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
-		  CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
-		  CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
+	ni_writel(dev, CDO_Reset_Bit, M_Offset_CDIO_Command);
+	switch (cmd->scan_begin_src) {
+	case TRIG_EXT:
+		cdo_mode_bits |=
+		    CR_CHAN(cmd->scan_begin_arg) &
+		    CDO_Sample_Source_Select_Mask;
+		break;
+	default:
+		BUG();
+		break;
+	}
+	if (cmd->scan_begin_arg & CR_INVERT)
+		cdo_mode_bits |= CDO_Polarity_Bit;
+	ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode);
+	if (s->io_bits) {
+		ni_writel(dev, s->state, M_Offset_CDO_FIFO_Data);
+		ni_writel(dev, CDO_SW_Update_Bit, M_Offset_CDIO_Command);
+		ni_writel(dev, s->io_bits, M_Offset_CDO_Mask_Enable);
+	} else {
+		dev_err(dev->class_dev,
+			"attempted to run digital output command with no lines configured as outputs\n");
+		return -EIO;
+	}
+	retval = ni_request_cdo_mite_channel(dev);
+	if (retval < 0)
+		return retval;
+
+	s->async->inttrig = ni_cdo_inttrig;
+
+	return 0;
+}
+
+static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	ni_writel(dev, CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
+		       CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
+		       CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
 		  M_Offset_CDIO_Command);
 /*
-* XXX not sure what interrupt C group does ni_writeb(0,
+* XXX not sure what interrupt C group does ni_writeb(dev, 0,
 * M_Offset_Interrupt_C_Enable);
 */
-	ni_writel(0, M_Offset_CDO_Mask_Enable);
+	ni_writel(dev, 0, M_Offset_CDO_Mask_Enable);
 	ni_release_cdo_mite_channel(dev);
 	return 0;
 }
 
 static void handle_cdio_interrupt(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv __maybe_unused = dev->private;
+	struct ni_private *devpriv = dev->private;
 	unsigned cdio_status;
 	struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
 #ifdef PCIDMA
 	unsigned long flags;
 #endif
 
-	if ((board->reg_type & ni_reg_m_series_mask) == 0)
+	if (!devpriv->is_m_series)
 		return;
 #ifdef PCIDMA
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -3646,112 +3701,21 @@ static void handle_cdio_interrupt(struct
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 #endif
 
-	cdio_status = ni_readl(M_Offset_CDIO_Status);
+	cdio_status = ni_readl(dev, M_Offset_CDIO_Status);
 	if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) {
-		/* printk("cdio error: statux=0x%x\n", cdio_status); */
-		ni_writel(CDO_Error_Interrupt_Confirm_Bit, M_Offset_CDIO_Command);	/*  XXX just guessing this is needed and does something useful */
+		/* XXX just guessing this is needed and does something useful */
+		ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit,
+			  M_Offset_CDIO_Command);
 		s->async->events |= COMEDI_CB_OVERFLOW;
 	}
 	if (cdio_status & CDO_FIFO_Empty_Bit) {
-		/* printk("cdio fifo empty\n"); */
-		ni_writel(CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit,
+		ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit,
 			  M_Offset_CDIO_Command);
 		/* s->async->events |= COMEDI_CB_EOA; */
 	}
 	cfc_handle_events(dev, s);
 }
 
-static int ni_serial_insn_config(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
-{
-	struct ni_private *devpriv = dev->private;
-	int err = insn->n;
-	unsigned char byte_out, byte_in = 0;
-
-	if (insn->n != 2)
-		return -EINVAL;
-
-	switch (data[0]) {
-	case INSN_CONFIG_SERIAL_CLOCK:
-		devpriv->serial_hw_mode = 1;
-		devpriv->dio_control |= DIO_HW_Serial_Enable;
-
-		if (data[1] == SERIAL_DISABLED) {
-			devpriv->serial_hw_mode = 0;
-			devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
-						  DIO_Software_Serial_Control);
-			data[1] = SERIAL_DISABLED;
-			devpriv->serial_interval_ns = data[1];
-		} else if (data[1] <= SERIAL_600NS) {
-			/* Warning: this clock speed is too fast to reliably
-			   control SCXI. */
-			devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
-			devpriv->clock_and_fout |= Slow_Internal_Timebase;
-			devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2;
-			data[1] = SERIAL_600NS;
-			devpriv->serial_interval_ns = data[1];
-		} else if (data[1] <= SERIAL_1_2US) {
-			devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
-			devpriv->clock_and_fout |= Slow_Internal_Timebase |
-			    DIO_Serial_Out_Divide_By_2;
-			data[1] = SERIAL_1_2US;
-			devpriv->serial_interval_ns = data[1];
-		} else if (data[1] <= SERIAL_10US) {
-			devpriv->dio_control |= DIO_HW_Serial_Timebase;
-			devpriv->clock_and_fout |= Slow_Internal_Timebase |
-			    DIO_Serial_Out_Divide_By_2;
-			/* Note: DIO_Serial_Out_Divide_By_2 only affects
-			   600ns/1.2us. If you turn divide_by_2 off with the
-			   slow clock, you will still get 10us, except then
-			   all your delays are wrong. */
-			data[1] = SERIAL_10US;
-			devpriv->serial_interval_ns = data[1];
-		} else {
-			devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
-						  DIO_Software_Serial_Control);
-			devpriv->serial_hw_mode = 0;
-			data[1] = (data[1] / 1000) * 1000;
-			devpriv->serial_interval_ns = data[1];
-		}
-
-		devpriv->stc_writew(dev, devpriv->dio_control,
-				    DIO_Control_Register);
-		devpriv->stc_writew(dev, devpriv->clock_and_fout,
-				    Clock_and_FOUT_Register);
-		return 1;
-
-		break;
-
-	case INSN_CONFIG_BIDIRECTIONAL_DATA:
-
-		if (devpriv->serial_interval_ns == 0)
-			return -EINVAL;
-
-		byte_out = data[1] & 0xFF;
-
-		if (devpriv->serial_hw_mode) {
-			err = ni_serial_hw_readwrite8(dev, s, byte_out,
-						      &byte_in);
-		} else if (devpriv->serial_interval_ns > 0) {
-			err = ni_serial_sw_readwrite8(dev, s, byte_out,
-						      &byte_in);
-		} else {
-			printk("ni_serial_insn_config: serial disabled!\n");
-			return -EINVAL;
-		}
-		if (err < 0)
-			return err;
-		data[1] = byte_in & 0xFF;
-		return insn->n;
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
-}
-
 static int ni_serial_hw_readwrite8(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   unsigned char data_out,
@@ -3763,28 +3727,27 @@ static int ni_serial_hw_readwrite8(struc
 
 	devpriv->dio_output &= ~DIO_Serial_Data_Mask;
 	devpriv->dio_output |= DIO_Serial_Data_Out(data_out);
-	devpriv->stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
+	ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
 
-	status1 = devpriv->stc_readw(dev, Joint_Status_1_Register);
+	status1 = ni_stc_readw(dev, Joint_Status_1_Register);
 	if (status1 & DIO_Serial_IO_In_Progress_St) {
 		err = -EBUSY;
 		goto Error;
 	}
 
 	devpriv->dio_control |= DIO_HW_Serial_Start;
-	devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+	ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
 	devpriv->dio_control &= ~DIO_HW_Serial_Start;
 
 	/* Wait until STC says we're done, but don't loop infinitely. */
-	while ((status1 =
-		devpriv->stc_readw(dev,
-				   Joint_Status_1_Register)) &
+	while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) &
 	       DIO_Serial_IO_In_Progress_St) {
 		/* Delay one bit per loop */
 		udelay((devpriv->serial_interval_ns + 999) / 1000);
 		if (--count < 0) {
-			printk
-			    ("ni_serial_hw_readwrite8: SPI serial I/O didn't finish in time!\n");
+			dev_err(dev->class_dev,
+				"%s: SPI serial I/O didn't finish in time!\n",
+				__func__);
 			err = -ETIME;
 			goto Error;
 		}
@@ -3795,10 +3758,10 @@ static int ni_serial_hw_readwrite8(struc
 	udelay((devpriv->serial_interval_ns + 999) / 1000);
 
 	if (data_in != NULL)
-		*data_in = devpriv->stc_readw(dev, DIO_Serial_Input_Register);
+		*data_in = ni_stc_readw(dev, DIO_Serial_Input_Register);
 
 Error:
-	devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+	ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
 
 	return err;
 }
@@ -3821,29 +3784,23 @@ static int ni_serial_sw_readwrite8(struc
 		devpriv->dio_output &= ~DIO_SDOUT;
 		if (data_out & mask)
 			devpriv->dio_output |= DIO_SDOUT;
-		devpriv->stc_writew(dev, devpriv->dio_output,
-				    DIO_Output_Register);
+		ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
 
 		/* Assert SDCLK (active low, inverted), wait for half of
 		   the delay, deassert SDCLK, and wait for the other half. */
 		devpriv->dio_control |= DIO_Software_Serial_Control;
-		devpriv->stc_writew(dev, devpriv->dio_control,
-				    DIO_Control_Register);
+		ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
 
 		udelay((devpriv->serial_interval_ns + 999) / 2000);
 
 		devpriv->dio_control &= ~DIO_Software_Serial_Control;
-		devpriv->stc_writew(dev, devpriv->dio_control,
-				    DIO_Control_Register);
+		ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
 
 		udelay((devpriv->serial_interval_ns + 999) / 2000);
 
 		/* Input current bit */
-		if (devpriv->stc_readw(dev,
-				       DIO_Parallel_Input_Register) & DIO_SDIN) {
-			/* printk("DIO_P_I_R: 0x%x\n", devpriv->stc_readw(dev, DIO_Parallel_Input_Register)); */
+		if (ni_stc_readw(dev, DIO_Parallel_Input_Register) & DIO_SDIN)
 			input |= mask;
-		}
 	}
 
 	if (data_in)
@@ -3852,14 +3809,96 @@ static int ni_serial_sw_readwrite8(struc
 	return 0;
 }
 
-static void mio_common_detach(struct comedi_device *dev)
+static int ni_serial_insn_config(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
+	int err = insn->n;
+	unsigned char byte_out, byte_in = 0;
 
-	if (devpriv) {
-		if (devpriv->counter_dev)
-			ni_gpct_device_destroy(devpriv->counter_dev);
+	if (insn->n != 2)
+		return -EINVAL;
+
+	switch (data[0]) {
+	case INSN_CONFIG_SERIAL_CLOCK:
+		devpriv->serial_hw_mode = 1;
+		devpriv->dio_control |= DIO_HW_Serial_Enable;
+
+		if (data[1] == SERIAL_DISABLED) {
+			devpriv->serial_hw_mode = 0;
+			devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
+						  DIO_Software_Serial_Control);
+			data[1] = SERIAL_DISABLED;
+			devpriv->serial_interval_ns = data[1];
+		} else if (data[1] <= SERIAL_600NS) {
+			/* Warning: this clock speed is too fast to reliably
+			   control SCXI. */
+			devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
+			devpriv->clock_and_fout |= Slow_Internal_Timebase;
+			devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2;
+			data[1] = SERIAL_600NS;
+			devpriv->serial_interval_ns = data[1];
+		} else if (data[1] <= SERIAL_1_2US) {
+			devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
+			devpriv->clock_and_fout |= Slow_Internal_Timebase |
+			    DIO_Serial_Out_Divide_By_2;
+			data[1] = SERIAL_1_2US;
+			devpriv->serial_interval_ns = data[1];
+		} else if (data[1] <= SERIAL_10US) {
+			devpriv->dio_control |= DIO_HW_Serial_Timebase;
+			devpriv->clock_and_fout |= Slow_Internal_Timebase |
+			    DIO_Serial_Out_Divide_By_2;
+			/* Note: DIO_Serial_Out_Divide_By_2 only affects
+			   600ns/1.2us. If you turn divide_by_2 off with the
+			   slow clock, you will still get 10us, except then
+			   all your delays are wrong. */
+			data[1] = SERIAL_10US;
+			devpriv->serial_interval_ns = data[1];
+		} else {
+			devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
+						  DIO_Software_Serial_Control);
+			devpriv->serial_hw_mode = 0;
+			data[1] = (data[1] / 1000) * 1000;
+			devpriv->serial_interval_ns = data[1];
+		}
+
+		ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+		ni_stc_writew(dev, devpriv->clock_and_fout,
+			      Clock_and_FOUT_Register);
+		return 1;
+
+		break;
+
+	case INSN_CONFIG_BIDIRECTIONAL_DATA:
+
+		if (devpriv->serial_interval_ns == 0)
+			return -EINVAL;
+
+		byte_out = data[1] & 0xFF;
+
+		if (devpriv->serial_hw_mode) {
+			err = ni_serial_hw_readwrite8(dev, s, byte_out,
+						      &byte_in);
+		} else if (devpriv->serial_interval_ns > 0) {
+			err = ni_serial_sw_readwrite8(dev, s, byte_out,
+						      &byte_in);
+		} else {
+			dev_err(dev->class_dev, "%s: serial disabled!\n",
+				__func__);
+			return -EINVAL;
+		}
+		if (err < 0)
+			return err;
+		data[1] = byte_in & 0xFF;
+		return insn->n;
+
+		break;
+	default:
+		return -EINVAL;
 	}
+
 }
 
 static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -3870,12 +3909,13 @@ static void init_ao_67xx(struct comedi_d
 		ni_ao_win_outw(dev, AO_Channel(i) | 0x0,
 			       AO_Configuration_2_67xx);
 	}
-	ao_win_out(0x0, AO_Later_Single_Point_Updates);
+	ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates);
 }
 
 static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg)
 {
 	unsigned stc_register;
+
 	switch (reg) {
 	case NITIO_G0_AUTO_INC:
 		stc_register = G_Autoincrement_Register(0);
@@ -3960,7 +4000,6 @@ static unsigned ni_gpct_to_stc_register(
 		       __func__, reg);
 		BUG();
 		return 0;
-		break;
 	}
 	return stc_register;
 }
@@ -3969,7 +4008,6 @@ static void ni_gpct_write_register(struc
 				   enum ni_gpct_register reg)
 {
 	struct comedi_device *dev = counter->counter_dev->dev;
-	struct ni_private *devpriv = dev->private;
 	unsigned stc_register;
 	/* bits in the join reset register which are relevant to counters */
 	static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
@@ -3981,28 +4019,28 @@ static void ni_gpct_write_register(struc
 	switch (reg) {
 		/* m-series-only registers */
 	case NITIO_G0_CNT_MODE:
-		ni_writew(bits, M_Offset_G0_Counting_Mode);
+		ni_writew(dev, bits, M_Offset_G0_Counting_Mode);
 		break;
 	case NITIO_G1_CNT_MODE:
-		ni_writew(bits, M_Offset_G1_Counting_Mode);
+		ni_writew(dev, bits, M_Offset_G1_Counting_Mode);
 		break;
 	case NITIO_G0_GATE2:
-		ni_writew(bits, M_Offset_G0_Second_Gate);
+		ni_writew(dev, bits, M_Offset_G0_Second_Gate);
 		break;
 	case NITIO_G1_GATE2:
-		ni_writew(bits, M_Offset_G1_Second_Gate);
+		ni_writew(dev, bits, M_Offset_G1_Second_Gate);
 		break;
 	case NITIO_G0_DMA_CFG:
-		ni_writew(bits, M_Offset_G0_DMA_Config);
+		ni_writew(dev, bits, M_Offset_G0_DMA_Config);
 		break;
 	case NITIO_G1_DMA_CFG:
-		ni_writew(bits, M_Offset_G1_DMA_Config);
+		ni_writew(dev, bits, M_Offset_G1_DMA_Config);
 		break;
 	case NITIO_G0_ABZ:
-		ni_writew(bits, M_Offset_G0_MSeries_ABZ);
+		ni_writew(dev, bits, M_Offset_G0_MSeries_ABZ);
 		break;
 	case NITIO_G1_ABZ:
-		ni_writew(bits, M_Offset_G1_MSeries_ABZ);
+		ni_writew(dev, bits, M_Offset_G1_MSeries_ABZ);
 		break;
 
 		/* 32 bit registers */
@@ -4011,7 +4049,7 @@ static void ni_gpct_write_register(struc
 	case NITIO_G0_LOADB:
 	case NITIO_G1_LOADB:
 		stc_register = ni_gpct_to_stc_register(reg);
-		devpriv->stc_writel(dev, bits, stc_register);
+		ni_stc_writel(dev, bits, stc_register);
 		break;
 
 		/* 16 bit registers */
@@ -4030,7 +4068,7 @@ static void ni_gpct_write_register(struc
 		/* fall-through */
 	default:
 		stc_register = ni_gpct_to_stc_register(reg);
-		devpriv->stc_writew(dev, bits, stc_register);
+		ni_stc_writew(dev, bits, stc_register);
 	}
 }
 
@@ -4038,15 +4076,14 @@ static unsigned ni_gpct_read_register(st
 				      enum ni_gpct_register reg)
 {
 	struct comedi_device *dev = counter->counter_dev->dev;
-	struct ni_private *devpriv = dev->private;
 	unsigned stc_register;
 
 	switch (reg) {
 		/* m-series only registers */
 	case NITIO_G0_DMA_STATUS:
-		return ni_readw(M_Offset_G0_DMA_Status);
+		return ni_readw(dev, M_Offset_G0_DMA_Status);
 	case NITIO_G1_DMA_STATUS:
-		return ni_readw(M_Offset_G1_DMA_Status);
+		return ni_readw(dev, M_Offset_G1_DMA_Status);
 
 		/* 32 bit registers */
 	case NITIO_G0_HW_SAVE:
@@ -4054,506 +4091,101 @@ static unsigned ni_gpct_read_register(st
 	case NITIO_G0_SW_SAVE:
 	case NITIO_G1_SW_SAVE:
 		stc_register = ni_gpct_to_stc_register(reg);
-		return devpriv->stc_readl(dev, stc_register);
+		return ni_stc_readl(dev, stc_register);
 
 		/* 16 bit registers */
 	default:
 		stc_register = ni_gpct_to_stc_register(reg);
-		return devpriv->stc_readw(dev, stc_register);
-		break;
+		return ni_stc_readw(dev, stc_register);
 	}
 	return 0;
 }
 
 static int ni_freq_out_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
+	unsigned int val = devpriv->clock_and_fout & FOUT_Divider_mask;
+	int i;
 
-	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
-	return 1;
-}
-
-static int ni_freq_out_insn_write(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
-{
-	struct ni_private *devpriv = dev->private;
+	for (i = 0; i < insn->n; i++)
+		data[i] = val;
 
-	devpriv->clock_and_fout &= ~FOUT_Enable;
-	devpriv->stc_writew(dev, devpriv->clock_and_fout,
-			    Clock_and_FOUT_Register);
-	devpriv->clock_and_fout &= ~FOUT_Divider_mask;
-	devpriv->clock_and_fout |= FOUT_Divider(data[0]);
-	devpriv->clock_and_fout |= FOUT_Enable;
-	devpriv->stc_writew(dev, devpriv->clock_and_fout,
-			    Clock_and_FOUT_Register);
 	return insn->n;
 }
 
-static int ni_set_freq_out_clock(struct comedi_device *dev,
-				 unsigned int clock_source)
+static int ni_freq_out_insn_write(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
 
-	switch (clock_source) {
-	case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
-		devpriv->clock_and_fout &= ~FOUT_Timebase_Select;
-		break;
-	case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC:
-		devpriv->clock_and_fout |= FOUT_Timebase_Select;
-		break;
-	default:
-		return -EINVAL;
-	}
-	devpriv->stc_writew(dev, devpriv->clock_and_fout,
-			    Clock_and_FOUT_Register);
-	return 3;
-}
+	if (insn->n) {
+		devpriv->clock_and_fout &= ~FOUT_Enable;
+		ni_stc_writew(dev, devpriv->clock_and_fout,
+			      Clock_and_FOUT_Register);
+		devpriv->clock_and_fout &= ~FOUT_Divider_mask;
 
-static void ni_get_freq_out_clock(struct comedi_device *dev,
-				  unsigned int *clock_source,
-				  unsigned int *clock_period_ns)
-{
-	struct ni_private *devpriv = dev->private;
+		/* use the last data value to set the fout divider */
+		devpriv->clock_and_fout |= FOUT_Divider(data[insn->n - 1]);
 
-	if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
-		*clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
-		*clock_period_ns = TIMEBASE_2_NS;
-	} else {
-		*clock_source = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC;
-		*clock_period_ns = TIMEBASE_1_NS * 2;
+		devpriv->clock_and_fout |= FOUT_Enable;
+		ni_stc_writew(dev, devpriv->clock_and_fout,
+			      Clock_and_FOUT_Register);
 	}
+	return insn->n;
 }
 
 static int ni_freq_out_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	switch (data[0]) {
 	case INSN_CONFIG_SET_CLOCK_SRC:
-		return ni_set_freq_out_clock(dev, data[1]);
+		switch (data[1]) {
+		case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
+			devpriv->clock_and_fout &= ~FOUT_Timebase_Select;
+			break;
+		case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC:
+			devpriv->clock_and_fout |= FOUT_Timebase_Select;
+			break;
+		default:
+			return -EINVAL;
+		}
+		ni_stc_writew(dev, devpriv->clock_and_fout,
+			      Clock_and_FOUT_Register);
 		break;
 	case INSN_CONFIG_GET_CLOCK_SRC:
-		ni_get_freq_out_clock(dev, &data[1], &data[2]);
-		return 3;
-	default:
+		if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
+			data[1] = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
+			data[2] = TIMEBASE_2_NS;
+		} else {
+			data[1] = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC;
+			data[2] = TIMEBASE_1_NS * 2;
+		}
 		break;
-	}
-	return -EINVAL;
-}
-
-static int ni_alloc_private(struct comedi_device *dev)
-{
-	struct ni_private *devpriv;
-
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
-
-	spin_lock_init(&devpriv->window_lock);
-	spin_lock_init(&devpriv->soft_reg_copy_lock);
-	spin_lock_init(&devpriv->mite_channel_lock);
-
-	return 0;
-};
-
-static int ni_E_init(struct comedi_device *dev)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-	unsigned j;
-	enum ni_gpct_variant counter_variant;
-	int ret;
-
-	if (board->n_aochan > MAX_N_AO_CHAN) {
-		printk("bug! n_aochan > MAX_N_AO_CHAN\n");
+	default:
 		return -EINVAL;
 	}
-
-	ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES);
-	if (ret)
-		return ret;
-
-	/* analog input subdevice */
-
-	s = &dev->subdevices[NI_AI_SUBDEV];
-	dev->read_subdev = s;
-	if (board->n_adchan) {
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags =
-		    SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ;
-		if (board->reg_type != ni_reg_611x)
-			s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER;
-		if (board->adbits > 16)
-			s->subdev_flags |= SDF_LSAMPL;
-		if (board->reg_type & ni_reg_m_series_mask)
-			s->subdev_flags |= SDF_SOFT_CALIBRATED;
-		s->n_chan = board->n_adchan;
-		s->len_chanlist = 512;
-		s->maxdata = (1 << board->adbits) - 1;
-		s->range_table = ni_range_lkup[board->gainlkup];
-		s->insn_read = &ni_ai_insn_read;
-		s->insn_config = &ni_ai_insn_config;
-		s->do_cmdtest = &ni_ai_cmdtest;
-		s->do_cmd = &ni_ai_cmd;
-		s->cancel = &ni_ai_reset;
-		s->poll = &ni_ai_poll;
-		s->munge = &ni_ai_munge;
-#ifdef PCIDMA
-		s->async_dma_dir = DMA_FROM_DEVICE;
-#endif
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
-
-	/* analog output subdevice */
-
-	s = &dev->subdevices[NI_AO_SUBDEV];
-	if (board->n_aochan) {
-		s->type = COMEDI_SUBD_AO;
-		s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND;
-		if (board->reg_type & ni_reg_m_series_mask)
-			s->subdev_flags |= SDF_SOFT_CALIBRATED;
-		s->n_chan = board->n_aochan;
-		s->maxdata = (1 << board->aobits) - 1;
-		s->range_table = board->ao_range_table;
-		s->insn_read = &ni_ao_insn_read;
-		if (board->reg_type & ni_reg_6xxx_mask)
-			s->insn_write = &ni_ao_insn_write_671x;
-		else
-			s->insn_write = &ni_ao_insn_write;
-		s->insn_config = &ni_ao_insn_config;
-#ifdef PCIDMA
-		if (board->n_aochan) {
-			s->async_dma_dir = DMA_TO_DEVICE;
-#else
-		if (board->ao_fifo_depth) {
-#endif
-			dev->write_subdev = s;
-			s->subdev_flags |= SDF_CMD_WRITE;
-			s->do_cmd = &ni_ao_cmd;
-			s->do_cmdtest = &ni_ao_cmdtest;
-			s->len_chanlist = board->n_aochan;
-			if ((board->reg_type & ni_reg_m_series_mask) == 0)
-				s->munge = ni_ao_munge;
-		}
-		s->cancel = &ni_ao_reset;
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
-	if ((board->reg_type & ni_reg_67xx_mask))
-		init_ao_67xx(dev, s);
-
-	/* digital i/o subdevice */
-
-	s = &dev->subdevices[NI_DIO_SUBDEV];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->maxdata = 1;
-	s->io_bits = 0;		/* all bits input */
-	s->range_table = &range_digital;
-	s->n_chan = board->num_p0_dio_channels;
-	if (board->reg_type & ni_reg_m_series_mask) {
-		s->subdev_flags |=
-		    SDF_LSAMPL | SDF_CMD_WRITE /* | SDF_CMD_READ */;
-		s->insn_bits = &ni_m_series_dio_insn_bits;
-		s->insn_config = &ni_m_series_dio_insn_config;
-		s->do_cmd = &ni_cdio_cmd;
-		s->do_cmdtest = &ni_cdio_cmdtest;
-		s->cancel = &ni_cdio_cancel;
-		s->async_dma_dir = DMA_BIDIRECTIONAL;
-		s->len_chanlist = s->n_chan;
-
-		ni_writel(CDO_Reset_Bit | CDI_Reset_Bit, M_Offset_CDIO_Command);
-		ni_writel(s->io_bits, M_Offset_DIO_Direction);
-	} else {
-		s->insn_bits = &ni_dio_insn_bits;
-		s->insn_config = &ni_dio_insn_config;
-		devpriv->dio_control = DIO_Pins_Dir(s->io_bits);
-		ni_writew(devpriv->dio_control, DIO_Control_Register);
-	}
-
-	/* 8255 device */
-	s = &dev->subdevices[NI_8255_DIO_SUBDEV];
-	if (board->has_8255) {
-		ret = subdev_8255_init(dev, s, ni_8255_callback,
-				       (unsigned long)dev);
-		if (ret)
-			return ret;
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
-
-	/* formerly general purpose counter/timer device, but no longer used */
-	s = &dev->subdevices[NI_UNUSED_SUBDEV];
-	s->type = COMEDI_SUBD_UNUSED;
-
-	/* calibration subdevice -- ai and ao */
-	s = &dev->subdevices[NI_CALIBRATION_SUBDEV];
-	s->type = COMEDI_SUBD_CALIB;
-	if (board->reg_type & ni_reg_m_series_mask) {
-		/*  internal PWM analog output used for AI nonlinearity calibration */
-		s->subdev_flags = SDF_INTERNAL;
-		s->insn_config = &ni_m_series_pwm_config;
-		s->n_chan = 1;
-		s->maxdata = 0;
-		ni_writel(0x0, M_Offset_Cal_PWM);
-	} else if (board->reg_type == ni_reg_6143) {
-		/*  internal PWM analog output used for AI nonlinearity calibration */
-		s->subdev_flags = SDF_INTERNAL;
-		s->insn_config = &ni_6143_pwm_config;
-		s->n_chan = 1;
-		s->maxdata = 0;
-	} else {
-		s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
-		s->insn_read = &ni_calib_insn_read;
-		s->insn_write = &ni_calib_insn_write;
-		caldac_setup(dev, s);
-	}
-
-	/* EEPROM */
-	s = &dev->subdevices[NI_EEPROM_SUBDEV];
-	s->type = COMEDI_SUBD_MEMORY;
-	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
-	s->maxdata = 0xff;
-	if (board->reg_type & ni_reg_m_series_mask) {
-		s->n_chan = M_SERIES_EEPROM_SIZE;
-		s->insn_read = &ni_m_series_eeprom_insn_read;
-	} else {
-		s->n_chan = 512;
-		s->insn_read = &ni_eeprom_insn_read;
-	}
-
-	/* PFI */
-	s = &dev->subdevices[NI_PFI_DIO_SUBDEV];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-	if (board->reg_type & ni_reg_m_series_mask) {
-		unsigned i;
-		s->n_chan = 16;
-		ni_writew(s->state, M_Offset_PFI_DO);
-		for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) {
-			ni_writew(devpriv->pfi_output_select_reg[i],
-				  M_Offset_PFI_Output_Select(i + 1));
-		}
-	} else {
-		s->n_chan = 10;
-	}
-	s->maxdata = 1;
-	if (board->reg_type & ni_reg_m_series_mask)
-		s->insn_bits = &ni_pfi_insn_bits;
-	s->insn_config = &ni_pfi_insn_config;
-	ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0);
-
-	/* cs5529 calibration adc */
-	s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV];
-	if (board->reg_type & ni_reg_67xx_mask) {
-		s->type = COMEDI_SUBD_AI;
-		s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL;
-		/*  one channel for each analog output channel */
-		s->n_chan = board->n_aochan;
-		s->maxdata = (1 << 16) - 1;
-		s->range_table = &range_unknown;	/* XXX */
-		s->insn_read = cs5529_ai_insn_read;
-		s->insn_config = NULL;
-		init_cs5529(dev);
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
-
-	/* Serial */
-	s = &dev->subdevices[NI_SERIAL_SUBDEV];
-	s->type = COMEDI_SUBD_SERIAL;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-	s->n_chan = 1;
-	s->maxdata = 0xff;
-	s->insn_config = ni_serial_insn_config;
-	devpriv->serial_interval_ns = 0;
-	devpriv->serial_hw_mode = 0;
-
-	/* RTSI */
-	s = &dev->subdevices[NI_RTSI_SUBDEV];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->insn_bits = ni_rtsi_insn_bits;
-	s->insn_config = ni_rtsi_insn_config;
-	ni_rtsi_init(dev);
-
-	if (board->reg_type & ni_reg_m_series_mask)
-		counter_variant = ni_gpct_variant_m_series;
-	else
-		counter_variant = ni_gpct_variant_e_series;
-	devpriv->counter_dev = ni_gpct_device_construct(dev,
-							&ni_gpct_write_register,
-							&ni_gpct_read_register,
-							counter_variant,
-							NUM_GPCT);
-	if (!devpriv->counter_dev)
-		return -ENOMEM;
-
-	/* General purpose counters */
-	for (j = 0; j < NUM_GPCT; ++j) {
-		s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
-		s->type = COMEDI_SUBD_COUNTER;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
-		s->n_chan = 3;
-		if (board->reg_type & ni_reg_m_series_mask)
-			s->maxdata = 0xffffffff;
-		else
-			s->maxdata = 0xffffff;
-		s->insn_read = ni_tio_insn_read;
-		s->insn_write = ni_tio_insn_read;
-		s->insn_config = ni_tio_insn_config;
-#ifdef PCIDMA
-		s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */;
-		s->do_cmd = &ni_gpct_cmd;
-		s->len_chanlist = 1;
-		s->do_cmdtest = ni_tio_cmdtest;
-		s->cancel = &ni_gpct_cancel;
-		s->async_dma_dir = DMA_BIDIRECTIONAL;
-#endif
-		s->private = &devpriv->counter_dev->counters[j];
-
-		devpriv->counter_dev->counters[j].chip_index = 0;
-		devpriv->counter_dev->counters[j].counter_index = j;
-		ni_tio_init_counter(&devpriv->counter_dev->counters[j]);
-	}
-
-	/* Frequency output */
-	s = &dev->subdevices[NI_FREQ_OUT_SUBDEV];
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 1;
-	s->maxdata = 0xf;
-	s->insn_read = &ni_freq_out_insn_read;
-	s->insn_write = &ni_freq_out_insn_write;
-	s->insn_config = &ni_freq_out_insn_config;
-
-	/* ai configuration */
-	s = &dev->subdevices[NI_AI_SUBDEV];
-	ni_ai_reset(dev, s);
-	if ((board->reg_type & ni_reg_6xxx_mask) == 0) {
-		/*  BEAM is this needed for PCI-6143 ?? */
-		devpriv->clock_and_fout =
-		    Slow_Internal_Time_Divide_By_2 |
-		    Slow_Internal_Timebase |
-		    Clock_To_Board_Divide_By_2 |
-		    Clock_To_Board |
-		    AI_Output_Divide_By_2 | AO_Output_Divide_By_2;
-	} else {
-		devpriv->clock_and_fout =
-		    Slow_Internal_Time_Divide_By_2 |
-		    Slow_Internal_Timebase |
-		    Clock_To_Board_Divide_By_2 | Clock_To_Board;
-	}
-	devpriv->stc_writew(dev, devpriv->clock_and_fout,
-			    Clock_and_FOUT_Register);
-
-	/* analog output configuration */
-	s = &dev->subdevices[NI_AO_SUBDEV];
-	ni_ao_reset(dev, s);
-
-	if (dev->irq) {
-		devpriv->stc_writew(dev,
-				    (IRQ_POLARITY ? Interrupt_Output_Polarity :
-				     0) | (Interrupt_Output_On_3_Pins & 0) |
-				    Interrupt_A_Enable | Interrupt_B_Enable |
-				    Interrupt_A_Output_Select(interrupt_pin
-							      (dev->irq)) |
-				    Interrupt_B_Output_Select(interrupt_pin
-							      (dev->irq)),
-				    Interrupt_Control_Register);
-	}
-
-	/* DMA setup */
-	ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
-	ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select);
-
-	if (board->reg_type & ni_reg_6xxx_mask) {
-		ni_writeb(0, Magic_611x);
-	} else if (board->reg_type & ni_reg_m_series_mask) {
-		int channel;
-		for (channel = 0; channel < board->n_aochan; ++channel) {
-			ni_writeb(0xf, M_Offset_AO_Waveform_Order(channel));
-			ni_writeb(0x0,
-				  M_Offset_AO_Reference_Attenuation(channel));
-		}
-		ni_writeb(0x0, M_Offset_AO_Calibration);
-	}
-
-	return 0;
+	return insn->n;
 }
 
 static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
 {
 	struct comedi_device *dev = (struct comedi_device *)arg;
-	struct ni_private *devpriv __maybe_unused = dev->private;
 
 	if (dir) {
-		ni_writeb(data, Port_A + 2 * port);
+		ni_writeb(dev, data, Port_A + 2 * port);
 		return 0;
-	} else {
-		return ni_readb(Port_A + 2 * port);
-	}
-}
-
-/*
-	presents the EEPROM as a subdevice
-*/
-
-static int ni_eeprom_insn_read(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
-{
-	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
-
-	return 1;
-}
-
-/*
-	reads bytes out of eeprom
-*/
-
-static int ni_read_eeprom(struct comedi_device *dev, int addr)
-{
-	struct ni_private *devpriv __maybe_unused = dev->private;
-	int bit;
-	int bitstring;
-
-	bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff);
-	ni_writeb(0x04, Serial_Command);
-	for (bit = 0x8000; bit; bit >>= 1) {
-		ni_writeb(0x04 | ((bit & bitstring) ? 0x02 : 0),
-			  Serial_Command);
-		ni_writeb(0x05 | ((bit & bitstring) ? 0x02 : 0),
-			  Serial_Command);
 	}
-	bitstring = 0;
-	for (bit = 0x80; bit; bit >>= 1) {
-		ni_writeb(0x04, Serial_Command);
-		ni_writeb(0x05, Serial_Command);
-		bitstring |= ((ni_readb(XXX_Status) & PROMOUT) ? bit : 0);
-	}
-	ni_writeb(0x00, Serial_Command);
-
-	return bitstring;
-}
-
-static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn,
-					unsigned int *data)
-{
-	struct ni_private *devpriv = dev->private;
 
-	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
-
-	return 1;
+	return ni_readb(dev, Port_A + 2 * port);
 }
 
 static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data)
@@ -4567,7 +4199,8 @@ static int ni_get_pwm_config(struct come
 
 static int ni_m_series_pwm_config(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
 	unsigned up_count, down_count;
@@ -4590,7 +4223,6 @@ static int ni_m_series_pwm_config(struct
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		switch (data[3]) {
 		case TRIG_ROUND_NEAREST:
@@ -4608,7 +4240,6 @@ static int ni_m_series_pwm_config(struct
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		if (up_count * devpriv->clock_ns != data[2] ||
 		    down_count * devpriv->clock_ns != data[4]) {
@@ -4616,26 +4247,24 @@ static int ni_m_series_pwm_config(struct
 			data[4] = down_count * devpriv->clock_ns;
 			return -EAGAIN;
 		}
-		ni_writel(MSeries_Cal_PWM_High_Time_Bits(up_count) |
-			  MSeries_Cal_PWM_Low_Time_Bits(down_count),
+		ni_writel(dev, MSeries_Cal_PWM_High_Time_Bits(up_count) |
+			       MSeries_Cal_PWM_Low_Time_Bits(down_count),
 			  M_Offset_Cal_PWM);
 		devpriv->pwm_up_count = up_count;
 		devpriv->pwm_down_count = down_count;
 		return 5;
-		break;
 	case INSN_CONFIG_GET_PWM_OUTPUT:
 		return ni_get_pwm_config(dev, data);
-		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 0;
 }
 
 static int ni_6143_pwm_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
 	unsigned up_count, down_count;
@@ -4658,7 +4287,6 @@ static int ni_6143_pwm_config(struct com
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		switch (data[3]) {
 		case TRIG_ROUND_NEAREST:
@@ -4676,7 +4304,6 @@ static int ni_6143_pwm_config(struct com
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		if (up_count * devpriv->clock_ns != data[2] ||
 		    down_count * devpriv->clock_ns != data[4]) {
@@ -4684,51 +4311,66 @@ static int ni_6143_pwm_config(struct com
 			data[4] = down_count * devpriv->clock_ns;
 			return -EAGAIN;
 		}
-		ni_writel(up_count, Calibration_HighTime_6143);
+		ni_writel(dev, up_count, Calibration_HighTime_6143);
 		devpriv->pwm_up_count = up_count;
-		ni_writel(down_count, Calibration_LowTime_6143);
+		ni_writel(dev, down_count, Calibration_LowTime_6143);
 		devpriv->pwm_down_count = down_count;
 		return 5;
-		break;
 	case INSN_CONFIG_GET_PWM_OUTPUT:
 		return ni_get_pwm_config(dev, data);
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 0;
 }
 
-static void ni_write_caldac(struct comedi_device *dev, int addr, int val);
-/*
-	calibration subdevice
-*/
-static int ni_calib_insn_write(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+static int pack_mb88341(int addr, int val, int *bitstring)
 {
-	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+	/*
+	   Fujitsu MB 88341
+	   Note that address bits are reversed.  Thanks to
+	   Ingo Keen for noticing this.
 
-	return 1;
+	   Note also that the 88341 expects address values from
+	   1-12, whereas we use channel numbers 0-11.  The NI
+	   docs use 1-12, also, so be careful here.
+	 */
+	addr++;
+	*bitstring = ((addr & 0x1) << 11) |
+	    ((addr & 0x2) << 9) |
+	    ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff);
+	return 12;
 }
 
-static int ni_calib_insn_read(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+static int pack_dac8800(int addr, int val, int *bitstring)
 {
-	struct ni_private *devpriv = dev->private;
+	*bitstring = ((addr & 0x7) << 8) | (val & 0xff);
+	return 11;
+}
 
-	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+static int pack_dac8043(int addr, int val, int *bitstring)
+{
+	*bitstring = val & 0xfff;
+	return 12;
+}
 
-	return 1;
+static int pack_ad8522(int addr, int val, int *bitstring)
+{
+	*bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000);
+	return 16;
 }
 
-static int pack_mb88341(int addr, int val, int *bitstring);
-static int pack_dac8800(int addr, int val, int *bitstring);
-static int pack_dac8043(int addr, int val, int *bitstring);
-static int pack_ad8522(int addr, int val, int *bitstring);
-static int pack_ad8804(int addr, int val, int *bitstring);
-static int pack_ad8842(int addr, int val, int *bitstring);
+static int pack_ad8804(int addr, int val, int *bitstring)
+{
+	*bitstring = ((addr & 0xf) << 8) | (val & 0xff);
+	return 12;
+}
+
+static int pack_ad8842(int addr, int val, int *bitstring)
+{
+	*bitstring = ((addr + 1) << 8) | (val & 0xff);
+	return 12;
+}
 
 struct caldac_struct {
 	int n_chans;
@@ -4746,6 +4388,64 @@ static struct caldac_struct caldacs[] =
 	[ad8804_debug] = {16, 8, pack_ad8804},
 };
 
+static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
+{
+	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
+	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
+	int i;
+	int type;
+
+	if (devpriv->caldacs[addr] == val)
+		return;
+	devpriv->caldacs[addr] = val;
+
+	for (i = 0; i < 3; i++) {
+		type = board->caldac[i];
+		if (type == caldac_none)
+			break;
+		if (addr < caldacs[type].n_chans) {
+			bits = caldacs[type].packbits(addr, val, &bitstring);
+			loadbit = SerDacLd(i);
+			break;
+		}
+		addr -= caldacs[type].n_chans;
+	}
+
+	for (bit = 1 << (bits - 1); bit; bit >>= 1) {
+		ni_writeb(dev, ((bit & bitstring) ? 0x02 : 0), Serial_Command);
+		udelay(1);
+		ni_writeb(dev, 1 | ((bit & bitstring) ? 0x02 : 0),
+			  Serial_Command);
+		udelay(1);
+	}
+	ni_writeb(dev, loadbit, Serial_Command);
+	udelay(1);
+	ni_writeb(dev, 0, Serial_Command);
+}
+
+static int ni_calib_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+
+	return 1;
+}
+
+static int ni_calib_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
+{
+	struct ni_private *devpriv = dev->private;
+
+	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+
+	return 1;
+}
+
 static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
@@ -4777,7 +4477,8 @@ static void caldac_setup(struct comedi_d
 		unsigned int *maxdata_list;
 
 		if (n_chans > MAX_N_CALDACS)
-			printk("BUG! MAX_N_CALDACS too small\n");
+			dev_err(dev->class_dev,
+				"BUG! MAX_N_CALDACS too small\n");
 		s->maxdata_list = maxdata_list = devpriv->caldac_maxdata_list;
 		chan = 0;
 		for (i = 0; i < n_dacs; i++) {
@@ -4800,221 +4501,106 @@ static void caldac_setup(struct comedi_d
 	}
 }
 
-static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
+static int ni_read_eeprom(struct comedi_device *dev, int addr)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv = dev->private;
-	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
-	int i;
-	int type;
-
-	/* printk("ni_write_caldac: chan=%d val=%d\n",addr,val); */
-	if (devpriv->caldacs[addr] == val)
-		return;
-	devpriv->caldacs[addr] = val;
+	int bit;
+	int bitstring;
 
-	for (i = 0; i < 3; i++) {
-		type = board->caldac[i];
-		if (type == caldac_none)
-			break;
-		if (addr < caldacs[type].n_chans) {
-			bits = caldacs[type].packbits(addr, val, &bitstring);
-			loadbit = SerDacLd(i);
-			/* printk("caldac: using i=%d addr=%d %x\n",i,addr,bitstring); */
-			break;
-		}
-		addr -= caldacs[type].n_chans;
+	bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff);
+	ni_writeb(dev, 0x04, Serial_Command);
+	for (bit = 0x8000; bit; bit >>= 1) {
+		ni_writeb(dev, 0x04 | ((bit & bitstring) ? 0x02 : 0),
+			  Serial_Command);
+		ni_writeb(dev, 0x05 | ((bit & bitstring) ? 0x02 : 0),
+			  Serial_Command);
 	}
-
-	for (bit = 1 << (bits - 1); bit; bit >>= 1) {
-		ni_writeb(((bit & bitstring) ? 0x02 : 0), Serial_Command);
-		udelay(1);
-		ni_writeb(1 | ((bit & bitstring) ? 0x02 : 0), Serial_Command);
-		udelay(1);
+	bitstring = 0;
+	for (bit = 0x80; bit; bit >>= 1) {
+		ni_writeb(dev, 0x04, Serial_Command);
+		ni_writeb(dev, 0x05, Serial_Command);
+		bitstring |= ((ni_readb(dev, XXX_Status) & PROMOUT) ? bit : 0);
 	}
-	ni_writeb(loadbit, Serial_Command);
-	udelay(1);
-	ni_writeb(0, Serial_Command);
-}
-
-static int pack_mb88341(int addr, int val, int *bitstring)
-{
-	/*
-	   Fujitsu MB 88341
-	   Note that address bits are reversed.  Thanks to
-	   Ingo Keen for noticing this.
-
-	   Note also that the 88341 expects address values from
-	   1-12, whereas we use channel numbers 0-11.  The NI
-	   docs use 1-12, also, so be careful here.
-	 */
-	addr++;
-	*bitstring = ((addr & 0x1) << 11) |
-	    ((addr & 0x2) << 9) |
-	    ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff);
-	return 12;
-}
-
-static int pack_dac8800(int addr, int val, int *bitstring)
-{
-	*bitstring = ((addr & 0x7) << 8) | (val & 0xff);
-	return 11;
-}
-
-static int pack_dac8043(int addr, int val, int *bitstring)
-{
-	*bitstring = val & 0xfff;
-	return 12;
-}
+	ni_writeb(dev, 0x00, Serial_Command);
 
-static int pack_ad8522(int addr, int val, int *bitstring)
-{
-	*bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000);
-	return 16;
+	return bitstring;
 }
 
-static int pack_ad8804(int addr, int val, int *bitstring)
+static int ni_eeprom_insn_read(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	*bitstring = ((addr & 0xf) << 8) | (val & 0xff);
-	return 12;
-}
+	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
 
-static int pack_ad8842(int addr, int val, int *bitstring)
-{
-	*bitstring = ((addr + 1) << 8) | (val & 0xff);
-	return 12;
+	return 1;
 }
 
-#if 0
-/*
- *	Read the GPCTs current value.
- */
-static int GPCT_G_Watch(struct comedi_device *dev, int chan)
+static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
-	unsigned int hi1, hi2, lo;
-
-	devpriv->gpct_command[chan] &= ~G_Save_Trace;
-	devpriv->stc_writew(dev, devpriv->gpct_command[chan],
-			    G_Command_Register(chan));
-
-	devpriv->gpct_command[chan] |= G_Save_Trace;
-	devpriv->stc_writew(dev, devpriv->gpct_command[chan],
-			    G_Command_Register(chan));
+	struct ni_private *devpriv = dev->private;
 
-	/* This procedure is used because the two registers cannot
-	 * be read atomically. */
-	do {
-		hi1 = devpriv->stc_readw(dev, G_Save_Register_High(chan));
-		lo = devpriv->stc_readw(dev, G_Save_Register_Low(chan));
-		hi2 = devpriv->stc_readw(dev, G_Save_Register_High(chan));
-	} while (hi1 != hi2);
+	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
 
-	return (hi1 << 16) | lo;
+	return 1;
 }
 
-static void GPCT_Reset(struct comedi_device *dev, int chan)
+static unsigned ni_old_get_pfi_routing(struct comedi_device *dev,
+				       unsigned chan)
 {
-	int temp_ack_reg = 0;
-
-	/* printk("GPCT_Reset..."); */
-	devpriv->gpct_cur_operation[chan] = GPCT_RESET;
-
+	/*  pre-m-series boards have fixed signals on pfi pins */
 	switch (chan) {
 	case 0:
-		devpriv->stc_writew(dev, G0_Reset, Joint_Reset_Register);
-		ni_set_bits(dev, Interrupt_A_Enable_Register,
-			    G0_TC_Interrupt_Enable, 0);
-		ni_set_bits(dev, Interrupt_A_Enable_Register,
-			    G0_Gate_Interrupt_Enable, 0);
-		temp_ack_reg |= G0_Gate_Error_Confirm;
-		temp_ack_reg |= G0_TC_Error_Confirm;
-		temp_ack_reg |= G0_TC_Interrupt_Ack;
-		temp_ack_reg |= G0_Gate_Interrupt_Ack;
-		devpriv->stc_writew(dev, temp_ack_reg,
-				    Interrupt_A_Ack_Register);
-
-		/* problem...this interferes with the other ctr... */
-		devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable;
-		devpriv->stc_writew(dev, devpriv->an_trig_etc_reg,
-				    Analog_Trigger_Etc_Register);
-		break;
+		return NI_PFI_OUTPUT_AI_START1;
 	case 1:
-		devpriv->stc_writew(dev, G1_Reset, Joint_Reset_Register);
-		ni_set_bits(dev, Interrupt_B_Enable_Register,
-			    G1_TC_Interrupt_Enable, 0);
-		ni_set_bits(dev, Interrupt_B_Enable_Register,
-			    G0_Gate_Interrupt_Enable, 0);
-		temp_ack_reg |= G1_Gate_Error_Confirm;
-		temp_ack_reg |= G1_TC_Error_Confirm;
-		temp_ack_reg |= G1_TC_Interrupt_Ack;
-		temp_ack_reg |= G1_Gate_Interrupt_Ack;
-		devpriv->stc_writew(dev, temp_ack_reg,
-				    Interrupt_B_Ack_Register);
-
-		devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable;
-		devpriv->stc_writew(dev, devpriv->an_trig_etc_reg,
-				    Analog_Trigger_Etc_Register);
+		return NI_PFI_OUTPUT_AI_START2;
+	case 2:
+		return NI_PFI_OUTPUT_AI_CONVERT;
+	case 3:
+		return NI_PFI_OUTPUT_G_SRC1;
+	case 4:
+		return NI_PFI_OUTPUT_G_GATE1;
+	case 5:
+		return NI_PFI_OUTPUT_AO_UPDATE_N;
+	case 6:
+		return NI_PFI_OUTPUT_AO_START1;
+	case 7:
+		return NI_PFI_OUTPUT_AI_START_PULSE;
+	case 8:
+		return NI_PFI_OUTPUT_G_SRC0;
+	case 9:
+		return NI_PFI_OUTPUT_G_GATE0;
+	default:
+		dev_err(dev->class_dev,
+			"%s: bug, unhandled case in switch.\n", __func__);
 		break;
 	}
-
-	devpriv->gpct_mode[chan] = 0;
-	devpriv->gpct_input_select[chan] = 0;
-	devpriv->gpct_command[chan] = 0;
-
-	devpriv->gpct_command[chan] |= G_Synchronized_Gate;
-
-	devpriv->stc_writew(dev, devpriv->gpct_mode[chan],
-			    G_Mode_Register(chan));
-	devpriv->stc_writew(dev, devpriv->gpct_input_select[chan],
-			    G_Input_Select_Register(chan));
-	devpriv->stc_writew(dev, 0, G_Autoincrement_Register(chan));
-
-	/* printk("exit GPCT_Reset\n"); */
+	return 0;
 }
 
-#endif
-
-#ifdef PCIDMA
-static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+static int ni_old_set_pfi_routing(struct comedi_device *dev,
+				  unsigned chan, unsigned source)
 {
-	struct ni_gpct *counter = s->private;
-	int retval;
-
-	retval = ni_request_gpct_mite_channel(dev, counter->counter_index,
-					      COMEDI_INPUT);
-	if (retval) {
-		comedi_error(dev,
-			     "no dma channel available for use by counter");
-		return retval;
-	}
-	ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
-	ni_e_series_enable_second_irq(dev, counter->counter_index, 1);
-
-	return ni_tio_cmd(dev, s);
+	/*  pre-m-series boards have fixed signals on pfi pins */
+	if (source != ni_old_get_pfi_routing(dev, chan))
+		return -EINVAL;
+	return 2;
 }
-#endif
 
-#ifdef PCIDMA
-static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev,
+					    unsigned chan)
 {
-	struct ni_gpct *counter = s->private;
-	int retval;
+	struct ni_private *devpriv = dev->private;
+	const unsigned array_offset = chan / 3;
 
-	retval = ni_tio_cancel(counter);
-	ni_e_series_enable_second_irq(dev, counter->counter_index, 0);
-	ni_release_gpct_mite_channel(dev, counter->counter_index);
-	return retval;
+	return MSeries_PFI_Output_Select_Source(chan,
+				devpriv->pfi_output_select_reg[array_offset]);
 }
-#endif
-
-/*
- *
- *  Programmable Function Inputs
- *
- */
 
-static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan,
-				       unsigned source)
+static int ni_m_series_set_pfi_routing(struct comedi_device *dev,
+				       unsigned chan, unsigned source)
 {
 	struct ni_private *devpriv = dev->private;
 	unsigned pfi_reg_index;
@@ -5028,132 +4614,51 @@ static int ni_m_series_set_pfi_routing(s
 	    ~MSeries_PFI_Output_Select_Mask(chan);
 	devpriv->pfi_output_select_reg[array_offset] |=
 	    MSeries_PFI_Output_Select_Bits(chan, source);
-	ni_writew(devpriv->pfi_output_select_reg[array_offset],
+	ni_writew(dev, devpriv->pfi_output_select_reg[array_offset],
 		  M_Offset_PFI_Output_Select(pfi_reg_index));
 	return 2;
 }
 
-static int ni_old_set_pfi_routing(struct comedi_device *dev, unsigned chan,
-				  unsigned source)
+static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 {
-	/*  pre-m-series boards have fixed signals on pfi pins */
-	if (source != ni_old_get_pfi_routing(dev, chan))
-		return -EINVAL;
-	return 2;
+	struct ni_private *devpriv = dev->private;
+
+	return (devpriv->is_m_series)
+			? ni_m_series_get_pfi_routing(dev, chan)
+			: ni_old_get_pfi_routing(dev, chan);
 }
 
 static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 			      unsigned source)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-
-	if (board->reg_type & ni_reg_m_series_mask)
-		return ni_m_series_set_pfi_routing(dev, chan, source);
-	else
-		return ni_old_set_pfi_routing(dev, chan, source);
-}
-
-static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev,
-					    unsigned chan)
-{
 	struct ni_private *devpriv = dev->private;
-	const unsigned array_offset = chan / 3;
-
-	return MSeries_PFI_Output_Select_Source(chan,
-						devpriv->
-						pfi_output_select_reg
-						[array_offset]);
-}
-
-static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan)
-{
-	/*  pre-m-series boards have fixed signals on pfi pins */
-	switch (chan) {
-	case 0:
-		return NI_PFI_OUTPUT_AI_START1;
-		break;
-	case 1:
-		return NI_PFI_OUTPUT_AI_START2;
-		break;
-	case 2:
-		return NI_PFI_OUTPUT_AI_CONVERT;
-		break;
-	case 3:
-		return NI_PFI_OUTPUT_G_SRC1;
-		break;
-	case 4:
-		return NI_PFI_OUTPUT_G_GATE1;
-		break;
-	case 5:
-		return NI_PFI_OUTPUT_AO_UPDATE_N;
-		break;
-	case 6:
-		return NI_PFI_OUTPUT_AO_START1;
-		break;
-	case 7:
-		return NI_PFI_OUTPUT_AI_START_PULSE;
-		break;
-	case 8:
-		return NI_PFI_OUTPUT_G_SRC0;
-		break;
-	case 9:
-		return NI_PFI_OUTPUT_G_GATE0;
-		break;
-	default:
-		printk("%s: bug, unhandled case in switch.\n", __func__);
-		break;
-	}
-	return 0;
-}
 
-static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-
-	if (board->reg_type & ni_reg_m_series_mask)
-		return ni_m_series_get_pfi_routing(dev, chan);
-	else
-		return ni_old_get_pfi_routing(dev, chan);
+	return (devpriv->is_m_series)
+			? ni_m_series_set_pfi_routing(dev, chan, source)
+			: ni_old_set_pfi_routing(dev, chan, source);
 }
 
-static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
+static int ni_config_filter(struct comedi_device *dev,
+			    unsigned pfi_channel,
 			    enum ni_pfi_filter_select filter)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv __maybe_unused = dev->private;
+	struct ni_private *devpriv = dev->private;
 	unsigned bits;
 
-	if ((board->reg_type & ni_reg_m_series_mask) == 0)
+	if (!devpriv->is_m_series)
 		return -ENOTSUPP;
-	bits = ni_readl(M_Offset_PFI_Filter);
+
+	bits = ni_readl(dev, M_Offset_PFI_Filter);
 	bits &= ~MSeries_PFI_Filter_Select_Mask(pfi_channel);
 	bits |= MSeries_PFI_Filter_Select_Bits(pfi_channel, filter);
-	ni_writel(bits, M_Offset_PFI_Filter);
+	ni_writel(dev, bits, M_Offset_PFI_Filter);
 	return 0;
 }
 
-static int ni_pfi_insn_bits(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn,
-			    unsigned int *data)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-	struct ni_private *devpriv __maybe_unused = dev->private;
-
-	if (!(board->reg_type & ni_reg_m_series_mask))
-		return -ENOTSUPP;
-
-	if (comedi_dio_update_state(s, data))
-		ni_writew(s->state, M_Offset_PFI_DO);
-
-	data[1] = ni_readw(M_Offset_PFI_DI);
-
-	return insn->n;
-}
-
 static int ni_pfi_insn_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan;
@@ -5175,78 +4680,178 @@ static int ni_pfi_insn_config(struct com
 		    (devpriv->io_bidirection_pin_reg & (1 << chan)) ?
 		    COMEDI_OUTPUT : COMEDI_INPUT;
 		return 0;
-		break;
 	case INSN_CONFIG_SET_ROUTING:
 		return ni_set_pfi_routing(dev, chan, data[1]);
-		break;
 	case INSN_CONFIG_GET_ROUTING:
 		data[1] = ni_get_pfi_routing(dev, chan);
 		break;
 	case INSN_CONFIG_FILTER:
 		return ni_config_filter(dev, chan, data[1]);
-		break;
 	default:
 		return -EINVAL;
 	}
 	return 0;
 }
 
-/*
- *
- *  NI RTSI Bus Functions
- *
- */
-static void ni_rtsi_init(struct comedi_device *dev)
+static int ni_pfi_insn_bits(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
-	/*  Initialises the RTSI bus signal switch to a default state */
+	if (!devpriv->is_m_series)
+		return -ENOTSUPP;
 
-	/*  Set clock mode to internal */
-	devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit;
-	if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0)
-		printk("ni_set_master_clock failed, bug?");
-	/*  default internal lines routing to RTSI bus lines */
-	devpriv->rtsi_trig_a_output_reg =
-	    RTSI_Trig_Output_Bits(0,
-				  NI_RTSI_OUTPUT_ADR_START1) |
-	    RTSI_Trig_Output_Bits(1,
-				  NI_RTSI_OUTPUT_ADR_START2) |
-	    RTSI_Trig_Output_Bits(2,
-				  NI_RTSI_OUTPUT_SCLKG) |
-	    RTSI_Trig_Output_Bits(3, NI_RTSI_OUTPUT_DACUPDN);
-	devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
-			    RTSI_Trig_A_Output_Register);
-	devpriv->rtsi_trig_b_output_reg =
-	    RTSI_Trig_Output_Bits(4,
-				  NI_RTSI_OUTPUT_DA_START1) |
-	    RTSI_Trig_Output_Bits(5,
-				  NI_RTSI_OUTPUT_G_SRC0) |
-	    RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0);
-	if (board->reg_type & ni_reg_m_series_mask)
-		devpriv->rtsi_trig_b_output_reg |=
-		    RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC);
-	devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
-			    RTSI_Trig_B_Output_Register);
+	if (comedi_dio_update_state(s, data))
+		ni_writew(dev, s->state, M_Offset_PFI_DO);
 
-/*
-* Sets the source and direction of the 4 on board lines
-* devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register);
-*/
+	data[1] = ni_readw(dev, M_Offset_PFI_DI);
+
+	return insn->n;
 }
 
-static int ni_rtsi_insn_bits(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+static int cs5529_wait_for_idle(struct comedi_device *dev)
 {
-	data[1] = 0;
+	unsigned short status;
+	const int timeout = HZ;
+	int i;
+
+	for (i = 0; i < timeout; i++) {
+		status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
+		if ((status & CSS_ADC_BUSY) == 0)
+			break;
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (schedule_timeout(1))
+			return -EIO;
+	}
+	if (i == timeout) {
+		dev_err(dev->class_dev, "%s timeout\n", __func__);
+		return -ETIME;
+	}
+	return 0;
+}
+
+static void cs5529_command(struct comedi_device *dev, unsigned short value)
+{
+	static const int timeout = 100;
+	int i;
+
+	ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx);
+	/* give time for command to start being serially clocked into cs5529.
+	 * this insures that the CSS_ADC_BUSY bit will get properly
+	 * set before we exit this function.
+	 */
+	for (i = 0; i < timeout; i++) {
+		if ((ni_ao_win_inw(dev, CAL_ADC_Status_67xx) & CSS_ADC_BUSY))
+			break;
+		udelay(1);
+	}
+	if (i == timeout)
+		dev_err(dev->class_dev,
+			"possible problem - never saw adc go busy?\n");
+}
+
+static int cs5529_do_conversion(struct comedi_device *dev,
+				unsigned short *data)
+{
+	int retval;
+	unsigned short status;
 
+	cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION);
+	retval = cs5529_wait_for_idle(dev);
+	if (retval) {
+		dev_err(dev->class_dev,
+			"timeout or signal in cs5529_do_conversion()\n");
+		return -ETIME;
+	}
+	status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
+	if (status & CSS_OSC_DETECT) {
+		dev_err(dev->class_dev,
+			"cs5529 conversion error, status CSS_OSC_DETECT\n");
+		return -EIO;
+	}
+	if (status & CSS_OVERRANGE) {
+		dev_err(dev->class_dev,
+			"cs5529 conversion error, overrange (ignoring)\n");
+	}
+	if (data) {
+		*data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx);
+		/* cs5529 returns 16 bit signed data in bipolar mode */
+		*data ^= (1 << 15);
+	}
+	return 0;
+}
+
+static int cs5529_ai_insn_read(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	int n, retval;
+	unsigned short sample;
+	unsigned int channel_select;
+	const unsigned int INTERNAL_REF = 0x1000;
+
+	/* Set calibration adc source.  Docs lie, reference select bits 8 to 11
+	 * do nothing. bit 12 seems to chooses internal reference voltage, bit
+	 * 13 causes the adc input to go overrange (maybe reads external reference?) */
+	if (insn->chanspec & CR_ALT_SOURCE)
+		channel_select = INTERNAL_REF;
+	else
+		channel_select = CR_CHAN(insn->chanspec);
+	ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx);
+
+	for (n = 0; n < insn->n; n++) {
+		retval = cs5529_do_conversion(dev, &sample);
+		if (retval < 0)
+			return retval;
+		data[n] = sample;
+	}
 	return insn->n;
 }
 
-/* Find best multiplier/divider to try and get the PLL running at 80 MHz
- * given an arbitrary frequency input clock */
+static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
+				unsigned int reg_select_bits)
+{
+	ni_ao_win_outw(dev, ((value >> 16) & 0xff),
+		       CAL_ADC_Config_Data_High_Word_67xx);
+	ni_ao_win_outw(dev, (value & 0xffff),
+		       CAL_ADC_Config_Data_Low_Word_67xx);
+	reg_select_bits &= CSCMD_REGISTER_SELECT_MASK;
+	cs5529_command(dev, CSCMD_COMMAND | reg_select_bits);
+	if (cs5529_wait_for_idle(dev))
+		dev_err(dev->class_dev,
+			"timeout or signal in %s\n", __func__);
+}
+
+static int init_cs5529(struct comedi_device *dev)
+{
+	unsigned int config_bits =
+	    CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES;
+
+#if 1
+	/* do self-calibration */
+	cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN,
+			    CSCMD_CONFIG_REGISTER);
+	/* need to force a conversion for calibration to run */
+	cs5529_do_conversion(dev, NULL);
+#else
+	/* force gain calibration to 1 */
+	cs5529_config_write(dev, 0x400000, CSCMD_GAIN_REGISTER);
+	cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET,
+			    CSCMD_CONFIG_REGISTER);
+	if (cs5529_wait_for_idle(dev))
+		dev_err(dev->class_dev,
+			"timeout or signal in %s\n", __func__);
+#endif
+	return 0;
+}
+
+/*
+ * Find best multiplier/divider to try and get the PLL running at 80 MHz
+ * given an arbitrary frequency input clock.
+ */
 static int ni_mseries_get_pll_parameters(unsigned reference_period_ns,
 					 unsigned *freq_divider,
 					 unsigned *freq_multiplier,
@@ -5266,6 +4871,7 @@ static int ni_mseries_get_pll_parameters
 	static const unsigned target_picosec = 12500;
 	static const unsigned fudge_factor_80_to_20Mhz = 4;
 	int best_period_picosec = 0;
+
 	for (div = 1; div <= max_div; ++div) {
 		for (mult = 1; mult <= max_mult; ++mult) {
 			unsigned new_period_ps =
@@ -5278,10 +4884,9 @@ static int ni_mseries_get_pll_parameters
 			}
 		}
 	}
-	if (best_period_picosec == 0) {
-		printk("%s: bug, failed to find pll parameters\n", __func__);
+	if (best_period_picosec == 0)
 		return -EIO;
-	}
+
 	*freq_divider = best_div;
 	*freq_multiplier = best_mult;
 	*actual_period_ns =
@@ -5290,16 +4895,6 @@ static int ni_mseries_get_pll_parameters
 	return 0;
 }
 
-static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
-{
-	const struct ni_board_struct *board = comedi_board(dev);
-
-	if (board->reg_type & ni_reg_m_series_mask)
-		return 8;
-	else
-		return 7;
-}
-
 static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 					   unsigned source, unsigned period_ns)
 {
@@ -5317,15 +4912,14 @@ static int ni_mseries_set_pll_master_clo
 		period_ns = 100;
 	/*  these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that */
 	if (period_ns < min_period_ns || period_ns > max_period_ns) {
-		printk
-		    ("%s: you must specify an input clock frequency between %i and %i nanosec "
-		     "for the phased-lock loop.\n", __func__,
-		     min_period_ns, max_period_ns);
+		dev_err(dev->class_dev,
+			"%s: you must specify an input clock frequency between %i and %i nanosec for the phased-lock loop\n",
+			__func__, min_period_ns, max_period_ns);
 		return -EINVAL;
 	}
 	devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
-	devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
-			    RTSI_Trig_Direction_Register);
+	ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+		      RTSI_Trig_Direction_Register);
 	pll_control_bits =
 	    MSeries_PLL_Enable_Bit | MSeries_PLL_VCO_Mode_75_150MHz_Bits;
 	devpriv->clock_and_fout2 |=
@@ -5335,26 +4929,17 @@ static int ni_mseries_set_pll_master_clo
 	case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK:
 		devpriv->clock_and_fout2 |=
 		    MSeries_PLL_In_Source_Select_Star_Trigger_Bits;
-		retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider,
-						       &freq_multiplier,
-						       &devpriv->clock_ns);
-		if (retval < 0)
-			return retval;
 		break;
 	case NI_MIO_PLL_PXI10_CLOCK:
 		/* pxi clock is 10MHz */
 		devpriv->clock_and_fout2 |=
 		    MSeries_PLL_In_Source_Select_PXI_Clock10;
-		retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider,
-						       &freq_multiplier,
-						       &devpriv->clock_ns);
-		if (retval < 0)
-			return retval;
 		break;
 	default:
 		{
 			unsigned rtsi_channel;
 			static const unsigned max_rtsi_channel = 7;
+
 			for (rtsi_channel = 0; rtsi_channel <= max_rtsi_channel;
 			     ++rtsi_channel) {
 				if (source ==
@@ -5367,81 +4952,78 @@ static int ni_mseries_set_pll_master_clo
 			}
 			if (rtsi_channel > max_rtsi_channel)
 				return -EINVAL;
-			retval = ni_mseries_get_pll_parameters(period_ns,
-							       &freq_divider,
-							       &freq_multiplier,
-							       &devpriv->
-							       clock_ns);
-			if (retval < 0)
-				return retval;
 		}
 		break;
 	}
-	ni_writew(devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2);
+	retval = ni_mseries_get_pll_parameters(period_ns,
+					       &freq_divider,
+					       &freq_multiplier,
+					       &devpriv->clock_ns);
+	if (retval < 0) {
+		dev_err(dev->class_dev,
+			"%s: bug, failed to find pll parameters\n", __func__);
+		return retval;
+	}
+
+	ni_writew(dev, devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2);
 	pll_control_bits |=
 	    MSeries_PLL_Divisor_Bits(freq_divider) |
 	    MSeries_PLL_Multiplier_Bits(freq_multiplier);
 
-	/* printk("using divider=%i, multiplier=%i for PLL. pll_control_bits = 0x%x\n",
-	 * freq_divider, freq_multiplier, pll_control_bits); */
-	/* printk("clock_ns=%d\n", devpriv->clock_ns); */
-	ni_writew(pll_control_bits, M_Offset_PLL_Control);
+	ni_writew(dev, pll_control_bits, M_Offset_PLL_Control);
 	devpriv->clock_source = source;
 	/* it seems to typically take a few hundred microseconds for PLL to lock */
 	for (i = 0; i < timeout; ++i) {
-		if (ni_readw(M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit)
+		if (ni_readw(dev, M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit)
 			break;
 		udelay(1);
 	}
 	if (i == timeout) {
-		printk
-		    ("%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns.\n",
-		     __func__, source, period_ns);
+		dev_err(dev->class_dev,
+			"%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns\n",
+			__func__, source, period_ns);
 		return -ETIMEDOUT;
 	}
 	return 3;
 }
 
-static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
-			       unsigned period_ns)
+static int ni_set_master_clock(struct comedi_device *dev,
+			       unsigned source, unsigned period_ns)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	if (source == NI_MIO_INTERNAL_CLOCK) {
 		devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
-		devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
-				    RTSI_Trig_Direction_Register);
+		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+			      RTSI_Trig_Direction_Register);
 		devpriv->clock_ns = TIMEBASE_1_NS;
-		if (board->reg_type & ni_reg_m_series_mask) {
+		if (devpriv->is_m_series) {
 			devpriv->clock_and_fout2 &=
 			    ~(MSeries_Timebase1_Select_Bit |
 			      MSeries_Timebase3_Select_Bit);
-			ni_writew(devpriv->clock_and_fout2,
+			ni_writew(dev, devpriv->clock_and_fout2,
 				  M_Offset_Clock_and_Fout2);
-			ni_writew(0, M_Offset_PLL_Control);
+			ni_writew(dev, 0, M_Offset_PLL_Control);
 		}
 		devpriv->clock_source = source;
 	} else {
-		if (board->reg_type & ni_reg_m_series_mask) {
+		if (devpriv->is_m_series) {
 			return ni_mseries_set_pll_master_clock(dev, source,
 							       period_ns);
 		} else {
 			if (source == NI_MIO_RTSI_CLOCK) {
 				devpriv->rtsi_trig_direction_reg |=
 				    Use_RTSI_Clock_Bit;
-				devpriv->stc_writew(dev,
-						    devpriv->
-						    rtsi_trig_direction_reg,
-						    RTSI_Trig_Direction_Register);
+				ni_stc_writew(dev,
+					      devpriv->rtsi_trig_direction_reg,
+					      RTSI_Trig_Direction_Register);
 				if (period_ns == 0) {
-					printk
-					    ("%s: we don't handle an unspecified clock period correctly yet, returning error.\n",
-					     __func__);
+					dev_err(dev->class_dev,
+						"%s: we don't handle an unspecified clock period correctly yet, returning error\n",
+						__func__);
 					return -EINVAL;
-				} else {
-					devpriv->clock_ns = period_ns;
 				}
+				devpriv->clock_ns = period_ns;
 				devpriv->clock_source = source;
 			} else
 				return -EINVAL;
@@ -5450,21 +5032,27 @@ static int ni_set_master_clock(struct co
 	return 3;
 }
 
-static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
-				       unsigned source)
+static unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
+
+	return (devpriv->is_m_series) ? 8 : 7;
+}
+
+static int ni_valid_rtsi_output_source(struct comedi_device *dev,
+				       unsigned chan, unsigned source)
+{
+	struct ni_private *devpriv = dev->private;
 
 	if (chan >= num_configurable_rtsi_channels(dev)) {
 		if (chan == old_RTSI_clock_channel) {
 			if (source == NI_RTSI_OUTPUT_RTSI_OSC)
 				return 1;
-			else {
-				printk
-				    ("%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards.\n",
-				     __func__, chan, old_RTSI_clock_channel);
-				return 0;
-			}
+
+			dev_err(dev->class_dev,
+				"%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards\n",
+				__func__, chan, old_RTSI_clock_channel);
+			return 0;
 		}
 		return 0;
 	}
@@ -5479,21 +5067,15 @@ static int ni_valid_rtsi_output_source(s
 	case NI_RTSI_OUTPUT_RGOUT0:
 	case NI_RTSI_OUTPUT_RTSI_BRD_0:
 		return 1;
-		break;
 	case NI_RTSI_OUTPUT_RTSI_OSC:
-		if (board->reg_type & ni_reg_m_series_mask)
-			return 1;
-		else
-			return 0;
-		break;
+		return (devpriv->is_m_series) ? 1 : 0;
 	default:
 		return 0;
-		break;
 	}
 }
 
-static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
-			       unsigned source)
+static int ni_set_rtsi_routing(struct comedi_device *dev,
+			       unsigned chan, unsigned source)
 {
 	struct ni_private *devpriv = dev->private;
 
@@ -5503,14 +5085,14 @@ static int ni_set_rtsi_routing(struct co
 		devpriv->rtsi_trig_a_output_reg &= ~RTSI_Trig_Output_Mask(chan);
 		devpriv->rtsi_trig_a_output_reg |=
 		    RTSI_Trig_Output_Bits(chan, source);
-		devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
-				    RTSI_Trig_A_Output_Register);
+		ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
+			      RTSI_Trig_A_Output_Register);
 	} else if (chan < 8) {
 		devpriv->rtsi_trig_b_output_reg &= ~RTSI_Trig_Output_Mask(chan);
 		devpriv->rtsi_trig_b_output_reg |=
 		    RTSI_Trig_Output_Bits(chan, source);
-		devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
-				    RTSI_Trig_B_Output_Register);
+		ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
+			      RTSI_Trig_B_Output_Register);
 	}
 	return 2;
 }
@@ -5528,16 +5110,17 @@ static unsigned ni_get_rtsi_routing(stru
 	} else {
 		if (chan == old_RTSI_clock_channel)
 			return NI_RTSI_OUTPUT_RTSI_OSC;
-		printk("%s: bug! should never get here?\n", __func__);
+		dev_err(dev->class_dev, "%s: bug! should never get here?\n",
+			__func__);
 		return 0;
 	}
 }
 
 static int ni_rtsi_insn_config(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 
@@ -5545,33 +5128,30 @@ static int ni_rtsi_insn_config(struct co
 	case INSN_CONFIG_DIO_OUTPUT:
 		if (chan < num_configurable_rtsi_channels(dev)) {
 			devpriv->rtsi_trig_direction_reg |=
-			    RTSI_Output_Bit(chan,
-				(board->reg_type & ni_reg_m_series_mask) != 0);
+			    RTSI_Output_Bit(chan, devpriv->is_m_series);
 		} else if (chan == old_RTSI_clock_channel) {
 			devpriv->rtsi_trig_direction_reg |=
 			    Drive_RTSI_Clock_Bit;
 		}
-		devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
-				    RTSI_Trig_Direction_Register);
+		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+			      RTSI_Trig_Direction_Register);
 		break;
 	case INSN_CONFIG_DIO_INPUT:
 		if (chan < num_configurable_rtsi_channels(dev)) {
 			devpriv->rtsi_trig_direction_reg &=
-			    ~RTSI_Output_Bit(chan,
-				(board->reg_type & ni_reg_m_series_mask) != 0);
+			    ~RTSI_Output_Bit(chan, devpriv->is_m_series);
 		} else if (chan == old_RTSI_clock_channel) {
 			devpriv->rtsi_trig_direction_reg &=
 			    ~Drive_RTSI_Clock_Bit;
 		}
-		devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
-				    RTSI_Trig_Direction_Register);
+		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+			      RTSI_Trig_Direction_Register);
 		break;
 	case INSN_CONFIG_DIO_QUERY:
 		if (chan < num_configurable_rtsi_channels(dev)) {
 			data[1] =
 			    (devpriv->rtsi_trig_direction_reg &
-			     RTSI_Output_Bit(chan,
-				(board->reg_type & ni_reg_m_series_mask) != 0))
+			     RTSI_Output_Bit(chan, devpriv->is_m_series))
 				? INSN_CONFIG_DIO_OUTPUT
 				: INSN_CONFIG_DIO_INPUT;
 		} else if (chan == old_RTSI_clock_channel) {
@@ -5581,160 +5161,600 @@ static int ni_rtsi_insn_config(struct co
 			    ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT;
 		}
 		return 2;
-		break;
 	case INSN_CONFIG_SET_CLOCK_SRC:
 		return ni_set_master_clock(dev, data[1], data[2]);
-		break;
 	case INSN_CONFIG_GET_CLOCK_SRC:
 		data[1] = devpriv->clock_source;
 		data[2] = devpriv->clock_ns;
 		return 3;
-		break;
 	case INSN_CONFIG_SET_ROUTING:
 		return ni_set_rtsi_routing(dev, chan, data[1]);
-		break;
 	case INSN_CONFIG_GET_ROUTING:
 		data[1] = ni_get_rtsi_routing(dev, chan);
 		return 2;
-		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 1;
 }
 
-static int cs5529_wait_for_idle(struct comedi_device *dev)
+static int ni_rtsi_insn_bits(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
-	unsigned short status;
-	const int timeout = HZ;
-	int i;
+	data[1] = 0;
 
-	for (i = 0; i < timeout; i++) {
-		status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
-		if ((status & CSS_ADC_BUSY) == 0)
-			break;
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (schedule_timeout(1))
-			return -EIO;
+	return insn->n;
+}
+
+static void ni_rtsi_init(struct comedi_device *dev)
+{
+	struct ni_private *devpriv = dev->private;
+
+	/*  Initialises the RTSI bus signal switch to a default state */
+
+	/*  Set clock mode to internal */
+	devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit;
+	if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0)
+		dev_err(dev->class_dev, "ni_set_master_clock failed, bug?\n");
+	/*  default internal lines routing to RTSI bus lines */
+	devpriv->rtsi_trig_a_output_reg =
+	    RTSI_Trig_Output_Bits(0,
+				  NI_RTSI_OUTPUT_ADR_START1) |
+	    RTSI_Trig_Output_Bits(1,
+				  NI_RTSI_OUTPUT_ADR_START2) |
+	    RTSI_Trig_Output_Bits(2,
+				  NI_RTSI_OUTPUT_SCLKG) |
+	    RTSI_Trig_Output_Bits(3, NI_RTSI_OUTPUT_DACUPDN);
+	ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
+		      RTSI_Trig_A_Output_Register);
+	devpriv->rtsi_trig_b_output_reg =
+	    RTSI_Trig_Output_Bits(4,
+				  NI_RTSI_OUTPUT_DA_START1) |
+	    RTSI_Trig_Output_Bits(5,
+				  NI_RTSI_OUTPUT_G_SRC0) |
+	    RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0);
+	if (devpriv->is_m_series)
+		devpriv->rtsi_trig_b_output_reg |=
+		    RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC);
+	ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
+		      RTSI_Trig_B_Output_Register);
+
+/*
+* Sets the source and direction of the 4 on board lines
+* ni_stc_writew(dev, 0x0000, RTSI_Board_Register);
+*/
+}
+
+#ifdef PCIDMA
+static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct ni_gpct *counter = s->private;
+	int retval;
+
+	retval = ni_request_gpct_mite_channel(dev, counter->counter_index,
+					      COMEDI_INPUT);
+	if (retval) {
+		dev_err(dev->class_dev,
+			"no dma channel available for use by counter\n");
+		return retval;
 	}
-/* printk("looped %i times waiting for idle\n", i); */
-	if (i == timeout) {
-		printk("%s: %s: timeout\n", __FILE__, __func__);
-		return -ETIME;
+	ni_tio_acknowledge(counter);
+	ni_e_series_enable_second_irq(dev, counter->counter_index, 1);
+
+	return ni_tio_cmd(dev, s);
+}
+
+static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct ni_gpct *counter = s->private;
+	int retval;
+
+	retval = ni_tio_cancel(counter);
+	ni_e_series_enable_second_irq(dev, counter->counter_index, 0);
+	ni_release_gpct_mite_channel(dev, counter->counter_index);
+	return retval;
+}
+#endif
+
+#if 0
+/*
+ *	Read the GPCTs current value.
+ */
+static int GPCT_G_Watch(struct comedi_device *dev, int chan)
+{
+	unsigned int hi1, hi2, lo;
+
+	devpriv->gpct_command[chan] &= ~G_Save_Trace;
+	ni_stc_writew(dev, devpriv->gpct_command[chan],
+		      G_Command_Register(chan));
+
+	devpriv->gpct_command[chan] |= G_Save_Trace;
+	ni_stc_writew(dev, devpriv->gpct_command[chan],
+		      G_Command_Register(chan));
+
+	/* This procedure is used because the two registers cannot
+	 * be read atomically. */
+	do {
+		hi1 = ni_stc_readw(dev, G_Save_Register_High(chan));
+		lo = ni_stc_readw(dev, G_Save_Register_Low(chan));
+		hi2 = ni_stc_readw(dev, G_Save_Register_High(chan));
+	} while (hi1 != hi2);
+
+	return (hi1 << 16) | lo;
+}
+
+static void GPCT_Reset(struct comedi_device *dev, int chan)
+{
+	int temp_ack_reg = 0;
+
+	devpriv->gpct_cur_operation[chan] = GPCT_RESET;
+
+	switch (chan) {
+	case 0:
+		ni_stc_writew(dev, G0_Reset, Joint_Reset_Register);
+		ni_set_bits(dev, Interrupt_A_Enable_Register,
+			    G0_TC_Interrupt_Enable, 0);
+		ni_set_bits(dev, Interrupt_A_Enable_Register,
+			    G0_Gate_Interrupt_Enable, 0);
+		temp_ack_reg |= G0_Gate_Error_Confirm;
+		temp_ack_reg |= G0_TC_Error_Confirm;
+		temp_ack_reg |= G0_TC_Interrupt_Ack;
+		temp_ack_reg |= G0_Gate_Interrupt_Ack;
+		ni_stc_writew(dev, temp_ack_reg, Interrupt_A_Ack_Register);
+
+		/* problem...this interferes with the other ctr... */
+		devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable;
+		ni_stc_writew(dev, devpriv->an_trig_etc_reg,
+			      Analog_Trigger_Etc_Register);
+		break;
+	case 1:
+		ni_stc_writew(dev, G1_Reset, Joint_Reset_Register);
+		ni_set_bits(dev, Interrupt_B_Enable_Register,
+			    G1_TC_Interrupt_Enable, 0);
+		ni_set_bits(dev, Interrupt_B_Enable_Register,
+			    G0_Gate_Interrupt_Enable, 0);
+		temp_ack_reg |= G1_Gate_Error_Confirm;
+		temp_ack_reg |= G1_TC_Error_Confirm;
+		temp_ack_reg |= G1_TC_Interrupt_Ack;
+		temp_ack_reg |= G1_Gate_Interrupt_Ack;
+		ni_stc_writew(dev, temp_ack_reg, Interrupt_B_Ack_Register);
+
+		devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable;
+		ni_stc_writew(dev, devpriv->an_trig_etc_reg,
+			      Analog_Trigger_Etc_Register);
+		break;
 	}
-	return 0;
+
+	devpriv->gpct_mode[chan] = 0;
+	devpriv->gpct_input_select[chan] = 0;
+	devpriv->gpct_command[chan] = 0;
+
+	devpriv->gpct_command[chan] |= G_Synchronized_Gate;
+
+	ni_stc_writew(dev, devpriv->gpct_mode[chan], G_Mode_Register(chan));
+	ni_stc_writew(dev, devpriv->gpct_input_select[chan],
+		      G_Input_Select_Register(chan));
+	ni_stc_writew(dev, 0, G_Autoincrement_Register(chan));
 }
+#endif
 
-static void cs5529_command(struct comedi_device *dev, unsigned short value)
+static irqreturn_t ni_E_interrupt(int irq, void *d)
 {
-	static const int timeout = 100;
-	int i;
+	struct comedi_device *dev = d;
+	unsigned short a_status;
+	unsigned short b_status;
+	unsigned int ai_mite_status = 0;
+	unsigned int ao_mite_status = 0;
+	unsigned long flags;
+#ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
+	struct mite_struct *mite = devpriv->mite;
+#endif
 
-	ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx);
-	/* give time for command to start being serially clocked into cs5529.
-	 * this insures that the CSS_ADC_BUSY bit will get properly
-	 * set before we exit this function.
-	 */
-	for (i = 0; i < timeout; i++) {
-		if ((ni_ao_win_inw(dev, CAL_ADC_Status_67xx) & CSS_ADC_BUSY))
-			break;
-		udelay(1);
+	if (!dev->attached)
+		return IRQ_NONE;
+	smp_mb();		/*  make sure dev->attached is checked before handler does anything else. */
+
+	/*  lock to avoid race with comedi_poll */
+	spin_lock_irqsave(&dev->spinlock, flags);
+	a_status = ni_stc_readw(dev, AI_Status_1_Register);
+	b_status = ni_stc_readw(dev, AO_Status_1_Register);
+#ifdef PCIDMA
+	if (mite) {
+		struct ni_private *devpriv = dev->private;
+		unsigned long flags_too;
+
+		spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
+		if (devpriv->ai_mite_chan) {
+			ai_mite_status = mite_get_status(devpriv->ai_mite_chan);
+			if (ai_mite_status & CHSR_LINKC)
+				writel(CHOR_CLRLC,
+				       devpriv->mite->mite_io_addr +
+				       MITE_CHOR(devpriv->
+						 ai_mite_chan->channel));
+		}
+		if (devpriv->ao_mite_chan) {
+			ao_mite_status = mite_get_status(devpriv->ao_mite_chan);
+			if (ao_mite_status & CHSR_LINKC)
+				writel(CHOR_CLRLC,
+				       mite->mite_io_addr +
+				       MITE_CHOR(devpriv->
+						 ao_mite_chan->channel));
+		}
+		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too);
 	}
-/* printk("looped %i times writing command to cs5529\n", i); */
-	if (i == timeout)
-		comedi_error(dev, "possible problem - never saw adc go busy?");
+#endif
+	ack_a_interrupt(dev, a_status);
+	ack_b_interrupt(dev, b_status);
+	if ((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT))
+		handle_a_interrupt(dev, a_status, ai_mite_status);
+	if ((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT))
+		handle_b_interrupt(dev, b_status, ao_mite_status);
+	handle_gpct_interrupt(dev, 0);
+	handle_gpct_interrupt(dev, 1);
+	handle_cdio_interrupt(dev);
+
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+	return IRQ_HANDLED;
 }
 
-/* write to cs5529 register */
-static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
-				unsigned int reg_select_bits)
+static int ni_alloc_private(struct comedi_device *dev)
 {
-	ni_ao_win_outw(dev, ((value >> 16) & 0xff),
-		       CAL_ADC_Config_Data_High_Word_67xx);
-	ni_ao_win_outw(dev, (value & 0xffff),
-		       CAL_ADC_Config_Data_Low_Word_67xx);
-	reg_select_bits &= CSCMD_REGISTER_SELECT_MASK;
-	cs5529_command(dev, CSCMD_COMMAND | reg_select_bits);
-	if (cs5529_wait_for_idle(dev))
-		comedi_error(dev, "time or signal in cs5529_config_write()");
+	struct ni_private *devpriv;
+
+	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+	if (!devpriv)
+		return -ENOMEM;
+
+	spin_lock_init(&devpriv->window_lock);
+	spin_lock_init(&devpriv->soft_reg_copy_lock);
+	spin_lock_init(&devpriv->mite_channel_lock);
+
+	return 0;
 }
 
-static int cs5529_do_conversion(struct comedi_device *dev, unsigned short *data)
+static int ni_E_init(struct comedi_device *dev,
+		     unsigned interrupt_pin, unsigned irq_polarity)
 {
-	int retval;
-	unsigned short status;
+	const struct ni_board_struct *board = comedi_board(dev);
+	struct ni_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+	int ret;
+	int i;
 
-	cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION);
-	retval = cs5529_wait_for_idle(dev);
-	if (retval) {
-		comedi_error(dev,
-			     "timeout or signal in cs5529_do_conversion()");
-		return -ETIME;
+	if (board->n_aochan > MAX_N_AO_CHAN) {
+		dev_err(dev->class_dev, "bug! n_aochan > MAX_N_AO_CHAN\n");
+		return -EINVAL;
 	}
-	status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
-	if (status & CSS_OSC_DETECT) {
-		printk
-		    ("ni_mio_common: cs5529 conversion error, status CSS_OSC_DETECT\n");
-		return -EIO;
+
+	/* initialize clock dividers */
+	devpriv->clock_and_fout = Slow_Internal_Time_Divide_By_2 |
+				  Slow_Internal_Timebase |
+				  Clock_To_Board_Divide_By_2 |
+				  Clock_To_Board;
+	if (!devpriv->is_6xxx) {
+		/* BEAM is this needed for PCI-6143 ?? */
+		devpriv->clock_and_fout |= (AI_Output_Divide_By_2 |
+					    AO_Output_Divide_By_2);
 	}
-	if (status & CSS_OVERRANGE) {
-		printk
-		    ("ni_mio_common: cs5529 conversion error, overrange (ignoring)\n");
+	ni_stc_writew(dev, devpriv->clock_and_fout, Clock_and_FOUT_Register);
+
+	ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES);
+	if (ret)
+		return ret;
+
+	/* Analog Input subdevice */
+	s = &dev->subdevices[NI_AI_SUBDEV];
+	if (board->n_adchan) {
+		s->type		= COMEDI_SUBD_AI;
+		s->subdev_flags	= SDF_READABLE | SDF_DIFF | SDF_DITHER;
+		if (!devpriv->is_611x)
+			s->subdev_flags	|= SDF_GROUND | SDF_COMMON | SDF_OTHER;
+		if (board->ai_maxdata > 0xffff)
+			s->subdev_flags	|= SDF_LSAMPL;
+		if (devpriv->is_m_series)
+			s->subdev_flags	|= SDF_SOFT_CALIBRATED;
+		s->n_chan	= board->n_adchan;
+		s->maxdata	= board->ai_maxdata;
+		s->range_table	= ni_range_lkup[board->gainlkup];
+		s->insn_read	= ni_ai_insn_read;
+		s->insn_config	= ni_ai_insn_config;
+		if (dev->irq) {
+			dev->read_subdev = s;
+			s->subdev_flags	|= SDF_CMD_READ;
+			s->len_chanlist	= 512;
+			s->do_cmdtest	= ni_ai_cmdtest;
+			s->do_cmd	= ni_ai_cmd;
+			s->cancel	= ni_ai_reset;
+			s->poll		= ni_ai_poll;
+			s->munge	= ni_ai_munge;
+
+			if (devpriv->mite)
+				s->async_dma_dir = DMA_FROM_DEVICE;
+		}
+
+		/* reset the analog input configuration */
+		ni_ai_reset(dev, s);
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
-	if (data) {
-		*data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx);
-		/* cs5529 returns 16 bit signed data in bipolar mode */
-		*data ^= (1 << 15);
+
+	/* Analog Output subdevice */
+	s = &dev->subdevices[NI_AO_SUBDEV];
+	if (board->n_aochan) {
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND;
+		if (devpriv->is_m_series)
+			s->subdev_flags	|= SDF_SOFT_CALIBRATED;
+		s->n_chan	= board->n_aochan;
+		s->maxdata	= board->ao_maxdata;
+		s->range_table	= board->ao_range_table;
+		s->insn_read	= ni_ao_insn_read;
+		s->insn_write	= ni_ao_insn_write;
+		s->insn_config	= ni_ao_insn_config;
+
+		/*
+		 * Along with the IRQ we need either a FIFO or DMA for
+		 * async command support.
+		 */
+		if (dev->irq && (board->ao_fifo_depth || devpriv->mite)) {
+			dev->write_subdev = s;
+			s->subdev_flags	|= SDF_CMD_WRITE;
+			s->len_chanlist	= s->n_chan;
+			s->do_cmdtest	= ni_ao_cmdtest;
+			s->do_cmd	= ni_ao_cmd;
+			s->cancel	= ni_ao_reset;
+			if (!devpriv->is_m_series)
+				s->munge	= ni_ao_munge;
+
+			if (devpriv->mite)
+				s->async_dma_dir = DMA_TO_DEVICE;
+		}
+
+		if (devpriv->is_67xx)
+			init_ao_67xx(dev, s);
+
+		/* reset the analog output configuration */
+		ni_ao_reset(dev, s);
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
 	}
-	return 0;
-}
 
-static int cs5529_ai_insn_read(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
-{
-	int n, retval;
-	unsigned short sample;
-	unsigned int channel_select;
-	const unsigned int INTERNAL_REF = 0x1000;
+	/* Digital I/O subdevice */
+	s = &dev->subdevices[NI_DIO_SUBDEV];
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= board->has_32dio_chan ? 32 : 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	if (devpriv->is_m_series) {
+		s->subdev_flags	|= SDF_LSAMPL;
+		s->insn_bits	= ni_m_series_dio_insn_bits;
+		s->insn_config	= ni_m_series_dio_insn_config;
+		if (dev->irq) {
+			s->subdev_flags	|= SDF_CMD_WRITE /* | SDF_CMD_READ */;
+			s->len_chanlist	= s->n_chan;
+			s->do_cmdtest	= ni_cdio_cmdtest;
+			s->do_cmd	= ni_cdio_cmd;
+			s->cancel	= ni_cdio_cancel;
 
-	/* Set calibration adc source.  Docs lie, reference select bits 8 to 11
-	 * do nothing. bit 12 seems to chooses internal reference voltage, bit
-	 * 13 causes the adc input to go overrange (maybe reads external reference?) */
-	if (insn->chanspec & CR_ALT_SOURCE)
-		channel_select = INTERNAL_REF;
-	else
-		channel_select = CR_CHAN(insn->chanspec);
-	ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx);
+			/* M-series boards use DMA */
+			s->async_dma_dir = DMA_BIDIRECTIONAL;
+		}
 
-	for (n = 0; n < insn->n; n++) {
-		retval = cs5529_do_conversion(dev, &sample);
-		if (retval < 0)
-			return retval;
-		data[n] = sample;
+		/* reset DIO and set all channels to inputs */
+		ni_writel(dev, CDO_Reset_Bit | CDI_Reset_Bit,
+			  M_Offset_CDIO_Command);
+		ni_writel(dev, s->io_bits, M_Offset_DIO_Direction);
+	} else {
+		s->insn_bits	= ni_dio_insn_bits;
+		s->insn_config	= ni_dio_insn_config;
+
+		/* set all channels to inputs */
+		devpriv->dio_control = DIO_Pins_Dir(s->io_bits);
+		ni_writew(dev, devpriv->dio_control, DIO_Control_Register);
 	}
-	return insn->n;
-}
 
-static int init_cs5529(struct comedi_device *dev)
-{
-	unsigned int config_bits =
-	    CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES;
+	/* 8255 device */
+	s = &dev->subdevices[NI_8255_DIO_SUBDEV];
+	if (board->has_8255) {
+		ret = subdev_8255_init(dev, s, ni_8255_callback,
+				       (unsigned long)dev);
+		if (ret)
+			return ret;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-#if 1
-	/* do self-calibration */
-	cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN,
-			    CSCMD_CONFIG_REGISTER);
-	/* need to force a conversion for calibration to run */
-	cs5529_do_conversion(dev, NULL);
-#else
-	/* force gain calibration to 1 */
-	cs5529_config_write(dev, 0x400000, CSCMD_GAIN_REGISTER);
-	cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET,
-			    CSCMD_CONFIG_REGISTER);
-	if (cs5529_wait_for_idle(dev))
-		comedi_error(dev, "timeout or signal in init_cs5529()\n");
+	/* formerly general purpose counter/timer device, but no longer used */
+	s = &dev->subdevices[NI_UNUSED_SUBDEV];
+	s->type = COMEDI_SUBD_UNUSED;
+
+	/* Calibration subdevice */
+	s = &dev->subdevices[NI_CALIBRATION_SUBDEV];
+	s->type		= COMEDI_SUBD_CALIB;
+	s->subdev_flags	= SDF_INTERNAL;
+	s->n_chan	= 1;
+	s->maxdata	= 0;
+	if (devpriv->is_m_series) {
+		/* internal PWM output used for AI nonlinearity calibration */
+		s->insn_config	= ni_m_series_pwm_config;
+
+		ni_writel(dev, 0x0, M_Offset_Cal_PWM);
+	} else if (devpriv->is_6143) {
+		/* internal PWM output used for AI nonlinearity calibration */
+		s->insn_config	= ni_6143_pwm_config;
+	} else {
+		s->subdev_flags	|= SDF_WRITABLE;
+		s->insn_read	= ni_calib_insn_read;
+		s->insn_write	= ni_calib_insn_write;
+
+		/* setup the caldacs and find the real n_chan and maxdata */
+		caldac_setup(dev, s);
+	}
+
+	/* EEPROM subdevice */
+	s = &dev->subdevices[NI_EEPROM_SUBDEV];
+	s->type		= COMEDI_SUBD_MEMORY;
+	s->subdev_flags	= SDF_READABLE | SDF_INTERNAL;
+	s->maxdata	= 0xff;
+	if (devpriv->is_m_series) {
+		s->n_chan	= M_SERIES_EEPROM_SIZE;
+		s->insn_read	= ni_m_series_eeprom_insn_read;
+	} else {
+		s->n_chan	= 512;
+		s->insn_read	= ni_eeprom_insn_read;
+	}
+
+	/* Digital I/O (PFI) subdevice */
+	s = &dev->subdevices[NI_PFI_DIO_SUBDEV];
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->maxdata	= 1;
+	if (devpriv->is_m_series) {
+		s->n_chan	= 16;
+		s->insn_bits	= ni_pfi_insn_bits;
+
+		ni_writew(dev, s->state, M_Offset_PFI_DO);
+		for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) {
+			ni_writew(dev, devpriv->pfi_output_select_reg[i],
+				  M_Offset_PFI_Output_Select(i + 1));
+		}
+	} else {
+		s->n_chan	= 10;
+	}
+	s->insn_config	= ni_pfi_insn_config;
+
+	ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0);
+
+	/* cs5529 calibration adc */
+	s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV];
+	if (devpriv->is_67xx) {
+		s->type = COMEDI_SUBD_AI;
+		s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL;
+		/*  one channel for each analog output channel */
+		s->n_chan = board->n_aochan;
+		s->maxdata = (1 << 16) - 1;
+		s->range_table = &range_unknown;	/* XXX */
+		s->insn_read = cs5529_ai_insn_read;
+		s->insn_config = NULL;
+		init_cs5529(dev);
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+
+	/* Serial */
+	s = &dev->subdevices[NI_SERIAL_SUBDEV];
+	s->type = COMEDI_SUBD_SERIAL;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan = 1;
+	s->maxdata = 0xff;
+	s->insn_config = ni_serial_insn_config;
+	devpriv->serial_interval_ns = 0;
+	devpriv->serial_hw_mode = 0;
+
+	/* RTSI */
+	s = &dev->subdevices[NI_RTSI_SUBDEV];
+	s->type = COMEDI_SUBD_DIO;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan = 8;
+	s->maxdata = 1;
+	s->insn_bits = ni_rtsi_insn_bits;
+	s->insn_config = ni_rtsi_insn_config;
+	ni_rtsi_init(dev);
+
+	/* allocate and initialize the gpct counter device */
+	devpriv->counter_dev = ni_gpct_device_construct(dev,
+					ni_gpct_write_register,
+					ni_gpct_read_register,
+					(devpriv->is_m_series)
+						? ni_gpct_variant_m_series
+						: ni_gpct_variant_e_series,
+					NUM_GPCT);
+	if (!devpriv->counter_dev)
+		return -ENOMEM;
+
+	/* Counter (gpct) subdevices */
+	for (i = 0; i < NUM_GPCT; ++i) {
+		struct ni_gpct *gpct = &devpriv->counter_dev->counters[i];
+
+		/* setup and initialize the counter */
+		gpct->chip_index = 0;
+		gpct->counter_index = i;
+		ni_tio_init_counter(gpct);
+
+		s = &dev->subdevices[NI_GPCT_SUBDEV(i)];
+		s->type		= COMEDI_SUBD_COUNTER;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
+		s->n_chan	= 3;
+		s->maxdata	= (devpriv->is_m_series) ? 0xffffffff
+							 : 0x00ffffff;
+		s->insn_read	= ni_tio_insn_read;
+		s->insn_write	= ni_tio_insn_read;
+		s->insn_config	= ni_tio_insn_config;
+#ifdef PCIDMA
+		if (dev->irq && devpriv->mite) {
+			s->subdev_flags	|= SDF_CMD_READ /* | SDF_CMD_WRITE */;
+			s->len_chanlist	= 1;
+			s->do_cmdtest	= ni_tio_cmdtest;
+			s->do_cmd	= ni_gpct_cmd;
+			s->cancel	= ni_gpct_cancel;
+
+			s->async_dma_dir = DMA_BIDIRECTIONAL;
+		}
 #endif
+		s->private	= gpct;
+	}
+
+	/* Frequency output subdevice */
+	s = &dev->subdevices[NI_FREQ_OUT_SUBDEV];
+	s->type		= COMEDI_SUBD_COUNTER;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 1;
+	s->maxdata	= 0xf;
+	s->insn_read	= ni_freq_out_insn_read;
+	s->insn_write	= ni_freq_out_insn_write;
+	s->insn_config	= ni_freq_out_insn_config;
+
+	if (dev->irq) {
+		ni_stc_writew(dev,
+			      (irq_polarity ? Interrupt_Output_Polarity : 0) |
+			      (Interrupt_Output_On_3_Pins & 0) |
+			      Interrupt_A_Enable | Interrupt_B_Enable |
+			      Interrupt_A_Output_Select(interrupt_pin) |
+			      Interrupt_B_Output_Select(interrupt_pin),
+			      Interrupt_Control_Register);
+	}
+
+	/* DMA setup */
+	ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select);
+	ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select);
+
+	if (devpriv->is_6xxx) {
+		ni_writeb(dev, 0, Magic_611x);
+	} else if (devpriv->is_m_series) {
+		int channel;
+
+		for (channel = 0; channel < board->n_aochan; ++channel) {
+			ni_writeb(dev, 0xf,
+				  M_Offset_AO_Waveform_Order(channel));
+			ni_writeb(dev, 0x0,
+				  M_Offset_AO_Reference_Attenuation(channel));
+		}
+		ni_writeb(dev, 0x0, M_Offset_AO_Calibration);
+	}
+
 	return 0;
 }
+
+static void mio_common_detach(struct comedi_device *dev)
+{
+	struct ni_private *devpriv = dev->private;
+
+	if (devpriv) {
+		if (devpriv->counter_dev)
+			ni_gpct_device_destroy(devpriv->counter_dev);
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_mio_cs.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_mio_cs.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_mio_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_mio_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,156 +47,85 @@ See the notes in the ni_atmio.o driver.
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-#define ATMIO 1
-#undef PCIMIO
-
 /*
  *  AT specific setup
  */
 
-#define NI_SIZE 0x20
-
-#define MAX_N_CALDACS 32
-
 static const struct ni_board_struct ni_boards[] = {
 	{
-		.device_id	= 0x010d,
 		.name		= "DAQCard-ai-16xe-50",
+		.device_id	= 0x010d,
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 1024,
 		.gainlkup	= ai_gain_8,
 		.ai_speed	= 5000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043 },
 	}, {
-		.device_id	= 0x010c,
 		.name		= "DAQCard-ai-16e-4",
+		.device_id	= 0x010c,
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 1024,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 4000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { mb88341 },		/* verified */
 	}, {
-		.device_id	= 0x02c4,
 		.name		= "DAQCard-6062E",
+		.device_id	= 0x02c4,
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 8192,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 2000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1176,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* verified */
 	 }, {
 		/* specs incorrect! */
-		.device_id	= 0x075e,
 		.name		= "DAQCard-6024E",
+		.device_id	= 0x075e,
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 1024,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	}, {
 		/* specs incorrect! */
-		.device_id	= 0x0245,
 		.name		= "DAQCard-6036E",
+		.device_id	= 0x0245,
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 1024,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	 },
 #if 0
 	{
-		.device_id	= 0x0000,	/* unknown */
 		.name		= "DAQCard-6715",
+		.device_id	= 0x0000,	/* unknown */
 		.n_aochan	= 8,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_671x	= 8192,
-		.num_p0_dio_channels = 8,
 		.caldac		= { mb88341, mb88341 },
 	},
 #endif
 };
 
-#define interrupt_pin(a)	0
-
-#define IRQ_POLARITY 1
-
-struct ni_private {
-
-	struct pcmcia_device *link;
-
-NI_PRIVATE_COMMON};
-
-/* How we access registers */
-
-#define ni_writel(a, b)		(outl((a), (b)+dev->iobase))
-#define ni_readl(a)		(inl((a)+dev->iobase))
-#define ni_writew(a, b)		(outw((a), (b)+dev->iobase))
-#define ni_readw(a)		(inw((a)+dev->iobase))
-#define ni_writeb(a, b)		(outb((a), (b)+dev->iobase))
-#define ni_readb(a)		(inb((a)+dev->iobase))
-
-/* How we access windowed registers */
-
-/* We automatically take advantage of STC registers that can be
- * read/written directly in the I/O space of the board.  The
- * DAQCard devices map the low 8 STC registers to iobase+addr*2. */
-
-static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	if (addr < 8) {
-		ni_writew(data, addr * 2);
-	} else {
-		ni_writew(addr, Window_Address);
-		ni_writew(data, Window_Data);
-	}
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
-}
-
-static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
-	uint16_t ret;
-
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	if (addr < 8) {
-		ret = ni_readw(addr * 2);
-	} else {
-		ni_writew(addr, Window_Address);
-		ret = ni_readw(Window_Data);
-	}
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
-
-	return ret;
-}
-
 #include "ni_mio_common.c"
 
 static const void *ni_getboardtype(struct comedi_device *dev,
@@ -260,12 +189,8 @@ static int mio_cs_auto_attach(struct com
 		return ret;
 
 	devpriv = dev->private;
-	devpriv->stc_writew	= mio_cs_win_out;
-	devpriv->stc_readw	= mio_cs_win_in;
-	devpriv->stc_writel	= win_out2;
-	devpriv->stc_readl	= win_in2;
 
-	return ni_E_init(dev);
+	return ni_E_init(dev, 0, 1);
 }
 
 static void mio_cs_detach(struct comedi_device *dev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_pcidio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_pcidio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_pcidio.c	2014-08-07 04:59:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_pcidio.c	2014-09-28 21:41:38.000000000 -0400
@@ -58,9 +58,6 @@ comedi_nonfree_firmware tarball availabl
 #include "comedi_fc.h"
 #include "mite.h"
 
-#define PCI_DIO_SIZE 4096
-#define PCI_MITE_SIZE 4096
-
 /* defines for the PCI-DIO-32HS */
 
 #define Window_Address			4	/* W */
@@ -295,16 +292,6 @@ struct nidio96_private {
 	spinlock_t mite_channel_lock;
 };
 
-static int ni_pcidio_cmdtest(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_cmd *cmd);
-static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ni_pcidio_inttrig(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int trignum);
-static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
-static int setup_mite_dma(struct comedi_device *dev,
-			  struct comedi_subdevice *s);
-
 static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 {
 	struct nidio96_private *devpriv = dev->private;
@@ -317,13 +304,13 @@ static int ni_pcidio_request_di_mite_cha
 					  devpriv->di_mite_ring, 1, 2);
 	if (devpriv->di_mite_chan == NULL) {
 		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-		comedi_error(dev, "failed to reserve mite dma channel.");
+		dev_err(dev->class_dev, "failed to reserve mite dma channel\n");
 		return -EBUSY;
 	}
 	devpriv->di_mite_chan->dir = COMEDI_INPUT;
 	writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
 	       secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
-	       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
+	       dev->mmio + DMA_Line_Control_Group1);
 	mmiowb();
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 	return 0;
@@ -342,12 +329,36 @@ static void ni_pcidio_release_di_mite_ch
 		devpriv->di_mite_chan = NULL;
 		writeb(primary_DMAChannel_bits(0) |
 		       secondary_DMAChannel_bits(0),
-		       devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
+		       dev->mmio + DMA_Line_Control_Group1);
 		mmiowb();
 	}
 	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 }
 
+static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct nidio96_private *devpriv = dev->private;
+	int retval;
+	unsigned long flags;
+
+	retval = ni_pcidio_request_di_mite_channel(dev);
+	if (retval)
+		return retval;
+
+	/* write alloc the entire buffer */
+	comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
+
+	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+	if (devpriv->di_mite_chan) {
+		mite_prep_dma(devpriv->di_mite_chan, 32, 32);
+		mite_dma_arm(devpriv->di_mite_chan);
+	} else
+		retval = -EIO;
+	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+
+	return retval;
+}
+
 static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct nidio96_private *devpriv = dev->private;
@@ -359,7 +370,7 @@ static int ni_pcidio_poll(struct comedi_
 	if (devpriv->di_mite_chan)
 		mite_sync_input_dma(devpriv->di_mite_chan, s);
 	spin_unlock(&devpriv->mite_channel_lock);
-	count = s->async->buf_write_count - s->async->buf_read_count;
+	count = comedi_buf_n_bytes_ready(s);
 	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 	return count;
 }
@@ -390,9 +401,8 @@ static irqreturn_t nidio_interrupt(int i
 	/* Lock to avoid race with comedi_poll */
 	spin_lock(&dev->spinlock);
 
-	status = readb(devpriv->mite->daq_io_addr +
-		       Interrupt_And_Window_Status);
-	flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
+	status = readb(dev->mmio + Interrupt_And_Window_Status);
+	flags = readb(dev->mmio + Group_1_Flags);
 
 	spin_lock(&devpriv->mite_channel_lock);
 	if (devpriv->di_mite_chan)
@@ -421,8 +431,7 @@ static irqreturn_t nidio_interrupt(int i
 		if (work > 20) {
 			dev_dbg(dev->class_dev, "too much work in interrupt\n");
 			writeb(0x00,
-			       devpriv->mite->daq_io_addr +
-			       Master_DMA_And_Interrupt_Control);
+			       dev->mmio + Master_DMA_And_Interrupt_Control);
 			break;
 		}
 
@@ -434,64 +443,50 @@ static irqreturn_t nidio_interrupt(int i
 				if (work > 100) {
 					dev_dbg(dev->class_dev,
 						"too much work in interrupt\n");
-					writeb(0x00,
-					       devpriv->mite->daq_io_addr +
+					writeb(0x00, dev->mmio +
 					       Master_DMA_And_Interrupt_Control
 					      );
 					goto out;
 				}
-				auxdata =
-				    readl(devpriv->mite->daq_io_addr +
-					  Group_1_FIFO);
+				auxdata = readl(dev->mmio + Group_1_FIFO);
 				data1 = auxdata & 0xffff;
 				data2 = (auxdata & 0xffff0000) >> 16;
 				comedi_buf_put(s, data1);
 				comedi_buf_put(s, data2);
-				flags = readb(devpriv->mite->daq_io_addr +
-					      Group_1_Flags);
+				flags = readb(dev->mmio + Group_1_Flags);
 			}
 			async->events |= COMEDI_CB_BLOCK;
 		}
 
 		if (flags & CountExpired) {
-			writeb(ClearExpired,
-			       devpriv->mite->daq_io_addr +
-			       Group_1_Second_Clear);
+			writeb(ClearExpired, dev->mmio + Group_1_Second_Clear);
 			async->events |= COMEDI_CB_EOA;
 
-			writeb(0x00, devpriv->mite->daq_io_addr + OpMode);
+			writeb(0x00, dev->mmio + OpMode);
 			break;
 		} else if (flags & Waited) {
-			writeb(ClearWaited,
-			       devpriv->mite->daq_io_addr +
-			       Group_1_First_Clear);
+			writeb(ClearWaited, dev->mmio + Group_1_First_Clear);
 			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 			break;
 		} else if (flags & PrimaryTC) {
 			writeb(ClearPrimaryTC,
-			       devpriv->mite->daq_io_addr +
-			       Group_1_First_Clear);
+			       dev->mmio + Group_1_First_Clear);
 			async->events |= COMEDI_CB_EOA;
 		} else if (flags & SecondaryTC) {
 			writeb(ClearSecondaryTC,
-			       devpriv->mite->daq_io_addr +
-			       Group_1_First_Clear);
+			       dev->mmio + Group_1_First_Clear);
 			async->events |= COMEDI_CB_EOA;
 		}
 
-		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
-		status = readb(devpriv->mite->daq_io_addr +
-			       Interrupt_And_Window_Status);
+		flags = readb(dev->mmio + Group_1_Flags);
+		status = readb(dev->mmio + Interrupt_And_Window_Status);
 	}
 
 out:
 	cfc_handle_events(dev, s);
 #if 0
-	if (!tag) {
-		writeb(0x03,
-		       devpriv->mite->daq_io_addr +
-		       Master_DMA_And_Interrupt_Control);
-	}
+	if (!tag)
+		writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 #endif
 
 	spin_unlock(&dev->spinlock);
@@ -503,14 +498,13 @@ static int ni_pcidio_insn_config(struct
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	struct nidio96_private *devpriv = dev->private;
 	int ret;
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 	if (ret)
 		return ret;
 
-	writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
+	writel(s->io_bits, dev->mmio + Port_Pin_Directions(0));
 
 	return insn->n;
 }
@@ -520,16 +514,37 @@ static int ni_pcidio_insn_bits(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct nidio96_private *devpriv = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
+		writel(s->state, dev->mmio + Port_IO(0));
 
-	data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
+	data[1] = readl(dev->mmio + Port_IO(0));
 
 	return insn->n;
 }
 
+static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags)
+{
+	int divider, base;
+
+	base = TIMER_BASE;
+
+	switch (flags & TRIG_ROUND_MASK) {
+	case TRIG_ROUND_NEAREST:
+	default:
+		divider = (*nanosec + base / 2) / base;
+		break;
+	case TRIG_ROUND_DOWN:
+		divider = (*nanosec) / base;
+		break;
+	case TRIG_ROUND_UP:
+		divider = (*nanosec + base - 1) / base;
+		break;
+	}
+
+	*nanosec = base * divider;
+	return divider;
+}
+
 static int ni_pcidio_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
@@ -594,7 +609,7 @@ static int ni_pcidio_cmdtest(struct come
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		ni_pcidio_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		ni_pcidio_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 
@@ -604,27 +619,20 @@ static int ni_pcidio_cmdtest(struct come
 	return 0;
 }
 
-static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
+static int ni_pcidio_inttrig(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     unsigned int trig_num)
 {
-	int divider, base;
+	struct nidio96_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
 
-	base = TIMER_BASE;
+	if (trig_num != cmd->start_arg)
+		return -EINVAL;
 
-	switch (round_mode) {
-	case TRIG_ROUND_NEAREST:
-	default:
-		divider = (*nanosec + base / 2) / base;
-		break;
-	case TRIG_ROUND_DOWN:
-		divider = (*nanosec) / base;
-		break;
-	case TRIG_ROUND_UP:
-		divider = (*nanosec + base - 1) / base;
-		break;
-	}
+	writeb(devpriv->OpModeBits, dev->mmio + OpMode);
+	s->async->inttrig = NULL;
 
-	*nanosec = base * divider;
-	return divider;
+	return 1;
 }
 
 static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -633,98 +641,94 @@ static int ni_pcidio_cmd(struct comedi_d
 	struct comedi_cmd *cmd = &s->async->cmd;
 
 	/* XXX configure ports for input */
-	writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
+	writel(0x0000, dev->mmio + Port_Pin_Directions(0));
 
 	if (1) {
 		/* enable fifos A B C D */
-		writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path);
+		writeb(0x0f, dev->mmio + Data_Path);
 
 		/* set transfer width a 32 bits */
 		writeb(TransferWidth(0) | TransferLength(0),
-		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
+		       dev->mmio + Transfer_Size_Control);
 	} else {
-		writeb(0x03, devpriv->mite->daq_io_addr + Data_Path);
+		writeb(0x03, dev->mmio + Data_Path);
 		writeb(TransferWidth(3) | TransferLength(0),
-		       devpriv->mite->daq_io_addr + Transfer_Size_Control);
+		       dev->mmio + Transfer_Size_Control);
 	}
 
 	/* protocol configuration */
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		/* page 4-5, "input with internal REQs" */
-		writeb(0, devpriv->mite->daq_io_addr + OpMode);
-		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
-		writeb(1, devpriv->mite->daq_io_addr + Sequence);
-		writeb(0x04, devpriv->mite->daq_io_addr + ReqReg);
-		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
-		writeb(3, devpriv->mite->daq_io_addr + LinePolarities);
-		writeb(0xc0, devpriv->mite->daq_io_addr + AckSer);
+		writeb(0, dev->mmio + OpMode);
+		writeb(0x00, dev->mmio + ClockReg);
+		writeb(1, dev->mmio + Sequence);
+		writeb(0x04, dev->mmio + ReqReg);
+		writeb(4, dev->mmio + BlockMode);
+		writeb(3, dev->mmio + LinePolarities);
+		writeb(0xc0, dev->mmio + AckSer);
 		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
 					     TRIG_ROUND_NEAREST),
-		       devpriv->mite->daq_io_addr + StartDelay);
-		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
-		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
-		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
-		writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay);
-		writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay);
+		       dev->mmio + StartDelay);
+		writeb(1, dev->mmio + ReqDelay);
+		writeb(1, dev->mmio + ReqNotDelay);
+		writeb(1, dev->mmio + AckDelay);
+		writeb(0x0b, dev->mmio + AckNotDelay);
+		writeb(0x01, dev->mmio + Data1Delay);
 		/* manual, page 4-5: ClockSpeed comment is incorrectly listed
 		 * on DAQOptions */
-		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
-		writeb(0, devpriv->mite->daq_io_addr + DAQOptions);
+		writew(0, dev->mmio + ClockSpeed);
+		writeb(0, dev->mmio + DAQOptions);
 	} else {
 		/* TRIG_EXT */
 		/* page 4-5, "input with external REQs" */
-		writeb(0, devpriv->mite->daq_io_addr + OpMode);
-		writeb(0x00, devpriv->mite->daq_io_addr + ClockReg);
-		writeb(0, devpriv->mite->daq_io_addr + Sequence);
-		writeb(0x00, devpriv->mite->daq_io_addr + ReqReg);
-		writeb(4, devpriv->mite->daq_io_addr + BlockMode);
-		if (!(cmd->scan_begin_arg & CR_INVERT)) {
-			/* Leading Edge pulse mode */
-			writeb(0, devpriv->mite->daq_io_addr + LinePolarities);
-		} else {
-			/* Trailing Edge pulse mode */
-			writeb(2, devpriv->mite->daq_io_addr + LinePolarities);
-		}
-		writeb(0x00, devpriv->mite->daq_io_addr + AckSer);
-		writel(1, devpriv->mite->daq_io_addr + StartDelay);
-		writeb(1, devpriv->mite->daq_io_addr + ReqDelay);
-		writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay);
-		writeb(1, devpriv->mite->daq_io_addr + AckDelay);
-		writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay);
-		writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay);
-		writew(0, devpriv->mite->daq_io_addr + ClockSpeed);
-		writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions);
+		writeb(0, dev->mmio + OpMode);
+		writeb(0x00, dev->mmio + ClockReg);
+		writeb(0, dev->mmio + Sequence);
+		writeb(0x00, dev->mmio + ReqReg);
+		writeb(4, dev->mmio + BlockMode);
+		if (!(cmd->scan_begin_arg & CR_INVERT))	/* Leading Edge */
+			writeb(0, dev->mmio + LinePolarities);
+		else					/* Trailing Edge */
+			writeb(2, dev->mmio + LinePolarities);
+		writeb(0x00, dev->mmio + AckSer);
+		writel(1, dev->mmio + StartDelay);
+		writeb(1, dev->mmio + ReqDelay);
+		writeb(1, dev->mmio + ReqNotDelay);
+		writeb(1, dev->mmio + AckDelay);
+		writeb(0x0C, dev->mmio + AckNotDelay);
+		writeb(0x10, dev->mmio + Data1Delay);
+		writew(0, dev->mmio + ClockSpeed);
+		writeb(0x60, dev->mmio + DAQOptions);
 	}
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		writel(cmd->stop_arg,
-		       devpriv->mite->daq_io_addr + Transfer_Count);
+		       dev->mmio + Transfer_Count);
 	} else {
 		/* XXX */
 	}
 
 #ifdef USE_DMA
 	writeb(ClearPrimaryTC | ClearSecondaryTC,
-	       devpriv->mite->daq_io_addr + Group_1_First_Clear);
+	       dev->mmio + Group_1_First_Clear);
 
 	{
 		int retval = setup_mite_dma(dev, s);
+
 		if (retval)
 			return retval;
 	}
 #else
-	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1);
+	writeb(0x00, dev->mmio + DMA_Line_Control_Group1);
 #endif
-	writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2);
+	writeb(0x00, dev->mmio + DMA_Line_Control_Group2);
 
 	/* clear and enable interrupts */
-	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
-	/* writeb(ClearExpired,
-	       devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
+	writeb(0xff, dev->mmio + Group_1_First_Clear);
+	/* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */
 
-	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
-	writeb(0x03,
-	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
+	writeb(IntEn, dev->mmio + Interrupt_Control);
+	writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 
 	if (cmd->stop_src == TRIG_NONE) {
 		devpriv->OpModeBits = DataLatching(0) | RunMode(7);
@@ -733,8 +737,7 @@ static int ni_pcidio_cmd(struct comedi_d
 	}
 	if (cmd->start_src == TRIG_NOW) {
 		/* start */
-		writeb(devpriv->OpModeBits,
-		       devpriv->mite->daq_io_addr + OpMode);
+		writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 		s->async->inttrig = NULL;
 	} else {
 		/* TRIG_INT */
@@ -744,60 +747,17 @@ static int ni_pcidio_cmd(struct comedi_d
 	return 0;
 }
 
-static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct nidio96_private *devpriv = dev->private;
-	int retval;
-	unsigned long flags;
-
-	retval = ni_pcidio_request_di_mite_channel(dev);
-	if (retval)
-		return retval;
-
-	/* write alloc the entire buffer */
-	comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
-
-	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
-	if (devpriv->di_mite_chan) {
-		mite_prep_dma(devpriv->di_mite_chan, 32, 32);
-		mite_dma_arm(devpriv->di_mite_chan);
-	} else
-		retval = -EIO;
-	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-
-	return retval;
-}
-
-static int ni_pcidio_inttrig(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     unsigned int trig_num)
-{
-	struct nidio96_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
-
-	if (trig_num != cmd->start_arg)
-		return -EINVAL;
-
-	writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode);
-	s->async->inttrig = NULL;
-
-	return 1;
-}
-
 static int ni_pcidio_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	struct nidio96_private *devpriv = dev->private;
-
-	writeb(0x00,
-	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
+	writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control);
 	ni_pcidio_release_di_mite_channel(dev);
 
 	return 0;
 }
 
 static int ni_pcidio_change(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned long new_size)
+			    struct comedi_subdevice *s)
 {
 	struct nidio96_private *devpriv = dev->private;
 	int ret;
@@ -815,19 +775,16 @@ static int pci_6534_load_fpga(struct com
 			      const u8 *data, size_t data_len,
 			      unsigned long context)
 {
-	struct nidio96_private *devpriv = dev->private;
 	static const int timeout = 1000;
 	int fpga_index = context;
 	int i;
 	size_t j;
 
-	writew(0x80 | fpga_index,
-	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
-	writew(0xc0 | fpga_index,
-	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
+	writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
+	writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register);
 	for (i = 0;
-	     (readw(devpriv->mite->daq_io_addr +
-		    Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) {
+	     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 &&
+	     i < timeout; ++i) {
 		udelay(1);
 	}
 	if (i == timeout) {
@@ -836,11 +793,10 @@ static int pci_6534_load_fpga(struct com
 			 fpga_index);
 		return -EIO;
 	}
-	writew(0x80 | fpga_index,
-	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
+	writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 	for (i = 0;
-	     readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) !=
-	     0x3 && i < timeout; ++i) {
+	     readw(dev->mmio + Firmware_Status_Register) != 0x3 &&
+	     i < timeout; ++i) {
 		udelay(1);
 	}
 	if (i == timeout) {
@@ -851,12 +807,11 @@ static int pci_6534_load_fpga(struct com
 	}
 	for (j = 0; j + 1 < data_len;) {
 		unsigned int value = data[j++];
+
 		value |= data[j++] << 8;
-		writew(value,
-		       devpriv->mite->daq_io_addr + Firmware_Data_Register);
+		writew(value, dev->mmio + Firmware_Data_Register);
 		for (i = 0;
-		     (readw(devpriv->mite->daq_io_addr +
-			    Firmware_Status_Register) & 0x2) == 0
+		     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0
 		     && i < timeout; ++i) {
 			udelay(1);
 		}
@@ -869,7 +824,7 @@ static int pci_6534_load_fpga(struct com
 		if (need_resched())
 			schedule();
 	}
-	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
+	writew(0x0, dev->mmio + Firmware_Control_Register);
 	return 0;
 }
 
@@ -880,30 +835,27 @@ static int pci_6534_reset_fpga(struct co
 
 static int pci_6534_reset_fpgas(struct comedi_device *dev)
 {
-	struct nidio96_private *devpriv = dev->private;
 	int ret;
 	int i;
 
-	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
+	writew(0x0, dev->mmio + Firmware_Control_Register);
 	for (i = 0; i < 3; ++i) {
 		ret = pci_6534_reset_fpga(dev, i);
 		if (ret < 0)
 			break;
 	}
-	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register);
+	writew(0x0, dev->mmio + Firmware_Mask_Register);
 	return ret;
 }
 
 static void pci_6534_init_main_fpga(struct comedi_device *dev)
 {
-	struct nidio96_private *devpriv = dev->private;
-
-	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
-	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
-	writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
-	writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register);
-	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register);
-	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
+	writel(0, dev->mmio + FPGA_Control1_Register);
+	writel(0, dev->mmio + FPGA_Control2_Register);
+	writel(0, dev->mmio + FPGA_SCALS_Counter_Register);
+	writel(0, dev->mmio + FPGA_SCAMS_Counter_Register);
+	writel(0, dev->mmio + FPGA_SCBLS_Counter_Register);
+	writel(0, dev->mmio + FPGA_SCBMS_Counter_Register);
 }
 
 static int pci_6534_upload_firmware(struct comedi_device *dev)
@@ -935,15 +887,12 @@ static int pci_6534_upload_firmware(stru
 
 static void nidio_reset_board(struct comedi_device *dev)
 {
-	struct nidio96_private *devpriv = dev->private;
-	void __iomem *daq_mmio = devpriv->mite->daq_io_addr;
-
-	writel(0, daq_mmio + Port_IO(0));
-	writel(0, daq_mmio + Port_Pin_Directions(0));
-	writel(0, daq_mmio + Port_Pin_Mask(0));
+	writel(0, dev->mmio + Port_IO(0));
+	writel(0, dev->mmio + Port_Pin_Directions(0));
+	writel(0, dev->mmio + Port_Pin_Mask(0));
 
 	/* disable interrupts on board */
-	writeb(0, daq_mmio + Master_DMA_And_Interrupt_Control);
+	writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control);
 }
 
 static int nidio_auto_attach(struct comedi_device *dev,
@@ -977,11 +926,9 @@ static int nidio_auto_attach(struct come
 	if (!devpriv->mite)
 		return -ENOMEM;
 
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, "error setting up mite\n");
+	ret = mite_setup(dev, devpriv->mite);
+	if (ret < 0)
 		return ret;
-	}
 
 	devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 	if (devpriv->di_mite_ring == NULL)
@@ -1000,7 +947,7 @@ static int nidio_auto_attach(struct come
 		return ret;
 
 	dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
-		 readb(devpriv->mite->daq_io_addr + Chip_Version));
+		 readb(dev->mmio + Chip_Version));
 
 	s = &dev->subdevices[0];
 
@@ -1022,7 +969,7 @@ static int nidio_auto_attach(struct come
 	s->async_dma_dir = DMA_BIDIRECTIONAL;
 	s->poll = &ni_pcidio_poll;
 
-	irq = mite_irq(devpriv->mite);
+	irq = pcidev->irq;
 	if (irq) {
 		ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 				  dev->board_name, dev);
@@ -1044,11 +991,10 @@ static void nidio_detach(struct comedi_d
 			mite_free_ring(devpriv->di_mite_ring);
 			devpriv->di_mite_ring = NULL;
 		}
-		if (devpriv->mite) {
-			mite_unsetup(devpriv->mite);
-			mite_free(devpriv->mite);
-		}
+		mite_detach(devpriv->mite);
 	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_pcimio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_pcimio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_pcimio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_pcimio.c	2014-09-28 17:29:07.000000000 -0400
@@ -118,13 +118,6 @@ Bugs:
 
 #define PCIDMA
 
-#define PCIMIO 1
-#undef ATMIO
-
-#define MAX_N_CALDACS (16+16+2)
-
-#define DRV_NAME "ni_pcimio"
-
 /* These are not all the possible ao ranges for 628x boards.
  They can do OFFSET +- REFERENCE where OFFSET can be
  0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can
@@ -218,87 +211,79 @@ static const struct ni_board_struct ni_b
 	[BOARD_PCIMIO_16XE_50] = {
 		.name		= "pci-mio-16xe-50",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 2048,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_8,
 		.ai_speed	= 50000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 50000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043 },
 	},
 	[BOARD_PCIMIO_16XE_10] = {
 		.name		= "pci-mio-16xe-10",	/*  aka pci-6030E */
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCI6014] = {
 		.name		= "pci-6014",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PXI6030E] = {
 		.name		= "pxi-6030e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCIMIO_16E_1] = {
 		.name		= "pci-mio-16e-1",	/* aka pci-6070e */
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { mb88341 },
 	},
 	[BOARD_PCIMIO_16E_4] = {
 		.name		= "pci-mio-16e-4",	/* aka pci-6040e */
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_16,
 		/*
@@ -307,216 +292,195 @@ static const struct ni_board_struct ni_b
 		 */
 		.ai_speed	= 2000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 512,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* doc says mb88341 */
 	},
 	[BOARD_PXI6040E] = {
 		.name		= "pxi-6040e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 2000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 512,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { mb88341 },
 	},
 	[BOARD_PCI6031E] = {
 		.name		= "pci-6031e",
 		.n_adchan	= 64,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCI6032E] = {
 		.name		= "pci-6032e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCI6033E] = {
 		.name		= "pci-6033e",
 		.n_adchan	= 64,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCI6071E] = {
 		.name		= "pci-6071e",
 		.n_adchan	= 64,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PCI6023E] = {
 		.name		= "pci-6023e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* manual is wrong */
 	},
 	[BOARD_PCI6024E] = {
 		.name		= "pci-6024e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* manual is wrong */
 	},
 	[BOARD_PCI6025E] = {
 		.name		= "pci-6025e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* manual is wrong */
 		.has_8255	= 1,
 	},
 	[BOARD_PXI6025E] = {
 		.name		= "pxi-6025e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },	/* manual is wrong */
 		.has_8255	= 1,
 	},
 	[BOARD_PCI6034E] = {
 		.name		= "pci-6034e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PCI6035E] = {
 		.name		= "pci-6035e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PCI6052E] = {
 		.name		= "pci-6052e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 3000,
 		.n_aochan	= 2,
-		.aobits		= 16,
-		.ao_unipolar	= 1,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
 		.ao_speed	= 3000,
-		.num_p0_dio_channels = 8,
 		/* manual is wrong */
 		.caldac		= { ad8804_debug, ad8804_debug, ad8522 },
 	},
 	[BOARD_PCI6110] = {
 		.name		= "pci-6110",
 		.n_adchan	= 4,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 8192,
 		.alwaysdither	= 0,
 		.gainlkup	= ai_gain_611x,
 		.ai_speed	= 200,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.reg_type	= ni_reg_611x,
 		.ao_range_table	= &range_bipolar10,
 		.ao_fifo_depth	= 2048,
 		.ao_speed	= 250,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804, ad8804 },
 	},
 	[BOARD_PCI6111] = {
 		.name		= "pci-6111",
 		.n_adchan	= 2,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 8192,
 		.gainlkup	= ai_gain_611x,
 		.ai_speed	= 200,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.reg_type	= ni_reg_611x,
 		.ao_range_table	= &range_bipolar10,
 		.ao_fifo_depth	= 2048,
 		.ao_speed	= 250,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804, ad8804 },
 	},
 #if 0
@@ -524,16 +488,15 @@ static const struct ni_board_struct ni_b
 	[BOARD_PCI6115] = {	/* .device_id = 0x2ed0, */
 		.name		= "pci-6115",
 		.n_adchan	= 4,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 8192,
 		.gainlkup	= ai_gain_611x,
 		.ai_speed	= 100,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_671x	= 1,
 		.ao_fifo_depth	= 2048,
 		.ao_speed	= 250,
-		.num_p0_dio_channels = 8,
 		.reg_611x	= 1,
 		/* XXX */
 		.caldac		= { ad8804_debug, ad8804_debug, ad8804_debug },
@@ -543,17 +506,16 @@ static const struct ni_board_struct ni_b
 	[BOARD_PXI6115] = {	/* .device_id = ????, */
 		.name		= "pxi-6115",
 		.n_adchan	= 4,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 8192,
 		.gainlkup	= ai_gain_611x,
 		.ai_speed	= 100,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_671x	= 1,
 		.ao_fifo_depth	= 2048,
 		.ao_speed	= 250,
 		.reg_611x	= 1,
-		.num_p0_dio_channels = 8,
 		/* XXX */
 		.caldac		= { ad8804_debug, ad8804_debug, ad8804_debug },
 	},
@@ -561,56 +523,51 @@ static const struct ni_board_struct ni_b
 	[BOARD_PCI6711] = {
 		.name = "pci-6711",
 		.n_aochan	= 4,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		/* data sheet says 8192, but fifo really holds 16384 samples */
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6711,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PXI6711] = {
 		.name		= "pxi-6711",
 		.n_aochan	= 4,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6711,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PCI6713] = {
 		.name		= "pci-6713",
 		.n_aochan	= 8,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6713,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 	[BOARD_PXI6713] = {
 		.name		= "pxi-6713",
 		.n_aochan	= 8,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6713,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 	[BOARD_PCI6731] = {
 		.name		= "pci-6731",
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8192,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6711,
 		.caldac		= { ad8804_debug },
 	},
@@ -618,10 +575,9 @@ static const struct ni_board_struct ni_b
 	[BOARD_PXI6731] = {	/* .device_id = ????, */
 		.name		= "pxi-6731",
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8192,
 		.ao_range_table	= &range_bipolar10,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6711,
 		.caldac		= { ad8804_debug },
 	},
@@ -629,759 +585,462 @@ static const struct ni_board_struct ni_b
 	[BOARD_PCI6733] = {
 		.name		= "pci-6733",
 		.n_aochan	= 8,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6713,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 	[BOARD_PXI6733] = {
 		.name		= "pxi-6733",
 		.n_aochan	= 8,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 16384,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_6713,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 	[BOARD_PXI6071E] = {
 		.name		= "pxi-6071e",
 		.n_adchan	= 64,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PXI6070E] = {
 		.name		= "pxi-6070e",
 		.n_adchan	= 16,
-		.adbits		= 12,
+		.ai_maxdata	= 0x0fff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 12,
+		.ao_maxdata	= 0x0fff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 1000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PXI6052E] = {
 		.name		= "pxi-6052e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_16,
 		.ai_speed	= 3000,
 		.n_aochan	= 2,
-		.aobits		= 16,
-		.ao_unipolar	= 1,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
 		.ao_speed	= 3000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { mb88341, mb88341, ad8522 },
 	},
 	[BOARD_PXI6031E] = {
 		.name		= "pxi-6031e",
 		.n_adchan	= 64,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_14,
 		.ai_speed	= 10000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 2048,
 		.ao_range_table	= &range_ni_E_ao_ext,
-		.ao_unipolar	= 1,
 		.ao_speed	= 10000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { dac8800, dac8043, ad8522 },
 	},
 	[BOARD_PCI6036E] = {
 		.name = "pci-6036e",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,
 		.alwaysdither	= 1,
 		.gainlkup	= ai_gain_4,
 		.ai_speed	= 5000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_range_table	= &range_bipolar10,
 		.ao_speed	= 100000,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug },
 	},
 	[BOARD_PCI6220] = {
 		.name		= "pci-6220",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 512,		/* FIXME: guess */
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
-		.num_p0_dio_channels = 8,
 		.reg_type	= ni_reg_622x,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6221] = {
 		.name		= "pci-6221",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_bipolar10,
 		.reg_type	= ni_reg_622x,
 		.ao_speed	= 1200,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6221_37PIN] = {
 		.name		= "pci-6221_37pin",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_bipolar10,
 		.reg_type	= ni_reg_622x,
 		.ao_speed	= 1200,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6224] = {
 		.name		= "pci-6224",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.reg_type	= ni_reg_622x,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PXI6224] = {
 		.name		= "pxi-6224",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.reg_type	= ni_reg_622x,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6225] = {
 		.name		= "pci-6225",
 		.n_adchan	= 80,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_bipolar10,
 		.reg_type	= ni_reg_622x,
 		.ao_speed	= 1200,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PXI6225] = {
 		.name		= "pxi-6225",
 		.n_adchan	= 80,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_bipolar10,
 		.reg_type	= ni_reg_622x,
 		.ao_speed	= 1200,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6229] = {
 		.name		= "pci-6229",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_622x,
 		.ai_speed	= 4000,
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_bipolar10,
 		.reg_type	= ni_reg_622x,
 		.ao_speed	= 1200,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6250] = {
 		.name		= "pci-6250",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.reg_type	= ni_reg_625x,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6251] = {
 		.name		= "pci-6251",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_625x_ao,
 		.reg_type	= ni_reg_625x,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCIE6251] = {
 		.name		= "pcie-6251",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_625x_ao,
 		.reg_type	= ni_reg_625x,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PXIE6251] = {
 		.name		= "pxie-6251",
 		.n_adchan	= 16,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_625x_ao,
 		.reg_type	= ni_reg_625x,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6254] = {
 		.name		= "pci-6254",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.reg_type	= ni_reg_625x,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6259] = {
 		.name		= "pci-6259",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_625x_ao,
 		.reg_type	= ni_reg_625x,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCIE6259] = {
 		.name		= "pcie-6259",
 		.n_adchan	= 32,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 4095,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 800,
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_625x_ao,
 		.reg_type	= ni_reg_625x,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6280] = {
 		.name		= "pci-6280",
 		.n_adchan	= 16,
-		.adbits		= 18,
+		.ai_maxdata	= 0x3ffff,
 		.ai_fifo_depth	= 2047,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 1600,
 		.ao_fifo_depth	= 8191,
 		.reg_type	= ni_reg_628x,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6281] = {
 		.name		= "pci-6281",
 		.n_adchan	= 16,
-		.adbits		= 18,
+		.ai_maxdata	= 0x3ffff,
 		.ai_fifo_depth	= 2047,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 1600,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table = &range_ni_M_628x_ao,
 		.reg_type	= ni_reg_628x,
-		.ao_unipolar	= 1,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PXI6281] = {
 		.name		= "pxi-6281",
 		.n_adchan	= 16,
-		.adbits		= 18,
+		.ai_maxdata	= 0x3ffff,
 		.ai_fifo_depth	= 2047,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 1600,
 		.n_aochan	= 2,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_628x_ao,
 		.reg_type	= ni_reg_628x,
-		.ao_unipolar	= 1,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 8,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6284] = {
 		.name		= "pci-6284",
 		.n_adchan	= 32,
-		.adbits		= 18,
+		.ai_maxdata	= 0x3ffff,
 		.ai_fifo_depth	= 2047,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 1600,
 		.reg_type	= ni_reg_628x,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6289] = {
 		.name		= "pci-6289",
 		.n_adchan	= 32,
-		.adbits		= 18,
+		.ai_maxdata	= 0x3ffff,
 		.ai_fifo_depth	= 2047,
 		.gainlkup	= ai_gain_628x,
 		.ai_speed	= 1600,
 		.n_aochan	= 4,
-		.aobits		= 16,
+		.ao_maxdata	= 0xffff,
 		.ao_fifo_depth	= 8191,
 		.ao_range_table	= &range_ni_M_628x_ao,
 		.reg_type	= ni_reg_628x,
-		.ao_unipolar	= 1,
 		.ao_speed	= 350,
-		.num_p0_dio_channels = 32,
+		.has_32dio_chan	= 1,
 		.caldac		= { caldac_none },
 	},
 	[BOARD_PCI6143] = {
 		.name		= "pci-6143",
 		.n_adchan	= 8,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 1024,
 		.gainlkup	= ai_gain_6143,
 		.ai_speed	= 4000,
 		.reg_type	= ni_reg_6143,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 	[BOARD_PXI6143] = {
 		.name		= "pxi-6143",
 		.n_adchan	= 8,
-		.adbits		= 16,
+		.ai_maxdata	= 0xffff,
 		.ai_fifo_depth	= 1024,
 		.gainlkup	= ai_gain_6143,
 		.ai_speed	= 4000,
 		.reg_type	= ni_reg_6143,
-		.num_p0_dio_channels = 8,
 		.caldac		= { ad8804_debug, ad8804_debug },
 	},
 };
 
-struct ni_private {
-NI_PRIVATE_COMMON};
-
-/* How we access registers */
-
-#define ni_writel(a, b)	(writel((a), devpriv->mite->daq_io_addr + (b)))
-#define ni_readl(a)	(readl(devpriv->mite->daq_io_addr + (a)))
-#define ni_writew(a, b)	(writew((a), devpriv->mite->daq_io_addr + (b)))
-#define ni_readw(a)	(readw(devpriv->mite->daq_io_addr + (a)))
-#define ni_writeb(a, b)	(writeb((a), devpriv->mite->daq_io_addr + (b)))
-#define ni_readb(a)	(readb(devpriv->mite->daq_io_addr + (a)))
-
-/* How we access STC registers */
-
-/* We automatically take advantage of STC registers that can be
- * read/written directly in the I/O space of the board.  Most
- * PCIMIO devices map the low 8 STC registers to iobase+addr*2.
- * The 611x devices map the write registers to iobase+addr*2, and
- * the read registers to iobase+(addr-1)*2. */
-/* However, the 611x boards still aren't working, so I'm disabling
- * non-windowed STC access temporarily */
+#include "ni_mio_common.c"
 
-static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
+static int pcimio_ai_change(struct comedi_device *dev,
+			    struct comedi_subdevice *s)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
+	int ret;
 
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	ni_writew(reg, Window_Address);
-	ni_writew(data, Window_Data);
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
+	ret = mite_buf_change(devpriv->ai_mite_ring, s);
+	if (ret < 0)
+		return ret;
+
+	return 0;
 }
 
-static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
+static int pcimio_ao_change(struct comedi_device *dev,
+			    struct comedi_subdevice *s)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned long flags;
-	uint16_t ret;
+	int ret;
 
-	spin_lock_irqsave(&devpriv->window_lock, flags);
-	ni_writew(reg, Window_Address);
-	ret = ni_readw(Window_Data);
-	spin_unlock_irqrestore(&devpriv->window_lock, flags);
+	ret = mite_buf_change(devpriv->ao_mite_ring, s);
+	if (ret < 0)
+		return ret;
 
-	return ret;
+	return 0;
 }
 
-static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
-				int reg)
+static int pcimio_gpct0_change(struct comedi_device *dev,
+			       struct comedi_subdevice *s)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned offset;
-
-	switch (reg) {
-	case ADC_FIFO_Clear:
-		offset = M_Offset_AI_FIFO_Clear;
-		break;
-	case AI_Command_1_Register:
-		offset = M_Offset_AI_Command_1;
-		break;
-	case AI_Command_2_Register:
-		offset = M_Offset_AI_Command_2;
-		break;
-	case AI_Mode_1_Register:
-		offset = M_Offset_AI_Mode_1;
-		break;
-	case AI_Mode_2_Register:
-		offset = M_Offset_AI_Mode_2;
-		break;
-	case AI_Mode_3_Register:
-		offset = M_Offset_AI_Mode_3;
-		break;
-	case AI_Output_Control_Register:
-		offset = M_Offset_AI_Output_Control;
-		break;
-	case AI_Personal_Register:
-		offset = M_Offset_AI_Personal;
-		break;
-	case AI_SI2_Load_A_Register:
-		/*  this is actually a 32 bit register on m series boards */
-		ni_writel(data, M_Offset_AI_SI2_Load_A);
-		return;
-		break;
-	case AI_SI2_Load_B_Register:
-		/*  this is actually a 32 bit register on m series boards */
-		ni_writel(data, M_Offset_AI_SI2_Load_B);
-		return;
-		break;
-	case AI_START_STOP_Select_Register:
-		offset = M_Offset_AI_START_STOP_Select;
-		break;
-	case AI_Trigger_Select_Register:
-		offset = M_Offset_AI_Trigger_Select;
-		break;
-	case Analog_Trigger_Etc_Register:
-		offset = M_Offset_Analog_Trigger_Etc;
-		break;
-	case AO_Command_1_Register:
-		offset = M_Offset_AO_Command_1;
-		break;
-	case AO_Command_2_Register:
-		offset = M_Offset_AO_Command_2;
-		break;
-	case AO_Mode_1_Register:
-		offset = M_Offset_AO_Mode_1;
-		break;
-	case AO_Mode_2_Register:
-		offset = M_Offset_AO_Mode_2;
-		break;
-	case AO_Mode_3_Register:
-		offset = M_Offset_AO_Mode_3;
-		break;
-	case AO_Output_Control_Register:
-		offset = M_Offset_AO_Output_Control;
-		break;
-	case AO_Personal_Register:
-		offset = M_Offset_AO_Personal;
-		break;
-	case AO_Start_Select_Register:
-		offset = M_Offset_AO_Start_Select;
-		break;
-	case AO_Trigger_Select_Register:
-		offset = M_Offset_AO_Trigger_Select;
-		break;
-	case Clock_and_FOUT_Register:
-		offset = M_Offset_Clock_and_FOUT;
-		break;
-	case Configuration_Memory_Clear:
-		offset = M_Offset_Configuration_Memory_Clear;
-		break;
-	case DAC_FIFO_Clear:
-		offset = M_Offset_AO_FIFO_Clear;
-		break;
-	case DIO_Control_Register:
-		dev_dbg(dev->class_dev,
-			"%s: FIXME: register 0x%x does not map cleanly on to m-series boards.\n",
-			__func__, reg);
-		return;
-		break;
-	case G_Autoincrement_Register(0):
-		offset = M_Offset_G0_Autoincrement;
-		break;
-	case G_Autoincrement_Register(1):
-		offset = M_Offset_G1_Autoincrement;
-		break;
-	case G_Command_Register(0):
-		offset = M_Offset_G0_Command;
-		break;
-	case G_Command_Register(1):
-		offset = M_Offset_G1_Command;
-		break;
-	case G_Input_Select_Register(0):
-		offset = M_Offset_G0_Input_Select;
-		break;
-	case G_Input_Select_Register(1):
-		offset = M_Offset_G1_Input_Select;
-		break;
-	case G_Mode_Register(0):
-		offset = M_Offset_G0_Mode;
-		break;
-	case G_Mode_Register(1):
-		offset = M_Offset_G1_Mode;
-		break;
-	case Interrupt_A_Ack_Register:
-		offset = M_Offset_Interrupt_A_Ack;
-		break;
-	case Interrupt_A_Enable_Register:
-		offset = M_Offset_Interrupt_A_Enable;
-		break;
-	case Interrupt_B_Ack_Register:
-		offset = M_Offset_Interrupt_B_Ack;
-		break;
-	case Interrupt_B_Enable_Register:
-		offset = M_Offset_Interrupt_B_Enable;
-		break;
-	case Interrupt_Control_Register:
-		offset = M_Offset_Interrupt_Control;
-		break;
-	case IO_Bidirection_Pin_Register:
-		offset = M_Offset_IO_Bidirection_Pin;
-		break;
-	case Joint_Reset_Register:
-		offset = M_Offset_Joint_Reset;
-		break;
-	case RTSI_Trig_A_Output_Register:
-		offset = M_Offset_RTSI_Trig_A_Output;
-		break;
-	case RTSI_Trig_B_Output_Register:
-		offset = M_Offset_RTSI_Trig_B_Output;
-		break;
-	case RTSI_Trig_Direction_Register:
-		offset = M_Offset_RTSI_Trig_Direction;
-		break;
-		/* FIXME: DIO_Output_Register (16 bit reg) is replaced by M_Offset_Static_Digital_Output (32 bit)
-		   and M_Offset_SCXI_Serial_Data_Out (8 bit) */
-	default:
-		dev_warn(dev->class_dev,
-			 "%s: bug! unhandled register=0x%x in switch.\n",
-			 __func__, reg);
-		BUG();
-		return;
-		break;
-	}
-	ni_writew(data, offset);
-}
+	int ret;
 
-static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
-{
-	struct ni_private *devpriv = dev->private;
-	unsigned offset;
+	ret = mite_buf_change(devpriv->gpct_mite_ring[0], s);
+	if (ret < 0)
+		return ret;
 
-	switch (reg) {
-	case AI_Status_1_Register:
-		offset = M_Offset_AI_Status_1;
-		break;
-	case AO_Status_1_Register:
-		offset = M_Offset_AO_Status_1;
-		break;
-	case AO_Status_2_Register:
-		offset = M_Offset_AO_Status_2;
-		break;
-	case DIO_Serial_Input_Register:
-		return ni_readb(M_Offset_SCXI_Serial_Data_In);
-		break;
-	case Joint_Status_1_Register:
-		offset = M_Offset_Joint_Status_1;
-		break;
-	case Joint_Status_2_Register:
-		offset = M_Offset_Joint_Status_2;
-		break;
-	case G_Status_Register:
-		offset = M_Offset_G01_Status;
-		break;
-	default:
-		dev_warn(dev->class_dev,
-			 "%s: bug! unhandled register=0x%x in switch.\n",
-			 __func__, reg);
-		BUG();
-		return 0;
-		break;
-	}
-	return ni_readw(offset);
+	return 0;
 }
 
-static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
-				int reg)
+static int pcimio_gpct1_change(struct comedi_device *dev,
+			       struct comedi_subdevice *s)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned offset;
+	int ret;
 
-	switch (reg) {
-	case AI_SC_Load_A_Registers:
-		offset = M_Offset_AI_SC_Load_A;
-		break;
-	case AI_SI_Load_A_Registers:
-		offset = M_Offset_AI_SI_Load_A;
-		break;
-	case AO_BC_Load_A_Register:
-		offset = M_Offset_AO_BC_Load_A;
-		break;
-	case AO_UC_Load_A_Register:
-		offset = M_Offset_AO_UC_Load_A;
-		break;
-	case AO_UI_Load_A_Register:
-		offset = M_Offset_AO_UI_Load_A;
-		break;
-	case G_Load_A_Register(0):
-		offset = M_Offset_G0_Load_A;
-		break;
-	case G_Load_A_Register(1):
-		offset = M_Offset_G1_Load_A;
-		break;
-	case G_Load_B_Register(0):
-		offset = M_Offset_G0_Load_B;
-		break;
-	case G_Load_B_Register(1):
-		offset = M_Offset_G1_Load_B;
-		break;
-	default:
-		dev_warn(dev->class_dev,
-			 "%s: bug! unhandled register=0x%x in switch.\n",
-			 __func__, reg);
-		BUG();
-		return;
-		break;
-	}
-	ni_writel(data, offset);
+	ret = mite_buf_change(devpriv->gpct_mite_ring[1], s);
+	if (ret < 0)
+		return ret;
+
+	return 0;
 }
 
-static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
+static int pcimio_dio_change(struct comedi_device *dev,
+			     struct comedi_subdevice *s)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned offset;
-
-	switch (reg) {
-	case G_HW_Save_Register(0):
-		offset = M_Offset_G0_HW_Save;
-		break;
-	case G_HW_Save_Register(1):
-		offset = M_Offset_G1_HW_Save;
-		break;
-	case G_Save_Register(0):
-		offset = M_Offset_G0_Save;
-		break;
-	case G_Save_Register(1):
-		offset = M_Offset_G1_Save;
-		break;
-	default:
-		dev_warn(dev->class_dev,
-			 "%s: bug! unhandled register=0x%x in switch.\n",
-			 __func__, reg);
-		BUG();
-		return 0;
-		break;
-	}
-	return ni_readl(offset);
-}
-
-#define interrupt_pin(a)	0
-#define IRQ_POLARITY 1
+	int ret;
 
-#define NI_E_IRQ_FLAGS		IRQF_SHARED
+	ret = mite_buf_change(devpriv->cdo_mite_ring, s);
+	if (ret < 0)
+		return ret;
 
-#include "ni_mio_common.c"
+	return 0;
+}
 
-static int pcimio_ai_change(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned long new_size);
-static int pcimio_ao_change(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned long new_size);
-static int pcimio_gpct0_change(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       unsigned long new_size);
-static int pcimio_gpct1_change(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       unsigned long new_size);
-static int pcimio_dio_change(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     unsigned long new_size);
 
 static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 {
@@ -1408,12 +1067,12 @@ static void m_series_init_eeprom_buffer(
 	BUG_ON(serial_number_eeprom_length > sizeof(devpriv->serial_number));
 	for (i = 0; i < serial_number_eeprom_length; ++i) {
 		char *byte_ptr = (char *)&devpriv->serial_number + i;
-		*byte_ptr = ni_readb(serial_number_eeprom_offset + i);
+		*byte_ptr = ni_readb(dev, serial_number_eeprom_offset + i);
 	}
 	devpriv->serial_number = be32_to_cpu(devpriv->serial_number);
 
 	for (i = 0; i < M_SERIES_EEPROM_SIZE; ++i)
-		devpriv->eeprom_buffer[i] = ni_readb(Start_Cal_EEPROM + i);
+		devpriv->eeprom_buffer[i] = ni_readb(dev, Start_Cal_EEPROM + i);
 
 	writel(old_iodwbsr1_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR_1);
 	writel(old_iodwbsr_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR);
@@ -1427,21 +1086,26 @@ static void init_6143(struct comedi_devi
 	struct ni_private *devpriv = dev->private;
 
 	/*  Disable interrupts */
-	devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
+	ni_stc_writew(dev, 0, Interrupt_Control_Register);
 
 	/*  Initialise 6143 AI specific bits */
-	ni_writeb(0x00, Magic_6143);	/*  Set G0,G1 DMA mode to E series version */
-	ni_writeb(0x80, PipelineDelay_6143);	/*  Set EOCMode, ADCMode and pipelinedelay */
-	ni_writeb(0x00, EOC_Set_6143);	/*  Set EOC Delay */
+
+	/* Set G0,G1 DMA mode to E series version */
+	ni_writeb(dev, 0x00, Magic_6143);
+	/* Set EOCMode, ADCMode and pipelinedelay */
+	ni_writeb(dev, 0x80, PipelineDelay_6143);
+	/* Set EOC Delay */
+	ni_writeb(dev, 0x00, EOC_Set_6143);
 
 	/* Set the FIFO half full level */
-	ni_writel(board->ai_fifo_depth / 2, AIFIFO_Flag_6143);
+	ni_writel(dev, board->ai_fifo_depth / 2, AIFIFO_Flag_6143);
 
 	/*  Strobe Relay disable bit */
 	devpriv->ai_calib_source_enabled = 0;
-	ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff,
+	ni_writew(dev, devpriv->ai_calib_source |
+		       Calibration_Channel_6143_RelayOff,
 		  Calibration_Channel_6143);
-	ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143);
+	ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143);
 }
 
 static void pcimio_detach(struct comedi_device *dev)
@@ -1457,11 +1121,10 @@ static void pcimio_detach(struct comedi_
 		mite_free_ring(devpriv->cdo_mite_ring);
 		mite_free_ring(devpriv->gpct_mite_ring[0]);
 		mite_free_ring(devpriv->gpct_mite_ring[1]);
-		if (devpriv->mite) {
-			mite_unsetup(devpriv->mite);
-			mite_free(devpriv->mite);
-		}
+		mite_detach(devpriv->mite);
 	}
+	if (dev->mmio)
+		iounmap(dev->mmio);
 	comedi_pci_disable(dev);
 }
 
@@ -1494,23 +1157,30 @@ static int pcimio_auto_attach(struct com
 	if (!devpriv->mite)
 		return -ENOMEM;
 
-	if (board->reg_type & ni_reg_m_series_mask) {
-		devpriv->stc_writew = &m_series_stc_writew;
-		devpriv->stc_readw = &m_series_stc_readw;
-		devpriv->stc_writel = &m_series_stc_writel;
-		devpriv->stc_readl = &m_series_stc_readl;
-	} else {
-		devpriv->stc_writew = &e_series_win_out;
-		devpriv->stc_readw = &e_series_win_in;
-		devpriv->stc_writel = &win_out2;
-		devpriv->stc_readl = &win_in2;
-	}
+	if (board->reg_type & ni_reg_m_series_mask)
+		devpriv->is_m_series = 1;
+	if (board->reg_type & ni_reg_6xxx_mask)
+		devpriv->is_6xxx = 1;
+	if (board->reg_type == ni_reg_611x)
+		devpriv->is_611x = 1;
+	if (board->reg_type == ni_reg_6143)
+		devpriv->is_6143 = 1;
+	if (board->reg_type == ni_reg_622x)
+		devpriv->is_622x = 1;
+	if (board->reg_type == ni_reg_625x)
+		devpriv->is_625x = 1;
+	if (board->reg_type == ni_reg_628x)
+		devpriv->is_628x = 1;
+	if (board->reg_type & ni_reg_67xx_mask)
+		devpriv->is_67xx = 1;
+	if (board->reg_type == ni_reg_6711)
+		devpriv->is_6711 = 1;
+	if (board->reg_type == ni_reg_6713)
+		devpriv->is_6713 = 1;
 
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0) {
-		pr_warn("error setting up mite\n");
+	ret = mite_setup(dev, devpriv->mite);
+	if (ret < 0)
 		return ret;
-	}
 
 	devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite);
 	if (devpriv->ai_mite_ring == NULL)
@@ -1528,20 +1198,20 @@ static int pcimio_auto_attach(struct com
 	if (devpriv->gpct_mite_ring[1] == NULL)
 		return -ENOMEM;
 
-	if (board->reg_type & ni_reg_m_series_mask)
+	if (devpriv->is_m_series)
 		m_series_init_eeprom_buffer(dev);
-	if (board->reg_type == ni_reg_6143)
+	if (devpriv->is_6143)
 		init_6143(dev);
 
-	irq = mite_irq(devpriv->mite);
+	irq = pcidev->irq;
 	if (irq) {
-		ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
+		ret = request_irq(irq, ni_E_interrupt, IRQF_SHARED,
 				  dev->board_name, dev);
 		if (ret == 0)
 			dev->irq = irq;
 	}
 
-	ret = ni_E_init(dev);
+	ret = ni_E_init(dev, 0, 1);
 	if (ret < 0)
 		return ret;
 
@@ -1553,73 +1223,6 @@ static int pcimio_auto_attach(struct com
 
 	return 0;
 }
-
-static int pcimio_ai_change(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned long new_size)
-{
-	struct ni_private *devpriv = dev->private;
-	int ret;
-
-	ret = mite_buf_change(devpriv->ai_mite_ring, s);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int pcimio_ao_change(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned long new_size)
-{
-	struct ni_private *devpriv = dev->private;
-	int ret;
-
-	ret = mite_buf_change(devpriv->ao_mite_ring, s);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int pcimio_gpct0_change(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       unsigned long new_size)
-{
-	struct ni_private *devpriv = dev->private;
-	int ret;
-
-	ret = mite_buf_change(devpriv->gpct_mite_ring[0], s);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int pcimio_gpct1_change(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       unsigned long new_size)
-{
-	struct ni_private *devpriv = dev->private;
-	int ret;
-
-	ret = mite_buf_change(devpriv->gpct_mite_ring[1], s);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int pcimio_dio_change(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned long new_size)
-{
-	struct ni_private *devpriv = dev->private;
-	int ret;
-
-	ret = mite_buf_change(devpriv->cdo_mite_ring, s);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
 
 static struct comedi_driver ni_pcimio_driver = {
 	.driver_name	= "ni_pcimio",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_stc.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_stc.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_stc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_stc.h	2014-09-28 17:29:07.000000000 -0400
@@ -1285,14 +1285,6 @@ static inline unsigned MSeries_PFI_Outpu
 	return (bits >> ((channel % 3) * 5)) & 0x1f;
 };
 
-enum MSeries_Gi_DMA_Config_Bits {
-	Gi_DMA_BankSW_Error_Bit = 0x10,
-	Gi_DMA_Reset_Bit = 0x8,
-	Gi_DMA_Int_Enable_Bit = 0x4,
-	Gi_DMA_Write_Bit = 0x2,
-	Gi_DMA_Enable_Bit = 0x1,
-};
-
 static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel)
 {
 	return 0x3 << (channel * 2);
@@ -1388,12 +1380,12 @@ enum Interrupt_C_Status_Bits {
 #define M_SERIES_EEPROM_SIZE 1024
 
 struct ni_board_struct {
+	const char *name;
 	int device_id;
 	int isapnp_id;
-	char *name;
 
 	int n_adchan;
-	int adbits;
+	unsigned int ai_maxdata;
 
 	int ai_fifo_depth;
 	unsigned int alwaysdither:1;
@@ -1401,107 +1393,100 @@ struct ni_board_struct {
 	int ai_speed;
 
 	int n_aochan;
-	int aobits;
+	unsigned int ao_maxdata;
 	int ao_fifo_depth;
 	const struct comedi_lrange *ao_range_table;
 	unsigned ao_speed;
 
-	unsigned num_p0_dio_channels;
-
 	int reg_type;
-	unsigned int ao_unipolar:1;
 	unsigned int has_8255:1;
-	unsigned int has_analog_trig:1;
+	unsigned int has_32dio_chan:1;
 
 	enum caldac_enum caldac[3];
 };
 
-#define MAX_N_AO_CHAN 8
-#define NUM_GPCT 2
+#define MAX_N_CALDACS	34
+#define MAX_N_AO_CHAN	8
+#define NUM_GPCT	2
 
-#define NI_PRIVATE_COMMON					\
-	uint16_t (*stc_readw)(struct comedi_device *dev, int register);	\
-	uint32_t (*stc_readl)(struct comedi_device *dev, int register);	\
-	void (*stc_writew)(struct comedi_device *dev, uint16_t value, int register);	\
-	void (*stc_writel)(struct comedi_device *dev, uint32_t value, int register);	\
-	\
-	unsigned short dio_output;				\
-	unsigned short dio_control;				\
-	int ao0p, ao1p;						\
-	int lastchan;						\
-	int last_do;						\
-	int rt_irq;						\
-	int irqmask;						\
-	int aimode;						\
-	int ai_continuous;					\
-	int blocksize;						\
-	int n_left;						\
-	unsigned int ai_calib_source;				\
-	unsigned int ai_calib_source_enabled;			\
-	spinlock_t window_lock; \
-	spinlock_t soft_reg_copy_lock; \
-	spinlock_t mite_channel_lock; \
-								\
-	int changain_state;					\
-	unsigned int changain_spec;				\
-								\
-	unsigned int caldac_maxdata_list[MAX_N_CALDACS];	\
-	unsigned short ao[MAX_N_AO_CHAN];					\
-	unsigned short caldacs[MAX_N_CALDACS];				\
-								\
-	unsigned short ai_cmd2;	\
-								\
-	unsigned short ao_conf[MAX_N_AO_CHAN];				\
-	unsigned short ao_mode1;				\
-	unsigned short ao_mode2;				\
-	unsigned short ao_mode3;				\
-	unsigned short ao_cmd1;					\
-	unsigned short ao_cmd2;					\
-	unsigned short ao_cmd3;					\
-	unsigned short ao_trigger_select;			\
-								\
-	struct ni_gpct_device *counter_dev;	\
-	unsigned short an_trig_etc_reg;				\
-								\
-	unsigned ai_offset[512];				\
-								\
-	unsigned long serial_interval_ns;                       \
-	unsigned char serial_hw_mode;                           \
-	unsigned short clock_and_fout;				\
-	unsigned short clock_and_fout2;				\
-								\
-	unsigned short int_a_enable_reg;			\
-	unsigned short int_b_enable_reg;			\
-	unsigned short io_bidirection_pin_reg;			\
-	unsigned short rtsi_trig_direction_reg;			\
-	unsigned short rtsi_trig_a_output_reg; \
-	unsigned short rtsi_trig_b_output_reg; \
-	unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS]; \
-	unsigned short ai_ao_select_reg; \
-	unsigned short g0_g1_select_reg; \
-	unsigned short cdio_dma_select_reg; \
-	\
-	unsigned clock_ns; \
-	unsigned clock_source; \
-	\
-	unsigned short atrig_mode;				\
-	unsigned short atrig_high;				\
-	unsigned short atrig_low;				\
-	\
-	unsigned short pwm_up_count;	\
-	unsigned short pwm_down_count;	\
-	\
-	unsigned short ai_fifo_buffer[0x2000];			\
-	uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \
-	uint32_t serial_number; \
-	\
-	struct mite_struct *mite; \
-	struct mite_channel *ai_mite_chan; \
-	struct mite_channel *ao_mite_chan;\
-	struct mite_channel *cdo_mite_chan;\
-	struct mite_dma_descriptor_ring *ai_mite_ring; \
-	struct mite_dma_descriptor_ring *ao_mite_ring; \
-	struct mite_dma_descriptor_ring *cdo_mite_ring; \
+struct ni_private {
+	unsigned short dio_output;
+	unsigned short dio_control;
+	int aimode;
+	unsigned int ai_calib_source;
+	unsigned int ai_calib_source_enabled;
+	spinlock_t window_lock;
+	spinlock_t soft_reg_copy_lock;
+	spinlock_t mite_channel_lock;
+
+	int changain_state;
+	unsigned int changain_spec;
+
+	unsigned int caldac_maxdata_list[MAX_N_CALDACS];
+	unsigned short ao[MAX_N_AO_CHAN];
+	unsigned short caldacs[MAX_N_CALDACS];
+
+	unsigned short ai_cmd2;
+
+	unsigned short ao_conf[MAX_N_AO_CHAN];
+	unsigned short ao_mode1;
+	unsigned short ao_mode2;
+	unsigned short ao_mode3;
+	unsigned short ao_cmd1;
+	unsigned short ao_cmd2;
+	unsigned short ao_trigger_select;
+
+	struct ni_gpct_device *counter_dev;
+	unsigned short an_trig_etc_reg;
+
+	unsigned ai_offset[512];
+
+	unsigned long serial_interval_ns;
+	unsigned char serial_hw_mode;
+	unsigned short clock_and_fout;
+	unsigned short clock_and_fout2;
+
+	unsigned short int_a_enable_reg;
+	unsigned short int_b_enable_reg;
+	unsigned short io_bidirection_pin_reg;
+	unsigned short rtsi_trig_direction_reg;
+	unsigned short rtsi_trig_a_output_reg;
+	unsigned short rtsi_trig_b_output_reg;
+	unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS];
+	unsigned short ai_ao_select_reg;
+	unsigned short g0_g1_select_reg;
+	unsigned short cdio_dma_select_reg;
+
+	unsigned clock_ns;
+	unsigned clock_source;
+
+	unsigned short pwm_up_count;
+	unsigned short pwm_down_count;
+
+	unsigned short ai_fifo_buffer[0x2000];
+	uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE];
+	uint32_t serial_number;
+
+	struct mite_struct *mite;
+	struct mite_channel *ai_mite_chan;
+	struct mite_channel *ao_mite_chan;
+	struct mite_channel *cdo_mite_chan;
+	struct mite_dma_descriptor_ring *ai_mite_ring;
+	struct mite_dma_descriptor_ring *ao_mite_ring;
+	struct mite_dma_descriptor_ring *cdo_mite_ring;
 	struct mite_dma_descriptor_ring *gpct_mite_ring[NUM_GPCT];
 
+	/* ni_pcimio board type flags (based on the boardinfo reg_type) */
+	unsigned int is_m_series:1;
+	unsigned int is_6xxx:1;
+	unsigned int is_611x:1;
+	unsigned int is_6143:1;
+	unsigned int is_622x:1;
+	unsigned int is_625x:1;
+	unsigned int is_628x:1;
+	unsigned int is_67xx:1;
+	unsigned int is_6711:1;
+	unsigned int is_6713:1;
+};
+
 #endif /* _COMEDI_NI_STC_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,363 +49,336 @@ TODO:
 
 #include "ni_tio_internal.h"
 
-static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
-				       unsigned generic_clock_source);
-static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter);
+/*
+ * clock sources for ni e and m series boards,
+ * get bits with GI_SRC_SEL()
+ */
+#define NI_M_TIMEBASE_1_CLK		0x0	/* 20MHz */
+#define NI_M_PFI_CLK(x)			(((x) < 10) ? (1 + (x)) : (0xb + (x)))
+#define NI_M_RTSI_CLK(x)		(((x) == 7) ? 0x1b : (0xb + (x)))
+#define NI_M_TIMEBASE_2_CLK		0x12	/* 100KHz */
+#define NI_M_NEXT_TC_CLK		0x13
+#define NI_M_NEXT_GATE_CLK		0x14	/* Gi_Src_SubSelect=0 */
+#define NI_M_PXI_STAR_TRIGGER_CLK	0x14	/* Gi_Src_SubSelect=1 */
+#define NI_M_PXI10_CLK			0x1d
+#define NI_M_TIMEBASE_3_CLK		0x1e	/* 80MHz, Gi_Src_SubSelect=0 */
+#define NI_M_ANALOG_TRIGGER_OUT_CLK	0x1e	/* Gi_Src_SubSelect=1 */
+#define NI_M_LOGIC_LOW_CLK		0x1f
+#define NI_M_MAX_PFI_CHAN		15
+#define NI_M_MAX_RTSI_CHAN		7
 
-static inline enum Gi_Counting_Mode_Reg_Bits Gi_Alternate_Sync_Bit(enum
-								   ni_gpct_variant
-								   variant)
+/*
+ * clock sources for ni_660x boards,
+ * get bits with GI_SRC_SEL()
+ */
+#define NI_660X_TIMEBASE_1_CLK		0x0	/* 20MHz */
+#define NI_660X_SRC_PIN_I_CLK		0x1
+#define NI_660X_SRC_PIN_CLK(x)		(0x2 + (x))
+#define NI_660X_NEXT_GATE_CLK		0xa
+#define NI_660X_RTSI_CLK(x)		(0xb + (x))
+#define NI_660X_TIMEBASE_2_CLK		0x12	/* 100KHz */
+#define NI_660X_NEXT_TC_CLK		0x13
+#define NI_660X_TIMEBASE_3_CLK		0x1e	/* 80MHz */
+#define NI_660X_LOGIC_LOW_CLK		0x1f
+#define NI_660X_MAX_SRC_PIN		7
+#define NI_660X_MAX_RTSI_CHAN		6
+
+/* ni m series gate_select */
+#define NI_M_TIMESTAMP_MUX_GATE_SEL	0x0
+#define NI_M_PFI_GATE_SEL(x)		(((x) < 10) ? (1 + (x)) : (0xb + (x)))
+#define NI_M_RTSI_GATE_SEL(x)		(((x) == 7) ? 0x1b : (0xb + (x)))
+#define NI_M_AI_START2_GATE_SEL		0x12
+#define NI_M_PXI_STAR_TRIGGER_GATE_SEL	0x13
+#define NI_M_NEXT_OUT_GATE_SEL		0x14
+#define NI_M_AI_START1_GATE_SEL		0x1c
+#define NI_M_NEXT_SRC_GATE_SEL		0x1d
+#define NI_M_ANALOG_TRIG_OUT_GATE_SEL	0x1e
+#define NI_M_LOGIC_LOW_GATE_SEL		0x1f
+
+/* ni_660x gate select */
+#define NI_660X_SRC_PIN_I_GATE_SEL	0x0
+#define NI_660X_GATE_PIN_I_GATE_SEL	0x1
+#define NI_660X_PIN_GATE_SEL(x)		(0x2 + (x))
+#define NI_660X_NEXT_SRC_GATE_SEL	0xa
+#define NI_660X_RTSI_GATE_SEL(x)	(0xb + (x))
+#define NI_660X_NEXT_OUT_GATE_SEL	0x14
+#define NI_660X_LOGIC_LOW_GATE_SEL	0x1f
+#define NI_660X_MAX_GATE_PIN		7
+
+/* ni_660x second gate select */
+#define NI_660X_SRC_PIN_I_GATE2_SEL	0x0
+#define NI_660X_UD_PIN_I_GATE2_SEL	0x1
+#define NI_660X_UD_PIN_GATE2_SEL(x)	(0x2 + (x))
+#define NI_660X_NEXT_SRC_GATE2_SEL	0xa
+#define NI_660X_RTSI_GATE2_SEL(x)	(0xb + (x))
+#define NI_660X_NEXT_OUT_GATE2_SEL	0x14
+#define NI_660X_SELECTED_GATE2_SEL	0x1e
+#define NI_660X_LOGIC_LOW_GATE2_SEL	0x1f
+#define NI_660X_MAX_UP_DOWN_PIN		7
+
+static inline unsigned GI_ALT_SYNC(enum ni_gpct_variant variant)
 {
 	switch (variant) {
 	case ni_gpct_variant_e_series:
+	default:
 		return 0;
-		break;
 	case ni_gpct_variant_m_series:
-		return Gi_M_Series_Alternate_Sync_Bit;
-		break;
+		return GI_M_ALT_SYNC;
 	case ni_gpct_variant_660x:
-		return Gi_660x_Alternate_Sync_Bit;
-		break;
-	default:
-		BUG();
-		break;
+		return GI_660X_ALT_SYNC;
 	}
-	return 0;
 }
 
-static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X2_Bit(enum
-								ni_gpct_variant
-								variant)
+static inline unsigned GI_PRESCALE_X2(enum ni_gpct_variant variant)
 {
 	switch (variant) {
 	case ni_gpct_variant_e_series:
+	default:
 		return 0;
-		break;
 	case ni_gpct_variant_m_series:
-		return Gi_M_Series_Prescale_X2_Bit;
-		break;
+		return GI_M_PRESCALE_X2;
 	case ni_gpct_variant_660x:
-		return Gi_660x_Prescale_X2_Bit;
-		break;
-	default:
-		BUG();
-		break;
+		return GI_660X_PRESCALE_X2;
 	}
-	return 0;
 }
 
-static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X8_Bit(enum
-								ni_gpct_variant
-								variant)
+static inline unsigned GI_PRESCALE_X8(enum ni_gpct_variant variant)
 {
 	switch (variant) {
 	case ni_gpct_variant_e_series:
+	default:
 		return 0;
-		break;
 	case ni_gpct_variant_m_series:
-		return Gi_M_Series_Prescale_X8_Bit;
-		break;
+		return GI_M_PRESCALE_X8;
 	case ni_gpct_variant_660x:
-		return Gi_660x_Prescale_X8_Bit;
-		break;
-	default:
-		BUG();
-		break;
+		return GI_660X_PRESCALE_X8;
 	}
-	return 0;
 }
 
-static inline enum Gi_Counting_Mode_Reg_Bits Gi_HW_Arm_Select_Mask(enum
-								   ni_gpct_variant
-								   variant)
+static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant)
 {
 	switch (variant) {
 	case ni_gpct_variant_e_series:
+	default:
 		return 0;
-		break;
 	case ni_gpct_variant_m_series:
-		return Gi_M_Series_HW_Arm_Select_Mask;
-		break;
+		return GI_M_HW_ARM_SEL_MASK;
 	case ni_gpct_variant_660x:
-		return Gi_660x_HW_Arm_Select_Mask;
-		break;
-	default:
-		BUG();
-		break;
+		return GI_660X_HW_ARM_SEL_MASK;
 	}
-	return 0;
-}
-
-/* clock sources for ni_660x boards, get bits with Gi_Source_Select_Bits() */
-enum ni_660x_clock_source {
-	NI_660x_Timebase_1_Clock = 0x0,	/* 20MHz */
-	NI_660x_Source_Pin_i_Clock = 0x1,
-	NI_660x_Next_Gate_Clock = 0xa,
-	NI_660x_Timebase_2_Clock = 0x12,	/* 100KHz */
-	NI_660x_Next_TC_Clock = 0x13,
-	NI_660x_Timebase_3_Clock = 0x1e,	/* 80MHz */
-	NI_660x_Logic_Low_Clock = 0x1f,
-};
-static const unsigned ni_660x_max_rtsi_channel = 6;
-static inline unsigned NI_660x_RTSI_Clock(unsigned n)
-{
-	BUG_ON(n > ni_660x_max_rtsi_channel);
-	return 0xb + n;
-}
-
-static const unsigned ni_660x_max_source_pin = 7;
-static inline unsigned NI_660x_Source_Pin_Clock(unsigned n)
-{
-	BUG_ON(n > ni_660x_max_source_pin);
-	return 0x2 + n;
-}
-
-/* clock sources for ni e and m series boards, get bits with Gi_Source_Select_Bits() */
-enum ni_m_series_clock_source {
-	NI_M_Series_Timebase_1_Clock = 0x0,	/* 20MHz */
-	NI_M_Series_Timebase_2_Clock = 0x12,	/* 100KHz */
-	NI_M_Series_Next_TC_Clock = 0x13,
-	NI_M_Series_Next_Gate_Clock = 0x14,	/* when Gi_Src_SubSelect = 0 */
-	NI_M_Series_PXI_Star_Trigger_Clock = 0x14,	/* when Gi_Src_SubSelect = 1 */
-	NI_M_Series_PXI10_Clock = 0x1d,
-	NI_M_Series_Timebase_3_Clock = 0x1e,	/* 80MHz, when Gi_Src_SubSelect = 0 */
-	NI_M_Series_Analog_Trigger_Out_Clock = 0x1e,	/* when Gi_Src_SubSelect = 1 */
-	NI_M_Series_Logic_Low_Clock = 0x1f,
-};
-static const unsigned ni_m_series_max_pfi_channel = 15;
-static inline unsigned NI_M_Series_PFI_Clock(unsigned n)
-{
-	BUG_ON(n > ni_m_series_max_pfi_channel);
-	if (n < 10)
-		return 1 + n;
-	else
-		return 0xb + n;
-}
-
-static const unsigned ni_m_series_max_rtsi_channel = 7;
-static inline unsigned NI_M_Series_RTSI_Clock(unsigned n)
-{
-	BUG_ON(n > ni_m_series_max_rtsi_channel);
-	if (n == 7)
-		return 0x1b;
-	else
-		return 0xb + n;
-}
-
-enum ni_660x_gate_select {
-	NI_660x_Source_Pin_i_Gate_Select = 0x0,
-	NI_660x_Gate_Pin_i_Gate_Select = 0x1,
-	NI_660x_Next_SRC_Gate_Select = 0xa,
-	NI_660x_Next_Out_Gate_Select = 0x14,
-	NI_660x_Logic_Low_Gate_Select = 0x1f,
-};
-static const unsigned ni_660x_max_gate_pin = 7;
-static inline unsigned NI_660x_Gate_Pin_Gate_Select(unsigned n)
-{
-	BUG_ON(n > ni_660x_max_gate_pin);
-	return 0x2 + n;
-}
-
-static inline unsigned NI_660x_RTSI_Gate_Select(unsigned n)
-{
-	BUG_ON(n > ni_660x_max_rtsi_channel);
-	return 0xb + n;
-}
-
-enum ni_m_series_gate_select {
-	NI_M_Series_Timestamp_Mux_Gate_Select = 0x0,
-	NI_M_Series_AI_START2_Gate_Select = 0x12,
-	NI_M_Series_PXI_Star_Trigger_Gate_Select = 0x13,
-	NI_M_Series_Next_Out_Gate_Select = 0x14,
-	NI_M_Series_AI_START1_Gate_Select = 0x1c,
-	NI_M_Series_Next_SRC_Gate_Select = 0x1d,
-	NI_M_Series_Analog_Trigger_Out_Gate_Select = 0x1e,
-	NI_M_Series_Logic_Low_Gate_Select = 0x1f,
-};
-static inline unsigned NI_M_Series_RTSI_Gate_Select(unsigned n)
-{
-	BUG_ON(n > ni_m_series_max_rtsi_channel);
-	if (n == 7)
-		return 0x1b;
-	return 0xb + n;
 }
 
-static inline unsigned NI_M_Series_PFI_Gate_Select(unsigned n)
-{
-	BUG_ON(n > ni_m_series_max_pfi_channel);
-	if (n < 10)
-		return 1 + n;
-	return 0xb + n;
-}
-
-static inline unsigned Gi_Source_Select_Bits(unsigned source)
-{
-	return (source << Gi_Source_Select_Shift) & Gi_Source_Select_Mask;
-}
-
-static inline unsigned Gi_Gate_Select_Bits(unsigned gate_select)
+static int ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev)
 {
-	return (gate_select << Gi_Gate_Select_Shift) & Gi_Gate_Select_Mask;
+	switch (counter_dev->variant) {
+	case ni_gpct_variant_e_series:
+	default:
+		return 0;
+	case ni_gpct_variant_m_series:
+	case ni_gpct_variant_660x:
+		return 1;
+	}
 }
 
-enum ni_660x_second_gate_select {
-	NI_660x_Source_Pin_i_Second_Gate_Select = 0x0,
-	NI_660x_Up_Down_Pin_i_Second_Gate_Select = 0x1,
-	NI_660x_Next_SRC_Second_Gate_Select = 0xa,
-	NI_660x_Next_Out_Second_Gate_Select = 0x14,
-	NI_660x_Selected_Gate_Second_Gate_Select = 0x1e,
-	NI_660x_Logic_Low_Second_Gate_Select = 0x1f,
-};
-static const unsigned ni_660x_max_up_down_pin = 7;
-static inline unsigned NI_660x_Up_Down_Pin_Second_Gate_Select(unsigned n)
+static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter)
 {
-	BUG_ON(n > ni_660x_max_up_down_pin);
-	return 0x2 + n;
-}
+	unsigned cidx = counter->counter_index;
 
-static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n)
-{
-	BUG_ON(n > ni_660x_max_rtsi_channel);
-	return 0xb + n;
+	write_register(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx));
 }
 
-static const unsigned int counter_status_mask =
-	COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING;
-
-struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device *dev,
-						void (*write_register) (struct
-									ni_gpct
-									*
-									counter,
-									unsigned
-									bits,
-									enum
-									ni_gpct_register
-									reg),
-						unsigned (*read_register)
-						(struct ni_gpct *counter,
-						 enum ni_gpct_register reg),
-						enum ni_gpct_variant variant,
-						unsigned num_counters)
+static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
+				       unsigned generic_clock_source)
 {
-	unsigned i;
+	uint64_t clock_period_ps;
 
-	struct ni_gpct_device *counter_dev =
-	    kzalloc(sizeof(struct ni_gpct_device), GFP_KERNEL);
-	if (counter_dev == NULL)
-		return NULL;
-	counter_dev->dev = dev;
-	counter_dev->write_register = write_register;
-	counter_dev->read_register = read_register;
-	counter_dev->variant = variant;
-	spin_lock_init(&counter_dev->regs_lock);
-	BUG_ON(num_counters == 0);
-	counter_dev->counters =
-	    kzalloc(sizeof(struct ni_gpct) * num_counters, GFP_KERNEL);
-	if (counter_dev->counters == NULL) {
-		kfree(counter_dev);
-		return NULL;
-	}
-	for (i = 0; i < num_counters; ++i) {
-		counter_dev->counters[i].counter_dev = counter_dev;
-		spin_lock_init(&counter_dev->counters[i].lock);
+	switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) {
+	case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS:
+		clock_period_ps = 50000;
+		break;
+	case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS:
+		clock_period_ps = 10000000;
+		break;
+	case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
+		clock_period_ps = 12500;
+		break;
+	case NI_GPCT_PXI10_CLOCK_SRC_BITS:
+		clock_period_ps = 100000;
+		break;
+	default:
+		/*
+		 * clock period is specified by user with prescaling
+		 * already taken into account.
+		 */
+		return counter->clock_period_ps;
 	}
-	counter_dev->num_counters = num_counters;
-	return counter_dev;
-}
-EXPORT_SYMBOL_GPL(ni_gpct_device_construct);
-
-void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev)
-{
-	if (counter_dev->counters == NULL)
-		return;
-	kfree(counter_dev->counters);
-	kfree(counter_dev);
-}
-EXPORT_SYMBOL_GPL(ni_gpct_device_destroy);
 
-static int ni_tio_second_gate_registers_present(const struct ni_gpct_device
-						*counter_dev)
-{
-	switch (counter_dev->variant) {
-	case ni_gpct_variant_e_series:
-		return 0;
+	switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) {
+	case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS:
 		break;
-	case ni_gpct_variant_m_series:
-	case ni_gpct_variant_660x:
-		return 1;
+	case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS:
+		clock_period_ps *= 2;
+		break;
+	case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS:
+		clock_period_ps *= 8;
 		break;
 	default:
 		BUG();
 		break;
 	}
-	return 0;
+	return clock_period_ps;
 }
 
-static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter)
+static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter)
 {
+	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
+	const unsigned counting_mode_bits =
+		ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx));
+	unsigned bits = 0;
 
-	write_register(counter, Gi_Reset_Bit(cidx), NITIO_RESET_REG(cidx));
+	if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) &
+	    GI_SRC_POL_INVERT)
+		bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT;
+	if (counting_mode_bits & GI_PRESCALE_X2(counter_dev->variant))
+		bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS;
+	if (counting_mode_bits & GI_PRESCALE_X8(counter_dev->variant))
+		bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS;
+	return bits;
 }
 
-void ni_tio_init_counter(struct ni_gpct *counter)
+static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter)
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
+	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
+	unsigned clock_source = 0;
+	unsigned src;
+	unsigned i;
 
-	ni_tio_reset_count_and_disarm(counter);
-
-	/* initialize counter registers */
-	counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0;
-	write_register(counter, counter_dev->regs[NITIO_AUTO_INC_REG(cidx)],
-		       NITIO_AUTO_INC_REG(cidx));
-
-	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
-			~0, Gi_Synchronize_Gate_Bit);
-
-	ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0);
-
-	counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0;
-	write_register(counter, counter_dev->regs[NITIO_LOADA_REG(cidx)],
-		       NITIO_LOADA_REG(cidx));
+	src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter,
+						  NITIO_INPUT_SEL_REG(cidx)));
 
-	counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0;
-	write_register(counter, counter_dev->regs[NITIO_LOADB_REG(cidx)],
-		       NITIO_LOADB_REG(cidx));
+	switch (src) {
+	case NI_M_TIMEBASE_1_CLK:
+		clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS;
+		break;
+	case NI_M_TIMEBASE_2_CLK:
+		clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS;
+		break;
+	case NI_M_TIMEBASE_3_CLK:
+		if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL)
+			clock_source =
+			    NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS;
+		else
+			clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS;
+		break;
+	case NI_M_LOGIC_LOW_CLK:
+		clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS;
+		break;
+	case NI_M_NEXT_GATE_CLK:
+		if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL)
+			clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS;
+		else
+			clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS;
+		break;
+	case NI_M_PXI10_CLK:
+		clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS;
+		break;
+	case NI_M_NEXT_TC_CLK:
+		clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS;
+		break;
+	default:
+		for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) {
+			if (src == NI_M_RTSI_CLK(i)) {
+				clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i);
+				break;
+			}
+		}
+		if (i <= NI_M_MAX_RTSI_CHAN)
+			break;
+		for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) {
+			if (src == NI_M_PFI_CLK(i)) {
+				clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i);
+				break;
+			}
+		}
+		if (i <= NI_M_MAX_PFI_CHAN)
+			break;
+		BUG();
+		break;
+	}
+	clock_source |= ni_tio_clock_src_modifiers(counter);
+	return clock_source;
+}
 
-	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0);
+static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter)
+{
+	unsigned clock_source = 0;
+	unsigned cidx = counter->counter_index;
+	unsigned src;
+	unsigned i;
 
-	if (ni_tio_counting_mode_registers_present(counter_dev))
-		ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0);
+	src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter,
+						  NITIO_INPUT_SEL_REG(cidx)));
 
-	if (ni_tio_second_gate_registers_present(counter_dev)) {
-		counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0;
-		write_register(counter,
-			       counter_dev->regs[NITIO_GATE2_REG(cidx)],
-			       NITIO_GATE2_REG(cidx));
+	switch (src) {
+	case NI_660X_TIMEBASE_1_CLK:
+		clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_TIMEBASE_2_CLK:
+		clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_TIMEBASE_3_CLK:
+		clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_LOGIC_LOW_CLK:
+		clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_SRC_PIN_I_CLK:
+		clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_NEXT_GATE_CLK:
+		clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS;
+		break;
+	case NI_660X_NEXT_TC_CLK:
+		clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS;
+		break;
+	default:
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (src == NI_660X_RTSI_CLK(i)) {
+				clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i);
+				break;
+			}
+		}
+		if (i <= NI_660X_MAX_RTSI_CHAN)
+			break;
+		for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) {
+			if (src == NI_660X_SRC_PIN_CLK(i)) {
+				clock_source =
+				    NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i);
+				break;
+			}
+		}
+		if (i <= NI_660X_MAX_SRC_PIN)
+			break;
+		BUG();
+		break;
 	}
-
-	ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0);
-
-	ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), ~0, 0x0);
+	clock_source |= ni_tio_clock_src_modifiers(counter);
+	return clock_source;
 }
-EXPORT_SYMBOL_GPL(ni_tio_init_counter);
 
-static unsigned int ni_tio_counter_status(struct ni_gpct *counter)
+static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter)
 {
-	unsigned cidx = counter->counter_index;
-	const unsigned bits = read_register(counter,
-					    NITIO_SHARED_STATUS_REG(cidx));
-	unsigned int status = 0;
-
-	if (bits & Gi_Armed_Bit(cidx)) {
-		status |= COMEDI_COUNTER_ARMED;
-		if (bits & Gi_Counting_Bit(cidx))
-			status |= COMEDI_COUNTER_COUNTING;
+	switch (counter->counter_dev->variant) {
+	case ni_gpct_variant_e_series:
+	case ni_gpct_variant_m_series:
+	default:
+		return ni_m_series_clock_src_select(counter);
+	case ni_gpct_variant_660x:
+		return ni_660x_clock_src_select(counter);
 	}
-	return status;
 }
 
 static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync)
@@ -414,34 +387,40 @@ static void ni_tio_set_sync_mode(struct
 	unsigned cidx = counter->counter_index;
 	const unsigned counting_mode_reg = NITIO_CNT_MODE_REG(cidx);
 	static const uint64_t min_normal_sync_period_ps = 25000;
-	const uint64_t clock_period_ps = ni_tio_clock_period_ps(counter,
-								ni_tio_generic_clock_src_select
-								(counter));
+	unsigned mode;
+	uint64_t clock_period_ps;
 
 	if (ni_tio_counting_mode_registers_present(counter_dev) == 0)
 		return;
 
-	switch (ni_tio_get_soft_copy(counter, counting_mode_reg) & Gi_Counting_Mode_Mask) {
-	case Gi_Counting_Mode_QuadratureX1_Bits:
-	case Gi_Counting_Mode_QuadratureX2_Bits:
-	case Gi_Counting_Mode_QuadratureX4_Bits:
-	case Gi_Counting_Mode_Sync_Source_Bits:
+	mode = ni_tio_get_soft_copy(counter, counting_mode_reg);
+	switch (mode & GI_CNT_MODE_MASK) {
+	case GI_CNT_MODE_QUADX1:
+	case GI_CNT_MODE_QUADX2:
+	case GI_CNT_MODE_QUADX4:
+	case GI_CNT_MODE_SYNC_SRC:
 		force_alt_sync = 1;
 		break;
 	default:
 		break;
 	}
-	/* It's not clear what we should do if clock_period is unknown, so we are not
-	   using the alt sync bit in that case, but allow the caller to decide by using the
-	   force_alt_sync parameter. */
+
+	clock_period_ps = ni_tio_clock_period_ps(counter,
+				ni_tio_generic_clock_src_select(counter));
+
+	/*
+	 * It's not clear what we should do if clock_period is unknown, so we
+	 * are not using the alt sync bit in that case, but allow the caller
+	 * to decide by using the force_alt_sync parameter.
+	 */
 	if (force_alt_sync ||
 	    (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) {
 		ni_tio_set_bits(counter, counting_mode_reg,
-				Gi_Alternate_Sync_Bit(counter_dev->variant),
-				Gi_Alternate_Sync_Bit(counter_dev->variant));
+				GI_ALT_SYNC(counter_dev->variant),
+				GI_ALT_SYNC(counter_dev->variant));
 	} else {
 		ni_tio_set_bits(counter, counting_mode_reg,
-				Gi_Alternate_Sync_Bit(counter_dev->variant),
+				GI_ALT_SYNC(counter_dev->variant),
 				0x0);
 	}
 }
@@ -460,18 +439,18 @@ static int ni_tio_set_counter_mode(struc
 	    NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT |
 	    NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT;
 
-	mode_reg_mask = mode_reg_direct_mask | Gi_Reload_Source_Switching_Bit;
+	mode_reg_mask = mode_reg_direct_mask | GI_RELOAD_SRC_SWITCHING;
 	mode_reg_values = mode & mode_reg_direct_mask;
 	switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) {
 	case NI_GPCT_RELOAD_SOURCE_FIXED_BITS:
 		break;
 	case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS:
-		mode_reg_values |= Gi_Reload_Source_Switching_Bit;
+		mode_reg_values |= GI_RELOAD_SRC_SWITCHING;
 		break;
 	case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS:
-		input_select_bits |= Gi_Gate_Select_Load_Source_Bit;
-		mode_reg_mask |= Gi_Gating_Mode_Mask;
-		mode_reg_values |= Gi_Level_Gating_Bits;
+		input_select_bits |= GI_GATE_SEL_LOAD_SRC;
+		mode_reg_mask |= GI_GATING_MODE_MASK;
+		mode_reg_values |= GI_LEVEL_GATING;
 		break;
 	default:
 		break;
@@ -480,33 +459,28 @@ static int ni_tio_set_counter_mode(struc
 			mode_reg_mask, mode_reg_values);
 
 	if (ni_tio_counting_mode_registers_present(counter_dev)) {
-		unsigned counting_mode_bits = 0;
-		counting_mode_bits |=
-		    (mode >> NI_GPCT_COUNTING_MODE_SHIFT) &
-		    Gi_Counting_Mode_Mask;
-		counting_mode_bits |=
-		    ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) <<
-		     Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask;
+		unsigned bits = 0;
+
+		bits |= GI_CNT_MODE(mode >> NI_GPCT_COUNTING_MODE_SHIFT);
+		bits |= GI_INDEX_PHASE((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT));
 		if (mode & NI_GPCT_INDEX_ENABLE_BIT)
-			counting_mode_bits |= Gi_Index_Mode_Bit;
+			bits |= GI_INDEX_MODE;
 		ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx),
-				Gi_Counting_Mode_Mask | Gi_Index_Phase_Mask |
-				Gi_Index_Mode_Bit, counting_mode_bits);
+				GI_CNT_MODE_MASK | GI_INDEX_PHASE_MASK |
+				GI_INDEX_MODE, bits);
 		ni_tio_set_sync_mode(counter, 0);
 	}
 
-	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
-			Gi_Up_Down_Mask,
-			(mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) <<
-			Gi_Up_Down_Shift);
+	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_CNT_DIR_MASK,
+			GI_CNT_DIR(mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT));
 
 	if (mode & NI_GPCT_OR_GATE_BIT)
-		input_select_bits |= Gi_Or_Gate_Bit;
+		input_select_bits |= GI_OR_GATE;
 	if (mode & NI_GPCT_INVERT_OUTPUT_BIT)
-		input_select_bits |= Gi_Output_Polarity_Bit;
+		input_select_bits |= GI_OUTPUT_POL_INVERT;
 	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
-			Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit |
-			Gi_Output_Polarity_Bit, input_select_bits);
+			GI_GATE_SEL_LOAD_SRC | GI_OR_GATE |
+			GI_OUTPUT_POL_INVERT, input_select_bits);
 
 	return 0;
 }
@@ -520,16 +494,19 @@ int ni_tio_arm(struct ni_gpct *counter,
 	if (arm) {
 		switch (start_trigger) {
 		case NI_GPCT_ARM_IMMEDIATE:
-			command_transient_bits |= Gi_Arm_Bit;
+			command_transient_bits |= GI_ARM;
 			break;
 		case NI_GPCT_ARM_PAIRED_IMMEDIATE:
-			command_transient_bits |= Gi_Arm_Bit | Gi_Arm_Copy_Bit;
+			command_transient_bits |= GI_ARM | GI_ARM_COPY;
 			break;
 		default:
 			break;
 		}
 		if (ni_tio_counting_mode_registers_present(counter_dev)) {
-			unsigned counting_mode_bits = 0;
+			unsigned bits = 0;
+			unsigned sel_mask;
+
+			sel_mask = GI_HW_ARM_SEL_MASK(counter_dev->variant);
 
 			switch (start_trigger) {
 			case NI_GPCT_ARM_IMMEDIATE:
@@ -537,29 +514,24 @@ int ni_tio_arm(struct ni_gpct *counter,
 				break;
 			default:
 				if (start_trigger & NI_GPCT_ARM_UNKNOWN) {
-					/* pass-through the least significant bits so we can figure out what select later */
-					unsigned hw_arm_select_bits =
-					    (start_trigger <<
-					     Gi_HW_Arm_Select_Shift) &
-					    Gi_HW_Arm_Select_Mask
-					    (counter_dev->variant);
-
-					counting_mode_bits |=
-					    Gi_HW_Arm_Enable_Bit |
-					    hw_arm_select_bits;
+					/*
+					 * pass-through the least significant
+					 * bits so we can figure out what
+					 * select later
+					 */
+					bits |= GI_HW_ARM_ENA |
+						(GI_HW_ARM_SEL(start_trigger) &
+						 sel_mask);
 				} else {
 					return -EINVAL;
 				}
 				break;
 			}
 			ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx),
-					Gi_HW_Arm_Select_Mask
-					(counter_dev->variant) |
-					Gi_HW_Arm_Enable_Bit,
-					counting_mode_bits);
+					GI_HW_ARM_ENA | sel_mask, bits);
 		}
 	} else {
-		command_transient_bits |= Gi_Disarm_Bit;
+		command_transient_bits |= GI_DISARM;
 	}
 	ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx),
 				  0, 0, command_transient_bits);
@@ -567,118 +539,116 @@ int ni_tio_arm(struct ni_gpct *counter,
 }
 EXPORT_SYMBOL_GPL(ni_tio_arm);
 
-static unsigned ni_660x_source_select_bits(unsigned int clock_source)
+static unsigned ni_660x_clk_src(unsigned int clock_source)
 {
+	unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK;
 	unsigned ni_660x_clock;
 	unsigned i;
-	const unsigned clock_select_bits =
-	    clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK;
 
-	switch (clock_select_bits) {
+	switch (clk_src) {
 	case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Timebase_1_Clock;
+		ni_660x_clock = NI_660X_TIMEBASE_1_CLK;
 		break;
 	case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Timebase_2_Clock;
+		ni_660x_clock = NI_660X_TIMEBASE_2_CLK;
 		break;
 	case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Timebase_3_Clock;
+		ni_660x_clock = NI_660X_TIMEBASE_3_CLK;
 		break;
 	case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Logic_Low_Clock;
+		ni_660x_clock = NI_660X_LOGIC_LOW_CLK;
 		break;
 	case NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Source_Pin_i_Clock;
+		ni_660x_clock = NI_660X_SRC_PIN_I_CLK;
 		break;
 	case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Next_Gate_Clock;
+		ni_660x_clock = NI_660X_NEXT_GATE_CLK;
 		break;
 	case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS:
-		ni_660x_clock = NI_660x_Next_TC_Clock;
+		ni_660x_clock = NI_660X_NEXT_TC_CLK;
 		break;
 	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) {
-				ni_660x_clock = NI_660x_RTSI_Clock(i);
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) {
+				ni_660x_clock = NI_660X_RTSI_CLK(i);
 				break;
 			}
 		}
-		if (i <= ni_660x_max_rtsi_channel)
+		if (i <= NI_660X_MAX_RTSI_CHAN)
 			break;
-		for (i = 0; i <= ni_660x_max_source_pin; ++i) {
-			if (clock_select_bits ==
-			    NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) {
-				ni_660x_clock = NI_660x_Source_Pin_Clock(i);
+		for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) {
+			if (clk_src == NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) {
+				ni_660x_clock = NI_660X_SRC_PIN_CLK(i);
 				break;
 			}
 		}
-		if (i <= ni_660x_max_source_pin)
+		if (i <= NI_660X_MAX_SRC_PIN)
 			break;
 		ni_660x_clock = 0;
 		BUG();
 		break;
 	}
-	return Gi_Source_Select_Bits(ni_660x_clock);
+	return GI_SRC_SEL(ni_660x_clock);
 }
 
-static unsigned ni_m_series_source_select_bits(unsigned int clock_source)
+static unsigned ni_m_clk_src(unsigned int clock_source)
 {
+	unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK;
 	unsigned ni_m_series_clock;
 	unsigned i;
-	const unsigned clock_select_bits =
-	    clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK;
-	switch (clock_select_bits) {
+
+	switch (clk_src) {
 	case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Timebase_1_Clock;
+		ni_m_series_clock = NI_M_TIMEBASE_1_CLK;
 		break;
 	case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Timebase_2_Clock;
+		ni_m_series_clock = NI_M_TIMEBASE_2_CLK;
 		break;
 	case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Timebase_3_Clock;
+		ni_m_series_clock = NI_M_TIMEBASE_3_CLK;
 		break;
 	case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Logic_Low_Clock;
+		ni_m_series_clock = NI_M_LOGIC_LOW_CLK;
 		break;
 	case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Next_Gate_Clock;
+		ni_m_series_clock = NI_M_NEXT_GATE_CLK;
 		break;
 	case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Next_TC_Clock;
+		ni_m_series_clock = NI_M_NEXT_TC_CLK;
 		break;
 	case NI_GPCT_PXI10_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_PXI10_Clock;
+		ni_m_series_clock = NI_M_PXI10_CLK;
 		break;
 	case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_PXI_Star_Trigger_Clock;
+		ni_m_series_clock = NI_M_PXI_STAR_TRIGGER_CLK;
 		break;
 	case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS:
-		ni_m_series_clock = NI_M_Series_Analog_Trigger_Out_Clock;
+		ni_m_series_clock = NI_M_ANALOG_TRIGGER_OUT_CLK;
 		break;
 	default:
-		for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) {
-			if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) {
-				ni_m_series_clock = NI_M_Series_RTSI_Clock(i);
+		for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) {
+			if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) {
+				ni_m_series_clock = NI_M_RTSI_CLK(i);
 				break;
 			}
 		}
-		if (i <= ni_m_series_max_rtsi_channel)
+		if (i <= NI_M_MAX_RTSI_CHAN)
 			break;
-		for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) {
-			if (clock_select_bits == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) {
-				ni_m_series_clock = NI_M_Series_PFI_Clock(i);
+		for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) {
+			if (clk_src == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) {
+				ni_m_series_clock = NI_M_PFI_CLK(i);
 				break;
 			}
 		}
-		if (i <= ni_m_series_max_pfi_channel)
+		if (i <= NI_M_MAX_PFI_CHAN)
 			break;
-		printk(KERN_ERR "invalid clock source 0x%lx\n",
+		pr_err("invalid clock source 0x%lx\n",
 		       (unsigned long)clock_source);
 		BUG();
 		ni_m_series_clock = 0;
 		break;
 	}
-	return Gi_Source_Select_Bits(ni_m_series_clock);
+	return GI_SRC_SEL(ni_m_series_clock);
 };
 
 static void ni_tio_set_source_subselect(struct ni_gpct *counter,
@@ -694,17 +664,16 @@ static void ni_tio_set_source_subselect(
 		/* Gi_Source_Subselect is zero */
 	case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS:
 	case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
-		counter_dev->regs[second_gate_reg] &= ~Gi_Source_Subselect_Bit;
+		counter_dev->regs[second_gate_reg] &= ~GI_SRC_SUBSEL;
 		break;
 		/* Gi_Source_Subselect is one */
 	case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS:
 	case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS:
-		counter_dev->regs[second_gate_reg] |= Gi_Source_Subselect_Bit;
+		counter_dev->regs[second_gate_reg] |= GI_SRC_SUBSEL;
 		break;
 		/* Gi_Source_Subselect doesn't matter */
 	default:
 		return;
-		break;
 	}
 	write_register(counter, counter_dev->regs[second_gate_reg],
 		       second_gate_reg);
@@ -716,344 +685,109 @@ static int ni_tio_set_clock_src(struct n
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	unsigned input_select_bits = 0;
-	static const uint64_t pico_per_nano = 1000;
+	unsigned bits = 0;
 
-/*FIXME: validate clock source */
+	/* FIXME: validate clock source */
 	switch (counter_dev->variant) {
 	case ni_gpct_variant_660x:
-		input_select_bits |= ni_660x_source_select_bits(clock_source);
+		bits |= ni_660x_clk_src(clock_source);
 		break;
 	case ni_gpct_variant_e_series:
 	case ni_gpct_variant_m_series:
-		input_select_bits |=
-		    ni_m_series_source_select_bits(clock_source);
-		break;
 	default:
-		BUG();
+		bits |= ni_m_clk_src(clock_source);
 		break;
 	}
 	if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT)
-		input_select_bits |= Gi_Source_Polarity_Bit;
+		bits |= GI_SRC_POL_INVERT;
 	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
-			Gi_Source_Select_Mask | Gi_Source_Polarity_Bit,
-			input_select_bits);
+			GI_SRC_SEL_MASK | GI_SRC_POL_INVERT, bits);
 	ni_tio_set_source_subselect(counter, clock_source);
-	if (ni_tio_counting_mode_registers_present(counter_dev)) {
-		const unsigned prescaling_mode =
-		    clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK;
-		unsigned counting_mode_bits = 0;
 
-		switch (prescaling_mode) {
+	if (ni_tio_counting_mode_registers_present(counter_dev)) {
+		bits = 0;
+		switch (clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) {
 		case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS:
 			break;
 		case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS:
-			counting_mode_bits |=
-			    Gi_Prescale_X2_Bit(counter_dev->variant);
+			bits |= GI_PRESCALE_X2(counter_dev->variant);
 			break;
 		case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS:
-			counting_mode_bits |=
-			    Gi_Prescale_X8_Bit(counter_dev->variant);
+			bits |= GI_PRESCALE_X8(counter_dev->variant);
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx),
-				Gi_Prescale_X2_Bit(counter_dev->variant) |
-				Gi_Prescale_X8_Bit(counter_dev->variant),
-				counting_mode_bits);
+				GI_PRESCALE_X2(counter_dev->variant) |
+				GI_PRESCALE_X8(counter_dev->variant), bits);
 	}
-	counter->clock_period_ps = pico_per_nano * period_ns;
+	counter->clock_period_ps = period_ns * 1000;
 	ni_tio_set_sync_mode(counter, 0);
 	return 0;
 }
 
-static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter)
-{
-	struct ni_gpct_device *counter_dev = counter->counter_dev;
-	unsigned cidx = counter->counter_index;
-	const unsigned counting_mode_bits =
-		ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx));
-	unsigned bits = 0;
-
-	if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) &
-	    Gi_Source_Polarity_Bit)
-		bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT;
-	if (counting_mode_bits & Gi_Prescale_X2_Bit(counter_dev->variant))
-		bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS;
-	if (counting_mode_bits & Gi_Prescale_X8_Bit(counter_dev->variant))
-		bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS;
-	return bits;
-}
-
-static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter)
-{
-	struct ni_gpct_device *counter_dev = counter->counter_dev;
-	unsigned cidx = counter->counter_index;
-	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
-	unsigned clock_source = 0;
-	unsigned i;
-	const unsigned input_select =
-		(ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) &
-			Gi_Source_Select_Mask) >> Gi_Source_Select_Shift;
-
-	switch (input_select) {
-	case NI_M_Series_Timebase_1_Clock:
-		clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_Timebase_2_Clock:
-		clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_Timebase_3_Clock:
-		if (counter_dev->regs[second_gate_reg] &
-		    Gi_Source_Subselect_Bit)
-			clock_source =
-			    NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS;
-		else
-			clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_Logic_Low_Clock:
-		clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_Next_Gate_Clock:
-		if (counter_dev->regs[second_gate_reg] &
-		    Gi_Source_Subselect_Bit)
-			clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS;
-		else
-			clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_PXI10_Clock:
-		clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS;
-		break;
-	case NI_M_Series_Next_TC_Clock:
-		clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS;
-		break;
-	default:
-		for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) {
-			if (input_select == NI_M_Series_RTSI_Clock(i)) {
-				clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i);
-				break;
-			}
-		}
-		if (i <= ni_m_series_max_rtsi_channel)
-			break;
-		for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) {
-			if (input_select == NI_M_Series_PFI_Clock(i)) {
-				clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i);
-				break;
-			}
-		}
-		if (i <= ni_m_series_max_pfi_channel)
-			break;
-		BUG();
-		break;
-	}
-	clock_source |= ni_tio_clock_src_modifiers(counter);
-	return clock_source;
-}
-
-static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter)
-{
-	unsigned clock_source = 0;
-	unsigned cidx = counter->counter_index;
-	const unsigned input_select =
-		(ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) &
-			Gi_Source_Select_Mask) >> Gi_Source_Select_Shift;
-	unsigned i;
-
-	switch (input_select) {
-	case NI_660x_Timebase_1_Clock:
-		clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Timebase_2_Clock:
-		clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Timebase_3_Clock:
-		clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Logic_Low_Clock:
-		clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Source_Pin_i_Clock:
-		clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Next_Gate_Clock:
-		clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS;
-		break;
-	case NI_660x_Next_TC_Clock:
-		clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS;
-		break;
-	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (input_select == NI_660x_RTSI_Clock(i)) {
-				clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i);
-				break;
-			}
-		}
-		if (i <= ni_660x_max_rtsi_channel)
-			break;
-		for (i = 0; i <= ni_660x_max_source_pin; ++i) {
-			if (input_select == NI_660x_Source_Pin_Clock(i)) {
-				clock_source =
-				    NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i);
-				break;
-			}
-		}
-		if (i <= ni_660x_max_source_pin)
-			break;
-		BUG();
-		break;
-	}
-	clock_source |= ni_tio_clock_src_modifiers(counter);
-	return clock_source;
-}
-
-static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter)
-{
-	switch (counter->counter_dev->variant) {
-	case ni_gpct_variant_e_series:
-	case ni_gpct_variant_m_series:
-		return ni_m_series_clock_src_select(counter);
-		break;
-	case ni_gpct_variant_660x:
-		return ni_660x_clock_src_select(counter);
-		break;
-	default:
-		BUG();
-		break;
-	}
-	return 0;
-}
-
-static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
-				       unsigned generic_clock_source)
-{
-	uint64_t clock_period_ps;
-
-	switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) {
-	case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS:
-		clock_period_ps = 50000;
-		break;
-	case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS:
-		clock_period_ps = 10000000;
-		break;
-	case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS:
-		clock_period_ps = 12500;
-		break;
-	case NI_GPCT_PXI10_CLOCK_SRC_BITS:
-		clock_period_ps = 100000;
-		break;
-	default:
-		/* clock period is specified by user with prescaling already taken into account. */
-		return counter->clock_period_ps;
-		break;
-	}
-
-	switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) {
-	case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS:
-		break;
-	case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS:
-		clock_period_ps *= 2;
-		break;
-	case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS:
-		clock_period_ps *= 8;
-		break;
-	default:
-		BUG();
-		break;
-	}
-	return clock_period_ps;
-}
-
 static void ni_tio_get_clock_src(struct ni_gpct *counter,
 				 unsigned int *clock_source,
 				 unsigned int *period_ns)
 {
-	static const unsigned pico_per_nano = 1000;
 	uint64_t temp64;
+
 	*clock_source = ni_tio_generic_clock_src_select(counter);
 	temp64 = ni_tio_clock_period_ps(counter, *clock_source);
-	do_div(temp64, pico_per_nano);
+	do_div(temp64, 1000);	/* ps to ns */
 	*period_ns = temp64;
 }
 
-static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter,
-					    unsigned int gate_source)
-{
-	const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask;
-	unsigned cidx = counter->counter_index;
-	unsigned mode_values = 0;
-
-	if (gate_source & CR_INVERT)
-		mode_values |= Gi_Gate_Polarity_Bit;
-	if (gate_source & CR_EDGE)
-		mode_values |= Gi_Rising_Edge_Gating_Bits;
-	else
-		mode_values |= Gi_Level_Gating_Bits;
-	ni_tio_set_bits(counter, NITIO_MODE_REG(cidx),
-			mode_mask, mode_values);
-}
-
-static int ni_660x_set_first_gate(struct ni_gpct *counter,
-				  unsigned int gate_source)
+static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source)
 {
-	const unsigned selected_gate = CR_CHAN(gate_source);
+	unsigned int chan = CR_CHAN(gate_source);
 	unsigned cidx = counter->counter_index;
-	/* bits of selected_gate that may be meaningful to input select register */
-	const unsigned selected_gate_mask = 0x1f;
-	unsigned ni_660x_gate_select;
+	unsigned gate_sel;
 	unsigned i;
 
-	switch (selected_gate) {
+	switch (chan) {
 	case NI_GPCT_NEXT_SOURCE_GATE_SELECT:
-		ni_660x_gate_select = NI_660x_Next_SRC_Gate_Select;
+		gate_sel = NI_660X_NEXT_SRC_GATE_SEL;
 		break;
 	case NI_GPCT_NEXT_OUT_GATE_SELECT:
 	case NI_GPCT_LOGIC_LOW_GATE_SELECT:
 	case NI_GPCT_SOURCE_PIN_i_GATE_SELECT:
 	case NI_GPCT_GATE_PIN_i_GATE_SELECT:
-		ni_660x_gate_select = selected_gate & selected_gate_mask;
+		gate_sel = chan & 0x1f;
 		break;
 	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) {
-				ni_660x_gate_select =
-				    selected_gate & selected_gate_mask;
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) {
+				gate_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_660x_max_rtsi_channel)
+		if (i <= NI_660X_MAX_RTSI_CHAN)
 			break;
-		for (i = 0; i <= ni_660x_max_gate_pin; ++i) {
-			if (selected_gate == NI_GPCT_GATE_PIN_GATE_SELECT(i)) {
-				ni_660x_gate_select =
-				    selected_gate & selected_gate_mask;
+		for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) {
+			if (chan == NI_GPCT_GATE_PIN_GATE_SELECT(i)) {
+				gate_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_660x_max_gate_pin)
+		if (i <= NI_660X_MAX_GATE_PIN)
 			break;
 		return -EINVAL;
-		break;
 	}
 	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
-			Gi_Gate_Select_Mask,
-			Gi_Gate_Select_Bits(ni_660x_gate_select));
+			GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel));
 	return 0;
 }
 
-static int ni_m_series_set_first_gate(struct ni_gpct *counter,
-				      unsigned int gate_source)
+static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source)
 {
-	const unsigned selected_gate = CR_CHAN(gate_source);
+	unsigned int chan = CR_CHAN(gate_source);
 	unsigned cidx = counter->counter_index;
-	/* bits of selected_gate that may be meaningful to input select register */
-	const unsigned selected_gate_mask = 0x1f;
-	unsigned ni_m_series_gate_select;
+	unsigned gate_sel;
 	unsigned i;
 
-	switch (selected_gate) {
+	switch (chan) {
 	case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT:
 	case NI_GPCT_AI_START2_GATE_SELECT:
 	case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT:
@@ -1062,120 +796,99 @@ static int ni_m_series_set_first_gate(st
 	case NI_GPCT_NEXT_SOURCE_GATE_SELECT:
 	case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT:
 	case NI_GPCT_LOGIC_LOW_GATE_SELECT:
-		ni_m_series_gate_select = selected_gate & selected_gate_mask;
+		gate_sel = chan & 0x1f;
 		break;
 	default:
-		for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) {
-			if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) {
-				ni_m_series_gate_select =
-				    selected_gate & selected_gate_mask;
+		for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) {
+			if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) {
+				gate_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_m_series_max_rtsi_channel)
+		if (i <= NI_M_MAX_RTSI_CHAN)
 			break;
-		for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) {
-			if (selected_gate == NI_GPCT_PFI_GATE_SELECT(i)) {
-				ni_m_series_gate_select =
-				    selected_gate & selected_gate_mask;
+		for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) {
+			if (chan == NI_GPCT_PFI_GATE_SELECT(i)) {
+				gate_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_m_series_max_pfi_channel)
+		if (i <= NI_M_MAX_PFI_CHAN)
 			break;
 		return -EINVAL;
-		break;
 	}
 	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
-			Gi_Gate_Select_Mask,
-			Gi_Gate_Select_Bits(ni_m_series_gate_select));
+			GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel));
 	return 0;
 }
 
-static int ni_660x_set_second_gate(struct ni_gpct *counter,
-				   unsigned int gate_source)
+static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source)
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
-	const unsigned selected_second_gate = CR_CHAN(gate_source);
-	/* bits of second_gate that may be meaningful to second gate register */
-	static const unsigned selected_second_gate_mask = 0x1f;
-	unsigned ni_660x_second_gate_select;
+	unsigned int chan = CR_CHAN(gate_source);
+	unsigned gate2_reg = NITIO_GATE2_REG(cidx);
+	unsigned gate2_sel;
 	unsigned i;
 
-	switch (selected_second_gate) {
+	switch (chan) {
 	case NI_GPCT_SOURCE_PIN_i_GATE_SELECT:
 	case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT:
 	case NI_GPCT_SELECTED_GATE_GATE_SELECT:
 	case NI_GPCT_NEXT_OUT_GATE_SELECT:
 	case NI_GPCT_LOGIC_LOW_GATE_SELECT:
-		ni_660x_second_gate_select =
-		    selected_second_gate & selected_second_gate_mask;
+		gate2_sel = chan & 0x1f;
 		break;
 	case NI_GPCT_NEXT_SOURCE_GATE_SELECT:
-		ni_660x_second_gate_select =
-		    NI_660x_Next_SRC_Second_Gate_Select;
+		gate2_sel = NI_660X_NEXT_SRC_GATE2_SEL;
 		break;
 	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (selected_second_gate == NI_GPCT_RTSI_GATE_SELECT(i)) {
-				ni_660x_second_gate_select =
-				    selected_second_gate &
-				    selected_second_gate_mask;
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) {
+				gate2_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_660x_max_rtsi_channel)
+		if (i <= NI_660X_MAX_RTSI_CHAN)
 			break;
-		for (i = 0; i <= ni_660x_max_up_down_pin; ++i) {
-			if (selected_second_gate ==
-			    NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) {
-				ni_660x_second_gate_select =
-				    selected_second_gate &
-				    selected_second_gate_mask;
+		for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) {
+			if (chan == NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) {
+				gate2_sel = chan & 0x1f;
 				break;
 			}
 		}
-		if (i <= ni_660x_max_up_down_pin)
+		if (i <= NI_660X_MAX_UP_DOWN_PIN)
 			break;
 		return -EINVAL;
-		break;
 	}
-	counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit;
-	counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask;
-	counter_dev->regs[second_gate_reg] |=
-	    Gi_Second_Gate_Select_Bits(ni_660x_second_gate_select);
-	write_register(counter, counter_dev->regs[second_gate_reg],
-		       second_gate_reg);
+	counter_dev->regs[gate2_reg] |= GI_GATE2_MODE;
+	counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK;
+	counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel);
+	write_register(counter, counter_dev->regs[gate2_reg], gate2_reg);
 	return 0;
 }
 
-static int ni_m_series_set_second_gate(struct ni_gpct *counter,
-				       unsigned int gate_source)
+static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source)
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
-	const unsigned selected_second_gate = CR_CHAN(gate_source);
-	/* bits of second_gate that may be meaningful to second gate register */
-	static const unsigned selected_second_gate_mask = 0x1f;
-	unsigned ni_m_series_second_gate_select;
+	unsigned int chan = CR_CHAN(gate_source);
+	unsigned gate2_reg = NITIO_GATE2_REG(cidx);
+	unsigned gate2_sel;
 
-	/* FIXME: We don't know what the m-series second gate codes are, so we'll just pass
-	   the bits through for now. */
-	switch (selected_second_gate) {
+	/*
+	 * FIXME: We don't know what the m-series second gate codes are,
+	 * so we'll just pass the bits through for now.
+	 */
+	switch (chan) {
 	default:
-		ni_m_series_second_gate_select =
-		    selected_second_gate & selected_second_gate_mask;
+		gate2_sel = chan & 0x1f;
 		break;
 	}
-	counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit;
-	counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask;
-	counter_dev->regs[second_gate_reg] |=
-	    Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select);
-	write_register(counter, counter_dev->regs[second_gate_reg],
-		       second_gate_reg);
+	counter_dev->regs[gate2_reg] |= GI_GATE2_MODE;
+	counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK;
+	counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel);
+	write_register(counter, counter_dev->regs[gate2_reg], gate2_reg);
 	return 0;
 }
 
@@ -1184,56 +897,55 @@ int ni_tio_set_gate_src(struct ni_gpct *
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
+	unsigned int chan = CR_CHAN(gate_source);
+	unsigned gate2_reg = NITIO_GATE2_REG(cidx);
+	unsigned mode = 0;
 
 	switch (gate_index) {
 	case 0:
-		if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) {
+		if (chan == NI_GPCT_DISABLED_GATE_SELECT) {
 			ni_tio_set_bits(counter, NITIO_MODE_REG(cidx),
-					Gi_Gating_Mode_Mask,
-					Gi_Gating_Disabled_Bits);
+					GI_GATING_MODE_MASK,
+					GI_GATING_DISABLED);
 			return 0;
 		}
-		ni_tio_set_first_gate_modifiers(counter, gate_source);
+		if (gate_source & CR_INVERT)
+			mode |= GI_GATE_POL_INVERT;
+		if (gate_source & CR_EDGE)
+			mode |= GI_RISING_EDGE_GATING;
+		else
+			mode |= GI_LEVEL_GATING;
+		ni_tio_set_bits(counter, NITIO_MODE_REG(cidx),
+				GI_GATE_POL_INVERT | GI_GATING_MODE_MASK,
+				mode);
 		switch (counter_dev->variant) {
 		case ni_gpct_variant_e_series:
 		case ni_gpct_variant_m_series:
-			return ni_m_series_set_first_gate(counter, gate_source);
-			break;
-		case ni_gpct_variant_660x:
-			return ni_660x_set_first_gate(counter, gate_source);
-			break;
 		default:
-			BUG();
-			break;
+			return ni_m_set_gate(counter, gate_source);
+		case ni_gpct_variant_660x:
+			return ni_660x_set_gate(counter, gate_source);
 		}
 		break;
 	case 1:
-		if (ni_tio_second_gate_registers_present(counter_dev) == 0)
+		if (!ni_tio_has_gate2_registers(counter_dev))
 			return -EINVAL;
-		if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) {
-			counter_dev->regs[second_gate_reg] &=
-			    ~Gi_Second_Gate_Mode_Bit;
-			write_register(counter,
-				       counter_dev->regs[second_gate_reg],
-				       second_gate_reg);
+
+		if (chan == NI_GPCT_DISABLED_GATE_SELECT) {
+			counter_dev->regs[gate2_reg] &= ~GI_GATE2_MODE;
+			write_register(counter, counter_dev->regs[gate2_reg],
+				       gate2_reg);
 			return 0;
 		}
-		if (gate_source & CR_INVERT) {
-			counter_dev->regs[second_gate_reg] |=
-			    Gi_Second_Gate_Polarity_Bit;
-		} else {
-			counter_dev->regs[second_gate_reg] &=
-			    ~Gi_Second_Gate_Polarity_Bit;
-		}
+		if (gate_source & CR_INVERT)
+			counter_dev->regs[gate2_reg] |= GI_GATE2_POL_INVERT;
+		else
+			counter_dev->regs[gate2_reg] &= ~GI_GATE2_POL_INVERT;
 		switch (counter_dev->variant) {
 		case ni_gpct_variant_m_series:
-			return ni_m_series_set_second_gate(counter,
-							   gate_source);
-			break;
+			return ni_m_set_gate2(counter, gate_source);
 		case ni_gpct_variant_660x:
-			return ni_660x_set_second_gate(counter, gate_source);
-			break;
+			return ni_660x_set_gate2(counter, gate_source);
 		default:
 			BUG();
 			break;
@@ -1241,7 +953,6 @@ int ni_tio_set_gate_src(struct ni_gpct *
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 0;
 }
@@ -1252,196 +963,142 @@ static int ni_tio_set_other_src(struct n
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
+	unsigned int abz_reg, shift, mask;
 
-	if (counter_dev->variant == ni_gpct_variant_m_series) {
-		unsigned int abz_reg, shift, mask;
+	if (counter_dev->variant != ni_gpct_variant_m_series)
+		return -EINVAL;
 
-		abz_reg = NITIO_ABZ_REG(cidx);
-		switch (index) {
-		case NI_GPCT_SOURCE_ENCODER_A:
-			shift = 10;
-			break;
-		case NI_GPCT_SOURCE_ENCODER_B:
-			shift = 5;
-			break;
-		case NI_GPCT_SOURCE_ENCODER_Z:
-			shift = 0;
-			break;
-		default:
-			return -EINVAL;
-			break;
-		}
-		mask = 0x1f << shift;
-		if (source > 0x1f) {
-			/* Disable gate */
-			source = 0x1f;
-		}
-		counter_dev->regs[abz_reg] &= ~mask;
-		counter_dev->regs[abz_reg] |= (source << shift) & mask;
-		write_register(counter, counter_dev->regs[abz_reg], abz_reg);
-		return 0;
+	abz_reg = NITIO_ABZ_REG(cidx);
+	switch (index) {
+	case NI_GPCT_SOURCE_ENCODER_A:
+		shift = 10;
+		break;
+	case NI_GPCT_SOURCE_ENCODER_B:
+		shift = 5;
+		break;
+	case NI_GPCT_SOURCE_ENCODER_Z:
+		shift = 0;
+		break;
+	default:
+		return -EINVAL;
 	}
-	return -EINVAL;
+	mask = 0x1f << shift;
+	if (source > 0x1f)
+		source = 0x1f;	/* Disable gate */
+
+	counter_dev->regs[abz_reg] &= ~mask;
+	counter_dev->regs[abz_reg] |= (source << shift) & mask;
+	write_register(counter, counter_dev->regs[abz_reg], abz_reg);
+	return 0;
 }
 
-static unsigned ni_660x_first_gate_to_generic_gate_source(unsigned
-							  ni_660x_gate_select)
+static unsigned ni_660x_gate_to_generic_gate(unsigned gate)
 {
 	unsigned i;
 
-	switch (ni_660x_gate_select) {
-	case NI_660x_Source_Pin_i_Gate_Select:
+	switch (gate) {
+	case NI_660X_SRC_PIN_I_GATE_SEL:
 		return NI_GPCT_SOURCE_PIN_i_GATE_SELECT;
-		break;
-	case NI_660x_Gate_Pin_i_Gate_Select:
+	case NI_660X_GATE_PIN_I_GATE_SEL:
 		return NI_GPCT_GATE_PIN_i_GATE_SELECT;
-		break;
-	case NI_660x_Next_SRC_Gate_Select:
+	case NI_660X_NEXT_SRC_GATE_SEL:
 		return NI_GPCT_NEXT_SOURCE_GATE_SELECT;
-		break;
-	case NI_660x_Next_Out_Gate_Select:
+	case NI_660X_NEXT_OUT_GATE_SEL:
 		return NI_GPCT_NEXT_OUT_GATE_SELECT;
-		break;
-	case NI_660x_Logic_Low_Gate_Select:
+	case NI_660X_LOGIC_LOW_GATE_SEL:
 		return NI_GPCT_LOGIC_LOW_GATE_SELECT;
-		break;
 	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (ni_660x_gate_select == NI_660x_RTSI_Gate_Select(i)) {
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (gate == NI_660X_RTSI_GATE_SEL(i))
 				return NI_GPCT_RTSI_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_660x_max_rtsi_channel)
-			break;
-		for (i = 0; i <= ni_660x_max_gate_pin; ++i) {
-			if (ni_660x_gate_select ==
-			    NI_660x_Gate_Pin_Gate_Select(i)) {
+		for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) {
+			if (gate == NI_660X_PIN_GATE_SEL(i))
 				return NI_GPCT_GATE_PIN_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_660x_max_gate_pin)
-			break;
 		BUG();
 		break;
 	}
 	return 0;
 };
 
-static unsigned ni_m_series_first_gate_to_generic_gate_source(unsigned
-							      ni_m_series_gate_select)
+static unsigned ni_m_gate_to_generic_gate(unsigned gate)
 {
 	unsigned i;
 
-	switch (ni_m_series_gate_select) {
-	case NI_M_Series_Timestamp_Mux_Gate_Select:
+	switch (gate) {
+	case NI_M_TIMESTAMP_MUX_GATE_SEL:
 		return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT;
-		break;
-	case NI_M_Series_AI_START2_Gate_Select:
+	case NI_M_AI_START2_GATE_SEL:
 		return NI_GPCT_AI_START2_GATE_SELECT;
-		break;
-	case NI_M_Series_PXI_Star_Trigger_Gate_Select:
+	case NI_M_PXI_STAR_TRIGGER_GATE_SEL:
 		return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT;
-		break;
-	case NI_M_Series_Next_Out_Gate_Select:
+	case NI_M_NEXT_OUT_GATE_SEL:
 		return NI_GPCT_NEXT_OUT_GATE_SELECT;
-		break;
-	case NI_M_Series_AI_START1_Gate_Select:
+	case NI_M_AI_START1_GATE_SEL:
 		return NI_GPCT_AI_START1_GATE_SELECT;
-		break;
-	case NI_M_Series_Next_SRC_Gate_Select:
+	case NI_M_NEXT_SRC_GATE_SEL:
 		return NI_GPCT_NEXT_SOURCE_GATE_SELECT;
-		break;
-	case NI_M_Series_Analog_Trigger_Out_Gate_Select:
+	case NI_M_ANALOG_TRIG_OUT_GATE_SEL:
 		return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT;
-		break;
-	case NI_M_Series_Logic_Low_Gate_Select:
+	case NI_M_LOGIC_LOW_GATE_SEL:
 		return NI_GPCT_LOGIC_LOW_GATE_SELECT;
-		break;
 	default:
-		for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) {
-			if (ni_m_series_gate_select ==
-			    NI_M_Series_RTSI_Gate_Select(i)) {
+		for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) {
+			if (gate == NI_M_RTSI_GATE_SEL(i))
 				return NI_GPCT_RTSI_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_m_series_max_rtsi_channel)
-			break;
-		for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) {
-			if (ni_m_series_gate_select ==
-			    NI_M_Series_PFI_Gate_Select(i)) {
+		for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) {
+			if (gate == NI_M_PFI_GATE_SEL(i))
 				return NI_GPCT_PFI_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_m_series_max_pfi_channel)
-			break;
 		BUG();
 		break;
 	}
 	return 0;
 };
 
-static unsigned ni_660x_second_gate_to_generic_gate_source(unsigned
-							   ni_660x_gate_select)
+static unsigned ni_660x_gate2_to_generic_gate(unsigned gate)
 {
 	unsigned i;
 
-	switch (ni_660x_gate_select) {
-	case NI_660x_Source_Pin_i_Second_Gate_Select:
+	switch (gate) {
+	case NI_660X_SRC_PIN_I_GATE2_SEL:
 		return NI_GPCT_SOURCE_PIN_i_GATE_SELECT;
-		break;
-	case NI_660x_Up_Down_Pin_i_Second_Gate_Select:
+	case NI_660X_UD_PIN_I_GATE2_SEL:
 		return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT;
-		break;
-	case NI_660x_Next_SRC_Second_Gate_Select:
+	case NI_660X_NEXT_SRC_GATE2_SEL:
 		return NI_GPCT_NEXT_SOURCE_GATE_SELECT;
-		break;
-	case NI_660x_Next_Out_Second_Gate_Select:
+	case NI_660X_NEXT_OUT_GATE2_SEL:
 		return NI_GPCT_NEXT_OUT_GATE_SELECT;
-		break;
-	case NI_660x_Selected_Gate_Second_Gate_Select:
+	case NI_660X_SELECTED_GATE2_SEL:
 		return NI_GPCT_SELECTED_GATE_GATE_SELECT;
-		break;
-	case NI_660x_Logic_Low_Second_Gate_Select:
+	case NI_660X_LOGIC_LOW_GATE2_SEL:
 		return NI_GPCT_LOGIC_LOW_GATE_SELECT;
-		break;
 	default:
-		for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) {
-			if (ni_660x_gate_select ==
-			    NI_660x_RTSI_Second_Gate_Select(i)) {
+		for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) {
+			if (gate == NI_660X_RTSI_GATE2_SEL(i))
 				return NI_GPCT_RTSI_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_660x_max_rtsi_channel)
-			break;
-		for (i = 0; i <= ni_660x_max_up_down_pin; ++i) {
-			if (ni_660x_gate_select ==
-			    NI_660x_Up_Down_Pin_Second_Gate_Select(i)) {
+		for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) {
+			if (gate == NI_660X_UD_PIN_GATE2_SEL(i))
 				return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i);
-				break;
-			}
 		}
-		if (i <= ni_660x_max_up_down_pin)
-			break;
 		BUG();
 		break;
 	}
 	return 0;
 };
 
-static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned
-							       ni_m_series_gate_select)
+static unsigned ni_m_gate2_to_generic_gate(unsigned gate)
 {
-	/*FIXME: the second gate sources for the m series are undocumented, so we just return
-	 * the raw bits for now. */
-	switch (ni_m_series_gate_select) {
+	/*
+	 * FIXME: the second gate sources for the m series are undocumented,
+	 * so we just return the raw bits for now.
+	 */
+	switch (gate) {
 	default:
-		return ni_m_series_gate_select;
-		break;
+		return gate;
 	}
 	return 0;
 };
@@ -1451,84 +1108,62 @@ static int ni_tio_get_gate_src(struct ni
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	const unsigned mode_bits =
-		ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx));
-	const unsigned second_gate_reg = NITIO_GATE2_REG(cidx);
-	unsigned gate_select_bits;
+	unsigned mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx));
+	unsigned gate2_reg = NITIO_GATE2_REG(cidx);
+	unsigned gate;
 
 	switch (gate_index) {
 	case 0:
-		if ((mode_bits & Gi_Gating_Mode_Mask) ==
-		    Gi_Gating_Disabled_Bits) {
+		if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) {
 			*gate_source = NI_GPCT_DISABLED_GATE_SELECT;
 			return 0;
-		} else {
-			gate_select_bits =
-			    (ni_tio_get_soft_copy(counter,
-						  NITIO_INPUT_SEL_REG(cidx)) &
-			     Gi_Gate_Select_Mask) >> Gi_Gate_Select_Shift;
 		}
+
+		gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter,
+						NITIO_INPUT_SEL_REG(cidx)));
+
 		switch (counter_dev->variant) {
 		case ni_gpct_variant_e_series:
 		case ni_gpct_variant_m_series:
-			*gate_source =
-			    ni_m_series_first_gate_to_generic_gate_source
-			    (gate_select_bits);
+		default:
+			*gate_source = ni_m_gate_to_generic_gate(gate);
 			break;
 		case ni_gpct_variant_660x:
-			*gate_source =
-			    ni_660x_first_gate_to_generic_gate_source
-			    (gate_select_bits);
-			break;
-		default:
-			BUG();
+			*gate_source = ni_660x_gate_to_generic_gate(gate);
 			break;
 		}
-		if (mode_bits & Gi_Gate_Polarity_Bit)
+		if (mode & GI_GATE_POL_INVERT)
 			*gate_source |= CR_INVERT;
-		if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits)
+		if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING)
 			*gate_source |= CR_EDGE;
 		break;
 	case 1:
-		if ((mode_bits & Gi_Gating_Mode_Mask) == Gi_Gating_Disabled_Bits
-		    || (counter_dev->regs[second_gate_reg] &
-			Gi_Second_Gate_Mode_Bit)
-		    == 0) {
+		if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED ||
+		    !(counter_dev->regs[gate2_reg] & GI_GATE2_MODE)) {
 			*gate_source = NI_GPCT_DISABLED_GATE_SELECT;
 			return 0;
-		} else {
-			gate_select_bits =
-			    (counter_dev->regs[second_gate_reg] &
-			     Gi_Second_Gate_Select_Mask) >>
-			    Gi_Second_Gate_Select_Shift;
 		}
+
+		gate = GI_BITS_TO_GATE2(counter_dev->regs[gate2_reg]);
+
 		switch (counter_dev->variant) {
 		case ni_gpct_variant_e_series:
 		case ni_gpct_variant_m_series:
-			*gate_source =
-			    ni_m_series_second_gate_to_generic_gate_source
-			    (gate_select_bits);
+		default:
+			*gate_source = ni_m_gate2_to_generic_gate(gate);
 			break;
 		case ni_gpct_variant_660x:
-			*gate_source =
-			    ni_660x_second_gate_to_generic_gate_source
-			    (gate_select_bits);
-			break;
-		default:
-			BUG();
+			*gate_source = ni_660x_gate2_to_generic_gate(gate);
 			break;
 		}
-		if (counter_dev->regs[second_gate_reg] &
-		    Gi_Second_Gate_Polarity_Bit) {
+		if (counter_dev->regs[gate2_reg] & GI_GATE2_POL_INVERT)
 			*gate_source |= CR_INVERT;
-		}
 		/* second gate can't have edge/level mode set independently */
-		if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits)
+		if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING)
 			*gate_source |= CR_EDGE;
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 0;
 }
@@ -1539,43 +1174,41 @@ int ni_tio_insn_config(struct comedi_dev
 		       unsigned int *data)
 {
 	struct ni_gpct *counter = s->private;
+	unsigned cidx = counter->counter_index;
+	unsigned status;
 
 	switch (data[0]) {
 	case INSN_CONFIG_SET_COUNTER_MODE:
 		return ni_tio_set_counter_mode(counter, data[1]);
-		break;
 	case INSN_CONFIG_ARM:
 		return ni_tio_arm(counter, 1, data[1]);
-		break;
 	case INSN_CONFIG_DISARM:
 		ni_tio_arm(counter, 0, 0);
 		return 0;
-		break;
 	case INSN_CONFIG_GET_COUNTER_STATUS:
-		data[1] = ni_tio_counter_status(counter);
-		data[2] = counter_status_mask;
+		data[1] = 0;
+		status = read_register(counter, NITIO_SHARED_STATUS_REG(cidx));
+		if (status & GI_ARMED(cidx)) {
+			data[1] |= COMEDI_COUNTER_ARMED;
+			if (status & GI_COUNTING(cidx))
+				data[1] |= COMEDI_COUNTER_COUNTING;
+		}
+		data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING;
 		return 0;
-		break;
 	case INSN_CONFIG_SET_CLOCK_SRC:
 		return ni_tio_set_clock_src(counter, data[1], data[2]);
-		break;
 	case INSN_CONFIG_GET_CLOCK_SRC:
 		ni_tio_get_clock_src(counter, &data[1], &data[2]);
 		return 0;
-		break;
 	case INSN_CONFIG_SET_GATE_SRC:
 		return ni_tio_set_gate_src(counter, data[1], data[2]);
-		break;
 	case INSN_CONFIG_GET_GATE_SRC:
 		return ni_tio_get_gate_src(counter, data[1], &data[2]);
-		break;
 	case INSN_CONFIG_SET_OTHER_SRC:
 		return ni_tio_set_other_src(counter, data[1], data[2]);
-		break;
 	case INSN_CONFIG_RESET:
 		ni_tio_reset_count_and_disarm(counter);
 		return 0;
-		break;
 	default:
 		break;
 	}
@@ -1583,6 +1216,33 @@ int ni_tio_insn_config(struct comedi_dev
 }
 EXPORT_SYMBOL_GPL(ni_tio_insn_config);
 
+static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev,
+					    struct comedi_subdevice *s)
+{
+	struct ni_gpct *counter = s->private;
+	unsigned cidx = counter->counter_index;
+	unsigned int val;
+
+	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0);
+	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
+			GI_SAVE_TRACE, GI_SAVE_TRACE);
+
+	/*
+	 * The count doesn't get latched until the next clock edge, so it is
+	 * possible the count may change (once) while we are reading. Since
+	 * the read of the SW_Save_Reg isn't atomic (apparently even when it's
+	 * a 32 bit register according to 660x docs), we need to read twice
+	 * and make sure the reading hasn't changed. If it has, a third read
+	 * will be correct since the count value will definitely have latched
+	 * by then.
+	 */
+	val = read_register(counter, NITIO_SW_SAVE_REG(cidx));
+	if (val != read_register(counter, NITIO_SW_SAVE_REG(cidx)))
+		val = read_register(counter, NITIO_SW_SAVE_REG(cidx));
+
+	return val;
+}
+
 int ni_tio_insn_read(struct comedi_device *dev,
 		     struct comedi_subdevice *s,
 		     struct comedi_insn *insn,
@@ -1590,43 +1250,24 @@ int ni_tio_insn_read(struct comedi_devic
 {
 	struct ni_gpct *counter = s->private;
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
-	const unsigned channel = CR_CHAN(insn->chanspec);
+	unsigned int channel = CR_CHAN(insn->chanspec);
 	unsigned cidx = counter->counter_index;
-	unsigned first_read;
-	unsigned second_read;
-	unsigned correct_read;
+	int i;
 
-	if (insn->n < 1)
-		return 0;
-	switch (channel) {
-	case 0:
-		ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
-				Gi_Save_Trace_Bit, 0);
-		ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
-				Gi_Save_Trace_Bit, Gi_Save_Trace_Bit);
-		/* The count doesn't get latched until the next clock edge, so it is possible the count
-		   may change (once) while we are reading.  Since the read of the SW_Save_Reg isn't
-		   atomic (apparently even when it's a 32 bit register according to 660x docs),
-		   we need to read twice and make sure the reading hasn't changed.  If it has,
-		   a third read will be correct since the count value will definitely have latched by then. */
-		first_read = read_register(counter, NITIO_SW_SAVE_REG(cidx));
-		second_read = read_register(counter, NITIO_SW_SAVE_REG(cidx));
-		if (first_read != second_read)
-			correct_read =
-			    read_register(counter, NITIO_SW_SAVE_REG(cidx));
-		else
-			correct_read = first_read;
-		data[0] = correct_read;
-		return 0;
-		break;
-	case 1:
-		data[0] = counter_dev->regs[NITIO_LOADA_REG(cidx)];
-		break;
-	case 2:
-		data[0] = counter_dev->regs[NITIO_LOADB_REG(cidx)];
-		break;
+	for (i = 0; i < insn->n; i++) {
+		switch (channel) {
+		case 0:
+			data[i] = ni_tio_read_sw_save_reg(dev, s);
+			break;
+		case 1:
+			data[i] = counter_dev->regs[NITIO_LOADA_REG(cidx)];
+			break;
+		case 2:
+			data[i] = counter_dev->regs[NITIO_LOADB_REG(cidx)];
+			break;
+		}
 	}
-	return 0;
+	return insn->n;
 }
 EXPORT_SYMBOL_GPL(ni_tio_insn_read);
 
@@ -1636,10 +1277,9 @@ static unsigned ni_tio_next_load_registe
 	const unsigned bits =
 		read_register(counter, NITIO_SHARED_STATUS_REG(cidx));
 
-	if (bits & Gi_Next_Load_Source_Bit(cidx))
-		return NITIO_LOADB_REG(cidx);
-	else
-		return NITIO_LOADA_REG(cidx);
+	return (bits & GI_NEXT_LOAD_SRC(cidx))
+			? NITIO_LOADB_REG(cidx)
+			: NITIO_LOADA_REG(cidx);
 }
 
 int ni_tio_insn_write(struct comedi_device *dev,
@@ -1657,13 +1297,20 @@ int ni_tio_insn_write(struct comedi_devi
 		return 0;
 	switch (channel) {
 	case 0:
-		/* Unsafe if counter is armed.  Should probably check status and return -EBUSY if armed. */
-		/* Don't disturb load source select, just use whichever load register is already selected. */
+		/*
+		 * Unsafe if counter is armed.
+		 * Should probably check status and return -EBUSY if armed.
+		 */
+
+		/*
+		 * Don't disturb load source select, just use whichever
+		 * load register is already selected.
+		 */
 		load_reg = ni_tio_next_load_register(counter);
 		write_register(counter, data[0], load_reg);
 		ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx),
-					  0, 0, Gi_Load_Bit);
-		/* restore state of load reg to whatever the user set last set it to */
+					  0, 0, GI_LOAD);
+		/* restore load reg */
 		write_register(counter, counter_dev->regs[load_reg], load_reg);
 		break;
 	case 1:
@@ -1676,12 +1323,104 @@ int ni_tio_insn_write(struct comedi_devi
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ni_tio_insn_write);
 
+void ni_tio_init_counter(struct ni_gpct *counter)
+{
+	struct ni_gpct_device *counter_dev = counter->counter_dev;
+	unsigned cidx = counter->counter_index;
+
+	ni_tio_reset_count_and_disarm(counter);
+
+	/* initialize counter registers */
+	counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0;
+	write_register(counter, 0x0, NITIO_AUTO_INC_REG(cidx));
+
+	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx),
+			~0, GI_SYNC_GATE);
+
+	ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0);
+
+	counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0;
+	write_register(counter, 0x0, NITIO_LOADA_REG(cidx));
+
+	counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0;
+	write_register(counter, 0x0, NITIO_LOADB_REG(cidx));
+
+	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0);
+
+	if (ni_tio_counting_mode_registers_present(counter_dev))
+		ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0);
+
+	if (ni_tio_has_gate2_registers(counter_dev)) {
+		counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0;
+		write_register(counter, 0x0, NITIO_GATE2_REG(cidx));
+	}
+
+	ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0);
+
+	ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), ~0, 0x0);
+}
+EXPORT_SYMBOL_GPL(ni_tio_init_counter);
+
+struct ni_gpct_device *
+ni_gpct_device_construct(struct comedi_device *dev,
+			 void (*write_register)(struct ni_gpct *counter,
+						unsigned bits,
+						enum ni_gpct_register reg),
+			 unsigned (*read_register)(struct ni_gpct *counter,
+						   enum ni_gpct_register reg),
+			 enum ni_gpct_variant variant,
+			 unsigned num_counters)
+{
+	struct ni_gpct_device *counter_dev;
+	struct ni_gpct *counter;
+	unsigned i;
+
+	if (num_counters == 0)
+		return NULL;
+
+	counter_dev = kzalloc(sizeof(*counter_dev), GFP_KERNEL);
+	if (!counter_dev)
+		return NULL;
+
+	counter_dev->dev = dev;
+	counter_dev->write_register = write_register;
+	counter_dev->read_register = read_register;
+	counter_dev->variant = variant;
+
+	spin_lock_init(&counter_dev->regs_lock);
+
+	counter_dev->counters = kcalloc(num_counters, sizeof(*counter),
+					GFP_KERNEL);
+	if (!counter_dev->counters) {
+		kfree(counter_dev);
+		return NULL;
+	}
+
+	for (i = 0; i < num_counters; ++i) {
+		counter = &counter_dev->counters[i];
+		counter->counter_dev = counter_dev;
+		spin_lock_init(&counter->lock);
+	}
+	counter_dev->num_counters = num_counters;
+
+	return counter_dev;
+}
+EXPORT_SYMBOL_GPL(ni_gpct_device_construct);
+
+void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev)
+{
+	if (!counter_dev->counters)
+		return;
+	kfree(counter_dev->counters);
+	kfree(counter_dev);
+}
+EXPORT_SYMBOL_GPL(ni_gpct_device_destroy);
+
 static int __init ni_tio_init_module(void)
 {
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,40 +49,38 @@ TODO:
 #include "ni_tio_internal.h"
 #include "mite.h"
 
-static void ni_tio_configure_dma(struct ni_gpct *counter, short enable,
-				 short read_not_write)
+static void ni_tio_configure_dma(struct ni_gpct *counter,
+				 bool enable, bool read)
 {
 	struct ni_gpct_device *counter_dev = counter->counter_dev;
 	unsigned cidx = counter->counter_index;
-	unsigned input_select_bits = 0;
+	unsigned mask;
+	unsigned bits;
+
+	mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ;
+	bits = 0;
 
 	if (enable) {
-		if (read_not_write)
-			input_select_bits |= Gi_Read_Acknowledges_Irq;
+		if (read)
+			bits |= GI_READ_ACKS_IRQ;
 		else
-			input_select_bits |= Gi_Write_Acknowledges_Irq;
+			bits |= GI_WRITE_ACKS_IRQ;
 	}
-	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
-			Gi_Read_Acknowledges_Irq | Gi_Write_Acknowledges_Irq,
-			input_select_bits);
+	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), mask, bits);
+
 	switch (counter_dev->variant) {
 	case ni_gpct_variant_e_series:
 		break;
 	case ni_gpct_variant_m_series:
 	case ni_gpct_variant_660x:
-		{
-			unsigned gi_dma_config_bits = 0;
+		mask = GI_DMA_ENABLE | GI_DMA_INT_ENA | GI_DMA_WRITE;
+		bits = 0;
 
-			if (enable) {
-				gi_dma_config_bits |= Gi_DMA_Enable_Bit;
-				gi_dma_config_bits |= Gi_DMA_Int_Bit;
-			}
-			if (read_not_write == 0)
-				gi_dma_config_bits |= Gi_DMA_Write_Bit;
-			ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx),
-					Gi_DMA_Enable_Bit | Gi_DMA_Int_Bit |
-					Gi_DMA_Write_Bit, gi_dma_config_bits);
-		}
+		if (enable)
+			bits |= GI_DMA_ENABLE | GI_DMA_INT_ENA;
+		if (!read)
+			bits |= GI_DMA_WRITE;
+		ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), mask, bits);
 		break;
 	}
 }
@@ -94,9 +92,7 @@ static int ni_tio_input_inttrig(struct c
 	struct ni_gpct *counter = s->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned long flags;
-	int retval = 0;
-
-	BUG_ON(counter == NULL);
+	int ret = 0;
 
 	if (trig_num != cmd->start_src)
 		return -EINVAL;
@@ -105,14 +101,14 @@ static int ni_tio_input_inttrig(struct c
 	if (counter->mite_chan)
 		mite_dma_arm(counter->mite_chan);
 	else
-		retval = -EIO;
+		ret = -EIO;
 	spin_unlock_irqrestore(&counter->lock, flags);
-	if (retval < 0)
-		return retval;
-	retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
+	if (ret < 0)
+		return ret;
+	ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
 	s->async->inttrig = NULL;
 
-	return retval;
+	return ret;
 }
 
 static int ni_tio_input_cmd(struct comedi_subdevice *s)
@@ -122,7 +118,7 @@ static int ni_tio_input_cmd(struct comed
 	unsigned cidx = counter->counter_index;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
-	int retval = 0;
+	int ret = 0;
 
 	/* write alloc the entire buffer */
 	comedi_buf_write_alloc(s, async->prealloc_bufsz);
@@ -139,31 +135,21 @@ static int ni_tio_input_cmd(struct comed
 		BUG();
 		break;
 	}
-	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), Gi_Save_Trace_Bit, 0);
-	ni_tio_configure_dma(counter, 1, 1);
-	switch (cmd->start_src) {
-	case TRIG_NOW:
-		async->inttrig = NULL;
-		mite_dma_arm(counter->mite_chan);
-		retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
-		break;
-	case TRIG_INT:
+	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0);
+	ni_tio_configure_dma(counter, true, true);
+
+	if (cmd->start_src == TRIG_INT) {
 		async->inttrig = &ni_tio_input_inttrig;
-		break;
-	case TRIG_EXT:
-		async->inttrig = NULL;
-		mite_dma_arm(counter->mite_chan);
-		retval = ni_tio_arm(counter, 1, cmd->start_arg);
-		break;
-	case TRIG_OTHER:
+	} else {	/* TRIG_NOW || TRIG_EXT || TRIG_OTHER */
 		async->inttrig = NULL;
 		mite_dma_arm(counter->mite_chan);
-		break;
-	default:
-		BUG();
-		break;
+
+		if (cmd->start_src == TRIG_NOW)
+			ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
+		else if (cmd->start_src == TRIG_EXT)
+			ret = ni_tio_arm(counter, 1, cmd->start_arg);
 	}
-	return retval;
+	return ret;
 }
 
 static int ni_tio_output_cmd(struct comedi_subdevice *s)
@@ -176,7 +162,7 @@ static int ni_tio_output_cmd(struct come
 
 	counter->mite_chan->dir = COMEDI_OUTPUT;
 	mite_prep_dma(counter->mite_chan, 32, 32);
-	ni_tio_configure_dma(counter, 1, 0);
+	ni_tio_configure_dma(counter, true, false);
 	mite_dma_arm(counter->mite_chan);
 	return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
 }
@@ -201,8 +187,8 @@ static int ni_tio_cmd_setup(struct comed
 		retval = ni_tio_set_gate_src(counter, 0, gate_source);
 	if (cmd->flags & TRIG_WAKE_EOS) {
 		ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
-				Gi_Gate_Interrupt_Enable_Bit(cidx),
-				Gi_Gate_Interrupt_Enable_Bit(cidx));
+				GI_GATE_INTERRUPT_ENABLE(cidx),
+				GI_GATE_INTERRUPT_ENABLE(cidx));
 	}
 	return retval;
 }
@@ -319,10 +305,10 @@ int ni_tio_cancel(struct ni_gpct *counte
 	if (counter->mite_chan)
 		mite_dma_disarm(counter->mite_chan);
 	spin_unlock_irqrestore(&counter->lock, flags);
-	ni_tio_configure_dma(counter, 0, 0);
+	ni_tio_configure_dma(counter, false, false);
 
 	ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
-			Gi_Gate_Interrupt_Enable_Bit(cidx), 0x0);
+			GI_GATE_INTERRUPT_ENABLE(cidx), 0x0);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ni_tio_cancel);
@@ -342,7 +328,6 @@ static int should_ack_gate(struct ni_gpc
 	    in register-level manual) */
 	case ni_gpct_variant_660x:
 		return 1;
-		break;
 	case ni_gpct_variant_e_series:
 		spin_lock_irqsave(&counter->lock, flags);
 		{
@@ -358,9 +343,11 @@ static int should_ack_gate(struct ni_gpc
 	return retval;
 }
 
-void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error,
-				    int *tc_error, int *perm_stale_data,
-				    int *stale_data)
+static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
+					   int *gate_error,
+					   int *tc_error,
+					   int *perm_stale_data,
+					   int *stale_data)
 {
 	unsigned cidx = counter->counter_index;
 	const unsigned short gxx_status = read_register(counter,
@@ -378,8 +365,8 @@ void ni_tio_acknowledge_and_confirm(stru
 	if (stale_data)
 		*stale_data = 0;
 
-	if (gxx_status & Gi_Gate_Error_Bit(cidx)) {
-		ack |= Gi_Gate_Error_Confirm_Bit(cidx);
+	if (gxx_status & GI_GATE_ERROR(cidx)) {
+		ack |= GI_GATE_ERROR_CONFIRM(cidx);
 		if (gate_error) {
 			/*660x don't support automatic acknowledgement
 			  of gate interrupt via dma read/write
@@ -390,27 +377,27 @@ void ni_tio_acknowledge_and_confirm(stru
 			}
 		}
 	}
-	if (gxx_status & Gi_TC_Error_Bit(cidx)) {
-		ack |= Gi_TC_Error_Confirm_Bit(cidx);
+	if (gxx_status & GI_TC_ERROR(cidx)) {
+		ack |= GI_TC_ERROR_CONFIRM(cidx);
 		if (tc_error)
 			*tc_error = 1;
 	}
-	if (gi_status & Gi_TC_Bit)
-		ack |= Gi_TC_Interrupt_Ack_Bit;
-	if (gi_status & Gi_Gate_Interrupt_Bit) {
+	if (gi_status & GI_TC)
+		ack |= GI_TC_INTERRUPT_ACK;
+	if (gi_status & GI_GATE_INTERRUPT) {
 		if (should_ack_gate(counter))
-			ack |= Gi_Gate_Interrupt_Ack_Bit;
+			ack |= GI_GATE_INTERRUPT_ACK;
 	}
 	if (ack)
 		write_register(counter, ack, NITIO_INT_ACK_REG(cidx));
 	if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) &
-	    Gi_Loading_On_Gate_Bit) {
-		if (gxx_status & Gi_Stale_Data_Bit(cidx)) {
+	    GI_LOADING_ON_GATE) {
+		if (gxx_status & GI_STALE_DATA(cidx)) {
 			if (stale_data)
 				*stale_data = 1;
 		}
 		if (read_register(counter, NITIO_STATUS2_REG(cidx)) &
-		    Gi_Permanent_Stale_Bit(cidx)) {
+		    GI_PERMANENT_STALE(cidx)) {
 			dev_info(counter->counter_dev->dev->class_dev,
 				 "%s: Gi_Permanent_Stale_Data detected.\n",
 				 __func__);
@@ -419,7 +406,12 @@ void ni_tio_acknowledge_and_confirm(stru
 		}
 	}
 }
-EXPORT_SYMBOL_GPL(ni_tio_acknowledge_and_confirm);
+
+void ni_tio_acknowledge(struct ni_gpct *counter)
+{
+	ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(ni_tio_acknowledge);
 
 void ni_tio_handle_interrupt(struct ni_gpct *counter,
 			     struct comedi_subdevice *s)
@@ -444,7 +436,7 @@ void ni_tio_handle_interrupt(struct ni_g
 	case ni_gpct_variant_m_series:
 	case ni_gpct_variant_660x:
 		if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) &
-		    Gi_DRQ_Error_Bit) {
+		    GI_DRQ_ERROR) {
 			dev_notice(counter->counter_dev->dev->class_dev,
 				   "%s: Gi_DRQ_Error detected.\n", __func__);
 			s->async->events |= COMEDI_CB_OVERFLOW;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio.h	2014-09-28 17:29:07.000000000 -0400
@@ -149,8 +149,6 @@ int ni_tio_cmdtest(struct comedi_device
 int ni_tio_cancel(struct ni_gpct *);
 void ni_tio_handle_interrupt(struct ni_gpct *, struct comedi_subdevice *);
 void ni_tio_set_mite_channel(struct ni_gpct *, struct mite_channel *);
-void ni_tio_acknowledge_and_confirm(struct ni_gpct *,
-				    int *gate_error, int *tc_error,
-				    int *perm_stale_data, int *stale_data);
+void ni_tio_acknowledge(struct ni_gpct *);
 
 #endif /* _COMEDI_NI_TIO_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio_internal.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/ni_tio_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/ni_tio_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -22,296 +22,139 @@
 #include "ni_tio.h"
 
 #define NITIO_AUTO_INC_REG(x)		(NITIO_G0_AUTO_INC + (x))
+#define GI_AUTO_INC_MASK		0xff
 #define NITIO_CMD_REG(x)		(NITIO_G0_CMD + (x))
+#define GI_ARM				(1 << 0)
+#define GI_SAVE_TRACE			(1 << 1)
+#define GI_LOAD				(1 << 2)
+#define GI_DISARM			(1 << 4)
+#define GI_CNT_DIR(x)			(((x) & 0x3) << 5)
+#define GI_CNT_DIR_MASK			(3 << 5)
+#define GI_WRITE_SWITCH			(1 << 7)
+#define GI_SYNC_GATE			(1 << 8)
+#define GI_LITTLE_BIG_ENDIAN		(1 << 9)
+#define GI_BANK_SWITCH_START		(1 << 10)
+#define GI_BANK_SWITCH_MODE		(1 << 11)
+#define GI_BANK_SWITCH_ENABLE		(1 << 12)
+#define GI_ARM_COPY			(1 << 13)
+#define GI_SAVE_TRACE_COPY		(1 << 14)
+#define GI_DISARM_COPY			(1 << 15)
 #define NITIO_HW_SAVE_REG(x)		(NITIO_G0_HW_SAVE + (x))
 #define NITIO_SW_SAVE_REG(x)		(NITIO_G0_SW_SAVE + (x))
 #define NITIO_MODE_REG(x)		(NITIO_G0_MODE + (x))
+#define GI_GATING_DISABLED		(0 << 0)
+#define GI_LEVEL_GATING			(1 << 0)
+#define GI_RISING_EDGE_GATING		(2 << 0)
+#define GI_FALLING_EDGE_GATING		(3 << 0)
+#define GI_GATING_MODE_MASK		(3 << 0)
+#define GI_GATE_ON_BOTH_EDGES		(1 << 2)
+#define GI_EDGE_GATE_STARTS_STOPS	(0 << 3)
+#define GI_EDGE_GATE_STOPS_STARTS	(1 << 3)
+#define GI_EDGE_GATE_STARTS		(2 << 3)
+#define GI_EDGE_GATE_NO_STARTS_OR_STOPS	(3 << 3)
+#define GI_EDGE_GATE_MODE_MASK		(3 << 3)
+#define GI_STOP_ON_GATE			(0 << 5)
+#define GI_STOP_ON_GATE_OR_TC		(1 << 5)
+#define GI_STOP_ON_GATE_OR_SECOND_TC	(2 << 5)
+#define GI_STOP_MODE_MASK		(3 << 5)
+#define GI_LOAD_SRC_SEL			(1 << 7)
+#define GI_OUTPUT_TC_PULSE		(1 << 8)
+#define GI_OUTPUT_TC_TOGGLE		(2 << 8)
+#define GI_OUTPUT_TC_OR_GATE_TOGGLE	(3 << 8)
+#define GI_OUTPUT_MODE_MASK		(3 << 8)
+#define GI_NO_HARDWARE_DISARM		(0 << 10)
+#define GI_DISARM_AT_TC			(1 << 10)
+#define GI_DISARM_AT_GATE		(2 << 10)
+#define GI_DISARM_AT_TC_OR_GATE		(3 << 10)
+#define GI_COUNTING_ONCE_MASK		(3 << 10)
+#define GI_LOADING_ON_TC		(1 << 12)
+#define GI_GATE_POL_INVERT		(1 << 13)
+#define GI_LOADING_ON_GATE		(1 << 14)
+#define GI_RELOAD_SRC_SWITCHING		(1 << 15)
 #define NITIO_LOADA_REG(x)		(NITIO_G0_LOADA + (x))
 #define NITIO_LOADB_REG(x)		(NITIO_G0_LOADB + (x))
 #define NITIO_INPUT_SEL_REG(x)		(NITIO_G0_INPUT_SEL + (x))
+#define GI_READ_ACKS_IRQ		(1 << 0)
+#define GI_WRITE_ACKS_IRQ		(1 << 1)
+#define GI_BITS_TO_SRC(x)		(((x) >> 2) & 0x1f)
+#define GI_SRC_SEL(x)			(((x) & 0x1f) << 2)
+#define GI_SRC_SEL_MASK			(0x1f << 2)
+#define GI_BITS_TO_GATE(x)		(((x) >> 7) & 0x1f)
+#define GI_GATE_SEL(x)			(((x) & 0x1f) << 7)
+#define GI_GATE_SEL_MASK		(0x1f << 7)
+#define GI_GATE_SEL_LOAD_SRC		(1 << 12)
+#define GI_OR_GATE			(1 << 13)
+#define GI_OUTPUT_POL_INVERT		(1 << 14)
+#define GI_SRC_POL_INVERT		(1 << 15)
 #define NITIO_CNT_MODE_REG(x)		(NITIO_G0_CNT_MODE + (x))
+#define GI_CNT_MODE(x)			(((x) & 0x7) << 0)
+#define GI_CNT_MODE_NORMAL		GI_CNT_MODE(0)
+#define GI_CNT_MODE_QUADX1		GI_CNT_MODE(1)
+#define GI_CNT_MODE_QUADX2		GI_CNT_MODE(2)
+#define GI_CNT_MODE_QUADX4		GI_CNT_MODE(3)
+#define GI_CNT_MODE_TWO_PULSE		GI_CNT_MODE(4)
+#define GI_CNT_MODE_SYNC_SRC		GI_CNT_MODE(6)
+#define GI_CNT_MODE_MASK		(7 << 0)
+#define GI_INDEX_MODE			(1 << 4)
+#define GI_INDEX_PHASE(x)		(((x) & 0x3) << 5)
+#define GI_INDEX_PHASE_MASK		(3 << 5)
+#define GI_HW_ARM_ENA			(1 << 7)
+#define GI_HW_ARM_SEL(x)		((x) << 8)
+#define GI_660X_HW_ARM_SEL_MASK		(0x7 << 8)
+#define GI_M_HW_ARM_SEL_MASK		(0x1f << 8)
+#define GI_660X_PRESCALE_X8		(1 << 12)
+#define GI_M_PRESCALE_X8		(1 << 13)
+#define GI_660X_ALT_SYNC		(1 << 13)
+#define GI_M_ALT_SYNC			(1 << 14)
+#define GI_660X_PRESCALE_X2		(1 << 14)
+#define GI_M_PRESCALE_X2		(1 << 15)
 #define NITIO_GATE2_REG(x)		(NITIO_G0_GATE2 + (x))
+#define GI_GATE2_MODE			(1 << 0)
+#define GI_BITS_TO_GATE2(x)		(((x) >> 7) & 0x1f)
+#define GI_GATE2_SEL(x)			(((x) & 0x1f) << 7)
+#define GI_GATE2_SEL_MASK		(0x1f << 7)
+#define GI_GATE2_POL_INVERT		(1 << 13)
+#define GI_GATE2_SUBSEL			(1 << 14)
+#define GI_SRC_SUBSEL			(1 << 15)
 #define NITIO_SHARED_STATUS_REG(x)	(NITIO_G01_STATUS + ((x) / 2))
+#define GI_SAVE(x)			(((x) % 2) ? (1 << 1) : (1 << 0))
+#define GI_COUNTING(x)			(((x) % 2) ? (1 << 3) : (1 << 2))
+#define GI_NEXT_LOAD_SRC(x)		(((x) % 2) ? (1 << 5) : (1 << 4))
+#define GI_STALE_DATA(x)		(((x) % 2) ? (1 << 7) : (1 << 6))
+#define GI_ARMED(x)			(((x) % 2) ? (1 << 9) : (1 << 8))
+#define GI_NO_LOAD_BETWEEN_GATES(x)	(((x) % 2) ? (1 << 11) : (1 << 10))
+#define GI_TC_ERROR(x)			(((x) % 2) ? (1 << 13) : (1 << 12))
+#define GI_GATE_ERROR(x)		(((x) % 2) ? (1 << 15) : (1 << 14))
 #define NITIO_RESET_REG(x)		(NITIO_G01_RESET + ((x) / 2))
+#define GI_RESET(x)			(1 << (2 + ((x) % 2)))
 #define NITIO_STATUS1_REG(x)		(NITIO_G01_STATUS1 + ((x) / 2))
 #define NITIO_STATUS2_REG(x)		(NITIO_G01_STATUS2 + ((x) / 2))
+#define GI_OUTPUT(x)			(((x) % 2) ? (1 << 1) : (1 << 0))
+#define GI_HW_SAVE(x)			(((x) % 2) ? (1 << 13) : (1 << 12))
+#define GI_PERMANENT_STALE(x)		(((x) % 2) ? (1 << 15) : (1 << 14))
 #define NITIO_DMA_CFG_REG(x)		(NITIO_G0_DMA_CFG + (x))
+#define GI_DMA_ENABLE			(1 << 0)
+#define GI_DMA_WRITE			(1 << 1)
+#define GI_DMA_INT_ENA			(1 << 2)
+#define GI_DMA_RESET			(1 << 3)
+#define GI_DMA_BANKSW_ERROR		(1 << 4)
 #define NITIO_DMA_STATUS_REG(x)		(NITIO_G0_DMA_STATUS + (x))
+#define GI_DMA_READBANK			(1 << 13)
+#define GI_DRQ_ERROR			(1 << 14)
+#define GI_DRQ_STATUS			(1 << 15)
 #define NITIO_ABZ_REG(x)		(NITIO_G0_ABZ + (x))
 #define NITIO_INT_ACK_REG(x)		(NITIO_G0_INT_ACK + (x))
+#define GI_GATE_ERROR_CONFIRM(x)	(((x) % 2) ? (1 << 1) : (1 << 5))
+#define GI_TC_ERROR_CONFIRM(x)		(((x) % 2) ? (1 << 2) : (1 << 6))
+#define GI_TC_INTERRUPT_ACK		(1 << 14)
+#define GI_GATE_INTERRUPT_ACK		(1 << 15)
 #define NITIO_STATUS_REG(x)		(NITIO_G0_STATUS + (x))
+#define GI_GATE_INTERRUPT		(1 << 2)
+#define GI_TC				(1 << 3)
+#define GI_INTERRUPT			(1 << 15)
 #define NITIO_INT_ENA_REG(x)		(NITIO_G0_INT_ENA + (x))
-
-enum Gi_Auto_Increment_Reg_Bits {
-	Gi_Auto_Increment_Mask = 0xff
-};
-
-#define Gi_Up_Down_Shift 5
-enum Gi_Command_Reg_Bits {
-	Gi_Arm_Bit = 0x1,
-	Gi_Save_Trace_Bit = 0x2,
-	Gi_Load_Bit = 0x4,
-	Gi_Disarm_Bit = 0x10,
-	Gi_Up_Down_Mask = 0x3 << Gi_Up_Down_Shift,
-	Gi_Always_Down_Bits = 0x0 << Gi_Up_Down_Shift,
-	Gi_Always_Up_Bits = 0x1 << Gi_Up_Down_Shift,
-	Gi_Up_Down_Hardware_IO_Bits = 0x2 << Gi_Up_Down_Shift,
-	Gi_Up_Down_Hardware_Gate_Bits = 0x3 << Gi_Up_Down_Shift,
-	Gi_Write_Switch_Bit = 0x80,
-	Gi_Synchronize_Gate_Bit = 0x100,
-	Gi_Little_Big_Endian_Bit = 0x200,
-	Gi_Bank_Switch_Start_Bit = 0x400,
-	Gi_Bank_Switch_Mode_Bit = 0x800,
-	Gi_Bank_Switch_Enable_Bit = 0x1000,
-	Gi_Arm_Copy_Bit = 0x2000,
-	Gi_Save_Trace_Copy_Bit = 0x4000,
-	Gi_Disarm_Copy_Bit = 0x8000
-};
-
-#define Gi_Index_Phase_Bitshift 5
-#define Gi_HW_Arm_Select_Shift 8
-enum Gi_Counting_Mode_Reg_Bits {
-	Gi_Counting_Mode_Mask = 0x7,
-	Gi_Counting_Mode_Normal_Bits = 0x0,
-	Gi_Counting_Mode_QuadratureX1_Bits = 0x1,
-	Gi_Counting_Mode_QuadratureX2_Bits = 0x2,
-	Gi_Counting_Mode_QuadratureX4_Bits = 0x3,
-	Gi_Counting_Mode_Two_Pulse_Bits = 0x4,
-	Gi_Counting_Mode_Sync_Source_Bits = 0x6,
-	Gi_Index_Mode_Bit = 0x10,
-	Gi_Index_Phase_Mask = 0x3 << Gi_Index_Phase_Bitshift,
-	Gi_Index_Phase_LowA_LowB = 0x0 << Gi_Index_Phase_Bitshift,
-	Gi_Index_Phase_LowA_HighB = 0x1 << Gi_Index_Phase_Bitshift,
-	Gi_Index_Phase_HighA_LowB = 0x2 << Gi_Index_Phase_Bitshift,
-	Gi_Index_Phase_HighA_HighB = 0x3 << Gi_Index_Phase_Bitshift,
-	/* from m-series example code, not documented in 660x register level
-	 * manual */
-	Gi_HW_Arm_Enable_Bit = 0x80,
-	/* from m-series example code, not documented in 660x register level
-	 * manual */
-	Gi_660x_HW_Arm_Select_Mask = 0x7 << Gi_HW_Arm_Select_Shift,
-	Gi_660x_Prescale_X8_Bit = 0x1000,
-	Gi_M_Series_Prescale_X8_Bit = 0x2000,
-	Gi_M_Series_HW_Arm_Select_Mask = 0x1f << Gi_HW_Arm_Select_Shift,
-	/* must be set for clocks over 40MHz, which includes synchronous
-	 * counting and quadrature modes */
-	Gi_660x_Alternate_Sync_Bit = 0x2000,
-	Gi_M_Series_Alternate_Sync_Bit = 0x4000,
-	/* from m-series example code, not documented in 660x register level
-	 * manual */
-	Gi_660x_Prescale_X2_Bit = 0x4000,
-	Gi_M_Series_Prescale_X2_Bit = 0x8000,
-};
-
-#define Gi_Source_Select_Shift 2
-#define Gi_Gate_Select_Shift 7
-enum Gi_Input_Select_Bits {
-	Gi_Read_Acknowledges_Irq = 0x1,	/*  not present on 660x */
-	Gi_Write_Acknowledges_Irq = 0x2,	/*  not present on 660x */
-	Gi_Source_Select_Mask = 0x7c,
-	Gi_Gate_Select_Mask = 0x1f << Gi_Gate_Select_Shift,
-	Gi_Gate_Select_Load_Source_Bit = 0x1000,
-	Gi_Or_Gate_Bit = 0x2000,
-	Gi_Output_Polarity_Bit = 0x4000,	/* set to invert */
-	Gi_Source_Polarity_Bit = 0x8000	/* set to invert */
-};
-
-enum Gi_Mode_Bits {
-	Gi_Gating_Mode_Mask = 0x3,
-	Gi_Gating_Disabled_Bits = 0x0,
-	Gi_Level_Gating_Bits = 0x1,
-	Gi_Rising_Edge_Gating_Bits = 0x2,
-	Gi_Falling_Edge_Gating_Bits = 0x3,
-	Gi_Gate_On_Both_Edges_Bit = 0x4,	/* used in conjunction with
-						 * rising edge gating mode */
-	Gi_Trigger_Mode_for_Edge_Gate_Mask = 0x18,
-	Gi_Edge_Gate_Starts_Stops_Bits = 0x0,
-	Gi_Edge_Gate_Stops_Starts_Bits = 0x8,
-	Gi_Edge_Gate_Starts_Bits = 0x10,
-	Gi_Edge_Gate_No_Starts_or_Stops_Bits = 0x18,
-	Gi_Stop_Mode_Mask = 0x60,
-	Gi_Stop_on_Gate_Bits = 0x00,
-	Gi_Stop_on_Gate_or_TC_Bits = 0x20,
-	Gi_Stop_on_Gate_or_Second_TC_Bits = 0x40,
-	Gi_Load_Source_Select_Bit = 0x80,
-	Gi_Output_Mode_Mask = 0x300,
-	Gi_Output_TC_Pulse_Bits = 0x100,
-	Gi_Output_TC_Toggle_Bits = 0x200,
-	Gi_Output_TC_or_Gate_Toggle_Bits = 0x300,
-	Gi_Counting_Once_Mask = 0xc00,
-	Gi_No_Hardware_Disarm_Bits = 0x000,
-	Gi_Disarm_at_TC_Bits = 0x400,
-	Gi_Disarm_at_Gate_Bits = 0x800,
-	Gi_Disarm_at_TC_or_Gate_Bits = 0xc00,
-	Gi_Loading_On_TC_Bit = 0x1000,
-	Gi_Gate_Polarity_Bit = 0x2000,
-	Gi_Loading_On_Gate_Bit = 0x4000,
-	Gi_Reload_Source_Switching_Bit = 0x8000
-};
-
-#define Gi_Second_Gate_Select_Shift 7
-/*FIXME: m-series has a second gate subselect bit */
-/*FIXME: m-series second gate sources are undocumented (by NI)*/
-enum Gi_Second_Gate_Bits {
-	Gi_Second_Gate_Mode_Bit = 0x1,
-	Gi_Second_Gate_Select_Mask = 0x1f << Gi_Second_Gate_Select_Shift,
-	Gi_Second_Gate_Polarity_Bit = 0x2000,
-	Gi_Second_Gate_Subselect_Bit = 0x4000,	/* m-series only */
-	Gi_Source_Subselect_Bit = 0x8000	/* m-series only */
-};
-static inline unsigned Gi_Second_Gate_Select_Bits(unsigned second_gate_select)
-{
-	return (second_gate_select << Gi_Second_Gate_Select_Shift) &
-	    Gi_Second_Gate_Select_Mask;
-}
-
-enum Gxx_Status_Bits {
-	G0_Save_Bit = 0x1,
-	G1_Save_Bit = 0x2,
-	G0_Counting_Bit = 0x4,
-	G1_Counting_Bit = 0x8,
-	G0_Next_Load_Source_Bit = 0x10,
-	G1_Next_Load_Source_Bit = 0x20,
-	G0_Stale_Data_Bit = 0x40,
-	G1_Stale_Data_Bit = 0x80,
-	G0_Armed_Bit = 0x100,
-	G1_Armed_Bit = 0x200,
-	G0_No_Load_Between_Gates_Bit = 0x400,
-	G1_No_Load_Between_Gates_Bit = 0x800,
-	G0_TC_Error_Bit = 0x1000,
-	G1_TC_Error_Bit = 0x2000,
-	G0_Gate_Error_Bit = 0x4000,
-	G1_Gate_Error_Bit = 0x8000
-};
-static inline enum Gxx_Status_Bits Gi_Counting_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_Counting_Bit;
-	return G0_Counting_Bit;
-}
-
-static inline enum Gxx_Status_Bits Gi_Armed_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_Armed_Bit;
-	return G0_Armed_Bit;
-}
-
-static inline enum Gxx_Status_Bits Gi_Next_Load_Source_Bit(unsigned
-							   counter_index)
-{
-	if (counter_index % 2)
-		return G1_Next_Load_Source_Bit;
-	return G0_Next_Load_Source_Bit;
-}
-
-static inline enum Gxx_Status_Bits Gi_Stale_Data_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_Stale_Data_Bit;
-	return G0_Stale_Data_Bit;
-}
-
-static inline enum Gxx_Status_Bits Gi_TC_Error_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_TC_Error_Bit;
-	return G0_TC_Error_Bit;
-}
-
-static inline enum Gxx_Status_Bits Gi_Gate_Error_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_Gate_Error_Bit;
-	return G0_Gate_Error_Bit;
-}
-
-/* joint reset register bits */
-static inline unsigned Gi_Reset_Bit(unsigned counter_index)
-{
-	return 0x1 << (2 + (counter_index % 2));
-}
-
-enum Gxx_Joint_Status2_Bits {
-	G0_Output_Bit = 0x1,
-	G1_Output_Bit = 0x2,
-	G0_HW_Save_Bit = 0x1000,
-	G1_HW_Save_Bit = 0x2000,
-	G0_Permanent_Stale_Bit = 0x4000,
-	G1_Permanent_Stale_Bit = 0x8000
-};
-static inline enum Gxx_Joint_Status2_Bits Gi_Permanent_Stale_Bit(unsigned
-								 counter_index)
-{
-	if (counter_index % 2)
-		return G1_Permanent_Stale_Bit;
-	return G0_Permanent_Stale_Bit;
-}
-
-enum Gi_DMA_Config_Reg_Bits {
-	Gi_DMA_Enable_Bit = 0x1,
-	Gi_DMA_Write_Bit = 0x2,
-	Gi_DMA_Int_Bit = 0x4
-};
-
-enum Gi_DMA_Status_Reg_Bits {
-	Gi_DMA_Readbank_Bit = 0x2000,
-	Gi_DRQ_Error_Bit = 0x4000,
-	Gi_DRQ_Status_Bit = 0x8000
-};
-
-enum G02_Interrupt_Acknowledge_Bits {
-	G0_Gate_Error_Confirm_Bit = 0x20,
-	G0_TC_Error_Confirm_Bit = 0x40
-};
-enum G13_Interrupt_Acknowledge_Bits {
-	G1_Gate_Error_Confirm_Bit = 0x2,
-	G1_TC_Error_Confirm_Bit = 0x4
-};
-static inline unsigned Gi_Gate_Error_Confirm_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_Gate_Error_Confirm_Bit;
-	return G0_Gate_Error_Confirm_Bit;
-}
-
-static inline unsigned Gi_TC_Error_Confirm_Bit(unsigned counter_index)
-{
-	if (counter_index % 2)
-		return G1_TC_Error_Confirm_Bit;
-	return G0_TC_Error_Confirm_Bit;
-}
-
-/* bits that are the same in G0/G2 and G1/G3 interrupt acknowledge registers */
-enum Gxx_Interrupt_Acknowledge_Bits {
-	Gi_TC_Interrupt_Ack_Bit = 0x4000,
-	Gi_Gate_Interrupt_Ack_Bit = 0x8000
-};
-
-enum Gi_Status_Bits {
-	Gi_Gate_Interrupt_Bit = 0x4,
-	Gi_TC_Bit = 0x8,
-	Gi_Interrupt_Bit = 0x8000
-};
-
-enum G02_Interrupt_Enable_Bits {
-	G0_TC_Interrupt_Enable_Bit = 0x40,
-	G0_Gate_Interrupt_Enable_Bit = 0x100
-};
-enum G13_Interrupt_Enable_Bits {
-	G1_TC_Interrupt_Enable_Bit = 0x200,
-	G1_Gate_Interrupt_Enable_Bit = 0x400
-};
-static inline unsigned Gi_Gate_Interrupt_Enable_Bit(unsigned counter_index)
-{
-	unsigned bit;
-
-	if (counter_index % 2)
-		bit = G1_Gate_Interrupt_Enable_Bit;
-	else
-		bit = G0_Gate_Interrupt_Enable_Bit;
-	return bit;
-}
+#define GI_TC_INTERRUPT_ENABLE(x)	(((x) % 2) ? (1 << 9) : (1 << 6))
+#define GI_GATE_INTERRUPT_ENABLE(x)	(((x) % 2) ? (1 << 10) : (1 << 8))
 
 static inline void write_register(struct ni_gpct *counter, unsigned bits,
 				  enum ni_gpct_register reg)
@@ -334,11 +177,9 @@ static inline int ni_tio_counting_mode_r
 	switch (counter_dev->variant) {
 	case ni_gpct_variant_e_series:
 		return 0;
-		break;
 	case ni_gpct_variant_m_series:
 	case ni_gpct_variant_660x:
 		return 1;
-		break;
 	default:
 		BUG();
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl711.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl711.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl711.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl711.c	2014-09-28 17:29:07.000000000 -0400
@@ -206,7 +206,7 @@ static irqreturn_t pcl711_interrupt(int
 	unsigned int data;
 
 	if (!dev->attached) {
-		comedi_error(dev, "spurious interrupt");
+		dev_err(dev->class_dev, "spurious interrupt\n");
 		return IRQ_HANDLED;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl724.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl724.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl724.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl724.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,6 +15,7 @@
  *	    (ADLink) ACL-7124 [acl7124]
  *	    (ADLink) PET-48DIO [pet48dio]
  *	    (WinSystems) PCM-IO48 [pcmio48]
+ *	    (Diamond Systems) ONYX-MM-DIO [onyx-mm-dio]
  * Author: Michal Dobes <dobes@tesnet.cz>
  * Status: untested
  *
@@ -73,6 +74,10 @@ static const struct pcl724_board boardty
 		.name		= "pcmio48",
 		.io_range	= 0x08,
 		.numofports	= 2,	/* 48 DIO channels */
+	}, {
+		.name		= "onyx-mm-dio",
+		.io_range	= 0x10,
+		.numofports	= 2,	/* 48 DIO channels */
 	},
 };
 
@@ -83,14 +88,12 @@ static int pcl724_8255mapped_io(int dir,
 
 	iobase &= 0x0fff;
 
+	outb(port + movport, iobase);
 	if (dir) {
-		outb(port + movport, iobase);
 		outb(data, iobase + 1);
 		return 0;
-	} else {
-		outb(port + movport, iobase);
-		return inb(iobase + 1);
 	}
+	return inb(iobase + 1);
 }
 
 static int pcl724_attach(struct comedi_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl730.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl730.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl730.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl730.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,6 +19,7 @@
  *	    (Advantech) PCL-734 [pcl734]
  *	    (Diamond Systems) OPMM-1616-XT [opmm-1616-xt]
  *	    (Diamond Systems) PEARL-MM-P [prearl-mm-p]
+ *	    (Diamond Systems) IR104-PBF [ir104-pbf]
  * Author: JosÃ© Luis SÃ¡nchez (jsanchezv@teleline.es)
  * Status: untested
  *
@@ -93,6 +94,15 @@
  *
  *     BASE+0  Isolated outputs 0-7 (write)
  *     BASE+1  Isolated outputs 8-15 (write)
+ *
+ * The ir104-pbf board has this register mapping:
+ *
+ *     BASE+0  Isolated outputs 0-7 (write) (read back)
+ *     BASE+1  Isolated outputs 8-15 (write) (read back)
+ *     BASE+2  Isolated outputs 16-19 (write) (read back)
+ *     BASE+4  Isolated inputs 0-7 (read)
+ *     BASE+5  Isolated inputs 8-15 (read)
+ *     BASE+6  Isolated inputs 16-19 (read)
  */
 
 struct pcl730_board {
@@ -100,6 +110,7 @@ struct pcl730_board {
 	unsigned int io_range;
 	unsigned is_pcl725:1;
 	unsigned is_acl7225b:1;
+	unsigned is_ir104:1;
 	unsigned has_readback:1;
 	unsigned has_ttl_io:1;
 	int n_subdevs;
@@ -194,6 +205,13 @@ static const struct pcl730_board pcl730_
 		.io_range	= 0x02,
 		.n_subdevs	= 1,
 		.n_iso_out_chan	= 16,
+	}, {
+		.name		= "ir104-pbf",
+		.io_range	= 0x08,
+		.is_ir104	= 1,
+		.has_readback	= 1,
+		.n_iso_out_chan	= 20,
+		.n_iso_in_chan	= 20,
 	},
 };
 
@@ -292,7 +310,8 @@ static int pcl730_attach(struct comedi_d
 		s->maxdata	= 1;
 		s->range_table	= &range_digital;
 		s->insn_bits	= pcl730_di_insn_bits;
-		s->private	= board->is_acl7225b ? (void *)2 :
+		s->private	= board->is_ir104 ? (void *)4 :
+				  board->is_acl7225b ? (void *)2 :
 				  board->is_pcl725 ? (void *)1 : (void *)0;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl812.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl812.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl812.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl812.c	2014-09-28 17:29:07.000000000 -0400
@@ -985,7 +985,7 @@ static int pcl812_ai_poll(struct comedi_
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	return s->async->buf_write_count - s->async->buf_read_count;
+	return comedi_buf_n_bytes_ready(s);
 }
 
 static int pcl812_ai_cancel(struct comedi_device *dev,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl816.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl816.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl816.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl816.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,10 +130,6 @@ struct pcl816_private {
 	unsigned int ai_cmd_canceled:1;
 };
 
-static int check_channel_list(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      unsigned int *chanlist, unsigned int chanlen);
-
 static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters)
 {
 	struct pcl816_private *devpriv = dev->private;
@@ -363,6 +359,62 @@ static irqreturn_t pcl816_interrupt(int
 	return IRQ_HANDLED;
 }
 
+static int check_channel_list(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      unsigned int *chanlist,
+			      unsigned int chanlen)
+{
+	unsigned int chansegment[16];
+	unsigned int i, nowmustbechan, seglen, segpos;
+
+	/*  correct channel and range number check itself comedi/range.c */
+	if (chanlen < 1) {
+		dev_err(dev->class_dev, "range/channel list is empty!\n");
+		return 0;
+	}
+
+	if (chanlen > 1) {
+		/*  first channel is every time ok */
+		chansegment[0] = chanlist[0];
+		for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
+			/*  we detect loop, this must by finish */
+			    if (chanlist[0] == chanlist[i])
+				break;
+			nowmustbechan =
+			    (CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
+			if (nowmustbechan != CR_CHAN(chanlist[i])) {
+				/*  channel list isn't continuous :-( */
+				dev_dbg(dev->class_dev,
+					"channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
+					i, CR_CHAN(chanlist[i]), nowmustbechan,
+					CR_CHAN(chanlist[0]));
+				return 0;
+			}
+			/*  well, this is next correct channel in list */
+			chansegment[i] = chanlist[i];
+		}
+
+		/*  check whole chanlist */
+		for (i = 0, segpos = 0; i < chanlen; i++) {
+			    if (chanlist[i] != chansegment[i % seglen]) {
+				dev_dbg(dev->class_dev,
+					"bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+					i, CR_CHAN(chansegment[i]),
+					CR_RANGE(chansegment[i]),
+					CR_AREF(chansegment[i]),
+					CR_CHAN(chanlist[i % seglen]),
+					CR_RANGE(chanlist[i % seglen]),
+					CR_AREF(chansegment[i % seglen]));
+				return 0;	/*  chan/gain list is strange */
+			}
+		}
+	} else {
+		seglen = 1;
+	}
+
+	return seglen;	/*  we can serve this with MUX logic */
+}
+
 static int pcl816_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
@@ -516,7 +568,7 @@ static int pcl816_ai_poll(struct comedi_
 
 	cfc_handle_events(dev, s);
 
-	return s->async->buf_write_count - s->async->buf_read_count;
+	return comedi_buf_n_bytes_ready(s);
 }
 
 static int pcl816_ai_cancel(struct comedi_device *dev,
@@ -542,62 +594,6 @@ static int pcl816_ai_cancel(struct comed
 	return 0;
 }
 
-static int
-check_channel_list(struct comedi_device *dev,
-		   struct comedi_subdevice *s, unsigned int *chanlist,
-		   unsigned int chanlen)
-{
-	unsigned int chansegment[16];
-	unsigned int i, nowmustbechan, seglen, segpos;
-
-	/*  correct channel and range number check itself comedi/range.c */
-	if (chanlen < 1) {
-		comedi_error(dev, "range/channel list is empty!");
-		return 0;
-	}
-
-	if (chanlen > 1) {
-		/*  first channel is every time ok */
-		chansegment[0] = chanlist[0];
-		for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
-			/*  we detect loop, this must by finish */
-			    if (chanlist[0] == chanlist[i])
-				break;
-			nowmustbechan =
-			    (CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
-			if (nowmustbechan != CR_CHAN(chanlist[i])) {
-				/*  channel list isn't continuous :-( */
-				dev_dbg(dev->class_dev,
-					"channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
-					i, CR_CHAN(chanlist[i]), nowmustbechan,
-					CR_CHAN(chanlist[0]));
-				return 0;
-			}
-			/*  well, this is next correct channel in list */
-			chansegment[i] = chanlist[i];
-		}
-
-		/*  check whole chanlist */
-		for (i = 0, segpos = 0; i < chanlen; i++) {
-			    if (chanlist[i] != chansegment[i % seglen]) {
-				dev_dbg(dev->class_dev,
-					"bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
-					i, CR_CHAN(chansegment[i]),
-					CR_RANGE(chansegment[i]),
-					CR_AREF(chansegment[i]),
-					CR_CHAN(chanlist[i % seglen]),
-					CR_RANGE(chanlist[i % seglen]),
-					CR_AREF(chansegment[i % seglen]));
-				return 0;	/*  chan/gain list is strange */
-			}
-		}
-	} else {
-		seglen = 1;
-	}
-
-	return seglen;	/*  we can serve this with MUX logic */
-}
-
 static int pcl816_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl818.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl818.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcl818.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcl818.c	2014-09-28 17:29:07.000000000 -0400
@@ -551,7 +551,7 @@ static void pcl818_handle_eoc(struct com
 	unsigned int val;
 
 	if (pcl818_ai_eoc(dev, s, NULL, 0)) {
-		comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
+		dev_err(dev->class_dev, "A/D mode1/3 IRQ without DRDY!\n");
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		return;
 	}
@@ -608,13 +608,14 @@ static void pcl818_handle_fifo(struct co
 	status = inb(dev->iobase + PCL818_FI_STATUS);
 
 	if (status & 4) {
-		comedi_error(dev, "A/D mode1/3 FIFO overflow!");
+		dev_err(dev->class_dev, "A/D mode1/3 FIFO overflow!\n");
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		return;
 	}
 
 	if (status & 1) {
-		comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
+		dev_err(dev->class_dev,
+			"A/D mode1/3 FIFO interrupt without data!\n");
 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		return;
 	}
@@ -682,7 +683,7 @@ static int check_channel_list(struct com
 
 	/* correct channel and range number check itself comedi/range.c */
 	if (n_chan < 1) {
-		comedi_error(dev, "range/channel list is empty!");
+		dev_err(dev->class_dev, "range/channel list is empty!\n");
 		return 0;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcm3724.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcm3724.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcm3724.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcm3724.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ Copy/pasted/hacked from pcm724.c
 
 #include "8255.h"
 
-#define PCM3724_SIZE   16
 #define SIZE_8255	4
 
 #define BUF_C0 0x1
@@ -66,19 +65,6 @@ struct priv_pcm3724 {
 	int dio_2;
 };
 
-static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
-{
-	unsigned long iobase = arg;
-	unsigned char inbres;
-	if (dir) {
-		outb(data, iobase + port);
-		return 0;
-	} else {
-		inbres = inb(iobase + port);
-		return inbres;
-	}
-}
-
 static int compute_buffer(int config, int devno, struct comedi_subdevice *s)
 {
 	/* 1 in io_bits indicates output */
@@ -215,7 +201,7 @@ static int pcm3724_attach(struct comedi_
 	if (!priv)
 		return -ENOMEM;
 
-	ret = comedi_request_region(dev, it->options[0], PCM3724_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
@@ -225,7 +211,7 @@ static int pcm3724_attach(struct comedi_
 
 	for (i = 0; i < dev->n_subdevices; i++) {
 		s = &dev->subdevices[i];
-		ret = subdev_8255_init(dev, s, subdev_8255_cb,
+		ret = subdev_8255_init(dev, s, NULL,
 				       dev->iobase + SIZE_8255 * i);
 		if (ret)
 			return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcmuio.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcmuio.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/pcmuio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/pcmuio.c	2014-09-28 17:29:07.000000000 -0400
@@ -333,6 +333,7 @@ static void pcmuio_handle_intr_subdev(st
 
 	for (i = 0; i < cmd->chanlist_len; i++) {
 		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
 		if (triggered & (1 << chan))
 			val |= (1 << i);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/quatech_daqp_cs.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/quatech_daqp_cs.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/quatech_daqp_cs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/quatech_daqp_cs.c	2014-09-28 17:29:07.000000000 -0400
@@ -351,7 +351,7 @@ static int daqp_ai_insn_read(struct come
  * time that the device will use.
  */
 
-static int daqp_ns_to_timer(unsigned int *ns, int round)
+static int daqp_ns_to_timer(unsigned int *ns, unsigned int flags)
 {
 	int timer;
 
@@ -436,13 +436,13 @@ static int daqp_ai_cmdtest(struct comedi
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		daqp_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		daqp_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 	}
 
@@ -488,15 +488,13 @@ static int daqp_ai_cmd(struct comedi_dev
 	 */
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		counter = daqp_ns_to_timer(&cmd->convert_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		counter = daqp_ns_to_timer(&cmd->convert_arg, cmd->flags);
 		outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW);
 		outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID);
 		outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH);
 		scanlist_start_on_every_entry = 1;
 	} else {
-		counter = daqp_ns_to_timer(&cmd->scan_begin_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		counter = daqp_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
 		outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW);
 		outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID);
 		outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/rtd520.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/rtd520.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/rtd520.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/rtd520.c	2014-09-28 17:29:07.000000000 -0400
@@ -373,7 +373,6 @@ static const struct rtd_boardinfo rtd520
 
 struct rtd_private {
 	/* memory mapped board structures */
-	void __iomem *las0;
 	void __iomem *las1;
 	void __iomem *lcfg;
 
@@ -397,11 +396,11 @@ struct rtd_private {
   Note: you have to check if the value is larger than the counter range!
 */
 static int rtd_ns_to_timer_base(unsigned int *nanosec,
-				int round_mode, int base)
+				unsigned int flags, int base)
 {
 	int divider;
 
-	switch (round_mode) {
+	switch (flags & TRIG_ROUND_MASK) {
 	case TRIG_ROUND_NEAREST:
 	default:
 		divider = (*nanosec + base / 2) / base;
@@ -428,9 +427,9 @@ static int rtd_ns_to_timer_base(unsigned
   return the proper counter value (divider-1) for the internal clock.
   Sets the original period to be the true value.
 */
-static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+static int rtd_ns_to_timer(unsigned int *ns, unsigned int flags)
 {
-	return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
+	return rtd_ns_to_timer_base(ns, flags, RTD_CLOCK_BASE);
 }
 
 /*
@@ -490,21 +489,19 @@ static unsigned short rtd_convert_chan_g
 static void rtd_load_channelgain_list(struct comedi_device *dev,
 				      unsigned int n_chan, unsigned int *list)
 {
-	struct rtd_private *devpriv = dev->private;
-
 	if (n_chan > 1) {	/* setup channel gain table */
 		int ii;
 
-		writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
-		writel(1, devpriv->las0 + LAS0_CGT_ENABLE);
+		writel(0, dev->mmio + LAS0_CGT_CLEAR);
+		writel(1, dev->mmio + LAS0_CGT_ENABLE);
 		for (ii = 0; ii < n_chan; ii++) {
 			writel(rtd_convert_chan_gain(dev, list[ii], ii),
-				devpriv->las0 + LAS0_CGT_WRITE);
+			       dev->mmio + LAS0_CGT_WRITE);
 		}
 	} else {		/* just use the channel gain latch */
-		writel(0, devpriv->las0 + LAS0_CGT_ENABLE);
+		writel(0, dev->mmio + LAS0_CGT_ENABLE);
 		writel(rtd_convert_chan_gain(dev, list[0], 0),
-			devpriv->las0 + LAS0_CGL_WRITE);
+		       dev->mmio + LAS0_CGL_WRITE);
 	}
 }
 
@@ -512,23 +509,22 @@ static void rtd_load_channelgain_list(st
 empty status flag clears */
 static int rtd520_probe_fifo_depth(struct comedi_device *dev)
 {
-	struct rtd_private *devpriv = dev->private;
 	unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
 	unsigned i;
 	static const unsigned limit = 0x2000;
 	unsigned fifo_size = 0;
 
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
 	rtd_load_channelgain_list(dev, 1, &chanspec);
 	/* ADC conversion trigger source: SOFTWARE */
-	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
+	writel(0, dev->mmio + LAS0_ADC_CONVERSION);
 	/* convert  samples */
 	for (i = 0; i < limit; ++i) {
 		unsigned fifo_status;
 		/* trigger conversion */
-		writew(0, devpriv->las0 + LAS0_ADC);
+		writew(0, dev->mmio + LAS0_ADC);
 		udelay(1);
-		fifo_status = readl(devpriv->las0 + LAS0_ADC);
+		fifo_status = readl(dev->mmio + LAS0_ADC);
 		if ((fifo_status & FS_ADC_HEMPTY) == 0) {
 			fifo_size = 2 * i;
 			break;
@@ -538,7 +534,7 @@ static int rtd520_probe_fifo_depth(struc
 		dev_info(dev->class_dev, "failed to probe fifo size.\n");
 		return -EIO;
 	}
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
 	if (fifo_size != 0x400 && fifo_size != 0x2000) {
 		dev_info(dev->class_dev,
 			 "unexpected fifo size of %i, expected 1024 or 8192.\n",
@@ -553,10 +549,9 @@ static int rtd_ai_eoc(struct comedi_devi
 		      struct comedi_insn *insn,
 		      unsigned long context)
 {
-	struct rtd_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readl(devpriv->las0 + LAS0_ADC);
+	status = readl(dev->mmio + LAS0_ADC);
 	if (status & FS_ADC_NOT_EMPTY)
 		return 0;
 	return -EBUSY;
@@ -571,19 +566,19 @@ static int rtd_ai_rinsn(struct comedi_de
 	int n;
 
 	/* clear any old fifo data */
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
 
 	/* write channel to multiplexer and clear channel gain table */
 	rtd_load_channelgain_list(dev, 1, &insn->chanspec);
 
 	/* ADC conversion trigger source: SOFTWARE */
-	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
+	writel(0, dev->mmio + LAS0_ADC_CONVERSION);
 
 	/* convert n samples */
 	for (n = 0; n < insn->n; n++) {
 		unsigned short d;
 		/* trigger conversion */
-		writew(0, devpriv->las0 + LAS0_ADC);
+		writew(0, dev->mmio + LAS0_ADC);
 
 		ret = comedi_timeout(dev, s, insn, rtd_ai_eoc, 0);
 		if (ret)
@@ -645,7 +640,7 @@ static int ai_read_dregs(struct comedi_d
 {
 	struct rtd_private *devpriv = dev->private;
 
-	while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
+	while (readl(dev->mmio + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
 		unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 
 		if (0 == devpriv->ai_count) {	/* done */
@@ -685,12 +680,12 @@ static irqreturn_t rtd_interrupt(int irq
 	if (!dev->attached)
 		return IRQ_NONE;
 
-	fifo_status = readl(devpriv->las0 + LAS0_ADC);
+	fifo_status = readl(dev->mmio + LAS0_ADC);
 	/* check for FIFO full, this automatically halts the ADC! */
 	if (!(fifo_status & FS_ADC_NOT_FULL))	/* 0 -> full */
 		goto xfer_abort;
 
-	status = readw(devpriv->las0 + LAS0_IT);
+	status = readw(dev->mmio + LAS0_IT);
 	/* if interrupt was not caused by our board, or handled above */
 	if (0 == status)
 		return IRQ_HANDLED;
@@ -725,30 +720,30 @@ static irqreturn_t rtd_interrupt(int irq
 		}
 	}
 
-	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
+	overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff;
 	if (overrun)
 		goto xfer_abort;
 
 	/* clear the interrupt */
-	writew(status, devpriv->las0 + LAS0_CLEAR);
-	readw(devpriv->las0 + LAS0_CLEAR);
+	writew(status, dev->mmio + LAS0_CLEAR);
+	readw(dev->mmio + LAS0_CLEAR);
 	return IRQ_HANDLED;
 
 xfer_abort:
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
 	s->async->events |= COMEDI_CB_ERROR;
 	devpriv->ai_count = 0;	/* stop and don't transfer any more */
 	/* fall into xfer_done */
 
 xfer_done:
 	/* pacer stop source: SOFTWARE */
-	writel(0, devpriv->las0 + LAS0_PACER_STOP);
-	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
-	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	writew(0, devpriv->las0 + LAS0_IT);
+	writel(0, dev->mmio + LAS0_PACER_STOP);
+	writel(0, dev->mmio + LAS0_PACER);	/* stop pacer */
+	writel(0, dev->mmio + LAS0_ADC_CONVERSION);
+	writew(0, dev->mmio + LAS0_IT);
 
 	if (devpriv->ai_count > 0) {	/* there shouldn't be anything left */
-		fifo_status = readl(devpriv->las0 + LAS0_ADC);
+		fifo_status = readl(dev->mmio + LAS0_ADC);
 		ai_read_dregs(dev, s);	/* read anything left in FIFO */
 	}
 
@@ -756,12 +751,12 @@ xfer_done:
 	comedi_event(dev, s);
 
 	/* clear the interrupt */
-	status = readw(devpriv->las0 + LAS0_IT);
-	writew(status, devpriv->las0 + LAS0_CLEAR);
-	readw(devpriv->las0 + LAS0_CLEAR);
+	status = readw(dev->mmio + LAS0_IT);
+	writew(status, dev->mmio + LAS0_CLEAR);
+	readw(dev->mmio + LAS0_CLEAR);
 
-	fifo_status = readl(devpriv->las0 + LAS0_ADC);
-	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
+	fifo_status = readl(dev->mmio + LAS0_ADC);
+	overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff;
 
 	return IRQ_HANDLED;
 }
@@ -895,13 +890,13 @@ static int rtd_ai_cmdtest(struct comedi_
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		rtd_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		rtd_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -931,12 +926,12 @@ static int rtd_ai_cmd(struct comedi_devi
 
 	/* stop anything currently running */
 	/* pacer stop source: SOFTWARE */
-	writel(0, devpriv->las0 + LAS0_PACER_STOP);
-	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
-	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	writew(0, devpriv->las0 + LAS0_IT);
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
-	writel(0, devpriv->las0 + LAS0_OVERRUN);
+	writel(0, dev->mmio + LAS0_PACER_STOP);
+	writel(0, dev->mmio + LAS0_PACER);	/* stop pacer */
+	writel(0, dev->mmio + LAS0_ADC_CONVERSION);
+	writew(0, dev->mmio + LAS0_IT);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_OVERRUN);
 
 	/* start configuration */
 	/* load channel list and reset CGT */
@@ -945,18 +940,18 @@ static int rtd_ai_cmd(struct comedi_devi
 	/* setup the common case and override if needed */
 	if (cmd->chanlist_len > 1) {
 		/* pacer start source: SOFTWARE */
-		writel(0, devpriv->las0 + LAS0_PACER_START);
+		writel(0, dev->mmio + LAS0_PACER_START);
 		/* burst trigger source: PACER */
-		writel(1, devpriv->las0 + LAS0_BURST_START);
+		writel(1, dev->mmio + LAS0_BURST_START);
 		/* ADC conversion trigger source: BURST */
-		writel(2, devpriv->las0 + LAS0_ADC_CONVERSION);
+		writel(2, dev->mmio + LAS0_ADC_CONVERSION);
 	} else {		/* single channel */
 		/* pacer start source: SOFTWARE */
-		writel(0, devpriv->las0 + LAS0_PACER_START);
+		writel(0, dev->mmio + LAS0_PACER_START);
 		/* ADC conversion trigger source: PACER */
-		writel(1, devpriv->las0 + LAS0_ADC_CONVERSION);
+		writel(1, dev->mmio + LAS0_ADC_CONVERSION);
 	}
-	writel((devpriv->fifosz / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT);
+	writel((devpriv->fifosz / 2 - 1) & 0xffff, dev->mmio + LAS0_ACNT);
 
 	if (TRIG_TIMER == cmd->scan_begin_src) {
 		/* scan_begin_arg is in nanoseconds */
@@ -993,16 +988,16 @@ static int rtd_ai_cmd(struct comedi_devi
 		} else {
 			/* interrupt for each transfer */
 			writel((devpriv->xfer_count - 1) & 0xffff,
-				devpriv->las0 + LAS0_ACNT);
+			       dev->mmio + LAS0_ACNT);
 		}
 	} else {		/* unknown timing, just use 1/2 FIFO */
 		devpriv->xfer_count = 0;
 		devpriv->flags &= ~SEND_EOS;
 	}
 	/* pacer clock source: INTERNAL 8MHz */
-	writel(1, devpriv->las0 + LAS0_PACER_SELECT);
+	writel(1, dev->mmio + LAS0_PACER_SELECT);
 	/* just interrupt, don't stop */
-	writel(1, devpriv->las0 + LAS0_ACNT_STOP_ENABLE);
+	writel(1, dev->mmio + LAS0_ACNT_STOP_ENABLE);
 
 	/* BUG??? these look like enumerated values, but they are bit fields */
 
@@ -1027,13 +1022,13 @@ static int rtd_ai_cmd(struct comedi_devi
 		timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
 					TRIG_ROUND_NEAREST);
 		/* set PACER clock */
-		writel(timer & 0xffffff, devpriv->las0 + LAS0_PCLK);
+		writel(timer & 0xffffff, dev->mmio + LAS0_PCLK);
 
 		break;
 
 	case TRIG_EXT:
 		/* pacer start source: EXTERNAL */
-		writel(1, devpriv->las0 + LAS0_PACER_START);
+		writel(1, dev->mmio + LAS0_PACER_START);
 		break;
 	}
 
@@ -1045,33 +1040,32 @@ static int rtd_ai_cmd(struct comedi_devi
 			timer = rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_NEAREST);
 			/* setup BURST clock */
-			writel(timer & 0x3ff, devpriv->las0 + LAS0_BCLK);
+			writel(timer & 0x3ff, dev->mmio + LAS0_BCLK);
 		}
 
 		break;
 
 	case TRIG_EXT:		/* external */
 		/* burst trigger source: EXTERNAL */
-		writel(2, devpriv->las0 + LAS0_BURST_START);
+		writel(2, dev->mmio + LAS0_BURST_START);
 		break;
 	}
 	/* end configuration */
 
 	/* This doesn't seem to work.  There is no way to clear an interrupt
 	   that the priority controller has queued! */
-	writew(~0, devpriv->las0 + LAS0_CLEAR);
-	readw(devpriv->las0 + LAS0_CLEAR);
+	writew(~0, dev->mmio + LAS0_CLEAR);
+	readw(dev->mmio + LAS0_CLEAR);
 
 	/* TODO: allow multiple interrupt sources */
-	if (devpriv->xfer_count > 0) {	/* transfer every N samples */
-		writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
-	} else {		/* 1/2 FIFO transfers */
-		writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
-	}
+	if (devpriv->xfer_count > 0)	/* transfer every N samples */
+		writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT);
+	else				/* 1/2 FIFO transfers */
+		writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT);
 
 	/* BUG: start_src is ASSUMED to be TRIG_NOW */
 	/* BUG? it seems like things are running before the "start" */
-	readl(devpriv->las0 + LAS0_PACER);	/* start pacer */
+	readl(dev->mmio + LAS0_PACER);	/* start pacer */
 	return 0;
 }
 
@@ -1085,13 +1079,13 @@ static int rtd_ai_cancel(struct comedi_d
 	u16 status;
 
 	/* pacer stop source: SOFTWARE */
-	writel(0, devpriv->las0 + LAS0_PACER_STOP);
-	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
-	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	writew(0, devpriv->las0 + LAS0_IT);
+	writel(0, dev->mmio + LAS0_PACER_STOP);
+	writel(0, dev->mmio + LAS0_PACER);	/* stop pacer */
+	writel(0, dev->mmio + LAS0_ADC_CONVERSION);
+	writew(0, dev->mmio + LAS0_IT);
 	devpriv->ai_count = 0;	/* stop and don't transfer any more */
-	status = readw(devpriv->las0 + LAS0_IT);
-	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
+	status = readw(dev->mmio + LAS0_IT);
+	overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff;
 	return 0;
 }
 
@@ -1100,12 +1094,11 @@ static int rtd_ao_eoc(struct comedi_devi
 		      struct comedi_insn *insn,
 		      unsigned long context)
 {
-	struct rtd_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int bit = (chan == 0) ? FS_DAC1_NOT_EMPTY : FS_DAC2_NOT_EMPTY;
 	unsigned int status;
 
-	status = readl(devpriv->las0 + LAS0_ADC);
+	status = readl(dev->mmio + LAS0_ADC);
 	if (status & bit)
 		return 0;
 	return -EBUSY;
@@ -1122,8 +1115,8 @@ static int rtd_ao_winsn(struct comedi_de
 	int ret;
 
 	/* Configure the output range (table index matches the range values) */
-	writew(range & 7, devpriv->las0 +
-		((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL));
+	writew(range & 7,
+	       dev->mmio + ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL));
 
 	/* Writing a list of values to an AO channel is probably not
 	 * very useful, but that's how the interface is defined. */
@@ -1143,8 +1136,7 @@ static int rtd_ao_winsn(struct comedi_de
 		/* a typical programming sequence */
 		writew(val, devpriv->las1 +
 			((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO));
-		writew(0, devpriv->las0 +
-			((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
+		writew(0, dev->mmio + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
 
 		devpriv->ao_readback[chan] = data[i];
 
@@ -1179,12 +1171,10 @@ static int rtd_dio_insn_bits(struct come
 			     struct comedi_insn *insn,
 			     unsigned int *data)
 {
-	struct rtd_private *devpriv = dev->private;
-
 	if (comedi_dio_update_state(s, data))
-		writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0);
+		writew(s->state & 0xff, dev->mmio + LAS0_DIO0);
 
-	data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
+	data[1] = readw(dev->mmio + LAS0_DIO0) & 0xff;
 
 	return insn->n;
 }
@@ -1194,7 +1184,6 @@ static int rtd_dio_insn_config(struct co
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	struct rtd_private *devpriv = dev->private;
 	int ret;
 
 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
@@ -1204,11 +1193,11 @@ static int rtd_dio_insn_config(struct co
 	/* TODO support digital match interrupts and strobes */
 
 	/* set direction */
-	writew(0x01, devpriv->las0 + LAS0_DIO_STATUS);
-	writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL);
+	writew(0x01, dev->mmio + LAS0_DIO_STATUS);
+	writew(s->io_bits & 0xff, dev->mmio + LAS0_DIO0_CTRL);
 
 	/* clear interrupts */
-	writew(0x00, devpriv->las0 + LAS0_DIO_STATUS);
+	writew(0x00, dev->mmio + LAS0_DIO_STATUS);
 
 	/* port1 can only be all input or all output */
 
@@ -1221,12 +1210,12 @@ static void rtd_reset(struct comedi_devi
 {
 	struct rtd_private *devpriv = dev->private;
 
-	writel(0, devpriv->las0 + LAS0_BOARD_RESET);
+	writel(0, dev->mmio + LAS0_BOARD_RESET);
 	udelay(100);		/* needed? */
 	writel(0, devpriv->lcfg + PLX_INTRCS_REG);
-	writew(0, devpriv->las0 + LAS0_IT);
-	writew(~0, devpriv->las0 + LAS0_CLEAR);
-	readw(devpriv->las0 + LAS0_CLEAR);
+	writew(0, dev->mmio + LAS0_IT);
+	writew(~0, dev->mmio + LAS0_CLEAR);
+	readw(dev->mmio + LAS0_CLEAR);
 }
 
 /*
@@ -1235,21 +1224,19 @@ static void rtd_reset(struct comedi_devi
  */
 static void rtd_init_board(struct comedi_device *dev)
 {
-	struct rtd_private *devpriv = dev->private;
-
 	rtd_reset(dev);
 
-	writel(0, devpriv->las0 + LAS0_OVERRUN);
-	writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
-	writel(0, devpriv->las0 + LAS0_DAC1_RESET);
-	writel(0, devpriv->las0 + LAS0_DAC2_RESET);
+	writel(0, dev->mmio + LAS0_OVERRUN);
+	writel(0, dev->mmio + LAS0_CGT_CLEAR);
+	writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
+	writel(0, dev->mmio + LAS0_DAC1_RESET);
+	writel(0, dev->mmio + LAS0_DAC2_RESET);
 	/* clear digital IO fifo */
-	writew(0, devpriv->las0 + LAS0_DIO_STATUS);
-	writeb((0 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
-	writeb((1 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
-	writeb((2 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
-	writeb((3 << 6) | 0x00, devpriv->las0 + LAS0_UTC_CTRL);
+	writew(0, dev->mmio + LAS0_DIO_STATUS);
+	writeb((0 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL);
+	writeb((1 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL);
+	writeb((2 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL);
+	writeb((3 << 6) | 0x00, dev->mmio + LAS0_UTC_CTRL);
 	/* TODO: set user out source ??? */
 }
 
@@ -1292,10 +1279,10 @@ static int rtd_auto_attach(struct comedi
 	if (ret)
 		return ret;
 
-	devpriv->las0 = pci_ioremap_bar(pcidev, 2);
+	dev->mmio = pci_ioremap_bar(pcidev, 2);
 	devpriv->las1 = pci_ioremap_bar(pcidev, 3);
 	devpriv->lcfg = pci_ioremap_bar(pcidev, 0);
-	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
+	if (!dev->mmio || !devpriv->las1 || !devpriv->lcfg)
 		return -ENOMEM;
 
 	rtd_pci_latency_quirk(dev, pcidev);
@@ -1375,7 +1362,7 @@ static void rtd_detach(struct comedi_dev
 
 	if (devpriv) {
 		/* Shut down any board ops by resetting it */
-		if (devpriv->las0 && devpriv->lcfg)
+		if (dev->mmio && devpriv->lcfg)
 			rtd_reset(dev);
 		if (dev->irq) {
 			writel(readl(devpriv->lcfg + PLX_INTRCS_REG) &
@@ -1383,8 +1370,8 @@ static void rtd_detach(struct comedi_dev
 				devpriv->lcfg + PLX_INTRCS_REG);
 			free_irq(dev->irq, dev);
 		}
-		if (devpriv->las0)
-			iounmap(devpriv->las0);
+		if (dev->mmio)
+			iounmap(dev->mmio);
 		if (devpriv->las1)
 			iounmap(devpriv->las1);
 		if (devpriv->lcfg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/rti800.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/rti800.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/rti800.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/rti800.c	2014-09-28 17:29:07.000000000 -0400
@@ -81,8 +81,6 @@
 #define RTI800_9513A_CNTRL	0x0d
 #define RTI800_9513A_STATUS	0x0d
 
-#define RTI800_IOSIZE		0x10
-
 static const struct comedi_lrange range_rti800_ai_10_bipolar = {
 	4, {
 		BIP_RANGE(10),
@@ -281,7 +279,7 @@ static int rti800_attach(struct comedi_d
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], RTI800_IOSIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x10);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s526.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s526.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s526.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s526.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,13 +40,10 @@ comedi_config /dev/comedi0 s526 0x2C0,0x
 #include "../comedidev.h"
 #include <asm/byteorder.h>
 
-#define S526_SIZE 64
-
 #define S526_START_AI_CONV	0
 #define S526_AI_READ		0
 
 /* Ports */
-#define S526_IOSIZE 0x40
 #define S526_NUM_PORTS 27
 
 /* registers */
@@ -345,7 +342,6 @@ static int s526_gpct_insn_config(struct
 
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	return insn->n;
@@ -557,7 +553,7 @@ static int s526_attach(struct comedi_dev
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], S526_IOSIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x40);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s626.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s626.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s626.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s626.c	2014-09-28 17:29:07.000000000 -0400
@@ -77,7 +77,6 @@ struct s626_buffer_dma {
 };
 
 struct s626_private {
-	void __iomem *mmio;
 	uint8_t ai_cmd_running;		/* ai_cmd is running */
 	uint8_t ai_continuous;		/* continuous acquisition */
 	int ai_sample_count;		/* number of samples to acquire */
@@ -102,60 +101,9 @@ struct s626_private {
 	unsigned int ao_readback[S626_DAC_CHANNELS];
 };
 
-/* COUNTER OBJECT ------------------------------------------------ */
-struct s626_enc_info {
-	/* Pointers to functions that differ for A and B counters: */
-	/* Return clock enable. */
-	uint16_t (*get_enable)(struct comedi_device *dev,
-			      const struct s626_enc_info *k);
-	/* Return interrupt source. */
-	uint16_t (*get_int_src)(struct comedi_device *dev,
-			       const struct s626_enc_info *k);
-	/* Return preload trigger source. */
-	uint16_t (*get_load_trig)(struct comedi_device *dev,
-				 const struct s626_enc_info *k);
-	/* Return standardized operating mode. */
-	uint16_t (*get_mode)(struct comedi_device *dev,
-			    const struct s626_enc_info *k);
-	/* Generate soft index strobe. */
-	void (*pulse_index)(struct comedi_device *dev,
-			    const struct s626_enc_info *k);
-	/* Program clock enable. */
-	void (*set_enable)(struct comedi_device *dev,
-			   const struct s626_enc_info *k, uint16_t enab);
-	/* Program interrupt source. */
-	void (*set_int_src)(struct comedi_device *dev,
-			    const struct s626_enc_info *k, uint16_t int_source);
-	/* Program preload trigger source. */
-	void (*set_load_trig)(struct comedi_device *dev,
-			      const struct s626_enc_info *k, uint16_t trig);
-	/* Program standardized operating mode. */
-	void (*set_mode)(struct comedi_device *dev,
-			 const struct s626_enc_info *k, uint16_t setup,
-			 uint16_t disable_int_src);
-	/* Reset event capture flags. */
-	void (*reset_cap_flags)(struct comedi_device *dev,
-				const struct s626_enc_info *k);
-
-	uint16_t my_cra;	/* address of CRA register */
-	uint16_t my_crb;	/* address of CRB register */
-	uint16_t my_latch_lsw;	/* address of Latch least-significant-word
-				 * register */
-	uint16_t my_event_bits[4]; /* bit translations for IntSrc -->RDMISC2 */
-};
-
 /* Counter overflow/index event flag masks for RDMISC2. */
 #define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
 #define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
-#define S626_EVBITS(C)	{ 0, S626_OVERMASK(C), S626_INDXMASK(C), \
-			  S626_OVERMASK(C) | S626_INDXMASK(C) }
-
-/*
- * Translation table to map IntSrc into equivalent RDMISC2 event flag  bits.
- * static const uint16_t s626_event_bits[][4] =
- *     { S626_EVBITS(0), S626_EVBITS(1), S626_EVBITS(2), S626_EVBITS(3),
- *       S626_EVBITS(4), S626_EVBITS(5) };
- */
 
 /*
  * Enable/disable a function or test status bit(s) that are accessed
@@ -164,29 +112,25 @@ struct s626_enc_info {
 static void s626_mc_enable(struct comedi_device *dev,
 			   unsigned int cmd, unsigned int reg)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int val = (cmd << 16) | cmd;
 
 	mmiowb();
-	writel(val, devpriv->mmio + reg);
+	writel(val, dev->mmio + reg);
 }
 
 static void s626_mc_disable(struct comedi_device *dev,
 			    unsigned int cmd, unsigned int reg)
 {
-	struct s626_private *devpriv = dev->private;
-
-	writel(cmd << 16 , devpriv->mmio + reg);
+	writel(cmd << 16 , dev->mmio + reg);
 	mmiowb();
 }
 
 static bool s626_mc_test(struct comedi_device *dev,
 			 unsigned int cmd, unsigned int reg)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int val;
 
-	val = readl(devpriv->mmio + reg);
+	val = readl(dev->mmio + reg);
 
 	return (val & cmd) ? true : false;
 }
@@ -208,7 +152,6 @@ static const struct comedi_lrange s626_r
  */
 static void s626_debi_transfer(struct comedi_device *dev)
 {
-	struct s626_private *devpriv = dev->private;
 	static const int timeout = 10000;
 	int i;
 
@@ -225,17 +168,17 @@ static void s626_debi_transfer(struct co
 		udelay(1);
 	}
 	if (i == timeout)
-		comedi_error(dev,
-			"Timeout while uploading to DEBI control register.");
+		dev_err(dev->class_dev,
+			"Timeout while uploading to DEBI control register\n");
 
 	/* Wait until DEBI transfer is done */
 	for (i = 0; i < timeout; i++) {
-		if (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_DEBI_S))
+		if (!(readl(dev->mmio + S626_P_PSR) & S626_PSR_DEBI_S))
 			break;
 		udelay(1);
 	}
 	if (i == timeout)
-		comedi_error(dev, "DEBI transfer timeout.");
+		dev_err(dev->class_dev, "DEBI transfer timeout\n");
 }
 
 /*
@@ -243,15 +186,13 @@ static void s626_debi_transfer(struct co
  */
 static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr)
 {
-	struct s626_private *devpriv = dev->private;
-
 	/* Set up DEBI control register value in shadow RAM */
-	writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD);
+	writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
 
 	/*  Execute the DEBI transfer. */
 	s626_debi_transfer(dev);
 
-	return readl(devpriv->mmio + S626_P_DEBIAD);
+	return readl(dev->mmio + S626_P_DEBIAD);
 }
 
 /*
@@ -260,11 +201,9 @@ static uint16_t s626_debi_read(struct co
 static void s626_debi_write(struct comedi_device *dev, uint16_t addr,
 			    uint16_t wdata)
 {
-	struct s626_private *devpriv = dev->private;
-
 	/* Set up DEBI control register value in shadow RAM */
-	writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD);
-	writel(wdata, devpriv->mmio + S626_P_DEBIAD);
+	writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
+	writel(wdata, dev->mmio + S626_P_DEBIAD);
 
 	/*  Execute the DEBI transfer. */
 	s626_debi_transfer(dev);
@@ -278,18 +217,17 @@ static void s626_debi_write(struct comed
 static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
 			      unsigned int mask, unsigned int wdata)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int val;
 
 	addr &= 0xffff;
-	writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD);
+	writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
 	s626_debi_transfer(dev);
 
-	writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD);
-	val = readl(devpriv->mmio + S626_P_DEBIAD);
+	writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
+	val = readl(dev->mmio + S626_P_DEBIAD);
 	val &= mask;
 	val |= wdata;
-	writel(val & 0xffff, devpriv->mmio + S626_P_DEBIAD);
+	writel(val & 0xffff, dev->mmio + S626_P_DEBIAD);
 	s626_debi_transfer(dev);
 }
 
@@ -310,12 +248,11 @@ static int s626_i2c_handshake_eoc(struct
 
 static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int ctrl;
 	int ret;
 
 	/* Write I2C command to I2C Transfer Control shadow register */
-	writel(val, devpriv->mmio + S626_P_I2CCTRL);
+	writel(val, dev->mmio + S626_P_I2CCTRL);
 
 	/*
 	 * Upload I2C shadow registers into working registers and
@@ -328,7 +265,7 @@ static int s626_i2c_handshake(struct com
 
 	/* Wait until I2C bus transfer is finished or an error occurs */
 	do {
-		ctrl = readl(devpriv->mmio + S626_P_I2CCTRL);
+		ctrl = readl(dev->mmio + S626_P_I2CCTRL);
 	} while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY);
 
 	/* Return non-zero if I2C error occurred */
@@ -366,7 +303,7 @@ static uint8_t s626_i2c_read(struct come
 		/* Abort function and declare error if handshake failed. */
 		return 0;
 
-	return (readl(devpriv->mmio + S626_P_I2CCTRL) >> 16) & 0xff;
+	return (readl(dev->mmio + S626_P_I2CCTRL) >> 16) & 0xff;
 }
 
 /* ***********  DAC FUNCTIONS *********** */
@@ -391,27 +328,26 @@ static int s626_send_dac_eoc(struct come
 			     struct comedi_insn *insn,
 			     unsigned long context)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int status;
 
 	switch (context) {
 	case s626_send_dac_wait_not_mc1_a2out:
-		status = readl(devpriv->mmio + S626_P_MC1);
+		status = readl(dev->mmio + S626_P_MC1);
 		if (!(status & S626_MC1_A2OUT))
 			return 0;
 		break;
 	case s626_send_dac_wait_ssr_af2_out:
-		status = readl(devpriv->mmio + S626_P_SSR);
+		status = readl(dev->mmio + S626_P_SSR);
 		if (status & S626_SSR_AF2_OUT)
 			return 0;
 		break;
 	case s626_send_dac_wait_fb_buffer2_msb_00:
-		status = readl(devpriv->mmio + S626_P_FB_BUFFER2);
+		status = readl(dev->mmio + S626_P_FB_BUFFER2);
 		if (!(status & 0xff000000))
 			return 0;
 		break;
 	case s626_send_dac_wait_fb_buffer2_msb_ff:
-		status = readl(devpriv->mmio + S626_P_FB_BUFFER2);
+		status = readl(dev->mmio + S626_P_FB_BUFFER2);
 		if (status & 0xff000000)
 			return 0;
 		break;
@@ -448,7 +384,7 @@ static int s626_send_dac(struct comedi_d
 	/* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */
 
 	/* Copy DAC setpoint value to DAC's output DMA buffer. */
-	/* writel(val, devpriv->mmio + (uint32_t)devpriv->dac_wbuf); */
+	/* writel(val, dev->mmio + (uint32_t)devpriv->dac_wbuf); */
 	*devpriv->dac_wbuf = val;
 
 	/*
@@ -466,7 +402,7 @@ static int s626_send_dac(struct comedi_d
 	 * other FIFO underflow/overflow flags). When set, this flag
 	 * will indicate that we have emerged from slot 0.
 	 */
-	writel(S626_ISR_AFOU, devpriv->mmio + S626_P_ISR);
+	writel(S626_ISR_AFOU, dev->mmio + S626_P_ISR);
 
 	/*
 	 * Wait for the DMA transfer to finish so that there will be data
@@ -478,7 +414,7 @@ static int s626_send_dac(struct comedi_d
 	ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
 			     s626_send_dac_wait_not_mc1_a2out);
 	if (ret) {
-		comedi_error(dev, "DMA transfer timeout.");
+		dev_err(dev->class_dev, "DMA transfer timeout\n");
 		return ret;
 	}
 
@@ -491,7 +427,7 @@ static int s626_send_dac(struct comedi_d
 	 * detection.
 	 */
 	writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2,
-	       devpriv->mmio + S626_VECTPORT(0));
+	       dev->mmio + S626_VECTPORT(0));
 
 	/*
 	 * Wait for slot 1 to execute to ensure that the Packet will be
@@ -503,7 +439,8 @@ static int s626_send_dac(struct comedi_d
 	ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
 			     s626_send_dac_wait_ssr_af2_out);
 	if (ret) {
-		comedi_error(dev, "TSL timeout waiting for slot 1 to execute.");
+		dev_err(dev->class_dev,
+			"TSL timeout waiting for slot 1 to execute\n");
 		return ret;
 	}
 
@@ -515,7 +452,7 @@ static int s626_send_dac(struct comedi_d
 	 * buffer register.
 	 */
 	writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS,
-	       devpriv->mmio + S626_VECTPORT(0));
+	       dev->mmio + S626_VECTPORT(0));
 
 	/* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
 
@@ -537,7 +474,7 @@ static int s626_send_dac(struct comedi_d
 	 *    we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
 	 *    the TSL has not yet finished executing slot 5 ...
 	 */
-	if (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) {
+	if (readl(dev->mmio + S626_P_FB_BUFFER2) & 0xff000000) {
 		/*
 		 * The trap was set on time and we are still executing somewhere
 		 * in slots 2-5, so we now wait for slot 0 to execute and trap
@@ -548,8 +485,8 @@ static int s626_send_dac(struct comedi_d
 		ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
 				     s626_send_dac_wait_fb_buffer2_msb_00);
 		if (ret) {
-			comedi_error(dev,
-				"TSL timeout waiting for slot 0 to execute.");
+			dev_err(dev->class_dev,
+				"TSL timeout waiting for slot 0 to execute\n");
 			return ret;
 		}
 	}
@@ -563,7 +500,7 @@ static int s626_send_dac(struct comedi_d
 	 * SD3, which is driven only by a pull-up resistor.
 	 */
 	writel(S626_RSD3 | S626_SIB_A2 | S626_EOS,
-	       devpriv->mmio + S626_VECTPORT(0));
+	       dev->mmio + S626_VECTPORT(0));
 
 	/*
 	 * Wait for slot 0 to execute, at which time the TSL is setup for
@@ -573,7 +510,8 @@ static int s626_send_dac(struct comedi_d
 	ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
 			     s626_send_dac_wait_fb_buffer2_msb_ff);
 	if (ret) {
-		comedi_error(dev, "TSL timeout waiting for slot 0 to execute.");
+		dev_err(dev->class_dev,
+			"TSL timeout waiting for slot 0 to execute\n");
 		return ret;
 	}
 	return 0;
@@ -620,16 +558,16 @@ static int s626_set_dac(struct comedi_de
 	ws_image = (chan & 2) ? S626_WS1 : S626_WS2;
 	/* Slot 2: Transmit high data byte to target DAC */
 	writel(S626_XSD2 | S626_XFIFO_1 | ws_image,
-	       devpriv->mmio + S626_VECTPORT(2));
+	       dev->mmio + S626_VECTPORT(2));
 	/* Slot 3: Transmit low data byte to target DAC */
 	writel(S626_XSD2 | S626_XFIFO_0 | ws_image,
-	       devpriv->mmio + S626_VECTPORT(3));
+	       dev->mmio + S626_VECTPORT(3));
 	/* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
 	writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3,
-	       devpriv->mmio + S626_VECTPORT(4));
+	       dev->mmio + S626_VECTPORT(4));
 	/* Slot 5: running after writing target DAC's low data byte */
 	writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS,
-	       devpriv->mmio + S626_VECTPORT(5));
+	       dev->mmio + S626_VECTPORT(5));
 
 	/*
 	 * Construct and transmit target DAC's serial packet:
@@ -671,16 +609,16 @@ static int s626_write_trim_dac(struct co
 
 	/* Slot 2: Send high uint8_t to target TrimDac */
 	writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3,
-	       devpriv->mmio + S626_VECTPORT(2));
+	       dev->mmio + S626_VECTPORT(2));
 	/* Slot 3: Send low uint8_t to target TrimDac */
 	writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3,
-	       devpriv->mmio + S626_VECTPORT(3));
+	       dev->mmio + S626_VECTPORT(3));
 	/* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */
 	writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1,
-	       devpriv->mmio + S626_VECTPORT(4));
+	       dev->mmio + S626_VECTPORT(4));
 	/* Slot 5: Send NOP low  uint8_t to DAC0 */
 	writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS,
-	       devpriv->mmio + S626_VECTPORT(5));
+	       dev->mmio + S626_VECTPORT(5));
 
 	/*
 	 * Construct and transmit target DAC's serial packet:
@@ -723,32 +661,14 @@ static int s626_load_trim_dacs(struct co
  */
 
 /*
- * Read a counter's output latch.
- */
-static uint32_t s626_read_latch(struct comedi_device *dev,
-				const struct s626_enc_info *k)
-{
-	uint32_t value;
-
-	/* Latch counts and fetch LSW of latched counts value. */
-	value = s626_debi_read(dev, k->my_latch_lsw);
-
-	/* Fetch MSW of latched counts and combine with LSW. */
-	value |= ((uint32_t)s626_debi_read(dev, k->my_latch_lsw + 2) << 16);
-
-	/* Return latched counts. */
-	return value;
-}
-
-/*
  * Return/set a counter pair's latch trigger source.  0: On read
  * access, 1: A index latches A, 2: B index latches B, 3: A overflow
  * latches B.
  */
 static void s626_set_latch_source(struct comedi_device *dev,
-				  const struct s626_enc_info *k, uint16_t value)
+				  unsigned int chan, uint16_t value)
 {
-	s626_debi_replace(dev, k->my_crb,
+	s626_debi_replace(dev, S626_LP_CRB(chan),
 			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC),
 			  S626_SET_CRB_LATCHSRC(value));
 }
@@ -757,10 +677,10 @@ static void s626_set_latch_source(struct
  * Write value into counter preload register.
  */
 static void s626_preload(struct comedi_device *dev,
-			 const struct s626_enc_info *k, uint32_t value)
+			 unsigned int chan, uint32_t value)
 {
-	s626_debi_write(dev, k->my_latch_lsw, value);
-	s626_debi_write(dev, k->my_latch_lsw + 2, value >> 16);
+	s626_debi_write(dev, S626_LP_CNTR(chan), value);
+	s626_debi_write(dev, S626_LP_CNTR(chan) + 2, value >> 16);
 }
 
 /* ******  PRIVATE COUNTER FUNCTIONS ****** */
@@ -768,28 +688,27 @@ static void s626_preload(struct comedi_d
 /*
  * Reset a counter's index and overflow event capture flags.
  */
-static void s626_reset_cap_flags_a(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
+static void s626_reset_cap_flags(struct comedi_device *dev,
+				 unsigned int chan)
 {
-	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
-			  (S626_SET_CRB_INTRESETCMD(1) |
-			   S626_SET_CRB_INTRESET_A(1)));
-}
+	uint16_t set;
 
-static void s626_reset_cap_flags_b(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
-{
-	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
-			  (S626_SET_CRB_INTRESETCMD(1) |
-			   S626_SET_CRB_INTRESET_B(1)));
+	set = S626_SET_CRB_INTRESETCMD(1);
+	if (chan < 3)
+		set |= S626_SET_CRB_INTRESET_A(1);
+	else
+		set |= S626_SET_CRB_INTRESET_B(1);
+
+	s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set);
 }
 
+#ifdef unused
 /*
  * Return counter setup in a format (COUNTER_SETUP) that is consistent
  * for both A and B counters.
  */
 static uint16_t s626_get_mode_a(struct comedi_device *dev,
-				const struct s626_enc_info *k)
+				unsigned int chan)
 {
 	uint16_t cra;
 	uint16_t crb;
@@ -797,8 +716,8 @@ static uint16_t s626_get_mode_a(struct c
 	unsigned cntsrc, clkmult, clkpol, encmode;
 
 	/* Fetch CRA and CRB register images. */
-	cra = s626_debi_read(dev, k->my_cra);
-	crb = s626_debi_read(dev, k->my_crb);
+	cra = s626_debi_read(dev, S626_LP_CRA(chan));
+	crb = s626_debi_read(dev, S626_LP_CRB(chan));
 
 	/*
 	 * Populate the standardized counter setup bit fields.
@@ -844,7 +763,7 @@ static uint16_t s626_get_mode_a(struct c
 }
 
 static uint16_t s626_get_mode_b(struct comedi_device *dev,
-				const struct s626_enc_info *k)
+				unsigned int chan)
 {
 	uint16_t cra;
 	uint16_t crb;
@@ -852,8 +771,8 @@ static uint16_t s626_get_mode_b(struct c
 	unsigned cntsrc, clkmult, clkpol, encmode;
 
 	/* Fetch CRA and CRB register images. */
-	cra = s626_debi_read(dev, k->my_cra);
-	crb = s626_debi_read(dev, k->my_crb);
+	cra = s626_debi_read(dev, S626_LP_CRA(chan));
+	crb = s626_debi_read(dev, S626_LP_CRB(chan));
 
 	/*
 	 * Populate the standardized counter setup bit fields.
@@ -903,6 +822,14 @@ static uint16_t s626_get_mode_b(struct c
 	return setup;
 }
 
+static uint16_t s626_get_mode(struct comedi_device *dev,
+			      unsigned int chan)
+{
+	return (chan < 3) ? s626_get_mode_a(dev, chan)
+			  : s626_get_mode_b(dev, chan);
+}
+#endif
+
 /*
  * Set the operating mode for the specified counter.  The setup
  * parameter is treated as a COUNTER_SETUP data type.  The following
@@ -910,7 +837,7 @@ static uint16_t s626_get_mode_b(struct c
  * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
  */
 static void s626_set_mode_a(struct comedi_device *dev,
-			    const struct s626_enc_info *k, uint16_t setup,
+			    unsigned int chan, uint16_t setup,
 			    uint16_t disable_int_src)
 {
 	struct s626_private *devpriv = dev->private;
@@ -974,20 +901,21 @@ static void s626_set_mode_a(struct comed
 	 * enable mask to indicate the counter interrupt is disabled.
 	 */
 	if (disable_int_src)
-		devpriv->counter_int_enabs &= ~k->my_event_bits[3];
+		devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
+						S626_INDXMASK(chan));
 
 	/*
 	 * While retaining CounterB and LatchSrc configurations, program the
 	 * new counter operating mode.
 	 */
-	s626_debi_replace(dev, k->my_cra,
+	s626_debi_replace(dev, S626_LP_CRA(chan),
 			  S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra);
-	s626_debi_replace(dev, k->my_crb,
+	s626_debi_replace(dev, S626_LP_CRB(chan),
 			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb);
 }
 
 static void s626_set_mode_b(struct comedi_device *dev,
-			    const struct s626_enc_info *k, uint16_t setup,
+			    unsigned int chan, uint16_t setup,
 			    uint16_t disable_int_src)
 {
 	struct s626_private *devpriv = dev->private;
@@ -1058,54 +986,64 @@ static void s626_set_mode_b(struct comed
 	 * enable mask to indicate the counter interrupt is disabled.
 	 */
 	if (disable_int_src)
-		devpriv->counter_int_enabs &= ~k->my_event_bits[3];
+		devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
+						S626_INDXMASK(chan));
 
 	/*
 	 * While retaining CounterA and LatchSrc configurations, program the
 	 * new counter operating mode.
 	 */
-	s626_debi_replace(dev, k->my_cra,
+	s626_debi_replace(dev, S626_LP_CRA(chan),
 			  ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra);
-	s626_debi_replace(dev, k->my_crb,
+	s626_debi_replace(dev, S626_LP_CRB(chan),
 			  S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb);
 }
 
+static void s626_set_mode(struct comedi_device *dev,
+			  unsigned int chan,
+			  uint16_t setup, uint16_t disable_int_src)
+{
+	if (chan < 3)
+		s626_set_mode_a(dev, chan, setup, disable_int_src);
+	else
+		s626_set_mode_b(dev, chan, setup, disable_int_src);
+}
+
 /*
  * Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index.
  */
-static void s626_set_enable_a(struct comedi_device *dev,
-			      const struct s626_enc_info *k, uint16_t enab)
+static void s626_set_enable(struct comedi_device *dev,
+			    unsigned int chan, uint16_t enab)
 {
-	s626_debi_replace(dev, k->my_crb,
-			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A),
-			  S626_SET_CRB_CLKENAB_A(enab));
-}
+	unsigned int mask = S626_CRBMSK_INTCTRL;
+	unsigned int set;
 
-static void s626_set_enable_b(struct comedi_device *dev,
-			      const struct s626_enc_info *k, uint16_t enab)
-{
-	s626_debi_replace(dev, k->my_crb,
-			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_B),
-			  S626_SET_CRB_CLKENAB_B(enab));
+	if (chan < 3) {
+		mask |= S626_CRBMSK_CLKENAB_A;
+		set = S626_SET_CRB_CLKENAB_A(enab);
+	} else {
+		mask |= S626_CRBMSK_CLKENAB_B;
+		set = S626_SET_CRB_CLKENAB_B(enab);
+	}
+	s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set);
 }
 
-static uint16_t s626_get_enable_a(struct comedi_device *dev,
-				  const struct s626_enc_info *k)
+#ifdef unused
+static uint16_t s626_get_enable(struct comedi_device *dev,
+				unsigned int chan)
 {
-	return S626_GET_CRB_CLKENAB_A(s626_debi_read(dev, k->my_crb));
-}
+	uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan));
 
-static uint16_t s626_get_enable_b(struct comedi_device *dev,
-				  const struct s626_enc_info *k)
-{
-	return S626_GET_CRB_CLKENAB_B(s626_debi_read(dev, k->my_crb));
+	return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb)
+			  : S626_GET_CRB_CLKENAB_B(crb);
 }
+#endif
 
 #ifdef unused
 static uint16_t s626_get_latch_source(struct comedi_device *dev,
-				      const struct s626_enc_info *k)
+				      unsigned int chan)
 {
-	return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, k->my_crb));
+	return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan)));
 }
 #endif
 
@@ -1114,295 +1052,244 @@ static uint16_t s626_get_latch_source(st
  * register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
  * 2=OverflowA (B counters only), 3=disabled.
  */
-static void s626_set_load_trig_a(struct comedi_device *dev,
-				 const struct s626_enc_info *k, uint16_t trig)
-{
-	s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_LOADSRC_A,
-			  S626_SET_CRA_LOADSRC_A(trig));
-}
-
-static void s626_set_load_trig_b(struct comedi_device *dev,
-				 const struct s626_enc_info *k, uint16_t trig)
+static void s626_set_load_trig(struct comedi_device *dev,
+			       unsigned int chan, uint16_t trig)
 {
-	s626_debi_replace(dev, k->my_crb,
-			  ~(S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL),
-			  S626_SET_CRB_LOADSRC_B(trig));
-}
+	uint16_t reg;
+	uint16_t mask;
+	uint16_t set;
 
-static uint16_t s626_get_load_trig_a(struct comedi_device *dev,
-				     const struct s626_enc_info *k)
-{
-	return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, k->my_cra));
+	if (chan < 3) {
+		reg = S626_LP_CRA(chan);
+		mask = S626_CRAMSK_LOADSRC_A;
+		set = S626_SET_CRA_LOADSRC_A(trig);
+	} else {
+		reg = S626_LP_CRB(chan);
+		mask = S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL;
+		set = S626_SET_CRB_LOADSRC_B(trig);
+	}
+	s626_debi_replace(dev, reg, ~mask, set);
 }
 
-static uint16_t s626_get_load_trig_b(struct comedi_device *dev,
-				     const struct s626_enc_info *k)
+#ifdef unused
+static uint16_t s626_get_load_trig(struct comedi_device *dev,
+				   unsigned int chan)
 {
-	return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, k->my_crb));
+	if (chan < 3)
+		return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev,
+							S626_LP_CRA(chan)));
+	else
+		return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev,
+							S626_LP_CRB(chan)));
 }
+#endif
 
 /*
  * Return/set counter interrupt source and clear any captured
  * index/overflow events.  int_source: 0=Disabled, 1=OverflowOnly,
  * 2=IndexOnly, 3=IndexAndOverflow.
  */
-static void s626_set_int_src_a(struct comedi_device *dev,
-			       const struct s626_enc_info *k,
-			       uint16_t int_source)
+static void s626_set_int_src(struct comedi_device *dev,
+			     unsigned int chan, uint16_t int_source)
 {
 	struct s626_private *devpriv = dev->private;
+	uint16_t cra_reg = S626_LP_CRA(chan);
+	uint16_t crb_reg = S626_LP_CRB(chan);
 
-	/* Reset any pending counter overflow or index captures. */
-	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
-			  (S626_SET_CRB_INTRESETCMD(1) |
-			   S626_SET_CRB_INTRESET_A(1)));
-
-	/* Program counter interrupt source. */
-	s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_INTSRC_A,
-			  S626_SET_CRA_INTSRC_A(int_source));
-
-	/* Update MISC2 interrupt enable mask. */
-	devpriv->counter_int_enabs =
-	    (devpriv->counter_int_enabs & ~k->my_event_bits[3]) |
-	    k->my_event_bits[int_source];
-}
+	if (chan < 3) {
+		/* Reset any pending counter overflow or index captures */
+		s626_debi_replace(dev, crb_reg, ~S626_CRBMSK_INTCTRL,
+				  S626_SET_CRB_INTRESETCMD(1) |
+				  S626_SET_CRB_INTRESET_A(1));
 
-static void s626_set_int_src_b(struct comedi_device *dev,
-			       const struct s626_enc_info *k,
-			       uint16_t int_source)
-{
-	struct s626_private *devpriv = dev->private;
-	uint16_t crb;
+		/* Program counter interrupt source */
+		s626_debi_replace(dev, cra_reg, ~S626_CRAMSK_INTSRC_A,
+				  S626_SET_CRA_INTSRC_A(int_source));
+	} else {
+		uint16_t crb;
 
-	/* Cache writeable CRB register image. */
-	crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL;
+		/* Cache writeable CRB register image */
+		crb = s626_debi_read(dev, crb_reg);
+		crb &= ~S626_CRBMSK_INTCTRL;
 
-	/* Reset any pending counter overflow or index captures. */
-	s626_debi_write(dev, k->my_crb, (crb | S626_SET_CRB_INTRESETCMD(1) |
-					 S626_SET_CRB_INTRESET_B(1)));
+		/* Reset any pending counter overflow or index captures */
+		s626_debi_write(dev, crb_reg,
+				crb | S626_SET_CRB_INTRESETCMD(1) |
+				S626_SET_CRB_INTRESET_B(1));
 
-	/* Program counter interrupt source. */
-	s626_debi_write(dev, k->my_crb, ((crb & ~S626_CRBMSK_INTSRC_B) |
-					 S626_SET_CRB_INTSRC_B(int_source)));
+		/* Program counter interrupt source */
+		s626_debi_write(dev, crb_reg,
+				(crb & ~S626_CRBMSK_INTSRC_B) |
+				S626_SET_CRB_INTSRC_B(int_source));
+	}
 
 	/* Update MISC2 interrupt enable mask. */
-	devpriv->counter_int_enabs =
-		(devpriv->counter_int_enabs & ~k->my_event_bits[3]) |
-		k->my_event_bits[int_source];
-}
-
-static uint16_t s626_get_int_src_a(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
-{
-	return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, k->my_cra));
+	devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
+					S626_INDXMASK(chan));
+	switch (int_source) {
+	case 0:
+	default:
+		break;
+	case 1:
+		devpriv->counter_int_enabs |= S626_OVERMASK(chan);
+		break;
+	case 2:
+		devpriv->counter_int_enabs |= S626_INDXMASK(chan);
+		break;
+	case 3:
+		devpriv->counter_int_enabs |= (S626_OVERMASK(chan) |
+					       S626_INDXMASK(chan));
+		break;
+	}
 }
 
-static uint16_t s626_get_int_src_b(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
+#ifdef unused
+static uint16_t s626_get_int_src(struct comedi_device *dev,
+				 unsigned int chan)
 {
-	return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, k->my_crb));
+	if (chan < 3)
+		return S626_GET_CRA_INTSRC_A(s626_debi_read(dev,
+							S626_LP_CRA(chan)));
+	else
+		return S626_GET_CRB_INTSRC_B(s626_debi_read(dev,
+							S626_LP_CRB(chan)));
 }
+#endif
 
 #ifdef unused
 /*
  * Return/set the clock multiplier.
  */
 static void s626_set_clk_mult(struct comedi_device *dev,
-			      const struct s626_enc_info *k, uint16_t value)
+			      unsigned int chan, uint16_t value)
 {
-	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKMULT) |
-			     S626_SET_STD_CLKMULT(value)), false);
+	uint16_t mode;
+
+	mode = s626_get_mode(dev, chan);
+	mode &= ~S626_STDMSK_CLKMULT;
+	mode |= S626_SET_STD_CLKMULT(value);
+
+	s626_set_mode(dev, chan, mode, false);
 }
 
 static uint16_t s626_get_clk_mult(struct comedi_device *dev,
-				  const struct s626_enc_info *k)
+				  unsigned int chan)
 {
-	return S626_GET_STD_CLKMULT(k->get_mode(dev, k));
+	return S626_GET_STD_CLKMULT(s626_get_mode(dev, chan));
 }
 
 /*
  * Return/set the clock polarity.
  */
 static void s626_set_clk_pol(struct comedi_device *dev,
-			     const struct s626_enc_info *k, uint16_t value)
+			     unsigned int chan, uint16_t value)
 {
-	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKPOL) |
-			     S626_SET_STD_CLKPOL(value)), false);
+	uint16_t mode;
+
+	mode = s626_get_mode(dev, chan);
+	mode &= ~S626_STDMSK_CLKPOL;
+	mode |= S626_SET_STD_CLKPOL(value);
+
+	s626_set_mode(dev, chan, mode, false);
 }
 
 static uint16_t s626_get_clk_pol(struct comedi_device *dev,
-				 const struct s626_enc_info *k)
+				 unsigned int chan)
 {
-	return S626_GET_STD_CLKPOL(k->get_mode(dev, k));
+	return S626_GET_STD_CLKPOL(s626_get_mode(dev, chan));
 }
 
 /*
  * Return/set the encoder mode.
  */
 static void s626_set_enc_mode(struct comedi_device *dev,
-			      const struct s626_enc_info *k, uint16_t value)
+			      unsigned int chan, uint16_t value)
 {
-	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_ENCMODE) |
-			     S626_SET_STD_ENCMODE(value)), false);
+	uint16_t mode;
+
+	mode = s626_get_mode(dev, chan);
+	mode &= ~S626_STDMSK_ENCMODE;
+	mode |= S626_SET_STD_ENCMODE(value);
+
+	s626_set_mode(dev, chan, mode, false);
 }
 
 static uint16_t s626_get_enc_mode(struct comedi_device *dev,
-				  const struct s626_enc_info *k)
+				  unsigned int chan)
 {
-	return S626_GET_STD_ENCMODE(k->get_mode(dev, k));
+	return S626_GET_STD_ENCMODE(s626_get_mode(dev, chan));
 }
 
 /*
  * Return/set the index polarity.
  */
 static void s626_set_index_pol(struct comedi_device *dev,
-			       const struct s626_enc_info *k, uint16_t value)
+			       unsigned int chan, uint16_t value)
 {
-	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXPOL) |
-			     S626_SET_STD_INDXPOL(value != 0)), false);
+	uint16_t mode;
+
+	mode = s626_get_mode(dev, chan);
+	mode &= ~S626_STDMSK_INDXPOL;
+	mode |= S626_SET_STD_INDXPOL(value != 0);
+
+	s626_set_mode(dev, chan, mode, false);
 }
 
 static uint16_t s626_get_index_pol(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
+				   unsigned int chan)
 {
-	return S626_GET_STD_INDXPOL(k->get_mode(dev, k));
+	return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan));
 }
 
 /*
  * Return/set the index source.
  */
 static void s626_set_index_src(struct comedi_device *dev,
-			       const struct s626_enc_info *k, uint16_t value)
+			       unsigned int chan, uint16_t value)
 {
-	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXSRC) |
-			     S626_SET_STD_INDXSRC(value != 0)), false);
+	uint16_t mode;
+
+	mode = s626_get_mode(dev, chan);
+	mode &= ~S626_STDMSK_INDXSRC;
+	mode |= S626_SET_STD_INDXSRC(value != 0);
+
+	s626_set_mode(dev, chan, mode, false);
 }
 
 static uint16_t s626_get_index_src(struct comedi_device *dev,
-				   const struct s626_enc_info *k)
+				   unsigned int chan)
 {
-	return S626_GET_STD_INDXSRC(k->get_mode(dev, k));
+	return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan));
 }
 #endif
 
 /*
  * Generate an index pulse.
  */
-static void s626_pulse_index_a(struct comedi_device *dev,
-			       const struct s626_enc_info *k)
+static void s626_pulse_index(struct comedi_device *dev,
+			     unsigned int chan)
 {
-	uint16_t cra;
+	if (chan < 3) {
+		uint16_t cra;
 
-	cra = s626_debi_read(dev, k->my_cra);
-	/* Pulse index. */
-	s626_debi_write(dev, k->my_cra, (cra ^ S626_CRAMSK_INDXPOL_A));
-	s626_debi_write(dev, k->my_cra, cra);
-}
+		cra = s626_debi_read(dev, S626_LP_CRA(chan));
 
-static void s626_pulse_index_b(struct comedi_device *dev,
-			       const struct s626_enc_info *k)
-{
-	uint16_t crb;
+		/* Pulse index */
+		s626_debi_write(dev, S626_LP_CRA(chan),
+				(cra ^ S626_CRAMSK_INDXPOL_A));
+		s626_debi_write(dev, S626_LP_CRA(chan), cra);
+	} else {
+		uint16_t crb;
 
-	crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL;
-	/* Pulse index. */
-	s626_debi_write(dev, k->my_crb, (crb ^ S626_CRBMSK_INDXPOL_B));
-	s626_debi_write(dev, k->my_crb, crb);
-}
+		crb = s626_debi_read(dev, S626_LP_CRB(chan));
+		crb &= ~S626_CRBMSK_INTCTRL;
 
-static const struct s626_enc_info s626_enc_chan_info[] = {
-	{
-		.get_enable		= s626_get_enable_a,
-		.get_int_src		= s626_get_int_src_a,
-		.get_load_trig		= s626_get_load_trig_a,
-		.get_mode		= s626_get_mode_a,
-		.pulse_index		= s626_pulse_index_a,
-		.set_enable		= s626_set_enable_a,
-		.set_int_src		= s626_set_int_src_a,
-		.set_load_trig		= s626_set_load_trig_a,
-		.set_mode		= s626_set_mode_a,
-		.reset_cap_flags	= s626_reset_cap_flags_a,
-		.my_cra			= S626_LP_CR0A,
-		.my_crb			= S626_LP_CR0B,
-		.my_latch_lsw		= S626_LP_CNTR0ALSW,
-		.my_event_bits		= S626_EVBITS(0),
-	}, {
-		.get_enable		= s626_get_enable_a,
-		.get_int_src		= s626_get_int_src_a,
-		.get_load_trig		= s626_get_load_trig_a,
-		.get_mode		= s626_get_mode_a,
-		.pulse_index		= s626_pulse_index_a,
-		.set_enable		= s626_set_enable_a,
-		.set_int_src		= s626_set_int_src_a,
-		.set_load_trig		= s626_set_load_trig_a,
-		.set_mode		= s626_set_mode_a,
-		.reset_cap_flags	= s626_reset_cap_flags_a,
-		.my_cra			= S626_LP_CR1A,
-		.my_crb			= S626_LP_CR1B,
-		.my_latch_lsw		= S626_LP_CNTR1ALSW,
-		.my_event_bits		= S626_EVBITS(1),
-	}, {
-		.get_enable		= s626_get_enable_a,
-		.get_int_src		= s626_get_int_src_a,
-		.get_load_trig		= s626_get_load_trig_a,
-		.get_mode		= s626_get_mode_a,
-		.pulse_index		= s626_pulse_index_a,
-		.set_enable		= s626_set_enable_a,
-		.set_int_src		= s626_set_int_src_a,
-		.set_load_trig		= s626_set_load_trig_a,
-		.set_mode		= s626_set_mode_a,
-		.reset_cap_flags	= s626_reset_cap_flags_a,
-		.my_cra			= S626_LP_CR2A,
-		.my_crb			= S626_LP_CR2B,
-		.my_latch_lsw		= S626_LP_CNTR2ALSW,
-		.my_event_bits		= S626_EVBITS(2),
-	}, {
-		.get_enable		= s626_get_enable_b,
-		.get_int_src		= s626_get_int_src_b,
-		.get_load_trig		= s626_get_load_trig_b,
-		.get_mode		= s626_get_mode_b,
-		.pulse_index		= s626_pulse_index_b,
-		.set_enable		= s626_set_enable_b,
-		.set_int_src		= s626_set_int_src_b,
-		.set_load_trig		= s626_set_load_trig_b,
-		.set_mode		= s626_set_mode_b,
-		.reset_cap_flags	= s626_reset_cap_flags_b,
-		.my_cra			= S626_LP_CR0A,
-		.my_crb			= S626_LP_CR0B,
-		.my_latch_lsw		= S626_LP_CNTR0BLSW,
-		.my_event_bits		= S626_EVBITS(3),
-	}, {
-		.get_enable		= s626_get_enable_b,
-		.get_int_src		= s626_get_int_src_b,
-		.get_load_trig		= s626_get_load_trig_b,
-		.get_mode		= s626_get_mode_b,
-		.pulse_index		= s626_pulse_index_b,
-		.set_enable		= s626_set_enable_b,
-		.set_int_src		= s626_set_int_src_b,
-		.set_load_trig		= s626_set_load_trig_b,
-		.set_mode		= s626_set_mode_b,
-		.reset_cap_flags	= s626_reset_cap_flags_b,
-		.my_cra			= S626_LP_CR1A,
-		.my_crb			= S626_LP_CR1B,
-		.my_latch_lsw		= S626_LP_CNTR1BLSW,
-		.my_event_bits		= S626_EVBITS(4),
-	}, {
-		.get_enable		= s626_get_enable_b,
-		.get_int_src		= s626_get_int_src_b,
-		.get_load_trig		= s626_get_load_trig_b,
-		.get_mode		= s626_get_mode_b,
-		.pulse_index		= s626_pulse_index_b,
-		.set_enable		= s626_set_enable_b,
-		.set_int_src		= s626_set_int_src_b,
-		.set_load_trig		= s626_set_load_trig_b,
-		.set_mode		= s626_set_mode_b,
-		.reset_cap_flags	= s626_reset_cap_flags_b,
-		.my_cra			= S626_LP_CR2A,
-		.my_crb			= S626_LP_CR2B,
-		.my_latch_lsw		= S626_LP_CNTR2BLSW,
-		.my_event_bits		= S626_EVBITS(5),
-	},
-};
+		/* Pulse index */
+		s626_debi_write(dev, S626_LP_CRB(chan),
+				(crb ^ S626_CRBMSK_INDXPOL_B));
+		s626_debi_write(dev, S626_LP_CRB(chan), crb);
+	}
+}
 
 static unsigned int s626_ai_reg_to_uint(unsigned int data)
 {
@@ -1490,11 +1377,8 @@ static void s626_handle_dio_interrupt(st
 			}
 
 			if (cmd->convert_src == TRIG_TIMER) {
-				const struct s626_enc_info *k =
-					&s626_enc_chan_info[5];
-
 				devpriv->ai_convert_count = cmd->chanlist_len;
-				k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
+				s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
 			}
 		}
 		if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 &&
@@ -1533,7 +1417,6 @@ static void s626_check_counter_interrupt
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
-	const struct s626_enc_info *k;
 	uint16_t irqbit;
 
 	/* read interrupt type */
@@ -1541,39 +1424,29 @@ static void s626_check_counter_interrupt
 
 	/* check interrupt on counters */
 	if (irqbit & S626_IRQ_COINT1A) {
-		k = &s626_enc_chan_info[0];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 0);
 	}
 	if (irqbit & S626_IRQ_COINT2A) {
-		k = &s626_enc_chan_info[1];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 1);
 	}
 	if (irqbit & S626_IRQ_COINT3A) {
-		k = &s626_enc_chan_info[2];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 2);
 	}
 	if (irqbit & S626_IRQ_COINT1B) {
-		k = &s626_enc_chan_info[3];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 3);
 	}
 	if (irqbit & S626_IRQ_COINT2B) {
-		k = &s626_enc_chan_info[4];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 4);
 
 		if (devpriv->ai_convert_count > 0) {
 			devpriv->ai_convert_count--;
 			if (devpriv->ai_convert_count == 0)
-				k->set_enable(dev, k, S626_CLKENAB_INDEX);
+				s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
 
 			if (cmd->convert_src == TRIG_TIMER) {
 				/* Trigger ADC scan loop start */
@@ -1583,10 +1456,8 @@ static void s626_check_counter_interrupt
 		}
 	}
 	if (irqbit & S626_IRQ_COINT3B) {
-		k = &s626_enc_chan_info[5];
-
 		/* clear interrupt capture flag */
-		k->reset_cap_flags(dev, k);
+		s626_reset_cap_flags(dev, 5);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
 			/* Trigger ADC scan loop start */
@@ -1594,9 +1465,8 @@ static void s626_check_counter_interrupt
 		}
 
 		if (cmd->convert_src == TRIG_TIMER) {
-			k = &s626_enc_chan_info[4];
 			devpriv->ai_convert_count = cmd->chanlist_len;
-			k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
+			s626_set_enable(dev, 4, S626_CLKENAB_ALWAYS);
 		}
 	}
 }
@@ -1661,7 +1531,6 @@ static bool s626_handle_eos_interrupt(st
 static irqreturn_t s626_irq_handler(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct s626_private *devpriv = dev->private;
 	unsigned long flags;
 	uint32_t irqtype, irqstatus;
 
@@ -1671,16 +1540,16 @@ static irqreturn_t s626_irq_handler(int
 	spin_lock_irqsave(&dev->spinlock, flags);
 
 	/* save interrupt enable register state */
-	irqstatus = readl(devpriv->mmio + S626_P_IER);
+	irqstatus = readl(dev->mmio + S626_P_IER);
 
 	/* read interrupt type */
-	irqtype = readl(devpriv->mmio + S626_P_ISR);
+	irqtype = readl(dev->mmio + S626_P_ISR);
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + S626_P_IER);
+	writel(0, dev->mmio + S626_P_IER);
 
 	/* clear interrupt */
-	writel(irqtype, devpriv->mmio + S626_P_ISR);
+	writel(irqtype, dev->mmio + S626_P_ISR);
 
 	switch (irqtype) {
 	case S626_IRQ_RPS1:	/* end_of_scan occurs */
@@ -1695,7 +1564,7 @@ static irqreturn_t s626_irq_handler(int
 	}
 
 	/* enable interrupt */
-	writel(irqstatus, devpriv->mmio + S626_P_IER);
+	writel(irqstatus, dev->mmio + S626_P_IER);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 	return IRQ_HANDLED;
@@ -1723,7 +1592,7 @@ static void s626_reset_adc(struct comedi
 
 	/* Initialize RPS instruction pointer */
 	writel((uint32_t)devpriv->rps_buf.physical_base,
-	       devpriv->mmio + S626_P_RPSADDR1);
+	       dev->mmio + S626_P_RPSADDR1);
 
 	/* Construct RPS program in rps_buf DMA buffer */
 	if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
@@ -1944,10 +1813,9 @@ static int s626_ai_eoc(struct comedi_dev
 		       struct comedi_insn *insn,
 		       unsigned long context)
 {
-	struct s626_private *devpriv = dev->private;
 	unsigned int status;
 
-	status = readl(devpriv->mmio + S626_P_PSR);
+	status = readl(dev->mmio + S626_P_PSR);
 	if (status & S626_PSR_GPIO2)
 		return 0;
 	return -EBUSY;
@@ -1955,9 +1823,9 @@ static int s626_ai_eoc(struct comedi_dev
 
 static int s626_ai_insn_read(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
-	struct s626_private *devpriv = dev->private;
 	uint16_t chan = CR_CHAN(insn->chanspec);
 	uint16_t range = CR_RANGE(insn->chanspec);
 	uint16_t adc_spec = 0;
@@ -1986,17 +1854,14 @@ static int s626_ai_insn_read(struct come
 		udelay(10);
 
 		/* Start ADC by pulsing GPIO1 low */
-		gpio_image = readl(devpriv->mmio + S626_P_GPIO);
+		gpio_image = readl(dev->mmio + S626_P_GPIO);
 		/* Assert ADC Start command */
-		writel(gpio_image & ~S626_GPIO1_HI,
-		       devpriv->mmio + S626_P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 		/* and stretch it out */
-		writel(gpio_image & ~S626_GPIO1_HI,
-		       devpriv->mmio + S626_P_GPIO);
-		writel(gpio_image & ~S626_GPIO1_HI,
-		       devpriv->mmio + S626_P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 		/* Negate ADC Start command */
-		writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+		writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 
 		/*
 		 * Wait for ADC to complete (GPIO2 is asserted high when
@@ -2011,7 +1876,7 @@ static int s626_ai_insn_read(struct come
 
 		/* Fetch ADC data */
 		if (n != 0) {
-			tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1);
+			tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
 			data[n - 1] = s626_ai_reg_to_uint(tmp);
 		}
 
@@ -2031,14 +1896,14 @@ static int s626_ai_insn_read(struct come
 	 * Start a dummy conversion to cause the data from the
 	 * previous conversion to be shifted in.
 	 */
-	gpio_image = readl(devpriv->mmio + S626_P_GPIO);
+	gpio_image = readl(dev->mmio + S626_P_GPIO);
 	/* Assert ADC Start command */
-	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 	/* and stretch it out */
-	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
-	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 	/* Negate ADC Start command */
-	writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+	writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 
 	/* Wait for the data to arrive in FB BUFFER 1 register. */
 
@@ -2051,7 +1916,7 @@ static int s626_ai_insn_read(struct come
 
 	/* Fetch ADC data */
 	if (n != 0) {
-		tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1);
+		tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
 		data[n - 1] = s626_ai_reg_to_uint(tmp);
 	}
 
@@ -2098,13 +1963,13 @@ static int s626_ai_inttrig(struct comedi
  * Also, it should adjust ns so that it cooresponds to the actual time
  * that the device will use.
  */
-static int s626_ns_to_timer(unsigned int *nanosec, int round_mode)
+static int s626_ns_to_timer(unsigned int *nanosec, unsigned int flags)
 {
 	int divider, base;
 
 	base = 500;		/* 2MHz internal clock */
 
-	switch (round_mode) {
+	switch (flags & TRIG_ROUND_MASK) {
 	case TRIG_ROUND_NEAREST:
 	default:
 		divider = (*nanosec + base / 2) / base;
@@ -2122,7 +1987,7 @@ static int s626_ns_to_timer(unsigned int
 }
 
 static void s626_timer_load(struct comedi_device *dev,
-			    const struct s626_enc_info *k, int tick)
+			    unsigned int chan, int tick)
 {
 	uint16_t setup =
 		/* Preload upon index. */
@@ -2140,26 +2005,26 @@ static void s626_timer_load(struct comed
 	uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA;
 	/* uint16_t enab = S626_CLKENAB_ALWAYS; */
 
-	k->set_mode(dev, k, setup, false);
+	s626_set_mode(dev, chan, setup, false);
 
 	/* Set the preload register */
-	s626_preload(dev, k, tick);
+	s626_preload(dev, chan, tick);
 
 	/*
 	 * Software index pulse forces the preload register to load
 	 * into the counter
 	 */
-	k->set_load_trig(dev, k, 0);
-	k->pulse_index(dev, k);
+	s626_set_load_trig(dev, chan, 0);
+	s626_pulse_index(dev, chan);
 
 	/* set reload on counter overflow */
-	k->set_load_trig(dev, k, 1);
+	s626_set_load_trig(dev, chan, 1);
 
 	/* set interrupt on overflow */
-	k->set_int_src(dev, k, S626_INTSRC_OVER);
+	s626_set_int_src(dev, chan, S626_INTSRC_OVER);
 
-	s626_set_latch_source(dev, k, value_latchsrc);
-	/* k->set_enable(dev, k, (uint16_t)(enab != 0)); */
+	s626_set_latch_source(dev, chan, value_latchsrc);
+	/* s626_set_enable(dev, chan, (uint16_t)(enab != 0)); */
 }
 
 /* TO COMPLETE  */
@@ -2168,7 +2033,6 @@ static int s626_ai_cmd(struct comedi_dev
 	struct s626_private *devpriv = dev->private;
 	uint8_t ppl[16];
 	struct comedi_cmd *cmd = &s->async->cmd;
-	const struct s626_enc_info *k;
 	int tick;
 
 	if (devpriv->ai_cmd_running) {
@@ -2177,10 +2041,10 @@ static int s626_ai_cmd(struct comedi_dev
 		return -EBUSY;
 	}
 	/* disable interrupt */
-	writel(0, devpriv->mmio + S626_P_IER);
+	writel(0, dev->mmio + S626_P_IER);
 
 	/* clear interrupt request */
-	writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, devpriv->mmio + S626_P_ISR);
+	writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, dev->mmio + S626_P_ISR);
 
 	/* clear any pending interrupt */
 	s626_dio_clear_irq(dev);
@@ -2205,13 +2069,11 @@ static int s626_ai_cmd(struct comedi_dev
 		 * set a counter to generate adc trigger at scan_begin_arg
 		 * interval
 		 */
-		k = &s626_enc_chan_info[5];
-		tick = s626_ns_to_timer(&cmd->scan_begin_arg,
-					cmd->flags & TRIG_ROUND_MASK);
+		tick = s626_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
 
 		/* load timer value and enable interrupt */
-		s626_timer_load(dev, k, tick);
-		k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
+		s626_timer_load(dev, 5, tick);
+		s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
 		break;
 	case TRIG_EXT:
 		/* set the digital line and interrupt for scan trigger */
@@ -2228,13 +2090,11 @@ static int s626_ai_cmd(struct comedi_dev
 		 * set a counter to generate adc trigger at convert_arg
 		 * interval
 		 */
-		k = &s626_enc_chan_info[4];
-		tick = s626_ns_to_timer(&cmd->convert_arg,
-					cmd->flags & TRIG_ROUND_MASK);
+		tick = s626_ns_to_timer(&cmd->convert_arg, cmd->flags);
 
 		/* load timer value and enable interrupt */
-		s626_timer_load(dev, k, tick);
-		k->set_enable(dev, k, S626_CLKENAB_INDEX);
+		s626_timer_load(dev, 4, tick);
+		s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
 		break;
 	case TRIG_EXT:
 		/* set the digital line and interrupt for convert trigger */
@@ -2279,7 +2139,7 @@ static int s626_ai_cmd(struct comedi_dev
 	}
 
 	/* enable interrupt */
-	writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, devpriv->mmio + S626_P_IER);
+	writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, dev->mmio + S626_P_IER);
 
 	return 0;
 }
@@ -2372,13 +2232,13 @@ static int s626_ai_cmdtest(struct comedi
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		s626_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		s626_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -2402,7 +2262,7 @@ static int s626_ai_cancel(struct comedi_
 	s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + S626_P_IER);
+	writel(0, dev->mmio + S626_P_IER);
 
 	devpriv->ai_cmd_running = 0;
 
@@ -2516,6 +2376,7 @@ static int s626_enc_insn_config(struct c
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	uint16_t setup =
 		/* Preload upon index. */
 		S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
@@ -2533,51 +2394,58 @@ static int s626_enc_insn_config(struct c
 	/* uint32_t Preloadvalue;              //Counter initial value */
 	uint16_t value_latchsrc = S626_LATCHSRC_AB_READ;
 	uint16_t enab = S626_CLKENAB_ALWAYS;
-	const struct s626_enc_info *k =
-		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
 
 	/* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
 
-	k->set_mode(dev, k, setup, true);
-	s626_preload(dev, k, data[0]);
-	k->pulse_index(dev, k);
-	s626_set_latch_source(dev, k, value_latchsrc);
-	k->set_enable(dev, k, (enab != 0));
+	s626_set_mode(dev, chan, setup, true);
+	s626_preload(dev, chan, data[0]);
+	s626_pulse_index(dev, chan);
+	s626_set_latch_source(dev, chan, value_latchsrc);
+	s626_set_enable(dev, chan, (enab != 0));
 
 	return insn->n;
 }
 
 static int s626_enc_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	int n;
-	const struct s626_enc_info *k =
-		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	uint16_t cntr_latch_reg = S626_LP_CNTR(chan);
+	int i;
 
-	for (n = 0; n < insn->n; n++)
-		data[n] = s626_read_latch(dev, k);
+	for (i = 0; i < insn->n; i++) {
+		unsigned int val;
 
-	return n;
+		/*
+		 * Read the counter's output latch LSW/MSW.
+		 * Latches on LSW read.
+		 */
+		val = s626_debi_read(dev, cntr_latch_reg);
+		val |= (s626_debi_read(dev, cntr_latch_reg + 2) << 16);
+		data[i] = val;
+	}
+
+	return insn->n;
 }
 
 static int s626_enc_insn_write(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
-	const struct s626_enc_info *k =
-		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
+	unsigned int chan = CR_CHAN(insn->chanspec);
 
 	/* Set the preload register */
-	s626_preload(dev, k, data[0]);
+	s626_preload(dev, chan, data[0]);
 
 	/*
 	 * Software index pulse forces the preload register to load
 	 * into the counter
 	 */
-	k->set_load_trig(dev, k, 0);
-	k->pulse_index(dev, k);
-	k->set_load_trig(dev, k, 2);
+	s626_set_load_trig(dev, chan, 0);
+	s626_pulse_index(dev, chan);
+	s626_set_load_trig(dev, chan, 2);
 
 	return 1;
 }
@@ -2612,7 +2480,6 @@ static void s626_close_dma_b(struct come
 static void s626_counters_init(struct comedi_device *dev)
 {
 	int chan;
-	const struct s626_enc_info *k;
 	uint16_t setup =
 		/* Preload upon index. */
 		S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
@@ -2631,11 +2498,10 @@ static void s626_counters_init(struct co
 	 * Disable all counter interrupts and clear any captured counter events.
 	 */
 	for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
-		k = &s626_enc_chan_info[chan];
-		k->set_mode(dev, k, setup, true);
-		k->set_int_src(dev, k, 0);
-		k->reset_cap_flags(dev, k);
-		k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
+		s626_set_mode(dev, chan, setup, true);
+		s626_set_int_src(dev, chan, 0);
+		s626_reset_cap_flags(dev, chan);
+		s626_set_enable(dev, chan, S626_CLKENAB_ALWAYS);
 	}
 }
 
@@ -2683,13 +2549,13 @@ static int s626_initialize(struct comedi
 	 */
 	writel(S626_DEBI_CFG_SLAVE16 |
 	       (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP |
-	       S626_DEBI_CFG_INTEL, devpriv->mmio + S626_P_DEBICFG);
+	       S626_DEBI_CFG_INTEL, dev->mmio + S626_P_DEBICFG);
 
 	/* Disable MMU paging */
-	writel(S626_DEBI_PAGE_DISABLE, devpriv->mmio + S626_P_DEBIPAGE);
+	writel(S626_DEBI_PAGE_DISABLE, dev->mmio + S626_P_DEBIPAGE);
 
 	/* Init GPIO so that ADC Start* is negated */
-	writel(S626_GPIO_BASE | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+	writel(S626_GPIO_BASE | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
 
 	/* I2C device address for onboard eeprom (revb) */
 	devpriv->i2c_adrs = 0xA0;
@@ -2699,7 +2565,7 @@ static int s626_initialize(struct comedi
 	 * operation in progress and reset BUSY flag.
 	 */
 	writel(S626_I2C_CLKSEL | S626_I2C_ABORT,
-	       devpriv->mmio + S626_P_I2CSTAT);
+	       dev->mmio + S626_P_I2CSTAT);
 	s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
 	ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
 	if (ret)
@@ -2710,7 +2576,7 @@ static int s626_initialize(struct comedi
 	 * reg twice to reset all  I2C error flags.
 	 */
 	for (i = 0; i < 2; i++) {
-		writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT);
+		writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT);
 		s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
 		ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
 		if (ret)
@@ -2723,7 +2589,7 @@ static int s626_initialize(struct comedi
 	 * DAC data setup times are satisfied, enable DAC serial
 	 * clock out.
 	 */
-	writel(S626_ACON2_INIT, devpriv->mmio + S626_P_ACON2);
+	writel(S626_ACON2_INIT, dev->mmio + S626_P_ACON2);
 
 	/*
 	 * Set up TSL1 slot list, which is used to control the
@@ -2731,12 +2597,12 @@ static int s626_initialize(struct comedi
 	 * S626_SIB_A1  = store data uint8_t at next available location
 	 * in FB BUFFER1 register.
 	 */
-	writel(S626_RSD1 | S626_SIB_A1, devpriv->mmio + S626_P_TSL1);
+	writel(S626_RSD1 | S626_SIB_A1, dev->mmio + S626_P_TSL1);
 	writel(S626_RSD1 | S626_SIB_A1 | S626_EOS,
-	       devpriv->mmio + S626_P_TSL1 + 4);
+	       dev->mmio + S626_P_TSL1 + 4);
 
 	/* Enable TSL1 slot list so that it executes all the time */
-	writel(S626_ACON1_ADCSTART, devpriv->mmio + S626_P_ACON1);
+	writel(S626_ACON1_ADCSTART, dev->mmio + S626_P_ACON1);
 
 	/*
 	 * Initialize RPS registers used for ADC
@@ -2744,11 +2610,11 @@ static int s626_initialize(struct comedi
 
 	/* Physical start of RPS program */
 	writel((uint32_t)devpriv->rps_buf.physical_base,
-	       devpriv->mmio + S626_P_RPSADDR1);
+	       dev->mmio + S626_P_RPSADDR1);
 	/* RPS program performs no explicit mem writes */
-	writel(0, devpriv->mmio + S626_P_RPSPAGE1);
+	writel(0, dev->mmio + S626_P_RPSPAGE1);
 	/* Disable RPS timeouts */
-	writel(0, devpriv->mmio + S626_P_RPS1_TOUT);
+	writel(0, dev->mmio + S626_P_RPS1_TOUT);
 
 #if 0
 	/*
@@ -2804,7 +2670,7 @@ static int s626_initialize(struct comedi
 	 *   burst length = 1 DWORD
 	 *   threshold = 1 DWORD.
 	 */
-	writel(0, devpriv->mmio + S626_P_PCI_BT_A);
+	writel(0, dev->mmio + S626_P_PCI_BT_A);
 
 	/*
 	 * Init Audio2's output DMA physical addresses.  The protection
@@ -2814,9 +2680,9 @@ static int s626_initialize(struct comedi
 	 */
 	phys_buf = devpriv->ana_buf.physical_base +
 		   (S626_DAC_WDMABUF_OS * sizeof(uint32_t));
-	writel((uint32_t)phys_buf, devpriv->mmio + S626_P_BASEA2_OUT);
+	writel((uint32_t)phys_buf, dev->mmio + S626_P_BASEA2_OUT);
 	writel((uint32_t)(phys_buf + sizeof(uint32_t)),
-	       devpriv->mmio + S626_P_PROTA2_OUT);
+	       dev->mmio + S626_P_PROTA2_OUT);
 
 	/*
 	 * Cache Audio2's output DMA buffer logical address.  This is
@@ -2831,7 +2697,7 @@ static int s626_initialize(struct comedi
 	 * DMAC will automatically halt and its PCI address pointer
 	 * will be reset when the protection address is reached.
 	 */
-	writel(8, devpriv->mmio + S626_P_PAGEA2_OUT);
+	writel(8, dev->mmio + S626_P_PAGEA2_OUT);
 
 	/*
 	 * Initialize time slot list 2 (TSL2), which is used to control
@@ -2847,7 +2713,7 @@ static int s626_initialize(struct comedi
 
 	/* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */
 	writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS,
-	       devpriv->mmio + S626_VECTPORT(0));
+	       dev->mmio + S626_VECTPORT(0));
 
 	/*
 	 * Initialize slot 1, which is constant.  Slot 1 causes a
@@ -2859,10 +2725,10 @@ static int s626_initialize(struct comedi
 	 */
 
 	/* Slot 1: Fetch DWORD from Audio2's output FIFO */
-	writel(S626_LF_A2, devpriv->mmio + S626_VECTPORT(1));
+	writel(S626_LF_A2, dev->mmio + S626_VECTPORT(1));
 
 	/* Start DAC's audio interface (TSL2) running */
-	writel(S626_ACON1_DACSTART, devpriv->mmio + S626_P_ACON1);
+	writel(S626_ACON1_DACSTART, dev->mmio + S626_P_ACON1);
 
 	/*
 	 * Init Trim DACs to calibrated values.  Do it twice because the
@@ -2926,15 +2792,15 @@ static int s626_auto_attach(struct comed
 	if (ret)
 		return ret;
 
-	devpriv->mmio = pci_ioremap_bar(pcidev, 0);
-	if (!devpriv->mmio)
+	dev->mmio = pci_ioremap_bar(pcidev, 0);
+	if (!dev->mmio)
 		return -ENOMEM;
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + S626_P_IER);
+	writel(0, dev->mmio + S626_P_IER);
 
 	/* soft reset */
-	writel(S626_MC1_SOFT_RESET, devpriv->mmio + S626_P_MC1);
+	writel(S626_MC1_SOFT_RESET, dev->mmio + S626_P_MC1);
 
 	/* DMA FIXME DMA// */
 
@@ -3043,20 +2909,20 @@ static void s626_detach(struct comedi_de
 		/* stop ai_command */
 		devpriv->ai_cmd_running = 0;
 
-		if (devpriv->mmio) {
+		if (dev->mmio) {
 			/* interrupt mask */
 			/* Disable master interrupt */
-			writel(0, devpriv->mmio + S626_P_IER);
+			writel(0, dev->mmio + S626_P_IER);
 			/* Clear board's IRQ status flag */
 			writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1,
-			       devpriv->mmio + S626_P_ISR);
+			       dev->mmio + S626_P_ISR);
 
 			/* Disable the watchdog timer and battery charger. */
 			s626_write_misc2(dev, 0);
 
 			/* Close all interfaces on 7146 device */
-			writel(S626_MC1_SHUTDOWN, devpriv->mmio + S626_P_MC1);
-			writel(S626_ACON1_BASE, devpriv->mmio + S626_P_ACON1);
+			writel(S626_MC1_SHUTDOWN, dev->mmio + S626_P_MC1);
+			writel(S626_ACON1_BASE, dev->mmio + S626_P_ACON1);
 
 			s626_close_dma_b(dev, &devpriv->rps_buf,
 					 S626_DMABUF_SIZE);
@@ -3066,8 +2932,8 @@ static void s626_detach(struct comedi_de
 
 		if (dev->irq)
 			free_irq(dev->irq, dev);
-		if (devpriv->mmio)
-			iounmap(devpriv->mmio);
+		if (dev->mmio)
+			iounmap(dev->mmio);
 	}
 	comedi_pci_disable(dev);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s626.h linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s626.h
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/s626.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/s626.h	2014-09-28 17:29:07.000000000 -0400
@@ -229,27 +229,13 @@
 #define S626_LP_RDEDGSEL(x)	(0x004c + (x) * 0x10)	/* R: edge selection */
 #define S626_LP_RDCAPSEL(x)	(0x004e + (x) * 0x10)	/* R: capture enable */
 
-/* Counter Registers (read/write): */
-#define S626_LP_CR0A		0x0000	/* 0A setup register. */
-#define S626_LP_CR0B		0x0002	/* 0B setup register. */
-#define S626_LP_CR1A		0x0004	/* 1A setup register. */
-#define S626_LP_CR1B		0x0006	/* 1B setup register. */
-#define S626_LP_CR2A		0x0008	/* 2A setup register. */
-#define S626_LP_CR2B		0x000A	/* 2B setup register. */
+/* Counter registers (read/write): 0A 1A 2A 0B 1B 2B */
+#define S626_LP_CRA(x)		(0x0000 + (((x) % 3) * 0x4))
+#define S626_LP_CRB(x)		(0x0002 + (((x) % 3) * 0x4))
 
-/* Counter PreLoad (write) and Latch (read) Registers: */
-#define	S626_LP_CNTR0ALSW	0x000C	/* 0A lsw. */
-#define	S626_LP_CNTR0AMSW	0x000E	/* 0A msw. */
-#define	S626_LP_CNTR0BLSW	0x0010	/* 0B lsw. */
-#define	S626_LP_CNTR0BMSW	0x0012	/* 0B msw. */
-#define	S626_LP_CNTR1ALSW	0x0014	/* 1A lsw. */
-#define	S626_LP_CNTR1AMSW	0x0016	/* 1A msw. */
-#define	S626_LP_CNTR1BLSW	0x0018	/* 1B lsw. */
-#define	S626_LP_CNTR1BMSW	0x001A	/* 1B msw. */
-#define	S626_LP_CNTR2ALSW	0x001C	/* 2A lsw. */
-#define	S626_LP_CNTR2AMSW	0x001E	/* 2A msw. */
-#define	S626_LP_CNTR2BLSW	0x0020	/* 2B lsw. */
-#define	S626_LP_CNTR2BMSW	0x0022	/* 2B msw. */
+/* Counter PreLoad (write) and Latch (read) Registers: 0A 1A 2A 0B 1B 2B */
+#define S626_LP_CNTR(x)		(0x000c  + (((x) < 3) ? 0x0 : 0x4) + \
+					   (((x) % 3) * 0x8))
 
 /* Miscellaneous Registers (read/write): */
 #define S626_LP_MISC1		0x0088	/* Read/write Misc1. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/serial2002.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/serial2002.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/serial2002.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/serial2002.c	2014-09-28 17:29:07.000000000 -0400
@@ -174,6 +174,7 @@ static int serial2002_tty_read(struct fi
 		} else {
 			/* Device does not support poll, busy wait */
 			int retries = 0;
+
 			while (1) {
 				retries++;
 				if (retries >= timeout)
@@ -311,6 +312,7 @@ static void serial2002_write(struct file
 	} else {
 		unsigned char ch[6];
 		int i = 0;
+
 		if (data.value >= (1L << 30)) {
 			ch[i] = 0x80 | ((data.value >> 30) & 0x03);
 			i++;
@@ -359,7 +361,8 @@ static int serial2002_setup_subdevice(st
 	s->n_chan = chan;
 	s->maxdata = 0;
 	kfree(s->maxdata_list);
-	maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL);
+	maxdata_list = kmalloc_array(s->n_chan, sizeof(unsigned int),
+				     GFP_KERNEL);
 	if (!maxdata_list)
 		return -ENOMEM;
 	s->maxdata_list = maxdata_list;
@@ -369,9 +372,8 @@ static int serial2002_setup_subdevice(st
 	if (kind == 1 || kind == 2) {
 		s->range_table = &range_digital;
 	} else if (range) {
-		range_table_list =
-			kmalloc(sizeof(struct serial2002_range_table_t) *
-				s->n_chan, GFP_KERNEL);
+		range_table_list = kmalloc_array(s->n_chan, sizeof(*range),
+						 GFP_KERNEL);
 		if (!range_table_list)
 			return -ENOMEM;
 		s->range_table_list = range_table_list;
@@ -420,67 +422,65 @@ static int serial2002_setup_subdevs(stru
 	serial2002_tty_setspeed(devpriv->tty, devpriv->speed);
 	serial2002_poll_channel(devpriv->tty, 31);
 	while (1) {
-		struct serial_data data;
+		struct serial_data data = serial2002_read(devpriv->tty, 1000);
+		int kind = S2002_CFG_KIND(data.value);
+		int channel = S2002_CFG_CHAN(data.value);
+		int range = S2002_CFG_BASE(data.value);
+		int cmd = S2002_CFG_CMD(data.value);
 
-		data = serial2002_read(devpriv->tty, 1000);
 		if (data.kind != is_channel || data.index != 31 ||
-		    S2002_CFG_KIND(data.value) == S2002_CFG_KIND_INVALID) {
+		    kind == S2002_CFG_KIND_INVALID)
 			break;
-		} else {
-			int channel = S2002_CFG_CHAN(data.value);
-			int range = S2002_CFG_BASE(data.value);
 
-			switch (S2002_CFG_KIND(data.value)) {
-			case S2002_CFG_KIND_DIGITAL_IN:
-				cfg = di_cfg;
-				break;
-			case S2002_CFG_KIND_DIGITAL_OUT:
-				cfg = do_cfg;
-				break;
-			case S2002_CFG_KIND_ANALOG_IN:
-				cfg = ai_cfg;
-				break;
-			case S2002_CFG_KIND_ANALOG_OUT:
-				cfg = ao_cfg;
-				break;
-			case S2002_CFG_KIND_ENCODER_IN:
-				cfg = ai_cfg;
-				break;
-			default:
-				cfg = NULL;
-				break;
-			}
-			if (!cfg)
-				continue;	/* unknown kind, skip it */
+		switch (kind) {
+		case S2002_CFG_KIND_DIGITAL_IN:
+			cfg = di_cfg;
+			break;
+		case S2002_CFG_KIND_DIGITAL_OUT:
+			cfg = do_cfg;
+			break;
+		case S2002_CFG_KIND_ANALOG_IN:
+			cfg = ai_cfg;
+			break;
+		case S2002_CFG_KIND_ANALOG_OUT:
+			cfg = ao_cfg;
+			break;
+		case S2002_CFG_KIND_ENCODER_IN:
+			cfg = ai_cfg;
+			break;
+		default:
+			cfg = NULL;
+			break;
+		}
+		if (!cfg)
+			continue;	/* unknown kind, skip it */
 
-			cfg[channel].kind = S2002_CFG_KIND(data.value);
+		cfg[channel].kind = kind;
 
-			switch (S2002_CFG_CMD(data.value)) {
-			case S2002_CFG_CMD_BITS:
-				cfg[channel].bits = S2002_CFG_BITS(data.value);
+		switch (cmd) {
+		case S2002_CFG_CMD_BITS:
+			cfg[channel].bits = S2002_CFG_BITS(data.value);
+			break;
+		case S2002_CFG_CMD_MIN:
+		case S2002_CFG_CMD_MAX:
+			switch (S2002_CFG_UNITS(data.value)) {
+			case 0:
+				range *= 1000000;
 				break;
-			case S2002_CFG_CMD_MIN:
-			case S2002_CFG_CMD_MAX:
-				switch (S2002_CFG_UNITS(data.value)) {
-				case 0:
-					range *= 1000000;
-					break;
-				case 1:
-					range *= 1000;
-					break;
-				case 2:
-					range *= 1;
-					break;
-				}
-				if (S2002_CFG_SIGN(data.value))
-					range = -range;
-				if (S2002_CFG_CMD(data.value) ==
-				    S2002_CFG_CMD_MIN)
-					cfg[channel].min = range;
-				else
-					cfg[channel].max = range;
+			case 1:
+				range *= 1000;
+				break;
+			case 2:
+				range *= 1;
 				break;
 			}
+			if (S2002_CFG_SIGN(data.value))
+				range = -range;
+			if (cmd == S2002_CFG_CMD_MIN)
+				cfg[channel].min = range;
+			else
+				cfg[channel].max = range;
+			break;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/skel.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/skel.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/skel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/skel.c	2014-09-28 17:29:07.000000000 -0400
@@ -75,9 +75,6 @@ Configuration Options:
 #include "comedi_fc.h"
 
 /* Imaginary registers for the imaginary board */
-
-#define SKEL_SIZE 0
-
 #define SKEL_START_AI_CONV	0
 #define SKEL_AI_READ		0
 
@@ -129,7 +126,7 @@ struct skel_private {
  * convert ns nanoseconds to a counter value suitable for programming
  * the device.  Also, it should adjust ns so that it cooresponds to
  * the actual time that the device will use. */
-static int skel_ns_to_timer(unsigned int *ns, int round)
+static int skel_ns_to_timer(unsigned int *ns, unsigned int flags)
 {
 	/* trivial timer */
 	/* if your timing is done through two cascaded timers, the
@@ -287,12 +284,12 @@ static int skel_ai_cmdtest(struct comedi
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		arg = cmd->scan_begin_arg;
-		skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		skel_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
 		arg = cmd->convert_arg;
-		skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK);
+		skel_ns_to_timer(&arg, cmd->flags);
 		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/unioxx5.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/unioxx5.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/unioxx5.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/unioxx5.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 #include <linux/delay.h>
 #include "../comedidev.h"
 
-#define DRIVER_NAME "unioxx5"
 #define UNIOXX5_SIZE 0x10
 #define UNIOXX5_SUBDEV_BASE 0xA000	/* base addr of first subdev */
 #define UNIOXX5_SUBDEV_ODDS 0x400
@@ -496,7 +495,7 @@ static void unioxx5_detach(struct comedi
 }
 
 static struct comedi_driver unioxx5_driver = {
-	.driver_name	= DRIVER_NAME,
+	.driver_name	= "unioxx5",
 	.module		= THIS_MODULE,
 	.attach		= unioxx5_attach,
 	.detach		= unioxx5_detach,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbdux.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbdux.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbdux.c	2014-08-07 04:59:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbdux.c	2014-09-28 21:41:41.000000000 -0400
@@ -1327,13 +1327,13 @@ static int usbdux_pwm_period(struct come
 	struct usbdux_private *devpriv = dev->private;
 	int fx2delay = 255;
 
-	if (period < MIN_PWM_PERIOD) {
+	if (period < MIN_PWM_PERIOD)
 		return -EAGAIN;
-	} else {
-		fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
-		if (fx2delay > 255)
-			return -EAGAIN;
-	}
+
+	fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
+	if (fx2delay > 255)
+		return -EAGAIN;
+
 	devpriv->pwm_delay = fx2delay;
 	devpriv->pwm_period = period;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbduxfast.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbduxfast.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbduxfast.c	2014-08-07 04:59:07.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbduxfast.c	2014-09-28 21:41:44.000000000 -0400
@@ -33,8 +33,6 @@
  *       udev coldplug problem
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -275,8 +273,9 @@ static void usbduxfast_ai_interrupt(stru
 		return;
 
 	default:
-		pr_err("non-zero urb status received in ai intr context: %d\n",
-		       urb->status);
+		dev_err(dev->class_dev,
+			"non-zero urb status received in ai intr context: %d\n",
+			urb->status);
 		async->events |= COMEDI_CB_EOA;
 		async->events |= COMEDI_CB_ERROR;
 		comedi_event(dev, s);
@@ -746,6 +745,7 @@ static int usbduxfast_ai_cmd(struct come
 				    0x00, (0xff - 0x02) & rngmask, 0x00);
 
 		usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
+		break;
 
 	case 16:
 		if (CR_RANGE(cmd->chanlist[0]) > 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbduxsigma.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbduxsigma.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/usbduxsigma.c	2014-08-07 04:59:10.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/usbduxsigma.c	2014-09-28 21:41:47.000000000 -0400
@@ -136,7 +136,7 @@
 
 static const struct comedi_lrange usbduxsigma_ai_range = {
 	1, {
-		BIP_RANGE(2.65 / 2.0)
+		BIP_RANGE(2.5 * 0x800000 / 0x780000 / 2.0)
 	}
 };
 
@@ -1176,13 +1176,13 @@ static int usbduxsigma_pwm_period(struct
 	struct usbduxsigma_private *devpriv = dev->private;
 	int fx2delay = 255;
 
-	if (period < MIN_PWM_PERIOD) {
+	if (period < MIN_PWM_PERIOD)
 		return -EAGAIN;
-	} else {
-		fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
-		if (fx2delay > 255)
-			return -EAGAIN;
-	}
+
+	fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
+	if (fx2delay > 255)
+		return -EAGAIN;
+
 	devpriv->pwm_delay = fx2delay;
 	devpriv->pwm_period = period;
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers/vmk80xx.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/vmk80xx.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers/vmk80xx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers/vmk80xx.c	2014-09-28 17:29:07.000000000 -0400
@@ -959,5 +959,4 @@ module_comedi_usb_driver(vmk80xx_driver,
 MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
 MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
 MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
-MODULE_VERSION("0.8.01");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/drivers.c linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers.c
--- linux-libre-3.16-gnu/drivers/staging/comedi/drivers.c	2014-08-07 04:58:52.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/drivers.c	2014-09-28 21:41:28.000000000 -0400
@@ -38,6 +38,7 @@
 #include "comedi_internal.h"
 
 struct comedi_driver *comedi_drivers;
+/* protects access to comedi_drivers */
 DEFINE_MUTEX(comedi_drivers_list_lock);
 
 int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
@@ -120,6 +121,7 @@ static void comedi_device_detach_cleanup
 	dev->driver = NULL;
 	dev->board_name = NULL;
 	dev->board_ptr = NULL;
+	dev->mmio = NULL;
 	dev->iobase = 0;
 	dev->iolen = 0;
 	dev->ioenabled = false;
@@ -319,7 +321,7 @@ static int __comedi_device_postconfig_as
 		return -ENOMEM;
 	}
 	if (s->buf_change) {
-		ret = s->buf_change(dev, s, buf_size);
+		ret = s->buf_change(dev, s);
 		if (ret < 0)
 			return ret;
 	}
@@ -566,8 +568,9 @@ int comedi_device_attach(struct comedi_d
 			dev->board_ptr = comedi_recognize(driv, it->board_name);
 			if (dev->board_ptr)
 				break;
-		} else if (strcmp(driv->driver_name, it->board_name) == 0)
+		} else if (strcmp(driv->driver_name, it->board_name) == 0) {
 			break;
+		}
 		module_put(driv->module);
 	}
 	if (driv == NULL) {
@@ -591,8 +594,6 @@ int comedi_device_attach(struct comedi_d
 		ret = -ENOSYS;
 		goto out;
 	}
-	/* initialize dev->driver here so
-	 * comedi_error() can be called from attach */
 	dev->driver = driv;
 	dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr
 					 : dev->driver->driver_name;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/comedi/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/comedi/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/comedi/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/comedi/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -135,13 +135,14 @@ config COMEDI_PCL724
 	  support driver.
 
 	  Supported boards include:
-	    Advantech PCL-724    24 channels
-	    Advantech PCL-722    144 (or 96) channels
-	    Advantech PCL-731    48 channels
-	    ADlink ACL-7122      144 (or 96) channels
-	    ADlink ACL-7124      24 channels
-	    ADlink PET-48DIO     48 channels
-	    WinSystems PCM-IO48  48 channels (PC/104)
+	    Advantech PCL-724            24 channels
+	    Advantech PCL-722            144 (or 96) channels
+	    Advantech PCL-731            48 channels
+	    ADlink ACL-7122              144 (or 96) channels
+	    ADlink ACL-7124              24 channels
+	    ADlink PET-48DIO             48 channels
+	    WinSystems PCM-IO48          48 channels (PC/104)
+	    Diamond Systems ONYX-MM-DIO  48 channels (PC/104)
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called pcl724.
@@ -172,6 +173,7 @@ config COMEDI_PCL730
 	  Advantech PCL-734             iso - 32 out
 	  Diamond Systems OPMM-1616-XT  iso - 16 in/16 out
 	  Diamond Systems PEARL-MM-P    iso - 16 out
+	  Diamond Systems IR104-PBF     iso - 20 in/20 out
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called pcl730.
@@ -813,7 +815,7 @@ config COMEDI_AMPLC_PC236_PCI
 	  Enable support for Amplicon PCI236 DIO board.
 
 	  To compile this driver as a module, choose M here: the module will be
-	  called amplc_pc236.
+	  called amplc_pci236.
 
 config COMEDI_AMPLC_PC263_PCI
 	tristate "Amplicon PCI263 relay board support"
@@ -1012,8 +1014,6 @@ config COMEDI_NI_6527
 
 config COMEDI_NI_65XX
 	tristate "NI 65xx static dio PCI card support"
-	depends on HAS_DMA
-	select COMEDI_MITE
 	---help---
 	  Enable support for National Instruments 65xx static dio boards.
 	  Supported devices: National Instruments PCI-6509 (ni_65xx),
@@ -1037,8 +1037,6 @@ config COMEDI_NI_660X
 
 config COMEDI_NI_670X
 	tristate "NI 670x PCI card support"
-	depends on HAS_DMA
-	select COMEDI_MITE
 	---help---
 	  Enable support for National Instruments PCI-6703 and PCI-6704
 
@@ -1047,9 +1045,7 @@ config COMEDI_NI_670X
 
 config COMEDI_NI_LABPC_PCI
 	tristate "NI Lab-PC PCI-1200 support"
-	depends on HAS_DMA
 	select COMEDI_NI_LABPC
-	select COMEDI_MITE
 	---help---
 	  Enable support for National Instruments Lab-PC PCI-1200.
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cptm1217/clearpad_tm1217.c linux-libre-3.17-rc7-gnu/drivers/staging/cptm1217/clearpad_tm1217.c
--- linux-libre-3.16-gnu/drivers/staging/cptm1217/clearpad_tm1217.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cptm1217/clearpad_tm1217.c	2014-09-28 17:29:07.000000000 -0400
@@ -147,12 +147,11 @@ static int cp_tm1217_read(struct cp_tm12
 	msleep(WAIT_FOR_RESPONSE);
 	for (i = 0; i < MAX_RETRIES; i++) {
 		retval = i2c_master_recv(ts->client, &req[1], size);
-		if (retval == size) {
+		if (retval == size)
 			break;
-		} else {
-			msleep(INCREMENTAL_DELAY);
-			dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i);
-		}
+
+		msleep(INCREMENTAL_DELAY);
+		dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i);
 	}
 	if (retval != size)
 		dev_err(ts->dev, "cp_tm1217: Read from device failed\n");
@@ -288,11 +287,11 @@ static irqreturn_t cp_tm1217_sample_thre
 	if (ts->thread_running == 1) {
 		mutex_unlock(&ts->thread_mutex);
 		return IRQ_HANDLED;
-	} else {
-		ts->thread_running = 1;
-		mutex_unlock(&ts->thread_mutex);
 	}
 
+	ts->thread_running = 1;
+	mutex_unlock(&ts->thread_mutex);
+
 	/* Mask the interrupts */
 	retval = cp_tm1217_mask_interrupt(ts);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/bc_dts_defs.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bc_dts_defs.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/bc_dts_defs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bc_dts_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,572 +0,0 @@
-/********************************************************************
- * Copyright(c) 2006-2009 Broadcom Corporation.
- *
- *  Name: bc_dts_defs.h
- *
- *  Description: Common definitions for all components. Only types
- *		 is allowed to be included from this file.
- *
- *  AU
- *
- *  HISTORY:
- *
- ********************************************************************
- * This header 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.
- *
- * This header is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header.  If not, see <http://www.gnu.org/licenses/>.
- *******************************************************************/
-
-#ifndef _BC_DTS_DEFS_H_
-#define _BC_DTS_DEFS_H_
-
-#include <linux/types.h>
-
-/* BIT Mask */
-#define BC_BIT(_x)		(1 << (_x))
-
-enum BC_STATUS {
-	BC_STS_SUCCESS		= 0,
-	BC_STS_INV_ARG		= 1,
-	BC_STS_BUSY		= 2,
-	BC_STS_NOT_IMPL		= 3,
-	BC_STS_PGM_QUIT		= 4,
-	BC_STS_NO_ACCESS	= 5,
-	BC_STS_INSUFF_RES	= 6,
-	BC_STS_IO_ERROR		= 7,
-	BC_STS_NO_DATA		= 8,
-	BC_STS_VER_MISMATCH	= 9,
-	BC_STS_TIMEOUT		= 10,
-	BC_STS_FW_CMD_ERR	= 11,
-	BC_STS_DEC_NOT_OPEN	= 12,
-	BC_STS_ERR_USAGE	= 13,
-	BC_STS_IO_USER_ABORT	= 14,
-	BC_STS_IO_XFR_ERROR	= 15,
-	BC_STS_DEC_NOT_STARTED	= 16,
-	BC_STS_FWHEX_NOT_FOUND	= 17,
-	BC_STS_FMT_CHANGE	= 18,
-	BC_STS_HIF_ACCESS	= 19,
-	BC_STS_CMD_CANCELLED	= 20,
-	BC_STS_FW_AUTH_FAILED	= 21,
-	BC_STS_BOOTLOADER_FAILED = 22,
-	BC_STS_CERT_VERIFY_ERROR = 23,
-	BC_STS_DEC_EXIST_OPEN	= 24,
-	BC_STS_PENDING		= 25,
-	BC_STS_CLK_NOCHG	= 26,
-
-	/* Must be the last one.*/
-	BC_STS_ERROR		= -1
-};
-
-/*------------------------------------------------------*
- *    Registry Key Definitions				*
- *------------------------------------------------------*/
-#define BC_REG_KEY_MAIN_PATH	"Software\\Broadcom\\MediaPC\\70010"
-#define BC_REG_KEY_FWPATH		"FirmwareFilePath"
-#define BC_REG_KEY_SEC_OPT		"DbgOptions"
-
-/*
- * Options:
- *
- *  b[5] = Enable RSA KEY in EEPROM Support
- *  b[6] = Enable Old PIB scheme. (0 = Use PIB with video scheme)
- *
- *  b[12] = Enable send message to NotifyIcon
- *
- */
-
-enum BC_SW_OPTIONS {
-	BC_OPT_DOSER_OUT_ENCRYPT	= BC_BIT(3),
-	BC_OPT_LINK_OUT_ENCRYPT		= BC_BIT(29),
-};
-
-struct BC_REG_CONFIG {
-	uint32_t		DbgOptions;
-};
-
-#if defined(__KERNEL__) || defined(__LINUX_USER__)
-#else
-/* Align data structures */
-#define ALIGN(x)	__declspec(align(x))
-#endif
-
-/* mode
- * b[0]..b[7]	= _DtsDeviceOpenMode
- * b[8]		=  Load new FW
- * b[9]		=  Load file play back FW
- * b[10]	=  Disk format (0 for HD DVD and 1 for BLU ray)
- * b[11]-b[15]	=  default output resolution
- * b[16]	=  Skip TX CPB Buffer Check
- * b[17]	=  Adaptive Output Encrypt/Scramble Scheme
- * b[18]-b[31]	=  reserved for future use
- */
-
-/* To allow multiple apps to open the device. */
-enum DtsDeviceOpenMode {
-	DTS_PLAYBACK_MODE = 0,
-	DTS_DIAG_MODE,
-	DTS_MONITOR_MODE,
-	DTS_HWINIT_MODE
-};
-
-/* To enable the filter to selectively enable/disable fixes or erratas */
-enum DtsDeviceFixMode {
-	DTS_LOAD_NEW_FW		= BC_BIT(8),
-	DTS_LOAD_FILE_PLAY_FW	= BC_BIT(9),
-	DTS_DISK_FMT_BD		= BC_BIT(10),
-	/* b[11]-b[15] : Default output resolution */
-	DTS_SKIP_TX_CHK_CPB	= BC_BIT(16),
-	DTS_ADAPTIVE_OUTPUT_PER	= BC_BIT(17),
-	DTS_INTELLIMAP		= BC_BIT(18),
-	/* b[19]-b[21] : select clock frequency */
-	DTS_PLAYBACK_DROP_RPT_MODE = BC_BIT(22)
-};
-
-#define DTS_DFLT_RESOLUTION(x)	(x<<11)
-
-#define DTS_DFLT_CLOCK(x) (x<<19)
-
-/* F/W File Version corresponding to S/W Releases */
-enum FW_FILE_VER {
-	/* S/W release: 02.04.02	F/W release 2.12.2.0 */
-	BC_FW_VER_020402 = ((12<<16) | (2<<8) | (0))
-};
-
-/*------------------------------------------------------*
- *    Stream Types for DtsOpenDecoder()			*
- *------------------------------------------------------*/
-enum DtsOpenDecStreamTypes {
-	BC_STREAM_TYPE_ES		= 0,
-	BC_STREAM_TYPE_PES		= 1,
-	BC_STREAM_TYPE_TS		= 2,
-	BC_STREAM_TYPE_ES_TSTAMP	= 6,
-};
-
-/*------------------------------------------------------*
- *    Video Algorithms for DtsSetVideoParams()		*
- *------------------------------------------------------*/
-enum DtsSetVideoParamsAlgo {
-	BC_VID_ALGO_H264		= 0,
-	BC_VID_ALGO_MPEG2		= 1,
-	BC_VID_ALGO_VC1			= 4,
-	BC_VID_ALGO_VC1MP		= 7,
-};
-
-/*------------------------------------------------------*
- *    MPEG Extension to the PPB				*
- *------------------------------------------------------*/
-#define BC_MPEG_VALID_PANSCAN		(1)
-
-struct BC_PIB_EXT_MPEG {
-	uint32_t	valid;
-	/* Always valid,  defaults to picture size if no
-	 * sequence display extension in the stream. */
-	uint32_t	display_horizontal_size;
-	uint32_t	display_vertical_size;
-
-	/* MPEG_VALID_PANSCAN
-	 * Offsets are a copy values from the MPEG stream. */
-	uint32_t	offset_count;
-	int32_t		horizontal_offset[3];
-	int32_t		vertical_offset[3];
-};
-
-/*------------------------------------------------------*
- *    H.264 Extension to the PPB			*
- *------------------------------------------------------*/
-/* Bit definitions for 'other.h264.valid' field */
-#define H264_VALID_PANSCAN		(1)
-#define H264_VALID_SPS_CROP		(2)
-#define H264_VALID_VUI			(4)
-
-struct BC_PIB_EXT_H264 {
-	/* 'valid' specifies which fields (or sets of
-	 * fields) below are valid.  If the corresponding
-	 * bit in 'valid' is NOT set then that field(s)
-	 * is (are) not initialized. */
-	uint32_t	valid;
-
-	/* H264_VALID_PANSCAN */
-	uint32_t	pan_scan_count;
-	int32_t		pan_scan_left[3];
-	int32_t		pan_scan_right[3];
-	int32_t		pan_scan_top[3];
-	int32_t		pan_scan_bottom[3];
-
-	/* H264_VALID_SPS_CROP */
-	int32_t		sps_crop_left;
-	int32_t		sps_crop_right;
-	int32_t		sps_crop_top;
-	int32_t		sps_crop_bottom;
-
-	/* H264_VALID_VUI */
-	uint32_t	chroma_top;
-	uint32_t	chroma_bottom;
-};
-
-/*------------------------------------------------------*
- *    VC1 Extension to the PPB				*
- *------------------------------------------------------*/
-#define VC1_VALID_PANSCAN		(1)
-
-struct BC_PIB_EXT_VC1 {
-	uint32_t	valid;
-
-	/* Always valid, defaults to picture size if no
-	 * sequence display extension in the stream. */
-	uint32_t	display_horizontal_size;
-	uint32_t	display_vertical_size;
-
-	/* VC1 pan scan windows */
-	uint32_t	num_panscan_windows;
-	int32_t		ps_horiz_offset[4];
-	int32_t		ps_vert_offset[4];
-	int32_t		ps_width[4];
-	int32_t		ps_height[4];
-};
-
-/*------------------------------------------------------*
- *    Picture Information Block				*
- *------------------------------------------------------*/
-#if defined(__LINUX_USER__)
-/* Values for 'pulldown' field.  '0' means no pulldown information
- * was present for this picture. */
-enum {
-	vdecNoPulldownInfo	= 0,
-	vdecTop			= 1,
-	vdecBottom		= 2,
-	vdecTopBottom		= 3,
-	vdecBottomTop		= 4,
-	vdecTopBottomTop	= 5,
-	vdecBottomTopBottom	= 6,
-	vdecFrame_X2		= 7,
-	vdecFrame_X3		= 8,
-	vdecFrame_X1		= 9,
-	vdecFrame_X4		= 10,
-};
-
-/* Values for the 'frame_rate' field. */
-enum {
-	vdecFrameRateUnknown = 0,
-	vdecFrameRate23_97,
-	vdecFrameRate24,
-	vdecFrameRate25,
-	vdecFrameRate29_97,
-	vdecFrameRate30,
-	vdecFrameRate50,
-	vdecFrameRate59_94,
-	vdecFrameRate60,
-};
-
-/* Values for the 'aspect_ratio' field. */
-enum {
-	vdecAspectRatioUnknown = 0,
-	vdecAspectRatioSquare,
-	vdecAspectRatio12_11,
-	vdecAspectRatio10_11,
-	vdecAspectRatio16_11,
-	vdecAspectRatio40_33,
-	vdecAspectRatio24_11,
-	vdecAspectRatio20_11,
-	vdecAspectRatio32_11,
-	vdecAspectRatio80_33,
-	vdecAspectRatio18_11,
-	vdecAspectRatio15_11,
-	vdecAspectRatio64_33,
-	vdecAspectRatio160_99,
-	vdecAspectRatio4_3,
-	vdecAspectRatio16_9,
-	vdecAspectRatio221_1,
-	vdecAspectRatioOther = 255,
-};
-
-/* Values for the 'colour_primaries' field. */
-enum {
-	vdecColourPrimariesUnknown = 0,
-	vdecColourPrimariesBT709,
-	vdecColourPrimariesUnspecified,
-	vdecColourPrimariesReserved,
-	vdecColourPrimariesBT470_2M = 4,
-	vdecColourPrimariesBT470_2BG,
-	vdecColourPrimariesSMPTE170M,
-	vdecColourPrimariesSMPTE240M,
-	vdecColourPrimariesGenericFilm,
-};
-/**
- * @vdecRESOLUTION_CUSTOM: custom
- * @vdecRESOLUTION_480i: 480i
- * @vdecRESOLUTION_1080i: 1080i (1920x1080, 60i)
- * @vdecRESOLUTION_NTSC: NTSC (720x483, 60i)
- * @vdecRESOLUTION_480p: 480p (720x480, 60p)
- * @vdecRESOLUTION_720p: 720p (1280x720, 60p)
- * @vdecRESOLUTION_PAL1: PAL_1 (720x576, 50i)
- * @vdecRESOLUTION_1080i25: 1080i25 (1920x1080, 50i)
- * @vdecRESOLUTION_720p50: 720p50 (1280x720, 50p)
- * @vdecRESOLUTION_576p: 576p (720x576, 50p)
- * @vdecRESOLUTION_1080i29_97: 1080i (1920x1080, 59.94i)
- * @vdecRESOLUTION_720p59_94: 720p (1280x720, 59.94p)
- * @vdecRESOLUTION_SD_DVD: SD DVD (720x483, 60i)
- * @vdecRESOLUTION_480p656: 480p (720x480, 60p),
- *	output bus width 8 bit, clock 74.25MHz
- * @vdecRESOLUTION_1080p23_976: 1080p23_976 (1920x1080, 23.976p)
- * @vdecRESOLUTION_720p23_976: 720p23_976 (1280x720p, 23.976p)
- * @vdecRESOLUTION_240p29_97: 240p (1440x240, 29.97p )
- * @vdecRESOLUTION_240p30: 240p (1440x240, 30p)
- * @vdecRESOLUTION_288p25: 288p (1440x288p, 25p)
- * @vdecRESOLUTION_1080p29_97: 1080p29_97 (1920x1080, 29.97p)
- * @vdecRESOLUTION_1080p30: 1080p30 (1920x1080, 30p)
- * @vdecRESOLUTION_1080p24: 1080p24 (1920x1080, 24p)
- * @vdecRESOLUTION_1080p25: 1080p25 (1920x1080, 25p)
- * @vdecRESOLUTION_720p24: 720p24 (1280x720, 25p)
- * @vdecRESOLUTION_720p29_97: 720p29.97 (1280x720, 29.97p)
- * @vdecRESOLUTION_480p23_976: 480p23.976 (720*480, 23.976)
- * @vdecRESOLUTION_480p29_97: 480p29.976 (720*480, 29.97p)
- * @vdecRESOLUTION_576p25: 576p25 (720*576, 25p)
- * @vdecRESOLUTION_480p0: 480p (720x480, 0p)
- * @vdecRESOLUTION_480i0: 480i (720x480, 0i)
- * @vdecRESOLUTION_576p0: 576p (720x576, 0p)
- * @vdecRESOLUTION_720p0: 720p (1280x720, 0p)
- * @vdecRESOLUTION_1080p0: 1080p (1920x1080, 0p)
- * @vdecRESOLUTION_1080i0: 1080i (1920x1080, 0i)
- */
-enum {
-	vdecRESOLUTION_CUSTOM	= 0x00000000,
-	vdecRESOLUTION_480i	= 0x00000001,
-	vdecRESOLUTION_1080i	= 0x00000002,
-	vdecRESOLUTION_NTSC	= 0x00000003,
-	vdecRESOLUTION_480p	= 0x00000004,
-	vdecRESOLUTION_720p	= 0x00000005,
-	vdecRESOLUTION_PAL1	= 0x00000006,
-	vdecRESOLUTION_1080i25	= 0x00000007,
-	vdecRESOLUTION_720p50	= 0x00000008,
-	vdecRESOLUTION_576p	= 0x00000009,
-	vdecRESOLUTION_1080i29_97 = 0x0000000A,
-	vdecRESOLUTION_720p59_94  = 0x0000000B,
-	vdecRESOLUTION_SD_DVD	= 0x0000000C,
-	vdecRESOLUTION_480p656	= 0x0000000D,
-	vdecRESOLUTION_1080p23_976 = 0x0000000E,
-	vdecRESOLUTION_720p23_976  = 0x0000000F,
-	vdecRESOLUTION_240p29_97   = 0x00000010,
-	vdecRESOLUTION_240p30	= 0x00000011,
-	vdecRESOLUTION_288p25	= 0x00000012,
-	vdecRESOLUTION_1080p29_97 = 0x00000013,
-	vdecRESOLUTION_1080p30	= 0x00000014,
-	vdecRESOLUTION_1080p24	= 0x00000015,
-	vdecRESOLUTION_1080p25	= 0x00000016,
-	vdecRESOLUTION_720p24	= 0x00000017,
-	vdecRESOLUTION_720p29_97  = 0x00000018,
-	vdecRESOLUTION_480p23_976 = 0x00000019,
-	vdecRESOLUTION_480p29_97  = 0x0000001A,
-	vdecRESOLUTION_576p25	= 0x0000001B,
-	/* For Zero Frame Rate */
-	vdecRESOLUTION_480p0	= 0x0000001C,
-	vdecRESOLUTION_480i0	= 0x0000001D,
-	vdecRESOLUTION_576p0	= 0x0000001E,
-	vdecRESOLUTION_720p0	= 0x0000001F,
-	vdecRESOLUTION_1080p0	= 0x00000020,
-	vdecRESOLUTION_1080i0	= 0x00000021,
-};
-
-/* Bit definitions for 'flags' field */
-#define VDEC_FLAG_EOS				(0x0004)
-
-#define VDEC_FLAG_FRAME				(0x0000)
-#define VDEC_FLAG_FIELDPAIR			(0x0008)
-#define VDEC_FLAG_TOPFIELD			(0x0010)
-#define VDEC_FLAG_BOTTOMFIELD			(0x0018)
-
-#define VDEC_FLAG_PROGRESSIVE_SRC		(0x0000)
-#define VDEC_FLAG_INTERLACED_SRC		(0x0020)
-#define VDEC_FLAG_UNKNOWN_SRC			(0x0040)
-
-#define VDEC_FLAG_BOTTOM_FIRST			(0x0080)
-#define VDEC_FLAG_LAST_PICTURE			(0x0100)
-
-#define VDEC_FLAG_PICTURE_META_DATA_PRESENT	(0x40000)
-
-#endif /* __LINUX_USER__ */
-
-enum _BC_OUTPUT_FORMAT {
-	MODE420				= 0x0,
-	MODE422_YUY2			= 0x1,
-	MODE422_UYVY			= 0x2,
-};
-/**
- * struct BC_PIC_INFO_BLOCK
- * @timeStam;: Timestamp
- * @picture_number: Ordinal display number
- * @width:  pixels
- * @height:  pixels
- * @chroma_format:  0x420, 0x422 or 0x444
- * @n_drop;:  number of non-reference frames
- *	remaining to be dropped
- */
-struct BC_PIC_INFO_BLOCK {
-	/* Common fields. */
-	uint64_t	timeStamp;
-	uint32_t	picture_number;
-	uint32_t	width;
-	uint32_t	height;
-	uint32_t	chroma_format;
-	uint32_t	pulldown;
-	uint32_t	flags;
-	uint32_t	frame_rate;
-	uint32_t	aspect_ratio;
-	uint32_t	colour_primaries;
-	uint32_t	picture_meta_payload;
-	uint32_t	sess_num;
-	uint32_t	ycom;
-	uint32_t	custom_aspect_ratio_width_height;
-	uint32_t	n_drop;	/* number of non-reference frames
-					remaining to be dropped */
-
-	/* Protocol-specific extensions. */
-	union {
-		struct BC_PIB_EXT_H264	h264;
-		struct BC_PIB_EXT_MPEG	mpeg;
-		struct BC_PIB_EXT_VC1	 vc1;
-	} other;
-
-};
-
-/*------------------------------------------------------*
- *    ProcOut Info					*
- *------------------------------------------------------*/
-
-/**
- * enum POUT_OPTIONAL_IN_FLAGS - Optional flags for ProcOut Interface.
- * @BC_POUT_FLAGS_YV12:  Copy Data in YV12 format
- * @BC_POUT_FLAGS_STRIDE:  Stride size is valid.
- * @BC_POUT_FLAGS_SIZE:  Take size information from Application
- * @BC_POUT_FLAGS_INTERLACED:  copy only half the bytes
- * @BC_POUT_FLAGS_INTERLEAVED:  interleaved frame
- * @:  * @BC_POUT_FLAGS_FMT_CHANGE:  Data is not VALID when this flag is set
- * @BC_POUT_FLAGS_PIB_VALID:  PIB Information valid
- * @BC_POUT_FLAGS_ENCRYPTED:  Data is encrypted.
- * @BC_POUT_FLAGS_FLD_BOT:  Bottom Field data
- */
-enum POUT_OPTIONAL_IN_FLAGS_ {
-	/* Flags from App to Device */
-	BC_POUT_FLAGS_YV12	  = 0x01,
-	BC_POUT_FLAGS_STRIDE	  = 0x02,
-	BC_POUT_FLAGS_SIZE	  = 0x04,
-	BC_POUT_FLAGS_INTERLACED  = 0x08,
-	BC_POUT_FLAGS_INTERLEAVED = 0x10,
-
-	/* Flags from Device to APP */
-	BC_POUT_FLAGS_FMT_CHANGE  = 0x10000,
-	BC_POUT_FLAGS_PIB_VALID	  = 0x20000,
-	BC_POUT_FLAGS_ENCRYPTED	  = 0x40000,
-	BC_POUT_FLAGS_FLD_BOT	  = 0x80000,
-};
-
-typedef enum BC_STATUS(*dts_pout_callback)(void  *shnd, uint32_t width,
-			uint32_t height, uint32_t stride, void *pOut);
-
-/* Line 21 Closed Caption */
-/* User Data */
-#define MAX_UD_SIZE		1792	/* 1920 - 128 */
-
-/**
- * struct BC_DTS_PROC_OUT
- * @Ybuff: Caller Supplied buffer for Y data
- * @YbuffSz: Caller Supplied Y buffer size
- * @YBuffDoneSz: Transferred Y datasize
- * @*UVbuff: Caller Supplied buffer for UV data
- * @UVbuffSz: Caller Supplied UV buffer size
- * @UVBuffDoneSz: Transferred UV data size
- * @StrideSz: Caller supplied Stride Size
- * @PoutFlags: Call IN Flags
- * @discCnt: Picture discontinuity count
- * @PicInfo: Picture Information Block Data
- * @b422Mode: Picture output Mode
- * @bPibEnc: PIB encrypted
- */
-struct BC_DTS_PROC_OUT {
-	uint8_t		*Ybuff;
-	uint32_t	YbuffSz;
-	uint32_t	YBuffDoneSz;
-
-	uint8_t		*UVbuff;
-	uint32_t	UVbuffSz;
-	uint32_t	UVBuffDoneSz;
-
-	uint32_t	StrideSz;
-	uint32_t	PoutFlags;
-
-	uint32_t	discCnt;
-
-	struct BC_PIC_INFO_BLOCK PicInfo;
-
-	/* Line 21 Closed Caption */
-	/* User Data */
-	uint32_t	UserDataSz;
-	uint8_t		UserData[MAX_UD_SIZE];
-
-	void		*hnd;
-	dts_pout_callback AppCallBack;
-	uint8_t		DropFrames;
-	uint8_t		b422Mode;
-	uint8_t		bPibEnc;
-	uint8_t		bRevertScramble;
-
-};
-/**
- * struct BC_DTS_STATUS
- * @ReadyListCount: Number of frames in ready list (reported by driver)
- * @PowerStateChange: Number of active state power
- *	transitions (reported by driver)
- * @FramesDropped:  Number of frames dropped.  (reported by DIL)
- * @FramesCaptured: Number of frames captured. (reported by DIL)
- * @FramesRepeated: Number of frames repeated. (reported by DIL)
- * @InputCount:	Times compressed video has been sent to the HW.
- *	i.e. Successful DtsProcInput() calls (reported by DIL)
- * @InputTotalSize: Amount of compressed video that has been sent to the HW.
- *	(reported by DIL)
- * @InputBusyCount: Times compressed video has attempted to be sent to the HW
- *	but the input FIFO was full. (reported by DIL)
- * @PIBMissCount: Amount of times a PIB is invalid. (reported by DIL)
- * @cpbEmptySize: supported only for H.264, specifically changed for
- *	Adobe. Report size of CPB buffer available. (reported by DIL)
- * @NextTimeStamp: TimeStamp of the next picture that will be returned
- *	by a call to ProcOutput. Added for Adobe. Reported
- *	back from the driver
- */
-struct BC_DTS_STATUS {
-	uint8_t		ReadyListCount;
-	uint8_t		FreeListCount;
-	uint8_t		PowerStateChange;
-	uint8_t		reserved_[1];
-	uint32_t	FramesDropped;
-	uint32_t	FramesCaptured;
-	uint32_t	FramesRepeated;
-	uint32_t	InputCount;
-	uint64_t	InputTotalSize;
-	uint32_t	InputBusyCount;
-	uint32_t	PIBMissCount;
-	uint32_t	cpbEmptySize;
-	uint64_t	NextTimeStamp;
-	uint8_t		reserved__[16];
-};
-
-#define BC_SWAP32(_v)			\
-	((((_v) & 0xFF000000)>>24)|	\
-	  (((_v) & 0x00FF0000)>>8)|	\
-	  (((_v) & 0x0000FF00)<<8)|	\
-	  (((_v) & 0x000000FF)<<24))
-
-#define WM_AGENT_TRAYICON_DECODER_OPEN	10001
-#define WM_AGENT_TRAYICON_DECODER_CLOSE	10002
-#define WM_AGENT_TRAYICON_DECODER_START	10003
-#define WM_AGENT_TRAYICON_DECODER_STOP	10004
-#define WM_AGENT_TRAYICON_DECODER_RUN	10005
-#define WM_AGENT_TRAYICON_DECODER_PAUSE	10006
-
-
-#endif	/* _BC_DTS_DEFS_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/bc_dts_glob_lnx.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bc_dts_glob_lnx.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/bc_dts_glob_lnx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bc_dts_glob_lnx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,300 +0,0 @@
-/********************************************************************
- * Copyright(c) 2006-2009 Broadcom Corporation.
- *
- *  Name: bc_dts_glob_lnx.h
- *
- *  Description: Wrapper to Windows dts_glob.h for Link-Linux usage.
- *		 The idea is to define additional Linux related defs
- *		 in this file to avoid changes to existing Windows
- *		 glob file.
- *
- *  AU
- *
- *  HISTORY:
- *
- ********************************************************************
- * This header 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.
- *
- * This header is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header.  If not, see <http://www.gnu.org/licenses/>.
- *******************************************************************/
-
-#ifndef _BC_DTS_GLOB_LNX_H_
-#define _BC_DTS_GLOB_LNX_H_
-
-#ifdef __LINUX_USER__
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <netdb.h>
-#include <sys/time.h>
-#include <time.h>
-#include <arpa/inet.h>
-#include <linux/param.h>
-#include <linux/ioctl.h>
-#include <sys/select.h>
-
-#define DRVIFLIB_INT_API
-
-#endif
-
-#include "crystalhd.h"
-
-#define CRYSTALHD_API_NAME	"crystalhd"
-#define CRYSTALHD_API_DEV_NAME	"/dev/crystalhd"
-
-/*
- * These are SW stack tunable parameters shared
- * between the driver and the application.
- */
-enum BC_DTS_GLOBALS {
-	BC_MAX_FW_CMD_BUFF_SZ = 0x40, /* FW passthrough cmd/rsp buffer size */
-	PCI_CFG_SIZE		= 256,		/* PCI config size buffer */
-	BC_IOCTL_DATA_POOL_SIZE	= 8,		/* BC_IOCTL_DATA Pool size */
-	BC_LINK_MAX_OPENS	= 3,	/* Maximum simultaneous opens*/
-	BC_LINK_MAX_SGLS	= 1024,	/* Maximum SG elements 4M/4K */
-	BC_TX_LIST_CNT		= 2,		/* Max Tx DMA Rings */
-	BC_RX_LIST_CNT		= 8,		/* Max Rx DMA Rings*/
-	BC_PROC_OUTPUT_TIMEOUT	= 3000,		/* Milliseconds */
-	BC_INFIFO_THRESHOLD	= 0x10000,
-};
-
-struct BC_CMD_REG_ACC {
-	uint32_t		Offset;
-	uint32_t		Value;
-};
-
-struct BC_CMD_DEV_MEM {
-	uint32_t		StartOff;
-	uint32_t		NumDwords;
-	uint32_t		Rsrd;
-};
-
-/* FW Passthrough command structure */
-enum bc_fw_cmd_flags {
-	BC_FW_CMD_FLAGS_NONE	= 0,
-	BC_FW_CMD_PIB_QS	= 0x01,
-};
-
-struct BC_FW_CMD {
-	uint32_t		cmd[BC_MAX_FW_CMD_BUFF_SZ];
-	uint32_t		rsp[BC_MAX_FW_CMD_BUFF_SZ];
-	uint32_t		flags;
-	uint32_t		add_data;
-};
-
-struct BC_HW_TYPE {
-	uint16_t		PciDevId;
-	uint16_t		PciVenId;
-	uint8_t			HwRev;
-	uint8_t			Align[3];
-};
-
-struct BC_PCI_CFG {
-	uint32_t		Size;
-	uint32_t		Offset;
-	uint8_t			pci_cfg_space[PCI_CFG_SIZE];
-};
-
-struct BC_VERSION_INFO {
-	uint8_t			DriverMajor;
-	uint8_t			DriverMinor;
-	uint16_t		DriverRevision;
-};
-
-struct BC_START_RX_CAP {
-	uint32_t		Rsrd;
-	uint32_t		StartDeliveryThsh;
-	uint32_t		PauseThsh;
-	uint32_t		ResumeThsh;
-};
-
-struct BC_FLUSH_RX_CAP {
-	uint32_t		Rsrd;
-	uint32_t		bDiscardOnly;
-};
-
-struct BC_DTS_STATS {
-	uint8_t			drvRLL;
-	uint8_t			drvFLL;
-	uint8_t			eosDetected;
-	uint8_t			pwr_state_change;
-
-	/* Stats from App */
-	uint32_t		opFrameDropped;
-	uint32_t		opFrameCaptured;
-	uint32_t		ipSampleCnt;
-	uint64_t		ipTotalSize;
-	uint32_t		reptdFrames;
-	uint32_t		pauseCount;
-	uint32_t		pibMisses;
-	uint32_t		discCounter;
-
-	/* Stats from Driver */
-	uint32_t		TxFifoBsyCnt;
-	uint32_t		intCount;
-	uint32_t		DrvIgnIntrCnt;
-	uint32_t		DrvTotalFrmDropped;
-	uint32_t		DrvTotalHWErrs;
-	uint32_t		DrvTotalPIBFlushCnt;
-	uint32_t		DrvTotalFrmCaptured;
-	uint32_t		DrvPIBMisses;
-	uint32_t		DrvPauseTime;
-	uint32_t		DrvRepeatedFrms;
-	uint32_t		res1[13];
-
-};
-
-struct BC_PROC_INPUT {
-	uint8_t			*pDmaBuff;
-	uint32_t		BuffSz;
-	uint8_t			Mapped;
-	uint8_t			Encrypted;
-	uint8_t			Rsrd[2];
-	uint32_t		DramOffset;	/* For debug use only */
-};
-
-struct BC_DEC_YUV_BUFFS {
-	uint32_t		b422Mode;
-	uint8_t			*YuvBuff;
-	uint32_t		YuvBuffSz;
-	uint32_t		UVbuffOffset;
-	uint32_t		YBuffDoneSz;
-	uint32_t		UVBuffDoneSz;
-	uint32_t		RefCnt;
-};
-
-enum DECOUT_COMPLETION_FLAGS {
-	COMP_FLAG_NO_INFO	= 0x00,
-	COMP_FLAG_FMT_CHANGE	= 0x01,
-	COMP_FLAG_PIB_VALID	= 0x02,
-	COMP_FLAG_DATA_VALID	= 0x04,
-	COMP_FLAG_DATA_ENC	= 0x08,
-	COMP_FLAG_DATA_BOT	= 0x10,
-};
-
-struct BC_DEC_OUT_BUFF {
-	struct BC_DEC_YUV_BUFFS	OutPutBuffs;
-	struct BC_PIC_INFO_BLOCK PibInfo;
-	uint32_t		Flags;
-	uint32_t		BadFrCnt;
-};
-
-struct BC_NOTIFY_MODE {
-	uint32_t		Mode;
-	uint32_t		Rsvr[3];
-};
-
-struct BC_CLOCK {
-	uint32_t		clk;
-	uint32_t		Rsvr[3];
-};
-
-struct BC_IOCTL_DATA {
-	enum BC_STATUS		RetSts;
-	uint32_t		IoctlDataSz;
-	uint32_t		Timeout;
-	union {
-		struct BC_CMD_REG_ACC	regAcc;
-		struct BC_CMD_DEV_MEM	devMem;
-		struct BC_FW_CMD	fwCmd;
-		struct BC_HW_TYPE	hwType;
-		struct BC_PCI_CFG	pciCfg;
-		struct BC_VERSION_INFO	VerInfo;
-		struct BC_PROC_INPUT	ProcInput;
-		struct BC_DEC_YUV_BUFFS	RxBuffs;
-		struct BC_DEC_OUT_BUFF	DecOutData;
-		struct BC_START_RX_CAP	RxCap;
-		struct BC_FLUSH_RX_CAP	FlushRxCap;
-		struct BC_DTS_STATS	drvStat;
-		struct BC_NOTIFY_MODE	NotifyMode;
-		struct BC_CLOCK		clockValue;
-	} u;
-	struct _BC_IOCTL_DATA	*next;
-};
-
-enum BC_DRV_CMD {
-	DRV_CMD_VERSION = 0,	/* Get SW version */
-	DRV_CMD_GET_HWTYPE,	/* Get HW version and type Dozer/Tank */
-	DRV_CMD_REG_RD,		/* Read Device Register */
-	DRV_CMD_REG_WR,		/* Write Device Register */
-	DRV_CMD_FPGA_RD,	/* Read FPGA Register */
-	DRV_CMD_FPGA_WR,	/* Write FPGA Register */
-	DRV_CMD_MEM_RD,		/* Read Device Memory */
-	DRV_CMD_MEM_WR,		/* Write Device Memory */
-	DRV_CMD_RD_PCI_CFG,	/* Read PCI Config Space */
-	DRV_CMD_WR_PCI_CFG,	/* Write the PCI Configuration Space*/
-	DRV_CMD_FW_DOWNLOAD,	/* Download Firmware */
-	DRV_ISSUE_FW_CMD,	/* Issue FW Cmd (pass through mode) */
-	DRV_CMD_PROC_INPUT,	/* Process Input Sample */
-	DRV_CMD_ADD_RXBUFFS,	/* Add Rx side buffers to driver pool */
-	DRV_CMD_FETCH_RXBUFF,	/* Get Rx DMAed buffer */
-	DRV_CMD_START_RX_CAP,	/* Start Rx Buffer Capture */
-	DRV_CMD_FLUSH_RX_CAP,	/* Stop the capture for now...
-			we will enhance this later*/
-	DRV_CMD_GET_DRV_STAT,	/* Get Driver Internal Statistics */
-	DRV_CMD_RST_DRV_STAT,	/* Reset Driver Internal Statistics */
-	DRV_CMD_NOTIFY_MODE,	/* Notify the Mode to driver
-			in which the application is Operating*/
-	DRV_CMD_CHANGE_CLOCK,	/* Change the core clock to either save power
-			or improve performance */
-
-	/* MUST be the last one.. */
-	DRV_CMD_END,			/* End of the List.. */
-};
-
-#define BC_IOC_BASE		'b'
-#define BC_IOC_VOID		_IOC_NONE
-#define BC_IOC_IOWR(nr, type)	_IOWR(BC_IOC_BASE, nr, type)
-#define BC_IOCTL_MB		struct BC_IOCTL_DATA
-
-#define	BCM_IOC_GET_VERSION	BC_IOC_IOWR(DRV_CMD_VERSION, BC_IOCTL_MB)
-#define	BCM_IOC_GET_HWTYPE	BC_IOC_IOWR(DRV_CMD_GET_HWTYPE, BC_IOCTL_MB)
-#define	BCM_IOC_REG_RD		BC_IOC_IOWR(DRV_CMD_REG_RD, BC_IOCTL_MB)
-#define	BCM_IOC_REG_WR		BC_IOC_IOWR(DRV_CMD_REG_WR, BC_IOCTL_MB)
-#define	BCM_IOC_MEM_RD		BC_IOC_IOWR(DRV_CMD_MEM_RD, BC_IOCTL_MB)
-#define	BCM_IOC_MEM_WR		BC_IOC_IOWR(DRV_CMD_MEM_WR, BC_IOCTL_MB)
-#define BCM_IOC_FPGA_RD		BC_IOC_IOWR(DRV_CMD_FPGA_RD, BC_IOCTL_MB)
-#define BCM_IOC_FPGA_WR		BC_IOC_IOWR(DRV_CMD_FPGA_WR, BC_IOCTL_MB)
-#define	BCM_IOC_RD_PCI_CFG	BC_IOC_IOWR(DRV_CMD_RD_PCI_CFG, BC_IOCTL_MB)
-#define	BCM_IOC_WR_PCI_CFG	BC_IOC_IOWR(DRV_CMD_WR_PCI_CFG, BC_IOCTL_MB)
-#define BCM_IOC_PROC_INPUT	BC_IOC_IOWR(DRV_CMD_PROC_INPUT, BC_IOCTL_MB)
-#define BCM_IOC_ADD_RXBUFFS	BC_IOC_IOWR(DRV_CMD_ADD_RXBUFFS, BC_IOCTL_MB)
-#define BCM_IOC_FETCH_RXBUFF	BC_IOC_IOWR(DRV_CMD_FETCH_RXBUFF, BC_IOCTL_MB)
-#define	BCM_IOC_FW_CMD		BC_IOC_IOWR(DRV_ISSUE_FW_CMD, BC_IOCTL_MB)
-#define	BCM_IOC_START_RX_CAP	BC_IOC_IOWR(DRV_CMD_START_RX_CAP, BC_IOCTL_MB)
-#define BCM_IOC_FLUSH_RX_CAP	BC_IOC_IOWR(DRV_CMD_FLUSH_RX_CAP, BC_IOCTL_MB)
-#define BCM_IOC_GET_DRV_STAT	BC_IOC_IOWR(DRV_CMD_GET_DRV_STAT, BC_IOCTL_MB)
-#define BCM_IOC_RST_DRV_STAT	BC_IOC_IOWR(DRV_CMD_RST_DRV_STAT, BC_IOCTL_MB)
-#define BCM_IOC_NOTIFY_MODE	BC_IOC_IOWR(DRV_CMD_NOTIFY_MODE, BC_IOCTL_MB)
-#define	BCM_IOC_FW_DOWNLOAD	BC_IOC_IOWR(DRV_CMD_FW_DOWNLOAD, BC_IOCTL_MB)
-#define BCM_IOC_CHG_CLK		BC_IOC_IOWR(DRV_CMD_CHANGE_CLOCK, BC_IOCTL_MB)
-#define	BCM_IOC_END		BC_IOC_VOID
-
-/* Wrapper for main IOCTL data */
-struct crystalhd_ioctl_data {
-	struct BC_IOCTL_DATA	udata;		/* IOCTL from App..*/
-	uint32_t		u_id;		/* Driver specific user ID */
-	uint32_t		cmd;		/* Cmd ID for driver's use. */
-	void	 *add_cdata;	/* Additional command specific data..*/
-	uint32_t add_cdata_sz;	/* Additional command specific data size */
-	struct crystalhd_ioctl_data *next;	/* List/Fifo management */
-};
-
-enum crystalhd_kmod_ver {
-	crystalhd_kmod_major	= 0,
-	crystalhd_kmod_minor	= 9,
-	crystalhd_kmod_rev	= 27,
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/bcm_70012_regs.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bcm_70012_regs.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/bcm_70012_regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/bcm_70012_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,758 +0,0 @@
-/***************************************************************************
- * Copyright (c) 1999-2009, Broadcom Corporation.
- *
- *  Name: bcm_70012_regs.h
- *
- *  Description: BCM70012 registers
- *
- ********************************************************************
- * This header 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.
- *
- * This header is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header.  If not, see <http://www.gnu.org/licenses/>.
- ***************************************************************************/
-
-#ifndef MACFILE_H__
-#define MACFILE_H__
-
-/**
- * m = memory, c = core, r = register, f = field, d = data.
- */
-#if !defined(GET_FIELD) && !defined(SET_FIELD)
-#define BRCM_ALIGN(c, r, f)   c##_##r##_##f##_ALIGN
-#define BRCM_BITS(c, r, f)    c##_##r##_##f##_BITS
-#define BRCM_MASK(c, r, f)    c##_##r##_##f##_MASK
-#define BRCM_SHIFT(c, r, f)   c##_##r##_##f##_SHIFT
-
-#define GET_FIELD(m, c, r, f) \
-	((((m) & BRCM_MASK(c, r, f)) >> BRCM_SHIFT(c, r, f)) << \
-	 BRCM_ALIGN(c, r, f))
-
-#define SET_FIELD(m, c, r, f, d) \
-	((m) = (((m) & ~BRCM_MASK(c, r, f)) | ((((d) >> BRCM_ALIGN(c, r, f)) << \
-	 BRCM_SHIFT(c, r, f)) & BRCM_MASK(c, r, f))) \
-	)
-
-#define SET_TYPE_FIELD(m, c, r, f, d) SET_FIELD(m, c, r, f, c##_##d)
-#define SET_NAME_FIELD(m, c, r, f, d) SET_FIELD(m, c, r, f, c##_##r##_##f##_##d)
-#define SET_VALUE_FIELD(m, c, r, f, d) SET_FIELD(m, c, r, f, d)
-
-#endif /* GET & SET */
-
-/****************************************************************************
- * Core Enums.
- ***************************************************************************/
-/****************************************************************************
- * Enums: AES_RGR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define AES_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
-#define AES_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
-
-/****************************************************************************
- * Enums: CCE_RGR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define CCE_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
-#define CCE_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
-
-/****************************************************************************
- * Enums: DBU_RGR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define DBU_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
-#define DBU_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
-
-/****************************************************************************
- * Enums: DCI_RGR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define DCI_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
-#define DCI_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
-
-/****************************************************************************
- * Enums: GISB_ARBITER_DEASSERT_ASSERT
- ***************************************************************************/
-#define GISB_ARBITER_DEASSERT_ASSERT_DEASSERT              0
-#define GISB_ARBITER_DEASSERT_ASSERT_ASSERT                1
-
-/****************************************************************************
- * Enums: GISB_ARBITER_UNMASK_MASK
- ***************************************************************************/
-#define GISB_ARBITER_UNMASK_MASK_UNMASK                    0
-#define GISB_ARBITER_UNMASK_MASK_MASK                      1
-
-/****************************************************************************
- * Enums: GISB_ARBITER_DISABLE_ENABLE
- ***************************************************************************/
-#define GISB_ARBITER_DISABLE_ENABLE_DISABLE                0
-#define GISB_ARBITER_DISABLE_ENABLE_ENABLE                 1
-
-/****************************************************************************
- * Enums: I2C_GR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define I2C_GR_BRIDGE_RESET_CTRL_DEASSERT                  0
-#define I2C_GR_BRIDGE_RESET_CTRL_ASSERT                    1
-
-/****************************************************************************
- * Enums: MISC_GR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define MISC_GR_BRIDGE_RESET_CTRL_DEASSERT                 0
-#define MISC_GR_BRIDGE_RESET_CTRL_ASSERT                   1
-
-/****************************************************************************
- * Enums: OTP_GR_BRIDGE_RESET_CTRL
- ***************************************************************************/
-#define OTP_GR_BRIDGE_RESET_CTRL_DEASSERT                  0
-#define OTP_GR_BRIDGE_RESET_CTRL_ASSERT                    1
-
-/****************************************************************************
- * BCM70012_TGT_TOP_PCIE_CFG
- ***************************************************************************/
-#define PCIE_CFG_DEVICE_VENDOR_ID      0x00000000 /* DEVICE_VENDOR_ID Register */
-#define PCIE_CFG_STATUS_COMMAND        0x00000004 /* STATUS_COMMAND Register */
-#define PCIE_CFG_PCI_CLASSCODE_AND_REVISION_ID 0x00000008 /* PCI_CLASSCODE_AND_REVISION_ID Register */
-#define PCIE_CFG_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE 0x0000000c /* BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE Register */
-#define PCIE_CFG_BASE_ADDRESS_1        0x00000010 /* BASE_ADDRESS_1 Register */
-#define PCIE_CFG_BASE_ADDRESS_2        0x00000014 /* BASE_ADDRESS_2 Register */
-#define PCIE_CFG_BASE_ADDRESS_3        0x00000018 /* BASE_ADDRESS_3 Register */
-#define PCIE_CFG_BASE_ADDRESS_4        0x0000001c /* BASE_ADDRESS_4 Register */
-#define PCIE_CFG_CARDBUS_CIS_POINTER   0x00000028 /* CARDBUS_CIS_POINTER Register */
-#define PCIE_CFG_SUBSYSTEM_DEVICE_VENDOR_ID 0x0000002c /* SUBSYSTEM_DEVICE_VENDOR_ID Register */
-#define PCIE_CFG_EXPANSION_ROM_BASE_ADDRESS 0x00000030 /* EXPANSION_ROM_BASE_ADDRESS Register */
-#define PCIE_CFG_CAPABILITIES_POINTER  0x00000034 /* CAPABILITIES_POINTER Register */
-#define PCIE_CFG_INTERRUPT             0x0000003c /* INTERRUPT Register */
-#define PCIE_CFG_VPD_CAPABILITIES      0x00000040 /* VPD_CAPABILITIES Register */
-#define PCIE_CFG_VPD_DATA              0x00000044 /* VPD_DATA Register */
-#define PCIE_CFG_POWER_MANAGEMENT_CAPABILITY 0x00000048 /* POWER_MANAGEMENT_CAPABILITY Register */
-#define PCIE_CFG_POWER_MANAGEMENT_CONTROL_STATUS 0x0000004c /* POWER_MANAGEMENT_CONTROL_STATUS Register */
-#define PCIE_CFG_MSI_CAPABILITY_HEADER 0x00000050 /* MSI_CAPABILITY_HEADER Register */
-#define PCIE_CFG_MSI_LOWER_ADDRESS     0x00000054 /* MSI_LOWER_ADDRESS Register */
-#define PCIE_CFG_MSI_UPPER_ADDRESS_REGISTER 0x00000058 /* MSI_UPPER_ADDRESS_REGISTER Register */
-#define PCIE_CFG_MSI_DATA              0x0000005c /* MSI_DATA Register */
-#define PCIE_CFG_BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER 0x00000060 /* BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER Register */
-#define PCIE_CFG_RESET_COUNTERS_INITIAL_VALUES 0x00000064 /* RESET_COUNTERS_INITIAL_VALUES Register */
-#define PCIE_CFG_MISCELLANEOUS_HOST_CONTROL 0x00000068 /* MISCELLANEOUS_HOST_CONTROL Register */
-#define PCIE_CFG_SPARE                 0x0000006c /* SPARE Register */
-#define PCIE_CFG_PCI_STATE             0x00000070 /* PCI_STATE Register */
-#define PCIE_CFG_CLOCK_CONTROL         0x00000074 /* CLOCK_CONTROL Register */
-#define PCIE_CFG_REGISTER_BASE         0x00000078 /* REGISTER_BASE Register */
-#define PCIE_CFG_MEMORY_BASE           0x0000007c /* MEMORY_BASE Register */
-#define PCIE_CFG_REGISTER_DATA         0x00000080 /* REGISTER_DATA Register */
-#define PCIE_CFG_MEMORY_DATA           0x00000084 /* MEMORY_DATA Register */
-#define PCIE_CFG_EXPANSION_ROM_BAR_SIZE 0x00000088 /* EXPANSION_ROM_BAR_SIZE Register */
-#define PCIE_CFG_EXPANSION_ROM_ADDRESS 0x0000008c /* EXPANSION_ROM_ADDRESS Register */
-#define PCIE_CFG_EXPANSION_ROM_DATA    0x00000090 /* EXPANSION_ROM_DATA Register */
-#define PCIE_CFG_VPD_INTERFACE         0x00000094 /* VPD_INTERFACE Register */
-#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER 0x00000098 /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER Register */
-#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER 0x0000009c /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER Register */
-#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER 0x000000a0 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER Register */
-#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER 0x000000a4 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER Register */
-#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER 0x000000a8 /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER Register */
-#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER 0x000000ac /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER Register */
-#define PCIE_CFG_INT_MAILBOX_UPPER     0x000000b0 /* INT_MAILBOX_UPPER Register */
-#define PCIE_CFG_INT_MAILBOX_LOWER     0x000000b4 /* INT_MAILBOX_LOWER Register */
-#define PCIE_CFG_PRODUCT_ID_AND_ASIC_REVISION 0x000000bc /* PRODUCT_ID_AND_ASIC_REVISION Register */
-#define PCIE_CFG_FUNCTION_EVENT        0x000000c0 /* FUNCTION_EVENT Register */
-#define PCIE_CFG_FUNCTION_EVENT_MASK   0x000000c4 /* FUNCTION_EVENT_MASK Register */
-#define PCIE_CFG_FUNCTION_PRESENT      0x000000c8 /* FUNCTION_PRESENT Register */
-#define PCIE_CFG_PCIE_CAPABILITIES     0x000000cc /* PCIE_CAPABILITIES Register */
-#define PCIE_CFG_DEVICE_CAPABILITIES   0x000000d0 /* DEVICE_CAPABILITIES Register */
-#define PCIE_CFG_DEVICE_STATUS_CONTROL 0x000000d4 /* DEVICE_STATUS_CONTROL Register */
-#define PCIE_CFG_LINK_CAPABILITY       0x000000d8 /* LINK_CAPABILITY Register */
-#define PCIE_CFG_LINK_STATUS_CONTROL   0x000000dc /* LINK_STATUS_CONTROL Register */
-#define PCIE_CFG_DEVICE_CAPABILITIES_2 0x000000f0 /* DEVICE_CAPABILITIES_2 Register */
-#define PCIE_CFG_DEVICE_STATUS_CONTROL_2 0x000000f4 /* DEVICE_STATUS_CONTROL_2 Register */
-#define PCIE_CFG_LINK_CAPABILITIES_2   0x000000f8 /* LINK_CAPABILITIES_2 Register */
-#define PCIE_CFG_LINK_STATUS_CONTROL_2 0x000000fc /* LINK_STATUS_CONTROL_2 Register */
-#define PCIE_CFG_ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER 0x00000100 /* ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER Register */
-#define PCIE_CFG_UNCORRECTABLE_ERROR_STATUS 0x00000104 /* UNCORRECTABLE_ERROR_STATUS Register */
-#define PCIE_CFG_UNCORRECTABLE_ERROR_MASK 0x00000108 /* UNCORRECTABLE_ERROR_MASK Register */
-#define PCIE_CFG_UNCORRECTABLE_ERROR_SEVERITY 0x0000010c /* UNCORRECTABLE_ERROR_SEVERITY Register */
-#define PCIE_CFG_CORRECTABLE_ERROR_STATUS 0x00000110 /* CORRECTABLE_ERROR_STATUS Register */
-#define PCIE_CFG_CORRECTABLE_ERROR_MASK 0x00000114 /* CORRECTABLE_ERROR_MASK Register */
-#define PCIE_CFG_ADVANCED_ERROR_CAPABILITIES_AND_CONTROL 0x00000118 /* ADVANCED_ERROR_CAPABILITIES_AND_CONTROL Register */
-#define PCIE_CFG_HEADER_LOG_1          0x0000011c /* HEADER_LOG_1 Register */
-#define PCIE_CFG_HEADER_LOG_2          0x00000120 /* HEADER_LOG_2 Register */
-#define PCIE_CFG_HEADER_LOG_3          0x00000124 /* HEADER_LOG_3 Register */
-#define PCIE_CFG_HEADER_LOG_4          0x00000128 /* HEADER_LOG_4 Register */
-#define PCIE_CFG_VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER 0x0000013c /* VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER Register */
-#define PCIE_CFG_PORT_VC_CAPABILITY    0x00000140 /* PORT_VC_CAPABILITY Register */
-#define PCIE_CFG_PORT_VC_CAPABILITY_2  0x00000144 /* PORT_VC_CAPABILITY_2 Register */
-#define PCIE_CFG_PORT_VC_STATUS_CONTROL 0x00000148 /* PORT_VC_STATUS_CONTROL Register */
-#define PCIE_CFG_VC_RESOURCE_CAPABILITY 0x0000014c /* VC_RESOURCE_CAPABILITY Register */
-#define PCIE_CFG_VC_RESOURCE_CONTROL   0x00000150 /* VC_RESOURCE_CONTROL Register */
-#define PCIE_CFG_VC_RESOURCE_STATUS    0x00000154 /* VC_RESOURCE_STATUS Register */
-#define PCIE_CFG_DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER 0x00000160 /* DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER Register */
-#define PCIE_CFG_DEVICE_SERIAL_NO_LOWER_DW 0x00000164 /* DEVICE_SERIAL_NO_LOWER_DW Register */
-#define PCIE_CFG_DEVICE_SERIAL_NO_UPPER_DW 0x00000168 /* DEVICE_SERIAL_NO_UPPER_DW Register */
-#define PCIE_CFG_POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER 0x0000016c /* POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER Register */
-#define PCIE_CFG_POWER_BUDGETING_DATA_SELECT 0x00000170 /* POWER_BUDGETING_DATA_SELECT Register */
-#define PCIE_CFG_POWER_BUDGETING_DATA  0x00000174 /* POWER_BUDGETING_DATA Register */
-#define PCIE_CFG_POWER_BUDGETING_CAPABILITY 0x00000178 /* POWER_BUDGETING_CAPABILITY Register */
-#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_2_1 0x0000017c /* FIRMWARE_POWER_BUDGETING_2_1 Register */
-#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_4_3 0x00000180 /* FIRMWARE_POWER_BUDGETING_4_3 Register */
-#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_6_5 0x00000184 /* FIRMWARE_POWER_BUDGETING_6_5 Register */
-#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_8_7 0x00000188 /* FIRMWARE_POWER_BUDGETING_8_7 Register */
-#define PCIE_CFG_PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING 0x0000018c /* PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING Register */
-
-
-/****************************************************************************
- * BCM70012_TGT_TOP_PCIE_TL
- ***************************************************************************/
-#define PCIE_TL_TL_CONTROL             0x00000400 /* TL_CONTROL Register */
-#define PCIE_TL_TRANSACTION_CONFIGURATION 0x00000404 /* TRANSACTION_CONFIGURATION Register */
-
-
-/****************************************************************************
- * BCM70012_TGT_TOP_PCIE_DLL
- ***************************************************************************/
-#define PCIE_DLL_DATA_LINK_CONTROL     0x00000500 /* DATA_LINK_CONTROL Register */
-#define PCIE_DLL_DATA_LINK_STATUS      0x00000504 /* DATA_LINK_STATUS Register */
-
-
-/****************************************************************************
- * BCM70012_TGT_TOP_INTR
- ***************************************************************************/
-#define INTR_INTR_STATUS               0x00000700 /* Interrupt Status Register */
-#define INTR_INTR_SET                  0x00000704 /* Interrupt Set Register */
-#define INTR_INTR_CLR_REG              0x00000708 /* Interrupt Clear Register */
-#define INTR_INTR_MSK_STS_REG          0x0000070c /* Interrupt Mask Status Register */
-#define INTR_INTR_MSK_SET_REG          0x00000710 /* Interrupt Mask Set Register */
-#define INTR_INTR_MSK_CLR_REG          0x00000714 /* Interrupt Mask Clear Register */
-#define INTR_EOI_CTRL                  0x00000720 /* End of interrupt control register */
-
-
-/****************************************************************************
- * BCM70012_MISC_TOP_MISC1
- ***************************************************************************/
-#define MISC1_TX_FIRST_DESC_L_ADDR_LIST0 0x00000c00 /* Tx DMA Descriptor List0 First Descriptor lower Address */
-#define MISC1_TX_FIRST_DESC_U_ADDR_LIST0 0x00000c04 /* Tx DMA Descriptor List0 First Descriptor Upper Address */
-#define MISC1_TX_FIRST_DESC_L_ADDR_LIST1 0x00000c08 /* Tx DMA Descriptor List1 First Descriptor Lower Address */
-#define MISC1_TX_FIRST_DESC_U_ADDR_LIST1 0x00000c0c /* Tx DMA Descriptor List1 First Descriptor Upper Address */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS 0x00000c10 /* Tx DMA Software Descriptor List Control and Status */
-#define MISC1_TX_DMA_ERROR_STATUS      0x00000c18 /* Tx DMA Engine Error Status */
-#define MISC1_TX_DMA_LIST0_CUR_DESC_L_ADDR 0x00000c1c /* Tx DMA List0 Current Descriptor Lower Address */
-#define MISC1_TX_DMA_LIST0_CUR_DESC_U_ADDR 0x00000c20 /* Tx DMA List0 Current Descriptor Upper Address */
-#define MISC1_TX_DMA_LIST0_CUR_BYTE_CNT_REM 0x00000c24 /* Tx DMA List0 Current Descriptor Upper Address */
-#define MISC1_TX_DMA_LIST1_CUR_DESC_L_ADDR 0x00000c28 /* Tx DMA List1 Current Descriptor Lower Address */
-#define MISC1_TX_DMA_LIST1_CUR_DESC_U_ADDR 0x00000c2c /* Tx DMA List1 Current Descriptor Upper Address */
-#define MISC1_TX_DMA_LIST1_CUR_BYTE_CNT_REM 0x00000c30 /* Tx DMA List1 Current Descriptor Upper Address */
-#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c34 /* Y Rx Descriptor List0 First Descriptor Lower Address */
-#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c38 /* Y Rx Descriptor List0 First Descriptor Upper Address */
-#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c3c /* Y Rx Descriptor List1 First Descriptor Lower Address */
-#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c40 /* Y Rx Descriptor List1 First Descriptor Upper Address */
-#define MISC1_Y_RX_SW_DESC_LIST_CTRL_STS 0x00000c44 /* Y Rx Software Descriptor List Control and Status */
-#define MISC1_Y_RX_ERROR_STATUS        0x00000c4c /* Y Rx Engine Error Status */
-#define MISC1_Y_RX_LIST0_CUR_DESC_L_ADDR 0x00000c50 /* Y Rx List0 Current Descriptor Lower Address */
-#define MISC1_Y_RX_LIST0_CUR_DESC_U_ADDR 0x00000c54 /* Y Rx List0 Current Descriptor Upper Address */
-#define MISC1_Y_RX_LIST0_CUR_BYTE_CNT  0x00000c58 /* Y Rx List0 Current Descriptor Byte Count */
-#define MISC1_Y_RX_LIST1_CUR_DESC_L_ADDR 0x00000c5c /* Y Rx List1 Current Descriptor Lower address */
-#define MISC1_Y_RX_LIST1_CUR_DESC_U_ADDR 0x00000c60 /* Y Rx List1 Current Descriptor Upper address */
-#define MISC1_Y_RX_LIST1_CUR_BYTE_CNT  0x00000c64 /* Y Rx List1 Current Descriptor Byte Count */
-#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c68 /* UV Rx Descriptor List0 First Descriptor lower Address */
-#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c6c /* UV Rx Descriptor List0 First Descriptor Upper Address */
-#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c70 /* UV Rx Descriptor List1 First Descriptor Lower Address */
-#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c74 /* UV Rx Descriptor List1 First Descriptor Upper Address */
-#define MISC1_UV_RX_SW_DESC_LIST_CTRL_STS 0x00000c78 /* UV Rx Software Descriptor List Control and Status */
-#define MISC1_UV_RX_ERROR_STATUS       0x00000c7c /* UV Rx Engine Error Status */
-#define MISC1_UV_RX_LIST0_CUR_DESC_L_ADDR 0x00000c80 /* UV Rx List0 Current Descriptor Lower Address */
-#define MISC1_UV_RX_LIST0_CUR_DESC_U_ADDR 0x00000c84 /* UV Rx List0 Current Descriptor Upper Address */
-#define MISC1_UV_RX_LIST0_CUR_BYTE_CNT 0x00000c88 /* UV Rx List0 Current Descriptor Byte Count */
-#define MISC1_UV_RX_LIST1_CUR_DESC_L_ADDR 0x00000c8c /* UV Rx List1 Current Descriptor Lower Address */
-#define MISC1_UV_RX_LIST1_CUR_DESC_U_ADDR 0x00000c90 /* UV Rx List1 Current Descriptor Upper Address */
-#define MISC1_UV_RX_LIST1_CUR_BYTE_CNT 0x00000c94 /* UV Rx List1 Current Descriptor Byte Count */
-#define MISC1_DMA_DEBUG_OPTIONS_REG    0x00000c98 /* DMA Debug Options Register */
-#define MISC1_READ_CHANNEL_ERROR_STATUS 0x00000c9c /* Read Channel Error Status */
-#define MISC1_PCIE_DMA_CTRL            0x00000ca0 /* PCIE DMA Control Register */
-
-
-/****************************************************************************
- * BCM70012_MISC_TOP_MISC2
- ***************************************************************************/
-#define MISC2_GLOBAL_CTRL              0x00000d00 /* Global Control Register */
-#define MISC2_INTERNAL_STATUS          0x00000d04 /* Internal Status Register */
-#define MISC2_INTERNAL_STATUS_MUX_CTRL 0x00000d08 /* Internal Debug Mux Control */
-#define MISC2_DEBUG_FIFO_LENGTH        0x00000d0c /* Debug FIFO Length */
-
-
-/****************************************************************************
- * BCM70012_MISC_TOP_MISC3
- ***************************************************************************/
-#define MISC3_RESET_CTRL               0x00000e00 /* Reset Control Register */
-#define MISC3_BIST_CTRL                0x00000e04 /* BIST Control Register */
-#define MISC3_BIST_STATUS              0x00000e08 /* BIST Status Register */
-#define MISC3_RX_CHECKSUM              0x00000e0c /* Receive Checksum */
-#define MISC3_TX_CHECKSUM              0x00000e10 /* Transmit Checksum */
-#define MISC3_ECO_CTRL_CORE            0x00000e14 /* ECO Core Reset Control Register */
-#define MISC3_CSI_TEST_CTRL            0x00000e18 /* CSI Test Control Register */
-#define MISC3_HD_DVI_TEST_CTRL         0x00000e1c /* HD DVI Test Control Register */
-
-
-/****************************************************************************
- * BCM70012_MISC_TOP_MISC_PERST
- ***************************************************************************/
-#define MISC_PERST_ECO_CTRL_PERST      0x00000e80 /* ECO PCIE Reset Control Register */
-#define MISC_PERST_DECODER_CTRL        0x00000e84 /* Decoder Control Register */
-#define MISC_PERST_CCE_STATUS          0x00000e88 /* Config Copy Engine Status */
-#define MISC_PERST_PCIE_DEBUG          0x00000e8c /* PCIE Debug Control Register */
-#define MISC_PERST_PCIE_DEBUG_STATUS   0x00000e90 /* PCIE Debug Status Register */
-#define MISC_PERST_VREG_CTRL           0x00000e94 /* Voltage Regulator Control Register */
-#define MISC_PERST_MEM_CTRL            0x00000e98 /* Memory Control Register */
-#define MISC_PERST_CLOCK_CTRL          0x00000e9c /* Clock Control Register */
-
-
-/****************************************************************************
- * BCM70012_MISC_TOP_GISB_ARBITER
- ***************************************************************************/
-#define GISB_ARBITER_REVISION          0x00000f00 /* GISB ARBITER REVISION */
-#define GISB_ARBITER_SCRATCH           0x00000f04 /* GISB ARBITER Scratch Register */
-#define GISB_ARBITER_REQ_MASK          0x00000f08 /* GISB ARBITER Master Request Mask Register */
-#define GISB_ARBITER_TIMER             0x00000f0c /* GISB ARBITER Timer Value Register */
-
-
-/****************************************************************************
- * BCM70012_OTP_TOP_OTP
- ***************************************************************************/
-#define OTP_CONFIG_INFO                0x00001400 /* OTP Configuration Register */
-#define OTP_CMD                        0x00001404 /* OTP Command Register */
-#define OTP_STATUS                     0x00001408 /* OTP Status Register */
-#define OTP_CONTENT_MISC               0x0000140c /* Content : Miscellaneous Register */
-#define OTP_CONTENT_AES_0              0x00001410 /* Content : AES Key 0 Register */
-#define OTP_CONTENT_AES_1              0x00001414 /* Content : AES Key 1 Register */
-#define OTP_CONTENT_AES_2              0x00001418 /* Content : AES Key 2 Register */
-#define OTP_CONTENT_AES_3              0x0000141c /* Content : AES Key 3 Register */
-#define OTP_CONTENT_SHA_0              0x00001420 /* Content : SHA Key 0 Register */
-#define OTP_CONTENT_SHA_1              0x00001424 /* Content : SHA Key 1 Register */
-#define OTP_CONTENT_SHA_2              0x00001428 /* Content : SHA Key 2 Register */
-#define OTP_CONTENT_SHA_3              0x0000142c /* Content : SHA Key 3 Register */
-#define OTP_CONTENT_SHA_4              0x00001430 /* Content : SHA Key 4 Register */
-#define OTP_CONTENT_SHA_5              0x00001434 /* Content : SHA Key 5 Register */
-#define OTP_CONTENT_SHA_6              0x00001438 /* Content : SHA Key 6 Register */
-#define OTP_CONTENT_SHA_7              0x0000143c /* Content : SHA Key 7 Register */
-#define OTP_CONTENT_CHECKSUM           0x00001440 /* Content : Checksum  Register */
-#define OTP_PROG_CTRL                  0x00001444 /* Programming Control Register */
-#define OTP_PROG_STATUS                0x00001448 /* Programming Status Register */
-#define OTP_PROG_PULSE                 0x0000144c /* Program Pulse Width Register */
-#define OTP_VERIFY_PULSE               0x00001450 /* Verify Pulse Width Register */
-#define OTP_PROG_MASK                  0x00001454 /* Program Mask Register */
-#define OTP_DATA_INPUT                 0x00001458 /* Data Input Register */
-#define OTP_DATA_OUTPUT                0x0000145c /* Data Output Register */
-
-
-/****************************************************************************
- * BCM70012_AES_TOP_AES
- ***************************************************************************/
-#define AES_CONFIG_INFO                0x00001800 /* AES Configuration Information Register */
-#define AES_CMD                        0x00001804 /* AES Command Register */
-#define AES_STATUS                     0x00001808 /* AES Status Register */
-#define AES_EEPROM_CONFIG              0x0000180c /* AES EEPROM Configuration Register */
-#define AES_EEPROM_DATA_0              0x00001810 /* AES EEPROM Data Register 0 */
-#define AES_EEPROM_DATA_1              0x00001814 /* AES EEPROM Data Register 1 */
-#define AES_EEPROM_DATA_2              0x00001818 /* AES EEPROM Data Register 2 */
-#define AES_EEPROM_DATA_3              0x0000181c /* AES EEPROM Data Register 3 */
-
-
-/****************************************************************************
- * BCM70012_DCI_TOP_DCI
- ***************************************************************************/
-#define DCI_CMD                        0x00001c00 /* DCI Command Register */
-#define DCI_STATUS                     0x00001c04 /* DCI Status Register */
-#define DCI_DRAM_BASE_ADDR             0x00001c08 /* DRAM Base Address Register */
-#define DCI_FIRMWARE_ADDR              0x00001c0c /* Firmware Address Register */
-#define DCI_FIRMWARE_DATA              0x00001c10 /* Firmware Data Register */
-#define DCI_SIGNATURE_DATA_0           0x00001c14 /* Signature Data Register 0 */
-#define DCI_SIGNATURE_DATA_1           0x00001c18 /* Signature Data Register 1 */
-#define DCI_SIGNATURE_DATA_2           0x00001c1c /* Signature Data Register 2 */
-#define DCI_SIGNATURE_DATA_3           0x00001c20 /* Signature Data Register 3 */
-#define DCI_SIGNATURE_DATA_4           0x00001c24 /* Signature Data Register 4 */
-#define DCI_SIGNATURE_DATA_5           0x00001c28 /* Signature Data Register 5 */
-#define DCI_SIGNATURE_DATA_6           0x00001c2c /* Signature Data Register 6 */
-#define DCI_SIGNATURE_DATA_7           0x00001c30 /* Signature Data Register 7 */
-
-
-/****************************************************************************
- * BCM70012_TGT_TOP_INTR
- ***************************************************************************/
-/****************************************************************************
- * INTR :: INTR_STATUS
- ***************************************************************************/
-/* INTR :: INTR_STATUS :: reserved0 [31:26] */
-#define INTR_INTR_STATUS_reserved0_MASK                            0xfc000000
-#define INTR_INTR_STATUS_reserved0_ALIGN                           0
-#define INTR_INTR_STATUS_reserved0_BITS                            6
-#define INTR_INTR_STATUS_reserved0_SHIFT                           26
-
-/* INTR :: INTR_STATUS :: PCIE_TGT_CA_ATTN [25:25] */
-#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_MASK                     0x02000000
-#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_ALIGN                    0
-#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_BITS                     1
-#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_SHIFT                    25
-
-/* INTR :: INTR_STATUS :: PCIE_TGT_UR_ATTN [24:24] */
-#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_MASK                     0x01000000
-#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_ALIGN                    0
-#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_BITS                     1
-#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_SHIFT                    24
-
-/* INTR :: INTR_STATUS :: reserved1 [23:14] */
-#define INTR_INTR_STATUS_reserved1_MASK                            0x00ffc000
-#define INTR_INTR_STATUS_reserved1_ALIGN                           0
-#define INTR_INTR_STATUS_reserved1_BITS                            10
-#define INTR_INTR_STATUS_reserved1_SHIFT                           14
-
-/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_ERR_INTR [13:13] */
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK                0x00002000
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_ALIGN               0
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_BITS                1
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_SHIFT               13
-
-/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_DONE_INTR [12:12] */
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK               0x00001000
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_ALIGN              0
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_BITS               1
-#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_SHIFT              12
-
-/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_ERR_INTR [11:11] */
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK                 0x00000800
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_ALIGN                0
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_BITS                 1
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_SHIFT                11
-
-/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_DONE_INTR [10:10] */
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK                0x00000400
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_ALIGN               0
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_BITS                1
-#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_SHIFT               10
-
-/* INTR :: INTR_STATUS :: L1_TX_DMA_ERR_INTR [09:09] */
-#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK                   0x00000200
-#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_ALIGN                  0
-#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_BITS                   1
-#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_SHIFT                  9
-
-/* INTR :: INTR_STATUS :: L1_TX_DMA_DONE_INTR [08:08] */
-#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK                  0x00000100
-#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_ALIGN                 0
-#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_BITS                  1
-#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_SHIFT                 8
-
-/* INTR :: INTR_STATUS :: reserved2 [07:06] */
-#define INTR_INTR_STATUS_reserved2_MASK                            0x000000c0
-#define INTR_INTR_STATUS_reserved2_ALIGN                           0
-#define INTR_INTR_STATUS_reserved2_BITS                            2
-#define INTR_INTR_STATUS_reserved2_SHIFT                           6
-
-/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_ERR_INTR [05:05] */
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK                0x00000020
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_ALIGN               0
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_BITS                1
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_SHIFT               5
-
-/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_DONE_INTR [04:04] */
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK               0x00000010
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_ALIGN              0
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_BITS               1
-#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_SHIFT              4
-
-/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_ERR_INTR [03:03] */
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK                 0x00000008
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_ALIGN                0
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_BITS                 1
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_SHIFT                3
-
-/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_DONE_INTR [02:02] */
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK                0x00000004
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_ALIGN               0
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_BITS                1
-#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_SHIFT               2
-
-/* INTR :: INTR_STATUS :: L0_TX_DMA_ERR_INTR [01:01] */
-#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK                   0x00000002
-#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_ALIGN                  0
-#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_BITS                   1
-#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_SHIFT                  1
-
-/* INTR :: INTR_STATUS :: L0_TX_DMA_DONE_INTR [00:00] */
-#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK                  0x00000001
-#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_ALIGN                 0
-#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_BITS                  1
-#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_SHIFT                 0
-
-
-/****************************************************************************
- * MISC1 :: TX_SW_DESC_LIST_CTRL_STS
- ***************************************************************************/
-/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: reserved0 [31:04] */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_MASK              0xfffffff0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_ALIGN             0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_BITS              28
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_SHIFT             4
-
-/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DMA_DATA_SERV_PTR [03:03] */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_MASK      0x00000008
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_ALIGN     0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_BITS      1
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_SHIFT     3
-
-/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DESC_SERV_PTR [02:02] */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_MASK          0x00000004
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_ALIGN         0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_BITS          1
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_SHIFT         2
-
-/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_HALT_ON_ERROR [01:01] */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_MASK   0x00000002
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_ALIGN  0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_BITS   1
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_SHIFT  1
-
-/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_RUN_STOP [00:00] */
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK        0x00000001
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_ALIGN       0
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_BITS        1
-#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_SHIFT       0
-
-
-/****************************************************************************
- * MISC1 :: TX_DMA_ERROR_STATUS
- ***************************************************************************/
-/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved0 [31:10] */
-#define MISC1_TX_DMA_ERROR_STATUS_reserved0_MASK                   0xfffffc00
-#define MISC1_TX_DMA_ERROR_STATUS_reserved0_ALIGN                  0
-#define MISC1_TX_DMA_ERROR_STATUS_reserved0_BITS                   22
-#define MISC1_TX_DMA_ERROR_STATUS_reserved0_SHIFT                  10
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DESC_TX_ABORT_ERRORS [09:09] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK  0x00000200
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_BITS  1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved1 [08:08] */
-#define MISC1_TX_DMA_ERROR_STATUS_reserved1_MASK                   0x00000100
-#define MISC1_TX_DMA_ERROR_STATUS_reserved1_ALIGN                  0
-#define MISC1_TX_DMA_ERROR_STATUS_reserved1_BITS                   1
-#define MISC1_TX_DMA_ERROR_STATUS_reserved1_SHIFT                  8
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DESC_TX_ABORT_ERRORS [07:07] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK  0x00000080
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_BITS  1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved2 [06:06] */
-#define MISC1_TX_DMA_ERROR_STATUS_reserved2_MASK                   0x00000040
-#define MISC1_TX_DMA_ERROR_STATUS_reserved2_ALIGN                  0
-#define MISC1_TX_DMA_ERROR_STATUS_reserved2_BITS                   1
-#define MISC1_TX_DMA_ERROR_STATUS_reserved2_SHIFT                  6
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DMA_DATA_TX_ABORT_ERRORS [05:05] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000020
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_BITS 1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_SHIFT 5
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_FIFO_FULL_ERRORS [04:04] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK      0x00000010
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_ALIGN     0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_BITS      1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_SHIFT     4
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved3 [03:03] */
-#define MISC1_TX_DMA_ERROR_STATUS_reserved3_MASK                   0x00000008
-#define MISC1_TX_DMA_ERROR_STATUS_reserved3_ALIGN                  0
-#define MISC1_TX_DMA_ERROR_STATUS_reserved3_BITS                   1
-#define MISC1_TX_DMA_ERROR_STATUS_reserved3_SHIFT                  3
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DMA_DATA_TX_ABORT_ERRORS [02:02] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000004
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_BITS 1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_SHIFT 2
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_FIFO_FULL_ERRORS [01:01] */
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK      0x00000002
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_ALIGN     0
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_BITS      1
-#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_SHIFT     1
-
-/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved4 [00:00] */
-#define MISC1_TX_DMA_ERROR_STATUS_reserved4_MASK                   0x00000001
-#define MISC1_TX_DMA_ERROR_STATUS_reserved4_ALIGN                  0
-#define MISC1_TX_DMA_ERROR_STATUS_reserved4_BITS                   1
-#define MISC1_TX_DMA_ERROR_STATUS_reserved4_SHIFT                  0
-
-
-/****************************************************************************
- * MISC1 :: Y_RX_ERROR_STATUS
- ***************************************************************************/
-/* MISC1 :: Y_RX_ERROR_STATUS :: reserved0 [31:14] */
-#define MISC1_Y_RX_ERROR_STATUS_reserved0_MASK                     0xffffc000
-#define MISC1_Y_RX_ERROR_STATUS_reserved0_ALIGN                    0
-#define MISC1_Y_RX_ERROR_STATUS_reserved0_BITS                     18
-#define MISC1_Y_RX_ERROR_STATUS_reserved0_SHIFT                    14
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK          0x00002000
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN         0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS          1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT         13
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK           0x00001000
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN          0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS           1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT          12
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK          0x00000800
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN         0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS          1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT         11
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK           0x00000400
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN          0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS           1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT          10
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK    0x00000200
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN   0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS    1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT   9
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: reserved1 [08:08] */
-#define MISC1_Y_RX_ERROR_STATUS_reserved1_MASK                     0x00000100
-#define MISC1_Y_RX_ERROR_STATUS_reserved1_ALIGN                    0
-#define MISC1_Y_RX_ERROR_STATUS_reserved1_BITS                     1
-#define MISC1_Y_RX_ERROR_STATUS_reserved1_SHIFT                    8
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK    0x00000080
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN   0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS    1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT   7
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: reserved2 [06:05] */
-#define MISC1_Y_RX_ERROR_STATUS_reserved2_MASK                     0x00000060
-#define MISC1_Y_RX_ERROR_STATUS_reserved2_ALIGN                    0
-#define MISC1_Y_RX_ERROR_STATUS_reserved2_BITS                     2
-#define MISC1_Y_RX_ERROR_STATUS_reserved2_SHIFT                    5
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK        0x00000010
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN       0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS        1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT       4
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: reserved3 [03:02] */
-#define MISC1_Y_RX_ERROR_STATUS_reserved3_MASK                     0x0000000c
-#define MISC1_Y_RX_ERROR_STATUS_reserved3_ALIGN                    0
-#define MISC1_Y_RX_ERROR_STATUS_reserved3_BITS                     2
-#define MISC1_Y_RX_ERROR_STATUS_reserved3_SHIFT                    2
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK        0x00000002
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN       0
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS        1
-#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT       1
-
-/* MISC1 :: Y_RX_ERROR_STATUS :: reserved4 [00:00] */
-#define MISC1_Y_RX_ERROR_STATUS_reserved4_MASK                     0x00000001
-#define MISC1_Y_RX_ERROR_STATUS_reserved4_ALIGN                    0
-#define MISC1_Y_RX_ERROR_STATUS_reserved4_BITS                     1
-#define MISC1_Y_RX_ERROR_STATUS_reserved4_SHIFT                    0
-
-
-/****************************************************************************
- * MISC1 :: UV_RX_ERROR_STATUS
- ***************************************************************************/
-/* MISC1 :: UV_RX_ERROR_STATUS :: reserved0 [31:14] */
-#define MISC1_UV_RX_ERROR_STATUS_reserved0_MASK                    0xffffc000
-#define MISC1_UV_RX_ERROR_STATUS_reserved0_ALIGN                   0
-#define MISC1_UV_RX_ERROR_STATUS_reserved0_BITS                    18
-#define MISC1_UV_RX_ERROR_STATUS_reserved0_SHIFT                   14
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK         0x00002000
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN        0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS         1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT        13
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK          0x00001000
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN         0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS          1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT         12
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK         0x00000800
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN        0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS         1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT        11
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK          0x00000400
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN         0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS          1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT         10
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK   0x00000200
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN  0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS   1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT  9
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: reserved1 [08:08] */
-#define MISC1_UV_RX_ERROR_STATUS_reserved1_MASK                    0x00000100
-#define MISC1_UV_RX_ERROR_STATUS_reserved1_ALIGN                   0
-#define MISC1_UV_RX_ERROR_STATUS_reserved1_BITS                    1
-#define MISC1_UV_RX_ERROR_STATUS_reserved1_SHIFT                   8
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK   0x00000080
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN  0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS   1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT  7
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: reserved2 [06:05] */
-#define MISC1_UV_RX_ERROR_STATUS_reserved2_MASK                    0x00000060
-#define MISC1_UV_RX_ERROR_STATUS_reserved2_ALIGN                   0
-#define MISC1_UV_RX_ERROR_STATUS_reserved2_BITS                    2
-#define MISC1_UV_RX_ERROR_STATUS_reserved2_SHIFT                   5
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK       0x00000010
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN      0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS       1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT      4
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: reserved3 [03:02] */
-#define MISC1_UV_RX_ERROR_STATUS_reserved3_MASK                    0x0000000c
-#define MISC1_UV_RX_ERROR_STATUS_reserved3_ALIGN                   0
-#define MISC1_UV_RX_ERROR_STATUS_reserved3_BITS                    2
-#define MISC1_UV_RX_ERROR_STATUS_reserved3_SHIFT                   2
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK       0x00000002
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN      0
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS       1
-#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT      1
-
-/* MISC1 :: UV_RX_ERROR_STATUS :: reserved4 [00:00] */
-#define MISC1_UV_RX_ERROR_STATUS_reserved4_MASK                    0x00000001
-#define MISC1_UV_RX_ERROR_STATUS_reserved4_ALIGN                   0
-#define MISC1_UV_RX_ERROR_STATUS_reserved4_BITS                    1
-#define MISC1_UV_RX_ERROR_STATUS_reserved4_SHIFT                   0
-
-/****************************************************************************
- * Datatype Definitions.
- ***************************************************************************/
-#endif /* #ifndef MACFILE_H__ */
-
-/* End of File */
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_cmds.c linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_cmds.c
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_cmds.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_cmds.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1066 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_cmds . c
- *
- *  Description:
- *		BCM70010 Linux driver user command interfaces.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#include "crystalhd.h"
-
-static struct crystalhd_user *bc_cproc_get_uid(struct crystalhd_cmd *ctx)
-{
-	struct crystalhd_user *user = NULL;
-	int i;
-
-	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
-		if (!ctx->user[i].in_use) {
-			user = &ctx->user[i];
-			break;
-		}
-	}
-
-	return user;
-}
-
-static int bc_cproc_get_user_count(struct crystalhd_cmd *ctx)
-{
-	int i, count = 0;
-
-	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
-		if (ctx->user[i].in_use)
-			count++;
-	}
-
-	return count;
-}
-
-static void bc_cproc_mark_pwr_state(struct crystalhd_cmd *ctx)
-{
-	int i;
-
-	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
-		if (!ctx->user[i].in_use)
-			continue;
-		if (ctx->user[i].mode == DTS_DIAG_MODE ||
-		    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
-			ctx->pwr_state_change = 1;
-			break;
-		}
-	}
-}
-
-static enum BC_STATUS bc_cproc_notify_mode(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	int rc = 0, i = 0;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (ctx->user[idata->u_id].mode != DTS_MODE_INV) {
-		BCMLOG_ERR("Close the handle first..\n");
-		return BC_STS_ERR_USAGE;
-	}
-	if (idata->udata.u.NotifyMode.Mode == DTS_MONITOR_MODE) {
-		ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
-		return BC_STS_SUCCESS;
-	}
-	if (ctx->state != BC_LINK_INVALID) {
-		BCMLOG_ERR("Link invalid state %d\n", ctx->state);
-		return BC_STS_ERR_USAGE;
-	}
-	/* Check for duplicate playback sessions..*/
-	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
-		if (ctx->user[i].mode == DTS_DIAG_MODE ||
-		    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
-			BCMLOG_ERR("multiple playback sessions are not supported..\n");
-			return BC_STS_ERR_USAGE;
-		}
-	}
-	ctx->cin_wait_exit = 0;
-	ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
-	/* Setup mmap pool for uaddr sgl mapping..*/
-	rc = crystalhd_create_dio_pool(ctx->adp, BC_LINK_MAX_SGLS);
-	if (rc)
-		return BC_STS_ERROR;
-
-	/* Setup Hardware DMA rings */
-	return crystalhd_hw_setup_dma_rings(&ctx->hw_ctx);
-}
-
-static enum BC_STATUS bc_cproc_get_version(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-	idata->udata.u.VerInfo.DriverMajor = crystalhd_kmod_major;
-	idata->udata.u.VerInfo.DriverMinor = crystalhd_kmod_minor;
-	idata->udata.u.VerInfo.DriverRevision	= crystalhd_kmod_rev;
-	return BC_STS_SUCCESS;
-}
-
-
-static enum BC_STATUS bc_cproc_get_hwtype(struct crystalhd_cmd *ctx,
-					struct crystalhd_ioctl_data *idata)
-{
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_pci_cfg_rd(ctx->adp, 0, 2,
-			   (uint32_t *)&idata->udata.u.hwType.PciVenId);
-	crystalhd_pci_cfg_rd(ctx->adp, 2, 2,
-			   (uint32_t *)&idata->udata.u.hwType.PciDevId);
-	crystalhd_pci_cfg_rd(ctx->adp, 8, 1,
-			   (uint32_t *)&idata->udata.u.hwType.HwRev);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_reg_rd(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-	idata->udata.u.regAcc.Value = bc_dec_reg_rd(ctx->adp,
-					idata->udata.u.regAcc.Offset);
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_reg_wr(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-
-	bc_dec_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
-		      idata->udata.u.regAcc.Value);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_link_reg_rd(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-
-	idata->udata.u.regAcc.Value = crystalhd_reg_rd(ctx->adp,
-					idata->udata.u.regAcc.Offset);
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_link_reg_wr(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-
-	crystalhd_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
-		       idata->udata.u.regAcc.Value);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_mem_rd(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata || !idata->add_cdata)
-		return BC_STS_INV_ARG;
-
-	if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
-		BCMLOG_ERR("insufficient buffer\n");
-		return BC_STS_INV_ARG;
-	}
-	sts = crystalhd_mem_rd(ctx->adp, idata->udata.u.devMem.StartOff,
-			     idata->udata.u.devMem.NumDwords,
-			     (uint32_t *)idata->add_cdata);
-	return sts;
-
-}
-
-static enum BC_STATUS bc_cproc_mem_wr(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata || !idata->add_cdata)
-		return BC_STS_INV_ARG;
-
-	if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
-		BCMLOG_ERR("insufficient buffer\n");
-		return BC_STS_INV_ARG;
-	}
-
-	sts = crystalhd_mem_wr(ctx->adp, idata->udata.u.devMem.StartOff,
-			     idata->udata.u.devMem.NumDwords,
-			     (uint32_t *)idata->add_cdata);
-	return sts;
-}
-
-static enum BC_STATUS bc_cproc_cfg_rd(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	uint32_t ix, cnt, off, len;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	uint32_t *temp;
-
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-
-	temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
-	off = idata->udata.u.pciCfg.Offset;
-	len = idata->udata.u.pciCfg.Size;
-
-	if (len <= 4)
-		return crystalhd_pci_cfg_rd(ctx->adp, off, len, temp);
-
-	/* Truncate to dword alignment..*/
-	len = 4;
-	cnt = idata->udata.u.pciCfg.Size / len;
-	for (ix = 0; ix < cnt; ix++) {
-		sts = crystalhd_pci_cfg_rd(ctx->adp, off, len, &temp[ix]);
-		if (sts != BC_STS_SUCCESS) {
-			BCMLOG_ERR("config read : %d\n", sts);
-			return sts;
-		}
-		off += len;
-	}
-
-	return sts;
-}
-
-static enum BC_STATUS bc_cproc_cfg_wr(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata)
-{
-	uint32_t ix, cnt, off, len;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	uint32_t *temp;
-
-	if (!ctx || !idata)
-		return BC_STS_INV_ARG;
-
-	temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
-	off = idata->udata.u.pciCfg.Offset;
-	len = idata->udata.u.pciCfg.Size;
-
-	if (len <= 4)
-		return crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[0]);
-
-	/* Truncate to dword alignment..*/
-	len = 4;
-	cnt = idata->udata.u.pciCfg.Size / len;
-	for (ix = 0; ix < cnt; ix++) {
-		sts = crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[ix]);
-		if (sts != BC_STS_SUCCESS) {
-			BCMLOG_ERR("config write : %d\n", sts);
-			return sts;
-		}
-		off += len;
-	}
-
-	return sts;
-}
-
-static enum BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata || !idata->add_cdata || !idata->add_cdata_sz) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (ctx->state != BC_LINK_INVALID) {
-		BCMLOG_ERR("Link invalid state %d\n", ctx->state);
-		return BC_STS_ERR_USAGE;
-	}
-
-	sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
-				  idata->add_cdata_sz);
-
-	if (sts != BC_STS_SUCCESS)
-		BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
-	else
-		ctx->state |= BC_LINK_INIT;
-
-	return sts;
-}
-
-/*
- * We use the FW_CMD interface to sync up playback state with application
- * and  firmware. This function will perform the required pre and post
- * processing of the Firmware commands.
- *
- * Pause -
- *	Disable capture after decoder pause.
- * Resume -
- *	First enable capture and issue decoder resume command.
- * Flush -
- *	Abort pending input transfers and issue decoder flush command.
- *
- */
-static enum BC_STATUS bc_cproc_do_fw_cmd(struct crystalhd_cmd *ctx,
-					struct crystalhd_ioctl_data *idata)
-{
-	enum BC_STATUS sts;
-	uint32_t *cmd;
-
-	if (!(ctx->state & BC_LINK_INIT)) {
-		BCMLOG_ERR("Link invalid state %d\n", ctx->state);
-		return BC_STS_ERR_USAGE;
-	}
-
-	cmd = idata->udata.u.fwCmd.cmd;
-
-	/* Pre-Process */
-	if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
-		if (!cmd[3]) {
-			ctx->state &= ~BC_LINK_PAUSED;
-			crystalhd_hw_unpause(&ctx->hw_ctx);
-		}
-	} else if (cmd[0] == eCMD_C011_DEC_CHAN_FLUSH) {
-		BCMLOG(BCMLOG_INFO, "Flush issued\n");
-		if (cmd[3])
-			ctx->cin_wait_exit = 1;
-	}
-
-	sts = crystalhd_do_fw_cmd(&ctx->hw_ctx, &idata->udata.u.fwCmd);
-
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG(BCMLOG_INFO, "fw cmd %x failed\n", cmd[0]);
-		return sts;
-	}
-
-	/* Post-Process */
-	if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
-		if (cmd[3]) {
-			ctx->state |= BC_LINK_PAUSED;
-			crystalhd_hw_pause(&ctx->hw_ctx);
-		}
-	}
-
-	return sts;
-}
-
-static void bc_proc_in_completion(struct crystalhd_dio_req *dio_hnd,
-				  wait_queue_head_t *event, enum BC_STATUS sts)
-{
-	if (!dio_hnd || !event) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return;
-	}
-	if (sts == BC_STS_IO_USER_ABORT)
-		return;
-
-	dio_hnd->uinfo.comp_sts = sts;
-	dio_hnd->uinfo.ev_sts = 1;
-	crystalhd_set_event(event);
-}
-
-static enum BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx)
-{
-	wait_queue_head_t sleep_ev;
-	int rc = 0;
-
-	if (ctx->state & BC_LINK_SUSPEND)
-		return BC_STS_IO_USER_ABORT;
-
-	if (ctx->cin_wait_exit) {
-		ctx->cin_wait_exit = 0;
-		return BC_STS_CMD_CANCELLED;
-	}
-	crystalhd_create_event(&sleep_ev);
-	crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0);
-	if (rc == -EINTR)
-		return BC_STS_IO_USER_ABORT;
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx,
-				   struct crystalhd_ioctl_data *idata,
-				   struct crystalhd_dio_req *dio)
-{
-	uint32_t tx_listid = 0;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	wait_queue_head_t event;
-	int rc = 0;
-
-	if (!ctx || !idata || !dio) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_create_event(&event);
-
-	ctx->tx_list_id = 0;
-	/* msleep_interruptible(2000); */
-	sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion,
-				 &event, &tx_listid,
-				 idata->udata.u.ProcInput.Encrypted);
-
-	while (sts == BC_STS_BUSY) {
-		sts = bc_cproc_codein_sleep(ctx);
-		if (sts != BC_STS_SUCCESS)
-			break;
-		sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio,
-					 bc_proc_in_completion,
-					 &event, &tx_listid,
-					 idata->udata.u.ProcInput.Encrypted);
-	}
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts);
-		return sts;
-	}
-	if (ctx->cin_wait_exit)
-		ctx->cin_wait_exit = 0;
-
-	ctx->tx_list_id = tx_listid;
-
-	/* _post() succeeded.. wait for the completion. */
-	crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0);
-	ctx->tx_list_id = 0;
-	if (!rc) {
-		return dio->uinfo.comp_sts;
-	} else if (rc == -EBUSY) {
-		BCMLOG(BCMLOG_DBG, "_tx_post() T/O\n");
-		sts = BC_STS_TIMEOUT;
-	} else if (rc == -EINTR) {
-		BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n");
-		sts = BC_STS_IO_USER_ABORT;
-	} else {
-		sts = BC_STS_IO_ERROR;
-	}
-
-	/* We are cancelling the IO from the same context as the _post().
-	 * so no need to wait on the event again.. the return itself
-	 * ensures the release of our resources.
-	 */
-	crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid);
-
-	return sts;
-}
-
-/* Helper function to check on user buffers */
-static enum BC_STATUS bc_cproc_check_inbuffs(bool pin, void *ubuff,
-				 uint32_t ub_sz, uint32_t uv_off, bool en_422)
-{
-	if (!ubuff || !ub_sz) {
-		BCMLOG_ERR("%s->Invalid Arg %p %x\n",
-			((pin) ? "TX" : "RX"), ubuff, ub_sz);
-		return BC_STS_INV_ARG;
-	}
-
-	/* Check for alignment */
-	if (((uintptr_t)ubuff) & 0x03) {
-		BCMLOG_ERR(
-			"%s-->Un-aligned address not implemented yet.. %p\n",
-			 ((pin) ? "TX" : "RX"), ubuff);
-		return BC_STS_NOT_IMPL;
-	}
-	if (pin)
-		return BC_STS_SUCCESS;
-
-	if (!en_422 && !uv_off) {
-		BCMLOG_ERR("Need UV offset for 420 mode.\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (en_422 && uv_off) {
-		BCMLOG_ERR("UV offset in 422 mode ??\n");
-		return BC_STS_INV_ARG;
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_proc_input(struct crystalhd_cmd *ctx,
-					struct crystalhd_ioctl_data *idata)
-{
-	void *ubuff;
-	uint32_t ub_sz;
-	struct crystalhd_dio_req *dio_hnd = NULL;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	ubuff = idata->udata.u.ProcInput.pDmaBuff;
-	ub_sz = idata->udata.u.ProcInput.BuffSz;
-
-	sts = bc_cproc_check_inbuffs(1, ubuff, ub_sz, 0, 0);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, 0, 0, 1, &dio_hnd);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("dio map - %d\n", sts);
-		return sts;
-	}
-
-	if (!dio_hnd)
-		return BC_STS_ERROR;
-
-	sts = bc_cproc_hw_txdma(ctx, idata, dio_hnd);
-
-	crystalhd_unmap_dio(ctx->adp, dio_hnd);
-
-	return sts;
-}
-
-static enum BC_STATUS bc_cproc_add_cap_buff(struct crystalhd_cmd *ctx,
-				       struct crystalhd_ioctl_data *idata)
-{
-	void *ubuff;
-	uint32_t ub_sz, uv_off;
-	bool en_422;
-	struct crystalhd_dio_req *dio_hnd = NULL;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	ubuff = idata->udata.u.RxBuffs.YuvBuff;
-	ub_sz = idata->udata.u.RxBuffs.YuvBuffSz;
-	uv_off = idata->udata.u.RxBuffs.UVbuffOffset;
-	en_422 = idata->udata.u.RxBuffs.b422Mode;
-
-	sts = bc_cproc_check_inbuffs(0, ubuff, ub_sz, uv_off, en_422);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, uv_off,
-			      en_422, 0, &dio_hnd);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("dio map - %d\n", sts);
-		return sts;
-	}
-
-	if (!dio_hnd)
-		return BC_STS_ERROR;
-
-	sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio_hnd,
-					 (ctx->state == BC_LINK_READY));
-	if ((sts != BC_STS_SUCCESS) && (sts != BC_STS_BUSY)) {
-		crystalhd_unmap_dio(ctx->adp, dio_hnd);
-		return sts;
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_fmt_change(struct crystalhd_cmd *ctx,
-				     struct crystalhd_dio_req *dio)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio, 0);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	ctx->state |= BC_LINK_FMT_CHG;
-	if (ctx->state == BC_LINK_READY)
-		sts = crystalhd_hw_start_capture(&ctx->hw_ctx);
-
-	return sts;
-}
-
-static enum BC_STATUS bc_cproc_fetch_frame(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	struct crystalhd_dio_req *dio = NULL;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	struct BC_DEC_OUT_BUFF *frame;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (!(ctx->state & BC_LINK_CAP_EN)) {
-		BCMLOG(BCMLOG_DBG, "Capture not enabled..%x\n", ctx->state);
-		return BC_STS_ERR_USAGE;
-	}
-
-	frame = &idata->udata.u.DecOutData;
-
-	sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
-	if (sts != BC_STS_SUCCESS)
-		return (ctx->state & BC_LINK_SUSPEND) ?
-					 BC_STS_IO_USER_ABORT : sts;
-
-	frame->Flags = dio->uinfo.comp_flags;
-
-	if (frame->Flags & COMP_FLAG_FMT_CHANGE)
-		return bc_cproc_fmt_change(ctx, dio);
-
-	frame->OutPutBuffs.YuvBuff = dio->uinfo.xfr_buff;
-	frame->OutPutBuffs.YuvBuffSz = dio->uinfo.xfr_len;
-	frame->OutPutBuffs.UVbuffOffset = dio->uinfo.uv_offset;
-	frame->OutPutBuffs.b422Mode = dio->uinfo.b422mode;
-
-	frame->OutPutBuffs.YBuffDoneSz = dio->uinfo.y_done_sz;
-	frame->OutPutBuffs.UVBuffDoneSz = dio->uinfo.uv_done_sz;
-
-	crystalhd_unmap_dio(ctx->adp, dio);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_start_capture(struct crystalhd_cmd *ctx,
-					struct crystalhd_ioctl_data *idata)
-{
-	ctx->state |= BC_LINK_CAP_EN;
-	if (ctx->state == BC_LINK_READY)
-		return crystalhd_hw_start_capture(&ctx->hw_ctx);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx,
-					  struct crystalhd_ioctl_data *idata)
-{
-	struct crystalhd_dio_req *dio = NULL;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	struct BC_DEC_OUT_BUFF *frame;
-	uint32_t count;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (!(ctx->state & BC_LINK_CAP_EN))
-		return BC_STS_ERR_USAGE;
-
-	/* We should ack flush even when we are in paused/suspend state */
-	if (!(ctx->state & BC_LINK_READY))
-		return crystalhd_hw_stop_capture(&ctx->hw_ctx);
-
-	ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG);
-
-	frame = &idata->udata.u.DecOutData;
-	for (count = 0; count < BC_RX_LIST_CNT; count++) {
-
-		sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx,
-					 &frame->PibInfo, &dio);
-		if (sts != BC_STS_SUCCESS)
-			break;
-
-		crystalhd_unmap_dio(ctx->adp, dio);
-	}
-
-	return crystalhd_hw_stop_capture(&ctx->hw_ctx);
-}
-
-static enum BC_STATUS bc_cproc_get_stats(struct crystalhd_cmd *ctx,
-				    struct crystalhd_ioctl_data *idata)
-{
-	struct BC_DTS_STATS *stats;
-	struct crystalhd_hw_stats	hw_stats;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_hw_stats(&ctx->hw_ctx, &hw_stats);
-
-	stats = &idata->udata.u.drvStat;
-	stats->drvRLL = hw_stats.rdyq_count;
-	stats->drvFLL = hw_stats.freeq_count;
-	stats->DrvTotalFrmDropped = hw_stats.rx_errors;
-	stats->DrvTotalHWErrs = hw_stats.rx_errors + hw_stats.tx_errors;
-	stats->intCount = hw_stats.num_interrupts;
-	stats->DrvIgnIntrCnt = hw_stats.num_interrupts -
-				hw_stats.dev_interrupts;
-	stats->TxFifoBsyCnt = hw_stats.cin_busy;
-	stats->pauseCount = hw_stats.pause_cnt;
-
-	if (ctx->pwr_state_change)
-		stats->pwr_state_change = 1;
-	if (ctx->state & BC_LINK_PAUSED)
-		stats->DrvPauseTime = 1;
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_reset_stats(struct crystalhd_cmd *ctx,
-				      struct crystalhd_ioctl_data *idata)
-{
-	crystalhd_hw_stats(&ctx->hw_ctx, NULL);
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS bc_cproc_chg_clk(struct crystalhd_cmd *ctx,
-				  struct crystalhd_ioctl_data *idata)
-{
-	struct BC_CLOCK *clock;
-	uint32_t oldClk;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	clock = &idata->udata.u.clockValue;
-	oldClk = ctx->hw_ctx.core_clock_mhz;
-	ctx->hw_ctx.core_clock_mhz = clock->clk;
-
-	if (ctx->state & BC_LINK_READY) {
-		sts = crystalhd_hw_set_core_clock(&ctx->hw_ctx);
-		if (sts == BC_STS_CLK_NOCHG)
-			ctx->hw_ctx.core_clock_mhz = oldClk;
-	}
-
-	clock->clk = ctx->hw_ctx.core_clock_mhz;
-
-	return sts;
-}
-
-/*=============== Cmd Proc Table.. ======================================*/
-static const struct crystalhd_cmd_tbl	g_crystalhd_cproc_tbl[] = {
-	{ BCM_IOC_GET_VERSION,		bc_cproc_get_version,	0},
-	{ BCM_IOC_GET_HWTYPE,		bc_cproc_get_hwtype,	0},
-	{ BCM_IOC_REG_RD,		bc_cproc_reg_rd,	0},
-	{ BCM_IOC_REG_WR,		bc_cproc_reg_wr,	0},
-	{ BCM_IOC_FPGA_RD,		bc_cproc_link_reg_rd,	0},
-	{ BCM_IOC_FPGA_WR,		bc_cproc_link_reg_wr,	0},
-	{ BCM_IOC_MEM_RD,		bc_cproc_mem_rd,	0},
-	{ BCM_IOC_MEM_WR,		bc_cproc_mem_wr,	0},
-	{ BCM_IOC_RD_PCI_CFG,		bc_cproc_cfg_rd,	0},
-	{ BCM_IOC_WR_PCI_CFG,		bc_cproc_cfg_wr,	1},
-	{ BCM_IOC_FW_DOWNLOAD,		bc_cproc_download_fw,	1},
-	{ BCM_IOC_FW_CMD,		bc_cproc_do_fw_cmd,	1},
-	{ BCM_IOC_PROC_INPUT,		bc_cproc_proc_input,	1},
-	{ BCM_IOC_ADD_RXBUFFS,		bc_cproc_add_cap_buff,	1},
-	{ BCM_IOC_FETCH_RXBUFF,		bc_cproc_fetch_frame,	1},
-	{ BCM_IOC_START_RX_CAP,		bc_cproc_start_capture,	1},
-	{ BCM_IOC_FLUSH_RX_CAP,		bc_cproc_flush_cap_buffs, 1},
-	{ BCM_IOC_GET_DRV_STAT,		bc_cproc_get_stats,	0},
-	{ BCM_IOC_RST_DRV_STAT,		bc_cproc_reset_stats,	0},
-	{ BCM_IOC_NOTIFY_MODE,		bc_cproc_notify_mode,	0},
-	{ BCM_IOC_CHG_CLK,		bc_cproc_chg_clk, 0},
-	{ BCM_IOC_END,			NULL},
-};
-
-/*=============== Cmd Proc Functions.. ===================================*/
-
-/**
- * crystalhd_suspend - Power management suspend request.
- * @ctx: Command layer context.
- * @idata: Iodata - required for internal use.
- *
- * Return:
- *	status
- *
- * 1. Set the state to Suspend.
- * 2. Flush the Rx Buffers it will unmap all the buffers and
- *    stop the RxDMA engine.
- * 3. Cancel The TX Io and Stop Dma Engine.
- * 4. Put the DDR in to deep sleep.
- * 5. Stop the hardware putting it in to Reset State.
- *
- * Current gstreamer frame work does not provide any power management
- * related notification to user mode decoder plug-in. As a work-around
- * we pass on the power management notification to our plug-in by completing
- * all outstanding requests with BC_STS_IO_USER_ABORT return code.
- */
-enum BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx,
-				struct crystalhd_ioctl_data *idata)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!ctx || !idata) {
-		BCMLOG_ERR("Invalid Parameters\n");
-		return BC_STS_ERROR;
-	}
-
-	if (ctx->state & BC_LINK_SUSPEND)
-		return BC_STS_SUCCESS;
-
-	if (ctx->state == BC_LINK_INVALID) {
-		BCMLOG(BCMLOG_DBG, "Nothing To Do Suspend Success\n");
-		return BC_STS_SUCCESS;
-	}
-
-	ctx->state |= BC_LINK_SUSPEND;
-
-	bc_cproc_mark_pwr_state(ctx);
-
-	if (ctx->state & BC_LINK_CAP_EN) {
-		sts = bc_cproc_flush_cap_buffs(ctx, idata);
-		if (sts != BC_STS_SUCCESS)
-			return sts;
-	}
-
-	if (ctx->tx_list_id) {
-		sts = crystalhd_hw_cancel_tx(&ctx->hw_ctx, ctx->tx_list_id);
-		if (sts != BC_STS_SUCCESS)
-			return sts;
-	}
-
-	sts = crystalhd_hw_suspend(&ctx->hw_ctx);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	BCMLOG(BCMLOG_DBG, "BCM70012 suspend success\n");
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_resume - Resume frame capture.
- * @ctx: Command layer contextx.
- *
- * Return:
- *	status
- *
- *
- * Resume frame capture.
- *
- * PM_Resume can't resume the playback state back to pre-suspend state
- * because we don't keep video clip related information within driver.
- * To get back to the pre-suspend state App will re-open the device and
- * start a new playback session from the pre-suspend clip position.
- *
- */
-enum BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx)
-{
-	BCMLOG(BCMLOG_DBG, "crystalhd_resume Success %x\n", ctx->state);
-
-	bc_cproc_mark_pwr_state(ctx);
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_user_open - Create application handle.
- * @ctx: Command layer contextx.
- * @user_ctx: User ID context.
- *
- * Return:
- *	status
- *
- * Creates an application specific UID and allocates
- * application specific resources. HW layer initialization
- * is done for the first open request.
- */
-enum BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
-			    struct crystalhd_user **user_ctx)
-{
-	struct crystalhd_user *uc;
-
-	if (!ctx || !user_ctx) {
-		BCMLOG_ERR("Invalid arg..\n");
-		return BC_STS_INV_ARG;
-	}
-
-	uc = bc_cproc_get_uid(ctx);
-	if (!uc) {
-		BCMLOG(BCMLOG_INFO, "No free user context...\n");
-		return BC_STS_BUSY;
-	}
-
-	BCMLOG(BCMLOG_INFO, "Opening new user[%x] handle\n", uc->uid);
-
-	crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
-
-	uc->in_use = 1;
-
-	*user_ctx = uc;
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_user_close - Close application handle.
- * @ctx: Command layer contextx.
- * @uc: User ID context.
- *
- * Return:
- *	status
- *
- * Closer application handle and release app specific
- * resources.
- */
-enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx,
-					 struct crystalhd_user *uc)
-{
-	uint32_t mode = uc->mode;
-
-	ctx->user[uc->uid].mode = DTS_MODE_INV;
-	ctx->user[uc->uid].in_use = 0;
-	ctx->cin_wait_exit = 1;
-	ctx->pwr_state_change = 0;
-
-	BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid);
-
-	if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) {
-		crystalhd_hw_free_dma_rings(&ctx->hw_ctx);
-		crystalhd_destroy_dio_pool(ctx->adp);
-	} else if (bc_cproc_get_user_count(ctx)) {
-		return BC_STS_SUCCESS;
-	}
-
-	crystalhd_hw_close(&ctx->hw_ctx);
-
-	ctx->state = BC_LINK_INVALID;
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_setup_cmd_context - Setup Command layer resources.
- * @ctx: Command layer contextx.
- * @adp: Adapter context
- *
- * Return:
- *	status
- *
- * Called at the time of driver load.
- */
-enum BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
-				    struct crystalhd_adp *adp)
-{
-	int i = 0;
-
-	if (!ctx || !adp) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (ctx->adp)
-		BCMLOG(BCMLOG_DBG, "Resetting Cmd context delete missing..\n");
-
-	ctx->adp = adp;
-	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
-		ctx->user[i].uid = i;
-		ctx->user[i].in_use = 0;
-		ctx->user[i].mode = DTS_MODE_INV;
-	}
-
-	/*Open and Close the Hardware to put it in to sleep state*/
-	crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
-	crystalhd_hw_close(&ctx->hw_ctx);
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_delete_cmd_context - Release Command layer resources.
- * @ctx: Command layer contextx.
- *
- * Return:
- *	status
- *
- * Called at the time of driver un-load.
- */
-enum BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
-{
-	BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
-
-	ctx->adp = NULL;
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_get_cmd_proc  - Cproc table lookup.
- * @ctx: Command layer contextx.
- * @cmd: IOCTL command code.
- * @uc: User ID context.
- *
- * Return:
- *	command proc function pointer
- *
- * This function checks the process context, application's
- * mode of operation and returns the function pointer
- * from the cproc table.
- */
-crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx,
-				 uint32_t cmd, struct crystalhd_user *uc)
-{
-	crystalhd_cmd_proc cproc = NULL;
-	unsigned int i, tbl_sz;
-
-	if (!ctx) {
-		BCMLOG_ERR("Invalid arg.. Cmd[%d]\n", cmd);
-		return NULL;
-	}
-
-	if ((cmd != BCM_IOC_GET_DRV_STAT) && (ctx->state & BC_LINK_SUSPEND)) {
-		BCMLOG_ERR("Invalid State [suspend Set].. Cmd[%d]\n", cmd);
-		return NULL;
-	}
-
-	tbl_sz = sizeof(g_crystalhd_cproc_tbl) /
-				 sizeof(struct crystalhd_cmd_tbl);
-	for (i = 0; i < tbl_sz; i++) {
-		if (g_crystalhd_cproc_tbl[i].cmd_id == cmd) {
-			if ((uc->mode == DTS_MONITOR_MODE) &&
-			    (g_crystalhd_cproc_tbl[i].block_mon)) {
-				BCMLOG(BCMLOG_INFO, "Blocking cmd %d\n", cmd);
-				break;
-			}
-			cproc = g_crystalhd_cproc_tbl[i].cmd_proc;
-			break;
-		}
-	}
-
-	return cproc;
-}
-
-/**
- * crystalhd_cmd_interrupt - ISR entry point
- * @ctx: Command layer contextx.
- *
- * Return:
- *	TRUE: If interrupt from bcm70012 device.
- *
- *
- * ISR entry point from OS layer.
- */
-bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx)
-{
-	if (!ctx) {
-		BCMLOG_ERR("Invalid arg..\n");
-		return false;
-	}
-
-	return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_cmds.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_cmds.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_cmds.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_cmds.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_cmds . h
- *
- *  Description:
- *		BCM70010 Linux driver user command interfaces.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#ifndef _CRYSTALHD_CMDS_H_
-#define _CRYSTALHD_CMDS_H_
-
-/*
- * NOTE:: This is the main interface file between the Linux layer
- *        and the hardware layer. This file will use the definitions
- *        from _dts_glob and dts_defs etc.. which are defined for
- *        windows.
- */
-
-#include "crystalhd.h"
-
-enum crystalhd_state {
-	BC_LINK_INVALID		= 0x00,
-	BC_LINK_INIT		= 0x01,
-	BC_LINK_CAP_EN		= 0x02,
-	BC_LINK_FMT_CHG		= 0x04,
-	BC_LINK_SUSPEND		= 0x10,
-	BC_LINK_PAUSED		= 0x20,
-	BC_LINK_READY	= (BC_LINK_INIT | BC_LINK_CAP_EN | BC_LINK_FMT_CHG),
-};
-
-struct crystalhd_user {
-	uint32_t	uid;
-	uint32_t	in_use;
-	uint32_t	mode;
-};
-
-#define DTS_MODE_INV	(-1)
-
-struct crystalhd_cmd {
-	uint32_t		state;
-	struct crystalhd_adp	*adp;
-	struct crystalhd_user	user[BC_LINK_MAX_OPENS];
-
-	spinlock_t		ctx_lock;
-	uint32_t		tx_list_id;
-	uint32_t		cin_wait_exit;
-	uint32_t		pwr_state_change;
-	struct crystalhd_hw	hw_ctx;
-};
-
-typedef enum BC_STATUS(*crystalhd_cmd_proc)(struct crystalhd_cmd *,
-					 struct crystalhd_ioctl_data *);
-
-struct crystalhd_cmd_tbl {
-	uint32_t		cmd_id;
-	const crystalhd_cmd_proc	cmd_proc;
-	uint32_t		block_mon;
-};
-
-enum BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx,
-				 struct crystalhd_ioctl_data *idata);
-enum BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx);
-crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx,
-				 uint32_t cmd, struct crystalhd_user *uc);
-enum BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
-				 struct crystalhd_user **user_ctx);
-enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx,
-				 struct crystalhd_user *uc);
-enum BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
-				 struct crystalhd_adp *adp);
-enum BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx);
-bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_fw_if.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_fw_if.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_fw_if.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_fw_if.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,370 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_fw_if . h
- *
- *  Description:
- *		BCM70012 Firmware interface definitions.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#ifndef _CRYSTALHD_FW_IF_H_
-#define _CRYSTALHD_FW_IF_H_
-
-/* TBD: Pull in only required defs into this file.. */
-
-/* User Data Header */
-struct user_data {
-	struct user_data	*next;
-	uint32_t		type;
-	uint32_t		size;
-};
-
-/*------------------------------------------------------*
- *    MPEG Extension to the PPB			 *
- *------------------------------------------------------*/
-struct ppb_mpeg {
-	uint32_t		to_be_defined;
-	uint32_t		valid;
-
-	/* Always valid, defaults to picture size if no
-	   sequence display extension in the stream. */
-	uint32_t		display_horizontal_size;
-	uint32_t		display_vertical_size;
-
-	/* MPEG_VALID_PANSCAN
-	   Offsets are a copy values from the MPEG stream. */
-	uint32_t		offset_count;
-	int32_t		horizontal_offset[3];
-	int32_t		vertical_offset[3];
-
-	/* MPEG_VALID_USERDATA
-	   User data is in the form of a linked list. */
-	int32_t		userDataSize;
-	struct user_data	*userData;
-
-};
-
-
-/*------------------------------------------------------*
- *    VC1 Extension to the PPB			  *
- *------------------------------------------------------*/
-struct ppb_vc1 {
-	uint32_t		to_be_defined;
-	uint32_t		valid;
-
-	/* Always valid, defaults to picture size if no
-	   sequence display extension in the stream. */
-	uint32_t		display_horizontal_size;
-	uint32_t		display_vertical_size;
-
-	/* VC1 pan scan windows */
-	uint32_t		num_panscan_windows;
-	int32_t		ps_horiz_offset[4];
-	int32_t		ps_vert_offset[4];
-	int32_t		ps_width[4];
-	int32_t		ps_height[4];
-
-	/* VC1_VALID_USERDATA
-	   User data is in the form of a linked list. */
-	int32_t		userDataSize;
-	struct user_data	*userData;
-
-};
-
-/*------------------------------------------------------*
- *    H.264 Extension to the PPB			*
- *------------------------------------------------------*/
-
-/**
- * @brief Film grain SEI message.
- *
- * Content of the film grain SEI message.
- */
-
-/* maximum number of model-values as for Thomson spec(standard says 5) */
-#define MAX_FGT_MODEL_VALUE	 (3)
-
-/* maximum number of intervals(as many as 256 intervals?) */
-#define MAX_FGT_VALUE_INTERVAL	(256)
-
-struct fgt_sei {
-	struct fgt_sei *next;
-	unsigned char
-		 model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
-	unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
-	unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
-
-	unsigned char cancel_flag;	/* Cancel flag: 1 no film grain. */
-	unsigned char model_id;	/* Model id. */
-
-	/* +unused SE based on Thomson spec */
-	unsigned char color_desc_flag;	/* Separate color description flag. */
-	unsigned char bit_depth_luma;	/* Bit depth luma minus 8. */
-	unsigned char bit_depth_chroma;	/* Bit depth chroma minus 8. */
-	unsigned char full_range_flag;	/* Full range flag. */
-	unsigned char color_primaries;	/* Color primaries. */
-	unsigned char transfer_charact;	/* Transfer characteristics. */
-	unsigned char matrix_coeff;		/*< Matrix coefficients. */
-	/* -unused SE based on Thomson spec */
-
-	unsigned char blending_mode_id;	/* Blending mode. */
-	unsigned char log2_scale_factor;	/* Log2 scale factor (2-7). */
-	unsigned char comp_flag[3];	/* Components [0,2]
-					 parameters present flag. */
-	unsigned char num_intervals_minus1[3]; /* Number of
-					 intensity level intervals. */
-	unsigned char num_model_values[3];	/* Number of model values. */
-	uint16_t      repetition_period; /* Repetition period (0-16384) */
-
-};
-
-struct ppb_h264 {
-	/* 'valid' specifies which fields (or sets of
-	 * fields) below are valid.  If the corresponding
-	 * bit in 'valid' is NOT set then that field(s)
-	 * is (are) not initialized. */
-	uint32_t	valid;
-
-	int32_t		poc_top;	/* POC for Top Field/Frame */
-	int32_t		poc_bottom;	/* POC for Bottom Field    */
-	uint32_t		idr_pic_id;
-
-	/* H264_VALID_PANSCAN */
-	uint32_t		pan_scan_count;
-	int32_t		pan_scan_left[3];
-	int32_t		pan_scan_right[3];
-	int32_t		pan_scan_top[3];
-	int32_t		pan_scan_bottom[3];
-
-	/* H264_VALID_CT_TYPE */
-	uint32_t		ct_type_count;
-	uint32_t		ct_type[3];
-
-	/* H264_VALID_SPS_CROP */
-	int32_t		sps_crop_left;
-	int32_t		sps_crop_right;
-	int32_t		sps_crop_top;
-	int32_t		sps_crop_bottom;
-
-	/* H264_VALID_VUI */
-	uint32_t		chroma_top;
-	uint32_t		chroma_bottom;
-
-	/* H264_VALID_USER */
-	uint32_t		user_data_size;
-	struct user_data	*user_data;
-
-	/* H264 VALID FGT */
-	struct fgt_sei	*pfgt;
-
-};
-
-struct ppb {
-	/* Common fields. */
-	uint32_t	picture_number;	/* Ordinal display number */
-	uint32_t	video_buffer;	/* Video (picbuf) number */
-	uint32_t	video_address;	/* Address of picbuf Y */
-	uint32_t	video_address_uv; /* Address of picbuf UV */
-	uint32_t	video_stripe;	/* Picbuf stripe */
-	uint32_t	video_width;	/* Picbuf width */
-	uint32_t	video_height;	/* Picbuf height */
-
-	uint32_t	channel_id;	/* Decoder channel ID */
-	uint32_t	status;		/* reserved */
-	uint32_t	width;		/* pixels */
-	uint32_t	height;		/* pixels */
-	uint32_t	chroma_format;	/* see above */
-	uint32_t	pulldown;	/* see above */
-	uint32_t	flags;		/* see above */
-	uint32_t	pts;		/* 32 LSBs of PTS */
-	uint32_t	protocol;	/* protocolXXX (above) */
-
-	uint32_t	frame_rate;	/* see above */
-	uint32_t	matrix_coeff;	/* see above */
-	uint32_t	aspect_ratio;	/* see above */
-	uint32_t	colour_primaries; /* see above */
-	uint32_t	transfer_char;	/* see above */
-	uint32_t	pcr_offset;	/* 45kHz if PCR type; else 27MHz */
-	uint32_t	n_drop;		/* Number of pictures to be dropped */
-
-	uint32_t	custom_aspect_ratio_width_height;
-	/* upper 16-bits is Y and lower 16-bits is X */
-
-	uint32_t	picture_tag;	/* Indexing tag from BUD packets */
-	uint32_t	picture_done_payload;
-	uint32_t	picture_meta_payload;
-	uint32_t	reserved[1];
-
-	/* Protocol-specific extensions. */
-	union {
-		struct ppb_h264	h264;
-		struct ppb_mpeg	mpeg;
-		struct ppb_vc1	 vc1;
-	} other;
-
-};
-
-struct c011_pib {
-	uint32_t	bFormatChange;
-	uint32_t	resolution;
-	uint32_t	channelId;
-	uint32_t	ppbPtr;
-	int32_t	ptsStcOffset;
-	uint32_t	zeroPanscanValid;
-	uint32_t	dramOutBufAddr;
-	uint32_t	yComponent;
-	struct ppb	ppb;
-
-};
-
-struct dec_rsp_channel_start_video {
-	uint32_t	command;
-	uint32_t	sequence;
-	uint32_t	status;
-	uint32_t	picBuf;
-	uint32_t	picRelBuf;
-	uint32_t	picInfoDeliveryQ;
-	uint32_t	picInfoReleaseQ;
-	uint32_t	channelStatus;
-	uint32_t	userDataDeliveryQ;
-	uint32_t	userDataReleaseQ;
-	uint32_t	transportStreamCaptureAddr;
-	uint32_t	asyncEventQ;
-
-};
-
-#define eCMD_C011_CMD_BASE	  (0x73763000)
-
-/* host commands */
-enum  c011_ts_cmd {
-	eCMD_TS_GET_NEXT_PIC	= 0x7376F100, /* debug get next picture */
-	eCMD_TS_GET_LAST_PIC	= 0x7376F102, /* debug get last pic status */
-	eCMD_TS_READ_WRITE_MEM	= 0x7376F104, /* debug read write memory */
-
-	/* New API commands */
-	/* General commands */
-	eCMD_C011_INIT		= eCMD_C011_CMD_BASE + 0x01,
-	eCMD_C011_RESET		= eCMD_C011_CMD_BASE + 0x02,
-	eCMD_C011_SELF_TEST		= eCMD_C011_CMD_BASE + 0x03,
-	eCMD_C011_GET_VERSION	= eCMD_C011_CMD_BASE + 0x04,
-	eCMD_C011_GPIO		= eCMD_C011_CMD_BASE + 0x05,
-	eCMD_C011_DEBUG_SETUP	= eCMD_C011_CMD_BASE + 0x06,
-
-	/* Decoding commands */
-	eCMD_C011_DEC_CHAN_OPEN			= eCMD_C011_CMD_BASE + 0x100,
-	eCMD_C011_DEC_CHAN_CLOSE		= eCMD_C011_CMD_BASE + 0x101,
-	eCMD_C011_DEC_CHAN_ACTIVATE		= eCMD_C011_CMD_BASE + 0x102,
-	eCMD_C011_DEC_CHAN_STATUS		= eCMD_C011_CMD_BASE + 0x103,
-	eCMD_C011_DEC_CHAN_FLUSH		= eCMD_C011_CMD_BASE + 0x104,
-	eCMD_C011_DEC_CHAN_TRICK_PLAY		= eCMD_C011_CMD_BASE + 0x105,
-	eCMD_C011_DEC_CHAN_TS_PIDS		= eCMD_C011_CMD_BASE + 0x106,
-	eCMD_C011_DEC_CHAN_PS_STREAM_ID		= eCMD_C011_CMD_BASE + 0x107,
-	eCMD_C011_DEC_CHAN_INPUT_PARAMS		= eCMD_C011_CMD_BASE + 0x108,
-	eCMD_C011_DEC_CHAN_VIDEO_OUTPUT		= eCMD_C011_CMD_BASE + 0x109,
-	eCMD_C011_DEC_CHAN_OUTPUT_FORMAT	= eCMD_C011_CMD_BASE + 0x10A,
-	eCMD_C011_DEC_CHAN_SCALING_FILTERS	= eCMD_C011_CMD_BASE + 0x10B,
-	eCMD_C011_DEC_CHAN_OSD_MODE		= eCMD_C011_CMD_BASE + 0x10D,
-	eCMD_C011_DEC_CHAN_DROP			= eCMD_C011_CMD_BASE + 0x10E,
-	eCMD_C011_DEC_CHAN_RELEASE		= eCMD_C011_CMD_BASE + 0x10F,
-	eCMD_C011_DEC_CHAN_STREAM_SETTINGS	= eCMD_C011_CMD_BASE + 0x110,
-	eCMD_C011_DEC_CHAN_PAUSE_OUTPUT		= eCMD_C011_CMD_BASE + 0x111,
-	eCMD_C011_DEC_CHAN_CHANGE		= eCMD_C011_CMD_BASE + 0x112,
-	eCMD_C011_DEC_CHAN_SET_STC		= eCMD_C011_CMD_BASE + 0x113,
-	eCMD_C011_DEC_CHAN_SET_PTS		= eCMD_C011_CMD_BASE + 0x114,
-	eCMD_C011_DEC_CHAN_CC_MODE		= eCMD_C011_CMD_BASE + 0x115,
-	eCMD_C011_DEC_CREATE_AUDIO_CONTEXT	= eCMD_C011_CMD_BASE + 0x116,
-	eCMD_C011_DEC_COPY_AUDIO_CONTEXT	= eCMD_C011_CMD_BASE + 0x117,
-	eCMD_C011_DEC_DELETE_AUDIO_CONTEXT	= eCMD_C011_CMD_BASE + 0x118,
-	eCMD_C011_DEC_CHAN_SET_DECYPTION	= eCMD_C011_CMD_BASE + 0x119,
-	eCMD_C011_DEC_CHAN_START_VIDEO		= eCMD_C011_CMD_BASE + 0x11A,
-	eCMD_C011_DEC_CHAN_STOP_VIDEO		= eCMD_C011_CMD_BASE + 0x11B,
-	eCMD_C011_DEC_CHAN_PIC_CAPTURE		= eCMD_C011_CMD_BASE + 0x11C,
-	eCMD_C011_DEC_CHAN_PAUSE		= eCMD_C011_CMD_BASE + 0x11D,
-	eCMD_C011_DEC_CHAN_PAUSE_STATE		= eCMD_C011_CMD_BASE + 0x11E,
-	eCMD_C011_DEC_CHAN_SET_SLOWM_RATE	= eCMD_C011_CMD_BASE + 0x11F,
-	eCMD_C011_DEC_CHAN_GET_SLOWM_RATE	= eCMD_C011_CMD_BASE + 0x120,
-	eCMD_C011_DEC_CHAN_SET_FF_RATE		= eCMD_C011_CMD_BASE + 0x121,
-	eCMD_C011_DEC_CHAN_GET_FF_RATE		= eCMD_C011_CMD_BASE + 0x122,
-	eCMD_C011_DEC_CHAN_FRAME_ADVANCE	= eCMD_C011_CMD_BASE + 0x123,
-	eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE	= eCMD_C011_CMD_BASE + 0x124,
-	eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE	= eCMD_C011_CMD_BASE + 0x125,
-	eCMD_C011_DEC_CHAN_FILL_PIC_BUF		= eCMD_C011_CMD_BASE + 0x126,
-	eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK	= eCMD_C011_CMD_BASE + 0x127,
-	eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK	= eCMD_C011_CMD_BASE + 0x128,
-	eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x129,
-	eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x12A,
-	eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS	= eCMD_C011_CMD_BASE + 0x12B,
-	eCMD_C011_DEC_CHAN_I_PICTURE_FOUND	= eCMD_C011_CMD_BASE + 0x12C,
-	eCMD_C011_DEC_CHAN_SET_PARAMETER	= eCMD_C011_CMD_BASE + 0x12D,
-	eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE	= eCMD_C011_CMD_BASE + 0x12E,
-	eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x12F,
-	eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x130,
-	eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x131,
-	eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE = eCMD_C011_CMD_BASE +
-								 0x132,
-	eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x133,
-	eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x134,
-	eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD	= eCMD_C011_CMD_BASE + 0x135,
-	eCMD_C011_DEC_CHAN_STREAM_OPEN		= eCMD_C011_CMD_BASE + 0x136,
-	eCMD_C011_DEC_CHAN_SET_PCR_PID		= eCMD_C011_CMD_BASE + 0x137,
-	eCMD_C011_DEC_CHAN_SET_VID_PID		= eCMD_C011_CMD_BASE + 0x138,
-	eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE	= eCMD_C011_CMD_BASE + 0x139,
-	eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS	= eCMD_C011_CMD_BASE + 0x140,
-	eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS	= eCMD_C011_CMD_BASE + 0x141,
-	eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER	= eCMD_C011_CMD_BASE + 0x142,
-	eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER	= eCMD_C011_CMD_BASE + 0x143,
-	eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x144,
-	eCMD_C011_DEC_CHAN_SET_OPERATION_MODE	= eCMD_C011_CMD_BASE + 0x145,
-	eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS = eCMD_C011_CMD_BASE + 0x146,
-	eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE +
-								 0x147,
-	eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF	= eCMD_C011_CMD_BASE + 0x148,
-	eCMD_C011_DEC_CHAN_SET_CLIPPING		= eCMD_C011_CMD_BASE + 0x149,
-	eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
-		= eCMD_C011_CMD_BASE + 0x150,
-
-	/* Decoder RevD commands */
-	eCMD_C011_DEC_CHAN_SET_CSC	= eCMD_C011_CMD_BASE + 0x180, /* color
-							 space conversion */
-	eCMD_C011_DEC_CHAN_SET_RANGE_REMAP	= eCMD_C011_CMD_BASE + 0x181,
-	eCMD_C011_DEC_CHAN_SET_FGT		= eCMD_C011_CMD_BASE + 0x182,
-	/* Note: 0x183 not implemented yet in Rev D main */
-	eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE +
-								 0x183,
-
-	/* Decoder 7412 commands (7412-only) */
-	eCMD_C011_DEC_CHAN_SET_CONTENT_KEY	= eCMD_C011_CMD_BASE + 0x190,
-	eCMD_C011_DEC_CHAN_SET_SESSION_KEY	= eCMD_C011_CMD_BASE + 0x191,
-	eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK	= eCMD_C011_CMD_BASE + 0x192,
-
-	eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT    = eCMD_C011_CMD_BASE + 0x1FF,
-
-	/* Encoding commands */
-	eCMD_C011_ENC_CHAN_OPEN		= eCMD_C011_CMD_BASE + 0x200,
-	eCMD_C011_ENC_CHAN_CLOSE		= eCMD_C011_CMD_BASE + 0x201,
-	eCMD_C011_ENC_CHAN_ACTIVATE		= eCMD_C011_CMD_BASE + 0x202,
-	eCMD_C011_ENC_CHAN_CONTROL		= eCMD_C011_CMD_BASE + 0x203,
-	eCMD_C011_ENC_CHAN_STATISTICS	= eCMD_C011_CMD_BASE + 0x204,
-
-	eNOTIFY_C011_ENC_CHAN_EVENT		= eCMD_C011_CMD_BASE + 0x210,
-
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-#ifndef _CRYSTALHD_H_
-#define _CRYSTALHD_H_
-
-#include "bc_dts_defs.h"
-#include "crystalhd_misc.h"
-#include "bc_dts_glob_lnx.h"
-#include "crystalhd_hw.h"
-#include "crystalhd_cmds.h"
-#include "crystalhd_lnx.h"
-#include "bcm_70012_regs.h"
-#include "crystalhd_fw_if.h"
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_hw.c linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_hw.c
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2458 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_hw . c
- *
- *  Description:
- *		BCM70010 Linux driver HW layer.
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#include "crystalhd.h"
-
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-/* Functions internal to this file */
-
-static void crystalhd_enable_uarts(struct crystalhd_adp *adp)
-{
-	bc_dec_reg_wr(adp, UartSelectA, BSVS_UART_STREAM);
-	bc_dec_reg_wr(adp, UartSelectB, BSVS_UART_DEC_OUTER);
-}
-
-
-static void crystalhd_start_dram(struct crystalhd_adp *adp)
-{
-	bc_dec_reg_wr(adp, SDRAM_PARAM, ((40 / 5 - 1) <<  0) |
-	/* tras (40ns tras)/(5ns period) -1 ((15/5 - 1) <<  4) | // trcd */
-		      ((15 / 5 - 1) <<  7) |	/* trp */
-		      ((10 / 5 - 1) << 10) |	/* trrd */
-		      ((15 / 5 + 1) << 12) |	/* twr */
-		      ((2 + 1) << 16) |		/* twtr */
-		      ((70 / 5 - 2) << 19) |	/* trfc */
-		      (0 << 23));
-
-	bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
-	bc_dec_reg_wr(adp, SDRAM_EXT_MODE, 2);
-	bc_dec_reg_wr(adp, SDRAM_MODE, 0x132);
-	bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
-	bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
-	bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
-	bc_dec_reg_wr(adp, SDRAM_MODE, 0x32);
-	/* setting the refresh rate here */
-	bc_dec_reg_wr(adp, SDRAM_REF_PARAM, ((1 << 12) | 96));
-}
-
-
-static bool crystalhd_bring_out_of_rst(struct crystalhd_adp *adp)
-{
-	union link_misc_perst_deco_ctrl rst_deco_cntrl;
-	union link_misc_perst_clk_ctrl rst_clk_cntrl;
-	uint32_t temp;
-
-	/*
-	 * Link clocks: MISC_PERST_CLOCK_CTRL Clear PLL power down bit,
-	 * delay to allow PLL to lock Clear alternate clock, stop clock bits
-	 */
-	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
-	rst_clk_cntrl.pll_pwr_dn = 0;
-	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
-	msleep_interruptible(50);
-
-	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
-	rst_clk_cntrl.stop_core_clk = 0;
-	rst_clk_cntrl.sel_alt_clk = 0;
-
-	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
-	msleep_interruptible(50);
-
-	/*
-	 * Bus Arbiter Timeout: GISB_ARBITER_TIMER
-	 * Set internal bus arbiter timeout to 40us based on core clock speed
-	 * (63MHz * 40us = 0x9D8)
-	 */
-	crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x9D8);
-
-	/*
-	 * Decoder clocks: MISC_PERST_DECODER_CTRL
-	 * Enable clocks while 7412 reset is asserted, delay
-	 * De-assert 7412 reset
-	 */
-	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp,
-					 MISC_PERST_DECODER_CTRL);
-	rst_deco_cntrl.stop_bcm_7412_clk = 0;
-	rst_deco_cntrl.bcm7412_rst = 1;
-	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL,
-					 rst_deco_cntrl.whole_reg);
-	msleep_interruptible(10);
-
-	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp,
-					 MISC_PERST_DECODER_CTRL);
-	rst_deco_cntrl.bcm7412_rst = 0;
-	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL,
-					 rst_deco_cntrl.whole_reg);
-	msleep_interruptible(50);
-
-	/* Disable OTP_CONTENT_MISC to 0 to disable all secure modes */
-	crystalhd_reg_wr(adp, OTP_CONTENT_MISC, 0);
-
-	/* Clear bit 29 of 0x404 */
-	temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
-	temp &= ~BC_BIT(29);
-	crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
-
-	/* 2.5V regulator must be set to 2.6 volts (+6%) */
-	/* FIXME: jarod: what's the point of this reg read? */
-	temp = crystalhd_reg_rd(adp, MISC_PERST_VREG_CTRL);
-	crystalhd_reg_wr(adp, MISC_PERST_VREG_CTRL, 0xF3);
-
-	return true;
-}
-
-static bool crystalhd_put_in_reset(struct crystalhd_adp *adp)
-{
-	union link_misc_perst_deco_ctrl rst_deco_cntrl;
-	union link_misc_perst_clk_ctrl  rst_clk_cntrl;
-	uint32_t                  temp;
-
-	/*
-	 * Decoder clocks: MISC_PERST_DECODER_CTRL
-	 * Assert 7412 reset, delay
-	 * Assert 7412 stop clock
-	 */
-	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp,
-					 MISC_PERST_DECODER_CTRL);
-	rst_deco_cntrl.stop_bcm_7412_clk = 1;
-	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL,
-					 rst_deco_cntrl.whole_reg);
-	msleep_interruptible(50);
-
-	/* Bus Arbiter Timeout: GISB_ARBITER_TIMER
-	 * Set internal bus arbiter timeout to 40us based on core clock speed
-	 * (6.75MHZ * 40us = 0x10E)
-	 */
-	crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x10E);
-
-	/* Link clocks: MISC_PERST_CLOCK_CTRL
-	 * Stop core clk, delay
-	 * Set alternate clk, delay, set PLL power down
-	 */
-	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
-	rst_clk_cntrl.stop_core_clk = 1;
-	rst_clk_cntrl.sel_alt_clk = 1;
-	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
-	msleep_interruptible(50);
-
-	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
-	rst_clk_cntrl.pll_pwr_dn = 1;
-	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
-
-	/*
-	 * Read and restore the Transaction Configuration Register
-	 * after core reset
-	 */
-	temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
-
-	/*
-	 * Link core soft reset: MISC3_RESET_CTRL
-	 * - Write BIT[0]=1 and read it back for core reset to take place
-	 */
-	crystalhd_reg_wr(adp, MISC3_RESET_CTRL, 1);
-	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC3_RESET_CTRL);
-	msleep_interruptible(50);
-
-	/* restore the transaction configuration register */
-	crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
-
-	return true;
-}
-
-static void crystalhd_disable_interrupts(struct crystalhd_adp *adp)
-{
-	union intr_mask_reg   intr_mask;
-	intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
-	intr_mask.mask_pcie_err = 1;
-	intr_mask.mask_pcie_rbusmast_err = 1;
-	intr_mask.mask_pcie_rgr_bridge   = 1;
-	intr_mask.mask_rx_done = 1;
-	intr_mask.mask_rx_err  = 1;
-	intr_mask.mask_tx_done = 1;
-	intr_mask.mask_tx_err  = 1;
-	crystalhd_reg_wr(adp, INTR_INTR_MSK_SET_REG, intr_mask.whole_reg);
-
-	return;
-}
-
-static void crystalhd_enable_interrupts(struct crystalhd_adp *adp)
-{
-	union intr_mask_reg   intr_mask;
-	intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
-	intr_mask.mask_pcie_err = 1;
-	intr_mask.mask_pcie_rbusmast_err = 1;
-	intr_mask.mask_pcie_rgr_bridge   = 1;
-	intr_mask.mask_rx_done = 1;
-	intr_mask.mask_rx_err  = 1;
-	intr_mask.mask_tx_done = 1;
-	intr_mask.mask_tx_err  = 1;
-	crystalhd_reg_wr(adp, INTR_INTR_MSK_CLR_REG, intr_mask.whole_reg);
-
-	return;
-}
-
-static void crystalhd_clear_errors(struct crystalhd_adp *adp)
-{
-	uint32_t reg;
-
-	/* FIXME: jarod: wouldn't we want to write a 0 to the reg?
-	 Or does the write clear the bits specified? */
-	reg = crystalhd_reg_rd(adp, MISC1_Y_RX_ERROR_STATUS);
-	if (reg)
-		crystalhd_reg_wr(adp, MISC1_Y_RX_ERROR_STATUS, reg);
-
-	reg = crystalhd_reg_rd(adp, MISC1_UV_RX_ERROR_STATUS);
-	if (reg)
-		crystalhd_reg_wr(adp, MISC1_UV_RX_ERROR_STATUS, reg);
-
-	reg = crystalhd_reg_rd(adp, MISC1_TX_DMA_ERROR_STATUS);
-	if (reg)
-		crystalhd_reg_wr(adp, MISC1_TX_DMA_ERROR_STATUS, reg);
-}
-
-static void crystalhd_clear_interrupts(struct crystalhd_adp *adp)
-{
-	uint32_t intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
-
-	if (intr_sts) {
-		crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
-
-		/* Write End Of Interrupt for PCIE */
-		crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
-	}
-}
-
-static void crystalhd_soft_rst(struct crystalhd_adp *adp)
-{
-	uint32_t val;
-
-	/* Assert c011 soft reset*/
-	bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000001);
-	msleep_interruptible(50);
-
-	/* Release c011 soft reset*/
-	bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000000);
-
-	/* Disable Stuffing..*/
-	val = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
-	val |= BC_BIT(8);
-	crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, val);
-}
-
-static bool crystalhd_load_firmware_config(struct crystalhd_adp *adp)
-{
-	uint32_t i = 0, reg;
-
-	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (BC_DRAM_FW_CFG_ADDR >> 19));
-
-	crystalhd_reg_wr(adp, AES_CMD, 0);
-	crystalhd_reg_wr(adp, AES_CONFIG_INFO,
-		 (BC_DRAM_FW_CFG_ADDR & 0x7FFFF));
-	crystalhd_reg_wr(adp, AES_CMD, 0x1);
-
-	/* FIXME: jarod: I've seen this fail,
-	 and introducing extra delays helps... */
-	for (i = 0; i < 100; ++i) {
-		reg = crystalhd_reg_rd(adp, AES_STATUS);
-		if (reg & 0x1)
-			return true;
-		msleep_interruptible(10);
-	}
-
-	return false;
-}
-
-
-static bool crystalhd_start_device(struct crystalhd_adp *adp)
-{
-	uint32_t dbg_options, glb_cntrl = 0, reg_pwrmgmt = 0;
-
-	BCMLOG(BCMLOG_INFO, "Starting BCM70012 Device\n");
-
-	reg_pwrmgmt = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
-	reg_pwrmgmt &= ~ASPM_L1_ENABLE;
-
-	crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg_pwrmgmt);
-
-	if (!crystalhd_bring_out_of_rst(adp)) {
-		BCMLOG_ERR("Failed To Bring Link Out Of Reset\n");
-		return false;
-	}
-
-	crystalhd_disable_interrupts(adp);
-
-	crystalhd_clear_errors(adp);
-
-	crystalhd_clear_interrupts(adp);
-
-	crystalhd_enable_interrupts(adp);
-
-	/* Enable the option for getting the total no. of DWORDS
-	 * that have been transferred by the RXDMA engine
-	 */
-	dbg_options = crystalhd_reg_rd(adp, MISC1_DMA_DEBUG_OPTIONS_REG);
-	dbg_options |= 0x10;
-	crystalhd_reg_wr(adp, MISC1_DMA_DEBUG_OPTIONS_REG, dbg_options);
-
-	/* Enable PCI Global Control options */
-	glb_cntrl = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
-	glb_cntrl |= 0x100;
-	glb_cntrl |= 0x8000;
-	crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, glb_cntrl);
-
-	crystalhd_enable_interrupts(adp);
-
-	crystalhd_soft_rst(adp);
-	crystalhd_start_dram(adp);
-	crystalhd_enable_uarts(adp);
-
-	return true;
-}
-
-static bool crystalhd_stop_device(struct crystalhd_adp *adp)
-{
-	uint32_t reg;
-
-	BCMLOG(BCMLOG_INFO, "Stopping BCM70012 Device\n");
-	/* Clear and disable interrupts */
-	crystalhd_disable_interrupts(adp);
-	crystalhd_clear_errors(adp);
-	crystalhd_clear_interrupts(adp);
-
-	if (!crystalhd_put_in_reset(adp))
-		BCMLOG_ERR("Failed to Put Link To Reset State\n");
-
-	reg = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
-	reg |= ASPM_L1_ENABLE;
-	crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg);
-
-	/* Set PCI Clk Req */
-	reg = crystalhd_reg_rd(adp, PCIE_CLK_REQ_REG);
-	reg |= PCI_CLK_REQ_ENABLE;
-	crystalhd_reg_wr(adp, PCIE_CLK_REQ_REG, reg);
-
-	return true;
-}
-
-static struct crystalhd_rx_dma_pkt *crystalhd_hw_alloc_rx_pkt(
-					struct crystalhd_hw *hw)
-{
-	unsigned long flags = 0;
-	struct crystalhd_rx_dma_pkt *temp = NULL;
-
-	if (!hw)
-		return NULL;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	temp = hw->rx_pkt_pool_head;
-	if (temp) {
-		hw->rx_pkt_pool_head = hw->rx_pkt_pool_head->next;
-		temp->dio_req = NULL;
-		temp->pkt_tag = 0;
-		temp->flags = 0;
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	return temp;
-}
-
-static void crystalhd_hw_free_rx_pkt(struct crystalhd_hw *hw,
-				   struct crystalhd_rx_dma_pkt *pkt)
-{
-	unsigned long flags = 0;
-
-	if (!hw || !pkt)
-		return;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	pkt->next = hw->rx_pkt_pool_head;
-	hw->rx_pkt_pool_head = pkt;
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-/*
- * Call back from TX - IOQ deletion.
- *
- * This routine will release the TX DMA rings allocated
- * during setup_dma rings interface.
- *
- * Memory is allocated per DMA ring basis. This is just
- * a place holder to be able to create the dio queues.
- */
-static void crystalhd_tx_desc_rel_call_back(void *context, void *data)
-{
-}
-
-/*
- * Rx Packet release callback..
- *
- * Release All user mapped capture buffers and Our DMA packets
- * back to our free pool. The actual cleanup of the DMA
- * ring descriptors happen during dma ring release.
- */
-static void crystalhd_rx_pkt_rel_call_back(void *context, void *data)
-{
-	struct crystalhd_hw *hw = (struct crystalhd_hw *)context;
-	struct crystalhd_rx_dma_pkt *pkt = (struct crystalhd_rx_dma_pkt *)data;
-
-	if (!pkt || !hw) {
-		BCMLOG_ERR("Invalid arg - %p %p\n", hw, pkt);
-		return;
-	}
-
-	if (pkt->dio_req)
-		crystalhd_unmap_dio(hw->adp, pkt->dio_req);
-	else
-		BCMLOG_ERR("Missing dio_req: 0x%x\n", pkt->pkt_tag);
-
-	crystalhd_hw_free_rx_pkt(hw, pkt);
-}
-
-#define crystalhd_hw_delete_ioq(adp, q)		\
-do {						\
-	if (q) {				\
-		crystalhd_delete_dioq(adp, q);	\
-		q = NULL;			\
-	}					\
-} while (0)
-
-static void crystalhd_hw_delete_ioqs(struct crystalhd_hw *hw)
-{
-	if (!hw)
-		return;
-
-	BCMLOG(BCMLOG_DBG, "Deleting IOQs\n");
-	crystalhd_hw_delete_ioq(hw->adp, hw->tx_actq);
-	crystalhd_hw_delete_ioq(hw->adp, hw->tx_freeq);
-	crystalhd_hw_delete_ioq(hw->adp, hw->rx_actq);
-	crystalhd_hw_delete_ioq(hw->adp, hw->rx_freeq);
-	crystalhd_hw_delete_ioq(hw->adp, hw->rx_rdyq);
-}
-
-#define crystalhd_hw_create_ioq(sts, hw, q, cb)			\
-do {								\
-	sts = crystalhd_create_dioq(hw->adp, &q, cb, hw);	\
-	if (sts != BC_STS_SUCCESS)				\
-		goto hw_create_ioq_err;				\
-} while (0)
-
-/*
- * Create IOQs..
- *
- * TX - Active & Free
- * RX - Active, Ready and Free.
- */
-static enum BC_STATUS crystalhd_hw_create_ioqs(struct crystalhd_hw   *hw)
-{
-	enum BC_STATUS   sts = BC_STS_SUCCESS;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_hw_create_ioq(sts, hw, hw->tx_freeq,
-			      crystalhd_tx_desc_rel_call_back);
-	crystalhd_hw_create_ioq(sts, hw, hw->tx_actq,
-			      crystalhd_tx_desc_rel_call_back);
-
-	crystalhd_hw_create_ioq(sts, hw, hw->rx_freeq,
-			      crystalhd_rx_pkt_rel_call_back);
-	crystalhd_hw_create_ioq(sts, hw, hw->rx_rdyq,
-			      crystalhd_rx_pkt_rel_call_back);
-	crystalhd_hw_create_ioq(sts, hw, hw->rx_actq,
-			      crystalhd_rx_pkt_rel_call_back);
-
-	return sts;
-
-hw_create_ioq_err:
-	crystalhd_hw_delete_ioqs(hw);
-
-	return sts;
-}
-
-
-static bool crystalhd_code_in_full(struct crystalhd_adp *adp,
-		 uint32_t needed_sz, bool b_188_byte_pkts,  uint8_t flags)
-{
-	uint32_t base, end, writep, readp;
-	uint32_t cpbSize, cpbFullness, fifoSize;
-
-	if (flags & 0x02) { /* ASF Bit is set */
-		base   = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Base);
-		end    = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2End);
-		writep = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Wrptr);
-		readp  = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Rdptr);
-	} else if (b_188_byte_pkts) { /*Encrypted 188 byte packets*/
-		base   = bc_dec_reg_rd(adp, REG_Dec_TsUser0Base);
-		end    = bc_dec_reg_rd(adp, REG_Dec_TsUser0End);
-		writep = bc_dec_reg_rd(adp, REG_Dec_TsUser0Wrptr);
-		readp  = bc_dec_reg_rd(adp, REG_Dec_TsUser0Rdptr);
-	} else {
-		base   = bc_dec_reg_rd(adp, REG_DecCA_RegCinBase);
-		end    = bc_dec_reg_rd(adp, REG_DecCA_RegCinEnd);
-		writep = bc_dec_reg_rd(adp, REG_DecCA_RegCinWrPtr);
-		readp  = bc_dec_reg_rd(adp, REG_DecCA_RegCinRdPtr);
-	}
-
-	cpbSize = end - base;
-	if (writep >= readp)
-		cpbFullness = writep - readp;
-	else
-		cpbFullness = (end - base) - (readp - writep);
-
-	fifoSize = cpbSize - cpbFullness;
-
-	if (fifoSize < BC_INFIFO_THRESHOLD)
-		return true;
-
-	if (needed_sz > (fifoSize - BC_INFIFO_THRESHOLD))
-		return true;
-
-	return false;
-}
-
-static enum BC_STATUS crystalhd_hw_tx_req_complete(struct crystalhd_hw *hw,
-					 uint32_t list_id, enum BC_STATUS cs)
-{
-	struct tx_dma_pkt *tx_req;
-
-	if (!hw || !list_id) {
-		BCMLOG_ERR("Invalid Arg..\n");
-		return BC_STS_INV_ARG;
-	}
-
-	hw->pwr_lock--;
-
-	tx_req = (struct tx_dma_pkt *)crystalhd_dioq_find_and_fetch(
-					hw->tx_actq, list_id);
-	if (!tx_req) {
-		if (cs != BC_STS_IO_USER_ABORT)
-			BCMLOG_ERR("Find and Fetch Did not find req\n");
-		return BC_STS_NO_DATA;
-	}
-
-	if (tx_req->call_back) {
-		tx_req->call_back(tx_req->dio_req, tx_req->cb_event, cs);
-		tx_req->dio_req   = NULL;
-		tx_req->cb_event  = NULL;
-		tx_req->call_back = NULL;
-	} else {
-		BCMLOG(BCMLOG_DBG, "Missing Tx Callback - %X\n",
-		       tx_req->list_tag);
-	}
-
-	/* Now put back the tx_list back in FreeQ */
-	tx_req->list_tag = 0;
-
-	return crystalhd_dioq_add(hw->tx_freeq, tx_req, false, 0);
-}
-
-static bool crystalhd_tx_list0_handler(struct crystalhd_hw *hw,
-					 uint32_t err_sts)
-{
-	uint32_t err_mask, tmp;
-	unsigned long flags = 0;
-
-	err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK |
-		MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK |
-		MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
-
-	if (!(err_sts & err_mask))
-		return false;
-
-	BCMLOG_ERR("Error on Tx-L0 %x\n", err_sts);
-
-	tmp = err_mask;
-
-	if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK)
-		tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
-
-	if (tmp) {
-		spin_lock_irqsave(&hw->lock, flags);
-		/* reset list index.*/
-		hw->tx_list_post_index = 0;
-		spin_unlock_irqrestore(&hw->lock, flags);
-	}
-
-	tmp = err_sts & err_mask;
-	crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
-
-	return true;
-}
-
-static bool crystalhd_tx_list1_handler(struct crystalhd_hw *hw,
-					 uint32_t err_sts)
-{
-	uint32_t err_mask, tmp;
-	unsigned long flags = 0;
-
-	err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK |
-		MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK |
-		MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
-
-	if (!(err_sts & err_mask))
-		return false;
-
-	BCMLOG_ERR("Error on Tx-L1 %x\n", err_sts);
-
-	tmp = err_mask;
-
-	if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK)
-		tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
-
-	if (tmp) {
-		spin_lock_irqsave(&hw->lock, flags);
-		/* reset list index.*/
-		hw->tx_list_post_index = 0;
-		spin_unlock_irqrestore(&hw->lock, flags);
-	}
-
-	tmp = err_sts & err_mask;
-	crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
-
-	return true;
-}
-
-static void crystalhd_tx_isr(struct crystalhd_hw *hw, uint32_t int_sts)
-{
-	uint32_t err_sts;
-
-	if (int_sts & INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK)
-		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
-					   BC_STS_SUCCESS);
-
-	if (int_sts & INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK)
-		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
-					   BC_STS_SUCCESS);
-
-	if (!(int_sts & (INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK |
-			INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK))) {
-			/* No error mask set.. */
-			return;
-	}
-
-	/* Handle Tx errors. */
-	err_sts = crystalhd_reg_rd(hw->adp, MISC1_TX_DMA_ERROR_STATUS);
-
-	if (crystalhd_tx_list0_handler(hw, err_sts))
-		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
-					   BC_STS_ERROR);
-
-	if (crystalhd_tx_list1_handler(hw, err_sts))
-		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
-					   BC_STS_ERROR);
-
-	hw->stats.tx_errors++;
-}
-
-static void crystalhd_hw_dump_desc(struct dma_descriptor *p_dma_desc,
-				 uint32_t ul_desc_index, uint32_t cnt)
-{
-	uint32_t ix, ll = 0;
-
-	if (!p_dma_desc || !cnt)
-		return;
-
-	/* FIXME: jarod: perhaps a modparam desc_debug to enable this,
-	 rather than setting ll (log level, I presume) to non-zero? */
-	if (!ll)
-		return;
-
-	for (ix = ul_desc_index; ix < (ul_desc_index + cnt); ix++) {
-		BCMLOG(ll,
-		 "%s[%d] Buff[%x:%x] Next:[%x:%x] XferSz:%x Intr:%x,Last:%x\n",
-		 ((p_dma_desc[ul_desc_index].dma_dir) ? "TDesc" : "RDesc"),
-		       ul_desc_index,
-		       p_dma_desc[ul_desc_index].buff_addr_high,
-		       p_dma_desc[ul_desc_index].buff_addr_low,
-		       p_dma_desc[ul_desc_index].next_desc_addr_high,
-		       p_dma_desc[ul_desc_index].next_desc_addr_low,
-		       p_dma_desc[ul_desc_index].xfer_size,
-		       p_dma_desc[ul_desc_index].intr_enable,
-		       p_dma_desc[ul_desc_index].last_rec_indicator);
-	}
-
-}
-
-static enum BC_STATUS crystalhd_hw_fill_desc(struct crystalhd_dio_req *ioreq,
-				      struct dma_descriptor *desc,
-				      dma_addr_t desc_paddr_base,
-				      uint32_t sg_cnt, uint32_t sg_st_ix,
-				      uint32_t sg_st_off, uint32_t xfr_sz)
-{
-	uint32_t count = 0, ix = 0, sg_ix = 0, len = 0, last_desc_ix = 0;
-	dma_addr_t desc_phy_addr = desc_paddr_base;
-	union addr_64 addr_temp;
-
-	if (!ioreq || !desc || !desc_paddr_base || !xfr_sz ||
-	    (!sg_cnt && !ioreq->uinfo.dir_tx)) {
-		BCMLOG_ERR("Invalid Args\n");
-		return BC_STS_INV_ARG;
-	}
-
-	for (ix = 0; ix < sg_cnt; ix++) {
-
-		/* Setup SGLE index. */
-		sg_ix = ix + sg_st_ix;
-
-		/* Get SGLE length */
-		len = crystalhd_get_sgle_len(ioreq, sg_ix);
-		if (len % 4) {
-			BCMLOG_ERR(" len in sg %d %d %d\n", len, sg_ix,
-				 sg_cnt);
-			return BC_STS_NOT_IMPL;
-		}
-		/* Setup DMA desc with Phy addr & Length at current index. */
-		addr_temp.full_addr = crystalhd_get_sgle_paddr(ioreq, sg_ix);
-		if (sg_ix == sg_st_ix) {
-			addr_temp.full_addr += sg_st_off;
-			len -= sg_st_off;
-		}
-		memset(&desc[ix], 0, sizeof(desc[ix]));
-		desc[ix].buff_addr_low  = addr_temp.low_part;
-		desc[ix].buff_addr_high = addr_temp.high_part;
-		desc[ix].dma_dir        = ioreq->uinfo.dir_tx;
-
-		/* Chain DMA descriptor.  */
-		addr_temp.full_addr = desc_phy_addr +
-					 sizeof(struct dma_descriptor);
-		desc[ix].next_desc_addr_low = addr_temp.low_part;
-		desc[ix].next_desc_addr_high = addr_temp.high_part;
-
-		if ((count + len) > xfr_sz)
-			len = xfr_sz - count;
-
-		/* Debug.. */
-		if ((!len) || (len > crystalhd_get_sgle_len(ioreq, sg_ix))) {
-			BCMLOG_ERR(
-			 "inv-len(%x) Ix(%d) count:%x xfr_sz:%x sg_cnt:%d\n",
-			 len, ix, count, xfr_sz, sg_cnt);
-			return BC_STS_ERROR;
-		}
-		/* Length expects Multiple of 4 */
-		desc[ix].xfer_size = (len / 4);
-
-		crystalhd_hw_dump_desc(desc, ix, 1);
-
-		count += len;
-		desc_phy_addr += sizeof(struct dma_descriptor);
-	}
-
-	last_desc_ix = ix - 1;
-
-	if (ioreq->fb_size) {
-		memset(&desc[ix], 0, sizeof(desc[ix]));
-		addr_temp.full_addr     = ioreq->fb_pa;
-		desc[ix].buff_addr_low  = addr_temp.low_part;
-		desc[ix].buff_addr_high = addr_temp.high_part;
-		desc[ix].dma_dir        = ioreq->uinfo.dir_tx;
-		desc[ix].xfer_size	= 1;
-		desc[ix].fill_bytes	= 4 - ioreq->fb_size;
-		count += ioreq->fb_size;
-		last_desc_ix++;
-	}
-
-	/* setup last descriptor..*/
-	desc[last_desc_ix].last_rec_indicator  = 1;
-	desc[last_desc_ix].next_desc_addr_low  = 0;
-	desc[last_desc_ix].next_desc_addr_high = 0;
-	desc[last_desc_ix].intr_enable = 1;
-
-	crystalhd_hw_dump_desc(desc, last_desc_ix, 1);
-
-	if (count != xfr_sz) {
-		BCMLOG_ERR("internal error sz curr:%x exp:%x\n", count, xfr_sz);
-		return BC_STS_ERROR;
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS crystalhd_xlat_sgl_to_dma_desc(
-					      struct crystalhd_dio_req *ioreq,
-					      struct dma_desc_mem *pdesc_mem,
-					      uint32_t *uv_desc_index)
-{
-	struct dma_descriptor *desc = NULL;
-	dma_addr_t desc_paddr_base = 0;
-	uint32_t sg_cnt = 0, sg_st_ix = 0, sg_st_off = 0;
-	uint32_t xfr_sz = 0;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	/* Check params.. */
-	if (!ioreq || !pdesc_mem || !uv_desc_index) {
-		BCMLOG_ERR("Invalid Args\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (!pdesc_mem->sz || !pdesc_mem->pdma_desc_start ||
-	    !ioreq->sg || (!ioreq->sg_cnt && !ioreq->uinfo.dir_tx)) {
-		BCMLOG_ERR("Invalid Args\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if ((ioreq->uinfo.dir_tx) && (ioreq->uinfo.uv_offset)) {
-		BCMLOG_ERR("UV offset for TX??\n");
-		return BC_STS_INV_ARG;
-
-	}
-
-	desc = pdesc_mem->pdma_desc_start;
-	desc_paddr_base = pdesc_mem->phy_addr;
-
-	if (ioreq->uinfo.dir_tx || (ioreq->uinfo.uv_offset == 0)) {
-		sg_cnt = ioreq->sg_cnt;
-		xfr_sz = ioreq->uinfo.xfr_len;
-	} else {
-		sg_cnt = ioreq->uinfo.uv_sg_ix + 1;
-		xfr_sz = ioreq->uinfo.uv_offset;
-	}
-
-	sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
-				   sg_st_ix, sg_st_off, xfr_sz);
-
-	if ((sts != BC_STS_SUCCESS) || !ioreq->uinfo.uv_offset)
-		return sts;
-
-	/* Prepare for UV mapping.. */
-	desc = &pdesc_mem->pdma_desc_start[sg_cnt];
-	desc_paddr_base = pdesc_mem->phy_addr +
-			  (sg_cnt * sizeof(struct dma_descriptor));
-
-	/* Done with desc addr.. now update sg stuff.*/
-	sg_cnt    = ioreq->sg_cnt - ioreq->uinfo.uv_sg_ix;
-	xfr_sz    = ioreq->uinfo.xfr_len - ioreq->uinfo.uv_offset;
-	sg_st_ix  = ioreq->uinfo.uv_sg_ix;
-	sg_st_off = ioreq->uinfo.uv_sg_off;
-
-	sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
-				   sg_st_ix, sg_st_off, xfr_sz);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	*uv_desc_index = sg_st_ix;
-
-	return sts;
-}
-
-static void crystalhd_start_tx_dma_engine(struct crystalhd_hw *hw)
-{
-	uint32_t dma_cntrl;
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
-	if (!(dma_cntrl & DMA_START_BIT)) {
-		dma_cntrl |= DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS,
-			       dma_cntrl);
-	}
-
-	return;
-}
-
-/* _CHECK_THIS_
- *
- * Verify if the Stop generates a completion interrupt or not.
- * if it does not generate an interrupt, then add polling here.
- */
-static enum BC_STATUS crystalhd_stop_tx_dma_engine(struct crystalhd_hw *hw)
-{
-	uint32_t dma_cntrl, cnt = 30;
-	uint32_t l1 = 1, l2 = 1;
-	unsigned long flags = 0;
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
-
-	BCMLOG(BCMLOG_DBG, "Stopping TX DMA Engine..\n");
-
-	if (!(dma_cntrl & DMA_START_BIT)) {
-		BCMLOG(BCMLOG_DBG, "Already Stopped\n");
-		return BC_STS_SUCCESS;
-	}
-
-	crystalhd_disable_interrupts(hw->adp);
-
-	/* Issue stop to HW */
-	/* This bit when set gave problems. Please check*/
-	dma_cntrl &= ~DMA_START_BIT;
-	crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-
-	BCMLOG(BCMLOG_DBG, "Cleared the DMA Start bit\n");
-
-	/* Poll for 3seconds (30 * 100ms) on both the lists..*/
-	while ((l1 || l2) && cnt) {
-
-		if (l1) {
-			l1 = crystalhd_reg_rd(hw->adp,
-				 MISC1_TX_FIRST_DESC_L_ADDR_LIST0);
-			l1 &= DMA_START_BIT;
-		}
-
-		if (l2) {
-			l2 = crystalhd_reg_rd(hw->adp,
-				 MISC1_TX_FIRST_DESC_L_ADDR_LIST1);
-			l2 &= DMA_START_BIT;
-		}
-
-		msleep_interruptible(100);
-
-		cnt--;
-	}
-
-	if (!cnt) {
-		BCMLOG_ERR("Failed to stop TX DMA.. l1 %d, l2 %d\n", l1, l2);
-		crystalhd_enable_interrupts(hw->adp);
-		return BC_STS_ERROR;
-	}
-
-	spin_lock_irqsave(&hw->lock, flags);
-	hw->tx_list_post_index = 0;
-	spin_unlock_irqrestore(&hw->lock, flags);
-	BCMLOG(BCMLOG_DBG, "stopped TX DMA..\n");
-	crystalhd_enable_interrupts(hw->adp);
-
-	return BC_STS_SUCCESS;
-}
-
-static uint32_t crystalhd_get_pib_avail_cnt(struct crystalhd_hw *hw)
-{
-	/*
-	* Position of the PIB Entries can be found at
-	* 0th and the 1st location of the Circular list.
-	*/
-	uint32_t Q_addr;
-	uint32_t pib_cnt, r_offset, w_offset;
-
-	Q_addr = hw->pib_del_Q_addr;
-
-	/* Get the Read Pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
-
-	/* Get the Write Pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
-
-	if (r_offset == w_offset)
-		return 0;	/* Queue is empty */
-
-	if (w_offset > r_offset)
-		pib_cnt = w_offset - r_offset;
-	else
-		pib_cnt = (w_offset + MAX_PIB_Q_DEPTH) -
-			  (r_offset + MIN_PIB_Q_DEPTH);
-
-	if (pib_cnt > MAX_PIB_Q_DEPTH) {
-		BCMLOG_ERR("Invalid PIB Count (%u)\n", pib_cnt);
-		return 0;
-	}
-
-	return pib_cnt;
-}
-
-static uint32_t crystalhd_get_addr_from_pib_Q(struct crystalhd_hw *hw)
-{
-	uint32_t Q_addr;
-	uint32_t addr_entry, r_offset, w_offset;
-
-	Q_addr = hw->pib_del_Q_addr;
-
-	/* Get the Read Pointer 0Th Location is Read Pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
-
-	/* Get the Write Pointer 1st Location is Write pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
-
-	/* Queue is empty */
-	if (r_offset == w_offset)
-		return 0;
-
-	if ((r_offset < MIN_PIB_Q_DEPTH) || (r_offset >= MAX_PIB_Q_DEPTH))
-		return 0;
-
-	/* Get the Actual Address of the PIB */
-	crystalhd_mem_rd(hw->adp, Q_addr + (r_offset * sizeof(uint32_t)),
-		       1, &addr_entry);
-
-	/* Increment the Read Pointer */
-	r_offset++;
-
-	if (MAX_PIB_Q_DEPTH == r_offset)
-		r_offset = MIN_PIB_Q_DEPTH;
-
-	/* Write back the read pointer to It's Location */
-	crystalhd_mem_wr(hw->adp, Q_addr, 1, &r_offset);
-
-	return addr_entry;
-}
-
-static bool crystalhd_rel_addr_to_pib_Q(struct crystalhd_hw *hw,
-					 uint32_t addr_to_rel)
-{
-	uint32_t Q_addr;
-	uint32_t r_offset, w_offset, n_offset;
-
-	Q_addr = hw->pib_rel_Q_addr;
-
-	/* Get the Read Pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
-
-	/* Get the Write Pointer */
-	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
-
-	if ((r_offset < MIN_PIB_Q_DEPTH) ||
-	    (r_offset >= MAX_PIB_Q_DEPTH))
-		return false;
-
-	n_offset = w_offset + 1;
-
-	if (MAX_PIB_Q_DEPTH == n_offset)
-		n_offset = MIN_PIB_Q_DEPTH;
-
-	if (r_offset == n_offset)
-		return false; /* should never happen */
-
-	/* Write the DRAM ADDR to the Queue at Next Offset */
-	crystalhd_mem_wr(hw->adp, Q_addr + (w_offset * sizeof(uint32_t)),
-		       1, &addr_to_rel);
-
-	/* Put the New value of the write pointer in Queue */
-	crystalhd_mem_wr(hw->adp, Q_addr + sizeof(uint32_t), 1, &n_offset);
-
-	return true;
-}
-
-static void cpy_pib_to_app(struct c011_pib *src_pib,
-					 struct BC_PIC_INFO_BLOCK *dst_pib)
-{
-	if (!src_pib || !dst_pib) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return;
-	}
-
-	dst_pib->timeStamp           = 0;
-	dst_pib->picture_number      = src_pib->ppb.picture_number;
-	dst_pib->width               = src_pib->ppb.width;
-	dst_pib->height              = src_pib->ppb.height;
-	dst_pib->chroma_format       = src_pib->ppb.chroma_format;
-	dst_pib->pulldown            = src_pib->ppb.pulldown;
-	dst_pib->flags               = src_pib->ppb.flags;
-	dst_pib->sess_num            = src_pib->ptsStcOffset;
-	dst_pib->aspect_ratio        = src_pib->ppb.aspect_ratio;
-	dst_pib->colour_primaries     = src_pib->ppb.colour_primaries;
-	dst_pib->picture_meta_payload = src_pib->ppb.picture_meta_payload;
-	dst_pib->frame_rate		= src_pib->resolution;
-	return;
-}
-
-static void crystalhd_hw_proc_pib(struct crystalhd_hw *hw)
-{
-	unsigned int cnt;
-	struct c011_pib src_pib;
-	uint32_t pib_addr, pib_cnt;
-	struct BC_PIC_INFO_BLOCK *AppPib;
-	struct crystalhd_rx_dma_pkt *rx_pkt = NULL;
-
-	pib_cnt = crystalhd_get_pib_avail_cnt(hw);
-
-	if (!pib_cnt)
-		return;
-
-	for (cnt = 0; cnt < pib_cnt; cnt++) {
-
-		pib_addr = crystalhd_get_addr_from_pib_Q(hw);
-		crystalhd_mem_rd(hw->adp, pib_addr, sizeof(struct c011_pib) / 4,
-			       (uint32_t *)&src_pib);
-
-		if (src_pib.bFormatChange) {
-			rx_pkt = (struct crystalhd_rx_dma_pkt *)
-					crystalhd_dioq_fetch(hw->rx_freeq);
-			if (!rx_pkt)
-				return;
-			rx_pkt->flags = 0;
-			rx_pkt->flags |= COMP_FLAG_PIB_VALID |
-					 COMP_FLAG_FMT_CHANGE;
-			AppPib = &rx_pkt->pib;
-			cpy_pib_to_app(&src_pib, AppPib);
-
-			BCMLOG(BCMLOG_DBG,
-			       "App PIB:%x %x %x %x %x %x %x %x %x %x\n",
-			       rx_pkt->pib.picture_number,
-			       rx_pkt->pib.aspect_ratio,
-			       rx_pkt->pib.chroma_format,
-			       rx_pkt->pib.colour_primaries,
-			       rx_pkt->pib.frame_rate,
-			       rx_pkt->pib.height,
-			       rx_pkt->pib.height,
-			       rx_pkt->pib.n_drop,
-			       rx_pkt->pib.pulldown,
-			       rx_pkt->pib.ycom);
-
-			crystalhd_dioq_add(hw->rx_rdyq, (void *)rx_pkt, true,
-					 rx_pkt->pkt_tag);
-
-		}
-
-		crystalhd_rel_addr_to_pib_Q(hw, pib_addr);
-	}
-}
-
-static void crystalhd_start_rx_dma_engine(struct crystalhd_hw *hw)
-{
-	uint32_t        dma_cntrl;
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
-	if (!(dma_cntrl & DMA_START_BIT)) {
-		dma_cntrl |= DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
-	if (!(dma_cntrl & DMA_START_BIT)) {
-		dma_cntrl |= DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-
-	return;
-}
-
-static void crystalhd_stop_rx_dma_engine(struct crystalhd_hw *hw)
-{
-	uint32_t dma_cntrl = 0, count = 30;
-	uint32_t l0y = 1, l0uv = 1, l1y = 1, l1uv = 1;
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
-	if ((dma_cntrl & DMA_START_BIT)) {
-		dma_cntrl &= ~DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
-	if ((dma_cntrl & DMA_START_BIT)) {
-		dma_cntrl &= ~DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-
-	/* Poll for 3seconds (30 * 100ms) on both the lists..*/
-	while ((l0y || l0uv || l1y || l1uv) && count) {
-
-		if (l0y) {
-			l0y = crystalhd_reg_rd(hw->adp,
-				 MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0);
-			l0y &= DMA_START_BIT;
-			if (!l0y)
-				hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
-		}
-
-		if (l1y) {
-			l1y = crystalhd_reg_rd(hw->adp,
-				 MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1);
-			l1y &= DMA_START_BIT;
-			if (!l1y)
-				hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
-		}
-
-		if (l0uv) {
-			l0uv = crystalhd_reg_rd(hw->adp,
-				 MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0);
-			l0uv &= DMA_START_BIT;
-			if (!l0uv)
-				hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
-		}
-
-		if (l1uv) {
-			l1uv = crystalhd_reg_rd(hw->adp,
-				 MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1);
-			l1uv &= DMA_START_BIT;
-			if (!l1uv)
-				hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
-		}
-		msleep_interruptible(100);
-		count--;
-	}
-
-	hw->rx_list_post_index = 0;
-
-	BCMLOG(BCMLOG_SSTEP, "Capture Stop: %d List0:Sts:%x List1:Sts:%x\n",
-	       count, hw->rx_list_sts[0], hw->rx_list_sts[1]);
-}
-
-static enum BC_STATUS crystalhd_hw_prog_rxdma(struct crystalhd_hw *hw,
-					 struct crystalhd_rx_dma_pkt *rx_pkt)
-{
-	uint32_t y_low_addr_reg, y_high_addr_reg;
-	uint32_t uv_low_addr_reg, uv_high_addr_reg;
-	union addr_64 desc_addr;
-	unsigned long flags;
-
-	if (!hw || !rx_pkt) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (hw->rx_list_post_index >= DMA_ENGINE_CNT) {
-		BCMLOG_ERR("List Out Of bounds %x\n", hw->rx_list_post_index);
-		return BC_STS_INV_ARG;
-	}
-
-	spin_lock_irqsave(&hw->rx_lock, flags);
-	/* FIXME: jarod: sts_free is an enum for 0,
-	 in crystalhd_hw.h... yuk... */
-	if (sts_free != hw->rx_list_sts[hw->rx_list_post_index]) {
-		spin_unlock_irqrestore(&hw->rx_lock, flags);
-		return BC_STS_BUSY;
-	}
-
-	if (!hw->rx_list_post_index) {
-		y_low_addr_reg   = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0;
-		y_high_addr_reg  = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0;
-		uv_low_addr_reg  = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0;
-		uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0;
-	} else {
-		y_low_addr_reg   = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1;
-		y_high_addr_reg  = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1;
-		uv_low_addr_reg  = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1;
-		uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1;
-	}
-	rx_pkt->pkt_tag = hw->rx_pkt_tag_seed + hw->rx_list_post_index;
-	hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_y_intr;
-	if (rx_pkt->uv_phy_addr)
-		hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_uv_intr;
-	hw->rx_list_post_index = (hw->rx_list_post_index + 1) % DMA_ENGINE_CNT;
-	spin_unlock_irqrestore(&hw->rx_lock, flags);
-
-	crystalhd_dioq_add(hw->rx_actq, (void *)rx_pkt, false,
-			 rx_pkt->pkt_tag);
-
-	crystalhd_start_rx_dma_engine(hw);
-	/* Program the Y descriptor */
-	desc_addr.full_addr = rx_pkt->desc_mem.phy_addr;
-	crystalhd_reg_wr(hw->adp, y_high_addr_reg, desc_addr.high_part);
-	crystalhd_reg_wr(hw->adp, y_low_addr_reg, desc_addr.low_part | 0x01);
-
-	if (rx_pkt->uv_phy_addr) {
-		/* Program the UV descriptor */
-		desc_addr.full_addr = rx_pkt->uv_phy_addr;
-		crystalhd_reg_wr(hw->adp, uv_high_addr_reg,
-			 desc_addr.high_part);
-		crystalhd_reg_wr(hw->adp, uv_low_addr_reg,
-			 desc_addr.low_part | 0x01);
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-static enum BC_STATUS crystalhd_hw_post_cap_buff(struct crystalhd_hw *hw,
-					  struct crystalhd_rx_dma_pkt *rx_pkt)
-{
-	enum BC_STATUS sts = crystalhd_hw_prog_rxdma(hw, rx_pkt);
-
-	if (sts == BC_STS_BUSY)
-		crystalhd_dioq_add(hw->rx_freeq, (void *)rx_pkt,
-				 false, rx_pkt->pkt_tag);
-
-	return sts;
-}
-
-static void crystalhd_get_dnsz(struct crystalhd_hw *hw, uint32_t list_index,
-			     uint32_t *y_dw_dnsz, uint32_t *uv_dw_dnsz)
-{
-	uint32_t y_dn_sz_reg, uv_dn_sz_reg;
-
-	if (!list_index) {
-		y_dn_sz_reg  = MISC1_Y_RX_LIST0_CUR_BYTE_CNT;
-		uv_dn_sz_reg = MISC1_UV_RX_LIST0_CUR_BYTE_CNT;
-	} else {
-		y_dn_sz_reg  = MISC1_Y_RX_LIST1_CUR_BYTE_CNT;
-		uv_dn_sz_reg = MISC1_UV_RX_LIST1_CUR_BYTE_CNT;
-	}
-
-	*y_dw_dnsz  = crystalhd_reg_rd(hw->adp, y_dn_sz_reg);
-	*uv_dw_dnsz = crystalhd_reg_rd(hw->adp, uv_dn_sz_reg);
-}
-
-/*
- * This function should be called only after making sure that the two DMA
- * lists are free. This function does not check if DMA's are active, before
- * turning off the DMA.
- */
-static void crystalhd_hw_finalize_pause(struct crystalhd_hw *hw)
-{
-	uint32_t dma_cntrl, aspm;
-
-	hw->stop_pending = 0;
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
-	if (dma_cntrl & DMA_START_BIT) {
-		dma_cntrl &= ~DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-
-	dma_cntrl = crystalhd_reg_rd(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
-	if (dma_cntrl & DMA_START_BIT) {
-		dma_cntrl &= ~DMA_START_BIT;
-		crystalhd_reg_wr(hw->adp,
-			 MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
-	}
-	hw->rx_list_post_index = 0;
-
-	aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
-	aspm |= ASPM_L1_ENABLE;
-	/* NAREN BCMLOG(BCMLOG_INFO, "aspm on\n"); */
-	crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
-}
-
-static enum BC_STATUS crystalhd_rx_pkt_done(struct crystalhd_hw *hw,
-			 uint32_t list_index, enum BC_STATUS comp_sts)
-{
-	struct crystalhd_rx_dma_pkt *rx_pkt = NULL;
-	uint32_t y_dw_dnsz, uv_dw_dnsz;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	if (!hw || list_index >= DMA_ENGINE_CNT) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	rx_pkt = crystalhd_dioq_find_and_fetch(hw->rx_actq,
-					     hw->rx_pkt_tag_seed + list_index);
-	if (!rx_pkt) {
-		BCMLOG_ERR(
-		"Act-Q:PostIx:%x L0Sts:%x L1Sts:%x current L:%x tag:%x comp:%x\n",
-			   hw->rx_list_post_index, hw->rx_list_sts[0],
-			   hw->rx_list_sts[1], list_index,
-			   hw->rx_pkt_tag_seed + list_index, comp_sts);
-		return BC_STS_INV_ARG;
-	}
-
-	if (comp_sts == BC_STS_SUCCESS) {
-		crystalhd_get_dnsz(hw, list_index, &y_dw_dnsz, &uv_dw_dnsz);
-		rx_pkt->dio_req->uinfo.y_done_sz = y_dw_dnsz;
-		rx_pkt->flags = COMP_FLAG_DATA_VALID;
-		if (rx_pkt->uv_phy_addr)
-			rx_pkt->dio_req->uinfo.uv_done_sz = uv_dw_dnsz;
-		crystalhd_dioq_add(hw->rx_rdyq, rx_pkt, true,
-				hw->rx_pkt_tag_seed + list_index);
-		return sts;
-	}
-
-	/* Check if we can post this DIO again. */
-	return crystalhd_hw_post_cap_buff(hw, rx_pkt);
-}
-
-static bool crystalhd_rx_list0_handler(struct crystalhd_hw *hw,
-		 uint32_t int_sts, uint32_t y_err_sts, uint32_t uv_err_sts)
-{
-	uint32_t tmp;
-	enum list_sts tmp_lsts;
-
-	if (!(y_err_sts & GET_Y0_ERR_MSK) && !(uv_err_sts & GET_UV0_ERR_MSK))
-		return false;
-
-	tmp_lsts = hw->rx_list_sts[0];
-
-	/* Y0 - DMA */
-	tmp = y_err_sts & GET_Y0_ERR_MSK;
-	if (int_sts & INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
-		hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
-
-	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
-		hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
-		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
-	}
-
-	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
-		hw->rx_list_sts[0] &= ~rx_y_mask;
-		hw->rx_list_sts[0] |= rx_y_error;
-		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
-	}
-
-	if (tmp) {
-		hw->rx_list_sts[0] &= ~rx_y_mask;
-		hw->rx_list_sts[0] |= rx_y_error;
-		hw->rx_list_post_index = 0;
-	}
-
-	/* UV0 - DMA */
-	tmp = uv_err_sts & GET_UV0_ERR_MSK;
-	if (int_sts & INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK)
-		hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
-
-	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
-		hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
-		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
-	}
-
-	if (uv_err_sts &
-	 MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
-		hw->rx_list_sts[0] &= ~rx_uv_mask;
-		hw->rx_list_sts[0] |= rx_uv_error;
-		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
-	}
-
-	if (tmp) {
-		hw->rx_list_sts[0] &= ~rx_uv_mask;
-		hw->rx_list_sts[0] |= rx_uv_error;
-		hw->rx_list_post_index = 0;
-	}
-
-	if (y_err_sts & GET_Y0_ERR_MSK) {
-		tmp = y_err_sts & GET_Y0_ERR_MSK;
-		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
-	}
-
-	if (uv_err_sts & GET_UV0_ERR_MSK) {
-		tmp = uv_err_sts & GET_UV0_ERR_MSK;
-		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
-	}
-
-	return tmp_lsts != hw->rx_list_sts[0];
-}
-
-static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw,
-		 uint32_t int_sts, uint32_t y_err_sts, uint32_t uv_err_sts)
-{
-	uint32_t tmp;
-	enum list_sts tmp_lsts;
-
-	if (!(y_err_sts & GET_Y1_ERR_MSK) && !(uv_err_sts & GET_UV1_ERR_MSK))
-		return false;
-
-	tmp_lsts = hw->rx_list_sts[1];
-
-	/* Y1 - DMA */
-	tmp = y_err_sts & GET_Y1_ERR_MSK;
-	if (int_sts & INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK)
-		hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
-
-	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
-		hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
-		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
-	}
-
-	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
-		/* Add retry-support..*/
-		hw->rx_list_sts[1] &= ~rx_y_mask;
-		hw->rx_list_sts[1] |= rx_y_error;
-		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
-	}
-
-	if (tmp) {
-		hw->rx_list_sts[1] &= ~rx_y_mask;
-		hw->rx_list_sts[1] |= rx_y_error;
-		hw->rx_list_post_index = 0;
-	}
-
-	/* UV1 - DMA */
-	tmp = uv_err_sts & GET_UV1_ERR_MSK;
-	if (int_sts & INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK)
-		hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
-
-	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
-		hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
-		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
-	}
-
-	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
-		/* Add retry-support*/
-		hw->rx_list_sts[1] &= ~rx_uv_mask;
-		hw->rx_list_sts[1] |= rx_uv_error;
-		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
-	}
-
-	if (tmp) {
-		hw->rx_list_sts[1] &= ~rx_uv_mask;
-		hw->rx_list_sts[1] |= rx_uv_error;
-		hw->rx_list_post_index = 0;
-	}
-
-	if (y_err_sts & GET_Y1_ERR_MSK) {
-		tmp = y_err_sts & GET_Y1_ERR_MSK;
-		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
-	}
-
-	if (uv_err_sts & GET_UV1_ERR_MSK) {
-		tmp = uv_err_sts & GET_UV1_ERR_MSK;
-		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
-	}
-
-	return tmp_lsts != hw->rx_list_sts[1];
-}
-
-
-static void crystalhd_rx_isr(struct crystalhd_hw *hw, uint32_t intr_sts)
-{
-	unsigned long flags;
-	uint32_t i, list_avail = 0;
-	enum BC_STATUS comp_sts = BC_STS_NO_DATA;
-	uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
-	bool ret = false;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return;
-	}
-
-	if (!(intr_sts & GET_RX_INTR_MASK))
-		return;
-
-	y_err_sts = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_ERROR_STATUS);
-	uv_err_sts = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_ERROR_STATUS);
-
-	for (i = 0; i < DMA_ENGINE_CNT; i++) {
-		/* Update States..*/
-		spin_lock_irqsave(&hw->rx_lock, flags);
-		if (i == 0)
-			ret = crystalhd_rx_list0_handler(hw, intr_sts,
-					 y_err_sts, uv_err_sts);
-		else
-			ret = crystalhd_rx_list1_handler(hw, intr_sts,
-					 y_err_sts, uv_err_sts);
-		if (ret) {
-			switch (hw->rx_list_sts[i]) {
-			case sts_free:
-				comp_sts = BC_STS_SUCCESS;
-				list_avail = 1;
-				break;
-			case rx_y_error:
-			case rx_uv_error:
-			case rx_sts_error:
-				/* We got error on both or Y or uv. */
-				hw->stats.rx_errors++;
-				crystalhd_get_dnsz(hw, i, &y_dn_sz, &uv_dn_sz);
-				/* FIXME: jarod: this is where
-				 my mini pci-e card is tripping up */
-				BCMLOG(BCMLOG_DBG, "list_index:%x rx[%d] Y:%x UV:%x Int:%x YDnSz:%x UVDnSz:%x\n",
-				       i, hw->stats.rx_errors, y_err_sts,
-				       uv_err_sts, intr_sts, y_dn_sz,
-				       uv_dn_sz);
-				hw->rx_list_sts[i] = sts_free;
-				comp_sts = BC_STS_ERROR;
-				break;
-			default:
-				/* Wait for completion..*/
-				comp_sts = BC_STS_NO_DATA;
-				break;
-			}
-		}
-		spin_unlock_irqrestore(&hw->rx_lock, flags);
-
-		/* handle completion...*/
-		if (comp_sts != BC_STS_NO_DATA) {
-			crystalhd_rx_pkt_done(hw, i, comp_sts);
-			comp_sts = BC_STS_NO_DATA;
-		}
-	}
-
-	if (list_avail) {
-		if (hw->stop_pending) {
-			if ((hw->rx_list_sts[0] == sts_free) &&
-			    (hw->rx_list_sts[1] == sts_free))
-				crystalhd_hw_finalize_pause(hw);
-		} else {
-			crystalhd_hw_start_capture(hw);
-		}
-	}
-}
-
-static enum BC_STATUS crystalhd_fw_cmd_post_proc(struct crystalhd_hw *hw,
-					  struct BC_FW_CMD *fw_cmd)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	struct dec_rsp_channel_start_video *st_rsp = NULL;
-
-	switch (fw_cmd->cmd[0]) {
-	case eCMD_C011_DEC_CHAN_START_VIDEO:
-		st_rsp = (struct dec_rsp_channel_start_video *)fw_cmd->rsp;
-		hw->pib_del_Q_addr = st_rsp->picInfoDeliveryQ;
-		hw->pib_rel_Q_addr = st_rsp->picInfoReleaseQ;
-		BCMLOG(BCMLOG_DBG, "DelQAddr:%x RelQAddr:%x\n",
-		       hw->pib_del_Q_addr, hw->pib_rel_Q_addr);
-		break;
-	case eCMD_C011_INIT:
-		if (!(crystalhd_load_firmware_config(hw->adp))) {
-			BCMLOG_ERR("Invalid Params.\n");
-			sts = BC_STS_FW_AUTH_FAILED;
-		}
-		break;
-	default:
-		break;
-	}
-	return sts;
-}
-
-static enum BC_STATUS crystalhd_put_ddr2sleep(struct crystalhd_hw *hw)
-{
-	uint32_t reg;
-	union link_misc_perst_decoder_ctrl rst_cntrl_reg;
-
-	/* Pulse reset pin of 7412 (MISC_PERST_DECODER_CTRL) */
-	rst_cntrl_reg.whole_reg = crystalhd_reg_rd(hw->adp,
-					 MISC_PERST_DECODER_CTRL);
-
-	rst_cntrl_reg.bcm_7412_rst = 1;
-	crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL,
-					 rst_cntrl_reg.whole_reg);
-	msleep_interruptible(50);
-
-	rst_cntrl_reg.bcm_7412_rst = 0;
-	crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL,
-					 rst_cntrl_reg.whole_reg);
-
-	/* Close all banks, put DDR in idle */
-	bc_dec_reg_wr(hw->adp, SDRAM_PRECHARGE, 0);
-
-	/* Set bit 25 (drop CKE pin of DDR) */
-	reg = bc_dec_reg_rd(hw->adp, SDRAM_PARAM);
-	reg |= 0x02000000;
-	bc_dec_reg_wr(hw->adp, SDRAM_PARAM, reg);
-
-	/* Reset the audio block */
-	bc_dec_reg_wr(hw->adp, AUD_DSP_MISC_SOFT_RESET, 0x1);
-
-	/* Power down Raptor PLL */
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllCCtl);
-	reg |= 0x00008000;
-	bc_dec_reg_wr(hw->adp, DecHt_PllCCtl, reg);
-
-	/* Power down all Audio PLL */
-	bc_dec_reg_wr(hw->adp, AIO_MISC_PLL_RESET, 0x1);
-
-	/* Power down video clock (75MHz) */
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllECtl);
-	reg |= 0x00008000;
-	bc_dec_reg_wr(hw->adp, DecHt_PllECtl, reg);
-
-	/* Power down video clock (75MHz) */
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllDCtl);
-	reg |= 0x00008000;
-	bc_dec_reg_wr(hw->adp, DecHt_PllDCtl, reg);
-
-	/* Power down core clock (200MHz) */
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
-	reg |= 0x00008000;
-	bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
-
-	/* Power down core clock (200MHz) */
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllBCtl);
-	reg |= 0x00008000;
-	bc_dec_reg_wr(hw->adp, DecHt_PllBCtl, reg);
-
-	return BC_STS_SUCCESS;
-}
-
-/************************************************
-**
-*************************************************/
-
-enum BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp, void *buffer,
-					 uint32_t sz)
-{
-	uint32_t reg_data, cnt, *temp_buff;
-	uint32_t fw_sig_len = 36;
-	uint32_t dram_offset = BC_FWIMG_ST_ADDR, sig_reg;
-
-
-	if (!adp || !buffer || !sz) {
-		BCMLOG_ERR("Invalid Params.\n");
-		return BC_STS_INV_ARG;
-	}
-
-	reg_data = crystalhd_reg_rd(adp, OTP_CMD);
-	if (!(reg_data & 0x02)) {
-		BCMLOG_ERR("Invalid hw config.. otp not programmed\n");
-		return BC_STS_ERROR;
-	}
-
-	reg_data = 0;
-	crystalhd_reg_wr(adp, DCI_CMD, 0);
-	reg_data |= BC_BIT(0);
-	crystalhd_reg_wr(adp, DCI_CMD, reg_data);
-
-	reg_data = 0;
-	cnt = 1000;
-	msleep_interruptible(10);
-
-	while (reg_data != BC_BIT(4)) {
-		reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
-		reg_data &= BC_BIT(4);
-		if (--cnt == 0) {
-			BCMLOG_ERR("Firmware Download RDY Timeout.\n");
-			return BC_STS_TIMEOUT;
-		}
-	}
-
-	msleep_interruptible(10);
-	/*  Load the FW to the FW_ADDR field in the DCI_FIRMWARE_ADDR */
-	crystalhd_reg_wr(adp, DCI_FIRMWARE_ADDR, dram_offset);
-	temp_buff = (uint32_t *)buffer;
-	for (cnt = 0; cnt < (sz - fw_sig_len); cnt += 4) {
-		crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (dram_offset >> 19));
-		crystalhd_reg_wr(adp, DCI_FIRMWARE_DATA, *temp_buff);
-		dram_offset += 4;
-		temp_buff++;
-	}
-	msleep_interruptible(10);
-
-	temp_buff++;
-
-	sig_reg = (uint32_t)DCI_SIGNATURE_DATA_7;
-	for (cnt = 0; cnt < 8; cnt++) {
-		uint32_t swapped_data = *temp_buff;
-		swapped_data = bswap_32_1(swapped_data);
-		crystalhd_reg_wr(adp, sig_reg, swapped_data);
-		sig_reg -= 4;
-		temp_buff++;
-	}
-	msleep_interruptible(10);
-
-	reg_data = 0;
-	reg_data |= BC_BIT(1);
-	crystalhd_reg_wr(adp, DCI_CMD, reg_data);
-	msleep_interruptible(10);
-
-	reg_data = 0;
-	reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
-
-	if ((reg_data & BC_BIT(9)) == BC_BIT(9)) {
-		cnt = 1000;
-		while ((reg_data & BC_BIT(0)) != BC_BIT(0)) {
-			reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
-			reg_data &= BC_BIT(0);
-			if (!(--cnt))
-				break;
-			msleep_interruptible(10);
-		}
-		reg_data = 0;
-		reg_data = crystalhd_reg_rd(adp, DCI_CMD);
-		reg_data |= BC_BIT(4);
-		crystalhd_reg_wr(adp, DCI_CMD, reg_data);
-
-	} else {
-		BCMLOG_ERR("F/w Signature mismatch\n");
-		return BC_STS_FW_AUTH_FAILED;
-	}
-
-	BCMLOG(BCMLOG_INFO, "Firmware Downloaded Successfully\n");
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw,
-				struct BC_FW_CMD *fw_cmd)
-{
-	uint32_t cnt = 0, cmd_res_addr;
-	uint32_t *cmd_buff, *res_buff;
-	wait_queue_head_t fw_cmd_event;
-	int rc = 0;
-	enum BC_STATUS sts;
-
-	crystalhd_create_event(&fw_cmd_event);
-
-	if (!hw || !fw_cmd) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	cmd_buff = fw_cmd->cmd;
-	res_buff = fw_cmd->rsp;
-
-	if (!cmd_buff || !res_buff) {
-		BCMLOG_ERR("Invalid Parameters for F/W Command\n");
-		return BC_STS_INV_ARG;
-	}
-
-	hw->pwr_lock++;
-
-	hw->fwcmd_evt_sts = 0;
-	hw->pfw_cmd_event = &fw_cmd_event;
-
-	/*Write the command to the memory*/
-	crystalhd_mem_wr(hw->adp, TS_Host2CpuSnd, FW_CMD_BUFF_SZ, cmd_buff);
-
-	/*Memory Read for memory arbitrator flush*/
-	crystalhd_mem_rd(hw->adp, TS_Host2CpuSnd, 1, &cnt);
-
-	/* Write the command address to mailbox */
-	bc_dec_reg_wr(hw->adp, Hst2CpuMbx1, TS_Host2CpuSnd);
-	msleep_interruptible(50);
-
-	crystalhd_wait_on_event(&fw_cmd_event, hw->fwcmd_evt_sts, 20000, rc, 0);
-
-	if (!rc) {
-		sts = BC_STS_SUCCESS;
-	} else if (rc == -EBUSY) {
-		BCMLOG_ERR("Firmware command T/O\n");
-		sts = BC_STS_TIMEOUT;
-	} else if (rc == -EINTR) {
-		BCMLOG(BCMLOG_DBG, "FwCmd Wait Signal int.\n");
-		sts = BC_STS_IO_USER_ABORT;
-	} else {
-		BCMLOG_ERR("FwCmd IO Error.\n");
-		sts = BC_STS_IO_ERROR;
-	}
-
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("FwCmd Failed.\n");
-		hw->pwr_lock--;
-		return sts;
-	}
-
-	/*Get the Response Address*/
-	cmd_res_addr = bc_dec_reg_rd(hw->adp, Cpu2HstMbx1);
-
-	/*Read the Response*/
-	crystalhd_mem_rd(hw->adp, cmd_res_addr, FW_CMD_BUFF_SZ, res_buff);
-
-	hw->pwr_lock--;
-
-	if (res_buff[2] != C011_RET_SUCCESS) {
-		BCMLOG_ERR("res_buff[2] != C011_RET_SUCCESS\n");
-		return BC_STS_FW_CMD_ERR;
-	}
-
-	sts = crystalhd_fw_cmd_post_proc(hw, fw_cmd);
-	if (sts != BC_STS_SUCCESS)
-		BCMLOG_ERR("crystalhd_fw_cmd_post_proc Failed.\n");
-
-	return sts;
-}
-
-bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
-{
-	uint32_t intr_sts = 0;
-	uint32_t deco_intr = 0;
-	bool rc = false;
-
-	if (!adp || !hw->dev_started)
-		return rc;
-
-	hw->stats.num_interrupts++;
-	hw->pwr_lock++;
-
-	deco_intr = bc_dec_reg_rd(adp, Stream2Host_Intr_Sts);
-	intr_sts  = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
-
-	if (intr_sts) {
-		/* let system know we processed interrupt..*/
-		rc = true;
-		hw->stats.dev_interrupts++;
-	}
-
-	if (deco_intr && (deco_intr != 0xdeaddead)) {
-
-		if (deco_intr & 0x80000000) {
-			/*Set the Event and the status flag*/
-			if (hw->pfw_cmd_event) {
-				hw->fwcmd_evt_sts = 1;
-				crystalhd_set_event(hw->pfw_cmd_event);
-			}
-		}
-
-		if (deco_intr & BC_BIT(1))
-			crystalhd_hw_proc_pib(hw);
-
-		bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, deco_intr);
-		/* FIXME: jarod: No udelay? might this be
-		 the real reason mini pci-e cards were stalling out? */
-		bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
-		rc = true;
-	}
-
-	/* Rx interrupts */
-	crystalhd_rx_isr(hw, intr_sts);
-
-	/* Tx interrupts*/
-	crystalhd_tx_isr(hw, intr_sts);
-
-	/* Clear interrupts */
-	if (rc) {
-		if (intr_sts)
-			crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
-
-		crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
-	}
-
-	hw->pwr_lock--;
-
-	return rc;
-}
-
-enum BC_STATUS crystalhd_hw_open(struct crystalhd_hw *hw,
-			 struct crystalhd_adp *adp)
-{
-	if (!hw || !adp) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (hw->dev_started)
-		return BC_STS_SUCCESS;
-
-	memset(hw, 0, sizeof(struct crystalhd_hw));
-
-	hw->adp = adp;
-	spin_lock_init(&hw->lock);
-	spin_lock_init(&hw->rx_lock);
-	/* FIXME: jarod: what are these magic numbers?!? */
-	hw->tx_ioq_tag_seed = 0x70023070;
-	hw->rx_pkt_tag_seed = 0x70029070;
-
-	hw->stop_pending = 0;
-	crystalhd_start_device(hw->adp);
-	hw->dev_started = true;
-
-	/* set initial core clock  */
-	hw->core_clock_mhz = CLOCK_PRESET;
-	hw->prev_n = 0;
-	hw->pwr_lock = 0;
-	crystalhd_hw_set_core_clock(hw);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_close(struct crystalhd_hw *hw)
-{
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if (!hw->dev_started)
-		return BC_STS_SUCCESS;
-
-	/* Stop and DDR sleep will happen in here */
-	crystalhd_hw_suspend(hw);
-	hw->dev_started = false;
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
-{
-	unsigned int i;
-	void *mem;
-	size_t mem_len;
-	dma_addr_t phy_addr;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	struct crystalhd_rx_dma_pkt *rpkt;
-
-	if (!hw || !hw->adp) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	sts = crystalhd_hw_create_ioqs(hw);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("Failed to create IOQs..\n");
-		return sts;
-	}
-
-	mem_len = BC_LINK_MAX_SGLS * sizeof(struct dma_descriptor);
-
-	for (i = 0; i < BC_TX_LIST_CNT; i++) {
-		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
-		if (mem) {
-			memset(mem, 0, mem_len);
-		} else {
-			BCMLOG_ERR("Insufficient Memory For TX\n");
-			crystalhd_hw_free_dma_rings(hw);
-			return BC_STS_INSUFF_RES;
-		}
-		/* rx_pkt_pool -- static memory allocation  */
-		hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = mem;
-		hw->tx_pkt_pool[i].desc_mem.phy_addr = phy_addr;
-		hw->tx_pkt_pool[i].desc_mem.sz = BC_LINK_MAX_SGLS *
-						 sizeof(struct dma_descriptor);
-		hw->tx_pkt_pool[i].list_tag = 0;
-
-		/* Add TX dma requests to Free Queue..*/
-		sts = crystalhd_dioq_add(hw->tx_freeq,
-				       &hw->tx_pkt_pool[i], false, 0);
-		if (sts != BC_STS_SUCCESS) {
-			crystalhd_hw_free_dma_rings(hw);
-			return sts;
-		}
-	}
-
-	for (i = 0; i < BC_RX_LIST_CNT; i++) {
-		rpkt = kzalloc(sizeof(*rpkt), GFP_KERNEL);
-		if (!rpkt) {
-			BCMLOG_ERR("Insufficient Memory For RX\n");
-			crystalhd_hw_free_dma_rings(hw);
-			return BC_STS_INSUFF_RES;
-		}
-
-		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
-		if (mem) {
-			memset(mem, 0, mem_len);
-		} else {
-			BCMLOG_ERR("Insufficient Memory For RX\n");
-			crystalhd_hw_free_dma_rings(hw);
-			kfree(rpkt);
-			return BC_STS_INSUFF_RES;
-		}
-		rpkt->desc_mem.pdma_desc_start = mem;
-		rpkt->desc_mem.phy_addr = phy_addr;
-		rpkt->desc_mem.sz  = BC_LINK_MAX_SGLS *
-					 sizeof(struct dma_descriptor);
-		rpkt->pkt_tag = hw->rx_pkt_tag_seed + i;
-		crystalhd_hw_free_rx_pkt(hw, rpkt);
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *hw)
-{
-	unsigned int i;
-	struct crystalhd_rx_dma_pkt *rpkt = NULL;
-
-	if (!hw || !hw->adp) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	/* Delete all IOQs.. */
-	crystalhd_hw_delete_ioqs(hw);
-
-	for (i = 0; i < BC_TX_LIST_CNT; i++) {
-		if (hw->tx_pkt_pool[i].desc_mem.pdma_desc_start) {
-			bc_kern_dma_free(hw->adp,
-				hw->tx_pkt_pool[i].desc_mem.sz,
-				hw->tx_pkt_pool[i].desc_mem.pdma_desc_start,
-				hw->tx_pkt_pool[i].desc_mem.phy_addr);
-
-			hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = NULL;
-		}
-	}
-
-	BCMLOG(BCMLOG_DBG, "Releasing RX Pkt pool\n");
-	do {
-		rpkt = crystalhd_hw_alloc_rx_pkt(hw);
-		if (!rpkt)
-			break;
-		bc_kern_dma_free(hw->adp, rpkt->desc_mem.sz,
-				 rpkt->desc_mem.pdma_desc_start,
-				 rpkt->desc_mem.phy_addr);
-		kfree(rpkt);
-	} while (rpkt);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw,
-			     struct crystalhd_dio_req *ioreq,
-			     hw_comp_callback call_back,
-			     wait_queue_head_t *cb_event, uint32_t *list_id,
-			     uint8_t data_flags)
-{
-	struct tx_dma_pkt *tx_dma_packet = NULL;
-	uint32_t first_desc_u_addr, first_desc_l_addr;
-	uint32_t low_addr, high_addr;
-	union addr_64 desc_addr;
-	enum BC_STATUS sts, add_sts;
-	uint32_t dummy_index = 0;
-	unsigned long flags;
-	bool rc;
-
-	if (!hw || !ioreq || !call_back || !cb_event || !list_id) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	/*
-	 * Since we hit code in busy condition very frequently,
-	 * we will check the code in status first before
-	 * checking the availability of free elem.
-	 *
-	 * This will avoid the Q fetch/add in normal condition.
-	 */
-	rc = crystalhd_code_in_full(hw->adp, ioreq->uinfo.xfr_len,
-				  false, data_flags);
-	if (rc) {
-		hw->stats.cin_busy++;
-		return BC_STS_BUSY;
-	}
-
-	/* Get a list from TxFreeQ */
-	tx_dma_packet = (struct tx_dma_pkt *)crystalhd_dioq_fetch(
-						hw->tx_freeq);
-	if (!tx_dma_packet) {
-		BCMLOG_ERR("No empty elements..\n");
-		return BC_STS_ERR_USAGE;
-	}
-
-	sts = crystalhd_xlat_sgl_to_dma_desc(ioreq,
-					   &tx_dma_packet->desc_mem,
-					   &dummy_index);
-	if (sts != BC_STS_SUCCESS) {
-		add_sts = crystalhd_dioq_add(hw->tx_freeq, tx_dma_packet,
-					   false, 0);
-		if (add_sts != BC_STS_SUCCESS)
-			BCMLOG_ERR("double fault..\n");
-
-		return sts;
-	}
-
-	hw->pwr_lock++;
-
-	desc_addr.full_addr = tx_dma_packet->desc_mem.phy_addr;
-	low_addr = desc_addr.low_part;
-	high_addr = desc_addr.high_part;
-
-	tx_dma_packet->call_back = call_back;
-	tx_dma_packet->cb_event  = cb_event;
-	tx_dma_packet->dio_req   = ioreq;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	if (hw->tx_list_post_index == 0) {
-		first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST0;
-		first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST0;
-	} else {
-		first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST1;
-		first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST1;
-	}
-
-	*list_id = tx_dma_packet->list_tag = hw->tx_ioq_tag_seed +
-					     hw->tx_list_post_index;
-
-	hw->tx_list_post_index = (hw->tx_list_post_index + 1) % DMA_ENGINE_CNT;
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-
-	/* Insert in Active Q..*/
-	crystalhd_dioq_add(hw->tx_actq, tx_dma_packet, false,
-			 tx_dma_packet->list_tag);
-
-	/*
-	 * Interrupt will come as soon as you write
-	 * the valid bit. So be ready for that. All
-	 * the initialization should happen before that.
-	 */
-	crystalhd_start_tx_dma_engine(hw);
-	crystalhd_reg_wr(hw->adp, first_desc_u_addr, desc_addr.high_part);
-
-	crystalhd_reg_wr(hw->adp, first_desc_l_addr, desc_addr.low_part |
-					 0x01);
-					/* Be sure we set the valid bit ^^^^ */
-
-	return BC_STS_SUCCESS;
-}
-
-/*
- * This is a force cancel and we are racing with ISR.
- *
- * Will try to remove the req from ActQ before ISR gets it.
- * If ISR gets it first then the completion happens in the
- * normal path and we will return _STS_NO_DATA from here.
- *
- * FIX_ME: Not Tested the actual condition..
- */
-enum BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw,
-					 uint32_t list_id)
-{
-	if (!hw || !list_id) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_stop_tx_dma_engine(hw);
-	crystalhd_hw_tx_req_complete(hw, list_id, BC_STS_IO_USER_ABORT);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
-				 struct crystalhd_dio_req *ioreq, bool en_post)
-{
-	struct crystalhd_rx_dma_pkt *rpkt;
-	uint32_t tag, uv_desc_ix = 0;
-	enum BC_STATUS sts;
-
-	if (!hw || !ioreq) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	rpkt = crystalhd_hw_alloc_rx_pkt(hw);
-	if (!rpkt) {
-		BCMLOG_ERR("Insufficient resources\n");
-		return BC_STS_INSUFF_RES;
-	}
-
-	rpkt->dio_req = ioreq;
-	tag = rpkt->pkt_tag;
-
-	sts = crystalhd_xlat_sgl_to_dma_desc(ioreq, &rpkt->desc_mem,
-					 &uv_desc_ix);
-	if (sts != BC_STS_SUCCESS)
-		return sts;
-
-	rpkt->uv_phy_addr = 0;
-
-	/* Store the address of UV in the rx packet for post*/
-	if (uv_desc_ix)
-		rpkt->uv_phy_addr = rpkt->desc_mem.phy_addr +
-			 (sizeof(struct dma_descriptor) * (uv_desc_ix + 1));
-
-	if (en_post)
-		sts = crystalhd_hw_post_cap_buff(hw, rpkt);
-	else
-		sts = crystalhd_dioq_add(hw->rx_freeq, rpkt, false, tag);
-
-	return sts;
-}
-
-enum BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
-				    struct BC_PIC_INFO_BLOCK *pib,
-				    struct crystalhd_dio_req **ioreq)
-{
-	struct crystalhd_rx_dma_pkt *rpkt;
-	uint32_t timeout = BC_PROC_OUTPUT_TIMEOUT / 1000;
-	uint32_t sig_pending = 0;
-
-
-	if (!hw || !ioreq || !pib) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	rpkt = crystalhd_dioq_fetch_wait(hw->rx_rdyq, timeout, &sig_pending);
-	if (!rpkt) {
-		if (sig_pending) {
-			BCMLOG(BCMLOG_INFO, "wait on frame time out %d\n",
-					 sig_pending);
-			return BC_STS_IO_USER_ABORT;
-		} else {
-			return BC_STS_TIMEOUT;
-		}
-	}
-
-	rpkt->dio_req->uinfo.comp_flags = rpkt->flags;
-
-	if (rpkt->flags & COMP_FLAG_PIB_VALID)
-		memcpy(pib, &rpkt->pib, sizeof(*pib));
-
-	*ioreq = rpkt->dio_req;
-
-	crystalhd_hw_free_rx_pkt(hw, rpkt);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw)
-{
-	struct crystalhd_rx_dma_pkt *rx_pkt;
-	enum BC_STATUS sts;
-	uint32_t i;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	/* This is start of capture.. Post to both the lists.. */
-	for (i = 0; i < DMA_ENGINE_CNT; i++) {
-		rx_pkt = crystalhd_dioq_fetch(hw->rx_freeq);
-		if (!rx_pkt)
-			return BC_STS_NO_DATA;
-		sts = crystalhd_hw_post_cap_buff(hw, rx_pkt);
-		if (BC_STS_SUCCESS != sts)
-			break;
-
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw)
-{
-	void *temp = NULL;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	crystalhd_stop_rx_dma_engine(hw);
-
-	do {
-		temp = crystalhd_dioq_fetch(hw->rx_freeq);
-		if (temp)
-			crystalhd_rx_pkt_rel_call_back(hw, temp);
-	} while (temp);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw)
-{
-	hw->stats.pause_cnt++;
-	hw->stop_pending = 1;
-
-	if ((hw->rx_list_sts[0] == sts_free) &&
-	    (hw->rx_list_sts[1] == sts_free))
-		crystalhd_hw_finalize_pause(hw);
-
-	return BC_STS_SUCCESS;
-}
-
-enum BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw)
-{
-	enum BC_STATUS sts;
-	uint32_t aspm;
-
-	hw->stop_pending = 0;
-
-	aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
-	aspm &= ~ASPM_L1_ENABLE;
-/* NAREN BCMLOG(BCMLOG_INFO, "aspm off\n"); */
-	crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
-
-	sts = crystalhd_hw_start_capture(hw);
-	return sts;
-}
-
-enum BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw)
-{
-	enum BC_STATUS sts;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	sts = crystalhd_put_ddr2sleep(hw);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("Failed to Put DDR To Sleep!!\n");
-		return BC_STS_ERROR;
-	}
-
-	if (!crystalhd_stop_device(hw->adp)) {
-		BCMLOG_ERR("Failed to Stop Device!!\n");
-		return BC_STS_ERROR;
-	}
-
-	return BC_STS_SUCCESS;
-}
-
-void crystalhd_hw_stats(struct crystalhd_hw *hw,
-		 struct crystalhd_hw_stats *stats)
-{
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return;
-	}
-
-	/* if called w/NULL stats, its a req to zero out the stats */
-	if (!stats) {
-		memset(&hw->stats, 0, sizeof(hw->stats));
-		return;
-	}
-
-	hw->stats.freeq_count = crystalhd_dioq_count(hw->rx_freeq);
-	hw->stats.rdyq_count  = crystalhd_dioq_count(hw->rx_rdyq);
-	memcpy(stats, &hw->stats, sizeof(*stats));
-}
-
-enum BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *hw)
-{
-	uint32_t reg, n, i;
-	uint32_t vco_mg, refresh_reg;
-
-	if (!hw) {
-		BCMLOG_ERR("Invalid Arguments\n");
-		return BC_STS_INV_ARG;
-	}
-
-	/* FIXME: jarod: wha? */
-	/*n = (hw->core_clock_mhz * 3) / 20 + 1; */
-	n = hw->core_clock_mhz/5;
-
-	if (n == hw->prev_n)
-		return BC_STS_CLK_NOCHG;
-
-	if (hw->pwr_lock > 0) {
-		/* BCMLOG(BCMLOG_INFO,"pwr_lock is %u\n", hw->pwr_lock) */
-		return BC_STS_CLK_NOCHG;
-	}
-
-	i = n * 27;
-	if (i < 560)
-		vco_mg = 0;
-	else if (i < 900)
-		vco_mg = 1;
-	else if (i < 1030)
-		vco_mg = 2;
-	else
-		vco_mg = 3;
-
-	reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
-
-	reg &= 0xFFFFCFC0;
-	reg |= n;
-	reg |= vco_mg << 12;
-
-	BCMLOG(BCMLOG_INFO, "clock is moving to %d with n %d with vco_mg %d\n",
-	       hw->core_clock_mhz, n, vco_mg);
-
-	/* Change the DRAM refresh rate to accommodate the new frequency */
-	/* refresh reg = ((refresh_rate * clock_rate)/16) - 1; rounding up*/
-	refresh_reg = (7 * hw->core_clock_mhz / 16);
-	bc_dec_reg_wr(hw->adp, SDRAM_REF_PARAM, ((1 << 12) | refresh_reg));
-
-	bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
-
-	i = 0;
-
-	for (i = 0; i < 10; i++) {
-		reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
-
-		if (reg & 0x00020000) {
-			hw->prev_n = n;
-			/* FIXME: jarod: outputting
-			 a random "C" is... confusing... */
-			BCMLOG(BCMLOG_INFO, "C");
-			return BC_STS_SUCCESS;
-		} else {
-			msleep_interruptible(10);
-		}
-	}
-	BCMLOG(BCMLOG_INFO, "clk change failed\n");
-	return BC_STS_CLK_NOCHG;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_hw.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_hw.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,407 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_hw . h
- *
- *  Description:
- *		BCM70012 Linux driver hardware layer.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#ifndef _CRYSTALHD_HW_H_
-#define _CRYSTALHD_HW_H_
-
-#include "crystalhd.h"
-
-/* HW constants..*/
-#define DMA_ENGINE_CNT		2
-#define MAX_PIB_Q_DEPTH		64
-#define MIN_PIB_Q_DEPTH		2
-#define WR_POINTER_OFF		4
-
-#define ASPM_L1_ENABLE		(BC_BIT(27))
-
-/*************************************************
-  7412 Decoder  Registers.
-**************************************************/
-#define FW_CMD_BUFF_SZ		64
-#define TS_Host2CpuSnd		0x00000100
-#define Hst2CpuMbx1		0x00100F00
-#define Cpu2HstMbx1		0x00100F04
-#define MbxStat1		0x00100F08
-#define Stream2Host_Intr_Sts	0x00100F24
-#define C011_RET_SUCCESS	0x0 /* Return status of firmware command. */
-
-/* TS input status register */
-#define TS_StreamAFIFOStatus	0x0010044C
-#define TS_StreamBFIFOStatus	0x0010084C
-
-/*UART Selection definitions*/
-#define UartSelectA		0x00100300
-#define UartSelectB		0x00100304
-
-#define BSVS_UART_DEC_NONE	0x00
-#define BSVS_UART_DEC_OUTER	0x01
-#define BSVS_UART_DEC_INNER	0x02
-#define BSVS_UART_STREAM	0x03
-
-/* Code-In fifo */
-#define REG_DecCA_RegCinCTL	0xa00
-#define REG_DecCA_RegCinBase	0xa0c
-#define REG_DecCA_RegCinEnd	0xa10
-#define REG_DecCA_RegCinWrPtr	0xa04
-#define REG_DecCA_RegCinRdPtr	0xa08
-
-#define REG_Dec_TsUser0Base	0x100864
-#define REG_Dec_TsUser0Rdptr	0x100868
-#define REG_Dec_TsUser0Wrptr	0x10086C
-#define REG_Dec_TsUser0End	0x100874
-
-/* ASF Case ...*/
-#define REG_Dec_TsAudCDB2Base	0x10036c
-#define REG_Dec_TsAudCDB2Rdptr  0x100378
-#define REG_Dec_TsAudCDB2Wrptr  0x100374
-#define REG_Dec_TsAudCDB2End	0x100370
-
-/* DRAM bringup Registers */
-#define SDRAM_PARAM		0x00040804
-#define SDRAM_PRECHARGE		0x000408B0
-#define SDRAM_EXT_MODE		0x000408A4
-#define SDRAM_MODE		0x000408A0
-#define SDRAM_REFRESH		0x00040890
-#define SDRAM_REF_PARAM		0x00040808
-
-#define DecHt_PllACtl		0x34000C
-#define DecHt_PllBCtl		0x340010
-#define DecHt_PllCCtl		0x340014
-#define DecHt_PllDCtl		0x340034
-#define DecHt_PllECtl		0x340038
-#define AUD_DSP_MISC_SOFT_RESET	0x00240104
-#define AIO_MISC_PLL_RESET	0x0026000C
-#define PCIE_CLK_REQ_REG	0xDC
-#define	PCI_CLK_REQ_ENABLE	(BC_BIT(8))
-
-/*************************************************
-  F/W Copy engine definitions..
-**************************************************/
-#define BC_FWIMG_ST_ADDR	0x00000000
-/* FIXME: jarod: there's a kernel function that'll do this for us... */
-#define rotr32_1(x, n)		(((x) >> n) | ((x) << (32 - n)))
-#define bswap_32_1(x) ((rotr32_1((x), 24) & 0x00ff00ff) | (rotr32_1((x), 8) & 0xff00ff00))
-
-#define DecHt_HostSwReset	0x340000
-#define BC_DRAM_FW_CFG_ADDR	0x001c2000
-
-union addr_64 {
-	struct {
-		uint32_t	low_part;
-		uint32_t	high_part;
-	};
-
-	uint64_t	full_addr;
-
-};
-
-union intr_mask_reg {
-	struct {
-		uint32_t	mask_tx_done:1;
-		uint32_t	mask_tx_err:1;
-		uint32_t	mask_rx_done:1;
-		uint32_t	mask_rx_err:1;
-		uint32_t	mask_pcie_err:1;
-		uint32_t	mask_pcie_rbusmast_err:1;
-		uint32_t	mask_pcie_rgr_bridge:1;
-		uint32_t	reserved:25;
-	};
-
-	uint32_t	whole_reg;
-
-};
-
-union link_misc_perst_deco_ctrl {
-	struct {
-		uint32_t	bcm7412_rst:1;	/* 1 -> BCM7412 is held
-						in reset. Reset value 1.*/
-		uint32_t	reserved0:3;		/* Reserved.No Effect*/
-		uint32_t	stop_bcm_7412_clk:1;	/* 1 ->Stops branch of
-						27MHz clk used to clk BCM7412*/
-		uint32_t	reserved1:27;		/* Reserved. No Effect*/
-	};
-
-	uint32_t	whole_reg;
-
-};
-
-union link_misc_perst_clk_ctrl {
-	struct {
-		uint32_t	sel_alt_clk:1;	  /* When set, selects a
-				 6.75MHz clock as the source of core_clk */
-		uint32_t	stop_core_clk:1;  /* When set, stops the branch
-		 of core_clk that is not needed for low power operation */
-		uint32_t	pll_pwr_dn:1;	  /* When set, powers down the
-			 main PLL. The alternate clock bit should be set to
-			 select an alternate clock before setting this bit.*/
-		uint32_t	reserved0:5;	  /* Reserved */
-		uint32_t	pll_mult:8;	  /* This setting controls
-						 the multiplier for the PLL. */
-		uint32_t	pll_div:4;	  /* This setting controls
-						 the divider for the PLL. */
-		uint32_t	reserved1:12;	  /* Reserved */
-	};
-
-	uint32_t	whole_reg;
-
-};
-
-union link_misc_perst_decoder_ctrl {
-	struct {
-		uint32_t	bcm_7412_rst:1; /* 1 -> BCM7412 is held
-						 in reset. Reset value 1.*/
-		uint32_t	res0:3; /* Reserved.No Effect*/
-		uint32_t	stop_7412_clk:1; /* 1 ->Stops branch of 27MHz
-						 clk used to clk BCM7412*/
-		uint32_t	res1:27; /* Reserved. No Effect */
-	};
-
-	uint32_t	whole_reg;
-
-};
-
-union desc_low_addr_reg {
-	struct {
-		uint32_t	list_valid:1;
-		uint32_t	reserved:4;
-		uint32_t	low_addr:27;
-	};
-
-	uint32_t	whole_reg;
-
-};
-
-struct dma_descriptor {	/* 8 32-bit values */
-	/* 0th u32 */
-	uint32_t sdram_buff_addr:28;	/* bits 0-27:  SDRAM Address */
-	uint32_t res0:4;		/* bits 28-31: Reserved */
-
-	/* 1st u32 */
-	uint32_t buff_addr_low;		/* 1 buffer address low */
-	uint32_t buff_addr_high;	/* 2 buffer address high */
-
-	/* 3rd u32 */
-	uint32_t res2:2;		/* 0-1 - Reserved */
-	uint32_t xfer_size:23;		/* 2-24 = Xfer size in words */
-	uint32_t res3:6;		/* 25-30 reserved */
-	uint32_t intr_enable:1;		/* 31 - Interrupt After this desc */
-
-	/* 4th u32 */
-	uint32_t endian_xlat_align:2;	/* 0-1 Endian Translation */
-	uint32_t next_desc_cont:1;	/* 2 - Next desc is in contig memory */
-	uint32_t res4:25;		/* 3 - 27 Reserved bits */
-	uint32_t fill_bytes:2;		/* 28-29 Bits Fill Bytes */
-	uint32_t dma_dir:1;		/* 30 bit DMA Direction */
-	uint32_t last_rec_indicator:1;	/* 31 bit Last Record Indicator */
-
-	/* 5th u32 */
-	uint32_t next_desc_addr_low;	/* 32-bits Next Desc Addr lower */
-
-	/* 6th u32 */
-	uint32_t next_desc_addr_high;	/* 32-bits Next Desc Addr Higher */
-
-	/* 7th u32 */
-	uint32_t res8;			/* Last 32bits reserved */
-
-};
-
-/*
- * We will allocate the memory in 4K pages
- * the linked list will be a list of 32 byte descriptors.
- * The  virtual address will determine what should be freed.
- */
-struct dma_desc_mem {
-	struct dma_descriptor	*pdma_desc_start; /* 32-bytes for dma
-				 descriptor. should be first element */
-	dma_addr_t		phy_addr;	/* physical address
-						 of each DMA desc */
-	uint32_t		sz;
-	struct _dma_desc_mem_	*Next; /* points to Next Descriptor in chain */
-
-};
-
-enum list_sts {
-	sts_free = 0,
-
-	/* RX-Y Bits 0:7 */
-	rx_waiting_y_intr	= 0x00000001,
-	rx_y_error		= 0x00000004,
-
-	/* RX-UV Bits 8:16 */
-	rx_waiting_uv_intr	= 0x0000100,
-	rx_uv_error		= 0x0000400,
-
-	rx_sts_waiting		= (rx_waiting_y_intr|rx_waiting_uv_intr),
-	rx_sts_error		= (rx_y_error|rx_uv_error),
-
-	rx_y_mask		= 0x000000FF,
-	rx_uv_mask		= 0x0000FF00,
-};
-
-struct tx_dma_pkt {
-	struct dma_desc_mem	desc_mem;
-	hw_comp_callback	call_back;
-	struct crystalhd_dio_req	*dio_req;
-	wait_queue_head_t	*cb_event;
-	uint32_t		list_tag;
-};
-
-struct crystalhd_rx_dma_pkt {
-	struct dma_desc_mem		desc_mem;
-	struct crystalhd_dio_req	*dio_req;
-	uint32_t			pkt_tag;
-	uint32_t			flags;
-	struct BC_PIC_INFO_BLOCK	pib;
-	dma_addr_t			uv_phy_addr;
-	struct crystalhd_rx_dma_pkt	*next;
-};
-
-struct crystalhd_hw_stats {
-	uint32_t	rx_errors;
-	uint32_t	tx_errors;
-	uint32_t	freeq_count;
-	uint32_t	rdyq_count;
-	uint32_t	num_interrupts;
-	uint32_t	dev_interrupts;
-	uint32_t	cin_busy;
-	uint32_t	pause_cnt;
-};
-
-struct crystalhd_hw {
-	struct tx_dma_pkt	tx_pkt_pool[DMA_ENGINE_CNT];
-	spinlock_t		lock;
-
-	uint32_t		tx_ioq_tag_seed;
-	uint32_t		tx_list_post_index;
-
-	struct crystalhd_rx_dma_pkt *rx_pkt_pool_head;
-	uint32_t		rx_pkt_tag_seed;
-
-	bool			dev_started;
-	void			*adp;
-
-	wait_queue_head_t	*pfw_cmd_event;
-	int			fwcmd_evt_sts;
-
-	uint32_t		pib_del_Q_addr;
-	uint32_t		pib_rel_Q_addr;
-
-	struct crystalhd_dioq	*tx_freeq;
-	struct crystalhd_dioq	*tx_actq;
-
-	/* Rx DMA Engine Specific Locks */
-	spinlock_t		rx_lock;
-	uint32_t		rx_list_post_index;
-	enum list_sts		rx_list_sts[DMA_ENGINE_CNT];
-	struct crystalhd_dioq	*rx_rdyq;
-	struct crystalhd_dioq	*rx_freeq;
-	struct crystalhd_dioq	*rx_actq;
-	uint32_t		stop_pending;
-
-	/* HW counters.. */
-	struct crystalhd_hw_stats	stats;
-
-	/* Core clock in MHz */
-	uint32_t		core_clock_mhz;
-	uint32_t		prev_n;
-	uint32_t		pwr_lock;
-};
-
-/* Clock defines for power control */
-#define CLOCK_PRESET 175
-
-/* DMA engine register BIT mask wrappers.. */
-#define DMA_START_BIT	MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK
-
-#define GET_RX_INTR_MASK (INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK |	\
-	INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK |	\
-	INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK |		\
-	INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK |		\
-	INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK |		\
-	INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK |	\
-	INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK |		\
-	INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
-
-#define GET_Y0_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
-	MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK |		\
-	MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK |	\
-	MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
-
-#define GET_UV0_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
-	MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK |		\
-	MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK |	\
-	MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
-
-#define GET_Y1_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
-	MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK |		\
-	MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK |	\
-	MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
-
-#define GET_UV1_ERR_MSK	(MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
-	MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK |		\
-	MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK |	\
-	MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
-
-
-/**** API Exposed to the other layers ****/
-enum BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp,
-			      void *buffer, uint32_t sz);
-enum BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw,
-				 struct BC_FW_CMD *fw_cmd);
-bool crystalhd_hw_interrupt(struct crystalhd_adp *adp,
-				 struct crystalhd_hw *hw);
-enum BC_STATUS crystalhd_hw_open(struct crystalhd_hw *,
-				 struct crystalhd_adp *);
-enum BC_STATUS crystalhd_hw_close(struct crystalhd_hw *);
-enum BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *);
-enum BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *);
-
-
-enum BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw,
-			     struct crystalhd_dio_req *ioreq,
-			     hw_comp_callback call_back,
-			     wait_queue_head_t *cb_event,
-			     uint32_t *list_id, uint8_t data_flags);
-
-enum BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw);
-enum BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw);
-enum BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw);
-enum BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw,
-				 uint32_t list_id);
-enum BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
-			 struct crystalhd_dio_req *ioreq, bool en_post);
-enum BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
-				    struct BC_PIC_INFO_BLOCK *pib,
-				    struct crystalhd_dio_req **ioreq);
-enum BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw);
-enum BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw);
-void crystalhd_hw_stats(struct crystalhd_hw *hw,
-			 struct crystalhd_hw_stats *stats);
-
-/* API to program the core clock on the decoder */
-enum BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_lnx.c linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_lnx.c
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_lnx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_lnx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,782 +0,0 @@
-/***************************************************************************
-  BCM70010 Linux driver
-  Copyright (c) 2005-2009, Broadcom Corporation.
-
-  This driver is free software; 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 driver is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this driver.  If not, see <http://www.gnu.org/licenses/>.
-***************************************************************************/
-
-#include "crystalhd.h"
-
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-
-static DEFINE_MUTEX(chd_dec_mutex);
-static struct class *crystalhd_class;
-
-static struct crystalhd_adp *g_adp_info;
-
-static irqreturn_t chd_dec_isr(int irq, void *arg)
-{
-	struct crystalhd_adp *adp = arg;
-	int rc = 0;
-	if (adp)
-		rc = crystalhd_cmd_interrupt(&adp->cmds);
-
-	return IRQ_RETVAL(rc);
-}
-
-static int chd_dec_enable_int(struct crystalhd_adp *adp)
-{
-	int rc = 0;
-
-	if (!adp || !adp->pdev) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return -EINVAL;
-	}
-
-	if (adp->pdev->msi_enabled)
-		adp->msi = 1;
-	else
-		adp->msi = pci_enable_msi(adp->pdev);
-
-	rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
-			 adp->name, (void *)adp);
-	if (rc) {
-		BCMLOG_ERR("Interrupt request failed..\n");
-		pci_disable_msi(adp->pdev);
-	}
-
-	return rc;
-}
-
-static int chd_dec_disable_int(struct crystalhd_adp *adp)
-{
-	if (!adp || !adp->pdev) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return -EINVAL;
-	}
-
-	free_irq(adp->pdev->irq, adp);
-
-	if (adp->msi)
-		pci_disable_msi(adp->pdev);
-
-	return 0;
-}
-
-static struct
-crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp,
-					   bool isr)
-{
-	unsigned long flags = 0;
-	struct crystalhd_ioctl_data *temp;
-
-	if (!adp)
-		return NULL;
-
-	spin_lock_irqsave(&adp->lock, flags);
-
-	temp = adp->idata_free_head;
-	if (temp) {
-		adp->idata_free_head = adp->idata_free_head->next;
-		memset(temp, 0, sizeof(*temp));
-	}
-
-	spin_unlock_irqrestore(&adp->lock, flags);
-	return temp;
-}
-
-static void chd_dec_free_iodata(struct crystalhd_adp *adp,
-				struct crystalhd_ioctl_data *iodata, bool isr)
-{
-	unsigned long flags = 0;
-
-	if (!adp || !iodata)
-		return;
-
-	spin_lock_irqsave(&adp->lock, flags);
-	iodata->next = adp->idata_free_head;
-	adp->idata_free_head = iodata;
-	spin_unlock_irqrestore(&adp->lock, flags);
-}
-
-static inline int crystalhd_user_data(void __user *ud, void *dr,
-				      int size, int set)
-{
-	int rc;
-
-	if (!ud || !dr) {
-		BCMLOG_ERR("Invalid arg\n");
-		return -EINVAL;
-	}
-
-	if (set)
-		rc = copy_to_user(ud, dr, size);
-	else
-		rc = copy_from_user(dr, ud, size);
-
-	if (rc) {
-		BCMLOG_ERR("Invalid args for command\n");
-		rc = -EFAULT;
-	}
-
-	return rc;
-}
-
-static int chd_dec_fetch_cdata(struct crystalhd_adp *adp,
-			       struct crystalhd_ioctl_data *io, uint32_t m_sz,
-			       unsigned long ua)
-{
-	unsigned long ua_off;
-	int rc = 0;
-
-	if (!adp || !io || !ua || !m_sz) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return -EINVAL;
-	}
-
-	io->add_cdata = vmalloc(m_sz);
-	if (!io->add_cdata) {
-		BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
-		return -ENOMEM;
-	}
-
-	io->add_cdata_sz = m_sz;
-	ua_off = ua + sizeof(io->udata);
-	rc = crystalhd_user_data((void __user *)ua_off, io->add_cdata,
-				 io->add_cdata_sz, 0);
-	if (rc) {
-		BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
-			   io->add_cdata_sz, (unsigned int)ua_off);
-		vfree(io->add_cdata);
-		io->add_cdata = NULL;
-		return -ENODATA;
-	}
-
-	return rc;
-}
-
-static int chd_dec_release_cdata(struct crystalhd_adp *adp,
-				 struct crystalhd_ioctl_data *io,
-				 unsigned long ua)
-{
-	unsigned long ua_off;
-	int rc;
-
-	if (!adp || !io || !ua) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return -EINVAL;
-	}
-
-	if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
-		ua_off = ua + sizeof(io->udata);
-		rc = crystalhd_user_data((void __user *)ua_off, io->add_cdata,
-					 io->add_cdata_sz, 1);
-		if (rc) {
-			BCMLOG_ERR(
-				"failed to push add_cdata sz:%x ua_off:%x\n",
-				 io->add_cdata_sz, (unsigned int)ua_off);
-			return -ENODATA;
-		}
-	}
-
-	if (io->add_cdata) {
-		vfree(io->add_cdata);
-		io->add_cdata = NULL;
-	}
-
-	return 0;
-}
-
-static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
-				  struct crystalhd_ioctl_data *io,
-				  unsigned long ua, int set)
-{
-	int rc;
-	uint32_t m_sz = 0;
-
-	if (!adp || !io || !ua) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return -EINVAL;
-	}
-
-	rc = crystalhd_user_data((void __user *)ua, &io->udata,
-				 sizeof(io->udata), set);
-	if (rc) {
-		BCMLOG_ERR("failed to %s iodata\n", (set ? "set" : "get"));
-		return rc;
-	}
-
-	switch (io->cmd) {
-	case BCM_IOC_MEM_RD:
-	case BCM_IOC_MEM_WR:
-	case BCM_IOC_FW_DOWNLOAD:
-		m_sz = io->udata.u.devMem.NumDwords * 4;
-		if (set)
-			rc = chd_dec_release_cdata(adp, io, ua);
-		else
-			rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
-		break;
-	default:
-		break;
-	}
-
-	return rc;
-}
-
-static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
-			   uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
-{
-	int rc;
-	struct crystalhd_ioctl_data *temp;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	temp = chd_dec_alloc_iodata(adp, 0);
-	if (!temp) {
-		BCMLOG_ERR("Failed to get iodata..\n");
-		return -EINVAL;
-	}
-
-	temp->u_id = uid;
-	temp->cmd  = cmd;
-
-	rc = chd_dec_proc_user_data(adp, temp, ua, 0);
-	if (!rc) {
-		sts = func(&adp->cmds, temp);
-		if (sts == BC_STS_PENDING)
-			sts = BC_STS_NOT_IMPL;
-		temp->udata.RetSts = sts;
-		rc = chd_dec_proc_user_data(adp, temp, ua, 1);
-	}
-
-	chd_dec_free_iodata(adp, temp, 0);
-
-	return rc;
-}
-
-/* API interfaces */
-static long chd_dec_ioctl(struct file *fd, unsigned int cmd, unsigned long ua)
-{
-	struct crystalhd_adp *adp = chd_get_adp();
-	crystalhd_cmd_proc cproc;
-	struct crystalhd_user *uc;
-	int ret;
-
-	if (!adp || !fd) {
-		BCMLOG_ERR("Invalid adp\n");
-		return -EINVAL;
-	}
-
-	uc = fd->private_data;
-	if (!uc) {
-		BCMLOG_ERR("Failed to get uc\n");
-		return -ENODATA;
-	}
-
-	mutex_lock(&chd_dec_mutex);
-	cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
-	if (!cproc) {
-		BCMLOG_ERR("Unhandled command: %d\n", cmd);
-		mutex_unlock(&chd_dec_mutex);
-		return -EINVAL;
-	}
-
-	ret = chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
-	mutex_unlock(&chd_dec_mutex);
-	return ret;
-}
-
-static int chd_dec_open(struct inode *in, struct file *fd)
-{
-	struct crystalhd_adp *adp = chd_get_adp();
-	int rc = 0;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	struct crystalhd_user *uc = NULL;
-
-	if (!adp) {
-		BCMLOG_ERR("Invalid adp\n");
-		return -EINVAL;
-	}
-
-	if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
-		BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
-		return -EBUSY;
-	}
-
-	sts = crystalhd_user_open(&adp->cmds, &uc);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("cmd_user_open - %d\n", sts);
-		rc = -EBUSY;
-	}
-
-	adp->cfg_users++;
-
-	fd->private_data = uc;
-
-	return rc;
-}
-
-static int chd_dec_close(struct inode *in, struct file *fd)
-{
-	struct crystalhd_adp *adp = chd_get_adp();
-	struct crystalhd_user *uc;
-
-	if (!adp) {
-		BCMLOG_ERR("Invalid adp\n");
-		return -EINVAL;
-	}
-
-	uc = fd->private_data;
-	if (!uc) {
-		BCMLOG_ERR("Failed to get uc\n");
-		return -ENODATA;
-	}
-
-	crystalhd_user_close(&adp->cmds, uc);
-
-	adp->cfg_users--;
-
-	return 0;
-}
-
-static const struct file_operations chd_dec_fops = {
-	.owner   = THIS_MODULE,
-	.unlocked_ioctl = chd_dec_ioctl,
-	.open    = chd_dec_open,
-	.release = chd_dec_close,
-	.llseek = noop_llseek,
-};
-
-static int chd_dec_init_chdev(struct crystalhd_adp *adp)
-{
-	struct crystalhd_ioctl_data *temp;
-	struct device *dev;
-	int rc = -ENODEV, i = 0;
-
-	if (!adp)
-		goto fail;
-
-	adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
-					     &chd_dec_fops);
-	if (adp->chd_dec_major < 0) {
-		BCMLOG_ERR("Failed to create config dev\n");
-		rc = adp->chd_dec_major;
-		goto fail;
-	}
-
-	/* register crystalhd class */
-	crystalhd_class = class_create(THIS_MODULE, "crystalhd");
-	if (IS_ERR(crystalhd_class)) {
-		rc = PTR_ERR(crystalhd_class);
-		BCMLOG_ERR("failed to create class\n");
-		goto class_create_fail;
-	}
-
-	dev = device_create(crystalhd_class, NULL,
-			    MKDEV(adp->chd_dec_major, 0), NULL, "crystalhd");
-	if (IS_ERR(dev)) {
-		rc = PTR_ERR(dev);
-		BCMLOG_ERR("failed to create device\n");
-		goto device_create_fail;
-	}
-
-	rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
-	if (rc) {
-		BCMLOG_ERR("failed to create device\n");
-		goto elem_pool_fail;
-	}
-
-	/* Allocate general purpose ioctl pool. */
-	for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
-		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
-		if (!temp) {
-			BCMLOG_ERR("ioctl data pool kzalloc failed\n");
-			rc = -ENOMEM;
-			goto kzalloc_fail;
-		}
-		/* Add to global pool.. */
-		chd_dec_free_iodata(adp, temp, 0);
-	}
-
-	return 0;
-
-kzalloc_fail:
-	crystalhd_delete_elem_pool(adp);
-elem_pool_fail:
-	device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
-device_create_fail:
-	class_destroy(crystalhd_class);
-class_create_fail:
-	unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
-fail:
-	return rc;
-}
-
-static void chd_dec_release_chdev(struct crystalhd_adp *adp)
-{
-	struct crystalhd_ioctl_data *temp = NULL;
-	if (!adp)
-		return;
-
-	if (adp->chd_dec_major > 0) {
-		/* unregister crystalhd class */
-		device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
-		unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
-		BCMLOG(BCMLOG_INFO, "released api device - %d\n",
-		       adp->chd_dec_major);
-		class_destroy(crystalhd_class);
-	}
-	adp->chd_dec_major = 0;
-
-	/* Clear iodata pool.. */
-	do {
-		temp = chd_dec_alloc_iodata(adp, 0);
-		kfree(temp);
-	} while (temp);
-
-	crystalhd_delete_elem_pool(adp);
-}
-
-static int chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
-{
-	int rc;
-	unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
-	uint32_t mem_len   = pci_resource_len(pinfo->pdev, 2);
-	unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
-	uint32_t i2o_len   = pci_resource_len(pinfo->pdev, 0);
-
-	BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x  bar0:0x%lx-0x%08x\n",
-	       bar2, mem_len, bar0, i2o_len);
-
-	rc = check_mem_region(bar2, mem_len);
-	if (rc) {
-		BCMLOG_ERR("No valid mem region...\n");
-		return -ENOMEM;
-	}
-
-	pinfo->addr = ioremap_nocache(bar2, mem_len);
-	if (!pinfo->addr) {
-		BCMLOG_ERR("Failed to remap mem region...\n");
-		return -ENOMEM;
-	}
-
-	pinfo->pci_mem_start = bar2;
-	pinfo->pci_mem_len   = mem_len;
-
-	rc = check_mem_region(bar0, i2o_len);
-	if (rc) {
-		BCMLOG_ERR("No valid mem region...\n");
-		return -ENOMEM;
-	}
-
-	pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
-	if (!pinfo->i2o_addr) {
-		BCMLOG_ERR("Failed to remap mem region...\n");
-		return -ENOMEM;
-	}
-
-	pinfo->pci_i2o_start = bar0;
-	pinfo->pci_i2o_len   = i2o_len;
-
-	rc = pci_request_regions(pinfo->pdev, pinfo->name);
-	if (rc < 0) {
-		BCMLOG_ERR("Region request failed: %d\n", rc);
-		return rc;
-	}
-
-	BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx  i2o_addr:0x%08lx\n",
-	       (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
-
-	return 0;
-}
-
-static void chd_pci_release_mem(struct crystalhd_adp *pinfo)
-{
-	if (!pinfo)
-		return;
-
-	if (pinfo->addr)
-		iounmap(pinfo->addr);
-
-	if (pinfo->i2o_addr)
-		iounmap(pinfo->i2o_addr);
-
-	pci_release_regions(pinfo->pdev);
-}
-
-
-static void chd_dec_pci_remove(struct pci_dev *pdev)
-{
-	struct crystalhd_adp *pinfo;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	pinfo = pci_get_drvdata(pdev);
-	if (!pinfo) {
-		BCMLOG_ERR("could not get adp\n");
-		return;
-	}
-
-	sts = crystalhd_delete_cmd_context(&pinfo->cmds);
-	if (sts != BC_STS_SUCCESS)
-		BCMLOG_ERR("cmd delete :%d\n", sts);
-
-	chd_dec_release_chdev(pinfo);
-
-	chd_dec_disable_int(pinfo);
-
-	chd_pci_release_mem(pinfo);
-	pci_disable_device(pinfo->pdev);
-
-	kfree(pinfo);
-	g_adp_info = NULL;
-}
-
-static int chd_dec_pci_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *entry)
-{
-	struct crystalhd_adp *pinfo;
-	int rc;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	BCMLOG(BCMLOG_DBG,
-	       "PCI_INFO: Vendor:0x%04x Device:0x%04x s_vendor:0x%04x s_device: 0x%04x\n",
-	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
-	       pdev->subsystem_device);
-
-	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-	if (!pinfo) {
-		BCMLOG_ERR("Failed to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	pinfo->pdev = pdev;
-
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		BCMLOG_ERR("Failed to enable PCI device\n");
-		goto err;
-	}
-
-	snprintf(pinfo->name, sizeof(pinfo->name), "crystalhd_pci_e:%d:%d:%d",
-		 pdev->bus->number, PCI_SLOT(pdev->devfn),
-		 PCI_FUNC(pdev->devfn));
-
-	rc = chd_pci_reserve_mem(pinfo);
-	if (rc) {
-		BCMLOG_ERR("Failed to setup memory regions.\n");
-		pci_disable_device(pdev);
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	pinfo->present	= 1;
-	pinfo->drv_data = entry->driver_data;
-
-	/* Setup adapter level lock.. */
-	spin_lock_init(&pinfo->lock);
-
-	/* setup api stuff.. */
-	chd_dec_init_chdev(pinfo);
-	rc = chd_dec_enable_int(pinfo);
-	if (rc) {
-		BCMLOG_ERR("_enable_int err:%d\n", rc);
-		pci_disable_device(pdev);
-		rc = -ENODEV;
-		goto err;
-	}
-
-	/* Set dma mask... */
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-		pinfo->dmabits = 64;
-	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-		pinfo->dmabits = 32;
-	} else {
-		BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
-		pci_disable_device(pdev);
-		rc = -ENODEV;
-		goto err;
-	}
-
-	sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("cmd setup :%d\n", sts);
-		pci_disable_device(pdev);
-		rc = -ENODEV;
-		goto err;
-	}
-
-	pci_set_master(pdev);
-
-	pci_set_drvdata(pdev, pinfo);
-
-	g_adp_info = pinfo;
-
-	return 0;
-
-err:
-	kfree(pinfo);
-	return rc;
-}
-
-#ifdef CONFIG_PM
-static int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct crystalhd_adp *adp;
-	struct crystalhd_ioctl_data *temp;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-
-	adp = pci_get_drvdata(pdev);
-	if (!adp) {
-		BCMLOG_ERR("could not get adp\n");
-		return -ENODEV;
-	}
-
-	temp = chd_dec_alloc_iodata(adp, false);
-	if (!temp) {
-		BCMLOG_ERR("could not get ioctl data\n");
-		return -ENODEV;
-	}
-
-	sts = crystalhd_suspend(&adp->cmds, temp);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
-		return -ENODEV;
-	}
-
-	chd_dec_free_iodata(adp, temp, false);
-	chd_dec_disable_int(adp);
-	pci_save_state(pdev);
-
-	/* Disable IO/bus master/irq router */
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	return 0;
-}
-
-static int chd_dec_pci_resume(struct pci_dev *pdev)
-{
-	struct crystalhd_adp *adp;
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	int rc;
-
-	adp = pci_get_drvdata(pdev);
-	if (!adp) {
-		BCMLOG_ERR("could not get adp\n");
-		return -ENODEV;
-	}
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-
-	/* device's irq possibly is changed, driver should take care */
-	if (pci_enable_device(pdev)) {
-		BCMLOG_ERR("Failed to enable PCI device\n");
-		return 1;
-	}
-
-	pci_set_master(pdev);
-
-	rc = chd_dec_enable_int(adp);
-	if (rc) {
-		BCMLOG_ERR("_enable_int err:%d\n", rc);
-		pci_disable_device(pdev);
-		return -ENODEV;
-	}
-
-	sts = crystalhd_resume(&adp->cmds);
-	if (sts != BC_STS_SUCCESS) {
-		BCMLOG_ERR("BCM70012 Resume %d\n", sts);
-		pci_disable_device(pdev);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-#endif
-
-static const struct pci_device_id chd_dec_pci_id_table[] = {
-	{ PCI_VDEVICE(BROADCOM, 0x1612), 8 },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
-
-static struct pci_driver bc_chd_70012_driver = {
-	.name     = "Broadcom 70012 Decoder",
-	.probe    = chd_dec_pci_probe,
-	.remove   = chd_dec_pci_remove,
-	.id_table = chd_dec_pci_id_table,
-#ifdef CONFIG_PM
-	.suspend  = chd_dec_pci_suspend,
-	.resume   = chd_dec_pci_resume
-#endif
-};
-
-void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
-{
-	if ((!arg) || (strlen(arg) < 3))
-		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
-	else if (!strncmp(arg, "sstep", 5))
-		g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
-				  BCMLOG_SSTEP | BCMLOG_ERROR;
-	else if (!strncmp(arg, "info", 4))
-		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
-	else if (!strncmp(arg, "debug", 5))
-		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
-				  BCMLOG_DBG;
-	else if (!strncmp(arg, "pball", 5))
-		g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
-	else if (!strncmp(arg, "silent", 6))
-		g_linklog_level = 0;
-	else
-		g_linklog_level = 0;
-}
-
-struct crystalhd_adp *chd_get_adp(void)
-{
-	return g_adp_info;
-}
-
-static int __init chd_dec_module_init(void)
-{
-	int rc;
-
-	chd_set_log_level(NULL, "debug");
-	BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d\n",
-	       crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
-
-	rc = pci_register_driver(&bc_chd_70012_driver);
-
-	if (rc < 0)
-		BCMLOG_ERR("Could not find any devices. err:%d\n", rc);
-
-	return rc;
-}
-module_init(chd_dec_module_init);
-
-static void __exit chd_dec_module_cleanup(void)
-{
-	BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d\n",
-	       crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
-
-	pci_unregister_driver(&bc_chd_70012_driver);
-}
-module_exit(chd_dec_module_cleanup);
-
-MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
-MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
-MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("bcm70012");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_lnx.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_lnx.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_lnx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_lnx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_lnx . h
- *
- *  Description:
- *		BCM70012 Linux driver
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#ifndef _CRYSTALHD_LNX_H_
-#define _CRYSTALHD_LNX_H_
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/pagemap.h>
-#include <linux/vmalloc.h>
-
-#include <linux/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <linux/uaccess.h>
-
-#include "crystalhd.h"
-
-#define CRYSTAL_HD_NAME		"Broadcom Crystal HD Decoder (BCM70012) Driver"
-
-/* OS specific PCI information structure and adapter information. */
-struct crystalhd_adp {
-	/* Hardware board/PCI specifics */
-	char			name[32];
-	struct pci_dev		*pdev;
-
-	unsigned long		pci_mem_start;
-	uint32_t		pci_mem_len;
-	void __iomem		*addr;
-
-	unsigned long		pci_i2o_start;
-	uint32_t		pci_i2o_len;
-	void __iomem		*i2o_addr;
-
-	unsigned int		drv_data;
-	unsigned int		dmabits;	/* 32 | 64 */
-	unsigned int		registered;
-	unsigned int		present;
-	unsigned int		msi;
-
-	spinlock_t		lock;
-
-	/* API Related */
-	int		chd_dec_major;
-	unsigned int		cfg_users;
-
-	struct crystalhd_ioctl_data	*idata_free_head; /* ioctl data pool */
-	struct crystalhd_elem	*elem_pool_head; /* Queue element pool */
-
-	struct crystalhd_cmd	cmds;
-
-	struct crystalhd_dio_req	*ua_map_free_head;
-	struct pci_pool		*fill_byte_pool;
-};
-
-
-struct crystalhd_adp *chd_get_adp(void);
-void chd_set_log_level(struct crystalhd_adp *adp, char *arg);
-
-#endif
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_misc.c linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_misc.c
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_misc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_misc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1044 +0,0 @@
-/***************************************************************************
- *	   Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_misc . c
- *
- *  Description:
- *		BCM70012 Linux driver misc routines.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#include "crystalhd.h"
-
-#include <linux/slab.h>
-
-uint32_t g_linklog_level;
-
-static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp,
-					 uint32_t mem_off)
-{
-	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
-	return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
-}
-
-static inline void crystalhd_dram_wr(struct crystalhd_adp *adp,
-					 uint32_t mem_off, uint32_t val)
-{
-	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
-	bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
-}
-
-static inline enum BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp,
-					 uint32_t start_off, uint32_t cnt)
-{
-	return BC_STS_SUCCESS;
-}
-
-static struct crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
-{
-	unsigned long flags = 0;
-	struct crystalhd_dio_req *temp = NULL;
-
-	if (!adp) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return temp;
-	}
-
-	spin_lock_irqsave(&adp->lock, flags);
-	temp = adp->ua_map_free_head;
-	if (temp)
-		adp->ua_map_free_head = adp->ua_map_free_head->next;
-	spin_unlock_irqrestore(&adp->lock, flags);
-
-	return temp;
-}
-
-static void crystalhd_free_dio(struct crystalhd_adp *adp,
-					 struct crystalhd_dio_req *dio)
-{
-	unsigned long flags = 0;
-
-	if (!adp || !dio)
-		return;
-	spin_lock_irqsave(&adp->lock, flags);
-	dio->sig = crystalhd_dio_inv;
-	dio->page_cnt = 0;
-	dio->fb_size = 0;
-	memset(&dio->uinfo, 0, sizeof(dio->uinfo));
-	dio->next = adp->ua_map_free_head;
-	adp->ua_map_free_head = dio;
-	spin_unlock_irqrestore(&adp->lock, flags);
-}
-
-static struct crystalhd_elem *crystalhd_alloc_elem(struct crystalhd_adp *adp)
-{
-	unsigned long flags = 0;
-	struct crystalhd_elem *temp = NULL;
-
-	if (!adp)
-		return temp;
-	spin_lock_irqsave(&adp->lock, flags);
-	temp = adp->elem_pool_head;
-	if (temp) {
-		adp->elem_pool_head = adp->elem_pool_head->flink;
-		memset(temp, 0, sizeof(*temp));
-	}
-	spin_unlock_irqrestore(&adp->lock, flags);
-
-	return temp;
-}
-static void crystalhd_free_elem(struct crystalhd_adp *adp,
-					 struct crystalhd_elem *elem)
-{
-	unsigned long flags = 0;
-
-	if (!adp || !elem)
-		return;
-	spin_lock_irqsave(&adp->lock, flags);
-	elem->flink = adp->elem_pool_head;
-	adp->elem_pool_head = elem;
-	spin_unlock_irqrestore(&adp->lock, flags);
-}
-
-static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
-				  unsigned int len, unsigned int offset)
-{
-	sg_set_page(sg, page, len, offset);
-#ifdef CONFIG_X86_64
-	sg->dma_length = len;
-#endif
-}
-
-static inline void crystalhd_init_sg(struct scatterlist *sg,
-					 unsigned int entries)
-{
-	/* http://lkml.org/lkml/2007/11/27/68 */
-	sg_init_table(sg, entries);
-}
-
-/*========================== Extern ========================================*/
-/**
- * bc_dec_reg_rd - Read 7412's device register.
- * @adp: Adapter instance
- * @reg_off: Register offset.
- *
- * Return:
- *	32bit value read
- *
- * 7412's device register read routine. This interface use
- * 7412's device access range mapped from BAR-2 (4M) of PCIe
- * configuration space.
- */
-uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
-{
-	if (!adp || (reg_off > adp->pci_mem_len)) {
-		BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
-		return 0;
-	}
-
-	return readl(adp->addr + reg_off);
-}
-
-/**
- * bc_dec_reg_wr - Write 7412's device register
- * @adp: Adapter instance
- * @reg_off: Register offset.
- * @val: Dword value to be written.
- *
- * Return:
- *	none.
- *
- * 7412's device register write routine. This interface use
- * 7412's device access range mapped from BAR-2 (4M) of PCIe
- * configuration space.
- */
-void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
-{
-	if (!adp || (reg_off > adp->pci_mem_len)) {
-		BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
-		return;
-	}
-	writel(val, adp->addr + reg_off);
-	udelay(8);
-}
-
-/**
- * crystalhd_reg_rd - Read Link's device register.
- * @adp: Adapter instance
- * @reg_off: Register offset.
- *
- * Return:
- *	32bit value read
- *
- * Link device register  read routine. This interface use
- * Link's device access range mapped from BAR-1 (64K) of PCIe
- * configuration space.
- *
- */
-uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
-{
-	if (!adp || (reg_off > adp->pci_i2o_len)) {
-		BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
-		return 0;
-	}
-	return readl(adp->i2o_addr + reg_off);
-}
-
-/**
- * crystalhd_reg_wr - Write Link's device register
- * @adp: Adapter instance
- * @reg_off: Register offset.
- * @val: Dword value to be written.
- *
- * Return:
- *	none.
- *
- * Link device register  write routine. This interface use
- * Link's device access range mapped from BAR-1 (64K) of PCIe
- * configuration space.
- *
- */
-void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off,
-					 uint32_t val)
-{
-	if (!adp || (reg_off > adp->pci_i2o_len)) {
-		BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
-		return;
-	}
-	writel(val, adp->i2o_addr + reg_off);
-}
-
-/**
- * crystalhd_mem_rd - Read data from 7412's DRAM area.
- * @adp: Adapter instance
- * @start_off: Start offset.
- * @dw_cnt: Count in dwords.
- * @rd_buff: Buffer to copy the data from dram.
- *
- * Return:
- *	Status.
- *
- * 7412's Dram read routine.
- */
-enum BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
-			 uint32_t dw_cnt, uint32_t *rd_buff)
-{
-	uint32_t ix = 0;
-
-	if (!adp || !rd_buff ||
-	    (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-	for (ix = 0; ix < dw_cnt; ix++)
-		rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_mem_wr - Write data to 7412's DRAM area.
- * @adp: Adapter instance
- * @start_off: Start offset.
- * @dw_cnt: Count in dwords.
- * @wr_buff: Data Buffer to be written.
- *
- * Return:
- *	Status.
- *
- * 7412's Dram write routine.
- */
-enum BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
-			 uint32_t dw_cnt, uint32_t *wr_buff)
-{
-	uint32_t ix = 0;
-
-	if (!adp || !wr_buff ||
-	    (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-
-	for (ix = 0; ix < dw_cnt; ix++)
-		crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
-
-	return BC_STS_SUCCESS;
-}
-/**
- * crystalhd_pci_cfg_rd - PCIe config read
- * @adp: Adapter instance
- * @off: PCI config space offset.
- * @len: Size -- Byte, Word & dword.
- * @val: Value read
- *
- * Return:
- *	Status.
- *
- * Get value from Link's PCIe config space.
- */
-enum BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
-			     uint32_t len, uint32_t *val)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	int rc = 0;
-
-	if (!adp || !val) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-
-	switch (len) {
-	case 1:
-		rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
-		break;
-	case 2:
-		rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
-		break;
-	case 4:
-		rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
-		break;
-	default:
-		rc = -EINVAL;
-		sts = BC_STS_INV_ARG;
-		BCMLOG_ERR("Invalid len:%d\n", len);
-	}
-
-	if (rc && (sts == BC_STS_SUCCESS))
-		sts = BC_STS_ERROR;
-
-	return sts;
-}
-
-/**
- * crystalhd_pci_cfg_wr - PCIe config write
- * @adp: Adapter instance
- * @off: PCI config space offset.
- * @len: Size -- Byte, Word & dword.
- * @val: Value to be written
- *
- * Return:
- *	Status.
- *
- * Set value to Link's PCIe config space.
- */
-enum BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
-			     uint32_t len, uint32_t val)
-{
-	enum BC_STATUS sts = BC_STS_SUCCESS;
-	int rc = 0;
-
-	if (!adp || !val) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-
-	switch (len) {
-	case 1:
-		rc = pci_write_config_byte(adp->pdev, off, (u8)val);
-		break;
-	case 2:
-		rc = pci_write_config_word(adp->pdev, off, (u16)val);
-		break;
-	case 4:
-		rc = pci_write_config_dword(adp->pdev, off, val);
-		break;
-	default:
-		rc = -EINVAL;
-		sts = BC_STS_INV_ARG;
-		BCMLOG_ERR("Invalid len:%d\n", len);
-	}
-
-	if (rc && (sts == BC_STS_SUCCESS))
-		sts = BC_STS_ERROR;
-
-	return sts;
-}
-
-/**
- * bc_kern_dma_alloc - Allocate memory for Dma rings
- * @adp: Adapter instance
- * @sz: Size of the memory to allocate.
- * @phy_addr: Physical address of the memory allocated.
- *	   Typedef to system's dma_addr_t (u64)
- *
- * Return:
- *  Pointer to allocated memory..
- *
- * Wrapper to Linux kernel interface.
- *
- */
-void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
-			dma_addr_t *phy_addr)
-{
-	void *temp = NULL;
-
-	if (!adp || !sz || !phy_addr) {
-		BCMLOG_ERR("Invalid Arg..\n");
-		return temp;
-	}
-
-	temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
-	if (temp)
-		memset(temp, 0, sz);
-
-	return temp;
-}
-
-/**
- * bc_kern_dma_free - Release Dma ring memory.
- * @adp: Adapter instance
- * @sz: Size of the memory to allocate.
- * @ka: Kernel virtual address returned during _dio_alloc()
- * @phy_addr: Physical address of the memory allocated.
- *	   Typedef to system's dma_addr_t (u64)
- *
- * Return:
- *     none.
- */
-void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
-		      dma_addr_t phy_addr)
-{
-	if (!adp || !ka || !sz || !phy_addr) {
-		BCMLOG_ERR("Invalid Arg..\n");
-		return;
-	}
-
-	pci_free_consistent(adp->pdev, sz, ka, phy_addr);
-}
-
-/**
- * crystalhd_create_dioq - Create Generic DIO queue
- * @adp: Adapter instance
- * @dioq_hnd: Handle to the dio queue created
- * @cb	: Optional - Call back To free the element.
- * @cbctx: Context to pass to callback.
- *
- * Return:
- *  status
- *
- * Initialize Generic DIO queue to hold any data. Callback
- * will be used to free elements while deleting the queue.
- */
-enum BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
-			      struct crystalhd_dioq **dioq_hnd,
-			      crystalhd_data_free_cb cb, void *cbctx)
-{
-	struct crystalhd_dioq *dioq = NULL;
-
-	if (!adp || !dioq_hnd) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
-	if (!dioq)
-		return BC_STS_INSUFF_RES;
-
-	spin_lock_init(&dioq->lock);
-	dioq->sig = BC_LINK_DIOQ_SIG;
-	dioq->head = (struct crystalhd_elem *)&dioq->head;
-	dioq->tail = (struct crystalhd_elem *)&dioq->head;
-	crystalhd_create_event(&dioq->event);
-	dioq->adp = adp;
-	dioq->data_rel_cb = cb;
-	dioq->cb_context = cbctx;
-	*dioq_hnd = dioq;
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_delete_dioq - Delete Generic DIO queue
- * @adp: Adapter instance
- * @dioq: DIOQ instance..
- *
- * Return:
- *  None.
- *
- * Release Generic DIO queue. This function will remove
- * all the entries from the Queue and will release data
- * by calling the call back provided during creation.
- *
- */
-void crystalhd_delete_dioq(struct crystalhd_adp *adp,
-			 struct crystalhd_dioq *dioq)
-{
-	void *temp;
-
-	if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
-		return;
-
-	do {
-		temp = crystalhd_dioq_fetch(dioq);
-		if (temp && dioq->data_rel_cb)
-			dioq->data_rel_cb(dioq->cb_context, temp);
-	} while (temp);
-	dioq->sig = 0;
-	kfree(dioq);
-}
-
-/**
- * crystalhd_dioq_add - Add new DIO request element.
- * @ioq: DIO queue instance
- * @t: DIO request to be added.
- * @wake: True - Wake up suspended process.
- * @tag: Special tag to assign - For search and get.
- *
- * Return:
- *  Status.
- *
- * Insert new element to Q tail.
- */
-enum BC_STATUS crystalhd_dioq_add(struct crystalhd_dioq *ioq, void *data,
-			   bool wake, uint32_t tag)
-{
-	unsigned long flags = 0;
-	struct crystalhd_elem *tmp;
-
-	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	tmp = crystalhd_alloc_elem(ioq->adp);
-	if (!tmp) {
-		BCMLOG_ERR("No free elements.\n");
-		return BC_STS_INSUFF_RES;
-	}
-
-	tmp->data = data;
-	tmp->tag = tag;
-	spin_lock_irqsave(&ioq->lock, flags);
-	tmp->flink = (struct crystalhd_elem *)&ioq->head;
-	tmp->blink = ioq->tail;
-	tmp->flink->blink = tmp;
-	tmp->blink->flink = tmp;
-	ioq->count++;
-	spin_unlock_irqrestore(&ioq->lock, flags);
-
-	if (wake)
-		crystalhd_set_event(&ioq->event);
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_dioq_fetch - Fetch element from head.
- * @ioq: DIO queue instance
- *
- * Return:
- *	data element from the head..
- *
- * Remove an element from Queue.
- */
-void *crystalhd_dioq_fetch(struct crystalhd_dioq *ioq)
-{
-	unsigned long flags = 0;
-	struct crystalhd_elem *tmp;
-	struct crystalhd_elem *ret = NULL;
-	void *data = NULL;
-
-	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return data;
-	}
-
-	spin_lock_irqsave(&ioq->lock, flags);
-	tmp = ioq->head;
-	if (tmp != (struct crystalhd_elem *)&ioq->head) {
-		ret = tmp;
-		tmp->flink->blink = tmp->blink;
-		tmp->blink->flink = tmp->flink;
-		ioq->count--;
-	}
-	spin_unlock_irqrestore(&ioq->lock, flags);
-	if (ret) {
-		data = ret->data;
-		crystalhd_free_elem(ioq->adp, ret);
-	}
-
-	return data;
-}
-/**
- * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
- * @ioq: DIO queue instance
- * @tag: Tag to search for.
- *
- * Return:
- *	element from the head..
- *
- * Search TAG and remove the element.
- */
-void *crystalhd_dioq_find_and_fetch(struct crystalhd_dioq *ioq, uint32_t tag)
-{
-	unsigned long flags = 0;
-	struct crystalhd_elem *tmp;
-	struct crystalhd_elem *ret = NULL;
-	void *data = NULL;
-
-	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return data;
-	}
-
-	spin_lock_irqsave(&ioq->lock, flags);
-	tmp = ioq->head;
-	while (tmp != (struct crystalhd_elem *)&ioq->head) {
-		if (tmp->tag == tag) {
-			ret = tmp;
-			tmp->flink->blink = tmp->blink;
-			tmp->blink->flink = tmp->flink;
-			ioq->count--;
-			break;
-		}
-		tmp = tmp->flink;
-	}
-	spin_unlock_irqrestore(&ioq->lock, flags);
-
-	if (ret) {
-		data = ret->data;
-		crystalhd_free_elem(ioq->adp, ret);
-	}
-
-	return data;
-}
-
-/**
- * crystalhd_dioq_fetch_wait - Fetch element from Head.
- * @ioq: DIO queue instance
- * @to_secs: Wait timeout in seconds..
- *
- * Return:
- *	element from the head..
- *
- * Return element from head if Q is not empty. Wait for new element
- * if Q is empty for Timeout seconds.
- */
-void *crystalhd_dioq_fetch_wait(struct crystalhd_dioq *ioq, uint32_t to_secs,
-			      uint32_t *sig_pend)
-{
-	unsigned long flags = 0;
-	int rc = 0, count;
-	void *tmp = NULL;
-
-	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
-		BCMLOG_ERR("Invalid arg!!\n");
-		return tmp;
-	}
-
-	count = to_secs;
-	spin_lock_irqsave(&ioq->lock, flags);
-	while ((ioq->count == 0) && count) {
-		spin_unlock_irqrestore(&ioq->lock, flags);
-
-		crystalhd_wait_on_event(&ioq->event,
-				 (ioq->count > 0), 1000, rc, 0);
-		if (rc == 0) {
-			goto out;
-		} else if (rc == -EINTR) {
-			BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
-			*sig_pend = 1;
-			return tmp;
-		}
-		spin_lock_irqsave(&ioq->lock, flags);
-		count--;
-	}
-	spin_unlock_irqrestore(&ioq->lock, flags);
-
-out:
-	return crystalhd_dioq_fetch(ioq);
-}
-
-/**
- * crystalhd_map_dio - Map user address for DMA
- * @adp:	Adapter instance
- * @ubuff:	User buffer to map.
- * @ubuff_sz:	User buffer size.
- * @uv_offset:	UV buffer offset.
- * @en_422mode: TRUE:422 FALSE:420 Capture mode.
- * @dir_tx:	TRUE for Tx (To device from host)
- * @dio_hnd:	Handle to mapped DIO request.
- *
- * Return:
- *	Status.
- *
- * This routine maps user address and lock pages for DMA.
- *
- */
-enum BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
-			  uint32_t ubuff_sz, uint32_t uv_offset,
-			  bool en_422mode, bool dir_tx,
-			  struct crystalhd_dio_req **dio_hnd)
-{
-	struct crystalhd_dio_req	*dio;
-	/* FIXME: jarod: should some of these
-	 unsigned longs be uint32_t or uintptr_t? */
-	unsigned long start = 0, end = 0, uaddr = 0, count = 0;
-	unsigned long spsz = 0, uv_start = 0;
-	int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
-
-	if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-	/* Compute pages */
-	uaddr = (unsigned long)ubuff;
-	count = (unsigned long)ubuff_sz;
-	end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	start = uaddr >> PAGE_SHIFT;
-	nr_pages = end - start;
-
-	if (!count || ((uaddr + count) < uaddr)) {
-		BCMLOG_ERR("User addr overflow!!\n");
-		return BC_STS_INV_ARG;
-	}
-
-	dio = crystalhd_alloc_dio(adp);
-	if (!dio) {
-		BCMLOG_ERR("dio pool empty..\n");
-		return BC_STS_INSUFF_RES;
-	}
-
-	if (dir_tx) {
-		rw = WRITE;
-		dio->direction = DMA_TO_DEVICE;
-	} else {
-		rw = READ;
-		dio->direction = DMA_FROM_DEVICE;
-	}
-
-	if (nr_pages > dio->max_pages) {
-		BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
-			   dio->max_pages, nr_pages);
-		crystalhd_unmap_dio(adp, dio);
-		return BC_STS_INSUFF_RES;
-	}
-
-	if (uv_offset) {
-		uv_start = (uaddr + (unsigned long)uv_offset)  >> PAGE_SHIFT;
-		dio->uinfo.uv_sg_ix = uv_start - start;
-		dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) &
-					 ~PAGE_MASK);
-	}
-
-	dio->fb_size = ubuff_sz & 0x03;
-	if (dio->fb_size) {
-		res = copy_from_user(dio->fb_va,
-				     (void __user *)(uaddr + count - dio->fb_size),
-				     dio->fb_size);
-		if (res) {
-			BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
-				   res, dio->fb_size,
-				   (void *)(uaddr + count-dio->fb_size));
-			crystalhd_unmap_dio(adp, dio);
-			return BC_STS_INSUFF_RES;
-		}
-	}
-
-	down_read(&current->mm->mmap_sem);
-	res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
-			     0, dio->pages, NULL);
-	up_read(&current->mm->mmap_sem);
-
-	/* Save for release..*/
-	dio->sig = crystalhd_dio_locked;
-	if (res < nr_pages) {
-		BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
-		dio->page_cnt = res;
-		crystalhd_unmap_dio(adp, dio);
-		return BC_STS_ERROR;
-	}
-
-	dio->page_cnt = nr_pages;
-	/* Get scatter/gather */
-	crystalhd_init_sg(dio->sg, dio->page_cnt);
-	crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
-	if (nr_pages > 1) {
-		dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
-
-#ifdef CONFIG_X86_64
-		dio->sg[0].dma_length = dio->sg[0].length;
-#endif
-		count -= dio->sg[0].length;
-		for (i = 1; i < nr_pages; i++) {
-			if (count < 4) {
-				spsz = count;
-				skip_fb_sg = 1;
-			} else {
-				spsz = (count < PAGE_SIZE) ?
-					(count & ~0x03) : PAGE_SIZE;
-			}
-			crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
-			count -= spsz;
-		}
-	} else {
-		if (count < 4) {
-			dio->sg[0].length = count;
-			skip_fb_sg = 1;
-		} else {
-			dio->sg[0].length = count - dio->fb_size;
-		}
-#ifdef CONFIG_X86_64
-		dio->sg[0].dma_length = dio->sg[0].length;
-#endif
-	}
-	dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
-				 dio->page_cnt, dio->direction);
-	if (dio->sg_cnt <= 0) {
-		BCMLOG_ERR("sg map %d-%d\n", dio->sg_cnt, dio->page_cnt);
-		crystalhd_unmap_dio(adp, dio);
-		return BC_STS_ERROR;
-	}
-	if (dio->sg_cnt && skip_fb_sg)
-		dio->sg_cnt -= 1;
-	dio->sig = crystalhd_dio_sg_mapped;
-	/* Fill in User info.. */
-	dio->uinfo.xfr_len   = ubuff_sz;
-	dio->uinfo.xfr_buff  = ubuff;
-	dio->uinfo.uv_offset = uv_offset;
-	dio->uinfo.b422mode  = en_422mode;
-	dio->uinfo.dir_tx    = dir_tx;
-
-	*dio_hnd = dio;
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_unmap_sgl - Release mapped resources
- * @adp: Adapter instance
- * @dio: DIO request instance
- *
- * Return:
- *	Status.
- *
- * This routine is to unmap the user buffer pages.
- */
-enum BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp,
-				 struct crystalhd_dio_req *dio)
-{
-	struct page *page = NULL;
-	int j = 0;
-
-	if (!adp || !dio) {
-		BCMLOG_ERR("Invalid arg\n");
-		return BC_STS_INV_ARG;
-	}
-
-	if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
-		for (j = 0; j < dio->page_cnt; j++) {
-			page = dio->pages[j];
-			if (page) {
-				if (!PageReserved(page) &&
-				    (dio->direction == DMA_FROM_DEVICE))
-					SetPageDirty(page);
-				page_cache_release(page);
-			}
-		}
-	}
-	if (dio->sig == crystalhd_dio_sg_mapped)
-		pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt,
-			 dio->direction);
-
-	crystalhd_free_dio(adp, dio);
-
-	return BC_STS_SUCCESS;
-}
-
-/**
- * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
- * @adp: Adapter instance
- * @max_pages: Max pages for size calculation.
- *
- * Return:
- *	system error.
- *
- * This routine creates a memory pool to hold dio context for
- * for HW Direct IO operation.
- */
-int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
-{
-	uint32_t asz = 0, i = 0;
-	uint8_t	*temp;
-	struct crystalhd_dio_req *dio;
-
-	if (!adp || !max_pages) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return -EINVAL;
-	}
-
-	/* Get dma memory for fill byte handling..*/
-	adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
-					      adp->pdev, 8, 8, 0);
-	if (!adp->fill_byte_pool) {
-		BCMLOG_ERR("failed to create fill byte pool\n");
-		return -ENOMEM;
-	}
-
-	/* Get the max size from user based on 420/422 modes */
-	asz =  (sizeof(*dio->pages) * max_pages) +
-	       (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
-
-	BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
-	       BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
-
-	for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
-		temp = kzalloc(asz, GFP_KERNEL);
-		if ((temp) == NULL) {
-			BCMLOG_ERR("Failed to alloc %d mem\n", asz);
-			return -ENOMEM;
-		}
-
-		dio = (struct crystalhd_dio_req *)temp;
-		temp += sizeof(*dio);
-		dio->pages = (struct page **)temp;
-		temp += (sizeof(*dio->pages) * max_pages);
-		dio->sg = (struct scatterlist *)temp;
-		dio->max_pages = max_pages;
-		dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
-					    &dio->fb_pa);
-		if (!dio->fb_va) {
-			BCMLOG_ERR("fill byte alloc failed.\n");
-			return -ENOMEM;
-		}
-
-		crystalhd_free_dio(adp, dio);
-	}
-
-	return 0;
-}
-
-/**
- * crystalhd_destroy_dio_pool - Release DIO mem pool.
- * @adp: Adapter instance
- *
- * Return:
- *	none.
- *
- * This routine releases dio memory pool during close.
- */
-void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
-{
-	struct crystalhd_dio_req *dio;
-	int count = 0;
-
-	if (!adp) {
-		BCMLOG_ERR("Invalid Arg!!\n");
-		return;
-	}
-
-	do {
-		dio = crystalhd_alloc_dio(adp);
-		if (dio) {
-			if (dio->fb_va)
-				pci_pool_free(adp->fill_byte_pool,
-					      dio->fb_va, dio->fb_pa);
-			count++;
-			kfree(dio);
-		}
-	} while (dio);
-
-	if (adp->fill_byte_pool) {
-		pci_pool_destroy(adp->fill_byte_pool);
-		adp->fill_byte_pool = NULL;
-	}
-
-	BCMLOG(BCMLOG_DBG, "Released dio pool %d\n", count);
-}
-
-/**
- * crystalhd_create_elem_pool - List element pool creation.
- * @adp: Adapter instance
- * @pool_size: Number of elements in the pool.
- *
- * Return:
- *	0 - success, <0 error
- *
- * Create general purpose list element pool to hold pending,
- * and active requests.
- */
-int crystalhd_create_elem_pool(struct crystalhd_adp *adp,
-		uint32_t pool_size)
-{
-	uint32_t i;
-	struct crystalhd_elem *temp;
-
-	if (!adp || !pool_size)
-		return -EINVAL;
-
-	for (i = 0; i < pool_size; i++) {
-		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
-		if (!temp) {
-			BCMLOG_ERR("kalloc failed\n");
-			return -ENOMEM;
-		}
-		crystalhd_free_elem(adp, temp);
-	}
-	BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
-	return 0;
-}
-
-/**
- * crystalhd_delete_elem_pool - List element pool deletion.
- * @adp: Adapter instance
- *
- * Return:
- *	none
- *
- * Delete general purpose list element pool.
- */
-void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
-{
-	struct crystalhd_elem *temp;
-	int dbg_cnt = 0;
-
-	if (!adp)
-		return;
-
-	do {
-		temp = crystalhd_alloc_elem(adp);
-		if (temp) {
-			kfree(temp);
-			dbg_cnt++;
-		}
-	} while (temp);
-
-	BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
-}
-
-/*================ Debug support routines.. ================================*/
-void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
-{
-	uint32_t i, k = 1;
-
-	for (i = 0; i < dwcount; i++) {
-		if (k == 1)
-			BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
-
-		BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
-
-		buff += sizeof(uint32_t);
-		off  += sizeof(uint32_t);
-		k++;
-		if ((i == dwcount - 1) || (k > 4)) {
-			BCMLOG(BCMLOG_DATA, "\n");
-			k = 1;
-		}
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_misc.h linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_misc.h
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/crystalhd_misc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/crystalhd_misc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2005-2009, Broadcom Corporation.
- *
- *  Name: crystalhd_misc . h
- *
- *  Description:
- *		BCM70012 Linux driver general purpose routines.
- *		Includes reg/mem read and write routines.
- *
- *  HISTORY:
- *
- **********************************************************************
- * This file is part of the crystalhd device driver.
- *
- * This driver is free software; 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 driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
- **********************************************************************/
-
-#ifndef _CRYSTALHD_MISC_H_
-#define _CRYSTALHD_MISC_H_
-
-#include "crystalhd.h"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ioctl.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-#include "bc_dts_glob_lnx.h"
-
-/* Global log level variable defined in crystal_misc.c file */
-extern uint32_t g_linklog_level;
-
-/* Global element pool for all Queue management.
- * TX: Active = BC_TX_LIST_CNT, Free = BC_TX_LIST_CNT.
- * RX: Free = BC_RX_LIST_CNT, Active = 2
- * FW-CMD: 4
- */
-#define	BC_LINK_ELEM_POOL_SZ	((BC_TX_LIST_CNT * 2) + BC_RX_LIST_CNT + 2 + 4)
-
-/* Driver's IODATA pool count */
-#define	CHD_IODATA_POOL_SZ    (BC_IOCTL_DATA_POOL_SIZE * BC_LINK_MAX_OPENS)
-
-/* Scatter Gather memory pool size for Tx and Rx */
-#define BC_LINK_SG_POOL_SZ    (BC_TX_LIST_CNT + BC_RX_LIST_CNT)
-
-enum crystalhd_dio_sig {
-	crystalhd_dio_inv = 0,
-	crystalhd_dio_locked,
-	crystalhd_dio_sg_mapped,
-};
-
-struct crystalhd_dio_user_info {
-	void			*xfr_buff;
-	uint32_t		xfr_len;
-	uint32_t		uv_offset;
-	bool			dir_tx;
-
-	uint32_t		uv_sg_ix;
-	uint32_t		uv_sg_off;
-	int			comp_sts;
-	int			ev_sts;
-	uint32_t		y_done_sz;
-	uint32_t		uv_done_sz;
-	uint32_t		comp_flags;
-	bool			b422mode;
-};
-
-struct crystalhd_dio_req {
-	uint32_t			sig;
-	uint32_t			max_pages;
-	struct page			**pages;
-	struct scatterlist		*sg;
-	int				sg_cnt;
-	int				page_cnt;
-	int				direction;
-	struct crystalhd_dio_user_info	uinfo;
-	void				*fb_va;
-	uint32_t			fb_size;
-	dma_addr_t			fb_pa;
-	struct crystalhd_dio_req	*next;
-};
-
-#define BC_LINK_DIOQ_SIG	(0x09223280)
-
-struct crystalhd_elem {
-	struct crystalhd_elem	*flink;
-	struct crystalhd_elem	*blink;
-	void			*data;
-	uint32_t		tag;
-};
-
-typedef void (*crystalhd_data_free_cb)(void *context, void *data);
-
-struct crystalhd_dioq {
-	uint32_t		sig;
-	struct crystalhd_adp	*adp;
-	struct crystalhd_elem		*head;
-	struct crystalhd_elem		*tail;
-	uint32_t		count;
-	spinlock_t		lock;
-	wait_queue_head_t	event;
-	crystalhd_data_free_cb	data_rel_cb;
-	void			*cb_context;
-};
-
-typedef void (*hw_comp_callback)(struct crystalhd_dio_req *,
-				 wait_queue_head_t *event, enum BC_STATUS sts);
-
-/*========= Decoder (7412) register access routines.================= */
-uint32_t bc_dec_reg_rd(struct crystalhd_adp *, uint32_t);
-void bc_dec_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
-
-/*========= Link (70012) register access routines.. =================*/
-uint32_t crystalhd_reg_rd(struct crystalhd_adp *, uint32_t);
-void crystalhd_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
-
-/*========= Decoder (7412) memory access routines..=================*/
-enum BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *,
-			 uint32_t, uint32_t, uint32_t *);
-enum BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *,
-			 uint32_t, uint32_t, uint32_t *);
-
-/*==========Link (70012) PCIe Config access routines.================*/
-enum BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *,
-			 uint32_t, uint32_t, uint32_t *);
-enum BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *,
-			 uint32_t, uint32_t, uint32_t);
-
-/*========= Linux Kernel Interface routines. ======================= */
-void *bc_kern_dma_alloc(struct crystalhd_adp *, uint32_t, dma_addr_t *);
-void bc_kern_dma_free(struct crystalhd_adp *, uint32_t,
-		      void *, dma_addr_t);
-#define crystalhd_create_event(_ev)	init_waitqueue_head(_ev)
-#define crystalhd_set_event(_ev)		wake_up_interruptible(_ev)
-#define crystalhd_wait_on_event(ev, condition, timeout, ret, nosig)	\
-do {									\
-	DECLARE_WAITQUEUE(entry, current);				\
-	unsigned long end = jiffies + ((timeout * HZ) / 1000);		\
-		ret = 0;						\
-	add_wait_queue(ev, &entry);					\
-	for (;;) {							\
-		__set_current_state(TASK_INTERRUPTIBLE);		\
-		if (condition) {					\
-			break;						\
-		}							\
-		if (time_after_eq(jiffies, end)) {			\
-			ret = -EBUSY;					\
-			break;						\
-		}							\
-		schedule_timeout((HZ / 100 > 1) ? HZ / 100 : 1);	\
-		if (!nosig && signal_pending(current)) {		\
-			ret = -EINTR;					\
-			break;						\
-		}							\
-	}								\
-	__set_current_state(TASK_RUNNING);				\
-	remove_wait_queue(ev, &entry);					\
-} while (0)
-
-/*================ Direct IO mapping routines ==================*/
-extern int crystalhd_create_dio_pool(struct crystalhd_adp *, uint32_t);
-extern void crystalhd_destroy_dio_pool(struct crystalhd_adp *);
-extern enum BC_STATUS crystalhd_map_dio(struct crystalhd_adp *, void *,
-		 uint32_t, uint32_t, bool, bool, struct crystalhd_dio_req**);
-
-extern enum BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *,
-					 struct crystalhd_dio_req*);
-#define crystalhd_get_sgle_paddr(_dio, _ix) (sg_dma_address(&_dio->sg[_ix]))
-#define crystalhd_get_sgle_len(_dio, _ix) (sg_dma_len(&_dio->sg[_ix]))
-
-/*================ General Purpose Queues ==================*/
-extern enum BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *,
-		 struct crystalhd_dioq **, crystalhd_data_free_cb , void *);
-extern void crystalhd_delete_dioq(struct crystalhd_adp *,
-		 struct crystalhd_dioq *);
-extern enum BC_STATUS crystalhd_dioq_add(struct crystalhd_dioq *ioq,
-		 void *data, bool wake, uint32_t tag);
-extern void *crystalhd_dioq_fetch(struct crystalhd_dioq *ioq);
-extern void *crystalhd_dioq_find_and_fetch(struct crystalhd_dioq *ioq,
-		 uint32_t tag);
-extern void *crystalhd_dioq_fetch_wait(struct crystalhd_dioq *ioq,
-		 uint32_t to_secs, uint32_t *sig_pend);
-
-#define crystalhd_dioq_count(_ioq)	((_ioq) ? _ioq->count : 0)
-
-extern int crystalhd_create_elem_pool(struct crystalhd_adp *, uint32_t);
-extern void crystalhd_delete_elem_pool(struct crystalhd_adp *);
-
-
-/*================ Debug routines/macros .. ================================*/
-extern void crystalhd_show_buffer(uint32_t off, uint8_t *buff,
-		 uint32_t dwcount);
-
-enum _chd_log_levels {
-	BCMLOG_ERROR		= 0x80000000,	/* Don't disable this option */
-	BCMLOG_DATA		= 0x40000000,	/* Data, enable by default */
-	BCMLOG_SPINLOCK		= 0x20000000,	/* Special case for Spin locks*/
-
-	/* Following are allowed only in debug mode */
-	BCMLOG_INFO		= 0x00000001,	/* Generic informational */
-	BCMLOG_DBG		= 0x00000002,	/* First level Debug info */
-	BCMLOG_SSTEP		= 0x00000004,	/* Stepping information */
-};
-
-
-#define BCMLOG(trace, fmt, args...)	\
-do {					\
-	if (g_linklog_level & trace)	\
-		printk(fmt, ##args);	\
-} while (0)
-
-
-#define BCMLOG_ERR(fmt, args...)				\
-do {								\
-	if (g_linklog_level & BCMLOG_ERROR)			\
-		pr_err("*ERR*:%s:%d: "fmt,			\
-				__FILE__, __LINE__, ##args);	\
-} while (0)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-config CRYSTALHD
-	tristate "Broadcom Crystal HD video decoder support"
-	depends on PCI
-	default n
-	help
-	  Support for the Broadcom Crystal HD video decoder chipset
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/Makefile
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-obj-$(CONFIG_CRYSTALHD)	+= crystalhd.o
-
-crystalhd-y		:= crystalhd_cmds.o	\
-			   crystalhd_hw.o	\
-			   crystalhd_lnx.o	\
-			   crystalhd_misc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/crystalhd/TODO linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/TODO
--- linux-libre-3.16-gnu/drivers/staging/crystalhd/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/crystalhd/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-- Testing
-- Cleanup return codes
-- Cleanup typedefs
-- Allocate an Accelerator device class specific Major number,
-  since we don't have any other open sourced accelerators, it is the only
-  one in that category for now.
-  A somewhat similar device is the DXR2/3
-
-Please send patches to:
-Greg Kroah-Hartman <greg@kroah.com>
-Naren Sankar <nsankar@broadcom.com>
-Jarod Wilson <jarod@wilsonet.com>
-Scott Davilla <davilla@4pi.com>
-Manu Abraham <abraham.manu@gmail.com>
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,596 +0,0 @@
-/* Copyright (C) 2003-2005  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/io.h>
-#include <linux/hdlc.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4.h"
-#include "comet.h"
-#include "comet_tables.h"
-
-
-#define COMET_NUM_SAMPLES   24  /* Number of entries in the waveform table */
-#define COMET_NUM_UNITS     5   /* Number of points per entry in table */
-
-/* forward references */
-static void SetPwrLevel(struct s_comet_reg *comet);
-static void WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet,
-				u_int32_t *table);
-static void WrtXmtWaveformTbl(ci_t *ci, struct s_comet_reg *comet,
-				u_int8_t table[COMET_NUM_SAMPLES]
-				[COMET_NUM_UNITS]);
-
-
-static void *TWV_table[12] = {
-	TWVLongHaul0DB, TWVLongHaul7_5DB, TWVLongHaul15DB, TWVLongHaul22_5DB,
-	TWVShortHaul0, TWVShortHaul1, TWVShortHaul2, TWVShortHaul3,
-	TWVShortHaul4, TWVShortHaul5,
-	/** PORT POINT - 75 Ohm not supported **/
-	TWV_E1_75Ohm,
-	TWV_E1_120Ohm
-};
-
-
-static int
-lbo_tbl_lkup(int t1, int lbo) {
-	/* error switches to default */
-	if ((lbo < CFG_LBO_LH0) || (lbo > CFG_LBO_E120)) {
-		if (t1)
-			/* default T1 waveform table */
-			lbo = CFG_LBO_LH0;
-
-		else
-			/* default E1 waveform table */
-			lbo = CFG_LBO_E120;
-	}
-	/* make index ZERO relative */
-	return lbo - 1;
-}
-
-void init_comet(void *ci, struct s_comet_reg *comet, u_int32_t port_mode,
-		int clockmaster, u_int8_t moreParams)
-{
-	u_int8_t isT1mode;
-	/* T1 default */
-	u_int8_t    tix = CFG_LBO_LH0;
-	isT1mode = IS_FRAME_ANY_T1(port_mode);
-	/* T1 or E1 */
-	if (isT1mode) {
-		/* Select T1 Mode & PIO output enabled */
-		pci_write_32((u_int32_t *) &comet->gbl_cfg, 0xa0);
-		/* default T1 waveform table */
-		tix = lbo_tbl_lkup(isT1mode, CFG_LBO_LH0);
-	} else {
-		/* Select E1 Mode & PIO output enabled */
-		pci_write_32((u_int32_t *) &comet->gbl_cfg, 0x81);
-		/* default E1 waveform table */
-		tix = lbo_tbl_lkup(isT1mode, CFG_LBO_E120);
-	}
-
-	if (moreParams & CFG_LBO_MASK)
-		/* dial-in requested waveform table */
-		tix = lbo_tbl_lkup(isT1mode, moreParams & CFG_LBO_MASK);
-	/* Tx line Intfc cfg Set for analog & no special patterns */
-	/* Transmit Line Interface Config. */
-	pci_write_32((u_int32_t *) &comet->tx_line_cfg, 0x00);
-	/* master test Ignore Test settings for now */
-	/* making sure it's Default value */
-	pci_write_32((u_int32_t *) &comet->mtest, 0x00);
-	/* Turn on Center (CENT) and everything else off */
-	/* RJAT cfg */
-	pci_write_32((u_int32_t *) &comet->rjat_cfg, 0x10);
-	/* Set Jitter Attenuation to recommend T1 values */
-	if (isT1mode) {
-		/* RJAT Divider N1 Control */
-		pci_write_32((u_int32_t *) &comet->rjat_n1clk, 0x2F);
-		/* RJAT Divider N2 Control */
-		pci_write_32((u_int32_t *) &comet->rjat_n2clk, 0x2F);
-	} else {
-		/* RJAT Divider N1 Control */
-		pci_write_32((u_int32_t *) &comet->rjat_n1clk, 0xFF);
-		/* RJAT Divider N2 Control */
-		pci_write_32((u_int32_t *) &comet->rjat_n2clk, 0xFF);
-	}
-
-	/* Turn on Center (CENT) and everything else off */
-	/* TJAT Config. */
-	pci_write_32((u_int32_t *) &comet->tjat_cfg, 0x10);
-
-	/* Do not bypass jitter attenuation and bypass elastic store */
-	/* rx opts */
-	pci_write_32((u_int32_t *) &comet->rx_opt, 0x00);
-
-	/* TJAT ctrl & TJAT divider ctrl */
-	/* Set Jitter Attenuation to recommended T1 values */
-	if (isT1mode) {
-		/* TJAT Divider N1 Control */
-		pci_write_32((u_int32_t *) &comet->tjat_n1clk, 0x2F);
-		/* TJAT Divider N2  Control */
-		pci_write_32((u_int32_t *) &comet->tjat_n2clk, 0x2F);
-	} else {
-		/* TJAT Divider N1 Control */
-		pci_write_32((u_int32_t *) &comet->tjat_n1clk, 0xFF);
-		/* TJAT Divider N2 Control */
-		pci_write_32((u_int32_t *) &comet->tjat_n2clk, 0xFF);
-	}
-
-	/* 1c: rx ELST cfg   20: tx ELST cfg  28&38: rx&tx data link ctrl */
-
-	/* Select 193-bit frame format */
-	if (isT1mode) {
-		pci_write_32((u_int32_t *) &comet->rx_elst_cfg, 0x00);
-		pci_write_32((u_int32_t *) &comet->tx_elst_cfg, 0x00);
-	} else {
-		/* Select 256-bit frame format */
-		pci_write_32((u_int32_t *) &comet->rx_elst_cfg, 0x03);
-		pci_write_32((u_int32_t *) &comet->tx_elst_cfg, 0x03);
-		/* disable T1 data link receive */
-		pci_write_32((u_int32_t *) &comet->rxce1_ctl, 0x00);
-		/* disable T1 data link transmit */
-		pci_write_32((u_int32_t *) &comet->txci1_ctl, 0x00);
-	}
-
-    /* the following is a default value */
-    /* Enable 8 out of 10 validation */
-	 /* t1RBOC enable(BOC:BitOriented Code) */
-	pci_write_32((u_int32_t *) &comet->t1_rboc_ena, 0x00);
-	if (isT1mode) {
-		/* IBCD cfg: aka Inband Code Detection ** loopback code length
-		 * set to
-		 */
-		/* 6 bit down, 5 bit up (assert) */
-		pci_write_32((u_int32_t *) &comet->ibcd_cfg, 0x04);
-		/* line loopback activate pattern */
-		pci_write_32((u_int32_t *) &comet->ibcd_act, 0x08);
-		/* deactivate code pattern (i.e.001) */
-		pci_write_32((u_int32_t *) &comet->ibcd_deact, 0x24);
-	}
-    /* 10: CDRC cfg 28&38: rx&tx data link 1 ctrl 48: t1 frmr cfg  */
-    /* 50: SIGX cfg, COSS (change of signaling state) 54: XBAS cfg  */
-    /* 60: t1 ALMI cfg */
-    /* Configure Line Coding */
-
-	switch (port_mode) {
-	/* 1 - T1 B8ZS */
-	case CFG_FRAME_SF:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->t1_frmr_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		/* 5:B8ZS */
-		pci_write_32((u_int32_t *) &comet->t1_xbas_cfg, 0x20);
-		pci_write_32((u_int32_t *) &comet->t1_almi_cfg, 0);
-		break;
-	/* 2 - T1 B8ZS */
-	case CFG_FRAME_ESF:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		/* Bit 5: T1 DataLink Enable */
-		pci_write_32((u_int32_t *) &comet->rxce1_ctl, 0x20);
-		/* 5: T1 DataLink Enable */
-		pci_write_32((u_int32_t *) &comet->txci1_ctl, 0x20);
-		/* 4:ESF  5:ESFFA */
-		pci_write_32((u_int32_t *) &comet->t1_frmr_cfg, 0x30);
-		/* 2:ESF */
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0x04);
-		/* 4:ESF  5:B8ZS */
-		pci_write_32((u_int32_t *) &comet->t1_xbas_cfg, 0x30);
-		/* 4:ESF */
-		pci_write_32((u_int32_t *) &comet->t1_almi_cfg, 0x10);
-		break;
-	/* 3 - HDB3 */
-	case CFG_FRAME_E1PLAIN:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0x40);
-		break;
-	/* 4 - HDB3 */
-	case CFG_FRAME_E1CAS:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0x60);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0);
-		break;
-	/* 5 - HDB3 */
-	case CFG_FRAME_E1CRC:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0x10);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0xc2);
-		break;
-	/* 6 - HDB3 */
-	case CFG_FRAME_E1CRC_CAS:
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0x70);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0x82);
-		break;
-	/* 7 - T1 AMI */
-	case CFG_FRAME_SF_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->t1_frmr_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->t1_xbas_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->t1_almi_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		break;
-	/* 8 - T1 AMI */
-	case CFG_FRAME_ESF_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		/* 5: T1 DataLink Enable */
-		pci_write_32((u_int32_t *) &comet->rxce1_ctl, 0x20);
-		/* 5: T1 DataLink Enable */
-		pci_write_32((u_int32_t *) &comet->txci1_ctl, 0x20);
-		/* Bit 4:ESF  5:ESFFA */
-		pci_write_32((u_int32_t *) &comet->t1_frmr_cfg, 0x30);
-		/* 2:ESF */
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0x04);
-		/* 4:ESF */
-		pci_write_32((u_int32_t *) &comet->t1_xbas_cfg, 0x10);
-		/* 4:ESF */
-		pci_write_32((u_int32_t *) &comet->t1_almi_cfg, 0x10);
-		break;
-	/* 9 - AMI */
-	case CFG_FRAME_E1PLAIN_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0x40);
-		break;
-	/* 10 - AMI */
-	case CFG_FRAME_E1CAS_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0xe0);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0);
-		break;
-	/* 11 - AMI */
-	case CFG_FRAME_E1CRC_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0x90);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0xc2);
-		break;
-	/* 12 - AMI */
-	case CFG_FRAME_E1CRC_CAS_AMI:
-		/* Enable AMI Line Decoding */
-		pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0x80);
-		pci_write_32((u_int32_t *) &comet->sigx_cfg, 0);
-		pci_write_32((u_int32_t *) &comet->e1_tran_cfg, 0xf0);
-		pci_write_32((u_int32_t *) &comet->e1_frmr_aopts, 0x82);
-		break;
-	}	/* end switch */
-
-    /***
-     * Set Full Frame mode (NXDSO[1] = 0, NXDSO[0] = 0)
-     * CMODE=1: Clock slave mode with BRCLK as an input,
-     * DE=0: Use falling edge of BRCLK for data,
-     * FE=0: Use falling edge of BRCLK for frame,
-     * CMS=0: Use backplane freq,
-     * RATE[1:0]=0,0: T1
-     ***/
-
-
-    /* 0x30: "BRIF cfg"; 0x20 is 'CMODE', 0x03 is (bit) rate */
-    /* note "rate bits can only be set once after reset" */
-	if (clockmaster) {
-		/* CMODE == clockMode, 0=clock master
-		 * (so all 3 others should be slave)
-		 */
-		/* rate = 1.544 Mb/s */
-		if (isT1mode)
-			/* Comet 0 Master Mode(CMODE=0) */
-			pci_write_32((u_int32_t *) &comet->brif_cfg, 0x00);
-		/* rate = 2.048 Mb/s */
-		else
-			/* Comet 0 Master Mode(CMODE=0) */
-			pci_write_32((u_int32_t *) &comet->brif_cfg, 0x01);
-
-		/* 31: BRIF frame pulse cfg  06: tx timing options */
-
-		/* Master Mode i.e.FPMODE=0 (@0x20) */
-		pci_write_32((u_int32_t *) &comet->brif_fpcfg, 0x00);
-		if ((moreParams & CFG_CLK_PORT_MASK) == CFG_CLK_PORT_INTERNAL) {
-			if (cxt1e1_log_level >= LOG_SBEBUG12)
-				pr_info(">> %s: clockmaster internal clock\n",
-					__func__);
-			/* internal oscillator */
-			pci_write_32((u_int32_t *) &comet->tx_time, 0x0d);
-		} else {
-			/* external clock source */
-			if (cxt1e1_log_level >= LOG_SBEBUG12)
-				pr_info(">> %s: clockmaster external clock\n",
-					__func__);
-			/* loop timing(external) */
-			pci_write_32((u_int32_t *) &comet->tx_time, 0x09);
-		}
-
-	} else  {
-		/* slave */
-		if (isT1mode)
-			/* Slave Mode(CMODE=1, see above) */
-			pci_write_32((u_int32_t *) &comet->brif_cfg, 0x20);
-		else
-			/* Slave Mode(CMODE=1)*/
-			pci_write_32((u_int32_t *) &comet->brif_cfg, 0x21);
-		/* Slave Mode i.e. FPMODE=1 (@0x20) */
-		pci_write_32((u_int32_t *) &comet->brif_fpcfg, 0x20);
-	if (cxt1e1_log_level >= LOG_SBEBUG12)
-		pr_info(">> %s: clockslave internal clock\n", __func__);
-	/* oscillator timing */
-	pci_write_32((u_int32_t *) &comet->tx_time, 0x0d);
-	}
-
-	/* 32: BRIF parity F-bit cfg */
-	/* Totem-pole operation */
-	/* Receive Backplane Parity/F-bit */
-	pci_write_32((u_int32_t *) &comet->brif_pfcfg, 0x01);
-
-    /* dc: RLPS equalizer V ref */
-    /* Configuration */
-	if (isT1mode)
-		/* RLPS Equalizer Voltage  */
-		pci_write_32((u_int32_t *) &comet->rlps_eqvr, 0x2c);
-	else
-		/* RLPS Equalizer Voltage  */
-		pci_write_32((u_int32_t *) &comet->rlps_eqvr, 0x34);
-
-    /* Reserved bit set and SQUELCH enabled */
-    /* f8: RLPS cfg & status  f9: RLPS ALOS detect/clear threshold */
-	/* RLPS Configuration Status */
-	pci_write_32((u_int32_t *) &comet->rlps_cfgsts, 0x11);
-	if (isT1mode)
-		/* ? */
-		pci_write_32((u_int32_t *) &comet->rlps_alos_thresh, 0x55);
-	else
-		/* ? */
-		pci_write_32((u_int32_t *) &comet->rlps_alos_thresh, 0x22);
-
-
-    /* Set Full Frame mode (NXDSO[1] = 0, NXDSO[0] = 0) */
-    /* CMODE=0: Clock slave mode with BTCLK as an input, DE=1: Use rising */
-    /* edge of BTCLK for data, FE=1: Use rising edge of BTCLK for frame, */
-    /* CMS=0: Use backplane freq, RATE[1:0]=0,0: T1 */
-    /***    Transmit side is always an Input, Slave Clock*/
-    /* 40: BTIF cfg  41: loop timing(external) */
-	/*BTIF frame pulse cfg */
-	if (isT1mode)
-		/* BTIF Configuration  Reg. */
-		pci_write_32((u_int32_t *) &comet->btif_cfg, 0x38);
-	else
-		/* BTIF Configuration  Reg. */
-		pci_write_32((u_int32_t *) &comet->btif_cfg, 0x39);
-	/* BTIF Frame Pulse Config. */
-	pci_write_32((u_int32_t *) &comet->btif_fpcfg, 0x01);
-
-    /* 0a: master diag  06: tx timing options */
-    /* if set Comet to loop back */
-
-    /* Comets set to normal */
-	pci_write_32((u_int32_t *) &comet->mdiag, 0x00);
-
-    /* BTCLK driven by TCLKI internally (crystal driven) and Xmt Elasted  */
-    /* Store is enabled. */
-
-	WrtXmtWaveformTbl(ci, comet, TWV_table[tix]);
-	if (isT1mode)
-		WrtRcvEqualizerTbl((ci_t *) ci, comet, &T1_Equalizer[0]);
-	else
-		WrtRcvEqualizerTbl((ci_t *) ci, comet, &E1_Equalizer[0]);
-	SetPwrLevel(comet);
-}
-
-/*
-** Name:        WrtXmtWaveform
-** Description: Formulate the Data for the Pulse Waveform Storage
-**                Write register, (F2), from the sample and unit inputs.
-**                Write the data to the Pulse Waveform Storage Data register.
-** Returns:     Nothing
-*/
-static void
-WrtXmtWaveform(ci_t *ci, struct s_comet_reg *comet, u_int32_t sample,
-		u_int32_t unit, u_int8_t data)
-{
-	u_int8_t    WaveformAddr;
-
-	WaveformAddr = (sample << 3) + (unit & 7);
-	pci_write_32((u_int32_t *) &comet->xlpg_pwave_addr, WaveformAddr);
-	/* for write order preservation when Optimizing driver */
-	pci_flush_write(ci);
-	pci_write_32((u_int32_t *) &comet->xlpg_pwave_data, 0x7F & data);
-}
-
-/*
-** Name:        WrtXmtWaveformTbl
-** Description: Fill in the Transmit Waveform Values
-**                for driving the transmitter DAC.
-** Returns:     Nothing
-*/
-static void
-WrtXmtWaveformTbl(ci_t *ci, struct s_comet_reg *comet,
-		  u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS])
-{
-	u_int32_t sample, unit;
-
-	for (sample = 0; sample < COMET_NUM_SAMPLES; sample++) {
-		for (unit = 0; unit < COMET_NUM_UNITS; unit++)
-			WrtXmtWaveform(ci, comet, sample, unit,
-					table[sample][unit]);
-		}
-
-    /* Enable transmitter and set output amplitude */
-	pci_write_32((u_int32_t *) &comet->xlpg_cfg,
-			table[COMET_NUM_SAMPLES][0]);
-}
-
-
-/*
-** Name:        WrtXmtWaveform
-** Description: Fill in the Receive Equalizer RAM from the desired
-**                table.
-** Returns:     Nothing
-**
-** Remarks:  Per PM4351 Device Errata, Receive Equalizer RAM Initialization
-**           is coded with early setup of indirect address.
-*/
-
-static void
-WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table)
-{
-	u_int32_t   ramaddr;
-	u_int32_t value;
-
-	for (ramaddr = 0; ramaddr < 256; ramaddr++) {
-		/*** the following lines are per Errata 7, 2.5 ***/
-		{
-		/* Set up for a read operation */
-		pci_write_32((u_int32_t *) &comet->rlps_eq_rwsel, 0x80);
-		/* for write order preservation when Optimizing driver */
-		pci_flush_write(ci);
-		/* write the addr, initiate a read */
-		pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr,
-				(u_int8_t) ramaddr);
-		/* for write order preservation when Optimizing driver */
-		pci_flush_write(ci);
-		/*
-		* wait 3 line rate clock cycles to ensure address bits are
-		* captured by T1/E1 clock
-		*/
-
-		/* 683ns * 3 = 1366 ns, approx 2us (but use 4us) */
-		OS_uwait(4, "wret");
-	}
-
-	value = *table++;
-	pci_write_32((u_int32_t *) &comet->rlps_idata3,
-			(u_int8_t) (value >> 24));
-	pci_write_32((u_int32_t *) &comet->rlps_idata2,
-			(u_int8_t) (value >> 16));
-	pci_write_32((u_int32_t *) &comet->rlps_idata1,
-			(u_int8_t) (value >> 8));
-	pci_write_32((u_int32_t *) &comet->rlps_idata0, (u_int8_t) value);
-	 /* for write order preservation when Optimizing driver */
-	pci_flush_write(ci);
-
-	/* Storing RAM address, causes RAM to be updated */
-
-		/* Set up for a write operation */
-		pci_write_32((u_int32_t *) &comet->rlps_eq_rwsel, 0);
-		/* for write order preservation when optimizing driver */
-		pci_flush_write(ci);
-		/* write the addr, initiate a read */
-		pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr,
-				(u_int8_t) ramaddr);
-		 /* for write order preservation when optimizing driver */
-		pci_flush_write(ci);
-
-	/*
-	* wait 3 line rate clock cycles to ensure address bits are captured
-	* by T1/E1 clock
-	*/
-		/* 683ns * 3 = 1366 ns, approx 2us (but use 4us) */
-		OS_uwait(4, "wret");
-	}
-
-	/* Enable Equalizer & set it to use 256 periods */
-	pci_write_32((u_int32_t *) &comet->rlps_eq_cfg, 0xCB);
-}
-
-
-/*
-** Name:        SetPwrLevel
-** Description: Implement power level setting algorithm described below
-** Returns:     Nothing
-*/
-
-static void
-SetPwrLevel(struct s_comet_reg *comet)
-{
-	u_int32_t temp;
-
-/*
-**    Algorithm to Balance the Power Distribution of Ttip Tring
-**
-**    Zero register F6
-**    Write 0x01 to register F4
-**    Write another 0x01 to register F4
-**    Read register F4
-**    Remove the 0x01 bit by Anding register F4 with 0xFE
-**    Write the resultant value to register F4
-**    Repeat these steps for register F5
-**    Write 0x01 to register F6
-*/
-	/* XLPG Fuse Data Select */
-	pci_write_32((u_int32_t *) &comet->xlpg_fdata_sel, 0x00);
-	/* XLPG Analog Test Positive control */
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_pctl, 0x01);
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_pctl, 0x01);
-	temp = pci_read_32((u_int32_t *) &comet->xlpg_atest_pctl) & 0xfe;
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_pctl, temp);
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_nctl, 0x01);
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_nctl, 0x01);
-	/* XLPG Analog Test Negative control */
-	temp = pci_read_32((u_int32_t *) &comet->xlpg_atest_nctl) & 0xfe;
-	pci_write_32((u_int32_t *) &comet->xlpg_atest_nctl, temp);
-	/* XLPG */
-	pci_write_32((u_int32_t *) &comet->xlpg_fdata_sel, 0x01);
-}
-
-
-/*
-** Name:        SetCometOps
-** Description: Set up the selected Comet's clock edge drive for both
-**                the transmit out the analog side and receive to the
-**                backplane side.
-** Returns:     Nothing
-*/
-#if 0
-static void
-SetCometOps(struct s_comet_reg *comet)
-{
-	u_int8_t rd_value;
-
-	if (comet == mConfig.C4Func1Base + (COMET0_OFFSET >> 2)) {
-		/* read the BRIF Configuration */
-		rd_value = (u_int8_t) pci_read_32((u_int32_t *)
-				&comet->brif_cfg);
-		rd_value &= ~0x20;
-		pci_write_32((u_int32_t *) &comet->brif_cfg,
-				(u_int32_t) rd_value);
-		/* read the BRIF Frame Pulse Configuration */
-		rd_value = (u_int8_t) pci_read_32((u_int32_t *)
-				&comet->brif_fpcfg);
-		rd_value &= ~0x20;
-		pci_write_32((u_int32_t *) &comet->brif_fpcfg,
-				(u_int8_t) rd_value);
-	} else {
-	/* read the BRIF Configuration */
-	rd_value = (u_int8_t) pci_read_32((u_int32_t *) &comet->brif_cfg);
-	rd_value |= 0x20;
-	pci_write_32((u_int32_t *) &comet->brif_cfg, (u_int32_t) rd_value);
-	/* read the BRIF Frame Pulse Configuration */
-	rd_value = (u_int8_t) pci_read_32((u_int32_t *) &comet->brif_fpcfg);
-	rd_value |= 0x20;
-	pci_write_32(u_int32_t *) & comet->brif_fpcfg, (u_int8_t) rd_value);
-	}
-}
-#endif
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,353 +0,0 @@
-#ifndef _INC_COMET_H_
-#define _INC_COMET_H_
-
-/*-----------------------------------------------------------------------------
- * comet.h -
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-
-#define VINT32  volatile u_int32_t
-
-struct s_comet_reg {
-	VINT32 gbl_cfg;      /* 00  Global Cfg */
-	VINT32 clkmon;       /* 01  Clk Monitor */
-	VINT32 rx_opt;       /* 02  RX Options */
-	VINT32 rx_line_cfg;  /* 03  RX Line Interface Cfg */
-	VINT32 tx_line_cfg;  /* 04  TX Line Interface Cfg */
-	VINT32 tx_frpass;    /* 05  TX Framing & Bypass Options */
-	VINT32 tx_time;      /* 06  TX Timing Options */
-	VINT32 intr_1;       /* 07  Intr Source #1 */
-	VINT32 intr_2;       /* 08  Intr Source #2 */
-	VINT32 intr_3;       /* 09  Intr Source #3 */
-	VINT32 mdiag;        /* 0A  Master Diagnostics */
-	VINT32 mtest;        /* 0B  Master Test */
-	VINT32 adiag;        /* 0C  Analog Diagnostics */
-	VINT32 rev_id;       /* 0D  Rev/Chip Id/Global PMON Update */
-#define pmon  rev_id
-	VINT32 reset;        /* 0E  Reset */
-	VINT32 prgd_phctl;   /* 0F  PRGD Positioning/Ctl & HDLC Ctl */
-	VINT32 cdrc_cfg;     /* 10  CDRC Cfg */
-	VINT32 cdrc_ien;     /* 11  CDRC Intr Enable */
-	VINT32 cdrc_ists;    /* 12  CDRC Intr Sts */
-	VINT32 cdrc_alos;    /* 13  CDRC Alternate Loss of Signal */
-
-	VINT32 rjat_ists;    /* 14  RJAT Intr Sts */
-	VINT32 rjat_n1clk;   /* 15  RJAT Reference Clk Divisor (N1) Ctl */
-	VINT32 rjat_n2clk;   /* 16  RJAT Output Clk Divisor (N2) Ctl */
-	VINT32 rjat_cfg;     /* 17  RJAT Cfg */
-
-	VINT32 tjat_ists;    /* 18  TJAT Intr Sts */
-	VINT32 tjat_n1clk;   /* 19  TJAT Reference Clk Divisor (N1) Ctl */
-	VINT32 tjat_n2clk;   /* 1A  TJAT Output Clk Divisor (N2) Ctl */
-	VINT32 tjat_cfg;     /* 1B  TJAT Cfg */
-
-	VINT32 rx_elst_cfg;      /* 1C  RX-ELST Cfg */
-	VINT32 rx_elst_ists;     /* 1D  RX-ELST Intr Sts */
-	VINT32 rx_elst_idle;     /* 1E  RX-ELST Idle Code */
-	VINT32 _rx_elst_res1f;   /* 1F     RX-ELST Reserved */
-
-	VINT32 tx_elst_cfg;      /* 20  TX-ELST Cfg */
-	VINT32 tx_elst_ists;     /* 21  TX-ELST Intr Sts */
-	VINT32 _tx_elst_res22;   /* 22     TX-ELST Reserved */
-	VINT32 _tx_elst_res23;   /* 23     TX-ELST Reserved */
-	VINT32 __res24;          /* 24     Reserved */
-	VINT32 __res25;          /* 25     Reserved */
-	VINT32 __res26;          /* 26     Reserved */
-	VINT32 __res27;          /* 27     Reserved */
-
-	VINT32 rxce1_ctl;        /* 28  RXCE RX Data Link 1 Ctl */
-	VINT32 rxce1_bits;       /* 29  RXCE RX Data Link 1 Bit Select */
-	VINT32 rxce2_ctl;        /* 2A  RXCE RX Data Link 2 Ctl */
-	VINT32 rxce2_bits;       /* 2B  RXCE RX Data Link 2 Bit Select */
-	VINT32 rxce3_ctl;        /* 2C  RXCE RX Data Link 3 Ctl */
-	VINT32 rxce3_bits;       /* 2D  RXCE RX Data Link 3 Bit Select */
-	VINT32 _rxce_res2E;      /* 2E     RXCE Reserved */
-	VINT32 _rxce_res2F;      /* 2F     RXCE Reserved */
-
-	VINT32 brif_cfg;         /* 30  BRIF RX Backplane Cfg */
-	VINT32 brif_fpcfg;       /* 31  BRIF RX Backplane Frame Pulse Cfg */
-	VINT32 brif_pfcfg;       /* 32  BRIF RX Backplane Parity/F-Bit Cfg */
-	VINT32 brif_tsoff;       /* 33  BRIF RX Backplane Time Slot Offset */
-	VINT32 brif_boff;        /* 34  BRIF RX Backplane Bit Offset */
-	VINT32 _brif_res35;      /* 35     BRIF RX Backplane Reserved */
-	VINT32 _brif_res36;      /* 36     BRIF RX Backplane Reserved */
-	VINT32 _brif_res37;      /* 37     BRIF RX Backplane Reserved */
-
-	VINT32 txci1_ctl;        /* 38  TXCI TX Data Link 1 Ctl */
-	VINT32 txci1_bits;       /* 39  TXCI TX Data Link 2 Bit Select */
-	VINT32 txci2_ctl;        /* 3A  TXCI TX Data Link 1 Ctl */
-	VINT32 txci2_bits;       /* 3B  TXCI TX Data Link 2 Bit Select */
-	VINT32 txci3_ctl;        /* 3C  TXCI TX Data Link 1 Ctl */
-	VINT32 txci3_bits;       /* 3D  TXCI TX Data Link 2 Bit Select */
-	VINT32 _txci_res3E;      /* 3E     TXCI Reserved */
-	VINT32 _txci_res3F;      /* 3F     TXCI Reserved */
-
-	VINT32 btif_cfg;         /* 40  BTIF TX Backplane Cfg */
-	VINT32 btif_fpcfg;       /* 41  BTIF TX Backplane Frame Pulse Cfg */
-	VINT32 btif_pcfgsts;     /* 42  BTIF TX Backplane Parity Cfg & Sts */
-	VINT32 btif_tsoff;       /* 43  BTIF TX Backplane Time Slot Offset */
-	VINT32 btif_boff;        /* 44  BTIF TX Backplane Bit Offset */
-	VINT32 _btif_res45;      /* 45     BTIF TX Backplane Reserved */
-	VINT32 _btif_res46;      /* 46     BTIF TX Backplane Reserved */
-	VINT32 _btif_res47;      /* 47     BTIF TX Backplane Reserved */
-	VINT32 t1_frmr_cfg;      /* 48  T1 FRMR Cfg */
-	VINT32 t1_frmr_ien;      /* 49  T1 FRMR Intr Enable */
-	VINT32 t1_frmr_ists;     /* 4A  T1 FRMR Intr Sts */
-	VINT32 __res_4B;         /* 4B     Reserved */
-	VINT32 ibcd_cfg;         /* 4C  IBCD Cfg */
-	VINT32 ibcd_ies;         /* 4D  IBCD Intr Enable/Sts */
-	VINT32 ibcd_act;         /* 4E  IBCD Activate Code */
-	VINT32 ibcd_deact;       /* 4F  IBCD Deactivate Code */
-
-	VINT32 sigx_cfg;         /* 50  SIGX Cfg/Change of Signaling State */
-	VINT32 sigx_acc_cos;     /* 51  SIGX
-				  * uP Access Sts/Change of Signaling State */
-	VINT32 sigx_iac_cos;     /* 52  SIGX Channel Indirect
-				  * Addr/Ctl/Change of Signaling State */
-	VINT32 sigx_idb_cos;     /* 53  SIGX Channel Indirect Data
-				  * Buffer/Change of Signaling State */
-
-	VINT32 t1_xbas_cfg;      /* 54  T1 XBAS Cfg */
-	VINT32 t1_xbas_altx;     /* 55  T1 XBAS Alarm TX */
-	VINT32 t1_xibc_ctl;      /* 56  T1 XIBC Ctl */
-	VINT32 t1_xibc_lbcode;   /* 57  T1 XIBC Loopback Code */
-
-	VINT32 pmon_ies;         /* 58  PMON Intr Enable/Sts */
-	VINT32 pmon_fberr;       /* 59  PMON Framing Bit Err Cnt */
-	VINT32 pmon_feb_lsb;     /* 5A  PMON
-				  * OFF/COFA/Far End Block Err Cnt (LSB) */
-	VINT32 pmon_feb_msb;     /* 5B  PMON
-				  * OFF/COFA/Far End Block Err Cnt (MSB) */
-	VINT32 pmon_bed_lsb;     /* 5C  PMON Bit/Err/CRCE Cnt (LSB) */
-	VINT32 pmon_bed_msb;     /* 5D  PMON Bit/Err/CRCE Cnt (MSB) */
-	VINT32 pmon_lvc_lsb;     /* 5E  PMON LVC Cnt (LSB) */
-	VINT32 pmon_lvc_msb;     /* 5F  PMON LVC Cnt (MSB) */
-
-	VINT32 t1_almi_cfg;      /* 60  T1 ALMI Cfg */
-	VINT32 t1_almi_ien;      /* 61  T1 ALMI Intr Enable */
-	VINT32 t1_almi_ists;     /* 62  T1 ALMI Intr Sts */
-	VINT32 t1_almi_detsts;   /* 63  T1 ALMI Alarm Detection Sts */
-
-	VINT32 _t1_pdvd_res64;   /* 64     T1 PDVD Reserved */
-	VINT32 t1_pdvd_ies;      /* 65  T1 PDVD Intr Enable/Sts */
-	VINT32 _t1_xboc_res66;   /* 66     T1 XBOC Reserved */
-	VINT32 t1_xboc_code;     /* 67  T1 XBOC Code */
-	VINT32 _t1_xpde_res68;   /* 68     T1 XPDE Reserved */
-	VINT32 t1_xpde_ies;      /* 69  T1 XPDE Intr Enable/Sts */
-
-	VINT32 t1_rboc_ena;      /* 6A  T1 RBOC Enable */
-	VINT32 t1_rboc_sts;      /* 6B  T1 RBOC Code Sts */
-
-	VINT32 t1_tpsc_cfg;      /* 6C  TPSC Cfg */
-	VINT32 t1_tpsc_sts;      /* 6D  TPSC uP Access Sts */
-	VINT32 t1_tpsc_ciaddr;   /* 6E  TPSC Channel Indirect
-				  * Addr/Ctl */
-	VINT32 t1_tpsc_cidata;   /* 6F  TPSC Channel Indirect Data
-				  * Buffer */
-	VINT32 t1_rpsc_cfg;      /* 70  RPSC Cfg */
-	VINT32 t1_rpsc_sts;      /* 71  RPSC uP Access Sts */
-	VINT32 t1_rpsc_ciaddr;   /* 72  RPSC Channel Indirect
-				  * Addr/Ctl */
-	VINT32 t1_rpsc_cidata;   /* 73  RPSC Channel Indirect Data
-				  * Buffer */
-	VINT32 __res74;          /* 74     Reserved */
-	VINT32 __res75;          /* 75     Reserved */
-	VINT32 __res76;          /* 76     Reserved */
-	VINT32 __res77;          /* 77     Reserved */
-
-	VINT32 t1_aprm_cfg;      /* 78  T1 APRM Cfg/Ctl */
-	VINT32 t1_aprm_load;     /* 79  T1 APRM Manual Load */
-	VINT32 t1_aprm_ists;     /* 7A  T1 APRM Intr Sts */
-	VINT32 t1_aprm_1sec_2;   /* 7B  T1 APRM One Second Content Octet 2 */
-	VINT32 t1_aprm_1sec_3;   /* 7C  T1 APRM One Second Content Octet 3 */
-	VINT32 t1_aprm_1sec_4;   /* 7D  T1 APRM One Second Content Octet 4 */
-	VINT32 t1_aprm_1sec_5;   /* 7E  T1 APRM
-				  * One Second Content MSB (Octect 5) */
-	VINT32 t1_aprm_1sec_6;   /* 7F  T1 APRM
-				  * One Second Content MSB (Octect 6) */
-
-	VINT32 e1_tran_cfg;      /* 80  E1 TRAN Cfg */
-	VINT32 e1_tran_txalarm;  /* 81  E1 TRAN TX Alarm/Diagnostic Ctl */
-	VINT32 e1_tran_intctl;   /* 82  E1 TRAN International Ctl */
-	VINT32 e1_tran_extrab;   /* 83  E1 TRAN Extra Bits Ctl */
-	VINT32 e1_tran_ien;      /* 84  E1 TRAN Intr Enable */
-	VINT32 e1_tran_ists;     /* 85  E1 TRAN Intr Sts */
-	VINT32 e1_tran_nats;     /* 86  E1 TRAN National Bit Codeword
-				  * Select */
-	VINT32 e1_tran_nat;      /* 87  E1 TRAN National Bit Codeword */
-	VINT32 __res88;          /* 88     Reserved */
-	VINT32 __res89;          /* 89     Reserved */
-	VINT32 __res8A;          /* 8A     Reserved */
-	VINT32 __res8B;          /* 8B     Reserved */
-
-	VINT32 _t1_frmr_res8C;   /* 8C     T1 FRMR Reserved */
-	VINT32 _t1_frmr_res8D;   /* 8D     T1 FRMR Reserved */
-	VINT32 __res8E;          /* 8E     Reserved */
-	VINT32 __res8F;          /* 8F     Reserved */
-
-	VINT32 e1_frmr_aopts;    /* 90  E1 FRMR Frame Alignment Options */
-	VINT32 e1_frmr_mopts;    /* 91  E1 FRMR Maintenance Mode Options */
-	VINT32 e1_frmr_ien;      /* 92  E1 FRMR Framing Sts Intr Enable */
-	VINT32 e1_frmr_mien;     /* 93  E1 FRMR
-				  * Maintenance/Alarm Sts Intr Enable */
-	VINT32 e1_frmr_ists;     /* 94  E1 FRMR Framing Sts Intr Indication */
-	VINT32 e1_frmr_mists;    /* 95  E1 FRMR
-				  * Maintenance/Alarm Sts Indication Enable */
-	VINT32 e1_frmr_sts;      /* 96  E1 FRMR Framing Sts */
-	VINT32 e1_frmr_masts;    /* 97  E1 FRMR Maintenance/Alarm Sts */
-	VINT32 e1_frmr_nat_bits; /* 98  E1 FRMR International/National Bits */
-	VINT32 e1_frmr_crc_lsb;  /* 99  E1 FRMR CRC Err Cnt - LSB */
-	VINT32 e1_frmr_crc_msb;  /* 9A  E1 FRMR CRC Err Cnt - MSB */
-	VINT32 e1_frmr_nat_ien;  /* 9B  E1 FRMR
-				  * National Bit Codeword Intr Enables */
-	VINT32 e1_frmr_nat_ists; /* 9C  E1 FRMR
-				  * National Bit Codeword Intr/Sts */
-	VINT32 e1_frmr_nat;      /* 9D  E1 FRMR National Bit Codewords */
-	VINT32 e1_frmr_fp_ien;   /* 9E  E1 FRMR
-				  * Frame Pulse/Alarm Intr Enables */
-	VINT32 e1_frmr_fp_ists;  /* 9F  E1 FRMR Frame Pulse/Alarm Intr/Sts */
-
-	VINT32 __resA0;          /* A0     Reserved */
-	VINT32 __resA1;          /* A1     Reserved */
-	VINT32 __resA2;          /* A2     Reserved */
-	VINT32 __resA3;          /* A3     Reserved */
-	VINT32 __resA4;          /* A4     Reserved */
-	VINT32 __resA5;          /* A5     Reserved */
-	VINT32 __resA6;          /* A6     Reserved */
-	VINT32 __resA7;          /* A7     Reserved */
-
-	VINT32 tdpr1_cfg;        /* A8  TDPR #1 Cfg */
-	VINT32 tdpr1_utl;        /* A9  TDPR #1 Upper TX Threshold */
-	VINT32 tdpr1_ltl;        /* AA  TDPR #1 Lower TX Threshold */
-	VINT32 tdpr1_ien;        /* AB  TDPR #1 Intr Enable */
-	VINT32 tdpr1_ists;       /* AC  TDPR #1 Intr Sts/UDR Clear */
-	VINT32 tdpr1_data;       /* AD  TDPR #1 TX Data */
-	VINT32 __resAE;          /* AE     Reserved */
-	VINT32 __resAF;          /* AF     Reserved */
-	VINT32 tdpr2_cfg;        /* B0  TDPR #2 Cfg */
-	VINT32 tdpr2_utl;        /* B1  TDPR #2 Upper TX Threshold */
-	VINT32 tdpr2_ltl;        /* B2  TDPR #2 Lower TX Threshold */
-	VINT32 tdpr2_ien;        /* B3  TDPR #2 Intr Enable */
-	VINT32 tdpr2_ists;       /* B4  TDPR #2 Intr Sts/UDR Clear */
-	VINT32 tdpr2_data;       /* B5  TDPR #2 TX Data */
-	VINT32 __resB6;          /* B6     Reserved */
-	VINT32 __resB7;          /* B7     Reserved1 */
-	VINT32 tdpr3_cfg;        /* B8  TDPR #3 Cfg */
-	VINT32 tdpr3_utl;        /* B9  TDPR #3 Upper TX Threshold */
-	VINT32 tdpr3_ltl;        /* BA  TDPR #3 Lower TX Threshold */
-	VINT32 tdpr3_ien;        /* BB  TDPR #3 Intr Enable */
-	VINT32 tdpr3_ists;       /* BC  TDPR #3 Intr Sts/UDR Clear */
-	VINT32 tdpr3_data;       /* BD  TDPR #3 TX Data */
-	VINT32 __resBE;          /* BE     Reserved */
-	VINT32 __resBF;          /* BF     Reserved */
-
-	VINT32 rdlc1_cfg;        /* C0  RDLC #1 Cfg */
-	VINT32 rdlc1_intctl;     /* C1  RDLC #1 Intr Ctl */
-	VINT32 rdlc1_sts;        /* C2  RDLC #1 Sts */
-	VINT32 rdlc1_data;       /* C3  RDLC #1 Data */
-	VINT32 rdlc1_paddr;      /* C4  RDLC #1 Primary Addr Match */
-	VINT32 rdlc1_saddr;      /* C5  RDLC #1 Secondary Addr Match */
-	VINT32 __resC6;          /* C6     Reserved */
-	VINT32 __resC7;          /* C7     Reserved */
-	VINT32 rdlc2_cfg;        /* C8  RDLC #2 Cfg */
-	VINT32 rdlc2_intctl;     /* C9  RDLC #2 Intr Ctl */
-	VINT32 rdlc2_sts;        /* CA  RDLC #2 Sts */
-	VINT32 rdlc2_data;       /* CB  RDLC #2 Data */
-	VINT32 rdlc2_paddr;      /* CC  RDLC #2 Primary Addr Match */
-	VINT32 rdlc2_saddr;      /* CD  RDLC #2 Secondary Addr Match */
-	VINT32 __resCE;          /* CE     Reserved */
-	VINT32 __resCF;          /* CF     Reserved */
-	VINT32 rdlc3_cfg;        /* D0  RDLC #3 Cfg */
-	VINT32 rdlc3_intctl;     /* D1  RDLC #3 Intr Ctl */
-	VINT32 rdlc3_sts;        /* D2  RDLC #3 Sts */
-	VINT32 rdlc3_data;       /* D3  RDLC #3 Data */
-	VINT32 rdlc3_paddr;      /* D4  RDLC #3 Primary Addr Match */
-	VINT32 rdlc3_saddr;      /* D5  RDLC #3 Secondary Addr Match */
-
-	VINT32 csu_cfg;          /* D6  CSU Cfg */
-	VINT32 _csu_resD7;       /* D7     CSU Reserved */
-
-	VINT32 rlps_idata3;      /* D8  RLPS Indirect Data, 24-31 */
-	VINT32 rlps_idata2;      /* D9  RLPS Indirect Data, 16-23 */
-	VINT32 rlps_idata1;      /* DA  RLPS Indirect Data, 8-15 */
-	VINT32 rlps_idata0;      /* DB  RLPS Indirect Data, 0-7 */
-	VINT32 rlps_eqvr;        /* DC  RLPS Equalizer Voltage Reference
-				  *    (E1 missing) */
-	VINT32 _rlps_resDD;      /* DD     RLPS Reserved */
-	VINT32 _rlps_resDE;      /* DE     RLPS Reserved */
-	VINT32 _rlps_resDF;      /* DF     RLPS Reserved */
-
-	VINT32 prgd_ctl;         /* E0  PRGD Ctl */
-	VINT32 prgd_ies;         /* E1  PRGD Intr Enable/Sts */
-	VINT32 prgd_shift_len;   /* E2  PRGD Shift Length */
-	VINT32 prgd_tap;         /* E3  PRGD Tap */
-	VINT32 prgd_errin;       /* E4  PRGD Err Insertion */
-	VINT32 _prgd_resE5;      /* E5     PRGD Reserved */
-	VINT32 _prgd_resE6;      /* E6     PRGD Reserved */
-	VINT32 _prgd_resE7;      /* E7     PRGD Reserved */
-	VINT32 prgd_patin1;      /* E8  PRGD Pattern Insertion #1 */
-	VINT32 prgd_patin2;      /* E9  PRGD Pattern Insertion #2 */
-	VINT32 prgd_patin3;      /* EA  PRGD Pattern Insertion #3 */
-	VINT32 prgd_patin4;      /* EB  PRGD Pattern Insertion #4 */
-	VINT32 prgd_patdet1;     /* EC  PRGD Pattern Detector #1 */
-	VINT32 prgd_patdet2;     /* ED  PRGD Pattern Detector #2 */
-	VINT32 prgd_patdet3;     /* EE  PRGD Pattern Detector #3 */
-	VINT32 prgd_patdet4;     /* EF  PRGD Pattern Detector #4 */
-
-	VINT32 xlpg_cfg;         /* F0  XLPG Line Driver Cfg */
-	VINT32 xlpg_ctlsts;      /* F1  XLPG Ctl/Sts */
-	VINT32 xlpg_pwave_addr;  /* F2  XLPG
-				  * Pulse Waveform Storage Write Addr */
-	VINT32 xlpg_pwave_data;  /* F3  XLPG Pulse Waveform Storage Data */
-	VINT32 xlpg_atest_pctl;  /* F4  XLPG Analog Test Positive Ctl */
-	VINT32 xlpg_atest_nctl;  /* F5  XLPG Analog Test Negative Ctl */
-	VINT32 xlpg_fdata_sel;   /* F6  XLPG Fuse Data Select */
-	VINT32 _xlpg_resF7;      /* F7     XLPG Reserved */
-
-	VINT32 rlps_cfgsts;      /* F8  RLPS Cfg & Sts */
-	VINT32 rlps_alos_thresh; /* F9  RLPS
-				  * ALOS Detection/Clearance Threshold */
-	VINT32 rlps_alos_dper;   /* FA  RLPS ALOS Detection Period */
-	VINT32 rlps_alos_cper;   /* FB  RLPS ALOS Clearance Period */
-	VINT32 rlps_eq_iaddr;    /* FC  RLPS Equalization Indirect Addr */
-	VINT32 rlps_eq_rwsel;    /* FD  RLPS Equalization Read/WriteB Select */
-	VINT32 rlps_eq_ctlsts;   /* FE  RLPS Equalizer Loop Sts & Ctl */
-	VINT32 rlps_eq_cfg;      /* FF  RLPS Equalizer Cfg */
-};
-
-/* 00AH: MDIAG Register bit definitions */
-#define COMET_MDIAG_ID5        0x40
-#define COMET_MDIAG_LBMASK     0x3F
-#define COMET_MDIAG_PAYLB      0x20
-#define COMET_MDIAG_LINELB     0x10
-#define COMET_MDIAG_RAIS       0x08
-#define COMET_MDIAG_DDLB       0x04
-#define COMET_MDIAG_TXMFP      0x02
-#define COMET_MDIAG_TXLOS      0x01
-#define COMET_MDIAG_LBOFF      0x00
-
-#undef VINT32
-
-#ifdef __KERNEL__
-extern void
-init_comet(void *, struct s_comet_reg *, u_int32_t, int, u_int8_t);
-#endif
-
-#endif                          /* _INC_COMET_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet_tables.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet_tables.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet_tables.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet_tables.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,538 +0,0 @@
-/*-----------------------------------------------------------------------------
- * comet_tables.c - waveform tables for the PM4351 'COMET'
- *
- * Copyright (C) 2003-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-#include "comet_tables.h"
-
-/*****************************************************************************
-*
-*  Array names:
-*
-*       TWVLongHaul0DB
-*       TWVLongHaul7_5DB
-*       TWVLongHaul15DB
-*       TWVLongHaul22_5DB
-*       TWVShortHaul0
-*       TWVShortHaul1
-*       TWVShortHaul2
-*       TWVShortHaul3
-*       TWVShortHaul4
-*       TWVShortHaul5
-*       TWV_E1_120Ohm
-*       TWV_E1_75Ohm   <not supported>
-*       T1_Equalizer
-*       E1_Equalizer
-*
-*****************************************************************************/
-
-u_int8_t TWVLongHaul0DB[25][5] =/* T1 Long Haul 0 DB */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x20, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x32, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3E, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3D, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x3C, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x3B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x37, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x34, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x4C, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x0C}                              /* PMC's suggested value */
-/*  {0x14}                    Output Amplitude */
-};
-
-u_int8_t    TWVLongHaul7_5DB[25][5] =   /* T1 Long Haul 7.5 DB */
-{
-    {0x00, 0x10, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x01, 0x0E, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x02, 0x0C, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x04, 0x0A, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x08, 0x08, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x0C, 0x06, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x10, 0x04, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x16, 0x02, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x1A, 0x01, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x1E, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x22, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x20, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x1C, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x18, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x14, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x12, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x07}                      /* PMC's suggested value */
-/*  { 0x0A }                        Output Amplitude */
-};
-
-u_int8_t    TWVLongHaul15DB[25][5] =    /* T1 Long Haul 15 DB */
-{
-    {0x00, 0x2A, 0x09, 0x01, 0x00},     /* Sample 0 */
-    {0x00, 0x28, 0x08, 0x01, 0x00},     /* Sample 1 */
-    {0x00, 0x26, 0x08, 0x01, 0x00},     /* Sample 2 */
-    {0x00, 0x24, 0x07, 0x01, 0x00},     /* Sample 3 */
-    {0x01, 0x22, 0x07, 0x01, 0x00},     /* Sample 4 */
-    {0x02, 0x20, 0x06, 0x01, 0x00},     /* Sample 5 */
-    {0x04, 0x1E, 0x06, 0x01, 0x00},     /* Sample 6 */
-    {0x07, 0x1C, 0x05, 0x00, 0x00},     /* Sample 7 */
-    {0x0A, 0x1B, 0x05, 0x00, 0x00},     /* Sample 8 */
-    {0x0D, 0x19, 0x05, 0x00, 0x00},     /* Sample 9 */
-    {0x10, 0x18, 0x04, 0x00, 0x00},     /* Sample 10 */
-    {0x14, 0x16, 0x04, 0x00, 0x00},     /* Sample 11 */
-    {0x18, 0x15, 0x04, 0x00, 0x00},     /* Sample 12 */
-    {0x1B, 0x13, 0x03, 0x00, 0x00},     /* Sample 13 */
-    {0x1E, 0x12, 0x03, 0x00, 0x00},     /* Sample 14 */
-    {0x21, 0x10, 0x03, 0x00, 0x00},     /* Sample 15 */
-    {0x24, 0x0F, 0x03, 0x00, 0x00},     /* Sample 16 */
-    {0x27, 0x0D, 0x03, 0x00, 0x00},     /* Sample 17 */
-    {0x2A, 0x0D, 0x02, 0x00, 0x00},     /* Sample 18 */
-    {0x2D, 0x0B, 0x02, 0x00, 0x00},     /* Sample 19 */
-    {0x30, 0x0B, 0x02, 0x00, 0x00},     /* Sample 20 */
-    {0x30, 0x0A, 0x02, 0x00, 0x00},     /* Sample 21 */
-    {0x2E, 0x0A, 0x02, 0x00, 0x00},     /* Sample 22 */
-    {0x2C, 0x09, 0x02, 0x00, 0x00},     /* Sample 23 */
-    {0x03}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVLongHaul22_5DB[25][5] =  /* T1 Long Haul 22.5 DB */
-{
-    {0x00, 0x1F, 0x16, 0x06, 0x01},     /* Sample 0 */
-    {0x00, 0x20, 0x15, 0x05, 0x01},     /* Sample 1 */
-    {0x00, 0x21, 0x15, 0x05, 0x01},     /* Sample 2 */
-    {0x00, 0x22, 0x14, 0x05, 0x01},     /* Sample 3 */
-    {0x00, 0x22, 0x13, 0x04, 0x00},     /* Sample 4 */
-    {0x00, 0x23, 0x12, 0x04, 0x00},     /* Sample 5 */
-    {0x01, 0x23, 0x12, 0x04, 0x00},     /* Sample 6 */
-    {0x01, 0x24, 0x11, 0x03, 0x00},     /* Sample 7 */
-    {0x01, 0x23, 0x10, 0x03, 0x00},     /* Sample 8 */
-    {0x02, 0x23, 0x10, 0x03, 0x00},     /* Sample 9 */
-    {0x03, 0x22, 0x0F, 0x03, 0x00},     /* Sample 10 */
-    {0x05, 0x22, 0x0E, 0x03, 0x00},     /* Sample 11 */
-    {0x07, 0x21, 0x0E, 0x02, 0x00},     /* Sample 12 */
-    {0x09, 0x20, 0x0D, 0x02, 0x00},     /* Sample 13 */
-    {0x0B, 0x1E, 0x0C, 0x02, 0x00},     /* Sample 14 */
-    {0x0E, 0x1D, 0x0C, 0x02, 0x00},     /* Sample 15 */
-    {0x10, 0x1B, 0x0B, 0x02, 0x00},     /* Sample 16 */
-    {0x13, 0x1B, 0x0A, 0x02, 0x00},     /* Sample 17 */
-    {0x15, 0x1A, 0x0A, 0x02, 0x00},     /* Sample 18 */
-    {0x17, 0x19, 0x09, 0x01, 0x00},     /* Sample 19 */
-    {0x19, 0x19, 0x08, 0x01, 0x00},     /* Sample 20 */
-    {0x1B, 0x18, 0x08, 0x01, 0x00},     /* Sample 21 */
-    {0x1D, 0x17, 0x07, 0x01, 0x00},     /* Sample 22 */
-    {0x1E, 0x17, 0x06, 0x01, 0x00},     /* Sample 23 */
-    {0x02}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul0[25][5] =      /* T1 Short Haul 0 - 110 ft */
-{
-    {0x00, 0x45, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x20, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x3C, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x3B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x37, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x34, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x59, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x55, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x50, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x4D, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x48, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x0C}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul1[25][5] =      /* T1 Short Haul 110 - 220 ft */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x36, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x34, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x2E, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x68, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x54, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x10}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul2[25][5] =      /* T1 Short Haul 220 - 330 ft */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3A, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3A, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x38, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x2E, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x23, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x6C, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x60, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x11}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul3[25][5] =      /* T1 Short Haul 330 - 440 ft */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x2E, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x19, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x60, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x12}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul4[25][5] =      /* T1 Short Haul 440 - 550 ft */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x2B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x27, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x14}                      /* Output Amplitude */
-};
-
-u_int8_t    TWVShortHaul5[25][5] =      /* T1 Short Haul 550 - 660 ft */
-{
-    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x3F, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x27, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x25, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x5F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x50, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x15}                      /* Output Amplitude */
-};
-
-u_int8_t    TWV_E1_120Ohm[25][5] =      /* E1 120 Ohm */
-{
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x0A, 0x00, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x3F, 0x00, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3F, 0x00, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-    {0x0C}                      /* PMC's suggested value */
-/*  { 0x10 }                Output Amplitude */
-};
-
-
-
-u_int8_t    TWV_E1_75Ohm[25][5] =       /* E1 75 Ohm */
-{
-#ifdef PMCC4_DOES_NOT_SUPPORT
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 0 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 1 */
-    {0x0A, 0x00, 0x00, 0x00, 0x00},     /* Sample 2 */
-    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 3 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 4 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 5 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 6 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 7 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
-    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
-    {0x32, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
-    {0x14, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
-    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
-#endif
-    {0x0C}                      /* Output Amplitude */
-};
-
-
-u_int32_t T1_Equalizer[256] =   /* T1 Receiver Equalizer */
-{
-    0x03FE1840, 0x03F61840, 0x03EE1840, 0x03E61840,     /* 000 - 003 */
-        0x03DE1840, 0x03D61840, 0x03D61840, 0x03D61840, /* 004 - 007 */
-        0x03CE1840, 0x03CE1840, 0x03CE1840, 0x03CE1840, /* 008 - 011 */
-        0x03C61840, 0x03C61840, 0x03C61840, 0x0BBE1840, /* 012 - 015 */
-        0x0BBE1840, 0x0BBE1840, 0x0BBE1840, 0x0BB61840, /* 016 - 019 */
-        0x0BB61840, 0x0BB61840, 0x0BB61840, 0x13AE1838, /* 020 - 023 */
-        0x13AE183C, 0x13AE1840, 0x13AE1840, 0x13AE1840, /* 024 - 027 */
-        0x13AE1840, 0x1BB618B8, 0x1BAE18B8, 0x1BAE18BC, /* 028 - 031 */
-        0x1BAE18C0, 0x1BAE18C0, 0x23A618C0, 0x23A618C0, /* 032 - 035 */
-        0x23A618C0, 0x23A618C0, 0x23A618C0, 0x239E18C0, /* 036 - 039 */
-        0x239E18C0, 0x239E18C0, 0x239E18C0, 0x239E18C0, /* 040 - 043 */
-        0x2B9618C0, 0x2B9618C0, 0x2B9618C0, 0x33961940, /* 044 - 047 */
-        0x37961940, 0x37961940, 0x37961940, 0x3F9E19C0, /* 048 - 051 */
-        0x3F9E19C0, 0x3F9E19C0, 0x3FA61A40, 0x3FA61A40, /* 052 - 055 */
-        0x3FA61A40, 0x3FA61A40, 0x3F9619C0, 0x3F9619C0, /* 056 - 059 */
-        0x3F9619C0, 0x3F9619C0, 0x479E1A40, 0x479E1A40, /* 060 - 063 */
-        0x479E1A40, 0x47961A40, 0x47961A40, 0x47961A40, /* 064 - 067 */
-        0x47961A40, 0x4F8E1A40, 0x4F8E1A40, 0x4F8E1A40, /* 068 - 071 */
-        0x4F8E1A40, 0x4F8E1A40, 0x57861A40, 0x57861A40, /* 072 - 075 */
-        0x57861A40, 0x57861A40, 0x57861A40, 0x5F861AC0, /* 076 - 079 */
-        0x5F861AC0, 0x5F861AC0, 0x5F861AC0, 0x5F861AC0, /* 080 - 083 */
-        0x5F861AC0, 0x5F7E1AC0, 0x5F7E1AC0, 0x5F7E1AC0, /* 084 - 087 */
-        0x5F7E1AC0, 0x5F7E1AC0, 0x677E2AC0, 0x677E2AC0, /* 088 - 091 */
-        0x677E2AC0, 0x677E2AC0, 0x67762AC0, 0x67762AC0, /* 092 - 095 */
-        0x67762AC0, 0x67762AC0, 0x67762AC0, 0x6F6E2AC0, /* 096 - 099 */
-        0x6F6E2AC0, 0x6F6E2AC0, 0x6F6E2AC0, 0x776E3AC0, /* 100 - 103 */
-        0x776E3AC0, 0x776E3AC0, 0x776E3AC0, 0x7F663AC0, /* 104 - 107 */
-        0x7F663AC0, 0x7F664AC0, 0x7F664AC0, 0x7F664AC0, /* 108 - 111 */
-        0x7F664AC0, 0x87665AC0, 0x87665AC0, 0x87665AC0, /* 112 - 115 */
-        0x87665AC0, 0x87665AC0, 0x875E5AC0, 0x875E5AC0, /* 116 - 119 */
-        0x875E5AC0, 0x875E5AC0, 0x875E5AC0, 0x8F5E6AC0, /* 120 - 123 */
-        0x8F5E6AC0, 0x8F5E6AC0, 0x8F5E6AC0, 0x975E7AC0, /* 124 - 127 */
-        0x975E7AC0, 0x975E7AC0, 0x975E7AC0, 0x9F5E8AC0, /* 128 - 131 */
-        0x9F5E8AC0, 0x9F5E8AC0, 0x9F5E8AC0, 0x9F5E8AC0, /* 132 - 135 */
-        0xA7569AC0, 0xA7569AC0, 0xA7569AC0, 0xA7569AC0, /* 136 - 139 */
-        0xA756AAC0, 0xA756AAC0, 0xA756AAC0, 0xAF4EAAC0, /* 140 - 143 */
-        0xAF4EAAC0, 0xAF4EAAC0, 0xAF4EAAC0, 0xAF4EAAC0, /* 144 - 147 */
-        0xB746AAC0, 0xB746AAC0, 0xB746AAC0, 0xB746AAC0, /* 148 - 151 */
-        0xB746AAC0, 0xB746AAC0, 0xB746AAC0, 0xB746BAC0, /* 152 - 155 */
-        0xB746BAC0, 0xB746BAC0, 0xBF4EBB40, 0xBF4EBB40, /* 156 - 159 */
-        0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, /* 160 - 163 */
-        0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, 0xBE46CB40, /* 164 - 167 */
-        0xBE46CB40, 0xBE46CB40, 0xBE46CB40, 0xBE46CB40, /* 168 - 171 */
-        0xBE46CB40, 0xBE46DB40, 0xBE46DB40, 0xBE46DB40, /* 172 - 175 */
-        0xC63ECB40, 0xC63ECB40, 0xC63EDB40, 0xC63EDB40, /* 176 - 179 */
-        0xC63EDB40, 0xC644DB40, 0xC644DB40, 0xC644DB40, /* 180 - 183 */
-        0xC644DB40, 0xC63CDB40, 0xC63CDB40, 0xC63CDB40, /* 184 - 187 */
-        0xC63CDB40, 0xD634DB40, 0xD634DB40, 0xD634DB40, /* 188 - 191 */
-        0xD634DB40, 0xD634DB40, 0xDE2CDB3C, 0xDE2CDB3C, /* 192 - 195 */
-        0xDE2CDB3C, 0xE62CDB40, 0xE62CDB40, 0xE62CDB40, /* 196 - 199 */
-        0xE62CDB40, 0xE62CDB40, 0xE62CEB40, 0xE62CEB40, /* 200 - 203 */
-        0xE62CEB40, 0xEE2CFB40, 0xEE2CFB40, 0xEE2CFB40, /* 204 - 207 */
-        0xEE2D0B40, 0xEE2D0B40, 0xEE2D0B40, 0xEE2D0B40, /* 208 - 211 */
-        0xEE2D0B40, 0xF5250B38, 0xF5250B3C, 0xF5250B40, /* 212 - 215 */
-        0xF5251B40, 0xF5251B40, 0xF5251B40, 0xF5251B40, /* 216 - 219 */
-        0xF5251B40, 0xFD252B40, 0xFD252B40, 0xFD252B40, /* 220 - 223 */
-        0xFD252B40, 0xFD252740, 0xFD252740, 0xFD252740, /* 224 - 227 */
-        0xFD252340, 0xFD252340, 0xFD252340, 0xFD253340, /* 228 - 231 */
-        0xFD253340, 0xFD253340, 0xFD253340, 0xFD253340, /* 232 - 235 */
-        0xFD253340, 0xFD253340, 0xFD253340, 0xFC254340, /* 236 - 239 */
-        0xFD254340, 0xFD254340, 0xFD254344, 0xFC254348, /* 240 - 243 */
-        0xFC25434C, 0xFD2543BC, 0xFD2543C0, 0xFC2543C0, /* 244 - 247 */
-        0xFC2343C0, 0xFC2343C0, 0xFD2343C0, 0xFC2143C0, /* 248 - 251 */
-        0xFC2143C0, 0xFC2153C0, 0xFD2153C0, 0xFC2153C0  /* 252 - 255 */
-};
-
-
-u_int32_t   E1_Equalizer[256] = /* E1 Receiver Equalizer */
-{
-    0x07DE182C, 0x07DE182C, 0x07D6182C, 0x07D6182C,     /* 000 - 003 */
-    0x07D6182C, 0x07CE182C, 0x07CE182C, 0x07CE182C,     /* 004 - 007 */
-    0x07C6182C, 0x07C6182C, 0x07C6182C, 0x07BE182C,     /* 008 - 011 */
-    0x07BE182C, 0x07BE182C, 0x07BE182C, 0x07BE182C,     /* 012 - 015 */
-    0x07B6182C, 0x07B6182C, 0x07B6182C, 0x07B6182C,     /* 016 - 019 */
-    0x07B6182C, 0x07AE182C, 0x07AE182C, 0x07AE182C,     /* 020 - 023 */
-    0x07AE182C, 0x07AE182C, 0x07B618AC, 0x07AE18AC,     /* 024 - 027 */
-    0x07AE18AC, 0x07AE18AC, 0x07AE18AC, 0x07A618AC,     /* 028 - 031 */
-    0x07A618AC, 0x07A618AC, 0x07A618AC, 0x079E18AC,     /* 032 - 035 */
-    0x07A6192C, 0x07A6192C, 0x07A6192C, 0x0FA6192C,     /* 036 - 039 */
-    0x0FA6192C, 0x0F9E192C, 0x0F9E192C, 0x0F9E192C,     /* 040 - 043 */
-    0x179E192C, 0x17A619AC, 0x179E19AC, 0x179E19AC,     /* 044 - 047 */
-    0x179619AC, 0x1F9619AC, 0x1F9619AC, 0x1F8E19AC,     /* 048 - 051 */
-    0x1F8E19AC, 0x1F8E19AC, 0x278E19AC, 0x278E1A2C,     /* 052 - 055 */
-    0x278E1A2C, 0x278E1A2C, 0x278E1A2C, 0x2F861A2C,     /* 056 - 059 */
-    0x2F861A2C, 0x2F861A2C, 0x2F7E1A2C, 0x2F7E1A2C,     /* 060 - 063 */
-    0x2F7E1A2C, 0x377E1A2C, 0x377E1AAC, 0x377E1AAC,     /* 064 - 067 */
-    0x377E1AAC, 0x377E1AAC, 0x3F7E2AAC, 0x3F7E2AAC,     /* 068 - 071 */
-    0x3F762AAC, 0x3F862B2C, 0x3F7E2B2C, 0x477E2B2C,     /* 072 - 075 */
-    0x477E2F2C, 0x477E2F2C, 0x477E2F2C, 0x47762F2C,     /* 076 - 079 */
-    0x4F762F2C, 0x4F762F2C, 0x4F6E2F2C, 0x4F6E2F2C,     /* 080 - 083 */
-    0x4F6E2F2C, 0x576E2F2C, 0x576E2F2C, 0x576E3F2C,     /* 084 - 087 */
-    0x576E3F2C, 0x576E3F2C, 0x5F6E3F2C, 0x5F6E4F2C,     /* 088 - 091 */
-    0x5F6E4F2C, 0x5F6E4F2C, 0x5F664F2C, 0x67664F2C,     /* 092 - 095 */
-    0x67664F2C, 0x675E4F2C, 0x675E4F2C, 0x67664F2C,     /* 096 - 099 */
-    0x67664F2C, 0x67665F2C, 0x6F6E5F2C, 0x6F6E6F2C,     /* 100 - 103 */
-    0x6F6E6F2C, 0x6F6E7F2C, 0x6F6E7F2C, 0x6F6E7F2C,     /* 104 - 107 */
-    0x77667F2C, 0x77667F2C, 0x775E6F2C, 0x775E7F2C,     /* 108 - 111 */
-    0x775E7F2C, 0x7F5E7F2C, 0x7F5E8F2C, 0x7F5E8F2C,     /* 112 - 115 */
-    0x7F5E8F2C, 0x87568F2C, 0x87568F2C, 0x87568F2C,     /* 116 - 119 */
-    0x874E8F2C, 0x874E8F2C, 0x874E8F2C, 0x8F4E9F2C,     /* 120 - 123 */
-    0x8F4E9F2C, 0x8F4EAF2C, 0x8F4EAF2C, 0x8F4EAF2C,     /* 124 - 127 */
-    0x974EAF2C, 0x974EAF2C, 0x974EAB2C, 0x974EAB2C,     /* 128 - 131 */
-    0x974EAB2C, 0x9F4EAB2C, 0x9F4EBB2C, 0x9F4EBB2C,     /* 132 - 135 */
-    0x9F4EBB2C, 0x9F4ECB2C, 0xA74ECB2C, 0xA74ECB2C,     /* 136 - 139 */
-    0xA746CB2C, 0xA746CB2C, 0xA746CB2C, 0xA746DB2C,     /* 140 - 143 */
-    0xAF46DB2C, 0xAF46EB2C, 0xAF46EB2C, 0xAF4EEB2C,     /* 144 - 147 */
-    0xAE4EEB2C, 0xAE4EEB2C, 0xB546FB2C, 0xB554FB2C,     /* 148 - 151 */
-    0xB54CEB2C, 0xB554FB2C, 0xB554FB2C, 0xBD54FB2C,     /* 152 - 155 */
-    0xBD4CFB2C, 0xBD4CFB2C, 0xBD4CFB2C, 0xBD44EB2C,     /* 156 - 159 */
-    0xC544FB2C, 0xC544FB2C, 0xC544FB2C, 0xC5450B2C,     /* 160 - 163 */
-    0xC5450B2C, 0xC5450B2C, 0xCD450B2C, 0xCD450B2C,     /* 164 - 167 */
-    0xCD3D0B2C, 0xCD3D0B2C, 0xCD3D0B2C, 0xD53D0B2C,     /* 168 - 171 */
-    0xD53D0B2C, 0xD53D1B2C, 0xD53D1B2C, 0xD53D1B2C,     /* 172 - 175 */
-    0xDD3D1B2C, 0xDD3D1B2C, 0xDD351B2C, 0xDD351B2C,     /* 176 - 179 */
-    0xDD351B2C, 0xE5351B2C, 0xE5351B2C, 0xE52D1B2C,     /* 180 - 183 */
-    0xE52D1B2C, 0xE52D3B2C, 0xED2D4B2C, 0xED2D1BA8,     /* 184 - 187 */
-    0xED2D1BAC, 0xED2D17AC, 0xED2D17AC, 0xED2D27AC,     /* 188 - 191 */
-    0xF52D27AC, 0xF52D27AC, 0xF52D2BAC, 0xF52D2BAC,     /* 192 - 195 */
-    0xF52D2BAC, 0xFD2D2BAC, 0xFD2B2BAC, 0xFD2B2BAC,     /* 196 - 199 */
-    0xFD2B2BAC, 0xFD2B2BAC, 0xFD232BAC, 0xFD232BAC,     /* 200 - 203 */
-    0xFD232BAC, 0xFD212BAC, 0xFD212BAC, 0xFD292BAC,     /* 204 - 207 */
-    0xFD292BAC, 0xFD2927AC, 0xFD2937AC, 0xFD2923AC,     /* 208 - 211 */
-    0xFD2923AC, 0xFD2923AC, 0xFD2923AC, 0xFD2123AC,     /* 212 - 215 */
-    0xFD2123AC, 0xFD2123AC, 0xFD2133AC, 0xFD2133AC,     /* 216 - 219 */
-    0xFD2133AC, 0xFD2143AC, 0xFD2143AC, 0xFD2143AC,     /* 220 - 223 */
-    0xFC2143AC, 0xFC2143AC, 0xFC1943AC, 0xFC1943AC,     /* 224 - 227 */
-    0xFC1943AC, 0xFC1943AC, 0xFC1953AC, 0xFC1953AC,     /* 228 - 231 */
-    0xFC1953AC, 0xFC1953AC, 0xFC1963AC, 0xFC1963AC,     /* 232 - 235 */
-    0xFC1963AC, 0xFC1973AC, 0xFC1973AC, 0xFC1973AC,     /* 236 - 239 */
-    0xFC1973AC, 0xFC1973AC, 0xFC1983AC, 0xFC1983AC,     /* 240 - 243 */
-    0xFC1983AC, 0xFC1983AC, 0xFC1983AC, 0xFC1993AC,     /* 244 - 247 */
-    0xFC1993AC, 0xFC1993AC, 0xFC19A3AC, 0xFC19A3AC,     /* 248 - 251 */
-    0xFC19B3AC, 0xFC19B3AC, 0xFC19B3AC, 0xFC19B3AC      /* 252 - 255 */
-};
-
-/*** End-of-Files ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet_tables.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet_tables.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/comet_tables.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/comet_tables.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-#ifndef _INC_COMET_TBLS_H_
-#define _INC_COMET_TBLS_H_
-
-/*-----------------------------------------------------------------------------
- * comet_tables.h - Waveform Tables for the PM4351 'COMET'
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-
-/*****************************************************************************
-*
-*  Array names:
-*
-*       TWVLongHaul0DB
-*       TWVLongHaul7_5DB
-*       TWVLongHaul15DB
-*       TWVLongHaul22_5DB
-*       TWVShortHaul0
-*       TWVShortHaul1
-*       TWVShortHaul2
-*       TWVShortHaul3
-*       TWVShortHaul4
-*       TWVShortHaul5
-*       TWV_E1_120Ohm
-*       TWV_E1_75Ohm    <not supported>
-*       T1_Equalizer
-*       E1_Equalizer
-*
-*****************************************************************************/
-
-extern u_int8_t TWVLongHaul0DB[25][5];      /* T1 Long Haul 0 DB */
-extern u_int8_t TWVLongHaul7_5DB[25][5];    /* T1 Long Haul 7.5 DB */
-extern u_int8_t TWVLongHaul15DB[25][5];     /* T1 Long Haul 15 DB */
-extern u_int8_t TWVLongHaul22_5DB[25][5];   /* T1 Long Haul 22.5 DB */
-extern u_int8_t TWVShortHaul0[25][5];       /* T1 Short Haul 0-110 ft */
-extern u_int8_t TWVShortHaul1[25][5];       /* T1 Short Haul 110-220 ft */
-extern u_int8_t TWVShortHaul2[25][5];       /* T1 Short Haul 220-330 ft */
-extern u_int8_t TWVShortHaul3[25][5];       /* T1 Short Haul 330-440 ft */
-extern u_int8_t TWVShortHaul4[25][5];       /* T1 Short Haul 440-550 ft */
-extern u_int8_t TWVShortHaul5[25][5];       /* T1 Short Haul 550-660 ft */
-extern u_int8_t TWV_E1_75Ohm[25][5];        /* E1 75 Ohm */
-extern u_int8_t TWV_E1_120Ohm[25][5];       /* E1 120 Ohm */
-extern u_int32_t T1_Equalizer[256];    /* T1 Receiver Equalizer */
-extern u_int32_t E1_Equalizer[256];    /* E1 Receiver Equalizer */
-
-#endif                          /* _INC_COMET_TBLS_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/functions.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/functions.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/functions.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/functions.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,318 +0,0 @@
-/* Copyright (C) 2003-2005  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <asm/byteorder.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/hdlc.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4.h"
-
-
-#ifndef USE_MAX_INT_DELAY
-static int  dummy = 0;
-
-#endif
-
-extern int  drvr_state;
-
-
-#if 1
-u_int32_t
-pci_read_32(u_int32_t *p)
-{
-#ifdef FLOW_DEBUG
-	u_int32_t   v;
-
-	FLUSH_PCI_READ();
-	v = le32_to_cpu(*p);
-	if (cxt1e1_log_level >= LOG_DEBUG)
-		pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
-	return v;
-#else
-	FLUSH_PCI_READ();              /* */
-	return le32_to_cpu(*p);
-#endif
-}
-
-void
-pci_write_32(u_int32_t *p, u_int32_t v)
-{
-#ifdef FLOW_DEBUG
-	if (cxt1e1_log_level >= LOG_DEBUG)
-		pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
-#endif
-	*p = cpu_to_le32 (v);
-	FLUSH_PCI_WRITE();             /* This routine is called from routines
-					* which do multiple register writes
-					* which themselves need flushing between
-					* writes in order to guarantee write
-					* ordering.  It is less code-cumbersome
-					* to flush here-in then to investigate
-					* and code the many other register
-					* writing routines. */
-}
-#endif
-
-
-void
-pci_flush_write(ci_t *ci)
-{
-	volatile u_int32_t v;
-
-    /* issue a PCI read to flush PCI write thru bridge */
-	v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
-
-    /*
-     * return nothing, this just reads PCI bridge interface to flush
-     * previously written data
-     */
-}
-
-
-static void
-watchdog_func(unsigned long arg)
-{
-	struct watchdog *wd = (void *) arg;
-
-	if (drvr_state != SBE_DRVR_AVAILABLE) {
-		if (cxt1e1_log_level >= LOG_MONITOR)
-			pr_warning("%s: drvr not available (%x)\n",
-				   __func__, drvr_state);
-		return;
-	}
-	schedule_work(&wd->work);
-	mod_timer(&wd->h, jiffies + wd->ticks);
-}
-
-int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *),
-		     void *c, int usec)
-{
-	wdp->func = f;
-	wdp->softc = c;
-	wdp->ticks = (HZ) * (usec / 1000) / 1000;
-	INIT_WORK(&wdp->work, (void *)f);
-	init_timer(&wdp->h);
-	{
-		ci_t       *ci = (ci_t *) c;
-
-		wdp->h.data = (unsigned long) &ci->wd;
-	}
-	wdp->h.function = watchdog_func;
-	return 0;
-}
-
-void
-OS_uwait(int usec, char *description)
-{
-	int         tmp;
-
-	if (usec >= 1000) {
-		mdelay(usec / 1000);
-		/* now delay residual */
-		tmp = (usec / 1000) * 1000; /* round */
-		tmp = usec - tmp;           /* residual */
-		if (tmp) {                           /* wait on residual */
-			udelay(tmp);
-		}
-	} else {
-		udelay(usec);
-	}
-}
-
-/* dummy short delay routine called as a subroutine so that compiler
- * does not optimize/remove its intent (a short delay)
- */
-
-void
-OS_uwait_dummy(void)
-{
-#ifndef USE_MAX_INT_DELAY
-	dummy++;
-#else
-	udelay(1);
-#endif
-}
-
-
-void
-OS_sem_init(void *sem, int state)
-{
-	switch (state) {
-	case SEM_TAKEN:
-	    sema_init((struct semaphore *) sem, 0);
-	    break;
-	case SEM_AVAILABLE:
-	    sema_init((struct semaphore *) sem, 1);
-	    break;
-	default:                        /* otherwise, set sem.count to state's
-					* value */
-	    sema_init(sem, state);
-	    break;
-	}
-}
-
-
-int
-sd_line_is_ok(void *user)
-{
-	struct net_device *ndev = (struct net_device *) user;
-
-	return netif_carrier_ok(ndev);
-}
-
-void
-sd_line_is_up(void *user)
-{
-	struct net_device *ndev = (struct net_device *) user;
-
-	netif_carrier_on(ndev);
-	return;
-}
-
-void
-sd_line_is_down(void *user)
-{
-	struct net_device *ndev = (struct net_device *) user;
-
-	netif_carrier_off(ndev);
-	return;
-}
-
-void
-sd_disable_xmit(void *user)
-{
-	struct net_device *dev = (struct net_device *) user;
-
-	netif_stop_queue(dev);
-	return;
-}
-
-void
-sd_enable_xmit(void *user)
-{
-	struct net_device *dev = (struct net_device *) user;
-
-	netif_wake_queue(dev);
-	return;
-}
-
-int
-sd_queue_stopped(void *user)
-{
-	struct net_device *ndev = (struct net_device *) user;
-
-	return netif_queue_stopped(ndev);
-}
-
-void sd_recv_consume(void *token, size_t len, void *user)
-{
-	struct net_device *ndev = user;
-	struct sk_buff *skb = token;
-
-	skb->dev = ndev;
-	skb_put(skb, len);
-	skb->protocol = hdlc_type_trans(skb, ndev);
-	netif_rx(skb);
-}
-
-
-/**
- ** Read some reserved location w/in the COMET chip as a usable
- ** VMETRO trigger point or other trace marking event.
- **/
-
-#include "comet.h"
-
-extern ci_t *CI;                /* dummy pointer to board ZERO's data */
-void
-VMETRO_TRIGGER(ci_t *ci, int x)
-{
-	struct s_comet_reg    *comet;
-	volatile u_int32_t data;
-
-	comet = ci->port[0].cometbase;  /* default to COMET # 0 */
-
-	switch (x) {
-	default:
-	case 0:
-	    data = pci_read_32((u_int32_t *) &comet->__res24);     /* 0x90 */
-	    break;
-	case 1:
-	    data = pci_read_32((u_int32_t *) &comet->__res25);     /* 0x94 */
-	    break;
-	case 2:
-	    data = pci_read_32((u_int32_t *) &comet->__res26);     /* 0x98 */
-	    break;
-	case 3:
-	    data = pci_read_32((u_int32_t *) &comet->__res27);     /* 0x9C */
-	    break;
-	case 4:
-	    data = pci_read_32((u_int32_t *) &comet->__res88);     /* 0x220 */
-	    break;
-	case 5:
-	    data = pci_read_32((u_int32_t *) &comet->__res89);     /* 0x224 */
-	    break;
-	case 6:
-	    data = pci_read_32((u_int32_t *) &comet->__res8A);     /* 0x228 */
-	    break;
-	case 7:
-	    data = pci_read_32((u_int32_t *) &comet->__res8B);     /* 0x22C */
-	    break;
-	case 8:
-	    data = pci_read_32((u_int32_t *) &comet->__resA0);     /* 0x280 */
-	    break;
-	case 9:
-	    data = pci_read_32((u_int32_t *) &comet->__resA1);     /* 0x284 */
-	    break;
-	case 10:
-	    data = pci_read_32((u_int32_t *) &comet->__resA2);     /* 0x288 */
-	    break;
-	case 11:
-	    data = pci_read_32((u_int32_t *) &comet->__resA3);     /* 0x28C */
-	    break;
-	case 12:
-	    data = pci_read_32((u_int32_t *) &comet->__resA4);     /* 0x290 */
-	    break;
-	case 13:
-	    data = pci_read_32((u_int32_t *) &comet->__resA5);     /* 0x294 */
-	    break;
-	case 14:
-	    data = pci_read_32((u_int32_t *) &comet->__resA6);     /* 0x298 */
-	    break;
-	case 15:
-	    data = pci_read_32((u_int32_t *) &comet->__resA7);     /* 0x29C */
-	    break;
-	case 16:
-	    data = pci_read_32((u_int32_t *) &comet->__res74);     /* 0x1D0 */
-	    break;
-	case 17:
-	    data = pci_read_32((u_int32_t *) &comet->__res75);     /* 0x1D4 */
-	    break;
-	case 18:
-	    data = pci_read_32((u_int32_t *) &comet->__res76);     /* 0x1D8 */
-	    break;
-	case 19:
-	    data = pci_read_32((u_int32_t *) &comet->__res77);     /* 0x1DC */
-	    break;
-	}
-}
-
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/hwprobe.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/hwprobe.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/hwprobe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/hwprobe.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,382 +0,0 @@
-/* Copyright (C) 2007  One Stop Systems
- * Copyright (C) 2003-2005  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/netdevice.h>
-#include <linux/hdlc.h>
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-#include <linux/rtnetlink.h>
-#include <linux/pci.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4_private.h"
-#include "pmcc4.h"
-#include "pmcc4_ioctls.h"
-#include "pmc93x6_eeprom.h"
-#ifdef CONFIG_PROC_FS
-#include "sbeproc.h"
-#endif
-
-extern int  error_flag;
-extern int  drvr_state;
-
-/* forward references */
-void        c4_stopwd(ci_t *);
-struct net_device * __init c4_add_dev(hdw_info_t *, int, unsigned long,
-				      unsigned long, int, int);
-
-
-struct s_hdw_info hdw_info[MAX_BOARDS];
-
-
-void __init
-show_two(hdw_info_t *hi, int brdno)
-{
-	ci_t       *ci;
-	struct pci_dev *pdev;
-	char       *bid;
-	char       banner[80];
-	char	sn[6] = {0,};
-
-	ci = (ci_t *)(netdev_priv(hi->ndev));
-	bid = sbeid_get_bdname(ci);
-	switch (hi->promfmt) {
-	case PROM_FORMAT_TYPE1:
-		memcpy(sn, hi->mfg_info.pft1.Serial, 6);
-		break;
-	case PROM_FORMAT_TYPE2:
-		memcpy(sn, hi->mfg_info.pft2.Serial, 6);
-		break;
-	}
-
-	sprintf(banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
-		hi->devname, bid,
-		((sn[3] << 16) & 0xff0000) |
-		((sn[4] << 8) & 0x00ff00) |
-		(sn[5] & 0x0000ff),
-		(u_int8_t) hi->revid[0]);
-
-	pr_info("%s\n", banner);
-
-	pdev = hi->pdev[0];
-	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-		hi->devname, "MUSYCC",
-		(unsigned long) hi->addr_mapped[0], hi->addr[0],
-		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
-		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
-
-	pdev = hi->pdev[1];
-	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-		hi->devname, "EBUS  ",
-		(unsigned long) hi->addr_mapped[1], hi->addr[1],
-		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
-		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
-}
-
-
-void __init
-hdw_sn_get(hdw_info_t *hi, int brdno)
-{
-	/* obtain hardware EEPROM information */
-	long        addr;
-
-	addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
-
-	/* read EEPROM with largest known format size... */
-	pmc_eeprom_read_buffer(addr, 0, (char *)hi->mfg_info.data,
-			       sizeof(FLD_TYPE2));
-
-#if 0
-	{
-		unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
-
-		pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3),
-			*(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
-		pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11),
-			*(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
-		pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19),
-			*(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
-		pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27),
-			*(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
-		pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35),
-			*(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
-		pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-			*(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43),
-			*(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
-	}
-#endif
-#if 0
-	pr_info("sn: %x %x %x %x %x %x\n",
-			hi->mfg_info.Serial[0],
-			hi->mfg_info.Serial[1],
-			hi->mfg_info.Serial[2],
-			hi->mfg_info.Serial[3],
-			hi->mfg_info.Serial[4],
-			hi->mfg_info.Serial[5]);
-#endif
-
-	hi->promfmt = pmc_verify_cksum(&hi->mfg_info.data);
-	if (hi->promfmt == PROM_FORMAT_Unk) {
-		/* bad crc, data is suspect */
-		if (cxt1e1_log_level >= LOG_WARN)
-			pr_info("%s: EEPROM cksum error\n", hi->devname);
-		hi->mfg_info_sts = EEPROM_CRCERR;
-	} else
-		hi->mfg_info_sts = EEPROM_OK;
-}
-
-
-	void __init
-prep_hdw_info(void)
-{
-	hdw_info_t *hi;
-	int         i;
-
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		hi->pci_busno = 0xff;
-		hi->pci_slot = 0xff;
-		hi->pci_pin[0] = 0;
-		hi->pci_pin[1] = 0;
-		hi->ndev = NULL;
-		hi->addr[0] = 0L;
-		hi->addr[1] = 0L;
-		hi->addr_mapped[0] = NULL;
-		hi->addr_mapped[1] = NULL;
-	}
-}
-
-void
-cleanup_ioremap(void)
-{
-	hdw_info_t *hi;
-	int         i;
-
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->pci_slot == 0xff)
-			break;
-		if (hi->addr_mapped[0]) {
-			iounmap(hi->addr_mapped[0]);
-			release_mem_region((long) hi->addr[0], hi->len[0]);
-			hi->addr_mapped[0] = NULL;
-		}
-		if (hi->addr_mapped[1]) {
-			iounmap(hi->addr_mapped[1]);
-			release_mem_region((long) hi->addr[1], hi->len[1]);
-			hi->addr_mapped[1] = NULL;
-		}
-	}
-}
-
-
-void
-cleanup_devs(void)
-{
-	hdw_info_t *hi;
-	int         i;
-
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->pci_slot == 0xff || !hi->ndev)
-			break;
-		c4_stopwd(netdev_priv(hi->ndev));
-#ifdef CONFIG_PROC_FS
-		sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
-#endif
-		unregister_netdev(hi->ndev);
-		free_irq(hi->pdev[0]->irq, hi->ndev);
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-		free_irq(hi->pdev[1]->irq, hi->ndev);
-#endif
-		kfree(hi->ndev);
-	}
-}
-
-
-static int  __init
-c4_hdw_init(struct pci_dev *pdev, int found)
-{
-	hdw_info_t *hi;
-	int         i;
-	int         fun, slot;
-	unsigned char busno = 0xff;
-
-	/* our MUSYCC chip supports two functions, 0 & 1 */
-	fun = PCI_FUNC(pdev->devfn);
-	if (fun > 1) {
-		pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
-		return 0;
-	}
-
-	/* obtain bus number */
-	if (pdev->bus)
-		busno = pdev->bus->number;
-	else
-		busno = 0; /* default for system PCI inconsistency */
-	slot = pdev->devfn & ~0x07;
-
-	/*
-	 * Functions 0 & 1 for a given board (identified by same bus(busno) and
-	 * slot(slot)) are placed into the same 'hardware' structure.  The first
-	 * part of the board's functionality will be placed into an unpopulated
-	 * element, identified by "slot==(0xff)".  The second part of a board's
-	 * functionality will match the previously loaded slot/busno.
-	 */
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		/*
-		 * match with board's first found interface, otherwise this is
-		 * fisrt found
-		 */
-		if ((hi->pci_slot == 0xff) ||   /* new board */
-		    ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
-			break;                  /* found for-loop exit */
-	}
-
-	/* no match in above loop means MAX exceeded */
-	if (i == MAX_BOARDS) {
-		pr_warning("exceeded number of allowed devices (>%d)?\n",
-			   MAX_BOARDS);
-		return 0;
-	}
-
-	if (pdev->bus)
-		hi->pci_busno = pdev->bus->number;
-	else
-		hi->pci_busno = 0; /* default for system PCI inconsistency */
-
-	hi->pci_slot = slot;
-	pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hi->revid[fun]);
-	hi->bus = pdev->bus;
-	hi->addr[fun] = pci_resource_start(pdev, 0);
-	hi->len[fun] = pci_resource_end(pdev, 0) - hi->addr[fun] + 1;
-	hi->pdev[fun] = pdev;
-
-	{
-		/*
-		 * create device name from module name, plus add the appropriate
-		 * board number
-		 */
-		char       *cp = hi->devname;
-
-		strcpy(cp, KBUILD_MODNAME);
-		cp += strlen(cp);          /* reposition */
-		*cp++ = '-';
-		*cp++ = '0' + (found / 2);  /* there are two found interfaces per
-		* board */
-		*cp = 0;                    /* termination */
-	}
-
-	return 1;
-}
-
-status_t __init
-c4hw_attach_all(void)
-{
-	hdw_info_t *hi;
-	struct pci_dev *pdev = NULL;
-	int         found = 0, i, j;
-
-	error_flag = 0;
-	prep_hdw_info();
-	/*** scan PCI bus for all possible boards */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_CONEXANT,
-				      PCI_DEVICE_ID_CN8474,
-				      pdev))) {
-		if (c4_hdw_init(pdev, found))
-			found++;
-	}
-
-	if (!found) {
-		pr_warning("No boards found\n");
-		return -ENODEV;
-	}
-
-	/* sanity check for consistent hardware found */
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1])) {
-			pr_warning("%s: something very wrong with pci_get_device\n",
-				   hi->devname);
-			return -EIO;
-		}
-	}
-	/* bring board's memory regions on/line */
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->pci_slot == 0xff)
-			break;
-		for (j = 0; j < 2; j++) {
-			if (!request_mem_region(hi->addr[j], hi->len[j], hi->devname)) {
-				pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
-					   hi->devname, hi->addr[j], hi->len[j]);
-				cleanup_ioremap();
-				return -ENOMEM;
-			}
-
-			hi->addr_mapped[j] = ioremap(hi->addr[j], hi->len[j]);
-			if (!hi->addr_mapped[j]) {
-				pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
-					   hi->devname, hi->addr[j], hi->len[j]);
-				cleanup_ioremap();
-				return -ENOMEM;
-			}
-#ifdef SBE_MAP_DEBUG
-			pr_warning("%s: io remapped from phys %x to virt %x\n",
-				   hi->devname, (u_int32_t) hi->addr[j],
-				   (u_int32_t) hi->addr_mapped[j]);
-#endif
-		}
-	}
-
-	drvr_state = SBE_DRVR_AVAILABLE;
-
-	/* Have now memory mapped all boards.  Now allow board's access to system */
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->pci_slot == 0xff)
-			break;
-		if (pci_enable_device(hi->pdev[0]) ||
-		    pci_enable_device(hi->pdev[1])) {
-			drvr_state = SBE_DRVR_DOWN;
-			pr_warning("%s: failed to enable card %d slot %d\n",
-				   hi->devname, i, hi->pci_slot);
-			cleanup_devs();
-			cleanup_ioremap();
-			return -EIO;
-		}
-		pci_set_master(hi->pdev[0]);
-		pci_set_master(hi->pdev[1]);
-		hi->ndev = c4_add_dev(hi, i, (long) hi->addr_mapped[0],
-				      (long) hi->addr_mapped[1],
-				      hi->pdev[0]->irq,
-				      hi->pdev[1]->irq);
-		if (!hi->ndev) {
-			drvr_state = SBE_DRVR_DOWN;
-			cleanup_ioremap();
-			/* NOTE: c4_add_dev() does its own device cleanup */
-#if 0
-			cleanup_devs();
-#endif
-			return error_flag; /* error_flag set w/in add_dev() */
-		}
-		show_two(hi, i); /* displays found information */
-	}
-	return 0;
-}
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-config CXT1E1
-	tristate "SBE wanPMC-C[421]E1T1 hardware support"
-	depends on HDLC && PCI
-	---help---
-      This driver supports the SBE wanPMC-CxT1E1 1, 2 and 4 port T3
-      channelized stream WAN adapter card which contains a HDLC/Transparent
-      mode controller.
-
-      If you want to compile this driver as a module say M here.
-      The module will be called 'cxt1e1'.
-
-      If unsure, say N.
-
-config SBE_PMCC4_NCOMM
-	bool "SBE PMCC4 NCOMM support"
-	depends on CXT1E1
-	---help---
-      SBE supplies optional support for NCOMM products.
-
-      If you have purchased this optional support you must say Y
-      here to allow the driver to operate with the NCOMM product.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/libsbew.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/libsbew.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/libsbew.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/libsbew.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,549 +0,0 @@
-#ifndef _INC_LIBSBEW_H_
-#define _INC_LIBSBEW_H_
-
-/*-----------------------------------------------------------------------------
- * libsbew.h - common library elements, charge across mulitple boards
- *
- *   This file contains common Ioctl structures and contents definitions.
- *
- * Copyright (C) 2004-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-/********************************/
-/**  set driver logging level  **/
-/********************************/
-
-/* routine/ioctl: wancfg_set_loglevel() - SBE_IOC_SET_LOGLEVEL */
-
-#define LOG_NONE          0
-#define LOG_ERROR         1
-#define LOG_SBEBUG3       3     /* hidden, for development/debug usage */
-#define LOG_LSCHANGE      5     /* line state change logging */
-#define LOG_LSIMMEDIATE   6     /* line state change logging w/o hysterisis */
-#define LOG_WARN          8
-#define LOG_MONITOR      10
-#define LOG_SBEBUG12     12     /* hidden, for development/debug usage */
-#define LOG_MONITOR2     14     /* hidden, for development/debug usage */
-#define LOG_DEBUG        16
-
-    /* TEMPORARY DEFINES *//* RLD DEBUG */
-#define c4_LOG_NONE      LOG_NONE
-#define c4_LOG_ERROR     LOG_ERROR
-#define c4_LOG_WARN      LOG_WARN
-#define c4_LOG_sTrace    LOG_MONITOR    /* do some trace logging into
-                                         * functions */
-#define c4_LOG_DEBUG     LOG_DEBUG
-#define c4_LOG_MAX       LOG_DEBUG
-
-
-
-/******************************/
-/**  get driver information  **/
-/******************************/
-
-/* routine/ioctl: wancfg_get_drvinfo() - SBE_IOC_GET_DRVINFO */
-
-#define REL_STRLEN   80
-    struct sbe_drv_info
-    {
-        int         rel_strlen;
-        char        release[REL_STRLEN];
-    };
-
-
-/*****************************/
-/**  get board information  **/
-/*****************************/
-
-/* routine/ioctl: wancfg_get_brdinfo() - SBE_IOC_GET_BRDINFO */
-
-#define CHNM_STRLEN   16
-    struct sbe_brd_info
-    {
-        u_int32_t brd_id;       /* SBE's unique PCI VENDOR/DEVID */
-        u_int32_t   brd_sn;
-        int         brd_chan_cnt;       /* number of channels being used */
-        int         brd_port_cnt;       /* number of ports being used */
-        unsigned char brdno;    /* our board number */
-        unsigned char brd_pci_speed;    /* PCI speed, 33/66Mhz */
-                    u_int8_t brd_mac_addr[6];
-        char        first_iname[CHNM_STRLEN];   /* first assigned channel's
-                                                 * interface name */
-        char        last_iname[CHNM_STRLEN];    /* last assigned channel's
-                                                 * interface name */
-        u_int8_t    brd_hdw_id; /* on/board unique hdw ID */
-        u_int8_t    reserved8[3];       /* alignment preservation */
-        u_int32_t   reserved32[3];      /* size preservation */
-    };
-
-/* These IDs are sometimes available thru pci_ids.h, but not currently. */
-
-#define PCI_VENDOR_ID_SBE              0x1176
-#define PCI_DEVICE_ID_WANPMC_C4T1E1    0x0701   /* BID 0x0X, BTYP 0x0X */
-#define PCI_DEVICE_ID_WANPTMC_C4T1E1   0x0702   /* BID 0x41 */
-#define PCI_DEVICE_ID_WANADAPT_HC4T1E1 0x0703   /* BID 0x44 */
-#define PCI_DEVICE_ID_WANPTMC_256T3_T1 0x0704   /* BID 0x42 (T1 Version) */
-#define PCI_DEVICE_ID_WANPCI_C4T1E1    0x0705   /* BID 0x1X, BTYP 0x0X */
-#define PCI_DEVICE_ID_WANPMC_C1T3      0x0706   /* BID 0x45 */
-#define PCI_DEVICE_ID_WANPCI_C2T1E1    0x0707   /* BID 0x1X, BTYP 0x2X */
-#define PCI_DEVICE_ID_WANPCI_C1T1E1    0x0708   /* BID 0x1X, BTYP 0x1X */
-#define PCI_DEVICE_ID_WANPMC_C2T1E1    0x0709   /* BID 0x0X, BTYP 0x2X */
-#define PCI_DEVICE_ID_WANPMC_C1T1E1    0x070A   /* BID 0x0X, BTYP 0x1X */
-#define PCI_DEVICE_ID_WANPTMC_256T3_E1 0x070B   /* BID 0x46 (E1 Version) */
-#define PCI_DEVICE_ID_WANPTMC_C24TE1   0x070C   /* BID 0x47 */
-#define PCI_DEVICE_ID_WANPMC_C4T1E1_L  0x070D   /* BID 0x2X, BTYPE 0x0X w/FP
-                                                 * LEDs */
-#define PCI_DEVICE_ID_WANPMC_C2T1E1_L  0x070E   /* BID 0x2X, BTYPE 0x2X w/FP
-                                                 * LEDs */
-#define PCI_DEVICE_ID_WANPMC_C1T1E1_L  0x070F   /* BID 0x2X, BTYPE 0x1X w/FP
-                                                 * LEDs */
-#define PCI_DEVICE_ID_WANPMC_2SSI      0x0801
-#define PCI_DEVICE_ID_WANPCI_4SSI      0x0802
-#define PCI_DEVICE_ID_WANPMC_2T3E3     0x0900   /* BID 0x43 */
-#define SBE_BOARD_ID(v,id)           ((v<<16) | id)
-
-#define BINFO_PCI_SPEED_unk     0
-#define BINFO_PCI_SPEED_33      1
-#define BINFO_PCI_SPEED_66      2
-
-/***************************/
-/**  obtain interface ID  **/
-/***************************/
-
-/* routine/ioctl: wancfg_get_iid() - SBE_IOC_IID_GET */
-
-    struct sbe_iid_info
-    {
-        u_int32_t   channum;    /* channel requested */
-        char        iname[CHNM_STRLEN]; /* channel's interface name */
-    };
-
-/**************************************/
-/**  get board address information  **/
-/**************************************/
-
-/* routine/ioctl: wancfg_get_brdaddr() - SBE_IOC_BRDADDR_GET */
-
-    struct sbe_brd_addr
-    {
-        unsigned char func;     /* select PCI address space function */
-        unsigned char brdno;    /* returns brdno requested */
-        unsigned char irq;
-        unsigned char size;     /* returns size of address */
-#define BRDADDR_SIZE_64  1
-#define BRDADDR_SIZE_32  2
-        int         reserved1;  /* mod64 align, reserved for future use */
-
-        union
-        {
-            unsigned long virt64;       /* virtual/mapped address */
-            u_int32_t   virt32[2];
-        }           v;
-        union
-        {
-            unsigned long phys64;       /* physical bus address */
-            u_int32_t   phys32[2];
-        }           p;
-        int         reserved2[4];       /* reserved for future use */
-    };
-
-/**********************************/
-/**  read/write board registers  **/
-/**********************************/
-
-/* routine/ioctl: wancfg_read_vec() - SBE_IOC_READ_VEC */
-/* routine/ioctl: wancfg_write_vec() - SBE_IOC_WRITE_VEC */
-
-    struct sbecom_wrt_vec
-    {
-        u_int32_t   reg;
-        u_int32_t   data;
-    };
-
-#define C1T3_CHIP_MSCC_32        0x01000000
-#define C1T3_CHIP_TECT3_8        0x02000000
-#define C1T3_CHIP_CPLD_8         0x03000000
-#define C1T3_CHIP_EEPROM_8       0x04000000
-
-#define W256T3_CHIP_MUSYCC_32    0x02000000
-#define W256T3_CHIP_TEMUX_8      0x10000000
-#define W256T3_CHIP_T8110_8      0x20000000
-#define W256T3_CHIP_T8110_32     0x22000000
-#define W256T3_CHIP_CPLD_8       0x30000000
-#define W256T3_CHIP_EEPROM_8     0x40000000
-
-
-/**********************************/
-/**  read write port parameters  **/
-/**********************************/
-
-/* routine/ioctl: wancfg_getset_port_param() - SBE_IOC_PORT_GET */
-/* routine/ioctl: wancfg_set_port_param() - SBE_IOC_PORT_SET */
-
-/* NOTE: this structure supports hardware which supports individual per/port control */
-
-struct sbecom_port_param
-{
-    u_int8_t    portnum;
-    u_int8_t    port_mode;           /* variations of T1 or E1 mode */
-    u_int8_t    portStatus;
-    u_int8_t    portP;          /* more port parameters (clock source - 0x80;
-                                 * and LBO - 0xf; */
-                                /* bits 0x70 are reserved for future use ) */
-#ifdef SBE_PMCC4_ENABLE
-	u_int32_t   hypersize;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
-#endif
-    int         reserved[3-1];    /* reserved for future use */
-    int    _res[4];
-};
-
-#define CFG_CLK_PORT_MASK      0x80     /* Loop timing */
-#define CFG_CLK_PORT_INTERNAL  0x80     /* Loop timing */
-#define CFG_CLK_PORT_EXTERNAL  0x00     /* Loop timing */
-
-#define CFG_LBO_MASK      0x0F
-#define CFG_LBO_unk       0     /* <not defined> */
-#define CFG_LBO_LH0       1     /* T1 Long Haul (default) */
-#define CFG_LBO_LH7_5     2     /* T1 Long Haul */
-#define CFG_LBO_LH15      3     /* T1 Long Haul */
-#define CFG_LBO_LH22_5    4     /* T1 Long Haul */
-#define CFG_LBO_SH110     5     /* T1 Short Haul */
-#define CFG_LBO_SH220     6     /* T1 Short Haul */
-#define CFG_LBO_SH330     7     /* T1 Short Haul */
-#define CFG_LBO_SH440     8     /* T1 Short Haul */
-#define CFG_LBO_SH550     9     /* T1 Short Haul */
-#define CFG_LBO_SH660     10    /* T1 Short Haul */
-#define CFG_LBO_E75       11    /* E1 75 Ohm */
-#define CFG_LBO_E120      12    /* E1 120 Ohm (default) */
-
-
-/*************************************/
-/**  read write channel parameters  **/
-/*************************************/
-
-/* routine/ioctl: wancfg_getset_chan_param() - SBE_IOC_CHAN_GET */
-/* routine/ioctl: wancfg_set_chan_param() - SBE_IOC_CHAN_SET */
-
-/* NOTE: this structure supports hardware which supports individual per/channel control */
-
-    struct sbecom_chan_param
-    {
-        u_int32_t   channum;    /* 0: */
-#ifdef SBE_PMCC4_ENABLE
-	u_int32_t   card;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
-	u_int32_t   port;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
-	u_int8_t bitmask[32];
-#endif
-        u_int32_t   intr_mask;  /* 4: interrupt mask, specify ored
-                                 * (SS7_)INTR_* to disable */
-        u_int8_t    status;     /* 8: channel transceiver status (TX_ENABLED,
-                                 * RX_ENABLED) */
-        u_int8_t    chan_mode;  /* 9: protocol mode */
-        u_int8_t    idlecode;   /* A: idle code, in (FLAG_7E, FLAG_FF,
-                                 * FLAG_00) */
-        u_int8_t    pad_fill_count;     /* B: pad fill count (1-127), 0 - pad
-                                         * fill disabled */
-        u_int8_t    data_inv;   /* C: channel data inversion selection */
-        u_int8_t    mode_56k;   /* D: 56kbps mode */
-        u_int8_t    reserved[2 + 8];    /* E: */
-    };
-
-/* SS7 interrupt signals <intr_mask> */
-#define SS7_INTR_SFILT      0x00000020
-#define SS7_INTR_SDEC       0x00000040
-#define SS7_INTR_SINC       0x00000080
-#define SS7_INTR_SUERR      0x00000100
-/* Other interrupts that can be masked */
-#define INTR_BUFF           0x00000002
-#define INTR_EOM            0x00000004
-#define INTR_MSG            0x00000008
-#define INTR_IDLE           0x00000010
-
-/* transceiver status flags <status> */
-#define TX_ENABLED          0x01
-#define RX_ENABLED          0x02
-
-/* Protocol modes <mode> */
-#define CFG_CH_PROTO_TRANS         0
-#define CFG_CH_PROTO_SS7           1
-#define CFG_CH_PROTO_HDLC_FCS16    2
-#define CFG_CH_PROTO_HDLC_FCS32    3
-#define CFG_CH_PROTO_ISLP_MODE     4
-
-/* Possible idle code assignments <idlecode> */
-#define CFG_CH_FLAG_7E      0
-#define CFG_CH_FLAG_FF      1
-#define CFG_CH_FLAG_00      2
-
-/* data inversion selection <data_inv> */
-#define CFG_CH_DINV_NONE    0x00
-#define CFG_CH_DINV_RX      0x01
-#define CFG_CH_DINV_TX      0x02
-
-
-/* Possible resettable chipsets/functions */
-#define RESET_DEV_TEMUX     1
-#define RESET_DEV_TECT3     RESET_DEV_TEMUX
-#define RESET_DEV_PLL       2
-
-
-/*********************************************/
-/**  read reset channel thruput statistics  **/
-/*********************************************/
-
-/* routine/ioctl: wancfg_get_chan_stats() - SBE_IOC_CHAN_GET_STAT */
-/* routine/ioctl: wancfg_del_chan_stats() - SBE_IOC_CHAN_DEL_STAT */
-/* routine/ioctl: wancfg_get_card_chan_stats() - SBE_IOC_CARD_CHAN_STAT */
-
-    struct sbecom_chan_stats
-    {
-        unsigned long rx_packets;       /* total packets received       */
-        unsigned long tx_packets;       /* total packets transmitted    */
-        unsigned long rx_bytes; /* total bytes received         */
-        unsigned long tx_bytes; /* total bytes transmitted      */
-        unsigned long rx_errors;/* bad packets received         */
-        unsigned long tx_errors;/* packet transmit problems     */
-        unsigned long rx_dropped;       /* no space in linux buffers    */
-        unsigned long tx_dropped;       /* no space available in linux  */
-
-        /* detailed rx_errors: */
-        unsigned long rx_length_errors;
-        unsigned long rx_over_errors;   /* receiver ring buff overflow  */
-        unsigned long rx_crc_errors;    /* recved pkt with crc error    */
-        unsigned long rx_frame_errors;  /* recv'd frame alignment error */
-        unsigned long rx_fifo_errors;   /* recv'r fifo overrun          */
-        unsigned long rx_missed_errors; /* receiver missed packet       */
-
-        /* detailed tx_errors */
-        unsigned long tx_aborted_errors;
-        unsigned long tx_fifo_errors;
-        unsigned long tx_pending;
-    };
-
-
-/****************************************/
-/**  read write card level parameters  **/
-/****************************************/
-
- /* NOTE: this structure supports hardware which supports per/card control */
-
-    struct sbecom_card_param
-    {
-        u_int8_t    framing_type;       /* 0: CBP or M13 */
-        u_int8_t    loopback;   /* 1: one of LOOPBACK_* */
-        u_int8_t    line_build_out;     /* 2: boolean */
-        u_int8_t    receive_eq; /* 3: boolean */
-        u_int8_t    transmit_ones;      /* 4: boolean */
-        u_int8_t    clock;      /* 5: 0 - internal, i>0 - external (recovered
-                                 * from framer i) */
-        u_int8_t    h110enable; /* 6: */
-        u_int8_t    disable_leds;       /* 7: */
-        u_int8_t    reserved1;  /* 8: available - old 256t3 hypersized, but
-                                 * never used */
-        u_int8_t    rear_io;    /* 9: rear I/O off/on */
-        u_int8_t    disable_tx; /* A: disable TX off/on */
-        u_int8_t    mute_los;   /* B: mute LOS off/on */
-        u_int8_t    los_threshold;      /* C: LOS threshold norm/low
-                                         * (default: norm) */
-        u_int8_t    ds1_mode;   /* D: DS1 mode T1/E1 (default: T1) */
-        u_int8_t    ds3_unchan; /* E: DS3 unchannelized mode off/on */
-        u_int8_t    reserved[1 + 16];   /* reserved for expansion - must be
-                                         * ZERO filled */
-    };
-
-/* framing types <framing_type> */
-#define FRAMING_M13                0
-#define FRAMING_CBP                1
-
-/* card level loopback options <loopback> */
-#define CFG_CARD_LOOPBACK_NONE     0x00
-#define CFG_CARD_LOOPBACK_DIAG     0x01
-#define CFG_CARD_LOOPBACK_LINE     0x02
-#define CFG_CARD_LOOPBACK_PAYLOAD  0x03
-
-/* line level loopback options <loopback> */
-#define CFG_LIU_LOOPBACK_NONE      0x00
-#define CFG_LIU_LOOPBACK_ANALOG    0x10
-#define CFG_LIU_LOOPBACK_DIGITAL   0x11
-#define CFG_LIU_LOOPBACK_REMOTE    0x12
-
-/* card level clock options <clock> */
-#define CFG_CLK_INTERNAL           0x00
-#define CFG_CLK_EXTERNAL           0x01
-
-/* legacy 256T3 loopback values */
-#define LOOPBACK_NONE              0
-#define LOOPBACK_LIU_ANALOG        1
-#define LOOPBACK_LIU_DIGITAL       2
-#define LOOPBACK_FRAMER_DS3        3
-#define LOOPBACK_FRAMER_T1         4
-#define LOOPBACK_LIU_REMOTE        5
-
-/* DS1 mode <ds1_mode> */
-#define CFG_DS1_MODE_MASK          0x0f
-#define CFG_DS1_MODE_T1            0x00
-#define CFG_DS1_MODE_E1            0x01
-#define CFG_DS1_MODE_CHANGE        0x80
-
-/* DS3 unchannelized values <ds1_unchan> */
-#define CFG_DS3_UNCHAN_MASK        0x01
-#define CFG_DS3_UNCHAN_OFF         0x00
-#define CFG_DS3_UNCHAN_ON          0x01
-
-
-/************************************/
-/**  read write framer parameters  **/
-/************************************/
-
-/* routine/ioctl: wancfg_get_framer() - SBE_IOC_FRAMER_GET */
-/* routine/ioctl: wancfg_set_framer() - SBE_IOC_FRAMER_SET */
-
-    struct sbecom_framer_param
-    {
-        u_int8_t    framer_num;
-        u_int8_t    frame_type; /* SF, ESF, E1PLAIN, E1CAS, E1CRC, E1CRC+CAS */
-        u_int8_t    loopback_type;      /* DIGITAL, LINE, PAYLOAD */
-        u_int8_t    auto_alarms;/* auto alarms */
-        u_int8_t    reserved[12];       /* reserved for expansion - must be
-                                         * ZERO filled */
-    };
-
-/* frame types <frame_type> */
-#define CFG_FRAME_NONE             0
-#define CFG_FRAME_SF               1    /* T1 B8ZS */
-#define CFG_FRAME_ESF              2    /* T1 B8ZS */
-#define CFG_FRAME_E1PLAIN          3    /* HDB3 w/o CAS,CRC */
-#define CFG_FRAME_E1CAS            4    /* HDB3 */
-#define CFG_FRAME_E1CRC            5    /* HDB3 */
-#define CFG_FRAME_E1CRC_CAS        6    /* HDB3 */
-#define CFG_FRAME_SF_AMI           7    /* T1 AMI */
-#define CFG_FRAME_ESF_AMI          8    /* T1 AMI */
-#define CFG_FRAME_E1PLAIN_AMI      9    /* E1 AMI w/o CAS,CRC */
-#define CFG_FRAME_E1CAS_AMI       10    /* E1 AMI */
-#define CFG_FRAME_E1CRC_AMI       11    /* E1 AMI */
-#define CFG_FRAME_E1CRC_CAS_AMI   12    /* E1 AMI */
-
-#define IS_FRAME_ANY_T1(field) \
-                    (((field) == CFG_FRAME_NONE) || \
-                     ((field) == CFG_FRAME_SF)   || \
-                     ((field) == CFG_FRAME_ESF)  || \
-                     ((field) == CFG_FRAME_SF_AMI) || \
-                     ((field) == CFG_FRAME_ESF_AMI))
-
-#define IS_FRAME_ANY_T1ESF(field) \
-                    (((field) == CFG_FRAME_ESF) || \
-                     ((field) == CFG_FRAME_ESF_AMI))
-
-#define IS_FRAME_ANY_E1(field) \
-                    (((field) == CFG_FRAME_E1PLAIN) || \
-                     ((field) == CFG_FRAME_E1CAS)   || \
-                     ((field) == CFG_FRAME_E1CRC)   || \
-                     ((field) == CFG_FRAME_E1CRC_CAS) || \
-                     ((field) == CFG_FRAME_E1PLAIN_AMI) || \
-                     ((field) == CFG_FRAME_E1CAS_AMI) || \
-                     ((field) == CFG_FRAME_E1CRC_AMI) || \
-                     ((field) == CFG_FRAME_E1CRC_CAS_AMI))
-
-#define IS_FRAME_ANY_AMI(field) \
-                    (((field) == CFG_FRAME_SF_AMI) || \
-                     ((field) == CFG_FRAME_ESF_AMI) || \
-                     ((field) == CFG_FRAME_E1PLAIN_AMI) || \
-                     ((field) == CFG_FRAME_E1CAS_AMI) || \
-                     ((field) == CFG_FRAME_E1CRC_AMI) || \
-                     ((field) == CFG_FRAME_E1CRC_CAS_AMI))
-
-/* frame level loopback options <loopback_type> */
-#define CFG_FRMR_LOOPBACK_NONE     0
-#define CFG_FRMR_LOOPBACK_DIAG     1
-#define CFG_FRMR_LOOPBACK_LINE     2
-#define CFG_FRMR_LOOPBACK_PAYLOAD  3
-
-
-/****************************************/
-/**  read reset card error statistics  **/
-/****************************************/
-
-/* routine/ioctl: wancfg_get_card_stats() - SBE_IOC_CARD_GET_STAT */
-/* routine/ioctl: wancfg_del_card_stats() - SBE_IOC_CARD_DEL_STAT */
-
-    struct temux_card_stats
-    {
-        struct temux_stats
-        {
-            /* TEMUX DS3 PMON counters */
-            u_int32_t   lcv;
-            u_int32_t   err_framing;
-            u_int32_t   febe;
-            u_int32_t   err_cpbit;
-            u_int32_t   err_parity;
-            /* TEMUX DS3 FRMR status */
-            u_int8_t    los;
-            u_int8_t    oof;
-            u_int8_t    red;
-            u_int8_t    yellow;
-            u_int8_t    idle;
-            u_int8_t    ais;
-            u_int8_t    cbit;
-            /* TEMUX DS3 FEAC receiver */
-            u_int8_t    feac;
-            u_int8_t    feac_last;
-        }           t;
-        u_int32_t   tx_pending; /* total */
-    };
-
-/**************************************************************/
-
-    struct wancfg
-    {
-        int         cs, ds;
-        char       *p;
-    };
-    typedef struct wancfg wcfg_t;
-
-    extern wcfg_t *wancfg_init(char *, char *);
-    extern int wancfg_card_blink(wcfg_t *, int);
-    extern int wancfg_ctl(wcfg_t *, int, void *, int, void *, int);
-    extern int wancfg_del_card_stats(wcfg_t *);
-    extern int wancfg_del_chan_stats(wcfg_t *, int);
-    extern int wancfg_enable_ports(wcfg_t *, int);
-    extern int wancfg_free(wcfg_t *);
-    extern int wancfg_get_brdaddr(wcfg_t *, struct sbe_brd_addr *);
-    extern int wancfg_get_brdinfo(wcfg_t *, struct sbe_brd_info *);
-    extern int wancfg_get_card(wcfg_t *, struct sbecom_card_param *);
-    extern int wancfg_get_card_chan_stats(wcfg_t *, struct sbecom_chan_stats *);
-    extern int wancfg_get_card_sn(wcfg_t *);
-    extern int wancfg_get_card_stats(wcfg_t *, struct temux_card_stats *);
-    extern int wancfg_get_chan(wcfg_t *, int, struct sbecom_chan_param *);
-    extern int wancfg_get_chan_stats(wcfg_t *, int, struct sbecom_chan_stats *);
-    extern int wancfg_get_drvinfo(wcfg_t *, int, struct sbe_drv_info *);
-    extern int wancfg_get_framer(wcfg_t *, int, struct sbecom_framer_param *);
-    extern int wancfg_get_iid(wcfg_t *, int, struct sbe_iid_info *);
-    extern int wancfg_get_sn(wcfg_t *, unsigned int *);
-    extern int wancfg_read(wcfg_t *, int, struct sbecom_wrt_vec *);
-    extern int wancfg_reset_device(wcfg_t *, int);
-    extern int wancfg_set_card(wcfg_t *, struct sbecom_card_param *);
-    extern int wancfg_set_chan(wcfg_t *, int, struct sbecom_chan_param *);
-    extern int wancfg_set_framer(wcfg_t *, int, struct sbecom_framer_param *);
-    extern int wancfg_set_loglevel(wcfg_t *, uint);
-    extern int wancfg_write(wcfg_t *, int, struct sbecom_wrt_vec *);
-
-#ifdef NOT_YET_COMMON
-    extern int  wancfg_get_tsioc(wcfg_t *, struct wanc1t3_ts_hdr *, struct wanc1t3_ts_param *);
-    extern int  wancfg_set_tsioc(wcfg_t *, struct wanc1t3_ts_param *);
-#endif
-
-#endif                          /*** _INC_LIBSBEW_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/linux.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/linux.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/linux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1142 +0,0 @@
-/* Copyright (C) 2007-2008  One Stop Systems
- * Copyright (C) 2003-2006  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/module.h>
-#include <linux/hdlc.h>
-#include <linux/if_arp.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/rtnetlink.h>
-#include <linux/skbuff.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4.h"
-#include "pmcc4_ioctls.h"
-#include "pmcc4_private.h"
-#include "sbeproc.h"
-
-/*******************************************************************************
- * Error out early if we have compiler trouble.
- *
- *   (This section is included from the kernel's init/main.c as a friendly
- *   spiderman recommendation...)
- *
- * Versions of gcc older than that listed below may actually compile and link
- * okay, but the end product can have subtle run time bugs.  To avoid associated
- * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
- * too old from the very beginning.
- */
-#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
-#error Sorry, your GCC is too old. It builds incorrect kernels.
-#endif
-
-#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0
-#warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
-#endif
-
-/*******************************************************************************/
-
-#define CHANNAME "hdlc"
-
-/*******************************************************************/
-/* forward references */
-status_t    c4_chan_work_init(mpi_t *, mch_t *);
-void        musycc_wq_chan_restart(void *);
-status_t __init c4_init(ci_t *, u_char *, u_char *);
-status_t __init c4_init2(ci_t *);
-int __init  c4hw_attach_all(void);
-void __init hdw_sn_get(hdw_info_t *, int);
-
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-irqreturn_t c4_ebus_intr_th_handler(void *);
-
-#endif
-int         c4_frame_rw(ci_t *, struct sbecom_port_param *);
-status_t    c4_get_port(ci_t *, int);
-int         c4_loop_port(ci_t *, int, u_int8_t);
-int         c4_musycc_rw(ci_t *, struct c4_musycc_param *);
-int         c4_new_chan(ci_t *, int, int, void *);
-status_t    c4_set_port(ci_t *, int);
-int         c4_pld_rw(ci_t *, struct sbecom_port_param *);
-void        cleanup_devs(void);
-void        cleanup_ioremap(void);
-status_t    musycc_chan_down(ci_t *, int);
-irqreturn_t musycc_intr_th_handler(void *);
-int         musycc_start_xmit(ci_t *, int, void *);
-
-extern ci_t *CI;
-extern struct s_hdw_info hdw_info[];
-
-int         error_flag;         /* module load error reporting */
-int         cxt1e1_log_level = LOG_ERROR;
-static int  log_level_default = LOG_ERROR;
-module_param(cxt1e1_log_level, int, 0444);
-
-int         cxt1e1_max_mru = MUSYCC_MRU;
-static int  max_mru_default = MUSYCC_MRU;
-module_param(cxt1e1_max_mru, int, 0444);
-
-int         cxt1e1_max_mtu = MUSYCC_MTU;
-int         max_mtu_default = MUSYCC_MTU;
-module_param(cxt1e1_max_mtu, int, 0444);
-
-int         max_txdesc_used = MUSYCC_TXDESC_MIN;
-int         max_txdesc_default = MUSYCC_TXDESC_MIN;
-module_param(max_txdesc_used, int, 0444);
-
-int         max_rxdesc_used = MUSYCC_RXDESC_MIN;
-int         max_rxdesc_default = MUSYCC_RXDESC_MIN;
-module_param(max_rxdesc_used, int, 0444);
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-void *
-getuserbychan(int channum)
-{
-	mch_t      *ch;
-
-	ch = c4_find_chan(channum);
-	return ch ? ch->user : NULL;
-}
-
-
-char *
-get_hdlc_name(hdlc_device *hdlc)
-{
-	struct c4_priv *priv = hdlc->priv;
-	struct net_device *dev = getuserbychan(priv->channum);
-
-	return dev->name;
-}
-
-/***************************************************************************/
-#include <linux/workqueue.h>
-
-/***
- * One workqueue (wq) per port (since musycc allows simultaneous group
- * commands), with individual data for each channel:
- *
- *   mpi_t -> struct workqueue_struct *wq_port;  (dynamically allocated using
- *                                               create_workqueue())
- *
- * With work structure (work) statically allocated for each channel:
- *
- *   mch_t -> struct work_struct ch_work;  (statically allocated using ???)
- *
- ***/
-
-
-/*
- * Called by the start transmit routine when a channel TX_ENABLE is to be
- * issued.  This queues the transmission start request among other channels
- * within a port's group.
- */
-void
-c4_wk_chan_restart(mch_t *ch)
-{
-	mpi_t      *pi = ch->up;
-
-#ifdef RLD_RESTART_DEBUG
-	pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
-		__func__, pi->portnum, ch->channum, ch);
-#endif
-
-	/* create new entry w/in workqueue for this channel and let'er rip */
-
-	/** queue_work(struct workqueue_struct *queue,
-	 **            struct work_struct *work);
-	 **/
-	queue_work(pi->wq_port, &ch->ch_work);
-}
-
-status_t
-c4_wk_chan_init(mpi_t *pi, mch_t *ch)
-{
-	/*
-	 * this will be used to restart a stopped channel
-	 */
-
-	/** INIT_WORK(struct work_struct *work,
-	 **           void (*function)(void *),
-	 **           void *data);
-	 **/
-	INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
-	return 0;                       /* success */
-}
-
-status_t
-c4_wq_port_init(mpi_t *pi)
-{
-
-	char        name[16];  /* NOTE: name of the queue limited by system
-				     * to 10 characters */
-	if (pi->wq_port)
-		return 0;                   /* already initialized */
-
-	/* IE pmcc4-01 */
-	snprintf(name, sizeof(name), "%s%d", pi->up->devname, pi->portnum);
-
-#ifdef RLD_RESTART_DEBUG
-	pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
-		__func__, name, pi->portnum); /* RLD DEBUG */
-#endif
-	pi->wq_port = create_singlethread_workqueue(name);
-	if (!pi->wq_port)
-		return -ENOMEM;
-	return 0;                       /* success */
-}
-
-void
-c4_wq_port_cleanup(mpi_t *pi)
-{
-	/*
-	 * PORT POINT: cannot call this if WQ is statically allocated w/in
-	 * structure since it calls kfree(wq);
-	 */
-	if (pi->wq_port) {
-		destroy_workqueue(pi->wq_port);        /* this also calls
-							* flush_workqueue() */
-		pi->wq_port = NULL;
-	}
-}
-
-/***************************************************************************/
-
-static irqreturn_t
-c4_linux_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *ndev = dev_instance;
-
-	return musycc_intr_th_handler(netdev_priv(ndev));
-}
-
-
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-static irqreturn_t
-c4_ebus_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *ndev = dev_instance;
-
-	return c4_ebus_intr_th_handler(netdev_priv(ndev));
-}
-#endif
-
-
-static int
-void_open(struct net_device *ndev)
-{
-	pr_info("%s: trying to open master device !\n", ndev->name);
-	return -1;
-}
-
-
-static int
-chan_open(struct net_device *ndev)
-{
-	hdlc_device *hdlc = dev_to_hdlc(ndev);
-	const struct c4_priv *priv = hdlc->priv;
-	int         ret;
-
-	ret = hdlc_open(ndev);
-	if (ret) {
-		pr_info("hdlc_open failure, err %d.\n", ret);
-		return ret;
-	}
-
-	ret = c4_chan_up(priv->ci, priv->channum);
-	if (ret < 0)
-		return ret;
-	try_module_get(THIS_MODULE);
-	netif_start_queue(ndev);
-	return 0;                       /* no error = success */
-}
-
-
-static int
-chan_close(struct net_device *ndev)
-{
-	hdlc_device *hdlc = dev_to_hdlc(ndev);
-	const struct c4_priv *priv = hdlc->priv;
-
-	netif_stop_queue(ndev);
-	musycc_chan_down((ci_t *) 0, priv->channum);
-	hdlc_close(ndev);
-	module_put(THIS_MODULE);
-	return 0;
-}
-
-
-static int
-chan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	return hdlc_ioctl(dev, ifr, cmd);
-}
-
-
-static int
-chan_attach_noop(struct net_device *ndev, unsigned short foo_1,
-		 unsigned short foo_2)
-{
-	/* our driver has nothing to do here, show's
-	 * over, go home
-	 */
-	return 0;
-}
-
-
-static struct net_device_stats *
-chan_get_stats(struct net_device *ndev)
-{
-	mch_t      *ch;
-	struct net_device_stats *nstats;
-	struct sbecom_chan_stats *stats;
-	int         channum;
-
-	{
-		struct c4_priv *priv;
-
-		priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
-		channum = priv->channum;
-	}
-
-	ch = c4_find_chan(channum);
-	if (ch == NULL)
-		return NULL;
-
-	nstats = &ndev->stats;
-	stats = &ch->s;
-
-	memset(nstats, 0, sizeof(struct net_device_stats));
-	nstats->rx_packets = stats->rx_packets;
-	nstats->tx_packets = stats->tx_packets;
-	nstats->rx_bytes = stats->rx_bytes;
-	nstats->tx_bytes = stats->tx_bytes;
-	nstats->rx_errors = stats->rx_length_errors +
-		stats->rx_over_errors +
-		stats->rx_crc_errors +
-		stats->rx_frame_errors +
-		stats->rx_fifo_errors +
-		stats->rx_missed_errors;
-	nstats->tx_errors = stats->tx_dropped +
-		stats->tx_aborted_errors +
-		stats->tx_fifo_errors;
-	nstats->rx_dropped = stats->rx_dropped;
-	nstats->tx_dropped = stats->tx_dropped;
-
-	nstats->rx_length_errors = stats->rx_length_errors;
-	nstats->rx_over_errors = stats->rx_over_errors;
-	nstats->rx_crc_errors = stats->rx_crc_errors;
-	nstats->rx_frame_errors = stats->rx_frame_errors;
-	nstats->rx_fifo_errors = stats->rx_fifo_errors;
-	nstats->rx_missed_errors = stats->rx_missed_errors;
-
-	nstats->tx_aborted_errors = stats->tx_aborted_errors;
-	nstats->tx_fifo_errors = stats->tx_fifo_errors;
-
-	return nstats;
-}
-
-
-static ci_t *
-get_ci_by_dev(struct net_device *ndev)
-{
-	return (ci_t *)(netdev_priv(ndev));
-}
-
-
-static int
-c4_linux_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	const struct c4_priv *priv;
-	int         rval;
-
-	hdlc_device *hdlc = dev_to_hdlc(ndev);
-
-	priv = hdlc->priv;
-
-	rval = musycc_start_xmit(priv->ci, priv->channum, skb);
-	return rval;
-}
-
-static const struct net_device_ops chan_ops = {
-	.ndo_open       = chan_open,
-	.ndo_stop       = chan_close,
-	.ndo_start_xmit = c4_linux_xmit,
-	.ndo_do_ioctl   = chan_dev_ioctl,
-	.ndo_get_stats  = chan_get_stats,
-};
-
-static struct net_device *
-create_chan(struct net_device *ndev, ci_t *ci,
-	    struct sbecom_chan_param *cp)
-{
-	hdlc_device *hdlc;
-	struct net_device *dev;
-	hdw_info_t *hi;
-	int         ret;
-
-	if (c4_find_chan(cp->channum))
-		return NULL;                   /* channel already exists */
-
-	{
-		struct c4_priv *priv;
-
-		/* allocate then fill in private data structure */
-		priv = kzalloc(sizeof(struct c4_priv), GFP_KERNEL);
-		if (!priv) {
-			pr_warning("%s: no memory for net_device !\n",
-				   ci->devname);
-			return NULL;
-		}
-		dev = alloc_hdlcdev(priv);
-		if (!dev) {
-			pr_warning("%s: no memory for hdlc_device !\n",
-				   ci->devname);
-			kfree(priv);
-			return NULL;
-		}
-		priv->ci = ci;
-		priv->channum = cp->channum;
-	}
-
-	hdlc = dev_to_hdlc(dev);
-
-	dev->base_addr = 0;             /* not I/O mapped */
-	dev->irq = ndev->irq;
-	dev->type = ARPHRD_RAWHDLC;
-	*dev->name = 0;                 /* default ifconfig name = "hdlc" */
-
-	hi = (hdw_info_t *)ci->hdw_info;
-	if (hi->mfg_info_sts == EEPROM_OK) {
-		switch (hi->promfmt) {
-		case PROM_FORMAT_TYPE1:
-			memcpy(dev->dev_addr,
-			       (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-			break;
-		case PROM_FORMAT_TYPE2:
-			memcpy(dev->dev_addr,
-			       (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-			break;
-		default:
-			memset(dev->dev_addr, 0, 6);
-			break;
-		}
-	} else
-		memset(dev->dev_addr, 0, 6);
-
-	hdlc->xmit = c4_linux_xmit;
-
-	dev->netdev_ops = &chan_ops;
-	/*
-	 * The native hdlc stack calls this 'attach' routine during
-	 * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
-	 * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
-	 * routine is actually registered or not, we supply a dummy routine which
-	 * does nothing (since encoding and parity are setup for our driver via a
-	 * special configuration application).
-	 */
-
-	hdlc->attach = chan_attach_noop;
-
-	/* needed due to Ioctl calling sequence */
-	rtnl_unlock();
-	ret = register_hdlc_device(dev);
-	/* NOTE: <stats> setting must occur AFTER registration in order to "take" */
-	dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
-
-	/* needed due to Ioctl calling sequence */
-	rtnl_lock();
-	if (ret) {
-		if (cxt1e1_log_level >= LOG_WARN)
-			pr_info("%s: create_chan[%d] registration error = %d.\n",
-				ci->devname, cp->channum, ret);
-		/* cleanup */
-		free_netdev(dev);
-		/* failed to register */
-		return NULL;
-	}
-	return dev;
-}
-
-
-/* the idea here is to get port information and pass it back (using pointer) */
-static status_t
-do_get_port(struct net_device *ndev, void *data)
-{
-	int         ret;
-	ci_t       *ci;             /* ci stands for card information */
-	struct sbecom_port_param pp;/* copy data to kernel land */
-
-	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	if (pp.portnum >= MUSYCC_NPORTS)
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;             /* get card info */
-
-	ret = c4_get_port(ci, pp.portnum);
-	if (ret < 0)
-		return ret;
-	if (copy_to_user(data, &ci->port[pp.portnum].p,
-			 sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	return 0;
-}
-
-/* this function copys the user data and then calls the real action function */
-static status_t
-do_set_port(struct net_device *ndev, void *data)
-{
-	ci_t       *ci;             /* ci stands for card information */
-	struct sbecom_port_param pp;/* copy data to kernel land */
-
-	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	if (pp.portnum >= MUSYCC_NPORTS)
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;             /* get card info */
-
-	if (pp.portnum >= ci->max_port) /* sanity check */
-		return -ENXIO;
-
-	memcpy(&ci->port[pp.portnum].p, &pp, sizeof(struct sbecom_port_param));
-	return c4_set_port(ci, pp.portnum);
-}
-
-/* work the port loopback mode as per directed */
-static status_t
-do_port_loop(struct net_device *ndev, void *data)
-{
-	struct sbecom_port_param pp;
-	ci_t       *ci;
-
-	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	return c4_loop_port(ci, pp.portnum, pp.port_mode);
-}
-
-/* set the specified register with the given value / or just read it */
-static status_t
-do_framer_rw(struct net_device *ndev, void *data)
-{
-	struct sbecom_port_param pp;
-	ci_t       *ci;
-	int         ret;
-
-	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	ret = c4_frame_rw(ci, &pp);
-	if (ret < 0)
-		return ret;
-	if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	return 0;
-}
-
-/* set the specified register with the given value / or just read it */
-static status_t
-do_pld_rw(struct net_device *ndev, void *data)
-{
-	struct sbecom_port_param pp;
-	ci_t       *ci;
-	int         ret;
-
-	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-
-	ret = c4_pld_rw(ci, &pp);
-	if (ret)
-		return ret;
-	if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
-		return -EFAULT;
-	return 0;
-}
-
-/* set the specified register with the given value / or just read it */
-static status_t
-do_musycc_rw(struct net_device *ndev, void *data)
-{
-	struct c4_musycc_param mp;
-	ci_t       *ci;
-	int         ret;
-
-	if (copy_from_user(&mp, data, sizeof(struct c4_musycc_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	ret = c4_musycc_rw(ci, &mp);
-	if (ret < 0)
-		return ret;
-	if (copy_to_user(data, &mp, sizeof(struct c4_musycc_param)))
-		return -EFAULT;
-	return 0;
-}
-
-static status_t
-do_get_chan(struct net_device *ndev, void *data)
-{
-	struct sbecom_chan_param cp;
-	int         ret;
-
-	if (copy_from_user(&cp, data,
-				sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-
-	ret = c4_get_chan(cp.channum, &cp);
-	if (ret < 0)
-		return ret;
-
-	if (copy_to_user(data, &cp, sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-	return 0;
-}
-
-static status_t
-do_set_chan(struct net_device *ndev, void *data)
-{
-	struct sbecom_chan_param cp;
-	ci_t       *ci;
-
-	if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	return c4_set_chan(cp.channum, &cp);
-}
-
-static status_t
-do_create_chan(struct net_device *ndev, void *data)
-{
-	ci_t       *ci;
-	struct net_device *dev;
-	struct sbecom_chan_param cp;
-	int         ret;
-
-	if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	dev = create_chan(ndev, ci, &cp);
-	if (!dev)
-		return -EBUSY;
-	ret = c4_new_chan(ci, cp.port, cp.channum, dev);
-	if (ret < 0) {
-		/* needed due to Ioctl calling sequence */
-		rtnl_unlock();
-		unregister_hdlc_device(dev);
-		/* needed due to Ioctl calling sequence */
-		rtnl_lock();
-		free_netdev(dev);
-	}
-	return ret;
-}
-
-static status_t
-do_get_chan_stats(struct net_device *ndev, void *data)
-{
-	struct c4_chan_stats_wrap ccs;
-	int         ret;
-
-	if (copy_from_user(&ccs, data,
-			   sizeof(struct c4_chan_stats_wrap)))
-		return -EFAULT;
-
-	ret = c4_get_chan_stats(ccs.channum, &ccs.stats);
-	if (ret < 0)
-		return ret;
-
-	if (copy_to_user(data, &ccs,
-			 sizeof(struct c4_chan_stats_wrap)))
-		return -EFAULT;
-	return 0;
-}
-static status_t
-do_set_loglevel(struct net_device *ndev, void *data)
-{
-	unsigned int cxt1e1_log_level;
-
-	if (copy_from_user(&cxt1e1_log_level, data, sizeof(int)))
-		return -EFAULT;
-	sbecom_set_loglevel(cxt1e1_log_level);
-	return 0;
-}
-
-static status_t
-do_deluser(struct net_device *ndev, int lockit)
-{
-	if (ndev->flags & IFF_UP)
-		return -EBUSY;
-
-	{
-		ci_t       *ci;
-		mch_t      *ch;
-		const struct c4_priv *priv;
-		int         channum;
-
-		priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
-		ci = priv->ci;
-		channum = priv->channum;
-
-		ch = c4_find_chan(channum);
-		if (ch == NULL)
-			return -ENOENT;
-		ch->user = NULL;	/* will be freed, below */
-	}
-
-	/* needed if Ioctl calling sequence */
-	if (lockit)
-		rtnl_unlock();
-	unregister_hdlc_device(ndev);
-	/* needed if Ioctl calling sequence */
-	if (lockit)
-		rtnl_lock();
-	free_netdev(ndev);
-	return 0;
-}
-
-int
-do_del_chan(struct net_device *musycc_dev, void *data)
-{
-	struct sbecom_chan_param cp;
-	char        buf[sizeof(CHANNAME) + 3];
-	struct net_device *dev;
-	int         ret;
-
-	if (copy_from_user(&cp, data,
-			   sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-	if (cp.channum > 999)
-		return -EINVAL;
-	snprintf(buf, sizeof(buf), CHANNAME "%d", cp.channum);
-	dev = __dev_get_by_name(&init_net, buf);
-	if (!dev)
-		return -ENODEV;
-	ret = do_deluser(dev, 1);
-	if (ret)
-		return ret;
-	return c4_del_chan(cp.channum);
-}
-int c4_reset_board(void *);
-
-int
-do_reset(struct net_device *musycc_dev, void *data)
-{
-	const struct c4_priv *priv;
-	int         i;
-
-	for (i = 0; i < 128; i++) {
-		struct net_device *ndev;
-		char        buf[sizeof(CHANNAME) + 3];
-
-		sprintf(buf, CHANNAME "%d", i);
-		ndev = __dev_get_by_name(&init_net, buf);
-		if (!ndev)
-			continue;
-		priv = dev_to_hdlc(ndev)->priv;
-
-		if ((unsigned long) (priv->ci) ==
-			(unsigned long) (netdev_priv(musycc_dev))) {
-			ndev->flags &= ~IFF_UP;
-			netif_stop_queue(ndev);
-			do_deluser(ndev, 1);
-		}
-	}
-	return 0;
-}
-
-int
-do_reset_chan_stats(struct net_device *musycc_dev, void *data)
-{
-	struct sbecom_chan_param cp;
-
-	if (copy_from_user(&cp, data,
-			   sizeof(struct sbecom_chan_param)))
-		return -EFAULT;
-	return c4_del_chan_stats(cp.channum);
-}
-
-static status_t
-c4_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
-{
-	ci_t       *ci;
-	void       *data;
-	int         iocmd, iolen;
-	status_t    ret;
-	static struct data {
-		union {
-			u_int8_t c;
-			u_int32_t i;
-			struct sbe_brd_info bip;
-			struct sbe_drv_info dip;
-			struct sbe_iid_info iip;
-			struct sbe_brd_addr bap;
-			struct sbecom_chan_stats stats;
-			struct sbecom_chan_param param;
-			struct temux_card_stats cards;
-			struct sbecom_card_param cardp;
-			struct sbecom_framer_param frp;
-		} u;
-	} arg;
-
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (cmd != SIOCDEVPRIVATE + 15)
-		return -EINVAL;
-	ci = get_ci_by_dev(ndev);
-	if (!ci)
-		return -EINVAL;
-	if (ci->state != C_RUNNING)
-		return -ENODEV;
-	if (copy_from_user(&iocmd, ifr->ifr_data, sizeof(iocmd)))
-		return -EFAULT;
-#if 0
-	if (copy_from_user(&len, ifr->ifr_data + sizeof(iocmd), sizeof(len)))
-		return -EFAULT;
-#endif
-
-#if 0
-	pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
-		_IOC_DIR(iocmd), _IOC_TYPE(iocmd), _IOC_NR(iocmd),
-		_IOC_SIZE(iocmd));
-#endif
-	iolen = _IOC_SIZE(iocmd);
-	if (iolen > sizeof(arg))
-		return -EFAULT;
-	data = ifr->ifr_data + sizeof(iocmd);
-	if (copy_from_user(&arg, data, iolen))
-		return -EFAULT;
-
-	ret = 0;
-	switch (iocmd) {
-	case SBE_IOC_PORT_GET:
-		ret = do_get_port(ndev, data);
-		break;
-	case SBE_IOC_PORT_SET:
-		ret = do_set_port(ndev, data);
-		break;
-	case SBE_IOC_CHAN_GET:
-		ret = do_get_chan(ndev, data);
-		break;
-	case SBE_IOC_CHAN_SET:
-		ret = do_set_chan(ndev, data);
-		break;
-	case C4_DEL_CHAN:
-		ret = do_del_chan(ndev, data);
-		break;
-	case SBE_IOC_CHAN_NEW:
-		ret = do_create_chan(ndev, data);
-		break;
-	case SBE_IOC_CHAN_GET_STAT:
-		ret = do_get_chan_stats(ndev, data);
-		break;
-	case SBE_IOC_LOGLEVEL:
-		ret = do_set_loglevel(ndev, data);
-		break;
-	case SBE_IOC_RESET_DEV:
-		ret = do_reset(ndev, data);
-		break;
-	case SBE_IOC_CHAN_DEL_STAT:
-		ret = do_reset_chan_stats(ndev, data);
-		break;
-	case C4_LOOP_PORT:
-		ret = do_port_loop(ndev, data);
-		break;
-	case C4_RW_FRMR:
-		ret = do_framer_rw(ndev, data);
-		break;
-	case C4_RW_MSYC:
-		ret = do_musycc_rw(ndev, data);
-		break;
-	case C4_RW_PLD:
-		ret = do_pld_rw(ndev, data);
-		break;
-	case SBE_IOC_IID_GET:
-		ret = (iolen == sizeof(struct sbe_iid_info)) ?
-		       c4_get_iidinfo(ci, &arg.u.iip) : -EFAULT;
-		if (ret == 0)               /* no error, copy data */
-			if (copy_to_user(data, &arg, iolen))
-				return -EFAULT;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static const struct net_device_ops c4_ops = {
-	.ndo_open       = void_open,
-	.ndo_start_xmit = c4_linux_xmit,
-	.ndo_do_ioctl   = c4_ioctl,
-};
-
-static void c4_setup(struct net_device *dev)
-{
-	dev->type = ARPHRD_VOID;
-	dev->netdev_ops = &c4_ops;
-}
-
-struct net_device *__init
-c4_add_dev(hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
-	   int irq0, int irq1)
-{
-	struct net_device *ndev;
-	ci_t       *ci;
-
-	ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
-	if (!ndev) {
-		pr_warning("%s: no memory for struct net_device !\n",
-			   hi->devname);
-		error_flag = -ENOMEM;
-		return NULL;
-	}
-	ci = (ci_t *)(netdev_priv(ndev));
-	ndev->irq = irq0;
-
-	ci->hdw_info = hi;
-	ci->state = C_INIT;         /* mark as hardware not available */
-	ci->next = c4_list;
-	c4_list = ci;
-	ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
-
-	if (!CI)
-		CI = ci;                    /* DEBUG, only board 0 usage */
-
-	strcpy(ci->devname, hi->devname);
-
-	/* tasklet */
-#if defined(SBE_ISR_TASKLET)
-	tasklet_init(&ci->ci_musycc_isr_tasklet,
-		     (void (*) (unsigned long)) musycc_intr_bh_tasklet,
-		     (unsigned long) ci);
-
-	if (atomic_read(&ci->ci_musycc_isr_tasklet.count) == 0)
-		tasklet_disable_nosync(&ci->ci_musycc_isr_tasklet);
-#elif defined(SBE_ISR_IMMEDIATE)
-	ci->ci_musycc_isr_tq.routine = (void *)(unsigned long)musycc_intr_bh_tasklet;
-	ci->ci_musycc_isr_tq.data = ci;
-#endif
-
-
-	if (register_netdev(ndev) ||
-		(c4_init(ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS)) {
-		kfree(netdev_priv(ndev));
-		kfree(ndev);
-		error_flag = -ENODEV;
-		return NULL;
-	}
-	/*************************************************************
-	 *  int request_irq(unsigned int irq,
-	 *                  void (*handler)(int, void *, struct pt_regs *),
-	 *                  unsigned long flags, const char *dev_name, void *dev_id);
-	 *  wherein:
-	 *  irq      -> The interrupt number that is being requested.
-	 *  handler  -> Pointer to handling function being installed.
-	 *  flags    -> A bit mask of options related to interrupt management.
-	 *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
-	 *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
-	 *              private data area (to identify which device is interrupting).
-	 *
-	 *  extern void free_irq(unsigned int irq, void *dev_id);
-	 **************************************************************/
-
-	if (request_irq(irq0, &c4_linux_interrupt,
-			IRQF_SHARED,
-			ndev->name, ndev)) {
-		pr_warning("%s: MUSYCC could not get irq: %d\n",
-			   ndev->name, irq0);
-		unregister_netdev(ndev);
-		kfree(netdev_priv(ndev));
-		kfree(ndev);
-		error_flag = -EIO;
-		return NULL;
-	}
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-	if (request_irq(irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev)) {
-		pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
-		unregister_netdev(ndev);
-		free_irq(irq0, ndev);
-		kfree(netdev_priv(ndev));
-		kfree(ndev);
-		error_flag = -EIO;
-		return NULL;
-	}
-#endif
-
-	/* setup board identification information */
-
-	{
-		u_int32_t   tmp;
-
-		/* also sets PROM format type (promfmt) for later usage */
-		hdw_sn_get(hi, brdno);
-
-		switch (hi->promfmt) {
-		case PROM_FORMAT_TYPE1:
-			memcpy(ndev->dev_addr,
-			       (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-			/* unaligned data acquisition */
-			memcpy(&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);
-			ci->brd_id = cpu_to_be32(tmp);
-			break;
-		case PROM_FORMAT_TYPE2:
-			memcpy(ndev->dev_addr,
-			       (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-			/* unaligned data acquisition */
-			memcpy(&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);
-			ci->brd_id = cpu_to_be32(tmp);
-			break;
-		default:
-			ci->brd_id = 0;
-			memset(ndev->dev_addr, 0, 6);
-			break;
-		}
-
-#if 1
-		/* requires bid to be preset */
-		sbeid_set_hdwbid(ci);
-#else
-		/* requires hdw_bid to be preset */
-		sbeid_set_bdtype(ci);
-#endif
-	}
-
-#ifdef CONFIG_PROC_FS
-	sbecom_proc_brd_init(ci);
-#endif
-#if defined(SBE_ISR_TASKLET)
-	tasklet_enable(&ci->ci_musycc_isr_tasklet);
-#endif
-
-	error_flag = c4_init2(ci);
-	if (error_flag != SBE_DRVR_SUCCESS) {
-#ifdef CONFIG_PROC_FS
-		sbecom_proc_brd_cleanup(ci);
-#endif
-		unregister_netdev(ndev);
-		free_irq(irq1, ndev);
-		free_irq(irq0, ndev);
-		kfree(netdev_priv(ndev));
-		kfree(ndev);
-		/* failure, error_flag is set */
-		return NULL;
-	}
-	return ndev;
-}
-
-static int  __init
-c4_mod_init(void)
-{
-	int         rtn;
-
-	rtn = c4hw_attach_all();
-	if (rtn)
-		return -rtn; /* installation failure - see system log */
-
-	/* housekeeping notifications */
-	if (cxt1e1_log_level != log_level_default)
-		pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
-			log_level_default, cxt1e1_log_level);
-	if (cxt1e1_max_mru != max_mru_default)
-		pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
-			max_mru_default, cxt1e1_max_mru);
-	if (cxt1e1_max_mtu != max_mtu_default)
-		pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
-			max_mtu_default, cxt1e1_max_mtu);
-	if (max_rxdesc_used != max_rxdesc_default) {
-		if (max_rxdesc_used > 2000)
-			max_rxdesc_used = 2000; /* out-of-bounds reset */
-		pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
-			max_rxdesc_default, max_rxdesc_used);
-	}
-	if (max_txdesc_used != max_txdesc_default) {
-		if (max_txdesc_used > 1000)
-			max_txdesc_used = 1000; /* out-of-bounds reset */
-		pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
-			max_txdesc_default, max_txdesc_used);
-	}
-	return 0;                       /* installation success */
-}
-
-
- /*
-  * find any still allocated hdlc registrations and unregister via call to
-  * do_deluser()
-  */
-
-static void __exit
-cleanup_hdlc(void)
-{
-	hdw_info_t *hi;
-	ci_t       *ci;
-	struct net_device *ndev;
-	int         i, j, k;
-
-	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
-		if (hi->ndev) {          /* a board has been attached */
-			ci = (ci_t *)(netdev_priv(hi->ndev));
-			for (j = 0; j < ci->max_port; j++)
-				for (k = 0; k < MUSYCC_NCHANS; k++) {
-					ndev = ci->port[j].chan[k]->user;
-					if (ndev)
-						do_deluser(ndev, 0);
-				}
-		}
-	}
-}
-
-
-static void __exit
-c4_mod_remove(void)
-{
-	cleanup_hdlc();            /* delete any missed channels */
-	cleanup_devs();
-	c4_cleanup();
-	cleanup_ioremap();
-	pr_info("SBE - driver removed.\n");
-}
-
-module_init(c4_mod_init);
-module_exit(c4_mod_remove);
-
-MODULE_AUTHOR("SBE Technical Services <support@sbei.com>");
-MODULE_DESCRIPTION("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
-#ifdef MODULE_LICENSE
-MODULE_LICENSE("GPL");
-#endif
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/Makefile
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-obj-$(CONFIG_CXT1E1)	+= cxt1e1.o
-
-ccflags-y := -DSBE_PMCC4_ENABLE
-ccflags-y += -DSBE_ISR_TASKLET
-
-cxt1e1-y := 	\
-  musycc.o 		\
-  pmcc4_drv.o 		\
-  comet.o 		\
-  linux.o 		\
-  functions.o 		\
-  hwprobe.o 		\
-  pmc93x6_eeprom.o 	\
-  sbecrc.o 		\
-  comet_tables.o 	\
-  sbeid.o
-
-cxt1e1-$(CONFIG_PROC_FS) += sbeproc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/musycc.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/musycc.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/musycc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/musycc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1720 +0,0 @@
-static unsigned int max_intcnt;
-static unsigned int max_bh;
-
-/*-----------------------------------------------------------------------------
- * musycc.c -
- *
- * Copyright (C) 2007  One Stop Systems, Inc.
- * Copyright (C) 2003-2006  SBE, 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.
- *
- * For further information, contact via email: support@onestopsystems.com
- * One Stop Systems, Inc.  Escondido, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include "pmcc4_sysdep.h"
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4_private.h"
-#include "pmcc4.h"
-#include "musycc.h"
-
-#define sd_find_chan(ci,ch)   c4_find_chan(ch)
-
-
-/*******************************************************************/
-/* global driver variables */
-extern ci_t *c4_list;
-extern int  drvr_state;
-
-extern int  cxt1e1_max_mru;
-extern int  cxt1e1_max_mtu;
-extern int  max_rxdesc_used;
-extern int  max_txdesc_used;
-extern ci_t *CI;                /* dummy pointr to board ZEROE's data - DEBUG
-				 * USAGE */
-
-
-/*******************************************************************/
-/* forward references */
-void        c4_fifo_free(mpi_t *, int);
-void        c4_wk_chan_restart(mch_t *);
-void        musycc_bh_tx_eom(mpi_t *, int);
-int         musycc_chan_up(ci_t *, int);
-status_t __init musycc_init(ci_t *);
-void        musycc_intr_bh_tasklet(ci_t *);
-void        musycc_serv_req(mpi_t *, u_int32_t);
-void        musycc_update_timeslots(mpi_t *);
-
-/*******************************************************************/
-
-static int
-musycc_dump_rxbuffer_ring(mch_t *ch, int lockit)
-{
-	struct mdesc *m;
-	unsigned long flags = 0;
-
-	u_int32_t status;
-	int         n;
-
-#ifdef RLD_DUMP_BUFDATA
-	u_int32_t *dp;
-	int len = 0;
-#endif
-	if (lockit)
-		spin_lock_irqsave(&ch->ch_rxlock, flags);
-	if (ch->rxd_num == 0)
-		pr_info("  ZERO receive buffers allocated for this channel.");
-	else {
-		FLUSH_MEM_READ();
-		m = &ch->mdr[ch->rxix_irq_srv];
-		for (n = ch->rxd_num; n; n--) {
-			status = le32_to_cpu(m->status);
-			pr_info("%c  %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
-				(m == &ch->mdr[ch->rxix_irq_srv]) ? 'F' : ' ',
-				(unsigned long) m, n,
-				status,
-				m->data ? (status & HOST_RX_OWNED ? 'H' : 'M') : '-',
-				status & POLL_DISABLED ? 'P' : '-',
-				status & EOBIRQ_ENABLE ? 'b' : '-',
-				status & EOMIRQ_ENABLE ? 'm' : '-',
-				status & LENGTH_MASK,
-				le32_to_cpu(m->data), le32_to_cpu(m->next));
-#ifdef RLD_DUMP_BUFDATA
-				len = status & LENGTH_MASK;
-
-#if 1
-				if (m->data && (status & HOST_RX_OWNED))
-#else
-				/* always dump regardless of valid RX data */
-				if (m->data)
-#endif
-				{
-					dp = (u_int32_t *)OS_phystov((void *)(le32_to_cpu(m->data)));
-					if (len >= 0x10)
-						pr_info("    %x[%x]: %08X %08X %08X %08x\n",
-							(u_int32_t)dp, len,
-							*dp, *(dp + 1),
-							*(dp + 2), *(dp + 3));
-					else if (len >= 0x08)
-						pr_info("    %x[%x]: %08X %08X\n",
-							(u_int32_t)dp, len,
-							*dp, *(dp + 1));
-					else
-						pr_info("    %x[%x]: %08X\n",
-							(u_int32_t)dp,
-							len, *dp);
-				}
-#endif
-			m = m->snext;
-		}
-	}
-	pr_info("\n");
-
-	if (lockit)
-		spin_unlock_irqrestore(&ch->ch_rxlock, flags);
-	return 0;
-}
-
-static int
-musycc_dump_txbuffer_ring(mch_t *ch, int lockit)
-{
-	struct mdesc *m;
-	unsigned long flags = 0;
-	u_int32_t   status;
-	int         n;
-#ifdef RLD_DUMP_BUFDATA
-	u_int32_t *dp;
-	int len = 0;
-#endif
-
-	if (lockit)
-		spin_lock_irqsave(&ch->ch_txlock, flags);
-	if (ch->txd_num == 0)
-		pr_info("  ZERO transmit buffers allocated for this channel.");
-	else {
-		FLUSH_MEM_READ();
-		m = ch->txd_irq_srv;
-		for (n = ch->txd_num; n; n--) {
-			status = le32_to_cpu(m->status);
-			pr_info("%c%c %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
-				(m == ch->txd_usr_add) ? 'F' : ' ',
-				(m == ch->txd_irq_srv) ? 'L' : ' ',
-				(unsigned long) m, n,
-				status,
-				m->data ? (status & MUSYCC_TX_OWNED ? 'M' : 'H') : '-',
-				status & POLL_DISABLED ? 'P' : '-',
-				status & EOBIRQ_ENABLE ? 'b' : '-',
-				status & EOMIRQ_ENABLE ? 'm' : '-',
-				status & LENGTH_MASK,
-				le32_to_cpu(m->data), le32_to_cpu(m->next));
-#ifdef RLD_DUMP_BUFDATA
-			len = status & LENGTH_MASK;
-
-			if (m->data) {
-				dp = (u_int32_t *)OS_phystov((void *)(le32_to_cpu(m->data)));
-				if (len >= 0x10)
-					pr_info("    %x[%x]: %08X %08X %08X %08x\n",
-						(u_int32_t) dp, len,
-						*dp, *(dp + 1),
-						*(dp + 2), *(dp + 3));
-				else if (len >= 0x08)
-					pr_info("    %x[%x]: %08X %08X\n",
-						(u_int32_t)dp, len,
-						*dp, *(dp + 1));
-				else
-					pr_info("    %x[%x]: %08X\n",
-						(u_int32_t)dp, len, *dp);
-			}
-#endif
-			m = m->snext;
-		}
-	}                               /* -for- */
-	pr_info("\n");
-
-	if (lockit)
-		spin_unlock_irqrestore(&ch->ch_txlock, flags);
-	return 0;
-}
-
-/*
- * The following supports a backdoor debug facility which can be used to
- * display the state of a board's channel.
- */
-
-status_t
-musycc_dump_ring(ci_t *ci, unsigned int chan)
-{
-	mch_t      *ch;
-	int bh;
-
-	if (chan >= MAX_CHANS_USED)
-		return SBE_DRVR_FAIL;       /* E2BIG */
-
-	bh = atomic_read(&ci->bh_pending);
-	pr_info(">> bh_pend %d [%d] ihead %d itail %d [%d] th_cnt %d bh_cnt %d wdcnt %d note %d\n",
-		bh, max_bh, ci->iqp_headx, ci->iqp_tailx, max_intcnt,
-		ci->intlog.drvr_intr_thcount,
-		ci->intlog.drvr_intr_bhcount,
-		ci->wdcount, ci->wd_notify);
-	max_bh = 0;                 /* reset counter */
-	max_intcnt = 0;             /* reset counter */
-
-	ch = sd_find_chan(dummy, chan);
-	if (!ch) {
-		pr_info(">> musycc_dump_ring: channel %d not up.\n", chan);
-		return ENOENT;
-	}
-	pr_info(">> CI %p CHANNEL %3d @ %p: state %x status/p %x/%x\n",
-		ci, chan, ch, ch->state,
-		ch->status, ch->p.status);
-	pr_info("--------------------------------\n");
-	pr_info("TX Buffer Ring - Channel %d, txd_num %d. (bd/ch pend %d %d), TXD required %d, txpkt %lu\n",
-		chan, ch->txd_num,
-		(u_int32_t)atomic_read(&ci->tx_pending),
-		(u_int32_t)atomic_read(&ch->tx_pending),
-		ch->txd_required, ch->s.tx_packets);
-	pr_info("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-		ch->user, ch->txd_irq_srv, ch->txd_usr_add,
-		sd_queue_stopped(ch->user),
-		ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
-	musycc_dump_txbuffer_ring(ch, 1);
-	pr_info("RX Buffer Ring - Channel %d, rxd_num %d. IRQ_SRV[%d] 0x%p, start_rx %x rxpkt %lu\n",
-		chan, ch->rxd_num, ch->rxix_irq_srv,
-		&ch->mdr[ch->rxix_irq_srv], ch->ch_start_rx, ch->s.rx_packets);
-	musycc_dump_rxbuffer_ring(ch, 1);
-
-	return SBE_DRVR_SUCCESS;
-}
-
-
-status_t
-musycc_dump_rings(ci_t *ci, unsigned int start_chan)
-{
-	unsigned int chan;
-
-	for (chan = start_chan; chan < (start_chan + 5); chan++)
-		musycc_dump_ring(ci, chan);
-	return SBE_DRVR_SUCCESS;
-}
-
-
-/*
- * NOTE on musycc_init_mdt():  These MUSYCC writes are only operational after
- * a MUSYCC GROUP_INIT command has been issued.
- */
-
-void
-musycc_init_mdt(mpi_t *pi)
-{
-	u_int32_t  *addr, cfg;
-	int         i;
-
-	/*
-	 * This Idle Code insertion takes effect prior to channel's first
-	 * transmitted  message.  After that, each message contains its own Idle
-	 * Code information which is to be issued after the message is
-	 * transmitted (Ref.MUSYCC 5.2.2.3: MCENBL bit in Group Configuration
-	 * Descriptor).
-	 */
-
-	addr = (u_int32_t *) ((u_long) pi->reg + MUSYCC_MDT_BASE03_ADDR);
-	cfg = CFG_CH_FLAG_7E << IDLE_CODE;
-
-	for (i = 0; i < 32; addr++, i++)
-		pci_write_32(addr, cfg);
-}
-
-
-/* Set TX thp to the next unprocessed md */
-
-void
-musycc_update_tx_thp(mch_t *ch)
-{
-	struct mdesc *md;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ch->ch_txlock, flags);
-	while (1) {
-		md = ch->txd_irq_srv;
-		FLUSH_MEM_READ();
-		if (!md->data) {
-			/* No MDs with buffers to process */
-			spin_unlock_irqrestore(&ch->ch_txlock, flags);
-			return;
-		}
-		if ((le32_to_cpu(md->status)) & MUSYCC_TX_OWNED) {
-			/* this is the MD to restart TX with */
-			break;
-		}
-		/*
-		 * Otherwise, we have a valid, host-owned message descriptor which
-		 * has been successfully transmitted and whose buffer can be freed,
-		 * so... process this MD, it's owned by the host.  (This might give
-		 * as a new, updated txd_irq_srv.)
-		 */
-		musycc_bh_tx_eom(ch->up, ch->gchan);
-	}
-	md = ch->txd_irq_srv;
-	ch->up->regram->thp[ch->gchan] = cpu_to_le32(OS_vtophys(md));
-	FLUSH_MEM_WRITE();
-
-	if (ch->tx_full) {
-		ch->tx_full = 0;
-		ch->txd_required = 0;
-		sd_enable_xmit(ch->user);  /* re-enable to catch flow controlled
-					    * channel */
-	}
-	spin_unlock_irqrestore(&ch->ch_txlock, flags);
-
-#ifdef RLD_TRANS_DEBUG
-	pr_info("++ musycc_update_tx_thp[%d]: setting thp = %p, sts %x\n",
-		ch->channum, md, md->status);
-#endif
-}
-
-
-/*
- * This is the workq task executed by the OS when our queue_work() is
- * scheduled and run.  It can fire off either RX or TX ACTIVATION depending
- * upon the channel's ch_start_tx and ch_start_rx variables.  This routine
- * is implemented as a work queue so that the call to the service request is
- * able to sleep, awaiting an interrupt acknowledgment response (SACK) from
- * the hardware.
- */
-
-void
-musycc_wq_chan_restart(void *arg)      /* channel private structure */
-{
-	mch_t      *ch;
-	mpi_t      *pi;
-	struct mdesc *md;
-
-#if defined(RLD_TRANS_DEBUG) || defined(RLD_RXACT_DEBUG)
-	static int hereb4 = 7;
-#endif
-
-	ch = container_of(arg, struct c4_chan_info, ch_work);
-	pi = ch->up;
-
-#ifdef RLD_TRANS_DEBUG
-	pr_info("wq_chan_restart[%d]: start_RT[%d/%d] status %x\n",
-		ch->channum, ch->ch_start_rx, ch->ch_start_tx, ch->status);
-
-#endif
-
-	/**********************************/
-	/** check for RX restart request **/
-	/**********************************/
-
-	if ((ch->ch_start_rx) && (ch->status & RX_ENABLED)) {
-
-		ch->ch_start_rx = 0;
-#if defined(RLD_TRANS_DEBUG) || defined(RLD_RXACT_DEBUG)
-		if (hereb4) {            /* RLD DEBUG */
-			hereb4--;
-#ifdef RLD_TRANS_DEBUG
-			md = &ch->mdr[ch->rxix_irq_srv];
-			pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
-				ch->channum, ch->rxix_irq_srv, md,
-				le32_to_cpu(md->status), ch->s.rx_packets);
-#elif defined(RLD_RXACT_DEBUG)
-			md = &ch->mdr[ch->rxix_irq_srv];
-			pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
-				ch->channum, ch->rxix_irq_srv,
-				md, le32_to_cpu(md->status),
-				ch->s.rx_packets);
-			musycc_dump_rxbuffer_ring(ch, 1);      /* RLD DEBUG */
-#endif
-		}
-#endif
-		musycc_serv_req(pi, SR_CHANNEL_ACTIVATE |
-				SR_RX_DIRECTION | ch->gchan);
-	}
-	/**********************************/
-	/** check for TX restart request **/
-	/**********************************/
-
-	if ((ch->ch_start_tx) && (ch->status & TX_ENABLED)) {
-		/* find next unprocessed message, then set TX thp to it */
-		musycc_update_tx_thp(ch);
-
-		md = ch->txd_irq_srv;
-		if (!md) {
-#ifdef RLD_TRANS_DEBUG
-			pr_info("-- musycc_wq_chan_restart[%d]: WARNING, starting NULL md\n",
-				ch->channum);
-#endif
-		} else if (md->data && ((le32_to_cpu(md->status)) &
-			   MUSYCC_TX_OWNED)) {
-			ch->ch_start_tx = 0;
-
-#ifdef RLD_TRANS_DEBUG
-			pr_info("++ musycc_wq_chan_restart() CHAN TX ACTIVATE: chan %d txd_irq_srv %p = sts %x, txpkt %lu\n",
-				ch->channum, ch->txd_irq_srv,
-				ch->txd_irq_srv->status, ch->s.tx_packets);
-#endif
-			musycc_serv_req(pi, SR_CHANNEL_ACTIVATE |
-					SR_TX_DIRECTION | ch->gchan);
-		}
-#ifdef RLD_RESTART_DEBUG
-		else {
-			/* retain request to start until retried and we have data to xmit */
-			pr_info("-- musycc_wq_chan_restart[%d]: DELAYED due to md %p sts %x data %x, start_tx %x\n",
-				ch->channum, md,
-				le32_to_cpu(md->status),
-				le32_to_cpu(md->data), ch->ch_start_tx);
-			musycc_dump_txbuffer_ring(ch, 0);
-		}
-#endif
-	}
-}
-
-
- /*
-  * Channel restart either fires of a workqueue request (2.6) or lodges a
-  * watchdog activation sequence (2.4).
-  */
-
-void
-musycc_chan_restart(mch_t *ch)
-{
-#ifdef RLD_RESTART_DEBUG
-	pr_info("++ musycc_chan_restart[%d]: txd_irq_srv @ %p = sts %x\n",
-		ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status);
-#endif
-
-	/* 2.6 - find next unprocessed message, then set TX thp to it */
-#ifdef RLD_RESTART_DEBUG
-	pr_info(">> musycc_chan_restart: scheduling Chan %x workQ @ %p\n",
-		ch->channum, &ch->ch_work);
-#endif
-	c4_wk_chan_restart(ch);        /* work queue mechanism fires off: Ref:
-					* musycc_wq_chan_restart () */
-}
-
-
-void
-rld_put_led(mpi_t *pi, u_int32_t ledval)
-{
-	static u_int32_t led;
-
-	if (ledval == 0)
-		led = 0;
-	else
-		led |= ledval;
-
-	/* RLD DEBUG TRANHANG */
-	pci_write_32((u_int32_t *) &pi->up->cpldbase->leds, led);
-}
-
-
-#define MUSYCC_SR_RETRY_CNT  9
-
-void
-musycc_serv_req(mpi_t *pi, u_int32_t req)
-{
-	volatile u_int32_t r;
-	int         rcnt;
-
-	/*
-	 * PORT NOTE: Semaphore protect service loop guarantees only a single
-	 * operation at a time.  Per MUSYCC Manual - "Issuing service requests to
-	 * the same channel group without first receiving ACK from each request
-	 * may cause the host to lose track of which service request has been
-	 * acknowledged."
-	 */
-
-	SD_SEM_TAKE(&pi->sr_sem_busy, "serv");     /* only 1 thru here, per
-						    * group */
-
-	if (pi->sr_last == req) {
-#ifdef RLD_TRANS_DEBUG
-		pr_info(">> same SR, Port %d Req %x\n", pi->portnum, req);
-#endif
-
-		/*
-		 * The most likely repeated request is the channel activation command
-		 * which follows the occurrence of a Transparent mode TX ONR or a
-		 * BUFF error.  If the previous command was a CHANNEL ACTIVATE,
-		 * precede it with a NOOP command in order maintain coherent control
-		 * of this current (re)ACTIVATE.
-		 */
-
-		r = (pi->sr_last & ~SR_GCHANNEL_MASK);
-		if ((r == (SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION)) ||
-		    (r == (SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION))) {
-#ifdef RLD_TRANS_DEBUG
-			pr_info(">> same CHAN ACT SR, Port %d Req %x => issue SR_NOOP CMD\n", pi->portnum, req);
-#endif
-			/* allow this next request */
-			SD_SEM_GIVE(&pi->sr_sem_busy);
-			musycc_serv_req(pi, SR_NOOP);
-			/* relock & continue w/ original req */
-			SD_SEM_TAKE(&pi->sr_sem_busy, "serv");
-		} else if (req == SR_NOOP) {
-			/* no need to issue back-to-back
-			 * SR_NOOP commands at this time
-			 */
-#ifdef RLD_TRANS_DEBUG
-			pr_info(">> same Port SR_NOOP skipped, Port %d\n",
-				pi->portnum);
-#endif
-			/* allow this next request */
-			SD_SEM_GIVE(&pi->sr_sem_busy);
-			return;
-		}
-	}
-	rcnt = 0;
-	pi->sr_last = req;
-rewrite:
-	pci_write_32((u_int32_t *) &pi->reg->srd, req);
-	FLUSH_MEM_WRITE();
-
-	/*
-	 * Per MUSYCC Manual, Section 6.1,2 - "When writing an SCR service
-	 * request, the host must ensure at least one PCI bus clock cycle has
-	 * elapsed before writing another service request.  To meet this minimum
-	 * elapsed service request write timing interval, it is recommended that
-	 * the host follow any SCR write with another operation which reads from
-	 * the same address."
-	 */
-
-	/* adhere to write timing imposition */
-	r = pci_read_32((u_int32_t *) &pi->reg->srd);
-
-
-	if ((r != req) && (req != SR_CHIP_RESET) &&
-	    (++rcnt <= MUSYCC_SR_RETRY_CNT)) {
-		if (cxt1e1_log_level >= LOG_MONITOR)
-			pr_info("%s: %d - reissue srv req/last %x/%x (hdw reads %x), Chan %d.\n",
-				pi->up->devname, rcnt, req, pi->sr_last, r,
-				(pi->portnum * MUSYCC_NCHANS) + (req & 0x1f));
-		/* this delay helps reduce reissue counts
-		 * (reason not yet researched)
-		 */
-		OS_uwait_dummy();
-		goto rewrite;
-	}
-	if (rcnt > MUSYCC_SR_RETRY_CNT) {
-		pr_warning("%s: failed service request (#%d)= %x, group %d.\n",
-			   pi->up->devname, MUSYCC_SR_RETRY_CNT,
-			   req, pi->portnum);
-		SD_SEM_GIVE(&pi->sr_sem_busy); /* allow any next request */
-		return;
-	}
-	if (req == SR_CHIP_RESET) {
-		/*
-		 * PORT NOTE: the CHIP_RESET command is NOT ack'd by the MUSYCC, thus
-		 * the upcoming delay is used.  Though the MUSYCC documentation
-		 * suggests a read-after-write would supply the required delay, it's
-		 * unclear what CPU/BUS clock speeds might have been assumed when
-		 * suggesting this 'lack of ACK' workaround.  Thus the use of uwait.
-		 */
-		OS_uwait(100000, "icard"); /* 100ms */
-	} else {
-		FLUSH_MEM_READ();
-		/* sleep until SACK interrupt occurs */
-		SD_SEM_TAKE(&pi->sr_sem_wait, "sakack");
-	}
-	SD_SEM_GIVE(&pi->sr_sem_busy); /* allow any next request */
-}
-
-
-#ifdef  SBE_PMCC4_ENABLE
-void
-musycc_update_timeslots(mpi_t *pi)
-{
-	int         i, ch;
-	char        e1mode = IS_FRAME_ANY_E1(pi->p.port_mode);
-
-	for (i = 0; i < 32; i++) {
-		int         usedby = 0, last = 0, ts, j, bits[8];
-
-		u_int8_t lastval = 0;
-
-		if (((i == 0) && e1mode) || /* disable if  E1 mode */
-		    ((i == 16) && ((pi->p.port_mode == CFG_FRAME_E1CRC_CAS) ||
-		    (pi->p.port_mode == CFG_FRAME_E1CRC_CAS_AMI))) ||
-		    ((i > 23) && (!e1mode))) /* disable if T1 mode */
-			/* make tslot unavailable for this mode */
-			pi->tsm[i] = 0xff;
-		else
-			/* make tslot available for assignment */
-			pi->tsm[i] = 0x00;
-		for (j = 0; j < 8; j++)
-			bits[j] = -1;
-		for (ch = 0; ch < MUSYCC_NCHANS; ch++) {
-			if ((pi->chan[ch]->state == UP) &&
-			    (pi->chan[ch]->p.bitmask[i])) {
-				usedby++;
-				last = ch;
-				lastval = pi->chan[ch]->p.bitmask[i];
-				for (j = 0; j < 8; j++)
-					if (lastval & (1 << j))
-						bits[j] = ch;
-				pi->tsm[i] |= lastval;
-			}
-		}
-		if (!usedby)
-			ts = 0;
-		else if ((usedby == 1) && (lastval == 0xff))
-			ts = (4 << 5) | last;
-		else if ((usedby == 1) && (lastval == 0x7f))
-			ts = (5 << 5) | last;
-		else {
-			int         idx;
-
-			if (bits[0] < 0)
-				ts = (6 << 5) | (idx = last);
-			else
-				ts = (7 << 5) | (idx = bits[0]);
-			for (j = 1; j < 8; j++) {
-				pi->regram->rscm[idx * 8 + j] =
-					(bits[j] < 0) ? 0 : (0x80 | bits[j]);
-				pi->regram->tscm[idx * 8 + j] =
-					(bits[j] < 0) ? 0 : (0x80 | bits[j]);
-			}
-		}
-		pi->regram->rtsm[i] = ts;
-		pi->regram->ttsm[i] = ts;
-	}
-	FLUSH_MEM_WRITE();
-
-	musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
-	musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
-	musycc_serv_req(pi, SR_SUBCHANNEL_MAP | SR_RX_DIRECTION);
-	musycc_serv_req(pi, SR_SUBCHANNEL_MAP | SR_TX_DIRECTION);
-}
-#endif
-
-
-#ifdef SBE_WAN256T3_ENABLE
-	void
-musycc_update_timeslots(mpi_t *pi)
-{
-	mch_t      *ch;
-
-	u_int8_t    ts, hmask, tsen;
-	int         gchan;
-	int         i;
-
-#ifdef SBE_PMCC4_ENABLE
-	hmask = (0x1f << pi->up->p.hypersize) & 0x1f;
-#endif
-#ifdef SBE_WAN256T3_ENABLE
-	hmask = (0x1f << hyperdummy) & 0x1f;
-#endif
-	for (i = 0; i < 128; i++) {
-		gchan = ((pi->portnum * MUSYCC_NCHANS) +
-			(i & hmask)) % MUSYCC_NCHANS;
-		ch = pi->chan[gchan];
-		if (ch->p.mode_56k)
-			tsen = MODE_56KBPS;
-		else
-			tsen = MODE_64KBPS;     /* also the default */
-		ts = ((pi->portnum % 4) == (i / 32)) ? (tsen << 5) | (i & hmask) : 0;
-		pi->regram->rtsm[i] = ts;
-		pi->regram->ttsm[i] = ts;
-	}
-	FLUSH_MEM_WRITE();
-	musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
-	musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
-}
-#endif
-
-
- /*
-  * This routine converts a generic library channel configuration parameter
-  * into a hardware specific register value (IE. MUSYCC CCD Register).
-  */
-u_int32_t
-musycc_chan_proto(int proto)
-{
-	int         reg;
-
-	switch (proto) {
-	case CFG_CH_PROTO_TRANS:        /* 0 */
-		reg = MUSYCC_CCD_TRANS;
-		break;
-	case CFG_CH_PROTO_SS7:          /* 1 */
-		reg = MUSYCC_CCD_SS7;
-		break;
-	default:
-	case CFG_CH_PROTO_ISLP_MODE:   /* 4 */
-	case CFG_CH_PROTO_HDLC_FCS16:  /* 2 */
-		reg = MUSYCC_CCD_HDLC_FCS16;
-		break;
-	case CFG_CH_PROTO_HDLC_FCS32:  /* 3 */
-		reg = MUSYCC_CCD_HDLC_FCS32;
-		break;
-	}
-
-	return reg;
-}
-
-#ifdef SBE_WAN256T3_ENABLE
-static void __init
-musycc_init_port(mpi_t *pi)
-{
-	pci_write_32((u_int32_t *) &pi->reg->gbp, OS_vtophys(pi->regram));
-
-	pi->regram->grcd =
-		__constant_cpu_to_le32(MUSYCC_GRCD_RX_ENABLE |
-				       MUSYCC_GRCD_TX_ENABLE |
-				       MUSYCC_GRCD_SF_ALIGN |
-				       MUSYCC_GRCD_SUBCHAN_DISABLE |
-				       MUSYCC_GRCD_OOFMP_DISABLE |
-				       MUSYCC_GRCD_COFAIRQ_DISABLE |
-				       MUSYCC_GRCD_MC_ENABLE |
-				       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
-
-	pi->regram->pcd =
-		__constant_cpu_to_le32(MUSYCC_PCD_E1X4_MODE |
-				       MUSYCC_PCD_TXDATA_RISING |
-				       MUSYCC_PCD_TX_DRIVEN);
-
-	/* Message length descriptor */
-	pi->regram->mld = __constant_cpu_to_le32(cxt1e1_max_mru | (cxt1e1_max_mru << 16));
-	FLUSH_MEM_WRITE();
-
-	musycc_serv_req(pi, SR_GROUP_INIT | SR_RX_DIRECTION);
-	musycc_serv_req(pi, SR_GROUP_INIT | SR_TX_DIRECTION);
-
-	musycc_init_mdt(pi);
-
-	musycc_update_timeslots(pi);
-}
-#endif
-
-
-status_t    __init
-musycc_init(ci_t *ci)
-{
-	char       *regaddr;        /* temp for address boundary calculations */
-	int         i, gchan;
-
-	OS_sem_init(&ci->sem_wdbusy, SEM_AVAILABLE); /* watchdog exclusion */
-
-	/*
-	 * Per MUSYCC manual, Section 6.3.4 - "The host must allocate a dword
-	 * aligned memory segment for interrupt queue pointers."
-	 */
-
-#define INT_QUEUE_BOUNDARY  4
-
-	regaddr = kzalloc((INT_QUEUE_SIZE + 1) * sizeof(u_int32_t),
-			  GFP_KERNEL | GFP_DMA);
-	if (!regaddr)
-		return -ENOMEM;
-	ci->iqd_p_saved = regaddr;      /* save orig value for free's usage */
-	/* this calculates closest boundary */
-	ci->iqd_p = (u_int32_t *) ((unsigned long)(regaddr + INT_QUEUE_BOUNDARY - 1) &
-				   (~(INT_QUEUE_BOUNDARY - 1)));
-
-	for (i = 0; i < INT_QUEUE_SIZE; i++)
-		ci->iqd_p[i] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
-
-	for (i = 0; i < ci->max_port; i++) {
-		mpi_t      *pi = &ci->port[i];
-
-		/*
-		 * Per MUSYCC manual, Section 6.3.2 - "The host must allocate a 2KB
-		 * bound memory segment for Channel Group 0."
-		 */
-
-#define GROUP_BOUNDARY   0x800
-
-		regaddr = kzalloc(sizeof(struct musycc_groupr) + GROUP_BOUNDARY,
-				  GFP_KERNEL | GFP_DMA);
-		if (!regaddr) {
-			for (gchan = 0; gchan < i; gchan++) {
-				pi = &ci->port[gchan];
-				kfree(pi->reg);
-				pi->reg = NULL;
-			}
-			return -ENOMEM;
-		}
-		pi->regram_saved = regaddr; /* save orig value for free's usage */
-		/* this calculates closest boundary */
-		pi->regram = (struct musycc_groupr *) ((unsigned long)(regaddr + GROUP_BOUNDARY - 1) &
-				(~(GROUP_BOUNDARY - 1)));
-	}
-
-	/* any board centric MUSYCC commands will use group ZERO as its "home" */
-	ci->regram = ci->port[0].regram;
-	musycc_serv_req(&ci->port[0], SR_CHIP_RESET);
-
-	pci_write_32((u_int32_t *) &ci->reg->gbp, OS_vtophys(ci->regram));
-	pci_flush_write(ci);
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-	ci->regram->__glcd = __constant_cpu_to_le32(GCD_MAGIC);
-#else
-	/* standard driver POLLS for INTB via CPLD register */
-	ci->regram->__glcd = __constant_cpu_to_le32(GCD_MAGIC |
-						    MUSYCC_GCD_INTB_DISABLE);
-#endif
-
-	ci->regram->__iqp = cpu_to_le32(OS_vtophys(&ci->iqd_p[0]));
-	ci->regram->__iql = __constant_cpu_to_le32(INT_QUEUE_SIZE - 1);
-	pci_write_32((u_int32_t *) &ci->reg->dacbp, 0);
-	FLUSH_MEM_WRITE();
-
-	ci->state = C_RUNNING;          /* mark as full interrupt processing
-					 * available */
-
-	musycc_serv_req(&ci->port[0], SR_GLOBAL_INIT); /* FIRST INTERRUPT ! */
-
-	/* sanity check settable parameters */
-
-	if (cxt1e1_max_mru > 0xffe) {
-		pr_warning("Maximum allowed MRU exceeded, resetting %d to %d.\n",
-			   cxt1e1_max_mru, 0xffe);
-		cxt1e1_max_mru = 0xffe;
-	}
-	if (cxt1e1_max_mtu > 0xffe) {
-		pr_warning("Maximum allowed MTU exceeded, resetting %d to %d.\n",
-			   cxt1e1_max_mtu, 0xffe);
-		cxt1e1_max_mtu = 0xffe;
-	}
-#ifdef SBE_WAN256T3_ENABLE
-	for (i = 0; i < MUSYCC_NPORTS; i++)
-		musycc_init_port(&ci->port[i]);
-#endif
-
-	return SBE_DRVR_SUCCESS;        /* no error */
-}
-
-
-void
-musycc_bh_tx_eom(mpi_t *pi, int gchan)
-{
-	mch_t      *ch;
-	struct mdesc *md;
-
-	volatile u_int32_t status;
-
-	ch = pi->chan[gchan];
-	if (!ch || ch->state != UP) {
-		if (cxt1e1_log_level >= LOG_ERROR)
-			pr_info("%s: intr: xmit EOM on uninitialized channel %d\n",
-				pi->up->devname, gchan);
-	}
-	if (!ch || !ch->mdt)
-		return;                     /* note: mdt==0 implies a malloc()
-					     * failure w/in chan_up() routine */
-
-	do {
-		FLUSH_MEM_READ();
-		md = ch->txd_irq_srv;
-		status = le32_to_cpu(md->status);
-
-		/*
-		 * Note: Per MUSYCC Ref 6.4.9, the host does not poll a host-owned
-		 * Transmit Buffer Descriptor during Transparent Mode.
-		 */
-		if (status & MUSYCC_TX_OWNED) {
-			int         readCount, loopCount;
-
-			/***********************************************************/
-			/* HW Bug Fix                                              */
-			/* ----------                                              */
-			/* Under certain PCI Bus loading conditions, the data      */
-			/* associated with an update of Shared Memory is delayed   */
-			/* relative to its PCI Interrupt.  This is caught when     */
-			/* the host determines it does not yet OWN the descriptor. */
-			/***********************************************************/
-
-			readCount = 0;
-			while (status & MUSYCC_TX_OWNED) {
-				for (loopCount = 0; loopCount < 0x30; loopCount++)
-					/* use call to avoid optimization
-					 * removal of dummy delay */
-					OS_uwait_dummy();
-				FLUSH_MEM_READ();
-				status = le32_to_cpu(md->status);
-				if (readCount++ > 40)
-					break; /* don't wait any longer */
-			}
-			if (status & MUSYCC_TX_OWNED) {
-				if (cxt1e1_log_level >= LOG_MONITOR) {
-					pr_info("%s: Port %d Chan %2d - unexpected TX msg ownership intr (md %p sts %x)\n",
-						pi->up->devname, pi->portnum,
-						ch->channum, md, status);
-					pr_info("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-						ch->user, ch->txd_irq_srv,
-						ch->txd_usr_add,
-						sd_queue_stopped(ch->user),
-						ch->ch_start_tx, ch->tx_full,
-						ch->txd_free, ch->p.chan_mode);
-					musycc_dump_txbuffer_ring(ch, 0);
-				}
-				break;              /* Not our mdesc, done */
-			} else {
-				if (cxt1e1_log_level >= LOG_MONITOR)
-					pr_info("%s: Port %d Chan %2d - recovered TX msg ownership [%d] (md %p sts %x)\n",
-						pi->up->devname, pi->portnum,
-						ch->channum, readCount,
-						md, status);
-			}
-		}
-		ch->txd_irq_srv = md->snext;
-
-		md->data = 0;
-		if (md->mem_token) {
-			/* upcount channel */
-			atomic_sub(OS_mem_token_tlen(md->mem_token),
-				   &ch->tx_pending);
-			/* upcount card */
-			atomic_sub(OS_mem_token_tlen(md->mem_token),
-				   &pi->up->tx_pending);
-#ifdef SBE_WAN256T3_ENABLE
-			if (!atomic_read(&pi->up->tx_pending))
-				wan256t3_led(pi->up, LED_TX, 0);
-#endif
-			OS_mem_token_free_irq(md->mem_token);
-			md->mem_token = NULL;
-		}
-		md->status = 0;
-#ifdef RLD_TXFULL_DEBUG
-		if (cxt1e1_log_level >= LOG_MONITOR2)
-			pr_info("~~ tx_eom: tx_full %x  txd_free %d -> %d\n",
-				ch->tx_full, ch->txd_free, ch->txd_free + 1);
-#endif
-		++ch->txd_free;
-		FLUSH_MEM_WRITE();
-
-		if ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) &&
-		    (status & EOBIRQ_ENABLE)) {
-			if (cxt1e1_log_level >= LOG_MONITOR)
-				pr_info("%s: Mode (%x) incorrect EOB status (%x)\n",
-					pi->up->devname, ch->p.chan_mode,
-					status);
-			if ((status & EOMIRQ_ENABLE) == 0)
-				break;
-		}
-	} while ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) &&
-		 ((status & EOMIRQ_ENABLE) == 0));
-	/*
-	 * NOTE: (The above 'while' is coupled w/ previous 'do', way above.) Each
-	 * Transparent data buffer has the EOB bit, and NOT the EOM bit, set and
-	 * will furthermore have a separate IQD associated with each messages
-	 * buffer.
-	 */
-
-	FLUSH_MEM_READ();
-	/*
-	 * Smooth flow control hysterisis by maintaining task stoppage until half
-	 * the available write buffers are available.
-	 */
-	if (ch->tx_full && (ch->txd_free >= (ch->txd_num / 2))) {
-		/*
-		 * Then, only releave task stoppage if we actually have enough
-		 * buffers to service the last requested packet.  It may require MORE
-		 * than half the available!
-		 */
-		if (ch->txd_free >= ch->txd_required) {
-
-#ifdef RLD_TXFULL_DEBUG
-			if (cxt1e1_log_level >= LOG_MONITOR2)
-				pr_info("tx_eom[%d]: enable xmit tx_full no more, txd_free %d txd_num/2 %d\n",
-					ch->channum,
-					ch->txd_free, ch->txd_num / 2);
-#endif
-			ch->tx_full = 0;
-			ch->txd_required = 0;
-			/* re-enable to catch flow controlled channel */
-			sd_enable_xmit(ch->user);
-		}
-	}
-#ifdef RLD_TXFULL_DEBUG
-	else if (ch->tx_full) {
-		if (cxt1e1_log_level >= LOG_MONITOR2)
-			pr_info("tx_eom[%d]: bypass TX enable though room available? (txd_free %d txd_num/2 %d)\n",
-				ch->channum,
-				ch->txd_free, ch->txd_num / 2);
-	}
-#endif
-
-	FLUSH_MEM_WRITE();
-}
-
-
-static void
-musycc_bh_rx_eom(mpi_t *pi, int gchan)
-{
-	mch_t      *ch;
-	void       *m, *m2;
-	struct mdesc *md;
-	volatile u_int32_t status;
-	u_int32_t   error;
-
-	ch = pi->chan[gchan];
-	if (!ch || ch->state != UP) {
-		if (cxt1e1_log_level > LOG_ERROR)
-			pr_info("%s: intr: receive EOM on uninitialized channel %d\n",
-				pi->up->devname, gchan);
-		return;
-	}
-	if (!ch->mdr)
-		return;                     /* can this happen ? */
-
-	for (;;) {
-		FLUSH_MEM_READ();
-		md = &ch->mdr[ch->rxix_irq_srv];
-		status = le32_to_cpu(md->status);
-		if (!(status & HOST_RX_OWNED))
-			break;                  /* Not our mdesc, done */
-		m = md->mem_token;
-		error = (status >> 16) & 0xf;
-		if (error == 0) {
-			{
-				m2 = OS_mem_token_alloc(cxt1e1_max_mru);
-				if (m2) {
-					/* substitute the mbuf+cluster */
-					md->mem_token = m2;
-					md->data = cpu_to_le32(OS_vtophys(
-							       OS_mem_token_data(m2)));
-
-					/* pass the received mbuf upward */
-					sd_recv_consume(m, status & LENGTH_MASK,
-							ch->user);
-					ch->s.rx_packets++;
-					ch->s.rx_bytes += status & LENGTH_MASK;
-				} else
-					ch->s.rx_dropped++;
-			}
-		} else if (error == ERR_FCS)
-			ch->s.rx_crc_errors++;
-		else if (error == ERR_ALIGN)
-			ch->s.rx_missed_errors++;
-		else if (error == ERR_ABT)
-			ch->s.rx_missed_errors++;
-		else if (error == ERR_LNG)
-			ch->s.rx_length_errors++;
-		else if (error == ERR_SHT)
-			ch->s.rx_length_errors++;
-		FLUSH_MEM_WRITE();
-		status = cxt1e1_max_mru;
-		if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-			status |= EOBIRQ_ENABLE;
-		md->status = cpu_to_le32(status);
-
-		/* Check next mdesc in the ring */
-		if (++ch->rxix_irq_srv >= ch->rxd_num)
-			ch->rxix_irq_srv = 0;
-		FLUSH_MEM_WRITE();
-	}
-}
-
-
-irqreturn_t
-musycc_intr_th_handler(void *devp)
-{
-	ci_t       *ci = (ci_t *) devp;
-	volatile u_int32_t status, currInt = 0;
-	u_int32_t   nextInt, intCnt;
-
-	/*
-	 * Hardware not available, potential interrupt hang.  But since interrupt
-	 * might be shared, just return.
-	 */
-	if (ci->state == C_INIT)
-		return IRQ_NONE;
-	/*
-	 * Marked as hardware available. Don't service interrupts, just clear the
-	 * event.
-	 */
-
-	if (ci->state == C_IDLE) {
-		status = pci_read_32((u_int32_t *) &ci->reg->isd);
-
-		/* clear the interrupt but process nothing else */
-		pci_write_32((u_int32_t *) &ci->reg->isd, status);
-		return IRQ_HANDLED;
-	}
-	FLUSH_PCI_READ();
-	FLUSH_MEM_READ();
-
-	status = pci_read_32((u_int32_t *) &ci->reg->isd);
-	nextInt = INTRPTS_NEXTINT(status);
-	intCnt = INTRPTS_INTCNT(status);
-	ci->intlog.drvr_intr_thcount++;
-
-	/*********************************************************/
-	/* HW Bug Fix                                            */
-	/* ----------                                            */
-	/* Under certain PCI Bus loading conditions, the         */
-	/* MUSYCC looses the data associated with an update      */
-	/* of its ISD and erroneously returns the immediately    */
-	/* preceding 'nextInt' value.  However, the 'intCnt'     */
-	/* value appears to be correct.  By not starting service */
-	/* where the 'missing' 'nextInt' SHOULD point causes     */
-	/* the IQD not to be serviced - the 'not serviced'       */
-	/* entries then remain and continue to increase as more  */
-	/* incorrect ISD's are encountered.                      */
-	/*********************************************************/
-
-	if (nextInt != INTRPTS_NEXTINT(ci->intlog.this_status_new)) {
-		if (cxt1e1_log_level >= LOG_MONITOR) {
-			pr_info("%s: note - updated ISD from %08x to %08x\n",
-				ci->devname, status,
-				(status & (~INTRPTS_NEXTINT_M)) |
-				ci->intlog.this_status_new);
-		}
-		/*
-		 * Replace bogus status with software corrected value.
-		 *
-		 * It's not known whether, during this problem occurrence, if the
-		 * INTFULL bit is correctly reported or not.
-		 */
-		status = (status & (~INTRPTS_NEXTINT_M)) |
-			 (ci->intlog.this_status_new);
-		nextInt = INTRPTS_NEXTINT(status);
-	}
-	/**********************************************/
-	/* Cn847x Bug Fix                             */
-	/* --------------                             */
-	/* Fix for inability to write back same index */
-	/* as read for a full interrupt queue.        */
-	/**********************************************/
-
-	if (intCnt == INT_QUEUE_SIZE)
-		currInt = ((intCnt - 1) + nextInt) & (INT_QUEUE_SIZE - 1);
-	else
-		/************************************************/
-		/* Interrupt Write Location Issues              */
-		/* -------------------------------              */
-		/* When the interrupt status descriptor is      */
-		/* written, the interrupt line is de-asserted   */
-		/* by the Cn847x.  In the case of MIPS          */
-		/* microprocessors, this must occur at the      */
-		/* beginning of the interrupt handler so that   */
-		/* the interrupt handle is not re-entered due   */
-		/* to interrupt dis-assertion latency.          */
-		/* In the case of all other processors, this    */
-		/* action should occur at the end of the        */
-		/* interrupt handler to avoid overwriting the   */
-		/* interrupt queue.                             */
-		/************************************************/
-
-		if (intCnt)
-			currInt = (intCnt + nextInt) & (INT_QUEUE_SIZE - 1);
-		else {
-			/*
-			 * NOTE: Servicing an interrupt whose ISD contains a count of ZERO
-			 * can be indicative of a Shared Interrupt chain.  Our driver can be
-			 * called from the system's interrupt handler as a matter of the OS
-			 * walking the chain.  As the chain is walked, the interrupt will
-			 * eventually be serviced by the correct driver/handler.
-			 */
-			return IRQ_NONE;
-		}
-
-	ci->iqp_tailx = currInt;
-
-	currInt <<= INTRPTS_NEXTINT_S;
-	ci->intlog.last_status_new = ci->intlog.this_status_new;
-	ci->intlog.this_status_new = currInt;
-
-	if ((cxt1e1_log_level >= LOG_WARN) && (status & INTRPTS_INTFULL_M))
-		pr_info("%s: Interrupt queue full condition occurred\n",
-			ci->devname);
-	if (cxt1e1_log_level >= LOG_DEBUG)
-		pr_info("%s: interrupts pending, isd @ 0x%p: %x curr %d cnt %d NEXT %d\n",
-			ci->devname, &ci->reg->isd,
-			status, nextInt, intCnt,
-			(intCnt + nextInt) & (INT_QUEUE_SIZE - 1));
-
-	FLUSH_MEM_WRITE();
-#if defined(SBE_ISR_TASKLET)
-	pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
-	atomic_inc(&ci->bh_pending);
-	tasklet_schedule(&ci->ci_musycc_isr_tasklet);
-#elif defined(SBE_ISR_IMMEDIATE)
-	pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
-	atomic_inc(&ci->bh_pending);
-	queue_task(&ci->ci_musycc_isr_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-#elif defined(SBE_ISR_INLINE)
-	(void) musycc_intr_bh_tasklet(ci);
-	pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
-#endif
-	return IRQ_HANDLED;
-}
-
-
-#if defined(SBE_ISR_IMMEDIATE)
-unsigned long
-#else
-void
-#endif
-musycc_intr_bh_tasklet(ci_t *ci)
-{
-	mpi_t      *pi;
-	mch_t      *ch;
-	unsigned int intCnt;
-	volatile u_int32_t currInt = 0;
-	volatile unsigned int headx, tailx;
-	int         readCount, loopCount;
-	int         group, gchan, event, err, tx;
-	u_int32_t   badInt = INT_EMPTY_ENTRY;
-	u_int32_t   badInt2 = INT_EMPTY_ENTRY2;
-
-	/*
-	 * Hardware not available, potential interrupt hang.  But since interrupt
-	 * might be shared, just return.
-	 */
-	if ((drvr_state != SBE_DRVR_AVAILABLE) || (ci->state == C_INIT)) {
-#if defined(SBE_ISR_IMMEDIATE)
-		return 0L;
-#else
-		return;
-#endif
-	}
-#if defined(SBE_ISR_TASKLET) || defined(SBE_ISR_IMMEDIATE)
-	if (drvr_state != SBE_DRVR_AVAILABLE) {
-#if defined(SBE_ISR_TASKLET)
-		return;
-#elif defined(SBE_ISR_IMMEDIATE)
-		return 0L;
-#endif
-	}
-#elif defined(SBE_ISR_INLINE)
-	/* no semaphore taken, no double checks */
-#endif
-
-	ci->intlog.drvr_intr_bhcount++;
-	FLUSH_MEM_READ();
-	{
-		unsigned int bh = atomic_read(&ci->bh_pending);
-
-		max_bh = max(bh, max_bh);
-	}
-	atomic_set(&ci->bh_pending, 0);/* if here, no longer pending */
-	while ((headx = ci->iqp_headx) != (tailx = ci->iqp_tailx)) {
-		intCnt = (tailx >= headx) ? (tailx - headx) : (tailx - headx + INT_QUEUE_SIZE);
-		currInt = le32_to_cpu(ci->iqd_p[headx]);
-
-		max_intcnt = max(intCnt, max_intcnt);  /* RLD DEBUG */
-
-		/**************************************************/
-		/* HW Bug Fix                                     */
-		/* ----------                                     */
-		/* The following code checks for the condition    */
-		/* of interrupt assertion before interrupt        */
-		/* queue update.  This is a problem on several    */
-		/* PCI-Local bridge chips found on some products. */
-		/**************************************************/
-
-		readCount = 0;
-		if ((currInt == badInt) || (currInt == badInt2))
-			ci->intlog.drvr_int_failure++;
-
-		while ((currInt == badInt) || (currInt == badInt2)) {
-			for (loopCount = 0; loopCount < 0x30; loopCount++)
-				/* use call to avoid optimization
-				 * removal of dummy delay
-				 */
-				OS_uwait_dummy();
-			FLUSH_MEM_READ();
-			currInt = le32_to_cpu(ci->iqd_p[headx]);
-			if (readCount++ > 20)
-				break;
-		}
-
-		/* catch failure of Bug Fix checking */
-		if ((currInt == badInt) || (currInt == badInt2)) {
-			if (cxt1e1_log_level >= LOG_WARN)
-				pr_info("%s: Illegal Interrupt Detected @ 0x%p, mod %d.)\n",
-					ci->devname, &ci->iqd_p[headx], headx);
-
-			/*
-			 * If the descriptor has not recovered, then leaving the EMPTY
-			 * entry set will not signal to the MUSYCC that this descriptor
-			 * has been serviced. The Interrupt Queue can then start losing
-			 * available descriptors and MUSYCC eventually encounters and
-			 * reports the INTFULL condition.  Per manual, changing any bit
-			 * marks descriptor as available, thus the use of different
-			 * EMPTY_ENTRY values.
-			 */
-
-			if (currInt == badInt)
-				ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY2);
-			else
-				ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
-			/* insure wrapness */
-			ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1);
-			FLUSH_MEM_WRITE();
-			FLUSH_MEM_READ();
-			continue;
-		}
-		group = INTRPT_GRP(currInt);
-		gchan = INTRPT_CH(currInt);
-		event = INTRPT_EVENT(currInt);
-		err = INTRPT_ERROR(currInt);
-		tx = currInt & INTRPT_DIR_M;
-
-		ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
-		FLUSH_MEM_WRITE();
-
-		if (cxt1e1_log_level >= LOG_DEBUG) {
-			if (err != 0)
-				pr_info(" %08x -> err: %2d,", currInt, err);
-
-			pr_info("+ interrupt event: %d, grp: %d, chan: %2d, side: %cX\n",
-				event, group, gchan, tx ? 'T' : 'R');
-		}
-		/* notice that here we assume 1-1 group - port mapping */
-		pi = &ci->port[group];
-		ch = pi->chan[gchan];
-		switch (event) {
-		case EVE_SACK:              /* Service Request Acknowledge */
-			if (cxt1e1_log_level >= LOG_DEBUG) {
-				volatile u_int32_t r;
-
-				r = pci_read_32((u_int32_t *) &pi->reg->srd);
-				pr_info("- SACK cmd: %08x (hdw= %08x)\n",
-					pi->sr_last, r);
-			}
-			/* wake up waiting process */
-			SD_SEM_GIVE(&pi->sr_sem_wait);
-			break;
-		case EVE_CHABT: /* Change To Abort Code (0x7e -> 0xff) */
-		case EVE_CHIC:  /* Change To Idle Code (0xff -> 0x7e) */
-			break;
-		case EVE_EOM:   /* End Of Message */
-		case EVE_EOB:   /* End Of Buffer (Transparent mode) */
-			if (tx)
-				musycc_bh_tx_eom(pi, gchan);
-			else
-				musycc_bh_rx_eom(pi, gchan);
-			/*
-			 * MUSYCC Interrupt Descriptor section states that EOB and EOM
-			 * can be combined with the NONE error (as well as others).  So
-			 * drop thru to catch this...
-			 */
-		case EVE_NONE:
-			if (err == ERR_SHT)
-				ch->s.rx_length_errors++;
-			break;
-		default:
-			if (cxt1e1_log_level >= LOG_WARN)
-				pr_info("%s: unexpected interrupt event: %d, iqd[%d]: %08x, port: %d\n", ci->devname,
-					event, headx, currInt, group);
-			break;
-		}                           /* switch on event */
-
-
-		/*
-		 * Per MUSYCC Manual, Section 6.4.8.3 [Transmit Errors], TX errors
-		 * are service-affecting and require action to resume normal
-		 * bit-level processing.
-		 */
-
-		switch (err) {
-		case ERR_ONR:
-			/*
-			 * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors], this
-			 * error requires Transmit channel reactivation.
-			 *
-			 * Per MUSYCC manual, Section  6.4.8.4 [Receive Errors], this error
-			 * requires Receive channel reactivation.
-			 */
-			if (tx) {
-
-				/*
-				 * TX ONR Error only occurs when channel is configured for
-				 * Transparent Mode.  However, this code will catch and
-				 * re-activate on ANY TX ONR error.
-				 */
-
-				/*
-				 * Set flag to re-enable on any next transmit attempt.
-				 */
-				ch->ch_start_tx = CH_START_TX_ONR;
-
-#ifdef RLD_TRANS_DEBUG
-				if (1 || cxt1e1_log_level >= LOG_MONITOR)
-#else
-				if (cxt1e1_log_level >= LOG_MONITOR)
-#endif
-				{
-					pr_info("%s: TX buffer underflow [ONR] on channel %d, mode %x QStopped %x free %d\n",
-						ci->devname, ch->channum,
-						ch->p.chan_mode,
-						sd_queue_stopped(ch->user),
-						ch->txd_free);
-#ifdef RLD_DEBUG
-					/* problem = ONR on HDLC mode */
-					if (ch->p.chan_mode == 2) {
-						pr_info("++ Failed Last %x Next %x QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-							(u_int32_t)ch->txd_irq_srv,
-							(u_int32_t)ch->txd_usr_add,
-							sd_queue_stopped(ch->user),
-							ch->ch_start_tx,
-							ch->tx_full,
-							ch->txd_free,
-							ch->p.chan_mode);
-						musycc_dump_txbuffer_ring(ch, 0);
-					}
-#endif
-				}
-			} else {                 /* RX buffer overrun */
-				/*
-				 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors],
-				 * channel recovery for this RX ONR error IS required.  It is
-				 * also suggested to increase the number of receive buffers
-				 * for this channel.  Receive channel reactivation IS
-				 * required, and data has been lost.
-				 */
-				ch->s.rx_over_errors++;
-				ch->ch_start_rx = CH_START_RX_ONR;
-
-				if (cxt1e1_log_level >= LOG_WARN) {
-					pr_info("%s: RX buffer overflow [ONR] on channel %d, mode %x\n",
-						ci->devname, ch->channum,
-						ch->p.chan_mode);
-#ifdef RLD_DEBUG
-					musycc_dump_rxbuffer_ring(ch, 0);
-#endif
-				}
-			}
-			musycc_chan_restart(ch);
-			break;
-		case ERR_BUF:
-			if (tx) {
-				ch->s.tx_fifo_errors++;
-				ch->ch_start_tx = CH_START_TX_BUF;
-				/*
-				 * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors],
-				 * this BUFF error requires Transmit channel reactivation.
-				 */
-				if (cxt1e1_log_level >= LOG_MONITOR)
-					pr_info("%s: TX buffer underrun [BUFF] on channel %d, mode %x\n",
-						ci->devname, ch->channum,
-						ch->p.chan_mode);
-			} else {                 /* RX buffer overrun */
-				ch->s.rx_over_errors++;
-				/*
-				 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors], HDLC
-				 * mode requires NO recovery for this RX BUFF error is
-				 * required.  It is suggested to increase the FIFO buffer
-				 * space for this channel.  Receive channel reactivation is
-				 * not required, but data has been lost.
-				 */
-				if (cxt1e1_log_level >= LOG_WARN)
-					pr_info("%s: RX buffer overrun [BUFF] on channel %d, mode %x\n",
-						ci->devname, ch->channum,
-						ch->p.chan_mode);
-				/*
-				 * Per MUSYCC manual, Section 6.4.9.4 [Receive Errors],
-				 * Transparent mode DOES require recovery for the RX BUFF
-				 * error.  It is suggested to increase the FIFO buffer space
-				 * for this channel.  Receive channel reactivation IS
-				 * required and data has been lost.
-				 */
-				if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-					ch->ch_start_rx = CH_START_RX_BUF;
-			}
-
-			if (tx || (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
-				musycc_chan_restart(ch);
-			break;
-		default:
-			break;
-		}                           /* switch on err */
-
-		/* Check for interrupt lost condition */
-		if ((currInt & INTRPT_ILOST_M) &&
-		    (cxt1e1_log_level >= LOG_ERROR))
-			pr_info("%s: Interrupt queue overflow - ILOST asserted\n",
-				ci->devname);
-		/* insure wrapness */
-		ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1);
-		FLUSH_MEM_WRITE();
-		FLUSH_MEM_READ();
-	}                               /* while */
-	if ((cxt1e1_log_level >= LOG_MONITOR2) &&
-	    (ci->iqp_headx != ci->iqp_tailx)) {
-		int         bh;
-
-		bh = atomic_read(&CI->bh_pending);
-		pr_info("_bh_: late arrivals, head %d != tail %d, pending %d\n",
-			ci->iqp_headx, ci->iqp_tailx, bh);
-	}
-#if defined(SBE_ISR_IMMEDIATE)
-	return 0L;
-#endif
-	/* else, nothing returned */
-}
-
-#ifdef SBE_PMCC4_ENABLE
-	status_t
-musycc_chan_down(ci_t *dummy, int channum)
-{
-	mpi_t      *pi;
-	mch_t      *ch;
-	int         i, gchan;
-
-	ch = sd_find_chan(dummy, channum);
-	if (!ch)
-		return -EINVAL;
-	pi = ch->up;
-	gchan = ch->gchan;
-
-	/* Deactivate the channel */
-	musycc_serv_req(pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan);
-	ch->ch_start_rx = 0;
-	musycc_serv_req(pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan);
-	ch->ch_start_tx = 0;
-
-	if (ch->state == DOWN)
-		return 0;
-	ch->state = DOWN;
-
-	pi->regram->thp[gchan] = 0;
-	pi->regram->tmp[gchan] = 0;
-	pi->regram->rhp[gchan] = 0;
-	pi->regram->rmp[gchan] = 0;
-	FLUSH_MEM_WRITE();
-	for (i = 0; i < ch->txd_num; i++)
-		if (ch->mdt[i].mem_token)
-			OS_mem_token_free(ch->mdt[i].mem_token);
-
-	for (i = 0; i < ch->rxd_num; i++)
-		if (ch->mdr[i].mem_token)
-			OS_mem_token_free(ch->mdr[i].mem_token);
-
-	kfree(ch->mdr);
-	ch->mdr = NULL;
-	ch->rxd_num = 0;
-	kfree(ch->mdt);
-	ch->mdt = NULL;
-	ch->txd_num = 0;
-
-	musycc_update_timeslots(pi);
-	c4_fifo_free(pi, ch->gchan);
-
-	pi->openchans--;
-	return 0;
-}
-#endif
-
-int
-musycc_start_xmit(ci_t *ci, int channum, void *mem_token)
-{
-	mch_t      *ch;
-	struct mdesc *md;
-	void       *m2;
-	int         txd_need_cnt;
-	u_int32_t   len;
-
-	ch = sd_find_chan(ci, channum);
-	if (!ch)
-		return -ENOENT;
-
-	/* full interrupt processing available */
-	if (ci->state != C_RUNNING)
-		return -EINVAL;
-	if (ch->state != UP)
-		return -EINVAL;
-
-	/* how else to flag unwritable state ? */
-	if (!(ch->status & TX_ENABLED))
-		return -EROFS;
-
-#ifdef RLD_TRANS_DEBUG
-	if (1 || cxt1e1_log_level >= LOG_MONITOR2)
-#else
-	if (cxt1e1_log_level >= LOG_MONITOR2)
-#endif
-	{
-		pr_info("++ start_xmt[%d]: state %x start %x full %d free %d required %d stopped %x\n",
-			channum, ch->state, ch->ch_start_tx, ch->tx_full,
-			ch->txd_free, ch->txd_required,
-			sd_queue_stopped(ch->user));
-	}
-	/***********************************************/
-	/** Determine total amount of data to be sent **/
-	/***********************************************/
-	m2 = mem_token;
-	txd_need_cnt = 0;
-	for (len = OS_mem_token_tlen(m2); len > 0;
-	     m2 = (void *) OS_mem_token_next(m2)) {
-		if (!OS_mem_token_len(m2))
-			continue;
-		txd_need_cnt++;
-		len -= OS_mem_token_len(m2);
-	}
-
-	if (txd_need_cnt == 0) {
-		if (cxt1e1_log_level >= LOG_MONITOR2)
-			pr_info("%s channel %d: no TX data in User buffer\n",
-				ci->devname, channum);
-		OS_mem_token_free(mem_token);
-		return 0;                   /* no data to send */
-	}
-	/*************************************************/
-	/** Are there sufficient descriptors available? **/
-	/*************************************************/
-	if (txd_need_cnt > ch->txd_num) { /* never enough descriptors for this
-					   * large a buffer */
-		if (cxt1e1_log_level >= LOG_DEBUG)
-			pr_info("start_xmit: discarding buffer, insufficient descriptor cnt %d, need %d.\n",
-				ch->txd_num, txd_need_cnt + 1);
-		ch->s.tx_dropped++;
-		OS_mem_token_free(mem_token);
-		return 0;
-	}
-
-	/************************************************************/
-	/** flow control the line if not enough descriptors remain **/
-	/************************************************************/
-	if (txd_need_cnt > ch->txd_free) {
-		if (cxt1e1_log_level >= LOG_MONITOR2)
-			pr_info("start_xmit[%d]: EBUSY - need more descriptors, have %d of %d need %d\n",
-				channum, ch->txd_free,
-				ch->txd_num, txd_need_cnt);
-		ch->tx_full = 1;
-		ch->txd_required = txd_need_cnt;
-		sd_disable_xmit(ch->user);
-		return -EBUSY;               /* tell user to try again later */
-	}
-	/**************************************************/
-	/** Put the user data into MUSYCC data buffer(s) **/
-	/**************************************************/
-	m2 = mem_token;
-	md = ch->txd_usr_add;           /* get current available descriptor */
-
-	for (len = OS_mem_token_tlen(m2); len > 0; m2 = OS_mem_token_next(m2)) {
-		int         u = OS_mem_token_len(m2);
-
-		if (!u)
-			continue;
-		len -= u;
-
-		/*
-		 * Enable following chunks, yet wait to enable the FIRST chunk until
-		 * after ALL subsequent chunks are setup.
-		 */
-		if (md != ch->txd_usr_add)  /* not first chunk */
-			/* transfer ownership from HOST to MUSYCC */
-			u |= MUSYCC_TX_OWNED;
-
-		if (len)                    /* not last chunk */
-			u |= EOBIRQ_ENABLE;
-		else if (ch->p.chan_mode == CFG_CH_PROTO_TRANS) {
-			/*
-			 * Per MUSYCC Ref 6.4.9 for Transparent Mode, the host must
-			 * always clear EOMIRQ_ENABLE in every Transmit Buffer Descriptor
-			 * (IE. don't set herein).
-			 */
-			u |= EOBIRQ_ENABLE;
-		} else
-			u |= EOMIRQ_ENABLE;     /* EOM, last HDLC chunk */
-
-
-		/* last chunk in hdlc mode */
-		u |= (ch->p.idlecode << IDLE_CODE);
-		if (ch->p.pad_fill_count) {
-			u |= (PADFILL_ENABLE | (ch->p.pad_fill_count << EXTRA_FLAGS));
-		}
-		/* Fill in mds on last segment, others set ZERO
-		 * so that entire token is removed ONLY when ALL
-		 * segments have been transmitted.
-		 */
-		md->mem_token = len ? NULL : mem_token;
-
-		md->data = cpu_to_le32(OS_vtophys(OS_mem_token_data(m2)));
-		FLUSH_MEM_WRITE();
-		md->status = cpu_to_le32(u);
-		--ch->txd_free;
-		md = md->snext;
-	}
-	FLUSH_MEM_WRITE();
-
-
-	/*
-	 * Now transfer ownership of first chunk from HOST to MUSYCC in order to
-	 * fire-off this XMIT.
-	 */
-	ch->txd_usr_add->status |= __constant_cpu_to_le32(MUSYCC_TX_OWNED);
-	FLUSH_MEM_WRITE();
-	ch->txd_usr_add = md;
-
-	len = OS_mem_token_tlen(mem_token);
-	atomic_add(len, &ch->tx_pending);
-	atomic_add(len, &ci->tx_pending);
-	ch->s.tx_packets++;
-	ch->s.tx_bytes += len;
-	/*
-	 * If an ONR was seen, then channel requires poking to restart
-	 * transmission.
-	 */
-	if (ch->ch_start_tx)
-		musycc_chan_restart(ch);
-#ifdef SBE_WAN256T3_ENABLE
-	wan256t3_led(ci, LED_TX, LEDV_G);
-#endif
-	return 0;
-}
-
-
-/*** End-of-File ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/musycc.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/musycc.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/musycc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/musycc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,427 +0,0 @@
-#ifndef _INC_MUSYCC_H_
-#define _INC_MUSYCC_H_
-
-/*-----------------------------------------------------------------------------
- * musycc.h - Multichannel Synchronous Communications Controller
- *            CN8778/8474A/8472A/8471A
- *
- * Copyright (C) 2002-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-
-#define VINT8   volatile u_int8_t
-#define VINT32  volatile u_int32_t
-
-#include "pmcc4_defs.h"
-
-
-/*------------------------------------------------------------------------
-//      Vendor, Board Identification definitions
-//------------------------------------------------------------------------
-*/
-
-#define PCI_VENDOR_ID_CONEXANT   0x14f1
-#define PCI_DEVICE_ID_CN8471     0x8471
-#define PCI_DEVICE_ID_CN8472     0x8472
-#define PCI_DEVICE_ID_CN8474     0x8474
-#define PCI_DEVICE_ID_CN8478     0x8478
-#define PCI_DEVICE_ID_CN8500     0x8500
-#define PCI_DEVICE_ID_CN8501     0x8501
-#define PCI_DEVICE_ID_CN8502     0x8502
-#define PCI_DEVICE_ID_CN8503     0x8503
-
-#define INT_QUEUE_SIZE    MUSYCC_NIQD
-
-/* RAM image of MUSYCC registers laid out as a C structure */
-struct musycc_groupr {
-	VINT32      thp[32];    /* Transmit Head Pointer [5-29]           */
-	VINT32      tmp[32];    /* Transmit Message Pointer [5-30]        */
-	VINT32      rhp[32];    /* Receive Head Pointer [5-29]            */
-	VINT32      rmp[32];    /* Receive Message Pointer [5-30]         */
-	VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
-	VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
-	VINT32      tcct[32];   /* Channel Configuration [5-26]           */
-	VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
-	VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
-	VINT32      rcct[32];   /* Channel Configuration [5-26]           */
-	VINT32      __glcd;     /* Global Configuration Descriptor [5-10] */
-	VINT32      __iqp;      /* Interrupt Queue Pointer [5-36]         */
-	VINT32      __iql;      /* Interrupt Queue Length [5-36]          */
-	VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
-	VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
-	VINT32      mld;        /* Message Length Descriptor [5-20]       */
-	VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
-};
-
-/* hardware MUSYCC registers laid out as a C structure */
-struct musycc_globalr {
-	VINT32      gbp;        /* Group Base Pointer                     */
-	VINT32      dacbp;      /* Dual Address Cycle Base Pointer        */
-	VINT32      srd;        /* Service Request Descriptor             */
-	VINT32      isd;        /* Interrupt Service Descriptor           */
-	/*
-	 * adjust __thp due to above 4 registers, which are not contained
-	 * within musycc_groupr[]. All __XXX[] are just place holders,
-	 * anyhow.
-	 */
-	VINT32      __thp[32 - 4];      /* Transmit Head Pointer [5-29]           */
-	VINT32      __tmp[32];  /* Transmit Message Pointer [5-30]        */
-	VINT32      __rhp[32];  /* Receive Head Pointer [5-29]            */
-	VINT32      __rmp[32];  /* Receive Message Pointer [5-30]         */
-	VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
-	VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
-	VINT32      tcct[32];   /* Channel Configuration [5-26]           */
-	VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
-	VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
-	VINT32      rcct[32];   /* Channel Configuration [5-26]           */
-	VINT32      glcd;       /* Global Configuration Descriptor [5-10] */
-	VINT32      iqp;        /* Interrupt Queue Pointer [5-36]         */
-	VINT32      iql;        /* Interrupt Queue Length [5-36]          */
-	VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
-	VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
-	VINT32      mld;        /* Message Length Descriptor [5-20]       */
-	VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
-	VINT32      rbist;      /* Receive BIST status [5-4]              */
-	VINT32      tbist;      /* Receive BIST status [5-4]              */
-};
-
-/* Global Config Descriptor bit macros */
-#define MUSYCC_GCD_ECLK_ENABLE  0x00000800      /* EBUS clock enable */
-#define MUSYCC_GCD_INTEL_SELECT 0x00000400      /* MPU type select */
-#define MUSYCC_GCD_INTA_DISABLE 0x00000008      /* PCI INTA disable */
-#define MUSYCC_GCD_INTB_DISABLE 0x00000004      /* PCI INTB disable */
-#define MUSYCC_GCD_BLAPSE       12      /* Position index for BLAPSE bit
-					 * field */
-#define MUSYCC_GCD_ALAPSE       8       /* Position index for ALAPSE bit
-					 * field */
-#define MUSYCC_GCD_ELAPSE       4       /* Position index for ELAPSE bit
-					 * field */
-#define MUSYCC_GCD_PORTMAP_3    3       /* Reserved */
-#define MUSYCC_GCD_PORTMAP_2    2       /* Port 0=>Grp 0,1,2,3; Port 1=>Grp
-					 * 4,5,6,7 */
-#define MUSYCC_GCD_PORTMAP_1    1       /* Port 0=>Grp 0,1; Port 1=>Grp 2,3,
-					 * etc... */
-#define MUSYCC_GCD_PORTMAP_0    0       /* Port 0=>Grp 0; Port 1=>Grp 2,
-					 * etc... */
-
-/* and board specific assignments... */
-#ifdef SBE_WAN256T3_ENABLE
-#define BLAPSE_VAL      0
-#define ALAPSE_VAL      0
-#define ELAPSE_VAL      7
-#define PORTMAP_VAL     MUSYCC_GCD_PORTMAP_2
-#endif
-
-#ifdef SBE_PMCC4_ENABLE
-#define BLAPSE_VAL      7
-#define ALAPSE_VAL      3
-#define ELAPSE_VAL      7
-#define PORTMAP_VAL     MUSYCC_GCD_PORTMAP_0
-#endif
-
-#define GCD_MAGIC   (((BLAPSE_VAL)<<(MUSYCC_GCD_BLAPSE)) | \
-		     ((ALAPSE_VAL)<<(MUSYCC_GCD_ALAPSE)) | \
-		     ((ELAPSE_VAL)<<(MUSYCC_GCD_ELAPSE)) | \
-		     (MUSYCC_GCD_ECLK_ENABLE) | PORTMAP_VAL)
-
-/* Group Config Descriptor bit macros */
-#define MUSYCC_GRCD_RX_ENABLE       0x00000001  /* Enable receive processing */
-#define MUSYCC_GRCD_TX_ENABLE       0x00000002  /* Enable transmit processing */
-#define MUSYCC_GRCD_SUBCHAN_DISABLE 0x00000004  /* Master disable for
-						 * subchanneling */
-#define MUSYCC_GRCD_OOFMP_DISABLE   0x00000008  /* Out of Frame message
-						 * processing disabled all
-						 * channels */
-#define MUSYCC_GRCD_OOFIRQ_DISABLE  0x00000010  /* Out of Frame/In Frame irqs
-						 * disabled */
-#define MUSYCC_GRCD_COFAIRQ_DISABLE 0x00000020  /* Change of Frame Alignment
-						 * irq disabled */
-#define MUSYCC_GRCD_INHRBSD         0x00000100  /* Receive Buffer Status
-						 * overwrite disabled */
-#define MUSYCC_GRCD_INHTBSD         0x00000200  /* Transmit Buffer Status
-						 * overwrite disabled */
-#define MUSYCC_GRCD_SF_ALIGN        0x00008000  /* External frame sync */
-#define MUSYCC_GRCD_MC_ENABLE       0x00000040  /* Message configuration bits
-						 * copy enable. Conexant sez
-						 * turn this on */
-#define MUSYCC_GRCD_POLLTH_16       0x00000001  /* Poll every 16th frame */
-#define MUSYCC_GRCD_POLLTH_32       0x00000002  /* Poll every 32nd frame */
-#define MUSYCC_GRCD_POLLTH_64       0x00000003  /* Poll every 64th frame */
-#define MUSYCC_GRCD_POLLTH_SHIFT    10  /* Position index for poll throttle
-					 * bit field */
-#define MUSYCC_GRCD_SUERM_THRESH_SHIFT 16       /* Position index for SUERM
-						 * count threshold */
-
-/* Port Config Descriptor bit macros */
-#define MUSYCC_PCD_E1X2_MODE       2    /* Port mode in bits 0-2. T1 and E1 */
-#define MUSYCC_PCD_E1X4_MODE       3    /* are defined in cn847x.h */
-#define MUSYCC_PCD_NX64_MODE       4
-#define MUSYCC_PCD_TXDATA_RISING   0x00000010   /* Sample Tx data on TCLK
-						 * rising edge */
-#define MUSYCC_PCD_TXSYNC_RISING   0x00000020   /* Sample Tx frame sync on
-						 * TCLK rising edge */
-#define MUSYCC_PCD_RXDATA_RISING   0x00000040   /* Sample Rx data on RCLK
-						 * rising edge */
-#define MUSYCC_PCD_RXSYNC_RISING   0x00000080   /* Sample Rx frame sync on
-						 * RCLK rising edge */
-#define MUSYCC_PCD_ROOF_RISING     0x00000100   /* Sample Rx Out Of Frame
-						 * signal on RCLK rising edge */
-#define MUSYCC_PCD_TX_DRIVEN       0x00000200   /* No mapped timeslots causes
-						 * logic 1 on output, else
-						 * tristate */
-#define MUSYCC_PCD_PORTMODE_MASK   0xfffffff8   /* For changing the port mode
-						 * between E1 and T1 */
-
-/* Time Slot Descriptor bit macros */
-#define MUSYCC_TSD_MODE_64KBPS              4
-#define MUSYCC_TSD_MODE_56KBPS              5
-#define MUSYCC_TSD_SUBCHANNEL_WO_FIRST      6
-#define MUSYCC_TSD_SUBCHANNEL_WITH_FIRST    7
-
-/* Message Descriptor bit macros */
-#define MUSYCC_MDT_BASE03_ADDR     0x00006000
-
-/* Channel Config Descriptor bit macros */
-#define MUSYCC_CCD_BUFIRQ_DISABLE  0x00000002   /* BUFF and ONR irqs disabled */
-#define MUSYCC_CCD_EOMIRQ_DISABLE  0x00000004   /* EOM irq disabled */
-#define MUSYCC_CCD_MSGIRQ_DISABLE  0x00000008   /* LNG, FCS, ALIGN, and ABT
-						 * irqs disabled */
-#define MUSYCC_CCD_IDLEIRQ_DISABLE 0x00000010   /* CHABT, CHIC, and SHT irqs
-						 * disabled */
-#define MUSYCC_CCD_FILTIRQ_DISABLE 0x00000020   /* SFILT irq disabled */
-#define MUSYCC_CCD_SDECIRQ_DISABLE 0x00000040   /* SDEC irq disabled */
-#define MUSYCC_CCD_SINCIRQ_DISABLE 0x00000080   /* SINC irq disabled */
-#define MUSYCC_CCD_SUERIRQ_DISABLE 0x00000100   /* SUERR irq disabled */
-#define MUSYCC_CCD_FCS_XFER        0x00000200   /* Propagate FCS along with
-						 * received data */
-#define MUSYCC_CCD_PROTO_SHIFT     12   /* Position index for protocol bit
-					 * field */
-#define MUSYCC_CCD_TRANS           0    /* Protocol mode in bits 12-14 */
-#define MUSYCC_CCD_SS7             1
-#define MUSYCC_CCD_HDLC_FCS16      2
-#define MUSYCC_CCD_HDLC_FCS32      3
-#define MUSYCC_CCD_EOPIRQ_DISABLE  0x00008000   /* EOP irq disabled */
-#define MUSYCC_CCD_INVERT_DATA     0x00800000   /* Invert data */
-#define MUSYCC_CCD_MAX_LENGTH      10   /* Position index for max length bit
-					 * field */
-#define MUSYCC_CCD_BUFFER_LENGTH   16   /* Position index for internal data
-					 * buffer length */
-#define MUSYCC_CCD_BUFFER_LOC      24   /* Position index for internal data
-					 * buffer starting location */
-
-/****************************************************************************
- * Interrupt Descriptor Information */
-
-#define INT_EMPTY_ENTRY     0xfeedface
-#define INT_EMPTY_ENTRY2    0xdeadface
-
-/****************************************************************************
- * Interrupt Status Descriptor
- *
- * NOTE: One must first fetch the value of the interrupt status descriptor
- * into a local variable, then pass that value into the read macros. This
- * is required to avoid race conditions.
- ***/
-
-#define INTRPTS_NEXTINT_M      0x7FFF0000
-#define INTRPTS_NEXTINT_S      16
-#define INTRPTS_NEXTINT(x)     ((x & INTRPTS_NEXTINT_M) >> INTRPTS_NEXTINT_S)
-
-#define INTRPTS_INTFULL_M      0x00008000
-#define INTRPTS_INTFULL_S      15
-#define INTRPTS_INTFULL(x)     ((x & INTRPTS_INTFULL_M) >> INTRPTS_INTFULL_S)
-
-#define INTRPTS_INTCNT_M       0x00007FFF
-#define INTRPTS_INTCNT_S       0
-#define INTRPTS_INTCNT(x)      ((x & INTRPTS_INTCNT_M) >> INTRPTS_INTCNT_S)
-
-
-/****************************************************************************
- * Interrupt Descriptor
- ***/
-
-#define INTRPT_DIR_M           0x80000000
-#define INTRPT_DIR_S           31
-#define INTRPT_DIR(x)          ((x & INTRPT_DIR_M) >> INTRPT_DIR_S)
-
-#define INTRPT_GRP_M           0x60000000
-#define INTRPT_GRP_MSB_M       0x00004000
-#define INTRPT_GRP_S           29
-#define INTRPT_GRP_MSB_S       12
-#define INTRPT_GRP(x)          (((x & INTRPT_GRP_M) >> INTRPT_GRP_S) | \
-			       ((x & INTRPT_GRP_MSB_M) >> INTRPT_GRP_MSB_S))
-
-#define INTRPT_CH_M            0x1F000000
-#define INTRPT_CH_S            24
-#define INTRPT_CH(x)           ((x & INTRPT_CH_M) >> INTRPT_CH_S)
-
-#define INTRPT_EVENT_M         0x00F00000
-#define INTRPT_EVENT_S         20
-#define INTRPT_EVENT(x)        ((x & INTRPT_EVENT_M) >> INTRPT_EVENT_S)
-
-#define INTRPT_ERROR_M         0x000F0000
-#define INTRPT_ERROR_S         16
-#define INTRPT_ERROR(x)        ((x & INTRPT_ERROR_M) >> INTRPT_ERROR_S)
-
-#define INTRPT_ILOST_M         0x00008000
-#define INTRPT_ILOST_S         15
-#define INTRPT_ILOST(x)        ((x & INTRPT_ILOST_M) >> INTRPT_ILOST_S)
-
-#define INTRPT_PERR_M          0x00004000
-#define INTRPT_PERR_S          14
-#define INTRPT_PERR(x)         ((x & INTRPT_PERR_M) >> INTRPT_PERR_S)
-
-#define INTRPT_BLEN_M          0x00003FFF
-#define INTRPT_BLEN_S          0
-#define INTRPT_BLEN(x)         ((x & INTRPT_BLEN_M) >> INTRPT_BLEN_S)
-
-
-/* Buffer Descriptor bit macros */
-#define OWNER_BIT       0x80000000      /* Set for MUSYCC owner on xmit, host
-					 * owner on receive */
-#define HOST_TX_OWNED   0x00000000      /* Host owns descriptor */
-#define MUSYCC_TX_OWNED 0x80000000      /* MUSYCC owns descriptor */
-#define HOST_RX_OWNED   0x80000000      /* Host owns descriptor */
-#define MUSYCC_RX_OWNED 0x00000000      /* MUSYCC owns descriptor */
-
-#define POLL_DISABLED   0x40000000      /* MUSYCC not allowed to poll buffer
-					 * for ownership */
-#define EOMIRQ_ENABLE   0x20000000      /* This buffer contains the end of
-					 * the message */
-#define EOBIRQ_ENABLE   0x10000000      /* EOB irq enabled */
-#define PADFILL_ENABLE  0x01000000      /* Enable padfill */
-#define REPEAT_BIT      0x00008000      /* Bit on for FISU descriptor */
-#define LENGTH_MASK         0X3fff      /* This part of status descriptor is
-					 * length */
-#define IDLE_CODE               25      /* Position index for idle code (2
-					 * bits) */
-#define EXTRA_FLAGS             16      /* Position index for minimum flags
-					 * between messages (8 bits) */
-#define IDLE_CODE_MASK        0x03      /* Gets rid of garbage before the
-					 * pattern is OR'd in */
-#define EXTRA_FLAGS_MASK      0xff      /* Gets rid of garbage before the
-					 * pattern is OR'd in */
-#define PCI_PERMUTED_OWNER_BIT  0x00000080      /* For flipping the bit on
-						 * the polled mode descriptor */
-
-/* Service Request Descriptor bit macros */
-#define SREQ  8                 /* Position index for service request bit
-				 * field */
-#define SR_NOOP                 (0<<(SREQ))     /* No Operation. Generates SACK */
-#define SR_CHIP_RESET           (1<<(SREQ))     /* Soft chip reset */
-#define SR_GROUP_RESET          (2<<(SREQ))     /* Group reset */
-#define SR_GLOBAL_INIT          (4<<(SREQ))     /* Global init: read global
-						 * config deswc and interrupt
-						 * queue desc */
-#define SR_GROUP_INIT           (5<<(SREQ))     /* Group init: read Timeslot
-						 * and Subchannel maps,
-						 * Channel Config, */
-    /*
-     * Group Config, Memory Protect, Message Length, and Port Config
-     * Descriptors
-     */
-#define SR_CHANNEL_ACTIVATE     (8<<(SREQ))     /* Init channel, read Head
-						 * Pointer, process first
-						 * Message Descriptor */
-#define SR_GCHANNEL_MASK        0x001F          /* channel portion (gchan) */
-#define SR_CHANNEL_DEACTIVATE   (9<<(SREQ))     /* Stop channel processing */
-#define SR_JUMP                 (10<<(SREQ))    /* a: Process new Message
-						 * List */
-#define SR_CHANNEL_CONFIG       (11<<(SREQ))    /* b: Read channel
-						 * Configuration Descriptor */
-#define SR_GLOBAL_CONFIG        (16<<(SREQ))    /* 10: Read Global
-						 * Configuration Descriptor */
-#define SR_INTERRUPT_Q          (17<<(SREQ))    /* 11: Read Interrupt Queue
-						 * Descriptor */
-#define SR_GROUP_CONFIG         (18<<(SREQ))    /* 12: Read Group
-						 * Configuration Descriptor */
-#define SR_MEMORY_PROTECT       (19<<(SREQ))    /* 13: Read Memory Protection
-						 * Descriptor */
-#define SR_MESSAGE_LENGTH       (20<<(SREQ))    /* 14: Read Message Length
-						 * Descriptor */
-#define SR_PORT_CONFIG          (21<<(SREQ))    /* 15: Read Port
-						 * Configuration Descriptor */
-#define SR_TIMESLOT_MAP         (24<<(SREQ))    /* 18: Read Timeslot Map */
-#define SR_SUBCHANNEL_MAP       (25<<(SREQ))    /* 19: Read Subchannel Map */
-#define SR_CHAN_CONFIG_TABLE    (26<<(SREQ))    /* 20: Read Channel
-						 * Configuration Table for
-						 * the group */
-#define SR_TX_DIRECTION         0x00000020      /* Transmit direction bit.
-						 * Bit off indicates receive
-						 * direction */
-#define SR_RX_DIRECTION         0x00000000
-
-/* Interrupt Descriptor bit macros */
-#define GROUP10                     29  /* Position index for the 2 LS group
-					 * bits */
-#define CHANNEL                     24  /* Position index for channel bits */
-#define INT_IQD_TX          0x80000000
-#define INT_IQD_GRP         0x60000000
-#define INT_IQD_CHAN        0x1f000000
-#define INT_IQD_EVENT       0x00f00000
-#define INT_IQD_ERROR       0x000f0000
-#define INT_IQD_ILOST       0x00008000
-#define INT_IQD_PERR        0x00004000
-#define INT_IQD_BLEN        0x00003fff
-
-/* Interrupt Descriptor Events */
-#define EVE_EVENT               20      /* Position index for event bits */
-#define EVE_NONE                0       /* No event to report in this
-					 * interrupt */
-#define EVE_SACK                1       /* Service Request acknowledge */
-#define EVE_EOB                 2       /* End of Buffer */
-#define EVE_EOM                 3       /* End of Message */
-#define EVE_EOP                 4       /* End of Padfill */
-#define EVE_CHABT               5       /* Change to Abort Code */
-#define EVE_CHIC                6       /* Change to Idle Code */
-#define EVE_FREC                7       /* Frame Recovery */
-#define EVE_SINC                8       /* MTP2 SUERM Increment */
-#define EVE_SDEC                9       /* MTP2 SUERM Decrement */
-#define EVE_SFILT               10      /* MTP2 SUERM Filtered Message */
-/* Interrupt Descriptor Errors */
-#define ERR_ERRORS              16      /* Position index for error bits */
-#define ERR_BUF                 1       /* Buffer Error */
-#define ERR_COFA                2       /* Change of Frame Alignment Error */
-#define ERR_ONR                 3       /* Owner Bit Error */
-#define ERR_PROT                4       /* Memory Protection Error */
-#define ERR_OOF                 8       /* Out of Frame Error */
-#define ERR_FCS                 9       /* FCS Error */
-#define ERR_ALIGN               10      /* Octet Alignment Error */
-#define ERR_ABT                 11      /* Abort Termination */
-#define ERR_LNG                 12      /* Long Message Error */
-#define ERR_SHT                 13      /* Short Message Error */
-#define ERR_SUERR               14      /* SUERM threshold exceeded */
-#define ERR_PERR                15      /* PCI Parity Error */
-/* Other Stuff */
-#define TRANSMIT_DIRECTION  0x80000000  /* Transmit direction bit. Bit off
-					 * indicates receive direction */
-#define ILOST               0x00008000  /* Interrupt Lost */
-#define GROUPMSB            0x00004000  /* Group number MSB */
-#define SACK_IMAGE          0x00100000  /* Used in IRQ for semaphore test */
-#define INITIAL_STATUS      0x10000     /* IRQ status should be this after
-					 * reset */
-
-/*  This must be defined on an entire channel group (Port) basis */
-#define SUERM_THRESHOLD     0x1f
-
-#undef VINT32
-#undef VINT8
-
-#endif                          /*** _INC_MUSYCC_H_ ***/
-
-/*** End-of-File ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,532 +0,0 @@
-/* pmc93x6_eeprom.c - PMC's 93LC46 EEPROM Device
- *
- *    The 93LC46 is a low-power, serial Electrically Erasable and
- *    Programmable Read Only Memory organized as 128 8-bit bytes.
- *
- *    Accesses to the 93LC46 are done in a bit serial stream, organized
- *    in a 3 wire format.  Writes are internally timed by the device
- *    (the In data bit is pulled low until the write is complete and
- *    then is pulled high) and take about 6 milliseconds.
- *
- * Copyright (C) 2003-2005  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "pmcc4.h"
-#include "sbe_promformat.h"
-#include "pmc93x6_eeprom.h"
-
-#ifndef TRUE
-#define TRUE   1
-#define FALSE  0
-#endif
-
-/*------------------------------------------------------------------------
- *      EEPROM address definitions
- *------------------------------------------------------------------------
- *
- *      The offset in the definitions below allows the test to skip over
- *      areas of the EEPROM that other programs (such a VxWorks) are
- *      using.
- */
-
-#define EE_MFG      (long)0	/* Index to manufacturing record */
-#define EE_FIRST    0x28	/* Index to start testing at */
-#define EE_LIMIT    128		/* Index to end testing at */
-
-/*  Bit Ordering for Instructions
- *
- *  A0, A1, A2, A3, A4, A5, A6, OP0, OP1, SB   (lsb, or 1st bit out)
- *
- */
-
-#define EPROM_EWEN      0x0019	/* Erase/Write enable (reversed) */
-#define EPROM_EWDS      0x0001	/* Erase/Write disable (reversed) */
-#define EPROM_READ      0x0003	/* Read (reversed) */
-#define EPROM_WRITE     0x0005	/* Write (reversed) */
-#define EPROM_ERASE     0x0007	/* Erase (reversed) */
-#define EPROM_ERAL      0x0009	/* Erase All (reversed) */
-#define EPROM_WRAL      0x0011	/* Write All (reversed) */
-
-#define EPROM_ADR_SZ    7	/* Number of bits in offset address */
-#define EPROM_OP_SZ     3	/* Number of bits in command */
-#define SIZE_ADDR_OP    (EPROM_ADR_SZ + EPROM_OP_SZ)
-#define LC46A_MAX_OPS   10	/* Number of bits in Instruction */
-#define NUM_OF_BITS     8	/* Number of bits in data */
-
-/* EEPROM signal bits */
-#define EPROM_ACTIVE_OUT_BIT    0x0001	/* Out data bit */
-#define EPROM_ACTIVE_IN_BIT     0x0002	/* In data bit */
-#define ACTIVE_IN_BIT_SHIFT     0x0001	/* Shift In data bit to LSB */
-#define EPROM_ENCS              0x0004	/* Set EEPROM CS during operation */
-
-/*------------------------------------------------------------------------
- *      The ByteReverse table is used to reverses the 8 bits within a byte
- *------------------------------------------------------------------------
- */
-
-static unsigned char ByteReverse[256];
-static int ByteReverseBuilt = FALSE;
-
-/*------------------------------------------------------------------------
- *      mfg_template - initial serial EEPROM data structure
- *------------------------------------------------------------------------
- */
-
-static u8 mfg_template[sizeof(FLD_TYPE2)] = {
-	PROM_FORMAT_TYPE2,	/* type; */
-	0x00, 0x1A,		/* length[2]; */
-	0x00, 0x00, 0x00, 0x00,	/* Crc32[4]; */
-	0x11, 0x76,		/* Id[2]; */
-	0x07, 0x05,		/* SubId[2] E1; */
-	0x00, 0xA0, 0xD6, 0x00, 0x00, 0x00,	/* Serial[6]; */
-	0x00, 0x00, 0x00, 0x00,	/* CreateTime[4]; */
-	0x00, 0x00, 0x00, 0x00,	/* HeatRunTime[4]; */
-	0x00, 0x00, 0x00, 0x00,	/* HeatRunIterations[4]; */
-	0x00, 0x00, 0x00, 0x00,	/* HeatRunErrors[4]; */
-};
-
-/*------------------------------------------------------------------------
- *      BuildByteReverse - build the 8-bit reverse table
- *------------------------------------------------------------------------
- *
- *      The 'ByteReverse' table reverses the 8 bits within a byte
- *      (the MSB becomes the LSB etc.).
- */
-
-static void BuildByteReverse(void)
-{
-	/* Used to build by powers to 2 */
-	long half;
-	int i;
-
-	ByteReverse[0] = 0;
-
-	for (half = 1; half < sizeof(ByteReverse); half <<= 1)
-		for (i = 0; i < half; i++)
-			ByteReverse[half + i] =
-			    (char)(ByteReverse[i] | (0x80 / half));
-
-	ByteReverseBuilt = TRUE;
-}
-
-/*------------------------------------------------------------------------
- *      eeprom_delay - small delay for EEPROM timing
- *------------------------------------------------------------------------
- */
-
-static void eeprom_delay(void)
-{
-	int timeout;
-
-	for (timeout = 20; timeout; --timeout)
-		OS_uwait_dummy();
-}
-
-/*------------------------------------------------------------------------
- *      eeprom_put_byte - Send a byte to the EEPROM serially
- *------------------------------------------------------------------------
- *
- *      Given the PCI address and the data, this routine serially sends
- *      the data to the EEPROM.
- */
-
-static void eeprom_put_byte(long addr, long data, int count)
-{
-	u_int32_t output;
-
-	while (--count >= 0) {
-		/* Get next data bit */
-		output = (data & EPROM_ACTIVE_OUT_BIT) ? 1 : 0;
-		/* Add Chip Select */
-		output |= EPROM_ENCS;
-		data >>= 1;
-
-		eeprom_delay();
-		/* Output it */
-		pci_write_32((u_int32_t *) addr, output);
-	}
-}
-
-/*------------------------------------------------------------------------
- *      eeprom_get_byte - Receive a byte from the EEPROM serially
- *------------------------------------------------------------------------
- *
- *      Given the PCI address, this routine serially fetches the data
- *      from the  EEPROM.
- */
-
-static u_int32_t eeprom_get_byte(long addr)
-{
-	u_int32_t input;
-	u_int32_t data;
-	int count;
-
-/*  Start the Reading of DATA
- *
- *  The first read is a dummy as the data is latched in the
- *  EPLD and read on the next read access to the EEPROM.
- */
-
-	input = pci_read_32((u_int32_t *) addr);
-
-	data = 0;
-	count = NUM_OF_BITS;
-	while (--count >= 0) {
-		eeprom_delay();
-		input = pci_read_32((u_int32_t *) addr);
-
-		/* Shift data over */
-		data <<= 1;
-		data |= (input & EPROM_ACTIVE_IN_BIT) ? 1 : 0;
-
-	}
-
-	return data;
-}
-
-/*------------------------------------------------------------------------
- *      disable_pmc_eeprom - Disable writes to the EEPROM
- *------------------------------------------------------------------------
- *
- *      Issue the EEPROM command to disable writes.
- */
-
-static void disable_pmc_eeprom(long addr)
-{
-	eeprom_put_byte(addr, EPROM_EWDS, SIZE_ADDR_OP);
-
-	/* this removes Chip Select from EEPROM */
-	pci_write_32((u_int32_t *) addr, 0);
-}
-
-/*------------------------------------------------------------------------
- *      enable_pmc_eeprom - Enable writes to the EEPROM
- *------------------------------------------------------------------------
- *
- *      Issue the EEPROM command to enable writes.
- */
-
-static void enable_pmc_eeprom(long addr)
-{
-	eeprom_put_byte(addr, EPROM_EWEN, SIZE_ADDR_OP);
-
-	/* this removes Chip Select from EEPROM */
-	pci_write_32((u_int32_t *) addr, 0);
-}
-
-/*------------------------------------------------------------------------
- *      pmc_eeprom_read - EEPROM location read
- *------------------------------------------------------------------------
- *
- *      Given a EEPROM PCI address and location offset, this routine returns
- *      the contents of the specified location to the calling routine.
- */
-
-static u_int32_t pmc_eeprom_read(long addr, long mem_offset)
-{
-	/* Data from chip */
-	u_int32_t data;
-
-	if (!ByteReverseBuilt)
-		BuildByteReverse();
-
-	/* Reverse address */
-	mem_offset = ByteReverse[0x7F & mem_offset];
-
-	/*
-	 * NOTE: The max offset address is 128 or half the reversal table. So
-	 * the LSB is always zero and counts as a built in shift of one bit.
-	 * So even though we need to shift 3 bits to make room for the command,
-	 * we only need to shift twice more because of the built in shift.
-	 */
-
-	/* Shift for command */
-	mem_offset <<= 2;
-	/* Add command */
-	mem_offset |= EPROM_READ;
-
-	/* Output chip address */
-	eeprom_put_byte(addr, mem_offset, SIZE_ADDR_OP);
-
-	/* Read chip data */
-	data = eeprom_get_byte(addr);
-
-	/* Remove Chip Select from EEPROM */
-	pci_write_32((u_int32_t *) addr, 0);
-
-	return (data & 0x000000FF);
-}
-
-/*------------------------------------------------------------------------
- *      pmc_eeprom_write - EEPROM location write
- *------------------------------------------------------------------------
- *
- *      Given a EEPROM PCI address, location offset and value, this
- *      routine writes the value to the specified location.
- *
- *      Note: it is up to the caller to determine if the write
- *      operation succeeded.
- */
-
-static int pmc_eeprom_write(long addr, long mem_offset, u_int32_t data)
-{
-	u_int32_t temp;
-	int count;
-
-	if (!ByteReverseBuilt)
-		BuildByteReverse();
-
-	/* Reverse address */
-	mem_offset = ByteReverse[0x7F & mem_offset];
-
-	/*
-	 * NOTE: The max offset address is 128 or half the reversal table. So
-	 * the LSB is always zero and counts as a built in shift of one bit.
-	 * So even though we need to shift 3 bits to make room for the command,
-	 * we only need to shift twice more because of the built in shift.
-	 */
-
-	/* Shift for command */
-	mem_offset <<= 2;
-	/* Add command */
-	mem_offset |= EPROM_WRITE;
-
-	/* Output chip address */
-	eeprom_put_byte(addr, mem_offset, SIZE_ADDR_OP);
-
-	/* Reverse data */
-	data = ByteReverse[0xFF & data];
-	/* Output chip data */
-	eeprom_put_byte(addr, data, NUM_OF_BITS);
-
-	/* Remove Chip Select from EEPROM */
-	pci_write_32((u_int32_t *) addr, 0);
-
-/*
- *  Must see Data In at a low state before completing this transaction.
- *
- *  Afterwards, the data bit will return to a high state, ~6 ms, terminating
- *  the operation.
- */
-	/* Re-enable Chip Select */
-	pci_write_32((u_int32_t *) addr, EPROM_ENCS);
-	/* discard first read */
-	temp = pci_read_32((u_int32_t *) addr);
-	temp = pci_read_32((u_int32_t *) addr);
-	if (temp & EPROM_ACTIVE_IN_BIT) {
-		temp = pci_read_32((u_int32_t *) addr);
-		if (temp & EPROM_ACTIVE_IN_BIT) {
-			/* Remove Chip Select from EEPROM */
-			pci_write_32((u_int32_t *) addr, 0);
-			return 1;
-		}
-	}
-	count = 1000;
-	while (count--) {
-		for (temp = 0; temp < 0x10; temp++)
-			OS_uwait_dummy();
-
-		if (pci_read_32((u_int32_t *) addr) & EPROM_ACTIVE_IN_BIT)
-			break;
-	}
-
-	if (count == -1)
-		return 2;
-
-	return 0;
-}
-
-/*------------------------------------------------------------------------
- *      pmcGetBuffValue - read the specified value from buffer
- *------------------------------------------------------------------------
- */
-
-static long pmcGetBuffValue(char *ptr, int size)
-{
-	long value = 0;
-	int index;
-
-	for (index = 0; index < size; ++index) {
-		value <<= 8;
-		value |= ptr[index] & 0xFF;
-	}
-
-	return value;
-}
-
-/*------------------------------------------------------------------------
- *      pmcSetBuffValue - save the specified value to buffer
- *------------------------------------------------------------------------
- */
-
-static void pmcSetBuffValue(char *ptr, long value, int size)
-{
-	int index = size;
-
-	while (--index >= 0) {
-		ptr[index] = (char)(value & 0xFF);
-		value >>= 8;
-	}
-}
-
-/*------------------------------------------------------------------------
- *      pmc_eeprom_read_buffer - read EEPROM data into specified buffer
- *------------------------------------------------------------------------
- */
-
-void
-pmc_eeprom_read_buffer(long addr, long mem_offset, char *dest_ptr, int size)
-{
-	while (--size >= 0)
-		*dest_ptr++ = (char)pmc_eeprom_read(addr, mem_offset++);
-}
-
-/*------------------------------------------------------------------------
- *      pmc_eeprom_write_buffer - write EEPROM data from specified buffer
- *------------------------------------------------------------------------
- */
-
-void
-pmc_eeprom_write_buffer(long addr, long mem_offset, char *dest_ptr, int size)
-{
-	enable_pmc_eeprom(addr);
-
-	while (--size >= 0)
-		pmc_eeprom_write(addr, mem_offset++, *dest_ptr++);
-
-	disable_pmc_eeprom(addr);
-}
-
-/*------------------------------------------------------------------------
- *      pmcCalcCrc - calculate the CRC for the serial EEPROM structure
- *------------------------------------------------------------------------
- */
-
-static u_int32_t pmcCalcCrc_T01(void *bufp)
-{
-	FLD_TYPE2 *buf = bufp;
-	/* CRC of the structure */
-	u_int32_t crc;
-
-	/* Calc CRC for type and length fields */
-	sbeCrc((u_int8_t *) &buf->type,
-	       (u_int32_t) STRUCT_OFFSET(FLD_TYPE1, Crc32),
-	       (u_int32_t) 0, (u_int32_t *) &crc);
-
-#ifdef EEPROM_TYPE_DEBUG
-	/* RLD DEBUG */
-	pr_info("sbeCrc: crc 1 calculated as %08x\n", crc);
-#endif
-	return ~crc;
-}
-
-static u_int32_t pmcCalcCrc_T02(void *bufp)
-{
-	FLD_TYPE2 *buf = bufp;
-	/* CRC of the structure */
-	u_int32_t crc;
-
-	/* Calc CRC for type and length fields */
-	sbeCrc((u_int8_t *) &buf->type,
-	       (u_int32_t) STRUCT_OFFSET(FLD_TYPE2, Crc32),
-	       (u_int32_t) 0, (u_int32_t *) &crc);
-
-	/* Calc CRC for remaining fields */
-	sbeCrc((u_int8_t *) &buf->Id[0],
-	       (u_int32_t) (sizeof(FLD_TYPE2) - STRUCT_OFFSET(FLD_TYPE2, Id)),
-	       (u_int32_t) crc, (u_int32_t *) &crc);
-
-#ifdef EEPROM_TYPE_DEBUG
-	/* RLD DEBUG */
-	pr_info("sbeCrc: crc 2 calculated as %08x\n", crc);
-#endif
-	return crc;
-}
-
-/*------------------------------------------------------------------------
- *      pmc_init_seeprom - initialize the serial EEPROM structure
- *------------------------------------------------------------------------
- *
- *      At the front of the serial EEPROM there is a record that contains
- *      manufacturing information.  If the info does not already exist, it
- *      is created.  The only field modifiable by the operator is the
- *      serial number field.
- */
-
-void pmc_init_seeprom(u_int32_t addr, u_int32_t serialNum)
-{
-	/* Memory image of structure */
-	PROMFORMAT buffer;
-	/* CRC of structure */
-	u_int32_t crc;
-	time_t createTime;
-
-	createTime = get_seconds();
-
-	/* use template data */
-	memcpy(&buffer.fldType2, mfg_template, sizeof(buffer.fldType2));
-
-	/* Update serial number field in buffer */
-	pmcSetBuffValue(&buffer.fldType2.Serial[3], serialNum, 3);
-
-	/* Update create time field in buffer */
-	pmcSetBuffValue(&buffer.fldType2.CreateTime[0], createTime, 4);
-
-	/* Update CRC field in buffer */
-	crc = pmcCalcCrc_T02(&buffer);
-	pmcSetBuffValue(&buffer.fldType2.Crc32[0], crc, 4);
-
-#ifdef DEBUG
-	for (i = 0; i < sizeof(FLD_TYPE2); ++i)
-		pr_info("[%02X] = %02X\n", i, buffer.bytes[i] & 0xFF);
-#endif
-
-	/* Write structure to serial EEPROM */
-	pmc_eeprom_write_buffer(addr, EE_MFG, (char *)&buffer,
-				sizeof(FLD_TYPE2));
-}
-
-char pmc_verify_cksum(void *bufp)
-{
-	FLD_TYPE1 *buf1 = bufp;
-	FLD_TYPE2 *buf2 = bufp;
-	/* CRC read from EEPROM */
-	u_int32_t crc1, crc2;
-
-	/* Retrieve contents of CRC field */
-	crc1 = pmcGetBuffValue(&buf1->Crc32[0], sizeof(buf1->Crc32));
-#ifdef EEPROM_TYPE_DEBUG
-	/* RLD DEBUG */
-	pr_info("EEPROM: chksum 1 reads   as %08x\n", crc1);
-#endif
-	if ((buf1->type == PROM_FORMAT_TYPE1) &&
-	    (pmcCalcCrc_T01((void *)buf1) == crc1))
-		return PROM_FORMAT_TYPE1;	/* checksum type 1 verified */
-
-	crc2 = pmcGetBuffValue(&buf2->Crc32[0], sizeof(buf2->Crc32));
-#ifdef EEPROM_TYPE_DEBUG
-	/* RLD DEBUG */
-	pr_info("EEPROM: chksum 2 reads   as %08x\n", crc2);
-#endif
-	if ((buf2->type == PROM_FORMAT_TYPE2) &&
-	    (pmcCalcCrc_T02((void *)buf2) == crc2))
-		return PROM_FORMAT_TYPE2;	/* checksum type 2 verified */
-
-	/* failed to validate */
-	return PROM_FORMAT_Unk;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmc93x6_eeprom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-#ifndef _INC_PMC93X6_EEPROM_H_
-#define _INC_PMC93X6_EEPROM_H_
-
-/*-----------------------------------------------------------------------------
- * pmc93x6_eeprom.h -
- *
- * Copyright (C) 2002-2004  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-
-#ifdef __KERNEL__
-
-#include "pmcc4_private.h"
-
-void        pmc_eeprom_read_buffer (long, long, char *, int);
-void        pmc_eeprom_write_buffer (long, long, char *, int);
-void        pmc_init_seeprom (u_int32_t, u_int32_t);
-char        pmc_verify_cksum (void *);
-
-#endif    /*** __KERNEL__ ***/
-
-#endif
-
-/*** End-of-File ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_cpld.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_cpld.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_cpld.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_cpld.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-#ifndef _INC_PMCC4_CPLD_H_
-#define _INC_PMCC4_CPLD_H_
-
-/*-----------------------------------------------------------------------------
- * pmcc4_cpld.h -
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-
-/********************************/
-/* iSPLD control chip registers */
-/********************************/
-
-#if 0
-#define CPLD_MCSR    0x0
-#define CPLD_MCLK    0x1
-#define CPLD_LEDS    0x2
-#define CPLD_INTR    0x3
-#endif
-
-    struct c4_cpld
-    {
-        volatile u_int32_t mcsr;/* r/w: Master Clock Source Register */
-        volatile u_int32_t mclk;/* r/w: Master Clock Register */
-        volatile u_int32_t leds;/* r/w: LED Register */
-        volatile u_int32_t intr;/* r: Interrupt Register */
-    };
-
-    typedef struct c4_cpld c4cpld_t;
-
-/* mcsr note: sourcing COMET must be initialized to Master Mode */
-#define PMCC4_CPLD_MCSR_IND     0       /* ports used individual BP Clk as
-                                         * source, no slaves */
-#define PMCC4_CPLD_MCSR_CMT_1   1       /* COMET 1 BP Clk is source, 2,3,4
-                                         * are Clk slaves */
-#define PMCC4_CPLD_MCSR_CMT_2   2       /* COMET 2 BP Clk is source, 1,3,4
-                                         * are Clk slaves */
-#define PMCC4_CPLD_MCSR_CMT_3   3       /* COMET 3 BP Clk is source, 1,2,4
-                                         * are Clk slaves */
-#define PMCC4_CPLD_MCSR_CMT_4   4       /* COMET 4 BP Clk is source, 1,2,3
-                                         * are Clk slaves */
-
-#define PMCC4_CPLD_MCLK_MASK    0x0f
-#define PMCC4_CPLD_MCLK_P1      0x1
-#define PMCC4_CPLD_MCLK_P2      0x2
-#define PMCC4_CPLD_MCLK_P3      0x4
-#define PMCC4_CPLD_MCLK_P4      0x8
-#define PMCC4_CPLD_MCLK_T1      0x00
-#define PMCC4_CPLD_MCLK_P1_E1   0x01
-#define PMCC4_CPLD_MCLK_P2_E1   0x02
-#define PMCC4_CPLD_MCLK_P3_E1   0x04
-#define PMCC4_CPLD_MCLK_P4_E1   0x08
-
-#define PMCC4_CPLD_LED_OFF      0
-#define PMCC4_CPLD_LED_ON       1
-#define PMCC4_CPLD_LED_GP0      0x01    /* port 0, green  */
-#define PMCC4_CPLD_LED_YP0      0x02    /* port 0, yellow */
-#define PMCC4_CPLD_LED_GP1      0x04    /* port 1, green  */
-#define PMCC4_CPLD_LED_YP1      0x08    /* port 1, yellow */
-#define PMCC4_CPLD_LED_GP2      0x10    /* port 2, green  */
-#define PMCC4_CPLD_LED_YP2      0x20    /* port 2, yellow */
-#define PMCC4_CPLD_LED_GP3      0x40    /* port 3, green  */
-#define PMCC4_CPLD_LED_YP3      0x80    /* port 3, yellow */
-#define PMCC4_CPLD_LED_GREEN   (PMCC4_CPLD_LED_GP0 | PMCC4_CPLD_LED_GP1 | \
-                                PMCC4_CPLD_LED_GP2 | PMCC4_CPLD_LED_GP3 )
-#define PMCC4_CPLD_LED_YELLOW  (PMCC4_CPLD_LED_YP0 | PMCC4_CPLD_LED_YP1 | \
-                                PMCC4_CPLD_LED_YP2 | PMCC4_CPLD_LED_YP3)
-
-#define PMCC4_CPLD_INTR_MASK    0x0f
-#define PMCC4_CPLD_INTR_CMT_1   0x01
-#define PMCC4_CPLD_INTR_CMT_2   0x02
-#define PMCC4_CPLD_INTR_CMT_3   0x04
-#define PMCC4_CPLD_INTR_CMT_4   0x08
-
-#endif                          /* _INC_PMCC4_CPLD_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_defs.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_defs.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_defs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-#ifndef _INC_PMCC4_DEFS_H_
-#define _INC_PMCC4_DEFS_H_
-
-/*-----------------------------------------------------------------------------
- * c4_defs.h -
- *
- *   Implementation elements of the wanPMC-C4T1E1 device driver
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-
-#define MAX_BOARDS          8
-#define MAX_CHANS_USED      128
-
-#ifdef  SBE_PMCC4_ENABLE
-#define MUSYCC_NPORTS       4     /* CN8474 */
-#endif
-#ifdef SBE_WAN256T3_ENABLE
-#define MUSYCC_NPORTS       8     /* CN8478 */
-#endif
-#define MUSYCC_NCHANS       32    /* actually, chans per port */
-
-#define MUSYCC_NIQD         0x1000    /* power of 2 */
-#define MUSYCC_MRU          2048  /* default */
-#define MUSYCC_MTU          2048  /* default */
-#define MUSYCC_TXDESC_MIN   10    /* HDLC mode default */
-#define MUSYCC_RXDESC_MIN   18    /* HDLC mode default */
-#define MUSYCC_TXDESC_TRANS 4     /* Transparent mode minimum # of TX descriptors */
-#define MUSYCC_RXDESC_TRANS 12    /* Transparent mode minimum # of RX descriptors */
-
-#define MAX_DEFAULT_IFQLEN  32    /* network qlen */
-
-
-#define SBE_IFACETMPL        "pmcc4-%d"
-#ifdef IFNAMSIZ
-#define SBE_IFACETMPL_SIZE    IFNAMSIZ
-#else
-#define SBE_IFACETMPL_SIZE    16
-#endif
-
-/* we want the PMCC4 watchdog to fire off every 250ms */
-#define WATCHDOG_TIMEOUT      250000
-
-/* if we restart the watchdog every 250ms, then we'll time out
- * an additional 300ms later */
-#define WATCHDOG_UTIMEOUT     (WATCHDOG_TIMEOUT+300000)
-
-#if !defined(SBE_ISR_TASKLET) && !defined(SBE_ISR_IMMEDIATE) && !defined(SBE_ISR_INLINE)
-#define SBE_ISR_TASKLET
-#endif
-
-#endif   /*** _INC_PMCC4_DEFS_H_ ***/
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_drv.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_drv.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_drv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_drv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1613 +0,0 @@
-/*-----------------------------------------------------------------------------
- * pmcc4_drv.c -
- *
- * Copyright (C) 2007  One Stop Systems, Inc.
- * Copyright (C) 2002-2006  SBE, 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.
- *
- * For further information, contact via email: support@onestopsystems.com
- * One Stop Systems, Inc.  Escondido, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include "pmcc4_sysdep.h"
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>        /* include for timer */
-#include <linux/timer.h>        /* include for timer */
-#include <linux/hdlc.h>
-#include <linux/io.h>
-
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4_private.h"
-#include "pmcc4.h"
-#include "pmcc4_ioctls.h"
-#include "musycc.h"
-#include "comet.h"
-#include "sbe_bid.h"
-
-#define KERN_WARN KERN_WARNING
-
-/* forward references */
-status_t    c4_wk_chan_init (mpi_t *, mch_t *);
-void        c4_wq_port_cleanup (mpi_t *);
-status_t    c4_wq_port_init (mpi_t *);
-
-int         c4_loop_port (ci_t *, int, u_int8_t);
-status_t    c4_set_port (ci_t *, int);
-status_t    musycc_chan_down (ci_t *, int);
-
-u_int32_t musycc_chan_proto (int);
-status_t    musycc_dump_ring (ci_t *, unsigned int);
-status_t __init musycc_init (ci_t *);
-void        musycc_init_mdt (mpi_t *);
-void        musycc_serv_req (mpi_t *, u_int32_t);
-void        musycc_update_timeslots (mpi_t *);
-
-extern void musycc_update_tx_thp (mch_t *);
-extern int  cxt1e1_log_level;
-extern int  cxt1e1_max_mru;
-extern int  cxt1e1_max_mtu;
-extern int  max_rxdesc_used, max_rxdesc_default;
-extern int  max_txdesc_used, max_txdesc_default;
-
-#if defined (__powerpc__)
-extern void *memset (void *s, int c, size_t n);
-
-#endif
-
-int         drvr_state = SBE_DRVR_INIT;
-ci_t       *c4_list = NULL;
-ci_t       *CI;                 /* dummy pointer to board ZEROE's data -
-                                 * DEBUG USAGE */
-
-
-void
-sbecom_set_loglevel (int d)
-{
-    /*
-     * The code within the following -if- clause is a backdoor debug facility
-     * which can be used to display the state of a board's channel.
-     */
-    if (d > LOG_DEBUG)
-    {
-        unsigned int channum = d - (LOG_DEBUG + 1);     /* convert to ZERO
-                                                         * relativity */
-
-        (void) musycc_dump_ring ((ci_t *) CI, channum); /* CI implies support
-                                                         * for card 0 only */
-    } else
-    {
-        if (cxt1e1_log_level != d)
-        {
-            pr_info("log level changed from %d to %d\n", cxt1e1_log_level, d);
-            cxt1e1_log_level = d;          /* set new */
-        } else
-            pr_info("log level is %d\n", cxt1e1_log_level);
-    }
-}
-
-
-mch_t      *
-c4_find_chan (int channum)
-{
-    ci_t       *ci;
-    mch_t      *ch;
-    int         portnum, gchan;
-
-    for (ci = c4_list; ci; ci = ci->next)
-        for (portnum = 0; portnum < ci->max_port; portnum++)
-            for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
-            {
-		ch = ci->port[portnum].chan[gchan];
-		if (ch) {
-			if ((ch->state != UNASSIGNED) &&
-			   (ch->channum == channum))
-				return ch;
-		}
-            }
-    return NULL;
-}
-
-/***
- * Check port state and set LED states using watchdog or ioctl...
- * also check for in-band SF loopback commands (& cause results if they are there)
- *
- * Alarm function depends on comet bits indicating change in
- * link status (linkMask) to keep the link status indication straight.
- *
- * Indications are only LED and system log -- except when ioctl is invoked.
- *
- * "alarmed" record (a.k.a. copyVal, in some cases below) decodes as:
- *
- *   RMAI  (E1 only) 0x100
- *   alarm LED on    0x80
- *   link LED on     0x40
- *   link returned   0x20 (link was down, now it's back and 'port get' hasn't run)
- *   change in LED   0x10 (update LED register because value has changed)
- *   link is down    0x08
- *   YelAlm(RAI)     0x04
- *   RedAlm          0x02
- *   AIS(blue)Alm    0x01
- *
- * note "link has returned" indication is reset on read
- * (e.g. by use of the c4_control port get command)
- */
-
-#define sbeLinkMask       0x41  /* change in signal status (lost/recovered) +
-                                 * state */
-#define sbeLinkChange     0x40
-#define sbeLinkDown       0x01
-#define sbeAlarmsMask     0x07  /* red / yellow / blue alarm conditions */
-#define sbeE1AlarmsMask   0x107 /* alarm conditions */
-
-#define COMET_LBCMD_READ  0x80  /* read only (do not set, return read value) */
-
-void
-checkPorts (ci_t *ci)
-{
-#ifndef CONFIG_SBE_PMCC4_NCOMM
-    /*
-     * PORT POINT - NCOMM needs to avoid this code since the polling of
-     * alarms conflicts with NCOMM's interrupt servicing implementation.
-     */
-
-    struct s_comet_reg    *comet;
-    volatile u_int32_t value;
-    u_int32_t   copyVal, LEDval;
-
-    u_int8_t portnum;
-
-    LEDval = 0;
-    for (portnum = 0; portnum < ci->max_port; portnum++)
-    {
-        copyVal = 0x12f & (ci->alarmed[portnum]);       /* port's alarm record */
-        comet = ci->port[portnum].cometbase;
-        value = pci_read_32 ((u_int32_t *) &comet->cdrc_ists) & sbeLinkMask;    /* link loss reg */
-
-        if (value & sbeLinkChange)  /* is there a change in the link stuff */
-        {
-            /* if there's been a change (above) and yet it's the same (below) */
-            if (!(((copyVal >> 3) & sbeLinkDown) ^ (value & sbeLinkDown)))
-            {
-                if (value & sbeLinkDown)
-                    pr_warning("%s: Port %d momentarily recovered.\n",
-                               ci->devname, portnum);
-                else
-                    pr_warning("%s: Warning: Port %d link was briefly down.\n",
-                               ci->devname, portnum);
-            } else if (value & sbeLinkDown)
-                pr_warning("%s: Warning: Port %d link is down.\n",
-                           ci->devname, portnum);
-            else
-            {
-                pr_warning("%s: Port %d link has recovered.\n",
-                           ci->devname, portnum);
-                copyVal |= 0x20;    /* record link transition to up */
-            }
-            copyVal |= 0x10;        /* change (link) --> update LEDs  */
-        }
-        copyVal &= 0x137;           /* clear LED & link old history bits &
-                                     * save others */
-        if (value & sbeLinkDown)
-            copyVal |= 0x08;        /* record link status (now) */
-        else
-        {                           /* if link is up, do this */
-            copyVal |= 0x40;        /* LED indicate link is up    */
-            /* Alarm things & the like ... first if E1, then if T1 */
-            if (IS_FRAME_ANY_E1 (ci->port[portnum].p.port_mode))
-            {
-                /*
-                 * first check Codeword (SaX) changes & CRC and
-                 * sub-multi-frame errors
-                 */
-                /*
-                 * note these errors are printed every time they are detected
-                 * vs. alarms
-                 */
-                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_nat_ists);   /* codeword */
-                if (value & 0x1f)
-                {                   /* if errors (crc or smf only) */
-                    if (value & 0x10)
-                        pr_warning("%s: E1 Port %d Codeword Sa4 change detected.\n",
-                                   ci->devname, portnum);
-                    if (value & 0x08)
-                        pr_warning("%s: E1 Port %d Codeword Sa5 change detected.\n",
-                                   ci->devname, portnum);
-                    if (value & 0x04)
-                        pr_warning("%s: E1 Port %d Codeword Sa6 change detected.\n",
-                                   ci->devname, portnum);
-                    if (value & 0x02)
-                        pr_warning("%s: E1 Port %d Codeword Sa7 change detected.\n",
-                                   ci->devname, portnum);
-                    if (value & 0x01)
-                        pr_warning("%s: E1 Port %d Codeword Sa8 change detected.\n",
-                                   ci->devname, portnum);
-                }
-                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_mists);      /* crc & smf */
-                if (value & 0x3)
-                {                   /* if errors (crc or smf only) */
-                    if (value & sbeE1CRC)
-                        pr_warning("%s: E1 Port %d CRC-4 error(s) detected.\n",
-                                   ci->devname, portnum);
-                    if (value & sbeE1errSMF)    /* error in sub-multiframe */
-                        pr_warning("%s: E1 Port %d received errored SMF.\n",
-                                   ci->devname, portnum);
-                }
-                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_masts) & 0xcc; /* alarms */
-                /*
-                 * pack alarms together (bitmiser), and construct similar to
-                 * T1
-                 */
-                /* RAI,RMAI,.,.,LOF,AIS,.,. ==>  RMAI,.,.,.,.,.,RAI,LOF,AIS */
-                /* see 0x97 */
-                value = (value >> 2);
-                if (value & 0x30)
-                {
-                    if (value & 0x20)
-                        value |= 0x40;  /* RAI */
-                    if (value & 0x10)
-                        value |= 0x100; /* RMAI */
-                    value &= ~0x30;
-                }                   /* finished packing alarm in handy order */
-                if (value != (copyVal & sbeE1AlarmsMask))
-                {                   /* if alarms changed */
-                    copyVal |= 0x10;/* change LED status   */
-                    if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
-                    {
-                        copyVal &= ~sbeRedAlm;
-                        pr_warning("%s: E1 Port %d LOF alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
-                    {
-                        copyVal |= sbeRedAlm;
-                        pr_warning("%s: E1 Warning: Port %d LOF alarm.\n",
-                                   ci->devname, portnum);
-                    } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
-                    {
-                        copyVal &= ~sbeYelAlm;
-                        pr_warning("%s: E1 Port %d RAI alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
-                    {
-                        copyVal |= sbeYelAlm;
-                        pr_warning("%s: E1 Warning: Port %d RAI alarm.\n",
-                                   ci->devname, portnum);
-                    } else if ((copyVal & sbeE1RMAI) && !(value & sbeE1RMAI))
-                    {
-                        copyVal &= ~sbeE1RMAI;
-                        pr_warning("%s: E1 Port %d RMAI alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeE1RMAI) && (value & sbeE1RMAI))
-                    {
-                        copyVal |= sbeE1RMAI;
-                        pr_warning("%s: E1 Warning: Port %d RMAI alarm.\n",
-                                   ci->devname, portnum);
-                    } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
-                    {
-                        copyVal &= ~sbeAISAlm;
-                        pr_warning("%s: E1 Port %d AIS alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
-                    {
-                        copyVal |= sbeAISAlm;
-                        pr_warning("%s: E1 Warning: Port %d AIS alarm.\n",
-                                   ci->devname, portnum);
-                    }
-                }
-                /* end of E1 alarm code */
-            } else
-            {                       /* if a T1 mode */
-                value = pci_read_32 ((u_int32_t *) &comet->t1_almi_ists);       /* alarms */
-                value &= sbeAlarmsMask;
-                if (value != (copyVal & sbeAlarmsMask))
-                {                   /* if alarms changed */
-                    copyVal |= 0x10;/* change LED status   */
-                    if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
-                    {
-                        copyVal &= ~sbeRedAlm;
-                        pr_warning("%s: Port %d red alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
-                    {
-                        copyVal |= sbeRedAlm;
-                        pr_warning("%s: Warning: Port %d red alarm.\n",
-                                   ci->devname, portnum);
-                    } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
-                    {
-                        copyVal &= ~sbeYelAlm;
-                        pr_warning("%s: Port %d yellow (RAI) alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
-                    {
-                        copyVal |= sbeYelAlm;
-                        pr_warning("%s: Warning: Port %d yellow (RAI) alarm.\n",
-                                   ci->devname, portnum);
-                    } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
-                    {
-                        copyVal &= ~sbeAISAlm;
-                        pr_warning("%s: Port %d blue (AIS) alarm ended.\n",
-                                   ci->devname, portnum);
-                    } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
-                    {
-                        copyVal |= sbeAISAlm;
-                        pr_warning("%s: Warning: Port %d blue (AIS) alarm.\n",
-                                   ci->devname, portnum);
-                    }
-                }
-            }                       /* end T1 mode alarm checks */
-        }
-        if (copyVal & sbeAlarmsMask)
-            copyVal |= 0x80;        /* if alarm turn yel LED on */
-        if (copyVal & 0x10)
-            LEDval |= 0x100;        /* tag if LED values have changed  */
-        LEDval |= ((copyVal & 0xc0) >> (6 - (portnum * 2)));
-
-        ci->alarmed[portnum] &= 0xfffff000;     /* out with the old (it's fff
-                                                 * ... foo) */
-        ci->alarmed[portnum] |= (copyVal);      /* in with the new */
-
-        /*
-         * enough with the alarms and LED's, now let's check for loopback
-         * requests
-         */
-
-        if (IS_FRAME_ANY_T1 (ci->port[portnum].p.port_mode))
-        {                           /* if a T1 mode  */
-            /*
-             * begin in-band (SF) loopback code detection -- start by reading
-             * command
-             */
-            value = pci_read_32 ((u_int32_t *) &comet->ibcd_ies);       /* detect reg. */
-            value &= 0x3;           /* trim to handy bits */
-            if (value & 0x2)
-            {                       /* activate loopback (sets for deactivate
-                                     * code length) */
-                copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
-                                                                         * mode */
-                if (copyVal != COMET_MDIAG_LINELB)      /* don't do it again if
-                                                         * already in that mode */
-                    c4_loop_port (ci, portnum, COMET_MDIAG_LINELB);     /* put port in line
-                                                                         * loopback mode */
-            }
-            if (value & 0x1)
-            {                       /* deactivate loopback (sets for activate
-                                     * code length) */
-                copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
-                                                                         * mode */
-                if (copyVal != COMET_MDIAG_LBOFF)       /* don't do it again if
-                                                         * already in that mode */
-                    c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);      /* take port out of any
-                                                                         * loopback mode */
-            }
-        }
-        if (IS_FRAME_ANY_T1ESF (ci->port[portnum].p.port_mode))
-        {                           /* if a T1 ESF mode  */
-            /* begin ESF loopback code */
-            value = pci_read_32 ((u_int32_t *) &comet->t1_rboc_sts) & 0x3f;     /* read command */
-            if (value == 0x07)
-                c4_loop_port (ci, portnum, COMET_MDIAG_LINELB); /* put port in line
-                                                                 * loopback mode */
-            if (value == 0x0a)
-                c4_loop_port (ci, portnum, COMET_MDIAG_PAYLB);  /* put port in payload
-                                                                 * loopbk mode */
-            if ((value == 0x1c) || (value == 0x19) || (value == 0x12))
-                c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);  /* take port out of any
-                                                                 * loopbk mode */
-            if (cxt1e1_log_level >= LOG_DEBUG)
-                if (value != 0x3f)
-                    pr_warning("%s: BOC value = %x on Port %d\n",
-                               ci->devname, value, portnum);
-            /* end ESF loopback code */
-        }
-    }
-
-    /* if something is new, update LED's */
-    if (LEDval & 0x100)
-        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, LEDval & 0xff);
-#endif                              /*** CONFIG_SBE_PMCC4_NCOMM ***/
-}
-
-
-static void
-c4_watchdog (ci_t *ci)
-{
-    if (drvr_state != SBE_DRVR_AVAILABLE)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_info("drvr not available (%x)\n", drvr_state);
-        return;
-    }
-    ci->wdcount++;
-    checkPorts (ci);
-    ci->wd_notify = 0;
-}
-
-
-void
-c4_cleanup (void)
-{
-    ci_t       *ci, *next;
-    mpi_t      *pi;
-    int         portnum, j;
-
-    ci = c4_list;
-    while (ci)
-    {
-        next = ci->next;            /* protect <next> from upcoming <free> */
-        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
-        for (portnum = 0; portnum < ci->max_port; portnum++)
-        {
-            pi = &ci->port[portnum];
-            c4_wq_port_cleanup (pi);
-            for (j = 0; j < MUSYCC_NCHANS; j++)
-            {
-                if (pi->chan[j])
-                    kfree(pi->chan[j]);     /* free mch_t struct */
-            }
-            kfree(pi->regram_saved);
-        }
-        kfree(ci->iqd_p_saved);
-        kfree(ci);
-        ci = next;                  /* cleanup next board, if any */
-    }
-}
-
-
-/*
- * This function issues a write to all comet chips and expects the same data
- * to be returned from the subsequent read.  This determines the board build
- * to be a 1-port, 2-port, or 4-port build.  The value returned represents a
- * bit-mask of the found ports.  Only certain configurations are considered
- * VALID or LEGAL builds.
- */
-
-int
-c4_get_portcfg (ci_t *ci)
-{
-    struct s_comet_reg    *comet;
-    int         portnum, mask;
-    u_int32_t   wdata, rdata;
-
-    wdata = COMET_MDIAG_LBOFF;      /* take port out of any loopback mode */
-
-    mask = 0;
-    for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
-    {
-        comet = ci->port[portnum].cometbase;
-        pci_write_32 ((u_int32_t *) &comet->mdiag, wdata);
-        rdata = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
-        if (wdata == rdata)
-            mask |= 1 << portnum;
-    }
-    return mask;
-}
-
-
-/* nothing herein should generate interrupts */
-
-status_t    __init
-c4_init (ci_t *ci, u_char *func0, u_char *func1)
-{
-    mpi_t      *pi;
-    mch_t      *ch;
-    static u_int32_t count = 0;
-    int         portnum, j;
-
-    ci->state = C_INIT;
-    ci->brdno = count++;
-    ci->intlog.this_status_new = 0;
-    atomic_set (&ci->bh_pending, 0);
-
-    ci->reg = (struct musycc_globalr *) func0;
-    ci->eeprombase = (u_int32_t *) (func1 + EEPROM_OFFSET);
-    ci->cpldbase = (c4cpld_t *) ((u_int32_t *) (func1 + ISPLD_OFFSET));
-
-    /*** PORT POINT - the following is the first access of any type to the hardware ***/
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-    /* NCOMM driver uses INTB interrupt to monitor CPLD register */
-    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC);
-#else
-    /* standard driver POLLS for INTB via CPLD register */
-    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
-#endif
-
-    {
-        int         pmsk;
-
-        /* need comet addresses available for determination of hardware build */
-        for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
-        {
-            pi = &ci->port[portnum];
-            pi->cometbase = (struct s_comet_reg *) ((u_int32_t *) (func1 + COMET_OFFSET (portnum)));
-            pi->reg = (struct musycc_globalr *) ((u_char *) ci->reg + (portnum * 0x800));
-            pi->portnum = portnum;
-            pi->p.portnum = portnum;
-            pi->openchans = 0;
-#ifdef SBE_MAP_DEBUG
-            pr_info("Comet-%d: addr = %p\n", portnum, pi->cometbase);
-#endif
-        }
-        pmsk = c4_get_portcfg (ci);
-        switch (pmsk)
-        {
-        case 0x1:
-            ci->max_port = 1;
-            break;
-        case 0x3:
-            ci->max_port = 2;
-            break;
-#if 0
-        case 0x7:                   /* not built, but could be... */
-            ci->max_port = 3;
-            break;
-#endif
-        case 0xf:
-            ci->max_port = 4;
-            break;
-        default:
-            ci->max_port = 0;
-            pr_warning("%s: illegal port configuration (%x)\n",
-                       ci->devname, pmsk);
-            return SBE_DRVR_FAIL;
-        }
-#ifdef SBE_MAP_DEBUG
-        pr_info(">> %s: c4_get_build - pmsk %x max_port %x\n",
-                ci->devname, pmsk, ci->max_port);
-#endif
-    }
-
-    for (portnum = 0; portnum < ci->max_port; portnum++)
-    {
-        pi = &ci->port[portnum];
-        pi->up = ci;
-        pi->sr_last = 0xffffffff;
-        pi->p.port_mode = CFG_FRAME_SF; /* T1 B8ZS, the default */
-        pi->p.portP = (CFG_CLK_PORT_EXTERNAL | CFG_LBO_LH0);    /* T1 defaults */
-
-        OS_sem_init (&pi->sr_sem_busy, SEM_AVAILABLE);
-        OS_sem_init (&pi->sr_sem_wait, SEM_TAKEN);
-
-        for (j = 0; j < 32; j++)
-        {
-            pi->fifomap[j] = -1;
-            pi->tsm[j] = 0;         /* no assignments, all available */
-        }
-
-        /* allocate channel structures for this port */
-        for (j = 0; j < MUSYCC_NCHANS; j++)
-        {
-		ch = kzalloc(sizeof(mch_t), GFP_KERNEL | GFP_DMA);
-            if (ch)
-            {
-                pi->chan[j] = ch;
-                ch->state = UNASSIGNED;
-                ch->up = pi;
-                ch->gchan = (-1);   /* channel assignment not yet known */
-                ch->channum = (-1); /* channel assignment not yet known */
-                ch->p.card = ci->brdno;
-                ch->p.port = portnum;
-                ch->p.channum = (-1);   /* channel assignment not yet known */
-                ch->p.mode_56k = 0; /* default is 64kbps mode */
-            } else
-            {
-                pr_warning("failed mch_t malloc, port %d channel %d size %u.\n",
-                           portnum, j, (unsigned int) sizeof (mch_t));
-                break;
-            }
-        }
-    }
-
-
-    {
-        /*
-         * Set LEDs through their paces to supply visual proof that LEDs are
-         * functional and not burnt out nor broken.
-         *
-         * YELLOW + GREEN -> OFF.
-         */
-
-        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds,
-                      PMCC4_CPLD_LED_GREEN | PMCC4_CPLD_LED_YELLOW);
-        OS_uwait (750000, "leds");
-        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
-    }
-
-    OS_init_watchdog (&ci->wd, (void (*) (void *)) c4_watchdog, ci, WATCHDOG_TIMEOUT);
-    return SBE_DRVR_SUCCESS;
-}
-
-
-/* better be fully setup to handle interrupts when you call this */
-
-status_t    __init
-c4_init2 (ci_t *ci)
-{
-    status_t    ret;
-
-    /* PORT POINT: this routine generates first interrupt */
-	ret = musycc_init(ci);
-	if (ret != SBE_DRVR_SUCCESS)
-		return ret;
-
-#if 0
-    ci->p.framing_type = FRAMING_CBP;
-    ci->p.h110enable = 1;
-#if 0
-    ci->p.hypersize = 0;
-#else
-    hyperdummy = 0;
-#endif
-    ci->p.clock = 0;                /* Use internal clocking until set to
-                                     * external */
-    c4_card_set_params (ci, &ci->p);
-#endif
-    OS_start_watchdog (&ci->wd);
-    return SBE_DRVR_SUCCESS;
-}
-
-
-/* This function sets the loopback mode (or clears it, as the case may be). */
-
-int
-c4_loop_port (ci_t *ci, int portnum, u_int8_t cmd)
-{
-    struct s_comet_reg    *comet;
-    volatile u_int32_t loopValue;
-
-    comet = ci->port[portnum].cometbase;
-    loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
-
-    if (cmd & COMET_LBCMD_READ)
-        return loopValue;           /* return the read value */
-
-    if (loopValue != cmd)
-    {
-        switch (cmd)
-        {
-        case COMET_MDIAG_LINELB:
-            /* set(SF)loopback down (turn off) code length to 6 bits */
-            pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x05);
-            break;
-        case COMET_MDIAG_LBOFF:
-            /* set (SF) loopback up (turn on) code length to 5 bits */
-            pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x00);
-            break;
-        }
-
-        pci_write_32 ((u_int32_t *) &comet->mdiag, cmd);
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: loopback mode changed to %2x from %2x on Port %d\n",
-                    ci->devname, cmd, loopValue, portnum);
-        loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
-        if (loopValue != cmd)
-        {
-            if (cxt1e1_log_level >= LOG_ERROR)
-                pr_info("%s: write to loop register failed, unknown state for Port %d\n",
-                        ci->devname, portnum);
-        }
-    } else
-    {
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: loopback already in that mode (%2x)\n",
-                    ci->devname, loopValue);
-    }
-    return 0;
-}
-
-
-/* c4_frame_rw: read or write the comet register specified
- * (modifies use of port_param to non-standard use of struct)
- * Specifically:
- *   pp.portnum     (one guess)
- *   pp.port_mode   offset of register
- *   pp.portP       write (or not, i.e. read)
- *   pp.portStatus  write value
- * BTW:
- *   pp.portStatus  also used to return read value
- *   pp.portP       also used during write, to return old reg value
- */
-
-status_t
-c4_frame_rw (ci_t *ci, struct sbecom_port_param *pp)
-{
-    struct s_comet_reg    *comet;
-    volatile u_int32_t data;
-
-    if (pp->portnum >= ci->max_port)/* sanity check */
-        return -ENXIO;
-
-    comet = ci->port[pp->portnum].cometbase;
-    data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
-
-    if (pp->portP)
-    {                               /* control says this is a register
-                                     * _write_ */
-        if (pp->portStatus == data)
-            pr_info("%s: Port %d already that value!  Writing again anyhow.\n",
-                    ci->devname, pp->portnum);
-        pp->portP = (u_int8_t) data;
-        pci_write_32 ((u_int32_t *) comet + pp->port_mode,
-                      pp->portStatus);
-        data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
-    }
-    pp->portStatus = (u_int8_t) data;
-    return 0;
-}
-
-
-/* c4_pld_rw: read or write the pld register specified
- * (modifies use of port_param to non-standard use of struct)
- * Specifically:
- *   pp.port_mode   offset of register
- *   pp.portP       write (or not, i.e. read)
- *   pp.portStatus  write value
- * BTW:
- *   pp.portStatus  also used to return read value
- *   pp.portP       also used during write, to return old reg value
- */
-
-status_t
-c4_pld_rw (ci_t *ci, struct sbecom_port_param *pp)
-{
-    volatile u_int32_t *regaddr;
-    volatile u_int32_t data;
-    int         regnum = pp->port_mode;
-
-    regaddr = (u_int32_t *) ci->cpldbase + regnum;
-    data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
-
-    if (pp->portP)
-    {                               /* control says this is a register
-                                     * _write_ */
-        pp->portP = (u_int8_t) data;
-        pci_write_32 ((u_int32_t *) regaddr, pp->portStatus);
-        data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
-    }
-    pp->portStatus = (u_int8_t) data;
-    return 0;
-}
-
-/* c4_musycc_rw: read or write the musycc register specified
- * (modifies use of port_param to non-standard use of struct)
- * Specifically:
- *    mcp.RWportnum   port number and write indication bit (0x80)
- *    mcp.offset      offset of register
- *    mcp.value       write value going in and read value returning
- */
-
-/* PORT POINT: TX Subchannel Map registers are write-only
- * areas within the MUSYCC and always return FF */
-/* PORT POINT: regram and reg structures are minorly different and <offset> ioctl
- * settings are aligned with the <reg> struct musycc_globalr{} usage.
- * Also, regram is separately allocated shared memory, allocated for each port.
- * PORT POINT: access offsets of 0x6000 for Msg Cfg Desc Tbl are for 4-port MUSYCC
- * only.  (An 8-port MUSYCC has 0x16000 offsets for accessing its upper 4 tables.)
- */
-
-status_t
-c4_musycc_rw (ci_t *ci, struct c4_musycc_param *mcp)
-{
-    mpi_t      *pi;
-    volatile u_int32_t *dph;    /* hardware implemented register */
-    u_int32_t *dpr = NULL;	/* RAM image of registers for group command
-                                 * usage */
-    int         offset = mcp->offset % 0x800;   /* group relative address
-                                                 * offset, mcp->portnum is
-                                                 * not used */
-    int         portnum, ramread = 0;
-    volatile u_int32_t data;
-
-    /*
-     * Sanity check hardware accessibility.  The 0x6000 portion handles port
-     * numbers associated with Msg Descr Tbl decoding.
-     */
-    portnum = (mcp->offset % 0x6000) / 0x800;
-    if (portnum >= ci->max_port)
-        return -ENXIO;
-    pi = &ci->port[portnum];
-    if (mcp->offset >= 0x6000)
-        offset += 0x6000;           /* put back in MsgCfgDesc address offset */
-    dph = (u_int32_t *) ((u_long) pi->reg + offset);
-
-    /* read of TX are from RAM image, since hardware returns FF */
-    dpr = (u_int32_t *) ((u_long) pi->regram + offset);
-    if (mcp->offset < 0x6000)       /* non MsgDesc Tbl accesses might require
-                                     * RAM access */
-    {
-        if (offset >= 0x200 && offset < 0x380)
-            ramread = 1;
-        if (offset >= 0x10 && offset < 0x200)
-            ramread = 1;
-    }
-    /* read register from RAM or hardware, depending... */
-    if (ramread)
-    {
-        data = *dpr;
-        //pr_info("c4_musycc_rw: RAM addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dpr, data, portnum, offset, ramread); /* RLD DEBUG */
-    } else
-    {
-        data = pci_read_32 ((u_int32_t *) dph);
-        //pr_info("c4_musycc_rw: REG addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dph, data, portnum, offset, ramread); /* RLD DEBUG */
-    }
-
-
-    if (mcp->RWportnum & 0x80)
-    {                               /* control says this is a register
-                                     * _write_ */
-        if (mcp->value == data)
-            pr_info("%s: musycc grp%d already that value! writing again anyhow.\n",
-                    ci->devname, (mcp->RWportnum & 0x7));
-        /* write register RAM */
-        if (ramread)
-            *dpr = mcp->value;
-        /* write hardware register */
-        pci_write_32 ((u_int32_t *) dph, mcp->value);
-    }
-    mcp->value = data;              /* return the read value (or the 'old
-                                     * value', if is write) */
-    return 0;
-}
-
-status_t
-c4_get_port (ci_t *ci, int portnum)
-{
-    if (portnum >= ci->max_port)    /* sanity check */
-        return -ENXIO;
-
-    SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");      /* only 1 thru here, per
-                                                 * board */
-    checkPorts (ci);
-    ci->port[portnum].p.portStatus = (u_int8_t) ci->alarmed[portnum];
-    ci->alarmed[portnum] &= 0xdf;
-    SD_SEM_GIVE (&ci->sem_wdbusy);  /* release per-board hold */
-    return 0;
-}
-
-status_t
-c4_set_port (ci_t *ci, int portnum)
-{
-    mpi_t      *pi;
-    struct sbecom_port_param *pp;
-    int         e1mode;
-    u_int8_t    clck;
-    int         i;
-
-    if (portnum >= ci->max_port)    /* sanity check */
-        return -ENXIO;
-
-    pi = &ci->port[portnum];
-    pp = &ci->port[portnum].p;
-    e1mode = IS_FRAME_ANY_E1 (pp->port_mode);
-    if (cxt1e1_log_level >= LOG_MONITOR2)
-    {
-        pr_info("%s: c4_set_port[%d]:  entered, e1mode = %x, openchans %d.\n",
-                ci->devname,
-                portnum, e1mode, pi->openchans);
-    }
-    if (pi->openchans)
-        return -EBUSY;               /* group needs initialization only for
-                                     * first channel of a group */
-
-    {
-        status_t    ret;
-
-	ret = c4_wq_port_init(pi);
-	if (ret)       /* create/init workqueue_struct */
-		return ret;
-    }
-
-    init_comet (ci, pi->cometbase, pp->port_mode, 1 /* clockmaster == true */ , pp->portP);
-    clck = pci_read_32 ((u_int32_t *) &ci->cpldbase->mclk) & PMCC4_CPLD_MCLK_MASK;
-    if (e1mode)
-        clck |= 1 << portnum;
-    else
-        clck &= 0xf ^ (1 << portnum);
-
-    pci_write_32 ((u_int32_t *) &ci->cpldbase->mclk, clck);
-    pci_write_32 ((u_int32_t *) &ci->cpldbase->mcsr, PMCC4_CPLD_MCSR_IND);
-    pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
-
-    /*********************************************************************/
-    /* ERRATA: If transparent mode is used, do not set OOFMP_DISABLE bit */
-    /*********************************************************************/
-
-    pi->regram->grcd =
-        __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
-                                MUSYCC_GRCD_TX_ENABLE |
-                                MUSYCC_GRCD_OOFMP_DISABLE |
-                                MUSYCC_GRCD_SF_ALIGN |  /* per MUSYCC ERRATA,
-                                                         * for T1 * fix */
-                                MUSYCC_GRCD_COFAIRQ_DISABLE |
-                                MUSYCC_GRCD_MC_ENABLE |
-                       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
-
-    pi->regram->pcd =
-        __constant_cpu_to_le32 ((e1mode ? 1 : 0) |
-                                MUSYCC_PCD_TXSYNC_RISING |
-                                MUSYCC_PCD_RXSYNC_RISING |
-                                MUSYCC_PCD_RXDATA_RISING);
-
-    /* Message length descriptor */
-       pi->regram->mld = __constant_cpu_to_le32 (cxt1e1_max_mru | (cxt1e1_max_mru << 16));
-
-    /* tsm algorithm */
-    for (i = 0; i < 32; i++)
-    {
-
-        /*** ASSIGNMENT NOTES:                             ***/
-        /*** Group's channel  ZERO  unavailable if E1.     ***/
-        /*** Group's channel  16    unavailable if E1 CAS. ***/
-        /*** Group's channels 24-31 unavailable if T1.     ***/
-
-        if (((i == 0) && e1mode) ||
-            ((i == 16) && ((pp->port_mode == CFG_FRAME_E1CRC_CAS) || (pp->port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
-            || ((i > 23) && (!e1mode)))
-        {
-            pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
-        } else
-        {
-            pi->tsm[i] = 0x00;      /* make tslot available for assignment */
-        }
-    }
-    for (i = 0; i < MUSYCC_NCHANS; i++)
-    {
-        pi->regram->ttsm[i] = 0;
-        pi->regram->rtsm[i] = 0;
-    }
-    FLUSH_MEM_WRITE ();
-    musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
-    musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
-
-    musycc_init_mdt (pi);
-
-    pi->group_is_set = 1;
-    pi->p = *pp;
-    return 0;
-}
-
-
-unsigned int max_int = 0;
-
-status_t
-c4_new_chan (ci_t *ci, int portnum, int channum, void *user)
-{
-    mpi_t      *pi;
-    mch_t      *ch;
-    int         gchan;
-
-    if (c4_find_chan (channum))     /* a new channel shouldn't already exist */
-        return -EEXIST;
-
-    if (portnum >= ci->max_port)    /* sanity check */
-        return -ENXIO;
-
-    pi = &(ci->port[portnum]);
-    /* find any available channel within this port */
-    for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
-    {
-        ch = pi->chan[gchan];
-        if (ch && ch->state == UNASSIGNED)      /* no assignment is good! */
-            break;
-    }
-    if (gchan == MUSYCC_NCHANS)     /* exhausted table, all were assigned */
-        return -ENFILE;
-
-    ch->up = pi;
-
-    /* NOTE: mch_t already cleared during OS_kmalloc() */
-    ch->state = DOWN;
-    ch->user = user;
-    ch->gchan = gchan;
-    ch->channum = channum;          /* mark our channel assignment */
-    ch->p.channum = channum;
-#if 1
-    ch->p.card = ci->brdno;
-    ch->p.port = portnum;
-#endif
-    ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
-    ch->p.idlecode = CFG_CH_FLAG_7E;
-    ch->p.pad_fill_count = 2;
-    spin_lock_init (&ch->ch_rxlock);
-    spin_lock_init (&ch->ch_txlock);
-
-    {
-        status_t    ret;
-
-	ret = c4_wk_chan_init(pi, ch);
-	if (ret)
-		return ret;
-    }
-
-    /* save off interface assignments which bound a board */
-    if (!ci->first_if)		/* first channel registered is assumed to
-                                     * be the lowest channel */
-    {
-        ci->first_if = ci->last_if = user;
-        ci->first_channum = ci->last_channum = channum;
-    } else
-    {
-        ci->last_if = user;
-        if (ci->last_channum < channum) /* higher number channel found */
-            ci->last_channum = channum;
-    }
-    return 0;
-}
-
-status_t
-c4_del_chan (int channum)
-{
-    mch_t      *ch;
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-    if (ch->state == UP)
-        musycc_chan_down ((ci_t *) 0, channum);
-    ch->state = UNASSIGNED;
-    ch->gchan = (-1);
-    ch->channum = (-1);
-    ch->p.channum = (-1);
-    return 0;
-}
-
-status_t
-c4_del_chan_stats (int channum)
-{
-    mch_t      *ch;
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-    memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
-    return 0;
-}
-
-
-status_t
-c4_set_chan (int channum, struct sbecom_chan_param *p)
-{
-    mch_t      *ch;
-    int         i, x = 0;
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-#if 1
-    if (ch->p.card != p->card ||
-        ch->p.port != p->port ||
-        ch->p.channum != p->channum)
-        return -EINVAL;
-#endif
-
-    if (!(ch->up->group_is_set))
-    {
-        return -EIO;                 /* out of order, SET_PORT command
-                                     * required prior to first group's
-                                     * SET_CHAN command */
-    }
-    /*
-     * Check for change of parameter settings in order to invoke closing of
-     * channel prior to hardware poking.
-     */
-
-    if (ch->p.status != p->status || ch->p.chan_mode != p->chan_mode ||
-        ch->p.data_inv != p->data_inv || ch->p.intr_mask != p->intr_mask ||
-        ch->txd_free < ch->txd_num) /* to clear out queued messages */
-        x = 1;                      /* we have a change requested */
-    for (i = 0; i < 32; i++)        /* check for timeslot mapping changes */
-        if (ch->p.bitmask[i] != p->bitmask[i])
-            x = 1;                  /* we have a change requested */
-    ch->p = *p;
-    if (x && (ch->state == UP))     /* if change request and channel is
-                                     * open... */
-    {
-        status_t    ret;
-
-	ret = musycc_chan_down((ci_t *)0, channum);
-	if (ret)
-		return ret;
-	ret = c4_chan_up(ch->up->up, channum);
-	if (ret)
-		return ret;
-        sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
-                                     * channel */
-    }
-    return 0;
-}
-
-
-status_t
-c4_get_chan (int channum, struct sbecom_chan_param *p)
-{
-    mch_t      *ch;
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-    *p = ch->p;
-    return 0;
-}
-
-status_t
-c4_get_chan_stats (int channum, struct sbecom_chan_stats *p)
-{
-    mch_t      *ch;
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-    *p = ch->s;
-    p->tx_pending = atomic_read (&ch->tx_pending);
-    return 0;
-}
-
-static int
-c4_fifo_alloc (mpi_t *pi, int chan, int *len)
-{
-    int         i, l = 0, start = 0, max = 0, maxstart = 0;
-
-    for (i = 0; i < 32; i++)
-    {
-        if (pi->fifomap[i] != -1)
-        {
-            l = 0;
-            start = i + 1;
-            continue;
-        }
-        ++l;
-        if (l > max)
-        {
-            max = l;
-            maxstart = start;
-        }
-        if (max == *len)
-            break;
-    }
-    if (max != *len)
-    {
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: wanted to allocate %d fifo space, but got only %d\n",
-                    pi->up->devname, *len, max);
-        *len = max;
-    }
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("%s: allocated %d fifo at %d for channel %d/%d\n",
-                pi->up->devname, max, start, chan, pi->p.portnum);
-    for (i = maxstart; i < (maxstart + max); i++)
-        pi->fifomap[i] = chan;
-    return start;
-}
-
-void
-c4_fifo_free (mpi_t *pi, int chan)
-{
-    int         i;
-
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("%s: deallocated fifo for channel %d/%d\n",
-                pi->up->devname, chan, pi->p.portnum);
-    for (i = 0; i < 32; i++)
-        if (pi->fifomap[i] == chan)
-            pi->fifomap[i] = -1;
-}
-
-
-status_t
-c4_chan_up (ci_t *ci, int channum)
-{
-    mpi_t      *pi;
-    mch_t      *ch;
-    struct mbuf *m;
-    struct mdesc *md;
-    int         nts, nbuf, txnum, rxnum;
-    int         addr, i, j, gchan;
-    u_int32_t   tmp;            /* for optimizing conversion across BE
-                                 * platform */
-
-	ch = c4_find_chan(channum);
-	if (!ch)
-		return -ENOENT;
-
-    if (ch->state == UP)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_info("%s: channel already UP, graceful early exit\n",
-                    ci->devname);
-        return 0;
-    }
-    pi = ch->up;
-    gchan = ch->gchan;
-    /* find nts ('number of timeslots') */
-    nts = 0;
-    for (i = 0; i < 32; i++)
-    {
-        if (ch->p.bitmask[i] & pi->tsm[i])
-        {
-            if (1 || cxt1e1_log_level >= LOG_WARN)
-            {
-                pr_info("%s: c4_chan_up[%d] EINVAL (attempt to cfg in-use or unavailable TimeSlot[%d])\n",
-                        ci->devname, channum, i);
-                pr_info("+ ask4 %x, currently %x\n",
-                        ch->p.bitmask[i], pi->tsm[i]);
-            }
-            return -EINVAL;
-        }
-        for (j = 0; j < 8; j++)
-            if (ch->p.bitmask[i] & (1 << j))
-                nts++;
-    }
-
-    nbuf = nts / 8 ? nts / 8 : 1;
-    if (!nbuf)
-    {
-        /* if( cxt1e1_log_level >= LOG_WARN)  */
-        pr_info("%s: c4_chan_up[%d] ENOBUFS (no TimeSlots assigned)\n",
-                ci->devname, channum);
-        return -ENOBUFS;             /* this should not happen */
-    }
-    addr = c4_fifo_alloc (pi, gchan, &nbuf);
-    ch->state = UP;
-
-    /* Setup the Time Slot Map */
-    musycc_update_timeslots (pi);
-
-    /* ch->tx_limit = nts; */
-    ch->s.tx_pending = 0;
-
-    /* Set Channel Configuration Descriptors */
-    {
-        u_int32_t   ccd;
-
-        ccd = musycc_chan_proto (ch->p.chan_mode) << MUSYCC_CCD_PROTO_SHIFT;
-        if ((ch->p.chan_mode == CFG_CH_PROTO_ISLP_MODE) ||
-            (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
-        {
-            ccd |= MUSYCC_CCD_FCS_XFER; /* Non FSC Mode */
-        }
-        ccd |= 2 << MUSYCC_CCD_MAX_LENGTH;      /* Select second MTU */
-        ccd |= ch->p.intr_mask;
-        ccd |= addr << MUSYCC_CCD_BUFFER_LOC;
-        if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-            ccd |= (nbuf) << MUSYCC_CCD_BUFFER_LENGTH;
-        else
-            ccd |= (nbuf - 1) << MUSYCC_CCD_BUFFER_LENGTH;
-
-        if (ch->p.data_inv & CFG_CH_DINV_TX)
-            ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
-        pi->regram->tcct[gchan] = cpu_to_le32 (ccd);
-
-        if (ch->p.data_inv & CFG_CH_DINV_RX)
-            ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
-        else
-            ccd &= ~MUSYCC_CCD_INVERT_DATA;     /* take away data inversion */
-        pi->regram->rcct[gchan] = cpu_to_le32 (ccd);
-        FLUSH_MEM_WRITE ();
-    }
-
-    /* Reread the Channel Configuration Descriptor for this channel */
-    musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_RX_DIRECTION | gchan);
-    musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_TX_DIRECTION | gchan);
-
-    /*
-     * Figure out how many buffers we want.  If the customer has changed from
-     * the defaults, then use the changed values.  Otherwise, use Transparent
-     * mode's specific minimum default settings.
-     */
-    if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-    {
-        if (max_rxdesc_used == max_rxdesc_default)      /* use default setting */
-            max_rxdesc_used = MUSYCC_RXDESC_TRANS;
-        if (max_txdesc_used == max_txdesc_default)      /* use default setting */
-            max_txdesc_used = MUSYCC_TXDESC_TRANS;
-    }
-    /*
-     * Increase counts when hyperchanneling, since this implies an increase
-     * in throughput per channel
-     */
-    rxnum = max_rxdesc_used + (nts / 4);
-    txnum = max_txdesc_used + (nts / 4);
-
-#if 0
-    /* DEBUG INFO */
-    if (cxt1e1_log_level >= LOG_MONITOR)
-        pr_info("%s: mode %x rxnum %d (rxused %d def %d) txnum %d (txused %d def %d)\n",
-                ci->devname, ch->p.chan_mode,
-                rxnum, max_rxdesc_used, max_rxdesc_default,
-                txnum, max_txdesc_used, max_txdesc_default);
-#endif
-
-    ch->rxd_num = rxnum;
-    ch->txd_num = txnum;
-    ch->rxix_irq_srv = 0;
-
-	ch->mdr = kzalloc(sizeof(struct mdesc) * rxnum, GFP_KERNEL | GFP_DMA);
-	ch->mdt = kzalloc(sizeof(struct mdesc) * txnum, GFP_KERNEL | GFP_DMA);
-    if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-               tmp = __constant_cpu_to_le32 (cxt1e1_max_mru | EOBIRQ_ENABLE);
-    else
-               tmp = __constant_cpu_to_le32 (cxt1e1_max_mru);
-
-    for (i = 0, md = ch->mdr; i < rxnum; i++, md++)
-    {
-        if (i == (rxnum - 1))
-        {
-            md->snext = &ch->mdr[0];/* wrapness */
-        } else
-        {
-            md->snext = &ch->mdr[i + 1];
-        }
-        md->next = cpu_to_le32 (OS_vtophys (md->snext));
-
-	m = OS_mem_token_alloc(cxt1e1_max_mru);
-	if (!m) {
-		if (cxt1e1_log_level >= LOG_MONITOR)
-			pr_info(
-			"%s: c4_chan_up[%d] - token alloc failure, size = %d.\n",
-			ci->devname, channum, cxt1e1_max_mru);
-		goto errfree;
-        }
-        md->mem_token = m;
-        md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m)));
-        md->status = tmp | MUSYCC_RX_OWNED;     /* MUSYCC owns RX descriptor **
-                                                 * CODING NOTE:
-                                                 * MUSYCC_RX_OWNED = 0 so no
-                                                 * need to byteSwap */
-    }
-
-    for (i = 0, md = ch->mdt; i < txnum; i++, md++)
-    {
-        md->status = HOST_TX_OWNED; /* Host owns TX descriptor ** CODING
-                                     * NOTE: HOST_TX_OWNED = 0 so no need to
-                                     * byteSwap */
-        md->mem_token = NULL;
-        md->data = 0;
-        if (i == (txnum - 1))
-        {
-            md->snext = &ch->mdt[0];/* wrapness */
-        } else
-        {
-            md->snext = &ch->mdt[i + 1];
-        }
-        md->next = cpu_to_le32 (OS_vtophys (md->snext));
-    }
-    ch->txd_irq_srv = ch->txd_usr_add = &ch->mdt[0];
-    ch->txd_free = txnum;
-    ch->tx_full = 0;
-    ch->txd_required = 0;
-
-    /* Configure it into the chip */
-    tmp = cpu_to_le32 (OS_vtophys (&ch->mdt[0]));
-    pi->regram->thp[gchan] = tmp;
-    pi->regram->tmp[gchan] = tmp;
-
-    tmp = cpu_to_le32 (OS_vtophys (&ch->mdr[0]));
-    pi->regram->rhp[gchan] = tmp;
-    pi->regram->rmp[gchan] = tmp;
-
-    /* Activate the Channel */
-    FLUSH_MEM_WRITE ();
-    if (ch->p.status & RX_ENABLED)
-    {
-#ifdef RLD_TRANS_DEBUG
-        pr_info("++ c4_chan_up() CHAN RX ACTIVATE: chan %d\n", ch->channum);
-#endif
-        ch->ch_start_rx = 0;        /* we are restarting RX... */
-        musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan);
-    }
-    if (ch->p.status & TX_ENABLED)
-    {
-#ifdef RLD_TRANS_DEBUG
-        pr_info("++ c4_chan_up() CHAN TX ACTIVATE: chan %d <delayed>\n", ch->channum);
-#endif
-        ch->ch_start_tx = CH_START_TX_1ST;      /* we are delaying start
-                                                 * until receipt from user of
-                                                 * first packet to transmit. */
-    }
-    ch->status = ch->p.status;
-    pi->openchans++;
-    return 0;
-
-errfree:
-    while (i > 0)
-    {
-        /* Don't leak all the previously allocated mbufs in this loop */
-        i--;
-        OS_mem_token_free (ch->mdr[i].mem_token);
-    }
-    kfree(ch->mdt);
-    ch->mdt = NULL;
-    ch->txd_num = 0;
-    kfree(ch->mdr);
-    ch->mdr = NULL;
-    ch->rxd_num = 0;
-    ch->state = DOWN;
-    return -ENOBUFS;
-}
-
-/* stop the hardware from servicing & interrupting */
-
-void
-c4_stopwd (ci_t *ci)
-{
-    OS_stop_watchdog (&ci->wd);
-    SD_SEM_TAKE (&ci->sem_wdbusy, "_stop_");    /* ensure WD not running */
-    SD_SEM_GIVE (&ci->sem_wdbusy);
-}
-
-
-void
-sbecom_get_brdinfo (ci_t *ci, struct sbe_brd_info *bip, u_int8_t *bsn)
-{
-    char       *np;
-    u_int32_t   sn = 0;
-    int         i;
-
-    bip->brdno = ci->brdno;         /* our board number */
-    bip->brd_id = ci->brd_id;
-    bip->brd_hdw_id = ci->hdw_bid;
-    bip->brd_chan_cnt = MUSYCC_NCHANS *ci->max_port;   /* number of channels
-                                                         * being used */
-    bip->brd_port_cnt = ci->max_port;   /* number of ports being used */
-    bip->brd_pci_speed = BINFO_PCI_SPEED_unk;   /* PCI speed not yet
-                                                 * determinable */
-
-    if (ci->first_if)
-    {
-        {
-            struct net_device *dev;
-
-            dev = (struct net_device *) ci->first_if;
-            np = (char *) dev->name;
-        }
-        strncpy (bip->first_iname, np, CHNM_STRLEN - 1);
-    } else
-        strcpy (bip->first_iname, "<NULL>");
-    if (ci->last_if)
-    {
-        {
-            struct net_device *dev;
-
-            dev = (struct net_device *) ci->last_if;
-            np = (char *) dev->name;
-        }
-        strncpy (bip->last_iname, np, CHNM_STRLEN - 1);
-    } else
-        strcpy (bip->last_iname, "<NULL>");
-
-    if (bsn)
-    {
-        for (i = 0; i < 3; i++)
-        {
-            bip->brd_mac_addr[i] = *bsn++;
-        }
-        for (; i < 6; i++)
-        {
-            bip->brd_mac_addr[i] = *bsn;
-            sn = (sn << 8) | *bsn++;
-        }
-    } else
-    {
-        for (i = 0; i < 6; i++)
-            bip->brd_mac_addr[i] = 0;
-    }
-    bip->brd_sn = sn;
-}
-
-
-status_t
-c4_get_iidinfo (ci_t *ci, struct sbe_iid_info *iip)
-{
-    struct net_device *dev;
-    char       *np;
-
-	dev = getuserbychan(iip->channum);
-	if (!dev)
-		return -ENOENT;
-
-    np = dev->name;
-    strncpy (iip->iname, np, CHNM_STRLEN - 1);
-    iip->iname[CHNM_STRLEN - 1] = '\0';
-    return 0;
-}
-
-
-#ifdef CONFIG_SBE_PMCC4_NCOMM
-void        (*nciInterrupt[MAX_BOARDS][4]) (void);
-extern void wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler);
-
-void
-wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler)
-{
-    if (cardID < MAX_BOARDS)    /* sanity check */
-        nciInterrupt[cardID][deviceID] = handler;
-}
-
-irqreturn_t
-c4_ebus_intr_th_handler (void *devp)
-{
-    ci_t       *ci = (ci_t *) devp;
-    volatile u_int32_t ists;
-    int         handled = 0;
-    int         brdno;
-
-    /* which COMET caused the interrupt */
-    brdno = ci->brdno;
-    ists = pci_read_32 ((u_int32_t *) &ci->cpldbase->intr);
-    if (ists & PMCC4_CPLD_INTR_CMT_1)
-    {
-        handled = 0x1;
-        if (nciInterrupt[brdno][0] != NULL)
-            (*nciInterrupt[brdno][0]) ();
-    }
-    if (ists & PMCC4_CPLD_INTR_CMT_2)
-    {
-        handled |= 0x2;
-        if (nciInterrupt[brdno][1] != NULL)
-            (*nciInterrupt[brdno][1]) ();
-    }
-    if (ists & PMCC4_CPLD_INTR_CMT_3)
-    {
-        handled |= 0x4;
-        if (nciInterrupt[brdno][2] != NULL)
-            (*nciInterrupt[brdno][2]) ();
-    }
-    if (ists & PMCC4_CPLD_INTR_CMT_4)
-    {
-        handled |= 0x8;
-        if (nciInterrupt[brdno][3] != NULL)
-            (*nciInterrupt[brdno][3]) ();
-    }
-#if 0
-    /*** Test code just de-implements the asserted interrupt.  Alternate
-    vendor will supply COMET interrupt handling code herein or such.
-    ***/
-    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
-#endif
-
-    return IRQ_RETVAL (handled);
-}
-
-
-unsigned long
-wanpmcC4T1E1_getBaseAddress (int cardID, int deviceID)
-{
-    ci_t       *ci;
-    unsigned long base = 0;
-
-    ci = c4_list;
-    while (ci)
-    {
-        if (ci->brdno == cardID)    /* found valid device */
-        {
-            if (deviceID < ci->max_port)        /* comet is supported */
-                base = ((unsigned long) ci->port[deviceID].cometbase);
-            break;
-        }
-        ci = ci->next;              /* next board, if any */
-    }
-    return base;
-}
-
-#endif                          /*** CONFIG_SBE_PMCC4_NCOMM ***/
-
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-#ifndef _INC_PMCC4_H_
-#define _INC_PMCC4_H_
-
-/*-----------------------------------------------------------------------------
- * pmcc4.h -
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/types.h>
-
-typedef int status_t;
-
-#define SBE_DRVR_FAIL     0
-#define SBE_DRVR_SUCCESS  1
-
-/********************/
-/* PMCC4 memory Map */
-/********************/
-
-#define COMET_OFFSET(x) (0x80000+(x)*0x10000)
-#define EEPROM_OFFSET   0xC0000
-#define CPLD_OFFSET     0xD0000
-
-    struct pmcc4_timeslot_param
-    {
-        u_int8_t    card;       /* the card number */
-        u_int8_t    port;       /* the port number */
-        u_int8_t    _reserved1;
-        u_int8_t    _reserved2;
-
-        /*
-         * each byte in bitmask below represents one timeslot (bitmask[0] is
-         * for timeslot 0 and so on), each bit in the byte selects timeslot
-         * bits for this channel (0xff - whole timeslot, 0x7f - 56kbps mode)
-         */
-        u_int8_t    bitmask[32];
-    };
-
-    struct c4_musycc_param
-    {
-        u_int8_t    RWportnum;
-                    u_int16_t offset;
-        u_int32_t   value;
-    };
-
-/*Alarm values */
-#define sbeE1RMAI      0x100
-#define sbeYelAlm      0x04
-#define sbeRedAlm      0x02
-#define sbeAISAlm      0x01
-
-#define sbeE1errSMF    0x02
-#define sbeE1CRC       0x01
-
-#ifdef __KERNEL__
-
-/*
- * Device Driver interface, routines are for internal use only.
- */
-
-#include "pmcc4_private.h"
-
-char       *get_hdlc_name (hdlc_device *);
-
-/*
- * external interface
- */
-
-void        c4_cleanup (void);
-status_t    c4_chan_up (ci_t *, int channum);
-status_t    c4_del_chan_stats (int channum);
-status_t    c4_del_chan (int channum);
-status_t    c4_get_iidinfo (ci_t *ci, struct sbe_iid_info *iip);
-int         c4_is_chan_up (int channum);
-
-void       *getuserbychan (int channum);
-void        pci_flush_write (ci_t *ci);
-void        sbecom_set_loglevel (int debuglevel);
-char       *sbeid_get_bdname (ci_t *ci);
-void        sbeid_set_bdtype (ci_t *ci);
-void        sbeid_set_hdwbid (ci_t *ci);
-u_int32_t   sbeCrc (u_int8_t *, u_int32_t, u_int32_t, u_int32_t *);
-
-void        VMETRO_TRIGGER (ci_t *, int);       /* Note: int = 0(default)
-                                                 * thru 15 */
-
-#if defined (SBE_ISR_TASKLET)
-void        musycc_intr_bh_tasklet (ci_t *);
-
-#endif
-
-#endif                          /*** __KERNEL __ ***/
-#endif                          /* _INC_PMCC4_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_ioctls.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_ioctls.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_ioctls.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_ioctls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-#ifndef _INC_PMCC4_IOCTLS_H_
-#define _INC_PMCC4_IOCTLS_H_
-
-/*-----------------------------------------------------------------------------
- * pmcc4_ioctls.h -
- *
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-#include "sbew_ioc.h"
-
-enum
-{
-    // C4_GET_PORT = 0,
-    // C4_SET_PORT,
-    // C4_GET_CHAN,
-    // C4_SET_CHAN,
-    C4_DEL_CHAN = 0,
-    // C4_CREATE_CHAN,
-    // C4_GET_CHAN_STATS,
-    // C4_RESET,
-    // C4_DEBUG,
-    C4_RESET_STATS,
-    C4_LOOP_PORT,
-    C4_RW_FRMR,
-    C4_RW_MSYC,
-    C4_RW_PLD
-};
-
-#define C4_GET_PORT          SBE_IOC_PORT_GET
-#define C4_SET_PORT          SBE_IOC_PORT_SET
-#define C4_GET_CHAN          SBE_IOC_CHAN_GET
-#define C4_SET_CHAN          SBE_IOC_CHAN_SET
-// #define C4_DEL_CHAN          XXX
-#define C4_CREATE_CHAN       SBE_IOC_CHAN_NEW
-#define C4_GET_CHAN_STATS    SBE_IOC_CHAN_GET_STAT
-#define C4_RESET             SBE_IOC_RESET_DEV
-#define C4_DEBUG             SBE_IOC_LOGLEVEL
-// #define C4_RESET_STATS       XXX
-// #define C4_LOOP_PORT         XXX
-// #define C4_RW_FRMR           XXX
-// #define C4_RW_MSYC           XXX
-// #define C4_RW_PLD            XXX
-
-struct c4_chan_stats_wrap
-{
-    int         channum;
-    struct sbecom_chan_stats stats;
-};
-
-#endif   /* _INC_PMCC4_IOCTLS_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_private.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_private.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_private.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_private.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,295 +0,0 @@
-#ifndef _INC_PMCC4_PRIVATE_H_
-#define _INC_PMCC4_PRIVATE_H_
-
-/*-----------------------------------------------------------------------------
- * pmcc4_private.h -
- *
- * Copyright (C) 2005  SBE, Inc.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>    /* support for tasklets */
-#include <linux/timer.h>        /* support for timer */
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-
-#include "libsbew.h"
-#include "pmcc4_defs.h"
-#include "pmcc4_cpld.h"
-#include "musycc.h"
-#include "sbe_promformat.h"
-#include "comet.h"
-
-
-/* driver state */
-#define SBE_DRVR_INIT        0x0
-#define SBE_DRVR_AVAILABLE   0x69734F4E
-#define SBE_DRVR_DOWN        0x1
-
-/******************************************************************************
- * MUSYCC Message Descriptor - coupled to hardware implementation, the first
- * three u_int32 must not be reordered.
- */
-
-struct mdesc
-{
-    volatile u_int32_t status;  /* Buffer Descriptor */
-    u_int32_t   data;           /* Data Pointer */
-    u_int32_t   next;           /* MUSYCC view of Next Pointer */
-    void       *mem_token;      /* Data */
-    struct mdesc *snext;
-};
-
-
-/*************************************************************************
- * Private driver data structures, internal use only.
- */
-
-struct c4_chan_info
-{
-    int         gchan;          /* channel number within group/port 0-31 */
-    int         channum;        /* absolute channel number 0-128 */
-    u_int8_t    status;
-#define TX_RECOVERY_MASK   0x0f
-#define TX_ONR_RECOVERY    0x01
-#define TX_BUFF_RECOVERY   0x02
-#define RX_RECOVERY_MASK   0xf0
-#define RX_ONR_RECOVERY    0x10
-
-    unsigned char ch_start_rx;
-#define CH_START_RX_NOW    1
-#define CH_START_RX_ONR    2
-#define CH_START_RX_BUF    3
-
-    unsigned char ch_start_tx;
-#define CH_START_TX_1ST    1
-#define CH_START_TX_ONR    2
-#define CH_START_TX_BUF    3
-
-    char        tx_full;        /* boolean */
-    short       txd_free;       /* count of TX Desc available */
-    short       txd_required;   /* count of TX Desc needed by mesg */
-    unsigned short rxd_num;     /* must support range up to 2000 */
-    unsigned short txd_num;     /* must support range up to 1000 */
-    int         rxix_irq_srv;
-
-    enum
-    {
-        UNASSIGNED,             /* AVAILABLE, NOTINUSE */
-        DOWN,                   /* ASSIGNED, NOTINUSE */
-        UP                      /* ASSIGNED and INUSE */
-    }           state;
-
-    struct c4_port_info *up;
-    void       *user;
-
-    struct work_struct ch_work;
-    struct mdesc *mdt;
-    struct mdesc *mdr;
-    struct mdesc *txd_irq_srv;
-    struct mdesc *txd_usr_add;
-
-#if 0
-    /*
-     * FUTURE CODE MIGHT SEPARATE TIMESLOT MAP SETUPS INTO SINGLE IOCTL and
-     * REMOVE MAPS FROM CHANNEL PARAMETER STRUCTURE
-     */
-    /*
-     * each byte in bitmask below represents one timeslot (bitmask[0] is for
-     * timeslot 0 and so on), each bit in the byte selects timeslot bits for
-     * this channel (0xff - whole timeslot, 0x7f - 56kbps mode)
-     */
-
-    u_int8_t    ts_bitmask[32];
-#endif
-    spinlock_t  ch_rxlock;
-    spinlock_t  ch_txlock;
-    atomic_t    tx_pending;
-
-    struct sbecom_chan_stats s;
-    struct sbecom_chan_param p;
-};
-typedef struct c4_chan_info mch_t;
-
-struct c4_port_info
-{
-
-    struct musycc_globalr *reg;
-    struct musycc_groupr *regram;
-    void       *regram_saved;   /* Original malloc value may have non-2KB
-                                 * boundary.  Need to save for use when
-                                 * freeing. */
-    struct s_comet_reg    *cometbase;
-    struct sbe_card_info *up;
-
-    /*
-     * The workqueue is used for TX restart of ONR'd channels when in
-     * Transparent mode.
-     */
-
-    struct workqueue_struct *wq_port;   /* chan restart work queue */
-    struct semaphore sr_sem_busy;       /* service request exclusion
-                                         * semaphore */
-    struct semaphore sr_sem_wait;       /* service request handshake
-                                         * semaphore */
-    u_int32_t   sr_last;
-    short       openchans;
-    char        portnum;
-    char        group_is_set;   /* GROUP_INIT command issued to MUSYCC,
-                                 * otherwise SET_CHAN Ioctl fails */
-
-    mch_t      *chan[MUSYCC_NCHANS];
-    struct sbecom_port_param p;
-
-    /*
-     * The MUSYCC timeslot mappings are maintained within the driver and are
-     * modified and reloaded as each of a group's channels are configured.
-     */
-    u_int8_t    tsm[32];        /* tsm (time slot map) */
-    int         fifomap[32];
-};
-typedef struct c4_port_info mpi_t;
-
-
-#define COMET_OFFSET(x) (0x80000+(x)*0x10000)
-#define EEPROM_OFFSET   0xC0000
-#define ISPLD_OFFSET    0xD0000
-
-/* iSPLD control chip registers */
-#define ISPLD_MCSR  0x0
-#define ISPLD_MCLK  0x1
-#define ISPLD_LEDS  0x2
-#define ISPLD_INTR  0x3
-#define ISPLD_MAX   0x3
-
-struct sbe_card_info
-{
-    struct musycc_globalr *reg;
-    struct musycc_groupr *regram;
-    u_int32_t  *iqd_p;          /* pointer to dword aligned interrupt queue
-                                 * descriptors */
-    void       *iqd_p_saved;    /* Original malloc value may have non-dword
-                                 * aligned boundary.  Need to save for use
-                                 * when freeing. */
-    unsigned int iqp_headx, iqp_tailx;
-
-    struct semaphore sem_wdbusy;/* watchdog exclusion semaphore */
-    struct watchdog wd;         /* statically allocated watchdog structure */
-    atomic_t    bh_pending;     /* bh queued, but not yet running */
-    u_int32_t   brd_id;         /* unique PCI ID */
-    u_int16_t   hdw_bid;      /* on/board hardware ID */
-    unsigned short wdcount;
-    unsigned char max_port;
-    unsigned char brdno;        /* our board number */
-    unsigned char wd_notify;
-#define WD_NOTIFY_1TX       1
-#define WD_NOTIFY_BUF       2
-#define WD_NOTIFY_ONR       4
-    enum                        /* state as regards interrupt processing */
-    {
-        C_INIT,                 /* of-board-address not configured or are in
-                                 * process of being removed, don't access
-                                 * hardware */
-        C_IDLE,                 /* off-board-addresses are configured, but
-                                 * don't service interrupts, just clear them
-                                 * from hardware */
-        C_RUNNING               /* life is good, service away */
-    }           state;
-
-    struct sbe_card_info *next;
-    u_int32_t  *eeprombase;     /* mapped address of board's EEPROM */
-    c4cpld_t   *cpldbase;       /* mapped address of board's CPLD hardware */
-    void       *hdw_info;
-#ifdef CONFIG_PROC_FS
-    struct proc_dir_entry *dir_dev;
-#endif
-
-    /* saved off interface assignments which bound a board */
-    hdlc_device *first_if;
-    hdlc_device *last_if;
-    short       first_channum, last_channum;
-
-    struct intlog
-    {
-        u_int32_t   this_status_new;
-        u_int32_t   last_status_new;
-        u_int32_t   drvr_intr_thcount;
-        u_int32_t   drvr_intr_bhcount;
-        u_int32_t   drvr_int_failure;
-    }           intlog;
-
-    mpi_t       port[MUSYCC_NPORTS];
-    char        devname[SBE_IFACETMPL_SIZE + 1];
-    atomic_t    tx_pending;
-    u_int32_t   alarmed[4];     /* dpm211 */
-
-#if defined(SBE_ISR_TASKLET)
-    struct tasklet_struct ci_musycc_isr_tasklet;
-#elif defined(SBE_ISR_IMMEDIATE)
-    struct tq_struct ci_musycc_isr_tq;
-#endif
-};
-typedef struct sbe_card_info ci_t;
-
-struct s_hdw_info
-{
-    u_int8_t    pci_busno;
-    u_int8_t    pci_slot;
-    u_int8_t    pci_pin[2];
-    u_int8_t    revid[2];
-    u_int8_t    mfg_info_sts;
-#define EEPROM_OK          0x00
-#define EEPROM_CRCERR      0x01
-    char        promfmt;        /* prom type, from sbe_promformat.h */
-
-    char        devname[SBE_IFACETMPL_SIZE];
-    struct pci_bus *bus;
-    struct net_device *ndev;
-    struct pci_dev *pdev[2];
-
-    unsigned long addr[2];
-    void __iomem *addr_mapped[2];
-    unsigned long len[2];
-
-    union
-    {
-        char        data[128];
-        FLD_TYPE1   pft1;       /* prom field, type #1 */
-        FLD_TYPE2   pft2;       /* prom field, type #2 */
-    }           mfg_info;
-};
-typedef struct s_hdw_info hdw_info_t;
-
-/*****************************************************************/
-
-struct c4_priv
-{
-    int         channum;
-    struct sbe_card_info *ci;
-};
-
-
-/*****************************************************************/
-
-extern ci_t *c4_list;
-
-mch_t      *c4_find_chan (int);
-int         c4_set_chan (int channum, struct sbecom_chan_param *);
-int         c4_get_chan (int channum, struct sbecom_chan_param *);
-int         c4_get_chan_stats (int channum, struct sbecom_chan_stats *);
-
-#endif                          /* _INC_PMCC4_PRIVATE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_sysdep.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_sysdep.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/pmcc4_sysdep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/pmcc4_sysdep.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-#ifndef _INC_PMCC4_SYSDEP_H_
-#define _INC_PMCC4_SYSDEP_H_
-
-/*-----------------------------------------------------------------------------
- * pmcc4_sysdep.h -
- *
- * Copyright (C) 2005  SBE, 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.
- */
-
-/* reduce multiple autoconf entries to a single definition */
-
-#ifdef CONFIG_SBE_PMCC4_HDLC_V7_MODULE
-#undef CONFIG_SBE_PMCC4_HDLC_V7
-#define CONFIG_SBE_PMCC4_HDLC_V7  1
-#endif
-
-#ifdef CONFIG_SBE_PMCC4_NCOMM_MODULE
-#undef CONFIG_SBE_PMCC4_NCOMM
-#define CONFIG_SBE_PMCC4_NCOMM  1
-#endif
-
-
-/* FLUSH MACROS - if using ioremap_nocache(), then these can be NOOPS,
- * otherwise a memory barrier needs to be inserted.
- */
-
-#define FLUSH_PCI_READ()     rmb()
-#define FLUSH_PCI_WRITE()    wmb()
-#define FLUSH_MEM_READ()     rmb()
-#define FLUSH_MEM_WRITE()    wmb()
-
-
-/*
- * System dependent callbacks routines, not inlined...
- * For inlined system dependent routines, see include/sbecom_inlinux_linux.h
- */
-
-/*
- * passes received memory token back to the system, <user> is parameter from
- * sd_new_chan() used to create the channel which the data arrived on
- */
-
-void sd_recv_consume(void *token, size_t len, void *user);
-
-void        sd_disable_xmit (void *user);
-void        sd_enable_xmit (void *user);
-int         sd_line_is_ok (void *user);
-void        sd_line_is_up (void *user);
-void        sd_line_is_down (void *user);
-int         sd_queue_stopped (void *user);
-
-#endif                          /*** _INC_PMCC4_SYSDEP_H_ ***/
-extern int  cxt1e1_log_level;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbe_bid.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbe_bid.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbe_bid.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbe_bid.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-#ifndef _INC_SBEBID_H_
-#define _INC_SBEBID_H_
-
-/*-----------------------------------------------------------------------------
- * sbe_bid.h -
- *
- * Copyright (C) 2004-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *
- *-----------------------------------------------------------------------------
- */
-
-#define SBE_BID_REG        0x00000000   /* Board ID Register */
-
-#define SBE_BID_256T3_E1         0x46   /* SBE wanPTMC-256T3 (E1 Version) */
-#define SBE_BID_256T3_T1         0x42   /* SBE wanPTMC-256T3 (T1 Version) */
-#define SBE_BID_2T3E3            0x43   /* SBE wanPMC-2T3E3 */
-#define SBE_BID_C1T3             0x45   /* SBE wanPMC-C1T3 */
-#define SBE_BID_C24TE1           0x47   /* SBE wanPTMC-C24TE1  */
-#define SBE_BID_C24TE1_RTM_24    0x48   /* C24TE1 RTM (24 Port) */
-#define SBE_BID_C24TE1_RTM_12    0x49   /* C24TE1 RTM (12 Port) */
-#define SBE_BID_C24TE1_RTM_12DSU 0x4A   /* C24TE1 RTM (12 Port/DSU) */
-#define SBE_BID_C24TE1_RTM_T3    0x4B   /* C24TE1 RTM (T3) */
-#define SBE_BID_C4T1E1           0x41   /* SBE wanPTMC-C4T1E1 */
-#define SBE_BID_HC4T1E1          0x44   /* SBE wanADAPT-HC4T1E1 */
-
-/* bogus temporary usage values */
-#define SBE_BID_PMC_C4T1E1       0xC4   /* SBE wanPMC-C4T1E1 (4 Port) */
-#define SBE_BID_PMC_C2T1E1       0xC2   /* SBE wanPMC-C2T1E1 (2 Port) */
-#define SBE_BID_PMC_C1T1E1       0xC1   /* SBE wanPMC-C1T1E1 (1 Port) */
-#define SBE_BID_PCI_C4T1E1       0x04   /* SBE wanPCI-C4T1E1 (4 Port) */
-#define SBE_BID_PCI_C2T1E1       0x02   /* SBE wanPCI-C2T1E1 (2 Port) */
-#define SBE_BID_PCI_C1T1E1       0x01   /* SBE wanPCI-C1T1E1 (1 Port) */
-
-#endif                          /*** _INC_SBEBID_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbecom_inline_linux.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbecom_inline_linux.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbecom_inline_linux.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbecom_inline_linux.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,193 +0,0 @@
-#ifndef _INC_SBECOM_INLNX_H_
-#define _INC_SBECOM_INLNX_H_
-
-/*-----------------------------------------------------------------------------
- * sbecom_inline_linux.h - SBE common Linux inlined routines
- *
- * Copyright (C) 2007  One Stop Systems, Inc.
- * Copyright (C) 2005  SBE, 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.
- *
- * For further information, contact via email: support@onestopsystems.com
- * One Stop Systems, Inc.  Escondido, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>       /* resolves kmalloc references */
-#include <linux/skbuff.h>       /* resolves skb references */
-#include <linux/netdevice.h>    /* resolves dev_kree_skb_any */
-#include <asm/byteorder.h>      /* resolves cpu_to_le32 */
-
-/* forward reference */
-u_int32_t   pci_read_32 (u_int32_t *p);
-void        pci_write_32 (u_int32_t *p, u_int32_t v);
-
-
-/*
- * system dependent callbacks
- */
-
-/****************/
-/* memory token */
-/****************/
-
-static inline void *
-OS_mem_token_alloc (size_t size)
-{
-    struct sk_buff *skb;
-
-    skb = dev_alloc_skb (size);
-    if (!skb)
-    {
-        //pr_warning("no mem in OS_mem_token_alloc !\n");
-        return NULL;
-    }
-    return skb;
-}
-
-
-static inline void
-OS_mem_token_free (void *token)
-{
-    dev_kfree_skb_any (token);
-}
-
-
-static inline void
-OS_mem_token_free_irq (void *token)
-{
-    dev_kfree_skb_irq (token);
-}
-
-
-static inline void *
-OS_mem_token_data (void *token)
-{
-    return ((struct sk_buff *) token)->data;
-}
-
-
-static inline void *
-OS_mem_token_next (void *token)
-{
-    return NULL;
-}
-
-
-static inline int
-OS_mem_token_len (void *token)
-{
-    return ((struct sk_buff *) token)->len;
-}
-
-
-static inline int
-OS_mem_token_tlen (void *token)
-{
-    return ((struct sk_buff *) token)->len;
-}
-
-
-/***************************************/
-/* virtual to physical addr conversion */
-/***************************************/
-
-static inline u_long
-OS_phystov (void *addr)
-{
-    return (u_long) __va (addr);
-}
-
-
-static inline u_long
-OS_vtophys (void *addr)
-{
-    return __pa (addr);
-}
-
-
-/**********/
-/* semops */
-/**********/
-
-void        OS_sem_init (void *, int);
-
-
-static inline void
-OS_sem_free (void *sem)
-{
-    /*
-     * NOOP - since semaphores structures predeclared w/in structures, no
-     * longer malloc'd
-     */
-}
-
-#define SD_SEM_TAKE(sem,desc)  down(sem)
-#define SD_SEM_GIVE(sem)       up(sem)
-#define SEM_AVAILABLE     1
-#define SEM_TAKEN         0
-
-
-/**********************/
-/* watchdog functions */
-/**********************/
-
-struct watchdog
-{
-    struct timer_list h;
-    struct work_struct work;
-    void       *softc;
-    void        (*func) (void *softc);
-    int         ticks;
-    int         init_tq;
-};
-
-
-static inline int
-OS_start_watchdog (struct watchdog *wd)
-{
-    wd->h.expires = jiffies + wd->ticks;
-    add_timer (&wd->h);
-    return 0;
-}
-
-
-static inline int
-OS_stop_watchdog (struct watchdog *wd)
-{
-    del_timer_sync (&wd->h);
-    return 0;
-}
-
-
-static inline int
-OS_free_watchdog (struct watchdog *wd)
-{
-    OS_stop_watchdog (wd);
-    kfree(wd);
-    return 0;
-}
-
-
-/* sleep in microseconds */
-void        OS_uwait (int usec, char *description);
-void        OS_uwait_dummy (void);
-
-
-/* watchdog functions */
-int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *ci, int usec);
-
-
-#endif                          /*** _INC_SBECOM_INLNX_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbecrc.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbecrc.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbecrc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbecrc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/*   Based on "File Verification Using CRC" by Mark R. Nelson in Dr. Dobbs'
- *   Journal, May 1992, pp. 64-67.  This algorithm generates the same CRC
- *   values as ZMODEM and PKZIP
- *
- * Copyright (C) 2002-2005  SBE, 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/types.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "sbe_promformat.h"
-
-/* defines */
-#define CRC32_POLYNOMIAL                0xEDB88320L
-#define CRC_TABLE_ENTRIES                       256
-
-
-
-static      u_int32_t crcTableInit;
-
-#ifdef STATIC_CRC_TABLE
-static u_int32_t CRCTable[CRC_TABLE_ENTRIES];
-
-#endif
-
-
-/***************************************************************************
-*
-* genCrcTable - fills in CRCTable, as used by sbeCrc()
-*
-* RETURNS: N/A
-*
-* ERRNO: N/A
-***************************************************************************/
-
-static void
-genCrcTable(u_int32_t *CRCTable)
-{
-	int         ii, jj;
-	u_int32_t      crc;
-
-	for (ii = 0; ii < CRC_TABLE_ENTRIES; ii++) {
-		crc = ii;
-		for (jj = 8; jj > 0; jj--) {
-			if (crc & 1)
-				crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
-			else
-				crc >>= 1;
-		}
-		CRCTable[ii] = crc;
-	}
-
-	crcTableInit++;
-}
-
-
-/***************************************************************************
-*
-* sbeCrc - generates a CRC on a given buffer, and initial CRC
-*
-* This routine calculates the CRC for a buffer of data using the
-* table lookup method. It accepts an original value for the crc,
-* and returns the updated value. This permits "catenation" of
-* discontiguous buffers. An original value of 0 for the "first"
-* buffer is the norm.
-*
-* Based on "File Verification Using CRC" by Mark R. Nelson in Dr. Dobb's
-* Journal, May 1992, pp. 64-67.  This algorithm generates the same CRC
-* values as ZMODEM and PKZIP.
-*
-* RETURNS: calculated crc of block
-*
-*/
-
-void
-sbeCrc(u_int8_t *buffer,          /* data buffer to crc */
-	u_int32_t count,           /* length of block in bytes */
-	u_int32_t initialCrc,      /* starting CRC */
-	u_int32_t *result)
-{
-	u_int32_t     *tbl = NULL;
-	u_int32_t      temp1, temp2, crc;
-
-	/*
-	* if table not yet created, do so. Don't care about "extra" time
-	* checking this every time sbeCrc() is called, since CRC calculations
-	* are already time consuming
-	*/
-	if (!crcTableInit) {
-#ifdef STATIC_CRC_TABLE
-		tbl = &CRCTable;
-		genCrcTable(tbl);
-#else
-		tbl = kzalloc(CRC_TABLE_ENTRIES * sizeof(u_int32_t),
-			      GFP_KERNEL);
-		if (!tbl) {
-			*result = 0;   /* dummy up return value due to malloc
-					* failure */
-			return;
-		}
-		genCrcTable(tbl);
-#endif
-	}
-	/* inverting bits makes ZMODEM & PKZIP compatible */
-	crc = initialCrc ^ 0xFFFFFFFFL;
-
-	while (count-- != 0) {
-		temp1 = (crc >> 8) & 0x00FFFFFFL;
-		temp2 = tbl[((int) crc ^ *buffer++) & 0xff];
-		crc = temp1 ^ temp2;
-	}
-
-	crc ^= 0xFFFFFFFFL;
-
-	*result = crc;
-
-#ifndef STATIC_CRC_TABLE
-	crcTableInit = 0;
-	kfree(tbl);
-#endif
-}
-
-/*** End-of-File ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeid.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeid.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeid.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/* Copyright (C) 2005  SBE, 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/types.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "libsbew.h"
-#include "pmcc4_private.h"
-#include "pmcc4.h"
-#include "sbe_bid.h"
-
-char       *
-sbeid_get_bdname(ci_t *ci)
-{
-	char       *np = NULL;
-
-	switch (ci->brd_id) {
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
-		np = "wanPTMC-256T3 <E1>";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
-		np = "wanPTMC-256T3 <T1>";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
-		np = "wanPMC-C4T1E1";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
-		np = "wanPMC-C2T1E1";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
-		np = "wanPMC-C1T1E1";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
-		np = "wanPCI-C4T1E1";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
-		np = "wanPCI-C2T1E1";
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
-		np = "wanPCI-C1T1E1";
-		break;
-	default:
-		/*** np = "<unknown>";  ***/
-		np = "wanPCI-CxT1E1";
-		break;
-	}
-
-	return np;
-}
-
-
-/* given the presetting of brd_id, set the corresponding hdw_id */
-
-void
-sbeid_set_hdwbid(ci_t *ci)
-{
-	/*
-	 * set SBE's unique hardware identification (for legacy boards might not
-	 * have this register implemented)
-	 */
-
-	switch (ci->brd_id) {
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
-		ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1
-						 * Version) */
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
-		ci->hdw_bid = SBE_BID_256T3_T1; /* 0x42 - SBE wanPTMC-256T3 (T1
-						 * Version) */
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
-		/*
-		 * This Board ID is a generic identification.  Use the found number
-		 * of ports to further define this hardware.
-		 */
-		switch (ci->max_port) {
-		default:                    /* shouldn't need a default, but have one
-					     * anyway */
-		case 4:
-			ci->hdw_bid = SBE_BID_PMC_C4T1E1;   /* 0xC4 - SBE wanPMC-C4T1E1 */
-			break;
-		case 2:
-			ci->hdw_bid = SBE_BID_PMC_C2T1E1;   /* 0xC2 - SBE wanPMC-C2T1E1 */
-			ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1);
-			break;
-		case 1:
-			ci->hdw_bid = SBE_BID_PMC_C1T1E1;   /* 0xC1 - SBE wanPMC-C1T1E1 */
-			ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1);
-			break;
-		}
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
-		ci->hdw_bid = SBE_BID_PMC_C2T1E1;       /* 0xC2 - SBE wanPMC-C2T1E1 */
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
-		ci->hdw_bid = SBE_BID_PMC_C1T1E1;       /* 0xC1 - SBE wanPMC-C1T1E1 */
-		break;
-#ifdef SBE_PMCC4_ENABLE
-		/*
-		 * This case is entered as a result of the inability to obtain the
-		 * <bid> from the board's EEPROM.  Assume a PCI board and set
-		 * <hdsbid> according to the number ofr found ports.
-		 */
-	case 0:
-		/* start by assuming 4-port for ZERO casing */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
-		/* drop thru to set hdw_bid and alternate PCI CxT1E1 settings */
-#endif
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
-		/*
-		 * This Board ID is a generic identification.  Use the number of
-		 * found ports to further define this hardware.
-		 */
-		switch (ci->max_port) {
-		default:                    /* shouldn't need a default, but have one
-					     * anyway */
-		case 4:
-			ci->hdw_bid = SBE_BID_PCI_C4T1E1;   /* 0x04 - SBE wanPCI-C4T1E1 */
-			break;
-		case 2:
-			ci->hdw_bid = SBE_BID_PCI_C2T1E1;   /* 0x02 - SBE wanPCI-C2T1E1 */
-			ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1);
-			break;
-		case 1:
-			ci->hdw_bid = SBE_BID_PCI_C1T1E1;   /* 0x01 - SBE wanPCI-C1T1E1 */
-			ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1);
-			break;
-		}
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
-		ci->hdw_bid = SBE_BID_PCI_C2T1E1;       /* 0x02 - SBE wanPCI-C2T1E1 */
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
-		ci->hdw_bid = SBE_BID_PCI_C1T1E1;       /* 0x01 - SBE wanPCI-C1T1E1 */
-		break;
-	default:
-		/*** bid = "<unknown>";  ***/
-		ci->hdw_bid = SBE_BID_PMC_C4T1E1;       /* 0x41 - SBE wanPTMC-C4T1E1 */
-		break;
-	}
-}
-
-/* given the presetting of hdw_bid, set the corresponding brd_id */
-
-void
-sbeid_set_bdtype(ci_t *ci)
-{
-	/* set SBE's unique PCI VENDOR/DEVID */
-	switch (ci->hdw_bid) {
-	case SBE_BID_C1T3:      /* SBE wanPMC-C1T3 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3);
-		break;
-	case SBE_BID_C24TE1:            /* SBE wanPTMC-C24TE1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1);
-		break;
-	case SBE_BID_256T3_E1:          /* SBE wanPTMC-256T3 E1 Version */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1);
-		break;
-	case SBE_BID_256T3_T1:          /* SBE wanPTMC-256T3 T1 Version */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1);
-		break;
-	case SBE_BID_PMC_C4T1E1:        /* 0xC4 - SBE wanPMC-C4T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1);
-		break;
-	case SBE_BID_PMC_C2T1E1:        /* 0xC2 - SBE wanPMC-C2T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1);
-		break;
-	case SBE_BID_PMC_C1T1E1:        /* 0xC1 - SBE wanPMC-C1T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1);
-		break;
-	case SBE_BID_PCI_C4T1E1:        /* 0x04 - SBE wanPCI-C4T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
-		break;
-	case SBE_BID_PCI_C2T1E1:        /* 0x02 - SBE wanPCI-C2T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1);
-		break;
-	case SBE_BID_PCI_C1T1E1:        /* 0x01 - SBE wanPCI-C1T1E1 */
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1);
-		break;
-
-	default:
-		/*** hdw_bid = "<unknown>";  ***/
-		ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
-		break;
-	}
-}
-
-
-/***  End-of-File  ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeproc.c linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeproc.c
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeproc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeproc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,219 +0,0 @@
-/* Copyright (C) 2004-2005  SBE, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include "pmcc4_sysdep.h"
-#include "sbecom_inline_linux.h"
-#include "pmcc4_private.h"
-#include "sbeproc.h"
-
-extern void sbecom_get_brdinfo(ci_t *, struct sbe_brd_info *, u_int8_t *);
-extern struct s_hdw_info hdw_info[MAX_BOARDS];
-
-void sbecom_proc_brd_cleanup(ci_t *ci)
-{
-	if (ci->dir_dev) {
-		char dir[7 + SBE_IFACETMPL_SIZE + 1];
-		snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
-		remove_proc_entry("info", ci->dir_dev);
-		remove_proc_entry(dir, NULL);
-		ci->dir_dev = NULL;
-	}
-}
-
-static void sbecom_proc_get_brdinfo(ci_t *ci, struct sbe_brd_info *bip)
-{
-	hdw_info_t *hi = &hdw_info[ci->brdno];
-	u_int8_t *bsn = NULL;
-
-	switch (hi->promfmt)
-	{
-	case PROM_FORMAT_TYPE1:
-		bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
-		break;
-	case PROM_FORMAT_TYPE2:
-		bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
-		break;
-	}
-
-	sbecom_get_brdinfo (ci, bip, bsn);
-
-	pr_devel(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
-		 bip->first_iname, bip->first_iname,
-		 bip->last_iname, bip->last_iname);
-}
-
-/*
- * Describe the driver state through /proc
- */
-static int sbecom_proc_get_sbe_info(struct seq_file *m, void *v)
-{
-	ci_t       *ci = m->private;
-	char       *spd;
-	struct sbe_brd_info *bip;
-
-	bip = kzalloc(sizeof(struct sbe_brd_info), GFP_KERNEL | GFP_DMA);
-	if (!bip)
-		return -ENOMEM;
-
-	pr_devel(">> sbecom_proc_get_sbe_info: entered\n");
-
-	sbecom_proc_get_brdinfo(ci, bip);
-
-	seq_puts(m, "Board Type:    ");
-	switch (bip->brd_id) {
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3):
-		seq_puts(m, "wanPMC-C1T3");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
-		seq_puts(m, "wanPTMC-256T3 <E1>");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
-		seq_puts(m, "wanPTMC-256T3 <T1>");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1):
-		seq_puts(m, "wanPTMC-C24TE1");
-		break;
-
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
-		seq_puts(m, "wanPMC-C4T1E1");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
-		seq_puts(m, "wanPMC-C2T1E1");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
-		seq_puts(m, "wanPMC-C1T1E1");
-		break;
-
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
-		seq_puts(m, "wanPCI-C4T1E1");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
-		seq_puts(m, "wanPCI-C2T1E1");
-		break;
-	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
-		seq_puts(m, "wanPCI-C1T1E1");
-		break;
-
-	default:
-		seq_puts(m, "unknown");
-		break;
-	}
-
-	seq_printf(m, "  [%08X]\n", bip->brd_id);
-
-	seq_printf(m, "Board Number:  %d\n", bip->brdno);
-	seq_printf(m, "Hardware ID:   0x%02X\n", ci->hdw_bid);
-	seq_printf(m, "Board SN:      %06X\n", bip->brd_sn);
-	seq_printf(m, "Board MAC:     %pMF\n", bip->brd_mac_addr);
-	seq_printf(m, "Ports:         %d\n", ci->max_port);
-	seq_printf(m, "Channels:      %d\n", bip->brd_chan_cnt);
-#if 1
-	seq_printf(m, "Interface:     %s -> %s\n",
-		   bip->first_iname, bip->last_iname);
-#else
-	seq_printf(m, "Interface:     <not available> 1st %p lst %p\n",
-		   bip->first_iname, bip->last_iname);
-#endif
-
-	switch (bip->brd_pci_speed) {
-	case BINFO_PCI_SPEED_33:
-		spd = "33Mhz";
-		break;
-	case BINFO_PCI_SPEED_66:
-		spd = "66Mhz";
-		break;
-	default:
-		spd = "<not available>";
-		break;
-	}
-	seq_printf(m, "PCI Bus Speed: %s\n", spd);
-
-#ifdef SBE_PMCC4_ENABLE
-	{
-		extern int cxt1e1_max_mru;
-#if 0
-		extern int max_chans_used;
-		extern int cxt1e1_max_mtu;
-#endif
-		extern int max_rxdesc_used, max_txdesc_used;
-
-		seq_printf(m, "\ncxt1e1_max_mru:         %d\n", cxt1e1_max_mru);
-#if 0
-		seq_printf(m, "\nmax_chans_used:  %d\n", max_chans_used);
-		seq_printf(m, "cxt1e1_max_mtu:         %d\n", cxt1e1_max_mtu);
-#endif
-		seq_printf(m, "max_rxdesc_used: %d\n", max_rxdesc_used);
-		seq_printf(m, "max_txdesc_used: %d\n", max_txdesc_used);
-	}
-#endif
-
-	kfree(bip);
-
-	pr_devel(">> proc_fs: finished\n");
-	return 0;
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int sbecom_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, sbecom_proc_get_sbe_info, PDE_DATA(inode));
-}
-
-static const struct file_operations sbecom_proc_fops = {
-	.open		= sbecom_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * Initialize the /proc subsystem for the specific SBE driver
- */
-int __init sbecom_proc_brd_init(ci_t *ci)
-{
-	char dir[7 + SBE_IFACETMPL_SIZE + 1];
-
-	snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
-	ci->dir_dev = proc_mkdir(dir, NULL);
-	if (!ci->dir_dev) {
-		pr_err("Unable to create directory /proc/driver/%s\n", ci->devname);
-		goto fail;
-	}
-
-	if (!proc_create_data("info", S_IFREG | S_IRUGO, ci->dir_dev,
-			      &sbecom_proc_fops, ci)) {
-		pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname);
-		goto fail;
-	}
-	return 0;
-
-fail:
-	sbecom_proc_brd_cleanup(ci);
-	return 1;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeproc.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeproc.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbeproc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbeproc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-#ifndef _INC_SBEPROC_H_
-#define _INC_SBEPROC_H_
-
-/*-----------------------------------------------------------------------------
- * sbeproc.h -
- *
- * Copyright (C) 2004-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *-----------------------------------------------------------------------------
- */
-
-
-#ifdef CONFIG_PROC_FS
-void        sbecom_proc_brd_cleanup (ci_t *);
-int __init  sbecom_proc_brd_init (ci_t *);
-
-#else
-
-static inline void sbecom_proc_brd_cleanup(ci_t *ci)
-{
-}
-
-static inline int __init sbecom_proc_brd_init(ci_t *ci)
-{
-	return 0;
-}
-
-#endif                          /*** CONFIG_PROC_FS ***/
-
-#endif                          /*** _INC_SBEPROC_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbe_promformat.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbe_promformat.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbe_promformat.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbe_promformat.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-#ifndef _INC_SBE_PROMFORMAT_H_
-#define _INC_SBE_PROMFORMAT_H_
-
-/*-----------------------------------------------------------------------------
- * sbe_promformat.h - Contents of seeprom used by dvt and manufacturing tests
- *
- * Copyright (C) 2002-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *
- *-----------------------------------------------------------------------------
- */
-
-
-/***
- *  PMCC4 SAMPLE EEPROM IMAGE
- *
- *  eeprom[00]:  01 11 76 07  01 00 a0 d6
- *  eeprom[08]:  22 34 56 3e  5b c1 1c 3e
- *  eeprom[16]:  5b e1 b6 00  00 00 01 00
- *  eeprom[24]:  00 08 46 d3  7b 5e a8 fb
- *  eeprom[32]:  f7 ef df bf  7f 55 00 01
- *  eeprom[40]:  02 04 08 10  20 40 80 ff
- *  eeprom[48]:  fe fd fb f7  ef df bf 7f
- *
- ***/
-
-
-/*------------------------------------------------------------------------
- *          Type 1 Format
- * byte:
- * 0    1  2    3  4      5   6   7    8  9  10    11 12 13 14    15 16 17 18
- * -------------------------------------------------------------------------
- * 01   11 76   SS SS     00 0A D6 <SERIAL NUM>    <Create TIME>  <Heatrun TIME>
- *       SBE    SUB       SERIAL #    (BCD)         (time_t)       (time_t)
- *       ID     VENDOR                              (format)       (format)
- *
- *  19 20 21 22    23 24 25 26
- *  Heat Run        Heat Run
- *  Iterations      Errors
- *------------------------------------------------------------------------
- *
- *
- *
- *           Type 2 Format  - Added length, CRC in fixed position
- * byte:
- * 0    1  2       3  4  5  6      7  8        9  10     11 12 13 14 15 16
- * -------------------------------------------------------------------------
- * 02   00 1A      CC CC CC CC    11  76       07 03    00 0A D6 <SERIAL NUM>
- *      Payload    SBE Crc32      SUB System   System    SERIAL/MAC
- *      Length                    VENDOR ID    ID
- *
- *  17 18 19 20     21 22 23 24     25 26 27 28    29 39 31 32
- * --------------------------------------------------------------------------
- *  <Create TIME>   <Heatrun TIME>   Heat Run      Heat Run
- *  (time_t)         (time_t)        Iterations    Errors
- *
- */
-
-#define STRUCT_OFFSET(type, symbol)  ((long)&(((type *)0)->symbol))
-
-/*------------------------------------------------------------------------
- *  Historically different Prom format types.
- *
- *  For diagnostic and failure purposes, do not create a type 0x00 or a
- *  type 0xff
- *------------------------------------------------------------------------
- */
-#define PROM_FORMAT_Unk   (-1)
-#define PROM_FORMAT_TYPE1   1
-#define PROM_FORMAT_TYPE2   2
-
-
-/****** bit fields  for a type 1 formatted seeprom **************************/
-    typedef struct
-    {
-        char        type;       /* 0x00 */
-        char        Id[2];      /* 0x01-0x02 */
-        char        SubId[2];   /* 0x03-0x04 */
-        char        Serial[6];  /* 0x05-0x0a */
-        char        CreateTime[4];      /* 0x0b-0x0e */
-        char        HeatRunTime[4];     /* 0x0f-0x12 */
-        char        HeatRunIterations[4];       /* 0x13-0x16 */
-        char        HeatRunErrors[4];   /* 0x17-0x1a */
-        char        Crc32[4];   /* 0x1b-0x1e */
-    }           FLD_TYPE1;
-
-
-/****** bit fields  for a type 2 formatted seeprom **************************/
-    typedef struct
-    {
-        char        type;       /* 0x00 */
-        char        length[2];  /* 0x01-0x02 */
-        char        Crc32[4];   /* 0x03-0x06 */
-        char        Id[2];      /* 0x07-0x08 */
-        char        SubId[2];   /* 0x09-0x0a */
-        char        Serial[6];  /* 0x0b-0x10 */
-        char        CreateTime[4];      /* 0x11-0x14 */
-        char        HeatRunTime[4];     /* 0x15-0x18 */
-        char        HeatRunIterations[4];       /* 0x19-0x1c */
-        char        HeatRunErrors[4];   /* 0x1d-0x20 */
-    }           FLD_TYPE2;
-
-
-
-/***** this union allows us to access the seeprom as an array of bytes ***/
-/***** or as individual fields                                         ***/
-
-#define SBE_EEPROM_SIZE    128
-#define SBE_MFG_INFO_SIZE  sizeof(FLD_TYPE2)
-
-    typedef union
-    {
-        char        bytes[128];
-        FLD_TYPE1   fldType1;
-        FLD_TYPE2   fldType2;
-    }           PROMFORMAT;
-
-#endif                          /*** _INC_SBE_PROMFORMAT_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbew_ioc.h linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbew_ioc.h
--- linux-libre-3.16-gnu/drivers/staging/cxt1e1/sbew_ioc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/cxt1e1/sbew_ioc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-#ifndef _INC_SBEWIOC_H_
-#define _INC_SBEWIOC_H_
-
-/*-----------------------------------------------------------------------------
- * sbew_ioc.h -
- *
- * Copyright (C) 2002-2005  SBE, 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.
- *
- * For further information, contact via email: support@sbei.com
- * SBE, Inc.  San Ramon, California  U.S.A.
- *
- *-----------------------------------------------------------------------------
- */
-
-#include <linux/ioctl.h>
-
-#define SBE_LOCKFILE   "/tmp/.sbewan.LCK"
-
-#define SBE_IOC_COOKIE     0x19780926
-#define SBE_IOC_MAGIC      ('s')
-
-/* IOW write - data has to go into driver from application */
-/* IOR read - data has to be returned to application from driver */
-
-/*
- * Note: for an IOWR Ioctl, the read and write data do not have to
- * be the same size, but the entity declared within the IOC must be
- * the larger of the two.
- */
-
-#define SBE_IOC_LOGLEVEL       _IOW(SBE_IOC_MAGIC, 0x00, int)
-#define SBE_IOC_CHAN_NEW       _IOW(SBE_IOC_MAGIC, 0x01, int)    /* unused */
-#define SBE_IOC_CHAN_UP        _IOW(SBE_IOC_MAGIC, 0x02, int)    /* unused */
-#define SBE_IOC_CHAN_DOWN      _IOW(SBE_IOC_MAGIC, 0x03, int)    /* unused */
-#define SBE_IOC_CHAN_GET       _IOWR(SBE_IOC_MAGIC, 0x04, struct sbecom_chan_param)
-#define SBE_IOC_CHAN_SET       _IOW(SBE_IOC_MAGIC, 0x05, struct sbecom_chan_param)
-#define SBE_IOC_CHAN_GET_STAT  _IOWR(SBE_IOC_MAGIC, 0x06, struct sbecom_chan_stats)
-#define SBE_IOC_CHAN_DEL_STAT  _IOW(SBE_IOC_MAGIC, 0x07, int)
-#define SBE_IOC_PORTS_ENABLE   _IOW(SBE_IOC_MAGIC, 0x0A, int)
-#define SBE_IOC_PORT_GET       _IOWR(SBE_IOC_MAGIC, 0x0C, struct sbecom_port_param)
-#define SBE_IOC_PORT_SET       _IOW(SBE_IOC_MAGIC, 0x0D, struct sbecom_port_param)
-#define SBE_IOC_READ_VEC       _IOWR(SBE_IOC_MAGIC, 0x10, struct sbecom_wrt_vec)
-#define SBE_IOC_WRITE_VEC      _IOWR(SBE_IOC_MAGIC, 0x11, struct sbecom_wrt_vec)
-#define SBE_IOC_GET_SN         _IOR(SBE_IOC_MAGIC, 0x12, u_int32_t)
-#define SBE_IOC_RESET_DEV      _IOW(SBE_IOC_MAGIC, 0x13, int)
-#define SBE_IOC_FRAMER_GET     _IOWR(SBE_IOC_MAGIC, 0x14, struct sbecom_framer_param)
-#define SBE_IOC_FRAMER_SET     _IOW(SBE_IOC_MAGIC, 0x15, struct sbecom_framer_param)
-#define SBE_IOC_CARD_GET       _IOR(SBE_IOC_MAGIC, 0x20, struct sbecom_card_param)
-#define SBE_IOC_CARD_SET       _IOW(SBE_IOC_MAGIC, 0x21, struct sbecom_card_param)
-#define SBE_IOC_CARD_GET_STAT  _IOR(SBE_IOC_MAGIC, 0x22, struct temux_card_stats)
-#define SBE_IOC_CARD_DEL_STAT  _IO(SBE_IOC_MAGIC,  0x23)
-#define SBE_IOC_CARD_CHAN_STAT _IOR(SBE_IOC_MAGIC, 0x24, struct sbecom_chan_stats)
-#define SBE_IOC_CARD_BLINK     _IOW(SBE_IOC_MAGIC, 0x30, int)
-#define SBE_IOC_DRVINFO_GET    _IOWR(SBE_IOC_MAGIC, 0x31, struct sbe_drv_info)
-#define SBE_IOC_BRDINFO_GET    _IOR(SBE_IOC_MAGIC, 0x32, struct sbe_brd_info)
-#define SBE_IOC_IID_GET        _IOWR(SBE_IOC_MAGIC, 0x33, struct sbe_iid_info)
-#define SBE_IOC_BRDADDR_GET    _IOWR(SBE_IOC_MAGIC, 0x34, struct sbe_brd_addr)
-
-#ifdef NOT_YET_COMMON
-#define SBE_IOC_TSIOC_GET      _IOWR(SBE_IOC_MAGIC, 0x16, struct wanc1t3_ts_param)
-#define SBE_IOC_TSIOC_SET      _IOW(SBE_IOC_MAGIC, 0x17, struct wanc1t3_ts_param)
-#endif
-
-/*
- * Restrict SBE_IOC_WRITE_VEC & READ_VEC to a single parameter pair, application
- * then must issue multiple Ioctls for large blocks of contiguous data.
- */
-
-#define SBE_IOC_MAXVEC    1
-
-#endif                          /*** _INC_SBEWIOC_H_ ***/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgap/dgap.c linux-libre-3.17-rc7-gnu/drivers/staging/dgap/dgap.c
--- linux-libre-3.16-gnu/drivers/staging/dgap/dgap.c	2014-08-07 04:58:35.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgap/dgap.c	2014-09-28 21:41:07.000000000 -0400
@@ -70,14 +70,14 @@ MODULE_SUPPORTED_DEVICE("dgap");
 
 static int dgap_start(void);
 static void dgap_init_globals(void);
-static int dgap_found_board(struct pci_dev *pdev, int id);
+static struct board_t *dgap_found_board(struct pci_dev *pdev, int id,
+					int boardnum);
 static void dgap_cleanup_board(struct board_t *brd);
 static void dgap_poll_handler(ulong dummy);
-static int dgap_init_pci(void);
 static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void dgap_remove_one(struct pci_dev *dev);
-static int dgap_probe1(struct pci_dev *pdev, int card_type);
 static int dgap_do_remap(struct board_t *brd);
+static void dgap_release_remap(struct board_t *brd);
 static irqreturn_t dgap_intr(int irq, void *voidbrd);
 
 static int dgap_tty_open(struct tty_struct *tty, struct file *file);
@@ -86,12 +86,12 @@ static int dgap_block_til_ready(struct t
 				struct channel_t *ch);
 static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
 				unsigned long arg);
-static int dgap_tty_digigeta(struct tty_struct *tty,
-				struct digi_t __user *retinfo);
-static int dgap_tty_digiseta(struct tty_struct *tty,
-				struct digi_t __user *new_info);
+static int dgap_tty_digigeta(struct channel_t *ch, struct digi_t __user *retinfo);
+static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd,
+			     struct un_t *un, struct digi_t __user *new_info);
 static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd,
+				  struct un_t *un, int __user *new_info);
 static int dgap_tty_write_room(struct tty_struct *tty);
 static int dgap_tty_chars_in_buffer(struct tty_struct *tty);
 static void dgap_tty_start(struct tty_struct *tty);
@@ -102,14 +102,14 @@ static void dgap_tty_flush_chars(struct
 static void dgap_tty_flush_buffer(struct tty_struct *tty);
 static void dgap_tty_hangup(struct tty_struct *tty);
 static int dgap_wait_for_drain(struct tty_struct *tty);
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command,
-				unsigned int __user *value);
+static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, struct un_t *un,
+			       unsigned int command, unsigned int __user *value);
 static int dgap_get_modem_info(struct channel_t *ch,
 				unsigned int __user *value);
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty,
-				int __user *new_info);
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty,
-				int __user *retinfo);
+static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd,
+				      struct un_t *un, int __user *new_info);
+static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un,
+				      int __user *retinfo);
 static int dgap_tty_tiocmget(struct tty_struct *tty);
 static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set,
 				unsigned int clear);
@@ -123,8 +123,10 @@ static int dgap_tty_put_char(struct tty_
 static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
 
 static int dgap_tty_register(struct board_t *brd);
+static void dgap_tty_unregister(struct board_t *brd);
 static int dgap_tty_init(struct board_t *);
-static void dgap_tty_uninit(struct board_t *);
+static void dgap_tty_free(struct board_t *);
+static void dgap_cleanup_tty(struct board_t *);
 static void dgap_carrier(struct channel_t *ch);
 static void dgap_input(struct channel_t *ch);
 
@@ -139,7 +141,7 @@ static void dgap_cmdb(struct channel_t *
 			u8 byte2, uint ncmds);
 static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds);
 static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
-static int dgap_param(struct tty_struct *tty);
+static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type);
 static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
 				unsigned char *fbuf, int *len);
 static uint dgap_get_custom_baud(struct channel_t *ch);
@@ -148,9 +150,8 @@ static void dgap_firmware_reset_port(str
 /*
  * Function prototypes from dgap_parse.c.
  */
-static int dgap_gettok(char **in, struct cnode *p);
+static int dgap_gettok(char **in);
 static char *dgap_getword(char **in);
-static struct cnode *dgap_newnode(int t);
 static int dgap_checknode(struct cnode *p);
 static void dgap_err(char *s);
 
@@ -175,7 +176,7 @@ static void dgap_remove_tty_sysfs(struct
 /*
  * Function prototypes from dgap_parse.h
  */
-static int dgap_parsefile(char **in, int remove);
+static int dgap_parsefile(char **in);
 static struct cnode *dgap_find_config(int type, int bus, int slot);
 static uint dgap_config_get_num_prts(struct board_t *bd);
 static char *dgap_create_config_string(struct board_t *bd, char *string);
@@ -188,15 +189,18 @@ static void dgap_do_fep_load(struct boar
 #ifdef DIGI_CONCENTRATORS_SUPPORTED
 static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len);
 #endif
-static int dgap_after_config_loaded(int board);
-static int dgap_finalize_board_init(struct board_t *brd);
+static int dgap_alloc_flipbuf(struct board_t *brd);
+static void dgap_free_flipbuf(struct board_t *brd);
+static int dgap_request_irq(struct board_t *brd);
+static void dgap_free_irq(struct board_t *brd);
 
 static void dgap_get_vpd(struct board_t *brd);
 static void dgap_do_reset_board(struct board_t *brd);
 static int dgap_test_bios(struct board_t *brd);
 static int dgap_test_fep(struct board_t *brd);
 static int dgap_tty_register_ports(struct board_t *brd);
-static int dgap_firmware_load(struct pci_dev *pdev, int card_type);
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
+			      struct board_t *brd);
 
 static void dgap_cleanup_module(void);
 
@@ -212,9 +216,7 @@ static const struct file_operations dgap
 static uint dgap_numboards;
 static struct board_t *dgap_board[MAXBOARDS];
 static ulong dgap_poll_counter;
-static char *dgap_config_buf;
 static int dgap_driver_state = DRIVER_INITIALIZED;
-static wait_queue_head_t dgap_dl_wait;
 static int dgap_poll_tick = 20;	/* Poll interval - 20 ms */
 
 static struct class *dgap_class;
@@ -474,7 +476,7 @@ static int dgap_init_module(void)
 	if (rc)
 		return rc;
 
-	rc = dgap_init_pci();
+	rc = pci_register_driver(&dgap_driver);
 	if (rc)
 		goto err_cleanup;
 
@@ -558,17 +560,10 @@ failed_class:
 	return rc;
 }
 
-/*
- * Register pci driver, and return how many boards we have.
- */
-static int dgap_init_pci(void)
-{
-	return pci_register_driver(&dgap_driver);
-}
-
 static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int rc;
+	struct board_t *brd;
 
 	if (dgap_numboards >= MAXBOARDS)
 		return -EPERM;
@@ -577,17 +572,57 @@ static int dgap_init_one(struct pci_dev
 	if (rc)
 		return -EIO;
 
-	rc = dgap_probe1(pdev, ent->driver_data);
+	brd = dgap_found_board(pdev, ent->driver_data, dgap_numboards);
+	if (IS_ERR(brd))
+		return PTR_ERR(brd);
+
+	rc = dgap_firmware_load(pdev, ent->driver_data, brd);
 	if (rc)
-		return rc;
+		goto cleanup_brd;
 
-	dgap_numboards++;
-	return dgap_firmware_load(pdev, ent->driver_data);
-}
+	rc = dgap_alloc_flipbuf(brd);
+	if (rc)
+		goto cleanup_brd;
 
-static int dgap_probe1(struct pci_dev *pdev, int card_type)
-{
-	return dgap_found_board(pdev, card_type);
+	rc = dgap_tty_register(brd);
+	if (rc)
+		goto free_flipbuf;
+
+	rc = dgap_request_irq(brd);
+	if (rc)
+		goto unregister_tty;
+
+	/*
+	 * Do tty device initialization.
+	 */
+	rc = dgap_tty_init(brd);
+	if (rc < 0)
+		goto free_irq;
+
+	rc = dgap_tty_register_ports(brd);
+	if (rc)
+		goto tty_free;
+
+	brd->state = BOARD_READY;
+	brd->dpastatus = BD_RUNNING;
+
+	dgap_board[dgap_numboards++] = brd;
+
+	return 0;
+
+tty_free:
+	dgap_tty_free(brd);
+free_irq:
+	dgap_free_irq(brd);
+unregister_tty:
+	dgap_tty_unregister(brd);
+free_flipbuf:
+	dgap_free_flipbuf(brd);
+cleanup_brd:
+	dgap_release_remap(brd);
+	kfree(brd);
+
+	return rc;
 }
 
 static void dgap_remove_one(struct pci_dev *dev)
@@ -620,7 +655,7 @@ static void dgap_cleanup_module(void)
 
 	for (i = 0; i < dgap_numboards; ++i) {
 		dgap_remove_ports_sysfiles(dgap_board[i]);
-		dgap_tty_uninit(dgap_board[i]);
+		dgap_cleanup_tty(dgap_board[i]);
 		dgap_cleanup_board(dgap_board[i]);
 	}
 
@@ -640,8 +675,7 @@ static void dgap_cleanup_board(struct bo
 	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
 		return;
 
-	if (brd->intr_used && brd->irq)
-		free_irq(brd->irq, brd);
+	dgap_free_irq(brd);
 
 	tasklet_kill(&brd->helper_tasklet);
 
@@ -674,23 +708,22 @@ static void dgap_cleanup_board(struct bo
  *
  * A board has been found, init it.
  */
-static int dgap_found_board(struct pci_dev *pdev, int id)
+static struct board_t *dgap_found_board(struct pci_dev *pdev, int id,
+					int boardnum)
 {
 	struct board_t *brd;
 	unsigned int pci_irq;
 	int i;
+	int ret;
 
 	/* get the board structure and prep it */
 	brd = kzalloc(sizeof(struct board_t), GFP_KERNEL);
 	if (!brd)
-		return -ENOMEM;
-
-	dgap_board[dgap_numboards] = brd;
+		return ERR_PTR(-ENOMEM);
 
 	/* store the info for the board we've found */
 	brd->magic = DGAP_BOARD_MAGIC;
-	brd->boardnum = dgap_numboards;
-	brd->firstminor = 0;
+	brd->boardnum = boardnum;
 	brd->vendor = dgap_pci_tbl[id].vendor;
 	brd->device = dgap_pci_tbl[id].device;
 	brd->pdev = pdev;
@@ -734,8 +767,10 @@ static int dgap_found_board(struct pci_d
 		brd->membase_end = pci_resource_end(pdev, 0);
 	}
 
-	if (!brd->membase)
-		return -ENODEV;
+	if (!brd->membase) {
+		ret = -ENODEV;
+		goto free_brd;
+	}
 
 	if (brd->membase & 1)
 		brd->membase &= ~3;
@@ -776,18 +811,23 @@ static int dgap_found_board(struct pci_d
 	tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet,
 			(unsigned long) brd);
 
-	i = dgap_do_remap(brd);
-	if (i)
-		brd->state = BOARD_FAILED;
+	ret = dgap_do_remap(brd);
+	if (ret)
+		goto free_brd;
 
 	pr_info("dgap: board %d: %s (rev %d), irq %ld\n",
-		dgap_numboards, brd->name, brd->rev, brd->irq);
+		boardnum, brd->name, brd->rev, brd->irq);
 
-	return 0;
+	return brd;
+
+free_brd:
+	kfree(brd);
+
+	return ERR_PTR(ret);
 }
 
 
-static int dgap_finalize_board_init(struct board_t *brd)
+static int dgap_request_irq(struct board_t *brd)
 {
 	int rc;
 
@@ -814,17 +854,24 @@ static int dgap_finalize_board_init(stru
 	return 0;
 }
 
-static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
+static void dgap_free_irq(struct board_t *brd)
+{
+	if (brd->intr_used && brd->irq)
+		free_irq(brd->irq, brd);
+}
+
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
+			      struct board_t *brd)
 {
-	struct board_t *brd = dgap_board[dgap_numboards - 1];
 	const struct firmware *fw;
 	char *tmp_ptr;
 	int ret;
+	char *dgap_config_buf;
 
 	dgap_get_vpd(brd);
 	dgap_do_reset_board(brd);
 
-	if ((fw_info[card_type].conf_name) && !dgap_config_buf) {
+	if (fw_info[card_type].conf_name) {
 		ret = reject_firmware(&fw, fw_info[card_type].conf_name,
 					 &pdev->dev);
 		if (ret) {
@@ -849,16 +896,13 @@ static int dgap_firmware_load(struct pci
 		 */
 		tmp_ptr = dgap_config_buf;
 
-		if (dgap_parsefile(&tmp_ptr, TRUE) != 0) {
+		if (dgap_parsefile(&tmp_ptr) != 0) {
 			kfree(dgap_config_buf);
 			return -EINVAL;
 		}
 		kfree(dgap_config_buf);
 	}
 
-	ret = dgap_after_config_loaded(brd->boardnum);
-	if (ret)
-		return ret;
 	/*
 	 * Match this board to a config the user created for us.
 	 */
@@ -880,14 +924,6 @@ static int dgap_firmware_load(struct pci
 		return -EINVAL;
 	}
 
-	ret = dgap_tty_register(brd);
-	if (ret)
-		return ret;
-
-	ret = dgap_finalize_board_init(brd);
-	if (ret)
-		return ret;
-
 	if (fw_info[card_type].bios_name) {
 		ret = reject_firmware(&fw, fw_info[card_type].bios_name,
 					&pdev->dev);
@@ -950,21 +986,6 @@ static int dgap_firmware_load(struct pci
 		release_firmware(fw);
 	}
 #endif
-	/*
-	 * Do tty device initialization.
-	 */
-	ret = dgap_tty_init(brd);
-	if (ret < 0) {
-		dgap_tty_uninit(brd);
-		return ret;
-	}
-
-	ret = dgap_tty_register_ports(brd);
-	if (ret)
-		return ret;
-
-	brd->state = BOARD_READY;
-	brd->dpastatus = BD_RUNNING;
 
 	return 0;
 }
@@ -1004,6 +1025,12 @@ static int dgap_do_remap(struct board_t
 	return 0;
 }
 
+static void dgap_release_remap(struct board_t *brd)
+{
+	release_mem_region(brd->membase, 0x200000);
+	release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+	iounmap(brd->re_map_membase);
+}
 /*****************************************************************************
 *
 * Function:
@@ -1171,8 +1198,6 @@ static void dgap_init_globals(void)
 		dgap_board[i] = NULL;
 
 	init_timer(&dgap_poll_timer);
-
-	init_waitqueue_head(&dgap_dl_wait);
 }
 
 /************************************************************************
@@ -1311,6 +1336,14 @@ free_serial_drv:
 	return rc;
 }
 
+static void dgap_tty_unregister(struct board_t *brd)
+{
+	tty_unregister_driver(brd->print_driver);
+	tty_unregister_driver(brd->serial_driver);
+	put_tty_driver(brd->print_driver);
+	put_tty_driver(brd->serial_driver);
+}
+
 /*
  * dgap_tty_init()
  *
@@ -1327,9 +1360,7 @@ static int dgap_tty_init(struct board_t
 	struct channel_t *ch;
 	struct bs_t __iomem *bs;
 	struct cm_t __iomem *cm;
-
-	if (!brd)
-		return -EIO;
+	int ret;
 
 	/*
 	 * Initialize board structure elements.
@@ -1376,11 +1407,11 @@ static int dgap_tty_init(struct board_t
 	 * when the driver was first loaded.
 	 */
 	for (i = 0; i < brd->nasync; i++) {
+		brd->channels[i] =
+			kzalloc(sizeof(struct channel_t), GFP_KERNEL);
 		if (!brd->channels[i]) {
-			brd->channels[i] =
-				kzalloc(sizeof(struct channel_t), GFP_KERNEL);
-			if (!brd->channels[i])
-				return -ENOMEM;
+			ret = -ENOMEM;
+			goto free_chan;
 		}
 	}
 
@@ -1395,9 +1426,6 @@ static int dgap_tty_init(struct board_t
 	/* Set up channel variables */
 	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
 
-		if (!brd->channels[i])
-			continue;
-
 		spin_lock_init(&ch->ch_lock);
 
 		/* Store all our magic numbers */
@@ -1480,15 +1508,34 @@ static int dgap_tty_init(struct board_t
 	}
 
 	return 0;
+
+free_chan:
+	while (--i >= 0) {
+		kfree(brd->channels[i]);
+		brd->channels[i] = NULL;
+	}
+	return ret;
 }
 
 /*
- * dgap_tty_uninit()
+ * dgap_tty_free()
+ *
+ * Free the channles which are allocated in dgap_tty_init().
+ */
+static void dgap_tty_free(struct board_t *brd)
+{
+	int i;
+
+	for (i = 0; i < brd->nasync; i++)
+		kfree(brd->channels[i]);
+}
+/*
+ * dgap_cleanup_tty()
  *
  * Uninitialize the TTY portion of this driver.  Free all memory and
  * resources.
  */
-static void dgap_tty_uninit(struct board_t *brd)
+static void dgap_cleanup_tty(struct board_t *brd)
 {
 	struct device *dev;
 	int i;
@@ -1981,7 +2028,7 @@ static int dgap_tty_open(struct tty_stru
 	/*
 	 * Run param in case we changed anything
 	 */
-	dgap_param(tty);
+	dgap_param(ch, brd, un->un_type);
 
 	/*
 	 * follow protocol for opening port
@@ -2133,10 +2180,7 @@ static int dgap_block_til_ready(struct t
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
 
-	if (retval)
-		return retval;
-
-	return 0;
+	return retval;
 }
 
 /*
@@ -2459,22 +2503,9 @@ static int dgap_wait_for_drain(struct tt
  * returns the new bytes_available.  This only affects printer
  * output.
  */
-static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
+static int dgap_maxcps_room(struct channel_t *ch, struct un_t *un,
+			    int bytes_available)
 {
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!tty)
-		return bytes_available;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return bytes_available;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return bytes_available;
-
 	/*
 	 * If its not the Transparent print device, return
 	 * the full data amount.
@@ -2576,7 +2607,7 @@ static int dgap_tty_write_room(struct tt
 		ret += ch->ch_tsize;
 
 	/* Limit printer to maxcps */
-	ret = dgap_maxcps_room(tty, ret);
+	ret = dgap_maxcps_room(ch, un, ret);
 
 	/*
 	 * If we are printer device, leave space for
@@ -2681,7 +2712,7 @@ static int dgap_tty_write(struct tty_str
 	 * Limit printer output to maxcps overall, with bursts allowed
 	 * up to bufsize characters.
 	 */
-	bufcount = dgap_maxcps_room(tty, bufcount);
+	bufcount = dgap_maxcps_room(ch, un, bufcount);
 
 	/*
 	 * Take minimum of what the user wants to send, and the
@@ -2892,7 +2923,7 @@ static int dgap_tty_tiocmset(struct tty_
 		ch->ch_mval   &= ~(D_DTR(ch));
 	}
 
-	dgap_param(tty);
+	dgap_param(ch, bd, un->un_type);
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3014,8 +3045,6 @@ static void dgap_tty_send_xchar(struct t
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
-	return;
 }
 
 /*
@@ -3028,9 +3057,6 @@ static int dgap_get_modem_info(struct ch
 	ulong lock_flags;
 	int rc;
 
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EIO;
-
 	spin_lock_irqsave(&ch->ch_lock, lock_flags);
 
 	mstat = readb(&(ch->ch_bs->m_stat));
@@ -3064,32 +3090,14 @@ static int dgap_get_modem_info(struct ch
  *
  * Set modem signals, called by ld.
  */
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command,
-				unsigned int __user *value)
+static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, struct un_t *un,
+			       unsigned int command, unsigned int __user *value)
 {
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
 	int ret;
 	unsigned int arg;
 	ulong lock_flags;
 	ulong lock_flags2;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EIO;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EIO;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EIO;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -EIO;
-
 	ret = get_user(arg, value);
 	if (ret)
 		return ret;
@@ -3143,7 +3151,7 @@ static int dgap_set_modem_info(struct tt
 	spin_lock_irqsave(&bd->bd_lock, lock_flags);
 	spin_lock_irqsave(&ch->ch_lock, lock_flags2);
 
-	dgap_param(tty);
+	dgap_param(ch, bd, un->un_type);
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3159,28 +3167,14 @@ static int dgap_set_modem_info(struct tt
  *
  *
  */
-static int dgap_tty_digigeta(struct tty_struct *tty,
-				struct digi_t __user *retinfo)
+static int dgap_tty_digigeta(struct channel_t *ch, struct digi_t __user *retinfo)
 {
-	struct channel_t *ch;
-	struct un_t *un;
 	struct digi_t tmp;
 	ulong lock_flags;
 
 	if (!retinfo)
 		return -EFAULT;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EFAULT;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EFAULT;
-
 	memset(&tmp, 0, sizeof(tmp));
 
 	spin_lock_irqsave(&ch->ch_lock, lock_flags);
@@ -3201,31 +3195,13 @@ static int dgap_tty_digigeta(struct tty_
  *
  *
  */
-static int dgap_tty_digiseta(struct tty_struct *tty,
-				struct digi_t __user *new_info)
+static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd,
+			     struct un_t *un, struct digi_t __user *new_info)
 {
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
 	struct digi_t new_digi;
 	ulong lock_flags = 0;
 	unsigned long lock_flags2;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EFAULT;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EFAULT;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -EFAULT;
-
 	if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t)))
 		return -EFAULT;
 
@@ -3255,7 +3231,7 @@ static int dgap_tty_digiseta(struct tty_
 	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
 		ch->ch_digi.digi_offlen = DIGI_PLEN;
 
-	dgap_param(tty);
+	dgap_param(ch, bd, un->un_type);
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3310,30 +3286,13 @@ static int dgap_tty_digigetedelay(struct
  * Ioctl to set the EDELAY setting
  *
  */
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
+static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd,
+				  struct un_t *un, int __user *new_info)
 {
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
 	int new_digi;
 	ulong lock_flags;
 	ulong lock_flags2;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EFAULT;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EFAULT;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -EFAULT;
-
 	if (copy_from_user(&new_digi, new_info, sizeof(int)))
 		return -EFAULT;
 
@@ -3342,7 +3301,7 @@ static int dgap_tty_digisetedelay(struct
 
 	writew((u16) new_digi, &(ch->ch_bs->edelay));
 
-	dgap_param(tty);
+	dgap_param(ch, bd, un->un_type);
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3355,28 +3314,15 @@ static int dgap_tty_digisetedelay(struct
  *
  * Ioctl to get the current custom baud rate setting.
  */
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty,
-					int __user *retinfo)
+static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un,
+				      int __user *retinfo)
 {
-	struct channel_t *ch;
-	struct un_t *un;
 	int tmp;
 	ulong lock_flags;
 
 	if (!retinfo)
 		return -EFAULT;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EFAULT;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EFAULT;
-
 	memset(&tmp, 0, sizeof(tmp));
 
 	spin_lock_irqsave(&ch->ch_lock, lock_flags);
@@ -3394,32 +3340,13 @@ static int dgap_tty_digigetcustombaud(st
  *
  * Ioctl to set the custom baud rate setting
  */
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty,
-					int __user *new_info)
+static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd,
+				      struct un_t *un, int __user *new_info)
 {
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
 	uint new_rate;
 	ulong lock_flags;
 	ulong lock_flags2;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EFAULT;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EFAULT;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -EFAULT;
-
-
 	if (copy_from_user(&new_rate, new_info, sizeof(unsigned int)))
 		return -EFAULT;
 
@@ -3430,7 +3357,7 @@ static int dgap_tty_digisetcustombaud(st
 
 		ch->ch_custom_speed = new_rate;
 
-		dgap_param(tty);
+		dgap_param(ch, bd, un->un_type);
 
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3477,7 +3404,7 @@ static void dgap_tty_set_termios(struct
 	ch->ch_stopc     = tty->termios.c_cc[VSTOP];
 
 	dgap_carrier(ch);
-	dgap_param(tty);
+	dgap_param(ch, bd, un->un_type);
 
 	spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 	spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
@@ -3884,7 +3811,7 @@ static int dgap_tty_ioctl(struct tty_str
 		spin_lock_irqsave(&ch->ch_lock, lock_flags2);
 		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) |
 						(arg ? CLOCAL : 0));
-		dgap_param(tty);
+		dgap_param(ch, bd, un->un_type);
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
 
@@ -3900,7 +3827,7 @@ static int dgap_tty_ioctl(struct tty_str
 	case TIOCMSET:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_set_modem_info(tty, cmd, uarg);
+		return dgap_set_modem_info(ch, bd, un, cmd, uarg);
 
 		/*
 		 * Here are any additional ioctl's that we want to implement
@@ -4048,7 +3975,7 @@ static int dgap_tty_ioctl(struct tty_str
 		/* get information for ditty */
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_tty_digigeta(tty, uarg);
+		return dgap_tty_digigeta(ch, uarg);
 
 	case DIGI_SETAW:
 	case DIGI_SETAF:
@@ -4070,7 +3997,7 @@ static int dgap_tty_ioctl(struct tty_str
 	case DIGI_SETA:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_tty_digiseta(tty, uarg);
+		return dgap_tty_digiseta(ch, bd, un, uarg);
 
 	case DIGI_GEDELAY:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
@@ -4080,21 +4007,21 @@ static int dgap_tty_ioctl(struct tty_str
 	case DIGI_SEDELAY:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_tty_digisetedelay(tty, uarg);
+		return dgap_tty_digisetedelay(ch, bd, un, uarg);
 
 	case DIGI_GETCUSTOMBAUD:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_tty_digigetcustombaud(tty, uarg);
+		return dgap_tty_digigetcustombaud(ch, un, uarg);
 
 	case DIGI_SETCUSTOMBAUD:
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-		return dgap_tty_digisetcustombaud(tty, uarg);
+		return dgap_tty_digisetcustombaud(ch, bd, un, uarg);
 
 	case DIGI_RESET_PORT:
 		dgap_firmware_reset_port(ch);
-		dgap_param(tty);
+		dgap_param(ch, bd, un->un_type);
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
 		spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
 		return 0;
@@ -4107,29 +4034,30 @@ static int dgap_tty_ioctl(struct tty_str
 	}
 }
 
-static int dgap_after_config_loaded(int board)
+static int dgap_alloc_flipbuf(struct board_t *brd)
 {
 	/*
-	 * Initialize KME waitqueues...
-	 */
-	init_waitqueue_head(&(dgap_board[board]->kme_wait));
-
-	/*
 	 * allocate flip buffer for board.
 	 */
-	dgap_board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
-	if (!dgap_board[board]->flipbuf)
+	brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+	if (!brd->flipbuf)
 		return -ENOMEM;
 
-	dgap_board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
-	if (!dgap_board[board]->flipflagbuf) {
-		kfree(dgap_board[board]->flipbuf);
+	brd->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+	if (!brd->flipflagbuf) {
+		kfree(brd->flipbuf);
 		return -ENOMEM;
 	}
 
 	return 0;
 }
 
+static void dgap_free_flipbuf(struct board_t *brd)
+{
+	kfree(brd->flipbuf);
+	kfree(brd->flipflagbuf);
+}
+
 /*
  * Create pr and tty device entries
  */
@@ -4137,6 +4065,7 @@ static int dgap_tty_register_ports(struc
 {
 	struct channel_t *ch;
 	int i;
+	int ret;
 
 	brd->serial_ports = kcalloc(brd->nasync, sizeof(*brd->serial_ports),
 					GFP_KERNEL);
@@ -4146,8 +4075,8 @@ static int dgap_tty_register_ports(struc
 	brd->printer_ports = kcalloc(brd->nasync, sizeof(*brd->printer_ports),
 					GFP_KERNEL);
 	if (!brd->printer_ports) {
-		kfree(brd->serial_ports);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free_serial_ports;
 	}
 
 	for (i = 0; i < brd->nasync; i++) {
@@ -4161,15 +4090,25 @@ static int dgap_tty_register_ports(struc
 		struct device *classp;
 
 		classp = tty_port_register_device(&brd->serial_ports[i],
-					brd->serial_driver,
-					brd->firstminor + i, NULL);
+						  brd->serial_driver,
+						  i, NULL);
+
+		if (IS_ERR(classp)) {
+			ret = PTR_ERR(classp);
+			goto unregister_ttys;
+		}
 
 		dgap_create_tty_sysfs(&ch->ch_tun, classp);
 		ch->ch_tun.un_sysfs = classp;
 
 		classp = tty_port_register_device(&brd->printer_ports[i],
-					brd->print_driver,
-					brd->firstminor + i, NULL);
+						  brd->print_driver,
+						  i, NULL);
+
+		if (IS_ERR(classp)) {
+			ret = PTR_ERR(classp);
+			goto unregister_ttys;
+		}
 
 		dgap_create_tty_sysfs(&ch->ch_pun, classp);
 		ch->ch_pun.un_sysfs = classp;
@@ -4177,6 +4116,35 @@ static int dgap_tty_register_ports(struc
 	dgap_create_ports_sysfiles(brd);
 
 	return 0;
+
+unregister_ttys:
+	while (i >= 0) {
+		ch = brd->channels[i];
+		if (ch->ch_tun.un_sysfs) {
+			dgap_remove_tty_sysfs(ch->ch_tun.un_sysfs);
+			tty_unregister_device(brd->serial_driver, i);
+		}
+
+		if (ch->ch_pun.un_sysfs) {
+			dgap_remove_tty_sysfs(ch->ch_pun.un_sysfs);
+			tty_unregister_device(brd->print_driver, i);
+		}
+		i--;
+	}
+
+	for (i = 0; i < brd->nasync; i++) {
+		tty_port_destroy(&brd->serial_ports[i]);
+		tty_port_destroy(&brd->printer_ports[i]);
+	}
+
+	kfree(brd->printer_ports);
+	brd->printer_ports = NULL;
+
+free_serial_ports:
+	kfree(brd->serial_ports);
+	brd->serial_ports = NULL;
+
+	return ret;
 }
 
 /*
@@ -4995,40 +4963,14 @@ static void dgap_firmware_reset_port(str
  *              struct tty_struct *     - TTY for port.
  *
  *=======================================================================*/
-static int dgap_param(struct tty_struct *tty)
+static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
 {
-	struct ktermios *ts;
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct bs_t __iomem *bs;
-	struct un_t *un;
 	u16 head;
 	u16 cflag;
 	u16 iflag;
 	u8 mval;
 	u8 hflow;
 
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EIO;
-
-	un = (struct un_t *) tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -EIO;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -EIO;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -EIO;
-
-	bs = ch->ch_bs;
-	if (!bs)
-		return -EIO;
-
-	ts = &tty->termios;
-
 	/*
 	 * If baud rate is zero, flush queues, and set mval to drop DTR.
 	 */
@@ -5108,7 +5050,7 @@ static int dgap_param(struct tty_struct
 		 * terminal unit is NOT open
 		 */
 		if (!(ch->ch_tun.un_flags & UN_ISOPEN) &&
-		     (un->un_type == DGAP_PRINT))
+		    un_type == DGAP_PRINT)
 			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
 		else
 			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
@@ -5281,6 +5223,7 @@ static int dgap_param(struct tty_struct
 	 */
 	if (bd->bd_flags & BD_FEP5PLUS) {
 		u16 hflow2 = 0;
+
 		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
 			hflow2 |= (D_RTS(ch));
 		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)
@@ -5305,7 +5248,7 @@ static int dgap_param(struct tty_struct
 	/*
 	 * Read modem signals, and then call carrier function.
 	 */
-	ch->ch_mistat = readb(&(bs->m_stat));
+	ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
 	dgap_carrier(ch);
 
 	/*
@@ -5690,6 +5633,7 @@ static int dgap_create_driver_sysfiles(s
 static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
 {
 	struct device_driver *driverfs = &dgap_driver->driver;
+
 	driver_remove_file(driverfs, &driver_attr_version);
 	driver_remove_file(driverfs, &driver_attr_boards);
 	driver_remove_file(driverfs, &driver_attr_maxboards);
@@ -6283,6 +6227,7 @@ static ssize_t dgap_tty_name_show(struct
 
 		if (cptr->type == TNODE && found == TRUE) {
 			char *ptr1;
+
 			if (strstr(cptr->u.ttyname, "tty")) {
 				ptr1 = cptr->u.ttyname;
 				ptr1 += 3;
@@ -6381,7 +6326,7 @@ static void dgap_remove_tty_sysfs(struct
 /*
  * Parse a configuration file read into memory as a string.
  */
-static int dgap_parsefile(char **in, int remove)
+static int dgap_parsefile(char **in)
 {
 	struct cnode *p, *brd, *line, *conc;
 	int rc;
@@ -6396,7 +6341,7 @@ static int dgap_parsefile(char **in, int
 		p = p->next;
 
 	/* file must start with a BEGIN */
-	while ((rc = dgap_gettok(in, p)) != BEGIN) {
+	while ((rc = dgap_gettok(in)) != BEGIN) {
 		if (rc == 0) {
 			dgap_err("unexpected EOF");
 			return -1;
@@ -6404,17 +6349,13 @@ static int dgap_parsefile(char **in, int
 	}
 
 	for (; ;) {
-		rc = dgap_gettok(in, p);
+		rc = dgap_gettok(in);
 		if (rc == 0) {
 			dgap_err("unexpected EOF");
 			return -1;
 		}
 
 		switch (rc) {
-		case 0:
-			dgap_err("unexpected end of file");
-			return -1;
-
 		case BEGIN:	/* should only be 1 begin */
 			dgap_err("unexpected config_begin\n");
 			return -1;
@@ -6425,13 +6366,15 @@ static int dgap_parsefile(char **in, int
 		case BOARD:	/* board info */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(BNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
 			p = p->next;
 
+			p->type = BNODE;
 			p->u.board.status = kstrdup("No", GFP_KERNEL);
 			line = conc = NULL;
 			brd = p;
@@ -6716,12 +6659,16 @@ static int dgap_parsefile(char **in, int
 		case TTYN:	/* tty name prefix */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(TNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = TNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpeced end of file");
@@ -6737,12 +6684,16 @@ static int dgap_parsefile(char **in, int
 		case CU:	/* cu name prefix */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(CUNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = CUNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpeced end of file");
@@ -6767,12 +6718,15 @@ static int dgap_parsefile(char **in, int
 				dgap_err("line not vaild for PC/em");
 				return -1;
 			}
-			p->next = dgap_newnode(LNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = LNODE;
 			conc = NULL;
 			line = p;
 			linecnt++;
@@ -6785,13 +6739,17 @@ static int dgap_parsefile(char **in, int
 				dgap_err("must specify line info before concentrator");
 				return -1;
 			}
-			p->next = dgap_newnode(CNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = CNODE;
 			conc = p;
+
 			if (linecnt)
 				brd->u.board.conc2++;
 			else
@@ -6834,12 +6792,15 @@ static int dgap_parsefile(char **in, int
 					return -1;
 				}
 			}
-			p->next = dgap_newnode(MNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
 			p = p->next;
+			p->type = MNODE;
+
 			if (linecnt)
 				brd->u.board.module2++;
 			else
@@ -6920,12 +6881,16 @@ static int dgap_parsefile(char **in, int
 		case PRINT:	/* transparent print name prefix */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(PNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = PNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpeced end of file");
@@ -6941,12 +6906,16 @@ static int dgap_parsefile(char **in, int
 		case CMAJOR:	/* major number */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(JNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = JNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -6961,12 +6930,16 @@ static int dgap_parsefile(char **in, int
 		case ALTPIN:	/* altpin setting */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(ANODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = ANODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -6981,12 +6954,14 @@ static int dgap_parsefile(char **in, int
 		case USEINTR:		/* enable interrupt setting */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(INTRNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
 			p = p->next;
+			p->type = INTRNODE;
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7001,12 +6976,16 @@ static int dgap_parsefile(char **in, int
 		case TTSIZ:	/* size of tty structure */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(TSNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = TSNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7021,12 +7000,16 @@ static int dgap_parsefile(char **in, int
 		case CHSIZ:	/* channel structure size */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(CSNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = CSNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7041,12 +7024,16 @@ static int dgap_parsefile(char **in, int
 		case BSSIZ:	/* board structure size */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(BSNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = BSNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7061,12 +7048,16 @@ static int dgap_parsefile(char **in, int
 		case UNTSIZ:	/* sched structure size */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(USNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = USNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7081,12 +7072,16 @@ static int dgap_parsefile(char **in, int
 		case F2SIZ:	/* f2200 structure size */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(FSNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = FSNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7101,12 +7096,16 @@ static int dgap_parsefile(char **in, int
 		case VPSIZ:	/* vpix structure size */
 			if (dgap_checknode(p))
 				return -1;
-			p->next = dgap_newnode(VSNODE);
+
+			p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
 			if (!p->next) {
 				dgap_err("out of memory");
 				return -1;
 			}
+
 			p = p->next;
+			p->type = VSNODE;
+
 			s = dgap_getword(in);
 			if (!s) {
 				dgap_err("unexpected end of file");
@@ -7158,12 +7157,12 @@ static char *dgap_sindex(char *string, c
 /*
  * Get a token from the input file; return 0 if end of file is reached
  */
-static int dgap_gettok(char **in, struct cnode *p)
+static int dgap_gettok(char **in)
 {
 	char *w;
 	struct toklist *t;
 
-	if (strstr(dgap_cword, "boar")) {
+	if (strstr(dgap_cword, "board")) {
 		w = dgap_getword(in);
 		snprintf(dgap_cword, MAXCWORD, "%s", w);
 		for (t = dgap_tlist; t->token != 0; t++) {
@@ -7223,21 +7222,6 @@ static void dgap_err(char *s)
 }
 
 /*
- * allocate a new configuration node of type t
- */
-static struct cnode *dgap_newnode(int t)
-{
-	struct cnode *n;
-
-	n = kmalloc(sizeof(struct cnode), GFP_KERNEL);
-	if (n) {
-		memset((char *)n, 0, sizeof(struct cnode));
-		n->type = t;
-	}
-	return n;
-}
-
-/*
  * dgap_checknode: see if all the necessary info has been supplied for a node
  * before creating the next node.
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgap/dgap.h linux-libre-3.17-rc7-gnu/drivers/staging/dgap/dgap.h
--- linux-libre-3.16-gnu/drivers/staging/dgap/dgap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgap/dgap.h	2014-09-28 17:29:07.000000000 -0400
@@ -529,7 +529,6 @@ struct macounter {
 struct board_t {
 	int		magic;		/* Board Magic number.  */
 	int		boardnum;	/* Board number: 0-3 */
-	int		firstminor;	/* First minor, e.g. 0, 30, 60 */
 
 	int		type;		/* Type of board */
 	char		*name;		/* Product Name */
@@ -604,7 +603,6 @@ struct board_t {
 					/* by DPA                         */
 	u16		dpastatus;	/* The board "status", as defined */
 					/* by DPA                         */
-	wait_queue_head_t kme_wait;	/* Needed for DPA support         */
 
 	u32		conc_dl_status;	/* Status of any pending conc     */
 					/* download                       */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_cls.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_cls.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_cls.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_cls.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,6 @@
 #include "dgnc_driver.h"	/* Driver main header file */
 #include "dgnc_cls.h"
 #include "dgnc_tty.h"
-#include "dgnc_trace.h"
 
 static inline void cls_parse_isr(struct dgnc_board *brd, uint port);
 static inline void cls_clear_break(struct channel_t *ch, int force);
@@ -1040,16 +1039,13 @@ static void cls_flush_uart_read(struct c
 	 * For complete POSIX compatibility, we should be purging the
 	 * read FIFO in the UART here.
 	 *
-	 * However, doing the statement below also incorrectly flushes
-	 * write data as well as just basically trashing the FIFO.
+	 * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also
+	 * incorrectly flushes write data as well as just basically trashing the
+	 * FIFO.
 	 *
-	 * I believe this is a BUG in this UART.
-	 * So for now, we will leave the code #ifdef'ed out...
+	 * Presumably, this is a bug in this UART.
 	 */
-#if 0
-	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR),
-					 &ch->ch_cls_uart->isr_fcr);
-#endif
+
 	udelay(10);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_driver.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_driver.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,6 @@
 #include "dpacompat.h"
 #include "dgnc_mgmt.h"
 #include "dgnc_tty.h"
-#include "dgnc_trace.h"
 #include "dgnc_cls.h"
 #include "dgnc_neo.h"
 #include "dgnc_sysfs.h"
@@ -88,8 +87,7 @@ module_exit(dgnc_cleanup_module);
 /*
  * File operations permitted on Control/Management major.
  */
-static const struct file_operations dgnc_BoardFops =
-{
+static const struct file_operations dgnc_BoardFops = {
 	.owner		=	THIS_MODULE,
 	.unlocked_ioctl =  	dgnc_mgmt_ioctl,
 	.open		=	dgnc_mgmt_open,
@@ -389,10 +387,6 @@ void dgnc_cleanup_module(void)
 
 	dgnc_tty_post_uninit();
 
-#if defined(DGNC_TRACER)
-	/* last thing, make sure we release the tracebuffer */
-	dgnc_tracer_free();
-#endif
 	if (dgnc_NumBoards)
 		pci_unregister_driver(&dgnc_driver);
 }
@@ -407,7 +401,7 @@ static void dgnc_cleanup_board(struct dg
 {
 	int i = 0;
 
-	if(!brd || brd->magic != DGNC_BOARD_MAGIC)
+	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
 		return;
 
 	switch (brd->device) {
@@ -480,7 +474,7 @@ static int dgnc_found_board(struct pci_d
 	/* get the board structure and prep it */
 	brd = dgnc_Board[dgnc_NumBoards] =
 		kzalloc(sizeof(*brd), GFP_KERNEL);
-	if (!brd) 
+	if (!brd)
 		return -ENOMEM;
 
 	/* make a temporary message buffer for the boot messages */
@@ -523,7 +517,7 @@ static int dgnc_found_board(struct pci_d
 	brd->irq = pci_irq;
 
 
-	switch(brd->device) {
+	switch (brd->device) {
 
 	case PCI_DEVICE_CLASSIC_4_DID:
 	case PCI_DEVICE_CLASSIC_8_DID:
@@ -710,7 +704,8 @@ failed:
 }
 
 
-static int dgnc_finalize_board_init(struct dgnc_board *brd) {
+static int dgnc_finalize_board_init(struct dgnc_board *brd)
+{
 	int rc = 0;
 
 	DPR_INIT(("dgnc_finalize_board_init() - start\n"));
@@ -886,7 +881,7 @@ int dgnc_ms_sleep(ulong ms)
  */
 char *dgnc_ioctl_name(int cmd)
 {
-	switch(cmd) {
+	switch (cmd) {
 
 	case TCGETA:		return "TCGETA";
 	case TCGETS:		return "TCGETS";
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_driver.h linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_driver.h
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_driver.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_driver.h	2014-09-28 17:29:07.000000000 -0400
@@ -91,57 +91,6 @@
 
 #define	DBG_CARR		(dgnc_debug & 0x10000)
 
-
-#if defined(DGNC_TRACER)
-
-# if defined(TRC_TO_KMEM)
-/* Choose one: */
-#  define TRC_ON_OVERFLOW_WRAP_AROUND
-#  undef  TRC_ON_OVERFLOW_SHIFT_BUFFER
-# endif //TRC_TO_KMEM
-
-# define TRC_MAXMSG		1024
-# define TRC_OVERFLOW		"(OVERFLOW)"
-# define TRC_DTRC		"/usr/bin/dtrc"
-
-#if defined TRC_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
-#else //!defined TRACE_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args)
-#endif
-
-#if defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args) dgnc_tracef args
-#else //!defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args)
-#endif
-
-#define	TRC(args)	{ PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
-
-# define DPR_INIT(ARGS)		if (DBG_INIT) TRC(ARGS)
-# define DPR_BASIC(ARGS)	if (DBG_BASIC) TRC(ARGS)
-# define DPR_CORE(ARGS)		if (DBG_CORE) TRC(ARGS)
-# define DPR_OPEN(ARGS)		if (DBG_OPEN)  TRC(ARGS)
-# define DPR_CLOSE(ARGS)	if (DBG_CLOSE)  TRC(ARGS)
-# define DPR_READ(ARGS)		if (DBG_READ)  TRC(ARGS)
-# define DPR_WRITE(ARGS)	if (DBG_WRITE) TRC(ARGS)
-# define DPR_IOCTL(ARGS)	if (DBG_IOCTL) TRC(ARGS)
-# define DPR_PROC(ARGS)		if (DBG_PROC)  TRC(ARGS)
-# define DPR_PARAM(ARGS)	if (DBG_PARAM)  TRC(ARGS)
-# define DPR_PSCAN(ARGS)	if (DBG_PSCAN)  TRC(ARGS)
-# define DPR_EVENT(ARGS)	if (DBG_EVENT)  TRC(ARGS)
-# define DPR_DRAIN(ARGS)	if (DBG_DRAIN)  TRC(ARGS)
-# define DPR_CARR(ARGS)		if (DBG_CARR)  TRC(ARGS)
-# define DPR_MGMT(ARGS)		if (DBG_MGMT)  TRC(ARGS)
-# define DPR_INTR(ARGS)		if (DBG_INTR)  TRC(ARGS)
-# define DPR_MSIGS(ARGS)	if (DBG_MSIGS)  TRC(ARGS)
-
-# define DPR(ARGS)		if (dgnc_debug) TRC(ARGS)
-# define P(X)			dgnc_tracef(#X "=%p\n", X)
-# define X(X)			dgnc_tracef(#X "=%x\n", X)
-
-#else//!defined DGNC_TRACER
-
 #define PRINTF_TO_KMEM(args)
 # define TRC(ARGS)
 # define DPR_INIT(ARGS)
@@ -164,8 +113,6 @@
 
 # define DPR(args)
 
-#endif//DGNC_TRACER
-
 /* Number of boards we support at once. */
 #define	MAXBOARDS	20
 #define	MAXPORTS	8
@@ -219,8 +166,8 @@
  * Makes spotting lock/unlock locations easier.
  */
 # define DGNC_SPINLOCK_INIT(x)		spin_lock_init(&(x))
-# define DGNC_LOCK(x,y)			spin_lock_irqsave(&(x), y)
-# define DGNC_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
+# define DGNC_LOCK(x, y)		spin_lock_irqsave(&(x), y)
+# define DGNC_UNLOCK(x, y)		spin_unlock_irqrestore(&(x), y)
 
 /*
  * All the possible states the driver can be while being loaded.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_neo.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_neo.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_neo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_neo.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,6 @@
 #include "dgnc_driver.h"	/* Driver main header file */
 #include "dgnc_neo.h"		/* Our header file */
 #include "dgnc_tty.h"
-#include "dgnc_trace.h"
 
 static inline void neo_parse_lsr(struct dgnc_board *brd, uint port);
 static inline void neo_parse_isr(struct dgnc_board *brd, uint port);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_sysfs.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_sysfs.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_sysfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -150,15 +150,17 @@ void dgnc_remove_driver_sysfiles(struct
 }
 
 
-#define DGNC_VERIFY_BOARD(p, bd)			\
-	if (!p)						\
-		return 0;				\
-							\
-	bd = dev_get_drvdata(p);			\
-	if (!bd || bd->magic != DGNC_BOARD_MAGIC)	\
-		return 0;				\
-	if (bd->state != BOARD_READY)			\
-		return 0;				\
+#define DGNC_VERIFY_BOARD(p, bd)				\
+	do {							\
+		if (!p)						\
+			return 0;				\
+								\
+		bd = dev_get_drvdata(p);			\
+		if (!bd || bd->magic != DGNC_BOARD_MAGIC)	\
+			return 0;				\
+		if (bd->state != BOARD_READY)			\
+			return 0;				\
+	} while (0)
 
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_trace.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_trace.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_trace.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_trace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,185 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- * You 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.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>	/* For jiffies, task states */
-#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
-#include <linux/vmalloc.h>
-
-#include "dgnc_driver.h"
-#include "dgnc_trace.h"
-
-#define TRC_TO_CONSOLE 1
-
-/* file level globals */
-static char *dgnc_trcbuf;		/* the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static int dgnc_trcbufi = 0;		/* index of the tilde at the end of */
-#endif
-
-#if defined(TRC_TO_KMEM)
-static DEFINE_SPINLOCK(dgnc_tracef_lock);
-#endif
-
-
-#if 0
-
-#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
-
-void dgnc_tracef(const char *fmt, ...)
-{
-	return;
-}
-
-#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-void dgnc_tracef(const char *fmt, ...)
-{
-	va_list		ap;
-	char		buf[TRC_MAXMSG+1];
-	size_t		lenbuf;
-	int		i;
-	static int	failed = FALSE;
-# if defined(TRC_TO_KMEM)
-	unsigned long	 flags;
-#endif
-
-	if (failed)
-		return;
-# if defined(TRC_TO_KMEM)
-	DGNC_LOCK(dgnc_tracef_lock, flags);
-#endif
-
-	/* Format buf using fmt and arguments contained in ap. */
-	va_start(ap, fmt);
-	i = vsprintf(buf, fmt,  ap);
-	va_end(ap);
-	lenbuf = strlen(buf);
-
-# if defined(TRC_TO_KMEM)
-	{
-		static int	 initd = 0;
-
-		/*
-		 * Now, in addition to (or instead of) printing this stuff out
-		 * (which is a buffered operation), also tuck it away into a
-		 * corner of memory which can be examined post-crash in kdb.
-		 */
-		if (!initd) {
-			dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size);
-			if (!dgnc_trcbuf) {
-				failed = TRUE;
-				printk("dgnc: tracing init failed!\n");
-				return;
-			}
-
-			memset(dgnc_trcbuf, '\0',  dgnc_trcbuf_size);
-			dgnc_trcbufi = 0;
-			initd++;
-
-			printk("dgnc: tracing enabled - " TRC_DTRC
-				" 0x%lx 0x%x\n",
-				(unsigned long)dgnc_trcbuf,
-				dgnc_trcbuf_size);
-		}
-
-#  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
-		/*
-		 * This is the less CPU-intensive way to do things.  We simply
-		 * wrap around before we fall off the end of the buffer.  A
-		 * tilde (~) demarcates the current end of the trace.
-		 *
-		 * This method should be used if you are concerned about race
-		 * conditions as it is less likely to affect the timing of
-		 * things.
-		 */
-
-		if (dgnc_trcbufi + lenbuf >= dgnc_trcbuf_size) {
-			/* We are wrapping, so wipe out the last tilde. */
-			dgnc_trcbuf[dgnc_trcbufi] = '\0';
-			/* put the new string at the beginning of the buffer */
-			dgnc_trcbufi = 0;
-		}
-
-		strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
-		dgnc_trcbufi += lenbuf;
-		dgnc_trcbuf[dgnc_trcbufi] = '~';
-
-#  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
-		/*
-		 * This is the more CPU-intensive way to do things.  If we
-		 * venture into the last 1/8 of the buffer, we shift the
-		 * last 7/8 of the buffer forward, wiping out the first 1/8.
-		 * Advantage: No wrap-around, only truncation from the
-		 * beginning.
-		 *
-		 * This method should not be used if you are concerned about
-		 * timing changes affecting the behaviour of the driver (ie,
-		 * race conditions).
-		 */
-		strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
-		dgnc_trcbufi += lenbuf;
-		dgnc_trcbuf[dgnc_trcbufi] = '~';
-		dgnc_trcbuf[dgnc_trcbufi+1] = '\0';
-
-		/* If we're near the end of the trace buffer... */
-		if (dgnc_trcbufi > (dgnc_trcbuf_size/8)*7) {
-			/* Wipe out the first eighth to make some more room. */
-			strcpy(dgnc_trcbuf, &dgnc_trcbuf[dgnc_trcbuf_size/8]);
-			dgnc_trcbufi = strlen(dgnc_trcbuf)-1;
-			/* Plop overflow message at the top of the buffer. */
-			bcopy(TRC_OVERFLOW, dgnc_trcbuf, strlen(TRC_OVERFLOW));
-		}
-#  else
-#   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
-#  endif
-	}
-	DGNC_UNLOCK(dgnc_tracef_lock, flags);
-
-# endif /* defined(TRC_TO_KMEM) */
-}
-
-#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-#endif
-
-
-/*
- * dgnc_tracer_free()
- *
- *
- */
-void dgnc_tracer_free(void)
-{
-	if (dgnc_trcbuf)
-		vfree(dgnc_trcbuf);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_trace.h linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_trace.h
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_trace.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_trace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- * You 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.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *****************************************************************************
- * Header file for dgnc_trace.c
- *
- */
-
-#ifndef __DGNC_TRACE_H
-#define __DGNC_TRACE_H
-
-#include "dgnc_driver.h"
-
-#if 0
-
-# if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
-   void dgnc_tracef(const char *fmt, ...);
-# else
-   void dgnc_tracef(const char *fmt, ...);
-# endif
-
-#endif
-
-void dgnc_tracer_free(void);
-
-#endif
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_tty.c linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_tty.c
--- linux-libre-3.16-gnu/drivers/staging/dgnc/dgnc_tty.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/dgnc_tty.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,6 @@
 #include "dgnc_driver.h"
 #include "dgnc_tty.h"
 #include "dgnc_types.h"
-#include "dgnc_trace.h"
 #include "dgnc_neo.h"
 #include "dgnc_cls.h"
 #include "dpacompat.h"
@@ -200,9 +199,6 @@ int dgnc_tty_register(struct dgnc_board
 
 	DPR_INIT(("tty_register start\n"));
 
-	memset(&brd->SerialDriver, 0, sizeof(brd->SerialDriver));
-	memset(&brd->PrintDriver, 0, sizeof(brd->PrintDriver));
-
 	brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
 
 	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum);
@@ -417,10 +413,8 @@ int dgnc_tty_init(struct dgnc_board *brd
  */
 void dgnc_tty_post_uninit(void)
 {
-	if (dgnc_TmpWriteBuf) {
-		kfree(dgnc_TmpWriteBuf);
-		dgnc_TmpWriteBuf = NULL;
-	}
+	kfree(dgnc_TmpWriteBuf);
+	dgnc_TmpWriteBuf = NULL;
 }
 
 
@@ -456,14 +450,10 @@ void dgnc_tty_uninit(struct dgnc_board *
 		brd->dgnc_Major_TransparentPrint_Registered = FALSE;
 	}
 
-	if (brd->SerialDriver.ttys) {
-		kfree(brd->SerialDriver.ttys);
-		brd->SerialDriver.ttys = NULL;
-	}
-	if (brd->PrintDriver.ttys) {
-		kfree(brd->PrintDriver.ttys);
-		brd->PrintDriver.ttys = NULL;
-	}
+	kfree(brd->SerialDriver.ttys);
+	brd->SerialDriver.ttys = NULL;
+	kfree(brd->PrintDriver.ttys);
+	brd->PrintDriver.ttys = NULL;
 }
 
 
@@ -1642,10 +1632,10 @@ static void dgnc_tty_close(struct tty_st
 		un->un_open_count = 1;
 	}
 
-	if (--un->un_open_count < 0) {
+	if (un->un_open_count)
+		un->un_open_count--;
+	else
 		APR(("bad serial port open count of %d\n", un->un_open_count));
-		un->un_open_count = 0;
-	}
 
 	ch->ch_open_count--;
 
@@ -2116,24 +2106,6 @@ static int dgnc_tty_write(struct tty_str
 		ch->ch_w_head = head;
 	}
 
-#if 0
-	/*
-	 * If this is the print device, and the
-	 * printer is still on, we need to turn it
-	 * off before going idle.
-	 */
-	if (count == orig_count) {
-		if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON)) {
-			head &= tmask;
-			ch->ch_w_head = head;
-			dgnc_wmove(ch, ch->ch_digi.digi_offstr,
-				(int) ch->ch_digi.digi_offlen);
-			head = (ch->ch_w_head) & tmask;
-			ch->ch_flags &= ~CH_PRON;
-		}
-	}
-#endif
-
 	/* Update printer buffer empty time. */
 	if ((un->un_type == DGNC_PRINT) && (ch->ch_digi.digi_maxcps > 0)
 	    && (ch->ch_digi.digi_bufsize > 0)) {
@@ -3436,11 +3408,4 @@ static int dgnc_tty_ioctl(struct tty_str
 
 		return -ENOIOCTLCMD;
 	}
-
-	DGNC_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
-		dgnc_ioctl_name(cmd), cmd, arg));
-
-	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/digi.h linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/digi.h
--- linux-libre-3.16-gnu/drivers/staging/dgnc/digi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/digi.h	2014-09-28 17:29:07.000000000 -0400
@@ -394,23 +394,22 @@ struct digi_getcounter {
 #define DIGI_REALPORT_GETCOUNTERS ('e'<<8 ) | 110
 #define DIGI_REALPORT_GETEVENTS ('e'<<8 ) | 111
 
-#define EV_OPU		0x0001		//!<Output paused by client
-#define EV_OPS		0x0002		//!<Output paused by reqular sw flowctrl
-#define EV_OPX		0x0004		//!<Output paused by extra sw flowctrl
-#define EV_OPH		0x0008		//!<Output paused by hw flowctrl
-#define EV_OPT		0x0800		//!<Output paused for RTS Toggle predelay
+#define EV_OPU		0x0001		/* !<Output paused by client */
+#define EV_OPS		0x0002		/* !<Output paused by reqular sw flowctrl */
+#define EV_OPX		0x0004		/* !<Output paused by extra sw flowctrl */
+#define EV_OPH		0x0008		/* !<Output paused by hw flowctrl */
+#define EV_OPT		0x0800		/* !<Output paused for RTS Toggle predelay */
 
-#define EV_IPU		0x0010		//!<Input paused unconditionally by user
-#define EV_IPS		0x0020		//!<Input paused by high/low water marks
-//#define EV_IPH	0x0040		//!<Input paused w/ hardware
-#define EV_IPA		0x0400		//!<Input paused by pattern alarm module
+#define EV_IPU		0x0010		/* !<Input paused unconditionally by user */
+#define EV_IPS		0x0020		/* !<Input paused by high/low water marks */
+#define EV_IPA		0x0400		/* !<Input paused by pattern alarm module */
 
-#define EV_TXB		0x0040		//!<Transmit break pending
-#define EV_TXI		0x0080		//!<Transmit immediate pending
-#define EV_TXF		0x0100		//!<Transmit flowctrl char pending
-#define EV_RXB		0x0200		//!<Break received
+#define EV_TXB		0x0040		/* !<Transmit break pending */
+#define EV_TXI		0x0080		/* !<Transmit immediate pending */
+#define EV_TXF		0x0100		/* !<Transmit flowctrl char pending */
+#define EV_RXB		0x0200		/* !<Break received */
 
-#define EV_OPALL	0x080f		//!<Output pause flags
-#define EV_IPALL	0x0430		//!<Input pause flags
+#define EV_OPALL	0x080f		/* !<Output pause flags */
+#define EV_IPALL	0x0430		/* !<Input pause flags */
 
 #endif /* DIGI_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgnc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/dgnc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgnc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,4 +4,4 @@ obj-$(CONFIG_DGNC) += dgnc.o
 
 dgnc-objs :=   dgnc_cls.o dgnc_driver.o\
                dgnc_mgmt.o dgnc_neo.o\
-               dgnc_trace.o dgnc_tty.o dgnc_sysfs.o
+               dgnc_tty.o dgnc_sysfs.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_common.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_common.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_common.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,169 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_common.c
- *
- *  Description:
- *
- *     Definitions of global variables and functions which are either
- *     shared by the tty, mon, and net drivers; or which cross them
- *     functionally (like the poller).
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/cred.h>
-
-#include "dgrp_common.h"
-
-/**
- * dgrp_carrier -- check for carrier change state and act
- * @ch: struct ch_struct *
- */
-void dgrp_carrier(struct ch_struct *ch)
-{
-	struct nd_struct *nd;
-
-	int virt_carrier = 0;
-	int phys_carrier = 0;
-
-	/* fix case when the tty has already closed. */
-
-	if (!ch)
-		return;
-	nd  = ch->ch_nd;
-	if (!nd)
-		return;
-
-	/*
-	 *  If we are currently waiting to determine the status of the port,
-	 *  we don't yet know the state of the modem lines.  As a result,
-	 *  we ignore state changes when we are waiting for the modem lines
-	 *  to be established.  We know, as a result of code in dgrp_net_ops,
-	 *  that we will be called again immediately following the reception
-	 *  of the status message with the true modem status flags in it.
-	 */
-	if (ch->ch_expect & RR_STATUS)
-		return;
-
-	/*
-	 * If CH_HANGUP is set, we gotta keep trying to get all the processes
-	 * that have the port open to close the port.
-	 * So lets just keep sending a hangup every time we get here.
-	 */
-	if ((ch->ch_flag & CH_HANGUP) &&
-	    (ch->ch_tun.un_open_count > 0))
-		tty_hangup(ch->ch_tun.un_tty);
-
-	/*
-	 *  Compute the effective state of both the physical and virtual
-	 *  senses of carrier.
-	 */
-
-	if (ch->ch_s_mlast & DM_CD)
-		phys_carrier = 1;
-
-	if ((ch->ch_s_mlast & DM_CD) ||
-	    (ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
-	    (ch->ch_flag & CH_CLOCAL))
-		virt_carrier = 1;
-
-	/*
-	 *  Test for a VIRTUAL carrier transition to HIGH.
-	 *
-	 *  The CH_HANGUP condition is intended to prevent any action
-	 *  except for close.  As a result, we ignore positive carrier
-	 *  transitions during CH_HANGUP.
-	 */
-	if (((ch->ch_flag & CH_HANGUP)  == 0) &&
-	    ((ch->ch_flag & CH_VIRT_CD) == 0) &&
-	    (virt_carrier == 1)) {
-		/*
-		 * When carrier rises, wake any threads waiting
-		 * for carrier in the open routine.
-		 */
-		nd->nd_tx_work = 1;
-
-		if (waitqueue_active(&ch->ch_flag_wait))
-			wake_up_interruptible(&ch->ch_flag_wait);
-	}
-
-	/*
-	 *  Test for a PHYSICAL transition to low, so long as we aren't
-	 *  currently ignoring physical transitions (which is what "virtual
-	 *  carrier" indicates).
-	 *
-	 *  The transition of the virtual carrier to low really doesn't
-	 *  matter... it really only means "ignore carrier state", not
-	 *  "make pretend that carrier is there".
-	 */
-	if ((virt_carrier == 0) &&
-	    ((ch->ch_flag & CH_PHYS_CD) != 0) &&
-	    (phys_carrier == 0)) {
-		/*
-		 * When carrier drops:
-		 *
-		 *   Do a Hard Hangup if that is called for.
-		 *
-		 *   Drop carrier on all open units.
-		 *
-		 *   Flush queues, waking up any task waiting in the
-		 *   line discipline.
-		 *
-		 *   Send a hangup to the control terminal.
-		 *
-		 *   Enable all select calls.
-		 */
-
-		nd->nd_tx_work = 1;
-
-		ch->ch_flag &= ~(CH_LOW | CH_EMPTY | CH_DRAIN | CH_INPUT);
-
-		if (waitqueue_active(&ch->ch_flag_wait))
-			wake_up_interruptible(&ch->ch_flag_wait);
-
-		if (ch->ch_tun.un_open_count > 0)
-			tty_hangup(ch->ch_tun.un_tty);
-
-		if (ch->ch_pun.un_open_count > 0)
-			tty_hangup(ch->ch_pun.un_tty);
-	}
-
-	/*
-	 *  Make sure that our cached values reflect the current reality.
-	 */
-	if (virt_carrier == 1)
-		ch->ch_flag |= CH_VIRT_CD;
-	else
-		ch->ch_flag &= ~CH_VIRT_CD;
-
-	if (phys_carrier == 1)
-		ch->ch_flag |= CH_PHYS_CD;
-	else
-		ch->ch_flag &= ~CH_PHYS_CD;
-
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_common.h linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_common.h
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,150 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- */
-
-#ifndef __DGRP_COMMON_H
-#define __DGRP_COMMON_H
-
-#define DIGI_VERSION "1.9-29"
-
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include "drp.h"
-
-#define DGRP_TTIME 100
-#define DGRP_RTIME 100
-
-/************************************************************************
- * All global storage allocation.
- ************************************************************************/
-
-extern int dgrp_register_cudevices; /* enable legacy cu devices */
-extern int dgrp_register_prdevices; /* enable transparent print devices */
-extern int dgrp_poll_tick;          /* Poll interval - in ms */
-
-extern struct list_head nd_struct_list;
-
-struct dgrp_poll_data {
-	spinlock_t poll_lock;
-	struct timer_list timer;
-	int poll_tick;
-	ulong poll_round;	/* Timer rouding factor */
-	long node_active_count;
-};
-
-extern struct dgrp_poll_data dgrp_poll_data;
-extern void dgrp_poll_handler(unsigned long arg);
-
-/* from dgrp_mon_ops.c */
-extern const struct file_operations dgrp_mon_ops;
-
-/* from dgrp_tty.c */
-extern int dgrp_tty_init(struct nd_struct *nd);
-extern void dgrp_tty_uninit(struct nd_struct *nd);
-
-/* from dgrp_ports_ops.c */
-extern const struct file_operations dgrp_ports_ops;
-
-/* from dgrp_net_ops.c */
-extern const struct file_operations dgrp_net_ops;
-
-/* from dgrp_dpa_ops.c */
-extern const struct file_operations dgrp_dpa_ops;
-extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int);
-
-/* from dgrp_sysfs.c */
-extern int dgrp_create_class_sysfs_files(void);
-extern void dgrp_remove_class_sysfs_files(void);
-
-extern void dgrp_create_node_class_sysfs_files(struct nd_struct *nd);
-extern void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd);
-
-extern void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c);
-extern void dgrp_remove_tty_sysfs(struct device *c);
-
-/* from dgrp_specproc.c */
-extern void dgrp_unregister_proc(void);
-extern void dgrp_register_proc(void);
-
-/*-----------------------------------------------------------------------*
- *
- *  Declarations for common operations:
- *
- *      (either used by more than one of net, mon, or tty,
- *       or in interrupt context (i.e. the poller))
- *
- *-----------------------------------------------------------------------*/
-
-void dgrp_carrier(struct ch_struct *ch);
-
-
-/*
- *  ID manipulation macros (where c1 & c2 are characters, i is
- *  a long integer, and s is a character array of at least three members
- */
-
-static inline void ID_TO_CHAR(long i, char *s)
-{
-	s[0] = ((i & 0xff00)>>8);
-	s[1] = (i & 0xff);
-	s[2] = 0;
-}
-
-static inline long CHAR_TO_ID(char *s)
-{
-	return ((s[0] & 0xff) << 8) | (s[1] & 0xff);
-}
-
-static inline struct nd_struct *nd_struct_get(long major)
-{
-	struct nd_struct *nd;
-
-	list_for_each_entry(nd, &nd_struct_list, list) {
-		if (major == nd->nd_major)
-			return nd;
-	}
-
-	return NULL;
-}
-
-static inline int nd_struct_add(struct nd_struct *entry)
-{
-	struct nd_struct *ptr;
-
-	ptr = nd_struct_get(entry->nd_major);
-
-	if (ptr)
-		return -EBUSY;
-
-	list_add_tail(&entry->list, &nd_struct_list);
-
-	return 0;
-}
-
-static inline int nd_struct_del(struct nd_struct *entry)
-{
-	struct nd_struct *nd;
-
-	nd = nd_struct_get(entry->nd_major);
-
-	if (!nd)
-		return -ENODEV;
-
-	list_del(&nd->list);
-	return 0;
-}
-
-#endif /* __DGRP_COMMON_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_dpa_ops.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_dpa_ops.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_dpa_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_dpa_ops.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,534 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_dpa_ops.c
- *
- *  Description:
- *
- *     Handle the file operations required for the "dpa" devices.
- *     Includes those functions required to register the "dpa" devices
- *     in "/proc".
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/tty.h>
-#include <linux/poll.h>
-#include <linux/cred.h>
-#include <linux/sched.h>
-#include <linux/ratelimit.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-
-#include "dgrp_common.h"
-
-/* File operation declarations */
-static int dgrp_dpa_open(struct inode *, struct file *);
-static int dgrp_dpa_release(struct inode *, struct file *);
-static ssize_t dgrp_dpa_read(struct file *, char __user *, size_t, loff_t *);
-static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg);
-static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
-
-const struct file_operations dgrp_dpa_ops = {
-	.owner   =  THIS_MODULE,
-	.read    =  dgrp_dpa_read,
-	.poll    =  dgrp_dpa_select,
-	.unlocked_ioctl =  dgrp_dpa_ioctl,
-	.open    =  dgrp_dpa_open,
-	.release =  dgrp_dpa_release,
-};
-
-struct digi_node {
-	uint	nd_state;		/* Node state: 1 = up, 0 = down. */
-	uint	nd_chan_count;		/* Number of channels found */
-	uint	nd_tx_byte;		/* Tx data count */
-	uint	nd_rx_byte;		/* RX data count */
-	u8	nd_ps_desc[MAX_DESC_LEN]; /* Description from PS */
-};
-
-#define DIGI_GETNODE      (('d'<<8) | 249)	/* get board info */
-
-
-struct digi_chan {
-	uint	ch_port;	/* Port number to get info on */
-	uint	ch_open;	/* 1 if open, 0 if not */
-	uint	ch_txcount;	/* TX data count  */
-	uint	ch_rxcount;	/* RX data count  */
-	uint	ch_s_brate;	/* Realport BRATE */
-	uint	ch_s_estat;	/* Realport ELAST */
-	uint	ch_s_cflag;	/* Realport CFLAG */
-	uint	ch_s_iflag;	/* Realport IFLAG */
-	uint	ch_s_oflag;	/* Realport OFLAG */
-	uint	ch_s_xflag;	/* Realport XFLAG */
-	uint	ch_s_mstat;	/* Realport MLAST */
-};
-
-#define DIGI_GETCHAN      (('d'<<8) | 248)	/* get channel info */
-
-
-struct digi_vpd {
-	int vpd_len;
-	char vpd_data[VPDSIZE];
-};
-
-#define DIGI_GETVPD       (('d'<<8) | 246)	/* get VPD info */
-
-
-struct digi_debug {
-	int onoff;
-	int port;
-};
-
-#define DIGI_SETDEBUG      (('d'<<8) | 247)	/* set debug info */
-
-
-/*
- * dgrp_dpa_open -- open the DPA device for a particular PortServer
- */
-static int dgrp_dpa_open(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-	int rtn = 0;
-
-	rtn = try_module_get(THIS_MODULE);
-	if (!rtn)
-		return -ENXIO;
-
-	rtn = 0;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		rtn = -EPERM;
-		goto done;
-	}
-
-	/*
-	 *  Make sure that the "private_data" field hasn't already been used.
-	 */
-	if (file->private_data) {
-		rtn = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 *  Get the node pointer, and fail if it doesn't exist.
-	 */
-	nd = PDE_DATA(inode);
-	if (!nd) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	file->private_data = (void *) nd;
-
-	/*
-	 * Allocate the DPA buffer.
-	 */
-
-	if (nd->nd_dpa_buf) {
-		rtn = -EBUSY;
-	} else {
-		nd->nd_dpa_buf = kmalloc(DPA_MAX, GFP_KERNEL);
-
-		if (!nd->nd_dpa_buf) {
-			rtn = -ENOMEM;
-		} else {
-			nd->nd_dpa_out = 0;
-			nd->nd_dpa_in = 0;
-			nd->nd_dpa_lbolt = jiffies;
-		}
-	}
-
-done:
-
-	if (rtn)
-		module_put(THIS_MODULE);
-	return rtn;
-}
-
-/*
- * dgrp_dpa_release -- close the DPA device for a particular PortServer
- */
-static int dgrp_dpa_release(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-	u8 *buf;
-	unsigned long lock_flags;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		goto done;
-
-	/*
-	 *  Free the dpa buffer.
-	 */
-
-	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-
-	buf = nd->nd_dpa_buf;
-
-	nd->nd_dpa_buf = NULL;
-	nd->nd_dpa_out = nd->nd_dpa_in;
-
-	/*
-	 *  Wakeup any thread waiting for buffer space.
-	 */
-
-	if (nd->nd_dpa_flag & DPA_WAIT_SPACE) {
-		nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
-		wake_up_interruptible(&nd->nd_dpa_wqueue);
-	}
-
-	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-
-	kfree(buf);
-
-done:
-	module_put(THIS_MODULE);
-	file->private_data = NULL;
-	return 0;
-}
-
-/*
- * dgrp_dpa_read
- *
- * Copy data from the monitoring buffer to the user, freeing space
- * in the monitoring buffer for more messages
- */
-static ssize_t dgrp_dpa_read(struct file *file, char __user *buf, size_t count,
-			     loff_t *ppos)
-{
-	struct nd_struct *nd;
-	int n;
-	int r;
-	int offset = 0;
-	int res = 0;
-	ssize_t rtn;
-	unsigned long lock_flags;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		return -ENXIO;
-
-	/*
-	 *  Wait for some data to appear in the buffer.
-	 */
-
-	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-
-	for (;;) {
-		n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
-
-		if (n != 0)
-			break;
-
-		nd->nd_dpa_flag |= DPA_WAIT_DATA;
-
-		spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-
-		/*
-		 * Go to sleep waiting until the condition becomes true.
-		 */
-		rtn = wait_event_interruptible(nd->nd_dpa_wqueue,
-			((nd->nd_dpa_flag & DPA_WAIT_DATA) == 0));
-
-		if (rtn)
-			return rtn;
-
-		spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-	}
-
-	/*
-	 *  Read whatever is there.
-	 */
-
-	if (n > count)
-		n = count;
-
-	res = n;
-
-	r = DPA_MAX - nd->nd_dpa_out;
-
-	if (r <= n) {
-
-		spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-		rtn = copy_to_user((void __user *)buf,
-				   nd->nd_dpa_buf + nd->nd_dpa_out, r);
-		spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-
-		if (rtn) {
-			rtn = -EFAULT;
-			goto done;
-		}
-
-		nd->nd_dpa_out = 0;
-		n -= r;
-		offset = r;
-	}
-
-	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-	rtn = copy_to_user((void __user *)buf + offset,
-			   nd->nd_dpa_buf + nd->nd_dpa_out, n);
-	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-
-	if (rtn) {
-		rtn = -EFAULT;
-		goto done;
-	}
-
-	nd->nd_dpa_out += n;
-
-	*ppos += res;
-
-	rtn = res;
-
-	/*
-	 *  Wakeup any thread waiting for buffer space.
-	 */
-
-	n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
-
-	if (nd->nd_dpa_flag & DPA_WAIT_SPACE &&
-	    (DPA_MAX - n) > DPA_HIGH_WATER) {
-		nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
-		wake_up_interruptible(&nd->nd_dpa_wqueue);
-	}
-
- done:
-	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-	return rtn;
-}
-
-static unsigned int dgrp_dpa_select(struct file *file,
-				    struct poll_table_struct *table)
-{
-	unsigned int retval = 0;
-	struct nd_struct *nd = file->private_data;
-
-	if (nd->nd_dpa_out != nd->nd_dpa_in)
-		retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
-
-	retval |= POLLOUT | POLLWRNORM;        /* Always writeable */
-
-	return retval;
-}
-
-static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg)
-{
-
-	struct nd_struct  *nd;
-	struct digi_chan getchan;
-	struct digi_node getnode;
-	struct ch_struct *ch;
-	struct digi_debug setdebug;
-	struct digi_vpd vpd;
-	unsigned int port;
-	void __user *uarg = (void __user *) arg;
-
-	nd = file->private_data;
-
-	switch (cmd) {
-	case DIGI_GETCHAN:
-		if (copy_from_user(&getchan, uarg, sizeof(struct digi_chan)))
-			return -EFAULT;
-
-		port = getchan.ch_port;
-
-		if (port > nd->nd_chan_count)
-			return -EINVAL;
-
-		ch = nd->nd_chan + port;
-
-		getchan.ch_open = (ch->ch_open_count > 0) ? 1 : 0;
-		getchan.ch_txcount = ch->ch_txcount;
-		getchan.ch_rxcount = ch->ch_rxcount;
-		getchan.ch_s_brate = ch->ch_s_brate;
-		getchan.ch_s_estat = ch->ch_s_elast;
-		getchan.ch_s_cflag = ch->ch_s_cflag;
-		getchan.ch_s_iflag = ch->ch_s_iflag;
-		getchan.ch_s_oflag = ch->ch_s_oflag;
-		getchan.ch_s_xflag = ch->ch_s_xflag;
-		getchan.ch_s_mstat = ch->ch_s_mlast;
-
-		if (copy_to_user(uarg, &getchan, sizeof(struct digi_chan)))
-			return -EFAULT;
-		break;
-
-
-	case DIGI_GETNODE:
-		getnode.nd_state = (nd->nd_state & NS_READY) ? 1 : 0;
-		getnode.nd_chan_count = nd->nd_chan_count;
-		getnode.nd_tx_byte = nd->nd_tx_byte;
-		getnode.nd_rx_byte = nd->nd_rx_byte;
-
-		memset(&getnode.nd_ps_desc, 0, MAX_DESC_LEN);
-		strlcpy(getnode.nd_ps_desc, nd->nd_ps_desc, MAX_DESC_LEN);
-
-		if (copy_to_user(uarg, &getnode, sizeof(struct digi_node)))
-			return -EFAULT;
-		break;
-
-
-	case DIGI_SETDEBUG:
-		if (copy_from_user(&setdebug, uarg, sizeof(struct digi_debug)))
-			return -EFAULT;
-
-		nd->nd_dpa_debug = setdebug.onoff;
-		nd->nd_dpa_port = setdebug.port;
-		break;
-
-
-	case DIGI_GETVPD:
-		memset(&vpd, 0, sizeof(vpd));
-		if (nd->nd_vpd_len > 0) {
-			vpd.vpd_len = nd->nd_vpd_len;
-			memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len);
-		} else {
-			vpd.vpd_len = 0;
-		}
-
-		if (copy_to_user(uarg, &vpd, sizeof(struct digi_vpd)))
-			return -EFAULT;
-		break;
-	}
-
-	return 0;
-}
-
-/**
- * dgrp_dpa() -- send data to the device monitor queue
- * @nd: pointer to a node structure
- * @buf: buffer of data to copy to the monitoring buffer
- * @len: number of bytes to transfer to the buffer
- *
- * Called by the net device routines to send data to the device
- * monitor queue.  If the device monitor buffer is too full to
- * accept the data, it waits until the buffer is ready.
- */
-static void dgrp_dpa(struct nd_struct *nd, u8 *buf, int nbuf)
-{
-	int n;
-	int r;
-	unsigned long lock_flags;
-
-	/*
-	 *  Grab DPA lock.
-	 */
-	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
-
-	/*
-	 *  Loop while data remains.
-	 */
-	while (nbuf > 0 && nd->nd_dpa_buf != NULL) {
-
-		n = (nd->nd_dpa_out - nd->nd_dpa_in - 1) & DPA_MASK;
-
-		/*
-		 * Enforce flow control on the DPA device.
-		 */
-		if (n < (DPA_MAX - DPA_HIGH_WATER))
-			nd->nd_dpa_flag |= DPA_WAIT_SPACE;
-
-		/*
-		 * This should never happen, as the flow control above
-		 * should have stopped things before they got to this point.
-		 */
-		if (n == 0) {
-			spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-			return;
-		}
-
-		/*
-		 * Copy as much data as will fit.
-		 */
-
-		if (n > nbuf)
-			n = nbuf;
-
-		r = DPA_MAX - nd->nd_dpa_in;
-
-		if (r <= n) {
-			memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, r);
-
-			n -= r;
-
-			nd->nd_dpa_in = 0;
-
-			buf += r;
-			nbuf -= r;
-		}
-
-		memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, n);
-
-		nd->nd_dpa_in += n;
-
-		buf += n;
-		nbuf -= n;
-
-		if (nd->nd_dpa_in >= DPA_MAX)
-			pr_info_ratelimited("%s - nd->nd_dpa_in (%i) >= DPA_MAX\n",
-					    __func__, nd->nd_dpa_in);
-
-		/*
-		 *  Wakeup any thread waiting for data
-		 */
-		if (nd->nd_dpa_flag & DPA_WAIT_DATA) {
-			nd->nd_dpa_flag &= ~DPA_WAIT_DATA;
-			wake_up_interruptible(&nd->nd_dpa_wqueue);
-		}
-	}
-
-	/*
-	 *  Release the DPA lock.
-	 */
-	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
-}
-
-/**
- * dgrp_monitor_data() -- builds a DPA data packet
- * @nd: pointer to a node structure
- * @type: type of message to be logged in the DPA buffer
- * @buf: buffer of data to be logged in the DPA buffer
- * @size -- number of bytes in the "buf" buffer
- */
-void dgrp_dpa_data(struct nd_struct *nd, int type, u8 *buf, int size)
-{
-	u8 header[5];
-
-	header[0] = type;
-
-	put_unaligned_be32(size, header + 1);
-
-	dgrp_dpa(nd, header, sizeof(header));
-	dgrp_dpa(nd, buf, size);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_driver.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_driver.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_driver.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-/*
- *
- * Copyright 1999-2003 Digi International (www.digi.com)
- *     Jeff Randall
- *     James Puzzo  <jamesp at digi dot com>
- *     Scott Kilau  <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *	Driver specific includes
- */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-
-/*
- *  PortServer includes
- */
-#include "dgrp_common.h"
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Digi International, http://www.digi.com");
-MODULE_DESCRIPTION("RealPort driver for Digi's ethernet-based serial connectivity product line");
-MODULE_VERSION(DIGI_VERSION);
-
-struct list_head nd_struct_list;
-struct dgrp_poll_data dgrp_poll_data;
-
-int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */
-int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */
-int dgrp_poll_tick = 20;	/* Poll interval - in ms */
-
-module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644);
-MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices");
-
-module_param_named(register_prdevices, dgrp_register_prdevices, int, 0644);
-MODULE_PARM_DESC(register_prdevices, "Turn on/off registering transparent print devices");
-
-module_param_named(pollrate, dgrp_poll_tick, int, 0644);
-MODULE_PARM_DESC(pollrate, "Poll interval in ms");
-
-/*
- * init_module()
- *
- * Module load.  This is where it all starts.
- */
-static int __init dgrp_init_module(void)
-{
-	int ret;
-
-	INIT_LIST_HEAD(&nd_struct_list);
-
-	spin_lock_init(&dgrp_poll_data.poll_lock);
-	init_timer(&dgrp_poll_data.timer);
-	dgrp_poll_data.poll_tick = dgrp_poll_tick;
-	dgrp_poll_data.timer.function = dgrp_poll_handler;
-	dgrp_poll_data.timer.data = (unsigned long) &dgrp_poll_data;
-
-	ret = dgrp_create_class_sysfs_files();
-	if (ret)
-		return ret;
-
-	dgrp_register_proc();
-
-	return 0;
-}
-
-
-/*
- *	Module unload.  This is where it all ends.
- */
-static void __exit dgrp_cleanup_module(void)
-{
-	struct nd_struct *nd, *next;
-
-	/*
-	 *	Attempting to free resources in backwards
-	 *	order of allocation, in case that helps
-	 *	memory pool fragmentation.
-	 */
-	dgrp_unregister_proc();
-
-	dgrp_remove_class_sysfs_files();
-
-
-	list_for_each_entry_safe(nd, next, &nd_struct_list, list) {
-		dgrp_tty_uninit(nd);
-		kfree(nd);
-	}
-}
-
-module_init(dgrp_init_module);
-module_exit(dgrp_cleanup_module);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_mon_ops.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_mon_ops.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_mon_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_mon_ops.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,327 +0,0 @@
-/*****************************************************************************
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_mon_ops.c
- *
- *  Description:
- *
- *     Handle the file operations required for the "monitor" devices.
- *     Includes those functions required to register the "mon" devices
- *     in "/proc".
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <asm/unaligned.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/uaccess.h>
-
-#include "dgrp_common.h"
-
-/* File operation declarations */
-static int dgrp_mon_open(struct inode *, struct file *);
-static int dgrp_mon_release(struct inode *, struct file *);
-static ssize_t dgrp_mon_read(struct file *, char __user *, size_t, loff_t *);
-static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg);
-
-const struct file_operations dgrp_mon_ops = {
-	.owner   = THIS_MODULE,
-	.read    = dgrp_mon_read,
-	.unlocked_ioctl = dgrp_mon_ioctl,
-	.open    = dgrp_mon_open,
-	.release = dgrp_mon_release,
-};
-
-/**
- * dgrp_mon_open() -- open /proc/dgrp/ports device for a PortServer
- * @inode: struct inode *
- * @file: struct file *
- *
- * Open function to open the /proc/dgrp/ports device for a PortServer.
- */
-static int dgrp_mon_open(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-	struct timeval tv;
-	uint32_t time;
-	u8 *buf;
-	int rtn;
-
-	rtn = try_module_get(THIS_MODULE);
-	if (!rtn)
-		return -ENXIO;
-
-	rtn = 0;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		rtn = -EPERM;
-		goto done;
-	}
-
-	/*
-	 *  Make sure that the "private_data" field hasn't already been used.
-	 */
-	if (file->private_data) {
-		rtn = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 *  Get the node pointer, and fail if it doesn't exist.
-	 */
-	nd = PDE_DATA(inode);
-	if (!nd) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	file->private_data = (void *) nd;
-
-	/*
-	 * Allocate the monitor buffer.
-	 */
-
-	/*
-	 *  Grab the MON lock.
-	 */
-	down(&nd->nd_mon_semaphore);
-
-	if (nd->nd_mon_buf) {
-		rtn = -EBUSY;
-		goto done_up;
-	}
-
-	nd->nd_mon_buf = kmalloc(MON_MAX, GFP_KERNEL);
-
-	if (!nd->nd_mon_buf) {
-		rtn = -ENOMEM;
-		goto done_up;
-	}
-
-	/*
-	 *  Enter an RPDUMP file header into the buffer.
-	 */
-
-	buf = nd->nd_mon_buf;
-
-	strcpy(buf, RPDUMP_MAGIC);
-	buf += strlen(buf) + 1;
-
-	do_gettimeofday(&tv);
-
-	/*
-	 *  tv.tv_sec might be a 64 bit quantity.  Pare
-	 *  it down to 32 bits before attempting to encode
-	 *  it.
-	 */
-	time = (uint32_t) (tv.tv_sec & 0xffffffff);
-
-	put_unaligned_be32(time, buf);
-	put_unaligned_be16(0, buf + 4);
-	buf += 6;
-
-	if (nd->nd_tx_module) {
-		buf[0] = RPDUMP_CLIENT;
-		put_unaligned_be32(0, buf + 1);
-		put_unaligned_be16(1, buf + 5);
-		buf[7] = 0xf0 + nd->nd_tx_module;
-		buf += 8;
-	}
-
-	if (nd->nd_rx_module) {
-		buf[0] = RPDUMP_SERVER;
-		put_unaligned_be32(0, buf + 1);
-		put_unaligned_be16(1, buf + 5);
-		buf[7] = 0xf0 + nd->nd_rx_module;
-		buf += 8;
-	}
-
-	nd->nd_mon_out = 0;
-	nd->nd_mon_in  = buf - nd->nd_mon_buf;
-	nd->nd_mon_lbolt = jiffies;
-
-done_up:
-	up(&nd->nd_mon_semaphore);
-
-done:
-	if (rtn)
-		module_put(THIS_MODULE);
-	return rtn;
-}
-
-
-/**
- * dgrp_mon_release() - Close the MON device for a particular PortServer
- * @inode: struct inode *
- * @file: struct file *
- */
-static int dgrp_mon_release(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		goto done;
-
-	/*
-	 *  Free the monitor buffer.
-	 */
-
-	down(&nd->nd_mon_semaphore);
-
-	kfree(nd->nd_mon_buf);
-	nd->nd_mon_buf = NULL;
-	nd->nd_mon_out = nd->nd_mon_in;
-
-	/*
-	 *  Wakeup any thread waiting for buffer space.
-	 */
-
-	if (nd->nd_mon_flag & MON_WAIT_SPACE) {
-		nd->nd_mon_flag &= ~MON_WAIT_SPACE;
-		wake_up_interruptible(&nd->nd_mon_wqueue);
-	}
-
-	up(&nd->nd_mon_semaphore);
-
-	/*
-	 *  Make sure there is no thread in the middle of writing a packet.
-	 */
-	down(&nd->nd_net_semaphore);
-	up(&nd->nd_net_semaphore);
-
-done:
-	module_put(THIS_MODULE);
-	file->private_data = NULL;
-	return 0;
-}
-
-/**
- * dgrp_mon_read() -- Copy data from the monitoring buffer to the user
- */
-static ssize_t dgrp_mon_read(struct file *file, char __user *buf, size_t count,
-			     loff_t *ppos)
-{
-	struct nd_struct *nd;
-	int r;
-	int offset = 0;
-	int res = 0;
-	ssize_t rtn;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		return -ENXIO;
-
-	/*
-	 *  Wait for some data to appear in the buffer.
-	 */
-
-	down(&nd->nd_mon_semaphore);
-
-	for (;;) {
-		res = (nd->nd_mon_in - nd->nd_mon_out) & MON_MASK;
-
-		if (res)
-			break;
-
-		nd->nd_mon_flag |= MON_WAIT_DATA;
-
-		up(&nd->nd_mon_semaphore);
-
-		/*
-		 * Go to sleep waiting until the condition becomes true.
-		 */
-		rtn = wait_event_interruptible(nd->nd_mon_wqueue,
-					       ((nd->nd_mon_flag & MON_WAIT_DATA) == 0));
-
-		if (rtn)
-			return rtn;
-
-		down(&nd->nd_mon_semaphore);
-	}
-
-	/*
-	 *  Read whatever is there.
-	 */
-
-	if (res > count)
-		res = count;
-
-	r = MON_MAX - nd->nd_mon_out;
-
-	if (r <= res) {
-		rtn = copy_to_user((void __user *)buf,
-				   nd->nd_mon_buf + nd->nd_mon_out, r);
-		if (rtn) {
-			up(&nd->nd_mon_semaphore);
-			return -EFAULT;
-		}
-
-		nd->nd_mon_out = 0;
-		res -= r;
-		offset = r;
-	}
-
-	rtn = copy_to_user((void __user *) buf + offset,
-			   nd->nd_mon_buf + nd->nd_mon_out, res);
-	if (rtn) {
-		up(&nd->nd_mon_semaphore);
-		return -EFAULT;
-	}
-
-	nd->nd_mon_out += res;
-
-	*ppos += res;
-
-	up(&nd->nd_mon_semaphore);
-
-	/*
-	 *  Wakeup any thread waiting for buffer space.
-	 */
-
-	if (nd->nd_mon_flag & MON_WAIT_SPACE) {
-		nd->nd_mon_flag &= ~MON_WAIT_SPACE;
-		wake_up_interruptible(&nd->nd_mon_wqueue);
-	}
-
-	return res;
-}
-
-/*  ioctl is not valid on monitor device */
-static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg)
-{
-	return -EINVAL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_net_ops.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_net_ops.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_net_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_net_ops.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3666 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo  <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_net_ops.c
- *
- *  Description:
- *
- *     Handle the file operations required for the "network" devices.
- *     Includes those functions required to register the "net" devices
- *     in "/proc".
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/ratelimit.h>
-#include <asm/unaligned.h>
-
-#define MYFLIPLEN	TBUF_MAX
-
-#include "dgrp_common.h"
-
-#define TTY_FLIPBUF_SIZE 512
-#define DEVICE_NAME_SIZE 50
-
-/*
- *  Generic helper function declarations
- */
-static void   parity_scan(struct ch_struct *ch, unsigned char *cbuf,
-				unsigned char *fbuf, int *len);
-
-/*
- *  File operation declarations
- */
-static int dgrp_net_open(struct inode *, struct file *);
-static int dgrp_net_release(struct inode *, struct file *);
-static ssize_t dgrp_net_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t dgrp_net_write(struct file *, const char __user *, size_t,
-			      loff_t *);
-static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg);
-static unsigned int dgrp_net_select(struct file *file,
-				    struct poll_table_struct *table);
-
-const struct file_operations dgrp_net_ops = {
-	.owner   =  THIS_MODULE,
-	.read    =  dgrp_net_read,
-	.write   =  dgrp_net_write,
-	.poll    =  dgrp_net_select,
-	.unlocked_ioctl =  dgrp_net_ioctl,
-	.open    =  dgrp_net_open,
-	.release =  dgrp_net_release,
-};
-
-/**
- * dgrp_dump() -- prints memory for debugging purposes.
- * @mem: Memory location which should be printed to the console
- * @len: Number of bytes to be dumped
- */
-static void dgrp_dump(u8 *mem, int len)
-{
-	int i;
-
-	pr_debug("dgrp dump length = %d, data = ", len);
-	for (i = 0; i < len; ++i)
-		pr_debug("%.2x ", mem[i]);
-	pr_debug("\n");
-}
-
-/**
- * dgrp_read_data_block() -- Read a data block
- * @ch: struct ch_struct *
- * @flipbuf: u8 *
- * @flipbuf_size: size of flipbuf
- */
-static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf,
-				 int flipbuf_size)
-{
-	int t;
-	int n;
-
-	if (flipbuf_size <= 0)
-		return;
-
-	t = RBUF_MAX - ch->ch_rout;
-	n = flipbuf_size;
-
-	if (n >= t) {
-		memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, t);
-		flipbuf += t;
-		n -= t;
-		ch->ch_rout = 0;
-	}
-
-	memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, n);
-	flipbuf += n;
-	ch->ch_rout += n;
-}
-
-
-/**
- * dgrp_input() -- send data to the line disipline
- * @ch: pointer to channel struct
- *
- * Copys the rbuf to the flipbuf and sends to line discipline.
- * Sends input buffer data to the line discipline.
- *
- */
-static void dgrp_input(struct ch_struct *ch)
-{
-	struct nd_struct *nd;
-	struct tty_struct *tty;
-	int data_len;
-	int len;
-	int tty_count;
-	ulong lock_flags;
-	u8  *myflipbuf;
-	u8  *myflipflagbuf;
-
-	if (!ch)
-		return;
-
-	nd = ch->ch_nd;
-
-	if (!nd)
-		return;
-
-	spin_lock_irqsave(&nd->nd_lock, lock_flags);
-
-	myflipbuf = nd->nd_inputbuf;
-	myflipflagbuf = nd->nd_inputflagbuf;
-
-	if (!ch->ch_open_count) {
-		ch->ch_rout = ch->ch_rin;
-		goto out;
-	}
-
-	if (ch->ch_tun.un_flag & UN_CLOSING) {
-		ch->ch_rout = ch->ch_rin;
-		goto out;
-	}
-
-	tty = (ch->ch_tun).un_tty;
-
-
-	if (!tty || tty->magic != TTY_MAGIC) {
-		ch->ch_rout = ch->ch_rin;
-		goto out;
-	}
-
-	tty_count = tty->count;
-	if (!tty_count) {
-		ch->ch_rout = ch->ch_rin;
-		goto out;
-	}
-
-	if (tty->closing || test_bit(TTY_CLOSING, &tty->flags)) {
-		ch->ch_rout = ch->ch_rin;
-		goto out;
-	}
-
-	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-
-	/* data_len should be the number of chars that we read in */
-	data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK;
-
-	/* len is the amount of data we are going to transfer here */
-	len = tty_buffer_request_room(&ch->port, data_len);
-
-	/* Check DPA flow control */
-	if ((nd->nd_dpa_debug) &&
-	    (nd->nd_dpa_flag & DPA_WAIT_SPACE) &&
-	    (nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty))))
-		len = 0;
-
-	if ((len) && !(ch->ch_flag & CH_RXSTOP)) {
-
-		dgrp_read_data_block(ch, myflipbuf, len);
-
-		if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
-			parity_scan(ch, myflipbuf, myflipflagbuf, &len);
-		else
-			memset(myflipflagbuf, TTY_NORMAL, len);
-
-		if ((nd->nd_dpa_debug) &&
-		    (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty)))))
-			dgrp_dpa_data(nd, 1, myflipbuf, len);
-
-		tty_insert_flip_string_flags(&ch->port, myflipbuf,
-					     myflipflagbuf, len);
-		tty_flip_buffer_push(&ch->port);
-
-		ch->ch_rxcount += len;
-	}
-
-	/*
-	 * Wake up any sleepers (maybe dgrp close) that might be waiting
-	 * for a channel flag state change.
-	 */
-	wake_up_interruptible(&ch->ch_flag_wait);
-	return;
-
-out:
-	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-}
-
-
-/*
- *  parity_scan
- *
- *  Loop to inspect each single character or 0xFF escape.
- *
- *  if PARMRK & ~DOSMODE:
- *     0xFF  0xFF           Normal 0xFF character, escaped
- *                          to eliminate confusion.
- *     0xFF  0x00  0x00     Break
- *     0xFF  0x00  CC       Error character CC.
- *     CC                   Normal character CC.
- *
- *  if PARMRK & DOSMODE:
- *     0xFF  0x18  0x00     Break
- *     0xFF  0x08  0x00     Framing Error
- *     0xFF  0x04  0x00     Parity error
- *     0xFF  0x0C  0x00     Both Framing and Parity error
- *
- *  TODO:  do we need to do the XMODEM, XOFF, XON, XANY processing??
- *         as per protocol
- */
-static void parity_scan(struct ch_struct *ch, unsigned char *cbuf,
-			unsigned char *fbuf, int *len)
-{
-	int l = *len;
-	int count = 0;
-	int DOS = ((ch->ch_iflag & IF_DOSMODE) == 0 ? 0 : 1);
-	unsigned char *cout; /* character buffer */
-	unsigned char *fout; /* flag buffer */
-	unsigned char *in;
-	unsigned char c;
-
-	in = cbuf;
-	cout = cbuf;
-	fout = fbuf;
-
-	while (l--) {
-		c = *in;
-		in++;
-
-		switch (ch->ch_pscan_state) {
-		default:
-			/* reset to sanity and fall through */
-			ch->ch_pscan_state = 0;
-
-		case 0:
-			/* No FF seen yet */
-			if (c == 0xff) /* delete this character from stream */
-				ch->ch_pscan_state = 1;
-			else {
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-			}
-			break;
-
-		case 1:
-			/* first FF seen */
-			if (c == 0xff) {
-				/* doubled ff, transform to single ff */
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-				ch->ch_pscan_state = 0;
-			} else {
-				/* save value examination in next state */
-				ch->ch_pscan_savechar = c;
-				ch->ch_pscan_state = 2;
-			}
-			break;
-
-		case 2:
-			/* third character of ff sequence */
-			*cout++ = c;
-			if (DOS) {
-				if (ch->ch_pscan_savechar & 0x10)
-					*fout++ = TTY_BREAK;
-				else if (ch->ch_pscan_savechar & 0x08)
-					*fout++ = TTY_FRAME;
-				else
-					/*
-					 * either marked as a parity error,
-					 * indeterminate, or not in DOSMODE
-					 * call it a parity error
-					 */
-					*fout++ = TTY_PARITY;
-			} else {
-				/* case FF XX ?? where XX is not 00 */
-				if (ch->ch_pscan_savechar & 0xff) {
-					/* this should not happen */
-					pr_info("%s: parity_scan: error unexpected byte\n",
-						__func__);
-					*fout++ = TTY_PARITY;
-				}
-				/* case FF 00 XX where XX is not 00 */
-				else if (c == 0xff)
-					*fout++ = TTY_PARITY;
-				/* case FF 00 00 */
-				else
-					*fout++ = TTY_BREAK;
-
-			}
-			count += 1;
-			ch->ch_pscan_state = 0;
-		}
-	}
-	*len = count;
-}
-
-
-/**
- * dgrp_net_idle() -- Idle the network connection
- * @nd: pointer to node structure to idle
- */
-static void dgrp_net_idle(struct nd_struct *nd)
-{
-	struct ch_struct *ch;
-	int i;
-
-	nd->nd_tx_work = 1;
-
-	nd->nd_state = NS_IDLE;
-	nd->nd_flag = 0;
-
-	for (i = nd->nd_seq_out; ; i = (i + 1) & SEQ_MASK) {
-		if (!nd->nd_seq_wait[i]) {
-			nd->nd_seq_wait[i] = 0;
-			wake_up_interruptible(&nd->nd_seq_wque[i]);
-		}
-
-		if (i == nd->nd_seq_in)
-			break;
-	}
-
-	nd->nd_seq_out = nd->nd_seq_in;
-
-	nd->nd_unack = 0;
-	nd->nd_remain = 0;
-
-	nd->nd_tx_module = 0x10;
-	nd->nd_rx_module = 0x00;
-
-	for (i = 0, ch = nd->nd_chan; i < CHAN_MAX; i++, ch++) {
-		ch->ch_state = CS_IDLE;
-
-		ch->ch_otype = 0;
-		ch->ch_otype_waiting = 0;
-	}
-}
-
-/*
- *  Increase the number of channels, waking up any
- *  threads that might be waiting for the channels
- *  to appear.
- */
-static void increase_channel_count(struct nd_struct *nd, int n)
-{
-	struct ch_struct *ch;
-	struct device *classp;
-	char name[DEVICE_NAME_SIZE];
-	int ret;
-	u8 *buf;
-	int i;
-
-	for (i = nd->nd_chan_count; i < n; ++i) {
-		ch = nd->nd_chan + i;
-
-		/* FIXME: return a useful error instead! */
-		buf = kmalloc(TBUF_MAX, GFP_KERNEL);
-		if (!buf)
-			return;
-
-		if (ch->ch_tbuf)
-			pr_info_ratelimited("%s - ch_tbuf was not NULL\n",
-					    __func__);
-
-		ch->ch_tbuf = buf;
-
-		buf = kmalloc(RBUF_MAX, GFP_KERNEL);
-		if (!buf)
-			return;
-
-		if (ch->ch_rbuf)
-			pr_info("%s - ch_rbuf was not NULL\n",
-				__func__);
-		ch->ch_rbuf = buf;
-
-		classp = tty_port_register_device(&ch->port,
-						  nd->nd_serial_ttdriver, i,
-						  NULL);
-
-		ch->ch_tun.un_sysfs = classp;
-		snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i);
-
-		dgrp_create_tty_sysfs(&ch->ch_tun, classp);
-		ret = sysfs_create_link(&nd->nd_class_dev->kobj,
-					&classp->kobj, name);
-
-		/* NOTE: We don't support "cu" devices anymore,
-		 * so you will notice we don't register them
-		 * here anymore. */
-		if (dgrp_register_prdevices) {
-			classp = tty_register_device(nd->nd_xprint_ttdriver,
-						     i, NULL);
-			ch->ch_pun.un_sysfs = classp;
-			snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i);
-
-			dgrp_create_tty_sysfs(&ch->ch_pun, classp);
-			ret = sysfs_create_link(&nd->nd_class_dev->kobj,
-						&classp->kobj, name);
-		}
-
-		nd->nd_chan_count = i + 1;
-		wake_up_interruptible(&ch->ch_flag_wait);
-	}
-}
-
-/*
- * Decrease the number of channels, and wake up any threads that might
- * be waiting on the channels that vanished.
- */
-static void decrease_channel_count(struct nd_struct *nd, int n)
-{
-	struct ch_struct *ch;
-	char name[DEVICE_NAME_SIZE];
-	int i;
-
-	for (i = nd->nd_chan_count - 1; i >= n; --i) {
-		ch = nd->nd_chan + i;
-
-		/*
-		 *  Make any open ports inoperative.
-		 */
-		ch->ch_state = CS_IDLE;
-
-		ch->ch_otype = 0;
-		ch->ch_otype_waiting = 0;
-
-		/*
-		 *  Only "HANGUP" if we care about carrier
-		 *  transitions and we are already open.
-		 */
-		if (ch->ch_open_count != 0) {
-			ch->ch_flag |= CH_HANGUP;
-			dgrp_carrier(ch);
-		}
-
-		/*
-		 * Unlike the CH_HANGUP flag above, use another
-		 * flag to indicate to the RealPort state machine
-		 * that this port has disappeared.
-		 */
-		if (ch->ch_open_count != 0)
-			ch->ch_flag |= CH_PORT_GONE;
-
-		wake_up_interruptible(&ch->ch_flag_wait);
-
-		nd->nd_chan_count = i;
-
-		kfree(ch->ch_tbuf);
-		ch->ch_tbuf = NULL;
-
-		kfree(ch->ch_rbuf);
-		ch->ch_rbuf = NULL;
-
-		nd->nd_chan_count = i;
-
-		dgrp_remove_tty_sysfs(ch->ch_tun.un_sysfs);
-		snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i);
-		sysfs_remove_link(&nd->nd_class_dev->kobj, name);
-		tty_unregister_device(nd->nd_serial_ttdriver, i);
-
-		/*
-		 * NOTE: We don't support "cu" devices anymore, so don't
-		 * unregister them here anymore.
-		 */
-
-		if (dgrp_register_prdevices) {
-			dgrp_remove_tty_sysfs(ch->ch_pun.un_sysfs);
-			snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i);
-			sysfs_remove_link(&nd->nd_class_dev->kobj, name);
-			tty_unregister_device(nd->nd_xprint_ttdriver, i);
-		}
-	}
-}
-
-/**
- * dgrp_chan_count() -- Adjust the node channel count.
- * @nd: pointer to a node structure
- * @n: new value for channel count
- *
- * Adjusts the node channel count.  If new ports have appeared, it tries
- * to signal those processes that might have been waiting for ports to
- * appear.  If ports have disappeared it tries to signal those processes
- * that might be hung waiting for a response for the now non-existant port.
- */
-static void dgrp_chan_count(struct nd_struct *nd, int n)
-{
-	if (n == nd->nd_chan_count)
-		return;
-
-	if (n > nd->nd_chan_count)
-		increase_channel_count(nd, n);
-
-	if (n < nd->nd_chan_count)
-		decrease_channel_count(nd, n);
-}
-
-/**
- * dgrp_monitor() -- send data to the device monitor queue
- * @nd: pointer to a node structure
- * @buf: data to copy to the monitoring buffer
- * @len: number of bytes to transfer to the buffer
- *
- * Called by the net device routines to send data to the device
- * monitor queue.  If the device monitor buffer is too full to
- * accept the data, it waits until the buffer is ready.
- */
-static void dgrp_monitor(struct nd_struct *nd, u8 *buf, int len)
-{
-	int n;
-	int r;
-	int rtn;
-
-	/*
-	 *  Grab monitor lock.
-	 */
-	down(&nd->nd_mon_semaphore);
-
-	/*
-	 *  Loop while data remains.
-	 */
-	while ((len > 0) && (nd->nd_mon_buf)) {
-		/*
-		 *  Determine the amount of available space left in the
-		 *  buffer.  If there's none, wait until some appears.
-		 */
-
-		n = (nd->nd_mon_out - nd->nd_mon_in - 1) & MON_MASK;
-
-		if (!n) {
-			nd->nd_mon_flag |= MON_WAIT_SPACE;
-
-			up(&nd->nd_mon_semaphore);
-
-			/*
-			 * Go to sleep waiting until the condition becomes true.
-			 */
-			rtn = wait_event_interruptible(nd->nd_mon_wqueue,
-						       ((nd->nd_mon_flag & MON_WAIT_SPACE) == 0));
-
-/* FIXME: really ignore rtn? */
-
-			/*
-			 *  We can't exit here if we receive a signal, since
-			 *  to do so would trash the debug stream.
-			 */
-
-			down(&nd->nd_mon_semaphore);
-
-			continue;
-		}
-
-		/*
-		 * Copy as much data as will fit.
-		 */
-
-		if (n > len)
-			n = len;
-
-		r = MON_MAX - nd->nd_mon_in;
-
-		if (r <= n) {
-			memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, r);
-
-			n -= r;
-
-			nd->nd_mon_in = 0;
-
-			buf += r;
-			len -= r;
-		}
-
-		memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, n);
-
-		nd->nd_mon_in += n;
-
-		buf += n;
-		len -= n;
-
-		if (nd->nd_mon_in >= MON_MAX)
-			pr_info_ratelimited("%s - nd_mon_in (%i) >= MON_MAX\n",
-					    __func__, nd->nd_mon_in);
-
-		/*
-		 *  Wakeup any thread waiting for data
-		 */
-
-		if (nd->nd_mon_flag & MON_WAIT_DATA) {
-			nd->nd_mon_flag &= ~MON_WAIT_DATA;
-			wake_up_interruptible(&nd->nd_mon_wqueue);
-		}
-	}
-
-	/*
-	 *  Release the monitor lock.
-	 */
-	up(&nd->nd_mon_semaphore);
-}
-
-/**
- * dgrp_encode_time() -- Encodes rpdump time into a 4-byte quantity.
- * @nd: pointer to a node structure
- * @buf: destination buffer
- *
- * Encodes "rpdump" time into a 4-byte quantity.  Time is measured since
- * open.
- */
-static void dgrp_encode_time(struct nd_struct *nd, u8 *buf)
-{
-	ulong t;
-
-	/*
-	 *  Convert time in HZ since open to time in milliseconds
-	 *  since open.
-	 */
-	t = jiffies - nd->nd_mon_lbolt;
-	t = 1000 * (t / HZ) + 1000 * (t % HZ) / HZ;
-
-	put_unaligned_be32((uint)(t & 0xffffffff), buf);
-}
-
-
-
-/**
- * dgrp_monitor_message() -- Builds a rpdump style message.
- * @nd: pointer to a node structure
- * @message: destination buffer
- */
-static void dgrp_monitor_message(struct nd_struct *nd, char *message)
-{
-	u8 header[7];
-	int n;
-
-	header[0] = RPDUMP_MESSAGE;
-
-	dgrp_encode_time(nd, header + 1);
-
-	n = strlen(message);
-
-	put_unaligned_be16(n, header + 5);
-
-	dgrp_monitor(nd, header, sizeof(header));
-	dgrp_monitor(nd, (u8 *) message, n);
-}
-
-
-
-/**
- * dgrp_monitor_reset() -- Note a reset in the monitoring buffer.
- * @nd: pointer to a node structure
- */
-static void dgrp_monitor_reset(struct nd_struct *nd)
-{
-	u8 header[5];
-
-	header[0] = RPDUMP_RESET;
-
-	dgrp_encode_time(nd, header + 1);
-
-	dgrp_monitor(nd, header, sizeof(header));
-}
-
-/**
- * dgrp_monitor_data() -- builds a monitor data packet
- * @nd: pointer to a node structure
- * @type: type of message to be logged
- * @buf: data to be logged
- * @size: number of bytes in the buffer
- */
-static void dgrp_monitor_data(struct nd_struct *nd, u8 type, u8 *buf, int size)
-{
-	u8 header[7];
-
-	header[0] = type;
-
-	dgrp_encode_time(nd, header + 1);
-
-	put_unaligned_be16(size, header + 5);
-
-	dgrp_monitor(nd, header, sizeof(header));
-	dgrp_monitor(nd, buf, size);
-}
-
-static int alloc_nd_buffers(struct nd_struct *nd)
-{
-
-	nd->nd_iobuf = NULL;
-	nd->nd_writebuf = NULL;
-	nd->nd_inputbuf = NULL;
-	nd->nd_inputflagbuf = NULL;
-
-	/*
-	 *  Allocate the network read/write buffer.
-	 */
-	nd->nd_iobuf = kzalloc(UIO_MAX + 10, GFP_KERNEL);
-	if (!nd->nd_iobuf)
-		goto out_err;
-
-	/*
-	 * Allocate a buffer for doing the copy from user space to
-	 * kernel space in the write routines.
-	 */
-	nd->nd_writebuf = kzalloc(WRITEBUFLEN, GFP_KERNEL);
-	if (!nd->nd_writebuf)
-		goto out_err;
-
-	/*
-	 * Allocate a buffer for doing the copy from kernel space to
-	 * tty buffer space in the read routines.
-	 */
-	nd->nd_inputbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
-	if (!nd->nd_inputbuf)
-		goto out_err;
-
-	/*
-	 * Allocate a buffer for doing the copy from kernel space to
-	 * tty buffer space in the read routines.
-	 */
-	nd->nd_inputflagbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
-	if (!nd->nd_inputflagbuf)
-		goto out_err;
-
-	return 0;
-
-out_err:
-	kfree(nd->nd_iobuf);
-	kfree(nd->nd_writebuf);
-	kfree(nd->nd_inputbuf);
-	kfree(nd->nd_inputflagbuf);
-	return -ENOMEM;
-}
-
-/*
- * dgrp_net_open() -- Open the NET device for a particular PortServer
- */
-static int dgrp_net_open(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-	ulong  lock_flags;
-	int rtn;
-
-	rtn = try_module_get(THIS_MODULE);
-	if (!rtn)
-		return -EAGAIN;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		rtn = -EPERM;
-		goto done;
-	}
-
-	/*
-	 *  Make sure that the "private_data" field hasn't already been used.
-	 */
-	if (file->private_data) {
-		rtn = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 *  Get the node pointer, and fail if it doesn't exist.
-	 */
-	nd = PDE_DATA(inode);
-	if (!nd) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	file->private_data = (void *) nd;
-
-	/*
-	 *  Grab the NET lock.
-	 */
-	down(&nd->nd_net_semaphore);
-
-	if (nd->nd_state != NS_CLOSED) {
-		rtn = -EBUSY;
-		goto unlock;
-	}
-
-	/*
-	 *  Initialize the link speed parameters.
-	 */
-
-	nd->nd_link.lk_fast_rate = UIO_MAX;
-	nd->nd_link.lk_slow_rate = UIO_MAX;
-
-	nd->nd_link.lk_fast_delay = 1000;
-	nd->nd_link.lk_slow_delay = 1000;
-
-	nd->nd_link.lk_header_size = 46;
-
-
-	rtn = alloc_nd_buffers(nd);
-	if (rtn)
-		goto unlock;
-
-	/*
-	 *  The port is now open, so move it to the IDLE state
-	 */
-	dgrp_net_idle(nd);
-
-	nd->nd_tx_time = jiffies;
-
-	/*
-	 *  If the polling routing is not running, start it running here
-	 */
-	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
-
-	if (!dgrp_poll_data.node_active_count) {
-		dgrp_poll_data.node_active_count = 2;
-		dgrp_poll_data.timer.expires = jiffies +
-			dgrp_poll_tick * HZ / 1000;
-		add_timer(&dgrp_poll_data.timer);
-	}
-
-	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
-
-	dgrp_monitor_message(nd, "Net Open");
-
-unlock:
-	/*
-	 *  Release the NET lock.
-	 */
-	up(&nd->nd_net_semaphore);
-
-done:
-	if (rtn)
-		module_put(THIS_MODULE);
-
-	return rtn;
-}
-
-/* dgrp_net_release() -- close the NET device for a particular PortServer */
-static int dgrp_net_release(struct inode *inode, struct file *file)
-{
-	struct nd_struct *nd;
-	ulong  lock_flags;
-
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		goto done;
-
-/* TODO : historical locking placeholder */
-/*
- *  In the HPUX version of the RealPort driver (which served as a basis
- *  for this driver) this locking code was used.  Saved if ever we need
- *  to review the locking under Linux.
- */
-/*	spinlock(&nd->nd_lock); */
-
-
-	/*
-	 *  Grab the NET lock.
-	 */
-	down(&nd->nd_net_semaphore);
-
-	/*
-	 *  Before "closing" the internal connection, make sure all
-	 *  ports are "idle".
-	 */
-	dgrp_net_idle(nd);
-
-	nd->nd_state = NS_CLOSED;
-	nd->nd_flag = 0;
-
-	/*
-	 *  TODO ... must the wait queue be reset on close?
-	 *  should any pending waiters be reset?
-	 *  Let's decide to assert that the waitq is empty... and see
-	 *  how soon we break.
-	 */
-	if (waitqueue_active(&nd->nd_tx_waitq))
-		pr_info("%s - expected waitqueue_active to be false\n",
-			__func__);
-
-	nd->nd_send = 0;
-
-	kfree(nd->nd_iobuf);
-	nd->nd_iobuf = NULL;
-
-/* TODO : historical locking placeholder */
-/*
- *  In the HPUX version of the RealPort driver (which served as a basis
- *  for this driver) this locking code was used.  Saved if ever we need
- *  to review the locking under Linux.
- */
-/*	spinunlock( &nd->nd_lock ); */
-
-
-	kfree(nd->nd_writebuf);
-	nd->nd_writebuf = NULL;
-
-	kfree(nd->nd_inputbuf);
-	nd->nd_inputbuf = NULL;
-
-	kfree(nd->nd_inputflagbuf);
-	nd->nd_inputflagbuf = NULL;
-
-/* TODO : historical locking placeholder */
-/*
- *  In the HPUX version of the RealPort driver (which served as a basis
- *  for this driver) this locking code was used.  Saved if ever we need
- *  to review the locking under Linux.
- */
-/*	spinlock(&nd->nd_lock); */
-
-	/*
-	 *  Set the active port count to zero.
-	 */
-	dgrp_chan_count(nd, 0);
-
-/* TODO : historical locking placeholder */
-/*
- *  In the HPUX version of the RealPort driver (which served as a basis
- *  for this driver) this locking code was used.  Saved if ever we need
- *  to review the locking under Linux.
- */
-/*	spinunlock(&nd->nd_lock); */
-
-	/*
-	 *  Release the NET lock.
-	 */
-	up(&nd->nd_net_semaphore);
-
-	/*
-	 *  Cause the poller to stop scheduling itself if this is
-	 *  the last active node.
-	 */
-	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
-
-	if (dgrp_poll_data.node_active_count == 2) {
-		del_timer(&dgrp_poll_data.timer);
-		dgrp_poll_data.node_active_count = 0;
-	}
-
-	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
-
-	down(&nd->nd_net_semaphore);
-
-	dgrp_monitor_message(nd, "Net Close");
-
-	up(&nd->nd_net_semaphore);
-
-done:
-	module_put(THIS_MODULE);
-	file->private_data = NULL;
-	return 0;
-}
-
-/* used in dgrp_send to setup command header */
-static inline u8 *set_cmd_header(u8 *b, u8 port, u8 cmd)
-{
-	*b++ = 0xb0 + (port & 0x0f);
-	*b++ = cmd;
-	return b;
-}
-
-/**
- * dgrp_send() -- build a packet for transmission to the server
- * @nd: pointer to a node structure
- * @tmax: maximum bytes to transmit
- *
- * returns number of bytes sent
- */
-static int dgrp_send(struct nd_struct *nd, long tmax)
-{
-	struct ch_struct *ch = nd->nd_chan;
-	u8 *b;
-	u8 *buf;
-	u8 *mbuf;
-	u8 port;
-	int mod;
-	long send;
-	int maxport;
-	long lastport = -1;
-	ushort rwin;
-	long in;
-	ushort n;
-	long t;
-	long ttotal;
-	long tchan;
-	long tsend;
-	ushort tsafe;
-	long work;
-	long send_sync;
-	long wanted_sync_port = -1;
-	ushort tdata[CHAN_MAX];
-	long used_buffer;
-
-	mbuf = nd->nd_iobuf + UIO_BASE;
-	buf = b = mbuf;
-
-	send_sync = nd->nd_link.lk_slow_rate < UIO_MAX;
-
-	ttotal = 0;
-	tchan = 0;
-
-	memset(tdata, 0, sizeof(tdata));
-
-
-	/*
-	 * If there are any outstanding requests to be serviced,
-	 * service them here.
-	 */
-	if (nd->nd_send & NR_PASSWORD) {
-
-		/*
-		 *  Send Password response.
-		 */
-
-		b[0] = 0xfc;
-		b[1] = 0x20;
-		put_unaligned_be16(strlen(nd->password), b + 2);
-		b += 4;
-		b += strlen(nd->password);
-		nd->nd_send &= ~(NR_PASSWORD);
-	}
-
-
-	/*
-	 *  Loop over all modules to generate commands, and determine
-	 *  the amount of data queued for transmit.
-	 */
-
-	for (mod = 0, port = 0; port < nd->nd_chan_count; mod++) {
-		/*
-		 *  If this is not the current module, enter a module select
-		 *  code in the buffer.
-		 */
-
-		if (mod != nd->nd_tx_module)
-			mbuf = ++b;
-
-		/*
-		 *  Loop to process one module.
-		 */
-
-		maxport = port + 16;
-
-		if (maxport > nd->nd_chan_count)
-			maxport = nd->nd_chan_count;
-
-		for (; port < maxport; port++, ch++) {
-			/*
-			 *  Switch based on channel state.
-			 */
-
-			switch (ch->ch_state) {
-			/*
-			 *  Send requests when the port is closed, and there
-			 *  are no Open, Close or Cancel requests expected.
-			 */
-
-			case CS_IDLE:
-				/*
-				 * Wait until any open error code
-				 * has been delivered to all
-				 * associated ports.
-				 */
-
-				if (ch->ch_open_error) {
-					if (ch->ch_wait_count[ch->ch_otype]) {
-						work = 1;
-						break;
-					}
-
-					ch->ch_open_error = 0;
-				}
-
-				/*
-				 *  Wait until the channel HANGUP flag is reset
-				 *  before sending the first open.  We can only
-				 *  get to this state after a server disconnect.
-				 */
-
-				if ((ch->ch_flag & CH_HANGUP) != 0)
-					break;
-
-				/*
-				 *  If recovering from a TCP disconnect, or if
-				 *  there is an immediate open pending, send an
-				 *  Immediate Open request.
-				 */
-				if ((ch->ch_flag & CH_PORT_GONE) ||
-				    ch->ch_wait_count[OTYPE_IMMEDIATE] != 0) {
-					b = set_cmd_header(b, port, 10);
-					*b++ = 0;
-
-					ch->ch_state = CS_WAIT_OPEN;
-					ch->ch_otype = OTYPE_IMMEDIATE;
-					break;
-				}
-
-	/*
-	 *  If there is no Persistent or Incoming Open on the wait
-	 *  list in the server, and a thread is waiting for a
-	 *  Persistent or Incoming Open, send a Persistent or Incoming
-	 *  Open Request.
-	 */
-				if (ch->ch_otype_waiting == 0) {
-					if (ch->ch_wait_count[OTYPE_PERSISTENT] != 0) {
-						b = set_cmd_header(b, port, 10);
-						*b++ = 1;
-
-						ch->ch_state = CS_WAIT_OPEN;
-						ch->ch_otype = OTYPE_PERSISTENT;
-					} else if (ch->ch_wait_count[OTYPE_INCOMING] != 0) {
-						b = set_cmd_header(b, port, 10);
-						*b++ = 2;
-
-						ch->ch_state = CS_WAIT_OPEN;
-						ch->ch_otype = OTYPE_INCOMING;
-					}
-					break;
-				}
-
-				/*
-				 *  If a Persistent or Incoming Open is pending in
-				 *  the server, but there is no longer an open
-				 *  thread waiting for it, cancel the request.
-				 */
-
-				if (ch->ch_wait_count[ch->ch_otype_waiting] == 0) {
-					b = set_cmd_header(b, port, 10);
-					*b++ = 4;
-
-					ch->ch_state = CS_WAIT_CANCEL;
-					ch->ch_otype = ch->ch_otype_waiting;
-				}
-				break;
-
-				/*
-				 *  Send port parameter queries.
-				 */
-			case CS_SEND_QUERY:
-				/*
-				 *  Clear out all FEP state that might remain
-				 *  from the last connection.
-				 */
-
-				ch->ch_flag |= CH_PARAM;
-
-				ch->ch_flag &= ~CH_RX_FLUSH;
-
-				ch->ch_expect = 0;
-
-				ch->ch_s_tin   = 0;
-				ch->ch_s_tpos  = 0;
-				ch->ch_s_tsize = 0;
-				ch->ch_s_treq  = 0;
-				ch->ch_s_elast = 0;
-
-				ch->ch_s_rin   = 0;
-				ch->ch_s_rwin  = 0;
-				ch->ch_s_rsize = 0;
-
-				ch->ch_s_tmax  = 0;
-				ch->ch_s_ttime = 0;
-				ch->ch_s_rmax  = 0;
-				ch->ch_s_rtime = 0;
-				ch->ch_s_rlow  = 0;
-				ch->ch_s_rhigh = 0;
-
-				ch->ch_s_brate = 0;
-				ch->ch_s_iflag = 0;
-				ch->ch_s_cflag = 0;
-				ch->ch_s_oflag = 0;
-				ch->ch_s_xflag = 0;
-
-				ch->ch_s_mout  = 0;
-				ch->ch_s_mflow = 0;
-				ch->ch_s_mctrl = 0;
-				ch->ch_s_xon   = 0;
-				ch->ch_s_xoff  = 0;
-				ch->ch_s_lnext = 0;
-				ch->ch_s_xxon  = 0;
-				ch->ch_s_xxoff = 0;
-
-				/* Send Sequence Request */
-				b = set_cmd_header(b, port, 14);
-
-				/* Configure Event Conditions Packet */
-				b = set_cmd_header(b, port, 42);
-				put_unaligned_be16(0x02c0, b);
-				b += 2;
-				*b++ = (DM_DTR | DM_RTS | DM_CTS |
-					DM_DSR | DM_RI | DM_CD);
-
-				/* Send Status Request */
-				b = set_cmd_header(b, port, 16);
-
-				/* Send Buffer Request  */
-				b = set_cmd_header(b, port, 20);
-
-				/* Send Port Capability Request */
-				b = set_cmd_header(b, port, 22);
-
-				ch->ch_expect = (RR_SEQUENCE |
-						 RR_STATUS  |
-						 RR_BUFFER |
-						 RR_CAPABILITY);
-
-				ch->ch_state = CS_WAIT_QUERY;
-
-				/* Raise modem signals */
-				b = set_cmd_header(b, port, 44);
-
-				if (ch->ch_flag & CH_PORT_GONE)
-					ch->ch_s_mout = ch->ch_mout;
-				else
-					ch->ch_s_mout = ch->ch_mout = DM_DTR | DM_RTS;
-
-				*b++ = ch->ch_mout;
-				*b++ = ch->ch_s_mflow = 0;
-				*b++ = ch->ch_s_mctrl = ch->ch_mctrl = 0;
-
-				if (ch->ch_flag & CH_PORT_GONE)
-					ch->ch_flag &= ~CH_PORT_GONE;
-
-				break;
-
-			/*
-			 *  Handle normal open and ready mode.
-			 */
-
-			case CS_READY:
-
-				/*
-				 *  If the port is not open, and there are no
-				 *  no longer any ports requesting an open,
-				 *  then close the port.
-				 */
-
-				if (ch->ch_open_count == 0 &&
-				    ch->ch_wait_count[ch->ch_otype] == 0) {
-					goto send_close;
-				}
-
-	/*
-	 *  Process waiting input.
-	 *
-	 *  If there is no one to read it, discard the data.
-	 *
-	 *  Otherwise if we are not in fastcook mode, or if there is a
-	 *  fastcook thread waiting for data, send the data to the
-	 *  line discipline.
-	 */
-				if (ch->ch_rin != ch->ch_rout) {
-					if (ch->ch_tun.un_open_count == 0 ||
-					     (ch->ch_tun.un_flag & UN_CLOSING) ||
-					    (ch->ch_cflag & CF_CREAD) == 0) {
-						ch->ch_rout = ch->ch_rin;
-					} else if ((ch->ch_flag & CH_FAST_READ) == 0 ||
-							ch->ch_inwait != 0) {
-						dgrp_input(ch);
-
-						if (ch->ch_rin != ch->ch_rout)
-							work = 1;
-					}
-				}
-
-				/*
-				 *  Handle receive flush, and changes to
-				 *  server port parameters.
-				 */
-
-				if (ch->ch_flag & (CH_RX_FLUSH | CH_PARAM)) {
-				/*
-				 *  If we are in receive flush mode,
-				 *  and enough data has gone by, reset
-				 *  receive flush mode.
-				 */
-					if (ch->ch_flag & CH_RX_FLUSH) {
-						if (((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >
-						    ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK))
-							ch->ch_flag &= ~CH_RX_FLUSH;
-						else
-							work = 1;
-					}
-
-					/*
-					 *  Send TMAX, TTIME.
-					 */
-
-					if (ch->ch_s_tmax  != ch->ch_tmax ||
-					    ch->ch_s_ttime != ch->ch_ttime) {
-						b = set_cmd_header(b, port, 48);
-
-						ch->ch_s_tmax = ch->ch_tmax;
-						ch->ch_s_ttime = ch->ch_ttime;
-
-						put_unaligned_be16(ch->ch_s_tmax,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_ttime,
-								   b);
-						b += 2;
-					}
-
-					/*
-					 *  Send RLOW, RHIGH.
-					 */
-
-					if (ch->ch_s_rlow  != ch->ch_rlow ||
-					    ch->ch_s_rhigh != ch->ch_rhigh) {
-						b = set_cmd_header(b, port, 45);
-
-						ch->ch_s_rlow  = ch->ch_rlow;
-						ch->ch_s_rhigh = ch->ch_rhigh;
-
-						put_unaligned_be16(ch->ch_s_rlow,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_rhigh,
-								   b);
-						b += 2;
-					}
-
-					/*
-					 *  Send BRATE, CFLAG, IFLAG,
-					 *  OFLAG, XFLAG.
-					 */
-
-					if (ch->ch_s_brate != ch->ch_brate ||
-					    ch->ch_s_cflag != ch->ch_cflag ||
-					    ch->ch_s_iflag != ch->ch_iflag ||
-					    ch->ch_s_oflag != ch->ch_oflag ||
-					    ch->ch_s_xflag != ch->ch_xflag) {
-						b = set_cmd_header(b, port, 40);
-
-						ch->ch_s_brate = ch->ch_brate;
-						ch->ch_s_cflag = ch->ch_cflag;
-						ch->ch_s_iflag = ch->ch_iflag;
-						ch->ch_s_oflag = ch->ch_oflag;
-						ch->ch_s_xflag = ch->ch_xflag;
-
-						put_unaligned_be16(ch->ch_s_brate,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_cflag,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_iflag,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_oflag,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_xflag,
-								   b);
-						b += 2;
-					}
-
-					/*
-					 *  Send MOUT, MFLOW, MCTRL.
-					 */
-
-					if (ch->ch_s_mout  != ch->ch_mout  ||
-					    ch->ch_s_mflow != ch->ch_mflow ||
-					    ch->ch_s_mctrl != ch->ch_mctrl) {
-						b = set_cmd_header(b, port, 44);
-
-						*b++ = ch->ch_s_mout  = ch->ch_mout;
-						*b++ = ch->ch_s_mflow = ch->ch_mflow;
-						*b++ = ch->ch_s_mctrl = ch->ch_mctrl;
-					}
-
-					/*
-					 *  Send Flow control characters.
-					 */
-
-					if (ch->ch_s_xon   != ch->ch_xon   ||
-					    ch->ch_s_xoff  != ch->ch_xoff  ||
-					    ch->ch_s_lnext != ch->ch_lnext ||
-					    ch->ch_s_xxon  != ch->ch_xxon  ||
-					    ch->ch_s_xxoff != ch->ch_xxoff) {
-						b = set_cmd_header(b, port, 46);
-
-						*b++ = ch->ch_s_xon   = ch->ch_xon;
-						*b++ = ch->ch_s_xoff  = ch->ch_xoff;
-						*b++ = ch->ch_s_lnext = ch->ch_lnext;
-						*b++ = ch->ch_s_xxon  = ch->ch_xxon;
-						*b++ = ch->ch_s_xxoff = ch->ch_xxoff;
-					}
-
-					/*
-					 *  Send RMAX, RTIME.
-					 */
-
-					if (ch->ch_s_rmax != ch->ch_rmax ||
-					    ch->ch_s_rtime != ch->ch_rtime) {
-						b = set_cmd_header(b, port, 47);
-
-						ch->ch_s_rmax  = ch->ch_rmax;
-						ch->ch_s_rtime = ch->ch_rtime;
-
-						put_unaligned_be16(ch->ch_s_rmax,
-								   b);
-						b += 2;
-
-						put_unaligned_be16(ch->ch_s_rtime,
-								   b);
-						b += 2;
-					}
-
-					ch->ch_flag &= ~CH_PARAM;
-					wake_up_interruptible(&ch->ch_flag_wait);
-				}
-
-
-				/*
-				 *  Handle action commands.
-				 */
-
-				if (ch->ch_send != 0) {
-					/* int send = ch->ch_send & ~ch->ch_expect; */
-					send = ch->ch_send & ~ch->ch_expect;
-
-					/* Send character immediate */
-					if ((send & RR_TX_ICHAR) != 0) {
-						b = set_cmd_header(b, port, 60);
-
-						*b++ = ch->ch_xon;
-						ch->ch_expect |= RR_TX_ICHAR;
-					}
-
-					/* BREAK request */
-					if ((send & RR_TX_BREAK) != 0) {
-						if (ch->ch_break_time != 0) {
-							b = set_cmd_header(b, port, 61);
-							put_unaligned_be16(ch->ch_break_time,
-									   b);
-							b += 2;
-
-							ch->ch_expect |= RR_TX_BREAK;
-							ch->ch_break_time = 0;
-						} else {
-							ch->ch_send &= ~RR_TX_BREAK;
-							ch->ch_flag &= ~CH_TX_BREAK;
-							wake_up_interruptible(&ch->ch_flag_wait);
-						}
-					}
-
-					/*
-					 *  Flush input/output buffers.
-					 */
-
-					if ((send & (RR_RX_FLUSH | RR_TX_FLUSH)) != 0) {
-						b = set_cmd_header(b, port, 62);
-
-						*b++ = ((send & RR_TX_FLUSH) == 0 ? 1 :
-							(send & RR_RX_FLUSH) == 0 ? 2 : 3);
-
-						if (send & RR_RX_FLUSH) {
-							ch->ch_flush_seq = nd->nd_seq_in;
-							ch->ch_flag |= CH_RX_FLUSH;
-							work = 1;
-							send_sync = 1;
-							wanted_sync_port = port;
-						}
-
-						ch->ch_send &= ~(RR_RX_FLUSH | RR_TX_FLUSH);
-					}
-
-					/*  Pause input/output */
-					if ((send & (RR_RX_STOP | RR_TX_STOP)) != 0) {
-						b = set_cmd_header(b, port, 63);
-						*b = 0;
-
-						if ((send & RR_TX_STOP) != 0)
-							*b |= EV_OPU;
-
-						if ((send & RR_RX_STOP) != 0)
-							*b |= EV_IPU;
-
-						b++;
-
-						ch->ch_send &= ~(RR_RX_STOP | RR_TX_STOP);
-					}
-
-					/* Start input/output */
-					if ((send & (RR_RX_START | RR_TX_START)) != 0) {
-						b = set_cmd_header(b, port, 64);
-						*b = 0;
-
-						if ((send & RR_TX_START) != 0)
-							*b |= EV_OPU | EV_OPS | EV_OPX;
-
-						if ((send & RR_RX_START) != 0)
-							*b |= EV_IPU | EV_IPS;
-
-						b++;
-
-						ch->ch_send &= ~(RR_RX_START | RR_TX_START);
-					}
-				}
-
-
-				/*
-				 *  Send a window sequence to acknowledge received data.
-				 */
-
-				rwin = (ch->ch_s_rin +
-					((ch->ch_rout - ch->ch_rin - 1) & RBUF_MASK));
-
-				n = (rwin - ch->ch_s_rwin) & 0xffff;
-
-				if (n >= RBUF_MAX / 4) {
-					b[0] = 0xa0 + (port & 0xf);
-					ch->ch_s_rwin = rwin;
-					put_unaligned_be16(rwin, b + 1);
-					b += 3;
-				}
-
-				/*
-				 *  If the terminal is waiting on LOW
-				 *  water or EMPTY, and the condition
-				 *  is now satisfied, call the line
-				 *  discipline to put more data in the
-				 *  buffer.
-				 */
-
-				n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-
-				if ((ch->ch_tun.un_flag & (UN_EMPTY|UN_LOW)) != 0) {
-					if ((ch->ch_tun.un_flag & UN_LOW) != 0 ?
-					    (n <= TBUF_LOW) :
-					    (n == 0 && ch->ch_s_tpos == ch->ch_s_tin)) {
-						ch->ch_tun.un_flag &= ~(UN_EMPTY|UN_LOW);
-
-						if (waitqueue_active(&((ch->ch_tun.un_tty)->write_wait)))
-							wake_up_interruptible(&((ch->ch_tun.un_tty)->write_wait));
-						tty_wakeup(ch->ch_tun.un_tty);
-						n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-					}
-				}
-
-				/*
-				 * If the printer is waiting on LOW
-				 * water, TIME, EMPTY or PWAIT, and is
-				 * now ready to put more data in the
-				 * buffer, call the line discipline to
-				 * do the job.
-				 */
-
-				/* FIXME: jiffies - ch->ch_waketime can never
-				   be < 0. Someone needs to work out what is
-				   actually intended here */
-				if (ch->ch_pun.un_open_count &&
-				    (ch->ch_pun.un_flag &
-				    (UN_EMPTY|UN_TIME|UN_LOW|UN_PWAIT)) != 0) {
-
-					if ((ch->ch_pun.un_flag & UN_LOW) != 0 ?
-					    (n <= TBUF_LOW) :
-					    (ch->ch_pun.un_flag & UN_TIME) != 0 ?
-					    time_is_before_jiffies(ch->ch_waketime) :
-					    (n == 0 && ch->ch_s_tpos == ch->ch_s_tin) &&
-					    ((ch->ch_pun.un_flag & UN_EMPTY) != 0 ||
-					    ((ch->ch_tun.un_open_count &&
-					      ch->ch_tun.un_tty->ops->chars_in_buffer) ?
-					     (ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) == 0
-					     : 1
-					    )
-					    )) {
-						ch->ch_pun.un_flag &= ~(UN_EMPTY | UN_TIME | UN_LOW | UN_PWAIT);
-
-						if (waitqueue_active(&((ch->ch_pun.un_tty)->write_wait)))
-							wake_up_interruptible(&((ch->ch_pun.un_tty)->write_wait));
-						tty_wakeup(ch->ch_pun.un_tty);
-						n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-
-					} else if ((ch->ch_pun.un_flag & UN_TIME) != 0) {
-						work = 1;
-					}
-				}
-
-
-				/*
-				 *  Determine the max number of bytes
-				 *  this port can send, including
-				 *  packet header overhead.
-				 */
-
-				t = ((ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff);
-
-				if (n > t)
-					n = t;
-
-				if (n != 0) {
-					n += (n <= 8 ? 1 : n <= 255 ? 2 : 3);
-
-					tdata[tchan++] = n;
-					ttotal += n;
-				}
-				break;
-
-			/*
-			 *  Close the port.
-			 */
-
-send_close:
-			case CS_SEND_CLOSE:
-				b = set_cmd_header(b, port, 10);
-				if (ch->ch_otype == OTYPE_IMMEDIATE)
-					*b++ = 3;
-				else
-					*b++ = 4;
-
-				ch->ch_state = CS_WAIT_CLOSE;
-				break;
-
-			/*
-			 *  Wait for a previous server request.
-			 */
-
-			case CS_WAIT_OPEN:
-			case CS_WAIT_CANCEL:
-			case CS_WAIT_FAIL:
-			case CS_WAIT_QUERY:
-			case CS_WAIT_CLOSE:
-				break;
-
-			default:
-				pr_info("%s - unexpected channel state (%i)\n",
-					__func__, ch->ch_state);
-			}
-		}
-
-		/*
-		 *  If a module select code is needed, drop one in.  If space
-		 *  was reserved for one, but none is needed, recover the space.
-		 */
-
-		if (mod != nd->nd_tx_module) {
-			if (b != mbuf) {
-				mbuf[-1] = 0xf0 | mod;
-				nd->nd_tx_module = mod;
-			} else {
-				b--;
-			}
-		}
-	}
-
-	/*
-	 *  Adjust "tmax" so that under worst case conditions we do
-	 *  not overflow either the daemon buffer or the internal
-	 *  buffer in the loop that follows.   Leave a safe area
-	 *  of 64 bytes so we start getting asserts before we start
-	 *  losing data or clobbering memory.
-	 */
-
-	n = UIO_MAX - UIO_BASE;
-
-	if (tmax > n)
-		tmax = n;
-
-	tmax -= 64;
-
-	tsafe = tmax;
-
-	/*
-	 *  Allocate space for 5 Module Selects, 1 Sequence Request,
-	 *  and 1 Set TREQ for each active channel.
-	 */
-
-	tmax -= 5 + 3 + 4 * nd->nd_chan_count;
-
-	/*
-	 *  Further reduce "tmax" to the available transmit credit.
-	 *  Note that this is a soft constraint;  The transmit credit
-	 *  can go negative for a time and then recover.
-	 */
-
-	n = nd->nd_tx_deposit - nd->nd_tx_charge - nd->nd_link.lk_header_size;
-
-	if (tmax > n)
-		tmax = n;
-
-	/*
-	 *  Finally reduce tmax by the number of bytes already in
-	 *  the buffer.
-	 */
-
-	tmax -= b - buf;
-
-	/*
-	 *  Suspend data transmit unless every ready channel can send
-	 *  at least 1 character.
-	 */
-	if (tmax < 2 * nd->nd_chan_count) {
-		tsend = 1;
-
-	} else if (tchan > 1 && ttotal > tmax) {
-
-		/*
-		 *  If transmit is limited by the credit budget, find the
-		 *  largest number of characters we can send without driving
-		 *  the credit negative.
-		 */
-
-		long tm = tmax;
-		int tc = tchan;
-		int try;
-
-		tsend = tm / tc;
-
-		for (try = 0; try < 3; try++) {
-			int i;
-			int c = 0;
-
-			for (i = 0; i < tc; i++) {
-				if (tsend < tdata[i])
-					tdata[c++] = tdata[i];
-				else
-					tm -= tdata[i];
-			}
-
-			if (c == tc)
-				break;
-
-			tsend = tm / c;
-
-			if (c == 1)
-				break;
-
-			tc = c;
-		}
-
-		tsend = tm / nd->nd_chan_count;
-
-		if (tsend < 2)
-			tsend = 1;
-
-	} else {
-		/*
-		 *  If no budgetary constraints, or only one channel ready
-		 *  to send, set the character limit to the remaining
-		 *  buffer size.
-		 */
-
-		tsend = tmax;
-	}
-
-	tsend -= (tsend <= 9) ? 1 : (tsend <= 257) ? 2 : 3;
-
-	/*
-	 *  Loop over all channels, sending queued data.
-	 */
-
-	port = 0;
-	ch = nd->nd_chan;
-	used_buffer = tmax;
-
-	for (mod = 0; port < nd->nd_chan_count; mod++) {
-		/*
-		 *  If this is not the current module, enter a module select
-		 *  code in the buffer.
-		 */
-
-		if (mod != nd->nd_tx_module)
-			mbuf = ++b;
-
-		/*
-		 *  Loop to process one module.
-		 */
-
-		maxport = port + 16;
-
-		if (maxport > nd->nd_chan_count)
-			maxport = nd->nd_chan_count;
-
-		for (; port < maxport; port++, ch++) {
-			if (ch->ch_state != CS_READY)
-				continue;
-
-			lastport = port;
-
-			n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-
-			/*
-			 *  If there is data that can be sent, send it.
-			 */
-
-			if (n != 0 && used_buffer > 0) {
-				t = (ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff;
-
-				if (n > t)
-					n = t;
-
-				if (n > tsend) {
-					work = 1;
-					n = tsend;
-				}
-
-				if (n > used_buffer) {
-					work = 1;
-					n = used_buffer;
-				}
-
-				if (n <= 0)
-					continue;
-
-				/*
-				 *  Create the correct size transmit header,
-				 *  depending on the amount of data to transmit.
-				 */
-
-				if (n <= 8) {
-
-					b[0] = ((n - 1) << 4) + (port & 0xf);
-					b += 1;
-
-				} else if (n <= 255) {
-
-					b[0] = 0x80 + (port & 0xf);
-					b[1] = n;
-					b += 2;
-
-				} else {
-
-					b[0] = 0x90 + (port & 0xf);
-					put_unaligned_be16(n, b + 1);
-					b += 3;
-				}
-
-				ch->ch_s_tin = (ch->ch_s_tin + n) & 0xffff;
-
-				/*
-				 *  Copy transmit data to the packet.
-				 */
-
-				t = TBUF_MAX - ch->ch_tout;
-
-				if (n >= t) {
-					memcpy(b, ch->ch_tbuf + ch->ch_tout, t);
-					b += t;
-					n -= t;
-					used_buffer -= t;
-					ch->ch_tout = 0;
-				}
-
-				memcpy(b, ch->ch_tbuf + ch->ch_tout, n);
-				b += n;
-				used_buffer -= n;
-				ch->ch_tout += n;
-				n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-			}
-
-			/*
-			 *  Wake any terminal unit process waiting in the
-			 *  dgrp_write routine for low water.
-			 */
-
-			if (n > TBUF_LOW)
-				continue;
-
-			if ((ch->ch_flag & CH_LOW) != 0) {
-				ch->ch_flag &= ~CH_LOW;
-				wake_up_interruptible(&ch->ch_flag_wait);
-			}
-
-			/* selwakeup tty_sel */
-			if (ch->ch_tun.un_open_count) {
-				struct tty_struct *tty = (ch->ch_tun.un_tty);
-
-				if (waitqueue_active(&tty->write_wait))
-					wake_up_interruptible(&tty->write_wait);
-
-				tty_wakeup(tty);
-			}
-
-			if (ch->ch_pun.un_open_count) {
-				struct tty_struct *tty = (ch->ch_pun.un_tty);
-
-				if (waitqueue_active(&tty->write_wait))
-					wake_up_interruptible(&tty->write_wait);
-
-				tty_wakeup(tty);
-			}
-
-			/*
-			 *  Do EMPTY processing.
-			 */
-
-			if (n != 0)
-				continue;
-
-			if ((ch->ch_flag & (CH_EMPTY | CH_DRAIN)) != 0 ||
-			    (ch->ch_pun.un_flag & UN_EMPTY) != 0) {
-				/*
-				 *  If there is still data in the server, ask the server
-				 *  to notify us when its all gone.
-				 */
-
-				if (ch->ch_s_treq != ch->ch_s_tin) {
-					b = set_cmd_header(b, port, 43);
-
-					ch->ch_s_treq = ch->ch_s_tin;
-					put_unaligned_be16(ch->ch_s_treq,
-							   b);
-					b += 2;
-				}
-
-				/*
-				 *  If there is a thread waiting for buffer empty,
-				 *  and we are truly empty, wake the thread.
-				 */
-
-				else if ((ch->ch_flag & CH_EMPTY) != 0 &&
-					(ch->ch_send & RR_TX_BREAK) == 0) {
-					ch->ch_flag &= ~CH_EMPTY;
-
-					wake_up_interruptible(&ch->ch_flag_wait);
-				}
-			}
-		}
-
-		/*
-		 *  If a module select code is needed, drop one in.  If space
-		 *  was reserved for one, but none is needed, recover the space.
-		 */
-
-		if (mod != nd->nd_tx_module) {
-			if (b != mbuf) {
-				mbuf[-1] = 0xf0 | mod;
-				nd->nd_tx_module = mod;
-			} else {
-				b--;
-			}
-		}
-	}
-
-	/*
-	 *  Send a synchronization sequence associated with the last open
-	 *  channel that sent data, and remember the time when the data was
-	 *  sent.
-	 */
-
-	in = nd->nd_seq_in;
-
-	if ((send_sync || nd->nd_seq_wait[in] != 0) && lastport >= 0) {
-		u8 *bb = b;
-
-		/*
-		 * Attempt the use the port that really wanted the sync.
-		 * This gets around a race condition where the "lastport" is in
-		 * the middle of the close() routine, and by the time we
-		 * send this command, it will have already acked the close, and
-		 * thus not send the sync response.
-		 */
-		if (wanted_sync_port >= 0)
-			lastport = wanted_sync_port;
-		/*
-		 * Set a flag just in case the port is in the middle of a close,
-		 * it will not be permitted to actually close until we get an
-		 * sync response, and clear the flag there.
-		 */
-		ch = nd->nd_chan + lastport;
-		ch->ch_flag |= CH_WAITING_SYNC;
-
-		mod = lastport >> 4;
-
-		if (mod != nd->nd_tx_module) {
-			bb[0] = 0xf0 + mod;
-			bb += 1;
-
-			nd->nd_tx_module = mod;
-		}
-
-		bb = set_cmd_header(bb, lastport, 12);
-		*bb++ = in;
-
-		nd->nd_seq_size[in] = bb - buf;
-		nd->nd_seq_time[in] = jiffies;
-
-		if (++in >= SEQ_MAX)
-			in = 0;
-
-		if (in != nd->nd_seq_out) {
-			b = bb;
-			nd->nd_seq_in = in;
-			nd->nd_unack += b - buf;
-		}
-	}
-
-	/*
-	 *  If there are no open ports, a sync cannot be sent.
-	 *  There is nothing left to wait for anyway, so wake any
-	 *  thread waiting for an acknowledgement.
-	 */
-
-	else if (nd->nd_seq_wait[in] != 0) {
-		nd->nd_seq_wait[in] = 0;
-
-		wake_up_interruptible(&nd->nd_seq_wque[in]);
-	}
-
-	/*
-	 *  If there is no traffic for an interval of IDLE_MAX, then
-	 *  send a single byte packet.
-	 */
-
-	if (b != buf) {
-		nd->nd_tx_time = jiffies;
-	} else if ((ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX) {
-		*b++ = 0xf0 | nd->nd_tx_module;
-		nd->nd_tx_time = jiffies;
-	}
-
-	n = b - buf;
-
-	if (n >= tsafe)
-		pr_info("%s - n(%i) >= tsafe(%i)\n",
-			__func__, n, tsafe);
-
-	if (tsend < 0)
-		dgrp_dump(buf, n);
-
-	nd->nd_tx_work = work;
-
-	return n;
-}
-
-/*
- * dgrp_net_read()
- * Data to be sent TO the PortServer from the "async." half of the driver.
- */
-static ssize_t dgrp_net_read(struct file *file, char __user *buf, size_t count,
-			     loff_t *ppos)
-{
-	struct nd_struct *nd;
-	long n;
-	u8 *local_buf;
-	u8 *b;
-	ssize_t rtn;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		return -ENXIO;
-
-	if (count < UIO_MIN)
-		return -EINVAL;
-
-	/*
-	 *  Only one read/write operation may be in progress at
-	 *  any given time.
-	 */
-
-	/*
-	 *  Grab the NET lock.
-	 */
-	down(&nd->nd_net_semaphore);
-
-	nd->nd_read_count++;
-
-	nd->nd_tx_ready = 0;
-
-	/*
-	 *  Determine the effective size of the buffer.
-	 */
-
-	if (nd->nd_remain > UIO_BASE)
-		pr_info_ratelimited("%s - nd_remain(%i) > UIO_BASE\n",
-				    __func__, nd->nd_remain);
-
-	b = local_buf = nd->nd_iobuf + UIO_BASE;
-
-	/*
-	 *  Generate data according to the node state.
-	 */
-
-	switch (nd->nd_state) {
-	/*
-	 *  Initialize the connection.
-	 */
-
-	case NS_IDLE:
-		if (nd->nd_mon_buf)
-			dgrp_monitor_reset(nd);
-
-		/*
-		 *  Request a Product ID Packet.
-		 */
-
-		b[0] = 0xfb;
-		b[1] = 0x01;
-		b += 2;
-
-		nd->nd_expect |= NR_IDENT;
-
-		/*
-		 *  Request a Server Capability ID Response.
-		 */
-
-		b[0] = 0xfb;
-		b[1] = 0x02;
-		b += 2;
-
-		nd->nd_expect |= NR_CAPABILITY;
-
-		/*
-		 *  Request a Server VPD Response.
-		 */
-
-		b[0] = 0xfb;
-		b[1] = 0x18;
-		b += 2;
-
-		nd->nd_expect |= NR_VPD;
-
-		nd->nd_state = NS_WAIT_QUERY;
-		break;
-
-	/*
-	 *  We do serious communication with the server only in
-	 *  the READY state.
-	 */
-
-	case NS_READY:
-		b = dgrp_send(nd, count) + local_buf;
-		break;
-
-	/*
-	 *  Send off an error after receiving a bogus message
-	 *  from the server.
-	 */
-
-	case NS_SEND_ERROR:
-		n = strlen(nd->nd_error);
-
-		b[0] = 0xff;
-		b[1] = n;
-		memcpy(b + 2, nd->nd_error, n);
-		b += 2 + n;
-
-		dgrp_net_idle(nd);
-		/*
-		 *  Set the active port count to zero.
-		 */
-		dgrp_chan_count(nd, 0);
-		break;
-
-	default:
-		break;
-	}
-
-	n = b - local_buf;
-
-	if (n != 0) {
-		nd->nd_send_count++;
-
-		nd->nd_tx_byte   += n + nd->nd_link.lk_header_size;
-		nd->nd_tx_charge += n + nd->nd_link.lk_header_size;
-	}
-
-	rtn = copy_to_user((void __user *)buf, local_buf, n);
-	if (rtn) {
-		rtn = -EFAULT;
-		goto done;
-	}
-
-	*ppos += n;
-
-	rtn = n;
-
-	if (nd->nd_mon_buf)
-		dgrp_monitor_data(nd, RPDUMP_CLIENT, local_buf, n);
-
-	/*
-	 *  Release the NET lock.
-	 */
-done:
-	up(&nd->nd_net_semaphore);
-
-	return rtn;
-}
-
-/**
- * dgrp_receive() -- decode data packets received from the remote PortServer.
- * @nd: pointer to a node structure
- */
-static void dgrp_receive(struct nd_struct *nd)
-{
-	struct ch_struct *ch;
-	u8 *buf;
-	u8 *b;
-	u8 *dbuf;
-	char *error;
-	long port;
-	long dlen;
-	long plen;
-	long remain;
-	long n;
-	long mlast;
-	long elast;
-	long mstat;
-	long estat;
-
-	char ID[3];
-
-	nd->nd_tx_time = jiffies;
-
-	ID_TO_CHAR(nd->nd_ID, ID);
-
-	b = buf = nd->nd_iobuf;
-	remain = nd->nd_remain;
-
-	/*
-	 *  Loop to process Realport protocol packets.
-	 */
-
-	while (remain > 0) {
-		int n0 = b[0] >> 4;
-		int n1 = b[0] & 0x0f;
-
-		if (n0 <= 12) {
-			port = (nd->nd_rx_module << 4) + n1;
-
-			if (port >= nd->nd_chan_count) {
-				error = "Improper Port Number";
-				goto prot_error;
-			}
-
-			ch = nd->nd_chan + port;
-		} else {
-			port = -1;
-			ch = NULL;
-		}
-
-		/*
-		 *  Process by major packet type.
-		 */
-
-		switch (n0) {
-
-		/*
-		 *  Process 1-byte header data packet.
-		 */
-
-		case 0:
-		case 1:
-		case 2:
-		case 3:
-		case 4:
-		case 5:
-		case 6:
-		case 7:
-			dlen = n0 + 1;
-			plen = dlen + 1;
-
-			dbuf = b + 1;
-			goto data;
-
-		/*
-		 *  Process 2-byte header data packet.
-		 */
-
-		case 8:
-			if (remain < 3)
-				goto done;
-
-			dlen = b[1];
-			plen = dlen + 2;
-
-			dbuf = b + 2;
-			goto data;
-
-		/*
-		 *  Process 3-byte header data packet.
-		 */
-
-		case 9:
-			if (remain < 4)
-				goto done;
-
-			dlen = get_unaligned_be16(b + 1);
-			plen = dlen + 3;
-
-			dbuf = b + 3;
-
-		/*
-		 *  Common packet handling code.
-		 */
-
-data:
-			nd->nd_tx_work = 1;
-
-			/*
-			 *  Otherwise data should appear only when we are
-			 *  in the CS_READY state.
-			 */
-
-			if (ch->ch_state < CS_READY) {
-				error = "Data received before RWIN established";
-				goto prot_error;
-			}
-
-			/*
-			 *  Assure that the data received is within the
-			 *  allowable window.
-			 */
-
-			n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff;
-
-			if (dlen > n) {
-				error = "Receive data overrun";
-				goto prot_error;
-			}
-
-			/*
-			 *  If we received 3 or less characters,
-			 *  assume it is a human typing, and set RTIME
-			 *  to 10 milliseconds.
-			 *
-			 *  If we receive 10 or more characters,
-			 *  assume its not a human typing, and set RTIME
-			 *  to 100 milliseconds.
-			 */
-
-			if (ch->ch_edelay != DGRP_RTIME) {
-				if (ch->ch_rtime != ch->ch_edelay) {
-					ch->ch_rtime = ch->ch_edelay;
-					ch->ch_flag |= CH_PARAM;
-				}
-			} else if (dlen <= 3) {
-				if (ch->ch_rtime != 10) {
-					ch->ch_rtime = 10;
-					ch->ch_flag |= CH_PARAM;
-				}
-			} else {
-				if (ch->ch_rtime != DGRP_RTIME) {
-					ch->ch_rtime = DGRP_RTIME;
-					ch->ch_flag |= CH_PARAM;
-				}
-			}
-
-			/*
-			 *  If a portion of the packet is outside the
-			 *  buffer, shorten the effective length of the
-			 *  data packet to be the amount of data received.
-			 */
-
-			if (remain < plen)
-				dlen -= plen - remain;
-
-			/*
-			 *  Detect if receive flush is now complete.
-			 */
-
-			if ((ch->ch_flag & CH_RX_FLUSH) != 0 &&
-			    ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >=
-			    ((nd->nd_seq_in    - nd->nd_seq_out) & SEQ_MASK)) {
-				ch->ch_flag &= ~CH_RX_FLUSH;
-			}
-
-			/*
-			 *  If we are ready to receive, move the data into
-			 *  the receive buffer.
-			 */
-
-			ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff;
-
-			if (ch->ch_state == CS_READY &&
-			    (ch->ch_tun.un_open_count != 0) &&
-			    (ch->ch_tun.un_flag & UN_CLOSING) == 0 &&
-			    (ch->ch_cflag & CF_CREAD) != 0 &&
-			    (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 &&
-			    (ch->ch_send & RR_RX_FLUSH) == 0) {
-
-				if (ch->ch_rin + dlen >= RBUF_MAX) {
-					n = RBUF_MAX - ch->ch_rin;
-
-					memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n);
-
-					ch->ch_rin = 0;
-					dbuf += n;
-					dlen -= n;
-				}
-
-				memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen);
-
-				ch->ch_rin += dlen;
-
-
-				/*
-				 *  If we are not in fastcook mode, or
-				 *  if there is a fastcook thread
-				 *  waiting for data, send the data to
-				 *  the line discipline.
-				 */
-
-				if ((ch->ch_flag & CH_FAST_READ) == 0 ||
-				    ch->ch_inwait != 0) {
-					dgrp_input(ch);
-				}
-
-				/*
-				 *  If there is a read thread waiting
-				 *  in select, and we are in fastcook
-				 *  mode, wake him up.
-				 */
-
-				if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) &&
-				    (ch->ch_flag & CH_FAST_READ) != 0)
-					wake_up_interruptible(&ch->ch_tun.un_tty->read_wait);
-
-				/*
-				 * Wake any thread waiting in the
-				 * fastcook loop.
-				 */
-
-				if ((ch->ch_flag & CH_INPUT) != 0) {
-					ch->ch_flag &= ~CH_INPUT;
-
-					wake_up_interruptible(&ch->ch_flag_wait);
-				}
-			}
-
-			/*
-			 *  Fabricate and insert a data packet header to
-			 *  preced the remaining data when it comes in.
-			 */
-
-			if (remain < plen) {
-				dlen = plen - remain;
-				b = buf;
-
-				b[0] = 0x90 + n1;
-				put_unaligned_be16(dlen, b + 1);
-
-				remain = 3;
-				goto done;
-			}
-			break;
-
-		/*
-		 *  Handle Window Sequence packets.
-		 */
-
-		case 10:
-			plen = 3;
-			if (remain < plen)
-				goto done;
-
-			nd->nd_tx_work = 1;
-
-			{
-				ushort tpos   = get_unaligned_be16(b + 1);
-
-				ushort ack    = (tpos          - ch->ch_s_tpos) & 0xffff;
-				ushort unack  = (ch->ch_s_tin  - ch->ch_s_tpos) & 0xffff;
-				ushort notify = (ch->ch_s_treq - ch->ch_s_tpos) & 0xffff;
-
-				if (ch->ch_state < CS_READY || ack > unack) {
-					error = "Improper Window Sequence";
-					goto prot_error;
-				}
-
-				ch->ch_s_tpos = tpos;
-
-				if (notify <= ack)
-					ch->ch_s_treq = tpos;
-			}
-			break;
-
-		/*
-		 *  Handle Command response packets.
-		 */
-
-		case 11:
-
-			/*
-			 * RealPort engine fix - 03/11/2004
-			 *
-			 * This check did not used to be here.
-			 *
-			 * We were using b[1] without verifying that the data
-			 * is actually there and valid. On a split packet, it
-			 * might not be yet.
-			 *
-			 * NOTE:  I have never actually seen the failure happen
-			 *        under Linux,  but since I have seen it occur
-			 *        under both Solaris and HP-UX,  the assumption
-			 *        is that it *could* happen here as well...
-			 */
-			if (remain < 2)
-				goto done;
-
-
-			switch (b[1]) {
-
-			/*
-			 *  Handle Open Response.
-			 */
-
-			case 11:
-				plen = 6;
-				if (remain < plen)
-					goto done;
-
-				nd->nd_tx_work = 1;
-
-				{
-					int req = b[2];
-					int resp = b[3];
-					port = get_unaligned_be16(b + 4);
-
-					if (port >= nd->nd_chan_count) {
-						error = "Open channel number out of range";
-						goto prot_error;
-					}
-
-					ch = nd->nd_chan + port;
-
-					/*
-					 *  How we handle an open response depends primarily
-					 *  on our current channel state.
-					 */
-
-					switch (ch->ch_state) {
-					case CS_IDLE:
-
-						/*
-						 *  Handle a delayed open.
-						 */
-
-						if (ch->ch_otype_waiting != 0 &&
-						    req == ch->ch_otype_waiting &&
-						    resp == 0) {
-							ch->ch_otype = req;
-							ch->ch_otype_waiting = 0;
-							ch->ch_state = CS_SEND_QUERY;
-							break;
-						}
-						goto open_error;
-
-					case CS_WAIT_OPEN:
-
-						/*
-						 *  Handle the open response.
-						 */
-
-						if (req == ch->ch_otype) {
-							switch (resp) {
-
-							/*
-							 *  On successful response, open the
-							 *  port and proceed normally.
-							 */
-
-							case 0:
-								ch->ch_state = CS_SEND_QUERY;
-								break;
-
-							/*
-							 *  On a busy response to a persistent open,
-							 *  remember that the open is pending.
-							 */
-
-							case 1:
-							case 2:
-								if (req != OTYPE_IMMEDIATE) {
-									ch->ch_otype_waiting = req;
-									ch->ch_state = CS_IDLE;
-									break;
-								}
-
-							/*
-							 *  Otherwise the server open failed.  If
-							 *  the Unix port is open, hang it up.
-							 */
-
-							default:
-								if (ch->ch_open_count != 0) {
-									ch->ch_flag |= CH_HANGUP;
-									dgrp_carrier(ch);
-									ch->ch_state = CS_IDLE;
-									break;
-								}
-
-								ch->ch_open_error = resp;
-								ch->ch_state = CS_IDLE;
-
-								wake_up_interruptible(&ch->ch_flag_wait);
-							}
-							break;
-						}
-
-						/*
-						 *  Handle delayed response arrival preceding
-						 *  the open response we are waiting for.
-						 */
-
-						if (ch->ch_otype_waiting != 0 &&
-						    req == ch->ch_otype_waiting &&
-						    resp == 0) {
-							ch->ch_otype = ch->ch_otype_waiting;
-							ch->ch_otype_waiting = 0;
-							ch->ch_state = CS_WAIT_FAIL;
-							break;
-						}
-						goto open_error;
-
-
-					case CS_WAIT_FAIL:
-
-						/*
-						 *  Handle response to immediate open arriving
-						 *  after a delayed open success.
-						 */
-
-						if (req == OTYPE_IMMEDIATE) {
-							ch->ch_state = CS_SEND_QUERY;
-							break;
-						}
-						goto open_error;
-
-
-					case CS_WAIT_CANCEL:
-						/*
-						 *  Handle delayed open response arriving before
-						 *  the cancel response.
-						 */
-
-						if (req == ch->ch_otype_waiting &&
-						    resp == 0) {
-							ch->ch_otype_waiting = 0;
-							break;
-						}
-
-						/*
-						 *  Handle cancel response.
-						 */
-
-						if (req == 4 && resp == 0) {
-							ch->ch_otype_waiting = 0;
-							ch->ch_state = CS_IDLE;
-							break;
-						}
-						goto open_error;
-
-
-					case CS_WAIT_CLOSE:
-						/*
-						 *  Handle a successful response to a port
-						 *  close.
-						 */
-
-						if (req >= 3) {
-							ch->ch_state = CS_IDLE;
-							break;
-						}
-						goto open_error;
-
-open_error:
-					default:
-						{
-							error = "Improper Open Response";
-							goto prot_error;
-						}
-					}
-				}
-				break;
-
-			/*
-			 *  Handle Synchronize Response.
-			 */
-
-			case 13:
-				plen = 3;
-				if (remain < plen)
-					goto done;
-				{
-					int seq = b[2];
-					int s;
-
-					/*
-					 * If channel was waiting for this sync response,
-					 * unset the flag, and wake up anyone waiting
-					 * on the event.
-					 */
-					if (ch->ch_flag & CH_WAITING_SYNC) {
-						ch->ch_flag &= ~(CH_WAITING_SYNC);
-						wake_up_interruptible(&ch->ch_flag_wait);
-					}
-
-					if (((seq - nd->nd_seq_out) & SEQ_MASK) >=
-					    ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) {
-						break;
-					}
-
-					for (s = nd->nd_seq_out;; s = (s + 1) & SEQ_MASK) {
-						if (nd->nd_seq_wait[s] != 0) {
-							nd->nd_seq_wait[s] = 0;
-
-							wake_up_interruptible(&nd->nd_seq_wque[s]);
-						}
-
-						nd->nd_unack -= nd->nd_seq_size[s];
-
-						if (s == seq)
-							break;
-					}
-
-					nd->nd_seq_out = (seq + 1) & SEQ_MASK;
-				}
-				break;
-
-			/*
-			 *  Handle Sequence Response.
-			 */
-
-			case 15:
-				plen = 6;
-				if (remain < plen)
-					goto done;
-
-				{
-				/* Record that we have received the Sequence
-				 * Response, but we aren't interested in the
-				 * sequence numbers.  We were using RIN like it
-				 * was ROUT and that was causing problems,
-				 * fixed 7-13-2001 David Fries. See comment in
-				 * drp.h for ch_s_rin variable.
-					int rin = get_unaligned_be16(b + 2);
-					int tpos = get_unaligned_be16(b + 4);
-				*/
-
-					ch->ch_send   &= ~RR_SEQUENCE;
-					ch->ch_expect &= ~RR_SEQUENCE;
-				}
-				goto check_query;
-
-			/*
-			 *  Handle Status Response.
-			 */
-
-			case 17:
-				plen = 5;
-				if (remain < plen)
-					goto done;
-
-				{
-					ch->ch_s_elast = get_unaligned_be16(b + 2);
-					ch->ch_s_mlast = b[4];
-
-					ch->ch_expect &= ~RR_STATUS;
-					ch->ch_send   &= ~RR_STATUS;
-
-					/*
-					 *  CH_PHYS_CD is cleared because something _could_ be
-					 *  waiting for the initial sense of carrier... and if
-					 *  carrier is high immediately, we want to be sure to
-					 *  wake them as soon as possible.
-					 */
-					ch->ch_flag &= ~CH_PHYS_CD;
-
-					dgrp_carrier(ch);
-				}
-				goto check_query;
-
-			/*
-			 *  Handle Line Error Response.
-			 */
-
-			case 19:
-				plen = 14;
-				if (remain < plen)
-					goto done;
-
-				break;
-
-			/*
-			 *  Handle Buffer Response.
-			 */
-
-			case 21:
-				plen = 6;
-				if (remain < plen)
-					goto done;
-
-				{
-					ch->ch_s_rsize = get_unaligned_be16(b + 2);
-					ch->ch_s_tsize = get_unaligned_be16(b + 4);
-
-					ch->ch_send   &= ~RR_BUFFER;
-					ch->ch_expect &= ~RR_BUFFER;
-				}
-				goto check_query;
-
-			/*
-			 *  Handle Port Capability Response.
-			 */
-
-			case 23:
-				plen = 32;
-				if (remain < plen)
-					goto done;
-
-				{
-					ch->ch_send   &= ~RR_CAPABILITY;
-					ch->ch_expect &= ~RR_CAPABILITY;
-				}
-
-			/*
-			 *  When all queries are complete, set those parameters
-			 *  derived from the query results, then transition
-			 *  to the READY state.
-			 */
-
-check_query:
-				if (ch->ch_state == CS_WAIT_QUERY &&
-				    (ch->ch_expect & (RR_SEQUENCE |
-							RR_STATUS |
-							RR_BUFFER |
-							RR_CAPABILITY)) == 0) {
-					ch->ch_tmax  = ch->ch_s_tsize / 4;
-
-					if (ch->ch_edelay == DGRP_TTIME)
-						ch->ch_ttime = DGRP_TTIME;
-					else
-						ch->ch_ttime = ch->ch_edelay;
-
-					ch->ch_rmax = ch->ch_s_rsize / 4;
-
-					if (ch->ch_edelay == DGRP_RTIME)
-						ch->ch_rtime = DGRP_RTIME;
-					else
-						ch->ch_rtime = ch->ch_edelay;
-
-					ch->ch_rlow  = 2 * ch->ch_s_rsize / 8;
-					ch->ch_rhigh = 6 * ch->ch_s_rsize / 8;
-
-					ch->ch_state = CS_READY;
-
-					nd->nd_tx_work = 1;
-					wake_up_interruptible(&ch->ch_flag_wait);
-
-				}
-				break;
-
-			default:
-				goto decode_error;
-			}
-			break;
-
-		/*
-		 *  Handle Events.
-		 */
-
-		case 12:
-			plen = 4;
-			if (remain < plen)
-				goto done;
-
-			mlast = ch->ch_s_mlast;
-			elast = ch->ch_s_elast;
-
-			mstat = ch->ch_s_mlast = b[1];
-			estat = ch->ch_s_elast = get_unaligned_be16(b + 2);
-
-			/*
-			 *  Handle modem changes.
-			 */
-
-			if (((mstat ^ mlast) & DM_CD) != 0)
-				dgrp_carrier(ch);
-
-
-			/*
-			 *  Handle received break.
-			 */
-
-			if ((estat & ~elast & EV_RXB) != 0 &&
-			    (ch->ch_tun.un_open_count != 0) &&
-			    I_BRKINT(ch->ch_tun.un_tty) &&
-			    !(I_IGNBRK(ch->ch_tun.un_tty))) {
-
-				tty_buffer_request_room(&ch->port, 1);
-				tty_insert_flip_char(&ch->port, 0, TTY_BREAK);
-				tty_flip_buffer_push(&ch->port);
-
-			}
-
-			/*
-			 *  On transmit break complete, if more break traffic
-			 *  is waiting then send it.  Otherwise wake any threads
-			 *  waiting for transmitter empty.
-			 */
-
-			if ((~estat & elast & EV_TXB) != 0 &&
-			    (ch->ch_expect & RR_TX_BREAK) != 0) {
-
-				nd->nd_tx_work = 1;
-
-				ch->ch_expect &= ~RR_TX_BREAK;
-
-				if (ch->ch_break_time != 0) {
-					ch->ch_send |= RR_TX_BREAK;
-				} else {
-					ch->ch_send &= ~RR_TX_BREAK;
-					ch->ch_flag &= ~CH_TX_BREAK;
-					wake_up_interruptible(&ch->ch_flag_wait);
-				}
-			}
-			break;
-
-		case 13:
-		case 14:
-			error = "Unrecognized command";
-			goto prot_error;
-
-		/*
-		 *  Decode Special Codes.
-		 */
-
-		case 15:
-			switch (n1) {
-			/*
-			 *  One byte module select.
-			 */
-
-			case 0:
-			case 1:
-			case 2:
-			case 3:
-			case 4:
-			case 5:
-			case 6:
-			case 7:
-				plen = 1;
-				nd->nd_rx_module = n1;
-				break;
-
-			/*
-			 *  Two byte module select.
-			 */
-
-			case 8:
-				plen = 2;
-				if (remain < plen)
-					goto done;
-
-				nd->nd_rx_module = b[1];
-				break;
-
-			/*
-			 *  ID Request packet.
-			 */
-
-			case 11:
-				if (remain < 4)
-					goto done;
-
-				plen = get_unaligned_be16(b + 2);
-
-				if (plen < 12 || plen > 1000) {
-					error = "Response Packet length error";
-					goto prot_error;
-				}
-
-				nd->nd_tx_work = 1;
-
-				switch (b[1]) {
-				/*
-				 *  Echo packet.
-				 */
-
-				case 0:
-					nd->nd_send |= NR_ECHO;
-					break;
-
-				/*
-				 *  ID Response packet.
-				 */
-
-				case 1:
-					nd->nd_send |= NR_IDENT;
-					break;
-
-				/*
-				 *  ID Response packet.
-				 */
-
-				case 32:
-					nd->nd_send |= NR_PASSWORD;
-					break;
-
-				}
-				break;
-
-			/*
-			 *  Various node-level response packets.
-			 */
-
-			case 12:
-				if (remain < 4)
-					goto done;
-
-				plen = get_unaligned_be16(b + 2);
-
-				if (plen < 4 || plen > 1000) {
-					error = "Response Packet length error";
-					goto prot_error;
-				}
-
-				nd->nd_tx_work = 1;
-
-				switch (b[1]) {
-				/*
-				 *  Echo packet.
-				 */
-
-				case 0:
-					nd->nd_expect &= ~NR_ECHO;
-					break;
-
-				/*
-				 *  Product Response Packet.
-				 */
-
-				case 1:
-					{
-						int desclen;
-
-						nd->nd_hw_ver = (b[8] << 8) | b[9];
-						nd->nd_sw_ver = (b[10] << 8) | b[11];
-						nd->nd_hw_id = b[6];
-						desclen = (plen - 12 > MAX_DESC_LEN - 1) ? MAX_DESC_LEN - 1 :
-							plen - 12;
-
-						if (desclen <= 0) {
-							error = "Response Packet desclen error";
-							goto prot_error;
-						}
-
-						strncpy(nd->nd_ps_desc, b + 12, desclen);
-						nd->nd_ps_desc[desclen] = 0;
-					}
-
-					nd->nd_expect &= ~NR_IDENT;
-					break;
-
-				/*
-				 *  Capability Response Packet.
-				 */
-
-				case 2:
-					{
-						int nn = get_unaligned_be16(b + 4);
-
-						if (nn > CHAN_MAX)
-							nn = CHAN_MAX;
-
-						dgrp_chan_count(nd, nn);
-					}
-
-					nd->nd_expect &= ~NR_CAPABILITY;
-					break;
-
-				/*
-				 *  VPD Response Packet.
-				 */
-
-				case 15:
-					/*
-					 * NOTE: case 15 is here ONLY because the EtherLite
-					 * is broken, and sends a response to 24 back as 15.
-					 * To resolve this, the EtherLite firmware is now
-					 * fixed to send back 24 correctly, but, for backwards
-					 * compatibility, we now have reserved 15 for the
-					 * bad EtherLite response to 24 as well.
-					 */
-
-					/* Fallthru! */
-
-				case 24:
-
-					/*
-					 * If the product doesn't support VPD,
-					 * it will send back a null IDRESP,
-					 * which is a length of 4 bytes.
-					 */
-					if (plen > 4) {
-						memcpy(nd->nd_vpd, b + 4, min(plen - 4, (long) VPDSIZE));
-						nd->nd_vpd_len = min(plen - 4, (long) VPDSIZE);
-					}
-
-					nd->nd_expect &= ~NR_VPD;
-					break;
-
-				default:
-					goto decode_error;
-				}
-
-				if (nd->nd_expect == 0 &&
-				    nd->nd_state == NS_WAIT_QUERY) {
-					nd->nd_state = NS_READY;
-				}
-				break;
-
-			/*
-			 *  Debug packet.
-			 */
-
-			case 14:
-				if (remain < 4)
-					goto done;
-
-				plen = get_unaligned_be16(b + 2) + 4;
-
-				if (plen > 1000) {
-					error = "Debug Packet too large";
-					goto prot_error;
-				}
-
-				if (remain < plen)
-					goto done;
-				break;
-
-			/*
-			 *  Handle reset packet.
-			 */
-
-			case 15:
-				if (remain < 2)
-					goto done;
-
-				plen = 2 + b[1];
-
-				if (remain < plen)
-					goto done;
-
-				nd->nd_tx_work = 1;
-
-				n = b[plen];
-				b[plen] = 0;
-
-				b[plen] = n;
-
-				error = "Client Reset Acknowledge";
-				goto prot_error;
-
-			default:
-				goto decode_error;
-			}
-			break;
-
-		default:
-			goto decode_error;
-		}
-
-		b += plen;
-		remain -= plen;
-	}
-
-	/*
-	 *  When the buffer is exhausted, copy any data left at the
-	 *  top of the buffer back down to the bottom for the next
-	 *  read request.
-	 */
-
-done:
-	if (remain > 0 && b != buf)
-		memcpy(buf, b, remain);
-
-	nd->nd_remain = remain;
-	return;
-
-/*
- *  Handle a decode error.
- */
-
-decode_error:
-	error = "Protocol decode error";
-
-/*
- *  Handle a general protocol error.
- */
-
-prot_error:
-	nd->nd_remain = 0;
-	nd->nd_state = NS_SEND_ERROR;
-	nd->nd_error = error;
-}
-
-/*
- * dgrp_net_write() -- write data to the network device.
- *
- * A zero byte write indicates that the connection to the RealPort
- * device has been broken.
- *
- * A non-zero write indicates data from the RealPort device.
- */
-static ssize_t dgrp_net_write(struct file *file, const char __user *buf,
-			      size_t count, loff_t *ppos)
-{
-	struct nd_struct *nd;
-	ssize_t rtn = 0;
-	long n;
-	long total = 0;
-
-	/*
-	 *  Get the node pointer, and quit if it doesn't exist.
-	 */
-	nd = (struct nd_struct *)(file->private_data);
-	if (!nd)
-		return -ENXIO;
-
-	/*
-	 *  Grab the NET lock.
-	 */
-	down(&nd->nd_net_semaphore);
-
-	nd->nd_write_count++;
-
-	/*
-	 *  Handle disconnect.
-	 */
-
-	if (count == 0) {
-		dgrp_net_idle(nd);
-		/*
-		 *  Set the active port count to zero.
-		 */
-		dgrp_chan_count(nd, 0);
-		goto unlock;
-	}
-
-	/*
-	 *  Loop to process entire receive packet.
-	 */
-
-	while (count > 0) {
-		n = UIO_MAX - nd->nd_remain;
-
-		if (n > count)
-			n = count;
-
-		nd->nd_rx_byte += n + nd->nd_link.lk_header_size;
-
-		rtn = copy_from_user(nd->nd_iobuf + nd->nd_remain,
-				     (void __user *) buf + total, n);
-		if (rtn) {
-			rtn = -EFAULT;
-			goto unlock;
-		}
-
-		*ppos += n;
-
-		total += n;
-
-		count -= n;
-
-		if (nd->nd_mon_buf)
-			dgrp_monitor_data(nd, RPDUMP_SERVER,
-					  nd->nd_iobuf + nd->nd_remain, n);
-
-		nd->nd_remain += n;
-
-		dgrp_receive(nd);
-	}
-
-	rtn = total;
-
-unlock:
-	/*
-	 *  Release the NET lock.
-	 */
-	up(&nd->nd_net_semaphore);
-
-	return rtn;
-}
-
-
-/*
- * dgrp_net_select()
- *  Determine whether a device is ready to be read or written to, and
- *  sleep if not.
- */
-static unsigned int dgrp_net_select(struct file *file,
-				    struct poll_table_struct *table)
-{
-	unsigned int retval = 0;
-	struct nd_struct *nd = file->private_data;
-
-	poll_wait(file, &nd->nd_tx_waitq, table);
-
-	if (nd->nd_tx_ready)
-		retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
-
-	retval |= POLLOUT | POLLWRNORM;        /* Always writeable */
-
-	return retval;
-}
-
-/*
- * dgrp_net_ioctl
- *
- * Implement those functions which allow the network daemon to control
- * the network parameters in the driver.  The ioctls include ones to
- * get and set the link speed parameters for the PortServer.
- */
-static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
-			   unsigned long arg)
-{
-	struct nd_struct  *nd;
-	int    rtn = 0;
-	long   size = _IOC_SIZE(cmd);
-	struct link_struct link;
-
-	nd = file->private_data;
-
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		rtn = access_ok(VERIFY_WRITE, (void __user *) arg, size);
-	else if (_IOC_DIR(cmd) & _IOC_WRITE)
-		rtn = access_ok(VERIFY_READ,  (void __user *) arg, size);
-
-	if (!rtn)
-		return rtn;
-
-	switch (cmd) {
-	case DIGI_SETLINK:
-		if (size != sizeof(struct link_struct))
-			return -EINVAL;
-
-		if (copy_from_user(&link, (void __user *)arg, size))
-			return -EFAULT;
-
-		if (link.lk_fast_rate < 9600)
-			link.lk_fast_rate = 9600;
-
-		if (link.lk_slow_rate < 2400)
-			link.lk_slow_rate = 2400;
-
-		if (link.lk_fast_rate > 10000000)
-			link.lk_fast_rate = 10000000;
-
-		if (link.lk_slow_rate > link.lk_fast_rate)
-			link.lk_slow_rate = link.lk_fast_rate;
-
-		if (link.lk_fast_delay > 2000)
-			link.lk_fast_delay = 2000;
-
-		if (link.lk_slow_delay > 10000)
-			link.lk_slow_delay = 10000;
-
-		if (link.lk_fast_delay < 60)
-			link.lk_fast_delay = 60;
-
-		if (link.lk_slow_delay < link.lk_fast_delay)
-			link.lk_slow_delay = link.lk_fast_delay;
-
-		if (link.lk_header_size < 2)
-			link.lk_header_size = 2;
-
-		if (link.lk_header_size > 128)
-			link.lk_header_size = 128;
-
-		link.lk_fast_rate /= 8 * 1000 / dgrp_poll_tick;
-		link.lk_slow_rate /= 8 * 1000 / dgrp_poll_tick;
-
-		link.lk_fast_delay /= dgrp_poll_tick;
-		link.lk_slow_delay /= dgrp_poll_tick;
-
-		nd->nd_link = link;
-
-		break;
-
-	case DIGI_GETLINK:
-		if (size != sizeof(struct link_struct))
-			return -EINVAL;
-
-		if (copy_to_user((void __user *)arg, (void *)(&nd->nd_link),
-				 size))
-			return -EFAULT;
-
-		break;
-
-	default:
-		return -EINVAL;
-
-	}
-
-	return 0;
-}
-
-/**
- * dgrp_poll_handler() -- handler for poll timer
- *
- * As each timer expires, it determines (a) whether the "transmit"
- * waiter needs to be woken up, and (b) whether the poller needs to
- * be rescheduled.
- */
-void dgrp_poll_handler(unsigned long arg)
-{
-	struct dgrp_poll_data *poll_data;
-	struct nd_struct *nd;
-	struct link_struct *lk;
-	ulong time;
-	ulong poll_time;
-	ulong freq;
-	ulong lock_flags;
-
-	poll_data = (struct dgrp_poll_data *) arg;
-	freq = 1000 / poll_data->poll_tick;
-	poll_data->poll_round += 17;
-
-	if (poll_data->poll_round >= freq)
-		poll_data->poll_round -= freq;
-
-	/*
-	 * Loop to process all open nodes.
-	 *
-	 * For each node, determine the rate at which it should
-	 * be transmitting data.  Then if the node should wake up
-	 * and transmit data now, enable the net receive select
-	 * to get the transmit going.
-	 */
-
-	list_for_each_entry(nd, &nd_struct_list, list) {
-
-		lk = &nd->nd_link;
-
-		/*
-		 * Decrement statistics.  These are only for use with
-		 * KME, so don't worry that the operations are done
-		 * unlocked, and so the results are occasionally wrong.
-		 */
-
-		nd->nd_read_count -= (nd->nd_read_count +
-				      poll_data->poll_round) / freq;
-		nd->nd_write_count -= (nd->nd_write_count +
-				       poll_data->poll_round) / freq;
-		nd->nd_send_count -= (nd->nd_send_count +
-				      poll_data->poll_round) / freq;
-		nd->nd_tx_byte -= (nd->nd_tx_byte +
-				   poll_data->poll_round) / freq;
-		nd->nd_rx_byte -= (nd->nd_rx_byte +
-				   poll_data->poll_round) / freq;
-
-		/*
-		 * Wake the daemon to transmit data only when there is
-		 * enough byte credit to send data.
-		 *
-		 * The results are approximate because the operations
-		 * are performed unlocked, and we are inspecting
-		 * data asynchronously updated elsewhere.  The whole
-		 * thing is just approximation anyway, so that should
-		 * be okay.
-		 */
-
-		if (lk->lk_slow_rate >= UIO_MAX) {
-
-			nd->nd_delay = 0;
-			nd->nd_rate = UIO_MAX;
-
-			nd->nd_tx_deposit = nd->nd_tx_charge + 3 * UIO_MAX;
-			nd->nd_tx_credit  = 3 * UIO_MAX;
-
-		} else {
-
-			long rate;
-			long delay;
-			long deposit;
-			long charge;
-			long size;
-			long excess;
-
-			long seq_in = nd->nd_seq_in;
-			long seq_out = nd->nd_seq_out;
-
-			/*
-			 * If there are no outstanding packets, run at the
-			 * fastest rate.
-			 */
-
-			if (seq_in == seq_out) {
-				delay = 0;
-				rate = lk->lk_fast_rate;
-			}
-
-			/*
-			 * Otherwise compute the transmit rate based on the
-			 * delay since the oldest packet.
-			 */
-
-			else {
-				/*
-				 * The actual delay is computed as the
-				 * time since the oldest unacknowledged
-				 * packet was sent, minus the time it
-				 * took to send that packet to the server.
-				 */
-
-				delay = ((jiffies - nd->nd_seq_time[seq_out])
-					- (nd->nd_seq_size[seq_out] /
-					lk->lk_fast_rate));
-
-				/*
-				 * If the delay is less than the "fast"
-				 * delay, transmit full speed.  If greater
-				 * than the "slow" delay, transmit at the
-				 * "slow" speed.   In between, interpolate
-				 * between the fast and slow speeds.
-				 */
-
-				rate =
-				  (delay <= lk->lk_fast_delay ?
-				    lk->lk_fast_rate :
-				    delay >= lk->lk_slow_delay ?
-				      lk->lk_slow_rate :
-				      (lk->lk_slow_rate +
-				       (lk->lk_slow_delay - delay) *
-				       (lk->lk_fast_rate - lk->lk_slow_rate) /
-				       (lk->lk_slow_delay - lk->lk_fast_delay)
-				      )
-				  );
-			}
-
-			nd->nd_delay = delay;
-			nd->nd_rate = rate;
-
-			/*
-			 * Increase the transmit credit by depositing the
-			 * current transmit rate.
-			 */
-
-			deposit = nd->nd_tx_deposit;
-			charge  = nd->nd_tx_charge;
-
-			deposit += rate;
-
-			/*
-			 * If the available transmit credit becomes too large,
-			 * reduce the deposit to correct the value.
-			 *
-			 * Too large is the max of:
-			 *		6 times the header size
-			 *		3 times the current transmit rate.
-			 */
-
-			size = 2 * nd->nd_link.lk_header_size;
-
-			if (size < rate)
-				size = rate;
-
-			size *= 3;
-
-			excess = deposit - charge - size;
-
-			if (excess > 0)
-				deposit -= excess;
-
-			nd->nd_tx_deposit = deposit;
-			nd->nd_tx_credit  = deposit - charge;
-
-			/*
-			 * Wake the transmit task only if the transmit credit
-			 * is at least 3 times the transmit header size.
-			 */
-
-			size = 3 * lk->lk_header_size;
-
-			if (nd->nd_tx_credit < size)
-				continue;
-		}
-
-
-		/*
-		 * Enable the READ select to wake the daemon if there
-		 * is useful work for the drp_read routine to perform.
-		 */
-
-		if (waitqueue_active(&nd->nd_tx_waitq) &&
-		    (nd->nd_tx_work != 0 ||
-		    (ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX)) {
-			nd->nd_tx_ready = 1;
-
-			wake_up_interruptible(&nd->nd_tx_waitq);
-
-			/* not needed */
-			/* nd->nd_flag &= ~ND_SELECT; */
-		}
-	}
-
-
-	/*
-	 * Schedule ourself back at the nominal wakeup interval.
-	 */
-	spin_lock_irqsave(&poll_data->poll_lock, lock_flags);
-
-	poll_data->node_active_count--;
-	if (poll_data->node_active_count > 0) {
-		poll_data->node_active_count++;
-		poll_time = poll_data->timer.expires +
-			poll_data->poll_tick * HZ / 1000;
-
-		time = poll_time - jiffies;
-
-		if (time >= 2 * poll_data->poll_tick)
-			poll_time = jiffies + dgrp_poll_tick * HZ / 1000;
-
-		poll_data->timer.expires = poll_time;
-		add_timer(&poll_data->timer);
-	}
-
-	spin_unlock_irqrestore(&poll_data->poll_lock, lock_flags);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_ports_ops.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_ports_ops.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_ports_ops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_ports_ops.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,156 +0,0 @@
-/*
- *
- * Copyright 1999-2000 Digi International (www.digi.com)
- *     James Puzzo <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- * You 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_ports_ops.c
- *
- *  Description:
- *
- *     Handle the file operations required for the /proc/dgrp/ports/...
- *     devices.  Basically gathers tty status for the node and returns it.
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-
-#include "dgrp_common.h"
-
-/* File operation declarations */
-static int dgrp_ports_open(struct inode *, struct file *);
-
-const struct file_operations dgrp_ports_ops = {
-	.owner   = THIS_MODULE,
-	.open    = dgrp_ports_open,
-	.read    = seq_read,
-	.llseek	 = seq_lseek,
-	.release = seq_release
-};
-
-static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	if (*pos == 0)
-		seq_puts(seq, "#num tty_open pr_open tot_wait MSTAT  IFLAG  OFLAG  CFLAG  BPS    DIGIFLAGS\n");
-
-	return pos;
-}
-
-static void *dgrp_ports_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	struct nd_struct *nd = seq->private;
-
-	if (*pos >= nd->nd_chan_count)
-		return NULL;
-
-	*pos += 1;
-
-	return pos;
-}
-
-static void dgrp_ports_seq_stop(struct seq_file *seq, void *v)
-{
-}
-
-static int dgrp_ports_seq_show(struct seq_file *seq, void *v)
-{
-	loff_t *pos = v;
-	struct nd_struct *nd;
-	struct ch_struct *ch;
-	struct un_struct *tun, *pun;
-	unsigned int totcnt;
-
-	nd = seq->private;
-	if (!nd)
-		return 0;
-
-	if (*pos >= nd->nd_chan_count)
-		return 0;
-
-	ch = &nd->nd_chan[*pos];
-	tun = &ch->ch_tun;
-	pun = &ch->ch_pun;
-
-	/*
-	 * If port is not open and no one is waiting to
-	 * open it, the modem signal values can't be
-	 * trusted, and will be zeroed.
-	 */
-	totcnt = tun->un_open_count +
-		pun->un_open_count +
-		ch->ch_wait_count[0] +
-		ch->ch_wait_count[1] +
-		ch->ch_wait_count[2];
-
-	seq_printf(seq, "%02d      %02d      %02d      %02d     0x%04X 0x%04X 0x%04X 0x%04X %-6d 0x%04X\n",
-		   (int) *pos,
-		   tun->un_open_count,
-		   pun->un_open_count,
-		   ch->ch_wait_count[0] +
-		   ch->ch_wait_count[1] +
-		   ch->ch_wait_count[2],
-		   (totcnt ? ch->ch_s_mlast : 0),
-		   ch->ch_s_iflag,
-		   ch->ch_s_oflag,
-		   ch->ch_s_cflag,
-		   (ch->ch_s_brate ? (1843200 / ch->ch_s_brate) : 0),
-		   ch->ch_digi.digi_flags);
-
-	return 0;
-}
-
-static const struct seq_operations ports_seq_ops = {
-	.start = dgrp_ports_seq_start,
-	.next  = dgrp_ports_seq_next,
-	.stop  = dgrp_ports_seq_stop,
-	.show  = dgrp_ports_seq_show,
-};
-
-/**
- * dgrp_ports_open -- open the /proc/dgrp/ports/... device
- * @inode: struct inode *
- * @file: struct file *
- *
- * Open function to open the /proc/dgrp/ports device for a PortServer.
- * This is the open function for struct file_operations
- */
-static int dgrp_ports_open(struct inode *inode, struct file *file)
-{
-	struct seq_file *seq;
-	int rtn;
-
-	rtn = seq_open(file, &ports_seq_ops);
-	if (!rtn) {
-		seq = file->private_data;
-		seq->private = PDE_DATA(inode);
-	}
-
-	return rtn;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_specproc.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_specproc.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_specproc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_specproc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,541 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     James Puzzo  <jamesp at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_specproc.c
- *
- *  Description:
- *
- *     Handle the "config" proc entry for the linux realport device driver
- *     and provide slots for the "net" and "mon" devices
- *
- *  Author:
- *
- *     James A. Puzzo
- *
- */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/cred.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-
-#include "dgrp_common.h"
-
-static struct proc_dir_entry *dgrp_proc_dir_entry;
-
-static int dgrp_add_id(long id);
-static int dgrp_remove_nd(struct nd_struct *nd);
-static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
-				 struct proc_dir_entry *root,
-				 const struct file_operations *fops);
-
-/* File operation declarations */
-static int parse_write_config(char *);
-
-static ssize_t dgrp_config_proc_write(struct file *file,
-				      const char __user *buffer,
-				      size_t count, loff_t *pos);
-
-static int dgrp_nodeinfo_proc_open(struct inode *inode, struct file *file);
-static int dgrp_info_proc_open(struct inode *inode, struct file *file);
-static int dgrp_config_proc_open(struct inode *inode, struct file *file);
-
-static const struct file_operations config_proc_file_ops = {
-	.owner	 = THIS_MODULE,
-	.open	 = dgrp_config_proc_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = seq_release,
-	.write   = dgrp_config_proc_write,
-};
-
-static const struct file_operations info_proc_file_ops = {
-	.owner	 = THIS_MODULE,
-	.open	 = dgrp_info_proc_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations nodeinfo_proc_file_ops = {
-	.owner	 = THIS_MODULE,
-	.open	 = dgrp_nodeinfo_proc_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = seq_release,
-};
-
-static struct proc_dir_entry *net_entry_pointer;
-static struct proc_dir_entry *mon_entry_pointer;
-static struct proc_dir_entry *dpa_entry_pointer;
-static struct proc_dir_entry *ports_entry_pointer;
-
-static void remove_files(struct nd_struct *nd)
-{
-	char buf[3];
-	ID_TO_CHAR(nd->nd_ID, buf);
-	dgrp_remove_node_class_sysfs_files(nd);
-	if (nd->nd_net_de)
-		remove_proc_entry(buf, net_entry_pointer);
-	if (nd->nd_mon_de)
-		remove_proc_entry(buf, mon_entry_pointer);
-	if (nd->nd_dpa_de)
-		remove_proc_entry(buf, dpa_entry_pointer);
-	if (nd->nd_ports_de)
-		remove_proc_entry(buf, ports_entry_pointer);
-}
-
-void dgrp_unregister_proc(void)
-{
-	net_entry_pointer = NULL;
-	mon_entry_pointer = NULL;
-	dpa_entry_pointer = NULL;
-	ports_entry_pointer = NULL;
-
-	if (dgrp_proc_dir_entry) {
-		struct nd_struct *nd;
-		list_for_each_entry(nd, &nd_struct_list, list)
-			remove_files(nd);
-		remove_proc_entry("dgrp/config", NULL);
-		remove_proc_entry("dgrp/info", NULL);
-		remove_proc_entry("dgrp/nodeinfo", NULL);
-		remove_proc_entry("dgrp/net", NULL);
-		remove_proc_entry("dgrp/mon", NULL);
-		remove_proc_entry("dgrp/dpa", NULL);
-		remove_proc_entry("dgrp/ports", NULL);
-		remove_proc_entry("dgrp", NULL);
-		dgrp_proc_dir_entry = NULL;
-	}
-}
-
-void dgrp_register_proc(void)
-{
-	/*
-	 *	Register /proc/dgrp
-	 */
-	dgrp_proc_dir_entry = proc_mkdir("dgrp", NULL);
-	if (!dgrp_proc_dir_entry)
-		return;
-	proc_create("dgrp/config", 0644, NULL, &config_proc_file_ops);
-	proc_create("dgrp/info", 0644, NULL, &info_proc_file_ops);
-	proc_create("dgrp/nodeinfo", 0644, NULL, &nodeinfo_proc_file_ops);
-	net_entry_pointer = proc_mkdir_mode("dgrp/net", 0500, NULL);
-	mon_entry_pointer = proc_mkdir_mode("dgrp/mon", 0500, NULL);
-	dpa_entry_pointer = proc_mkdir_mode("dgrp/dpa", 0500, NULL);
-	ports_entry_pointer = proc_mkdir_mode("dgrp/ports", 0500, NULL);
-}
-
-static void *dgrp_config_proc_start(struct seq_file *m, loff_t *pos)
-{
-	return seq_list_start_head(&nd_struct_list, *pos);
-}
-
-static void *dgrp_config_proc_next(struct seq_file *p, void *v, loff_t *pos)
-{
-	return seq_list_next(v, &nd_struct_list, pos);
-}
-
-static void dgrp_config_proc_stop(struct seq_file *m, void *v)
-{
-}
-
-static int dgrp_config_proc_show(struct seq_file *m, void *v)
-{
-	struct nd_struct *nd;
-	char tmp_id[4];
-
-	if (v == &nd_struct_list) {
-		seq_puts(m, "#-----------------------------------------------------------------------------\n");
-		seq_puts(m, "#                        Avail\n");
-		seq_puts(m, "# ID  Major  State       Ports\n");
-		return 0;
-	}
-
-	nd = list_entry(v, struct nd_struct, list);
-
-	ID_TO_CHAR(nd->nd_ID, tmp_id);
-
-	seq_printf(m, "  %-2.2s  %-5ld  %-10.10s  %-5d\n",
-		   tmp_id,
-		   nd->nd_major,
-		   ND_STATE_STR(nd->nd_state),
-		   nd->nd_chan_count);
-
-	return 0;
-}
-
-static const struct seq_operations proc_config_ops = {
-	.start = dgrp_config_proc_start,
-	.next  = dgrp_config_proc_next,
-	.stop  = dgrp_config_proc_stop,
-	.show  = dgrp_config_proc_show,
-};
-
-static int dgrp_config_proc_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &proc_config_ops);
-}
-
-
-/*
- *  When writing configuration information, each "record" (i.e. each
- *  write) is treated as an independent request.  See the "parse"
- *  description for more details.
- */
-static ssize_t dgrp_config_proc_write(struct file *file,
-				      const char __user *buffer,
-				      size_t count, loff_t *pos)
-{
-	ssize_t retval;
-	char *inbuf, *sp;
-	char *line, *ldelim;
-
-	if (count > 32768)
-		return -EINVAL;
-
-	inbuf = sp = vzalloc(count + 1);
-	if (!inbuf)
-		return -ENOMEM;
-
-	if (copy_from_user(inbuf, buffer, count)) {
-		retval = -EFAULT;
-		goto done;
-	}
-
-	inbuf[count] = 0;
-
-	ldelim = "\n";
-
-	line = strpbrk(sp, ldelim);
-	while (line) {
-		*line = 0;
-		retval = parse_write_config(sp);
-		if (retval)
-			goto done;
-
-		sp = line + 1;
-		line = strpbrk(sp, ldelim);
-	}
-
-	retval = count;
-done:
-	vfree(inbuf);
-	return retval;
-}
-
-/*
- *  ------------------------------------------------------------------------
- *
- *  The following are the functions to parse input
- *
- *  ------------------------------------------------------------------------
- */
-static inline char *skip_past_ws(const char *str)
-{
-	while ((*str) && !isspace(*str))
-		++str;
-
-	return skip_spaces(str);
-}
-
-static int parse_id(char **c, char *cID)
-{
-	int tmp = **c;
-
-	if (isalnum(tmp) || (tmp == '_'))
-		cID[0] = tmp;
-	else
-		return -EINVAL;
-
-	(*c)++; tmp = **c;
-
-	if (isalnum(tmp) || (tmp == '_')) {
-		cID[1] = tmp;
-		(*c)++;
-	} else
-		cID[1] = 0;
-
-	return 0;
-}
-
-static int parse_add_config(char *buf)
-{
-	char *c = buf;
-	int  retval;
-	char cID[2];
-	long ID;
-
-	c = skip_past_ws(c);
-
-	retval = parse_id(&c, cID);
-	if (retval < 0)
-		return retval;
-
-	ID = CHAR_TO_ID(cID);
-
-	c = skip_past_ws(c);
-
-	return dgrp_add_id(ID);
-}
-
-static int parse_del_config(char *buf)
-{
-	char *c = buf;
-	int  retval;
-	struct nd_struct *nd;
-	char cID[2];
-	long ID;
-	long major;
-
-	c = skip_past_ws(c);
-
-	retval = parse_id(&c, cID);
-	if (retval < 0)
-		return retval;
-
-	ID = CHAR_TO_ID(cID);
-
-	c = skip_past_ws(c);
-
-	retval = kstrtol(c, 10, &major);
-	if (retval)
-		return retval;
-
-	nd = nd_struct_get(major);
-	if (!nd)
-		return -EINVAL;
-
-	if ((nd->nd_major != major) || (nd->nd_ID != ID))
-		return -EINVAL;
-
-	return dgrp_remove_nd(nd);
-}
-
-static int parse_chg_config(char *buf)
-{
-	return -EINVAL;
-}
-
-/*
- *  The passed character buffer represents a single configuration request.
- *  If the first character is a "+", it is parsed as a request to add a
- *     PortServer
- *  If the first character is a "-", it is parsed as a request to delete a
- *     PortServer
- *  If the first character is a "*", it is parsed as a request to change a
- *     PortServer
- *  Any other character (including whitespace) causes the record to be
- *     ignored.
- */
-static int parse_write_config(char *buf)
-{
-	int retval;
-
-	switch (buf[0]) {
-	case '+':
-		retval = parse_add_config(buf);
-		break;
-	case '-':
-		retval = parse_del_config(buf);
-		break;
-	case '*':
-		retval = parse_chg_config(buf);
-		break;
-	default:
-		retval = -EINVAL;
-	}
-
-	return retval;
-}
-
-static int dgrp_info_proc_show(struct seq_file *m, void *v)
-{
-	seq_printf(m, "version: %s\n", DIGI_VERSION);
-	seq_puts(m, "register_with_sysfs: 1\n");
-	seq_printf(m, "pollrate: 0x%08x\t(%d)\n",
-		   dgrp_poll_tick, dgrp_poll_tick);
-
-	return 0;
-}
-
-static int dgrp_info_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, dgrp_info_proc_show, NULL);
-}
-
-
-static void *dgrp_nodeinfo_start(struct seq_file *m, loff_t *pos)
-{
-	return seq_list_start_head(&nd_struct_list, *pos);
-}
-
-static void *dgrp_nodeinfo_next(struct seq_file *p, void *v, loff_t *pos)
-{
-	return seq_list_next(v, &nd_struct_list, pos);
-}
-
-static void dgrp_nodeinfo_stop(struct seq_file *m, void *v)
-{
-}
-
-static int dgrp_nodeinfo_show(struct seq_file *m, void *v)
-{
-	struct nd_struct *nd;
-	char hwver[8];
-	char swver[8];
-	char tmp_id[4];
-
-	if (v == &nd_struct_list) {
-		seq_puts(m, "#-----------------------------------------------------------------------------\n");
-		seq_puts(m, "#                 HW       HW   SW\n");
-		seq_puts(m, "# ID  State       Version  ID   Version  Description\n");
-		return 0;
-	}
-
-	nd = list_entry(v, struct nd_struct, list);
-
-	ID_TO_CHAR(nd->nd_ID, tmp_id);
-
-	if (nd->nd_state == NS_READY) {
-		sprintf(hwver, "%d.%d", (nd->nd_hw_ver >> 8) & 0xff,
-			nd->nd_hw_ver & 0xff);
-		sprintf(swver, "%d.%d", (nd->nd_sw_ver >> 8) & 0xff,
-			nd->nd_sw_ver & 0xff);
-		seq_printf(m, "  %-2.2s  %-10.10s  %-7.7s  %-3d  %-7.7s  %-35.35s\n",
-			   tmp_id,
-			   ND_STATE_STR(nd->nd_state),
-			   hwver,
-			   nd->nd_hw_id,
-			   swver,
-			   nd->nd_ps_desc);
-
-	} else {
-		seq_printf(m, "  %-2.2s  %-10.10s\n",
-			   tmp_id,
-			   ND_STATE_STR(nd->nd_state));
-	}
-
-	return 0;
-}
-
-
-static const struct seq_operations nodeinfo_ops = {
-	.start = dgrp_nodeinfo_start,
-	.next  = dgrp_nodeinfo_next,
-	.stop  = dgrp_nodeinfo_stop,
-	.show  = dgrp_nodeinfo_show,
-};
-
-static int dgrp_nodeinfo_proc_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &nodeinfo_ops);
-}
-
-/**
- * dgrp_add_id() -- creates new nd struct and adds it to list
- * @id: id of device to add
- */
-static int dgrp_add_id(long id)
-{
-	struct nd_struct *nd;
-	int ret;
-	int i;
-
-	nd = kzalloc(sizeof(struct nd_struct), GFP_KERNEL);
-	if (!nd)
-		return -ENOMEM;
-
-	nd->nd_major = 0;
-	nd->nd_ID = id;
-
-	spin_lock_init(&nd->nd_lock);
-
-	init_waitqueue_head(&nd->nd_tx_waitq);
-	init_waitqueue_head(&nd->nd_mon_wqueue);
-	init_waitqueue_head(&nd->nd_dpa_wqueue);
-	sema_init(&nd->nd_mon_semaphore, 1);
-	sema_init(&nd->nd_net_semaphore, 1);
-	spin_lock_init(&nd->nd_dpa_lock);
-	nd->nd_state = NS_CLOSED;
-	for (i = 0; i < SEQ_MAX; i++)
-		init_waitqueue_head(&nd->nd_seq_wque[i]);
-
-	/* setup the structures to get the major number */
-	ret = dgrp_tty_init(nd);
-	if (ret)
-		goto error_out;
-
-	nd->nd_major = nd->nd_serial_ttdriver->major;
-
-	ret = nd_struct_add(nd);
-	if (ret)
-		goto error_out;
-
-	dgrp_create_node_class_sysfs_files(nd);
-	nd->nd_net_de = add_proc_file(nd, net_entry_pointer, &dgrp_net_ops);
-	nd->nd_mon_de = add_proc_file(nd, mon_entry_pointer, &dgrp_mon_ops);
-	nd->nd_dpa_de = add_proc_file(nd, dpa_entry_pointer, &dgrp_dpa_ops);
-	nd->nd_ports_de = add_proc_file(nd, ports_entry_pointer,
-					&dgrp_ports_ops);
-	return 0;
-
-	/* FIXME this guy should free the tty driver stored in nd and destroy
-	 * all channel ports */
-error_out:
-	kfree(nd);
-	return ret;
-
-}
-
-static int dgrp_remove_nd(struct nd_struct *nd)
-{
-	int ret;
-
-	/* Check to see if the selected structure is in use */
-	if (nd->nd_tty_ref_cnt)
-		return -EBUSY;
-
-	remove_files(nd);
-
-	dgrp_tty_uninit(nd);
-
-	ret = nd_struct_del(nd);
-	if (ret)
-		return ret;
-
-	kfree(nd);
-	return 0;
-}
-
-static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
-				 struct proc_dir_entry *root,
-				 const struct file_operations *fops)
-{
-	char buf[3];
-	ID_TO_CHAR(node->nd_ID, buf);
-	return proc_create_data(buf, 0600, root, fops, node);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_sysfs.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_sysfs.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_sysfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_sysfs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,558 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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 "dgrp_common.h"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/serial_reg.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-
-
-#define PORTSERVER_DIVIDEND 1843200
-#define SERIAL_TYPE_NORMAL      1
-#define SERIAL_TYPE_CALLOUT     2
-#define SERIAL_TYPE_XPRINT      3
-
-
-static struct class *dgrp_class;
-static struct device *dgrp_class_nodes_dev;
-static struct device *dgrp_class_global_settings_dev;
-
-
-static ssize_t dgrp_class_version_show(struct class *class,
-				       struct class_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION);
-}
-static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL);
-
-
-static ssize_t dgrp_class_register_with_sysfs_show(struct device *c,
-						   struct device_attribute *attr,
-						   char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "1\n");
-}
-static DEVICE_ATTR(register_with_sysfs, 0400,
-		   dgrp_class_register_with_sysfs_show, NULL);
-
-
-static ssize_t dgrp_class_pollrate_show(struct device *c,
-					struct device_attribute *attr,
-					char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick);
-}
-
-static ssize_t dgrp_class_pollrate_store(struct device *c,
-					 struct device_attribute *attr,
-					 const char *buf, size_t count)
-{
-	if (sscanf(buf, "0x%x\n", &dgrp_poll_tick) != 1)
-		return -EINVAL;
-
-	return count;
-}
-static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
-		   dgrp_class_pollrate_store);
-
-static struct attribute *dgrp_sysfs_global_settings_entries[] = {
-	&dev_attr_pollrate.attr,
-	&dev_attr_register_with_sysfs.attr,
-	NULL
-};
-
-
-static struct attribute_group dgrp_global_settings_attribute_group = {
-	.name = NULL,
-	.attrs = dgrp_sysfs_global_settings_entries,
-};
-
-
-
-int dgrp_create_class_sysfs_files(void)
-{
-	int ret = 0;
-	int max_majors = 1U << (32 - MINORBITS);
-
-	dgrp_class = class_create(THIS_MODULE, "digi_realport");
-	if (IS_ERR(dgrp_class))
-		return PTR_ERR(dgrp_class);
-	ret = class_create_file(dgrp_class, &class_attr_driver_version);
-	if (ret)
-		goto err_class;
-
-	dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
-		MKDEV(0, max_majors + 1), NULL, "driver_settings");
-	if (IS_ERR(dgrp_class_global_settings_dev)) {
-		ret = PTR_ERR(dgrp_class_global_settings_dev);
-		goto err_file;
-	}
-	ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
-		&dgrp_global_settings_attribute_group);
-	if (ret) {
-		pr_alert("%s: failed to create sysfs global settings device attributes.\n",
-			__func__);
-		goto err_dev1;
-	}
-
-	dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
-		MKDEV(0, max_majors + 2), NULL, "nodes");
-	if (IS_ERR(dgrp_class_nodes_dev)) {
-		ret = PTR_ERR(dgrp_class_nodes_dev);
-		goto err_group;
-	}
-
-	return 0;
-err_group:
-	sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
-		&dgrp_global_settings_attribute_group);
-err_dev1:
-	device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
-err_file:
-	class_remove_file(dgrp_class, &class_attr_driver_version);
-err_class:
-	class_destroy(dgrp_class);
-	return ret;
-}
-
-
-void dgrp_remove_class_sysfs_files(void)
-{
-	struct nd_struct *nd;
-	int max_majors = 1U << (32 - MINORBITS);
-
-	list_for_each_entry(nd, &nd_struct_list, list)
-		dgrp_remove_node_class_sysfs_files(nd);
-
-	sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
-		&dgrp_global_settings_attribute_group);
-
-	class_remove_file(dgrp_class, &class_attr_driver_version);
-
-	device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
-	device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
-	class_destroy(dgrp_class);
-}
-
-static ssize_t dgrp_node_state_show(struct device *c,
-				    struct device_attribute *attr, char *buf)
-{
-	struct nd_struct *nd;
-
-	if (!c)
-		return 0;
-	nd = dev_get_drvdata(c);
-	if (!nd)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
-}
-
-static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
-
-static ssize_t dgrp_node_description_show(struct device *c,
-					  struct device_attribute *attr,
-					  char *buf)
-{
-	struct nd_struct *nd;
-
-	if (!c)
-		return 0;
-	nd = dev_get_drvdata(c);
-	if (!nd)
-		return 0;
-
-	if (nd->nd_state == NS_READY)
-		return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
-	return 0;
-}
-static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
-
-static ssize_t dgrp_node_hw_version_show(struct device *c,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct nd_struct *nd;
-
-	if (!c)
-		return 0;
-	nd = dev_get_drvdata(c);
-	if (!nd)
-		return 0;
-
-	if (nd->nd_state == NS_READY)
-		return snprintf(buf, PAGE_SIZE, "%d.%d\n",
-				(nd->nd_hw_ver >> 8) & 0xff,
-				nd->nd_hw_ver & 0xff);
-
-	return 0;
-}
-static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
-
-static ssize_t dgrp_node_hw_id_show(struct device *c,
-				    struct device_attribute *attr, char *buf)
-{
-	struct nd_struct *nd;
-
-	if (!c)
-		return 0;
-	nd = dev_get_drvdata(c);
-	if (!nd)
-		return 0;
-
-
-	if (nd->nd_state == NS_READY)
-		return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
-	return 0;
-}
-static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
-
-static ssize_t dgrp_node_sw_version_show(struct device *c,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct nd_struct *nd;
-
-	if (!c)
-		return 0;
-
-	nd = dev_get_drvdata(c);
-	if (!nd)
-		return 0;
-
-	if (nd->nd_state == NS_READY)
-		return snprintf(buf, PAGE_SIZE, "%d.%d\n",
-				(nd->nd_sw_ver >> 8) & 0xff,
-				nd->nd_sw_ver & 0xff);
-
-	return 0;
-}
-static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
-
-
-static struct attribute *dgrp_sysfs_node_entries[] = {
-	&dev_attr_state.attr,
-	&dev_attr_description_info.attr,
-	&dev_attr_hw_version_info.attr,
-	&dev_attr_hw_id_info.attr,
-	&dev_attr_sw_version_info.attr,
-	NULL
-};
-
-
-static struct attribute_group dgrp_node_attribute_group = {
-	.name = NULL,
-	.attrs = dgrp_sysfs_node_entries,
-};
-
-
-void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
-{
-	int ret;
-	char name[10];
-
-	if (nd->nd_ID)
-		ID_TO_CHAR(nd->nd_ID, name);
-	else
-		sprintf(name, "node%ld", nd->nd_major);
-
-	nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
-		MKDEV(0, nd->nd_major), NULL, "%s", name);
-
-	ret = sysfs_create_group(&nd->nd_class_dev->kobj,
-				 &dgrp_node_attribute_group);
-
-	if (ret) {
-		pr_alert("%s: failed to create sysfs node device attributes.\n",
-			__func__);
-		sysfs_remove_group(&nd->nd_class_dev->kobj,
-				   &dgrp_node_attribute_group);
-		return;
-	}
-
-	dev_set_drvdata(nd->nd_class_dev, nd);
-
-}
-
-
-void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
-{
-	if (nd->nd_class_dev) {
-		sysfs_remove_group(&nd->nd_class_dev->kobj,
-				   &dgrp_node_attribute_group);
-
-		device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
-		nd->nd_class_dev = NULL;
-	}
-}
-
-
-
-static ssize_t dgrp_tty_state_show(struct device *d,
-				   struct device_attribute *attr, char *buf)
-{
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			un->un_open_count ? "Open" : "Closed");
-}
-static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
-
-static ssize_t dgrp_tty_baud_show(struct device *d,
-				  struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-		un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
-}
-static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
-
-
-static ssize_t dgrp_tty_msignals_show(struct device *d,
-				      struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-
-	if (ch->ch_open_count) {
-		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
-			(ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
-			(ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
-			(ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
-			(ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
-			(ch->ch_s_mlast & DM_CD) ? "DCD" : "",
-			(ch->ch_s_mlast & DM_RI)  ? "RI"  : "");
-	}
-	return 0;
-}
-static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
-
-
-static ssize_t dgrp_tty_iflag_show(struct device *d,
-				   struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
-}
-static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
-
-
-static ssize_t dgrp_tty_cflag_show(struct device *d,
-				   struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
-}
-static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
-
-
-static ssize_t dgrp_tty_oflag_show(struct device *d,
-				   struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
-}
-static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
-
-
-static ssize_t dgrp_tty_digi_flag_show(struct device *d,
-				       struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
-}
-static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
-
-
-static ssize_t dgrp_tty_rxcount_show(struct device *d,
-				     struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
-}
-static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
-
-
-static ssize_t dgrp_tty_txcount_show(struct device *d,
-				     struct device_attribute *attr, char *buf)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
-}
-static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
-
-
-static ssize_t dgrp_tty_name_show(struct device *d,
-				  struct device_attribute *attr, char *buf)
-{
-	struct nd_struct *nd;
-	struct ch_struct *ch;
-	struct un_struct *un;
-	char name[10];
-
-	if (!d)
-		return 0;
-	un = dev_get_drvdata(d);
-	if (!un)
-		return 0;
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-	nd = ch->ch_nd;
-	if (!nd)
-		return 0;
-
-	ID_TO_CHAR(nd->nd_ID, name);
-
-	return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-		un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
-		name, ch->ch_portnum);
-}
-static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
-
-
-static struct attribute *dgrp_sysfs_tty_entries[] = {
-	&dev_attr_state_info.attr,
-	&dev_attr_baud_info.attr,
-	&dev_attr_msignals_info.attr,
-	&dev_attr_iflag_info.attr,
-	&dev_attr_cflag_info.attr,
-	&dev_attr_oflag_info.attr,
-	&dev_attr_digi_flag_info.attr,
-	&dev_attr_rxcount_info.attr,
-	&dev_attr_txcount_info.attr,
-	&dev_attr_custom_name.attr,
-	NULL
-};
-
-
-static struct attribute_group dgrp_tty_attribute_group = {
-	.name = NULL,
-	.attrs = dgrp_sysfs_tty_entries,
-};
-
-
-void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
-{
-	int ret;
-
-	ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
-	if (ret) {
-		pr_alert("%s: failed to create sysfs tty device attributes.\n",
-			__func__);
-		sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
-		return;
-	}
-
-	dev_set_drvdata(c, un);
-
-}
-
-
-void dgrp_remove_tty_sysfs(struct device *c)
-{
-	sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_tty.c linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_tty.c
--- linux-libre-3.16-gnu/drivers/staging/dgrp/dgrp_tty.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/dgrp_tty.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3337 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     Gene Olson    <Gene_Olson at digi dot com>
- *     James Puzzo   <jamesp at digi dot com>
- *     Jeff Randall
- *     Scott Kilau   <scottk at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/*
- *
- *  Filename:
- *
- *     dgrp_tty.c
- *
- *  Description:
- *
- *     This file implements the tty driver functionality for the
- *     RealPort driver software.
- *
- *  Author:
- *
- *     James A. Puzzo
- *     Ann-Marie Westgate
- *
- */
-
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/device.h>
-#include <linux/sched.h>
-#include <linux/uaccess.h>
-
-#include "dgrp_common.h"
-
-#ifndef _POSIX_VDISABLE
-#define   _POSIX_VDISABLE ('\0')
-#endif
-
-/*
- *	forward declarations
- */
-
-static void drp_param(struct ch_struct *);
-static void dgrp_tty_close(struct tty_struct *, struct file *);
-
-/* ioctl helper functions */
-static int set_modem_info(struct ch_struct *, unsigned int, unsigned int *);
-static int get_modem_info(struct ch_struct *, unsigned int *);
-static void dgrp_set_custom_speed(struct ch_struct *, int);
-static int dgrp_tty_digigetedelay(struct tty_struct *, int *);
-static int dgrp_tty_digisetedelay(struct tty_struct *, int *);
-static int dgrp_send_break(struct ch_struct *, int);
-
-static ushort  tty_to_ch_flags(struct tty_struct *, char);
-static tcflag_t ch_to_tty_flags(unsigned short, char);
-
-static void dgrp_tty_input_start(struct tty_struct *);
-static void dgrp_tty_input_stop(struct tty_struct *);
-
-static void drp_wmove(struct ch_struct *, int, void*, int);
-
-static int dgrp_tty_open(struct tty_struct *, struct file *);
-static void dgrp_tty_close(struct tty_struct *, struct file *);
-static int dgrp_tty_write(struct tty_struct *, const unsigned char *, int);
-static int dgrp_tty_write_room(struct tty_struct *);
-static void dgrp_tty_flush_buffer(struct tty_struct *);
-static int dgrp_tty_chars_in_buffer(struct tty_struct *);
-static int dgrp_tty_ioctl(struct tty_struct *, unsigned int, unsigned long);
-static void dgrp_tty_set_termios(struct tty_struct *, struct ktermios *);
-static void dgrp_tty_stop(struct tty_struct *);
-static void dgrp_tty_start(struct tty_struct *);
-static void dgrp_tty_throttle(struct tty_struct *);
-static void dgrp_tty_unthrottle(struct tty_struct *);
-static void dgrp_tty_hangup(struct tty_struct *);
-static int dgrp_tty_put_char(struct tty_struct *, unsigned char);
-static int dgrp_tty_tiocmget(struct tty_struct *);
-static int dgrp_tty_tiocmset(struct tty_struct *, unsigned int, unsigned int);
-static int dgrp_tty_send_break(struct tty_struct *, int);
-static void dgrp_tty_send_xchar(struct tty_struct *, char);
-
-/*
- *	tty defines
- */
-#define	SERIAL_TYPE_NORMAL	1
-#define	SERIAL_TYPE_CALLOUT	2
-#define	SERIAL_TYPE_XPRINT	3
-
-
-/*
- *	tty globals/statics
- */
-
-
-#define PORTSERVER_DIVIDEND	1843200
-
-/*
- *  Default transparent print information.
- */
-static struct digi_struct digi_init = {
-	.digi_flags   = DIGI_COOK,	/* Flags			*/
-	.digi_maxcps  = 100,		/* Max CPS			*/
-	.digi_maxchar = 50,		/* Max chars in print queue	*/
-	.digi_bufsize = 100,		/* Printer buffer size		*/
-	.digi_onlen   = 4,		/* size of printer on string	*/
-	.digi_offlen  = 4,		/* size of printer off string	*/
-	.digi_onstr   = "\033[5i",	/* ANSI printer on string	*/
-	.digi_offstr  = "\033[4i",	/* ANSI printer off string	*/
-	.digi_term    = "ansi"		/* default terminal type	*/
-};
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially.
- *
- *	This defines a raw port at 9600 baud, 8 data bits, no parity,
- *	1 stop bit.
- */
-static struct ktermios DefaultTermios = {
-	.c_iflag = (ICRNL | IXON),
-	.c_oflag = (OPOST | ONLCR),
-	.c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_lflag = (ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL
-		    | ECHOKE | IEXTEN),
-	.c_cc    = INIT_C_CC,
-	.c_line  = 0,
-};
-
-/* Define our tty operations struct */
-static const struct tty_operations dgrp_tty_ops = {
-	.open            = dgrp_tty_open,
-	.close           = dgrp_tty_close,
-	.write           = dgrp_tty_write,
-	.write_room      = dgrp_tty_write_room,
-	.flush_buffer    = dgrp_tty_flush_buffer,
-	.chars_in_buffer = dgrp_tty_chars_in_buffer,
-	.flush_chars     = NULL,
-	.ioctl           = dgrp_tty_ioctl,
-	.set_termios     = dgrp_tty_set_termios,
-	.stop            = dgrp_tty_stop,
-	.start           = dgrp_tty_start,
-	.throttle        = dgrp_tty_throttle,
-	.unthrottle      = dgrp_tty_unthrottle,
-	.hangup          = dgrp_tty_hangup,
-	.put_char        = dgrp_tty_put_char,
-	.tiocmget        = dgrp_tty_tiocmget,
-	.tiocmset        = dgrp_tty_tiocmset,
-	.break_ctl       = dgrp_tty_send_break,
-	.send_xchar      = dgrp_tty_send_xchar
-};
-
-
-static int calc_baud_rate(struct un_struct *un)
-{
-	int i;
-	int brate;
-
-	struct baud_rates {
-		unsigned int rate;
-		unsigned int cflag;
-	};
-
-	static struct baud_rates baud_rates[] = {
-		{ 921600, B921600 },
-		{ 460800, B460800 },
-		{ 230400, B230400 },
-		{ 115200, B115200 },
-		{  57600, B57600  },
-		{  38400, B38400  },
-		{  19200, B19200  },
-		{   9600, B9600   },
-		{   4800, B4800   },
-		{   2400, B2400   },
-		{   1200, B1200   },
-		{    600, B600    },
-		{    300, B300    },
-		{    200, B200    },
-		{    150, B150    },
-		{    134, B134    },
-		{    110, B110    },
-		{     75, B75     },
-		{     50, B50     },
-		{      0, B9600  }
-	};
-
-	brate = C_BAUD(un->un_tty);
-
-	for (i = 0; baud_rates[i].rate; i++) {
-		if (baud_rates[i].cflag == brate)
-			break;
-	}
-
-	return baud_rates[i].rate;
-}
-
-static int calc_fastbaud_rate(struct un_struct *un, struct ktermios *uts)
-{
-	int i;
-	int brate;
-
-	ulong bauds[2][16] = {
-		{ /* fastbaud*/
-			0,      57600,	 76800,	115200,
-			131657, 153600, 230400, 460800,
-			921600, 1200,   1800,	2400,
-			4800,   9600,	19200,	38400 },
-		{ /* fastbaud & CBAUDEX */
-			0,      57600,	115200,	230400,
-			460800, 150,    200,    921600,
-			600,    1200,   1800,	2400,
-			4800,   9600,	19200,	38400 }
-	};
-
-	brate = C_BAUD(un->un_tty) & 0xff;
-
-	i = (uts->c_cflag & CBAUDEX) ? 1 : 0;
-
-
-	if ((i >= 0) && (i < 2) && (brate >= 0) && (brate < 16))
-		brate = bauds[i][brate];
-	else
-		brate = 0;
-
-	return brate;
-}
-
-/**
- * drp_param() -- send parameter values to be sent to the node
- * @ch: channel structure of port to modify
- *
- * Interprets the tty and modem changes made by an application
- * program (by examining the termios structures) and sets up
- * parameter values to be sent to the node.
- */
-static void drp_param(struct ch_struct *ch)
-{
-	struct nd_struct *nd;
-	struct un_struct *un;
-	int   brate;
-	int   mflow;
-	int   xflag;
-	int   iflag;
-	struct ktermios *tts, *pts, *uts;
-
-	nd = ch->ch_nd;
-
-	/*
-	 *  If the terminal device is open, use it to set up all tty
-	 *  modes and functions.  Otherwise use the printer device.
-	 */
-
-	if (ch->ch_tun.un_open_count) {
-
-		un = &ch->ch_tun;
-		tts = &ch->ch_tun.un_tty->termios;
-
-		/*
-		 *  If both devices are open, copy critical line
-		 *  parameters from the tty device to the printer,
-		 *  so that if the tty is closed, the printer will
-		 *  continue without disruption.
-		 */
-
-		if (ch->ch_pun.un_open_count) {
-
-			pts = &ch->ch_pun.un_tty->termios;
-
-			pts->c_cflag ^=
-				(pts->c_cflag ^ tts->c_cflag) &
-				(CBAUD  | CSIZE | CSTOPB | CREAD | PARENB |
-				 PARODD | HUPCL | CLOCAL);
-
-			pts->c_iflag ^=
-				(pts->c_iflag ^ tts->c_iflag) &
-				(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK |
-				 ISTRIP | IXON   | IXANY  | IXOFF);
-
-			pts->c_cc[VSTART] = tts->c_cc[VSTART];
-			pts->c_cc[VSTOP] = tts->c_cc[VSTOP];
-		}
-	} else if (ch->ch_pun.un_open_count == 0) {
-		pr_warn("%s - ch_pun.un_open_count shouldn't be 0\n",
-		       __func__);
-		return;
-	} else {
-		un = &ch->ch_pun;
-	}
-
-	uts = &un->un_tty->termios;
-
-	/*
-	 * Determine if FAST writes can be performed.
-	 */
-
-	if ((ch->ch_digi.digi_flags & DIGI_COOK) != 0 &&
-	    (ch->ch_tun.un_open_count != 0)  &&
-	    !((un->un_tty)->ldisc->ops->flags & LDISC_FLAG_DEFINED) &&
-	    !(L_XCASE(un->un_tty))) {
-		ch->ch_flag |= CH_FAST_WRITE;
-	} else {
-		ch->ch_flag &= ~CH_FAST_WRITE;
-	}
-
-	/*
-	 *  If FAST writes can be performed, and OPOST is on in the
-	 *  terminal device, do OPOST handling in the server.
-	 */
-
-	if ((ch->ch_flag & CH_FAST_WRITE) &&
-	      O_OPOST(un->un_tty) != 0) {
-		int oflag = tty_to_ch_flags(un->un_tty, 'o');
-
-		/* add to ch_ocook any processing flags set in the termio */
-		ch->ch_ocook |= oflag & (OF_OLCUC |
-					 OF_ONLCR |
-					 OF_OCRNL |
-					 OF_ONLRET |
-					 OF_TABDLY);
-
-		/*
-		 * the hpux driver clears any flags set in ch_ocook
-		 * from the termios oflag.  It is STILL reported though
-		 * by a TCGETA
-		 */
-
-		oflag = ch_to_tty_flags(ch->ch_ocook, 'o');
-		uts->c_oflag &= ~oflag;
-
-	} else {
-		/* clear the ch->ch_ocook flag */
-		int oflag = ch_to_tty_flags(ch->ch_ocook, 'o');
-		uts->c_oflag |= oflag;
-		ch->ch_ocook = 0;
-	}
-
-	ch->ch_oflag = ch->ch_ocook;
-
-
-	ch->ch_flag &= ~CH_FAST_READ;
-
-	/*
-	 *  Generate channel flags
-	 */
-
-	if (C_BAUD(un->un_tty) == B0) {
-		if (!(ch->ch_flag & CH_BAUD0)) {
-			/* TODO : the HPUX driver flushes line */
-			/* TODO : discipline, I assume I don't have to */
-
-			ch->ch_tout = ch->ch_tin;
-			ch->ch_rout = ch->ch_rin;
-
-			ch->ch_break_time = 0;
-
-			ch->ch_send |= RR_TX_FLUSH | RR_RX_FLUSH;
-
-			ch->ch_mout &= ~(DM_DTR | DM_RTS);
-
-			ch->ch_flag |= CH_BAUD0;
-		}
-	} else if (ch->ch_custom_speed) {
-		ch->ch_brate = PORTSERVER_DIVIDEND / ch->ch_custom_speed;
-
-		if (ch->ch_flag & CH_BAUD0) {
-			ch->ch_mout |= DM_DTR | DM_RTS;
-
-			ch->ch_flag &= ~CH_BAUD0;
-		}
-	} else {
-		/*
-		 * Baud rate mapping.
-		 *
-		 * If FASTBAUD isn't on, we can scan the new baud rate list
-		 * as required.
-		 *
-		 * However, if FASTBAUD is on, we must go to the old
-		 * baud rate mapping that existed many many moons ago,
-		 * for compatibility reasons.
-		 */
-
-		if (!(ch->ch_digi.digi_flags & DIGI_FAST))
-			brate = calc_baud_rate(un);
-		else
-			brate = calc_fastbaud_rate(un, uts);
-
-		if (brate == 0)
-			brate = 9600;
-
-		ch->ch_brate = PORTSERVER_DIVIDEND / brate;
-
-		if (ch->ch_flag & CH_BAUD0) {
-			ch->ch_mout |= DM_DTR | DM_RTS;
-
-			ch->ch_flag &= ~CH_BAUD0;
-		}
-	}
-
-	/*
-	 *  Generate channel cflags from the termio.
-	 */
-
-	ch->ch_cflag = tty_to_ch_flags(un->un_tty, 'c');
-
-	/*
-	 *  Generate channel iflags from the termio.
-	 */
-
-	iflag = (int) tty_to_ch_flags(un->un_tty, 'i');
-
-	if (START_CHAR(un->un_tty) == _POSIX_VDISABLE ||
-	    STOP_CHAR(un->un_tty) == _POSIX_VDISABLE) {
-		iflag &= ~(IF_IXON | IF_IXANY | IF_IXOFF);
-	}
-
-	ch->ch_iflag = iflag;
-
-	/*
-	 *  Generate flow control characters
-	 */
-
-	/*
-	 * From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE}
-	 * is defined for the terminal device file, and the value
-	 * of one of the changeable special control characters (see
-	 * 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be
-	 * disabled, that is, no input data shall be recognized as
-	 * the disabled special character."
-	 *
-	 * OK, so we don't ever assign S/DXB XON or XOFF to _POSIX_VDISABLE.
-	 */
-
-	if (uts->c_cc[VSTART] != _POSIX_VDISABLE)
-		ch->ch_xon = uts->c_cc[VSTART];
-	if (uts->c_cc[VSTOP] != _POSIX_VDISABLE)
-		ch->ch_xoff = uts->c_cc[VSTOP];
-
-	ch->ch_lnext = (uts->c_cc[VLNEXT] == _POSIX_VDISABLE ? 0 :
-			uts->c_cc[VLNEXT]);
-
-	/*
-	 * Also, if either c_cc[START] or c_cc[STOP] is set to
-	 * _POSIX_VDISABLE, we can't really do software flow
-	 * control--in either direction--so we turn it off as
-	 * far as S/DXB is concerned.  In essence, if you disable
-	 * one, you disable the other too.
-	 */
-	if ((uts->c_cc[VSTART] == _POSIX_VDISABLE) ||
-	    (uts->c_cc[VSTOP] == _POSIX_VDISABLE))
-		ch->ch_iflag &= ~(IF_IXOFF | IF_IXON);
-
-	/*
-	 *  Update xflags.
-	 */
-
-	xflag = 0;
-
-	if (ch->ch_digi.digi_flags & DIGI_AIXON)
-		xflag = XF_XIXON;
-
-	if ((ch->ch_xxon == _POSIX_VDISABLE) ||
-	    (ch->ch_xxoff == _POSIX_VDISABLE))
-		xflag &= ~XF_XIXON;
-
-	ch->ch_xflag = xflag;
-
-
-	/*
-	 *  Figure effective DCD value.
-	 */
-
-	if (C_CLOCAL(un->un_tty))
-		ch->ch_flag |= CH_CLOCAL;
-	else
-		ch->ch_flag &= ~CH_CLOCAL;
-
-	/*
-	 *  Check modem signals
-	 */
-
-	dgrp_carrier(ch);
-
-	/*
-	 *  Get hardware handshake value.
-	 */
-
-	mflow = 0;
-
-	if (C_CRTSCTS(un->un_tty))
-		mflow |= (DM_RTS | DM_CTS);
-
-	if (ch->ch_digi.digi_flags & RTSPACE)
-		mflow |= DM_RTS;
-
-	if (ch->ch_digi.digi_flags & DTRPACE)
-		mflow |= DM_DTR;
-
-	if (ch->ch_digi.digi_flags & CTSPACE)
-		mflow |= DM_CTS;
-
-	if (ch->ch_digi.digi_flags & DSRPACE)
-		mflow |= DM_DSR;
-
-	if (ch->ch_digi.digi_flags & DCDPACE)
-		mflow |= DM_CD;
-
-	if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
-		mflow |= DM_RTS_TOGGLE;
-
-	ch->ch_mflow = mflow;
-
-	/*
-	 *  Send the changes to the server.
-	 */
-
-	ch->ch_flag |= CH_PARAM;
-	(ch->ch_nd)->nd_tx_work = 1;
-
-	if (waitqueue_active(&ch->ch_flag_wait))
-		wake_up_interruptible(&ch->ch_flag_wait);
-}
-
-/*
- * This function is just used as a callback for timeouts
- * waiting on the ch_sleep flag.
- */
-static void wake_up_drp_sleep_timer(unsigned long ptr)
-{
-	struct ch_struct *ch = (struct ch_struct *) ptr;
-	if (ch)
-		wake_up(&ch->ch_sleep);
-}
-
-
-/*
- * Set up our own sleep that can't be cancelled
- * until our timeout occurs.
- */
-static void drp_my_sleep(struct ch_struct *ch)
-{
-	struct timer_list drp_wakeup_timer;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/*
-	 * First make sure we're ready to receive the wakeup.
-	 */
-
-	add_wait_queue(&ch->ch_sleep, &wait);
-	current->state = TASK_UNINTERRUPTIBLE;
-
-	/*
-	 * Since we are uninterruptible, set a timer to
-	 * unset the uninterruptable state in 1 second.
-	 */
-
-	init_timer(&drp_wakeup_timer);
-	drp_wakeup_timer.function = wake_up_drp_sleep_timer;
-	drp_wakeup_timer.data = (unsigned long) ch;
-	drp_wakeup_timer.expires = jiffies + (1 * HZ);
-	add_timer(&drp_wakeup_timer);
-
-	schedule();
-
-	del_timer(&drp_wakeup_timer);
-
-	remove_wait_queue(&ch->ch_sleep, &wait);
-}
-
-/*
- * dgrp_tty_open()
- *
- * returns:
- *    -EBUSY    - this is a callout device and the normal device is active
- *              - there is an error in opening the tty
- *    -ENODEV   - the channel does not exist
- *    -EAGAIN   - we are in the middle of hanging up or closing
- *              - IMMEDIATE_OPEN fails
- *    -ENXIO or -EAGAIN
- *              - if the port is outside physical range
- *    -EINTR    - the open is interrupted
- *
- */
-static int dgrp_tty_open(struct tty_struct *tty, struct file *file)
-{
-	int    retval = 0;
-	struct nd_struct  *nd;
-	struct ch_struct *ch;
-	struct un_struct  *un;
-	int    port;
-	int    delay_error;
-	int    otype;
-	int    unf;
-	int    wait_carrier;
-	int    category;
-	int    counts_were_incremented = 0;
-	ulong lock_flags;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/*
-	 * Do some initial checks to see if the node and port exist
-	 */
-
-	nd = nd_struct_get(MAJOR(tty_devnum(tty)));
-	port = PORT_NUM(MINOR(tty_devnum(tty)));
-	category = OPEN_CATEGORY(MINOR(tty_devnum(tty)));
-
-	if (!nd)
-		return -ENODEV;
-
-	if (port >= CHAN_MAX)
-		return -ENODEV;
-
-	/*
-	 *  The channel exists.
-	 */
-
-	ch = nd->nd_chan + port;
-
-	un = IS_PRINT(MINOR(tty_devnum(tty))) ? &ch->ch_pun : &ch->ch_tun;
-	un->un_tty = tty;
-	tty->driver_data = un;
-
-	/*
-	 * If we are in the middle of hanging up,
-	 * then return an error
-	 */
-	if (tty_hung_up_p(file)) {
-		retval = ((un->un_flag & UN_HUP_NOTIFY) ?
-			   -EAGAIN : -ERESTARTSYS);
-		goto done;
-	}
-
-	/*
-	 * If the port is in the middle of closing, then block
-	 * until it is done, then try again.
-	 */
-	retval = wait_event_interruptible(un->un_close_wait,
-			((un->un_flag & UN_CLOSING) == 0));
-
-	if (retval)
-		goto done;
-
-	/*
-	 * If the port is in the middle of a reopen after a network disconnect,
-	 * wait until it is done, then try again.
-	 */
-	retval = wait_event_interruptible(ch->ch_flag_wait,
-			((ch->ch_flag & CH_PORT_GONE) == 0));
-
-	if (retval)
-		goto done;
-
-	/*
-	 * If this is a callout device, then just make sure the normal
-	 * device isn't being used.
-	 */
-
-	if (tty->driver->subtype == SERIAL_TYPE_CALLOUT) {
-		if (un->un_flag & UN_NORMAL_ACTIVE) {
-			retval = -EBUSY;
-			goto done;
-		} else {
-			un->un_flag |= UN_CALLOUT_ACTIVE;
-		}
-	}
-
-	/*
-	 *  Loop waiting until the open can be successfully completed.
-	 */
-
-	spin_lock_irqsave(&nd->nd_lock, lock_flags);
-
-	nd->nd_tx_work = 1;
-
-	for (;;) {
-		wait_carrier = 0;
-
-		/*
-		 * Determine the open type from the flags provided.
-		 */
-
-		/*
-		 * If the port is not enabled, then exit
-		 */
-		if (test_bit(TTY_IO_ERROR, &tty->flags)) {
-			/* there was an error in opening the tty */
-			if (un->un_flag & UN_CALLOUT_ACTIVE)
-				retval = -EBUSY;
-			else
-				un->un_flag |= UN_NORMAL_ACTIVE;
-			goto unlock;
-		}
-
-		if (file->f_flags & O_NONBLOCK) {
-
-			/*
-			 * if the O_NONBLOCK is set, errors on read and write
-			 * must return -EAGAIN immediately and NOT sleep
-			 * on the waitqs.
-			 */
-			otype = OTYPE_IMMEDIATE;
-			delay_error = -EAGAIN;
-
-		} else if (!OPEN_WAIT_AVAIL(category) ||
-			  (file->f_flags & O_NDELAY) != 0) {
-			otype = OTYPE_IMMEDIATE;
-			delay_error = -EBUSY;
-
-		} else if (!OPEN_WAIT_CARRIER(category) ||
-			  ((ch->ch_digi.digi_flags & DIGI_FORCEDCD) != 0) ||
-			  C_CLOCAL(tty)) {
-			otype = OTYPE_PERSISTENT;
-			delay_error = 0;
-
-		} else {
-			otype = OTYPE_INCOMING;
-			delay_error = 0;
-		}
-
-		/*
-		 * Handle port currently outside physical port range.
-		 */
-
-		if (port >= nd->nd_chan_count) {
-			if (otype == OTYPE_IMMEDIATE) {
-				retval = (nd->nd_state == NS_READY) ?
-						-ENXIO : -EAGAIN;
-				goto unlock;
-			}
-		}
-
-		/*
-		 *  Handle port not currently open.
-		 */
-
-		else if (ch->ch_open_count == 0) {
-			/*
-			 * Return an error when an Incoming Open
-			 * response indicates the port is busy.
-			 */
-
-			if (ch->ch_open_error != 0 && otype == ch->ch_otype) {
-				retval = (ch->ch_open_error <= 2) ?
-					  delay_error : -ENXIO;
-				goto unlock;
-			}
-
-			/*
-			 * Fail any new Immediate open if we do not have
-			 * a normal connection to the server.
-			 */
-
-			if (nd->nd_state != NS_READY &&
-			    otype == OTYPE_IMMEDIATE) {
-				retval = -EAGAIN;
-				goto unlock;
-			}
-
-			/*
-			 * If a Realport open of the correct type has
-			 * succeeded, complete the open.
-			 */
-
-			if (ch->ch_state == CS_READY && ch->ch_otype == otype)
-				break;
-		}
-
-		/*
-		 * Handle port already open and active as a device
-		 * of same category.
-		 */
-
-		else if ((ch->ch_category == category) ||
-			  IS_PRINT(MINOR(tty_devnum(tty)))) {
-			/*
-			 * Fail if opening the device now would
-			 * violate exclusive use.
-			 */
-			unf = ch->ch_tun.un_flag | ch->ch_pun.un_flag;
-
-			if ((file->f_flags & O_EXCL) || (unf & UN_EXCL)) {
-				retval = -EBUSY;
-				goto unlock;
-			}
-
-			/*
-			 * If the open device is in the hangup state, all
-			 * system calls fail except close().
-			 */
-
-			/* TODO : check on hangup_p calls */
-
-			if (ch->ch_flag & CH_HANGUP) {
-				retval = -ENXIO;
-				goto unlock;
-			}
-
-			/*
-			 * If the port is ready, and carrier is ignored
-			 * or present, then complete the open.
-			 */
-
-			if (ch->ch_state == CS_READY &&
-			    (otype != OTYPE_INCOMING ||
-			    ch->ch_flag & CH_VIRT_CD))
-				break;
-
-			wait_carrier = 1;
-		}
-
-		/*
-		 *  Handle port active with a different category device.
-		 */
-
-		else {
-			if (otype == OTYPE_IMMEDIATE) {
-				retval = delay_error;
-				goto unlock;
-			}
-		}
-
-		/*
-		 * Wait until conditions change, then take another
-		 * try at the open.
-		 */
-
-		ch->ch_wait_count[otype]++;
-
-		if (wait_carrier)
-			ch->ch_wait_carrier++;
-
-		/*
-		 * Prepare the task to accept the wakeup, then
-		 * release our locks and release control.
-		 */
-
-		add_wait_queue(&ch->ch_flag_wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-
-		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-
-		/*
-		 * Give up control, we'll come back if we're
-		 * interrupted or are woken up.
-		 */
-		schedule();
-		remove_wait_queue(&ch->ch_flag_wait, &wait);
-
-		spin_lock_irqsave(&nd->nd_lock, lock_flags);
-
-		current->state = TASK_RUNNING;
-
-		ch->ch_wait_count[otype]--;
-
-		if (wait_carrier)
-			ch->ch_wait_carrier--;
-
-		nd->nd_tx_work = 1;
-
-		if (signal_pending(current)) {
-			retval = -EINTR;
-			goto unlock;
-		}
-	} /* end for(;;) */
-
-	/*
-	 *  The open has succeeded.  No turning back.
-	 */
-	counts_were_incremented = 1;
-	un->un_open_count++;
-	ch->ch_open_count++;
-
-	/*
-	 * Initialize the channel, if it's not already open.
-	 */
-
-	if (ch->ch_open_count == 1) {
-		ch->ch_flag = 0;
-		ch->ch_inwait = 0;
-		ch->ch_category = category;
-		ch->ch_pscan_state = 0;
-
-		/* TODO : find out what PS-1 bug Gene was referring to */
-		/* TODO : in the following comment. */
-
-		ch->ch_send = RR_TX_START | RR_RX_START;  /* PS-1 bug */
-
-		if (C_CLOCAL(tty) ||
-		    ch->ch_s_mlast & DM_CD ||
-		    ch->ch_digi.digi_flags & DIGI_FORCEDCD)
-			ch->ch_flag |= CH_VIRT_CD;
-		else if (OPEN_FORCES_CARRIER(category))
-			ch->ch_flag |= CH_VIRT_CD;
-
-	}
-
-	/*
-	 *  Initialize the unit, if it is not already open.
-	 */
-
-	if (un->un_open_count == 1) {
-		/*
-		 *  Since all terminal options are always sticky in Linux,
-		 *  we don't need the UN_STICKY flag to be handled specially.
-		 */
-		/* clears all the digi flags, leaves serial flags */
-		un->un_flag &= ~UN_DIGI_MASK;
-
-		if (file->f_flags & O_EXCL)
-			un->un_flag |= UN_EXCL;
-
-		/* TODO : include "session" and "pgrp" */
-
-		/*
-		 *  In Linux, all terminal parameters are intended to be sticky.
-		 *  as a result, we "remove" the code which once reset the ports
-		 *  to sane values.
-		 */
-
-		drp_param(ch);
-
-	}
-
-	un->un_flag |= UN_INITIALIZED;
-
-	retval = 0;
-
-unlock:
-
-	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-
-done:
-	/*
-	 * Linux does a close for every open, even failed ones!
-	 */
-	if (!counts_were_incremented) {
-		un->un_open_count++;
-		ch->ch_open_count++;
-	}
-
-	if (retval)
-		dev_err(tty->dev, "tty open bad return (%i)\n", retval);
-
-	return retval;
-}
-
-
-
-
-/*
- * dgrp_tty_close() -- close function for tty_operations
- */
-static void dgrp_tty_close(struct tty_struct *tty, struct file *file)
-{
-	struct ch_struct *ch;
-	struct un_struct *un;
-	struct nd_struct *nd;
-	int	tpos;
-	int	port;
-	int	err = 0;
-	int	s = 0;
-	ulong  waketime;
-	ulong  lock_flags;
-	int sent_printer_offstr = 0;
-
-	port = PORT_NUM(MINOR(tty_devnum(tty)));
-
-	un = tty->driver_data;
-
-	if (!un)
-		return;
-
-	ch = un->un_ch;
-
-	if (!ch)
-		return;
-
-	nd = ch->ch_nd;
-
-	if (!nd)
-		return;
-
-	spin_lock_irqsave(&nd->nd_lock, lock_flags);
-
-
-	/* Used to be on channel basis, now we check on a unit basis. */
-	if (un->un_open_count != 1)
-		goto unlock;
-
-	/*
-	 * OK, its the last close on the unit
-	 */
-	un->un_flag |= UN_CLOSING;
-
-	/*
-	 * Notify the discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-
-	/*
-	 * Wait for output to drain only if this is
-	 * the last close against the channel
-	 */
-
-	if (ch->ch_open_count == 1) {
-		/*
-		 * If its the print device, we need to ensure at all costs that
-		 * the offstr will fit. If it won't, flush our tbuf.
-		 */
-		if (IS_PRINT(MINOR(tty_devnum(tty))) &&
-		    (((ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK) <
-		    ch->ch_digi.digi_offlen))
-			ch->ch_tin = ch->ch_tout;
-
-		/*
-		 * Turn off the printer.  Don't bother checking to see if its
-		 * IS_PRINT... Since this is the last close the flag is going
-		 * to be cleared, so we MUST make sure the offstr gets inserted
-		 * into tbuf.
-		 */
-
-		if ((ch->ch_flag & CH_PRON) != 0) {
-			drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
-				  ch->ch_digi.digi_offlen);
-			ch->ch_flag &= ~CH_PRON;
-			sent_printer_offstr = 1;
-		}
-	}
-
-	/*
-	 *  Wait until either the output queue has drained, or we see
-	 *  absolutely no progress for 15 seconds.
-	 */
-
-	tpos = ch->ch_s_tpos;
-
-	waketime = jiffies + 15 * HZ;
-
-	for (;;) {
-
-		/*
-		 *  Make sure the port still exists.
-		 */
-
-		if (port >= nd->nd_chan_count) {
-			err = 1;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			err = 1;
-			break;
-		}
-
-		/*
-		 * If the port is idle (not opened on the server), we have
-		 * no way of draining/flushing/closing the port on that server.
-		 * So break out of loop.
-		 */
-		if (ch->ch_state == CS_IDLE)
-			break;
-
-		nd->nd_tx_work = 1;
-
-		/*
-		 *  Exit if the queues for this unit are empty,
-		 *  and either the other unit is still open or all
-		 *  data has drained.
-		 */
-
-		if ((un->un_tty)->ops->chars_in_buffer ?
-		    ((un->un_tty)->ops->chars_in_buffer)(un->un_tty) == 0 : 1) {
-
-			/*
-			 * We don't need to wait for a buffer to drain
-			 * if the other unit is open.
-			 */
-
-			if (ch->ch_open_count != un->un_open_count)
-				break;
-
-			/*
-			 *  The wait is complete when all queues are
-			 *  drained, and any break in progress is complete.
-			 */
-
-			if (ch->ch_tin == ch->ch_tout &&
-			    ch->ch_s_tin == ch->ch_s_tpos &&
-			    (ch->ch_send & RR_TX_BREAK) == 0) {
-				break;
-			}
-		}
-
-		/*
-		 * Flush TX data and exit the wait if NDELAY is set,
-		 * or this is not a DIGI printer, and the close timeout
-		 * expires.
-		 */
-
-		if ((file->f_flags & (O_NDELAY | O_NONBLOCK)) ||
-		    ((long)(jiffies - waketime) >= 0 &&
-		      (ch->ch_digi.digi_flags & DIGI_PRINTER) == 0)) {
-
-				/*
-				 * If we sent the printer off string, we cannot
-				 * flush our internal buffers, or we might lose
-				 * the offstr.
-				 */
-				if (!sent_printer_offstr)
-					dgrp_tty_flush_buffer(tty);
-
-				spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-				tty_ldisc_flush(tty);
-				spin_lock_irqsave(&nd->nd_lock, lock_flags);
-				break;
-		}
-
-		/*
-		 *  Otherwise take a short nap.
-		 */
-
-		ch->ch_flag |= CH_DRAIN;
-
-		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-
-		schedule_timeout_interruptible(1);
-		s = signal_pending(current);
-
-		spin_lock_irqsave(&nd->nd_lock, lock_flags);
-
-		if (s) {
-			/*
-			 * If we had sent the printer off string, we now have
-			 * some problems.
-			 *
-			 * The system won't let us sleep since we got an error
-			 * back from sleep, presumably because the user did
-			 * a ctrl-c...
-			 * But we need to ensure that the offstr gets sent!
-			 * Thus, we have to do something else besides sleeping.
-			 * The plan:
-			 * 1) Make this task uninterruptable.
-			 * 2) Set up a timer to go off in 1 sec.
-			 * 3) Act as tho we just got out of the sleep above.
-			 *
-			 * Thankfully, in the real world, this just
-			 * never happens.
-			 */
-
-			if (sent_printer_offstr) {
-				spin_unlock_irqrestore(&nd->nd_lock,
-						       lock_flags);
-				drp_my_sleep(ch);
-				spin_lock_irqsave(&nd->nd_lock, lock_flags);
-			} else {
-				err = 1;
-				break;
-			}
-		}
-
-		/*
-		 *  Restart the wait if any progress is seen.
-		 */
-
-		if (ch->ch_s_tpos != tpos) {
-			tpos = ch->ch_s_tpos;
-
-			/* TODO:  this gives us timeout problems with nist ?? */
-			waketime = jiffies + 15 * HZ;
-		}
-	}
-
-	/*
-	 *  Close the line discipline
-	 */
-
-	/* this is done in tty_io.c */
-	/* if ((un->un_tty)->ldisc.close)
-	 *	((un->un_tty)->ldisc.close)(un->un_tty);
-	 */
-
-	/* don't do this here */
-	/* un->un_flag = 0; */
-
-	/*
-	 *  Flush the receive buffer on terminal unit close only.
-	 */
-
-	if (!IS_PRINT(MINOR(tty_devnum(tty))))
-		ch->ch_rout = ch->ch_rin;
-
-
-	/*
-	 * Don't permit the close to happen until we get any pending
-	 * sync request responses.
-	 * There could be other ports depending upon the response as well.
-	 *
-	 * Also, don't permit the close to happen until any parameter
-	 * changes have been sent out from the state machine as well.
-	 * This is required because of a ditty -a race with -HUPCL
-	 * We MUST make sure all channel parameters have been sent to the
-	 * Portserver before sending a close.
-	 */
-
-	if ((err != 1) && (ch->ch_state != CS_IDLE)) {
-		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-		s = wait_event_interruptible(ch->ch_flag_wait,
-			((ch->ch_flag & (CH_WAITING_SYNC | CH_PARAM)) == 0));
-		spin_lock_irqsave(&nd->nd_lock, lock_flags);
-	}
-
-	/*
-	 * Cleanup the channel if last unit open.
-	 */
-
-	if (ch->ch_open_count == 1) {
-		ch->ch_flag = 0;
-		ch->ch_category = 0;
-		ch->ch_send = 0;
-		ch->ch_expect = 0;
-		ch->ch_tout = ch->ch_tin;
-		/* (un->un_tty)->device = 0; */
-
-		if (ch->ch_state == CS_READY)
-			ch->ch_state = CS_SEND_CLOSE;
-	}
-
-	/*
-	 * Send the changes to the server
-	 */
-	if (ch->ch_state != CS_IDLE) {
-		ch->ch_flag |= CH_PARAM;
-		wake_up_interruptible(&ch->ch_flag_wait);
-	}
-
-	nd->nd_tx_work = 1;
-	nd->nd_tx_ready = 1;
-
-unlock:
-	tty->closing = 0;
-
-	if (ch->ch_open_count <= 0)
-		dev_info(tty->dev,
-			 "%s - unexpected value for ch->ch_open_count: %i\n",
-			 __func__, ch->ch_open_count);
-	else
-		ch->ch_open_count--;
-
-	if (un->un_open_count <= 0)
-		dev_info(tty->dev,
-			 "%s - unexpected value for un->un_open_count: %i\n",
-			 __func__, un->un_open_count);
-	else
-		un->un_open_count--;
-
-	un->un_flag &= ~(UN_NORMAL_ACTIVE | UN_CALLOUT_ACTIVE | UN_CLOSING);
-	if (waitqueue_active(&un->un_close_wait))
-		wake_up_interruptible(&un->un_close_wait);
-
-	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-
-	return;
-
-}
-
-static void drp_wmove(struct ch_struct *ch, int from_user, void *buf, int count)
-{
-	int n;
-	int ret = 0;
-
-	ch->ch_nd->nd_tx_work = 1;
-
-	n = TBUF_MAX - ch->ch_tin;
-
-	if (count >= n) {
-		if (from_user)
-			ret = copy_from_user(ch->ch_tbuf + ch->ch_tin,
-					     (void __user *) buf, n);
-		else
-			memcpy(ch->ch_tbuf + ch->ch_tin, buf, n);
-
-		buf = (char *) buf + n;
-		count -= n;
-		ch->ch_tin = 0;
-	}
-
-	if (from_user)
-		ret = copy_from_user(ch->ch_tbuf + ch->ch_tin,
-				     (void __user *) buf, count);
-	else
-		memcpy(ch->ch_tbuf + ch->ch_tin, buf, count);
-
-	ch->ch_tin += count;
-}
-
-
-static int dgrp_calculate_txprint_bounds(struct ch_struct *ch, int space,
-					 int *un_flag)
-{
-	clock_t tt;
-	clock_t mt;
-	unsigned short tmax = 0;
-
-	/*
-	 * If the terminal device is busy, reschedule when
-	 * the terminal device becomes idle.
-	 */
-
-	if (ch->ch_tun.un_open_count != 0 &&
-	    ch->ch_tun.un_tty->ops->chars_in_buffer &&
-	    ((ch->ch_tun.un_tty->ops->chars_in_buffer)
-	     (ch->ch_tun.un_tty) != 0)) {
-		*un_flag = UN_PWAIT;
-		return 0;
-	}
-
-	/*
-	 * Assure that whenever there is printer data in the output
-	 * buffer, there always remains enough space after it to
-	 * turn the printer off.
-	 */
-	space -= ch->ch_digi.digi_offlen;
-
-	if (space <= 0) {
-		*un_flag = UN_EMPTY;
-		return 0;
-	}
-
-	/*
-	 * We measure printer CPS speed by incrementing
-	 * ch_cpstime by (HZ / digi_maxcps) for every
-	 * character we output, restricting output so
-	 * that ch_cpstime never exceeds lbolt.
-	 *
-	 * However if output has not been done for some
-	 * time, lbolt will grow to very much larger than
-	 * ch_cpstime, which would allow essentially
-	 * unlimited amounts of output until ch_cpstime
-	 * finally caught up.   To avoid this, we adjust
-	 * cps_time when necessary so the difference
-	 * between lbolt and ch_cpstime never results
-	 * in sending more than digi_bufsize characters.
-	 *
-	 * This nicely models a printer with an internal
-	 * buffer of digi_bufsize characters.
-	 *
-	 * Get the time between lbolt and ch->ch_cpstime;
-	 */
-
-	tt = jiffies - ch->ch_cpstime;
-
-	/*
-	 * Compute the time required to send digi_bufsize
-	 * characters.
-	 */
-
-	mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps;
-
-	/*
-	 * Compute the number of characters that can be sent
-	 * without violating the time constraint.   If the
-	 * direct calculation of this number is bigger than
-	 * digi_bufsize, limit the number to digi_bufsize,
-	 * and adjust cpstime to match.
-	 */
-
-	if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) {
-		tmax = ch->ch_digi.digi_bufsize;
-		ch->ch_cpstime = jiffies - mt;
-	} else {
-		tmax = ch->ch_digi.digi_maxcps * tt / HZ;
-	}
-
-	/*
-	 * If the time constraint now binds, limit the transmit
-	 * count accordingly, and tentatively arrange to be
-	 * rescheduled based on time.
-	 */
-
-	if (tmax < space) {
-		*un_flag = UN_TIME;
-		space = tmax;
-	}
-
-	/*
-	 * Compute the total number of characters we can
-	 * output before the total number of characters known
-	 * to be in the output queue exceeds digi_maxchar.
-	 */
-
-	tmax = (ch->ch_digi.digi_maxchar -
-		((ch->ch_tin - ch->ch_tout) & TBUF_MASK) -
-		((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff));
-
-
-	/*
-	 * If the digi_maxchar constraint now holds, limit
-	 * the transmit count accordingly, and arrange to
-	 * be rescheduled when the queue becomes empty.
-	 */
-
-	if (space > tmax) {
-		*un_flag = UN_EMPTY;
-		space = tmax;
-	}
-
-	if (space <= 0)
-		*un_flag |= UN_EMPTY;
-
-	return space;
-}
-
-
-static int dgrp_tty_write(struct tty_struct *tty,
-			  const unsigned char *buf,
-			  int count)
-{
-	struct nd_struct *nd;
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int	space;
-	int	n;
-	int	t;
-	int sendcount;
-	int un_flag;
-	ulong lock_flags;
-
-	if (tty == NULL)
-		return 0;
-
-	un = tty->driver_data;
-	if (!un)
-		return 0;
-
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-
-	nd = ch->ch_nd;
-	if (!nd)
-		return 0;
-
-	/*
-	 * Ignore the request if the channel is not ready.
-	 */
-	if (ch->ch_state != CS_READY)
-		return 0;
-
-	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
-
-	/*
-	 * Ignore the request if output is blocked.
-	 */
-	if ((un->un_flag & (UN_EMPTY | UN_LOW | UN_TIME | UN_PWAIT)) != 0) {
-		count = 0;
-		goto out;
-	}
-
-	/*
-	 * Also ignore the request if DPA has this port open,
-	 * and is flow controlled on reading more data.
-	 */
-	if (nd->nd_dpa_debug && nd->nd_dpa_flag & DPA_WAIT_SPACE &&
-		nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty))) {
-		count = 0;
-		goto out;
-	}
-
-	/*
-	 *	Limit amount we will write to the amount of space
-	 *	available in the channel buffer.
-	 */
-	sendcount = 0;
-
-	space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
-
-	/*
-	 * Handle the printer device.
-	 */
-
-	un_flag = UN_LOW;
-
-	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
-		clock_t tt;
-		clock_t mt;
-		unsigned short tmax = 0;
-
-		/*
-		 * If the terminal device is busy, reschedule when
-		 * the terminal device becomes idle.
-		 */
-
-		if (ch->ch_tun.un_open_count != 0 &&
-		    ((ch->ch_tun.un_tty->ops->chars_in_buffer)
-		     (ch->ch_tun.un_tty) != 0)) {
-			un->un_flag |= UN_PWAIT;
-			count = 0;
-			goto out;
-		}
-
-		/*
-		 * Assure that whenever there is printer data in the output
-		 * buffer, there always remains enough space after it to
-		 * turn the printer off.
-		 */
-		space -= ch->ch_digi.digi_offlen;
-
-		/*
-		 * Output the printer on string.
-		 */
-
-		if ((ch->ch_flag & CH_PRON) == 0) {
-			space -= ch->ch_digi.digi_onlen;
-
-			if (space < 0) {
-				un->un_flag |= UN_EMPTY;
-				(ch->ch_nd)->nd_tx_work = 1;
-				count = 0;
-				goto out;
-			}
-
-			drp_wmove(ch, 0, ch->ch_digi.digi_onstr,
-				ch->ch_digi.digi_onlen);
-
-			ch->ch_flag |= CH_PRON;
-		}
-
-		/*
-		 * We measure printer CPS speed by incrementing
-		 * ch_cpstime by (HZ / digi_maxcps) for every
-		 * character we output, restricting output so
-		 * that ch_cpstime never exceeds lbolt.
-		 *
-		 * However if output has not been done for some
-		 * time, lbolt will grow to very much larger than
-		 * ch_cpstime, which would allow essentially
-		 * unlimited amounts of output until ch_cpstime
-		 * finally caught up.   To avoid this, we adjust
-		 * cps_time when necessary so the difference
-		 * between lbolt and ch_cpstime never results
-		 * in sending more than digi_bufsize characters.
-		 *
-		 * This nicely models a printer with an internal
-		 * buffer of digi_bufsize characters.
-		 *
-		 * Get the time between lbolt and ch->ch_cpstime;
-		 */
-
-		tt = jiffies - ch->ch_cpstime;
-
-		/*
-		 * Compute the time required to send digi_bufsize
-		 * characters.
-		 */
-
-		mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps;
-
-		/*
-		 * Compute the number of characters that can be sent
-		 * without violating the time constraint.   If the
-		 * direct calculation of this number is bigger than
-		 * digi_bufsize, limit the number to digi_bufsize,
-		 * and adjust cpstime to match.
-		 */
-
-		if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) {
-			tmax = ch->ch_digi.digi_bufsize;
-			ch->ch_cpstime = jiffies - mt;
-		} else {
-			tmax = ch->ch_digi.digi_maxcps * tt / HZ;
-		}
-
-		/*
-		 * If the time constraint now binds, limit the transmit
-		 * count accordingly, and tentatively arrange to be
-		 * rescheduled based on time.
-		 */
-
-		if (tmax < space) {
-			space = tmax;
-			un_flag = UN_TIME;
-		}
-
-		/*
-		 * Compute the total number of characters we can
-		 * output before the total number of characters known
-		 * to be in the output queue exceeds digi_maxchar.
-		 */
-
-		tmax = (ch->ch_digi.digi_maxchar -
-			((ch->ch_tin - ch->ch_tout) & TBUF_MASK) -
-			((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff));
-
-
-		/*
-		 * If the digi_maxchar constraint now holds, limit
-		 * the transmit count accordingly, and arrange to
-		 * be rescheduled when the queue becomes empty.
-		 */
-
-		if (space > tmax) {
-			space = tmax;
-			un_flag = UN_EMPTY;
-		}
-
-	}
-	/*
-	 * Handle the terminal device.
-	 */
-	else {
-
-		/*
-		 * If the printer device is on, turn it off.
-		 */
-
-		if ((ch->ch_flag & CH_PRON) != 0) {
-
-			space -= ch->ch_digi.digi_offlen;
-
-			drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
-				  ch->ch_digi.digi_offlen);
-
-			ch->ch_flag &= ~CH_PRON;
-		}
-	}
-
-	/*
-	 *	If space is 0 and its because the ch->tbuf
-	 *	is full, then Linux will handle a callback when queue
-	 *	space becomes available.
-	 *	tty_write returns count = 0
-	 */
-
-	if (space <= 0) {
-		/* the linux tty_io.c handles this if we return 0 */
-		/* if (fp->flags & O_NONBLOCK) return -EAGAIN; */
-
-		un->un_flag |= UN_EMPTY;
-		(ch->ch_nd)->nd_tx_work = 1;
-		count = 0;
-		goto out;
-	}
-
-	count = min(count, space);
-
-	if (count > 0) {
-
-		un->un_tbusy++;
-
-		/*
-		 *	Copy the buffer contents to the ch_tbuf
-		 *	being careful to wrap around the circular queue
-		 */
-
-		t = TBUF_MAX - ch->ch_tin;
-		n = count;
-
-		if (n >= t) {
-			memcpy(ch->ch_tbuf + ch->ch_tin, buf, t);
-			if (nd->nd_dpa_debug && nd->nd_dpa_port ==
-				PORT_NUM(MINOR(tty_devnum(un->un_tty))))
-				dgrp_dpa_data(nd, 0, (char *) buf, t);
-			buf += t;
-			n -= t;
-			ch->ch_tin = 0;
-			sendcount += n;
-		}
-
-		memcpy(ch->ch_tbuf + ch->ch_tin, buf, n);
-		if (nd->nd_dpa_debug && nd->nd_dpa_port ==
-			PORT_NUM(MINOR(tty_devnum(un->un_tty))))
-			dgrp_dpa_data(nd, 0, (char *) buf, n);
-		buf += n;
-		ch->ch_tin += n;
-		sendcount += n;
-
-		un->un_tbusy--;
-		(ch->ch_nd)->nd_tx_work = 1;
-		if (ch->ch_edelay != DGRP_RTIME) {
-			(ch->ch_nd)->nd_tx_ready = 1;
-			wake_up_interruptible(&nd->nd_tx_waitq);
-		}
-	}
-
-	ch->ch_txcount += count;
-
-	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
-
-		/*
-		 * Adjust ch_cpstime to account
-		 * for the characters just output.
-		 */
-
-		if (sendcount > 0) {
-			int cc = HZ * sendcount + ch->ch_cpsrem;
-
-			ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps;
-			ch->ch_cpsrem   = cc % ch->ch_digi.digi_maxcps;
-		}
-
-		/*
-		 * If we are now waiting on time, schedule ourself
-		 * back when we'll be able to send a block of
-		 * digi_maxchar characters.
-		 */
-
-		if ((un_flag & UN_TIME) != 0) {
-			ch->ch_waketime = (ch->ch_cpstime +
-				(ch->ch_digi.digi_maxchar * HZ /
-				ch->ch_digi.digi_maxcps));
-		}
-	}
-
-	/*
-	 * If the printer unit is waiting for completion
-	 * of terminal output, get him going again.
-	 */
-
-	if ((ch->ch_pun.un_flag & UN_PWAIT) != 0)
-		(ch->ch_nd)->nd_tx_work = 1;
-
-out:
-	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
-
-	return count;
-}
-
-
-/*
- *	Put a character into ch->ch_buf
- *
- *	- used by the line discipline for OPOST processing
- */
-
-static int dgrp_tty_put_char(struct tty_struct *tty, unsigned char new_char)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	ulong  lock_flags;
-	int space;
-	int retval = 0;
-
-	if (tty == NULL)
-		return 0;
-
-	un = tty->driver_data;
-	if (!un)
-		return 0;
-
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-
-	if (ch->ch_state != CS_READY)
-		return 0;
-
-	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
-
-
-	/*
-	 *	If space is 0 and its because the ch->tbuf
-	 *	Warn and dump the character, there isn't anything else
-	 *	we can do about it.  David_Fries@digi.com
-	 */
-
-	space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
-
-	un->un_tbusy++;
-
-	/*
-	 * Output the printer on string if device is TXPrint.
-	 */
-	if (IS_PRINT(MINOR(tty_devnum(tty))) && (ch->ch_flag & CH_PRON) == 0) {
-		if (space < ch->ch_digi.digi_onlen) {
-			un->un_tbusy--;
-			goto out;
-		}
-		space -= ch->ch_digi.digi_onlen;
-		drp_wmove(ch, 0, ch->ch_digi.digi_onstr,
-			  ch->ch_digi.digi_onlen);
-		ch->ch_flag |= CH_PRON;
-	}
-
-	/*
-	 * Output the printer off string if device is NOT TXPrint.
-	 */
-
-	if (!IS_PRINT(MINOR(tty_devnum(tty))) &&
-	    ((ch->ch_flag & CH_PRON) != 0)) {
-		if (space < ch->ch_digi.digi_offlen) {
-			un->un_tbusy--;
-			goto out;
-		}
-
-		space -= ch->ch_digi.digi_offlen;
-		drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
-			  ch->ch_digi.digi_offlen);
-		ch->ch_flag &= ~CH_PRON;
-	}
-
-	if (!space) {
-		un->un_tbusy--;
-		goto out;
-	}
-
-	/*
-	 *	Copy the character to the ch_tbuf being
-	 *	careful to wrap around the circular queue
-	 */
-	ch->ch_tbuf[ch->ch_tin] = new_char;
-	ch->ch_tin = (1 + ch->ch_tin) & TBUF_MASK;
-
-	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
-
-		/*
-		 * Adjust ch_cpstime to account
-		 * for the character just output.
-		 */
-
-		int cc = HZ + ch->ch_cpsrem;
-
-		ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps;
-		ch->ch_cpsrem   = cc % ch->ch_digi.digi_maxcps;
-
-		/*
-		 * If we are now waiting on time, schedule ourself
-		 * back when we'll be able to send a block of
-		 * digi_maxchar characters.
-		 */
-
-		ch->ch_waketime = (ch->ch_cpstime +
-			(ch->ch_digi.digi_maxchar * HZ /
-			ch->ch_digi.digi_maxcps));
-	}
-
-
-	un->un_tbusy--;
-	(ch->ch_nd)->nd_tx_work = 1;
-
-	retval = 1;
-out:
-	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
-	return retval;
-}
-
-
-
-/*
- *	Flush TX buffer (make in == out)
- *
- *	check tty_ioctl.c  -- this is called after TCOFLUSH
- */
-static void dgrp_tty_flush_buffer(struct tty_struct *tty)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-	un = tty->driver_data;
-	if (!un)
-		return;
-
-	ch = un->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_tout = ch->ch_tin;
-	/* do NOT do this here! */
-	/* ch->ch_s_tpos = ch->ch_s_tin = 0; */
-
-	/* send the flush output command now */
-	ch->ch_send |= RR_TX_FLUSH;
-	(ch->ch_nd)->nd_tx_ready = 1;
-	(ch->ch_nd)->nd_tx_work = 1;
-	wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-
-	if (waitqueue_active(&tty->write_wait))
-		wake_up_interruptible(&tty->write_wait);
-
-	tty_wakeup(tty);
-
-}
-
-/*
- *	Return space available in Tx buffer
- *	count = ( ch->ch_tout - ch->ch_tin ) mod (TBUF_MAX - 1)
- */
-static int dgrp_tty_write_room(struct tty_struct *tty)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int	count;
-
-	if (!tty)
-		return 0;
-
-	un = tty->driver_data;
-	if (!un)
-		return 0;
-
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-
-	count = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
-
-	/* We *MUST* check this, and return 0 if the Printer Unit cannot
-	 * take any more data within its time constraints...  If we don't
-	 * return 0 and the printer has hit it time constraint, the ld will
-	 * call us back doing a put_char, which cannot be rejected!!!
-	 */
-	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
-		int un_flag = 0;
-		count = dgrp_calculate_txprint_bounds(ch, count, &un_flag);
-		if (count <= 0)
-			count = 0;
-
-		ch->ch_pun.un_flag |= un_flag;
-		(ch->ch_nd)->nd_tx_work = 1;
-	}
-
-	return count;
-}
-
-/*
- *	Return number of characters that have not been transmitted yet.
- *	chars_in_buffer = ( ch->ch_tin - ch->ch_tout ) mod (TBUF_MAX - 1)
- *			+ ( ch->ch_s_tin - ch->ch_s_tout ) mod (0xffff)
- *			= number of characters "in transit"
- *
- * Remember that sequence number math is always with a sixteen bit
- * mask, not the TBUF_MASK.
- */
-
-static int dgrp_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int	count;
-	int	count1;
-
-	if (!tty)
-		return 0;
-
-	un = tty->driver_data;
-	if (!un)
-		return 0;
-
-	ch = un->un_ch;
-	if (!ch)
-		return 0;
-
-	count1 = count = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
-	count += (ch->ch_s_tin - ch->ch_s_tpos) & 0xffff;
-	/* one for tbuf, one for the PS */
-
-	/*
-	 * If we are busy transmitting add 1
-	 */
-	count += un->un_tbusy;
-
-	return count;
-}
-
-
-/*****************************************************************************
- *
- * Helper applications for dgrp_tty_ioctl()
- *
- *****************************************************************************
- */
-
-
-/**
- * ch_to_tty_flags() -- convert channel flags to termio flags
- * @ch_flag: Digi channel flags
- * @flagtype: type of ch_flag (iflag, oflag or cflag)
- *
- * take the channel flags of the specified type and return the
- * corresponding termio flag
- */
-static tcflag_t ch_to_tty_flags(ushort ch_flag, char flagtype)
-{
-	tcflag_t retval = 0;
-
-	switch (flagtype) {
-	case 'i':
-		retval = ((ch_flag & IF_IGNBRK) ? IGNBRK : 0)
-		     | ((ch_flag & IF_BRKINT) ? BRKINT : 0)
-		     | ((ch_flag & IF_IGNPAR) ? IGNPAR : 0)
-		     | ((ch_flag & IF_PARMRK) ? PARMRK : 0)
-		     | ((ch_flag & IF_INPCK) ? INPCK  : 0)
-		     | ((ch_flag & IF_ISTRIP) ? ISTRIP : 0)
-		     | ((ch_flag & IF_IXON) ? IXON   : 0)
-		     | ((ch_flag & IF_IXANY) ? IXANY  : 0)
-		     | ((ch_flag & IF_IXOFF) ? IXOFF  : 0);
-		break;
-
-	case 'o':
-		retval = ((ch_flag & OF_OLCUC) ? OLCUC : 0)
-		     | ((ch_flag & OF_ONLCR) ? ONLCR  : 0)
-		     | ((ch_flag & OF_OCRNL) ? OCRNL  : 0)
-		     | ((ch_flag & OF_ONOCR) ? ONOCR  : 0)
-		     | ((ch_flag & OF_ONLRET) ? ONLRET : 0)
-		  /* | ((ch_flag & OF_OTAB3) ? OFILL  : 0) */
-		     | ((ch_flag & OF_TABDLY) ? TABDLY : 0);
-		break;
-
-	case 'c':
-		retval = ((ch_flag & CF_CSTOPB) ? CSTOPB : 0)
-		     | ((ch_flag & CF_CREAD) ? CREAD  : 0)
-		     | ((ch_flag & CF_PARENB) ? PARENB : 0)
-		     | ((ch_flag & CF_PARODD) ? PARODD : 0)
-		     | ((ch_flag & CF_HUPCL) ? HUPCL  : 0);
-
-		switch (ch_flag & CF_CSIZE) {
-		case CF_CS5:
-			retval |= CS5;
-			break;
-		case CF_CS6:
-			retval |= CS6;
-			break;
-		case CF_CS7:
-			retval |= CS7;
-			break;
-		case CF_CS8:
-			retval |= CS8;
-			break;
-		default:
-			retval |= CS8;
-			break;
-		}
-		break;
-	case 'x':
-		break;
-	case 'l':
-		break;
-	default:
-		return 0;
-	}
-
-	return retval;
-}
-
-
-/**
- * tty_to_ch_flags() -- convert termio flags to digi channel flags
- * @tty: pointer to a TTY structure holding flag to be converted
- * @flagtype: identifies which flag (iflags, oflags, or cflags) should
- *                 be converted
- *
- * take the termio flag of the specified type and return the
- * corresponding Digi version of the flags
- */
-static ushort tty_to_ch_flags(struct tty_struct *tty, char flagtype)
-{
-	ushort retval = 0;
-	tcflag_t tflag = 0;
-
-	switch (flagtype) {
-	case 'i':
-		tflag  = tty->termios.c_iflag;
-		retval = (I_IGNBRK(tty) ? IF_IGNBRK : 0)
-		      | (I_BRKINT(tty) ? IF_BRKINT : 0)
-		      | (I_IGNPAR(tty) ? IF_IGNPAR : 0)
-		      | (I_PARMRK(tty) ? IF_PARMRK : 0)
-		      | (I_INPCK(tty)  ? IF_INPCK  : 0)
-		      | (I_ISTRIP(tty) ? IF_ISTRIP : 0)
-		      | (I_IXON(tty)   ? IF_IXON   : 0)
-		      | (I_IXANY(tty)  ? IF_IXANY  : 0)
-		      | (I_IXOFF(tty)  ? IF_IXOFF  : 0);
-		break;
-	case 'o':
-		tflag  = tty->termios.c_oflag;
-		/*
-		 * If OPOST is set, then do the post processing in the
-		 * firmware by setting all the processing flags on.
-		 * If ~OPOST, then make sure we are not doing any
-		 * output processing!!
-		 */
-		if (!O_OPOST(tty))
-			retval = 0;
-		else
-			retval = (O_OLCUC(tty) ? OF_OLCUC : 0)
-			     | (O_ONLCR(tty)  ? OF_ONLCR  : 0)
-			     | (O_OCRNL(tty)  ? OF_OCRNL  : 0)
-			     | (O_ONOCR(tty)  ? OF_ONOCR  : 0)
-			     | (O_ONLRET(tty) ? OF_ONLRET : 0)
-			  /* | (O_OFILL(tty)  ? OF_TAB3   : 0) */
-			     | (O_TABDLY(tty) ? OF_TABDLY : 0);
-		break;
-	case 'c':
-		tflag  = tty->termios.c_cflag;
-		retval = (C_CSTOPB(tty) ? CF_CSTOPB : 0)
-		     | (C_CREAD(tty)  ? CF_CREAD  : 0)
-		     | (C_PARENB(tty) ? CF_PARENB : 0)
-		     | (C_PARODD(tty) ? CF_PARODD : 0)
-		     | (C_HUPCL(tty)  ? CF_HUPCL  : 0);
-		switch (C_CSIZE(tty)) {
-		case CS8:
-			retval |= CF_CS8;
-			break;
-		case CS7:
-			retval |= CF_CS7;
-			break;
-		case CS6:
-			retval |= CF_CS6;
-			break;
-		case CS5:
-			retval |= CF_CS5;
-			break;
-		default:
-			retval |= CF_CS8;
-			break;
-		}
-		break;
-	case 'x':
-		break;
-	case 'l':
-		break;
-	default:
-		return 0;
-	}
-
-	return retval;
-}
-
-
-static int dgrp_tty_send_break(struct tty_struct *tty, int msec)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int ret = -EIO;
-
-	if (!tty)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch)
-		return ret;
-
-	dgrp_send_break(ch, msec);
-	return 0;
-}
-
-
-/*
- * This routine sends a break character out the serial port.
- *
- * duration is in 1/1000's of a second
- */
-static int dgrp_send_break(struct ch_struct *ch, int msec)
-{
-	ulong x;
-
-	wait_event_interruptible(ch->ch_flag_wait,
-		((ch->ch_flag & CH_TX_BREAK) == 0));
-	ch->ch_break_time += max(msec, 250);
-	ch->ch_send |= RR_TX_BREAK;
-	ch->ch_flag |= CH_TX_BREAK;
-	(ch->ch_nd)->nd_tx_work = 1;
-
-	x = (msec * HZ) / 1000;
-	wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-
-	return 0;
-}
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgrp_tty_tiocmget(struct tty_struct *tty)
-{
-	unsigned int mlast;
-	struct un_struct *un = tty->driver_data;
-	struct ch_struct *ch;
-
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) |
-		(ch->ch_mout & (DM_RTS | DM_DTR)));
-
-	/* defined in /usr/include/asm/termios.h */
-	mlast =   ((mlast & DM_RTS) ? TIOCM_RTS : 0)
-		| ((mlast & DM_DTR) ? TIOCM_DTR : 0)
-		| ((mlast & DM_CD)  ? TIOCM_CAR : 0)
-		| ((mlast & DM_RI)  ? TIOCM_RNG : 0)
-		| ((mlast & DM_DSR) ? TIOCM_DSR : 0)
-		| ((mlast & DM_CTS) ? TIOCM_CTS : 0);
-
-	return mlast;
-}
-
-
-/*
- *      Set modem lines
- */
-static int dgrp_tty_tiocmset(struct tty_struct *tty,
-			     unsigned int set, unsigned int clear)
-{
-	ulong lock_flags;
-	struct un_struct *un = tty->driver_data;
-	struct ch_struct *ch;
-
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	if (set & TIOCM_RTS)
-		ch->ch_mout |= DM_RTS;
-
-	if (set & TIOCM_DTR)
-		ch->ch_mout |= DM_DTR;
-
-	if (clear & TIOCM_RTS)
-		ch->ch_mout &= ~(DM_RTS);
-
-	if (clear & TIOCM_DTR)
-		ch->ch_mout &= ~(DM_DTR);
-
-	spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags);
-	ch->ch_flag |= CH_PARAM;
-	(ch->ch_nd)->nd_tx_work = 1;
-	wake_up_interruptible(&ch->ch_flag_wait);
-
-	spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags);
-
-	return 0;
-}
-
-
-
-/*
- *      Get current modem status
- */
-static int get_modem_info(struct ch_struct *ch, unsigned int *value)
-{
-	unsigned int mlast;
-
-	mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) |
-		(ch->ch_mout    &  (DM_RTS | DM_DTR)));
-
-	/* defined in /usr/include/asm/termios.h */
-	mlast =   ((mlast & DM_RTS) ? TIOCM_RTS : 0)
-		| ((mlast & DM_DTR) ? TIOCM_DTR : 0)
-		| ((mlast & DM_CD)  ? TIOCM_CAR : 0)
-		| ((mlast & DM_RI)  ? TIOCM_RNG : 0)
-		| ((mlast & DM_DSR) ? TIOCM_DSR : 0)
-		| ((mlast & DM_CTS) ? TIOCM_CTS : 0);
-	return put_user(mlast, (unsigned int __user *) value);
-}
-
-/*
- *      Set modem lines
- */
-static int set_modem_info(struct ch_struct *ch, unsigned int command,
-			  unsigned int *value)
-{
-	int error;
-	unsigned int arg;
-	int mval = 0;
-	ulong lock_flags;
-
-	error = access_ok(VERIFY_READ, (void __user *) value, sizeof(int));
-	if (error == 0)
-		return -EFAULT;
-
-	if (get_user(arg, (unsigned int __user *) value))
-		return -EFAULT;
-	mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0)
-		| ((arg & TIOCM_DTR) ? DM_DTR : 0);
-
-	switch (command) {
-	case TIOCMBIS:  /* set flags */
-		ch->ch_mout |= mval;
-		break;
-	case TIOCMBIC:  /* clear flags */
-		ch->ch_mout &= ~mval;
-		break;
-	case TIOCMSET:
-		ch->ch_mout = mval;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags);
-
-	ch->ch_flag |= CH_PARAM;
-	(ch->ch_nd)->nd_tx_work = 1;
-	wake_up_interruptible(&ch->ch_flag_wait);
-
-	spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags);
-
-	return 0;
-}
-
-
-/*
- *  Assign the custom baud rate to the channel structure
- */
-static void dgrp_set_custom_speed(struct ch_struct *ch, int newrate)
-{
-	int testdiv;
-	int testrate_high;
-	int testrate_low;
-
-	int deltahigh, deltalow;
-
-	if (newrate < 0)
-		newrate = 0;
-
-	/*
-	 * Since the divisor is stored in a 16-bit integer, we make sure
-	 * we don't allow any rates smaller than a 16-bit integer would allow.
-	 * And of course, rates above the dividend won't fly.
-	 */
-	if (newrate && newrate < ((PORTSERVER_DIVIDEND / 0xFFFF) + 1))
-		newrate = ((PORTSERVER_DIVIDEND / 0xFFFF) + 1);
-	if (newrate && newrate > PORTSERVER_DIVIDEND)
-		newrate = PORTSERVER_DIVIDEND;
-
-	while (newrate > 0) {
-		testdiv = PORTSERVER_DIVIDEND / newrate;
-
-		/*
-		 * If we try to figure out what rate the PortServer would use
-		 * with the test divisor, it will be either equal or higher
-		 * than the requested baud rate.  If we then determine the
-		 * rate with a divisor one higher, we will get the next lower
-		 * supported rate below the requested.
-		 */
-		testrate_high = PORTSERVER_DIVIDEND / testdiv;
-		testrate_low  = PORTSERVER_DIVIDEND / (testdiv + 1);
-
-		/*
-		 * If the rate for the requested divisor is correct, just
-		 * use it and be done.
-		 */
-		if (testrate_high == newrate)
-			break;
-
-		/*
-		 * Otherwise, pick the rate that is closer (i.e. whichever rate
-		 * has a smaller delta).
-		 */
-		deltahigh = testrate_high - newrate;
-		deltalow = newrate - testrate_low;
-
-		if (deltahigh < deltalow)
-			newrate = testrate_high;
-		else
-			newrate = testrate_low;
-
-		break;
-	}
-
-	ch->ch_custom_speed = newrate;
-
-	drp_param(ch);
-
-	return;
-}
-
-
-/*
- # dgrp_tty_digiseta()
- *
- * Ioctl to set the information from ditty.
- *
- * NOTE: DIGI_IXON, DSRPACE, DCDPACE, and DTRPACE are unsupported.  JAR 990922
- */
-static int dgrp_tty_digiseta(struct tty_struct *tty,
-			     struct digi_struct *new_info)
-{
-	struct un_struct *un = tty->driver_data;
-	struct ch_struct *ch;
-
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	if (copy_from_user(&ch->ch_digi, (void __user *) new_info,
-			   sizeof(struct digi_struct)))
-		return -EFAULT;
-
-	if ((ch->ch_digi.digi_flags & RTSPACE) ||
-	    (ch->ch_digi.digi_flags & CTSPACE))
-		tty->termios.c_cflag |= CRTSCTS;
-	else
-		tty->termios.c_cflag &= ~CRTSCTS;
-
-	if (ch->ch_digi.digi_maxcps < 1)
-		ch->ch_digi.digi_maxcps = 1;
-
-	if (ch->ch_digi.digi_maxcps > 10000)
-		ch->ch_digi.digi_maxcps = 10000;
-
-	if (ch->ch_digi.digi_bufsize < 10)
-		ch->ch_digi.digi_bufsize = 10;
-
-	if (ch->ch_digi.digi_maxchar < 1)
-		ch->ch_digi.digi_maxchar = 1;
-
-	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
-		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
-
-	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
-		ch->ch_digi.digi_onlen = DIGI_PLEN;
-
-	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
-		ch->ch_digi.digi_offlen = DIGI_PLEN;
-
-	/* make the changes now */
-	drp_param(ch);
-
-	return 0;
-}
-
-
-
-/*
- * dgrp_tty_digigetedelay()
- *
- * Ioctl to get the current edelay setting.
- *
- *
- *
- */
-static int dgrp_tty_digigetedelay(struct tty_struct *tty, int *retinfo)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int tmp;
-
-	if (!retinfo)
-		return -EFAULT;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	tmp = ch->ch_edelay;
-
-	if (copy_to_user((void __user *) retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-/*
- * dgrp_tty_digisetedelay()
- *
- * Ioctl to set the EDELAY setting
- *
- */
-static int dgrp_tty_digisetedelay(struct tty_struct *tty, int *new_info)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int new_digi;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -EFAULT;
-
-	un = tty->driver_data;
-
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	if (copy_from_user(&new_digi, (void __user *)new_info, sizeof(int)))
-		return -EFAULT;
-
-	ch->ch_edelay = new_digi;
-
-	/* make the changes now */
-	drp_param(ch);
-
-	return 0;
-}
-
-
-/*
- *	The usual assortment of ioctl's
- *
- *	note:  use tty_check_change to make sure that we are not
- *	changing the state of a terminal when we are not a process
- *	in the forground.  See tty_io.c
- *		rc = tty_check_change(tty);
- *		if (rc) return rc;
- */
-static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
-			  unsigned long arg)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-	int rc;
-	struct digiflow_struct   dflow;
-
-	if (!tty)
-		return -ENODEV;
-
-	un = tty->driver_data;
-	if (!un)
-		return -ENODEV;
-
-	ch = un->un_ch;
-	if (!ch)
-		return -ENODEV;
-
-	switch (cmd) {
-
-	/*
-	 * Here are all the standard ioctl's that we MUST implement
-	 */
-
-	case TCSBRK:
-		/*
-		 * TCSBRK is SVID version: non-zero arg --> no break
-		 * this behaviour is exploited by tcdrain().
-		 *
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds
-		 */
-
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		tty_wait_until_sent(tty, 0);
-
-		if (!arg)
-			rc = dgrp_send_break(ch, 250); /* 1/4 second */
-
-		if (dgrp_tty_chars_in_buffer(tty) != 0)
-			return -EINTR;
-
-		return 0;
-
-	case TCSBRKP:
-		/* support for POSIX tcsendbreak()
-		 *
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds so we'll ask for something
-		 * in the middle: 0.375 seconds.
-		 */
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		tty_wait_until_sent(tty, 0);
-
-		rc = dgrp_send_break(ch, arg ? arg*250 : 250);
-
-		if (dgrp_tty_chars_in_buffer(tty) != 0)
-			return -EINTR;
-		return 0;
-
-	case TIOCSBRK:
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		tty_wait_until_sent(tty, 0);
-
-		/*
-		 * RealPort doesn't support turning on a break unconditionally.
-		 * The RealPort device will stop sending a break automatically
-		 * after the specified time value that we send in.
-		 */
-		rc = dgrp_send_break(ch, 250); /* 1/4 second */
-
-		if (dgrp_tty_chars_in_buffer(tty) != 0)
-			return -EINTR;
-		return 0;
-
-	case TIOCCBRK:
-		/*
-		 * RealPort doesn't support turning off a break unconditionally.
-		 * The RealPort device will stop sending a break automatically
-		 * after the specified time value that was sent when turning on
-		 * the break.
-		 */
-		return 0;
-
-	case TIOCMGET:
-		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
-				 sizeof(unsigned int));
-		if (rc == 0)
-			return -EFAULT;
-		return get_modem_info(ch, (unsigned int *) arg);
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return set_modem_info(ch, cmd, (unsigned int *) arg);
-
-	/*
-	 * Here are any additional ioctl's that we want to implement
-	 */
-
-	case TCFLSH:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-
-		switch (arg) {
-		case TCIFLUSH:
-		case TCIOFLUSH:
-			/* only flush input if this is the only open unit */
-			if (!IS_PRINT(MINOR(tty_devnum(tty)))) {
-				ch->ch_rout = ch->ch_rin;
-				ch->ch_send |= RR_RX_FLUSH;
-				(ch->ch_nd)->nd_tx_work = 1;
-				(ch->ch_nd)->nd_tx_ready = 1;
-				wake_up_interruptible(
-					&(ch->ch_nd)->nd_tx_waitq);
-			}
-			if (arg == TCIFLUSH)
-				break;
-
-		case TCOFLUSH: /* flush output, or the receive buffer */
-			/*
-			 * This is handled in the tty_ioctl.c code
-			 * calling tty_flush_buffer
-			 */
-			break;
-
-		default:
-			/* POSIX.1 says return EINVAL if we got a bad arg */
-			return -EINVAL;
-		}
-		/* pretend we didn't recognize this IOCTL */
-		return -ENOIOCTLCMD;
-
-#ifdef TIOCGETP
-	case TIOCGETP:
-#endif
-	/*****************************************
-	Linux		HPUX		Function
-	TCSETA		TCSETA		- set the termios
-	TCSETAF		TCSETAF		- wait for drain first, then set termios
-	TCSETAW		TCSETAW		- wait for drain,
-					flush the input queue, then set termios
-	- looking at the tty_ioctl code, these command all call our
-	tty_set_termios at the driver's end, when a TCSETA* is sent,
-	it is expecting the tty to have a termio structure,
-	NOT a termios structure.  These two structures differ in size
-	and the tty_ioctl code does a conversion before processing them both.
-	- we should treat the TCSETAW TCSETAF ioctls the same, and let
-	the tty_ioctl code do the conversion stuff.
-
-	TCSETS
-	TCSETSF		(none)
-	TCSETSW
-	- the associated tty structure has a termios structure.
-	*****************************************/
-
-	case TCGETS:
-	case TCGETA:
-		return -ENOIOCTLCMD;
-
-	case TCSETAW:
-	case TCSETAF:
-	case TCSETSF:
-	case TCSETSW:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-
-		/*
-		 * Also, now that we have TXPrint, we have to check
-		 * if this is the TXPrint device and the terminal
-		 * device is open. If so, do NOT run check_change,
-		 * as the terminal device is ALWAYS the parent.
-		 */
-		if (!IS_PRINT(MINOR(tty_devnum(tty))) ||
-		    !ch->ch_tun.un_open_count) {
-			rc = tty_check_change(tty);
-			if (rc)
-				return rc;
-		}
-
-		/* wait for all the characters in tbuf to drain */
-		tty_wait_until_sent(tty, 0);
-
-		if ((cmd == TCSETSF) || (cmd == TCSETAF)) {
-			/* flush the contents of the rbuf queue */
-			/* TODO:  check if this is print device? */
-			ch->ch_send |= RR_RX_FLUSH;
-			(ch->ch_nd)->nd_tx_ready = 1;
-			(ch->ch_nd)->nd_tx_work = 1;
-			wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-			/* do we need to do this?  just to be safe! */
-			ch->ch_rout = ch->ch_rin;
-		}
-
-		/* pretend we didn't recognize this */
-		return -ENOIOCTLCMD;
-
-	case TCXONC:
-		/*
-		 * The Linux Line Discipline (LD) would do this for us if we
-		 * let it, but we have the special firmware options to do this
-		 * the "right way" regardless of hardware or software flow
-		 * control so we'll do it outselves instead of letting the LD
-		 * do it.
-		 */
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-
-		switch (arg) {
-		case TCOON:
-			dgrp_tty_start(tty);
-			return 0;
-		case TCOOFF:
-			dgrp_tty_stop(tty);
-			return 0;
-		case TCION:
-			dgrp_tty_input_start(tty);
-			return 0;
-		case TCIOFF:
-			dgrp_tty_input_stop(tty);
-			return 0;
-		default:
-			return -EINVAL;
-		}
-
-	case DIGI_GETA:
-		/* get information for ditty */
-		if (copy_to_user((struct digi_struct __user *) arg,
-				 &ch->ch_digi, sizeof(struct digi_struct)))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-		/* wait for all the characters in tbuf to drain */
-		tty_wait_until_sent(tty, 0);
-
-		if (cmd == DIGI_SETAF) {
-			/* flush the contents of the rbuf queue */
-			/* send down a packet with RR_RX_FLUSH set */
-			ch->ch_send |= RR_RX_FLUSH;
-			(ch->ch_nd)->nd_tx_ready = 1;
-			(ch->ch_nd)->nd_tx_work = 1;
-			wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-			/* do we need to do this?  just to be safe! */
-			ch->ch_rout = ch->ch_rin;
-		}
-
-		/* pretend we didn't recognize this */
-		/* fall-through */
-
-	case DIGI_SETA:
-		return dgrp_tty_digiseta(tty, (struct digi_struct *) arg);
-
-	case DIGI_SEDELAY:
-		return dgrp_tty_digisetedelay(tty, (int *) arg);
-
-	case DIGI_GEDELAY:
-		return dgrp_tty_digigetedelay(tty, (int *) arg);
-
-	case DIGI_GETFLOW:
-	case DIGI_GETAFLOW:
-		if (cmd == (DIGI_GETFLOW)) {
-			dflow.startc = tty->termios.c_cc[VSTART];
-			dflow.stopc = tty->termios.c_cc[VSTOP];
-		} else {
-			dflow.startc = ch->ch_xxon;
-			dflow.stopc = ch->ch_xxoff;
-		}
-
-		if (copy_to_user((char __user *)arg, &dflow, sizeof(dflow)))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETFLOW:
-	case DIGI_SETAFLOW:
-
-		if (copy_from_user(&dflow, (char __user *)arg, sizeof(dflow)))
-			return -EFAULT;
-
-		if (cmd == (DIGI_SETFLOW)) {
-			tty->termios.c_cc[VSTART] = dflow.startc;
-			tty->termios.c_cc[VSTOP] = dflow.stopc;
-		} else {
-			ch->ch_xxon = dflow.startc;
-			ch->ch_xxoff = dflow.stopc;
-		}
-		break;
-
-	case DIGI_GETCUSTOMBAUD:
-		if (put_user(ch->ch_custom_speed, (unsigned int __user *) arg))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETCUSTOMBAUD:
-	{
-		int new_rate;
-
-		if (get_user(new_rate, (unsigned int __user *) arg))
-			return -EFAULT;
-		dgrp_set_custom_speed(ch, new_rate);
-
-		break;
-	}
-
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	return 0;
-}
-
-/*
- *  This routine allows the tty driver to be notified when
- *  the device's termios setting have changed.  Note that we
- *  should be prepared to accept the case where old == NULL
- *  and try to do something rational.
- *
- *  So we need to make sure that our copies of ch_oflag,
- *  ch_clag, and ch_iflag reflect the tty->termios flags.
- */
-static void dgrp_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct ktermios *ts;
-	struct ch_struct *ch;
-	struct un_struct *un;
-
-	/* seems silly, but we have to check all these! */
-	if (!tty)
-		return;
-
-	un = tty->driver_data;
-	if (!un)
-		return;
-
-	ts = &tty->termios;
-
-	ch = un->un_ch;
-	if (!ch)
-		return;
-
-	drp_param(ch);
-
-	/* the CLOCAL flag has just been set */
-	if (!(old->c_cflag & CLOCAL) && C_CLOCAL(tty))
-		wake_up_interruptible(&un->un_open_wait);
-}
-
-
-/*
- *	Throttle receiving data.  We just set a bit and stop reading
- *	data out of the channel buffer.  It will back up and the
- *	FEP will do whatever is necessary to stop the far end.
- */
-static void dgrp_tty_throttle(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_flag |= CH_RXSTOP;
-}
-
-
-static void dgrp_tty_unthrottle(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_flag &= ~CH_RXSTOP;
-}
-
-/*
- *	Stop the transmitter
- */
-static void dgrp_tty_stop(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_send |= RR_TX_STOP;
-	ch->ch_send &= ~RR_TX_START;
-
-	/* make the change NOW! */
-	(ch->ch_nd)->nd_tx_ready = 1;
-	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
-		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-}
-
-/*
- *	Start the transmitter
- */
-static void dgrp_tty_start(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	/* TODO: don't do anything if the transmitter is not stopped */
-
-	ch->ch_send |= RR_TX_START;
-	ch->ch_send &= ~RR_TX_STOP;
-
-	/* make the change NOW! */
-	(ch->ch_nd)->nd_tx_ready = 1;
-	(ch->ch_nd)->nd_tx_work = 1;
-	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
-		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-
-}
-
-/*
- *	Stop the receiver
- */
-static void dgrp_tty_input_stop(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_send |= RR_RX_STOP;
-	ch->ch_send &= ~RR_RX_START;
-	(ch->ch_nd)->nd_tx_ready = 1;
-	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
-		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-
-}
-
-
-static void dgrp_tty_send_xchar(struct tty_struct *tty, char c)
-{
-	struct un_struct *un;
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	un = tty->driver_data;
-	if (!un)
-		return;
-
-	ch = un->un_ch;
-	if (!ch)
-		return;
-	if (c == STOP_CHAR(tty))
-		ch->ch_send |= RR_RX_STOP;
-	else if (c == START_CHAR(tty))
-		ch->ch_send |= RR_RX_START;
-
-	ch->ch_nd->nd_tx_ready = 1;
-	ch->ch_nd->nd_tx_work = 1;
-
-	return;
-}
-
-
-static void dgrp_tty_input_start(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-
-	if (!tty)
-		return;
-
-	ch = ((struct un_struct *) tty->driver_data)->un_ch;
-	if (!ch)
-		return;
-
-	ch->ch_send |= RR_RX_START;
-	ch->ch_send &= ~RR_RX_STOP;
-	(ch->ch_nd)->nd_tx_ready = 1;
-	(ch->ch_nd)->nd_tx_work = 1;
-	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
-		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
-
-}
-
-
-/*
- *	Hangup the port.  Like a close, but don't wait for output
- *	to drain.
- *
- *	How do we close all the channels that are open?
- */
-static void dgrp_tty_hangup(struct tty_struct *tty)
-{
-	struct ch_struct *ch;
-	struct nd_struct *nd;
-	struct un_struct *un;
-
-	if (!tty)
-		return;
-
-	un = tty->driver_data;
-	if (!un)
-		return;
-
-	ch = un->un_ch;
-	if (!ch)
-		return;
-
-	nd = ch->ch_nd;
-
-	if (C_HUPCL(tty)) {
-		/* LOWER DTR */
-		ch->ch_mout &= ~DM_DTR;
-		/* Don't do this here */
-		/* ch->ch_flag |= CH_HANGUP; */
-		ch->ch_nd->nd_tx_ready = 1;
-		ch->ch_nd->nd_tx_work  = 1;
-		if (waitqueue_active(&ch->ch_flag_wait))
-			wake_up_interruptible(&ch->ch_flag_wait);
-	}
-
-}
-
-/************************************************************************/
-/*                                                                      */
-/*       TTY Initialization/Cleanup Functions                           */
-/*                                                                      */
-/************************************************************************/
-
-/*
- *	Uninitialize the TTY portion of the supplied node.  Free all
- *      memory and resources associated with this node.  Do it in reverse
- *      allocation order: this might possibly result in less fragmentation
- *      of memory, though I don't know this for sure.
- */
-void
-dgrp_tty_uninit(struct nd_struct *nd)
-{
-	unsigned int i;
-	char id[3];
-
-	ID_TO_CHAR(nd->nd_ID, id);
-
-	if (nd->nd_ttdriver_flags & SERIAL_TTDRV_REG) {
-		tty_unregister_driver(nd->nd_serial_ttdriver);
-
-		kfree(nd->nd_serial_ttdriver->ttys);
-		nd->nd_serial_ttdriver->ttys = NULL;
-
-		put_tty_driver(nd->nd_serial_ttdriver);
-		nd->nd_ttdriver_flags &= ~SERIAL_TTDRV_REG;
-	}
-
-	if (nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG) {
-		tty_unregister_driver(nd->nd_callout_ttdriver);
-
-		kfree(nd->nd_callout_ttdriver->ttys);
-		nd->nd_callout_ttdriver->ttys = NULL;
-
-		put_tty_driver(nd->nd_callout_ttdriver);
-		nd->nd_ttdriver_flags &= ~CALLOUT_TTDRV_REG;
-	}
-
-	if (nd->nd_ttdriver_flags & XPRINT_TTDRV_REG) {
-		tty_unregister_driver(nd->nd_xprint_ttdriver);
-
-		kfree(nd->nd_xprint_ttdriver->ttys);
-		nd->nd_xprint_ttdriver->ttys = NULL;
-
-		put_tty_driver(nd->nd_xprint_ttdriver);
-		nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG;
-	}
-	for (i = 0; i < CHAN_MAX; i++)
-		tty_port_destroy(&nd->nd_chan[i].port);
-}
-
-
-
-/*
- *     Initialize the TTY portion of the supplied node.
- */
-int
-dgrp_tty_init(struct nd_struct *nd)
-{
-	char id[3];
-	int  rc;
-	int  i;
-
-	ID_TO_CHAR(nd->nd_ID, id);
-
-	/*
-	 *  Initialize the TTDRIVER structures.
-	 */
-
-	nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX);
-	if (!nd->nd_serial_ttdriver)
-		return -ENOMEM;
-
-	sprintf(nd->nd_serial_name,  "tty_dgrp_%s_", id);
-
-	nd->nd_serial_ttdriver->owner = THIS_MODULE;
-	nd->nd_serial_ttdriver->name = nd->nd_serial_name;
-	nd->nd_serial_ttdriver->name_base = 0;
-	nd->nd_serial_ttdriver->major = 0;
-	nd->nd_serial_ttdriver->minor_start = 0;
-	nd->nd_serial_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
-	nd->nd_serial_ttdriver->subtype = SERIAL_TYPE_NORMAL;
-	nd->nd_serial_ttdriver->init_termios = DefaultTermios;
-	nd->nd_serial_ttdriver->driver_name = "dgrp";
-	nd->nd_serial_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
-					 TTY_DRIVER_DYNAMIC_DEV |
-					 TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs. */
-	nd->nd_serial_ttdriver->ttys =
-		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!nd->nd_serial_ttdriver->ttys)
-		return -ENOMEM;
-
-	tty_set_operations(nd->nd_serial_ttdriver, &dgrp_tty_ops);
-
-	if (!(nd->nd_ttdriver_flags & SERIAL_TTDRV_REG)) {
-		/*
-		 *   Register tty devices
-		 */
-		rc = tty_register_driver(nd->nd_serial_ttdriver);
-		if (rc < 0) {
-			/*
-			 * If errno is EBUSY, this means there are no more
-			 * slots available to have us auto-majored.
-			 * (Which is currently supported up to 256)
-			 *
-			 * We can still request majors above 256,
-			 * we just have to do it manually.
-			 */
-			if (rc == -EBUSY) {
-				int i;
-				int max_majors = 1U << (32 - MINORBITS);
-				for (i = 256; i < max_majors; i++) {
-					nd->nd_serial_ttdriver->major = i;
-					rc = tty_register_driver
-						(nd->nd_serial_ttdriver);
-					if (rc >= 0)
-						break;
-				}
-				/* Really fail now, since we ran out
-				 * of majors to try. */
-				if (i == max_majors)
-					return rc;
-
-			} else {
-				return rc;
-			}
-		}
-		nd->nd_ttdriver_flags |= SERIAL_TTDRV_REG;
-	}
-
-	nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX);
-	if (!nd->nd_callout_ttdriver)
-		return -ENOMEM;
-
-	sprintf(nd->nd_callout_name, "cu_dgrp_%s_",  id);
-
-	nd->nd_callout_ttdriver->owner = THIS_MODULE;
-	nd->nd_callout_ttdriver->name = nd->nd_callout_name;
-	nd->nd_callout_ttdriver->name_base = 0;
-	nd->nd_callout_ttdriver->major = nd->nd_serial_ttdriver->major;
-	nd->nd_callout_ttdriver->minor_start = 0x40;
-	nd->nd_callout_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
-	nd->nd_callout_ttdriver->subtype = SERIAL_TYPE_CALLOUT;
-	nd->nd_callout_ttdriver->init_termios = DefaultTermios;
-	nd->nd_callout_ttdriver->driver_name = "dgrp";
-	nd->nd_callout_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
-					  TTY_DRIVER_DYNAMIC_DEV |
-					  TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs. */
-	nd->nd_callout_ttdriver->ttys =
-		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!nd->nd_callout_ttdriver->ttys)
-		return -ENOMEM;
-
-	tty_set_operations(nd->nd_callout_ttdriver, &dgrp_tty_ops);
-
-	if (dgrp_register_cudevices) {
-		if (!(nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG)) {
-			/*
-			 *   Register cu devices
-			 */
-			rc = tty_register_driver(nd->nd_callout_ttdriver);
-			if (rc < 0)
-				return rc;
-			nd->nd_ttdriver_flags |= CALLOUT_TTDRV_REG;
-		}
-	}
-
-
-	nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX);
-	if (!nd->nd_xprint_ttdriver)
-		return -ENOMEM;
-
-	sprintf(nd->nd_xprint_name,  "pr_dgrp_%s_", id);
-
-	nd->nd_xprint_ttdriver->owner = THIS_MODULE;
-	nd->nd_xprint_ttdriver->name = nd->nd_xprint_name;
-	nd->nd_xprint_ttdriver->name_base = 0;
-	nd->nd_xprint_ttdriver->major = nd->nd_serial_ttdriver->major;
-	nd->nd_xprint_ttdriver->minor_start = 0x80;
-	nd->nd_xprint_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
-	nd->nd_xprint_ttdriver->subtype = SERIAL_TYPE_XPRINT;
-	nd->nd_xprint_ttdriver->init_termios = DefaultTermios;
-	nd->nd_xprint_ttdriver->driver_name = "dgrp";
-	nd->nd_xprint_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
-					 TTY_DRIVER_DYNAMIC_DEV |
-					 TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs. */
-	nd->nd_xprint_ttdriver->ttys =
-		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!nd->nd_xprint_ttdriver->ttys)
-		return -ENOMEM;
-
-	tty_set_operations(nd->nd_xprint_ttdriver, &dgrp_tty_ops);
-
-	if (dgrp_register_prdevices) {
-		if (!(nd->nd_ttdriver_flags & XPRINT_TTDRV_REG)) {
-			/*
-			 *   Register transparent print devices
-			 */
-			rc = tty_register_driver(nd->nd_xprint_ttdriver);
-			if (rc < 0)
-				return rc;
-			nd->nd_ttdriver_flags |= XPRINT_TTDRV_REG;
-		}
-	}
-
-	for (i = 0; i < CHAN_MAX; i++) {
-		struct ch_struct *ch = nd->nd_chan + i;
-
-		ch->ch_nd = nd;
-		ch->ch_digi = digi_init;
-		ch->ch_edelay = 100;
-		ch->ch_custom_speed = 0;
-		ch->ch_portnum = i;
-		ch->ch_tun.un_ch = ch;
-		ch->ch_pun.un_ch = ch;
-		ch->ch_tun.un_type = SERIAL_TYPE_NORMAL;
-		ch->ch_pun.un_type = SERIAL_TYPE_XPRINT;
-
-		init_waitqueue_head(&(ch->ch_flag_wait));
-		init_waitqueue_head(&(ch->ch_sleep));
-
-		init_waitqueue_head(&(ch->ch_tun.un_open_wait));
-		init_waitqueue_head(&(ch->ch_tun.un_close_wait));
-
-		init_waitqueue_head(&(ch->ch_pun.un_open_wait));
-		init_waitqueue_head(&(ch->ch_pun.un_close_wait));
-		tty_port_init(&ch->port);
-	}
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/digirp.h linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/digirp.h
--- linux-libre-3.16-gnu/drivers/staging/dgrp/digirp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/digirp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,129 +0,0 @@
-/************************************************************************
- * HP-UX Realport Daemon interface file.
- *
- * Copyright (C) 1998, by Digi International.  All Rights Reserved.
- ************************************************************************/
-
-#ifndef _DIGIDRP_H
-#define _DIGIDRP_H
-
-/************************************************************************
- * This file contains defines for the ioctl() interface to
- * the realport driver.   This ioctl() interface is used by the
- * daemon to set speed setup parameters honored by the driver.
- ************************************************************************/
-
-struct link_struct {
-	int lk_fast_rate;  /* Fast line rate to be used
-			      when the delay is less-equal
-			      to lk_fast_delay */
-
-	int lk_fast_delay; /* Fast line rate delay in
-			      milliseconds */
-
-	int lk_slow_rate;  /* Slow line rate to be used when
-			      the delay is greater-equal
-			      to lk_slow_delay */
-
-	int lk_slow_delay; /* Slow line rate delay in
-			      milliseconds */
-
-	int lk_header_size; /* Estimated packet header size
-			       when sent across the slowest
-			       link.  */
-};
-
-#define DIGI_GETLINK	_IOW('e', 103, struct link_struct)	/* Get link parameters */
-#define DIGI_SETLINK	_IOW('e', 104, struct link_struct)	/* Set link parameters */
-
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-struct	digiflow_struct {
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
-};
-
-/************************************************************************
- * Values for digi_flags
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl */
-#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input */
-#define DIGI_422	0x4000		/* Change parallel port to input */
-#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		 */
-
-
-/************************************************************************
- * Values associated with transparent print
- ************************************************************************/
-#define DIGI_PLEN	8		/* String length */
-#define	DIGI_TSIZ	10		/* Terminal string len */
-
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_struct {
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-	unsigned short	digi_maxcps;		/* Max printer CPS	*/
-	unsigned short	digi_maxchar;		/* Max chars in print queue */
-	unsigned short	digi_bufsize;		/* Buffer size		*/
-	unsigned char	digi_onlen;		/* Length of ON string	*/
-	unsigned char	digi_offlen;		/* Length of OFF string	*/
-	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
-	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
-	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
-};
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-/* Read params */
-#define DIGI_GETA	_IOR('e', 94, struct digi_struct)
-
-/* Set params */
-#define DIGI_SETA	_IOW('e', 95, struct digi_struct)
-
-/* Drain & set params	*/
-#define DIGI_SETAW	_IOW('e', 96, struct digi_struct)
-
-/* Drain, flush & set params */
-#define DIGI_SETAF	_IOW('e', 97, struct digi_struct)
-
-/* Get startc/stopc flow control characters */
-#define	DIGI_GETFLOW	_IOR('e', 99, struct digiflow_struct)
-
-/* Set startc/stopc flow control characters */
-#define	DIGI_SETFLOW	_IOW('e', 100, struct digiflow_struct)
-
-/* Get Aux. startc/stopc flow control chars */
-#define	DIGI_GETAFLOW	_IOR('e', 101, struct digiflow_struct)
-
-/* Set Aux. startc/stopc flow control chars */
-#define	DIGI_SETAFLOW	_IOW('e', 102, struct digiflow_struct)
-
-/* Set integer baud rate */
-#define	DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)
-
-/* Get integer baud rate */
-#define	DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)
-
-#define	DIGI_GEDELAY	_IOR('d', 246, int)	/* Get edelay */
-#define	DIGI_SEDELAY	_IOW('d', 247, int)	/* Get edelay */
-
-
-#endif /* _DIGIDRP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/drp.h linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/drp.h
--- linux-libre-3.16-gnu/drivers/staging/dgrp/drp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/drp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,693 +0,0 @@
-/*
- *
- * Copyright 1999 Digi International (www.digi.com)
- *     Gene Olson  <gene at digi dot com>
- *     James Puzzo <jamesp at digi dot com>
- *     Scott Kilau <scottk at digi dot com>
- *
- * This program is free software; you can redistribute 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, 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.
- *
- */
-
-/************************************************************************
- * Master include file for Linux Realport Driver.
- ************************************************************************/
-
-#ifndef __DRP_H
-#define __DRP_H
-
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/semaphore.h>
-#include <linux/tty.h>
-
-
-#include "digirp.h"
-
-/************************************************************************
- * Tuning parameters.
- ************************************************************************/
-
-#define CHAN_MAX	64		/* Max # ports per server */
-
-#define SEQ_MAX		128		/* Max # transmit sequences (2^n) */
-#define SEQ_MASK	(SEQ_MAX-1)	/* Sequence buffer modulus mask */
-
-#define TBUF_MAX	4096		/* Size of transmit buffer (2^n) */
-#define RBUF_MAX	4096		/* Size of receive buffer (2^n) */
-
-#define TBUF_MASK	(TBUF_MAX-1)	/* Transmit buffer modulus mask */
-#define RBUF_MASK	(RBUF_MAX-1)	/* Receive buffer modulus mask */
-
-#define TBUF_LOW	1000		/* Transmit low water mark */
-
-#define UIO_BASE	1000		/* Base for write operations */
-#define UIO_MIN		2000		/* Minimum size application buffer */
-#define UIO_MAX		8100		/* Unix I/O buffer size */
-
-#define MON_MAX		65536		/* Monitor buffer size (2^n) */
-#define MON_MASK	(MON_MAX-1)	/* Monitor wrap mask */
-
-#define DPA_MAX		65536		/* DPA buffer size (2^n) */
-#define DPA_MASK	(DPA_MAX-1)	/* DPA wrap mask */
-#define DPA_HIGH_WATER	58000		/* Enforce flow control when
-					 * over this amount
-					 */
-
-#define IDLE_MAX	(20 * HZ)	/* Max TCP link idle time */
-
-#define MAX_DESC_LEN	100		/* Maximum length of stored PS
-					 * description
-					 */
-
-#define WRITEBUFLEN	((4096) + 4)    /* 4 extra for alignment play space */
-
-#define VPDSIZE		512
-
-/************************************************************************
- * Minor device decoding conventions.
- ************************************************************************
- *
- * For Linux, the net and mon devices are handled via "proc", so we
- * only have to mux the "tty" devices.  Since every PortServer will
- * have an individual major number, the PortServer number does not
- * need to be encoded, and in fact, does not need to exist.
- *
- */
-
-/*
- * Port device decoding conventions:
- *
- *	Device 00 - 3f        64 dial-in modem devices. (tty)
- *	Device 40 - 7f        64 dial-out tty devices.  (cu)
- *	Device 80 - bf        64 dial-out printer devices.
- *
- *  IS_PRINT(dev)		This is a printer device.
- *
- *  OPEN_CATEGORY(dev)		Specifies the device category.  No two
- *				devices of different categories may be open
- *				at the same time.
- *
- * The following require the category returned by OPEN_CATEGORY().
- *
- *  OPEN_WAIT_AVAIL(cat)	Waits on open until the device becomes
- *				available.  Fails if NDELAY specified.
- *
- *  OPEN_WAIT_CARRIER(cat)	Waits on open if carrier is not present.
- *				Succeeds if NDELAY is given.
- *
- *  OPEN_FORCES_CARRIER(cat)	Carrier is forced high on open.
- *
- */
-
-#define PORT_NUM(dev)			((dev) & 0x3f)
-
-#define OPEN_CATEGORY(dev)		((((dev) & 0x80) & 0x40))
-#define IS_PRINT(dev)			(((dev) & 0xff) >= 0x80)
-
-#define OPEN_WAIT_AVAIL(cat)		(((cat) & 0x40) == 0x000)
-#define OPEN_WAIT_CARRIER(cat)		(((cat) & 0x40) == 0x000)
-#define OPEN_FORCES_CARRIER(cat)	(((cat) & 0x40) != 0x000)
-
-
-/************************************************************************
- * Modem signal defines for 16450/16550 compatible FEP.
- * set in ch_mout, ch_mflow, ch_mlast etc
- ************************************************************************/
-
-/* TODO : Re-verify that these modem signal definitions are correct */
-
-#define DM_DTR		0x01
-#define DM_RTS		0x02
-#define DM_RTS_TOGGLE	0x04
-
-#define DM_OUT1		0x04
-#define DM_OUT2		0x08
-
-#define DM_CTS		0x10
-#define DM_DSR		0x20
-#define DM_RI		0x40
-#define DM_CD		0x80		/* This is the DCD flag */
-
-
-/************************************************************************
- * Realport Event Flags.
- ************************************************************************/
-
-#define EV_OPU		0x0001		/* Ouput paused by client */
-#define EV_OPS		0x0002		/* Output paused by XOFF */
-#define EV_OPX		0x0004		/* Output paused by XXOFF */
-#define EV_OPH		0x0008		/* Output paused by MFLOW */
-#define EV_IPU		0x0010		/* Input paused by client */
-#define EV_IPS		0x0020		/* Input paused by hi/low water */
-#define EV_TXB		0x0040		/* Transmit break pending */
-#define EV_TXI		0x0080		/* Transmit immediate pending */
-#define EV_TXF		0x0100		/* Transmit flow control pending */
-#define EV_RXB		0x0200		/* Break received */
-
-
-/************************************************************************
- * Realport CFLAGS.
- ************************************************************************/
-
-#define CF_CS5		0x0000		/* 5 bit characters */
-#define CF_CS6		0x0010		/* 6 bit characters */
-#define CF_CS7		0x0020		/* 7 bit characters */
-#define CF_CS8		0x0030		/* 8 bit characters */
-#define CF_CSIZE	0x0030		/* Character size */
-#define CF_CSTOPB	0x0040		/* Two stop bits */
-#define CF_CREAD	0x0080		/* Enable receiver */
-#define CF_PARENB	0x0100		/* Enable parity */
-#define CF_PARODD	0x0200		/* Odd parity */
-#define CF_HUPCL	0x0400		/* Drop DTR on close */
-
-
-/************************************************************************
- * Realport XFLAGS.
- ************************************************************************/
-
-#define XF_XPAR		0x0001		/* Enable Mark/Space Parity */
-#define XF_XMODEM	0x0002		/* Enable in-band modem signalling */
-#define XF_XCASE	0x0004		/* Convert special characters */
-#define XF_XEDATA	0x0008		/* Error data in stream */
-#define XF_XTOSS	0x0010		/* Toss IXANY characters */
-#define XF_XIXON	0x0020		/* xxon/xxoff enable */
-
-
-/************************************************************************
- * Realport IFLAGS.
- ************************************************************************/
-
-#define IF_IGNBRK	0x0001		/* Ignore input break */
-#define IF_BRKINT	0x0002		/* Break interrupt */
-#define IF_IGNPAR	0x0004		/* Ignore error characters */
-#define IF_PARMRK	0x0008		/* Error chars marked with 0xff */
-#define IF_INPCK	0x0010		/* Input parity checking enabled */
-#define IF_ISTRIP	0x0020		/* Input chars masked with 0x7F */
-#define IF_IXON		0x0400		/* Output software flow control */
-#define IF_IXANY	0x0800		/* Restart output on any char */
-#define	IF_IXOFF	0x1000		/* Input software flow control */
-#define IF_DOSMODE	0x8000		/* 16450-compatible errors */
-
-
-/************************************************************************
- * Realport OFLAGS.
- ************************************************************************/
-
-#define OF_OLCUC	0x0002		/* Map lower to upper case */
-#define OF_ONLCR	0x0004		/* Map NL to CR-NL */
-#define OF_OCRNL	0x0008		/* Map CR to NL */
-#define OF_ONOCR	0x0010		/* No CR output at column 0 */
-#define OF_ONLRET	0x0020		/* Assume NL does NL/CR */
-#define OF_TAB3		0x1800		/* Tabs expand to 8 spaces */
-#define OF_TABDLY	0x1800		/* Tab delay */
-
-/************************************************************************
- * Unit flag definitions for un_flag.
- ************************************************************************/
-
-/* These are the DIGI unit flags */
-#define UN_EXCL		0x00010000	/* Exclusive open */
-#define UN_STICKY	0x00020000	/* TTY Settings are now sticky */
-#define UN_BUSY		0x00040000	/* Some work this channel */
-#define UN_PWAIT	0x00080000	/* Printer waiting for terminal */
-#define UN_TIME		0x00100000	/* Waiting on time */
-#define UN_EMPTY	0x00200000	/* Waiting output queue empty */
-#define UN_LOW		0x00400000	/* Waiting output low water */
-#define UN_DIGI_MASK	0x00FF0000	/* Waiting output low water */
-
-/*
- * Definitions for async_struct (and serial_struct) flags field
- *
- * these are the ASYNC flags copied from serial.h
- *
- */
-#define UN_HUP_NOTIFY	0x0001 /* Notify getty on hangups and
-				* closes on the callout port
-				*/
-#define UN_FOURPORT	0x0002	/* Set OU1, OUT2 per AST Fourport settings */
-#define UN_SAK		0x0004	/* Secure Attention Key (Orange book) */
-#define UN_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
-
-#define UN_SPD_MASK	0x0030
-#define UN_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
-#define UN_SPD_VHI	0x0020	/* Use 115200 instead of 38400 bps */
-#define UN_SPD_CUST	0x0030	/* Use user-specified divisor */
-
-#define UN_SKIP_TEST	0x0040 /* Skip UART test during autoconfiguration */
-#define UN_AUTO_IRQ	0x0080 /* Do automatic IRQ during autoconfiguration */
-
-#define UN_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
-#define UN_PGRP_LOCKOUT	   0x0200 /* Lock out cua opens based on pgrp */
-#define UN_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
-
-#define UN_FLAGS	0x0FFF	/* Possible legal async flags */
-#define UN_USR_MASK	0x0430	/* Legal flags that non-privileged
-				 * users can set or reset
-				 */
-
-#define UN_INITIALIZED		0x80000000 /* Serial port was initialized */
-#define UN_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
-#define UN_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
-#define UN_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
-#define UN_CLOSING		0x08000000 /* Serial port is closing */
-#define UN_CTS_FLOW		0x04000000 /* Do CTS flow control */
-#define UN_CHECK_CD		0x02000000 /* i.e., CLOCAL */
-#define UN_SHARE_IRQ		0x01000000 /* for multifunction cards */
-
-
-/************************************************************************
- * Structure for terminal or printer unit.  struct un_struct
- *
- * Note that in some places the code assumes the "tty_t" is placed
- * first in the structure.
- ************************************************************************/
-
-struct un_struct {
-	struct tty_struct *un_tty;		/* System TTY struct */
-	struct ch_struct *un_ch;		/* Associated channel */
-
-	ushort     un_open_count;		/* Successful open count */
-	int		un_flag;		/* Unit flags */
-	ushort     un_tbusy;		/* Busy transmit count */
-
-	wait_queue_head_t  un_open_wait;
-	wait_queue_head_t  un_close_wait;
-	ushort	un_type;
-	struct device *un_sysfs;
-};
-
-
-/************************************************************************
- * Channel State Numbers for ch_state.
- ************************************************************************/
-
-/*
- * The ordering is important.
- *
- *    state <= CS_WAIT_CANCEL implies the channel is definitely closed.
- *
- *    state >= CS_WAIT_FAIL  implies the channel is definitely open.
- *
- *    state >= CS_READY implies data is allowed on the channel.
- */
-
-enum dgrp_ch_state_t {
-	CS_IDLE = 0,	    /* Channel is idle */
-	CS_WAIT_OPEN = 1,   /* Waiting for Immediate Open Resp */
-	CS_WAIT_CANCEL = 2, /* Waiting for Per/Incom Cancel Resp */
-	CS_WAIT_FAIL = 3,   /* Waiting for Immed Open Failure */
-	CS_SEND_QUERY = 4,  /* Ready to send Port Query */
-	CS_WAIT_QUERY = 5,  /* Waiting for Port Query Response */
-	CS_READY = 6,	    /* Ready to accept commands and data */
-	CS_SEND_CLOSE =	7,  /* Ready to send Close Request */
-	CS_WAIT_CLOSE =	8   /* Waiting for Close Response */
-};
-
-/************************************************************************
- * Device flag definitions for ch_flag.
- ************************************************************************/
-
-/*
- *  Note that the state of the two carrier based flags is key.	When
- *  we check for carrier state transitions, we look at the current
- *  physical state of the DCD line and compare it with PHYS_CD (which
- *  was the state the last time we checked), and we also determine
- *  a new virtual state (composite of the physical state, FORCEDCD,
- *  CLOCAL, etc.) and compare it with VIRT_CD.
- *
- *  VIRTUAL transitions high will have the side effect of waking blocked
- *  opens.
- *
- *  PHYSICAL transitions low will cause hangups to occur _IF_ the virtual
- *  state is also low.	We DON'T want to hangup on a PURE virtual drop.
- */
-
-#define CH_HANGUP	0x00002		/* Server port ready to close */
-
-#define CH_VIRT_CD	0x00004		/* Carrier was virtually present */
-#define CH_PHYS_CD	0x00008		/* Carrier was physically present */
-
-#define CH_CLOCAL	0x00010		/* CLOCAL set in cflags */
-#define CH_BAUD0	0x00020		/* Baud rate zero hangup */
-
-#define CH_FAST_READ	0x00040		/* Fast reads are enabled */
-#define CH_FAST_WRITE	0x00080		/* Fast writes are enabled */
-
-#define CH_PRON		0x00100		/* Printer on string active */
-#define CH_RX_FLUSH	0x00200		/* Flushing receive data */
-#define CH_LOW		0x00400		/* Thread waiting for LOW water */
-#define CH_EMPTY	0x00800		/* Thread waiting for EMPTY */
-#define CH_DRAIN	0x01000		/* Close is waiting to drain */
-#define CH_INPUT	0x02000		/* Thread waiting for INPUT */
-#define CH_RXSTOP	0x04000		/* Stop output to ldisc */
-#define CH_PARAM	0x08000		/* A parameter was updated */
-#define CH_WAITING_SYNC 0x10000		/* A pending sync was assigned
-					 * to this port.
-					 */
-#define CH_PORT_GONE	0x20000		/* Port has disappeared */
-#define CH_TX_BREAK	0x40000		/* TX Break to be sent,
-					 * but has not yet.
-					 */
-
-/************************************************************************
- * Types of Open Requests for ch_otype.
- ************************************************************************/
-
-#define OTYPE_IMMEDIATE	  0		/* Immediate Open */
-#define OTYPE_PERSISTENT  1		/* Persistent Open */
-#define OTYPE_INCOMING	  2		/* Incoming Open */
-
-
-/************************************************************************
- * Request/Response flags.
- ************************************************************************/
-
-#define RR_SEQUENCE	0x0001		/* Get server RLAST, TIN */
-#define RR_STATUS	0x0002		/* Get server MINT, EINT */
-#define RR_BUFFER	0x0004		/* Get server RSIZE, TSIZE */
-#define RR_CAPABILITY	0x0008		/* Get server port capabilities */
-
-#define RR_TX_FLUSH	0x0040		/* Flush output buffers */
-#define RR_RX_FLUSH	0x0080		/* Flush input buffers */
-
-#define RR_TX_STOP	0x0100		/* Pause output */
-#define RR_RX_STOP	0x0200		/* Pause input */
-#define RR_TX_START	0x0400		/* Start output */
-#define RR_RX_START	0x0800		/* Start input */
-
-#define RR_TX_BREAK	0x1000		/* Send BREAK */
-#define RR_TX_ICHAR	0x2000		/* Send character immediate */
-
-
-/************************************************************************
- * Channel information structure.   struct ch_struct
- ************************************************************************/
-
-struct ch_struct {
-	struct digi_struct ch_digi;		/* Digi variables */
-	int	ch_edelay;		/* Digi edelay */
-
-	struct tty_port port;
-	struct un_struct ch_tun;	/* Terminal unit info */
-	struct un_struct ch_pun;	/* Printer unit info */
-
-	struct nd_struct *ch_nd;	/* Node pointer */
-	u8  *ch_tbuf;		/* Local Transmit Buffer */
-	u8  *ch_rbuf;		/* Local Receive Buffer */
-	ulong	ch_cpstime;		/* Printer CPS time */
-	ulong	ch_waketime;		/* Printer wake time */
-
-	ulong	ch_flag;		/* CH_* flags */
-
-	enum dgrp_ch_state_t ch_state;		/* CS_* Protocol state */
-	ushort	ch_send;		/* Bit vector of RR_* requests */
-	ushort	ch_expect;		/* Bit vector of RR_* responses */
-	ushort	ch_wait_carrier;	/* Thread count waiting for carrier */
-	ushort	ch_wait_count[3];	/* Thread count waiting by otype */
-
-	ushort	ch_portnum;		/* Port number */
-	ushort	ch_open_count;		/* Successful open count */
-	ushort	ch_category;		/* Device category */
-	ushort	ch_open_error;		/* Last open error number */
-	ushort	ch_break_time;		/* Pending break request time */
-	ushort	ch_cpsrem;		/* Printer CPS remainder */
-	ushort	ch_ocook;		/* Realport fastcook oflags */
-	ushort	ch_inwait;		/* Thread count in CLIST input */
-
-	ushort	ch_tin;			/* Local transmit buffer in ptr */
-	ushort	ch_tout;		/* Local transmit buffer out ptr */
-	ushort	ch_s_tin;		/* Realport TIN */
-	ushort	ch_s_tpos;		/* Realport TPOS */
-	ushort	ch_s_tsize;		/* Realport TSIZE */
-	ushort	ch_s_treq;		/* Realport TREQ */
-	ushort	ch_s_elast;		/* Realport ELAST */
-
-	ushort	ch_rin;			/* Local receive buffer in ptr */
-	ushort	ch_rout;		/* Local receive buffer out ptr */
-	ushort	ch_s_rin;		/* Realport RIN */
-	/* David Fries 7-13-2001, ch_s_rin should be renamed ch_s_rout because
-	 * the variable we want to represent is the PortServer's ROUT, which is
-	 * the sequence number for the next byte the PortServer will send us.
-	 * RIN is the sequence number for the next byte the PortServer will
-	 * receive from the uart.  The port server will send data as long as
-	 * ROUT is less than RWIN.  What would happen is the port is opened, it
-	 * receives data, it gives the value of RIN, we set the RWIN to
-	 * RIN+RBUF_MAX-1, it sends us RWIN-ROUT bytes which overflows.	 ROUT
-	 * is set to zero when the port is opened, so we start at zero and
-	 * count up as data is received.
-	 */
-	ushort	ch_s_rwin;		/* Realport RWIN */
-	ushort	ch_s_rsize;		/* Realport RSIZE */
-
-	ushort	ch_tmax;		/* Local TMAX */
-	ushort	ch_ttime;		/* Local TTIME */
-	ushort	ch_rmax;		/* Local RMAX */
-	ushort	ch_rtime;		/* Local RTIME */
-	ushort	ch_rlow;		/* Local RLOW */
-	ushort	ch_rhigh;		/* Local RHIGH */
-
-	ushort	ch_s_tmax;		/* Realport TMAX */
-	ushort	ch_s_ttime;		/* Realport TTIME */
-	ushort	ch_s_rmax;		/* Realport RMAX */
-	ushort	ch_s_rtime;		/* Realport RTIME */
-	ushort	ch_s_rlow;		/* Realport RLOW */
-	ushort	ch_s_rhigh;		/* Realport RHIGH */
-
-	ushort	ch_brate;		/* Local baud rate */
-	ushort	ch_cflag;		/* Local tty cflags */
-	ushort	ch_iflag;		/* Local tty iflags */
-	ushort	ch_oflag;		/* Local tty oflags */
-	ushort	ch_xflag;		/* Local tty xflags */
-
-	ushort	ch_s_brate;		/* Realport BRATE */
-	ushort	ch_s_cflag;		/* Realport CFLAG */
-	ushort	ch_s_iflag;		/* Realport IFLAG */
-	ushort	ch_s_oflag;		/* Realport OFLAG */
-	ushort	ch_s_xflag;		/* Realport XFLAG */
-
-	u8	ch_otype;		/* Open request type */
-	u8	ch_pscan_savechar;	/* Last character read by parity scan */
-	u8	ch_pscan_state;		/* PScan State based on last 2 chars */
-	u8	ch_otype_waiting;	/* Type of open pending in server */
-	u8	ch_flush_seq;		/* Receive flush end sequence */
-	u8	ch_s_mlast;		/* Realport MLAST */
-
-	u8	ch_mout;		/* Local MOUT */
-	u8	ch_mflow;		/* Local MFLOW */
-	u8	ch_mctrl;		/* Local MCTRL */
-	u8	ch_xon;			/* Local XON */
-	u8	ch_xoff;		/* Local XOFF */
-	u8	ch_lnext;		/* Local LNEXT */
-	u8	ch_xxon;		/* Local XXON */
-	u8	ch_xxoff;		/* Local XXOFF */
-
-	u8	ch_s_mout;		/* Realport MOUT */
-	u8	ch_s_mflow;		/* Realport MFLOW */
-	u8	ch_s_mctrl;		/* Realport MCTRL */
-	u8	ch_s_xon;		/* Realport XON */
-	u8	ch_s_xoff;		/* Realport XOFF */
-	u8	ch_s_lnext;		/* Realport LNEXT */
-	u8	ch_s_xxon;		/* Realport XXON */
-	u8	ch_s_xxoff;		/* Realport XXOFF */
-
-	wait_queue_head_t ch_flag_wait;	/* Wait queue for ch_flag changes */
-	wait_queue_head_t ch_sleep;	/* Wait queue for my_sleep() */
-
-	int	ch_custom_speed;	/* Realport custom speed */
-	int	ch_txcount;		/* Running TX count */
-	int	ch_rxcount;		/* Running RX count */
-};
-
-
-/************************************************************************
- * Node State definitions.
- ************************************************************************/
-
-enum dgrp_nd_state_t {
-	NS_CLOSED = 0,	   /* Network device is closed */
-	NS_IDLE = 1,	   /* Network connection inactive */
-	NS_SEND_QUERY =	2, /* Send server query */
-	NS_WAIT_QUERY =	3, /* Wait for query response */
-	NS_READY = 4,	   /* Network ready */
-	NS_SEND_ERROR =	5  /* Must send error hangup */
-};
-
-#define ND_STATE_STR(x) \
-	((x) == NS_CLOSED     ? "CLOSED"     : \
-	((x) == NS_IDLE	      ? "IDLE"	     : \
-	((x) == NS_SEND_QUERY ? "SEND_QUERY" : \
-	((x) == NS_WAIT_QUERY ? "WAIT_QUERY" : \
-	((x) == NS_READY      ? "READY"	     : \
-	((x) == NS_SEND_ERROR ? "SEND_ERROR" : "UNKNOWN"))))))
-
-/************************************************************************
- * Node Flag definitions.
- ************************************************************************/
-
-#define ND_SELECT	0x0001		/* Multiple net read selects */
-#define ND_DEB_WAIT	0x0002		/* Debug Device waiting */
-
-
-/************************************************************************
- * Monitoring flag definitions.
- ************************************************************************/
-
-#define MON_WAIT_DATA	0x0001		/* Waiting for buffer data */
-#define MON_WAIT_SPACE	0x0002		/* Waiting for buffer space */
-
-/************************************************************************
- * DPA flag definitions.
- ************************************************************************/
-
-#define DPA_WAIT_DATA	0x0001		/* Waiting for buffer data */
-#define DPA_WAIT_SPACE	0x0002		/* Waiting for buffer space */
-
-
-/************************************************************************
- * Definitions taken from Realport Dump.
- ************************************************************************/
-
-#define RPDUMP_MAGIC	"Digi-RealPort-1.0"
-
-#define RPDUMP_MESSAGE	0xE2		/* Descriptive message */
-#define RPDUMP_RESET	0xE7		/* Connection reset */
-#define RPDUMP_CLIENT	0xE8		/* Client data */
-#define RPDUMP_SERVER	0xE9		/* Server data */
-
-
-/************************************************************************
- * Node request/response definitions.
- ************************************************************************/
-
-#define NR_ECHO		0x0001		/* Server echo packet */
-#define NR_IDENT	0x0002		/* Server Product ID */
-#define NR_CAPABILITY	0x0004		/* Server Capabilties */
-#define NR_VPD		0x0008		/* Server VPD, if any */
-#define NR_PASSWORD	0x0010		/* Server Password */
-
-/************************************************************************
- * Registration status of the node's Linux struct tty_driver structures.
- ************************************************************************/
-#define SERIAL_TTDRV_REG   0x0001     /* nd_serial_ttdriver registered	*/
-#define CALLOUT_TTDRV_REG  0x0002     /* nd_callout_ttdriver registered */
-#define XPRINT_TTDRV_REG   0x0004     /* nd_xprint_ttdriver registered	*/
-
-
-/************************************************************************
- * Node structure.  There exists one of these for each associated
- * realport server.
- ************************************************************************/
-
-struct nd_struct {
-	struct list_head	list;
-	long	      nd_major;		   /* Node's major number	    */
-	long	      nd_ID;		   /* Node's ID code		    */
-
-	char	      nd_serial_name[50];   /* "tty_dgrp_<id>_" + null	    */
-	char	      nd_callout_name[50];  /* "cu_dgrp_<id>_" + null	    */
-	char	      nd_xprint_name[50];   /* "pr_dgrp_<id>_" + null	    */
-
-	char	     password[16];	  /* Password for server, if needed */
-	int	     nd_tty_ref_cnt;	  /* Linux tty reference count	   */
-
-	struct proc_dir_entry *nd_net_de; /* Dir entry for /proc/dgrp/net  */
-	struct proc_dir_entry *nd_mon_de; /* Dir entry for /proc/dgrp/mon  */
-	struct proc_dir_entry *nd_ports_de; /* Dir entry for /proc/dgrp/ports*/
-	struct proc_dir_entry *nd_dpa_de; /* Dir entry for /proc/dgrp/dpa  */
-
-	spinlock_t nd_lock;		  /* General node lock		   */
-
-	struct semaphore nd_net_semaphore; /* Net read/write lock	    */
-	struct semaphore nd_mon_semaphore; /* Monitor buffer lock	    */
-	spinlock_t nd_dpa_lock;		/* DPA buffer lock	     */
-
-	enum dgrp_nd_state_t nd_state;	  /* NS_* network state */
-	int	      nd_chan_count;	   /* # active channels		    */
-	int	      nd_flag;		   /* Node flags		    */
-	int	      nd_send;		   /* Responses to send		    */
-	int	      nd_expect;	   /* Responses we expect	    */
-
-	u8	 *nd_iobuf;	       /* Network R/W Buffer		*/
-	wait_queue_head_t nd_tx_waitq;	  /* Network select wait queue	   */
-
-	u8	 *nd_inputbuf;	       /* Input Buffer			*/
-	u8	 *nd_inputflagbuf;     /* Input Flags Buffer		*/
-
-	int	      nd_tx_deposit;	   /* Accumulated transmit deposits */
-	int	      nd_tx_charge;	   /* Accumulated transmit charges  */
-	int	      nd_tx_credit;	   /* Current TX credit		    */
-	int	      nd_tx_ready;	   /* Ready to transmit		    */
-	int	      nd_tx_work;	   /* TX work waiting		    */
-	ulong	     nd_tx_time;	  /* Last transmit time		   */
-	ulong	     nd_poll_time;	  /* Next scheduled poll time	   */
-
-	int	      nd_delay;		   /* Current TX delay		    */
-	int	      nd_rate;		   /* Current TX rate		    */
-	struct link_struct nd_link;		/* Link speed params.		 */
-
-	int	      nd_seq_in;	   /* TX seq in ptr		    */
-	int	      nd_seq_out;	   /* TX seq out ptr		    */
-	int	      nd_unack;		   /* Unacknowledged byte count	    */
-	int	      nd_remain;	   /* Remaining receive bytes	    */
-	int	      nd_tx_module;	   /* Current TX module #	    */
-	int	      nd_rx_module;	   /* Current RX module #	    */
-	char	     *nd_error;		   /* Protocol error message	    */
-
-	int	      nd_write_count;	   /* drp_write() call count	    */
-	int	      nd_read_count;	   /* drp_read() count		    */
-	int	      nd_send_count;	   /* TCP message sent		    */
-	int	      nd_tx_byte;	   /* Transmit byte count	    */
-	int	      nd_rx_byte;	   /* Receive byte count	    */
-
-	ulong	     nd_mon_lbolt;	 /* Monitor start time		   */
-	int	      nd_mon_flag;	  /* Monitor flags		    */
-	int	      nd_mon_in;	  /* Monitor in pointer		    */
-	int	      nd_mon_out;	  /* Monitor out pointer	    */
-	wait_queue_head_t nd_mon_wqueue;  /* Monitor wait queue (on flags)  */
-	u8	 *nd_mon_buf;	      /* Monitor buffer			*/
-
-	ulong	     nd_dpa_lbolt;	/* DPA start time	      */
-	int	     nd_dpa_flag;	/* DPA flags		      */
-	int	     nd_dpa_in;		/* DPA in pointer	      */
-	int	     nd_dpa_out;	/* DPA out pointer	      */
-	wait_queue_head_t nd_dpa_wqueue; /* DPA wait queue (on flags)  */
-	u8	  *nd_dpa_buf;	/* DPA buffer		      */
-
-	uint	     nd_dpa_debug;
-	uint	     nd_dpa_port;
-
-	wait_queue_head_t nd_seq_wque[SEQ_MAX];	  /* TX thread wait queues */
-	u8	  nd_seq_wait[SEQ_MAX];	  /* Transmit thread wait count */
-
-	ushort	     nd_seq_size[SEQ_MAX];   /* Transmit seq packet size   */
-	ulong	     nd_seq_time[SEQ_MAX];   /* Transmit seq packet time   */
-
-	ushort	     nd_hw_ver;		  /* HW version returned from PS   */
-	ushort	     nd_sw_ver;		  /* SW version returned from PS   */
-	uint	     nd_hw_id;		  /* HW ID returned from PS	   */
-	u8	  nd_ps_desc[MAX_DESC_LEN];  /* Description from PS	*/
-	uint	     nd_vpd_len;		/* VPD len, if any */
-	u8	     nd_vpd[VPDSIZE];		/* VPD, if any */
-
-	ulong	     nd_ttdriver_flags;	  /* Registration status	    */
-	struct tty_driver *nd_serial_ttdriver;	/* Linux TTYDRIVER structure */
-	struct tty_driver *nd_callout_ttdriver; /* Linux TTYDRIVER structure */
-	struct tty_driver *nd_xprint_ttdriver;	/* Linux TTYDRIVER structure */
-
-	u8	     *nd_writebuf;		/* Used to cache data read
-						 * from user
-						 */
-	struct ch_struct nd_chan[CHAN_MAX];  /* Channel array		    */
-	struct device *nd_class_dev;	/* Hang our sysfs stuff off of here */
-};
-
-#endif /* __DRP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/dgrp/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-config DGRP
-       tristate "Digi Realport driver"
-       default n
-       depends on SYSFS && TTY
-       ---help---
-       Support for Digi Realport devices.  These devices allow you to
-       access remote serial ports as if they are local tty devices.  This
-       will build the kernel driver, you will still need the userspace
-       component to make your Realport device work.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/Makefile
--- linux-libre-3.16-gnu/drivers/staging/dgrp/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-obj-$(CONFIG_DGRP) += dgrp.o
-
-dgrp-y := 			\
-	dgrp_common.o 		\
-	dgrp_dpa_ops.o 		\
-	dgrp_driver.o 		\
-	dgrp_mon_ops.o 	 	\
-	dgrp_net_ops.o 		\
-	dgrp_ports_ops.o 	\
-	dgrp_specproc.o 	\
-	dgrp_tty.o 		\
-	dgrp_sysfs.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/README linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/README
--- linux-libre-3.16-gnu/drivers/staging/dgrp/README	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/README	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-The user space code to work with this driver is located at
-https://github.com/wfp5p/dgrp-utils
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/dgrp/TODO linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/TODO
--- linux-libre-3.16-gnu/drivers/staging/dgrp/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/dgrp/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-- Use configfs for config stuff.  This will require changes to the
-  user space code.
-
-- dgrp_send() and dgrp_receive() could use some refactoring
-
-- Don't automatically create CHAN_MAX (64) channel array entries for
-  every device as many devices are going to have much less than 64
-  channels.
-
-- The locking needs to be checked.  It seems haphazardly done in most
-  places.
-
-- Check Kconfig dependencies
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/emxx_udc/emxx_udc.c linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/emxx_udc.c
--- linux-libre-3.16-gnu/drivers/staging/emxx_udc/emxx_udc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/emxx_udc.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,3520 @@
+/*
+ *  drivers/usb/gadget/emxx_udc.c
+ *     EMXX FCD (Function Controller Driver) for USB.
+ *
+ *  Copyright (C) 2010 Renesas Electronics Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include "emxx_udc.h"
+
+#define	DRIVER_DESC	"EMXX UDC driver"
+#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+static const char	driver_name[] = "emxx_udc";
+static const char	driver_desc[] = DRIVER_DESC;
+
+/*===========================================================================*/
+/* Prototype */
+static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *, struct nbu2ss_ep *);
+static void _nbu2ss_ep0_enable(struct nbu2ss_udc *);
+/*static void _nbu2ss_ep0_disable(struct nbu2ss_udc *);*/
+static void _nbu2ss_ep_done(struct nbu2ss_ep *, struct nbu2ss_req *, int);
+static void _nbu2ss_set_test_mode(struct nbu2ss_udc *, u32 mode);
+static void _nbu2ss_endpoint_toggle_reset(struct nbu2ss_udc *udc, u8 ep_adrs);
+
+static int _nbu2ss_pullup(struct nbu2ss_udc *, int);
+static void _nbu2ss_fifo_flush(struct nbu2ss_udc *, struct nbu2ss_ep *);
+
+/*===========================================================================*/
+/* Macro */
+#define	_nbu2ss_zero_len_pkt(udc, epnum)	\
+	_nbu2ss_ep_in_end(udc, epnum, 0, 0)
+
+
+/*===========================================================================*/
+/* Global */
+struct nbu2ss_udc udc_controller;
+
+
+/*-------------------------------------------------------------------------*/
+/* Read */
+static inline u32 _nbu2ss_readl(void *address)
+{
+	return __raw_readl(address) ;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Write */
+static inline void _nbu2ss_writel(void *address, u32 udata)
+{
+	__raw_writel(udata, address) ;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Set Bit */
+static inline void _nbu2ss_bitset(void *address, u32 udata)
+{
+	u32	reg_dt = __raw_readl(address) | (udata);
+	__raw_writel(reg_dt, address) ;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Clear Bit */
+static inline void _nbu2ss_bitclr(void *address, u32 udata)
+{
+	u32	reg_dt = __raw_readl(address) & ~(udata);
+	__raw_writel(reg_dt, address) ;
+}
+
+#ifdef UDC_DEBUG_DUMP
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_dump_register(struct nbu2ss_udc *udc)
+{
+	int		i;
+	u32 reg_data;
+
+	pr_info("=== %s()\n", __func__);
+
+	if (udc == NULL) {
+		ERR("%s udc == NULL\n", __func__);
+		return;
+	}
+
+	spin_unlock(&udc->lock);
+
+	printk(KERN_DEBUG "\n-USB REG-\n");
+	for (i = 0x0 ; i < USB_BASE_SIZE ; i += 16) {
+		reg_data =   _nbu2ss_readl(
+			(u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i));
+		printk(KERN_DEBUG "USB%04x =%08x", i, (int)reg_data);
+
+		reg_data =  _nbu2ss_readl(
+			(u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 4));
+		printk(KERN_DEBUG " %08x", (int)reg_data);
+
+		reg_data =  _nbu2ss_readl(
+			(u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 8));
+		printk(KERN_DEBUG " %08x", (int)reg_data);
+
+		reg_data =  _nbu2ss_readl(
+			(u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 12));
+		printk(KERN_DEBUG " %08x\n", (int)reg_data);
+
+	}
+
+	spin_lock(&udc->lock);
+}
+#endif /* UDC_DEBUG_DUMP */
+
+/*-------------------------------------------------------------------------*/
+/* Endpoint 0 Callback (Complete) */
+static void _nbu2ss_ep0_complete(struct usb_ep *_ep, struct usb_request *_req)
+{
+	u8		recipient;
+	u16		selector;
+	u32		test_mode;
+	struct usb_ctrlrequest	*p_ctrl;
+	struct nbu2ss_udc *udc;
+
+	if ((_ep == NULL) || (_req == NULL))
+		return;
+
+	udc = (struct nbu2ss_udc *)_req->context;
+	p_ctrl = &udc->ctrl;
+	if ((p_ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+
+		if (p_ctrl->bRequest == USB_REQ_SET_FEATURE) {
+			/*-------------------------------------------------*/
+			/* SET_FEATURE */
+			recipient = (u8)(p_ctrl->bRequestType & USB_RECIP_MASK);
+			selector  = p_ctrl->wValue;
+			if ((recipient == USB_RECIP_DEVICE) &&
+				(selector == USB_DEVICE_TEST_MODE)) {
+				test_mode = (u32)(p_ctrl->wIndex >> 8);
+				_nbu2ss_set_test_mode(udc, test_mode);
+			}
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+/* Initialization usb_request */
+static void _nbu2ss_create_ep0_packet(
+	struct nbu2ss_udc *udc,
+	void *p_buf,
+	unsigned length
+)
+{
+	udc->ep0_req.req.buf		= p_buf;
+	udc->ep0_req.req.length		= length;
+	udc->ep0_req.req.dma		= 0;
+	udc->ep0_req.req.zero		= TRUE;
+	udc->ep0_req.req.complete	= _nbu2ss_ep0_complete;
+	udc->ep0_req.req.status		= -EINPROGRESS;
+	udc->ep0_req.req.context	= udc;
+	udc->ep0_req.req.actual		= 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Acquisition of the first address of RAM(FIFO) */
+static u32 _nbu2ss_get_begin_ram_address(struct nbu2ss_udc *udc)
+{
+	u32		num, buf_type;
+	u32		data, last_ram_adr, use_ram_size;
+
+	PT_EP_REGS	p_ep_regs;
+
+	last_ram_adr = (D_RAM_SIZE_CTRL / sizeof(u32)) * 2;
+	use_ram_size = 0;
+
+	for (num = 0; num < NUM_ENDPOINTS - 1; num++) {
+		p_ep_regs = &udc->p_regs->EP_REGS[num];
+		data = _nbu2ss_readl(&p_ep_regs->EP_PCKT_ADRS);
+		buf_type = _nbu2ss_readl(&p_ep_regs->EP_CONTROL) & EPn_BUF_TYPE;
+		if (buf_type == 0) {
+			/* Single Buffer */
+			use_ram_size += (data & EPn_MPKT) / sizeof(u32);
+		} else {
+			/* Double Buffer */
+			use_ram_size += ((data & EPn_MPKT) / sizeof(u32)) * 2;
+		}
+
+		if ((data >> 16) > last_ram_adr)
+			last_ram_adr = data>>16;
+	}
+
+	return last_ram_adr + use_ram_size;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Construction of Endpoint */
+static int _nbu2ss_ep_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	u32		num;
+	u32		data;
+	u32		begin_adrs;
+
+	if (ep->epnum == 0)
+		return	-EINVAL;
+
+	num = ep->epnum - 1;
+
+	/*-------------------------------------------------------------*/
+	/* RAM Transfer Address */
+	begin_adrs = _nbu2ss_get_begin_ram_address(udc);
+	data = (begin_adrs << 16) | ep->ep.maxpacket;
+	_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_PCKT_ADRS, data);
+
+	/*-------------------------------------------------------------*/
+	/* Interrupt Enable */
+	data = 1 << (ep->epnum + 8);
+	_nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, data);
+
+	/*-------------------------------------------------------------*/
+	/* Endpoint Type(Mode) */
+	/*   Bulk, Interrupt, ISO */
+	switch (ep->ep_type) {
+	case USB_ENDPOINT_XFER_BULK:
+		data = EPn_BULK;
+		break;
+
+	case USB_ENDPOINT_XFER_INT:
+		data = EPn_BUF_SINGLE | EPn_INTERRUPT;
+		break;
+
+	case USB_ENDPOINT_XFER_ISOC:
+		data = EPn_ISO;
+		break;
+
+	default:
+		data = 0;
+		break;
+	}
+
+	_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+	_nbu2ss_endpoint_toggle_reset(udc, (ep->epnum|ep->direct));
+
+	if (ep->direct == USB_DIR_OUT) {
+		/*---------------------------------------------------------*/
+		/* OUT */
+		data = EPn_EN | EPn_BCLR | EPn_DIR0;
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = (EPn_ONAK | EPn_OSTL_EN | EPn_OSTL);
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = (EPn_OUT_EN | EPn_OUT_END_EN);
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
+	} else {
+		/*---------------------------------------------------------*/
+		/* IN */
+		data = (EPn_EN | EPn_BCLR | EPn_AUTO);
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = (EPn_ISTL);
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = (EPn_IN_EN | EPn_IN_END_EN);
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Release of Endpoint */
+static int _nbu2ss_epn_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	u32		num;
+	u32		data;
+
+	if ((ep->epnum == 0) || (udc->vbus_active == 0))
+		return	-EINVAL;
+
+	num = ep->epnum - 1;
+
+	/*-------------------------------------------------------------*/
+	/* RAM Transfer Address */
+	_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_PCKT_ADRS, 0);
+
+	/*-------------------------------------------------------------*/
+	/* Interrupt Disable */
+	data = 1 << (ep->epnum + 8);
+	_nbu2ss_bitclr(&udc->p_regs->USB_INT_ENA, data);
+
+	if (ep->direct == USB_DIR_OUT) {
+		/*---------------------------------------------------------*/
+		/* OUT */
+		data = EPn_ONAK | EPn_BCLR;
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = EPn_EN | EPn_DIR0;
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = EPn_OUT_EN | EPn_OUT_END_EN;
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
+	} else {
+		/*---------------------------------------------------------*/
+		/* IN */
+		data = EPn_BCLR;
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = EPn_EN | EPn_AUTO;
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+
+		data = EPn_IN_EN | EPn_IN_END_EN;
+		_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* DMA setting (without Endpoint 0) */
+static void _nbu2ss_ep_dma_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	u32		num;
+	u32		data;
+
+	data = _nbu2ss_readl(&udc->p_regs->USBSSCONF);
+	if (((ep->epnum == 0) || (data & (1 << ep->epnum)) == 0))
+		return;		/* Not Support DMA */
+
+	num = ep->epnum - 1;
+
+	if (ep->direct == USB_DIR_OUT) {
+		/*---------------------------------------------------------*/
+		/* OUT */
+		data = ep->ep.maxpacket;
+		_nbu2ss_writel(&udc->p_regs->EP_DCR[num].EP_DCR2, data);
+
+		/*---------------------------------------------------------*/
+		/* Transfer Direct */
+		data = DCR1_EPn_DIR0;
+		_nbu2ss_bitset(&udc->p_regs->EP_DCR[num].EP_DCR1, data);
+
+		/*---------------------------------------------------------*/
+		/* DMA Mode etc. */
+		data = EPn_STOP_MODE | EPn_STOP_SET  | EPn_DMAMODE0;
+		_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
+	} else {
+		/*---------------------------------------------------------*/
+		/* IN */
+		_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+
+		/*---------------------------------------------------------*/
+		/* DMA Mode etc. */
+		data = EPn_BURST_SET | EPn_DMAMODE0;
+		_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+/* DMA setting release */
+static void _nbu2ss_ep_dma_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	u32		num;
+	u32		data;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (udc->vbus_active == 0)
+		return;		/* VBUS OFF */
+
+	data = _nbu2ss_readl(&preg->USBSSCONF);
+	if ((ep->epnum == 0) || ((data & (1 << ep->epnum)) == 0))
+		return;		/* Not Support DMA */
+
+	num = ep->epnum - 1;
+
+	_nbu2ss_ep_dma_abort(udc, ep);
+
+	if (ep->direct == USB_DIR_OUT) {
+		/*---------------------------------------------------------*/
+		/* OUT */
+		_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, 0);
+		_nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_DIR0);
+		_nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
+	} else {
+		/*---------------------------------------------------------*/
+		/* IN */
+		_nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+		_nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+/* Abort DMA */
+static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	PT_FC_REGS	preg = udc->p_regs;
+
+	_nbu2ss_bitclr(&preg->EP_DCR[ep->epnum-1].EP_DCR1, DCR1_EPn_REQEN);
+	mdelay(DMA_DISABLE_TIME);	/* DCR1_EPn_REQEN Clear */
+	_nbu2ss_bitclr(&preg->EP_REGS[ep->epnum-1].EP_DMA_CTRL, EPn_DMA_EN);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Start IN Transfer */
+static void _nbu2ss_ep_in_end(
+	struct nbu2ss_udc *udc,
+	u32 epnum,
+	u32 data32,
+	u32 length
+)
+{
+	u32		data;
+	u32		num;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (length >= sizeof(u32))
+		return;
+
+	if (epnum == 0) {
+		_nbu2ss_bitclr(&preg->EP0_CONTROL, EP0_AUTO);
+
+		/* Writing of 1-4 bytes */
+		if (length)
+			_nbu2ss_writel(&preg->EP0_WRITE, data32);
+
+		data = ((length << 5) & EP0_DW) | EP0_DEND;
+		_nbu2ss_writel(&preg->EP0_CONTROL, data);
+
+		_nbu2ss_bitset(&preg->EP0_CONTROL, EP0_AUTO);
+	} else {
+		num = epnum - 1;
+
+		_nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+
+		/* Writing of 1-4 bytes */
+		if (length)
+			_nbu2ss_writel(&preg->EP_REGS[num].EP_WRITE, data32);
+
+		data = (((((u32)length) << 5) & EPn_DW) | EPn_DEND);
+		_nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
+
+		_nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+	}
+
+	return;
+}
+
+#ifdef USE_DMA
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_dma_map_single(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u8		direct
+)
+{
+	if (req->req.dma == DMA_ADDR_INVALID) {
+		if (req->unaligned)
+			req->req.dma = ep->phys_buf;
+		else {
+			req->req.dma = dma_map_single(
+				udc->gadget.dev.parent,
+				req->req.buf,
+				req->req.length,
+				(direct == USB_DIR_IN)
+				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		}
+		req->mapped = 1;
+	} else {
+		if (!req->unaligned)
+			dma_sync_single_for_device(
+				udc->gadget.dev.parent,
+				req->req.dma,
+				req->req.length,
+				(direct == USB_DIR_IN)
+				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		req->mapped = 0;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_dma_unmap_single(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u8		direct
+)
+{
+	u8		data[4];
+	u8		*p;
+	u32		count = 0;
+
+	if (direct == USB_DIR_OUT) {
+		count = req->req.actual % 4;
+		if (count) {
+			p = req->req.buf;
+			p += (req->req.actual - count);
+			memcpy(data, p, count);
+		}
+	}
+
+	if (req->mapped) {
+		if (req->unaligned) {
+			if (direct == USB_DIR_OUT)
+				memcpy(req->req.buf, ep->virt_buf,
+					req->req.actual & 0xfffffffc);
+		} else
+			dma_unmap_single(udc->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				(direct == USB_DIR_IN)
+				? DMA_TO_DEVICE
+				: DMA_FROM_DEVICE);
+		req->req.dma = DMA_ADDR_INVALID;
+		req->mapped = 0;
+	} else {
+		if (!req->unaligned)
+			dma_sync_single_for_cpu(udc->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				(direct == USB_DIR_IN)
+				? DMA_TO_DEVICE
+				: DMA_FROM_DEVICE);
+	}
+
+	if (count) {
+		p = req->req.buf;
+		p += (req->req.actual - count);
+		memcpy(p, data, count);
+	}
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Endpoint 0 OUT Transfer (PIO) */
+static int EP0_out_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
+{
+	u32		i;
+	int		nret   = 0;
+	u32		iWordLength = 0;
+	USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+
+	/*------------------------------------------------------------*/
+	/* Read Length */
+	iWordLength = length / sizeof(u32);
+
+	/*------------------------------------------------------------*/
+	/* PIO Read */
+	if (iWordLength) {
+		for (i = 0; i < iWordLength; i++) {
+			pBuf32->dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
+			pBuf32++;
+		}
+		nret = iWordLength * sizeof(u32);
+	}
+
+	return nret;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Endpoint 0 OUT Transfer (PIO, OverBytes) */
+static int EP0_out_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
+{
+	u32		i;
+	u32		iReadSize = 0;
+	USB_REG_ACCESS  Temp32;
+	USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+
+	if ((0 < length) && (length < sizeof(u32))) {
+		Temp32.dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
+		for (i = 0 ; i < length ; i++)
+			pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
+		iReadSize += length;
+	}
+
+	return iReadSize;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Endpoint 0 IN Transfer (PIO) */
+static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
+{
+	u32		i;
+	u32		iMaxLength   = EP0_PACKETSIZE;
+	u32		iWordLength  = 0;
+	u32		iWriteLength = 0;
+	USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+
+	/*------------------------------------------------------------*/
+	/* Transfer Length */
+	if (iMaxLength < length)
+		iWordLength = iMaxLength / sizeof(u32);
+	else
+		iWordLength = length / sizeof(u32);
+
+	/*------------------------------------------------------------*/
+	/* PIO */
+	for (i = 0; i < iWordLength; i++) {
+		_nbu2ss_writel(&udc->p_regs->EP0_WRITE, pBuf32->dw);
+		pBuf32++;
+		iWriteLength += sizeof(u32);
+	}
+
+	return iWriteLength;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Endpoint 0 IN Transfer (PIO, OverBytes) */
+static int EP0_in_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 iRemainSize)
+{
+	u32		i;
+	USB_REG_ACCESS Temp32;
+	USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+
+	if ((0 < iRemainSize) && (iRemainSize < sizeof(u32))) {
+		for (i = 0 ; i < iRemainSize ; i++)
+			Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
+		_nbu2ss_ep_in_end(udc, 0, Temp32.dw, iRemainSize);
+
+		return iRemainSize;
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Transfer NULL Packet (Epndoint 0) */
+static int EP0_send_NULL(struct nbu2ss_udc *udc, bool pid_flag)
+{
+	u32		data;
+
+	data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
+	data &= ~(u32)EP0_INAK;
+
+	if (pid_flag)
+		data |= (EP0_INAK_EN | EP0_PIDCLR | EP0_DEND);
+	else
+		data |= (EP0_INAK_EN | EP0_DEND);
+
+	_nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Receive NULL Packet (Endpoint 0) */
+static int EP0_receive_NULL(struct nbu2ss_udc *udc, bool pid_flag)
+{
+	u32		data;
+
+	data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
+	data &= ~(u32)EP0_ONAK;
+
+	if (pid_flag)
+		data |= EP0_PIDCLR;
+
+	_nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_ep0_in_transfer(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req
+)
+{
+	u8		*pBuffer;			/* IN Data Buffer */
+	u32		data;
+	u32		iRemainSize = 0;
+	int		result = 0;
+
+	/*-------------------------------------------------------------*/
+	/* End confirmation */
+	if (req->req.actual == req->req.length) {
+		if ((req->req.actual % EP0_PACKETSIZE) == 0) {
+			if (req->zero) {
+				req->zero = 0;
+				EP0_send_NULL(udc, FALSE);
+				return 1;
+			}
+		}
+
+		return 0;		/* Transfer End */
+	}
+
+	/*-------------------------------------------------------------*/
+	/* NAK release */
+	data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
+	data |= EP0_INAK_EN;
+	data &= ~(u32)EP0_INAK;
+	_nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
+
+	iRemainSize = req->req.length - req->req.actual;
+	pBuffer = (u8 *)req->req.buf;
+	pBuffer += req->req.actual;
+
+	/*-------------------------------------------------------------*/
+	/* Data transfer */
+	result = EP0_in_PIO(udc, pBuffer, iRemainSize);
+
+	req->div_len = result;
+	iRemainSize -= result;
+
+	if (iRemainSize == 0) {
+		EP0_send_NULL(udc, FALSE);
+		return result;
+	}
+
+	if ((iRemainSize < sizeof(u32)) && (result != EP0_PACKETSIZE)) {
+		pBuffer += result;
+		result += EP0_in_OverBytes(udc, pBuffer, iRemainSize);
+		req->div_len = result;
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_ep0_out_transfer(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req
+)
+{
+	u8		*pBuffer;
+	u32		iRemainSize;
+	u32		iRecvLength;
+	int		result = 0;
+	int		fRcvZero;
+
+	/*-------------------------------------------------------------*/
+	/* Receive data confirmation */
+	iRecvLength = _nbu2ss_readl(&udc->p_regs->EP0_LENGTH) & EP0_LDATA;
+	if (iRecvLength != 0) {
+
+		fRcvZero = 0;
+
+		iRemainSize = req->req.length - req->req.actual;
+		pBuffer = (u8 *)req->req.buf;
+		pBuffer += req->req.actual;
+
+		result = EP0_out_PIO(udc, pBuffer
+					, min(iRemainSize, iRecvLength));
+		if (result < 0)
+			return result;
+
+		req->req.actual += result;
+		iRecvLength -= result;
+
+		if ((0 < iRecvLength) && (iRecvLength < sizeof(u32))) {
+			pBuffer += result;
+			iRemainSize -= result;
+
+			result = EP0_out_OverBytes(udc, pBuffer
+					, min(iRemainSize, iRecvLength));
+			req->req.actual += result;
+		}
+	} else {
+		fRcvZero = 1;
+	}
+
+	/*-------------------------------------------------------------*/
+	/* End confirmation */
+	if (req->req.actual == req->req.length) {
+		if ((req->req.actual % EP0_PACKETSIZE) == 0) {
+			if (req->zero) {
+				req->zero = 0;
+				EP0_receive_NULL(udc, FALSE);
+				return 1;
+			}
+		}
+
+		return 0;		/* Transfer End */
+	}
+
+	if ((req->req.actual % EP0_PACKETSIZE) != 0)
+		return 0;		/* Short Packet Transfer End */
+
+	if (req->req.actual > req->req.length) {
+		ERR(" *** Overrun Error\n");
+		return -EOVERFLOW;
+	}
+
+	if (fRcvZero != 0) {
+		iRemainSize = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
+		if (iRemainSize & EP0_ONAK) {
+			/*---------------------------------------------------*/
+			/* NACK release */
+			_nbu2ss_bitclr(&udc->p_regs->EP0_CONTROL, EP0_ONAK);
+		}
+		result = 1;
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_out_dma(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_req *req,
+	u32		num,
+	u32		length
+)
+{
+	u8		*pBuffer;
+	u32		mpkt;
+	u32		lmpkt;
+	u32		dmacnt;
+	u32		burst = 1;
+	u32		data;
+	int		result = -EINVAL;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (req->dma_flag)
+		return 1;		/* DMA is forwarded */
+
+	req->dma_flag = TRUE;
+	pBuffer = (u8 *)req->req.dma;
+	pBuffer += req->req.actual;
+
+	/* DMA Address */
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
+
+	/* Number of transfer packets */
+	mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
+	dmacnt = (length / mpkt);
+	lmpkt = (length % mpkt) & ~(u32)0x03;
+
+	if (DMA_MAX_COUNT < dmacnt) {
+		dmacnt = DMA_MAX_COUNT;
+		lmpkt = 0;
+	} else if (0 != lmpkt) {
+		if (0 == dmacnt)
+			burst = 0;	/* Burst OFF */
+		dmacnt++;
+	}
+
+	data = mpkt | (lmpkt << 16);
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
+
+	data = ((dmacnt & 0xff) << 16) | DCR1_EPn_DIR0 | DCR1_EPn_REQEN;
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
+
+	if (0 == burst) {
+		_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, 0);
+		_nbu2ss_bitclr(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
+	} else {
+		_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT
+				, (dmacnt << 16));
+		_nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
+	}
+	_nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
+
+	result = length & ~(u32)0x03;
+	req->div_len = result;
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_out_pio(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u32		length
+)
+{
+	u8		*pBuffer;
+	u32		i;
+	u32		data;
+	u32		iWordLength;
+	USB_REG_ACCESS	Temp32;
+	USB_REG_ACCESS	*pBuf32;
+	int		result = 0;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (req->dma_flag)
+		return 1;		/* DMA is forwarded */
+
+	if (length == 0)
+		return 0;
+
+	pBuffer = (u8 *)req->req.buf;
+	pBuf32 = (USB_REG_ACCESS *)(pBuffer + req->req.actual);
+
+	iWordLength = length / sizeof(u32);
+	if (iWordLength > 0) {
+		/*---------------------------------------------------------*/
+		/* Copy of every four bytes */
+		for (i = 0; i < iWordLength; i++) {
+			pBuf32->dw =
+			_nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ);
+			pBuf32++;
+		}
+		result = iWordLength * sizeof(u32);
+	}
+
+	data = length - result;
+	if (data > 0) {
+		/*---------------------------------------------------------*/
+		/* Copy of fraction byte */
+		Temp32.dw = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ);
+		for (i = 0 ; i < data ; i++)
+			pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
+		result += data;
+	}
+
+	req->req.actual += result;
+
+	if ((req->req.actual == req->req.length)
+			|| ((req->req.actual % ep->ep.maxpacket) != 0)) {
+
+		result = 0;
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_out_data(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u32		data_size
+)
+{
+	u32		num;
+	u32		iBufSize;
+	int		nret = 1;
+
+	if (ep->epnum == 0)
+		return -EINVAL;
+
+	num = ep->epnum - 1;
+
+	iBufSize = min((req->req.length - req->req.actual), data_size);
+
+	if ((ep->ep_type != USB_ENDPOINT_XFER_INT)
+		&& (req->req.dma != 0)
+		&& (iBufSize  >= sizeof(u32))) {
+		nret = _nbu2ss_out_dma(udc, req, num, iBufSize);
+	} else {
+		iBufSize = min(iBufSize, (u32)ep->ep.maxpacket);
+		nret = _nbu2ss_epn_out_pio(udc, ep, req, iBufSize);
+	}
+
+	return nret;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_out_transfer(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req
+)
+{
+	u32		num;
+	u32		iRecvLength;
+	int		result = 1;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (ep->epnum == 0)
+		return -EINVAL;
+
+	num = ep->epnum - 1;
+
+	/*-------------------------------------------------------------*/
+	/* Receive Length */
+	iRecvLength
+		= _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT) & EPn_LDATA;
+
+	if (iRecvLength != 0) {
+		result = _nbu2ss_epn_out_data(udc, ep, req, iRecvLength);
+		if (iRecvLength < ep->ep.maxpacket) {
+			if (iRecvLength == result) {
+				req->req.actual += result;
+				result = 0;
+			}
+		}
+	} else {
+		if ((req->req.actual == req->req.length)
+			|| ((req->req.actual % ep->ep.maxpacket) != 0)) {
+
+			result = 0;
+		}
+	}
+
+	if (result == 0) {
+		if ((req->req.actual % ep->ep.maxpacket) == 0) {
+			if (req->zero) {
+				req->zero = 0;
+				return 1;
+			}
+		}
+	}
+
+	if (req->req.actual > req->req.length) {
+		ERR(" *** Overrun Error\n");
+		ERR(" *** actual = %d, length = %d\n",
+			req->req.actual, req->req.length);
+		result = -EOVERFLOW;
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_in_dma(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u32		num,
+	u32		length
+)
+{
+	u8		*pBuffer;
+	u32		mpkt;		/* MaxPacketSize */
+	u32		lmpkt;		/* Last Packet Data Size */
+	u32		dmacnt;		/* IN Data Size */
+	u32		iWriteLength;
+	u32		data;
+	int		result = -EINVAL;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (req->dma_flag)
+		return 1;		/* DMA is forwarded */
+
+#ifdef USE_DMA
+	if (req->req.actual == 0)
+		_nbu2ss_dma_map_single(udc, ep, req, USB_DIR_IN);
+#endif
+	req->dma_flag = TRUE;
+
+	/* MAX Packet Size */
+	mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
+
+	if ((DMA_MAX_COUNT * mpkt) < length)
+		iWriteLength = DMA_MAX_COUNT * mpkt;
+	else
+		iWriteLength = length;
+
+	/*------------------------------------------------------------*/
+	/* Number of transmission packets */
+	if (mpkt < iWriteLength) {
+		dmacnt = iWriteLength / mpkt;
+		lmpkt  = (iWriteLength % mpkt) & ~(u32)0x3;
+		if (lmpkt != 0)
+			dmacnt++;
+		else
+			lmpkt = mpkt & ~(u32)0x3;
+
+	} else {
+		dmacnt = 1;
+		lmpkt  = iWriteLength & ~(u32)0x3;
+	}
+
+	/* Packet setting */
+	data = mpkt | (lmpkt << 16);
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
+
+	/* Address setting */
+	pBuffer = (u8 *)req->req.dma;
+	pBuffer += req->req.actual;
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
+
+	/* Packet and DMA setting */
+	data = ((dmacnt & 0xff) << 16) | DCR1_EPn_REQEN;
+	_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
+
+	/* Packet setting of EPC */
+	data = dmacnt << 16;
+	_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, data);
+
+	/*DMA setting of EPC */
+	_nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
+
+	result = iWriteLength & ~(u32)0x3;
+	req->div_len = result;
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_in_pio(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u32		length
+)
+{
+	u8		*pBuffer;
+	u32		i;
+	u32		data;
+	u32		iWordLength;
+	USB_REG_ACCESS	Temp32;
+	USB_REG_ACCESS	*pBuf32 = NULL;
+	int		result = 0;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (req->dma_flag)
+		return 1;		/* DMA is forwarded */
+
+	if (length > 0) {
+		pBuffer = (u8 *)req->req.buf;
+		pBuf32 = (USB_REG_ACCESS *)(pBuffer + req->req.actual);
+
+		iWordLength = length / sizeof(u32);
+		if (iWordLength > 0) {
+			for (i = 0; i < iWordLength; i++) {
+				_nbu2ss_writel(
+					&preg->EP_REGS[ep->epnum-1].EP_WRITE
+					, pBuf32->dw
+				);
+
+				pBuf32++;
+			}
+			result = iWordLength * sizeof(u32);
+		}
+	}
+
+	if (result != ep->ep.maxpacket) {
+		data = length - result;
+		Temp32.dw = 0;
+		for (i = 0 ; i < data ; i++)
+			Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
+
+		_nbu2ss_ep_in_end(udc, ep->epnum, Temp32.dw, data);
+		result += data;
+	}
+
+	req->div_len = result;
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_in_data(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	u32		data_size
+)
+{
+	u32		num;
+	int		nret = 1;
+
+	if (ep->epnum == 0)
+		return -EINVAL;
+
+	num = ep->epnum - 1;
+
+	if ((ep->ep_type != USB_ENDPOINT_XFER_INT)
+		&& (req->req.dma != 0)
+		&& (data_size >= sizeof(u32))) {
+		nret = _nbu2ss_in_dma(udc, ep, req, num, data_size);
+	} else {
+		data_size = min(data_size, (u32)ep->ep.maxpacket);
+		nret = _nbu2ss_epn_in_pio(udc, ep, req, data_size);
+	}
+
+	return nret;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_epn_in_transfer(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req
+)
+{
+	u32		num;
+	u32		iBufSize;
+	int		result = 0;
+	u32		status;
+
+	if (ep->epnum == 0)
+		return -EINVAL;
+
+	num = ep->epnum - 1;
+
+	status = _nbu2ss_readl(&udc->p_regs->EP_REGS[num].EP_STATUS);
+
+	/*-------------------------------------------------------------*/
+	/* State confirmation of FIFO */
+	if (req->req.actual == 0) {
+		if ((status & EPn_IN_EMPTY) == 0)
+			return 1;	/* Not Empty */
+
+	} else {
+		if ((status & EPn_IN_FULL) != 0)
+			return 1;	/* Not Empty */
+	}
+
+	/*-------------------------------------------------------------*/
+	/* Start tranfer */
+	iBufSize = req->req.length - req->req.actual;
+	if (iBufSize > 0)
+		result = _nbu2ss_epn_in_data(udc, ep, req, iBufSize);
+	else if (req->req.length == 0)
+		_nbu2ss_zero_len_pkt(udc, ep->epnum);
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_start_transfer(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	bool	bflag)
+{
+	int		nret = -EINVAL;
+
+	req->dma_flag = FALSE;
+	req->div_len = 0;
+
+	if (req->req.length == 0)
+		req->zero = 0;
+	else {
+		if ((req->req.length % ep->ep.maxpacket) == 0)
+			req->zero = req->req.zero;
+		else
+			req->zero = 0;
+	}
+
+	if (ep->epnum == 0) {
+		/* EP0 */
+		switch (udc->ep0state) {
+		case EP0_IN_DATA_PHASE:
+			nret = _nbu2ss_ep0_in_transfer(udc, ep, req);
+			break;
+
+		case EP0_OUT_DATA_PHASE:
+			nret = _nbu2ss_ep0_out_transfer(udc, ep, req);
+			break;
+
+		case EP0_IN_STATUS_PHASE:
+			nret = EP0_send_NULL(udc, TRUE);
+			break;
+
+		default:
+			break;
+		}
+
+	} else {
+		/* EPn */
+		if (ep->direct == USB_DIR_OUT) {
+			/* OUT */
+			if (bflag == FALSE)
+				nret = _nbu2ss_epn_out_transfer(udc, ep, req);
+		} else {
+			/* IN */
+			nret = _nbu2ss_epn_in_transfer(udc, ep, req);
+		}
+	}
+
+	return nret;
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep)
+{
+	u32		length;
+	bool	bflag = FALSE;
+	struct nbu2ss_req *req;
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+
+	if (req == NULL)
+		return;
+
+	if (ep->epnum > 0) {
+		length = _nbu2ss_readl(
+			&ep->udc->p_regs->EP_REGS[ep->epnum-1].EP_LEN_DCNT);
+
+		length &= EPn_LDATA;
+		if (length < ep->ep.maxpacket)
+			bflag = TRUE;
+	}
+
+	_nbu2ss_start_transfer(ep->udc, ep, req, bflag);
+}
+
+/*-------------------------------------------------------------------------*/
+/*	Endpoint Toggle Reset */
+static void _nbu2ss_endpoint_toggle_reset(
+	struct nbu2ss_udc *udc,
+	u8 ep_adrs)
+{
+	u8		num;
+	u32		data;
+
+	if ((ep_adrs == 0) || (ep_adrs == 0x80))
+		return;
+
+	num = (ep_adrs & 0x7F) - 1;
+
+	if (ep_adrs & USB_DIR_IN)
+		data = EPn_IPIDCLR;
+	else
+		data = EPn_BCLR | EPn_OPIDCLR;
+
+	_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
+}
+
+/*-------------------------------------------------------------------------*/
+/*	Endpoint STALL set */
+static void _nbu2ss_set_endpoint_stall(
+	struct nbu2ss_udc *udc,
+	u8 ep_adrs,
+	bool bstall)
+{
+	u8		num, epnum;
+	u32		data;
+	struct nbu2ss_ep *ep;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if ((ep_adrs == 0) || (ep_adrs == 0x80)) {
+		if (bstall) {
+			/* Set STALL */
+			_nbu2ss_bitset(&preg->EP0_CONTROL, EP0_STL);
+		} else {
+			/* Clear STALL */
+			_nbu2ss_bitclr(&preg->EP0_CONTROL, EP0_STL);
+		}
+	} else {
+		epnum = ep_adrs & USB_ENDPOINT_NUMBER_MASK;
+		num = epnum - 1;
+		ep = &udc->ep[epnum];
+
+		if (bstall) {
+			/* Set STALL */
+			ep->halted = TRUE;
+
+			if (ep_adrs & USB_DIR_IN)
+				data = EPn_BCLR | EPn_ISTL;
+			else
+				data = EPn_OSTL_EN | EPn_OSTL;
+
+			_nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
+		} else {
+			/* Clear STALL */
+			ep->stalled = FALSE;
+			if (ep_adrs & USB_DIR_IN) {
+				_nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL
+						, EPn_ISTL);
+			} else {
+				data =
+				_nbu2ss_readl(&preg->EP_REGS[num].EP_CONTROL);
+
+				data &= ~EPn_OSTL;
+				data |= EPn_OSTL_EN;
+
+				_nbu2ss_writel(&preg->EP_REGS[num].EP_CONTROL
+						, data);
+			}
+
+			ep->stalled = FALSE;
+			if (ep->halted) {
+				ep->halted = FALSE;
+				_nbu2ss_restert_transfer(ep);
+			}
+		}
+	}
+
+	return;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Device Descriptor */
+static struct usb_device_descriptor device_desc = {
+	.bLength              = sizeof(device_desc),
+	.bDescriptorType      = USB_DT_DEVICE,
+	.bcdUSB               = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass         = USB_CLASS_VENDOR_SPEC,
+	.bDeviceSubClass      = 0x00,
+	.bDeviceProtocol      = 0x00,
+	.bMaxPacketSize0      = 64,
+	.idVendor             = __constant_cpu_to_le16 (0x0409),
+	.idProduct            = __constant_cpu_to_le16 (0xfff0),
+	.bcdDevice            = 0xffff,
+	.iManufacturer        = 0x00,
+	.iProduct             = 0x00,
+	.iSerialNumber        = 0x00,
+	.bNumConfigurations   = 0x01,
+};
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_set_test_mode(struct nbu2ss_udc *udc, u32 mode)
+{
+	u32		data;
+
+	if (mode > MAX_TEST_MODE_NUM)
+		return;
+
+	pr_info("SET FEATURE : test mode = %d\n", mode);
+
+	data = _nbu2ss_readl(&udc->p_regs->USB_CONTROL);
+	data &= ~TEST_FORCE_ENABLE;
+	data |= mode << TEST_MODE_SHIFT;
+
+	_nbu2ss_writel(&udc->p_regs->USB_CONTROL, data);
+	_nbu2ss_bitset(&udc->p_regs->TEST_CONTROL, CS_TESTMODEEN);
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_set_feature_device(
+	struct nbu2ss_udc *udc,
+	u16 selector,
+	u16 wIndex
+)
+{
+	int	result = -EOPNOTSUPP;
+
+	switch (selector) {
+	case USB_DEVICE_REMOTE_WAKEUP:
+		if (0x0000 == wIndex) {
+			udc->remote_wakeup = U2F_ENABLE;
+			result = 0;
+		}
+		break;
+
+	case USB_DEVICE_TEST_MODE:
+		wIndex = wIndex >> 8;
+		if (wIndex <= MAX_TEST_MODE_NUM)
+			result = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_get_ep_stall(struct nbu2ss_udc *udc, u8 ep_adrs)
+{
+	u8		epnum;
+	u32		data = 0, bit_data;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	epnum = ep_adrs & ~USB_ENDPOINT_DIR_MASK;
+	if (epnum == 0) {
+		data = _nbu2ss_readl(&preg->EP0_CONTROL);
+		bit_data = EP0_STL;
+
+	} else {
+		data = _nbu2ss_readl(&preg->EP_REGS[epnum-1].EP_CONTROL);
+		if ((data & EPn_EN) == 0)
+			return -1;
+
+		if (ep_adrs & USB_ENDPOINT_DIR_MASK)
+			bit_data = EPn_ISTL;
+		else
+			bit_data = EPn_OSTL;
+	}
+
+	if ((data & bit_data) == 0)
+		return 0;
+	else
+		return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline int _nbu2ss_req_feature(struct nbu2ss_udc *udc, bool bset)
+{
+	u8	recipient = (u8)(udc->ctrl.bRequestType & USB_RECIP_MASK);
+	u8	direction = (u8)(udc->ctrl.bRequestType & USB_DIR_IN);
+	u16	selector  = udc->ctrl.wValue;
+	u16	wIndex    = udc->ctrl.wIndex;
+	u8	ep_adrs;
+	int	result = -EOPNOTSUPP;
+
+	if ((0x0000 != udc->ctrl.wLength) ||
+			(USB_DIR_OUT != direction)) {
+		return -EINVAL;
+	}
+
+	switch (recipient) {
+	case USB_RECIP_DEVICE:
+		if (bset)
+			result =
+			_nbu2ss_set_feature_device(udc, selector, wIndex);
+		break;
+
+	case USB_RECIP_ENDPOINT:
+		if (0x0000 == (wIndex & 0xFF70)) {
+			if (USB_ENDPOINT_HALT == selector) {
+				ep_adrs = wIndex & 0xFF;
+				if (bset == FALSE) {
+					_nbu2ss_endpoint_toggle_reset(
+						udc, ep_adrs);
+				}
+
+				_nbu2ss_set_endpoint_stall(
+					udc, ep_adrs, bset);
+
+				result = 0;
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if (result >= 0)
+		_nbu2ss_create_ep0_packet(udc, udc->ep0_buf, 0);
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline enum usb_device_speed _nbu2ss_get_speed(struct nbu2ss_udc *udc)
+{
+	u32		data;
+	enum usb_device_speed speed = USB_SPEED_FULL;
+
+	data = _nbu2ss_readl(&udc->p_regs->USB_STATUS);
+	if (data & HIGH_SPEED)
+		speed = USB_SPEED_HIGH;
+
+	return speed;
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_epn_set_stall(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep
+)
+{
+	u8	ep_adrs;
+	u32	regdata;
+	int	limit_cnt = 0;
+
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (ep->direct == USB_DIR_IN) {
+		for (limit_cnt = 0
+			; limit_cnt < IN_DATA_EMPTY_COUNT
+			; limit_cnt++) {
+
+			regdata = _nbu2ss_readl(
+				&preg->EP_REGS[ep->epnum-1].EP_STATUS);
+
+			if ((regdata & EPn_IN_DATA) == 0)
+				break;
+
+			mdelay(1);
+		}
+	}
+
+	ep_adrs = ep->epnum | ep->direct;
+	_nbu2ss_set_endpoint_stall(udc, ep_adrs, 1);
+}
+
+/*-------------------------------------------------------------------------*/
+static int std_req_get_status(struct nbu2ss_udc *udc)
+{
+	u32	length;
+	u16	status_data = 0;
+	u8	recipient = (u8)(udc->ctrl.bRequestType & USB_RECIP_MASK);
+	u8	direction = (u8)(udc->ctrl.bRequestType & USB_DIR_IN);
+	u8	ep_adrs;
+	int	result = -EINVAL;
+
+	if ((0x0000 != udc->ctrl.wValue)
+		|| (USB_DIR_IN != direction)) {
+
+		return result;
+	}
+
+	length = min(udc->ctrl.wLength, (u16)sizeof(status_data));
+
+	switch (recipient) {
+	case USB_RECIP_DEVICE:
+		if (udc->ctrl.wIndex == 0x0000) {
+			if (udc->self_powered)
+				status_data |= (1 << USB_DEVICE_SELF_POWERED);
+
+			if (udc->remote_wakeup)
+				status_data |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+
+			result = 0;
+		}
+		break;
+
+	case USB_RECIP_ENDPOINT:
+		if (0x0000 == (udc->ctrl.wIndex & 0xFF70)) {
+			ep_adrs = (u8)(udc->ctrl.wIndex & 0xFF);
+			result = _nbu2ss_get_ep_stall(udc, ep_adrs);
+
+			if (result > 0)
+				status_data |= (1 << USB_ENDPOINT_HALT);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if (result >= 0) {
+		memcpy(udc->ep0_buf, &status_data, length);
+		_nbu2ss_create_ep0_packet(udc, udc->ep0_buf, length);
+		_nbu2ss_ep0_in_transfer(udc, &udc->ep[0], &udc->ep0_req);
+
+	} else {
+		ERR("*** Error GET_STATUS\n");
+	}
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int std_req_clear_feature(struct nbu2ss_udc *udc)
+{
+	return _nbu2ss_req_feature(udc, FALSE);
+}
+
+/*-------------------------------------------------------------------------*/
+static int std_req_set_feature(struct nbu2ss_udc *udc)
+{
+	return _nbu2ss_req_feature(udc, TRUE);
+}
+
+/*-------------------------------------------------------------------------*/
+static int std_req_set_address(struct nbu2ss_udc *udc)
+{
+	int		result = 0;
+	u32		wValue = udc->ctrl.wValue;
+
+	if ((0x00 != udc->ctrl.bRequestType)	||
+		(0x0000 != udc->ctrl.wIndex)	||
+		(0x0000 != udc->ctrl.wLength)) {
+		return -EINVAL;
+	}
+
+	if (wValue != (wValue & 0x007F))
+		return -EINVAL;
+
+	wValue = wValue << USB_ADRS_SHIFT;
+
+	_nbu2ss_writel(&udc->p_regs->USB_ADDRESS, wValue);
+	_nbu2ss_create_ep0_packet(udc, udc->ep0_buf, 0);
+
+	return result;
+}
+
+/*-------------------------------------------------------------------------*/
+static int std_req_set_configuration(struct nbu2ss_udc *udc)
+{
+	u32 ConfigValue = (u32)(udc->ctrl.wValue & 0x00ff);
+
+	if ((0x0000 != udc->ctrl.wIndex)	||
+		(0x0000 != udc->ctrl.wLength)	||
+		(0x00 != udc->ctrl.bRequestType)) {
+		return -EINVAL;
+	}
+
+	udc->curr_config = ConfigValue;
+
+	if (ConfigValue > 0) {
+		_nbu2ss_bitset(&udc->p_regs->USB_CONTROL, CONF);
+		udc->devstate = USB_STATE_CONFIGURED;
+
+	} else {
+		_nbu2ss_bitclr(&udc->p_regs->USB_CONTROL, CONF);
+		udc->devstate = USB_STATE_ADDRESS;
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_read_request_data(struct nbu2ss_udc *udc, u32 *pdata)
+{
+	if ((udc == NULL) && (pdata == NULL))
+		return;
+
+	*pdata = _nbu2ss_readl(&udc->p_regs->SETUP_DATA0);
+	pdata++;
+	*pdata = _nbu2ss_readl(&udc->p_regs->SETUP_DATA1);
+}
+
+/*-------------------------------------------------------------------------*/
+static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc)
+{
+	bool			bcall_back = TRUE;
+	int			nret = -EINVAL;
+	struct usb_ctrlrequest	*p_ctrl;
+
+	p_ctrl = &udc->ctrl;
+	_nbu2ss_read_request_data(udc, (u32 *)p_ctrl);
+
+	/* ep0 state control */
+	if (p_ctrl->wLength == 0) {
+		udc->ep0state = EP0_IN_STATUS_PHASE;
+
+	} else {
+		if (p_ctrl->bRequestType & USB_DIR_IN)
+			udc->ep0state = EP0_IN_DATA_PHASE;
+		else
+			udc->ep0state = EP0_OUT_DATA_PHASE;
+	}
+
+	if ((p_ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (p_ctrl->bRequest) {
+		case USB_REQ_GET_STATUS:
+			nret = std_req_get_status(udc);
+			bcall_back = FALSE;
+			break;
+
+		case USB_REQ_CLEAR_FEATURE:
+			nret = std_req_clear_feature(udc);
+			bcall_back = FALSE;
+			break;
+
+		case USB_REQ_SET_FEATURE:
+			nret = std_req_set_feature(udc);
+			bcall_back = FALSE;
+			break;
+
+		case USB_REQ_SET_ADDRESS:
+			nret = std_req_set_address(udc);
+			bcall_back = FALSE;
+			break;
+
+		case USB_REQ_SET_CONFIGURATION:
+			nret = std_req_set_configuration(udc);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (bcall_back == FALSE) {
+		if (udc->ep0state == EP0_IN_STATUS_PHASE) {
+			if (nret >= 0) {
+				/*--------------------------------------*/
+				/* Status Stage */
+				nret = EP0_send_NULL(udc, TRUE);
+			}
+		}
+
+	} else {
+		spin_unlock(&udc->lock);
+		nret = udc->driver->setup(&udc->gadget, &udc->ctrl);
+		spin_lock(&udc->lock);
+	}
+
+	if (nret < 0)
+		udc->ep0state = EP0_IDLE;
+
+	return nret;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc)
+{
+	int			nret;
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep = &udc->ep[0];
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+
+	if (req == NULL)
+		req = &udc->ep0_req;
+
+	req->req.actual += req->div_len;
+	req->div_len = 0;
+
+	nret = _nbu2ss_ep0_in_transfer(udc, ep, req);
+	if (nret == 0) {
+		udc->ep0state = EP0_OUT_STATUS_PAHSE;
+		EP0_receive_NULL(udc, TRUE);
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline int _nbu2ss_ep0_out_data_stage(struct nbu2ss_udc *udc)
+{
+	int			nret;
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep = &udc->ep[0];
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+
+	if (req == NULL)
+		req = &udc->ep0_req;
+
+	nret = _nbu2ss_ep0_out_transfer(udc, ep, req);
+	if (nret == 0) {
+		udc->ep0state = EP0_IN_STATUS_PHASE;
+		EP0_send_NULL(udc, TRUE);
+
+	} else if (nret < 0) {
+		_nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, EP0_BCLR);
+		req->req.status = nret;
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline int _nbu2ss_ep0_status_stage(struct nbu2ss_udc *udc)
+{
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep = &udc->ep[0];
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+
+	if (req == NULL) {
+		req = &udc->ep0_req;
+		if (req->req.complete)
+			req->req.complete(&ep->ep, &req->req);
+
+	} else {
+		if (req->req.complete)
+			_nbu2ss_ep_done(ep, req, 0);
+	}
+
+	udc->ep0state = EP0_IDLE;
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc)
+{
+	int		i;
+	u32		status;
+	u32		intr;
+	int		nret = -1;
+
+	status = _nbu2ss_readl(&udc->p_regs->EP0_STATUS);
+	intr = status & EP0_STATUS_RW_BIT;
+	_nbu2ss_writel(&udc->p_regs->EP0_STATUS, ~(u32)intr);
+
+	status &= (SETUP_INT | EP0_IN_INT | EP0_OUT_INT
+			| STG_END_INT | EP0_OUT_NULL_INT);
+
+	if (status == 0) {
+		pr_info("--- %s Not Decode Interrupt\n", __func__);
+		pr_info("--- EP0_STATUS = 0x%08x\n", intr);
+		return;
+	}
+
+	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+		udc->gadget.speed = _nbu2ss_get_speed(udc);
+
+	for (i = 0; i < EP0_END_XFER; i++) {
+		switch (udc->ep0state) {
+		case EP0_IDLE:
+			if (status & SETUP_INT) {
+				status = 0;
+				nret = _nbu2ss_decode_request(udc);
+			}
+			break;
+
+		case EP0_IN_DATA_PHASE:
+			if (status & EP0_IN_INT) {
+				status &= ~EP0_IN_INT;
+				nret = _nbu2ss_ep0_in_data_stage(udc);
+			}
+			break;
+
+		case EP0_OUT_DATA_PHASE:
+			if (status & EP0_OUT_INT) {
+				status &= ~EP0_OUT_INT;
+				nret = _nbu2ss_ep0_out_data_stage(udc);
+			}
+			break;
+
+		case EP0_IN_STATUS_PHASE:
+			if ((status & STG_END_INT) || (status & SETUP_INT)) {
+				status &= ~(STG_END_INT | EP0_IN_INT);
+				nret = _nbu2ss_ep0_status_stage(udc);
+			}
+			break;
+
+		case EP0_OUT_STATUS_PAHSE:
+			if ((status & STG_END_INT)
+			|| (status & SETUP_INT)
+			|| (status & EP0_OUT_NULL_INT)) {
+				status &= ~(STG_END_INT
+						| EP0_OUT_INT
+						| EP0_OUT_NULL_INT);
+
+				nret = _nbu2ss_ep0_status_stage(udc);
+			}
+
+			break;
+
+		default:
+			status = 0;
+			break;
+		}
+
+		if (status == 0)
+			break;
+	}
+
+	if (nret < 0) {
+		/* Send Stall */
+		_nbu2ss_set_endpoint_stall(udc, 0, TRUE);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_ep_done(
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req,
+	int status)
+{
+	struct nbu2ss_udc *udc = ep->udc;
+
+	list_del_init(&req->queue);
+
+	if (status == -ECONNRESET)
+		_nbu2ss_fifo_flush(udc, ep);
+
+	if (likely(req->req.status == -EINPROGRESS))
+		req->req.status = status;
+
+	if (ep->stalled)
+		_nbu2ss_epn_set_stall(udc, ep);
+	else {
+		if (!list_empty(&ep->queue))
+			_nbu2ss_restert_transfer(ep);
+	}
+
+#ifdef USE_DMA
+	if ((ep->direct == USB_DIR_OUT) && (ep->epnum > 0) &&
+			(req->req.dma != 0))
+		_nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_OUT);
+#endif
+
+	spin_unlock(&udc->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&udc->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_epn_in_int(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req)
+{
+	int	result = 0;
+	u32	status;
+
+	PT_FC_REGS	preg = udc->p_regs;
+
+	if (req->dma_flag)
+		return;		/* DMA is forwarded */
+
+	req->req.actual += req->div_len;
+	req->div_len = 0;
+
+	if (req->req.actual != req->req.length) {
+		/*---------------------------------------------------------*/
+		/* remainder of data */
+		result = _nbu2ss_epn_in_transfer(udc, ep, req);
+
+	} else {
+		if ((req->zero != 0)
+		&& ((req->req.actual % ep->ep.maxpacket) == 0)) {
+
+			status =
+			_nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_STATUS);
+
+			if ((status & EPn_IN_FULL) == 0) {
+				/*-----------------------------------------*/
+				/* 0 Length Packet */
+				req->zero = 0;
+				_nbu2ss_zero_len_pkt(udc, ep->epnum);
+			}
+			return;
+		}
+	}
+
+	if (result <= 0) {
+		/*---------------------------------------------------------*/
+		/* Complete */
+		_nbu2ss_ep_done(ep, req, result);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_epn_out_int(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req)
+{
+	int	result;
+
+	result = _nbu2ss_epn_out_transfer(udc, ep, req);
+	if (result <= 0)
+		_nbu2ss_ep_done(ep, req, result);
+
+	return;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_epn_in_dma_int(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req)
+{
+	u32		mpkt;
+	u32		size;
+	struct usb_request *preq;
+
+	preq = &req->req;
+
+	if (req->dma_flag == FALSE)
+		return;
+
+	preq->actual += req->div_len;
+	req->div_len = 0;
+	req->dma_flag = FALSE;
+
+#ifdef USE_DMA
+	_nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_IN);
+#endif
+
+	if (preq->actual != preq->length) {
+		_nbu2ss_epn_in_transfer(udc, ep, req);
+	} else {
+		mpkt = ep->ep.maxpacket;
+		size = preq->actual % mpkt;
+		if (size > 0) {
+			if (((preq->actual & 0x03) == 0) && (size < mpkt))
+				_nbu2ss_ep_in_end(udc, ep->epnum, 0, 0);
+		} else {
+			_nbu2ss_epn_in_int(udc, ep, req);
+		}
+	}
+
+	return;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_epn_out_dma_int(
+	struct nbu2ss_udc *udc,
+	struct nbu2ss_ep *ep,
+	struct nbu2ss_req *req)
+{
+	int		i;
+	u32		num;
+	u32		dmacnt, ep_dmacnt;
+	u32		mpkt;
+	PT_FC_REGS	preg = udc->p_regs;
+
+	num = ep->epnum - 1;
+
+	if (req->req.actual == req->req.length) {
+		if ((req->req.length % ep->ep.maxpacket)
+				&& (req->zero == 0)) {
+			req->div_len = 0;
+			req->dma_flag = FALSE;
+			_nbu2ss_ep_done(ep, req, 0);
+			return;
+		}
+	}
+
+	ep_dmacnt = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT)
+		 & EPn_DMACNT;
+	ep_dmacnt >>= 16;
+
+	for (i = 0; i < EPC_PLL_LOCK_COUNT; i++) {
+		dmacnt = _nbu2ss_readl(&preg->EP_DCR[num].EP_DCR1)
+			 & DCR1_EPn_DMACNT;
+		dmacnt >>= 16;
+		if (ep_dmacnt == dmacnt)
+			break;
+	}
+
+	_nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_REQEN);
+
+	if (dmacnt != 0) {
+		mpkt = ep->ep.maxpacket;
+		if ((req->div_len % mpkt) == 0)
+			req->div_len -= mpkt * dmacnt;
+	}
+
+	if ((req->req.actual % ep->ep.maxpacket) > 0) {
+		if (req->req.actual == req->div_len) {
+			req->div_len = 0;
+			req->dma_flag = FALSE;
+			_nbu2ss_ep_done(ep, req, 0);
+			return;
+		}
+	}
+
+	req->req.actual += req->div_len;
+	req->div_len = 0;
+	req->dma_flag = FALSE;
+
+	_nbu2ss_epn_out_int(udc, ep, req);
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_epn_int(struct nbu2ss_udc *udc, u32 epnum)
+{
+	u32	num;
+	u32	status;
+
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep = &udc->ep[epnum];
+
+	num = epnum - 1;
+
+	/* Interrupt Status */
+	status = _nbu2ss_readl(&udc->p_regs->EP_REGS[num].EP_STATUS);
+
+	/* Interrupt Clear */
+	_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status);
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+
+	if (req == NULL) {
+		/* pr_warning("=== %s(%d) req == NULL\n", __func__, epnum); */
+		return;
+	}
+
+	if (status & EPn_OUT_END_INT) {
+		status &= ~EPn_OUT_INT;
+		_nbu2ss_epn_out_dma_int(udc, ep, req);
+	}
+
+	if (status & EPn_OUT_INT)
+		_nbu2ss_epn_out_int(udc, ep, req);
+
+	if (status & EPn_IN_END_INT) {
+		status &= ~EPn_IN_INT;
+		_nbu2ss_epn_in_dma_int(udc, ep, req);
+	}
+
+	if (status & EPn_IN_INT)
+		_nbu2ss_epn_in_int(udc, ep, req);
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_ep_int(struct nbu2ss_udc *udc, u32 epnum)
+{
+	if (epnum == 0)
+		_nbu2ss_ep0_int(udc);
+	else
+		_nbu2ss_epn_int(udc, epnum);
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_ep0_enable(struct nbu2ss_udc *udc)
+{
+	_nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, (EP0_AUTO | EP0_BCLR));
+	_nbu2ss_writel(&udc->p_regs->EP0_INT_ENA, EP0_INT_EN_BIT);
+
+	return;
+}
+
+#if 0
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_ep0_disable(struct nbu2ss_udc *udc)
+{
+	_nbu2ss_bitclr(&udc->p_regs->EP0_INT_ENA, EP0_INT_EN_BIT);
+
+	_nbu2ss_bitset(&udc->p_regs->EP0_CONTROL
+			, (EP0_BCLR | EP0_INAK | EP0_ONAK | EP0_BCLR));
+
+	_nbu2ss_bitclr(&udc->p_regs->EP0_CONTROL, EP0_AUTO);
+
+	return;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_nuke(struct nbu2ss_udc *udc,
+			struct nbu2ss_ep *ep,
+			int status)
+{
+	struct nbu2ss_req *req;
+
+	/* Endpoint Disable */
+	_nbu2ss_epn_exit(udc, ep);
+
+	/* DMA Disable */
+	_nbu2ss_ep_dma_exit(udc, ep);
+
+	if (list_empty(&ep->queue))
+		return 0;
+
+	/* called with irqs blocked */
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+		_nbu2ss_ep_done(ep, req, status);
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_quiesce(struct nbu2ss_udc *udc)
+{
+	struct nbu2ss_ep	*ep;
+
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+
+	_nbu2ss_nuke(udc, &udc->ep[0], -ESHUTDOWN);
+
+	/* Endpoint n */
+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+		_nbu2ss_nuke(udc, ep, -ESHUTDOWN);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_pullup(struct nbu2ss_udc *udc, int is_on)
+{
+	u32	reg_dt;
+
+	if (!udc) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	if (udc->vbus_active == 0)
+		return -ESHUTDOWN;
+
+	if (is_on) {
+		/* D+ Pullup */
+/*		INFO(" --- D+ Pullup\n"); */
+
+		if (udc->driver) {
+			reg_dt = (_nbu2ss_readl(&udc->p_regs->USB_CONTROL)
+				| PUE2) & ~(u32)CONNECTB;
+
+			_nbu2ss_writel(&udc->p_regs->USB_CONTROL, reg_dt);
+		}
+
+	} else {
+		/* D+ Pulldown */
+/*		INFO(" --- D+ Pulldown\n"); */
+
+		reg_dt = (_nbu2ss_readl(&udc->p_regs->USB_CONTROL) | CONNECTB)
+			& ~(u32)PUE2;
+
+		_nbu2ss_writel(&udc->p_regs->USB_CONTROL, reg_dt);
+		udc->gadget.speed = USB_SPEED_UNKNOWN;
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_fifo_flush(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
+{
+	PT_FC_REGS	p = udc->p_regs;
+
+	if (udc->vbus_active == 0)
+		return;
+
+	if (ep->epnum == 0) {
+		/* EP0 */
+		_nbu2ss_bitset(&p->EP0_CONTROL, EP0_BCLR);
+
+	} else {
+		/* EPn */
+		_nbu2ss_ep_dma_abort(udc, ep);
+		_nbu2ss_bitset(&p->EP_REGS[ep->epnum - 1].EP_CONTROL, EPn_BCLR);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc)
+{
+	int	waitcnt = 0;
+
+	if (udc->udc_enabled)
+		return 0;
+
+#if 0
+	emxx_open_clockgate(EMXX_CLK_USB1);
+	/* emxx_clkctrl_off(EMXX_CLKCTRL_USB1); */
+	/* emxx_clkctrl_on(EMXX_CLKCTRL_USB1); */
+	emxx_unreset_device(EMXX_RST_USB1);
+#endif
+	/*
+		Reset
+	*/
+	_nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST));
+	udelay(EPC_RST_DISABLE_TIME);	/* 1us wait */
+
+	_nbu2ss_bitclr(&udc->p_regs->EPCTR, DIRPD);
+	mdelay(EPC_DIRPD_DISABLE_TIME);	/* 1ms wait */
+
+	_nbu2ss_bitclr(&udc->p_regs->EPCTR, EPC_RST);
+
+	_nbu2ss_writel(&udc->p_regs->AHBSCTR, WAIT_MODE);
+
+#if 0
+	/* DMA Mode Setting */
+	if ((system_rev & EMXX_REV_MASK) == EMXX_REV_ES1) {
+		_nbu2ss_bitset(&udc->p_regs->AHBMCTR, BURST_TYPE);
+		_nbu2ss_bitclr(&udc->p_regs->AHBMCTR, HTRANS_MODE);
+	} else
+#endif
+		_nbu2ss_writel(&udc->p_regs->AHBMCTR,
+			HBUSREQ_MODE | HTRANS_MODE | WBURST_TYPE);
+
+	while (!(_nbu2ss_readl(&udc->p_regs->EPCTR) & PLL_LOCK)) {
+		waitcnt++;
+		udelay(1);	/* 1us wait */
+		if (waitcnt == EPC_PLL_LOCK_COUNT) {
+			ERR("*** Reset Cancel failed\n");
+			return -EINVAL;
+		}
+	};
+
+#if 0
+	if ((system_rev & EMXX_REV_MASK) < EMXX_REV_ES3)
+#endif
+		_nbu2ss_bitset(&udc->p_regs->UTMI_CHARACTER_1, USB_SQUSET);
+
+	_nbu2ss_bitset(&udc->p_regs->USB_CONTROL, (INT_SEL | SOF_RCV));
+
+	/* EP0 */
+	_nbu2ss_ep0_enable(udc);
+
+	/* USB Interrupt Enable */
+	_nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, USB_INT_EN_BIT);
+
+	udc->udc_enabled = TRUE;
+
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_reset_controller(struct nbu2ss_udc *udc)
+{
+	_nbu2ss_bitset(&udc->p_regs->EPCTR, EPC_RST);
+	_nbu2ss_bitclr(&udc->p_regs->EPCTR, EPC_RST);
+}
+
+/*-------------------------------------------------------------------------*/
+static void _nbu2ss_disable_controller(struct nbu2ss_udc *udc)
+{
+	if (udc->udc_enabled) {
+		udc->udc_enabled = FALSE;
+		_nbu2ss_reset_controller(udc);
+		_nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST));
+	}
+#if 0
+	emxx_reset_device(EMXX_RST_USB1);
+	/* emxx_clkctrl_on(EMXX_CLKCTRL_USB1); */
+	emxx_close_clockgate(EMXX_CLK_USB1);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
+{
+	int	nret;
+	u32	reg_dt;
+
+	/* chattering */
+	mdelay(VBUS_CHATTERING_MDELAY);		/* wait (ms) */
+
+	/* VBUS ON Check*/
+	reg_dt = gpio_get_value(VBUS_VALUE);
+	if (reg_dt == 0) {
+
+		udc->linux_suspended = 0;
+
+		_nbu2ss_reset_controller(udc);
+		pr_info(" ----- VBUS OFF\n");
+
+		if (udc->vbus_active == 1) {
+			/* VBUS OFF */
+			udc->vbus_active = 0;
+			if (udc->usb_suspended) {
+				udc->usb_suspended = 0;
+				/* _nbu2ss_reset_controller(udc); */
+			}
+			udc->devstate = USB_STATE_NOTATTACHED;
+
+			_nbu2ss_quiesce(udc);
+			if (udc->driver) {
+				spin_unlock(&udc->lock);
+				udc->driver->disconnect(&udc->gadget);
+				spin_lock(&udc->lock);
+			}
+
+			_nbu2ss_disable_controller(udc);
+		}
+	} else {
+		mdelay(5);		/* wait (5ms) */
+		reg_dt = gpio_get_value(VBUS_VALUE);
+		if (reg_dt == 0)
+			return;
+
+		pr_info(" ----- VBUS ON\n");
+
+		if (udc->linux_suspended)
+			return;
+
+		if (udc->vbus_active == 0) {
+			/* VBUS ON */
+			udc->vbus_active = 1;
+			udc->devstate = USB_STATE_POWERED;
+
+			nret = _nbu2ss_enable_controller(udc);
+			if (nret < 0) {
+				_nbu2ss_disable_controller(udc);
+				udc->vbus_active = 0;
+				return;
+			}
+
+			_nbu2ss_pullup(udc, 1);
+
+#ifdef UDC_DEBUG_DUMP
+			_nbu2ss_dump_register(udc);
+#endif /* UDC_DEBUG_DUMP */
+
+		} else {
+			if (udc->devstate == USB_STATE_POWERED)
+				_nbu2ss_pullup(udc, 1);
+		}
+	}
+
+	return;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_int_bus_reset(struct nbu2ss_udc *udc)
+{
+	udc->devstate		= USB_STATE_DEFAULT;
+	udc->remote_wakeup	= 0;
+
+	_nbu2ss_quiesce(udc);
+
+	udc->ep0state = EP0_IDLE;
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_int_usb_resume(struct nbu2ss_udc *udc)
+{
+	if (udc->usb_suspended == 1) {
+		udc->usb_suspended = 0;
+		if (udc->driver && udc->driver->resume) {
+			spin_unlock(&udc->lock);
+			udc->driver->resume(&udc->gadget);
+			spin_lock(&udc->lock);
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static inline void _nbu2ss_int_usb_suspend(struct nbu2ss_udc *udc)
+{
+	u32	reg_dt;
+
+	if (udc->usb_suspended == 0) {
+		reg_dt = gpio_get_value(VBUS_VALUE);
+
+		if (reg_dt == 0)
+			return;
+
+		udc->usb_suspended = 1;
+		if (udc->driver && udc->driver->suspend) {
+			spin_unlock(&udc->lock);
+			udc->driver->suspend(&udc->gadget);
+			spin_lock(&udc->lock);
+		}
+
+		_nbu2ss_bitset(&udc->p_regs->USB_CONTROL, SUSPEND);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+/* VBUS (GPIO153) Interrupt */
+static irqreturn_t _nbu2ss_vbus_irq(int irq, void *_udc)
+{
+	struct nbu2ss_udc	*udc = (struct nbu2ss_udc *)_udc;
+
+	spin_lock(&udc->lock);
+	_nbu2ss_check_vbus(udc);
+	spin_unlock(&udc->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Interrupt (udc) */
+static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
+{
+	u8	suspend_flag = 0;
+	u32	status;
+	u32	epnum, int_bit;
+
+	struct nbu2ss_udc	*udc = (struct nbu2ss_udc *)_udc;
+	PT_FC_REGS		preg = udc->p_regs;
+
+	if (gpio_get_value(VBUS_VALUE) == 0) {
+		_nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
+		_nbu2ss_writel(&preg->USB_INT_ENA, 0);
+		return IRQ_HANDLED;
+	}
+
+	spin_lock(&udc->lock);
+
+	for (;;) {
+		if (gpio_get_value(VBUS_VALUE) == 0) {
+			_nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
+			_nbu2ss_writel(&preg->USB_INT_ENA, 0);
+			status = 0;
+		} else
+			status = _nbu2ss_readl(&preg->USB_INT_STA);
+
+		if (status == 0)
+			break;
+
+		_nbu2ss_writel(&preg->USB_INT_STA, ~(status & USB_INT_STA_RW));
+
+		if (status & USB_RST_INT) {
+			/* USB Reset */
+			_nbu2ss_int_bus_reset(udc);
+		}
+
+		if (status & RSUM_INT) {
+			/* Resume */
+			_nbu2ss_int_usb_resume(udc);
+		}
+
+		if (status & SPND_INT) {
+			/* Suspend */
+			suspend_flag = 1;
+		}
+
+		if (status & EPn_INT) {
+			/* EP INT */
+			int_bit = status >> 8;
+
+			for (epnum = 0; epnum < NUM_ENDPOINTS; epnum++) {
+
+				if (0x01 & int_bit)
+					_nbu2ss_ep_int(udc, epnum);
+
+				int_bit >>= 1;
+
+				if (int_bit == 0)
+					break;
+			}
+		}
+	}
+
+	if (suspend_flag)
+		_nbu2ss_int_usb_suspend(udc);
+
+	spin_unlock(&udc->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+/* usb_ep_ops */
+static int nbu2ss_ep_enable(
+	struct usb_ep *_ep,
+	const struct usb_endpoint_descriptor *desc)
+{
+	u8		ep_type;
+	unsigned long	flags;
+
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+
+	if ((_ep == NULL) || (desc == NULL)) {
+		ERR(" *** %s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if ((ep == NULL) || (ep->udc == NULL)) {
+		ERR(" *** %s, ep == NULL !!\n", __func__);
+		return -EINVAL;
+	}
+
+	ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	if ((ep_type == USB_ENDPOINT_XFER_CONTROL)
+		|| (ep_type == USB_ENDPOINT_XFER_ISOC)) {
+
+		ERR(" *** %s, bat bmAttributes\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (udc->vbus_active == 0)
+		return -ESHUTDOWN;
+
+	if ((udc->driver == NULL)
+		|| (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
+
+		ERR(" *** %s, udc !!\n", __func__);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	ep->desc = desc;
+	ep->epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep->direct = desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+	ep->ep_type = ep_type;
+	ep->wedged = 0;
+	ep->halted = FALSE;
+	ep->stalled = FALSE;
+
+	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+	/* DMA setting */
+	_nbu2ss_ep_dma_init(udc, ep);
+
+	/* Endpoint setting */
+	_nbu2ss_ep_init(udc, ep);
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_ep_disable(struct usb_ep *_ep)
+{
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+
+	if (_ep == NULL) {
+		ERR(" *** %s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if ((ep == NULL) || (ep->udc == NULL)) {
+		ERR(" *** %s, ep == NULL !!\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (udc->vbus_active == 0)
+		return -ESHUTDOWN;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	_nbu2ss_nuke(udc, ep, -EINPROGRESS);		/* dequeue request */
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct usb_request *nbu2ss_ep_alloc_request(
+	struct usb_ep *ep,
+	gfp_t gfp_flags)
+{
+	struct nbu2ss_req *req;
+
+	req = kzalloc(sizeof(*req), gfp_flags);
+	if (!req)
+		return 0;
+
+#ifdef USE_DMA
+	req->req.dma = DMA_ADDR_INVALID;
+#endif
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+/*-------------------------------------------------------------------------*/
+static void nbu2ss_ep_free_request(
+	struct usb_ep *_ep,
+	struct usb_request *_req)
+{
+	struct nbu2ss_req *req;
+
+	if (_req != NULL) {
+		req = container_of(_req, struct nbu2ss_req, req);
+
+		if (req != NULL)
+			kfree(req);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_ep_queue(
+	struct usb_ep *_ep,
+	struct usb_request *_req,
+	gfp_t gfp_flags)
+{
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+	bool			bflag;
+	int			result = -EINVAL;
+
+	/* catch various bogus parameters */
+	if ((_ep == NULL) || (_req == NULL)) {
+		if (_ep == NULL)
+			ERR("*** %s --- _ep == NULL\n", __func__);
+
+		if (_req == NULL)
+			ERR("*** %s --- _req == NULL\n", __func__);
+
+		return -EINVAL;
+	}
+
+	req = container_of(_req, struct nbu2ss_req, req);
+	if (unlikely
+	    (!_req->complete || !_req->buf
+	     || !list_empty(&req->queue))) {
+
+		if (!_req->complete)
+			ERR("*** %s --- !_req->complete\n", __func__);
+
+		if (!_req->buf)
+			ERR("*** %s --- !_req->buf\n", __func__);
+
+		if (!list_empty(&req->queue))
+			ERR("*** %s --- !list_empty(&req->queue)\n", __func__);
+
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	udc = ep->udc;
+
+/*	INFO("=== %s(ep%d), zero=%d\n", __func__, ep->epnum, _req->zero); */
+
+	if (udc->vbus_active == 0) {
+		pr_info("Can't ep_queue (VBUS OFF)\n");
+		return -ESHUTDOWN;
+	}
+
+	if (unlikely(!udc->driver)) {
+		ERR("%s, bogus device state %p\n", __func__, udc->driver);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+#ifdef USE_DMA
+	if ((u32)req->req.buf & 0x3)
+		req->unaligned = TRUE;
+	else
+		req->unaligned = FALSE;
+
+	if (req->unaligned) {
+		if (ep->virt_buf == NULL)
+			ep->virt_buf = (u8 *)dma_alloc_coherent(
+				NULL, PAGE_SIZE,
+				&ep->phys_buf, GFP_KERNEL | GFP_DMA);
+		if (ep->epnum > 0)  {
+			if (ep->direct == USB_DIR_IN)
+				memcpy(ep->virt_buf, req->req.buf,
+					req->req.length);
+		}
+	}
+
+	if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT) &&
+			(req->req.dma != 0))
+		_nbu2ss_dma_map_single(udc, ep, req, USB_DIR_OUT);
+#endif
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	bflag = list_empty(&ep->queue);
+	list_add_tail(&req->queue, &ep->queue);
+
+	if ((bflag != FALSE) && (ep->stalled == FALSE)) {
+
+		result = _nbu2ss_start_transfer(udc, ep, req, FALSE);
+		if (result < 0) {
+			ERR(" *** %s, result = %d\n", __func__, result);
+			list_del(&req->queue);
+		} else if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT)) {
+#ifdef USE_DMA
+			if (req->req.length < 4 &&
+				req->req.length == req->req.actual)
+#else
+			if (req->req.length == req->req.actual)
+#endif
+				_nbu2ss_ep_done(ep, req, result);
+		}
+	}
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_ep_dequeue(
+	struct usb_ep *_ep,
+	struct usb_request *_req)
+{
+	struct nbu2ss_req	*req;
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+	unsigned long flags;
+
+	/*INFO("=== %s()\n", __func__);*/
+
+	/* catch various bogus parameters */
+	if ((_ep == NULL) || (_req == NULL)) {
+		/* ERR("%s, bad param(1)\n", __func__); */
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if (!ep) {
+		ERR("%s, ep == NULL !!\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (udc == NULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&udc->lock, flags);
+		pr_debug("%s no queue(EINVAL)\n", __func__);
+		return -EINVAL;
+	}
+
+	_nbu2ss_ep_done(ep, req, -ECONNRESET);
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	u8		ep_adrs;
+	unsigned long	flags;
+
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (!_ep) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if (!ep) {
+		ERR("%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (!udc) {
+		ERR(" *** %s, bad udc\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	ep_adrs = ep->epnum | ep->direct;
+	if (value == 0) {
+		_nbu2ss_set_endpoint_stall(udc, ep_adrs, value);
+		ep->stalled = FALSE;
+	} else {
+		if (list_empty(&ep->queue))
+			_nbu2ss_epn_set_stall(udc, ep);
+		else
+			ep->stalled = TRUE;
+	}
+
+	if (value == 0)
+		ep->wedged = 0;
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+static int nbu2ss_ep_set_wedge(struct usb_ep *_ep)
+{
+	return nbu2ss_ep_set_halt(_ep, 1);
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_ep_fifo_status(struct usb_ep *_ep)
+{
+	u32		data;
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+	PT_FC_REGS		preg;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (!_ep) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if (!ep) {
+		ERR("%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (!udc) {
+		ERR("%s, bad udc\n", __func__);
+		return -EINVAL;
+	}
+
+	preg = udc->p_regs;
+
+	data = gpio_get_value(VBUS_VALUE);
+	if (data == 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	if (ep->epnum == 0) {
+		data = _nbu2ss_readl(&preg->EP0_LENGTH) & EP0_LDATA;
+
+	} else {
+		data = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_LEN_DCNT)
+			& EPn_LDATA;
+	}
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void  nbu2ss_ep_fifo_flush(struct usb_ep *_ep)
+{
+	u32			data;
+	struct nbu2ss_ep	*ep;
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (!_ep) {
+		ERR("%s, bad param\n", __func__);
+		return;
+	}
+
+	ep = container_of(_ep, struct nbu2ss_ep, ep);
+	if (!_ep) {
+		ERR("%s, bad ep\n", __func__);
+		return;
+	}
+
+	udc = ep->udc;
+	if (!udc) {
+		ERR("%s, bad udc\n", __func__);
+		return;
+	}
+
+	data = gpio_get_value(VBUS_VALUE);
+	if (data == 0)
+		return;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	_nbu2ss_fifo_flush(udc, ep);
+	spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static struct usb_ep_ops nbu2ss_ep_ops = {
+	.enable		= nbu2ss_ep_enable,
+	.disable	= nbu2ss_ep_disable,
+
+	.alloc_request	= nbu2ss_ep_alloc_request,
+	.free_request	= nbu2ss_ep_free_request,
+
+	.queue		= nbu2ss_ep_queue,
+	.dequeue	= nbu2ss_ep_dequeue,
+
+	.set_halt	= nbu2ss_ep_set_halt,
+	.set_wedge	= nbu2ss_ep_set_wedge,
+
+	.fifo_status	= nbu2ss_ep_fifo_status,
+	.fifo_flush	= nbu2ss_ep_fifo_flush,
+};
+
+
+/*-------------------------------------------------------------------------*/
+/* usb_gadget_ops */
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_get_frame(struct usb_gadget *pgadget)
+{
+	u32			data;
+	struct nbu2ss_udc	*udc;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (pgadget == NULL) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = container_of(pgadget, struct nbu2ss_udc, gadget);
+	if (udc == NULL) {
+		ERR("%s, udc == NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	data = gpio_get_value(VBUS_VALUE);
+	if (data == 0)
+		return -EINVAL;
+
+	data = _nbu2ss_readl(&udc->p_regs->USB_ADDRESS) & FRAME;
+
+	return data;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget)
+{
+	int	i;
+	u32	data;
+
+	struct nbu2ss_udc	*udc;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (pgadget == NULL) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = container_of(pgadget, struct nbu2ss_udc, gadget);
+	if (udc == NULL) {
+		ERR("%s, udc == NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	data = gpio_get_value(VBUS_VALUE);
+	if (data == 0) {
+		pr_warning("VBUS LEVEL = %d\n", data);
+		return -EINVAL;
+	}
+
+	_nbu2ss_bitset(&udc->p_regs->EPCTR, PLL_RESUME);
+
+	for (i = 0; i < EPC_PLL_LOCK_COUNT; i++) {
+		data = _nbu2ss_readl(&udc->p_regs->EPCTR);
+
+		if (data & PLL_LOCK)
+			break;
+	}
+
+	_nbu2ss_bitclr(&udc->p_regs->EPCTR, PLL_RESUME);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
+					int is_selfpowered)
+{
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (pgadget == NULL) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = container_of(pgadget, struct nbu2ss_udc, gadget);
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->self_powered = (is_selfpowered != 0);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_vbus_session(struct usb_gadget *pgadget, int is_active)
+{
+/*	INFO("=== %s()\n", __func__); */
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_vbus_draw(struct usb_gadget *pgadget, unsigned mA)
+{
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (pgadget == NULL) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = container_of(pgadget, struct nbu2ss_udc, gadget);
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->mA = mA;
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_pullup(struct usb_gadget *pgadget, int is_on)
+{
+	struct nbu2ss_udc	*udc;
+	unsigned long		flags;
+
+/*	INFO("=== %s()\n", __func__); */
+
+	if (pgadget == NULL) {
+		ERR("%s, bad param\n", __func__);
+		return -EINVAL;
+	}
+
+	udc = container_of(pgadget, struct nbu2ss_udc, gadget);
+
+	if (udc->driver == NULL) {
+		pr_warning("%s, Not Regist Driver\n", __func__);
+		return -EINVAL;
+	}
+
+	if (udc->vbus_active == 0)
+		return -ESHUTDOWN;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	_nbu2ss_pullup(udc, is_on);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_gad_ioctl(
+	struct usb_gadget *pgadget,
+	unsigned code,
+	unsigned long param)
+{
+/*	INFO("=== %s()\n", __func__); */
+	return 0;
+}
+
+
+static const struct usb_gadget_ops nbu2ss_gadget_ops = {
+	.get_frame		= nbu2ss_gad_get_frame,
+	.wakeup			= nbu2ss_gad_wakeup,
+	.set_selfpowered	= nbu2ss_gad_set_selfpowered,
+	.vbus_session		= nbu2ss_gad_vbus_session,
+	.vbus_draw		= nbu2ss_gad_vbus_draw,
+	.pullup			= nbu2ss_gad_pullup,
+	.ioctl			= nbu2ss_gad_ioctl,
+};
+
+static char g_ep0_name[] = "ep0";
+static char g_ep1_name[] = "ep1-bulk";
+static char g_ep2_name[] = "ep2-bulk";
+static char g_ep3_name[] = "ep3in-int";
+static char g_ep4_name[] = "ep4-iso";
+static char g_ep5_name[] = "ep5-iso";
+static char g_ep6_name[] = "ep6-bulk";
+static char g_ep7_name[] = "ep7-bulk";
+static char g_ep8_name[] = "ep8in-int";
+static char g_ep9_name[] = "ep9-iso";
+static char g_epa_name[] = "epa-iso";
+static char g_epb_name[] = "epb-bulk";
+static char g_epc_name[] = "epc-nulk";
+static char g_epd_name[] = "epdin-int";
+
+static char *gp_ep_name[NUM_ENDPOINTS] = {
+	g_ep0_name,
+	g_ep1_name,
+	g_ep2_name,
+	g_ep3_name,
+	g_ep4_name,
+	g_ep5_name,
+	g_ep6_name,
+	g_ep7_name,
+	g_ep8_name,
+	g_ep9_name,
+	g_epa_name,
+	g_epb_name,
+	g_epc_name,
+	g_epd_name,
+};
+
+/*-------------------------------------------------------------------------*/
+static void __init nbu2ss_drv_set_ep_info(
+	struct nbu2ss_udc	*udc,
+	struct nbu2ss_ep	*ep,
+	u8 *name)
+{
+	ep->udc = udc;
+	ep->desc = NULL;
+
+	ep->ep.driver_data = NULL;
+	ep->ep.name = name;
+	ep->ep.ops = &nbu2ss_ep_ops;
+
+	if (isdigit(name[2])) {
+
+		long	num;
+		int	res;
+		char	tempbuf[2];
+
+		tempbuf[0] = name[2];
+		tempbuf[1] = '\0';
+		res = kstrtol(tempbuf, 16, &num);
+
+		if (num == 0)
+			ep->ep.maxpacket = EP0_PACKETSIZE;
+		else
+			ep->ep.maxpacket = EP_PACKETSIZE;
+
+	} else {
+		ep->ep.maxpacket = EP_PACKETSIZE;
+	}
+
+	list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+	INIT_LIST_HEAD(&ep->queue);
+}
+
+/*-------------------------------------------------------------------------*/
+static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
+{
+	int	i;
+
+	INIT_LIST_HEAD(&udc->gadget.ep_list);
+	udc->gadget.ep0 = &udc->ep[0].ep;
+
+
+	for (i = 0; i < NUM_ENDPOINTS; i++)
+		nbu2ss_drv_set_ep_info(udc, &udc->ep[i], gp_ep_name[i]);
+
+	list_del_init(&udc->ep[0].ep.ep_list);
+}
+
+/*-------------------------------------------------------------------------*/
+/* platform_driver */
+static int __init nbu2ss_drv_contest_init(
+	struct platform_device *pdev,
+	struct nbu2ss_udc *udc)
+{
+	spin_lock_init(&udc->lock);
+	udc->dev = &pdev->dev;
+
+	udc->self_powered = 1;
+	udc->devstate = USB_STATE_NOTATTACHED;
+	udc->pdev = pdev;
+	udc->mA = 0;
+
+	udc->pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	/* init Endpoint */
+	nbu2ss_drv_ep_init(udc);
+
+	/* init Gadget */
+	udc->gadget.ops = &nbu2ss_gadget_ops;
+	udc->gadget.ep0 = &udc->ep[0].ep;
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->gadget.name = driver_name;
+	/* udc->gadget.is_dualspeed = 1; */
+
+	device_initialize(&udc->gadget.dev);
+
+	dev_set_name(&udc->gadget.dev, "gadget");
+	udc->gadget.dev.parent = &pdev->dev;
+	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+	return 0;
+}
+
+/*
+ *	probe - binds to the platform device
+ */
+static int nbu2ss_drv_probe(struct platform_device *pdev)
+{
+	int	status = -ENODEV;
+	struct nbu2ss_udc	*udc;
+	struct resource *r;
+	int irq;
+	void __iomem *mmio_base;
+
+	udc = &udc_controller;
+	memset(udc, 0, sizeof(struct nbu2ss_udc));
+
+	platform_set_drvdata(pdev, udc);
+
+	/* require I/O memory and IRQ to be provided as resources */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mmio_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(mmio_base))
+		return PTR_ERR(mmio_base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get IRQ\n");
+		return irq;
+	}
+	status = devm_request_irq(&pdev->dev, irq, _nbu2ss_udc_irq,
+				  0, driver_name, udc);
+
+	/* IO Memory */
+	udc->p_regs = (PT_FC_REGS)mmio_base;
+
+	/* USB Function Controller Interrupt */
+	if (status != 0) {
+		ERR("request_irq(USB_UDC_IRQ_1) failed\n");
+		goto cleanup1;
+	}
+
+	/* Driver Initialization */
+	status = nbu2ss_drv_contest_init(pdev, udc);
+	if (status < 0) {
+		/* Error */
+		goto cleanup1;
+	}
+
+	/* VBUS Interrupt */
+	irq_set_irq_type(INT_VBUS, IRQ_TYPE_EDGE_BOTH);
+	status = request_irq(INT_VBUS,
+				_nbu2ss_vbus_irq,
+				IRQF_SHARED,
+				driver_name,
+				udc);
+
+	if (status != 0) {
+		ERR("request_irq(INT_VBUS) failed\n");
+		goto cleanup1;
+	}
+
+	return status;
+
+cleanup1:
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+static void nbu2ss_drv_shutdown(struct platform_device *pdev)
+{
+	struct nbu2ss_udc	*udc;
+
+	udc = platform_get_drvdata(pdev);
+	if (udc == NULL)
+		return;
+
+	_nbu2ss_disable_controller(udc);
+}
+
+/*-------------------------------------------------------------------------*/
+static int __exit nbu2ss_drv_remove(struct platform_device *pdev)
+{
+	struct nbu2ss_udc	*udc;
+	struct nbu2ss_ep	*ep;
+	int	i;
+
+	udc = &udc_controller;
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+		if (ep->virt_buf)
+			dma_free_coherent(NULL, PAGE_SIZE,
+				(void *)ep->virt_buf, ep->phys_buf);
+	}
+
+	/* Interrupt Handler - Release */
+	free_irq(INT_VBUS, udc);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct nbu2ss_udc	*udc;
+
+	udc = platform_get_drvdata(pdev);
+	if (udc == NULL)
+		return 0;
+
+	if (udc->vbus_active) {
+		udc->vbus_active = 0;
+		udc->devstate = USB_STATE_NOTATTACHED;
+		udc->linux_suspended = 1;
+
+		if (udc->usb_suspended) {
+			udc->usb_suspended = 0;
+			_nbu2ss_reset_controller(udc);
+		}
+
+		_nbu2ss_quiesce(udc);
+	}
+	_nbu2ss_disable_controller(udc);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int nbu2ss_drv_resume(struct platform_device *pdev)
+{
+	u32	data;
+	struct nbu2ss_udc	*udc;
+
+	udc = platform_get_drvdata(pdev);
+	if (udc == NULL)
+		return 0;
+
+	data = gpio_get_value(VBUS_VALUE);
+	if (data) {
+		udc->vbus_active = 1;
+		udc->devstate = USB_STATE_POWERED;
+		_nbu2ss_enable_controller(udc);
+		_nbu2ss_pullup(udc, 1);
+	}
+
+	udc->linux_suspended = 0;
+
+	return 0;
+}
+
+
+static struct platform_driver udc_driver = {
+	.probe		= nbu2ss_drv_probe,
+	.shutdown	= nbu2ss_drv_shutdown,
+	.remove		= __exit_p(nbu2ss_drv_remove),
+	.suspend	= nbu2ss_drv_suspend,
+	.resume		= nbu2ss_drv_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= driver_name,
+	},
+};
+
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Renesas Electronics Corporation");
+MODULE_LICENSE("GPL");
+
+
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/emxx_udc/emxx_udc.h linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/emxx_udc.h
--- linux-libre-3.16-gnu/drivers/staging/emxx_udc/emxx_udc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/emxx_udc.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,653 @@
+/*
+ *  EMXX FCD (Function Controller Driver) for USB.
+ *
+ *  Copyright (C) 2010 Renesas Electronics Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+ */
+
+
+
+
+#ifndef _LINUX_EMXX_H
+#define _LINUX_EMXX_H
+
+
+
+/*---------------------------------------------------------------------------*/
+/*----------------- Default undef */
+#if 0
+#define DEBUG
+#define UDC_DEBUG_DUMP
+#endif
+
+/* #define USE_INT_COUNT_OVER */
+
+/*----------------- Default define */
+#define	USE_DMA	1
+#define USE_SUSPEND_WAIT	1
+
+
+
+#ifndef TRUE
+#define TRUE	1
+#define FALSE	0
+#endif
+
+
+/*------------ Board dependence(Resource) */
+#define	VBUS_VALUE		GPIO_VBUS
+
+/* below hacked up for staging integration */
+#define GPIO_VBUS 0 /* GPIO_P153 on KZM9D */
+#define INT_VBUS 0 /* IRQ for GPIO_P153 */
+
+/*------------ Board dependence(Wait) */
+
+/* CHATTERING wait time ms */
+#define VBUS_CHATTERING_MDELAY		1
+/* DMA Abort wait time ms */
+#define DMA_DISABLE_TIME		10
+
+
+
+/*------------ Controller dependence */
+#define NUM_ENDPOINTS		14		/* Endpoint */
+#define REG_EP_NUM		15		/* Endpoint Register */
+#define DMA_MAX_COUNT		256		/* DMA Block */
+
+
+
+#define EPC_RST_DISABLE_TIME		1	/* 1 usec */
+#define EPC_DIRPD_DISABLE_TIME		1	/* 1 msec */
+#define EPC_PLL_LOCK_COUNT		1000	/* 1000 */
+#define IN_DATA_EMPTY_COUNT		1000	/* 1000 */
+
+#define CHATGER_TIME			700	/* 700msec */
+#define USB_SUSPEND_TIME		2000	/* 2 sec */
+
+
+/* U2F FLAG */
+#define U2F_ENABLE		1
+#define U2F_DISABLE		0
+
+
+/*------- BIT */
+#define BIT00		0x00000001
+#define BIT01		0x00000002
+#define BIT02		0x00000004
+#define BIT03		0x00000008
+#define BIT04		0x00000010
+#define BIT05		0x00000020
+#define BIT06		0x00000040
+#define BIT07		0x00000080
+#define BIT08		0x00000100
+#define BIT09		0x00000200
+#define BIT10		0x00000400
+#define BIT11		0x00000800
+#define BIT12		0x00001000
+#define BIT13		0x00002000
+#define BIT14		0x00004000
+#define BIT15		0x00008000
+#define BIT16		0x00010000
+#define BIT17		0x00020000
+#define BIT18		0x00040000
+#define BIT19		0x00080000
+#define BIT20		0x00100000
+#define BIT21		0x00200000
+#define BIT22		0x00400000
+#define BIT23		0x00800000
+#define BIT24		0x01000000
+#define BIT25		0x02000000
+#define BIT26		0x04000000
+#define BIT27		0x08000000
+#define BIT28		0x10000000
+#define BIT29		0x20000000
+#define BIT30		0x40000000
+#define BIT31		0x80000000
+
+#if 0
+/*------- (0x0000) USB Control Register */
+#define USBTESTMODE			(BIT18+BIT17+BIT16)
+#define TEST_J				BIT16
+#define TEST_K				BIT17
+#define TEST_SE0_NAK			(BIT17+BIT16)
+#define TEST_PACKET			BIT18
+#endif
+#define TEST_FORCE_ENABLE		(BIT18+BIT16)
+
+#define INT_SEL				BIT10
+#define CONSTFS				BIT09
+#define SOF_RCV				BIT08
+#define RSUM_IN				BIT07
+#define SUSPEND				BIT06
+#define CONF				BIT05
+#define DEFAULT				BIT04
+#define CONNECTB			BIT03
+#define PUE2				BIT02
+
+#define MAX_TEST_MODE_NUM		0x05
+#define TEST_MODE_SHIFT			16
+
+/*------- (0x0004) USB Status Register */
+#define SPEED_MODE			BIT06
+#define HIGH_SPEED			BIT06
+
+#define CONF				BIT05
+#define DEFAULT				BIT04
+#define USB_RST				BIT03
+#define SPND_OUT			BIT02
+#define RSUM_OUT			BIT01
+
+/*------- (0x0008) USB Address Register */
+#define USB_ADDR			0x007F0000
+#define SOF_STATUS			BIT15
+#define UFRAME				(BIT14+BIT13+BIT12)
+#define FRAME				0x000007FF
+
+#define USB_ADRS_SHIFT			16
+
+/*------- (0x000C) UTMI Characteristic 1 Register */
+#define SQUSET				(BIT07+BIT06+BIT05+BIT04)
+
+#define USB_SQUSET			(BIT06+BIT05+BIT04)
+
+/*------- (0x0010) TEST Control Register */
+#define FORCEHS				BIT02
+#define CS_TESTMODEEN			BIT01
+#define LOOPBACK			BIT00
+
+/*------- (0x0018) Setup Data 0 Register */
+/*------- (0x001C) Setup Data 1 Register */
+
+/*------- (0x0020) USB Interrupt Status Register */
+#define EPn_INT				0x00FFFF00
+#define EP15_INT			BIT23
+#define EP14_INT			BIT22
+#define EP13_INT			BIT21
+#define EP12_INT			BIT20
+#define EP11_INT			BIT19
+#define EP10_INT			BIT18
+#define EP9_INT				BIT17
+#define EP8_INT				BIT16
+#define EP7_INT				BIT15
+#define EP6_INT				BIT14
+#define EP5_INT				BIT13
+#define EP4_INT				BIT12
+#define EP3_INT				BIT11
+#define EP2_INT				BIT10
+#define EP1_INT				BIT09
+#define EP0_INT				BIT08
+#define SPEED_MODE_INT			BIT06
+#define SOF_ERROR_INT			BIT05
+#define SOF_INT				BIT04
+#define USB_RST_INT			BIT03
+#define SPND_INT			BIT02
+#define RSUM_INT			BIT01
+
+#define USB_INT_STA_RW			0x7E
+
+/*------- (0x0024) USB Interrupt Enable Register */
+#define EP15_0_EN			0x00FFFF00
+#define EP15_EN				BIT23
+#define EP14_EN				BIT22
+#define EP13_EN				BIT21
+#define EP12_EN				BIT20
+#define EP11_EN				BIT19
+#define EP10_EN				BIT18
+#define EP9_EN				BIT17
+#define EP8_EN				BIT16
+#define EP7_EN				BIT15
+#define EP6_EN				BIT14
+#define EP5_EN				BIT13
+#define EP4_EN				BIT12
+#define EP3_EN				BIT11
+#define EP2_EN				BIT10
+#define EP1_EN				BIT09
+#define EP0_EN				BIT08
+#define SPEED_MODE_EN			BIT06
+#define SOF_ERROR_EN			BIT05
+#define SOF_EN				BIT04
+#define USB_RST_EN			BIT03
+#define SPND_EN				BIT02
+#define RSUM_EN				BIT01
+
+#define USB_INT_EN_BIT	\
+	(EP0_EN|SPEED_MODE_EN|USB_RST_EN|SPND_EN|RSUM_EN)
+
+/*------- (0x0028) EP0 Control Register */
+#define EP0_STGSEL			BIT18
+#define EP0_OVERSEL			BIT17
+#define EP0_AUTO			BIT16
+#define EP0_PIDCLR			BIT09
+#define EP0_BCLR			BIT08
+#define EP0_DEND			BIT07
+#define EP0_DW				(BIT06+BIT05)
+#define EP0_DW4				0
+#define EP0_DW3				(BIT06+BIT05)
+#define EP0_DW2				BIT06
+#define EP0_DW1				BIT05
+
+#define EP0_INAK_EN			BIT04
+#define EP0_PERR_NAK_CLR		BIT03
+#define EP0_STL				BIT02
+#define EP0_INAK			BIT01
+#define EP0_ONAK			BIT00
+
+/*------- (0x002C) EP0 Status Register */
+#define EP0_PID				BIT18
+#define EP0_PERR_NAK			BIT17
+#define EP0_PERR_NAK_INT		BIT16
+#define EP0_OUT_NAK_INT			BIT15
+#define EP0_OUT_NULL			BIT14
+#define EP0_OUT_FULL			BIT13
+#define EP0_OUT_EMPTY			BIT12
+#define EP0_IN_NAK_INT			BIT11
+#define EP0_IN_DATA			BIT10
+#define EP0_IN_FULL			BIT09
+#define EP0_IN_EMPTY			BIT08
+#define EP0_OUT_NULL_INT		BIT07
+#define EP0_OUT_OR_INT			BIT06
+#define EP0_OUT_INT			BIT05
+#define EP0_IN_INT			BIT04
+#define EP0_STALL_INT			BIT03
+#define STG_END_INT			BIT02
+#define STG_START_INT			BIT01
+#define SETUP_INT			BIT00
+
+#define EP0_STATUS_RW_BIT	(BIT16|BIT15|BIT11|0xFF)
+
+/*------- (0x0030) EP0 Interrupt Enable Register */
+#define EP0_PERR_NAK_EN			BIT16
+#define EP0_OUT_NAK_EN			BIT15
+
+#define EP0_IN_NAK_EN			BIT11
+
+#define EP0_OUT_NULL_EN			BIT07
+#define EP0_OUT_OR_EN			BIT06
+#define EP0_OUT_EN			BIT05
+#define EP0_IN_EN			BIT04
+#define EP0_STALL_EN			BIT03
+#define STG_END_EN			BIT02
+#define STG_START_EN			BIT01
+#define SETUP_EN			BIT00
+
+#define EP0_INT_EN_BIT	\
+	(EP0_OUT_OR_EN|EP0_OUT_EN|EP0_IN_EN|STG_END_EN|SETUP_EN)
+
+/*------- (0x0034) EP0 Length Register */
+#define EP0_LDATA			0x0000007F
+
+/*------- (0x0038) EP0 Read Register */
+/*------- (0x003C) EP0 Write Register */
+
+/*------- (0x0040:) EPn Control Register */
+#define EPn_EN				BIT31
+#define EPn_BUF_TYPE			BIT30
+#define EPn_BUF_SINGLE			BIT30
+
+#define EPn_DIR0			BIT26
+#define EPn_MODE			(BIT25+BIT24)
+#define EPn_BULK			0
+#define EPn_INTERRUPT			BIT24
+#define EPn_ISO				BIT25
+
+#define EPn_OVERSEL			BIT17
+#define EPn_AUTO			BIT16
+
+#define EPn_IPIDCLR			BIT11
+#define EPn_OPIDCLR			BIT10
+#define EPn_BCLR			BIT09
+#define EPn_CBCLR			BIT08
+#define EPn_DEND			BIT07
+#define EPn_DW				(BIT06+BIT05)
+#define EPn_DW4				0
+#define EPn_DW3				(BIT06+BIT05)
+#define EPn_DW2				BIT06
+#define EPn_DW1				BIT05
+
+#define EPn_OSTL_EN			BIT04
+#define EPn_ISTL			BIT03
+#define EPn_OSTL			BIT02
+
+#define EPn_ONAK			BIT00
+
+/*------- (0x0044:) EPn Status Register	*/
+#define EPn_ISO_PIDERR			BIT29		/* R */
+#define EPn_OPID			BIT28		/* R */
+#define EPn_OUT_NOTKN			BIT27		/* R */
+#define EPn_ISO_OR			BIT26		/* R */
+
+#define EPn_ISO_CRC			BIT24		/* R */
+#define EPn_OUT_END_INT			BIT23		/* RW */
+#define EPn_OUT_OR_INT			BIT22		/* RW */
+#define EPn_OUT_NAK_ERR_INT		BIT21		/* RW */
+#define EPn_OUT_STALL_INT		BIT20		/* RW */
+#define EPn_OUT_INT			BIT19		/* RW */
+#define EPn_OUT_NULL_INT		BIT18		/* RW */
+#define EPn_OUT_FULL			BIT17		/* R */
+#define EPn_OUT_EMPTY			BIT16		/* R */
+
+#define EPn_IPID			BIT10		/* R */
+#define EPn_IN_NOTKN			BIT09		/* R */
+#define EPn_ISO_UR			BIT08		/* R */
+#define EPn_IN_END_INT			BIT07		/* RW */
+
+#define EPn_IN_NAK_ERR_INT		BIT05		/* RW */
+#define EPn_IN_STALL_INT		BIT04		/* RW */
+#define EPn_IN_INT			BIT03		/* RW */
+#define EPn_IN_DATA			BIT02		/* R */
+#define EPn_IN_FULL			BIT01		/* R */
+#define EPn_IN_EMPTY			BIT00		/* R */
+
+#define EPn_INT_EN	\
+	(EPn_OUT_END_INT|EPn_OUT_INT|EPn_IN_END_INT|EPn_IN_INT)
+
+/*------- (0x0048:) EPn Interrupt Enable Register */
+#define EPn_OUT_END_EN			BIT23		/* RW */
+#define EPn_OUT_OR_EN			BIT22		/* RW */
+#define EPn_OUT_NAK_ERR_EN		BIT21		/* RW */
+#define EPn_OUT_STALL_EN		BIT20		/* RW */
+#define EPn_OUT_EN			BIT19		/* RW */
+#define EPn_OUT_NULL_EN			BIT18		/* RW */
+
+#define EPn_IN_END_EN			BIT07		/* RW */
+
+#define EPn_IN_NAK_ERR_EN		BIT05		/* RW */
+#define EPn_IN_STALL_EN			BIT04		/* RW */
+#define EPn_IN_EN			BIT03		/* RW */
+
+/*------- (0x004C:) EPn Interrupt Enable Register */
+#define EPn_STOP_MODE			BIT11
+#define EPn_DEND_SET			BIT10
+#define EPn_BURST_SET			BIT09
+#define EPn_STOP_SET			BIT08
+
+#define EPn_DMA_EN			BIT04
+
+#define EPn_DMAMODE0			BIT00
+
+/*------- (0x0050:) EPn MaxPacket & BaseAddress Register */
+#define EPn_BASEAD			0x1FFF0000
+#define EPn_MPKT			0x000007FF
+
+/*------- (0x0054:) EPn Length & DMA Count Register */
+#define EPn_DMACNT			0x01FF0000
+#define EPn_LDATA			0x000007FF
+
+/*------- (0x0058:) EPn Read Register */
+/*------- (0x005C:) EPn Write Register */
+
+/*------- (0x1000) AHBSCTR Register */
+#define WAIT_MODE			BIT00
+
+/*------- (0x1004) AHBMCTR Register */
+#define ARBITER_CTR			BIT31		/* RW */
+#define MCYCLE_RST			BIT12		/* RW */
+
+#define ENDIAN_CTR			(BIT09+BIT08)	/* RW */
+#define ENDIAN_BYTE_SWAP		BIT09
+#define ENDIAN_HALF_WORD_SWAP		ENDIAN_CTR
+
+#define HBUSREQ_MODE			BIT05		/* RW */
+#define HTRANS_MODE			BIT04		/* RW */
+
+#define WBURST_TYPE			BIT02		/* RW */
+#define BURST_TYPE			(BIT01+BIT00)	/* RW */
+#define BURST_MAX_16			0
+#define BURST_MAX_8			BIT00
+#define BURST_MAX_4			BIT01
+#define BURST_SINGLE			BURST_TYPE
+
+/*------- (0x1008) AHBBINT Register */
+#define DMA_ENDINT			0xFFFE0000	/* RW */
+
+#define AHB_VBUS_INT			BIT13		/* RW */
+
+#define MBUS_ERRINT			BIT06		/* RW */
+
+#define SBUS_ERRINT0			BIT04		/* RW */
+#define ERR_MASTER			0x0000000F	/* R */
+
+/*------- (0x100C) AHBBINTEN Register */
+#define DMA_ENDINTEN			0xFFFE0000	/* RW */
+
+#define VBUS_INTEN			BIT13		/* RW */
+
+#define MBUS_ERRINTEN			BIT06		/* RW */
+
+#define SBUS_ERRINT0EN			BIT04		/* RW */
+
+/*------- (0x1010) EPCTR Register */
+#define DIRPD				BIT12		/* RW */
+
+#define VBUS_LEVEL			BIT08		/* R */
+
+#define PLL_RESUME			BIT05		/* RW */
+#define PLL_LOCK			BIT04		/* R */
+
+#ifdef CONFIG_MACH_EMGR
+#define PLL_RST				BIT02		/* RW */
+#endif
+
+#define EPC_RST				BIT00		/* RW */
+
+/*------- (0x1014) USBF_EPTEST Register */
+#define LINESTATE			(BIT09+BIT08)	/* R */
+#define DM_LEVEL			BIT09		/* R */
+#define DP_LEVEL			BIT08		/* R */
+
+#define PHY_TST				BIT01		/* RW */
+#define PHY_TSTCLK			BIT00		/* RW */
+
+/*------- (0x1020) USBSSVER Register */
+#define AHBB_VER			0x00FF0000	/* R */
+#define EPC_VER				0x0000FF00	/* R */
+#define SS_VER				0x000000FF	/* R */
+
+/*------- (0x1024) USBSSCONF Register */
+#define EP_AVAILABLE			0xFFFF0000	/* R */
+#define DMA_AVAILABLE			0x0000FFFF	/* R */
+
+/*------- (0x1110:) EPnDCR1 Register */
+#define DCR1_EPn_DMACNT			0x00FF0000	/* RW */
+
+#define DCR1_EPn_DIR0			BIT01		/* RW */
+#define DCR1_EPn_REQEN			BIT00		/* RW */
+
+/*------- (0x1114:) EPnDCR2 Register */
+#define DCR2_EPn_LMPKT			0x07FF0000	/* RW */
+
+#define DCR2_EPn_MPKT			0x000007FF	/* RW */
+
+/*------- (0x1118:) EPnTADR Register */
+#define EPn_TADR			0xFFFFFFFF	/* RW */
+
+
+
+/*===========================================================================*/
+/* Struct */
+/*------- T_EP_REGS */
+typedef struct _T_EP_REGS {
+	u32 EP_CONTROL;			/* EP Control */
+	u32 EP_STATUS;			/* EP Status */
+	u32 EP_INT_ENA;			/* EP Interrupt Enable */
+	u32 EP_DMA_CTRL;		/* EP DMA Control */
+	u32 EP_PCKT_ADRS;		/* EP Maxpacket & BaseAddress */
+	u32 EP_LEN_DCNT;		/* EP Length & DMA count */
+	u32 EP_READ;			/* EP Read */
+	u32 EP_WRITE;			/* EP Write */
+} T_EP_REGS, *PT_EP_REGS;
+
+/*------- T_EP_DCR */
+typedef struct _T_EP_DCR {
+	u32 EP_DCR1;			/* EP_DCR1 */
+	u32 EP_DCR2;			/* EP_DCR2 */
+	u32 EP_TADR;			/* EP_TADR */
+	u32 Reserved;			/* Reserved */
+} T_EP_DCR, *PT_EP_DCR;
+
+/*------- Function Registers */
+typedef struct _T_FC_REGS {
+	u32 USB_CONTROL;		/* (0x0000) USB Control */
+	u32 USB_STATUS;			/* (0x0004) USB Status */
+	u32 USB_ADDRESS;		/* (0x0008) USB Address */
+	u32 UTMI_CHARACTER_1;		/* (0x000C) UTMI Setting */
+	u32 TEST_CONTROL;		/* (0x0010) TEST Control */
+	u32 Reserved_14;		/* (0x0014) Reserved */
+	u32 SETUP_DATA0;		/* (0x0018) Setup Data0 */
+	u32 SETUP_DATA1;		/* (0x001C) Setup Data1 */
+	u32 USB_INT_STA;		/* (0x0020) USB Interrupt Status */
+	u32 USB_INT_ENA;		/* (0x0024) USB Interrupt Enable */
+	u32 EP0_CONTROL;		/* (0x0028) EP0 Control */
+	u32 EP0_STATUS;			/* (0x002C) EP0 Status */
+	u32 EP0_INT_ENA;		/* (0x0030) EP0 Interrupt Enable */
+	u32 EP0_LENGTH;			/* (0x0034) EP0 Length */
+	u32 EP0_READ;			/* (0x0038) EP0 Read */
+	u32 EP0_WRITE;			/* (0x003C) EP0 Write */
+
+	T_EP_REGS EP_REGS[REG_EP_NUM];	/* Endpoint Register */
+
+	u8 Reserved220[0x1000-0x220];	/* (0x0220:0x0FFF) Reserved */
+
+	u32 AHBSCTR;			/* (0x1000) AHBSCTR */
+	u32 AHBMCTR;			/* (0x1004) AHBMCTR */
+	u32 AHBBINT;			/* (0x1008) AHBBINT */
+	u32 AHBBINTEN;			/* (0x100C) AHBBINTEN */
+	u32 EPCTR;			/* (0x1010) EPCTR */
+	u32 USBF_EPTEST;		/* (0x1014) USBF_EPTEST */
+
+	u8 Reserved1018[0x20-0x18];	/* (0x1018:0x101F) Reserved */
+
+	u32 USBSSVER;			/* (0x1020) USBSSVER */
+	u32 USBSSCONF;			/* (0x1024) USBSSCONF */
+
+	u8 Reserved1028[0x110-0x28];	/* (0x1028:0x110F) Reserved */
+
+	T_EP_DCR EP_DCR[REG_EP_NUM];	/* */
+
+	u8 Reserved1200[0x1000-0x200];	/* Reserved */
+
+} __attribute__ ((aligned(32))) T_FC_REGS, *PT_FC_REGS;
+
+
+
+
+
+
+
+
+#define EP0_PACKETSIZE			64
+#define EP_PACKETSIZE			1024
+
+/* EPn RAM SIZE */
+#define D_RAM_SIZE_CTRL			64
+
+/* EPn Bulk Endpoint Max Packet Size */
+#define D_FS_RAM_SIZE_BULK		64
+#define D_HS_RAM_SIZE_BULK		512
+
+
+struct nbu2ss_udc;
+
+
+enum ep0_state {
+	EP0_IDLE,
+	EP0_IN_DATA_PHASE,
+	EP0_OUT_DATA_PHASE,
+	EP0_IN_STATUS_PHASE,
+	EP0_OUT_STATUS_PAHSE,
+	EP0_END_XFER,
+	EP0_SUSPEND,
+	EP0_STALL,
+};
+
+struct nbu2ss_req {
+	struct usb_request		req;
+	struct list_head		queue;
+
+	u32			div_len;
+	bool		dma_flag;
+	bool		zero;
+
+	bool		unaligned;
+
+	unsigned			mapped:1;
+};
+
+struct nbu2ss_ep {
+	struct usb_ep			ep;
+	struct list_head		queue;
+
+	struct nbu2ss_udc		*udc;
+
+	const struct usb_endpoint_descriptor *desc;
+
+	u8		epnum;
+	u8		direct;
+	u8		ep_type;
+
+	unsigned		wedged:1;
+	unsigned		halted:1;
+	unsigned		stalled:1;
+
+	u8		*virt_buf;
+	dma_addr_t	phys_buf;
+};
+
+
+struct nbu2ss_udc {
+	struct usb_gadget gadget;
+	struct usb_gadget_driver *driver;
+	struct platform_device *pdev;
+	struct device *dev;
+	spinlock_t lock;
+	struct completion		*pdone;
+
+	enum ep0_state			ep0state;
+	enum usb_device_state	devstate;
+	struct usb_ctrlrequest	ctrl;
+	struct nbu2ss_req		ep0_req;
+	u8		ep0_buf[EP0_PACKETSIZE];
+
+	struct nbu2ss_ep	ep[NUM_ENDPOINTS];
+
+	unsigned		softconnect:1;
+	unsigned		vbus_active:1;
+	unsigned		linux_suspended:1;
+	unsigned		linux_resume:1;
+	unsigned		usb_suspended:1;
+	unsigned		self_powered:1;
+	unsigned		remote_wakeup:1;
+	unsigned		udc_enabled:1;
+
+	unsigned		mA;
+
+	u32		curr_config;	/* Current Configuration Number */
+
+	PT_FC_REGS		p_regs;
+};
+
+/* USB register access structure */
+typedef volatile union {
+	struct {
+		unsigned char	DATA[4];
+	} byte;
+	unsigned int		dw;
+} USB_REG_ACCESS;
+
+/*-------------------------------------------------------------------------*/
+#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
+
+#endif  /* _LINUX_EMXX_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/emxx_udc/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/emxx_udc/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,10 @@
+config USB_EMXX
+	boolean "EMXX USB Function Device Controller"
+ 	depends on USB_GADGET && (ARCH_SHMOBILE || (ARM && COMPILE_TEST))
+	help
+	   The Emma Mobile series of SoCs from Renesas Electronics and
+	   former NEC Electronics include USB Function hardware.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "emxx_udc" and force all
+	   gadget drivers to also be dynamically linked.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/emxx_udc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/emxx_udc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_EMXX)	:= emxx_udc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/emxx_udc/TODO linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/TODO
--- linux-libre-3.16-gnu/drivers/staging/emxx_udc/TODO	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/emxx_udc/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,4 @@
+* add clock framework support (platform device with CCF needs special care)
+* break out board-specific VBUS GPIO to work with multiplatform
+* DT bindings
+* move driver into drivers/usb/gadget/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/et131x/et131x.c linux-libre-3.17-rc7-gnu/drivers/staging/et131x/et131x.c
--- linux-libre-3.16-gnu/drivers/staging/et131x/et131x.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/et131x/et131x.c	2014-09-28 17:29:07.000000000 -0400
@@ -285,7 +285,7 @@ struct fbr_lookup {
 	dma_addr_t	 buffsize;
 };
 
-/* struct rx_ring is the sructure representing the adaptor's local
+/* struct rx_ring is the structure representing the adaptor's local
  * reference(s) to the rings
  */
 struct rx_ring {
@@ -532,8 +532,6 @@ struct et131x_adapter {
 
 	/* Stats */
 	struct ce_stats stats;
-
-	struct net_device_stats net_stats;
 };
 
 static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status)
@@ -1423,22 +1421,16 @@ static int et131x_mii_read(struct et131x
  * @reg: the register to read
  * @value: 16-bit value to write
  */
-static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
+static int et131x_mii_write(struct et131x_adapter *adapter, u8 addr, u8 reg,
+			    u16 value)
 {
 	struct mac_regs __iomem *mac = &adapter->regs->mac;
-	struct phy_device *phydev = adapter->phydev;
 	int status = 0;
-	u8 addr;
 	u32 delay = 0;
 	u32 mii_addr;
 	u32 mii_cmd;
 	u32 mii_indicator;
 
-	if (!phydev)
-		return -EIO;
-
-	addr = phydev->addr;
-
 	/* Save a local copy of the registers we are dealing with so we can
 	 * set them back
 	 */
@@ -1633,17 +1625,7 @@ static int et131x_mdio_write(struct mii_
 	struct net_device *netdev = bus->priv;
 	struct et131x_adapter *adapter = netdev_priv(netdev);
 
-	return et131x_mii_write(adapter, reg, value);
-}
-
-static int et131x_mdio_reset(struct mii_bus *bus)
-{
-	struct net_device *netdev = bus->priv;
-	struct et131x_adapter *adapter = netdev_priv(netdev);
-
-	et131x_mii_write(adapter, MII_BMCR, BMCR_RESET);
-
-	return 0;
+	return et131x_mii_write(adapter, phy_addr, reg, value);
 }
 
 /*	et1310_phy_power_switch	-	PHY power control
@@ -1658,18 +1640,20 @@ static int et131x_mdio_reset(struct mii_
 static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down)
 {
 	u16 data;
+	struct  phy_device *phydev = adapter->phydev;
 
 	et131x_mii_read(adapter, MII_BMCR, &data);
 	data &= ~BMCR_PDOWN;
 	if (down)
 		data |= BMCR_PDOWN;
-	et131x_mii_write(adapter, MII_BMCR, data);
+	et131x_mii_write(adapter, phydev->addr, MII_BMCR, data);
 }
 
 /* et131x_xcvr_init - Init the phy if we are setting it into force mode */
 static void et131x_xcvr_init(struct et131x_adapter *adapter)
 {
 	u16 lcr2;
+	struct  phy_device *phydev = adapter->phydev;
 
 	/* Set the LED behavior such that LED 1 indicates speed (off =
 	 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
@@ -1690,7 +1674,7 @@ static void et131x_xcvr_init(struct et13
 		else
 			lcr2 |= (LED_VAL_LINKON << LED_TXRX_SHIFT);
 
-		et131x_mii_write(adapter, PHY_LED_2, lcr2);
+		et131x_mii_write(adapter, phydev->addr, PHY_LED_2, lcr2);
 	}
 }
 
@@ -1943,7 +1927,7 @@ static void et131x_disable_interrupts(st
 /* et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310 */
 static void et131x_tx_dma_disable(struct et131x_adapter *adapter)
 {
-	/* Setup the tramsmit dma configuration register */
+	/* Setup the transmit dma configuration register */
 	writel(ET_TXDMA_CSR_HALT | ET_TXDMA_SNGL_EPKT,
 					&adapter->regs->txdma.csr);
 }
@@ -2618,7 +2602,7 @@ static struct rfd *nic_rx_pkts(struct et
 		return NULL;
 	}
 
-	adapter->net_stats.rx_bytes += rfd->len;
+	adapter->netdev->stats.rx_bytes += rfd->len;
 
 	memcpy(skb_put(skb, rfd->len), fbr->virt[buff_index], rfd->len);
 
@@ -2666,7 +2650,7 @@ static void et131x_handle_recv_interrupt
 			continue;
 
 		/* Increment the number of packets we received */
-		adapter->net_stats.rx_packets++;
+		adapter->netdev->stats.rx_packets++;
 
 		/* Set the status on the packet, either resources or success */
 		if (rx_ring->num_ready_recv < RFD_LOW_WATER_MARK)
@@ -3037,7 +3021,7 @@ static int et131x_send_packets(struct sk
 			dev_kfree_skb_any(skb);
 			skb = NULL;
 
-			adapter->net_stats.tx_dropped++;
+			adapter->netdev->stats.tx_dropped++;
 		} else {
 			status = send_packet(skb, adapter);
 			if (status != 0 && status != -ENOMEM) {
@@ -3046,7 +3030,7 @@ static int et131x_send_packets(struct sk
 				 */
 				dev_kfree_skb_any(skb);
 				skb = NULL;
-				adapter->net_stats.tx_dropped++;
+				adapter->netdev->stats.tx_dropped++;
 			}
 		}
 	}
@@ -3065,7 +3049,7 @@ static inline void free_send_packet(stru
 {
 	unsigned long flags;
 	struct tx_desc *desc = NULL;
-	struct net_device_stats *stats = &adapter->net_stats;
+	struct net_device_stats *stats = &adapter->netdev->stats;
 	struct tx_ring *tx_ring = &adapter->tx_ring;
 	u64  dma_addr;
 
@@ -3110,7 +3094,7 @@ static inline void free_send_packet(stru
 	/* Add the TCB to the Ready Q */
 	spin_lock_irqsave(&adapter->tcb_ready_qlock, flags);
 
-	adapter->net_stats.tx_packets++;
+	stats->tx_packets++;
 
 	if (tx_ring->tcb_qtail)
 		tx_ring->tcb_qtail->next = tcb;
@@ -3645,14 +3629,14 @@ static void et131x_adjust_link(struct ne
 
 			et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG,
 					 &register18);
-			et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-					 register18 | 0x4);
-			et131x_mii_write(adapter, PHY_INDEX_REG,
+			et131x_mii_write(adapter, phydev->addr,
+					 PHY_MPHY_CONTROL_REG, register18 | 0x4);
+			et131x_mii_write(adapter, phydev->addr, PHY_INDEX_REG,
 					 register18 | 0x8402);
-			et131x_mii_write(adapter, PHY_DATA_REG,
+			et131x_mii_write(adapter, phydev->addr, PHY_DATA_REG,
 					 register18 | 511);
-			et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-					 register18);
+			et131x_mii_write(adapter, phydev->addr,
+					 PHY_MPHY_CONTROL_REG, register18);
 		}
 
 		et1310_config_flow_control(adapter);
@@ -3664,7 +3648,8 @@ static void et131x_adjust_link(struct ne
 			et131x_mii_read(adapter, PHY_CONFIG, &reg);
 			reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH;
 			reg |= ET_PHY_CONFIG_FIFO_DEPTH_32;
-			et131x_mii_write(adapter, PHY_CONFIG, reg);
+			et131x_mii_write(adapter, phydev->addr, PHY_CONFIG,
+					 reg);
 		}
 
 		et131x_set_rx_dma_timer(adapter);
@@ -3677,14 +3662,14 @@ static void et131x_adjust_link(struct ne
 
 			et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG,
 					 &register18);
-			et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-					 register18 | 0x4);
-			et131x_mii_write(adapter, PHY_INDEX_REG,
-					 register18 | 0x8402);
-			et131x_mii_write(adapter, PHY_DATA_REG,
-					 register18 | 511);
-			et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-					 register18);
+			et131x_mii_write(adapter, phydev->addr,
+					PHY_MPHY_CONTROL_REG, register18 | 0x4);
+			et131x_mii_write(adapter, phydev->addr,
+					PHY_INDEX_REG, register18 | 0x8402);
+			et131x_mii_write(adapter, phydev->addr,
+					PHY_DATA_REG, register18 | 511);
+			et131x_mii_write(adapter, phydev->addr,
+					PHY_MPHY_CONTROL_REG, register18);
 		}
 
 		/* Free the packets being actively sent & stopped */
@@ -4025,7 +4010,7 @@ static void et131x_isr_handler(struct wo
 	if (status & ET_INTR_RXDMA_STAT_LOW) {
 		/* Same idea as with the two Free Buffer Rings. Packets going
 		 * from the network to the host each consume a free buffer
-		 * resource and a packet status resource. These resoures are
+		 * resource and a packet status resource. These resources are
 		 * passed to the OS. When the OS is done with the resources,
 		 * they need to be returned to the ET1310. This is one method
 		 * of returning the resources.
@@ -4134,7 +4119,7 @@ out:
 static struct net_device_stats *et131x_stats(struct net_device *netdev)
 {
 	struct et131x_adapter *adapter = netdev_priv(netdev);
-	struct net_device_stats *stats = &adapter->net_stats;
+	struct net_device_stats *stats = &adapter->netdev->stats;
 	struct ce_stats *devstat = &adapter->stats;
 
 	stats->rx_errors = devstat->rx_length_errs +
@@ -4426,7 +4411,7 @@ static void et131x_tx_timeout(struct net
 				tcb->index,
 				tcb->flags);
 
-			adapter->net_stats.tx_errors++;
+			adapter->netdev->stats.tx_errors++;
 
 			/* perform reset of tx/rx */
 			et131x_disable_txrx(netdev);
@@ -4633,7 +4618,7 @@ static int et131x_pci_setup(struct pci_d
 	/* Allocate DMA memory */
 	rc = et131x_adapter_memory_alloc(adapter);
 	if (rc < 0) {
-		dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n");
+		dev_err(&pdev->dev, "Could not alloc adapter memory (DMA)\n");
 		goto err_iounmap;
 	}
 
@@ -4646,10 +4631,6 @@ static int et131x_pci_setup(struct pci_d
 	/* Copy address into the net_device struct */
 	memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN);
 
-	/* Init variable for counting how long we do not have link status */
-	adapter->boot_coma = 0;
-	et1310_disable_phy_coma(adapter);
-
 	rc = -ENOMEM;
 
 	/* Setup the mii_bus struct */
@@ -4665,7 +4646,6 @@ static int et131x_pci_setup(struct pci_d
 	adapter->mii_bus->priv = netdev;
 	adapter->mii_bus->read = et131x_mdio_read;
 	adapter->mii_bus->write = et131x_mdio_write;
-	adapter->mii_bus->reset = et131x_mdio_reset;
 	adapter->mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int),
 					      GFP_KERNEL);
 	if (!adapter->mii_bus->irq)
@@ -4689,6 +4669,10 @@ static int et131x_pci_setup(struct pci_d
 	/* Setup et1310 as per the documentation */
 	et131x_adapter_setup(adapter);
 
+	/* Init variable for counting how long we do not have link status */
+	adapter->boot_coma = 0;
+	et1310_disable_phy_coma(adapter);
+
 	/* We can enable interrupts now
 	 *
 	 *  NOTE - Because registration of interrupt handler is done in the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/et131x/et131x.h linux-libre-3.17-rc7-gnu/drivers/staging/et131x/et131x.h
--- linux-libre-3.16-gnu/drivers/staging/et131x/et131x.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/et131x/et131x.h	2014-09-28 17:29:07.000000000 -0400
@@ -145,7 +145,7 @@
  *31:	selfclr_disable
  */
 
-#define ET_RESET_ALL	0x007F;
+#define ET_RESET_ALL	0x007F
 
 /*
  * SLV Timer reg at address 0x002C (low 24 bits)
@@ -394,7 +394,7 @@ struct txdma_regs {			/* Location: */
  * 11-0: psr ndes
  */
 
-#define ET_RXDMA_PSR_NUM_DES_MASK	0xFFF;
+#define ET_RXDMA_PSR_NUM_DES_MASK	0xFFF
 
 /*
  * structure for packet status ring available offset reg in rxdma address map
@@ -755,7 +755,7 @@ struct txmac_regs {			/* Location: */
  */
 
 /*
- * structure for Unicast Paket Filter Address 1 reg in rxmac address map
+ * structure for Unicast Packet Filter Address 1 reg in rxmac address map
  * located at address 0x4068
  *
  * 31-24: addr1_3
@@ -769,7 +769,7 @@ struct txmac_regs {			/* Location: */
 #define ET_RX_UNI_PF_ADDR1_5_SHIFT 8
 
 /*
- * structure for Unicast Paket Filter Address 2 reg in rxmac address map
+ * structure for Unicast Packet Filter Address 2 reg in rxmac address map
  * located at address 0x406C
  *
  * 31-24: addr2_3
@@ -783,7 +783,7 @@ struct txmac_regs {			/* Location: */
 #define ET_RX_UNI_PF_ADDR2_5_SHIFT 8
 
 /*
- * structure for Unicast Paket Filter Address 1 & 2 reg in rxmac address map
+ * structure for Unicast Packet Filter Address 1 & 2 reg in rxmac address map
  * located at address 0x4070
  *
  * 31-24: addr2_1
@@ -815,11 +815,11 @@ struct txmac_regs {			/* Location: */
  * 0: filter_broad_en
  */
 
-#define ET_RX_PFCTRL_MIN_PKT_SZ_SHIFT		16;
-#define ET_RX_PFCTRL_FRAG_FILTER_ENABLE		0x0008;
-#define ET_RX_PFCTRL_UNICST_FILTER_ENABLE	0x0004;
-#define ET_RX_PFCTRL_MLTCST_FILTER_ENABLE	0x0002;
-#define ET_RX_PFCTRL_BRDCST_FILTER_ENABLE	0x0001;
+#define ET_RX_PFCTRL_MIN_PKT_SZ_SHIFT		16
+#define ET_RX_PFCTRL_FRAG_FILTER_ENABLE		0x0008
+#define ET_RX_PFCTRL_UNICST_FILTER_ENABLE	0x0004
+#define ET_RX_PFCTRL_MLTCST_FILTER_ENABLE	0x0002
+#define ET_RX_PFCTRL_BRDCST_FILTER_ENABLE	0x0001
 
 /*
  * structure for Memory Controller Interface Control Max Segment reg in rxmac
@@ -831,9 +831,9 @@ struct txmac_regs {			/* Location: */
  * 0: seg_en
  */
 
-#define ET_RX_MCIF_CTRL_MAX_SEG_SIZE_SHIFT	2;
-#define ET_RX_MCIF_CTRL_MAX_SEG_FC_ENABLE	0x0002;
-#define ET_RX_MCIF_CTRL_MAX_SEG_ENABLE		0x0001;
+#define ET_RX_MCIF_CTRL_MAX_SEG_SIZE_SHIFT	2
+#define ET_RX_MCIF_CTRL_MAX_SEG_FC_ENABLE	0x0002
+#define ET_RX_MCIF_CTRL_MAX_SEG_ENABLE		0x0001
 
 /*
  * structure for Memory Controller Interface Water Mark reg in rxmac address
@@ -987,15 +987,15 @@ struct rxmac_regs {					/* Location: */
  * 0: full duplex
  */
 
-#define ET_MAC_CFG2_PREAMBLE_SHIFT	12;
-#define ET_MAC_CFG2_IFMODE_MASK		0x0300;
-#define ET_MAC_CFG2_IFMODE_1000		0x0200;
-#define ET_MAC_CFG2_IFMODE_100		0x0100;
-#define ET_MAC_CFG2_IFMODE_HUGE_FRAME	0x0020;
-#define ET_MAC_CFG2_IFMODE_LEN_CHECK	0x0010;
-#define ET_MAC_CFG2_IFMODE_PAD_CRC	0x0004;
-#define ET_MAC_CFG2_IFMODE_CRC_ENABLE	0x0002;
-#define ET_MAC_CFG2_IFMODE_FULL_DPLX	0x0001;
+#define ET_MAC_CFG2_PREAMBLE_SHIFT	12
+#define ET_MAC_CFG2_IFMODE_MASK		0x0300
+#define ET_MAC_CFG2_IFMODE_1000		0x0200
+#define ET_MAC_CFG2_IFMODE_100		0x0100
+#define ET_MAC_CFG2_IFMODE_HUGE_FRAME	0x0020
+#define ET_MAC_CFG2_IFMODE_LEN_CHECK	0x0010
+#define ET_MAC_CFG2_IFMODE_PAD_CRC	0x0004
+#define ET_MAC_CFG2_IFMODE_CRC_ENABLE	0x0002
+#define ET_MAC_CFG2_IFMODE_FULL_DPLX	0x0001
 
 /*
  * structure for Interpacket gap reg in mac address map.
@@ -1084,7 +1084,7 @@ struct rxmac_regs {					/* Location: */
  * 15-0: phy control
  */
 
-#define ET_MAC_MIIMGMT_STAT_PHYCRTL_MASK 0xFFFF;
+#define ET_MAC_MIIMGMT_STAT_PHYCRTL_MASK 0xFFFF
 
 /*
  * structure for MII Management Indicators reg in mac address map.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/alphatrack.c linux-libre-3.17-rc7-gnu/drivers/staging/frontier/alphatrack.c
--- linux-libre-3.16-gnu/drivers/staging/frontier/alphatrack.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/alphatrack.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,849 +0,0 @@
-/*
- * Frontier Designs Alphatrack driver
- *
- * Copyright (C) 2007 Michael Taht (m@taht.net)
- *
- * Based on the usbled driver and ldusb drivers by
- *
- * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
- *
- * The ldusb driver was, in turn, derived from Lego USB Tower driver
- * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
- *		 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- *
- */
-
-/**
- * This driver uses a ring buffer for time critical reading of
- * interrupt in reports and provides read and write methods for
- * raw interrupt reports.
- */
-
-/*
- * Note: this currently uses a dumb ringbuffer for reads and writes.
- * A more optimal driver would cache and kill off outstanding urbs that are
- * now invalid, and ignore ones that already were in the queue but valid
- * as we only have 30 commands for the alphatrack. In particular this is
- * key for getting lights to flash in time as otherwise many commands
- * can be buffered up before the light change makes it to the interface.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kobject.h>
-#include <linux/mutex.h>
-
-#include <linux/uaccess.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/poll.h>
-
-#include "alphatrack.h"
-
-#define VENDOR_ID	0x165b
-#define PRODUCT_ID	0xfad1
-
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define USB_ALPHATRACK_MINOR_BASE	0
-#else
-/* FIXME 176 - is another driver's minor - apply for that */
-#define USB_ALPHATRACK_MINOR_BASE	176
-#endif
-
-/* table of devices that work with this driver */
-static const struct usb_device_id usb_alphatrack_table[] = {
-	{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, usb_alphatrack_table);
-MODULE_VERSION("0.41");
-MODULE_AUTHOR("Mike Taht <m@taht.net>");
-MODULE_DESCRIPTION("Alphatrack USB Driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Frontier Designs Alphatrack Control Surface");
-
-/* These aren't done yet */
-
-#define SUPPRESS_EXTRA_ONLINE_EVENTS 0
-#define BUFFERED_WRITES 0
-#define SUPPRESS_EXTRA_OFFLINE_EVENTS 0
-#define COMPRESS_FADER_EVENTS 0
-
-#define BUFFERED_READS 1
-#define RING_BUFFER_SIZE 512
-#define WRITE_BUFFER_SIZE 34
-#define ALPHATRACK_USB_TIMEOUT 10
-#define OUTPUT_CMD_SIZE 8
-#define INPUT_CMD_SIZE 12
-#define ALPHATRACK_DEBUG 0
-
-static int debug = ALPHATRACK_DEBUG;
-
-/* Use our own dbg macro */
-#define dbg_info(dev, format, arg...) do \
-	{ if (debug) dev_info(dev , format , ## arg); } while (0)
-
-#define alphatrack_ocmd_info(dev, cmd, format, arg...)
-
-#define alphatrack_icmd_info(dev, cmd, format, arg...)
-
-/* Module parameters */
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-/*
- * All interrupt in transfers are collected in a ring buffer to
- * avoid racing conditions and get better performance of the driver.
- */
-
-static int ring_buffer_size = RING_BUFFER_SIZE;
-
-module_param(ring_buffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size");
-
-/* The write_buffer can one day contain more than one interrupt out transfer.*/
-
-static int write_buffer_size = WRITE_BUFFER_SIZE;
-module_param(write_buffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
-
-/*
- * Increase the interval for debugging purposes.
- * or set to 1 to use the standard interval from the endpoint descriptors.
- */
-
-static int min_interrupt_in_interval = ALPHATRACK_USB_TIMEOUT;
-module_param(min_interrupt_in_interval, int, 0);
-MODULE_PARM_DESC(min_interrupt_in_interval,
-		 "Minimum interrupt in interval in ms");
-
-static int min_interrupt_out_interval = ALPHATRACK_USB_TIMEOUT;
-module_param(min_interrupt_out_interval, int, 0);
-MODULE_PARM_DESC(min_interrupt_out_interval,
-		 "Minimum interrupt out interval in ms");
-
-/* Structure to hold all of our device specific stuff */
-
-struct usb_alphatrack {
-	struct mutex mtx;	/* locks this structure */
-	struct usb_interface *intf;	/* save off the usb interface pointer */
-	int open_count;		/* number of times this port has been opened */
-
-	/* make gcc happy */
-	struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE];
-	struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE];
-	unsigned int ring_head;
-	unsigned int ring_tail;
-
-	wait_queue_head_t read_wait;
-	wait_queue_head_t write_wait;
-
-	unsigned char *interrupt_in_buffer;
-	unsigned char *oldi_buffer;
-	struct usb_endpoint_descriptor *interrupt_in_endpoint;
-	struct urb *interrupt_in_urb;
-	int interrupt_in_interval;
-	size_t interrupt_in_endpoint_size;
-	int interrupt_in_running;
-	int interrupt_in_done;
-
-	char *interrupt_out_buffer;
-	struct usb_endpoint_descriptor *interrupt_out_endpoint;
-	struct urb *interrupt_out_urb;
-	int interrupt_out_interval;
-	size_t interrupt_out_endpoint_size;
-	int interrupt_out_busy;
-
-	atomic_t writes_pending;
-	int event;		/* alternate interface to events */
-	int fader;		/* 10 bits */
-	int lights;		/* 23 bits */
-	unsigned char dump_state;	/* 0 if disabled 1 if enabled */
-	unsigned char enable;	/* 0 if disabled 1 if enabled */
-	unsigned char offline;	/* if the device is out of range or asleep */
-	unsigned char verbose;	/* be verbose in error reporting */
-	unsigned char last_cmd[OUTPUT_CMD_SIZE];
-	unsigned char screen[32];
-};
-
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
-/* forward declaration */
-
-static struct usb_driver usb_alphatrack_driver;
-
-/**
- *	usb_alphatrack_abort_transfers
- *      aborts transfers and frees associated data structures
- */
-static void usb_alphatrack_abort_transfers(struct usb_alphatrack *dev)
-{
-	/* shutdown transfer */
-	if (dev->interrupt_in_running) {
-		dev->interrupt_in_running = 0;
-		if (dev->intf)
-			usb_kill_urb(dev->interrupt_in_urb);
-	}
-	if (dev->interrupt_out_busy)
-		if (dev->intf)
-			usb_kill_urb(dev->interrupt_out_urb);
-}
-
-/** usb_alphatrack_delete */
-static void usb_alphatrack_delete(struct usb_alphatrack *dev)
-{
-	usb_alphatrack_abort_transfers(dev);
-	usb_free_urb(dev->interrupt_in_urb);
-	usb_free_urb(dev->interrupt_out_urb);
-	kfree(dev->ring_buffer);
-	kfree(dev->interrupt_in_buffer);
-	kfree(dev->interrupt_out_buffer);
-	kfree(dev->oldi_buffer);
-	kfree(dev->write_buffer);
-	kfree(dev);
-}
-
-/** usb_alphatrack_interrupt_in_callback */
-
-static void usb_alphatrack_interrupt_in_callback(struct urb *urb)
-{
-	struct usb_alphatrack *dev = urb->context;
-	unsigned int next_ring_head;
-	int retval = -1;
-
-	if (urb->status) {
-		if (urb->status == -ENOENT ||
-		    urb->status == -ECONNRESET || urb->status == -ESHUTDOWN) {
-			goto exit;
-		} else {
-			dbg_info(&dev->intf->dev,
-				 "%s: nonzero status received: %d\n", __func__,
-				 urb->status);
-			goto resubmit;	/* maybe we can recover */
-		}
-	}
-
-	if (urb->actual_length != INPUT_CMD_SIZE) {
-		dev_warn(&dev->intf->dev,
-			 "Urb length was %d bytes!! Do something intelligent\n",
-			 urb->actual_length);
-	} else {
-		alphatrack_ocmd_info(&dev->intf->dev,
-				     &(*dev->ring_buffer)[dev->ring_tail].cmd,
-				     "%s", "bla");
-		if (memcmp
-		    (dev->interrupt_in_buffer, dev->oldi_buffer,
-		     INPUT_CMD_SIZE) == 0) {
-			goto resubmit;
-		}
-		memcpy(dev->oldi_buffer, dev->interrupt_in_buffer,
-		       INPUT_CMD_SIZE);
-
-#if SUPPRESS_EXTRA_OFFLINE_EVENTS
-		if (dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff)
-			goto resubmit;
-		if (dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) {
-			dev->offline = 2;
-			goto resubmit;
-		}
-/* Always pass one offline event up the stack */
-		if (dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff)
-			dev->offline = 0;
-		if (dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff)
-			dev->offline = 1;
-#endif
-		dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
-			 __func__, dev->ring_head, dev->ring_tail);
-		next_ring_head = (dev->ring_head + 1) % ring_buffer_size;
-
-		if (next_ring_head != dev->ring_tail) {
-			memcpy(&((*dev->ring_buffer)[dev->ring_head]),
-			       dev->interrupt_in_buffer, urb->actual_length);
-			dev->ring_head = next_ring_head;
-			retval = 0;
-			memset(dev->interrupt_in_buffer, 0, urb->actual_length);
-		} else {
-			dev_warn(&dev->intf->dev,
-				 "Ring buffer overflow, %d bytes dropped\n",
-				 urb->actual_length);
-			memset(dev->interrupt_in_buffer, 0, urb->actual_length);
-		}
-	}
-
-resubmit:
-	/* resubmit if we're still running */
-	if (dev->interrupt_in_running && dev->intf) {
-		retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
-		if (retval)
-			dev_err(&dev->intf->dev,
-				"usb_submit_urb failed (%d)\n", retval);
-	}
-
-exit:
-	dev->interrupt_in_done = 1;
-	wake_up_interruptible(&dev->read_wait);
-}
-
-/** usb_alphatrack_interrupt_out_callback */
-static void usb_alphatrack_interrupt_out_callback(struct urb *urb)
-{
-	struct usb_alphatrack *dev = urb->context;
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status && !(urb->status == -ENOENT ||
-			     urb->status == -ECONNRESET ||
-			     urb->status == -ESHUTDOWN))
-		dbg_info(&dev->intf->dev,
-			 "%s - nonzero write interrupt status received: %d\n",
-			 __func__, urb->status);
-	atomic_dec(&dev->writes_pending);
-	dev->interrupt_out_busy = 0;
-	wake_up_interruptible(&dev->write_wait);
-}
-
-/** usb_alphatrack_open */
-static int usb_alphatrack_open(struct inode *inode, struct file *file)
-{
-	struct usb_alphatrack *dev;
-	int subminor;
-	int retval = 0;
-	struct usb_interface *interface;
-
-	nonseekable_open(inode, file);
-	subminor = iminor(inode);
-
-	mutex_lock(&disconnect_mutex);
-
-	interface = usb_find_interface(&usb_alphatrack_driver, subminor);
-
-	if (!interface) {
-		pr_err("%s - error, can't find device for minor %d\n",
-		       __func__, subminor);
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
-	}
-
-	dev = usb_get_intfdata(interface);
-
-	if (!dev) {
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
-	}
-
-	/* lock this device */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto unlock_disconnect_exit;
-	}
-
-	/* allow opening only once */
-	if (dev->open_count) {
-		retval = -EBUSY;
-		goto unlock_exit;
-	}
-	dev->open_count = 1;
-
-	/* initialize in direction */
-	dev->ring_head = 0;
-	dev->ring_tail = 0;
-	usb_fill_int_urb(dev->interrupt_in_urb,
-			 interface_to_usbdev(interface),
-			 usb_rcvintpipe(interface_to_usbdev(interface),
-					dev->interrupt_in_endpoint->
-					bEndpointAddress),
-			 dev->interrupt_in_buffer,
-			 dev->interrupt_in_endpoint_size,
-			 usb_alphatrack_interrupt_in_callback, dev,
-			 dev->interrupt_in_interval);
-
-	dev->interrupt_in_running = 1;
-	dev->interrupt_in_done = 0;
-	dev->enable = 1;
-	dev->offline = 0;
-
-	retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&interface->dev,
-			"Couldn't submit interrupt_in_urb %d\n", retval);
-		dev->interrupt_in_running = 0;
-		dev->open_count = 0;
-		goto unlock_exit;
-	}
-
-	/* save device in the file's private structure */
-	file->private_data = dev;
-
-unlock_exit:
-	mutex_unlock(&dev->mtx);
-
-unlock_disconnect_exit:
-	mutex_unlock(&disconnect_mutex);
-
-	return retval;
-}
-
-/** usb_alphatrack_release */
-static int usb_alphatrack_release(struct inode *inode, struct file *file)
-{
-	struct usb_alphatrack *dev;
-	int retval = 0;
-
-	dev = file->private_data;
-
-	if (dev == NULL) {
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	if (dev->open_count != 1) {
-		retval = -ENODEV;
-		goto unlock_exit;
-	}
-
-	if (dev->intf == NULL) {
-		/* the device was unplugged before the file was released */
-		mutex_unlock(&dev->mtx);
-		/* unlock here as usb_alphatrack_delete frees dev */
-		usb_alphatrack_delete(dev);
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	/* wait until write transfer is finished */
-	if (dev->interrupt_out_busy)
-		wait_event_interruptible_timeout(dev->write_wait,
-						 !dev->interrupt_out_busy,
-						 2 * HZ);
-	usb_alphatrack_abort_transfers(dev);
-	dev->open_count = 0;
-
-unlock_exit:
-	mutex_unlock(&dev->mtx);
-
-exit:
-	return retval;
-}
-
-/** usb_alphatrack_poll */
-static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait)
-{
-	struct usb_alphatrack *dev;
-	unsigned int mask = 0;
-
-	dev = file->private_data;
-
-	poll_wait(file, &dev->read_wait, wait);
-	poll_wait(file, &dev->write_wait, wait);
-
-	if (dev->ring_head != dev->ring_tail)
-		mask |= POLLIN | POLLRDNORM;
-	if (!dev->interrupt_out_busy)
-		mask |= POLLOUT | POLLWRNORM;
-
-	return mask;
-}
-
-/** usb_alphatrack_read */
-static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
-				   size_t count, loff_t *ppos)
-{
-	struct usb_alphatrack *dev;
-	int retval = 0;
-
-	int c = 0;
-
-	dev = file->private_data;
-
-	/* verify that we actually have some data to read */
-	if (count == 0)
-		goto exit;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	/* verify that the device wasn't unplugged */
-	if (dev->intf == NULL) {
-		retval = -ENODEV;
-		pr_err("%s: No device or device unplugged %d\n",
-		       __func__, retval);
-		goto unlock_exit;
-	}
-
-	while (dev->ring_head == dev->ring_tail) {
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto unlock_exit;
-		}
-		dev->interrupt_in_done = 0;
-		retval =
-		    wait_event_interruptible(dev->read_wait,
-					     dev->interrupt_in_done);
-		if (retval < 0)
-			goto unlock_exit;
-	}
-
-	alphatrack_ocmd_info(&dev->intf->dev,
-			     &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s",
-			     ": copying to userspace");
-
-	c = 0;
-	while ((c < count) && (dev->ring_tail != dev->ring_head)) {
-		if (copy_to_user
-		    (&buffer[c], &(*dev->ring_buffer)[dev->ring_tail],
-		     INPUT_CMD_SIZE)) {
-			retval = -EFAULT;
-			goto unlock_exit;
-		}
-		dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
-		c += INPUT_CMD_SIZE;
-		dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
-			 __func__, dev->ring_head, dev->ring_tail);
-	}
-	retval = c;
-
-unlock_exit:
-	/* unlock the device */
-	mutex_unlock(&dev->mtx);
-
-exit:
-	return retval;
-}
-
-/** usb_alphatrack_write */
-static ssize_t usb_alphatrack_write(struct file *file,
-				    const char __user *buffer, size_t count,
-				    loff_t *ppos)
-{
-	struct usb_alphatrack *dev;
-	size_t bytes_to_write;
-	int retval = 0;
-
-	dev = file->private_data;
-
-	/* verify that we actually have some data to write */
-	if (count == 0)
-		goto exit;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	/* verify that the device wasn't unplugged */
-	if (dev->intf == NULL) {
-		retval = -ENODEV;
-		pr_err("%s: No device or device unplugged %d\n",
-		       __func__, retval);
-		goto unlock_exit;
-	}
-
-	/* wait until previous transfer is finished */
-	if (dev->interrupt_out_busy) {
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto unlock_exit;
-		}
-		retval =
-		    wait_event_interruptible(dev->write_wait,
-					     !dev->interrupt_out_busy);
-		if (retval < 0)
-			goto unlock_exit;
-	}
-
-	/* write the data into interrupt_out_buffer from userspace */
-	/* FIXME - if you write more than 12 bytes this breaks */
-	bytes_to_write =
-	    min(count, write_buffer_size * dev->interrupt_out_endpoint_size);
-	if (bytes_to_write < count)
-		dev_warn(&dev->intf->dev,
-			 "Write buffer overflow, %zd bytes dropped\n",
-			 count - bytes_to_write);
-
-	dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n",
-		 __func__, count, bytes_to_write);
-
-	if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
-		retval = -EFAULT;
-		goto unlock_exit;
-	}
-
-	if (dev->interrupt_out_endpoint == NULL) {
-		dev_err(&dev->intf->dev, "Endpoint should not be null!\n");
-		goto unlock_exit;
-	}
-
-	/* send off the urb */
-	usb_fill_int_urb(dev->interrupt_out_urb,
-			 interface_to_usbdev(dev->intf),
-			 usb_sndintpipe(interface_to_usbdev(dev->intf),
-					dev->interrupt_out_endpoint->
-					bEndpointAddress),
-			 dev->interrupt_out_buffer, bytes_to_write,
-			 usb_alphatrack_interrupt_out_callback, dev,
-			 dev->interrupt_out_interval);
-	dev->interrupt_out_busy = 1;
-	atomic_inc(&dev->writes_pending);
-	wmb();
-
-	retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
-	if (retval) {
-		dev->interrupt_out_busy = 0;
-		dev_err(&dev->intf->dev,
-			"Couldn't submit interrupt_out_urb %d\n", retval);
-		atomic_dec(&dev->writes_pending);
-		goto unlock_exit;
-	}
-	retval = bytes_to_write;
-
-unlock_exit:
-	/* unlock the device */
-	mutex_unlock(&dev->mtx);
-
-exit:
-	return retval;
-}
-
-/* file operations needed when we register this driver */
-static const struct file_operations usb_alphatrack_fops = {
-	.owner = THIS_MODULE,
-	.read = usb_alphatrack_read,
-	.write = usb_alphatrack_write,
-	.open = usb_alphatrack_open,
-	.release = usb_alphatrack_release,
-	.poll = usb_alphatrack_poll,
-	.llseek = no_llseek,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with the driver core
- */
-
-static struct usb_class_driver usb_alphatrack_class = {
-	.name = "alphatrack%d",
-	.fops = &usb_alphatrack_fops,
-	.minor_base = USB_ALPHATRACK_MINOR_BASE,
-};
-
-/**
- *	usb_alphatrack_probe
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
-static int usb_alphatrack_probe(struct usb_interface *intf,
-				const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_alphatrack *dev = NULL;
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *endpoint;
-	int i;
-	int true_size;
-	int retval = -ENOMEM;
-
-	/* allocate memory for our device state and initialize it */
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL)
-		goto exit;
-
-	mutex_init(&dev->mtx);
-	dev->intf = intf;
-	init_waitqueue_head(&dev->read_wait);
-	init_waitqueue_head(&dev->write_wait);
-
-	iface_desc = intf->cur_altsetting;
-
-	/* set up the endpoint information */
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		if (usb_endpoint_is_int_in(endpoint))
-			dev->interrupt_in_endpoint = endpoint;
-
-		if (usb_endpoint_is_int_out(endpoint))
-			dev->interrupt_out_endpoint = endpoint;
-	}
-	if (dev->interrupt_in_endpoint == NULL) {
-		dev_err(&intf->dev, "Interrupt in endpoint not found\n");
-		goto error;
-	}
-	if (dev->interrupt_out_endpoint == NULL)
-		dev_warn(&intf->dev,
-			 "Interrupt out endpoint not found (using control endpoint instead)\n");
-
-	dev->interrupt_in_endpoint_size =
-	    le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
-
-	if (dev->interrupt_in_endpoint_size != 64)
-		dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n");
-
-	if (ring_buffer_size == 0)
-		ring_buffer_size = RING_BUFFER_SIZE;
-
-	true_size = min(ring_buffer_size, RING_BUFFER_SIZE);
-
-	/*
-	 * FIXME - there are more usb_alloc routines for dma correctness.
-	 * Needed?
-	 */
-	dev->ring_buffer = kmalloc_array(true_size,
-					 sizeof(struct alphatrack_icmd),
-					 GFP_KERNEL);
-	if (!dev->ring_buffer)
-		goto error;
-
-	dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size,
-					   GFP_KERNEL);
-	if (!dev->interrupt_in_buffer)
-		goto error;
-
-	dev->oldi_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
-	if (!dev->oldi_buffer)
-		goto error;
-
-	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->interrupt_in_urb) {
-		dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
-		goto error;
-	}
-
-	dev->interrupt_out_endpoint_size =
-	    dev->interrupt_out_endpoint ? le16_to_cpu(dev->
-						      interrupt_out_endpoint->
-						      wMaxPacketSize) : udev->
-	    descriptor.bMaxPacketSize0;
-
-	if (dev->interrupt_out_endpoint_size != 64)
-		dev_warn(&intf->dev,
-			 "Interrupt out endpoint size is not 64!)\n");
-
-	if (write_buffer_size == 0)
-		write_buffer_size = WRITE_BUFFER_SIZE;
-	true_size = min(write_buffer_size, WRITE_BUFFER_SIZE);
-
-	dev->interrupt_out_buffer =
-		kmalloc_array(true_size,
-			      dev->interrupt_out_endpoint_size,
-			      GFP_KERNEL);
-	if (!dev->interrupt_out_buffer)
-		goto error;
-
-	dev->write_buffer = kmalloc_array(true_size,
-					  sizeof(struct alphatrack_ocmd),
-					  GFP_KERNEL);
-	if (!dev->write_buffer)
-		goto error;
-
-	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->interrupt_out_urb) {
-		dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
-		goto error;
-	}
-	dev->interrupt_in_interval =
-	    min_interrupt_in_interval >
-	    dev->interrupt_in_endpoint->
-	    bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->
-	    bInterval;
-	if (dev->interrupt_out_endpoint)
-		dev->interrupt_out_interval =
-		    min_interrupt_out_interval >
-		    dev->interrupt_out_endpoint->
-		    bInterval ? min_interrupt_out_interval : dev->
-		    interrupt_out_endpoint->bInterval;
-
-	/* we can register the device now, as it is ready */
-	usb_set_intfdata(intf, dev);
-
-	atomic_set(&dev->writes_pending, 0);
-	retval = usb_register_dev(intf, &usb_alphatrack_class);
-	if (retval) {
-		/* something prevented us from registering this driver */
-		dev_err(&intf->dev,
-			"Not able to get a minor for this device.\n");
-		usb_set_intfdata(intf, NULL);
-		goto error;
-	}
-
-	/* let the user know what node this device is now attached to */
-	dev_info(&intf->dev,
-		 "Alphatrack Device #%d now attached to major %d minor %d\n",
-		 (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR,
-		 intf->minor);
-
-exit:
-	return retval;
-
-error:
-	usb_alphatrack_delete(dev);
-
-	return retval;
-}
-
-/**
- *	usb_alphatrack_disconnect
- *
- *	Called by the usb core when the device is removed from the system.
- */
-static void usb_alphatrack_disconnect(struct usb_interface *intf)
-{
-	struct usb_alphatrack *dev;
-	int minor;
-
-	mutex_lock(&disconnect_mutex);
-
-	dev = usb_get_intfdata(intf);
-	usb_set_intfdata(intf, NULL);
-
-	mutex_lock(&dev->mtx);
-
-	minor = intf->minor;
-
-	/* give back our minor */
-	usb_deregister_dev(intf, &usb_alphatrack_class);
-
-	/* if the device is not opened, then we clean up right now */
-	if (!dev->open_count) {
-		mutex_unlock(&dev->mtx);
-		usb_alphatrack_delete(dev);
-	} else {
-		atomic_set(&dev->writes_pending, 0);
-		dev->intf = NULL;
-		mutex_unlock(&dev->mtx);
-	}
-
-	mutex_unlock(&disconnect_mutex);
-
-	dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n",
-		 (minor - USB_ALPHATRACK_MINOR_BASE));
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver usb_alphatrack_driver = {
-	.name = "alphatrack",
-	.probe = usb_alphatrack_probe,
-	.disconnect = usb_alphatrack_disconnect,
-	.id_table = usb_alphatrack_table,
-};
-
-module_usb_driver(usb_alphatrack_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/alphatrack.h linux-libre-3.17-rc7-gnu/drivers/staging/frontier/alphatrack.h
--- linux-libre-3.16-gnu/drivers/staging/frontier/alphatrack.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/alphatrack.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-struct alphatrack_icmd {
-	unsigned char cmd[12];
-};
-
-struct alphatrack_ocmd {
-	unsigned char cmd[8];
-};
-
-/*
- * These are unused by the present driver but provide documentation for the
- * userspace API.
- */
-enum LightID {
-	LIGHT_EQ = 0,
-	LIGHT_OUT,
-	LIGHT_F2,
-	LIGHT_SEND,
-	LIGHT_IN,
-	LIGHT_F1,
-	LIGHT_PAN,
-	LIGHT_UNDEF1,
-	LIGHT_UNDEF2,
-	LIGHT_SHIFT,
-	LIGHT_TRACKMUTE,
-	LIGHT_TRACKSOLO,
-	LIGHT_TRACKREC,
-	LIGHT_READ,
-	LIGHT_WRITE,
-	LIGHT_ANYSOLO,
-	LIGHT_AUTO,
-	LIGHT_F4,
-	LIGHT_RECORD,
-	LIGHT_WINDOW,
-	LIGHT_PLUGIN,
-	LIGHT_F3,
-	LIGHT_LOOP
-};
-
-#define BUTTONMASK_BATTERY     0x00004000
-#define BUTTONMASK_BACKLIGHT   0x00008000
-#define BUTTONMASK_FASTFORWARD 0x04000000
-#define BUTTONMASK_TRACKMUTE   0x00040000
-#define BUTTONMASK_TRACKSOLO   0x00800000
-#define BUTTONMASK_TRACKLEFT   0x80000000
-#define BUTTONMASK_RECORD      0x02000000
-#define BUTTONMASK_SHIFT       0x20000000
-#define BUTTONMASK_PUNCH       0x00800000
-#define BUTTONMASK_TRACKRIGHT  0x00020000
-#define BUTTONMASK_REWIND      0x01000000
-#define BUTTONMASK_STOP        0x10000000
-#define BUTTONMASK_LOOP        0x00010000
-#define BUTTONMASK_TRACKREC    0x00001000
-#define BUTTONMASK_PLAY        0x08000000
-#define BUTTONMASK_TOUCH1      0x00000008
-#define BUTTONMASK_TOUCH2      0x00000010
-#define BUTTONMASK_TOUCH3      0x00000020
-
-#define BUTTONMASK_PRESS1      0x00000009
-#define BUTTONMASK_PRESS2      0x00008010
-#define BUTTONMASK_PRESS3      0x00002020
-
-/*
- * last 3 bytes are the slider position
- * 40 is the actual slider moving, the most sig bits, and 3 lsb
- */
-
-#define BUTTONMASK_FLIP         0x40000000
-#define BUTTONMASK_F1           0x00100000
-#define BUTTONMASK_F2           0x00400000
-#define BUTTONMASK_F3           0x00200000
-#define BUTTONMASK_F4           0x00080000
-#define BUTTONMASK_PAN          0x00000200
-#define BUTTONMASK_SEND         0x00000800
-#define BUTTONMASK_EQ           0x00004000
-#define BUTTONMASK_PLUGIN       0x00000400
-#define BUTTONMASK_AUTO         0x00000100
-
-/* #define BUTTONMASK_FOOTSWITCH FIXME */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/frontier/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/frontier/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-config TRANZPORT
-	tristate "Frontier Tranzport and Alphatrack support"
-	depends on USB
-	---help---
-	  Enable support for the Frontier Tranzport and Alphatrack devices.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/frontier/Makefile
--- linux-libre-3.16-gnu/drivers/staging/frontier/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-obj-$(CONFIG_TRANZPORT)		+= tranzport.o
-obj-$(CONFIG_TRANZPORT)		+= alphatrack.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/README linux-libre-3.17-rc7-gnu/drivers/staging/frontier/README
--- linux-libre-3.16-gnu/drivers/staging/frontier/README	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/README	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-This directory contains the Linux USB Tranzport and Alphatrack Kernel drivers.
-
-See http://www.frontierdesign.com for details on these devices.
-
-Userspace test code is available from
-
-git://toutatis.isc.org/home/d/src/git/frontier.git
-
-At present the tranzport does reads/writes of 8 byte cmds to
-/dev/tranzport0 to control the lights, screen, and wheel.
-
-At present the alphatrack accepts reads/writes of 12 byte cmds to
-/dev/tranzport0 to control the lights, screen, fader and touchpad.
-
-The tranzport driver provides a rudimentary sysfs interface for the status of
-the device and a writable parameter for turning wheel compression on and off.
-
-The API is nothing more than the USB commands issued to the device. Why?
-
-The control wheel/fader can generate events far too quickly for
-a typical userspace application to keep up with them via libusb. Input
-needs to be 100% accurate and fast in order for the alphatrack or tranzport
-to be useful.
-
-UIO would be useful except that usb disconnect events need
-to be handled correctly.
-
-A sysfs interface is perfect for simple userspace apps to do fun things with
-the lights and screen. But it's fairly lousy for handling input events and
-very lousy for watching the state of the shuttle wheel.
-
-A linux input events interface is great for the input events and shuttle wheel.
-* It's theoretically OK on LEDs.
-* A fader can be mapped to an absolute mouse device.
-* But there is no LCD support at all, or fader feedback support in that API
-
-So, thus, these stubby drivers exist.
-
-In the end this could be driven by a midi layer, which handles all those
-cases via a well defined API, but - among other things - is slow, doesn't do
-flow control, and is a LOT of extra work, none of which is required at
-the kernel level (probably). Frankly, I'd like to keep the
-core driver simple because the only realtime work really required is
-the bottom half interrupt handler and the output overlapping.
-
-Exposing some sort of clean api to userspace would be perfect. What that
-API looks like? Gah. beats me.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/TODO linux-libre-3.17-rc7-gnu/drivers/staging/frontier/TODO
--- linux-libre-3.16-gnu/drivers/staging/frontier/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-TODO:
-	- checkpatch.pl clean
-	- sparse clean
-	- fix userspace interface to be sane
-	- possibly just port to userspace with libusb
-	- review by the USB developer community
-
-Please send any patches for this driver to Greg Kroah-Hartman <greg@kroah.com>
-and David Taht <d@teklibre.com>.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/frontier/tranzport.c linux-libre-3.17-rc7-gnu/drivers/staging/frontier/tranzport.c
--- linux-libre-3.16-gnu/drivers/staging/frontier/tranzport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/frontier/tranzport.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,973 +0,0 @@
-/*
- * Frontier Designs Tranzport driver
- *
- * Copyright (C) 2007 Michael Taht (m@taht.net)
- *
- * Based on the usbled driver and ldusb drivers by
- *
- * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
- *
- * The ldusb driver was, in turn, derived from Lego USB Tower driver
- * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
- *		 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- *
- */
-
-/*
- * This driver uses a ring buffer for time critical reading of
- * interrupt in reports and provides read and write methods for
- * raw interrupt reports.
- */
-
-/* Note: this currently uses a dumb ringbuffer for reads and writes.
- * A more optimal driver would cache and kill off outstanding urbs that are
- * now invalid, and ignore ones that already were in the queue but valid
- * as we only have 17 commands for the tranzport. In particular this is
- * key for getting lights to flash in time as otherwise many commands
- * can be buffered up before the light change makes it to the interface.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-
-#include <linux/uaccess.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/poll.h>
-
-/* Define these values to match your devices */
-#define VENDOR_ID   0x165b
-#define PRODUCT_ID  0x8101
-
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define USB_TRANZPORT_MINOR_BASE	0
-#else  /* FIXME 177- is the another driver's minor - apply for a minor soon */
-#define USB_TRANZPORT_MINOR_BASE	177
-#endif
-
-/* table of devices that work with this driver */
-static const struct usb_device_id usb_tranzport_table[] = {
-	{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, usb_tranzport_table);
-MODULE_VERSION("0.35");
-MODULE_AUTHOR("Mike Taht <m@taht.net>");
-MODULE_DESCRIPTION("Tranzport USB Driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Frontier Designs Tranzport Control Surface");
-
-#define SUPPRESS_EXTRA_OFFLINE_EVENTS 1
-#define COMPRESS_WHEEL_EVENTS 1
-#define BUFFERED_READS 1
-#define RING_BUFFER_SIZE 1000
-#define WRITE_BUFFER_SIZE 34
-#define TRANZPORT_USB_TIMEOUT 10
-#define TRANZPORT_DEBUG 0
-
-static int debug = TRANZPORT_DEBUG;
-
-/* Use our own dbg macro */
-#define dbg_info(dev, format, arg...) do			\
-	{ if (debug) dev_info(dev , format , ## arg); } while (0)
-
-/* Module parameters */
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-/*
- * All interrupt in transfers are collected in a ring buffer to
- * avoid racing conditions and get better performance of the driver.
- */
-
-static int ring_buffer_size = RING_BUFFER_SIZE;
-
-module_param(ring_buffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
-
-/*
- * The write_buffer can one day contain more than one interrupt out transfer.
- */
-static int write_buffer_size = WRITE_BUFFER_SIZE;
-module_param(write_buffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
-
-/*
- * Increase the interval for debugging purposes.
- * or set to 1 to use the standard interval from the endpoint descriptors.
- */
-
-static int min_interrupt_in_interval = TRANZPORT_USB_TIMEOUT;
-module_param(min_interrupt_in_interval, int, 0);
-MODULE_PARM_DESC(min_interrupt_in_interval,
-		"Minimum interrupt in interval in ms");
-
-static int min_interrupt_out_interval = TRANZPORT_USB_TIMEOUT;
-module_param(min_interrupt_out_interval, int, 0);
-MODULE_PARM_DESC(min_interrupt_out_interval,
-		"Minimum interrupt out interval in ms");
-
-struct tranzport_cmd {
-	unsigned char cmd[8];
-};
-
-/* Structure to hold all of our device specific stuff */
-
-struct usb_tranzport {
-	struct mutex mtx;	/* locks this structure */
-	struct usb_interface *intf;	/* save off the usb interface pointer */
-	int open_count;		/* number of times this port opened */
-	struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE];
-	unsigned int ring_head;
-	unsigned int ring_tail;
-	wait_queue_head_t read_wait;
-	wait_queue_head_t write_wait;
-	unsigned char *interrupt_in_buffer;
-	struct usb_endpoint_descriptor *interrupt_in_endpoint;
-	struct urb *interrupt_in_urb;
-	int interrupt_in_interval;
-	size_t interrupt_in_endpoint_size;
-	int interrupt_in_running;
-	int interrupt_in_done;
-	char *interrupt_out_buffer;
-	struct usb_endpoint_descriptor *interrupt_out_endpoint;
-	struct urb *interrupt_out_urb;
-	int interrupt_out_interval;
-	size_t interrupt_out_endpoint_size;
-	int interrupt_out_busy;
-
-	/* Sysfs support */
-
-	unsigned char enable;	/* 0 if disabled 1 if enabled */
-	unsigned char offline;	/* if the device is out of range or asleep */
-	unsigned char compress_wheel;	/* flag to compress wheel events */
-};
-
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
-static struct usb_driver usb_tranzport_driver;
-
-/**
- *	usb_tranzport_abort_transfers
- *      aborts transfers and frees associated data structures
- */
-static void usb_tranzport_abort_transfers(struct usb_tranzport *dev)
-{
-	/* shutdown transfer */
-	if (dev->interrupt_in_running) {
-		dev->interrupt_in_running = 0;
-		if (dev->intf)
-			usb_kill_urb(dev->interrupt_in_urb);
-	}
-	if (dev->interrupt_out_busy)
-		if (dev->intf)
-			usb_kill_urb(dev->interrupt_out_urb);
-}
-
-#define show_int(value)	\
-	static ssize_t value##_show(struct device *dev,	\
-			      struct device_attribute *attr, char *buf)	\
-	{	\
-		struct usb_interface *intf = to_usb_interface(dev);	\
-		struct usb_tranzport *t = usb_get_intfdata(intf);	\
-		return sprintf(buf, "%d\n", t->value);	\
-	}	\
-	static DEVICE_ATTR_RO(value)
-
-#define show_set_int(value)	\
-	static ssize_t value##_show(struct device *dev,	\
-			      struct device_attribute *attr, char *buf)	\
-	{	\
-		struct usb_interface *intf = to_usb_interface(dev);	\
-		struct usb_tranzport *t = usb_get_intfdata(intf);	\
-		return sprintf(buf, "%d\n", t->value);	\
-	}	\
-	static ssize_t value##_store(struct device *dev,	\
-			     struct device_attribute *attr,		\
-			     const char *buf, size_t count)		\
-	{	\
-		struct usb_interface *intf = to_usb_interface(dev);	\
-		struct usb_tranzport *t = usb_get_intfdata(intf);	\
-		unsigned long temp;	\
-		if (kstrtoul(buf, 10, &temp))	\
-			return -EINVAL;	\
-		t->value = temp;	\
-		return count;	\
-	}	\
-	static DEVICE_ATTR_RW(value)
-
-show_int(enable);
-show_int(offline);
-show_set_int(compress_wheel);
-
-/**
- *	usb_tranzport_delete
- */
-static void usb_tranzport_delete(struct usb_tranzport *dev)
-{
-	usb_tranzport_abort_transfers(dev);
-	if (dev->intf != NULL) {
-		device_remove_file(&dev->intf->dev, &dev_attr_enable);
-		device_remove_file(&dev->intf->dev, &dev_attr_offline);
-		device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel);
-	}
-
-	/* free data structures */
-	usb_free_urb(dev->interrupt_in_urb);
-	usb_free_urb(dev->interrupt_out_urb);
-	kfree(dev->ring_buffer);
-	kfree(dev->interrupt_in_buffer);
-	kfree(dev->interrupt_out_buffer);
-	kfree(dev);
-}
-
-/**
- *	usb_tranzport_interrupt_in_callback
- */
-
-static void usb_tranzport_interrupt_in_callback(struct urb *urb)
-{
-	struct usb_tranzport *dev = urb->context;
-	unsigned int next_ring_head;
-	int retval = -1;
-
-	if (urb->status) {
-		if (urb->status == -ENOENT ||
-			urb->status == -ECONNRESET ||
-			urb->status == -ESHUTDOWN) {
-			goto exit;
-		} else {
-			dbg_info(&dev->intf->dev,
-				 "%s: nonzero status received: %d\n",
-				 __func__, urb->status);
-			goto resubmit;	/* maybe we can recover */
-		}
-	}
-
-	if (urb->actual_length != 8) {
-		dev_warn(&dev->intf->dev,
-			"Urb length was %d bytes!! Do something intelligent\n",
-			 urb->actual_length);
-	} else {
-		dbg_info(&dev->intf->dev,
-			 "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n",
-			 __func__, dev->interrupt_in_buffer[0],
-			 dev->interrupt_in_buffer[1],
-			 dev->interrupt_in_buffer[2],
-			 dev->interrupt_in_buffer[3],
-			 dev->interrupt_in_buffer[4],
-			 dev->interrupt_in_buffer[5],
-			 dev->interrupt_in_buffer[6],
-			 dev->interrupt_in_buffer[7]);
-#if SUPPRESS_EXTRA_OFFLINE_EVENTS
-		if (dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff)
-			goto resubmit;
-		if (dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) {
-			dev->offline = 2;
-			goto resubmit;
-		}
-
-		/* Always pass one offline event up the stack */
-		if (dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff)
-			dev->offline = 0;
-		if (dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff)
-			dev->offline = 1;
-
-#endif	/* SUPPRESS_EXTRA_OFFLINE_EVENTS */
-		dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
-			 __func__, dev->ring_head, dev->ring_tail);
-
-		next_ring_head = (dev->ring_head + 1) % ring_buffer_size;
-
-		if (next_ring_head != dev->ring_tail) {
-			memcpy(&((*dev->ring_buffer)[dev->ring_head]),
-			       dev->interrupt_in_buffer, urb->actual_length);
-			dev->ring_head = next_ring_head;
-			retval = 0;
-			memset(dev->interrupt_in_buffer, 0, urb->actual_length);
-		} else {
-			dev_warn(&dev->intf->dev,
-				 "Ring buffer overflow, %d bytes dropped\n",
-				 urb->actual_length);
-			memset(dev->interrupt_in_buffer, 0, urb->actual_length);
-		}
-	}
-
-resubmit:
-/* resubmit if we're still running */
-	if (dev->interrupt_in_running && dev->intf) {
-		retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
-		if (retval)
-			dev_err(&dev->intf->dev,
-				"usb_submit_urb failed (%d)\n", retval);
-	}
-
-exit:
-	dev->interrupt_in_done = 1;
-	wake_up_interruptible(&dev->read_wait);
-}
-
-/**
- *	usb_tranzport_interrupt_out_callback
- */
-static void usb_tranzport_interrupt_out_callback(struct urb *urb)
-{
-	struct usb_tranzport *dev = urb->context;
-	/* sync/async unlink faults aren't errors */
-	if (urb->status && !(urb->status == -ENOENT ||
-				urb->status == -ECONNRESET ||
-				urb->status == -ESHUTDOWN))
-		dbg_info(&dev->intf->dev,
-			"%s - nonzero write interrupt status received: %d\n",
-			__func__, urb->status);
-
-	dev->interrupt_out_busy = 0;
-	wake_up_interruptible(&dev->write_wait);
-}
-/**
- *	usb_tranzport_open
- */
-static int usb_tranzport_open(struct inode *inode, struct file *file)
-{
-	struct usb_tranzport *dev;
-	int subminor;
-	int retval = 0;
-	struct usb_interface *interface;
-
-	nonseekable_open(inode, file);
-	subminor = iminor(inode);
-
-	mutex_lock(&disconnect_mutex);
-
-	interface = usb_find_interface(&usb_tranzport_driver, subminor);
-
-	if (!interface) {
-		pr_err("%s - error, can't find device for minor %d\n",
-		       __func__, subminor);
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
-	}
-
-	dev = usb_get_intfdata(interface);
-
-	if (!dev) {
-		retval = -ENODEV;
-		goto unlock_disconnect_exit;
-	}
-
-	/* lock this device */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto unlock_disconnect_exit;
-	}
-
-	/* allow opening only once */
-	if (dev->open_count) {
-		retval = -EBUSY;
-		goto unlock_exit;
-	}
-	dev->open_count = 1;
-
-	/* initialize in direction */
-	dev->ring_head = 0;
-	dev->ring_tail = 0;
-	usb_fill_int_urb(dev->interrupt_in_urb,
-			interface_to_usbdev(interface),
-			usb_rcvintpipe(interface_to_usbdev(interface),
-				dev->interrupt_in_endpoint->
-				bEndpointAddress),
-			dev->interrupt_in_buffer,
-			dev->interrupt_in_endpoint_size,
-			usb_tranzport_interrupt_in_callback, dev,
-			dev->interrupt_in_interval);
-
-	dev->interrupt_in_running = 1;
-	dev->interrupt_in_done = 0;
-	dev->enable = 1;
-	dev->offline = 0;
-	dev->compress_wheel = 1;
-
-	retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&interface->dev,
-			"Couldn't submit interrupt_in_urb %d\n", retval);
-		dev->interrupt_in_running = 0;
-		dev->open_count = 0;
-		goto unlock_exit;
-	}
-
-	/* save device in the file's private structure */
-	file->private_data = dev;
-
-unlock_exit:
-	mutex_unlock(&dev->mtx);
-
-unlock_disconnect_exit:
-	mutex_unlock(&disconnect_mutex);
-
-	return retval;
-}
-
-/**
- *	usb_tranzport_release
- */
-static int usb_tranzport_release(struct inode *inode, struct file *file)
-{
-	struct usb_tranzport *dev;
-	int retval = 0;
-
-	dev = file->private_data;
-
-	if (dev == NULL) {
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	if (dev->open_count != 1) {
-		retval = -ENODEV;
-		goto unlock_exit;
-	}
-
-	if (dev->intf == NULL) {
-		/* the device was unplugged before the file was released */
-		mutex_unlock(&dev->mtx);
-		/* unlock here as usb_tranzport_delete frees dev */
-		usb_tranzport_delete(dev);
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	/* wait until write transfer is finished */
-	if (dev->interrupt_out_busy)
-		wait_event_interruptible_timeout(dev->write_wait,
-						!dev->interrupt_out_busy,
-						2 * HZ);
-	usb_tranzport_abort_transfers(dev);
-	dev->open_count = 0;
-
-unlock_exit:
-	mutex_unlock(&dev->mtx);
-
-exit:
-	return retval;
-}
-
-/**
- *	usb_tranzport_poll
- */
-static unsigned int usb_tranzport_poll(struct file *file, poll_table *wait)
-{
-	struct usb_tranzport *dev;
-	unsigned int mask = 0;
-
-	dev = file->private_data;
-	poll_wait(file, &dev->read_wait, wait);
-	poll_wait(file, &dev->write_wait, wait);
-	if (dev->ring_head != dev->ring_tail)
-		mask |= POLLIN | POLLRDNORM;
-	if (!dev->interrupt_out_busy)
-		mask |= POLLOUT | POLLWRNORM;
-	return mask;
-}
-/**
- *	usb_tranzport_read
- */
-
-static ssize_t usb_tranzport_read(struct file *file, char __user *buffer,
-				size_t count, loff_t *ppos)
-{
-	struct usb_tranzport *dev;
-	int retval = 0;
-#if BUFFERED_READS
-	int c = 0;
-#endif
-#if COMPRESS_WHEEL_EVENTS
-	signed char oldwheel;
-	signed char newwheel;
-	int cancompress = 1;
-	int next_tail;
-#endif
-
-	/* do I have such a thing as a null event? */
-
-	dev = file->private_data;
-
-	/* verify that we actually have some data to read */
-	if (count == 0)
-		goto exit;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	/* verify that the device wasn't unplugged */
-	if (dev->intf == NULL) {
-		retval = -ENODEV;
-		pr_err("%s: No device or device unplugged %d\n",
-		       __func__, retval);
-		goto unlock_exit;
-	}
-
-	while (dev->ring_head == dev->ring_tail) {
-
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto unlock_exit;
-		}
-		/* tiny race - FIXME: make atomic? */
-		/* atomic_cmp_exchange(&dev->interrupt_in_done,0,0); */
-		dev->interrupt_in_done = 0;
-		retval = wait_event_interruptible(dev->read_wait,
-						  dev->interrupt_in_done);
-		if (retval < 0)
-			goto unlock_exit;
-	}
-
-	dbg_info(&dev->intf->dev,
-		"%s: copying to userspace: %02x%02x%02x%02x%02x%02x%02x%02x\n",
-		 __func__,
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[0],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[1],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[2],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[3],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[4],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[5],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[6],
-		 (*dev->ring_buffer)[dev->ring_tail].cmd[7]);
-
-#if BUFFERED_READS
-	c = 0;
-	while ((c < count) && (dev->ring_tail != dev->ring_head)) {
-
-#if COMPRESS_WHEEL_EVENTS
-		next_tail = (dev->ring_tail+1) % ring_buffer_size;
-		if (dev->compress_wheel)
-			cancompress = 1;
-		while (dev->ring_head != next_tail && cancompress == 1) {
-			newwheel = (*dev->ring_buffer)[next_tail].cmd[6];
-			oldwheel = (*dev->ring_buffer)[dev->ring_tail].cmd[6];
-			/* if both are wheel events, and
-			 * no buttons have changes (FIXME, do I have to check?),
-			 * and we are the same sign, we can compress +- 7F
-			 */
-			dbg_info(&dev->intf->dev,
-				"%s: trying to compress: %02x%02x%02x%02x%02x%02x%02x%02x\n",
-				__func__,
-				(*dev->ring_buffer)[dev->ring_tail].cmd[0],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[1],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[2],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[3],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[4],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[5],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[6],
-				(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
-
-			if (((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 &&
-				(*dev->ring_buffer)[next_tail].cmd[6] != 0) &&
-				((newwheel > 0 && oldwheel > 0) ||
-					(newwheel < 0 && oldwheel < 0)) &&
-				((*dev->ring_buffer)[dev->ring_tail].cmd[2] ==
-				(*dev->ring_buffer)[next_tail].cmd[2]) &&
-				((*dev->ring_buffer)[dev->ring_tail].cmd[3] ==
-				(*dev->ring_buffer)[next_tail].cmd[3]) &&
-				((*dev->ring_buffer)[dev->ring_tail].cmd[4] ==
-				(*dev->ring_buffer)[next_tail].cmd[4]) &&
-				((*dev->ring_buffer)[dev->ring_tail].cmd[5] ==
-				(*dev->ring_buffer)[next_tail].cmd[5])) {
-				dbg_info(&dev->intf->dev,
-					"%s: should compress: "
-					"%02x%02x%02x%02x%02x%02x%02x%02x\n",
-					__func__,
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[0],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[1],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[2],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[3],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[4],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[5],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[6],
-					(*dev->ring_buffer)[dev->ring_tail].
-					cmd[7]);
-				newwheel += oldwheel;
-				if (oldwheel > 0 && !(newwheel > 0)) {
-					newwheel = 0x7f;
-					cancompress = 0;
-				}
-				if (oldwheel < 0 && !(newwheel < 0)) {
-					newwheel = 0x80;
-					cancompress = 0;
-				}
-
-				(*dev->ring_buffer)[next_tail].cmd[6] =
-					newwheel;
-				dev->ring_tail = next_tail;
-				next_tail =
-					(dev->ring_tail + 1) % ring_buffer_size;
-			} else {
-				cancompress = 0;
-			}
-		}
-#endif /* COMPRESS_WHEEL_EVENTS */
-		if (copy_to_user(
-				&buffer[c],
-				&(*dev->ring_buffer)[dev->ring_tail], 8)) {
-			retval = -EFAULT;
-			goto unlock_exit;
-		}
-		dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
-		c += 8;
-		dbg_info(&dev->intf->dev,
-			 "%s: head, tail are %x, %x\n",
-			 __func__, dev->ring_head, dev->ring_tail);
-	}
-	retval = c;
-
-#else
-/*  if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) { */
-	retval = -EFAULT;
-	goto unlock_exit;
-}
-
-dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
-dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
-	 __func__, dev->ring_head, dev->ring_tail);
-
-retval = 8;
-#endif /* BUFFERED_READS */
-
-unlock_exit:
-/* unlock the device */
-mutex_unlock(&dev->mtx);
-
-exit:
-return retval;
-}
-
-/**
- *	usb_tranzport_write
- */
-static ssize_t usb_tranzport_write(struct file *file,
-				const char __user *buffer, size_t count,
-				loff_t *ppos)
-{
-	struct usb_tranzport *dev;
-	size_t bytes_to_write;
-	int retval = 0;
-
-	dev = file->private_data;
-
-	/* verify that we actually have some data to write */
-	if (count == 0)
-		goto exit;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&dev->mtx)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-	/* verify that the device wasn't unplugged */
-	if (dev->intf == NULL) {
-		retval = -ENODEV;
-		pr_err("%s: No device or device unplugged %d\n",
-		       __func__, retval);
-		goto unlock_exit;
-	}
-
-	/* wait until previous transfer is finished */
-	if (dev->interrupt_out_busy) {
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto unlock_exit;
-		}
-		retval = wait_event_interruptible(dev->write_wait,
-						!dev->interrupt_out_busy);
-		if (retval < 0)
-			goto unlock_exit;
-	}
-
-	/* write the data into interrupt_out_buffer from userspace */
-	bytes_to_write = min(count,
-			write_buffer_size *
-			dev->interrupt_out_endpoint_size);
-	if (bytes_to_write < count)
-		dev_warn(&dev->intf->dev,
-			"Write buffer overflow, %zd bytes dropped\n",
-			count - bytes_to_write);
-
-	dbg_info(&dev->intf->dev,
-		"%s: count = %zd, bytes_to_write = %zd\n", __func__,
-		count, bytes_to_write);
-
-	if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
-		retval = -EFAULT;
-		goto unlock_exit;
-	}
-
-	if (dev->interrupt_out_endpoint == NULL) {
-		dev_err(&dev->intf->dev, "Endpoint should not be null!\n");
-		goto unlock_exit;
-	}
-
-	/* send off the urb */
-	usb_fill_int_urb(dev->interrupt_out_urb,
-			interface_to_usbdev(dev->intf),
-			usb_sndintpipe(interface_to_usbdev(dev->intf),
-				dev->interrupt_out_endpoint->
-				bEndpointAddress),
-			dev->interrupt_out_buffer, bytes_to_write,
-			usb_tranzport_interrupt_out_callback, dev,
-			dev->interrupt_out_interval);
-
-	dev->interrupt_out_busy = 1;
-	wmb();
-
-	retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
-	if (retval) {
-		dev->interrupt_out_busy = 0;
-		dev_err(&dev->intf->dev,
-			"Couldn't submit interrupt_out_urb %d\n", retval);
-		goto unlock_exit;
-	}
-	retval = bytes_to_write;
-
-unlock_exit:
-	/* unlock the device */
-	mutex_unlock(&dev->mtx);
-
-exit:
-	return retval;
-}
-
-/* file operations needed when we register this driver */
-static const struct file_operations usb_tranzport_fops = {
-	.owner = THIS_MODULE,
-	.read = usb_tranzport_read,
-	.write = usb_tranzport_write,
-	.open = usb_tranzport_open,
-	.release = usb_tranzport_release,
-	.poll = usb_tranzport_poll,
-	.llseek = no_llseek,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with the driver core
- */
-static struct usb_class_driver usb_tranzport_class = {
-	.name = "tranzport%d",
-	.fops = &usb_tranzport_fops,
-	.minor_base = USB_TRANZPORT_MINOR_BASE,
-};
-
-/**
- *	usb_tranzport_probe
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
-static int usb_tranzport_probe(struct usb_interface *intf,
-			       const struct usb_device_id *id) {
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_tranzport *dev = NULL;
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *endpoint;
-	int i;
-	int true_size;
-	int retval = -ENOMEM;
-
-	/* allocate memory for our device state and initialize it */
-
-	 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL)
-		goto exit;
-
-	mutex_init(&dev->mtx);
-	dev->intf = intf;
-	init_waitqueue_head(&dev->read_wait);
-	init_waitqueue_head(&dev->write_wait);
-
-	iface_desc = intf->cur_altsetting;
-
-	/* set up the endpoint information */
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		if (usb_endpoint_is_int_in(endpoint))
-			dev->interrupt_in_endpoint = endpoint;
-
-		if (usb_endpoint_is_int_out(endpoint))
-			dev->interrupt_out_endpoint = endpoint;
-	}
-	if (dev->interrupt_in_endpoint == NULL) {
-		dev_err(&intf->dev, "Interrupt in endpoint not found\n");
-		goto error;
-	}
-	if (dev->interrupt_out_endpoint == NULL)
-		dev_warn(&intf->dev,
-			"Interrupt out endpoint not found (using control endpoint instead)\n");
-
-	dev->interrupt_in_endpoint_size =
-	    le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
-
-	if (dev->interrupt_in_endpoint_size != 8)
-		dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n");
-
-	if (ring_buffer_size == 0)
-		ring_buffer_size = RING_BUFFER_SIZE;
-	true_size = min(ring_buffer_size, RING_BUFFER_SIZE);
-
-	/*
-	 * FIXME - there are more usb_alloc routines for dma correctness.
-	 * Needed?
-	 */
-
-	dev->ring_buffer =
-	    kmalloc((true_size * sizeof(struct tranzport_cmd)) + 8, GFP_KERNEL);
-	if (!dev->ring_buffer)
-		goto error;
-
-	dev->interrupt_in_buffer =
-	    kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
-	if (!dev->interrupt_in_buffer)
-		goto error;
-
-	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->interrupt_in_urb) {
-		dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
-		goto error;
-	}
-	dev->interrupt_out_endpoint_size =
-	    dev->interrupt_out_endpoint ?
-	    le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
-	    udev->descriptor.bMaxPacketSize0;
-
-	if (dev->interrupt_out_endpoint_size != 8)
-		dev_warn(&intf->dev,
-			 "Interrupt out endpoint size is not 8!)\n");
-
-	dev->interrupt_out_buffer =
-		kmalloc_array(write_buffer_size,
-			      dev->interrupt_out_endpoint_size, GFP_KERNEL);
-	if (!dev->interrupt_out_buffer)
-		goto error;
-
-	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->interrupt_out_urb) {
-		dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
-		goto error;
-	}
-	dev->interrupt_in_interval =
-	    min_interrupt_in_interval >
-	    dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval
-	    : dev->interrupt_in_endpoint->bInterval;
-
-	if (dev->interrupt_out_endpoint) {
-		dev->interrupt_out_interval =
-		    min_interrupt_out_interval >
-		    dev->interrupt_out_endpoint->bInterval ?
-		    min_interrupt_out_interval :
-		    dev->interrupt_out_endpoint->bInterval;
-	}
-
-	/* we can register the device now, as it is ready */
-	usb_set_intfdata(intf, dev);
-
-	retval = usb_register_dev(intf, &usb_tranzport_class);
-	if (retval) {
-		/* something prevented us from registering this driver */
-		dev_err(&intf->dev,
-			"Not able to get a minor for this device.\n");
-		usb_set_intfdata(intf, NULL);
-		goto error;
-	}
-
-	retval = device_create_file(&intf->dev, &dev_attr_compress_wheel);
-	if (retval)
-		goto error;
-	retval = device_create_file(&intf->dev, &dev_attr_enable);
-	if (retval)
-		goto error;
-	retval = device_create_file(&intf->dev, &dev_attr_offline);
-	if (retval)
-		goto error;
-
-	/* let the user know what node this device is now attached to */
-	dev_info(&intf->dev,
-		"Tranzport Device #%d now attached to major %d minor %d\n",
-		(intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR,
-		intf->minor);
-
-exit:
-	return retval;
-
-error:
-	usb_tranzport_delete(dev);
-	return retval;
-}
-
-/**
- *	usb_tranzport_disconnect
- *
- *	Called by the usb core when the device is removed from the system.
- */
-static void usb_tranzport_disconnect(struct usb_interface *intf)
-{
-	struct usb_tranzport *dev;
-	int minor;
-
-	mutex_lock(&disconnect_mutex);
-	dev = usb_get_intfdata(intf);
-	usb_set_intfdata(intf, NULL);
-	mutex_lock(&dev->mtx);
-	minor = intf->minor;
-	/* give back our minor */
-	usb_deregister_dev(intf, &usb_tranzport_class);
-
-	/* if the device is not opened, then we clean up right now */
-	if (!dev->open_count) {
-		mutex_unlock(&dev->mtx);
-		usb_tranzport_delete(dev);
-	} else {
-		dev->intf = NULL;
-		mutex_unlock(&dev->mtx);
-	}
-
-	mutex_unlock(&disconnect_mutex);
-
-	dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n",
-		(minor - USB_TRANZPORT_MINOR_BASE));
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver usb_tranzport_driver = {
-	.name = "tranzport",
-	.probe = usb_tranzport_probe,
-	.disconnect = usb_tranzport_disconnect,
-	.id_table = usb_tranzport_table,
-};
-
-module_usb_driver(usb_tranzport_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000.h linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000.h
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000.h	2014-09-28 17:29:07.000000000 -0400
@@ -363,6 +363,4 @@ struct ft1000_info {
 		u16 Rec[MAX_DSP_SESS_REC];
 		u32 MagRec[MAX_DSP_SESS_REC/2];
 	} DSPSess;
-	struct proc_dir_entry *ft1000_proc_dir;
-	char netdevname[IFNAMSIZ];
 };
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c	2014-09-28 17:29:07.000000000 -0400
@@ -15,8 +15,8 @@
    Suite 330, Boston, MA 02111-1307, USA.
   --------------------------------------------------------------------------
 
-   Description:  This module will handshake with the DSP bootloader to
-                 download the DSP runtime image.
+   Description: This module will handshake with the DSP bootloader to
+		download the DSP runtime image.
 
 ---------------------------------------------------------------------------*/
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,8 +47,6 @@ extern struct net_device *init_ft1000_ca
 extern void stop_ft1000_card(struct net_device *dev);
 extern int card_download(struct net_device *dev, const u8 *pFileStart,
 			 size_t FileLength);
-extern void ft1000InitProc(struct net_device *dev);
-extern void ft1000CleanupProc(struct net_device *dev);
 
 extern u16 ft1000_read_dpram(struct net_device *dev, int offset);
 extern void card_bootload(struct net_device *dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c	2014-08-07 04:52:13.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c	2014-09-28 21:33:43.000000000 -0400
@@ -19,8 +19,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/proc_fs.h>
-
 #include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
@@ -2103,7 +2101,6 @@ void stop_ft1000_card(struct net_device
 	release_region(dev->base_addr,256);
 	release_firmware(fw_entry);
 	flarion_ft1000_cnt--;
-	ft1000CleanupProc(dev);
 
 }
 
@@ -2248,7 +2245,6 @@ struct net_device *init_ft1000_card(stru
 
 	ft1000_enable_interrupts(dev);
 
-	ft1000InitProc(dev);
 	ft1000_card_present = 1;
 	dev->ethtool_ops = &ops;
 	printk(KERN_INFO "ft1000: %s: addr 0x%04lx irq %d, MAC addr %pM\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,211 +0,0 @@
-/*---------------------------------------------------------------------------
-   FT1000 driver for Flarion Flash OFDM NIC Device
-
-   Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
-   Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the Free
-   Software Foundation; either version 2 of the License, or (at your option) any
-   later version. This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-   more details. You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the
-   Free Software Foundation, Inc., 59 Temple Place -
-   Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------------*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/netdevice.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include "ft1000.h"
-
-#define FT1000_PROC "ft1000"
-#define MAX_FILE_LEN 255
-
-#define seq_putx(m, message, size, var) \
-	seq_printf(m, message);	\
-	for (i = 0; i < (size - 1); i++) { \
-		seq_printf(m, "%02x:", var[i]); \
-	} \
-	seq_printf(m, "%02x\n", var[i])
-
-#define seq_putd(m, message, size, var) \
-	seq_printf(m, message); \
-	for (i = 0; i < (size - 1); i++) { \
-		seq_printf(m, "%d.", var[i]); \
-	} \
-	seq_printf(m, "%d\n", var[i])
-
-static int ft1000ReadProc(struct seq_file *m, void *v)
-{
-	static const char *status[] = {
-		"Idle (Disconnect)", "Searching", "Active (Connected)",
-		"Waiting for L2", "Sleep", "No Coverage", "", ""
-	};
-	static const char *signal[] = { "", "*", "**", "***", "****" };
-
-	struct net_device *dev = m->private;
-	struct ft1000_info *info = netdev_priv(dev);
-	int i;
-	int strength;
-	int quality;
-	struct timeval tv;
-	time_t delta;
-
-	if (info->AsicID == ELECTRABUZZ_ID) {
-		if (info->ProgConStat != 0xFF) {
-			info->LedStat =
-				ft1000_read_dpram(dev, FT1000_DSP_LED);
-			info->ConStat =
-				ft1000_read_dpram(dev, FT1000_DSP_CON_STATE);
-		} else {
-			info->ConStat = 0xf;
-		}
-	} else {
-		if (info->ProgConStat != 0xFF) {
-			info->LedStat =
-				ntohs(ft1000_read_dpram_mag_16(
-					      dev, FT1000_MAG_DSP_LED,
-					      FT1000_MAG_DSP_LED_INDX));
-			info->ConStat =
-				ntohs(ft1000_read_dpram_mag_16(
-					      dev, FT1000_MAG_DSP_CON_STATE,
-					      FT1000_MAG_DSP_CON_STATE_INDX));
-		} else {
-			info->ConStat = 0xf;
-		}
-	}
-
-	i = (info->LedStat) & 0xf;
-	switch (i) {
-	case 0x1:
-		strength = 1;
-		break;
-	case 0x3:
-		strength = 2;
-		break;
-	case 0x7:
-		strength = 3;
-		break;
-	case 0xf:
-		strength = 4;
-		break;
-	default:
-		strength = 0;
-	}
-
-	i = (info->LedStat >> 8) & 0xf;
-	switch (i) {
-	case 0x1:
-		quality = 1;
-		break;
-	case 0x3:
-		quality = 2;
-		break;
-	case 0x7:
-		quality = 3;
-		break;
-	case 0xf:
-		quality = 4;
-		break;
-	default:
-		quality = 0;
-	}
-
-	do_gettimeofday(&tv);
-	delta = tv.tv_sec - info->ConTm;
-	seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n",
-			 ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
-	seq_printf(m, "Connection Time[s]: %ld\n", delta);
-	seq_printf(m, "Asic ID: %s\n",
-			 info->AsicID ==
-			 ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
-	seq_putx(m, "SKU: ", SKUSZ, info->Sku);
-	seq_putx(m, "EUI64: ", EUISZ, info->eui64);
-	seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer);
-	seq_putx(m, "Hardware Serial Number: ", HWSERNUMSZ, info->HwSerNum);
-	seq_putx(m, "Caliberation Version: ", CALVERSZ, info->RfCalVer);
-	seq_putd(m, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
-	seq_printf(m, "Media State: %s\n",
-			 (info->mediastate) ? "link" : "no link");
-	seq_printf(m, "Connection Status: %s\n", status[info->ConStat & 0x7]);
-	seq_printf(m, "RX packets: %ld\n", info->stats.rx_packets);
-	seq_printf(m, "TX packets: %ld\n", info->stats.tx_packets);
-	seq_printf(m, "RX bytes: %ld\n", info->stats.rx_bytes);
-	seq_printf(m, "TX bytes: %ld\n", info->stats.tx_bytes);
-	seq_printf(m, "Signal Strength: %s\n", signal[strength]);
-	seq_printf(m, "Signal Quality: %s\n", signal[quality]);
-	return 0;
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int ft1000_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ft1000ReadProc, PDE_DATA(inode));
-}
-
-static const struct file_operations ft1000_proc_fops = {
-	.open		= ft1000_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
-				void *ptr)
-{
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct ft1000_info *info;
-
-	info = netdev_priv(dev);
-
-	switch (event) {
-	case NETDEV_CHANGENAME:
-		remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-		proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
-				 &ft1000_proc_fops, dev);
-		snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
-		break;
-	}
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block ft1000_netdev_notifier = {
-	.notifier_call = ft1000NotifyProc
-};
-
-void ft1000InitProc(struct net_device *dev)
-{
-	struct ft1000_info *info;
-
-	info = netdev_priv(dev);
-
-	info->ft1000_proc_dir = proc_mkdir(FT1000_PROC, init_net.proc_net);
-
-	proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
-			 &ft1000_proc_fops, dev);
-
-	snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
-	register_netdevice_notifier(&ft1000_netdev_notifier);
-}
-
-void ft1000CleanupProc(struct net_device *dev)
-{
-	struct ft1000_info *info;
-
-	info = netdev_priv(dev);
-
-	remove_proc_entry(dev->name, info->ft1000_proc_dir);
-	remove_proc_entry(FT1000_PROC, init_net.proc_net);
-	unregister_netdevice_notifier(&ft1000_netdev_notifier);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/Makefile
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-pcmcia/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-pcmcia/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,2 @@
 obj-$(CONFIG_FT1000_PCMCIA) = ft1000_pcmcia.o
-ft1000_pcmcia-y := ft1000_hw.o ft1000_dnld.o ft1000_proc.o ft1000_cs.o
-
+ft1000_pcmcia-y := ft1000_hw.o ft1000_dnld.o ft1000_cs.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -482,14 +482,14 @@ static long ft1000_ioctl(struct file *fi
         /* Connect Message */
         DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_CONNECT\n");
         ConnectionMsg[79] = 0xfc;
-			   card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+			   result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
 
         break;
     case IOCTL_DISCONNECT:
         /* Disconnect Message */
         DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_DISCONNECT\n");
         ConnectionMsg[79] = 0xfd;
-			   card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+			   result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
         break;
     case IOCTL_GET_DSP_STAT_CMD:
         /* DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_GET_DSP_STAT called\n"); */
@@ -652,7 +652,7 @@ static long ft1000_ioctl(struct file *fi
                             }
                             pmsg++;
 				ppseudo_hdr = (struct pseudo_hdr *)pmsg;
-                           card_send_command(ft1000dev,(unsigned short*)dpram_data,total_len+2);
+                           result = card_send_command(ft1000dev,(unsigned short*)dpram_data,total_len+2);
 
 
                             ft1000dev->app_info[app_index].nTxMsg++;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c	2014-09-28 17:29:07.000000000 -0400
@@ -322,18 +322,23 @@ static void card_reset_dsp(struct ft1000
 *               ptempbuffer - command buffer
 *               size - command buffer size
 */
-void card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer,
+int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer,
 		       int size)
 {
+	int ret;
 	unsigned short temp;
 	unsigned char *commandbuf;
 
 	DEBUG("card_send_command: enter card_send_command... size=%d\n", size);
 
 	commandbuf = kmalloc(size + 2, GFP_KERNEL);
+	if (!commandbuf)
+		return -ENOMEM;
 	memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size);
 
-	ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
+	ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
+	if (ret)
+		return ret;
 
 	if (temp & 0x0100)
 		usleep_range(900, 1100);
@@ -345,19 +350,23 @@ void card_send_command(struct ft1000_usb
 	if (size % 4)
 		size += 4 - (size % 4);
 
-	ft1000_write_dpram32(ft1000dev, 0, commandbuf, size);
+	ret = ft1000_write_dpram32(ft1000dev, 0, commandbuf, size);
+	if (ret)
+		return ret;
 	usleep_range(900, 1100);
-	ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX,
+	ret = ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX,
 			      FT1000_REG_DOORBELL);
+	if (ret)
+		return ret;
 	usleep_range(900, 1100);
 
-	ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
+	ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
 
 #if 0
 	if ((temp & 0x0100) == 0)
 		DEBUG("card_send_command: Message sent\n");
 #endif
-
+	return ret;
 }
 
 /* load or reload the DSP */
@@ -1375,8 +1384,10 @@ static int ft1000_proc_drvmsg(struct ft1
 			*pmsg++ = convert.wrd;
 			*pmsg++ = htons(info->DrvErrNum);
 
-			card_send_command(dev, (unsigned char *)&tempbuffer[0],
+			status = card_send_command(dev, (unsigned char *)&tempbuffer[0],
 					(u16)(0x0012 + PSEUDOSZ));
+			if (status)
+				goto out;
 			info->DrvErrNum = 0;
 		}
 		dev->DrvMsgPend = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-/*
- * ft1000_proc.c - ft1000 proc interface
- *
- * Copyright	(C) 2009-2010 Quintec
- *		(C) 2010 Open-nandra
- *      <marek.belisko@open-nandra.com>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of this
- * archive for more details.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/netdevice.h>
-
-
-#include "ft1000_usb.h"
-
-#define FT1000_PROC_DIR "ft1000"
-
-
-#define seq_putx(m, message, size, var) \
-	do { \
-		seq_printf(m, message);	\
-		for (i = 0; i < (size - 1); i++) \
-			seq_printf(m, "%02x:", var[i]); \
-		seq_printf(m, "%02x\n", var[i]);	\
-	} while (0)
-
-#define seq_putd(m, message, size, var) \
-	do { \
-		seq_printf(m, message); \
-		for (i = 0; i < (size - 1); i++) \
-			seq_printf(m, "%d.", var[i]); \
-		seq_printf(m, "%d\n", var[i]);	      \
-	} while (0)
-
-#define FTNET_PROC init_net.proc_net
-
-
-int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx,
-			 u8 *buffer, u8 highlow);
-
-
-static int ft1000ReadProc(struct seq_file *m, void *v)
-{
-	static const char *status[] = {
-		"Idle (Disconnect)",
-		"Searching",
-		"Active (Connected)",
-		"Waiting for L2",
-		"Sleep",
-		"No Coverage",
-		"",
-		"",
-	};
-	static const char *signal[] = { "", "*", "**", "***", "****" };
-
-	struct net_device *dev = m->private;
-	struct ft1000_info *info = netdev_priv(dev);
-	int i;
-	unsigned short ledStat;
-	unsigned short conStat;
-	int strength;
-	int quality;
-	struct timeval tv;
-	time_t delta;
-
-	if (info->ProgConStat != 0xFF) {
-		ft1000_read_dpram16(info->priv, FT1000_MAG_DSP_LED,
-			   (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
-		info->LedStat = ntohs(ledStat);
-
-		ft1000_read_dpram16(info->priv, FT1000_MAG_DSP_CON_STATE,
-			(u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
-		info->ConStat = ntohs(conStat);
-		do_gettimeofday(&tv);
-		delta = (tv.tv_sec - info->ConTm);
-	} else {
-		info->ConStat = 0xf;
-		delta = 0;
-	}
-
-	i = (info->LedStat) & 0xf;
-	switch (i) {
-	case 0x1:
-		strength = 1;
-		break;
-	case 0x3:
-		strength = 2;
-		break;
-	case 0x7:
-		strength = 3;
-		break;
-	case 0xf:
-		strength = 4;
-		break;
-	default:
-		strength = 0;
-	}
-
-	i = (info->LedStat >> 8) & 0xf;
-	switch (i) {
-	case 0x1:
-		quality = 1;
-		break;
-	case 0x3:
-		quality = 2;
-		break;
-	case 0x7:
-		quality = 3;
-		break;
-	case 0xf:
-		quality = 4;
-		break;
-	default:
-		quality = 0;
-	}
-
-	seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n",
-		((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
-	seq_printf(m, "Connection Time[s]: %ld\n", delta);
-	seq_printf(m, "Asic ID: %s\n",
-	(info->AsicID) == ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
-	seq_putx(m, "SKU: ", SKUSZ, info->Sku);
-	seq_putx(m, "EUI64: ", EUISZ, info->eui64);
-	seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer);
-	seq_putx(m, "Hardware Serial Number: ", HWSERNUMSZ, info->HwSerNum);
-	seq_putx(m, "Caliberation Version: ", CALVERSZ, info->RfCalVer);
-	seq_putd(m, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
-	seq_printf(m, "Media State: %s\n", (info->mediastate) ? "link" : "no link");
-	seq_printf(m, "Connection Status: %s\n", status[info->ConStat & 0x7]);
-	seq_printf(m, "RX packets: %ld\n", info->stats.rx_packets);
-	seq_printf(m, "TX packets: %ld\n", info->stats.tx_packets);
-	seq_printf(m, "RX bytes: %ld\n", info->stats.rx_bytes);
-	seq_printf(m, "TX bytes: %ld\n", info->stats.tx_bytes);
-	seq_printf(m, "Signal Strength: %s\n", signal[strength]);
-	seq_printf(m, "Signal Quality: %s\n", signal[quality]);
-	return 0;
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int ft1000_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ft1000ReadProc, PDE_DATA(inode));
-}
-
-static const struct file_operations ft1000_proc_fops = {
-	.open		= ft1000_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int
-ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr)
-{
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct ft1000_info *info;
-	struct proc_dir_entry *ft1000_proc_file;
-
-	info = netdev_priv(dev);
-
-	switch (event) {
-	case NETDEV_CHANGENAME:
-		remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-		ft1000_proc_file =
-			proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
-					 &ft1000_proc_fops, dev);
-		snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block ft1000_netdev_notifier = {
-	.notifier_call = ft1000NotifyProc,
-};
-
-
-int ft1000_init_proc(struct net_device *dev)
-{
-	struct ft1000_info *info;
-	struct proc_dir_entry *ft1000_proc_file;
-	int ret = -EINVAL;
-
-	info = netdev_priv(dev);
-
-	info->ft1000_proc_dir = proc_mkdir(FT1000_PROC_DIR, FTNET_PROC);
-	if (info->ft1000_proc_dir == NULL) {
-		netdev_warn(dev, "Unable to create %s dir.\n",
-			FT1000_PROC_DIR);
-		goto fail;
-	}
-
-	ft1000_proc_file =
-		proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
-				 &ft1000_proc_fops, dev);
-
-	if (!ft1000_proc_file) {
-		netdev_warn(dev, "Unable to create /proc entry.\n");
-		goto fail_entry;
-	}
-
-	snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
-
-	ret = register_netdevice_notifier(&ft1000_netdev_notifier);
-	if (ret)
-		goto fail_notif;
-
-	return 0;
-
-fail_notif:
-	remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-fail_entry:
-	remove_proc_entry(FT1000_PROC_DIR, FTNET_PROC);
-fail:
-	return ret;
-}
-
-void ft1000_cleanup_proc(struct ft1000_info *info)
-{
-	remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-	remove_proc_entry(FT1000_PROC_DIR, FTNET_PROC);
-	unregister_netdevice_notifier(&ft1000_netdev_notifier);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c	2014-08-07 04:52:15.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c	2014-09-28 21:33:45.000000000 -0400
@@ -196,17 +196,10 @@ static int ft1000_probe(struct usb_inter
 	if (ret)
 		goto err_thread;
 
-	ret = ft1000_init_proc(ft1000dev->net);
-	if (ret)
-		goto err_proc;
-
 	ft1000dev->NetDevRegDone = 1;
 
 	return 0;
 
-err_proc:
-	unregister_netdev(ft1000dev->net);
-	free_netdev(ft1000dev->net);
 err_thread:
 	kthread_stop(ft1000dev->pPollThread);
 err_load:
@@ -230,7 +223,6 @@ static void ft1000_disconnect(struct usb
 
 	if (pft1000info) {
 		ft1000dev = pft1000info->priv;
-		ft1000_cleanup_proc(pft1000info);
 		if (ft1000dev->pPollThread)
 			kthread_stop(ft1000dev->pPollThread);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h	2014-09-28 17:29:07.000000000 -0400
@@ -136,7 +136,7 @@ extern spinlock_t free_buff_lock;
 
 int ft1000_create_dev(struct ft1000_usb *dev);
 void ft1000_destroy_dev(struct net_device *dev);
-extern void card_send_command(struct ft1000_usb *ft1000dev,
+extern int card_send_command(struct ft1000_usb *ft1000dev,
 			      void *ptempbuffer, int size);
 
 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
@@ -149,7 +149,4 @@ int reg_ft1000_netdev(struct ft1000_usb
 		      struct usb_interface *intf);
 int ft1000_poll(void *dev_id);
 
-int ft1000_init_proc(struct net_device *dev);
-void ft1000_cleanup_proc(struct ft1000_info *info);
-
 #endif  /* _FT1000_USB_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/Makefile
--- linux-libre-3.16-gnu/drivers/staging/ft1000/ft1000-usb/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/ft1000/ft1000-usb/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,3 +1,3 @@
 obj-$(CONFIG_FT1000_USB) += ft1000.o
 
-ft1000-y := ft1000_debug.o ft1000_download.o ft1000_hw.o ft1000_proc.o ft1000_usb.o
+ft1000-y := ft1000_debug.o ft1000_download.o ft1000_hw.o ft1000_usb.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/fwserial/fwserial.c linux-libre-3.17-rc7-gnu/drivers/staging/fwserial/fwserial.c
--- linux-libre-3.16-gnu/drivers/staging/fwserial/fwserial.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/fwserial/fwserial.c	2014-09-28 17:29:07.000000000 -0400
@@ -785,6 +785,7 @@ static int fwtty_tx(struct fwtty_port *p
 		len = dma_fifo_out_level(&port->tx_fifo);
 		if (len) {
 			unsigned long delay = (n == -ENOMEM) ? HZ : 1;
+
 			schedule_delayed_work(&port->drain, delay);
 		}
 		len = dma_fifo_level(&port->tx_fifo);
@@ -1995,6 +1996,7 @@ static struct fwtty_peer *__fwserial_pee
 
 	list_for_each_entry_rcu(peer, &serial->peer_list, list) {
 		int g = peer->generation;
+
 		smp_rmb();
 		if (generation == g && id == peer->node_id)
 			return peer;
@@ -2015,6 +2017,7 @@ static void __dump_peer_list(struct fw_c
 
 	list_for_each_entry_rcu(peer, &serial->peer_list, list) {
 		int g = peer->generation;
+
 		smp_rmb();
 		fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n",
 			  g, peer->node_id, (unsigned long long) peer->guid);
@@ -2120,6 +2123,7 @@ static int fwserial_add_peer(struct fw_s
 		serial->self = peer;
 		if (create_loop_dev) {
 			struct fwtty_port *port;
+
 			port = fwserial_claim_port(peer, num_ttys);
 			if (!IS_ERR(port)) {
 				struct virt_plug_params params;
@@ -2611,7 +2615,6 @@ cleanup:
 	if (port)
 		fwserial_release_port(port, false);
 	kfree(pkt);
-	return;
 }
 
 static void fwserial_handle_unplug_req(struct work_struct *work)
@@ -2663,7 +2666,6 @@ cleanup:
 	if (port)
 		fwserial_release_port(port, true);
 	kfree(pkt);
-	return;
 }
 
 static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_lte.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_lte.c
--- linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_lte.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_lte.c	2014-09-28 17:29:07.000000000 -0400
@@ -447,6 +447,7 @@ static int gdm_lte_tx(struct sk_buff *sk
 	 */
 	if (nic_type & NIC_TYPE_F_VLAN) {
 		struct vlan_ethhdr *vlan_eth = (struct vlan_ethhdr *)skb->data;
+
 		nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK;
 		data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN);
 		data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN);
@@ -505,6 +506,7 @@ static int gdm_lte_tx(struct sk_buff *sk
 static struct net_device_stats *gdm_lte_stats(struct net_device *dev)
 {
 	struct nic *nic = netdev_priv(dev);
+
 	return &nic->stats;
 }
 
@@ -885,7 +887,7 @@ int register_lte_device(struct phy_dev *
 
 		/* Allocate netdev */
 		net = alloc_netdev(sizeof(struct nic), pdn_dev_name,
-				ether_setup);
+				   NET_NAME_UNKNOWN, ether_setup);
 		if (net == NULL) {
 			pr_err("alloc_netdev failed\n");
 			ret = -ENOMEM;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_tty.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_tty.c
--- linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_tty.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_tty.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,24 +111,28 @@ static int gdm_tty_install(struct tty_dr
 static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
 {
 	struct gdm *gdm = tty->driver_data;
+
 	return tty_port_open(&gdm->port, tty, filp);
 }
 
 static void gdm_tty_cleanup(struct tty_struct *tty)
 {
 	struct gdm *gdm = tty->driver_data;
+
 	tty_port_put(&gdm->port);
 }
 
 static void gdm_tty_hangup(struct tty_struct *tty)
 {
 	struct gdm *gdm = tty->driver_data;
+
 	tty_port_hangup(&gdm->port);
 }
 
 static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct gdm *gdm = tty->driver_data;
+
 	tty_port_close(&gdm->port, tty, filp);
 }
 
@@ -139,6 +143,7 @@ static int gdm_tty_recv_complete(void *d
 				 int complete)
 {
 	struct gdm *gdm = tty_dev->gdm[index];
+
 	if (!GDM_TTY_READY(gdm)) {
 		if (complete == RECV_PACKET_PROCESS_COMPLETE)
 			gdm_tty_recv(gdm, gdm_tty_recv_complete);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_usb.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_usb.c
--- linux-libre-3.16-gnu/drivers/staging/gdm724x/gdm_usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/gdm_usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -125,11 +125,11 @@ static struct usb_tx_sdu *alloc_tx_sdu_s
 {
 	struct usb_tx_sdu *t_sdu;
 
-	t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC);
+	t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_KERNEL);
 	if (!t_sdu)
 		return NULL;
 
-	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC);
+	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL);
 	if (!t_sdu->buf) {
 		kfree(t_sdu);
 		return NULL;
@@ -183,14 +183,14 @@ static struct usb_rx *alloc_rx_struct(vo
 	struct usb_rx *r = NULL;
 	int ret = 0;
 
-	r = kmalloc(sizeof(struct usb_rx), GFP_ATOMIC);
+	r = kmalloc(sizeof(struct usb_rx), GFP_KERNEL);
 	if (!r) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	r->urb = usb_alloc_urb(0, GFP_ATOMIC);
-	r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC);
+	r->urb = usb_alloc_urb(0, GFP_KERNEL);
+	r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
 	if (!r->urb || !r->buf) {
 		ret = -ENOMEM;
 		goto out;
@@ -264,28 +264,25 @@ static void release_usb(struct lte_udev
 	unsigned long flags;
 
 	spin_lock_irqsave(&tx->lock, flags);
-	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list)
-	{
+	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) {
 		list_del(&t_sdu->list);
 		free_tx_sdu_struct(t_sdu);
 	}
 
-	list_for_each_entry_safe(t, t_next, &tx->hci_list, list)
-	{
+	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
 		list_del(&t->list);
 		free_tx_struct(t);
 	}
 
-	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list)
-	{
+	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) {
 		list_del(&t_sdu->list);
 		free_tx_sdu_struct(t_sdu);
 	}
 	spin_unlock_irqrestore(&tx->lock, flags);
 
 	spin_lock_irqsave(&rx->submit_lock, flags);
-	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list)
-	{
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
+				 rx_submit_list) {
 		spin_unlock_irqrestore(&rx->submit_lock, flags);
 		usb_kill_urb(r->urb);
 		spin_lock_irqsave(&rx->submit_lock, flags);
@@ -293,16 +290,14 @@ static void release_usb(struct lte_udev
 	spin_unlock_irqrestore(&rx->submit_lock, flags);
 
 	spin_lock_irqsave(&rx->rx_lock, flags);
-	list_for_each_entry_safe(r, r_next, &rx->free_list, free_list)
-	{
+	list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) {
 		list_del(&r->free_list);
 		free_rx_struct(r);
 	}
 	spin_unlock_irqrestore(&rx->rx_lock, flags);
 
 	spin_lock_irqsave(&rx->to_host_lock, flags);
-	list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list)
-	{
+	list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
 		if (r->index == (void *)udev) {
 			list_del(&r->to_host_list);
 			free_rx_struct(r);
@@ -366,6 +361,7 @@ static int init_usb(struct lte_udev *ude
 	INIT_DELAYED_WORK(&udev->work_rx, do_rx);
 	return 0;
 fail:
+	release_usb(udev);
 	return ret;
 }
 
@@ -457,9 +453,8 @@ static void remove_rx_submit_list(struct
 	struct usb_rx	*r_remove, *r_remove_next;
 
 	spin_lock_irqsave(&rx->submit_lock, flags);
-	list_for_each_entry_safe(r_remove,
-			r_remove_next, &rx->rx_submit_list, rx_submit_list)
-	{
+	list_for_each_entry_safe(r_remove, r_remove_next,
+				 &rx->rx_submit_list, rx_submit_list) {
 		if (r == r_remove) {
 			list_del(&r->rx_submit_list);
 			break;
@@ -895,6 +890,7 @@ static void gdm_usb_disconnect(struct us
 	struct lte_udev *udev;
 	u16 idVendor, idProduct;
 	struct usb_device *usbdev;
+
 	usbdev = interface_to_usbdev(intf);
 
 	idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
@@ -936,8 +932,8 @@ static int gdm_usb_suspend(struct usb_in
 	udev->usb_state = PM_SUSPEND;
 
 	spin_lock_irqsave(&rx->submit_lock, flags);
-	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list)
-	{
+	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
+				 rx_submit_list) {
 		spin_unlock_irqrestore(&rx->submit_lock, flags);
 		usb_kill_urb(r->urb);
 		spin_lock_irqsave(&rx->submit_lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm724x/netlink_k.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/netlink_k.c
--- linux-libre-3.16-gnu/drivers/staging/gdm724x/netlink_k.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm724x/netlink_k.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,7 @@ static void netlink_rcv_cb(struct sk_buf
 		return;
 	}
 
-	if (skb->len < NLMSG_SPACE(0)) {
+	if (skb->len < NLMSG_HDRLEN) {
 		pr_err("nl cb - invalid skb length\n");
 		return;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_qos.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_qos.c
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_qos.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_qos.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,8 +24,6 @@
 #include "hci.h"
 #include "gdm_qos.h"
 
-#define B2H(x)	__be16_to_cpu(x)
-
 #define MAX_FREE_LIST_CNT		32
 static struct {
 	struct list_head head;
@@ -100,7 +98,7 @@ void gdm_qos_init(void *nic_ptr)
 	for (i = 0; i < QOS_MAX; i++) {
 		INIT_LIST_HEAD(&qcb->qos_list[i]);
 		qcb->csr[i].qos_buf_count = 0;
-		qcb->csr[i].enabled = 0;
+		qcb->csr[i].enabled = false;
 	}
 
 	qcb->qos_list_cnt = 0;
@@ -127,7 +125,7 @@ void gdm_qos_release_list(void *nic_ptr)
 
 	for (i = 0; i < QOS_MAX; i++) {
 		qcb->csr[i].qos_buf_count = 0;
-		qcb->csr[i].enabled = 0;
+		qcb->csr[i].enabled = false;
 	}
 
 	qcb->qos_list_cnt = 0;
@@ -142,7 +140,7 @@ void gdm_qos_release_list(void *nic_ptr)
 	free_qos_entry_list(&free_list);
 }
 
-static u32 chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port)
+static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port)
 {
 	int i;
 
@@ -188,17 +186,17 @@ static u32 chk_ipv4_rule(struct gdm_wima
 	return 0;
 }
 
-static u32 get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph)
+static int get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph)
 {
-	u32 IP_ver, i;
+	int ip_ver, i;
 	struct qos_cb_s *qcb = &nic->qos;
 
 	if (iph == NULL || tcpudph == NULL)
 		return -1;
 
-	IP_ver = (iph[0]>>4)&0xf;
+	ip_ver = (iph[0]>>4)&0xf;
 
-	if (IP_ver != 4)
+	if (ip_ver != 4)
 		return -1;
 
 	for (i = 0; i < QOS_MAX; i++) {
@@ -213,7 +211,7 @@ static u32 get_qos_index(struct nic *nic
 	return -1;
 }
 
-static u32 extract_qos_list(struct nic *nic, struct list_head *head)
+static void extract_qos_list(struct nic *nic, struct list_head *head)
 {
 	struct qos_cb_s *qcb = &nic->qos;
 	struct qos_entry_s *entry;
@@ -238,8 +236,6 @@ static u32 extract_qos_list(struct nic *
 		if (!list_empty(&qcb->qos_list[i]))
 			netdev_warn(nic->netdev, "Index(%d) is piled!!\n", i);
 	}
-
-	return 0;
 }
 
 static void send_qos_list(struct nic *nic, struct list_head *head)
@@ -268,7 +264,7 @@ int gdm_qos_send_hci_pkt(struct sk_buff
 
 	tcph = (struct tcphdr *)iph + iph->ihl*4;
 
-	if (B2H(ethh->h_proto) == ETH_P_IP) {
+	if (ethh->h_proto == cpu_to_be16(ETH_P_IP)) {
 		if (qcb->qos_list_cnt && !qos_free_list.cnt) {
 			entry = alloc_qos_entry();
 			entry->skb = skb;
@@ -305,19 +301,19 @@ out:
 	return ret;
 }
 
-static u32 get_csr(struct qos_cb_s *qcb, u32 SFID, int mode)
+static int get_csr(struct qos_cb_s *qcb, u32 sfid, int mode)
 {
 	int i;
 
 	for (i = 0; i < qcb->qos_list_cnt; i++) {
-		if (qcb->csr[i].SFID == SFID)
+		if (qcb->csr[i].sfid == sfid)
 			return i;
 	}
 
 	if (mode) {
 		for (i = 0; i < QOS_MAX; i++) {
-			if (qcb->csr[i].enabled == 0) {
-				qcb->csr[i].enabled = 1;
+			if (!qcb->csr[i].enabled) {
+				qcb->csr[i].enabled = true;
 				qcb->qos_list_cnt++;
 				return i;
 			}
@@ -333,7 +329,8 @@ static u32 get_csr(struct qos_cb_s *qcb,
 void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 {
 	struct nic *nic = nic_ptr;
-	u32 i, SFID, index, pos;
+	int i, index, pos;
+	u32 sfid;
 	u8 sub_cmd_evt;
 	struct qos_cb_s *qcb = &nic->qos;
 	struct qos_entry_s *entry, *n;
@@ -346,11 +343,11 @@ void gdm_recv_qos_hci_packet(void *nic_p
 	if (sub_cmd_evt == QOS_REPORT) {
 		spin_lock_irqsave(&qcb->qos_lock, flags);
 		for (i = 0; i < qcb->qos_list_cnt; i++) {
-			SFID = ((buf[(i*5)+6]<<24)&0xff000000);
-			SFID += ((buf[(i*5)+7]<<16)&0xff0000);
-			SFID += ((buf[(i*5)+8]<<8)&0xff00);
-			SFID += (buf[(i*5)+9]);
-			index = get_csr(qcb, SFID, 0);
+			sfid = ((buf[(i*5)+6]<<24)&0xff000000);
+			sfid += ((buf[(i*5)+7]<<16)&0xff0000);
+			sfid += ((buf[(i*5)+8]<<8)&0xff00);
+			sfid += (buf[(i*5)+9]);
+			index = get_csr(qcb, sfid, 0);
 			if (index == -1) {
 				spin_unlock_irqrestore(&qcb->qos_lock, flags);
 				netdev_err(nic->netdev, "QoS ERROR: No SF\n");
@@ -367,12 +364,12 @@ void gdm_recv_qos_hci_packet(void *nic_p
 
 	/* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */
 	pos = 6;
-	SFID = ((buf[pos++]<<24)&0xff000000);
-	SFID += ((buf[pos++]<<16)&0xff0000);
-	SFID += ((buf[pos++]<<8)&0xff00);
-	SFID += (buf[pos++]);
+	sfid = ((buf[pos++]<<24)&0xff000000);
+	sfid += ((buf[pos++]<<16)&0xff0000);
+	sfid += ((buf[pos++]<<8)&0xff00);
+	sfid += (buf[pos++]);
 
-	index = get_csr(qcb, SFID, 1);
+	index = get_csr(qcb, sfid, 1);
 	if (index == -1) {
 		netdev_err(nic->netdev,
 			   "QoS ERROR: csr Update Error / Wrong index (%d)\n",
@@ -382,10 +379,10 @@ void gdm_recv_qos_hci_packet(void *nic_p
 
 	if (sub_cmd_evt == QOS_ADD) {
 		netdev_dbg(nic->netdev, "QOS_ADD SFID = 0x%x, index=%d\n",
-			   SFID, index);
+			   sfid, index);
 
 		spin_lock_irqsave(&qcb->qos_lock, flags);
-		qcb->csr[index].SFID = SFID;
+		qcb->csr[index].sfid = sfid;
 		qcb->csr[index].classifier_rule_en = ((buf[pos++]<<8)&0xff00);
 		qcb->csr[index].classifier_rule_en += buf[pos++];
 		if (qcb->csr[index].classifier_rule_en == 0)
@@ -423,12 +420,12 @@ void gdm_recv_qos_hci_packet(void *nic_p
 		spin_unlock_irqrestore(&qcb->qos_lock, flags);
 	} else if (sub_cmd_evt == QOS_CHANGE_DEL) {
 		netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n",
-			   SFID, index);
+			   sfid, index);
 
 		INIT_LIST_HEAD(&free_list);
 
 		spin_lock_irqsave(&qcb->qos_lock, flags);
-		qcb->csr[index].enabled = 0;
+		qcb->csr[index].enabled = false;
 		qcb->qos_list_cnt--;
 		qcb->qos_limit_size = 254/qcb->qos_list_cnt;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_qos.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_qos.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_qos.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_qos.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,15 +11,13 @@
  * GNU General Public License for more details.
  */
 
-#if !defined(GDM_QOS_H_20090403)
-#define GDM_QOS_H_20090403
+#ifndef __GDM72XX_GDM_QOS_H__
+#define __GDM72XX_GDM_QOS_H__
 
 #include <linux/types.h>
 #include <linux/usb.h>
 #include <linux/list.h>
 
-#define BOOLEAN	u8
-
 #define QOS_MAX				16
 #define IPTYPEOFSERVICE			0x8000
 #define	PROTOCOL			0x4000
@@ -34,8 +32,8 @@
 #define	IEEE802_1QVLANID		0x10
 
 struct gdm_wimax_csr_s {
-	BOOLEAN		enabled;
-	u32		SFID;
+	bool		enabled;
+	u32		sfid;
 	u8		qos_buf_count;
 	u16		classifier_rule_en;
 	u8		ip2s_lo;
@@ -61,11 +59,11 @@ struct qos_entry_s {
 
 struct qos_cb_s {
 	struct list_head	qos_list[QOS_MAX];
-	u32			qos_list_cnt;
-	u32			qos_null_idx;
+	int			qos_list_cnt;
+	int			qos_null_idx;
 	struct gdm_wimax_csr_s	csr[QOS_MAX];
 	spinlock_t		qos_lock;
-	u32			qos_limit_size;
+	int			qos_limit_size;
 };
 
 void gdm_qos_init(void *nic_ptr);
@@ -73,4 +71,4 @@ void gdm_qos_release_list(void *nic_ptr)
 int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev);
 void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size);
 
-#endif
+#endif /* __GDM72XX_GDM_QOS_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_sdio.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_sdio.c
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_sdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_sdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,9 +38,6 @@
 #define TX_HZ		2000
 #define TX_INTERVAL	(1000000/TX_HZ)
 
-static int init_sdio(struct sdiowm_dev *sdev);
-static void release_sdio(struct sdiowm_dev *sdev);
-
 static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx)
 {
 	struct sdio_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC);
@@ -124,6 +121,43 @@ static void put_rx_struct(struct rx_cxt
 	list_add_tail(&r->list, &rx->free_list);
 }
 
+static void release_sdio(struct sdiowm_dev *sdev)
+{
+	struct tx_cxt	*tx = &sdev->tx;
+	struct rx_cxt	*rx = &sdev->rx;
+	struct sdio_tx	*t, *t_next;
+	struct sdio_rx	*r, *r_next;
+
+	kfree(tx->sdu_buf);
+
+	list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	kfree(rx->rx_buf);
+
+	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
+		list_del(&r->list);
+		free_rx_struct(r);
+	}
+
+	list_for_each_entry_safe(r, r_next, &rx->req_list, list) {
+		list_del(&r->list);
+		free_rx_struct(r);
+	}
+}
+
 static int init_sdio(struct sdiowm_dev *sdev)
 {
 	int ret = 0, i;
@@ -176,43 +210,6 @@ fail:
 	return ret;
 }
 
-static void release_sdio(struct sdiowm_dev *sdev)
-{
-	struct tx_cxt	*tx = &sdev->tx;
-	struct rx_cxt	*rx = &sdev->rx;
-	struct sdio_tx	*t, *t_next;
-	struct sdio_rx	*r, *r_next;
-
-	kfree(tx->sdu_buf);
-
-	list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	kfree(rx->rx_buf);
-
-	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
-		list_del(&r->list);
-		free_rx_struct(r);
-	}
-
-	list_for_each_entry_safe(r, r_next, &rx->req_list, list) {
-		list_del(&r->list);
-		free_rx_struct(r);
-	}
-}
-
 static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
 {
 	int n, blocks, ret, remain;
@@ -275,14 +272,14 @@ static void send_sdu(struct sdio_func *f
 	aggr_len = pos;
 
 	hci = (struct hci_s *)(tx->sdu_buf + TYPE_A_HEADER_SIZE);
-	hci->cmd_evt = H2B(WIMAX_TX_SDU_AGGR);
-	hci->length = H2B(aggr_len - TYPE_A_HEADER_SIZE - HCI_HEADER_SIZE);
+	hci->cmd_evt = cpu_to_be16(WIMAX_TX_SDU_AGGR);
+	hci->length = cpu_to_be16(aggr_len - TYPE_A_HEADER_SIZE -
+				  HCI_HEADER_SIZE);
 
 	spin_unlock_irqrestore(&tx->lock, flags);
 
-	print_hex_dump_debug("sdio_send: ", DUMP_PREFIX_NONE, 16, 1,
-			     tx->sdu_buf + TYPE_A_HEADER_SIZE,
-			     aggr_len - TYPE_A_HEADER_SIZE, false);
+	dev_dbg(&func->dev, "sdio_send: %*ph\n", aggr_len - TYPE_A_HEADER_SIZE,
+		tx->sdu_buf + TYPE_A_HEADER_SIZE);
 
 	for (pos = TYPE_A_HEADER_SIZE; pos < aggr_len; pos += TX_CHUNK_SIZE) {
 		len = aggr_len - pos;
@@ -317,9 +314,9 @@ static void send_hci(struct sdio_func *f
 {
 	unsigned long flags;
 
-	print_hex_dump_debug("sdio_send: ", DUMP_PREFIX_NONE, 16, 1,
-			     t->buf + TYPE_A_HEADER_SIZE,
-			     t->len - TYPE_A_HEADER_SIZE, false);
+	dev_dbg(&func->dev, "sdio_send: %*ph\n", t->len - TYPE_A_HEADER_SIZE,
+		t->buf + TYPE_A_HEADER_SIZE);
+
 	send_sdio_pkt(func, t->buf, t->len);
 
 	spin_lock_irqsave(&tx->lock, flags);
@@ -390,7 +387,8 @@ static int gdm_sdio_send(void *priv_dev,
 	u16 cmd_evt;
 	unsigned long flags;
 
-	BUG_ON(len > TX_BUF_SIZE - TYPE_A_HEADER_SIZE);
+	if (len > TX_BUF_SIZE - TYPE_A_HEADER_SIZE)
+		return -EINVAL;
 
 	spin_lock_irqsave(&tx->lock, flags);
 
@@ -439,9 +437,7 @@ static int gdm_sdio_send(void *priv_dev,
 	return 0;
 }
 
-/*
- * Handle the HCI, WIMAX_SDU_TX_FLOW.
- */
+/* Handle the HCI, WIMAX_SDU_TX_FLOW. */
 static int control_sdu_tx_flow(struct sdiowm_dev *sdev, u8 *hci_data, int len)
 {
 	struct tx_cxt *tx = &sdev->tx;
@@ -462,8 +458,7 @@ static int control_sdu_tx_flow(struct sd
 		tx->stop_sdu_tx = 0;
 		if (tx->can_send)
 			schedule_work(&sdev->ws);
-		/*
-		 * If free buffer for sdu tx doesn't exist, then tx queue
+		/* If free buffer for sdu tx doesn't exist, then tx queue
 		 * should not be woken. For this reason, don't pass the command,
 		 * START_SDU_TX.
 		 */
@@ -553,8 +548,8 @@ static void gdm_sdio_irq(struct sdio_fun
 	}
 
 end_io:
-	print_hex_dump_debug("sdio_receive: ", DUMP_PREFIX_NONE, 16, 1,
-			     rx->rx_buf, len, false);
+	dev_dbg(&func->dev, "sdio_receive: %*ph\n", len, rx->rx_buf);
+
 	len = control_sdu_tx_flow(sdev, rx->rx_buf, len);
 
 	spin_lock_irqsave(&rx->lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_sdio.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_sdio.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_sdio.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_sdio.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __GDM_SDIO_H__
-#define __GDM_SDIO_H__
+#ifndef __GDM72XX_GDM_SDIO_H__
+#define __GDM72XX_GDM_SDIO_H__
 
 #include <linux/types.h>
 #include <linux/time.h>
@@ -60,4 +60,4 @@ struct sdiowm_dev {
 	struct work_struct	ws;
 };
 
-#endif /* __GDM_SDIO_H__ */
+#endif /* __GDM72XX_GDM_SDIO_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_usb.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_usb.c
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_usb.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,10 +36,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 #define GDM7205_PADDING		256
 
-#define H2B(x)		__cpu_to_be16(x)
-#define B2H(x)		__be16_to_cpu(x)
-#define DB2H(x)		__be32_to_cpu(x)
-
 #define DOWNLOAD_CONF_VALUE	0x21
 
 #ifdef CONFIG_WIMAX_GDM72XX_K_MODE
@@ -53,9 +49,6 @@ static int k_mode_stop;
 
 #endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
 
-static int init_usb(struct usbwm_dev *udev);
-static void release_usb(struct usbwm_dev *udev);
-
 static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx)
 {
 	struct usb_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC);
@@ -164,6 +157,48 @@ static void put_rx_struct(struct rx_cxt
 	list_move(&r->list, &rx->free_list);
 }
 
+static void release_usb(struct usbwm_dev *udev)
+{
+	struct tx_cxt *tx = &udev->tx;
+	struct rx_cxt *rx = &udev->rx;
+	struct usb_tx *t, *t_next;
+	struct usb_rx *r, *r_next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx->lock, flags);
+
+	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
+		list_del(&t->list);
+		free_tx_struct(t);
+	}
+
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	spin_lock_irqsave(&rx->lock, flags);
+
+	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
+		list_del(&r->list);
+		free_rx_struct(r);
+	}
+
+	list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
+		list_del(&r->list);
+		free_rx_struct(r);
+	}
+
+	spin_unlock_irqrestore(&rx->lock, flags);
+}
+
 static int init_usb(struct usbwm_dev *udev)
 {
 	int ret = 0, i;
@@ -214,48 +249,6 @@ fail:
 	return ret;
 }
 
-static void release_usb(struct usbwm_dev *udev)
-{
-	struct tx_cxt *tx = &udev->tx;
-	struct rx_cxt *rx = &udev->rx;
-	struct usb_tx *t, *t_next;
-	struct usb_rx *r, *r_next;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tx->lock, flags);
-
-	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
-		list_del(&t->list);
-		free_tx_struct(t);
-	}
-
-	spin_unlock_irqrestore(&tx->lock, flags);
-
-	spin_lock_irqsave(&rx->lock, flags);
-
-	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
-		list_del(&r->list);
-		free_rx_struct(r);
-	}
-
-	list_for_each_entry_safe(r, r_next, &rx->used_list, list) {
-		list_del(&r->list);
-		free_rx_struct(r);
-	}
-
-	spin_unlock_irqrestore(&rx->lock, flags);
-}
-
 static void __gdm_usb_send_complete(struct urb *urb)
 {
 	struct usb_tx *t = urb->context;
@@ -312,7 +305,8 @@ static int gdm_usb_send(void *priv_dev,
 		return -ENODEV;
 	}
 
-	BUG_ON(len > TX_BUF_SIZE - padding - 1);
+	if (len > TX_BUF_SIZE - padding - 1)
+		return -EINVAL;
 
 	spin_lock_irqsave(&tx->lock, flags);
 
@@ -338,8 +332,7 @@ static int gdm_usb_send(void *priv_dev,
 	t->callback = cb;
 	t->cb_data = cb_data;
 
-	/*
-	 * In some cases, USB Module of WiMax is blocked when data size is
+	/* In some cases, USB Module of WiMax is blocked when data size is
 	 * the multiple of 512. So, increment length by one in that case.
 	 */
 	if ((len % 512) == 0)
@@ -348,8 +341,8 @@ static int gdm_usb_send(void *priv_dev,
 	usb_fill_bulk_urb(t->urb, usbdev, usb_sndbulkpipe(usbdev, 1), t->buf,
 			  len + padding, gdm_usb_send_complete, t);
 
-	print_hex_dump_debug("usb_send: ", DUMP_PREFIX_NONE, 16, 1, t->buf,
-			     len + padding, false);
+	dev_dbg(&usbdev->dev, "usb_send: %*ph\n", len + padding, t->buf);
+
 #ifdef CONFIG_WIMAX_GDM72XX_USB_PM
 	if (usbdev->state & USB_STATE_SUSPENDED) {
 		list_add_tail(&t->p_list, &tx->pending_list);
@@ -427,8 +420,10 @@ static void gdm_usb_rcv_complete(struct
 
 	if (!urb->status) {
 		cmd_evt = (r->buf[0] << 8) | (r->buf[1]);
-		print_hex_dump_debug("usb_receive: ", DUMP_PREFIX_NONE, 16, 1,
-				     r->buf, urb->actual_length, false);
+
+		dev_dbg(&dev->dev, "usb_receive: %*ph\n", urb->actual_length,
+			r->buf);
+
 		if (cmd_evt == WIMAX_SDU_TX_FLOW) {
 			if (r->buf[4] == 0) {
 				dev_dbg(&dev->dev, "WIMAX ==> STOP SDU TX\n");
@@ -439,8 +434,7 @@ static void gdm_usb_rcv_complete(struct
 				list_for_each_entry(t, &tx->sdu_list, list) {
 					usb_submit_urb(t->urb, GFP_ATOMIC);
 				}
-				/*
-				 * If free buffer for sdu tx doesn't
+				/* If free buffer for sdu tx doesn't
 				 * exist, then tx queue should not be
 				 * woken. For this reason, don't pass
 				 * the command, START_SDU_TX.
@@ -542,9 +536,9 @@ static int gdm_usb_probe(struct usb_inte
 	bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue;
 
 	/*USB description is set up with Little-Endian*/
-	idVendor = L2H(usbdev->descriptor.idVendor);
-	idProduct = L2H(usbdev->descriptor.idProduct);
-	bcdDevice = L2H(usbdev->descriptor.bcdDevice);
+	idVendor = le16_to_cpu(usbdev->descriptor.idVendor);
+	idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
+	bcdDevice = le16_to_cpu(usbdev->descriptor.bcdDevice);
 
 	dev_info(&intf->dev, "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
 		 idVendor, idProduct);
@@ -627,12 +621,11 @@ static void gdm_usb_disconnect(struct us
 	phy_dev = usb_get_intfdata(intf);
 
 	/*USB description is set up with Little-Endian*/
-	idProduct = L2H(usbdev->descriptor.idProduct);
+	idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
 
 	if (idProduct != EMERGENCY_PID &&
 	    bConfigurationValue != DOWNLOAD_CONF_VALUE &&
 	    (idProduct & B_DOWNLOAD) == 0) {
-
 		udev = phy_dev->priv_dev;
 		udev->usbdev = NULL;
 
@@ -710,10 +703,8 @@ static int k_mode_thread(void *arg)
 	int ret;
 
 	while (!k_mode_stop) {
-
 		spin_lock_irqsave(&k_lock, flags2);
 		while (!list_empty(&k_list)) {
-
 			udev = list_entry(k_list.next, struct usbwm_dev, list);
 			tx = &udev->tx;
 			rx = &udev->rx;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_usb.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_usb.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_usb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_usb.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __GDM_USB_H__
-#define __GDM_USB_H__
+#ifndef __GDM72XX_GDM_USB_H__
+#define __GDM72XX_GDM_USB_H__
 
 #include <linux/types.h>
 #include <linux/usb.h>
@@ -75,4 +75,4 @@ struct usbwm_dev {
 	int			padding;
 };
 
-#endif /* __GDM_USB_H__ */
+#endif /* __GDM72XX_GDM_USB_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_wimax.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_wimax.c
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_wimax.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_wimax.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,12 +41,6 @@ struct evt_entry {
 	int	size;
 };
 
-static void __gdm_wimax_event_send(struct work_struct *work);
-static inline struct evt_entry *alloc_event_entry(void);
-static inline void free_event_entry(struct evt_entry *e);
-static struct evt_entry *get_event_entry(void);
-static void put_event_entry(struct evt_entry *e);
-
 static struct {
 	int ref_cnt;
 	struct sock *sock;
@@ -58,114 +52,10 @@ static struct {
 
 static u8 gdm_wimax_macaddr[6] = {0x00, 0x0a, 0x3b, 0xf0, 0x01, 0x30};
 
-static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm);
-static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up);
-
-static const char *get_protocol_name(u16 protocol)
-{
-	static char buf[32];
-	const char *name = "-";
-
-	switch (protocol) {
-	case ETH_P_ARP:
-		name = "ARP";
-		break;
-	case ETH_P_IP:
-		name = "IP";
-		break;
-	case ETH_P_IPV6:
-		name = "IPv6";
-		break;
-	}
-
-	sprintf(buf, "0x%04x(%s)", protocol, name);
-	return buf;
-}
-
-static const char *get_ip_protocol_name(u8 ip_protocol)
-{
-	static char buf[32];
-	const char *name = "-";
-
-	switch (ip_protocol) {
-	case IPPROTO_TCP:
-		name = "TCP";
-		break;
-	case IPPROTO_UDP:
-		name = "UDP";
-		break;
-	case IPPROTO_ICMP:
-		name = "ICMP";
-		break;
-	}
-
-	sprintf(buf, "%u(%s)", ip_protocol, name);
-	return buf;
-}
-
-static const char *get_port_name(u16 port)
-{
-	static char buf[32];
-	const char *name = "-";
-
-	switch (port) {
-	case 67:
-		name = "DHCP-Server";
-		break;
-	case 68:
-		name = "DHCP-Client";
-		break;
-	case 69:
-		name = "TFTP";
-		break;
-	}
-
-	sprintf(buf, "%u(%s)", port, name);
-	return buf;
-}
-
-static void dump_eth_packet(struct net_device *dev, const char *title,
-			    u8 *data, int len)
-{
-	struct iphdr *ih = NULL;
-	struct udphdr *uh = NULL;
-	u16 protocol = 0;
-	u8 ip_protocol = 0;
-	u16 port = 0;
-
-	protocol = (data[12]<<8) | data[13];
-	ih = (struct iphdr *)(data+ETH_HLEN);
-
-	if (protocol == ETH_P_IP) {
-		uh = (struct udphdr *)((char *)ih + sizeof(struct iphdr));
-		ip_protocol = ih->protocol;
-		port = ntohs(uh->dest);
-	} else if (protocol == ETH_P_IPV6) {
-		struct ipv6hdr *i6h = (struct ipv6hdr *)data;
-
-		uh = (struct udphdr *)((char *)i6h + sizeof(struct ipv6hdr));
-		ip_protocol = i6h->nexthdr;
-		port = ntohs(uh->dest);
-	}
-
-	netdev_dbg(dev, "[%s] len=%d, %s, %s, %s\n", title, len,
-		   get_protocol_name(protocol),
-		   get_ip_protocol_name(ip_protocol),
-		   get_port_name(port));
-
-	if (!(data[0] == 0xff && data[1] == 0xff)) {
-		if (protocol == ETH_P_IP)
-			netdev_dbg(dev, "     src=%pI4\n", &ih->saddr);
-		else if (protocol == ETH_P_IPV6)
-			netdev_dbg(dev, "     src=%pI6\n", &ih->saddr);
-	}
-
-	print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, data, len, false);
-}
-
 static inline int gdm_wimax_header(struct sk_buff **pskb)
 {
 	u16 buf[HCI_HEADER_SIZE / sizeof(u16)];
+	struct hci_s *hci = (struct hci_s *)buf;
 	struct sk_buff *skb = *pskb;
 
 	if (unlikely(skb_headroom(skb) < HCI_HEADER_SIZE)) {
@@ -181,14 +71,45 @@ static inline int gdm_wimax_header(struc
 	}
 
 	skb_push(skb, HCI_HEADER_SIZE);
-	buf[0] = H2B(WIMAX_TX_SDU);
-	buf[1] = H2B(skb->len - HCI_HEADER_SIZE);
+	hci->cmd_evt = cpu_to_be16(WIMAX_TX_SDU);
+	hci->length = cpu_to_be16(skb->len - HCI_HEADER_SIZE);
 	memcpy(skb->data, buf, HCI_HEADER_SIZE);
 
 	*pskb = skb;
 	return 0;
 }
 
+static inline struct evt_entry *alloc_event_entry(void)
+{
+	return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC);
+}
+
+static inline void free_event_entry(struct evt_entry *e)
+{
+	kfree(e);
+}
+
+static struct evt_entry *get_event_entry(void)
+{
+	struct evt_entry *e;
+
+	if (list_empty(&wm_event.freeq)) {
+		e = alloc_event_entry();
+	} else {
+		e = list_entry(wm_event.freeq.next, struct evt_entry, list);
+		list_del(&e->list);
+	}
+
+	return e;
+}
+
+static void put_event_entry(struct evt_entry *e)
+{
+	BUG_ON(!e);
+
+	list_add_tail(&e->list, &wm_event.freeq);
+}
+
 static void gdm_wimax_event_rcv(struct net_device *dev, u16 type, void *msg,
 				int len)
 {
@@ -203,6 +124,30 @@ static void gdm_wimax_event_rcv(struct n
 	gdm_wimax_send(nic, msg, len);
 }
 
+static void __gdm_wimax_event_send(struct work_struct *work)
+{
+	int idx;
+	unsigned long flags;
+	struct evt_entry *e;
+
+	spin_lock_irqsave(&wm_event.evt_lock, flags);
+
+	while (!list_empty(&wm_event.evtq)) {
+		e = list_entry(wm_event.evtq.next, struct evt_entry, list);
+		spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+
+		if (sscanf(e->dev->name, "wm%d", &idx) == 1)
+			netlink_send(wm_event.sock, idx, 0, e->evt_data,
+				     e->size);
+
+		spin_lock_irqsave(&wm_event.evt_lock, flags);
+		list_del(&e->list);
+		put_event_entry(e);
+	}
+
+	spin_unlock_irqrestore(&wm_event.evt_lock, flags);
+}
+
 static int gdm_wimax_event_init(void)
 {
 	if (!wm_event.ref_cnt) {
@@ -248,60 +193,6 @@ static void gdm_wimax_event_exit(void)
 	}
 }
 
-static inline struct evt_entry *alloc_event_entry(void)
-{
-	return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC);
-}
-
-static inline void free_event_entry(struct evt_entry *e)
-{
-	kfree(e);
-}
-
-static struct evt_entry *get_event_entry(void)
-{
-	struct evt_entry *e;
-
-	if (list_empty(&wm_event.freeq)) {
-		e = alloc_event_entry();
-	} else {
-		e = list_entry(wm_event.freeq.next, struct evt_entry, list);
-		list_del(&e->list);
-	}
-
-	return e;
-}
-
-static void put_event_entry(struct evt_entry *e)
-{
-	BUG_ON(!e);
-
-	list_add_tail(&e->list, &wm_event.freeq);
-}
-
-static void __gdm_wimax_event_send(struct work_struct *work)
-{
-	int idx;
-	unsigned long flags;
-	struct evt_entry *e;
-
-	spin_lock_irqsave(&wm_event.evt_lock, flags);
-
-	while (!list_empty(&wm_event.evtq)) {
-		e = list_entry(wm_event.evtq.next, struct evt_entry, list);
-		spin_unlock_irqrestore(&wm_event.evt_lock, flags);
-
-		sscanf(e->dev->name, "wm%d", &idx);
-		netlink_send(wm_event.sock, idx, 0, e->evt_data, e->size);
-
-		spin_lock_irqsave(&wm_event.evt_lock, flags);
-		list_del(&e->list);
-		put_event_entry(e);
-	}
-
-	spin_unlock_irqrestore(&wm_event.evt_lock, flags);
-}
-
 static int gdm_wimax_event_send(struct net_device *dev, char *buf, int size)
 {
 	struct evt_entry *e;
@@ -358,8 +249,8 @@ int gdm_wimax_send_tx(struct sk_buff *sk
 		return ret;
 	}
 
-	nic->stats.tx_packets++;
-	nic->stats.tx_bytes += skb->len - HCI_HEADER_SIZE;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len - HCI_HEADER_SIZE;
 	kfree_skb(skb);
 	return ret;
 }
@@ -367,10 +258,6 @@ int gdm_wimax_send_tx(struct sk_buff *sk
 static int gdm_wimax_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	int ret = 0;
-	struct nic *nic = netdev_priv(dev);
-	struct fsm_s *fsm = (struct fsm_s *)nic->sdk_data[SIOC_DATA_FSM].buf;
-
-	dump_eth_packet(dev, "TX", skb->data, skb->len);
 
 	ret = gdm_wimax_header(&skb);
 	if (ret < 0) {
@@ -378,17 +265,6 @@ static int gdm_wimax_tx(struct sk_buff *
 		return ret;
 	}
 
-	#if !defined(LOOPBACK_TEST)
-	if (!fsm) {
-		netdev_err(dev, "ASSERTION ERROR: fsm is NULL!!\n");
-	} else if (fsm->m_status != M_CONNECTED) {
-		netdev_emerg(dev, "ASSERTION ERROR: Device is NOT ready. status=%d\n",
-			     fsm->m_status);
-		kfree_skb(skb);
-		return 0;
-	}
-	#endif
-
 #if defined(CONFIG_WIMAX_GDM72XX_QOS)
 	ret = gdm_qos_send_hci_pkt(skb, dev);
 #else
@@ -408,7 +284,7 @@ static int gdm_wimax_set_config(struct n
 static void __gdm_wimax_set_mac_addr(struct net_device *dev, char *mac_addr)
 {
 	u16 hci_pkt_buf[32 / sizeof(u16)];
-	u8 *pkt = (u8 *)&hci_pkt_buf[0];
+	struct hci_s *hci = (struct hci_s *)hci_pkt_buf;
 	struct nic *nic = netdev_priv(dev);
 
 	/* Since dev is registered as a ethernet device,
@@ -419,13 +295,13 @@ static void __gdm_wimax_set_mac_addr(str
 	/* Let lower layer know of this change by sending
 	 * SetInformation(MAC Address)
 	 */
-	hci_pkt_buf[0] = H2B(WIMAX_SET_INFO);	/* cmd_evt */
-	hci_pkt_buf[1] = H2B(8);			/* size */
-	pkt[4] = 0; /* T */
-	pkt[5] = 6; /* L */
-	memcpy(pkt + 6, mac_addr, dev->addr_len); /* V */
+	hci->cmd_evt = cpu_to_be16(WIMAX_SET_INFO);
+	hci->length = cpu_to_be16(8);
+	hci->data[0] = 0; /* T */
+	hci->data[1] = 6; /* L */
+	memcpy(&hci->data[2], mac_addr, dev->addr_len); /* V */
 
-	gdm_wimax_send(nic, pkt, HCI_HEADER_SIZE + 8);
+	gdm_wimax_send(nic, hci, HCI_HEADER_SIZE + 8);
 }
 
 /* A driver function */
@@ -444,11 +320,20 @@ static int gdm_wimax_set_mac_addr(struct
 	return 0;
 }
 
-static struct net_device_stats *gdm_wimax_stats(struct net_device *dev)
+static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up)
 {
-	struct nic *nic = netdev_priv(dev);
+	u16 buf[32 / sizeof(u16)];
+	struct hci_s *hci = (struct hci_s *)buf;
+	unsigned char up_down;
 
-	return &nic->stats;
+	up_down = if_up ? WIMAX_IF_UP : WIMAX_IF_DOWN;
+
+	/* Indicate updating fsm */
+	hci->cmd_evt = cpu_to_be16(WIMAX_IF_UPDOWN);
+	hci->length = cpu_to_be16(sizeof(up_down));
+	hci->data[0] = up_down;
+
+	gdm_wimax_event_send(dev, (char *)hci, HCI_HEADER_SIZE+sizeof(up_down));
 }
 
 static int gdm_wimax_open(struct net_device *dev)
@@ -533,6 +418,20 @@ static void gdm_wimax_cleanup_ioctl(stru
 		kdelete(&nic->sdk_data[i].buf);
 }
 
+static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm)
+{
+	u16 buf[32 / sizeof(u16)];
+	struct hci_s *hci = (struct hci_s *)buf;
+
+	/* Indicate updating fsm */
+	hci->cmd_evt = cpu_to_be16(WIMAX_FSM_UPDATE);
+	hci->length = cpu_to_be16(sizeof(struct fsm_s));
+	memcpy(&hci->data[0], fsm, sizeof(struct fsm_s));
+
+	gdm_wimax_event_send(dev, (char *)hci,
+			     HCI_HEADER_SIZE + sizeof(struct fsm_s));
+}
+
 static void gdm_update_fsm(struct net_device *dev, struct fsm_s *new_fsm)
 {
 	struct nic *nic = netdev_priv(dev);
@@ -580,8 +479,9 @@ static int gdm_wimax_ioctl(struct net_de
 				return ret;
 		} else if (req->cmd == SIOCS_DATA) {
 			if (req->data_id == SIOC_DATA_FSM) {
-				/*NOTE: gdm_update_fsm should be called
-				before gdm_wimax_ioctl_set_data is called*/
+				/* NOTE: gdm_update_fsm should be called
+				 * before gdm_wimax_ioctl_set_data is called.
+				 */
 				gdm_update_fsm(dev,
 					       (struct fsm_s *)req->data.buf);
 			}
@@ -606,39 +506,35 @@ static void gdm_wimax_prepare_device(str
 	struct hci_s *hci = (struct hci_s *)buf;
 	u16 len = 0;
 	u32 val = 0;
-
-	#define BIT_MULTI_CS	0
-	#define BIT_WIMAX		1
-	#define BIT_QOS			2
-	#define BIT_AGGREGATION	3
+	__be32 val_be32;
 
 	/* GetInformation mac address */
 	len = 0;
-	hci->cmd_evt = H2B(WIMAX_GET_INFO);
+	hci->cmd_evt = cpu_to_be16(WIMAX_GET_INFO);
 	hci->data[len++] = TLV_T(T_MAC_ADDRESS);
-	hci->length = H2B(len);
+	hci->length = cpu_to_be16(len);
 	gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len);
 
-	val = (1<<BIT_WIMAX) | (1<<BIT_MULTI_CS);
+	val = T_CAPABILITY_WIMAX | T_CAPABILITY_MULTI_CS;
 	#if defined(CONFIG_WIMAX_GDM72XX_QOS)
-	val |= (1<<BIT_QOS);
+	val |= T_CAPABILITY_QOS;
 	#endif
 	#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2)
-	val |= (1<<BIT_AGGREGATION);
+	val |= T_CAPABILITY_AGGREGATION;
 	#endif
 
 	/* Set capability */
 	len = 0;
-	hci->cmd_evt = H2B(WIMAX_SET_INFO);
+	hci->cmd_evt = cpu_to_be16(WIMAX_SET_INFO);
 	hci->data[len++] = TLV_T(T_CAPABILITY);
 	hci->data[len++] = TLV_L(T_CAPABILITY);
-	val = DH2B(val);
-	memcpy(&hci->data[len], &val, TLV_L(T_CAPABILITY));
+	val_be32 = cpu_to_be32(val);
+	memcpy(&hci->data[len], &val_be32, TLV_L(T_CAPABILITY));
 	len += TLV_L(T_CAPABILITY);
-	hci->length = H2B(len);
+	hci->length = cpu_to_be16(len);
 	gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len);
 
-	netdev_info(dev, "GDM WiMax Set CAPABILITY: 0x%08X\n", DB2H(val));
+	netdev_info(dev, "GDM WiMax Set CAPABILITY: 0x%08X\n", val);
 }
 
 static int gdm_wimax_hci_get_tlv(u8 *buf, u8 *T, u16 *L, u8 **V)
@@ -648,7 +544,7 @@ static int gdm_wimax_hci_get_tlv(u8 *buf
 
 	*T = buf[0];
 	if (buf[1] == 0x82) {
-		*L = B2H(__U82U16(&buf[2]));
+		*L = be16_to_cpu(__U82U16(&buf[2]));
 		next_pos = 1/*type*/+3/*len*/;
 	} else {
 		*L = buf[1];
@@ -668,8 +564,8 @@ static int gdm_wimax_get_prepared_info(s
 	u16 cmd_evt, cmd_len;
 	int pos = HCI_HEADER_SIZE;
 
-	cmd_evt = B2H(*(u16 *)&buf[0]);
-	cmd_len = B2H(*(u16 *)&buf[2]);
+	cmd_evt = be16_to_cpup((const __be16 *)&buf[0]);
+	cmd_len = be16_to_cpup((const __be16 *)&buf[2]);
 
 	if (len < cmd_len + HCI_HEADER_SIZE) {
 		netdev_err(dev, "%s: invalid length [%d/%d]\n", __func__,
@@ -705,12 +601,9 @@ static int gdm_wimax_get_prepared_info(s
 
 static void gdm_wimax_netif_rx(struct net_device *dev, char *buf, int len)
 {
-	struct nic *nic = netdev_priv(dev);
 	struct sk_buff *skb;
 	int ret;
 
-	dump_eth_packet(dev, "RX", buf, len);
-
 	skb = dev_alloc_skb(len + 2);
 	if (!skb) {
 		netdev_err(dev, "%s: dev_alloc_skb failed!\n", __func__);
@@ -718,8 +611,8 @@ static void gdm_wimax_netif_rx(struct ne
 	}
 	skb_reserve(skb, 2);
 
-	nic->stats.rx_packets++;
-	nic->stats.rx_bytes += len;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += len;
 
 	memcpy(skb_put(skb, len), buf, len);
 
@@ -742,13 +635,13 @@ static void gdm_wimax_transmit_aggr_pkt(
 	while (len > 0) {
 		hci = (struct hci_s *)buf;
 
-		if (B2H(hci->cmd_evt) != WIMAX_RX_SDU) {
+		if (hci->cmd_evt != cpu_to_be16(WIMAX_RX_SDU)) {
 			netdev_err(dev, "Wrong cmd_evt(0x%04X)\n",
-				   B2H(hci->cmd_evt));
+				   be16_to_cpu(hci->cmd_evt));
 			break;
 		}
 
-		length = B2H(hci->length);
+		length = be16_to_cpu(hci->length);
 		gdm_wimax_netif_rx(dev, hci->data, length);
 
 		if (length & 0x3) {
@@ -773,8 +666,8 @@ static void gdm_wimax_transmit_pkt(struc
 	if (len == 0)
 		return;
 
-	cmd_evt = B2H(*(u16 *)&buf[0]);
-	cmd_len = B2H(*(u16 *)&buf[2]);
+	cmd_evt = be16_to_cpup((const __be16 *)&buf[0]);
+	cmd_len = be16_to_cpup((const __be16 *)&buf[2]);
 
 	if (len < cmd_len + HCI_HEADER_SIZE) {
 		if (len)
@@ -811,36 +704,6 @@ static void gdm_wimax_transmit_pkt(struc
 	}
 }
 
-static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm)
-{
-	u16 buf[32 / sizeof(u16)];
-	u8 *hci_pkt_buf = (u8 *)&buf[0];
-
-	/* Indicate updating fsm */
-	buf[0] = H2B(WIMAX_FSM_UPDATE);
-	buf[1] = H2B(sizeof(struct fsm_s));
-	memcpy(&hci_pkt_buf[HCI_HEADER_SIZE], fsm, sizeof(struct fsm_s));
-
-	gdm_wimax_event_send(dev, hci_pkt_buf,
-			     HCI_HEADER_SIZE + sizeof(struct fsm_s));
-}
-
-static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up)
-{
-	u16 buf[32 / sizeof(u16)];
-	struct hci_s *hci = (struct hci_s *)buf;
-	unsigned char up_down;
-
-	up_down = if_up ? WIMAX_IF_UP : WIMAX_IF_DOWN;
-
-	/* Indicate updating fsm */
-	hci->cmd_evt = H2B(WIMAX_IF_UPDOWN);
-	hci->length = H2B(sizeof(up_down));
-	hci->data[0] = up_down;
-
-	gdm_wimax_event_send(dev, (char *)hci, HCI_HEADER_SIZE+sizeof(up_down));
-}
-
 static void rx_complete(void *arg, void *data, int len)
 {
 	struct nic *nic = arg;
@@ -875,7 +738,6 @@ static struct net_device_ops gdm_netdev_
 	.ndo_stop		= gdm_wimax_close,
 	.ndo_set_config		= gdm_wimax_set_config,
 	.ndo_start_xmit		= gdm_wimax_tx,
-	.ndo_get_stats		= gdm_wimax_stats,
 	.ndo_set_mac_address	= gdm_wimax_set_mac_addr,
 	.ndo_do_ioctl		= gdm_wimax_ioctl,
 };
@@ -886,7 +748,8 @@ int register_wimax_device(struct phy_dev
 	struct net_device *dev;
 	int ret;
 
-	dev = alloc_netdev(sizeof(*nic), "wm%d", ether_setup);
+	dev = alloc_netdev(sizeof(*nic), "wm%d", NET_NAME_UNKNOWN,
+			   ether_setup);
 
 	if (dev == NULL) {
 		pr_err("alloc_etherdev failed\n");
@@ -900,8 +763,6 @@ int register_wimax_device(struct phy_dev
 	memcpy(dev->dev_addr, gdm_wimax_macaddr, sizeof(gdm_wimax_macaddr));
 
 	nic = netdev_priv(dev);
-	memset(nic, 0, sizeof(*nic));
-
 	nic->netdev = dev;
 	nic->phy_dev = phy_dev;
 	phy_dev->netdev = dev;
@@ -917,12 +778,7 @@ int register_wimax_device(struct phy_dev
 	if (ret)
 		goto cleanup;
 
-	#if defined(LOOPBACK_TEST)
-	netif_start_queue(dev);
-	netif_carrier_on(dev);
-	#else
 	netif_carrier_off(dev);
-	#endif
 
 #ifdef CONFIG_WIMAX_GDM72XX_QOS
 	gdm_qos_init(nic);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_wimax.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_wimax.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/gdm_wimax.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/gdm_wimax.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __GDM_WIMAX_H__
-#define __GDM_WIMAX_H__
+#ifndef __GDM72XX_GDM_WIMAX_H__
+#define __GDM72XX_GDM_WIMAX_H__
 
 #include <linux/netdevice.h>
 #include <linux/types.h>
@@ -23,16 +23,6 @@
 
 #define DRIVER_VERSION		"3.2.3"
 
-#define H2L(x)		__cpu_to_le16(x)
-#define L2H(x)		__le16_to_cpu(x)
-#define DH2L(x)		__cpu_to_le32(x)
-#define DL2H(x)		__le32_to_cpu(x)
-
-#define H2B(x)		__cpu_to_be16(x)
-#define B2H(x)		__be16_to_cpu(x)
-#define DH2B(x)		__cpu_to_be32(x)
-#define DB2H(x)		__be32_to_cpu(x)
-
 struct phy_dev {
 	void			*priv_dev;
 	struct net_device	*netdev;
@@ -46,7 +36,6 @@ struct phy_dev {
 struct nic {
 	struct net_device	*netdev;
 	struct phy_dev		*phy_dev;
-	struct net_device_stats	stats;
 	struct data_s		sdk_data[SIOC_DATA_MAX];
 #if defined(CONFIG_WIMAX_GDM72XX_QOS)
 	struct qos_cb_s		qos;
@@ -57,4 +46,4 @@ int register_wimax_device(struct phy_dev
 int gdm_wimax_send_tx(struct sk_buff *skb, struct net_device *dev);
 void unregister_wimax_device(struct phy_dev *phy_dev);
 
-#endif
+#endif /* __GDM72XX_GDM_WIMAX_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/hci.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/hci.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/hci.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/hci.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef HCI_H_20080801
-#define HCI_H_20080801
+#ifndef __GDM72XX_HCI_H__
+#define __GDM72XX_HCI_H__
 
 #define HCI_HEADER_SIZE		4
 #define HCI_VALUE_OFFS		(HCI_HEADER_SIZE)
@@ -112,13 +112,11 @@
 #define W_SCAN_ALL_SUBSCRIPTION		1
 #define W_SCAN_SPECIFIED_SUBSCRIPTION	2
 
-/*
- * TLV
+/* TLV
  *
  * [31:31] indicates the type is composite.
  * [30:16] is the length of the type. 0 length means length is variable.
  * [15:0] is the actual type.
- *
  */
 #define TLV_L(x)		(((x) >> 16) & 0xff)
 #define TLV_T(x)		((x) & 0xff)
@@ -200,10 +198,16 @@
 #define T_FFTSIZE			(0xda	| (4 << 16))
 #define T_DUPLEX_MODE			(0xdb	| (4 << 16))
 
+/* T_CAPABILITY */
+#define T_CAPABILITY_MULTI_CS		(1 << 0)
+#define T_CAPABILITY_WIMAX		(1 << 1)
+#define T_CAPABILITY_QOS		(1 << 2)
+#define T_CAPABILITY_AGGREGATION	(1 << 3)
+
 struct hci_s {
-	unsigned short cmd_evt;
-	unsigned short length;
-	unsigned char  data[0];
+	__be16	cmd_evt;
+	__be16	length;
+	u8	data[0];
 } __packed;
 
-#endif
+#endif /* __GDM72XX_HCI_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -6,21 +6,29 @@ menuconfig WIMAX_GDM72XX
 	tristate "GCT GDM72xx WiMAX support"
 	depends on NET && (USB || MMC)
 	help
-	  Support for the GCT GDM72xx WiMAX chip
+	  Support a WiMAX module based on the GCT GDM72xx WiMAX chip.
 
 if WIMAX_GDM72XX
 
 config WIMAX_GDM72XX_QOS
 	bool "Enable QoS support"
 	default n
+	help
+	  Enable Quality of Service support based on the data protocol of
+	  transmitting packets.
 
 config WIMAX_GDM72XX_K_MODE
 	bool "Enable K mode"
 	default n
+	help
+	  Enable support for proprietary functions for KT (Korea Telecom).
 
 config WIMAX_GDM72XX_WIMAX2
 	bool "Enable WiMAX2 support"
 	default n
+	help
+	  Enable support for transmitting multiple packets (packet
+	  aggregation) from the WiMAX module to the host processor.
 
 choice
 	prompt "Select interface"
@@ -28,10 +36,16 @@ choice
 config WIMAX_GDM72XX_USB
 	bool "USB interface"
 	depends on (USB = y || USB = WIMAX_GDM72XX)
+	help
+	  Select this option if the WiMAX module interfaces with the host
+	  processor via USB.
 
 config WIMAX_GDM72XX_SDIO
 	bool "SDIO interface"
 	depends on (MMC = y || MMC = WIMAX_GDM72XX)
+	help
+	  Select this option if the WiMAX module interfaces with the host
+	  processor via SDIO.
 
 endchoice
 
@@ -40,6 +54,9 @@ if WIMAX_GDM72XX_USB
 config WIMAX_GDM72XX_USB_PM
 	bool "Enable power management support"
 	depends on PM_RUNTIME
+	help
+	  Enable USB power management in order to reduce power consumption
+	  while the interface is not in use.
 
 endif # WIMAX_GDM72XX_USB
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/netlink_k.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/netlink_k.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/netlink_k.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/netlink_k.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,9 @@
  * GNU General Public License for more details.
  */
 
-#if !defined(NETLINK_H_20081202)
-#define NETLINK_H_20081202
+#ifndef __GDM72XX_NETLINK_K_H__
+#define __GDM72XX_NETLINK_K_H__
+
 #include <linux/netdevice.h>
 #include <net/sock.h>
 
@@ -21,4 +22,4 @@ struct sock *netlink_init(int unit, void
 void netlink_exit(struct sock *sock);
 int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len);
 
-#endif
+#endif /* __GDM72XX_NETLINK_K_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/sdio_boot.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/sdio_boot.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/sdio_boot.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/sdio_boot.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,11 +11,11 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __SDIO_BOOT_H__
-#define __SDIO_BOOT_H__
+#ifndef __GDM72XX_SDIO_BOOT_H__
+#define __GDM72XX_SDIO_BOOT_H__
 
 struct sdio_func;
 
 int sdio_boot(struct sdio_func *func);
 
-#endif /* __SDIO_BOOT_H__ */
+#endif /* __GDM72XX_SDIO_BOOT_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_boot.c linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_boot.c
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_boot.c	2014-08-07 04:58:16.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_boot.c	2014-09-28 21:40:47.000000000 -0400
@@ -36,8 +36,8 @@
 #define FW_FS			"ramdisk.jffs2"
 
 struct dn_header {
-	u32	magic_num;
-	u32	file_size;
+	__be32	magic_num;
+	__be32	file_size;
 };
 
 struct img_header {
@@ -69,7 +69,7 @@ static void array_le32_to_cpu(u32 *arr,
 	int i;
 
 	for (i = 0; i < num; i++, arr++)
-		*arr = __le32_to_cpu(*arr);
+		le32_to_cpus(arr);
 }
 
 static u8 *tx_buf;
@@ -115,8 +115,8 @@ static int download_image(struct usb_dev
 	u32 size;
 
 	size = ALIGN(img_len, DOWNLOAD_SIZE);
-	h.magic_num = __cpu_to_be32(magic_num);
-	h.file_size = __cpu_to_be32(size);
+	h.magic_num = cpu_to_be32(magic_num);
+	h.file_size = cpu_to_be32(size);
 
 	ret = gdm_wibro_send(usbdev, &h, sizeof(h));
 	if (ret < 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_boot.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_boot.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_boot.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_boot.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,12 +11,12 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __USB_BOOT_H__
-#define __USB_BOOT_H__
+#ifndef __GDM72XX_USB_BOOT_H__
+#define __GDM72XX_USB_BOOT_H__
 
 struct usb_device;
 
 int usb_boot(struct usb_device *usbdev, u16 pid);
 int usb_emergency(struct usb_device *usbdev);
 
-#endif /* __USB_BOOT_H__ */
+#endif /* __GDM72XX_USB_BOOT_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_ids.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_ids.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/usb_ids.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/usb_ids.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __USB_IDS_H__
-#define __USB_IDS_H__
+#ifndef __GDM72XX_USB_IDS_H__
+#define __GDM72XX_USB_IDS_H__
 
 /*You can replace vendor-ID as yours.*/
 #define GCT_VID			0x1076
@@ -79,4 +79,4 @@ static const struct usb_device_id id_tab
 	{ }
 };
 
-#endif /* __USB_IDS_H__ */
+#endif /* __GDM72XX_USB_IDS_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/gdm72xx/wm_ioctl.h linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/wm_ioctl.h
--- linux-libre-3.16-gnu/drivers/staging/gdm72xx/wm_ioctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/gdm72xx/wm_ioctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -11,8 +11,9 @@
  * GNU General Public License for more details.
  */
 
-#if !defined(WM_IOCTL_H_20080714)
-#define WM_IOCTL_H_20080714
+#ifndef __GDM72XX_WM_IOCTL_H__
+#define __GDM72XX_WM_IOCTL_H__
+
 #if !defined(__KERNEL__)
 #include <net/if.h>
 #endif
@@ -92,4 +93,4 @@ struct wm_req_s {
 #define ifr_name ifr_ifrn.ifrn_name
 #endif
 
-#endif
+#endif /* __GDM72XX_WM_IOCTL_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/goldfish/goldfish_audio.c linux-libre-3.17-rc7-gnu/drivers/staging/goldfish/goldfish_audio.c
--- linux-libre-3.16-gnu/drivers/staging/goldfish/goldfish_audio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/goldfish/goldfish_audio.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,10 +203,10 @@ static int goldfish_audio_open(struct in
 					     AUDIO_INT_WRITE_BUFFER_2_EMPTY);
 		AUDIO_WRITE(audio_data, AUDIO_INT_ENABLE, AUDIO_INT_MASK);
 		return 0;
-	} else {
-		atomic_dec(&open_count);
-		return -EBUSY;
 	}
+
+	atomic_dec(&open_count);
+	return -EBUSY;
 }
 
 static int goldfish_audio_release(struct inode *ip, struct file *fp)
@@ -223,8 +223,8 @@ static long goldfish_audio_ioctl(struct
 	/* temporary workaround, until we switch to the ALSA API */
 	if (cmd == 315)
 		return -1;
-	else
-		return 0;
+
+	return 0;
 }
 
 static irqreturn_t goldfish_audio_interrupt(int irq, void *dev_id)
@@ -274,11 +274,9 @@ static int goldfish_audio_probe(struct p
 	struct goldfish_audio *data;
 	dma_addr_t buf_addr;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (data == NULL) {
-		ret = -ENOMEM;
-		goto err_data_alloc_failed;
-	}
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
 	spin_lock_init(&data->lock);
 	init_waitqueue_head(&data->wait);
 	platform_set_drvdata(pdev, data);
@@ -286,38 +284,33 @@ static int goldfish_audio_probe(struct p
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "platform_get_resource failed\n");
-		ret = -ENODEV;
-		goto err_no_io_base;
-	}
-	data->reg_base = ioremap(r->start, PAGE_SIZE);
-	if (data->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto err_no_io_base;
+		return -ENODEV;
 	}
+	data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
+	if (data->reg_base == NULL)
+		return -ENOMEM;
 
 	data->irq = platform_get_irq(pdev, 0);
 	if (data->irq < 0) {
 		dev_err(&pdev->dev, "platform_get_irq failed\n");
-		ret = -ENODEV;
-		goto err_no_irq;
+		return -ENODEV;
 	}
-	data->buffer_virt = dma_alloc_coherent(&pdev->dev,
+	data->buffer_virt = dmam_alloc_coherent(&pdev->dev,
 				COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL);
-	if (data->buffer_virt == 0) {
-		ret = -ENOMEM;
+	if (data->buffer_virt == NULL) {
 		dev_err(&pdev->dev, "allocate buffer failed\n");
-		goto err_alloc_write_buffer_failed;
+		return -ENOMEM;
 	}
 	data->buffer_phys = buf_addr;
 	data->write_buffer1 = data->buffer_virt;
 	data->write_buffer2 = data->buffer_virt + WRITE_BUFFER_SIZE;
 	data->read_buffer = data->buffer_virt + 2 * WRITE_BUFFER_SIZE;
 
-	ret = request_irq(data->irq, goldfish_audio_interrupt,
+	ret = devm_request_irq(&pdev->dev, data->irq, goldfish_audio_interrupt,
 					IRQF_SHARED, pdev->name, data);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq failed\n");
-		goto err_request_irq_failed;
+		return ret;
 	}
 
 	ret = misc_register(&goldfish_audio_device);
@@ -325,7 +318,7 @@ static int goldfish_audio_probe(struct p
 		dev_err(&pdev->dev,
 			"misc_register returned %d in goldfish_audio_init\n",
 								ret);
-		goto err_misc_register_failed;
+		return ret;
 	}
 
 	AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_1,
@@ -344,31 +337,11 @@ static int goldfish_audio_probe(struct p
 
 	audio_data = data;
 	return 0;
-
-err_misc_register_failed:
-	free_irq(data->irq, data);
-err_request_irq_failed:
-	dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
-					data->buffer_virt, data->buffer_phys);
-err_alloc_write_buffer_failed:
-err_no_irq:
-	iounmap(data->reg_base);
-err_no_io_base:
-	kfree(data);
-err_data_alloc_failed:
-	return ret;
 }
 
 static int goldfish_audio_remove(struct platform_device *pdev)
 {
-	struct goldfish_audio *data = platform_get_drvdata(pdev);
-
 	misc_deregister(&goldfish_audio_device);
-	free_irq(data->irq, data);
-	dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
-					data->buffer_virt, data->buffer_phys);
-	iounmap(data->reg_base);
-	kfree(data);
 	audio_data = NULL;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16201_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16201_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16201_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16201_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -131,17 +131,17 @@ static int adis16201_write_raw(struct ii
 }
 
 static const struct iio_chan_spec adis16201_channels[] = {
-	ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
-	ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
+  ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
+  ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
-	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12),
 	ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(7)
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16203_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16203_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16203_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16203_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -99,13 +99,14 @@ static int adis16203_read_raw(struct iio
 }
 
 static const struct iio_chan_spec adis16203_channels[] = {
-	ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
-	ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
+	ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12),
+	ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12),
 	ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	/* Fixme: Not what it appears to be - see data sheet */
-	ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
-	ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
+	ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y,
+		0, 0, 14),
+	ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16204_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16204_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16204_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16204_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -136,15 +136,15 @@ static int adis16204_write_raw(struct ii
 }
 
 static const struct iio_chan_spec adis16204_channels[] = {
-	ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12),
-	ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
-	ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
+	ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12),
+	ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
+	ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
 	ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
-		ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14),
+		ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16209_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16209_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16209_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16209_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -130,16 +130,18 @@ static int adis16209_read_raw(struct iio
 }
 
 static const struct iio_chan_spec adis16209_channels[] = {
-	ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
-	ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
+	ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14),
+	ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
-		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
-	ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
-	ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
-	ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
-	ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+	ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 0, 12),
+	ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X,
+		0, 0, 14),
+	ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y,
+		0, 0, 14),
+	ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 0, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(8)
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16240_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16240_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/adis16240_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/adis16240_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -173,15 +173,15 @@ static int adis16240_write_raw(struct ii
 }
 
 static const struct iio_chan_spec adis16240_channels[] = {
-	ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
-	ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
+	ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10),
+	ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10),
 	ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
 	ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
 	ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
-		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
-	ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
+	ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10),
 	IIO_CHAN_SOFT_TIMESTAMP(6)
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/lis3l02dq_ring.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/lis3l02dq_ring.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/lis3l02dq_ring.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/lis3l02dq_ring.c	2014-09-28 17:29:07.000000000 -0400
@@ -31,7 +31,7 @@ irqreturn_t lis3l02dq_data_rdy_trig_poll
 	struct lis3l02dq_state *st = iio_priv(indio_dev);
 
 	if (st->trigger_on) {
-		iio_trigger_poll(st->trig, iio_get_time_ns());
+		iio_trigger_poll(st->trig);
 		return IRQ_HANDLED;
 	} else
 		return IRQ_WAKE_THREAD;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/accel/sca3000_ring.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/sca3000_ring.c
--- linux-libre-3.16-gnu/drivers/staging/iio/accel/sca3000_ring.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/accel/sca3000_ring.c	2014-09-28 17:29:07.000000000 -0400
@@ -141,6 +141,11 @@ static int sca3000_ring_get_bytes_per_da
 	return 6;
 }
 
+static bool sca3000_ring_buf_data_available(struct iio_buffer *r)
+{
+	return r->stufftoread;
+}
+
 static IIO_BUFFER_ENABLE_ATTR;
 static IIO_BUFFER_LENGTH_ATTR;
 
@@ -274,6 +279,7 @@ static const struct iio_buffer_access_fu
 	.read_first_n = &sca3000_read_first_n_hw_rb,
 	.get_length = &sca3000_ring_get_length,
 	.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum,
+	.data_available = sca3000_ring_buf_data_available,
 	.release = sca3000_ring_release,
 };
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7291.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7291.c
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7291.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7291.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,580 +0,0 @@
-/*
- * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor
- *
- * Copyright 2010-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-
-#include "ad7291.h"
-
-/*
- * Simplified handling
- *
- * If no events enabled - single polled channel read
- * If event enabled direct reads disable unless channel
- * is in the read mask.
- *
- * The noise-delayed bit as per datasheet suggestion is always enabled.
- *
- */
-
-/*
- * AD7291 registers definition
- */
-#define AD7291_COMMAND			0x00
-#define AD7291_VOLTAGE			0x01
-#define AD7291_T_SENSE			0x02
-#define AD7291_T_AVERAGE		0x03
-#define AD7291_DATA_HIGH(x)		((x) * 3 + 0x4)
-#define AD7291_DATA_LOW(x)		((x) * 3 + 0x5)
-#define AD7291_HYST(x)			((x) * 3 + 0x6)
-#define AD7291_VOLTAGE_ALERT_STATUS	0x1F
-#define AD7291_T_ALERT_STATUS		0x20
-
-#define AD7291_VOLTAGE_LIMIT_COUNT	8
-
-
-/*
- * AD7291 command
- */
-#define AD7291_AUTOCYCLE		(1 << 0)
-#define AD7291_RESET			(1 << 1)
-#define AD7291_ALERT_CLEAR		(1 << 2)
-#define AD7291_ALERT_POLARITY		(1 << 3)
-#define AD7291_EXT_REF			(1 << 4)
-#define AD7291_NOISE_DELAY		(1 << 5)
-#define AD7291_T_SENSE_MASK		(1 << 7)
-#define AD7291_VOLTAGE_MASK		0xFF00
-#define AD7291_VOLTAGE_OFFSET		0x8
-
-/*
- * AD7291 value masks
- */
-#define AD7291_CHANNEL_MASK		0xF000
-#define AD7291_BITS			12
-#define AD7291_VALUE_MASK		0xFFF
-#define AD7291_T_VALUE_SIGN		0x400
-#define AD7291_T_VALUE_FLOAT_OFFSET	2
-#define AD7291_T_VALUE_FLOAT_MASK	0x2
-
-#define AD7291_BITS			12
-
-struct ad7291_chip_info {
-	struct i2c_client	*client;
-	struct regulator	*reg;
-	u16			command;
-	u16			c_mask;	/* Active voltage channels for events */
-	struct mutex		state_lock;
-};
-
-static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
-{
-	struct i2c_client *client = chip->client;
-	int ret = 0;
-
-	ret = i2c_smbus_read_word_swapped(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = ret;
-
-	return 0;
-}
-
-static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
-{
-	return i2c_smbus_write_word_swapped(chip->client, reg, data);
-}
-
-static irqreturn_t ad7291_event_handler(int irq, void *private)
-{
-	struct iio_dev *indio_dev = private;
-	struct ad7291_chip_info *chip = iio_priv(private);
-	u16 t_status, v_status;
-	u16 command;
-	int i;
-	s64 timestamp = iio_get_time_ns();
-
-	if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
-		return IRQ_HANDLED;
-
-	if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
-		return IRQ_HANDLED;
-
-	if (!(t_status || v_status))
-		return IRQ_HANDLED;
-
-	command = chip->command | AD7291_ALERT_CLEAR;
-	ad7291_i2c_write(chip, AD7291_COMMAND, command);
-
-	command = chip->command & ~AD7291_ALERT_CLEAR;
-	ad7291_i2c_write(chip, AD7291_COMMAND, command);
-
-	/* For now treat t_sense and t_sense_average the same */
-	if ((t_status & (1 << 0)) || (t_status & (1 << 2)))
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP,
-						    0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_FALLING),
-			       timestamp);
-	if ((t_status & (1 << 1)) || (t_status & (1 << 3)))
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP,
-						    0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_RISING),
-			       timestamp);
-
-	for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
-		if (v_status & (1 << i))
-			iio_push_event(indio_dev,
-				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-							    i/2,
-							    IIO_EV_TYPE_THRESH,
-							    IIO_EV_DIR_FALLING),
-				       timestamp);
-		if (v_status & (1 << (i + 1)))
-			iio_push_event(indio_dev,
-				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-							    i/2,
-							    IIO_EV_TYPE_THRESH,
-							    IIO_EV_DIR_RISING),
-				       timestamp);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
-	enum iio_event_direction dir, enum iio_event_info info)
-{
-	unsigned int offset;
-
-	switch (chan->type) {
-	case IIO_VOLTAGE:
-		offset = chan->channel;
-		break;
-	case IIO_TEMP:
-		offset = 8;
-		break;
-	default:
-	    return 0;
-	}
-
-	switch (info) {
-	case IIO_EV_INFO_VALUE:
-			if (dir == IIO_EV_DIR_FALLING)
-					return AD7291_DATA_HIGH(offset);
-			else
-					return AD7291_DATA_LOW(offset);
-	case IIO_EV_INFO_HYSTERESIS:
-			return AD7291_HYST(offset);
-	default:
-			break;
-	}
-	return 0;
-}
-
-static int ad7291_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)
-{
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-	int ret;
-	u16 uval;
-
-	ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
-		&uval);
-	if (ret < 0)
-		return ret;
-
-	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
-		*val = uval & AD7291_VALUE_MASK;
-
-	else
-		*val = sign_extend32(uval, 11);
-
-	return IIO_VAL_INT;
-}
-
-static int ad7291_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 ad7291_chip_info *chip = iio_priv(indio_dev);
-
-	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
-		if (val > AD7291_VALUE_MASK || val < 0)
-			return -EINVAL;
-	} else {
-		if (val > 2047 || val < -2048)
-			return -EINVAL;
-	}
-
-	return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
-		val);
-}
-
-static int ad7291_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 ad7291_chip_info *chip = iio_priv(indio_dev);
-	/* To be enabled the channel must simply be on. If any are enabled
-	   we are in continuous sampling mode */
-
-	switch (chan->type) {
-	case IIO_VOLTAGE:
-		if (chip->c_mask & (1 << (15 - chan->channel)))
-			return 1;
-		else
-			return 0;
-	case IIO_TEMP:
-		/* always on */
-		return 1;
-	default:
-		return -EINVAL;
-	}
-
-}
-
-static int ad7291_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)
-{
-	int ret = 0;
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-	unsigned int mask;
-	u16 regval;
-
-	mutex_lock(&chip->state_lock);
-	regval = chip->command;
-	/*
-	 * To be enabled the channel must simply be on. If any are enabled
-	 * use continuous sampling mode.
-	 * Possible to disable temp as well but that makes single read tricky.
-	 */
-
-	mask = BIT(15 - chan->channel);
-
-	switch (chan->type) {
-	case IIO_VOLTAGE:
-		if ((!state) && (chip->c_mask & mask))
-			chip->c_mask &= ~mask;
-		else if (state && (!(chip->c_mask & mask)))
-			chip->c_mask |= mask;
-		else
-			break;
-
-		regval &= ~AD7291_AUTOCYCLE;
-		regval |= chip->c_mask;
-		if (chip->c_mask) /* Enable autocycle? */
-			regval |= AD7291_AUTOCYCLE;
-
-		ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
-		if (ret < 0)
-			goto error_ret;
-
-		chip->command = regval;
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-error_ret:
-	mutex_unlock(&chip->state_lock);
-	return ret;
-}
-
-static int ad7291_read_raw(struct iio_dev *indio_dev,
-			   struct iio_chan_spec const *chan,
-			   int *val,
-			   int *val2,
-			   long mask)
-{
-	int ret;
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-	u16 regval;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		switch (chan->type) {
-		case IIO_VOLTAGE:
-			mutex_lock(&chip->state_lock);
-			/* If in autocycle mode drop through */
-			if (chip->command & AD7291_AUTOCYCLE) {
-				mutex_unlock(&chip->state_lock);
-				return -EBUSY;
-			}
-			/* Enable this channel alone */
-			regval = chip->command & (~AD7291_VOLTAGE_MASK);
-			regval |= 1 << (15 - chan->channel);
-			ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
-			if (ret < 0) {
-				mutex_unlock(&chip->state_lock);
-				return ret;
-			}
-			/* Read voltage */
-			ret = i2c_smbus_read_word_swapped(chip->client,
-						       AD7291_VOLTAGE);
-			if (ret < 0) {
-				mutex_unlock(&chip->state_lock);
-				return ret;
-			}
-			*val = ret & AD7291_VALUE_MASK;
-			mutex_unlock(&chip->state_lock);
-			return IIO_VAL_INT;
-		case IIO_TEMP:
-			/* Assumes tsense bit of command register always set */
-			ret = i2c_smbus_read_word_swapped(chip->client,
-						       AD7291_T_SENSE);
-			if (ret < 0)
-				return ret;
-			*val = sign_extend32(ret, 11);
-			return IIO_VAL_INT;
-		default:
-			return -EINVAL;
-		}
-	case IIO_CHAN_INFO_AVERAGE_RAW:
-		ret = i2c_smbus_read_word_swapped(chip->client,
-					       AD7291_T_AVERAGE);
-			if (ret < 0)
-				return ret;
-			*val = sign_extend32(ret, 11);
-			return IIO_VAL_INT;
-	case IIO_CHAN_INFO_SCALE:
-		switch (chan->type) {
-		case IIO_VOLTAGE:
-			if (chip->reg) {
-				int vref;
-				vref = regulator_get_voltage(chip->reg);
-				if (vref < 0)
-					return vref;
-				*val = vref / 1000;
-			} else {
-				*val = 2500;
-			}
-			*val2 = AD7291_BITS;
-			return IIO_VAL_FRACTIONAL_LOG2;
-		case IIO_TEMP:
-			/*
-			 * One LSB of the ADC corresponds to 0.25 deg C.
-			 * The temperature reading is in 12-bit twos
-			 * complement format
-			 */
-			*val = 250;
-			return IIO_VAL_INT;
-		default:
-			return -EINVAL;
-		}
-	default:
-		return -EINVAL;
-	}
-}
-
-static const struct iio_event_spec ad7291_events[] = {
-	{
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_RISING,
-		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
-			BIT(IIO_EV_INFO_ENABLE),
-	}, {
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_FALLING,
-		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
-			BIT(IIO_EV_INFO_ENABLE),
-	}, {
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_EITHER,
-		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
-	},
-};
-
-#define AD7291_VOLTAGE_CHAN(_chan)					\
-{									\
-	.type = IIO_VOLTAGE,						\
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
-	.indexed = 1,							\
-	.channel = _chan,						\
-	.event_spec = ad7291_events,					\
-	.num_event_specs = ARRAY_SIZE(ad7291_events),			\
-}
-
-static const struct iio_chan_spec ad7291_channels[] = {
-	AD7291_VOLTAGE_CHAN(0),
-	AD7291_VOLTAGE_CHAN(1),
-	AD7291_VOLTAGE_CHAN(2),
-	AD7291_VOLTAGE_CHAN(3),
-	AD7291_VOLTAGE_CHAN(4),
-	AD7291_VOLTAGE_CHAN(5),
-	AD7291_VOLTAGE_CHAN(6),
-	AD7291_VOLTAGE_CHAN(7),
-	{
-		.type = IIO_TEMP,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-				BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
-				BIT(IIO_CHAN_INFO_SCALE),
-		.indexed = 1,
-		.channel = 0,
-		.event_spec = ad7291_events,
-		.num_event_specs = ARRAY_SIZE(ad7291_events),
-	}
-};
-
-static const struct iio_info ad7291_info = {
-	.read_raw = &ad7291_read_raw,
-	.read_event_config = &ad7291_read_event_config,
-	.write_event_config = &ad7291_write_event_config,
-	.read_event_value = &ad7291_read_event_value,
-	.write_event_value = &ad7291_write_event_value,
-	.driver_module = THIS_MODULE,
-};
-
-static int ad7291_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct ad7291_platform_data *pdata = client->dev.platform_data;
-	struct ad7291_chip_info *chip;
-	struct iio_dev *indio_dev;
-	int ret;
-
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
-	if (!indio_dev)
-		return -ENOMEM;
-	chip = iio_priv(indio_dev);
-
-	if (pdata && pdata->use_external_ref) {
-		chip->reg = devm_regulator_get(&client->dev, "vref");
-		if (IS_ERR(chip->reg))
-			return PTR_ERR(chip->reg);
-
-		ret = regulator_enable(chip->reg);
-		if (ret)
-			return ret;
-	}
-
-	mutex_init(&chip->state_lock);
-	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, indio_dev);
-
-	chip->client = client;
-
-	chip->command = AD7291_NOISE_DELAY |
-			AD7291_T_SENSE_MASK | /* Tsense always enabled */
-			AD7291_ALERT_POLARITY; /* set irq polarity low level */
-
-	if (pdata && pdata->use_external_ref)
-		chip->command |= AD7291_EXT_REF;
-
-	indio_dev->name = id->name;
-	indio_dev->channels = ad7291_channels;
-	indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
-
-	indio_dev->dev.parent = &client->dev;
-	indio_dev->info = &ad7291_info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET);
-	if (ret) {
-		ret = -EIO;
-		goto error_disable_reg;
-	}
-
-	ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
-	if (ret) {
-		ret = -EIO;
-		goto error_disable_reg;
-	}
-
-	if (client->irq > 0) {
-		ret = request_threaded_irq(client->irq,
-					   NULL,
-					   &ad7291_event_handler,
-					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					   id->name,
-					   indio_dev);
-		if (ret)
-			goto error_disable_reg;
-	}
-
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_unreg_irq;
-
-	return 0;
-
-error_unreg_irq:
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
-error_disable_reg:
-	if (chip->reg)
-		regulator_disable(chip->reg);
-
-	return ret;
-}
-
-static int ad7291_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
-
-	if (chip->reg)
-		regulator_disable(chip->reg);
-
-	return 0;
-}
-
-static const struct i2c_device_id ad7291_id[] = {
-	{ "ad7291", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, ad7291_id);
-
-static struct i2c_driver ad7291_driver = {
-	.driver = {
-		.name = KBUILD_MODNAME,
-	},
-	.probe = ad7291_probe,
-	.remove = ad7291_remove,
-	.id_table = ad7291_id,
-};
-module_i2c_driver(ad7291_driver);
-
-MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7291.h linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7291.h
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7291.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7291.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-#ifndef __IIO_AD7291_H__
-#define __IIO_AD7291_H__
-
-/**
- * struct ad7291_platform_data - AD7291 platform data
- * @use_external_ref: Whether to use an external or internal reference voltage
- */
-struct ad7291_platform_data {
-	bool use_external_ref;
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7606_par.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7606_par.c
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/ad7606_par.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/ad7606_par.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,7 +53,7 @@ static int ad7606_par_probe(struct platf
 	struct iio_dev *indio_dev;
 	void __iomem *addr;
 	resource_size_t remap_size;
-	int ret, irq;
+	int irq;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -62,56 +62,31 @@ static int ad7606_par_probe(struct platf
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+	addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(addr))
+		return PTR_ERR(addr);
 
 	remap_size = resource_size(res);
 
-	/* Request the regions */
-	if (!request_mem_region(res->start, remap_size, "iio-ad7606")) {
-		ret = -EBUSY;
-		goto out1;
-	}
-	addr = ioremap(res->start, remap_size);
-	if (!addr) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
 	indio_dev = ad7606_probe(&pdev->dev, irq, addr,
 			  platform_get_device_id(pdev)->driver_data,
 			  remap_size > 1 ? &ad7606_par16_bops :
 			  &ad7606_par8_bops);
 
-	if (IS_ERR(indio_dev))  {
-		ret = PTR_ERR(indio_dev);
-		goto out2;
-	}
+	if (IS_ERR(indio_dev))
+		return PTR_ERR(indio_dev);
 
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
-
-out2:
-	iounmap(addr);
-out1:
-	release_mem_region(res->start, remap_size);
-
-	return ret;
 }
 
 static int ad7606_par_remove(struct platform_device *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
-	struct resource *res;
-	struct ad7606_state *st = iio_priv(indio_dev);
 
 	ad7606_remove(indio_dev, platform_get_irq(pdev, 0));
 
-	iounmap(st->base_address);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -3,13 +3,6 @@
 #
 menu "Analog to digital converters"
 
-config AD7291
-	tristate "Analog Devices AD7291 ADC driver"
-	depends on I2C
-	help
-	  Say yes here to build support for Analog Devices AD7291
-	  8 Channel ADC with temperature sensor.
-
 config AD7606
 	tristate "Analog Devices AD7606 ADC driver"
 	depends on GPIOLIB
@@ -94,7 +87,7 @@ config LPC32XX_ADC
 
 config MXS_LRADC
 	tristate "Freescale i.MX23/i.MX28 LRADC"
-	depends on ARCH_MXS || COMPILE_TEST
+	depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
 	depends on INPUT
 	select STMP_DEVICE
 	select IIO_BUFFER
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) +
 ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
 obj-$(CONFIG_AD7606) += ad7606.o
 
-obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_AD7192) += ad7192.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/adc/mxs-lradc.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/mxs-lradc.c
--- linux-libre-3.16-gnu/drivers/staging/iio/adc/mxs-lradc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/adc/mxs-lradc.c	2014-09-28 17:29:07.000000000 -0400
@@ -1170,7 +1170,7 @@ static irqreturn_t mxs_lradc_handle_irq(
 		mxs_lradc_handle_touch(lradc);
 
 	if (iio_buffer_enabled(iio))
-		iio_trigger_poll(iio->trig, iio_get_time_ns());
+		iio_trigger_poll(iio->trig);
 	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
 		complete(&lradc->completion);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/Documentation/generic_buffer.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/generic_buffer.c
--- linux-libre-3.16-gnu/drivers/staging/iio/Documentation/generic_buffer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/generic_buffer.c	2014-09-28 17:29:07.000000000 -0400
@@ -305,9 +305,12 @@ int main(int argc, char **argv)
 		read_size = read(fp,
 				 data,
 				 toread*scan_size);
-		if (read_size == -EAGAIN) {
-			printf("nothing available\n");
-			continue;
+		if (read_size < 0) {
+			if (errno == -EAGAIN) {
+				printf("nothing available\n");
+				continue;
+			} else
+				break;
 		}
 		for (i = 0; i < read_size/scan_size; i++)
 			process_scan(data + scan_size*i,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/Documentation/iio_event_monitor.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/iio_event_monitor.c
--- linux-libre-3.16-gnu/drivers/staging/iio/Documentation/iio_event_monitor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/iio_event_monitor.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,6 +46,9 @@ static const char * const iio_chan_type_
 	[IIO_TIMESTAMP] = "timestamp",
 	[IIO_CAPACITANCE] = "capacitance",
 	[IIO_ALTVOLTAGE] = "altvoltage",
+	[IIO_CCT] = "cct",
+	[IIO_PRESSURE] = "pressure",
+	[IIO_HUMIDITYRELATIVE] = "humidityrelative",
 };
 
 static const char * const iio_ev_type_text[] = {
@@ -70,6 +73,8 @@ static const char * const iio_modifier_n
 	[IIO_MOD_LIGHT_IR] = "ir",
 	[IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
 	[IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
+	[IIO_MOD_LIGHT_BOTH] = "both",
+	[IIO_MOD_LIGHT_IR] = "ir",
 	[IIO_MOD_LIGHT_CLEAR] = "clear",
 	[IIO_MOD_LIGHT_RED] = "red",
 	[IIO_MOD_LIGHT_GREEN] = "green",
@@ -100,6 +105,9 @@ static bool event_is_known(struct iio_ev
 	case IIO_TIMESTAMP:
 	case IIO_CAPACITANCE:
 	case IIO_ALTVOLTAGE:
+	case IIO_CCT:
+	case IIO_PRESSURE:
+	case IIO_HUMIDITYRELATIVE:
 		break;
 	default:
 		return false;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/Documentation/iio_utils.h linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/iio_utils.h
--- linux-libre-3.16-gnu/drivers/staging/iio/Documentation/iio_utils.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/iio_utils.h	2014-09-28 17:29:07.000000000 -0400
@@ -633,7 +633,7 @@ error_free:
 
 int read_sysfs_float(char *filename, char *basedir, float *val)
 {
-	float ret = 0;
+	int ret = 0;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	if (temp == NULL) {
@@ -653,9 +653,9 @@ error_free:
 	return ret;
 }
 
-read_sysfs_string(const char *filename, const char *basedir, char *str)
+int read_sysfs_string(const char *filename, const char *basedir, char *str)
 {
-	float ret = 0;
+	int ret = 0;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	if (temp == NULL) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs
--- linux-libre-3.16-gnu/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-What:		/sys/bus/iio/devices/triggerX/trigger_now
-KernelVersion:	2.6.38
-Contact:	linux-iio@vger.kernel.org
-Description:
-		This file is provided by the iio-trig-sysfs stand-alone trigger
-		driver. Writing this file with any value triggers an event
-		driven driver, associated with this trigger, to capture data
-		into an in kernel buffer. This approach can be valuable during
-		automated testing or in situations, where other trigger methods
-		are not applicable. For example no RTC or spare GPIOs.
-		X is the IIO index of the trigger.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/Documentation/trigger.txt linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/trigger.txt
--- linux-libre-3.16-gnu/drivers/staging/iio/Documentation/trigger.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/Documentation/trigger.txt	2014-09-28 17:29:07.000000000 -0400
@@ -31,5 +31,5 @@ consumers.
 Trigger Consumers
 
 Currently triggers are only used for the filling of software
-buffers and as such any device supporting INDIO_RING_TRIGGERED has the
+buffers and as such any device supporting INDIO_BUFFER_TRIGGERED has the
 consumer interface automatically created.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/frequency/ad9832.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/frequency/ad9832.c
--- linux-libre-3.16-gnu/drivers/staging/iio/frequency/ad9832.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/frequency/ad9832.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,7 +57,7 @@ static int ad9832_write_frequency(struct
 }
 
 static int ad9832_write_phase(struct ad9832_state *st,
-				  unsigned long addr, unsigned long phase)
+			      unsigned long addr, unsigned long phase)
 {
 	if (phase > (1 << AD9832_PHASE_BITS))
 		return -EINVAL;
@@ -72,10 +72,8 @@ static int ad9832_write_phase(struct ad9
 	return spi_sync(st->spi, &st->phase_msg);
 }
 
-static ssize_t ad9832_write(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
+static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad9832_state *st = iio_priv(indio_dev);
@@ -109,11 +107,11 @@ static ssize_t ad9832_write(struct devic
 		ret = spi_sync(st->spi, &st->msg);
 		break;
 	case AD9832_FREQ_SYM:
-		if (val == 1)
+		if (val == 1) {
 			st->ctrl_fp |= AD9832_FREQ;
-		else if (val == 0)
+		} else if (val == 0) {
 			st->ctrl_fp &= ~AD9832_FREQ;
-		else {
+		} else {
 			ret = -EINVAL;
 			break;
 		}
@@ -122,7 +120,7 @@ static ssize_t ad9832_write(struct devic
 		ret = spi_sync(st->spi, &st->msg);
 		break;
 	case AD9832_PHASE_SYM:
-		if (val < 0 || val > 3) {
+		if (val > 3) {
 			ret = -EINVAL;
 			break;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/frequency/ad9850.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/frequency/ad9850.c
--- linux-libre-3.16-gnu/drivers/staging/iio/frequency/ad9850.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/frequency/ad9850.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,9 +21,6 @@
 
 #define DRV_NAME "ad9850"
 
-#define value_mask (u16)0xf000
-#define addr_shift 12
-
 /* Register format: 4 bits addr + 12 bits value */
 struct ad9850_config {
 	u8 control[5];
@@ -50,9 +47,6 @@ static ssize_t ad9850_set_parameter(stru
 	mutex_lock(&st->lock);
 
 	ret = spi_sync_transfer(st->sdev, &xfer, 1);
-	if (ret)
-		goto error_ret;
-error_ret:
 	mutex_unlock(&st->lock);
 
 	return ret ? ret : len;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/iio_simple_dummy.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/iio_simple_dummy.c
--- linux-libre-3.16-gnu/drivers/staging/iio/iio_simple_dummy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/iio_simple_dummy.c	2014-09-28 17:29:07.000000000 -0400
@@ -550,6 +550,7 @@ error_ret:
 static __init int iio_dummy_init(void)
 {
 	int i, ret;
+
 	if (instances > 10) {
 		instances = 1;
 		return -EINVAL;
@@ -577,6 +578,7 @@ module_init(iio_dummy_init);
 static __exit void iio_dummy_exit(void)
 {
 	int i;
+
 	for (i = 0; i < instances; i++)
 		iio_dummy_remove(i);
 	kfree(iio_dummy_devs);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843.c
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,652 +0,0 @@
-/*  Copyright (C) 2010 Texas Instruments
-    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
-    Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
-
-    Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/triggered_buffer.h>
-#include <linux/delay.h>
-
-#define HMC5843_CONFIG_REG_A			0x00
-#define HMC5843_CONFIG_REG_B			0x01
-#define HMC5843_MODE_REG			0x02
-#define HMC5843_DATA_OUT_MSB_REGS		0x03
-#define HMC5843_STATUS_REG			0x09
-#define HMC5843_ID_REG				0x0a
-
-enum hmc5843_ids {
-	HMC5843_ID,
-	HMC5883_ID,
-	HMC5883L_ID,
-};
-
-/*
- * Range gain settings in (+-)Ga
- * Beware: HMC5843 and HMC5883 have different recommended sensor field
- * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
- */
-#define HMC5843_RANGE_GAIN_OFFSET		0x05
-#define HMC5843_RANGE_GAIN_DEFAULT		0x01
-#define HMC5843_RANGE_GAINS			8
-
-/* Device status */
-#define HMC5843_DATA_READY			0x01
-#define HMC5843_DATA_OUTPUT_LOCK		0x02
-
-/* Mode register configuration */
-#define HMC5843_MODE_CONVERSION_CONTINUOUS	0x00
-#define HMC5843_MODE_CONVERSION_SINGLE		0x01
-#define HMC5843_MODE_IDLE			0x02
-#define HMC5843_MODE_SLEEP			0x03
-#define HMC5843_MODE_MASK			0x03
-
-/*
- * HMC5843: Minimum data output rate
- * HMC5883: Typical data output rate
- */
-#define HMC5843_RATE_OFFSET			0x02
-#define HMC5843_RATE_DEFAULT			0x04
-#define HMC5843_RATES				7
-
-/* Device measurement configuration */
-#define HMC5843_MEAS_CONF_NORMAL		0x00
-#define HMC5843_MEAS_CONF_POSITIVE_BIAS		0x01
-#define HMC5843_MEAS_CONF_NEGATIVE_BIAS		0x02
-#define HMC5843_MEAS_CONF_MASK			0x03
-
-/* Scaling factors: 10000000/Gain */
-static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
-};
-
-static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
-};
-
-static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
-};
-
-/*
- * From the datasheet:
- * Value	| HMC5843		| HMC5883/HMC5883L
- *		| Data output rate (Hz)	| Data output rate (Hz)
- * 0		| 0.5			| 0.75
- * 1		| 1			| 1.5
- * 2		| 2			| 3
- * 3		| 5			| 7.5
- * 4		| 10 (default)		| 15
- * 5		| 20			| 30
- * 6		| 50			| 75
- * 7		| Not used		| Not used
- */
-static const int hmc5843_regval_to_samp_freq[7][2] = {
-	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
-};
-
-static const int hmc5883_regval_to_samp_freq[7][2] = {
-	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
-	{75, 0}
-};
-
-/* Describe chip variants */
-struct hmc5843_chip_info {
-	const struct iio_chan_spec *channels;
-	const int (*regval_to_samp_freq)[2];
-	const int *regval_to_nanoscale;
-};
-
-/* Each client has this additional data */
-struct hmc5843_data {
-	struct i2c_client *client;
-	struct mutex lock;
-	u8 rate;
-	u8 meas_conf;
-	u8 operating_mode;
-	u8 range;
-	const struct hmc5843_chip_info *variant;
-	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
-};
-
-/* The lower two bits contain the current conversion mode */
-static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_MODE_REG,
-					operating_mode & HMC5843_MODE_MASK);
-	if (ret >= 0)
-		data->operating_mode = operating_mode;
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static int hmc5843_wait_measurement(struct hmc5843_data *data)
-{
-	s32 result;
-	int tries = 150;
-
-	while (tries-- > 0) {
-		result = i2c_smbus_read_byte_data(data->client,
-			HMC5843_STATUS_REG);
-		if (result < 0)
-			return result;
-		if (result & HMC5843_DATA_READY)
-			break;
-		msleep(20);
-	}
-
-	if (tries < 0) {
-		dev_err(&data->client->dev, "data not ready\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/* Return the measurement value from the specified channel */
-static int hmc5843_read_measurement(struct hmc5843_data *data,
-				    int idx, int *val)
-{
-	s32 result;
-	__be16 values[3];
-
-	mutex_lock(&data->lock);
-	result = hmc5843_wait_measurement(data);
-	if (result < 0) {
-		mutex_unlock(&data->lock);
-		return result;
-	}
-	result = i2c_smbus_read_i2c_block_data(data->client,
-		HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values);
-	mutex_unlock(&data->lock);
-	if (result < 0)
-		return -EINVAL;
-
-	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
-	return IIO_VAL_INT;
-}
-
-/*
- * API for setting the measurement configuration to
- * Normal, Positive bias and Negative bias
- *
- * From the datasheet:
- * 0 - Normal measurement configuration (default): In normal measurement
- *     configuration the device follows normal measurement flow. Pins BP
- *     and BN are left floating and high impedance.
- *
- * 1 - Positive bias configuration: In positive bias configuration, a
- *     positive current is forced across the resistive load on pins BP
- *     and BN.
- *
- * 2 - Negative bias configuration. In negative bias configuration, a
- *     negative current is forced across the resistive load on pins BP
- *     and BN.
- *
- */
-static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
-		(meas_conf & HMC5843_MEAS_CONF_MASK) |
-		(data->rate << HMC5843_RATE_OFFSET));
-	if (ret >= 0)
-		data->meas_conf = meas_conf;
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
-						struct device_attribute *attr,
-						char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	return sprintf(buf, "%d\n", data->meas_conf);
-}
-
-static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
-						struct device_attribute *attr,
-						const char *buf,
-						size_t count)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	unsigned long meas_conf = 0;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &meas_conf);
-	if (ret)
-		return ret;
-	if (meas_conf >= HMC5843_MEAS_CONF_MASK)
-		return -EINVAL;
-
-	ret = hmc5843_set_meas_conf(data, meas_conf);
-
-	return (ret < 0) ? ret : count;
-}
-
-static IIO_DEVICE_ATTR(meas_conf,
-			S_IWUSR | S_IRUGO,
-			hmc5843_show_measurement_configuration,
-			hmc5843_set_measurement_configuration,
-			0);
-
-static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	size_t len = 0;
-	int i;
-
-	for (i = 0; i < HMC5843_RATES; i++)
-		len += scnprintf(buf + len, PAGE_SIZE - len,
-			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
-			data->variant->regval_to_samp_freq[i][1]);
-
-	/* replace trailing space by newline */
-	buf[len - 1] = '\n';
-
-	return len;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
-
-static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
-		data->meas_conf | (rate << HMC5843_RATE_OFFSET));
-	if (ret >= 0)
-		data->rate = rate;
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
-				   int val, int val2)
-{
-	int i;
-
-	for (i = 0; i < HMC5843_RATES; i++)
-		if (val == data->variant->regval_to_samp_freq[i][0] &&
-			val2 == data->variant->regval_to_samp_freq[i][1])
-			return i;
-
-	return -EINVAL;
-}
-
-static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B,
-		range << HMC5843_RANGE_GAIN_OFFSET);
-	if (ret >= 0)
-		data->range = range;
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static ssize_t hmc5843_show_scale_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-
-	size_t len = 0;
-	int i;
-
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
-		len += scnprintf(buf + len, PAGE_SIZE - len,
-			"0.%09d ", data->variant->regval_to_nanoscale[i]);
-
-	/* replace trailing space by newline */
-	buf[len - 1] = '\n';
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(scale_available, S_IRUGO,
-	hmc5843_show_scale_avail, NULL, 0);
-
-static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
-{
-	int i;
-
-	if (val != 0)
-		return -EINVAL;
-
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
-		if (val2 == data->variant->regval_to_nanoscale[i])
-			return i;
-
-	return -EINVAL;
-}
-
-static int hmc5843_read_raw(struct iio_dev *indio_dev,
-			    struct iio_chan_spec const *chan,
-			    int *val, int *val2, long mask)
-{
-	struct hmc5843_data *data = iio_priv(indio_dev);
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		return hmc5843_read_measurement(data, chan->scan_index, val);
-	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = data->variant->regval_to_nanoscale[data->range];
-		return IIO_VAL_INT_PLUS_NANO;
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		*val = data->variant->regval_to_samp_freq[data->rate][0];
-		*val2 = data->variant->regval_to_samp_freq[data->rate][1];
-		return IIO_VAL_INT_PLUS_MICRO;
-	}
-	return -EINVAL;
-}
-
-static int hmc5843_write_raw(struct iio_dev *indio_dev,
-			     struct iio_chan_spec const *chan,
-			     int val, int val2, long mask)
-{
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int rate, range;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		rate = hmc5843_get_samp_freq_index(data, val, val2);
-		if (rate < 0)
-			return -EINVAL;
-
-		return hmc5843_set_samp_freq(data, rate);
-	case IIO_CHAN_INFO_SCALE:
-		range = hmc5843_get_scale_index(data, val, val2);
-		if (range < 0)
-			return -EINVAL;
-
-		return hmc5843_set_range_gain(data, range);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
-			       struct iio_chan_spec const *chan, long mask)
-{
-	switch (mask) {
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		return IIO_VAL_INT_PLUS_MICRO;
-	case IIO_CHAN_INFO_SCALE:
-		return IIO_VAL_INT_PLUS_NANO;
-	default:
-		return -EINVAL;
-	}
-}
-
-static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = hmc5843_wait_measurement(data);
-	if (ret < 0) {
-		mutex_unlock(&data->lock);
-		goto done;
-	}
-
-	ret = i2c_smbus_read_i2c_block_data(data->client,
-		HMC5843_DATA_OUT_MSB_REGS, 3 * sizeof(__be16),
-			(u8 *) data->buffer);
-	mutex_unlock(&data->lock);
-	if (ret < 0)
-		goto done;
-
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
-		iio_get_time_ns());
-
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-#define HMC5843_CHANNEL(axis, idx)					\
-	{								\
-		.type = IIO_MAGN,					\
-		.modified = 1,						\
-		.channel2 = IIO_MOD_##axis,				\
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
-			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
-		.scan_index = idx,					\
-		.scan_type = {						\
-			.sign = 's',					\
-			.realbits = 16,					\
-			.storagebits = 16,				\
-			.endianness = IIO_BE,				\
-		},							\
-	}
-
-static const struct iio_chan_spec hmc5843_channels[] = {
-	HMC5843_CHANNEL(X, 0),
-	HMC5843_CHANNEL(Y, 1),
-	HMC5843_CHANNEL(Z, 2),
-	IIO_CHAN_SOFT_TIMESTAMP(3),
-};
-
-/* Beware: Y and Z are exchanged on HMC5883 */
-static const struct iio_chan_spec hmc5883_channels[] = {
-	HMC5843_CHANNEL(X, 0),
-	HMC5843_CHANNEL(Z, 1),
-	HMC5843_CHANNEL(Y, 2),
-	IIO_CHAN_SOFT_TIMESTAMP(3),
-};
-
-static struct attribute *hmc5843_attributes[] = {
-	&iio_dev_attr_meas_conf.dev_attr.attr,
-	&iio_dev_attr_scale_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group hmc5843_group = {
-	.attrs = hmc5843_attributes,
-};
-
-static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
-	[HMC5843_ID] = {
-		.channels = hmc5843_channels,
-		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
-	},
-	[HMC5883_ID] = {
-		.channels = hmc5883_channels,
-		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
-	},
-	[HMC5883L_ID] = {
-		.channels = hmc5883_channels,
-		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
-	},
-};
-
-static int hmc5843_init(struct hmc5843_data *data)
-{
-	int ret;
-	u8 id[3];
-
-	ret = i2c_smbus_read_i2c_block_data(data->client, HMC5843_ID_REG,
-		sizeof(id), id);
-	if (ret < 0)
-		return ret;
-	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
-		dev_err(&data->client->dev, "no HMC5843/5883/5883L sensor\n");
-		return -ENODEV;
-	}
-
-	ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
-	if (ret < 0)
-		return ret;
-	ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT);
-	if (ret < 0)
-		return ret;
-	ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT);
-	if (ret < 0)
-		return ret;
-	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
-}
-
-static const struct iio_info hmc5843_info = {
-	.attrs = &hmc5843_group,
-	.read_raw = &hmc5843_read_raw,
-	.write_raw = &hmc5843_write_raw,
-	.write_raw_get_fmt = &hmc5843_write_raw_get_fmt,
-	.driver_module = THIS_MODULE,
-};
-
-static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
-
-static int hmc5843_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct hmc5843_data *data;
-	struct iio_dev *indio_dev;
-	int ret;
-
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
-	if (indio_dev == NULL)
-		return -ENOMEM;
-
-	/* default settings at probe */
-	data = iio_priv(indio_dev);
-	data->client = client;
-	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
-	mutex_init(&data->lock);
-
-	i2c_set_clientdata(client, indio_dev);
-	indio_dev->info = &hmc5843_info;
-	indio_dev->name = id->name;
-	indio_dev->dev.parent = &client->dev;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = data->variant->channels;
-	indio_dev->num_channels = 4;
-	indio_dev->available_scan_masks = hmc5843_scan_masks;
-
-	ret = hmc5843_init(data);
-	if (ret < 0)
-		return ret;
-
-	ret = iio_triggered_buffer_setup(indio_dev, NULL,
-		hmc5843_trigger_handler, NULL);
-	if (ret < 0)
-		return ret;
-
-	ret = iio_device_register(indio_dev);
-	if (ret < 0)
-		goto buffer_cleanup;
-
-	return 0;
-
-buffer_cleanup:
-	iio_triggered_buffer_cleanup(indio_dev);
-	return ret;
-}
-
-static int hmc5843_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);
-
-	/*  sleep mode to save power */
-	hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int hmc5843_suspend(struct device *dev)
-{
-	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
-		to_i2c_client(dev)));
-
-	return hmc5843_set_mode(data, HMC5843_MODE_SLEEP);
-}
-
-static int hmc5843_resume(struct device *dev)
-{
-	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
-		to_i2c_client(dev)));
-
-	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
-}
-
-static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume);
-#define HMC5843_PM_OPS (&hmc5843_pm_ops)
-#else
-#define HMC5843_PM_OPS NULL
-#endif
-
-static const struct i2c_device_id hmc5843_id[] = {
-	{ "hmc5843", HMC5843_ID },
-	{ "hmc5883", HMC5883_ID },
-	{ "hmc5883l", HMC5883L_ID },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, hmc5843_id);
-
-static const struct of_device_id hmc5843_of_match[] = {
-	{ .compatible = "honeywell,hmc5843" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, hmc5843_of_match);
-
-static struct i2c_driver hmc5843_driver = {
-	.driver = {
-		.name	= "hmc5843",
-		.pm	= HMC5843_PM_OPS,
-		.of_match_table = hmc5843_of_match,
-	},
-	.id_table	= hmc5843_id,
-	.probe		= hmc5843_probe,
-	.remove		= hmc5843_remove,
-};
-module_i2c_driver(hmc5843_driver);
-
-MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
-MODULE_DESCRIPTION("HMC5843/5883/5883L driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_core.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_core.c
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,638 @@
+/*  Copyright (C) 2010 Texas Instruments
+    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
+    Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
+
+    Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
+
+    Split to multiple files by Josef Gajdusek <atx@atx.name> - 2014
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/delay.h>
+
+#include "hmc5843.h"
+
+/*
+ * Range gain settings in (+-)Ga
+ * Beware: HMC5843 and HMC5883 have different recommended sensor field
+ * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
+ */
+#define HMC5843_RANGE_GAIN_OFFSET		0x05
+#define HMC5843_RANGE_GAIN_DEFAULT		0x01
+#define HMC5843_RANGE_GAIN_MASK		0xe0
+
+/* Device status */
+#define HMC5843_DATA_READY			0x01
+#define HMC5843_DATA_OUTPUT_LOCK		0x02
+
+/* Mode register configuration */
+#define HMC5843_MODE_CONVERSION_CONTINUOUS	0x00
+#define HMC5843_MODE_CONVERSION_SINGLE		0x01
+#define HMC5843_MODE_IDLE			0x02
+#define HMC5843_MODE_SLEEP			0x03
+#define HMC5843_MODE_MASK			0x03
+
+/*
+ * HMC5843: Minimum data output rate
+ * HMC5883: Typical data output rate
+ */
+#define HMC5843_RATE_OFFSET			0x02
+#define HMC5843_RATE_DEFAULT			0x04
+#define HMC5843_RATE_MASK		0x1c
+
+/* Device measurement configuration */
+#define HMC5843_MEAS_CONF_NORMAL		0x00
+#define HMC5843_MEAS_CONF_POSITIVE_BIAS		0x01
+#define HMC5843_MEAS_CONF_NEGATIVE_BIAS		0x02
+#define HMC5843_MEAS_CONF_MASK			0x03
+
+/* Scaling factors: 10000000/Gain */
+static const int hmc5843_regval_to_nanoscale[] = {
+	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
+};
+
+static const int hmc5883_regval_to_nanoscale[] = {
+	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
+};
+
+static const int hmc5883l_regval_to_nanoscale[] = {
+	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
+};
+
+/*
+ * From the datasheet:
+ * Value	| HMC5843		| HMC5883/HMC5883L
+ *		| Data output rate (Hz)	| Data output rate (Hz)
+ * 0		| 0.5			| 0.75
+ * 1		| 1			| 1.5
+ * 2		| 2			| 3
+ * 3		| 5			| 7.5
+ * 4		| 10 (default)		| 15
+ * 5		| 20			| 30
+ * 6		| 50			| 75
+ * 7		| Not used		| Not used
+ */
+static const int hmc5843_regval_to_samp_freq[][2] = {
+	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
+};
+
+static const int hmc5883_regval_to_samp_freq[][2] = {
+	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
+	{75, 0}
+};
+
+static const int hmc5983_regval_to_samp_freq[][2] = {
+	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
+	{75, 0}, {220, 0}
+};
+
+/* Describe chip variants */
+struct hmc5843_chip_info {
+	const struct iio_chan_spec *channels;
+	const int (*regval_to_samp_freq)[2];
+	const int n_regval_to_samp_freq;
+	const int *regval_to_nanoscale;
+	const int n_regval_to_nanoscale;
+};
+
+/* The lower two bits contain the current conversion mode */
+static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG,
+			HMC5843_MODE_MASK, operating_mode);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int hmc5843_wait_measurement(struct hmc5843_data *data)
+{
+	int tries = 150;
+	int val;
+	int ret;
+
+	while (tries-- > 0) {
+		ret = regmap_read(data->regmap, HMC5843_STATUS_REG, &val);
+		if (ret < 0)
+			return ret;
+		if (val & HMC5843_DATA_READY)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(data->dev, "data not ready\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Return the measurement value from the specified channel */
+static int hmc5843_read_measurement(struct hmc5843_data *data,
+				    int idx, int *val)
+{
+	__be16 values[3];
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		return ret;
+	}
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			values, sizeof(values));
+	mutex_unlock(&data->lock);
+	if (ret < 0)
+		return ret;
+
+	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
+	return IIO_VAL_INT;
+}
+
+/*
+ * API for setting the measurement configuration to
+ * Normal, Positive bias and Negative bias
+ *
+ * From the datasheet:
+ * 0 - Normal measurement configuration (default): In normal measurement
+ *     configuration the device follows normal measurement flow. Pins BP
+ *     and BN are left floating and high impedance.
+ *
+ * 1 - Positive bias configuration: In positive bias configuration, a
+ *     positive current is forced across the resistive load on pins BP
+ *     and BN.
+ *
+ * 2 - Negative bias configuration. In negative bias configuration, a
+ *     negative current is forced across the resistive load on pins BP
+ *     and BN.
+ *
+ */
+static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_MEAS_CONF_MASK, meas_conf);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	int val;
+	int ret;
+
+	ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
+	if (ret)
+		return ret;
+	val &= HMC5843_MEAS_CONF_MASK;
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf,
+						size_t count)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	unsigned long meas_conf = 0;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &meas_conf);
+	if (ret)
+		return ret;
+	if (meas_conf >= HMC5843_MEAS_CONF_MASK)
+		return -EINVAL;
+
+	ret = hmc5843_set_meas_conf(data, meas_conf);
+
+	return (ret < 0) ? ret : count;
+}
+
+static IIO_DEVICE_ATTR(meas_conf,
+			S_IWUSR | S_IRUGO,
+			hmc5843_show_measurement_configuration,
+			hmc5843_set_measurement_configuration,
+			0);
+
+static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < data->variant->n_regval_to_samp_freq; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
+			data->variant->regval_to_samp_freq[i][1]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
+
+static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
+				   int val, int val2)
+{
+	int i;
+
+	for (i = 0; i < data->variant->n_regval_to_samp_freq; i++)
+		if (val == data->variant->regval_to_samp_freq[i][0] &&
+			val2 == data->variant->regval_to_samp_freq[i][1])
+			return i;
+
+	return -EINVAL;
+}
+
+static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B,
+			HMC5843_RANGE_GAIN_MASK,
+			range << HMC5843_RANGE_GAIN_OFFSET);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t hmc5843_show_scale_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < data->variant->n_regval_to_nanoscale; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"0.%09d ", data->variant->regval_to_nanoscale[i]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static IIO_DEVICE_ATTR(scale_available, S_IRUGO,
+	hmc5843_show_scale_avail, NULL, 0);
+
+static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
+{
+	int i;
+
+	if (val != 0)
+		return -EINVAL;
+
+	for (i = 0; i < data->variant->n_regval_to_nanoscale; i++)
+		if (val2 == data->variant->regval_to_nanoscale[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int hmc5843_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rval;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return hmc5843_read_measurement(data, chan->scan_index, val);
+	case IIO_CHAN_INFO_SCALE:
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
+		if (ret < 0)
+			return ret;
+		rval >>= HMC5843_RANGE_GAIN_OFFSET;
+		*val = 0;
+		*val2 = data->variant->regval_to_nanoscale[rval];
+		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
+		if (ret < 0)
+			return ret;
+		rval >>= HMC5843_RATE_OFFSET;
+		*val = data->variant->regval_to_samp_freq[rval][0];
+		*val2 = data->variant->regval_to_samp_freq[rval][1];
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int hmc5843_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rate, range;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		rate = hmc5843_get_samp_freq_index(data, val, val2);
+		if (rate < 0)
+			return -EINVAL;
+
+		return hmc5843_set_samp_freq(data, rate);
+	case IIO_CHAN_INFO_SCALE:
+		range = hmc5843_get_scale_index(data, val, val2);
+		if (range < 0)
+			return -EINVAL;
+
+		return hmc5843_set_range_gain(data, range);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan, long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SCALE:
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		goto done;
+	}
+
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			data->buffer, 3 * sizeof(__be16));
+
+	mutex_unlock(&data->lock);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+#define HMC5843_CHANNEL(axis, idx)					\
+	{								\
+		.type = IIO_MAGN,					\
+		.modified = 1,						\
+		.channel2 = IIO_MOD_##axis,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
+		.scan_index = idx,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 16,					\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+static const struct iio_chan_spec hmc5843_channels[] = {
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Y, 1),
+	HMC5843_CHANNEL(Z, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+/* Beware: Y and Z are exchanged on HMC5883 and 5983 */
+static const struct iio_chan_spec hmc5883_channels[] = {
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Z, 1),
+	HMC5843_CHANNEL(Y, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static struct attribute *hmc5843_attributes[] = {
+	&iio_dev_attr_meas_conf.dev_attr.attr,
+	&iio_dev_attr_scale_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group hmc5843_group = {
+	.attrs = hmc5843_attributes,
+};
+
+static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
+	[HMC5843_ID] = {
+		.channels = hmc5843_channels,
+		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5843_regval_to_samp_freq),
+		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5843_regval_to_nanoscale),
+	},
+	[HMC5883_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5883_regval_to_samp_freq),
+		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883_regval_to_nanoscale),
+	},
+	[HMC5883L_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5883_regval_to_samp_freq),
+		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883l_regval_to_nanoscale),
+	},
+	[HMC5983_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5983_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5983_regval_to_samp_freq),
+		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883l_regval_to_nanoscale),
+	}
+};
+
+static int hmc5843_init(struct hmc5843_data *data)
+{
+	int ret;
+	u8 id[3];
+
+	ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG,
+			id, ARRAY_SIZE(id));
+	if (ret < 0)
+		return ret;
+	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
+		dev_err(data->dev, "no HMC5843/5883/5883L/5983 sensor\n");
+		return -ENODEV;
+	}
+
+	ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT);
+	if (ret < 0)
+		return ret;
+	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
+}
+
+static const struct iio_info hmc5843_info = {
+	.attrs = &hmc5843_group,
+	.read_raw = &hmc5843_read_raw,
+	.write_raw = &hmc5843_write_raw,
+	.write_raw_get_fmt = &hmc5843_write_raw_get_fmt,
+	.driver_module = THIS_MODULE,
+};
+
+static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
+
+
+int hmc5843_common_suspend(struct device *dev)
+{
+	return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)),
+			HMC5843_MODE_CONVERSION_CONTINUOUS);
+}
+EXPORT_SYMBOL(hmc5843_common_suspend);
+
+int hmc5843_common_resume(struct device *dev)
+{
+	return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)),
+			HMC5843_MODE_SLEEP);
+}
+EXPORT_SYMBOL(hmc5843_common_resume);
+
+int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
+		enum hmc5843_ids id)
+{
+	struct hmc5843_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, indio_dev);
+
+	/* default settings at probe */
+	data = iio_priv(indio_dev);
+	data->dev = dev;
+	data->regmap = regmap;
+	data->variant = &hmc5843_chip_info_tbl[id];
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &hmc5843_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = data->variant->channels;
+	indio_dev->num_channels = 4;
+	indio_dev->available_scan_masks = hmc5843_scan_masks;
+
+	ret = hmc5843_init(data);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		hmc5843_trigger_handler, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+EXPORT_SYMBOL(hmc5843_common_probe);
+
+int hmc5843_common_remove(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	/*  sleep mode to save power */
+	hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
+
+	return 0;
+}
+EXPORT_SYMBOL(hmc5843_common_remove);
+
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
+MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 core driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843.h linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843.h
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Header file for hmc5843 driver
+ *
+ * Split from hmc5843.c
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can 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 HMC5843_CORE_H
+#define HMC5843_CORE_H
+
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+#define HMC5843_CONFIG_REG_A			0x00
+#define HMC5843_CONFIG_REG_B			0x01
+#define HMC5843_MODE_REG			0x02
+#define HMC5843_DATA_OUT_MSB_REGS		0x03
+#define HMC5843_STATUS_REG			0x09
+#define HMC5843_ID_REG				0x0a
+#define HMC5843_ID_END				0x0c
+
+enum hmc5843_ids {
+	HMC5843_ID,
+	HMC5883_ID,
+	HMC5883L_ID,
+	HMC5983_ID,
+};
+
+struct hmc5843_data {
+	struct device *dev;
+	struct mutex lock;
+	struct regmap *regmap;
+	const struct hmc5843_chip_info *variant;
+	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
+};
+
+int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
+		enum hmc5843_ids id);
+int hmc5843_common_remove(struct device *dev);
+
+int hmc5843_common_suspend(struct device *dev);
+int hmc5843_common_resume(struct device *dev);
+
+#ifdef CONFIG_PM_SLEEP
+static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops,
+		hmc5843_common_suspend,
+		hmc5843_common_resume);
+#define HMC5843_PM_OPS (&hmc5843_pm_ops)
+#else
+#define HMC5843_PM_OPS NULL
+#endif
+
+#endif /* HMC5843_CORE_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_i2c.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_i2c.c
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_i2c.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * i2c driver for hmc5843/5843/5883/5883l/5983
+ *
+ * Split from hmc5843.c
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can redistribute it 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/i2c.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include "hmc5843.h"
+
+static const struct regmap_range hmc5843_readable_ranges[] = {
+		regmap_reg_range(0, HMC5843_ID_END),
+};
+
+static struct regmap_access_table hmc5843_readable_table = {
+		.yes_ranges = hmc5843_readable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
+};
+
+static const struct regmap_range hmc5843_writable_ranges[] = {
+		regmap_reg_range(0, HMC5843_MODE_REG),
+};
+
+static struct regmap_access_table hmc5843_writable_table = {
+		.yes_ranges = hmc5843_writable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
+};
+
+static const struct regmap_range hmc5843_volatile_ranges[] = {
+		regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
+};
+
+static struct regmap_access_table hmc5843_volatile_table = {
+		.yes_ranges = hmc5843_volatile_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
+};
+
+static struct regmap_config hmc5843_i2c_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+
+		.rd_table = &hmc5843_readable_table,
+		.wr_table = &hmc5843_writable_table,
+		.volatile_table = &hmc5843_volatile_table,
+
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int hmc5843_i2c_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	return hmc5843_common_probe(&client->dev,
+			devm_regmap_init_i2c(client, &hmc5843_i2c_regmap_config),
+			id->driver_data);
+}
+
+static int hmc5843_i2c_remove(struct i2c_client *client)
+{
+	return hmc5843_common_remove(&client->dev);
+}
+
+static const struct i2c_device_id hmc5843_id[] = {
+	{ "hmc5843", HMC5843_ID },
+	{ "hmc5883", HMC5883_ID },
+	{ "hmc5883l", HMC5883L_ID },
+	{ "hmc5983", HMC5983_ID },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, hmc5843_id);
+
+static const struct of_device_id hmc5843_of_match[] = {
+	{ .compatible = "honeywell,hmc5843", .data = (void *)HMC5843_ID },
+	{ .compatible = "honeywell,hmc5883", .data = (void *)HMC5883_ID },
+	{ .compatible = "honeywell,hmc5883l", .data = (void *)HMC5883L_ID },
+	{ .compatible = "honeywell,hmc5983", .data = (void *)HMC5983_ID },
+	{}
+};
+MODULE_DEVICE_TABLE(of, hmc5843_of_match);
+
+static struct i2c_driver hmc5843_driver = {
+	.driver = {
+		.name	= "hmc5843",
+		.pm	= HMC5843_PM_OPS,
+		.of_match_table = hmc5843_of_match,
+	},
+	.id_table	= hmc5843_id,
+	.probe		= hmc5843_i2c_probe,
+	.remove		= hmc5843_i2c_remove,
+};
+module_i2c_driver(hmc5843_driver);
+
+MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
+MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 i2c driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_spi.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_spi.c
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/hmc5843_spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/hmc5843_spi.c	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * SPI driver for hmc5983
+ *
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can redistribute it 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/spi/spi.h>
+#include <linux/iio/iio.h>
+
+#include "hmc5843.h"
+
+static const struct regmap_range hmc5843_readable_ranges[] = {
+		regmap_reg_range(0, HMC5843_ID_END),
+};
+
+static struct regmap_access_table hmc5843_readable_table = {
+		.yes_ranges = hmc5843_readable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
+};
+
+static const struct regmap_range hmc5843_writable_ranges[] = {
+		regmap_reg_range(0, HMC5843_MODE_REG),
+};
+
+static struct regmap_access_table hmc5843_writable_table = {
+		.yes_ranges = hmc5843_writable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
+};
+
+static const struct regmap_range hmc5843_volatile_ranges[] = {
+		regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
+};
+
+static struct regmap_access_table hmc5843_volatile_table = {
+		.yes_ranges = hmc5843_volatile_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
+};
+
+static struct regmap_config hmc5843_spi_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+
+		.rd_table = &hmc5843_readable_table,
+		.wr_table = &hmc5843_writable_table,
+		.volatile_table = &hmc5843_volatile_table,
+
+		/* Autoincrement address pointer */
+		.read_flag_mask = 0xc0,
+
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int hmc5843_spi_probe(struct spi_device *spi)
+{
+	int ret;
+
+	spi->mode = SPI_MODE_3;
+	spi->max_speed_hz = 8000000;
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret)
+		return ret;
+
+	return hmc5843_common_probe(&spi->dev,
+			devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config),
+			HMC5983_ID);
+}
+
+static int hmc5843_spi_remove(struct spi_device *spi)
+{
+	return hmc5843_common_remove(&spi->dev);
+}
+
+static const struct spi_device_id hmc5843_id[] = {
+	{ "hmc5983", HMC5983_ID },
+	{ }
+};
+
+static struct spi_driver hmc5843_driver = {
+		.driver = {
+				.name = "hmc5843",
+				.pm = HMC5843_PM_OPS,
+				.owner = THIS_MODULE,
+		},
+		.id_table = hmc5843_id,
+		.probe = hmc5843_spi_probe,
+		.remove = hmc5843_spi_remove,
+};
+
+module_spi_driver(hmc5843_driver);
+
+MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
+MODULE_DESCRIPTION("HMC5983 SPI driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -4,15 +4,37 @@
 menu "Magnetometer sensors"
 
 config SENSORS_HMC5843
-	tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer"
-	depends on I2C
+	tristate
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
+
+config SENSORS_HMC5843_I2C
+	tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer (I2C)"
+	depends on I2C
+	select SENSORS_HMC5843
+	select REGMAP_I2C
 	help
 	  Say Y here to add support for the Honeywell HMC5843, HMC5883 and
 	  HMC5883L 3-Axis Magnetometer (digital compass).
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called hmc5843.
+	  This driver can also be compiled as a set of modules.
+	  If so, these modules will be created:
+	  - hmc5843_core (core functions)
+	  - hmc5843_i2c (support for HMC5843, HMC5883, HMC5883L and HMC5983)
+
+config SENSORS_HMC5843_SPI
+	tristate "Honeywell HMC5983 3-Axis Magnetometer (SPI)"
+	depends on SPI_MASTER
+	select SENSORS_HMC5843
+	select REGMAP_SPI
+	help
+	  Say Y here to add support for the Honeywell HMC5983 3-Axis Magnetometer
+	  (digital compass).
+
+	  This driver can also be compiled as a set of modules.
+	  If so, these modules will be created:
+	  - hmc5843_core (core functions)
+	  - hmc5843_spi (support for HMC5983)
+
 
 endmenu
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/Makefile
--- linux-libre-3.16-gnu/drivers/staging/iio/magnetometer/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/magnetometer/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,4 +2,6 @@
 # Makefile for industrial I/O Magnetometer sensors
 #
 
-obj-$(CONFIG_SENSORS_HMC5843)	+= hmc5843.o
+obj-$(CONFIG_SENSORS_HMC5843)		+= hmc5843_core.o
+obj-$(CONFIG_SENSORS_HMC5843_I2C)	+= hmc5843_i2c.o
+obj-$(CONFIG_SENSORS_HMC5843_SPI)	+= hmc5843_spi.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/meter/ade7758_trigger.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/meter/ade7758_trigger.c
--- linux-libre-3.16-gnu/drivers/staging/iio/meter/ade7758_trigger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/meter/ade7758_trigger.c	2014-09-28 17:29:07.000000000 -0400
@@ -21,7 +21,7 @@
 static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private)
 {
 	disable_irq_nosync(irq);
-	iio_trigger_poll(private, iio_get_time_ns());
+	iio_trigger_poll(private);
 
 	return IRQ_HANDLED;
 }
@@ -85,7 +85,7 @@ int ade7758_probe_trigger(struct iio_dev
 	ret = iio_trigger_register(st->trig);
 
 	/* select default trigger */
-	indio_dev->trig = st->trig;
+	indio_dev->trig = iio_trigger_get(st->trig);
 	if (ret)
 		goto error_free_irq;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/trigger/iio-trig-bfin-timer.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
--- linux-libre-3.16-gnu/drivers/staging/iio/trigger/iio-trig-bfin-timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/trigger/iio-trig-bfin-timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -154,7 +154,7 @@ static irqreturn_t iio_bfin_tmr_trigger_
 	struct bfin_tmr_state *st = devid;
 
 	clear_gptimer_intr(st->t->id);
-	iio_trigger_poll(st->trig, 0);
+	iio_trigger_poll(st->trig);
 
 	return IRQ_HANDLED;
 }
@@ -182,45 +182,40 @@ static int iio_bfin_tmr_trigger_probe(st
 	unsigned int config;
 	int ret;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
 
 	st->irq = platform_get_irq(pdev, 0);
 	if (!st->irq) {
 		dev_err(&pdev->dev, "No IRQs specified");
-		ret = -ENODEV;
-		goto out1;
+		return -ENODEV;
 	}
 
 	ret = iio_bfin_tmr_get_number(st->irq);
 	if (ret < 0)
-		goto out1;
+		return ret;
 
 	st->timer_num = ret;
 	st->t = &iio_bfin_timer_code[st->timer_num];
 
 	st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num);
-	if (!st->trig) {
-		ret = -ENOMEM;
-		goto out1;
-	}
+	if (!st->trig)
+		return -ENOMEM;
 
 	st->trig->ops = &iio_bfin_tmr_trigger_ops;
 	st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
 	iio_trigger_set_drvdata(st->trig, st);
 	ret = iio_trigger_register(st->trig);
 	if (ret)
-		goto out2;
+		goto out;
 
 	ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
 			  0, st->trig->name, st);
 	if (ret) {
 		dev_err(&pdev->dev,
 			"request IRQ-%d failed", st->irq);
-		goto out4;
+		goto out1;
 	}
 
 	config = PWM_OUT | PERIOD_CNT | IRQ_ENA;
@@ -260,13 +255,10 @@ static int iio_bfin_tmr_trigger_probe(st
 	return 0;
 out_free_irq:
 	free_irq(st->irq, st);
-out4:
-	iio_trigger_unregister(st->trig);
-out2:
-	iio_trigger_put(st->trig);
 out1:
-	kfree(st);
+	iio_trigger_unregister(st->trig);
 out:
+	iio_trigger_put(st->trig);
 	return ret;
 }
 
@@ -280,7 +272,6 @@ static int iio_bfin_tmr_trigger_remove(s
 	free_irq(st->irq, st);
 	iio_trigger_unregister(st->trig);
 	iio_trigger_put(st->trig);
-	kfree(st);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c linux-libre-3.17-rc7-gnu/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
--- linux-libre-3.16-gnu/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,16 +26,22 @@ struct iio_prtc_trigger_info {
 	struct rtc_device *rtc;
 	int frequency;
 	struct rtc_task task;
+	bool state;
 };
 
 static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state)
 {
 	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
-	if (trig_info->frequency == 0)
+	int ret;
+	if (trig_info->frequency == 0 && state)
 		return -EINVAL;
-	dev_info(&trig_info->rtc->dev, "trigger frequency is %d\n",
+	dev_dbg(&trig_info->rtc->dev, "trigger frequency is %d\n",
 			trig_info->frequency);
-	return rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
+	ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
+	if (ret == 0)
+		trig_info->state = state;
+
+	return ret;
 }
 
 static ssize_t iio_trig_periodic_read_freq(struct device *dev,
@@ -61,7 +67,14 @@ static ssize_t iio_trig_periodic_write_f
 	if (ret)
 		goto error_ret;
 
-	ret = rtc_irq_set_freq(trig_info->rtc, &trig_info->task, val);
+	if (val > 0) {
+		ret = rtc_irq_set_freq(trig_info->rtc, &trig_info->task, val);
+		if (ret == 0 && trig_info->state && trig_info->frequency == 0)
+			ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 1);
+	} else if (val == 0) {
+		ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0);
+	} else
+		ret = -EINVAL;
 	if (ret)
 		goto error_ret;
 
@@ -93,8 +106,7 @@ static const struct attribute_group *iio
 
 static void iio_prtc_trigger_poll(void *private_data)
 {
-	/* Timestamp is not provided currently */
-	iio_trigger_poll(private_data, 0);
+	iio_trigger_poll(private_data);
 }
 
 static const struct iio_trigger_ops iio_prtc_trigger_ops = {
@@ -128,8 +140,7 @@ static int iio_trig_periodic_rtc_probe(s
 		iio_trigger_set_drvdata(trig, trig_info);
 		trig->ops = &iio_prtc_trigger_ops;
 		/* RTC access */
-		trig_info->rtc
-			= rtc_class_open(pdata[i]);
+		trig_info->rtc = rtc_class_open(pdata[i]);
 		if (trig_info->rtc == NULL) {
 			ret = -EINVAL;
 			goto error_free_trig_info;
@@ -199,5 +210,5 @@ static struct platform_driver iio_trig_p
 module_platform_driver(iio_trig_periodic_rtc_driver);
 
 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
-MODULE_DESCRIPTION("Periodic realtime clock  trigger for the iio subsystem");
+MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/imx-drm/imx-drm-core.c linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/imx-drm-core.c
--- linux-libre-3.16-gnu/drivers/staging/imx-drm/imx-drm-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/imx-drm-core.c	2014-09-28 17:29:07.000000000 -0400
@@ -202,7 +202,7 @@ static const struct file_operations imx_
 
 void imx_drm_connector_destroy(struct drm_connector *connector)
 {
-	drm_sysfs_connector_remove(connector);
+	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
 EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
@@ -293,10 +293,10 @@ static int imx_drm_driver_load(struct dr
 	 * userspace will expect to be able to access DRM at this point.
 	 */
 	list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-		ret = drm_sysfs_connector_add(connector);
+		ret = drm_connector_register(connector);
 		if (ret) {
 			dev_err(drm->dev,
-				"[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n",
+				"[CONNECTOR:%d:%s] drm_connector_register failed: %d\n",
 				connector->base.id,
 				connector->name, ret);
 			goto err_unbind;
@@ -570,22 +570,6 @@ static int compare_of(struct device *dev
 	return dev->of_node == np;
 }
 
-static LIST_HEAD(imx_drm_components);
-
-static int imx_drm_add_components(struct device *master, struct master *m)
-{
-	struct imx_drm_component *component;
-	int ret;
-
-	list_for_each_entry(component, &imx_drm_components, list) {
-		ret = component_master_add_child(m, compare_of,
-						 component->of_node);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
 static int imx_drm_bind(struct device *dev)
 {
 	return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
@@ -597,43 +581,14 @@ static void imx_drm_unbind(struct device
 }
 
 static const struct component_master_ops imx_drm_ops = {
-	.add_components = imx_drm_add_components,
 	.bind = imx_drm_bind,
 	.unbind = imx_drm_unbind,
 };
 
-static struct imx_drm_component *imx_drm_find_component(struct device *dev,
-		struct device_node *node)
-{
-	struct imx_drm_component *component;
-
-	list_for_each_entry(component, &imx_drm_components, list)
-		if (component->of_node == node)
-			return component;
-
-	return NULL;
-}
-
-static int imx_drm_add_component(struct device *dev, struct device_node *node)
-{
-	struct imx_drm_component *component;
-
-	if (imx_drm_find_component(dev, node))
-		return 0;
-
-	component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
-	if (!component)
-		return -ENOMEM;
-
-	component->of_node = node;
-	list_add_tail(&component->list, &imx_drm_components);
-
-	return 0;
-}
-
 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
 	struct device_node *ep, *port, *remote;
+	struct component_match *match = NULL;
 	int ret;
 	int i;
 
@@ -647,9 +602,7 @@ static int imx_drm_platform_probe(struct
 		if (!port)
 			break;
 
-		ret = imx_drm_add_component(&pdev->dev, port);
-		if (ret < 0)
-			return ret;
+		component_match_add(&pdev->dev, &match, compare_of, port);
 	}
 
 	if (i == 0) {
@@ -675,10 +628,8 @@ static int imx_drm_platform_probe(struct
 				continue;
 			}
 
-			ret = imx_drm_add_component(&pdev->dev, remote);
+			component_match_add(&pdev->dev, &match, compare_of, remote);
 			of_node_put(remote);
-			if (ret < 0)
-				return ret;
 		}
 		of_node_put(port);
 	}
@@ -687,7 +638,7 @@ static int imx_drm_platform_probe(struct
 	if (ret)
 		return ret;
 
-	return component_master_add(&pdev->dev, &imx_drm_ops);
+	return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match);
 }
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/imx-drm/imx-ldb.c linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/imx-ldb.c
--- linux-libre-3.16-gnu/drivers/staging/imx-drm/imx-ldb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/imx-ldb.c	2014-09-28 17:29:07.000000000 -0400
@@ -574,6 +574,9 @@ static void imx_ldb_unbind(struct device
 	for (i = 0; i < 2; i++) {
 		struct imx_ldb_channel *channel = &imx_ldb->channel[i];
 
+		if (!channel->connector.funcs)
+			continue;
+
 		channel->connector.funcs->destroy(&channel->connector);
 		channel->encoder.funcs->destroy(&channel->encoder);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/imx-drm/ipuv3-plane.c linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/ipuv3-plane.c
--- linux-libre-3.16-gnu/drivers/staging/imx-drm/ipuv3-plane.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/imx-drm/ipuv3-plane.c	2014-09-28 17:29:07.000000000 -0400
@@ -281,7 +281,8 @@ static void ipu_plane_dpms(struct ipu_pl
 
 		ipu_idmac_put(ipu_plane->ipu_ch);
 		ipu_dmfc_put(ipu_plane->dmfc);
-		ipu_dp_put(ipu_plane->dp);
+		if (ipu_plane->dp)
+			ipu_dp_put(ipu_plane->dp);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -28,10 +28,6 @@ source "drivers/staging/et131x/Kconfig"
 
 source "drivers/staging/slicoss/Kconfig"
 
-source "drivers/staging/usbip/Kconfig"
-
-source "drivers/staging/winbond/Kconfig"
-
 source "drivers/staging/wlan-ng/Kconfig"
 
 source "drivers/staging/comedi/Kconfig"
@@ -56,41 +52,21 @@ source "drivers/staging/rtl8821ae/Kconfi
 
 source "drivers/staging/rts5208/Kconfig"
 
-source "drivers/staging/frontier/Kconfig"
-
-source "drivers/staging/phison/Kconfig"
-
 source "drivers/staging/line6/Kconfig"
 
 source "drivers/staging/octeon/Kconfig"
 
 source "drivers/staging/octeon-usb/Kconfig"
 
-source "drivers/staging/serqt_usb2/Kconfig"
-
 source "drivers/staging/vt6655/Kconfig"
 
 source "drivers/staging/vt6656/Kconfig"
 
-source "drivers/staging/sep/Kconfig"
-
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/wlags49_h2/Kconfig"
-
-source "drivers/staging/wlags49_h25/Kconfig"
-
-source "drivers/staging/crystalhd/Kconfig"
-
-source "drivers/staging/cxt1e1/Kconfig"
-
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/tidspbridge/Kconfig"
-
-source "drivers/staging/quickstart/Kconfig"
-
-source "drivers/staging/keucr/Kconfig"
+source "drivers/staging/emxx_udc/Kconfig"
 
 source "drivers/staging/bcm/Kconfig"
 
@@ -108,20 +84,16 @@ source "drivers/staging/media/Kconfig"
 
 source "drivers/staging/android/Kconfig"
 
+source "drivers/staging/board/Kconfig"
+
 source "drivers/staging/ozwpan/Kconfig"
 
 source "drivers/staging/gdm72xx/Kconfig"
 
 source "drivers/staging/gdm724x/Kconfig"
 
-source "drivers/staging/silicom/Kconfig"
-
-source "drivers/staging/ced1401/Kconfig"
-
 source "drivers/staging/imx-drm/Kconfig"
 
-source "drivers/staging/dgrp/Kconfig"
-
 source "drivers/staging/fwserial/Kconfig"
 
 source "drivers/staging/goldfish/Kconfig"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/common.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/common.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/common.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef COMMON_INCD
-#define COMMON_INCD
-
-#define BYTE_MASK	0xff
-
-#endif
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/init.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/init.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/init.c	2014-08-07 05:00:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,334 +0,0 @@
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-#include "smil.h"
-#include "init.h"
-
-/*
- * ENE_InitMedia():
- */
-int ENE_InitMedia(struct us_data *us)
-{
-	int	result;
-	u8	MiscReg03 = 0;
-
-	dev_info(&us->pusb_dev->dev, "--- Init Media ---\n");
-	result = ene_read_byte(us, REG_CARD_STATUS, &MiscReg03);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev, "Failed to read register\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-	dev_info(&us->pusb_dev->dev, "MiscReg03 = %x\n", MiscReg03);
-
-	if (MiscReg03 & 0x02) {
-		if (!us->SM_Status.Ready && !us->MS_Status.Ready) {
-			result = ENE_SMInit(us);
-			if (result != USB_STOR_XFER_GOOD)
-				return USB_STOR_TRANSPORT_ERROR;
-		}
-
-	}
-	return result;
-}
-
-/*
- * ene_read_byte() :
- */
-int ene_read_byte(struct us_data *us, u16 index, void *buf)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x01;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xED;
-	bcb->CDB[2]			= (u8)(index>>8);
-	bcb->CDB[3]			= (u8)index;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
-	return result;
-}
-
-/*
- *ENE_SMInit()
- */
-int ENE_SMInit(struct us_data *us)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u8	buf[0x200];
-
-	dev_dbg(&us->pusb_dev->dev, "transport --- ENE_SMInit\n");
-
-	result = ENE_LoadBinCode(us, SM_INIT_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_info(&us->pusb_dev->dev,
-			 "Failed to load SmartMedia init code\n: result= %x\n",
-			 result);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x01;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia init code: result = %x\n",
-			result);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	us->SM_Status = *(struct keucr_sm_status *)&buf[0];
-
-	us->SM_DeviceID = buf[1];
-	us->SM_CardID   = buf[2];
-
-	if (us->SM_Status.Insert && us->SM_Status.Ready) {
-		dev_info(&us->pusb_dev->dev, "Insert     = %x\n",
-					     us->SM_Status.Insert);
-		dev_info(&us->pusb_dev->dev, "Ready      = %x\n",
-					     us->SM_Status.Ready);
-		dev_info(&us->pusb_dev->dev, "WtP        = %x\n",
-					     us->SM_Status.WtP);
-		dev_info(&us->pusb_dev->dev, "DeviceID   = %x\n",
-					     us->SM_DeviceID);
-		dev_info(&us->pusb_dev->dev, "CardID     = %x\n",
-					     us->SM_CardID);
-		MediaChange = 1;
-		Check_D_MediaFmt(us);
-	} else {
-		dev_err(&us->pusb_dev->dev,
-			"SmartMedia Card Not Ready --- %x\n", buf[0]);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * ENE_LoadBinCode()
- */
-int ENE_LoadBinCode(struct us_data *us, u8 flag)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result;
-	/* void *buf; */
-	u8 *buf;
-
-	/* dev_info(&us->pusb_dev->dev, "transport --- ENE_LoadBinCode\n"); */
-	if (us->BIN_FLAG == flag)
-		return USB_STOR_TRANSPORT_GOOD;
-
-	return /*(DEBLOBBED)*/ USB_STOR_TRANSPORT_ERROR;
-	buf = kmalloc(0x800, GFP_KERNEL);
-	if (buf == NULL)
-		return USB_STOR_TRANSPORT_ERROR;
-	switch (flag) {
-	/* For SS */
-	case SM_INIT_PATTERN:
-		dev_dbg(&us->pusb_dev->dev, "SM_INIT_PATTERN\n");
-		memcpy(buf, SM_Init, 0x800);
-		break;
-	case SM_RW_PATTERN:
-		dev_dbg(&us->pusb_dev->dev, "SM_RW_PATTERN\n");
-		memcpy(buf, SM_Rdwr, 0x800);
-		break;
-	}
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x800;
-	bcb->Flags = 0x00;
-	bcb->CDB[0] = 0xEF;
-
-	result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
-
-	kfree(buf);
-	us->BIN_FLAG = flag;
-	return result;
-}
-
-/*
- * ENE_SendScsiCmd():
- */
-int ENE_SendScsiCmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
-
-	int result;
-	unsigned int transfer_length = bcb->DataTransferLength,
-		     cswlen = 0, partial = 0;
-	unsigned int residue;
-
-	/* dev_dbg(&us->pusb_dev->dev, "transport --- ENE_SendScsiCmd\n"); */
-	/* send cmd to out endpoint */
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-					    bcb, US_BULK_CB_WRAP_LEN, NULL);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-				"send cmd to out endpoint fail ---\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	if (buf) {
-		unsigned int pipe = fDir;
-
-		if (fDir == FDIR_READ)
-			pipe = us->recv_bulk_pipe;
-		else
-			pipe = us->send_bulk_pipe;
-
-		/* Bulk */
-		if (use_sg)
-			result = usb_stor_bulk_srb(us, pipe, us->srb);
-		else
-			result = usb_stor_bulk_transfer_sg(us, pipe, buf,
-						transfer_length, 0, &partial);
-		if (result != USB_STOR_XFER_GOOD) {
-			dev_err(&us->pusb_dev->dev, "data transfer fail ---\n");
-			return USB_STOR_TRANSPORT_ERROR;
-		}
-	}
-
-	/* Get CSW for device status */
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, &cswlen);
-
-	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
-		dev_warn(&us->pusb_dev->dev,
-				"Received 0-length CSW; retrying...\n");
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-					bcs, US_BULK_CS_WRAP_LEN, &cswlen);
-	}
-
-	if (result == USB_STOR_XFER_STALLED) {
-		/* get the status again */
-		dev_warn(&us->pusb_dev->dev,
-				"Attempting to get CSW (2nd try)...\n");
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-						bcs, US_BULK_CS_WRAP_LEN, NULL);
-	}
-
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* check bulk status */
-	residue = le32_to_cpu(bcs->Residue);
-
-	/*
-	 * try to compute the actual residue, based on how much data
-	 * was really transferred and what the device tells us
-	 */
-	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
-		residue = min(residue, transfer_length);
-		if (us->srb)
-			scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
-					(int) residue));
-	}
-
-	if (bcs->Status != US_BULK_STAT_OK)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * ENE_Read_Data()
- */
-int ENE_Read_Data(struct us_data *us, void *buf, unsigned int length)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
-	int result;
-
-	/* dev_dbg(&us->pusb_dev->dev, "transport --- ENE_Read_Data\n"); */
-	/* set up the command wrapper */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = length;
-	bcb->Flags = 0x80;
-	bcb->CDB[0] = 0xED;
-	bcb->CDB[2] = 0xFF;
-	bcb->CDB[3] = 0x81;
-
-	/* send cmd to out endpoint */
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb,
-						US_BULK_CB_WRAP_LEN, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* R/W data */
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-						buf, length, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Get CSW for device status */
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-	if (bcs->Status != US_BULK_STAT_OK)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * ENE_Write_Data():
- */
-int ENE_Write_Data(struct us_data *us, void *buf, unsigned int length)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
-	int result;
-
-	/* printk("transport --- ENE_Write_Data\n"); */
-	/* set up the command wrapper */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = length;
-	bcb->Flags = 0x00;
-	bcb->CDB[0] = 0xEE;
-	bcb->CDB[2] = 0xFF;
-	bcb->CDB[3] = 0x81;
-
-	/* send cmd to out endpoint */
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb,
-						US_BULK_CB_WRAP_LEN, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* R/W data */
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-						buf, length, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Get CSW for device status */
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, NULL);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-	if (bcs->Status != US_BULK_STAT_OK)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/init.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/init.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/init.h	2014-08-07 05:00:05.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/init.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#include "common.h"
-
-static u8 SM_Init[] = {
-/*(DEBLOBBED)*/ };
-
-static u8 SM_Rdwr[] = {
-/*(DEBLOBBED)*/ };
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/keucr/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/keucr/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-config USB_ENESTORAGE
-	tristate "USB ENE SM card reader support"
-	depends on USB && SCSI && m
-	---help---
-	  Say Y here if you wish to control a ENE SM Card reader.
-	  To use SD/MS card, please build driver/usb/storage/ums-eneub6250.ko
-
-	  This option depends on 'SCSI' support being enabled, but you
-	  probably also need 'SCSI device support: SCSI disk support'
-	  (BLK_DEV_SD) for most USB storage devices.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called keucr.
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/keucr/Makefile
--- linux-libre-3.16-gnu/drivers/staging/keucr/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-ccflags-y := -Idrivers/scsi
-
-obj-$(CONFIG_USB_ENESTORAGE)	+= keucr.o
-
-keucr-y :=			\
-		usb.o		\
-		scsiglue.o	\
-		transport.o	\
-		init.o		\
-		smscsi.o	\
-		smilmain.o	\
-		smilsub.o	\
-		smilecc.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/scsiglue.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/scsiglue.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/scsiglue.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/scsiglue.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,467 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_devinfo.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_eh.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-/* Host functions */
-/*
- * host_info()
- */
-static const char *host_info(struct Scsi_Host *host)
-{
-	/* pr_info("scsiglue --- host_info\n"); */
-	return "SCSI emulation for USB Mass Storage devices";
-}
-
-/*
- * slave_alloc()
- */
-static int slave_alloc(struct scsi_device *sdev)
-{
-	struct us_data *us = host_to_us(sdev->host);
-
-	/* pr_info("scsiglue --- slave_alloc\n"); */
-	sdev->inquiry_len = 36;
-
-	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
-
-	if (us->subclass == USB_SC_UFI)
-		sdev->sdev_target->pdt_1f_for_no_lun = 1;
-
-	return 0;
-}
-
-/*
- * slave_configure()
- */
-static int slave_configure(struct scsi_device *sdev)
-{
-	struct us_data *us = host_to_us(sdev->host);
-
-	/* pr_info("scsiglue --- slave_configure\n"); */
-	if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
-		unsigned int max_sectors = 64;
-
-		if (us->fflags & US_FL_MAX_SECTORS_MIN)
-			max_sectors = PAGE_CACHE_SIZE >> 9;
-		if (queue_max_sectors(sdev->request_queue) > max_sectors)
-			blk_queue_max_hw_sectors(sdev->request_queue,
-					      max_sectors);
-	}
-
-	if (sdev->type == TYPE_DISK) {
-		if (us->subclass != USB_SC_SCSI &&
-			us->subclass != USB_SC_CYP_ATACB)
-			sdev->use_10_for_ms = 1;
-		sdev->use_192_bytes_for_3f = 1;
-		if (us->fflags & US_FL_NO_WP_DETECT)
-			sdev->skip_ms_page_3f = 1;
-		sdev->skip_ms_page_8 = 1;
-		if (us->fflags & US_FL_FIX_CAPACITY)
-			sdev->fix_capacity = 1;
-		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
-			sdev->guess_capacity = 1;
-		if (sdev->scsi_level > SCSI_2)
-			sdev->sdev_target->scsi_level = sdev->scsi_level
-								= SCSI_2;
-		sdev->retry_hwerror = 1;
-		sdev->allow_restart = 1;
-		sdev->last_sector_bug = 1;
-	} else {
-		sdev->use_10_for_ms = 1;
-	}
-
-	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_CBI) &&
-					sdev->scsi_level == SCSI_UNKNOWN)
-		us->max_lun = 0;
-
-	if (us->fflags & US_FL_NOT_LOCKABLE)
-		sdev->lockable = 0;
-
-	return 0;
-}
-
-/* This is always called with scsi_lock(host) held */
-/*
- * queuecommand()
- */
-static int queuecommand_lck(struct scsi_cmnd *srb,
-				void (*done)(struct scsi_cmnd *))
-{
-	struct us_data *us = host_to_us(srb->device->host);
-
-	/* pr_info("scsiglue --- queuecommand\n"); */
-
-	/* check for state-transition errors */
-	if (us->srb != NULL) {
-		/* pr_info("Error in %s: us->srb = %p\n"
-				 __func__, us->srb); */
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
-
-	/* fail the command if we are disconnecting */
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-		pr_info("Fail command during disconnect\n");
-		srb->result = DID_NO_CONNECT << 16;
-		done(srb);
-		return 0;
-	}
-
-	/* enqueue the command and wake up the control thread */
-	srb->scsi_done = done;
-	us->srb = srb;
-	complete(&us->cmnd_ready);
-
-	return 0;
-}
-
-static DEF_SCSI_QCMD(queuecommand)
-
-/***********************************************************************
- * Error handling functions
- ***********************************************************************/
-
-/* Command timeout and abort */
-/*
- * command_abort()
- */
-static int command_abort(struct scsi_cmnd *srb)
-{
-	struct us_data *us = host_to_us(srb->device->host);
-
-	/* pr_info("scsiglue --- command_abort\n"); */
-
-	scsi_lock(us_to_host(us));
-	if (us->srb != srb) {
-		scsi_unlock(us_to_host(us));
-		dev_info(&us->pusb_dev->dev, "-- nothing to abort\n");
-		return FAILED;
-	}
-
-	set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
-	if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) {
-		set_bit(US_FLIDX_ABORTING, &us->dflags);
-		usb_stor_stop_transport(us);
-	}
-	scsi_unlock(us_to_host(us));
-
-	/* Wait for the aborted command to finish */
-	wait_for_completion(&us->notify);
-	return SUCCESS;
-}
-
-/* This invokes the transport reset mechanism to reset the state of the
- * device.
- */
-/*
- * device_reset()
- */
-static int device_reset(struct scsi_cmnd *srb)
-{
-	struct us_data *us = host_to_us(srb->device->host);
-	int result;
-
-	/* pr_info("scsiglue --- device_reset\n"); */
-
-	/* lock the device pointers and do the reset */
-	mutex_lock(&(us->dev_mutex));
-	result = us->transport_reset(us);
-	mutex_unlock(&us->dev_mutex);
-
-	return result < 0 ? FAILED : SUCCESS;
-}
-
-/*
- * bus_reset()
- */
-static int bus_reset(struct scsi_cmnd *srb)
-{
-	struct us_data *us = host_to_us(srb->device->host);
-	int result;
-
-	/* pr_info("scsiglue --- bus_reset\n"); */
-	result = usb_stor_port_reset(us);
-	return result < 0 ? FAILED : SUCCESS;
-}
-
-/*
- * usb_stor_report_device_reset()
- */
-void usb_stor_report_device_reset(struct us_data *us)
-{
-	int i;
-	struct Scsi_Host *host = us_to_host(us);
-
-	/* pr_info("scsiglue --- usb_stor_report_device_reset\n"); */
-	scsi_report_device_reset(host, 0, 0);
-	if (us->fflags & US_FL_SCM_MULT_TARG) {
-		for (i = 1; i < host->max_id; ++i)
-			scsi_report_device_reset(host, 0, i);
-	}
-}
-
-/*
- * usb_stor_report_bus_reset()
- */
-void usb_stor_report_bus_reset(struct us_data *us)
-{
-	struct Scsi_Host *host = us_to_host(us);
-
-	/* pr_info("scsiglue --- usb_stor_report_bus_reset\n"); */
-	scsi_lock(host);
-	scsi_report_bus_reset(host, 0);
-	scsi_unlock(host);
-}
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) seq_printf(m, ##args)
-
-static int write_info(struct Scsi_Host *host, char *buffer, int length)
-{
-	return length;
-}
-
-static int show_info(struct seq_file *m, struct Scsi_Host *host)
-{
-	struct us_data *us = host_to_us(host);
-	const char *string;
-
-	/* print the controller name */
-	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
-
-	/* print product, vendor, and serial number strings */
-	if (us->pusb_dev->manufacturer)
-		string = us->pusb_dev->manufacturer;
-	else if (us->unusual_dev->vendorName)
-		string = us->unusual_dev->vendorName;
-	else
-		string = "Unknown";
-	SPRINTF("       Vendor: %s\n", string);
-	if (us->pusb_dev->product)
-		string = us->pusb_dev->product;
-	else if (us->unusual_dev->productName)
-		string = us->unusual_dev->productName;
-	else
-		string = "Unknown";
-	SPRINTF("      Product: %s\n", string);
-	if (us->pusb_dev->serial)
-		string = us->pusb_dev->serial;
-	else
-		string = "None";
-	SPRINTF("Serial Number: %s\n", string);
-
-	/* show the protocol and transport */
-	SPRINTF("     Protocol: %s\n", us->protocol_name);
-	SPRINTF("    Transport: %s\n", us->transport_name);
-
-	/* show the device flags */
-	SPRINTF("       Quirks:");
-
-#define US_FLAG(name, value) \
-	do { \
-		if (us->fflags & value) \
-			SPRINTF(" " #name); \
-	} while (0);
-US_DO_ALL_FLAGS
-#undef US_FLAG
-	seq_putc(m, '\n');
-	return 0;
-}
-
-/***********************************************************************
- * Sysfs interface
- ***********************************************************************/
-
-/* Output routine for the sysfs max_sectors file */
-static ssize_t max_sectors_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct scsi_device *sdev = to_scsi_device(dev);
-
-	/* pr_info("scsiglue --- ssize_t show_max_sectors\n"); */
-	return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue));
-}
-
-/* Input routine for the sysfs max_sectors file */
-static ssize_t max_sectors_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct scsi_device *sdev = to_scsi_device(dev);
-	unsigned short ms;
-
-	/* pr_info("scsiglue --- ssize_t store_max_sectors\n"); */
-	if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS) {
-		blk_queue_max_hw_sectors(sdev->request_queue, ms);
-		return strlen(buf);
-	}
-	return -EINVAL;
-}
-static DEVICE_ATTR_RW(max_sectors);
-
-static struct device_attribute *sysfs_device_attr_list[] = {
-	&dev_attr_max_sectors, NULL,
-};
-
-/* this defines our host template, with which we'll allocate hosts */
-
-/*
- * usb_stor_host_template()
- */
-struct scsi_host_template usb_stor_host_template = {
-	/* basic userland interface stuff */
-	.name =				"eucr-storage",
-	.proc_name =			"eucr-storage",
-	.write_info =			write_info,
-	.show_info =			show_info,
-	.info =				host_info,
-
-	/* command interface -- queued only */
-	.queuecommand =			queuecommand,
-
-	/* error and abort handlers */
-	.eh_abort_handler =		command_abort,
-	.eh_device_reset_handler =	device_reset,
-	.eh_bus_reset_handler =		bus_reset,
-
-	/* queue commands only, only one command per LUN */
-	.can_queue =			1,
-	.cmd_per_lun =			1,
-
-	/* unknown initiator id */
-	.this_id =			-1,
-
-	.slave_alloc =			slave_alloc,
-	.slave_configure =		slave_configure,
-
-	/* lots of sg segments can be handled */
-	.sg_tablesize =			SG_ALL,
-
-	/* limit the total size of a transfer to 120 KB */
-	.max_sectors =                  240,
-
-	/* merge commands... this seems to help performance, but
-	 * periodically someone should test to see which setting is more
-	 * optimal.
-	 */
-	.use_clustering =		1,
-
-	/* emulated HBA */
-	.emulated =			1,
-
-	/* we do our own delay after a device or bus reset */
-	.skip_settle_delay =		1,
-
-	/* sysfs device attributes */
-	.sdev_attrs =			sysfs_device_attr_list,
-
-	/* module management */
-	.module =			THIS_MODULE
-};
-
-/* To Report "Illegal Request: Invalid Field in CDB */
-unsigned char usb_stor_sense_invalidCDB[18] = {
-	[0]	= 0x70,			    /* current error */
-	[2]	= ILLEGAL_REQUEST,	    /* Illegal Request = 0x05 */
-	[7]	= 0x0a,			    /* additional length */
-	[12]	= 0x24			    /* Invalid Field in CDB */
-};
-
-/***********************************************************************
- * Scatter-gather transfer buffer access routines
- ***********************************************************************/
-
-/*
- * usb_stor_access_xfer_buf()
- */
-unsigned int usb_stor_access_xfer_buf(struct us_data *us,
-	unsigned char *buffer, unsigned int buflen,
-	struct scsi_cmnd *srb, struct scatterlist **sgptr,
-	unsigned int *offset, enum xfer_buf_dir dir)
-{
-	unsigned int cnt;
-
-	/* pr_info("transport --- usb_stor_access_xfer_buf\n"); */
-	struct scatterlist *sg = *sgptr;
-
-	if (!sg)
-		sg = scsi_sglist(srb);
-
-	cnt = 0;
-	while (cnt < buflen && sg) {
-		struct page *page = sg_page(sg) +
-					((sg->offset + *offset) >> PAGE_SHIFT);
-		unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
-		unsigned int sglen = sg->length - *offset;
-
-		if (sglen > buflen - cnt) {
-			/* Transfer ends within this s-g entry */
-			sglen = buflen - cnt;
-			*offset += sglen;
-		} else {
-			/* Transfer continues to next s-g entry */
-			*offset = 0;
-			sg = sg_next(sg);
-		}
-
-		while (sglen > 0) {
-			unsigned int plen = min(sglen,
-					(unsigned int)PAGE_SIZE - poff);
-			unsigned char *ptr = kmap(page);
-
-			if (dir == TO_XFER_BUF)
-				memcpy(ptr + poff, buffer + cnt, plen);
-			else
-				memcpy(buffer + cnt, ptr + poff, plen);
-			kunmap(page);
-
-			/* Start at the beginning of the next page */
-			poff = 0;
-			++page;
-			cnt += plen;
-			sglen -= plen;
-		}
-	}
-	*sgptr = sg;
-
-	/* Return the amount actually transferred */
-	return cnt;
-}
-
-/*
- * Store the contents of buffer into srb's transfer
- * buffer and set the SCSI residue.
- */
-/*
- * usb_stor_set_xfer_buf()
- */
-void usb_stor_set_xfer_buf(struct us_data *us, unsigned char *buffer,
-		unsigned int buflen, struct scsi_cmnd *srb, unsigned int dir)
-{
-	unsigned int offset = 0;
-	struct scatterlist *sg = NULL;
-
-	/* pr_info("transport --- usb_stor_set_xfer_buf\n"); */
-	/* TO_XFER_BUF = 0, FROM_XFER_BUF = 1 */
-	buflen = min(buflen, scsi_bufflen(srb));
-	buflen = usb_stor_access_xfer_buf(us, buffer, buflen, srb,
-						&sg, &offset, dir);
-	if (buflen < scsi_bufflen(srb))
-		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/scsiglue.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/scsiglue.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/scsiglue.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/scsiglue.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#ifndef _SCSIGLUE_H_
-#define _SCSIGLUE_H_
-
-extern void usb_stor_report_device_reset(struct us_data *us);
-extern void usb_stor_report_bus_reset(struct us_data *us);
-
-extern unsigned char usb_stor_sense_invalidCDB[18];
-extern struct scsi_host_template usb_stor_host_template;
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smcommon.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smcommon.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/smcommon.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smcommon.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*----- < SMCommon.h> --------------------------------------------------*/
-#ifndef SMCOMMON_INCD
-#define SMCOMMON_INCD
-
-
-/***************************************************************************
-Define Definition
-***************************************************************************/
-#define SMSUCCESS           0x0000 /* SUCCESS */
-#define ERROR               0xFFFF /* ERROR */
-#define CORRECT             0x0001 /* CORRECTABLE */
-
-/***************************************************************************/
-#define NO_ERROR            0x0000 /* NO ERROR */
-#define ERR_WriteFault      0x0003 /* Peripheral Device Write Fault */
-#define ERR_HwError         0x0004 /* Hardware Error */
-#define ERR_DataStatus      0x0010 /* DataStatus Error */
-#define ERR_EccReadErr      0x0011 /* Unrecovered Read Error */
-#define ERR_CorReadErr      0x0018 /* Recovered Read Data with ECC */
-#define ERR_OutOfLBA        0x0021 /* Illegal Logical Block Address */
-#define ERR_WrtProtect      0x0027 /* Write Protected */
-#define ERR_ChangedMedia    0x0028 /* Medium Changed */
-#define ERR_UnknownMedia    0x0030 /* Incompatible Medium Installed */
-#define ERR_IllegalFmt      0x0031 /* Medium Format Corrupted */
-#define ERR_NoSmartMedia    0x003A /* Medium Not Present */
-
-/***************************************************************************/
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smilecc.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilecc.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/smilecc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilecc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,211 +0,0 @@
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-/* #include "stdlib.h" */
-/* #include "EUCR6SK.h" */
-#include "smcommon.h"
-#include "smil.h"
-
-/* #include <stdio.h> */
-/* #include <stdlib.h> */
-/* #include <string.h> */
-/* #include <dos.h> */
-/* #include "EMCRIOS.h" */
-
-/* CP0-CP5 code table */
-static u8 ecctable[256] = {
-0x00, 0x55, 0x56, 0x03, 0x59, 0x0C, 0x0F, 0x5A, 0x5A, 0x0F, 0x0C, 0x59, 0x03,
-0x56, 0x55, 0x00, 0x65, 0x30, 0x33, 0x66, 0x3C, 0x69, 0x6A, 0x3F, 0x3F, 0x6A,
-0x69, 0x3C, 0x66, 0x33, 0x30, 0x65, 0x66, 0x33, 0x30, 0x65, 0x3F, 0x6A, 0x69,
-0x3C, 0x3C, 0x69, 0x6A, 0x3F, 0x65, 0x30, 0x33, 0x66, 0x03, 0x56, 0x55, 0x00,
-0x5A, 0x0F, 0x0C, 0x59, 0x59, 0x0C, 0x0F, 0x5A, 0x00, 0x55, 0x56, 0x03, 0x69,
-0x3C, 0x3F, 0x6A, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6A, 0x3F,
-0x3C, 0x69, 0x0C, 0x59, 0x5A, 0x0F, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00,
-0x55, 0x0F, 0x5A, 0x59, 0x0C, 0x0F, 0x5A, 0x59, 0x0C, 0x56, 0x03, 0x00, 0x55,
-0x55, 0x00, 0x03, 0x56, 0x0C, 0x59, 0x5A, 0x0F, 0x6A, 0x3F, 0x3C, 0x69, 0x33,
-0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3C, 0x3F, 0x6A, 0x6A, 0x3F,
-0x3C, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3C, 0x3F,
-0x6A, 0x0F, 0x5A, 0x59, 0x0C, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56,
-0x0C, 0x59, 0x5A, 0x0F, 0x0C, 0x59, 0x5A, 0x0F, 0x55, 0x00, 0x03, 0x56, 0x56,
-0x03, 0x00, 0x55, 0x0F, 0x5A, 0x59, 0x0C, 0x69, 0x3C, 0x3F, 0x6A, 0x30, 0x65,
-0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6A, 0x3F, 0x3C, 0x69, 0x03, 0x56, 0x55,
-0x00, 0x5A, 0x0F, 0x0C, 0x59, 0x59, 0x0C, 0x0F, 0x5A, 0x00, 0x55, 0x56, 0x03,
-0x66, 0x33, 0x30, 0x65, 0x3F, 0x6A, 0x69, 0x3C, 0x3C, 0x69, 0x6A, 0x3F, 0x65,
-0x30, 0x33, 0x66, 0x65, 0x30, 0x33, 0x66, 0x3C, 0x69, 0x6A, 0x3F, 0x3F, 0x6A,
-0x69, 0x3C, 0x66, 0x33, 0x30, 0x65, 0x00, 0x55, 0x56, 0x03, 0x59, 0x0C, 0x0F,
-0x5A, 0x5A, 0x0F, 0x0C, 0x59, 0x03, 0x56, 0x55, 0x00
-};
-
-static void   trans_result(u8,   u8,   u8 *, u8 *);
-
-#define BIT7        0x80
-#define BIT6        0x40
-#define BIT5        0x20
-#define BIT4        0x10
-#define BIT3        0x08
-#define BIT2        0x04
-#define BIT1        0x02
-#define BIT0        0x01
-#define BIT1BIT0    0x03
-#define BIT23       0x00800000L
-#define MASK_CPS    0x3f
-#define CORRECTABLE 0x00555554L
-
-/*
- * reg2; * LP14,LP12,LP10,...
- * reg3; * LP15,LP13,LP11,...
- * *ecc1; * LP15,LP14,LP13,...
- * *ecc2; * LP07,LP06,LP05,...
- */
-static void trans_result(u8 reg2, u8 reg3, u8 *ecc1, u8 *ecc2)
-{
-	u8 a; /* Working for reg2,reg3 */
-	u8 b; /* Working for ecc1,ecc2 */
-	u8 i; /* For counting */
-
-	a = BIT7; b = BIT7; /* 80h=10000000b */
-	*ecc1 = *ecc2 = 0; /* Clear ecc1,ecc2 */
-	for (i = 0; i < 4; ++i) {
-		if ((reg3&a) != 0)
-			*ecc1 |= b; /* LP15,13,11,9 -> ecc1 */
-		b = b>>1; /* Right shift */
-		if ((reg2&a) != 0)
-			*ecc1 |= b; /* LP14,12,10,8 -> ecc1 */
-		b = b>>1; /* Right shift */
-		a = a>>1; /* Right shift */
-	}
-
-	b = BIT7; /* 80h=10000000b */
-	for (i = 0; i < 4; ++i) {
-		if ((reg3&a) != 0)
-			*ecc2 |= b; /* LP7,5,3,1 -> ecc2 */
-		b = b>>1; /* Right shift */
-		if ((reg2&a) != 0)
-			*ecc2 |= b; /* LP6,4,2,0 -> ecc2 */
-		b = b>>1; /* Right shift */
-		a = a>>1; /* Right shift */
-	}
-}
-
-/*static void calculate_ecc(table,data,ecc1,ecc2,ecc3) */
-/*
- * *table; * CP0-CP5 code table
- * *data; * DATA
- * *ecc1; * LP15,LP14,LP13,...
- * *ecc2; * LP07,LP06,LP05,...
- * *ecc3; * CP5,CP4,CP3,...,"1","1"
- */
-void calculate_ecc(u8 *table, u8 *data, u8 *ecc1, u8 *ecc2, u8 *ecc3)
-{
-	u32  i;    /* For counting */
-	u8 a;    /* Working for table */
-	u8 reg1; /* D-all,CP5,CP4,CP3,... */
-	u8 reg2; /* LP14,LP12,L10,... */
-	u8 reg3; /* LP15,LP13,L11,... */
-
-	reg1 = reg2 = reg3 = 0;   /* Clear parameter */
-	for (i = 0; i < 256; ++i) {
-		a = table[data[i]]; /* Get CP0-CP5 code from table */
-		reg1 ^= (a&MASK_CPS); /* XOR with a */
-		if ((a&BIT6) != 0) { /* If D_all(all bit XOR) = 1 */
-			reg3 ^= (u8)i; /* XOR with counter */
-			reg2 ^= ~((u8)i); /* XOR with inv. of counter */
-		}
-	}
-
-	/* Trans LP14,12,10,... & LP15,13,11,... ->
-						LP15,14,13,... & LP7,6,5,.. */
-	trans_result(reg2, reg3, ecc1, ecc2);
-	*ecc1 = ~(*ecc1); *ecc2 = ~(*ecc2); /* Inv. ecc2 & ecc3 */
-	*ecc3 = ((~reg1)<<2)|BIT1BIT0; /* Make TEL format */
-}
-
-/*
- * *data; * DATA
- * *eccdata; * ECC DATA
- * ecc1; * LP15,LP14,LP13,...
- * ecc2; * LP07,LP06,LP05,...
- * ecc3; * CP5,CP4,CP3,...,"1","1"
- */
-u8 correct_data(u8 *data, u8 *eccdata, u8 ecc1, u8 ecc2, u8 ecc3)
-{
-	u32 l; /* Working to check d */
-	u32 d; /* Result of comparison */
-	u32 i; /* For counting */
-	u8 d1, d2, d3; /* Result of comparison */
-	u8 a; /* Working for add */
-	u8 add; /* Byte address of cor. DATA */
-	u8 b; /* Working for bit */
-	u8 bit; /* Bit address of cor. DATA */
-
-	d1 = ecc1^eccdata[1]; d2 = ecc2^eccdata[0]; /* Compare LP's */
-	d3 = ecc3^eccdata[2]; /* Compare CP's */
-	d = ((u32)d1<<16) /* Result of comparison */
-	+((u32)d2<<8)
-	+(u32)d3;
-
-	if (d == 0)
-		return 0; /* If No error, return */
-
-	if (((d^(d>>1))&CORRECTABLE) == CORRECTABLE) { /* If correctable */
-		l = BIT23;
-		add = 0; /* Clear parameter */
-		a = BIT7;
-
-		for (i = 0; i < 8; ++i) { /* Checking 8 bit */
-			if ((d&l) != 0)
-				add |= a; /* Make byte address from LP's */
-			l >>= 2; a >>= 1; /* Right Shift */
-		}
-
-		bit = 0; /* Clear parameter */
-		b = BIT2;
-		for (i = 0; i < 3; ++i) { /* Checking 3 bit */
-			if ((d&l) != 0)
-				bit |= b; /* Make bit address from CP's */
-			l >>= 2; b >>= 1; /* Right shift */
-		}
-
-		b = BIT0;
-		data[add] ^= (b<<bit); /* Put corrected data */
-		return 1;
-	}
-
-	i = 0; /* Clear count */
-	d &= 0x00ffffffL; /* Masking */
-
-	while (d) { /* If d=0 finish counting */
-		if (d&BIT0)
-			++i; /* Count number of 1 bit */
-		d >>= 1; /* Right shift */
-	}
-
-	if (i == 1) { /* If ECC error */
-		eccdata[1] = ecc1; eccdata[0] = ecc2; /* Put right ECC code */
-		eccdata[2] = ecc3;
-		return 2;
-	}
-	return 3; /* Uncorrectable error */
-}
-
-int _Correct_D_SwECC(u8 *buf, u8 *redundant_ecc, u8 *calculate_ecc)
-{
-	u32 err;
-
-	err = correct_data(buf, redundant_ecc, *(calculate_ecc + 1),
-			   *(calculate_ecc), *(calculate_ecc + 2));
-	if (err == 1)
-		memcpy(calculate_ecc, redundant_ecc, 3);
-
-	if (err == 0 || err == 1 || err == 2)
-		return 0;
-
-	return -1;
-}
-
-void _Calculate_D_SwECC(u8 *buf, u8 *ecc)
-{
-	calculate_ecc(ecctable, buf, ecc+1, ecc+0, ecc+2);
-}
-
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smil.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smil.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/smil.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smil.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,288 +0,0 @@
-/*----- < smil.h> ----------------------------------------------------*/
-#ifndef SMIL_INCD
-#define SMIL_INCD
-
-/***************************************************************************
-Define Definition
-***************************************************************************/
-#define K_BYTE              1024   /* Kilo Byte */
-#define SECTSIZE            512    /* Sector buffer size */
-#define REDTSIZE            16     /* Redundant buffer size */
-
-/***************************************************************************/
-#define DUMMY_DATA          0xFF   /* No Assign Sector Read Data */
-
-/***************************************************************************
-Max Zone/Block/Sectors Data Definition
-***************************************************************************/
-#define MAX_ZONENUM         128    /* Max Zone Numbers in a SmartMedia    */
-#define MAX_BLOCKNUM        0x0400 /* Max Block Numbers in a Zone         */
-#define MAX_SECTNUM         0x20   /* Max Sector Numbers in a Block       */
-#define MAX_LOGBLOCK        1000   /* Max Logical Block Numbers in a Zone */
-
-/***************************************************************************/
-#define CIS_SEARCH_SECT     0x08   /* Max CIS Search Sector Number */
-
-/***************************************************************************
-Logical to Physical Block Table Data Definition
-***************************************************************************/
-#define NO_ASSIGN           0xFFFF /* No Assign Logical Block Address */
-
-/***************************************************************************
-'SectCopyMode' Data
-***************************************************************************/
-#define COMPLETED           0      /* Sector Copy Completed */
-#define REQ_ERASE           1      /* Request Read Block Erase */
-#define REQ_FAIL            2      /* Request Read Block Failed */
-
-/***************************************************************************
-Retry Counter Definition
-***************************************************************************/
-#define RDERR_REASSIGN      1      /* Reassign with Read Error */
-#define L2P_ERR_ERASE       1      /* BlockErase for Contradicted L2P Table */
-
-/***************************************************************************
-Hardware ECC Definition
-***************************************************************************/
-#define HW_ECC_SUPPORTED    1	   /* Hardware ECC Supported */
-/* No definition for Software ECC */
-
-/***************************************************************************
-SmartMedia Command & Status Definition
-***************************************************************************/
-/* SmartMedia Command */
-#define WRDATA        0x80
-/* #define READ          0x00 */
-#define READ_REDT     0x50
-/* #define WRITE         0x10 */
-#define RDSTATUS      0x70
-
-#define READ1         0x00 /* NO */
-#define READ2         0x01 /* NO */
-#define READ3         0x50 /* NO */
-#define RST_CHIP      0xFF
-#define ERASE1        0x60
-#define ERASE2        0xD0
-#define READ_ID_1     0x90
-#define READ_ID_2     0x91
-#define READ_ID_3     0x9A
-
-/* 712 SmartMedia Command */
-#define SM_CMD_RESET                0x00    /* 0xFF */
-#define SM_CMD_READ_ID_1            0x10    /* 0x90 */
-#define SM_CMD_READ_ID_2            0x20    /* 0x91 */
-#define SM_CMD_READ_STAT            0x30    /* 0x70 */
-#define SM_CMD_RDMULTPL_STAT        0x40    /* 0x71 */
-#define SM_CMD_READ_1               0x50    /* 0x00 */
-#define SM_CMD_READ_2               0x60    /* 0x01 */
-#define SM_CMD_READ_3               0x70    /* 0x50 */
-#define SM_CMD_PAGPRGM_TRUE         0x80    /* {0x80, 0x10} */
-#define SM_CMD_PAGPRGM_DUMY         0x90    /* {0x80, 0x11} */
-#define SM_CMD_PAGPRGM_MBLK         0xA0    /* {0x80, 0x15} */
-#define SM_CMD_BLKERASE             0xB0    /* {0x60, 0xD0} */
-#define SM_CMD_BLKERASE_MULTPL      0xC0    /* {0x60-0x60, 0xD0} */
-
-#define SM_CRADDTCT_DEBNCETIMER_EN  0x02
-#define SM_CMD_START_BIT            0x01
-
-#define SM_WaitCmdDone { while (!SM_CmdDone); }
-#define SM_WaitDmaDone { while (!SM_DmaDone); }
-
-/* SmartMedia Status */
-#define WR_FAIL       0x01      /* 0:Pass, 1:Fail */
-#define SUSPENDED     0x20      /* 0:Not Suspended, 1:Suspended */
-#define READY         0x40      /* 0:Busy, 1:Ready */
-#define WR_PRTCT      0x80      /* 0:Protect, 1:Not Protect */
-
-/* SmartMedia Busy Time (1bit:0.1ms) */
-#define BUSY_PROG 200 /* tPROG   : 20ms  ----- Program Time old : 200 */
-#define BUSY_ERASE 4000 /* tBERASE : 400ms ----- Block Erase Time old : 4000 */
-
-/*for 712 Test */
-/* #define BUSY_READ 1 *//* tR : 100us ----- Data transfer Time   old : 1 */
-/* #define BUSY_READ 10 *//* tR : 100us ----- Data transfer Time   old : 1 */
-
-#define BUSY_READ 200 /* tR : 20ms   ----- Data transfer Time   old : 1 */
-
-/* #define BUSY_RESET 60 *//* tRST : 6ms ----- Device Resetting Time old : 60 */
-
-#define BUSY_RESET 600 /* tRST : 60ms   ----- Device Resetting Time old : 60 */
-
-/* Hardware Timer (1bit:0.1ms) */
-#define TIME_PON      3000      /* 300ms ------ Power On Wait Time */
-#define TIME_CDCHK    200       /* 20ms  ------ Card Check Interval Timer */
-#define TIME_WPCHK    50        /* 5ms   ------ WP Check Interval Timer */
-#define TIME_5VCHK    10        /* 1ms   ------ 5V Check Interval Timer */
-
-/***************************************************************************
-Redundant Data
-***************************************************************************/
-#define REDT_DATA     0x04
-#define REDT_BLOCK    0x05
-#define REDT_ADDR1H   0x06
-#define REDT_ADDR1L   0x07
-#define REDT_ADDR2H   0x0B
-#define REDT_ADDR2L   0x0C
-#define REDT_ECC10    0x0D
-#define REDT_ECC11    0x0E
-#define REDT_ECC12    0x0F
-#define REDT_ECC20    0x08
-#define REDT_ECC21    0x09
-#define REDT_ECC22    0x0A
-
-/***************************************************************************
-SmartMedia Model & Attribute
-***************************************************************************/
-/* SmartMedia Attribute */
-#define NOWP          0x00 /* 0... .... No Write Protect */
-#define WP            0x80 /* 1... .... Write Protected */
-#define MASK          0x00 /* .00. .... NAND MASK ROM Model */
-#define FLASH         0x20 /* .01. .... NAND Flash ROM Model */
-#define AD3CYC        0x00 /* ...0 .... Address 3-cycle */
-#define AD4CYC        0x10 /* ...1 .... Address 4-cycle */
-#define BS16          0x00 /* .... 00.. 16page/block */
-#define BS32          0x04 /* .... 01.. 32page/block */
-#define PS256         0x00 /* .... ..00 256byte/page */
-#define PS512         0x01 /* .... ..01 512byte/page */
-#define MWP           0x80 /* WriteProtect mask */
-#define MFLASH        0x60 /* Flash Rom mask */
-#define MADC          0x10 /* Address Cycle */
-#define MBS           0x0C /* BlockSize mask */
-#define MPS           0x03 /* PageSize mask */
-
-/* SmartMedia Model */
-#define NOSSFDC       0x00 /* NO   SmartMedia */
-#define SSFDC1MB      0x01 /* 1MB  SmartMedia */
-#define SSFDC2MB      0x02 /* 2MB  SmartMedia */
-#define SSFDC4MB      0x03 /* 4MB  SmartMedia */
-#define SSFDC8MB      0x04 /* 8MB  SmartMedia */
-#define SSFDC16MB     0x05 /* 16MB SmartMedia */
-#define SSFDC32MB     0x06 /* 32MB SmartMedia */
-#define SSFDC64MB     0x07 /* 64MB SmartMedia */
-#define SSFDC128MB    0x08 /*128MB SmartMedia */
-#define SSFDC256MB    0x09
-#define SSFDC512MB    0x0A
-#define SSFDC1GB      0x0B
-#define SSFDC2GB      0x0C
-
-/***************************************************************************
-Struct Definition
-***************************************************************************/
-struct keucr_media_info {
-	u8 Model;
-	u8 Attribute;
-	u8 MaxZones;
-	u8 MaxSectors;
-	u16 MaxBlocks;
-	u16 MaxLogBlocks;
-};
-
-struct keucr_media_address {
-	u8 Zone;	/* Zone Number */
-	u8 Sector;	/* Sector(512byte) Number on Block */
-	u16 PhyBlock;	/* Physical Block Number on Zone */
-	u16 LogBlock;	/* Logical Block Number of Zone */
-};
-
-struct keucr_media_area {
-	u8 Sector;	/* Sector(512byte) Number on Block */
-	u16 PhyBlock;	/* Physical Block Number on Zone 0 */
-};
-
-extern u16	ReadBlock;
-extern u16	WriteBlock;
-extern u32	MediaChange;
-
-extern struct keucr_media_info    Ssfdc;
-extern struct keucr_media_address Media;
-extern struct keucr_media_area    CisArea;
-
-/*
- * SMILMain.c
- */
-/******************************************/
-int         Init_D_SmartMedia(void);
-int         Pwoff_D_SmartMedia(void);
-int         Check_D_SmartMedia(void);
-int         Check_D_MediaFmt(struct us_data *);
-int         Check_D_Parameter(struct us_data *, u16 *, u8 *, u8 *);
-int         Media_D_ReadSector(struct us_data *, u32, u16, u8 *);
-int         Media_D_WriteSector(struct us_data *, u32, u16, u8 *);
-int         Media_D_CopySector(struct us_data *, u32, u16, u8 *);
-int         Media_D_EraseBlock(struct us_data *, u32, u16);
-int         Media_D_EraseAll(struct us_data *);
-/******************************************/
-int         Media_D_OneSectWriteStart(struct us_data *, u32, u8 *);
-int         Media_D_OneSectWriteNext(struct us_data *, u8 *);
-int         Media_D_OneSectWriteFlush(struct us_data *);
-
-/******************************************/
-extern int	SM_FreeMem(void);	/* ENE SM function */
-void        SM_EnableLED(struct us_data *, bool);
-void        Led_D_TernOn(void);
-void        Led_D_TernOff(void);
-
-int         Media_D_EraseAllRedtData(u32 Index, bool CheckBlock);
-/*DWORD Media_D_GetMediaInfo(struct us_data * fdoExt,
-	PIOCTL_MEDIA_INFO_IN pParamIn, PIOCTL_MEDIA_INFO_OUT pParamOut); */
-
-/*
- * SMILSub.c
- */
-/******************************************/
-int  Check_D_DataBlank(u8 *);
-int  Check_D_FailBlock(u8 *);
-int  Check_D_DataStatus(u8 *);
-int  Load_D_LogBlockAddr(u8 *);
-void Clr_D_RedundantData(u8 *);
-void Set_D_LogBlockAddr(u8 *);
-void Set_D_FailBlock(u8 *);
-void Set_D_DataStaus(u8 *);
-
-/******************************************/
-void Ssfdc_D_Reset(struct us_data *);
-int  Ssfdc_D_ReadCisSect(struct us_data *, u8 *, u8 *);
-void Ssfdc_D_WriteRedtMode(void);
-void Ssfdc_D_ReadID(u8 *, u8);
-int  Ssfdc_D_ReadSect(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_ReadBlock(struct us_data *, u16, u8 *, u8 *);
-int  Ssfdc_D_WriteSect(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_WriteBlock(struct us_data *, u16, u8 *, u8 *);
-int  Ssfdc_D_CopyBlock(struct us_data *, u16, u8 *, u8 *);
-int  Ssfdc_D_WriteSectForCopy(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_EraseBlock(struct us_data *);
-int  Ssfdc_D_ReadRedtData(struct us_data *, u8 *);
-int  Ssfdc_D_WriteRedtData(struct us_data *, u8 *);
-int  Ssfdc_D_CheckStatus(void);
-int  Set_D_SsfdcModel(u8);
-void Cnt_D_Reset(void);
-int  Cnt_D_PowerOn(void);
-void Cnt_D_PowerOff(void);
-void Cnt_D_LedOn(void);
-void Cnt_D_LedOff(void);
-int  Check_D_CntPower(void);
-int  Check_D_CardExist(void);
-int  Check_D_CardStsChg(void);
-int  Check_D_SsfdcWP(void);
-int  SM_ReadBlock(struct us_data *, u8 *, u8 *);
-
-int  Ssfdc_D_ReadSect_DMA(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_ReadSect_PIO(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_WriteSect_DMA(struct us_data *, u8 *, u8 *);
-int  Ssfdc_D_WriteSect_PIO(struct us_data *, u8 *, u8 *);
-
-/******************************************/
-int  Check_D_ReadError(u8 *);
-int  Check_D_Correct(u8 *, u8 *);
-int  Check_D_CISdata(u8 *, u8 *);
-void Set_D_RightECC(u8 *);
-
-/*
- * SMILECC.c
- */
-void calculate_ecc(u8 *, u8 *, u8 *, u8 *, u8 *);
-u8 correct_data(u8 *, u8 *, u8,   u8,   u8);
-int  _Correct_D_SwECC(u8 *, u8 *, u8 *);
-void _Calculate_D_SwECC(u8 *, u8 *);
-
-#endif /* already included */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smilmain.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilmain.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/smilmain.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilmain.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,760 +0,0 @@
-#include <linux/slab.h>
-#include "usb.h"
-#include "scsiglue.h"
-#include "smcommon.h"
-#include "smil.h"
-
-static int         Conv_D_MediaAddr(struct us_data *, u32);
-static int         Inc_D_MediaAddr(struct us_data *);
-static int         Media_D_ReadOneSect(struct us_data *, u16, u8 *);
-
-static int  Copy_D_BlockAll(struct us_data *, u32);
-
-static int  Assign_D_WriteBlock(void);
-static int  Release_D_ReadBlock(struct us_data *);
-static int  Release_D_WriteBlock(struct us_data *);
-static int  Release_D_CopySector(struct us_data *);
-
-static int  Copy_D_PhyOneSect(struct us_data *);
-static int  Read_D_PhyOneSect(struct us_data *, u16, u8 *);
-static int  Erase_D_PhyOneBlock(struct us_data *);
-
-static int  Set_D_PhyFmtValue(struct us_data *);
-static int  Search_D_CIS(struct us_data *);
-static int  Make_D_LogTable(struct us_data *);
-
-static int  MarkFail_D_PhyOneBlock(struct us_data *);
-
-static u32 ErrCode;
-static u8  WorkBuf[SECTSIZE];
-static u8  Redundant[REDTSIZE];
-static u8  WorkRedund[REDTSIZE];
-/* 128 x 1000, Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; */
-static u16  *Log2Phy[MAX_ZONENUM];
-static u8  Assign[MAX_ZONENUM][MAX_BLOCKNUM / 8];
-static u16  AssignStart[MAX_ZONENUM];
-u16  ReadBlock;
-u16  WriteBlock;
-u32 MediaChange;
-static u32 SectCopyMode;
-
-/* BIT Control Macro */
-static u8 BitData[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
-#define Set_D_Bit(a, b)    (a[(u8)((b) / 8)] |= BitData[(b) % 8])
-#define Clr_D_Bit(a, b)    (a[(u8)((b) / 8)] &= ~BitData[(b) % 8])
-#define Chk_D_Bit(a, b)    (a[(u8)((b) / 8)] & BitData[(b) % 8])
-
-/* ----- SM_FreeMem() ------------------------------------------------- */
-int SM_FreeMem(void)
-{
-	int	i;
-
-	pr_info("SM_FreeMem start\n");
-	for (i = 0; i < MAX_ZONENUM; i++) {
-		if (Log2Phy[i] != NULL) {
-			pr_info("Free Zone = %x, Addr = %p\n", i, Log2Phy[i]);
-			kfree(Log2Phy[i]);
-			Log2Phy[i] = NULL;
-		}
-	}
-	return NO_ERROR;
-}
-
-/* SmartMedia Read/Write/Erase Function */
-/* ----- Media_D_ReadSector() ------------------------------------------- */
-int Media_D_ReadSector(struct us_data *us, u32 start, u16 count, u8 *buf)
-{
-	u16 len, bn;
-
-	if (Conv_D_MediaAddr(us, start))
-		return ErrCode;
-
-	while (1) {
-		len = Ssfdc.MaxSectors - Media.Sector;
-		if (count > len)
-			bn = len;
-		else
-			bn = count;
-
-		if (Media_D_ReadOneSect(us, bn, buf)) {
-			ErrCode = ERR_EccReadErr;
-			return ErrCode;
-		}
-
-		Media.Sector += bn;
-		count -= bn;
-
-		if (count <= 0)
-			break;
-
-		buf += bn * SECTSIZE;
-
-		if (Inc_D_MediaAddr(us))
-			return ErrCode;
-	}
-
-	return NO_ERROR;
-}
-/* here */
-/* ----- Media_D_CopySector() ------------------------------------------ */
-int Media_D_CopySector(struct us_data *us, u32 start, u16 count, u8 *buf)
-{
-	u16 len, bn;
-
-	/* pr_info("Media_D_CopySector !!!\n"); */
-	if (Conv_D_MediaAddr(us, start))
-		return ErrCode;
-
-	while (1) {
-		if (Assign_D_WriteBlock())
-			return ERROR;
-
-		len = Ssfdc.MaxSectors - Media.Sector;
-		if (count > len)
-			bn = len;
-		else
-		bn = count;
-
-		if (Ssfdc_D_CopyBlock(us, bn, buf, Redundant)) {
-			ErrCode = ERR_WriteFault;
-			return ErrCode;
-		}
-
-		Media.Sector = 0x1F;
-		if (Release_D_CopySector(us)) {
-			if (ErrCode == ERR_HwError) {
-				ErrCode = ERR_WriteFault;
-				return ErrCode;
-			}
-		}
-		count -= bn;
-
-		if (count <= 0)
-			break;
-
-		buf += bn * SECTSIZE;
-
-		if (Inc_D_MediaAddr(us))
-			return ErrCode;
-
-	}
-	return NO_ERROR;
-}
-
-/* SmartMedia Physical Format Test Subroutine */
-/* ----- Check_D_MediaFmt() --------------------------------------------- */
-int Check_D_MediaFmt(struct us_data *us)
-{
-	pr_info("Check_D_MediaFmt\n");
-
-	if (!MediaChange)
-		return SMSUCCESS;
-
-	MediaChange  = ERROR;
-	SectCopyMode = COMPLETED;
-
-	if (Set_D_PhyFmtValue(us)) {
-		ErrCode = ERR_UnknownMedia;
-		return ERROR;
-	}
-
-	if (Search_D_CIS(us)) {
-		ErrCode = ERR_IllegalFmt;
-		return ERROR;
-	}
-
-	MediaChange = SMSUCCESS;
-	return SMSUCCESS;
-}
-
-/* ----- Release_D_CopySector() ------------------------------------------ */
-static int Release_D_CopySector(struct us_data *us)
-{
-	Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock;
-	Media.PhyBlock = ReadBlock;
-
-	if (Media.PhyBlock == NO_ASSIGN) {
-		Media.PhyBlock = WriteBlock;
-		return SMSUCCESS;
-	}
-
-	Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock);
-	Media.PhyBlock = WriteBlock;
-
-	return SMSUCCESS;
-}
-
-/* SmartMedia Physical Address Control Subroutine */
-/* ----- Conv_D_MediaAddr() --------------------------------------------- */
-static int Conv_D_MediaAddr(struct us_data *us, u32 addr)
-{
-	u32 temp;
-
-	temp           = addr / Ssfdc.MaxSectors;
-	Media.Zone     = (u8) (temp / Ssfdc.MaxLogBlocks);
-
-	if (Log2Phy[Media.Zone] == NULL) {
-		if (Make_D_LogTable(us)) {
-			ErrCode = ERR_IllegalFmt;
-			return ERROR;
-		}
-	}
-
-	Media.Sector   = (u8) (addr % Ssfdc.MaxSectors);
-	Media.LogBlock = (u16) (temp % Ssfdc.MaxLogBlocks);
-
-	if (Media.Zone < Ssfdc.MaxZones) {
-		Clr_D_RedundantData(Redundant);
-		Set_D_LogBlockAddr(Redundant);
-		Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
-		return SMSUCCESS;
-	}
-
-	ErrCode = ERR_OutOfLBA;
-	return ERROR;
-}
-
-/* ----- Inc_D_MediaAddr() ---------------------------------------------- */
-static int Inc_D_MediaAddr(struct us_data *us)
-{
-	u16        LogBlock = Media.LogBlock;
-
-	if (++Media.Sector < Ssfdc.MaxSectors)
-		return SMSUCCESS;
-
-	if (Log2Phy[Media.Zone] == NULL) {
-		if (Make_D_LogTable(us)) {
-			ErrCode = ERR_IllegalFmt;
-			return ERROR;
-		}
-	}
-
-	Media.Sector = 0;
-	Media.LogBlock = LogBlock;
-
-	if (++Media.LogBlock < Ssfdc.MaxLogBlocks) {
-		Clr_D_RedundantData(Redundant);
-		Set_D_LogBlockAddr(Redundant);
-		Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
-		return SMSUCCESS;
-	}
-
-	Media.LogBlock = 0;
-
-	if (++Media.Zone < Ssfdc.MaxZones) {
-		if (Log2Phy[Media.Zone] == NULL) {
-			if (Make_D_LogTable(us)) {
-				ErrCode = ERR_IllegalFmt;
-				return ERROR;
-			}
-		}
-
-		Media.LogBlock = 0;
-
-		Clr_D_RedundantData(Redundant);
-		Set_D_LogBlockAddr(Redundant);
-		Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
-		return SMSUCCESS;
-	}
-
-	Media.Zone = 0;
-	ErrCode = ERR_OutOfLBA;
-
-	return ERROR;
-}
-
-/* SmartMedia Read/Write Subroutine with Retry */
-/* ----- Media_D_ReadOneSect() ------------------------------------------ */
-static int Media_D_ReadOneSect(struct us_data *us, u16 count, u8 *buf)
-{
-	u32 err, retry;
-
-	if (!Read_D_PhyOneSect(us, count, buf))
-		return SMSUCCESS;
-	if (ErrCode == ERR_HwError)
-		return ERROR;
-	if (ErrCode == ERR_DataStatus)
-		return ERROR;
-
-#ifdef RDERR_REASSIGN
-	if (Ssfdc.Attribute & MWP) {
-		if (ErrCode == ERR_CorReadErr)
-			return SMSUCCESS;
-		return ERROR;
-	}
-
-	err = ErrCode;
-	for (retry = 0; retry < 2; retry++) {
-		if (Copy_D_BlockAll(us,
-			(err == ERR_EccReadErr) ? REQ_FAIL : REQ_ERASE)) {
-			if (ErrCode == ERR_HwError)
-				return ERROR;
-			continue;
-		}
-
-		ErrCode = err;
-		if (ErrCode == ERR_CorReadErr)
-			return SMSUCCESS;
-		return ERROR;
-	}
-
-	MediaChange = ERROR;
-#else
-	if (ErrCode == ERR_CorReadErr)
-		return SMSUCCESS;
-#endif
-
-	return ERROR;
-}
-
-/* SmartMedia Physical Sector Data Copy Subroutine */
-/* ----- Copy_D_BlockAll() ---------------------------------------------- */
-static int Copy_D_BlockAll(struct us_data *us, u32 mode)
-{
-	u8 sect;
-
-	sect = Media.Sector;
-
-	if (Assign_D_WriteBlock())
-		return ERROR;
-	if (mode == REQ_FAIL)
-		SectCopyMode = REQ_FAIL;
-
-	for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors;
-							Media.Sector++) {
-		if (Copy_D_PhyOneSect(us)) {
-			if (ErrCode == ERR_HwError)
-				return ERROR;
-			if (Release_D_WriteBlock(us))
-				return ERROR;
-
-			ErrCode = ERR_WriteFault;
-			Media.PhyBlock = ReadBlock;
-			Media.Sector = sect;
-
-			return ERROR;
-		}
-	}
-
-	if (Release_D_ReadBlock(us))
-		return ERROR;
-
-	Media.PhyBlock = WriteBlock;
-	Media.Sector = sect;
-	return SMSUCCESS;
-}
-
-/* SmartMedia Physical Block Assign/Release Subroutine */
-/* ----- Assign_D_WriteBlock() ------------------------------------------ */
-static int Assign_D_WriteBlock(void)
-{
-	ReadBlock = Media.PhyBlock;
-
-	for (WriteBlock = AssignStart[Media.Zone];
-			WriteBlock < Ssfdc.MaxBlocks; WriteBlock++) {
-		if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) {
-			Set_D_Bit(Assign[Media.Zone], WriteBlock);
-			AssignStart[Media.Zone] = WriteBlock + 1;
-			Media.PhyBlock = WriteBlock;
-			SectCopyMode = REQ_ERASE;
-			return SMSUCCESS;
-		}
-	}
-
-	for (WriteBlock = 0;
-			WriteBlock < AssignStart[Media.Zone]; WriteBlock++) {
-		if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) {
-			Set_D_Bit(Assign[Media.Zone], WriteBlock);
-			AssignStart[Media.Zone] = WriteBlock + 1;
-			Media.PhyBlock = WriteBlock;
-			SectCopyMode = REQ_ERASE;
-			return SMSUCCESS;
-		}
-	}
-
-	WriteBlock = NO_ASSIGN;
-	ErrCode = ERR_WriteFault;
-
-	return ERROR;
-}
-
-/* ----- Release_D_ReadBlock() ------------------------------------------ */
-static int Release_D_ReadBlock(struct us_data *us)
-{
-	u32 mode;
-
-	mode = SectCopyMode;
-	SectCopyMode = COMPLETED;
-
-	if (mode == COMPLETED)
-		return SMSUCCESS;
-
-	Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock;
-	Media.PhyBlock = ReadBlock;
-
-	if (Media.PhyBlock == NO_ASSIGN) {
-		Media.PhyBlock = WriteBlock;
-		return SMSUCCESS;
-	}
-
-	if (mode == REQ_ERASE) {
-		if (Erase_D_PhyOneBlock(us)) {
-			if (ErrCode == ERR_HwError)
-				return ERROR;
-			if (MarkFail_D_PhyOneBlock(us))
-				return ERROR;
-		} else
-			Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock);
-	} else if (MarkFail_D_PhyOneBlock(us))
-		return ERROR;
-
-	Media.PhyBlock = WriteBlock;
-	return SMSUCCESS;
-}
-
-/* ----- Release_D_WriteBlock() ----------------------------------------- */
-static int Release_D_WriteBlock(struct us_data *us)
-{
-	SectCopyMode = COMPLETED;
-	Media.PhyBlock = WriteBlock;
-
-	if (MarkFail_D_PhyOneBlock(us))
-		return ERROR;
-
-	Media.PhyBlock = ReadBlock;
-	return SMSUCCESS;
-}
-
-/* SmartMedia Physical Sector Data Copy Subroutine */
-/* ----- Copy_D_PhyOneSect() -------------------------------------------- */
-static int Copy_D_PhyOneSect(struct us_data *us)
-{
-	int           i;
-	u32  err, retry;
-
-	/* pr_info("Copy_D_PhyOneSect --- Sector = %x\n", Media.Sector); */
-	if (ReadBlock != NO_ASSIGN) {
-		Media.PhyBlock = ReadBlock;
-		for (retry = 0; retry < 2; retry++) {
-			if (retry != 0) {
-				Ssfdc_D_Reset(us);
-				if (Ssfdc_D_ReadCisSect(us, WorkBuf,
-								WorkRedund)) {
-					ErrCode = ERR_HwError;
-					MediaChange = ERROR;
-					return ERROR;
-				}
-
-				if (Check_D_CISdata(WorkBuf, WorkRedund)) {
-					ErrCode = ERR_HwError;
-					MediaChange = ERROR;
-					return ERROR;
-				}
-			}
-
-			if (Ssfdc_D_ReadSect(us, WorkBuf, WorkRedund)) {
-				ErrCode = ERR_HwError;
-				MediaChange = ERROR;
-				return ERROR;
-			}
-			if (Check_D_DataStatus(WorkRedund)) {
-				err = ERROR;
-				break;
-			}
-			if (!Check_D_ReadError(WorkRedund)) {
-				err = SMSUCCESS;
-				break;
-			}
-			if (!Check_D_Correct(WorkBuf, WorkRedund)) {
-				err = SMSUCCESS;
-				break;
-			}
-
-			err = ERROR;
-			SectCopyMode = REQ_FAIL;
-		}
-	} else {
-		err = SMSUCCESS;
-		for (i = 0; i < SECTSIZE; i++)
-			WorkBuf[i] = DUMMY_DATA;
-		Clr_D_RedundantData(WorkRedund);
-	}
-
-	Set_D_LogBlockAddr(WorkRedund);
-	if (err == ERROR) {
-		Set_D_RightECC(WorkRedund);
-		Set_D_DataStaus(WorkRedund);
-	}
-
-	Media.PhyBlock = WriteBlock;
-
-	if (Ssfdc_D_WriteSectForCopy(us, WorkBuf, WorkRedund)) {
-		ErrCode = ERR_HwError;
-		MediaChange = ERROR;
-		return ERROR;
-	}
-	if (Ssfdc_D_CheckStatus()) {
-		ErrCode = ERR_WriteFault;
-		return ERROR;
-	}
-
-	Media.PhyBlock = ReadBlock;
-	return SMSUCCESS;
-}
-
-/* SmartMedia Physical Sector Read/Write/Erase Subroutine */
-/* ----- Read_D_PhyOneSect() -------------------------------------------- */
-static int Read_D_PhyOneSect(struct us_data *us, u16 count, u8 *buf)
-{
-	int           i;
-	u32  retry;
-
-	if (Media.PhyBlock == NO_ASSIGN) {
-		for (i = 0; i < SECTSIZE; i++)
-			*buf++ = DUMMY_DATA;
-		return SMSUCCESS;
-	}
-
-	for (retry = 0; retry < 2; retry++) {
-		if (retry != 0) {
-			Ssfdc_D_Reset(us);
-
-			if (Ssfdc_D_ReadCisSect(us, WorkBuf, WorkRedund)) {
-				ErrCode = ERR_HwError;
-				MediaChange = ERROR;
-				return ERROR;
-			}
-			if (Check_D_CISdata(WorkBuf, WorkRedund)) {
-				ErrCode = ERR_HwError;
-				MediaChange = ERROR;
-				return ERROR;
-			}
-		}
-
-		if (Ssfdc_D_ReadBlock(us, count, buf, Redundant)) {
-			ErrCode = ERR_HwError;
-			MediaChange = ERROR;
-			return ERROR;
-		}
-		if (Check_D_DataStatus(Redundant)) {
-			ErrCode = ERR_DataStatus;
-			return ERROR;
-		}
-
-		if (!Check_D_ReadError(Redundant))
-			return SMSUCCESS;
-
-		if (!Check_D_Correct(buf, Redundant)) {
-			ErrCode = ERR_CorReadErr;
-			return ERROR;
-		}
-	}
-
-	ErrCode = ERR_EccReadErr;
-	return ERROR;
-}
-
-/* ----- Erase_D_PhyOneBlock() ------------------------------------------ */
-static int Erase_D_PhyOneBlock(struct us_data *us)
-{
-	if (Ssfdc_D_EraseBlock(us)) {
-		ErrCode = ERR_HwError;
-		MediaChange = ERROR;
-		return ERROR;
-	}
-	if (Ssfdc_D_CheckStatus()) {
-		ErrCode = ERR_WriteFault;
-		return ERROR;
-	}
-
-	return SMSUCCESS;
-}
-
-/* SmartMedia Physical Format Check Local Subroutine */
-/* ----- Set_D_PhyFmtValue() -------------------------------------------- */
-static int Set_D_PhyFmtValue(struct us_data *us)
-{
-	if (Set_D_SsfdcModel(us->SM_DeviceID))
-		return ERROR;
-
-	return SMSUCCESS;
-}
-
-/* ----- Search_D_CIS() ------------------------------------------------- */
-static int Search_D_CIS(struct us_data *us)
-{
-	Media.Zone = 0;
-	Media.Sector = 0;
-
-	for (Media.PhyBlock = 0;
-		Media.PhyBlock < (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1);
-		Media.PhyBlock++) {
-		if (Ssfdc_D_ReadRedtData(us, Redundant)) {
-			Ssfdc_D_Reset(us);
-			return ERROR;
-		}
-
-		if (!Check_D_FailBlock(Redundant))
-			break;
-	}
-
-	if (Media.PhyBlock == (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1)) {
-		Ssfdc_D_Reset(us);
-		return ERROR;
-	}
-
-	while (Media.Sector < CIS_SEARCH_SECT) {
-		if (Media.Sector) {
-			if (Ssfdc_D_ReadRedtData(us, Redundant)) {
-				Ssfdc_D_Reset(us);
-				return ERROR;
-			}
-		}
-		if (!Check_D_DataStatus(Redundant)) {
-			if (Ssfdc_D_ReadSect(us, WorkBuf, Redundant)) {
-				Ssfdc_D_Reset(us);
-				return ERROR;
-			}
-
-			if (Check_D_CISdata(WorkBuf, Redundant)) {
-				Ssfdc_D_Reset(us);
-				return ERROR;
-			}
-
-			CisArea.PhyBlock = Media.PhyBlock;
-			CisArea.Sector = Media.Sector;
-			Ssfdc_D_Reset(us);
-			return SMSUCCESS;
-		}
-
-		Media.Sector++;
-	}
-
-	Ssfdc_D_Reset(us);
-	return ERROR;
-}
-
-/* ----- Make_D_LogTable() ---------------------------------------------- */
-static int Make_D_LogTable(struct us_data *us)
-{
-	u16  phyblock, logblock;
-
-	if (Log2Phy[Media.Zone] == NULL) {
-		Log2Phy[Media.Zone] = kmalloc(MAX_LOGBLOCK * sizeof(u16),
-								GFP_KERNEL);
-		/* pr_info("ExAllocatePool Zone = %x, Addr = %x\n",
-				Media.Zone, Log2Phy[Media.Zone]); */
-		if (Log2Phy[Media.Zone] == NULL)
-			return ERROR;
-	}
-
-	Media.Sector = 0;
-
-	/* pr_info("Make_D_LogTable --- MediaZone = 0x%x\n",
-						Media.Zone); */
-	for (Media.LogBlock = 0; Media.LogBlock < Ssfdc.MaxLogBlocks;
-						Media.LogBlock++)
-		Log2Phy[Media.Zone][Media.LogBlock] = NO_ASSIGN;
-
-	for (Media.PhyBlock = 0; Media.PhyBlock < (MAX_BLOCKNUM / 8);
-						Media.PhyBlock++)
-		Assign[Media.Zone][Media.PhyBlock] = 0x00;
-
-	for (Media.PhyBlock = 0; Media.PhyBlock < Ssfdc.MaxBlocks;
-						Media.PhyBlock++) {
-		if ((!Media.Zone) && (Media.PhyBlock <= CisArea.PhyBlock)) {
-			Set_D_Bit(Assign[Media.Zone], Media.PhyBlock);
-			continue;
-		}
-
-		if (Ssfdc_D_ReadRedtData(us, Redundant)) {
-			Ssfdc_D_Reset(us);
-			return ERROR;
-		}
-
-		if (!Check_D_DataBlank(Redundant))
-			continue;
-
-		Set_D_Bit(Assign[Media.Zone], Media.PhyBlock);
-
-		if (Check_D_FailBlock(Redundant))
-			continue;
-
-		if (Load_D_LogBlockAddr(Redundant))
-			continue;
-
-		if (Media.LogBlock >= Ssfdc.MaxLogBlocks)
-			continue;
-
-		if (Log2Phy[Media.Zone][Media.LogBlock] == NO_ASSIGN) {
-			Log2Phy[Media.Zone][Media.LogBlock] = Media.PhyBlock;
-			continue;
-		}
-
-		phyblock     = Media.PhyBlock;
-		logblock     = Media.LogBlock;
-		Media.Sector = (u8)(Ssfdc.MaxSectors - 1);
-
-		if (Ssfdc_D_ReadRedtData(us, Redundant)) {
-			Ssfdc_D_Reset(us);
-			return ERROR;
-		}
-
-		if (!Load_D_LogBlockAddr(Redundant) &&
-				(Media.LogBlock == logblock)) {
-			Media.PhyBlock = Log2Phy[Media.Zone][logblock];
-
-			if (Ssfdc_D_ReadRedtData(us, Redundant)) {
-				Ssfdc_D_Reset(us);
-				return ERROR;
-			}
-
-			Media.PhyBlock = phyblock;
-
-			if (!Load_D_LogBlockAddr(Redundant)) {
-				if (Media.LogBlock != logblock) {
-					Media.PhyBlock =
-						Log2Phy[Media.Zone][logblock];
-					Log2Phy[Media.Zone][logblock] =
-								phyblock;
-				}
-			} else {
-				Media.PhyBlock = Log2Phy[Media.Zone][logblock];
-				Log2Phy[Media.Zone][logblock] = phyblock;
-			}
-		}
-
-		Media.Sector = 0;
-		Media.PhyBlock = phyblock;
-
-	AssignStart[Media.Zone] = 0;
-
-	} /* End for (Media.Zone<MAX_ZONENUM) */
-
-	Ssfdc_D_Reset(us);
-	return SMSUCCESS;
-}
-
-/* ----- MarkFail_D_PhyOneBlock() --------------------------------------- */
-static int MarkFail_D_PhyOneBlock(struct us_data *us)
-{
-	u8 sect;
-
-	sect = Media.Sector;
-	Set_D_FailBlock(WorkRedund);
-
-	for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors;
-							Media.Sector++) {
-		if (Ssfdc_D_WriteRedtData(us, WorkRedund)) {
-			Ssfdc_D_Reset(us);
-			Media.Sector   = sect;
-			ErrCode        = ERR_HwError;
-			MediaChange = ERROR;
-			return ERROR;
-		} /* NO Status Check */
-	}
-
-	Ssfdc_D_Reset(us);
-	Media.Sector = sect;
-	return SMSUCCESS;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smilsub.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilsub.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/smilsub.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smilsub.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,679 +0,0 @@
-#include <linux/slab.h>
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-#include "smcommon.h"
-#include "smil.h"
-
-static u8   _Check_D_DevCode(u8);
-static u32	ErrXDCode;
-static u8	IsSSFDCCompliance;
-static u8	IsXDCompliance;
-
-struct keucr_media_info         Ssfdc;
-struct keucr_media_address      Media;
-struct keucr_media_area         CisArea;
-
-static u8                            EccBuf[6];
-
-#define EVEN                    0             /* Even Page for 256byte/page */
-#define ODD                     1             /* Odd Page for 256byte/page */
-
-
-/* SmartMedia Redundant buffer data Control Subroutine
- *----- Check_D_DataBlank() --------------------------------------------
- */
-int Check_D_DataBlank(u8 *redundant)
-{
-	char i;
-
-	for (i = 0; i < REDTSIZE; i++)
-		if (*redundant++ != 0xFF)
-			return  ERROR;
-
-	return SMSUCCESS;
-}
-
-/* ----- Check_D_FailBlock() -------------------------------------------- */
-int Check_D_FailBlock(u8 *redundant)
-{
-	redundant += REDT_BLOCK;
-
-	if (*redundant == 0xFF)
-		return SMSUCCESS;
-	if (!*redundant)
-		return ERROR;
-	if (hweight8(*redundant) < 7)
-		return ERROR;
-
-	return SMSUCCESS;
-}
-
-/* ----- Check_D_DataStatus() ------------------------------------------- */
-int Check_D_DataStatus(u8 *redundant)
-{
-	redundant += REDT_DATA;
-
-	if (*redundant == 0xFF)
-		return SMSUCCESS;
-	if (!*redundant) {
-		ErrXDCode = ERR_DataStatus;
-		return ERROR;
-	} else
-		ErrXDCode = NO_ERROR;
-
-	if (hweight8(*redundant) < 5)
-		return ERROR;
-
-	return SMSUCCESS;
-}
-
-/* ----- Load_D_LogBlockAddr() ------------------------------------------ */
-int Load_D_LogBlockAddr(u8 *redundant)
-{
-	u16 addr1, addr2;
-
-	addr1 = (u16)*(redundant + REDT_ADDR1H)*0x0100 +
-					(u16)*(redundant + REDT_ADDR1L);
-	addr2 = (u16)*(redundant + REDT_ADDR2H)*0x0100 +
-					(u16)*(redundant + REDT_ADDR2L);
-
-	if (addr1 == addr2)
-		if ((addr1 & 0xF000) == 0x1000) {
-			Media.LogBlock = (addr1 & 0x0FFF) / 2;
-			return SMSUCCESS;
-		}
-
-	if (hweight16((u16)(addr1^addr2)) != 0x01)
-		return ERROR;
-
-	if ((addr1 & 0xF000) == 0x1000)
-		if (!(hweight16(addr1) & 0x01)) {
-			Media.LogBlock = (addr1 & 0x0FFF) / 2;
-			return SMSUCCESS;
-		}
-
-	if ((addr2 & 0xF000) == 0x1000)
-		if (!(hweight16(addr2) & 0x01)) {
-			Media.LogBlock = (addr2 & 0x0FFF) / 2;
-			return SMSUCCESS;
-		}
-
-	return ERROR;
-}
-
-/* ----- Clr_D_RedundantData() ------------------------------------------ */
-void Clr_D_RedundantData(u8 *redundant)
-{
-	char i;
-
-	for (i = 0; i < REDTSIZE; i++)
-		*(redundant + i) = 0xFF;
-}
-
-/* ----- Set_D_LogBlockAddr() ------------------------------------------- */
-void Set_D_LogBlockAddr(u8 *redundant)
-{
-	u16 addr;
-
-	*(redundant + REDT_BLOCK) = 0xFF;
-	*(redundant + REDT_DATA) = 0xFF;
-	addr = Media.LogBlock*2 + 0x1000;
-
-	if ((hweight16(addr) % 2))
-		addr++;
-
-	*(redundant + REDT_ADDR1H) = *(redundant + REDT_ADDR2H) =
-							(u8)(addr / 0x0100);
-	*(redundant + REDT_ADDR1L) = *(redundant + REDT_ADDR2L) = (u8)addr;
-}
-
-/*----- Set_D_FailBlock() ---------------------------------------------- */
-void Set_D_FailBlock(u8 *redundant)
-{
-	char i;
-
-	for (i = 0; i < REDTSIZE; i++)
-		*redundant++ = (u8)((i == REDT_BLOCK) ? 0xF0 : 0xFF);
-}
-
-/* ----- Set_D_DataStaus() ---------------------------------------------- */
-void Set_D_DataStaus(u8 *redundant)
-{
-	redundant += REDT_DATA;
-	*redundant = 0x00;
-}
-
-/* SmartMedia Function Command Subroutine
- * 6250 CMD 6
- */
-/* ----- Ssfdc_D_Reset() ------------------------------------------------ */
-void Ssfdc_D_Reset(struct us_data *us)
-{
-	return;
-}
-
-/* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */
-int Ssfdc_D_ReadCisSect(struct us_data *us, u8 *buf, u8 *redundant)
-{
-	u8 zone, sector;
-	u16 block;
-
-	zone = Media.Zone; block = Media.PhyBlock; sector = Media.Sector;
-	Media.Zone = 0;
-	Media.PhyBlock = CisArea.PhyBlock;
-	Media.Sector = CisArea.Sector;
-
-	if (Ssfdc_D_ReadSect(us, buf, redundant)) {
-		Media.Zone = zone;
-		Media.PhyBlock = block;
-		Media.Sector = sector;
-		return ERROR;
-	}
-
-	Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
-	return SMSUCCESS;
-}
-
-/* 6250 CMD 1 */
-/* ----- Ssfdc_D_ReadSect() --------------------------------------------- */
-int Ssfdc_D_ReadSect(struct us_data *us, u8 *buf, u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	addr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors + Media.Sector;
-
-	/* Read sect data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x02;
-	bcb->CDB[4]			= (u8)addr;
-	bcb->CDB[3]			= (u8)(addr / 0x0100);
-	bcb->CDB[2]			= Media.Zone / 2;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Read redundant */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x10;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[4]			= (u8)addr;
-	bcb->CDB[3]			= (u8)(addr / 0x0100);
-	bcb->CDB[2]			= Media.Zone / 2;
-	bcb->CDB[8]			= 0;
-	bcb->CDB[9]			= 1;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- Ssfdc_D_ReadBlock() --------------------------------------------- */
-int Ssfdc_D_ReadBlock(struct us_data *us, u16 count, u8 *buf,
-							u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	addr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors + Media.Sector;
-
-	/* Read sect data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200*count;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x02;
-	bcb->CDB[4]			= (u8)addr;
-	bcb->CDB[3]			= (u8)(addr / 0x0100);
-	bcb->CDB[2]			= Media.Zone / 2;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Read redundant */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x10;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[4]			= (u8)addr;
-	bcb->CDB[3]			= (u8)(addr / 0x0100);
-	bcb->CDB[2]			= Media.Zone / 2;
-	bcb->CDB[8]			= 0;
-	bcb->CDB[9]			= 1;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-/* ----- Ssfdc_D_CopyBlock() -------------------------------------------- */
-int Ssfdc_D_CopyBlock(struct us_data *us, u16 count, u8 *buf,
-							u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	ReadAddr, WriteAddr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	ReadAddr = (u16)Media.Zone*Ssfdc.MaxBlocks + ReadBlock;
-	ReadAddr = ReadAddr*(u16)Ssfdc.MaxSectors;
-	WriteAddr = (u16)Media.Zone*Ssfdc.MaxBlocks + WriteBlock;
-	WriteAddr = WriteAddr*(u16)Ssfdc.MaxSectors;
-
-	/* Write sect data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200*count;
-	bcb->Flags			= 0x00;
-	bcb->CDB[0]			= 0xF0;
-	bcb->CDB[1]			= 0x08;
-	bcb->CDB[7]			= (u8)WriteAddr;
-	bcb->CDB[6]			= (u8)(WriteAddr / 0x0100);
-	bcb->CDB[5]			= Media.Zone / 2;
-	bcb->CDB[8]			= *(redundant + REDT_ADDR1H);
-	bcb->CDB[9]			= *(redundant + REDT_ADDR1L);
-	bcb->CDB[10]		= Media.Sector;
-
-	if (ReadBlock != NO_ASSIGN) {
-		bcb->CDB[4]		= (u8)ReadAddr;
-		bcb->CDB[3]		= (u8)(ReadAddr / 0x0100);
-		bcb->CDB[2]		= Media.Zone / 2;
-	} else
-		bcb->CDB[11]	= 1;
-
-	result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- Ssfdc_D_WriteSectForCopy() ------------------------------------- */
-int Ssfdc_D_WriteSectForCopy(struct us_data *us, u8 *buf, u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	addr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors + Media.Sector;
-
-	/* Write sect data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x00;
-	bcb->CDB[0]			= 0xF0;
-	bcb->CDB[1]			= 0x04;
-	bcb->CDB[7]			= (u8)addr;
-	bcb->CDB[6]			= (u8)(addr / 0x0100);
-	bcb->CDB[5]			= Media.Zone / 2;
-	bcb->CDB[8]			= *(redundant + REDT_ADDR1H);
-	bcb->CDB[9]			= *(redundant + REDT_ADDR1L);
-
-	result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* 6250 CMD 5 */
-/* ----- Ssfdc_D_EraseBlock() ------------------------------------------- */
-int Ssfdc_D_EraseBlock(struct us_data *us)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	addr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF2;
-	bcb->CDB[1]			= 0x06;
-	bcb->CDB[7]			= (u8)addr;
-	bcb->CDB[6]			= (u8)(addr / 0x0100);
-	bcb->CDB[5]			= Media.Zone / 2;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* 6250 CMD 2 */
-/*----- Ssfdc_D_ReadRedtData() ----------------------------------------- */
-int Ssfdc_D_ReadRedtData(struct us_data *us, u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16	addr;
-	u8	*buf;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors + Media.Sector;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x10;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[4]			= (u8)addr;
-	bcb->CDB[3]			= (u8)(addr / 0x0100);
-	bcb->CDB[2]			= Media.Zone / 2;
-	bcb->CDB[8]			= 0;
-	bcb->CDB[9]			= 1;
-
-	buf = kmalloc(0x10, GFP_KERNEL);
-	result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
-	memcpy(redundant, buf, 0x10);
-	kfree(buf);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* 6250 CMD 4 */
-/* ----- Ssfdc_D_WriteRedtData() ---------------------------------------- */
-int Ssfdc_D_WriteRedtData(struct us_data *us, u8 *redundant)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	u16                    addr;
-
-	result = ENE_LoadBinCode(us, SM_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		dev_err(&us->pusb_dev->dev,
-			"Failed to load SmartMedia read/write code\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	addr = (u16)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
-	addr = addr*(u16)Ssfdc.MaxSectors + Media.Sector;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x10;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF2;
-	bcb->CDB[1]			= 0x05;
-	bcb->CDB[7]			= (u8)addr;
-	bcb->CDB[6]			= (u8)(addr / 0x0100);
-	bcb->CDB[5]			= Media.Zone / 2;
-	bcb->CDB[8]			= *(redundant + REDT_ADDR1H);
-	bcb->CDB[9]			= *(redundant + REDT_ADDR1L);
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- Ssfdc_D_CheckStatus() ------------------------------------------ */
-int Ssfdc_D_CheckStatus(void)
-{
-	return SMSUCCESS;
-}
-
-
-
-/* SmartMedia ID Code Check & Mode Set Subroutine
- * ----- Set_D_SsfdcModel() ---------------------------------------------
- */
-int Set_D_SsfdcModel(u8 dcode)
-{
-	switch (_Check_D_DevCode(dcode)) {
-	case SSFDC1MB:
-		Ssfdc.Model        = SSFDC1MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
-		Ssfdc.MaxZones     = 1;
-		Ssfdc.MaxBlocks    = 256;
-		Ssfdc.MaxLogBlocks = 250;
-		Ssfdc.MaxSectors   = 8;
-		break;
-	case SSFDC2MB:
-		Ssfdc.Model        = SSFDC2MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
-		Ssfdc.MaxZones     = 1;
-		Ssfdc.MaxBlocks    = 512;
-		Ssfdc.MaxLogBlocks = 500;
-		Ssfdc.MaxSectors   = 8;
-		break;
-	case SSFDC4MB:
-		Ssfdc.Model        = SSFDC4MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
-		Ssfdc.MaxZones     = 1;
-		Ssfdc.MaxBlocks    = 512;
-		Ssfdc.MaxLogBlocks = 500;
-		Ssfdc.MaxSectors   = 16;
-		break;
-	case SSFDC8MB:
-		Ssfdc.Model        = SSFDC8MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
-		Ssfdc.MaxZones     = 1;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 16;
-		break;
-	case SSFDC16MB:
-		Ssfdc.Model        = SSFDC16MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 1;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC32MB:
-		Ssfdc.Model        = SSFDC32MB;
-		Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 2;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC64MB:
-		Ssfdc.Model        = SSFDC64MB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 4;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC128MB:
-		Ssfdc.Model        = SSFDC128MB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 8;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC256MB:
-		Ssfdc.Model        = SSFDC256MB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 16;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC512MB:
-		Ssfdc.Model        = SSFDC512MB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 32;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC1GB:
-		Ssfdc.Model        = SSFDC1GB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 64;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	case SSFDC2GB:
-		Ssfdc.Model        = SSFDC2GB;
-		Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
-		Ssfdc.MaxZones     = 128;
-		Ssfdc.MaxBlocks    = 1024;
-		Ssfdc.MaxLogBlocks = 1000;
-		Ssfdc.MaxSectors   = 32;
-		break;
-	default:
-		Ssfdc.Model = NOSSFDC;
-		return ERROR;
-	}
-
-	return SMSUCCESS;
-}
-
-/* ----- _Check_D_DevCode() --------------------------------------------- */
-static u8 _Check_D_DevCode(u8 dcode)
-{
-	switch (dcode) {
-	case 0x6E:
-	case 0xE8:
-	case 0xEC: return SSFDC1MB;   /* 8Mbit (1M) NAND */
-	case 0x64:
-	case 0xEA: return SSFDC2MB;   /* 16Mbit (2M) NAND */
-	case 0x6B:
-	case 0xE3:
-	case 0xE5: return SSFDC4MB;   /* 32Mbit (4M) NAND */
-	case 0xE6: return SSFDC8MB;   /* 64Mbit (8M) NAND */
-	case 0x73: return SSFDC16MB;  /* 128Mbit (16M)NAND */
-	case 0x75: return SSFDC32MB;  /* 256Mbit (32M)NAND */
-	case 0x76: return SSFDC64MB;  /* 512Mbit (64M)NAND */
-	case 0x79: return SSFDC128MB; /* 1Gbit(128M)NAND */
-	case 0x71: return SSFDC256MB;
-	case 0xDC: return SSFDC512MB;
-	case 0xD3: return SSFDC1GB;
-	case 0xD5: return SSFDC2GB;
-	default: return NOSSFDC;
-	}
-}
-
-
-
-
-/* SmartMedia ECC Control Subroutine
- * ----- Check_D_ReadError() ----------------------------------------------
- */
-int Check_D_ReadError(u8 *redundant)
-{
-	return SMSUCCESS;
-}
-
-/* ----- Check_D_Correct() ---------------------------------------------- */
-int Check_D_Correct(u8 *buf, u8 *redundant)
-{
-	return SMSUCCESS;
-}
-
-/* ----- Check_D_CISdata() ---------------------------------------------- */
-int Check_D_CISdata(u8 *buf, u8 *redundant)
-{
-	u8 cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
-		      0xDF, 0x01, 0x20};
-
-	int cis_len = sizeof(cis);
-
-	if (!IsSSFDCCompliance && !IsXDCompliance)
-		return SMSUCCESS;
-
-	if (!memcmp(redundant + 0x0D, EccBuf, 3))
-		return memcmp(buf, cis, cis_len);
-
-	if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
-		return memcmp(buf, cis, cis_len);
-
-	buf += 0x100;
-	if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
-		return memcmp(buf, cis, cis_len);
-
-	if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
-		return memcmp(buf, cis, cis_len);
-
-	return ERROR;
-}
-
-/* ----- Set_D_RightECC() ---------------------------------------------- */
-void Set_D_RightECC(u8 *redundant)
-{
-	/* Driver ECC Check */
-	return;
-}
-
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/smscsi.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smscsi.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/smscsi.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/smscsi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,194 +0,0 @@
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-#include "smil.h"
-
-static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb);
-static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb);
-static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb);
-static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb);
-static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb);
-static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb);
-
-/* ----- SM_SCSIIrp() -------------------------------------------------- */
-int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
-{
-	int    result;
-
-	us->SrbStatus = SS_SUCCESS;
-	switch (srb->cmnd[0]) {
-	case TEST_UNIT_READY:
-		result = SM_SCSI_Test_Unit_Ready(us, srb);
-		break;		/* 0x00 */
-	case INQUIRY:
-		result = SM_SCSI_Inquiry(us, srb);
-		break;		/* 0x12 */
-	case MODE_SENSE:
-		result = SM_SCSI_Mode_Sense(us, srb);
-		break;		/* 0x1A */
-	case READ_CAPACITY:
-		result = SM_SCSI_Read_Capacity(us, srb);
-		break;		/* 0x25 */
-	case READ_10:
-		result = SM_SCSI_Read(us, srb);
-		break;		/* 0x28 */
-	case WRITE_10:
-		result = SM_SCSI_Write(us, srb);
-		break;		/* 0x2A */
-
-	default:
-			us->SrbStatus = SS_ILLEGAL_REQUEST;
-			result = USB_STOR_TRANSPORT_FAILED;
-			break;
-	}
-	return result;
-}
-
-/* ----- SM_SCSI_Test_Unit_Ready() ------------------------------------- */
-static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
-{
-	if (us->SM_Status.Insert && us->SM_Status.Ready)
-		return USB_STOR_TRANSPORT_GOOD;
-	else {
-		ENE_SMInit(us);
-		return USB_STOR_TRANSPORT_GOOD;
-	}
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- SM_SCSI_Inquiry() --------------------------------------------- */
-static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
-{
-	u8 data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00,
-				 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20,
-				 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65,
-				 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20,
-				 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
-
-	usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-/* ----- SM_SCSI_Mode_Sense() ------------------------------------------ */
-static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
-{
-	u8	mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
-				0x71, 0xc0, 0x00, 0x00, 0x02, 0x00};
-	u8	mediaWP[12]   = {0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
-				0x71, 0xc0, 0x00, 0x00, 0x02, 0x00};
-
-	if (us->SM_Status.WtP)
-		usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
-	else
-		usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
-
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- SM_SCSI_Read_Capacity() --------------------------------------- */
-static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
-{
-	unsigned int offset = 0;
-	struct scatterlist *sg = NULL;
-	u32   bl_num;
-	u16    bl_len;
-	u8    buf[8];
-
-	dev_dbg(&us->pusb_dev->dev, "SM_SCSI_Read_Capacity\n");
-
-	bl_len = 0x200;
-	bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1;
-
-	us->bl_num = bl_num;
-	dev_dbg(&us->pusb_dev->dev, "bl_len = %x\n", bl_len);
-	dev_dbg(&us->pusb_dev->dev, "bl_num = %x\n", bl_num);
-
-	buf[0] = (bl_num >> 24) & 0xff;
-	buf[1] = (bl_num >> 16) & 0xff;
-	buf[2] = (bl_num >> 8) & 0xff;
-	buf[3] = (bl_num >> 0) & 0xff;
-	buf[4] = (bl_len >> 24) & 0xff;
-	buf[5] = (bl_len >> 16) & 0xff;
-	buf[6] = (bl_len >> 8) & 0xff;
-	buf[7] = (bl_len >> 0) & 0xff;
-
-	usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- SM_SCSI_Read() -------------------------------------------------- */
-static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
-{
-	int result = 0;
-	u8 *Cdb = srb->cmnd;
-	u32 bn  =  ((Cdb[2] << 24) & 0xff000000) |
-			((Cdb[3] << 16) & 0x00ff0000) |
-			((Cdb[4] << 8) & 0x0000ff00) |
-			((Cdb[5] << 0) & 0x000000ff);
-	u16  blen = ((Cdb[7] << 8) & 0xff00)     | ((Cdb[8] << 0) & 0x00ff);
-	u32	blenByte = blen * 0x200;
-	void	*buf;
-
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	buf = kmalloc(blenByte, GFP_KERNEL);
-	if (buf == NULL)
-		return USB_STOR_TRANSPORT_ERROR;
-	result = Media_D_ReadSector(us, bn, blen, buf);
-	usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
-	kfree(buf);
-
-	if (!result)
-		return USB_STOR_TRANSPORT_GOOD;
-	else
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* ----- SM_SCSI_Write() -------------------------------------------------- */
-static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
-{
-	int result = 0;
-	u8 *Cdb = srb->cmnd;
-	u32 bn  =  ((Cdb[2] << 24) & 0xff000000) |
-			((Cdb[3] << 16) & 0x00ff0000) |
-			((Cdb[4] << 8) & 0x0000ff00) |
-			((Cdb[5] << 0) & 0x000000ff);
-	u16  blen = ((Cdb[7] << 8) & 0xff00)     | ((Cdb[8] << 0) & 0x00ff);
-	u32	blenByte = blen * 0x200;
-	void	*buf;
-
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	buf = kmalloc(blenByte, GFP_KERNEL);
-	if (buf == NULL)
-		return USB_STOR_TRANSPORT_ERROR;
-	usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
-	result = Media_D_CopySector(us, bn, blen, buf);
-	kfree(buf);
-
-	if (!result)
-		return USB_STOR_TRANSPORT_GOOD;
-	else
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/TODO linux-libre-3.17-rc7-gnu/drivers/staging/keucr/TODO
--- linux-libre-3.16-gnu/drivers/staging/keucr/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-TODO:
-	- checkpatch.pl clean
-	- sparse clean
-	- determine if the driver should not be using a duplicate
-	  version of the usb-storage scsi interface code, but should
-	  be merged into the drivers/usb/storage/ directory and
-	  infrastructure instead.
-	- review by the USB developer community
-	- smcommon.h & smilsub.c: use kernel hweight8(), hweight16()
-
-Please send any patches for this driver to Al Cho <acho@novell.com> and
-Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/transport.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/transport.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/transport.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/transport.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,865 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-/***********************************************************************
- * Data transfer routines
- ***********************************************************************/
-/*
- * usb_stor_blocking_completion()
- */
-static void usb_stor_blocking_completion(struct urb *urb)
-{
-	struct completion *urb_done_ptr = urb->context;
-
-	/* pr_info("transport --- usb_stor_blocking_completion\n"); */
-	complete(urb_done_ptr);
-}
-
-/*
- * usb_stor_msg_common()
- */
-static int usb_stor_msg_common(struct us_data *us, int timeout)
-{
-	struct completion urb_done;
-	long timeleft;
-	int status;
-
-	/* pr_info("transport --- usb_stor_msg_common\n"); */
-	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
-		return -EIO;
-
-	init_completion(&urb_done);
-
-	us->current_urb->context = &urb_done;
-	us->current_urb->actual_length = 0;
-	us->current_urb->error_count = 0;
-	us->current_urb->status = 0;
-
-	us->current_urb->transfer_flags = 0;
-	if (us->current_urb->transfer_buffer == us->iobuf)
-		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	us->current_urb->transfer_dma = us->iobuf_dma;
-	us->current_urb->setup_dma = us->cr_dma;
-
-	status = usb_submit_urb(us->current_urb, GFP_NOIO);
-	if (status)
-		return status;
-
-	set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
-
-	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
-		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
-			/* pr_info("-- cancelling URB\n"); */
-			usb_unlink_urb(us->current_urb);
-		}
-	}
-
-	timeleft = wait_for_completion_interruptible_timeout(&urb_done,
-					timeout ? : MAX_SCHEDULE_TIMEOUT);
-	clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
-
-	if (timeleft <= 0) {
-		/* pr_info("%s -- cancelling URB\n",
-			timeleft == 0 ? "Timeout" : "Signal"); */
-		usb_kill_urb(us->current_urb);
-	}
-
-	return us->current_urb->status;
-}
-
-/*
- * usb_stor_print_cmd():
- */
-static void usb_stor_print_cmd(struct us_data *us, struct scsi_cmnd *srb)
-{
-	u8 *Cdb = srb->cmnd;
-	u32   cmd = Cdb[0];
-
-	switch (cmd) {
-	case TEST_UNIT_READY:
-		break;
-	case INQUIRY:
-		dev_dbg(&us->pusb_dev->dev,
-				"scsi cmd %X --- SCSIOP_INQUIRY\n", cmd);
-		break;
-	case MODE_SENSE:
-		dev_dbg(&us->pusb_dev->dev,
-				"scsi cmd %X --- SCSIOP_MODE_SENSE\n", cmd);
-		break;
-	case START_STOP:
-		dev_dbg(&us->pusb_dev->dev,
-				"scsi cmd %X --- SCSIOP_START_STOP\n", cmd);
-		break;
-	case READ_CAPACITY:
-		dev_dbg(&us->pusb_dev->dev,
-				"scsi cmd %X --- SCSIOP_READ_CAPACITY\n", cmd);
-		break;
-	case READ_10:
-		break;
-	case WRITE_10:
-		break;
-	case ALLOW_MEDIUM_REMOVAL:
-		dev_dbg(&us->pusb_dev->dev,
-			"scsi cmd %X --- SCSIOP_ALLOW_MEDIUM_REMOVAL\n", cmd);
-		break;
-	default:
-		dev_dbg(&us->pusb_dev->dev, "scsi cmd %X --- Other cmd\n", cmd);
-		break;
-	}
-}
-
-/*
- * usb_stor_control_msg()
- */
-int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
-		 u8 request, u8 requesttype, u16 value, u16 index,
-		 void *data, u16 size, int timeout)
-{
-	int status;
-
-	/* pr_info("transport --- usb_stor_control_msg\n"); */
-
-	/* fill in the devrequest structure */
-	us->cr->bRequestType = requesttype;
-	us->cr->bRequest = request;
-	us->cr->wValue = cpu_to_le16(value);
-	us->cr->wIndex = cpu_to_le16(index);
-	us->cr->wLength = cpu_to_le16(size);
-
-	/* fill and submit the URB */
-	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
-			 (unsigned char *) us->cr, data, size,
-			 usb_stor_blocking_completion, NULL);
-	status = usb_stor_msg_common(us, timeout);
-
-	/* return the actual length of the data transferred if no error */
-	if (status == 0)
-		status = us->current_urb->actual_length;
-	return status;
-}
-
-/*
- * usb_stor_clear_halt()
- */
-int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
-{
-	int result;
-	int endp = usb_pipeendpoint(pipe);
-
-	/* pr_info("transport --- usb_stor_clear_halt\n"); */
-	if (usb_pipein(pipe))
-		endp |= USB_DIR_IN;
-
-	result = usb_stor_control_msg(us, us->send_ctrl_pipe,
-		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
-		USB_ENDPOINT_HALT, endp,
-		NULL, 0, 3*HZ);
-
-	/* reset the endpoint toggle */
-	if (result >= 0)
-		/* usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
-						usb_pipeout(pipe), 0); */
-		usb_reset_endpoint(us->pusb_dev, endp);
-
-	return result;
-}
-
-/*
- * interpret_urb_result()
- */
-static int interpret_urb_result(struct us_data *us, unsigned int pipe,
-		unsigned int length, int result, unsigned int partial)
-{
-	/* pr_info("transport --- interpret_urb_result\n"); */
-	switch (result) {
-	/* no error code; did we send all the data? */
-	case 0:
-		if (partial != length) {
-			/* pr_info("-- short transfer\n"); */
-			return USB_STOR_XFER_SHORT;
-		}
-		/* pr_info("-- transfer complete\n"); */
-		return USB_STOR_XFER_GOOD;
-	case -EPIPE:
-		if (usb_pipecontrol(pipe)) {
-			/* pr_info("-- stall on control pipe\n"); */
-			return USB_STOR_XFER_STALLED;
-		}
-		/* pr_info("clearing endpoint halt for pipe 0x%x\n", pipe); */
-		if (usb_stor_clear_halt(us, pipe) < 0)
-			return USB_STOR_XFER_ERROR;
-		return USB_STOR_XFER_STALLED;
-	case -EOVERFLOW:
-		/* pr_info("-- babble\n"); */
-		return USB_STOR_XFER_LONG;
-	case -ECONNRESET:
-		/* pr_info("-- transfer cancelled\n"); */
-		return USB_STOR_XFER_ERROR;
-	case -EREMOTEIO:
-		/* pr_info("-- short read transfer\n"); */
-		return USB_STOR_XFER_SHORT;
-	case -EIO:
-		/* pr_info("-- abort or disconnect in progress\n"); */
-		return USB_STOR_XFER_ERROR;
-	default:
-		/* pr_info("-- unknown error\n"); */
-		return USB_STOR_XFER_ERROR;
-	}
-}
-
-/*
- * usb_stor_bulk_transfer_buf()
- */
-int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
-	void *buf, unsigned int length, unsigned int *act_len)
-{
-	int result;
-
-	/* pr_info("transport --- usb_stor_bulk_transfer_buf\n"); */
-
-	/* fill and submit the URB */
-	usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf,
-				length, usb_stor_blocking_completion, NULL);
-	result = usb_stor_msg_common(us, 0);
-
-	/* store the actual length of the data transferred */
-	if (act_len)
-		*act_len = us->current_urb->actual_length;
-
-	return interpret_urb_result(us, pipe, length, result,
-					us->current_urb->actual_length);
-}
-
-/*
- * usb_stor_bulk_transfer_sglist()
- */
-static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
-		struct scatterlist *sg, int num_sg, unsigned int length,
-		unsigned int *act_len)
-{
-	int result;
-
-	/* pr_info("transport --- usb_stor_bulk_transfer_sglist\n"); */
-	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
-		return USB_STOR_XFER_ERROR;
-
-	/* initialize the scatter-gather request block */
-	result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
-					sg, num_sg, length, GFP_NOIO);
-	if (result) {
-		/* pr_info("usb_sg_init returned %d\n", result); */
-		return USB_STOR_XFER_ERROR;
-	}
-
-	/* since the block has been initialized successfully,
-					it's now okay to cancel it */
-	set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
-
-	/* did an abort/disconnect occur during the submission? */
-	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
-		/* cancel the request, if it hasn't been cancelled already */
-		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
-			/* pr_info("-- cancelling sg request\n"); */
-			usb_sg_cancel(&us->current_sg);
-		}
-	}
-
-	/* wait for the completion of the transfer */
-	usb_sg_wait(&us->current_sg);
-	clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
-
-	result = us->current_sg.status;
-	if (act_len)
-		*act_len = us->current_sg.bytes;
-
-	return interpret_urb_result(us, pipe, length,
-					result, us->current_sg.bytes);
-}
-
-/*
- * usb_stor_bulk_srb()
- */
-int usb_stor_bulk_srb(struct us_data *us, unsigned int pipe,
-					struct scsi_cmnd *srb)
-{
-	unsigned int partial;
-	int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb),
-				      scsi_sg_count(srb), scsi_bufflen(srb),
-				      &partial);
-
-	scsi_set_resid(srb, scsi_bufflen(srb) - partial);
-	return result;
-}
-
-/*
- * usb_stor_bulk_transfer_sg()
- */
-int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
-		void *buf, unsigned int length_left, int use_sg, int *residual)
-{
-	int result;
-	unsigned int partial;
-
-	/* pr_info("transport --- usb_stor_bulk_transfer_sg\n"); */
-	/* are we scatter-gathering? */
-	if (use_sg) {
-		/* use the usb core scatter-gather primitives */
-		result = usb_stor_bulk_transfer_sglist(us, pipe,
-				(struct scatterlist *) buf, use_sg,
-				length_left, &partial);
-		length_left -= partial;
-	} else {
-		/* no scatter-gather, just make the request */
-		result = usb_stor_bulk_transfer_buf(us, pipe, buf,
-							length_left, &partial);
-		length_left -= partial;
-	}
-
-	/* store the residual and return the error code */
-	if (residual)
-		*residual = length_left;
-	return result;
-}
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-/*
- * usb_stor_invoke_transport()
- */
-void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
-{
-	int need_auto_sense;
-	int result;
-
-	/* pr_info("transport --- usb_stor_invoke_transport\n"); */
-	usb_stor_print_cmd(us, srb);
-	/* send the command to the transport layer */
-	scsi_set_resid(srb, 0);
-	result = us->transport(srb, us); /* usb_stor_Bulk_transport; */
-
-	/* if the command gets aborted by the higher layers,
-		we need to short-circuit all other processing */
-	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-		/* pr_info("-- command was aborted\n"); */
-		srb->result = DID_ABORT << 16;
-		goto Handle_Errors;
-	}
-
-	/* if there is a transport error, reset and don't auto-sense */
-	if (result == USB_STOR_TRANSPORT_ERROR) {
-		/* pr_info("-- transport indicates error, resetting\n"); */
-		srb->result = DID_ERROR << 16;
-		goto Handle_Errors;
-	}
-
-	/* if the transport provided its own sense data, don't auto-sense */
-	if (result == USB_STOR_TRANSPORT_NO_SENSE) {
-		srb->result = SAM_STAT_CHECK_CONDITION;
-		return;
-	}
-
-	srb->result = SAM_STAT_GOOD;
-
-	/* Determine if we need to auto-sense */
-	need_auto_sense = 0;
-
-	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
-				srb->sc_data_direction != DMA_FROM_DEVICE) {
-		/* pr_info("-- CB transport device requiring auto-sense\n"); */
-		need_auto_sense = 1;
-	}
-
-	if (result == USB_STOR_TRANSPORT_FAILED) {
-		/* pr_info("-- transport indicates command failure\n"); */
-		need_auto_sense = 1;
-	}
-
-	/* Now, if we need to do the auto-sense, let's do it */
-	if (need_auto_sense) {
-		int temp_result;
-		struct scsi_eh_save ses;
-
-		pr_info("Issuing auto-REQUEST_SENSE\n");
-
-		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
-
-		/* we must do the protocol translation here */
-		if (us->subclass == USB_SC_RBC ||
-			us->subclass == USB_SC_SCSI ||
-			us->subclass == USB_SC_CYP_ATACB) {
-			srb->cmd_len = 6;
-		} else {
-			srb->cmd_len = 12;
-		}
-		/* issue the auto-sense command */
-		scsi_set_resid(srb, 0);
-		temp_result = us->transport(us->srb, us);
-
-		/* let's clean up right away */
-		scsi_eh_restore_cmnd(srb, &ses);
-
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-			/* pr_info("-- auto-sense aborted\n"); */
-			srb->result = DID_ABORT << 16;
-			goto Handle_Errors;
-		}
-		if (temp_result != USB_STOR_TRANSPORT_GOOD) {
-			/* pr_info("-- auto-sense failure\n"); */
-			srb->result = DID_ERROR << 16;
-			if (!(us->fflags & US_FL_SCM_MULT_TARG))
-				goto Handle_Errors;
-			return;
-		}
-
-		/* set the result so the higher layers expect this data */
-		srb->result = SAM_STAT_CHECK_CONDITION;
-
-		if (result == USB_STOR_TRANSPORT_GOOD &&
-			(srb->sense_buffer[2] & 0xaf) == 0 &&
-			srb->sense_buffer[12] == 0 &&
-			srb->sense_buffer[13] == 0) {
-			srb->result = SAM_STAT_GOOD;
-			srb->sense_buffer[0] = 0x0;
-		}
-	}
-
-	/* Did we transfer less than the minimum amount required? */
-	if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) -
-				scsi_get_resid(srb) < srb->underflow)
-		srb->result = (DID_ERROR << 16);
-		/* v02 | (SUGGEST_RETRY << 24); */
-
-	return;
-
-Handle_Errors:
-	scsi_lock(us_to_host(us));
-	set_bit(US_FLIDX_RESETTING, &us->dflags);
-	clear_bit(US_FLIDX_ABORTING, &us->dflags);
-	scsi_unlock(us_to_host(us));
-
-	mutex_unlock(&us->dev_mutex);
-	result = usb_stor_port_reset(us);
-	mutex_lock(&us->dev_mutex);
-
-	if (result < 0) {
-		scsi_lock(us_to_host(us));
-		usb_stor_report_device_reset(us);
-		scsi_unlock(us_to_host(us));
-		us->transport_reset(us);
-	}
-	clear_bit(US_FLIDX_RESETTING, &us->dflags);
-}
-
-/*
- * ENE_stor_invoke_transport()
- */
-void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
-{
-	int result = 0;
-
-	/* pr_info("transport --- ENE_stor_invoke_transport\n"); */
-	usb_stor_print_cmd(us, srb);
-	/* send the command to the transport layer */
-	scsi_set_resid(srb, 0);
-	if (!(us->SM_Status.Ready))
-		result = ENE_InitMedia(us);
-
-	if (us->Power_IsResum == true) {
-		result = ENE_InitMedia(us);
-		us->Power_IsResum = false;
-	}
-
-	if (us->SM_Status.Ready)
-		result = SM_SCSIIrp(us, srb);
-
-	/* if the command gets aborted by the higher layers,
-		we need to short-circuit all other processing */
-	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-		/* pr_info("-- command was aborted\n"); */
-		srb->result = DID_ABORT << 16;
-		goto Handle_Errors;
-	}
-
-	/* if there is a transport error, reset and don't auto-sense */
-	if (result == USB_STOR_TRANSPORT_ERROR) {
-		/* pr_info("-- transport indicates error, resetting\n"); */
-		srb->result = DID_ERROR << 16;
-		goto Handle_Errors;
-	}
-
-	/* if the transport provided its own sense data, don't auto-sense */
-	if (result == USB_STOR_TRANSPORT_NO_SENSE) {
-		srb->result = SAM_STAT_CHECK_CONDITION;
-		return;
-	}
-
-	srb->result = SAM_STAT_GOOD;
-	if (result == USB_STOR_TRANSPORT_FAILED) {
-		/* pr_info("-- transport indicates command failure\n"); */
-		/* need_auto_sense = 1; */
-		BuildSenseBuffer(srb, us->SrbStatus);
-		srb->result = SAM_STAT_CHECK_CONDITION;
-	}
-
-	/* Did we transfer less than the minimum amount required? */
-	if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) -
-					scsi_get_resid(srb) < srb->underflow)
-		srb->result = (DID_ERROR << 16);
-		/* v02 | (SUGGEST_RETRY << 24); */
-
-	return;
-
-Handle_Errors:
-	scsi_lock(us_to_host(us));
-	set_bit(US_FLIDX_RESETTING, &us->dflags);
-	clear_bit(US_FLIDX_ABORTING, &us->dflags);
-	scsi_unlock(us_to_host(us));
-
-	mutex_unlock(&us->dev_mutex);
-	result = usb_stor_port_reset(us);
-	mutex_lock(&us->dev_mutex);
-
-	if (result < 0) {
-		scsi_lock(us_to_host(us));
-		usb_stor_report_device_reset(us);
-		scsi_unlock(us_to_host(us));
-		us->transport_reset(us);
-	}
-	clear_bit(US_FLIDX_RESETTING, &us->dflags);
-}
-
-/*
- * BuildSenseBuffer()
- */
-void BuildSenseBuffer(struct scsi_cmnd *srb, int SrbStatus)
-{
-	u8    *buf = srb->sense_buffer;
-	u8    asc;
-
-	pr_info("transport --- BuildSenseBuffer\n");
-	switch (SrbStatus) {
-	case SS_NOT_READY:
-		asc = 0x3a;
-		break;  /*  sense key = 0x02 */
-	case SS_MEDIUM_ERR:
-		asc = 0x0c;
-		break;  /*  sense key = 0x03 */
-	case SS_ILLEGAL_REQUEST:
-		asc = 0x20;
-		break;  /*  sense key = 0x05 */
-	default:
-		asc = 0x00;
-		break;  /*  ?? */
-	}
-
-	memset(buf, 0, 18);
-	buf[0x00] = 0xf0;
-	buf[0x02] = SrbStatus;
-	buf[0x07] = 0x0b;
-	buf[0x0c] = asc;
-}
-
-/*
- * usb_stor_stop_transport()
- */
-void usb_stor_stop_transport(struct us_data *us)
-{
-	/* pr_info("transport --- usb_stor_stop_transport\n"); */
-
-	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
-		/* pr_info("-- cancelling URB\n"); */
-		usb_unlink_urb(us->current_urb);
-	}
-
-	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
-		/* pr_info("-- cancelling sg request\n"); */
-		usb_sg_cancel(&us->current_sg);
-	}
-}
-
-/*
- * usb_stor_Bulk_max_lun()
- */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
-	int result;
-
-	/* pr_info("transport --- usb_stor_Bulk_max_lun\n"); */
-	/* issue the command */
-	us->iobuf[0] = 0;
-	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
-				 US_BULK_GET_MAX_LUN,
-				 USB_DIR_IN | USB_TYPE_CLASS |
-				 USB_RECIP_INTERFACE,
-				 0, us->ifnum, us->iobuf, 1, HZ);
-
-	/* pr_info("GetMaxLUN command result is %d, data is %d\n",
-						result, us->iobuf[0]); */
-
-	/* if we have a successful request, return the result */
-	if (result > 0)
-		return us->iobuf[0];
-
-	return 0;
-}
-
-/*
- * usb_stor_Bulk_transport()
- */
-int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
-	unsigned int transfer_length = scsi_bufflen(srb);
-	unsigned int residue;
-	int result;
-	int fake_sense = 0;
-	unsigned int cswlen;
-	unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
-
-	/* pr_info("transport --- usb_stor_Bulk_transport\n"); */
-	/* Take care of BULK32 devices; set extra byte to 0 */
-	if (unlikely(us->fflags & US_FL_BULK32)) {
-		cbwlen = 32;
-		us->iobuf[31] = 0;
-	}
-
-	/* set up the command wrapper */
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = cpu_to_le32(transfer_length);
-	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
-	bcb->Tag = ++us->tag;
-	bcb->Lun = srb->device->lun;
-	if (us->fflags & US_FL_SCM_MULT_TARG)
-		bcb->Lun |= srb->device->id << 4;
-	bcb->Length = srb->cmd_len;
-
-	/* copy the command payload */
-	memset(bcb->CDB, 0, sizeof(bcb->CDB));
-	memcpy(bcb->CDB, srb->cmnd, bcb->Length);
-
-	/*  send command */
-	/* send it to out endpoint */
-	/* pr_info("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
-			le32_to_cpu(bcb->Signature), bcb->Tag,
-			le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
-			(bcb->Lun >> 4), (bcb->Lun & 0x0F),
-			bcb->Length); */
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-						bcb, cbwlen, NULL);
-	/* pr_info("Bulk command transfer result=%d\n", result); */
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	if (unlikely(us->fflags & US_FL_GO_SLOW))
-		udelay(125);
-
-	/*  R/W data */
-	if (transfer_length) {
-		unsigned int pipe;
-
-		if (srb->sc_data_direction == DMA_FROM_DEVICE)
-			pipe = us->recv_bulk_pipe;
-		else
-			pipe = us->send_bulk_pipe;
-
-		result = usb_stor_bulk_srb(us, pipe, srb);
-		/* pr_info("Bulk data transfer result 0x%x\n", result); */
-		if (result == USB_STOR_XFER_ERROR)
-			return USB_STOR_TRANSPORT_ERROR;
-
-		if (result == USB_STOR_XFER_LONG)
-			fake_sense = 1;
-	}
-
-	/* get CSW for device status */
-	/* pr_info("Attempting to get CSW...\n"); */
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, &cswlen);
-
-	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
-		/* pr_info("Received 0-length CSW; retrying...\n"); */
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, &cswlen);
-	}
-
-	/* did the attempt to read the CSW fail? */
-	if (result == USB_STOR_XFER_STALLED) {
-		/* get the status again */
-		/* pr_info("Attempting to get CSW (2nd try)...\n"); */
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
-						US_BULK_CS_WRAP_LEN, NULL);
-	}
-
-	/* if we still have a failure at this point, we're in trouble */
-	/* pr_info("Bulk status result = %d\n", result); */
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* check bulk status */
-	residue = le32_to_cpu(bcs->Residue);
-	/* pr_info("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
-				le32_to_cpu(bcs->Signature),
-				bcs->Tag, residue, bcs->Status); */
-	if (!(bcs->Tag == us->tag ||
-		(us->fflags & US_FL_BULK_IGNORE_TAG)) ||
-		bcs->Status > US_BULK_STAT_PHASE) {
-		/* pr_info("Bulk logical error\n"); */
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	if (!us->bcs_signature) {
-		us->bcs_signature = bcs->Signature;
-		/* if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN)) */
-		/* pr_info("Learnt BCS signature 0x%08X\n",
-				le32_to_cpu(us->bcs_signature)); */
-	} else if (bcs->Signature != us->bcs_signature) {
-		/* pr_info("Signature mismatch: got %08X, expecting %08X\n",
-			  le32_to_cpu(bcs->Signature),
-			  le32_to_cpu(us->bcs_signature)); */
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	/* try to compute the actual residue, based on how much data
-	 * was really transferred and what the device tells us */
-	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
-
-		/* Heuristically detect devices that generate bogus residues
-		 * by seeing what happens with INQUIRY and READ CAPACITY
-		 * commands.
-		 */
-		if (bcs->Status == US_BULK_STAT_OK &&
-				scsi_get_resid(srb) == 0 &&
-					((srb->cmnd[0] == INQUIRY &&
-						transfer_length == 36) ||
-					(srb->cmnd[0] == READ_CAPACITY &&
-						transfer_length == 8))) {
-			us->fflags |= US_FL_IGNORE_RESIDUE;
-
-		} else {
-			residue = min(residue, transfer_length);
-			scsi_set_resid(srb, max_t(int, scsi_get_resid(srb),
-							residue));
-		}
-	}
-
-	/* based on the status code, we report good or bad */
-	switch (bcs->Status) {
-	case US_BULK_STAT_OK:
-		if (fake_sense) {
-			memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB,
-					sizeof(usb_stor_sense_invalidCDB));
-			return USB_STOR_TRANSPORT_NO_SENSE;
-		}
-		return USB_STOR_TRANSPORT_GOOD;
-
-	case US_BULK_STAT_FAIL:
-		return USB_STOR_TRANSPORT_FAILED;
-
-	case US_BULK_STAT_PHASE:
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-	return USB_STOR_TRANSPORT_ERROR;
-}
-
-/***********************************************************************
- * Reset routines
- ***********************************************************************/
-/*
- * usb_stor_reset_common()
- */
-static int usb_stor_reset_common(struct us_data *us,
-		u8 request, u8 requesttype,
-		u16 value, u16 index, void *data, u16 size)
-{
-	int result;
-	int result2;
-
-	/* pr_info("transport --- usb_stor_reset_common\n"); */
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-		/* pr_info("No reset during disconnect\n"); */
-		return -EIO;
-	}
-
-	result = usb_stor_control_msg(us, us->send_ctrl_pipe,
-			request, requesttype, value, index, data, size,	5*HZ);
-
-	if (result < 0) {
-		/* pr_info("Soft reset failed: %d\n", result); */
-		return result;
-	}
-
-	wait_event_interruptible_timeout(us->delay_wait,
-			test_bit(US_FLIDX_DISCONNECTING, &us->dflags),	HZ*6);
-
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-		/* pr_info("Reset interrupted by disconnect\n"); */
-		return -EIO;
-	}
-
-	/* pr_info("Soft reset: clearing bulk-in endpoint halt\n"); */
-	result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
-
-	/* pr_info("Soft reset: clearing bulk-out endpoint halt\n"); */
-	result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
-
-	/* return a result code based on the result of the clear-halts */
-	if (result >= 0)
-		result = result2;
-	/* if (result < 0) */
-		/* pr_info("Soft reset failed\n"); */
-	/* else */
-		/* pr_info("Soft reset done\n"); */
-	return result;
-}
-
-/*
- * usb_stor_Bulk_reset()
- */
-int usb_stor_Bulk_reset(struct us_data *us)
-{
-	/* pr_info("transport --- usb_stor_Bulk_reset\n"); */
-	return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
-				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, NULL, 0);
-}
-
-/*
- * usb_stor_port_reset()
- */
-int usb_stor_port_reset(struct us_data *us)
-{
-	int result;
-
-	/* pr_info("transport --- usb_stor_port_reset\n"); */
-	result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
-	if (result < 0)
-		pr_info("unable to lock device for reset: %d\n", result);
-	else {
-		/* Were we disconnected while waiting for the lock? */
-		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-			result = -EIO;
-			/* pr_info("No reset during disconnect\n"); */
-		} else {
-			result = usb_reset_device(us->pusb_dev);
-			/* pr_info("usb_reset_composite_device returns %d\n",
-								result); */
-		}
-		usb_unlock_device(us->pusb_dev);
-	}
-	return result;
-}
-
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/transport.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/transport.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/transport.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/transport.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-#ifndef _TRANSPORT_H_
-#define _TRANSPORT_H_
-
-#include <linux/blkdev.h>
-
-/* usb_stor_bulk_transfer_xxx() return codes, in order of severity */
-#define USB_STOR_XFER_GOOD	0	/* good transfer                 */
-#define USB_STOR_XFER_SHORT	1	/* transferred less than expected */
-#define USB_STOR_XFER_STALLED	2	/* endpoint stalled              */
-#define USB_STOR_XFER_LONG	3	/* device tried to send too much */
-#define USB_STOR_XFER_ERROR	4	/* transfer died in the middle   */
-
-/* Transport return codes */
-#define USB_STOR_TRANSPORT_GOOD	0	/* Transport good, command good	*/
-#define USB_STOR_TRANSPORT_FAILED 1	/* Transport good, command failed */
-#define USB_STOR_TRANSPORT_NO_SENSE 2	/* Command failed, no auto-sense */
-#define USB_STOR_TRANSPORT_ERROR 3	/* Transport bad (i.e. device dead) */
-
-/*
- * We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
- * return codes.  But now the transport and low-level transfer routines
- * treat an abort as just another error (-ENOENT for a cancelled URB).
- * It is up to the invoke_transport() function to test for aborts and
- * distinguish them from genuine communication errors.
- */
-
-/* CBI accept device specific command */
-#define US_CBI_ADSC		0
-extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
-extern int usb_stor_Bulk_max_lun(struct us_data *);
-extern int usb_stor_Bulk_reset(struct us_data *);
-extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
-extern void usb_stor_stop_transport(struct us_data *);
-extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
-		u8 request, u8 requesttype, u16 value, u16 index,
-		void *data, u16 size, int timeout);
-extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
-extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
-		void *buf, unsigned int length, unsigned int *act_len);
-extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
-		void *buf, unsigned int length, int use_sg, int *residual);
-extern int usb_stor_bulk_srb(struct us_data *us, unsigned int pipe,
-		struct scsi_cmnd *srb);
-extern int usb_stor_port_reset(struct us_data *us);
-
-/* Protocol handling routines */
-enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
-extern unsigned int usb_stor_access_xfer_buf(struct us_data*,
-	unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb,
-	struct scatterlist **, unsigned int *offset, enum xfer_buf_dir dir);
-extern void usb_stor_set_xfer_buf(struct us_data*, unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb,
-	unsigned int dir);
-
-/*
- * ENE scsi function
- */
-extern void ENE_stor_invoke_transport(struct scsi_cmnd *, struct us_data *);
-extern int ENE_InitMedia(struct us_data *);
-extern int ENE_SMInit(struct us_data *);
-extern int ENE_SendScsiCmd(struct us_data*, u8, void*, int);
-extern int ENE_LoadBinCode(struct us_data*, u8);
-extern int ene_read_byte(struct us_data*, u16 index, void *buf);
-extern int ENE_Read_Data(struct us_data*, void *buf, unsigned int length);
-extern int ENE_Write_Data(struct us_data*, void *buf, unsigned int length);
-extern void BuildSenseBuffer(struct scsi_cmnd *, int);
-
-/*
- * ENE scsi function
- */
-extern int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/usb.c linux-libre-3.17-rc7-gnu/drivers/staging/keucr/usb.c
--- linux-libre-3.16-gnu/drivers/staging/keucr/usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/usb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,642 +0,0 @@
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/freezer.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-#include <linux/utsname.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "smil.h"
-#include "transport.h"
-
-/* Some informational data */
-MODULE_AUTHOR("Domao");
-MODULE_DESCRIPTION("ENE USB Mass Storage driver for Linux");
-MODULE_LICENSE("GPL");
-
-static unsigned int delay_use = 1;
-
-static struct usb_device_id eucr_usb_ids[] = {
-	{ USB_DEVICE(0x058f, 0x6366) },
-	{ USB_DEVICE(0x0cf2, 0x6230) },
-	{ USB_DEVICE(0x0cf2, 0x6250) },
-	{ }                                            /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, eucr_usb_ids);
-
-
-#ifdef CONFIG_PM
-
-static int eucr_suspend(struct usb_interface *iface, pm_message_t message)
-{
-	struct us_data *us = usb_get_intfdata(iface);
-	pr_info("--- eucr_suspend ---\n");
-	/* Wait until no command is running */
-	mutex_lock(&us->dev_mutex);
-
-	if (us->suspend_resume_hook)
-		(us->suspend_resume_hook)(us, US_SUSPEND);
-
-	mutex_unlock(&us->dev_mutex);
-	return 0;
-}
-
-static int eucr_resume(struct usb_interface *iface)
-{
-	u8    tmp = 0;
-
-	struct us_data *us = usb_get_intfdata(iface);
-	pr_info("--- eucr_resume---\n");
-	mutex_lock(&us->dev_mutex);
-
-	if (us->suspend_resume_hook)
-		(us->suspend_resume_hook)(us, US_RESUME);
-
-
-	mutex_unlock(&us->dev_mutex);
-
-	us->Power_IsResum = true;
-
-	us->SM_Status = *(struct keucr_sm_status *)&tmp;
-
-	return 0;
-}
-
-static int eucr_reset_resume(struct usb_interface *iface)
-{
-	u8    tmp = 0;
-	struct us_data *us = usb_get_intfdata(iface);
-
-	pr_info("--- eucr_reset_resume---\n");
-
-	/* Report the reset to the SCSI core */
-	usb_stor_report_bus_reset(us);
-
-	/*
-	 * FIXME: Notify the subdrivers that they need to reinitialize
-	 * the device
-	 */
-
-	us->Power_IsResum = true;
-
-	us->SM_Status = *(struct keucr_sm_status *)&tmp;
-
-	return 0;
-}
-
-#else
-
-#define eucr_suspend		NULL
-#define eucr_resume		NULL
-#define eucr_reset_resume	NULL
-
-#endif
-
-static int eucr_pre_reset(struct usb_interface *iface)
-{
-	struct us_data *us = usb_get_intfdata(iface);
-
-	pr_info("usb --- eucr_pre_reset\n");
-
-	/* Make sure no command runs during the reset */
-	mutex_lock(&us->dev_mutex);
-	return 0;
-}
-
-static int eucr_post_reset(struct usb_interface *iface)
-{
-	struct us_data *us = usb_get_intfdata(iface);
-
-	pr_info("usb --- eucr_post_reset\n");
-
-	/* Report the reset to the SCSI core */
-	usb_stor_report_bus_reset(us);
-
-	mutex_unlock(&us->dev_mutex);
-	return 0;
-}
-
-void fill_inquiry_response(struct us_data *us, unsigned char *data,
-							unsigned int data_len)
-{
-	pr_info("usb --- fill_inquiry_response\n");
-	if (data_len < 36) /* You lose. */
-		return;
-
-	if (data[0]&0x20) {
-		memset(data+8, 0, 28);
-	} else {
-		u16 bcdDevice =
-			le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
-		memcpy(data+8, us->unusual_dev->vendorName,
-			strlen(us->unusual_dev->vendorName) > 8 ? 8 :
-			strlen(us->unusual_dev->vendorName));
-		memcpy(data+16, us->unusual_dev->productName,
-			strlen(us->unusual_dev->productName) > 16 ? 16 :
-			strlen(us->unusual_dev->productName));
-		data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
-		data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
-		data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
-		data[35] = 0x30 + ((bcdDevice) & 0x0F);
-	}
-	usb_stor_set_xfer_buf(us, data, data_len, us->srb, TO_XFER_BUF);
-}
-
-static int usb_stor_control_thread(void *__us)
-{
-	struct us_data *us = (struct us_data *)__us;
-	struct Scsi_Host *host = us_to_host(us);
-
-	pr_info("usb --- usb_stor_control_thread\n");
-	for (;;) {
-		if (wait_for_completion_interruptible(&us->cmnd_ready))
-			break;
-
-		/* lock the device pointers */
-		mutex_lock(&(us->dev_mutex));
-
-		/* if the device has disconnected, we are free to exit */
-		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-			mutex_unlock(&us->dev_mutex);
-			break;
-		}
-
-		/* lock access to the state */
-		scsi_lock(host);
-
-		/* When we are called with no command pending, we're done */
-		if (us->srb == NULL) {
-			scsi_unlock(host);
-			mutex_unlock(&us->dev_mutex);
-			break;
-		}
-
-		/* has the command timed out *already* ? */
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-			us->srb->result = DID_ABORT << 16;
-			goto SkipForAbort;
-		}
-
-		scsi_unlock(host);
-
-		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
-			us->srb->result = DID_ERROR << 16;
-		} else if (us->srb->device->id
-			   && !(us->fflags & US_FL_SCM_MULT_TARG)) {
-			us->srb->result = DID_BAD_TARGET << 16;
-		} else if (us->srb->device->lun > us->max_lun) {
-			us->srb->result = DID_BAD_TARGET << 16;
-		} else if ((us->srb->cmnd[0] == INQUIRY)
-			   && (us->fflags & US_FL_FIX_INQUIRY)) {
-			unsigned char data_ptr[36] = {0x00, 0x80, 0x02, 0x02,
-						0x1F, 0x00, 0x00, 0x00};
-
-			fill_inquiry_response(us, data_ptr, 36);
-			us->srb->result = SAM_STAT_GOOD;
-		} else {
-			us->proto_handler(us->srb, us);
-		}
-
-		/* lock access to the state */
-		scsi_lock(host);
-
-		/* indicate that the command is done */
-		if (us->srb->result != DID_ABORT << 16) {
-			us->srb->scsi_done(us->srb);
-		} else {
-SkipForAbort:
-			pr_info("scsi command aborted\n");
-		}
-
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-			complete(&(us->notify));
-
-			/* Allow USB transfers to resume */
-			clear_bit(US_FLIDX_ABORTING, &us->dflags);
-			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
-		}
-
-		/* finished working on this command */
-		us->srb = NULL;
-		scsi_unlock(host);
-
-		/* unlock the device pointers */
-		mutex_unlock(&us->dev_mutex);
-	} /* for (;;) */
-
-	/* Wait until we are told to stop */
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (kthread_should_stop())
-			break;
-		schedule();
-	}
-	__set_current_state(TASK_RUNNING);
-	return 0;
-}
-
-static int associate_dev(struct us_data *us, struct usb_interface *intf)
-{
-	pr_info("usb --- associate_dev\n");
-
-	/* Fill in the device-related fields */
-	us->pusb_dev = interface_to_usbdev(intf);
-	us->pusb_intf = intf;
-	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-	/* Store our private data in the interface */
-	usb_set_intfdata(intf, us);
-
-	/* Allocate the device-related DMA-mapped buffers */
-	us->cr = usb_alloc_coherent(us->pusb_dev, sizeof(*us->cr), GFP_KERNEL,
-							&us->cr_dma);
-	if (!us->cr) {
-		pr_info("usb_ctrlrequest allocation failed\n");
-		return -ENOMEM;
-	}
-
-	us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE, GFP_KERNEL,
-							&us->iobuf_dma);
-	if (!us->iobuf) {
-		pr_info("I/O buffer allocation failed\n");
-		return -ENOMEM;
-	}
-
-	us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
-	if (!us->sensebuf)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int get_device_info(struct us_data *us, const struct usb_device_id *id)
-{
-	struct usb_device *dev = us->pusb_dev;
-	struct usb_interface_descriptor *idesc =
-					&us->pusb_intf->cur_altsetting->desc;
-
-	pr_info("usb --- get_device_info\n");
-
-	us->subclass = idesc->bInterfaceSubClass;
-	us->protocol = idesc->bInterfaceProtocol;
-	us->fflags = id->driver_info;
-	us->Power_IsResum = false;
-
-	if (us->fflags & US_FL_IGNORE_DEVICE) {
-		pr_info("device ignored\n");
-		return -ENODEV;
-	}
-
-	if (dev->speed != USB_SPEED_HIGH)
-		us->fflags &= ~US_FL_GO_SLOW;
-
-	return 0;
-}
-
-static int get_transport(struct us_data *us)
-{
-	pr_info("usb --- get_transport\n");
-	switch (us->protocol) {
-	case USB_PR_BULK:
-		us->transport_name = "Bulk";
-		us->transport = usb_stor_Bulk_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		break;
-
-	default:
-		return -EIO;
-	}
-
-	/* fix for single-lun devices */
-	if (us->fflags & US_FL_SINGLE_LUN)
-		us->max_lun = 0;
-	return 0;
-}
-
-static int get_protocol(struct us_data *us)
-{
-	pr_info("usb --- get_protocol\n");
-	pr_info("us->pusb_dev->descriptor.idVendor = %x\n",
-			us->pusb_dev->descriptor.idVendor);
-	pr_info("us->pusb_dev->descriptor.idProduct = %x\n",
-			us->pusb_dev->descriptor.idProduct);
-	switch (us->subclass) {
-	case USB_SC_SCSI:
-		us->protocol_name = "Transparent SCSI";
-		if ((us->pusb_dev->descriptor.idVendor == 0x0CF2)
-		    && (us->pusb_dev->descriptor.idProduct == 0x6250))
-			us->proto_handler = ENE_stor_invoke_transport;
-		else
-			us->proto_handler = usb_stor_invoke_transport;
-		break;
-
-	default:
-		return -EIO;
-	}
-	return 0;
-}
-
-static int get_pipes(struct us_data *us)
-{
-	struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
-	int i;
-	struct usb_endpoint_descriptor *ep;
-	struct usb_endpoint_descriptor *ep_in = NULL;
-	struct usb_endpoint_descriptor *ep_out = NULL;
-	struct usb_endpoint_descriptor *ep_int = NULL;
-
-	pr_info("usb --- get_pipes\n");
-
-	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
-		ep = &altsetting->endpoint[i].desc;
-
-		if (usb_endpoint_xfer_bulk(ep)) {
-			if (usb_endpoint_dir_in(ep)) {
-				if (!ep_in)
-					ep_in = ep;
-			} else {
-				if (!ep_out)
-					ep_out = ep;
-			}
-		} else if (usb_endpoint_is_int_in(ep)) {
-			if (!ep_int)
-				ep_int = ep;
-		}
-	}
-
-	if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
-		pr_info("Endpoint sanity check failed! Rejecting dev.\n");
-		return -EIO;
-	}
-
-	/* Calculate and store the pipe values */
-	us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0);
-	us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
-	us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,
-			ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-	us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
-			ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-	if (ep_int) {
-		us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,
-			ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-		us->ep_bInterval = ep_int->bInterval;
-	}
-	return 0;
-}
-
-static int usb_stor_acquire_resources(struct us_data *us)
-{
-	struct task_struct *th;
-
-	pr_info("usb --- usb_stor_acquire_resources\n");
-	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!us->current_urb) {
-		pr_info("URB allocation failed\n");
-		return -ENOMEM;
-	}
-
-	/* Start up our control thread */
-	th = kthread_run(usb_stor_control_thread, us, "eucr-storage");
-	if (IS_ERR(th)) {
-		pr_info("Unable to start control thread\n");
-		return PTR_ERR(th);
-	}
-	us->ctl_thread = th;
-
-	return 0;
-}
-
-static void usb_stor_release_resources(struct us_data *us)
-{
-	pr_info("usb --- usb_stor_release_resources\n");
-
-	SM_FreeMem();
-
-	complete(&us->cmnd_ready);
-	if (us->ctl_thread)
-		kthread_stop(us->ctl_thread);
-
-	/* Call the destructor routine, if it exists */
-	if (us->extra_destructor) {
-		pr_info("-- calling extra_destructor()\n");
-		us->extra_destructor(us->extra);
-	}
-
-	/* Free the extra data and the URB */
-	kfree(us->extra);
-	usb_free_urb(us->current_urb);
-}
-
-static void dissociate_dev(struct us_data *us)
-{
-	pr_info("usb --- dissociate_dev\n");
-
-	kfree(us->sensebuf);
-
-	/* Free the device-related DMA-mapped buffers */
-	usb_free_coherent(us->pusb_dev, sizeof(*us->cr), us->cr, us->cr_dma);
-	usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
-			  us->iobuf_dma);
-
-	/* Remove our private data from the interface */
-	usb_set_intfdata(us->pusb_intf, NULL);
-}
-
-static void quiesce_and_remove_host(struct us_data *us)
-{
-	struct Scsi_Host *host = us_to_host(us);
-
-	pr_info("usb --- quiesce_and_remove_host\n");
-
-	/* If the device is really gone, cut short reset delays */
-	if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
-		set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
-
-	/*
-	 * Prevent SCSI-scanning (if it hasn't started yet)
-	 * and wait for the SCSI-scanning thread to stop.
-	 */
-	set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
-	wake_up(&us->delay_wait);
-	wait_for_completion(&us->scanning_done);
-
-	/*
-	 * Removing the host will perform an orderly shutdown: caches
-	 * synchronized, disks spun down, etc.
-	 */
-	scsi_remove_host(host);
-
-	/*
-	 * Prevent any new commands from being accepted and cut short
-	 * reset delays.
-	 */
-	scsi_lock(host);
-	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
-	scsi_unlock(host);
-	wake_up(&us->delay_wait);
-}
-
-static void release_everything(struct us_data *us)
-{
-	pr_info("usb --- release_everything\n");
-
-	usb_stor_release_resources(us);
-	dissociate_dev(us);
-	scsi_host_put(us_to_host(us));
-}
-
-static int usb_stor_scan_thread(void *__us)
-{
-	struct us_data *us = (struct us_data *)__us;
-
-	pr_info("usb --- usb_stor_scan_thread\n");
-	pr_info("EUCR : device found at %d\n", us->pusb_dev->devnum);
-
-	set_freezable();
-	/* Wait for the timeout to expire or for a disconnect */
-	if (delay_use > 0) {
-		wait_event_freezable_timeout(us->delay_wait,
-				test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
-				delay_use * HZ);
-	}
-
-	/* If the device is still connected, perform the scanning */
-	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
-		/* For bulk-only devices, determine the max LUN value */
-		if (us->protocol == USB_PR_BULK
-		    && !(us->fflags & US_FL_SINGLE_LUN)) {
-			mutex_lock(&us->dev_mutex);
-			us->max_lun = usb_stor_Bulk_max_lun(us);
-			mutex_unlock(&us->dev_mutex);
-		}
-		scsi_scan_host(us_to_host(us));
-		pr_info("EUCR : device scan complete\n");
-	}
-	complete_and_exit(&us->scanning_done, 0);
-}
-
-static int eucr_probe(struct usb_interface *intf,
-					const struct usb_device_id *id)
-{
-	struct Scsi_Host *host;
-	struct us_data *us;
-	int result;
-	u8	MiscReg03 = 0;
-	struct task_struct *th;
-
-	pr_info("usb --- eucr_probe\n");
-
-	host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
-	if (!host) {
-		pr_info("Unable to allocate the scsi host\n");
-		return -ENOMEM;
-	}
-
-	/* Allow 16-byte CDBs and thus > 2TB */
-	host->max_cmd_len = 16;
-	us = host_to_us(host);
-	memset(us, 0, sizeof(struct us_data));
-	mutex_init(&(us->dev_mutex));
-	init_completion(&us->cmnd_ready);
-	init_completion(&(us->notify));
-	init_waitqueue_head(&us->delay_wait);
-	init_completion(&us->scanning_done);
-
-	/* Associate the us_data structure with the USB device */
-	result = associate_dev(us, intf);
-	if (result)
-		goto BadDevice;
-
-	/* Get Device info */
-	result = get_device_info(us, id);
-	if (result)
-		goto BadDevice;
-
-	/* Get the transport, protocol, and pipe settings */
-	result = get_transport(us);
-	if (result)
-		goto BadDevice;
-	result = get_protocol(us);
-	if (result)
-		goto BadDevice;
-	result = get_pipes(us);
-	if (result)
-		goto BadDevice;
-
-	/* Acquire all the other resources and add the host */
-	result = usb_stor_acquire_resources(us);
-	if (result)
-		goto BadDevice;
-
-	result = scsi_add_host(host, &intf->dev);
-	if (result) {
-		pr_info("Unable to add the scsi host\n");
-		goto BadDevice;
-	}
-
-	/* Start up the thread for delayed SCSI-device scanning */
-	th = kthread_create(usb_stor_scan_thread, us, "eucr-stor-scan");
-	if (IS_ERR(th)) {
-		pr_info("Unable to start the device-scanning thread\n");
-		complete(&us->scanning_done);
-		quiesce_and_remove_host(us);
-		result = PTR_ERR(th);
-		goto BadDevice;
-	}
-	wake_up_process(th);
-
-	/* probe card type */
-	result = ene_read_byte(us, REG_CARD_STATUS, &MiscReg03);
-	if (result != USB_STOR_XFER_GOOD) {
-		result = USB_STOR_TRANSPORT_ERROR;
-		quiesce_and_remove_host(us);
-		goto BadDevice;
-	}
-
-	if (!(MiscReg03 & 0x02)) {
-		result = -ENODEV;
-		quiesce_and_remove_host(us);
-		pr_info("keucr: The driver only supports SM/MS card. To use SD card, please build driver/usb/storage/ums-eneub6250.ko\n");
-		goto BadDevice;
-	}
-
-	return 0;
-
-	/* We come here if there are any problems */
-BadDevice:
-	pr_info("usb --- eucr_probe failed\n");
-	release_everything(us);
-	return result;
-}
-
-static void eucr_disconnect(struct usb_interface *intf)
-{
-	struct us_data *us = usb_get_intfdata(intf);
-
-	pr_info("usb --- eucr_disconnect\n");
-	quiesce_and_remove_host(us);
-	release_everything(us);
-}
-
-/* Initialization and registration */
-static struct usb_driver usb_storage_driver = {
-	.name =		"eucr",
-	.probe =		eucr_probe,
-	.suspend =	    eucr_suspend,
-	.resume =	    eucr_resume,
-	.reset_resume =	eucr_reset_resume,
-	.disconnect =	eucr_disconnect,
-	.pre_reset =	eucr_pre_reset,
-	.post_reset =	eucr_post_reset,
-	.id_table =		eucr_usb_ids,
-	.soft_unbind =	1,
-};
-
-module_usb_driver(usb_storage_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/keucr/usb.h linux-libre-3.17-rc7-gnu/drivers/staging/keucr/usb.h
--- linux-libre-3.16-gnu/drivers/staging/keucr/usb.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/keucr/usb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,240 +0,0 @@
-/* Driver for USB Mass Storage compliant devices */
-
-#ifndef _USB_H_
-#define _USB_H_
-
-#include <linux/usb.h>
-#include <linux/usb_usual.h>
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <scsi/scsi_host.h>
-#include "common.h"
-
-struct us_data;
-struct scsi_cmnd;
-
-/*
- * Unusual device list definitions
- */
-
-struct us_unusual_dev {
-	const char *vendorName;
-	const char *productName;
-	__u8  useProtocol;
-	__u8  useTransport;
-	int (*initFunction)(struct us_data *);
-};
-
-/* EnE HW Register */
-#define REG_CARD_STATUS     0xFF83
-#define REG_HW_TRAP1        0xFF89
-
-/* SRB Status. Refers /usr/include/wine/wine/wnaspi32.h & SCSI sense key */
-#define SS_SUCCESS                  0x00      /* No Sense */
-#define SS_NOT_READY                0x02
-#define SS_MEDIUM_ERR               0x03
-#define SS_HW_ERR                   0x04
-#define SS_ILLEGAL_REQUEST          0x05
-#define SS_UNIT_ATTENTION           0x06
-
-/* ENE Load FW Pattern */
-#define SD_INIT1_PATTERN   1
-#define SD_INIT2_PATTERN   2
-#define SD_RW_PATTERN      3
-#define MS_INIT_PATTERN    4
-#define MSP_RW_PATTERN     5
-#define MS_RW_PATTERN      6
-#define SM_INIT_PATTERN    7
-#define SM_RW_PATTERN      8
-
-#define FDIR_WRITE        0
-#define FDIR_READ         1
-
-struct keucr_sd_status {
-	u8    Insert:1;
-	u8    Ready:1;
-	u8    MediaChange:1;
-	u8    IsMMC:1;
-	u8    HiCapacity:1;
-	u8    HiSpeed:1;
-	u8    WtP:1;
-	u8    Reserved:1;
-};
-
-struct keucr_ms_status {
-	u8    Insert:1;
-	u8    Ready:1;
-	u8    MediaChange:1;
-	u8    IsMSPro:1;
-	u8    IsMSPHG:1;
-	u8    Reserved1:1;
-	u8    WtP:1;
-	u8    Reserved2:1;
-};
-
-struct keucr_sm_status {
-	u8    Insert:1;
-	u8    Ready:1;
-	u8    MediaChange:1;
-	u8    Reserved:3;
-	u8    WtP:1;
-	u8    IsMS:1;
-};
-
-/* SD Block Length */
-#define SD_BLOCK_LEN		9	/* 2^9 = 512 Bytes,
-				The HW maximum read/write data length */
-
-/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */
-#define US_FLIDX_URB_ACTIVE	0	/* current_urb is in use    */
-#define US_FLIDX_SG_ACTIVE	1	/* current_sg is in use     */
-#define US_FLIDX_ABORTING	2	/* abort is in progress     */
-#define US_FLIDX_DISCONNECTING	3	/* disconnect in progress   */
-#define US_FLIDX_RESETTING	4	/* device reset in progress */
-#define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
-#define US_FLIDX_DONT_SCAN	6	/* don't scan (disconnect)  */
-
-
-#define USB_STOR_STRING_LEN 32
-
-/*
- * We provide a DMA-mapped I/O buffer for use with small USB transfers.
- * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
- * 31-byte buffer.  But Freecom needs a 64-byte buffer, so that's the
- * size we'll allocate.
- */
-
-#define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
-#define US_SENSE_SIZE		18	/* Size of the autosense data buffer */
-
-typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data *);
-typedef int (*trans_reset)(struct us_data *);
-typedef void (*proto_cmnd)(struct scsi_cmnd *, struct us_data *);
-typedef void (*extra_data_destructor)(void *);	/* extra data destructor */
-typedef void (*pm_hook)(struct us_data *, int);	/* power management hook */
-
-#define US_SUSPEND	0
-#define US_RESUME	1
-
-/* we allocate one of these for every device that we remember */
-struct us_data {
-	/* The device we're working with
-	 * It's important to note:
-	 *    (o) you must hold dev_mutex to change pusb_dev
-	 */
-	struct mutex		dev_mutex;	 /* protect pusb_dev */
-	struct usb_device	*pusb_dev;	 /* this usb_device */
-	struct usb_interface	*pusb_intf;	 /* this interface */
-	struct us_unusual_dev   *unusual_dev;	 /* device-filter entry     */
-	unsigned long		fflags;		 /* fixed flags from filter */
-	unsigned long		dflags;		 /* dynamic atomic bitflags */
-	unsigned int		send_bulk_pipe;	 /* cached pipe values */
-	unsigned int		recv_bulk_pipe;
-	unsigned int		send_ctrl_pipe;
-	unsigned int		recv_ctrl_pipe;
-	unsigned int		recv_intr_pipe;
-
-	/* information about the device */
-	char			*transport_name;
-	char			*protocol_name;
-	__le32			bcs_signature;
-	u8			subclass;
-	u8			protocol;
-	u8			max_lun;
-
-	u8			ifnum;		 /* interface number   */
-	u8			ep_bInterval;	 /* interrupt interval */
-
-	/* function pointers for this device */
-	trans_cmnd		transport;	 /* transport function	   */
-	trans_reset		transport_reset; /* transport device reset */
-	proto_cmnd		proto_handler;	 /* protocol handler	   */
-
-	/* SCSI interfaces */
-	struct scsi_cmnd	*srb;		 /* current srb		*/
-	unsigned int		tag;		 /* current dCBWTag	*/
-
-	/* control and bulk communications data */
-	struct urb		*current_urb;	 /* USB requests	 */
-	struct usb_ctrlrequest	*cr;		 /* control requests	 */
-	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
-	unsigned char		*iobuf;		 /* I/O buffer		 */
-	unsigned char		*sensebuf;	 /* sense data buffer	 */
-	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
-	dma_addr_t		iobuf_dma;
-	struct task_struct	*ctl_thread;	 /* the control thread   */
-
-	/* mutual exclusion and synchronization structures */
-	struct completion	cmnd_ready;	 /* to sleep thread on	    */
-	struct completion	notify;		 /* thread begin/end	    */
-	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
-	struct completion	scanning_done;	 /* wait for scan thread    */
-
-	/* subdriver information */
-	void			*extra;		 /* Any extra data          */
-	extra_data_destructor	extra_destructor;/* extra data destructor   */
-#ifdef CONFIG_PM
-	pm_hook			suspend_resume_hook;
-#endif
-	/* for 6250 code */
-	struct keucr_sd_status   SD_Status;
-	struct keucr_ms_status   MS_Status;
-	struct keucr_sm_status   SM_Status;
-
-	/* ----- SD Control Data ---------------- */
-	/* SD_REGISTER SD_Regs; */
-	u16        SD_Block_Mult;
-	u8        SD_READ_BL_LEN;
-	u16        SD_C_SIZE;
-	u8        SD_C_SIZE_MULT;
-
-	/* SD/MMC New spec. */
-	u8        SD_SPEC_VER;
-	u8        SD_CSD_VER;
-	u8        SD20_HIGH_CAPACITY;
-	u32       HC_C_SIZE;
-	u8        MMC_SPEC_VER;
-	u8        MMC_BusWidth;
-	u8        MMC_HIGH_CAPACITY;
-
-	/* ----- MS Control Data ---------------- */
-	bool             MS_SWWP;
-	u32               MSP_TotalBlock;
-	/* MS_LibControl       MS_Lib; */
-	bool             MS_IsRWPage;
-	u16                MS_Model;
-
-	/* ----- SM Control Data ---------------- */
-	u8		SM_DeviceID;
-	u8		SM_CardID;
-
-	u8 *testbuf;
-	u8		BIN_FLAG;
-	u32		bl_num;
-	int		SrbStatus;
-
-	/* ------Power Managerment --------------- */
-	bool         Power_IsResum;
-};
-
-/* Convert between us_data and the corresponding Scsi_Host */
-static inline struct Scsi_Host *us_to_host(struct us_data *us)
-{
-	return container_of((void *) us, struct Scsi_Host, hostdata);
-}
-static inline struct us_data *host_to_us(struct Scsi_Host *host)
-{
-	return (struct us_data *) host->hostdata;
-}
-
-/* Function to fill an inquiry response. See usb.c for details */
-extern void fill_inquiry_response(struct us_data *us,
-	unsigned char *data, unsigned int data_len);
-
-/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
- * single queue element srb for write access */
-#define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
-#define scsi_lock(host)		spin_lock_irq(host->host_lock)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/line6/driver.c linux-libre-3.17-rc7-gnu/drivers/staging/line6/driver.c
--- linux-libre-3.16-gnu/drivers/staging/line6/driver.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/line6/driver.c	2014-09-28 17:29:07.000000000 -0400
@@ -663,7 +663,7 @@ static int line6_probe(struct usb_interf
 	case LINE6_DEVID_POCKETPOD:
 		switch (interface_number) {
 		case 0:
-			return 0;	/* this interface has no endpoints */
+			return -ENODEV;	/* this interface has no endpoints */
 		case 1:
 			alternate = 0;
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/bitmap.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/bitmap.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/bitmap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/bitmap.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/curproc.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/curproc.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/curproc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/curproc.h	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ typedef __u32 cfs_cap_t;
 			 (1 << CFS_CAP_DAC_OVERRIDE) |	  \
 			 (1 << CFS_CAP_DAC_READ_SEARCH) |       \
 			 (1 << CFS_CAP_FOWNER) |		\
-			 (1 << CFS_CAP_FSETID ) |	       \
+			 (1 << CFS_CAP_FSETID) |	       \
 			 (1 << CFS_CAP_LINUX_IMMUTABLE) |       \
 			 (1 << CFS_CAP_SYS_ADMIN) |	     \
 			 (1 << CFS_CAP_SYS_BOOT) |	      \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h	2014-09-28 17:29:07.000000000 -0400
@@ -165,7 +165,7 @@ struct ptldebug_header {
 #define CDEBUG_DEFAULT_MIN_DELAY ((cfs_time_seconds(1) + 1) / 2) /* jiffies */
 #define CDEBUG_DEFAULT_BACKOFF   2
 struct cfs_debug_limit_state {
-	cfs_time_t   cdls_next;
+	unsigned long   cdls_next;
 	unsigned int cdls_delay;
 	int	     cdls_count;
 };
@@ -254,19 +254,19 @@ do {									\
 	goto label;							\
 } while (0)
 
-extern int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata,
+int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata,
 			    const char *format1, ...)
 	__attribute__ ((format (printf, 2, 3)));
 
-extern int libcfs_debug_vmsg2(struct libcfs_debug_msg_data *msgdata,
+int libcfs_debug_vmsg2(struct libcfs_debug_msg_data *msgdata,
 			      const char *format1,
 			      va_list args, const char *format2, ...)
 	__attribute__ ((format (printf, 4, 5)));
 
 /* other external symbols that tracefile provides: */
-extern int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
+int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
 				   const char *usr_buffer, int usr_buffer_nob);
-extern int cfs_trace_copyout_string(char *usr_buffer, int usr_buffer_nob,
+int cfs_trace_copyout_string(char *usr_buffer, int usr_buffer_nob,
 				    const char *knl_buffer, char *append);
 
 #define LIBCFS_DEBUG_FILE_PATH_DEFAULT "/tmp/lustre-log"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h	2014-09-28 17:29:07.000000000 -0400
@@ -153,6 +153,7 @@ static inline void cfs_race(__u32 id)
 	if (CFS_FAIL_PRECHECK(id)) {
 		if (unlikely(__cfs_fail_check_set(id, 0, CFS_FAIL_LOC_NOSET))) {
 			int rc;
+
 			cfs_race_state = 0;
 			CERROR("cfs_race id %x sleeping\n", id);
 			cfs_wait_event_interruptible(cfs_race_waitq,
@@ -165,6 +166,7 @@ static inline void cfs_race(__u32 id)
 		}
 	}
 }
+
 #define CFS_RACE(id) cfs_race(id)
 
 #endif /* _LIBCFS_FAIL_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,21 +41,21 @@
 #define __attribute__(x)
 #endif
 
-#include <linux/libcfs/linux/libcfs.h>
+#include "linux/libcfs.h"
 #include <linux/gfp.h>
 
 #include "curproc.h"
 
 #ifndef offsetof
-# define offsetof(typ,memb) ((long)(long_ptr_t)((char *)&(((typ *)0)->memb)))
+# define offsetof(typ, memb) ((long)(long_ptr_t)((char *)&(((typ *)0)->memb)))
 #endif
 
 #ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) ((sizeof (a)) / (sizeof ((a)[0])))
+#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
 #endif
 
 #if !defined(swap)
-#define swap(x,y) do { typeof(x) z = x; x = y; y = z; } while (0)
+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
 #endif
 
 #if !defined(container_of)
@@ -89,18 +89,18 @@ static inline int __is_po2(unsigned long
 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask);
 int libcfs_ipif_enumerate(char ***names);
 void libcfs_ipif_free_enumeration(char **names, int n);
-int libcfs_sock_listen(socket_t **sockp, __u32 ip, int port, int backlog);
-int libcfs_sock_accept(socket_t **newsockp, socket_t *sock);
-void libcfs_sock_abort_accept(socket_t *sock);
-int libcfs_sock_connect(socket_t **sockp, int *fatal,
+int libcfs_sock_listen(struct socket **sockp, __u32 ip, int port, int backlog);
+int libcfs_sock_accept(struct socket **newsockp, struct socket *sock);
+void libcfs_sock_abort_accept(struct socket *sock);
+int libcfs_sock_connect(struct socket **sockp, int *fatal,
 			__u32 local_ip, int local_port,
 			__u32 peer_ip, int peer_port);
-int libcfs_sock_setbuf(socket_t *socket, int txbufsize, int rxbufsize);
-int libcfs_sock_getbuf(socket_t *socket, int *txbufsize, int *rxbufsize);
-int libcfs_sock_getaddr(socket_t *socket, int remote, __u32 *ip, int *port);
-int libcfs_sock_write(socket_t *sock, void *buffer, int nob, int timeout);
-int libcfs_sock_read(socket_t *sock, void *buffer, int nob, int timeout);
-void libcfs_sock_release(socket_t *sock);
+int libcfs_sock_setbuf(struct socket *socket, int txbufsize, int rxbufsize);
+int libcfs_sock_getbuf(struct socket *socket, int *txbufsize, int *rxbufsize);
+int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port);
+int libcfs_sock_write(struct socket *sock, void *buffer, int nob, int timeout);
+int libcfs_sock_read(struct socket *sock, void *buffer, int nob, int timeout);
+void libcfs_sock_release(struct socket *sock);
 
 /* need both kernel and user-land acceptor */
 #define LNET_ACCEPTOR_MIN_RESERVED_PORT    512
@@ -155,20 +155,19 @@ unsigned int cfs_rand(void);
 void cfs_srand(unsigned int, unsigned int);
 void cfs_get_random_bytes(void *buf, int size);
 
-#include <linux/libcfs/libcfs_debug.h>
-#include <linux/libcfs/libcfs_cpu.h>
-#include <linux/libcfs/libcfs_private.h>
-#include <linux/libcfs/libcfs_ioctl.h>
-#include <linux/libcfs/libcfs_prim.h>
-#include <linux/libcfs/libcfs_time.h>
-#include <linux/libcfs/libcfs_string.h>
-#include <linux/libcfs/libcfs_kernelcomm.h>
-#include <linux/libcfs/libcfs_workitem.h>
-#include <linux/libcfs/libcfs_hash.h>
-#include <linux/libcfs/libcfs_heap.h>
-#include <linux/libcfs/libcfs_fail.h>
-#include <linux/libcfs/params_tree.h>
-#include <linux/libcfs/libcfs_crypto.h>
+#include "libcfs_debug.h"
+#include "libcfs_cpu.h"
+#include "libcfs_private.h"
+#include "libcfs_ioctl.h"
+#include "libcfs_prim.h"
+#include "libcfs_time.h"
+#include "libcfs_string.h"
+#include "libcfs_kernelcomm.h"
+#include "libcfs_workitem.h"
+#include "libcfs_hash.h"
+#include "libcfs_heap.h"
+#include "libcfs_fail.h"
+#include "libcfs_crypto.h"
 
 /* container_of depends on "likely" which is defined in libcfs_private.h */
 static inline void *__container_of(void *ptr, unsigned long shift)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h	2014-09-28 17:29:07.000000000 -0400
@@ -628,21 +628,21 @@ static inline int cfs_hash_bd_dec_and_lo
 }
 
 static inline struct hlist_head *cfs_hash_bd_hhead(struct cfs_hash *hs,
-						  struct cfs_hash_bd *bd)
+						   struct cfs_hash_bd *bd)
 {
 	return hs->hs_hops->hop_hhead(hs, bd);
 }
 
 struct hlist_node *cfs_hash_bd_lookup_locked(struct cfs_hash *hs,
-					    struct cfs_hash_bd *bd, const void *key);
+					     struct cfs_hash_bd *bd, const void *key);
 struct hlist_node *cfs_hash_bd_peek_locked(struct cfs_hash *hs,
-					  struct cfs_hash_bd *bd, const void *key);
+					   struct cfs_hash_bd *bd, const void *key);
 struct hlist_node *cfs_hash_bd_findadd_locked(struct cfs_hash *hs,
-					     struct cfs_hash_bd *bd, const void *key,
+					      struct cfs_hash_bd *bd, const void *key,
 					     struct hlist_node *hnode,
 					     int insist_add);
 struct hlist_node *cfs_hash_bd_finddel_locked(struct cfs_hash *hs,
-					     struct cfs_hash_bd *bd, const void *key,
+					      struct cfs_hash_bd *bd, const void *key,
 					     struct hlist_node *hnode);
 
 /**
@@ -661,21 +661,21 @@ static inline void cfs_hash_dual_bd_get_
 }
 
 struct hlist_node *cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs,
-						 struct cfs_hash_bd *bds,
+						  struct cfs_hash_bd *bds,
 						 const void *key);
 struct hlist_node *cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs,
-						  struct cfs_hash_bd *bds,
+						   struct cfs_hash_bd *bds,
 						  const void *key,
 						  struct hlist_node *hnode,
 						  int insist_add);
 struct hlist_node *cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs,
-						  struct cfs_hash_bd *bds,
+						   struct cfs_hash_bd *bds,
 						  const void *key,
 						  struct hlist_node *hnode);
 
 /* Hash init/cleanup functions */
 struct cfs_hash *cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
-			    unsigned bkt_bits, unsigned extra_bytes,
+				 unsigned bkt_bits, unsigned extra_bytes,
 			    unsigned min_theta, unsigned max_theta,
 			    cfs_hash_ops_t *ops, unsigned flags);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,6 @@
 #ifndef __LIBCFS_IOCTL_H__
 #define __LIBCFS_IOCTL_H__
 
-
 #define LIBCFS_IOCTL_VERSION 0x0001000a
 
 struct libcfs_ioctl_data {
@@ -90,7 +89,6 @@ do {						    \
 	data.ioc_len = sizeof(data);		    \
 } while (0)
 
-
 struct libcfs_ioctl_handler {
 	struct list_head item;
 	int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_data *data);
@@ -102,11 +100,9 @@ struct libcfs_ioctl_handler {
 		/* .handle_ioctl = */ func		      \
 	}
 
-
 /* FIXME check conflict with lustre_lib.h */
 #define LIBCFS_IOC_DEBUG_MASK	     _IOWR('f', 250, long)
 
-
 /* ioctls for manipulating snapshots 30- */
 #define IOC_LIBCFS_TYPE		   'e'
 #define IOC_LIBCFS_MIN_NR		 30
@@ -149,6 +145,7 @@ struct libcfs_ioctl_handler {
 static inline int libcfs_ioctl_packlen(struct libcfs_ioctl_data *data)
 {
 	int len = sizeof(*data);
+
 	len += cfs_size_round(data->ioc_inllen1);
 	len += cfs_size_round(data->ioc_inllen2);
 	return len;
@@ -157,64 +154,62 @@ static inline int libcfs_ioctl_packlen(s
 static inline int libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data)
 {
 	if (data->ioc_len > (1<<30)) {
-		CERROR ("LIBCFS ioctl: ioc_len larger than 1<<30\n");
+		CERROR("LIBCFS ioctl: ioc_len larger than 1<<30\n");
 		return 1;
 	}
 	if (data->ioc_inllen1 > (1<<30)) {
-		CERROR ("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n");
+		CERROR("LIBCFS ioctl: ioc_inllen1 larger than 1<<30\n");
 		return 1;
 	}
 	if (data->ioc_inllen2 > (1<<30)) {
-		CERROR ("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n");
+		CERROR("LIBCFS ioctl: ioc_inllen2 larger than 1<<30\n");
 		return 1;
 	}
 	if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
-		CERROR ("LIBCFS ioctl: inlbuf1 pointer but 0 length\n");
+		CERROR("LIBCFS ioctl: inlbuf1 pointer but 0 length\n");
 		return 1;
 	}
 	if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
-		CERROR ("LIBCFS ioctl: inlbuf2 pointer but 0 length\n");
+		CERROR("LIBCFS ioctl: inlbuf2 pointer but 0 length\n");
 		return 1;
 	}
 	if (data->ioc_pbuf1 && !data->ioc_plen1) {
-		CERROR ("LIBCFS ioctl: pbuf1 pointer but 0 length\n");
+		CERROR("LIBCFS ioctl: pbuf1 pointer but 0 length\n");
 		return 1;
 	}
 	if (data->ioc_pbuf2 && !data->ioc_plen2) {
-		CERROR ("LIBCFS ioctl: pbuf2 pointer but 0 length\n");
+		CERROR("LIBCFS ioctl: pbuf2 pointer but 0 length\n");
 		return 1;
 	}
 	if (data->ioc_plen1 && !data->ioc_pbuf1) {
-		CERROR ("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n");
+		CERROR("LIBCFS ioctl: plen1 nonzero but no pbuf1 pointer\n");
 		return 1;
 	}
 	if (data->ioc_plen2 && !data->ioc_pbuf2) {
-		CERROR ("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n");
+		CERROR("LIBCFS ioctl: plen2 nonzero but no pbuf2 pointer\n");
 		return 1;
 	}
-	if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_len ) {
-		CERROR ("LIBCFS ioctl: packlen != ioc_len\n");
+	if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_len) {
+		CERROR("LIBCFS ioctl: packlen != ioc_len\n");
 		return 1;
 	}
 	if (data->ioc_inllen1 &&
 	    data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
-		CERROR ("LIBCFS ioctl: inlbuf1 not 0 terminated\n");
+		CERROR("LIBCFS ioctl: inlbuf1 not 0 terminated\n");
 		return 1;
 	}
 	if (data->ioc_inllen2 &&
 	    data->ioc_bulk[cfs_size_round(data->ioc_inllen1) +
 			   data->ioc_inllen2 - 1] != '\0') {
-		CERROR ("LIBCFS ioctl: inlbuf2 not 0 terminated\n");
+		CERROR("LIBCFS ioctl: inlbuf2 not 0 terminated\n");
 		return 1;
 	}
 	return 0;
 }
 
-
 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand);
 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand);
 int libcfs_ioctl_getdata(char *buf, char *end, void *arg);
 int libcfs_ioctl_popdata(void *arg, void *buf, int size);
 
-
 #endif /* __LIBCFS_IOCTL_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,6 @@
 #error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
 #endif
 
-
 /* KUC message header.
  * All current and future KUC messages should use this header.
  * To avoid having to include Lustre headers from libcfs, define this here.
@@ -90,12 +89,12 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 da
 #define KUC_GRP_MAX	   KUC_GRP_HSM
 
 /* Kernel methods */
-extern int libcfs_kkuc_msg_put(struct file *fp, void *payload);
-extern int libcfs_kkuc_group_put(int group, void *payload);
-extern int libcfs_kkuc_group_add(struct file *fp, int uid, int group,
+int libcfs_kkuc_msg_put(struct file *fp, void *payload);
+int libcfs_kkuc_group_put(int group, void *payload);
+int libcfs_kkuc_group_add(struct file *fp, int uid, int group,
 				 __u32 data);
-extern int libcfs_kkuc_group_rem(int uid, int group);
-extern int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
+int libcfs_kkuc_group_rem(int uid, int group);
+int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
 				     void *cb_arg);
 
 #define LK_FLG_STOP 0x01
@@ -111,9 +110,9 @@ typedef struct lustre_kernelcomm {
 } __attribute__((packed)) lustre_kernelcomm;
 
 /* Userspace methods */
-extern int libcfs_ukuc_start(lustre_kernelcomm *l, int groups);
-extern int libcfs_ukuc_stop(lustre_kernelcomm *l);
-extern int libcfs_ukuc_msg_get(lustre_kernelcomm *l, char *buf, int maxsize,
+int libcfs_ukuc_start(lustre_kernelcomm *l, int groups);
+int libcfs_ukuc_stop(lustre_kernelcomm *l);
+int libcfs_ukuc_msg_get(lustre_kernelcomm *l, char *buf, int maxsize,
 			       int transport);
 
 #endif /* __LIBCFS_KERNELCOMM_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,10 +50,10 @@ void add_wait_queue_exclusive_head(wait_
 void cfs_init_timer(struct timer_list *t);
 void cfs_timer_init(struct timer_list *t, cfs_timer_func_t *func, void *arg);
 void cfs_timer_done(struct timer_list *t);
-void cfs_timer_arm(struct timer_list *t, cfs_time_t deadline);
+void cfs_timer_arm(struct timer_list *t, unsigned long deadline);
 void cfs_timer_disarm(struct timer_list *t);
 int  cfs_timer_is_armed(struct timer_list *t);
-cfs_time_t cfs_timer_deadline(struct timer_list *t);
+unsigned long cfs_timer_deadline(struct timer_list *t);
 
 /*
  * Memory
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,14 +43,13 @@
 #define __LIBCFS_PRIVATE_H__
 
 /* XXX this layering violation is for nidstrings */
-#include <linux/lnet/types.h>
+#include "../lnet/types.h"
 
 #ifndef DEBUG_SUBSYSTEM
 # define DEBUG_SUBSYSTEM S_UNDEFINED
 #endif
 
 
-
 /*
  * When this is on, LASSERT macro includes check for assignment used instead
  * of equality check, but doesn't have unlikely(). Turn this on from time to
@@ -58,7 +57,6 @@
  */
 #define LASSERT_CHECKED (0)
 
-
 #define LASSERTF(cond, fmt, ...)					\
 do {									\
 	if (unlikely(!(cond))) {					\
@@ -80,18 +78,18 @@ do {									\
  */
 # define LINVRNT(exp) LASSERT(exp)
 #else
-# define LINVRNT(exp) ((void)sizeof!!(exp))
+# define LINVRNT(exp) ((void)sizeof !!(exp))
 #endif
 
 #define KLASSERT(e) LASSERT(e)
 
-void lbug_with_loc(struct libcfs_debug_msg_data *) __attribute__((noreturn));
+void lbug_with_loc(struct libcfs_debug_msg_data *)__attribute__((noreturn));
 
 #define LBUG()							  \
 do {								    \
 	LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_EMERG, NULL);	     \
 	lbug_with_loc(&msgdata);					\
-} while(0)
+} while (0)
 
 extern atomic_t libcfs_kmemory;
 /*
@@ -111,7 +109,6 @@ do {						\
 # define libcfs_kmem_read()			\
 	atomic_read(&libcfs_kmemory)
 
-
 #ifndef LIBCFS_VMALLOC_SIZE
 #define LIBCFS_VMALLOC_SIZE	(2 << PAGE_CACHE_SHIFT) /* 2 pages */
 #endif
@@ -220,7 +217,6 @@ int libcfs_debug_mark_buffer(const char
 
 void libcfs_debug_set_level(unsigned int debug_level);
 
-
 /*
  * allocate per-cpu-partition data, returned value is an array of pointers,
  * variable can be indexed by CPU ID.
@@ -339,8 +335,8 @@ do {							    \
 #define LASSERT_ATOMIC_ZERO(a)		  LASSERT_ATOMIC_EQ(a, 0)
 #define LASSERT_ATOMIC_POS(a)		   LASSERT_ATOMIC_GT(a, 0)
 
-#define CFS_ALLOC_PTR(ptr)      LIBCFS_ALLOC(ptr, sizeof (*(ptr)));
-#define CFS_FREE_PTR(ptr)       LIBCFS_FREE(ptr, sizeof (*(ptr)));
+#define CFS_ALLOC_PTR(ptr)      LIBCFS_ALLOC(ptr, sizeof(*(ptr)));
+#define CFS_FREE_PTR(ptr)       LIBCFS_FREE(ptr, sizeof(*(ptr)));
 
 /*
  * percpu partition lock
@@ -363,7 +359,6 @@ enum {
 	CFS_PERCPT_LOCK_EX	= -1, /* negative */
 };
 
-
 struct cfs_percpt_lock {
 	/* cpu-partition-table for this lock */
 	struct cfs_cpt_table	*pcl_cptab;
@@ -380,7 +375,6 @@ cfs_percpt_lock_num(struct cfs_percpt_lo
 	return cfs_cpt_number(pcl->pcl_cptab);
 }
 
-
 /*
  * create a cpu-partition lock based on CPU partition table \a cptab,
  * each private lock has extra \a psize bytes padding data
@@ -400,7 +394,6 @@ void cfs_percpt_atomic_free(atomic_t **r
 /* return sum of all percpu refs */
 int cfs_percpt_atomic_summary(atomic_t **refs);
 
-
 /** Compile-time assertion.
 
  * Check an invariant described by a constant expression at compile time by
@@ -415,7 +408,7 @@ int cfs_percpt_atomic_summary(atomic_t *
  *       value  after  conversion...
  *
  */
-#define CLASSERT(cond) do {switch(42) {case (cond): case 0: break;}} while (0)
+#define CLASSERT(cond) do {switch (42) {case (cond): case 0: break; } } while (0)
 
 /* support decl needed both by kernel and liblustre */
 int	 libcfs_isknown_lnd(int type);
@@ -440,11 +433,11 @@ int	 cfs_match_nid(lnet_nid_t nid, struc
 /** extract the network part of an lnet_nid_t */
 #define LNET_NIDNET(nid)       ((__u32)(((nid) >> 32)) & 0xffffffff)
 /** make an lnet_nid_t from a network part and an address part */
-#define LNET_MKNID(net,addr)   ((((__u64)(net))<<32)|((__u64)(addr)))
+#define LNET_MKNID(net, addr)   ((((__u64)(net))<<32)|((__u64)(addr)))
 /* how net encodes type:number */
 #define LNET_NETNUM(net)       ((net) & 0xffff)
 #define LNET_NETTYP(net)       (((net) >> 16) & 0xffff)
-#define LNET_MKNET(typ,num)    ((((__u32)(typ))<<16)|((__u32)(num)))
+#define LNET_MKNET(typ, num)    ((((__u32)(typ))<<16)|((__u32)(num)))
 /** @} lnet_addr */
 
 /* max value for numeric network address */
@@ -458,7 +451,6 @@ int	 cfs_match_nid(lnet_nid_t nid, struc
 /* --------------------------------------------------------------------
  * Light-weight trace
  * Support for temporary event tracing with minimal Heisenberg effect.
- * All stuff about lwt are put in arch/kp30.h
  * -------------------------------------------------------------------- */
 
 struct libcfs_device_userstate
@@ -469,24 +461,25 @@ struct libcfs_device_userstate
 
 /* what used to be in portals_lib.h */
 #ifndef MIN
-# define MIN(a,b) (((a)<(b)) ? (a): (b))
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 #ifndef MAX
-# define MAX(a,b) (((a)>(b)) ? (a): (b))
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
 
-#define MKSTR(ptr) ((ptr))? (ptr) : ""
+#define MKSTR(ptr) ((ptr)) ? (ptr) : ""
 
-static inline int cfs_size_round4 (int val)
+static inline int cfs_size_round4(int val)
 {
 	return (val + 3) & (~0x3);
 }
 
 #ifndef HAVE_CFS_SIZE_ROUND
-static inline int cfs_size_round (int val)
+static inline int cfs_size_round(int val)
 {
 	return (val + 7) & (~0x7);
 }
+
 #define HAVE_CFS_SIZE_ROUND
 #endif
 
@@ -525,21 +518,21 @@ static inline unsigned int cfs_power2_ro
 	return val;
 }
 
-#define LOGL(var,len,ptr)				       \
+#define LOGL(var, len, ptr)				       \
 do {							    \
 	if (var)						\
 		memcpy((char *)ptr, (const char *)var, len);    \
 	ptr += cfs_size_round(len);			     \
 } while (0)
 
-#define LOGU(var,len,ptr)				       \
+#define LOGU(var, len, ptr)				       \
 do {							    \
 	if (var)						\
 		memcpy((char *)var, (const char *)ptr, len);    \
 	ptr += cfs_size_round(len);			     \
 } while (0)
 
-#define LOGL0(var,len,ptr)			      \
+#define LOGL0(var, len, ptr)			      \
 do {						    \
 	if (!len)				       \
 		break;				  \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,28 +43,27 @@
  * generic time manipulation functions.
  */
 
-static inline cfs_time_t cfs_time_add(cfs_time_t t, cfs_duration_t d)
+static inline unsigned long cfs_time_add(unsigned long t, long d)
 {
-	return (cfs_time_t)(t + d);
+	return (unsigned long)(t + d);
 }
 
-static inline cfs_duration_t cfs_time_sub(cfs_time_t t1, cfs_time_t t2)
+static inline unsigned long cfs_time_sub(unsigned long t1, unsigned long t2)
 {
-	return (cfs_time_t)(t1 - t2);
+	return (unsigned long)(t1 - t2);
 }
 
-static inline int cfs_time_after(cfs_time_t t1, cfs_time_t t2)
+static inline int cfs_time_after(unsigned long t1, unsigned long t2)
 {
-	return cfs_time_before(t2, t1);
+	return time_before(t2, t1);
 }
 
-static inline int cfs_time_aftereq(cfs_time_t t1, cfs_time_t t2)
+static inline int cfs_time_aftereq(unsigned long t1, unsigned long t2)
 {
-	return cfs_time_beforeq(t2, t1);
+	return time_before_eq(t2, t1);
 }
 
-
-static inline cfs_time_t cfs_time_shift(int seconds)
+static inline unsigned long cfs_time_shift(int seconds)
 {
 	return cfs_time_add(cfs_time_current(), cfs_time_seconds(seconds));
 }
@@ -72,7 +71,7 @@ static inline cfs_time_t cfs_time_shift(
 static inline long cfs_timeval_sub(struct timeval *large, struct timeval *small,
 				   struct timeval *result)
 {
-	long r = (long) (
+	long r = (long)(
 		(large->tv_sec - small->tv_sec) * ONE_MILLION +
 		(large->tv_usec - small->tv_usec));
 	if (result != NULL) {
@@ -82,12 +81,12 @@ static inline long cfs_timeval_sub(struc
 	return r;
 }
 
-static inline void cfs_slow_warning(cfs_time_t now, int seconds, char *msg)
+static inline void cfs_slow_warning(unsigned long now, int seconds, char *msg)
 {
 	if (cfs_time_after(cfs_time_current(),
 			   cfs_time_add(now, cfs_time_seconds(15))))
 		CERROR("slow %s "CFS_TIME_T" sec\n", msg,
-		       cfs_duration_sec(cfs_time_sub(cfs_time_current(),now)));
+		       cfs_duration_sec(cfs_time_sub(cfs_time_current(), now)));
 }
 
 #define CFS_RATELIMIT(seconds)				  \
@@ -112,7 +111,7 @@ static inline void cfs_slow_warning(cfs_
  */
 static inline void cfs_fs_timeval(struct timeval *tv)
 {
-	cfs_fs_time_t time;
+	struct timespec time;
 
 	cfs_fs_time_current(&time);
 	cfs_fs_time_usec(&time, tv);
@@ -122,7 +121,7 @@ static inline void cfs_fs_timeval(struct
  * return valid time-out based on user supplied one. Currently we only check
  * that time-out is not shorted than allowed.
  */
-static inline cfs_duration_t cfs_timeout_cap(cfs_duration_t timeout)
+static inline long cfs_timeout_cap(long timeout)
 {
 	if (timeout < CFS_TICK)
 		timeout = CFS_TICK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef __LIBCFS_LINUX_KP30_H__
-#define __LIBCFS_LINUX_KP30_H__
-
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/kmod.h>
-#include <linux/notifier.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/highmem.h>
-#include <linux/module.h>
-#include <asm/atomic.h>
-#include <asm/uaccess.h>
-#include <linux/rwsem.h>
-#include <linux/proc_fs.h>
-#include <linux/file.h>
-#include <linux/smp.h>
-#include <linux/ctype.h>
-#include <linux/compiler.h>
-#include <linux/mm_inline.h>
-#include <linux/kallsyms.h>
-#include <linux/moduleparam.h>
-#include <linux/scatterlist.h>
-
-#include <linux/libcfs/linux/portals_compat25.h>
-
-/* this is a bit chunky */
-
-# define LPU64 "%llu"
-# define LPD64 "%lld"
-# define LPX64 "%#llx"
-# define LPX64i "%llx"
-# define LPO64 "%#llo"
-# define LPF64 "L"
-
-/*
- * long_ptr_t & ulong_ptr_t, same to "long" for gcc
- */
-# define LPLU "%lu"
-# define LPLD "%ld"
-# define LPLX "%#lx"
-
-/*
- * pid_t
- */
-# define LPPID "%d"
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,28 +42,57 @@
 #endif
 
 
-
-#include <stdarg.h>
-#include <linux/libcfs/linux/linux-cpu.h>
-#include <linux/libcfs/linux/linux-time.h>
-#include <linux/libcfs/linux/linux-mem.h>
-#include <linux/libcfs/linux/linux-prim.h>
-#include <linux/libcfs/linux/linux-lock.h>
-#include <linux/libcfs/linux/linux-tcpip.h>
-#include <linux/libcfs/linux/linux-bitops.h>
-#include <linux/libcfs/linux/linux-types.h>
-#include <linux/libcfs/linux/kp30.h>
-
-#include <asm/types.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/kthread.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/mm_inline.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/proc_fs.h>
+#include <linux/random.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/timer.h>
 #include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/vmalloc.h>
+#include <net/sock.h>
+#include <asm/atomic.h>
+#include <asm/div64.h>
 #include <asm/timex.h>
-#include <linux/sched.h> /* THREAD_SIZE */
-#include <linux/rbtree.h>
+#include <asm/uaccess.h>
+#include <stdarg.h>
+#include "linux-cpu.h"
+#include "linux-time.h"
+#include "linux-mem.h"
+#include "portals_compat25.h"
+
 
 #define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5)
 
 #if !defined(__x86_64__)
-# ifdef  __ia64__
+# ifdef __ia64__
 #  define CDEBUG_STACK() (THREAD_SIZE -				 \
 			  ((unsigned long)__builtin_dwarf_cfa() &       \
 			   (THREAD_SIZE - 1)))
@@ -89,7 +118,7 @@ do {								    \
 } while (0)
 #define CFS_CHECK_STACK(msgdata, mask, cdls)  __CHECK_STACK(msgdata, mask, cdls)
 #else /* __x86_64__ */
-#define CFS_CHECK_STACK(msgdata, mask, cdls) do {} while(0)
+#define CFS_CHECK_STACK(msgdata, mask, cdls) do {} while (0)
 #define CDEBUG_STACK() (0L)
 #endif /* __x86_64__ */
 
@@ -103,7 +132,7 @@ do {								    \
  *
  * Implementation is in linux-curproc.c
  */
-#define CFS_CURPROC_COMM_MAX (sizeof ((struct task_struct *)0)->comm)
+#define CFS_CURPROC_COMM_MAX (sizeof((struct task_struct *)0)->comm)
 
 #include <linux/capability.h>
 
@@ -116,6 +145,4 @@ typedef long long_ptr_t;
 #endif
 
 
-
-
 #endif /* _LINUX_LIBCFS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-bitops.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-bitops.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-bitops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-bitops.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/linux/linux-bitops.h
- */
-#include <linux/bitops.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,6 @@
 #error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
 #endif
 
-
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/topology.h>
@@ -79,88 +78,5 @@ struct cfs_cpt_table {
 	nodemask_t			*ctb_nodemask;
 };
 
-/**
- * comment out definitions for compatible layer
- *
- * typedef cpumask_t			   cfs_cpumask_t;
- *
- * #define cfs_cpu_current()		   smp_processor_id()
- * #define cfs_cpu_online(i)		   cpu_online(i)
- * #define cfs_cpu_online_num()		num_online_cpus()
- * #define cfs_cpu_online_for_each(i)	  for_each_online_cpu(i)
- * #define cfs_cpu_possible_num()	      num_possible_cpus()
- * #define cfs_cpu_possible_for_each(i)	for_each_possible_cpu(i)
- *
- * #ifdef CONFIG_CPUMASK_SIZE
- * #define cfs_cpu_mask_size()		 cpumask_size()
- * #else
- * #define cfs_cpu_mask_size()		 sizeof(cfs_cpumask_t)
- * #endif
- *
- * #define cfs_cpu_mask_set(i, mask)	   cpu_set(i, mask)
- * #define cfs_cpu_mask_unset(i, mask)	 cpu_clear(i, mask)
- * #define cfs_cpu_mask_isset(i, mask)	 cpu_isset(i, mask)
- * #define cfs_cpu_mask_clear(mask)	    cpus_clear(mask)
- * #define cfs_cpu_mask_empty(mask)	    cpus_empty(mask)
- * #define cfs_cpu_mask_weight(mask)	   cpus_weight(mask)
- * #define cfs_cpu_mask_first(mask)	    first_cpu(mask)
- * #define cfs_cpu_mask_any_online(mask)      (any_online_cpu(mask) != NR_CPUS)
- * #define cfs_cpu_mask_for_each(i, mask)      for_each_cpu_mask(i, mask)
- * #define cfs_cpu_mask_bind(t, mask)	  set_cpus_allowed(t, mask)
- *
- * #ifdef HAVE_CPUMASK_COPY
- * #define cfs_cpu_mask_copy(dst, src)	 cpumask_copy(dst, src)
- * #else
- * #define cfs_cpu_mask_copy(dst, src)	 memcpy(dst, src, sizeof(*src))
- * #endif
- *
- * static inline void
- * cfs_cpu_mask_of_online(cfs_cpumask_t *mask)
- * {
- * cfs_cpu_mask_copy(mask, &cpu_online_map);
- * }
- *
- * #ifdef CONFIG_NUMA
- *
- * #define CFS_NODE_NR			 MAX_NUMNODES
- *
- * typedef nodemask_t			  cfs_node_mask_t;
- *
- * #define cfs_node_of_cpu(cpu)		cpu_to_node(cpu)
- * #define cfs_node_online(i)		  node_online(i)
- * #define cfs_node_online_num()	       num_online_nodes()
- * #define cfs_node_online_for_each(i)	 for_each_online_node(i)
- * #define cfs_node_possible_num()	     num_possible_nodes()
- * #define cfs_node_possible_for_each(i)       for_each_node(i)
- *
- * static inline void cfs_node_to_cpumask(int node, cfs_cpumask_t *mask)
- * {
- * #if defined(HAVE_NODE_TO_CPUMASK)
- *      *mask = node_to_cpumask(node);
- * #elif defined(HAVE_CPUMASK_OF_NODE)
- *      cfs_cpu_mask_copy(mask, cpumask_of_node(node));
- * #else
- * # error "Needs node_to_cpumask or cpumask_of_node"
- * #endif
- * }
- *
- * #define cfs_node_mask_set(i, mask)	  node_set(i, mask)
- * #define cfs_node_mask_unset(i, mask)	node_clear(i, mask)
- * #define cfs_node_mask_isset(i, mask)	node_isset(i, mask)
- * #define cfs_node_mask_clear(mask)	   nodes_reset(mask)
- * #define cfs_node_mask_empty(mask)	   nodes_empty(mask)
- * #define cfs_node_mask_weight(mask)	  nodes_weight(mask)
- * #define cfs_node_mask_for_each(i, mask)     for_each_node_mask(i, mask)
- * #define cfs_node_mask_copy(dst, src)	memcpy(dst, src, sizeof(*src))
- *
- * static inline void
- * cfs_node_mask_of_online(cfs_node_mask_t *mask)
- * {
- *       cfs_node_mask_copy(mask, &node_online_map);
- * }
- *
- * #endif
- */
-
 #endif /* CONFIG_SMP */
 #endif /* __LIBCFS_LINUX_CPU_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-crypto.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-crypto.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-crypto.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-crypto.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
- /*
- * 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
- */
-
-/**
- * Linux crypto hash specific functions.
- */
-
-/**
- * Functions for start/stop shash CRC32 algorithm.
- */
-int cfs_crypto_crc32_register(void);
-void cfs_crypto_crc32_unregister(void);
-
-/**
- * Functions for start/stop shash adler32 algorithm.
- */
-int cfs_crypto_adler32_register(void);
-void cfs_crypto_adler32_unregister(void);
-
-/**
- * Functions for start/stop shash crc32 pclmulqdq
- */
-int cfs_crypto_crc32_pclmul_register(void);
-void cfs_crypto_crc32_pclmul_unregister(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-lock.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-lock.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-lock.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-lock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,204 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/linux/linux-lock.h
- *
- * Basic library routines.
- */
-
-#ifndef __LIBCFS_LINUX_CFS_LOCK_H__
-#define __LIBCFS_LINUX_CFS_LOCK_H__
-
-#ifndef __LIBCFS_LIBCFS_H__
-#error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
-#endif
-
-
-#include <linux/mutex.h>
-
-/*
- * IMPORTANT !!!!!!!!
- *
- * All locks' declaration are not guaranteed to be initialized,
- * although some of them are initialized in Linux. All locks
- * declared by CFS_DECL_* should be initialized explicitly.
- */
-
-/*
- * spin_lock "implementation" (use Linux kernel's primitives)
- *
- * - spin_lock_init(x)
- * - spin_lock(x)
- * - spin_lock_bh(x)
- * - spin_lock_bh_init(x)
- * - spin_unlock(x)
- * - spin_unlock_bh(x)
- * - spin_trylock(x)
- * - assert_spin_locked(x)
- *
- * - spin_lock_irq(x)
- * - spin_lock_irqsave(x, f)
- * - spin_unlock_irqrestore(x, f)
- * - read_lock_irqsave(lock, f)
- * - write_lock_irqsave(lock, f)
- * - write_unlock_irqrestore(lock, f)
- */
-
-/*
- * spinlock "implementation"
- */
-
-
-
-
-/*
- * rw_semaphore "implementation" (use Linux kernel's primitives)
- *
- * - sema_init(x)
- * - init_rwsem(x)
- * - down_read(x)
- * - up_read(x)
- * - down_write(x)
- * - up_write(x)
- */
-
-
-#define fini_rwsem(s)		do {} while (0)
-
-
-/*
- * rwlock_t "implementation" (use Linux kernel's primitives)
- *
- * - rwlock_init(x)
- * - read_lock(x)
- * - read_unlock(x)
- * - write_lock(x)
- * - write_unlock(x)
- * - write_lock_bh(x)
- * - write_unlock_bh(x)
- *
- * - RW_LOCK_UNLOCKED
- */
-
-
-#ifndef DEFINE_RWLOCK
-#define DEFINE_RWLOCK(lock)	rwlock_t lock = __RW_LOCK_UNLOCKED(lock)
-#endif
-
-/*
- * completion "implementation" (use Linux kernel's primitives)
- *
- * - DECLARE_COMPLETION(work)
- * - INIT_COMPLETION(c)
- * - COMPLETION_INITIALIZER(work)
- * - init_completion(c)
- * - complete(c)
- * - wait_for_completion(c)
- * - wait_for_completion_interruptible(c)
- * - fini_completion(c)
- */
-#define fini_completion(c) do { } while (0)
-
-/*
- * semaphore "implementation" (use Linux kernel's primitives)
- * - DEFINE_SEMAPHORE(name)
- * - sema_init(sem, val)
- * - up(sem)
- * - down(sem)
- * - down_interruptible(sem)
- * - down_trylock(sem)
- */
-
-/*
- * mutex "implementation" (use Linux kernel's primitives)
- *
- * - DEFINE_MUTEX(name)
- * - mutex_init(x)
- * - mutex_lock(x)
- * - mutex_unlock(x)
- * - mutex_trylock(x)
- * - mutex_is_locked(x)
- * - mutex_destroy(x)
- */
-
-#ifndef lockdep_set_class
-
-/**************************************************************************
- *
- * Lockdep "implementation". Also see liblustre.h
- *
- **************************************************************************/
-
-struct lock_class_key {
-	;
-};
-
-#define lockdep_set_class(lock, key) \
-	do { (void)sizeof(lock); (void)sizeof(key); } while (0)
-/* This has to be a macro, so that `subclass' can be undefined in kernels
- * that do not support lockdep. */
-
-
-static inline void lockdep_off(void)
-{
-}
-
-static inline void lockdep_on(void)
-{
-}
-#else
-
-#endif /* lockdep_set_class */
-
-#ifndef CONFIG_DEBUG_LOCK_ALLOC
-#ifndef mutex_lock_nested
-#define mutex_lock_nested(mutex, subclass) mutex_lock(mutex)
-#endif
-
-#ifndef spin_lock_nested
-#define spin_lock_nested(lock, subclass) spin_lock(lock)
-#endif
-
-#ifndef down_read_nested
-#define down_read_nested(lock, subclass) down_read(lock)
-#endif
-
-#ifndef down_write_nested
-#define down_write_nested(lock, subclass) down_write(lock)
-#endif
-#endif /* CONFIG_DEBUG_LOCK_ALLOC */
-
-
-#endif /* __LIBCFS_LINUX_CFS_LOCK_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,7 +45,6 @@
 #error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
 #endif
 
-
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
@@ -55,7 +54,7 @@
 
 #ifndef HAVE_LIBCFS_CPT
 /* Need this for cfs_cpt_table */
-#include <linux/libcfs/libcfs_cpu.h>
+#include "../libcfs_cpu.h"
 #endif
 
 #define CFS_PAGE_MASK		   (~((__u64)PAGE_CACHE_SIZE-1))
@@ -73,15 +72,9 @@
 #define NUM_CACHEPAGES totalram_pages
 #endif
 
-/*
- * In Linux there is no way to determine whether current execution context is
- * blockable.
- */
-#define ALLOC_ATOMIC_TRY   GFP_ATOMIC
-
 #define DECL_MMSPACE		mm_segment_t __oldfs
 #define MMSPACE_OPEN \
-	do { __oldfs = get_fs(); set_fs(get_ds());} while(0)
+	do { __oldfs = get_fs(); set_fs(get_ds()); } while (0)
 #define MMSPACE_CLOSE	       set_fs(__oldfs)
 
 #endif /* __LINUX_CFS_MEM_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/linux/linux-prim.h
- *
- * Basic library routines.
- */
-
-#ifndef __LIBCFS_LINUX_CFS_PRIM_H__
-#define __LIBCFS_LINUX_CFS_PRIM_H__
-
-#ifndef __LIBCFS_LIBCFS_H__
-#error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
-#endif
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/random.h>
-
-#include <linux/miscdevice.h>
-#include <linux/libcfs/linux/portals_compat25.h>
-#include <asm/div64.h>
-
-#include <linux/libcfs/linux/linux-time.h>
-
-/*
- * Sysctl register
- */
-typedef struct ctl_table		ctl_table_t;
-typedef struct ctl_table_header		ctl_table_header_t;
-
-#define DECLARE_PROC_HANDLER(name)		      \
-static int					      \
-LL_PROC_PROTO(name)				     \
-{						       \
-	DECLARE_LL_PROC_PPOS_DECL;		      \
-							\
-	return proc_call_handler(table->data, write,    \
-				 ppos, buffer, lenp,    \
-				 __##name);	     \
-}
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/linux/linux-tcpip.h
- *
- * Basic library routines.
- */
-
-#ifndef __LIBCFS_LINUX_CFS_TCP_H__
-#define __LIBCFS_LINUX_CFS_TCP_H__
-
-#ifndef __LIBCFS_LIBCFS_H__
-#error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
-#endif
-
-
-#include <net/sock.h>
-
-typedef struct socket   socket_t;
-
-#define SOCK_SNDBUF(so)	 ((so)->sk->sk_sndbuf)
-#define SOCK_TEST_NOSPACE(so)   test_bit(SOCK_NOSPACE, &(so)->flags)
-
-static inline int
-cfs_sock_error(struct socket *sock)
-{
-	return sock->sk->sk_err;
-}
-
-static inline int
-cfs_sock_wmem_queued(struct socket *sock)
-{
-	return sock->sk->sk_wmem_queued;
-}
-
-#define cfs_sk_sleep(sk)	sk_sleep(sk)
-
-#define DEFAULT_NET	(&init_net)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,56 +45,15 @@
 #error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
 #endif
 
-
-/* Portable time API */
-
-/*
- * Platform provides three opaque data-types:
- *
- *  cfs_time_t	represents point in time. This is internal kernel
- *		    time rather than "wall clock". This time bears no
- *		    relation to gettimeofday().
- *
- *  cfs_duration_t    represents time interval with resolution of internal
- *		    platform clock
- *
- *  cfs_fs_time_t     represents instance in world-visible time. This is
- *		    used in file-system time-stamps
- *
- *  cfs_time_t     cfs_time_current(void);
- *  cfs_time_t     cfs_time_add    (cfs_time_t, cfs_duration_t);
- *  cfs_duration_t cfs_time_sub    (cfs_time_t, cfs_time_t);
- *  int	    cfs_impl_time_before (cfs_time_t, cfs_time_t);
- *  int	    cfs_impl_time_before_eq(cfs_time_t, cfs_time_t);
- *
- *  cfs_duration_t cfs_duration_build(int64_t);
- *
- *  time_t	 cfs_duration_sec (cfs_duration_t);
- *  void	   cfs_duration_usec(cfs_duration_t, struct timeval *);
- *  void	   cfs_duration_nsec(cfs_duration_t, struct timespec *);
- *
- *  void	   cfs_fs_time_current(cfs_fs_time_t *);
- *  time_t	 cfs_fs_time_sec    (cfs_fs_time_t *);
- *  void	   cfs_fs_time_usec   (cfs_fs_time_t *, struct timeval *);
- *  void	   cfs_fs_time_nsec   (cfs_fs_time_t *, struct timespec *);
- *  int	    cfs_fs_time_before (cfs_fs_time_t *, cfs_fs_time_t *);
- *  int	    cfs_fs_time_beforeq(cfs_fs_time_t *, cfs_fs_time_t *);
- *
- *  CFS_TIME_FORMAT
- *  CFS_DURATION_FORMAT
- *
- */
-
 #define ONE_BILLION ((u_int64_t)1000000000)
 #define ONE_MILLION 1000000
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <asm/div64.h>
 
-#include <linux/libcfs/linux/portals_compat25.h>
+#include "portals_compat25.h"
 
 /*
  * post 2.5 kernels.
@@ -102,133 +61,58 @@
 
 #include <linux/jiffies.h>
 
-typedef struct timespec cfs_fs_time_t;
 
-static inline void cfs_fs_time_usec(cfs_fs_time_t *t, struct timeval *v)
+static inline void cfs_fs_time_usec(struct timespec *t, struct timeval *v)
 {
 	v->tv_sec  = t->tv_sec;
 	v->tv_usec = t->tv_nsec / 1000;
 }
 
-static inline void cfs_fs_time_nsec(cfs_fs_time_t *t, struct timespec *s)
-{
-	*s = *t;
-}
-
-/*
- * internal helper function used by cfs_fs_time_before*()
- */
-static inline unsigned long long __cfs_fs_time_flat(cfs_fs_time_t *t)
-{
-	return (unsigned long long)t->tv_sec * ONE_BILLION + t->tv_nsec;
-}
-
-
 /*
  * Generic kernel stuff
  */
 
-typedef unsigned long cfs_time_t;      /* jiffies */
-typedef long cfs_duration_t;
-typedef cycles_t cfs_cycles_t;
-
-static inline int cfs_time_before(cfs_time_t t1, cfs_time_t t2)
-{
-	return time_before(t1, t2);
-}
-
-static inline int cfs_time_beforeq(cfs_time_t t1, cfs_time_t t2)
-{
-	return time_before_eq(t1, t2);
-}
-
-static inline cfs_time_t cfs_time_current(void)
+static inline unsigned long cfs_time_current(void)
 {
 	return jiffies;
 }
 
-static inline time_t cfs_time_current_sec(void)
-{
-	return get_seconds();
-}
-
-static inline void cfs_fs_time_current(cfs_fs_time_t *t)
+static inline void cfs_fs_time_current(struct timespec *t)
 {
 	*t = CURRENT_TIME;
 }
 
-static inline time_t cfs_fs_time_sec(cfs_fs_time_t *t)
+static inline time_t cfs_fs_time_sec(struct timespec *t)
 {
 	return t->tv_sec;
 }
 
-static inline int cfs_fs_time_before(cfs_fs_time_t *t1, cfs_fs_time_t *t2)
-{
-	return __cfs_fs_time_flat(t1) <  __cfs_fs_time_flat(t2);
-}
-
-static inline int cfs_fs_time_beforeq(cfs_fs_time_t *t1, cfs_fs_time_t *t2)
-{
-	return __cfs_fs_time_flat(t1) <= __cfs_fs_time_flat(t2);
-}
-
-#if 0
-static inline cfs_duration_t cfs_duration_build(int64_t nano)
-{
-#if (BITS_PER_LONG == 32)
-	/* We cannot use do_div(t, ONE_BILLION), do_div can only process
-	 * 64 bits n and 32 bits base */
-	int64_t  t = nano * HZ;
-	do_div(t, 1000);
-	do_div(t, 1000000);
-	return (cfs_duration_t)t;
-#else
-	return (nano * HZ / ONE_BILLION);
-#endif
-}
-#endif
-
-static inline cfs_duration_t cfs_time_seconds(int seconds)
+static inline long cfs_time_seconds(int seconds)
 {
-	return ((cfs_duration_t)seconds) * HZ;
+	return ((long)seconds) * HZ;
 }
 
-static inline time_t cfs_duration_sec(cfs_duration_t d)
+static inline time_t cfs_duration_sec(long d)
 {
 	return d / HZ;
 }
 
-static inline void cfs_duration_usec(cfs_duration_t d, struct timeval *s)
+static inline void cfs_duration_usec(long d, struct timeval *s)
 {
 #if (BITS_PER_LONG == 32) && (HZ > 4096)
 	__u64 t;
 
 	s->tv_sec = d / HZ;
-	t = (d - (cfs_duration_t)s->tv_sec * HZ) * ONE_MILLION;
+	t = (d - (long)s->tv_sec * HZ) * ONE_MILLION;
 	do_div(t, HZ);
 	s->tv_usec = t;
 #else
 	s->tv_sec = d / HZ;
-	s->tv_usec = ((d - (cfs_duration_t)s->tv_sec * HZ) * \
+	s->tv_usec = ((d - (long)s->tv_sec * HZ) * \
 		ONE_MILLION) / HZ;
 #endif
 }
 
-static inline void cfs_duration_nsec(cfs_duration_t d, struct timespec *s)
-{
-#if (BITS_PER_LONG == 32)
-	__u64 t;
-
-	s->tv_sec = d / HZ;
-	t = (d - s->tv_sec * HZ) * ONE_BILLION;
-	do_div(t, HZ);
-	s->tv_nsec = t;
-#else
-	s->tv_sec = d / HZ;
-	s->tv_nsec = ((d - s->tv_sec * HZ) * ONE_BILLION) / HZ;
-#endif
-}
-
 #define cfs_time_current_64 get_jiffies_64
 
 static inline __u64 cfs_time_add_64(__u64 t, __u64 d)
@@ -252,7 +136,6 @@ static inline int cfs_time_beforeq_64(__
 	return (__s64)t2 - (__s64)t1 >= 0;
 }
 
-
 /*
  * One jiffy
  */
@@ -261,14 +144,4 @@ static inline int cfs_time_beforeq_64(__
 #define CFS_TIME_T	      "%lu"
 #define CFS_DURATION_T	  "%ld"
 
-
 #endif /* __LIBCFS_LINUX_LINUX_TIME_H__ */
-/*
- * Local variables:
- * c-indentation-style: "K&R"
- * c-basic-offset: 8
- * tab-width: 8
- * fill-column: 80
- * scroll-step: 1
- * End:
- */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-types.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-types.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/linux-types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/include/libcfs/user-bitops.h
- */
-#include <linux/types.h>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,14 +37,14 @@
 #ifndef __LIBCFS_LINUX_PORTALS_COMPAT_H__
 #define __LIBCFS_LINUX_PORTALS_COMPAT_H__
 
-// XXX BUG 1511 -- remove this stanza and all callers when bug 1511 is resolved
+/* XXX BUG 1511 -- remove this stanza and all callers when bug 1511 is resolved */
 #if defined(SPINLOCK_DEBUG) && SPINLOCK_DEBUG
 #  define SIGNAL_MASK_ASSERT() \
    LASSERT(current->sighand->siglock.magic == SPINLOCK_MAGIC)
 #else
 # define SIGNAL_MASK_ASSERT()
 #endif
-// XXX BUG 1511 -- remove this stanza and all callers when bug 1511 is resolved
+/* XXX BUG 1511 -- remove this stanza and all callers when bug 1511 is resolved */
 
 #define SIGNAL_MASK_LOCK(task, flags)				  \
 	spin_lock_irqsave(&task->sighand->siglock, flags)
@@ -78,22 +78,4 @@
 #define __cfs_fls __fls
 #endif
 
-#define ll_proc_dointvec(table, write, filp, buffer, lenp, ppos)	\
-	proc_dointvec(table, write, buffer, lenp, ppos);
-
-#define ll_proc_dolongvec(table, write, filp, buffer, lenp, ppos)	\
-	proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
-#define ll_proc_dostring(table, write, filp, buffer, lenp, ppos)	\
-	proc_dostring(table, write, buffer, lenp, ppos);
-#define LL_PROC_PROTO(name)					     \
-	name(ctl_table_t *table, int write,		      \
-	     void __user *buffer, size_t *lenp, loff_t *ppos)
-#define DECLARE_LL_PROC_PPOS_DECL
-
-/* helper for sysctl handlers */
-int proc_call_handler(void *data, int write,
-		      loff_t *ppos, void *buffer, size_t *lenp,
-		      int (*handler)(void *data, int write,
-				     loff_t pos, void *buffer, int len));
-
 #endif /* _PORTALS_COMPAT_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/lucache.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/lucache.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/lucache.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/lucache.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #ifndef _LUCACHE_H
 #define _LUCACHE_H
 
-#include <linux/libcfs/libcfs.h>
+#include "libcfs.h"
 
 /** \defgroup ucache ucache
  *
@@ -88,8 +88,8 @@ struct upcall_cache_entry {
 	atomic_t	    ue_refcount;
 	int		     ue_flags;
 	wait_queue_head_t	     ue_waitq;
-	cfs_time_t	      ue_acquire_expire;
-	cfs_time_t	      ue_expire;
+	unsigned long	      ue_acquire_expire;
+	unsigned long	      ue_expire;
 	union {
 		struct md_identity     identity;
 	} u;
@@ -104,17 +104,17 @@ struct upcall_cache;
 struct upcall_cache_ops {
 	void	    (*init_entry)(struct upcall_cache_entry *, void *args);
 	void	    (*free_entry)(struct upcall_cache *,
-				      struct upcall_cache_entry *);
+				  struct upcall_cache_entry *);
 	int	     (*upcall_compare)(struct upcall_cache *,
-					  struct upcall_cache_entry *,
+				       struct upcall_cache_entry *,
 					  __u64 key, void *args);
 	int	     (*downcall_compare)(struct upcall_cache *,
-					    struct upcall_cache_entry *,
+					 struct upcall_cache_entry *,
 					    __u64 key, void *args);
 	int	     (*do_upcall)(struct upcall_cache *,
-				     struct upcall_cache_entry *);
+				  struct upcall_cache_entry *);
 	int	     (*parse_downcall)(struct upcall_cache *,
-					  struct upcall_cache_entry *, void *);
+				       struct upcall_cache_entry *, void *);
 };
 
 struct upcall_cache {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/params_tree.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/params_tree.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/libcfs/params_tree.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/libcfs/params_tree.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * API and structure definitions for params_tree.
- *
- * Author: LiuYing <emoly.liu@oracle.com>
- */
-#ifndef __PARAMS_TREE_H__
-#define __PARAMS_TREE_H__
-
-#include <linux/libcfs/libcfs.h>
-
-#undef LPROCFS
-#if  defined(CONFIG_PROC_FS)
-# define LPROCFS
-#endif
-
-#ifdef LPROCFS
-typedef struct file			     cfs_param_file_t;
-typedef struct inode			    cfs_inode_t;
-typedef struct proc_inode		       cfs_proc_inode_t;
-typedef struct seq_file			 cfs_seq_file_t;
-typedef struct seq_operations		   cfs_seq_ops_t;
-typedef struct file_operations		  cfs_param_file_ops_t;
-typedef struct proc_dir_entry		   cfs_param_dentry_t;
-typedef struct poll_table_struct		cfs_poll_table_t;
-#define CFS_PARAM_MODULE			THIS_MODULE
-#define cfs_file_private(file)		  (file->private_data)
-#define cfs_dentry_data(dentry)		 (dentry->data)
-#define cfs_proc_inode_pde(proc_inode)	  (proc_inode->pde)
-#define cfs_proc_inode(proc_inode)	      (proc_inode->vfs_inode)
-#define cfs_seq_read_common		     seq_read
-#define cfs_seq_lseek_common		    seq_lseek
-#define cfs_seq_private(seq)		    (seq->private)
-#define cfs_seq_printf(seq, format, ...)	seq_printf(seq, format,  \
-							   ## __VA_ARGS__)
-#define cfs_seq_release(inode, file)	    seq_release(inode, file)
-#define cfs_seq_puts(seq, s)		    seq_puts(seq, s)
-#define cfs_seq_putc(seq, s)		    seq_putc(seq, s)
-#define cfs_seq_read(file, buf, count, ppos, rc) (rc = seq_read(file, buf, \
-							    count, ppos))
-#define cfs_seq_open(file, ops, rc)	     (rc = seq_open(file, ops))
-
-#else /* !LPROCFS */
-
-typedef struct cfs_params_file {
-	void	   *param_private;
-	loff_t	  param_pos;
-	unsigned int    param_flags;
-} cfs_param_file_t;
-
-typedef struct cfs_param_inode {
-	void    *param_private;
-} cfs_inode_t;
-
-typedef struct cfs_param_dentry {
-	void *param_data;
-} cfs_param_dentry_t;
-
-typedef struct cfs_proc_inode {
-	cfs_param_dentry_t *param_pde;
-	cfs_inode_t	 param_inode;
-} cfs_proc_inode_t;
-
-struct cfs_seq_operations;
-typedef struct cfs_seq_file {
-	char		      *buf;
-	size_t		     size;
-	size_t		     from;
-	size_t		     count;
-	loff_t		     index;
-	loff_t		     version;
-	struct mutex			lock;
-	struct cfs_seq_operations *op;
-	void		      *private;
-} cfs_seq_file_t;
-
-typedef struct cfs_seq_operations {
-	void *(*start) (cfs_seq_file_t *m, loff_t *pos);
-	void  (*stop) (cfs_seq_file_t *m, void *v);
-	void *(*next) (cfs_seq_file_t *m, void *v, loff_t *pos);
-	int   (*show) (cfs_seq_file_t *m, void *v);
-} cfs_seq_ops_t;
-
-typedef void *cfs_poll_table_t;
-
-typedef struct cfs_param_file_ops {
-	struct module *owner;
-	int (*open) (cfs_inode_t *, struct file *);
-	loff_t (*llseek)(struct file *, loff_t, int);
-	int (*release) (cfs_inode_t *, cfs_param_file_t *);
-	unsigned int (*poll) (struct file *, cfs_poll_table_t *);
-	ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
-	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
-} cfs_param_file_ops_t;
-typedef cfs_param_file_ops_t *cfs_lproc_filep_t;
-
-static inline cfs_proc_inode_t *FAKE_PROC_I(const cfs_inode_t *inode)
-{
-	return container_of(inode, cfs_proc_inode_t, param_inode);
-}
-
-#define CFS_PARAM_MODULE			NULL
-#define cfs_file_private(file)		  (file->param_private)
-#define cfs_dentry_data(dentry)		 (dentry->param_data)
-#define cfs_proc_inode(proc_inode)	      (proc_inode->param_inode)
-#define cfs_proc_inode_pde(proc_inode)	  (proc_inode->param_pde)
-#define cfs_seq_read_common		     NULL
-#define cfs_seq_lseek_common		    NULL
-#define cfs_seq_private(seq)		    (seq->private)
-#define cfs_seq_read(file, buf, count, ppos, rc) do {} while(0)
-#define cfs_seq_open(file, ops, rc)		     \
-do {						    \
-	 cfs_seq_file_t *p = cfs_file_private(file);    \
-	 if (!p) {				      \
-		LIBCFS_ALLOC(p, sizeof(*p));	    \
-		if (!p) {			       \
-			rc = -ENOMEM;		   \
-			break;			  \
-		}				       \
-		cfs_file_private(file) = p;	     \
-	}					       \
-	memset(p, 0, sizeof(*p));		       \
-	p->op = ops;				    \
-	rc = 0;					 \
-} while(0)
-
-#endif /* LPROCFS */
-
-/* XXX: params_tree APIs */
-
-#endif  /* __PARAMS_TREE_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/api.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/api.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/api.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/api.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,7 @@
  * @{
  */
 
-#include <linux/lnet/types.h>
+#include "../lnet/types.h"
 
 /** \defgroup lnet_init_fini Initialization and cleanup
  * The LNet must be properly initialized before any LNet calls can be made.
@@ -84,7 +84,6 @@ void LNetSnprintHandle(char *str, int st
 
 /** @} lnet_addr */
 
-
 /** \defgroup lnet_me Match entries
  *
  * A match entry (abbreviated as ME) describes a set of criteria to accept
@@ -171,7 +170,6 @@ int LNetEQFree(lnet_handle_eq_t eventq_i
 int LNetEQGet(lnet_handle_eq_t  eventq_in,
 	      lnet_event_t     *event_out);
 
-
 int LNetEQWait(lnet_handle_eq_t  eventq_in,
 	       lnet_event_t     *event_out);
 
@@ -204,7 +202,6 @@ int LNetGet(lnet_nid_t	self,
 	    unsigned int      offset_in);
 /** @} lnet_data */
 
-
 /** \defgroup lnet_misc Miscellaneous operations.
  * Miscellaneous operations.
  * @{ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/api-support.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/api-support.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/api-support.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/api-support.h	2014-09-28 17:29:07.000000000 -0400
@@ -35,10 +35,10 @@
 #ifndef __LNET_API_SUPPORT_H__
 #define __LNET_API_SUPPORT_H__
 
-#include <linux/lnet/linux/api-support.h>
+#include "linux/api-support.h"
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/types.h>
-#include <linux/lnet/lnet.h>
+#include "../libcfs/libcfs.h"
+#include "types.h"
+#include "lnet.h"
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lib-lnet.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lib-lnet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lib-lnet.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,12 +41,11 @@
 #ifndef __LNET_LIB_LNET_H__
 #define __LNET_LIB_LNET_H__
 
-#include <linux/lnet/linux/lib-lnet.h>
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/types.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-types.h>
+#include "linux/lib-lnet.h"
+#include "../libcfs/libcfs.h"
+#include "types.h"
+#include "lnet.h"
+#include "lib-types.h"
 
 extern lnet_t  the_lnet;			/* THE network */
 
@@ -167,7 +166,6 @@ lnet_net_lock_current(void)
 #define LNET_LOCK()		lnet_net_lock(LNET_LOCK_EX)
 #define LNET_UNLOCK()		lnet_net_unlock(LNET_LOCK_EX)
 
-
 #define lnet_ptl_lock(ptl)	spin_lock(&(ptl)->ptl_lock)
 #define lnet_ptl_unlock(ptl)	spin_unlock(&(ptl)->ptl_lock)
 #define lnet_eq_wait_lock()	spin_lock(&the_lnet.ln_eq_wait_lock)
@@ -177,7 +175,6 @@ lnet_net_lock_current(void)
 #define LNET_MUTEX_LOCK(m)	mutex_lock(m)
 #define LNET_MUTEX_UNLOCK(m)	mutex_unlock(m)
 
-
 #define MAX_PORTALS     64
 
 /* these are only used by code with LNET_USE_LIB_FREELIST, but we still
@@ -215,7 +212,6 @@ lnet_freelist_free(lnet_freelist_t *fl,
 	list_add(&o->fo_list, &fl->fl_list);
 }
 
-
 static inline lnet_eq_t *
 lnet_eq_alloc(void)
 {
@@ -572,7 +568,7 @@ lnet_peer_addref_locked(lnet_peer_t *lp)
 	lp->lp_refcount++;
 }
 
-extern void lnet_destroy_peer_locked(lnet_peer_t *lp);
+void lnet_destroy_peer_locked(lnet_peer_t *lp);
 
 static inline void
 lnet_peer_decref_locked(lnet_peer_t *lp)
@@ -641,15 +637,14 @@ lnet_net2rnethash(__u32 net)
 
 extern lnd_t the_lolnd;
 
+int lnet_cpt_of_nid_locked(lnet_nid_t nid);
+int lnet_cpt_of_nid(lnet_nid_t nid);
+lnet_ni_t *lnet_nid2ni_locked(lnet_nid_t nid, int cpt);
+lnet_ni_t *lnet_net2ni_locked(__u32 net, int cpt);
+lnet_ni_t *lnet_net2ni(__u32 net);
 
-extern int lnet_cpt_of_nid_locked(lnet_nid_t nid);
-extern int lnet_cpt_of_nid(lnet_nid_t nid);
-extern lnet_ni_t *lnet_nid2ni_locked(lnet_nid_t nid, int cpt);
-extern lnet_ni_t *lnet_net2ni_locked(__u32 net, int cpt);
-extern lnet_ni_t *lnet_net2ni(__u32 net);
-
-int lnet_notify(lnet_ni_t *ni, lnet_nid_t peer, int alive, cfs_time_t when);
-void lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, cfs_time_t when);
+int lnet_notify(lnet_ni_t *ni, lnet_nid_t peer, int alive, unsigned long when);
+void lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, unsigned long when);
 int lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway_nid,
 		   unsigned int priority);
 int lnet_check_routes(void);
@@ -715,7 +710,7 @@ lnet_ptl_unsetopt(lnet_portal_t *ptl, in
 
 /* match-table functions */
 struct list_head *lnet_mt_match_head(struct lnet_match_table *mtable,
-			       lnet_process_id_t id, __u64 mbits);
+				     lnet_process_id_t id, __u64 mbits);
 struct lnet_match_table *lnet_mt_of_attach(unsigned int index,
 					   lnet_process_id_t id, __u64 mbits,
 					   __u64 ignore_bits,
@@ -735,7 +730,7 @@ void lnet_portals_destroy(void);
 
 /* message functions */
 int lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr,
-		lnet_nid_t fromnid, void *private, int rdma_req);
+	       lnet_nid_t fromnid, void *private, int rdma_req);
 void lnet_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed,
 	       unsigned int offset, unsigned int mlen, unsigned int rlen);
 lnet_msg_t *lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *get_msg);
@@ -758,7 +753,7 @@ void lnet_counters_reset(void);
 
 unsigned int lnet_iov_nob(unsigned int niov, struct iovec *iov);
 int lnet_extract_iov(int dst_niov, struct iovec *dst,
-		      int src_niov, struct iovec *src,
+		     int src_niov, struct iovec *src,
 		      unsigned int offset, unsigned int len);
 
 unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov);
@@ -767,19 +762,19 @@ int lnet_extract_kiov(int dst_niov, lnet
 		      unsigned int offset, unsigned int len);
 
 void lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov,
-			unsigned int doffset,
+		       unsigned int doffset,
 			unsigned int nsiov, struct iovec *siov,
 			unsigned int soffset, unsigned int nob);
 void lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov,
-			 unsigned int iovoffset,
+			unsigned int iovoffset,
 			 unsigned int nkiov, lnet_kiov_t *kiov,
 			 unsigned int kiovoffset, unsigned int nob);
 void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov,
-			 unsigned int kiovoffset,
+			unsigned int kiovoffset,
 			 unsigned int niov, struct iovec *iov,
 			 unsigned int iovoffset, unsigned int nob);
 void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov,
-			  unsigned int doffset,
+			 unsigned int doffset,
 			  unsigned int nskiov, lnet_kiov_t *skiov,
 			  unsigned int soffset, unsigned int nob);
 
@@ -810,6 +805,7 @@ lnet_copy_flat2iov(unsigned int ndiov, s
 		   int slen, void *src, unsigned int soffset, unsigned int nob)
 {
 	struct iovec siov = {/*.iov_base = */ src, /*.iov_len = */slen};
+
 	lnet_copy_iov2iov(ndiov, diov, doffset,
 			  1, &siov, soffset, nob);
 }
@@ -819,6 +815,7 @@ lnet_copy_flat2kiov(unsigned int ndiov,
 		    int slen, void *src, unsigned int soffset, unsigned int nob)
 {
 	struct iovec siov = {/* .iov_base = */ src, /* .iov_len = */ slen};
+
 	lnet_copy_iov2kiov(ndiov, dkiov, doffset,
 			   1, &siov, soffset, nob);
 }
@@ -832,7 +829,7 @@ void lnet_register_lnd(lnd_t *lnd);
 void lnet_unregister_lnd(lnd_t *lnd);
 int lnet_set_ip_niaddr(lnet_ni_t *ni);
 
-int lnet_connect(socket_t **sockp, lnet_nid_t peer_nid,
+int lnet_connect(struct socket **sockp, lnet_nid_t peer_nid,
 		 __u32 local_ip, __u32 peer_ip, int peer_port);
 void lnet_connect_console_error(int rc, lnet_nid_t peer_nid,
 				__u32 peer_ip, int port);
@@ -871,5 +868,4 @@ void lnet_peer_tables_destroy(void);
 int lnet_peer_tables_create(void);
 void lnet_debug_peer(lnet_nid_t nid);
 
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lib-types.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lib-types.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lib-types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lib-types.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,11 +42,11 @@
 #ifndef __LNET_LIB_TYPES_H__
 #define __LNET_LIB_TYPES_H__
 
-#include <linux/lnet/linux/lib-types.h>
+#include "linux/lib-types.h"
 
-#include <linux/libcfs/libcfs.h>
+#include "../libcfs/libcfs.h"
 #include <linux/list.h>
-#include <linux/lnet/types.h>
+#include "types.h"
 
 #define WIRE_ATTR       __attribute__((packed))
 
@@ -156,7 +156,6 @@ typedef struct {
  * "stub" reply using their current protocol */
 #define LNET_PROTO_MAGIC		    0x45726963 /* ! */
 
-
 #define LNET_PROTO_TCP_VERSION_MAJOR	1
 #define LNET_PROTO_TCP_VERSION_MINOR	0
 
@@ -225,7 +224,6 @@ typedef struct lnet_msg {
 	lnet_hdr_t	    msg_hdr;
 } lnet_msg_t;
 
-
 typedef struct lnet_libhandle {
 	struct list_head	    lh_hash_chain;
 	__u64		 lh_cookie;
@@ -280,6 +278,7 @@ typedef struct lnet_libmd {
 
 #define LNET_MD_FLAG_ZOMBIE	   (1 << 0)
 #define LNET_MD_FLAG_AUTO_UNLINK      (1 << 1)
+#define LNET_MD_FLAG_ABORTED	 (1 << 2)
 
 #ifdef LNET_USE_LIB_FREELIST
 typedef struct {
@@ -363,10 +362,10 @@ typedef struct lnet_lnd {
 	void (*lnd_notify)(struct lnet_ni *ni, lnet_nid_t peer, int alive);
 
 	/* query of peer aliveness */
-	void (*lnd_query)(struct lnet_ni *ni, lnet_nid_t peer, cfs_time_t *when);
+	void (*lnd_query)(struct lnet_ni *ni, lnet_nid_t peer, unsigned long *when);
 
 	/* accept a new connection */
-	int (*lnd_accept)(struct lnet_ni *ni, socket_t *sock);
+	int (*lnd_accept)(struct lnet_ni *ni, struct socket *sock);
 
 } lnd_t;
 
@@ -458,11 +457,11 @@ typedef struct lnet_peer {
 	unsigned int      lp_ping_notsent;      /* SEND event outstanding from ping */
 	int	       lp_alive_count;       /* # times router went dead<->alive */
 	long	      lp_txqnob;	    /* bytes queued for sending */
-	cfs_time_t	lp_timestamp;	 /* time of last aliveness news */
-	cfs_time_t	lp_ping_timestamp;    /* time of last ping attempt */
-	cfs_time_t	lp_ping_deadline;     /* != 0 if ping reply expected */
-	cfs_time_t	lp_last_alive;	/* when I was last alive */
-	cfs_time_t	lp_last_query;	/* when lp_ni was queried last time */
+	unsigned long	lp_timestamp;	 /* time of last aliveness news */
+	unsigned long	lp_ping_timestamp;    /* time of last ping attempt */
+	unsigned long	lp_ping_deadline;     /* != 0 if ping reply expected */
+	unsigned long	lp_last_alive;	/* when I was last alive */
+	unsigned long	lp_last_query;	/* when lp_ni was queried last time */
 	lnet_ni_t	*lp_ni;		/* interface peer is on */
 	lnet_nid_t	lp_nid;	       /* peer's NID */
 	int	       lp_refcount;	  /* # refs */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/linux/api-support.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/linux/api-support.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/linux/api-support.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/linux/api-support.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,5 +39,4 @@
 #error Do not #include this file directly. #include <lnet /api-support.h> instead
 #endif
 
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/linux/lib-lnet.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/linux/lib-lnet.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/linux/lib-lnet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/linux/lib-lnet.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,10 +42,10 @@
 # include <asm/page.h>
 # include <linux/string.h>
 # include <asm/io.h>
-# include <linux/libcfs/libcfs.h>
+#include "../../libcfs/libcfs.h"
 
 static inline __u64
-lnet_page2phys (struct page *p)
+lnet_page2phys(struct page *p)
 {
 	/* compiler optimizer will elide unused branches */
 
@@ -66,7 +66,6 @@ lnet_page2phys (struct page *p)
 	}
 }
 
-
 #define LNET_ROUTER
 
 #endif /* __LNET_LINUX_LIB_LNET_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnetctl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnetctl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnetctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnetctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -19,8 +19,8 @@
 #ifndef _PTLCTL_H_
 #define _PTLCTL_H_
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/types.h>
+#include "../libcfs/libcfs.h"
+#include "types.h"
 
 #define LNET_DEV_ID 0
 #define LNET_DEV_PATH "/dev/lnet"
@@ -43,10 +43,10 @@ int jt_ptl_which_nid(int argc, char **ar
 int jt_ptl_print_interfaces(int argc, char **argv);
 int jt_ptl_add_interface(int argc, char **argv);
 int jt_ptl_del_interface(int argc, char **argv);
-int jt_ptl_print_peers (int argc, char **argv);
-int jt_ptl_add_peer (int argc, char **argv);
-int jt_ptl_del_peer (int argc, char **argv);
-int jt_ptl_print_connections (int argc, char **argv);
+int jt_ptl_print_peers(int argc, char **argv);
+int jt_ptl_add_peer(int argc, char **argv);
+int jt_ptl_del_peer(int argc, char **argv);
+int jt_ptl_print_connections(int argc, char **argv);
 int jt_ptl_disconnect(int argc, char **argv);
 int jt_ptl_push_connection(int argc, char **argv);
 int jt_ptl_print_active_txs(int argc, char **argv);
@@ -56,11 +56,11 @@ int jt_ptl_add_uuid(int argc, char **arg
 int jt_ptl_add_uuid_old(int argc, char **argv); /* backwards compatibility  */
 int jt_ptl_close_uuid(int argc, char **argv);
 int jt_ptl_del_uuid(int argc, char **argv);
-int jt_ptl_add_route (int argc, char **argv);
-int jt_ptl_del_route (int argc, char **argv);
-int jt_ptl_notify_router (int argc, char **argv);
-int jt_ptl_print_routes (int argc, char **argv);
-int jt_ptl_fail_nid (int argc, char **argv);
+int jt_ptl_add_route(int argc, char **argv);
+int jt_ptl_del_route(int argc, char **argv);
+int jt_ptl_notify_router(int argc, char **argv);
+int jt_ptl_print_routes(int argc, char **argv);
+int jt_ptl_fail_nid(int argc, char **argv);
 int jt_ptl_lwt(int argc, char **argv);
 int jt_ptl_testprotocompat(int argc, char **argv);
 int jt_ptl_memhog(int argc, char **argv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnet.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnet.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnet.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,10 +40,10 @@
  *
  * User application interface file
  */
-#include <linux/lnet/linux/lnet.h>
+#include "linux/lnet.h"
 
-#include <linux/lnet/types.h>
-#include <linux/lnet/api.h>
+#include "types.h"
+#include "api.h"
 
 #define LNET_NIDSTR_COUNT  1024    /* # of nidstrings */
 #define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnetst.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnetst.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnetst.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnetst.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,9 +41,9 @@
 #ifndef __LNET_ST_H__
 #define __LNET_ST_H__
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-types.h>
+#include "../libcfs/libcfs.h"
+#include "lnet.h"
+#include "lib-types.h"
 
 #define LST_FEAT_NONE		(0)
 #define LST_FEAT_BULK_LEN	(1 << 0)	/* enable variable page size */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnet-sysctl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnet-sysctl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/lnet-sysctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/lnet-sysctl.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,6 @@
 
 #if defined(CONFIG_SYSCTL)
 
-
 #define CTL_KRANAL      201
 #define CTL_O2IBLND     205
 #define CTL_PTLLND      206
@@ -45,7 +44,6 @@
 #define CTL_SOCKLND     208
 #define CTL_GNILND      210
 
-
 #endif
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,11 +46,10 @@
  */
 #define LUSTRE_PORTALS_UNLINK_SEMANTICS
 
-
 #ifdef _USING_LUSTRE_PORTALS_
 
 /* NIDs are 64-bits on Lustre Portals */
-#define FMT_NID LPU64
+#define FMT_NID "%llu"
 #define FMT_PID "%d"
 
 /* When using Lustre Portals Lustre completion semantics are imlicit*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd_wire.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd_wire.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd_wire.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/ptllnd_wire.h	2014-09-28 17:29:07.000000000 -0400
@@ -54,7 +54,6 @@
  * enough to avoid RDMA for anything sent while control is not in liblustre */
 #define PTLLND_MAX_ULND_MSG_SIZE 512
 
-
 /************************************************************************
  * Portals LND Wire message format.
  * These are sent in sender's byte order (i.e. receiver flips).
@@ -103,7 +102,7 @@ typedef struct {
 } kptl_msg_t;
 
 /* kptl_msg_t::ptlm_credits is only a __u8 */
-#define PTLLND_MSG_MAX_CREDITS ((typeof(((kptl_msg_t*) 0)->ptlm_credits)) - 1)
+#define PTLLND_MSG_MAX_CREDITS ((typeof(((kptl_msg_t *)0)->ptlm_credits)) - 1)
 
 #define PTLLND_MSG_MAGIC		LNET_PROTO_PTL_MAGIC
 #define PTLLND_MSG_VERSION	      0x04
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/socklnd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/socklnd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/socklnd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/socklnd.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,8 +38,8 @@
 #ifndef __LNET_LNET_SOCKLND_H__
 #define __LNET_LNET_SOCKLND_H__
 
-#include <linux/lnet/types.h>
-#include <linux/lnet/lib-types.h>
+#include "types.h"
+#include "lib-types.h"
 
 #define SOCKLND_CONN_NONE     (-1)
 #define SOCKLND_CONN_ANY	0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/types.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/types.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/include/linux/lnet/types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/include/linux/lnet/types.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 /** \addtogroup lnet
  * @{ */
 
-#include <linux/libcfs/libcfs.h>
+#include "../libcfs/libcfs.h"
 
 /** \addtogroup lnet_addr
  * @{ */
@@ -110,7 +110,7 @@ static inline void LNetInvalidateHandle(
  *
  * \return 1 if handles are equal, 0 if otherwise.
  */
-static inline int LNetHandleIsEqual (lnet_handle_any_t h1, lnet_handle_any_t h2)
+static inline int LNetHandleIsEqual(lnet_handle_any_t h1, lnet_handle_any_t h2)
 {
 	return h1.cookie == h2.cookie;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,2 @@
 obj-$(CONFIG_LNET_XPRT_IB) += ko2iblnd.o
 ko2iblnd-y := o2iblnd.o o2iblnd_cb.o o2iblnd_modparams.o
-
-
-ccflags-y := -I$(src)/../../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c	2014-09-28 17:29:07.000000000 -0400
@@ -959,7 +959,7 @@ kiblnd_close_stale_conns_locked (kib_pee
 			continue;
 
 		CDEBUG(D_NET, "Closing stale conn -> %s version: %x, "
-			      "incarnation:"LPX64"(%x, "LPX64")\n",
+			      "incarnation:%#llx(%x, %#llx)\n",
 		       libcfs_nid2str(peer->ibp_nid),
 		       conn->ibc_version, conn->ibc_incarnation,
 		       version, incarnation);
@@ -1074,10 +1074,10 @@ kiblnd_ctl(lnet_ni_t *ni, unsigned int c
 }
 
 void
-kiblnd_query (lnet_ni_t *ni, lnet_nid_t nid, cfs_time_t *when)
+kiblnd_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 {
-	cfs_time_t	last_alive = 0;
-	cfs_time_t	now = cfs_time_current();
+	unsigned long	last_alive = 0;
+	unsigned long	now = cfs_time_current();
 	rwlock_t	*glock = &kiblnd_data.kib_global_lock;
 	kib_peer_t	*peer;
 	unsigned long	flags;
@@ -1202,7 +1202,7 @@ kiblnd_map_rx_descs(kib_conn_t *conn)
 						   rx->rx_msgaddr));
 		KIBLND_UNMAP_ADDR_SET(rx, rx_msgunmap, rx->rx_msgaddr);
 
-		CDEBUG(D_NET,"rx %d: %p "LPX64"("LPX64")\n",
+		CDEBUG(D_NET,"rx %d: %p %#llx(%#llx)\n",
 		       i, rx->rx_msg, rx->rx_msgaddr,
 		       lnet_page2phys(pg) + pg_off);
 
@@ -1509,7 +1509,7 @@ kiblnd_init_fmr_poolset(kib_fmr_poolset_
 }
 
 static int
-kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, cfs_time_t now)
+kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, unsigned long now)
 {
 	if (fpo->fpo_map_count != 0) /* still in use */
 		return 0;
@@ -1524,7 +1524,7 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, in
 	LIST_HEAD     (zombies);
 	kib_fmr_pool_t    *fpo = fmr->fmr_pool;
 	kib_fmr_poolset_t *fps = fpo->fpo_owner;
-	cfs_time_t	 now = cfs_time_current();
+	unsigned long	 now = cfs_time_current();
 	kib_fmr_pool_t    *tmp;
 	int		rc;
 
@@ -1606,7 +1606,7 @@ kiblnd_fmr_pool_map(kib_fmr_poolset_t *f
 
 	}
 
-	if (cfs_time_before(cfs_time_current(), fps->fps_next_retry)) {
+	if (time_before(cfs_time_current(), fps->fps_next_retry)) {
 		/* someone failed recently */
 		spin_unlock(&fps->fps_lock);
 		return -EAGAIN;
@@ -1731,7 +1731,7 @@ kiblnd_init_poolset(kib_poolset_t *ps, i
 }
 
 static int
-kiblnd_pool_is_idle(kib_pool_t *pool, cfs_time_t now)
+kiblnd_pool_is_idle(kib_pool_t *pool, unsigned long now)
 {
 	if (pool->po_allocated != 0) /* still in use */
 		return 0;
@@ -1746,7 +1746,7 @@ kiblnd_pool_free_node(kib_pool_t *pool,
 	LIST_HEAD  (zombies);
 	kib_poolset_t  *ps = pool->po_owner;
 	kib_pool_t     *tmp;
-	cfs_time_t      now = cfs_time_current();
+	unsigned long      now = cfs_time_current();
 
 	spin_lock(&ps->ps_lock);
 
@@ -1808,7 +1808,7 @@ kiblnd_pool_alloc_node(kib_poolset_t *ps
 		goto again;
 	}
 
-	if (cfs_time_before(cfs_time_current(), ps->ps_next_retry)) {
+	if (time_before(cfs_time_current(), ps->ps_next_retry)) {
 		/* someone failed recently */
 		spin_unlock(&ps->ps_lock);
 		return NULL;
@@ -2336,7 +2336,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev
 			return 0;
 	}
 
-	CERROR("Invalid mr size: "LPX64"\n", hdev->ibh_mr_size);
+	CERROR("Invalid mr size: %#llx\n", hdev->ibh_mr_size);
 	return -EINVAL;
 }
 
@@ -2418,8 +2418,8 @@ kiblnd_hdev_setup_mrs(kib_hca_dev_t *hde
 
 	if (hdev->ibh_mr_shift < 32 || hdev->ibh_nmrs > 1024) {
 		/* it's 4T..., assume we will re-code at that time */
-		CERROR("Can't support memory size: x"LPX64
-		       " with MR size: x"LPX64"\n", mm_size, mr_size);
+		CERROR("Can't support memory size: x%#llx with MR size: x%#llx\n",
+		       mm_size, mr_size);
 		return -EINVAL;
 	}
 
@@ -2430,8 +2430,6 @@ kiblnd_hdev_setup_mrs(kib_hca_dev_t *hde
 		return -ENOMEM;
 	}
 
-	memset(hdev->ibh_mrs, 0, sizeof(*hdev->ibh_mrs) * hdev->ibh_nmrs);
-
 	for (i = 0; i < hdev->ibh_nmrs; i++) {
 		struct ib_phys_buf ipb;
 		__u64	      iova;
@@ -2442,8 +2440,7 @@ kiblnd_hdev_setup_mrs(kib_hca_dev_t *hde
 
 		mr = ib_reg_phys_mr(hdev->ibh_pd, &ipb, 1, acflags, &iova);
 		if (IS_ERR(mr)) {
-			CERROR("Failed ib_reg_phys_mr addr "LPX64
-			       " size "LPX64" : %ld\n",
+			CERROR("Failed ib_reg_phys_mr addr %#llx size %#llx : %ld\n",
 			       ipb.addr, ipb.size, PTR_ERR(mr));
 			kiblnd_hdev_cleanup_mrs(hdev);
 			return PTR_ERR(mr);
@@ -2456,8 +2453,7 @@ kiblnd_hdev_setup_mrs(kib_hca_dev_t *hde
 
 out:
 	if (hdev->ibh_mr_size != ~0ULL || hdev->ibh_nmrs != 1)
-		LCONSOLE_INFO("Register global MR array, MR size: "
-			      LPX64", array size: %d\n",
+		LCONSOLE_INFO("Register global MR array, MR size: %#llx, array size: %d\n",
 			      hdev->ibh_mr_size, hdev->ibh_nmrs);
 	return 0;
 }
@@ -2704,7 +2700,6 @@ kiblnd_create_dev(char *ifname)
 	if (dev == NULL)
 		return NULL;
 
-	memset(dev, 0, sizeof(*dev));
 	netdev = dev_get_by_name(&init_net, ifname);
 	if (netdev == NULL) {
 		dev->ibd_can_failover = 0;
@@ -3088,8 +3083,6 @@ kiblnd_startup (lnet_ni_t *ni)
 	if (net == NULL)
 		goto failed;
 
-	memset(net, 0, sizeof(*net));
-
 	do_gettimeofday(&tv);
 	net->ibn_incarnation = (((__u64)tv.tv_sec) * 1000000) + tv.tv_usec;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c	2014-09-28 17:29:07.000000000 -0400
@@ -247,7 +247,7 @@ kiblnd_handle_completion(kib_conn_t *con
 	if (tx == NULL) {
 		spin_unlock(&conn->ibc_lock);
 
-		CWARN("Unmatched completion type %x cookie "LPX64" from %s\n",
+		CWARN("Unmatched completion type %x cookie %#llx from %s\n",
 		      txtype, cookie, libcfs_nid2str(conn->ibc_peer->ibp_nid));
 		kiblnd_close_conn(conn, -EPROTO);
 		return;
@@ -1005,8 +1005,7 @@ kiblnd_tx_complete (kib_tx_t *tx, int st
 
 	if (failed) {
 		if (conn->ibc_state == IBLND_CONN_ESTABLISHED)
-			CNETERR("Tx -> %s cookie "LPX64
-				" sending %d waiting %d: failed %d\n",
+			CNETERR("Tx -> %s cookie %#llx sending %d waiting %d: failed %d\n",
 				libcfs_nid2str(conn->ibc_peer->ibp_nid),
 				tx->tx_cookie, tx->tx_sending, tx->tx_waiting,
 				status);
@@ -1830,7 +1829,7 @@ static void
 kiblnd_peer_notify (kib_peer_t *peer)
 {
 	int	   error = 0;
-	cfs_time_t    last_alive = 0;
+	unsigned long    last_alive = 0;
 	unsigned long flags;
 
 	read_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
@@ -3465,8 +3464,8 @@ kiblnd_failover_thread(void *arg)
 
 		list_for_each_entry(dev, &kiblnd_data.kib_failed_devs,
 				    ibd_fail_list) {
-			if (cfs_time_before(cfs_time_current(),
-					    dev->ibd_next_failover))
+			if (time_before(cfs_time_current(),
+					dev->ibd_next_failover))
 				continue;
 			do_failover = 1;
 			break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,10 +62,10 @@
 
 #define DEBUG_SUBSYSTEM S_LND
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/lnet-sysctl.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../../../include/linux/lnet/lnet.h"
+#include "../../../include/linux/lnet/lib-lnet.h"
+#include "../../../include/linux/lnet/lnet-sysctl.h"
 
 #include <rdma/rdma_cm.h>
 #include <rdma/ib_cm.h>
@@ -195,7 +195,7 @@ typedef struct
 	char		 ibd_ifname[KIB_IFNAME_SIZE];
 	int		  ibd_nnets;	 /* # nets extant */
 
-	cfs_time_t	   ibd_next_failover;
+	unsigned long	   ibd_next_failover;
 	int		  ibd_failed_failover; /* # failover failures */
 	unsigned int	 ibd_failover;      /* failover in progress */
 	unsigned int	 ibd_can_failover;  /* IPoIB interface is a bonding master */
@@ -261,7 +261,7 @@ typedef struct kib_poolset
 	char		    ps_name[IBLND_POOL_NAME_LEN]; /* pool set name */
 	struct list_head	      ps_pool_list;	   /* list of pools */
 	struct list_head	      ps_failed_pool_list;    /* failed pool list */
-	cfs_time_t	      ps_next_retry;	  /* time stamp for retry if failed to allocate */
+	unsigned long	      ps_next_retry;	  /* time stamp for retry if failed to allocate */
 	int		     ps_increasing;	  /* is allocating new pool */
 	int		     ps_pool_size;	   /* new pool size */
 	int			ps_cpt;			/* CPT id */
@@ -277,7 +277,7 @@ typedef struct kib_pool
 	struct list_head	      po_list;		/* chain on pool list */
 	struct list_head	      po_free_list;	   /* pre-allocated node */
 	kib_poolset_t	  *po_owner;	       /* pool_set of this pool */
-	cfs_time_t	      po_deadline;	    /* deadline of this pool */
+	unsigned long	      po_deadline;	    /* deadline of this pool */
 	int		     po_allocated;	   /* # of elements in use */
 	int		     po_failed;	      /* pool is created on failed HCA */
 	int		     po_size;		/* # of pre-allocated elements */
@@ -317,7 +317,7 @@ typedef struct
 	/* is allocating new pool */
 	int			fps_increasing;
 	/* time stamp for retry if failed to allocate */
-	cfs_time_t		fps_next_retry;
+	unsigned long		fps_next_retry;
 } kib_fmr_poolset_t;
 
 typedef struct
@@ -326,7 +326,7 @@ typedef struct
 	struct kib_hca_dev     *fpo_hdev;	       /* device for this pool */
 	kib_fmr_poolset_t      *fpo_owner;	      /* owner of this pool */
 	struct ib_fmr_pool     *fpo_fmr_pool;	   /* IB FMR pool */
-	cfs_time_t	      fpo_deadline;	   /* deadline of this pool */
+	unsigned long	      fpo_deadline;	   /* deadline of this pool */
 	int		     fpo_failed;	     /* fmr pool is failed */
 	int		     fpo_map_count;	  /* # of mapped FMR */
 } kib_fmr_pool_t;
@@ -642,7 +642,7 @@ typedef struct kib_peer
 	int		  ibp_connecting;     /* current active connection attempts */
 	int		  ibp_accepting;      /* current passive connection attempts */
 	int		  ibp_error;	  /* errno on closing this peer */
-	cfs_time_t	   ibp_last_alive;     /* when (in jiffies) I was last alive */
+	unsigned long	   ibp_last_alive;     /* when (in jiffies) I was last alive */
 } kib_peer_t;
 
 extern kib_data_t      kiblnd_data;
@@ -990,7 +990,7 @@ void kiblnd_pmr_pool_unmap(kib_phys_mr_t
 int  kiblnd_startup (lnet_ni_t *ni);
 void kiblnd_shutdown (lnet_ni_t *ni);
 int  kiblnd_ctl (lnet_ni_t *ni, unsigned int cmd, void *arg);
-void kiblnd_query (struct lnet_ni *ni, lnet_nid_t nid, cfs_time_t *when);
+void kiblnd_query (struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
 
 int  kiblnd_tunables_init(void);
 void kiblnd_tunables_fini(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,7 +1,3 @@
 obj-$(CONFIG_LNET) += ksocklnd.o
 
 ksocklnd-y := socklnd.o socklnd_cb.o socklnd_proto.o socklnd_modparams.o socklnd_lib-linux.o
-
-
-
-ccflags-y := -I$(src)/../../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,10 +43,10 @@
 
 #include "socklnd.h"
 
-lnd_t		   the_ksocklnd;
-ksock_nal_data_t	ksocknal_data;
+static lnd_t the_ksocklnd;
+ksock_nal_data_t ksocknal_data;
 
-ksock_interface_t *
+static ksock_interface_t *
 ksocknal_ip2iface(lnet_ni_t *ni, __u32 ip)
 {
 	ksock_net_t       *net = ni->ni_data;
@@ -64,7 +64,7 @@ ksocknal_ip2iface(lnet_ni_t *ni, __u32 i
 	return NULL;
 }
 
-ksock_route_t *
+static ksock_route_t *
 ksocknal_create_route (__u32 ipaddr, int port)
 {
 	ksock_route_t *route;
@@ -99,7 +99,7 @@ ksocknal_destroy_route (ksock_route_t *r
 	LIBCFS_FREE (route, sizeof (*route));
 }
 
-int
+static int
 ksocknal_create_peer (ksock_peer_t **peerp, lnet_ni_t *ni, lnet_process_id_t id)
 {
 	ksock_net_t   *net = ni->ni_data;
@@ -113,8 +113,6 @@ ksocknal_create_peer (ksock_peer_t **pee
 	if (peer == NULL)
 		return -ENOMEM;
 
-	memset (peer, 0, sizeof (*peer));       /* NULL pointers/clear flags etc */
-
 	peer->ksnp_ni = ni;
 	peer->ksnp_id = id;
 	atomic_set (&peer->ksnp_refcount, 1);   /* 1 ref for caller */
@@ -216,7 +214,7 @@ ksocknal_find_peer (lnet_ni_t *ni, lnet_
 	return peer;
 }
 
-void
+static void
 ksocknal_unlink_peer_locked (ksock_peer_t *peer)
 {
 	int		i;
@@ -246,7 +244,7 @@ ksocknal_unlink_peer_locked (ksock_peer_
 	ksocknal_peer_decref(peer);
 }
 
-int
+static int
 ksocknal_get_peer_info (lnet_ni_t *ni, int index,
 			lnet_process_id_t *id, __u32 *myip, __u32 *peer_ip,
 			int *port, int *conn_count, int *share_count)
@@ -321,7 +319,7 @@ ksocknal_get_peer_info (lnet_ni_t *ni, i
 	return rc;
 }
 
-void
+static void
 ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn)
 {
 	ksock_peer_t      *peer = route->ksnr_peer;
@@ -366,7 +364,7 @@ ksocknal_associate_route_conn_locked(kso
 	route->ksnr_retry_interval = 0;
 }
 
-void
+static void
 ksocknal_add_route_locked (ksock_peer_t *peer, ksock_route_t *route)
 {
 	struct list_head	*tmp;
@@ -407,7 +405,7 @@ ksocknal_add_route_locked (ksock_peer_t
 	}
 }
 
-void
+static void
 ksocknal_del_route_locked (ksock_route_t *route)
 {
 	ksock_peer_t      *peer = route->ksnr_peer;
@@ -509,7 +507,7 @@ ksocknal_add_peer (lnet_ni_t *ni, lnet_p
 	return 0;
 }
 
-void
+static void
 ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
 {
 	ksock_conn_t     *conn;
@@ -564,7 +562,7 @@ ksocknal_del_peer_locked (ksock_peer_t *
 	/* NB peer unlinks itself when last conn/route is removed */
 }
 
-int
+static int
 ksocknal_del_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
 {
 	LIST_HEAD     (zombies);
@@ -623,7 +621,7 @@ ksocknal_del_peer (lnet_ni_t *ni, lnet_p
 	return rc;
 }
 
-ksock_conn_t *
+static ksock_conn_t *
 ksocknal_get_conn_by_idx (lnet_ni_t *ni, int index)
 {
 	ksock_peer_t      *peer;
@@ -660,7 +658,7 @@ ksocknal_get_conn_by_idx (lnet_ni_t *ni,
 	return NULL;
 }
 
-ksock_sched_t *
+static ksock_sched_t *
 ksocknal_choose_scheduler_locked(unsigned int cpt)
 {
 	struct ksock_sched_info	*info = ksocknal_data.ksnd_sched_info[cpt];
@@ -683,7 +681,7 @@ ksocknal_choose_scheduler_locked(unsigne
 	return sched;
 }
 
-int
+static int
 ksocknal_local_ipvec (lnet_ni_t *ni, __u32 *ipaddrs)
 {
 	ksock_net_t       *net = ni->ni_data;
@@ -711,7 +709,7 @@ ksocknal_local_ipvec (lnet_ni_t *ni, __u
 	return nip;
 }
 
-int
+static int
 ksocknal_match_peerip (ksock_interface_t *iface, __u32 *ips, int nips)
 {
 	int   best_netmatch = 0;
@@ -743,7 +741,7 @@ ksocknal_match_peerip (ksock_interface_t
 	return best;
 }
 
-int
+static int
 ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
 {
 	rwlock_t		*global_lock = &ksocknal_data.ksnd_global_lock;
@@ -845,7 +843,7 @@ ksocknal_select_ips(ksock_peer_t *peer,
 	return n_ips;
 }
 
-void
+static void
 ksocknal_create_routes(ksock_peer_t *peer, int port,
 		       __u32 *peer_ipaddrs, int npeer_ipaddrs)
 {
@@ -964,7 +962,7 @@ ksocknal_create_routes(ksock_peer_t *pee
 }
 
 int
-ksocknal_accept (lnet_ni_t *ni, socket_t *sock)
+ksocknal_accept (lnet_ni_t *ni, struct socket *sock)
 {
 	ksock_connreq_t    *cr;
 	int		 rc;
@@ -995,7 +993,7 @@ ksocknal_accept (lnet_ni_t *ni, socket_t
 	return 0;
 }
 
-int
+static int
 ksocknal_connecting (ksock_peer_t *peer, __u32 ipaddr)
 {
 	ksock_route_t   *route;
@@ -1010,7 +1008,7 @@ ksocknal_connecting (ksock_peer_t *peer,
 
 int
 ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
-		      socket_t *sock, int type)
+		      struct socket *sock, int type)
 {
 	rwlock_t		*global_lock = &ksocknal_data.ksnd_global_lock;
 	LIST_HEAD     (zombies);
@@ -1040,8 +1038,6 @@ ksocknal_create_conn (lnet_ni_t *ni, kso
 		goto failed_0;
 	}
 
-	memset (conn, 0, sizeof (*conn));
-
 	conn->ksnc_peer = NULL;
 	conn->ksnc_route = NULL;
 	conn->ksnc_sock = sock;
@@ -1262,7 +1258,7 @@ ksocknal_create_conn (lnet_ni_t *ni, kso
 
 	conn->ksnc_tx_last_post = cfs_time_current();
 	/* Set the deadline for the outgoing HELLO to drain */
-	conn->ksnc_tx_bufnob = cfs_sock_wmem_queued(sock);
+	conn->ksnc_tx_bufnob = sock->sk->sk_wmem_queued;
 	conn->ksnc_tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout);
 	mb();   /* order with adding to peer's conn list */
 
@@ -1293,7 +1289,7 @@ ksocknal_create_conn (lnet_ni_t *ni, kso
 	 */
 
 	CDEBUG(D_NET, "New conn %s p %d.x %pI4h -> %pI4h/%d"
-	       " incarnation:"LPD64" sched[%d:%d]\n",
+	       " incarnation:%lld sched[%d:%d]\n",
 	       libcfs_id2str(peerid), conn->ksnc_proto->pro_version,
 	       &conn->ksnc_myipaddr, &conn->ksnc_ipaddr,
 	       conn->ksnc_port, incarnation, cpt,
@@ -1487,7 +1483,7 @@ void
 ksocknal_peer_failed (ksock_peer_t *peer)
 {
 	int	notify = 0;
-	cfs_time_t last_alive = 0;
+	unsigned long last_alive = 0;
 
 	/* There has been a connection failure or comms error; but I'll only
 	 * tell LNET I think the peer is dead if it's to another kernel and
@@ -1624,7 +1620,7 @@ ksocknal_queue_zombie_conn (ksock_conn_t
 void
 ksocknal_destroy_conn (ksock_conn_t *conn)
 {
-	cfs_time_t      last_rcv;
+	unsigned long      last_rcv;
 
 	/* Final coup-de-grace of the reaper */
 	CDEBUG (D_NET, "connection %p\n", conn);
@@ -1793,11 +1789,11 @@ ksocknal_notify (lnet_ni_t *ni, lnet_nid
 }
 
 void
-ksocknal_query (lnet_ni_t *ni, lnet_nid_t nid, cfs_time_t *when)
+ksocknal_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 {
 	int		connect = 1;
-	cfs_time_t	 last_alive = 0;
-	cfs_time_t	 now = cfs_time_current();
+	unsigned long	 last_alive = 0;
+	unsigned long	 now = cfs_time_current();
 	ksock_peer_t      *peer = NULL;
 	rwlock_t		*glock = &ksocknal_data.ksnd_global_lock;
 	lnet_process_id_t  id = {.nid = nid, .pid = LUSTRE_SRV_LNET_PID};
@@ -1812,7 +1808,7 @@ ksocknal_query (lnet_ni_t *ni, lnet_nid_
 
 		list_for_each (tmp, &peer->ksnp_conns) {
 			conn = list_entry(tmp, ksock_conn_t, ksnc_list);
-			bufnob = cfs_sock_wmem_queued(conn->ksnc_sock);
+			bufnob = conn->ksnc_sock->sk->sk_wmem_queued;
 
 			if (bufnob < conn->ksnc_tx_bufnob) {
 				/* something got ACKed */
@@ -1853,7 +1849,7 @@ ksocknal_query (lnet_ni_t *ni, lnet_nid_
 	return;
 }
 
-void
+static void
 ksocknal_push_peer (ksock_peer_t *peer)
 {
 	int	       index;
@@ -1886,7 +1882,7 @@ ksocknal_push_peer (ksock_peer_t *peer)
 	}
 }
 
-int
+static int
 ksocknal_push (lnet_ni_t *ni, lnet_process_id_t id)
 {
 	ksock_peer_t      *peer;
@@ -1935,7 +1931,7 @@ ksocknal_push (lnet_ni_t *ni, lnet_proce
 	return rc;
 }
 
-int
+static int
 ksocknal_add_interface(lnet_ni_t *ni, __u32 ipaddress, __u32 netmask)
 {
 	ksock_net_t       *net = ni->ni_data;
@@ -1997,7 +1993,7 @@ ksocknal_add_interface(lnet_ni_t *ni, __
 	return rc;
 }
 
-void
+static void
 ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr)
 {
 	struct list_head	 *tmp;
@@ -2038,7 +2034,7 @@ ksocknal_peer_del_interface_locked(ksock
 	}
 }
 
-int
+static int
 ksocknal_del_interface(lnet_ni_t *ni, __u32 ipaddress)
 {
 	ksock_net_t       *net = ni->ni_data;
@@ -2213,7 +2209,7 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int
 	/* not reached */
 }
 
-void
+static void
 ksocknal_free_buffers (void)
 {
 	LASSERT (atomic_read(&ksocknal_data.ksnd_nactive_txs) == 0);
@@ -2256,7 +2252,7 @@ ksocknal_free_buffers (void)
 	}
 }
 
-void
+static void
 ksocknal_base_shutdown(void)
 {
 	struct ksock_sched_info *info;
@@ -2349,7 +2345,7 @@ ksocknal_base_shutdown(void)
 	module_put(THIS_MODULE);
 }
 
-__u64
+static __u64
 ksocknal_new_incarnation (void)
 {
 	struct timeval tv;
@@ -2364,7 +2360,7 @@ ksocknal_new_incarnation (void)
 	return (((__u64)tv.tv_sec) * 1000000) + tv.tv_usec;
 }
 
-int
+static int
 ksocknal_base_startup(void)
 {
 	struct ksock_sched_info	*info;
@@ -2449,7 +2445,7 @@ ksocknal_base_startup(void)
 
 	ksocknal_data.ksnd_connd_starting	 = 0;
 	ksocknal_data.ksnd_connd_failed_stamp     = 0;
-	ksocknal_data.ksnd_connd_starting_stamp   = cfs_time_current_sec();
+	ksocknal_data.ksnd_connd_starting_stamp   = get_seconds();
 	/* must have at least 2 connds to remain responsive to accepts while
 	 * connecting */
 	if (*ksocknal_tunables.ksnd_nconnds < SOCKNAL_CONND_RESV + 1)
@@ -2496,7 +2492,7 @@ ksocknal_base_startup(void)
 	return -ENETDOWN;
 }
 
-void
+static void
 ksocknal_debug_peerhash (lnet_ni_t *ni)
 {
 	ksock_peer_t	*peer = NULL;
@@ -2521,7 +2517,7 @@ ksocknal_debug_peerhash (lnet_ni_t *ni)
 		ksock_conn_t  *conn;
 
 		CWARN ("Active peer on shutdown: %s, ref %d, scnt %d, "
-		       "closing %d, accepting %d, err %d, zcookie "LPU64", "
+		       "closing %d, accepting %d, err %d, zcookie %llu, "
 		       "txq %d, zc_req %d\n", libcfs_id2str(peer->ksnp_id),
 		       atomic_read(&peer->ksnp_refcount),
 		       peer->ksnp_sharecount, peer->ksnp_closing,
@@ -2603,7 +2599,7 @@ ksocknal_shutdown (lnet_ni_t *ni)
 		ksocknal_base_shutdown();
 }
 
-int
+static int
 ksocknal_enumerate_interfaces(ksock_net_t *net)
 {
 	char      **names;
@@ -2660,7 +2656,7 @@ ksocknal_enumerate_interfaces(ksock_net_
 	return j;
 }
 
-int
+static int
 ksocknal_search_new_ipif(ksock_net_t *net)
 {
 	int	new_ipif = 0;
@@ -2702,7 +2698,7 @@ ksocknal_search_new_ipif(ksock_net_t *ne
 	return new_ipif;
 }
 
-int
+static int
 ksocknal_start_schedulers(struct ksock_sched_info *info)
 {
 	int	nthrs;
@@ -2748,7 +2744,7 @@ ksocknal_start_schedulers(struct ksock_s
 	return rc;
 }
 
-int
+static int
 ksocknal_net_start_threads(ksock_net_t *net, __u32 *cpts, int ncpts)
 {
 	int	newif = ksocknal_search_new_ipif(net);
@@ -2860,13 +2856,13 @@ ksocknal_startup (lnet_ni_t *ni)
 }
 
 
-void __exit
+static void __exit
 ksocknal_module_fini (void)
 {
 	lnet_unregister_lnd(&the_ksocklnd);
 }
 
-int __init
+static int __init
 ksocknal_module_init (void)
 {
 	int    rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c	2014-09-28 17:29:07.000000000 -0400
@@ -212,7 +212,7 @@ ksocknal_transmit (ksock_conn_t *conn, k
 			rc = ksocknal_send_kiov (conn, tx);
 		}
 
-		bufnob = cfs_sock_wmem_queued(conn->ksnc_sock);
+		bufnob = conn->ksnc_sock->sk->sk_wmem_queued;
 		if (rc > 0)		     /* sent something? */
 			conn->ksnc_tx_bufnob += rc; /* account it */
 
@@ -630,7 +630,7 @@ ksocknal_find_conn_locked(ksock_peer_t *
 	list_for_each (tmp, &peer->ksnp_conns) {
 		ksock_conn_t *c  = list_entry(tmp, ksock_conn_t, ksnc_list);
 		int	   nob = atomic_read(&c->ksnc_tx_nob) +
-				    cfs_sock_wmem_queued(c->ksnc_sock);
+				    c->ksnc_sock->sk->sk_wmem_queued;
 		int	   rc;
 
 		LASSERT (!c->ksnc_closing);
@@ -726,7 +726,7 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx
 	 * FIXME: SOCK_WMEM_QUEUED and SOCK_ERROR could block in __DARWIN8__
 	 * but they're used inside spinlocks a lot.
 	 */
-	bufnob = cfs_sock_wmem_queued(conn->ksnc_sock);
+	bufnob = conn->ksnc_sock->sk->sk_wmem_queued;
 	spin_lock_bh(&sched->kss_lock);
 
 	if (list_empty(&conn->ksnc_tx_queue) && bufnob == 0) {
@@ -780,7 +780,7 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx
 ksock_route_t *
 ksocknal_find_connectable_route_locked (ksock_peer_t *peer)
 {
-	cfs_time_t     now = cfs_time_current();
+	unsigned long     now = cfs_time_current();
 	struct list_head    *tmp;
 	ksock_route_t *route;
 
@@ -1199,7 +1199,7 @@ ksocknal_process_receive (ksock_conn_t *
 					       conn->ksnc_msg.ksm_zc_cookies[1]);
 
 			if (rc != 0) {
-				CERROR("%s: Unknown ZC-ACK cookie: "LPU64", "LPU64"\n",
+				CERROR("%s: Unknown ZC-ACK cookie: %llu, %llu\n",
 				       libcfs_id2str(conn->ksnc_peer->ksnp_id),
 				       cookie, conn->ksnc_msg.ksm_zc_cookies[1]);
 				ksocknal_new_packet(conn, 0);
@@ -1699,7 +1699,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksoc
 	 *	EALREADY   lost connection race
 	 *	EPROTO     protocol version mismatch
 	 */
-	socket_t	*sock = conn->ksnc_sock;
+	struct socket	*sock = conn->ksnc_sock;
 	int		  active = (conn->ksnc_proto != NULL);
 	int		  timeout;
 	int		  proto_match;
@@ -1844,8 +1844,8 @@ ksocknal_connect (ksock_route_t *route)
 	ksock_peer_t     *peer = route->ksnr_peer;
 	int	       type;
 	int	       wanted;
-	socket_t     *sock;
-	cfs_time_t	deadline;
+	struct socket     *sock;
+	unsigned long	deadline;
 	int	       retry_later = 0;
 	int	       rc = 0;
 
@@ -2059,7 +2059,7 @@ ksocknal_connd_check_start(long sec, lon
 	/* we tried ... */
 	LASSERT(ksocknal_data.ksnd_connd_starting > 0);
 	ksocknal_data.ksnd_connd_starting--;
-	ksocknal_data.ksnd_connd_failed_stamp = cfs_time_current_sec();
+	ksocknal_data.ksnd_connd_failed_stamp = get_seconds();
 
 	return 1;
 }
@@ -2111,7 +2111,7 @@ static ksock_route_t *
 ksocknal_connd_get_route_locked(signed long *timeout_p)
 {
 	ksock_route_t *route;
-	cfs_time_t     now;
+	unsigned long     now;
 
 	now = cfs_time_current();
 
@@ -2152,7 +2152,7 @@ ksocknal_connd (void *arg)
 
 	while (!ksocknal_data.ksnd_shuttingdown) {
 		ksock_route_t *route = NULL;
-		long sec = cfs_time_current_sec();
+		long sec = get_seconds();
 		long timeout = MAX_SCHEDULE_TIMEOUT;
 		int  dropped_lock = 0;
 
@@ -2260,7 +2260,7 @@ ksocknal_find_timed_out_conn (ksock_peer
 
 		/* SOCK_ERROR will reset error code of socket in
 		 * some platform (like Darwin8.x) */
-		error = cfs_sock_error(conn->ksnc_sock);
+		error = conn->ksnc_sock->sk->sk_err;
 		if (error != 0) {
 			ksocknal_conn_addref(conn);
 
@@ -2311,7 +2311,7 @@ ksocknal_find_timed_out_conn (ksock_peer
 		}
 
 		if ((!list_empty(&conn->ksnc_tx_queue) ||
-		     cfs_sock_wmem_queued(conn->ksnc_sock) != 0) &&
+		     conn->ksnc_sock->sk->sk_wmem_queued != 0) &&
 		    cfs_time_aftereq(cfs_time_current(),
 				     conn->ksnc_tx_deadline)) {
 			/* Timed out messages queued for sending or
@@ -2368,13 +2368,12 @@ ksocknal_send_keepalive_locked(ksock_pee
 		return 0;
 
 	if (*ksocknal_tunables.ksnd_keepalive <= 0 ||
-	    cfs_time_before(cfs_time_current(),
-			    cfs_time_add(peer->ksnp_last_alive,
-					 cfs_time_seconds(*ksocknal_tunables.ksnd_keepalive))))
+	    time_before(cfs_time_current(),
+			cfs_time_add(peer->ksnp_last_alive,
+				     cfs_time_seconds(*ksocknal_tunables.ksnd_keepalive))))
 		return 0;
 
-	if (cfs_time_before(cfs_time_current(),
-			    peer->ksnp_send_keepalive))
+	if (time_before(cfs_time_current(), peer->ksnp_send_keepalive))
 		return 0;
 
 	/* retry 10 secs later, so we wouldn't put pressure
@@ -2431,7 +2430,7 @@ ksocknal_check_peer_timeouts (int idx)
 	read_lock(&ksocknal_data.ksnd_global_lock);
 
 	list_for_each_entry(peer, peers, ksnp_list) {
-		cfs_time_t  deadline = 0;
+		unsigned long  deadline = 0;
 		int	 resid = 0;
 		int	 n     = 0;
 
@@ -2508,7 +2507,7 @@ ksocknal_check_peer_timeouts (int idx)
 		       "resid: %d, wmem: %d\n",
 		       n, libcfs_nid2str(peer->ksnp_id.nid), tx,
 		       cfs_duration_sec(cfs_time_current() - deadline),
-		       resid, cfs_sock_wmem_queued(conn->ksnc_sock));
+		       resid, conn->ksnc_sock->sk->sk_wmem_queued);
 
 		ksocknal_close_conn_and_siblings (conn, -ETIMEDOUT);
 		ksocknal_conn_decref(conn);
@@ -2526,10 +2525,10 @@ ksocknal_reaper (void *arg)
 	ksock_sched_t     *sched;
 	struct list_head	 enomem_conns;
 	int		nenomem_conns;
-	cfs_duration_t     timeout;
+	long     timeout;
 	int		i;
 	int		peer_index = 0;
-	cfs_time_t	 deadline = cfs_time_current();
+	unsigned long	 deadline = cfs_time_current();
 
 	cfs_block_allsigs ();
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,11 +30,11 @@
 
 #include "socklnd_lib-linux.h"
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/socklnd.h>
-#include <linux/lnet/lnet-sysctl.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../../../include/linux/lnet/lnet.h"
+#include "../../../include/linux/lnet/lib-lnet.h"
+#include "../../../include/linux/lnet/socklnd.h"
+#include "../../../include/linux/lnet/lnet-sysctl.h"
 
 #define SOCKNAL_PEER_HASH_SIZE  101	     /* # peer lists */
 #define SOCKNAL_RESCHED	 100	     /* # scheduler loops before reschedule */
@@ -164,7 +164,7 @@ typedef struct
 	struct list_head	ksnd_zombie_conns;   /* conns to free: reaper_lock */
 	struct list_head	ksnd_enomem_conns;   /* conns to retry: reaper_lock*/
 	wait_queue_head_t       ksnd_reaper_waitq;   /* reaper sleeps here */
-	cfs_time_t	ksnd_reaper_waketime;/* when reaper will wake */
+	unsigned long	ksnd_reaper_waketime;/* when reaper will wake */
 	spinlock_t	  ksnd_reaper_lock;	/* serialise */
 
 	int	       ksnd_enomem_tx;      /* test ENOMEM sender */
@@ -225,7 +225,7 @@ typedef struct				  /* transmit packet *
 	lnet_kiov_t   *tx_kiov;	/* packet page frags */
 	struct ksock_conn  *tx_conn;	/* owning conn */
 	lnet_msg_t    *tx_lnetmsg;     /* lnet message for lnet_finalize() */
-	cfs_time_t     tx_deadline;    /* when (in jiffies) tx times out */
+	unsigned long     tx_deadline;    /* when (in jiffies) tx times out */
 	ksock_msg_t    tx_msg;	 /* socklnd message buffer */
 	int	    tx_desc_size;   /* size of this descriptor */
 	union {
@@ -262,7 +262,7 @@ typedef struct ksock_conn
 	struct ksock_peer  *ksnc_peer;	 /* owning peer */
 	struct ksock_route *ksnc_route;	/* owning route */
 	struct list_head	  ksnc_list;	 /* stash on peer's conn list */
-	socket_t       *ksnc_sock;	 /* actual socket */
+	struct socket       *ksnc_sock;	 /* actual socket */
 	void	       *ksnc_saved_data_ready; /* socket's original data_ready() callback */
 	void	       *ksnc_saved_write_space; /* socket's original write_space() callback */
 	atomic_t	ksnc_conn_refcount; /* conn refcount */
@@ -280,7 +280,7 @@ typedef struct ksock_conn
 
 	/* reader */
 	struct list_head  ksnc_rx_list;     /* where I enq waiting input or a forwarding descriptor */
-	cfs_time_t	    ksnc_rx_deadline; /* when (in jiffies) receive times out */
+	unsigned long	    ksnc_rx_deadline; /* when (in jiffies) receive times out */
 	__u8		  ksnc_rx_started;  /* started receiving a message */
 	__u8		  ksnc_rx_ready;    /* data ready to read */
 	__u8		  ksnc_rx_scheduled;/* being progressed */
@@ -305,12 +305,12 @@ typedef struct ksock_conn
 	struct list_head	    ksnc_tx_list;     /* where I enq waiting for output space */
 	struct list_head	    ksnc_tx_queue;    /* packets waiting to be sent */
 	ksock_tx_t	   *ksnc_tx_carrier;  /* next TX that can carry a LNet message or ZC-ACK */
-	cfs_time_t	    ksnc_tx_deadline; /* when (in jiffies) tx times out */
+	unsigned long	    ksnc_tx_deadline; /* when (in jiffies) tx times out */
 	int		   ksnc_tx_bufnob;     /* send buffer marker */
 	atomic_t	  ksnc_tx_nob;	/* # bytes queued */
 	int		   ksnc_tx_ready;      /* write space */
 	int		   ksnc_tx_scheduled;  /* being progressed */
-	cfs_time_t	    ksnc_tx_last_post;  /* time stamp of the last posted TX */
+	unsigned long	    ksnc_tx_last_post;  /* time stamp of the last posted TX */
 } ksock_conn_t;
 
 typedef struct ksock_route
@@ -319,8 +319,8 @@ typedef struct ksock_route
 	struct list_head	    ksnr_connd_list;  /* chain on ksnr_connd_routes */
 	struct ksock_peer    *ksnr_peer;	/* owning peer */
 	atomic_t	  ksnr_refcount;    /* # users */
-	cfs_time_t	    ksnr_timeout;     /* when (in jiffies) reconnection can happen next */
-	cfs_duration_t	ksnr_retry_interval; /* how long between retries */
+	unsigned long	    ksnr_timeout;     /* when (in jiffies) reconnection can happen next */
+	long	ksnr_retry_interval; /* how long between retries */
 	__u32		 ksnr_myipaddr;    /* my IP */
 	__u32		 ksnr_ipaddr;      /* IP address to connect to */
 	int		   ksnr_port;	/* port to connect to */
@@ -337,7 +337,7 @@ typedef struct ksock_route
 typedef struct ksock_peer
 {
 	struct list_head	    ksnp_list;	/* stash on global peer list */
-	cfs_time_t	    ksnp_last_alive;  /* when (in jiffies) I was last alive */
+	unsigned long	    ksnp_last_alive;  /* when (in jiffies) I was last alive */
 	lnet_process_id_t     ksnp_id;       /* who's on the other end(s) */
 	atomic_t	  ksnp_refcount; /* # users */
 	int		   ksnp_sharecount;  /* lconf usage counter */
@@ -352,7 +352,7 @@ typedef struct ksock_peer
 	struct list_head	    ksnp_tx_queue; /* waiting packets */
 	spinlock_t	      ksnp_lock;	/* serialize, g_lock unsafe */
 	struct list_head	    ksnp_zc_req_list;   /* zero copy requests wait for ACK  */
-	cfs_time_t	    ksnp_send_keepalive; /* time to send keepalive */
+	unsigned long	    ksnp_send_keepalive; /* time to send keepalive */
 	lnet_ni_t	    *ksnp_ni;       /* which network */
 	int		   ksnp_n_passive_ips; /* # of... */
 	__u32		 ksnp_passive_ips[LNET_MAX_INTERFACES]; /* preferred local interfaces */
@@ -362,7 +362,7 @@ typedef struct ksock_connreq
 {
 	struct list_head	    ksncr_list;     /* stash on ksnd_connd_connreqs */
 	lnet_ni_t	    *ksncr_ni;       /* chosen NI */
-	socket_t	 *ksncr_sock;     /* accepted socket */
+	struct socket	 *ksncr_sock;     /* accepted socket */
 } ksock_connreq_t;
 
 extern ksock_nal_data_t ksocknal_data;
@@ -527,14 +527,14 @@ int ksocknal_recv(lnet_ni_t *ni, void *p
 		  int delayed, unsigned int niov,
 		  struct iovec *iov, lnet_kiov_t *kiov,
 		  unsigned int offset, unsigned int mlen, unsigned int rlen);
-int ksocknal_accept(lnet_ni_t *ni, socket_t *sock);
+int ksocknal_accept(lnet_ni_t *ni, struct socket *sock);
 
 extern int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port);
 extern ksock_peer_t *ksocknal_find_peer_locked (lnet_ni_t *ni, lnet_process_id_t id);
 extern ksock_peer_t *ksocknal_find_peer (lnet_ni_t *ni, lnet_process_id_t id);
 extern void ksocknal_peer_failed (ksock_peer_t *peer);
 extern int ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
-				 socket_t *sock, int type);
+				 struct socket *sock, int type);
 extern void ksocknal_close_conn_locked (ksock_conn_t *conn, int why);
 extern void ksocknal_terminate_conn (ksock_conn_t *conn);
 extern void ksocknal_destroy_conn (ksock_conn_t *conn);
@@ -555,7 +555,7 @@ extern void ksocknal_queue_tx_locked (ks
 extern void ksocknal_txlist_done (lnet_ni_t *ni, struct list_head *txlist,
 				  int error);
 extern void ksocknal_notify (lnet_ni_t *ni, lnet_nid_t gw_nid, int alive);
-extern void ksocknal_query (struct lnet_ni *ni, lnet_nid_t nid, cfs_time_t *when);
+extern void ksocknal_query (struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
 extern int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name);
 extern void ksocknal_thread_fini (void);
 extern void ksocknal_launch_all_connections_locked (ksock_peer_t *peer);
@@ -574,12 +574,12 @@ extern void ksocknal_read_callback(ksock
 extern void ksocknal_write_callback(ksock_conn_t *conn);
 
 extern int ksocknal_lib_zc_capable(ksock_conn_t *conn);
-extern void ksocknal_lib_save_callback(socket_t *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_set_callback(socket_t *sock,  ksock_conn_t *conn);
-extern void ksocknal_lib_reset_callback(socket_t *sock, ksock_conn_t *conn);
+extern void ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn);
+extern void ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn);
+extern void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn);
 extern void ksocknal_lib_push_conn (ksock_conn_t *conn);
 extern int ksocknal_lib_get_conn_addrs (ksock_conn_t *conn);
-extern int ksocknal_lib_setup_sock (socket_t *so);
+extern int ksocknal_lib_setup_sock (struct socket *so);
 extern int ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx);
 extern int ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx);
 extern void ksocknal_lib_eager_ack (ksock_conn_t *conn);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -695,7 +695,7 @@ ksocknal_lib_memory_pressure(ksock_conn_
 	sched = conn->ksnc_scheduler;
 	spin_lock_bh(&sched->kss_lock);
 
-	if (!SOCK_TEST_NOSPACE(conn->ksnc_sock) &&
+	if (!test_bit(SOCK_NOSPACE, &conn->ksnc_sock->flags) &&
 	    !conn->ksnc_tx_ready) {
 		/* SOCK_NOSPACE is set when the socket fills
 		 * and cleared in the write_space callback
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h	2014-09-28 17:29:07.000000000 -0400
@@ -62,8 +62,8 @@
 #include <asm/div64.h>
 #include <linux/syscalls.h>
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/libcfs/linux/portals_compat25.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../../../include/linux/libcfs/linux/portals_compat25.h"
 
 #include <linux/crc32.h>
 static inline __u32 ksocknal_csum(__u32 crc, unsigned char const *p, size_t len)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c	2014-09-28 17:29:07.000000000 -0400
@@ -192,7 +192,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t
 
 	if (cookie == tx->tx_msg.ksm_zc_cookies[0] ||
 	    cookie == tx->tx_msg.ksm_zc_cookies[1]) {
-		CWARN("%s: duplicated ZC cookie: "LPU64"\n",
+		CWARN("%s: duplicated ZC cookie: %llu\n",
 		      libcfs_id2str(conn->ksnc_peer->ksnp_id), cookie);
 		return 1; /* XXX return error in the future */
 	}
@@ -244,7 +244,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t
 		/* ksm_zc_cookies[0] < ksm_zc_cookies[1], it is range of cookies */
 		if (cookie >= tx->tx_msg.ksm_zc_cookies[0] &&
 		    cookie <= tx->tx_msg.ksm_zc_cookies[1]) {
-			CWARN("%s: duplicated ZC cookie: "LPU64"\n",
+			CWARN("%s: duplicated ZC cookie: %llu\n",
 			      libcfs_id2str(conn->ksnc_peer->ksnp_id), cookie);
 			return 1; /* XXX: return error in the future */
 		}
@@ -452,7 +452,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn
 static int
 ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 {
-	socket_t	*sock = conn->ksnc_sock;
+	struct socket	*sock = conn->ksnc_sock;
 	lnet_hdr_t	  *hdr;
 	lnet_magicversion_t *hmv;
 	int		  rc;
@@ -527,7 +527,7 @@ out:
 static int
 ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
 {
-	socket_t   *sock = conn->ksnc_sock;
+	struct socket *sock = conn->ksnc_sock;
 	int	     rc;
 
 	hello->kshm_magic   = LNET_PROTO_MAGIC;
@@ -570,7 +570,7 @@ ksocknal_send_hello_v2 (ksock_conn_t *co
 static int
 ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout)
 {
-	socket_t	*sock = conn->ksnc_sock;
+	struct socket	*sock = conn->ksnc_sock;
 	lnet_hdr_t	  *hdr;
 	int		  rc;
 	int		  i;
@@ -646,7 +646,7 @@ out:
 static int
 ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout)
 {
-	socket_t      *sock = conn->ksnc_sock;
+	struct socket   *sock = conn->ksnc_sock;
 	int		rc;
 	int		i;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/acceptor.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/acceptor.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/acceptor.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/acceptor.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,16 +35,16 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 
 static int   accept_port    = 988;
 static int   accept_backlog = 127;
 static int   accept_timeout = 5;
 
-struct {
+static struct {
 	int			pta_shutdown;
-	socket_t		*pta_sock;
+	struct socket		*pta_sock;
 	struct completion	pta_signal;
 } lnet_acceptor_state;
 
@@ -75,7 +75,7 @@ MODULE_PARM_DESC(accept_timeout, "Accept
 
 static char *accept_type;
 
-int
+static int
 lnet_acceptor_get_tunables(void)
 {
 	/* Userland acceptor uses 'accept_type' instead of 'accept', due to
@@ -139,11 +139,11 @@ lnet_connect_console_error(int rc, lnet_
 EXPORT_SYMBOL(lnet_connect_console_error);
 
 int
-lnet_connect(socket_t **sockp, lnet_nid_t peer_nid,
+lnet_connect(struct socket **sockp, lnet_nid_t peer_nid,
 	    __u32 local_ip, __u32 peer_ip, int peer_port)
 {
 	lnet_acceptor_connreq_t cr;
-	socket_t	   *sock;
+	struct socket	   *sock;
 	int		     rc;
 	int		     port;
 	int		     fatal;
@@ -207,8 +207,8 @@ EXPORT_SYMBOL(lnet_connect);
 
 /* Below is the code common for both kernel and MT user-space */
 
-int
-lnet_accept(socket_t *sock, __u32 magic)
+static int
+lnet_accept(struct socket *sock, __u32 magic)
 {
 	lnet_acceptor_connreq_t cr;
 	__u32		   peer_ip;
@@ -329,10 +329,10 @@ lnet_accept(socket_t *sock, __u32 magic)
 	return rc;
 }
 
-int
+static int
 lnet_acceptor(void *arg)
 {
-	socket_t  *newsock;
+	struct socket *newsock;
 	int	    rc;
 	__u32	  magic;
 	__u32	  peer_ip;
@@ -457,10 +457,8 @@ lnet_acceptor_start(void)
 
 	init_completion(&lnet_acceptor_state.pta_signal);
 	rc = accept2secure(accept_type, &secure);
-	if (rc <= 0) {
-		fini_completion(&lnet_acceptor_state.pta_signal);
+	if (rc <= 0)
 		return rc;
-	}
 
 	if (lnet_count_acceptor_nis() == 0)  /* not required */
 		return 0;
@@ -470,7 +468,6 @@ lnet_acceptor_start(void)
 				  "acceptor_%03ld", secure));
 	if (IS_ERR_VALUE(rc2)) {
 		CERROR("Can't start acceptor thread: %ld\n", rc2);
-		fini_completion(&lnet_acceptor_state.pta_signal);
 
 		return -ESRCH;
 	}
@@ -485,7 +482,6 @@ lnet_acceptor_start(void)
 	}
 
 	LASSERT(lnet_acceptor_state.pta_sock == NULL);
-	fini_completion(&lnet_acceptor_state.pta_signal);
 
 	return -ENETDOWN;
 }
@@ -501,6 +497,4 @@ lnet_acceptor_stop(void)
 
 	/* block until acceptor signals exit */
 	wait_for_completion(&lnet_acceptor_state.pta_signal);
-
-	fini_completion(&lnet_acceptor_state.pta_signal);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/api-ni.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/api-ni.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/api-ni.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/api-ni.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 #include <linux/log2.h>
 
 #define D_LNI D_CONSOLE
@@ -60,13 +60,13 @@ static int rnet_htable_size = LNET_REMOT
 module_param(rnet_htable_size, int, 0444);
 MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table");
 
-char *
+static char *
 lnet_get_routes(void)
 {
 	return routes;
 }
 
-char *
+static char *
 lnet_get_networks(void)
 {
 	char   *nets;
@@ -89,7 +89,7 @@ lnet_get_networks(void)
 	return "tcp";
 }
 
-void
+static void
 lnet_init_locks(void)
 {
 	spin_lock_init(&the_lnet.ln_eq_wait_lock);
@@ -98,7 +98,7 @@ lnet_init_locks(void)
 	mutex_init(&the_lnet.ln_api_mutex);
 }
 
-void
+static void
 lnet_fini_locks(void)
 {
 }
@@ -177,7 +177,7 @@ lnet_create_locks(void)
 	return -ENOMEM;
 }
 
-void lnet_assert_wire_constants (void)
+static void lnet_assert_wire_constants (void)
 {
 	/* Wire protocol assertions generated by 'wirecheck'
 	 * running on Linux robert.bartonsoftware.com 2.6.8-1.521
@@ -270,7 +270,7 @@ void lnet_assert_wire_constants (void)
 	CLASSERT ((int)sizeof(((lnet_hdr_t *)0)->msg.hello.type) == 4);
 }
 
-lnd_t *
+static lnd_t *
 lnet_find_lnd_by_type (int type)
 {
 	lnd_t	      *lnd;
@@ -415,7 +415,7 @@ lnet_freelist_fini (lnet_freelist_t *fl)
 
 #endif /* LNET_USE_LIB_FREELIST */
 
-__u64
+static __u64
 lnet_create_interface_cookie (void)
 {
 	/* NB the interface cookie in wire handles guards against delayed
@@ -446,7 +446,7 @@ lnet_res_type2str(int type)
 	}
 }
 
-void
+static void
 lnet_res_container_cleanup(struct lnet_res_container *rec)
 {
 	int	count = 0;
@@ -490,7 +490,7 @@ lnet_res_container_cleanup(struct lnet_r
 	rec->rec_type = 0; /* mark it as finalized */
 }
 
-int
+static int
 lnet_res_container_setup(struct lnet_res_container *rec,
 			 int cpt, int type, int objnum, int objsz)
 {
@@ -608,7 +608,7 @@ lnet_res_lh_initialize(struct lnet_res_c
 
 int lnet_unprepare(void);
 
-int
+static int
 lnet_prepare(lnet_pid_t requested_pid)
 {
 	/* Prepare to bring up the network */
@@ -913,7 +913,7 @@ lnet_ni_tq_credits(lnet_ni_t *ni)
 	return credits;
 }
 
-void
+static void
 lnet_shutdown_lndnis (void)
 {
 	int		i;
@@ -1030,7 +1030,7 @@ lnet_shutdown_lndnis (void)
 	}
 }
 
-int
+static int
 lnet_startup_lndnis (void)
 {
 	lnd_t			*lnd;
@@ -1452,7 +1452,7 @@ LNetCtl(unsigned int cmd, void *arg)
 	case IOC_LIBCFS_NOTIFY_ROUTER:
 		return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
 				   cfs_time_current() -
-				   cfs_time_seconds(cfs_time_current_sec() -
+				   cfs_time_seconds(get_seconds() -
 						    (time_t)data->ioc_u64[0]));
 
 	case IOC_LIBCFS_PORTALS_COMPATIBILITY:
@@ -1575,7 +1575,7 @@ EXPORT_SYMBOL(LNetGetId);
 void
 LNetSnprintHandle(char *str, int len, lnet_handle_any_t h)
 {
-	snprintf(str, len, LPX64, h.cookie);
+	snprintf(str, len, "%#llx", h.cookie);
 }
 EXPORT_SYMBOL(LNetSnprintHandle);
 
@@ -1662,7 +1662,7 @@ lnet_destroy_ping_info(void)
 int
 lnet_ping_target_init(void)
 {
-	lnet_md_t	 md = {0};
+	lnet_md_t	 md = { NULL };
 	lnet_handle_me_t  meh;
 	lnet_process_id_t id;
 	int	       rc;
@@ -1770,7 +1770,7 @@ lnet_ping (lnet_process_id_t id, int tim
 	lnet_handle_eq_t     eqh;
 	lnet_handle_md_t     mdh;
 	lnet_event_t	 event;
-	lnet_md_t	    md = {0};
+	lnet_md_t	    md = { NULL };
 	int		  which;
 	int		  unlinked = 0;
 	int		  replied = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/config.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/config.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/config.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/config.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 typedef struct {			    /* tmp struct for parsing routes */
 	struct list_head	 ltb_list;	/* stash on lists */
@@ -166,7 +166,7 @@ lnet_ni_alloc(__u32 net, struct cfs_expr
 
 	/* LND will fill in the address part of the NID */
 	ni->ni_nid = LNET_MKNID(net, 0);
-	ni->ni_last_alive = cfs_time_current_sec();
+	ni->ni_last_alive = get_seconds();
 	list_add_tail(&ni->ni_list, nilist);
 	return ni;
  failed:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-eq.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-eq.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-eq.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-eq.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 /**
  * Create an event queue that has room for \a count number of events.
@@ -330,7 +330,7 @@ __must_hold(&the_lnet.ln_eq_wait_lock)
 	int		tms = *timeout_ms;
 	int		wait;
 	wait_queue_t  wl;
-	cfs_time_t      now;
+	unsigned long      now;
 
 	if (tms == 0)
 		return -1; /* don't want to wait and no new event */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-md.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-md.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-md.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-md.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 /* must be called with lnet_res_lock held */
 void
@@ -387,7 +387,8 @@ EXPORT_SYMBOL(LNetMDBind);
 
 /**
  * Unlink the memory descriptor from any ME it may be linked to and release
- * the internal resources associated with it.
+ * the internal resources associated with it. As a result, active messages
+ * associated with the MD may get aborted.
  *
  * This function does not free the memory region associated with the MD;
  * i.e., the memory the user allocated for this MD. If the ME associated with
@@ -433,12 +434,11 @@ LNetMDUnlink (lnet_handle_md_t mdh)
 		return -ENOENT;
 	}
 
+	md->md_flags |= LNET_MD_FLAG_ABORTED;
 	/* If the MD is busy, lnet_md_unlink just marks it for deletion, and
-	 * when the NAL is done, the completion event flags that the MD was
+	 * when the LND is done, the completion event flags that the MD was
 	 * unlinked.  Otherwise, we enqueue an event now... */
-
-	if (md->md_eq != NULL &&
-	    md->md_refcount == 0) {
+	if (md->md_eq != NULL && md->md_refcount == 0) {
 		lnet_build_unlink_event(md, &ev);
 		lnet_eq_enqueue_event(md->md_eq, &ev);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-me.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-me.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-me.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-me.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 /**
  * Create and attach a match entry to the match list of \a portal. The new
@@ -246,11 +246,12 @@ LNetMEUnlink(lnet_handle_me_t meh)
 	}
 
 	md = me->me_md;
-	if (md != NULL &&
-	    md->md_eq != NULL &&
-	    md->md_refcount == 0) {
-		lnet_build_unlink_event(md, &ev);
-		lnet_eq_enqueue_event(md->md_eq, &ev);
+	if (md != NULL) {
+		md->md_flags |= LNET_MD_FLAG_ABORTED;
+		if (md->md_eq != NULL && md->md_refcount == 0) {
+			lnet_build_unlink_event(md, &ev);
+			lnet_eq_enqueue_event(md->md_eq, &ev);
+		}
 	}
 
 	lnet_me_unlink(me);
@@ -282,7 +283,7 @@ lnet_me_unlink(lnet_me_t *me)
 static void
 lib_me_dump(lnet_me_t *me)
 {
-	CWARN("Match Entry %p ("LPX64")\n", me,
+	CWARN("Match Entry %p (%#llx)\n", me,
 	      me->me_lh.lh_cookie);
 
 	CWARN("\tMatch/Ignore\t= %016lx / %016lx\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-move.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-move.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-move.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-move.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 static int local_nid_dist_zero = 1;
 module_param(local_nid_dist_zero, int, 0444);
@@ -682,7 +682,7 @@ lnet_ni_eager_recv(lnet_ni_t *ni, lnet_m
 void
 lnet_ni_query_locked(lnet_ni_t *ni, lnet_peer_t *lp)
 {
-	cfs_time_t last_alive = 0;
+	unsigned long last_alive = 0;
 
 	LASSERT(lnet_peer_aliveness_enabled(lp));
 	LASSERT(ni->ni_lnd->lnd_query != NULL);
@@ -699,10 +699,10 @@ lnet_ni_query_locked(lnet_ni_t *ni, lnet
 
 /* NB: always called with lnet_net_lock held */
 static inline int
-lnet_peer_is_alive(lnet_peer_t *lp, cfs_time_t now)
+lnet_peer_is_alive(lnet_peer_t *lp, unsigned long now)
 {
 	int	alive;
-	cfs_time_t deadline;
+	unsigned long deadline;
 
 	LASSERT(lnet_peer_aliveness_enabled(lp));
 
@@ -734,7 +734,7 @@ lnet_peer_is_alive(lnet_peer_t *lp, cfs_
 int
 lnet_peer_alive_locked(lnet_peer_t *lp)
 {
-	cfs_time_t now = cfs_time_current();
+	unsigned long now = cfs_time_current();
 
 	if (!lnet_peer_aliveness_enabled(lp))
 		return -ENODEV;
@@ -747,11 +747,11 @@ lnet_peer_alive_locked(lnet_peer_t *lp)
 	if (lp->lp_last_query != 0) {
 		static const int lnet_queryinterval = 1;
 
-		cfs_time_t next_query =
+		unsigned long next_query =
 			   cfs_time_add(lp->lp_last_query,
 					cfs_time_seconds(lnet_queryinterval));
 
-		if (cfs_time_before(now, next_query)) {
+		if (time_before(now, next_query)) {
 			if (lp->lp_alive)
 				CWARN("Unexpected aliveness of peer %s: "
 				      "%d < %d (%d/%d)\n",
@@ -773,26 +773,30 @@ lnet_peer_alive_locked(lnet_peer_t *lp)
 	return 0;
 }
 
-int
+/**
+ * \param msg The message to be sent.
+ * \param do_send True if lnet_ni_send() should be called in this function.
+ *	  lnet_send() is going to lnet_net_unlock immediately after this, so
+ *	  it sets do_send FALSE and I don't do the unlock/send/lock bit.
+ *
+ * \retval 0 If \a msg sent or OK to send.
+ * \retval EAGAIN If \a msg blocked for credit.
+ * \retval EHOSTUNREACH If the next hop of the message appears dead.
+ * \retval ECANCELED If the MD of the message has been unlinked.
+ */
+static int
 lnet_post_send_locked(lnet_msg_t *msg, int do_send)
 {
-	/* lnet_send is going to lnet_net_unlock immediately after this,
-	 * so it sets do_send FALSE and I don't do the unlock/send/lock bit.
-	 * I return EAGAIN if msg blocked, EHOSTUNREACH if msg_txpeer
-	 * appears dead, and 0 if sent or OK to send */
-	struct lnet_peer	*lp = msg->msg_txpeer;
-	struct lnet_ni		*ni = lp->lp_ni;
-	struct lnet_tx_queue	*tq;
-	int			cpt;
+	lnet_peer_t		*lp = msg->msg_txpeer;
+	lnet_ni_t		*ni = lp->lp_ni;
+	int			cpt = msg->msg_tx_cpt;
+	struct lnet_tx_queue	*tq = ni->ni_tx_queues[cpt];
 
 	/* non-lnet_send() callers have checked before */
 	LASSERT(!do_send || msg->msg_tx_delayed);
 	LASSERT(!msg->msg_receiving);
 	LASSERT(msg->msg_tx_committed);
 
-	cpt = msg->msg_tx_cpt;
-	tq = ni->ni_tx_queues[cpt];
-
 	/* NB 'lp' is always the next hop */
 	if ((msg->msg_target.pid & LNET_PID_USERFLAG) == 0 &&
 	    lnet_peer_alive_locked(lp) == 0) {
@@ -809,6 +813,20 @@ lnet_post_send_locked(lnet_msg_t *msg, i
 		return EHOSTUNREACH;
 	}
 
+	if (msg->msg_md != NULL &&
+	    (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED) != 0) {
+		lnet_net_unlock(cpt);
+
+		CNETERR("Aborting message for %s: LNetM[DE]Unlink() already "
+			"called on the MD/ME.\n",
+			libcfs_id2str(msg->msg_target));
+		if (do_send)
+			lnet_finalize(ni, msg, -ECANCELED);
+
+		lnet_net_lock(cpt);
+		return ECANCELED;
+	}
+
 	if (!msg->msg_peertxcredit) {
 		LASSERT((lp->lp_txcredits < 0) ==
 			 !list_empty(&lp->lp_txq));
@@ -1327,13 +1345,13 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t
 	rc = lnet_post_send_locked(msg, 0);
 	lnet_net_unlock(cpt);
 
-	if (rc == EHOSTUNREACH)
-		return -EHOSTUNREACH;
+	if (rc == EHOSTUNREACH || rc == ECANCELED)
+		return -rc;
 
 	if (rc == 0)
 		lnet_ni_send(src_ni, msg);
 
-	return 0;
+	return 0; /* rc == 0 or EAGAIN */
 }
 
 static void
@@ -1408,8 +1426,7 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t
 		/* fall through */
 
 	case LNET_MATCHMD_DROP:
-		CNETERR("Dropping PUT from %s portal %d match "LPU64
-			" offset %d length %d: %d\n",
+		CNETERR("Dropping PUT from %s portal %d match %llu offset %d length %d: %d\n",
 			libcfs_id2str(info.mi_id), info.mi_portal,
 			info.mi_mbits, info.mi_roffset, info.mi_rlength, rc);
 
@@ -1441,8 +1458,7 @@ lnet_parse_get(lnet_ni_t *ni, lnet_msg_t
 
 	rc = lnet_ptl_match_md(&info, msg);
 	if (rc == LNET_MATCHMD_DROP) {
-		CNETERR("Dropping GET from %s portal %d match "LPU64
-			" offset %d length %d\n",
+		CNETERR("Dropping GET from %s portal %d match %llu offset %d length %d\n",
 			libcfs_id2str(info.mi_id), info.mi_portal,
 			info.mi_mbits, info.mi_roffset, info.mi_rlength);
 		return ENOENT;	/* +ve: OK but no match */
@@ -1502,8 +1518,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg
 	/* NB handles only looked up by creator (no flips) */
 	md = lnet_wire_handle2md(&hdr->msg.reply.dst_wmd);
 	if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) {
-		CNETERR("%s: Dropping REPLY from %s for %s "
-			"MD "LPX64"."LPX64"\n",
+		CNETERR("%s: Dropping REPLY from %s for %s MD %#llx.%#llx\n",
 			libcfs_nid2str(ni->ni_nid), libcfs_id2str(src),
 			(md == NULL) ? "invalid" : "inactive",
 			hdr->msg.reply.dst_wmd.wh_interface_cookie,
@@ -1523,8 +1538,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg
 
 	if (mlength < rlength &&
 	    (md->md_options & LNET_MD_TRUNCATE) == 0) {
-		CNETERR("%s: Dropping REPLY from %s length %d "
-			"for MD "LPX64" would overflow (%d)\n",
+		CNETERR("%s: Dropping REPLY from %s length %d for MD %#llx would overflow (%d)\n",
 			libcfs_nid2str(ni->ni_nid), libcfs_id2str(src),
 			rlength, hdr->msg.reply.dst_wmd.wh_object_cookie,
 			mlength);
@@ -1532,7 +1546,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg
 		return ENOENT;	  /* +ve: OK but no match */
 	}
 
-	CDEBUG(D_NET, "%s: Reply from %s of length %d/%d into md "LPX64"\n",
+	CDEBUG(D_NET, "%s: Reply from %s of length %d/%d into md %#llx\n",
 	       libcfs_nid2str(ni->ni_nid), libcfs_id2str(src),
 	       mlength, rlength, hdr->msg.reply.dst_wmd.wh_object_cookie);
 
@@ -1572,7 +1586,7 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t
 	if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) {
 		/* Don't moan; this is expected */
 		CDEBUG(D_NET,
-		       "%s: Dropping ACK from %s to %s MD "LPX64"."LPX64"\n",
+		       "%s: Dropping ACK from %s to %s MD %#llx.%#llx\n",
 		       libcfs_nid2str(ni->ni_nid), libcfs_id2str(src),
 		       (md == NULL) ? "invalid" : "inactive",
 		       hdr->msg.ack.dst_wmd.wh_interface_cookie,
@@ -1585,7 +1599,7 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t
 		return ENOENT;		  /* +ve! */
 	}
 
-	CDEBUG(D_NET, "%s: ACK from %s into md "LPX64"\n",
+	CDEBUG(D_NET, "%s: ACK from %s into md %#llx\n",
 	       libcfs_nid2str(ni->ni_nid), libcfs_id2str(src),
 	       hdr->msg.ack.dst_wmd.wh_object_cookie);
 
@@ -1662,20 +1676,20 @@ lnet_print_hdr(lnet_hdr_t *hdr)
 		break;
 
 	case LNET_MSG_PUT:
-		CWARN("    Ptl index %d, ack md "LPX64"."LPX64", "
-		      "match bits "LPU64"\n",
+		CWARN("    Ptl index %d, ack md %#llx.%#llx, "
+		      "match bits %llu\n",
 		      hdr->msg.put.ptl_index,
 		      hdr->msg.put.ack_wmd.wh_interface_cookie,
 		      hdr->msg.put.ack_wmd.wh_object_cookie,
 		      hdr->msg.put.match_bits);
-		CWARN("    Length %d, offset %d, hdr data "LPX64"\n",
+		CWARN("    Length %d, offset %d, hdr data %#llx\n",
 		      hdr->payload_length, hdr->msg.put.offset,
 		      hdr->msg.put.hdr_data);
 		break;
 
 	case LNET_MSG_GET:
-		CWARN("    Ptl index %d, return md "LPX64"."LPX64", "
-		      "match bits "LPU64"\n", hdr->msg.get.ptl_index,
+		CWARN("    Ptl index %d, return md %#llx.%#llx, "
+		      "match bits %llu\n", hdr->msg.get.ptl_index,
 		      hdr->msg.get.return_wmd.wh_interface_cookie,
 		      hdr->msg.get.return_wmd.wh_object_cookie,
 		      hdr->msg.get.match_bits);
@@ -1685,7 +1699,7 @@ lnet_print_hdr(lnet_hdr_t *hdr)
 		break;
 
 	case LNET_MSG_ACK:
-		CWARN("    dst md "LPX64"."LPX64", "
+		CWARN("    dst md %#llx.%#llx, "
 		      "manipulated length %d\n",
 		      hdr->msg.ack.dst_wmd.wh_interface_cookie,
 		      hdr->msg.ack.dst_wmd.wh_object_cookie,
@@ -1693,7 +1707,7 @@ lnet_print_hdr(lnet_hdr_t *hdr)
 		break;
 
 	case LNET_MSG_REPLY:
-		CWARN("    dst md "LPX64"."LPX64", "
+		CWARN("    dst md %#llx.%#llx, "
 		      "length %d\n",
 		      hdr->msg.reply.dst_wmd.wh_interface_cookie,
 		      hdr->msg.reply.dst_wmd.wh_object_cookie,
@@ -1762,11 +1776,11 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hd
 	}
 
 	if (the_lnet.ln_routing &&
-	    ni->ni_last_alive != cfs_time_current_sec()) {
+	    ni->ni_last_alive != get_seconds()) {
 		lnet_ni_lock(ni);
 
 		/* NB: so far here is the only place to set NI status to "up */
-		ni->ni_last_alive = cfs_time_current_sec();
+		ni->ni_last_alive = get_seconds();
 		if (ni->ni_status != NULL &&
 		    ni->ni_status->ns_status == LNET_NI_STATUS_DOWN)
 			ni->ni_status->ns_status = LNET_NI_STATUS_UP;
@@ -1945,8 +1959,7 @@ lnet_drop_delayed_msg_list(struct list_h
 		LASSERT(msg->msg_rxpeer != NULL);
 		LASSERT(msg->msg_hdr.type == LNET_MSG_PUT);
 
-		CWARN("Dropping delayed PUT from %s portal %d match "LPU64
-		      " offset %d length %d: %s\n",
+		CWARN("Dropping delayed PUT from %s portal %d match %llu offset %d length %d: %s\n",
 		      libcfs_id2str(id),
 		      msg->msg_hdr.msg.put.ptl_index,
 		      msg->msg_hdr.msg.put.match_bits,
@@ -1991,7 +2004,7 @@ lnet_recv_delayed_msg_list(struct list_h
 		LASSERT(msg->msg_hdr.type == LNET_MSG_PUT);
 
 		CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d "
-		       "match "LPU64" offset %d length %d.\n",
+		       "match %llu offset %d length %d.\n",
 			libcfs_id2str(id), msg->msg_hdr.msg.put.ptl_index,
 			msg->msg_hdr.msg.put.match_bits,
 			msg->msg_hdr.msg.put.offset,
@@ -2079,7 +2092,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_
 
 	md = lnet_handle2md(&mdh);
 	if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) {
-		CERROR("Dropping PUT ("LPU64":%d:%s): MD (%d) invalid\n",
+		CERROR("Dropping PUT (%llu:%d:%s): MD (%d) invalid\n",
 		       match_bits, portal, libcfs_id2str(target),
 		       md == NULL ? -1 : md->md_threshold);
 		if (md != NULL && md->md_me != NULL)
@@ -2278,7 +2291,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_
 
 	md = lnet_handle2md(&mdh);
 	if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) {
-		CERROR("Dropping GET ("LPU64":%d:%s): MD (%d) invalid\n",
+		CERROR("Dropping GET (%llu:%d:%s): MD (%d) invalid\n",
 		       match_bits, portal, libcfs_id2str(target),
 		       md == NULL ? -1 : md->md_threshold);
 		if (md != NULL && md->md_me != NULL)
@@ -2288,7 +2301,6 @@ LNetGet(lnet_nid_t self, lnet_handle_md_
 		lnet_res_unlock(cpt);
 
 		lnet_msg_free(msg);
-
 		return -ENOENT;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-msg.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-msg.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-msg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-msg.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 void
 lnet_build_unlink_event(lnet_libmd_t *md, lnet_event_t *ev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-ptl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-ptl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lib-ptl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lib-ptl.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 /* NB: add /proc interfaces in upcoming patches */
 int	portal_rotor	= LNET_PTL_ROTOR_HASH_RT;
@@ -184,8 +184,7 @@ lnet_try_match_md(lnet_libmd_t *md,
 		mlength = info->mi_rlength;
 	} else if ((md->md_options & LNET_MD_TRUNCATE) == 0) {
 		/* this packet _really_ is too big */
-		CERROR("Matching packet from %s, match "LPU64
-		       " length %d too big: %d left, %d allowed\n",
+		CERROR("Matching packet from %s, match %llu length %d too big: %d left, %d allowed\n",
 		       libcfs_id2str(info->mi_id), info->mi_mbits,
 		       info->mi_rlength, md->md_length - offset, mlength);
 
@@ -194,7 +193,7 @@ lnet_try_match_md(lnet_libmd_t *md,
 
 	/* Commit to this ME/MD */
 	CDEBUG(D_NET, "Incoming %s index %x from %s of "
-	       "length %d/%d into md "LPX64" [%d] + %d\n",
+	       "length %d/%d into md %#llx [%d] + %d\n",
 	       (info->mi_opc == LNET_MD_OP_PUT) ? "put" : "get",
 	       info->mi_portal, libcfs_id2str(info->mi_id), mlength,
 	       info->mi_rlength, md->md_lh.lh_cookie, md->md_niov, offset);
@@ -541,9 +540,9 @@ lnet_ptl_match_md(struct lnet_match_info
 	struct lnet_portal	*ptl;
 	int			rc;
 
-	CDEBUG(D_NET, "Request from %s of length %d into portal %d "
-	       "MB="LPX64"\n", libcfs_id2str(info->mi_id),
-	       info->mi_rlength, info->mi_portal, info->mi_mbits);
+	CDEBUG(D_NET, "Request from %s of length %d into portal %d MB=%#llx\n",
+	       libcfs_id2str(info->mi_id), info->mi_rlength, info->mi_portal,
+	       info->mi_mbits);
 
 	if (info->mi_portal >= the_lnet.ln_nportals) {
 		CERROR("Invalid portal %d not in [0-%d]\n",
@@ -597,7 +596,7 @@ lnet_ptl_match_md(struct lnet_match_info
 
 	if (msg->msg_rx_delayed) {
 		CDEBUG(D_NET,
-		       "Delaying %s from %s ptl %d MB "LPX64" off %d len %d\n",
+		       "Delaying %s from %s ptl %d MB %#llx off %d len %d\n",
 		       info->mi_opc == LNET_MD_OP_PUT ? "PUT" : "GET",
 		       libcfs_id2str(info->mi_id), info->mi_portal,
 		       info->mi_mbits, info->mi_roffset, info->mi_rlength);
@@ -687,8 +686,7 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_l
 		if ((rc & LNET_MATCHMD_OK) != 0) {
 			list_add_tail(&msg->msg_list, matches);
 
-			CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d "
-			       "match "LPU64" offset %d length %d.\n",
+			CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d match %llu offset %d length %d.\n",
 			       libcfs_id2str(info.mi_id),
 			       info.mi_portal, info.mi_mbits,
 			       info.mi_roffset, info.mi_rlength);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/lo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/lo.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 int
 lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -3,6 +3,3 @@ obj-$(CONFIG_LNET) += lnet.o
 lnet-y := api-ni.o config.o lib-me.o lib-msg.o lib-eq.o	\
 	  lib-md.o lib-ptl.o lib-move.o module.o lo.o router.o		\
 	  router_proc.o acceptor.o peer.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/module.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/module.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/module.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 static int config_on_load;
 module_param(config_on_load, int, 0444);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/peer.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/peer.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/peer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/peer.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,7 +38,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 int
 lnet_peer_tables_create(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/router.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/router.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/router.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/router.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/lnet/lib-lnet.h"
 
 #if  defined(LNET_ROUTER)
 
@@ -107,9 +107,9 @@ lnet_peers_start_down(void)
 }
 
 void
-lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, cfs_time_t when)
+lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, unsigned long when)
 {
-	if (cfs_time_before(when, lp->lp_timestamp)) { /* out of date information */
+	if (time_before(when, lp->lp_timestamp)) { /* out of date information */
 		CDEBUG(D_NET, "Out of date\n");
 		return;
 	}
@@ -135,7 +135,7 @@ lnet_notify_locked(lnet_peer_t *lp, int
 	CDEBUG(D_NET, "set %s %d\n", libcfs_nid2str(lp->lp_nid), alive);
 }
 
-void
+static void
 lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp)
 {
 	int	alive;
@@ -273,7 +273,7 @@ static void lnet_shuffle_seed(void)
 }
 
 /* NB expects LNET_LOCK held */
-void
+static void
 lnet_add_route_to_rnet (lnet_remotenet_t *rnet, lnet_route_t *route)
 {
 	unsigned int      len = 0;
@@ -796,7 +796,7 @@ lnet_update_ni_status_locked(void)
 	timeout = router_ping_timeout +
 		  MAX(live_router_check_interval, dead_router_check_interval);
 
-	now = cfs_time_current_sec();
+	now = get_seconds();
 	list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
 		if (ni->ni_lnd->lnd_type == LOLND)
 			continue;
@@ -866,7 +866,6 @@ lnet_create_rc_data_locked(lnet_peer_t *
 	if (pi == NULL)
 		goto out;
 
-	memset(pi, 0, LNET_PINGINFO_SIZE);
 	for (i = 0; i < LNET_MAX_RTR_NIS; i++) {
 		pi->pi_ni[i].ns_nid = LNET_NID_ANY;
 		pi->pi_ni[i].ns_status = LNET_NI_STATUS_INVALID;
@@ -932,7 +931,7 @@ static void
 lnet_ping_router_locked (lnet_peer_t *rtr)
 {
 	lnet_rc_data_t *rcd = NULL;
-	cfs_time_t      now = cfs_time_current();
+	unsigned long      now = cfs_time_current();
 	int	     secs;
 
 	lnet_peer_addref_locked(rtr);
@@ -1498,10 +1497,10 @@ lnet_rtrpools_alloc(int im_a_router)
 }
 
 int
-lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, cfs_time_t when)
+lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
 {
 	struct lnet_peer	*lp = NULL;
-	cfs_time_t		now = cfs_time_current();
+	unsigned long		now = cfs_time_current();
 	int			cpt = lnet_cpt_of_nid(nid);
 
 	LASSERT (!in_interrupt ());
@@ -1577,7 +1576,7 @@ lnet_get_tunables (void)
 #else
 
 int
-lnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, cfs_time_t when)
+lnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
 {
 	return -EOPNOTSUPP;
 }
@@ -1588,7 +1587,7 @@ lnet_router_checker (void)
 	static time_t last = 0;
 	static int    running = 0;
 
-	time_t	    now = cfs_time_current_sec();
+	time_t	    now = get_seconds();
 	int	       interval = now - last;
 	int	       rc;
 	__u64	     version;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/router_proc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/router_proc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/lnet/router_proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/lnet/router_proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,15 +22,15 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lib-lnet.h"
 
 #if  defined(LNET_ROUTER)
 
 /* This is really lnet_proc.c. You might need to update sanity test 215
  * if any file format is changed. */
 
-static ctl_table_header_t *lnet_table_header;
+static struct ctl_table_header *lnet_table_header;
 
 #define CTL_LNET	 (0x100)
 enum {
@@ -90,6 +90,24 @@ enum {
 
 #define LNET_PROC_VERSION(v)	((unsigned int)((v) & LNET_PROC_VER_MASK))
 
+static int proc_call_handler(void *data, int write, loff_t *ppos, void *buffer,
+			     size_t *lenp, int (*handler)(void *data, int write,
+			     loff_t pos, void *buffer, int len))
+{
+	int rc = handler(data, write, *ppos, buffer, *lenp);
+
+	if (rc < 0)
+		return rc;
+
+	if (write) {
+		*ppos += *lenp;
+	} else {
+		*lenp = rc;
+		*ppos += rc;
+	}
+	return 0;
+}
+
 static int __proc_lnet_stats(void *data, int write,
 			     loff_t pos, void *buffer, int nob)
 {
@@ -97,7 +115,7 @@ static int __proc_lnet_stats(void *data,
 	lnet_counters_t *ctrs;
 	int	      len;
 	char	    *tmpstr;
-	const int	tmpsiz = 256; /* 7 %u and 4 LPU64 */
+	const int	tmpsiz = 256; /* 7 %u and 4 %llu */
 
 	if (write) {
 		lnet_counters_reset();
@@ -119,8 +137,7 @@ static int __proc_lnet_stats(void *data,
 	lnet_counters_get(ctrs);
 
 	len = snprintf(tmpstr, tmpsiz,
-		       "%u %u %u %u %u %u %u "LPU64" "LPU64" "
-		       LPU64" "LPU64,
+		       "%u %u %u %u %u %u %u %llu %llu %llu %llu",
 		       ctrs->msgs_alloc, ctrs->msgs_max,
 		       ctrs->errors,
 		       ctrs->send_count, ctrs->recv_count,
@@ -139,9 +156,15 @@ static int __proc_lnet_stats(void *data,
 	return rc;
 }
 
-DECLARE_PROC_HANDLER(proc_lnet_stats);
+static int proc_lnet_stats(struct ctl_table *table, int write,
+			   void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_lnet_stats);
+}
 
-int LL_PROC_PROTO(proc_lnet_routes)
+int proc_lnet_routes(struct ctl_table *table, int write, void __user *buffer,
+		     size_t *lenp, loff_t *ppos)
 {
 	const int	tmpsiz = 256;
 	char		*tmpstr;
@@ -151,8 +174,6 @@ int LL_PROC_PROTO(proc_lnet_routes)
 	int		ver;
 	int		off;
 
-	DECLARE_LL_PROC_PPOS_DECL;
-
 	CLASSERT(sizeof(loff_t) >= 4);
 
 	off = LNET_PROC_HOFF_GET(*ppos);
@@ -268,7 +289,8 @@ int LL_PROC_PROTO(proc_lnet_routes)
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_lnet_routers)
+int proc_lnet_routers(struct ctl_table *table, int write, void __user *buffer,
+		      size_t *lenp, loff_t *ppos)
 {
 	int	rc = 0;
 	char      *tmpstr;
@@ -278,8 +300,6 @@ int LL_PROC_PROTO(proc_lnet_routers)
 	int	ver;
 	int	off;
 
-	DECLARE_LL_PROC_PPOS_DECL;
-
 	off = LNET_PROC_HOFF_GET(*ppos);
 	ver = LNET_PROC_VER_GET(*ppos);
 
@@ -337,8 +357,8 @@ int LL_PROC_PROTO(proc_lnet_routers)
 
 		if (peer != NULL) {
 			lnet_nid_t nid = peer->lp_nid;
-			cfs_time_t now = cfs_time_current();
-			cfs_time_t deadline = peer->lp_ping_deadline;
+			unsigned long now = cfs_time_current();
+			unsigned long deadline = peer->lp_ping_deadline;
 			int nrefs     = peer->lp_refcount;
 			int nrtrrefs  = peer->lp_rtr_refcount;
 			int alive_cnt = peer->lp_alive_count;
@@ -404,7 +424,8 @@ int LL_PROC_PROTO(proc_lnet_routers)
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_lnet_peers)
+int proc_lnet_peers(struct ctl_table *table, int write, void __user *buffer,
+		    size_t *lenp, loff_t *ppos)
 {
 	const int		tmpsiz  = 256;
 	struct lnet_peer_table	*ptable;
@@ -515,8 +536,8 @@ int LL_PROC_PROTO(proc_lnet_peers)
 				aliveness = peer->lp_alive ? "up" : "down";
 
 			if (lnet_peer_aliveness_enabled(peer)) {
-				cfs_time_t     now = cfs_time_current();
-				cfs_duration_t delta;
+				unsigned long     now = cfs_time_current();
+				long delta;
 
 				delta = cfs_time_sub(now, peer->lp_last_alive);
 				lastalive = cfs_duration_sec(delta);
@@ -628,9 +649,15 @@ static int __proc_lnet_buffers(void *dat
 	return rc;
 }
 
-DECLARE_PROC_HANDLER(proc_lnet_buffers);
+static int proc_lnet_buffers(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_lnet_buffers);
+}
 
-int LL_PROC_PROTO(proc_lnet_nis)
+int proc_lnet_nis(struct ctl_table *table, int write, void __user *buffer,
+		  size_t *lenp, loff_t *ppos)
 {
 	int	tmpsiz = 128 * LNET_CPT_NUMBER;
 	int	rc = 0;
@@ -638,8 +665,6 @@ int LL_PROC_PROTO(proc_lnet_nis)
 	char      *s;
 	int	len;
 
-	DECLARE_LL_PROC_PPOS_DECL;
-
 	LASSERT(!write);
 
 	if (*lenp == 0)
@@ -681,7 +706,7 @@ int LL_PROC_PROTO(proc_lnet_nis)
 		if (ni != NULL) {
 			struct lnet_tx_queue	*tq;
 			char	*stat;
-			long	now = cfs_time_current_sec();
+			long	now = get_seconds();
 			int	last_alive = -1;
 			int	i;
 			int	j;
@@ -849,9 +874,16 @@ out:
 	LIBCFS_FREE(buf, buf_len);
 	return rc;
 }
-DECLARE_PROC_HANDLER(proc_lnet_portal_rotor);
 
-static ctl_table_t lnet_table[] = {
+static int proc_lnet_portal_rotor(struct ctl_table *table, int write,
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_lnet_portal_rotor);
+}
+
+static struct ctl_table lnet_table[] = {
 	/*
 	 * NB No .strategy entries have been provided since sysctl(8) prefers
 	 * to go via /proc for portability.
@@ -895,7 +927,7 @@ static ctl_table_t lnet_table[] = {
 	}
 };
 
-static ctl_table_t top_table[] = {
+static struct ctl_table top_table[] = {
 	{
 		.procname = "lnet",
 		.mode     = 0555,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/brw_test.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/brw_test.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/brw_test.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/brw_test.c	2014-09-28 17:29:07.000000000 -0400
@@ -216,7 +216,7 @@ brw_check_page(struct page *pg, int patt
 	LBUG();
 
 bad_data:
-	CERROR("Bad data in page %p: "LPX64", "LPX64" expected\n",
+	CERROR("Bad data in page %p: %#llx, %#llx expected\n",
 		pg, data, magic);
 	return 1;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conctl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conctl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,9 @@
  * Author: Liang Zhen <liangzhen@clusterfs.com>
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/lnetst.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lib-lnet.h"
+#include "../../include/linux/lnet/lnetst.h"
 #include "console.h"
 
 int
@@ -837,7 +837,7 @@ lstcon_ioctl_entry(unsigned int cmd, str
 
 	mutex_lock(&console_session.ses_mutex);
 
-	console_session.ses_laststamp = cfs_time_current_sec();
+	console_session.ses_laststamp = get_seconds();
 
 	if (console_session.ses_shutdown) {
 		rc = -ESHUTDOWN;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conrpc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conrpc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conrpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conrpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,8 @@
  */
 
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lib-lnet.h"
 #include "timer.h"
 #include "conrpc.h"
 #include "console.h"
@@ -477,7 +477,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_
 	lstcon_rpc_t	 *crpc;
 	srpc_msg_t	   *msg;
 	lstcon_node_t	*nd;
-	cfs_duration_t	dur;
+	long	dur;
 	struct timeval	tv;
 	int		   error;
 
@@ -503,8 +503,8 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_
 
 		nd = crpc->crp_node;
 
-		dur = (cfs_duration_t)cfs_time_sub(crpc->crp_stamp,
-		      (cfs_time_t)console_session.ses_id.ses_stamp);
+		dur = (long)cfs_time_sub(crpc->crp_stamp,
+		      (unsigned long)console_session.ses_id.ses_stamp);
 		cfs_duration_usec(dur, &tv);
 
 		if (copy_to_user(&ent->rpe_peer,
@@ -1187,7 +1187,7 @@ lstcon_rpc_pinger(void *arg)
 	}
 
 	if (!console_session.ses_expired &&
-	    cfs_time_current_sec() - console_session.ses_laststamp >
+	    get_seconds() - console_session.ses_laststamp >
 	    (time_t)console_session.ses_timeout)
 		console_session.ses_expired = 1;
 
@@ -1274,7 +1274,7 @@ lstcon_rpc_pinger(void *arg)
 
 	CDEBUG(D_NET, "Ping %d nodes in session\n", count);
 
-	ptimer->stt_expires = (cfs_time_t)(cfs_time_current_sec() + LST_PING_INTERVAL);
+	ptimer->stt_expires = (unsigned long)(get_seconds() + LST_PING_INTERVAL);
 	stt_add_timer(ptimer);
 
 	mutex_unlock(&console_session.ses_mutex);
@@ -1297,7 +1297,7 @@ lstcon_rpc_pinger_start(void)
 	}
 
 	ptimer = &console_session.ses_ping_timer;
-	ptimer->stt_expires = (cfs_time_t)(cfs_time_current_sec() + LST_PING_INTERVAL);
+	ptimer->stt_expires = (unsigned long)(get_seconds() + LST_PING_INTERVAL);
 
 	stt_add_timer(ptimer);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conrpc.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conrpc.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/conrpc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/conrpc.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,10 +43,10 @@
 #ifndef __LST_CONRPC_H__
 #define __LST_CONRPC_H__
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-types.h>
-#include <linux/lnet/lnetst.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lnet.h"
+#include "../../include/linux/lnet/lib-types.h"
+#include "../../include/linux/lnet/lnetst.h"
 #include "rpc.h"
 #include "selftest.h"
 
@@ -75,7 +75,7 @@ typedef struct lstcon_rpc {
 	/** RPC is embedded in other structure and can't free it */
 	unsigned int		 crp_embedded:1;
 	int		      crp_status;     /* console rpc errors */
-	cfs_time_t	       crp_stamp;      /* replied time stamp */
+	unsigned long	       crp_stamp;      /* replied time stamp */
 } lstcon_rpc_t;
 
 typedef struct lstcon_rpc_trans {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/console.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/console.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/console.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/console.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,8 @@
  */
 
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lib-lnet.h"
 #include "console.h"
 #include "conrpc.h"
 
@@ -204,9 +204,6 @@ lstcon_group_alloc(char *name, lstcon_gr
 	if (grp == NULL)
 		return -ENOMEM;
 
-	memset(grp, 0, offsetof(lstcon_group_t,
-				grp_ndl_hash[LST_NODE_HASHSIZE]));
-
 	grp->grp_ref = 1;
 	if (name != NULL)
 		strcpy(grp->grp_name, name);
@@ -815,8 +812,6 @@ lstcon_group_info(char *name, lstcon_ndl
 		return -ENOMEM;
 	}
 
-	memset(gentp, 0, sizeof(lstcon_ndlist_ent_t));
-
 	list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
 		LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
 
@@ -971,8 +966,6 @@ lstcon_batch_info(char *name, lstcon_tes
 	if (entp == NULL)
 		return -ENOMEM;
 
-	memset(entp, 0, sizeof(lstcon_test_batch_ent_t));
-
 	if (test == NULL) {
 		entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
 		entp->u.tbe_batch.bae_state = bat->bat_state;
@@ -1319,7 +1312,6 @@ lstcon_test_add(char *batch_name, int ty
 		goto out;
 	}
 
-	memset(test, 0, offsetof(lstcon_test_t, tes_param[paramlen]));
 	test->tes_hdr.tsb_id	= batch->bat_hdr.tsb_id;
 	test->tes_batch		= batch;
 	test->tes_type		= type;
@@ -1789,8 +1781,6 @@ lstcon_session_info(lst_sid_t *sid_up, i
 	if (entp == NULL)
 		return -ENOMEM;
 
-	memset(entp, 0, sizeof(*entp));
-
 	list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
 		LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
 
@@ -2016,7 +2006,7 @@ lstcon_console_init(void)
 	console_session.ses_expired	    = 0;
 	console_session.ses_feats_updated   = 0;
 	console_session.ses_features	    = LST_FEATS_MASK;
-	console_session.ses_laststamp	    = cfs_time_current_sec();
+	console_session.ses_laststamp	    = get_seconds();
 
 	mutex_init(&console_session.ses_mutex);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/console.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/console.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/console.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/console.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,10 +44,10 @@
 #define __LST_CONSOLE_H__
 
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-types.h>
-#include <linux/lnet/lnetst.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lnet.h"
+#include "../../include/linux/lnet/lib-types.h"
+#include "../../include/linux/lnet/lnetst.h"
 #include "selftest.h"
 #include "conrpc.h"
 
@@ -56,7 +56,7 @@ typedef struct lstcon_node {
 	int		  nd_ref;	 /* reference count */
 	int		  nd_state;       /* state of the node */
 	int		  nd_timeout;     /* session timeout */
-	cfs_time_t	   nd_stamp;       /* timestamp of last replied RPC */
+	unsigned long	   nd_stamp;       /* timestamp of last replied RPC */
 	struct lstcon_rpc    nd_ping;	/* ping rpc */
 } lstcon_node_t;				/*** node descriptor */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/framework.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/framework.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/framework.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/framework.c	2014-09-28 17:29:07.000000000 -0400
@@ -149,7 +149,6 @@ sfw_register_test (srpc_service_t *servi
 	if (tsc == NULL)
 		return -ENOMEM;
 
-	memset(tsc, 0, sizeof(sfw_test_case_t));
 	tsc->tsc_cli_ops     = cliops;
 	tsc->tsc_srv_service = service;
 
@@ -172,7 +171,7 @@ sfw_add_session_timer (void)
 
 	sn->sn_timer_active = 1;
 	timer->stt_expires = cfs_time_add(sn->sn_timeout,
-					  cfs_time_current_sec());
+					  get_seconds());
 	stt_add_timer(timer);
 	return;
 }
@@ -249,7 +248,7 @@ sfw_session_expired (void *data)
 	LASSERT (sn->sn_timer_active);
 	LASSERT (sn == sfw_data.fw_session);
 
-	CWARN ("Session expired! sid: %s-"LPU64", name: %s\n",
+	CWARN ("Session expired! sid: %s-%llu, name: %s\n",
 	       libcfs_nid2str(sn->sn_id.ses_nid),
 	       sn->sn_id.ses_stamp, &sn->sn_name[0]);
 
@@ -742,12 +741,11 @@ sfw_add_test_instance (sfw_batch_t *tsb,
 
 	LIBCFS_ALLOC(tsi, sizeof(*tsi));
 	if (tsi == NULL) {
-		CERROR ("Can't allocate test instance for batch: "LPU64"\n",
+		CERROR ("Can't allocate test instance for batch: %llu\n",
 			tsb->bat_id.bat_id);
 		return -ENOMEM;
 	}
 
-	memset(tsi, 0, sizeof(*tsi));
 	spin_lock_init(&tsi->tsi_lock);
 	atomic_set(&tsi->tsi_nactive, 0);
 	INIT_LIST_HEAD(&tsi->tsi_units);
@@ -1004,7 +1002,7 @@ sfw_run_batch (sfw_batch_t *tsb)
 	sfw_test_instance_t *tsi;
 
 	if (sfw_batch_active(tsb)) {
-		CDEBUG(D_NET, "Batch already active: "LPU64" (%d)\n",
+		CDEBUG(D_NET, "Batch already active: %llu (%d)\n",
 		       tsb->bat_id.bat_id, atomic_read(&tsb->bat_nactive));
 		return 0;
 	}
@@ -1039,7 +1037,7 @@ sfw_stop_batch (sfw_batch_t *tsb, int fo
 	srpc_client_rpc_t   *rpc;
 
 	if (!sfw_batch_active(tsb)) {
-		CDEBUG(D_NET, "Batch "LPU64" inactive\n", tsb->bat_id.bat_id);
+		CDEBUG(D_NET, "Batch %llu inactive\n", tsb->bat_id.bat_id);
 		return 0;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,5 +2,3 @@ obj-$(CONFIG_LNET_SELFTEST) := lnet_self
 
 lnet_selftest-y := console.o conrpc.o conctl.o framework.o timer.o rpc.o \
 		   module.o ping_test.o brw_test.o
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/rpc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/rpc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/rpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/rpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -386,7 +386,7 @@ srpc_post_passive_rdma(int portal, int l
 	}
 
 	CDEBUG (D_NET,
-		"Posted passive RDMA: peer %s, portal %d, matchbits "LPX64"\n",
+		"Posted passive RDMA: peer %s, portal %d, matchbits %#llx\n",
 		libcfs_id2str(peer), portal, matchbits);
 	return 0;
 }
@@ -426,7 +426,7 @@ srpc_post_active_rdma(int portal, __u64
 	}
 
 	if (rc != 0) {
-		CERROR ("LNet%s(%s, %d, "LPD64") failed: %d\n",
+		CERROR ("LNet%s(%s, %d, %lld) failed: %d\n",
 			((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get",
 			libcfs_id2str(peer), portal, matchbits, rc);
 
@@ -437,7 +437,7 @@ srpc_post_active_rdma(int portal, __u64
 		LASSERT (rc == 0);
 	} else {
 		CDEBUG (D_NET,
-			"Posted active RDMA: peer %s, portal %u, matchbits "LPX64"\n",
+			"Posted active RDMA: peer %s, portal %u, matchbits %#llx\n",
 			libcfs_id2str(peer), portal, matchbits);
 	}
 	return 0;
@@ -563,7 +563,7 @@ srpc_add_buffer(struct swi_workitem *wi)
 	}
 
 	if (rc != 0) {
-		scd->scd_buf_err_stamp = cfs_time_current_sec();
+		scd->scd_buf_err_stamp = get_seconds();
 		scd->scd_buf_err = rc;
 
 		LASSERT(scd->scd_buf_posting > 0);
@@ -1098,7 +1098,7 @@ srpc_add_client_rpc_timer (srpc_client_r
 	timer->stt_data    = rpc;
 	timer->stt_func    = srpc_client_rpc_expired;
 	timer->stt_expires = cfs_time_add(rpc->crpc_timeout,
-					  cfs_time_current_sec());
+					  get_seconds());
 	stt_add_timer(timer);
 	return;
 }
@@ -1481,7 +1481,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
 		}
 
 		if (scd->scd_buf_err_stamp != 0 &&
-		    scd->scd_buf_err_stamp < cfs_time_current_sec()) {
+		    scd->scd_buf_err_stamp < get_seconds()) {
 			/* re-enable adding buffer */
 			scd->scd_buf_err_stamp = 0;
 			scd->scd_buf_err = 0;
@@ -1587,7 +1587,7 @@ srpc_startup (void)
 	/* 1 second pause to avoid timestamp reuse */
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(cfs_time_seconds(1));
-	srpc_data.rpc_matchbits = ((__u64) cfs_time_current_sec()) << 48;
+	srpc_data.rpc_matchbits = ((__u64) get_seconds()) << 48;
 
 	srpc_data.rpc_state = SRPC_STATE_NONE;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/rpc.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/rpc.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/rpc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/rpc.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #ifndef __SELFTEST_RPC_H__
 #define __SELFTEST_RPC_H__
 
-#include <linux/lnet/lnetst.h>
+#include "../../include/linux/lnet/lnetst.h"
 
 /*
  * LST wired structures
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/selftest.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/selftest.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/selftest.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/selftest.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,11 +43,11 @@
 
 #define LNET_ONLY
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/lib-types.h>
-#include <linux/lnet/lnetst.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lnet.h"
+#include "../../include/linux/lnet/lib-lnet.h"
+#include "../../include/linux/lnet/lib-types.h"
+#include "../../include/linux/lnet/lnetst.h"
 
 #include "rpc.h"
 #include "timer.h"
@@ -334,7 +334,7 @@ typedef struct {
 	atomic_t      sn_refcount;
 	atomic_t      sn_brw_errors;
 	atomic_t      sn_ping_errors;
-	cfs_time_t	sn_started;
+	unsigned long	sn_started;
 } sfw_session_t;
 
 #define sfw_sid_equal(sid0, sid1)     ((sid0).ses_nid == (sid1).ses_nid && \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/timer.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/timer.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/timer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/timer.c	2014-09-28 17:29:07.000000000 -0400
@@ -60,7 +60,7 @@
 struct st_timer_data {
 	spinlock_t	 stt_lock;
 	/* start time of the slot processed previously */
-	cfs_time_t       stt_prev_slot;
+	unsigned long       stt_prev_slot;
 	struct list_head       stt_hash[STTIMER_NSLOTS];
 	int	      stt_shuttingdown;
 	wait_queue_head_t      stt_waitq;
@@ -78,7 +78,7 @@ stt_add_timer(stt_timer_t *timer)
 	LASSERT(!stt_data.stt_shuttingdown);
 	LASSERT(timer->stt_func != NULL);
 	LASSERT(list_empty(&timer->stt_list));
-	LASSERT(cfs_time_after(timer->stt_expires, cfs_time_current_sec()));
+	LASSERT(cfs_time_after(timer->stt_expires, get_seconds()));
 
 	/* a simple insertion sort */
 	list_for_each_prev(pos, STTIMER_SLOT(timer->stt_expires)) {
@@ -122,7 +122,7 @@ stt_del_timer(stt_timer_t *timer)
 
 /* called with stt_data.stt_lock held */
 int
-stt_expire_list(struct list_head *slot, cfs_time_t now)
+stt_expire_list(struct list_head *slot, unsigned long now)
 {
 	int	  expired = 0;
 	stt_timer_t *timer;
@@ -146,13 +146,13 @@ stt_expire_list(struct list_head *slot,
 }
 
 int
-stt_check_timers(cfs_time_t *last)
+stt_check_timers(unsigned long *last)
 {
 	int	expired = 0;
-	cfs_time_t now;
-	cfs_time_t this_slot;
+	unsigned long now;
+	unsigned long this_slot;
 
-	now = cfs_time_current_sec();
+	now = get_seconds();
 	this_slot = now & STTIMER_SLOTTIMEMASK;
 
 	spin_lock(&stt_data.stt_lock);
@@ -212,7 +212,7 @@ stt_startup(void)
 	int i;
 
 	stt_data.stt_shuttingdown = 0;
-	stt_data.stt_prev_slot = cfs_time_current_sec() & STTIMER_SLOTTIMEMASK;
+	stt_data.stt_prev_slot = get_seconds() & STTIMER_SLOTTIMEMASK;
 
 	spin_lock_init(&stt_data.stt_lock);
 	for (i = 0; i < STTIMER_NSLOTS; i++)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/timer.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/timer.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lnet/selftest/timer.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lnet/selftest/timer.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 
 typedef struct {
 	struct list_head	stt_list;
-	cfs_time_t	stt_expires;
+	unsigned long	stt_expires;
 	void	    (*stt_func) (void *);
 	void	     *stt_data;
 } stt_timer_t;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,16 +40,16 @@
 #ifndef __FID_INTERNAL_H
 #define __FID_INTERNAL_H
 
-#include <lustre/lustre_idl.h>
-#include <linux/libcfs/libcfs.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../../include/linux/libcfs/libcfs.h"
 
 /* Functions used internally in module. */
 int seq_client_alloc_super(struct lu_client_seq *seq,
 			   const struct lu_env *env);
 
-# ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 extern struct lprocfs_vars seq_client_proc_list[];
-# endif
+#endif
 
 extern struct proc_dir_entry *seq_type_proc_dir;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_lib.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_lib.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,10 +43,10 @@
 
 #define DEBUG_SUBSYSTEM S_FID
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/module.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_fid.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_fid.h"
 
 /**
  * A cluster-wide range from which fid-sequences are granted to servers and
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/fid_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/fid_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,15 +42,15 @@
 
 #define DEBUG_SUBSYSTEM S_FID
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/module.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
 /* mdc RPC locks */
-#include <lustre_mdc.h>
+#include "../include/lustre_mdc.h"
 #include "fid_internal.h"
 
 static int seq_client_rpc(struct lu_client_seq *seq,
@@ -197,7 +197,7 @@ static int seq_client_alloc_seq(const st
 		rc = seq_client_alloc_meta(env, seq);
 		if (rc) {
 			CERROR("%s: Can't allocate new meta-sequence, rc %d\n",
-				seq->lcs_name, rc);
+			       seq->lcs_name, rc);
 			return rc;
 		} else {
 			CDEBUG(D_INFO, "%s: New range - "DRANGE"\n",
@@ -211,7 +211,7 @@ static int seq_client_alloc_seq(const st
 	*seqnr = seq->lcs_space.lsr_start;
 	seq->lcs_space.lsr_start += 1;
 
-	CDEBUG(D_INFO, "%s: Allocated sequence ["LPX64"]\n", seq->lcs_name,
+	CDEBUG(D_INFO, "%s: Allocated sequence [%#llx]\n", seq->lcs_name,
 	       *seqnr);
 
 	return rc;
@@ -267,14 +267,14 @@ int seq_client_get_seq(const struct lu_e
 	rc = seq_client_alloc_seq(env, seq, seqnr);
 	if (rc) {
 		CERROR("%s: Can't allocate new sequence, rc %d\n",
-			seq->lcs_name, rc);
+		       seq->lcs_name, rc);
 		seq_fid_alloc_fini(seq);
 		mutex_unlock(&seq->lcs_mutex);
 		return rc;
 	}
 
-	CDEBUG(D_INFO, "%s: allocate sequence [0x%16.16"LPF64"x]\n",
-			seq->lcs_name, *seqnr);
+	CDEBUG(D_INFO, "%s: allocate sequence [0x%16.16Lx]\n",
+	       seq->lcs_name, *seqnr);
 
 	/* Since the caller require the whole seq,
 	 * so marked this seq to be used */
@@ -330,14 +330,14 @@ int seq_client_alloc_fid(const struct lu
 		rc = seq_client_alloc_seq(env, seq, &seqnr);
 		if (rc) {
 			CERROR("%s: Can't allocate new sequence, rc %d\n",
-				seq->lcs_name, rc);
+			       seq->lcs_name, rc);
 			seq_fid_alloc_fini(seq);
 			mutex_unlock(&seq->lcs_mutex);
 			return rc;
 		}
 
-		CDEBUG(D_INFO, "%s: Switch to sequence [0x%16.16"LPF64"x]\n",
-				seq->lcs_name, seqnr);
+		CDEBUG(D_INFO, "%s: Switch to sequence [0x%16.16Lx]\n",
+		       seq->lcs_name, seqnr);
 
 		seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID;
 		seq->lcs_fid.f_seq = seqnr;
@@ -400,18 +400,18 @@ EXPORT_SYMBOL(seq_client_flush);
 
 static void seq_client_proc_fini(struct lu_client_seq *seq)
 {
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	if (seq->lcs_proc_dir) {
 		if (!IS_ERR(seq->lcs_proc_dir))
 			lprocfs_remove(&seq->lcs_proc_dir);
 		seq->lcs_proc_dir = NULL;
 	}
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 }
 
 static int seq_client_proc_init(struct lu_client_seq *seq)
 {
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	int rc;
 
 	seq->lcs_proc_dir = lprocfs_register(seq->lcs_name,
@@ -429,7 +429,7 @@ static int seq_client_proc_init(struct l
 			      seq_client_proc_list, seq);
 	if (rc) {
 		CERROR("%s: Can't init sequence manager proc, rc %d\n",
-			seq->lcs_name, rc);
+		       seq->lcs_name, rc);
 		GOTO(out_cleanup, rc);
 	}
 
@@ -439,7 +439,7 @@ out_cleanup:
 	seq_client_proc_fini(seq);
 	return rc;
 
-#else /* LPROCFS */
+#else /* CONFIG_PROC_FS */
 	return 0;
 #endif
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/lproc_fid.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/lproc_fid.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/lproc_fid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/lproc_fid.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,16 +42,16 @@
 
 #define DEBUG_SUBSYSTEM S_FID
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include <linux/module.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <dt_object.h>
-#include <md_object.h>
-#include <obd_support.h>
-#include <lustre_req_layout.h>
-#include <lustre_fid.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/dt_object.h"
+#include "../include/md_object.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_fid.h"
 #include "fid_internal.h"
 
 /* Format: [0x64BIT_INT - 0x64BIT_INT] + 32 bytes just in case */
@@ -98,9 +98,10 @@ static ssize_t lprocfs_fid_space_seq_wri
 					   const char __user *buffer,
 					   size_t count, loff_t *off)
 {
-	struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
+	struct lu_client_seq *seq;
 	int rc;
 
+	seq = ((struct seq_file *)file->private_data)->private;
 	LASSERT(seq != NULL);
 
 	mutex_lock(&seq->lcs_mutex);
@@ -125,7 +126,7 @@ lprocfs_fid_space_seq_show(struct seq_fi
 	LASSERT(seq != NULL);
 
 	mutex_lock(&seq->lcs_mutex);
-	rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n", PRANGE(&seq->lcs_space));
+	rc = seq_printf(m, "[%#llx - %#llx]:%x:%s\n", PRANGE(&seq->lcs_space));
 	mutex_unlock(&seq->lcs_mutex);
 
 	return rc;
@@ -135,10 +136,11 @@ static ssize_t lprocfs_fid_width_seq_wri
 					   const char __user *buffer,
 					   size_t count, loff_t *off)
 {
-	struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
+	struct lu_client_seq *seq;
 	__u64  max;
 	int rc, val;
 
+	seq = ((struct seq_file *)file->private_data)->private;
 	LASSERT(seq != NULL);
 
 	rc = lprocfs_write_helper(buffer, count, &val);
@@ -155,7 +157,7 @@ static ssize_t lprocfs_fid_width_seq_wri
 		seq->lcs_width = val;
 
 		if (rc == 0) {
-			CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n",
+			CDEBUG(D_INFO, "%s: Sequence size: %llu\n",
 			       seq->lcs_name, seq->lcs_width);
 		}
 	}
@@ -174,7 +176,7 @@ lprocfs_fid_width_seq_show(struct seq_fi
 	LASSERT(seq != NULL);
 
 	mutex_lock(&seq->lcs_mutex);
-	rc = seq_printf(m, LPU64"\n", seq->lcs_width);
+	rc = seq_printf(m, "%llu\n", seq->lcs_width);
 	mutex_unlock(&seq->lcs_mutex);
 
 	return rc;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fid/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fid/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,3 @@
 obj-$(CONFIG_LUSTRE_FS) += fid.o
 fid-y := fid_request.o fid_lib.o
 fid-$(CONFIG_PROC_FS) += lproc_fid.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_cache.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_cache.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,20 +43,20 @@
 
 #define DEBUG_SUBSYSTEM S_FLD
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-# include <asm/div64.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include <linux/module.h>
+#include <asm/div64.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_ver.h>
-#include <obd_support.h>
-#include <lprocfs_status.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_ver.h"
+#include "../include/obd_support.h"
+#include "../include/lprocfs_status.h"
 
-#include <dt_object.h>
-#include <md_object.h>
-#include <lustre_req_layout.h>
-#include <lustre_fld.h>
+#include "../include/dt_object.h"
+#include "../include/md_object.h"
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_fld.h"
 #include "fld_internal.h"
 
 /**
@@ -113,9 +113,9 @@ void fld_cache_fini(struct fld_cache *ca
 	}
 
 	CDEBUG(D_INFO, "FLD cache statistics (%s):\n", cache->fci_name);
-	CDEBUG(D_INFO, "  Total reqs: "LPU64"\n", cache->fci_stat.fst_count);
-	CDEBUG(D_INFO, "  Cache reqs: "LPU64"\n", cache->fci_stat.fst_cache);
-	CDEBUG(D_INFO, "  Cache hits: "LPU64"%%\n", pct);
+	CDEBUG(D_INFO, "  Total reqs: %llu\n", cache->fci_stat.fst_count);
+	CDEBUG(D_INFO, "  Cache reqs: %llu\n", cache->fci_stat.fst_cache);
+	CDEBUG(D_INFO, "  Cache hits: %llu%%\n", pct);
 
 	OBD_FREE_PTR(cache);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,12 +41,12 @@
 #ifndef __FLD_INTERNAL_H
 #define __FLD_INTERNAL_H
 
-#include <lustre/lustre_idl.h>
-#include <dt_object.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/dt_object.h"
 
-#include <linux/libcfs/libcfs.h>
-#include <lustre_req_layout.h>
-#include <lustre_fld.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_fld.h"
 
 enum {
 	LUSTRE_FLD_INIT = 1 << 0,
@@ -142,7 +142,7 @@ extern struct lu_fld_hash fld_hash[];
 int fld_client_rpc(struct obd_export *exp,
 		   struct lu_seq_range *range, __u32 fld_op);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 extern struct lprocfs_vars fld_client_proc_list[];
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/fld_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/fld_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,21 +42,21 @@
 
 #define DEBUG_SUBSYSTEM S_FLD
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
-# include <asm/div64.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include <linux/module.h>
+#include <asm/div64.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_ver.h>
-#include <obd_support.h>
-#include <lprocfs_status.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_ver.h"
+#include "../include/obd_support.h"
+#include "../include/lprocfs_status.h"
 
-#include <dt_object.h>
-#include <md_object.h>
-#include <lustre_req_layout.h>
-#include <lustre_fld.h>
-#include <lustre_mdc.h>
+#include "../include/dt_object.h"
+#include "../include/md_object.h"
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_fld.h"
+#include "../include/lustre_mdc.h"
 #include "fld_internal.h"
 
 /* TODO: these 3 functions are copies of flow-control code from mdc_lib.c
@@ -138,7 +138,7 @@ fld_rrb_scan(struct lu_client_fld *fld,
 			return target;
 	}
 
-	CERROR("%s: Can't find target by hash %d (seq "LPX64"). Targets (%d):\n",
+	CERROR("%s: Can't find target by hash %d (seq %#llx). Targets (%d):\n",
 		fld->lcf_name, hash, seq, fld->lcf_count);
 
 	list_for_each_entry(target, &fld->lcf_targets, ft_chain) {
@@ -148,7 +148,7 @@ fld_rrb_scan(struct lu_client_fld *fld,
 			(char *)target->ft_exp->exp_obd->obd_uuid.uuid :
 			"<null>";
 
-		CERROR("  exp: 0x%p (%s), srv: 0x%p (%s), idx: "LPU64"\n",
+		CERROR("  exp: 0x%p (%s), srv: 0x%p (%s), idx: %llu\n",
 		       target->ft_exp, exp_name, target->ft_srv,
 		       srv_name, target->ft_idx);
 	}
@@ -168,7 +168,7 @@ struct lu_fld_hash fld_hash[] = {
 		.fh_scan_func = fld_rrb_scan
 	},
 	{
-		0,
+		NULL,
 	}
 };
 
@@ -184,9 +184,8 @@ fld_client_get_target(struct lu_client_f
 	spin_unlock(&fld->lcf_lock);
 
 	if (target != NULL) {
-		CDEBUG(D_INFO, "%s: Found target (idx "LPU64
-		       ") by seq "LPX64"\n", fld->lcf_name,
-		       target->ft_idx, seq);
+		CDEBUG(D_INFO, "%s: Found target (idx %llu) by seq %#llx\n",
+		       fld->lcf_name, target->ft_idx, seq);
 	}
 
 	return target;
@@ -208,12 +207,12 @@ int fld_client_add_target(struct lu_clie
 	LASSERT(tar->ft_srv != NULL || tar->ft_exp != NULL);
 
 	if (fld->lcf_flags != LUSTRE_FLD_INIT) {
-		CERROR("%s: Attempt to add target %s (idx "LPU64") on fly - skip it\n",
+		CERROR("%s: Attempt to add target %s (idx %llu) on fly - skip it\n",
 			fld->lcf_name, name, tar->ft_idx);
 		return 0;
 	} else {
-		CDEBUG(D_INFO, "%s: Adding target %s (idx "
-		       LPU64")\n", fld->lcf_name, name, tar->ft_idx);
+		CDEBUG(D_INFO, "%s: Adding target %s (idx %llu)\n",
+		       fld->lcf_name, name, tar->ft_idx);
 	}
 
 	OBD_ALLOC_PTR(target);
@@ -225,7 +224,7 @@ int fld_client_add_target(struct lu_clie
 		if (tmp->ft_idx == tar->ft_idx) {
 			spin_unlock(&fld->lcf_lock);
 			OBD_FREE_PTR(target);
-			CERROR("Target %s exists in FLD and known as %s:#"LPU64"\n",
+			CERROR("Target %s exists in FLD and known as %s:#%llu\n",
 			       name, fld_target_name(tmp), tmp->ft_idx);
 			return -EEXIST;
 		}
@@ -274,7 +273,7 @@ EXPORT_SYMBOL(fld_client_del_target);
 
 struct proc_dir_entry *fld_type_proc_dir = NULL;
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 static int fld_client_proc_init(struct lu_client_fld *fld)
 {
 	int rc;
@@ -324,7 +323,6 @@ void fld_client_proc_fini(struct lu_clie
 	return;
 }
 #endif
-
 EXPORT_SYMBOL(fld_client_proc_fini);
 
 static inline int hash_is_sane(int hash)
@@ -474,7 +472,7 @@ int fld_client_lookup(struct lu_client_f
 	target = fld_client_get_target(fld, seq);
 	LASSERT(target != NULL);
 
-	CDEBUG(D_INFO, "%s: Lookup fld entry (seq: "LPX64") on target %s (idx "LPU64")\n",
+	CDEBUG(D_INFO, "%s: Lookup fld entry (seq: %#llx) on target %s (idx %llu)\n",
 			fld->lcf_name, seq, fld_target_name(target), target->ft_idx);
 
 	res.lsr_start = seq;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/lproc_fld.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/lproc_fld.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/lproc_fld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/lproc_fld.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,17 +43,17 @@
 
 #define DEBUG_SUBSYSTEM S_FLD
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/module.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include <linux/module.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <dt_object.h>
-#include <md_object.h>
-#include <obd_support.h>
-#include <lustre_req_layout.h>
-#include <lustre_fld.h>
-#include <lustre_fid.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/dt_object.h"
+#include "../include/md_object.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_fld.h"
+#include "../include/lustre_fid.h"
 #include "fld_internal.h"
 
 static int
@@ -91,10 +91,11 @@ static ssize_t
 fld_proc_hash_seq_write(struct file *file, const char *buffer,
 			size_t count, loff_t *off)
 {
-	struct lu_client_fld *fld = ((struct seq_file *)file->private_data)->private;
+	struct lu_client_fld *fld;
 	struct lu_fld_hash *hash = NULL;
 	int i;
 
+	fld = ((struct seq_file *)file->private_data)->private;
 	LASSERT(fld != NULL);
 
 	for (i = 0; fld_hash[i].fh_name != NULL; i++) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/fld/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/fld/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,3 @@
 obj-$(CONFIG_LUSTRE_FS) += fld.o
 fld-y := fld_request.o fld_cache.o
 fld-$(CONFIG_PROC_FS) += lproc_fld.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/cl_object.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/cl_object.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/cl_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/cl_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,10 +97,10 @@
 /*
  * super-class definitions.
  */
-#include <lu_object.h>
-#include <lvfs.h>
-#	include <linux/mutex.h>
-#	include <linux/radix-tree.h>
+#include "lu_object.h"
+#include "lvfs.h"
+#include <linux/mutex.h>
+#include <linux/radix-tree.h>
 
 struct inode;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/dt_object.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/dt_object.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/dt_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/dt_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -53,9 +53,9 @@
 /*
  * super-class definitions.
  */
-#include <lu_object.h>
+#include "lu_object.h"
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 struct seq_file;
 struct proc_dir_entry;
@@ -1481,7 +1481,7 @@ static inline struct dt_thread_info *dt_
 int dt_global_init(void);
 void dt_global_fini(void);
 
-# ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int lprocfs_dt_rd_blksize(char *page, char **start, off_t off,
 			  int count, int *eof, void *data);
 int lprocfs_dt_rd_kbytestotal(char *page, char **start, off_t off,
@@ -1494,6 +1494,6 @@ int lprocfs_dt_rd_filestotal(char *page,
 			     int count, int *eof, void *data);
 int lprocfs_dt_rd_filesfree(char *page, char **start, off_t off,
 			    int count, int *eof, void *data);
-# endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 #endif /* __LUSTRE_DT_OBJECT_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/interval_tree.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/interval_tree.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/interval_tree.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/interval_tree.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 #ifndef _INTERVAL_H__
 #define _INTERVAL_H__
 
-#include <linux/libcfs/libcfs.h>   /* LASSERT. */
+#include "../../include/linux/libcfs/libcfs.h"	/* LASSERT. */
 
 struct interval_node {
 	struct interval_node   *in_left;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,7 +50,7 @@
 #include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/rwsem.h>
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 #include <linux/statfs.h>
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_acl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_acl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_acl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_acl.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@
 	(sizeof(posix_acl_xattr_header) +				\
 	 LUSTRE_POSIX_ACL_MAX_ENTRIES * sizeof(posix_acl_xattr_entry))
 
-#include <linux/lustre_intent.h>
+#include "lustre_intent.h"
 #include <linux/xattr.h> /* XATTR_{REPLACE,CREATE} */
 
 #ifndef LUSTRE_POSIX_ACL_MAX_SIZE
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,9 +39,9 @@
 
 #include <linux/fs_struct.h>
 #include <linux/namei.h>
-#include <linux/libcfs/linux/portals_compat25.h>
+#include "../../../include/linux/libcfs/linux/portals_compat25.h"
 
-#include <linux/lustre_patchless_compat.h>
+#include "lustre_patchless_compat.h"
 
 # define LOCK_FS_STRUCT(fs)	spin_lock(&(fs)->lock)
 # define UNLOCK_FS_STRUCT(fs)	spin_unlock(&(fs)->lock)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@
 #endif
 
 
-#include <obd.h>
-#include <obd_class.h>
+#include "../obd.h"
+#include "../obd_class.h"
 
 typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd,
 			    void *data, int error);
@@ -90,12 +90,12 @@ static inline char *fsfilt_get_label(str
 
 #define __fsfilt_check_slow(obd, start, msg)			      \
 do {								      \
-	if (cfs_time_before(jiffies, start + 15 * HZ))		\
+	if (time_before(jiffies, start + 15 * HZ))		\
 		break;						    \
-	else if (cfs_time_before(jiffies, start + 30 * HZ))	   \
+	else if (time_before(jiffies, start + 30 * HZ))	   \
 		CDEBUG(D_VFSTRACE, "%s: slow %s %lus\n", obd->obd_name,   \
 		       msg, (jiffies-start) / HZ);		    \
-	else if (cfs_time_before(jiffies, start + DISK_TIMEOUT * HZ)) \
+	else if (time_before(jiffies, start + DISK_TIMEOUT * HZ)) \
 		CWARN("%s: slow %s %lus\n", obd->obd_name, msg,	   \
 		      (jiffies - start) / HZ);			\
 	else							      \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lib.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lib.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lib.h	2014-09-28 17:29:07.000000000 -0400
@@ -49,8 +49,8 @@
 # include <linux/sched.h>
 # include <linux/signal.h>
 # include <linux/types.h>
-# include <linux/lustre_compat25.h>
-# include <linux/lustre_common.h>
+#include "lustre_compat25.h"
+#include "lustre_common.h"
 
 #ifndef LP_POISON
 # define LI_POISON 0x5a5a5a5a
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lite.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lite.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lite.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lustre_lite.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,13 +46,13 @@
 #include <linux/dcache.h>
 #include <linux/proc_fs.h>
 
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_ha.h>
+#include "../obd_class.h"
+#include "../lustre_net.h"
+#include "../lustre_ha.h"
 
 #include <linux/rbtree.h>
-#include <linux/lustre_compat25.h>
-#include <linux/lustre_common.h>
+#include "../../include/linux/lustre_compat25.h"
+#include "../../include/linux/lustre_common.h"
 #include <linux/pagemap.h>
 
 /* lprocfs.c */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lvfs.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lvfs.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lvfs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lvfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -45,9 +45,9 @@
 #error Do not #include this file directly. #include <lvfs.h> instead
 #endif
 
-#include <linux/lustre_compat25.h>
-#include <linux/lustre_common.h>
-#include <linux/lvfs_linux.h>
+#include "lustre_compat25.h"
+#include "lustre_common.h"
+#include "lvfs_linux.h"
 
 #define LLOG_LVFS
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lvfs_linux.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lvfs_linux.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/lvfs_linux.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/lvfs_linux.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,15 +41,10 @@
 #include <linux/namei.h>
 #include <linux/sched.h>
 
-#include <lvfs.h>
-
-#define l_file file
-#define l_dentry dentry
-
-#define l_filp_open filp_open
+#include "../lvfs.h"
 
 struct lvfs_run_ctxt;
-struct l_file *l_dentry_open(struct lvfs_run_ctxt *, struct l_dentry *,
+struct file *l_dentry_open(struct lvfs_run_ctxt *, struct dentry *,
 			     int flags);
 
 struct l_linux_dirent {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/obd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/obd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/obd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/obd.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,14 +41,14 @@
 #error Do not #include this file directly. #include <obd.h> instead
 #endif
 
-#include <obd_support.h>
+#include "../obd_support.h"
 
 # include <linux/fs.h>
 # include <linux/list.h>
 # include <linux/sched.h>  /* for struct task_struct, for current.h */
 # include <linux/proc_fs.h>
 # include <linux/mount.h>
-# include <linux/lustre_intent.h>
+#include "lustre_intent.h"
 
 struct ll_iattr {
 	struct iattr	iattr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/obd_support.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/obd_support.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/linux/obd_support.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/linux/obd_support.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,14 +50,14 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
-#include <linux/lustre_compat25.h>
-#include <linux/lustre_common.h>
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
+#include "../../include/linux/lustre_compat25.h"
+#include "lustre_common.h"
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../lustre/lustre_idl.h"
 
 
 # include <linux/types.h>
 # include <linux/blkdev.h>
-# include <lvfs.h>
+# include "../lvfs.h"
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lprocfs_status.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lprocfs_status.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lprocfs_status.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lprocfs_status.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,8 @@
 #ifndef _LPROCFS_SNMP_H
 #define _LPROCFS_SNMP_H
 
-#include <linux/lprocfs_status.h>
-#include <lustre/lustre_idl.h>
-#include <linux/libcfs/params_tree.h>
+#include "linux/lprocfs_status.h"
+#include "lustre/lustre_idl.h"
 
 struct lprocfs_vars {
 	const char		*name;
@@ -375,7 +374,7 @@ extern int lprocfs_write_frac_helper(con
 				     int *val, int mult);
 extern int lprocfs_read_frac_helper(char *buffer, unsigned long count,
 				    long val, int mult);
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 
 extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats,
 				   unsigned int cpuid);
@@ -605,7 +604,7 @@ extern int lprocfs_obd_seq_create(struct
 
 extern int lprocfs_rd_u64(struct seq_file *m, void *data);
 extern int lprocfs_rd_atomic(struct seq_file *m, void *data);
-extern int lprocfs_wr_atomic(struct file *file, const char *buffer,
+extern int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
 			     unsigned long count, void *data);
 extern int lprocfs_rd_uint(struct seq_file *m, void *data);
 extern int lprocfs_wr_uint(struct file *file, const char *buffer,
@@ -662,8 +661,8 @@ unsigned long lprocfs_oh_sum(struct obd_
 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
 			   struct lprocfs_counter *cnt);
 
-extern int lprocfs_single_release(cfs_inode_t *, struct file *);
-extern int lprocfs_seq_release(cfs_inode_t *, struct file *);
+extern int lprocfs_single_release(struct inode *, struct file *);
+extern int lprocfs_seq_release(struct inode *, struct file *);
 
 /* You must use these macros when you want to refer to
  * the import in a client obd_device for a lprocfs entry */
@@ -684,7 +683,7 @@ extern int lprocfs_seq_release(cfs_inode
   a read-write proc entry, and then call LPROC_SEQ_SEQ instead. Finally,
   call lprocfs_obd_seq_create(obd, filename, 0444, &name#_fops, data); */
 #define __LPROC_SEQ_FOPS(name, custom_seq_write)			\
-static int name##_single_open(cfs_inode_t *inode, struct file *file)	\
+static int name##_single_open(struct inode *inode, struct file *file)	\
 {									\
 	return single_open(file, name##_seq_show, PDE_DATA(inode));	\
 }									\
@@ -727,7 +726,7 @@ static struct file_operations name##_fop
 	{								\
 		return lprocfs_wr_##type(file, buffer, count, off);	\
 	}								\
-	static int name##_##type##_open(cfs_inode_t *inode, struct file *file) \
+	static int name##_##type##_open(struct inode *inode, struct file *file) \
 	{								\
 		return single_open(file, NULL, PDE_DATA(inode));	\
 	}								\
@@ -806,7 +805,7 @@ extern int lprocfs_quota_wr_qs_factor(st
 				      const char *buffer,
 				      unsigned long count, void *data);
 #else
-/* LPROCFS is not defined */
+/* CONFIG_PROC_FS is not defined */
 
 #define proc_lustre_root NULL
 
@@ -1000,6 +999,6 @@ __u64 lprocfs_stats_collector(struct lpr
 /* lproc_ptlrpc.c */
 #define target_print_req NULL
 
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 #endif /* LPROCFS_SNMP_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lu_object.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lu_object.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lu_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lu_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -38,9 +38,9 @@
 #define __LUSTRE_LU_OBJECT_H
 
 #include <stdarg.h>
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
-#include <lu_ref.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lustre/lustre_idl.h"
+#include "lu_ref.h"
 
 struct seq_file;
 struct proc_dir_entry;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h	2014-09-28 17:29:07.000000000 -0400
@@ -91,14 +91,11 @@
 #ifndef _LUSTRE_IDL_H_
 #define _LUSTRE_IDL_H_
 
-#if !defined(LPU64)
-#include <linux/libcfs/libcfs.h> /* for LPUX64, etc */
-#endif
+#include "../../../include/linux/libcfs/libcfs.h"
 
 /* Defn's shared with user-space. */
-#include <lustre/lustre_user.h>
-
-#include <lustre/lustre_errno.h>
+#include "lustre_user.h"
+#include "lustre_errno.h"
 
 /*
  *  GENERAL STUFF
@@ -302,7 +299,7 @@ static inline int range_compare_loc(cons
 	       r1->lsr_flags != r2->lsr_flags;
 }
 
-#define DRANGE "[%#16.16"LPF64"x-%#16.16"LPF64"x):%x:%s"
+#define DRANGE "[%#16.16Lx-%#16.16Lx):%x:%s"
 
 #define PRANGE(range)		\
 	(range)->lsr_start,	\
@@ -682,14 +679,14 @@ static inline void ostid_set_id(struct o
 {
 	if (fid_seq_is_mdt0(ostid_seq(oi))) {
 		if (oid >= IDIF_MAX_OID) {
-			CERROR("Bad "LPU64" to set "DOSTID"\n",
+			CERROR("Bad %llu to set "DOSTID"\n",
 				oid, POSTID(oi));
 			return;
 		}
 		oi->oi.oi_id = oid;
 	} else {
 		if (oid > OBIF_MAX_OID) {
-			CERROR("Bad "LPU64" to set "DOSTID"\n",
+			CERROR("Bad %llu to set "DOSTID"\n",
 				oid, POSTID(oi));
 			return;
 		}
@@ -2748,7 +2745,7 @@ struct ldlm_res_id {
 	__u64 name[RES_NAME_SIZE];
 };
 
-#define DLDLMRES	"["LPX64":"LPX64":"LPX64"]."LPX64i
+#define DLDLMRES	"[%#llx:%#llx:%#llx].%llx"
 #define PLDLMRES(res)	(res)->lr_name.name[0], (res)->lr_name.name[1], \
 			(res)->lr_name.name[2], (res)->lr_name.name[3]
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_user.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_user.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre/lustre_user.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,8 +46,8 @@
  * @{
  */
 
-#include <lustre/ll_fiemap.h>
-#include <linux/lustre_user.h>
+#include "ll_fiemap.h"
+#include "../linux/lustre_user.h"
 
 /* for statfs() */
 #define LL_SUPER_MAGIC 0x0BD00BD0
@@ -179,7 +179,7 @@ struct ost_id {
 	};
 };
 
-#define DOSTID LPX64":"LPU64
+#define DOSTID "%#llx:%llu"
 #define POSTID(oi) ostid_seq(oi), ostid_id(oi)
 
 /*
@@ -475,7 +475,7 @@ static inline void obd_uuid2fsname(char
    e.g. printf("file FID is "DFID"\n", PFID(fid)); */
 #define FID_NOBRACE_LEN 40
 #define FID_LEN (FID_NOBRACE_LEN + 2)
-#define DFID_NOBRACE LPX64":0x%x:0x%x"
+#define DFID_NOBRACE "%#llx:0x%x:0x%x"
 #define DFID "["DFID_NOBRACE"]"
 #define PFID(fid)     \
 	(fid)->f_seq, \
@@ -484,11 +484,7 @@ static inline void obd_uuid2fsname(char
 
 /* scanf input parse format -- strip '[' first.
    e.g. sscanf(fidstr, SFID, RFID(&fid)); */
-/* #define SFID "0x"LPX64i":0x"LPSZX":0x"LPSZX""
-liblustreapi.c:2893: warning: format '%lx' expects type 'long unsigned int *', but argument 4 has type 'unsigned int *'
-liblustreapi.c:2893: warning: format '%lx' expects type 'long unsigned int *', but argument 5 has type 'unsigned int *'
-*/
-#define SFID "0x"LPX64i":0x%x:0x%x"
+#define SFID "0x%llx:0x%x:0x%x"
 #define RFID(fid)     \
 	&((fid)->f_seq), \
 	&((fid)->f_oid), \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_acl.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_acl.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_acl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_acl.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,6 +37,6 @@
 #ifndef _LUSTRE_ACL_H
 #define _LUSTRE_ACL_H
 
-#include <linux/lustre_acl.h>
+#include "linux/lustre_acl.h"
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_capa.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_capa.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_capa.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_capa.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,7 +50,7 @@
  * capability
  */
 #include <linux/crypto.h>
-#include <lustre/lustre_idl.h>
+#include "lustre/lustre_idl.h"
 
 #define CAPA_TIMEOUT 1800		/* sec, == 30 min */
 #define CAPA_KEY_TIMEOUT (24 * 60 * 60)  /* sec, == 1 days */
@@ -82,7 +82,7 @@ struct obd_capa {
 
 	struct lustre_capa	c_capa;       /* capa */
 	atomic_t	      c_refc;       /* ref count */
-	cfs_time_t		c_expiry;     /* jiffies */
+	unsigned long		c_expiry;     /* jiffies */
 	spinlock_t		c_lock;	/* protect capa content */
 	int			c_site;
 
@@ -167,7 +167,7 @@ do {									   \
 
 #define DEBUG_CAPA_KEY(level, k, fmt, args...)				 \
 do {									   \
-CDEBUG(level, fmt " capability key@%p seq "LPU64" keyid %u\n",		 \
+CDEBUG(level, fmt " capability key@%p seq %llu keyid %u\n",		 \
        ##args, k, capa_key_seq(k), capa_key_keyid(k));			 \
 } while (0)
 
@@ -266,20 +266,20 @@ static inline __u64 capa_open_opc(int mo
 
 static inline void set_capa_expiry(struct obd_capa *ocapa)
 {
-	cfs_time_t expiry = cfs_time_sub((cfs_time_t)ocapa->c_capa.lc_expiry,
-					 cfs_time_current_sec());
+	unsigned long expiry = cfs_time_sub((unsigned long)ocapa->c_capa.lc_expiry,
+					 get_seconds());
 	ocapa->c_expiry = cfs_time_add(cfs_time_current(),
 				       cfs_time_seconds(expiry));
 }
 
 static inline int capa_is_expired_sec(struct lustre_capa *capa)
 {
-	return (capa->lc_expiry - cfs_time_current_sec() <= 0);
+	return (capa->lc_expiry - get_seconds() <= 0);
 }
 
 static inline int capa_is_expired(struct obd_capa *ocapa)
 {
-	return cfs_time_beforeq(ocapa->c_expiry, cfs_time_current());
+	return time_before_eq(ocapa->c_expiry, cfs_time_current());
 }
 
 static inline int capa_opc_supported(struct lustre_capa *capa, __u64 opc)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_cfg.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_cfg.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_cfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_cfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -222,7 +222,7 @@ static inline int lustre_cfg_len(__u32 b
 }
 
 
-#include <obd_support.h>
+#include "obd_support.h"
 
 static inline struct lustre_cfg *lustre_cfg_new(int cmd,
 						struct lustre_cfg_bufs *bufs)
@@ -286,7 +286,7 @@ static inline int lustre_cfg_sanity_chec
 	return 0;
 }
 
-#include <lustre/lustre_user.h>
+#include "lustre/lustre_user.h"
 
 /** @} cfg */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_debug.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_debug.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_debug.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_debug.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,8 @@
  * @{
  */
 
-#include <lustre_net.h>
-#include <obd.h>
+#include "lustre_net.h"
+#include "obd.h"
 
 /* lib/debug.c */
 void dump_lniobuf(struct niobuf_local *lnb);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_disk.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_disk.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_disk.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_disk.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,8 +48,8 @@
  * @{
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/types.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/types.h"
 #include <linux/backing-dev.h>
 
 /****************** on-disk files *********************/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_dlm.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_dlm.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_dlm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_dlm.h	2014-09-28 17:29:07.000000000 -0400
@@ -48,14 +48,14 @@
 #ifndef _LUSTRE_DLM_H__
 #define _LUSTRE_DLM_H__
 
-#include <linux/lustre_dlm.h>
+#include "linux/lustre_dlm.h"
 
-#include <lustre_lib.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_handles.h>
-#include <interval_tree.h> /* for interval_node{}, ldlm_extent */
-#include <lu_ref.h>
+#include "lustre_lib.h"
+#include "lustre_net.h"
+#include "lustre_import.h"
+#include "lustre_handles.h"
+#include "interval_tree.h"	/* for interval_node{}, ldlm_extent */
+#include "lu_ref.h"
 
 #include "lustre_dlm_flags.h"
 
@@ -441,7 +441,7 @@ struct ldlm_namespace {
 	 * \see ldlm_namespace_dump. Increased by 10 seconds every time
 	 * it is called.
 	 */
-	cfs_time_t		ns_next_dump;
+	unsigned long		ns_next_dump;
 
 	/** "policy" function that does actual lock conflict determination */
 	ldlm_res_policy		ns_policy;
@@ -783,13 +783,13 @@ struct ldlm_lock {
 	 * Seconds. It will be updated if there is any activity related to
 	 * the lock, e.g. enqueue the lock or send blocking AST.
 	 */
-	cfs_time_t		l_last_activity;
+	unsigned long		l_last_activity;
 
 	/**
 	 * Time last used by e.g. being matched by lock match.
 	 * Jiffies. Should be converted to time if needed.
 	 */
-	cfs_time_t		l_last_used;
+	unsigned long		l_last_used;
 
 	/** Originally requested extent for the extent lock. */
 	struct ldlm_extent	l_req_extent;
@@ -837,7 +837,7 @@ struct ldlm_lock {
 	 * under this lock.
 	 * \see ost_rw_prolong_locks
 	 */
-	cfs_time_t		l_callback_timeout;
+	unsigned long		l_callback_timeout;
 
 	/** Local PID of process which created this lock. */
 	__u32			l_pid;
@@ -951,7 +951,7 @@ struct ldlm_resource {
 	void			*lr_lvb_data;
 
 	/** When the resource was considered as contended. */
-	cfs_time_t		lr_contention_time;
+	unsigned long		lr_contention_time;
 	/** List of references to this resource. For debugging. */
 	struct lu_ref		lr_reference;
 
@@ -1285,7 +1285,7 @@ void ldlm_namespace_register(struct ldlm
 void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client);
 void ldlm_namespace_get(struct ldlm_namespace *ns);
 void ldlm_namespace_put(struct ldlm_namespace *ns);
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int ldlm_proc_setup(void);
 void ldlm_proc_cleanup(void);
 #else
@@ -1390,7 +1390,7 @@ int ldlm_cli_cancel_req(struct obd_expor
 int ldlm_cancel_resource_local(struct ldlm_resource *res,
 			       struct list_head *cancels,
 			       ldlm_policy_data_t *policy,
-			       ldlm_mode_t mode, int lock_flags,
+			       ldlm_mode_t mode, __u64 lock_flags,
 			       ldlm_cancel_flags_t cancel_flags, void *opaque);
 int ldlm_cli_cancel_list_local(struct list_head *cancels, int count,
 			       ldlm_cancel_flags_t flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_export.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_export.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_export.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_export.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,9 +46,9 @@
  * @{
  */
 
-#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_dlm.h>
+#include "lprocfs_status.h"
+#include "lustre/lustre_idl.h"
+#include "lustre_dlm.h"
 
 struct mds_client_data;
 struct mdt_client_data;
@@ -209,7 +209,7 @@ struct obd_export {
 	/** Last committed transno for this export */
 	__u64		     exp_last_committed;
 	/** When was last request received */
-	cfs_time_t		exp_last_request_time;
+	unsigned long		exp_last_request_time;
 	/** On replay all requests waiting for replay are linked here */
 	struct list_head		exp_req_replay_queue;
 	/**
@@ -245,7 +245,7 @@ struct obd_export {
 	enum lustre_sec_part      exp_sp_peer;
 	struct sptlrpc_flavor     exp_flvr;	     /* current */
 	struct sptlrpc_flavor     exp_flvr_old[2];      /* about-to-expire */
-	cfs_time_t		exp_flvr_expire[2];   /* seconds */
+	unsigned long		exp_flvr_expire[2];   /* seconds */
 
 	/** protects exp_hp_rpcs */
 	spinlock_t		  exp_rpc_lock;
@@ -294,11 +294,11 @@ static inline int exp_connect_multibulk(
 	return exp_max_brw_size(exp) > ONE_MB_BRW_SIZE;
 }
 
-static inline int exp_expired(struct obd_export *exp, cfs_duration_t age)
+static inline int exp_expired(struct obd_export *exp, long age)
 {
 	LASSERT(exp->exp_delayed);
-	return cfs_time_before(cfs_time_add(exp->exp_last_request_time, age),
-			       cfs_time_current_sec());
+	return time_before(cfs_time_add(exp->exp_last_request_time, age),
+			   get_seconds());
 }
 
 static inline int exp_connect_cancelset(struct obd_export *exp)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fid.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fid.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fid.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fid.h	2014-09-28 17:29:07.000000000 -0400
@@ -152,8 +152,8 @@
  *  Even so, the MDT and OST resources are also in different LDLM namespaces.
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lustre/lustre_idl.h"
 
 struct lu_env;
 struct lu_site;
@@ -312,7 +312,7 @@ static inline void lu_last_id_fid(struct
 		fid->f_seq = fid_idif_seq(0, 0);
 	} else {
 		LASSERTF(fid_seq_is_norm(seq) || fid_seq_is_echo(seq) ||
-			 fid_seq_is_idif(seq), LPX64"\n", seq);
+			 fid_seq_is_idif(seq), "%#llx\n", seq);
 		fid->f_seq = seq;
 	}
 	fid->f_oid = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fld.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fld.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fld.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fld.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,8 @@
  * @{
  */
 
-#include <lustre/lustre_idl.h>
-#include <linux/libcfs/libcfs.h>
+#include "lustre/lustre_idl.h"
+#include "../../include/linux/libcfs/libcfs.h"
 
 struct lu_client_fld;
 struct lu_server_fld;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fsfilt.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fsfilt.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_fsfilt.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_fsfilt.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 #ifndef _LUSTRE_FSFILT_H
 #define _LUSTRE_FSFILT_H
 
-#include <linux/lustre_fsfilt.h>
+#include "../include/linux/lustre_fsfilt.h"
 
 #define LU221_BAD_TIME (0x80000000U + 24 * 3600)
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_handles.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_handles.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_handles.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_handles.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,9 @@
  * @{
  */
 
-#include <linux/lustre_handles.h>
+#include "linux/lustre_handles.h"
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 
 struct portals_handle_ops {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_idmap.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_idmap.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_idmap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_idmap.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,7 +47,7 @@
  * @{
  */
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 #define CFS_NGROUPS_PER_BLOCK   ((int)(PAGE_CACHE_SIZE / sizeof(gid_t)))
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_import.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_import.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_import.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_import.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,8 +47,8 @@
  * @{
  */
 
-#include <lustre_handles.h>
-#include <lustre/lustre_idl.h>
+#include "lustre_handles.h"
+#include "lustre/lustre_idl.h"
 
 
 /**
@@ -200,7 +200,7 @@ struct obd_import {
 	 */
 	struct ptlrpc_sec	*imp_sec;
 	struct mutex		  imp_sec_mutex;
-	cfs_time_t		imp_sec_expire;
+	unsigned long		imp_sec_expire;
 	/** @} */
 
 	/** Wait queue for those who need to wait for recovery completion */
@@ -247,7 +247,7 @@ struct obd_import {
 	 */
 	struct lustre_handle      imp_remote_handle;
 	/** When to perform next ping. time in jiffies. */
-	cfs_time_t		imp_next_ping;
+	unsigned long		imp_next_ping;
 	/** When we last successfully connected. time in 64bit jiffies */
 	__u64		     imp_last_success_conn;
 
@@ -350,7 +350,7 @@ static inline void at_reset(struct adapt
 	spin_lock(&at->at_lock);
 	at->at_current = val;
 	at->at_worst_ever = val;
-	at->at_worst_time = cfs_time_current_sec();
+	at->at_worst_time = get_seconds();
 	spin_unlock(&at->at_lock);
 }
 static inline void at_init(struct adaptive_timeout *at, int val, int flags) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_lib.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_lib.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_lib.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_lib.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,20 +46,20 @@
  * @{
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_ver.h>
-#include <lustre_cfg.h>
-#include <linux/lustre_lib.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lustre/lustre_idl.h"
+#include "lustre_ver.h"
+#include "lustre_cfg.h"
+#include "linux/lustre_lib.h"
 
 /* target.c */
 struct ptlrpc_request;
 struct obd_export;
 struct lu_target;
 struct l_wait_info;
-#include <lustre_ha.h>
-#include <lustre_net.h>
-#include <lvfs.h>
+#include "lustre_ha.h"
+#include "lustre_net.h"
+#include "lvfs.h"
 
 
 int target_pack_pool_reply(struct ptlrpc_request *req);
@@ -241,7 +241,7 @@ static inline int obd_ioctl_is_invalid(s
 }
 
 
-#include <obd_support.h>
+#include "obd_support.h"
 
 /* function defined in lustre/obdclass/<platform>/<platform>-module.c */
 int obd_ioctl_getdata(char **buf, int *len, void *arg);
@@ -459,8 +459,8 @@ static inline int back_to_sleep(void *ar
 #define LWI_ON_SIGNAL_NOOP ((void (*)(void *))(-1))
 
 struct l_wait_info {
-	cfs_duration_t lwi_timeout;
-	cfs_duration_t lwi_interval;
+	long lwi_timeout;
+	long lwi_interval;
 	int	    lwi_allow_intr;
 	int  (*lwi_on_timeout)(void *);
 	void (*lwi_on_signal)(void *);
@@ -516,7 +516,7 @@ struct l_wait_info {
 #define __l_wait_event(wq, condition, info, ret, l_add_wait)		   \
 do {									   \
 	wait_queue_t __wait;						 \
-	cfs_duration_t __timeout = info->lwi_timeout;			  \
+	long __timeout = info->lwi_timeout;			  \
 	sigset_t   __blocked;					      \
 	int   __allow_intr = info->lwi_allow_intr;			     \
 									       \
@@ -548,11 +548,11 @@ do {									   \
 		if (__timeout == 0) {					  \
 			schedule();						\
 		} else {						       \
-			cfs_duration_t interval = info->lwi_interval?	  \
-					     min_t(cfs_duration_t,	     \
+			long interval = info->lwi_interval?	  \
+					     min_t(long,	     \
 						 info->lwi_interval,__timeout):\
 					     __timeout;			\
-			cfs_duration_t remaining = schedule_timeout(interval);\
+			long remaining = schedule_timeout(interval);\
 			__timeout = cfs_time_sub(__timeout,		    \
 					    cfs_time_sub(interval, remaining));\
 			if (__timeout == 0) {				  \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_lite.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_lite.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_lite.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_lite.h	2014-09-28 17:29:07.000000000 -0400
@@ -42,19 +42,19 @@
  * @{
  */
 
-#include <linux/lustre_lite.h>
+#include "linux/lustre_lite.h"
 
-#include <obd_class.h>
-#include <obd_ost.h>
-#include <lustre_net.h>
-#include <lustre_mds.h>
-#include <lustre_ha.h>
+#include "obd_class.h"
+#include "obd_ost.h"
+#include "lustre_net.h"
+#include "lustre_mds.h"
+#include "lustre_ha.h"
 
 /* 4UL * 1024 * 1024 */
 #define LL_MAX_BLKSIZE_BITS     (22)
 #define LL_MAX_BLKSIZE	  (1UL<<LL_MAX_BLKSIZE_BITS)
 
-#include <lustre/lustre_user.h>
+#include "lustre/lustre_user.h"
 
 
 struct lustre_rw_params {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_log.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_log.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_log.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_log.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,12 +56,12 @@
  * @{
  */
 
-#include <linux/lustre_log.h>
+#include "linux/lustre_log.h"
 
-#include <obd_class.h>
-#include <obd_ost.h>
-#include <lustre/lustre_idl.h>
-#include <dt_object.h>
+#include "obd_class.h"
+#include "obd_ost.h"
+#include "lustre/lustre_idl.h"
+#include "dt_object.h"
 
 #define LOG_NAME_LIMIT(logname, name)		   \
 	snprintf(logname, sizeof(logname), "LOGS/%s", name)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_mdc.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_mdc.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_mdc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_mdc.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,14 +50,14 @@
 
 #include <linux/fs.h>
 #include <linux/dcache.h>
-#include <linux/lustre_intent.h>
-#include <lustre_handles.h>
-#include <linux/libcfs/libcfs.h>
-#include <obd_class.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_lib.h>
-#include <lustre_dlm.h>
-#include <lustre_export.h>
+#include "linux/lustre_intent.h"
+#include "lustre_handles.h"
+#include "../../include/linux/libcfs/libcfs.h"
+#include "obd_class.h"
+#include "lustre/lustre_idl.h"
+#include "lustre_lib.h"
+#include "lustre_dlm.h"
+#include "lustre_export.h"
 
 struct ptlrpc_client;
 struct obd_export;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_mds.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_mds.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_mds.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_mds.h	2014-09-28 17:29:07.000000000 -0400
@@ -47,12 +47,12 @@
  * @{
  */
 
-#include <lustre_handles.h>
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_lib.h>
-#include <lustre_dlm.h>
-#include <lustre_export.h>
+#include "lustre_handles.h"
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lustre/lustre_idl.h"
+#include "lustre_lib.h"
+#include "lustre_dlm.h"
+#include "lustre_export.h"
 
 struct mds_group_info {
 	struct obd_uuid *uuid;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_net.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_net.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_net.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_net.h	2014-09-28 17:29:07.000000000 -0400
@@ -55,21 +55,21 @@
  * @{
  */
 
-#include <linux/lustre_net.h>
+#include "linux/lustre_net.h"
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 // #include <obd.h>
-#include <linux/lnet/lnet.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_ha.h>
-#include <lustre_sec.h>
-#include <lustre_import.h>
-#include <lprocfs_status.h>
-#include <lu_object.h>
-#include <lustre_req_layout.h>
+#include "../../include/linux/lnet/lnet.h"
+#include "lustre/lustre_idl.h"
+#include "lustre_ha.h"
+#include "lustre_sec.h"
+#include "lustre_import.h"
+#include "lprocfs_status.h"
+#include "lu_object.h"
+#include "lustre_req_layout.h"
 
-#include <obd_support.h>
-#include <lustre_ver.h>
+#include "obd_support.h"
+#include "lustre_ver.h"
 
 /* MD flags we _always_ use */
 #define PTLRPC_MD_OPTIONS  0
@@ -1591,7 +1591,8 @@ struct ptlrpc_request {
 		rq_replay:1,
 		rq_no_resend:1, rq_waiting:1, rq_receiving_reply:1,
 		rq_no_delay:1, rq_net_err:1, rq_wait_ctx:1,
-		rq_early:1, rq_must_unlink:1,
+		rq_early:1,
+		rq_req_unlink:1, rq_reply_unlink:1,
 		rq_memalloc:1,      /* req originated from "kswapd" */
 		/* server-side flags */
 		rq_packed_final:1,  /* packed final reply */
@@ -1712,9 +1713,9 @@ struct ptlrpc_request {
 	lnet_handle_md_t     rq_req_md_h;
 	struct ptlrpc_cb_id  rq_req_cbid;
 	/** optional time limit for send attempts */
-	cfs_duration_t       rq_delay_limit;
+	long       rq_delay_limit;
 	/** time request was first queued */
-	cfs_time_t	   rq_queued_time;
+	unsigned long	   rq_queued_time;
 
 	/* server-side... */
 	/** request arrival time */
@@ -2355,7 +2356,7 @@ struct ptlrpc_service_part {
 	/** incoming reqs */
 	struct list_head			scp_req_incoming;
 	/** timeout before re-posting reqs, in tick */
-	cfs_duration_t			scp_rqbd_timeout;
+	long			scp_rqbd_timeout;
 	/**
 	 * all threads sleep on this. This wait-queue is signalled when new
 	 * incoming request arrives and when difficult reply has to be handled.
@@ -2406,7 +2407,7 @@ struct ptlrpc_service_part {
 	/** early reply timer */
 	struct timer_list		scp_at_timer;
 	/** debug */
-	cfs_time_t			scp_at_checktime;
+	unsigned long			scp_at_checktime;
 	/** check early replies */
 	unsigned			scp_at_check;
 	/** @} */
@@ -2593,7 +2594,7 @@ static inline int ptlrpc_client_bulk_act
 	desc = req->rq_bulk;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_BULK_UNLINK) &&
-	    req->rq_bulk_deadline > cfs_time_current_sec())
+	    req->rq_bulk_deadline > get_seconds())
 		return 1;
 
 	if (!desc)
@@ -3001,7 +3002,7 @@ static inline int
 ptlrpc_client_early(struct ptlrpc_request *req)
 {
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
-	    req->rq_reply_deadline > cfs_time_current_sec())
+	    req->rq_reply_deadline > get_seconds())
 		return 0;
 	return req->rq_early;
 }
@@ -3013,7 +3014,7 @@ static inline int
 ptlrpc_client_replied(struct ptlrpc_request *req)
 {
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
-	    req->rq_reply_deadline > cfs_time_current_sec())
+	    req->rq_reply_deadline > get_seconds())
 		return 0;
 	return req->rq_replied;
 }
@@ -3023,7 +3024,7 @@ static inline int
 ptlrpc_client_recv(struct ptlrpc_request *req)
 {
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
-	    req->rq_reply_deadline > cfs_time_current_sec())
+	    req->rq_reply_deadline > get_seconds())
 		return 1;
 	return req->rq_receiving_reply;
 }
@@ -3035,11 +3036,12 @@ ptlrpc_client_recv_or_unlink(struct ptlr
 
 	spin_lock(&req->rq_lock);
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
-	    req->rq_reply_deadline > cfs_time_current_sec()) {
+	    req->rq_reply_deadline > get_seconds()) {
 		spin_unlock(&req->rq_lock);
 		return 1;
 	}
-	rc = req->rq_receiving_reply || req->rq_must_unlink;
+	rc = req->rq_receiving_reply;
+	rc = rc || req->rq_req_unlink || req->rq_reply_unlink;
 	spin_unlock(&req->rq_lock);
 	return rc;
 }
@@ -3098,9 +3100,9 @@ static inline int ptlrpc_req_get_repsize
 static inline int ptlrpc_send_limit_expired(struct ptlrpc_request *req)
 {
 	if (req->rq_delay_limit != 0 &&
-	    cfs_time_before(cfs_time_add(req->rq_queued_time,
-					 cfs_time_seconds(req->rq_delay_limit)),
-			    cfs_time_current())) {
+	    time_before(cfs_time_add(req->rq_queued_time,
+				     cfs_time_seconds(req->rq_delay_limit)),
+			cfs_time_current())) {
 		return 1;
 	}
 	return 0;
@@ -3227,7 +3229,7 @@ void ptlrpcd_decref(void);
  * @{
  */
 const char* ll_opcode2str(__u32 opcode);
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void ptlrpc_lprocfs_register_obd(struct obd_device *obd);
 void ptlrpc_lprocfs_unregister_obd(struct obd_device *obd);
 void ptlrpc_lprocfs_brw(struct ptlrpc_request *req, int bytes);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_quota.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_quota.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_quota.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_quota.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,11 +32,11 @@
  *
  */
 
-#include <linux/lustre_quota.h>
+#include "linux/lustre_quota.h"
 
-#include <dt_object.h>
-#include <lustre_fid.h>
-#include <lustre_dlm.h>
+#include "dt_object.h"
+#include "lustre_fid.h"
+#include "lustre_dlm.h"
 
 #ifndef MAX_IQ_TIME
 #define MAX_IQ_TIME  604800     /* (7*24*60*60) 1 week */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_req_layout.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_req_layout.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_req_layout.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_req_layout.h	2014-09-28 17:29:07.000000000 -0400
@@ -73,7 +73,7 @@ struct req_capsule {
 #if !defined(__REQ_LAYOUT_USER__)
 
 /* struct ptlrpc_request, lustre_msg* */
-#include <lustre_net.h>
+#include "lustre_net.h"
 
 void req_capsule_init(struct req_capsule *pill, struct ptlrpc_request *req,
 		      enum req_location location);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_sec.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_sec.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lustre_sec.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lustre_sec.h	2014-09-28 17:29:07.000000000 -0400
@@ -387,7 +387,7 @@ struct ptlrpc_ctx_ops {
 	/**
 	 * Force the \a ctx to die.
 	 */
-	void    (*die)	 (struct ptlrpc_cli_ctx *ctx,
+	void    (*force_die)   (struct ptlrpc_cli_ctx *ctx,
 				int grace);
 	int     (*display)     (struct ptlrpc_cli_ctx *ctx,
 				char *buf, int bufsize);
@@ -510,7 +510,7 @@ struct ptlrpc_cli_ctx {
 	atomic_t	    cc_refcount;
 	struct ptlrpc_sec      *cc_sec;
 	struct ptlrpc_ctx_ops  *cc_ops;
-	cfs_time_t	      cc_expire;     /* in seconds */
+	unsigned long	      cc_expire;     /* in seconds */
 	unsigned int	    cc_early_expire:1;
 	unsigned long	   cc_flags;
 	struct vfs_cred	 cc_vcred;
@@ -835,8 +835,8 @@ struct ptlrpc_sec {
 	 * garbage collection
 	 */
 	struct list_head		      ps_gc_list;
-	cfs_time_t		      ps_gc_interval; /* in seconds */
-	cfs_time_t		      ps_gc_next;     /* in seconds */
+	unsigned long		      ps_gc_interval; /* in seconds */
+	unsigned long		      ps_gc_next;     /* in seconds */
 };
 
 static inline int sec_is_reverse(struct ptlrpc_sec *sec)
@@ -1064,7 +1064,7 @@ const char * sec2target_str(struct ptlrp
 /*
  * lprocfs
  */
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 struct proc_dir_entry;
 extern struct proc_dir_entry *sptlrpc_proc_root;
 int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lvfs.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lvfs.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/lvfs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/lvfs.h	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
 
 #define LL_FID_NAMELEN (16 + 1 + 8 + 1)
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lvfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "linux/lvfs.h"
 
-#include <linux/libcfs/lucache.h>
+#include "../../include/linux/libcfs/lucache.h"
 
 
 /* lvfs_common.c */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/md_object.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/md_object.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/md_object.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/md_object.h	2014-09-28 17:29:07.000000000 -0400
@@ -56,7 +56,7 @@
 /*
  * super-class definitions.
  */
-#include <dt_object.h>
+#include "dt_object.h"
 
 struct md_device;
 struct md_device_operations;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_cksum.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_cksum.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_cksum.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_cksum.h	2014-09-28 17:29:07.000000000 -0400
@@ -34,8 +34,8 @@
 
 #ifndef __OBD_CKSUM
 #define __OBD_CKSUM
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lustre/lustre_idl.h"
 
 static inline unsigned char cksum_obd2cfs(cksum_type_t cksum_type)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_class.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_class.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_class.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_class.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,15 +37,15 @@
 #define __CLASS_OBD_H
 
 
-#include <obd_support.h>
-#include <lustre_import.h>
-#include <lustre_net.h>
-#include <obd.h>
-#include <lustre_lib.h>
-#include <lustre/lustre_idl.h>
-#include <lprocfs_status.h>
+#include "obd_support.h"
+#include "lustre_import.h"
+#include "lustre_net.h"
+#include "obd.h"
+#include "lustre_lib.h"
+#include "lustre/lustre_idl.h"
+#include "lprocfs_status.h"
 
-#include <linux/obd_class.h>
+#include "linux/obd_class.h"
 
 #define OBD_STATFS_NODELAY      0x0001  /* requests should be send without delay
 					 * and resends for avoid deadlocks */
@@ -141,7 +141,7 @@ int class_add_conn(struct obd_device *ob
 int class_add_uuid(const char *uuid, __u64 nid);
 
 /*obdecho*/
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 extern void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
 #else
 static inline void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars)
@@ -347,7 +347,7 @@ do {							    \
 } while (0)
 
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 #define OBD_COUNTER_OFFSET(op)				  \
 	((offsetof(struct obd_ops, o_ ## op) -		  \
 	  offsetof(struct obd_ops, o_iocontrol))		\
@@ -1160,13 +1160,12 @@ static inline int obd_statfs_async(struc
 	OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, statfs);
 
-	CDEBUG(D_SUPER, "%s: osfs %p age "LPU64", max_age "LPU64"\n",
+	CDEBUG(D_SUPER, "%s: osfs %p age %llu, max_age %llu\n",
 	       obd->obd_name, &obd->obd_osfs, obd->obd_osfs_age, max_age);
 	if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
 		rc = OBP(obd, statfs_async)(exp, oinfo, max_age, rqset);
 	} else {
-		CDEBUG(D_SUPER,"%s: use %p cache blocks "LPU64"/"LPU64
-		       " objects "LPU64"/"LPU64"\n",
+		CDEBUG(D_SUPER,"%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",
 		       obd->obd_name, &obd->obd_osfs,
 		       obd->obd_osfs.os_bavail, obd->obd_osfs.os_blocks,
 		       obd->obd_osfs.os_ffree, obd->obd_osfs.os_files);
@@ -1217,7 +1216,7 @@ static inline int obd_statfs(const struc
 	OBD_CHECK_DT_OP(obd, statfs, -EOPNOTSUPP);
 	OBD_COUNTER_INCREMENT(obd, statfs);
 
-	CDEBUG(D_SUPER, "osfs "LPU64", max_age "LPU64"\n",
+	CDEBUG(D_SUPER, "osfs %llu, max_age %llu\n",
 	       obd->obd_osfs_age, max_age);
 	if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
 		rc = OBP(obd, statfs)(env, exp, osfs, max_age, flags);
@@ -1228,8 +1227,7 @@ static inline int obd_statfs(const struc
 			spin_unlock(&obd->obd_osfs_lock);
 		}
 	} else {
-		CDEBUG(D_SUPER, "%s: use %p cache blocks "LPU64"/"LPU64
-		       " objects "LPU64"/"LPU64"\n",
+		CDEBUG(D_SUPER, "%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",
 		       obd->obd_name, &obd->obd_osfs,
 		       obd->obd_osfs.os_bavail, obd->obd_osfs.os_blocks,
 		       obd->obd_osfs.os_ffree, obd->obd_osfs.os_files);
@@ -1818,7 +1816,7 @@ static inline int md_enqueue(struct obd_
 			     struct lustre_handle *lockh,
 			     void *lmm, int lmmsize,
 			     struct ptlrpc_request **req,
-			     int extra_lock_flags)
+			     __u64 extra_lock_flags)
 {
 	int rc;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #ifndef __OBD_H
 #define __OBD_H
 
-#include <linux/obd.h>
+#include "linux/obd.h"
 
 #define IOC_OSC_TYPE	 'h'
 #define IOC_OSC_MIN_NR       20
@@ -48,14 +48,13 @@
 #define IOC_MDC_MIN_NR       20
 #define IOC_MDC_MAX_NR       50
 
-#include <lustre/lustre_idl.h>
-#include <lustre_lib.h>
-#include <linux/libcfs/bitmap.h>
-#include <lu_ref.h>
-#include <lustre_export.h>
-#include <lustre_fid.h>
-#include <lustre_fld.h>
-#include <lustre_capa.h>
+#include "lustre/lustre_idl.h"
+#include "lustre_lib.h"
+#include "lu_ref.h"
+#include "lustre_export.h"
+#include "lustre_fid.h"
+#include "lustre_fld.h"
+#include "lustre_capa.h"
 
 #define MAX_OBD_DEVICES 8192
 
@@ -282,7 +281,7 @@ enum llog_ctxt_id {
 
 struct timeout_item {
 	enum timeout_event ti_event;
-	cfs_time_t	 ti_timeout;
+	unsigned long	 ti_timeout;
 	timeout_cb_t       ti_cb;
 	void	      *ti_cb_data;
 	struct list_head	 ti_obd_list;
@@ -338,7 +337,7 @@ struct client_obd {
 	 * See osc_{reserve|unreserve}_grant for details. */
 	long		 cl_reserved_grant;
 	struct list_head	   cl_cache_waiters; /* waiting for cache/grant */
-	cfs_time_t	   cl_next_shrink_grant;   /* jiffies */
+	unsigned long	   cl_next_shrink_grant;   /* jiffies */
 	struct list_head	   cl_grant_shrink_list;  /* Timeout event list */
 	int		  cl_grant_shrink_interval; /* seconds */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_ost.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_ost.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_ost.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_ost.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@
 #ifndef _LUSTRE_OST_H
 #define _LUSTRE_OST_H
 
-#include <obd_class.h>
+#include "obd_class.h"
 
 struct osc_brw_async_args {
 	struct obdo       *aa_oa;
@@ -87,6 +87,10 @@ struct osc_enqueue_args {
 	unsigned int	      oa_agl:1;
 };
 
+extern void osc_update_enqueue(struct lustre_handle *lov_lockhp,
+			       struct lov_oinfo *loi, __u64 flags,
+			       struct ost_lvb *lvb, __u32 mode, int rc);
+
 #if 0
 int osc_extent_blocking_cb(struct ldlm_lock *lock,
 			   struct ldlm_lock_desc *new, void *data,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_support.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_support.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/include/obd_support.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/include/obd_support.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,11 +37,10 @@
 #ifndef _OBD_SUPPORT
 #define _OBD_SUPPORT
 
-#include <linux/libcfs/libcfs.h>
-#include <lvfs.h>
-#include <lprocfs_status.h>
-
-#include <linux/obd_support.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "lvfs.h"
+#include "lprocfs_status.h"
+#include "linux/obd_support.h"
 
 /* global variables */
 extern struct lprocfs_stats *obd_memory;
@@ -509,7 +508,7 @@ extern atomic_t libcfs_kmemory;
 
 extern void obd_update_maxusage(void);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 #define obd_memory_add(size)						  \
 	lprocfs_counter_add(obd_memory, OBD_MEMORY_STAT, (long)(size))
 #define obd_memory_sub(size)						  \
@@ -663,7 +662,7 @@ do {									      \
 	if (unlikely((ptr) == NULL)) {					\
 		CERROR("vmalloc of '" #ptr "' (%d bytes) failed\n",	   \
 		       (int)(size));					  \
-		CERROR(LPU64" total bytes allocated by Lustre, %d by LNET\n", \
+		CERROR("%llu total bytes allocated by Lustre, %d by LNET\n", \
 		       obd_memory_sum(), atomic_read(&libcfs_kmemory));   \
 	} else {							      \
 		OBD_ALLOC_POST(ptr, size, "vmalloced");		       \
@@ -823,11 +822,11 @@ do {									      \
 		alloc_page(gfp_mask) :				      \
 		alloc_pages_node(cfs_cpt_spread_node(cptab, cpt), gfp_mask, 0);\
 	if (unlikely((ptr) == NULL)) {					\
-		CERROR("alloc_pages of '" #ptr "' %d page(s) / "LPU64" bytes "\
+		CERROR("alloc_pages of '" #ptr "' %d page(s) / %llu bytes "\
 		       "failed\n", (int)1,				    \
 		       (__u64)(1 << PAGE_CACHE_SHIFT));			 \
-		CERROR(LPU64" total bytes and "LPU64" total pages "	   \
-		       "("LPU64" bytes) allocated by Lustre, "		\
+		CERROR("%llu total bytes and %llu total pages "	   \
+		       "(%llu bytes) allocated by Lustre, "		\
 		       "%d total bytes by LNET\n",			    \
 		       obd_memory_sum(),				      \
 		       obd_pages_sum() << PAGE_CACHE_SHIFT,		     \
@@ -836,7 +835,7 @@ do {									      \
 	} else {							      \
 		obd_pages_add(0);					     \
 		CDEBUG(D_MALLOC, "alloc_pages '" #ptr "': %d page(s) / "      \
-		       LPU64" bytes at %p.\n",				\
+		       "%llu bytes at %p.\n",				\
 		       (int)1,						\
 		       (__u64)(1 << PAGE_CACHE_SHIFT), ptr);		    \
 	}								     \
@@ -851,7 +850,7 @@ do {									      \
 do {									  \
 	LASSERT(ptr);							 \
 	obd_pages_sub(0);						     \
-	CDEBUG(D_MALLOC, "free_pages '" #ptr "': %d page(s) / "LPU64" bytes " \
+	CDEBUG(D_MALLOC, "free_pages '" #ptr "': %d page(s) / %llu bytes " \
 	       "at %p.\n",						    \
 	       (int)1, (__u64)(1 << PAGE_CACHE_SHIFT),			  \
 	       ptr);							  \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -57,4 +57,5 @@ config LUSTRE_TRANSLATE_ERRNOS
 config LUSTRE_LLITE_LLOOP
 	tristate "Lustre virtual block device"
 	depends on LUSTRE_FS && BLOCK
+	depends on !PPC_64K_PAGES && !ARM64_64K_PAGES
 	default m
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/glimpse.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/glimpse.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/glimpse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/glimpse.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,20 +40,20 @@
  *   Author: Oleg Drokin <oleg.drokin@sun.com>
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <obd.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/obd.h"
 
-# include <lustre_dlm.h>
-# include <lustre_lite.h>
-# include <lustre_mdc.h>
-# include <linux/pagemap.h>
-# include <linux/file.h>
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_mdc.h"
+#include <linux/pagemap.h>
+#include <linux/file.h>
 
-#include "cl_object.h"
-#include "lclient.h"
-# include "../llite/llite_internal.h"
+#include "../include/cl_object.h"
+#include "../include/lclient.h"
+#include "../llite/llite_internal.h"
 
 static const struct cl_lock_descr whole_file = {
 	.cld_start = 0,
@@ -177,7 +177,7 @@ static int cl_io_get(struct inode *inode
 			io->ci_obj = clob;
 			*envout = env;
 			*ioout  = io;
-			result = +1;
+			result = 1;
 		} else
 			result = PTR_ERR(env);
 	} else
@@ -204,7 +204,7 @@ int cl_glimpse_size0(struct inode *inode
 
 	result = cl_io_get(inode, &env, &io, &refcheck);
 	if (result > 0) {
-	again:
+again:
 		io->ci_verify_layout = 1;
 		result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
 		if (result > 0)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/lcommon_cl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/lcommon_cl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/lcommon_cl.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 # include <linux/fs.h>
 # include <linux/sched.h>
 # include <linux/mm.h>
@@ -50,16 +50,16 @@
 # include <linux/pagemap.h>
 # include <linux/rbtree.h>
 
-#include <obd.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
-#include <lustre_ver.h>
-#include <lustre_mdc.h>
-#include <cl_object.h>
+#include "../include/obd.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_ver.h"
+#include "../include/lustre_mdc.h"
+#include "../include/cl_object.h"
 
-#include <lclient.h>
+#include "../include/lclient.h"
 
 #include "../llite/llite_internal.h"
 
@@ -126,6 +126,7 @@ void ccc_key_fini(const struct lu_contex
 			 struct lu_context_key *key, void *data)
 {
 	struct ccc_thread_info *info = data;
+
 	OBD_SLAB_FREE_PTR(info, ccc_thread_kmem);
 }
 
@@ -144,6 +145,7 @@ void ccc_session_key_fini(const struct l
 				 struct lu_context_key *key, void *data)
 {
 	struct ccc_session *session = data;
+
 	OBD_SLAB_FREE_PTR(session, ccc_session_kmem);
 }
 
@@ -264,7 +266,7 @@ int ccc_req_init(const struct lu_env *en
  * fails. Access to this environment is serialized by ccc_inode_fini_guard
  * mutex.
  */
-static struct lu_env *ccc_inode_fini_env = NULL;
+static struct lu_env *ccc_inode_fini_env;
 
 /**
  * A mutex serializing calls to slp_inode_fini() under extreme memory
@@ -572,6 +574,7 @@ void ccc_lock_delete(const struct lu_env
 void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice)
 {
 	struct ccc_lock *clk = cl2ccc_lock(slice);
+
 	OBD_SLAB_FREE_PTR(clk, ccc_lock_kmem);
 }
 
@@ -733,6 +736,7 @@ int ccc_io_one_lock(const struct lu_env
 		    loff_t start, loff_t end)
 {
 	struct cl_object *obj = io->ci_obj;
+
 	return ccc_io_one_lock_index(env, io, enqflags, mode,
 				     cl_index(obj, start), cl_index(obj, end));
 }
@@ -817,11 +821,12 @@ int ccc_prep_size(const struct lu_env *e
 				 * linux-2.6.18-128.1.1 miss to do that.
 				 * --bug 17336 */
 				loff_t size = cl_isize_read(inode);
-				unsigned long cur_index = start >> PAGE_CACHE_SHIFT;
+				loff_t cur_index = start >> PAGE_CACHE_SHIFT;
+				loff_t size_index = ((size - 1) >> PAGE_CACHE_SHIFT);
 
 				if ((size == 0 && cur_index != 0) ||
-				    (((size - 1) >> PAGE_CACHE_SHIFT) < cur_index))
-				*exceed = 1;
+				    size_index < cur_index)
+					*exceed = 1;
 			}
 			return result;
 		} else {
@@ -838,7 +843,7 @@ int ccc_prep_size(const struct lu_env *e
 			if (cl_isize_read(inode) < kms) {
 				cl_isize_write_nolock(inode, kms);
 				CDEBUG(D_VFSTRACE,
-				       DFID" updating i_size "LPU64"\n",
+				       DFID" updating i_size %llu\n",
 				       PFID(lu_object_fid(&obj->co_lu)),
 				       (__u64)cl_isize_read(inode));
 
@@ -1269,7 +1274,7 @@ struct lov_stripe_md *ccc_inode_lsm_get(
 	return lov_lsm_get(cl_i2info(inode)->lli_clob);
 }
 
-void inline ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm)
+inline void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm)
 {
 	lov_lsm_put(cl_i2info(inode)->lli_clob, lsm);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/lcommon_misc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/lcommon_misc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lclient/lcommon_misc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lclient/lcommon_misc.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,13 +37,13 @@
  * future).
  *
  */
-#include <obd_class.h>
-#include <obd_support.h>
-#include <obd.h>
-#include <cl_object.h>
-#include <lclient.h>
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/obd.h"
+#include "../include/cl_object.h"
+#include "../include/lclient.h"
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 
 
 /* Initialize the default and maximum LOV EA and cookie sizes.  This allows
@@ -63,7 +63,7 @@ int cl_init_ea_size(struct obd_export *m
 	if (rc)
 		return rc;
 
-	stripes = min(desc.ld_tgt_count, (__u32)LOV_MAX_STRIPE_COUNT);
+	stripes = min_t(__u32, desc.ld_tgt_count, LOV_MAX_STRIPE_COUNT);
 	lsm.lsm_stripe_count = stripes;
 	easize = obd_size_diskmd(dt_exp, &lsm);
 
@@ -103,7 +103,7 @@ int cl_ocd_update(struct obd_device *hos
 		cli = &watched->u.cli;
 		lco = owner;
 		flags = cli->cl_import->imp_connect_data.ocd_connect_flags;
-		CDEBUG(D_SUPER, "Changing connect_flags: "LPX64" -> "LPX64"\n",
+		CDEBUG(D_SUPER, "Changing connect_flags: %#llx -> %#llx\n",
 		       lco->lco_flags, flags);
 		mutex_lock(&lco->lco_lock);
 		lco->lco_flags &= flags;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/interval_tree.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/interval_tree.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/interval_tree.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/interval_tree.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,9 +38,9 @@
  * Author: Huang Wei <huangwei@clusterfs.com>
  * Author: Jay Xiong <jinshan.xiong@sun.com>
  */
-# include <lustre_dlm.h>
-#include <obd_support.h>
-#include <interval_tree.h>
+#include "../include/lustre_dlm.h"
+#include "../include/obd_support.h"
+#include "../include/interval_tree.h"
 
 enum {
 	INTERVAL_RED = 0,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c	2014-09-28 17:29:07.000000000 -0400
@@ -50,14 +50,12 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LDLM
-# include <linux/libcfs/libcfs.h>
-
-#include <lustre_dlm.h>
-#include <obd_support.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre_dlm.h"
+#include "../include/obd_support.h"
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
 #include "ldlm_internal.h"
 
 
@@ -92,7 +90,7 @@ __u64 ldlm_extent_shift_kms(struct ldlm_
 		if (lck->l_policy_data.l_extent.end + 1 > kms)
 			kms = lck->l_policy_data.l_extent.end + 1;
 	}
-	LASSERTF(kms <= old_kms, "kms "LPU64" old_kms "LPU64"\n", kms, old_kms);
+	LASSERTF(kms <= old_kms, "kms %llu old_kms %llu\n", kms, old_kms);
 
 	return kms;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c	2014-09-28 17:29:07.000000000 -0400
@@ -56,12 +56,11 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-#include <lustre_dlm.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
+#include "../include/lustre_dlm.h"
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
 #include <linux/list.h>
-
 #include "ldlm_internal.h"
 
 int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
@@ -261,9 +260,8 @@ ldlm_process_flock_lock(struct ldlm_lock
 	int splitted = 0;
 	const struct ldlm_callback_suite null_cbs = { NULL };
 
-	CDEBUG(D_DLMTRACE, "flags %#llx owner "LPU64" pid %u mode %u start "
-	       LPU64" end "LPU64"\n", *flags,
-	       new->l_policy_data.l_flock.owner,
+	CDEBUG(D_DLMTRACE, "flags %#llx owner %llu pid %u mode %u start %llu end %llu\n",
+	       *flags, new->l_policy_data.l_flock.owner,
 	       new->l_policy_data.l_flock.pid, mode,
 	       req->l_policy_data.l_flock.start,
 	       req->l_policy_data.l_flock.end);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_inodebits.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_inodebits.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_inodebits.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_inodebits.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,10 +53,9 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-#include <lustre_dlm.h>
-#include <obd_support.h>
-#include <lustre_lib.h>
-
+#include "../include/lustre_dlm.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_lib.h"
 #include "ldlm_internal.h"
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,12 +43,12 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-# include <linux/libcfs/libcfs.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_dlm.h>
-#include <lustre_net.h>
-#include <lustre_sec.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_sec.h"
 #include "ldlm_internal.h"
 
 /* @priority: If non-zero, move the selected connection to the list head.
@@ -74,9 +74,8 @@ static int import_set_conn(struct obd_im
 
 	if (create) {
 		OBD_ALLOC(imp_conn, sizeof(*imp_conn));
-		if (!imp_conn) {
+		if (!imp_conn)
 			GOTO(out_put, rc = -ENOMEM);
-		}
 	}
 
 	spin_lock(&imp->imp_lock);
@@ -511,14 +510,14 @@ int client_connect_import(const struct l
 
 	rc = ptlrpc_connect_import(imp);
 	if (rc != 0) {
-		LASSERT (imp->imp_state == LUSTRE_IMP_DISCON);
+		LASSERT(imp->imp_state == LUSTRE_IMP_DISCON);
 		GOTO(out_ldlm, rc);
 	}
 	LASSERT(*exp != NULL && (*exp)->exp_connection);
 
 	if (data) {
 		LASSERTF((ocd->ocd_connect_flags & data->ocd_connect_flags) ==
-			 ocd->ocd_connect_flags, "old "LPX64", new "LPX64"\n",
+			 ocd->ocd_connect_flags, "old %#llx, new %#llx\n",
 			 data->ocd_connect_flags, ocd->ocd_connect_flags);
 		data->ocd_connect_flags = ocd->ocd_connect_flags;
 	}
@@ -546,7 +545,7 @@ int client_disconnect_export(struct obd_
 	int rc = 0, err;
 
 	if (!obd) {
-		CERROR("invalid export for disconnect: exp %p cookie "LPX64"\n",
+		CERROR("invalid export for disconnect: exp %p cookie %#llx\n",
 		       exp, exp ? exp->exp_handle.h_cookie : -1);
 		return -EINVAL;
 	}
@@ -662,33 +661,32 @@ void target_send_reply(struct ptlrpc_req
 	struct ptlrpc_reply_state *rs;
 	struct obd_export	 *exp;
 
-	if (req->rq_no_reply) {
+	if (req->rq_no_reply)
 		return;
-	}
 
 	svcpt = req->rq_rqbd->rqbd_svcpt;
 	rs = req->rq_reply_state;
 	if (rs == NULL || !rs->rs_difficult) {
 		/* no notifiers */
-		target_send_reply_msg (req, rc, fail_id);
+		target_send_reply_msg(req, rc, fail_id);
 		return;
 	}
 
 	/* must be an export if locks saved */
-	LASSERT (req->rq_export != NULL);
+	LASSERT(req->rq_export != NULL);
 	/* req/reply consistent */
 	LASSERT(rs->rs_svcpt == svcpt);
 
 	/* "fresh" reply */
-	LASSERT (!rs->rs_scheduled);
-	LASSERT (!rs->rs_scheduled_ever);
-	LASSERT (!rs->rs_handled);
-	LASSERT (!rs->rs_on_net);
-	LASSERT (rs->rs_export == NULL);
-	LASSERT (list_empty(&rs->rs_obd_list));
-	LASSERT (list_empty(&rs->rs_exp_list));
+	LASSERT(!rs->rs_scheduled);
+	LASSERT(!rs->rs_scheduled_ever);
+	LASSERT(!rs->rs_handled);
+	LASSERT(!rs->rs_on_net);
+	LASSERT(rs->rs_export == NULL);
+	LASSERT(list_empty(&rs->rs_obd_list));
+	LASSERT(list_empty(&rs->rs_exp_list));
 
-	exp = class_export_get (req->rq_export);
+	exp = class_export_get(req->rq_export);
 
 	/* disable reply scheduling while I'm setting up */
 	rs->rs_scheduled = 1;
@@ -699,7 +697,7 @@ void target_send_reply(struct ptlrpc_req
 	rs->rs_opc       = lustre_msg_get_opc(req->rq_reqmsg);
 
 	spin_lock(&exp->exp_uncommitted_replies_lock);
-	CDEBUG(D_NET, "rs transno = "LPU64", last committed = "LPU64"\n",
+	CDEBUG(D_NET, "rs transno = %llu, last committed = %llu\n",
 	       rs->rs_transno, exp->exp_last_committed);
 	if (rs->rs_transno > exp->exp_last_committed) {
 		/* not committed already */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,9 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-# include <linux/libcfs/libcfs.h>
-# include <linux/lustre_intent.h>
-
-#include <obd_class.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/linux/lustre_intent.h"
+#include "../include/obd_class.h"
 #include "ldlm_internal.h"
 
 /* lock types */
@@ -625,8 +624,7 @@ void ldlm_lock2desc(struct ldlm_lock *lo
 		LASSERTF(lock->l_policy_data.l_inodebits.bits ==
 			 (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
 			  MDS_INODELOCK_LAYOUT),
-			 "Inappropriate inode lock bits during "
-			 "conversion " LPU64 "\n",
+			 "Inappropriate inode lock bits during conversion %llu\n",
 			 lock->l_policy_data.l_inodebits.bits);
 
 		ldlm_res2desc(lock->l_resource, &desc->l_resource);
@@ -899,7 +897,7 @@ void ldlm_lock_decref_internal(struct ld
 void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode)
 {
 	struct ldlm_lock *lock = __ldlm_handle2lock(lockh, 0);
-	LASSERTF(lock != NULL, "Non-existing lock: "LPX64"\n", lockh->cookie);
+	LASSERTF(lock != NULL, "Non-existing lock: %#llx\n", lockh->cookie);
 	ldlm_lock_decref_internal(lock, mode);
 	LDLM_LOCK_PUT(lock);
 }
@@ -1351,7 +1349,7 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_
 	}
  out2:
 	if (rc) {
-		LDLM_DEBUG(lock, "matched ("LPU64" "LPU64")",
+		LDLM_DEBUG(lock, "matched (%llu %llu)",
 			   (type == LDLM_PLAIN || type == LDLM_IBITS) ?
 				res_id->name[2] : policy->l_extent.start,
 			   (type == LDLM_PLAIN || type == LDLM_IBITS) ?
@@ -1370,9 +1368,8 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_
 			LDLM_LOCK_RELEASE(lock);
 
 	} else if (!(flags & LDLM_FL_TEST_LOCK)) {/*less verbose for test-only*/
-		LDLM_DEBUG_NOLOCK("not matched ns %p type %u mode %u res "
-				  LPU64"/"LPU64" ("LPU64" "LPU64")", ns,
-				  type, mode, res_id->name[0], res_id->name[1],
+		LDLM_DEBUG_NOLOCK("not matched ns %p type %u mode %u res %llu/%llu (%llu %llu)",
+				  ns, type, mode, res_id->name[0], res_id->name[1],
 				  (type == LDLM_PLAIN || type == LDLM_IBITS) ?
 					res_id->name[2] :policy->l_extent.start,
 				  (type == LDLM_PLAIN || type == LDLM_IBITS) ?
@@ -1595,7 +1592,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ld
 	ldlm_error_t rc = ELDLM_OK;
 	struct ldlm_interval *node = NULL;
 
-	lock->l_last_activity = cfs_time_current_sec();
+	lock->l_last_activity = get_seconds();
 	/* policies are not executed on the client or during replay */
 	if ((*flags & (LDLM_FL_HAS_INTENT|LDLM_FL_REPLAY)) == LDLM_FL_HAS_INTENT
 	    && !local && ns->ns_policy) {
@@ -2258,9 +2255,9 @@ void _ldlm_lock_debug(struct ldlm_lock *
 
 	if (resource == NULL) {
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-		       " ns: \?\? lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-		       "res: \?\? rrc=\?\? type: \?\?\? flags: "LPX64" nid: %s "
-		       "remote: "LPX64" expref: %d pid: %u timeout: %lu "
+		       " ns: \?\? lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s "
+		       "res: \?\? rrc=\?\? type: \?\?\? flags: %#llx nid: %s "
+		       "remote: %#llx expref: %d pid: %u timeout: %lu "
 		       "lvb_type: %d\n",
 		       lock,
 		       lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
@@ -2277,10 +2274,10 @@ void _ldlm_lock_debug(struct ldlm_lock *
 	switch (resource->lr_type) {
 	case LDLM_EXTENT:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-			"res: "DLDLMRES" rrc: %d type: %s ["LPU64"->"LPU64"] "
-			"(req "LPU64"->"LPU64") flags: "LPX64" nid: %s remote: "
-			LPX64" expref: %d pid: %u timeout: %lu lvb_type: %d\n",
+			" ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" rrc: %d type: %s [%llu->%llu] "
+			"(req %llu->%llu) flags: %#llx nid: %s remote: "
+			"%#llx expref: %d pid: %u timeout: %lu lvb_type: %d\n",
 			ldlm_lock_to_ns_name(lock), lock,
 			lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
 			lock->l_readers, lock->l_writers,
@@ -2300,10 +2297,10 @@ void _ldlm_lock_debug(struct ldlm_lock *
 
 	case LDLM_FLOCK:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
+			" ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s "
 			"res: "DLDLMRES" rrc: %d type: %s pid: %d "
-			"["LPU64"->"LPU64"] flags: "LPX64" nid: %s "
-			"remote: "LPX64" expref: %d pid: %u timeout: %lu\n",
+			"[%llu->%llu] flags: %#llx nid: %s "
+			"remote: %#llx expref: %d pid: %u timeout: %lu\n",
 			ldlm_lock_to_ns_name(lock), lock,
 			lock->l_handle.h_cookie, atomic_read(&lock->l_refc),
 			lock->l_readers, lock->l_writers,
@@ -2322,9 +2319,9 @@ void _ldlm_lock_debug(struct ldlm_lock *
 
 	case LDLM_IBITS:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-			"res: "DLDLMRES" bits "LPX64" rrc: %d type: %s "
-			"flags: "LPX64" nid: %s remote: "LPX64" expref: %d "
+			" ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" bits %#llx rrc: %d type: %s "
+			"flags: %#llx nid: %s remote: %#llx expref: %d "
 			"pid: %u timeout: %lu lvb_type: %d\n",
 			ldlm_lock_to_ns_name(lock),
 			lock, lock->l_handle.h_cookie,
@@ -2344,9 +2341,9 @@ void _ldlm_lock_debug(struct ldlm_lock *
 
 	default:
 		libcfs_debug_vmsg2(msgdata, fmt, args,
-			" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "
-			"res: "DLDLMRES" rrc: %d type: %s flags: "LPX64" "
-			"nid: %s remote: "LPX64" expref: %d pid: %u "
+			" ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s "
+			"res: "DLDLMRES" rrc: %d type: %s flags: %#llx "
+			"nid: %s remote: %#llx expref: %d pid: %u "
 			"timeout: %lu lvb_type: %d\n",
 			ldlm_lock_to_ns_name(lock),
 			lock, lock->l_handle.h_cookie,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,9 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-# include <linux/libcfs/libcfs.h>
-
-#include <lustre_dlm.h>
-#include <obd_class.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre_dlm.h"
+#include "../include/obd_class.h"
 #include <linux/list.h>
 #include "ldlm_internal.h"
 
@@ -70,7 +69,7 @@ struct ldlm_cb_async_args {
 
 static struct ldlm_state *ldlm_state;
 
-inline cfs_time_t round_timeout(cfs_time_t timeout)
+inline unsigned long round_timeout(unsigned long timeout)
 {
 	return cfs_time_seconds((int)cfs_duration_sec(cfs_time_sub(timeout, 0)) + 1);
 }
@@ -526,7 +525,7 @@ static inline void ldlm_callback_errmsg(
 					struct lustre_handle *handle)
 {
 	DEBUG_REQ((req->rq_no_reply || rc) ? D_WARNING : D_DLMTRACE, req,
-		  "%s: [nid %s] [rc %d] [lock "LPX64"]",
+		  "%s: [nid %s] [rc %d] [lock %#llx]",
 		  msg, libcfs_id2str(req->rq_peer), rc,
 		  handle ? handle->cookie : 0);
 	if (req->rq_no_reply)
@@ -636,7 +635,7 @@ static int ldlm_callback_handler(struct
 
 	lock = ldlm_handle2lock_long(&dlm_req->lock_handle[0], 0);
 	if (!lock) {
-		CDEBUG(D_DLMTRACE, "callback on lock "LPX64" - lock "
+		CDEBUG(D_DLMTRACE, "callback on lock %#llx - lock "
 		       "disappeared\n", dlm_req->lock_handle[0].cookie);
 		rc = ldlm_callback_reply(req, -EINVAL);
 		ldlm_callback_errmsg(req, "Operate with invalid parameter", rc,
@@ -661,7 +660,7 @@ static int ldlm_callback_handler(struct
 		    (lock->l_flags & LDLM_FL_BL_DONE)) ||
 		    (lock->l_flags & LDLM_FL_FAILED)) {
 			LDLM_DEBUG(lock, "callback on lock "
-				   LPX64" - lock disappeared\n",
+				   "%#llx - lock disappeared\n",
 				   dlm_req->lock_handle[0].cookie);
 			unlock_res_and_lock(lock);
 			LDLM_LOCK_RELEASE(lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_plain.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_plain.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_plain.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_plain.c	2014-09-28 17:29:07.000000000 -0400
@@ -52,9 +52,9 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-#include <lustre_dlm.h>
-#include <obd_support.h>
-#include <lustre_lib.h>
+#include "../include/lustre_dlm.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_lib.h"
 
 #include "ldlm_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c	2014-09-28 17:29:07.000000000 -0400
@@ -97,12 +97,10 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-# include <lustre_dlm.h>
-
-#include <cl_object.h>
-
-#include <obd_class.h>
-#include <obd_support.h>
+#include "../include/lustre_dlm.h"
+#include "../include/cl_object.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
 #include "ldlm_internal.h"
 
 
@@ -336,12 +334,12 @@ static int ldlm_srv_pool_recalc(struct l
 {
 	time_t recalc_interval_sec;
 
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
+	recalc_interval_sec = get_seconds() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period)
 		return 0;
 
 	spin_lock(&pl->pl_lock);
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
+	recalc_interval_sec = get_seconds() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period) {
 		spin_unlock(&pl->pl_lock);
 		return 0;
@@ -362,7 +360,7 @@ static int ldlm_srv_pool_recalc(struct l
 	 */
 	ldlm_pool_recalc_grant_plan(pl);
 
-	pl->pl_recalc_time = cfs_time_current_sec();
+	pl->pl_recalc_time = get_seconds();
 	lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT,
 			    recalc_interval_sec);
 	spin_unlock(&pl->pl_lock);
@@ -473,7 +471,7 @@ static int ldlm_cli_pool_recalc(struct l
 {
 	time_t recalc_interval_sec;
 
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
+	recalc_interval_sec = get_seconds() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period)
 		return 0;
 
@@ -481,7 +479,7 @@ static int ldlm_cli_pool_recalc(struct l
 	/*
 	 * Check if we need to recalc lists now.
 	 */
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
+	recalc_interval_sec = get_seconds() - pl->pl_recalc_time;
 	if (recalc_interval_sec < pl->pl_recalc_period) {
 		spin_unlock(&pl->pl_lock);
 		return 0;
@@ -492,7 +490,7 @@ static int ldlm_cli_pool_recalc(struct l
 	 */
 	ldlm_cli_pool_pop_slv(pl);
 
-	pl->pl_recalc_time = cfs_time_current_sec();
+	pl->pl_recalc_time = get_seconds();
 	lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT,
 			    recalc_interval_sec);
 	spin_unlock(&pl->pl_lock);
@@ -566,7 +564,7 @@ int ldlm_pool_recalc(struct ldlm_pool *p
 	time_t recalc_interval_sec;
 	int count;
 
-	recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time;
+	recalc_interval_sec = get_seconds() - pl->pl_recalc_time;
 	if (recalc_interval_sec <= 0)
 		goto recalc;
 
@@ -591,7 +589,7 @@ int ldlm_pool_recalc(struct ldlm_pool *p
 		lprocfs_counter_add(pl->pl_stats, LDLM_POOL_RECALC_STAT,
 				    count);
 	}
-	recalc_interval_sec = pl->pl_recalc_time - cfs_time_current_sec() +
+	recalc_interval_sec = pl->pl_recalc_time - get_seconds() +
 			      pl->pl_recalc_period;
 
 	return recalc_interval_sec;
@@ -638,7 +636,7 @@ int ldlm_pool_setup(struct ldlm_pool *pl
 }
 EXPORT_SYMBOL(ldlm_pool_setup);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused)
 {
 	int granted, grant_rate, cancel_rate, grant_step;
@@ -661,8 +659,8 @@ static int lprocfs_pool_state_seq_show(s
 	spin_unlock(&pl->pl_lock);
 
 	seq_printf(m, "LDLM pool state (%s):\n"
-		      "  SLV: "LPU64"\n"
-		      "  CLV: "LPU64"\n"
+		      "  SLV: %llu\n"
+		      "  CLV: %llu\n"
 		      "  LVF: %d\n",
 		      pl->pl_name, slv, clv, lvf);
 
@@ -823,14 +821,14 @@ static void ldlm_pool_proc_fini(struct l
 		pl->pl_proc_dir = NULL;
 	}
 }
-#else /* !LPROCFS */
+#else /* !CONFIG_PROC_FS */
 static int ldlm_pool_proc_init(struct ldlm_pool *pl)
 {
 	return 0;
 }
 
 static void ldlm_pool_proc_fini(struct ldlm_pool *pl) {}
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns,
 		   int idx, ldlm_side_t client)
@@ -839,7 +837,7 @@ int ldlm_pool_init(struct ldlm_pool *pl,
 
 	spin_lock_init(&pl->pl_lock);
 	atomic_set(&pl->pl_granted, 0);
-	pl->pl_recalc_time = cfs_time_current_sec();
+	pl->pl_recalc_time = get_seconds();
 	atomic_set(&pl->pl_lock_volume_factor, 1);
 
 	atomic_set(&pl->pl_grant_rate, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,9 +61,9 @@
 
 #define DEBUG_SUBSYSTEM S_LDLM
 
-#include <lustre_dlm.h>
-#include <obd_class.h>
-#include <obd.h>
+#include "../include/lustre_dlm.h"
+#include "../include/obd_class.h"
+#include "../include/obd.h"
 
 #include "ldlm_internal.h"
 
@@ -95,18 +95,18 @@ int ldlm_expired_completion_wait(void *d
 	struct obd_device *obd;
 
 	if (lock->l_conn_export == NULL) {
-		static cfs_time_t next_dump = 0, last_dump = 0;
+		static unsigned long next_dump = 0, last_dump = 0;
 
 		LCONSOLE_WARN("lock timed out (enqueued at "CFS_TIME_T", "
 			      CFS_DURATION_T"s ago)\n",
 			      lock->l_last_activity,
-			      cfs_time_sub(cfs_time_current_sec(),
+			      cfs_time_sub(get_seconds(),
 					   lock->l_last_activity));
 		LDLM_DEBUG(lock, "lock timed out (enqueued at "CFS_TIME_T", "
 			   CFS_DURATION_T"s ago); not entering recovery in "
 			   "server code, just going back to sleep",
 			   lock->l_last_activity,
-			   cfs_time_sub(cfs_time_current_sec(),
+			   cfs_time_sub(get_seconds(),
 					lock->l_last_activity));
 		if (cfs_time_after(cfs_time_current(), next_dump)) {
 			last_dump = next_dump;
@@ -125,7 +125,7 @@ int ldlm_expired_completion_wait(void *d
 	LDLM_ERROR(lock, "lock timed out (enqueued at "CFS_TIME_T", "
 		  CFS_DURATION_T"s ago), entering recovery for %s@%s",
 		  lock->l_last_activity,
-		  cfs_time_sub(cfs_time_current_sec(), lock->l_last_activity),
+		  cfs_time_sub(get_seconds(), lock->l_last_activity),
 		  obd2cli_tgt(obd), imp->imp_connection->c_remote_uuid.uuid);
 
 	return 0;
@@ -160,7 +160,7 @@ static int ldlm_completion_tail(struct l
 		LDLM_DEBUG(lock, "client-side enqueue: destroyed");
 		result = -EIO;
 	} else {
-		delay = cfs_time_sub(cfs_time_current_sec(),
+		delay = cfs_time_sub(get_seconds(),
 				     lock->l_last_activity);
 		LDLM_DEBUG(lock, "client-side enqueue: granted after "
 			   CFS_DURATION_T"s", delay);
@@ -592,7 +592,7 @@ int ldlm_cli_enqueue_fini(struct obd_exp
 					      LDLM_FL_NO_TIMEOUT);
 	unlock_res_and_lock(lock);
 
-	CDEBUG(D_INFO, "local: %p, remote cookie: "LPX64", flags: 0x%llx\n",
+	CDEBUG(D_INFO, "local: %p, remote cookie: %#llx, flags: 0x%llx\n",
 	       lock, reply->lock_handle.cookie, *flags);
 
 	/* If enqueue returned a blocked lock but the completion handler has
@@ -1276,8 +1276,7 @@ int ldlm_cli_update_pool(struct ptlrpc_r
 	 * server-side namespace is not possible. */
 	if (lustre_msg_get_slv(req->rq_repmsg) == 0 ||
 	    lustre_msg_get_limit(req->rq_repmsg) == 0) {
-		DEBUG_REQ(D_HA, req, "Zero SLV or Limit found "
-			  "(SLV: "LPU64", Limit: %u)",
+		DEBUG_REQ(D_HA, req, "Zero SLV or Limit found (SLV: %llu, Limit: %u)",
 			  lustre_msg_get_slv(req->rq_repmsg),
 			  lustre_msg_get_limit(req->rq_repmsg));
 		return 0;
@@ -1447,10 +1446,10 @@ static ldlm_policy_res_t ldlm_cancel_lru
 						 int unused, int added,
 						 int count)
 {
-	cfs_time_t cur = cfs_time_current();
+	unsigned long cur = cfs_time_current();
 	struct ldlm_pool *pl = &ns->ns_pool;
 	__u64 slv, lvf, lv;
-	cfs_time_t la;
+	unsigned long la;
 
 	/* Stop LRU processing when we reach past @count or have checked all
 	 * locks in LRU. */
@@ -1508,9 +1507,8 @@ static ldlm_policy_res_t ldlm_cancel_age
 {
 	/* Stop LRU processing if young lock is found and we reach past count */
 	return ((added >= count) &&
-		cfs_time_before(cfs_time_current(),
-				cfs_time_add(lock->l_last_used,
-					     ns->ns_max_age))) ?
+		time_before(cfs_time_current(),
+			    cfs_time_add(lock->l_last_used, ns->ns_max_age))) ?
 		LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK;
 }
 
@@ -1768,7 +1766,7 @@ int ldlm_cancel_lru(struct ldlm_namespac
 int ldlm_cancel_resource_local(struct ldlm_resource *res,
 			       struct list_head *cancels,
 			       ldlm_policy_data_t *policy,
-			       ldlm_mode_t mode, int lock_flags,
+			       ldlm_mode_t mode, __u64 lock_flags,
 			       ldlm_cancel_flags_t cancel_flags, void *opaque)
 {
 	struct ldlm_lock *lock;
@@ -1894,7 +1892,7 @@ int ldlm_cli_cancel_unused_resource(stru
 	res = ldlm_resource_get(ns, NULL, res_id, 0, 0);
 	if (res == NULL) {
 		/* This is not a problem. */
-		CDEBUG(D_INFO, "No resource "LPU64"\n", res_id->name[0]);
+		CDEBUG(D_INFO, "No resource %llu\n", res_id->name[0]);
 		return 0;
 	}
 
@@ -2105,8 +2103,8 @@ static int replay_lock_interpret(const s
 
 	lock = ldlm_handle2lock(&aa->lock_handle);
 	if (!lock) {
-		CERROR("received replay ack for unknown local cookie "LPX64
-		       " remote cookie "LPX64 " from server %s id %s\n",
+		CERROR("received replay ack for unknown local cookie %#llx"
+		       " remote cookie %#llx from server %s id %s\n",
 		       aa->lock_handle.cookie, reply->lock_handle.cookie,
 		       req->rq_export->exp_client_uuid.uuid,
 		       libcfs_id2str(req->rq_peer));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,10 +40,9 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LDLM
-# include <lustre_dlm.h>
-
-#include <lustre_fid.h>
-#include <obd_class.h>
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_fid.h"
+#include "../include/obd_class.h"
 #include "ldlm_internal.h"
 
 struct kmem_cache *ldlm_resource_slab, *ldlm_lock_slab;
@@ -72,7 +71,7 @@ extern unsigned int ldlm_cancel_unused_l
  * DDOS. */
 unsigned int ldlm_dump_granted_max = 256;
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 static ssize_t lprocfs_wr_dump_ns(struct file *file, const char *buffer,
 				  size_t count, loff_t *off)
 {
@@ -190,13 +189,15 @@ static int lprocfs_lru_size_seq_show(str
 	return lprocfs_rd_uint(m, nr);
 }
 
-static ssize_t lprocfs_lru_size_seq_write(struct file *file, const char *buffer,
-				      size_t count, loff_t *off)
+static ssize_t lprocfs_lru_size_seq_write(struct file *file,
+					const char __user *buffer,
+					size_t count, loff_t *off)
 {
 	struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private;
-	char dummy[MAX_STRING_SIZE + 1], *end;
+	char dummy[MAX_STRING_SIZE + 1];
 	unsigned long tmp;
 	int lru_resize;
+	int err;
 
 	dummy[MAX_STRING_SIZE] = '\0';
 	if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
@@ -228,8 +229,8 @@ static ssize_t lprocfs_lru_size_seq_writ
 		return count;
 	}
 
-	tmp = simple_strtoul(dummy, &end, 0);
-	if (dummy == end) {
+	err = kstrtoul(dummy, 10, &tmp);
+	if (err != 0) {
 		CERROR("invalid value written\n");
 		return -EINVAL;
 	}
@@ -382,12 +383,12 @@ int ldlm_namespace_proc_register(struct
 	return 0;
 }
 #undef MAX_STRING_SIZE
-#else /* LPROCFS */
+#else /* CONFIG_PROC_FS */
 
 #define ldlm_namespace_proc_unregister(ns)      ({;})
 #define ldlm_namespace_proc_register(ns)	({0;})
 
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 static unsigned ldlm_res_hop_hash(struct cfs_hash *hs,
 				  const void *key, unsigned mask)
@@ -854,9 +855,8 @@ void ldlm_namespace_free_prior(struct ld
 {
 	int rc;
 
-	if (!ns) {
+	if (!ns)
 		return;
-	}
 
 	spin_lock(&ns->ns_lock);
 	ns->ns_stopping = 1;
@@ -888,9 +888,8 @@ void ldlm_namespace_free_prior(struct ld
  */
 void ldlm_namespace_free_post(struct ldlm_namespace *ns)
 {
-	if (!ns) {
+	if (!ns)
 		return;
-	}
 
 	/* Make sure that nobody can find this ns in its list. */
 	ldlm_namespace_unregister(ns, ns->ns_client);
@@ -1135,9 +1134,9 @@ ldlm_resource_get(struct ldlm_namespace
 		OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);
 		rc = ns->ns_lvbo->lvbo_init(res);
 		if (rc < 0) {
-			CERROR("%s: lvbo_init failed for resource "LPX64":"
-			       LPX64": rc = %d\n", ns->ns_obd->obd_name,
-			       name->name[0], name->name[1], rc);
+			CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n",
+			       ns->ns_obd->obd_name, name->name[0],
+			       name->name[1], rc);
 			if (res->lr_lvb_data) {
 				OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);
 				res->lr_lvb_data = NULL;
@@ -1371,7 +1370,7 @@ void ldlm_namespace_dump(int level, stru
 	       ldlm_ns_name(ns), atomic_read(&ns->ns_bref),
 	       ns_is_client(ns) ? "client" : "server");
 
-	if (cfs_time_before(cfs_time_current(), ns->ns_next_dump))
+	if (time_before(cfs_time_current(), ns->ns_next_dump))
 		return;
 
 	cfs_hash_for_each_nolock(ns->ns_rs_hash,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/l_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/l_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ldlm/l_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ldlm/l_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,10 +35,10 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LDLM
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <lustre_dlm.h>
-#include <lustre_lib.h>
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_lib.h"
 
 /**
  * Lock a lock and its resource.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/debug.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/debug.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 
 # define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include "tracefile.h"
 
 static char debug_file_name[1024];
@@ -342,8 +342,8 @@ void libcfs_debug_dumplog_internal(void
 
 	if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0) {
 		snprintf(debug_file_name, sizeof(debug_file_name) - 1,
-			 "%s.%ld." LPLD, libcfs_debug_file_path_arr,
-			 cfs_time_current_sec(), (long_ptr_t)arg);
+			 "%s.%ld.%ld", libcfs_debug_file_path_arr,
+			 get_seconds(), (long_ptr_t)arg);
 		printk(KERN_ALERT "LustreError: dumping log to %s\n",
 		       debug_file_name);
 		cfs_tracefile_dump_all_pages(debug_file_name);
@@ -463,7 +463,7 @@ EXPORT_SYMBOL(libcfs_debug_set_level);
 void libcfs_log_goto(struct libcfs_debug_msg_data *msgdata, const char *label,
 		     long_ptr_t rc)
 {
-	libcfs_debug_msg(msgdata, "Process leaving via %s (rc=" LPLU " : " LPLD
-			 " : " LPLX ")\n", label, (ulong_ptr_t)rc, rc, rc);
+	libcfs_debug_msg(msgdata, "Process leaving via %s (rc=%lu : %ld : %#lx)\n",
+			 label, (ulong_ptr_t)rc, rc, rc);
 }
 EXPORT_SYMBOL(libcfs_log_goto);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/fail.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/fail.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/fail.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/fail.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,16 +33,18 @@
  * Lustre is a trademark of Oracle Corporation, Inc.
  */
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 unsigned long cfs_fail_loc = 0;
-unsigned int cfs_fail_val = 0;
-wait_queue_head_t cfs_race_waitq;
-int cfs_race_state;
-
 EXPORT_SYMBOL(cfs_fail_loc);
+
+unsigned int cfs_fail_val = 0;
 EXPORT_SYMBOL(cfs_fail_val);
+
+wait_queue_head_t cfs_race_waitq;
 EXPORT_SYMBOL(cfs_race_waitq);
+
+int cfs_race_state;
 EXPORT_SYMBOL(cfs_race_state);
 
 int __cfs_fail_check_set(__u32 id, __u32 value, int set)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/hash.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/hash.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/hash.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/hash.c	2014-09-28 17:29:07.000000000 -0400
@@ -107,7 +107,7 @@
  *   table. Also, user can break the iteration by return 1 in callback.
  */
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/seq_file.h>
 
 #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
@@ -351,7 +351,7 @@ cfs_hash_dh_hnode_add(struct cfs_hash *h
 					    cfs_hash_dhead_t, dh_head);
 
 	if (dh->dh_tail != NULL) /* not empty */
-		hlist_add_after(dh->dh_tail, hnode);
+		hlist_add_behind(hnode, dh->dh_tail);
 	else /* empty list */
 		hlist_add_head(hnode, &dh->dh_head);
 	dh->dh_tail = hnode;
@@ -406,7 +406,7 @@ cfs_hash_dd_hnode_add(struct cfs_hash *h
 						cfs_hash_dhead_dep_t, dd_head);
 
 	if (dh->dd_tail != NULL) /* not empty */
-		hlist_add_after(dh->dd_tail, hnode);
+		hlist_add_behind(hnode, dh->dd_tail);
 	else /* empty list */
 		hlist_add_head(hnode, &dh->dd_head);
 	dh->dd_tail = hnode;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/heap.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/heap.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/heap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/heap.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 #define CBH_ALLOC(ptr, h)						\
 do {									\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,7 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 #define D_KUC D_OTHER
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 /* This is the kernel side (liblustre as well). */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 /** Global CPU partition table */
 struct cfs_cpt_table   *cfs_cpt_table __read_mostly = NULL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 
 /** destroy cpu-partition lock, see libcfs_private.h for more detail */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 struct cfs_var_array {
 	unsigned int		va_count;	/* # of buffers */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_string.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_string.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/libcfs_string.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
  * Author: Nathan Rutman <nathan.rutman@sun.com>
  */
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 /* Convert a text string to a bitmask */
 int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
 
 #include <linux/cpu.h>
 #include <linux/sched.h>
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 
 #ifdef CONFIG_SMP
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c	2014-09-28 17:29:07.000000000 -0400
@@ -32,12 +32,11 @@
 #include <linux/module.h>
 #include <linux/zutil.h>
 #include <crypto/internal/hash.h>
-
+#include "linux-crypto.h"
 
 #define CHKSUM_BLOCK_SIZE	1
 #define CHKSUM_DIGEST_SIZE	4
 
-
 static u32 __adler32(u32 cksum, unsigned char const *p, size_t len)
 {
 	return zlib_adler32(cksum, p, len);
@@ -135,10 +134,8 @@ int cfs_crypto_adler32_register(void)
 {
 	return crypto_register_shash(&alg);
 }
-EXPORT_SYMBOL(cfs_crypto_adler32_register);
 
 void cfs_crypto_adler32_unregister(void)
 {
 	crypto_unregister_shash(&alg);
 }
-EXPORT_SYMBOL(cfs_crypto_adler32_unregister);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,8 +29,8 @@
 
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
-#include <linux/libcfs/libcfs.h>
-#include <linux/libcfs/linux/linux-crypto.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "linux-crypto.h"
 /**
  *  Array of  hash algorithm speed in MByte per second
  */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.h	2014-09-28 17:29:07.000000000 -0400
@@ -0,0 +1,29 @@
+ /*
+ * 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
+ */
+
+/**
+ * Functions for start/stop shash adler32 algorithm.
+ */
+int cfs_crypto_adler32_register(void);
+void cfs_crypto_adler32_unregister(void);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,7 +48,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 
 /*
  * Implementation of cfs_curproc API (see portals/include/libcfs/curproc.h)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,10 +55,10 @@
 
 # define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/libcfs/linux/portals_compat25.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../../../include/linux/libcfs/linux/portals_compat25.h"
 
-#include "tracefile.h"
+#include "../tracefile.h"
 
 #include <linux/kallsyms.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,7 +36,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 
 #define LNET_MINOR 240
 
@@ -99,7 +99,7 @@ int libcfs_ioctl_popdata(void *arg, void
 extern struct cfs_psdev_ops	  libcfs_psdev_ops;
 
 static int
-libcfs_psdev_open(struct inode * inode, struct file * file)
+libcfs_psdev_open(struct inode *inode, struct file *file)
 {
 	struct libcfs_device_userstate **pdu = NULL;
 	int    rc = 0;
@@ -116,7 +116,7 @@ libcfs_psdev_open(struct inode * inode,
 
 /* called when closing /dev/device */
 static int
-libcfs_psdev_release(struct inode * inode, struct file * file)
+libcfs_psdev_release(struct inode *inode, struct file *file)
 {
 	struct libcfs_device_userstate *pdu;
 	int    rc = 0;
@@ -140,9 +140,9 @@ static long libcfs_ioctl(struct file *fi
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if ( _IOC_TYPE(cmd) != IOC_LIBCFS_TYPE ||
+	if (_IOC_TYPE(cmd) != IOC_LIBCFS_TYPE ||
 	     _IOC_NR(cmd) < IOC_LIBCFS_MIN_NR  ||
-	     _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR ) {
+	     _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR) {
 		CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
 		       _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
 		return (-EINVAL);
@@ -154,7 +154,7 @@ static long libcfs_ioctl(struct file *fi
 		if (!capable(CFS_CAP_SYS_BOOT))
 			return (-EPERM);
 		panic("debugctl-invoked panic");
-		return (0);
+		return 0;
 	case IOC_LIBCFS_MEMHOG:
 		if (!capable(CFS_CAP_SYS_ADMIN))
 			return -EPERM;
@@ -167,10 +167,10 @@ static long libcfs_ioctl(struct file *fi
 		rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg);
 	else
 		rc = -EPERM;
-	return (rc);
+	return rc;
 }
 
-static struct file_operations libcfs_fops = {
+static const struct file_operations libcfs_fops = {
 	.unlocked_ioctl	= libcfs_ioctl,
 	.open		= libcfs_psdev_open,
 	.release	= libcfs_psdev_release,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 #include <linux/fs_struct.h>
 #include <linux/sched.h>
 
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 
 #if defined(CONFIG_KGDB)
 #include <asm/kgdb.h>
@@ -90,7 +90,7 @@ void cfs_timer_done(struct timer_list *t
 }
 EXPORT_SYMBOL(cfs_timer_done);
 
-void cfs_timer_arm(struct timer_list *t, cfs_time_t deadline)
+void cfs_timer_arm(struct timer_list *t, unsigned long deadline)
 {
 	mod_timer(t, deadline);
 }
@@ -108,7 +108,7 @@ int  cfs_timer_is_armed(struct timer_lis
 }
 EXPORT_SYMBOL(cfs_timer_is_armed);
 
-cfs_time_t cfs_timer_deadline(struct timer_list *t)
+unsigned long cfs_timer_deadline(struct timer_list *t)
 {
 	return t->expires;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,11 +61,11 @@
 
 # define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 #include <asm/div64.h>
-#include "tracefile.h"
+#include "../tracefile.h"
 
-static ctl_table_header_t *lnet_table_header = NULL;
+static struct ctl_table_header *lnet_table_header = NULL;
 extern char lnet_upcall[1024];
 /**
  * The path of debug log dump upcall script.
@@ -98,11 +98,9 @@ enum {
 	PSDEV_LNET_FAIL_VAL,      /* userdata for fail loc */
 };
 
-int
-proc_call_handler(void *data, int write,
-		  loff_t *ppos, void *buffer, size_t *lenp,
-		  int (*handler)(void *data, int write,
-				 loff_t pos, void *buffer, int len))
+static int proc_call_handler(void *data, int write, loff_t *ppos, void *buffer,
+			     size_t *lenp, int (*handler)(void *data, int write,
+			     loff_t pos, void *buffer, int len))
 {
 	int rc = handler(data, write, *ppos, buffer, *lenp);
 
@@ -117,7 +115,6 @@ proc_call_handler(void *data, int write,
 	}
 	return 0;
 }
-EXPORT_SYMBOL(proc_call_handler);
 
 static int __proc_dobitmasks(void *data, int write,
 			     loff_t pos, void *buffer, int nob)
@@ -160,7 +157,12 @@ static int __proc_dobitmasks(void *data,
 	return rc;
 }
 
-DECLARE_PROC_HANDLER(proc_dobitmasks)
+static int proc_dobitmasks(struct ctl_table *table, int write,
+			   void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_dobitmasks);
+}
 
 static int min_watchdog_ratelimit = 0;	  /* disable ratelimiting */
 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
@@ -174,7 +176,12 @@ static int __proc_dump_kernel(void *data
 	return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
 }
 
-DECLARE_PROC_HANDLER(proc_dump_kernel)
+static int proc_dump_kernel(struct ctl_table *table, int write,
+			    void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_dump_kernel);
+}
 
 static int __proc_daemon_file(void *data, int write,
 			      loff_t pos, void *buffer, int nob)
@@ -192,7 +199,12 @@ static int __proc_daemon_file(void *data
 	return cfs_trace_daemon_command_usrstr(buffer, nob);
 }
 
-DECLARE_PROC_HANDLER(proc_daemon_file)
+static int proc_daemon_file(struct ctl_table *table, int write,
+			    void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_daemon_file);
+}
 
 static int __proc_debug_mb(void *data, int write,
 			   loff_t pos, void *buffer, int nob)
@@ -212,26 +224,32 @@ static int __proc_debug_mb(void *data, i
 	return cfs_trace_set_debug_mb_usrstr(buffer, nob);
 }
 
-DECLARE_PROC_HANDLER(proc_debug_mb)
+static int proc_debug_mb(struct ctl_table *table, int write,
+			 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_debug_mb);
+}
 
-int LL_PROC_PROTO(proc_console_max_delay_cs)
+int proc_console_max_delay_cs(struct ctl_table *table, int write,
+			      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc, max_delay_cs;
-	ctl_table_t dummy = *table;
-	cfs_duration_t d;
+	struct ctl_table dummy = *table;
+	long d;
 
 	dummy.data = &max_delay_cs;
 	dummy.proc_handler = &proc_dointvec;
 
 	if (!write) { /* read */
 		max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
-		rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+		rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 		return rc;
 	}
 
 	/* write */
 	max_delay_cs = 0;
-	rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+	rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 	if (rc < 0)
 		return rc;
 	if (max_delay_cs <= 0)
@@ -245,24 +263,25 @@ int LL_PROC_PROTO(proc_console_max_delay
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_console_min_delay_cs)
+int proc_console_min_delay_cs(struct ctl_table *table, int write,
+			      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc, min_delay_cs;
-	ctl_table_t dummy = *table;
-	cfs_duration_t d;
+	struct ctl_table dummy = *table;
+	long d;
 
 	dummy.data = &min_delay_cs;
 	dummy.proc_handler = &proc_dointvec;
 
 	if (!write) { /* read */
 		min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
-		rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+		rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 		return rc;
 	}
 
 	/* write */
 	min_delay_cs = 0;
-	rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+	rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 	if (rc < 0)
 		return rc;
 	if (min_delay_cs <= 0)
@@ -276,23 +295,24 @@ int LL_PROC_PROTO(proc_console_min_delay
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_console_backoff)
+int proc_console_backoff(struct ctl_table *table, int write,
+			 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc, backoff;
-	ctl_table_t dummy = *table;
+	struct ctl_table dummy = *table;
 
 	dummy.data = &backoff;
 	dummy.proc_handler = &proc_dointvec;
 
 	if (!write) { /* read */
 		backoff= libcfs_console_backoff;
-		rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+		rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 		return rc;
 	}
 
 	/* write */
 	backoff = 0;
-	rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
+	rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
 	if (rc < 0)
 		return rc;
 	if (backoff <= 0)
@@ -303,19 +323,21 @@ int LL_PROC_PROTO(proc_console_backoff)
 	return rc;
 }
 
-int LL_PROC_PROTO(libcfs_force_lbug)
+int libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer,
+		      size_t *lenp, loff_t *ppos)
 {
 	if (write)
 		LBUG();
 	return 0;
 }
 
-int LL_PROC_PROTO(proc_fail_loc)
+int proc_fail_loc(struct ctl_table *table, int write, void __user *buffer,
+		  size_t *lenp, loff_t *ppos)
 {
 	int rc;
 	long old_fail_loc = cfs_fail_loc;
 
-	rc = ll_proc_dolongvec(table, write, filp, buffer, lenp, ppos);
+	rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 	if (old_fail_loc != cfs_fail_loc)
 		wake_up(&cfs_race_waitq);
 	return rc;
@@ -361,9 +383,15 @@ static int __proc_cpt_table(void *data,
 		LIBCFS_FREE(buf, len);
 	return rc;
 }
-DECLARE_PROC_HANDLER(proc_cpt_table)
 
-static ctl_table_t lnet_table[] = {
+static int proc_cpt_table(struct ctl_table *table, int write,
+			   void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return proc_call_handler(table->data, write, ppos, buffer, lenp,
+				 __proc_cpt_table);
+}
+
+static struct ctl_table lnet_table[] = {
 	/*
 	 * NB No .strategy entries have been provided since sysctl(8) prefers
 	 * to go via /proc for portability.
@@ -516,7 +544,7 @@ static ctl_table_t lnet_table[] = {
 	}
 };
 
-static ctl_table_t top_table[] = {
+static struct ctl_table top_table[] = {
 	{
 		.procname = "lnet",
 		.mode     = 0555,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,7 +35,7 @@
  */
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../../include/linux/libcfs/libcfs.h"
 
 #include <linux/if.h>
 #include <linux/in.h>
@@ -46,16 +46,31 @@
 int
 libcfs_sock_ioctl(int cmd, unsigned long arg)
 {
+	mm_segment_t	oldmm = get_fs();
 	struct socket  *sock;
-	int	     rc;
+	int		rc;
+	struct file    *sock_filp;
 
 	rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
 	if (rc != 0) {
 		CERROR ("Can't create socket: %d\n", rc);
 		return rc;
 	}
-	rc = kernel_sock_ioctl(sock, cmd, arg);
-	sock_release(sock);
+
+	sock_filp = sock_alloc_file(sock, 0, NULL);
+	if (IS_ERR(sock_filp)) {
+		sock_release(sock);
+		rc = PTR_ERR(sock_filp);
+		goto out;
+	}
+
+	set_fs(KERNEL_DS);
+	if (sock_filp->f_op->unlocked_ioctl)
+		rc = sock_filp->f_op->unlocked_ioctl(sock_filp, cmd, arg);
+	set_fs(oldmm);
+
+	fput(sock_filp);
+out:
 	return rc;
 }
 
@@ -183,8 +198,6 @@ libcfs_ipif_enumerate (char ***namesp)
 		rc = -ENOMEM;
 		goto out1;
 	}
-	/* NULL out all names[i] */
-	memset (names, 0, nfound * sizeof(*names));
 
 	for (i = 0; i < nfound; i++) {
 
@@ -532,7 +545,7 @@ libcfs_sock_accept (struct socket **news
 	newsock->ops = sock->ops;
 
 	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(cfs_sk_sleep(sock->sk), &wait);
+	add_wait_queue(sk_sleep(sock->sk), &wait);
 
 	rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
 	if (rc == -EAGAIN) {
@@ -541,7 +554,7 @@ libcfs_sock_accept (struct socket **news
 		rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
 	}
 
-	remove_wait_queue(cfs_sk_sleep(sock->sk), &wait);
+	remove_wait_queue(sk_sleep(sock->sk), &wait);
 	set_current_state(TASK_RUNNING);
 
 	if (rc != 0)
@@ -560,7 +573,7 @@ EXPORT_SYMBOL(libcfs_sock_accept);
 void
 libcfs_sock_abort_accept (struct socket *sock)
 {
-	wake_up_all(cfs_sk_sleep(sock->sk));
+	wake_up_all(sk_sleep(sock->sk));
 }
 
 EXPORT_SYMBOL(libcfs_sock_abort_accept);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,8 +37,8 @@
 #define DEBUG_SUBSYSTEM S_LNET
 #define LUSTRE_TRACEFILE_PRIVATE
 
-#include <linux/libcfs/libcfs.h>
-#include "tracefile.h"
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../tracefile.h"
 
 /* percents to share the total debug memory for each type */
 static unsigned int pages_factor[CFS_TCD_TYPE_MAX] = {
@@ -112,8 +112,6 @@ void cfs_tracefile_fini_arch(void)
 		kfree(cfs_trace_data[i]);
 		cfs_trace_data[i] = NULL;
 	}
-
-	fini_rwsem(&cfs_tracefile_sem);
 }
 
 void cfs_tracefile_read_lock(void)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -16,6 +16,3 @@ libcfs-all-objs := debug.o fail.o nidstr
 		   libcfs_mem.o libcfs_lock.o
 
 libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs)
-
-ccflags-y := -I$(src)/../include
-ccflags-y += -I$(src)/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/module.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/module.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/module.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,10 +36,10 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/libcfs/libcfs_crypto.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/lnet.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/libcfs/libcfs_crypto.h"
+#include "../../include/linux/lnet/lib-lnet.h"
+#include "../../include/linux/lnet/lnet.h"
 #include "tracefile.h"
 
 void
@@ -439,9 +439,6 @@ static void exit_libcfs_module(void)
 		printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
 		       rc);
 
-	fini_rwsem(&ioctl_list_sem);
-	fini_rwsem(&cfs_tracefile_sem);
-
 	libcfs_arch_cleanup();
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/nidstrings.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/nidstrings.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/nidstrings.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/nidstrings.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,8 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lnet.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../../include/linux/lnet/lnet.h"
 
 /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
  * consistent in all conversion functions.  Some code fragments are copied
@@ -74,8 +74,7 @@ libcfs_next_nidstring(void)
 	spin_lock_irqsave(&libcfs_nidstring_lock, flags);
 
 	str = libcfs_nidstrings[libcfs_nidstring_idx++];
-	if (libcfs_nidstring_idx ==
-	    sizeof(libcfs_nidstrings)/sizeof(libcfs_nidstrings[0]))
+	if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings))
 		libcfs_nidstring_idx = 0;
 
 	spin_unlock_irqrestore(&libcfs_nidstring_lock, flags);
@@ -198,7 +197,7 @@ static struct netstrfns  libcfs_netstrfn
 	{/* .nf_type      */  -1},
 };
 
-const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
+const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns);
 
 int
 libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/prng.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/prng.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/prng.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/prng.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@
  * algorithm recommended by Marsaglia
 */
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 /*
 From: George Marsaglia <geo@stat.fsu.edu>
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,7 +44,7 @@
 #define LUSTRE_TRACEFILE_PRIVATE
 #include "tracefile.h"
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 /* XXX move things up to the top, comment */
 union cfs_trace_data_union (*cfs_trace_data[TCD_MAX_TYPES])[NR_CPUS] __cacheline_aligned;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/tracefile.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #ifndef __LIBCFS_TRACEFILE_H__
 #define __LIBCFS_TRACEFILE_H__
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 #include "linux/linux-tracefile.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/upcall_cache.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/upcall_cache.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/upcall_cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/upcall_cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@
  */
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/lucache.h>
+#include "../../include/linux/libcfs/lucache.h"
 
 static struct upcall_cache_entry *alloc_entry(struct upcall_cache *cache,
 					      __u64 key, void *args)
@@ -68,7 +68,7 @@ static void free_entry(struct upcall_cac
 		cache->uc_ops->free_entry(cache, entry);
 
 	list_del(&entry->ue_hash);
-	CDEBUG(D_OTHER, "destroy cache entry %p for key "LPU64"\n",
+	CDEBUG(D_OTHER, "destroy cache entry %p for key %llu\n",
 	       entry, entry->ue_key);
 	LIBCFS_FREE(entry, sizeof(*entry));
 }
@@ -117,13 +117,12 @@ static int check_unlink_entry(struct upc
 			      struct upcall_cache_entry *entry)
 {
 	if (UC_CACHE_IS_VALID(entry) &&
-	    cfs_time_before(cfs_time_current(), entry->ue_expire))
+	    time_before(cfs_time_current(), entry->ue_expire))
 		return 0;
 
 	if (UC_CACHE_IS_ACQUIRING(entry)) {
 		if (entry->ue_acquire_expire == 0 ||
-		    cfs_time_before(cfs_time_current(),
-				    entry->ue_acquire_expire))
+		    time_before(cfs_time_current(), entry->ue_acquire_expire))
 			return 0;
 
 		UC_CACHE_SET_EXPIRED(entry);
@@ -230,7 +229,7 @@ find_again:
 		if (UC_CACHE_IS_ACQUIRING(entry)) {
 			/* we're interrupted or upcall failed in the middle */
 			rc = left > 0 ? -EINTR : -ETIMEDOUT;
-			CERROR("acquire for key "LPU64": error %d\n",
+			CERROR("acquire for key %llu: error %d\n",
 			       entry->ue_key, rc);
 			put_entry(cache, entry);
 			GOTO(out, entry = ERR_PTR(rc));
@@ -303,7 +302,7 @@ int upcall_cache_downcall(struct upcall_
 	}
 
 	if (!found) {
-		CDEBUG(D_OTHER, "%s: upcall for key "LPU64" not expected\n",
+		CDEBUG(D_OTHER, "%s: upcall for key %llu not expected\n",
 		       cache->uc_name, key);
 		/* haven't found, it's possible */
 		spin_unlock(&cache->uc_lock);
@@ -311,19 +310,19 @@ int upcall_cache_downcall(struct upcall_
 	}
 
 	if (err) {
-		CDEBUG(D_OTHER, "%s: upcall for key "LPU64" returned %d\n",
+		CDEBUG(D_OTHER, "%s: upcall for key %llu returned %d\n",
 		       cache->uc_name, entry->ue_key, err);
 		GOTO(out, rc = -EINVAL);
 	}
 
 	if (!UC_CACHE_IS_ACQUIRING(entry)) {
-		CDEBUG(D_RPCTRACE,"%s: found uptodate entry %p (key "LPU64")\n",
+		CDEBUG(D_RPCTRACE,"%s: found uptodate entry %p (key %llu)\n",
 		       cache->uc_name, entry, entry->ue_key);
 		GOTO(out, rc = 0);
 	}
 
 	if (UC_CACHE_IS_INVALID(entry) || UC_CACHE_IS_EXPIRED(entry)) {
-		CERROR("%s: found a stale entry %p (key "LPU64") in ioctl\n",
+		CERROR("%s: found a stale entry %p (key %llu) in ioctl\n",
 		       cache->uc_name, entry, entry->ue_key);
 		GOTO(out, rc = -EINVAL);
 	}
@@ -337,7 +336,7 @@ int upcall_cache_downcall(struct upcall_
 
 	entry->ue_expire = cfs_time_shift(cache->uc_entry_expire);
 	UC_CACHE_SET_VALID(entry);
-	CDEBUG(D_OTHER, "%s: created upcall cache entry %p for key "LPU64"\n",
+	CDEBUG(D_OTHER, "%s: created upcall cache entry %p for key %llu\n",
 	       cache->uc_name, entry, entry->ue_key);
 out:
 	if (rc) {
@@ -402,11 +401,10 @@ void upcall_cache_flush_one(struct upcal
 	}
 
 	if (found) {
-		CWARN("%s: flush entry %p: key "LPU64", ref %d, fl %x, "
-		      "cur %lu, ex %ld/%ld\n",
+		CWARN("%s: flush entry %p: key %llu, ref %d, fl %x, cur %lu, ex %ld/%ld\n",
 		      cache->uc_name, entry, entry->ue_key,
 		      atomic_read(&entry->ue_refcount), entry->ue_flags,
-		      cfs_time_current_sec(), entry->ue_acquire_expire,
+		      get_seconds(), entry->ue_acquire_expire,
 		      entry->ue_expire);
 		UC_CACHE_SET_EXPIRED(entry);
 		if (!atomic_read(&entry->ue_refcount))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/workitem.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/workitem.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/libcfs/workitem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/libcfs/workitem.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 
 #define DEBUG_SUBSYSTEM S_LNET
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 #define CFS_WS_NAME_LEN	 16
 
@@ -365,6 +365,7 @@ cfs_wi_sched_create(char *name, struct c
 		return -ENOMEM;
 
 	strncpy(sched->ws_name, name, CFS_WS_NAME_LEN);
+	sched->ws_name[CFS_WS_NAME_LEN - 1] = '\0';
 	sched->ws_cptab = cptab;
 	sched->ws_cpt = cpt;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/dcache.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/dcache.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/dcache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/dcache.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,10 +40,10 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <obd_support.h>
-#include <lustre_lite.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_dlm.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_dlm.h"
 
 #include "llite_internal.h"
 
@@ -213,8 +213,8 @@ void ll_intent_drop_lock(struct lookup_i
 
 		handle.cookie = it->d.lustre.it_lock_handle;
 
-		CDEBUG(D_DLMTRACE, "releasing lock with cookie "LPX64
-		       " from it %p\n", handle.cookie, it);
+		CDEBUG(D_DLMTRACE, "releasing lock with cookie %#llx from it %p\n",
+		       handle.cookie, it);
 		ldlm_lock_decref(&handle, it->d.lustre.it_lock_mode);
 
 		/* bug 494: intent_release may be called multiple times, from
@@ -223,8 +223,8 @@ void ll_intent_drop_lock(struct lookup_i
 		if (it->d.lustre.it_remote_lock_mode != 0) {
 			handle.cookie = it->d.lustre.it_remote_lock_handle;
 
-			CDEBUG(D_DLMTRACE, "releasing remote lock with cookie"
-			       LPX64" from it %p\n", handle.cookie, it);
+			CDEBUG(D_DLMTRACE, "releasing remote lock with cookie%#llx from it %p\n",
+			       handle.cookie, it);
 			ldlm_lock_decref(&handle,
 					 it->d.lustre.it_remote_lock_mode);
 			it->d.lustre.it_remote_lock_mode = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/dir.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/dir.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/dir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/dir.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,13 +48,13 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
-#include <lustre_fid.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_fid.h"
 #include "llite_internal.h"
 
 /*
@@ -158,7 +158,7 @@ static int ll_dir_filler(void *_hash, st
 	int i;
 	int rc;
 
-	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash "LPU64"\n",
+	CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash %llu\n",
 	       inode->i_ino, inode->i_generation, inode, hash);
 
 	LASSERT(max_pages > 0 && max_pages <= MD_MAX_BRW_PAGES);
@@ -302,9 +302,9 @@ static struct page *ll_dir_page_locate(s
 				*start = le64_to_cpu(dp->ldp_hash_start);
 				*end   = le64_to_cpu(dp->ldp_hash_end);
 			}
-			LASSERTF(*start <= *hash, "start = "LPX64",end = "
-				 LPX64",hash = "LPX64"\n", *start, *end, *hash);
-			CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash "LPU64"\n",
+			LASSERTF(*start <= *hash, "start = %#llx,end = %#llx,hash = %#llx\n",
+				 *start, *end, *hash);
+			CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash %llu\n",
 			       offset, *start, *end, *hash);
 			if (*hash > *end) {
 				ll_release_page(page, 0);
@@ -376,7 +376,7 @@ struct page *ll_get_dir_page(struct inod
 		if (request)
 			ptlrpc_req_finished(request);
 		if (rc < 0) {
-			CERROR("lock enqueue: "DFID" at "LPU64": rc %d\n",
+			CERROR("lock enqueue: "DFID" at %llu: rc %d\n",
 				PFID(ll_inode2fid(dir)), hash, rc);
 			return ERR_PTR(rc);
 		}
@@ -396,7 +396,7 @@ struct page *ll_get_dir_page(struct inod
 	mutex_lock(&lli->lli_readdir_mutex);
 	page = ll_dir_page_locate(dir, &lhash, &start, &end);
 	if (IS_ERR(page)) {
-		CERROR("dir page locate: "DFID" at "LPU64": rc %ld\n",
+		CERROR("dir page locate: "DFID" at %llu: rc %ld\n",
 		       PFID(ll_inode2fid(dir)), lhash, PTR_ERR(page));
 		GOTO(out_unlock, page);
 	} else if (page != NULL) {
@@ -420,7 +420,7 @@ struct page *ll_get_dir_page(struct inod
 	page = read_cache_page(mapping, hash_x_index(hash, hash64),
 			       ll_dir_filler, &lhash);
 	if (IS_ERR(page)) {
-		CERROR("read cache page: "DFID" at "LPU64": rc %ld\n",
+		CERROR("read cache page: "DFID" at %llu: rc %ld\n",
 		       PFID(ll_inode2fid(dir)), hash, PTR_ERR(page));
 		GOTO(out_unlock, page);
 	}
@@ -428,14 +428,14 @@ struct page *ll_get_dir_page(struct inod
 	wait_on_page_locked(page);
 	(void)kmap(page);
 	if (!PageUptodate(page)) {
-		CERROR("page not updated: "DFID" at "LPU64": rc %d\n",
+		CERROR("page not updated: "DFID" at %llu: rc %d\n",
 		       PFID(ll_inode2fid(dir)), hash, -5);
 		goto fail;
 	}
 	if (!PageChecked(page))
 		ll_check_page(dir, page);
 	if (PageError(page)) {
-		CERROR("page error: "DFID" at "LPU64": rc %d\n",
+		CERROR("page error: "DFID" at %llu: rc %d\n",
 		       PFID(ll_inode2fid(dir)), hash, -5);
 		goto fail;
 	}
@@ -452,10 +452,9 @@ hash_collision:
 	}
 	if (end == start) {
 		LASSERT(start == lhash);
-		CWARN("Page-wide hash collision: "LPU64"\n", end);
+		CWARN("Page-wide hash collision: %llu\n", end);
 		if (BITS_PER_LONG == 32 && hash64)
-			CWARN("Real page-wide hash collision at ["LPU64" "LPU64
-			      "] with hash "LPU64"\n",
+			CWARN("Real page-wide hash collision at [%llu %llu] with hash %llu\n",
 			      le64_to_cpu(dp->ldp_hash_start),
 			      le64_to_cpu(dp->ldp_hash_end), hash);
 		/*
@@ -926,8 +925,7 @@ static int ll_ioc_copy_start(struct supe
 		iput(inode);
 		if (rc != 0) {
 			CDEBUG(D_HSM, "Could not read file data version of "
-				      DFID" (rc = %d). Archive request ("
-				      LPX64") could not be done.\n",
+				      DFID" (rc = %d). Archive request (%#llx) could not be done.\n",
 				      PFID(&copy->hc_hai.hai_fid), rc,
 				      copy->hc_hai.hai_cookie);
 			hpk.hpk_flags |= HP_FLAG_RETRY;
@@ -1023,7 +1021,7 @@ static int ll_ioc_copy_end(struct super_
 		    (copy->hc_data_version != data_version)) {
 			CDEBUG(D_HSM, "File data version mismatched. "
 			      "File content was changed during archiving. "
-			       DFID", start:"LPX64" current:"LPX64"\n",
+			       DFID", start:%#llx current:%#llx\n",
 			       PFID(&copy->hc_hai.hai_fid),
 			       copy->hc_data_version, data_version);
 			/* File was changed, send error to cdt. Do not ask for
@@ -1266,7 +1264,7 @@ static long ll_dir_ioctl(struct file *fi
 		if (mdtidx < 0)
 			return mdtidx;
 
-		if (put_user((int)mdtidx, (int*)arg))
+		if (put_user((int)mdtidx, (int *)arg))
 			return -EFAULT;
 
 		return 0;
@@ -1501,7 +1499,7 @@ out_rmdir:
 				GOTO(out_req, rc = -EFAULT);
 			rc = -EOVERFLOW;
 		}
-	skip_lmm:
+skip_lmm:
 		if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) {
 			struct lov_user_mds_data *lmdp;
 			lstat_t st = { 0 };
@@ -1525,7 +1523,7 @@ out_rmdir:
 				GOTO(out_req, rc = -EFAULT);
 		}
 
-	out_req:
+out_req:
 		ptlrpc_req_finished(request);
 		if (filename)
 			ll_putname(filename);
@@ -1589,9 +1587,9 @@ out_rmdir:
 		if (copy_to_user(&lumd->lmd_st, &st, sizeof(st)))
 			GOTO(free_lsm, rc = -EFAULT);
 
-	free_lsm:
+free_lsm:
 		obd_free_memmd(sbi->ll_dt_exp, &lsm);
-	free_lmm:
+free_lmm:
 		OBD_FREE_LARGE(lmm, lmmsize);
 		return rc;
 	}
@@ -1653,7 +1651,7 @@ out_rmdir:
 				CDEBUG(D_QUOTA, "copy_to_user failed\n");
 			GOTO(out_poll, rc);
 		}
-	out_poll:
+out_poll:
 		OBD_FREE_PTR(check);
 		return rc;
 	}
@@ -1702,9 +1700,9 @@ out_rmdir:
 				rc = -EFAULT;
 		}
 
-	out_quotactl_20:
+out_quotactl_20:
 		OBD_FREE_PTR(qctl_20);
-	out_quotactl_18:
+out_quotactl_18:
 		OBD_FREE_PTR(qctl_18);
 		return rc;
 	}
@@ -1726,7 +1724,7 @@ out_rmdir:
 		if (rc == 0 && copy_to_user((void *)arg,qctl,sizeof(*qctl)))
 			rc = -EFAULT;
 
-	out_quotactl:
+out_quotactl:
 		OBD_FREE_PTR(qctl);
 		return rc;
 	}
@@ -1778,7 +1776,7 @@ out_rmdir:
 			return -EFAULT;
 		return 0;
 	case LL_IOC_GET_CONNECT_FLAGS: {
-		return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void*)arg);
+		return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void *)arg);
 	}
 	case OBD_IOC_CHANGELOG_SEND:
 	case OBD_IOC_CHANGELOG_CLEAR:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/file.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/file.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/file.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/file.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,14 +41,14 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LLITE
-#include <lustre_dlm.h>
-#include <lustre_lite.h>
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_lite.h"
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include "llite_internal.h"
-#include <lustre/ll_fiemap.h>
+#include "../include/lustre/ll_fiemap.h"
 
-#include "cl_object.h"
+#include "../include/cl_object.h"
 
 static int
 ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg);
@@ -140,7 +140,7 @@ static int ll_close_inode_openhandle(str
 		 * XXX: in case of LMV, is this correct to access
 		 * ->exp_handle?
 		 */
-		CERROR("Invalid MDC connection handle "LPX64"\n",
+		CERROR("Invalid MDC connection handle %#llx\n",
 		       ll_i2mdexp(inode)->exp_handle.h_cookie);
 		GOTO(out, rc = 0);
 	}
@@ -290,7 +290,7 @@ static int ll_md_close(struct obd_export
 	   we can skip talking to MDS */
 	if (file->f_dentry->d_inode) { /* Can this ever be false? */
 		int lockmode;
-		int flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
+		__u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
 		struct lustre_handle lockh;
 		struct inode *inode = file->f_dentry->d_inode;
 		ldlm_policy_data_t policy = {.l_inodebits={MDS_INODELOCK_OPEN}};
@@ -471,7 +471,7 @@ void ll_ioepoch_open(struct ll_inode_inf
 {
 	if (ioepoch && lli->lli_ioepoch != ioepoch) {
 		lli->lli_ioepoch = ioepoch;
-		CDEBUG(D_INODE, "Epoch "LPU64" opened on "DFID"\n",
+		CDEBUG(D_INODE, "Epoch %llu opened on "DFID"\n",
 		       ioepoch, PFID(&lli->lli_fid));
 	}
 }
@@ -1008,7 +1008,7 @@ int ll_merge_lvb(const struct lu_env *en
 		if (lvb.lvb_mtime < attr->cat_mtime)
 			lvb.lvb_mtime = attr->cat_mtime;
 
-		CDEBUG(D_VFSTRACE, DFID" updating i_size "LPU64"\n",
+		CDEBUG(D_VFSTRACE, DFID" updating i_size %llu\n",
 				PFID(&lli->lli_fid), attr->cat_size);
 		cl_isize_write_nolock(inode, attr->cat_size);
 
@@ -2623,7 +2623,7 @@ ll_file_flock(struct file *file, int cmd
 	struct md_op_data *op_data;
 	struct lustre_handle lockh = {0};
 	ldlm_policy_data_t flock = {{0}};
-	int flags = 0;
+	__u64 flags = 0;
 	int rc;
 	int rc2 = 0;
 
@@ -2708,9 +2708,9 @@ ll_file_flock(struct file *file, int cmd
 	if (IS_ERR(op_data))
 		return PTR_ERR(op_data);
 
-	CDEBUG(D_DLMTRACE, "inode=%lu, pid=%u, flags=%#x, mode=%u, "
-	       "start="LPU64", end="LPU64"\n", inode->i_ino, flock.l_flock.pid,
-	       flags, einfo.ei_mode, flock.l_flock.start, flock.l_flock.end);
+	CDEBUG(D_DLMTRACE, "inode=%lu, pid=%u, flags=%#llx, mode=%u, start=%llu, end=%llu\n",
+	       inode->i_ino, flock.l_flock.pid, flags, einfo.ei_mode,
+	       flock.l_flock.start, flock.l_flock.end);
 
 	rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL,
 			op_data, &lockh, &flock, 0, NULL /* req */, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_capa.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_capa.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_capa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_capa.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,11 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include <linux/fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/file.h>
 #include <linux/kmod.h>
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 
 /* for obd_capa.c_list, client capa might stay in three places:
@@ -63,16 +63,16 @@ static struct list_head *ll_capa_list =
 struct timer_list ll_capa_timer;
 /* for debug: indicate whether capa on llite is enabled or not */
 static atomic_t ll_capa_debug = ATOMIC_INIT(0);
-static unsigned long long ll_capa_renewed = 0;
-static unsigned long long ll_capa_renewal_noent = 0;
-static unsigned long long ll_capa_renewal_failed = 0;
-static unsigned long long ll_capa_renewal_retries = 0;
+static unsigned long long ll_capa_renewed;
+static unsigned long long ll_capa_renewal_noent;
+static unsigned long long ll_capa_renewal_failed;
+static unsigned long long ll_capa_renewal_retries;
 
 static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa);
 
-static inline void update_capa_timer(struct obd_capa *ocapa, cfs_time_t expiry)
+static inline void update_capa_timer(struct obd_capa *ocapa, unsigned long expiry)
 {
-	if (cfs_time_before(expiry, ll_capa_timer.expires) ||
+	if (time_before(expiry, ll_capa_timer.expires) ||
 	    !timer_pending(&ll_capa_timer)) {
 		mod_timer(&ll_capa_timer, expiry);
 		DEBUG_CAPA(D_SEC, &ocapa->c_capa,
@@ -80,7 +80,7 @@ static inline void update_capa_timer(str
 	}
 }
 
-static inline cfs_time_t capa_renewal_time(struct obd_capa *ocapa)
+static inline unsigned long capa_renewal_time(struct obd_capa *ocapa)
 {
 	return cfs_time_sub(ocapa->c_expiry,
 			    cfs_time_seconds(ocapa->c_capa.lc_timeout) / 2);
@@ -88,7 +88,7 @@ static inline cfs_time_t capa_renewal_ti
 
 static inline int capa_is_to_expire(struct obd_capa *ocapa)
 {
-	return cfs_time_beforeq(capa_renewal_time(ocapa), cfs_time_current());
+	return time_before_eq(capa_renewal_time(ocapa), cfs_time_current());
 }
 
 static inline int have_expired_capa(void)
@@ -359,7 +359,7 @@ struct obd_capa *ll_osscapa_get(struct i
 		ocapa = NULL;
 
 		if (atomic_read(&ll_capa_debug)) {
-			CERROR("no capability for "DFID" opc "LPX64"\n",
+			CERROR("no capability for "DFID" opc %#llx\n",
 			       PFID(&lli->lli_fid), opc);
 			atomic_set(&ll_capa_debug, 0);
 		}
@@ -511,7 +511,7 @@ struct obd_capa *ll_add_capa(struct inod
 	return ocapa;
 }
 
-static inline void delay_capa_renew(struct obd_capa *oc, cfs_time_t delay)
+static inline void delay_capa_renew(struct obd_capa *oc, unsigned long delay)
 {
 	/* NB: set a fake expiry for this capa to prevent it renew too soon */
 	oc->c_expiry = cfs_time_add(oc->c_expiry, cfs_time_seconds(delay));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_close.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_close.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_close.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_close.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,7 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 
 /** records that a write is in flight */
@@ -170,7 +170,7 @@ void ll_ioepoch_close(struct inode *inod
 			GOTO(out, 0);
 		}
 	}
-	CDEBUG(D_INODE, "Epoch "LPU64" closed on "DFID"\n",
+	CDEBUG(D_INODE, "Epoch %llu closed on "DFID"\n",
 	       ll_i2info(inode)->lli_ioepoch, PFID(&lli->lli_fid));
 	op_data->op_flags |= MF_EPOCH_CLOSE;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -36,16 +36,16 @@
 
 #ifndef LLITE_INTERNAL_H
 #define LLITE_INTERNAL_H
-#include <lustre_debug.h>
-#include <lustre_ver.h>
-#include <lustre_disk.h>  /* for s2sbi */
-#include <lustre_eacl.h>
+#include "../include/lustre_debug.h"
+#include "../include/lustre_ver.h"
+#include "../include/lustre_disk.h"	/* for s2sbi */
+#include "../include/lustre_eacl.h"
 
 /* for struct cl_lock_descr and struct cl_io */
-#include <cl_object.h>
-#include <lclient.h>
-#include <lustre_mdc.h>
-#include <linux/lustre_intent.h>
+#include "../include/cl_object.h"
+#include "../include/lclient.h"
+#include "../include/lustre_mdc.h"
+#include "../include/linux/lustre_intent.h"
 #include <linux/compat.h>
 #include <linux/posix_acl_xattr.h>
 
@@ -145,7 +145,7 @@ struct ll_inode_info {
 	 * capability needs renewal */
 	atomic_t		    lli_open_count;
 	struct obd_capa		*lli_mds_capa;
-	cfs_time_t		      lli_rmtperm_time;
+	unsigned long		      lli_rmtperm_time;
 
 	/* handle is to be sent to MDS later on done_writing and setattr.
 	 * Open handle data are needed for the recovery to reconstruct
@@ -213,7 +213,7 @@ struct ll_inode_info {
 			struct mutex			f_write_mutex;
 
 			struct rw_semaphore		f_glimpse_sem;
-			cfs_time_t			f_glimpse_time;
+			unsigned long			f_glimpse_time;
 			struct list_head			f_agl_list;
 			__u64				f_agl_index;
 
@@ -670,7 +670,7 @@ void ll_ra_read_ex(struct file *f, struc
 struct ll_ra_read *ll_ra_read_get(struct file *f);
 
 /* llite/lproc_llite.c */
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
 				struct super_block *sb, char *osc, char *mdc);
 void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi);
@@ -1432,7 +1432,7 @@ static inline void ll_set_lock_data(stru
 		if (it->d.lustre.it_remote_lock_mode) {
 			handle.cookie = it->d.lustre.it_remote_lock_handle;
 			CDEBUG(D_DLMTRACE, "setting l_data to inode %p"
-			       "(%lu/%u) for remote lock "LPX64"\n", inode,
+			       "(%lu/%u) for remote lock %#llx\n", inode,
 			       inode->i_ino, inode->i_generation,
 			       handle.cookie);
 			md_set_lock_data(exp, &handle.cookie, inode, NULL);
@@ -1441,7 +1441,7 @@ static inline void ll_set_lock_data(stru
 		handle.cookie = it->d.lustre.it_lock_handle;
 
 		CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)"
-		       " for lock "LPX64"\n", inode, inode->i_ino,
+		       " for lock %#llx\n", inode, inode->i_ino,
 		       inode->i_generation, handle.cookie);
 
 		md_set_lock_data(exp, &handle.cookie, inode,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_lib.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_lib.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,15 +44,15 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 
-#include <lustre_lite.h>
-#include <lustre_ha.h>
-#include <lustre_dlm.h>
-#include <lprocfs_status.h>
-#include <lustre_disk.h>
-#include <lustre_param.h>
-#include <lustre_log.h>
-#include <cl_object.h>
-#include <obd_cksum.h>
+#include "../include/lustre_lite.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_disk.h"
+#include "../include/lustre_param.h"
+#include "../include/lustre_log.h"
+#include "../include/cl_object.h"
+#include "../include/obd_cksum.h"
 #include "llite_internal.h"
 
 struct kmem_cache *ll_file_data_slab;
@@ -152,7 +152,7 @@ static void ll_free_sbi(struct super_blo
 static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 				    struct vfsmount *mnt)
 {
-	struct inode *root = 0;
+	struct inode *root = NULL;
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct obd_device *obd;
 	struct obd_capa *oc = NULL;
@@ -426,7 +426,7 @@ static int client_common_fill_super(stru
 	if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
 		data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE;
 
-	CDEBUG(D_RPCTRACE, "ocd_connect_flags: "LPX64" ocd_version: %d "
+	CDEBUG(D_RPCTRACE, "ocd_connect_flags: %#llx ocd_version: %d "
 	       "ocd_grant: %d\n", data->ocd_connect_flags,
 	       data->ocd_version, data->ocd_grant);
 
@@ -568,7 +568,7 @@ static int client_common_fill_super(stru
 	if (sb->s_root == NULL) {
 		CERROR("%s: can't make root dentry\n",
 			ll_get_fsname(sb, NULL, 0));
-		GOTO(out_root, err = -ENOMEM);
+		GOTO(out_lock_cn_cb, err = -ENOMEM);
 	}
 
 	sbi->ll_sdev_orig = sb->s_dev;
@@ -1296,7 +1296,7 @@ static int ll_setattr_done_writing(struc
 	if (!S_ISREG(inode->i_mode))
 		return 0;
 
-	CDEBUG(D_INODE, "Epoch "LPU64" closed on "DFID" for truncate\n",
+	CDEBUG(D_INODE, "Epoch %llu closed on "DFID" for truncate\n",
 	       op_data->op_ioepoch, PFID(&lli->lli_fid));
 
 	op_data->op_flags = MF_EPOCH_CLOSE;
@@ -1377,7 +1377,7 @@ int ll_setattr_raw(struct dentry *dentry
 		 * OST maximum object size and number of stripes.  This
 		 * needs another check in addition to the VFS check above. */
 		if (attr->ia_size > ll_file_maxbytes(inode)) {
-			CDEBUG(D_INODE,"file "DFID" too large %llu > "LPU64"\n",
+			CDEBUG(D_INODE,"file "DFID" too large %llu > %llu\n",
 			       PFID(&lli->lli_fid), attr->ia_size,
 			       ll_file_maxbytes(inode));
 			return -EFBIG;
@@ -1412,7 +1412,7 @@ int ll_setattr_raw(struct dentry *dentry
 	if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
 		CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n",
 		       LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime),
-		       cfs_time_current_sec());
+		       get_seconds());
 
 	/* If we are changing file size, file content is modified, flag it. */
 	if (attr->ia_valid & ATTR_SIZE) {
@@ -1537,12 +1537,14 @@ int ll_setattr(struct dentry *de, struct
 	      !(attr->ia_mode & S_ISGID))))
 		attr->ia_valid |= ATTR_FORCE;
 
-	if ((mode & S_ISUID) &&
+	if ((attr->ia_valid & ATTR_MODE) &&
+	    (mode & S_ISUID) &&
 	    !(attr->ia_mode & S_ISUID) &&
 	    !(attr->ia_valid & ATTR_KILL_SUID))
 		attr->ia_valid |= ATTR_KILL_SUID;
 
-	if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
+	if ((attr->ia_valid & ATTR_MODE) &&
+	    ((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
 	    !(attr->ia_mode & S_ISGID) &&
 	    !(attr->ia_valid & ATTR_KILL_SGID))
 		attr->ia_valid |= ATTR_KILL_SGID;
@@ -1565,7 +1567,7 @@ int ll_statfs_internal(struct super_bloc
 
 	osfs->os_type = sb->s_magic;
 
-	CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
+	CDEBUG(D_SUPER, "MDC blocks %llu/%llu objects %llu/%llu\n",
 	       osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
 
 	if (sbi->ll_flags & LL_SBI_LAZYSTATFS)
@@ -1577,7 +1579,7 @@ int ll_statfs_internal(struct super_bloc
 		return rc;
 	}
 
-	CDEBUG(D_SUPER, "OSC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n",
+	CDEBUG(D_SUPER, "OSC blocks %llu/%llu objects %llu/%llu\n",
 	       obd_osfs.os_bavail, obd_osfs.os_blocks, obd_osfs.os_ffree,
 	       obd_osfs.os_files);
 
@@ -1604,7 +1606,7 @@ int ll_statfs(struct dentry *de, struct
 	struct obd_statfs osfs;
 	int rc;
 
-	CDEBUG(D_VFSTRACE, "VFS Op: at "LPU64" jiffies\n", get_jiffies_64());
+	CDEBUG(D_VFSTRACE, "VFS Op: at %llu jiffies\n", get_jiffies_64());
 	ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STAFS, 1);
 
 	/* Some amount of caching on the client is allowed */
@@ -1697,9 +1699,9 @@ void ll_update_inode(struct inode *inode
 	}
 	if (body->valid & OBD_MD_FLMTIME) {
 		if (body->mtime > LTIME_S(inode->i_mtime)) {
-			CDEBUG(D_INODE, "setting ino %lu mtime from %lu "
-			       "to "LPU64"\n", inode->i_ino,
-			       LTIME_S(inode->i_mtime), body->mtime);
+			CDEBUG(D_INODE, "setting ino %lu mtime from %lu to %llu\n",
+			       inode->i_ino, LTIME_S(inode->i_mtime),
+			       body->mtime);
 			LTIME_S(inode->i_mtime) = body->mtime;
 		}
 		lli->lli_lvb.lvb_mtime = body->mtime;
@@ -1997,7 +1999,7 @@ void ll_umount_begin(struct super_block
 
 	obd = class_exp2obd(sbi->ll_md_exp);
 	if (obd == NULL) {
-		CERROR("Invalid MDC connection handle "LPX64"\n",
+		CERROR("Invalid MDC connection handle %#llx\n",
 		       sbi->ll_md_exp->exp_handle.h_cookie);
 		return;
 	}
@@ -2005,7 +2007,7 @@ void ll_umount_begin(struct super_block
 
 	obd = class_exp2obd(sbi->ll_dt_exp);
 	if (obd == NULL) {
-		CERROR("Invalid LOV connection handle "LPX64"\n",
+		CERROR("Invalid LOV connection handle %#llx\n",
 		       sbi->ll_dt_exp->exp_handle.h_cookie);
 		return;
 	}
@@ -2245,7 +2247,7 @@ struct md_op_data * ll_prep_md_op_data(s
 	op_data->op_name = name;
 	op_data->op_namelen = namelen;
 	op_data->op_mode = mode;
-	op_data->op_mod_time = cfs_time_current_sec();
+	op_data->op_mod_time = get_seconds();
 	op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
 	op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
 	op_data->op_cap = cfs_curproc_cap_pack();
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_mmap.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_mmap.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_mmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_mmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,9 +47,9 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
-#include <linux/lustre_compat25.h>
+#include "../include/linux/lustre_compat25.h"
 
 static const struct vm_operations_struct ll_file_vm_ops;
 
@@ -449,7 +449,7 @@ int ll_teardown_mmaps(struct address_spa
 {
 	int rc = -ENOENT;
 
-	LASSERTF(last > first, "last "LPU64" first "LPU64"\n", last, first);
+	LASSERTF(last > first, "last %llu first %llu\n", last, first);
 	if (mapping_mapped(mapping)) {
 		rc = 0;
 		unmap_mapping_range(mapping, first + PAGE_CACHE_SIZE - 1,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_nfs.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_nfs.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_nfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_nfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,7 +42,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LLITE
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 #include <linux/exportfs.h>
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_rmtacl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_rmtacl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/llite_rmtacl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/llite_rmtacl.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,8 +44,8 @@
 
 #ifdef CONFIG_FS_POSIX_ACL
 
-#include <lustre_lite.h>
-#include <lustre_eacl.h>
+#include "../include/lustre_lite.h"
+#include "../include/lustre_eacl.h"
 #include "llite_internal.h"
 
 static inline __u32 rce_hashfunc(uid_t id)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/lloop.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/lloop.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/lloop.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/lloop.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,8 +103,8 @@
 
 #include <asm/uaccess.h>
 
-#include <lustre_lib.h>
-#include <lustre_lite.h>
+#include "../include/lustre_lib.h"
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 
 #define LLOOP_MAX_SEGMENTS	LNET_MAX_IOV
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,10 +35,10 @@
  */
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
-#include <lprocfs_status.h>
+#include "../include/lustre_lite.h"
+#include "../include/lprocfs_status.h"
 #include <linux/seq_file.h>
-#include <obd_support.h>
+#include "../include/obd_support.h"
 
 #include "llite_internal.h"
 #include "vvp_internal.h"
@@ -82,7 +82,7 @@ static int ll_kbytestotal_seq_show(struc
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -105,7 +105,7 @@ static int ll_kbytesfree_seq_show(struct
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -128,7 +128,7 @@ static int ll_kbytesavail_seq_show(struc
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -145,7 +145,7 @@ static int ll_filestotal_seq_show(struct
 				cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 				OBD_STATFS_NODELAY);
 	if (!rc)
-		 rc = seq_printf(m, LPU64"\n", osfs.os_files);
+		 rc = seq_printf(m, "%llu\n", osfs.os_files);
 	return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_filestotal);
@@ -161,7 +161,7 @@ static int ll_filesfree_seq_show(struct
 				cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 				OBD_STATFS_NODELAY);
 	if (!rc)
-		 rc = seq_printf(m, LPU64"\n", osfs.os_ffree);
+		 rc = seq_printf(m, "%llu\n", osfs.os_ffree);
 	return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_filesfree);
@@ -811,38 +811,39 @@ static ssize_t ll_xattr_cache_seq_write(
 LPROC_SEQ_FOPS(ll_xattr_cache);
 
 static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
-	{ "uuid",	  &ll_sb_uuid_fops,	  0, 0 },
+	{ "uuid",	  &ll_sb_uuid_fops,	  NULL, 0 },
 	//{ "mntpt_path",   ll_rd_path,	     0, 0 },
-	{ "fstype",       &ll_fstype_fops,	  0, 0 },
-	{ "site",	  &ll_site_stats_fops,    0, 0 },
-	{ "blocksize",    &ll_blksize_fops,	  0, 0 },
-	{ "kbytestotal",  &ll_kbytestotal_fops,   0, 0 },
-	{ "kbytesfree",   &ll_kbytesfree_fops,    0, 0 },
-	{ "kbytesavail",  &ll_kbytesavail_fops,   0, 0 },
-	{ "filestotal",   &ll_filestotal_fops,    0, 0 },
-	{ "filesfree",    &ll_filesfree_fops,	  0, 0 },
-	{ "client_type",  &ll_client_type_fops,   0, 0 },
+	{ "fstype",       &ll_fstype_fops,	  NULL, 0 },
+	{ "site",	  &ll_site_stats_fops,    NULL, 0 },
+	{ "blocksize",    &ll_blksize_fops,	  NULL, 0 },
+	{ "kbytestotal",  &ll_kbytestotal_fops,   NULL, 0 },
+	{ "kbytesfree",   &ll_kbytesfree_fops,    NULL, 0 },
+	{ "kbytesavail",  &ll_kbytesavail_fops,   NULL, 0 },
+	{ "filestotal",   &ll_filestotal_fops,    NULL, 0 },
+	{ "filesfree",    &ll_filesfree_fops,	  NULL, 0 },
+	{ "client_type",  &ll_client_type_fops,   NULL, 0 },
 	//{ "filegroups",   lprocfs_rd_filegroups,  0, 0 },
-	{ "max_read_ahead_mb", &ll_max_readahead_mb_fops, 0 },
-	{ "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops, 0 },
-	{ "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops, 0 },
-	{ "max_cached_mb",    &ll_max_cached_mb_fops, 0 },
-	{ "checksum_pages",   &ll_checksum_fops, 0 },
-	{ "max_rw_chunk",     &ll_max_rw_chunk_fops, 0 },
-	{ "stats_track_pid",  &ll_track_pid_fops, 0 },
-	{ "stats_track_ppid", &ll_track_ppid_fops, 0 },
-	{ "stats_track_gid",  &ll_track_gid_fops, 0 },
-	{ "statahead_max",    &ll_statahead_max_fops, 0 },
-	{ "statahead_agl",    &ll_statahead_agl_fops, 0 },
-	{ "statahead_stats",  &ll_statahead_stats_fops, 0, 0 },
-	{ "lazystatfs",       &ll_lazystatfs_fops, 0 },
-	{ "max_easize",       &ll_max_easize_fops, 0, 0 },
-	{ "default_easize",   &ll_defult_easize_fops, 0, 0 },
-	{ "max_cookiesize",   &ll_max_cookiesize_fops, 0, 0 },
-	{ "default_cookiesize", &ll_defult_cookiesize_fops, 0, 0 },
-	{ "sbi_flags",	      &ll_sbi_flags_fops, 0, 0 },
-	{ "xattr_cache",      &ll_xattr_cache_fops, 0, 0 },
-	{ 0 }
+	{ "max_read_ahead_mb", &ll_max_readahead_mb_fops, NULL },
+	{ "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops,
+		NULL },
+	{ "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops, NULL },
+	{ "max_cached_mb",    &ll_max_cached_mb_fops, NULL },
+	{ "checksum_pages",   &ll_checksum_fops, NULL },
+	{ "max_rw_chunk",     &ll_max_rw_chunk_fops, NULL },
+	{ "stats_track_pid",  &ll_track_pid_fops, NULL },
+	{ "stats_track_ppid", &ll_track_ppid_fops, NULL },
+	{ "stats_track_gid",  &ll_track_gid_fops, NULL },
+	{ "statahead_max",    &ll_statahead_max_fops, NULL },
+	{ "statahead_agl",    &ll_statahead_agl_fops, NULL },
+	{ "statahead_stats",  &ll_statahead_stats_fops, NULL, 0 },
+	{ "lazystatfs",       &ll_lazystatfs_fops, NULL },
+	{ "max_easize",       &ll_max_easize_fops, NULL, 0 },
+	{ "default_easize",   &ll_defult_easize_fops, NULL, 0 },
+	{ "max_cookiesize",   &ll_max_cookiesize_fops, NULL, 0 },
+	{ "default_cookiesize", &ll_defult_cookiesize_fops, NULL, 0 },
+	{ "sbi_flags",	      &ll_sbi_flags_fops, NULL, 0 },
+	{ "xattr_cache",      &ll_xattr_cache_fops, NULL, 0 },
+	{ NULL }
 };
 
 #define MAX_STRING_SIZE 128
@@ -909,7 +910,7 @@ void ll_stats_ops_tally(struct ll_sb_inf
 		 sbi->ll_stats_track_id == current->pid)
 		lprocfs_counter_add(sbi->ll_stats, op, count);
 	else if (sbi->ll_stats_track_type == STATS_TRACK_PPID &&
-		 sbi->ll_stats_track_id == current->parent->pid)
+		 sbi->ll_stats_track_id == current->real_parent->pid)
 		lprocfs_counter_add(sbi->ll_stats, op, count);
 	else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
 		 sbi->ll_stats_track_id ==
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -9,6 +9,3 @@ lustre-y := dcache.o dir.o file.o llite_
 
 lustre-$(CONFIG_PROC_FS) += lproc_llite.o
 llite_lloop-y := lloop.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/namei.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/namei.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/namei.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/namei.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,11 +44,11 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <obd_support.h>
-#include <lustre_fid.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
-#include <lustre_ver.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_ver.h"
 #include "llite_internal.h"
 
 static int ll_create_it(struct inode *, struct dentry *,
@@ -105,7 +105,7 @@ static int ll_set_inode(struct inode *in
 	lli->lli_fid = body->fid1;
 	if (unlikely(!(body->valid & OBD_MD_FLTYPE))) {
 		CERROR("Can not initialize inode "DFID" without object type: "
-		       "valid = "LPX64"\n", PFID(&lli->lli_fid), body->valid);
+		       "valid = %#llx\n", PFID(&lli->lli_fid), body->valid);
 		return -EINVAL;
 	}
 
@@ -758,7 +758,7 @@ static void ll_update_times(struct ptlrp
 	LASSERT(body);
 	if (body->valid & OBD_MD_FLMTIME &&
 	    body->mtime > LTIME_S(inode->i_mtime)) {
-		CDEBUG(D_INODE, "setting ino %lu mtime from %lu to "LPU64"\n",
+		CDEBUG(D_INODE, "setting ino %lu mtime from %lu to %llu\n",
 		       inode->i_ino, LTIME_S(inode->i_mtime), body->mtime);
 		LTIME_S(inode->i_mtime) = body->mtime;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/remote_perm.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/remote_perm.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/remote_perm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/remote_perm.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,12 +46,12 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-#include <lustre_lite.h>
-#include <lustre_ha.h>
-#include <lustre_dlm.h>
-#include <lprocfs_status.h>
-#include <lustre_disk.h>
-#include <lustre_param.h>
+#include "../include/lustre_lite.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_disk.h"
+#include "../include/lustre_param.h"
 #include "llite_internal.h"
 
 struct kmem_cache *ll_remote_perm_cachep = NULL;
@@ -249,7 +249,7 @@ int lustre_check_remote_perm(struct inod
 	struct ptlrpc_request *req = NULL;
 	struct mdt_remote_perm *perm;
 	struct obd_capa *oc;
-	cfs_time_t save;
+	unsigned long save;
 	int i = 0, rc;
 
 	do {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/rw26.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/rw26.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/rw26.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/rw26.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,9 +55,9 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
-#include <linux/lustre_compat25.h>
+#include "../include/linux/lustre_compat25.h"
 
 /**
  * Implements Linux VM address_space::invalidatepage() method. This method is
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/rw.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/rw.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/rw.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/rw.c	2014-09-28 17:29:07.000000000 -0400
@@ -54,10 +54,10 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
-#include <obd_cksum.h>
+#include "../include/lustre_lite.h"
+#include "../include/obd_cksum.h"
 #include "llite_internal.h"
-#include <linux/lustre_compat25.h>
+#include "../include/linux/lustre_compat25.h"
 
 /**
  * Finalizes cl-data before exiting typical address_space operation. Dual to
@@ -496,14 +496,9 @@ static int ll_read_ahead_page(const stru
 	struct cl_object *clob  = ll_i2info(mapping->host)->lli_clob;
 	struct cl_page   *page;
 	enum ra_stat      which = _NR_RA_STAT; /* keep gcc happy */
-	unsigned int      gfp_mask;
 	int	       rc    = 0;
 	const char       *msg   = NULL;
 
-	gfp_mask = GFP_HIGHUSER & ~__GFP_WAIT;
-#ifdef __GFP_NOWARN
-	gfp_mask |= __GFP_NOWARN;
-#endif
 	vmpage = grab_cache_page_nowait(mapping, index);
 	if (vmpage != NULL) {
 		/* Check if vmpage was truncated or reclaimed */
@@ -601,7 +596,7 @@ stride_pg_count(pgoff_t st_off, unsigned
 	if (end_left > st_pgs)
 		end_left = st_pgs;
 
-	CDEBUG(D_READA, "start "LPU64", end "LPU64" start_left %lu end_left %lu \n",
+	CDEBUG(D_READA, "start %llu, end %llu start_left %lu end_left %lu \n",
 	       start, end, start_left, end_left);
 
 	if (start == end)
@@ -1013,7 +1008,7 @@ void ras_update(struct ll_sb_info *sbi,
 		kms_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
 			    PAGE_CACHE_SHIFT;
 
-		CDEBUG(D_READA, "kmsp "LPU64" mwp %lu mp %lu\n", kms_pages,
+		CDEBUG(D_READA, "kmsp %llu mwp %lu mp %lu\n", kms_pages,
 		       ra->ra_max_read_ahead_whole_pages, ra->ra_max_pages_per_file);
 
 		if (kms_pages &&
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/statahead.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/statahead.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/statahead.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/statahead.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,9 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <obd_support.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
 #include "llite_internal.h"
 
 #define SA_OMITTED_ENTRY_MAX 8ULL
@@ -206,7 +206,7 @@ ll_sa_entry_alloc(struct ll_statahead_in
 	if (unlikely(entry == NULL))
 		return ERR_PTR(-ENOMEM);
 
-	CDEBUG(D_READA, "alloc sa entry %.*s(%p) index "LPU64"\n",
+	CDEBUG(D_READA, "alloc sa entry %.*s(%p) index %llu\n",
 	       len, name, entry, index);
 
 	entry->se_index = index;
@@ -325,7 +325,7 @@ static void ll_sa_entry_put(struct ll_st
 			     struct ll_sa_entry *entry)
 {
 	if (atomic_dec_and_test(&entry->se_refcount)) {
-		CDEBUG(D_READA, "free sa entry %.*s(%p) index "LPU64"\n",
+		CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n",
 		       entry->se_qstr.len, entry->se_qstr.name, entry,
 		       entry->se_index);
 
@@ -528,8 +528,8 @@ static void ll_sai_put(struct ll_statahe
 		spin_unlock(&lli->lli_sa_lock);
 
 		if (sai->sai_sent > sai->sai_replied)
-			CDEBUG(D_READA,"statahead for dir "DFID" does not "
-			      "finish: [sent:"LPU64"] [replied:"LPU64"]\n",
+			CDEBUG(D_READA,"statahead for dir "DFID
+			      " does not finish: [sent:%llu] [replied:%llu]\n",
 			      PFID(&lli->lli_fid),
 			      sai->sai_sent, sai->sai_replied);
 
@@ -587,7 +587,7 @@ static void ll_agl_trigger(struct inode
 	 *    affect the performance.
 	 */
 	if (lli->lli_glimpse_time != 0 &&
-	    cfs_time_before(cfs_time_shift(-1), lli->lli_glimpse_time)) {
+	    time_before(cfs_time_shift(-1), lli->lli_glimpse_time)) {
 		up_write(&lli->lli_glimpse_sem);
 		lli->lli_agl_index = 0;
 		iput(inode);
@@ -595,7 +595,7 @@ static void ll_agl_trigger(struct inode
 	}
 
 	CDEBUG(D_READA, "Handling (init) async glimpse: inode = "
-	       DFID", idx = "LPU64"\n", PFID(&lli->lli_fid), index);
+	       DFID", idx = %llu\n", PFID(&lli->lli_fid), index);
 
 	cl_agl(inode);
 	lli->lli_agl_index = 0;
@@ -603,7 +603,7 @@ static void ll_agl_trigger(struct inode
 	up_write(&lli->lli_glimpse_sem);
 
 	CDEBUG(D_READA, "Handled (init) async glimpse: inode= "
-	       DFID", idx = "LPU64", rc = %d\n",
+	       DFID", idx = %llu, rc = %d\n",
 	       PFID(&lli->lli_fid), index, rc);
 
 	iput(inode);
@@ -1081,8 +1081,7 @@ static int ll_statahead_thread(void *arg
 
 		if (IS_ERR(page)) {
 			rc = PTR_ERR(page);
-			CDEBUG(D_READA, "error reading dir "DFID" at "LPU64
-			       "/"LPU64": [rc %d] [parent %u]\n",
+			CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: [rc %d] [parent %u]\n",
 			       PFID(ll_inode2fid(dir)), pos, sai->sai_index,
 			       rc, plli->lli_opendir_pid);
 			GOTO(out, rc);
@@ -1362,8 +1361,7 @@ static int is_first_dirent(struct inode
 			struct ll_inode_info *lli = ll_i2info(dir);
 
 			rc = PTR_ERR(page);
-			CERROR("error reading dir "DFID" at "LPU64": "
-			       "[rc %d] [parent %u]\n",
+			CERROR("error reading dir "DFID" at %llu: [rc %d] [parent %u]\n",
 			       PFID(ll_inode2fid(dir)), pos,
 			       rc, lli->lli_opendir_pid);
 			break;
@@ -1479,8 +1477,8 @@ ll_sai_unplug(struct ll_statahead_info *
 		if (sa_low_hit(sai) && thread_is_running(thread)) {
 			atomic_inc(&sbi->ll_sa_wrong);
 			CDEBUG(D_READA, "Statahead for dir "DFID" hit "
-			       "ratio too low: hit/miss "LPU64"/"LPU64
-			       ", sent/replied "LPU64"/"LPU64", stopping "
+			       "ratio too low: hit/miss %llu/%llu"
+			       ", sent/replied %llu/%llu, stopping "
 			       "statahead thread\n",
 			       PFID(&lli->lli_fid), sai->sai_hit,
 			       sai->sai_miss, sai->sai_sent,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/super25.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/super25.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/super25.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/super25.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,12 +38,12 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <lustre_lite.h>
-#include <lustre_ha.h>
-#include <lustre_dlm.h>
+#include "../include/lustre_lite.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_dlm.h"
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <lprocfs_status.h>
+#include "../include/lprocfs_status.h"
 #include "llite_internal.h"
 
 static struct kmem_cache *ll_inode_cachep;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/symlink.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/symlink.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/symlink.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/symlink.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,7 +39,7 @@
 #include <linux/stat.h>
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 
 static int ll_readlink_internal(struct inode *inode,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_dev.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_dev.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,8 +41,8 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 
-#include <obd.h>
-#include <lustre_lite.h>
+#include "../include/obd.h"
+#include "../include/lustre_lite.h"
 #include "llite_internal.h"
 #include "vvp_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,7 @@
 #define VVP_INTERNAL_H
 
 
-#include <cl_object.h>
+#include "../include/cl_object.h"
 #include "llite_internal.h"
 
 int	       vvp_io_init     (const struct lu_env *env,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_io.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_io.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,8 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 
-#include <obd.h>
-#include <lustre_lite.h>
+#include "../include/obd.h"
+#include "../include/lustre_lite.h"
 
 #include "vvp_internal.h"
 
@@ -269,8 +269,10 @@ static int vvp_mmap_locks(const struct l
 			       descr->cld_mode, descr->cld_start,
 			       descr->cld_end);
 
-			if (result < 0)
+			if (result < 0) {
+				up_read(&mm->mmap_sem);
 				return result;
+			}
 
 			if (vma->vm_end - addr >= count)
 				break;
@@ -622,7 +624,7 @@ static int vvp_io_kernel_fault(struct vv
 		       page_private(vmf->page), vmf->virtual_address);
 		if (unlikely(!(cfio->fault.ft_flags & VM_FAULT_LOCKED))) {
 			lock_page(vmf->page);
-			cfio->fault.ft_flags &= VM_FAULT_LOCKED;
+			cfio->fault.ft_flags |= VM_FAULT_LOCKED;
 		}
 
 		cfio->ft_vmpage = vmf->page;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,8 +39,8 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 
-#include <obd.h>
-#include <lustre_lite.h>
+#include "../include/obd.h"
+#include "../include/lustre_lite.h"
 
 #include "vvp_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_object.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_object.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
-#include <lustre_lite.h>
+#include "../include/obd.h"
+#include "../include/lustre_lite.h"
 
 #include "vvp_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_page.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_page.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/vvp_page.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/vvp_page.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,8 @@
 #define DEBUG_SUBSYSTEM S_LLITE
 
 
-#include <obd.h>
-#include <lustre_lite.h>
+#include "../include/obd.h"
+#include "../include/lustre_lite.h"
 
 #include "vvp_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/xattr.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/xattr.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/xattr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/xattr.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,11 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <obd_support.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
-#include <lustre_ver.h>
-#include <lustre_eacl.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_ver.h"
+#include "../include/lustre_eacl.h"
 
 #include "llite_internal.h"
 
@@ -246,6 +246,7 @@ int ll_setxattr(struct dentry *dentry, c
 			int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ?
 				sizeof(*lump) : sizeof(struct lov_user_md_v3);
 
+			memset(&f, 0, sizeof(f)); /* f.f_flags is used below */
 			f.f_dentry = dentry;
 			rc = ll_lov_setstripe_ea_info(inode, &f, flags, lump,
 						      lum_size);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/xattr_cache.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/xattr_cache.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/llite/xattr_cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/llite/xattr_cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -10,10 +10,10 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <obd_support.h>
-#include <lustre_lite.h>
-#include <lustre_dlm.h>
-#include <lustre_ver.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_ver.h"
 #include "llite_internal.h"
 
 /* If we ever have hundreds of extended attributes, we might want to consider
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_fld.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_fld.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_fld.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_fld.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,14 +41,14 @@
 #include <asm/div64.h>
 #include <linux/seq_file.h>
 
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_fid.h>
-#include <lustre_lib.h>
-#include <lustre_net.h>
-#include <lustre_dlm.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/obd_support.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_dlm.h"
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 #include "lmv_internal.h"
 
 int lmv_fld_lookup(struct lmv_obd *lmv,
@@ -66,8 +66,8 @@ int lmv_fld_lookup(struct lmv_obd *lmv,
 	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
 			       LU_SEQ_RANGE_MDT, NULL);
 	if (rc) {
-		CERROR("Error while looking for mds number. Seq "LPX64
-		       ", err = %d\n", fid_seq(fid), rc);
+		CERROR("Error while looking for mds number. Seq %#llx, err = %d\n",
+		       fid_seq(fid), rc);
 		return rc;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_intent.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_intent.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_intent.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_intent.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,15 +41,14 @@
 #include <asm/div64.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
-#include <linux/lustre_intent.h>
-
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_lib.h>
-#include <lustre_net.h>
-#include <lustre_dlm.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/linux/lustre_intent.h"
+#include "../include/obd_support.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_dlm.h"
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 #include "lmv_internal.h"
 
 static int lmv_intent_remote(struct obd_export *exp, void *lmm,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,8 +37,8 @@
 #ifndef _LMV_INTERNAL_H_
 #define _LMV_INTERNAL_H_
 
-#include <lustre/lustre_idl.h>
-#include <obd.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/obd.h"
 
 #define LMV_MAX_TGT_COUNT 128
 
@@ -146,7 +146,7 @@ struct lmv_tgt_desc
 *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
 		struct lu_fid *fid);
 /* lproc_lmv.c */
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars);
 #else
 static inline void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_obd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_obd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lmv_obd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lmv_obd.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,14 +45,14 @@
 #include <linux/namei.h>
 #include <asm/uaccess.h>
 
-#include <lustre/lustre_idl.h>
-#include <obd_support.h>
-#include <lustre_lib.h>
-#include <lustre_net.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <lustre_lite.h>
-#include <lustre_fid.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_net.h"
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_lite.h"
+#include "../include/lustre_fid.h"
 #include "lmv_internal.h"
 
 static void lmv_activate_target(struct lmv_obd *lmv,
@@ -90,7 +90,7 @@ static int lmv_set_mdc_active(struct lmv
 		if (tgt == NULL || tgt->ltd_exp == NULL)
 			continue;
 
-		CDEBUG(D_INFO, "Target idx %d is %s conn "LPX64"\n", i,
+		CDEBUG(D_INFO, "Target idx %d is %s conn %#llx\n", i,
 		       tgt->ltd_uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
 
 		if (obd_uuid_equals(uuid, &tgt->ltd_uuid))
@@ -735,7 +735,7 @@ repeat_fid2path:
 		*ptr = '/';
 	}
 
-	CDEBUG(D_INFO, "%s: get path %s "DFID" rec: "LPU64" ln: %u\n",
+	CDEBUG(D_INFO, "%s: get path %s "DFID" rec: %llu ln: %u\n",
 	       tgt->ltd_exp->exp_obd->obd_name,
 	       gf->gf_path, PFID(&gf->gf_fid), gf->gf_recno,
 	       gf->gf_linkno);
@@ -1339,7 +1339,7 @@ static int lmv_setup(struct obd_device *
 	lprocfs_lmv_init_vars(&lvars);
 
 	lprocfs_obd_setup(obd, lvars.obd_vars);
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	{
 		rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
 					0444, &lmv_proc_target_fops, obd);
@@ -1715,7 +1715,7 @@ static int
 lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 		   struct lookup_intent *it, struct md_op_data *op_data,
 		   struct lustre_handle *lockh, void *lmm, int lmmsize,
-		   int extra_lock_flags)
+		   __u64 extra_lock_flags)
 {
 	struct ptlrpc_request      *req = it->d.lustre.it_data;
 	struct obd_device	  *obd = exp->exp_obd;
@@ -2173,7 +2173,7 @@ static int lmv_readpage(struct obd_expor
 	if (rc)
 		return rc;
 
-	CDEBUG(D_INODE, "READPAGE at "LPX64" from "DFID"\n",
+	CDEBUG(D_INODE, "READPAGE at %#llx from "DFID"\n",
 	       offset, PFID(&op_data->op_fid1));
 
 	tgt = lmv_find_target(lmv, &op_data->op_fid1);
@@ -2315,7 +2315,7 @@ static int lmv_get_info(const struct lu_
 
 	obd = class_exp2obd(exp);
 	if (obd == NULL) {
-		CDEBUG(D_IOCTL, "Invalid client cookie "LPX64"\n",
+		CDEBUG(D_IOCTL, "Invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
@@ -2381,7 +2381,7 @@ int lmv_set_info_async(const struct lu_e
 
 	obd = class_exp2obd(exp);
 	if (obd == NULL) {
-		CDEBUG(D_IOCTL, "Invalid client cookie "LPX64"\n",
+		CDEBUG(D_IOCTL, "Invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lproc_lmv.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lproc_lmv.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/lproc_lmv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/lproc_lmv.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,8 +38,8 @@
 
 #include <linux/seq_file.h>
 #include <asm/statfs.h>
-#include <lprocfs_status.h>
-#include <obd_class.h>
+#include "../include/lprocfs_status.h"
+#include "../include/obd_class.h"
 
 static int lmv_numobd_seq_show(struct seq_file *m, void *v)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lmv/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lmv/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,3 @@
 obj-$(CONFIG_LUSTRE_FS) += lmv.o
 lmv-y := lmv_obd.o lmv_intent.o lmv_fld.o
 lmv-$(CONFIG_PROC_FS) += lproc_lmv.o
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_cl_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_cl_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_cl_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,10 +46,10 @@
 #ifndef LOV_CL_INTERNAL_H
 #define LOV_CL_INTERNAL_H
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
-#include <cl_object.h>
+#include "../include/obd.h"
+#include "../include/cl_object.h"
 #include "lov_internal.h"
 
 /** \defgroup lov lov
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_dev.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_dev.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 #define DEBUG_SUBSYSTEM S_LOV
 
 /* class_name2obd() */
-#include <obd_class.h>
+#include "../include/obd_class.h"
 
 #include "lov_cl_internal.h"
 #include "lov_internal.h"
@@ -453,7 +453,7 @@ static int lov_process_config(const stru
 		case LCFG_LOV_ADD_INA:
 			rc = lov_cl_add_target(env, d, index);
 			if (rc != 0)
-				lov_del_target(d->ld_obd, index, 0, 0);
+				lov_del_target(d->ld_obd, index, NULL, 0);
 			break;
 		case LCFG_LOV_DEL_OBD:
 			lov_cl_del_target(env, d, index);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_ea.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_ea.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_ea.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_ea.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
 #define DEBUG_SUBSYSTEM S_LOV
 
 #include <asm/div64.h>
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_class.h>
-#include <lustre/lustre_idl.h>
+#include "../include/obd_class.h"
+#include "../include/lustre/lustre_idl.h"
 
 #include "lov_internal.h"
 
@@ -348,7 +348,7 @@ const struct lsm_operations lsm_v3_ops =
 
 void dump_lsm(unsigned int level, const struct lov_stripe_md *lsm)
 {
-	CDEBUG(level, "lsm %p, objid "DOSTID", maxbytes "LPX64", magic 0x%08X,"
+	CDEBUG(level, "lsm %p, objid "DOSTID", maxbytes %#llx, magic 0x%08X,"
 	       " stripe_size %u, stripe_count %u, refc: %d,"
 	       " layout_gen %u, pool ["LOV_POOLNAMEF"]\n", lsm,
 	       POSTID(&lsm->lsm_oi), lsm->lsm_maxbytes, lsm->lsm_magic,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,8 +37,8 @@
 #ifndef LOV_INTERNAL_H
 #define LOV_INTERNAL_H
 
-#include <obd_class.h>
-#include <lustre/lustre_user.h>
+#include "../include/obd_class.h"
+#include "../include/lustre/lustre_user.h"
 
 /* lov_do_div64(a, b) returns a % b, and a = a / b.
  * The 32-bit code is LOV-specific due to knowing about stripe limits in
@@ -252,7 +252,7 @@ int lov_prep_match_set(struct obd_export
 		       ldlm_policy_data_t *policy, __u32 mode,
 		       struct lustre_handle *lockh,
 		       struct lov_request_set **reqset);
-int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags);
+int lov_fini_match_set(struct lov_request_set *set, __u32 mode, __u64 flags);
 int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo,
 			struct lov_stripe_md *lsm,
 			__u32 mode, struct lustre_handle *lockh,
@@ -310,7 +310,7 @@ void dump_lsm(unsigned int level, const
 int lovea_destroy_object(struct lov_obd *lov, struct lov_stripe_md *lsm,
 			 struct obdo *oa, void *data);
 /* lproc_lov.c */
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 extern const struct file_operations lov_proc_target_fops;
 void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars);
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_io.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_io.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -398,7 +398,7 @@ static int lov_io_iter_init(const struct
 					   start, end);
 			rc = cl_io_iter_init(sub->sub_env, sub->sub_io);
 			lov_sub_put(sub);
-			CDEBUG(D_VFSTRACE, "shrink: %d ["LPU64", "LPU64")\n",
+			CDEBUG(D_VFSTRACE, "shrink: %d [%llu, %llu)\n",
 			       stripe, start, end);
 		} else
 			rc = PTR_ERR(sub);
@@ -436,8 +436,8 @@ static int lov_io_rw_iter_init(const str
 					      next) - io->u.ci_rw.crw_pos;
 		lio->lis_pos    = io->u.ci_rw.crw_pos;
 		lio->lis_endpos = io->u.ci_rw.crw_pos + io->u.ci_rw.crw_count;
-		CDEBUG(D_VFSTRACE, "stripe: "LPU64" chunk: ["LPU64", "LPU64") "
-		       LPU64"\n", (__u64)start, lio->lis_pos, lio->lis_endpos,
+		CDEBUG(D_VFSTRACE, "stripe: %llu chunk: [%llu, %llu) %llu\n",
+		       (__u64)start, lio->lis_pos, lio->lis_endpos,
 		       (__u64)lio->lis_io_endpos);
 	}
 	/*
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_merge.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_merge.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_merge.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_merge.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,9 +36,9 @@
 
 #define DEBUG_SUBSYSTEM S_LOV
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_class.h>
+#include "../include/obd_class.h"
 #include "lov_internal.h"
 
 /** Merge the lock value block(&lvb) attributes and KMS from each of the
@@ -61,10 +61,9 @@ int lov_merge_lvb_kms(struct lov_stripe_
 	assert_spin_locked(&lsm->lsm_lock);
 	LASSERT(lsm->lsm_lock_owner == current_pid());
 
-	CDEBUG(D_INODE, "MDT ID "DOSTID" initial value: s="LPU64" m="LPU64
-	       " a="LPU64" c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi),
-	       lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime,
-	       lvb->lvb_blocks);
+	CDEBUG(D_INODE, "MDT ID "DOSTID" initial value: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
+	       POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime,
+	       lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
 	for (i = 0; i < lsm->lsm_stripe_count; i++) {
 		struct lov_oinfo *loi = lsm->lsm_oinfo[i];
 		obd_size lov_size, tmpsize;
@@ -94,11 +93,11 @@ int lov_merge_lvb_kms(struct lov_stripe_
 		if (loi->loi_lvb.lvb_ctime > current_ctime)
 			current_ctime = loi->loi_lvb.lvb_ctime;
 
-		CDEBUG(D_INODE, "MDT ID "DOSTID" on OST[%u]: s="LPU64" m="LPU64
-		       " a="LPU64" c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi),
-		       loi->loi_ost_idx, loi->loi_lvb.lvb_size,
-		       loi->loi_lvb.lvb_mtime, loi->loi_lvb.lvb_atime,
-		       loi->loi_lvb.lvb_ctime, loi->loi_lvb.lvb_blocks);
+		CDEBUG(D_INODE, "MDT ID "DOSTID" on OST[%u]: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
+		       POSTID(&lsm->lsm_oi), loi->loi_ost_idx,
+		       loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime,
+		       loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime,
+		       loi->loi_lvb.lvb_blocks);
 	}
 
 	*kms_place = kms;
@@ -131,9 +130,9 @@ int lov_merge_lvb(struct obd_export *exp
 	if (kms_only)
 		lvb->lvb_size = kms;
 
-	CDEBUG(D_INODE, "merged for ID "DOSTID" s="LPU64" m="LPU64" a="LPU64
-	       " c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi), lvb->lvb_size,
-	       lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
+	CDEBUG(D_INODE, "merged for ID "DOSTID" s=%llu m=%llu a=%llu c=%llu b=%llu\n",
+	       POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime,
+	       lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
 	return rc;
 }
 
@@ -153,7 +152,7 @@ int lov_adjust_kms(struct obd_export *ex
 			struct lov_oinfo *loi = lsm->lsm_oinfo[stripe];
 			kms = lov_size_to_stripe(lsm, size, stripe);
 			CDEBUG(D_INODE,
-			       "stripe %d KMS %sing "LPU64"->"LPU64"\n",
+			       "stripe %d KMS %sing %llu->%llu\n",
 			       stripe, kms > loi->loi_kms ? "increase":"shrink",
 			       loi->loi_kms, kms);
 			loi_kms_set(loi, loi->loi_lvb.lvb_size = kms);
@@ -166,7 +165,7 @@ int lov_adjust_kms(struct obd_export *ex
 	kms = lov_size_to_stripe(lsm, size, stripe);
 	loi = lsm->lsm_oinfo[stripe];
 
-	CDEBUG(D_INODE, "stripe %d KMS %sincreasing "LPU64"->"LPU64"\n",
+	CDEBUG(D_INODE, "stripe %d KMS %sincreasing %llu->%llu\n",
 	       stripe, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms);
 	if (kms > loi->loi_kms)
 		loi_kms_set(loi, kms);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_obd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_obd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_obd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_obd.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,22 +42,22 @@
  */
 
 #define DEBUG_SUBSYSTEM S_LOV
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_support.h>
-#include <lustre_lib.h>
-#include <lustre_net.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_dlm.h>
-#include <lustre_mds.h>
-#include <obd_class.h>
-#include <obd_ost.h>
-#include <lprocfs_status.h>
-#include <lustre_param.h>
-#include <cl_object.h>
-#include <lclient.h> /* for cl_client_lru */
-#include <lustre/ll_fiemap.h>
-#include <lustre_fid.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_mds.h"
+#include "../include/obd_class.h"
+#include "../include/obd_ost.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_param.h"
+#include "../include/cl_object.h"
+#include "../include/lclient.h"		/* for cl_client_lru */
+#include "../include/lustre/ll_fiemap.h"
+#include "../include/lustre_fid.h"
 
 #include "lov_internal.h"
 
@@ -382,7 +382,7 @@ static int lov_set_osc_active(struct obd
 		if (!tgt->ltd_exp)
 			continue;
 
-		CDEBUG(D_INFO, "lov idx %d is %s conn "LPX64"\n",
+		CDEBUG(D_INFO, "lov idx %d is %s conn %#llx\n",
 		       index, obd_uuid2str(&tgt->ltd_uuid),
 		       tgt->ltd_exp->exp_handle.h_cookie);
 		if (obd_uuid_equals(uuid, &tgt->ltd_uuid))
@@ -727,8 +727,7 @@ void lov_fix_desc_stripe_size(__u64 *val
 		*val = LOV_DESC_STRIPE_SIZE_DEFAULT;
 	} else if (*val & (LOV_MIN_STRIPE_SIZE - 1)) {
 		*val &= ~(LOV_MIN_STRIPE_SIZE - 1);
-		LCONSOLE_WARN("Changing default stripe size to "LPU64" (a "
-			      "multiple of %u)\n",
+		LCONSOLE_WARN("Changing default stripe size to %llu (a multiple of %u)\n",
 			      *val, LOV_MIN_STRIPE_SIZE);
 	}
 }
@@ -821,7 +820,7 @@ int lov_setup(struct obd_device *obd, st
 
 	lprocfs_lov_init_vars(&lvars);
 	lprocfs_obd_setup(obd, lvars.obd_vars);
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	{
 		int rc1;
 
@@ -900,7 +899,7 @@ static int lov_cleanup(struct obd_device
 				       " deathrow=%d, lovrc=%d\n",
 				       i, lov->lov_death_row,
 				       atomic_read(&lov->lov_refcount));
-			lov_del_target(obd, i, 0, 0);
+			lov_del_target(obd, i, NULL, 0);
 		}
 		obd_putref(obd);
 		OBD_FREE(lov->lov_tgts, sizeof(*lov->lov_tgts) *
@@ -944,7 +943,7 @@ int lov_process_config_base(struct obd_d
 		GOTO(out, rc);
 	}
 	case LCFG_PARAM: {
-		struct lprocfs_static_vars lvars = { 0 };
+		struct lprocfs_static_vars lvars = { NULL };
 		struct lov_desc *desc = &(obd->u.lov.desc);
 
 		if (!desc)
@@ -1463,7 +1462,7 @@ static int lov_sync(const struct lu_env
 	if (rc)
 		return rc;
 
-	CDEBUG(D_INFO, "fsync objid "DOSTID" ["LPX64", "LPX64"]\n",
+	CDEBUG(D_INFO, "fsync objid "DOSTID" [%#llx, %#llx]\n",
 	       POSTID(&set->set_oi->oi_oa->o_oi), start, end);
 
 	list_for_each(pos, &set->set_list) {
@@ -2636,9 +2635,8 @@ static int lov_extent_calc(struct obd_ex
 	lov_do_div64(start, ssize);
 	start = start * ssize;
 
-	CDEBUG(D_DLMTRACE, "offset "LPU64", stripe %u, start "LPU64
-			   ", end "LPU64"\n", *offset, ssize, start,
-			   start + ssize - 1);
+	CDEBUG(D_DLMTRACE, "offset %llu, stripe %u, start %llu, end %llu\n",
+	       *offset, ssize, start, start + ssize - 1);
 	if (cmd == OBD_CALC_STRIPE_END) {
 		*offset = start + ssize - 1;
 	} else if (cmd == OBD_CALC_STRIPE_START) {
@@ -2818,7 +2816,7 @@ struct kmem_cache *lov_oinfo_slab;
 
 int __init lov_init(void)
 {
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc;
 
 	/* print an address of _any_ initialized kernel symbol from this
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_offset.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_offset.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_offset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_offset.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,9 +36,9 @@
 
 #define DEBUG_SUBSYSTEM S_LOV
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_class.h>
+#include "../include/obd_class.h"
 
 #include "lov_internal.h"
 
@@ -223,7 +223,7 @@ int lov_stripe_intersects(struct lov_str
 	start_side = lov_stripe_offset(lsm, start, stripeno, obd_start);
 	end_side = lov_stripe_offset(lsm, end, stripeno, obd_end);
 
-	CDEBUG(D_INODE, "["LPU64"->"LPU64"] -> [(%d) "LPU64"->"LPU64" (%d)]\n",
+	CDEBUG(D_INODE, "[%llu->%llu] -> [(%d) %llu->%llu (%d)]\n",
 	       start, end, start_side, *obd_start, *obd_end, end_side);
 
 	/* this stripe doesn't intersect the file extent when neither
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_pack.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_pack.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_pack.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_pack.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,11 +42,11 @@
 
 #define DEBUG_SUBSYSTEM S_LOV
 
-#include <lustre_net.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_user.h>
+#include "../include/lustre_net.h"
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre/lustre_user.h"
 
 #include "lov_internal.h"
 
@@ -555,7 +555,7 @@ int lov_setea(struct obd_export *exp, st
 			return rc;
 		if (ostid_id(&lmm_objects[i].l_ost_oi) > last_id) {
 			CERROR("Setting EA for object > than last id on"
-			       " ost idx %d "DOSTID" > "LPD64" \n",
+			       " ost idx %d "DOSTID" > %lld \n",
 			       lmm_objects[i].l_ost_idx,
 			       POSTID(&lmm_objects[i].l_ost_oi), last_id);
 			return -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_pool.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_pool.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_pool.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_pool.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,9 +44,9 @@
 
 #define DEBUG_SUBSYSTEM S_LOV
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
+#include "../include/obd.h"
 #include "lov_internal.h"
 
 #define pool_tgt(_p, _i) \
@@ -152,7 +152,7 @@ cfs_hash_ops_t pool_hash_operations = {
 
 };
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 /* ifdef needed for liblustre support */
 /*
  * pool /proc seq_file methods
@@ -294,7 +294,7 @@ static struct file_operations pool_proc_
 	.llseek	 = seq_lseek,
 	.release	= seq_release,
 };
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 void lov_dump_pool(int level, struct pool_desc *pool)
 {
@@ -452,7 +452,7 @@ int lov_pool_new(struct obd_device *obd,
 
 	INIT_HLIST_NODE(&new_pool->pool_hash);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	/* we need this assert seq_file is not implemented for liblustre */
 	/* get ref for /proc file */
 	lov_pool_getref(new_pool);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lov_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lov_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,11 +36,11 @@
 
 #define DEBUG_SUBSYSTEM S_LOV
 
-#include <linux/libcfs/libcfs.h>
-
-#include <obd_class.h>
-#include <lustre/lustre_idl.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
+#include "../include/obd_class.h"
+#include "../include/obd_ost.h"
+#include "../include/lustre/lustre_idl.h"
 #include "lov_internal.h"
 
 static void lov_init_set(struct lov_request_set *set)
@@ -140,16 +140,16 @@ void lov_set_add_req(struct lov_request
 
 static int lov_check_set(struct lov_obd *lov, int idx)
 {
-	int rc = 0;
-	mutex_lock(&lov->lov_lock);
-
-	if (lov->lov_tgts[idx] == NULL ||
-	    lov->lov_tgts[idx]->ltd_active ||
-	    (lov->lov_tgts[idx]->ltd_exp != NULL &&
-	     class_exp2cliimp(lov->lov_tgts[idx]->ltd_exp)->imp_connect_tried))
-		rc = 1;
+	int rc;
+	struct lov_tgt_desc *tgt;
 
+	mutex_lock(&lov->lov_lock);
+	tgt = lov->lov_tgts[idx];
+	rc = !tgt || tgt->ltd_active ||
+		(tgt->ltd_exp &&
+		 class_exp2cliimp(tgt->ltd_exp)->imp_connect_tried);
 	mutex_unlock(&lov->lov_lock);
+
 	return rc;
 }
 
@@ -194,13 +194,9 @@ out:
 	return rc;
 }
 
-extern void osc_update_enqueue(struct lustre_handle *lov_lockhp,
-			       struct lov_oinfo *loi, int flags,
-			       struct ost_lvb *lvb, __u32 mode, int rc);
-
 static int lov_update_enqueue_lov(struct obd_export *exp,
 				  struct lustre_handle *lov_lockhp,
-				  struct lov_oinfo *loi, int flags, int idx,
+				  struct lov_oinfo *loi, __u64 flags, int idx,
 				  struct ost_id *oi, int rc)
 {
 	struct lov_obd *lov = &exp->exp_obd->u.lov;
@@ -443,7 +439,7 @@ out_set:
 	return rc;
 }
 
-int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags)
+int lov_fini_match_set(struct lov_request_set *set, __u32 mode, __u64 flags)
 {
 	int rc = 0;
 
@@ -482,7 +478,7 @@ int lov_prep_match_set(struct obd_export
 		GOTO(out_set, rc = -ENOMEM);
 	lockh->cookie = set->set_lockh->llh_handle.h_cookie;
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++){
+	for (i = 0; i < lsm->lsm_stripe_count; i++) {
 		struct lov_oinfo *loi;
 		struct lov_request *req;
 		obd_off start, end;
@@ -570,7 +566,7 @@ int lov_prep_cancel_set(struct obd_expor
 	}
 	lockh->cookie = set->set_lockh->llh_handle.h_cookie;
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++){
+	for (i = 0; i < lsm->lsm_stripe_count; i++) {
 		struct lov_request *req;
 		struct lustre_handle *lov_lockhp;
 		struct lov_oinfo *loi = lsm->lsm_oinfo[i];
@@ -738,7 +734,7 @@ int lov_prep_brw_set(struct obd_export *
 
 	/* alloc and initialize lov request */
 	shift = 0;
-	for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++){
+	for (i = 0; i < oinfo->oi_md->lsm_stripe_count; i++) {
 		struct lov_oinfo *loi = NULL;
 		struct lov_request *req;
 
@@ -840,6 +836,7 @@ static int cb_getattr_update(void *cooki
 {
 	struct obd_info *oinfo = cookie;
 	struct lov_request *lovreq;
+
 	lovreq = container_of(oinfo, struct lov_request, rq_oi);
 	return lov_update_common_set(lovreq->rq_rqset, lovreq, rc);
 }
@@ -1022,6 +1019,7 @@ static int cb_setattr_update(void *cooki
 {
 	struct obd_info *oinfo = cookie;
 	struct lov_request *lovreq;
+
 	lovreq = container_of(oinfo, struct lov_request, rq_oi);
 	return lov_update_setattr_set(lovreq->rq_rqset, lovreq, rc);
 }
@@ -1080,7 +1078,7 @@ int lov_prep_setattr_set(struct obd_expo
 			if (off < 0 && req->rq_oi.oi_oa->o_size)
 				req->rq_oi.oi_oa->o_size--;
 
-			CDEBUG(D_INODE, "stripe %d has size "LPU64"/"LPU64"\n",
+			CDEBUG(D_INODE, "stripe %d has size %llu/%llu\n",
 			       i, req->rq_oi.oi_oa->o_size,
 			       oinfo->oi_oa->o_size);
 		}
@@ -1145,6 +1143,7 @@ static int cb_update_punch(void *cookie,
 {
 	struct obd_info *oinfo = cookie;
 	struct lov_request *lovreq;
+
 	lovreq = container_of(oinfo, struct lov_request, rq_oi);
 	return lov_update_punch_set(lovreq->rq_rqset, lovreq, rc);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lproc_lov.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lproc_lov.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/lproc_lov.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/lproc_lov.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,8 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <asm/statfs.h>
-#include <lprocfs_status.h>
-#include <obd_class.h>
+#include "../include/lprocfs_status.h"
+#include "../include/obd_class.h"
 #include <linux/seq_file.h>
 #include "lov_internal.h"
 
@@ -48,7 +48,7 @@ static int lov_stripesize_seq_show(struc
 
 	LASSERT(dev != NULL);
 	desc = &dev->u.lov.desc;
-	return seq_printf(m, LPU64"\n", desc->ld_default_stripe_size);
+	return seq_printf(m, "%llu\n", desc->ld_default_stripe_size);
 }
 
 static ssize_t lov_stripesize_seq_write(struct file *file, const char *buffer,
@@ -78,7 +78,7 @@ static int lov_stripeoffset_seq_show(str
 
 	LASSERT(dev != NULL);
 	desc = &dev->u.lov.desc;
-	return seq_printf(m, LPU64"\n", desc->ld_default_stripe_offset);
+	return seq_printf(m, "%llu\n", desc->ld_default_stripe_offset);
 }
 
 static ssize_t lov_stripeoffset_seq_write(struct file *file, const char *buffer,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lov/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lov/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -4,7 +4,3 @@ lov-y := lov_obd.o lov_pack.o lov_offset
 	 lov_lock.o lov_io.o lovsub_dev.o lovsub_object.o lovsub_page.o      \
 	 lovsub_lock.o lovsub_io.o lov_pool.o
 lov-$(CONFIG_PROC_FS) += lproc_lov.o
-
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/fsfilt.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/fsfilt.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/fsfilt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/fsfilt.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,8 +38,8 @@
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
-#include <linux/libcfs/libcfs.h>
-#include <lustre_fsfilt.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre_fsfilt.h"
 
 LIST_HEAD(fsfilt_types);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,8 @@
  * Author: Andreas Dilger <adilger@clusterfs.com>
  */
 #include <linux/module.h>
-#include <lustre_lib.h>
-#include <lprocfs_status.h>
+#include "../include/lustre_lib.h"
+#include "../include/lprocfs_status.h"
 
 void lprocfs_counter_add(struct lprocfs_stats *stats, int idx, long amount)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,13 +45,13 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
-#include <linux/libcfs/libcfs.h>
 #include <linux/module.h>
-#include <linux/lustre_compat25.h>
-#include <lvfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/linux/lustre_compat25.h"
+#include "../include/lvfs.h"
 
-#include <obd.h>
-#include <lustre_lib.h>
+#include "../include/obd.h"
+#include "../include/lustre_lib.h"
 
 struct lprocfs_stats *obd_memory = NULL;
 EXPORT_SYMBOL(obd_memory);
@@ -233,8 +233,8 @@ put_old:
 EXPORT_SYMBOL(lustre_rename);
 
 /* Note: dput(dchild) will *not* be called if there is an error */
-struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de,
-			     int flags)
+struct file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct dentry *de,
+			   int flags)
 {
 	struct path path = {
 		.dentry = de,
@@ -244,7 +244,7 @@ struct l_file *l_dentry_open(struct lvfs
 }
 EXPORT_SYMBOL(l_dentry_open);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
 			  struct lprocfs_counter_header *header,
 			  enum lprocfs_stats_flags flags,
@@ -286,7 +286,7 @@ __s64 lprocfs_read_helper(struct lprocfs
 	return ret;
 }
 EXPORT_SYMBOL(lprocfs_read_helper);
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS*/
 
 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
 MODULE_DESCRIPTION("Lustre VFS Filesystem Helper v0.1");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/lvfs/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/lvfs/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,6 +2,3 @@ obj-$(CONFIG_LUSTRE_FS) += lvfs.o
 
 lvfs-y := lvfs_linux.o fsfilt.o
 lvfs-$(CONFIG_PROC_FS) += lvfs_lib.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/lproc_mdc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/lproc_mdc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/lproc_mdc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/lproc_mdc.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,8 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <linux/vfs.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 
 static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
 {
@@ -172,39 +172,39 @@ LPROC_SEQ_FOPS_RW_TYPE(mdc, import);
 LPROC_SEQ_FOPS_RW_TYPE(mdc, pinger_recov);
 
 static struct lprocfs_vars lprocfs_mdc_obd_vars[] = {
-	{ "uuid",	    &mdc_uuid_fops,		0, 0 },
-	{ "ping",	    &mdc_ping_fops,		0, 0222 },
-	{ "connect_flags",  &mdc_connect_flags_fops,	0, 0 },
-	{ "blocksize",      &mdc_blksize_fops,		0, 0 },
-	{ "kbytestotal",    &mdc_kbytestotal_fops,	0, 0 },
-	{ "kbytesfree",     &mdc_kbytesfree_fops,	0, 0 },
-	{ "kbytesavail",    &mdc_kbytesavail_fops,	0, 0 },
-	{ "filestotal",     &mdc_filestotal_fops,	0, 0 },
-	{ "filesfree",      &mdc_filesfree_fops,	0, 0 },
-	/*{ "filegroups",      lprocfs_rd_filegroups,  0, 0 },*/
-	{ "mds_server_uuid", &mdc_server_uuid_fops,	0, 0 },
-	{ "mds_conn_uuid",  &mdc_conn_uuid_fops,	0, 0 },
+	{ "uuid",		&mdc_uuid_fops,			NULL, 0 },
+	{ "ping",		&mdc_ping_fops,			NULL, 0222 },
+	{ "connect_flags",	&mdc_connect_flags_fops,	NULL, 0 },
+	{ "blocksize",		&mdc_blksize_fops,		NULL, 0 },
+	{ "kbytestotal",	&mdc_kbytestotal_fops,		NULL, 0 },
+	{ "kbytesfree",		&mdc_kbytesfree_fops,		NULL, 0 },
+	{ "kbytesavail",	&mdc_kbytesavail_fops,		NULL, 0 },
+	{ "filestotal",		&mdc_filestotal_fops,		NULL, 0 },
+	{ "filesfree",		&mdc_filesfree_fops,		NULL, 0 },
+	/*{ "filegroups",	lprocfs_rd_filegroups,		NULL, 0 },*/
+	{ "mds_server_uuid",	&mdc_server_uuid_fops,		NULL, 0 },
+	{ "mds_conn_uuid",	&mdc_conn_uuid_fops,		NULL, 0 },
 	/*
 	 * FIXME: below proc entry is provided, but not in used, instead
 	 * sbi->sb_md_brw_size is used, the per obd variable should be used
 	 * when CMD is enabled, and dir pages are managed in MDC layer.
 	 * Remember to enable proc write function.
 	 */
-	{ "max_pages_per_rpc",  &mdc_obd_max_pages_per_rpc_fops, 0, 0 },
-	{ "max_rpcs_in_flight", &mdc_max_rpcs_in_flight_fops, 0, 0 },
-	{ "timeouts",		&mdc_timeouts_fops,    0, 0 },
-	{ "import",		&mdc_import_fops, 0 },
-	{ "state",		&mdc_state_fops, 0, 0 },
-	{ "hsm_nl",		&mdc_kuc_fops, 0, 0200 },
-	{ "pinger_recov",	&mdc_pinger_recov_fops, 0, 0 },
-	{ 0 }
+	{ "max_pages_per_rpc",	&mdc_obd_max_pages_per_rpc_fops, NULL, 0 },
+	{ "max_rpcs_in_flight",	&mdc_max_rpcs_in_flight_fops,	NULL, 0 },
+	{ "timeouts",		&mdc_timeouts_fops,		NULL, 0 },
+	{ "import",		&mdc_import_fops,		NULL, 0 },
+	{ "state",		&mdc_state_fops,		NULL, 0 },
+	{ "hsm_nl",		&mdc_kuc_fops,			NULL, 0200 },
+	{ "pinger_recov",	&mdc_pinger_recov_fops,		NULL, 0 },
+	{ NULL }
 };
 
 LPROC_SEQ_FOPS_RO_TYPE(mdc, numrefs);
 
 static struct lprocfs_vars lprocfs_mdc_module_vars[] = {
-	{ "num_refs",	&mdc_numrefs_fops,     0, 0 },
-	{ 0 }
+	{ "num_refs",		&mdc_numrefs_fops,		NULL, 0 },
+	{ NULL }
 };
 
 void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,3 @@
 obj-$(CONFIG_LUSTRE_FS) += mdc.o
 mdc-y := mdc_request.o mdc_reint.o mdc_lib.o mdc_locks.o
 mdc-$(CONFIG_PROC_FS) += lproc_mdc.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,10 +37,10 @@
 #ifndef _MDC_INTERNAL_H
 #define _MDC_INTERNAL_H
 
-#include <lustre_mdc.h>
-#include <lustre_mds.h>
+#include "../include/lustre_mdc.h"
+#include "../include/lustre_mds.h"
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars);
 #else
 static inline void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_lib.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_lib.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_lib.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_lib.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,8 +35,8 @@
  */
 
 #define DEBUG_SUBSYSTEM S_MDC
-#include <lustre_net.h>
-#include <lustre/lustre_idl.h>
+#include "../include/lustre_net.h"
+#include "../include/lustre/lustre_idl.h"
 #include "mdc_internal.h"
 
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_locks.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_locks.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_locks.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_locks.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,14 +38,14 @@
 
 # include <linux/module.h>
 
-#include <linux/lustre_intent.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_dlm.h>
-#include <lustre_fid.h> /* fid_res_name_eq() */
-#include <lustre_mdc.h>
-#include <lustre_net.h>
-#include <lustre_req_layout.h>
+#include "../include/linux/lustre_intent.h"
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_fid.h"	/* fid_res_name_eq() */
+#include "../include/lustre_mdc.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_req_layout.h"
 #include "mdc_internal.h"
 
 struct mdc_getattr_args {
@@ -860,7 +860,7 @@ resend:
 	if (resends) {
 		req->rq_generation_set = 1;
 		req->rq_import_generation = generation;
-		req->rq_sent = cfs_time_current_sec() + resends;
+		req->rq_sent = get_seconds() + resends;
 	}
 
 	/* It is important to obtain rpc_lock first (if applicable), so that
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_reint.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_reint.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_reint.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_reint.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,9 +39,9 @@
 # include <linux/module.h>
 # include <linux/kernel.h>
 
-#include <obd_class.h>
+#include "../include/obd_class.h"
 #include "mdc_internal.h"
-#include <lustre_fid.h>
+#include "../include/lustre_fid.h"
 
 /* mdc_setattr does its own semaphore handling */
 static int mdc_reint(struct ptlrpc_request *request,
@@ -273,7 +273,7 @@ rebuild:
 	if (resends) {
 		req->rq_generation_set = 1;
 		req->rq_import_generation = generation;
-		req->rq_sent = cfs_time_current_sec() + resends;
+		req->rq_sent = get_seconds() + resends;
 	}
 	level = LUSTRE_IMP_FULL;
  resend:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mdc/mdc_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mdc/mdc_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,12 +42,12 @@
 # include <linux/init.h>
 # include <linux/utsname.h>
 
-#include <lustre_acl.h>
-#include <obd_class.h>
-#include <lustre_fid.h>
-#include <lprocfs_status.h>
-#include <lustre_param.h>
-#include <lustre_log.h>
+#include "../include/lustre_acl.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_fid.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_param.h"
+#include "../include/lustre_log.h"
 
 #include "mdc_internal.h"
 
@@ -136,7 +136,7 @@ static int send_getstatus(struct obd_imp
 
 	*rootfid = body->fid1;
 	CDEBUG(D_NET,
-	       "root fid="DFID", last_committed="LPU64"\n",
+	       "root fid="DFID", last_committed=%llu\n",
 	       PFID(rootfid),
 	       lustre_msg_get_last_committed(req->rq_repmsg));
 out:
@@ -397,7 +397,7 @@ static int mdc_xattr_common(struct obd_e
 		rec->sx_suppgid2 = -1;
 		rec->sx_fid    = *fid;
 		rec->sx_valid  = valid | OBD_MD_FLCTIME;
-		rec->sx_time   = cfs_time_current_sec();
+		rec->sx_time   = get_seconds();
 		rec->sx_size   = output_size;
 		rec->sx_flags  = flags;
 
@@ -670,7 +670,7 @@ void mdc_replay_open(struct ptlrpc_reque
 		LASSERT(och->och_magic == OBD_CLIENT_HANDLE_MAGIC);
 
 		file_fh = &och->och_fh;
-		CDEBUG(D_HA, "updating handle from "LPX64" to "LPX64"\n",
+		CDEBUG(D_HA, "updating handle from %#llx to %#llx\n",
 		       file_fh->cookie, body->handle.cookie);
 		old = *file_fh;
 		*file_fh = body->handle;
@@ -1182,7 +1182,7 @@ static int mdc_ioc_fid2path(struct obd_e
 	memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
 	memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
 
-	CDEBUG(D_IOCTL, "path get "DFID" from "LPU64" #%d\n",
+	CDEBUG(D_IOCTL, "path get "DFID" from %llu #%d\n",
 	       PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno);
 
 	if (!fid_is_sane(&gf->gf_fid))
@@ -1200,7 +1200,7 @@ static int mdc_ioc_fid2path(struct obd_e
 	else if (vallen > sizeof(*gf) + gf->gf_pathlen)
 		GOTO(out, rc = -EOVERFLOW);
 
-	CDEBUG(D_IOCTL, "path get "DFID" from "LPU64" #%d\n%s\n",
+	CDEBUG(D_IOCTL, "path get "DFID" from %llu #%d\n%s\n",
 	       PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno, gf->gf_path);
 
 out:
@@ -1515,12 +1515,12 @@ static int changelog_kkuc_cb(const struc
 
 	if (rec->cr.cr_index < cs->cs_startrec) {
 		/* Skip entries earlier than what we are interested in */
-		CDEBUG(D_CHANGELOG, "rec="LPU64" start="LPU64"\n",
+		CDEBUG(D_CHANGELOG, "rec=%llu start=%llu\n",
 		       rec->cr.cr_index, cs->cs_startrec);
 		return 0;
 	}
 
-	CDEBUG(D_CHANGELOG, LPU64" %02d%-5s "LPU64" 0x%x t="DFID" p="DFID
+	CDEBUG(D_CHANGELOG, "%llu %02d%-5s %llu 0x%x t="DFID" p="DFID
 		" %.*s\n", rec->cr.cr_index, rec->cr.cr_type,
 		changelog_type2str(rec->cr.cr_type), rec->cr.cr_time,
 		rec->cr.cr_flags & CLF_FLAGMASK,
@@ -1547,7 +1547,7 @@ static int mdc_changelog_send_thread(voi
 	struct kuc_hdr *kuch;
 	int rc;
 
-	CDEBUG(D_CHANGELOG, "changelog to fp=%p start "LPU64"\n",
+	CDEBUG(D_CHANGELOG, "changelog to fp=%p start %llu\n",
 	       cs->cs_fp, cs->cs_startrec);
 
 	OBD_ALLOC(cs->cs_buf, KUC_CHANGELOG_MSG_MAXSIZE);
@@ -2423,7 +2423,7 @@ struct ldlm_valblock_ops inode_lvbo = {
 static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
 {
 	struct client_obd *cli = &obd->u.cli;
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc;
 
 	OBD_ALLOC(cli->cl_rpc_lock, sizeof (*cli->cl_rpc_lock));
@@ -2566,7 +2566,7 @@ static int mdc_llog_finish(struct obd_de
 static int mdc_process_config(struct obd_device *obd, obd_count len, void *buf)
 {
 	struct lustre_cfg *lcfg = buf;
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc = 0;
 
 	lprocfs_mdc_init_vars(&lvars);
@@ -2737,7 +2737,7 @@ struct md_ops mdc_md_ops = {
 int __init mdc_init(void)
 {
 	int rc;
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	lprocfs_mdc_init_vars(&lvars);
 
 	rc = class_register_type(&mdc_obd_ops, &mdc_md_ops, lvars.module_vars,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/libmgc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/libmgc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/libmgc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/libmgc.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,13 +44,13 @@
 
 #define DEBUG_SUBSYSTEM S_MGC
 
-#include <liblustre.h>
+#include "../include/liblustre.h"
 
-#include <obd_class.h>
-#include <lustre_dlm.h>
-#include <lustre_log.h>
-#include <lustre_fsfilt.h>
-#include <lustre_disk.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_fsfilt.h"
+#include "../include/lustre_disk.h"
 
 
 static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/lproc_mgc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/lproc_mgc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/lproc_mgc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/lproc_mgc.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,8 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <linux/vfs.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 #include "mgc_internal.h"
 
 LPROC_SEQ_FOPS_RO_TYPE(mgc, uuid);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,6 +1,3 @@
 obj-$(CONFIG_LUSTRE_FS) += mgc.o
 mgc-y := mgc_request.o
 mgc-$(CONFIG_PROC_FS) += lproc_mgc.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/mgc_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/mgc_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/mgc_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/mgc_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,14 +37,14 @@
 #ifndef _MGC_INTERNAL_H
 #define _MGC_INTERNAL_H
 
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_lib.h>
-#include <lustre_dlm.h>
-#include <lustre_log.h>
-#include <lustre_export.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_export.h"
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars);
 int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data);
 #else
@@ -56,7 +56,7 @@ static inline int lprocfs_mgc_rd_ir_stat
 {
 	return 0;
 }
-#endif  /* LPROCFS */
+#endif  /* CONFIG_PROC_FS */
 
 int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/mgc_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/mgc_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/mgc/mgc_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/mgc/mgc_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,12 +42,12 @@
 #define D_MGC D_CONFIG /*|D_WARNING*/
 
 #include <linux/module.h>
-#include <obd_class.h>
-#include <lustre_dlm.h>
-#include <lprocfs_status.h>
-#include <lustre_log.h>
-#include <lustre_disk.h>
-#include <dt_object.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_disk.h"
+#include "../include/dt_object.h"
 
 #include "mgc_internal.h"
 
@@ -83,7 +83,7 @@ static int mgc_name2resid(char *name, in
 		LBUG();
 	}
 	res_id->name[1] = cpu_to_le64(resname);
-	CDEBUG(D_MGC, "log %s to resid "LPX64"/"LPX64" (%.8s)\n", name,
+	CDEBUG(D_MGC, "log %s to resid %#llx/%#llx (%.8s)\n", name,
 	       res_id->name[0], res_id->name[1], (char *)&res_id->name[0]);
 	return 0;
 }
@@ -197,7 +197,7 @@ struct config_llog_data *do_config_log_a
 	int		      rc;
 
 	CDEBUG(D_MGC, "do adding config log %s:%p\n", logname,
-	       cfg ? cfg->cfg_instance : 0);
+	       cfg ? cfg->cfg_instance : NULL);
 
 	OBD_ALLOC(cld, sizeof(*cld) + strlen(logname) + 1);
 	if (!cld)
@@ -445,7 +445,7 @@ static int config_log_end(char *logname,
 	return rc;
 }
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 {
 	struct obd_device       *obd = data;
@@ -950,7 +950,10 @@ static int mgc_blocking_ast(struct ldlm_
 }
 
 /* Not sure where this should go... */
-#define  MGC_ENQUEUE_LIMIT 50
+/* This is the timeout value for MGS_CONNECT request plus a ping interval, such
+ * that we can have a chance to try the secondary MGS if any. */
+#define  MGC_ENQUEUE_LIMIT (INITIAL_CONNECT_TIMEOUT + (AT_OFF ? 0 : at_min) \
+				+ PING_INTERVAL)
 #define  MGC_TARGET_REG_LIMIT 10
 #define  MGC_SEND_PARAM_LIMIT 10
 
@@ -1008,7 +1011,7 @@ static int mgc_enqueue(struct obd_export
 	int short_limit = cld_is_sptlrpc(cld);
 	int rc;
 
-	CDEBUG(D_MGC, "Enqueue for %s (res "LPX64")\n", cld->cld_logname,
+	CDEBUG(D_MGC, "Enqueue for %s (res %#llx)\n", cld->cld_logname,
 	       cld->cld_resid.name[0]);
 
 	/* We need a callback for every lockholder, so don't try to
@@ -1454,7 +1457,7 @@ static int mgc_apply_recover_logs(struct
 			break;
 		}
 
-		CDEBUG(D_INFO, "ir apply logs "LPD64"/"LPD64" for %s -> %s\n",
+		CDEBUG(D_INFO, "ir apply logs %lld/%lld for %s -> %s\n",
 		       prev_version, max_version, obdname, params);
 
 		rc = class_process_config(lcfg);
@@ -1557,7 +1560,7 @@ again:
 	cfg->cfg_last_idx = res->mcr_offset;
 	eof = res->mcr_offset == res->mcr_size;
 
-	CDEBUG(D_INFO, "Latest version "LPD64", more %d.\n",
+	CDEBUG(D_INFO, "Latest version %lld, more %d.\n",
 	       res->mcr_offset, eof == false);
 
 	ealen = sptlrpc_cli_unwrap_bulk_read(req, req->rq_bulk, 0);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/acl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/acl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/acl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/acl.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
  */
 
 #define DEBUG_SUBSYSTEM S_SEC
-#include <lu_object.h>
-#include <lustre_acl.h>
-#include <lustre_eacl.h>
-#include <obd_support.h>
+#include "../include/lu_object.h"
+#include "../include/lustre_acl.h"
+#include "../include/lustre_eacl.h"
+#include "../include/obd_support.h"
 
 #ifdef CONFIG_FS_POSIX_ACL
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/capa.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/capa.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/capa.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/capa.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,12 +48,12 @@
 #include <linux/module.h>
 #include <linux/crypto.h>
 
-#include <obd_class.h>
-#include <lustre_debug.h>
-#include <lustre/lustre_idl.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_debug.h"
+#include "../include/lustre/lustre_idl.h"
 
 #include <linux/list.h>
-#include <lustre_capa.h>
+#include "../include/lustre_capa.h"
 
 #define NR_CAPAHASH 32
 #define CAPA_HASH_SIZE 3000	      /* for MDS & OSS */
@@ -143,9 +143,9 @@ static inline int capa_hashfn(struct lu_
  * client renew right after obtaining it. */
 static inline int capa_is_to_expire(struct obd_capa *oc)
 {
-	return cfs_time_before(cfs_time_sub(oc->c_expiry,
-				   cfs_time_seconds(oc->c_capa.lc_timeout)*2/3),
-			       cfs_time_current());
+	return time_before(cfs_time_sub(oc->c_expiry,
+					cfs_time_seconds(oc->c_capa.lc_timeout)*2/3),
+			   cfs_time_current());
 }
 
 static struct obd_capa *find_capa(struct lustre_capa *capa,
@@ -279,6 +279,7 @@ int capa_hmac(__u8 *hmac, struct lustre_
 	}
 	keylen = alg->ha_keylen;
 
+	sg_init_table(&sl, 1);
 	sg_set_page(&sl, virt_to_page(capa),
 		    offsetof(struct lustre_capa, lc_hmac),
 		    (unsigned long)(capa) % PAGE_CACHE_SIZE);
@@ -320,9 +321,11 @@ int capa_encrypt_id(__u32 *d, __u32 *s,
 		GOTO(out, rc);
 	}
 
+	sg_init_table(&sd, 1);
 	sg_set_page(&sd, virt_to_page(d), 16,
 		    (unsigned long)(d) % PAGE_CACHE_SIZE);
 
+	sg_init_table(&ss, 1);
 	sg_set_page(&ss, virt_to_page(s), 16,
 		    (unsigned long)(s) % PAGE_CACHE_SIZE);
 	desc.tfm   = tfm;
@@ -370,9 +373,11 @@ int capa_decrypt_id(__u32 *d, __u32 *s,
 		GOTO(out, rc);
 	}
 
+	sg_init_table(&sd, 1);
 	sg_set_page(&sd, virt_to_page(d), 16,
 		    (unsigned long)(d) % PAGE_CACHE_SIZE);
 
+	sg_init_table(&ss, 1);
 	sg_set_page(&ss, virt_to_page(s), 16,
 		    (unsigned long)(s) % PAGE_CACHE_SIZE);
 
@@ -406,8 +411,8 @@ void _debug_capa(struct lustre_capa *c,
 	va_list args;
 	va_start(args, fmt);
 	libcfs_debug_vmsg2(msgdata, fmt, args,
-			   " capability@%p fid "DFID" opc "LPX64" uid "LPU64
-			   " gid "LPU64" flags %u alg %d keyid %u timeout %u "
+			   " capability@%p fid "DFID" opc %#llx uid %llu"
+			   " gid %llu flags %u alg %d keyid %u timeout %u "
 			   "expiry %u\n", c, PFID(capa_fid(c)), capa_opc(c),
 			   capa_uid(c), capa_gid(c), capa_flags(c),
 			   capa_alg(c), capa_keyid(c), capa_timeout(c),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/class_obd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/class_obd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/class_obd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/class_obd.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,16 +35,16 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-# include <asm/atomic.h>
+# include <linux/atomic.h>
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <linux/lnet/lnetctl.h>
-#include <lustre_debug.h>
-#include <lprocfs_status.h>
-#include <lustre/lustre_build_version.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../../include/linux/lnet/lnetctl.h"
+#include "../include/lustre_debug.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre/lustre_build_version.h"
 #include <linux/list.h>
-#include <cl_object.h>
+#include "../include/cl_object.h"
 #include "llog_internal.h"
 
 
@@ -141,11 +141,11 @@ int obd_alloc_fail(const void *ptr, cons
 {
 	if (ptr == NULL ||
 	    (cfs_rand() & OBD_ALLOC_FAIL_MASK) < obd_alloc_fail_rate) {
-		CERROR("%s%salloc of %s ("LPU64" bytes) failed at %s:%d\n",
+		CERROR("%s%salloc of %s (%llu bytes) failed at %s:%d\n",
 		       ptr ? "force " :"", type, name, (__u64)size, file,
 		       line);
-		CERROR(LPU64" total bytes and "LPU64" total pages "
-		       "("LPU64" bytes) allocated by Lustre, "
+		CERROR("%llu total bytes and %llu total pages "
+		       "(%llu bytes) allocated by Lustre, "
 		       "%d total bytes by LNET\n",
 		       obd_memory_sum(),
 		       obd_pages_sum() << PAGE_CACHE_SHIFT,
@@ -420,61 +420,61 @@ int obd_init_checks(void)
 	char buf[64];
 	int len, ret = 0;
 
-	CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", LPU64, LPD64, LPX64);
+	CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", "%#llx");
 
-	CDEBUG(D_INFO, "OBD_OBJECT_EOF = "LPX64"\n", (__u64)OBD_OBJECT_EOF);
+	CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF);
 
 	u64val = OBD_OBJECT_EOF;
-	CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = "LPX64"\n", u64val);
+	CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
 	if (u64val != OBD_OBJECT_EOF) {
-		CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
+		CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
 		       u64val, (int)sizeof(u64val));
 		ret = -EINVAL;
 	}
-	len = snprintf(buf, sizeof(buf), LPX64, u64val);
+	len = snprintf(buf, sizeof(buf), "%#llx", u64val);
 	if (len != 18) {
 		CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
 		ret = -EINVAL;
 	}
 
 	div64val = OBD_OBJECT_EOF;
-	CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = "LPX64"\n", u64val);
+	CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
 	if (u64val != OBD_OBJECT_EOF) {
-		CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
+		CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
 		       u64val, (int)sizeof(u64val));
 		ret = -EOVERFLOW;
 	}
 	if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
-		CERROR("__u64 "LPX64"(%d) != 0xffffffffffffffff\n",
+		CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
 		       u64val, (int)sizeof(u64val));
 		return -EOVERFLOW;
 	}
 	if (do_div(div64val, 256) != (u64val & 255)) {
-		CERROR("do_div("LPX64",256) != "LPU64"\n", u64val, u64val &255);
+		CERROR("do_div(%#llx,256) != %llu\n", u64val, u64val &255);
 		return -EOVERFLOW;
 	}
 	if (u64val >> 8 != div64val) {
-		CERROR("do_div("LPX64",256) "LPU64" != "LPU64"\n",
+		CERROR("do_div(%#llx,256) %llu != %llu\n",
 		       u64val, div64val, u64val >> 8);
 		return -EOVERFLOW;
 	}
-	len = snprintf(buf, sizeof(buf), LPX64, u64val);
+	len = snprintf(buf, sizeof(buf), "%#llx", u64val);
 	if (len != 18) {
 		CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
 		ret = -EINVAL;
 	}
-	len = snprintf(buf, sizeof(buf), LPU64, u64val);
+	len = snprintf(buf, sizeof(buf), "%llu", u64val);
 	if (len != 20) {
 		CWARN("LPU64 wrong length! strlen(%s)=%d != 20\n", buf, len);
 		ret = -EINVAL;
 	}
-	len = snprintf(buf, sizeof(buf), LPD64, u64val);
+	len = snprintf(buf, sizeof(buf), "%lld", u64val);
 	if (len != 2) {
 		CWARN("LPD64 wrong length! strlen(%s)=%d != 2\n", buf, len);
 		ret = -EINVAL;
 	}
 	if ((u64val & ~CFS_PAGE_MASK) >= PAGE_CACHE_SIZE) {
-		CWARN("mask failed: u64val "LPU64" >= "LPU64"\n", u64val,
+		CWARN("mask failed: u64val %llu >= %llu\n", u64val,
 		      (__u64)PAGE_CACHE_SIZE);
 		ret = -EINVAL;
 	}
@@ -483,7 +483,7 @@ int obd_init_checks(void)
 }
 
 extern spinlock_t obd_types_lock;
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 extern int class_procfs_init(void);
 extern int class_procfs_clean(void);
 #else
@@ -594,7 +594,7 @@ void obd_update_maxusage(void)
 }
 EXPORT_SYMBOL(obd_update_maxusage);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 __u64 obd_memory_max(void)
 {
 	__u64 ret;
@@ -662,10 +662,10 @@ static void cleanup_obdclass(void)
 
 	lprocfs_free_stats(&obd_memory);
 	CDEBUG((memory_leaked) ? D_ERROR : D_INFO,
-	       "obd_memory max: "LPU64", leaked: "LPU64"\n",
+	       "obd_memory max: %llu, leaked: %llu\n",
 	       memory_max, memory_leaked);
 	CDEBUG((pages_leaked) ? D_ERROR : D_INFO,
-	       "obd_memory_pages max: "LPU64", leaked: "LPU64"\n",
+	       "obd_memory_pages max: %llu, leaked: %llu\n",
 	       pages_max, pages_leaked);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_io.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_io.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,11 +40,11 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
 #include <linux/list.h>
-#include <cl_object.h>
+#include "../include/cl_object.h"
 #include "cl_internal.h"
 
 /*****************************************************************************
@@ -227,7 +227,7 @@ int cl_io_rw_init(const struct lu_env *e
 	LINVRNT(io->ci_obj != NULL);
 
 	LU_OBJECT_HEADER(D_VFSTRACE, env, &io->ci_obj->co_lu,
-			 "io range: %u ["LPU64", "LPU64") %u %u\n",
+			 "io range: %u [%llu, %llu) %u %u\n",
 			 iot, (__u64)pos, (__u64)pos + count,
 			 io->u.ci_rw.crw_nonblock, io->u.ci_wr.wr_append);
 	io->u.ci_rw.crw_pos    = pos;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,11 +40,11 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
 #include <linux/list.h>
-#include <cl_object.h>
+#include "../include/cl_object.h"
 #include "cl_internal.h"
 
 /** Lock class of cl_lock::cll_guard */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_object.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_object.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -51,14 +51,14 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 /* class_put_type() */
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_fid.h"
 #include <linux/list.h>
-#include <linux/libcfs/libcfs_hash.h> /* for cfs_hash stuff */
-#include <cl_object.h>
+#include "../../include/linux/libcfs/libcfs_hash.h"	/* for cfs_hash stuff */
+#include "../include/cl_object.h"
 #include "cl_internal.h"
 
 static struct kmem_cache *cl_env_kmem;
@@ -295,8 +295,7 @@ int cl_object_glimpse(const struct lu_en
 		}
 	}
 	LU_OBJECT_HEADER(D_DLMTRACE, env, lu_object_top(top),
-			 "size: "LPU64" mtime: "LPU64" atime: "LPU64" "
-			 "ctime: "LPU64" blocks: "LPU64"\n",
+			 "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu\n",
 			 lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime,
 			 lvb->lvb_ctime, lvb->lvb_blocks);
 	return result;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_page.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_page.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/cl_page.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/cl_page.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,12 +40,12 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/libcfs/libcfs.h>
-#include <obd_class.h>
-#include <obd_support.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
 #include <linux/list.h>
 
-#include <cl_object.h>
+#include "../include/cl_object.h"
 #include "cl_internal.h"
 
 static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/debug.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/debug.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,15 +41,15 @@
 #define DEBUG_SUBSYSTEM D_OTHER
 
 
-#include <obd_ost.h>
-#include <obd_support.h>
-#include <lustre_debug.h>
-#include <lustre_net.h>
+#include "../include/obd_ost.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_debug.h"
+#include "../include/lustre_net.h"
 
 void dump_lniobuf(struct niobuf_local *nb)
 {
 	CDEBUG(D_RPCTRACE,
-	       "niobuf_local: file_offset="LPD64", len=%d, page=%p, rc=%d\n",
+	       "niobuf_local: file_offset=%lld, len=%d, page=%p, rc=%d\n",
 	       nb->lnb_file_offset, nb->len, nb->page, nb->rc);
 	CDEBUG(D_RPCTRACE, "nb->page: index = %ld\n",
 			nb->page ? page_index(nb->page) : -1);
@@ -84,25 +84,25 @@ int block_debug_check(char *who, void *a
 	ne_off = le64_to_cpu (off);
 	id = le64_to_cpu (id);
 	if (memcmp(addr, (char *)&ne_off, LPDS)) {
-		CDEBUG(D_ERROR, "%s: id "LPX64" offset "LPU64" off: "LPX64" != "
-		       LPX64"\n", who, id, off, *(__u64 *)addr, ne_off);
+		CDEBUG(D_ERROR, "%s: id %#llx offset %llu off: %#llx != %#llx\n",
+		       who, id, off, *(__u64 *)addr, ne_off);
 		err = -EINVAL;
 	}
 	if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
-		CDEBUG(D_ERROR, "%s: id "LPX64" offset "LPU64" id: "LPX64" != "LPX64"\n",
+		CDEBUG(D_ERROR, "%s: id %#llx offset %llu id: %#llx != %#llx\n",
 		       who, id, off, *(__u64 *)(addr + LPDS), id);
 		err = -EINVAL;
 	}
 
 	addr += end - LPDS - LPDS;
 	if (memcmp(addr, (char *)&ne_off, LPDS)) {
-		CDEBUG(D_ERROR, "%s: id "LPX64" offset "LPU64" end off: "LPX64" != "
-		       LPX64"\n", who, id, off, *(__u64 *)addr, ne_off);
+		CDEBUG(D_ERROR, "%s: id %#llx offset %llu end off: %#llx != %#llx\n",
+		       who, id, off, *(__u64 *)addr, ne_off);
 		err = -EINVAL;
 	}
 	if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
-		CDEBUG(D_ERROR, "%s: id "LPX64" offset "LPU64" end id: "LPX64" != "
-		       LPX64"\n", who, id, off, *(__u64 *)(addr + LPDS), id);
+		CDEBUG(D_ERROR, "%s: id %#llx offset %llu end id: %#llx != %#llx\n",
+		       who, id, off, *(__u64 *)(addr + LPDS), id);
 		err = -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/dt_object.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/dt_object.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/dt_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/dt_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,13 +43,13 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd.h>
-#include <dt_object.h>
+#include "../include/obd.h"
+#include "../include/dt_object.h"
 #include <linux/list.h>
 /* fid_be_to_cpu() */
-#include <lustre_fid.h>
+#include "../include/lustre_fid.h"
 
-#include <lustre_quota.h>
+#include "../include/lustre_quota.h"
 
 /* context key constructor/destructor: dt_global_key_init, dt_global_key_fini */
 LU_KEY_INIT(dt_global, struct dt_thread_info);
@@ -929,7 +929,7 @@ out:
 }
 EXPORT_SYMBOL(dt_index_read);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 
 int lprocfs_dt_rd_blksize(char *page, char **start, off_t off,
 			  int count, int *eof, void *data)
@@ -963,7 +963,7 @@ int lprocfs_dt_rd_kbytestotal(char *page
 			result <<= 1;
 
 		*eof = 1;
-		rc = snprintf(page, count, LPU64"\n", result);
+		rc = snprintf(page, count, "%llu\n", result);
 	}
 
 	return rc;
@@ -985,7 +985,7 @@ int lprocfs_dt_rd_kbytesfree(char *page,
 			result <<= 1;
 
 		*eof = 1;
-		rc = snprintf(page, count, LPU64"\n", result);
+		rc = snprintf(page, count, "%llu\n", result);
 	}
 
 	return rc;
@@ -1007,7 +1007,7 @@ int lprocfs_dt_rd_kbytesavail(char *page
 			result <<= 1;
 
 		*eof = 1;
-		rc = snprintf(page, count, LPU64"\n", result);
+		rc = snprintf(page, count, "%llu\n", result);
 	}
 
 	return rc;
@@ -1023,7 +1023,7 @@ int lprocfs_dt_rd_filestotal(char *page,
 	int rc = dt_statfs(NULL, dt, &osfs);
 	if (rc == 0) {
 		*eof = 1;
-		rc = snprintf(page, count, LPU64"\n", osfs.os_files);
+		rc = snprintf(page, count, "%llu\n", osfs.os_files);
 	}
 
 	return rc;
@@ -1039,11 +1039,11 @@ int lprocfs_dt_rd_filesfree(char *page,
 	int rc = dt_statfs(NULL, dt, &osfs);
 	if (rc == 0) {
 		*eof = 1;
-		rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
+		rc = snprintf(page, count, "%llu\n", osfs.os_ffree);
 	}
 
 	return rc;
 }
 EXPORT_SYMBOL(lprocfs_dt_rd_filesfree);
 
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/genops.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/genops.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/genops.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/genops.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,9 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-#include <obd_ost.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/obd_ost.h"
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 
 extern struct list_head obd_types;
 spinlock_t obd_types_lock;
@@ -699,7 +699,7 @@ struct obd_export *class_conn2export(str
 		return NULL;
 	}
 
-	CDEBUG(D_INFO, "looking for export cookie "LPX64"\n", conn->cookie);
+	CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie);
 	export = class_handle2object(conn->cookie);
 	return export;
 }
@@ -842,7 +842,7 @@ struct obd_export *class_new_export(stru
 	INIT_LIST_HEAD(&export->exp_handle.h_link);
 	INIT_LIST_HEAD(&export->exp_hp_rpcs);
 	class_handle_hash(&export->exp_handle, &export_handle_ops);
-	export->exp_last_request_time = cfs_time_current_sec();
+	export->exp_last_request_time = get_seconds();
 	spin_lock_init(&export->exp_lock);
 	spin_lock_init(&export->exp_rpc_lock);
 	INIT_HLIST_NODE(&export->exp_uuid_hash);
@@ -1113,7 +1113,7 @@ int class_connect(struct lustre_handle *
 	conn->cookie = export->exp_handle.h_cookie;
 	class_export_put(export);
 
-	CDEBUG(D_IOCTL, "connect: client %s, cookie "LPX64"\n",
+	CDEBUG(D_IOCTL, "connect: client %s, cookie %#llx\n",
 	       cluuid->uuid, conn->cookie);
 	return 0;
 }
@@ -1190,7 +1190,7 @@ int class_disconnect(struct obd_export *
 		GOTO(no_disconn, already_disconnected);
 	}
 
-	CDEBUG(D_IOCTL, "disconnect: cookie "LPX64"\n",
+	CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
 	       export->exp_handle.h_cookie);
 
 	if (!hlist_unhashed(&export->exp_nid_hash))
@@ -1493,7 +1493,7 @@ static void print_export_data(struct obd
 	}
 	spin_unlock(&exp->exp_lock);
 
-	CDEBUG(D_HA, "%s: %s %p %s %s %d (%d %d %d) %d %d %d %d: %p %s "LPU64"\n",
+	CDEBUG(D_HA, "%s: %s %p %s %s %d (%d %d %d) %d %d %d %d: %p %s %llu\n",
 	       exp->exp_obd->obd_name, status, exp, exp->exp_client_uuid.uuid,
 	       obd_export_nid2str(exp), atomic_read(&exp->exp_refcount),
 	       atomic_read(&exp->exp_rpc_count),
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/idmap.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/idmap.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/idmap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/idmap.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,9 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <lustre_idmap.h>
-#include <md_object.h>
-#include <obd_support.h>
+#include "../include/lustre_idmap.h"
+#include "../include/md_object.h"
+#include "../include/obd_support.h"
 
 #define lustre_get_group_info(group_info) do {	     \
 	atomic_inc(&(group_info)->usage);	      \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linkea.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linkea.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linkea.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linkea.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,9 +27,9 @@
  * Author: Di Wang <di.wang@intel.com>
  */
 
-#include <lustre/lustre_idl.h>
-#include <obd.h>
-#include <lustre_linkea.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/obd.h"
+#include "../include/lustre_linkea.h"
 
 int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,13 +65,13 @@
 #include <linux/miscdevice.h>
 #include <linux/seq_file.h>
 
-#include <linux/libcfs/libcfs.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <linux/lnet/lnetctl.h>
-#include <lprocfs_status.h>
-#include <lustre_ver.h>
-#include <lustre/lustre_build_version.h>
+#include "../../../include/linux/libcfs/libcfs.h"
+#include "../../../include/linux/lnet/lnetctl.h"
+#include "../../include/obd_support.h"
+#include "../../include/obd_class.h"
+#include "../../include/lprocfs_status.h"
+#include "../../include/lustre_ver.h"
+#include "../../include/lustre/lustre_build_version.h"
 
 int proc_version;
 
@@ -212,7 +212,7 @@ struct miscdevice obd_psdev = {
 };
 
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int obd_proc_version_seq_show(struct seq_file *m, void *v)
 {
 	return seq_printf(m, "lustre: %s\nkernel: %s\nbuild:  %s\n",
@@ -328,7 +328,7 @@ struct lprocfs_vars lprocfs_base[] = {
 	{ "jobid_var", &obd_proc_jobid_var_fops },
 	{ .name =	"jobid_name",
 	  .fops =	&obd_proc_jobid_name_fops},
-	{ 0 }
+	{ NULL }
 };
 
 static void *obd_device_list_seq_start(struct seq_file *p, loff_t *pos)
@@ -435,4 +435,4 @@ int class_procfs_clean(void)
 	}
 	return 0;
 }
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,8 +43,8 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <linux/module.h>
-#include <obd_class.h>
-#include <lustre/lustre_idl.h>
+#include "../../include/obd_class.h"
+#include "../../include/lustre/lustre_idl.h"
 
 #include <linux/fs.h>
 #include <linux/pagemap.h> /* for PAGE_CACHE_SIZE */
@@ -151,7 +151,7 @@ void obdo_refresh_inode(struct inode *ds
 
 	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
 		CDEBUG(D_INODE,
-		       "valid "LPX64", cur time %lu/%lu, new "LPU64"/"LPU64"\n",
+		       "valid %#llx, cur time %lu/%lu, new %llu/%llu\n",
 		       src->o_valid, LTIME_S(dst->i_mtime),
 		       LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime);
 
@@ -190,7 +190,7 @@ void obdo_to_inode(struct inode *dst, st
 
 	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
 		CDEBUG(D_INODE,
-		       "valid "LPX64", cur time %lu/%lu, new "LPU64"/"LPU64"\n",
+		       "valid %#llx, cur time %lu/%lu, new %llu/%llu\n",
 		       src->o_valid, LTIME_S(dst->i_mtime),
 		       LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,17 +42,17 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
 #include <linux/utsname.h>
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd_support.h>
-#include <lprocfs_status.h>
+#include "../../include/obd_support.h"
+#include "../../include/lprocfs_status.h"
 
 #ifdef CONFIG_SYSCTL
-ctl_table_header_t *obd_table_header = NULL;
+static struct ctl_table_header *obd_table_header;
 #endif
 
 
@@ -79,21 +79,22 @@ enum {
 };
 
 
-int LL_PROC_PROTO(proc_set_timeout)
+static int proc_set_timeout(struct ctl_table *table, int write,
+			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc;
 
-	rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
+	rc = proc_dointvec(table, write, buffer, lenp, ppos);
 	if (ldlm_timeout >= obd_timeout)
 		ldlm_timeout = max(obd_timeout / 3, 1U);
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_memory_alloc)
+static int proc_memory_alloc(struct ctl_table *table, int write,
+			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[22];
 	int len;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -102,7 +103,7 @@ int LL_PROC_PROTO(proc_memory_alloc)
 	if (write)
 		return -EINVAL;
 
-	len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_sum());
+	len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
 	if (len > *lenp)
 		len = *lenp;
 	buf[len] = '\0';
@@ -113,11 +114,11 @@ int LL_PROC_PROTO(proc_memory_alloc)
 	return 0;
 }
 
-int LL_PROC_PROTO(proc_pages_alloc)
+static int proc_pages_alloc(struct ctl_table *table, int write,
+			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[22];
 	int len;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -126,7 +127,7 @@ int LL_PROC_PROTO(proc_pages_alloc)
 	if (write)
 		return -EINVAL;
 
-	len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_sum());
+	len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_sum());
 	if (len > *lenp)
 		len = *lenp;
 	buf[len] = '\0';
@@ -137,11 +138,11 @@ int LL_PROC_PROTO(proc_pages_alloc)
 	return 0;
 }
 
-int LL_PROC_PROTO(proc_mem_max)
+static int proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
+		 size_t *lenp, loff_t *ppos)
 {
 	char buf[22];
 	int len;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -150,7 +151,7 @@ int LL_PROC_PROTO(proc_mem_max)
 	if (write)
 		return -EINVAL;
 
-	len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_max());
+	len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
 	if (len > *lenp)
 		len = *lenp;
 	buf[len] = '\0';
@@ -161,11 +162,11 @@ int LL_PROC_PROTO(proc_mem_max)
 	return 0;
 }
 
-int LL_PROC_PROTO(proc_pages_max)
+static int proc_pages_max(struct ctl_table *table, int write,
+			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[22];
 	int len;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -174,7 +175,7 @@ int LL_PROC_PROTO(proc_pages_max)
 	if (write)
 		return -EINVAL;
 
-	len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_max());
+	len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_max());
 	if (len > *lenp)
 		len = *lenp;
 	buf[len] = '\0';
@@ -185,10 +186,10 @@ int LL_PROC_PROTO(proc_pages_max)
 	return 0;
 }
 
-int LL_PROC_PROTO(proc_max_dirty_pages_in_mb)
+static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
+			       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc = 0;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -196,7 +197,7 @@ int LL_PROC_PROTO(proc_max_dirty_pages_i
 	}
 	if (write) {
 		rc = lprocfs_write_frac_helper(buffer, *lenp,
-					       (unsigned int*)table->data,
+					       (unsigned int *)table->data,
 					       1 << (20 - PAGE_CACHE_SHIFT));
 		/* Don't allow them to let dirty pages exceed 90% of system
 		 * memory and set a hard minimum of 4MB. */
@@ -214,7 +215,7 @@ int LL_PROC_PROTO(proc_max_dirty_pages_i
 		int len;
 
 		len = lprocfs_read_frac_helper(buf, sizeof(buf),
-					       *(unsigned int*)table->data,
+					       *(unsigned int *)table->data,
 					       1 << (20 - PAGE_CACHE_SHIFT));
 		if (len > *lenp)
 			len = *lenp;
@@ -227,10 +228,10 @@ int LL_PROC_PROTO(proc_max_dirty_pages_i
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_alloc_fail_rate)
+static int proc_alloc_fail_rate(struct ctl_table *table, int write,
+			 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	int rc	  = 0;
-	DECLARE_LL_PROC_PPOS_DECL;
 
 	if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -238,14 +239,14 @@ int LL_PROC_PROTO(proc_alloc_fail_rate)
 	}
 	if (write) {
 		rc = lprocfs_write_frac_helper(buffer, *lenp,
-					       (unsigned int*)table->data,
+					       (unsigned int *)table->data,
 					       OBD_ALLOC_FAIL_MULT);
 	} else {
 		char buf[21];
 		int  len;
 
 		len = lprocfs_read_frac_helper(buf, 21,
-					       *(unsigned int*)table->data,
+					       *(unsigned int *)table->data,
 					       OBD_ALLOC_FAIL_MULT);
 		if (len > *lenp)
 			len = *lenp;
@@ -258,29 +259,8 @@ int LL_PROC_PROTO(proc_alloc_fail_rate)
 	return rc;
 }
 
-int LL_PROC_PROTO(proc_at_min)
-{
-	return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
-}
-int LL_PROC_PROTO(proc_at_max)
-{
-	return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
-}
-int LL_PROC_PROTO(proc_at_extra)
-{
-	return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
-}
-int LL_PROC_PROTO(proc_at_early_margin)
-{
-	return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
-}
-int LL_PROC_PROTO(proc_at_history)
-{
-	return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
-}
-
 #ifdef CONFIG_SYSCTL
-static ctl_table_t obd_table[] = {
+static struct ctl_table obd_table[] = {
 	{
 		.procname = "timeout",
 		.data     = &obd_timeout,
@@ -363,40 +343,40 @@ static ctl_table_t obd_table[] = {
 		.data     = &at_min,
 		.maxlen   = sizeof(int),
 		.mode     = 0644,
-		.proc_handler = &proc_at_min
+		.proc_handler = &proc_dointvec,
 	},
 	{
 		.procname = "at_max",
 		.data     = &at_max,
 		.maxlen   = sizeof(int),
 		.mode     = 0644,
-		.proc_handler = &proc_at_max
+		.proc_handler = &proc_dointvec,
 	},
 	{
 		.procname = "at_extra",
 		.data     = &at_extra,
 		.maxlen   = sizeof(int),
 		.mode     = 0644,
-		.proc_handler = &proc_at_extra
+		.proc_handler = &proc_dointvec,
 	},
 	{
 		.procname = "at_early_margin",
 		.data     = &at_early_margin,
 		.maxlen   = sizeof(int),
 		.mode     = 0644,
-		.proc_handler = &proc_at_early_margin
+		.proc_handler = &proc_dointvec,
 	},
 	{
 		.procname = "at_history",
 		.data     = &at_history,
 		.maxlen   = sizeof(int),
 		.mode     = 0644,
-		.proc_handler = &proc_at_history
+		.proc_handler = &proc_dointvec,
 	},
 	{}
 };
 
-static ctl_table_t parent_table[] = {
+static struct ctl_table parent_table[] = {
 	{
 		.procname = "lustre",
 		.data     = NULL,
@@ -408,18 +388,18 @@ static ctl_table_t parent_table[] = {
 };
 #endif
 
-void obd_sysctl_init (void)
+void obd_sysctl_init(void)
 {
 #ifdef CONFIG_SYSCTL
-	if ( !obd_table_header )
+	if (!obd_table_header)
 		obd_table_header = register_sysctl_table(parent_table);
 #endif
 }
 
-void obd_sysctl_clean (void)
+void obd_sysctl_clean(void)
 {
 #ifdef CONFIG_SYSCTL
-	if ( obd_table_header )
+	if (obd_table_header)
 		unregister_sysctl_table(obd_table_header);
 	obd_table_header = NULL;
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog.c	2014-09-28 17:29:07.000000000 -0400
@@ -48,8 +48,8 @@
 #define DEBUG_SUBSYSTEM S_LOG
 
 
-#include <obd_class.h>
-#include <lustre_log.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
 #include "llog_internal.h"
 
 /*
@@ -188,7 +188,7 @@ static int llog_read_header(const struct
 		llh->llh_hdr.lrh_type = LLOG_HDR_MAGIC;
 		llh->llh_hdr.lrh_len = llh->llh_tail.lrt_len = LLOG_CHUNK_SIZE;
 		llh->llh_hdr.lrh_index = llh->llh_tail.lrt_index = 0;
-		llh->llh_timestamp = cfs_time_current_sec();
+		llh->llh_timestamp = get_seconds();
 		if (uuid)
 			memcpy(&llh->llh_tgtuuid, uuid,
 			       sizeof(llh->llh_tgtuuid));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_cat.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_cat.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_cat.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_cat.c	2014-09-28 17:29:07.000000000 -0400
@@ -49,7 +49,7 @@
 #define DEBUG_SUBSYSTEM S_LOG
 
 
-#include <obd_class.h>
+#include "../include/obd_class.h"
 
 #include "llog_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -37,7 +37,7 @@
 #ifndef __LLOG_INTERNAL_H__
 #define __LLOG_INTERNAL_H__
 
-#include <lustre_log.h>
+#include "../include/lustre_log.h"
 
 struct llog_process_info {
 	struct llog_handle *lpi_loghandle;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,8 +36,8 @@
 
 #define DEBUG_SUBSYSTEM S_LOG
 
-#include <obd_class.h>
-#include <lustre_log.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
 #include "llog_internal.h"
 
 static int str2logid(struct llog_logid *logid, char *str, int len)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,20 +46,20 @@
 #define DEBUG_SUBSYSTEM S_LOG
 
 
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_log.h>
-#include <obd_ost.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
+#include "../include/obd_ost.h"
 #include <linux/list.h>
-#include <lvfs.h>
-#include <lustre_fsfilt.h>
-#include <lustre_disk.h>
+#include "../include/lvfs.h"
+#include "../include/lustre_fsfilt.h"
+#include "../include/lustre_disk.h"
 #include "llog_internal.h"
 
 #if  defined(LLOG_LVFS)
 
-static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file,
-				int len, int index)
+static int llog_lvfs_pad(struct obd_device *obd, struct file *file, int len,
+			 int index)
 {
 	struct llog_rec_hdr rec = { 0 };
 	struct llog_rec_tail tail;
@@ -88,7 +88,7 @@ static int llog_lvfs_pad(struct obd_devi
 	return rc;
 }
 
-static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file,
+static int llog_lvfs_write_blob(struct obd_device *obd, struct file *file,
 				struct llog_rec_hdr *rec, void *buf, loff_t off)
 {
 	int rc;
@@ -140,7 +140,7 @@ static int llog_lvfs_write_blob(struct o
 	return rc;
 }
 
-static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file,
+static int llog_lvfs_read_blob(struct obd_device *obd, struct file *file,
 				void *buf, int size, loff_t off)
 {
 	loff_t offset = off;
@@ -389,7 +389,7 @@ static int llog_lvfs_next_block(const st
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
 		return -EINVAL;
 
-	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
+	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off %llu)\n",
 	       next_idx, *cur_idx, *cur_offset);
 
 	while (*cur_offset < i_size_read(loghandle->lgh_file->f_dentry->d_inode)) {
@@ -408,7 +408,7 @@ static int llog_lvfs_next_block(const st
 					cur_offset);
 		if (rc < 0) {
 			CERROR("Cant read llog block at log id "DOSTID
-			       "/%u offset "LPU64"\n",
+			       "/%u offset %llu\n",
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen,
 			       *cur_offset);
@@ -426,8 +426,8 @@ static int llog_lvfs_next_block(const st
 			return 0;
 
 		if (rc < sizeof(*tail)) {
-			CERROR("Invalid llog block at log id "DOSTID"/%u offset"
-			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
+			CERROR("Invalid llog block at log id "DOSTID"/%u offset%llu\n",
+			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
 			return -EINVAL;
 		}
@@ -451,8 +451,8 @@ static int llog_lvfs_next_block(const st
 
 		/* this shouldn't happen */
 		if (tail->lrt_index == 0) {
-			CERROR("Invalid llog tail at log id "DOSTID"/%u offset "
-			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
+			CERROR("Invalid llog tail at log id "DOSTID"/%u offset %llu\n",
+			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
 			return -EINVAL;
 		}
@@ -496,7 +496,7 @@ static int llog_lvfs_prev_block(const st
 					&cur_offset);
 		if (rc < 0) {
 			CERROR("Cant read llog block at log id "DOSTID
-			       "/%u offset "LPU64"\n",
+			       "/%u offset %llu\n",
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen,
 			       cur_offset);
@@ -510,8 +510,8 @@ static int llog_lvfs_prev_block(const st
 			return 0;
 
 		if (rc < sizeof(*tail)) {
-			CERROR("Invalid llog block at log id "DOSTID"/%u offset"
-			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
+			CERROR("Invalid llog block at log id "DOSTID"/%u offset%llu\n",
+			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
 			return -EINVAL;
 		}
@@ -533,8 +533,8 @@ static int llog_lvfs_prev_block(const st
 
 		/* this shouldn't happen */
 		if (tail->lrt_index == 0) {
-			CERROR("Invalid llog tail at log id "DOSTID"/%u offset"
-			       LPU64"\n", POSTID(&loghandle->lgh_id.lgl_oi),
+			CERROR("Invalid llog tail at log id "DOSTID"/%u offset%llu\n",
+			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
 			return -EINVAL;
 		}
@@ -567,7 +567,7 @@ static struct file *llog_filp_open(char
 	if (len >= PATH_MAX - 1) {
 		filp = ERR_PTR(-ENAMETOOLONG);
 	} else {
-		filp = l_filp_open(logname, flags, mode);
+		filp = filp_open(logname, flags, mode);
 		if (IS_ERR(filp) && PTR_ERR(filp) != -ENOENT)
 			CERROR("logfile creation %s: %ld\n", logname,
 			       PTR_ERR(filp));
@@ -581,7 +581,7 @@ static int llog_lvfs_open(const struct l
 			  enum llog_open_param open_param)
 {
 	struct llog_ctxt	*ctxt = handle->lgh_ctxt;
-	struct l_dentry		*dchild = NULL;
+	struct dentry		*dchild = NULL;
 	struct obd_device	*obd;
 	int			 rc = 0;
 
@@ -672,7 +672,7 @@ static int llog_lvfs_create(const struct
 {
 	struct llog_ctxt	*ctxt = handle->lgh_ctxt;
 	struct obd_device	*obd;
-	struct l_dentry		*dchild = NULL;
+	struct dentry		*dchild = NULL;
 	struct file		*file;
 	struct obdo		*oa = NULL;
 	int			 rc = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_obd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_obd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_obd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_obd.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,8 +37,8 @@
 #define DEBUG_SUBSYSTEM S_LOG
 
 
-#include <obd_class.h>
-#include <lustre_log.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
 #include "llog_internal.h"
 
 /* helper functions for calling the llog obd methods */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_osd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_osd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_osd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_osd.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
 
 #define DEBUG_SUBSYSTEM S_LOG
 
-#include <obd.h>
-#include <obd_class.h>
-#include <lustre_fid.h>
-#include <dt_object.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_fid.h"
+#include "../include/dt_object.h"
 
 #include "llog_internal.h"
 #include "local_storage.h"
@@ -533,7 +533,7 @@ static int llog_osd_next_block(const str
 	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
 		return -EINVAL;
 
-	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
+	CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off %llu)\n",
 	       next_idx, *cur_idx, *cur_offset);
 
 	LASSERT(loghandle);
@@ -574,7 +574,7 @@ static int llog_osd_next_block(const str
 		dt_read_unlock(env, o);
 		if (rc < 0) {
 			CERROR("%s: can't read llog block from log "DFID
-			       " offset "LPU64": rc = %d\n",
+			       " offset %llu: rc = %d\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       PFID(lu_object_fid(&o->do_lu)), *cur_offset,
 			       rc);
@@ -592,7 +592,7 @@ static int llog_osd_next_block(const str
 
 		if (rc < sizeof(*tail)) {
 			CERROR("%s: invalid llog block at log id "DOSTID"/%u "
-			       "offset "LPU64"\n",
+			       "offset %llu\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
@@ -618,7 +618,7 @@ static int llog_osd_next_block(const str
 		/* this shouldn't happen */
 		if (tail->lrt_index == 0) {
 			CERROR("%s: invalid llog tail at log id "DOSTID"/%u "
-			       "offset "LPU64"\n",
+			       "offset %llu\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, *cur_offset);
@@ -687,7 +687,7 @@ static int llog_osd_prev_block(const str
 		dt_read_unlock(env, o);
 		if (rc < 0) {
 			CERROR("%s: can't read llog block from log "DFID
-			       " offset "LPU64": rc = %d\n",
+			       " offset %llu: rc = %d\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       PFID(lu_object_fid(&o->do_lu)), cur_offset, rc);
 			GOTO(out, rc);
@@ -698,7 +698,7 @@ static int llog_osd_prev_block(const str
 
 		if (rc < sizeof(*tail)) {
 			CERROR("%s: invalid llog block at log id "DOSTID"/%u "
-			       "offset "LPU64"\n",
+			       "offset %llu\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
@@ -722,7 +722,7 @@ static int llog_osd_prev_block(const str
 		/* this shouldn't happen */
 		if (tail->lrt_index == 0) {
 			CERROR("%s: invalid llog tail at log id "DOSTID"/%u "
-			       "offset "LPU64"\n",
+			       "offset %llu\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       POSTID(&loghandle->lgh_id.lgl_oi),
 			       loghandle->lgh_id.lgl_ogen, cur_offset);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_swab.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_swab.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_swab.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_swab.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@
 #define DEBUG_SUBSYSTEM S_LOG
 
 
-#include <lustre_log.h>
+#include "../include/lustre_log.h"
 
 static void print_llogd_body(struct llogd_body *d)
 {
@@ -56,7 +56,7 @@ static void print_llogd_body(struct llog
 	CDEBUG(D_OTHER, "\tlgd_index: %#x\n", d->lgd_index);
 	CDEBUG(D_OTHER, "\tlgd_saved_index: %#x\n", d->lgd_saved_index);
 	CDEBUG(D_OTHER, "\tlgd_len: %#x\n", d->lgd_len);
-	CDEBUG(D_OTHER, "\tlgd_cur_offset: "LPX64"\n", d->lgd_cur_offset);
+	CDEBUG(D_OTHER, "\tlgd_cur_offset: %#llx\n", d->lgd_cur_offset);
 }
 
 void lustre_swab_lu_fid(struct lu_fid *fid)
@@ -284,7 +284,7 @@ static void print_llog_hdr(struct llog_l
 	CDEBUG(D_OTHER, "\tllh_hdr.lrh_index: %#x\n", h->llh_hdr.lrh_index);
 	CDEBUG(D_OTHER, "\tllh_hdr.lrh_len: %#x\n", h->llh_hdr.lrh_len);
 	CDEBUG(D_OTHER, "\tllh_hdr.lrh_type: %#x\n", h->llh_hdr.lrh_type);
-	CDEBUG(D_OTHER, "\tllh_timestamp: "LPX64"\n", h->llh_timestamp);
+	CDEBUG(D_OTHER, "\tllh_timestamp: %#llx\n", h->llh_timestamp);
 	CDEBUG(D_OTHER, "\tllh_count: %#x\n", h->llh_count);
 	CDEBUG(D_OTHER, "\tllh_bitmap_offset: %#x\n", h->llh_bitmap_offset);
 	CDEBUG(D_OTHER, "\tllh_flags: %#x\n", h->llh_flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_test.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_test.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/llog_test.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/llog_test.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,9 +44,9 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <obd_class.h>
-#include <lustre_fid.h>
-#include <lustre_log.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_log.h"
 
 /* This is slightly more than the number of records that can fit into a
  * single llog file, because the llog_log_header takes up some of the
@@ -939,9 +939,9 @@ cleanup_ctxt:
 	return rc;
 }
 
-#ifdef LPROCFS
-static struct lprocfs_vars lprocfs_llog_test_obd_vars[] = { {0} };
-static struct lprocfs_vars lprocfs_llog_test_module_vars[] = { {0} };
+#if defined (CONFIG_PROC_FS)
+static struct lprocfs_vars lprocfs_llog_test_obd_vars[] = { { NULL } };
+static struct lprocfs_vars lprocfs_llog_test_module_vars[] = { { NULL } };
 static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars)
 {
     lvars->module_vars  = lprocfs_llog_test_module_vars;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.c	2014-09-28 17:29:07.000000000 -0400
@@ -670,7 +670,7 @@ int lastid_compat_check(const struct lu_
 		return PTR_ERR(root);
 
 	/* find old last_id file */
-	snprintf(dti->dti_buf, sizeof(dti->dti_buf), "seq-"LPX64"-lastid",
+	snprintf(dti->dti_buf, sizeof(dti->dti_buf), "seq-%#llx-lastid",
 		 lastid_seq);
 	rc = dt_lookup_dir(env, root, dti->dti_buf, &dti->dti_fid);
 	lu_object_put_nocache(env, &root->do_lu);
@@ -693,7 +693,7 @@ int lastid_compat_check(const struct lu_
 	} else if (rc < 0) {
 		return rc;
 	} else {
-		CDEBUG(D_INFO, "Found old lastid file for sequence "LPX64"\n",
+		CDEBUG(D_INFO, "Found old lastid file for sequence %#llx\n",
 		       lastid_seq);
 		o = ls_locate(env, ls, &dti->dti_fid);
 		if (IS_ERR(o))
@@ -709,12 +709,12 @@ int lastid_compat_check(const struct lu_
 	dt_read_unlock(env, o);
 	lu_object_put_nocache(env, &o->do_lu);
 	if (rc == 0 && le32_to_cpu(losd.lso_magic) != LOS_MAGIC) {
-		CERROR("%s: wrong content of seq-"LPX64"-lastid file, magic %x\n",
+		CERROR("%s: wrong content of seq-%#llx-lastid file, magic %x\n",
 		       o->do_lu.lo_dev->ld_obd->obd_name, lastid_seq,
 		       le32_to_cpu(losd.lso_magic));
 		return -EINVAL;
 	} else if (rc < 0) {
-		CERROR("%s: failed to read seq-"LPX64"-lastid: rc = %d\n",
+		CERROR("%s: failed to read seq-%#llx-lastid: rc = %d\n",
 		       o->do_lu.lo_dev->ld_obd->obd_name, lastid_seq, rc);
 		return rc;
 	}
@@ -837,7 +837,7 @@ out_trans:
 		rc = dt_record_read(env, o, &dti->dti_lb, &dti->dti_off);
 		dt_read_unlock(env, o);
 		if (rc == 0 && le64_to_cpu(lastid) > OBIF_MAX_OID) {
-			CERROR("%s: bad oid "LPU64" is read from LAST_ID\n",
+			CERROR("%s: bad oid %llu is read from LAST_ID\n",
 			       o->do_lu.lo_dev->ld_obd->obd_name,
 			       le64_to_cpu(lastid));
 			rc = -EINVAL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/local_storage.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,10 +32,10 @@
 #ifndef __LOCAL_STORAGE_H
 #define __LOCAL_STORAGE_H
 
-#include <dt_object.h>
-#include <obd.h>
-#include <lustre_fid.h>
-#include <lustre_disk.h>
+#include "../include/dt_object.h"
+#include "../include/obd.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_disk.h"
 
 struct ls_device {
 	struct dt_device	 ls_top_dev;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,9 +41,9 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre/lustre_idl.h"
 #include <linux/seq_file.h>
 
 static const char * const obd_connect_names[] = {
@@ -116,7 +116,7 @@ int obd_connect_flags2str(char *page, in
 	}
 	if (flags & ~(mask - 1))
 		ret += snprintf(page + ret, count - ret,
-				"%sunknown flags "LPX64,
+				"%sunknown flags %#llx",
 				ret ? sep : "", flags & ~(mask - 1));
 	return ret;
 }
@@ -220,7 +220,7 @@ int lprocfs_write_frac_helper(const char
 }
 EXPORT_SYMBOL(lprocfs_write_frac_helper);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 
 static int lprocfs_no_percpu_stats = 0;
 module_param(lprocfs_no_percpu_stats, int, 0644);
@@ -400,7 +400,7 @@ EXPORT_SYMBOL(lprocfs_wr_uint);
 
 int lprocfs_rd_u64(struct seq_file *m, void *data)
 {
-	return seq_printf(m, LPU64"\n", *(__u64 *)data);
+	return seq_printf(m, "%llu\n", *(__u64 *)data);
 }
 EXPORT_SYMBOL(lprocfs_rd_u64);
 
@@ -476,7 +476,7 @@ int lprocfs_rd_kbytestotal(struct seq_fi
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -496,7 +496,7 @@ int lprocfs_rd_kbytesfree(struct seq_fil
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -516,7 +516,7 @@ int lprocfs_rd_kbytesavail(struct seq_fi
 		while (blk_size >>= 1)
 			result <<= 1;
 
-		rc = seq_printf(m, LPU64"\n", result);
+		rc = seq_printf(m, "%llu\n", result);
 	}
 	return rc;
 }
@@ -530,7 +530,7 @@ int lprocfs_rd_filestotal(struct seq_fil
 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 			    OBD_STATFS_NODELAY);
 	if (!rc)
-		rc = seq_printf(m, LPU64"\n", osfs.os_files);
+		rc = seq_printf(m, "%llu\n", osfs.os_files);
 
 	return rc;
 }
@@ -544,7 +544,7 @@ int lprocfs_rd_filesfree(struct seq_file
 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
 			    OBD_STATFS_NODELAY);
 	if (!rc)
-		rc = seq_printf(m, LPU64"\n", osfs.os_ffree);
+		rc = seq_printf(m, "%llu\n", osfs.os_ffree);
 	return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_filesfree);
@@ -667,7 +667,7 @@ static void obd_connect_seq_flags2str(st
 		}
 	}
 	if (flags & ~(mask - 1))
-		seq_printf(m, "%sunknown flags "LPX64,
+		seq_printf(m, "%sunknown flags %#llx",
 				first ? sep : "", flags & ~(mask - 1));
 }
 
@@ -744,7 +744,7 @@ int lprocfs_rd_import(struct seq_file *m
 		      "       inflight: %u\n"
 		      "       unregistering: %u\n"
 		      "       timeouts: %u\n"
-		      "       avg_waittime: "LPU64" %s\n",
+		      "       avg_waittime: %llu %s\n",
 		      atomic_read(&imp->imp_inflight),
 		      atomic_read(&imp->imp_unregistering),
 		      atomic_read(&imp->imp_timeouts),
@@ -766,9 +766,9 @@ int lprocfs_rd_import(struct seq_file *m
 
 	seq_printf(m,
 		      "    transactions:\n"
-		      "       last_replay: "LPU64"\n"
-		      "       peer_committed: "LPU64"\n"
-		      "       last_checked: "LPU64"\n",
+		      "       last_replay: %llu\n"
+		      "       peer_committed: %llu\n"
+		      "       last_checked: %llu\n",
 		      imp->imp_last_replay_transno,
 		      imp->imp_peer_committed_transno,
 		      imp->imp_last_transno_checked);
@@ -785,7 +785,7 @@ int lprocfs_rd_import(struct seq_file *m
 			ret.lc_sum = sum;
 			seq_printf(m,
 				      "    %s_data_averages:\n"
-				      "       bytes_per_rpc: "LPU64"\n",
+				      "       bytes_per_rpc: %llu\n",
 				      rw ? "write" : "read",
 				      ret.lc_sum);
 		}
@@ -799,7 +799,7 @@ int lprocfs_rd_import(struct seq_file *m
 			do_div(sum, ret.lc_count);
 			ret.lc_sum = sum;
 			seq_printf(m,
-				      "       %s_per_rpc: "LPU64"\n",
+				      "       %s_per_rpc: %llu\n",
 				      header->lc_units, ret.lc_sum);
 			j = (int)ret.lc_sum;
 			if (j > 0)
@@ -868,7 +868,7 @@ int lprocfs_rd_timeouts(struct seq_file
 	LPROCFS_CLIMP_CHECK(obd);
 	imp = obd->u.cli.cl_import;
 
-	now = cfs_time_current_sec();
+	now = get_seconds();
 
 	/* Some network health info for kicks */
 	s2dhms(&ts, now - imp->imp_last_reply_time);
@@ -908,7 +908,7 @@ int lprocfs_rd_connect_flags(struct seq_
 
 	LPROCFS_CLIMP_CHECK(obd);
 	flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
-	seq_printf(m, "flags="LPX64"\n", flags);
+	seq_printf(m, "flags=%#llx\n", flags);
 	obd_connect_seq_flags2str(m, flags, "\n");
 	seq_printf(m, "\n");
 	LPROCFS_CLIMP_EXIT(obd);
@@ -1175,19 +1175,19 @@ static int lprocfs_stats_seq_show(struct
 	if (ctr.lc_count == 0)
 		goto out;
 
-	rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
+	rc = seq_printf(p, "%-25s %lld samples [%s]", hdr->lc_name,
 			ctr.lc_count, hdr->lc_units);
 
 	if (rc < 0)
 		goto out;
 
 	if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ctr.lc_count > 0)) {
-		rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
+		rc = seq_printf(p, " %lld %lld %lld",
 				ctr.lc_min, ctr.lc_max, ctr.lc_sum);
 		if (rc < 0)
 			goto out;
 		if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
-			rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
+			rc = seq_printf(p, " %lld", ctr.lc_sumsquare);
 		if (rc < 0)
 			goto out;
 	}
@@ -1196,7 +1196,7 @@ out:
 	return (rc < 0) ? rc : 0;
 }
 
-struct seq_operations lprocfs_stats_seq_sops = {
+static const struct seq_operations lprocfs_stats_seq_sops = {
 	.start	= lprocfs_stats_seq_start,
 	.stop	= lprocfs_stats_seq_stop,
 	.next	= lprocfs_stats_seq_next,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_object.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_object.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,18 +44,18 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 # include <linux/module.h>
 
 /* hash_long() */
-#include <linux/libcfs/libcfs_hash.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_disk.h>
-#include <lustre_fid.h>
-#include <lu_object.h>
-#include <lu_ref.h>
+#include "../../include/linux/libcfs/libcfs_hash.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_disk.h"
+#include "../include/lustre_fid.h"
+#include "../include/lu_object.h"
+#include "../include/lu_ref.h"
 #include <linux/list.h>
 
 static void lu_object_free(const struct lu_env *env, struct lu_object *o);
@@ -1994,7 +1994,7 @@ void lu_global_fini(void)
 
 static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx)
 {
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 	struct lprocfs_counter ret;
 
 	lprocfs_stats_collect(stats, idx, &ret);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_ref.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_ref.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_ref.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_ref.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,9 +42,9 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lu_ref.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lu_ref.h"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lustre_handles.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lustre_handles.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lustre_handles.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,9 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd_support.h>
-#include <lustre_handles.h>
-#include <lustre_lib.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_handles.h"
+#include "../include/lustre_lib.h"
 
 
 static __u64 handle_base;
@@ -97,7 +97,7 @@ void class_handle_hash(struct portals_ha
 	h->h_in = 1;
 	spin_unlock(&bucket->lock);
 
-	CDEBUG(D_INFO, "added object %p with handle "LPX64" to hash\n",
+	CDEBUG(D_INFO, "added object %p with handle %#llx to hash\n",
 	       h, h->h_cookie);
 }
 EXPORT_SYMBOL(class_handle_hash);
@@ -105,12 +105,12 @@ EXPORT_SYMBOL(class_handle_hash);
 static void class_handle_unhash_nolock(struct portals_handle *h)
 {
 	if (list_empty(&h->h_link)) {
-		CERROR("removing an already-removed handle ("LPX64")\n",
+		CERROR("removing an already-removed handle (%#llx)\n",
 		       h->h_cookie);
 		return;
 	}
 
-	CDEBUG(D_INFO, "removing object %p with handle "LPX64" from hash\n",
+	CDEBUG(D_INFO, "removing object %p with handle %#llx from hash\n",
 	       h, h->h_cookie);
 
 	spin_lock(&h->h_lock);
@@ -230,7 +230,7 @@ static int cleanup_all_handles(void)
 
 		spin_lock(&handle_hash[i].lock);
 		list_for_each_entry_rcu(h, &(handle_hash[i].head), h_link) {
-			CERROR("force clean handle "LPX64" addr %p ops %p\n",
+			CERROR("force clean handle %#llx addr %p ops %p\n",
 			       h->h_cookie, h, h->h_ops);
 
 			class_handle_unhash_nolock(h);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lustre_peer.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lustre_peer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lustre_peer.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,13 +36,13 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <obd.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-#include <lustre_ha.h>
-#include <lustre_net.h>
-#include <lprocfs_status.h>
+#include "../include/obd.h"
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_net.h"
+#include "../include/lprocfs_status.h"
 
 #define NIDS_MAX	32
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_ucred.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_ucred.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/lu_ucred.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/lu_ucred.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,10 +44,10 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <linux/libcfs/libcfs.h>
-#include <obd_support.h>
-#include <lu_object.h>
-#include <md_object.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/obd_support.h"
+#include "../include/lu_object.h"
+#include "../include/md_object.h"
 
 /* context key constructor/destructor: lu_ucred_key_init, lu_ucred_key_fini */
 LU_KEY_INIT_FINI(lu_ucred, struct lu_ucred);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -8,6 +8,3 @@ obdclass-y := linux/linux-module.o linux
 	      mea.o lu_object.o dt_object.o capa.o cl_object.o   \
 	      cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o idmap.o	   \
 	      lu_ucred.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/md_attrs.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/md_attrs.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/md_attrs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/md_attrs.c	2014-09-28 17:29:07.000000000 -0400
@@ -27,9 +27,9 @@
  * Author: Johann Lombardi <johann.lombardi@intel.com>
  */
 
-#include <lustre/lustre_idl.h>
-#include <obd.h>
-#include <md_object.h>
+#include "../include/lustre/lustre_idl.h"
+#include "../include/obd.h"
+#include "../include/md_object.h"
 
 /**
  * Initialize new \a lma. Only fid is stored.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/mea.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/mea.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/mea.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/mea.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,13 +33,13 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-#include <obd_class.h>
+#include "../include/obd_class.h"
 #include <linux/kmod.h>   /* for request_module() */
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
+#include "../include/lprocfs_status.h"
+#include "../include/lustre/lustre_idl.h"
 
 static int mea_last_char_hash(int count, char *name, int namelen)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obd_config.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obd_config.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obd_config.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obd_config.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,11 +39,11 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-#include <obd_class.h>
+#include "../include/obd_class.h"
 #include <linux/string.h>
-#include <lustre_log.h>
-#include <lprocfs_status.h>
-#include <lustre_param.h>
+#include "../include/lustre_log.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_param.h"
 
 #include "llog_internal.h"
 
@@ -1093,9 +1093,9 @@ int class_process_config(struct lustre_c
 		GOTO(out, err);
 	}
 	case LCFG_ADD_UUID: {
-		CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
-		       " (%s)\n", lustre_cfg_string(lcfg, 1),
-		       lcfg->lcfg_nid, libcfs_nid2str(lcfg->lcfg_nid));
+		CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid %#llx (%s)\n",
+		       lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid,
+		       libcfs_nid2str(lcfg->lcfg_nid));
 
 		err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
 		GOTO(out, err);
@@ -1161,7 +1161,7 @@ int class_process_config(struct lustre_c
 		char *tmp;
 		/* llite has no obd */
 		if ((class_match_param(lustre_cfg_string(lcfg, 1),
-				       PARAM_LLITE, 0) == 0) &&
+				       PARAM_LLITE, NULL) == 0) &&
 		    client_process_config) {
 			err = (*client_process_config)(lcfg);
 			GOTO(out, err);
@@ -1303,8 +1303,8 @@ int class_process_proc_param(char *prefi
 		/* Search proc entries */
 		while (lvars[j].name) {
 			var = &lvars[j];
-			if (class_match_param(key, (char *)var->name, 0) == 0 &&
-			    keylen == strlen(var->name)) {
+			if (class_match_param(key, (char *)var->name, NULL) == 0
+			    && keylen == strlen(var->name)) {
 				matched++;
 				rc = -EROFS;
 				if (var->fops && var->fops->write) {
@@ -1614,7 +1614,7 @@ int class_config_parse_rec(struct llog_r
 		ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num);
 
 	if (lcfg->lcfg_nid)
-		ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
+		ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n     ",
 				libcfs_nid2str(lcfg->lcfg_nid),
 				lcfg->lcfg_nid);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obd_mount.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obd_mount.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obd_mount.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obd_mount.c	2014-09-28 17:29:07.000000000 -0400
@@ -45,13 +45,13 @@
 #define D_MOUNT (D_SUPER|D_CONFIG/*|D_WARNING */)
 #define PRINT_CMD CDEBUG
 
-#include <obd.h>
-#include <lvfs.h>
-#include <obd_class.h>
-#include <lustre/lustre_user.h>
-#include <lustre_log.h>
-#include <lustre_disk.h>
-#include <lustre_param.h>
+#include "../include/obd.h"
+#include "../include/lvfs.h"
+#include "../include/obd_class.h"
+#include "../include/lustre/lustre_user.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_disk.h"
+#include "../include/lustre_param.h"
 
 static int (*client_fill_super)(struct super_block *sb,
 				struct vfsmount *mnt);
@@ -219,7 +219,6 @@ int lustre_start_mgc(struct super_block
 	lnet_nid_t nid;
 	char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
 	char *ptr;
-	int recov_bk;
 	int rc = 0, i = 0, j, len;
 
 	LASSERT(lsi->lsi_lmd);
@@ -269,6 +268,8 @@ int lustre_start_mgc(struct super_block
 
 	obd = class_name2obd(mgcname);
 	if (obd && !obd->obd_stopping) {
+		int recov_bk;
+
 		rc = obd_set_info_async(NULL, obd->obd_self_export,
 					strlen(KEY_MGSSEC), KEY_MGSSEC,
 					strlen(mgssec), mgssec, NULL);
@@ -429,16 +430,6 @@ int lustre_start_mgc(struct super_block
 	   so we know when we can get rid of the mgc. */
 	atomic_set(&obd->u.cli.cl_mgc_refcount, 1);
 
-	/* Try all connections, but only once. */
-	recov_bk = 1;
-	rc = obd_set_info_async(NULL, obd->obd_self_export,
-				sizeof(KEY_INIT_RECOV_BACKUP),
-				KEY_INIT_RECOV_BACKUP,
-				sizeof(recov_bk), &recov_bk, NULL);
-	if (rc)
-		/* nonfatal */
-		CWARN("can't set %s %d\n", KEY_INIT_RECOV_BACKUP, rc);
-
 	/* We connect to the MGS at setup, and don't disconnect until cleanup */
 	data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
 				  OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
@@ -1225,7 +1216,9 @@ int lustre_fill_super(struct super_block
 
 	if (lmd_is_client(lmd)) {
 		CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
-		if (!client_fill_super) {
+		if (client_fill_super == NULL)
+			request_module("lustre");
+		if (client_fill_super == NULL) {
 			LCONSOLE_ERROR_MSG(0x165, "Nothing registered for "
 					   "client mount! Is the 'lustre' "
 					   "module loaded?\n");
@@ -1308,6 +1301,7 @@ struct file_system_type lustre_fs_type =
 	.fs_flags     = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV |
 			FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE,
 };
+MODULE_ALIAS_FS("lustre");
 
 int lustre_register_fs(void)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obdo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obdo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/obdo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/obdo.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,8 +42,8 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <obd_class.h>
-#include <lustre/lustre_idl.h>
+#include "../include/obd_class.h"
+#include "../include/lustre/lustre_idl.h"
 
 void obdo_set_parent_fid(struct obdo *dst, const struct lu_fid *parent)
 {
@@ -117,7 +117,7 @@ EXPORT_SYMBOL(obdo_from_inode);
 
 void obdo_cpy_md(struct obdo *dst, struct obdo *src, obd_flag valid)
 {
-	CDEBUG(D_INODE, "src obdo "DOSTID" valid "LPX64", dst obdo "DOSTID"\n",
+	CDEBUG(D_INODE, "src obdo "DOSTID" valid %#llx, dst obdo "DOSTID"\n",
 	       POSTID(&src->o_oi), src->o_valid, POSTID(&dst->o_oi));
 	if (valid & OBD_MD_FLATIME)
 		dst->o_atime = src->o_atime;
@@ -252,7 +252,7 @@ void iattr_from_obdo(struct iattr *attr,
 	valid &= oa->o_valid;
 
 	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
-		CDEBUG(D_INODE, "valid "LPX64", new time "LPU64"/"LPU64"\n",
+		CDEBUG(D_INODE, "valid %#llx, new time %llu/%llu\n",
 		       oa->o_valid, oa->o_mtime, oa->o_ctime);
 
 	attr->ia_valid = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/statfs_pack.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/statfs_pack.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/statfs_pack.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/statfs_pack.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,10 +41,10 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 
-#include <lustre_export.h>
-#include <lustre_net.h>
-#include <obd_support.h>
-#include <obd_class.h>
+#include "../include/lustre_export.h"
+#include "../include/lustre_net.h"
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
 
 void statfs_pack(struct obd_statfs *osfs, struct kstatfs *sfs)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/uuid.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/uuid.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdclass/uuid.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdclass/uuid.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,10 +38,10 @@
 
 #define DEBUG_SUBSYSTEM S_CLASS
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_support.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
 
 
 static inline __u32 consume(int nob, __u8 **ptr)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/echo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/echo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/echo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/echo.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,11 @@
 
 #define DEBUG_SUBSYSTEM S_ECHO
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_debug.h>
-#include <lustre_dlm.h>
-#include <lprocfs_status.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_debug.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lprocfs_status.h"
 
 #include "echo_internal.h"
 
@@ -120,18 +120,18 @@ static int echo_create(const struct lu_e
 	struct obd_device *obd = class_exp2obd(exp);
 
 	if (!obd) {
-		CERROR("invalid client cookie "LPX64"\n",
+		CERROR("invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
 
-	if (!(oa->o_mode && S_IFMT)) {
+	if (!(oa->o_mode & S_IFMT)) {
 		CERROR("echo obd: no type!\n");
 		return -ENOENT;
 	}
 
 	if (!(oa->o_valid & OBD_MD_FLTYPE)) {
-		CERROR("invalid o_valid "LPX64"\n", oa->o_valid);
+		CERROR("invalid o_valid %#llx\n", oa->o_valid);
 		return -EINVAL;
 	}
 
@@ -150,13 +150,13 @@ static int echo_destroy(const struct lu_
 	struct obd_device *obd = class_exp2obd(exp);
 
 	if (!obd) {
-		CERROR("invalid client cookie "LPX64"\n",
+		CERROR("invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
 
 	if (!(oa->o_valid & OBD_MD_FLID)) {
-		CERROR("obdo missing FLID valid flag: "LPX64"\n", oa->o_valid);
+		CERROR("obdo missing FLID valid flag: %#llx\n", oa->o_valid);
 		return -EINVAL;
 	}
 
@@ -176,13 +176,13 @@ static int echo_getattr(const struct lu_
 	obd_id id = ostid_id(&oinfo->oi_oa->o_oi);
 
 	if (!obd) {
-		CERROR("invalid client cookie "LPX64"\n",
+		CERROR("invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
 
 	if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
-		CERROR("obdo missing FLID valid flag: "LPX64"\n",
+		CERROR("obdo missing FLID valid flag: %#llx\n",
 		       oinfo->oi_oa->o_valid);
 		return -EINVAL;
 	}
@@ -200,13 +200,13 @@ static int echo_setattr(const struct lu_
 	struct obd_device *obd = class_exp2obd(exp);
 
 	if (!obd) {
-		CERROR("invalid client cookie "LPX64"\n",
+		CERROR("invalid client cookie %#llx\n",
 		       exp->exp_handle.h_cookie);
 		return -EINVAL;
 	}
 
 	if (!(oinfo->oi_oa->o_valid & OBD_MD_FLID)) {
-		CERROR("obdo missing FLID valid flag: "LPX64"\n",
+		CERROR("obdo missing FLID valid flag: %#llx\n",
 		       oinfo->oi_oa->o_valid);
 		return -EINVAL;
 	}
@@ -327,7 +327,7 @@ static int echo_map_nb_to_lb(struct obdo
 			}
 		}
 
-		CDEBUG(D_PAGE, "$$$$ get page %p @ "LPU64" for %d\n",
+		CDEBUG(D_PAGE, "$$$$ get page %p @ %llu for %d\n",
 		       res->page, res->lnb_file_offset, res->len);
 
 		if (cmd & OBD_BRW_READ)
@@ -365,7 +365,7 @@ static int echo_finalize_lb(struct obdo
 		void       *addr;
 
 		if (page == NULL) {
-			CERROR("null page objid "LPU64":%p, buf %d/%d\n",
+			CERROR("null page objid %llu:%p, buf %d/%d\n",
 			       ostid_id(&obj->ioo_oid), page, i,
 			       obj->ioo_bufcnt);
 			return -EFAULT;
@@ -373,7 +373,7 @@ static int echo_finalize_lb(struct obdo
 
 		addr = kmap(page);
 
-		CDEBUG(D_PAGE, "$$$$ use page %p, addr %p@"LPU64"\n",
+		CDEBUG(D_PAGE, "$$$$ use page %p, addr %p@%llu\n",
 		       res->page, addr, res->lnb_file_offset);
 
 		if (verify) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/echo_client.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/echo_client.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/echo_client.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/echo_client.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,18 +35,18 @@
  */
 
 #define DEBUG_SUBSYSTEM S_ECHO
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_debug.h>
-#include <lprocfs_status.h>
-#include <cl_object.h>
-#include <md_object.h>
-#include <lustre_fid.h>
-#include <lustre_acl.h>
-#include <lustre_net.h>
+#include "../include/obd.h"
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_debug.h"
+#include "../include/lprocfs_status.h"
+#include "../include/cl_object.h"
+#include "../include/md_object.h"
+#include "../include/lustre_fid.h"
+#include "../include/lustre_acl.h"
+#include "../include/lustre_net.h"
 
 #include "echo_internal.h"
 
@@ -1228,7 +1228,7 @@ static int cl_echo_cancel0(struct lu_env
 	spin_lock(&ec->ec_lock);
 	list_for_each (el, &ec->ec_locks) {
 		ecl = list_entry (el, struct echo_lock, el_chain);
-		CDEBUG(D_INFO, "ecl: %p, cookie: "LPX64"\n", ecl, ecl->el_cookie);
+		CDEBUG(D_INFO, "ecl: %p, cookie: %#llx\n", ecl, ecl->el_cookie);
 		found = (ecl->el_cookie == cookie);
 		if (found) {
 			if (atomic_dec_and_test(&ecl->el_refcount))
@@ -1430,7 +1430,7 @@ echo_copyin_lsm (struct echo_device *ed,
 static inline void echo_md_build_name(struct lu_name *lname, char *name,
 				      __u64 id)
 {
-	sprintf(name, LPU64, id);
+	sprintf(name, "%llu", id);
 	lname->ln_name = name;
 	lname->ln_namelen = strlen(name);
 }
@@ -1540,7 +1540,7 @@ int echo_attr_get_complex(const struct l
 #endif
 out:
 	ma->ma_need = need;
-	CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64" ma_lmm=%p\n",
+	CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = %#llx ma_lmm=%p\n",
 	       rc, ma->ma_valid, ma->ma_lmm);
 	return rc;
 }
@@ -2408,7 +2408,7 @@ static int echo_client_page_debug_check(
 					addr + delta, OBD_ECHO_BLOCK_SIZE,
 					stripe_off, stripe_id);
 		if (rc2 != 0) {
-			CERROR ("Error in echo object "LPX64"\n", id);
+			CERROR ("Error in echo object %#llx\n", id);
 			rc = rc2;
 		}
 	}
@@ -2703,7 +2703,7 @@ echo_client_enqueue(struct obd_export *e
 	rc = cl_echo_enqueue(eco, offset, end, mode, &ulh->cookie);
 	if (rc == 0) {
 		oa->o_valid |= OBD_MD_FLHANDLE;
-		CDEBUG(D_INFO, "Cookie is "LPX64"\n", ulh->cookie);
+		CDEBUG(D_INFO, "Cookie is %#llx\n", ulh->cookie);
 	}
 	echo_put_object(eco);
 	return rc;
@@ -2718,7 +2718,7 @@ echo_client_cancel(struct obd_export *ex
 	if ((oa->o_valid & OBD_MD_FLHANDLE) == 0)
 		return -EINVAL;
 
-	CDEBUG(D_INFO, "Cookie is "LPX64"\n", cookie);
+	CDEBUG(D_INFO, "Cookie is %#llx\n", cookie);
 	return cl_echo_cancel(ed, cookie);
 }
 
@@ -3084,7 +3084,7 @@ static int echo_client_disconnect(struct
 		rc = obd_cancel(ec->ec_exp, ecl->ecl_object->eco_lsm,
 				 ecl->ecl_mode, &ecl->ecl_lock_handle);
 
-		CDEBUG (D_INFO, "Cancel lock on object "LPX64" on disconnect "
+		CDEBUG (D_INFO, "Cancel lock on object %#llx on disconnect "
 			"(%d)\n", ecl->ecl_object->eco_id, rc);
 
 		echo_put_object (ecl->ecl_object);
@@ -3113,7 +3113,7 @@ static struct obd_ops echo_client_obd_op
 
 int echo_client_init(void)
 {
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc;
 
 	lprocfs_echo_init_vars(&lvars);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/lproc_echo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/lproc_echo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/lproc_echo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/lproc_echo.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,25 +33,25 @@
  */
 #define DEBUG_SUBSYSTEM S_ECHO
 
-#include <lprocfs_status.h>
-#include <obd_class.h>
+#include "../include/lprocfs_status.h"
+#include "../include/obd_class.h"
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 LPROC_SEQ_FOPS_RO_TYPE(echo, uuid);
 static struct lprocfs_vars lprocfs_echo_obd_vars[] = {
 	{ "uuid",	 &echo_uuid_fops,	NULL, 0 },
-	{ 0 }
+	{ NULL }
 };
 
 LPROC_SEQ_FOPS_RO_TYPE(echo, numrefs);
 static struct lprocfs_vars lprocfs_echo_module_vars[] = {
 	{ "num_refs",     &echo_numrefs_fops,     NULL, 0 },
-	{ 0 }
+	{ NULL }
 };
 
 void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars)
 {
-    lvars->module_vars  = lprocfs_echo_module_vars;
-    lvars->obd_vars     = lprocfs_echo_obd_vars;
+	lvars->module_vars  = lprocfs_echo_module_vars;
+	lvars->obd_vars     = lprocfs_echo_obd_vars;
 }
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/obdecho/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/obdecho/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,2 @@
 obj-$(CONFIG_LUSTRE_FS) += obdecho.o
 obdecho-y := echo_client.o lproc_echo.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/lproc_osc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/lproc_osc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/lproc_osc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/lproc_osc.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,9 +36,9 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 #include <asm/statfs.h>
-#include <obd_cksum.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
+#include "../include/obd_cksum.h"
+#include "../include/obd_class.h"
+#include "../include/lprocfs_status.h"
 #include <linux/seq_file.h>
 #include "osc_internal.h"
 
@@ -693,11 +693,11 @@ static int osc_stats_seq_show(struct seq
 
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
 		   now.tv_sec, (unsigned long)now.tv_usec);
-	seq_printf(seq, "lockless_write_bytes\t\t"LPU64"\n",
+	seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
 		   stats->os_lockless_writes);
-	seq_printf(seq, "lockless_read_bytes\t\t"LPU64"\n",
+	seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
 		   stats->os_lockless_reads);
-	seq_printf(seq, "lockless_truncate\t\t"LPU64"\n",
+	seq_printf(seq, "lockless_truncate\t\t%llu\n",
 		   stats->os_lockless_truncates);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,7 +2,3 @@ obj-$(CONFIG_LUSTRE_FS) += osc.o
 osc-y := osc_request.o osc_dev.o osc_object.o \
 	 osc_page.o osc_lock.o osc_io.o osc_quota.o osc_cache.o
 osc-$(CONFIG_PROC_FS) += lproc_osc.o
-
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_cache.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_cache.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_cache.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_cache.c	2014-09-28 17:29:07.000000000 -0400
@@ -871,7 +871,8 @@ static int osc_extent_wait(const struct
 	LASSERT(sanity_check_nolock(ext) == 0);
 	/* `Kick' this extent only if the caller is waiting for it to be
 	 * written out. */
-	if (state == OES_INV && !ext->oe_urgent && !ext->oe_hp) {
+	if (state == OES_INV && !ext->oe_urgent && !ext->oe_hp &&
+	    !ext->oe_trunc_pending) {
 		if (ext->oe_state == OES_ACTIVE) {
 			ext->oe_urgent = 1;
 		} else if (ext->oe_state == OES_CACHE) {
@@ -922,8 +923,8 @@ static int osc_extent_truncate(struct os
 	int		    rc       = 0;
 
 	LASSERT(sanity_check(ext) == 0);
-	LASSERT(ext->oe_state == OES_TRUNC);
-	LASSERT(!ext->oe_urgent);
+	EASSERT(ext->oe_state == OES_TRUNC, ext);
+	EASSERT(!ext->oe_urgent, ext);
 
 	/* Request new lu_env.
 	 * We can't use that env from osc_cache_truncate_start() because
@@ -2153,7 +2154,7 @@ int osc_prep_async_page(struct osc_objec
 	INIT_LIST_HEAD(&oap->oap_rpc_item);
 
 	spin_lock_init(&oap->oap_lock);
-	CDEBUG(D_INFO, "oap %p page %p obj off "LPU64"\n",
+	CDEBUG(D_INFO, "oap %p page %p obj off %llu\n",
 	       oap, page, oap->oap_obj_off);
 	return 0;
 }
@@ -2594,7 +2595,7 @@ again:
 			break;
 		}
 
-		OSC_EXTENT_DUMP(D_CACHE, ext, "try to trunc:"LPU64".\n", size);
+		OSC_EXTENT_DUMP(D_CACHE, ext, "try to trunc:%llu.\n", size);
 
 		osc_extent_get(ext);
 		if (ext->oe_state == OES_ACTIVE) {
@@ -2655,7 +2656,7 @@ again:
 			LASSERT(oio->oi_trunc == NULL);
 			oio->oi_trunc = osc_extent_get(ext);
 			OSC_EXTENT_DUMP(D_CACHE, ext,
-					"trunc at "LPU64"\n", size);
+					"trunc at %llu\n", size);
 		}
 		osc_extent_put(env, ext);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_cl_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_cl_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_cl_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_cl_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -46,13 +46,13 @@
 #ifndef OSC_CL_INTERNAL_H
 #define OSC_CL_INTERNAL_H
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd.h>
+#include "../include/obd.h"
 /* osc_build_res_name() */
-#include <obd_ost.h>
-#include <cl_object.h>
-#include <lclient.h>
+#include "../include/obd_ost.h"
+#include "../include/cl_object.h"
+#include "../include/lclient.h"
 #include "osc_internal.h"
 
 /** \defgroup osc osc
@@ -118,7 +118,7 @@ struct osc_object {
 	 * True if locking against this stripe got -EUSERS.
 	 */
 	int		oo_contended;
-	cfs_time_t	 oo_contention_time;
+	unsigned long	 oo_contention_time;
 	/**
 	 * List of pages in transfer.
 	 */
@@ -387,7 +387,7 @@ struct osc_page {
 	/**
 	 * Submit time - the time when the page is starting RPC. For debugging.
 	 */
-	cfs_time_t	    ops_submit_time;
+	unsigned long	    ops_submit_time;
 
 	/**
 	 * A lock of which we hold a reference covers this page. Only used by
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_dev.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_dev.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_dev.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_dev.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,7 +41,7 @@
 #define DEBUG_SUBSYSTEM S_OSC
 
 /* class_name2obd() */
-#include <obd_class.h>
+#include "../include/obd_class.h"
 
 #include "osc_cl_internal.h"
 
@@ -61,32 +61,32 @@ struct lu_kmem_descr osc_caches[] = {
 	{
 		.ckd_cache = &osc_lock_kmem,
 		.ckd_name  = "osc_lock_kmem",
-		.ckd_size  = sizeof (struct osc_lock)
+		.ckd_size  = sizeof(struct osc_lock)
 	},
 	{
 		.ckd_cache = &osc_object_kmem,
 		.ckd_name  = "osc_object_kmem",
-		.ckd_size  = sizeof (struct osc_object)
+		.ckd_size  = sizeof(struct osc_object)
 	},
 	{
 		.ckd_cache = &osc_thread_kmem,
 		.ckd_name  = "osc_thread_kmem",
-		.ckd_size  = sizeof (struct osc_thread_info)
+		.ckd_size  = sizeof(struct osc_thread_info)
 	},
 	{
 		.ckd_cache = &osc_session_kmem,
 		.ckd_name  = "osc_session_kmem",
-		.ckd_size  = sizeof (struct osc_session)
+		.ckd_size  = sizeof(struct osc_session)
 	},
 	{
 		.ckd_cache = &osc_req_kmem,
 		.ckd_name  = "osc_req_kmem",
-		.ckd_size  = sizeof (struct osc_req)
+		.ckd_size  = sizeof(struct osc_req)
 	},
 	{
 		.ckd_cache = &osc_extent_kmem,
 		.ckd_name  = "osc_extent_kmem",
-		.ckd_size  = sizeof (struct osc_extent)
+		.ckd_size  = sizeof(struct osc_extent)
 	},
 	{
 		.ckd_cache = &osc_quota_kmem,
@@ -132,6 +132,7 @@ static void osc_key_fini(const struct lu
 			 struct lu_context_key *key, void *data)
 {
 	struct osc_thread_info *info = data;
+
 	OBD_SLAB_FREE_PTR(info, osc_thread_kmem);
 }
 
@@ -156,6 +157,7 @@ static void osc_session_fini(const struc
 			     struct lu_context_key *key, void *data)
 {
 	struct osc_session *info = data;
+
 	OBD_SLAB_FREE_PTR(info, osc_session_kmem);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ void osc_update_next_shrink(struct clien
 /*
  * cl integration.
  */
-#include <cl_object.h>
+#include "../include/cl_object.h"
 
 extern struct ptlrpc_request_set *PTLRPCD_SET;
 
@@ -112,7 +112,7 @@ int osc_cancel_base(struct lustre_handle
 
 int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 		   __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-		   int *flags, void *data, struct lustre_handle *lockh,
+		   __u64 *flags, void *data, struct lustre_handle *lockh,
 		   int unref);
 
 int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo,
@@ -136,7 +136,7 @@ extern spinlock_t osc_ast_guard;
 int osc_cleanup(struct obd_device *obd);
 int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int lproc_osc_attach_seqstat(struct obd_device *dev);
 void lprocfs_osc_init_vars(struct lprocfs_static_vars *lvars);
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_io.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_io.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -204,7 +204,7 @@ static void osc_page_touch_at(const stru
 	 *
 	 * here
 	 */
-	CDEBUG(D_INODE, "stripe KMS %sincreasing "LPU64"->"LPU64" "LPU64"\n",
+	CDEBUG(D_INODE, "stripe KMS %sincreasing %llu->%llu %llu\n",
 	       kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms,
 	       loi->loi_lvb.lvb_size);
 
@@ -355,7 +355,7 @@ static int trunc_check_cb(const struct l
 
 	if (oap->oap_cmd & OBD_BRW_WRITE &&
 	    !list_empty(&oap->oap_pending_item))
-		CL_PAGE_DEBUG(D_ERROR, env, page, "exists " LPU64 "/%s.\n",
+		CL_PAGE_DEBUG(D_ERROR, env, page, "exists %llu/%s.\n",
 				start, current->comm);
 
 	{
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_lock.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_lock.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_lock.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_lock.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,9 +40,9 @@
 
 #define DEBUG_SUBSYSTEM S_OSC
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 /* fid_build_reg_res_name() */
-#include <lustre_fid.h>
+#include "../include/lustre_fid.h"
 
 #include "osc_cl_internal.h"
 
@@ -369,20 +369,19 @@ static void osc_lock_lvb_update(const st
 		if (size > dlmlock->l_policy_data.l_extent.end)
 			size = dlmlock->l_policy_data.l_extent.end + 1;
 		if (size >= oinfo->loi_kms) {
-			LDLM_DEBUG(dlmlock, "lock acquired, setting rss="LPU64
-				   ", kms="LPU64, lvb->lvb_size, size);
+			LDLM_DEBUG(dlmlock, "lock acquired, setting rss=%llu, kms=%llu",
+				   lvb->lvb_size, size);
 			valid |= CAT_KMS;
 			attr->cat_kms = size;
 		} else {
-			LDLM_DEBUG(dlmlock, "lock acquired, setting rss="
-				   LPU64"; leaving kms="LPU64", end="LPU64,
+			LDLM_DEBUG(dlmlock, "lock acquired, setting rss=%llu; leaving kms=%llu, end=%llu",
 				   lvb->lvb_size, oinfo->loi_kms,
 				   dlmlock->l_policy_data.l_extent.end);
 		}
 		ldlm_lock_allow_match_locked(dlmlock);
 	} else if (rc == -ENAVAIL && olck->ols_glimpse) {
-		CDEBUG(D_INODE, "glimpsed, setting rss="LPU64"; leaving"
-		       " kms="LPU64"\n", lvb->lvb_size, oinfo->loi_kms);
+		CDEBUG(D_INODE, "glimpsed, setting rss=%llu; leaving kms=%llu\n",
+		       lvb->lvb_size, oinfo->loi_kms);
 	} else
 		valid = 0;
 
@@ -1400,7 +1399,7 @@ static int osc_lock_print(const struct l
 	/*
 	 * XXX print ldlm lock and einfo properly.
 	 */
-	(*p)(env, cookie, "%p %#16llx "LPX64" %d %p ",
+	(*p)(env, cookie, "%p %#16llx %#llx %d %p ",
 	     lock->ols_lock, lock->ols_flags, lock->ols_handle.cookie,
 	     lock->ols_state, lock->ols_owner);
 	osc_lvb_print(env, cookie, p, &lock->ols_lvb);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_object.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_object.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_object.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_object.c	2014-09-28 17:29:07.000000000 -0400
@@ -128,8 +128,7 @@ static void osc_object_free(const struct
 int osc_lvb_print(const struct lu_env *env, void *cookie,
 		  lu_printer_t p, const struct ost_lvb *lvb)
 {
-	return (*p)(env, cookie, "size: "LPU64" mtime: "LPU64" atime: "LPU64" "
-		    "ctime: "LPU64" blocks: "LPU64,
+	return (*p)(env, cookie, "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu",
 		    lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime,
 		    lvb->lvb_ctime, lvb->lvb_blocks);
 }
@@ -142,8 +141,7 @@ static int osc_object_print(const struct
 	struct osc_async_rc *ar    = &oinfo->loi_ar;
 
 	(*p)(env, cookie, "id: "DOSTID" "
-	     "idx: %d gen: %d kms_valid: %u kms "LPU64" "
-	     "rc: %d force_sync: %d min_xid: "LPU64" ",
+	     "idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ",
 	     POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx,
 	     oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms,
 	     ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid);
@@ -179,7 +177,7 @@ int osc_attr_set(const struct lu_env *en
 	if (valid & CAT_BLOCKS)
 		lvb->lvb_blocks = attr->cat_blocks;
 	if (valid & CAT_KMS) {
-		CDEBUG(D_CACHE, "set kms from "LPU64"to "LPU64"\n",
+		CDEBUG(D_CACHE, "set kms from %llu to %llu\n",
 		       oinfo->loi_kms, (__u64)attr->cat_kms);
 		loi_kms_set(oinfo, attr->cat_kms);
 	}
@@ -213,8 +211,8 @@ int osc_object_is_contended(struct osc_o
 {
 	struct osc_device *dev  = lu2osc_dev(obj->oo_cl.co_lu.lo_dev);
 	int osc_contention_time = dev->od_contention_time;
-	cfs_time_t cur_time     = cfs_time_current();
-	cfs_time_t retry_time;
+	unsigned long cur_time     = cfs_time_current();
+	unsigned long retry_time;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION))
 		return 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_page.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_page.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_page.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_page.c	2014-09-28 17:29:07.000000000 -0400
@@ -70,7 +70,7 @@ static int osc_page_is_dlocked(const str
 	struct lustre_handle   *lockh;
 	ldlm_policy_data_t     *policy;
 	ldlm_mode_t	     dlmmode;
-	int		     flags;
+	__u64                   flags;
 
 	might_sleep();
 
@@ -352,7 +352,7 @@ static const char *osc_list(struct list_
 	return list_empty(head) ? "-" : "+";
 }
 
-static inline cfs_time_t osc_submit_duration(struct osc_page *opg)
+static inline unsigned long osc_submit_duration(struct osc_page *opg)
 {
 	if (opg->ops_submit_time == 0)
 		return 0;
@@ -371,7 +371,7 @@ static int osc_page_print(const struct l
 
 	return (*printer)(env, cookie, LUSTRE_OSC_NAME"-page@%p: "
 			  "1< %#x %d %u %s %s > "
-			  "2< "LPU64" %u %u %#x %#x | %p %p %p > "
+			  "2< %llu %u %u %#x %#x | %p %p %p > "
 			  "3< %s %p %d %lu %d > "
 			  "4< %d %d %d %lu %s | %s %s %s %s > "
 			  "5< %s %s %s %s | %d %s | %d %s %s>\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_quota.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_quota.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_quota.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_quota.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,7 +28,7 @@
  * Code originally extracted from quota directory
  */
 
-#include <obd_ost.h>
+#include "../include/obd_ost.h"
 #include "osc_internal.h"
 
 static inline struct osc_quota_info *osc_oqi_alloc(obd_uid id)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_request.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_request.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/osc/osc_request.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/osc/osc_request.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,21 +36,21 @@
 
 #define DEBUG_SUBSYSTEM S_OSC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
 
-#include <lustre_dlm.h>
-#include <lustre_net.h>
-#include <lustre/lustre_user.h>
-#include <obd_cksum.h>
-#include <obd_ost.h>
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre/lustre_user.h"
+#include "../include/obd_cksum.h"
+#include "../include/obd_ost.h"
 
-#include <lustre_ha.h>
-#include <lprocfs_status.h>
-#include <lustre_log.h>
-#include <lustre_debug.h>
-#include <lustre_param.h>
-#include <lustre_fid.h>
+#include "../include/lustre_ha.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_debug.h"
+#include "../include/lustre_param.h"
+#include "../include/lustre_fid.h"
 #include "osc_internal.h"
 #include "osc_cl_internal.h"
 
@@ -483,7 +483,7 @@ int osc_real_create(struct obd_export *e
 		}
 	}
 
-	CDEBUG(D_HA, "transno: "LPD64"\n",
+	CDEBUG(D_HA, "transno: %lld\n",
 	       lustre_msg_get_transno(req->rq_repmsg));
 out_req:
 	ptlrpc_req_finished(req);
@@ -635,7 +635,7 @@ static int osc_sync(const struct lu_env
  * locks added to @cancels list. */
 static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa,
 				   struct list_head *cancels,
-				   ldlm_mode_t mode, int lock_flags)
+				   ldlm_mode_t mode, __u64 lock_flags)
 {
 	struct ldlm_namespace *ns = exp->exp_obd->obd_namespace;
 	struct ldlm_res_id res_id;
@@ -836,7 +836,7 @@ static void osc_announce_cached(struct c
 	oa->o_dropped = cli->cl_lost_grant;
 	cli->cl_lost_grant = 0;
 	client_obd_list_unlock(&cli->cl_loi_list_lock);
-	CDEBUG(D_CACHE,"dirty: "LPU64" undirty: %u dropped %u grant: "LPU64"\n",
+	CDEBUG(D_CACHE,"dirty: %llu undirty: %u dropped %u grant: %llu\n",
 	       oa->o_dirty, oa->o_undirty, oa->o_dropped, oa->o_grant);
 
 }
@@ -859,7 +859,7 @@ static void __osc_update_grant(struct cl
 static void osc_update_grant(struct client_obd *cli, struct ost_body *body)
 {
 	if (body->oa.o_valid & OBD_MD_FLGRANT) {
-		CDEBUG(D_CACHE, "got "LPU64" extra grant\n", body->oa.o_grant);
+		CDEBUG(D_CACHE, "got %llu extra grant\n", body->oa.o_grant);
 		__osc_update_grant(cli, body->oa.o_grant);
 	}
 }
@@ -966,8 +966,8 @@ int osc_shrink_grant_to_target(struct cl
 
 static int osc_should_shrink_grant(struct client_obd *client)
 {
-	cfs_time_t time = cfs_time_current();
-	cfs_time_t next_shrink = client->cl_next_shrink_grant;
+	unsigned long time = cfs_time_current();
+	unsigned long next_shrink = client->cl_next_shrink_grant;
 
 	if ((client->cl_import->imp_connect_data.ocd_connect_flags &
 	     OBD_CONNECT_GRANT_SHRINK) == 0)
@@ -1313,11 +1313,11 @@ static int osc_brw_prep_request(int cmd,
 			  ergo(i > 0 && i < page_count - 1,
 			       poff == 0 && pg->count == PAGE_CACHE_SIZE)   &&
 			  ergo(i == page_count - 1, poff == 0)),
-			 "i: %d/%d pg: %p off: "LPU64", count: %u\n",
+			 "i: %d/%d pg: %p off: %llu, count: %u\n",
 			 i, page_count, pg, pg->off, pg->count);
 		LASSERTF(i == 0 || pg->off > pg_prev->off,
-			 "i %d p_c %u pg %p [pri %lu ind %lu] off "LPU64
-			 " prev_pg %p [pri %lu ind %lu] off "LPU64"\n",
+			 "i %d p_c %u pg %p [pri %lu ind %lu] off %llu"
+			 " prev_pg %p [pri %lu ind %lu] off %llu\n",
 			 i, page_count,
 			 pg->pg, page_private(pg->pg), pg->pg->index, pg->off,
 			 pg_prev->pg, page_private(pg_prev->pg),
@@ -1452,7 +1452,7 @@ static int check_write_checksum(struct o
 		      "likely false positive due to mmap IO (bug 11742)";
 
 	LCONSOLE_ERROR_MSG(0x132, "BAD WRITE CHECKSUM: %s: from %s inode "DFID
-			   " object "DOSTID" extent ["LPU64"-"LPU64"]\n",
+			   " object "DOSTID" extent [%llu-%llu]\n",
 			   msg, libcfs_nid2str(peer->nid),
 			   oa->o_valid & OBD_MD_FLFID ? oa->o_parent_seq : (__u64)0,
 			   oa->o_valid & OBD_MD_FLFID ? oa->o_parent_oid : 0,
@@ -1492,7 +1492,7 @@ static int osc_brw_fini_request(struct p
 	    body->oa.o_valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) {
 		unsigned int qid[MAXQUOTAS] = { body->oa.o_uid, body->oa.o_gid };
 
-		CDEBUG(D_QUOTA, "setdq for [%u %u] with valid "LPX64", flags %x\n",
+		CDEBUG(D_QUOTA, "setdq for [%u %u] with valid %#llx, flags %x\n",
 		       body->oa.o_uid, body->oa.o_gid, body->oa.o_valid,
 		       body->oa.o_flags);
 		osc_quota_setdq(cli, qid, body->oa.o_valid, body->oa.o_flags);
@@ -1570,15 +1570,10 @@ static int osc_brw_fini_request(struct p
 			router = libcfs_nid2str(req->rq_bulk->bd_sender);
 		}
 
-		if (server_cksum == ~0 && rc > 0) {
-			CERROR("Protocol error: server %s set the 'checksum' "
-			       "bit, but didn't send a checksum.  Not fatal, "
-			       "but please notify on http://bugs.whamcloud.com/\n",
-			       libcfs_nid2str(peer->nid));
-		} else if (server_cksum != client_cksum) {
+		if (server_cksum != client_cksum) {
 			LCONSOLE_ERROR_MSG(0x133, "%s: BAD READ CHECKSUM: from "
 					   "%s%s%s inode "DFID" object "DOSTID
-					   " extent ["LPU64"-"LPU64"]\n",
+					   " extent [%llu-%llu]\n",
 					   req->rq_import->imp_obd->obd_name,
 					   libcfs_nid2str(peer->nid),
 					   via, router,
@@ -1644,7 +1639,7 @@ restart_bulk:
 	if (resends) {
 		req->rq_generation_set = 1;
 		req->rq_import_generation = generation;
-		req->rq_sent = cfs_time_current_sec() + resends;
+		req->rq_sent = get_seconds() + resends;
 	}
 
 	rc = ptlrpc_queue_wait(req);
@@ -1727,9 +1722,9 @@ static int osc_brw_redo_request(struct p
 	/* cap resend delay to the current request timeout, this is similar to
 	 * what ptlrpc does (see after_reply()) */
 	if (aa->aa_resends > new_req->rq_timeout)
-		new_req->rq_sent = cfs_time_current_sec() + new_req->rq_timeout;
+		new_req->rq_sent = get_seconds() + new_req->rq_timeout;
 	else
-		new_req->rq_sent = cfs_time_current_sec() + aa->aa_resends;
+		new_req->rq_sent = get_seconds() + aa->aa_resends;
 	new_req->rq_generation_set = 1;
 	new_req->rq_import_generation = request->rq_import_generation;
 
@@ -1935,8 +1930,7 @@ static int brw_interpret(const struct lu
 		    client_should_resend(aa->aa_resends, aa->aa_cli)) {
 			rc = osc_brw_redo_request(req, aa, rc);
 		} else {
-			CERROR("%s: too many resent retries for object: "
-			       ""LPU64":"LPU64", rc = %d.\n",
+			CERROR("%s: too many resent retries for object: %llu:%llu, rc = %d.\n",
 			       req->rq_import->imp_obd->obd_name,
 			       POSTID(&aa->aa_oa->o_oi), rc);
 		}
@@ -2326,7 +2320,7 @@ static int osc_enqueue_fini(struct ptlrp
 	if ((intent != 0 && rc == ELDLM_LOCK_ABORTED && agl == 0) ||
 	    (rc == 0)) {
 		*flags |= LDLM_FL_LVB_READY;
-		CDEBUG(D_INODE,"got kms "LPU64" blocks "LPU64" mtime "LPU64"\n",
+		CDEBUG(D_INODE,"got kms %llu blocks %llu mtime %llu\n",
 		       lvb->lvb_size, lvb->lvb_blocks, lvb->lvb_mtime);
 	}
 
@@ -2398,7 +2392,7 @@ static int osc_enqueue_interpret(const s
 }
 
 void osc_update_enqueue(struct lustre_handle *lov_lockhp,
-			struct lov_oinfo *loi, int flags,
+			struct lov_oinfo *loi, __u64 flags,
 			struct ost_lvb *lvb, __u32 mode, int rc)
 {
 	struct ldlm_lock *lock = ldlm_handle2lock(lov_lockhp);
@@ -2414,12 +2408,11 @@ void osc_update_enqueue(struct lustre_ha
 		if (tmp > lock->l_policy_data.l_extent.end)
 			tmp = lock->l_policy_data.l_extent.end + 1;
 		if (tmp >= loi->loi_kms) {
-			LDLM_DEBUG(lock, "lock acquired, setting rss="LPU64
-				   ", kms="LPU64, loi->loi_lvb.lvb_size, tmp);
+			LDLM_DEBUG(lock, "lock acquired, setting rss=%llu, kms=%llu",
+				   loi->loi_lvb.lvb_size, tmp);
 			loi_kms_set(loi, tmp);
 		} else {
-			LDLM_DEBUG(lock, "lock acquired, setting rss="
-				   LPU64"; leaving kms="LPU64", end="LPU64,
+			LDLM_DEBUG(lock, "lock acquired, setting rss=%llu; leaving kms=%llu, end=%llu",
 				   loi->loi_lvb.lvb_size, loi->loi_kms,
 				   lock->l_policy_data.l_extent.end);
 		}
@@ -2428,8 +2421,8 @@ void osc_update_enqueue(struct lustre_ha
 		LASSERT(lock != NULL);
 		loi->loi_lvb = *lvb;
 		ldlm_lock_allow_match(lock);
-		CDEBUG(D_INODE, "glimpsed, setting rss="LPU64"; leaving"
-		       " kms="LPU64"\n", loi->loi_lvb.lvb_size, loi->loi_kms);
+		CDEBUG(D_INODE, "glimpsed, setting rss=%llu; leaving kms=%llu\n",
+		       loi->loi_lvb.lvb_size, loi->loi_kms);
 		rc = ELDLM_OK;
 	}
 
@@ -2462,7 +2455,7 @@ int osc_enqueue_base(struct obd_export *
 	struct obd_device *obd = exp->exp_obd;
 	struct ptlrpc_request *req = NULL;
 	int intent = *flags & LDLM_FL_HAS_INTENT;
-	int match_lvb = (agl != 0 ? 0 : LDLM_FL_LVB_READY);
+	__u64 match_lvb = (agl != 0 ? 0 : LDLM_FL_LVB_READY);
 	ldlm_mode_t mode;
 	int rc;
 
@@ -2613,11 +2606,11 @@ static int osc_enqueue(struct obd_export
 
 int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 		   __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-		   int *flags, void *data, struct lustre_handle *lockh,
+		   __u64 *flags, void *data, struct lustre_handle *lockh,
 		   int unref)
 {
 	struct obd_device *obd = exp->exp_obd;
-	int lflags = *flags;
+	__u64 lflags = *flags;
 	ldlm_mode_t rc;
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_MATCH))
@@ -3267,7 +3260,7 @@ static int osc_reconnect(const struct lu
 		cli->cl_lost_grant = 0;
 		client_obd_list_unlock(&cli->cl_loi_list_lock);
 
-		CDEBUG(D_RPCTRACE, "ocd_connect_flags: "LPX64" ocd_version: %d"
+		CDEBUG(D_RPCTRACE, "ocd_connect_flags: %#llx ocd_version: %d"
 		       " ocd_grant: %d, lost: %ld.\n", data->ocd_connect_flags,
 		       data->ocd_version, data->ocd_grant, lost_grant);
 	}
@@ -3428,7 +3421,7 @@ static int brw_queue_work(const struct l
 
 int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	struct client_obd	  *cli = &obd->u.cli;
 	void		       *handler;
 	int			rc;
@@ -3552,7 +3545,7 @@ int osc_cleanup(struct obd_device *obd)
 
 int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg)
 {
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc = 0;
 
 	lprocfs_osc_init_vars(&lvars);
@@ -3619,7 +3612,7 @@ extern struct lock_class_key osc_ast_gua
 
 int __init osc_init(void)
 {
-	struct lprocfs_static_vars lvars = { 0 };
+	struct lprocfs_static_vars lvars = { NULL };
 	int rc;
 
 	/* print an address of _any_ initialized kernel symbol from this
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/client.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/client.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/client.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/client.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,12 +38,12 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-#include <lustre_ha.h>
-#include <lustre_import.h>
-#include <lustre_req_layout.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_req_layout.h"
 
 #include "ptlrpc_internal.h"
 
@@ -283,7 +283,7 @@ static void ptlrpc_at_adj_net_latency(st
 {
 	unsigned int nl, oldnl;
 	struct imp_at *at;
-	time_t now = cfs_time_current_sec();
+	time_t now = get_seconds();
 
 	LASSERT(req->rq_import);
 	at = &req->rq_import->imp_at;
@@ -367,13 +367,13 @@ static int ptlrpc_at_recv_early_reply(st
 	olddl = req->rq_deadline;
 	/* server assumes it now has rq_timeout from when it sent the
 	 * early reply, so client should give it at least that long. */
-	req->rq_deadline = cfs_time_current_sec() + req->rq_timeout +
+	req->rq_deadline = get_seconds() + req->rq_timeout +
 			   ptlrpc_at_get_net_latency(req);
 
 	DEBUG_REQ(D_ADAPTTO, req,
 		  "Early reply #%d, new deadline in "CFS_DURATION_T"s "
 		  "("CFS_DURATION_T"s)", req->rq_early_count,
-		  cfs_time_sub(req->rq_deadline, cfs_time_current_sec()),
+		  cfs_time_sub(req->rq_deadline, get_seconds()),
 		  cfs_time_sub(req->rq_deadline, olddl));
 
 	return rc;
@@ -1181,7 +1181,7 @@ static void ptlrpc_save_versions(struct
 
 	LASSERT(versions);
 	lustre_msg_set_versions(reqmsg, versions);
-	CDEBUG(D_INFO, "Client save versions ["LPX64"/"LPX64"]\n",
+	CDEBUG(D_INFO, "Client save versions [%#llx/%#llx]\n",
 	       versions[0], versions[1]);
 }
 
@@ -1202,7 +1202,7 @@ static int after_reply(struct ptlrpc_req
 
 	LASSERT(obd != NULL);
 	/* repbuf must be unlinked */
-	LASSERT(!req->rq_receiving_reply && !req->rq_must_unlink);
+	LASSERT(!req->rq_receiving_reply && !req->rq_reply_unlink);
 
 	if (req->rq_reply_truncate) {
 		if (ptlrpc_no_resend(req)) {
@@ -1248,7 +1248,7 @@ static int after_reply(struct ptlrpc_req
 	/* retry indefinitely on EINPROGRESS */
 	if (lustre_msg_get_status(req->rq_repmsg) == -EINPROGRESS &&
 	    ptlrpc_no_resend(req) == 0 && !req->rq_no_retry_einprogress) {
-		time_t	now = cfs_time_current_sec();
+		time_t	now = get_seconds();
 
 		DEBUG_REQ(D_RPCTRACE, req, "Resending request on EINPROGRESS");
 		req->rq_resend = 1;
@@ -1395,7 +1395,7 @@ static int ptlrpc_send_new_req(struct pt
 	int rc;
 
 	LASSERT(req->rq_phase == RQ_PHASE_NEW);
-	if (req->rq_sent && (req->rq_sent > cfs_time_current_sec()) &&
+	if (req->rq_sent && (req->rq_sent > get_seconds()) &&
 	    (!req->rq_generation_set ||
 	     req->rq_import_generation == imp->imp_generation))
 		return 0;
@@ -1451,7 +1451,7 @@ static int ptlrpc_send_new_req(struct pt
 	}
 
 	CDEBUG(D_RPCTRACE, "Sending RPC pname:cluuid:pid:xid:nid:opc"
-	       " %s:%s:%d:"LPU64":%s:%d\n", current_comm(),
+	       " %s:%s:%d:%llu:%s:%d\n", current_comm(),
 	       imp->imp_obd->obd_uuid.uuid,
 	       lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
 	       libcfs_nid2str(imp->imp_connection->c_peer.nid),
@@ -1496,6 +1496,8 @@ static inline int ptlrpc_set_producer(st
  * and no more replies are expected.
  * (it is possible to get less replies than requests sent e.g. due to timed out
  * requests or requests that we had trouble to send out)
+ *
+ * NOTE: This function contains a potential schedule point (cond_resched()).
  */
 int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
 {
@@ -1513,6 +1515,14 @@ int ptlrpc_check_set(const struct lu_env
 		int unregistered = 0;
 		int rc = 0;
 
+		/* This schedule point is mainly for the ptlrpcd caller of this
+		 * function.  Most ptlrpc sets are not long-lived and unbounded
+		 * in length, but at the least the set used by the ptlrpcd is.
+		 * Since the processing time is unbounded, we need to insert an
+		 * explicit schedule point to make the thread well-behaved.
+		 */
+		cond_resched();
+
 		if (req->rq_phase == RQ_PHASE_NEW &&
 		    ptlrpc_send_new_req(req)) {
 			force_timer_recalc = 1;
@@ -1524,7 +1534,7 @@ int ptlrpc_check_set(const struct lu_env
 
 		/* delayed resend - skip */
 		if (req->rq_phase == RQ_PHASE_RPC && req->rq_resend &&
-		    req->rq_sent > cfs_time_current_sec())
+		    req->rq_sent > get_seconds())
 			continue;
 
 		if (!(req->rq_phase == RQ_PHASE_RPC ||
@@ -1688,9 +1698,7 @@ int ptlrpc_check_set(const struct lu_env
 						/* ensure previous bulk fails */
 						old_xid = req->rq_xid;
 						req->rq_xid = ptlrpc_next_xid();
-						CDEBUG(D_HA, "resend bulk "
-						       "old x"LPU64
-						       " new x"LPU64"\n",
+						CDEBUG(D_HA, "resend bulk old x%llu new x%llu\n",
 						       old_xid, req->rq_xid);
 					}
 				}
@@ -1821,7 +1829,7 @@ interpret:
 
 		CDEBUG(req->rq_reqmsg != NULL ? D_RPCTRACE : 0,
 			"Completed RPC pname:cluuid:pid:xid:nid:"
-			"opc %s:%s:%d:"LPU64":%s:%d\n",
+			"opc %s:%s:%d:%llu:%s:%d\n",
 			current_comm(), imp->imp_obd->obd_uuid.uuid,
 			lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
 			libcfs_nid2str(imp->imp_connection->c_peer.nid),
@@ -1884,7 +1892,7 @@ int ptlrpc_expire_one_request(struct ptl
 		  "/real "CFS_DURATION_T"]",
 		  req->rq_net_err ? "failed due to network error" :
 		     ((req->rq_real_sent == 0 ||
-		       cfs_time_before(req->rq_real_sent, req->rq_sent) ||
+		       time_before((unsigned long)req->rq_real_sent, (unsigned long)req->rq_sent) ||
 		       cfs_time_aftereq(req->rq_real_sent, req->rq_deadline)) ?
 		      "timed out for sent delay" : "timed out for slow reply"),
 		  req->rq_sent, req->rq_real_sent);
@@ -1945,7 +1953,7 @@ int ptlrpc_expired_set(void *data)
 {
 	struct ptlrpc_request_set *set = data;
 	struct list_head		*tmp;
-	time_t		     now = cfs_time_current_sec();
+	time_t		     now = get_seconds();
 
 	LASSERT(set != NULL);
 
@@ -2028,7 +2036,7 @@ EXPORT_SYMBOL(ptlrpc_interrupted_set);
 int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
 {
 	struct list_head	    *tmp;
-	time_t		 now = cfs_time_current_sec();
+	time_t		 now = get_seconds();
 	int		    timeout = 0;
 	struct ptlrpc_request *req;
 	int		    deadline;
@@ -2346,7 +2354,7 @@ int ptlrpc_unregister_reply(struct ptlrp
 	 */
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) &&
 	    async && request->rq_reply_deadline == 0)
-		request->rq_reply_deadline = cfs_time_current_sec()+LONG_UNLINK;
+		request->rq_reply_deadline = get_seconds()+LONG_UNLINK;
 
 	/*
 	 * Nothing left to do.
@@ -2396,9 +2404,10 @@ int ptlrpc_unregister_reply(struct ptlrp
 		}
 
 		LASSERT(rc == -ETIMEDOUT);
-		DEBUG_REQ(D_WARNING, request, "Unexpectedly long timeout "
-			  "rvcng=%d unlnk=%d", request->rq_receiving_reply,
-			  request->rq_must_unlink);
+		DEBUG_REQ(D_WARNING, request,
+			  "Unexpectedly long timeout rvcng=%d unlnk=%d/%d",
+			  request->rq_receiving_reply,
+			  request->rq_req_unlink, request->rq_reply_unlink);
 	}
 	return 0;
 }
@@ -2456,11 +2465,11 @@ void ptlrpc_free_committed(struct obd_im
 
 	if (imp->imp_peer_committed_transno == imp->imp_last_transno_checked &&
 	    imp->imp_generation == imp->imp_last_generation_checked) {
-		CDEBUG(D_INFO, "%s: skip recheck: last_committed "LPU64"\n",
+		CDEBUG(D_INFO, "%s: skip recheck: last_committed %llu\n",
 		       imp->imp_obd->obd_name, imp->imp_peer_committed_transno);
 		return;
 	}
-	CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n",
+	CDEBUG(D_RPCTRACE, "%s: committing for last_committed %llu gen %d\n",
 	       imp->imp_obd->obd_name, imp->imp_peer_committed_transno,
 	       imp->imp_generation);
 
@@ -2498,7 +2507,7 @@ void ptlrpc_free_committed(struct obd_im
 			continue;
 		}
 
-		DEBUG_REQ(D_INFO, req, "commit (last_committed "LPU64")",
+		DEBUG_REQ(D_INFO, req, "commit (last_committed %llu)",
 			  imp->imp_peer_committed_transno);
 free_req:
 		ptlrpc_free_request(req);
@@ -2530,10 +2539,19 @@ EXPORT_SYMBOL(ptlrpc_cleanup_client);
 void ptlrpc_resend_req(struct ptlrpc_request *req)
 {
 	DEBUG_REQ(D_HA, req, "going to resend");
+	spin_lock(&req->rq_lock);
+
+	/* Request got reply but linked to the import list still.
+	   Let ptlrpc_check_set() to process it. */
+	if (ptlrpc_client_replied(req)) {
+		spin_unlock(&req->rq_lock);
+		DEBUG_REQ(D_HA, req, "it has reply, so skip it");
+		return;
+	}
+
 	lustre_msg_set_handle(req->rq_reqmsg, &(struct lustre_handle){ 0 });
 	req->rq_status = -EAGAIN;
 
-	spin_lock(&req->rq_lock);
 	req->rq_resend = 1;
 	req->rq_net_err = 0;
 	req->rq_timedout = 0;
@@ -2542,7 +2560,7 @@ void ptlrpc_resend_req(struct ptlrpc_req
 
 		/* ensure previous bulk fails */
 		req->rq_xid = ptlrpc_next_xid();
-		CDEBUG(D_HA, "resend bulk old x"LPU64" new x"LPU64"\n",
+		CDEBUG(D_HA, "resend bulk old x%llu new x%llu\n",
 		       old_xid, req->rq_xid);
 	}
 	ptlrpc_client_wake_req(req);
@@ -2705,7 +2723,7 @@ static int ptlrpc_replay_interpret(const
 		LASSERTF(lustre_msg_get_transno(req->rq_reqmsg) ==
 			 lustre_msg_get_transno(req->rq_repmsg) ||
 			 lustre_msg_get_transno(req->rq_repmsg) == 0,
-			 LPX64"/"LPX64"\n",
+			 "%#llx/%#llx\n",
 			 lustre_msg_get_transno(req->rq_reqmsg),
 			 lustre_msg_get_transno(req->rq_repmsg));
 	}
@@ -2721,8 +2739,8 @@ static int ptlrpc_replay_interpret(const
 	/* transaction number shouldn't be bigger than the latest replayed */
 	if (req->rq_transno > lustre_msg_get_transno(req->rq_reqmsg)) {
 		DEBUG_REQ(D_ERROR, req,
-			  "Reported transno "LPU64" is bigger than the "
-			  "replayed one: "LPU64, req->rq_transno,
+			  "Reported transno %llu is bigger than the replayed one: %llu",
+			  req->rq_transno,
 			  lustre_msg_get_transno(req->rq_reqmsg));
 		GOTO(out, rc = -EINVAL);
 	}
@@ -2907,7 +2925,7 @@ static spinlock_t ptlrpc_last_xid_lock;
 #define YEAR_2004 (1ULL << 30)
 void ptlrpc_init_xid(void)
 {
-	time_t now = cfs_time_current_sec();
+	time_t now = get_seconds();
 
 	spin_lock_init(&ptlrpc_last_xid_lock);
 	if (now < YEAR_2004) {
@@ -2996,7 +3014,7 @@ static void ptlrpcd_add_work_req(struct
 {
 	/* re-initialize the req */
 	req->rq_timeout		= obd_timeout;
-	req->rq_sent		= cfs_time_current_sec();
+	req->rq_sent		= get_seconds();
 	req->rq_deadline	= req->rq_sent + req->rq_timeout;
 	req->rq_reply_deadline	= req->rq_deadline;
 	req->rq_phase		= RQ_PHASE_INTERPRET;
@@ -3062,7 +3080,7 @@ void *ptlrpcd_alloc_work(struct obd_impo
 	req->rq_interpret_reply = work_interpreter;
 	/* don't want reply */
 	req->rq_receiving_reply = 0;
-	req->rq_must_unlink = 0;
+	req->rq_req_unlink = req->rq_reply_unlink = 0;
 	req->rq_no_delay = req->rq_no_resend = 1;
 	req->rq_pill.rc_fmt = (void *)&worker_format;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/connection.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/connection.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/connection.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/connection.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,9 +35,9 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
 
 #include "ptlrpc_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/errno.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/errno.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/errno.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/errno.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,8 +25,8 @@
  * Copyright (c) 2013, Intel Corporation.
  */
 
-#include <linux/libcfs/libcfs.h>
-#include <lustre/lustre_errno.h>
+#include "../../include/linux/libcfs/libcfs.h"
+#include "../include/lustre/lustre_errno.h"
 
 /*
  * The two translation tables below must define a one-to-one mapping between
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/events.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/events.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/events.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/events.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,14 +36,14 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 # ifdef __mips64__
 #  include <linux/kernel.h>
 # endif
 
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_sec.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_sec.h"
 #include "ptlrpc_internal.h"
 
 lnet_handle_eq_t   ptlrpc_eq_h;
@@ -63,19 +63,20 @@ void request_out_callback(lnet_event_t *
 	DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status);
 
 	sptlrpc_request_out_callback(req);
-	req->rq_real_sent = cfs_time_current_sec();
+	spin_lock(&req->rq_lock);
+	req->rq_real_sent = get_seconds();
+	if (ev->unlinked)
+		req->rq_req_unlink = 0;
 
 	if (ev->type == LNET_EVENT_UNLINK || ev->status != 0) {
 
 		/* Failed send: make it seem like the reply timed out, just
 		 * like failing sends in client.c does currently...  */
 
-		spin_lock(&req->rq_lock);
 		req->rq_net_err = 1;
-		spin_unlock(&req->rq_lock);
-
 		ptlrpc_client_wake_req(req);
 	}
+	spin_unlock(&req->rq_lock);
 
 	ptlrpc_req_finished(req);
 }
@@ -102,7 +103,7 @@ void reply_in_callback(lnet_event_t *ev)
 	req->rq_receiving_reply = 0;
 	req->rq_early = 0;
 	if (ev->unlinked)
-		req->rq_must_unlink = 0;
+		req->rq_reply_unlink = 0;
 
 	if (ev->status)
 		goto out_wake;
@@ -145,6 +146,8 @@ void reply_in_callback(lnet_event_t *ev)
 		/* Real reply */
 		req->rq_rep_swab_mask = 0;
 		req->rq_replied = 1;
+		/* Got reply, no resend required */
+		req->rq_resend = 0;
 		req->rq_reply_off = ev->offset;
 		req->rq_nob_received = ev->mlength;
 		/* LNetMDUnlink can't be called under the LNET_LOCK,
@@ -155,7 +158,7 @@ void reply_in_callback(lnet_event_t *ev)
 			  ev->mlength, ev->offset, req->rq_replen);
 	}
 
-	req->rq_import->imp_last_reply_time = cfs_time_current_sec();
+	req->rq_import->imp_last_reply_time = get_seconds();
 
 out_wake:
 	/* NB don't unlock till after wakeup; req can disappear under us
@@ -307,7 +310,7 @@ void request_in_callback(lnet_event_t *e
 			/* We moaned above already... */
 			return;
 		}
-		req = ptlrpc_request_cache_alloc(ALLOC_ATOMIC_TRY);
+		req = ptlrpc_request_cache_alloc(GFP_ATOMIC);
 		if (req == NULL) {
 			CERROR("Can't allocate incoming request descriptor: "
 			       "Dropping %s RPC from %s\n",
@@ -334,7 +337,7 @@ void request_in_callback(lnet_event_t *e
 	INIT_LIST_HEAD(&req->rq_exp_list);
 	atomic_set(&req->rq_refcount, 1);
 	if (ev->type == LNET_EVENT_PUT)
-		CDEBUG(D_INFO, "incoming req@%p x"LPU64" msgsize %u\n",
+		CDEBUG(D_INFO, "incoming req@%p x%llu msgsize %u\n",
 		       req, req->rq_xid, ev->mlength);
 
 	CDEBUG(D_RPCTRACE, "peer: %s\n", libcfs_id2str(req->rq_peer));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- * Somewhat simplified version of the gss api.
- *
- * Dug Song <dugsong@monkey.org>
- * Andy Adamson <andros@umich.edu>
- * Bruce Fields <bfields@umich.edu>
- * Copyright (c) 2000 The Regents of the University of Michigan
- *
- */
-
-#ifndef __PTLRPC_GSS_GSS_API_H_
-#define __PTLRPC_GSS_GSS_API_H_
-
-struct gss_api_mech;
-
-/* The mechanism-independent gss-api context: */
-struct gss_ctx {
-	struct gss_api_mech    *mech_type;
-	void		   *internal_ctx_id;
-};
-
-#define GSS_C_NO_BUFFER	 ((rawobj_t) 0)
-#define GSS_C_NO_CONTEXT	((struct gss_ctx *) 0)
-#define GSS_C_NULL_OID	  ((rawobj_t) 0)
-
-/*
- * gss-api prototypes; note that these are somewhat simplified versions of
- * the prototypes specified in RFC 2744.
- */
-__u32 lgss_import_sec_context(
-		rawobj_t		*input_token,
-		struct gss_api_mech     *mech,
-		struct gss_ctx	 **ctx);
-__u32 lgss_copy_reverse_context(
-		struct gss_ctx	  *ctx,
-		struct gss_ctx	 **ctx_new);
-__u32 lgss_inquire_context(
-		struct gss_ctx	  *ctx,
-		unsigned long	   *endtime);
-__u32 lgss_get_mic(
-		struct gss_ctx	  *ctx,
-		int		      msgcnt,
-		rawobj_t		*msgs,
-		int		      iovcnt,
-		lnet_kiov_t	     *iovs,
-		rawobj_t		*mic_token);
-__u32 lgss_verify_mic(
-		struct gss_ctx	  *ctx,
-		int		      msgcnt,
-		rawobj_t		*msgs,
-		int		      iovcnt,
-		lnet_kiov_t	     *iovs,
-		rawobj_t		*mic_token);
-__u32 lgss_wrap(
-		struct gss_ctx	  *ctx,
-		rawobj_t		*gsshdr,
-		rawobj_t		*msg,
-		int		      msg_buflen,
-		rawobj_t		*out_token);
-__u32 lgss_unwrap(
-		struct gss_ctx	  *ctx,
-		rawobj_t		*gsshdr,
-		rawobj_t		*token,
-		rawobj_t		*out_msg);
-__u32 lgss_prep_bulk(
-		struct gss_ctx	  *gctx,
-		struct ptlrpc_bulk_desc *desc);
-__u32 lgss_wrap_bulk(
-		struct gss_ctx	  *gctx,
-		struct ptlrpc_bulk_desc *desc,
-		rawobj_t		*token,
-		int		      adj_nob);
-__u32 lgss_unwrap_bulk(
-		struct gss_ctx	  *gctx,
-		struct ptlrpc_bulk_desc *desc,
-		rawobj_t		*token,
-		int		      adj_nob);
-__u32 lgss_delete_sec_context(
-		struct gss_ctx	 **ctx);
-int lgss_display(
-		struct gss_ctx	  *ctx,
-		char		    *buf,
-		int		      bufsize);
-
-struct subflavor_desc {
-	__u32	   sf_subflavor;
-	__u32	   sf_qop;
-	__u32	   sf_service;
-	char	   *sf_name;
-};
-
-/* Each mechanism is described by the following struct: */
-struct gss_api_mech {
-	struct list_head	      gm_list;
-	struct module	   *gm_owner;
-	char		   *gm_name;
-	rawobj_t		gm_oid;
-	atomic_t	    gm_count;
-	struct gss_api_ops     *gm_ops;
-	int		     gm_sf_num;
-	struct subflavor_desc  *gm_sfs;
-};
-
-/* and must provide the following operations: */
-struct gss_api_ops {
-	__u32 (*gss_import_sec_context)(
-			rawobj_t	       *input_token,
-			struct gss_ctx	 *ctx);
-	__u32 (*gss_copy_reverse_context)(
-			struct gss_ctx	 *ctx,
-			struct gss_ctx	 *ctx_new);
-	__u32 (*gss_inquire_context)(
-			struct gss_ctx	 *ctx,
-			unsigned long	  *endtime);
-	__u32 (*gss_get_mic)(
-			struct gss_ctx	 *ctx,
-			int		     msgcnt,
-			rawobj_t	       *msgs,
-			int		     iovcnt,
-			lnet_kiov_t	    *iovs,
-			rawobj_t	       *mic_token);
-	__u32 (*gss_verify_mic)(
-			struct gss_ctx	 *ctx,
-			int		     msgcnt,
-			rawobj_t	       *msgs,
-			int		     iovcnt,
-			lnet_kiov_t	    *iovs,
-			rawobj_t	       *mic_token);
-	__u32 (*gss_wrap)(
-			struct gss_ctx	 *ctx,
-			rawobj_t	       *gsshdr,
-			rawobj_t	       *msg,
-			int		     msg_buflen,
-			rawobj_t	       *out_token);
-	__u32 (*gss_unwrap)(
-			struct gss_ctx	 *ctx,
-			rawobj_t	       *gsshdr,
-			rawobj_t	       *token,
-			rawobj_t	       *out_msg);
-	__u32 (*gss_prep_bulk)(
-			struct gss_ctx	 *gctx,
-			struct ptlrpc_bulk_desc *desc);
-	__u32 (*gss_wrap_bulk)(
-			struct gss_ctx	 *gctx,
-			struct ptlrpc_bulk_desc *desc,
-			rawobj_t	       *token,
-			int		     adj_nob);
-	__u32 (*gss_unwrap_bulk)(
-			struct gss_ctx	 *gctx,
-			struct ptlrpc_bulk_desc *desc,
-			rawobj_t	       *token,
-			int		     adj_nob);
-	void (*gss_delete_sec_context)(
-			void		   *ctx);
-	int  (*gss_display)(
-			struct gss_ctx	 *ctx,
-			char		   *buf,
-			int		     bufsize);
-};
-
-int lgss_mech_register(struct gss_api_mech *mech);
-void lgss_mech_unregister(struct gss_api_mech *mech);
-
-struct gss_api_mech * lgss_OID_to_mech(rawobj_t *oid);
-struct gss_api_mech * lgss_name_to_mech(char *name);
-struct gss_api_mech * lgss_subflavor_to_mech(__u32 subflavor);
-
-struct gss_api_mech * lgss_mech_get(struct gss_api_mech *mech);
-void lgss_mech_put(struct gss_api_mech *mech);
-
-#endif /* __PTLRPC_GSS_GSS_API_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  minimal asn1 for generic encoding/decoding of gss tokens
- *
- *  Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
- *  lib/gssapi/krb5/gssapiP_krb5.h, and others
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- */
-
-/*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, 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 M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-#define SIZEOF_INT 4
-
-/* from gssapi_err_generic.h */
-#define G_BAD_SERVICE_NAME		       (-2045022976L)
-#define G_BAD_STRING_UID			 (-2045022975L)
-#define G_NOUSER				 (-2045022974L)
-#define G_VALIDATE_FAILED			(-2045022973L)
-#define G_BUFFER_ALLOC			   (-2045022972L)
-#define G_BAD_MSG_CTX			    (-2045022971L)
-#define G_WRONG_SIZE			     (-2045022970L)
-#define G_BAD_USAGE			      (-2045022969L)
-#define G_UNKNOWN_QOP			    (-2045022968L)
-#define G_NO_HOSTNAME			    (-2045022967L)
-#define G_BAD_HOSTNAME			   (-2045022966L)
-#define G_WRONG_MECH			     (-2045022965L)
-#define G_BAD_TOK_HEADER			 (-2045022964L)
-#define G_BAD_DIRECTION			  (-2045022963L)
-#define G_TOK_TRUNC			      (-2045022962L)
-#define G_REFLECT				(-2045022961L)
-#define G_WRONG_TOKID			    (-2045022960L)
-
-#define g_OID_equal(o1, o2) \
-	(((o1)->len == (o2)->len) && \
-	 (memcmp((o1)->data, (o2)->data, (int) (o1)->len) == 0))
-
-__u32 g_verify_token_header(rawobj_t *mech,
-			    int *body_size,
-			    unsigned char **buf_in,
-			    int toksize);
-
-__u32 g_get_mech_oid(rawobj_t *mech,
-		     rawobj_t *in_buf);
-
-int g_token_size(rawobj_t *mech,
-		 unsigned int body_size);
-
-void g_make_token_header(rawobj_t *mech,
-			 int body_size,
-			 unsigned char **buf);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,505 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/ptlrpc/gss/gss_bulk.c
- *
- * Author: Eric Mei <eric.mei@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-#include <linux/crypto.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
-			  struct ptlrpc_request *req,
-			  struct ptlrpc_bulk_desc *desc)
-{
-	struct gss_cli_ctx	      *gctx;
-	struct lustre_msg	       *msg;
-	struct ptlrpc_bulk_sec_desc     *bsd;
-	rawobj_t			 token;
-	__u32			    maj;
-	int			      offset;
-	int			      rc;
-
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_read || req->rq_bulk_write);
-
-	gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-	LASSERT(gctx->gc_mechctx);
-
-	switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
-	case SPTLRPC_SVC_NULL:
-		LASSERT(req->rq_reqbuf->lm_bufcount >= 3);
-		msg = req->rq_reqbuf;
-		offset = msg->lm_bufcount - 1;
-		break;
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		LASSERT(req->rq_reqbuf->lm_bufcount >= 4);
-		msg = req->rq_reqbuf;
-		offset = msg->lm_bufcount - 2;
-		break;
-	case SPTLRPC_SVC_PRIV:
-		LASSERT(req->rq_clrbuf->lm_bufcount >= 2);
-		msg = req->rq_clrbuf;
-		offset = msg->lm_bufcount - 1;
-		break;
-	default:
-		LBUG();
-	}
-
-	bsd = lustre_msg_buf(msg, offset, sizeof(*bsd));
-	bsd->bsd_version = 0;
-	bsd->bsd_flags = 0;
-	bsd->bsd_type = SPTLRPC_BULK_DEFAULT;
-	bsd->bsd_svc = SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc);
-
-	if (bsd->bsd_svc == SPTLRPC_BULK_SVC_NULL)
-		return 0;
-
-	LASSERT(bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG ||
-		bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV);
-
-	if (req->rq_bulk_read) {
-		/*
-		 * bulk read: prepare receiving pages only for privacy mode.
-		 */
-		if (bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV)
-			return gss_cli_prep_bulk(req, desc);
-	} else {
-		/*
-		 * bulk write: sign or encrypt bulk pages.
-		 */
-		bsd->bsd_nob = desc->bd_nob;
-
-		if (bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG) {
-			/* integrity mode */
-			token.data = bsd->bsd_data;
-			token.len = lustre_msg_buflen(msg, offset) -
-				    sizeof(*bsd);
-
-			maj = lgss_get_mic(gctx->gc_mechctx, 0, NULL,
-					   desc->bd_iov_count, desc->bd_iov,
-					   &token);
-			if (maj != GSS_S_COMPLETE) {
-				CWARN("failed to sign bulk data: %x\n", maj);
-				return -EACCES;
-			}
-		} else {
-			/* privacy mode */
-			if (desc->bd_iov_count == 0)
-				return 0;
-
-			rc = sptlrpc_enc_pool_get_pages(desc);
-			if (rc) {
-				CERROR("bulk write: failed to allocate "
-				       "encryption pages: %d\n", rc);
-				return rc;
-			}
-
-			token.data = bsd->bsd_data;
-			token.len = lustre_msg_buflen(msg, offset) -
-				    sizeof(*bsd);
-
-			maj = lgss_wrap_bulk(gctx->gc_mechctx, desc, &token, 0);
-			if (maj != GSS_S_COMPLETE) {
-				CWARN("fail to encrypt bulk data: %x\n", maj);
-				return -EACCES;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
-			    struct ptlrpc_request *req,
-			    struct ptlrpc_bulk_desc *desc)
-{
-	struct gss_cli_ctx	      *gctx;
-	struct lustre_msg	       *rmsg, *vmsg;
-	struct ptlrpc_bulk_sec_desc     *bsdr, *bsdv;
-	rawobj_t			 token;
-	__u32			    maj;
-	int			      roff, voff;
-
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_read || req->rq_bulk_write);
-
-	switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
-	case SPTLRPC_SVC_NULL:
-		vmsg = req->rq_repdata;
-		LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 3);
-		voff = vmsg->lm_bufcount - 1;
-
-		rmsg = req->rq_reqbuf;
-		LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 3);
-		roff = rmsg->lm_bufcount - 1; /* last segment */
-		break;
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		vmsg = req->rq_repdata;
-		LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 4);
-		voff = vmsg->lm_bufcount - 2;
-
-		rmsg = req->rq_reqbuf;
-		LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 4);
-		roff = rmsg->lm_bufcount - 2; /* second last segment */
-		break;
-	case SPTLRPC_SVC_PRIV:
-		vmsg = req->rq_repdata;
-		LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 2);
-		voff = vmsg->lm_bufcount - 1;
-
-		rmsg = req->rq_clrbuf;
-		LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 2);
-		roff = rmsg->lm_bufcount - 1; /* last segment */
-		break;
-	default:
-		LBUG();
-	}
-
-	bsdr = lustre_msg_buf(rmsg, roff, sizeof(*bsdr));
-	bsdv = lustre_msg_buf(vmsg, voff, sizeof(*bsdv));
-	LASSERT(bsdr && bsdv);
-
-	if (bsdr->bsd_version != bsdv->bsd_version ||
-	    bsdr->bsd_type != bsdv->bsd_type ||
-	    bsdr->bsd_svc != bsdv->bsd_svc) {
-		CERROR("bulk security descriptor mismatch: "
-		       "(%u,%u,%u) != (%u,%u,%u)\n",
-		       bsdr->bsd_version, bsdr->bsd_type, bsdr->bsd_svc,
-		       bsdv->bsd_version, bsdv->bsd_type, bsdv->bsd_svc);
-		return -EPROTO;
-	}
-
-	LASSERT(bsdv->bsd_svc == SPTLRPC_BULK_SVC_NULL ||
-		bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG ||
-		bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV);
-
-	/*
-	 * in privacy mode if return success, make sure bd_nob_transferred
-	 * is the actual size of the clear text, otherwise upper layer
-	 * may be surprised.
-	 */
-	if (req->rq_bulk_write) {
-		if (bsdv->bsd_flags & BSD_FL_ERR) {
-			CERROR("server reported bulk i/o failure\n");
-			return -EIO;
-		}
-
-		if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV)
-			desc->bd_nob_transferred = desc->bd_nob;
-	} else {
-		/*
-		 * bulk read, upon return success, bd_nob_transferred is
-		 * the size of plain text actually received.
-		 */
-		gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-		LASSERT(gctx->gc_mechctx);
-
-		if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG) {
-			int i, nob;
-
-			/* fix the actual data size */
-			for (i = 0, nob = 0; i < desc->bd_iov_count; i++) {
-				if (desc->bd_iov[i].kiov_len + nob >
-				    desc->bd_nob_transferred) {
-					desc->bd_iov[i].kiov_len =
-						desc->bd_nob_transferred - nob;
-				}
-				nob += desc->bd_iov[i].kiov_len;
-			}
-
-			token.data = bsdv->bsd_data;
-			token.len = lustre_msg_buflen(vmsg, voff) -
-				    sizeof(*bsdv);
-
-			maj = lgss_verify_mic(gctx->gc_mechctx, 0, NULL,
-					      desc->bd_iov_count, desc->bd_iov,
-					      &token);
-			if (maj != GSS_S_COMPLETE) {
-				CERROR("failed to verify bulk read: %x\n", maj);
-				return -EACCES;
-			}
-		} else if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV) {
-			desc->bd_nob = bsdv->bsd_nob;
-			if (desc->bd_nob == 0)
-				return 0;
-
-			token.data = bsdv->bsd_data;
-			token.len = lustre_msg_buflen(vmsg, voff) -
-				    sizeof(*bsdr);
-
-			maj = lgss_unwrap_bulk(gctx->gc_mechctx, desc,
-					       &token, 1);
-			if (maj != GSS_S_COMPLETE) {
-				CERROR("failed to decrypt bulk read: %x\n",
-				       maj);
-				return -EACCES;
-			}
-
-			desc->bd_nob_transferred = desc->bd_nob;
-		}
-	}
-
-	return 0;
-}
-
-static int gss_prep_bulk(struct ptlrpc_bulk_desc *desc,
-			 struct gss_ctx *mechctx)
-{
-	int     rc;
-
-	if (desc->bd_iov_count == 0)
-		return 0;
-
-	rc = sptlrpc_enc_pool_get_pages(desc);
-	if (rc)
-		return rc;
-
-	if (lgss_prep_bulk(mechctx, desc) != GSS_S_COMPLETE)
-		return -EACCES;
-
-	return 0;
-}
-
-int gss_cli_prep_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc)
-{
-	int	     rc;
-
-	LASSERT(req->rq_cli_ctx);
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_read);
-
-	if (SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_BULK_SVC_PRIV)
-		return 0;
-
-	rc = gss_prep_bulk(desc, ctx2gctx(req->rq_cli_ctx)->gc_mechctx);
-	if (rc)
-		CERROR("bulk read: failed to prepare encryption "
-		       "pages: %d\n", rc);
-
-	return rc;
-}
-
-int gss_svc_prep_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc)
-{
-	struct gss_svc_reqctx	*grctx;
-	struct ptlrpc_bulk_sec_desc  *bsd;
-	int			   rc;
-
-	LASSERT(req->rq_svc_ctx);
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_write);
-
-	grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	LASSERT(grctx->src_reqbsd);
-	LASSERT(grctx->src_repbsd);
-	LASSERT(grctx->src_ctx);
-	LASSERT(grctx->src_ctx->gsc_mechctx);
-
-	bsd = grctx->src_reqbsd;
-	if (bsd->bsd_svc != SPTLRPC_BULK_SVC_PRIV)
-		return 0;
-
-	rc = gss_prep_bulk(desc, grctx->src_ctx->gsc_mechctx);
-	if (rc)
-		CERROR("bulk write: failed to prepare encryption "
-		       "pages: %d\n", rc);
-
-	return rc;
-}
-
-int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
-			struct ptlrpc_bulk_desc *desc)
-{
-	struct gss_svc_reqctx	*grctx;
-	struct ptlrpc_bulk_sec_desc  *bsdr, *bsdv;
-	rawobj_t		      token;
-	__u32			 maj;
-
-	LASSERT(req->rq_svc_ctx);
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_write);
-
-	grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-
-	LASSERT(grctx->src_reqbsd);
-	LASSERT(grctx->src_repbsd);
-	LASSERT(grctx->src_ctx);
-	LASSERT(grctx->src_ctx->gsc_mechctx);
-
-	bsdr = grctx->src_reqbsd;
-	bsdv = grctx->src_repbsd;
-
-	/* bsdr has been sanity checked during unpacking */
-	bsdv->bsd_version = 0;
-	bsdv->bsd_type = SPTLRPC_BULK_DEFAULT;
-	bsdv->bsd_svc = bsdr->bsd_svc;
-	bsdv->bsd_flags = 0;
-
-	switch (bsdv->bsd_svc) {
-	case SPTLRPC_BULK_SVC_INTG:
-		token.data = bsdr->bsd_data;
-		token.len = grctx->src_reqbsd_size - sizeof(*bsdr);
-
-		maj = lgss_verify_mic(grctx->src_ctx->gsc_mechctx, 0, NULL,
-				      desc->bd_iov_count, desc->bd_iov, &token);
-		if (maj != GSS_S_COMPLETE) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("failed to verify bulk signature: %x\n", maj);
-			return -EACCES;
-		}
-		break;
-	case SPTLRPC_BULK_SVC_PRIV:
-		if (bsdr->bsd_nob != desc->bd_nob) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("prepared nob %d doesn't match the actual "
-			       "nob %d\n", desc->bd_nob, bsdr->bsd_nob);
-			return -EPROTO;
-		}
-
-		if (desc->bd_iov_count == 0) {
-			LASSERT(desc->bd_nob == 0);
-			break;
-		}
-
-		token.data = bsdr->bsd_data;
-		token.len = grctx->src_reqbsd_size - sizeof(*bsdr);
-
-		maj = lgss_unwrap_bulk(grctx->src_ctx->gsc_mechctx,
-				       desc, &token, 0);
-		if (maj != GSS_S_COMPLETE) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("failed decrypt bulk data: %x\n", maj);
-			return -EACCES;
-		}
-		break;
-	}
-
-	return 0;
-}
-
-int gss_svc_wrap_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc)
-{
-	struct gss_svc_reqctx	*grctx;
-	struct ptlrpc_bulk_sec_desc  *bsdr, *bsdv;
-	rawobj_t		      token;
-	__u32			 maj;
-	int			   rc;
-
-	LASSERT(req->rq_svc_ctx);
-	LASSERT(req->rq_pack_bulk);
-	LASSERT(req->rq_bulk_read);
-
-	grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-
-	LASSERT(grctx->src_reqbsd);
-	LASSERT(grctx->src_repbsd);
-	LASSERT(grctx->src_ctx);
-	LASSERT(grctx->src_ctx->gsc_mechctx);
-
-	bsdr = grctx->src_reqbsd;
-	bsdv = grctx->src_repbsd;
-
-	/* bsdr has been sanity checked during unpacking */
-	bsdv->bsd_version = 0;
-	bsdv->bsd_type = SPTLRPC_BULK_DEFAULT;
-	bsdv->bsd_svc = bsdr->bsd_svc;
-	bsdv->bsd_flags = 0;
-
-	switch (bsdv->bsd_svc) {
-	case SPTLRPC_BULK_SVC_INTG:
-		token.data = bsdv->bsd_data;
-		token.len = grctx->src_repbsd_size - sizeof(*bsdv);
-
-		maj = lgss_get_mic(grctx->src_ctx->gsc_mechctx, 0, NULL,
-				   desc->bd_iov_count, desc->bd_iov, &token);
-		if (maj != GSS_S_COMPLETE) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("failed to sign bulk data: %x\n", maj);
-			return -EACCES;
-		}
-		break;
-	case SPTLRPC_BULK_SVC_PRIV:
-		bsdv->bsd_nob = desc->bd_nob;
-
-		if (desc->bd_iov_count == 0) {
-			LASSERT(desc->bd_nob == 0);
-			break;
-		}
-
-		rc = sptlrpc_enc_pool_get_pages(desc);
-		if (rc) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("bulk read: failed to allocate encryption "
-			       "pages: %d\n", rc);
-			return rc;
-		}
-
-		token.data = bsdv->bsd_data;
-		token.len = grctx->src_repbsd_size - sizeof(*bsdv);
-
-		maj = lgss_wrap_bulk(grctx->src_ctx->gsc_mechctx,
-				     desc, &token, 1);
-		if (maj != GSS_S_COMPLETE) {
-			bsdv->bsd_flags |= BSD_FL_ERR;
-			CERROR("failed to encrypt bulk data: %x\n", maj);
-			return -EACCES;
-		}
-		break;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,446 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/ptlrpc/gss/gss_cli_upcall.c
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-/**********************************************
- * gss context init/fini helper	       *
- **********************************************/
-
-static
-int ctx_init_pack_request(struct obd_import *imp,
-			  struct ptlrpc_request *req,
-			  int lustre_srv,
-			  uid_t uid, gid_t gid,
-			  long token_size,
-			  char __user *token)
-{
-	struct lustre_msg       *msg = req->rq_reqbuf;
-	struct gss_sec	  *gsec;
-	struct gss_header       *ghdr;
-	struct ptlrpc_user_desc *pud;
-	__u32		   *p, size, offset = 2;
-	rawobj_t		 obj;
-
-	LASSERT(msg->lm_bufcount <= 4);
-	LASSERT(req->rq_cli_ctx);
-	LASSERT(req->rq_cli_ctx->cc_sec);
-
-	/* gss hdr */
-	ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
-	ghdr->gh_version = PTLRPC_GSS_VERSION;
-	ghdr->gh_sp = (__u8) imp->imp_sec->ps_part;
-	ghdr->gh_flags = 0;
-	ghdr->gh_proc = PTLRPC_GSS_PROC_INIT;
-	ghdr->gh_seq = 0;
-	ghdr->gh_svc = SPTLRPC_SVC_NULL;
-	ghdr->gh_handle.len = 0;
-
-	/* fix the user desc */
-	if (req->rq_pack_udesc) {
-		ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
-
-		pud = lustre_msg_buf(msg, offset, sizeof(*pud));
-		LASSERT(pud);
-		pud->pud_uid = pud->pud_fsuid = uid;
-		pud->pud_gid = pud->pud_fsgid = gid;
-		pud->pud_cap = 0;
-		pud->pud_ngroups = 0;
-		offset++;
-	}
-
-	/* security payload */
-	p = lustre_msg_buf(msg, offset, 0);
-	size = msg->lm_buflens[offset];
-	LASSERT(p);
-
-	/* 1. lustre svc type */
-	LASSERT(size > 4);
-	*p++ = cpu_to_le32(lustre_srv);
-	size -= 4;
-
-	/* 2. target uuid */
-	obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1;
-	obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid;
-	if (rawobj_serialize(&obj, &p, &size))
-		LBUG();
-
-	/* 3. reverse context handle. actually only needed by root user,
-	 *    but we send it anyway. */
-	gsec = sec2gsec(req->rq_cli_ctx->cc_sec);
-	obj.len = sizeof(gsec->gs_rvs_hdl);
-	obj.data = (__u8 *) &gsec->gs_rvs_hdl;
-	if (rawobj_serialize(&obj, &p, &size))
-		LBUG();
-
-	/* 4. now the token */
-	LASSERT(size >= (sizeof(__u32) + token_size));
-	*p++ = cpu_to_le32(((__u32) token_size));
-	if (copy_from_user(p, token, token_size)) {
-		CERROR("can't copy token\n");
-		return -EFAULT;
-	}
-	size -= sizeof(__u32) + cfs_size_round4(token_size);
-
-	req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset,
-						msg->lm_buflens[offset] - size, 0);
-	return 0;
-}
-
-static
-int ctx_init_parse_reply(struct lustre_msg *msg, int swabbed,
-			 char __user *outbuf, long outlen)
-{
-	struct gss_rep_header   *ghdr;
-	__u32		    obj_len, round_len;
-	__u32		    status, effective = 0;
-
-	if (msg->lm_bufcount != 3) {
-		CERROR("unexpected bufcount %u\n", msg->lm_bufcount);
-		return -EPROTO;
-	}
-
-	ghdr = (struct gss_rep_header *) gss_swab_header(msg, 0, swabbed);
-	if (ghdr == NULL) {
-		CERROR("unable to extract gss reply header\n");
-		return -EPROTO;
-	}
-
-	if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
-		CERROR("invalid gss version %u\n", ghdr->gh_version);
-		return -EPROTO;
-	}
-
-	if (outlen < (4 + 2) * 4 + cfs_size_round4(ghdr->gh_handle.len) +
-		     cfs_size_round4(msg->lm_buflens[2])) {
-		CERROR("output buffer size %ld too small\n", outlen);
-		return -EFAULT;
-	}
-
-	status = 0;
-	effective = 0;
-
-	if (copy_to_user(outbuf, &status, 4))
-		return -EFAULT;
-	outbuf += 4;
-	if (copy_to_user(outbuf, &ghdr->gh_major, 4))
-		return -EFAULT;
-	outbuf += 4;
-	if (copy_to_user(outbuf, &ghdr->gh_minor, 4))
-		return -EFAULT;
-	outbuf += 4;
-	if (copy_to_user(outbuf, &ghdr->gh_seqwin, 4))
-		return -EFAULT;
-	outbuf += 4;
-	effective += 4 * 4;
-
-	/* handle */
-	obj_len = ghdr->gh_handle.len;
-	round_len = (obj_len + 3) & ~ 3;
-	if (copy_to_user(outbuf, &obj_len, 4))
-		return -EFAULT;
-	outbuf += 4;
-	if (copy_to_user(outbuf, (char *) ghdr->gh_handle.data, round_len))
-		return -EFAULT;
-	outbuf += round_len;
-	effective += 4 + round_len;
-
-	/* out token */
-	obj_len = msg->lm_buflens[2];
-	round_len = (obj_len + 3) & ~ 3;
-	if (copy_to_user(outbuf, &obj_len, 4))
-		return -EFAULT;
-	outbuf += 4;
-	if (copy_to_user(outbuf, lustre_msg_buf(msg, 2, 0), round_len))
-		return -EFAULT;
-	outbuf += round_len;
-	effective += 4 + round_len;
-
-	return effective;
-}
-
-/* XXX move to where lgssd could see */
-struct lgssd_ioctl_param {
-	int	     version;	/* in   */
-	int	     secid;	  /* in   */
-	char	   *uuid;	   /* in   */
-	int	     lustre_svc;     /* in   */
-	uid_t	   uid;	    /* in   */
-	gid_t	   gid;	    /* in   */
-	long	    send_token_size;/* in   */
-	char	   *send_token;     /* in   */
-	long	    reply_buf_size; /* in   */
-	char	   *reply_buf;      /* in   */
-	long	    status;	 /* out  */
-	long	    reply_length;   /* out  */
-};
-
-int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
-{
-	struct obd_import	*imp;
-	struct ptlrpc_request    *req;
-	struct lgssd_ioctl_param  param;
-	struct obd_device	*obd;
-	char		      obdname[64];
-	long		      lsize;
-	int		       rc;
-
-	if (count != sizeof(param)) {
-		CERROR("ioctl size %lu, expect %lu, please check lgss_keyring "
-		       "version\n", count, (unsigned long) sizeof(param));
-		return -EINVAL;
-	}
-	if (copy_from_user(&param, buffer, sizeof(param))) {
-		CERROR("failed copy data from lgssd\n");
-		return -EFAULT;
-	}
-
-	if (param.version != GSSD_INTERFACE_VERSION) {
-		CERROR("gssd interface version %d (expect %d)\n",
-			param.version, GSSD_INTERFACE_VERSION);
-		return -EINVAL;
-	}
-
-	/* take name */
-	if (strncpy_from_user(obdname, param.uuid, sizeof(obdname)) <= 0) {
-		CERROR("Invalid obdname pointer\n");
-		return -EFAULT;
-	}
-
-	obd = class_name2obd(obdname);
-	if (!obd) {
-		CERROR("no such obd %s\n", obdname);
-		return -EINVAL;
-	}
-
-	if (unlikely(!obd->obd_set_up)) {
-		CERROR("obd %s not setup\n", obdname);
-		return -EINVAL;
-	}
-
-	spin_lock(&obd->obd_dev_lock);
-	if (obd->obd_stopping) {
-		CERROR("obd %s has stopped\n", obdname);
-		spin_unlock(&obd->obd_dev_lock);
-		return -EINVAL;
-	}
-
-	if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
-	    strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
-	    strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
-		CERROR("obd %s is not a client device\n", obdname);
-		spin_unlock(&obd->obd_dev_lock);
-		return -EINVAL;
-	}
-	spin_unlock(&obd->obd_dev_lock);
-
-	down_read(&obd->u.cli.cl_sem);
-	if (obd->u.cli.cl_import == NULL) {
-		CERROR("obd %s: import has gone\n", obd->obd_name);
-		up_read(&obd->u.cli.cl_sem);
-		return -EINVAL;
-	}
-	imp = class_import_get(obd->u.cli.cl_import);
-	up_read(&obd->u.cli.cl_sem);
-
-	if (imp->imp_deactive) {
-		CERROR("import has been deactivated\n");
-		class_import_put(imp);
-		return -EINVAL;
-	}
-
-	req = ptlrpc_request_alloc_pack(imp, &RQF_SEC_CTX, LUSTRE_OBD_VERSION,
-					SEC_CTX_INIT);
-	if (req == NULL) {
-		param.status = -ENOMEM;
-		goto out_copy;
-	}
-
-	if (req->rq_cli_ctx->cc_sec->ps_id != param.secid) {
-		CWARN("original secid %d, now has changed to %d, "
-		      "cancel this negotiation\n", param.secid,
-		      req->rq_cli_ctx->cc_sec->ps_id);
-		param.status = -EINVAL;
-		goto out_copy;
-	}
-
-	/* get token */
-	rc = ctx_init_pack_request(imp, req,
-				   param.lustre_svc,
-				   param.uid, param.gid,
-				   param.send_token_size,
-				   param.send_token);
-	if (rc) {
-		param.status = rc;
-		goto out_copy;
-	}
-
-	ptlrpc_request_set_replen(req);
-
-	rc = ptlrpc_queue_wait(req);
-	if (rc) {
-		/* If any _real_ denial be made, we expect server return
-		 * -EACCES reply or return success but indicate gss error
-		 * inside reply message. All other errors are treated as
-		 * timeout, caller might try the negotiation repeatedly,
-		 * leave recovery decisions to general ptlrpc layer.
-		 *
-		 * FIXME maybe some other error code shouldn't be treated
-		 * as timeout. */
-		param.status = rc;
-		if (rc != -EACCES)
-			param.status = -ETIMEDOUT;
-		goto out_copy;
-	}
-
-	LASSERT(req->rq_repdata);
-	lsize = ctx_init_parse_reply(req->rq_repdata,
-				     ptlrpc_rep_need_swab(req),
-				     param.reply_buf, param.reply_buf_size);
-	if (lsize < 0) {
-		param.status = (int) lsize;
-		goto out_copy;
-	}
-
-	param.status = 0;
-	param.reply_length = lsize;
-
-out_copy:
-	if (copy_to_user(buffer, &param, sizeof(param)))
-		rc = -EFAULT;
-	else
-		rc = 0;
-
-	class_import_put(imp);
-	ptlrpc_req_finished(req);
-	return rc;
-}
-
-int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
-{
-	struct ptlrpc_cli_ctx   *ctx = &gctx->gc_base;
-	struct obd_import       *imp = ctx->cc_sec->ps_import;
-	struct ptlrpc_request   *req;
-	struct ptlrpc_user_desc *pud;
-	int		      rc;
-
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-	if (cli_ctx_is_error(ctx) || !cli_ctx_is_uptodate(ctx)) {
-		CDEBUG(D_SEC, "ctx %p(%u->%s) not uptodate, "
-		       "don't send destroy rpc\n", ctx,
-		       ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
-		return 0;
-	}
-
-	might_sleep();
-
-	CWARN("%s ctx %p idx "LPX64" (%u->%s)\n",
-	      sec_is_reverse(ctx->cc_sec) ?
-	      "server finishing reverse" : "client finishing forward",
-	      ctx, gss_handle_to_u64(&gctx->gc_handle),
-	      ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
-
-	gctx->gc_proc = PTLRPC_GSS_PROC_DESTROY;
-
-	req = ptlrpc_request_alloc(imp, &RQF_SEC_CTX);
-	if (req == NULL) {
-		CWARN("ctx %p(%u): fail to prepare rpc, destroy locally\n",
-		      ctx, ctx->cc_vcred.vc_uid);
-		GOTO(out, rc = -ENOMEM);
-	}
-
-	rc = ptlrpc_request_bufs_pack(req, LUSTRE_OBD_VERSION, SEC_CTX_FINI,
-				      NULL, ctx);
-	if (rc) {
-		ptlrpc_request_free(req);
-		GOTO(out_ref, rc);
-	}
-
-	/* fix the user desc */
-	if (req->rq_pack_udesc) {
-		/* we rely the fact that this request is in AUTH mode,
-		 * and user_desc at offset 2. */
-		pud = lustre_msg_buf(req->rq_reqbuf, 2, sizeof(*pud));
-		LASSERT(pud);
-		pud->pud_uid = pud->pud_fsuid = ctx->cc_vcred.vc_uid;
-		pud->pud_gid = pud->pud_fsgid = ctx->cc_vcred.vc_gid;
-		pud->pud_cap = 0;
-		pud->pud_ngroups = 0;
-	}
-
-	req->rq_phase = RQ_PHASE_RPC;
-	rc = ptl_send_rpc(req, 1);
-	if (rc)
-		CWARN("ctx %p(%u->%s): rpc error %d, destroy locally\n", ctx,
-		      ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), rc);
-
-out_ref:
-	ptlrpc_req_finished(req);
-out:
-	return rc;
-}
-
-int __init gss_init_cli_upcall(void)
-{
-	return 0;
-}
-
-void __exit gss_exit_cli_upcall(void)
-{
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,193 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  Adapted from MIT Kerberos 5-1.2.1 include/gssapi/gssapi.h
- *
- *  Copyright (c) 2002 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- */
-
-/*
- * Copyright 1993 by OpenVision Technologies, Inc.
- *
- * 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 appears in all copies and
- * that both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OpenVision not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. OpenVision makes no
- * representations about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty.
- *
- * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __PTLRPC_GSS_GSS_ERR_H_
-#define __PTLRPC_GSS_GSS_ERR_H_
-
-typedef unsigned int OM_uint32;
-
-/*
- * Flag bits for context-level services.
- */
-#define GSS_C_DELEG_FLAG	(1)
-#define GSS_C_MUTUAL_FLAG       (2)
-#define GSS_C_REPLAY_FLAG       (4)
-#define GSS_C_SEQUENCE_FLAG     (8)
-#define GSS_C_CONF_FLAG	 (16)
-#define GSS_C_INTEG_FLAG	(32)
-#define GSS_C_ANON_FLAG	 (64)
-#define GSS_C_PROT_READY_FLAG   (128)
-#define GSS_C_TRANS_FLAG	(256)
-
-/*
- * Credential usage options
- */
-#define GSS_C_BOTH	      (0)
-#define GSS_C_INITIATE	  (1)
-#define GSS_C_ACCEPT	    (2)
-
-/*
- * Status code types for gss_display_status
- */
-#define GSS_C_GSS_CODE	  (1)
-#define GSS_C_MECH_CODE	 (2)
-
-
-/*
- * Define the default Quality of Protection for per-message services.  Note
- * that an implementation that offers multiple levels of QOP may either reserve
- * a value (for example zero, as assumed here) to mean "default protection", or
- * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
- * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
- * implementation as a request for the default protection level.
- */
-#define GSS_C_QOP_DEFAULT       (0)
-
-/*
- * Expiration time of 2^32-1 seconds means infinite lifetime for a
- * credential or security context
- */
-#define GSS_C_INDEFINITE	((OM_uint32) 0xfffffffful)
-
-
-/* Major status codes */
-
-#define GSS_S_COMPLETE	  (0)
-
-/*
- * Some "helper" definitions to make the status code macros obvious.
- */
-#define GSS_C_CALLING_ERROR_OFFSET      (24)
-#define GSS_C_ROUTINE_ERROR_OFFSET      (16)
-#define GSS_C_SUPPLEMENTARY_OFFSET      (0)
-#define GSS_C_CALLING_ERROR_MASK	((OM_uint32) 0377ul)
-#define GSS_C_ROUTINE_ERROR_MASK	((OM_uint32) 0377ul)
-#define GSS_C_SUPPLEMENTARY_MASK	((OM_uint32) 0177777ul)
-
-/*
- * The macros that test status codes for error conditions.  Note that the
- * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
- * evaluates its argument only once.
- */
-#define GSS_CALLING_ERROR(x) \
-	((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
-#define GSS_ROUTINE_ERROR(x) \
-	((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
-#define GSS_SUPPLEMENTARY_INFO(x) \
-	((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
-#define GSS_ERROR(x) \
-	((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
-		(GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
-
-/*
- * Now the actual status code definitions
- */
-
-/*
- * Calling errors:
- */
-#define GSS_S_CALL_INACCESSIBLE_READ \
-	(((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
-#define GSS_S_CALL_INACCESSIBLE_WRITE \
-	(((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
-#define GSS_S_CALL_BAD_STRUCTURE \
-	(((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
-
-/*
- * Routine errors:
- */
-#define GSS_S_BAD_MECH \
-	(((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_NAME \
-	(((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_NAMETYPE \
-	(((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_BINDINGS \
-	(((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_STATUS \
-	(((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_SIG \
-	(((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_NO_CRED \
-	(((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_NO_CONTEXT \
-	(((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_DEFECTIVE_TOKEN \
-	(((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_DEFECTIVE_CREDENTIAL \
-	(((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_CREDENTIALS_EXPIRED \
-	(((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_CONTEXT_EXPIRED \
-	(((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_FAILURE \
-	(((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_QOP \
-	(((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_UNAUTHORIZED \
-	(((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_UNAVAILABLE \
-	(((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_DUPLICATE_ELEMENT \
-	(((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_NAME_NOT_MN \
-	(((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-
-/*
- * Supplementary info bits:
- */
-#define GSS_S_CONTINUE_NEEDED   (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
-#define GSS_S_DUPLICATE_TOKEN   (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
-#define GSS_S_OLD_TOKEN	 (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
-#define GSS_S_UNSEQ_TOKEN       (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
-#define GSS_S_GAP_TOKEN	 (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
-
-/* XXXX these are not part of the GSSAPI C bindings!  (but should be) */
-
-#define GSS_CALLING_ERROR_FIELD(x) \
-	(((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
-#define GSS_ROUTINE_ERROR_FIELD(x) \
-	(((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
-#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
-	(((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
-
-/* XXXX This is a necessary evil until the spec is fixed */
-#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
-
-#endif /* __PTLRPC_GSS_GSS_ERR_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,296 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  linux/net/sunrpc/gss_generic_token.c
- *
- *  Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic/util_token.c
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- */
-
-/*
- * Copyright 1993 by OpenVision Technologies, Inc.
- *
- * 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 appears in all copies and
- * that both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OpenVision not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. OpenVision makes no
- * representations about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty.
- *
- * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OPENVISION 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.
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-#include "gss_krb5.h"
-#include "gss_asn1.h"
-
-
-/* TWRITE_STR from gssapiP_generic.h */
-#define TWRITE_STR(ptr, str, len) \
-	memcpy((ptr), (char *) (str), (len)); \
-	(ptr) += (len);
-
-/* XXXX this code currently makes the assumption that a mech oid will
-   never be longer than 127 bytes.  This assumption is not inherent in
-   the interfaces, so the code can be fixed if the OSI namespace
-   balloons unexpectedly. */
-
-/* Each token looks like this:
-
-0x60				tag for APPLICATION 0, SEQUENCE
-					(constructed, definite-length)
-	<length>		possible multiple bytes, need to parse/generate
-	0x06			tag for OBJECT IDENTIFIER
-		<moid_length>	compile-time constant string (assume 1 byte)
-		<moid_bytes>	compile-time constant string
-	<inner_bytes>		the ANY containing the application token
-					bytes 0,1 are the token type
-					bytes 2,n are the token data
-
-For the purposes of this abstraction, the token "header" consists of
-the sequence tag and length octets, the mech OID DER encoding, and the
-first two inner bytes, which indicate the token type.  The token
-"body" consists of everything else.
-
-*/
-
-static
-int der_length_size(int length)
-{
-	if (length < (1 << 7))
-		return 1;
-	else if (length < (1 << 8))
-		return 2;
-#if (SIZEOF_INT == 2)
-	else
-		return 3;
-#else
-	else if (length < (1 << 16))
-		return 3;
-	else if (length < (1 << 24))
-		return 4;
-	else
-		return 5;
-#endif
-}
-
-static
-void der_write_length(unsigned char **buf, int length)
-{
-	if (length < (1 << 7)) {
-		*(*buf)++ = (unsigned char) length;
-	} else {
-		*(*buf)++ = (unsigned char) (der_length_size(length) + 127);
-#if (SIZEOF_INT > 2)
-		if (length >= (1 << 24))
-			*(*buf)++ = (unsigned char) (length >> 24);
-		if (length >= (1 << 16))
-			*(*buf)++ = (unsigned char) ((length >> 16) & 0xff);
-#endif
-		if (length >= (1 << 8))
-			*(*buf)++ = (unsigned char) ((length >> 8) & 0xff);
-		*(*buf)++ = (unsigned char) (length & 0xff);
-	}
-}
-
-/*
- * returns decoded length, or < 0 on failure.  Advances buf and
- * decrements bufsize
- */
-static
-int der_read_length(unsigned char **buf, int *bufsize)
-{
-	unsigned char sf;
-	int ret;
-
-	if (*bufsize < 1)
-		return -1;
-	sf = *(*buf)++;
-	(*bufsize)--;
-	if (sf & 0x80) {
-		sf &= 0x7f;
-		if (((*bufsize) - 1) < sf)
-			return -1;
-		if (sf > SIZEOF_INT)
-			return -1;
-		ret = 0;
-		for (; sf; sf--) {
-			ret = (ret << 8) + (*(*buf)++);
-			(*bufsize)--;
-		}
-	} else {
-		ret = sf;
-	}
-
-	return ret;
-}
-
-/*
- * returns the length of a token, given the mech oid and the body size
- */
-int g_token_size(rawobj_t *mech, unsigned int body_size)
-{
-	/* set body_size to sequence contents size */
-	body_size += 4 + (int) mech->len; /* NEED overflow check */
-	return (1 + der_length_size(body_size) + body_size);
-}
-
-/*
- * fills in a buffer with the token header.  The buffer is assumed to
- * be the right size.  buf is advanced past the token header
- */
-void g_make_token_header(rawobj_t *mech, int body_size, unsigned char **buf)
-{
-	*(*buf)++ = 0x60;
-	der_write_length(buf, 4 + mech->len + body_size);
-	*(*buf)++ = 0x06;
-	*(*buf)++ = (unsigned char) mech->len;
-	TWRITE_STR(*buf, mech->data, ((int) mech->len));
-}
-
-/*
- * Given a buffer containing a token, reads and verifies the token,
- * leaving buf advanced past the token header, and setting body_size
- * to the number of remaining bytes.  Returns 0 on success,
- * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
- * mechanism in the token does not match the mech argument.  buf and
- * *body_size are left unmodified on error.
- */
-__u32 g_verify_token_header(rawobj_t *mech, int *body_size,
-			    unsigned char **buf_in, int toksize)
-{
-	unsigned char *buf = *buf_in;
-	int seqsize;
-	rawobj_t toid;
-	int ret = 0;
-
-	toksize -= 1;
-	if (0 > toksize)
-		return (G_BAD_TOK_HEADER);
-	if (*buf++ != 0x60)
-		return (G_BAD_TOK_HEADER);
-
-	seqsize = der_read_length(&buf, &toksize);
-	if (seqsize < 0)
-		return(G_BAD_TOK_HEADER);
-
-	if (seqsize != toksize)
-		return (G_BAD_TOK_HEADER);
-
-	toksize -= 1;
-	if (0 > toksize)
-		return (G_BAD_TOK_HEADER);
-	if (*buf++ != 0x06)
-		return (G_BAD_TOK_HEADER);
-
-	toksize -= 1;
-	if (0 > toksize)
-		return (G_BAD_TOK_HEADER);
-	toid.len = *buf++;
-
-	toksize -= toid.len;
-	if (0 > toksize)
-		return (G_BAD_TOK_HEADER);
-	toid.data = buf;
-	buf += toid.len;
-
-	if (!g_OID_equal(&toid, mech))
-		ret = G_WRONG_MECH;
-
-	/* G_WRONG_MECH is not returned immediately because it's more
-	 * important to return G_BAD_TOK_HEADER if the token header is
-	 * in fact bad
-	 */
-	toksize -= 2;
-	if (0 > toksize)
-		return (G_BAD_TOK_HEADER);
-
-	if (ret)
-		return (ret);
-
-	if (!ret) {
-		*buf_in = buf;
-		*body_size = toksize;
-	}
-
-	return (ret);
-}
-
-/*
- * Given a buffer containing a token, returns a copy of the mech oid in
- * the parameter mech.
- */
-__u32 g_get_mech_oid(rawobj_t *mech, rawobj_t *in_buf)
-{
-	unsigned char *buf = in_buf->data;
-	int len = in_buf->len;
-	int ret = 0;
-	int seqsize;
-
-	len -= 1;
-	if (0 > len)
-		return (G_BAD_TOK_HEADER);
-	if (*buf++ != 0x60)
-		return (G_BAD_TOK_HEADER);
-
-	seqsize = der_read_length(&buf, &len);
-	if (seqsize < 0)
-		return (G_BAD_TOK_HEADER);
-
-	len -= 1;
-	if (0 > len)
-		return (G_BAD_TOK_HEADER);
-	if (*buf++ != 0x06)
-		return (G_BAD_TOK_HEADER);
-
-	len -= 1;
-	if (0 > len)
-		return (G_BAD_TOK_HEADER);
-	mech->len = *buf++;
-
-	len -= mech->len;
-	if (0 > len)
-		return (G_BAD_TOK_HEADER);
-	OBD_ALLOC_LARGE(mech->data, mech->len);
-	if (!mech->data)
-		return (G_BUFFER_ALLOC);
-	memcpy(mech->data, buf, mech->len);
-
-	return ret;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,526 +0,0 @@
-/*
- * Modified from NFSv4 project for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-#ifndef __PTLRPC_GSS_GSS_INTERNAL_H_
-#define __PTLRPC_GSS_GSS_INTERNAL_H_
-
-#include <lustre_sec.h>
-
-/*
- * rawobj stuff
- */
-typedef struct netobj_s {
-	__u32	   len;
-	__u8	    data[0];
-} netobj_t;
-
-#define NETOBJ_EMPTY    ((netobj_t) { 0 })
-
-typedef struct rawobj_s {
-	__u32	   len;
-	__u8	   *data;
-} rawobj_t;
-
-#define RAWOBJ_EMPTY    ((rawobj_t) { 0, NULL })
-
-typedef struct rawobj_buf_s {
-	__u32	   dataoff;
-	__u32	   datalen;
-	__u32	   buflen;
-	__u8	   *buf;
-} rawobj_buf_t;
-
-int rawobj_empty(rawobj_t *obj);
-int rawobj_alloc(rawobj_t *obj, char *buf, int len);
-void rawobj_free(rawobj_t *obj);
-int rawobj_equal(rawobj_t *a, rawobj_t *b);
-int rawobj_dup(rawobj_t *dest, rawobj_t *src);
-int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract_local_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_from_netobj(rawobj_t *rawobj, netobj_t *netobj);
-int rawobj_from_netobj_alloc(rawobj_t *obj, netobj_t *netobj);
-
-int buffer_extract_bytes(const void **buf, __u32 *buflen,
-			 void *res, __u32 reslen);
-
-/*
- * several timeout values. client refresh upcall timeout we using
- * default in pipefs implemnetation.
- */
-#define __TIMEOUT_DELTA		 (10)
-
-#define GSS_SECINIT_RPC_TIMEOUT					 \
-	(obd_timeout < __TIMEOUT_DELTA ?				\
-	 __TIMEOUT_DELTA : obd_timeout - __TIMEOUT_DELTA)
-
-#define GSS_SECFINI_RPC_TIMEOUT	 (__TIMEOUT_DELTA)
-#define GSS_SECSVC_UPCALL_TIMEOUT       (GSS_SECINIT_RPC_TIMEOUT)
-
-/*
- * default gc interval
- */
-#define GSS_GC_INTERVAL		 (60 * 60) /* 60 minutes */
-
-static inline
-unsigned long gss_round_ctx_expiry(unsigned long expiry,
-				   unsigned long sec_flags)
-{
-	if (sec_flags & PTLRPC_SEC_FL_REVERSE)
-		return expiry;
-
-	if (get_seconds() + __TIMEOUT_DELTA <= expiry)
-		return expiry - __TIMEOUT_DELTA;
-
-	return expiry;
-}
-
-/*
- * Max encryption element in block cipher algorithms.
- */
-#define GSS_MAX_CIPHER_BLOCK	       (16)
-
-/*
- * XXX make it visible of kernel and lgssd/lsvcgssd
- */
-#define GSSD_INTERFACE_VERSION	  (1)
-
-#define PTLRPC_GSS_VERSION	      (1)
-
-
-enum ptlrpc_gss_proc {
-	PTLRPC_GSS_PROC_DATA	    = 0,
-	PTLRPC_GSS_PROC_INIT	    = 1,
-	PTLRPC_GSS_PROC_CONTINUE_INIT   = 2,
-	PTLRPC_GSS_PROC_DESTROY	 = 3,
-	PTLRPC_GSS_PROC_ERR	     = 4,
-};
-
-enum ptlrpc_gss_tgt {
-	LUSTRE_GSS_TGT_MGS	      = 0,
-	LUSTRE_GSS_TGT_MDS	      = 1,
-	LUSTRE_GSS_TGT_OSS	      = 2,
-};
-
-enum ptlrpc_gss_header_flags {
-	LUSTRE_GSS_PACK_BULK	    = 1,
-	LUSTRE_GSS_PACK_USER	    = 2,
-};
-
-static inline
-__u32 import_to_gss_svc(struct obd_import *imp)
-{
-	const char *name = imp->imp_obd->obd_type->typ_name;
-
-	if (!strcmp(name, LUSTRE_MGC_NAME))
-		return LUSTRE_GSS_TGT_MGS;
-	if (!strcmp(name, LUSTRE_MDC_NAME))
-		return LUSTRE_GSS_TGT_MDS;
-	if (!strcmp(name, LUSTRE_OSC_NAME))
-		return LUSTRE_GSS_TGT_OSS;
-	LBUG();
-	return 0;
-}
-
-/*
- * following 3 header must have the same size and offset
- */
-struct gss_header {
-	__u8		    gh_version;     /* gss version */
-	__u8		    gh_sp;	  /* sec part */
-	__u16		   gh_pad0;
-	__u32		   gh_flags;       /* wrap flags */
-	__u32		   gh_proc;	/* proc */
-	__u32		   gh_seq;	 /* sequence */
-	__u32		   gh_svc;	 /* service */
-	__u32		   gh_pad1;
-	__u32		   gh_pad2;
-	__u32		   gh_pad3;
-	netobj_t		gh_handle;      /* context handle */
-};
-
-struct gss_rep_header {
-	__u8		    gh_version;
-	__u8		    gh_sp;
-	__u16		   gh_pad0;
-	__u32		   gh_flags;
-	__u32		   gh_proc;
-	__u32		   gh_major;
-	__u32		   gh_minor;
-	__u32		   gh_seqwin;
-	__u32		   gh_pad2;
-	__u32		   gh_pad3;
-	netobj_t		gh_handle;
-};
-
-struct gss_err_header {
-	__u8		    gh_version;
-	__u8		    gh_sp;
-	__u16		   gh_pad0;
-	__u32		   gh_flags;
-	__u32		   gh_proc;
-	__u32		   gh_major;
-	__u32		   gh_minor;
-	__u32		   gh_pad1;
-	__u32		   gh_pad2;
-	__u32		   gh_pad3;
-	netobj_t		gh_handle;
-};
-
-/*
- * part of wire context information send from client which be saved and
- * used later by server.
- */
-struct gss_wire_ctx {
-	__u32		   gw_flags;
-	__u32		   gw_proc;
-	__u32		   gw_seq;
-	__u32		   gw_svc;
-	rawobj_t		gw_handle;
-};
-
-#define PTLRPC_GSS_MAX_HANDLE_SIZE      (8)
-#define PTLRPC_GSS_HEADER_SIZE	  (sizeof(struct gss_header) + \
-					 PTLRPC_GSS_MAX_HANDLE_SIZE)
-
-
-static inline __u64 gss_handle_to_u64(rawobj_t *handle)
-{
-	if (handle->len != PTLRPC_GSS_MAX_HANDLE_SIZE)
-		return -1;
-	return *((__u64 *) handle->data);
-}
-
-#define GSS_SEQ_WIN		     (2048)
-#define GSS_SEQ_WIN_MAIN		GSS_SEQ_WIN
-#define GSS_SEQ_WIN_BACK		(128)
-#define GSS_SEQ_REPACK_THRESHOLD	(GSS_SEQ_WIN_MAIN / 2 + \
-					 GSS_SEQ_WIN_MAIN / 4)
-
-struct gss_svc_seq_data {
-	spinlock_t		ssd_lock;
-	/*
-	 * highest sequence number seen so far, for main and back window
-	 */
-	__u32		   ssd_max_main;
-	__u32		   ssd_max_back;
-	/*
-	 * main and back window
-	 * for i such that ssd_max - GSS_SEQ_WIN < i <= ssd_max, the i-th bit
-	 * of ssd_win is nonzero iff sequence number i has been seen already.
-	 */
-	unsigned long	   ssd_win_main[GSS_SEQ_WIN_MAIN/BITS_PER_LONG];
-	unsigned long	   ssd_win_back[GSS_SEQ_WIN_BACK/BITS_PER_LONG];
-};
-
-struct gss_svc_ctx {
-	struct gss_ctx	 *gsc_mechctx;
-	struct gss_svc_seq_data gsc_seqdata;
-	rawobj_t		gsc_rvs_hdl;
-	__u32		   gsc_rvs_seq;
-	uid_t		   gsc_uid;
-	gid_t		   gsc_gid;
-	uid_t		   gsc_mapped_uid;
-	unsigned int	    gsc_usr_root:1,
-				gsc_usr_mds:1,
-				gsc_usr_oss:1,
-				gsc_remote:1,
-				gsc_reverse:1;
-};
-
-struct gss_svc_reqctx {
-	struct ptlrpc_svc_ctx	   src_base;
-	/*
-	 * context
-	 */
-	struct gss_wire_ctx	     src_wirectx;
-	struct gss_svc_ctx	     *src_ctx;
-	/*
-	 * record place of bulk_sec_desc in request/reply buffer
-	 */
-	struct ptlrpc_bulk_sec_desc    *src_reqbsd;
-	int			     src_reqbsd_size;
-	struct ptlrpc_bulk_sec_desc    *src_repbsd;
-	int			     src_repbsd_size;
-	/*
-	 * flags
-	 */
-	unsigned int		    src_init:1,
-					src_init_continue:1,
-					src_err_notify:1;
-	int			     src_reserve_len;
-};
-
-struct gss_cli_ctx {
-	struct ptlrpc_cli_ctx   gc_base;
-	__u32		   gc_flavor;
-	__u32		   gc_proc;
-	__u32		   gc_win;
-	atomic_t	    gc_seq;
-	rawobj_t		gc_handle;
-	struct gss_ctx	 *gc_mechctx;
-	/* handle for the buddy svc ctx */
-	rawobj_t		gc_svc_handle;
-};
-
-struct gss_cli_ctx_keyring {
-	struct gss_cli_ctx      gck_base;
-	struct key	     *gck_key;
-	struct timer_list      *gck_timer;
-};
-
-struct gss_sec {
-	struct ptlrpc_sec	gs_base;
-	struct gss_api_mech	*gs_mech;
-	spinlock_t		gs_lock;
-	__u64			gs_rvs_hdl;
-};
-
-struct gss_sec_pipefs {
-	struct gss_sec	  gsp_base;
-	int		     gsp_chash_size;  /* must be 2^n */
-	struct hlist_head	gsp_chash[0];
-};
-
-/*
- * FIXME cleanup the keyring upcall mutexes
- */
-#define HAVE_KEYRING_UPCALL_SERIALIZED  1
-
-struct gss_sec_keyring {
-	struct gss_sec	  gsk_base;
-	/*
-	 * all contexts listed here. access is protected by sec spinlock.
-	 */
-	struct hlist_head	gsk_clist;
-	/*
-	 * specially point to root ctx (only one at a time). access is
-	 * protected by sec spinlock.
-	 */
-	struct ptlrpc_cli_ctx  *gsk_root_ctx;
-	/*
-	 * specially serialize upcalls for root context.
-	 */
-	struct mutex			gsk_root_uc_lock;
-
-#ifdef HAVE_KEYRING_UPCALL_SERIALIZED
-	struct mutex		gsk_uc_lock;	/* serialize upcalls */
-#endif
-};
-
-static inline struct gss_cli_ctx *ctx2gctx(struct ptlrpc_cli_ctx *ctx)
-{
-	return container_of(ctx, struct gss_cli_ctx, gc_base);
-}
-
-static inline
-struct gss_cli_ctx_keyring *ctx2gctx_keyring(struct ptlrpc_cli_ctx *ctx)
-{
-	return container_of(ctx2gctx(ctx),
-			    struct gss_cli_ctx_keyring, gck_base);
-}
-
-static inline struct gss_sec *sec2gsec(struct ptlrpc_sec *sec)
-{
-	return container_of(sec, struct gss_sec, gs_base);
-}
-
-static inline struct gss_sec_pipefs *sec2gsec_pipefs(struct ptlrpc_sec *sec)
-{
-	return container_of(sec2gsec(sec), struct gss_sec_pipefs, gsp_base);
-}
-
-static inline struct gss_sec_keyring *sec2gsec_keyring(struct ptlrpc_sec *sec)
-{
-	return container_of(sec2gsec(sec), struct gss_sec_keyring, gsk_base);
-}
-
-
-#define GSS_CTX_INIT_MAX_LEN	    (1024)
-
-/*
- * This only guaranteed be enough for current krb5 des-cbc-crc . We might
- * adjust this when new enc type or mech added in.
- */
-#define GSS_PRIVBUF_PREFIX_LEN	 (32)
-#define GSS_PRIVBUF_SUFFIX_LEN	 (32)
-
-static inline
-struct gss_svc_reqctx *gss_svc_ctx2reqctx(struct ptlrpc_svc_ctx *ctx)
-{
-	LASSERT(ctx);
-	return container_of(ctx, struct gss_svc_reqctx, src_base);
-}
-
-static inline
-struct gss_svc_ctx *gss_svc_ctx2gssctx(struct ptlrpc_svc_ctx *ctx)
-{
-	LASSERT(ctx);
-	return gss_svc_ctx2reqctx(ctx)->src_ctx;
-}
-
-/* sec_gss.c */
-int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred);
-int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize);
-int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req);
-int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req);
-int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req);
-int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req);
-
-int  gss_sec_install_rctx(struct obd_import *imp, struct ptlrpc_sec *sec,
-			  struct ptlrpc_cli_ctx *ctx);
-int  gss_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
-		      int msgsize);
-void gss_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req);
-int  gss_alloc_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
-		      int msgsize);
-void gss_free_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req);
-int  gss_enlarge_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
-			int segment, int newsize);
-
-int  gss_svc_accept(struct ptlrpc_sec_policy *policy,
-		    struct ptlrpc_request *req);
-void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx);
-int  gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen);
-int  gss_svc_authorize(struct ptlrpc_request *req);
-void gss_svc_free_rs(struct ptlrpc_reply_state *rs);
-void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx);
-
-int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx);
-int cli_ctx_check_death(struct ptlrpc_cli_ctx *ctx);
-
-int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx,
-			 struct ptlrpc_svc_ctx *svc_ctx);
-
-struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment,
-				   int swabbed);
-netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment);
-
-void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx);
-int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor);
-int gss_check_seq_num(struct gss_svc_seq_data *sd, __u32 seq_num, int set);
-
-int gss_sec_create_common(struct gss_sec *gsec,
-			  struct ptlrpc_sec_policy *policy,
-			  struct obd_import *imp,
-			  struct ptlrpc_svc_ctx *ctx,
-			  struct sptlrpc_flavor *sf);
-void gss_sec_destroy_common(struct gss_sec *gsec);
-void gss_sec_kill(struct ptlrpc_sec *sec);
-
-int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx,
-			    struct ptlrpc_ctx_ops *ctxops,
-			    struct vfs_cred *vcred);
-int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx);
-
-void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize);
-
-/* gss_keyring.c */
-int  __init gss_init_keyring(void);
-void __exit gss_exit_keyring(void);
-
-/* gss_pipefs.c */
-int  __init gss_init_pipefs(void);
-void __exit gss_exit_pipefs(void);
-
-/* gss_bulk.c */
-int gss_cli_prep_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc);
-int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
-			  struct ptlrpc_request *req,
-			  struct ptlrpc_bulk_desc *desc);
-int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
-			    struct ptlrpc_request *req,
-			    struct ptlrpc_bulk_desc *desc);
-int gss_svc_prep_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc);
-int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
-			struct ptlrpc_bulk_desc *desc);
-int gss_svc_wrap_bulk(struct ptlrpc_request *req,
-		      struct ptlrpc_bulk_desc *desc);
-
-/* gss_mech_switch.c */
-int init_kerberos_module(void);
-void cleanup_kerberos_module(void);
-
-/* gss_generic_token.c */
-int g_token_size(rawobj_t *mech, unsigned int body_size);
-void g_make_token_header(rawobj_t *mech, int body_size, unsigned char **buf);
-__u32 g_verify_token_header(rawobj_t *mech, int *body_size,
-			    unsigned char **buf_in, int toksize);
-
-
-/* gss_cli_upcall.c */
-int gss_do_ctx_init_rpc(char *buffer, unsigned long count);
-int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx);
-
-int  __init gss_init_cli_upcall(void);
-void __exit gss_exit_cli_upcall(void);
-
-/* gss_svc_upcall.c */
-__u64 gss_get_next_ctx_index(void);
-int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
-				   struct gss_sec *gsec,
-				   struct gss_cli_ctx *gctx);
-int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle);
-int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx);
-int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq);
-int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
-			       struct gss_svc_reqctx *grctx,
-			       struct gss_wire_ctx *gw,
-			       struct obd_device *target,
-			       __u32 lustre_svc,
-			       rawobj_t *rvs_hdl,
-			       rawobj_t *in_token);
-struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
-					   struct gss_wire_ctx *gw);
-void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx);
-void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx);
-
-int  __init gss_init_svc_upcall(void);
-void __exit gss_exit_svc_upcall(void);
-
-/* lproc_gss.c */
-void gss_stat_oos_record_cli(int behind);
-void gss_stat_oos_record_svc(int phase, int replay);
-
-int  __init gss_init_lproc(void);
-void __exit gss_exit_lproc(void);
-
-/* gss_krb5_mech.c */
-int __init init_kerberos_module(void);
-void __exit cleanup_kerberos_module(void);
-
-
-/* debug */
-static inline
-void __dbg_memdump(char *name, void *ptr, int size)
-{
-	char *buf, *p = (char *) ptr;
-	int bufsize = size * 2 + 1, i;
-
-	OBD_ALLOC(buf, bufsize);
-	if (!buf) {
-		CDEBUG(D_ERROR, "DUMP ERROR: can't alloc %d bytes\n", bufsize);
-		return;
-	}
-
-	for (i = 0; i < size; i++)
-		sprintf(&buf[i+i], "%02x", (__u8) p[i]);
-	buf[size + size] = '\0';
-	LCONSOLE_INFO("DUMP %s@%p(%d): %s\n", name, ptr, size, buf);
-	OBD_FREE(buf, bufsize);
-}
-
-#endif /* __PTLRPC_GSS_GSS_INTERNAL_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1409 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/ptlrpc/gss/gss_keyring.c
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/crypto.h>
-#include <linux/key.h>
-#include <linux/keyctl.h>
-#include <linux/key-type.h>
-#include <linux/mutex.h>
-#include <asm/atomic.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_sec.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-static struct ptlrpc_sec_policy gss_policy_keyring;
-static struct ptlrpc_ctx_ops gss_keyring_ctxops;
-static struct key_type gss_key_type;
-
-static int sec_install_rctx_kr(struct ptlrpc_sec *sec,
-			       struct ptlrpc_svc_ctx *svc_ctx);
-
-/*
- * the timeout is only for the case that upcall child process die abnormally.
- * in any other cases it should finally update kernel key.
- *
- * FIXME we'd better to incorporate the client & server side upcall timeouts
- * into the framework of Adaptive Timeouts, but we need to figure out how to
- * make sure that kernel knows the upcall processes is in-progress or died
- * unexpectedly.
- */
-#define KEYRING_UPCALL_TIMEOUT  (obd_timeout + obd_timeout)
-
-/****************************************
- * internal helpers		     *
- ****************************************/
-
-#define DUMP_PROCESS_KEYRINGS(tsk)					\
-{									\
-	CWARN("DUMP PK: %s[%u,%u/%u](<-%s[%u,%u/%u]): "			\
-	      "a %d, t %d, p %d, s %d, u %d, us %d, df %d\n",		\
-	      tsk->comm, tsk->pid, tsk->uid, tsk->fsuid,		\
-	      tsk->parent->comm, tsk->parent->pid,			\
-	      tsk->parent->uid, tsk->parent->fsuid,			\
-	      tsk->request_key_auth ?					\
-	      tsk->request_key_auth->serial : 0,			\
-	      key_cred(tsk)->thread_keyring ?				\
-	      key_cred(tsk)->thread_keyring->serial : 0,		\
-	      key_tgcred(tsk)->process_keyring ?			\
-	      key_tgcred(tsk)->process_keyring->serial : 0,		\
-	      key_tgcred(tsk)->session_keyring ?			\
-	      key_tgcred(tsk)->session_keyring->serial : 0,		\
-	      key_cred(tsk)->user->uid_keyring ?			\
-	      key_cred(tsk)->user->uid_keyring->serial : 0,		\
-	      key_cred(tsk)->user->session_keyring ?			\
-	      key_cred(tsk)->user->session_keyring->serial : 0,		\
-	      key_cred(tsk)->jit_keyring				\
-	     );								\
-}
-
-#define DUMP_KEY(key)						   \
-{								       \
-	CWARN("DUMP KEY: %p(%d) ref %d u%u/g%u desc %s\n",	      \
-	      key, key->serial, atomic_read(&key->usage),	       \
-	      key->uid, key->gid,				       \
-	      key->description ? key->description : "n/a"	       \
-	     );							 \
-}
-
-#define key_cred(tsk)   ((tsk)->cred)
-#define key_tgcred(tsk) ((tsk)->cred->tgcred)
-
-static inline void keyring_upcall_lock(struct gss_sec_keyring *gsec_kr)
-{
-#ifdef HAVE_KEYRING_UPCALL_SERIALIZED
-	mutex_lock(&gsec_kr->gsk_uc_lock);
-#endif
-}
-
-static inline void keyring_upcall_unlock(struct gss_sec_keyring *gsec_kr)
-{
-#ifdef HAVE_KEYRING_UPCALL_SERIALIZED
-	mutex_unlock(&gsec_kr->gsk_uc_lock);
-#endif
-}
-
-static inline void key_revoke_locked(struct key *key)
-{
-	set_bit(KEY_FLAG_REVOKED, &key->flags);
-}
-
-static void ctx_upcall_timeout_kr(unsigned long data)
-{
-	struct ptlrpc_cli_ctx *ctx = (struct ptlrpc_cli_ctx *) data;
-	struct key	    *key = ctx2gctx_keyring(ctx)->gck_key;
-
-	CWARN("ctx %p, key %p\n", ctx, key);
-
-	LASSERT(key);
-
-	cli_ctx_expire(ctx);
-	key_revoke_locked(key);
-}
-
-static
-void ctx_start_timer_kr(struct ptlrpc_cli_ctx *ctx, long timeout)
-{
-	struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx);
-	struct timer_list	  *timer = gctx_kr->gck_timer;
-
-	LASSERT(timer);
-
-	CDEBUG(D_SEC, "ctx %p: start timer %lds\n", ctx, timeout);
-	timeout = timeout * HZ + cfs_time_current();
-
-	init_timer(timer);
-	timer->expires = timeout;
-	timer->data = (unsigned long) ctx;
-	timer->function = ctx_upcall_timeout_kr;
-
-	add_timer(timer);
-}
-
-/*
- * caller should make sure no race with other threads
- */
-static
-void ctx_clear_timer_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx);
-	struct timer_list	  *timer = gctx_kr->gck_timer;
-
-	if (timer == NULL)
-		return;
-
-	CDEBUG(D_SEC, "ctx %p, key %p\n", ctx, gctx_kr->gck_key);
-
-	gctx_kr->gck_timer = NULL;
-
-	del_singleshot_timer_sync(timer);
-
-	OBD_FREE_PTR(timer);
-}
-
-static
-struct ptlrpc_cli_ctx *ctx_create_kr(struct ptlrpc_sec *sec,
-				     struct vfs_cred *vcred)
-{
-	struct ptlrpc_cli_ctx      *ctx;
-	struct gss_cli_ctx_keyring *gctx_kr;
-
-	OBD_ALLOC_PTR(gctx_kr);
-	if (gctx_kr == NULL)
-		return NULL;
-
-	OBD_ALLOC_PTR(gctx_kr->gck_timer);
-	if (gctx_kr->gck_timer == NULL) {
-		OBD_FREE_PTR(gctx_kr);
-		return NULL;
-	}
-	init_timer(gctx_kr->gck_timer);
-
-	ctx = &gctx_kr->gck_base.gc_base;
-
-	if (gss_cli_ctx_init_common(sec, ctx, &gss_keyring_ctxops, vcred)) {
-		OBD_FREE_PTR(gctx_kr->gck_timer);
-		OBD_FREE_PTR(gctx_kr);
-		return NULL;
-	}
-
-	ctx->cc_expire = cfs_time_current_sec() + KEYRING_UPCALL_TIMEOUT;
-	clear_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags);
-	atomic_inc(&ctx->cc_refcount); /* for the caller */
-
-	return ctx;
-}
-
-static void ctx_destroy_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	struct ptlrpc_sec	  *sec = ctx->cc_sec;
-	struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx);
-
-	CDEBUG(D_SEC, "destroying ctx %p\n", ctx);
-
-	/* at this time the association with key has been broken. */
-	LASSERT(sec);
-	LASSERT(atomic_read(&sec->ps_refcount) > 0);
-	LASSERT(atomic_read(&sec->ps_nctx) > 0);
-	LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
-	LASSERT(gctx_kr->gck_key == NULL);
-
-	ctx_clear_timer_kr(ctx);
-	LASSERT(gctx_kr->gck_timer == NULL);
-
-	if (gss_cli_ctx_fini_common(sec, ctx))
-		return;
-
-	OBD_FREE_PTR(gctx_kr);
-
-	atomic_dec(&sec->ps_nctx);
-	sptlrpc_sec_put(sec);
-}
-
-static void ctx_release_kr(struct ptlrpc_cli_ctx *ctx, int sync)
-{
-	if (sync) {
-		ctx_destroy_kr(ctx);
-	} else {
-		atomic_inc(&ctx->cc_refcount);
-		sptlrpc_gc_add_ctx(ctx);
-	}
-}
-
-static void ctx_put_kr(struct ptlrpc_cli_ctx *ctx, int sync)
-{
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-	if (atomic_dec_and_test(&ctx->cc_refcount))
-		ctx_release_kr(ctx, sync);
-}
-
-/*
- * key <-> ctx association and rules:
- * - ctx might not bind with any key
- * - key/ctx binding is protected by key semaphore (if the key present)
- * - key and ctx each take a reference of the other
- * - ctx enlist/unlist is protected by ctx spinlock
- * - never enlist a ctx after it's been unlisted
- * - whoever do enlist should also do bind, lock key before enlist:
- *   - lock key -> lock ctx -> enlist -> unlock ctx -> bind -> unlock key
- * - whoever do unlist should also do unbind:
- *   - lock key -> lock ctx -> unlist -> unlock ctx -> unbind -> unlock key
- *   - lock ctx -> unlist -> unlock ctx -> lock key -> unbind -> unlock key
- */
-
-static inline void spin_lock_if(spinlock_t *lock, int condition)
-{
-	if (condition)
-		spin_lock(lock);
-}
-
-static inline void spin_unlock_if(spinlock_t *lock, int condition)
-{
-	if (condition)
-		spin_unlock(lock);
-}
-
-static void ctx_enlist_kr(struct ptlrpc_cli_ctx *ctx, int is_root, int locked)
-{
-	struct ptlrpc_sec      *sec = ctx->cc_sec;
-	struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
-
-	LASSERT(!test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags));
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-	spin_lock_if(&sec->ps_lock, !locked);
-
-	atomic_inc(&ctx->cc_refcount);
-	set_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags);
-	hlist_add_head(&ctx->cc_cache, &gsec_kr->gsk_clist);
-	if (is_root)
-		gsec_kr->gsk_root_ctx = ctx;
-
-	spin_unlock_if(&sec->ps_lock, !locked);
-}
-
-/*
- * Note after this get called, caller should not access ctx again because
- * it might have been freed, unless caller hold at least one refcount of
- * the ctx.
- *
- * return non-zero if we indeed unlist this ctx.
- */
-static int ctx_unlist_kr(struct ptlrpc_cli_ctx *ctx, int locked)
-{
-	struct ptlrpc_sec       *sec = ctx->cc_sec;
-	struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
-
-	/* if hashed bit has gone, leave the job to somebody who is doing it */
-	if (test_and_clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0)
-		return 0;
-
-	/* drop ref inside spin lock to prevent race with other operations */
-	spin_lock_if(&sec->ps_lock, !locked);
-
-	if (gsec_kr->gsk_root_ctx == ctx)
-		gsec_kr->gsk_root_ctx = NULL;
-	hlist_del_init(&ctx->cc_cache);
-	atomic_dec(&ctx->cc_refcount);
-
-	spin_unlock_if(&sec->ps_lock, !locked);
-
-	return 1;
-}
-
-/*
- * bind a key with a ctx together.
- * caller must hold write lock of the key, as well as ref on key & ctx.
- */
-static void bind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
-{
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(atomic_read(&key->usage) > 0);
-	LASSERT(ctx2gctx_keyring(ctx)->gck_key == NULL);
-	LASSERT(key->payload.data == NULL);
-
-	/* at this time context may or may not in list. */
-	key_get(key);
-	atomic_inc(&ctx->cc_refcount);
-	ctx2gctx_keyring(ctx)->gck_key = key;
-	key->payload.data = ctx;
-}
-
-/*
- * unbind a key and a ctx.
- * caller must hold write lock, as well as a ref of the key.
- */
-static void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
-{
-	LASSERT(key->payload.data == ctx);
-	LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
-
-	/* must revoke the key, or others may treat it as newly created */
-	key_revoke_locked(key);
-
-	key->payload.data = NULL;
-	ctx2gctx_keyring(ctx)->gck_key = NULL;
-
-	/* once ctx get split from key, the timer is meaningless */
-	ctx_clear_timer_kr(ctx);
-
-	ctx_put_kr(ctx, 1);
-	key_put(key);
-}
-
-/*
- * given a ctx, unbind with its coupled key, if any.
- * unbind could only be called once, so we don't worry the key be released
- * by someone else.
- */
-static void unbind_ctx_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	struct key      *key = ctx2gctx_keyring(ctx)->gck_key;
-
-	if (key) {
-		LASSERT(key->payload.data == ctx);
-
-		key_get(key);
-		down_write(&key->sem);
-		unbind_key_ctx(key, ctx);
-		up_write(&key->sem);
-		key_put(key);
-	}
-}
-
-/*
- * given a key, unbind with its coupled ctx, if any.
- * caller must hold write lock, as well as a ref of the key.
- */
-static void unbind_key_locked(struct key *key)
-{
-	struct ptlrpc_cli_ctx   *ctx = key->payload.data;
-
-	if (ctx)
-		unbind_key_ctx(key, ctx);
-}
-
-/*
- * unlist a ctx, and unbind from coupled key
- */
-static void kill_ctx_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	if (ctx_unlist_kr(ctx, 0))
-		unbind_ctx_kr(ctx);
-}
-
-/*
- * given a key, unlist and unbind with the coupled ctx (if any).
- * caller must hold write lock, as well as a ref of the key.
- */
-static void kill_key_locked(struct key *key)
-{
-	struct ptlrpc_cli_ctx *ctx = key->payload.data;
-
-	if (ctx && ctx_unlist_kr(ctx, 0))
-		unbind_key_locked(key);
-}
-
-/*
- * caller should hold one ref on contexts in freelist.
- */
-static void dispose_ctx_list_kr(struct hlist_head *freelist)
-{
-	struct hlist_node      *next;
-	struct ptlrpc_cli_ctx  *ctx;
-	struct gss_cli_ctx     *gctx;
-
-	hlist_for_each_entry_safe(ctx, next, freelist, cc_cache) {
-		hlist_del_init(&ctx->cc_cache);
-
-		/* reverse ctx: update current seq to buddy svcctx if exist.
-		 * ideally this should be done at gss_cli_ctx_finalize(), but
-		 * the ctx destroy could be delayed by:
-		 *  1) ctx still has reference;
-		 *  2) ctx destroy is asynchronous;
-		 * and reverse import call inval_all_ctx() require this be done
-		 *_immediately_ otherwise newly created reverse ctx might copy
-		 * the very old sequence number from svcctx. */
-		gctx = ctx2gctx(ctx);
-		if (!rawobj_empty(&gctx->gc_svc_handle) &&
-		    sec_is_reverse(gctx->gc_base.cc_sec)) {
-			gss_svc_upcall_update_sequence(&gctx->gc_svc_handle,
-					(__u32) atomic_read(&gctx->gc_seq));
-		}
-
-		/* we need to wakeup waiting reqs here. the context might
-		 * be forced released before upcall finished, then the
-		 * late-arrived downcall can't find the ctx even. */
-		sptlrpc_cli_ctx_wakeup(ctx);
-
-		unbind_ctx_kr(ctx);
-		ctx_put_kr(ctx, 0);
-	}
-}
-
-/*
- * lookup a root context directly in a sec, return root ctx with a
- * reference taken or NULL.
- */
-static
-struct ptlrpc_cli_ctx * sec_lookup_root_ctx_kr(struct ptlrpc_sec *sec)
-{
-	struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
-	struct ptlrpc_cli_ctx   *ctx = NULL;
-
-	spin_lock(&sec->ps_lock);
-
-	ctx = gsec_kr->gsk_root_ctx;
-
-	if (ctx == NULL && unlikely(sec_is_reverse(sec))) {
-		struct ptlrpc_cli_ctx  *tmp;
-
-		/* reverse ctx, search root ctx in list, choose the one
-		 * with shortest expire time, which is most possibly have
-		 * an established peer ctx at client side. */
-		hlist_for_each_entry(tmp, &gsec_kr->gsk_clist, cc_cache) {
-			if (ctx == NULL || ctx->cc_expire == 0 ||
-			    ctx->cc_expire > tmp->cc_expire) {
-				ctx = tmp;
-				/* promote to be root_ctx */
-				gsec_kr->gsk_root_ctx = ctx;
-			}
-		}
-	}
-
-	if (ctx) {
-		LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-		LASSERT(!hlist_empty(&gsec_kr->gsk_clist));
-		atomic_inc(&ctx->cc_refcount);
-	}
-
-	spin_unlock(&sec->ps_lock);
-
-	return ctx;
-}
-
-#define RVS_CTX_EXPIRE_NICE    (10)
-
-static
-void rvs_sec_install_root_ctx_kr(struct ptlrpc_sec *sec,
-				 struct ptlrpc_cli_ctx *new_ctx,
-				 struct key *key)
-{
-	struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
-	struct ptlrpc_cli_ctx  *ctx;
-	cfs_time_t	      now;
-
-	LASSERT(sec_is_reverse(sec));
-
-	spin_lock(&sec->ps_lock);
-
-	now = cfs_time_current_sec();
-
-	/* set all existing ctxs short expiry */
-	hlist_for_each_entry(ctx, &gsec_kr->gsk_clist, cc_cache) {
-		if (ctx->cc_expire > now + RVS_CTX_EXPIRE_NICE) {
-			ctx->cc_early_expire = 1;
-			ctx->cc_expire = now + RVS_CTX_EXPIRE_NICE;
-		}
-	}
-
-	/* if there's root_ctx there, instead obsolete the current
-	 * immediately, we leave it continue operating for a little while.
-	 * hopefully when the first backward rpc with newest ctx send out,
-	 * the client side already have the peer ctx well established. */
-	ctx_enlist_kr(new_ctx, gsec_kr->gsk_root_ctx ? 0 : 1, 1);
-
-	if (key)
-		bind_key_ctx(key, new_ctx);
-
-	spin_unlock(&sec->ps_lock);
-}
-
-static void construct_key_desc(void *buf, int bufsize,
-			       struct ptlrpc_sec *sec, uid_t uid)
-{
-	snprintf(buf, bufsize, "%d@%x", uid, sec->ps_id);
-	((char *)buf)[bufsize - 1] = '\0';
-}
-
-/****************************************
- * sec apis			     *
- ****************************************/
-
-static
-struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
-				      struct ptlrpc_svc_ctx *svcctx,
-				      struct sptlrpc_flavor *sf)
-{
-	struct gss_sec_keyring  *gsec_kr;
-
-	OBD_ALLOC(gsec_kr, sizeof(*gsec_kr));
-	if (gsec_kr == NULL)
-		return NULL;
-
-	INIT_HLIST_HEAD(&gsec_kr->gsk_clist);
-	gsec_kr->gsk_root_ctx = NULL;
-	mutex_init(&gsec_kr->gsk_root_uc_lock);
-#ifdef HAVE_KEYRING_UPCALL_SERIALIZED
-	mutex_init(&gsec_kr->gsk_uc_lock);
-#endif
-
-	if (gss_sec_create_common(&gsec_kr->gsk_base, &gss_policy_keyring,
-				  imp, svcctx, sf))
-		goto err_free;
-
-	if (svcctx != NULL &&
-	    sec_install_rctx_kr(&gsec_kr->gsk_base.gs_base, svcctx)) {
-		gss_sec_destroy_common(&gsec_kr->gsk_base);
-		goto err_free;
-	}
-
-	return &gsec_kr->gsk_base.gs_base;
-
-err_free:
-	OBD_FREE(gsec_kr, sizeof(*gsec_kr));
-	return NULL;
-}
-
-static
-void gss_sec_destroy_kr(struct ptlrpc_sec *sec)
-{
-	struct gss_sec	  *gsec = sec2gsec(sec);
-	struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
-
-	CDEBUG(D_SEC, "destroy %s@%p\n", sec->ps_policy->sp_name, sec);
-
-	LASSERT(hlist_empty(&gsec_kr->gsk_clist));
-	LASSERT(gsec_kr->gsk_root_ctx == NULL);
-
-	gss_sec_destroy_common(gsec);
-
-	OBD_FREE(gsec_kr, sizeof(*gsec_kr));
-}
-
-static inline int user_is_root(struct ptlrpc_sec *sec, struct vfs_cred *vcred)
-{
-	/* except the ROOTONLY flag, treat it as root user only if real uid
-	 * is 0, euid/fsuid being 0 are handled as setuid scenarios */
-	if (sec_is_rootonly(sec) || (vcred->vc_uid == 0))
-		return 1;
-	else
-		return 0;
-}
-
-/*
- * unlink request key from it's ring, which is linked during request_key().
- * sadly, we have to 'guess' which keyring it's linked to.
- *
- * FIXME this code is fragile, depend on how request_key_link() is implemented.
- */
-static void request_key_unlink(struct key *key)
-{
-	struct task_struct *tsk = current;
-	struct key *ring;
-
-	switch (key_cred(tsk)->jit_keyring) {
-	case KEY_REQKEY_DEFL_DEFAULT:
-	case KEY_REQKEY_DEFL_THREAD_KEYRING:
-		ring = key_get(key_cred(tsk)->thread_keyring);
-		if (ring)
-			break;
-	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-		ring = key_get(key_tgcred(tsk)->process_keyring);
-		if (ring)
-			break;
-	case KEY_REQKEY_DEFL_SESSION_KEYRING:
-		rcu_read_lock();
-		ring = key_get(rcu_dereference(key_tgcred(tsk)
-					       ->session_keyring));
-		rcu_read_unlock();
-		if (ring)
-			break;
-	case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
-		ring = key_get(key_cred(tsk)->user->session_keyring);
-		break;
-	case KEY_REQKEY_DEFL_USER_KEYRING:
-		ring = key_get(key_cred(tsk)->user->uid_keyring);
-		break;
-	case KEY_REQKEY_DEFL_GROUP_KEYRING:
-	default:
-		LBUG();
-	}
-
-	LASSERT(ring);
-	key_unlink(ring, key);
-	key_put(ring);
-}
-
-static
-struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
-					      struct vfs_cred *vcred,
-					      int create, int remove_dead)
-{
-	struct obd_import       *imp = sec->ps_import;
-	struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
-	struct ptlrpc_cli_ctx   *ctx = NULL;
-	unsigned int	     is_root = 0, create_new = 0;
-	struct key	      *key;
-	char		     desc[24];
-	char		    *coinfo;
-	int		      coinfo_size;
-	char		    *co_flags = "";
-
-	LASSERT(imp != NULL);
-
-	is_root = user_is_root(sec, vcred);
-
-	/* a little bit optimization for root context */
-	if (is_root) {
-		ctx = sec_lookup_root_ctx_kr(sec);
-		/*
-		 * Only lookup directly for REVERSE sec, which should
-		 * always succeed.
-		 */
-		if (ctx || sec_is_reverse(sec))
-			return ctx;
-	}
-
-	LASSERT(create != 0);
-
-	/* for root context, obtain lock and check again, this time hold
-	 * the root upcall lock, make sure nobody else populated new root
-	 * context after last check. */
-	if (is_root) {
-		mutex_lock(&gsec_kr->gsk_root_uc_lock);
-
-		ctx = sec_lookup_root_ctx_kr(sec);
-		if (ctx)
-			goto out;
-
-		/* update reverse handle for root user */
-		sec2gsec(sec)->gs_rvs_hdl = gss_get_next_ctx_index();
-
-		switch (sec->ps_part) {
-		case LUSTRE_SP_MDT:
-			co_flags = "m";
-			break;
-		case LUSTRE_SP_OST:
-			co_flags = "o";
-			break;
-		case LUSTRE_SP_MGC:
-			co_flags = "rmo";
-			break;
-		case LUSTRE_SP_CLI:
-			co_flags = "r";
-			break;
-		case LUSTRE_SP_MGS:
-		default:
-			LBUG();
-		}
-	}
-
-	/* in case of setuid, key will be constructed as owner of fsuid/fsgid,
-	 * but we do authentication based on real uid/gid. the key permission
-	 * bits will be exactly as POS_ALL, so only processes who subscribed
-	 * this key could have the access, although the quota might be counted
-	 * on others (fsuid/fsgid).
-	 *
-	 * keyring will use fsuid/fsgid as upcall parameters, so we have to
-	 * encode real uid/gid into callout info.
-	 */
-
-	construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid);
-
-	/* callout info format:
-	 * secid:mech:uid:gid:flags:svc_type:peer_nid:target_uuid
-	 */
-	coinfo_size = sizeof(struct obd_uuid) + MAX_OBD_NAME + 64;
-	OBD_ALLOC(coinfo, coinfo_size);
-	if (coinfo == NULL)
-		goto out;
-
-	snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s",
-		 sec->ps_id, sec2gsec(sec)->gs_mech->gm_name,
-		 vcred->vc_uid, vcred->vc_gid,
-		 co_flags, import_to_gss_svc(imp),
-		 imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name);
-
-	CDEBUG(D_SEC, "requesting key for %s\n", desc);
-
-	keyring_upcall_lock(gsec_kr);
-	key = request_key(&gss_key_type, desc, coinfo);
-	keyring_upcall_unlock(gsec_kr);
-
-	OBD_FREE(coinfo, coinfo_size);
-
-	if (IS_ERR(key)) {
-		CERROR("failed request key: %ld\n", PTR_ERR(key));
-		goto out;
-	}
-	CDEBUG(D_SEC, "obtained key %08x for %s\n", key->serial, desc);
-
-	/* once payload.data was pointed to a ctx, it never changes until
-	 * we de-associate them; but parallel request_key() may return
-	 * a key with payload.data == NULL at the same time. so we still
-	 * need wirtelock of key->sem to serialize them. */
-	down_write(&key->sem);
-
-	if (likely(key->payload.data != NULL)) {
-		ctx = key->payload.data;
-
-		LASSERT(atomic_read(&ctx->cc_refcount) >= 1);
-		LASSERT(ctx2gctx_keyring(ctx)->gck_key == key);
-		LASSERT(atomic_read(&key->usage) >= 2);
-
-		/* simply take a ref and return. it's upper layer's
-		 * responsibility to detect & replace dead ctx. */
-		atomic_inc(&ctx->cc_refcount);
-	} else {
-		/* pre initialization with a cli_ctx. this can't be done in
-		 * key_instantiate() because we'v no enough information
-		 * there. */
-		ctx = ctx_create_kr(sec, vcred);
-		if (ctx != NULL) {
-			ctx_enlist_kr(ctx, is_root, 0);
-			bind_key_ctx(key, ctx);
-
-			ctx_start_timer_kr(ctx, KEYRING_UPCALL_TIMEOUT);
-
-			CDEBUG(D_SEC, "installed key %p <-> ctx %p (sec %p)\n",
-			       key, ctx, sec);
-		} else {
-			/* we'd prefer to call key_revoke(), but we more like
-			 * to revoke it within this key->sem locked period. */
-			key_revoke_locked(key);
-		}
-
-		create_new = 1;
-	}
-
-	up_write(&key->sem);
-
-	if (is_root && create_new)
-		request_key_unlink(key);
-
-	key_put(key);
-out:
-	if (is_root)
-		mutex_unlock(&gsec_kr->gsk_root_uc_lock);
-	return ctx;
-}
-
-static
-void gss_sec_release_ctx_kr(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx,
-			    int sync)
-{
-	LASSERT(atomic_read(&sec->ps_refcount) > 0);
-	LASSERT(atomic_read(&ctx->cc_refcount) == 0);
-	ctx_release_kr(ctx, sync);
-}
-
-/*
- * flush context of normal user, we must resort to keyring itself to find out
- * contexts which belong to me.
- *
- * Note here we suppose only to flush _my_ context, the "uid" will
- * be ignored in the search.
- */
-static
-void flush_user_ctx_cache_kr(struct ptlrpc_sec *sec,
-			     uid_t uid,
-			     int grace, int force)
-{
-	struct key	      *key;
-	char		     desc[24];
-
-	/* nothing to do for reverse or rootonly sec */
-	if (sec_is_reverse(sec) || sec_is_rootonly(sec))
-		return;
-
-	construct_key_desc(desc, sizeof(desc), sec, uid);
-
-	/* there should be only one valid key, but we put it in the
-	 * loop in case of any weird cases */
-	for (;;) {
-		key = request_key(&gss_key_type, desc, NULL);
-		if (IS_ERR(key)) {
-			CDEBUG(D_SEC, "No more key found for current user\n");
-			break;
-		}
-
-		down_write(&key->sem);
-
-		kill_key_locked(key);
-
-		/* kill_key_locked() should usually revoke the key, but we
-		 * revoke it again to make sure, e.g. some case the key may
-		 * not well coupled with a context. */
-		key_revoke_locked(key);
-
-		up_write(&key->sem);
-
-		key_put(key);
-	}
-}
-
-/*
- * flush context of root or all, we iterate through the list.
- */
-static
-void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec,
-			     uid_t uid,
-			     int grace, int force)
-{
-	struct gss_sec_keyring *gsec_kr;
-	struct hlist_head	freelist = HLIST_HEAD_INIT;
-	struct hlist_node      *next;
-	struct ptlrpc_cli_ctx  *ctx;
-
-	gsec_kr = sec2gsec_keyring(sec);
-
-	spin_lock(&sec->ps_lock);
-	hlist_for_each_entry_safe(ctx, next,
-				      &gsec_kr->gsk_clist, cc_cache) {
-		LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-		if (uid != -1 && uid != ctx->cc_vcred.vc_uid)
-			continue;
-
-		/* at this moment there's at least 2 base reference:
-		 * key association and in-list. */
-		if (atomic_read(&ctx->cc_refcount) > 2) {
-			if (!force)
-				continue;
-			CWARN("flush busy ctx %p(%u->%s, extra ref %d)\n",
-			      ctx, ctx->cc_vcred.vc_uid,
-			      sec2target_str(ctx->cc_sec),
-			      atomic_read(&ctx->cc_refcount) - 2);
-		}
-
-		set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags);
-		if (!grace)
-			clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
-
-		atomic_inc(&ctx->cc_refcount);
-
-		if (ctx_unlist_kr(ctx, 1)) {
-			hlist_add_head(&ctx->cc_cache, &freelist);
-		} else {
-			LASSERT(atomic_read(&ctx->cc_refcount) >= 2);
-			atomic_dec(&ctx->cc_refcount);
-		}
-	}
-	spin_unlock(&sec->ps_lock);
-
-	dispose_ctx_list_kr(&freelist);
-}
-
-static
-int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec,
-			       uid_t uid, int grace, int force)
-{
-	CDEBUG(D_SEC, "sec %p(%d, nctx %d), uid %d, grace %d, force %d\n",
-	       sec, atomic_read(&sec->ps_refcount),
-	       atomic_read(&sec->ps_nctx),
-	       uid, grace, force);
-
-	if (uid != -1 && uid != 0)
-		flush_user_ctx_cache_kr(sec, uid, grace, force);
-	else
-		flush_spec_ctx_cache_kr(sec, uid, grace, force);
-
-	return 0;
-}
-
-static
-void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec)
-{
-	struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
-	struct hlist_head	freelist = HLIST_HEAD_INIT;
-	struct hlist_node      *next;
-	struct ptlrpc_cli_ctx  *ctx;
-
-	CWARN("running gc\n");
-
-	spin_lock(&sec->ps_lock);
-	hlist_for_each_entry_safe(ctx, next,
-				      &gsec_kr->gsk_clist, cc_cache) {
-		LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-		atomic_inc(&ctx->cc_refcount);
-
-		if (cli_ctx_check_death(ctx) && ctx_unlist_kr(ctx, 1)) {
-			hlist_add_head(&ctx->cc_cache, &freelist);
-			CWARN("unhashed ctx %p\n", ctx);
-		} else {
-			LASSERT(atomic_read(&ctx->cc_refcount) >= 2);
-			atomic_dec(&ctx->cc_refcount);
-		}
-	}
-	spin_unlock(&sec->ps_lock);
-
-	dispose_ctx_list_kr(&freelist);
-}
-
-static
-int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq)
-{
-	struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
-	struct hlist_node      *next;
-	struct ptlrpc_cli_ctx  *ctx;
-	struct gss_cli_ctx     *gctx;
-	time_t		  now = cfs_time_current_sec();
-
-	spin_lock(&sec->ps_lock);
-	hlist_for_each_entry_safe(ctx, next,
-				  &gsec_kr->gsk_clist, cc_cache) {
-		struct key	     *key;
-		char		    flags_str[40];
-		char		    mech[40];
-
-		gctx = ctx2gctx(ctx);
-		key = ctx2gctx_keyring(ctx)->gck_key;
-
-		gss_cli_ctx_flags2str(ctx->cc_flags,
-				      flags_str, sizeof(flags_str));
-
-		if (gctx->gc_mechctx)
-			lgss_display(gctx->gc_mechctx, mech, sizeof(mech));
-		else
-			snprintf(mech, sizeof(mech), "N/A");
-		mech[sizeof(mech) - 1] = '\0';
-
-		seq_printf(seq, "%p: uid %u, ref %d, expire %ld(%+ld), fl %s, "
-			   "seq %d, win %u, key %08x(ref %d), "
-			   "hdl "LPX64":"LPX64", mech: %s\n",
-			   ctx, ctx->cc_vcred.vc_uid,
-			   atomic_read(&ctx->cc_refcount),
-			   ctx->cc_expire,
-			   ctx->cc_expire ?  ctx->cc_expire - now : 0,
-			   flags_str,
-			   atomic_read(&gctx->gc_seq),
-			   gctx->gc_win,
-			   key ? key->serial : 0,
-			   key ? atomic_read(&key->usage) : 0,
-			   gss_handle_to_u64(&gctx->gc_handle),
-			   gss_handle_to_u64(&gctx->gc_svc_handle),
-			   mech);
-	}
-	spin_unlock(&sec->ps_lock);
-
-	return 0;
-}
-
-/****************************************
- * cli_ctx apis			 *
- ****************************************/
-
-static
-int gss_cli_ctx_refresh_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	/* upcall is already on the way */
-	return 0;
-}
-
-static
-int gss_cli_ctx_validate_kr(struct ptlrpc_cli_ctx *ctx)
-{
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(ctx->cc_sec);
-
-	if (cli_ctx_check_death(ctx)) {
-		kill_ctx_kr(ctx);
-		return 1;
-	}
-
-	if (cli_ctx_is_ready(ctx))
-		return 0;
-	return 1;
-}
-
-static
-void gss_cli_ctx_die_kr(struct ptlrpc_cli_ctx *ctx, int grace)
-{
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(ctx->cc_sec);
-
-	cli_ctx_expire(ctx);
-	kill_ctx_kr(ctx);
-}
-
-/****************************************
- * (reverse) service		    *
- ****************************************/
-
-/*
- * reverse context could have nothing to do with keyrings. here we still keep
- * the version which bind to a key, for future reference.
- */
-#define HAVE_REVERSE_CTX_NOKEY
-
-
-static
-int sec_install_rctx_kr(struct ptlrpc_sec *sec,
-			struct ptlrpc_svc_ctx *svc_ctx)
-{
-	struct ptlrpc_cli_ctx   *cli_ctx;
-	struct vfs_cred	  vcred = { 0, 0 };
-	int		      rc;
-
-	LASSERT(sec);
-	LASSERT(svc_ctx);
-
-	cli_ctx = ctx_create_kr(sec, &vcred);
-	if (cli_ctx == NULL)
-		return -ENOMEM;
-
-	rc = gss_copy_rvc_cli_ctx(cli_ctx, svc_ctx);
-	if (rc) {
-		CERROR("failed copy reverse cli ctx: %d\n", rc);
-
-		ctx_put_kr(cli_ctx, 1);
-		return rc;
-	}
-
-	rvs_sec_install_root_ctx_kr(sec, cli_ctx, NULL);
-
-	ctx_put_kr(cli_ctx, 1);
-
-	return 0;
-}
-
-
-/****************************************
- * service apis			 *
- ****************************************/
-
-static
-int gss_svc_accept_kr(struct ptlrpc_request *req)
-{
-	return gss_svc_accept(&gss_policy_keyring, req);
-}
-
-static
-int gss_svc_install_rctx_kr(struct obd_import *imp,
-			    struct ptlrpc_svc_ctx *svc_ctx)
-{
-	struct ptlrpc_sec *sec;
-	int		rc;
-
-	sec = sptlrpc_import_sec_ref(imp);
-	LASSERT(sec);
-
-	rc = sec_install_rctx_kr(sec, svc_ctx);
-	sptlrpc_sec_put(sec);
-
-	return rc;
-}
-
-/****************************************
- * key apis			     *
- ****************************************/
-
-static
-int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
-{
-	int	     rc;
-
-	if (data != NULL || datalen != 0) {
-		CERROR("invalid: data %p, len %lu\n", data, (long)datalen);
-		return -EINVAL;
-	}
-
-	if (key->payload.data != 0) {
-		CERROR("key already have payload\n");
-		return -EINVAL;
-	}
-
-	/* link the key to session keyring, so following context negotiation
-	 * rpc fired from user space could find this key. This will be unlinked
-	 * automatically when upcall processes die.
-	 *
-	 * we can't do this through keyctl from userspace, because the upcall
-	 * might be neither possessor nor owner of the key (setuid).
-	 *
-	 * the session keyring is created upon upcall, and don't change all
-	 * the way until upcall finished, so rcu lock is not needed here.
-	 */
-	LASSERT(key_tgcred(current)->session_keyring);
-
-	lockdep_off();
-	rc = key_link(key_tgcred(current)->session_keyring, key);
-	lockdep_on();
-	if (unlikely(rc)) {
-		CERROR("failed to link key %08x to keyring %08x: %d\n",
-		       key->serial,
-		       key_tgcred(current)->session_keyring->serial, rc);
-		return rc;
-	}
-
-	CDEBUG(D_SEC, "key %p instantiated, ctx %p\n", key, key->payload.data);
-	return 0;
-}
-
-/*
- * called with key semaphore write locked. it means we can operate
- * on the context without fear of losing refcount.
- */
-static
-int gss_kt_update(struct key *key, const void *data, size_t datalen)
-{
-	struct ptlrpc_cli_ctx   *ctx = key->payload.data;
-	struct gss_cli_ctx      *gctx;
-	rawobj_t		 tmpobj = RAWOBJ_EMPTY;
-	__u32		    datalen32 = (__u32) datalen;
-	int		      rc;
-
-	if (data == NULL || datalen == 0) {
-		CWARN("invalid: data %p, len %lu\n", data, (long)datalen);
-		return -EINVAL;
-	}
-
-	/* if upcall finished negotiation too fast (mostly likely because
-	 * of local error happened) and call kt_update(), the ctx
-	 * might be still NULL. but the key will finally be associate
-	 * with a context, or be revoked. if key status is fine, return
-	 * -EAGAIN to allow userspace sleep a while and call again. */
-	if (ctx == NULL) {
-		CDEBUG(D_SEC, "update too soon: key %p(%x) flags %lx\n",
-		      key, key->serial, key->flags);
-
-		rc = key_validate(key);
-		if (rc == 0)
-			return -EAGAIN;
-		else
-			return rc;
-	}
-
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(ctx->cc_sec);
-
-	ctx_clear_timer_kr(ctx);
-
-	/* don't proceed if already refreshed */
-	if (cli_ctx_is_refreshed(ctx)) {
-		CWARN("ctx already done refresh\n");
-		return 0;
-	}
-
-	sptlrpc_cli_ctx_get(ctx);
-	gctx = ctx2gctx(ctx);
-
-	rc = buffer_extract_bytes(&data, &datalen32, &gctx->gc_win,
-				  sizeof(gctx->gc_win));
-	if (rc) {
-		CERROR("failed extract seq_win\n");
-		goto out;
-	}
-
-	if (gctx->gc_win == 0) {
-		__u32   nego_rpc_err, nego_gss_err;
-
-		rc = buffer_extract_bytes(&data, &datalen32, &nego_rpc_err,
-					  sizeof(nego_rpc_err));
-		if (rc) {
-			CERROR("failed to extrace rpc rc\n");
-			goto out;
-		}
-
-		rc = buffer_extract_bytes(&data, &datalen32, &nego_gss_err,
-					  sizeof(nego_gss_err));
-		if (rc) {
-			CERROR("failed to extrace gss rc\n");
-			goto out;
-		}
-
-		CERROR("negotiation: rpc err %d, gss err %x\n",
-		       nego_rpc_err, nego_gss_err);
-
-		rc = nego_rpc_err ? nego_rpc_err : -EACCES;
-	} else {
-		rc = rawobj_extract_local_alloc(&gctx->gc_handle,
-						(__u32 **) &data, &datalen32);
-		if (rc) {
-			CERROR("failed extract handle\n");
-			goto out;
-		}
-
-		rc = rawobj_extract_local(&tmpobj, (__u32 **) &data,&datalen32);
-		if (rc) {
-			CERROR("failed extract mech\n");
-			goto out;
-		}
-
-		rc = lgss_import_sec_context(&tmpobj,
-					     sec2gsec(ctx->cc_sec)->gs_mech,
-					     &gctx->gc_mechctx);
-		if (rc != GSS_S_COMPLETE)
-			CERROR("failed import context\n");
-		else
-			rc = 0;
-	}
-out:
-	/* we don't care what current status of this ctx, even someone else
-	 * is operating on the ctx at the same time. we just add up our own
-	 * opinions here. */
-	if (rc == 0) {
-		gss_cli_ctx_uptodate(gctx);
-	} else {
-		/* this will also revoke the key. has to be done before
-		 * wakeup waiters otherwise they can find the stale key */
-		kill_key_locked(key);
-
-		cli_ctx_expire(ctx);
-
-		if (rc != -ERESTART)
-			set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags);
-	}
-
-	/* let user space think it's a success */
-	sptlrpc_cli_ctx_put(ctx, 1);
-	return 0;
-}
-
-static
-int gss_kt_match(const struct key *key, const void *desc)
-{
-	return (strcmp(key->description, (const char *) desc) == 0);
-}
-
-static
-void gss_kt_destroy(struct key *key)
-{
-	LASSERT(key->payload.data == NULL);
-	CDEBUG(D_SEC, "destroy key %p\n", key);
-}
-
-static
-void gss_kt_describe(const struct key *key, struct seq_file *s)
-{
-	if (key->description == NULL)
-		seq_puts(s, "[null]");
-	else
-		seq_puts(s, key->description);
-}
-
-static struct key_type gss_key_type =
-{
-	.name	   = "lgssc",
-	.def_datalen    = 0,
-	.instantiate    = gss_kt_instantiate,
-	.update	 = gss_kt_update,
-	.match	  = gss_kt_match,
-	.destroy	= gss_kt_destroy,
-	.describe       = gss_kt_describe,
-};
-
-/****************************************
- * lustre gss keyring policy	    *
- ****************************************/
-
-static struct ptlrpc_ctx_ops gss_keyring_ctxops = {
-	.match		  = gss_cli_ctx_match,
-	.refresh		= gss_cli_ctx_refresh_kr,
-	.validate	       = gss_cli_ctx_validate_kr,
-	.die		    = gss_cli_ctx_die_kr,
-	.sign		   = gss_cli_ctx_sign,
-	.verify		 = gss_cli_ctx_verify,
-	.seal		   = gss_cli_ctx_seal,
-	.unseal		 = gss_cli_ctx_unseal,
-	.wrap_bulk	      = gss_cli_ctx_wrap_bulk,
-	.unwrap_bulk	    = gss_cli_ctx_unwrap_bulk,
-};
-
-static struct ptlrpc_sec_cops gss_sec_keyring_cops = {
-	.create_sec	     = gss_sec_create_kr,
-	.destroy_sec	    = gss_sec_destroy_kr,
-	.kill_sec	       = gss_sec_kill,
-	.lookup_ctx	     = gss_sec_lookup_ctx_kr,
-	.release_ctx	    = gss_sec_release_ctx_kr,
-	.flush_ctx_cache	= gss_sec_flush_ctx_cache_kr,
-	.gc_ctx		 = gss_sec_gc_ctx_kr,
-	.install_rctx	   = gss_sec_install_rctx,
-	.alloc_reqbuf	   = gss_alloc_reqbuf,
-	.free_reqbuf	    = gss_free_reqbuf,
-	.alloc_repbuf	   = gss_alloc_repbuf,
-	.free_repbuf	    = gss_free_repbuf,
-	.enlarge_reqbuf	 = gss_enlarge_reqbuf,
-	.display		= gss_sec_display_kr,
-};
-
-static struct ptlrpc_sec_sops gss_sec_keyring_sops = {
-	.accept		 = gss_svc_accept_kr,
-	.invalidate_ctx	 = gss_svc_invalidate_ctx,
-	.alloc_rs	       = gss_svc_alloc_rs,
-	.authorize	      = gss_svc_authorize,
-	.free_rs		= gss_svc_free_rs,
-	.free_ctx	       = gss_svc_free_ctx,
-	.prep_bulk	      = gss_svc_prep_bulk,
-	.unwrap_bulk	    = gss_svc_unwrap_bulk,
-	.wrap_bulk	      = gss_svc_wrap_bulk,
-	.install_rctx	   = gss_svc_install_rctx_kr,
-};
-
-static struct ptlrpc_sec_policy gss_policy_keyring = {
-	.sp_owner	       = THIS_MODULE,
-	.sp_name		= "gss.keyring",
-	.sp_policy	      = SPTLRPC_POLICY_GSS,
-	.sp_cops		= &gss_sec_keyring_cops,
-	.sp_sops		= &gss_sec_keyring_sops,
-};
-
-
-int __init gss_init_keyring(void)
-{
-	int rc;
-
-	rc = register_key_type(&gss_key_type);
-	if (rc) {
-		CERROR("failed to register keyring type: %d\n", rc);
-		return rc;
-	}
-
-	rc = sptlrpc_register_policy(&gss_policy_keyring);
-	if (rc) {
-		unregister_key_type(&gss_key_type);
-		return rc;
-	}
-
-	return 0;
-}
-
-void __exit gss_exit_keyring(void)
-{
-	unregister_key_type(&gss_key_type);
-	sptlrpc_unregister_policy(&gss_policy_keyring);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  linux/include/linux/sunrpc/gss_krb5_types.h
- *
- *  Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
- *  lib/gssapi/krb5/gssapiP_krb5.h, and others
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- *  Bruce Fields   <bfields@umich.edu>
- */
-
-/*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, 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 M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-#ifndef PTLRPC_GSS_KRB5_H
-#define PTLRPC_GSS_KRB5_H
-
-/*
- * RFC 4142
- */
-
-#define KG_USAGE_ACCEPTOR_SEAL	  22
-#define KG_USAGE_ACCEPTOR_SIGN	  23
-#define KG_USAGE_INITIATOR_SEAL	 24
-#define KG_USAGE_INITIATOR_SIGN	 25
-
-#define KG_TOK_MIC_MSG		  0x0404
-#define KG_TOK_WRAP_MSG		 0x0504
-
-#define FLAG_SENDER_IS_ACCEPTOR	 0x01
-#define FLAG_WRAP_CONFIDENTIAL	  0x02
-#define FLAG_ACCEPTOR_SUBKEY	    0x04
-
-struct krb5_header {
-	__u16	   kh_tok_id;      /* token id */
-	__u8	    kh_flags;       /* acceptor flags */
-	__u8	    kh_filler;      /* 0xff */
-	__u16	   kh_ec;	  /* extra count */
-	__u16	   kh_rrc;	 /* right rotation count */
-	__u64	   kh_seq;	 /* sequence number */
-	__u8	    kh_cksum[0];    /* checksum */
-};
-
-struct krb5_keyblock {
-	rawobj_t		 kb_key;
-	struct ll_crypto_cipher *kb_tfm;
-};
-
-struct krb5_ctx {
-	unsigned int	    kc_initiate:1,
-				kc_cfx:1,
-				kc_seed_init:1,
-				kc_have_acceptor_subkey:1;
-	__s32		   kc_endtime;
-	__u8		    kc_seed[16];
-	__u64		   kc_seq_send;
-	__u64		   kc_seq_recv;
-	__u32		   kc_enctype;
-	struct krb5_keyblock    kc_keye;	/* encryption */
-	struct krb5_keyblock    kc_keyi;	/* integrity */
-	struct krb5_keyblock    kc_keyc;	/* checksum */
-	rawobj_t		kc_mech_used;
-};
-
-enum sgn_alg {
-	SGN_ALG_DES_MAC_MD5	   = 0x0000,
-	SGN_ALG_MD2_5		 = 0x0001,
-	SGN_ALG_DES_MAC	       = 0x0002,
-	SGN_ALG_3		     = 0x0003, /* not published */
-	SGN_ALG_HMAC_MD5	      = 0x0011, /* microsoft w2k; no support */
-	SGN_ALG_HMAC_SHA1_DES3_KD     = 0x0004
-};
-
-enum seal_alg {
-	SEAL_ALG_NONE		 = 0xffff,
-	SEAL_ALG_DES		  = 0x0000,
-	SEAL_ALG_1		    = 0x0001, /* not published */
-	SEAL_ALG_MICROSOFT_RC4	= 0x0010, /* microsoft w2k; no support */
-	SEAL_ALG_DES3KD	       = 0x0002
-};
-
-#define CKSUMTYPE_CRC32		 0x0001
-#define CKSUMTYPE_RSA_MD4	       0x0002
-#define CKSUMTYPE_RSA_MD4_DES	   0x0003
-#define CKSUMTYPE_DESCBC		0x0004
-/* des-mac-k */
-/* rsa-md4-des-k */
-#define CKSUMTYPE_RSA_MD5	       0x0007
-#define CKSUMTYPE_RSA_MD5_DES	   0x0008
-#define CKSUMTYPE_NIST_SHA	      0x0009
-#define CKSUMTYPE_HMAC_SHA1_DES3	0x000c
-#define CKSUMTYPE_HMAC_SHA1_96_AES128   0x000f
-#define CKSUMTYPE_HMAC_SHA1_96_AES256   0x0010
-#define CKSUMTYPE_HMAC_MD5_ARCFOUR      -138
-
-/* from gssapi_err_krb5.h */
-#define KG_CCACHE_NOMATCH			(39756032L)
-#define KG_KEYTAB_NOMATCH			(39756033L)
-#define KG_TGT_MISSING			   (39756034L)
-#define KG_NO_SUBKEY			     (39756035L)
-#define KG_CONTEXT_ESTABLISHED		   (39756036L)
-#define KG_BAD_SIGN_TYPE			 (39756037L)
-#define KG_BAD_LENGTH			    (39756038L)
-#define KG_CTX_INCOMPLETE			(39756039L)
-#define KG_CONTEXT			       (39756040L)
-#define KG_CRED				  (39756041L)
-#define KG_ENC_DESC			      (39756042L)
-#define KG_BAD_SEQ			       (39756043L)
-#define KG_EMPTY_CCACHE			  (39756044L)
-#define KG_NO_CTYPES			     (39756045L)
-
-/* per Kerberos v5 protocol spec crypto types from the wire.
- * these get mapped to linux kernel crypto routines.
- */
-#define ENCTYPE_NULL	    0x0000
-#define ENCTYPE_DES_CBC_CRC     0x0001	/* DES cbc mode with CRC-32 */
-#define ENCTYPE_DES_CBC_MD4     0x0002	/* DES cbc mode with RSA-MD4 */
-#define ENCTYPE_DES_CBC_MD5     0x0003	/* DES cbc mode with RSA-MD5 */
-#define ENCTYPE_DES_CBC_RAW     0x0004	/* DES cbc mode raw */
-/* XXX deprecated? */
-#define ENCTYPE_DES3_CBC_SHA    0x0005	/* DES-3 cbc mode with NIST-SHA */
-#define ENCTYPE_DES3_CBC_RAW    0x0006	/* DES-3 cbc mode raw */
-#define ENCTYPE_DES_HMAC_SHA1   0x0008
-#define ENCTYPE_DES3_CBC_SHA1   0x0010
-#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
-#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
-#define ENCTYPE_ARCFOUR_HMAC    0x0017
-#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018
-#define ENCTYPE_UNKNOWN	 0x01ff
-
-#endif /* PTLRPC_GSS_KRB5_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1786 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  linux/net/sunrpc/gss_krb5_mech.c
- *  linux/net/sunrpc/gss_krb5_crypto.c
- *  linux/net/sunrpc/gss_krb5_seal.c
- *  linux/net/sunrpc/gss_krb5_seqnum.c
- *  linux/net/sunrpc/gss_krb5_unseal.c
- *
- *  Copyright (c) 2001 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *  J. Bruce Fields <bfields@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/crypto.h>
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-#include "gss_asn1.h"
-#include "gss_krb5.h"
-
-static spinlock_t krb5_seq_lock;
-
-struct krb5_enctype {
-	char	   *ke_dispname;
-	char	   *ke_enc_name;	    /* linux tfm name */
-	char	   *ke_hash_name;	   /* linux tfm name */
-	int	     ke_enc_mode;	    /* linux tfm mode */
-	int	     ke_hash_size;	   /* checksum size */
-	int	     ke_conf_size;	   /* confounder size */
-	unsigned int    ke_hash_hmac:1;	 /* is hmac? */
-};
-
-/*
- * NOTE: for aes128-cts and aes256-cts, MIT implementation use CTS encryption.
- * but currently we simply CBC with padding, because linux doesn't support CTS
- * yet. this need to be fixed in the future.
- */
-static struct krb5_enctype enctypes[] = {
-	[ENCTYPE_DES_CBC_RAW] = {	       /* des-cbc-md5 */
-		"des-cbc-md5",
-		"cbc(des)",
-		"md5",
-		0,
-		16,
-		8,
-		0,
-	},
-	[ENCTYPE_DES3_CBC_RAW] = {	      /* des3-hmac-sha1 */
-		"des3-hmac-sha1",
-		"cbc(des3_ede)",
-		"hmac(sha1)",
-		0,
-		20,
-		8,
-		1,
-	},
-	[ENCTYPE_AES128_CTS_HMAC_SHA1_96] = {   /* aes128-cts */
-		"aes128-cts-hmac-sha1-96",
-		"cbc(aes)",
-		"hmac(sha1)",
-		0,
-		12,
-		16,
-		1,
-	},
-	[ENCTYPE_AES256_CTS_HMAC_SHA1_96] = {   /* aes256-cts */
-		"aes256-cts-hmac-sha1-96",
-		"cbc(aes)",
-		"hmac(sha1)",
-		0,
-		12,
-		16,
-		1,
-	},
-	[ENCTYPE_ARCFOUR_HMAC] = {	      /* arcfour-hmac-md5 */
-		"arcfour-hmac-md5",
-		"ecb(arc4)",
-		"hmac(md5)",
-		0,
-		16,
-		8,
-		1,
-	},
-};
-
-#define MAX_ENCTYPES    sizeof(enctypes)/sizeof(struct krb5_enctype)
-
-static const char * enctype2str(__u32 enctype)
-{
-	if (enctype < MAX_ENCTYPES && enctypes[enctype].ke_dispname)
-		return enctypes[enctype].ke_dispname;
-
-	return "unknown";
-}
-
-static
-int keyblock_init(struct krb5_keyblock *kb, char *alg_name, int alg_mode)
-{
-	kb->kb_tfm = crypto_alloc_blkcipher(alg_name, alg_mode, 0);
-	if (IS_ERR(kb->kb_tfm)) {
-		CERROR("failed to alloc tfm: %s, mode %d\n",
-		       alg_name, alg_mode);
-		return -1;
-	}
-
-	if (crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data, kb->kb_key.len)) {
-		CERROR("failed to set %s key, len %d\n",
-		       alg_name, kb->kb_key.len);
-		return -1;
-	}
-
-	return 0;
-}
-
-static
-int krb5_init_keys(struct krb5_ctx *kctx)
-{
-	struct krb5_enctype *ke;
-
-	if (kctx->kc_enctype >= MAX_ENCTYPES ||
-	    enctypes[kctx->kc_enctype].ke_hash_size == 0) {
-		CERROR("unsupported enctype %x\n", kctx->kc_enctype);
-		return -1;
-	}
-
-	ke = &enctypes[kctx->kc_enctype];
-
-	/* tfm arc4 is stateful, user should alloc-use-free by his own */
-	if (kctx->kc_enctype != ENCTYPE_ARCFOUR_HMAC &&
-	    keyblock_init(&kctx->kc_keye, ke->ke_enc_name, ke->ke_enc_mode))
-		return -1;
-
-	/* tfm hmac is stateful, user should alloc-use-free by his own */
-	if (ke->ke_hash_hmac == 0 &&
-	    keyblock_init(&kctx->kc_keyi, ke->ke_enc_name, ke->ke_enc_mode))
-		return -1;
-	if (ke->ke_hash_hmac == 0 &&
-	    keyblock_init(&kctx->kc_keyc, ke->ke_enc_name, ke->ke_enc_mode))
-		return -1;
-
-	return 0;
-}
-
-static
-void keyblock_free(struct krb5_keyblock *kb)
-{
-	rawobj_free(&kb->kb_key);
-	if (kb->kb_tfm)
-		crypto_free_blkcipher(kb->kb_tfm);
-}
-
-static
-int keyblock_dup(struct krb5_keyblock *new, struct krb5_keyblock *kb)
-{
-	return rawobj_dup(&new->kb_key, &kb->kb_key);
-}
-
-static
-int get_bytes(char **ptr, const char *end, void *res, int len)
-{
-	char *p, *q;
-	p = *ptr;
-	q = p + len;
-	if (q > end || q < p)
-		return -1;
-	memcpy(res, p, len);
-	*ptr = q;
-	return 0;
-}
-
-static
-int get_rawobj(char **ptr, const char *end, rawobj_t *res)
-{
-	char   *p, *q;
-	__u32   len;
-
-	p = *ptr;
-	if (get_bytes(&p, end, &len, sizeof(len)))
-		return -1;
-
-	q = p + len;
-	if (q > end || q < p)
-		return -1;
-
-	OBD_ALLOC_LARGE(res->data, len);
-	if (!res->data)
-		return -1;
-
-	res->len = len;
-	memcpy(res->data, p, len);
-	*ptr = q;
-	return 0;
-}
-
-static
-int get_keyblock(char **ptr, const char *end,
-		 struct krb5_keyblock *kb, __u32 keysize)
-{
-	char *buf;
-
-	OBD_ALLOC_LARGE(buf, keysize);
-	if (buf == NULL)
-		return -1;
-
-	if (get_bytes(ptr, end, buf, keysize)) {
-		OBD_FREE_LARGE(buf, keysize);
-		return -1;
-	}
-
-	kb->kb_key.len = keysize;
-	kb->kb_key.data = buf;
-	return 0;
-}
-
-static
-void delete_context_kerberos(struct krb5_ctx *kctx)
-{
-	rawobj_free(&kctx->kc_mech_used);
-
-	keyblock_free(&kctx->kc_keye);
-	keyblock_free(&kctx->kc_keyi);
-	keyblock_free(&kctx->kc_keyc);
-}
-
-static
-__u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end)
-{
-	unsigned int    tmp_uint, keysize;
-
-	/* seed_init flag */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-		goto out_err;
-	kctx->kc_seed_init = (tmp_uint != 0);
-
-	/* seed */
-	if (get_bytes(&p, end, kctx->kc_seed, sizeof(kctx->kc_seed)))
-		goto out_err;
-
-	/* sign/seal algorithm, not really used now */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-	    get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-		goto out_err;
-
-	/* end time */
-	if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
-		goto out_err;
-
-	/* seq send */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-		goto out_err;
-	kctx->kc_seq_send = tmp_uint;
-
-	/* mech oid */
-	if (get_rawobj(&p, end, &kctx->kc_mech_used))
-		goto out_err;
-
-	/* old style enc/seq keys in format:
-	 *   - enctype (u32)
-	 *   - keysize (u32)
-	 *   - keydata
-	 * we decompose them to fit into the new context
-	 */
-
-	/* enc key */
-	if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
-		goto out_err;
-
-	if (get_bytes(&p, end, &keysize, sizeof(keysize)))
-		goto out_err;
-
-	if (get_keyblock(&p, end, &kctx->kc_keye, keysize))
-		goto out_err;
-
-	/* seq key */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-	    tmp_uint != kctx->kc_enctype)
-		goto out_err;
-
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-	    tmp_uint != keysize)
-		goto out_err;
-
-	if (get_keyblock(&p, end, &kctx->kc_keyc, keysize))
-		goto out_err;
-
-	/* old style fallback */
-	if (keyblock_dup(&kctx->kc_keyi, &kctx->kc_keyc))
-		goto out_err;
-
-	if (p != end)
-		goto out_err;
-
-	CDEBUG(D_SEC, "successfully imported rfc1964 context\n");
-	return 0;
-out_err:
-	return GSS_S_FAILURE;
-}
-
-/* Flags for version 2 context flags */
-#define KRB5_CTX_FLAG_INITIATOR		0x00000001
-#define KRB5_CTX_FLAG_CFX		0x00000002
-#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
-
-static
-__u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end)
-{
-	unsigned int    tmp_uint, keysize;
-
-	/* end time */
-	if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
-		goto out_err;
-
-	/* flags */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-		goto out_err;
-
-	if (tmp_uint & KRB5_CTX_FLAG_INITIATOR)
-		kctx->kc_initiate = 1;
-	if (tmp_uint & KRB5_CTX_FLAG_CFX)
-		kctx->kc_cfx = 1;
-	if (tmp_uint & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
-		kctx->kc_have_acceptor_subkey = 1;
-
-	/* seq send */
-	if (get_bytes(&p, end, &kctx->kc_seq_send, sizeof(kctx->kc_seq_send)))
-		goto out_err;
-
-	/* enctype */
-	if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
-		goto out_err;
-
-	/* size of each key */
-	if (get_bytes(&p, end, &keysize, sizeof(keysize)))
-		goto out_err;
-
-	/* number of keys - should always be 3 */
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-		goto out_err;
-
-	if (tmp_uint != 3) {
-		CERROR("Invalid number of keys: %u\n", tmp_uint);
-		goto out_err;
-	}
-
-	/* ke */
-	if (get_keyblock(&p, end, &kctx->kc_keye, keysize))
-		goto out_err;
-	/* ki */
-	if (get_keyblock(&p, end, &kctx->kc_keyi, keysize))
-		goto out_err;
-	/* ki */
-	if (get_keyblock(&p, end, &kctx->kc_keyc, keysize))
-		goto out_err;
-
-	CDEBUG(D_SEC, "successfully imported v2 context\n");
-	return 0;
-out_err:
-	return GSS_S_FAILURE;
-}
-
-/*
- * The whole purpose here is trying to keep user level gss context parsing
- * from nfs-utils unchanged as possible as we can, they are not quite mature
- * yet, and many stuff still not clear, like heimdal etc.
- */
-static
-__u32 gss_import_sec_context_kerberos(rawobj_t *inbuf,
-				      struct gss_ctx *gctx)
-{
-	struct krb5_ctx *kctx;
-	char	    *p = (char *) inbuf->data;
-	char	    *end = (char *) (inbuf->data + inbuf->len);
-	unsigned int     tmp_uint, rc;
-
-	if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) {
-		CERROR("Fail to read version\n");
-		return GSS_S_FAILURE;
-	}
-
-	/* only support 0, 1 for the moment */
-	if (tmp_uint > 2) {
-		CERROR("Invalid version %u\n", tmp_uint);
-		return GSS_S_FAILURE;
-	}
-
-	OBD_ALLOC_PTR(kctx);
-	if (!kctx)
-		return GSS_S_FAILURE;
-
-	if (tmp_uint == 0 || tmp_uint == 1) {
-		kctx->kc_initiate = tmp_uint;
-		rc = import_context_rfc1964(kctx, p, end);
-	} else {
-		rc = import_context_rfc4121(kctx, p, end);
-	}
-
-	if (rc == 0)
-		rc = krb5_init_keys(kctx);
-
-	if (rc) {
-		delete_context_kerberos(kctx);
-		OBD_FREE_PTR(kctx);
-
-		return GSS_S_FAILURE;
-	}
-
-	gctx->internal_ctx_id = kctx;
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx,
-					struct gss_ctx *gctx_new)
-{
-	struct krb5_ctx *kctx = gctx->internal_ctx_id;
-	struct krb5_ctx *knew;
-
-	OBD_ALLOC_PTR(knew);
-	if (!knew)
-		return GSS_S_FAILURE;
-
-	knew->kc_initiate = kctx->kc_initiate ? 0 : 1;
-	knew->kc_cfx = kctx->kc_cfx;
-	knew->kc_seed_init = kctx->kc_seed_init;
-	knew->kc_have_acceptor_subkey = kctx->kc_have_acceptor_subkey;
-	knew->kc_endtime = kctx->kc_endtime;
-
-	memcpy(knew->kc_seed, kctx->kc_seed, sizeof(kctx->kc_seed));
-	knew->kc_seq_send = kctx->kc_seq_recv;
-	knew->kc_seq_recv = kctx->kc_seq_send;
-	knew->kc_enctype = kctx->kc_enctype;
-
-	if (rawobj_dup(&knew->kc_mech_used, &kctx->kc_mech_used))
-		goto out_err;
-
-	if (keyblock_dup(&knew->kc_keye, &kctx->kc_keye))
-		goto out_err;
-	if (keyblock_dup(&knew->kc_keyi, &kctx->kc_keyi))
-		goto out_err;
-	if (keyblock_dup(&knew->kc_keyc, &kctx->kc_keyc))
-		goto out_err;
-	if (krb5_init_keys(knew))
-		goto out_err;
-
-	gctx_new->internal_ctx_id = knew;
-	CDEBUG(D_SEC, "successfully copied reverse context\n");
-	return GSS_S_COMPLETE;
-
-out_err:
-	delete_context_kerberos(knew);
-	OBD_FREE_PTR(knew);
-	return GSS_S_FAILURE;
-}
-
-static
-__u32 gss_inquire_context_kerberos(struct gss_ctx *gctx,
-				   unsigned long  *endtime)
-{
-	struct krb5_ctx *kctx = gctx->internal_ctx_id;
-
-	*endtime = (unsigned long) ((__u32) kctx->kc_endtime);
-	return GSS_S_COMPLETE;
-}
-
-static
-void gss_delete_sec_context_kerberos(void *internal_ctx)
-{
-	struct krb5_ctx *kctx = internal_ctx;
-
-	delete_context_kerberos(kctx);
-	OBD_FREE_PTR(kctx);
-}
-
-static
-void buf_to_sg(struct scatterlist *sg, void *ptr, int len)
-{
-	sg_set_buf(sg, ptr, len);
-}
-
-static
-__u32 krb5_encrypt(struct crypto_blkcipher *tfm,
-		   int decrypt,
-		   void * iv,
-		   void * in,
-		   void * out,
-		   int length)
-{
-	struct blkcipher_desc desc;
-	struct scatterlist    sg;
-	__u8 local_iv[16] = {0};
-	__u32 ret = -EINVAL;
-
-	LASSERT(tfm);
-	desc.tfm  = tfm;
-	desc.info = local_iv;
-	desc.flags= 0;
-
-	if (length % crypto_blkcipher_blocksize(tfm) != 0) {
-		CERROR("output length %d mismatch blocksize %d\n",
-		       length, crypto_blkcipher_blocksize(tfm));
-		goto out;
-	}
-
-	if (crypto_blkcipher_ivsize(tfm) > 16) {
-		CERROR("iv size too large %d\n", crypto_blkcipher_ivsize(tfm));
-		goto out;
-	}
-
-	if (iv)
-		memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
-
-	memcpy(out, in, length);
-	buf_to_sg(&sg, out, length);
-
-	if (decrypt)
-		ret = crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, length);
-	else
-		ret = crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, length);
-
-out:
-	return(ret);
-}
-
-
-static inline
-int krb5_digest_hmac(struct crypto_hash *tfm,
-		     rawobj_t *key,
-		     struct krb5_header *khdr,
-		     int msgcnt, rawobj_t *msgs,
-		     int iovcnt, lnet_kiov_t *iovs,
-		     rawobj_t *cksum)
-{
-	struct hash_desc   desc;
-	struct scatterlist sg[1];
-	int		i;
-
-	crypto_hash_setkey(tfm, key->data, key->len);
-	desc.tfm  = tfm;
-	desc.flags= 0;
-
-	crypto_hash_init(&desc);
-
-	for (i = 0; i < msgcnt; i++) {
-		if (msgs[i].len == 0)
-			continue;
-		buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len);
-		crypto_hash_update(&desc, sg, msgs[i].len);
-	}
-
-	for (i = 0; i < iovcnt; i++) {
-		if (iovs[i].kiov_len == 0)
-			continue;
-
-		sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
-			    iovs[i].kiov_offset);
-		crypto_hash_update(&desc, sg, iovs[i].kiov_len);
-	}
-
-	if (khdr) {
-		buf_to_sg(sg, (char *) khdr, sizeof(*khdr));
-		crypto_hash_update(&desc, sg, sizeof(*khdr));
-	}
-
-	return crypto_hash_final(&desc, cksum->data);
-}
-
-
-static inline
-int krb5_digest_norm(struct crypto_hash *tfm,
-		     struct krb5_keyblock *kb,
-		     struct krb5_header *khdr,
-		     int msgcnt, rawobj_t *msgs,
-		     int iovcnt, lnet_kiov_t *iovs,
-		     rawobj_t *cksum)
-{
-	struct hash_desc   desc;
-	struct scatterlist sg[1];
-	int		i;
-
-	LASSERT(kb->kb_tfm);
-	desc.tfm  = tfm;
-	desc.flags= 0;
-
-	crypto_hash_init(&desc);
-
-	for (i = 0; i < msgcnt; i++) {
-		if (msgs[i].len == 0)
-			continue;
-		buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len);
-		crypto_hash_update(&desc, sg, msgs[i].len);
-	}
-
-	for (i = 0; i < iovcnt; i++) {
-		if (iovs[i].kiov_len == 0)
-			continue;
-
-		sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
-			    iovs[i].kiov_offset);
-		crypto_hash_update(&desc, sg, iovs[i].kiov_len);
-	}
-
-	if (khdr) {
-		buf_to_sg(sg, (char *) khdr, sizeof(*khdr));
-		crypto_hash_update(&desc, sg, sizeof(*khdr));
-	}
-
-	crypto_hash_final(&desc, cksum->data);
-
-	return krb5_encrypt(kb->kb_tfm, 0, NULL, cksum->data,
-			    cksum->data, cksum->len);
-}
-
-/*
- * compute (keyed/keyless) checksum against the plain text which appended
- * with krb5 wire token header.
- */
-static
-__s32 krb5_make_checksum(__u32 enctype,
-			 struct krb5_keyblock *kb,
-			 struct krb5_header *khdr,
-			 int msgcnt, rawobj_t *msgs,
-			 int iovcnt, lnet_kiov_t *iovs,
-			 rawobj_t *cksum)
-{
-	struct krb5_enctype   *ke = &enctypes[enctype];
-	struct crypto_hash *tfm;
-	__u32		  code = GSS_S_FAILURE;
-	int		    rc;
-
-	tfm = ll_crypto_alloc_hash(ke->ke_hash_name, 0, 0);
-	if (!tfm) {
-		CERROR("failed to alloc TFM: %s\n", ke->ke_hash_name);
-		return GSS_S_FAILURE;
-	}
-
-	cksum->len = crypto_hash_digestsize(tfm);
-	OBD_ALLOC_LARGE(cksum->data, cksum->len);
-	if (!cksum->data) {
-		cksum->len = 0;
-		goto out_tfm;
-	}
-
-	if (ke->ke_hash_hmac)
-		rc = krb5_digest_hmac(tfm, &kb->kb_key,
-				      khdr, msgcnt, msgs, iovcnt, iovs, cksum);
-	else
-		rc = krb5_digest_norm(tfm, kb,
-				      khdr, msgcnt, msgs, iovcnt, iovs, cksum);
-
-	if (rc == 0)
-		code = GSS_S_COMPLETE;
-out_tfm:
-	crypto_free_hash(tfm);
-	return code;
-}
-
-static void fill_krb5_header(struct krb5_ctx *kctx,
-			     struct krb5_header *khdr,
-			     int privacy)
-{
-	unsigned char acceptor_flag;
-
-	acceptor_flag = kctx->kc_initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
-
-	if (privacy) {
-		khdr->kh_tok_id = cpu_to_be16(KG_TOK_WRAP_MSG);
-		khdr->kh_flags = acceptor_flag | FLAG_WRAP_CONFIDENTIAL;
-		khdr->kh_ec = cpu_to_be16(0);
-		khdr->kh_rrc = cpu_to_be16(0);
-	} else {
-		khdr->kh_tok_id = cpu_to_be16(KG_TOK_MIC_MSG);
-		khdr->kh_flags = acceptor_flag;
-		khdr->kh_ec = cpu_to_be16(0xffff);
-		khdr->kh_rrc = cpu_to_be16(0xffff);
-	}
-
-	khdr->kh_filler = 0xff;
-	spin_lock(&krb5_seq_lock);
-	khdr->kh_seq = cpu_to_be64(kctx->kc_seq_send++);
-	spin_unlock(&krb5_seq_lock);
-}
-
-static __u32 verify_krb5_header(struct krb5_ctx *kctx,
-				struct krb5_header *khdr,
-				int privacy)
-{
-	unsigned char acceptor_flag;
-	__u16	 tok_id, ec_rrc;
-
-	acceptor_flag = kctx->kc_initiate ? FLAG_SENDER_IS_ACCEPTOR : 0;
-
-	if (privacy) {
-		tok_id = KG_TOK_WRAP_MSG;
-		ec_rrc = 0x0;
-	} else {
-		tok_id = KG_TOK_MIC_MSG;
-		ec_rrc = 0xffff;
-	}
-
-	/* sanity checks */
-	if (be16_to_cpu(khdr->kh_tok_id) != tok_id) {
-		CERROR("bad token id\n");
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-	if ((khdr->kh_flags & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
-		CERROR("bad direction flag\n");
-		return GSS_S_BAD_SIG;
-	}
-	if (privacy && (khdr->kh_flags & FLAG_WRAP_CONFIDENTIAL) == 0) {
-		CERROR("missing confidential flag\n");
-		return GSS_S_BAD_SIG;
-	}
-	if (khdr->kh_filler != 0xff) {
-		CERROR("bad filler\n");
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-	if (be16_to_cpu(khdr->kh_ec) != ec_rrc ||
-	    be16_to_cpu(khdr->kh_rrc) != ec_rrc) {
-		CERROR("bad EC or RRC\n");
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_get_mic_kerberos(struct gss_ctx *gctx,
-			   int msgcnt,
-			   rawobj_t *msgs,
-			   int iovcnt,
-			   lnet_kiov_t *iovs,
-			   rawobj_t *token)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-
-	/* fill krb5 header */
-	LASSERT(token->len >= sizeof(*khdr));
-	khdr = (struct krb5_header *) token->data;
-	fill_krb5_header(kctx, khdr, 0);
-
-	/* checksum */
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
-			       khdr, msgcnt, msgs, iovcnt, iovs, &cksum))
-		return GSS_S_FAILURE;
-
-	LASSERT(cksum.len >= ke->ke_hash_size);
-	LASSERT(token->len >= sizeof(*khdr) + ke->ke_hash_size);
-	memcpy(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
-	       ke->ke_hash_size);
-
-	token->len = sizeof(*khdr) + ke->ke_hash_size;
-	rawobj_free(&cksum);
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_verify_mic_kerberos(struct gss_ctx *gctx,
-			      int msgcnt,
-			      rawobj_t *msgs,
-			      int iovcnt,
-			      lnet_kiov_t *iovs,
-			      rawobj_t *token)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-	__u32		major;
-
-	if (token->len < sizeof(*khdr)) {
-		CERROR("short signature: %u\n", token->len);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	khdr = (struct krb5_header *) token->data;
-
-	major = verify_krb5_header(kctx, khdr, 0);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("bad krb5 header\n");
-		return major;
-	}
-
-	if (token->len < sizeof(*khdr) + ke->ke_hash_size) {
-		CERROR("short signature: %u, require %d\n",
-		       token->len, (int) sizeof(*khdr) + ke->ke_hash_size);
-		return GSS_S_FAILURE;
-	}
-
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
-			       khdr, msgcnt, msgs, iovcnt, iovs, &cksum)) {
-		CERROR("failed to make checksum\n");
-		return GSS_S_FAILURE;
-	}
-
-	LASSERT(cksum.len >= ke->ke_hash_size);
-	if (memcmp(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
-		   ke->ke_hash_size)) {
-		CERROR("checksum mismatch\n");
-		rawobj_free(&cksum);
-		return GSS_S_BAD_SIG;
-	}
-
-	rawobj_free(&cksum);
-	return GSS_S_COMPLETE;
-}
-
-static
-int add_padding(rawobj_t *msg, int msg_buflen, int blocksize)
-{
-	int padding;
-
-	padding = (blocksize - (msg->len & (blocksize - 1))) &
-		  (blocksize - 1);
-	if (!padding)
-		return 0;
-
-	if (msg->len + padding > msg_buflen) {
-		CERROR("bufsize %u too small: datalen %u, padding %u\n",
-			msg_buflen, msg->len, padding);
-		return -EINVAL;
-	}
-
-	memset(msg->data + msg->len, padding, padding);
-	msg->len += padding;
-	return 0;
-}
-
-static
-int krb5_encrypt_rawobjs(struct crypto_blkcipher *tfm,
-			 int mode_ecb,
-			 int inobj_cnt,
-			 rawobj_t *inobjs,
-			 rawobj_t *outobj,
-			 int enc)
-{
-	struct blkcipher_desc desc;
-	struct scatterlist    src, dst;
-	__u8		  local_iv[16] = {0}, *buf;
-	__u32		 datalen = 0;
-	int		   i, rc;
-
-	buf = outobj->data;
-	desc.tfm  = tfm;
-	desc.info = local_iv;
-	desc.flags = 0;
-
-	for (i = 0; i < inobj_cnt; i++) {
-		LASSERT(buf + inobjs[i].len <= outobj->data + outobj->len);
-
-		buf_to_sg(&src, inobjs[i].data, inobjs[i].len);
-		buf_to_sg(&dst, buf, outobj->len - datalen);
-
-		if (mode_ecb) {
-			if (enc)
-				rc = crypto_blkcipher_encrypt(
-					&desc, &dst, &src, src.length);
-			else
-				rc = crypto_blkcipher_decrypt(
-					&desc, &dst, &src, src.length);
-		} else {
-			if (enc)
-				rc = crypto_blkcipher_encrypt_iv(
-					&desc, &dst, &src, src.length);
-			else
-				rc = crypto_blkcipher_decrypt_iv(
-					&desc, &dst, &src, src.length);
-		}
-
-		if (rc) {
-			CERROR("encrypt error %d\n", rc);
-			return rc;
-		}
-
-		datalen += inobjs[i].len;
-		buf += inobjs[i].len;
-	}
-
-	outobj->len = datalen;
-	return 0;
-}
-
-/*
- * if adj_nob != 0, we adjust desc->bd_nob to the actual cipher text size.
- */
-static
-int krb5_encrypt_bulk(struct crypto_blkcipher *tfm,
-		      struct krb5_header *khdr,
-		      char *confounder,
-		      struct ptlrpc_bulk_desc *desc,
-		      rawobj_t *cipher,
-		      int adj_nob)
-{
-	struct blkcipher_desc   ciph_desc;
-	__u8		    local_iv[16] = {0};
-	struct scatterlist      src, dst;
-	int		     blocksize, i, rc, nob = 0;
-
-	LASSERT(desc->bd_iov_count);
-	LASSERT(desc->bd_enc_iov);
-
-	blocksize = crypto_blkcipher_blocksize(tfm);
-	LASSERT(blocksize > 1);
-	LASSERT(cipher->len == blocksize + sizeof(*khdr));
-
-	ciph_desc.tfm  = tfm;
-	ciph_desc.info = local_iv;
-	ciph_desc.flags = 0;
-
-	/* encrypt confounder */
-	buf_to_sg(&src, confounder, blocksize);
-	buf_to_sg(&dst, cipher->data, blocksize);
-
-	rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src, blocksize);
-	if (rc) {
-		CERROR("error to encrypt confounder: %d\n", rc);
-		return rc;
-	}
-
-	/* encrypt clear pages */
-	for (i = 0; i < desc->bd_iov_count; i++) {
-		sg_set_page(&src, desc->bd_iov[i].kiov_page,
-			    (desc->bd_iov[i].kiov_len + blocksize - 1) &
-			    (~(blocksize - 1)),
-			    desc->bd_iov[i].kiov_offset);
-		if (adj_nob)
-			nob += src.length;
-		sg_set_page(&dst, desc->bd_enc_iov[i].kiov_page, src.length,
-			    src.offset);
-
-		desc->bd_enc_iov[i].kiov_offset = dst.offset;
-		desc->bd_enc_iov[i].kiov_len = dst.length;
-
-		rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src,
-						    src.length);
-		if (rc) {
-			CERROR("error to encrypt page: %d\n", rc);
-			return rc;
-		}
-	}
-
-	/* encrypt krb5 header */
-	buf_to_sg(&src, khdr, sizeof(*khdr));
-	buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr));
-
-	rc = crypto_blkcipher_encrypt_iv(&ciph_desc,
-					    &dst, &src, sizeof(*khdr));
-	if (rc) {
-		CERROR("error to encrypt krb5 header: %d\n", rc);
-		return rc;
-	}
-
-	if (adj_nob)
-		desc->bd_nob = nob;
-
-	return 0;
-}
-
-/*
- * desc->bd_nob_transferred is the size of cipher text received.
- * desc->bd_nob is the target size of plain text supposed to be.
- *
- * if adj_nob != 0, we adjust each page's kiov_len to the actual
- * plain text size.
- * - for client read: we don't know data size for each page, so
- *   bd_iov[]->kiov_len is set to PAGE_SIZE, but actual data received might
- *   be smaller, so we need to adjust it according to bd_enc_iov[]->kiov_len.
- *   this means we DO NOT support the situation that server send an odd size
- *   data in a page which is not the last one.
- * - for server write: we knows exactly data size for each page being expected,
- *   thus kiov_len is accurate already, so we should not adjust it at all.
- *   and bd_enc_iov[]->kiov_len should be round_up(bd_iov[]->kiov_len) which
- *   should have been done by prep_bulk().
- */
-static
-int krb5_decrypt_bulk(struct crypto_blkcipher *tfm,
-		      struct krb5_header *khdr,
-		      struct ptlrpc_bulk_desc *desc,
-		      rawobj_t *cipher,
-		      rawobj_t *plain,
-		      int adj_nob)
-{
-	struct blkcipher_desc   ciph_desc;
-	__u8		    local_iv[16] = {0};
-	struct scatterlist      src, dst;
-	int		     ct_nob = 0, pt_nob = 0;
-	int		     blocksize, i, rc;
-
-	LASSERT(desc->bd_iov_count);
-	LASSERT(desc->bd_enc_iov);
-	LASSERT(desc->bd_nob_transferred);
-
-	blocksize = crypto_blkcipher_blocksize(tfm);
-	LASSERT(blocksize > 1);
-	LASSERT(cipher->len == blocksize + sizeof(*khdr));
-
-	ciph_desc.tfm  = tfm;
-	ciph_desc.info = local_iv;
-	ciph_desc.flags = 0;
-
-	if (desc->bd_nob_transferred % blocksize) {
-		CERROR("odd transferred nob: %d\n", desc->bd_nob_transferred);
-		return -EPROTO;
-	}
-
-	/* decrypt head (confounder) */
-	buf_to_sg(&src, cipher->data, blocksize);
-	buf_to_sg(&dst, plain->data, blocksize);
-
-	rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src, blocksize);
-	if (rc) {
-		CERROR("error to decrypt confounder: %d\n", rc);
-		return rc;
-	}
-
-	for (i = 0; i < desc->bd_iov_count && ct_nob < desc->bd_nob_transferred;
-	     i++) {
-		if (desc->bd_enc_iov[i].kiov_offset % blocksize != 0 ||
-		    desc->bd_enc_iov[i].kiov_len % blocksize != 0) {
-			CERROR("page %d: odd offset %u len %u, blocksize %d\n",
-			       i, desc->bd_enc_iov[i].kiov_offset,
-			       desc->bd_enc_iov[i].kiov_len, blocksize);
-			return -EFAULT;
-		}
-
-		if (adj_nob) {
-			if (ct_nob + desc->bd_enc_iov[i].kiov_len >
-			    desc->bd_nob_transferred)
-				desc->bd_enc_iov[i].kiov_len =
-					desc->bd_nob_transferred - ct_nob;
-
-			desc->bd_iov[i].kiov_len = desc->bd_enc_iov[i].kiov_len;
-			if (pt_nob + desc->bd_enc_iov[i].kiov_len >desc->bd_nob)
-				desc->bd_iov[i].kiov_len = desc->bd_nob -pt_nob;
-		} else {
-			/* this should be guaranteed by LNET */
-			LASSERT(ct_nob + desc->bd_enc_iov[i].kiov_len <=
-				desc->bd_nob_transferred);
-			LASSERT(desc->bd_iov[i].kiov_len <=
-				desc->bd_enc_iov[i].kiov_len);
-		}
-
-		if (desc->bd_enc_iov[i].kiov_len == 0)
-			continue;
-
-		sg_set_page(&src, desc->bd_enc_iov[i].kiov_page,
-			    desc->bd_enc_iov[i].kiov_len,
-			    desc->bd_enc_iov[i].kiov_offset);
-		dst = src;
-		if (desc->bd_iov[i].kiov_len % blocksize == 0)
-			sg_assign_page(&dst, desc->bd_iov[i].kiov_page);
-
-		rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src,
-						    src.length);
-		if (rc) {
-			CERROR("error to decrypt page: %d\n", rc);
-			return rc;
-		}
-
-		if (desc->bd_iov[i].kiov_len % blocksize != 0) {
-			memcpy(page_address(desc->bd_iov[i].kiov_page) +
-			       desc->bd_iov[i].kiov_offset,
-			       page_address(desc->bd_enc_iov[i].kiov_page) +
-			       desc->bd_iov[i].kiov_offset,
-			       desc->bd_iov[i].kiov_len);
-		}
-
-		ct_nob += desc->bd_enc_iov[i].kiov_len;
-		pt_nob += desc->bd_iov[i].kiov_len;
-	}
-
-	if (unlikely(ct_nob != desc->bd_nob_transferred)) {
-		CERROR("%d cipher text transferred but only %d decrypted\n",
-		       desc->bd_nob_transferred, ct_nob);
-		return -EFAULT;
-	}
-
-	if (unlikely(!adj_nob && pt_nob != desc->bd_nob)) {
-		CERROR("%d plain text expected but only %d received\n",
-		       desc->bd_nob, pt_nob);
-		return -EFAULT;
-	}
-
-	/* if needed, clear up the rest unused iovs */
-	if (adj_nob)
-		while (i < desc->bd_iov_count)
-			desc->bd_iov[i++].kiov_len = 0;
-
-	/* decrypt tail (krb5 header) */
-	buf_to_sg(&src, cipher->data + blocksize, sizeof(*khdr));
-	buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr));
-
-	rc = crypto_blkcipher_decrypt_iv(&ciph_desc,
-					    &dst, &src, sizeof(*khdr));
-	if (rc) {
-		CERROR("error to decrypt tail: %d\n", rc);
-		return rc;
-	}
-
-	if (memcmp(cipher->data + blocksize, khdr, sizeof(*khdr))) {
-		CERROR("krb5 header doesn't match\n");
-		return -EACCES;
-	}
-
-	return 0;
-}
-
-static
-__u32 gss_wrap_kerberos(struct gss_ctx *gctx,
-			rawobj_t *gsshdr,
-			rawobj_t *msg,
-			int msg_buflen,
-			rawobj_t *token)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	int		  blocksize;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-	rawobj_t	     data_desc[3], cipher;
-	__u8		 conf[GSS_MAX_CIPHER_BLOCK];
-	int		  rc = 0;
-
-	LASSERT(ke);
-	LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK);
-	LASSERT(kctx->kc_keye.kb_tfm == NULL ||
-		ke->ke_conf_size >=
-		crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm));
-
-	/*
-	 * final token format:
-	 * ---------------------------------------------------
-	 * | krb5 header | cipher text | checksum (16 bytes) |
-	 * ---------------------------------------------------
-	 */
-
-	/* fill krb5 header */
-	LASSERT(token->len >= sizeof(*khdr));
-	khdr = (struct krb5_header *) token->data;
-	fill_krb5_header(kctx, khdr, 1);
-
-	/* generate confounder */
-	cfs_get_random_bytes(conf, ke->ke_conf_size);
-
-	/* get encryption blocksize. note kc_keye might not associated with
-	 * a tfm, currently only for arcfour-hmac */
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		LASSERT(kctx->kc_keye.kb_tfm == NULL);
-		blocksize = 1;
-	} else {
-		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
-	}
-	LASSERT(blocksize <= ke->ke_conf_size);
-
-	/* padding the message */
-	if (add_padding(msg, msg_buflen, blocksize))
-		return GSS_S_FAILURE;
-
-	/*
-	 * clear text layout for checksum:
-	 * ------------------------------------------------------
-	 * | confounder | gss header | clear msgs | krb5 header |
-	 * ------------------------------------------------------
-	 */
-	data_desc[0].data = conf;
-	data_desc[0].len = ke->ke_conf_size;
-	data_desc[1].data = gsshdr->data;
-	data_desc[1].len = gsshdr->len;
-	data_desc[2].data = msg->data;
-	data_desc[2].len = msg->len;
-
-	/* compute checksum */
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
-			       khdr, 3, data_desc, 0, NULL, &cksum))
-		return GSS_S_FAILURE;
-	LASSERT(cksum.len >= ke->ke_hash_size);
-
-	/*
-	 * clear text layout for encryption:
-	 * -----------------------------------------
-	 * | confounder | clear msgs | krb5 header |
-	 * -----------------------------------------
-	 */
-	data_desc[0].data = conf;
-	data_desc[0].len = ke->ke_conf_size;
-	data_desc[1].data = msg->data;
-	data_desc[1].len = msg->len;
-	data_desc[2].data = (__u8 *) khdr;
-	data_desc[2].len = sizeof(*khdr);
-
-	/* cipher text will be directly inplace */
-	cipher.data = (__u8 *) (khdr + 1);
-	cipher.len = token->len - sizeof(*khdr);
-	LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr));
-
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		rawobj_t		 arc4_keye;
-		struct crypto_blkcipher *arc4_tfm;
-
-		if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
-				       NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
-			CERROR("failed to obtain arc4 enc key\n");
-			GOTO(arc4_out, rc = -EACCES);
-		}
-
-		arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
-		if (IS_ERR(arc4_tfm)) {
-			CERROR("failed to alloc tfm arc4 in ECB mode\n");
-			GOTO(arc4_out_key, rc = -EACCES);
-		}
-
-		if (crypto_blkcipher_setkey(arc4_tfm, arc4_keye.data,
-					       arc4_keye.len)) {
-			CERROR("failed to set arc4 key, len %d\n",
-			       arc4_keye.len);
-			GOTO(arc4_out_tfm, rc = -EACCES);
-		}
-
-		rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
-					  3, data_desc, &cipher, 1);
-arc4_out_tfm:
-		crypto_free_blkcipher(arc4_tfm);
-arc4_out_key:
-		rawobj_free(&arc4_keye);
-arc4_out:
-		do {} while (0); /* just to avoid compile warning */
-	} else {
-		rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0,
-					  3, data_desc, &cipher, 1);
-	}
-
-	if (rc != 0) {
-		rawobj_free(&cksum);
-		return GSS_S_FAILURE;
-	}
-
-	/* fill in checksum */
-	LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
-	memcpy((char *)(khdr + 1) + cipher.len,
-	       cksum.data + cksum.len - ke->ke_hash_size,
-	       ke->ke_hash_size);
-	rawobj_free(&cksum);
-
-	/* final token length */
-	token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_prep_bulk_kerberos(struct gss_ctx *gctx,
-			     struct ptlrpc_bulk_desc *desc)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	int		  blocksize, i;
-
-	LASSERT(desc->bd_iov_count);
-	LASSERT(desc->bd_enc_iov);
-	LASSERT(kctx->kc_keye.kb_tfm);
-
-	blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
-
-	for (i = 0; i < desc->bd_iov_count; i++) {
-		LASSERT(desc->bd_enc_iov[i].kiov_page);
-		/*
-		 * offset should always start at page boundary of either
-		 * client or server side.
-		 */
-		if (desc->bd_iov[i].kiov_offset & blocksize) {
-			CERROR("odd offset %d in page %d\n",
-			       desc->bd_iov[i].kiov_offset, i);
-			return GSS_S_FAILURE;
-		}
-
-		desc->bd_enc_iov[i].kiov_offset = desc->bd_iov[i].kiov_offset;
-		desc->bd_enc_iov[i].kiov_len = (desc->bd_iov[i].kiov_len +
-						blocksize - 1) & (~(blocksize - 1));
-	}
-
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx,
-			     struct ptlrpc_bulk_desc *desc,
-			     rawobj_t *token, int adj_nob)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	int		  blocksize;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-	rawobj_t	     data_desc[1], cipher;
-	__u8		 conf[GSS_MAX_CIPHER_BLOCK];
-	int		  rc = 0;
-
-	LASSERT(ke);
-	LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK);
-
-	/*
-	 * final token format:
-	 * --------------------------------------------------
-	 * | krb5 header | head/tail cipher text | checksum |
-	 * --------------------------------------------------
-	 */
-
-	/* fill krb5 header */
-	LASSERT(token->len >= sizeof(*khdr));
-	khdr = (struct krb5_header *) token->data;
-	fill_krb5_header(kctx, khdr, 1);
-
-	/* generate confounder */
-	cfs_get_random_bytes(conf, ke->ke_conf_size);
-
-	/* get encryption blocksize. note kc_keye might not associated with
-	 * a tfm, currently only for arcfour-hmac */
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		LASSERT(kctx->kc_keye.kb_tfm == NULL);
-		blocksize = 1;
-	} else {
-		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
-	}
-
-	/*
-	 * we assume the size of krb5_header (16 bytes) must be n * blocksize.
-	 * the bulk token size would be exactly (sizeof(krb5_header) +
-	 * blocksize + sizeof(krb5_header) + hashsize)
-	 */
-	LASSERT(blocksize <= ke->ke_conf_size);
-	LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0);
-	LASSERT(token->len >= sizeof(*khdr) + blocksize + sizeof(*khdr) + 16);
-
-	/*
-	 * clear text layout for checksum:
-	 * ------------------------------------------
-	 * | confounder | clear pages | krb5 header |
-	 * ------------------------------------------
-	 */
-	data_desc[0].data = conf;
-	data_desc[0].len = ke->ke_conf_size;
-
-	/* compute checksum */
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
-			       khdr, 1, data_desc,
-			       desc->bd_iov_count, desc->bd_iov,
-			       &cksum))
-		return GSS_S_FAILURE;
-	LASSERT(cksum.len >= ke->ke_hash_size);
-
-	/*
-	 * clear text layout for encryption:
-	 * ------------------------------------------
-	 * | confounder | clear pages | krb5 header |
-	 * ------------------------------------------
-	 *	|	      |	     |
-	 *	----------  (cipher pages)   |
-	 * result token:   |		   |
-	 * -------------------------------------------
-	 * | krb5 header | cipher text | cipher text |
-	 * -------------------------------------------
-	 */
-	data_desc[0].data = conf;
-	data_desc[0].len = ke->ke_conf_size;
-
-	cipher.data = (__u8 *) (khdr + 1);
-	cipher.len = blocksize + sizeof(*khdr);
-
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		LBUG();
-		rc = 0;
-	} else {
-		rc = krb5_encrypt_bulk(kctx->kc_keye.kb_tfm, khdr,
-				       conf, desc, &cipher, adj_nob);
-	}
-
-	if (rc != 0) {
-		rawobj_free(&cksum);
-		return GSS_S_FAILURE;
-	}
-
-	/* fill in checksum */
-	LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
-	memcpy((char *)(khdr + 1) + cipher.len,
-	       cksum.data + cksum.len - ke->ke_hash_size,
-	       ke->ke_hash_size);
-	rawobj_free(&cksum);
-
-	/* final token length */
-	token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
-	return GSS_S_COMPLETE;
-}
-
-static
-__u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
-			  rawobj_t	*gsshdr,
-			  rawobj_t	*token,
-			  rawobj_t	*msg)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	unsigned char       *tmpbuf;
-	int		  blocksize, bodysize;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-	rawobj_t	     cipher_in, plain_out;
-	rawobj_t	     hash_objs[3];
-	int		  rc = 0;
-	__u32		major;
-
-	LASSERT(ke);
-
-	if (token->len < sizeof(*khdr)) {
-		CERROR("short signature: %u\n", token->len);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	khdr = (struct krb5_header *) token->data;
-
-	major = verify_krb5_header(kctx, khdr, 1);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("bad krb5 header\n");
-		return major;
-	}
-
-	/* block size */
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		LASSERT(kctx->kc_keye.kb_tfm == NULL);
-		blocksize = 1;
-	} else {
-		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
-	}
-
-	/* expected token layout:
-	 * ----------------------------------------
-	 * | krb5 header | cipher text | checksum |
-	 * ----------------------------------------
-	 */
-	bodysize = token->len - sizeof(*khdr) - ke->ke_hash_size;
-
-	if (bodysize % blocksize) {
-		CERROR("odd bodysize %d\n", bodysize);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	if (bodysize <= ke->ke_conf_size + sizeof(*khdr)) {
-		CERROR("incomplete token: bodysize %d\n", bodysize);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	if (msg->len < bodysize - ke->ke_conf_size - sizeof(*khdr)) {
-		CERROR("buffer too small: %u, require %d\n",
-		       msg->len, bodysize - ke->ke_conf_size);
-		return GSS_S_FAILURE;
-	}
-
-	/* decrypting */
-	OBD_ALLOC_LARGE(tmpbuf, bodysize);
-	if (!tmpbuf)
-		return GSS_S_FAILURE;
-
-	major = GSS_S_FAILURE;
-
-	cipher_in.data = (__u8 *) (khdr + 1);
-	cipher_in.len = bodysize;
-	plain_out.data = tmpbuf;
-	plain_out.len = bodysize;
-
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		rawobj_t		 arc4_keye;
-		struct crypto_blkcipher *arc4_tfm;
-
-		cksum.data = token->data + token->len - ke->ke_hash_size;
-		cksum.len = ke->ke_hash_size;
-
-		if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
-				       NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
-			CERROR("failed to obtain arc4 enc key\n");
-			GOTO(arc4_out, rc = -EACCES);
-		}
-
-		arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
-		if (IS_ERR(arc4_tfm)) {
-			CERROR("failed to alloc tfm arc4 in ECB mode\n");
-			GOTO(arc4_out_key, rc = -EACCES);
-		}
-
-		if (crypto_blkcipher_setkey(arc4_tfm,
-					 arc4_keye.data, arc4_keye.len)) {
-			CERROR("failed to set arc4 key, len %d\n",
-			       arc4_keye.len);
-			GOTO(arc4_out_tfm, rc = -EACCES);
-		}
-
-		rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
-					  1, &cipher_in, &plain_out, 0);
-arc4_out_tfm:
-		crypto_free_blkcipher(arc4_tfm);
-arc4_out_key:
-		rawobj_free(&arc4_keye);
-arc4_out:
-		cksum = RAWOBJ_EMPTY;
-	} else {
-		rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0,
-					  1, &cipher_in, &plain_out, 0);
-	}
-
-	if (rc != 0) {
-		CERROR("error decrypt\n");
-		goto out_free;
-	}
-	LASSERT(plain_out.len == bodysize);
-
-	/* expected clear text layout:
-	 * -----------------------------------------
-	 * | confounder | clear msgs | krb5 header |
-	 * -----------------------------------------
-	 */
-
-	/* verify krb5 header in token is not modified */
-	if (memcmp(khdr, plain_out.data + plain_out.len - sizeof(*khdr),
-		   sizeof(*khdr))) {
-		CERROR("decrypted krb5 header mismatch\n");
-		goto out_free;
-	}
-
-	/* verify checksum, compose clear text as layout:
-	 * ------------------------------------------------------
-	 * | confounder | gss header | clear msgs | krb5 header |
-	 * ------------------------------------------------------
-	 */
-	hash_objs[0].len = ke->ke_conf_size;
-	hash_objs[0].data = plain_out.data;
-	hash_objs[1].len = gsshdr->len;
-	hash_objs[1].data = gsshdr->data;
-	hash_objs[2].len = plain_out.len - ke->ke_conf_size - sizeof(*khdr);
-	hash_objs[2].data = plain_out.data + ke->ke_conf_size;
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
-			       khdr, 3, hash_objs, 0, NULL, &cksum))
-		goto out_free;
-
-	LASSERT(cksum.len >= ke->ke_hash_size);
-	if (memcmp((char *)(khdr + 1) + bodysize,
-		   cksum.data + cksum.len - ke->ke_hash_size,
-		   ke->ke_hash_size)) {
-		CERROR("checksum mismatch\n");
-		goto out_free;
-	}
-
-	msg->len =  bodysize - ke->ke_conf_size - sizeof(*khdr);
-	memcpy(msg->data, tmpbuf + ke->ke_conf_size, msg->len);
-
-	major = GSS_S_COMPLETE;
-out_free:
-	OBD_FREE_LARGE(tmpbuf, bodysize);
-	rawobj_free(&cksum);
-	return major;
-}
-
-static
-__u32 gss_unwrap_bulk_kerberos(struct gss_ctx *gctx,
-			       struct ptlrpc_bulk_desc *desc,
-			       rawobj_t *token, int adj_nob)
-{
-	struct krb5_ctx     *kctx = gctx->internal_ctx_id;
-	struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
-	struct krb5_header  *khdr;
-	int		  blocksize;
-	rawobj_t	     cksum = RAWOBJ_EMPTY;
-	rawobj_t	     cipher, plain;
-	rawobj_t	     data_desc[1];
-	int		  rc;
-	__u32		major;
-
-	LASSERT(ke);
-
-	if (token->len < sizeof(*khdr)) {
-		CERROR("short signature: %u\n", token->len);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	khdr = (struct krb5_header *) token->data;
-
-	major = verify_krb5_header(kctx, khdr, 1);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("bad krb5 header\n");
-		return major;
-	}
-
-	/* block size */
-	if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
-		LASSERT(kctx->kc_keye.kb_tfm == NULL);
-		blocksize = 1;
-		LBUG();
-	} else {
-		LASSERT(kctx->kc_keye.kb_tfm);
-		blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
-	}
-	LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0);
-
-	/*
-	 * token format is expected as:
-	 * -----------------------------------------------
-	 * | krb5 header | head/tail cipher text | cksum |
-	 * -----------------------------------------------
-	 */
-	if (token->len < sizeof(*khdr) + blocksize + sizeof(*khdr) +
-			 ke->ke_hash_size) {
-		CERROR("short token size: %u\n", token->len);
-		return GSS_S_DEFECTIVE_TOKEN;
-	}
-
-	cipher.data = (__u8 *) (khdr + 1);
-	cipher.len = blocksize + sizeof(*khdr);
-	plain.data = cipher.data;
-	plain.len = cipher.len;
-
-	rc = krb5_decrypt_bulk(kctx->kc_keye.kb_tfm, khdr,
-			       desc, &cipher, &plain, adj_nob);
-	if (rc)
-		return GSS_S_DEFECTIVE_TOKEN;
-
-	/*
-	 * verify checksum, compose clear text as layout:
-	 * ------------------------------------------
-	 * | confounder | clear pages | krb5 header |
-	 * ------------------------------------------
-	 */
-	data_desc[0].data = plain.data;
-	data_desc[0].len = blocksize;
-
-	if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
-			       khdr, 1, data_desc,
-			       desc->bd_iov_count, desc->bd_iov,
-			       &cksum))
-		return GSS_S_FAILURE;
-	LASSERT(cksum.len >= ke->ke_hash_size);
-
-	if (memcmp(plain.data + blocksize + sizeof(*khdr),
-		   cksum.data + cksum.len - ke->ke_hash_size,
-		   ke->ke_hash_size)) {
-		CERROR("checksum mismatch\n");
-		rawobj_free(&cksum);
-		return GSS_S_BAD_SIG;
-	}
-
-	rawobj_free(&cksum);
-	return GSS_S_COMPLETE;
-}
-
-int gss_display_kerberos(struct gss_ctx	*ctx,
-			 char		  *buf,
-			 int		    bufsize)
-{
-	struct krb5_ctx    *kctx = ctx->internal_ctx_id;
-	int		 written;
-
-	written = snprintf(buf, bufsize, "krb5 (%s)",
-			   enctype2str(kctx->kc_enctype));
-	return written;
-}
-
-static struct gss_api_ops gss_kerberos_ops = {
-	.gss_import_sec_context     = gss_import_sec_context_kerberos,
-	.gss_copy_reverse_context   = gss_copy_reverse_context_kerberos,
-	.gss_inquire_context	= gss_inquire_context_kerberos,
-	.gss_get_mic		= gss_get_mic_kerberos,
-	.gss_verify_mic	     = gss_verify_mic_kerberos,
-	.gss_wrap		   = gss_wrap_kerberos,
-	.gss_unwrap		 = gss_unwrap_kerberos,
-	.gss_prep_bulk	      = gss_prep_bulk_kerberos,
-	.gss_wrap_bulk	      = gss_wrap_bulk_kerberos,
-	.gss_unwrap_bulk	    = gss_unwrap_bulk_kerberos,
-	.gss_delete_sec_context     = gss_delete_sec_context_kerberos,
-	.gss_display		= gss_display_kerberos,
-};
-
-static struct subflavor_desc gss_kerberos_sfs[] = {
-	{
-		.sf_subflavor   = SPTLRPC_SUBFLVR_KRB5N,
-		.sf_qop	 = 0,
-		.sf_service     = SPTLRPC_SVC_NULL,
-		.sf_name	= "krb5n"
-	},
-	{
-		.sf_subflavor   = SPTLRPC_SUBFLVR_KRB5A,
-		.sf_qop	 = 0,
-		.sf_service     = SPTLRPC_SVC_AUTH,
-		.sf_name	= "krb5a"
-	},
-	{
-		.sf_subflavor   = SPTLRPC_SUBFLVR_KRB5I,
-		.sf_qop	 = 0,
-		.sf_service     = SPTLRPC_SVC_INTG,
-		.sf_name	= "krb5i"
-	},
-	{
-		.sf_subflavor   = SPTLRPC_SUBFLVR_KRB5P,
-		.sf_qop	 = 0,
-		.sf_service     = SPTLRPC_SVC_PRIV,
-		.sf_name	= "krb5p"
-	},
-};
-
-/*
- * currently we leave module owner NULL
- */
-static struct gss_api_mech gss_kerberos_mech = {
-	.gm_owner       = NULL, /*THIS_MODULE, */
-	.gm_name	= "krb5",
-	.gm_oid	 = (rawobj_t)
-				{9, "\052\206\110\206\367\022\001\002\002"},
-	.gm_ops	 = &gss_kerberos_ops,
-	.gm_sf_num      = 4,
-	.gm_sfs	 = gss_kerberos_sfs,
-};
-
-int __init init_kerberos_module(void)
-{
-	int status;
-
-	spin_lock_init(&krb5_seq_lock);
-
-	status = lgss_mech_register(&gss_kerberos_mech);
-	if (status)
-		CERROR("Failed to register kerberos gss mechanism!\n");
-	return status;
-}
-
-void __exit cleanup_kerberos_module(void)
-{
-	lgss_mech_unregister(&gss_kerberos_mech);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,358 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- *  linux/net/sunrpc/gss_mech_switch.c
- *
- *  Copyright (c) 2001 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  J. Bruce Fields   <bfields@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-static LIST_HEAD(registered_mechs);
-static DEFINE_SPINLOCK(registered_mechs_lock);
-
-int lgss_mech_register(struct gss_api_mech *gm)
-{
-	spin_lock(&registered_mechs_lock);
-	list_add(&gm->gm_list, &registered_mechs);
-	spin_unlock(&registered_mechs_lock);
-	CWARN("Register %s mechanism\n", gm->gm_name);
-	return 0;
-}
-
-void lgss_mech_unregister(struct gss_api_mech *gm)
-{
-	spin_lock(&registered_mechs_lock);
-	list_del(&gm->gm_list);
-	spin_unlock(&registered_mechs_lock);
-	CWARN("Unregister %s mechanism\n", gm->gm_name);
-}
-
-
-struct gss_api_mech *lgss_mech_get(struct gss_api_mech *gm)
-{
-	__module_get(gm->gm_owner);
-	return gm;
-}
-
-struct gss_api_mech *lgss_name_to_mech(char *name)
-{
-	struct gss_api_mech *pos, *gm = NULL;
-
-	spin_lock(&registered_mechs_lock);
-	list_for_each_entry(pos, &registered_mechs, gm_list) {
-		if (0 == strcmp(name, pos->gm_name)) {
-			if (!try_module_get(pos->gm_owner))
-				continue;
-			gm = pos;
-			break;
-		}
-	}
-	spin_unlock(&registered_mechs_lock);
-	return gm;
-
-}
-
-static inline
-int mech_supports_subflavor(struct gss_api_mech *gm, __u32 subflavor)
-{
-	int i;
-
-	for (i = 0; i < gm->gm_sf_num; i++) {
-		if (gm->gm_sfs[i].sf_subflavor == subflavor)
-			return 1;
-	}
-	return 0;
-}
-
-struct gss_api_mech *lgss_subflavor_to_mech(__u32 subflavor)
-{
-	struct gss_api_mech *pos, *gm = NULL;
-
-	spin_lock(&registered_mechs_lock);
-	list_for_each_entry(pos, &registered_mechs, gm_list) {
-		if (!try_module_get(pos->gm_owner))
-			continue;
-		if (!mech_supports_subflavor(pos, subflavor)) {
-			module_put(pos->gm_owner);
-			continue;
-		}
-		gm = pos;
-		break;
-	}
-	spin_unlock(&registered_mechs_lock);
-	return gm;
-}
-
-void lgss_mech_put(struct gss_api_mech *gm)
-{
-	module_put(gm->gm_owner);
-}
-
-/* The mech could probably be determined from the token instead, but it's just
- * as easy for now to pass it in. */
-__u32 lgss_import_sec_context(rawobj_t *input_token,
-			      struct gss_api_mech *mech,
-			      struct gss_ctx **ctx_id)
-{
-	OBD_ALLOC_PTR(*ctx_id);
-	if (*ctx_id == NULL)
-		return GSS_S_FAILURE;
-
-	(*ctx_id)->mech_type = lgss_mech_get(mech);
-
-	LASSERT(mech);
-	LASSERT(mech->gm_ops);
-	LASSERT(mech->gm_ops->gss_import_sec_context);
-	return mech->gm_ops->gss_import_sec_context(input_token, *ctx_id);
-}
-
-__u32 lgss_copy_reverse_context(struct gss_ctx *ctx_id,
-				struct gss_ctx **ctx_id_new)
-{
-	struct gss_api_mech *mech = ctx_id->mech_type;
-	__u32		major;
-
-	LASSERT(mech);
-
-	OBD_ALLOC_PTR(*ctx_id_new);
-	if (*ctx_id_new == NULL)
-		return GSS_S_FAILURE;
-
-	(*ctx_id_new)->mech_type = lgss_mech_get(mech);
-
-	LASSERT(mech);
-	LASSERT(mech->gm_ops);
-	LASSERT(mech->gm_ops->gss_copy_reverse_context);
-
-	major = mech->gm_ops->gss_copy_reverse_context(ctx_id, *ctx_id_new);
-	if (major != GSS_S_COMPLETE) {
-		lgss_mech_put(mech);
-		OBD_FREE_PTR(*ctx_id_new);
-		*ctx_id_new = NULL;
-	}
-	return major;
-}
-
-/*
- * this interface is much simplified, currently we only need endtime.
- */
-__u32 lgss_inquire_context(struct gss_ctx *context_handle,
-			   unsigned long  *endtime)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_inquire_context);
-
-	return context_handle->mech_type->gm_ops
-		->gss_inquire_context(context_handle,
-				      endtime);
-}
-
-/* gss_get_mic: compute a mic over message and return mic_token. */
-__u32 lgss_get_mic(struct gss_ctx *context_handle,
-		   int msgcnt,
-		   rawobj_t *msg,
-		   int iovcnt,
-		   lnet_kiov_t *iovs,
-		   rawobj_t *mic_token)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_get_mic);
-
-	return context_handle->mech_type->gm_ops
-		->gss_get_mic(context_handle,
-			      msgcnt,
-			      msg,
-			      iovcnt,
-			      iovs,
-			      mic_token);
-}
-
-/* gss_verify_mic: check whether the provided mic_token verifies message. */
-__u32 lgss_verify_mic(struct gss_ctx *context_handle,
-		      int msgcnt,
-		      rawobj_t *msg,
-		      int iovcnt,
-		      lnet_kiov_t *iovs,
-		      rawobj_t *mic_token)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_verify_mic);
-
-	return context_handle->mech_type->gm_ops
-		->gss_verify_mic(context_handle,
-				 msgcnt,
-				 msg,
-				 iovcnt,
-				 iovs,
-				 mic_token);
-}
-
-__u32 lgss_wrap(struct gss_ctx *context_handle,
-		rawobj_t *gsshdr,
-		rawobj_t *msg,
-		int msg_buflen,
-		rawobj_t *out_token)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_wrap);
-
-	return context_handle->mech_type->gm_ops
-		->gss_wrap(context_handle, gsshdr, msg, msg_buflen, out_token);
-}
-
-__u32 lgss_unwrap(struct gss_ctx *context_handle,
-		  rawobj_t *gsshdr,
-		  rawobj_t *token,
-		  rawobj_t *out_msg)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_unwrap);
-
-	return context_handle->mech_type->gm_ops
-		->gss_unwrap(context_handle, gsshdr, token, out_msg);
-}
-
-
-__u32 lgss_prep_bulk(struct gss_ctx *context_handle,
-		     struct ptlrpc_bulk_desc *desc)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_prep_bulk);
-
-	return context_handle->mech_type->gm_ops
-		->gss_prep_bulk(context_handle, desc);
-}
-
-__u32 lgss_wrap_bulk(struct gss_ctx *context_handle,
-		     struct ptlrpc_bulk_desc *desc,
-		     rawobj_t *token,
-		     int adj_nob)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_wrap_bulk);
-
-	return context_handle->mech_type->gm_ops
-		->gss_wrap_bulk(context_handle, desc, token, adj_nob);
-}
-
-__u32 lgss_unwrap_bulk(struct gss_ctx *context_handle,
-		       struct ptlrpc_bulk_desc *desc,
-		       rawobj_t *token,
-		       int adj_nob)
-{
-	LASSERT(context_handle);
-	LASSERT(context_handle->mech_type);
-	LASSERT(context_handle->mech_type->gm_ops);
-	LASSERT(context_handle->mech_type->gm_ops->gss_unwrap_bulk);
-
-	return context_handle->mech_type->gm_ops
-		->gss_unwrap_bulk(context_handle, desc, token, adj_nob);
-}
-
-/* gss_delete_sec_context: free all resources associated with context_handle.
- * Note this differs from the RFC 2744-specified prototype in that we don't
- * bother returning an output token, since it would never be used anyway. */
-
-__u32 lgss_delete_sec_context(struct gss_ctx **context_handle)
-{
-	struct gss_api_mech *mech;
-
-	CDEBUG(D_SEC, "deleting %p\n", *context_handle);
-
-	if (!*context_handle)
-		return(GSS_S_NO_CONTEXT);
-
-	mech = (*context_handle)->mech_type;
-	if ((*context_handle)->internal_ctx_id != 0) {
-		LASSERT(mech);
-		LASSERT(mech->gm_ops);
-		LASSERT(mech->gm_ops->gss_delete_sec_context);
-		mech->gm_ops->gss_delete_sec_context(
-					(*context_handle)->internal_ctx_id);
-	}
-	if (mech)
-		lgss_mech_put(mech);
-
-	OBD_FREE_PTR(*context_handle);
-	*context_handle=NULL;
-	return GSS_S_COMPLETE;
-}
-
-int lgss_display(struct gss_ctx *ctx,
-		 char	   *buf,
-		 int	     bufsize)
-{
-	LASSERT(ctx);
-	LASSERT(ctx->mech_type);
-	LASSERT(ctx->mech_type->gm_ops);
-	LASSERT(ctx->mech_type->gm_ops->gss_display);
-
-	return ctx->mech_type->gm_ops->gss_display(ctx, buf, bufsize);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1233 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- * linux/net/sunrpc/auth_gss.c
- *
- * RPCSEC_GSS client authentication.
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Dug Song       <dugsong@monkey.org>
- *  Andy Adamson   <andros@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-#include <linux/crypto.h>
-#include <asm/atomic.h>
-struct rpc_clnt; /* for rpc_pipefs */
-#include <linux/sunrpc/rpc_pipe_fs.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_sec.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-static struct ptlrpc_sec_policy gss_policy_pipefs;
-static struct ptlrpc_ctx_ops gss_pipefs_ctxops;
-
-static int gss_cli_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx);
-
-static int gss_sec_pipe_upcall_init(struct gss_sec *gsec)
-{
-	return 0;
-}
-
-static void gss_sec_pipe_upcall_fini(struct gss_sec *gsec)
-{
-}
-
-/****************************************
- * internal context helpers	     *
- ****************************************/
-
-static
-struct ptlrpc_cli_ctx *ctx_create_pf(struct ptlrpc_sec *sec,
-				     struct vfs_cred *vcred)
-{
-	struct gss_cli_ctx *gctx;
-	int		 rc;
-
-	OBD_ALLOC_PTR(gctx);
-	if (gctx == NULL)
-		return NULL;
-
-	rc = gss_cli_ctx_init_common(sec, &gctx->gc_base,
-				     &gss_pipefs_ctxops, vcred);
-	if (rc) {
-		OBD_FREE_PTR(gctx);
-		return NULL;
-	}
-
-	return &gctx->gc_base;
-}
-
-static
-void ctx_destroy_pf(struct ptlrpc_sec *sec, struct ptlrpc_cli_ctx *ctx)
-{
-	struct gss_cli_ctx *gctx = ctx2gctx(ctx);
-
-	if (gss_cli_ctx_fini_common(sec, ctx))
-		return;
-
-	OBD_FREE_PTR(gctx);
-
-	atomic_dec(&sec->ps_nctx);
-	sptlrpc_sec_put(sec);
-}
-
-static
-void ctx_enhash_pf(struct ptlrpc_cli_ctx *ctx, struct hlist_head *hash)
-{
-	set_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags);
-	atomic_inc(&ctx->cc_refcount);
-	hlist_add_head(&ctx->cc_cache, hash);
-}
-
-/*
- * caller must hold spinlock
- */
-static
-void ctx_unhash_pf(struct ptlrpc_cli_ctx *ctx, struct hlist_head *freelist)
-{
-	assert_spin_locked(&ctx->cc_sec->ps_lock);
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags));
-	LASSERT(!hlist_unhashed(&ctx->cc_cache));
-
-	clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags);
-
-	if (atomic_dec_and_test(&ctx->cc_refcount)) {
-		__hlist_del(&ctx->cc_cache);
-		hlist_add_head(&ctx->cc_cache, freelist);
-	} else {
-		hlist_del_init(&ctx->cc_cache);
-	}
-}
-
-/*
- * return 1 if the context is dead.
- */
-static
-int ctx_check_death_pf(struct ptlrpc_cli_ctx *ctx,
-		       struct hlist_head *freelist)
-{
-	if (cli_ctx_check_death(ctx)) {
-		if (freelist)
-			ctx_unhash_pf(ctx, freelist);
-		return 1;
-	}
-
-	return 0;
-}
-
-static inline
-int ctx_check_death_locked_pf(struct ptlrpc_cli_ctx *ctx,
-			      struct hlist_head *freelist)
-{
-	LASSERT(ctx->cc_sec);
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-	LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags));
-
-	return ctx_check_death_pf(ctx, freelist);
-}
-
-static inline
-int ctx_match_pf(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred)
-{
-	/* a little bit optimization for null policy */
-	if (!ctx->cc_ops->match)
-		return 1;
-
-	return ctx->cc_ops->match(ctx, vcred);
-}
-
-static
-void ctx_list_destroy_pf(struct hlist_head *head)
-{
-	struct ptlrpc_cli_ctx *ctx;
-
-	while (!hlist_empty(head)) {
-		ctx = hlist_entry(head->first, struct ptlrpc_cli_ctx,
-				      cc_cache);
-
-		LASSERT(atomic_read(&ctx->cc_refcount) == 0);
-		LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT,
-				     &ctx->cc_flags) == 0);
-
-		hlist_del_init(&ctx->cc_cache);
-		ctx_destroy_pf(ctx->cc_sec, ctx);
-	}
-}
-
-/****************************************
- * context apis			 *
- ****************************************/
-
-static
-int gss_cli_ctx_validate_pf(struct ptlrpc_cli_ctx *ctx)
-{
-	if (ctx_check_death_pf(ctx, NULL))
-		return 1;
-	if (cli_ctx_is_ready(ctx))
-		return 0;
-	return 1;
-}
-
-static
-void gss_cli_ctx_die_pf(struct ptlrpc_cli_ctx *ctx, int grace)
-{
-	LASSERT(ctx->cc_sec);
-	LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-	cli_ctx_expire(ctx);
-
-	spin_lock(&ctx->cc_sec->ps_lock);
-
-	if (test_and_clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags)) {
-		LASSERT(!hlist_unhashed(&ctx->cc_cache));
-		LASSERT(atomic_read(&ctx->cc_refcount) > 1);
-
-		hlist_del_init(&ctx->cc_cache);
-		if (atomic_dec_and_test(&ctx->cc_refcount))
-			LBUG();
-	}
-
-	spin_unlock(&ctx->cc_sec->ps_lock);
-}
-
-/****************************************
- * reverse context installation	 *
- ****************************************/
-
-static inline
-unsigned int ctx_hash_index(int hashsize, __u64 key)
-{
-	return (unsigned int) (key & ((__u64) hashsize - 1));
-}
-
-static
-void gss_sec_ctx_replace_pf(struct gss_sec *gsec,
-			    struct ptlrpc_cli_ctx *new)
-{
-	struct gss_sec_pipefs *gsec_pf;
-	struct ptlrpc_cli_ctx *ctx;
-	struct hlist_node     *next;
-	HLIST_HEAD(freelist);
-	unsigned int hash;
-
-	gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base);
-
-	hash = ctx_hash_index(gsec_pf->gsp_chash_size,
-			      (__u64) new->cc_vcred.vc_uid);
-	LASSERT(hash < gsec_pf->gsp_chash_size);
-
-	spin_lock(&gsec->gs_base.ps_lock);
-
-	hlist_for_each_entry_safe(ctx, next,
-				      &gsec_pf->gsp_chash[hash], cc_cache) {
-		if (!ctx_match_pf(ctx, &new->cc_vcred))
-			continue;
-
-		cli_ctx_expire(ctx);
-		ctx_unhash_pf(ctx, &freelist);
-		break;
-	}
-
-	ctx_enhash_pf(new, &gsec_pf->gsp_chash[hash]);
-
-	spin_unlock(&gsec->gs_base.ps_lock);
-
-	ctx_list_destroy_pf(&freelist);
-}
-
-static
-int gss_install_rvs_cli_ctx_pf(struct gss_sec *gsec,
-			       struct ptlrpc_svc_ctx *svc_ctx)
-{
-	struct vfs_cred	  vcred;
-	struct ptlrpc_cli_ctx   *cli_ctx;
-	int		      rc;
-
-	vcred.vc_uid = 0;
-	vcred.vc_gid = 0;
-
-	cli_ctx = ctx_create_pf(&gsec->gs_base, &vcred);
-	if (!cli_ctx)
-		return -ENOMEM;
-
-	rc = gss_copy_rvc_cli_ctx(cli_ctx, svc_ctx);
-	if (rc) {
-		ctx_destroy_pf(cli_ctx->cc_sec, cli_ctx);
-		return rc;
-	}
-
-	gss_sec_ctx_replace_pf(gsec, cli_ctx);
-	return 0;
-}
-
-static
-void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf,
-			 struct hlist_head *freelist)
-{
-	struct ptlrpc_sec       *sec;
-	struct ptlrpc_cli_ctx   *ctx;
-	struct hlist_node       *next;
-	int i;
-
-	sec = &gsec_pf->gsp_base.gs_base;
-
-	CDEBUG(D_SEC, "do gc on sec %s@%p\n", sec->ps_policy->sp_name, sec);
-
-	for (i = 0; i < gsec_pf->gsp_chash_size; i++) {
-		hlist_for_each_entry_safe(ctx, next,
-					      &gsec_pf->gsp_chash[i], cc_cache)
-			ctx_check_death_locked_pf(ctx, freelist);
-	}
-
-	sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
-}
-
-static
-struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
-				     struct ptlrpc_svc_ctx *ctx,
-				     struct sptlrpc_flavor *sf)
-{
-	struct gss_sec_pipefs   *gsec_pf;
-	int		      alloc_size, hash_size, i;
-
-#define GSS_SEC_PIPEFS_CTX_HASH_SIZE    (32)
-
-	if (ctx ||
-	    sf->sf_flags & (PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_REVERSE))
-		hash_size = 1;
-	else
-		hash_size = GSS_SEC_PIPEFS_CTX_HASH_SIZE;
-
-	alloc_size = sizeof(*gsec_pf) +
-		     sizeof(struct hlist_head) * hash_size;
-
-	OBD_ALLOC(gsec_pf, alloc_size);
-	if (!gsec_pf)
-		return NULL;
-
-	gsec_pf->gsp_chash_size = hash_size;
-	for (i = 0; i < hash_size; i++)
-		INIT_HLIST_HEAD(&gsec_pf->gsp_chash[i]);
-
-	if (gss_sec_create_common(&gsec_pf->gsp_base, &gss_policy_pipefs,
-				  imp, ctx, sf))
-		goto err_free;
-
-	if (ctx == NULL) {
-		if (gss_sec_pipe_upcall_init(&gsec_pf->gsp_base))
-			goto err_destroy;
-	} else {
-		if (gss_install_rvs_cli_ctx_pf(&gsec_pf->gsp_base, ctx))
-			goto err_destroy;
-	}
-
-	return &gsec_pf->gsp_base.gs_base;
-
-err_destroy:
-	gss_sec_destroy_common(&gsec_pf->gsp_base);
-err_free:
-	OBD_FREE(gsec_pf, alloc_size);
-	return NULL;
-}
-
-static
-void gss_sec_destroy_pf(struct ptlrpc_sec *sec)
-{
-	struct gss_sec_pipefs   *gsec_pf;
-	struct gss_sec	  *gsec;
-
-	CWARN("destroy %s@%p\n", sec->ps_policy->sp_name, sec);
-
-	gsec = container_of(sec, struct gss_sec, gs_base);
-	gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base);
-
-	LASSERT(gsec_pf->gsp_chash);
-	LASSERT(gsec_pf->gsp_chash_size);
-
-	gss_sec_pipe_upcall_fini(gsec);
-
-	gss_sec_destroy_common(gsec);
-
-	OBD_FREE(gsec, sizeof(*gsec_pf) +
-		       sizeof(struct hlist_head) * gsec_pf->gsp_chash_size);
-}
-
-static
-struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_pf(struct ptlrpc_sec *sec,
-					      struct vfs_cred *vcred,
-					      int create, int remove_dead)
-{
-	struct gss_sec	 *gsec;
-	struct gss_sec_pipefs  *gsec_pf;
-	struct ptlrpc_cli_ctx  *ctx = NULL, *new = NULL;
-	struct hlist_head       *hash_head;
-	struct hlist_node       *next;
-	HLIST_HEAD(freelist);
-	unsigned int	    hash, gc = 0, found = 0;
-
-	might_sleep();
-
-	gsec = container_of(sec, struct gss_sec, gs_base);
-	gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base);
-
-	hash = ctx_hash_index(gsec_pf->gsp_chash_size,
-			      (__u64) vcred->vc_uid);
-	hash_head = &gsec_pf->gsp_chash[hash];
-	LASSERT(hash < gsec_pf->gsp_chash_size);
-
-retry:
-	spin_lock(&sec->ps_lock);
-
-	/* gc_next == 0 means never do gc */
-	if (remove_dead && sec->ps_gc_next &&
-	    cfs_time_after(cfs_time_current_sec(), sec->ps_gc_next)) {
-		gss_ctx_cache_gc_pf(gsec_pf, &freelist);
-		gc = 1;
-	}
-
-	hlist_for_each_entry_safe(ctx, next, hash_head, cc_cache) {
-		if (gc == 0 &&
-		    ctx_check_death_locked_pf(ctx,
-					      remove_dead ? &freelist : NULL))
-			continue;
-
-		if (ctx_match_pf(ctx, vcred)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		if (new && new != ctx) {
-			/* lost the race, just free it */
-			hlist_add_head(&new->cc_cache, &freelist);
-			new = NULL;
-		}
-
-		/* hot node, move to head */
-		if (hash_head->first != &ctx->cc_cache) {
-			__hlist_del(&ctx->cc_cache);
-			hlist_add_head(&ctx->cc_cache, hash_head);
-		}
-	} else {
-		/* don't allocate for reverse sec */
-		if (sec_is_reverse(sec)) {
-			spin_unlock(&sec->ps_lock);
-			return NULL;
-		}
-
-		if (new) {
-			ctx_enhash_pf(new, hash_head);
-			ctx = new;
-		} else if (create) {
-			spin_unlock(&sec->ps_lock);
-			new = ctx_create_pf(sec, vcred);
-			if (new) {
-				clear_bit(PTLRPC_CTX_NEW_BIT, &new->cc_flags);
-				goto retry;
-			}
-		} else {
-			ctx = NULL;
-		}
-	}
-
-	/* hold a ref */
-	if (ctx)
-		atomic_inc(&ctx->cc_refcount);
-
-	spin_unlock(&sec->ps_lock);
-
-	/* the allocator of the context must give the first push to refresh */
-	if (new) {
-		LASSERT(new == ctx);
-		gss_cli_ctx_refresh_pf(new);
-	}
-
-	ctx_list_destroy_pf(&freelist);
-	return ctx;
-}
-
-static
-void gss_sec_release_ctx_pf(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx,
-			    int sync)
-{
-	LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
-	LASSERT(hlist_unhashed(&ctx->cc_cache));
-
-	/* if required async, we must clear the UPTODATE bit to prevent extra
-	 * rpcs during destroy procedure. */
-	if (!sync)
-		clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
-
-	/* destroy this context */
-	ctx_destroy_pf(sec, ctx);
-}
-
-/*
- * @uid: which user. "-1" means flush all.
- * @grace: mark context DEAD, allow graceful destroy like notify
- *	 server side, etc.
- * @force: also flush busy entries.
- *
- * return the number of busy context encountered.
- *
- * In any cases, never touch "eternal" contexts.
- */
-static
-int gss_sec_flush_ctx_cache_pf(struct ptlrpc_sec *sec,
-			       uid_t uid,
-			       int grace, int force)
-{
-	struct gss_sec	  *gsec;
-	struct gss_sec_pipefs   *gsec_pf;
-	struct ptlrpc_cli_ctx   *ctx;
-	struct hlist_node       *next;
-	HLIST_HEAD(freelist);
-	int i, busy = 0;
-
-	might_sleep_if(grace);
-
-	gsec = container_of(sec, struct gss_sec, gs_base);
-	gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base);
-
-	spin_lock(&sec->ps_lock);
-	for (i = 0; i < gsec_pf->gsp_chash_size; i++) {
-		hlist_for_each_entry_safe(ctx, next,
-					      &gsec_pf->gsp_chash[i],
-					      cc_cache) {
-			LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-
-			if (uid != -1 && uid != ctx->cc_vcred.vc_uid)
-				continue;
-
-			if (atomic_read(&ctx->cc_refcount) > 1) {
-				busy++;
-				if (!force)
-					continue;
-
-				CWARN("flush busy(%d) ctx %p(%u->%s) by force, "
-				      "grace %d\n",
-				      atomic_read(&ctx->cc_refcount),
-				      ctx, ctx->cc_vcred.vc_uid,
-				      sec2target_str(ctx->cc_sec), grace);
-			}
-			ctx_unhash_pf(ctx, &freelist);
-
-			set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags);
-			if (!grace)
-				clear_bit(PTLRPC_CTX_UPTODATE_BIT,
-					  &ctx->cc_flags);
-		}
-	}
-	spin_unlock(&sec->ps_lock);
-
-	ctx_list_destroy_pf(&freelist);
-	return busy;
-}
-
-/****************************************
- * service apis			 *
- ****************************************/
-
-static
-int gss_svc_accept_pf(struct ptlrpc_request *req)
-{
-	return gss_svc_accept(&gss_policy_pipefs, req);
-}
-
-static
-int gss_svc_install_rctx_pf(struct obd_import *imp,
-			    struct ptlrpc_svc_ctx *ctx)
-{
-	struct ptlrpc_sec *sec;
-	int		rc;
-
-	sec = sptlrpc_import_sec_ref(imp);
-	LASSERT(sec);
-	rc = gss_install_rvs_cli_ctx_pf(sec2gsec(sec), ctx);
-
-	sptlrpc_sec_put(sec);
-	return rc;
-}
-
-/****************************************
- * rpc_pipefs definitions	       *
- ****************************************/
-
-#define LUSTRE_PIPE_ROOT	"/lustre"
-#define LUSTRE_PIPE_KRB5	LUSTRE_PIPE_ROOT"/krb5"
-
-struct gss_upcall_msg_data {
-	__u32			   gum_seq;
-	__u32			   gum_uid;
-	__u32			   gum_gid;
-	__u32			   gum_svc;	/* MDS/OSS... */
-	__u64			   gum_nid;	/* peer NID */
-	__u8			    gum_obd[64];    /* client obd name */
-};
-
-struct gss_upcall_msg {
-	struct rpc_pipe_msg	     gum_base;
-	atomic_t		    gum_refcount;
-	struct list_head		      gum_list;
-	__u32			   gum_mechidx;
-	struct gss_sec		 *gum_gsec;
-	struct gss_cli_ctx	     *gum_gctx;
-	struct gss_upcall_msg_data      gum_data;
-};
-
-static atomic_t upcall_seq = ATOMIC_INIT(0);
-
-static inline
-__u32 upcall_get_sequence(void)
-{
-	return (__u32) atomic_inc_return(&upcall_seq);
-}
-
-enum mech_idx_t {
-	MECH_KRB5   = 0,
-	MECH_MAX
-};
-
-static inline
-__u32 mech_name2idx(const char *name)
-{
-	LASSERT(!strcmp(name, "krb5"));
-	return MECH_KRB5;
-}
-
-/* pipefs dentries for each mechanisms */
-static struct dentry *de_pipes[MECH_MAX] = { NULL, };
-/* all upcall messages linked here */
-static struct list_head upcall_lists[MECH_MAX];
-/* and protected by this */
-static spinlock_t upcall_locks[MECH_MAX];
-
-static inline
-void upcall_list_lock(int idx)
-{
-	spin_lock(&upcall_locks[idx]);
-}
-
-static inline
-void upcall_list_unlock(int idx)
-{
-	spin_unlock(&upcall_locks[idx]);
-}
-
-static
-void upcall_msg_enlist(struct gss_upcall_msg *msg)
-{
-	__u32 idx = msg->gum_mechidx;
-
-	upcall_list_lock(idx);
-	list_add(&msg->gum_list, &upcall_lists[idx]);
-	upcall_list_unlock(idx);
-}
-
-static
-void upcall_msg_delist(struct gss_upcall_msg *msg)
-{
-	__u32 idx = msg->gum_mechidx;
-
-	upcall_list_lock(idx);
-	list_del_init(&msg->gum_list);
-	upcall_list_unlock(idx);
-}
-
-/****************************************
- * rpc_pipefs upcall helpers	    *
- ****************************************/
-
-static
-void gss_release_msg(struct gss_upcall_msg *gmsg)
-{
-	LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
-
-	if (!atomic_dec_and_test(&gmsg->gum_refcount)) {
-		return;
-	}
-
-	if (gmsg->gum_gctx) {
-		sptlrpc_cli_ctx_wakeup(&gmsg->gum_gctx->gc_base);
-		sptlrpc_cli_ctx_put(&gmsg->gum_gctx->gc_base, 1);
-		gmsg->gum_gctx = NULL;
-	}
-
-	LASSERT(list_empty(&gmsg->gum_list));
-	LASSERT(list_empty(&gmsg->gum_base.list));
-	OBD_FREE_PTR(gmsg);
-}
-
-static
-void gss_unhash_msg_nolock(struct gss_upcall_msg *gmsg)
-{
-	__u32 idx = gmsg->gum_mechidx;
-
-	LASSERT(idx < MECH_MAX);
-	assert_spin_locked(&upcall_locks[idx]);
-
-	if (list_empty(&gmsg->gum_list))
-		return;
-
-	list_del_init(&gmsg->gum_list);
-	LASSERT(atomic_read(&gmsg->gum_refcount) > 1);
-	atomic_dec(&gmsg->gum_refcount);
-}
-
-static
-void gss_unhash_msg(struct gss_upcall_msg *gmsg)
-{
-	__u32 idx = gmsg->gum_mechidx;
-
-	LASSERT(idx < MECH_MAX);
-	upcall_list_lock(idx);
-	gss_unhash_msg_nolock(gmsg);
-	upcall_list_unlock(idx);
-}
-
-static
-void gss_msg_fail_ctx(struct gss_upcall_msg *gmsg)
-{
-	if (gmsg->gum_gctx) {
-		struct ptlrpc_cli_ctx *ctx = &gmsg->gum_gctx->gc_base;
-
-		LASSERT(atomic_read(&ctx->cc_refcount) > 0);
-		sptlrpc_cli_ctx_expire(ctx);
-		set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags);
-	}
-}
-
-static
-struct gss_upcall_msg * gss_find_upcall(__u32 mechidx, __u32 seq)
-{
-	struct gss_upcall_msg *gmsg;
-
-	upcall_list_lock(mechidx);
-	list_for_each_entry(gmsg, &upcall_lists[mechidx], gum_list) {
-		if (gmsg->gum_data.gum_seq != seq)
-			continue;
-
-		LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
-		LASSERT(gmsg->gum_mechidx == mechidx);
-
-		atomic_inc(&gmsg->gum_refcount);
-		upcall_list_unlock(mechidx);
-		return gmsg;
-	}
-	upcall_list_unlock(mechidx);
-	return NULL;
-}
-
-static
-int simple_get_bytes(char **buf, __u32 *buflen, void *res, __u32 reslen)
-{
-	if (*buflen < reslen) {
-		CERROR("buflen %u < %u\n", *buflen, reslen);
-		return -EINVAL;
-	}
-
-	memcpy(res, *buf, reslen);
-	*buf += reslen;
-	*buflen -= reslen;
-	return 0;
-}
-
-/****************************************
- * rpc_pipefs apis		      *
- ****************************************/
-
-static
-ssize_t gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
-			char *dst, size_t buflen)
-{
-	char *data = (char *)msg->data + msg->copied;
-	ssize_t mlen = msg->len;
-	ssize_t left;
-
-	if (mlen > buflen)
-		mlen = buflen;
-	left = copy_to_user(dst, data, mlen);
-	if (left < 0) {
-		msg->errno = left;
-		return left;
-	}
-	mlen -= left;
-	msg->copied += mlen;
-	msg->errno = 0;
-	return mlen;
-}
-
-static
-ssize_t gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
-{
-	struct rpc_inode	*rpci = RPC_I(filp->f_dentry->d_inode);
-	struct gss_upcall_msg   *gss_msg;
-	struct ptlrpc_cli_ctx   *ctx;
-	struct gss_cli_ctx      *gctx = NULL;
-	char		    *buf, *data;
-	int		      datalen;
-	int		      timeout, rc;
-	__u32		    mechidx, seq, gss_err;
-
-	mechidx = (__u32) (long) rpci->private;
-	LASSERT(mechidx < MECH_MAX);
-
-	OBD_ALLOC(buf, mlen);
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, src, mlen)) {
-		CERROR("failed copy user space data\n");
-		GOTO(out_free, rc = -EFAULT);
-	}
-	data = buf;
-	datalen = mlen;
-
-	/* data passed down format:
-	 *  - seq
-	 *  - timeout
-	 *  - gc_win / error
-	 *  - wire_ctx (rawobj)
-	 *  - mech_ctx (rawobj)
-	 */
-	if (simple_get_bytes(&data, &datalen, &seq, sizeof(seq))) {
-		CERROR("fail to get seq\n");
-		GOTO(out_free, rc = -EFAULT);
-	}
-
-	gss_msg = gss_find_upcall(mechidx, seq);
-	if (!gss_msg) {
-		CERROR("upcall %u has aborted earlier\n", seq);
-		GOTO(out_free, rc = -EINVAL);
-	}
-
-	gss_unhash_msg(gss_msg);
-	gctx = gss_msg->gum_gctx;
-	LASSERT(gctx);
-	LASSERT(atomic_read(&gctx->gc_base.cc_refcount) > 0);
-
-	/* timeout is not in use for now */
-	if (simple_get_bytes(&data, &datalen, &timeout, sizeof(timeout)))
-		GOTO(out_msg, rc = -EFAULT);
-
-	/* lgssd signal an error by gc_win == 0 */
-	if (simple_get_bytes(&data, &datalen, &gctx->gc_win,
-			     sizeof(gctx->gc_win)))
-		GOTO(out_msg, rc = -EFAULT);
-
-	if (gctx->gc_win == 0) {
-		/* followed by:
-		 * - rpc error
-		 * - gss error
-		 */
-		if (simple_get_bytes(&data, &datalen, &rc, sizeof(rc)))
-			GOTO(out_msg, rc = -EFAULT);
-		if (simple_get_bytes(&data, &datalen, &gss_err,sizeof(gss_err)))
-			GOTO(out_msg, rc = -EFAULT);
-
-		if (rc == 0 && gss_err == GSS_S_COMPLETE) {
-			CWARN("both rpc & gss error code not set\n");
-			rc = -EPERM;
-		}
-	} else {
-		rawobj_t tmpobj;
-
-		/* handle */
-		if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen))
-			GOTO(out_msg, rc = -EFAULT);
-		if (rawobj_dup(&gctx->gc_handle, &tmpobj))
-			GOTO(out_msg, rc = -ENOMEM);
-
-		/* mechctx */
-		if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen))
-			GOTO(out_msg, rc = -EFAULT);
-		gss_err = lgss_import_sec_context(&tmpobj,
-						  gss_msg->gum_gsec->gs_mech,
-						  &gctx->gc_mechctx);
-		rc = 0;
-	}
-
-	if (likely(rc == 0 && gss_err == GSS_S_COMPLETE)) {
-		gss_cli_ctx_uptodate(gctx);
-	} else {
-		ctx = &gctx->gc_base;
-		sptlrpc_cli_ctx_expire(ctx);
-		if (rc != -ERESTART || gss_err != GSS_S_COMPLETE)
-			set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags);
-
-		CERROR("refresh ctx %p(uid %d) failed: %d/0x%08x: %s\n",
-		       ctx, ctx->cc_vcred.vc_uid, rc, gss_err,
-		       test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags) ?
-		       "fatal error" : "non-fatal");
-	}
-
-	rc = mlen;
-
-out_msg:
-	gss_release_msg(gss_msg);
-
-out_free:
-	OBD_FREE(buf, mlen);
-	/* FIXME
-	 * hack pipefs: always return asked length unless all following
-	 * downcalls might be messed up. */
-	rc = mlen;
-	return rc;
-}
-
-static
-void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
-{
-	struct gss_upcall_msg	  *gmsg;
-	struct gss_upcall_msg_data     *gumd;
-	static cfs_time_t	       ratelimit = 0;
-
-	LASSERT(list_empty(&msg->list));
-
-	/* normally errno is >= 0 */
-	if (msg->errno >= 0) {
-		return;
-	}
-
-	gmsg = container_of(msg, struct gss_upcall_msg, gum_base);
-	gumd = &gmsg->gum_data;
-	LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
-
-	CERROR("failed msg %p (seq %u, uid %u, svc %u, nid "LPX64", obd %.*s): "
-	       "errno %d\n", msg, gumd->gum_seq, gumd->gum_uid, gumd->gum_svc,
-	       gumd->gum_nid, (int) sizeof(gumd->gum_obd),
-	       gumd->gum_obd, msg->errno);
-
-	atomic_inc(&gmsg->gum_refcount);
-	gss_unhash_msg(gmsg);
-	if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) {
-		cfs_time_t now = cfs_time_current_sec();
-
-		if (cfs_time_after(now, ratelimit)) {
-			CWARN("upcall timed out, is lgssd running?\n");
-			ratelimit = now + 15;
-		}
-	}
-	gss_msg_fail_ctx(gmsg);
-	gss_release_msg(gmsg);
-}
-
-static
-void gss_pipe_release(struct inode *inode)
-{
-	struct rpc_inode *rpci = RPC_I(inode);
-	__u32	     idx;
-
-	idx = (__u32) (long) rpci->private;
-	LASSERT(idx < MECH_MAX);
-
-	upcall_list_lock(idx);
-	while (!list_empty(&upcall_lists[idx])) {
-		struct gss_upcall_msg      *gmsg;
-		struct gss_upcall_msg_data *gumd;
-
-		gmsg = list_entry(upcall_lists[idx].next,
-				      struct gss_upcall_msg, gum_list);
-		gumd = &gmsg->gum_data;
-		LASSERT(list_empty(&gmsg->gum_base.list));
-
-		CERROR("failing remaining msg %p:seq %u, uid %u, svc %u, "
-		       "nid "LPX64", obd %.*s\n", gmsg,
-		       gumd->gum_seq, gumd->gum_uid, gumd->gum_svc,
-		       gumd->gum_nid, (int) sizeof(gumd->gum_obd),
-		       gumd->gum_obd);
-
-		gmsg->gum_base.errno = -EPIPE;
-		atomic_inc(&gmsg->gum_refcount);
-		gss_unhash_msg_nolock(gmsg);
-
-		gss_msg_fail_ctx(gmsg);
-
-		upcall_list_unlock(idx);
-		gss_release_msg(gmsg);
-		upcall_list_lock(idx);
-	}
-	upcall_list_unlock(idx);
-}
-
-static struct rpc_pipe_ops gss_upcall_ops = {
-	.upcall	 = gss_pipe_upcall,
-	.downcall       = gss_pipe_downcall,
-	.destroy_msg    = gss_pipe_destroy_msg,
-	.release_pipe   = gss_pipe_release,
-};
-
-/****************************************
- * upcall helper functions	      *
- ****************************************/
-
-static
-int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx)
-{
-	struct obd_import	  *imp;
-	struct gss_sec	     *gsec;
-	struct gss_upcall_msg      *gmsg;
-	int			 rc = 0;
-
-	might_sleep();
-
-	LASSERT(ctx->cc_sec);
-	LASSERT(ctx->cc_sec->ps_import);
-	LASSERT(ctx->cc_sec->ps_import->imp_obd);
-
-	imp = ctx->cc_sec->ps_import;
-	if (!imp->imp_connection) {
-		CERROR("import has no connection set\n");
-		return -EINVAL;
-	}
-
-	gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base);
-
-	OBD_ALLOC_PTR(gmsg);
-	if (!gmsg)
-		return -ENOMEM;
-
-	/* initialize pipefs base msg */
-	INIT_LIST_HEAD(&gmsg->gum_base.list);
-	gmsg->gum_base.data = &gmsg->gum_data;
-	gmsg->gum_base.len = sizeof(gmsg->gum_data);
-	gmsg->gum_base.copied = 0;
-	gmsg->gum_base.errno = 0;
-
-	/* init upcall msg */
-	atomic_set(&gmsg->gum_refcount, 1);
-	gmsg->gum_mechidx = mech_name2idx(gsec->gs_mech->gm_name);
-	gmsg->gum_gsec = gsec;
-	gmsg->gum_gctx = container_of(sptlrpc_cli_ctx_get(ctx),
-				      struct gss_cli_ctx, gc_base);
-	gmsg->gum_data.gum_seq = upcall_get_sequence();
-	gmsg->gum_data.gum_uid = ctx->cc_vcred.vc_uid;
-	gmsg->gum_data.gum_gid = 0; /* not used for now */
-	gmsg->gum_data.gum_svc = import_to_gss_svc(imp);
-	gmsg->gum_data.gum_nid = imp->imp_connection->c_peer.nid;
-	strncpy(gmsg->gum_data.gum_obd, imp->imp_obd->obd_name,
-		sizeof(gmsg->gum_data.gum_obd));
-
-	/* This only could happen when sysadmin set it dead/expired
-	 * using lctl by force. */
-	if (ctx->cc_flags & PTLRPC_CTX_STATUS_MASK) {
-		CWARN("ctx %p(%u->%s) was set flags %lx unexpectedly\n",
-		      ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
-		      ctx->cc_flags);
-
-		LASSERT(!(ctx->cc_flags & PTLRPC_CTX_UPTODATE));
-		ctx->cc_flags |= PTLRPC_CTX_DEAD | PTLRPC_CTX_ERROR;
-
-		rc = -EIO;
-		goto err_free;
-	}
-
-	upcall_msg_enlist(gmsg);
-
-	rc = rpc_queue_upcall(de_pipes[gmsg->gum_mechidx]->d_inode,
-			      &gmsg->gum_base);
-	if (rc) {
-		CERROR("rpc_queue_upcall failed: %d\n", rc);
-
-		upcall_msg_delist(gmsg);
-		goto err_free;
-	}
-
-	return 0;
-err_free:
-	OBD_FREE_PTR(gmsg);
-	return rc;
-}
-
-static
-int gss_cli_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx)
-{
-	/* if we are refreshing for root, also update the reverse
-	 * handle index, do not confuse reverse contexts. */
-	if (ctx->cc_vcred.vc_uid == 0) {
-		struct gss_sec *gsec;
-
-		gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base);
-		gsec->gs_rvs_hdl = gss_get_next_ctx_index();
-	}
-
-	return gss_ctx_refresh_pf(ctx);
-}
-
-/****************************************
- * lustre gss pipefs policy	     *
- ****************************************/
-
-static struct ptlrpc_ctx_ops gss_pipefs_ctxops = {
-	.match		  = gss_cli_ctx_match,
-	.refresh		= gss_cli_ctx_refresh_pf,
-	.validate	       = gss_cli_ctx_validate_pf,
-	.die		    = gss_cli_ctx_die_pf,
-	.sign		   = gss_cli_ctx_sign,
-	.verify		 = gss_cli_ctx_verify,
-	.seal		   = gss_cli_ctx_seal,
-	.unseal		 = gss_cli_ctx_unseal,
-	.wrap_bulk	      = gss_cli_ctx_wrap_bulk,
-	.unwrap_bulk	    = gss_cli_ctx_unwrap_bulk,
-};
-
-static struct ptlrpc_sec_cops gss_sec_pipefs_cops = {
-	.create_sec	     = gss_sec_create_pf,
-	.destroy_sec	    = gss_sec_destroy_pf,
-	.kill_sec	       = gss_sec_kill,
-	.lookup_ctx	     = gss_sec_lookup_ctx_pf,
-	.release_ctx	    = gss_sec_release_ctx_pf,
-	.flush_ctx_cache	= gss_sec_flush_ctx_cache_pf,
-	.install_rctx	   = gss_sec_install_rctx,
-	.alloc_reqbuf	   = gss_alloc_reqbuf,
-	.free_reqbuf	    = gss_free_reqbuf,
-	.alloc_repbuf	   = gss_alloc_repbuf,
-	.free_repbuf	    = gss_free_repbuf,
-	.enlarge_reqbuf	 = gss_enlarge_reqbuf,
-};
-
-static struct ptlrpc_sec_sops gss_sec_pipefs_sops = {
-	.accept		 = gss_svc_accept_pf,
-	.invalidate_ctx	 = gss_svc_invalidate_ctx,
-	.alloc_rs	       = gss_svc_alloc_rs,
-	.authorize	      = gss_svc_authorize,
-	.free_rs		= gss_svc_free_rs,
-	.free_ctx	       = gss_svc_free_ctx,
-	.unwrap_bulk	    = gss_svc_unwrap_bulk,
-	.wrap_bulk	      = gss_svc_wrap_bulk,
-	.install_rctx	   = gss_svc_install_rctx_pf,
-};
-
-static struct ptlrpc_sec_policy gss_policy_pipefs = {
-	.sp_owner	       = THIS_MODULE,
-	.sp_name		= "gss.pipefs",
-	.sp_policy	      = SPTLRPC_POLICY_GSS_PIPEFS,
-	.sp_cops		= &gss_sec_pipefs_cops,
-	.sp_sops		= &gss_sec_pipefs_sops,
-};
-
-static
-int __init gss_init_pipefs_upcall(void)
-{
-	struct dentry   *de;
-
-	/* pipe dir */
-	de = rpc_mkdir(LUSTRE_PIPE_ROOT, NULL);
-	if (IS_ERR(de) && PTR_ERR(de) != -EEXIST) {
-		CERROR("Failed to create gss pipe dir: %ld\n", PTR_ERR(de));
-		return PTR_ERR(de);
-	}
-
-	/* FIXME hack pipefs: dput will sometimes cause oops during module
-	 * unload and lgssd close the pipe fds. */
-
-	/* krb5 mechanism */
-	de = rpc_mkpipe(LUSTRE_PIPE_KRB5, (void *) MECH_KRB5, &gss_upcall_ops,
-			RPC_PIPE_WAIT_FOR_OPEN);
-	if (!de || IS_ERR(de)) {
-		CERROR("failed to make rpc_pipe %s: %ld\n",
-		       LUSTRE_PIPE_KRB5, PTR_ERR(de));
-		rpc_rmdir(LUSTRE_PIPE_ROOT);
-		return PTR_ERR(de);
-	}
-
-	de_pipes[MECH_KRB5] = de;
-	INIT_LIST_HEAD(&upcall_lists[MECH_KRB5]);
-	spin_lock_init(&upcall_locks[MECH_KRB5]);
-
-	return 0;
-}
-
-static
-void __exit gss_exit_pipefs_upcall(void)
-{
-	__u32   i;
-
-	for (i = 0; i < MECH_MAX; i++) {
-		LASSERT(list_empty(&upcall_lists[i]));
-
-		/* dput pipe dentry here might cause lgssd oops. */
-		de_pipes[i] = NULL;
-	}
-
-	rpc_unlink(LUSTRE_PIPE_KRB5);
-	rpc_rmdir(LUSTRE_PIPE_ROOT);
-}
-
-int __init gss_init_pipefs(void)
-{
-	int rc;
-
-	rc = gss_init_pipefs_upcall();
-	if (rc)
-		return rc;
-
-	rc = sptlrpc_register_policy(&gss_policy_pipefs);
-	if (rc) {
-		gss_exit_pipefs_upcall();
-		return rc;
-	}
-
-	return 0;
-}
-
-void __exit gss_exit_pipefs(void)
-{
-	gss_exit_pipefs_upcall();
-	sptlrpc_unregister_policy(&gss_policy_pipefs);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,242 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/ptlrpc/gss/gss_rawobj.c
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_sec.h>
-
-#include "gss_internal.h"
-
-int rawobj_empty(rawobj_t *obj)
-{
-	LASSERT(equi(obj->len, obj->data));
-	return (obj->len == 0);
-}
-
-int rawobj_alloc(rawobj_t *obj, char *buf, int len)
-{
-	LASSERT(obj);
-	LASSERT(len >= 0);
-
-	obj->len = len;
-	if (len) {
-		OBD_ALLOC_LARGE(obj->data, len);
-		if (!obj->data) {
-			obj->len = 0;
-			return -ENOMEM;
-		}
-		memcpy(obj->data, buf, len);
-	} else
-		obj->data = NULL;
-	return 0;
-}
-
-void rawobj_free(rawobj_t *obj)
-{
-	LASSERT(obj);
-
-	if (obj->len) {
-		LASSERT(obj->data);
-		OBD_FREE_LARGE(obj->data, obj->len);
-		obj->len = 0;
-		obj->data = NULL;
-	} else
-		LASSERT(!obj->data);
-}
-
-int rawobj_equal(rawobj_t *a, rawobj_t *b)
-{
-	LASSERT(a && b);
-
-	return (a->len == b->len &&
-		(!a->len || !memcmp(a->data, b->data, a->len)));
-}
-
-int rawobj_dup(rawobj_t *dest, rawobj_t *src)
-{
-	LASSERT(src && dest);
-
-	dest->len = src->len;
-	if (dest->len) {
-		OBD_ALLOC_LARGE(dest->data, dest->len);
-		if (!dest->data) {
-			dest->len = 0;
-			return -ENOMEM;
-		}
-		memcpy(dest->data, src->data, dest->len);
-	} else
-		dest->data = NULL;
-	return 0;
-}
-
-int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen)
-{
-	__u32 len;
-
-	LASSERT(obj);
-	LASSERT(buf);
-	LASSERT(buflen);
-
-	len = cfs_size_round4(obj->len);
-
-	if (*buflen < 4 + len) {
-		CERROR("buflen %u <  %u\n", *buflen, 4 + len);
-		return -EINVAL;
-	}
-
-	*(*buf)++ = cpu_to_le32(obj->len);
-	memcpy(*buf, obj->data, obj->len);
-	*buf += (len >> 2);
-	*buflen -= (4 + len);
-
-	return 0;
-}
-
-static int __rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen,
-			    int alloc, int local)
-{
-	__u32 len;
-
-	if (*buflen < sizeof(__u32)) {
-		CERROR("buflen %u\n", *buflen);
-		return -EINVAL;
-	}
-
-	obj->len = *(*buf)++;
-	if (!local)
-		obj->len = le32_to_cpu(obj->len);
-	*buflen -= sizeof(__u32);
-
-	if (!obj->len) {
-		obj->data = NULL;
-		return 0;
-	}
-
-	len = local ? obj->len : cfs_size_round4(obj->len);
-	if (*buflen < len) {
-		CERROR("buflen %u < %u\n", *buflen, len);
-		obj->len = 0;
-		return -EINVAL;
-	}
-
-	if (!alloc)
-		obj->data = (__u8 *) *buf;
-	else {
-		OBD_ALLOC_LARGE(obj->data, obj->len);
-		if (!obj->data) {
-			CERROR("fail to alloc %u bytes\n", obj->len);
-			obj->len = 0;
-			return -ENOMEM;
-		}
-		memcpy(obj->data, *buf, obj->len);
-	}
-
-	*((char **)buf) += len;
-	*buflen -= len;
-
-	return 0;
-}
-
-int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen)
-{
-	return __rawobj_extract(obj, buf, buflen, 0, 0);
-}
-
-int rawobj_extract_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen)
-{
-	return __rawobj_extract(obj, buf, buflen, 1, 0);
-}
-
-int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen)
-{
-	return __rawobj_extract(obj, buf, buflen, 0, 1);
-}
-
-int rawobj_extract_local_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen)
-{
-	return __rawobj_extract(obj, buf, buflen, 1, 1);
-}
-
-int rawobj_from_netobj(rawobj_t *rawobj, netobj_t *netobj)
-{
-	rawobj->len = netobj->len;
-	rawobj->data = netobj->data;
-	return 0;
-}
-
-int rawobj_from_netobj_alloc(rawobj_t *rawobj, netobj_t *netobj)
-{
-	rawobj->len = 0;
-	rawobj->data = NULL;
-
-	if (netobj->len == 0)
-		return 0;
-
-	OBD_ALLOC_LARGE(rawobj->data, netobj->len);
-	if (rawobj->data == NULL)
-		return -ENOMEM;
-
-	rawobj->len = netobj->len;
-	memcpy(rawobj->data, netobj->data, netobj->len);
-	return 0;
-}
-
-/****************************************
- * misc more			    *
- ****************************************/
-
-int buffer_extract_bytes(const void **buf, __u32 *buflen,
-			 void *res, __u32 reslen)
-{
-	if (*buflen < reslen) {
-		CERROR("buflen %u < %u\n", *buflen, reslen);
-		return -EINVAL;
-	}
-
-	memcpy(res, *buf, reslen);
-	*buf += reslen;
-	*buflen -= reslen;
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1093 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- * Neil Brown <neilb@cse.unsw.edu.au>
- * J. Bruce Fields <bfields@umich.edu>
- * Andy Adamson <andros@umich.edu>
- * Dug Song <dugsong@monkey.org>
- *
- * RPCSEC_GSS server authentication.
- * This implements RPCSEC_GSS as defined in rfc2203 (rpcsec_gss) and rfc2078
- * (gssapi)
- *
- * The RPCSEC_GSS involves three stages:
- *  1/ context creation
- *  2/ data exchange
- *  3/ context destruction
- *
- * Context creation is handled largely by upcalls to user-space.
- *  In particular, GSS_Accept_sec_context is handled by an upcall
- * Data exchange is handled entirely within the kernel
- *  In particular, GSS_GetMIC, GSS_VerifyMIC, GSS_Seal, GSS_Unseal are in-kernel.
- * Context destruction is handled in-kernel
- *  GSS_Delete_sec_context is in-kernel
- *
- * Context creation is initiated by a RPCSEC_GSS_INIT request arriving.
- * The context handle and gss_token are used as a key into the rpcsec_init cache.
- * The content of this cache includes some of the outputs of GSS_Accept_sec_context,
- * being major_status, minor_status, context_handle, reply_token.
- * These are sent back to the client.
- * Sequence window management is handled by the kernel.  The window size if currently
- * a compile time constant.
- *
- * When user-space is happy that a context is established, it places an entry
- * in the rpcsec_context cache. The key for this cache is the context_handle.
- * The content includes:
- *   uid/gidlist - for determining access rights
- *   mechanism type
- *   mechanism specific information, such as a key
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/hash.h>
-#include <linux/mutex.h>
-#include <linux/sunrpc/cache.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-#define GSS_SVC_UPCALL_TIMEOUT  (20)
-
-static spinlock_t __ctx_index_lock;
-static __u64 __ctx_index;
-
-__u64 gss_get_next_ctx_index(void)
-{
-	__u64 idx;
-
-	spin_lock(&__ctx_index_lock);
-	idx = __ctx_index++;
-	spin_unlock(&__ctx_index_lock);
-
-	return idx;
-}
-
-static inline unsigned long hash_mem(char *buf, int length, int bits)
-{
-	unsigned long hash = 0;
-	unsigned long l = 0;
-	int len = 0;
-	unsigned char c;
-
-	do {
-		if (len == length) {
-			c = (char) len;
-			len = -1;
-		} else
-			c = *buf++;
-
-		l = (l << 8) | c;
-		len++;
-
-		if ((len & (BITS_PER_LONG/8-1)) == 0)
-			hash = hash_long(hash^l, BITS_PER_LONG);
-	} while (len);
-
-	return hash >> (BITS_PER_LONG - bits);
-}
-
-/****************************************
- * rsi cache			    *
- ****************************************/
-
-#define RSI_HASHBITS    (6)
-#define RSI_HASHMAX     (1 << RSI_HASHBITS)
-#define RSI_HASHMASK    (RSI_HASHMAX - 1)
-
-struct rsi {
-	struct cache_head       h;
-	__u32		   lustre_svc;
-	__u64		   nid;
-	wait_queue_head_t	     waitq;
-	rawobj_t		in_handle, in_token;
-	rawobj_t		out_handle, out_token;
-	int		     major_status, minor_status;
-};
-
-static struct cache_head *rsi_table[RSI_HASHMAX];
-static struct cache_detail rsi_cache;
-static struct rsi *rsi_update(struct rsi *new, struct rsi *old);
-static struct rsi *rsi_lookup(struct rsi *item);
-
-static inline int rsi_hash(struct rsi *item)
-{
-	return hash_mem((char *)item->in_handle.data, item->in_handle.len,
-			RSI_HASHBITS) ^
-	       hash_mem((char *)item->in_token.data, item->in_token.len,
-			RSI_HASHBITS);
-}
-
-static inline int __rsi_match(struct rsi *item, struct rsi *tmp)
-{
-	return (rawobj_equal(&item->in_handle, &tmp->in_handle) &&
-		rawobj_equal(&item->in_token, &tmp->in_token));
-}
-
-static void rsi_free(struct rsi *rsi)
-{
-	rawobj_free(&rsi->in_handle);
-	rawobj_free(&rsi->in_token);
-	rawobj_free(&rsi->out_handle);
-	rawobj_free(&rsi->out_token);
-}
-
-static void rsi_request(struct cache_detail *cd,
-			struct cache_head *h,
-			char **bpp, int *blen)
-{
-	struct rsi *rsi = container_of(h, struct rsi, h);
-	__u64 index = 0;
-
-	/* if in_handle is null, provide kernel suggestion */
-	if (rsi->in_handle.len == 0)
-		index = gss_get_next_ctx_index();
-
-	qword_addhex(bpp, blen, (char *) &rsi->lustre_svc,
-		     sizeof(rsi->lustre_svc));
-	qword_addhex(bpp, blen, (char *) &rsi->nid, sizeof(rsi->nid));
-	qword_addhex(bpp, blen, (char *) &index, sizeof(index));
-	qword_addhex(bpp, blen, rsi->in_handle.data, rsi->in_handle.len);
-	qword_addhex(bpp, blen, rsi->in_token.data, rsi->in_token.len);
-	(*bpp)[-1] = '\n';
-}
-
-static int rsi_upcall(struct cache_detail *cd, struct cache_head *h)
-{
-	return sunrpc_cache_pipe_upcall(cd, h, rsi_request);
-}
-
-static inline void __rsi_init(struct rsi *new, struct rsi *item)
-{
-	new->out_handle = RAWOBJ_EMPTY;
-	new->out_token = RAWOBJ_EMPTY;
-
-	new->in_handle = item->in_handle;
-	item->in_handle = RAWOBJ_EMPTY;
-	new->in_token = item->in_token;
-	item->in_token = RAWOBJ_EMPTY;
-
-	new->lustre_svc = item->lustre_svc;
-	new->nid = item->nid;
-	init_waitqueue_head(&new->waitq);
-}
-
-static inline void __rsi_update(struct rsi *new, struct rsi *item)
-{
-	LASSERT(new->out_handle.len == 0);
-	LASSERT(new->out_token.len == 0);
-
-	new->out_handle = item->out_handle;
-	item->out_handle = RAWOBJ_EMPTY;
-	new->out_token = item->out_token;
-	item->out_token = RAWOBJ_EMPTY;
-
-	new->major_status = item->major_status;
-	new->minor_status = item->minor_status;
-}
-
-static void rsi_put(struct kref *ref)
-{
-	struct rsi *rsi = container_of(ref, struct rsi, h.ref);
-
-	LASSERT(rsi->h.next == NULL);
-	rsi_free(rsi);
-	OBD_FREE_PTR(rsi);
-}
-
-static int rsi_match(struct cache_head *a, struct cache_head *b)
-{
-	struct rsi *item = container_of(a, struct rsi, h);
-	struct rsi *tmp = container_of(b, struct rsi, h);
-
-	return __rsi_match(item, tmp);
-}
-
-static void rsi_init(struct cache_head *cnew, struct cache_head *citem)
-{
-	struct rsi *new = container_of(cnew, struct rsi, h);
-	struct rsi *item = container_of(citem, struct rsi, h);
-
-	__rsi_init(new, item);
-}
-
-static void update_rsi(struct cache_head *cnew, struct cache_head *citem)
-{
-	struct rsi *new = container_of(cnew, struct rsi, h);
-	struct rsi *item = container_of(citem, struct rsi, h);
-
-	__rsi_update(new, item);
-}
-
-static struct cache_head *rsi_alloc(void)
-{
-	struct rsi *rsi;
-
-	OBD_ALLOC_PTR(rsi);
-	if (rsi)
-		return &rsi->h;
-	else
-		return NULL;
-}
-
-static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen)
-{
-	char	   *buf = mesg;
-	char	   *ep;
-	int	     len;
-	struct rsi      rsii, *rsip = NULL;
-	time_t	  expiry;
-	int	     status = -EINVAL;
-
-	memset(&rsii, 0, sizeof(rsii));
-
-	/* handle */
-	len = qword_get(&mesg, buf, mlen);
-	if (len < 0)
-		goto out;
-	if (rawobj_alloc(&rsii.in_handle, buf, len)) {
-		status = -ENOMEM;
-		goto out;
-	}
-
-	/* token */
-	len = qword_get(&mesg, buf, mlen);
-	if (len < 0)
-		goto out;
-	if (rawobj_alloc(&rsii.in_token, buf, len)) {
-		status = -ENOMEM;
-		goto out;
-	}
-
-	rsip = rsi_lookup(&rsii);
-	if (!rsip)
-		goto out;
-
-	rsii.h.flags = 0;
-	/* expiry */
-	expiry = get_expiry(&mesg);
-	if (expiry == 0)
-		goto out;
-
-	len = qword_get(&mesg, buf, mlen);
-	if (len <= 0)
-		goto out;
-
-	/* major */
-	rsii.major_status = simple_strtol(buf, &ep, 10);
-	if (*ep)
-		goto out;
-
-	/* minor */
-	len = qword_get(&mesg, buf, mlen);
-	if (len <= 0)
-		goto out;
-	rsii.minor_status = simple_strtol(buf, &ep, 10);
-	if (*ep)
-		goto out;
-
-	/* out_handle */
-	len = qword_get(&mesg, buf, mlen);
-	if (len < 0)
-		goto out;
-	if (rawobj_alloc(&rsii.out_handle, buf, len)) {
-		status = -ENOMEM;
-		goto out;
-	}
-
-	/* out_token */
-	len = qword_get(&mesg, buf, mlen);
-	if (len < 0)
-		goto out;
-	if (rawobj_alloc(&rsii.out_token, buf, len)) {
-		status = -ENOMEM;
-		goto out;
-	}
-
-	rsii.h.expiry_time = expiry;
-	rsip = rsi_update(&rsii, rsip);
-	status = 0;
-out:
-	rsi_free(&rsii);
-	if (rsip) {
-		wake_up_all(&rsip->waitq);
-		cache_put(&rsip->h, &rsi_cache);
-	} else {
-		status = -ENOMEM;
-	}
-
-	if (status)
-		CERROR("rsi parse error %d\n", status);
-	return status;
-}
-
-static struct cache_detail rsi_cache = {
-	.hash_size      = RSI_HASHMAX,
-	.hash_table     = rsi_table,
-	.name	   = "auth.sptlrpc.init",
-	.cache_put      = rsi_put,
-	.cache_upcall   = rsi_upcall,
-	.cache_parse    = rsi_parse,
-	.match	  = rsi_match,
-	.init	   = rsi_init,
-	.update	 = update_rsi,
-	.alloc	  = rsi_alloc,
-};
-
-static struct rsi *rsi_lookup(struct rsi *item)
-{
-	struct cache_head *ch;
-	int hash = rsi_hash(item);
-
-	ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash);
-	if (ch)
-		return container_of(ch, struct rsi, h);
-	else
-		return NULL;
-}
-
-static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
-{
-	struct cache_head *ch;
-	int hash = rsi_hash(new);
-
-	ch = sunrpc_cache_update(&rsi_cache, &new->h, &old->h, hash);
-	if (ch)
-		return container_of(ch, struct rsi, h);
-	else
-		return NULL;
-}
-
-/****************************************
- * rsc cache			    *
- ****************************************/
-
-#define RSC_HASHBITS    (10)
-#define RSC_HASHMAX     (1 << RSC_HASHBITS)
-#define RSC_HASHMASK    (RSC_HASHMAX - 1)
-
-struct rsc {
-	struct cache_head       h;
-	struct obd_device      *target;
-	rawobj_t		handle;
-	struct gss_svc_ctx      ctx;
-};
-
-static struct cache_head *rsc_table[RSC_HASHMAX];
-static struct cache_detail rsc_cache;
-static struct rsc *rsc_update(struct rsc *new, struct rsc *old);
-static struct rsc *rsc_lookup(struct rsc *item);
-
-static void rsc_free(struct rsc *rsci)
-{
-	rawobj_free(&rsci->handle);
-	rawobj_free(&rsci->ctx.gsc_rvs_hdl);
-	lgss_delete_sec_context(&rsci->ctx.gsc_mechctx);
-}
-
-static inline int rsc_hash(struct rsc *rsci)
-{
-	return hash_mem((char *)rsci->handle.data,
-			rsci->handle.len, RSC_HASHBITS);
-}
-
-static inline int __rsc_match(struct rsc *new, struct rsc *tmp)
-{
-	return rawobj_equal(&new->handle, &tmp->handle);
-}
-
-static inline void __rsc_init(struct rsc *new, struct rsc *tmp)
-{
-	new->handle = tmp->handle;
-	tmp->handle = RAWOBJ_EMPTY;
-
-	new->target = NULL;
-	memset(&new->ctx, 0, sizeof(new->ctx));
-	new->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
-}
-
-static inline void __rsc_update(struct rsc *new, struct rsc *tmp)
-{
-	new->ctx = tmp->ctx;
-	tmp->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
-	tmp->ctx.gsc_mechctx = NULL;
-
-	memset(&new->ctx.gsc_seqdata, 0, sizeof(new->ctx.gsc_seqdata));
-	spin_lock_init(&new->ctx.gsc_seqdata.ssd_lock);
-}
-
-static void rsc_put(struct kref *ref)
-{
-	struct rsc *rsci = container_of(ref, struct rsc, h.ref);
-
-	LASSERT(rsci->h.next == NULL);
-	rsc_free(rsci);
-	OBD_FREE_PTR(rsci);
-}
-
-static int rsc_match(struct cache_head *a, struct cache_head *b)
-{
-	struct rsc *new = container_of(a, struct rsc, h);
-	struct rsc *tmp = container_of(b, struct rsc, h);
-
-	return __rsc_match(new, tmp);
-}
-
-static void rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
-{
-	struct rsc *new = container_of(cnew, struct rsc, h);
-	struct rsc *tmp = container_of(ctmp, struct rsc, h);
-
-	__rsc_init(new, tmp);
-}
-
-static void update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
-{
-	struct rsc *new = container_of(cnew, struct rsc, h);
-	struct rsc *tmp = container_of(ctmp, struct rsc, h);
-
-	__rsc_update(new, tmp);
-}
-
-static struct cache_head * rsc_alloc(void)
-{
-	struct rsc *rsc;
-
-	OBD_ALLOC_PTR(rsc);
-	if (rsc)
-		return &rsc->h;
-	else
-		return NULL;
-}
-
-static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
-{
-	char		*buf = mesg;
-	int		  len, rv, tmp_int;
-	struct rsc	   rsci, *rscp = NULL;
-	time_t	       expiry;
-	int		  status = -EINVAL;
-	struct gss_api_mech *gm = NULL;
-
-	memset(&rsci, 0, sizeof(rsci));
-
-	/* context handle */
-	len = qword_get(&mesg, buf, mlen);
-	if (len < 0) goto out;
-	status = -ENOMEM;
-	if (rawobj_alloc(&rsci.handle, buf, len))
-		goto out;
-
-	rsci.h.flags = 0;
-	/* expiry */
-	expiry = get_expiry(&mesg);
-	status = -EINVAL;
-	if (expiry == 0)
-		goto out;
-
-	/* remote flag */
-	rv = get_int(&mesg, &tmp_int);
-	if (rv) {
-		CERROR("fail to get remote flag\n");
-		goto out;
-	}
-	rsci.ctx.gsc_remote = (tmp_int != 0);
-
-	/* root user flag */
-	rv = get_int(&mesg, &tmp_int);
-	if (rv) {
-		CERROR("fail to get oss user flag\n");
-		goto out;
-	}
-	rsci.ctx.gsc_usr_root = (tmp_int != 0);
-
-	/* mds user flag */
-	rv = get_int(&mesg, &tmp_int);
-	if (rv) {
-		CERROR("fail to get mds user flag\n");
-		goto out;
-	}
-	rsci.ctx.gsc_usr_mds = (tmp_int != 0);
-
-	/* oss user flag */
-	rv = get_int(&mesg, &tmp_int);
-	if (rv) {
-		CERROR("fail to get oss user flag\n");
-		goto out;
-	}
-	rsci.ctx.gsc_usr_oss = (tmp_int != 0);
-
-	/* mapped uid */
-	rv = get_int(&mesg, (int *) &rsci.ctx.gsc_mapped_uid);
-	if (rv) {
-		CERROR("fail to get mapped uid\n");
-		goto out;
-	}
-
-	rscp = rsc_lookup(&rsci);
-	if (!rscp)
-		goto out;
-
-	/* uid, or NEGATIVE */
-	rv = get_int(&mesg, (int *) &rsci.ctx.gsc_uid);
-	if (rv == -EINVAL)
-		goto out;
-	if (rv == -ENOENT) {
-		CERROR("NOENT? set rsc entry negative\n");
-		set_bit(CACHE_NEGATIVE, &rsci.h.flags);
-	} else {
-		rawobj_t tmp_buf;
-		unsigned long ctx_expiry;
-
-		/* gid */
-		if (get_int(&mesg, (int *) &rsci.ctx.gsc_gid))
-			goto out;
-
-		/* mech name */
-		len = qword_get(&mesg, buf, mlen);
-		if (len < 0)
-			goto out;
-		gm = lgss_name_to_mech(buf);
-		status = -EOPNOTSUPP;
-		if (!gm)
-			goto out;
-
-		status = -EINVAL;
-		/* mech-specific data: */
-		len = qword_get(&mesg, buf, mlen);
-		if (len < 0)
-			goto out;
-
-		tmp_buf.len = len;
-		tmp_buf.data = (unsigned char *)buf;
-		if (lgss_import_sec_context(&tmp_buf, gm,
-					    &rsci.ctx.gsc_mechctx))
-			goto out;
-
-		/* currently the expiry time passed down from user-space
-		 * is invalid, here we retrieve it from mech. */
-		if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
-			CERROR("unable to get expire time, drop it\n");
-			goto out;
-		}
-		expiry = (time_t) ctx_expiry;
-	}
-
-	rsci.h.expiry_time = expiry;
-	rscp = rsc_update(&rsci, rscp);
-	status = 0;
-out:
-	if (gm)
-		lgss_mech_put(gm);
-	rsc_free(&rsci);
-	if (rscp)
-		cache_put(&rscp->h, &rsc_cache);
-	else
-		status = -ENOMEM;
-
-	if (status)
-		CERROR("parse rsc error %d\n", status);
-	return status;
-}
-
-static struct cache_detail rsc_cache = {
-	.hash_size      = RSC_HASHMAX,
-	.hash_table     = rsc_table,
-	.name	   = "auth.sptlrpc.context",
-	.cache_put      = rsc_put,
-	.cache_parse    = rsc_parse,
-	.match	  = rsc_match,
-	.init	   = rsc_init,
-	.update	 = update_rsc,
-	.alloc	  = rsc_alloc,
-};
-
-static struct rsc *rsc_lookup(struct rsc *item)
-{
-	struct cache_head *ch;
-	int		hash = rsc_hash(item);
-
-	ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash);
-	if (ch)
-		return container_of(ch, struct rsc, h);
-	else
-		return NULL;
-}
-
-static struct rsc *rsc_update(struct rsc *new, struct rsc *old)
-{
-	struct cache_head *ch;
-	int		hash = rsc_hash(new);
-
-	ch = sunrpc_cache_update(&rsc_cache, &new->h, &old->h, hash);
-	if (ch)
-		return container_of(ch, struct rsc, h);
-	else
-		return NULL;
-}
-
-#define COMPAT_RSC_PUT(item, cd)	cache_put((item), (cd))
-
-/****************************************
- * rsc cache flush		      *
- ****************************************/
-
-typedef int rsc_entry_match(struct rsc *rscp, long data);
-
-static void rsc_flush(rsc_entry_match *match, long data)
-{
-	struct cache_head **ch;
-	struct rsc *rscp;
-	int n;
-
-	write_lock(&rsc_cache.hash_lock);
-	for (n = 0; n < RSC_HASHMAX; n++) {
-		for (ch = &rsc_cache.hash_table[n]; *ch;) {
-			rscp = container_of(*ch, struct rsc, h);
-
-			if (!match(rscp, data)) {
-				ch = &((*ch)->next);
-				continue;
-			}
-
-			/* it seems simply set NEGATIVE doesn't work */
-			*ch = (*ch)->next;
-			rscp->h.next = NULL;
-			cache_get(&rscp->h);
-			set_bit(CACHE_NEGATIVE, &rscp->h.flags);
-			COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
-			rsc_cache.entries--;
-		}
-	}
-	write_unlock(&rsc_cache.hash_lock);
-}
-
-static int match_uid(struct rsc *rscp, long uid)
-{
-	if ((int) uid == -1)
-		return 1;
-	return ((int) rscp->ctx.gsc_uid == (int) uid);
-}
-
-static int match_target(struct rsc *rscp, long target)
-{
-	return (rscp->target == (struct obd_device *) target);
-}
-
-static inline void rsc_flush_uid(int uid)
-{
-	if (uid == -1)
-		CWARN("flush all gss contexts...\n");
-
-	rsc_flush(match_uid, (long) uid);
-}
-
-static inline void rsc_flush_target(struct obd_device *target)
-{
-	rsc_flush(match_target, (long) target);
-}
-
-void gss_secsvc_flush(struct obd_device *target)
-{
-	rsc_flush_target(target);
-}
-EXPORT_SYMBOL(gss_secsvc_flush);
-
-static struct rsc *gss_svc_searchbyctx(rawobj_t *handle)
-{
-	struct rsc  rsci;
-	struct rsc *found;
-
-	memset(&rsci, 0, sizeof(rsci));
-	if (rawobj_dup(&rsci.handle, handle))
-		return NULL;
-
-	found = rsc_lookup(&rsci);
-	rsc_free(&rsci);
-	if (!found)
-		return NULL;
-	if (cache_check(&rsc_cache, &found->h, NULL))
-		return NULL;
-	return found;
-}
-
-int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
-				   struct gss_sec *gsec,
-				   struct gss_cli_ctx *gctx)
-{
-	struct rsc      rsci, *rscp = NULL;
-	unsigned long   ctx_expiry;
-	__u32	   major;
-	int	     rc;
-
-	memset(&rsci, 0, sizeof(rsci));
-
-	if (rawobj_alloc(&rsci.handle, (char *) &gsec->gs_rvs_hdl,
-			 sizeof(gsec->gs_rvs_hdl)))
-		GOTO(out, rc = -ENOMEM);
-
-	rscp = rsc_lookup(&rsci);
-	if (rscp == NULL)
-		GOTO(out, rc = -ENOMEM);
-
-	major = lgss_copy_reverse_context(gctx->gc_mechctx,
-					  &rsci.ctx.gsc_mechctx);
-	if (major != GSS_S_COMPLETE)
-		GOTO(out, rc = -ENOMEM);
-
-	if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
-		CERROR("unable to get expire time, drop it\n");
-		GOTO(out, rc = -EINVAL);
-	}
-	rsci.h.expiry_time = (time_t) ctx_expiry;
-
-	if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0)
-		rsci.ctx.gsc_usr_mds = 1;
-	else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0)
-		rsci.ctx.gsc_usr_oss = 1;
-	else
-		rsci.ctx.gsc_usr_root = 1;
-
-	rscp = rsc_update(&rsci, rscp);
-	if (rscp == NULL)
-		GOTO(out, rc = -ENOMEM);
-
-	rscp->target = imp->imp_obd;
-	rawobj_dup(&gctx->gc_svc_handle, &rscp->handle);
-
-	CWARN("create reverse svc ctx %p to %s: idx "LPX64"\n",
-	      &rscp->ctx, obd2cli_tgt(imp->imp_obd), gsec->gs_rvs_hdl);
-	rc = 0;
-out:
-	if (rscp)
-		cache_put(&rscp->h, &rsc_cache);
-	rsc_free(&rsci);
-
-	if (rc)
-		CERROR("create reverse svc ctx: idx "LPX64", rc %d\n",
-		       gsec->gs_rvs_hdl, rc);
-	return rc;
-}
-
-int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle)
-{
-	const cfs_time_t	expire = 20;
-	struct rsc	     *rscp;
-
-	rscp = gss_svc_searchbyctx(handle);
-	if (rscp) {
-		CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n",
-		       &rscp->ctx, rscp);
-
-		rscp->h.expiry_time = cfs_time_current_sec() + expire;
-		COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
-	}
-	return 0;
-}
-
-int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx)
-{
-	struct rsc *rscp = container_of(ctx, struct rsc, ctx);
-
-	return rawobj_dup(handle, &rscp->handle);
-}
-
-int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq)
-{
-	struct rsc	     *rscp;
-
-	rscp = gss_svc_searchbyctx(handle);
-	if (rscp) {
-		CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n",
-		       &rscp->ctx, rscp, seq + 1);
-
-		rscp->ctx.gsc_rvs_seq = seq + 1;
-		COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
-	}
-	return 0;
-}
-
-static struct cache_deferred_req* cache_upcall_defer(struct cache_req *req)
-{
-	return NULL;
-}
-static struct cache_req cache_upcall_chandle = { cache_upcall_defer };
-
-int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
-			       struct gss_svc_reqctx *grctx,
-			       struct gss_wire_ctx *gw,
-			       struct obd_device *target,
-			       __u32 lustre_svc,
-			       rawobj_t *rvs_hdl,
-			       rawobj_t *in_token)
-{
-	struct ptlrpc_reply_state *rs;
-	struct rsc		*rsci = NULL;
-	struct rsi		*rsip = NULL, rsikey;
-	wait_queue_t	     wait;
-	int			replen = sizeof(struct ptlrpc_body);
-	struct gss_rep_header     *rephdr;
-	int			first_check = 1;
-	int			rc = SECSVC_DROP;
-
-	memset(&rsikey, 0, sizeof(rsikey));
-	rsikey.lustre_svc = lustre_svc;
-	rsikey.nid = (__u64) req->rq_peer.nid;
-
-	/* duplicate context handle. for INIT it always 0 */
-	if (rawobj_dup(&rsikey.in_handle, &gw->gw_handle)) {
-		CERROR("fail to dup context handle\n");
-		GOTO(out, rc);
-	}
-
-	if (rawobj_dup(&rsikey.in_token, in_token)) {
-		CERROR("can't duplicate token\n");
-		rawobj_free(&rsikey.in_handle);
-		GOTO(out, rc);
-	}
-
-	rsip = rsi_lookup(&rsikey);
-	rsi_free(&rsikey);
-	if (!rsip) {
-		CERROR("error in rsi_lookup.\n");
-
-		if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0))
-			rc = SECSVC_COMPLETE;
-
-		GOTO(out, rc);
-	}
-
-	cache_get(&rsip->h); /* take an extra ref */
-	init_waitqueue_head(&rsip->waitq);
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&rsip->waitq, &wait);
-
-cache_check:
-	/* Note each time cache_check() will drop a reference if return
-	 * non-zero. We hold an extra reference on initial rsip, but must
-	 * take care of following calls. */
-	rc = cache_check(&rsi_cache, &rsip->h, &cache_upcall_chandle);
-	switch (rc) {
-	case -EAGAIN: {
-		int valid;
-
-		if (first_check) {
-			first_check = 0;
-
-			read_lock(&rsi_cache.hash_lock);
-			valid = test_bit(CACHE_VALID, &rsip->h.flags);
-			if (valid == 0)
-				set_current_state(TASK_INTERRUPTIBLE);
-			read_unlock(&rsi_cache.hash_lock);
-
-			if (valid == 0)
-				schedule_timeout(GSS_SVC_UPCALL_TIMEOUT *
-						     HZ);
-
-			cache_get(&rsip->h);
-			goto cache_check;
-		}
-		CWARN("waited %ds timeout, drop\n", GSS_SVC_UPCALL_TIMEOUT);
-		break;
-	}
-	case -ENOENT:
-		CWARN("cache_check return ENOENT, drop\n");
-		break;
-	case 0:
-		/* if not the first check, we have to release the extra
-		 * reference we just added on it. */
-		if (!first_check)
-			cache_put(&rsip->h, &rsi_cache);
-		CDEBUG(D_SEC, "cache_check is good\n");
-		break;
-	}
-
-	remove_wait_queue(&rsip->waitq, &wait);
-	cache_put(&rsip->h, &rsi_cache);
-
-	if (rc)
-		GOTO(out, rc = SECSVC_DROP);
-
-	rc = SECSVC_DROP;
-	rsci = gss_svc_searchbyctx(&rsip->out_handle);
-	if (!rsci) {
-		CERROR("authentication failed\n");
-
-		if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0))
-			rc = SECSVC_COMPLETE;
-
-		GOTO(out, rc);
-	} else {
-		cache_get(&rsci->h);
-		grctx->src_ctx = &rsci->ctx;
-	}
-
-	if (rawobj_dup(&rsci->ctx.gsc_rvs_hdl, rvs_hdl)) {
-		CERROR("failed duplicate reverse handle\n");
-		GOTO(out, rc);
-	}
-
-	rsci->target = target;
-
-	CDEBUG(D_SEC, "server create rsc %p(%u->%s)\n",
-	       rsci, rsci->ctx.gsc_uid, libcfs_nid2str(req->rq_peer.nid));
-
-	if (rsip->out_handle.len > PTLRPC_GSS_MAX_HANDLE_SIZE) {
-		CERROR("handle size %u too large\n", rsip->out_handle.len);
-		GOTO(out, rc = SECSVC_DROP);
-	}
-
-	grctx->src_init = 1;
-	grctx->src_reserve_len = cfs_size_round4(rsip->out_token.len);
-
-	rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0);
-	if (rc) {
-		CERROR("failed to pack reply: %d\n", rc);
-		GOTO(out, rc = SECSVC_DROP);
-	}
-
-	rs = req->rq_reply_state;
-	LASSERT(rs->rs_repbuf->lm_bufcount == 3);
-	LASSERT(rs->rs_repbuf->lm_buflens[0] >=
-		sizeof(*rephdr) + rsip->out_handle.len);
-	LASSERT(rs->rs_repbuf->lm_buflens[2] >= rsip->out_token.len);
-
-	rephdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
-	rephdr->gh_version = PTLRPC_GSS_VERSION;
-	rephdr->gh_flags = 0;
-	rephdr->gh_proc = PTLRPC_GSS_PROC_ERR;
-	rephdr->gh_major = rsip->major_status;
-	rephdr->gh_minor = rsip->minor_status;
-	rephdr->gh_seqwin = GSS_SEQ_WIN;
-	rephdr->gh_handle.len = rsip->out_handle.len;
-	memcpy(rephdr->gh_handle.data, rsip->out_handle.data,
-	       rsip->out_handle.len);
-
-	memcpy(lustre_msg_buf(rs->rs_repbuf, 2, 0), rsip->out_token.data,
-	       rsip->out_token.len);
-
-	rs->rs_repdata_len = lustre_shrink_msg(rs->rs_repbuf, 2,
-					       rsip->out_token.len, 0);
-
-	rc = SECSVC_OK;
-
-out:
-	/* it looks like here we should put rsip also, but this mess up
-	 * with NFS cache mgmt code... FIXME */
-#if 0
-	if (rsip)
-		rsi_put(&rsip->h, &rsi_cache);
-#endif
-
-	if (rsci) {
-		/* if anything went wrong, we don't keep the context too */
-		if (rc != SECSVC_OK)
-			set_bit(CACHE_NEGATIVE, &rsci->h.flags);
-		else
-			CDEBUG(D_SEC, "create rsc with idx "LPX64"\n",
-			       gss_handle_to_u64(&rsci->handle));
-
-		COMPAT_RSC_PUT(&rsci->h, &rsc_cache);
-	}
-	return rc;
-}
-
-struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
-					   struct gss_wire_ctx *gw)
-{
-	struct rsc *rsc;
-
-	rsc = gss_svc_searchbyctx(&gw->gw_handle);
-	if (!rsc) {
-		CWARN("Invalid gss ctx idx "LPX64" from %s\n",
-		      gss_handle_to_u64(&gw->gw_handle),
-		      libcfs_nid2str(req->rq_peer.nid));
-		return NULL;
-	}
-
-	return &rsc->ctx;
-}
-
-void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx)
-{
-	struct rsc *rsc = container_of(ctx, struct rsc, ctx);
-
-	COMPAT_RSC_PUT(&rsc->h, &rsc_cache);
-}
-
-void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx)
-{
-	struct rsc *rsc = container_of(ctx, struct rsc, ctx);
-
-	/* can't be found */
-	set_bit(CACHE_NEGATIVE, &rsc->h.flags);
-	/* to be removed at next scan */
-	rsc->h.expiry_time = 1;
-}
-
-int __init gss_init_svc_upcall(void)
-{
-	int     i;
-
-	spin_lock_init(&__ctx_index_lock);
-	/*
-	 * this helps reducing context index confliction. after server reboot,
-	 * conflicting request from clients might be filtered out by initial
-	 * sequence number checking, thus no chance to sent error notification
-	 * back to clients.
-	 */
-	cfs_get_random_bytes(&__ctx_index, sizeof(__ctx_index));
-
-
-	cache_register(&rsi_cache);
-	cache_register(&rsc_cache);
-
-	/* FIXME this looks stupid. we intend to give lsvcgssd a chance to open
-	 * the init upcall channel, otherwise there's big chance that the first
-	 * upcall issued before the channel be opened thus nfsv4 cache code will
-	 * drop the request direclty, thus lead to unnecessary recovery time.
-	 * here we wait at maximum 1.5 seconds. */
-	for (i = 0; i < 6; i++) {
-		if (atomic_read(&rsi_cache.readers) > 0)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		LASSERT(HZ >= 4);
-		schedule_timeout(HZ / 4);
-	}
-
-	if (atomic_read(&rsi_cache.readers) == 0)
-		CWARN("Init channel is not opened by lsvcgssd, following "
-		      "request might be dropped until lsvcgssd is active\n");
-
-	return 0;
-}
-
-void __exit gss_exit_svc_upcall(void)
-{
-	cache_purge(&rsi_cache);
-	cache_unregister(&rsi_cache);
-
-	cache_purge(&rsc_cache);
-	cache_unregister(&rsc_cache);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,220 +0,0 @@
-/*
- * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lprocfs_status.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-static struct proc_dir_entry *gss_proc_root = NULL;
-static struct proc_dir_entry *gss_proc_lk = NULL;
-
-/*
- * statistic of "out-of-sequence-window"
- */
-static struct {
-	spinlock_t  oos_lock;
-	atomic_t    oos_cli_count;       /* client occurrence */
-	int	     oos_cli_behind;      /* client max seqs behind */
-	atomic_t    oos_svc_replay[3];   /* server replay detected */
-	atomic_t    oos_svc_pass[3];     /* server verified ok */
-} gss_stat_oos = {
-	.oos_cli_count  = ATOMIC_INIT(0),
-	.oos_cli_behind = 0,
-	.oos_svc_replay = { ATOMIC_INIT(0), },
-	.oos_svc_pass   = { ATOMIC_INIT(0), },
-};
-
-void gss_stat_oos_record_cli(int behind)
-{
-	atomic_inc(&gss_stat_oos.oos_cli_count);
-
-	spin_lock(&gss_stat_oos.oos_lock);
-	if (behind > gss_stat_oos.oos_cli_behind)
-		gss_stat_oos.oos_cli_behind = behind;
-	spin_unlock(&gss_stat_oos.oos_lock);
-}
-
-void gss_stat_oos_record_svc(int phase, int replay)
-{
-	LASSERT(phase >= 0 && phase <= 2);
-
-	if (replay)
-		atomic_inc(&gss_stat_oos.oos_svc_replay[phase]);
-	else
-		atomic_inc(&gss_stat_oos.oos_svc_pass[phase]);
-}
-
-static int gss_proc_oos_seq_show(struct seq_file *m, void *v)
-{
-	return seq_printf(m,
-			"seqwin:		%u\n"
-			"backwin:	       %u\n"
-			"client fall behind seqwin\n"
-			"  occurrence:	  %d\n"
-			"  max seq behind:      %d\n"
-			"server replay detected:\n"
-			"  phase 0:	     %d\n"
-			"  phase 1:	     %d\n"
-			"  phase 2:	     %d\n"
-			"server verify ok:\n"
-			"  phase 2:	     %d\n",
-			GSS_SEQ_WIN_MAIN,
-			GSS_SEQ_WIN_BACK,
-			atomic_read(&gss_stat_oos.oos_cli_count),
-			gss_stat_oos.oos_cli_behind,
-			atomic_read(&gss_stat_oos.oos_svc_replay[0]),
-			atomic_read(&gss_stat_oos.oos_svc_replay[1]),
-			atomic_read(&gss_stat_oos.oos_svc_replay[2]),
-			atomic_read(&gss_stat_oos.oos_svc_pass[2]));
-}
-LPROC_SEQ_FOPS_RO(gss_proc_oos);
-
-static int gss_proc_write_secinit(struct file *file, const char *buffer,
-				  size_t count, off_t *off)
-{
-	int rc;
-
-	rc = gss_do_ctx_init_rpc((char *) buffer, count);
-	if (rc) {
-		LASSERT(rc < 0);
-		return rc;
-	}
-
-	return count;
-}
-
-static const struct file_operations gss_proc_secinit = {
-	.write = gss_proc_write_secinit,
-};
-
-static struct lprocfs_vars gss_lprocfs_vars[] = {
-	{ "replays", &gss_proc_oos_fops },
-	{ "init_channel", &gss_proc_secinit, NULL, 0222 },
-	{ NULL }
-};
-
-/*
- * for userspace helper lgss_keyring.
- *
- * debug_level: [0, 4], defined in utils/gss/lgss_utils.h
- */
-static int gss_lk_debug_level = 1;
-
-static int gss_lk_proc_dl_seq_show(struct seq_file *m, void *v)
-{
-	return seq_printf(m, "%u\n", gss_lk_debug_level);
-}
-
-static int gss_lk_proc_dl_seq_write(struct file *file, const char *buffer,
-				    size_t count, off_t *off)
-{
-	int     val, rc;
-
-	rc = lprocfs_write_helper(buffer, count, &val);
-	if (rc < 0)
-		return rc;
-
-	if (val < 0 || val > 4)
-		return -ERANGE;
-
-	gss_lk_debug_level = val;
-	return count;
-}
-LPROC_SEQ_FOPS(gss_lk_proc_dl);
-
-static struct lprocfs_vars gss_lk_lprocfs_vars[] = {
-	{ "debug_level", &gss_lk_proc_dl_fops },
-	{ NULL }
-};
-
-void gss_exit_lproc(void)
-{
-	if (gss_proc_lk) {
-		lprocfs_remove(&gss_proc_lk);
-		gss_proc_lk = NULL;
-	}
-
-	if (gss_proc_root) {
-		lprocfs_remove(&gss_proc_root);
-		gss_proc_root = NULL;
-	}
-}
-
-int gss_init_lproc(void)
-{
-	int     rc;
-
-	spin_lock_init(&gss_stat_oos.oos_lock);
-
-	gss_proc_root = lprocfs_register("gss", sptlrpc_proc_root,
-					 gss_lprocfs_vars, NULL);
-	if (IS_ERR(gss_proc_root)) {
-		rc = PTR_ERR(gss_proc_root);
-		gss_proc_root = NULL;
-		GOTO(err_out, rc);
-	}
-
-	gss_proc_lk = lprocfs_register("lgss_keyring", gss_proc_root,
-				       gss_lk_lprocfs_vars, NULL);
-	if (IS_ERR(gss_proc_lk)) {
-		rc = PTR_ERR(gss_proc_lk);
-		gss_proc_lk = NULL;
-		GOTO(err_out, rc);
-	}
-
-	return 0;
-
-err_out:
-	CERROR("failed to initialize gss lproc entries: %d\n", rc);
-	gss_exit_lproc();
-	return rc;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-obj-$(CONFIG_LUSTRE_FS) := ptlrpc_gss.o
-
-ptlrpc_gss-y := sec_gss.o gss_bulk.o gss_cli_upcall.o gss_svc_upcall.o	\
-		gss_rawobj.o lproc_gss.o gss_generic_token.o		\
-		gss_mech_switch.o gss_krb5_mech.o
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2889 +0,0 @@
-/*
- * Modifications for Lustre
- *
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- *
- * Author: Eric Mei <ericm@clusterfs.com>
- */
-
-/*
- * linux/net/sunrpc/auth_gss.c
- *
- * RPCSEC_GSS client authentication.
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Dug Song       <dugsong@monkey.org>
- *  Andy Adamson   <andros@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-#include <asm/atomic.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <obd_cksum.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_sec.h>
-
-#include "gss_err.h"
-#include "gss_internal.h"
-#include "gss_api.h"
-
-#include <linux/crypto.h>
-#include <linux/crc32.h>
-
-/*
- * early reply have fixed size, respectively in privacy and integrity mode.
- * so we calculate them only once.
- */
-static int gss_at_reply_off_integ;
-static int gss_at_reply_off_priv;
-
-
-static inline int msg_last_segidx(struct lustre_msg *msg)
-{
-	LASSERT(msg->lm_bufcount > 0);
-	return msg->lm_bufcount - 1;
-}
-static inline int msg_last_seglen(struct lustre_msg *msg)
-{
-	return msg->lm_buflens[msg_last_segidx(msg)];
-}
-
-/********************************************
- * wire data swabber			*
- ********************************************/
-
-static
-void gss_header_swabber(struct gss_header *ghdr)
-{
-	__swab32s(&ghdr->gh_flags);
-	__swab32s(&ghdr->gh_proc);
-	__swab32s(&ghdr->gh_seq);
-	__swab32s(&ghdr->gh_svc);
-	__swab32s(&ghdr->gh_pad1);
-	__swab32s(&ghdr->gh_handle.len);
-}
-
-struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment,
-				   int swabbed)
-{
-	struct gss_header *ghdr;
-
-	ghdr = lustre_msg_buf(msg, segment, sizeof(*ghdr));
-	if (ghdr == NULL)
-		return NULL;
-
-	if (swabbed)
-		gss_header_swabber(ghdr);
-
-	if (sizeof(*ghdr) + ghdr->gh_handle.len > msg->lm_buflens[segment]) {
-		CERROR("gss header has length %d, now %u received\n",
-		       (int) sizeof(*ghdr) + ghdr->gh_handle.len,
-		       msg->lm_buflens[segment]);
-		return NULL;
-	}
-
-	return ghdr;
-}
-
-#if 0
-static
-void gss_netobj_swabber(netobj_t *obj)
-{
-	__swab32s(&obj->len);
-}
-
-netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment)
-{
-	netobj_t  *obj;
-
-	obj = lustre_swab_buf(msg, segment, sizeof(*obj), gss_netobj_swabber);
-	if (obj && sizeof(*obj) + obj->len > msg->lm_buflens[segment]) {
-		CERROR("netobj require length %u but only %u received\n",
-		       (unsigned int) sizeof(*obj) + obj->len,
-		       msg->lm_buflens[segment]);
-		return NULL;
-	}
-
-	return obj;
-}
-#endif
-
-/*
- * payload should be obtained from mechanism. but currently since we
- * only support kerberos, we could simply use fixed value.
- * krb5 "meta" data:
- *  - krb5 header:      16
- *  - krb5 checksum:    20
- *
- * for privacy mode, payload also include the cipher text which has the same
- * size as plain text, plus possible confounder, padding both at maximum cipher
- * block size.
- */
-#define GSS_KRB5_INTEG_MAX_PAYLOAD      (40)
-
-static inline
-int gss_mech_payload(struct gss_ctx *mechctx, int msgsize, int privacy)
-{
-	if (privacy)
-		return GSS_KRB5_INTEG_MAX_PAYLOAD + 16 + 16 + 16 + msgsize;
-	else
-		return GSS_KRB5_INTEG_MAX_PAYLOAD;
-}
-
-/*
- * return signature size, otherwise < 0 to indicate error
- */
-static int gss_sign_msg(struct lustre_msg *msg,
-			struct gss_ctx *mechctx,
-			enum lustre_sec_part sp,
-			__u32 flags, __u32 proc, __u32 seq, __u32 svc,
-			rawobj_t *handle)
-{
-	struct gss_header      *ghdr;
-	rawobj_t		text[4], mic;
-	int		     textcnt, max_textcnt, mic_idx;
-	__u32		   major;
-
-	LASSERT(msg->lm_bufcount >= 2);
-
-	/* gss hdr */
-	LASSERT(msg->lm_buflens[0] >=
-		sizeof(*ghdr) + (handle ? handle->len : 0));
-	ghdr = lustre_msg_buf(msg, 0, 0);
-
-	ghdr->gh_version = PTLRPC_GSS_VERSION;
-	ghdr->gh_sp = (__u8) sp;
-	ghdr->gh_flags = flags;
-	ghdr->gh_proc = proc;
-	ghdr->gh_seq = seq;
-	ghdr->gh_svc = svc;
-	if (!handle) {
-		/* fill in a fake one */
-		ghdr->gh_handle.len = 0;
-	} else {
-		ghdr->gh_handle.len = handle->len;
-		memcpy(ghdr->gh_handle.data, handle->data, handle->len);
-	}
-
-	/* no actual signature for null mode */
-	if (svc == SPTLRPC_SVC_NULL)
-		return lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
-
-	/* MIC */
-	mic_idx = msg_last_segidx(msg);
-	max_textcnt = (svc == SPTLRPC_SVC_AUTH) ? 1 : mic_idx;
-
-	for (textcnt = 0; textcnt < max_textcnt; textcnt++) {
-		text[textcnt].len = msg->lm_buflens[textcnt];
-		text[textcnt].data = lustre_msg_buf(msg, textcnt, 0);
-	}
-
-	mic.len = msg->lm_buflens[mic_idx];
-	mic.data = lustre_msg_buf(msg, mic_idx, 0);
-
-	major = lgss_get_mic(mechctx, textcnt, text, 0, NULL, &mic);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("fail to generate MIC: %08x\n", major);
-		return -EPERM;
-	}
-	LASSERT(mic.len <= msg->lm_buflens[mic_idx]);
-
-	return lustre_shrink_msg(msg, mic_idx, mic.len, 0);
-}
-
-/*
- * return gss error
- */
-static
-__u32 gss_verify_msg(struct lustre_msg *msg,
-		     struct gss_ctx *mechctx,
-		     __u32 svc)
-{
-	rawobj_t	text[4], mic;
-	int	     textcnt, max_textcnt;
-	int	     mic_idx;
-	__u32	   major;
-
-	LASSERT(msg->lm_bufcount >= 2);
-
-	if (svc == SPTLRPC_SVC_NULL)
-		return GSS_S_COMPLETE;
-
-	mic_idx = msg_last_segidx(msg);
-	max_textcnt = (svc == SPTLRPC_SVC_AUTH) ? 1 : mic_idx;
-
-	for (textcnt = 0; textcnt < max_textcnt; textcnt++) {
-		text[textcnt].len = msg->lm_buflens[textcnt];
-		text[textcnt].data = lustre_msg_buf(msg, textcnt, 0);
-	}
-
-	mic.len = msg->lm_buflens[mic_idx];
-	mic.data = lustre_msg_buf(msg, mic_idx, 0);
-
-	major = lgss_verify_mic(mechctx, textcnt, text, 0, NULL, &mic);
-	if (major != GSS_S_COMPLETE)
-		CERROR("mic verify error: %08x\n", major);
-
-	return major;
-}
-
-/*
- * return gss error code
- */
-static
-__u32 gss_unseal_msg(struct gss_ctx *mechctx,
-		   struct lustre_msg *msgbuf,
-		   int *msg_len, int msgbuf_len)
-{
-	rawobj_t		 clear_obj, hdrobj, token;
-	__u8		    *clear_buf;
-	int		      clear_buflen;
-	__u32		    major;
-
-	if (msgbuf->lm_bufcount != 2) {
-		CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount);
-		return GSS_S_FAILURE;
-	}
-
-	/* allocate a temporary clear text buffer, same sized as token,
-	 * we assume the final clear text size <= token size */
-	clear_buflen = lustre_msg_buflen(msgbuf, 1);
-	OBD_ALLOC_LARGE(clear_buf, clear_buflen);
-	if (!clear_buf)
-		return GSS_S_FAILURE;
-
-	/* buffer objects */
-	hdrobj.len = lustre_msg_buflen(msgbuf, 0);
-	hdrobj.data = lustre_msg_buf(msgbuf, 0, 0);
-	token.len = lustre_msg_buflen(msgbuf, 1);
-	token.data = lustre_msg_buf(msgbuf, 1, 0);
-	clear_obj.len = clear_buflen;
-	clear_obj.data = clear_buf;
-
-	major = lgss_unwrap(mechctx, &hdrobj, &token, &clear_obj);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("unwrap message error: %08x\n", major);
-		GOTO(out_free, major = GSS_S_FAILURE);
-	}
-	LASSERT(clear_obj.len <= clear_buflen);
-	LASSERT(clear_obj.len <= msgbuf_len);
-
-	/* now the decrypted message */
-	memcpy(msgbuf, clear_obj.data, clear_obj.len);
-	*msg_len = clear_obj.len;
-
-	major = GSS_S_COMPLETE;
-out_free:
-	OBD_FREE_LARGE(clear_buf, clear_buflen);
-	return major;
-}
-
-/********************************************
- * gss client context manipulation helpers  *
- ********************************************/
-
-int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx)
-{
-	LASSERT(atomic_read(&ctx->cc_refcount));
-
-	if (!test_and_set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags)) {
-		if (!ctx->cc_early_expire)
-			clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
-
-		CWARN("ctx %p(%u->%s) get expired: %lu(%+lds)\n",
-		      ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
-		      ctx->cc_expire,
-		      ctx->cc_expire == 0 ? 0 :
-		      cfs_time_sub(ctx->cc_expire, cfs_time_current_sec()));
-
-		sptlrpc_cli_ctx_wakeup(ctx);
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- * return 1 if the context is dead.
- */
-int cli_ctx_check_death(struct ptlrpc_cli_ctx *ctx)
-{
-	if (unlikely(cli_ctx_is_dead(ctx)))
-		return 1;
-
-	/* expire is 0 means never expire. a newly created gss context
-	 * which during upcall may has 0 expiration */
-	if (ctx->cc_expire == 0)
-		return 0;
-
-	/* check real expiration */
-	if (cfs_time_after(ctx->cc_expire, cfs_time_current_sec()))
-		return 0;
-
-	cli_ctx_expire(ctx);
-	return 1;
-}
-
-void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx)
-{
-	struct ptlrpc_cli_ctx  *ctx = &gctx->gc_base;
-	unsigned long	   ctx_expiry;
-
-	if (lgss_inquire_context(gctx->gc_mechctx, &ctx_expiry)) {
-		CERROR("ctx %p(%u): unable to inquire, expire it now\n",
-		       gctx, ctx->cc_vcred.vc_uid);
-		ctx_expiry = 1; /* make it expired now */
-	}
-
-	ctx->cc_expire = gss_round_ctx_expiry(ctx_expiry,
-					      ctx->cc_sec->ps_flvr.sf_flags);
-
-	/* At this point this ctx might have been marked as dead by
-	 * someone else, in which case nobody will make further use
-	 * of it. we don't care, and mark it UPTODATE will help
-	 * destroying server side context when it be destroyed. */
-	set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
-
-	if (sec_is_reverse(ctx->cc_sec)) {
-		CWARN("server installed reverse ctx %p idx "LPX64", "
-		      "expiry %lu(%+lds)\n", ctx,
-		      gss_handle_to_u64(&gctx->gc_handle),
-		      ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec());
-	} else {
-		CWARN("client refreshed ctx %p idx "LPX64" (%u->%s), "
-		      "expiry %lu(%+lds)\n", ctx,
-		      gss_handle_to_u64(&gctx->gc_handle),
-		      ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
-		      ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec());
-
-		/* install reverse svc ctx for root context */
-		if (ctx->cc_vcred.vc_uid == 0)
-			gss_sec_install_rctx(ctx->cc_sec->ps_import,
-					     ctx->cc_sec, ctx);
-	}
-
-	sptlrpc_cli_ctx_wakeup(ctx);
-}
-
-static void gss_cli_ctx_finalize(struct gss_cli_ctx *gctx)
-{
-	LASSERT(gctx->gc_base.cc_sec);
-
-	if (gctx->gc_mechctx) {
-		lgss_delete_sec_context(&gctx->gc_mechctx);
-		gctx->gc_mechctx = NULL;
-	}
-
-	if (!rawobj_empty(&gctx->gc_svc_handle)) {
-		/* forward ctx: mark buddy reverse svcctx soon-expire. */
-		if (!sec_is_reverse(gctx->gc_base.cc_sec) &&
-		    !rawobj_empty(&gctx->gc_svc_handle))
-			gss_svc_upcall_expire_rvs_ctx(&gctx->gc_svc_handle);
-
-		rawobj_free(&gctx->gc_svc_handle);
-	}
-
-	rawobj_free(&gctx->gc_handle);
-}
-
-/*
- * Based on sequence number algorithm as specified in RFC 2203.
- *
- * modified for our own problem: arriving request has valid sequence number,
- * but unwrapping request might cost a long time, after that its sequence
- * are not valid anymore (fall behind the window). It rarely happen, mostly
- * under extreme load.
- *
- * note we should not check sequence before verify the integrity of incoming
- * request, because just one attacking request with high sequence number might
- * cause all following request be dropped.
- *
- * so here we use a multi-phase approach: prepare 2 sequence windows,
- * "main window" for normal sequence and "back window" for fall behind sequence.
- * and 3-phase checking mechanism:
- *  0 - before integrity verification, perform a initial sequence checking in
- *      main window, which only try and don't actually set any bits. if the
- *      sequence is high above the window or fit in the window and the bit
- *      is 0, then accept and proceed to integrity verification. otherwise
- *      reject this sequence.
- *  1 - after integrity verification, check in main window again. if this
- *      sequence is high above the window or fit in the window and the bit
- *      is 0, then set the bit and accept; if it fit in the window but bit
- *      already set, then reject; if it fall behind the window, then proceed
- *      to phase 2.
- *  2 - check in back window. if it is high above the window or fit in the
- *      window and the bit is 0, then set the bit and accept. otherwise reject.
- *
- * return value:
- *   1: looks like a replay
- *   0: is ok
- *  -1: is a replay
- *
- * note phase 0 is necessary, because otherwise replay attacking request of
- * sequence which between the 2 windows can't be detected.
- *
- * this mechanism can't totally solve the problem, but could help much less
- * number of valid requests be dropped.
- */
-static
-int gss_do_check_seq(unsigned long *window, __u32 win_size, __u32 *max_seq,
-		     __u32 seq_num, int phase)
-{
-	LASSERT(phase >= 0 && phase <= 2);
-
-	if (seq_num > *max_seq) {
-		/*
-		 * 1. high above the window
-		 */
-		if (phase == 0)
-			return 0;
-
-		if (seq_num >= *max_seq + win_size) {
-			memset(window, 0, win_size / 8);
-			*max_seq = seq_num;
-		} else {
-			while (*max_seq < seq_num) {
-				(*max_seq)++;
-				__clear_bit((*max_seq) % win_size, window);
-			}
-		}
-		__set_bit(seq_num % win_size, window);
-	} else if (seq_num + win_size <= *max_seq) {
-		/*
-		 * 2. low behind the window
-		 */
-		if (phase == 0 || phase == 2)
-			goto replay;
-
-		CWARN("seq %u is %u behind (size %d), check backup window\n",
-		      seq_num, *max_seq - win_size - seq_num, win_size);
-		return 1;
-	} else {
-		/*
-		 * 3. fit into the window
-		 */
-		switch (phase) {
-		case 0:
-			if (test_bit(seq_num % win_size, window))
-				goto replay;
-			break;
-		case 1:
-		case 2:
-		     if (__test_and_set_bit(seq_num % win_size, window))
-				goto replay;
-			break;
-		}
-	}
-
-	return 0;
-
-replay:
-	CERROR("seq %u (%s %s window) is a replay: max %u, winsize %d\n",
-	       seq_num,
-	       seq_num + win_size > *max_seq ? "in" : "behind",
-	       phase == 2 ? "backup " : "main",
-	       *max_seq, win_size);
-	return -1;
-}
-
-/*
- * Based on sequence number algorithm as specified in RFC 2203.
- *
- * if @set == 0: initial check, don't set any bit in window
- * if @sec == 1: final check, set bit in window
- */
-int gss_check_seq_num(struct gss_svc_seq_data *ssd, __u32 seq_num, int set)
-{
-	int rc = 0;
-
-	spin_lock(&ssd->ssd_lock);
-
-	if (set == 0) {
-		/*
-		 * phase 0 testing
-		 */
-		rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN,
-				      &ssd->ssd_max_main, seq_num, 0);
-		if (unlikely(rc))
-			gss_stat_oos_record_svc(0, 1);
-	} else {
-		/*
-		 * phase 1 checking main window
-		 */
-		rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN,
-				      &ssd->ssd_max_main, seq_num, 1);
-		switch (rc) {
-		case -1:
-			gss_stat_oos_record_svc(1, 1);
-			/* fall through */
-		case 0:
-			goto exit;
-		}
-		/*
-		 * phase 2 checking back window
-		 */
-		rc = gss_do_check_seq(ssd->ssd_win_back, GSS_SEQ_WIN_BACK,
-				      &ssd->ssd_max_back, seq_num, 2);
-		if (rc)
-			gss_stat_oos_record_svc(2, 1);
-		else
-			gss_stat_oos_record_svc(2, 0);
-	}
-exit:
-	spin_unlock(&ssd->ssd_lock);
-	return rc;
-}
-
-/***************************************
- * cred APIs			   *
- ***************************************/
-
-static inline int gss_cli_payload(struct ptlrpc_cli_ctx *ctx,
-				  int msgsize, int privacy)
-{
-	return gss_mech_payload(NULL, msgsize, privacy);
-}
-
-static int gss_cli_bulk_payload(struct ptlrpc_cli_ctx *ctx,
-				struct sptlrpc_flavor *flvr,
-				int reply, int read)
-{
-	int     payload = sizeof(struct ptlrpc_bulk_sec_desc);
-
-	LASSERT(SPTLRPC_FLVR_BULK_TYPE(flvr->sf_rpc) == SPTLRPC_BULK_DEFAULT);
-
-	if ((!reply && !read) || (reply && read)) {
-		switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) {
-		case SPTLRPC_BULK_SVC_NULL:
-			break;
-		case SPTLRPC_BULK_SVC_INTG:
-			payload += gss_cli_payload(ctx, 0, 0);
-			break;
-		case SPTLRPC_BULK_SVC_PRIV:
-			payload += gss_cli_payload(ctx, 0, 1);
-			break;
-		case SPTLRPC_BULK_SVC_AUTH:
-		default:
-			LBUG();
-		}
-	}
-
-	return payload;
-}
-
-int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred)
-{
-	return (ctx->cc_vcred.vc_uid == vcred->vc_uid);
-}
-
-void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize)
-{
-	buf[0] = '\0';
-
-	if (flags & PTLRPC_CTX_NEW)
-		strncat(buf, "new,", bufsize);
-	if (flags & PTLRPC_CTX_UPTODATE)
-		strncat(buf, "uptodate,", bufsize);
-	if (flags & PTLRPC_CTX_DEAD)
-		strncat(buf, "dead,", bufsize);
-	if (flags & PTLRPC_CTX_ERROR)
-		strncat(buf, "error,", bufsize);
-	if (flags & PTLRPC_CTX_CACHED)
-		strncat(buf, "cached,", bufsize);
-	if (flags & PTLRPC_CTX_ETERNAL)
-		strncat(buf, "eternal,", bufsize);
-	if (buf[0] == '\0')
-		strncat(buf, "-,", bufsize);
-
-	buf[strlen(buf) - 1] = '\0';
-}
-
-int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
-		     struct ptlrpc_request *req)
-{
-	struct gss_cli_ctx      *gctx = ctx2gctx(ctx);
-	__u32		    flags = 0, seq, svc;
-	int		      rc;
-
-	LASSERT(req->rq_reqbuf);
-	LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
-	LASSERT(req->rq_cli_ctx == ctx);
-
-	/* nothing to do for context negotiation RPCs */
-	if (req->rq_ctx_init)
-		return 0;
-
-	svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-	if (req->rq_pack_bulk)
-		flags |= LUSTRE_GSS_PACK_BULK;
-	if (req->rq_pack_udesc)
-		flags |= LUSTRE_GSS_PACK_USER;
-
-redo:
-	seq = atomic_inc_return(&gctx->gc_seq);
-
-	rc = gss_sign_msg(req->rq_reqbuf, gctx->gc_mechctx,
-			  ctx->cc_sec->ps_part,
-			  flags, gctx->gc_proc, seq, svc,
-			  &gctx->gc_handle);
-	if (rc < 0)
-		return rc;
-
-	/* gss_sign_msg() msg might take long time to finish, in which period
-	 * more rpcs could be wrapped up and sent out. if we found too many
-	 * of them we should repack this rpc, because sent it too late might
-	 * lead to the sequence number fall behind the window on server and
-	 * be dropped. also applies to gss_cli_ctx_seal().
-	 *
-	 * Note: null mode doesn't check sequence number. */
-	if (svc != SPTLRPC_SVC_NULL &&
-	    atomic_read(&gctx->gc_seq) - seq > GSS_SEQ_REPACK_THRESHOLD) {
-		int behind = atomic_read(&gctx->gc_seq) - seq;
-
-		gss_stat_oos_record_cli(behind);
-		CWARN("req %p: %u behind, retry signing\n", req, behind);
-		goto redo;
-	}
-
-	req->rq_reqdata_len = rc;
-	return 0;
-}
-
-static
-int gss_cli_ctx_handle_err_notify(struct ptlrpc_cli_ctx *ctx,
-				  struct ptlrpc_request *req,
-				  struct gss_header *ghdr)
-{
-	struct gss_err_header *errhdr;
-	int rc;
-
-	LASSERT(ghdr->gh_proc == PTLRPC_GSS_PROC_ERR);
-
-	errhdr = (struct gss_err_header *) ghdr;
-
-	CWARN("req x"LPU64"/t"LPU64", ctx %p idx "LPX64"(%u->%s): "
-	      "%sserver respond (%08x/%08x)\n",
-	      req->rq_xid, req->rq_transno, ctx,
-	      gss_handle_to_u64(&ctx2gctx(ctx)->gc_handle),
-	      ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
-	      sec_is_reverse(ctx->cc_sec) ? "reverse" : "",
-	      errhdr->gh_major, errhdr->gh_minor);
-
-	/* context fini rpc, let it failed */
-	if (req->rq_ctx_fini) {
-		CWARN("context fini rpc failed\n");
-		return -EINVAL;
-	}
-
-	/* reverse sec, just return error, don't expire this ctx because it's
-	 * crucial to callback rpcs. note if the callback rpc failed because
-	 * of bit flip during network transfer, the client will be evicted
-	 * directly. so more gracefully we probably want let it retry for
-	 * number of times. */
-	if (sec_is_reverse(ctx->cc_sec))
-		return -EINVAL;
-
-	if (errhdr->gh_major != GSS_S_NO_CONTEXT &&
-	    errhdr->gh_major != GSS_S_BAD_SIG)
-		return -EACCES;
-
-	/* server return NO_CONTEXT might be caused by context expire
-	 * or server reboot/failover. we try to refresh a new ctx which
-	 * be transparent to upper layer.
-	 *
-	 * In some cases, our gss handle is possible to be incidentally
-	 * identical to another handle since the handle itself is not
-	 * fully random. In krb5 case, the GSS_S_BAD_SIG will be
-	 * returned, maybe other gss error for other mechanism.
-	 *
-	 * if we add new mechanism, make sure the correct error are
-	 * returned in this case. */
-	CWARN("%s: server might lost the context, retrying\n",
-	      errhdr->gh_major == GSS_S_NO_CONTEXT ?  "NO_CONTEXT" : "BAD_SIG");
-
-	sptlrpc_cli_ctx_expire(ctx);
-
-	/* we need replace the ctx right here, otherwise during
-	 * resent we'll hit the logic in sptlrpc_req_refresh_ctx()
-	 * which keep the ctx with RESEND flag, thus we'll never
-	 * get rid of this ctx. */
-	rc = sptlrpc_req_replace_dead_ctx(req);
-	if (rc == 0)
-		req->rq_resend = 1;
-
-	return rc;
-}
-
-int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
-		       struct ptlrpc_request *req)
-{
-	struct gss_cli_ctx     *gctx;
-	struct gss_header      *ghdr, *reqhdr;
-	struct lustre_msg      *msg = req->rq_repdata;
-	__u32		   major;
-	int		     pack_bulk, swabbed, rc = 0;
-
-	LASSERT(req->rq_cli_ctx == ctx);
-	LASSERT(msg);
-
-	gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-
-	/* special case for context negotiation, rq_repmsg/rq_replen actually
-	 * are not used currently. but early reply always be treated normally */
-	if (req->rq_ctx_init && !req->rq_early) {
-		req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
-		req->rq_replen = msg->lm_buflens[1];
-		return 0;
-	}
-
-	if (msg->lm_bufcount < 2 || msg->lm_bufcount > 4) {
-		CERROR("unexpected bufcount %u\n", msg->lm_bufcount);
-		return -EPROTO;
-	}
-
-	swabbed = ptlrpc_rep_need_swab(req);
-
-	ghdr = gss_swab_header(msg, 0, swabbed);
-	if (ghdr == NULL) {
-		CERROR("can't decode gss header\n");
-		return -EPROTO;
-	}
-
-	/* sanity checks */
-	reqhdr = lustre_msg_buf(msg, 0, sizeof(*reqhdr));
-	LASSERT(reqhdr);
-
-	if (ghdr->gh_version != reqhdr->gh_version) {
-		CERROR("gss version %u mismatch, expect %u\n",
-		       ghdr->gh_version, reqhdr->gh_version);
-		return -EPROTO;
-	}
-
-	switch (ghdr->gh_proc) {
-	case PTLRPC_GSS_PROC_DATA:
-		pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK;
-
-		if (!req->rq_early &&
-		    !equi(req->rq_pack_bulk == 1, pack_bulk)) {
-			CERROR("%s bulk flag in reply\n",
-			       req->rq_pack_bulk ? "missing" : "unexpected");
-			return -EPROTO;
-		}
-
-		if (ghdr->gh_seq != reqhdr->gh_seq) {
-			CERROR("seqnum %u mismatch, expect %u\n",
-			       ghdr->gh_seq, reqhdr->gh_seq);
-			return -EPROTO;
-		}
-
-		if (ghdr->gh_svc != reqhdr->gh_svc) {
-			CERROR("svc %u mismatch, expect %u\n",
-			       ghdr->gh_svc, reqhdr->gh_svc);
-			return -EPROTO;
-		}
-
-		if (swabbed)
-			gss_header_swabber(ghdr);
-
-		major = gss_verify_msg(msg, gctx->gc_mechctx, reqhdr->gh_svc);
-		if (major != GSS_S_COMPLETE) {
-			CERROR("failed to verify reply: %x\n", major);
-			return -EPERM;
-		}
-
-		if (req->rq_early && reqhdr->gh_svc == SPTLRPC_SVC_NULL) {
-			__u32 cksum;
-
-			cksum = crc32_le(!(__u32) 0,
-					 lustre_msg_buf(msg, 1, 0),
-					 lustre_msg_buflen(msg, 1));
-			if (cksum != msg->lm_cksum) {
-				CWARN("early reply checksum mismatch: "
-				      "%08x != %08x\n", cksum, msg->lm_cksum);
-				return -EPROTO;
-			}
-		}
-
-		if (pack_bulk) {
-			/* bulk checksum is right after the lustre msg */
-			if (msg->lm_bufcount < 3) {
-				CERROR("Invalid reply bufcount %u\n",
-				       msg->lm_bufcount);
-				return -EPROTO;
-			}
-
-			rc = bulk_sec_desc_unpack(msg, 2, swabbed);
-			if (rc) {
-				CERROR("unpack bulk desc: %d\n", rc);
-				return rc;
-			}
-		}
-
-		req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
-		req->rq_replen = msg->lm_buflens[1];
-		break;
-	case PTLRPC_GSS_PROC_ERR:
-		if (req->rq_early) {
-			CERROR("server return error with early reply\n");
-			rc = -EPROTO;
-		} else {
-			rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr);
-		}
-		break;
-	default:
-		CERROR("unknown gss proc %d\n", ghdr->gh_proc);
-		rc = -EPROTO;
-	}
-
-	return rc;
-}
-
-int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
-		     struct ptlrpc_request *req)
-{
-	struct gss_cli_ctx      *gctx;
-	rawobj_t		 hdrobj, msgobj, token;
-	struct gss_header       *ghdr;
-	__u32		    buflens[2], major;
-	int		      wiresize, rc;
-
-	LASSERT(req->rq_clrbuf);
-	LASSERT(req->rq_cli_ctx == ctx);
-	LASSERT(req->rq_reqlen);
-
-	gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-
-	/* final clear data length */
-	req->rq_clrdata_len = lustre_msg_size_v2(req->rq_clrbuf->lm_bufcount,
-						 req->rq_clrbuf->lm_buflens);
-
-	/* calculate wire data length */
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = gss_cli_payload(&gctx->gc_base, req->rq_clrdata_len, 1);
-	wiresize = lustre_msg_size_v2(2, buflens);
-
-	/* allocate wire buffer */
-	if (req->rq_pool) {
-		/* pre-allocated */
-		LASSERT(req->rq_reqbuf);
-		LASSERT(req->rq_reqbuf != req->rq_clrbuf);
-		LASSERT(req->rq_reqbuf_len >= wiresize);
-	} else {
-		OBD_ALLOC_LARGE(req->rq_reqbuf, wiresize);
-		if (!req->rq_reqbuf)
-			return -ENOMEM;
-		req->rq_reqbuf_len = wiresize;
-	}
-
-	lustre_init_msg_v2(req->rq_reqbuf, 2, buflens, NULL);
-	req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc;
-
-	/* gss header */
-	ghdr = lustre_msg_buf(req->rq_reqbuf, 0, 0);
-	ghdr->gh_version = PTLRPC_GSS_VERSION;
-	ghdr->gh_sp = (__u8) ctx->cc_sec->ps_part;
-	ghdr->gh_flags = 0;
-	ghdr->gh_proc = gctx->gc_proc;
-	ghdr->gh_svc = SPTLRPC_SVC_PRIV;
-	ghdr->gh_handle.len = gctx->gc_handle.len;
-	memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len);
-	if (req->rq_pack_bulk)
-		ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK;
-	if (req->rq_pack_udesc)
-		ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
-
-redo:
-	ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
-
-	/* buffer objects */
-	hdrobj.len = PTLRPC_GSS_HEADER_SIZE;
-	hdrobj.data = (__u8 *) ghdr;
-	msgobj.len = req->rq_clrdata_len;
-	msgobj.data = (__u8 *) req->rq_clrbuf;
-	token.len = lustre_msg_buflen(req->rq_reqbuf, 1);
-	token.data = lustre_msg_buf(req->rq_reqbuf, 1, 0);
-
-	major = lgss_wrap(gctx->gc_mechctx, &hdrobj, &msgobj,
-			  req->rq_clrbuf_len, &token);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("priv: wrap message error: %08x\n", major);
-		GOTO(err_free, rc = -EPERM);
-	}
-	LASSERT(token.len <= buflens[1]);
-
-	/* see explain in gss_cli_ctx_sign() */
-	if (unlikely(atomic_read(&gctx->gc_seq) - ghdr->gh_seq >
-		     GSS_SEQ_REPACK_THRESHOLD)) {
-		int behind = atomic_read(&gctx->gc_seq) - ghdr->gh_seq;
-
-		gss_stat_oos_record_cli(behind);
-		CWARN("req %p: %u behind, retry sealing\n", req, behind);
-
-		ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
-		goto redo;
-	}
-
-	/* now set the final wire data length */
-	req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 1, token.len,0);
-	return 0;
-
-err_free:
-	if (!req->rq_pool) {
-		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
-		req->rq_reqbuf = NULL;
-		req->rq_reqbuf_len = 0;
-	}
-	return rc;
-}
-
-int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
-		       struct ptlrpc_request *req)
-{
-	struct gss_cli_ctx      *gctx;
-	struct gss_header       *ghdr;
-	struct lustre_msg       *msg = req->rq_repdata;
-	int		      msglen, pack_bulk, swabbed, rc;
-	__u32		    major;
-
-	LASSERT(req->rq_cli_ctx == ctx);
-	LASSERT(req->rq_ctx_init == 0);
-	LASSERT(msg);
-
-	gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-	swabbed = ptlrpc_rep_need_swab(req);
-
-	ghdr = gss_swab_header(msg, 0, swabbed);
-	if (ghdr == NULL) {
-		CERROR("can't decode gss header\n");
-		return -EPROTO;
-	}
-
-	/* sanity checks */
-	if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
-		CERROR("gss version %u mismatch, expect %u\n",
-		       ghdr->gh_version, PTLRPC_GSS_VERSION);
-		return -EPROTO;
-	}
-
-	switch (ghdr->gh_proc) {
-	case PTLRPC_GSS_PROC_DATA:
-		pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK;
-
-		if (!req->rq_early &&
-		    !equi(req->rq_pack_bulk == 1, pack_bulk)) {
-			CERROR("%s bulk flag in reply\n",
-			       req->rq_pack_bulk ? "missing" : "unexpected");
-			return -EPROTO;
-		}
-
-		if (swabbed)
-			gss_header_swabber(ghdr);
-
-		/* use rq_repdata_len as buffer size, which assume unseal
-		 * doesn't need extra memory space. for precise control, we'd
-		 * better calculate out actual buffer size as
-		 * (repbuf_len - offset - repdata_len) */
-		major = gss_unseal_msg(gctx->gc_mechctx, msg,
-				       &msglen, req->rq_repdata_len);
-		if (major != GSS_S_COMPLETE) {
-			CERROR("failed to unwrap reply: %x\n", major);
-			rc = -EPERM;
-			break;
-		}
-
-		swabbed = __lustre_unpack_msg(msg, msglen);
-		if (swabbed < 0) {
-			CERROR("Failed to unpack after decryption\n");
-			return -EPROTO;
-		}
-
-		if (msg->lm_bufcount < 1) {
-			CERROR("Invalid reply buffer: empty\n");
-			return -EPROTO;
-		}
-
-		if (pack_bulk) {
-			if (msg->lm_bufcount < 2) {
-				CERROR("bufcount %u: missing bulk sec desc\n",
-				       msg->lm_bufcount);
-				return -EPROTO;
-			}
-
-			/* bulk checksum is the last segment */
-			if (bulk_sec_desc_unpack(msg, msg->lm_bufcount - 1,
-						 swabbed))
-				return -EPROTO;
-		}
-
-		req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
-		req->rq_replen = msg->lm_buflens[0];
-
-		rc = 0;
-		break;
-	case PTLRPC_GSS_PROC_ERR:
-		if (req->rq_early) {
-			CERROR("server return error with early reply\n");
-			rc = -EPROTO;
-		} else {
-			rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr);
-		}
-		break;
-	default:
-		CERROR("unexpected proc %d\n", ghdr->gh_proc);
-		rc = -EPERM;
-	}
-
-	return rc;
-}
-
-/*********************************************
- * reverse context installation	      *
- *********************************************/
-
-static inline
-int gss_install_rvs_svc_ctx(struct obd_import *imp,
-			    struct gss_sec *gsec,
-			    struct gss_cli_ctx *gctx)
-{
-	return gss_svc_upcall_install_rvs_ctx(imp, gsec, gctx);
-}
-
-/*********************************************
- * GSS security APIs			 *
- *********************************************/
-int gss_sec_create_common(struct gss_sec *gsec,
-			  struct ptlrpc_sec_policy *policy,
-			  struct obd_import *imp,
-			  struct ptlrpc_svc_ctx *svcctx,
-			  struct sptlrpc_flavor *sf)
-{
-	struct ptlrpc_sec   *sec;
-
-	LASSERT(imp);
-	LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_GSS);
-
-	gsec->gs_mech = lgss_subflavor_to_mech(
-				SPTLRPC_FLVR_BASE_SUB(sf->sf_rpc));
-	if (!gsec->gs_mech) {
-		CERROR("gss backend 0x%x not found\n",
-		       SPTLRPC_FLVR_BASE_SUB(sf->sf_rpc));
-		return -EOPNOTSUPP;
-	}
-
-	spin_lock_init(&gsec->gs_lock);
-	gsec->gs_rvs_hdl = 0ULL;
-
-	/* initialize upper ptlrpc_sec */
-	sec = &gsec->gs_base;
-	sec->ps_policy = policy;
-	atomic_set(&sec->ps_refcount, 0);
-	atomic_set(&sec->ps_nctx, 0);
-	sec->ps_id = sptlrpc_get_next_secid();
-	sec->ps_flvr = *sf;
-	sec->ps_import = class_import_get(imp);
-	spin_lock_init(&sec->ps_lock);
-	INIT_LIST_HEAD(&sec->ps_gc_list);
-
-	if (!svcctx) {
-		sec->ps_gc_interval = GSS_GC_INTERVAL;
-	} else {
-		LASSERT(sec_is_reverse(sec));
-
-		/* never do gc on reverse sec */
-		sec->ps_gc_interval = 0;
-	}
-
-	if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV)
-		sptlrpc_enc_pool_add_user();
-
-	CDEBUG(D_SEC, "create %s%s@%p\n", (svcctx ? "reverse " : ""),
-	       policy->sp_name, gsec);
-	return 0;
-}
-
-void gss_sec_destroy_common(struct gss_sec *gsec)
-{
-	struct ptlrpc_sec      *sec = &gsec->gs_base;
-
-	LASSERT(sec->ps_import);
-	LASSERT(atomic_read(&sec->ps_refcount) == 0);
-	LASSERT(atomic_read(&sec->ps_nctx) == 0);
-
-	if (gsec->gs_mech) {
-		lgss_mech_put(gsec->gs_mech);
-		gsec->gs_mech = NULL;
-	}
-
-	class_import_put(sec->ps_import);
-
-	if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV)
-		sptlrpc_enc_pool_del_user();
-}
-
-void gss_sec_kill(struct ptlrpc_sec *sec)
-{
-	sec->ps_dying = 1;
-}
-
-int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx,
-			    struct ptlrpc_ctx_ops *ctxops,
-			    struct vfs_cred *vcred)
-{
-	struct gss_cli_ctx    *gctx = ctx2gctx(ctx);
-
-	gctx->gc_win = 0;
-	atomic_set(&gctx->gc_seq, 0);
-
-	INIT_HLIST_NODE(&ctx->cc_cache);
-	atomic_set(&ctx->cc_refcount, 0);
-	ctx->cc_sec = sec;
-	ctx->cc_ops = ctxops;
-	ctx->cc_expire = 0;
-	ctx->cc_flags = PTLRPC_CTX_NEW;
-	ctx->cc_vcred = *vcred;
-	spin_lock_init(&ctx->cc_lock);
-	INIT_LIST_HEAD(&ctx->cc_req_list);
-	INIT_LIST_HEAD(&ctx->cc_gc_chain);
-
-	/* take a ref on belonging sec, balanced in ctx destroying */
-	atomic_inc(&sec->ps_refcount);
-	/* statistic only */
-	atomic_inc(&sec->ps_nctx);
-
-	CDEBUG(D_SEC, "%s@%p: create ctx %p(%u->%s)\n",
-	       sec->ps_policy->sp_name, ctx->cc_sec,
-	       ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
-	return 0;
-}
-
-/*
- * return value:
- *   1: the context has been taken care of by someone else
- *   0: proceed to really destroy the context locally
- */
-int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
-			    struct ptlrpc_cli_ctx *ctx)
-{
-	struct gss_cli_ctx *gctx = ctx2gctx(ctx);
-
-	LASSERT(atomic_read(&sec->ps_nctx) > 0);
-	LASSERT(atomic_read(&ctx->cc_refcount) == 0);
-	LASSERT(ctx->cc_sec == sec);
-
-	/*
-	 * remove UPTODATE flag of reverse ctx thus we won't send fini rpc,
-	 * this is to avoid potential problems of client side reverse svc ctx
-	 * be mis-destroyed in various recovery scenarios. anyway client can
-	 * manage its reverse ctx well by associating it with its buddy ctx.
-	 */
-	if (sec_is_reverse(sec))
-		ctx->cc_flags &= ~PTLRPC_CTX_UPTODATE;
-
-	if (gctx->gc_mechctx) {
-		/* the final context fini rpc will use this ctx too, and it's
-		 * asynchronous which finished by request_out_callback(). so
-		 * we add refcount, whoever drop finally drop the refcount to
-		 * 0 should responsible for the rest of destroy. */
-		atomic_inc(&ctx->cc_refcount);
-
-		gss_do_ctx_fini_rpc(gctx);
-		gss_cli_ctx_finalize(gctx);
-
-		if (!atomic_dec_and_test(&ctx->cc_refcount))
-			return 1;
-	}
-
-	if (sec_is_reverse(sec))
-		CWARN("reverse sec %p: destroy ctx %p\n",
-		      ctx->cc_sec, ctx);
-	else
-		CWARN("%s@%p: destroy ctx %p(%u->%s)\n",
-		      sec->ps_policy->sp_name, ctx->cc_sec,
-		      ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
-
-	return 0;
-}
-
-static
-int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
-			  struct ptlrpc_request *req,
-			  int svc, int msgsize)
-{
-	int		       bufsize, txtsize;
-	int		       bufcnt = 2;
-	__u32		     buflens[5];
-
-	/*
-	 * on-wire data layout:
-	 * - gss header
-	 * - lustre message
-	 * - user descriptor (optional)
-	 * - bulk sec descriptor (optional)
-	 * - signature (optional)
-	 *   - svc == NULL: NULL
-	 *   - svc == AUTH: signature of gss header
-	 *   - svc == INTG: signature of all above
-	 *
-	 * if this is context negotiation, reserver fixed space
-	 * at the last (signature) segment regardless of svc mode.
-	 */
-
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	txtsize = buflens[0];
-
-	buflens[1] = msgsize;
-	if (svc == SPTLRPC_SVC_INTG)
-		txtsize += buflens[1];
-
-	if (req->rq_pack_udesc) {
-		buflens[bufcnt] = sptlrpc_current_user_desc_size();
-		if (svc == SPTLRPC_SVC_INTG)
-			txtsize += buflens[bufcnt];
-		bufcnt++;
-	}
-
-	if (req->rq_pack_bulk) {
-		buflens[bufcnt] = gss_cli_bulk_payload(req->rq_cli_ctx,
-						       &req->rq_flvr,
-						       0, req->rq_bulk_read);
-		if (svc == SPTLRPC_SVC_INTG)
-			txtsize += buflens[bufcnt];
-		bufcnt++;
-	}
-
-	if (req->rq_ctx_init)
-		buflens[bufcnt++] = GSS_CTX_INIT_MAX_LEN;
-	else if (svc != SPTLRPC_SVC_NULL)
-		buflens[bufcnt++] = gss_cli_payload(req->rq_cli_ctx, txtsize,0);
-
-	bufsize = lustre_msg_size_v2(bufcnt, buflens);
-
-	if (!req->rq_reqbuf) {
-		bufsize = size_roundup_power2(bufsize);
-
-		OBD_ALLOC_LARGE(req->rq_reqbuf, bufsize);
-		if (!req->rq_reqbuf)
-			return -ENOMEM;
-
-		req->rq_reqbuf_len = bufsize;
-	} else {
-		LASSERT(req->rq_pool);
-		LASSERT(req->rq_reqbuf_len >= bufsize);
-		memset(req->rq_reqbuf, 0, bufsize);
-	}
-
-	lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
-	req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc;
-
-	req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, msgsize);
-	LASSERT(req->rq_reqmsg);
-
-	/* pack user desc here, later we might leave current user's process */
-	if (req->rq_pack_udesc)
-		sptlrpc_pack_user_desc(req->rq_reqbuf, 2);
-
-	return 0;
-}
-
-static
-int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
-			  struct ptlrpc_request *req,
-			  int msgsize)
-{
-	__u32		     ibuflens[3], wbuflens[2];
-	int		       ibufcnt;
-	int		       clearsize, wiresize;
-
-	LASSERT(req->rq_clrbuf == NULL);
-	LASSERT(req->rq_clrbuf_len == 0);
-
-	/* Inner (clear) buffers
-	 *  - lustre message
-	 *  - user descriptor (optional)
-	 *  - bulk checksum (optional)
-	 */
-	ibufcnt = 1;
-	ibuflens[0] = msgsize;
-
-	if (req->rq_pack_udesc)
-		ibuflens[ibufcnt++] = sptlrpc_current_user_desc_size();
-	if (req->rq_pack_bulk)
-		ibuflens[ibufcnt++] = gss_cli_bulk_payload(req->rq_cli_ctx,
-							   &req->rq_flvr, 0,
-							   req->rq_bulk_read);
-
-	clearsize = lustre_msg_size_v2(ibufcnt, ibuflens);
-	/* to allow append padding during encryption */
-	clearsize += GSS_MAX_CIPHER_BLOCK;
-
-	/* Wrapper (wire) buffers
-	 *  - gss header
-	 *  - cipher text
-	 */
-	wbuflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	wbuflens[1] = gss_cli_payload(req->rq_cli_ctx, clearsize, 1);
-	wiresize = lustre_msg_size_v2(2, wbuflens);
-
-	if (req->rq_pool) {
-		/* rq_reqbuf is preallocated */
-		LASSERT(req->rq_reqbuf);
-		LASSERT(req->rq_reqbuf_len >= wiresize);
-
-		memset(req->rq_reqbuf, 0, req->rq_reqbuf_len);
-
-		/* if the pre-allocated buffer is big enough, we just pack
-		 * both clear buf & request buf in it, to avoid more alloc. */
-		if (clearsize + wiresize <= req->rq_reqbuf_len) {
-			req->rq_clrbuf =
-				(void *) (((char *) req->rq_reqbuf) + wiresize);
-		} else {
-			CWARN("pre-allocated buf size %d is not enough for "
-			      "both clear (%d) and cipher (%d) text, proceed "
-			      "with extra allocation\n", req->rq_reqbuf_len,
-			      clearsize, wiresize);
-		}
-	}
-
-	if (!req->rq_clrbuf) {
-		clearsize = size_roundup_power2(clearsize);
-
-		OBD_ALLOC_LARGE(req->rq_clrbuf, clearsize);
-		if (!req->rq_clrbuf)
-			return -ENOMEM;
-	}
-	req->rq_clrbuf_len = clearsize;
-
-	lustre_init_msg_v2(req->rq_clrbuf, ibufcnt, ibuflens, NULL);
-	req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, msgsize);
-
-	if (req->rq_pack_udesc)
-		sptlrpc_pack_user_desc(req->rq_clrbuf, 1);
-
-	return 0;
-}
-
-/*
- * NOTE: any change of request buffer allocation should also consider
- * changing enlarge_reqbuf() series functions.
- */
-int gss_alloc_reqbuf(struct ptlrpc_sec *sec,
-		     struct ptlrpc_request *req,
-		     int msgsize)
-{
-	int     svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-
-	LASSERT(!req->rq_pack_bulk ||
-		(req->rq_bulk_read || req->rq_bulk_write));
-
-	switch (svc) {
-	case SPTLRPC_SVC_NULL:
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		return gss_alloc_reqbuf_intg(sec, req, svc, msgsize);
-	case SPTLRPC_SVC_PRIV:
-		return gss_alloc_reqbuf_priv(sec, req, msgsize);
-	default:
-		LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
-		return 0;
-	}
-}
-
-void gss_free_reqbuf(struct ptlrpc_sec *sec,
-		     struct ptlrpc_request *req)
-{
-	int     privacy;
-
-	LASSERT(!req->rq_pool || req->rq_reqbuf);
-	privacy = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc) == SPTLRPC_SVC_PRIV;
-
-	if (!req->rq_clrbuf)
-		goto release_reqbuf;
-
-	/* release clear buffer */
-	LASSERT(privacy);
-	LASSERT(req->rq_clrbuf_len);
-
-	if (req->rq_pool == NULL ||
-	    req->rq_clrbuf < req->rq_reqbuf ||
-	    (char *) req->rq_clrbuf >=
-	    (char *) req->rq_reqbuf + req->rq_reqbuf_len)
-		OBD_FREE_LARGE(req->rq_clrbuf, req->rq_clrbuf_len);
-
-	req->rq_clrbuf = NULL;
-	req->rq_clrbuf_len = 0;
-
-release_reqbuf:
-	if (!req->rq_pool && req->rq_reqbuf) {
-		LASSERT(req->rq_reqbuf_len);
-
-		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
-		req->rq_reqbuf = NULL;
-		req->rq_reqbuf_len = 0;
-	}
-}
-
-static int do_alloc_repbuf(struct ptlrpc_request *req, int bufsize)
-{
-	bufsize = size_roundup_power2(bufsize);
-
-	OBD_ALLOC_LARGE(req->rq_repbuf, bufsize);
-	if (!req->rq_repbuf)
-		return -ENOMEM;
-
-	req->rq_repbuf_len = bufsize;
-	return 0;
-}
-
-static
-int gss_alloc_repbuf_intg(struct ptlrpc_sec *sec,
-			  struct ptlrpc_request *req,
-			  int svc, int msgsize)
-{
-	int	     txtsize;
-	__u32	   buflens[4];
-	int	     bufcnt = 2;
-	int	     alloc_size;
-
-	/*
-	 * on-wire data layout:
-	 * - gss header
-	 * - lustre message
-	 * - bulk sec descriptor (optional)
-	 * - signature (optional)
-	 *   - svc == NULL: NULL
-	 *   - svc == AUTH: signature of gss header
-	 *   - svc == INTG: signature of all above
-	 *
-	 * if this is context negotiation, reserver fixed space
-	 * at the last (signature) segment regardless of svc mode.
-	 */
-
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	txtsize = buflens[0];
-
-	buflens[1] = msgsize;
-	if (svc == SPTLRPC_SVC_INTG)
-		txtsize += buflens[1];
-
-	if (req->rq_pack_bulk) {
-		buflens[bufcnt] = gss_cli_bulk_payload(req->rq_cli_ctx,
-						       &req->rq_flvr,
-						       1, req->rq_bulk_read);
-		if (svc == SPTLRPC_SVC_INTG)
-			txtsize += buflens[bufcnt];
-		bufcnt++;
-	}
-
-	if (req->rq_ctx_init)
-		buflens[bufcnt++] = GSS_CTX_INIT_MAX_LEN;
-	else if (svc != SPTLRPC_SVC_NULL)
-		buflens[bufcnt++] = gss_cli_payload(req->rq_cli_ctx, txtsize,0);
-
-	alloc_size = lustre_msg_size_v2(bufcnt, buflens);
-
-	/* add space for early reply */
-	alloc_size += gss_at_reply_off_integ;
-
-	return do_alloc_repbuf(req, alloc_size);
-}
-
-static
-int gss_alloc_repbuf_priv(struct ptlrpc_sec *sec,
-			  struct ptlrpc_request *req,
-			  int msgsize)
-{
-	int	     txtsize;
-	__u32	   buflens[2];
-	int	     bufcnt;
-	int	     alloc_size;
-
-	/* inner buffers */
-	bufcnt = 1;
-	buflens[0] = msgsize;
-
-	if (req->rq_pack_bulk)
-		buflens[bufcnt++] = gss_cli_bulk_payload(req->rq_cli_ctx,
-							 &req->rq_flvr,
-							 1, req->rq_bulk_read);
-	txtsize = lustre_msg_size_v2(bufcnt, buflens);
-	txtsize += GSS_MAX_CIPHER_BLOCK;
-
-	/* wrapper buffers */
-	bufcnt = 2;
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = gss_cli_payload(req->rq_cli_ctx, txtsize, 1);
-
-	alloc_size = lustre_msg_size_v2(bufcnt, buflens);
-	/* add space for early reply */
-	alloc_size += gss_at_reply_off_priv;
-
-	return do_alloc_repbuf(req, alloc_size);
-}
-
-int gss_alloc_repbuf(struct ptlrpc_sec *sec,
-		     struct ptlrpc_request *req,
-		     int msgsize)
-{
-	int     svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-
-	LASSERT(!req->rq_pack_bulk ||
-		(req->rq_bulk_read || req->rq_bulk_write));
-
-	switch (svc) {
-	case SPTLRPC_SVC_NULL:
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		return gss_alloc_repbuf_intg(sec, req, svc, msgsize);
-	case SPTLRPC_SVC_PRIV:
-		return gss_alloc_repbuf_priv(sec, req, msgsize);
-	default:
-		LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
-		return 0;
-	}
-}
-
-void gss_free_repbuf(struct ptlrpc_sec *sec,
-		     struct ptlrpc_request *req)
-{
-	OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len);
-	req->rq_repbuf = NULL;
-	req->rq_repbuf_len = 0;
-	req->rq_repdata = NULL;
-	req->rq_repdata_len = 0;
-}
-
-static int get_enlarged_msgsize(struct lustre_msg *msg,
-				int segment, int newsize)
-{
-	int save, newmsg_size;
-
-	LASSERT(newsize >= msg->lm_buflens[segment]);
-
-	save = msg->lm_buflens[segment];
-	msg->lm_buflens[segment] = newsize;
-	newmsg_size = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
-	msg->lm_buflens[segment] = save;
-
-	return newmsg_size;
-}
-
-static int get_enlarged_msgsize2(struct lustre_msg *msg,
-				 int segment1, int newsize1,
-				 int segment2, int newsize2)
-{
-	int save1, save2, newmsg_size;
-
-	LASSERT(newsize1 >= msg->lm_buflens[segment1]);
-	LASSERT(newsize2 >= msg->lm_buflens[segment2]);
-
-	save1 = msg->lm_buflens[segment1];
-	save2 = msg->lm_buflens[segment2];
-	msg->lm_buflens[segment1] = newsize1;
-	msg->lm_buflens[segment2] = newsize2;
-	newmsg_size = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
-	msg->lm_buflens[segment1] = save1;
-	msg->lm_buflens[segment2] = save2;
-
-	return newmsg_size;
-}
-
-static
-int gss_enlarge_reqbuf_intg(struct ptlrpc_sec *sec,
-			    struct ptlrpc_request *req,
-			    int svc,
-			    int segment, int newsize)
-{
-	struct lustre_msg      *newbuf;
-	int		     txtsize, sigsize = 0, i;
-	int		     newmsg_size, newbuf_size;
-
-	/*
-	 * gss header is at seg 0;
-	 * embedded msg is at seg 1;
-	 * signature (if any) is at the last seg
-	 */
-	LASSERT(req->rq_reqbuf);
-	LASSERT(req->rq_reqbuf_len > req->rq_reqlen);
-	LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
-	LASSERT(lustre_msg_buf(req->rq_reqbuf, 1, 0) == req->rq_reqmsg);
-
-	/* 1. compute new embedded msg size */
-	newmsg_size = get_enlarged_msgsize(req->rq_reqmsg, segment, newsize);
-	LASSERT(newmsg_size >= req->rq_reqbuf->lm_buflens[1]);
-
-	/* 2. compute new wrapper msg size */
-	if (svc == SPTLRPC_SVC_NULL) {
-		/* no signature, get size directly */
-		newbuf_size = get_enlarged_msgsize(req->rq_reqbuf,
-						   1, newmsg_size);
-	} else {
-		txtsize = req->rq_reqbuf->lm_buflens[0];
-
-		if (svc == SPTLRPC_SVC_INTG) {
-			for (i = 1; i < req->rq_reqbuf->lm_bufcount; i++)
-				txtsize += req->rq_reqbuf->lm_buflens[i];
-			txtsize += newmsg_size - req->rq_reqbuf->lm_buflens[1];
-		}
-
-		sigsize = gss_cli_payload(req->rq_cli_ctx, txtsize, 0);
-		LASSERT(sigsize >= msg_last_seglen(req->rq_reqbuf));
-
-		newbuf_size = get_enlarged_msgsize2(
-					req->rq_reqbuf,
-					1, newmsg_size,
-					msg_last_segidx(req->rq_reqbuf),
-					sigsize);
-	}
-
-	/* request from pool should always have enough buffer */
-	LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
-
-	if (req->rq_reqbuf_len < newbuf_size) {
-		newbuf_size = size_roundup_power2(newbuf_size);
-
-		OBD_ALLOC_LARGE(newbuf, newbuf_size);
-		if (newbuf == NULL)
-			return -ENOMEM;
-
-		memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
-
-		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
-		req->rq_reqbuf = newbuf;
-		req->rq_reqbuf_len = newbuf_size;
-		req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, 0);
-	}
-
-	/* do enlargement, from wrapper to embedded, from end to begin */
-	if (svc != SPTLRPC_SVC_NULL)
-		_sptlrpc_enlarge_msg_inplace(req->rq_reqbuf,
-					     msg_last_segidx(req->rq_reqbuf),
-					     sigsize);
-
-	_sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 1, newmsg_size);
-	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
-
-	req->rq_reqlen = newmsg_size;
-	return 0;
-}
-
-static
-int gss_enlarge_reqbuf_priv(struct ptlrpc_sec *sec,
-			    struct ptlrpc_request *req,
-			    int segment, int newsize)
-{
-	struct lustre_msg      *newclrbuf;
-	int		     newmsg_size, newclrbuf_size, newcipbuf_size;
-	__u32		   buflens[3];
-
-	/*
-	 * embedded msg is at seg 0 of clear buffer;
-	 * cipher text is at seg 2 of cipher buffer;
-	 */
-	LASSERT(req->rq_pool ||
-		(req->rq_reqbuf == NULL && req->rq_reqbuf_len == 0));
-	LASSERT(req->rq_reqbuf == NULL ||
-		(req->rq_pool && req->rq_reqbuf->lm_bufcount == 3));
-	LASSERT(req->rq_clrbuf);
-	LASSERT(req->rq_clrbuf_len > req->rq_reqlen);
-	LASSERT(lustre_msg_buf(req->rq_clrbuf, 0, 0) == req->rq_reqmsg);
-
-	/* compute new embedded msg size */
-	newmsg_size = get_enlarged_msgsize(req->rq_reqmsg, segment, newsize);
-
-	/* compute new clear buffer size */
-	newclrbuf_size = get_enlarged_msgsize(req->rq_clrbuf, 0, newmsg_size);
-	newclrbuf_size += GSS_MAX_CIPHER_BLOCK;
-
-	/* compute new cipher buffer size */
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0);
-	buflens[2] = gss_cli_payload(req->rq_cli_ctx, newclrbuf_size, 1);
-	newcipbuf_size = lustre_msg_size_v2(3, buflens);
-
-	/* handle the case that we put both clear buf and cipher buf into
-	 * pre-allocated single buffer. */
-	if (unlikely(req->rq_pool) &&
-	    req->rq_clrbuf >= req->rq_reqbuf &&
-	    (char *) req->rq_clrbuf <
-	    (char *) req->rq_reqbuf + req->rq_reqbuf_len) {
-		/* it couldn't be better we still fit into the
-		 * pre-allocated buffer. */
-		if (newclrbuf_size + newcipbuf_size <= req->rq_reqbuf_len) {
-			void *src, *dst;
-
-			/* move clear text backward. */
-			src = req->rq_clrbuf;
-			dst = (char *) req->rq_reqbuf + newcipbuf_size;
-
-			memmove(dst, src, req->rq_clrbuf_len);
-
-			req->rq_clrbuf = (struct lustre_msg *) dst;
-			req->rq_clrbuf_len = newclrbuf_size;
-			req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, 0);
-		} else {
-			/* sadly we have to split out the clear buffer */
-			LASSERT(req->rq_reqbuf_len >= newcipbuf_size);
-			LASSERT(req->rq_clrbuf_len < newclrbuf_size);
-		}
-	}
-
-	if (req->rq_clrbuf_len < newclrbuf_size) {
-		newclrbuf_size = size_roundup_power2(newclrbuf_size);
-
-		OBD_ALLOC_LARGE(newclrbuf, newclrbuf_size);
-		if (newclrbuf == NULL)
-			return -ENOMEM;
-
-		memcpy(newclrbuf, req->rq_clrbuf, req->rq_clrbuf_len);
-
-		if (req->rq_reqbuf == NULL ||
-		    req->rq_clrbuf < req->rq_reqbuf ||
-		    (char *) req->rq_clrbuf >=
-		    (char *) req->rq_reqbuf + req->rq_reqbuf_len) {
-			OBD_FREE_LARGE(req->rq_clrbuf, req->rq_clrbuf_len);
-		}
-
-		req->rq_clrbuf = newclrbuf;
-		req->rq_clrbuf_len = newclrbuf_size;
-		req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, 0);
-	}
-
-	_sptlrpc_enlarge_msg_inplace(req->rq_clrbuf, 0, newmsg_size);
-	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
-	req->rq_reqlen = newmsg_size;
-
-	return 0;
-}
-
-int gss_enlarge_reqbuf(struct ptlrpc_sec *sec,
-		       struct ptlrpc_request *req,
-		       int segment, int newsize)
-{
-	int     svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-
-	LASSERT(!req->rq_ctx_init && !req->rq_ctx_fini);
-
-	switch (svc) {
-	case SPTLRPC_SVC_NULL:
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		return gss_enlarge_reqbuf_intg(sec, req, svc, segment, newsize);
-	case SPTLRPC_SVC_PRIV:
-		return gss_enlarge_reqbuf_priv(sec, req, segment, newsize);
-	default:
-		LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
-		return 0;
-	}
-}
-
-int gss_sec_install_rctx(struct obd_import *imp,
-			 struct ptlrpc_sec *sec,
-			 struct ptlrpc_cli_ctx *ctx)
-{
-	struct gss_sec     *gsec;
-	struct gss_cli_ctx *gctx;
-	int		 rc;
-
-	gsec = container_of(sec, struct gss_sec, gs_base);
-	gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-
-	rc = gss_install_rvs_svc_ctx(imp, gsec, gctx);
-	return rc;
-}
-
-/********************************************
- * server side API			  *
- ********************************************/
-
-static inline
-int gss_svc_reqctx_is_special(struct gss_svc_reqctx *grctx)
-{
-	LASSERT(grctx);
-	return (grctx->src_init || grctx->src_init_continue ||
-		grctx->src_err_notify);
-}
-
-static
-void gss_svc_reqctx_free(struct gss_svc_reqctx *grctx)
-{
-	if (grctx->src_ctx)
-		gss_svc_upcall_put_ctx(grctx->src_ctx);
-
-	sptlrpc_policy_put(grctx->src_base.sc_policy);
-	OBD_FREE_PTR(grctx);
-}
-
-static inline
-void gss_svc_reqctx_addref(struct gss_svc_reqctx *grctx)
-{
-	LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0);
-	atomic_inc(&grctx->src_base.sc_refcount);
-}
-
-static inline
-void gss_svc_reqctx_decref(struct gss_svc_reqctx *grctx)
-{
-	LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0);
-
-	if (atomic_dec_and_test(&grctx->src_base.sc_refcount))
-		gss_svc_reqctx_free(grctx);
-}
-
-static
-int gss_svc_sign(struct ptlrpc_request *req,
-		 struct ptlrpc_reply_state *rs,
-		 struct gss_svc_reqctx *grctx,
-		 __u32 svc)
-{
-	__u32   flags = 0;
-	int     rc;
-
-	LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0));
-
-	/* embedded lustre_msg might have been shrunk */
-	if (req->rq_replen != rs->rs_repbuf->lm_buflens[1])
-		lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1);
-
-	if (req->rq_pack_bulk)
-		flags |= LUSTRE_GSS_PACK_BULK;
-
-	rc = gss_sign_msg(rs->rs_repbuf, grctx->src_ctx->gsc_mechctx,
-			  LUSTRE_SP_ANY, flags, PTLRPC_GSS_PROC_DATA,
-			  grctx->src_wirectx.gw_seq, svc, NULL);
-	if (rc < 0)
-		return rc;
-
-	rs->rs_repdata_len = rc;
-
-	if (likely(req->rq_packed_final)) {
-		if (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT)
-			req->rq_reply_off = gss_at_reply_off_integ;
-		else
-			req->rq_reply_off = 0;
-	} else {
-		if (svc == SPTLRPC_SVC_NULL)
-			rs->rs_repbuf->lm_cksum = crc32_le(!(__u32) 0,
-					lustre_msg_buf(rs->rs_repbuf, 1, 0),
-					lustre_msg_buflen(rs->rs_repbuf, 1));
-		req->rq_reply_off = 0;
-	}
-
-	return 0;
-}
-
-int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
-{
-	struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	struct ptlrpc_reply_state *rs;
-	struct gss_err_header     *ghdr;
-	int			replen = sizeof(struct ptlrpc_body);
-	int			rc;
-
-	//if (OBD_FAIL_CHECK_ORSET(OBD_FAIL_SVCGSS_ERR_NOTIFY, OBD_FAIL_ONCE))
-	//      return -EINVAL;
-
-	grctx->src_err_notify = 1;
-	grctx->src_reserve_len = 0;
-
-	rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0);
-	if (rc) {
-		CERROR("could not pack reply, err %d\n", rc);
-		return rc;
-	}
-
-	/* gss hdr */
-	rs = req->rq_reply_state;
-	LASSERT(rs->rs_repbuf->lm_buflens[1] >= sizeof(*ghdr));
-	ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
-	ghdr->gh_version = PTLRPC_GSS_VERSION;
-	ghdr->gh_flags = 0;
-	ghdr->gh_proc = PTLRPC_GSS_PROC_ERR;
-	ghdr->gh_major = major;
-	ghdr->gh_minor = minor;
-	ghdr->gh_handle.len = 0; /* fake context handle */
-
-	rs->rs_repdata_len = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount,
-						rs->rs_repbuf->lm_buflens);
-
-	CDEBUG(D_SEC, "prepare gss error notify(0x%x/0x%x) to %s\n",
-	       major, minor, libcfs_nid2str(req->rq_peer.nid));
-	return 0;
-}
-
-static
-int gss_svc_handle_init(struct ptlrpc_request *req,
-			struct gss_wire_ctx *gw)
-{
-	struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	struct lustre_msg	 *reqbuf = req->rq_reqbuf;
-	struct obd_uuid	   *uuid;
-	struct obd_device	 *target;
-	rawobj_t		   uuid_obj, rvs_hdl, in_token;
-	__u32		      lustre_svc;
-	__u32		     *secdata, seclen;
-	int			swabbed, rc;
-
-	CDEBUG(D_SEC, "processing gss init(%d) request from %s\n", gw->gw_proc,
-	       libcfs_nid2str(req->rq_peer.nid));
-
-	req->rq_ctx_init = 1;
-
-	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
-		CERROR("unexpected bulk flag\n");
-		return SECSVC_DROP;
-	}
-
-	if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) {
-		CERROR("proc %u: invalid handle length %u\n",
-		       gw->gw_proc, gw->gw_handle.len);
-		return SECSVC_DROP;
-	}
-
-	if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4) {
-		CERROR("Invalid bufcount %d\n", reqbuf->lm_bufcount);
-		return SECSVC_DROP;
-	}
-
-	swabbed = ptlrpc_req_need_swab(req);
-
-	/* ctx initiate payload is in last segment */
-	secdata = lustre_msg_buf(reqbuf, reqbuf->lm_bufcount - 1, 0);
-	seclen = reqbuf->lm_buflens[reqbuf->lm_bufcount - 1];
-
-	if (seclen < 4 + 4) {
-		CERROR("sec size %d too small\n", seclen);
-		return SECSVC_DROP;
-	}
-
-	/* lustre svc type */
-	lustre_svc = le32_to_cpu(*secdata++);
-	seclen -= 4;
-
-	/* extract target uuid, note this code is somewhat fragile
-	 * because touched internal structure of obd_uuid */
-	if (rawobj_extract(&uuid_obj, &secdata, &seclen)) {
-		CERROR("failed to extract target uuid\n");
-		return SECSVC_DROP;
-	}
-	uuid_obj.data[uuid_obj.len - 1] = '\0';
-
-	uuid = (struct obd_uuid *) uuid_obj.data;
-	target = class_uuid2obd(uuid);
-	if (!target || target->obd_stopping || !target->obd_set_up) {
-		CERROR("target '%s' is not available for context init (%s)\n",
-		       uuid->uuid, target == NULL ? "no target" :
-		       (target->obd_stopping ? "stopping" : "not set up"));
-		return SECSVC_DROP;
-	}
-
-	/* extract reverse handle */
-	if (rawobj_extract(&rvs_hdl, &secdata, &seclen)) {
-		CERROR("failed extract reverse handle\n");
-		return SECSVC_DROP;
-	}
-
-	/* extract token */
-	if (rawobj_extract(&in_token, &secdata, &seclen)) {
-		CERROR("can't extract token\n");
-		return SECSVC_DROP;
-	}
-
-	rc = gss_svc_upcall_handle_init(req, grctx, gw, target, lustre_svc,
-					&rvs_hdl, &in_token);
-	if (rc != SECSVC_OK)
-		return rc;
-
-	if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_oss ||
-	    grctx->src_ctx->gsc_usr_root)
-		CWARN("create svc ctx %p: user from %s authenticated as %s\n",
-		      grctx->src_ctx, libcfs_nid2str(req->rq_peer.nid),
-		      grctx->src_ctx->gsc_usr_mds ? "mds" :
-			(grctx->src_ctx->gsc_usr_oss ? "oss" : "root"));
-	else
-		CWARN("create svc ctx %p: accept user %u from %s\n",
-		      grctx->src_ctx, grctx->src_ctx->gsc_uid,
-		      libcfs_nid2str(req->rq_peer.nid));
-
-	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
-		if (reqbuf->lm_bufcount < 4) {
-			CERROR("missing user descriptor\n");
-			return SECSVC_DROP;
-		}
-		if (sptlrpc_unpack_user_desc(reqbuf, 2, swabbed)) {
-			CERROR("Mal-formed user descriptor\n");
-			return SECSVC_DROP;
-		}
-
-		req->rq_pack_udesc = 1;
-		req->rq_user_desc = lustre_msg_buf(reqbuf, 2, 0);
-	}
-
-	req->rq_reqmsg = lustre_msg_buf(reqbuf, 1, 0);
-	req->rq_reqlen = lustre_msg_buflen(reqbuf, 1);
-
-	return rc;
-}
-
-/*
- * last segment must be the gss signature.
- */
-static
-int gss_svc_verify_request(struct ptlrpc_request *req,
-			   struct gss_svc_reqctx *grctx,
-			   struct gss_wire_ctx *gw,
-			   __u32 *major)
-{
-	struct gss_svc_ctx *gctx = grctx->src_ctx;
-	struct lustre_msg  *msg = req->rq_reqbuf;
-	int		 offset = 2;
-	int		 swabbed;
-
-	*major = GSS_S_COMPLETE;
-
-	if (msg->lm_bufcount < 2) {
-		CERROR("Too few segments (%u) in request\n", msg->lm_bufcount);
-		return -EINVAL;
-	}
-
-	if (gw->gw_svc == SPTLRPC_SVC_NULL)
-		goto verified;
-
-	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
-		CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
-		*major = GSS_S_DUPLICATE_TOKEN;
-		return -EACCES;
-	}
-
-	*major = gss_verify_msg(msg, gctx->gsc_mechctx, gw->gw_svc);
-	if (*major != GSS_S_COMPLETE) {
-		CERROR("failed to verify request: %x\n", *major);
-		return -EACCES;
-	}
-
-	if (gctx->gsc_reverse == 0 &&
-	    gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
-		CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
-		*major = GSS_S_DUPLICATE_TOKEN;
-		return -EACCES;
-	}
-
-verified:
-	swabbed = ptlrpc_req_need_swab(req);
-
-	/* user descriptor */
-	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
-		if (msg->lm_bufcount < (offset + 1)) {
-			CERROR("no user desc included\n");
-			return -EINVAL;
-		}
-
-		if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) {
-			CERROR("Mal-formed user descriptor\n");
-			return -EINVAL;
-		}
-
-		req->rq_pack_udesc = 1;
-		req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
-		offset++;
-	}
-
-	/* check bulk_sec_desc data */
-	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
-		if (msg->lm_bufcount < (offset + 1)) {
-			CERROR("missing bulk sec descriptor\n");
-			return -EINVAL;
-		}
-
-		if (bulk_sec_desc_unpack(msg, offset, swabbed))
-			return -EINVAL;
-
-		req->rq_pack_bulk = 1;
-		grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
-		grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
-	}
-
-	req->rq_reqmsg = lustre_msg_buf(msg, 1, 0);
-	req->rq_reqlen = msg->lm_buflens[1];
-	return 0;
-}
-
-static
-int gss_svc_unseal_request(struct ptlrpc_request *req,
-			   struct gss_svc_reqctx *grctx,
-			   struct gss_wire_ctx *gw,
-			   __u32 *major)
-{
-	struct gss_svc_ctx *gctx = grctx->src_ctx;
-	struct lustre_msg  *msg = req->rq_reqbuf;
-	int		 swabbed, msglen, offset = 1;
-
-	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
-		CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
-		*major = GSS_S_DUPLICATE_TOKEN;
-		return -EACCES;
-	}
-
-	*major = gss_unseal_msg(gctx->gsc_mechctx, msg,
-			       &msglen, req->rq_reqdata_len);
-	if (*major != GSS_S_COMPLETE) {
-		CERROR("failed to unwrap request: %x\n", *major);
-		return -EACCES;
-	}
-
-	if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
-		CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
-		*major = GSS_S_DUPLICATE_TOKEN;
-		return -EACCES;
-	}
-
-	swabbed = __lustre_unpack_msg(msg, msglen);
-	if (swabbed < 0) {
-		CERROR("Failed to unpack after decryption\n");
-		return -EINVAL;
-	}
-	req->rq_reqdata_len = msglen;
-
-	if (msg->lm_bufcount < 1) {
-		CERROR("Invalid buffer: is empty\n");
-		return -EINVAL;
-	}
-
-	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
-		if (msg->lm_bufcount < offset + 1) {
-			CERROR("no user descriptor included\n");
-			return -EINVAL;
-		}
-
-		if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) {
-			CERROR("Mal-formed user descriptor\n");
-			return -EINVAL;
-		}
-
-		req->rq_pack_udesc = 1;
-		req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
-		offset++;
-	}
-
-	if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
-		if (msg->lm_bufcount < offset + 1) {
-			CERROR("no bulk checksum included\n");
-			return -EINVAL;
-		}
-
-		if (bulk_sec_desc_unpack(msg, offset, swabbed))
-			return -EINVAL;
-
-		req->rq_pack_bulk = 1;
-		grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
-		grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
-	}
-
-	req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
-	req->rq_reqlen = req->rq_reqbuf->lm_buflens[0];
-	return 0;
-}
-
-static
-int gss_svc_handle_data(struct ptlrpc_request *req,
-			struct gss_wire_ctx *gw)
-{
-	struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	__u32		  major = 0;
-	int		    rc = 0;
-
-	grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
-	if (!grctx->src_ctx) {
-		major = GSS_S_NO_CONTEXT;
-		goto error;
-	}
-
-	switch (gw->gw_svc) {
-	case SPTLRPC_SVC_NULL:
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		rc = gss_svc_verify_request(req, grctx, gw, &major);
-		break;
-	case SPTLRPC_SVC_PRIV:
-		rc = gss_svc_unseal_request(req, grctx, gw, &major);
-		break;
-	default:
-		CERROR("unsupported gss service %d\n", gw->gw_svc);
-		rc = -EINVAL;
-	}
-
-	if (rc == 0)
-		return SECSVC_OK;
-
-	CERROR("svc %u failed: major 0x%08x: req xid "LPU64" ctx %p idx "
-	       LPX64"(%u->%s)\n", gw->gw_svc, major, req->rq_xid,
-	       grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle),
-	       grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid));
-error:
-	/* we only notify client in case of NO_CONTEXT/BAD_SIG, which
-	 * might happen after server reboot, to allow recovery. */
-	if ((major == GSS_S_NO_CONTEXT || major == GSS_S_BAD_SIG) &&
-	    gss_pack_err_notify(req, major, 0) == 0)
-		return SECSVC_COMPLETE;
-
-	return SECSVC_DROP;
-}
-
-static
-int gss_svc_handle_destroy(struct ptlrpc_request *req,
-			   struct gss_wire_ctx *gw)
-{
-	struct gss_svc_reqctx  *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	__u32		   major;
-
-	req->rq_ctx_fini = 1;
-	req->rq_no_reply = 1;
-
-	grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
-	if (!grctx->src_ctx) {
-		CDEBUG(D_SEC, "invalid gss context handle for destroy.\n");
-		return SECSVC_DROP;
-	}
-
-	if (gw->gw_svc != SPTLRPC_SVC_INTG) {
-		CERROR("svc %u is not supported in destroy.\n", gw->gw_svc);
-		return SECSVC_DROP;
-	}
-
-	if (gss_svc_verify_request(req, grctx, gw, &major))
-		return SECSVC_DROP;
-
-	CWARN("destroy svc ctx %p idx "LPX64" (%u->%s)\n",
-	      grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle),
-	      grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid));
-
-	gss_svc_upcall_destroy_ctx(grctx->src_ctx);
-
-	if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
-		if (req->rq_reqbuf->lm_bufcount < 4) {
-			CERROR("missing user descriptor, ignore it\n");
-			return SECSVC_OK;
-		}
-		if (sptlrpc_unpack_user_desc(req->rq_reqbuf, 2,
-					     ptlrpc_req_need_swab(req))) {
-			CERROR("Mal-formed user descriptor, ignore it\n");
-			return SECSVC_OK;
-		}
-
-		req->rq_pack_udesc = 1;
-		req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0);
-	}
-
-	return SECSVC_OK;
-}
-
-int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
-{
-	struct gss_header      *ghdr;
-	struct gss_svc_reqctx  *grctx;
-	struct gss_wire_ctx    *gw;
-	int		     swabbed, rc;
-
-	LASSERT(req->rq_reqbuf);
-	LASSERT(req->rq_svc_ctx == NULL);
-
-	if (req->rq_reqbuf->lm_bufcount < 2) {
-		CERROR("buf count only %d\n", req->rq_reqbuf->lm_bufcount);
-		return SECSVC_DROP;
-	}
-
-	swabbed = ptlrpc_req_need_swab(req);
-
-	ghdr = gss_swab_header(req->rq_reqbuf, 0, swabbed);
-	if (ghdr == NULL) {
-		CERROR("can't decode gss header\n");
-		return SECSVC_DROP;
-	}
-
-	/* sanity checks */
-	if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
-		CERROR("gss version %u, expect %u\n", ghdr->gh_version,
-		       PTLRPC_GSS_VERSION);
-		return SECSVC_DROP;
-	}
-
-	req->rq_sp_from = ghdr->gh_sp;
-
-	/* alloc grctx data */
-	OBD_ALLOC_PTR(grctx);
-	if (!grctx)
-		return SECSVC_DROP;
-
-	grctx->src_base.sc_policy = sptlrpc_policy_get(policy);
-	atomic_set(&grctx->src_base.sc_refcount, 1);
-	req->rq_svc_ctx = &grctx->src_base;
-	gw = &grctx->src_wirectx;
-
-	/* save wire context */
-	gw->gw_flags = ghdr->gh_flags;
-	gw->gw_proc = ghdr->gh_proc;
-	gw->gw_seq = ghdr->gh_seq;
-	gw->gw_svc = ghdr->gh_svc;
-	rawobj_from_netobj(&gw->gw_handle, &ghdr->gh_handle);
-
-	/* keep original wire header which subject to checksum verification */
-	if (swabbed)
-		gss_header_swabber(ghdr);
-
-	switch (ghdr->gh_proc) {
-	case PTLRPC_GSS_PROC_INIT:
-	case PTLRPC_GSS_PROC_CONTINUE_INIT:
-		rc = gss_svc_handle_init(req, gw);
-		break;
-	case PTLRPC_GSS_PROC_DATA:
-		rc = gss_svc_handle_data(req, gw);
-		break;
-	case PTLRPC_GSS_PROC_DESTROY:
-		rc = gss_svc_handle_destroy(req, gw);
-		break;
-	default:
-		CERROR("unknown proc %u\n", gw->gw_proc);
-		rc = SECSVC_DROP;
-		break;
-	}
-
-	switch (rc) {
-	case SECSVC_OK:
-		LASSERT(grctx->src_ctx);
-
-		req->rq_auth_gss = 1;
-		req->rq_auth_remote = grctx->src_ctx->gsc_remote;
-		req->rq_auth_usr_mdt = grctx->src_ctx->gsc_usr_mds;
-		req->rq_auth_usr_ost = grctx->src_ctx->gsc_usr_oss;
-		req->rq_auth_usr_root = grctx->src_ctx->gsc_usr_root;
-		req->rq_auth_uid = grctx->src_ctx->gsc_uid;
-		req->rq_auth_mapped_uid = grctx->src_ctx->gsc_mapped_uid;
-		break;
-	case SECSVC_COMPLETE:
-		break;
-	case SECSVC_DROP:
-		gss_svc_reqctx_free(grctx);
-		req->rq_svc_ctx = NULL;
-		break;
-	}
-
-	return rc;
-}
-
-void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx)
-{
-	struct gss_svc_reqctx  *grctx;
-
-	if (svc_ctx == NULL) {
-		return;
-	}
-
-	grctx = gss_svc_ctx2reqctx(svc_ctx);
-
-	CWARN("gss svc invalidate ctx %p(%u)\n",
-	      grctx->src_ctx, grctx->src_ctx->gsc_uid);
-	gss_svc_upcall_destroy_ctx(grctx->src_ctx);
-}
-
-static inline
-int gss_svc_payload(struct gss_svc_reqctx *grctx, int early,
-		    int msgsize, int privacy)
-{
-	/* we should treat early reply normally, but which is actually sharing
-	 * the same ctx with original request, so in this case we should
-	 * ignore the special ctx's special flags */
-	if (early == 0 && gss_svc_reqctx_is_special(grctx))
-		return grctx->src_reserve_len;
-
-	return gss_mech_payload(NULL, msgsize, privacy);
-}
-
-static int gss_svc_bulk_payload(struct gss_svc_ctx *gctx,
-				struct sptlrpc_flavor *flvr,
-				int read)
-{
-	int     payload = sizeof(struct ptlrpc_bulk_sec_desc);
-
-	if (read) {
-		switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) {
-		case SPTLRPC_BULK_SVC_NULL:
-			break;
-		case SPTLRPC_BULK_SVC_INTG:
-			payload += gss_mech_payload(NULL, 0, 0);
-			break;
-		case SPTLRPC_BULK_SVC_PRIV:
-			payload += gss_mech_payload(NULL, 0, 1);
-			break;
-		case SPTLRPC_BULK_SVC_AUTH:
-		default:
-			LBUG();
-		}
-	}
-
-	return payload;
-}
-
-int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
-{
-	struct gss_svc_reqctx       *grctx;
-	struct ptlrpc_reply_state   *rs;
-	int			  early, privacy, svc, bsd_off = 0;
-	__u32			ibuflens[2], buflens[4];
-	int			  ibufcnt = 0, bufcnt;
-	int			  txtsize, wmsg_size, rs_size;
-
-	LASSERT(msglen % 8 == 0);
-
-	if (req->rq_pack_bulk && !req->rq_bulk_read && !req->rq_bulk_write) {
-		CERROR("client request bulk sec on non-bulk rpc\n");
-		return -EPROTO;
-	}
-
-	svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc);
-	early = (req->rq_packed_final == 0);
-
-	grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	if (!early && gss_svc_reqctx_is_special(grctx))
-		privacy = 0;
-	else
-		privacy = (svc == SPTLRPC_SVC_PRIV);
-
-	if (privacy) {
-		/* inner clear buffers */
-		ibufcnt = 1;
-		ibuflens[0] = msglen;
-
-		if (req->rq_pack_bulk) {
-			LASSERT(grctx->src_reqbsd);
-
-			bsd_off = ibufcnt;
-			ibuflens[ibufcnt++] = gss_svc_bulk_payload(
-							grctx->src_ctx,
-							&req->rq_flvr,
-							req->rq_bulk_read);
-		}
-
-		txtsize = lustre_msg_size_v2(ibufcnt, ibuflens);
-		txtsize += GSS_MAX_CIPHER_BLOCK;
-
-		/* wrapper buffer */
-		bufcnt = 2;
-		buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-		buflens[1] = gss_svc_payload(grctx, early, txtsize, 1);
-	} else {
-		bufcnt = 2;
-		buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-		buflens[1] = msglen;
-
-		txtsize = buflens[0];
-		if (svc == SPTLRPC_SVC_INTG)
-			txtsize += buflens[1];
-
-		if (req->rq_pack_bulk) {
-			LASSERT(grctx->src_reqbsd);
-
-			bsd_off = bufcnt;
-			buflens[bufcnt] = gss_svc_bulk_payload(
-							grctx->src_ctx,
-							&req->rq_flvr,
-							req->rq_bulk_read);
-			if (svc == SPTLRPC_SVC_INTG)
-				txtsize += buflens[bufcnt];
-			bufcnt++;
-		}
-
-		if ((!early && gss_svc_reqctx_is_special(grctx)) ||
-		    svc != SPTLRPC_SVC_NULL)
-			buflens[bufcnt++] = gss_svc_payload(grctx, early,
-							    txtsize, 0);
-	}
-
-	wmsg_size = lustre_msg_size_v2(bufcnt, buflens);
-
-	rs_size = sizeof(*rs) + wmsg_size;
-	rs = req->rq_reply_state;
-
-	if (rs) {
-		/* pre-allocated */
-		LASSERT(rs->rs_size >= rs_size);
-	} else {
-		OBD_ALLOC_LARGE(rs, rs_size);
-		if (rs == NULL)
-			return -ENOMEM;
-
-		rs->rs_size = rs_size;
-	}
-
-	rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
-	rs->rs_repbuf_len = wmsg_size;
-
-	/* initialize the buffer */
-	if (privacy) {
-		lustre_init_msg_v2(rs->rs_repbuf, ibufcnt, ibuflens, NULL);
-		rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 0, msglen);
-	} else {
-		lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
-		rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc;
-
-		rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 1, 0);
-	}
-
-	if (bsd_off) {
-		grctx->src_repbsd = lustre_msg_buf(rs->rs_repbuf, bsd_off, 0);
-		grctx->src_repbsd_size = lustre_msg_buflen(rs->rs_repbuf,
-							   bsd_off);
-	}
-
-	gss_svc_reqctx_addref(grctx);
-	rs->rs_svc_ctx = req->rq_svc_ctx;
-
-	LASSERT(rs->rs_msg);
-	req->rq_reply_state = rs;
-	return 0;
-}
-
-static int gss_svc_seal(struct ptlrpc_request *req,
-			struct ptlrpc_reply_state *rs,
-			struct gss_svc_reqctx *grctx)
-{
-	struct gss_svc_ctx      *gctx = grctx->src_ctx;
-	rawobj_t		 hdrobj, msgobj, token;
-	struct gss_header       *ghdr;
-	__u8		    *token_buf;
-	int		      token_buflen;
-	__u32		    buflens[2], major;
-	int		      msglen, rc;
-
-	/* get clear data length. note embedded lustre_msg might
-	 * have been shrunk */
-	if (req->rq_replen != lustre_msg_buflen(rs->rs_repbuf, 0))
-		msglen = lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1);
-	else
-		msglen = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount,
-					    rs->rs_repbuf->lm_buflens);
-
-	/* temporarily use tail of buffer to hold gss header data */
-	LASSERT(msglen + PTLRPC_GSS_HEADER_SIZE <= rs->rs_repbuf_len);
-	ghdr = (struct gss_header *) ((char *) rs->rs_repbuf +
-				rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE);
-	ghdr->gh_version = PTLRPC_GSS_VERSION;
-	ghdr->gh_sp = LUSTRE_SP_ANY;
-	ghdr->gh_flags = 0;
-	ghdr->gh_proc = PTLRPC_GSS_PROC_DATA;
-	ghdr->gh_seq = grctx->src_wirectx.gw_seq;
-	ghdr->gh_svc = SPTLRPC_SVC_PRIV;
-	ghdr->gh_handle.len = 0;
-	if (req->rq_pack_bulk)
-		ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK;
-
-	/* allocate temporary cipher buffer */
-	token_buflen = gss_mech_payload(gctx->gsc_mechctx, msglen, 1);
-	OBD_ALLOC_LARGE(token_buf, token_buflen);
-	if (token_buf == NULL)
-		return -ENOMEM;
-
-	hdrobj.len = PTLRPC_GSS_HEADER_SIZE;
-	hdrobj.data = (__u8 *) ghdr;
-	msgobj.len = msglen;
-	msgobj.data = (__u8 *) rs->rs_repbuf;
-	token.len = token_buflen;
-	token.data = token_buf;
-
-	major = lgss_wrap(gctx->gsc_mechctx, &hdrobj, &msgobj,
-			  rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE, &token);
-	if (major != GSS_S_COMPLETE) {
-		CERROR("wrap message error: %08x\n", major);
-		GOTO(out_free, rc = -EPERM);
-	}
-	LASSERT(token.len <= token_buflen);
-
-	/* we are about to override data at rs->rs_repbuf, nullify pointers
-	 * to which to catch further illegal usage. */
-	if (req->rq_pack_bulk) {
-		grctx->src_repbsd = NULL;
-		grctx->src_repbsd_size = 0;
-	}
-
-	/* now fill the actual wire data
-	 * - gss header
-	 * - gss token
-	 */
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = token.len;
-
-	rs->rs_repdata_len = lustre_msg_size_v2(2, buflens);
-	LASSERT(rs->rs_repdata_len <= rs->rs_repbuf_len);
-
-	lustre_init_msg_v2(rs->rs_repbuf, 2, buflens, NULL);
-	rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc;
-
-	memcpy(lustre_msg_buf(rs->rs_repbuf, 0, 0), ghdr,
-	       PTLRPC_GSS_HEADER_SIZE);
-	memcpy(lustre_msg_buf(rs->rs_repbuf, 1, 0), token.data, token.len);
-
-	/* reply offset */
-	if (req->rq_packed_final &&
-	    (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT))
-		req->rq_reply_off = gss_at_reply_off_priv;
-	else
-		req->rq_reply_off = 0;
-
-	/* to catch upper layer's further access */
-	rs->rs_msg = NULL;
-	req->rq_repmsg = NULL;
-	req->rq_replen = 0;
-
-	rc = 0;
-out_free:
-	OBD_FREE_LARGE(token_buf, token_buflen);
-	return rc;
-}
-
-int gss_svc_authorize(struct ptlrpc_request *req)
-{
-	struct ptlrpc_reply_state *rs = req->rq_reply_state;
-	struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
-	struct gss_wire_ctx       *gw = &grctx->src_wirectx;
-	int			early, rc;
-
-	early = (req->rq_packed_final == 0);
-
-	if (!early && gss_svc_reqctx_is_special(grctx)) {
-		LASSERT(rs->rs_repdata_len != 0);
-
-		req->rq_reply_off = gss_at_reply_off_integ;
-		return 0;
-	}
-
-	/* early reply could happen in many cases */
-	if (!early &&
-	    gw->gw_proc != PTLRPC_GSS_PROC_DATA &&
-	    gw->gw_proc != PTLRPC_GSS_PROC_DESTROY) {
-		CERROR("proc %d not support\n", gw->gw_proc);
-		return -EINVAL;
-	}
-
-	LASSERT(grctx->src_ctx);
-
-	switch (gw->gw_svc) {
-	case SPTLRPC_SVC_NULL:
-	case SPTLRPC_SVC_AUTH:
-	case SPTLRPC_SVC_INTG:
-		rc = gss_svc_sign(req, rs, grctx, gw->gw_svc);
-		break;
-	case SPTLRPC_SVC_PRIV:
-		rc = gss_svc_seal(req, rs, grctx);
-		break;
-	default:
-		CERROR("Unknown service %d\n", gw->gw_svc);
-		GOTO(out, rc = -EINVAL);
-	}
-	rc = 0;
-
-out:
-	return rc;
-}
-
-void gss_svc_free_rs(struct ptlrpc_reply_state *rs)
-{
-	struct gss_svc_reqctx *grctx;
-
-	LASSERT(rs->rs_svc_ctx);
-	grctx = container_of(rs->rs_svc_ctx, struct gss_svc_reqctx, src_base);
-
-	gss_svc_reqctx_decref(grctx);
-	rs->rs_svc_ctx = NULL;
-
-	if (!rs->rs_prealloc)
-		OBD_FREE_LARGE(rs, rs->rs_size);
-}
-
-void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx)
-{
-	LASSERT(atomic_read(&ctx->sc_refcount) == 0);
-	gss_svc_reqctx_free(gss_svc_ctx2reqctx(ctx));
-}
-
-int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx,
-			 struct ptlrpc_svc_ctx *svc_ctx)
-{
-	struct gss_cli_ctx     *cli_gctx = ctx2gctx(cli_ctx);
-	struct gss_svc_ctx     *svc_gctx = gss_svc_ctx2gssctx(svc_ctx);
-	struct gss_ctx	 *mechctx = NULL;
-
-	LASSERT(cli_gctx);
-	LASSERT(svc_gctx && svc_gctx->gsc_mechctx);
-
-	cli_gctx->gc_proc = PTLRPC_GSS_PROC_DATA;
-	cli_gctx->gc_win = GSS_SEQ_WIN;
-
-	/* The problem is the reverse ctx might get lost in some recovery
-	 * situations, and the same svc_ctx will be used to re-create it.
-	 * if there's callback be sentout before that, new reverse ctx start
-	 * with sequence 0 will lead to future callback rpc be treated as
-	 * replay.
-	 *
-	 * each reverse root ctx will record its latest sequence number on its
-	 * buddy svcctx before be destroyed, so here we continue use it.
-	 */
-	atomic_set(&cli_gctx->gc_seq, svc_gctx->gsc_rvs_seq);
-
-	if (gss_svc_upcall_dup_handle(&cli_gctx->gc_svc_handle, svc_gctx)) {
-		CERROR("failed to dup svc handle\n");
-		goto err_out;
-	}
-
-	if (lgss_copy_reverse_context(svc_gctx->gsc_mechctx, &mechctx) !=
-	    GSS_S_COMPLETE) {
-		CERROR("failed to copy mech context\n");
-		goto err_svc_handle;
-	}
-
-	if (rawobj_dup(&cli_gctx->gc_handle, &svc_gctx->gsc_rvs_hdl)) {
-		CERROR("failed to dup reverse handle\n");
-		goto err_ctx;
-	}
-
-	cli_gctx->gc_mechctx = mechctx;
-	gss_cli_ctx_uptodate(cli_gctx);
-
-	return 0;
-
-err_ctx:
-	lgss_delete_sec_context(&mechctx);
-err_svc_handle:
-	rawobj_free(&cli_gctx->gc_svc_handle);
-err_out:
-	return -ENOMEM;
-}
-
-static void gss_init_at_reply_offset(void)
-{
-	__u32 buflens[3];
-	int clearsize;
-
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = lustre_msg_early_size();
-	buflens[2] = gss_cli_payload(NULL, buflens[1], 0);
-	gss_at_reply_off_integ = lustre_msg_size_v2(3, buflens);
-
-	buflens[0] = lustre_msg_early_size();
-	clearsize = lustre_msg_size_v2(1, buflens);
-	buflens[0] = PTLRPC_GSS_HEADER_SIZE;
-	buflens[1] = gss_cli_payload(NULL, clearsize, 0);
-	buflens[2] = gss_cli_payload(NULL, clearsize, 1);
-	gss_at_reply_off_priv = lustre_msg_size_v2(3, buflens);
-}
-
-int __init sptlrpc_gss_init(void)
-{
-	int rc;
-
-	rc = gss_init_lproc();
-	if (rc)
-		return rc;
-
-	rc = gss_init_cli_upcall();
-	if (rc)
-		goto out_lproc;
-
-	rc = gss_init_svc_upcall();
-	if (rc)
-		goto out_cli_upcall;
-
-	rc = init_kerberos_module();
-	if (rc)
-		goto out_svc_upcall;
-
-	/* register policy after all other stuff be initialized, because it
-	 * might be in used immediately after the registration. */
-
-	rc = gss_init_keyring();
-	if (rc)
-		goto out_kerberos;
-
-#ifdef HAVE_GSS_PIPEFS
-	rc = gss_init_pipefs();
-	if (rc)
-		goto out_keyring;
-#endif
-
-	gss_init_at_reply_offset();
-
-	return 0;
-
-#ifdef HAVE_GSS_PIPEFS
-out_keyring:
-	gss_exit_keyring();
-#endif
-
-out_kerberos:
-	cleanup_kerberos_module();
-out_svc_upcall:
-	gss_exit_svc_upcall();
-out_cli_upcall:
-	gss_exit_cli_upcall();
-out_lproc:
-	gss_exit_lproc();
-	return rc;
-}
-
-static void __exit sptlrpc_gss_exit(void)
-{
-	gss_exit_keyring();
-#ifdef HAVE_GSS_PIPEFS
-	gss_exit_pipefs();
-#endif
-	cleanup_kerberos_module();
-	gss_exit_svc_upcall();
-	gss_exit_cli_upcall();
-	gss_exit_lproc();
-}
-
-MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("GSS security policy for Lustre");
-MODULE_LICENSE("GPL");
-
-module_init(sptlrpc_gss_init);
-module_exit(sptlrpc_gss_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/import.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/import.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/import.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/import.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,14 +40,14 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <obd_support.h>
-#include <lustre_ha.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_export.h>
-#include <obd.h>
-#include <obd_cksum.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_export.h"
+#include "../include/obd.h"
+#include "../include/obd_cksum.h"
+#include "../include/obd_class.h"
 
 #include "ptlrpc_internal.h"
 
@@ -66,7 +66,7 @@ static void __import_set_state(struct ob
 	imp->imp_state = state;
 	imp->imp_state_hist[imp->imp_state_hist_idx].ish_state = state;
 	imp->imp_state_hist[imp->imp_state_hist_idx].ish_time =
-		cfs_time_current_sec();
+		get_seconds();
 	imp->imp_state_hist_idx = (imp->imp_state_hist_idx + 1) %
 		IMP_STATE_HIST_LEN;
 }
@@ -242,7 +242,7 @@ ptlrpc_inflight_deadline(struct ptlrpc_r
 
 static unsigned int ptlrpc_inflight_timeout(struct obd_import *imp)
 {
-	time_t now = cfs_time_current_sec();
+	time_t now = get_seconds();
 	struct list_head *tmp, *n;
 	struct ptlrpc_request *req;
 	unsigned int timeout = 0;
@@ -275,6 +275,7 @@ void ptlrpc_invalidate_import(struct obd
 	if (!imp->imp_invalid || imp->imp_obd->obd_no_recov)
 		ptlrpc_deactivate_import(imp);
 
+	CFS_FAIL_TIMEOUT(OBD_FAIL_MGS_CONNECT_NET, 3 * cfs_fail_val / 2);
 	LASSERT(imp->imp_invalid);
 
 	/* Wait forever until inflight == 0. We really can't do it another
@@ -392,6 +393,19 @@ void ptlrpc_activate_import(struct obd_i
 }
 EXPORT_SYMBOL(ptlrpc_activate_import);
 
+static void ptlrpc_pinger_force(struct obd_import *imp)
+{
+	CDEBUG(D_HA, "%s: waking up pinger s:%s\n", obd2cli_tgt(imp->imp_obd),
+	       ptlrpc_import_state_name(imp->imp_state));
+
+	spin_lock(&imp->imp_lock);
+	imp->imp_force_verify = 1;
+	spin_unlock(&imp->imp_lock);
+
+	if (imp->imp_state != LUSTRE_IMP_CONNECTING)
+		ptlrpc_pinger_wake_up();
+}
+
 void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
 {
 	LASSERT(!imp->imp_dlm_fake);
@@ -406,20 +420,30 @@ void ptlrpc_fail_import(struct obd_impor
 			ptlrpc_deactivate_import(imp);
 		}
 
-		CDEBUG(D_HA, "%s: waking up pinger\n",
-		       obd2cli_tgt(imp->imp_obd));
-
-		spin_lock(&imp->imp_lock);
-		imp->imp_force_verify = 1;
-		spin_unlock(&imp->imp_lock);
-
-		ptlrpc_pinger_wake_up();
+		ptlrpc_pinger_force(imp);
 	}
 }
 EXPORT_SYMBOL(ptlrpc_fail_import);
 
 int ptlrpc_reconnect_import(struct obd_import *imp)
 {
+#ifdef ENABLE_PINGER
+	struct l_wait_info lwi;
+	int secs = cfs_time_seconds(obd_timeout);
+	int rc;
+
+	ptlrpc_pinger_force(imp);
+
+	CDEBUG(D_HA, "%s: recovery started, waiting %u seconds\n",
+	       obd2cli_tgt(imp->imp_obd), secs);
+
+	lwi = LWI_TIMEOUT(secs, NULL, NULL);
+	rc = l_wait_event(imp->imp_recovery_waitq,
+			  !ptlrpc_import_in_recovery(imp), &lwi);
+	CDEBUG(D_HA, "%s: recovery finished s:%s\n", obd2cli_tgt(imp->imp_obd),
+	       ptlrpc_import_state_name(imp->imp_state));
+	return rc;
+#else
 	ptlrpc_set_import_discon(imp, 0);
 	/* Force a new connect attempt */
 	ptlrpc_invalidate_import(imp);
@@ -444,6 +468,7 @@ int ptlrpc_reconnect_import(struct obd_i
 	/* Attempt a new connect */
 	ptlrpc_recover_import(imp, NULL, 0);
 	return 0;
+#endif
 }
 EXPORT_SYMBOL(ptlrpc_reconnect_import);
 
@@ -469,7 +494,7 @@ static int import_select_connection(stru
 	}
 
 	list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
-		CDEBUG(D_HA, "%s: connect to NID %s last attempt "LPU64"\n",
+		CDEBUG(D_HA, "%s: connect to NID %s last attempt %llu\n",
 		       imp->imp_obd->obd_name,
 		       libcfs_nid2str(conn->oic_conn->c_peer.nid),
 		       conn->oic_last_attempt);
@@ -817,8 +842,7 @@ static int ptlrpc_connect_interpret(cons
 	/* check that server granted subset of flags we asked for. */
 	if ((ocd->ocd_connect_flags & imp->imp_connect_flags_orig) !=
 	    ocd->ocd_connect_flags) {
-		CERROR("%s: Server didn't granted asked subset of flags: "
-		       "asked="LPX64" grranted="LPX64"\n",
+		CERROR("%s: Server didn't granted asked subset of flags: asked=%#llx grranted=%#llx\n",
 		       imp->imp_obd->obd_name,imp->imp_connect_flags_orig,
 		       ocd->ocd_connect_flags);
 		GOTO(out, rc = -EPROTO);
@@ -876,8 +900,7 @@ static int ptlrpc_connect_interpret(cons
 		memset(&old_hdl, 0, sizeof(old_hdl));
 		if (!memcmp(&old_hdl, lustre_msg_get_handle(request->rq_repmsg),
 			    sizeof(old_hdl))) {
-			LCONSOLE_WARN("Reconnect to %s (at @%s) failed due "
-				      "bad handle "LPX64"\n",
+			LCONSOLE_WARN("Reconnect to %s (at @%s) failed due bad handle %#llx\n",
 				      obd2cli_tgt(imp->imp_obd),
 				      imp->imp_connection->c_remote_uuid.uuid,
 				      imp->imp_dlm_handle.cookie);
@@ -898,9 +921,7 @@ static int ptlrpc_connect_interpret(cons
 			 * participate since we can reestablish all of our state
 			 * with server again */
 			if ((MSG_CONNECT_RECOVERING & msg_flags)) {
-				CDEBUG(level,"%s@%s changed server handle from "
-				       LPX64" to "LPX64
-				       " but is still in recovery\n",
+				CDEBUG(level,"%s@%s changed server handle from %#llx to %#llx but is still in recovery\n",
 				       obd2cli_tgt(imp->imp_obd),
 				       imp->imp_connection->c_remote_uuid.uuid,
 				       imp->imp_remote_handle.cookie,
@@ -908,8 +929,7 @@ static int ptlrpc_connect_interpret(cons
 				       request->rq_repmsg)->cookie);
 			} else {
 				LCONSOLE_WARN("Evicted from %s (at %s) "
-					      "after server handle changed from "
-					      LPX64" to "LPX64"\n",
+					      "after server handle changed from %#llx to %#llx\n",
 					      obd2cli_tgt(imp->imp_obd),
 					      imp->imp_connection-> \
 					      c_remote_uuid.uuid,
@@ -973,8 +993,8 @@ static int ptlrpc_connect_interpret(cons
 	if (lustre_msg_get_last_committed(request->rq_repmsg) > 0 &&
 	    lustre_msg_get_last_committed(request->rq_repmsg) <
 	    aa->pcaa_peer_committed) {
-		CERROR("%s went back in time (transno "LPD64
-		       " was previously committed, server now claims "LPD64
+		CERROR("%s went back in time (transno %lld"
+		       " was previously committed, server now claims %lld"
 		       ")!  See https://bugzilla.lustre.org/show_bug.cgi?"
 		       "id=9646\n",
 		       obd2cli_tgt(imp->imp_obd), aa->pcaa_peer_committed,
@@ -1092,9 +1112,8 @@ finish:
 		 * disable lru_resize, etc. */
 		if (old_connect_flags != exp_connect_flags(exp) ||
 		    aa->pcaa_initial_connect) {
-			CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server "
-			       "flags: "LPX64"\n", imp->imp_obd->obd_name,
-			      ocd->ocd_connect_flags);
+			CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n",
+			       imp->imp_obd->obd_name, ocd->ocd_connect_flags);
 			imp->imp_obd->obd_namespace->ns_connect_flags =
 				ocd->ocd_connect_flags;
 			imp->imp_obd->obd_namespace->ns_orig_connect_flags =
@@ -1429,7 +1448,7 @@ int ptlrpc_disconnect_import(struct obd_
 
 	if (ptlrpc_import_in_recovery(imp)) {
 		struct l_wait_info lwi;
-		cfs_duration_t timeout;
+		long timeout;
 
 		if (AT_OFF) {
 			if (imp->imp_server_timeout)
@@ -1512,7 +1531,7 @@ extern unsigned int at_min, at_max, at_h
 int at_measured(struct adaptive_timeout *at, unsigned int val)
 {
 	unsigned int old = at->at_current;
-	time_t now = cfs_time_current_sec();
+	time_t now = get_seconds();
 	time_t binlimit = max_t(time_t, at_history / AT_BINS, 1);
 
 	LASSERT(at);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/layout.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/layout.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/layout.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/layout.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,21 +53,21 @@
 #include <linux/module.h>
 
 /* LUSTRE_VERSION_CODE */
-#include <lustre_ver.h>
+#include "../include/lustre_ver.h"
 
-#include <obd_support.h>
+#include "../include/obd_support.h"
 /* lustre_swab_mdt_body */
-#include <lustre/lustre_idl.h>
+#include "../include/lustre/lustre_idl.h"
 /* obd2cli_tgt() (required by DEBUG_REQ()) */
-#include <obd.h>
+#include "../include/obd.h"
 
 /* __REQ_LAYOUT_USER__ */
 #endif
 /* struct ptlrpc_request, lustre_msg* */
-#include <lustre_req_layout.h>
-#include <lustre_update.h>
-#include <lustre_acl.h>
-#include <lustre_debug.h>
+#include "../include/lustre_req_layout.h"
+#include "../include/lustre_update.h"
+#include "../include/lustre_acl.h"
+#include "../include/lustre_debug.h"
 
 /*
  * RQFs (see below) refer to two struct req_msg_field arrays describing the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_client.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_client.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_client.c	2014-09-28 17:29:07.000000000 -0400
@@ -42,11 +42,11 @@
 
 #define DEBUG_SUBSYSTEM S_LOG
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_class.h>
-#include <lustre_log.h>
-#include <lustre_net.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_net.h"
 #include <linux/list.h>
 
 #define LLOG_CLIENT_ENTRY(ctxt, imp) do {			     \
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_net.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_net.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/llog_net.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,13 +46,13 @@
 
 #define DEBUG_SUBSYSTEM S_LOG
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_class.h>
-#include <lustre_log.h>
+#include "../include/obd_class.h"
+#include "../include/lustre_log.h"
 #include <linux/list.h>
-#include <lvfs.h>
-#include <lustre_fsfilt.h>
+#include "../include/lvfs.h"
+#include "../include/lustre_fsfilt.h"
 
 int llog_initiator_connect(struct llog_ctxt *ctxt)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,12 +36,12 @@
 #define DEBUG_SUBSYSTEM S_CLASS
 
 
-#include <obd_support.h>
-#include <obd.h>
-#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
-#include <lustre_net.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/obd.h"
+#include "../include/lprocfs_status.h"
+#include "../include/lustre/lustre_idl.h"
+#include "../include/lustre_net.h"
+#include "../include/obd_class.h"
 #include "ptlrpc_internal.h"
 
 
@@ -180,7 +180,7 @@ const char* ll_eopcode2str(__u32 opcode)
 	LASSERT(ll_eopcode_table[opcode].opcode == opcode);
 	return ll_eopcode_table[opcode].opname;
 }
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir,
 			     char *name, struct proc_dir_entry **procroot_ret,
 			     struct lprocfs_stats **stats_ret)
@@ -628,7 +628,8 @@ out:
  * if the optional token is omitted, the operation is performed on both the
  * regular and high-priority (if the service has one) NRS head.
  */
-static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, const char *buffer,
+static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file,
+					const char __user *buffer,
 					size_t count, loff_t *off)
 {
 	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
@@ -726,12 +727,12 @@ ptlrpc_lprocfs_svc_req_history_seek(stru
 		 * be near the head), we shouldn't have to do long
 		 * re-scans */
 		LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq,
-			 "%s:%d: seek seq "LPU64", request seq "LPU64"\n",
+			 "%s:%d: seek seq %llu, request seq %llu\n",
 			 svcpt->scp_service->srv_name, svcpt->scp_cpt,
 			 srhi->srhi_seq, srhi->srhi_req->rq_history_seq);
 		LASSERTF(!list_empty(&svcpt->scp_hist_reqs),
-			 "%s:%d: seek offset "LPU64", request seq "LPU64", "
-			 "last culled "LPU64"\n",
+			 "%s:%d: seek offset %llu, request seq %llu, "
+			 "last culled %llu\n",
 			 svcpt->scp_service->srv_name, svcpt->scp_cpt,
 			 seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled);
 		e = &srhi->srhi_req->rq_history_list;
@@ -932,7 +933,7 @@ static int ptlrpc_lprocfs_svc_req_histor
 		 * must be just as careful as the service's request
 		 * parser. Currently I only print stuff here I know is OK
 		 * to look at coz it was set up in request_in_callback()!!! */
-		seq_printf(s, LPD64":%s:%s:x"LPU64":%d:%s:%ld:%lds(%+lds) ",
+		seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%ld:%lds(%+lds) ",
 			   req->rq_history_seq, libcfs_nid2str(req->rq_self),
 			   libcfs_id2str(req->rq_peer), req->rq_xid,
 			   req->rq_reqlen, ptlrpc_rqphase2str(req),
@@ -991,7 +992,7 @@ static int ptlrpc_lprocfs_timeouts_seq_s
 		cur	= at_get(&svcpt->scp_at_estimate);
 		worst	= svcpt->scp_at_estimate.at_worst_ever;
 		worstt	= svcpt->scp_at_estimate.at_worst_time;
-		s2dhms(&ts, cfs_time_current_sec() - worstt);
+		s2dhms(&ts, get_seconds() - worstt);
 
 		seq_printf(m, "%10s : cur %3u  worst %3u (at %ld, "
 			      DHMS_FMT" ago) ", "service",
@@ -1339,4 +1340,4 @@ int lprocfs_wr_pinger_recov(struct file
 }
 EXPORT_SYMBOL(lprocfs_wr_pinger_recov);
 
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -18,8 +18,3 @@ ptlrpc_objs += sec_null.o sec_plain.o nr
 ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs)
 ptlrpc-$(CONFIG_PROC_FS) += sec_lproc.o
 ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.o
-
-obj-$(CONFIG_PTLRPC_GSS) += gss/
-
-
-ccflags-y := -I$(src)/../include
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/niobuf.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/niobuf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/niobuf.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,11 +35,11 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_lib.h>
-#include <obd.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_lib.h"
+#include "../include/obd.h"
+#include "../include/obd_class.h"
 #include "ptlrpc_internal.h"
 
 /**
@@ -79,7 +79,7 @@ static int ptl_send_buf(lnet_handle_md_t
 		return -ENOMEM;
 	}
 
-	CDEBUG(D_NET, "Sending %d bytes to portal %d, xid "LPD64", offset %u\n",
+	CDEBUG(D_NET, "Sending %d bytes to portal %d, xid %lld, offset %u\n",
 	       len, portal, xid, offset);
 
 	rc = LNetPut(conn->c_self, *mdh, ack,
@@ -89,7 +89,7 @@ static int ptl_send_buf(lnet_handle_md_t
 		/* We're going to get an UNLINK event when I unlink below,
 		 * which will complete just like any other failed send, so
 		 * I fall through and return success here! */
-		CERROR("LNetPut(%s, %d, "LPD64") failed: %d\n",
+		CERROR("LNetPut(%s, %d, %lld) failed: %d\n",
 		       libcfs_id2str(conn->c_peer), portal, xid, rc);
 		rc2 = LNetMDUnlink(*mdh);
 		LASSERTF(rc2 == 0, "rc2 = %d\n", rc2);
@@ -159,7 +159,7 @@ int ptlrpc_register_bulk(struct ptlrpc_r
 	LASSERTF(!(desc->bd_registered &&
 		   req->rq_send_state != LUSTRE_IMP_REPLAY) ||
 		 xid != desc->bd_last_xid,
-		 "registered: %d  rq_xid: "LPU64" bd_last_xid: "LPU64"\n",
+		 "registered: %d  rq_xid: %llu bd_last_xid: %llu\n",
 		 desc->bd_registered, xid, desc->bd_last_xid);
 
 	total_md = (desc->bd_iov_count + LNET_MAX_IOV - 1) / LNET_MAX_IOV;
@@ -179,7 +179,7 @@ int ptlrpc_register_bulk(struct ptlrpc_r
 		rc = LNetMEAttach(desc->bd_portal, peer, xid, 0,
 				  LNET_UNLINK, LNET_INS_AFTER, &me_h);
 		if (rc != 0) {
-			CERROR("%s: LNetMEAttach failed x"LPU64"/%d: rc = %d\n",
+			CERROR("%s: LNetMEAttach failed x%llu/%d: rc = %d\n",
 			       desc->bd_import->imp_obd->obd_name, xid,
 			       posted_md, rc);
 			break;
@@ -189,7 +189,7 @@ int ptlrpc_register_bulk(struct ptlrpc_r
 		rc = LNetMDAttach(me_h, md, LNET_UNLINK,
 				  &desc->bd_mds[posted_md]);
 		if (rc != 0) {
-			CERROR("%s: LNetMDAttach failed x"LPU64"/%d: rc = %d\n",
+			CERROR("%s: LNetMDAttach failed x%llu/%d: rc = %d\n",
 			       desc->bd_import->imp_obd->obd_name, xid,
 			       posted_md, rc);
 			rc2 = LNetMEUnlink(me_h);
@@ -213,7 +213,7 @@ int ptlrpc_register_bulk(struct ptlrpc_r
 	 * infer the number of bulks that were prepared */
 	req->rq_xid = --xid;
 	LASSERTF(desc->bd_last_xid == (req->rq_xid & PTLRPC_BULK_OPS_MASK),
-		 "bd_last_xid = x"LPU64", rq_xid = x"LPU64"\n",
+		 "bd_last_xid = x%llu, rq_xid = x%llu\n",
 		 desc->bd_last_xid, req->rq_xid);
 
 	spin_lock(&desc->bd_lock);
@@ -225,7 +225,7 @@ int ptlrpc_register_bulk(struct ptlrpc_r
 	spin_unlock(&desc->bd_lock);
 
 	CDEBUG(D_NET, "Setup %u bulk %s buffers: %u pages %u bytes, "
-	       "xid x"LPX64"-"LPX64", portal %u\n", desc->bd_md_count,
+	       "xid x%#llx-%#llx, portal %u\n", desc->bd_md_count,
 	       desc->bd_type == BULK_GET_SOURCE ? "get-source" : "put-sink",
 	       desc->bd_iov_count, desc->bd_nob,
 	       desc->bd_last_xid, req->rq_xid, desc->bd_portal);
@@ -252,7 +252,7 @@ int ptlrpc_unregister_bulk(struct ptlrpc
 	/* Let's setup deadline for reply unlink. */
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_BULK_UNLINK) &&
 	    async && req->rq_bulk_deadline == 0)
-		req->rq_bulk_deadline = cfs_time_current_sec() + LONG_UNLINK;
+		req->rq_bulk_deadline = get_seconds() + LONG_UNLINK;
 
 	if (ptlrpc_client_bulk_active(req) == 0)	/* completed or */
 		return 1;				/* never registered */
@@ -303,7 +303,7 @@ static void ptlrpc_at_set_reply(struct p
 {
 	struct ptlrpc_service_part	*svcpt = req->rq_rqbd->rqbd_svcpt;
 	struct ptlrpc_service		*svc = svcpt->scp_service;
-	int service_time = max_t(int, cfs_time_current_sec() -
+	int service_time = max_t(int, get_seconds() -
 				 req->rq_arrival_time.tv_sec, 1);
 
 	if (!(flags & PTLRPC_REPLY_EARLY) &&
@@ -422,7 +422,7 @@ int ptlrpc_send_reply(struct ptlrpc_requ
 	if (unlikely(rc))
 		goto out;
 
-	req->rq_sent = cfs_time_current_sec();
+	req->rq_sent = get_seconds();
 
 	rc = ptl_send_buf(&rs->rs_md_h, rs->rs_repbuf, rs->rs_repdata_len,
 			  (rs->rs_difficult && !rs->rs_no_ack) ?
@@ -505,11 +505,12 @@ int ptl_send_rpc(struct ptlrpc_request *
 	/* If this is a re-transmit, we're required to have disengaged
 	 * cleanly from the previous attempt */
 	LASSERT(!request->rq_receiving_reply);
+	LASSERT(!((lustre_msg_get_flags(request->rq_reqmsg) & MSG_REPLAY) &&
+		(request->rq_import->imp_state == LUSTRE_IMP_FULL)));
 
-	if (request->rq_import->imp_obd &&
-	    request->rq_import->imp_obd->obd_fail) {
+	if (unlikely(obd != NULL && obd->obd_fail)) {
 		CDEBUG(D_HA, "muting rpc for failed imp obd %s\n",
-		       request->rq_import->imp_obd->obd_name);
+			obd->obd_name);
 		/* this prevents us from waiting in ptlrpc_queue_wait */
 		spin_lock(&request->rq_lock);
 		request->rq_err = 1;
@@ -579,8 +580,9 @@ int ptl_send_rpc(struct ptlrpc_request *
 	spin_lock(&request->rq_lock);
 	/* If the MD attach succeeds, there _will_ be a reply_in callback */
 	request->rq_receiving_reply = !noreply;
+	request->rq_req_unlink = 1;
 	/* We are responsible for unlinking the reply buffer */
-	request->rq_must_unlink = !noreply;
+	request->rq_reply_unlink = !noreply;
 	/* Clear any flags that may be present from previous sends. */
 	request->rq_replied = 0;
 	request->rq_err = 0;
@@ -603,7 +605,7 @@ int ptl_send_rpc(struct ptlrpc_request *
 		reply_md.user_ptr  = &request->rq_reply_cbid;
 		reply_md.eq_handle = ptlrpc_eq_h;
 
-		/* We must see the unlink callback to unset rq_must_unlink,
+		/* We must see the unlink callback to unset rq_reply_unlink,
 		   so we can't auto-unlink */
 		rc = LNetMDAttach(reply_me_h, reply_md, LNET_RETAIN,
 				  &request->rq_reply_md_h);
@@ -617,22 +619,21 @@ int ptl_send_rpc(struct ptlrpc_request *
 			GOTO(cleanup_me, rc = -ENOMEM);
 		}
 
-		CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid "LPU64
-		       ", portal %u\n",
+		CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid %llu, portal %u\n",
 		       request->rq_repbuf_len, request->rq_xid,
 		       request->rq_reply_portal);
 	}
 
 	/* add references on request for request_out_callback */
 	ptlrpc_request_addref(request);
-	if (obd->obd_svc_stats != NULL)
+	if (obd != NULL && obd->obd_svc_stats != NULL)
 		lprocfs_counter_add(obd->obd_svc_stats, PTLRPC_REQACTIVE_CNTR,
 			atomic_read(&request->rq_import->imp_inflight));
 
 	OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_DELAY_SEND, request->rq_timeout + 5);
 
 	do_gettimeofday(&request->rq_arrival_time);
-	request->rq_sent = cfs_time_current_sec();
+	request->rq_sent = get_seconds();
 	/* We give the server rq_timeout secs to process the req, and
 	   add the network latency for our local timeout. */
 	request->rq_deadline = request->rq_sent + request->rq_timeout +
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,11 +40,11 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lprocfs_status.h>
-#include <linux/libcfs/libcfs.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lprocfs_status.h"
+#include "../../include/linux/libcfs/libcfs.h"
 #include "ptlrpc_internal.h"
 
 /* XXX: This is just for liblustre. Remove the #if defined directive when the
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c	2014-09-28 17:29:07.000000000 -0400
@@ -47,9 +47,9 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-#include <obd_support.h>
-#include <obd_class.h>
-#include <linux/libcfs/libcfs.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../../include/linux/libcfs/libcfs.h"
 #include "ptlrpc_internal.h"
 
 /**
@@ -174,9 +174,9 @@ struct ptlrpc_nrs_request * nrs_fifo_req
 
 		list_del_init(&nrq->nr_u.fifo.fr_list);
 
-		CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: "LPU64
-		       "\n", policy->pol_desc->pd_name,
-		       libcfs_id2str(req->rq_peer), nrq->nr_u.fifo.fr_sequence);
+		CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: %llu\n",
+		       policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
+		       nrq->nr_u.fifo.fr_sequence);
 	}
 
 	return nrq;
@@ -236,7 +236,7 @@ static void nrs_fifo_req_stop(struct ptl
 	struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
 						  rq_nrq);
 
-	CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: "LPU64"\n",
+	CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n",
 	       policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
 	       nrq->nr_u.fifo.fr_sequence);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,13 +44,13 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <obd_cksum.h>
-#include <lustre/ll_fiemap.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/obd_cksum.h"
+#include "../include/lustre/ll_fiemap.h"
 
 static inline int lustre_msg_hdr_size_v2(int count)
 {
@@ -2140,8 +2140,8 @@ static void print_lum(struct lov_user_md
 	CDEBUG(D_OTHER, "lov_user_md %p:\n", lum);
 	CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic);
 	CDEBUG(D_OTHER, "\tlmm_pattern: %#x\n", lum->lmm_pattern);
-	CDEBUG(D_OTHER, "\tlmm_object_id: "LPU64"\n", lmm_oi_id(&lum->lmm_oi));
-	CDEBUG(D_OTHER, "\tlmm_object_gr: "LPU64"\n", lmm_oi_seq(&lum->lmm_oi));
+	CDEBUG(D_OTHER, "\tlmm_object_id: %llu\n", lmm_oi_id(&lum->lmm_oi));
+	CDEBUG(D_OTHER, "\tlmm_object_gr: %llu\n", lmm_oi_seq(&lum->lmm_oi));
 	CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size);
 	CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count);
 	CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n",
@@ -2292,7 +2292,7 @@ EXPORT_SYMBOL(dump_ioo);
 
 void dump_rniobuf(struct niobuf_remote *nb)
 {
-	CDEBUG(D_RPCTRACE, "niobuf_remote: offset="LPU64", len=%d, flags=%x\n",
+	CDEBUG(D_RPCTRACE, "niobuf_remote: offset=%llu, len=%d, flags=%x\n",
 	       nb->offset, nb->len, nb->flags);
 }
 EXPORT_SYMBOL(dump_rniobuf);
@@ -2305,20 +2305,20 @@ void dump_obdo(struct obdo *oa)
 	if (valid & OBD_MD_FLID)
 		CDEBUG(D_RPCTRACE, "obdo: id = "DOSTID"\n", POSTID(&oa->o_oi));
 	if (valid & OBD_MD_FLFID)
-		CDEBUG(D_RPCTRACE, "obdo: o_parent_seq = "LPX64"\n",
+		CDEBUG(D_RPCTRACE, "obdo: o_parent_seq = %#llx\n",
 		       oa->o_parent_seq);
 	if (valid & OBD_MD_FLSIZE)
-		CDEBUG(D_RPCTRACE, "obdo: o_size = "LPD64"\n", oa->o_size);
+		CDEBUG(D_RPCTRACE, "obdo: o_size = %lld\n", oa->o_size);
 	if (valid & OBD_MD_FLMTIME)
-		CDEBUG(D_RPCTRACE, "obdo: o_mtime = "LPD64"\n", oa->o_mtime);
+		CDEBUG(D_RPCTRACE, "obdo: o_mtime = %lld\n", oa->o_mtime);
 	if (valid & OBD_MD_FLATIME)
-		CDEBUG(D_RPCTRACE, "obdo: o_atime = "LPD64"\n", oa->o_atime);
+		CDEBUG(D_RPCTRACE, "obdo: o_atime = %lld\n", oa->o_atime);
 	if (valid & OBD_MD_FLCTIME)
-		CDEBUG(D_RPCTRACE, "obdo: o_ctime = "LPD64"\n", oa->o_ctime);
+		CDEBUG(D_RPCTRACE, "obdo: o_ctime = %lld\n", oa->o_ctime);
 	if (valid & OBD_MD_FLBLOCKS)   /* allocation of space */
-		CDEBUG(D_RPCTRACE, "obdo: o_blocks = "LPD64"\n", oa->o_blocks);
+		CDEBUG(D_RPCTRACE, "obdo: o_blocks = %lld\n", oa->o_blocks);
 	if (valid & OBD_MD_FLGRANT)
-		CDEBUG(D_RPCTRACE, "obdo: o_grant = "LPD64"\n", oa->o_grant);
+		CDEBUG(D_RPCTRACE, "obdo: o_grant = %lld\n", oa->o_grant);
 	if (valid & OBD_MD_FLBLKSZ)
 		CDEBUG(D_RPCTRACE, "obdo: o_blksize = %d\n", oa->o_blksize);
 	if (valid & (OBD_MD_FLTYPE | OBD_MD_FLMODE))
@@ -2344,7 +2344,7 @@ void dump_obdo(struct obdo *oa)
 		CDEBUG(D_RPCTRACE, "obdo: o_parent_oid = %x\n",
 		       oa->o_parent_oid);
 	if (valid & OBD_MD_FLEPOCH)
-		CDEBUG(D_RPCTRACE, "obdo: o_ioepoch = "LPD64"\n",
+		CDEBUG(D_RPCTRACE, "obdo: o_ioepoch = %lld\n",
 		       oa->o_ioepoch);
 	if (valid & OBD_MD_FLFID) {
 		CDEBUG(D_RPCTRACE, "obdo: o_stripe_idx = %u\n",
@@ -2353,7 +2353,7 @@ void dump_obdo(struct obdo *oa)
 		       oa->o_parent_ver);
 	}
 	if (valid & OBD_MD_FLHANDLE)
-		CDEBUG(D_RPCTRACE, "obdo: o_handle = "LPD64"\n",
+		CDEBUG(D_RPCTRACE, "obdo: o_handle = %lld\n",
 		       oa->o_handle.cookie);
 	if (valid & OBD_MD_FLCOOKIE)
 		CDEBUG(D_RPCTRACE, "obdo: o_lcookie = "
@@ -2421,7 +2421,7 @@ void _debug_req(struct ptlrpc_request *r
 
 	va_start(args, fmt);
 	libcfs_debug_vmsg2(msgdata, fmt, args,
-			   " req@%p x"LPU64"/t"LPD64"("LPD64") o%d->%s@%s:%d/%d"
+			   " req@%p x%llu/t%lld(%lld) o%d->%s@%s:%d/%d"
 			   " lens %d/%d e %d to %d dl "CFS_TIME_T" ref %d "
 			   "fl "REQ_FLAGS_FMT"/%x/%x rc %d/%d\n",
 			   req, req->rq_xid, req->rq_transno,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pers.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pers.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pers.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pers.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,11 +34,11 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-#include <lustre_ha.h>
-#include <lustre_import.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_import.h"
 
 #include "ptlrpc_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pinger.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pinger.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/pinger.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/pinger.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,8 +40,8 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-#include <obd_support.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
 #include "ptlrpc_internal.h"
 
 static int suppress_pings;
@@ -141,10 +141,10 @@ static inline int ptlrpc_next_reconnect(
 		return cfs_time_shift(obd_timeout);
 }
 
-cfs_duration_t pinger_check_timeout(cfs_time_t time)
+long pinger_check_timeout(unsigned long time)
 {
 	struct timeout_item *item;
-	cfs_time_t timeout = PING_INTERVAL;
+	unsigned long timeout = PING_INTERVAL;
 
 	/* The timeout list is a increase order sorted list */
 	mutex_lock(&pinger_mutex);
@@ -224,6 +224,11 @@ static void ptlrpc_pinger_process_import
 		       "or recovery disabled: %s)\n",
 		       imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd),
 		       ptlrpc_import_state_name(level));
+		if (force) {
+			spin_lock(&imp->imp_lock);
+			imp->imp_force_verify = 1;
+			spin_unlock(&imp->imp_lock);
+		}
 	} else if ((imp->imp_pingable && !suppress) || force_next || force) {
 		ptlrpc_ping(imp);
 	}
@@ -239,9 +244,9 @@ static int ptlrpc_pinger_main(void *arg)
 
 	/* And now, loop forever, pinging as needed. */
 	while (1) {
-		cfs_time_t this_ping = cfs_time_current();
+		unsigned long this_ping = cfs_time_current();
 		struct l_wait_info lwi;
-		cfs_duration_t time_to_next_wake;
+		long time_to_next_wake;
 		struct timeout_item *item;
 		struct list_head *iter;
 
@@ -278,8 +283,7 @@ static int ptlrpc_pinger_main(void *arg)
 		       CFS_TIME_T")\n", time_to_next_wake,
 		       cfs_time_add(this_ping,cfs_time_seconds(PING_INTERVAL)));
 		if (time_to_next_wake > 0) {
-			lwi = LWI_TIMEOUT(max_t(cfs_duration_t,
-						time_to_next_wake,
+			lwi = LWI_TIMEOUT(max_t(long, time_to_next_wake,
 						cfs_time_seconds(1)),
 					  NULL, NULL);
 			l_wait_event(thread->t_ctl_waitq,
@@ -601,7 +605,7 @@ static int ping_evictor_main(void *arg)
 				     obd_evict_list);
 		spin_unlock(&pet_lock);
 
-		expire_time = cfs_time_current_sec() - PING_EVICT_TIMEOUT;
+		expire_time = get_seconds() - PING_EVICT_TIMEOUT;
 
 		CDEBUG(D_HA, "evicting all exports of obd %s older than %ld\n",
 		       obd->obd_name, expire_time);
@@ -626,9 +630,9 @@ static int ping_evictor_main(void *arg)
 					      obd->obd_name,
 					      obd_uuid2str(&exp->exp_client_uuid),
 					      obd_export_nid2str(exp),
-					      (long)(cfs_time_current_sec() -
+					      (long)(get_seconds() -
 						     exp->exp_last_request_time),
-					      exp, (long)cfs_time_current_sec(),
+					      exp, (long)get_seconds(),
 					      (long)expire_time,
 					      (long)exp->exp_last_request_time);
 				CDEBUG(D_HA, "Last request was at %ld\n",
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,16 +55,15 @@
 
 #define DEBUG_SUBSYSTEM S_RPC
 
-# include <linux/libcfs/libcfs.h>
-
-#include <lustre_net.h>
-# include <lustre_lib.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <lustre_ha.h>
-#include <obd_class.h>   /* for obd_zombie */
-#include <obd_support.h> /* for OBD_FAIL_CHECK */
-#include <cl_object.h> /* cl_env_{get,put}() */
-#include <lprocfs_status.h>
+#include "../include/lustre_net.h"
+#include "../include/lustre_lib.h"
+#include "../include/lustre_ha.h"
+#include "../include/obd_class.h"	/* for obd_zombie */
+#include "../include/obd_support.h"	/* for OBD_FAIL_CHECK */
+#include "../include/cl_object.h"	/* cl_env_{get,put}() */
+#include "../include/lprocfs_status.h"
 
 #include "ptlrpc_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h	2014-09-28 17:29:07.000000000 -0400
@@ -76,7 +76,7 @@ void ptlrpc_initiate_recovery(struct obd
 int lustre_unpack_req_ptlrpc_body(struct ptlrpc_request *req, int offset);
 int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset);
 
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 void ptlrpc_lprocfs_register_service(struct proc_dir_entry *proc_entry,
 				     struct ptlrpc_service *svc);
 void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc);
@@ -88,7 +88,7 @@ void ptlrpc_lprocfs_do_request_stat(stru
 #define ptlrpc_lprocfs_unregister_service(params...) do {} while (0)
 #define ptlrpc_lprocfs_rpc_sent(params...) do {} while (0)
 #define ptlrpc_lprocfs_do_request_stat(params...) do {} while (0)
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
 
 /* NRS */
 
@@ -263,7 +263,7 @@ void sptlrpc_enc_pool_fini(void);
 int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v);
 
 /* sec_lproc.c */
-#ifdef LPROCFS
+#if defined (CONFIG_PROC_FS)
 int  sptlrpc_lproc_init(void);
 void sptlrpc_lproc_fini(void);
 #else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c	2014-09-28 17:29:07.000000000 -0400
@@ -37,10 +37,10 @@
 #define DEBUG_SUBSYSTEM S_RPC
 
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_req_layout.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_req_layout.h"
 
 #include "ptlrpc_internal.h"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/recover.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/recover.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/recover.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/recover.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,16 +39,16 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-# include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_support.h>
-#include <lustre_ha.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_export.h>
-#include <obd.h>
-#include <obd_ost.h>
-#include <obd_class.h>
+#include "../include/obd_support.h"
+#include "../include/lustre_ha.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_export.h"
+#include "../include/obd.h"
+#include "../include/obd_ost.h"
+#include "../include/obd_class.h"
 #include <linux/list.h>
 
 #include "ptlrpc_internal.h"
@@ -85,7 +85,7 @@ int ptlrpc_replay_next(struct obd_import
 	last_transno = imp->imp_last_replay_transno;
 	spin_unlock(&imp->imp_lock);
 
-	CDEBUG(D_HA, "import %p from %s committed "LPU64" last "LPU64"\n",
+	CDEBUG(D_HA, "import %p from %s committed %llu last %llu\n",
 	       imp, obd2cli_tgt(imp->imp_obd),
 	       imp->imp_peer_committed_transno, last_transno);
 
@@ -164,8 +164,8 @@ int ptlrpc_replay_next(struct obd_import
 	if (req != NULL) {
 		rc = ptlrpc_replay_req(req);
 		if (rc) {
-			CERROR("recovery replay error %d for req "
-			       LPU64"\n", rc, req->rq_xid);
+			CERROR("recovery replay error %d for req %llu\n",
+			       rc, req->rq_xid);
 			return rc;
 		}
 		*inflight = 1;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,17 +40,17 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/crypto.h>
 
-#include <obd.h>
-#include <obd_cksum.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_sec.h>
+#include "../include/obd.h"
+#include "../include/obd_cksum.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_sec.h"
 
 #include "ptlrpc_internal.h"
 
@@ -113,7 +113,7 @@ static struct ptlrpc_enc_page_pool {
 	unsigned long    epp_st_missings;       /* # of cache missing */
 	unsigned long    epp_st_lowfree;	/* lowest free pages reached */
 	unsigned int     epp_st_max_wqlen;      /* highest waitqueue length */
-	cfs_time_t       epp_st_max_wait;       /* in jiffies */
+	unsigned long       epp_st_max_wait;       /* in jiffies */
 	/*
 	 * pointers to pools
 	 */
@@ -156,8 +156,8 @@ int sptlrpc_proc_enc_pool_seq_show(struc
 		      page_pools.epp_total_pages,
 		      page_pools.epp_free_pages,
 		      page_pools.epp_idle_idx,
-		      cfs_time_current_sec() - page_pools.epp_last_shrink,
-		      cfs_time_current_sec() - page_pools.epp_last_access,
+		      get_seconds() - page_pools.epp_last_shrink,
+		      get_seconds() - page_pools.epp_last_access,
 		      page_pools.epp_st_max_pages,
 		      page_pools.epp_st_grows,
 		      page_pools.epp_st_grow_fails,
@@ -228,7 +228,7 @@ static unsigned long enc_pools_shrink_co
 	 * if no pool access for a long time, we consider it's fully idle.
 	 * a little race here is fine.
 	 */
-	if (unlikely(cfs_time_current_sec() - page_pools.epp_last_access >
+	if (unlikely(get_seconds() - page_pools.epp_last_access >
 		     CACHE_QUIESCENT_PERIOD)) {
 		spin_lock(&page_pools.epp_lock);
 		page_pools.epp_idle_idx = IDLE_IDX_MAX;
@@ -255,7 +255,7 @@ static unsigned long enc_pools_shrink_sc
 		       (long)sc->nr_to_scan, page_pools.epp_free_pages);
 
 		page_pools.epp_st_shrinks++;
-		page_pools.epp_last_shrink = cfs_time_current_sec();
+		page_pools.epp_last_shrink = get_seconds();
 	}
 	spin_unlock(&page_pools.epp_lock);
 
@@ -263,7 +263,7 @@ static unsigned long enc_pools_shrink_sc
 	 * if no pool access for a long time, we consider it's fully idle.
 	 * a little race here is fine.
 	 */
-	if (unlikely(cfs_time_current_sec() - page_pools.epp_last_access >
+	if (unlikely(get_seconds() - page_pools.epp_last_access >
 		     CACHE_QUIESCENT_PERIOD)) {
 		spin_lock(&page_pools.epp_lock);
 		page_pools.epp_idle_idx = IDLE_IDX_MAX;
@@ -498,7 +498,7 @@ int sptlrpc_enc_pool_get_pages(struct pt
 {
 	wait_queue_t  waitlink;
 	unsigned long   this_idle = -1;
-	cfs_time_t      tick = 0;
+	unsigned long      tick = 0;
 	long	    now;
 	int	     p_idx, g_idx;
 	int	     i;
@@ -523,7 +523,7 @@ again:
 		if (tick == 0)
 			tick = cfs_time_current();
 
-		now = cfs_time_current_sec();
+		now = get_seconds();
 
 		page_pools.epp_st_missings++;
 		page_pools.epp_pages_short += desc->bd_iov_count;
@@ -602,7 +602,7 @@ again:
 				   this_idle) /
 				  (IDLE_IDX_WEIGHT + 1);
 
-	page_pools.epp_last_access = cfs_time_current_sec();
+	page_pools.epp_last_access = get_seconds();
 
 	spin_unlock(&page_pools.epp_lock);
 	return 0;
@@ -729,8 +729,8 @@ int sptlrpc_enc_pool_init(void)
 	page_pools.epp_growing = 0;
 
 	page_pools.epp_idle_idx = 0;
-	page_pools.epp_last_shrink = cfs_time_current_sec();
-	page_pools.epp_last_access = cfs_time_current_sec();
+	page_pools.epp_last_shrink = get_seconds();
+	page_pools.epp_last_access = get_seconds();
 
 	spin_lock_init(&page_pools.epp_lock);
 	page_pools.epp_total_pages = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,17 +40,17 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/crypto.h>
 #include <linux/key.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_sec.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_sec.h"
 
 #include "ptlrpc_internal.h"
 
@@ -305,8 +305,8 @@ EXPORT_SYMBOL(sptlrpc_cli_ctx_put);
  */
 void sptlrpc_cli_ctx_expire(struct ptlrpc_cli_ctx *ctx)
 {
-	LASSERT(ctx->cc_ops->die);
-	ctx->cc_ops->die(ctx, 0);
+	LASSERT(ctx->cc_ops->force_die);
+	ctx->cc_ops->force_die(ctx, 0);
 }
 EXPORT_SYMBOL(sptlrpc_cli_ctx_expire);
 
@@ -344,7 +344,7 @@ static int import_sec_check_expire(struc
 
 	spin_lock(&imp->imp_lock);
 	if (imp->imp_sec_expire &&
-	    imp->imp_sec_expire < cfs_time_current_sec()) {
+	    imp->imp_sec_expire < get_seconds()) {
 		adapt = 1;
 		imp->imp_sec_expire = 0;
 	}
@@ -591,7 +591,7 @@ int ctx_refresh_timeout(void *data)
 	 * later than the context refresh expire time.
 	 */
 	if (rc == 0)
-		req->rq_cli_ctx->cc_ops->die(req->rq_cli_ctx, 0);
+		req->rq_cli_ctx->cc_ops->force_die(req->rq_cli_ctx, 0);
 	return rc;
 }
 
@@ -992,7 +992,7 @@ static int do_cli_unwrap_reply(struct pt
 	case 0:
 		break;
 	default:
-		CERROR("failed unpack reply: x"LPU64"\n", req->rq_xid);
+		CERROR("failed unpack reply: x%llu\n", req->rq_xid);
 		return -EPROTO;
 	}
 
@@ -1774,7 +1774,7 @@ int sptlrpc_target_export_check(struct o
 		exp->exp_flvr_old[1] = exp->exp_flvr_old[0];
 		exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0];
 		exp->exp_flvr_old[0] = exp->exp_flvr;
-		exp->exp_flvr_expire[0] = cfs_time_current_sec() +
+		exp->exp_flvr_expire[0] = get_seconds() +
 					  EXP_FLVR_UPDATE_EXPIRE;
 		exp->exp_flvr = flavor;
 
@@ -1848,7 +1848,7 @@ int sptlrpc_target_export_check(struct o
 	}
 
 	if (exp->exp_flvr_expire[0]) {
-		if (exp->exp_flvr_expire[0] >= cfs_time_current_sec()) {
+		if (exp->exp_flvr_expire[0] >= get_seconds()) {
 			if (flavor_allowed(&exp->exp_flvr_old[0], req)) {
 				CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
 				       "middle one ("CFS_DURATION_T")\n", exp,
@@ -1856,7 +1856,7 @@ int sptlrpc_target_export_check(struct o
 				       exp->exp_flvr_old[0].sf_rpc,
 				       exp->exp_flvr_old[1].sf_rpc,
 				       exp->exp_flvr_expire[0] -
-						cfs_time_current_sec());
+						get_seconds());
 				spin_unlock(&exp->exp_lock);
 				return 0;
 			}
@@ -1873,7 +1873,7 @@ int sptlrpc_target_export_check(struct o
 	/* now it doesn't match the current flavor, the only chance we can
 	 * accept it is match the old flavors which is not expired. */
 	if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) {
-		if (exp->exp_flvr_expire[1] >= cfs_time_current_sec()) {
+		if (exp->exp_flvr_expire[1] >= get_seconds()) {
 			if (flavor_allowed(&exp->exp_flvr_old[1], req)) {
 				CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
 				       "oldest one ("CFS_DURATION_T")\n", exp,
@@ -1881,7 +1881,7 @@ int sptlrpc_target_export_check(struct o
 				       exp->exp_flvr_old[0].sf_rpc,
 				       exp->exp_flvr_old[1].sf_rpc,
 				       exp->exp_flvr_expire[1] -
-						cfs_time_current_sec());
+						get_seconds());
 				spin_unlock(&exp->exp_lock);
 				return 0;
 			}
@@ -1911,11 +1911,11 @@ int sptlrpc_target_export_check(struct o
 	      exp->exp_flvr_old[0].sf_rpc,
 	      exp->exp_flvr_expire[0] ?
 	      (unsigned long) (exp->exp_flvr_expire[0] -
-			       cfs_time_current_sec()) : 0,
+			       get_seconds()) : 0,
 	      exp->exp_flvr_old[1].sf_rpc,
 	      exp->exp_flvr_expire[1] ?
 	      (unsigned long) (exp->exp_flvr_expire[1] -
-			       cfs_time_current_sec()) : 0);
+			       get_seconds()) : 0);
 	return -EACCES;
 }
 EXPORT_SYMBOL(sptlrpc_target_export_check);
@@ -2033,7 +2033,7 @@ int sptlrpc_svc_unwrap_request(struct pt
 	case 0:
 		break;
 	default:
-		CERROR("error unpacking request from %s x"LPU64"\n",
+		CERROR("error unpacking request from %s x%llu\n",
 		       libcfs_id2str(req->rq_peer), req->rq_xid);
 		return SECSVC_DROP;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_config.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_config.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_config.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,20 +36,20 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/crypto.h>
 #include <linux/key.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_log.h>
-#include <lustre_disk.h>
-#include <lustre_dlm.h>
-#include <lustre_param.h>
-#include <lustre_sec.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_log.h"
+#include "../include/lustre_disk.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_param.h"
+#include "../include/lustre_sec.h"
 
 #include "ptlrpc_internal.h"
 
@@ -918,7 +918,7 @@ void sptlrpc_conf_client_adapt(struct ob
 	if (imp) {
 		spin_lock(&imp->imp_lock);
 		if (imp->imp_sec)
-			imp->imp_sec_expire = cfs_time_current_sec() +
+			imp->imp_sec_expire = get_seconds() +
 				SEC_ADAPT_DELAY;
 		spin_unlock(&imp->imp_lock);
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c	2014-09-28 17:29:07.000000000 -0400
@@ -40,12 +40,12 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_sec.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_sec.h"
 
 #define SEC_GC_INTERVAL (30 * 60)
 
@@ -67,7 +67,7 @@ void sptlrpc_gc_add_sec(struct ptlrpc_se
 	LASSERT(sec->ps_gc_interval > 0);
 	LASSERT(list_empty(&sec->ps_gc_list));
 
-	sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
+	sec->ps_gc_next = get_seconds() + sec->ps_gc_interval;
 
 	spin_lock(&sec_gc_list_lock);
 	list_add_tail(&sec_gc_list, &sec->ps_gc_list);
@@ -152,11 +152,11 @@ static void sec_do_gc(struct ptlrpc_sec
 
 	CDEBUG(D_SEC, "check on sec %p(%s)\n", sec, sec->ps_policy->sp_name);
 
-	if (cfs_time_after(sec->ps_gc_next, cfs_time_current_sec()))
+	if (cfs_time_after(sec->ps_gc_next, get_seconds()))
 		return;
 
 	sec->ps_policy->sp_cops->gc_ctx(sec);
-	sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
+	sec->ps_gc_next = get_seconds() + sec->ps_gc_interval;
 }
 
 static int sec_gc_main(void *arg)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,16 +38,16 @@
 
 #define DEBUG_SUBSYSTEM S_SEC
 
-#include <linux/libcfs/libcfs.h>
+#include "../../include/linux/libcfs/libcfs.h"
 #include <linux/crypto.h>
 
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_sec.h>
+#include "../include/obd.h"
+#include "../include/obd_class.h"
+#include "../include/obd_support.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_import.h"
+#include "../include/lustre_dlm.h"
+#include "../include/lustre_sec.h"
 
 #include "ptlrpc_internal.h"
 
@@ -55,7 +55,7 @@
 struct proc_dir_entry *sptlrpc_proc_root = NULL;
 EXPORT_SYMBOL(sptlrpc_proc_root);
 
-char *sec_flags2str(unsigned long flags, char *buf, int bufsize)
+static char *sec_flags2str(unsigned long flags, char *buf, int bufsize)
 {
 	buf[0] = '\0';
 
@@ -104,7 +104,7 @@ static int sptlrpc_info_lprocfs_seq_show
 	seq_printf(seq, "gc internal    %ld\n", sec->ps_gc_interval);
 	seq_printf(seq, "gc next	%ld\n",
 		   sec->ps_gc_interval ?
-		   sec->ps_gc_next - cfs_time_current_sec() : 0);
+		   sec->ps_gc_next - get_seconds() : 0);
 
 	sptlrpc_sec_put(sec);
 out:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_null.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_null.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_null.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_null.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,11 @@
 #define DEBUG_SUBSYSTEM S_SEC
 
 
-#include <obd_support.h>
-#include <obd_cksum.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_sec.h>
+#include "../include/obd_support.h"
+#include "../include/obd_cksum.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_sec.h"
 
 static struct ptlrpc_sec_policy null_policy;
 static struct ptlrpc_sec	null_sec;
@@ -260,11 +260,22 @@ int null_enlarge_reqbuf(struct ptlrpc_se
 		if (newbuf == NULL)
 			return -ENOMEM;
 
+		/* Must lock this, so that otherwise unprotected change of
+		 * rq_reqmsg is not racing with parallel processing of
+		 * imp_replay_list traversing threads. See LU-3333
+		 * This is a bandaid at best, we really need to deal with this
+		 * in request enlarging code before unpacking that's already
+		 * there */
+		if (req->rq_import)
+			spin_lock(&req->rq_import->imp_lock);
 		memcpy(newbuf, req->rq_reqbuf, req->rq_reqlen);
 
 		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
 		req->rq_reqbuf = req->rq_reqmsg = newbuf;
 		req->rq_reqbuf_len = alloc_size;
+
+		if (req->rq_import)
+			spin_unlock(&req->rq_import->imp_lock);
 	}
 
 	_sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c	2014-09-28 17:29:07.000000000 -0400
@@ -41,11 +41,11 @@
 #define DEBUG_SUBSYSTEM S_SEC
 
 
-#include <obd_support.h>
-#include <obd_cksum.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_sec.h>
+#include "../include/obd_support.h"
+#include "../include/obd_cksum.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_sec.h"
 
 struct plain_sec {
 	struct ptlrpc_sec       pls_base;
@@ -669,6 +669,15 @@ int plain_enlarge_reqbuf(struct ptlrpc_s
 		if (newbuf == NULL)
 			return -ENOMEM;
 
+		/* Must lock this, so that otherwise unprotected change of
+		 * rq_reqmsg is not racing with parallel processing of
+		 * imp_replay_list traversing threads. See LU-3333
+		 * This is a bandaid at best, we really need to deal with this
+		 * in request enlarging code before unpacking that's already
+		 * there */
+		if (req->rq_import)
+			spin_lock(&req->rq_import->imp_lock);
+
 		memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
 
 		OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
@@ -676,6 +685,9 @@ int plain_enlarge_reqbuf(struct ptlrpc_s
 		req->rq_reqbuf_len = newbuf_size;
 		req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf,
 						PLAIN_PACK_MSG_OFF, 0);
+
+		if (req->rq_import)
+			spin_unlock(&req->rq_import->imp_lock);
 	}
 
 	_sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, PLAIN_PACK_MSG_OFF,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/service.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/service.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/service.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/service.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,11 +35,11 @@
  */
 
 #define DEBUG_SUBSYSTEM S_RPC
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lu_object.h>
-#include <linux/lnet/types.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lu_object.h"
+#include "../../include/linux/lnet/types.h"
 #include "ptlrpc_internal.h"
 
 /* The following are visible and mutable through /sys/module/ptlrpc */
@@ -1037,7 +1037,7 @@ static void ptlrpc_update_export_timer(s
 	   will make it to the top of the list. */
 
 	/* Do not pay attention on 1sec or smaller renewals. */
-	new_time = cfs_time_current_sec() + extra_delay;
+	new_time = get_seconds() + extra_delay;
 	if (exp->exp_last_request_time + 1 /*second */ >= new_time)
 		return;
 
@@ -1070,20 +1070,20 @@ static void ptlrpc_update_export_timer(s
 	/* Note - racing to start/reset the obd_eviction timer is safe */
 	if (exp->exp_obd->obd_eviction_timer == 0) {
 		/* Check if the oldest entry is expired. */
-		if (cfs_time_current_sec() > (oldest_time + PING_EVICT_TIMEOUT +
+		if (get_seconds() > (oldest_time + PING_EVICT_TIMEOUT +
 					      extra_delay)) {
 			/* We need a second timer, in case the net was down and
 			 * it just came back. Since the pinger may skip every
 			 * other PING_INTERVAL (see note in ptlrpc_pinger_main),
 			 * we better wait for 3. */
 			exp->exp_obd->obd_eviction_timer =
-				cfs_time_current_sec() + 3 * PING_INTERVAL;
+				get_seconds() + 3 * PING_INTERVAL;
 			CDEBUG(D_HA, "%s: Think about evicting %s from "CFS_TIME_T"\n",
 			       exp->exp_obd->obd_name,
 			       obd_export_nid2str(oldest_exp), oldest_time);
 		}
 	} else {
-		if (cfs_time_current_sec() >
+		if (get_seconds() >
 		    (exp->exp_obd->obd_eviction_timer + extra_delay)) {
 			/* The evictor won't evict anyone who we've heard from
 			 * recently, so we don't have to check before we start
@@ -1100,6 +1100,7 @@ static void ptlrpc_update_export_timer(s
  */
 static int ptlrpc_check_req(struct ptlrpc_request *req)
 {
+	struct obd_device *obd = req->rq_export->exp_obd;
 	int rc = 0;
 
 	if (unlikely(lustre_msg_get_conn_cnt(req->rq_reqmsg) <
@@ -1110,26 +1111,24 @@ static int ptlrpc_check_req(struct ptlrp
 			  req->rq_export->exp_conn_cnt);
 		return -EEXIST;
 	}
-	if (unlikely(req->rq_export->exp_obd &&
-		     req->rq_export->exp_obd->obd_fail)) {
+	if (unlikely(obd == NULL || obd->obd_fail)) {
 		/*
 		 * Failing over, don't handle any more reqs, send
 		 * error response instead.
 		 */
 		CDEBUG(D_RPCTRACE, "Dropping req %p for failed obd %s\n",
-		       req, req->rq_export->exp_obd->obd_name);
+		       req, (obd != NULL) ? obd->obd_name : "unknown");
 		rc = -ENODEV;
 	} else if (lustre_msg_get_flags(req->rq_reqmsg) &
 		   (MSG_REPLAY | MSG_REQ_REPLAY_DONE) &&
-		   !(req->rq_export->exp_obd->obd_recovering)) {
+		   !obd->obd_recovering) {
 			DEBUG_REQ(D_ERROR, req,
 				  "Invalid replay without recovery");
 			class_fail_export(req->rq_export);
 			rc = -ENODEV;
 	} else if (lustre_msg_get_transno(req->rq_reqmsg) != 0 &&
-		   !(req->rq_export->exp_obd->obd_recovering)) {
-			DEBUG_REQ(D_ERROR, req, "Invalid req with transno "
-				  LPU64" without recovery",
+		   !obd->obd_recovering) {
+			DEBUG_REQ(D_ERROR, req, "Invalid req with transno %llu without recovery",
 				  lustre_msg_get_transno(req->rq_reqmsg));
 			class_fail_export(req->rq_export);
 			rc = -ENODEV;
@@ -1153,7 +1152,7 @@ static void ptlrpc_at_set_timer(struct p
 	}
 
 	/* Set timer for closest deadline */
-	next = (__s32)(array->paa_deadline - cfs_time_current_sec() -
+	next = (__s32)(array->paa_deadline - get_seconds() -
 		       at_early_margin);
 	if (next <= 0) {
 		ptlrpc_at_timer((unsigned long)svcpt);
@@ -1243,7 +1242,7 @@ static int ptlrpc_at_send_early_reply(st
 	struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
 	struct ptlrpc_request *reqcopy;
 	struct lustre_msg *reqmsg;
-	cfs_duration_t olddl = req->rq_deadline - cfs_time_current_sec();
+	long olddl = req->rq_deadline - get_seconds();
 	time_t newdl;
 	int rc;
 
@@ -1288,7 +1287,7 @@ static int ptlrpc_at_send_early_reply(st
 		/* Fake our processing time into the future to ask the clients
 		 * for some extra amount of time */
 		at_measured(&svcpt->scp_at_estimate, at_extra +
-			    cfs_time_current_sec() -
+			    get_seconds() -
 			    req->rq_arrival_time.tv_sec);
 
 		/* Check to see if we've actually increased the deadline -
@@ -1299,11 +1298,11 @@ static int ptlrpc_at_send_early_reply(st
 				  "(%ld/%ld), not sending early reply\n",
 				  olddl, req->rq_arrival_time.tv_sec +
 				  at_get(&svcpt->scp_at_estimate) -
-				  cfs_time_current_sec());
+				  get_seconds());
 			return -ETIMEDOUT;
 		}
 	}
-	newdl = cfs_time_current_sec() + at_get(&svcpt->scp_at_estimate);
+	newdl = get_seconds() + at_get(&svcpt->scp_at_estimate);
 
 	reqcopy = ptlrpc_request_cache_alloc(GFP_NOFS);
 	if (reqcopy == NULL)
@@ -1381,8 +1380,8 @@ static int ptlrpc_at_check_timed(struct
 	struct list_head work_list;
 	__u32  index, count;
 	time_t deadline;
-	time_t now = cfs_time_current_sec();
-	cfs_duration_t delay;
+	time_t now = get_seconds();
+	long delay;
 	int first, counter = 0;
 
 	spin_lock(&svcpt->scp_at_lock);
@@ -1766,24 +1765,24 @@ ptlrpc_server_handle_req_in(struct ptlrp
 	if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL) {
 		rc = ptlrpc_unpack_req_msg(req, req->rq_reqlen);
 		if (rc != 0) {
-			CERROR("error unpacking request: ptl %d from %s "
-			       "x"LPU64"\n", svc->srv_req_portal,
-			       libcfs_id2str(req->rq_peer), req->rq_xid);
+			CERROR("error unpacking request: ptl %d from %s x%llu\n",
+			       svc->srv_req_portal, libcfs_id2str(req->rq_peer),
+			       req->rq_xid);
 			goto err_req;
 		}
 	}
 
 	rc = lustre_unpack_req_ptlrpc_body(req, MSG_PTLRPC_BODY_OFF);
 	if (rc) {
-		CERROR("error unpacking ptlrpc body: ptl %d from %s x"
-		       LPU64"\n", svc->srv_req_portal,
-		       libcfs_id2str(req->rq_peer), req->rq_xid);
+		CERROR("error unpacking ptlrpc body: ptl %d from %s x%llu\n",
+		       svc->srv_req_portal, libcfs_id2str(req->rq_peer),
+		       req->rq_xid);
 		goto err_req;
 	}
 
 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_REQ_OPC) &&
 	    lustre_msg_get_opc(req->rq_reqmsg) == cfs_fail_val) {
-		CERROR("drop incoming rpc opc %u, x"LPU64"\n",
+		CERROR("drop incoming rpc opc %u, x%llu\n",
 		       cfs_fail_val, req->rq_xid);
 		goto err_req;
 	}
@@ -1808,7 +1807,7 @@ ptlrpc_server_handle_req_in(struct ptlrp
 		break;
 	}
 
-	CDEBUG(D_RPCTRACE, "got req x"LPU64"\n", req->rq_xid);
+	CDEBUG(D_RPCTRACE, "got req x%llu\n", req->rq_xid);
 
 	req->rq_export = class_conn2export(
 		lustre_msg_get_handle(req->rq_reqmsg));
@@ -1827,9 +1826,9 @@ ptlrpc_server_handle_req_in(struct ptlrp
 	}
 
 	/* req_in handling should/must be fast */
-	if (cfs_time_current_sec() - req->rq_arrival_time.tv_sec > 5)
+	if (get_seconds() - req->rq_arrival_time.tv_sec > 5)
 		DEBUG_REQ(D_WARNING, req, "Slow req_in handling "CFS_DURATION_T"s",
-			  cfs_time_sub(cfs_time_current_sec(),
+			  cfs_time_sub(get_seconds(),
 				       req->rq_arrival_time.tv_sec));
 
 	/* Set rpc server deadline and add it to the timed list */
@@ -1918,7 +1917,7 @@ ptlrpc_server_handle_request(struct ptlr
 	request->rq_session.lc_cookie = 0x5;
 	lu_context_enter(&request->rq_session);
 
-	CDEBUG(D_NET, "got req "LPU64"\n", request->rq_xid);
+	CDEBUG(D_NET, "got req %llu\n", request->rq_xid);
 
 	request->rq_svc_thread = thread;
 	if (thread)
@@ -1932,19 +1931,19 @@ ptlrpc_server_handle_request(struct ptlr
 
 	/* Discard requests queued for longer than the deadline.
 	   The deadline is increased if we send an early reply. */
-	if (cfs_time_current_sec() > request->rq_deadline) {
+	if (get_seconds() > request->rq_deadline) {
 		DEBUG_REQ(D_ERROR, request, "Dropping timed-out request from %s"
 			  ": deadline "CFS_DURATION_T":"CFS_DURATION_T"s ago\n",
 			  libcfs_id2str(request->rq_peer),
 			  cfs_time_sub(request->rq_deadline,
 			  request->rq_arrival_time.tv_sec),
-			  cfs_time_sub(cfs_time_current_sec(),
+			  cfs_time_sub(get_seconds(),
 			  request->rq_deadline));
 		goto put_conn;
 	}
 
 	CDEBUG(D_RPCTRACE, "Handling RPC pname:cluuid+ref:pid:xid:nid:opc "
-	       "%s:%s+%d:%d:x"LPU64":%s:%d\n", current_comm(),
+	       "%s:%s+%d:%d:x%llu:%s:%d\n", current_comm(),
 	       (request->rq_export ?
 		(char *)request->rq_export->exp_client_uuid.uuid : "0"),
 	       (request->rq_export ?
@@ -1964,22 +1963,22 @@ put_conn:
 	lu_context_exit(&request->rq_session);
 	lu_context_fini(&request->rq_session);
 
-	if (unlikely(cfs_time_current_sec() > request->rq_deadline)) {
+	if (unlikely(get_seconds() > request->rq_deadline)) {
 		DEBUG_REQ(D_WARNING, request,
 			  "Request took longer than estimated ("
 				CFS_DURATION_T":"CFS_DURATION_T
 				"s); client may timeout.",
 			  cfs_time_sub(request->rq_deadline,
 				       request->rq_arrival_time.tv_sec),
-			  cfs_time_sub(cfs_time_current_sec(),
+			  cfs_time_sub(get_seconds(),
 				       request->rq_deadline));
 	}
 
 	do_gettimeofday(&work_end);
 	timediff = cfs_timeval_sub(&work_end, &work_start, NULL);
 	CDEBUG(D_RPCTRACE, "Handled RPC pname:cluuid+ref:pid:xid:nid:opc "
-	       "%s:%s+%d:%d:x"LPU64":%s:%d Request processed in "
-	       "%ldus (%ldus total) trans "LPU64" rc %d/%d\n",
+	       "%s:%s+%d:%d:x%llu:%s:%d Request processed in "
+	       "%ldus (%ldus total) trans %llu rc %d/%d\n",
 		current_comm(),
 		(request->rq_export ?
 		 (char *)request->rq_export->exp_client_uuid.uuid : "0"),
@@ -2084,8 +2083,7 @@ ptlrpc_handle_rs(struct ptlrpc_reply_sta
 	if (nlocks == 0 && !been_handled) {
 		/* If we see this, we should already have seen the warning
 		 * in mds_steal_ack_locks()  */
-		CDEBUG(D_HA, "All locks stolen from rs %p x"LPD64".t"LPD64
-		       " o%d NID %s\n",
+		CDEBUG(D_HA, "All locks stolen from rs %p x%lld.t%lld o%d NID %s\n",
 		       rs,
 		       rs->rs_xid, rs->rs_transno, rs->rs_opc,
 		       libcfs_nid2str(exp->exp_connection->c_peer.nid));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/wiretest.c linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/wiretest.c
--- linux-libre-3.16-gnu/drivers/staging/lustre/lustre/ptlrpc/wiretest.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/lustre/ptlrpc/wiretest.c	2014-09-28 17:29:07.000000000 -0400
@@ -39,10 +39,10 @@
 #include <linux/fs.h>
 #include <linux/posix_acl_xattr.h>
 
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_net.h>
-#include <lustre_disk.h>
+#include "../include/obd_support.h"
+#include "../include/obd_class.h"
+#include "../include/lustre_net.h"
+#include "../include/lustre_disk.h"
 void lustre_assert_wire_constants(void)
 {
 	 /* Wire protocol assertions generated by 'wirecheck'
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/lustre/Makefile
--- linux-libre-3.16-gnu/drivers/staging/lustre/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,4 +1,2 @@
-subdir-ccflags-y := -I$(src)/include/
-
 obj-$(CONFIG_LNET)		+= lnet/
 obj-$(CONFIG_LUSTRE_FS)		+= lustre/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/lustre/TODO linux-libre-3.17-rc7-gnu/drivers/staging/lustre/TODO
--- linux-libre-3.16-gnu/drivers/staging/lustre/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/lustre/TODO	2014-09-28 17:29:07.000000000 -0400
@@ -9,5 +9,4 @@
 * Other minor misc cleanups...
 
 Please send any patches to Greg Kroah-Hartman <greg@kroah.com>, Andreas Dilger
-<andreas.dilger@intel.com>, Oleg Drokin <oleg.drokin@intel.com>. CCing
-hpdd-discuss <hpdd-discuss@lists.01.org> would be great too.
+<andreas.dilger@intel.com>, and Oleg Drokin <oleg.drokin@intel.com>.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/Makefile
--- linux-libre-3.16-gnu/drivers/staging/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -6,8 +6,6 @@ obj-$(CONFIG_STAGING)		+= staging.o
 obj-y				+= media/
 obj-$(CONFIG_ET131X)		+= et131x/
 obj-$(CONFIG_SLICOSS)		+= slicoss/
-obj-$(CONFIG_USBIP_CORE)	+= usbip/
-obj-$(CONFIG_W35UND)		+= winbond/
 obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon/
@@ -20,26 +18,16 @@ obj-$(CONFIG_R8192EE)		+= rtl8192ee/
 obj-$(CONFIG_R8723AU)		+= rtl8723au/
 obj-$(CONFIG_R8821AE)		+= rtl8821ae/
 obj-$(CONFIG_RTS5208)		+= rts5208/
-obj-$(CONFIG_TRANZPORT)		+= frontier/
-obj-$(CONFIG_IDE_PHISON)	+= phison/
 obj-$(CONFIG_LINE6_USB)		+= line6/
 obj-$(CONFIG_NETLOGIC_XLR_NET)	+= netlogic/
-obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_OCTEON_USB)	+= octeon-usb/
 obj-$(CONFIG_VT6655)		+= vt6655/
 obj-$(CONFIG_VT6656)		+= vt6656/
 obj-$(CONFIG_VME_BUS)		+= vme/
-obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)		+= iio/
-obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
-obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
-obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
-obj-$(CONFIG_CXT1E1)		+= cxt1e1/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
-obj-$(CONFIG_TIDSPBRIDGE)	+= tidspbridge/
-obj-$(CONFIG_ACPI_QUICKSTART)	+= quickstart/
-obj-$(CONFIG_USB_ENESTORAGE)	+= keucr/
+obj-$(CONFIG_USB_EMXX)		+= emxx_udc/
 obj-$(CONFIG_BCM_WIMAX)		+= bcm/
 obj-$(CONFIG_FT1000)		+= ft1000/
 obj-$(CONFIG_SPEAKUP)		+= speakup/
@@ -47,13 +35,11 @@ obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= ste_rmi4/
 obj-$(CONFIG_MFD_NVEC)		+= nvec/
 obj-$(CONFIG_ANDROID)		+= android/
+obj-$(CONFIG_STAGING_BOARD)	+= board/
 obj-$(CONFIG_USB_WPAN_HCD)	+= ozwpan/
 obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
 obj-$(CONFIG_LTE_GDM724X)	+= gdm724x/
-obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
-obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
-obj-$(CONFIG_DGRP)		+= dgrp/
 obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_LUSTRE_FS)		+= lustre/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/bcm2048/radio-bcm2048.c linux-libre-3.17-rc7-gnu/drivers/staging/media/bcm2048/radio-bcm2048.c
--- linux-libre-3.16-gnu/drivers/staging/media/bcm2048/radio-bcm2048.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/bcm2048/radio-bcm2048.c	2014-09-28 17:29:07.000000000 -0400
@@ -369,13 +369,12 @@ static int bcm2048_send_command(struct b
 	data[0] = reg & 0xff;
 	data[1] = value & 0xff;
 
-	if (i2c_master_send(client, data, 2) == 2) {
+	if (i2c_master_send(client, data, 2) == 2)
 		return 0;
-	} else {
-		dev_err(&bdev->client->dev, "BCM I2C error!\n");
-		dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n");
-		return -EIO;
-	}
+
+	dev_err(&bdev->client->dev, "BCM I2C error!\n");
+	dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n");
+	return -EIO;
 }
 
 static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg,
@@ -725,8 +724,8 @@ static int bcm2048_get_fm_deemphasis(str
 	if (!err) {
 		if (value & BCM2048_DE_EMPHASIS_SELECT)
 			return BCM2048_DE_EMPHASIS_75us;
-		else
-			return BCM2048_DE_EMPHASIS_50us;
+
+		return BCM2048_DE_EMPHASIS_50us;
 	}
 
 	return err;
@@ -1971,7 +1970,8 @@ static ssize_t bcm2048_##prop##_write(st
 	if (!bdev)							\
 		return -ENODEV;						\
 									\
-	sscanf(buf, mask, &value);					\
+	if (sscanf(buf, mask, &value) != 1)				\
+		return -EINVAL;						\
 									\
 	if (check)							\
 		return -EDOM;						\
@@ -2242,6 +2242,7 @@ static ssize_t bcm2048_fops_read(struct
 	i = 0;
 	while (i < count) {
 		unsigned char tmpbuf[3];
+
 		tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2];
 		tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1];
 		tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i]
@@ -2598,7 +2599,6 @@ static int bcm2048_i2c_driver_probe(stru
 
 	bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
 	if (!bdev) {
-		dev_dbg(&client->dev, "Failed to alloc video device.\n");
 		err = -ENOMEM;
 		goto exit;
 	}
@@ -2618,7 +2618,7 @@ static int bcm2048_i2c_driver_probe(stru
 
 	if (client->irq) {
 		err = request_irq(client->irq,
-			bcm2048_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+			bcm2048_handler, IRQF_TRIGGER_FALLING,
 			client->name, bdev);
 		if (err < 0) {
 			dev_err(&client->dev, "Could not request IRQ\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe.c linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
--- linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe.c	2014-09-28 17:29:07.000000000 -0400
@@ -1268,6 +1268,7 @@ static int ipipe_s_config(struct v4l2_su
 
 	for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) {
 		unsigned int bit = 1 << i;
+
 		if (cfg->flag & bit) {
 			const struct ipipe_module_if *module_if =
 						&ipipe_modules[i];
@@ -1310,6 +1311,7 @@ static int ipipe_g_config(struct v4l2_su
 
 	for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) {
 		unsigned int bit = 1 << i;
+
 		if (cfg->flag & bit) {
 			const struct ipipe_module_if *module_if =
 						&ipipe_modules[i];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h
--- linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h	2014-09-28 17:29:07.000000000 -0400
@@ -479,7 +479,6 @@
 #define RSZ_TYP_Y_SHIFT			0
 #define RSZ_TYP_C_SHIFT			1
 #define RSZ_LPF_INT_MASK		0x3f
-#define RSZ_LPF_INT_MASK		0x3f
 #define RSZ_LPF_INT_C_SHIFT		6
 #define RSZ_H_PHS_MASK			0x3fff
 #define RSZ_H_DIF_MASK			0x3fff
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
--- linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c	2014-09-28 17:29:07.000000000 -0400
@@ -196,6 +196,7 @@ static int ipipeif_hw_setup(struct v4l2_
 	int data_shift;
 	int pack_mode;
 	int source1;
+	int tmp;
 
 	ipipeif_base_addr = ipipeif->ipipeif_base_addr;
 
@@ -206,8 +207,8 @@ static int ipipeif_hw_setup(struct v4l2_
 	outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE];
 
 	/* Combine all the fields to make CFG1 register of IPIPEIF */
-	val = get_oneshot_mode(ipipeif->input);
-	if (val < 0) {
+	tmp = val = get_oneshot_mode(ipipeif->input);
+	if (tmp < 0) {
 		pr_err("ipipeif: links setup required");
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_resizer.c linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_resizer.c
--- linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/dm365_resizer.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/dm365_resizer.c	2014-09-28 17:29:07.000000000 -0400
@@ -219,7 +219,7 @@ configure_resizer_out_params(struct vpfe
  * @resizer: Pointer to VPFE resizer subdevice.
  * @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
  */
-void
+static void
 resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index)
 {
 	struct resizer_params *param = &resizer->config;
@@ -310,7 +310,7 @@ resizer_calculate_sdram_offsets(struct v
 	return 0;
 }
 
-int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
+static int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
 {
 	struct resizer_params *param = &resizer->config;
 	struct vpfe_rsz_output_spec output_specs;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/vpfe_video.c linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/vpfe_video.c
--- linux-libre-3.16-gnu/drivers/staging/media/davinci_vpfe/vpfe_video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/davinci_vpfe/vpfe_video.c	2014-09-28 17:29:07.000000000 -0400
@@ -1606,7 +1606,6 @@ int vpfe_video_init(struct vpfe_video_de
 	if (ret < 0)
 		return ret;
 
-	set_bit(V4L2_FL_USE_FH_PRIO, &video->video_dev.flags);
 	video_set_drvdata(&video->video_dev, video);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-driver.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-driver.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-driver.c	2014-08-07 04:50:36.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-driver.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,711 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/unistd.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/firmware.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-
-#include "go7007-priv.h"
-
-/*
- * Wait for an interrupt to be delivered from the GO7007SB and return
- * the associated value and data.
- *
- * Must be called with the hw_lock held.
- */
-int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
-{
-	go->interrupt_available = 0;
-	go->hpi_ops->read_interrupt(go);
-	if (wait_event_timeout(go->interrupt_waitq,
-				go->interrupt_available, 5*HZ) < 0) {
-		v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n");
-		return -1;
-	}
-	if (!go->interrupt_available)
-		return -1;
-	go->interrupt_available = 0;
-	*value = go->interrupt_value & 0xfffe;
-	*data = go->interrupt_data;
-	return 0;
-}
-EXPORT_SYMBOL(go7007_read_interrupt);
-
-/*
- * Read a register/address on the GO7007SB.
- *
- * Must be called with the hw_lock held.
- */
-int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data)
-{
-	int count = 100;
-	u16 value;
-
-	if (go7007_write_interrupt(go, 0x0010, addr) < 0)
-		return -EIO;
-	while (count-- > 0) {
-		if (go7007_read_interrupt(go, &value, data) == 0 &&
-				value == 0xa000)
-			return 0;
-	}
-	return -EIO;
-}
-EXPORT_SYMBOL(go7007_read_addr);
-
-/*
- * Send the boot firmware to the encoder, which just wakes it up and lets
- * us talk to the GPIO pins and on-board I2C adapter.
- *
- * Must be called with the hw_lock held.
- */
-static int go7007_load_encoder(struct go7007 *go)
-{
-	const struct firmware *fw_entry;
-	char fw_name[] = "/*(DEBLOBBED)*/";
-	void *bounce;
-	int fw_len, rv = 0;
-	u16 intr_val, intr_data;
-
-	if (go->boot_fw == NULL) {
-		if (reject_firmware(&fw_entry, fw_name, go->dev)) {
-			v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
-			return -1;
-		}
-		if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
-			v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
-			release_firmware(fw_entry);
-			return -1;
-		}
-		fw_len = fw_entry->size - 16;
-		bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
-		if (bounce == NULL) {
-			v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
-			release_firmware(fw_entry);
-			return -1;
-		}
-		release_firmware(fw_entry);
-		go->boot_fw_len = fw_len;
-		go->boot_fw = bounce;
-	}
-	if (go7007_interface_reset(go) < 0 ||
-	    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
-	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
-			(intr_val & ~0x1) != 0x5a5a) {
-		v4l2_err(go, "error transferring firmware\n");
-		rv = -1;
-	}
-	return rv;
-}
-
-/*(DEBLOBBED)*/
-
-/*
- * Boot the encoder and register the I2C adapter if requested.  Do the
- * minimum initialization necessary, since the board-specific code may
- * still need to probe the board ID.
- *
- * Must NOT be called with the hw_lock held.
- */
-int go7007_boot_encoder(struct go7007 *go, int init_i2c)
-{
-	int ret;
-
-	mutex_lock(&go->hw_lock);
-	ret = go7007_load_encoder(go);
-	mutex_unlock(&go->hw_lock);
-	if (ret < 0)
-		return -1;
-	if (!init_i2c)
-		return 0;
-	if (go7007_i2c_init(go) < 0)
-		return -1;
-	go->i2c_adapter_online = 1;
-	return 0;
-}
-EXPORT_SYMBOL(go7007_boot_encoder);
-
-/*
- * Configure any hardware-related registers in the GO7007, such as GPIO
- * pins and bus parameters, which are board-specific.  This assumes
- * the boot firmware has already been downloaded.
- *
- * Must be called with the hw_lock held.
- */
-static int go7007_init_encoder(struct go7007 *go)
-{
-	if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
-		go7007_write_addr(go, 0x1000, 0x0811);
-		go7007_write_addr(go, 0x1000, 0x0c11);
-	}
-	switch (go->board_id) {
-	case GO7007_BOARDID_MATRIX_REV:
-		/* Set GPIO pin 0 to be an output (audio clock control) */
-		go7007_write_addr(go, 0x3c82, 0x0001);
-		go7007_write_addr(go, 0x3c80, 0x00fe);
-		break;
-	case GO7007_BOARDID_ADLINK_MPG24:
-		/* set GPIO5 to be an output, currently low */
-		go7007_write_addr(go, 0x3c82, 0x0000);
-		go7007_write_addr(go, 0x3c80, 0x00df);
-		break;
-	case GO7007_BOARDID_ADS_USBAV_709:
-		/* GPIO pin 0: audio clock control */
-		/*      pin 2: TW9906 reset */
-		/*      pin 3: capture LED */
-		go7007_write_addr(go, 0x3c82, 0x000d);
-		go7007_write_addr(go, 0x3c80, 0x00f2);
-		break;
-	}
-	return 0;
-}
-
-/*
- * Send the boot firmware to the GO7007 and configure the registers.  This
- * is the only way to stop the encoder once it has started streaming video.
- *
- * Must be called with the hw_lock held.
- */
-int go7007_reset_encoder(struct go7007 *go)
-{
-	if (go7007_load_encoder(go) < 0)
-		return -1;
-	return go7007_init_encoder(go);
-}
-
-/*
- * Attempt to instantiate an I2C client by ID, probably loading a module.
- */
-static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c)
-{
-	struct go7007 *go = i2c_get_adapdata(adapter);
-	struct v4l2_device *v4l2_dev = &go->v4l2_dev;
-	struct v4l2_subdev *sd;
-	struct i2c_board_info info;
-
-	memset(&info, 0, sizeof(info));
-	strlcpy(info.type, i2c->type, sizeof(info.type));
-	info.addr = i2c->addr;
-	info.flags = i2c->flags;
-
-	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL);
-	if (sd) {
-		if (i2c->is_video)
-			go->sd_video = sd;
-		if (i2c->is_audio)
-			go->sd_audio = sd;
-		return 0;
-	}
-
-	printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type);
-	return -EINVAL;
-}
-
-/*
- * Detach and unregister the encoder.  The go7007 struct won't be freed
- * until v4l2 finishes releasing its resources and all associated fds are
- * closed by applications.
- */
-static void go7007_remove(struct v4l2_device *v4l2_dev)
-{
-	struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev);
-
-	v4l2_device_unregister(v4l2_dev);
-	if (go->hpi_ops->release)
-		go->hpi_ops->release(go);
-	if (go->i2c_adapter_online) {
-		i2c_del_adapter(&go->i2c_adapter);
-		go->i2c_adapter_online = 0;
-	}
-
-	kfree(go->boot_fw);
-	go7007_v4l2_remove(go);
-	kfree(go);
-}
-
-/*
- * Finalize the GO7007 hardware setup, register the on-board I2C adapter
- * (if used on this board), load the I2C client driver for the sensor
- * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2
- * interfaces.
- *
- * Must NOT be called with the hw_lock held.
- */
-int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
-{
-	int i, ret;
-
-	dev_info(go->dev, "go7007: registering new %s\n", go->name);
-
-	go->v4l2_dev.release = go7007_remove;
-	ret = v4l2_device_register(go->dev, &go->v4l2_dev);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&go->hw_lock);
-	ret = go7007_init_encoder(go);
-	mutex_unlock(&go->hw_lock);
-	if (ret < 0)
-		return ret;
-
-	ret = go7007_v4l2_ctrl_init(go);
-	if (ret < 0)
-		return ret;
-
-	if (!go->i2c_adapter_online &&
-			go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
-		ret = go7007_i2c_init(go);
-		if (ret < 0)
-			return ret;
-		go->i2c_adapter_online = 1;
-	}
-	if (go->i2c_adapter_online) {
-		if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
-			/* Reset the TW9906 */
-			go7007_write_addr(go, 0x3c82, 0x0009);
-			msleep(50);
-			go7007_write_addr(go, 0x3c82, 0x000d);
-		}
-		for (i = 0; i < num_i2c_devs; ++i)
-			init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]);
-
-		if (go->tuner_type >= 0) {
-			struct tuner_setup setup = {
-				.addr = ADDR_UNSET,
-				.type = go->tuner_type,
-				.mode_mask = T_ANALOG_TV,
-			};
-
-			v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
-				s_type_addr, &setup);
-		}
-		if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
-			v4l2_subdev_call(go->sd_video, video, s_routing,
-					0, 0, go->channel_number + 1);
-	}
-
-	ret = go7007_v4l2_init(go);
-	if (ret < 0)
-		return ret;
-
-	if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
-		go->audio_enabled = 1;
-		go7007_snd_init(go);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(go7007_register_encoder);
-
-/*
- * Send the encode firmware to the encoder, which will cause it
- * to immediately start delivering the video and audio streams.
- *
- * Must be called with the hw_lock held.
- */
-int go7007_start_encoder(struct go7007 *go)
-{
-	u8 *fw;
-	int fw_len, rv = 0, i;
-	u16 intr_val, intr_data;
-
-	go->modet_enable = 0;
-	if (!go->dvd_mode)
-		for (i = 0; i < 4; ++i) {
-			if (go->modet[i].enable) {
-				go->modet_enable = 1;
-				continue;
-			}
-			go->modet[i].pixel_threshold = 32767;
-			go->modet[i].motion_threshold = 32767;
-			go->modet[i].mb_threshold = 32767;
-		}
-
-	if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
-		return -1;
-
-	if (go7007_send_firmware(go, fw, fw_len) < 0 ||
-			go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
-		v4l2_err(&go->v4l2_dev, "error transferring firmware\n");
-		rv = -1;
-		goto start_error;
-	}
-
-	go->state = STATE_DATA;
-	go->parse_length = 0;
-	go->seen_frame = 0;
-	if (go7007_stream_start(go) < 0) {
-		v4l2_err(&go->v4l2_dev, "error starting stream transfer\n");
-		rv = -1;
-		goto start_error;
-	}
-
-start_error:
-	kfree(fw);
-	return rv;
-}
-
-/*
- * Store a byte in the current video buffer, if there is one.
- */
-static inline void store_byte(struct go7007_buffer *vb, u8 byte)
-{
-	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
-		u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
-
-		ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
-	}
-}
-
-/*
- * Deliver the last video buffer and get a new one to start writing to.
- */
-static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
-{
-	struct go7007_buffer *vb_tmp = NULL;
-	u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
-	int i;
-
-	if (vb) {
-		if (vb->modet_active) {
-			if (*bytesused + 216 < GO7007_BUF_SIZE) {
-				for (i = 0; i < 216; ++i)
-					store_byte(vb, go->active_map[i]);
-				*bytesused -= 216;
-			} else
-				vb->modet_active = 0;
-		}
-		vb->vb.v4l2_buf.sequence = go->next_seq++;
-		v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
-		vb_tmp = vb;
-		spin_lock(&go->spinlock);
-		list_del(&vb->list);
-		if (list_empty(&go->vidq_active))
-			vb = NULL;
-		else
-			vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
-		go->active_buf = vb;
-		spin_unlock(&go->spinlock);
-		vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
-		return vb;
-	}
-	spin_lock(&go->spinlock);
-	if (!list_empty(&go->vidq_active))
-		vb = go->active_buf =
-			list_first_entry(&go->vidq_active, struct go7007_buffer, list);
-	spin_unlock(&go->spinlock);
-	go->next_seq++;
-	return vb;
-}
-
-static void write_bitmap_word(struct go7007 *go)
-{
-	int x, y, i, stride = ((go->width >> 4) + 7) >> 3;
-
-	for (i = 0; i < 16; ++i) {
-		y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4);
-		x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4);
-		if (stride * y + (x >> 3) < sizeof(go->active_map))
-			go->active_map[stride * y + (x >> 3)] |=
-					(go->modet_word & 1) << (x & 0x7);
-		go->modet_word >>= 1;
-	}
-}
-
-/*
- * Parse a chunk of the video stream into frames.  The frames are not
- * delimited by the hardware, so we have to parse the frame boundaries
- * based on the type of video stream we're receiving.
- */
-void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
-{
-	struct go7007_buffer *vb = go->active_buf;
-	int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1;
-
-	switch (go->format) {
-	case V4L2_PIX_FMT_MPEG4:
-		seq_start_code = 0xB0;
-		gop_start_code = 0xB3;
-		frame_start_code = 0xB6;
-		break;
-	case V4L2_PIX_FMT_MPEG1:
-	case V4L2_PIX_FMT_MPEG2:
-		seq_start_code = 0xB3;
-		gop_start_code = 0xB8;
-		frame_start_code = 0x00;
-		break;
-	}
-
-	for (i = 0; i < length; ++i) {
-		if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
-			v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
-			vb->vb.v4l2_planes[0].bytesused = 0;
-			vb->frame_offset = 0;
-			vb->modet_active = 0;
-			vb = go->active_buf = NULL;
-		}
-
-		switch (go->state) {
-		case STATE_DATA:
-			switch (buf[i]) {
-			case 0x00:
-				go->state = STATE_00;
-				break;
-			case 0xFF:
-				go->state = STATE_FF;
-				break;
-			default:
-				store_byte(vb, buf[i]);
-				break;
-			}
-			break;
-		case STATE_00:
-			switch (buf[i]) {
-			case 0x00:
-				go->state = STATE_00_00;
-				break;
-			case 0xFF:
-				store_byte(vb, 0x00);
-				go->state = STATE_FF;
-				break;
-			default:
-				store_byte(vb, 0x00);
-				store_byte(vb, buf[i]);
-				go->state = STATE_DATA;
-				break;
-			}
-			break;
-		case STATE_00_00:
-			switch (buf[i]) {
-			case 0x00:
-				store_byte(vb, 0x00);
-				/* go->state remains STATE_00_00 */
-				break;
-			case 0x01:
-				go->state = STATE_00_00_01;
-				break;
-			case 0xFF:
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x00);
-				go->state = STATE_FF;
-				break;
-			default:
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x00);
-				store_byte(vb, buf[i]);
-				go->state = STATE_DATA;
-				break;
-			}
-			break;
-		case STATE_00_00_01:
-			if (buf[i] == 0xF8 && go->modet_enable == 0) {
-				/* MODET start code, but MODET not enabled */
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x01);
-				store_byte(vb, 0xF8);
-				go->state = STATE_DATA;
-				break;
-			}
-			/* If this is the start of a new MPEG frame,
-			 * get a new buffer */
-			if ((go->format == V4L2_PIX_FMT_MPEG1 ||
-			     go->format == V4L2_PIX_FMT_MPEG2 ||
-			     go->format == V4L2_PIX_FMT_MPEG4) &&
-			    (buf[i] == seq_start_code ||
-			     buf[i] == gop_start_code ||
-			     buf[i] == frame_start_code)) {
-				if (vb == NULL || go->seen_frame)
-					vb = frame_boundary(go, vb);
-				go->seen_frame = buf[i] == frame_start_code;
-				if (vb && go->seen_frame)
-					vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
-			}
-			/* Handle any special chunk types, or just write the
-			 * start code to the (potentially new) buffer */
-			switch (buf[i]) {
-			case 0xF5: /* timestamp */
-				go->parse_length = 12;
-				go->state = STATE_UNPARSED;
-				break;
-			case 0xF6: /* vbi */
-				go->state = STATE_VBI_LEN_A;
-				break;
-			case 0xF8: /* MD map */
-				go->parse_length = 0;
-				memset(go->active_map, 0,
-						sizeof(go->active_map));
-				go->state = STATE_MODET_MAP;
-				break;
-			case 0xFF: /* Potential JPEG start code */
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x01);
-				go->state = STATE_FF;
-				break;
-			default:
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x00);
-				store_byte(vb, 0x01);
-				store_byte(vb, buf[i]);
-				go->state = STATE_DATA;
-				break;
-			}
-			break;
-		case STATE_FF:
-			switch (buf[i]) {
-			case 0x00:
-				store_byte(vb, 0xFF);
-				go->state = STATE_00;
-				break;
-			case 0xFF:
-				store_byte(vb, 0xFF);
-				/* go->state remains STATE_FF */
-				break;
-			case 0xD8:
-				if (go->format == V4L2_PIX_FMT_MJPEG)
-					vb = frame_boundary(go, vb);
-				/* fall through */
-			default:
-				store_byte(vb, 0xFF);
-				store_byte(vb, buf[i]);
-				go->state = STATE_DATA;
-				break;
-			}
-			break;
-		case STATE_VBI_LEN_A:
-			go->parse_length = buf[i] << 8;
-			go->state = STATE_VBI_LEN_B;
-			break;
-		case STATE_VBI_LEN_B:
-			go->parse_length |= buf[i];
-			if (go->parse_length > 0)
-				go->state = STATE_UNPARSED;
-			else
-				go->state = STATE_DATA;
-			break;
-		case STATE_MODET_MAP:
-			if (go->parse_length < 204) {
-				if (go->parse_length & 1) {
-					go->modet_word |= buf[i];
-					write_bitmap_word(go);
-				} else
-					go->modet_word = buf[i] << 8;
-			} else if (go->parse_length == 207 && vb) {
-				vb->modet_active = buf[i];
-			}
-			if (++go->parse_length == 208)
-				go->state = STATE_DATA;
-			break;
-		case STATE_UNPARSED:
-			if (--go->parse_length == 0)
-				go->state = STATE_DATA;
-			break;
-		}
-	}
-}
-EXPORT_SYMBOL(go7007_parse_video_stream);
-
-/*
- * Allocate a new go7007 struct.  Used by the hardware-specific probe.
- */
-struct go7007 *go7007_alloc(const struct go7007_board_info *board,
-						struct device *dev)
-{
-	struct go7007 *go;
-	int i;
-
-	go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
-	if (go == NULL)
-		return NULL;
-	go->dev = dev;
-	go->board_info = board;
-	go->board_id = 0;
-	go->tuner_type = -1;
-	go->channel_number = 0;
-	go->name[0] = 0;
-	mutex_init(&go->hw_lock);
-	init_waitqueue_head(&go->frame_waitq);
-	spin_lock_init(&go->spinlock);
-	go->status = STATUS_INIT;
-	memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
-	go->i2c_adapter_online = 0;
-	go->interrupt_available = 0;
-	init_waitqueue_head(&go->interrupt_waitq);
-	go->input = 0;
-	go7007_update_board(go);
-	go->encoder_h_halve = 0;
-	go->encoder_v_halve = 0;
-	go->encoder_subsample = 0;
-	go->format = V4L2_PIX_FMT_MJPEG;
-	go->bitrate = 1500000;
-	go->fps_scale = 1;
-	go->pali = 0;
-	go->aspect_ratio = GO7007_RATIO_1_1;
-	go->gop_size = 0;
-	go->ipb = 0;
-	go->closed_gop = 0;
-	go->repeat_seqhead = 0;
-	go->seq_header_enable = 0;
-	go->gop_header_enable = 0;
-	go->dvd_mode = 0;
-	go->interlace_coding = 0;
-	for (i = 0; i < 4; ++i)
-		go->modet[i].enable = 0;
-	for (i = 0; i < 1624; ++i)
-		go->modet_map[i] = 0;
-	go->audio_deliver = NULL;
-	go->audio_enabled = 0;
-
-	return go;
-}
-EXPORT_SYMBOL(go7007_alloc);
-
-void go7007_update_board(struct go7007 *go)
-{
-	const struct go7007_board_info *board = go->board_info;
-
-	if (board->sensor_flags & GO7007_SENSOR_TV) {
-		go->standard = GO7007_STD_NTSC;
-		go->std = V4L2_STD_NTSC_M;
-		go->width = 720;
-		go->height = 480;
-		go->sensor_framerate = 30000;
-	} else {
-		go->standard = GO7007_STD_OTHER;
-		go->width = board->sensor_width;
-		go->height = board->sensor_height;
-		go->sensor_framerate = board->sensor_framerate;
-	}
-	go->encoder_v_offset = board->sensor_v_offset;
-	go->encoder_h_offset = board->sensor_h_offset;
-}
-EXPORT_SYMBOL(go7007_update_board);
-
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-fw.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-fw.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-fw.c	2014-08-07 04:50:39.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-fw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1628 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-/*
- * This file contains code to generate a firmware image for the GO7007SB
- * encoder.  Much of the firmware is read verbatim from a file, but some of
- * it concerning bitrate control and other things that can be configured at
- * run-time are generated dynamically.  Note that the format headers
- * generated here do not affect the functioning of the encoder; they are
- * merely parroted back to the host at the start of each frame.
- */
-
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include "go7007-priv.h"
-
-#define GO7007_FW_NAME "/*(DEBLOBBED)*/"
-
-/* Constants used in the source firmware image to describe code segments */
-
-#define	FLAG_MODE_MJPEG		(1)
-#define	FLAG_MODE_MPEG1		(1<<1)
-#define	FLAG_MODE_MPEG2		(1<<2)
-#define	FLAG_MODE_MPEG4		(1<<3)
-#define	FLAG_MODE_H263		(1<<4)
-#define FLAG_MODE_ALL		(FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \
-					FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \
-					FLAG_MODE_H263)
-#define FLAG_SPECIAL		(1<<8)
-
-#define SPECIAL_FRM_HEAD	0
-#define SPECIAL_BRC_CTRL	1
-#define SPECIAL_CONFIG		2
-#define SPECIAL_SEQHEAD		3
-#define SPECIAL_AV_SYNC		4
-#define SPECIAL_FINAL		5
-#define SPECIAL_AUDIO		6
-#define SPECIAL_MODET		7
-
-/* Little data class for creating MPEG headers bit-by-bit */
-
-struct code_gen {
-	unsigned char *p; /* destination */
-	u32 a; /* collects bits at the top of the variable */
-	int b; /* bit position of most recently-written bit */
-	int len; /* written out so far */
-};
-
-#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 }
-
-#define CODE_ADD(name, val, length) do { \
-	name.b -= (length); \
-	name.a |= (val) << name.b; \
-	while (name.b <= 24) { \
-		*name.p = name.a >> 24; \
-		++name.p; \
-		name.a <<= 8; \
-		name.b += 8; \
-		name.len += 8; \
-	} \
-} while (0)
-
-#define CODE_LENGTH(name) (name.len + (32 - name.b))
-
-/* Tables for creating the bitrate control data */
-
-static const s16 converge_speed_ip[101] = {
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
-	2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
-	3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
-	5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
-	9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
-	19, 20, 22, 23, 25, 27, 30, 32, 35, 38,
-	41, 45, 49, 53, 58, 63, 69, 76, 83, 91,
-	100
-};
-
-static const s16 converge_speed_ipb[101] = {
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
-	6, 6, 6, 7, 7, 7, 7, 8, 8, 9,
-	9, 9, 10, 10, 11, 12, 12, 13, 14, 14,
-	15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
-	28, 30, 32, 34, 37, 40, 42, 46, 49, 53,
-	57, 61, 66, 71, 77, 83, 90, 97, 106, 115,
-	125, 135, 147, 161, 175, 191, 209, 228, 249, 273,
-	300
-};
-
-static const s16 LAMBDA_table[4][101] = {
-	{	16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
-		19, 19, 19, 20, 20, 20, 21, 21, 22, 22,
-		22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
-		27, 27, 28, 28, 29, 29, 30, 31, 31, 32,
-		32, 33, 33, 34, 35, 35, 36, 37, 37, 38,
-		39, 39, 40, 41, 42, 42, 43, 44, 45, 46,
-		46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
-		67, 68, 69, 70, 72, 73, 74, 76, 77, 78,
-		80, 81, 83, 84, 86, 87, 89, 90, 92, 94,
-		96
-	},
-	{
-		20, 20, 20, 21, 21, 21, 22, 22, 23, 23,
-		23, 24, 24, 25, 25, 26, 26, 27, 27, 28,
-		28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
-		34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
-		40, 41, 42, 43, 43, 44, 45, 46, 47, 48,
-		48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-		58, 59, 60, 61, 62, 64, 65, 66, 67, 68,
-		70, 71, 72, 73, 75, 76, 78, 79, 80, 82,
-		83, 85, 86, 88, 90, 91, 93, 95, 96, 98,
-		100, 102, 103, 105, 107, 109, 111, 113, 115, 117,
-		120
-	},
-	{
-		24, 24, 24, 25, 25, 26, 26, 27, 27, 28,
-		28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
-		34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
-		41, 41, 42, 43, 44, 44, 45, 46, 47, 48,
-		49, 50, 50, 51, 52, 53, 54, 55, 56, 57,
-		58, 59, 60, 62, 63, 64, 65, 66, 67, 69,
-		70, 71, 72, 74, 75, 76, 78, 79, 81, 82,
-		84, 85, 87, 88, 90, 92, 93, 95, 97, 98,
-		100, 102, 104, 106, 108, 110, 112, 114, 116, 118,
-		120, 122, 124, 127, 129, 131, 134, 136, 138, 141,
-		144
-	},
-	{
-		32, 32, 33, 33, 34, 34, 35, 36, 36, 37,
-		38, 38, 39, 40, 41, 41, 42, 43, 44, 44,
-		45, 46, 47, 48, 49, 50, 50, 51, 52, 53,
-		54, 55, 56, 57, 58, 59, 60, 62, 63, 64,
-		65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
-		78, 79, 81, 82, 84, 85, 87, 88, 90, 92,
-		93, 95, 97, 98, 100, 102, 104, 106, 108, 110,
-		112, 114, 116, 118, 120, 122, 124, 127, 129, 131,
-		134, 136, 139, 141, 144, 146, 149, 152, 154, 157,
-		160, 163, 166, 169, 172, 175, 178, 181, 185, 188,
-		192
-	}
-};
-
-/* MPEG blank frame generation tables */
-
-enum mpeg_frame_type {
-	PFRAME,
-	BFRAME_PRE,
-	BFRAME_POST,
-	BFRAME_BIDIR,
-	BFRAME_EMPTY
-};
-
-static const u32 addrinctab[33][2] = {
-	{ 0x01, 1 },	{ 0x03, 3 },	{ 0x02, 3 },	{ 0x03, 4 },
-	{ 0x02, 4 },	{ 0x03, 5 },	{ 0x02, 5 },	{ 0x07, 7 },
-	{ 0x06, 7 },	{ 0x0b, 8 },	{ 0x0a, 8 },	{ 0x09, 8 },
-	{ 0x08, 8 },	{ 0x07, 8 },	{ 0x06, 8 },	{ 0x17, 10 },
-	{ 0x16, 10 },	{ 0x15, 10 },	{ 0x14, 10 },	{ 0x13, 10 },
-	{ 0x12, 10 },	{ 0x23, 11 },	{ 0x22, 11 },	{ 0x21, 11 },
-	{ 0x20, 11 },	{ 0x1f, 11 },	{ 0x1e, 11 },	{ 0x1d, 11 },
-	{ 0x1c, 11 },	{ 0x1b, 11 },	{ 0x1a, 11 },	{ 0x19, 11 },
-	{ 0x18, 11 }
-};
-
-/* Standard JPEG tables */
-
-static const u8 default_intra_quant_table[] = {
-	 8, 16, 19, 22, 26, 27, 29, 34,
-	16, 16, 22, 24, 27, 29, 34, 37,
-	19, 22, 26, 27, 29, 34, 34, 38,
-	22, 22, 26, 27, 29, 34, 37, 40,
-	22, 26, 27, 29, 32, 35, 40, 48,
-	26, 27, 29, 32, 35, 40, 48, 58,
-	26, 27, 29, 34, 38, 46, 56, 69,
-	27, 29, 35, 38, 46, 56, 69, 83
-};
-
-static const u8 bits_dc_luminance[] = {
-	0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const u8 val_dc_luminance[] = {
-	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-static const u8 bits_dc_chrominance[] = {
-	0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
-};
-
-static const u8 val_dc_chrominance[] = {
-	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-static const u8 bits_ac_luminance[] = {
-	0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
-};
-
-static const u8 val_ac_luminance[] = {
-	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa
-};
-
-static const u8 bits_ac_chrominance[] = {
-	0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
-};
-
-static const u8 val_ac_chrominance[] = {
-	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
-	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
-	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
-	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
-	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
-	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
-	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
-	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
-	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa
-};
-
-/* Zig-zag mapping for quant table
- *
- * OK, let's do this mapping on the actual table above so it doesn't have
- * to be done on the fly.
- */
-static const int zz[64] = {
-	0,   1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5,
-	12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28,
-	35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
-	58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
-};
-
-static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space)
-{
-	int i, cnt = pkg_cnt * 32;
-
-	if (space < cnt)
-		return -1;
-
-	for (i = 0; i < cnt; ++i)
-		dest[i] = cpu_to_le16p(src + i);
-
-	return cnt;
-}
-
-static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q)
-{
-	int i, p = 0;
-
-	buf[p++] = 0xff;
-	buf[p++] = 0xd8;
-	buf[p++] = 0xff;
-	buf[p++] = 0xdb;
-	buf[p++] = 0;
-	buf[p++] = 2 + 65;
-	buf[p++] = 0;
-	buf[p++] = default_intra_quant_table[0];
-	for (i = 1; i < 64; ++i)
-		/* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */
-		buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3;
-	buf[p++] = 0xff;
-	buf[p++] = 0xc0;
-	buf[p++] = 0;
-	buf[p++] = 17;
-	buf[p++] = 8;
-	buf[p++] = go->height >> 8;
-	buf[p++] = go->height & 0xff;
-	buf[p++] = go->width >> 8;
-	buf[p++] = go->width & 0xff;
-	buf[p++] = 3;
-	buf[p++] = 1;
-	buf[p++] = 0x22;
-	buf[p++] = 0;
-	buf[p++] = 2;
-	buf[p++] = 0x11;
-	buf[p++] = 0;
-	buf[p++] = 3;
-	buf[p++] = 0x11;
-	buf[p++] = 0;
-	buf[p++] = 0xff;
-	buf[p++] = 0xc4;
-	buf[p++] = 418 >> 8;
-	buf[p++] = 418 & 0xff;
-	buf[p++] = 0x00;
-	memcpy(buf + p, bits_dc_luminance + 1, 16);
-	p += 16;
-	memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance));
-	p += sizeof(val_dc_luminance);
-	buf[p++] = 0x01;
-	memcpy(buf + p, bits_dc_chrominance + 1, 16);
-	p += 16;
-	memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance));
-	p += sizeof(val_dc_chrominance);
-	buf[p++] = 0x10;
-	memcpy(buf + p, bits_ac_luminance + 1, 16);
-	p += 16;
-	memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance));
-	p += sizeof(val_ac_luminance);
-	buf[p++] = 0x11;
-	memcpy(buf + p, bits_ac_chrominance + 1, 16);
-	p += 16;
-	memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance));
-	p += sizeof(val_ac_chrominance);
-	buf[p++] = 0xff;
-	buf[p++] = 0xda;
-	buf[p++] = 0;
-	buf[p++] = 12;
-	buf[p++] = 3;
-	buf[p++] = 1;
-	buf[p++] = 0x00;
-	buf[p++] = 2;
-	buf[p++] = 0x11;
-	buf[p++] = 3;
-	buf[p++] = 0x11;
-	buf[p++] = 0;
-	buf[p++] = 63;
-	buf[p++] = 0;
-	return p;
-}
-
-static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
-{
-	u8 *buf;
-	u16 mem = 0x3e00;
-	unsigned int addr = 0x19;
-	int size = 0, i, off = 0, chunk;
-
-	buf = kzalloc(4096, GFP_KERNEL);
-	if (buf == NULL)
-		return -1;
-
-	for (i = 1; i < 32; ++i) {
-		mjpeg_frame_header(go, buf + size, i);
-		size += 80;
-	}
-	chunk = mjpeg_frame_header(go, buf + size, 1);
-	memmove(buf + size, buf + size + 80, chunk - 80);
-	size += chunk - 80;
-
-	for (i = 0; i < size; i += chunk * 2) {
-		if (space - off < 32) {
-			off = -1;
-			goto done;
-		}
-
-		code[off + 1] = __cpu_to_le16(0x8000 | mem);
-
-		chunk = 28;
-		if (mem + chunk > 0x4000)
-			chunk = 0x4000 - mem;
-		if (i + 2 * chunk > size)
-			chunk = (size - i) / 2;
-
-		if (chunk < 28) {
-			code[off] = __cpu_to_le16(0x4000 | chunk);
-			code[off + 31] = __cpu_to_le16(addr++);
-			mem = 0x3e00;
-		} else {
-			code[off] = __cpu_to_le16(0x1000 | 28);
-			code[off + 31] = 0;
-			mem += 28;
-		}
-
-		memcpy(&code[off + 2], buf + i, chunk * 2);
-		off += 32;
-	}
-done:
-	kfree(buf);
-	return off;
-}
-
-static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
-		int modulo, int pict_struct, enum mpeg_frame_type frame)
-{
-	int i, j, mb_code, mb_len;
-	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
-	CODE_GEN(c, buf + 6);
-
-	switch (frame) {
-	case PFRAME:
-		mb_code = 0x1;
-		mb_len = 3;
-		break;
-	case BFRAME_PRE:
-		mb_code = 0x2;
-		mb_len = 4;
-		break;
-	case BFRAME_POST:
-		mb_code = 0x2;
-		mb_len = 3;
-		break;
-	case BFRAME_BIDIR:
-		mb_code = 0x2;
-		mb_len = 2;
-		break;
-	default: /* keep the compiler happy */
-		mb_code = mb_len = 0;
-		break;
-	}
-
-	CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13);
-	CODE_ADD(c, 0xffff, 16);
-	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
-	if (frame != PFRAME)
-		CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
-	else
-		CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */
-	CODE_ADD(c, 0, 3); /* What is this?? */
-	/* Byte-align with zeros */
-	j = 8 - (CODE_LENGTH(c) % 8);
-	if (j != 8)
-		CODE_ADD(c, 0, j);
-
-	if (go->format == V4L2_PIX_FMT_MPEG2) {
-		CODE_ADD(c, 0x1, 24);
-		CODE_ADD(c, 0xb5, 8);
-		CODE_ADD(c, 0x844, 12);
-		CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8);
-		if (go->interlace_coding) {
-			CODE_ADD(c, pict_struct, 4);
-			if (go->dvd_mode)
-				CODE_ADD(c, 0x000, 11);
-			else
-				CODE_ADD(c, 0x200, 11);
-		} else {
-			CODE_ADD(c, 0x3, 4);
-			CODE_ADD(c, 0x20c, 11);
-		}
-		/* Byte-align with zeros */
-		j = 8 - (CODE_LENGTH(c) % 8);
-		if (j != 8)
-			CODE_ADD(c, 0, j);
-	}
-
-	for (i = 0; i < rows; ++i) {
-		CODE_ADD(c, 1, 24);
-		CODE_ADD(c, i + 1, 8);
-		CODE_ADD(c, 0x2, 6);
-		CODE_ADD(c, 0x1, 1);
-		CODE_ADD(c, mb_code, mb_len);
-		if (go->interlace_coding) {
-			CODE_ADD(c, 0x1, 2);
-			CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
-		}
-		if (frame == BFRAME_BIDIR) {
-			CODE_ADD(c, 0x3, 2);
-			if (go->interlace_coding)
-				CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
-		}
-		CODE_ADD(c, 0x3, 2);
-		for (j = (go->width >> 4) - 2; j >= 33; j -= 33)
-			CODE_ADD(c, 0x8, 11);
-		CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]);
-		CODE_ADD(c, mb_code, mb_len);
-		if (go->interlace_coding) {
-			CODE_ADD(c, 0x1, 2);
-			CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
-		}
-		if (frame == BFRAME_BIDIR) {
-			CODE_ADD(c, 0x3, 2);
-			if (go->interlace_coding)
-				CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
-		}
-		CODE_ADD(c, 0x3, 2);
-
-		/* Byte-align with zeros */
-		j = 8 - (CODE_LENGTH(c) % 8);
-		if (j != 8)
-			CODE_ADD(c, 0, j);
-	}
-
-	i = CODE_LENGTH(c) + 4 * 8;
-	buf[2] = 0x00;
-	buf[3] = 0x00;
-	buf[4] = 0x01;
-	buf[5] = 0x00;
-	return i;
-}
-
-static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
-{
-	int i, aspect_ratio, picture_rate;
-	CODE_GEN(c, buf + 6);
-
-	if (go->format == V4L2_PIX_FMT_MPEG1) {
-		switch (go->aspect_ratio) {
-		case GO7007_RATIO_4_3:
-			aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
-			break;
-		case GO7007_RATIO_16_9:
-			aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
-			break;
-		default:
-			aspect_ratio = 1;
-			break;
-		}
-	} else {
-		switch (go->aspect_ratio) {
-		case GO7007_RATIO_4_3:
-			aspect_ratio = 2;
-			break;
-		case GO7007_RATIO_16_9:
-			aspect_ratio = 3;
-			break;
-		default:
-			aspect_ratio = 1;
-			break;
-		}
-	}
-	switch (go->sensor_framerate) {
-	case 24000:
-		picture_rate = 1;
-		break;
-	case 24024:
-		picture_rate = 2;
-		break;
-	case 25025:
-		picture_rate = go->interlace_coding ? 6 : 3;
-		break;
-	case 30000:
-		picture_rate = go->interlace_coding ? 7 : 4;
-		break;
-	case 30030:
-		picture_rate = go->interlace_coding ? 8 : 5;
-		break;
-	default:
-		picture_rate = 5; /* 30 fps seems like a reasonable default */
-		break;
-	}
-
-	CODE_ADD(c, go->width, 12);
-	CODE_ADD(c, go->height, 12);
-	CODE_ADD(c, aspect_ratio, 4);
-	CODE_ADD(c, picture_rate, 4);
-	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18);
-	CODE_ADD(c, 1, 1);
-	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10);
-	CODE_ADD(c, 0, 3);
-
-	/* Byte-align with zeros */
-	i = 8 - (CODE_LENGTH(c) % 8);
-	if (i != 8)
-		CODE_ADD(c, 0, i);
-
-	if (go->format == V4L2_PIX_FMT_MPEG2) {
-		CODE_ADD(c, 0x1, 24);
-		CODE_ADD(c, 0xb5, 8);
-		CODE_ADD(c, 0x148, 12);
-		if (go->interlace_coding)
-			CODE_ADD(c, 0x20001, 20);
-		else
-			CODE_ADD(c, 0xa0001, 20);
-		CODE_ADD(c, 0, 16);
-
-		/* Byte-align with zeros */
-		i = 8 - (CODE_LENGTH(c) % 8);
-		if (i != 8)
-			CODE_ADD(c, 0, i);
-
-		if (ext) {
-			CODE_ADD(c, 0x1, 24);
-			CODE_ADD(c, 0xb52, 12);
-			CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3);
-			CODE_ADD(c, 0x105, 9);
-			CODE_ADD(c, 0x505, 16);
-			CODE_ADD(c, go->width, 14);
-			CODE_ADD(c, 1, 1);
-			CODE_ADD(c, go->height, 14);
-
-			/* Byte-align with zeros */
-			i = 8 - (CODE_LENGTH(c) % 8);
-			if (i != 8)
-				CODE_ADD(c, 0, i);
-		}
-	}
-
-	i = CODE_LENGTH(c) + 4 * 8;
-	buf[0] = i & 0xff;
-	buf[1] = i >> 8;
-	buf[2] = 0x00;
-	buf[3] = 0x00;
-	buf[4] = 0x01;
-	buf[5] = 0xb3;
-	return i;
-}
-
-static int gen_mpeg1hdr_to_package(struct go7007 *go,
-					__le16 *code, int space, int *framelen)
-{
-	u8 *buf;
-	u16 mem = 0x3e00;
-	unsigned int addr = 0x19;
-	int i, off = 0, chunk;
-
-	buf = kzalloc(5120, GFP_KERNEL);
-	if (buf == NULL)
-		return -1;
-
-	framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
-	if (go->interlace_coding)
-		framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8,
-							0, 2, PFRAME);
-	buf[0] = framelen[0] & 0xff;
-	buf[1] = framelen[0] >> 8;
-	i = 368;
-	framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE);
-	if (go->interlace_coding)
-		framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8,
-							0, 2, BFRAME_PRE);
-	buf[i] = framelen[1] & 0xff;
-	buf[i + 1] = framelen[1] >> 8;
-	i += 1632;
-	framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST);
-	if (go->interlace_coding)
-		framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8,
-							0, 2, BFRAME_POST);
-	buf[i] = framelen[2] & 0xff;
-	buf[i + 1] = framelen[2] >> 8;
-	i += 1432;
-	framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR);
-	if (go->interlace_coding)
-		framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8,
-							0, 2, BFRAME_BIDIR);
-	buf[i] = framelen[3] & 0xff;
-	buf[i + 1] = framelen[3] >> 8;
-	i += 1632 + 16;
-	mpeg1_sequence_header(go, buf + i, 0);
-	i += 40;
-	for (i = 0; i < 5120; i += chunk * 2) {
-		if (space - off < 32) {
-			off = -1;
-			goto done;
-		}
-
-		code[off + 1] = __cpu_to_le16(0x8000 | mem);
-
-		chunk = 28;
-		if (mem + chunk > 0x4000)
-			chunk = 0x4000 - mem;
-		if (i + 2 * chunk > 5120)
-			chunk = (5120 - i) / 2;
-
-		if (chunk < 28) {
-			code[off] = __cpu_to_le16(0x4000 | chunk);
-			code[off + 31] = __cpu_to_le16(addr);
-			if (mem + chunk == 0x4000) {
-				mem = 0x3e00;
-				++addr;
-			}
-		} else {
-			code[off] = __cpu_to_le16(0x1000 | 28);
-			code[off + 31] = 0;
-			mem += 28;
-		}
-
-		memcpy(&code[off + 2], buf + i, chunk * 2);
-		off += 32;
-	}
-done:
-	kfree(buf);
-	return off;
-}
-
-static int vti_bitlen(struct go7007 *go)
-{
-	unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale;
-
-	for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i)
-		;
-	return i + 1;
-}
-
-static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf,
-		int modulo, enum mpeg_frame_type frame)
-{
-	int i;
-	CODE_GEN(c, buf + 6);
-	int mb_count = (go->width >> 4) * (go->height >> 4);
-
-	CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2);
-	if (modulo)
-		CODE_ADD(c, 0x1, 1);
-	CODE_ADD(c, 0x1, 2);
-	CODE_ADD(c, 0, vti_bitlen(go));
-	CODE_ADD(c, 0x3, 2);
-	if (frame == PFRAME)
-		CODE_ADD(c, 0, 1);
-	CODE_ADD(c, 0xc, 11);
-	if (frame != PFRAME)
-		CODE_ADD(c, 0x4, 3);
-	if (frame != BFRAME_EMPTY) {
-		for (i = 0; i < mb_count; ++i) {
-			switch (frame) {
-			case PFRAME:
-				CODE_ADD(c, 0x1, 1);
-				break;
-			case BFRAME_PRE:
-				CODE_ADD(c, 0x47, 8);
-				break;
-			case BFRAME_POST:
-				CODE_ADD(c, 0x27, 7);
-				break;
-			case BFRAME_BIDIR:
-				CODE_ADD(c, 0x5f, 8);
-				break;
-			case BFRAME_EMPTY: /* keep compiler quiet */
-				break;
-			}
-		}
-	}
-
-	/* Byte-align with a zero followed by ones */
-	i = 8 - (CODE_LENGTH(c) % 8);
-	CODE_ADD(c, 0, 1);
-	CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
-
-	i = CODE_LENGTH(c) + 4 * 8;
-	buf[0] = i & 0xff;
-	buf[1] = i >> 8;
-	buf[2] = 0x00;
-	buf[3] = 0x00;
-	buf[4] = 0x01;
-	buf[5] = 0xb6;
-	return i;
-}
-
-static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
-{
-	const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali,
-		0x00, 0x00, 0x01, 0xb5, 0x09,
-		0x00, 0x00, 0x01, 0x00,
-		0x00, 0x00, 0x01, 0x20, };
-	int i, aspect_ratio;
-	int fps = go->sensor_framerate / go->fps_scale;
-	CODE_GEN(c, buf + 2 + sizeof(head));
-
-	switch (go->aspect_ratio) {
-	case GO7007_RATIO_4_3:
-		aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
-		break;
-	case GO7007_RATIO_16_9:
-		aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
-		break;
-	default:
-		aspect_ratio = 1;
-		break;
-	}
-
-	memcpy(buf + 2, head, sizeof(head));
-	CODE_ADD(c, 0x191, 17);
-	CODE_ADD(c, aspect_ratio, 4);
-	CODE_ADD(c, 0x1, 4);
-	CODE_ADD(c, fps, 16);
-	CODE_ADD(c, 0x3, 2);
-	CODE_ADD(c, 1001, vti_bitlen(go));
-	CODE_ADD(c, 1, 1);
-	CODE_ADD(c, go->width, 13);
-	CODE_ADD(c, 1, 1);
-	CODE_ADD(c, go->height, 13);
-	CODE_ADD(c, 0x2830, 14);
-
-	/* Byte-align */
-	i = 8 - (CODE_LENGTH(c) % 8);
-	CODE_ADD(c, 0, 1);
-	CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
-
-	i = CODE_LENGTH(c) + sizeof(head) * 8;
-	buf[0] = i & 0xff;
-	buf[1] = i >> 8;
-	return i;
-}
-
-static int gen_mpeg4hdr_to_package(struct go7007 *go,
-					__le16 *code, int space, int *framelen)
-{
-	u8 *buf;
-	u16 mem = 0x3e00;
-	unsigned int addr = 0x19;
-	int i, off = 0, chunk;
-
-	buf = kzalloc(5120, GFP_KERNEL);
-	if (buf == NULL)
-		return -1;
-
-	framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
-	i = 368;
-	framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE);
-	i += 1632;
-	framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST);
-	i += 1432;
-	framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR);
-	i += 1632;
-	mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY);
-	i += 16;
-	mpeg4_sequence_header(go, buf + i, 0);
-	i += 40;
-	for (i = 0; i < 5120; i += chunk * 2) {
-		if (space - off < 32) {
-			off = -1;
-			goto done;
-		}
-
-		code[off + 1] = __cpu_to_le16(0x8000 | mem);
-
-		chunk = 28;
-		if (mem + chunk > 0x4000)
-			chunk = 0x4000 - mem;
-		if (i + 2 * chunk > 5120)
-			chunk = (5120 - i) / 2;
-
-		if (chunk < 28) {
-			code[off] = __cpu_to_le16(0x4000 | chunk);
-			code[off + 31] = __cpu_to_le16(addr);
-			if (mem + chunk == 0x4000) {
-				mem = 0x3e00;
-				++addr;
-			}
-		} else {
-			code[off] = __cpu_to_le16(0x1000 | 28);
-			code[off + 31] = 0;
-			mem += 28;
-		}
-
-		memcpy(&code[off + 2], buf + i, chunk * 2);
-		off += 32;
-	}
-	mem = 0x3e00;
-	addr = go->ipb ? 0x14f9 : 0x0af9;
-	memset(buf, 0, 5120);
-	framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME);
-	i = 368;
-	framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE);
-	i += 1632;
-	framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST);
-	i += 1432;
-	framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR);
-	i += 1632;
-	mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY);
-	i += 16;
-	for (i = 0; i < 5120; i += chunk * 2) {
-		if (space - off < 32) {
-			off = -1;
-			goto done;
-		}
-
-		code[off + 1] = __cpu_to_le16(0x8000 | mem);
-
-		chunk = 28;
-		if (mem + chunk > 0x4000)
-			chunk = 0x4000 - mem;
-		if (i + 2 * chunk > 5120)
-			chunk = (5120 - i) / 2;
-
-		if (chunk < 28) {
-			code[off] = __cpu_to_le16(0x4000 | chunk);
-			code[off + 31] = __cpu_to_le16(addr);
-			if (mem + chunk == 0x4000) {
-				mem = 0x3e00;
-				++addr;
-			}
-		} else {
-			code[off] = __cpu_to_le16(0x1000 | 28);
-			code[off + 31] = 0;
-			mem += 28;
-		}
-
-		memcpy(&code[off + 2], buf + i, chunk * 2);
-		off += 32;
-	}
-done:
-	kfree(buf);
-	return off;
-}
-
-static int brctrl_to_package(struct go7007 *go,
-					__le16 *code, int space, int *framelen)
-{
-	int converge_speed = 0;
-	int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ?
-				100 : 0;
-	int peak_rate = 6 * go->bitrate / 5;
-	int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ?
-				go->bitrate :
-				(go->dvd_mode ? 900000 : peak_rate);
-	int fps = go->sensor_framerate / go->fps_scale;
-	int q = 0;
-	/* Bizarre math below depends on rounding errors in division */
-	u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps;
-	u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps;
-	u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000);
-	u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32);
-	u32 cplx[] = {
-		q > 0 ? sgop_expt_addr * q :
-			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
-		q > 0 ? sgop_expt_addr * q :
-			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
-		q > 0 ? sgop_expt_addr * q :
-			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
-		q > 0 ? sgop_expt_addr * q :
-			2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
-	};
-	u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr;
-	u16 pack[] = {
-		0x200e,		0x0000,
-		0xBF20,		go->ipb ? converge_speed_ipb[converge_speed]
-					: converge_speed_ip[converge_speed],
-		0xBF21,		go->ipb ? 2 : 0,
-		0xBF22,		go->ipb ? LAMBDA_table[0][lambda / 2 + 50]
-					: 32767,
-		0xBF23,		go->ipb ? LAMBDA_table[1][lambda] : 32767,
-		0xBF24,		32767,
-		0xBF25,		lambda > 99 ? 32767 : LAMBDA_table[3][lambda],
-		0xBF26,		sgop_expt_addr & 0x0000FFFF,
-		0xBF27,		sgop_expt_addr >> 16,
-		0xBF28,		sgop_peak_addr & 0x0000FFFF,
-		0xBF29,		sgop_peak_addr >> 16,
-		0xBF2A,		vbv_alert_addr & 0x0000FFFF,
-		0xBF2B,		vbv_alert_addr >> 16,
-		0xBF2C,		0,
-		0xBF2D,		0,
-		0,		0,
-
-		0x200e,		0x0000,
-		0xBF2E,		vbv_alert_addr & 0x0000FFFF,
-		0xBF2F,		vbv_alert_addr >> 16,
-		0xBF30,		cplx[0] & 0x0000FFFF,
-		0xBF31,		cplx[0] >> 16,
-		0xBF32,		cplx[1] & 0x0000FFFF,
-		0xBF33,		cplx[1] >> 16,
-		0xBF34,		cplx[2] & 0x0000FFFF,
-		0xBF35,		cplx[2] >> 16,
-		0xBF36,		cplx[3] & 0x0000FFFF,
-		0xBF37,		cplx[3] >> 16,
-		0xBF38,		0,
-		0xBF39,		0,
-		0xBF3A,		total_expt_addr & 0x0000FFFF,
-		0xBF3B,		total_expt_addr >> 16,
-		0,		0,
-
-		0x200e,		0x0000,
-		0xBF3C,		total_expt_addr & 0x0000FFFF,
-		0xBF3D,		total_expt_addr >> 16,
-		0xBF3E,		0,
-		0xBF3F,		0,
-		0xBF48,		0,
-		0xBF49,		0,
-		0xBF4A,		calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q),
-		0xBF4B,		4,
-		0xBF4C,		0,
-		0xBF4D,		0,
-		0xBF4E,		0,
-		0xBF4F,		0,
-		0xBF50,		0,
-		0xBF51,		0,
-		0,		0,
-
-		0x200e,		0x0000,
-		0xBF40,		sgop_expt_addr & 0x0000FFFF,
-		0xBF41,		sgop_expt_addr >> 16,
-		0xBF42,		0,
-		0xBF43,		0,
-		0xBF44,		0,
-		0xBF45,		0,
-		0xBF46,		(go->width >> 4) * (go->height >> 4),
-		0xBF47,		0,
-		0xBF64,		0,
-		0xBF65,		0,
-		0xBF18,		framelen[4],
-		0xBF19,		framelen[5],
-		0xBF1A,		framelen[6],
-		0xBF1B,		framelen[7],
-		0,		0,
-
-#if 0
-		/* Remove once we don't care about matching */
-		0x200e,		0x0000,
-		0xBF56,		4,
-		0xBF57,		0,
-		0xBF58,		5,
-		0xBF59,		0,
-		0xBF5A,		6,
-		0xBF5B,		0,
-		0xBF5C,		8,
-		0xBF5D,		0,
-		0xBF5E,		1,
-		0xBF5F,		0,
-		0xBF60,		1,
-		0xBF61,		0,
-		0xBF62,		0,
-		0xBF63,		0,
-		0,		0,
-#else
-		0x2008,		0x0000,
-		0xBF56,		4,
-		0xBF57,		0,
-		0xBF58,		5,
-		0xBF59,		0,
-		0xBF5A,		6,
-		0xBF5B,		0,
-		0xBF5C,		8,
-		0xBF5D,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-#endif
-
-		0x200e,		0x0000,
-		0xBF10,		0,
-		0xBF11,		0,
-		0xBF12,		0,
-		0xBF13,		0,
-		0xBF14,		0,
-		0xBF15,		0,
-		0xBF16,		0,
-		0xBF17,		0,
-		0xBF7E,		0,
-		0xBF7F,		1,
-		0xBF52,		framelen[0],
-		0xBF53,		framelen[1],
-		0xBF54,		framelen[2],
-		0xBF55,		framelen[3],
-		0,		0,
-	};
-
-	return copy_packages(code, pack, 6, space);
-}
-
-static int config_package(struct go7007 *go, __le16 *code, int space)
-{
-	int fps = go->sensor_framerate / go->fps_scale / 1000;
-	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
-	int brc_window_size = fps;
-	int q_min = 2, q_max = 31;
-	int THACCoeffSet0 = 0;
-	u16 pack[] = {
-		0x200e,		0x0000,
-		0xc002,		0x14b4,
-		0xc003,		0x28b4,
-		0xc004,		0x3c5a,
-		0xdc05,		0x2a77,
-		0xc6c3,		go->format == V4L2_PIX_FMT_MPEG4 ? 0 :
-				(go->format == V4L2_PIX_FMT_H263 ? 0 : 1),
-		0xc680,		go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 :
-				(go->format == V4L2_PIX_FMT_H263 ? 0x61 :
-									0xd3),
-		0xc780,		0x0140,
-		0xe009,		0x0001,
-		0xc60f,		0x0008,
-		0xd4ff,		0x0002,
-		0xe403,		2340,
-		0xe406,		75,
-		0xd411,		0x0001,
-		0xd410,		0xa1d6,
-		0x0001,		0x2801,
-
-		0x200d,		0x0000,
-		0xe402,		0x018b,
-		0xe401,		0x8b01,
-		0xd472,		(go->board_info->sensor_flags &
-							GO7007_SENSOR_TV) &&
-						(!go->interlace_coding) ?
-					0x01b0 : 0x0170,
-		0xd475,		(go->board_info->sensor_flags &
-							GO7007_SENSOR_TV) &&
-						(!go->interlace_coding) ?
-					0x0008 : 0x0009,
-		0xc404,		go->interlace_coding ? 0x44 :
-				(go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 :
-				(go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 :
-				(go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 :
-				(go->format == V4L2_PIX_FMT_H263  ? 0x08 :
-								     0x20)))),
-		0xbf0a,		(go->format == V4L2_PIX_FMT_MPEG4 ? 8 :
-				(go->format == V4L2_PIX_FMT_MPEG1 ? 1 :
-				(go->format == V4L2_PIX_FMT_MPEG2 ? 2 :
-				(go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) |
-				((go->repeat_seqhead ? 1 : 0) << 6) |
-				((go->dvd_mode ? 1 : 0) << 9) |
-				((go->gop_header_enable ? 1 : 0) << 10),
-		0xbf0b,		0,
-		0xdd5a,		go->ipb ? 0x14 : 0x0a,
-		0xbf0c,		0,
-		0xbf0d,		0,
-		0xc683,		THACCoeffSet0,
-		0xc40a,		(go->width << 4) | rows,
-		0xe01a,		go->board_info->hpi_buffer_cap,
-		0,		0,
-		0,		0,
-
-		0x2008,		0,
-		0xe402,		0x88,
-		0xe401,		0x8f01,
-		0xbf6a,		0,
-		0xbf6b,		0,
-		0xbf6c,		0,
-		0xbf6d,		0,
-		0xbf6e,		0,
-		0xbf6f,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-
-		0x200e,		0,
-		0xbf66,		brc_window_size,
-		0xbf67,		0,
-		0xbf68,		q_min,
-		0xbf69,		q_max,
-		0xbfe0,		0,
-		0xbfe1,		0,
-		0xbfe2,		0,
-		0xbfe3,		go->ipb ? 3 : 1,
-		0xc031,		go->board_info->sensor_flags &
-					GO7007_SENSOR_VBI ? 1 : 0,
-		0xc01c,		0x1f,
-		0xdd8c,		0x15,
-		0xdd94,		0x15,
-		0xdd88,		go->ipb ? 0x1401 : 0x0a01,
-		0xdd90,		go->ipb ? 0x1401 : 0x0a01,
-		0,		0,
-
-		0x200e,		0,
-		0xbfe4,		0,
-		0xbfe5,		0,
-		0xbfe6,		0,
-		0xbfe7,		fps << 8,
-		0xbfe8,		0x3a00,
-		0xbfe9,		0,
-		0xbfea,		0,
-		0xbfeb,		0,
-		0xbfec,		(go->interlace_coding ? 1 << 15 : 0) |
-					(go->modet_enable ? 0xa : 0) |
-					(go->board_info->sensor_flags &
-						GO7007_SENSOR_VBI ? 1 : 0),
-		0xbfed,		0,
-		0xbfee,		0,
-		0xbfef,		0,
-		0xbff0,		go->board_info->sensor_flags &
-					GO7007_SENSOR_TV ? 0xf060 : 0xb060,
-		0xbff1,		0,
-		0,		0,
-	};
-
-	return copy_packages(code, pack, 5, space);
-}
-
-static int seqhead_to_package(struct go7007 *go, __le16 *code, int space,
-	int (*sequence_header_func)(struct go7007 *go,
-		unsigned char *buf, int ext))
-{
-	int vop_time_increment_bitlength = vti_bitlen(go);
-	int fps = go->sensor_framerate / go->fps_scale *
-					(go->interlace_coding ? 2 : 1);
-	unsigned char buf[40] = { };
-	int len = sequence_header_func(go, buf, 1);
-	u16 pack[] = {
-		0x2006,		0,
-		0xbf08,		fps,
-		0xbf09,		0,
-		0xbff2,		vop_time_increment_bitlength,
-		0xbff3,		(1 << vop_time_increment_bitlength) - 1,
-		0xbfe6,		0,
-		0xbfe7,		(fps / 1000) << 8,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-
-		0x2007,		0,
-		0xc800,		buf[2] << 8 | buf[3],
-		0xc801,		buf[4] << 8 | buf[5],
-		0xc802,		buf[6] << 8 | buf[7],
-		0xc803,		buf[8] << 8 | buf[9],
-		0xc406,		64,
-		0xc407,		len - 64,
-		0xc61b,		1,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-
-		0x200e,		0,
-		0xc808,		buf[10] << 8 | buf[11],
-		0xc809,		buf[12] << 8 | buf[13],
-		0xc80a,		buf[14] << 8 | buf[15],
-		0xc80b,		buf[16] << 8 | buf[17],
-		0xc80c,		buf[18] << 8 | buf[19],
-		0xc80d,		buf[20] << 8 | buf[21],
-		0xc80e,		buf[22] << 8 | buf[23],
-		0xc80f,		buf[24] << 8 | buf[25],
-		0xc810,		buf[26] << 8 | buf[27],
-		0xc811,		buf[28] << 8 | buf[29],
-		0xc812,		buf[30] << 8 | buf[31],
-		0xc813,		buf[32] << 8 | buf[33],
-		0xc814,		buf[34] << 8 | buf[35],
-		0xc815,		buf[36] << 8 | buf[37],
-		0,		0,
-		0,		0,
-		0,		0,
-	};
-
-	return copy_packages(code, pack, 3, space);
-}
-
-static int relative_prime(int big, int little)
-{
-	int remainder;
-
-	while (little != 0) {
-		remainder = big % little;
-		big = little;
-		little = remainder;
-	}
-	return big;
-}
-
-static int avsync_to_package(struct go7007 *go, __le16 *code, int space)
-{
-	int arate = go->board_info->audio_rate * 1001 * go->fps_scale;
-	int ratio = arate / go->sensor_framerate;
-	int adjratio = ratio * 215 / 100;
-	int rprime = relative_prime(go->sensor_framerate,
-					arate % go->sensor_framerate);
-	int f1 = (arate % go->sensor_framerate) / rprime;
-	int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime;
-	u16 pack[] = {
-		0x200e,		0,
-		0xbf98,		(u16)((-adjratio) & 0xffff),
-		0xbf99,		(u16)((-adjratio) >> 16),
-		0xbf92,		0,
-		0xbf93,		0,
-		0xbff4,		f1 > f2 ? f1 : f2,
-		0xbff5,		f1 < f2 ? f1 : f2,
-		0xbff6,		f1 < f2 ? ratio : ratio + 1,
-		0xbff7,		f1 > f2 ? ratio : ratio + 1,
-		0xbff8,		0,
-		0xbff9,		0,
-		0xbffa,		adjratio & 0xffff,
-		0xbffb,		adjratio >> 16,
-		0xbf94,		0,
-		0xbf95,		0,
-		0,		0,
-	};
-
-	return copy_packages(code, pack, 1, space);
-}
-
-static int final_package(struct go7007 *go, __le16 *code, int space)
-{
-	int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
-	u16 pack[] = {
-		0x8000,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		2,
-		((go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
-						(!go->interlace_coding) ?
-					(1 << 14) | (1 << 9) : 0) |
-			((go->encoder_subsample ? 1 : 0) << 8) |
-			(go->board_info->sensor_flags &
-				GO7007_SENSOR_CONFIG_MASK),
-		((go->encoder_v_halve ? 1 : 0) << 14) |
-			(go->encoder_v_halve ? rows << 9 : rows << 8) |
-			(go->encoder_h_halve ? 1 << 6 : 0) |
-			(go->encoder_h_halve ? go->width >> 3 : go->width >> 4),
-		(1 << 15) | (go->encoder_v_offset << 6) |
-			(1 << 7) | (go->encoder_h_offset >> 2),
-		(1 << 6),
-		0,
-		0,
-		((go->fps_scale - 1) << 8) |
-			(go->board_info->sensor_flags & GO7007_SENSOR_TV ?
-						(1 << 7) : 0) |
-			0x41,
-		go->ipb ? 0xd4c : 0x36b,
-		(rows << 8) | (go->width >> 4),
-		go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0,
-		(1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) |
-			((go->closed_gop ? 1 : 0) << 12) |
-			((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) |
-		/*	(1 << 9) |   */
-			((go->ipb ? 3 : 0) << 7) |
-			((go->modet_enable ? 1 : 0) << 2) |
-			((go->dvd_mode ? 1 : 0) << 1) | 1,
-		(go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 :
-			(go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 :
-			(go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 :
-			(go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 :
-			(go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))),
-		go->ipb ? 0x1f15 : 0x1f0b,
-		go->ipb ? 0x0015 : 0x000b,
-		go->ipb ? 0xa800 : 0x5800,
-		0xffff,
-		0x0020 + 0x034b * 0,
-		0x0020 + 0x034b * 1,
-		0x0020 + 0x034b * 2,
-		0x0020 + 0x034b * 3,
-		0x0020 + 0x034b * 4,
-		0x0020 + 0x034b * 5,
-		go->ipb ? (go->gop_size / 3) : go->gop_size,
-		(go->height >> 4) * (go->width >> 4) * 110 / 100,
-	};
-
-	return copy_packages(code, pack, 1, space);
-}
-
-static int audio_to_package(struct go7007 *go, __le16 *code, int space)
-{
-	int clock_config = ((go->board_info->audio_flags &
-				GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) |
-			((go->board_info->audio_flags &
-				GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) |
-			(((go->board_info->audio_bclk_div / 4) - 1) << 4) |
-			(go->board_info->audio_main_div - 1);
-	u16 pack[] = {
-		0x200d,		0,
-		0x9002,		0,
-		0x9002,		0,
-		0x9031,		0,
-		0x9032,		0,
-		0x9033,		0,
-		0x9034,		0,
-		0x9035,		0,
-		0x9036,		0,
-		0x9037,		0,
-		0x9040,		0,
-		0x9000,		clock_config,
-		0x9001,		(go->board_info->audio_flags & 0xffff) |
-					(1 << 9),
-		0x9000,		((go->board_info->audio_flags &
-						GO7007_AUDIO_I2S_MASTER ?
-						1 : 0) << 10) |
-					clock_config,
-		0,		0,
-		0,		0,
-		0x2005,		0,
-		0x9041,		0,
-		0x9042,		256,
-		0x9043,		0,
-		0x9044,		16,
-		0x9045,		16,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-		0,		0,
-	};
-
-	return copy_packages(code, pack, 2, space);
-}
-
-static int modet_to_package(struct go7007 *go, __le16 *code, int space)
-{
-	int ret, mb, i, addr, cnt = 0;
-	u16 pack[32];
-	u16 thresholds[] = {
-		0x200e,		0,
-		0xbf82,		go->modet[0].pixel_threshold,
-		0xbf83,		go->modet[1].pixel_threshold,
-		0xbf84,		go->modet[2].pixel_threshold,
-		0xbf85,		go->modet[3].pixel_threshold,
-		0xbf86,		go->modet[0].motion_threshold,
-		0xbf87,		go->modet[1].motion_threshold,
-		0xbf88,		go->modet[2].motion_threshold,
-		0xbf89,		go->modet[3].motion_threshold,
-		0xbf8a,		go->modet[0].mb_threshold,
-		0xbf8b,		go->modet[1].mb_threshold,
-		0xbf8c,		go->modet[2].mb_threshold,
-		0xbf8d,		go->modet[3].mb_threshold,
-		0xbf8e,		0,
-		0xbf8f,		0,
-		0,		0,
-	};
-
-	ret = copy_packages(code, thresholds, 1, space);
-	if (ret < 0)
-		return -1;
-	cnt += ret;
-
-	addr = 0xbac0;
-	memset(pack, 0, 64);
-	i = 0;
-	for (mb = 0; mb < 1624; ++mb) {
-		pack[i * 2 + 3] <<= 2;
-		pack[i * 2 + 3] |= go->modet_map[mb];
-		if (mb % 8 != 7)
-			continue;
-		pack[i * 2 + 2] = addr++;
-		++i;
-		if (i == 10 || mb == 1623) {
-			pack[0] = 0x2000 | i;
-			ret = copy_packages(code + cnt, pack, 1, space - cnt);
-			if (ret < 0)
-				return -1;
-			cnt += ret;
-			i = 0;
-			memset(pack, 0, 64);
-		}
-		pack[i * 2 + 3] = 0;
-	}
-
-	memset(pack, 0, 64);
-	i = 0;
-	for (addr = 0xbb90; addr < 0xbbfa; ++addr) {
-		pack[i * 2 + 2] = addr;
-		pack[i * 2 + 3] = 0;
-		++i;
-		if (i == 10 || addr == 0xbbf9) {
-			pack[0] = 0x2000 | i;
-			ret = copy_packages(code + cnt, pack, 1, space - cnt);
-			if (ret < 0)
-				return -1;
-			cnt += ret;
-			i = 0;
-			memset(pack, 0, 64);
-		}
-	}
-	return cnt;
-}
-
-static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
-			int *framelen)
-{
-	switch (type) {
-	case SPECIAL_FRM_HEAD:
-		switch (go->format) {
-		case V4L2_PIX_FMT_MJPEG:
-			return gen_mjpeghdr_to_package(go, code, space);
-		case V4L2_PIX_FMT_MPEG1:
-		case V4L2_PIX_FMT_MPEG2:
-			return gen_mpeg1hdr_to_package(go, code, space,
-								framelen);
-		case V4L2_PIX_FMT_MPEG4:
-			return gen_mpeg4hdr_to_package(go, code, space,
-								framelen);
-		}
-	case SPECIAL_BRC_CTRL:
-		return brctrl_to_package(go, code, space, framelen);
-	case SPECIAL_CONFIG:
-		return config_package(go, code, space);
-	case SPECIAL_SEQHEAD:
-		switch (go->format) {
-		case V4L2_PIX_FMT_MPEG1:
-		case V4L2_PIX_FMT_MPEG2:
-			return seqhead_to_package(go, code, space,
-					mpeg1_sequence_header);
-		case V4L2_PIX_FMT_MPEG4:
-			return seqhead_to_package(go, code, space,
-					mpeg4_sequence_header);
-		default:
-			return 0;
-		}
-	case SPECIAL_AV_SYNC:
-		return avsync_to_package(go, code, space);
-	case SPECIAL_FINAL:
-		return final_package(go, code, space);
-	case SPECIAL_AUDIO:
-		return audio_to_package(go, code, space);
-	case SPECIAL_MODET:
-		return modet_to_package(go, code, space);
-	}
-	dev_err(go->dev,
-		"firmware file contains unsupported feature %04x\n", type);
-	return -1;
-}
-
-int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
-{
-	const struct firmware *fw_entry;
-	__le16 *code, *src;
-	int framelen[8] = { }; /* holds the lengths of empty frame templates */
-	int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags;
-	int mode_flag;
-	int ret;
-
-	switch (go->format) {
-	case V4L2_PIX_FMT_MJPEG:
-		mode_flag = FLAG_MODE_MJPEG;
-		break;
-	case V4L2_PIX_FMT_MPEG1:
-		mode_flag = FLAG_MODE_MPEG1;
-		break;
-	case V4L2_PIX_FMT_MPEG2:
-		mode_flag = FLAG_MODE_MPEG2;
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-		mode_flag = FLAG_MODE_MPEG4;
-		break;
-	default:
-		return -1;
-	}
-	if (reject_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) {
-		dev_err(go->dev,
-			"unable to load firmware from file \"%s\"\n",
-			GO7007_FW_NAME);
-		return -1;
-	}
-	code = kzalloc(codespace * 2, GFP_KERNEL);
-	if (code == NULL)
-		goto fw_failed;
-
-	src = (__le16 *)fw_entry->data;
-	srclen = fw_entry->size / 2;
-	while (srclen >= 2) {
-		chunk_flags = __le16_to_cpu(src[0]);
-		chunk_len = __le16_to_cpu(src[1]);
-		if (chunk_len + 2 > srclen) {
-			dev_err(go->dev,
-				"firmware file \"%s\" appears to be corrupted\n",
-				GO7007_FW_NAME);
-			goto fw_failed;
-		}
-		if (chunk_flags & mode_flag) {
-			if (chunk_flags & FLAG_SPECIAL) {
-				ret = do_special(go, __le16_to_cpu(src[2]),
-					&code[i], codespace - i, framelen);
-				if (ret < 0) {
-					dev_err(go->dev,
-						"insufficient memory for firmware construction\n");
-					goto fw_failed;
-				}
-				i += ret;
-			} else {
-				if (codespace - i < chunk_len) {
-					dev_err(go->dev,
-						"insufficient memory for firmware construction\n");
-					goto fw_failed;
-				}
-				memcpy(&code[i], &src[2], chunk_len * 2);
-				i += chunk_len;
-			}
-		}
-		srclen -= chunk_len + 2;
-		src += chunk_len + 2;
-	}
-	release_firmware(fw_entry);
-	*fw = (u8 *)code;
-	*fwlen = i * 2;
-	return 0;
-
-fw_failed:
-	kfree(code);
-	release_firmware(fw_entry);
-	return -1;
-}
-
-/*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007.h linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007.h
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and the associated README documentation 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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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.
- */
-
-struct go7007_md_params {
-	__u16 region;
-	__u16 trigger;
-	__u16 pixel_threshold;
-	__u16 motion_threshold;
-	__u32 reserved[8];
-};
-
-struct go7007_md_region {
-	__u16 region;
-	__u16 flags;
-	struct v4l2_clip *clips;
-	__u32 reserved[8];
-};
-
-#define	GO7007IOC_S_MD_PARAMS	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, \
-					struct go7007_md_params)
-#define	GO7007IOC_G_MD_PARAMS	_IOR('V', BASE_VIDIOC_PRIVATE + 7, \
-					struct go7007_md_params)
-#define	GO7007IOC_S_MD_REGION	_IOW('V', BASE_VIDIOC_PRIVATE + 8, \
-					struct go7007_md_region)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-i2c.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-i2c.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-i2c.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/unistd.h>
-#include <linux/time.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-
-#include "go7007-priv.h"
-
-/********************* Driver for on-board I2C adapter *********************/
-
-/* #define GO7007_I2C_DEBUG */
-
-#define SPI_I2C_ADDR_BASE		0x1400
-#define STATUS_REG_ADDR			(SPI_I2C_ADDR_BASE + 0x2)
-#define I2C_CTRL_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x6)
-#define I2C_DEV_UP_ADDR_REG_ADDR	(SPI_I2C_ADDR_BASE + 0x7)
-#define I2C_LO_ADDR_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x8)
-#define I2C_DATA_REG_ADDR		(SPI_I2C_ADDR_BASE + 0x9)
-#define I2C_CLKFREQ_REG_ADDR		(SPI_I2C_ADDR_BASE + 0xa)
-
-#define I2C_STATE_MASK			0x0007
-#define I2C_READ_READY_MASK		0x0008
-
-/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs
- * on the Adlink PCI-MPG24, so access is shared between all of them. */
-static DEFINE_MUTEX(adlink_mpg24_i2c_lock);
-
-static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
-		u16 command, int flags, u8 *data)
-{
-	int i, ret = -EIO;
-	u16 val;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -ENODEV;
-
-#ifdef GO7007_I2C_DEBUG
-	if (read)
-		dev_dbg(go->dev, "go7007-i2c: reading 0x%02x on 0x%02x\n",
-			command, addr);
-	else
-		dev_dbg(go->dev,
-			"go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n",
-			*data, command, addr);
-#endif
-
-	mutex_lock(&go->hw_lock);
-
-	if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
-		/* Bridge the I2C port on this GO7007 to the shared bus */
-		mutex_lock(&adlink_mpg24_i2c_lock);
-		go7007_write_addr(go, 0x3c82, 0x0020);
-	}
-
-	/* Wait for I2C adapter to be ready */
-	for (i = 0; i < 10; ++i) {
-		if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
-			goto i2c_done;
-		if (!(val & I2C_STATE_MASK))
-			break;
-		msleep(100);
-	}
-	if (i == 10) {
-		dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
-		goto i2c_done;
-	}
-
-	/* Set target register (command) */
-	go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags);
-	go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command);
-
-	/* If we're writing, send the data and target address and we're done */
-	if (!read) {
-		go7007_write_addr(go, I2C_DATA_REG_ADDR, *data);
-		go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
-					(addr << 9) | (command >> 8));
-		ret = 0;
-		goto i2c_done;
-	}
-
-	/* Otherwise, we're reading.  First clear i2c_rx_data_rdy. */
-	if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
-		goto i2c_done;
-
-	/* Send the target address plus read flag */
-	go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
-			(addr << 9) | 0x0100 | (command >> 8));
-
-	/* Wait for i2c_rx_data_rdy */
-	for (i = 0; i < 10; ++i) {
-		if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
-			goto i2c_done;
-		if (val & I2C_READ_READY_MASK)
-			break;
-		msleep(100);
-	}
-	if (i == 10) {
-		dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n");
-		goto i2c_done;
-	}
-
-	/* Retrieve the read byte */
-	if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
-		goto i2c_done;
-	*data = val;
-	ret = 0;
-
-i2c_done:
-	if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
-		/* Isolate the I2C port on this GO7007 from the shared bus */
-		go7007_write_addr(go, 0x3c82, 0x0000);
-		mutex_unlock(&adlink_mpg24_i2c_lock);
-	}
-	mutex_unlock(&go->hw_lock);
-	return ret;
-}
-
-static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
-		unsigned short flags, char read_write,
-		u8 command, int size, union i2c_smbus_data *data)
-{
-	struct go7007 *go = i2c_get_adapdata(adapter);
-
-	if (size != I2C_SMBUS_BYTE_DATA)
-		return -EIO;
-	return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command,
-			flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte);
-}
-
-/* VERY LIMITED I2C master xfer function -- only needed because the
- * SMBus functions only support 8-bit commands and the SAA7135 uses
- * 16-bit commands.  The I2C interface on the GO7007, as limited as
- * it is, does support this mode. */
-
-static int go7007_i2c_master_xfer(struct i2c_adapter *adapter,
-					struct i2c_msg msgs[], int num)
-{
-	struct go7007 *go = i2c_get_adapdata(adapter);
-	int i;
-
-	for (i = 0; i < num; ++i) {
-		/* We can only do two things here -- write three bytes, or
-		 * write two bytes and read one byte. */
-		if (msgs[i].len == 2) {
-			if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr ||
-					(msgs[i].flags & I2C_M_RD) ||
-					!(msgs[i + 1].flags & I2C_M_RD) ||
-					msgs[i + 1].len != 1)
-				return -EIO;
-			if (go7007_i2c_xfer(go, msgs[i].addr, 1,
-					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
-					0x01, &msgs[i + 1].buf[0]) < 0)
-				return -EIO;
-			++i;
-		} else if (msgs[i].len == 3) {
-			if (msgs[i].flags & I2C_M_RD)
-				return -EIO;
-			if (msgs[i].len != 3)
-				return -EIO;
-			if (go7007_i2c_xfer(go, msgs[i].addr, 0,
-					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
-					0x01, &msgs[i].buf[2]) < 0)
-				return -EIO;
-		} else
-			return -EIO;
-	}
-
-	return num;
-}
-
-static u32 go7007_functionality(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_SMBUS_BYTE_DATA;
-}
-
-static struct i2c_algorithm go7007_algo = {
-	.smbus_xfer	= go7007_smbus_xfer,
-	.master_xfer	= go7007_i2c_master_xfer,
-	.functionality	= go7007_functionality,
-};
-
-static struct i2c_adapter go7007_adap_templ = {
-	.owner			= THIS_MODULE,
-	.name			= "WIS GO7007SB",
-	.algo			= &go7007_algo,
-};
-
-int go7007_i2c_init(struct go7007 *go)
-{
-	memcpy(&go->i2c_adapter, &go7007_adap_templ,
-			sizeof(go7007_adap_templ));
-	go->i2c_adapter.dev.parent = go->dev;
-	i2c_set_adapdata(&go->i2c_adapter, go);
-	if (i2c_add_adapter(&go->i2c_adapter) < 0) {
-		dev_err(go->dev,
-			"go7007-i2c: error: i2c_add_adapter failed\n");
-		return -1;
-	}
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-loader.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-loader.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-loader.c	2014-08-07 04:50:43.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-loader.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2008 Sensoray Company Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/firmware.h>
-#include <cypress_firmware.h>
-
-struct fw_config {
-	u16 vendor;
-	u16 product;
-	const char * const fw_name1;
-	const char * const fw_name2;
-};
-
-static struct fw_config fw_configs[] = {
-	{ 0x1943, 0xa250, "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/" },
-	{ 0x093b, 0xa002, "/*(DEBLOBBED)*/", NULL },
-	{ 0x093b, 0xa004, "/*(DEBLOBBED)*/", NULL },
-	{ 0x0eb1, 0x6666, "/*(DEBLOBBED)*/", NULL },
-	{ 0x0eb1, 0x6668, "/*(DEBLOBBED)*/", NULL },
-	{ 0, 0, NULL, NULL }
-};
-/*(DEBLOBBED)*/
-
-static int go7007_loader_probe(struct usb_interface *interface,
-				const struct usb_device_id *id)
-{
-	struct usb_device *usbdev;
-	const struct firmware *fw;
-	u16 vendor, product;
-	const char *fw1, *fw2;
-	int ret;
-	int i;
-
-	usbdev = usb_get_dev(interface_to_usbdev(interface));
-	if (!usbdev)
-		goto failed2;
-
-	if (usbdev->descriptor.bNumConfigurations != 1) {
-		dev_err(&interface->dev, "can't handle multiple config\n");
-		goto failed2;
-	}
-
-	vendor = le16_to_cpu(usbdev->descriptor.idVendor);
-	product = le16_to_cpu(usbdev->descriptor.idProduct);
-
-	for (i = 0; fw_configs[i].fw_name1; i++)
-		if (fw_configs[i].vendor == vendor &&
-		    fw_configs[i].product == product)
-			break;
-
-	/* Should never happen */
-	if (fw_configs[i].fw_name1 == NULL)
-		goto failed2;
-
-	fw1 = fw_configs[i].fw_name1;
-	fw2 = fw_configs[i].fw_name2;
-
-	dev_info(&interface->dev, "loading firmware %s\n", fw1);
-
-	if (reject_firmware(&fw, fw1, &usbdev->dev)) {
-		dev_err(&interface->dev,
-			"unable to load firmware from file \"%s\"\n", fw1);
-		goto failed2;
-	}
-	ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
-	release_firmware(fw);
-	if (0 != ret) {
-		dev_err(&interface->dev, "loader download failed\n");
-		goto failed2;
-	}
-
-	if (fw2 == NULL)
-		return 0;
-
-	if (reject_firmware(&fw, fw2, &usbdev->dev)) {
-		dev_err(&interface->dev,
-			"unable to load firmware from file \"%s\"\n", fw2);
-		goto failed2;
-	}
-	ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
-	release_firmware(fw);
-	if (0 != ret) {
-		dev_err(&interface->dev, "firmware download failed\n");
-		goto failed2;
-	}
-	return 0;
-
-failed2:
-	usb_put_dev(usbdev);
-	dev_err(&interface->dev, "probe failed\n");
-	return -ENODEV;
-}
-
-static void go7007_loader_disconnect(struct usb_interface *interface)
-{
-	dev_info(&interface->dev, "disconnect\n");
-	usb_put_dev(interface_to_usbdev(interface));
-	usb_set_intfdata(interface, NULL);
-}
-
-static const struct usb_device_id go7007_loader_ids[] = {
-	{ USB_DEVICE(0x1943, 0xa250) },
-	{ USB_DEVICE(0x093b, 0xa002) },
-	{ USB_DEVICE(0x093b, 0xa004) },
-	{ USB_DEVICE(0x0eb1, 0x6666) },
-	{ USB_DEVICE(0x0eb1, 0x6668) },
-	{}                          /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, go7007_loader_ids);
-
-static struct usb_driver go7007_loader_driver = {
-	.name		= "go7007-loader",
-	.probe		= go7007_loader_probe,
-	.disconnect	= go7007_loader_disconnect,
-	.id_table	= go7007_loader_ids,
-};
-
-module_usb_driver(go7007_loader_driver);
-
-MODULE_AUTHOR("");
-MODULE_DESCRIPTION("firmware loader for go7007-usb");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-priv.h linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-priv.h
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-priv.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-priv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-/*
- * This is the private include file for the go7007 driver.  It should not
- * be included by anybody but the driver itself, and especially not by
- * user-space applications.
- */
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
-
-struct go7007;
-
-/* IDs to activate board-specific support code */
-#define GO7007_BOARDID_MATRIX_II	0
-#define GO7007_BOARDID_MATRIX_RELOAD	1
-#define GO7007_BOARDID_STAR_TREK	2
-#define GO7007_BOARDID_PCI_VOYAGER	3
-#define GO7007_BOARDID_XMEN		4
-#define GO7007_BOARDID_XMEN_II		5
-#define GO7007_BOARDID_XMEN_III		6
-#define GO7007_BOARDID_MATRIX_REV	7
-#define GO7007_BOARDID_PX_M402U		8
-#define GO7007_BOARDID_PX_TV402U	9
-#define GO7007_BOARDID_LIFEVIEW_LR192	10 /* TV Walker Ultra */
-#define GO7007_BOARDID_ENDURA		11
-#define GO7007_BOARDID_ADLINK_MPG24	12
-#define GO7007_BOARDID_SENSORAY_2250	13 /* Sensoray 2250/2251 */
-#define GO7007_BOARDID_ADS_USBAV_709    14
-
-/* Various characteristics of each board */
-#define GO7007_BOARD_HAS_AUDIO		(1<<0)
-#define GO7007_BOARD_USE_ONBOARD_I2C	(1<<1)
-#define GO7007_BOARD_HAS_TUNER		(1<<2)
-
-/* Characteristics of sensor devices */
-#define GO7007_SENSOR_VALID_POLAR	(1<<0)
-#define GO7007_SENSOR_HREF_POLAR	(1<<1)
-#define GO7007_SENSOR_VREF_POLAR	(1<<2)
-#define GO7007_SENSOR_FIELD_ID_POLAR	(1<<3)
-#define GO7007_SENSOR_BIT_WIDTH		(1<<4)
-#define GO7007_SENSOR_VALID_ENABLE	(1<<5)
-#define GO7007_SENSOR_656		(1<<6)
-#define GO7007_SENSOR_CONFIG_MASK	0x7f
-#define GO7007_SENSOR_TV		(1<<7)
-#define GO7007_SENSOR_VBI		(1<<8)
-#define GO7007_SENSOR_SCALING		(1<<9)
-#define GO7007_SENSOR_SAA7115		(1<<10)
-
-/* Characteristics of audio sensor devices */
-#define GO7007_AUDIO_I2S_MODE_1		(1)
-#define GO7007_AUDIO_I2S_MODE_2		(2)
-#define GO7007_AUDIO_I2S_MODE_3		(3)
-#define GO7007_AUDIO_BCLK_POLAR		(1<<2)
-#define GO7007_AUDIO_WORD_14		(14<<4)
-#define GO7007_AUDIO_WORD_16		(16<<4)
-#define GO7007_AUDIO_ONE_CHANNEL	(1<<11)
-#define GO7007_AUDIO_I2S_MASTER		(1<<16)
-#define GO7007_AUDIO_OKI_MODE		(1<<17)
-
-struct go7007_board_info {
-	unsigned int flags;
-	int hpi_buffer_cap;
-	unsigned int sensor_flags;
-	int sensor_width;
-	int sensor_height;
-	int sensor_framerate;
-	int sensor_h_offset;
-	int sensor_v_offset;
-	unsigned int audio_flags;
-	int audio_rate;
-	int audio_bclk_div;
-	int audio_main_div;
-	int num_i2c_devs;
-	struct go_i2c {
-		const char *type;
-		unsigned int is_video:1;
-		unsigned int is_audio:1;
-		int addr;
-		u32 flags;
-	} i2c_devs[5];
-	int num_inputs;
-	struct {
-		int video_input;
-		int audio_index;
-		char *name;
-	} inputs[4];
-	int video_config;
-	int num_aud_inputs;
-	struct {
-		int audio_input;
-		char *name;
-	} aud_inputs[3];
-};
-
-struct go7007_hpi_ops {
-	int (*interface_reset)(struct go7007 *go);
-	int (*write_interrupt)(struct go7007 *go, int addr, int data);
-	int (*read_interrupt)(struct go7007 *go);
-	int (*stream_start)(struct go7007 *go);
-	int (*stream_stop)(struct go7007 *go);
-	int (*send_firmware)(struct go7007 *go, u8 *data, int len);
-	int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg);
-	void (*release)(struct go7007 *go);
-};
-
-/* The video buffer size must be a multiple of PAGE_SIZE */
-#define	GO7007_BUF_PAGES	(128 * 1024 / PAGE_SIZE)
-#define	GO7007_BUF_SIZE		(GO7007_BUF_PAGES << PAGE_SHIFT)
-
-struct go7007_buffer {
-	struct vb2_buffer vb;
-	struct list_head list;
-	unsigned int frame_offset;
-	u32 modet_active;
-};
-
-#define GO7007_RATIO_1_1	0
-#define GO7007_RATIO_4_3	1
-#define GO7007_RATIO_16_9	2
-
-enum go7007_parser_state {
-	STATE_DATA,
-	STATE_00,
-	STATE_00_00,
-	STATE_00_00_01,
-	STATE_FF,
-	STATE_VBI_LEN_A,
-	STATE_VBI_LEN_B,
-	STATE_MODET_MAP,
-	STATE_UNPARSED,
-};
-
-struct go7007 {
-	struct device *dev;
-	u8 bus_info[32];
-	const struct go7007_board_info *board_info;
-	unsigned int board_id;
-	int tuner_type;
-	int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */
-	char name[64];
-	struct video_device vdev;
-	void *boot_fw;
-	unsigned boot_fw_len;
-	struct v4l2_device v4l2_dev;
-	struct v4l2_ctrl_handler hdl;
-	struct v4l2_ctrl *mpeg_video_encoding;
-	struct v4l2_ctrl *mpeg_video_gop_size;
-	struct v4l2_ctrl *mpeg_video_gop_closure;
-	struct v4l2_ctrl *mpeg_video_bitrate;
-	struct v4l2_ctrl *mpeg_video_aspect_ratio;
-	struct v4l2_ctrl *mpeg_video_b_frames;
-	struct v4l2_ctrl *mpeg_video_rep_seqheader;
-	enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
-	spinlock_t spinlock;
-	struct mutex hw_lock;
-	struct mutex serialize_lock;
-	int audio_enabled;
-	struct v4l2_subdev *sd_video;
-	struct v4l2_subdev *sd_audio;
-	u8 usb_buf[16];
-
-	/* Video input */
-	int input;
-	int aud_input;
-	enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard;
-	v4l2_std_id std;
-	int sensor_framerate;
-	int width;
-	int height;
-	int encoder_h_offset;
-	int encoder_v_offset;
-	unsigned int encoder_h_halve:1;
-	unsigned int encoder_v_halve:1;
-	unsigned int encoder_subsample:1;
-
-	/* Encoder config */
-	u32 format;
-	int bitrate;
-	int fps_scale;
-	int pali;
-	int aspect_ratio;
-	int gop_size;
-	unsigned int ipb:1;
-	unsigned int closed_gop:1;
-	unsigned int repeat_seqhead:1;
-	unsigned int seq_header_enable:1;
-	unsigned int gop_header_enable:1;
-	unsigned int dvd_mode:1;
-	unsigned int interlace_coding:1;
-
-	/* Motion detection */
-	unsigned int modet_enable:1;
-	struct {
-		unsigned int enable:1;
-		int pixel_threshold;
-		int motion_threshold;
-		int mb_threshold;
-	} modet[4];
-	unsigned char modet_map[1624];
-	unsigned char active_map[216];
-
-	/* Video streaming */
-	struct mutex queue_lock;
-	struct vb2_queue vidq;
-	enum go7007_parser_state state;
-	int parse_length;
-	u16 modet_word;
-	int seen_frame;
-	u32 next_seq;
-	struct list_head vidq_active;
-	wait_queue_head_t frame_waitq;
-	struct go7007_buffer *active_buf;
-
-	/* Audio streaming */
-	void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
-	void *snd_context;
-
-	/* I2C */
-	int i2c_adapter_online;
-	struct i2c_adapter i2c_adapter;
-
-	/* HPI driver */
-	struct go7007_hpi_ops *hpi_ops;
-	void *hpi_context;
-	int interrupt_available;
-	wait_queue_head_t interrupt_waitq;
-	unsigned short interrupt_value;
-	unsigned short interrupt_data;
-};
-
-static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev)
-{
-	return container_of(v4l2_dev, struct go7007, v4l2_dev);
-}
-
-/* All of these must be called with the hpi_lock mutex held! */
-#define go7007_interface_reset(go) \
-			((go)->hpi_ops->interface_reset(go))
-#define	go7007_write_interrupt(go, x, y) \
-			((go)->hpi_ops->write_interrupt)((go), (x), (y))
-#define go7007_stream_start(go) \
-			((go)->hpi_ops->stream_start(go))
-#define go7007_stream_stop(go) \
-			((go)->hpi_ops->stream_stop(go))
-#define	go7007_send_firmware(go, x, y) \
-			((go)->hpi_ops->send_firmware)((go), (x), (y))
-#define go7007_write_addr(go, x, y) \
-			((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y))
-
-/* go7007-driver.c */
-int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data);
-int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data);
-int go7007_boot_encoder(struct go7007 *go, int init_i2c);
-int go7007_reset_encoder(struct go7007 *go);
-int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs);
-int go7007_start_encoder(struct go7007 *go);
-void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length);
-struct go7007 *go7007_alloc(const struct go7007_board_info *board,
-					struct device *dev);
-void go7007_update_board(struct go7007 *go);
-
-/* go7007-fw.c */
-int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen);
-
-/* go7007-i2c.c */
-int go7007_i2c_init(struct go7007 *go);
-int go7007_i2c_remove(struct go7007 *go);
-
-/* go7007-v4l2.c */
-int go7007_v4l2_init(struct go7007 *go);
-int go7007_v4l2_ctrl_init(struct go7007 *go);
-void go7007_v4l2_remove(struct go7007 *go);
-
-/* snd-go7007.c */
-int go7007_snd_init(struct go7007 *go);
-int go7007_snd_remove(struct go7007 *go);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007.txt linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007.txt
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,478 +0,0 @@
-This is a driver for the WIS GO7007SB multi-format video encoder.
-
-Pete Eberlein <pete@sensoray.com>
-
-The driver was originally released under the GPL and is currently hosted at:
-http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver
-The go7007 firmware can be acquired from the package on the site above.
-
-I've modified the driver to support the following Video4Linux2 MPEG
-controls, with acceptable values:
-
-V4L2_CID_MPEG_STREAM_TYPE	V4L2_MPEG_STREAM_TYPE_MPEG2_DVD
-				V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
-V4L2_CID_MPEG_VIDEO_ENCODING	V4L2_MPEG_VIDEO_ENCODING_MPEG_1
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_2
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_4
-V4L2_CID_MPEG_VIDEO_ASPECT	V4L2_MPEG_VIDEO_ASPECT_1x1
-				V4L2_MPEG_VIDEO_ASPECT_4x3
-				V4L2_MPEG_VIDEO_ASPECT_16x9
-V4L2_CID_MPEG_VIDEO_GOP_SIZE	integer
-V4L2_CID_MPEG_VIDEO_BITRATE	64000 .. 10000000
-
-These should be used instead of the non-standard GO7007 ioctls described
-below.
-
-
-The README files from the orignal package appear below:
-
----------------------------------------------------------------------------
-		     WIS GO7007SB Public Linux Driver
----------------------------------------------------------------------------
-
-
-*** Please see the file RELEASE-NOTES for important last-minute updates ***
-
-
-  0. OVERVIEW AND LICENSING/DISCLAIMER
-
-
-This driver kit contains Linux drivers for the WIS GO7007SB multi-format
-video encoder.  Only kernel version 2.6.x is supported.  The video stream
-is available through the Video4Linux2 API and the audio stream is available
-through the ALSA API (or the OSS emulation layer of the ALSA system).
-
-The files in kernel/ and hotplug/ are licensed under the GNU General Public
-License Version 2 from the Free Software Foundation.  A copy of the license
-is included in the file COPYING.
-
-The example applications in apps/ and C header files in include/ are
-licensed under a permissive license included in the source files which
-allows copying, modification and redistribution for any purpose without
-attribution.
-
-The firmware files included in the firmware/ directory may be freely
-redistributed only in conjunction with this document; but modification,
-tampering and reverse engineering are prohibited.
-
-MICRONAS USA, INC., MAKES NO WARRANTIES TO ANY PERSON OR ENTITY WITH
-RESPECT TO THE SOFTWARE OR ANY DERIVATIVES THEREOF OR ANY SERVICES OR
-LICENSES AND DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION
-WARRANTIES OF MERCHANTABILITY, SUPPORT, AND FITNESS FOR A PARTICULAR
-PURPOSE AND NON-INFRINGEMENT.
-
-
-  1. SYSTEM REQUIREMENTS
-
-
-This driver requires Linux kernel 2.6.  Kernel 2.4 is not supported.  Using
-kernel 2.6.10 or later is recommended, as earlier kernels are known to have
-unstable USB 2.0 support.
-
-A fully built kernel source tree must be available.  Typically this will be
-linked from "/lib/modules/<KERNEL VERSION>/build" for convenience.  If this
-link does not exist, an extra parameter will need to be passed to the
-`make` command.
-
-All vendor-built kernels should already be configured properly.  However,
-for custom-built kernels, the following options need to be enabled in the
-kernel as built-in or modules:
-
-	CONFIG_MODULES           - Enable loadable module support
-	CONFIG_FW_LOADER         - Hotplug firmware loading support
-	CONFIG_I2C               - I2C support
-	CONFIG_VIDEO_DEV         - Video For Linux
-	CONFIG_SOUND             - Sound card support
-	CONFIG_SND               - Advanced Linux Sound Architecture
-	CONFIG_USB               - Support for Host-side USB
-	CONFIG_USB_EHCI_HCD      - EHCI HCD (USB 2.0) support
-
-Additionally, to use the example application, the following options need to
-be enabled in the ALSA section:
-
-	CONFIG_SND_MIXER_OSS     - OSS Mixer API
-	CONFIG_SND_PCM_OSS       - OSS PCM (digital audio) API
-
-The hotplug scripts, along with the fxload utility, must also be installed.
-These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>.
-Hotplugging is used for loading firmware into the Cypruss EZ-USB chip using
-fxload and for loading firmware into the driver using the firmware agent.
-
-
-  2. COMPILING AND INSTALLING THE DRIVER
-
-
-Most users should be able to compile the driver by simply running:
-
-	$ make
-
-in the top-level directory of the driver kit.  First the kernel modules
-will be built, followed by the example applications.
-
-If the build system is unable to locate the kernel source tree for the
-currently-running kernel, or if the module should be built for a kernel
-other than the currently-running kernel, an additional parameter will need
-to be passed to make to specify the appropriate kernel source directory:
-
-	$ make KERNELSRC=/usr/src/linux-2.6.10-custom3
-
-Once the compile completes, the driver and firmware files should be
-installed by running:
-
-	$ make install
-
-The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra"
-and the firmware files will be placed in the appropriate hotplug firmware
-directory, usually /lib/firmware.  In addition, USB maps and scripts will
-be placed in /etc/hotplug/usb to enable fxload to initialize the EZ-USB
-control chip when the device is connected.
-
-
-  3. PAL/SECAM TUNER CONFIGURATION (TV402U-EU only)
-
-
-The PAL model of the Plextor ConvertX TV402U may require additional
-configuration to correctly select the appropriate TV frequency band and
-audio subchannel.
-
-Users with a device other than the Plextor ConvertX TV402U-EU should skip
-this section.
-
-The wide variety of PAL TV systems used in Europe requires that additional
-information about the local TV standards be passed to the driver in order
-to properly tune TV channels.  The two necessary parameters are (a) the PAL
-TV band, and (b) the audio subchannel format in use.
-
-In many cases, the appropriate TV band selection is passed to the driver
-from applications.  However, in some cases, the application only specifies
-that the driver should use PAL but not the specific information about the
-appropriate TV band.  To work around this issue, the correct TV band may be
-specified in the "force_band" parameter to the wis-sony-tuner module:
-
-     TV band           force_band
-     -------           ----------
-     PAL B/G                B
-     PAL I                  I
-     PAL D/K                D
-     SECAM L                L
-
-If the "force_band" parameter is specified, the driver will ignore any TV
-band specified by applications and will always use the band provided in the
-module parameter.
-
-The other parameter that can be specified is the audio subchannel format.
-There are several stereo audio carrier systems in use, including NICAM and
-three varieties of A2.  To receive audio broadcast on one of these stereo
-carriers, the "force_mpx_mode" parameter must be specified to the
-wis-sony-tuner module.
-
-     TV band           Audio subcarrier       force_mpx_mode
-     -------           ----------------       --------------
-     PAL B/G            Mono (default)               1
-     PAL B/G                  A2                     2
-     PAL B/G                 NICAM                   3
-     PAL I              Mono (default)               4
-     PAL I                   NICAM                   5
-     PAL D/K            Mono (default)               6
-     PAL D/K                 A2 (1)                  7
-     PAL D/K                 A2 (2)                  8
-     PAL D/K                 A2 (3)                  9
-     PAL D/K                 NICAM                  10
-     SECAM L            Mono (default)              11
-     SECAM L                 NICAM                  12
-
-If the "force_mpx_mode" parameter is not specified, the correct mono-only
-mode will be chosen based on the TV band.  However, the tuner will not
-receive stereo audio or bilingual broadcasts correctly.
-
-To pass the "force_band" or "force_mpx_mode" parameters to the
-wis-sony-tuner module, the following line must be added to the modprobe
-configuration file, which varies from one Linux distribution to another.
-
-     options wis-sony-tuner force_band=B force_mpx_mode=2
-
-The above example would force the tuner to the PAL B/G TV band and receive
-stereo audio broadcasts on the A2 carrier.
-
-To verify that the configuration has been placed in the correct location,
-execute:
-
-	$ modprobe -c | grep wis-sony-tuner
-
-If the configuration line appears, then modprobe will pass the parameters
-correctly the next time the wis-sony-tuner module is loaded into the
-kernel.
-
-
-  4. TESTING THE DRIVER
-
-
-Because few Linux applications are able to correctly capture from
-Video4Linux2 devices with only compressed formats supported, the new driver
-should be tested with the "gorecord" application in the apps/ directory.
-
-First connect a video source to the device, such as a DVD player or VCR.
-This will be captured to a file for testing the driver.  If an input source
-is unavailable, a test file can still be captured, but the video will be
-black and the audio will be silent.
-
-This application will auto-detect the V4L2 and ALSA/OSS device names of the
-hardware and will record video and audio to an AVI file for a specified
-number of seconds.  For example:
-
-	$ apps/gorecord -duration 60 capture.avi
-
-If this application does not successfully record an AVI file, the error
-messages produced by gorecord and recorded in the system log (usually in
-/var/log/messages) should provide information to help resolve the problem.
-
-Supplying no parameters to gorecord will cause it to probe the available
-devices and exit.  Use the -help flag for usage information.
-
-
-  5. USING THE DRIVER
-
-
-The V4L2 device implemented by the driver provides a standard compressed
-format API, within the following criteria:
-
-  * Applications that only support the original Video4Linux1 API will not
-    be able to communicate with this driver at all.
-
-  * No raw video modes are supported, so applications like xawtv that
-    expect only uncompressed video will not function.
-
-  * Supported compression formats are: Motion-JPEG, MPEG1, MPEG2 and MPEG4.
-
-  * MPEG video formats are delivered as Video Elementary Streams only.
-    Program Stream (PS), Transport Stream (TS) and Packetized Elementary
-    Stream (PES) formats are not supported.
-
-  * Video parameters such as format and input port may not be changed while
-    the encoder is active.
-
-  * The audio capture device only functions when the video encoder is
-    actively capturing video.  Attempts to read from the audio device when
-    the encoder is inactive will result in an I/O error.
-
-  * The native format of the audio device is 48Khz 2-channel 16-bit
-    little-endian PCM, delivered through the ALSA system.  No audio
-    compression is implemented in the hardware.  ALSA may convert to other
-    uncompressed formats on the fly.
-
-The include/ directory contains a C header file describing non-standard
-features of the GO7007SB encoder, which are described below:
-
-
-  GO7007IOC_S_COMP_PARAMS, GO7007IOC_G_COMP_PARAMS
-
-    These ioctls are used to negotiate general compression parameters.
-
-    To query the current parameters, call the GO7007IOC_G_COMP_PARAMS ioctl
-    with a pointer to a struct go7007_comp_params.  If the driver is not
-    set to MPEG format, the EINVAL error code will be returned.
-
-    To change the current parameters, initialize all fields of a struct
-    go7007_comp_params and call the GO7007_IOC_S_COMP_PARAMS ioctl with a
-    pointer to this structure.  The driver will return the current
-    parameters with any necessary changes to conform to the limitations of
-    the hardware or current compression mode.  Any or all fields can be set
-    to zero to request a reasonable default value.  If the driver is not
-    set to MPEG format, the EINVAL error code will be returned.  When I/O
-    is in progress, the EBUSY error code will be returned.
-
-    Fields in struct go7007_comp_params:
-
-	__u32                        The maximum number of frames in each
-	  gop_size                   Group Of Pictures; i.e. the maximum
-				     number of frames minus one between
-				     each key frame.
-
-	__u32                        The maximum number of sequential
-	  max_b_frames               bidirectionally-predicted frames.
-				     (B-frames are not yet supported.)
-
-	enum go7007_aspect_ratio     The aspect ratio to be encoded in the
-	  aspect_ratio               meta-data of the compressed format.
-
-				     Choices are:
-					GO7007_ASPECT_RATIO_1_1
-					GO7007_ASPECT_RATIO_4_3_NTSC
-					GO7007_ASPECT_RATIO_4_3_PAL
-					GO7007_ASPECT_RATIO_16_9_NTSC
-					GO7007_ASPECT_RATIO_16_9_PAL
-
-	__u32                        Bit-wise OR of control flags (below)
-	  flags
-
-    Flags in struct go7007_comp_params:
-
-	GO7007_COMP_CLOSED_GOP       Only produce self-contained GOPs, used
-				     to produce streams appropriate for
-				     random seeking.
-
-	GO7007_COMP_OMIT_SEQ_HEADER  Omit the stream sequence header.
-
-
-  GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS
-
-    These ioctls are used to negotiate MPEG-specific stream parameters when
-    the pixelformat has been set to V4L2_PIX_FMT_MPEG.
-
-    To query the current parameters, call the GO7007IOC_G_MPEG_PARAMS ioctl
-    with a pointer to a struct go7007_mpeg_params.  If the driver is not
-    set to MPEG format, the EINVAL error code will be returned.
-
-    To change the current parameters, initialize all fields of a struct
-    go7007_mpeg_params and call the GO7007_IOC_S_MPEG_PARAMS ioctl with a
-    pointer to this structure.  The driver will return the current
-    parameters with any necessary changes to conform to the limitations of
-    the hardware or selected MPEG mode.  Any or all fields can be set to
-    zero to request a reasonable default value.  If the driver is not set
-    to MPEG format, the EINVAL error code will be returned.  When I/O is in
-    progress, the EBUSY error code will be returned.
-
-    Fields in struct go7007_mpeg_params:
-
-	enum go7007_mpeg_video_standard
-	  mpeg_video_standard        The MPEG video standard in which to
-				     compress the video.
-
-				     Choices are:
-					GO7007_MPEG_VIDEO_MPEG1
-					GO7007_MPEG_VIDEO_MPEG2
-					GO7007_MPEG_VIDEO_MPEG4
-
-	__u32                        Bit-wise OR of control flags (below)
-	  flags
-
-	__u32                        The profile and level indication to be
-	  pali                       stored in the sequence header.  This
-				     is only used as an indicator to the
-				     decoder, and does not affect the MPEG
-				     features used in the video stream.
-				     Not valid for MPEG1.
-
-				     Choices for MPEG2 are:
-					GO7007_MPEG2_PROFILE_MAIN_MAIN
-
-				     Choices for MPEG4 are:
-					GO7007_MPEG4_PROFILE_S_L0
-					GO7007_MPEG4_PROFILE_S_L1
-					GO7007_MPEG4_PROFILE_S_L2
-					GO7007_MPEG4_PROFILE_S_L3
-					GO7007_MPEG4_PROFILE_ARTS_L1
-					GO7007_MPEG4_PROFILE_ARTS_L2
-					GO7007_MPEG4_PROFILE_ARTS_L3
-					GO7007_MPEG4_PROFILE_ARTS_L4
-					GO7007_MPEG4_PROFILE_AS_L0
-					GO7007_MPEG4_PROFILE_AS_L1
-					GO7007_MPEG4_PROFILE_AS_L2
-					GO7007_MPEG4_PROFILE_AS_L3
-					GO7007_MPEG4_PROFILE_AS_L4
-					GO7007_MPEG4_PROFILE_AS_L5
-
-    Flags in struct go7007_mpeg_params:
-
-	GO7007_MPEG_FORCE_DVD_MODE   Force all compression parameters and
-				     bitrate control settings to comply
-				     with DVD MPEG2 stream requirements.
-				     This overrides most compression and
-				     bitrate settings!
-
-	GO7007_MPEG_OMIT_GOP_HEADER  Omit the GOP header.
-
-	GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at
-				     the start of each GOP.
-
-
-  GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE
-
-    These ioctls are used to set and query the target bitrate value for the
-    compressed video stream.  The bitrate may be selected by storing the
-    target bits per second in an int and calling GO7007IOC_S_BITRATE with a
-    pointer to the int.  The bitrate may be queried by calling
-    GO7007IOC_G_BITRATE with a pointer to an int where the current bitrate
-    will be stored.
-
-    Note that this is the primary means of controlling the video quality
-    for all compression modes, including V4L2_PIX_FMT_MJPEG.  The
-    VIDIOC_S_JPEGCOMP ioctl is not supported.
-
-
-----------------------------------------------------------------------------
-		   Installing the WIS PCI Voyager Driver
----------------------------------------------------------------------------
-
-The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x
-kernel source tree before compiling the driver.  These patches update the
-in-kernel SAA7134 driver to the newest development version and patch bugs
-in the TDA8290/TDA8275 tuner driver.
-
-The following patches must be downloaded from Gerd Knorr's website and
-applied in the order listed:
-
-	http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner
-	http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner2
-	http://dl.bytesex.org/patches/2.6.11-2/v4l2-api-mpeg
-	http://dl.bytesex.org/patches/2.6.11-2/saa7134-update
-
-The following patches are included with this SDK and can be applied in any
-order:
-
-	patches/2.6.11/saa7134-voyager.diff
-	patches/2.6.11/tda8275-newaddr.diff
-	patches/2.6.11/tda8290-ntsc.diff
-
-Check to make sure the CONFIG_VIDEO_SAA7134 option is enabled in the kernel
-configuration, and build and install the kernel.
-
-After rebooting into the new kernel, the GO7007 driver can be compiled and
-installed:
-
-	$ make SAA7134_BUILD=y
-	$ make install
-	$ modprobe saa7134-go7007
-
-There will be two V4L video devices associated with the PCI Voyager.  The
-first device (most likely /dev/video0) provides access to the raw video
-capture mode of the SAA7133 device and is used to configure the source
-video parameters and tune the TV tuner.  This device can be used with xawtv
-or other V4L(2) video software as a standard uncompressed device.
-
-The second device (most likely /dev/video1) provides access to the
-compression functions of the GO7007.  It can be tested using the gorecord
-application in the apps/ directory of this SDK:
-
-	$ apps/gorecord -vdevice /dev/video1 -noaudio test.avi
-
-Currently the frame resolution is fixed at 720x480 (NTSC) or 720x576 (PAL),
-and the video standard must be specified to both the raw and the compressed
-video devices (xawtv and gorecord, for example).
-
-
---------------------------------------------------------------------------
-RELEASE NOTES FOR WIS GO7007SB LINUX DRIVER
----------------------------------------------------------------------------
-
-Last updated: 5 November 2005
-
- - Release 0.9.7 includes new support for using udev to run fxload.  The
-   install script should automatically detect whether the old hotplug
-   scripts or the new udev rules should be used.  To force the use of
-   hotplug, run "make install USE_UDEV=n".  To force the use of udev, run
-   "make install USE_UDEV=y".
-
- - Motion detection is supported but undocumented.  Try the `modet` app
-   for a demonstration of how to use the facility.
-
- - Using USB2.0 devices such as the TV402U with USB1.1 HCDs or hubs can
-   cause buffer overruns and frame drops, even at low framerates, due to
-   inconsistency in the bitrate control mechanism.
-
- - On devices with an SAA7115, including the Plextor ConvertX, video height
-   values of 96, 128, 160, 192, 256, 320, and 384 do not work in NTSC mode.
-   All valid heights up to 512 work correctly in PAL mode.
-
- - The WIS Star Trek and PCI Voyager boards have no support yet for audio
-   or the TV tuner.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-usb.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-usb.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-usb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-usb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1349 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <asm/byteorder.h>
-#include <media/saa7115.h>
-#include <media/tuner.h>
-#include <media/uda1342.h>
-
-#include "go7007-priv.h"
-
-static unsigned int assume_endura;
-module_param(assume_endura, int, 0644);
-MODULE_PARM_DESC(assume_endura,
-			"when probing fails, hardware is a Pelco Endura");
-
-/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
-
-#define	HPI_STATUS_ADDR	0xFFF4
-#define	INT_PARAM_ADDR	0xFFF6
-#define	INT_INDEX_ADDR	0xFFF8
-
-/*
- * Pipes on EZ-USB interface:
- *	0 snd - Control
- *	0 rcv - Control
- *	2 snd - Download firmware (control)
- *	4 rcv - Read Interrupt (interrupt)
- *	6 rcv - Read Video (bulk)
- *	8 rcv - Read Audio (bulk)
- */
-
-#define GO7007_USB_EZUSB		(1<<0)
-#define GO7007_USB_EZUSB_I2C		(1<<1)
-
-struct go7007_usb_board {
-	unsigned int flags;
-	struct go7007_board_info main_info;
-};
-
-struct go7007_usb {
-	const struct go7007_usb_board *board;
-	struct mutex i2c_lock;
-	struct usb_device *usbdev;
-	struct urb *video_urbs[8];
-	struct urb *audio_urbs[8];
-	struct urb *intr_urb;
-};
-
-/*********************** Product specification data ***********************/
-
-static const struct go7007_usb_board board_matrix_ii = {
-	.flags		= GO7007_USB_EZUSB,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_VALID_ENABLE |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_SAA7115 |
-					GO7007_SENSOR_VBI |
-					GO7007_SENSOR_SCALING,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "saa7115",
-				.addr	= 0x20,
-				.is_video = 1,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-			{
-				.video_input	= 0,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 9,
-				.name		= "S-Video",
-			},
-		},
-		.video_config	= SAA7115_IDQ_IS_DEFAULT,
-	},
-};
-
-static const struct go7007_usb_board board_matrix_reload = {
-	.flags		= GO7007_USB_EZUSB,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "saa7113",
-				.addr	= 0x25,
-				.is_video = 1,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-			{
-				.video_input	= 0,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 9,
-				.name		= "S-Video",
-			},
-		},
-		.video_config	= SAA7115_IDQ_IS_DEFAULT,
-	},
-};
-
-static const struct go7007_usb_board board_star_trek = {
-	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO, /* |
-					GO7007_BOARD_HAS_TUNER, */
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_VALID_ENABLE |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_SAA7115 |
-					GO7007_SENSOR_VBI |
-					GO7007_SENSOR_SCALING,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_WORD_16,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "saa7115",
-				.addr	= 0x20,
-				.is_video = 1,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-		/*	{
-		 *		.video_input	= 3,
-		 *		.audio_index	= AUDIO_TUNER,
-		 *		.name		= "Tuner",
-		 *	},
-		 */
-			{
-				.video_input	= 1,
-			/*	.audio_index	= AUDIO_EXTERN, */
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 8,
-			/*	.audio_index	= AUDIO_EXTERN, */
-				.name		= "S-Video",
-			},
-		},
-		.video_config	= SAA7115_IDQ_IS_DEFAULT,
-	},
-};
-
-static const struct go7007_usb_board board_px_tv402u = {
-	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_HAS_TUNER,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_VALID_ENABLE |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_SAA7115 |
-					GO7007_SENSOR_VBI |
-					GO7007_SENSOR_SCALING,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_WORD_16,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.num_i2c_devs	 = 5,
-		.i2c_devs	 = {
-			{
-				.type	= "saa7115",
-				.addr	= 0x20,
-				.is_video = 1,
-			},
-			{
-				.type	= "uda1342",
-				.addr	= 0x1a,
-				.is_audio = 1,
-			},
-			{
-				.type	= "tuner",
-				.addr	= 0x60,
-			},
-			{
-				.type	= "tuner",
-				.addr	= 0x43,
-			},
-			{
-				.type	= "sony-btf-mpx",
-				.addr	= 0x44,
-			},
-		},
-		.num_inputs	 = 3,
-		.inputs		 = {
-			{
-				.video_input	= 3,
-				.audio_index	= 0,
-				.name		= "Tuner",
-			},
-			{
-				.video_input	= 1,
-				.audio_index	= 1,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 8,
-				.audio_index	= 1,
-				.name		= "S-Video",
-			},
-		},
-		.video_config	= SAA7115_IDQ_IS_DEFAULT,
-		.num_aud_inputs	 = 2,
-		.aud_inputs	 = {
-			{
-				.audio_input	= UDA1342_IN2,
-				.name		= "Tuner",
-			},
-			{
-				.audio_input	= UDA1342_IN1,
-				.name		= "Line In",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_xmen = {
-	.flags		= 0,
-	.main_info	= {
-		.flags		  = GO7007_BOARD_USE_ONBOARD_I2C,
-		.hpi_buffer_cap   = 0,
-		.sensor_flags	  = GO7007_SENSOR_VREF_POLAR,
-		.sensor_width	  = 320,
-		.sensor_height	  = 240,
-		.sensor_framerate = 30030,
-		.audio_flags	  = GO7007_AUDIO_ONE_CHANNEL |
-					GO7007_AUDIO_I2S_MODE_3 |
-					GO7007_AUDIO_WORD_14 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_BCLK_POLAR |
-					GO7007_AUDIO_OKI_MODE,
-		.audio_rate	  = 8000,
-		.audio_bclk_div	  = 48,
-		.audio_main_div	  = 1,
-		.num_i2c_devs	  = 1,
-		.i2c_devs	  = {
-			{
-				.type	= "ov7640",
-				.addr	= 0x21,
-			},
-		},
-		.num_inputs	  = 1,
-		.inputs		  = {
-			{
-				.name		= "Camera",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_matrix_revolution = {
-	.flags		= GO7007_USB_EZUSB,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_VBI,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "tw9903",
-				.is_video = 1,
-				.addr	= 0x44,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-			{
-				.video_input	= 2,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 8,
-				.name		= "S-Video",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_lifeview_lr192 = {
-	.flags		= GO7007_USB_EZUSB,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_VALID_ENABLE |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_VBI |
-					GO7007_SENSOR_SCALING,
-		.num_i2c_devs	 = 0,
-		.num_inputs	 = 1,
-		.inputs		 = {
-			{
-				.video_input	= 0,
-				.name		= "Composite",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_endura = {
-	.flags		= 0,
-	.main_info	= {
-		.flags		 = 0,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 8000,
-		.audio_bclk_div	 = 48,
-		.audio_main_div	 = 8,
-		.hpi_buffer_cap  = 0,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV,
-		.sensor_h_offset = 8,
-		.num_i2c_devs	 = 0,
-		.num_inputs	 = 1,
-		.inputs		 = {
-			{
-				.name		= "Camera",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_adlink_mpg24 = {
-	.flags		= 0,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 0,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_VBI,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "tw2804",
-				.addr	= 0x00, /* yes, really */
-				.flags  = I2C_CLIENT_TEN,
-				.is_video = 1,
-			},
-		},
-		.num_inputs	 = 1,
-		.inputs		 = {
-			{
-				.name		= "Composite",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_sensoray_2250 = {
-	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
-	.main_info	= {
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.flags		 = GO7007_BOARD_HAS_AUDIO,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "s2250",
-				.addr	= 0x43,
-				.is_video = 1,
-				.is_audio = 1,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-			{
-				.video_input	= 0,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 1,
-				.name		= "S-Video",
-			},
-		},
-		.num_aud_inputs	 = 3,
-		.aud_inputs	 = {
-			{
-				.audio_input	= 0,
-				.name		= "Line In",
-			},
-			{
-				.audio_input	= 1,
-				.name		= "Mic",
-			},
-			{
-				.audio_input	= 2,
-				.name		= "Mic Boost",
-			},
-		},
-	},
-};
-
-static const struct go7007_usb_board board_ads_usbav_709 = {
-	.flags		= GO7007_USB_EZUSB,
-	.main_info	= {
-		.flags		 = GO7007_BOARD_HAS_AUDIO |
-					GO7007_BOARD_USE_ONBOARD_I2C,
-		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
-					GO7007_AUDIO_I2S_MASTER |
-					GO7007_AUDIO_WORD_16,
-		.audio_rate	 = 48000,
-		.audio_bclk_div	 = 8,
-		.audio_main_div	 = 2,
-		.hpi_buffer_cap  = 7,
-		.sensor_flags	 = GO7007_SENSOR_656 |
-					GO7007_SENSOR_TV |
-					GO7007_SENSOR_VBI,
-		.num_i2c_devs	 = 1,
-		.i2c_devs	 = {
-			{
-				.type	= "tw9906",
-				.is_video = 1,
-				.addr	= 0x44,
-			},
-		},
-		.num_inputs	 = 2,
-		.inputs		 = {
-			{
-				.video_input	= 0,
-				.name		= "Composite",
-			},
-			{
-				.video_input	= 10,
-				.name		= "S-Video",
-			},
-		},
-	},
-};
-
-static const struct usb_device_id go7007_usb_id_table[] = {
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
-					USB_DEVICE_ID_MATCH_INT_INFO,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x200,   /* Revision number of XMen */
-		.bcdDevice_hi	= 0x200,
-		.bInterfaceClass	= 255,
-		.bInterfaceSubClass	= 0,
-		.bInterfaceProtocol	= 255,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x202,   /* Revision number of Matrix II */
-		.bcdDevice_hi	= 0x202,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x204,   /* Revision number of Matrix */
-		.bcdDevice_hi	= 0x204,   /*     Reloaded */
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
-					USB_DEVICE_ID_MATCH_INT_INFO,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x205,   /* Revision number of XMen-II */
-		.bcdDevice_hi	= 0x205,
-		.bInterfaceClass	= 255,
-		.bInterfaceSubClass	= 0,
-		.bInterfaceProtocol	= 255,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_II,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x208,   /* Revision number of Star Trek */
-		.bcdDevice_hi	= 0x208,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_STAR_TREK,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
-					USB_DEVICE_ID_MATCH_INT_INFO,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x209,   /* Revision number of XMen-III */
-		.bcdDevice_hi	= 0x209,
-		.bInterfaceClass	= 255,
-		.bInterfaceSubClass	= 0,
-		.bInterfaceProtocol	= 255,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_III,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
-		.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
-		.bcdDevice_lo	= 0x210,   /* Revision number of Matrix */
-		.bcdDevice_hi	= 0x210,   /*     Revolution */
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x093b,  /* Vendor ID of Plextor */
-		.idProduct	= 0xa102,  /* Product ID of M402U */
-		.bcdDevice_lo	= 0x1,	   /* revision number of Blueberry */
-		.bcdDevice_hi	= 0x1,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_M402U,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x093b,  /* Vendor ID of Plextor */
-		.idProduct	= 0xa104,  /* Product ID of TV402U */
-		.bcdDevice_lo	= 0x1,
-		.bcdDevice_hi	= 0x1,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x10fd,  /* Vendor ID of Anubis Electronics */
-		.idProduct	= 0xde00,  /* Product ID of Lifeview LR192 */
-		.bcdDevice_lo	= 0x1,
-		.bcdDevice_hi	= 0x1,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x1943,  /* Vendor ID Sensoray */
-		.idProduct	= 0x2250,  /* Product ID of 2250/2251 */
-		.bcdDevice_lo	= 0x1,
-		.bcdDevice_hi	= 0x1,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
-	},
-	{
-		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
-		.idVendor	= 0x06e1,  /* Vendor ID of ADS Technologies */
-		.idProduct	= 0x0709,  /* Product ID of DVD Xpress DX2 */
-		.bcdDevice_lo	= 0x204,
-		.bcdDevice_hi	= 0x204,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709,
-	},
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, go7007_usb_id_table);
-
-/********************* Driver for EZ-USB HPI interface *********************/
-
-static int go7007_usb_vendor_request(struct go7007 *go, int request,
-		int value, int index, void *transfer_buffer, int length, int in)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int timeout = 5000;
-
-	if (in) {
-		return usb_control_msg(usb->usbdev,
-				usb_rcvctrlpipe(usb->usbdev, 0), request,
-				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-				value, index, transfer_buffer, length, timeout);
-	} else {
-		return usb_control_msg(usb->usbdev,
-				usb_sndctrlpipe(usb->usbdev, 0), request,
-				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				value, index, transfer_buffer, length, timeout);
-	}
-}
-
-static int go7007_usb_interface_reset(struct go7007 *go)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	u16 intr_val, intr_data;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -1;
-	/* Reset encoder */
-	if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
-		return -1;
-	msleep(100);
-
-	if (usb->board->flags & GO7007_USB_EZUSB) {
-		/* Reset buffer in EZ-USB */
-		pr_debug("resetting EZ-USB buffers\n");
-		if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
-		    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
-			return -1;
-
-		/* Reset encoder again */
-		if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
-			return -1;
-		msleep(100);
-	}
-
-	/* Wait for an interrupt to indicate successful hardware reset */
-	if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
-			(intr_val & ~0x1) != 0x55aa) {
-		dev_err(go->dev, "unable to reset the USB interface\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
-						int addr, int data)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int i, r;
-	u16 status_reg = 0;
-	int timeout = 500;
-
-	pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
-
-	for (i = 0; i < 100; ++i) {
-		r = usb_control_msg(usb->usbdev,
-				usb_rcvctrlpipe(usb->usbdev, 0), 0x14,
-				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-				0, HPI_STATUS_ADDR, go->usb_buf,
-				sizeof(status_reg), timeout);
-		if (r < 0)
-			break;
-		status_reg = le16_to_cpu(*((u16 *)go->usb_buf));
-		if (!(status_reg & 0x0010))
-			break;
-		msleep(10);
-	}
-	if (r < 0)
-		goto write_int_error;
-	if (i == 100) {
-		dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg);
-		return -1;
-	}
-	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE, data,
-			INT_PARAM_ADDR, NULL, 0, timeout);
-	if (r < 0)
-		goto write_int_error;
-	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0),
-			0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr,
-			INT_INDEX_ADDR, NULL, 0, timeout);
-	if (r < 0)
-		goto write_int_error;
-	return 0;
-
-write_int_error:
-	dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
-	return r;
-}
-
-static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
-						int addr, int data)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int r;
-	int timeout = 500;
-
-	pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
-
-	go->usb_buf[0] = data & 0xff;
-	go->usb_buf[1] = data >> 8;
-	go->usb_buf[2] = addr & 0xff;
-	go->usb_buf[3] = addr >> 8;
-	go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0;
-	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00,
-			USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
-			0xf0f0, go->usb_buf, 8, timeout);
-	if (r < 0) {
-		dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
-		return r;
-	}
-	return 0;
-}
-
-static void go7007_usb_readinterrupt_complete(struct urb *urb)
-{
-	struct go7007 *go = (struct go7007 *)urb->context;
-	u16 *regs = (u16 *)urb->transfer_buffer;
-	int status = urb->status;
-
-	if (status) {
-		if (status != -ESHUTDOWN &&
-				go->status != STATUS_SHUTDOWN) {
-			dev_err(go->dev, "error in read interrupt: %d\n", urb->status);
-		} else {
-			wake_up(&go->interrupt_waitq);
-			return;
-		}
-	} else if (urb->actual_length != urb->transfer_buffer_length) {
-		dev_err(go->dev, "short read in interrupt pipe!\n");
-	} else {
-		go->interrupt_available = 1;
-		go->interrupt_data = __le16_to_cpu(regs[0]);
-		go->interrupt_value = __le16_to_cpu(regs[1]);
-		pr_debug("ReadInterrupt: %04x %04x\n",
-				go->interrupt_value, go->interrupt_data);
-	}
-
-	wake_up(&go->interrupt_waitq);
-}
-
-static int go7007_usb_read_interrupt(struct go7007 *go)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int r;
-
-	r = usb_submit_urb(usb->intr_urb, GFP_KERNEL);
-	if (r < 0) {
-		dev_err(go->dev, "unable to submit interrupt urb: %d\n", r);
-		return r;
-	}
-	return 0;
-}
-
-static void go7007_usb_read_video_pipe_complete(struct urb *urb)
-{
-	struct go7007 *go = (struct go7007 *)urb->context;
-	int r, status = urb->status;
-
-	if (!vb2_is_streaming(&go->vidq)) {
-		wake_up_interruptible(&go->frame_waitq);
-		return;
-	}
-	if (status) {
-		dev_err(go->dev, "error in video pipe: %d\n", status);
-		return;
-	}
-	if (urb->actual_length != urb->transfer_buffer_length) {
-		dev_err(go->dev, "short read in video pipe!\n");
-		return;
-	}
-	go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length);
-	r = usb_submit_urb(urb, GFP_ATOMIC);
-	if (r < 0)
-		dev_err(go->dev, "error in video pipe: %d\n", r);
-}
-
-static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
-{
-	struct go7007 *go = (struct go7007 *)urb->context;
-	int r, status = urb->status;
-
-	if (!vb2_is_streaming(&go->vidq))
-		return;
-	if (status) {
-		dev_err(go->dev, "error in audio pipe: %d\n",
-			status);
-		return;
-	}
-	if (urb->actual_length != urb->transfer_buffer_length) {
-		dev_err(go->dev, "short read in audio pipe!\n");
-		return;
-	}
-	if (go->audio_deliver != NULL)
-		go->audio_deliver(go, urb->transfer_buffer, urb->actual_length);
-	r = usb_submit_urb(urb, GFP_ATOMIC);
-	if (r < 0)
-		dev_err(go->dev, "error in audio pipe: %d\n", r);
-}
-
-static int go7007_usb_stream_start(struct go7007 *go)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int i, r;
-
-	for (i = 0; i < 8; ++i) {
-		r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL);
-		if (r < 0) {
-			dev_err(go->dev, "error submitting video urb %d: %d\n", i, r);
-			goto video_submit_failed;
-		}
-	}
-	if (!go->audio_enabled)
-		return 0;
-
-	for (i = 0; i < 8; ++i) {
-		r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL);
-		if (r < 0) {
-			dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r);
-			goto audio_submit_failed;
-		}
-	}
-	return 0;
-
-audio_submit_failed:
-	for (i = 0; i < 7; ++i)
-		usb_kill_urb(usb->audio_urbs[i]);
-video_submit_failed:
-	for (i = 0; i < 8; ++i)
-		usb_kill_urb(usb->video_urbs[i]);
-	return -1;
-}
-
-static int go7007_usb_stream_stop(struct go7007 *go)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int i;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return 0;
-	for (i = 0; i < 8; ++i)
-		usb_kill_urb(usb->video_urbs[i]);
-	if (go->audio_enabled)
-		for (i = 0; i < 8; ++i)
-			usb_kill_urb(usb->audio_urbs[i]);
-	return 0;
-}
-
-static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int transferred, pipe;
-	int timeout = 500;
-
-	pr_debug("DownloadBuffer sending %d bytes\n", len);
-
-	if (usb->board->flags & GO7007_USB_EZUSB)
-		pipe = usb_sndbulkpipe(usb->usbdev, 2);
-	else
-		pipe = usb_sndbulkpipe(usb->usbdev, 3);
-
-	return usb_bulk_msg(usb->usbdev, pipe, data, len,
-					&transferred, timeout);
-}
-
-static void go7007_usb_release(struct go7007 *go)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	struct urb *vurb, *aurb;
-	int i;
-
-	if (usb->intr_urb) {
-		usb_kill_urb(usb->intr_urb);
-		kfree(usb->intr_urb->transfer_buffer);
-		usb_free_urb(usb->intr_urb);
-	}
-
-	/* Free USB-related structs */
-	for (i = 0; i < 8; ++i) {
-		vurb = usb->video_urbs[i];
-		if (vurb) {
-			usb_kill_urb(vurb);
-			kfree(vurb->transfer_buffer);
-			usb_free_urb(vurb);
-		}
-		aurb = usb->audio_urbs[i];
-		if (aurb) {
-			usb_kill_urb(aurb);
-			kfree(aurb->transfer_buffer);
-			usb_free_urb(aurb);
-		}
-	}
-
-	kfree(go->hpi_context);
-}
-
-static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
-	.interface_reset	= go7007_usb_interface_reset,
-	.write_interrupt	= go7007_usb_ezusb_write_interrupt,
-	.read_interrupt		= go7007_usb_read_interrupt,
-	.stream_start		= go7007_usb_stream_start,
-	.stream_stop		= go7007_usb_stream_stop,
-	.send_firmware		= go7007_usb_send_firmware,
-	.release		= go7007_usb_release,
-};
-
-static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
-	.interface_reset	= go7007_usb_interface_reset,
-	.write_interrupt	= go7007_usb_onboard_write_interrupt,
-	.read_interrupt		= go7007_usb_read_interrupt,
-	.stream_start		= go7007_usb_stream_start,
-	.stream_stop		= go7007_usb_stream_stop,
-	.send_firmware		= go7007_usb_send_firmware,
-	.release		= go7007_usb_release,
-};
-
-/********************* Driver for EZ-USB I2C adapter *********************/
-
-static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
-					struct i2c_msg msgs[], int num)
-{
-	struct go7007 *go = i2c_get_adapdata(adapter);
-	struct go7007_usb *usb = go->hpi_context;
-	u8 *buf = go->usb_buf;
-	int buf_len, i;
-	int ret = -EIO;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -ENODEV;
-
-	mutex_lock(&usb->i2c_lock);
-
-	for (i = 0; i < num; ++i) {
-		/* The hardware command is "write some bytes then read some
-		 * bytes", so we try to coalesce a write followed by a read
-		 * into a single USB transaction */
-		if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr &&
-				!(msgs[i].flags & I2C_M_RD) &&
-				(msgs[i + 1].flags & I2C_M_RD)) {
-#ifdef GO7007_I2C_DEBUG
-			pr_debug("i2c write/read %d/%d bytes on %02x\n",
-				msgs[i].len, msgs[i + 1].len, msgs[i].addr);
-#endif
-			buf[0] = 0x01;
-			buf[1] = msgs[i].len + 1;
-			buf[2] = msgs[i].addr << 1;
-			memcpy(&buf[3], msgs[i].buf, msgs[i].len);
-			buf_len = msgs[i].len + 3;
-			buf[buf_len++] = msgs[++i].len;
-		} else if (msgs[i].flags & I2C_M_RD) {
-#ifdef GO7007_I2C_DEBUG
-			pr_debug("i2c read %d bytes on %02x\n",
-					msgs[i].len, msgs[i].addr);
-#endif
-			buf[0] = 0x01;
-			buf[1] = 1;
-			buf[2] = msgs[i].addr << 1;
-			buf[3] = msgs[i].len;
-			buf_len = 4;
-		} else {
-#ifdef GO7007_I2C_DEBUG
-			pr_debug("i2c write %d bytes on %02x\n",
-					msgs[i].len, msgs[i].addr);
-#endif
-			buf[0] = 0x00;
-			buf[1] = msgs[i].len + 1;
-			buf[2] = msgs[i].addr << 1;
-			memcpy(&buf[3], msgs[i].buf, msgs[i].len);
-			buf_len = msgs[i].len + 3;
-			buf[buf_len++] = 0;
-		}
-		if (go7007_usb_vendor_request(go, 0x24, 0, 0,
-						buf, buf_len, 0) < 0)
-			goto i2c_done;
-		if (msgs[i].flags & I2C_M_RD) {
-			memset(buf, 0, msgs[i].len + 1);
-			if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
-						msgs[i].len + 1, 1) < 0)
-				goto i2c_done;
-			memcpy(msgs[i].buf, buf + 1, msgs[i].len);
-		}
-	}
-	ret = num;
-
-i2c_done:
-	mutex_unlock(&usb->i2c_lock);
-	return ret;
-}
-
-static u32 go7007_usb_functionality(struct i2c_adapter *adapter)
-{
-	/* No errors are reported by the hardware, so we don't bother
-	 * supporting quick writes to avoid confusing probing */
-	return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK;
-}
-
-static struct i2c_algorithm go7007_usb_algo = {
-	.master_xfer	= go7007_usb_i2c_master_xfer,
-	.functionality	= go7007_usb_functionality,
-};
-
-static struct i2c_adapter go7007_usb_adap_templ = {
-	.owner			= THIS_MODULE,
-	.name			= "WIS GO7007SB EZ-USB",
-	.algo			= &go7007_usb_algo,
-};
-
-/********************* USB add/remove functions *********************/
-
-static int go7007_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct go7007 *go;
-	struct go7007_usb *usb;
-	const struct go7007_usb_board *board;
-	struct usb_device *usbdev = interface_to_usbdev(intf);
-	unsigned num_i2c_devs;
-	char *name;
-	int video_pipe, i, v_urb_len;
-
-	pr_debug("probing new GO7007 USB board\n");
-
-	switch (id->driver_info) {
-	case GO7007_BOARDID_MATRIX_II:
-		name = "WIS Matrix II or compatible";
-		board = &board_matrix_ii;
-		break;
-	case GO7007_BOARDID_MATRIX_RELOAD:
-		name = "WIS Matrix Reloaded or compatible";
-		board = &board_matrix_reload;
-		break;
-	case GO7007_BOARDID_MATRIX_REV:
-		name = "WIS Matrix Revolution or compatible";
-		board = &board_matrix_revolution;
-		break;
-	case GO7007_BOARDID_STAR_TREK:
-		name = "WIS Star Trek or compatible";
-		board = &board_star_trek;
-		break;
-	case GO7007_BOARDID_XMEN:
-		name = "WIS XMen or compatible";
-		board = &board_xmen;
-		break;
-	case GO7007_BOARDID_XMEN_II:
-		name = "WIS XMen II or compatible";
-		board = &board_xmen;
-		break;
-	case GO7007_BOARDID_XMEN_III:
-		name = "WIS XMen III or compatible";
-		board = &board_xmen;
-		break;
-	case GO7007_BOARDID_PX_M402U:
-		name = "Plextor PX-M402U";
-		board = &board_matrix_ii;
-		break;
-	case GO7007_BOARDID_PX_TV402U:
-		name = "Plextor PX-TV402U (unknown tuner)";
-		board = &board_px_tv402u;
-		break;
-	case GO7007_BOARDID_LIFEVIEW_LR192:
-		dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
-		return -ENODEV;
-		name = "Lifeview TV Walker Ultra";
-		board = &board_lifeview_lr192;
-		break;
-	case GO7007_BOARDID_SENSORAY_2250:
-		dev_info(&intf->dev, "Sensoray 2250 found\n");
-		name = "Sensoray 2250/2251";
-		board = &board_sensoray_2250;
-		break;
-	case GO7007_BOARDID_ADS_USBAV_709:
-		name = "ADS Tech DVD Xpress DX2";
-		board = &board_ads_usbav_709;
-		break;
-	default:
-		dev_err(&intf->dev, "unknown board ID %d!\n",
-				(unsigned int)id->driver_info);
-		return -ENODEV;
-	}
-
-	go = go7007_alloc(&board->main_info, &intf->dev);
-	if (go == NULL)
-		return -ENOMEM;
-
-	usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL);
-	if (usb == NULL) {
-		kfree(go);
-		return -ENOMEM;
-	}
-
-	usb->board = board;
-	usb->usbdev = usbdev;
-	usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info));
-	go->board_id = id->driver_info;
-	strncpy(go->name, name, sizeof(go->name));
-	if (board->flags & GO7007_USB_EZUSB)
-		go->hpi_ops = &go7007_usb_ezusb_hpi_ops;
-	else
-		go->hpi_ops = &go7007_usb_onboard_hpi_ops;
-	go->hpi_context = usb;
-
-	/* Allocate the URB and buffer for receiving incoming interrupts */
-	usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (usb->intr_urb == NULL)
-		goto allocfail;
-	usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
-	if (usb->intr_urb->transfer_buffer == NULL)
-		goto allocfail;
-
-	if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
-		usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
-			usb_rcvbulkpipe(usb->usbdev, 4),
-			usb->intr_urb->transfer_buffer, 2*sizeof(u16),
-			go7007_usb_readinterrupt_complete, go);
-	else
-		usb_fill_int_urb(usb->intr_urb, usb->usbdev,
-			usb_rcvintpipe(usb->usbdev, 4),
-			usb->intr_urb->transfer_buffer, 2*sizeof(u16),
-			go7007_usb_readinterrupt_complete, go, 8);
-	usb_set_intfdata(intf, &go->v4l2_dev);
-
-	/* Boot the GO7007 */
-	if (go7007_boot_encoder(go, go->board_info->flags &
-					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
-		goto allocfail;
-
-	/* Register the EZ-USB I2C adapter, if we're using it */
-	if (board->flags & GO7007_USB_EZUSB_I2C) {
-		memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
-				sizeof(go7007_usb_adap_templ));
-		mutex_init(&usb->i2c_lock);
-		go->i2c_adapter.dev.parent = go->dev;
-		i2c_set_adapdata(&go->i2c_adapter, go);
-		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
-			dev_err(go->dev, "error: i2c_add_adapter failed\n");
-			goto allocfail;
-		}
-		go->i2c_adapter_online = 1;
-	}
-
-	/* Pelco and Adlink reused the XMen and XMen-III vendor and product
-	 * IDs for their own incompatible designs.  We can detect XMen boards
-	 * by probing the sensor, but there is no way to probe the sensors on
-	 * the Pelco and Adlink designs so we default to the Adlink.  If it
-	 * is actually a Pelco, the user must set the assume_endura module
-	 * parameter. */
-	if ((go->board_id == GO7007_BOARDID_XMEN ||
-				go->board_id == GO7007_BOARDID_XMEN_III) &&
-			go->i2c_adapter_online) {
-		union i2c_smbus_data data;
-
-		/* Check to see if register 0x0A is 0x76 */
-		i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
-			I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
-		if (data.byte != 0x76) {
-			if (assume_endura) {
-				go->board_id = GO7007_BOARDID_ENDURA;
-				usb->board = board = &board_endura;
-				go->board_info = &board->main_info;
-				strncpy(go->name, "Pelco Endura",
-					sizeof(go->name));
-			} else {
-				u16 channel;
-
-				/* read channel number from GPIO[1:0] */
-				go7007_read_addr(go, 0x3c81, &channel);
-				channel &= 0x3;
-				go->board_id = GO7007_BOARDID_ADLINK_MPG24;
-				usb->board = board = &board_adlink_mpg24;
-				go->board_info = &board->main_info;
-				go->channel_number = channel;
-				snprintf(go->name, sizeof(go->name),
-					"Adlink PCI-MPG24, channel #%d",
-					channel);
-			}
-			go7007_update_board(go);
-		}
-	}
-
-	num_i2c_devs = go->board_info->num_i2c_devs;
-
-	/* Probe the tuner model on the TV402U */
-	if (go->board_id == GO7007_BOARDID_PX_TV402U) {
-		/* Board strapping indicates tuner model */
-		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
-					1) < 0) {
-			dev_err(go->dev, "GPIO read failed!\n");
-			goto allocfail;
-		}
-		switch (go->usb_buf[0] >> 6) {
-		case 1:
-			go->tuner_type = TUNER_SONY_BTF_PG472Z;
-			go->std = V4L2_STD_PAL;
-			strncpy(go->name, "Plextor PX-TV402U-EU",
-					sizeof(go->name));
-			break;
-		case 2:
-			go->tuner_type = TUNER_SONY_BTF_PK467Z;
-			go->std = V4L2_STD_NTSC_M_JP;
-			num_i2c_devs -= 2;
-			strncpy(go->name, "Plextor PX-TV402U-JP",
-					sizeof(go->name));
-			break;
-		case 3:
-			go->tuner_type = TUNER_SONY_BTF_PB463Z;
-			num_i2c_devs -= 2;
-			strncpy(go->name, "Plextor PX-TV402U-NA",
-					sizeof(go->name));
-			break;
-		default:
-			pr_debug("unable to detect tuner type!\n");
-			break;
-		}
-		/* Configure tuner mode selection inputs connected
-		 * to the EZ-USB GPIO output pins */
-		if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
-					NULL, 0, 0) < 0) {
-			dev_err(go->dev, "GPIO write failed!\n");
-			goto allocfail;
-		}
-	}
-
-	/* Print a nasty message if the user attempts to use a USB2.0 device in
-	 * a USB1.1 port.  There will be silent corruption of the stream. */
-	if ((board->flags & GO7007_USB_EZUSB) &&
-			usbdev->speed != USB_SPEED_HIGH)
-		dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
-
-	/* Allocate the URBs and buffers for receiving the video stream */
-	if (board->flags & GO7007_USB_EZUSB) {
-		v_urb_len = 1024;
-		video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
-	} else {
-		v_urb_len = 512;
-		video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
-	}
-	for (i = 0; i < 8; ++i) {
-		usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
-		if (usb->video_urbs[i] == NULL)
-			goto allocfail;
-		usb->video_urbs[i]->transfer_buffer =
-						kmalloc(v_urb_len, GFP_KERNEL);
-		if (usb->video_urbs[i]->transfer_buffer == NULL)
-			goto allocfail;
-		usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
-				usb->video_urbs[i]->transfer_buffer, v_urb_len,
-				go7007_usb_read_video_pipe_complete, go);
-	}
-
-	/* Allocate the URBs and buffers for receiving the audio stream */
-	if ((board->flags & GO7007_USB_EZUSB) &&
-	    (board->flags & GO7007_BOARD_HAS_AUDIO)) {
-		for (i = 0; i < 8; ++i) {
-			usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
-			if (usb->audio_urbs[i] == NULL)
-				goto allocfail;
-			usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
-								GFP_KERNEL);
-			if (usb->audio_urbs[i]->transfer_buffer == NULL)
-				goto allocfail;
-			usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
-				usb_rcvbulkpipe(usb->usbdev, 8),
-				usb->audio_urbs[i]->transfer_buffer, 4096,
-				go7007_usb_read_audio_pipe_complete, go);
-		}
-	}
-
-	/* Do any final GO7007 initialization, then register the
-	 * V4L2 and ALSA interfaces */
-	if (go7007_register_encoder(go, num_i2c_devs) < 0)
-		goto allocfail;
-
-	go->status = STATUS_ONLINE;
-	return 0;
-
-allocfail:
-	go7007_usb_release(go);
-	kfree(go);
-	return -ENOMEM;
-}
-
-static void go7007_usb_disconnect(struct usb_interface *intf)
-{
-	struct go7007 *go = to_go7007(usb_get_intfdata(intf));
-
-	mutex_lock(&go->queue_lock);
-	mutex_lock(&go->serialize_lock);
-
-	if (go->audio_enabled)
-		go7007_snd_remove(go);
-
-	go->status = STATUS_SHUTDOWN;
-	v4l2_device_disconnect(&go->v4l2_dev);
-	video_unregister_device(&go->vdev);
-	mutex_unlock(&go->serialize_lock);
-	mutex_unlock(&go->queue_lock);
-
-	v4l2_device_put(&go->v4l2_dev);
-}
-
-static struct usb_driver go7007_usb_driver = {
-	.name		= "go7007",
-	.probe		= go7007_usb_probe,
-	.disconnect	= go7007_usb_disconnect,
-	.id_table	= go7007_usb_id_table,
-};
-
-module_usb_driver(go7007_usb_driver);
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-v4l2.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-v4l2.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/go7007-v4l2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/go7007-v4l2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1055 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/unistd.h>
-#include <linux/time.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-subdev.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-#include <media/saa7115.h>
-
-#include "go7007.h"
-#include "go7007-priv.h"
-
-#define call_all(dev, o, f, args...) \
-	v4l2_device_call_until_err(dev, 0, o, f, ##args)
-
-static bool valid_pixelformat(u32 pixelformat)
-{
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_MJPEG:
-	case V4L2_PIX_FMT_MPEG1:
-	case V4L2_PIX_FMT_MPEG2:
-	case V4L2_PIX_FMT_MPEG4:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
-{
-	u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
-
-	switch (format) {
-	case V4L2_PIX_FMT_MJPEG:
-		return V4L2_BUF_FLAG_KEYFRAME;
-	case V4L2_PIX_FMT_MPEG4:
-		switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
-		case 0:
-			return V4L2_BUF_FLAG_KEYFRAME;
-		case 1:
-			return V4L2_BUF_FLAG_PFRAME;
-		case 2:
-			return V4L2_BUF_FLAG_BFRAME;
-		default:
-			return 0;
-		}
-	case V4L2_PIX_FMT_MPEG1:
-	case V4L2_PIX_FMT_MPEG2:
-		switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
-		case 1:
-			return V4L2_BUF_FLAG_KEYFRAME;
-		case 2:
-			return V4L2_BUF_FLAG_PFRAME;
-		case 3:
-			return V4L2_BUF_FLAG_BFRAME;
-		default:
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static void get_resolution(struct go7007 *go, int *width, int *height)
-{
-	switch (go->standard) {
-	case GO7007_STD_NTSC:
-		*width = 720;
-		*height = 480;
-		break;
-	case GO7007_STD_PAL:
-		*width = 720;
-		*height = 576;
-		break;
-	case GO7007_STD_OTHER:
-	default:
-		*width = go->board_info->sensor_width;
-		*height = go->board_info->sensor_height;
-		break;
-	}
-}
-
-static void set_formatting(struct go7007 *go)
-{
-	if (go->format == V4L2_PIX_FMT_MJPEG) {
-		go->pali = 0;
-		go->aspect_ratio = GO7007_RATIO_1_1;
-		go->gop_size = 0;
-		go->ipb = 0;
-		go->closed_gop = 0;
-		go->repeat_seqhead = 0;
-		go->seq_header_enable = 0;
-		go->gop_header_enable = 0;
-		go->dvd_mode = 0;
-		return;
-	}
-
-	switch (go->format) {
-	case V4L2_PIX_FMT_MPEG1:
-		go->pali = 0;
-		break;
-	default:
-	case V4L2_PIX_FMT_MPEG2:
-		go->pali = 0x48;
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-		/* For future reference: this is the list of MPEG4
-		 * profiles that are available, although they are
-		 * untested:
-		 *
-		 * Profile		pali
-		 * --------------	----
-		 * PROFILE_S_L0		0x08
-		 * PROFILE_S_L1		0x01
-		 * PROFILE_S_L2		0x02
-		 * PROFILE_S_L3		0x03
-		 * PROFILE_ARTS_L1	0x91
-		 * PROFILE_ARTS_L2	0x92
-		 * PROFILE_ARTS_L3	0x93
-		 * PROFILE_ARTS_L4	0x94
-		 * PROFILE_AS_L0	0xf0
-		 * PROFILE_AS_L1	0xf1
-		 * PROFILE_AS_L2	0xf2
-		 * PROFILE_AS_L3	0xf3
-		 * PROFILE_AS_L4	0xf4
-		 * PROFILE_AS_L5	0xf5
-		 */
-		go->pali = 0xf5;
-		break;
-	}
-	go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size);
-	go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure);
-	go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0;
-	go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate);
-	go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader);
-	go->gop_header_enable = 1;
-	go->dvd_mode = 0;
-	if (go->format == V4L2_PIX_FMT_MPEG2)
-		go->dvd_mode =
-			go->bitrate == 9800000 &&
-			go->gop_size == 15 &&
-			go->ipb == 0 &&
-			go->repeat_seqhead == 1 &&
-			go->closed_gop;
-
-	switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) {
-	default:
-	case V4L2_MPEG_VIDEO_ASPECT_1x1:
-		go->aspect_ratio = GO7007_RATIO_1_1;
-		break;
-	case V4L2_MPEG_VIDEO_ASPECT_4x3:
-		go->aspect_ratio = GO7007_RATIO_4_3;
-		break;
-	case V4L2_MPEG_VIDEO_ASPECT_16x9:
-		go->aspect_ratio = GO7007_RATIO_16_9;
-		break;
-	}
-}
-
-static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
-{
-	int sensor_height = 0, sensor_width = 0;
-	int width, height, i;
-
-	if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
-		return -EINVAL;
-
-	get_resolution(go, &sensor_width, &sensor_height);
-
-	if (fmt == NULL) {
-		width = sensor_width;
-		height = sensor_height;
-	} else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
-		if (fmt->fmt.pix.width > sensor_width)
-			width = sensor_width;
-		else if (fmt->fmt.pix.width < 144)
-			width = 144;
-		else
-			width = fmt->fmt.pix.width & ~0x0f;
-
-		if (fmt->fmt.pix.height > sensor_height)
-			height = sensor_height;
-		else if (fmt->fmt.pix.height < 96)
-			height = 96;
-		else
-			height = fmt->fmt.pix.height & ~0x0f;
-	} else {
-		width = fmt->fmt.pix.width;
-
-		if (width <= sensor_width / 4) {
-			width = sensor_width / 4;
-			height = sensor_height / 4;
-		} else if (width <= sensor_width / 2) {
-			width = sensor_width / 2;
-			height = sensor_height / 2;
-		} else {
-			width = sensor_width;
-			height = sensor_height;
-		}
-		width &= ~0xf;
-		height &= ~0xf;
-	}
-
-	if (fmt != NULL) {
-		u32 pixelformat = fmt->fmt.pix.pixelformat;
-
-		memset(fmt, 0, sizeof(*fmt));
-		fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		fmt->fmt.pix.width = width;
-		fmt->fmt.pix.height = height;
-		fmt->fmt.pix.pixelformat = pixelformat;
-		fmt->fmt.pix.field = V4L2_FIELD_NONE;
-		fmt->fmt.pix.bytesperline = 0;
-		fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
-		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	}
-
-	if (try)
-		return 0;
-
-	if (fmt)
-		go->format = fmt->fmt.pix.pixelformat;
-	go->width = width;
-	go->height = height;
-	go->encoder_h_offset = go->board_info->sensor_h_offset;
-	go->encoder_v_offset = go->board_info->sensor_v_offset;
-	for (i = 0; i < 4; ++i)
-		go->modet[i].enable = 0;
-	for (i = 0; i < 1624; ++i)
-		go->modet_map[i] = 0;
-
-	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
-		struct v4l2_mbus_framefmt mbus_fmt;
-
-		mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
-		mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
-		mbus_fmt.height = height;
-		go->encoder_h_halve = 0;
-		go->encoder_v_halve = 0;
-		go->encoder_subsample = 0;
-		call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt);
-	} else {
-		if (width <= sensor_width / 4) {
-			go->encoder_h_halve = 1;
-			go->encoder_v_halve = 1;
-			go->encoder_subsample = 1;
-		} else if (width <= sensor_width / 2) {
-			go->encoder_h_halve = 1;
-			go->encoder_v_halve = 1;
-			go->encoder_subsample = 0;
-		} else {
-			go->encoder_h_halve = 0;
-			go->encoder_v_halve = 0;
-			go->encoder_subsample = 0;
-		}
-	}
-	return 0;
-}
-
-#if 0
-static int clip_to_modet_map(struct go7007 *go, int region,
-		struct v4l2_clip *clip_list)
-{
-	struct v4l2_clip clip, *clip_ptr;
-	int x, y, mbnum;
-
-	/* Check if coordinates are OK and if any macroblocks are already
-	 * used by other regions (besides 0) */
-	clip_ptr = clip_list;
-	while (clip_ptr) {
-		if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
-			return -EFAULT;
-		if (clip.c.left < 0 || (clip.c.left & 0xF) ||
-				clip.c.width <= 0 || (clip.c.width & 0xF))
-			return -EINVAL;
-		if (clip.c.left + clip.c.width > go->width)
-			return -EINVAL;
-		if (clip.c.top < 0 || (clip.c.top & 0xF) ||
-				clip.c.height <= 0 || (clip.c.height & 0xF))
-			return -EINVAL;
-		if (clip.c.top + clip.c.height > go->height)
-			return -EINVAL;
-		for (y = 0; y < clip.c.height; y += 16)
-			for (x = 0; x < clip.c.width; x += 16) {
-				mbnum = (go->width >> 4) *
-						((clip.c.top + y) >> 4) +
-					((clip.c.left + x) >> 4);
-				if (go->modet_map[mbnum] != 0 &&
-						go->modet_map[mbnum] != region)
-					return -EBUSY;
-			}
-		clip_ptr = clip.next;
-	}
-
-	/* Clear old region macroblocks */
-	for (mbnum = 0; mbnum < 1624; ++mbnum)
-		if (go->modet_map[mbnum] == region)
-			go->modet_map[mbnum] = 0;
-
-	/* Claim macroblocks in this list */
-	clip_ptr = clip_list;
-	while (clip_ptr) {
-		if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
-			return -EFAULT;
-		for (y = 0; y < clip.c.height; y += 16)
-			for (x = 0; x < clip.c.width; x += 16) {
-				mbnum = (go->width >> 4) *
-						((clip.c.top + y) >> 4) +
-					((clip.c.left + x) >> 4);
-				go->modet_map[mbnum] = region;
-			}
-		clip_ptr = clip.next;
-	}
-	return 0;
-}
-#endif
-
-static int vidioc_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *cap)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	strlcpy(cap->driver, "go7007", sizeof(cap->driver));
-	strlcpy(cap->card, go->name, sizeof(cap->card));
-	strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
-
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
-
-	if (go->board_info->num_aud_inputs)
-		cap->device_caps |= V4L2_CAP_AUDIO;
-	if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
-		cap->device_caps |= V4L2_CAP_TUNER;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-					struct v4l2_fmtdesc *fmt)
-{
-	char *desc = NULL;
-
-	switch (fmt->index) {
-	case 0:
-		fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
-		desc = "Motion JPEG";
-		break;
-	case 1:
-		fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
-		desc = "MPEG-1 ES";
-		break;
-	case 2:
-		fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
-		desc = "MPEG-2 ES";
-		break;
-	case 3:
-		fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
-		desc = "MPEG-4 ES";
-		break;
-	default:
-		return -EINVAL;
-	}
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
-
-	strncpy(fmt->description, desc, sizeof(fmt->description));
-
-	return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *fmt)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fmt->fmt.pix.width = go->width;
-	fmt->fmt.pix.height = go->height;
-	fmt->fmt.pix.pixelformat = go->format;
-	fmt->fmt.pix.field = V4L2_FIELD_NONE;
-	fmt->fmt.pix.bytesperline = 0;
-	fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
-	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-	return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-			struct v4l2_format *fmt)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	return set_capture_size(go, fmt, 1);
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-			struct v4l2_format *fmt)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (vb2_is_busy(&go->vidq))
-		return -EBUSY;
-
-	return set_capture_size(go, fmt, 0);
-}
-
-static int go7007_queue_setup(struct vb2_queue *q,
-		const struct v4l2_format *fmt,
-		unsigned int *num_buffers, unsigned int *num_planes,
-		unsigned int sizes[], void *alloc_ctxs[])
-{
-	sizes[0] = GO7007_BUF_SIZE;
-	*num_planes = 1;
-
-	if (*num_buffers < 2)
-		*num_buffers = 2;
-
-	return 0;
-}
-
-static void go7007_buf_queue(struct vb2_buffer *vb)
-{
-	struct vb2_queue *vq = vb->vb2_queue;
-	struct go7007 *go = vb2_get_drv_priv(vq);
-	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
-	unsigned long flags;
-
-	spin_lock_irqsave(&go->spinlock, flags);
-	list_add_tail(&go7007_vb->list, &go->vidq_active);
-	spin_unlock_irqrestore(&go->spinlock, flags);
-}
-
-static int go7007_buf_prepare(struct vb2_buffer *vb)
-{
-	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
-
-	go7007_vb->modet_active = 0;
-	go7007_vb->frame_offset = 0;
-	vb->v4l2_planes[0].bytesused = 0;
-	return 0;
-}
-
-static void go7007_buf_finish(struct vb2_buffer *vb)
-{
-	struct vb2_queue *vq = vb->vb2_queue;
-	struct go7007 *go = vb2_get_drv_priv(vq);
-	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
-	u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
-	struct v4l2_buffer *buf = &vb->v4l2_buf;
-
-	buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
-			V4L2_BUF_FLAG_PFRAME);
-	buf->flags |= frame_type_flag;
-	buf->field = V4L2_FIELD_NONE;
-}
-
-static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct go7007 *go = vb2_get_drv_priv(q);
-	int ret;
-
-	set_formatting(go);
-	mutex_lock(&go->hw_lock);
-	go->next_seq = 0;
-	go->active_buf = NULL;
-	q->streaming = 1;
-	if (go7007_start_encoder(go) < 0)
-		ret = -EIO;
-	else
-		ret = 0;
-	mutex_unlock(&go->hw_lock);
-	if (ret) {
-		q->streaming = 0;
-		return ret;
-	}
-	call_all(&go->v4l2_dev, video, s_stream, 1);
-	v4l2_ctrl_grab(go->mpeg_video_gop_size, true);
-	v4l2_ctrl_grab(go->mpeg_video_gop_closure, true);
-	v4l2_ctrl_grab(go->mpeg_video_bitrate, true);
-	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true);
-	/* Turn on Capture LED */
-	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
-		go7007_write_addr(go, 0x3c82, 0x0005);
-	return ret;
-}
-
-static void go7007_stop_streaming(struct vb2_queue *q)
-{
-	struct go7007 *go = vb2_get_drv_priv(q);
-	unsigned long flags;
-
-	q->streaming = 0;
-	go7007_stream_stop(go);
-	mutex_lock(&go->hw_lock);
-	go7007_reset_encoder(go);
-	mutex_unlock(&go->hw_lock);
-	call_all(&go->v4l2_dev, video, s_stream, 0);
-
-	spin_lock_irqsave(&go->spinlock, flags);
-	INIT_LIST_HEAD(&go->vidq_active);
-	spin_unlock_irqrestore(&go->spinlock, flags);
-	v4l2_ctrl_grab(go->mpeg_video_gop_size, false);
-	v4l2_ctrl_grab(go->mpeg_video_gop_closure, false);
-	v4l2_ctrl_grab(go->mpeg_video_bitrate, false);
-	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false);
-	/* Turn on Capture LED */
-	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
-		go7007_write_addr(go, 0x3c82, 0x000d);
-}
-
-static struct vb2_ops go7007_video_qops = {
-	.queue_setup    = go7007_queue_setup,
-	.buf_queue      = go7007_buf_queue,
-	.buf_prepare    = go7007_buf_prepare,
-	.buf_finish     = go7007_buf_finish,
-	.start_streaming = go7007_start_streaming,
-	.stop_streaming = go7007_stop_streaming,
-	.wait_prepare   = vb2_ops_wait_prepare,
-	.wait_finish    = vb2_ops_wait_finish,
-};
-
-static int vidioc_g_parm(struct file *filp, void *priv,
-		struct v4l2_streamparm *parm)
-{
-	struct go7007 *go = video_drvdata(filp);
-	struct v4l2_fract timeperframe = {
-		.numerator = 1001 *  go->fps_scale,
-		.denominator = go->sensor_framerate,
-	};
-
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	parm->parm.capture.readbuffers = 2;
-	parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-	parm->parm.capture.timeperframe = timeperframe;
-
-	return 0;
-}
-
-static int vidioc_s_parm(struct file *filp, void *priv,
-		struct v4l2_streamparm *parm)
-{
-	struct go7007 *go = video_drvdata(filp);
-	unsigned int n, d;
-
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	n = go->sensor_framerate *
-		parm->parm.capture.timeperframe.numerator;
-	d = 1001 * parm->parm.capture.timeperframe.denominator;
-	if (n != 0 && d != 0 && n > d)
-		go->fps_scale = (n + d/2) / d;
-	else
-		go->fps_scale = 1;
-
-	return vidioc_g_parm(filp, priv, parm);
-}
-
-/* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
-   its resolution, when the device is not connected to TV.
-   This is were an API abuse, probably used by the lack of specific IOCTL's to
-   enumerate it, by the time the driver was written.
-
-   However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
-   and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
-
-   The two functions below implement the newer ioctls
-*/
-static int vidioc_enum_framesizes(struct file *filp, void *priv,
-				  struct v4l2_frmsizeenum *fsize)
-{
-	struct go7007 *go = video_drvdata(filp);
-	int width, height;
-
-	if (fsize->index > 2)
-		return -EINVAL;
-
-	if (!valid_pixelformat(fsize->pixel_format))
-		return -EINVAL;
-
-	get_resolution(go, &width, &height);
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete.width = (width >> fsize->index) & ~0xf;
-	fsize->discrete.height = (height >> fsize->index) & ~0xf;
-	return 0;
-}
-
-static int vidioc_enum_frameintervals(struct file *filp, void *priv,
-				      struct v4l2_frmivalenum *fival)
-{
-	struct go7007 *go = video_drvdata(filp);
-	int width, height;
-	int i;
-
-	if (fival->index > 4)
-		return -EINVAL;
-
-	if (!valid_pixelformat(fival->pixel_format))
-		return -EINVAL;
-
-	if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
-		get_resolution(go, &width, &height);
-		for (i = 0; i <= 2; i++)
-			if (fival->width == ((width >> i) & ~0xf) &&
-			    fival->height == ((height >> i) & ~0xf))
-				break;
-		if (i > 2)
-			return -EINVAL;
-	}
-	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-	fival->discrete.numerator = 1001 * (fival->index + 1);
-	fival->discrete.denominator = go->sensor_framerate;
-	return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	*std = go->std;
-	return 0;
-}
-
-static int go7007_s_std(struct go7007 *go)
-{
-	if (go->std & V4L2_STD_625_50) {
-		go->standard = GO7007_STD_PAL;
-		go->sensor_framerate = 25025;
-	} else {
-		go->standard = GO7007_STD_NTSC;
-		go->sensor_framerate = 30000;
-	}
-
-	call_all(&go->v4l2_dev, video, s_std, go->std);
-	set_capture_size(go, NULL, 0);
-	return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (vb2_is_busy(&go->vidq))
-		return -EBUSY;
-
-	go->std = std;
-
-	return go7007_s_std(go);
-}
-
-static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	return call_all(&go->v4l2_dev, video, querystd, std);
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-				struct v4l2_input *inp)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (inp->index >= go->board_info->num_inputs)
-		return -EINVAL;
-
-	strncpy(inp->name, go->board_info->inputs[inp->index].name,
-			sizeof(inp->name));
-
-	/* If this board has a tuner, it will be the first input */
-	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
-			inp->index == 0)
-		inp->type = V4L2_INPUT_TYPE_TUNER;
-	else
-		inp->type = V4L2_INPUT_TYPE_CAMERA;
-
-	if (go->board_info->num_aud_inputs)
-		inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
-	else
-		inp->audioset = 0;
-	inp->tuner = 0;
-	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
-		inp->std = video_devdata(file)->tvnorms;
-	else
-		inp->std = 0;
-
-	return 0;
-}
-
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	*input = go->input;
-
-	return 0;
-}
-
-static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (a->index >= go->board_info->num_aud_inputs)
-		return -EINVAL;
-	strlcpy(a->name, go->board_info->aud_inputs[a->index].name,
-		sizeof(a->name));
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	a->index = go->aud_input;
-	strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
-		sizeof(a->name));
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *fh,
-	const struct v4l2_audio *a)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (a->index >= go->board_info->num_aud_inputs)
-		return -EINVAL;
-	go->aud_input = a->index;
-	v4l2_subdev_call(go->sd_audio, audio, s_routing,
-		go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
-	return 0;
-}
-
-static void go7007_s_input(struct go7007 *go)
-{
-	unsigned int input = go->input;
-
-	v4l2_subdev_call(go->sd_video, video, s_routing,
-			go->board_info->inputs[input].video_input, 0,
-			go->board_info->video_config);
-	if (go->board_info->num_aud_inputs) {
-		int aud_input = go->board_info->inputs[input].audio_index;
-
-		v4l2_subdev_call(go->sd_audio, audio, s_routing,
-			go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
-		go->aud_input = aud_input;
-	}
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (input >= go->board_info->num_inputs)
-		return -EINVAL;
-	if (vb2_is_busy(&go->vidq))
-		return -EBUSY;
-
-	go->input = input;
-	go7007_s_input(go);
-
-	return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (t->index != 0)
-		return -EINVAL;
-
-	strlcpy(t->name, "Tuner", sizeof(t->name));
-	return call_all(&go->v4l2_dev, tuner, g_tuner, t);
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-				const struct v4l2_tuner *t)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (t->index != 0)
-		return -EINVAL;
-
-	return call_all(&go->v4l2_dev, tuner, s_tuner, t);
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (f->tuner)
-		return -EINVAL;
-
-	return call_all(&go->v4l2_dev, tuner, g_frequency, f);
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-				const struct v4l2_frequency *f)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	if (f->tuner)
-		return -EINVAL;
-
-	return call_all(&go->v4l2_dev, tuner, s_frequency, f);
-}
-
-static int vidioc_log_status(struct file *file, void *priv)
-{
-	struct go7007 *go = video_drvdata(file);
-
-	v4l2_ctrl_log_status(file, priv);
-	return call_all(&go->v4l2_dev, core, log_status);
-}
-
-/* FIXME:
-	Those ioctls are private, and not needed, since several standard
-	extended controls already provide streaming control.
-	So, those ioctls should be converted into vidioc_g_ext_ctrls()
-	and vidioc_s_ext_ctrls()
- */
-
-#if 0
-	case GO7007IOC_S_MD_PARAMS:
-	{
-		struct go7007_md_params *mdp = arg;
-
-		if (mdp->region > 3)
-			return -EINVAL;
-		if (mdp->trigger > 0) {
-			go->modet[mdp->region].pixel_threshold =
-					mdp->pixel_threshold >> 1;
-			go->modet[mdp->region].motion_threshold =
-					mdp->motion_threshold >> 1;
-			go->modet[mdp->region].mb_threshold =
-					mdp->trigger >> 1;
-			go->modet[mdp->region].enable = 1;
-		} else
-			go->modet[mdp->region].enable = 0;
-		/* fall-through */
-	}
-	case GO7007IOC_S_MD_REGION:
-	{
-		struct go7007_md_region *region = arg;
-
-		if (region->region < 1 || region->region > 3)
-			return -EINVAL;
-		return clip_to_modet_map(go, region->region, region->clips);
-	}
-#endif
-
-static struct v4l2_file_operations go7007_fops = {
-	.owner		= THIS_MODULE,
-	.open		= v4l2_fh_open,
-	.release	= vb2_fop_release,
-	.unlocked_ioctl	= video_ioctl2,
-	.read		= vb2_fop_read,
-	.mmap		= vb2_fop_mmap,
-	.poll		= vb2_fop_poll,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-	.vidioc_querycap          = vidioc_querycap,
-	.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
-	.vidioc_querybuf          = vb2_ioctl_querybuf,
-	.vidioc_qbuf              = vb2_ioctl_qbuf,
-	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
-	.vidioc_g_std             = vidioc_g_std,
-	.vidioc_s_std             = vidioc_s_std,
-	.vidioc_querystd          = vidioc_querystd,
-	.vidioc_enum_input        = vidioc_enum_input,
-	.vidioc_g_input           = vidioc_g_input,
-	.vidioc_s_input           = vidioc_s_input,
-	.vidioc_enumaudio         = vidioc_enumaudio,
-	.vidioc_g_audio           = vidioc_g_audio,
-	.vidioc_s_audio           = vidioc_s_audio,
-	.vidioc_streamon          = vb2_ioctl_streamon,
-	.vidioc_streamoff         = vb2_ioctl_streamoff,
-	.vidioc_g_tuner           = vidioc_g_tuner,
-	.vidioc_s_tuner           = vidioc_s_tuner,
-	.vidioc_g_frequency       = vidioc_g_frequency,
-	.vidioc_s_frequency       = vidioc_s_frequency,
-	.vidioc_g_parm            = vidioc_g_parm,
-	.vidioc_s_parm            = vidioc_s_parm,
-	.vidioc_enum_framesizes   = vidioc_enum_framesizes,
-	.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
-	.vidioc_log_status        = vidioc_log_status,
-	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static struct video_device go7007_template = {
-	.name		= "go7007",
-	.fops		= &go7007_fops,
-	.release	= video_device_release_empty,
-	.ioctl_ops	= &video_ioctl_ops,
-	.tvnorms	= V4L2_STD_ALL,
-};
-
-int go7007_v4l2_ctrl_init(struct go7007 *go)
-{
-	struct v4l2_ctrl_handler *hdl = &go->hdl;
-	struct v4l2_ctrl *ctrl;
-
-	v4l2_ctrl_handler_init(hdl, 13);
-	go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
-	go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
-	go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_BITRATE,
-			64000, 10000000, 1, 9800000);
-	go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0);
-	go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1);
-
-	go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL,
-			V4L2_CID_MPEG_VIDEO_ASPECT,
-			V4L2_MPEG_VIDEO_ASPECT_16x9, 0,
-			V4L2_MPEG_VIDEO_ASPECT_1x1);
-	ctrl = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_JPEG_ACTIVE_MARKER, 0,
-			V4L2_JPEG_ACTIVE_MARKER_DQT |
-			V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
-			V4L2_JPEG_ACTIVE_MARKER_DQT |
-			V4L2_JPEG_ACTIVE_MARKER_DHT);
-	if (ctrl)
-		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-	if (hdl->error) {
-		int rv = hdl->error;
-
-		v4l2_err(&go->v4l2_dev, "Could not register controls\n");
-		return rv;
-	}
-	go->v4l2_dev.ctrl_handler = hdl;
-	return 0;
-}
-
-int go7007_v4l2_init(struct go7007 *go)
-{
-	struct video_device *vdev = &go->vdev;
-	int rv;
-
-	mutex_init(&go->serialize_lock);
-	mutex_init(&go->queue_lock);
-
-	INIT_LIST_HEAD(&go->vidq_active);
-	go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	go->vidq.ops = &go7007_video_qops;
-	go->vidq.mem_ops = &vb2_vmalloc_memops;
-	go->vidq.drv_priv = go;
-	go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
-	go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	go->vidq.lock = &go->queue_lock;
-	rv = vb2_queue_init(&go->vidq);
-	if (rv)
-		return rv;
-	*vdev = go7007_template;
-	vdev->lock = &go->serialize_lock;
-	vdev->queue = &go->vidq;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
-	video_set_drvdata(vdev, go);
-	vdev->v4l2_dev = &go->v4l2_dev;
-	if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
-		v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
-	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
-		v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
-		v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
-		v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
-		v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
-	} else {
-		struct v4l2_frequency f = {
-			.type = V4L2_TUNER_ANALOG_TV,
-			.frequency = 980,
-		};
-
-		call_all(&go->v4l2_dev, tuner, s_frequency, &f);
-	}
-	if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
-		v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
-		v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
-		vdev->tvnorms = 0;
-	}
-	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
-		v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
-	if (go->board_info->num_aud_inputs == 0) {
-		v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
-		v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
-		v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
-	}
-	/* Setup correct crystal frequency on this board */
-	if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
-		v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
-				SAA7115_FREQ_24_576_MHZ,
-				SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
-				SAA7115_FREQ_FL_DOUBLE_ASCLK);
-	go7007_s_input(go);
-	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
-		go7007_s_std(go);
-	rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-	if (rv < 0)
-		return rv;
-	dev_info(go->dev, "registered device %s [v4l2]\n",
-		 video_device_node_name(vdev));
-
-	return 0;
-}
-
-void go7007_v4l2_remove(struct go7007 *go)
-{
-	v4l2_ctrl_handler_free(&go->hdl);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-config VIDEO_GO7007
-	tristate "WIS GO7007 MPEG encoder support"
-	depends on VIDEO_DEV && I2C
-	depends on SND && USB
-	select VIDEOBUF2_VMALLOC
-	select VIDEO_TUNER
-	select CYPRESS_FIRMWARE
-	select SND_PCM
-	select VIDEO_SONY_BTF_MPX if MEDIA_SUBDRV_AUTOSELECT
-	select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
-	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_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
-	---help---
-	  This is a video4linux driver for the WIS GO7007 MPEG
-	  encoder chip.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called go7007.
-
-config VIDEO_GO7007_USB
-	tristate "WIS GO7007 USB support"
-	depends on VIDEO_GO7007 && USB
-	---help---
-	  This is a video4linux driver for the WIS GO7007 MPEG
-	  encoder chip over USB.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called go7007-usb.
-
-config VIDEO_GO7007_LOADER
-	tristate "WIS GO7007 Loader support"
-	depends on VIDEO_GO7007
-	default y
-	---help---
-	  This is a go7007 firmware loader driver for the WIS GO7007
-	  MPEG encoder chip over USB.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called go7007-loader.
-
-config VIDEO_GO7007_USB_S2250_BOARD
-	tristate "Sensoray 2250/2251 support"
-	depends on VIDEO_GO7007_USB && USB
-	---help---
-	  This is a video4linux driver for the Sensoray 2250/2251 device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called s2250.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-obj-$(CONFIG_VIDEO_GO7007) += go7007.o
-obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
-obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o
-obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
-
-go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
-		snd-go7007.o
-
-s2250-y := s2250-board.o
-
-# Uncomment when the saa7134 patches get into upstream
-#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
-#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
-
-ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/README linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/README
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/README	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/README	1969-12-31 19:00:00.000000000 -0500
@@ -1,137 +0,0 @@
-Todo:
-	- create an API for motion detection
-	- let s2250-board use i2c subdevs as well instead of hardcoding
-	  support for the i2c devices.
-	- when the driver is moved out of staging, support for saa7134-go7007
-	  should be added to the saa7134 driver. The patch for that is
-	  included below.
-
-Patch for saa7134:
-
-diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
-index dc68cf1..9a53794 100644
---- a/drivers/media/pci/saa7134/saa7134-cards.c
-+++ b/drivers/media/pci/saa7134/saa7134-cards.c
-@@ -5790,6 +5790,29 @@ struct saa7134_board saa7134_boards[] = {
- 			.gpio = 0x6010000,
- 		} },
- 	},
-+	[SAA7134_BOARD_WIS_VOYAGER] = {
-+		.name           = "WIS Voyager or compatible",
-+		.audio_clock    = 0x00200000,
-+		.tuner_type	= TUNER_PHILIPS_TDA8290,
-+		.radio_type     = UNSET,
-+		.tuner_addr     = ADDR_UNSET,
-+		.radio_addr     = ADDR_UNSET,
-+		.mpeg		= SAA7134_MPEG_GO7007,
-+		.inputs		= { {
-+			.name = name_comp1,
-+			.vmux = 0,
-+			.amux = LINE2,
-+		}, {
-+			.name = name_tv,
-+			.vmux = 3,
-+			.amux = TV,
-+			.tv   = 1,
-+		}, {
-+			.name = name_svideo,
-+			.vmux = 6,
-+		.amux = LINE1,
-+		} },
-+	},
- 
- };
- 
-@@ -7037,6 +7060,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
- 		.subdevice    = 0x0911,
- 		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
- 	}, {
-+		.vendor       = PCI_VENDOR_ID_PHILIPS,
-+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-+		.subvendor    = 0x1905, /* WIS */
-+		.subdevice    = 0x7007,
-+		.driver_data  = SAA7134_BOARD_WIS_VOYAGER,
-+	}, {
- 		/* --- boards without eeprom + subsystem ID --- */
- 		.vendor       = PCI_VENDOR_ID_PHILIPS,
- 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
-index 8fd24e7..0a849ea 100644
---- a/drivers/media/pci/saa7134/saa7134-core.c
-+++ b/drivers/media/pci/saa7134/saa7134-core.c
-@@ -156,6 +156,8 @@ static void request_module_async(struct work_struct *work){
- 		request_module("saa7134-empress");
- 	if (card_is_dvb(dev))
- 		request_module("saa7134-dvb");
-+	if (card_is_go7007(dev))
-+		request_module("saa7134-go7007");
- 	if (alsa) {
- 		if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
- 			request_module("saa7134-alsa");
-@@ -557,8 +559,12 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
- 			saa7134_irq_vbi_done(dev,status);
- 
- 		if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
--		    card_has_mpeg(dev))
--			saa7134_irq_ts_done(dev,status);
-+		    card_has_mpeg(dev)) {
-+			if (dev->mops->irq_ts_done != NULL)
-+				dev->mops->irq_ts_done(dev, status);
-+			else
-+				saa7134_irq_ts_done(dev, status);
-+		}
- 
- 		if (report & SAA7134_IRQ_REPORT_GPIO16) {
- 			switch (dev->has_remote) {
-diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
-index 62169dd..5fad39a 100644
---- a/drivers/media/pci/saa7134/saa7134.h
-+++ b/drivers/media/pci/saa7134/saa7134.h
-@@ -334,6 +334,7 @@ struct saa7134_card_ir {
- #define SAA7134_BOARD_KWORLD_PC150U         189
- #define SAA7134_BOARD_ASUSTeK_PS3_100      190
- #define SAA7134_BOARD_HAWELL_HW_9004V1      191
-+#define SAA7134_BOARD_WIS_VOYAGER           192
- 
- #define SAA7134_MAXBOARDS 32
- #define SAA7134_INPUT_MAX 8
-@@ -364,6 +365,7 @@ enum saa7134_mpeg_type {
- 	SAA7134_MPEG_UNUSED,
- 	SAA7134_MPEG_EMPRESS,
- 	SAA7134_MPEG_DVB,
-+	SAA7134_MPEG_GO7007,
- };
- 
- enum saa7134_mpeg_ts_type {
-@@ -403,6 +405,7 @@ struct saa7134_board {
- #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
- #define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
- #define card_is_dvb(dev)      (SAA7134_MPEG_DVB     == saa7134_boards[dev->board].mpeg)
-+#define card_is_go7007(dev)   (SAA7134_MPEG_GO7007  == saa7134_boards[dev->board].mpeg)
- #define card_has_mpeg(dev)    (SAA7134_MPEG_UNUSED  != saa7134_boards[dev->board].mpeg)
- #define card(dev)             (saa7134_boards[dev->board])
- #define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
-@@ -535,6 +538,8 @@ struct saa7134_mpeg_ops {
- 	int                        (*init)(struct saa7134_dev *dev);
- 	int                        (*fini)(struct saa7134_dev *dev);
- 	void                       (*signal_change)(struct saa7134_dev *dev);
-+	void                       (*irq_ts_done)(struct saa7134_dev *dev,
-+						  unsigned long status);
- };
- 
- /* global device status */
-diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile
-index 9c6ad4a..1b23689 100644
---- a/drivers/staging/media/go7007/Makefile
-+++ b/drivers/staging/media/go7007/Makefile
-@@ -8,8 +8,7 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
- 
- s2250-y := s2250-board.o
- 
--# Uncomment when the saa7134 patches get into upstream
--#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
--#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
-+obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
-+ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
- 
- ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/s2250-board.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/s2250-board.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/s2250-board.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/s2250-board.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,631 +0,0 @@
-/*
- * Copyright (C) 2008 Sensoray Company Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-subdev.h>
-#include "go7007-priv.h"
-
-MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver");
-MODULE_LICENSE("GPL v2");
-
-/*
- * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b.
- * Due to the unusual way these are accessed on this device we do not
- * reuse the i2c drivers, but instead they are implemented in this
- * driver. It would be nice to improve on this, though.
- */
-
-#define TLV320_ADDRESS      0x34
-#define VPX322_ADDR_ANALOGCONTROL1	0x02
-#define VPX322_ADDR_BRIGHTNESS0		0x0127
-#define VPX322_ADDR_BRIGHTNESS1		0x0131
-#define VPX322_ADDR_CONTRAST0		0x0128
-#define VPX322_ADDR_CONTRAST1		0x0132
-#define VPX322_ADDR_HUE			0x00dc
-#define VPX322_ADDR_SAT			0x0030
-
-struct go7007_usb_board {
-	unsigned int flags;
-	struct go7007_board_info main_info;
-};
-
-struct go7007_usb {
-	struct go7007_usb_board *board;
-	struct mutex i2c_lock;
-	struct usb_device *usbdev;
-	struct urb *video_urbs[8];
-	struct urb *audio_urbs[8];
-	struct urb *intr_urb;
-};
-
-static unsigned char aud_regs[] = {
-	0x1e, 0x00,
-	0x00, 0x17,
-	0x02, 0x17,
-	0x04, 0xf9,
-	0x06, 0xf9,
-	0x08, 0x02,
-	0x0a, 0x00,
-	0x0c, 0x00,
-	0x0a, 0x00,
-	0x0c, 0x00,
-	0x0e, 0x02,
-	0x10, 0x00,
-	0x12, 0x01,
-	0x00, 0x00,
-};
-
-
-static unsigned char vid_regs[] = {
-	0xF2, 0x0f,
-	0xAA, 0x00,
-	0xF8, 0xff,
-	0x00, 0x00,
-};
-
-static u16 vid_regs_fp[] = {
-	0x028, 0x067,
-	0x120, 0x016,
-	0x121, 0xcF2,
-	0x122, 0x0F2,
-	0x123, 0x00c,
-	0x124, 0x2d0,
-	0x125, 0x2e0,
-	0x126, 0x004,
-	0x128, 0x1E0,
-	0x12A, 0x016,
-	0x12B, 0x0F2,
-	0x12C, 0x0F2,
-	0x12D, 0x00c,
-	0x12E, 0x2d0,
-	0x12F, 0x2e0,
-	0x130, 0x004,
-	0x132, 0x1E0,
-	0x140, 0x060,
-	0x153, 0x00C,
-	0x154, 0x200,
-	0x150, 0x801,
-	0x000, 0x000
-};
-
-/* PAL specific values */
-static u16 vid_regs_fp_pal[] = {
-	0x120, 0x017,
-	0x121, 0xd22,
-	0x122, 0x122,
-	0x12A, 0x017,
-	0x12B, 0x122,
-	0x12C, 0x122,
-	0x140, 0x060,
-	0x000, 0x000,
-};
-
-struct s2250 {
-	struct v4l2_subdev sd;
-	struct v4l2_ctrl_handler hdl;
-	v4l2_std_id std;
-	int input;
-	int brightness;
-	int contrast;
-	int saturation;
-	int hue;
-	int reg12b_val;
-	int audio_input;
-	struct i2c_client *audio;
-};
-
-static inline struct s2250 *to_state(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct s2250, sd);
-}
-
-/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
-static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
-	u16 value, u16 index, void *transfer_buffer, int length, int in)
-{
-	struct go7007_usb *usb = go->hpi_context;
-	int timeout = 5000;
-
-	if (in) {
-		return usb_control_msg(usb->usbdev,
-				usb_rcvctrlpipe(usb->usbdev, 0), request,
-				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-				value, index, transfer_buffer, length, timeout);
-	} else {
-		return usb_control_msg(usb->usbdev,
-				usb_sndctrlpipe(usb->usbdev, 0), request,
-				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				value, index, transfer_buffer, length, timeout);
-	}
-}
-/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
-
-static int write_reg(struct i2c_client *client, u8 reg, u8 value)
-{
-	struct go7007 *go = i2c_get_adapdata(client->adapter);
-	struct go7007_usb *usb;
-	int rc;
-	int dev_addr = client->addr << 1;  /* firmware wants 8-bit address */
-	u8 *buf;
-
-	if (go == NULL)
-		return -ENODEV;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -EBUSY;
-
-	buf = kzalloc(16, GFP_KERNEL);
-	if (buf == NULL)
-		return -ENOMEM;
-
-	usb = go->hpi_context;
-	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-		dev_info(&client->dev, "i2c lock failed\n");
-		kfree(buf);
-		return -EINTR;
-	}
-	rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
-				       (reg<<8 | value),
-				       buf,
-				       16, 1);
-
-	mutex_unlock(&usb->i2c_lock);
-	kfree(buf);
-	return rc;
-}
-
-static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
-{
-	struct go7007 *go = i2c_get_adapdata(client->adapter);
-	struct go7007_usb *usb;
-	int rc;
-	u8 *buf;
-	struct s2250 *dec = i2c_get_clientdata(client);
-
-	if (go == NULL)
-		return -ENODEV;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -EBUSY;
-
-	buf = kzalloc(16, GFP_KERNEL);
-
-	if (buf == NULL)
-		return -ENOMEM;
-
-
-
-	memset(buf, 0xcd, 6);
-
-	usb = go->hpi_context;
-	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-		dev_info(&client->dev, "i2c lock failed\n");
-		kfree(buf);
-		return -EINTR;
-	}
-	rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1);
-	mutex_unlock(&usb->i2c_lock);
-	if (rc < 0) {
-		kfree(buf);
-		return rc;
-	}
-
-	if (buf[0] == 0) {
-		unsigned int subaddr, val_read;
-
-		subaddr = (buf[4] << 8) + buf[5];
-		val_read = (buf[2] << 8) + buf[3];
-		kfree(buf);
-		if (val_read != val) {
-			dev_info(&client->dev, "invalid fp write %x %x\n",
-				 val_read, val);
-			return -EFAULT;
-		}
-		if (subaddr != addr) {
-			dev_info(&client->dev, "invalid fp write addr %x %x\n",
-				 subaddr, addr);
-			return -EFAULT;
-		}
-	} else {
-		kfree(buf);
-		return -EFAULT;
-	}
-
-	/* save last 12b value */
-	if (addr == 0x12b)
-		dec->reg12b_val = val;
-
-	return 0;
-}
-
-static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
-{
-	struct go7007 *go = i2c_get_adapdata(client->adapter);
-	struct go7007_usb *usb;
-	int rc;
-	u8 *buf;
-
-	if (go == NULL)
-		return -ENODEV;
-
-	if (go->status == STATUS_SHUTDOWN)
-		return -EBUSY;
-
-	buf = kzalloc(16, GFP_KERNEL);
-
-	if (buf == NULL)
-		return -ENOMEM;
-
-
-
-	memset(buf, 0xcd, 6);
-	usb = go->hpi_context;
-	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
-		dev_info(&client->dev, "i2c lock failed\n");
-		kfree(buf);
-		return -EINTR;
-	}
-	rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1);
-	mutex_unlock(&usb->i2c_lock);
-	if (rc < 0) {
-		kfree(buf);
-		return rc;
-	}
-
-	*val = (buf[0] << 8) | buf[1];
-	kfree(buf);
-
-	return 0;
-}
-
-
-static int write_regs(struct i2c_client *client, u8 *regs)
-{
-	int i;
-
-	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
-		if (write_reg(client, regs[i], regs[i+1]) < 0) {
-			dev_info(&client->dev, "failed\n");
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static int write_regs_fp(struct i2c_client *client, u16 *regs)
-{
-	int i;
-
-	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
-		if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
-			dev_info(&client->dev, "failed fp\n");
-			return -1;
-		}
-	}
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
-				 u32 config)
-{
-	struct s2250 *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int vidsys;
-
-	vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
-	if (input == 0) {
-		/* composite */
-		write_reg_fp(client, 0x20, 0x020 | vidsys);
-		write_reg_fp(client, 0x21, 0x662);
-		write_reg_fp(client, 0x140, 0x060);
-	} else if (input == 1) {
-		/* S-Video */
-		write_reg_fp(client, 0x20, 0x040 | vidsys);
-		write_reg_fp(client, 0x21, 0x666);
-		write_reg_fp(client, 0x140, 0x060);
-	} else {
-		return -EINVAL;
-	}
-	state->input = input;
-	return 0;
-}
-
-static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-	struct s2250 *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	u16 vidsource;
-
-	vidsource = (state->input == 1) ? 0x040 : 0x020;
-	if (norm & V4L2_STD_625_50) {
-		write_regs_fp(client, vid_regs_fp);
-		write_regs_fp(client, vid_regs_fp_pal);
-		write_reg_fp(client, 0x20, vidsource);
-	} else {
-		write_regs_fp(client, vid_regs_fp);
-		write_reg_fp(client, 0x20, vidsource | 1);
-	}
-	state->std = norm;
-	return 0;
-}
-
-static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
-	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
-	u16 oldvalue;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
-			     ctrl->val | (oldvalue & ~0xff));
-		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
-			     ctrl->val | (oldvalue & ~0xff));
-		write_reg_fp(client, 0x140, 0x60);
-		break;
-	case V4L2_CID_CONTRAST:
-		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
-			     ctrl->val | (oldvalue & ~0x3f));
-		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
-			     ctrl->val | (oldvalue & ~0x3f));
-		write_reg_fp(client, 0x140, 0x60);
-		break;
-	case V4L2_CID_SATURATION:
-		write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
-		break;
-	case V4L2_CID_HUE:
-		write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int s2250_s_mbus_fmt(struct v4l2_subdev *sd,
-			struct v4l2_mbus_framefmt *fmt)
-{
-	struct s2250 *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	if (fmt->height < 640) {
-		write_reg_fp(client, 0x12b, state->reg12b_val | 0x400);
-		write_reg_fp(client, 0x140, 0x060);
-	} else {
-		write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400);
-		write_reg_fp(client, 0x140, 0x060);
-	}
-	return 0;
-}
-
-static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output,
-				 u32 config)
-{
-	struct s2250 *state = to_state(sd);
-
-	switch (input) {
-	case 0:
-		write_reg(state->audio, 0x08, 0x02); /* Line In */
-		break;
-	case 1:
-		write_reg(state->audio, 0x08, 0x04); /* Mic */
-		break;
-	case 2:
-		write_reg(state->audio, 0x08, 0x05); /* Mic Boost */
-		break;
-	default:
-		return -EINVAL;
-	}
-	state->audio_input = input;
-	return 0;
-}
-
-
-static int s2250_log_status(struct v4l2_subdev *sd)
-{
-	struct s2250 *state = to_state(sd);
-
-	v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" :
-					state->std == V4L2_STD_PAL ? "PAL" :
-					state->std == V4L2_STD_SECAM ? "SECAM" :
-					"unknown");
-	v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" :
-					state->input == 1 ? "S-video" :
-					"error");
-	v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" :
-					state->audio_input == 1 ? "Mic" :
-					state->audio_input == 2 ? "Mic Boost" :
-					"error");
-	return v4l2_ctrl_subdev_log_status(sd);
-}
-
-/* --------------------------------------------------------------------------*/
-
-static const struct v4l2_ctrl_ops s2250_ctrl_ops = {
-	.s_ctrl = s2250_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops s2250_core_ops = {
-	.log_status = s2250_log_status,
-};
-
-static const struct v4l2_subdev_audio_ops s2250_audio_ops = {
-	.s_routing = s2250_s_audio_routing,
-};
-
-static const struct v4l2_subdev_video_ops s2250_video_ops = {
-	.s_std = s2250_s_std,
-	.s_routing = s2250_s_video_routing,
-	.s_mbus_fmt = s2250_s_mbus_fmt,
-};
-
-static const struct v4l2_subdev_ops s2250_ops = {
-	.core = &s2250_core_ops,
-	.audio = &s2250_audio_ops,
-	.video = &s2250_video_ops,
-};
-
-/* --------------------------------------------------------------------------*/
-
-static int s2250_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id)
-{
-	struct i2c_client *audio;
-	struct i2c_adapter *adapter = client->adapter;
-	struct s2250 *state;
-	struct v4l2_subdev *sd;
-	u8 *data;
-	struct go7007 *go = i2c_get_adapdata(adapter);
-	struct go7007_usb *usb = go->hpi_context;
-
-	audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
-	if (audio == NULL)
-		return -ENOMEM;
-
-	state = kzalloc(sizeof(struct s2250), GFP_KERNEL);
-	if (state == NULL) {
-		i2c_unregister_device(audio);
-		return -ENOMEM;
-	}
-
-	sd = &state->sd;
-	v4l2_i2c_subdev_init(sd, client, &s2250_ops);
-
-	v4l2_info(sd, "initializing %s at address 0x%x on %s\n",
-	       "Sensoray 2250/2251", client->addr, client->adapter->name);
-
-	v4l2_ctrl_handler_init(&state->hdl, 4);
-	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
-		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
-	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
-		V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32);
-	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
-		V4L2_CID_SATURATION, 0, 4094, 1, 2070);
-	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
-		V4L2_CID_HUE, -512, 511, 1, 0);
-	sd->ctrl_handler = &state->hdl;
-	if (state->hdl.error) {
-		int err = state->hdl.error;
-
-		v4l2_ctrl_handler_free(&state->hdl);
-		kfree(state);
-		return err;
-	}
-
-	state->std = V4L2_STD_NTSC;
-	state->brightness = 50;
-	state->contrast = 50;
-	state->saturation = 50;
-	state->hue = 0;
-	state->audio = audio;
-
-	/* initialize the audio */
-	if (write_regs(audio, aud_regs) < 0) {
-		dev_err(&client->dev, "error initializing audio\n");
-		goto fail;
-	}
-
-	if (write_regs(client, vid_regs) < 0) {
-		dev_err(&client->dev, "error initializing decoder\n");
-		goto fail;
-	}
-	if (write_regs_fp(client, vid_regs_fp) < 0) {
-		dev_err(&client->dev, "error initializing decoder\n");
-		goto fail;
-	}
-	/* set default channel */
-	/* composite */
-	write_reg_fp(client, 0x20, 0x020 | 1);
-	write_reg_fp(client, 0x21, 0x662);
-	write_reg_fp(client, 0x140, 0x060);
-
-	/* set default audio input */
-	state->audio_input = 0;
-	write_reg(client, 0x08, 0x02); /* Line In */
-
-	if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
-		data = kzalloc(16, GFP_KERNEL);
-		if (data != NULL) {
-			int rc;
-			rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
-						       data, 16, 1);
-			if (rc > 0) {
-				u8 mask;
-				data[0] = 0;
-				mask = 1<<5;
-				data[0] &= ~mask;
-				data[1] |= mask;
-				go7007_usb_vendor_request(go, 0x40, 0,
-							  (data[1]<<8)
-							  + data[1],
-							  data, 16, 0);
-			}
-			kfree(data);
-		}
-		mutex_unlock(&usb->i2c_lock);
-	}
-
-	v4l2_info(sd, "initialized successfully\n");
-	return 0;
-
-fail:
-	i2c_unregister_device(audio);
-	v4l2_ctrl_handler_free(&state->hdl);
-	kfree(state);
-	return -EIO;
-}
-
-static int s2250_remove(struct i2c_client *client)
-{
-	struct s2250 *state = to_state(i2c_get_clientdata(client));
-
-	v4l2_device_unregister_subdev(&state->sd);
-	v4l2_ctrl_handler_free(&state->hdl);
-	kfree(state);
-	return 0;
-}
-
-static const struct i2c_device_id s2250_id[] = {
-	{ "s2250", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, s2250_id);
-
-static struct i2c_driver s2250_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "s2250",
-	},
-	.probe		= s2250_probe,
-	.remove		= s2250_remove,
-	.id_table	= s2250_id,
-};
-
-module_i2c_driver(s2250_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/saa7134-go7007.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/saa7134-go7007.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/saa7134-go7007.c	2014-08-07 04:50:41.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/saa7134-go7007.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,567 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <asm/byteorder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-
-#include "saa7134.h"
-#include "saa7134-reg.h"
-#include "go7007.h"
-#include "go7007-priv.h"
-
-/*#define GO7007_HPI_DEBUG*/
-
-enum hpi_address {
-	HPI_ADDR_VIDEO_BUFFER = 0xe4,
-	HPI_ADDR_INIT_BUFFER = 0xea,
-	HPI_ADDR_INTR_RET_VALUE = 0xee,
-	HPI_ADDR_INTR_RET_DATA = 0xec,
-	HPI_ADDR_INTR_STATUS = 0xf4,
-	HPI_ADDR_INTR_WR_PARAM = 0xf6,
-	HPI_ADDR_INTR_WR_INDEX = 0xf8,
-};
-
-enum gpio_command {
-	GPIO_COMMAND_RESET = 0x00, /* 000b */
-	GPIO_COMMAND_REQ1  = 0x04, /* 001b */
-	GPIO_COMMAND_WRITE = 0x20, /* 010b */
-	GPIO_COMMAND_REQ2  = 0x24, /* 011b */
-	GPIO_COMMAND_READ  = 0x80, /* 100b */
-	GPIO_COMMAND_VIDEO = 0x84, /* 101b */
-	GPIO_COMMAND_IDLE  = 0xA0, /* 110b */
-	GPIO_COMMAND_ADDR  = 0xA4, /* 111b */
-};
-
-struct saa7134_go7007 {
-	struct v4l2_subdev sd;
-	struct saa7134_dev *dev;
-	u8 *top;
-	u8 *bottom;
-	dma_addr_t top_dma;
-	dma_addr_t bottom_dma;
-};
-
-static inline struct saa7134_go7007 *to_state(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct saa7134_go7007, sd);
-}
-
-static const struct go7007_board_info board_voyager = {
-	.flags		 = 0,
-	.sensor_flags	 = GO7007_SENSOR_656 |
-				GO7007_SENSOR_VALID_ENABLE |
-				GO7007_SENSOR_TV |
-				GO7007_SENSOR_VBI,
-	.audio_flags	= GO7007_AUDIO_I2S_MODE_1 |
-				GO7007_AUDIO_WORD_16,
-	.audio_rate	 = 48000,
-	.audio_bclk_div	 = 8,
-	.audio_main_div	 = 2,
-	.hpi_buffer_cap  = 7,
-	.num_inputs	 = 1,
-	.inputs		 = {
-		{
-			.name		= "SAA7134",
-		},
-	},
-};
-
-/********************* Driver for GPIO HPI interface *********************/
-
-static int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data)
-{
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
-
-	/* Write HPI address */
-	saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	/* Write low byte */
-	saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	/* Write high byte */
-	saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	return 0;
-}
-
-static int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data)
-{
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
-
-	/* Write HPI address */
-	saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
-
-	/* Read low byte */
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
-	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	*data = saa_readb(SAA7134_GPIO_GPSTATUS0);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	/* Read high byte */
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
-	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	*data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8;
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-
-	return 0;
-}
-
-static int saa7134_go7007_interface_reset(struct go7007 *go)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-	u32 status;
-	u16 intr_val, intr_data;
-	int count = 20;
-
-	saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */
-	saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4);
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
-
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET);
-	msleep(1);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
-	msleep(10);
-
-	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-	status = saa_readb(SAA7134_GPIO_GPSTATUS2);
-	/*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */
-
-	/* enter command mode...(?) */
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
-
-	do {
-		saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-		saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-		status = saa_readb(SAA7134_GPIO_GPSTATUS2);
-		/*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
-	} while (--count > 0);
-
-	/* Wait for an interrupt to indicate successful hardware reset */
-	if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
-			(intr_val & ~0x1) != 0x55aa) {
-		printk(KERN_ERR
-			"saa7134-go7007: unable to reset the GO7007\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-	int i;
-	u16 status_reg;
-
-#ifdef GO7007_HPI_DEBUG
-	printk(KERN_DEBUG
-		"saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
-#endif
-
-	for (i = 0; i < 100; ++i) {
-		gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
-		if (!(status_reg & 0x0010))
-			break;
-		msleep(10);
-	}
-	if (i == 100) {
-		printk(KERN_ERR
-			"saa7134-go7007: device is hung, status reg = 0x%04x\n",
-			status_reg);
-		return -1;
-	}
-	gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data);
-	gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr);
-
-	return 0;
-}
-
-static int saa7134_go7007_read_interrupt(struct go7007 *go)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-
-	/* XXX we need to wait if there is no interrupt available */
-	go->interrupt_available = 1;
-	gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value);
-	gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data);
-#ifdef GO7007_HPI_DEBUG
-	printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n",
-			go->interrupt_value, go->interrupt_data);
-#endif
-	return 0;
-}
-
-static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
-						unsigned long status)
-{
-	struct go7007 *go = video_get_drvdata(dev->empress_dev);
-	struct saa7134_go7007 *saa = go->hpi_context;
-
-	if (!vb2_is_streaming(&go->vidq))
-		return;
-	if (0 != (status & 0x000f0000))
-		printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
-				(status >> 16) & 0x0f);
-	if (status & 0x100000) {
-		dma_sync_single_for_cpu(&dev->pci->dev,
-					saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE);
-		go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE);
-		saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
-	} else {
-		dma_sync_single_for_cpu(&dev->pci->dev,
-					saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE);
-		go7007_parse_video_stream(go, saa->top, PAGE_SIZE);
-		saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
-	}
-}
-
-static int saa7134_go7007_stream_start(struct go7007 *go)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-
-	saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top),
-			0, PAGE_SIZE, DMA_FROM_DEVICE);
-	if (dma_mapping_error(&dev->pci->dev, saa->top_dma))
-		return -ENOMEM;
-	saa->bottom_dma = dma_map_page(&dev->pci->dev,
-			virt_to_page(saa->bottom),
-			0, PAGE_SIZE, DMA_FROM_DEVICE);
-	if (dma_mapping_error(&dev->pci->dev, saa->bottom_dma)) {
-		dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
-				DMA_FROM_DEVICE);
-		return -ENOMEM;
-	}
-
-	saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000);
-	saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200);
-
-	/* Set HPI interface for video */
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
-	saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER);
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
-	saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
-
-	/* Enable TS interface */
-	saa_writeb(SAA7134_TS_PARALLEL, 0xe6);
-
-	/* Reset TS interface */
-	saa_setb(SAA7134_TS_SERIAL1, 0x01);
-	saa_clearb(SAA7134_TS_SERIAL1, 0x01);
-
-	/* Set up transfer block size */
-	saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1);
-	saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1);
-	saa_writeb(SAA7134_TS_DMA1, 0);
-	saa_writeb(SAA7134_TS_DMA2, 0);
-
-	/* Enable video streaming mode */
-	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO);
-
-	saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
-	saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
-	saa_writel(SAA7134_RS_PITCH(5), 128);
-	saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX);
-
-	/* Enable TS FIFO */
-	saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
-
-	/* Enable DMA IRQ */
-	saa_setl(SAA7134_IRQ1,
-			SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
-
-	return 0;
-}
-
-static int saa7134_go7007_stream_stop(struct go7007 *go)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev;
-
-	if (!saa)
-		return -EINVAL;
-	dev = saa->dev;
-	if (!dev)
-		return -EINVAL;
-
-	/* Shut down TS FIFO */
-	saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
-
-	/* Disable DMA IRQ */
-	saa_clearl(SAA7134_IRQ1,
-			SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
-
-	/* Disable TS interface */
-	saa_clearb(SAA7134_TS_PARALLEL, 0x80);
-
-	dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
-			DMA_FROM_DEVICE);
-	dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE,
-			DMA_FROM_DEVICE);
-
-	return 0;
-}
-
-static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-	u16 status_reg;
-	int i;
-
-#ifdef GO7007_HPI_DEBUG
-	printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer "
-			"sending %d bytes\n", len);
-#endif
-
-	while (len > 0) {
-		i = len > 64 ? 64 : len;
-		saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
-		saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER);
-		saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
-		saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-		while (i-- > 0) {
-			saa_writeb(SAA7134_GPIO_GPSTATUS0, *data);
-			saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
-			saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
-			++data;
-			--len;
-		}
-		for (i = 0; i < 100; ++i) {
-			gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
-			if (!(status_reg & 0x0002))
-				break;
-		}
-		if (i == 100) {
-			printk(KERN_ERR "saa7134-go7007: device is hung, "
-					"status reg = 0x%04x\n", status_reg);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
-	.interface_reset	= saa7134_go7007_interface_reset,
-	.write_interrupt	= saa7134_go7007_write_interrupt,
-	.read_interrupt		= saa7134_go7007_read_interrupt,
-	.stream_start		= saa7134_go7007_stream_start,
-	.stream_stop		= saa7134_go7007_stream_stop,
-	.send_firmware		= saa7134_go7007_send_firmware,
-};
-/*(DEBLOBBED)*/
-
-/* --------------------------------------------------------------------------*/
-
-static int saa7134_go7007_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-	struct saa7134_go7007 *saa = to_state(sd);
-	struct saa7134_dev *dev = saa->dev;
-
-	return saa7134_s_std_internal(dev, NULL, norm);
-}
-
-static int saa7134_go7007_queryctrl(struct v4l2_subdev *sd,
-				    struct v4l2_queryctrl *query)
-{
-	return saa7134_queryctrl(NULL, NULL, query);
-}
-static int saa7134_go7007_s_ctrl(struct v4l2_subdev *sd,
-				 struct v4l2_control *ctrl)
-{
-	struct saa7134_go7007 *saa = to_state(sd);
-	struct saa7134_dev *dev = saa->dev;
-	return saa7134_s_ctrl_internal(dev, NULL, ctrl);
-}
-
-static int saa7134_go7007_g_ctrl(struct v4l2_subdev *sd,
-				 struct v4l2_control *ctrl)
-{
-	struct saa7134_go7007 *saa = to_state(sd);
-	struct saa7134_dev *dev = saa->dev;
-	return saa7134_g_ctrl_internal(dev, NULL, ctrl);
-}
-
-/* --------------------------------------------------------------------------*/
-
-static const struct v4l2_subdev_core_ops saa7134_go7007_core_ops = {
-	.g_ctrl = saa7134_go7007_g_ctrl,
-	.s_ctrl = saa7134_go7007_s_ctrl,
-	.queryctrl = saa7134_go7007_queryctrl,
-};
-
-static const struct v4l2_subdev_video_ops saa7134_go7007_video_ops = {
-	.s_std = saa7134_go7007_s_std,
-};
-
-static const struct v4l2_subdev_ops saa7134_go7007_sd_ops = {
-	.core = &saa7134_go7007_core_ops,
-	.video = &saa7134_go7007_video_ops,
-};
-
-/* --------------------------------------------------------------------------*/
-
-
-/********************* Add/remove functions *********************/
-
-static int saa7134_go7007_init(struct saa7134_dev *dev)
-{
-	struct go7007 *go;
-	struct saa7134_go7007 *saa;
-	struct v4l2_subdev *sd;
-
-	printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
-
-	go = go7007_alloc(&board_voyager, &dev->pci->dev);
-	if (go == NULL)
-		return -ENOMEM;
-
-	saa = kzalloc(sizeof(struct saa7134_go7007), GFP_KERNEL);
-	if (saa == NULL) {
-		kfree(go);
-		return -ENOMEM;
-	}
-
-	go->board_id = GO7007_BOARDID_PCI_VOYAGER;
-	snprintf(go->bus_info, sizeof(go->bus_info), "PCI:%s", pci_name(dev->pci));
-	strlcpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
-	go->hpi_ops = &saa7134_go7007_hpi_ops;
-	go->hpi_context = saa;
-	saa->dev = dev;
-
-	/* Init the subdevice interface */
-	sd = &saa->sd;
-	v4l2_subdev_init(sd, &saa7134_go7007_sd_ops);
-	v4l2_set_subdevdata(sd, saa);
-	strncpy(sd->name, "saa7134-go7007", sizeof(sd->name));
-
-	/* Allocate a couple pages for receiving the compressed stream */
-	saa->top = (u8 *)get_zeroed_page(GFP_KERNEL);
-	if (!saa->top)
-		goto allocfail;
-	saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL);
-	if (!saa->bottom)
-		goto allocfail;
-
-	/* Boot the GO7007 */
-	if (go7007_boot_encoder(go, go->board_info->flags &
-					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
-		goto allocfail;
-
-	/* Do any final GO7007 initialization, then register the
-	 * V4L2 and ALSA interfaces */
-	if (go7007_register_encoder(go, go->board_info->num_i2c_devs) < 0)
-		goto allocfail;
-
-	/* Register the subdevice interface with the go7007 device */
-	if (v4l2_device_register_subdev(&go->v4l2_dev, sd) < 0)
-		printk(KERN_INFO "saa7134-go7007: register subdev failed\n");
-
-	dev->empress_dev = &go->vdev;
-
-	go->status = STATUS_ONLINE;
-	return 0;
-
-allocfail:
-	if (saa->top)
-		free_page((unsigned long)saa->top);
-	if (saa->bottom)
-		free_page((unsigned long)saa->bottom);
-	kfree(saa);
-	kfree(go);
-	return -ENOMEM;
-}
-
-static int saa7134_go7007_fini(struct saa7134_dev *dev)
-{
-	struct go7007 *go;
-	struct saa7134_go7007 *saa;
-
-	if (NULL == dev->empress_dev)
-		return 0;
-
-	go = video_get_drvdata(dev->empress_dev);
-	if (go->audio_enabled)
-		go7007_snd_remove(go);
-
-	saa = go->hpi_context;
-	go->status = STATUS_SHUTDOWN;
-	free_page((unsigned long)saa->top);
-	free_page((unsigned long)saa->bottom);
-	v4l2_device_unregister_subdev(&saa->sd);
-	kfree(saa);
-	video_unregister_device(&go->vdev);
-
-	v4l2_device_put(&go->v4l2_dev);
-	dev->empress_dev = NULL;
-
-	return 0;
-}
-
-static struct saa7134_mpeg_ops saa7134_go7007_ops = {
-	.type          = SAA7134_MPEG_GO7007,
-	.init          = saa7134_go7007_init,
-	.fini          = saa7134_go7007_fini,
-	.irq_ts_done   = saa7134_go7007_irq_ts_done,
-};
-
-static int __init saa7134_go7007_mod_init(void)
-{
-	return saa7134_ts_register(&saa7134_go7007_ops);
-}
-
-static void __exit saa7134_go7007_mod_cleanup(void)
-{
-	saa7134_ts_unregister(&saa7134_go7007_ops);
-}
-
-module_init(saa7134_go7007_mod_init);
-module_exit(saa7134_go7007_mod_cleanup);
-
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/go7007/snd-go7007.c linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/snd-go7007.c
--- linux-libre-3.16-gnu/drivers/staging/media/go7007/snd-go7007.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/go7007/snd-go7007.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-
-#include "go7007-priv.h"
-
-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;
-
-module_param_array(index, int, NULL, 0444);
-module_param_array(id, charp, NULL, 0444);
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for the go7007 audio driver");
-MODULE_PARM_DESC(id, "ID string for the go7007 audio driver");
-MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver");
-
-struct go7007_snd {
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	struct snd_pcm_substream *substream;
-	spinlock_t lock;
-	int w_idx;
-	int hw_ptr;
-	int avail;
-	int capturing;
-};
-
-static struct snd_pcm_hardware go7007_snd_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_48000,
-	.rate_min		= 48000,
-	.rate_max		= 48000,
-	.channels_min		= 2,
-	.channels_max		= 2,
-	.buffer_bytes_max	= (128*1024),
-	.period_bytes_min	= 4096,
-	.period_bytes_max	= (128*1024),
-	.periods_min		= 1,
-	.periods_max		= 32,
-};
-
-static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length)
-{
-	struct go7007_snd *gosnd = go->snd_context;
-	struct snd_pcm_runtime *runtime = gosnd->substream->runtime;
-	int frames = bytes_to_frames(runtime, length);
-
-	spin_lock(&gosnd->lock);
-	gosnd->hw_ptr += frames;
-	if (gosnd->hw_ptr >= runtime->buffer_size)
-		gosnd->hw_ptr -= runtime->buffer_size;
-	gosnd->avail += frames;
-	spin_unlock(&gosnd->lock);
-	if (gosnd->w_idx + length > runtime->dma_bytes) {
-		int cpy = runtime->dma_bytes - gosnd->w_idx;
-
-		memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy);
-		length -= cpy;
-		buf += cpy;
-		gosnd->w_idx = 0;
-	}
-	memcpy(runtime->dma_area + gosnd->w_idx, buf, length);
-	gosnd->w_idx += length;
-	spin_lock(&gosnd->lock);
-	if (gosnd->avail < runtime->period_size) {
-		spin_unlock(&gosnd->lock);
-		return;
-	}
-	gosnd->avail -= runtime->period_size;
-	spin_unlock(&gosnd->lock);
-	if (gosnd->capturing)
-		snd_pcm_period_elapsed(gosnd->substream);
-}
-
-static int go7007_snd_hw_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *hw_params)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-	unsigned int bytes;
-
-	bytes = params_buffer_bytes(hw_params);
-	if (substream->runtime->dma_bytes > 0)
-		vfree(substream->runtime->dma_area);
-	substream->runtime->dma_bytes = 0;
-	substream->runtime->dma_area = vmalloc(bytes);
-	if (substream->runtime->dma_area == NULL)
-		return -ENOMEM;
-	substream->runtime->dma_bytes = bytes;
-	go->audio_deliver = parse_audio_stream_data;
-	return 0;
-}
-
-static int go7007_snd_hw_free(struct snd_pcm_substream *substream)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-
-	go->audio_deliver = NULL;
-	if (substream->runtime->dma_bytes > 0)
-		vfree(substream->runtime->dma_area);
-	substream->runtime->dma_bytes = 0;
-	return 0;
-}
-
-static int go7007_snd_capture_open(struct snd_pcm_substream *substream)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-	struct go7007_snd *gosnd = go->snd_context;
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&gosnd->lock, flags);
-	if (gosnd->substream == NULL) {
-		gosnd->substream = substream;
-		substream->runtime->hw = go7007_snd_capture_hw;
-		r = 0;
-	} else
-		r = -EBUSY;
-	spin_unlock_irqrestore(&gosnd->lock, flags);
-	return r;
-}
-
-static int go7007_snd_capture_close(struct snd_pcm_substream *substream)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-	struct go7007_snd *gosnd = go->snd_context;
-
-	gosnd->substream = NULL;
-	return 0;
-}
-
-static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream)
-{
-	return 0;
-}
-
-static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-	struct go7007_snd *gosnd = go->snd_context;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* Just set a flag to indicate we should signal ALSA when
-		 * sound comes in */
-		gosnd->capturing = 1;
-		return 0;
-	case SNDRV_PCM_TRIGGER_STOP:
-		gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
-		gosnd->capturing = 0;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream)
-{
-	struct go7007 *go = snd_pcm_substream_chip(substream);
-	struct go7007_snd *gosnd = go->snd_context;
-
-	return gosnd->hw_ptr;
-}
-
-static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream,
-					unsigned long offset)
-{
-	return vmalloc_to_page(substream->runtime->dma_area + offset);
-}
-
-static struct snd_pcm_ops go7007_snd_capture_ops = {
-	.open		= go7007_snd_capture_open,
-	.close		= go7007_snd_capture_close,
-	.ioctl		= snd_pcm_lib_ioctl,
-	.hw_params	= go7007_snd_hw_params,
-	.hw_free	= go7007_snd_hw_free,
-	.prepare	= go7007_snd_pcm_prepare,
-	.trigger	= go7007_snd_pcm_trigger,
-	.pointer	= go7007_snd_pcm_pointer,
-	.page		= go7007_snd_pcm_page,
-};
-
-static int go7007_snd_free(struct snd_device *device)
-{
-	struct go7007 *go = device->device_data;
-
-	kfree(go->snd_context);
-	go->snd_context = NULL;
-	return 0;
-}
-
-static struct snd_device_ops go7007_snd_device_ops = {
-	.dev_free	= go7007_snd_free,
-};
-
-int go7007_snd_init(struct go7007 *go)
-{
-	static int dev;
-	struct go7007_snd *gosnd;
-	int ret = 0;
-
-	if (dev >= SNDRV_CARDS)
-		return -ENODEV;
-	if (!enable[dev]) {
-		dev++;
-		return -ENOENT;
-	}
-	gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL);
-	if (gosnd == NULL)
-		return -ENOMEM;
-	spin_lock_init(&gosnd->lock);
-	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
-	gosnd->capturing = 0;
-	ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0,
-			   &gosnd->card);
-	if (ret < 0) {
-		kfree(gosnd);
-		return ret;
-	}
-	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
-			&go7007_snd_device_ops);
-	if (ret < 0) {
-		kfree(gosnd);
-		return ret;
-	}
-	ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
-	if (ret < 0) {
-		snd_card_free(gosnd->card);
-		kfree(gosnd);
-		return ret;
-	}
-	strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
-	strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
-	strlcpy(gosnd->card->longname, gosnd->card->shortname,
-			sizeof(gosnd->card->longname));
-
-	gosnd->pcm->private_data = go;
-	snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE,
-			&go7007_snd_capture_ops);
-
-	ret = snd_card_register(gosnd->card);
-	if (ret < 0) {
-		snd_card_free(gosnd->card);
-		kfree(gosnd);
-		return ret;
-	}
-
-	gosnd->substream = NULL;
-	go->snd_context = gosnd;
-	v4l2_device_get(&go->v4l2_dev);
-	++dev;
-
-	return 0;
-}
-EXPORT_SYMBOL(go7007_snd_init);
-
-int go7007_snd_remove(struct go7007 *go)
-{
-	struct go7007_snd *gosnd = go->snd_context;
-
-	snd_card_disconnect(gosnd->card);
-	snd_card_free_when_closed(gosnd->card);
-	v4l2_device_put(&go->v4l2_dev);
-	return 0;
-}
-EXPORT_SYMBOL(go7007_snd_remove);
-
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -29,20 +29,10 @@ source "drivers/staging/media/davinci_vp
 
 source "drivers/staging/media/dt3155v4l/Kconfig"
 
-source "drivers/staging/media/go7007/Kconfig"
-
-source "drivers/staging/media/msi3101/Kconfig"
-
 source "drivers/staging/media/omap24xx/Kconfig"
 
-source "drivers/staging/media/sn9c102/Kconfig"
-
-source "drivers/staging/media/solo6x10/Kconfig"
-
 source "drivers/staging/media/omap4iss/Kconfig"
 
-source "drivers/staging/media/rtl2832u_sdr/Kconfig"
-
 # Keep LIRC at the end, as it has sub-menus
 source "drivers/staging/media/lirc/Kconfig"
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_igorplugusb.c linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_igorplugusb.c
--- linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_igorplugusb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_igorplugusb.c	2014-09-28 17:29:07.000000000 -0400
@@ -209,12 +209,6 @@ static int unregister_from_lirc(struct i
 	struct lirc_driver *d;
 	int devnum;
 
-	if (!ir) {
-		dev_err(&ir->usbdev->dev,
-			"%s: called with NULL device struct!\n", __func__);
-		return -EINVAL;
-	}
-
 	devnum = ir->devnum;
 	d = ir->d;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_imon.c linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_imon.c
--- linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_imon.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_imon.c	2014-09-28 17:29:07.000000000 -0400
@@ -189,6 +189,7 @@ MODULE_PARM_DESC(debug, "Debug messages:
 static void free_imon_context(struct imon_context *context)
 {
 	struct device *dev = context->driver->dev;
+
 	usb_free_urb(context->tx_urb);
 	usb_free_urb(context->rx_urb);
 	lirc_buffer_free(context->driver->rbuf);
@@ -481,8 +482,6 @@ static void usb_tx_callback(struct urb *
 	/* notify waiters that write has finished */
 	atomic_set(&context->tx.busy, 0);
 	complete(&context->tx.finished);
-
-	return;
 }
 
 /**
@@ -547,7 +546,6 @@ static void ir_close(void *data)
 	}
 
 	mutex_unlock(&context->ctx_lock);
-	return;
 }
 
 /**
@@ -572,7 +570,6 @@ static void submit_data(struct imon_cont
 
 	lirc_buffer_write(context->driver->rbuf, buf);
 	wake_up(&context->driver->rbuf->wait_poll);
-	return;
 }
 
 static inline int tv2int(const struct timeval *a, const struct timeval *b)
@@ -656,6 +653,7 @@ static void imon_incoming_packet(struct
 		mask = 0x80;
 		for (bit = 0; bit < 8; ++bit) {
 			int curr_bit = !(buf[octet] & mask);
+
 			if (curr_bit != context->rx.prev_bit) {
 				if (context->rx.count) {
 					submit_data(context);
@@ -707,8 +705,6 @@ static void usb_rx_callback(struct urb *
 	}
 
 	usb_submit_urb(context->rx_urb, GFP_ATOMIC);
-
-	return;
 }
 
 /**
@@ -775,6 +771,7 @@ static int imon_probe(struct usb_interfa
 		struct usb_endpoint_descriptor *ep;
 		int ep_dir;
 		int ep_type;
+
 		ep = &iface_desc->endpoint[i].desc;
 		ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
 		ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_parallel.c linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_parallel.c
--- linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_parallel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_parallel.c	2014-09-28 17:29:07.000000000 -0400
@@ -169,23 +169,22 @@ static unsigned int init_lirc_timer(void
 			newtimer = (1000000*count)/timeelapsed;
 			pr_info("%u Hz timer detected\n", newtimer);
 			return newtimer;
-		}  else {
-			newtimer = (1000000*count)/timeelapsed;
-			if (abs(newtimer - default_timer) > default_timer/10) {
-				/* bad timer */
-				pr_notice("bad timer: %u Hz\n", newtimer);
-				pr_notice("using default timer: %u Hz\n",
-					  default_timer);
-				return default_timer;
-			} else {
-				pr_info("%u Hz timer detected\n", newtimer);
-				return newtimer; /* use detected value */
-			}
 		}
-	} else {
-		pr_notice("no timer detected\n");
-		return 0;
+		newtimer = (1000000*count)/timeelapsed;
+		if (abs(newtimer - default_timer) > default_timer/10) {
+			/* bad timer */
+			pr_notice("bad timer: %u Hz\n", newtimer);
+			pr_notice("using default timer: %u Hz\n",
+				  default_timer);
+			return default_timer;
+		} else {
+			pr_info("%u Hz timer detected\n", newtimer);
+			return newtimer; /* use detected value */
+		}
 	}
+
+	pr_notice("no timer detected\n");
+	return 0;
 }
 
 static int lirc_claim(void)
@@ -661,7 +660,8 @@ static int __init lirc_parallel_init(voi
 		goto exit_device_put;
 	}
 	ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
-					   pf, kf, lirc_lirc_irq_handler, 0, NULL);
+					   pf, kf, lirc_lirc_irq_handler, 0,
+					   NULL);
 	parport_put_port(pport);
 	if (ppdevice == NULL) {
 		pr_notice("parport_register_device() failed\n");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_serial.c linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_serial.c
--- linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_serial.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_serial.c	2014-09-28 17:29:07.000000000 -0400
@@ -782,7 +782,7 @@ static int lirc_serial_probe(struct plat
 {
 	int i, nlow, nhigh, result;
 
-	result = request_irq(irq, lirc_irq_handler,
+	result = devm_request_irq(&dev->dev, irq, lirc_irq_handler,
 			     (share_irq ? IRQF_SHARED : 0),
 			     LIRC_DRIVER_NAME, (void *)&hardware);
 	if (result < 0) {
@@ -800,22 +800,22 @@ static int lirc_serial_probe(struct plat
 	 * for the NSLU2 it's done in boot code.
 	 */
 	if (((iommap != 0)
-	     && (request_mem_region(iommap, 8 << ioshift,
-				    LIRC_DRIVER_NAME) == NULL))
+	     && (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift,
+					 LIRC_DRIVER_NAME) == NULL))
 	   || ((iommap == 0)
-	       && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) {
+	       && (devm_request_region(&dev->dev, io, 8,
+				       LIRC_DRIVER_NAME) == 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");
-		result = -EBUSY;
-		goto exit_free_irq;
+		return -EBUSY;
 	}
 
 	result = hardware_init_port();
 	if (result < 0)
-		goto exit_release_region;
+		return result;
 
 	/* Initialize pulse/space widths */
 	init_timing_params(duty_cycle, freq);
@@ -847,28 +847,6 @@ static int lirc_serial_probe(struct plat
 
 	dprintk("Interrupt %d, port %04x obtained\n", irq, io);
 	return 0;
-
-exit_release_region:
-	if (iommap != 0)
-		release_mem_region(iommap, 8 << ioshift);
-	else
-		release_region(io, 8);
-exit_free_irq:
-	free_irq(irq, (void *)&hardware);
-
-	return result;
-}
-
-static int lirc_serial_remove(struct platform_device *dev)
-{
-	free_irq(irq, (void *)&hardware);
-
-	if (iommap != 0)
-		release_mem_region(iommap, 8 << ioshift);
-	else
-		release_region(io, 8);
-
-	return 0;
 }
 
 static int set_use_inc(void *data)
@@ -1081,7 +1059,6 @@ static int lirc_serial_resume(struct pla
 
 static struct platform_driver lirc_serial_driver = {
 	.probe		= lirc_serial_probe,
-	.remove		= lirc_serial_remove,
 	.suspend	= lirc_serial_suspend,
 	.resume		= lirc_serial_resume,
 	.driver		= {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_sir.c linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_sir.c
--- linux-libre-3.16-gnu/drivers/staging/media/lirc/lirc_sir.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/lirc/lirc_sir.c	2014-09-28 17:29:07.000000000 -0400
@@ -55,13 +55,6 @@
 #include <asm/irq.h>
 #include <linux/fcntl.h>
 #include <linux/platform_device.h>
-#ifdef LIRC_ON_SA1100
-#include <asm/hardware.h>
-#ifdef CONFIG_SA1100_COLLIE
-#include <asm/arch/tc35143.h>
-#include <asm/ucb1200.h>
-#endif
-#endif
 
 #include <linux/timer.h>
 
@@ -94,35 +87,6 @@ static void init_act200(void);
 static void init_act220(void);
 #endif
 
-/*** SA1100 ***/
-#ifdef LIRC_ON_SA1100
-struct sa1100_ser2_registers {
-	/* HSSP control register */
-	unsigned char hscr0;
-	/* UART registers */
-	unsigned char utcr0;
-	unsigned char utcr1;
-	unsigned char utcr2;
-	unsigned char utcr3;
-	unsigned char utcr4;
-	unsigned char utdr;
-	unsigned char utsr0;
-	unsigned char utsr1;
-} sr;
-
-static int irq = IRQ_Ser2ICP;
-
-#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0
-
-/* pulse/space ratio of 50/50 */
-static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
-/* 1000000/freq-pulse_width */
-static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
-static unsigned int freq = 38000;      /* modulation frequency */
-static unsigned int duty_cycle = 50;   /* duty cycle of 50% */
-
-#endif
-
 #define RBUF_LEN 1024
 #define WBUF_LEN 1024
 
@@ -205,17 +169,6 @@ static void drop_hardware(void);
 static int init_port(void);
 static void drop_port(void);
 
-#ifdef LIRC_ON_SA1100
-static void on(void)
-{
-	PPSR |= PPC_TXD2;
-}
-
-static void off(void)
-{
-	PPSR &= ~PPC_TXD2;
-}
-#else
 static inline unsigned int sinp(int offset)
 {
 	return inb(io + offset);
@@ -225,7 +178,6 @@ static inline void soutp(int offset, int
 {
 	outb(value, io + offset);
 }
-#endif
 
 #ifndef MAX_UDELAY_MS
 #define MAX_UDELAY_US 5000
@@ -305,10 +257,6 @@ static ssize_t lirc_write(struct file *f
 	if (IS_ERR(tx_buf))
 		return PTR_ERR(tx_buf);
 	i = 0;
-#ifdef LIRC_ON_SA1100
-	/* disable receiver */
-	Ser2UTCR3 = 0;
-#endif
 	local_irq_save(flags);
 	while (1) {
 		if (i >= count)
@@ -323,15 +271,6 @@ static ssize_t lirc_write(struct file *f
 		i++;
 	}
 	local_irq_restore(flags);
-#ifdef LIRC_ON_SA1100
-	off();
-	udelay(1000); /* wait 1ms for IR diode to recover */
-	Ser2UTCR3 = 0;
-	/* clear status register to prevent unwanted interrupts */
-	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-	/* enable receiver */
-	Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE;
-#endif
 	kfree(tx_buf);
 	return count;
 }
@@ -341,25 +280,12 @@ static long lirc_ioctl(struct file *file
 	u32 __user *uptr = (u32 __user *)arg;
 	int retval = 0;
 	u32 value = 0;
-#ifdef LIRC_ON_SA1100
-
-	if (cmd == LIRC_GET_FEATURES)
-		value = LIRC_CAN_SEND_PULSE |
-			LIRC_CAN_SET_SEND_DUTY_CYCLE |
-			LIRC_CAN_SET_SEND_CARRIER |
-			LIRC_CAN_REC_MODE2;
-	else if (cmd == LIRC_GET_SEND_MODE)
-		value = LIRC_MODE_PULSE;
-	else if (cmd == LIRC_GET_REC_MODE)
-		value = LIRC_MODE_MODE2;
-#else
 	if (cmd == LIRC_GET_FEATURES)
 		value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
 	else if (cmd == LIRC_GET_SEND_MODE)
 		value = LIRC_MODE_PULSE;
 	else if (cmd == LIRC_GET_REC_MODE)
 		value = LIRC_MODE_MODE2;
-#endif
 
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
@@ -372,37 +298,6 @@ static long lirc_ioctl(struct file *file
 	case LIRC_SET_REC_MODE:
 		retval = get_user(value, uptr);
 		break;
-#ifdef LIRC_ON_SA1100
-	case LIRC_SET_SEND_DUTY_CYCLE:
-		retval = get_user(value, uptr);
-		if (retval)
-			return retval;
-		if (value <= 0 || value > 100)
-			return -EINVAL;
-		/* (value/100)*(1000000/freq) */
-		duty_cycle = value;
-		pulse_width = (unsigned long) duty_cycle*10000/freq;
-		space_width = (unsigned long) 1000000L/freq-pulse_width;
-		if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
-			pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
-		if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
-			space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
-		break;
-	case LIRC_SET_SEND_CARRIER:
-		retval = get_user(value, uptr);
-		if (retval)
-			return retval;
-		if (value > 500000 || value < 20000)
-			return -EINVAL;
-		freq = value;
-		pulse_width = (unsigned long) duty_cycle*10000/freq;
-		space_width = (unsigned long) 1000000L/freq-pulse_width;
-		if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
-			pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
-		if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
-			space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
-		break;
-#endif
 	default:
 		retval = -ENOIOCTLCMD;
 
@@ -539,10 +434,8 @@ static void sir_timeout(unsigned long da
 	/* avoid interference with interrupt */
 	spin_lock_irqsave(&timer_lock, flags);
 	if (last_value) {
-#ifndef LIRC_ON_SA1100
 		/* clear unread bits in UART and restart */
 		outb(UART_FCR_CLEAR_RCVR, io + UART_FCR);
-#endif
 		/* determine 'virtual' pulse end: */
 		pulse_end = delta(&last_tv, &last_intr_tv);
 		dprintk("timeout add %d for %lu usec\n", last_value, pulse_end);
@@ -558,62 +451,6 @@ static irqreturn_t sir_interrupt(int irq
 	unsigned char data;
 	struct timeval curr_tv;
 	static unsigned long deltv;
-#ifdef LIRC_ON_SA1100
-	int status;
-	static int n;
-
-	status = Ser2UTSR0;
-	/*
-	 * Deal with any receive errors first.  The bytes in error may be
-	 * the only bytes in the receive FIFO, so we do this first.
-	 */
-	while (status & UTSR0_EIF) {
-		int bstat;
-
-		if (debug) {
-			dprintk("EIF\n");
-			bstat = Ser2UTSR1;
-
-			if (bstat & UTSR1_FRE)
-				dprintk("frame error\n");
-			if (bstat & UTSR1_ROR)
-				dprintk("receive fifo overrun\n");
-			if (bstat & UTSR1_PRE)
-				dprintk("parity error\n");
-		}
-
-		bstat = Ser2UTDR;
-		n++;
-		status = Ser2UTSR0;
-	}
-
-	if (status & (UTSR0_RFS | UTSR0_RID)) {
-		do_gettimeofday(&curr_tv);
-		deltv = delta(&last_tv, &curr_tv);
-		do {
-			data = Ser2UTDR;
-			dprintk("%d data: %u\n", n, (unsigned int) data);
-			n++;
-		} while (status & UTSR0_RID && /* do not empty fifo in order to
-						* get UTSR0_RID in any case */
-		      Ser2UTSR1 & UTSR1_RNE); /* data ready */
-
-		if (status&UTSR0_RID) {
-			add_read_queue(0 , deltv - n * TIME_CONST); /*space*/
-			add_read_queue(1, n * TIME_CONST); /*pulse*/
-			n = 0;
-			last_tv = curr_tv;
-		}
-	}
-
-	if (status & UTSR0_TFS)
-		pr_err("transmit fifo not full, shouldn't happen\n");
-
-	/* We must clear certain bits. */
-	status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-	if (status)
-		Ser2UTSR0 = status;
-#else
 	unsigned long deltintrtv;
 	unsigned long flags;
 	int iir, lsr;
@@ -698,44 +535,9 @@ static irqreturn_t sir_interrupt(int irq
 			break;
 		}
 	}
-#endif
 	return IRQ_RETVAL(IRQ_HANDLED);
 }
 
-#ifdef LIRC_ON_SA1100
-static void send_pulse(unsigned long length)
-{
-	unsigned long k, delay;
-	int flag;
-
-	if (length == 0)
-		return;
-	/*
-	 * this won't give us the carrier frequency we really want
-	 * due to integer arithmetic, but we can accept this inaccuracy
-	 */
-
-	for (k = flag = 0; k < length; k += delay, flag = !flag) {
-		if (flag) {
-			off();
-			delay = space_width;
-		} else {
-			on();
-			delay = pulse_width;
-		}
-		safe_udelay(delay);
-	}
-	off();
-}
-
-static void send_space(unsigned long length)
-{
-	if (length == 0)
-		return;
-	off();
-	safe_udelay(length);
-}
-#else
 static void send_space(unsigned long len)
 {
 	safe_udelay(len);
@@ -755,31 +557,6 @@ static void send_pulse(unsigned long len
 			;
 	}
 }
-#endif
-
-#ifdef CONFIG_SA1100_COLLIE
-static int sa1100_irda_set_power_collie(int state)
-{
-	if (state) {
-		/*
-		 *  0 - off
-		 *  1 - short range, lowest power
-		 *  2 - medium range, medium power
-		 *  3 - maximum range, high power
-		 */
-		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,
-					 TC35143_IODIR_OUTPUT);
-		ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW);
-		udelay(100);
-	} else {
-		/* OFF */
-		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,
-					 TC35143_IODIR_OUTPUT);
-		ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH);
-	}
-	return 0;
-}
-#endif
 
 static int init_hardware(void)
 {
@@ -787,51 +564,7 @@ static int init_hardware(void)
 
 	spin_lock_irqsave(&hardware_lock, flags);
 	/* reset UART */
-#ifdef LIRC_ON_SA1100
-#ifdef CONFIG_SA1100_COLLIE
-	sa1100_irda_set_power_collie(3);	/* power on */
-#endif
-	sr.hscr0 = Ser2HSCR0;
-
-	sr.utcr0 = Ser2UTCR0;
-	sr.utcr1 = Ser2UTCR1;
-	sr.utcr2 = Ser2UTCR2;
-	sr.utcr3 = Ser2UTCR3;
-	sr.utcr4 = Ser2UTCR4;
-
-	sr.utdr = Ser2UTDR;
-	sr.utsr0 = Ser2UTSR0;
-	sr.utsr1 = Ser2UTSR1;
-
-	/* configure GPIO */
-	/* output */
-	PPDR |= PPC_TXD2;
-	PSDR |= PPC_TXD2;
-	/* set output to 0 */
-	off();
-
-	/* Enable HP-SIR modulation, and ensure that the port is disabled. */
-	Ser2UTCR3 = 0;
-	Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP);
-
-	/* clear status register to prevent unwanted interrupts */
-	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-
-	/* 7N1 */
-	Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData;
-	/* 115200 */
-	Ser2UTCR1 = 0;
-	Ser2UTCR2 = 1;
-	/* use HPSIR, 1.6 usec pulses */
-	Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us;
-
-	/* enable receiver, receive fifo interrupt */
-	Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE;
-
-	/* clear status register to prevent unwanted interrupts */
-	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-
-#elif defined(LIRC_SIR_TEKRAM)
+#if defined(LIRC_SIR_TEKRAM)
 	/* disable FIFO */
 	soutp(UART_FCR,
 	      UART_FCR_CLEAR_RCVR|
@@ -927,23 +660,9 @@ static void drop_hardware(void)
 
 	spin_lock_irqsave(&hardware_lock, flags);
 
-#ifdef LIRC_ON_SA1100
-	Ser2UTCR3 = 0;
-
-	Ser2UTCR0 = sr.utcr0;
-	Ser2UTCR1 = sr.utcr1;
-	Ser2UTCR2 = sr.utcr2;
-	Ser2UTCR4 = sr.utcr4;
-	Ser2UTCR3 = sr.utcr3;
-
-	Ser2HSCR0 = sr.hscr0;
-#ifdef CONFIG_SA1100_COLLIE
-	sa1100_irda_set_power_collie(0);	/* power off */
-#endif
-#else
 	/* turn off interrupts */
 	outb(0, io + UART_IER);
-#endif
+
 	spin_unlock_irqrestore(&hardware_lock, flags);
 }
 
@@ -954,24 +673,18 @@ static int init_port(void)
 	int retval;
 
 	/* get I/O port access and IRQ line */
-#ifndef LIRC_ON_SA1100
 	if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
 		pr_err("i/o port 0x%.4x already in use.\n", io);
 		return -EBUSY;
 	}
-#endif
 	retval = request_irq(irq, sir_interrupt, 0,
 			     LIRC_DRIVER_NAME, NULL);
 	if (retval < 0) {
-#               ifndef LIRC_ON_SA1100
 		release_region(io, 8);
-#               endif
 		pr_err("IRQ %d already in use.\n", irq);
 		return retval;
 	}
-#ifndef LIRC_ON_SA1100
 	pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq);
-#endif
 
 	init_timer(&timerlist);
 	timerlist.function = sir_timeout;
@@ -984,9 +697,7 @@ static void drop_port(void)
 {
 	free_irq(irq, NULL);
 	del_timer_sync(&timerlist);
-#ifndef LIRC_ON_SA1100
 	release_region(io, 8);
-#endif
 }
 
 #ifdef LIRC_SIR_ACTISYS_ACT200L
@@ -1284,9 +995,6 @@ module_exit(lirc_sir_exit);
 #ifdef LIRC_SIR_TEKRAM
 MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210");
 MODULE_AUTHOR("Christoph Bartelmus");
-#elif defined(LIRC_ON_SA1100)
-MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor");
-MODULE_AUTHOR("Christoph Bartelmus");
 #elif defined(LIRC_SIR_ACTISYS_ACT200L)
 MODULE_DESCRIPTION("LIRC driver for Actisys Act200L");
 MODULE_AUTHOR("Karl Bongers");
@@ -1299,10 +1007,6 @@ MODULE_AUTHOR("Milan Pikula");
 #endif
 MODULE_LICENSE("GPL");
 
-#ifdef LIRC_ON_SA1100
-module_param(irq, int, S_IRUGO);
-MODULE_PARM_DESC(irq, "Interrupt (16)");
-#else
 module_param(io, int, S_IRUGO);
 MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
 
@@ -1311,7 +1015,6 @@ MODULE_PARM_DESC(irq, "Interrupt (4 or 3
 
 module_param(threshold, int, S_IRUGO);
 MODULE_PARM_DESC(threshold, "space detection threshold (3)");
-#endif
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Enable debugging messages");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -2,14 +2,9 @@ obj-$(CONFIG_DVB_AS102)		+= as102/
 obj-$(CONFIG_I2C_BCM2048)	+= bcm2048/
 obj-$(CONFIG_DVB_CXD2099)	+= cxd2099/
 obj-$(CONFIG_LIRC_STAGING)	+= lirc/
-obj-$(CONFIG_SOLO6X10)		+= solo6x10/
 obj-$(CONFIG_VIDEO_DT3155)	+= dt3155v4l/
-obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
-obj-$(CONFIG_USB_MSI3101)	+= msi3101/
 obj-$(CONFIG_VIDEO_DM365_VPFE)	+= davinci_vpfe/
 obj-$(CONFIG_VIDEO_OMAP4)	+= omap4iss/
-obj-$(CONFIG_USB_SN9C102)       += sn9c102/
 obj-$(CONFIG_VIDEO_OMAP2)       += omap24xx/
 obj-$(CONFIG_VIDEO_TCM825X)     += omap24xx/
-obj-$(CONFIG_DVB_RTL2832_SDR)	+= rtl2832u_sdr/
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/msi3101/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/msi3101/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-config USB_MSI3101
-	tristate "Mirics MSi3101 SDR Dongle"
-	depends on USB && VIDEO_DEV && VIDEO_V4L2 && SPI
-	select VIDEOBUF2_CORE
-	select VIDEOBUF2_VMALLOC
-	select MEDIA_TUNER_MSI001
-
-config MEDIA_TUNER_MSI001
-	tristate "Mirics MSi001"
-	depends on VIDEO_V4L2 && SPI
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/msi3101/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/msi3101/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-obj-$(CONFIG_USB_MSI3101)             += sdr-msi3101.o
-obj-$(CONFIG_MEDIA_TUNER_MSI001)      += msi001.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/msi3101/msi001.c linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/msi001.c
--- linux-libre-3.16-gnu/drivers/staging/media/msi3101/msi001.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/msi001.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,500 +0,0 @@
-/*
- * Mirics MSi001 silicon tuner driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/gcd.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-static const struct v4l2_frequency_band bands[] = {
-	{
-		.type = V4L2_TUNER_RF,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =   49000000,
-		.rangehigh  =  263000000,
-	}, {
-		.type = V4L2_TUNER_RF,
-		.index = 1,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =  390000000,
-		.rangehigh  =  960000000,
-	},
-};
-
-struct msi001 {
-	struct spi_device *spi;
-	struct v4l2_subdev sd;
-
-	/* Controls */
-	struct v4l2_ctrl_handler hdl;
-	struct v4l2_ctrl *bandwidth_auto;
-	struct v4l2_ctrl *bandwidth;
-	struct v4l2_ctrl *lna_gain;
-	struct v4l2_ctrl *mixer_gain;
-	struct v4l2_ctrl *if_gain;
-
-	unsigned int f_tuner;
-};
-
-static inline struct msi001 *sd_to_msi001(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct msi001, sd);
-}
-
-static int msi001_wreg(struct msi001 *s, u32 data)
-{
-	/* Register format: 4 bits addr + 20 bits value */
-	return spi_write(s->spi, &data, 3);
-};
-
-static int msi001_set_gain(struct msi001 *s, int lna_gain, int mixer_gain,
-		int if_gain)
-{
-	int ret;
-	u32 reg;
-	dev_dbg(&s->spi->dev, "%s: lna=%d mixer=%d if=%d\n", __func__,
-			lna_gain, mixer_gain, if_gain);
-
-	reg = 1 << 0;
-	reg |= (59 - if_gain) << 4;
-	reg |= 0 << 10;
-	reg |= (1 - mixer_gain) << 12;
-	reg |= (1 - lna_gain) << 13;
-	reg |= 4 << 14;
-	reg |= 0 << 17;
-	ret = msi001_wreg(s, reg);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
-	return ret;
-};
-
-static int msi001_set_tuner(struct msi001 *s)
-{
-	int ret, i;
-	unsigned int n, m, thresh, frac, vco_step, tmp, f_if1;
-	u32 reg;
-	u64 f_vco, tmp64;
-	u8 mode, filter_mode, lo_div;
-	static const struct {
-		u32 rf;
-		u8 mode;
-		u8 lo_div;
-	} band_lut[] = {
-		{ 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */
-		{108000000, 0x42, 32}, /* VHF_MODE */
-		{330000000, 0x44, 16}, /* B3_MODE */
-		{960000000, 0x48,  4}, /* B45_MODE */
-		{      ~0U, 0x50,  2}, /* BL_MODE */
-	};
-	static const struct {
-		u32 freq;
-		u8 filter_mode;
-	} if_freq_lut[] = {
-		{      0, 0x03}, /* Zero IF */
-		{ 450000, 0x02}, /* 450 kHz IF */
-		{1620000, 0x01}, /* 1.62 MHz IF */
-		{2048000, 0x00}, /* 2.048 MHz IF */
-	};
-	static const struct {
-		u32 freq;
-		u8 val;
-	} bandwidth_lut[] = {
-		{ 200000, 0x00}, /* 200 kHz */
-		{ 300000, 0x01}, /* 300 kHz */
-		{ 600000, 0x02}, /* 600 kHz */
-		{1536000, 0x03}, /* 1.536 MHz */
-		{5000000, 0x04}, /* 5 MHz */
-		{6000000, 0x05}, /* 6 MHz */
-		{7000000, 0x06}, /* 7 MHz */
-		{8000000, 0x07}, /* 8 MHz */
-	};
-
-	unsigned int f_rf = s->f_tuner;
-
-	/*
-	 * bandwidth (Hz)
-	 * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
-	 */
-	unsigned int bandwidth;
-
-	/*
-	 * intermediate frequency (Hz)
-	 * 0, 450000, 1620000, 2048000
-	 */
-	unsigned int f_if = 0;
-	#define F_REF 24000000
-	#define R_REF 4
-	#define F_OUT_STEP 1
-
-	dev_dbg(&s->spi->dev,
-			"%s: f_rf=%d f_if=%d\n",
-			__func__, f_rf, f_if);
-
-	for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
-		if (f_rf <= band_lut[i].rf) {
-			mode = band_lut[i].mode;
-			lo_div = band_lut[i].lo_div;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(band_lut)) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* AM_MODE is upconverted */
-	if ((mode >> 0) & 0x1)
-		f_if1 =  5 * F_REF;
-	else
-		f_if1 =  0;
-
-	for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
-		if (f_if == if_freq_lut[i].freq) {
-			filter_mode = if_freq_lut[i].filter_mode;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(if_freq_lut)) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* filters */
-	bandwidth = s->bandwidth->val;
-	bandwidth = clamp(bandwidth, 200000U, 8000000U);
-
-	for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
-		if (bandwidth <= bandwidth_lut[i].freq) {
-			bandwidth = bandwidth_lut[i].val;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(bandwidth_lut)) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	s->bandwidth->val = bandwidth_lut[i].freq;
-
-	dev_dbg(&s->spi->dev, "%s: bandwidth selected=%d\n",
-			__func__, bandwidth_lut[i].freq);
-
-	f_vco = (u64) (f_rf + f_if + f_if1) * lo_div;
-	tmp64 = f_vco;
-	m = do_div(tmp64, F_REF * R_REF);
-	n = (unsigned int) tmp64;
-
-	vco_step = F_OUT_STEP * lo_div;
-	thresh = (F_REF * R_REF) / vco_step;
-	frac = 1ul * thresh * m / (F_REF * R_REF);
-
-	/* Find out greatest common divisor and divide to smaller. */
-	tmp = gcd(thresh, frac);
-	thresh /= tmp;
-	frac /= tmp;
-
-	/* Force divide to reg max. Resolution will be reduced. */
-	tmp = DIV_ROUND_UP(thresh, 4095);
-	thresh = DIV_ROUND_CLOSEST(thresh, tmp);
-	frac = DIV_ROUND_CLOSEST(frac, tmp);
-
-	/* calc real RF set */
-	tmp = 1ul * F_REF * R_REF * n;
-	tmp += 1ul * F_REF * R_REF * frac / thresh;
-	tmp /= lo_div;
-
-	dev_dbg(&s->spi->dev,
-			"%s: rf=%u:%u n=%d thresh=%d frac=%d\n",
-				__func__, f_rf, tmp, n, thresh, frac);
-
-	ret = msi001_wreg(s, 0x00000e);
-	if (ret)
-		goto err;
-
-	ret = msi001_wreg(s, 0x000003);
-	if (ret)
-		goto err;
-
-	reg = 0 << 0;
-	reg |= mode << 4;
-	reg |= filter_mode << 12;
-	reg |= bandwidth << 14;
-	reg |= 0x02 << 17;
-	reg |= 0x00 << 20;
-	ret = msi001_wreg(s, reg);
-	if (ret)
-		goto err;
-
-	reg = 5 << 0;
-	reg |= thresh << 4;
-	reg |= 1 << 19;
-	reg |= 1 << 21;
-	ret = msi001_wreg(s, reg);
-	if (ret)
-		goto err;
-
-	reg = 2 << 0;
-	reg |= frac << 4;
-	reg |= n << 16;
-	ret = msi001_wreg(s, reg);
-	if (ret)
-		goto err;
-
-	ret = msi001_set_gain(s, s->lna_gain->cur.val, s->mixer_gain->cur.val,
-			s->if_gain->cur.val);
-	if (ret)
-		goto err;
-
-	reg = 6 << 0;
-	reg |= 63 << 4;
-	reg |= 4095 << 10;
-	ret = msi001_wreg(s, reg);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret);
-	return ret;
-};
-
-static int msi001_s_power(struct v4l2_subdev *sd, int on)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	int ret;
-	dev_dbg(&s->spi->dev, "%s: on=%d\n", __func__, on);
-
-	if (on)
-		ret = 0;
-	else
-		ret = msi001_wreg(s, 0x000000);
-
-	return ret;
-}
-
-static const struct v4l2_subdev_core_ops msi001_core_ops = {
-	.s_power                  = msi001_s_power,
-};
-
-static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
-
-	strlcpy(v->name, "Mirics MSi001", sizeof(v->name));
-	v->type = V4L2_TUNER_RF;
-	v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-	v->rangelow =    49000000;
-	v->rangehigh =  960000000;
-
-	return 0;
-}
-
-static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index);
-	return 0;
-}
-
-static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	dev_dbg(&s->spi->dev, "%s: tuner=%d\n", __func__, f->tuner);
-	f->frequency = s->f_tuner;
-	return 0;
-}
-
-static int msi001_s_frequency(struct v4l2_subdev *sd,
-		const struct v4l2_frequency *f)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	unsigned int band;
-	dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d frequency=%u\n",
-			__func__, f->tuner, f->type, f->frequency);
-
-	if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2))
-		band = 0;
-	else
-		band = 1;
-	s->f_tuner = clamp_t(unsigned int, f->frequency,
-			bands[band].rangelow, bands[band].rangehigh);
-
-	return msi001_set_tuner(s);
-}
-
-static int msi001_enum_freq_bands(struct v4l2_subdev *sd,
-		struct v4l2_frequency_band *band)
-{
-	struct msi001 *s = sd_to_msi001(sd);
-	dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d index=%d\n",
-			__func__, band->tuner, band->type, band->index);
-
-	if (band->index >= ARRAY_SIZE(bands))
-		return -EINVAL;
-
-	band->capability = bands[band->index].capability;
-	band->rangelow = bands[band->index].rangelow;
-	band->rangehigh = bands[band->index].rangehigh;
-
-	return 0;
-}
-
-static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
-	.g_tuner                  = msi001_g_tuner,
-	.s_tuner                  = msi001_s_tuner,
-	.g_frequency              = msi001_g_frequency,
-	.s_frequency              = msi001_s_frequency,
-	.enum_freq_bands          = msi001_enum_freq_bands,
-};
-
-static const struct v4l2_subdev_ops msi001_ops = {
-	.core                     = &msi001_core_ops,
-	.tuner                    = &msi001_tuner_ops,
-};
-
-static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct msi001 *s = container_of(ctrl->handler, struct msi001, hdl);
-
-	int ret;
-	dev_dbg(&s->spi->dev,
-			"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
-			__func__, ctrl->id, ctrl->name, ctrl->val,
-			ctrl->minimum, ctrl->maximum, ctrl->step);
-
-	switch (ctrl->id) {
-	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
-	case V4L2_CID_RF_TUNER_BANDWIDTH:
-		ret = msi001_set_tuner(s);
-		break;
-	case  V4L2_CID_RF_TUNER_LNA_GAIN:
-		ret = msi001_set_gain(s, s->lna_gain->val,
-				s->mixer_gain->cur.val, s->if_gain->cur.val);
-		break;
-	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
-		ret = msi001_set_gain(s, s->lna_gain->cur.val,
-				s->mixer_gain->val, s->if_gain->cur.val);
-		break;
-	case  V4L2_CID_RF_TUNER_IF_GAIN:
-		ret = msi001_set_gain(s, s->lna_gain->cur.val,
-				s->mixer_gain->cur.val, s->if_gain->val);
-		break;
-	default:
-		dev_dbg(&s->spi->dev, "%s: unkown control %d\n",
-				__func__, ctrl->id);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct v4l2_ctrl_ops msi001_ctrl_ops = {
-	.s_ctrl                   = msi001_s_ctrl,
-};
-
-static int msi001_probe(struct spi_device *spi)
-{
-	struct msi001 *s;
-	int ret;
-	dev_dbg(&spi->dev, "%s:\n", __func__);
-
-	s = kzalloc(sizeof(struct msi001), GFP_KERNEL);
-	if (s == NULL) {
-		ret = -ENOMEM;
-		dev_dbg(&spi->dev, "Could not allocate memory for msi001\n");
-		goto err_kfree;
-	}
-
-	s->spi = spi;
-	s->f_tuner = bands[0].rangelow;
-	v4l2_spi_subdev_init(&s->sd, spi, &msi001_ops);
-
-	/* Register controls */
-	v4l2_ctrl_handler_init(&s->hdl, 5);
-	s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
-			V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
-	s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
-			V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000);
-	v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
-	s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
-			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1);
-	s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
-			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 1, 1, 1);
-	s->if_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops,
-			V4L2_CID_RF_TUNER_IF_GAIN, 0, 59, 1, 0);
-	if (s->hdl.error) {
-		ret = s->hdl.error;
-		dev_err(&s->spi->dev, "Could not initialize controls\n");
-		/* control init failed, free handler */
-		goto err_ctrl_handler_free;
-	}
-
-	s->sd.ctrl_handler = &s->hdl;
-	return 0;
-
-err_ctrl_handler_free:
-	v4l2_ctrl_handler_free(&s->hdl);
-err_kfree:
-	kfree(s);
-	return ret;
-}
-
-static int msi001_remove(struct spi_device *spi)
-{
-	struct v4l2_subdev *sd = spi_get_drvdata(spi);
-	struct msi001 *s = sd_to_msi001(sd);
-	dev_dbg(&spi->dev, "%s:\n", __func__);
-
-	/*
-	 * Registered by v4l2_spi_new_subdev() from master driver, but we must
-	 * unregister it from here. Weird.
-	 */
-	v4l2_device_unregister_subdev(&s->sd);
-	v4l2_ctrl_handler_free(&s->hdl);
-	kfree(s);
-	return 0;
-}
-
-static const struct spi_device_id msi001_id[] = {
-	{"msi001", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(spi, msi001_id);
-
-static struct spi_driver msi001_driver = {
-	.driver = {
-		.name	= "msi001",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= msi001_probe,
-	.remove		= msi001_remove,
-	.id_table	= msi001_id,
-};
-module_spi_driver(msi001_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Mirics MSi001");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/msi3101/sdr-msi3101.c linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/sdr-msi3101.c
--- linux-libre-3.16-gnu/drivers/staging/media/msi3101/sdr-msi3101.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/msi3101/sdr-msi3101.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1518 +0,0 @@
-/*
- * Mirics MSi3101 SDR Dongle driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * That driver is somehow based of pwc driver:
- *  (C) 1999-2004 Nemosoft Unv.
- *  (C) 2004-2006 Luc Saillard (luc@saillard.org)
- *  (C) 2011 Hans de Goede <hdegoede@redhat.com>
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <linux/usb.h>
-#include <media/videobuf2-vmalloc.h>
-#include <linux/spi/spi.h>
-
-/*
- *   iConfiguration          0
- *     bInterfaceNumber        0
- *     bAlternateSetting       1
- *     bNumEndpoints           1
- *       bEndpointAddress     0x81  EP 1 IN
- *       bmAttributes            1
- *         Transfer Type            Isochronous
- *       wMaxPacketSize     0x1400  3x 1024 bytes
- *       bInterval               1
- */
-#define MAX_ISO_BUFS            (8)
-#define ISO_FRAMES_PER_DESC     (8)
-#define ISO_MAX_FRAME_SIZE      (3 * 1024)
-#define ISO_BUFFER_SIZE         (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
-#define MAX_ISOC_ERRORS         20
-
-/* TODO: These should be moved to V4L2 API */
-#define V4L2_PIX_FMT_SDR_S8     v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
-#define V4L2_PIX_FMT_SDR_S12    v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */
-#define V4L2_PIX_FMT_SDR_S14    v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */
-#define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
-
-static const struct v4l2_frequency_band bands[] = {
-	{
-		.tuner = 0,
-		.type = V4L2_TUNER_ADC,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =  1200000,
-		.rangehigh  = 15000000,
-	},
-};
-
-/* stream formats */
-struct msi3101_format {
-	char	*name;
-	u32	pixelformat;
-};
-
-/* format descriptions for capture and preview */
-static struct msi3101_format formats[] = {
-	{
-		.name		= "IQ U8",
-		.pixelformat	= V4L2_SDR_FMT_CU8,
-	}, {
-		.name		= "IQ U16LE",
-		.pixelformat	=  V4L2_SDR_FMT_CU16LE,
-#if 0
-	}, {
-		.name		= "8-bit signed",
-		.pixelformat	= V4L2_PIX_FMT_SDR_S8,
-	}, {
-		.name		= "10+2-bit signed",
-		.pixelformat	= V4L2_PIX_FMT_SDR_MSI2500_384,
-	}, {
-		.name		= "12-bit signed",
-		.pixelformat	= V4L2_PIX_FMT_SDR_S12,
-	}, {
-		.name		= "14-bit signed",
-		.pixelformat	= V4L2_PIX_FMT_SDR_S14,
-#endif
-	},
-};
-
-static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
-
-/* intermediate buffers with raw data from the USB device */
-struct msi3101_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
-	struct list_head list;
-};
-
-struct msi3101_state {
-	struct video_device vdev;
-	struct v4l2_device v4l2_dev;
-	struct v4l2_subdev *v4l2_subdev;
-	struct spi_master *master;
-
-	/* videobuf2 queue and queued buffers list */
-	struct vb2_queue vb_queue;
-	struct list_head queued_bufs;
-	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
-
-	/* Note if taking both locks v4l2_lock must always be locked first! */
-	struct mutex v4l2_lock;      /* Protects everything else */
-	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
-
-	/* Pointer to our usb_device, will be NULL after unplug */
-	struct usb_device *udev; /* Both mutexes most be hold when setting! */
-
-	unsigned int f_adc;
-	u32 pixelformat;
-
-	unsigned int isoc_errors; /* number of contiguous ISOC errors */
-	unsigned int vb_full; /* vb is full and packets dropped */
-
-	struct urb *urbs[MAX_ISO_BUFS];
-	int (*convert_stream)(struct msi3101_state *s, u8 *dst, u8 *src,
-			unsigned int src_len);
-
-	/* Controls */
-	struct v4l2_ctrl_handler hdl;
-
-	u32 next_sample; /* for track lost packets */
-	u32 sample; /* for sample rate calc */
-	unsigned long jiffies_next;
-	unsigned int sample_ctrl_bit[4];
-};
-
-/* Private functions */
-static struct msi3101_frame_buf *msi3101_get_next_fill_buf(
-		struct msi3101_state *s)
-{
-	unsigned long flags = 0;
-	struct msi3101_frame_buf *buf = NULL;
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	if (list_empty(&s->queued_bufs))
-		goto leave;
-
-	buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, list);
-	list_del(&buf->list);
-leave:
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-	return buf;
-}
-
-/*
- * +===========================================================================
- * |   00-1023 | USB packet type '504'
- * +===========================================================================
- * |   00-  03 | sequence number of first sample in that USB packet
- * +---------------------------------------------------------------------------
- * |   04-  15 | garbage
- * +---------------------------------------------------------------------------
- * |   16-1023 | samples
- * +---------------------------------------------------------------------------
- * signed 8-bit sample
- * 504 * 2 = 1008 samples
- */
-static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, i_max, dst_len = 0;
-	u32 sample_num[3];
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
-		/* 504 x I+Q samples */
-		src += 16;
-		memcpy(dst, src, 1008);
-		src += 1008;
-		dst += 1008;
-		dst_len += 1008;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
-		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies_now;
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs);
-	}
-
-	/* next sample (sample = sample + i * 504) */
-	s->next_sample = sample_num[i_max - 1] + 504;
-
-	return dst_len;
-}
-
-static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, j, i_max, dst_len = 0;
-	u32 sample_num[3];
-	s8 *s8src;
-	u8 *u8dst;
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-	u8dst = (u8 *) dst;
-
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
-		/* 504 x I+Q samples */
-		src += 16;
-
-		s8src = (s8 *) src;
-		for (j = 0; j < 1008; j++)
-			*u8dst++ = *s8src++ + 128;
-
-		src += 1008;
-		dst += 1008;
-		dst_len += 1008;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
-#define MSECS 10000UL
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, MSECS,
-				samples * 1000UL / MSECS);
-	}
-
-	/* next sample (sample = sample + i * 504) */
-	s->next_sample = sample_num[i_max - 1] + 504;
-
-	return dst_len;
-}
-
-/*
- * +===========================================================================
- * |   00-1023 | USB packet type '384'
- * +===========================================================================
- * |   00-  03 | sequence number of first sample in that USB packet
- * +---------------------------------------------------------------------------
- * |   04-  15 | garbage
- * +---------------------------------------------------------------------------
- * |   16- 175 | samples
- * +---------------------------------------------------------------------------
- * |  176- 179 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * |  180- 339 | samples
- * +---------------------------------------------------------------------------
- * |  340- 343 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * |  344- 503 | samples
- * +---------------------------------------------------------------------------
- * |  504- 507 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * |  508- 667 | samples
- * +---------------------------------------------------------------------------
- * |  668- 671 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * |  672- 831 | samples
- * +---------------------------------------------------------------------------
- * |  832- 835 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * |  836- 995 | samples
- * +---------------------------------------------------------------------------
- * |  996- 999 | control bits for previous samples
- * +---------------------------------------------------------------------------
- * | 1000-1023 | garbage
- * +---------------------------------------------------------------------------
- *
- * Bytes 4 - 7 could have some meaning?
- *
- * Control bits for previous samples is 32-bit field, containing 16 x 2-bit
- * numbers. This results one 2-bit number for 8 samples. It is likely used for
- * for bit shifting sample by given bits, increasing actual sampling resolution.
- * Number 2 (0b10) was never seen.
- *
- * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes
- */
-static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, i_max, dst_len = 0;
-	u32 sample_num[3];
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev,
-				"%*ph  %*ph\n", 12, &src[4], 24, &src[1000]);
-
-		/* 384 x I+Q samples */
-		src += 16;
-		memcpy(dst, src, 984);
-		src += 984 + 24;
-		dst += 984;
-		dst_len += 984;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
-		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies_now;
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu bits=%d.%d.%d.%d\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs,
-				s->sample_ctrl_bit[0], s->sample_ctrl_bit[1],
-				s->sample_ctrl_bit[2], s->sample_ctrl_bit[3]);
-	}
-
-	/* next sample (sample = sample + i * 384) */
-	s->next_sample = sample_num[i_max - 1] + 384;
-
-	return dst_len;
-}
-
-/*
- * +===========================================================================
- * |   00-1023 | USB packet type '336'
- * +===========================================================================
- * |   00-  03 | sequence number of first sample in that USB packet
- * +---------------------------------------------------------------------------
- * |   04-  15 | garbage
- * +---------------------------------------------------------------------------
- * |   16-1023 | samples
- * +---------------------------------------------------------------------------
- * signed 12-bit sample
- */
-static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, i_max, dst_len = 0;
-	u32 sample_num[3];
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
-		/* 336 x I+Q samples */
-		src += 16;
-		memcpy(dst, src, 1008);
-		src += 1008;
-		dst += 1008;
-		dst_len += 1008;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
-		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies_now;
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs);
-	}
-
-	/* next sample (sample = sample + i * 336) */
-	s->next_sample = sample_num[i_max - 1] + 336;
-
-	return dst_len;
-}
-
-/*
- * +===========================================================================
- * |   00-1023 | USB packet type '252'
- * +===========================================================================
- * |   00-  03 | sequence number of first sample in that USB packet
- * +---------------------------------------------------------------------------
- * |   04-  15 | garbage
- * +---------------------------------------------------------------------------
- * |   16-1023 | samples
- * +---------------------------------------------------------------------------
- * signed 14-bit sample
- */
-static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, i_max, dst_len = 0;
-	u32 sample_num[3];
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
-		/* 252 x I+Q samples */
-		src += 16;
-		memcpy(dst, src, 1008);
-		src += 1008;
-		dst += 1008;
-		dst_len += 1008;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
-		unsigned long jiffies_now = jiffies;
-		unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies_now;
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs);
-	}
-
-	/* next sample (sample = sample + i * 252) */
-	s->next_sample = sample_num[i_max - 1] + 252;
-
-	return dst_len;
-}
-
-static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst,
-		u8 *src, unsigned int src_len)
-{
-	int i, j, i_max, dst_len = 0;
-	u32 sample_num[3];
-	u16 *u16dst = (u16 *) dst;
-	struct {signed int x:14;} se;
-
-	/* There could be 1-3 1024 bytes URB frames */
-	i_max = src_len / 1024;
-
-	for (i = 0; i < i_max; i++) {
-		sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
-		if (i == 0 && s->next_sample != sample_num[0]) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"%d samples lost, %d %08x:%08x\n",
-					sample_num[0] - s->next_sample,
-					src_len, s->next_sample, sample_num[0]);
-		}
-
-		/*
-		 * Dump all unknown 'garbage' data - maybe we will discover
-		 * someday if there is something rational...
-		 */
-		dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
-		/* 252 x I+Q samples */
-		src += 16;
-
-		for (j = 0; j < 1008; j += 4) {
-			unsigned int usample[2];
-			int ssample[2];
-
-			usample[0] = src[j + 0] >> 0 | src[j + 1] << 8;
-			usample[1] = src[j + 2] >> 0 | src[j + 3] << 8;
-
-			/* sign extension from 14-bit to signed int */
-			ssample[0] = se.x = usample[0];
-			ssample[1] = se.x = usample[1];
-
-			/* from signed to unsigned */
-			usample[0] = ssample[0] + 8192;
-			usample[1] = ssample[1] + 8192;
-
-			/* from 14-bit to 16-bit */
-			*u16dst++ = (usample[0] << 2) | (usample[0] >> 12);
-			*u16dst++ = (usample[1] << 2) | (usample[1] >> 12);
-		}
-
-		src += 1008;
-		dst += 1008;
-		dst_len += 1008;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
-#define MSECS 10000UL
-		unsigned int samples = sample_num[i_max - 1] - s->sample;
-		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
-		s->sample = sample_num[i_max - 1];
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, MSECS,
-				samples * 1000UL / MSECS);
-	}
-
-	/* next sample (sample = sample + i * 252) */
-	s->next_sample = sample_num[i_max - 1] + 252;
-
-	return dst_len;
-}
-
-/*
- * This gets called for the Isochronous pipe (stream). This is done in interrupt
- * time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void msi3101_isoc_handler(struct urb *urb)
-{
-	struct msi3101_state *s = (struct msi3101_state *)urb->context;
-	int i, flen, fstatus;
-	unsigned char *iso_buf = NULL;
-	struct msi3101_frame_buf *fbuf;
-
-	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
-			urb->status == -ESHUTDOWN)) {
-		dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n",
-				urb, urb->status == -ENOENT ? "" : "a");
-		return;
-	}
-
-	if (unlikely(urb->status != 0)) {
-		dev_dbg(&s->udev->dev,
-				"msi3101_isoc_handler() called with status %d\n",
-				urb->status);
-		/* Give up after a number of contiguous errors */
-		if (++s->isoc_errors > MAX_ISOC_ERRORS)
-			dev_dbg(&s->udev->dev,
-					"Too many ISOC errors, bailing out\n");
-		goto handler_end;
-	} else {
-		/* Reset ISOC error counter. We did get here, after all. */
-		s->isoc_errors = 0;
-	}
-
-	/* Compact data */
-	for (i = 0; i < urb->number_of_packets; i++) {
-		void *ptr;
-
-		/* Check frame error */
-		fstatus = urb->iso_frame_desc[i].status;
-		if (unlikely(fstatus)) {
-			dev_dbg_ratelimited(&s->udev->dev,
-					"frame=%d/%d has error %d skipping\n",
-					i, urb->number_of_packets, fstatus);
-			continue;
-		}
-
-		/* Check if that frame contains data */
-		flen = urb->iso_frame_desc[i].actual_length;
-		if (unlikely(flen == 0))
-			continue;
-
-		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-		/* Get free framebuffer */
-		fbuf = msi3101_get_next_fill_buf(s);
-		if (unlikely(fbuf == NULL)) {
-			s->vb_full++;
-			dev_dbg_ratelimited(&s->udev->dev,
-					"videobuf is full, %d packets dropped\n",
-					s->vb_full);
-			continue;
-		}
-
-		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		flen = s->convert_stream(s, ptr, iso_buf, flen);
-		vb2_set_plane_payload(&fbuf->vb, 0, flen);
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
-	}
-
-handler_end:
-	i = usb_submit_urb(urb, GFP_ATOMIC);
-	if (unlikely(i != 0))
-		dev_dbg(&s->udev->dev,
-				"Error (%d) re-submitting urb in msi3101_isoc_handler\n",
-				i);
-}
-
-static void msi3101_iso_stop(struct msi3101_state *s)
-{
-	int i;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	/* Unlinking ISOC buffers one by one */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		if (s->urbs[i]) {
-			dev_dbg(&s->udev->dev, "Unlinking URB %p\n",
-					s->urbs[i]);
-			usb_kill_urb(s->urbs[i]);
-		}
-	}
-}
-
-static void msi3101_iso_free(struct msi3101_state *s)
-{
-	int i;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	/* Freeing ISOC buffers one by one */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		if (s->urbs[i]) {
-			dev_dbg(&s->udev->dev, "Freeing URB\n");
-			if (s->urbs[i]->transfer_buffer) {
-				usb_free_coherent(s->udev,
-					s->urbs[i]->transfer_buffer_length,
-					s->urbs[i]->transfer_buffer,
-					s->urbs[i]->transfer_dma);
-			}
-			usb_free_urb(s->urbs[i]);
-			s->urbs[i] = NULL;
-		}
-	}
-}
-
-/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static void msi3101_isoc_cleanup(struct msi3101_state *s)
-{
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	msi3101_iso_stop(s);
-	msi3101_iso_free(s);
-}
-
-/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static int msi3101_isoc_init(struct msi3101_state *s)
-{
-	struct usb_device *udev;
-	struct urb *urb;
-	int i, j, ret;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	s->isoc_errors = 0;
-	udev = s->udev;
-
-	ret = usb_set_interface(s->udev, 0, 1);
-	if (ret)
-		return ret;
-
-	/* Allocate and init Isochronuous urbs */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
-		if (urb == NULL) {
-			dev_err(&s->udev->dev,
-					"Failed to allocate urb %d\n", i);
-			msi3101_isoc_cleanup(s);
-			return -ENOMEM;
-		}
-		s->urbs[i] = urb;
-		dev_dbg(&s->udev->dev, "Allocated URB at 0x%p\n", urb);
-
-		urb->interval = 1;
-		urb->dev = udev;
-		urb->pipe = usb_rcvisocpipe(udev, 0x81);
-		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		urb->transfer_buffer = usb_alloc_coherent(udev, ISO_BUFFER_SIZE,
-				GFP_KERNEL, &urb->transfer_dma);
-		if (urb->transfer_buffer == NULL) {
-			dev_err(&s->udev->dev,
-					"Failed to allocate urb buffer %d\n",
-					i);
-			msi3101_isoc_cleanup(s);
-			return -ENOMEM;
-		}
-		urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-		urb->complete = msi3101_isoc_handler;
-		urb->context = s;
-		urb->start_frame = 0;
-		urb->number_of_packets = ISO_FRAMES_PER_DESC;
-		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
-			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
-		}
-	}
-
-	/* link */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		ret = usb_submit_urb(s->urbs[i], GFP_KERNEL);
-		if (ret) {
-			dev_err(&s->udev->dev,
-					"isoc_init() submit_urb %d failed with error %d\n",
-					i, ret);
-			msi3101_isoc_cleanup(s);
-			return ret;
-		}
-		dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]);
-	}
-
-	/* All is done... */
-	return 0;
-}
-
-/* Must be called with vb_queue_lock hold */
-static void msi3101_cleanup_queued_bufs(struct msi3101_state *s)
-{
-	unsigned long flags = 0;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	while (!list_empty(&s->queued_bufs)) {
-		struct msi3101_frame_buf *buf;
-
-		buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf,
-				 list);
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-/* The user yanked out the cable... */
-static void msi3101_disconnect(struct usb_interface *intf)
-{
-	struct v4l2_device *v = usb_get_intfdata(intf);
-	struct msi3101_state *s =
-			container_of(v, struct msi3101_state, v4l2_dev);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->vb_queue_lock);
-	mutex_lock(&s->v4l2_lock);
-	/* No need to keep the urbs around after disconnection */
-	s->udev = NULL;
-	v4l2_device_disconnect(&s->v4l2_dev);
-	video_unregister_device(&s->vdev);
-	spi_unregister_master(s->master);
-	mutex_unlock(&s->v4l2_lock);
-	mutex_unlock(&s->vb_queue_lock);
-
-	v4l2_device_put(&s->v4l2_dev);
-}
-
-static int msi3101_querycap(struct file *file, void *fh,
-		struct v4l2_capability *cap)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
-	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-/* Videobuf2 operations */
-static int msi3101_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
-		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct msi3101_state *s = vb2_get_drv_priv(vq);
-	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
-
-	/* Absolute min and max number of buffers available for mmap() */
-	*nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32);
-	*nplanes = 1;
-	/*
-	 *   3, wMaxPacketSize 3x 1024 bytes
-	 * 504, max IQ sample pairs per 1024 frame
-	 *   2, two samples, I and Q
-	 *   2, 16-bit is enough for single sample
-	 */
-	sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 2);
-	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
-			__func__, *nbuffers, sizes[0]);
-	return 0;
-}
-
-static void msi3101_buf_queue(struct vb2_buffer *vb)
-{
-	struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue);
-	struct msi3101_frame_buf *buf =
-			container_of(vb, struct msi3101_frame_buf, vb);
-	unsigned long flags = 0;
-
-	/* Check the device has not disconnected between prep and queuing */
-	if (unlikely(!s->udev)) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-		return;
-	}
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	list_add_tail(&buf->list, &s->queued_bufs);
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-#define CMD_WREG               0x41
-#define CMD_START_STREAMING    0x43
-#define CMD_STOP_STREAMING     0x45
-#define CMD_READ_UNKNOW        0x48
-
-#define msi3101_dbg_usb_control_msg(udev, r, t, v, _i, b, l) { \
-	char *direction; \
-	if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
-		direction = ">>>"; \
-	else \
-		direction = "<<<"; \
-	dev_dbg(&udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
-			"%s %*ph\n",  __func__, t, r, v & 0xff, v >> 8, \
-			_i & 0xff, _i >> 8, l & 0xff, l >> 8, direction, l, b); \
-}
-
-static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data)
-{
-	int ret;
-	u8 request = cmd;
-	u8 requesttype = USB_DIR_OUT | USB_TYPE_VENDOR;
-	u16 value = (data >> 0) & 0xffff;
-	u16 index = (data >> 16) & 0xffff;
-
-	msi3101_dbg_usb_control_msg(s->udev,
-			request, requesttype, value, index, NULL, 0);
-
-	ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0),
-			request, requesttype, value, index, NULL, 0, 2000);
-
-	if (ret)
-		dev_err(&s->udev->dev, "%s: failed %d, cmd %02x, data %04x\n",
-				__func__, ret, cmd, data);
-
-	return ret;
-};
-
-#define F_REF 24000000
-#define DIV_R_IN 2
-static int msi3101_set_usb_adc(struct msi3101_state *s)
-{
-	int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract;
-	u32 reg3, reg4, reg7;
-	struct v4l2_ctrl *bandwidth_auto;
-	struct v4l2_ctrl *bandwidth;
-
-	f_sr = s->f_adc;
-
-	/* set tuner, subdev, filters according to sampling rate */
-	bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
-	if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
-		bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
-		v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
-	}
-
-	/* select stream format */
-	switch (s->pixelformat) {
-	case V4L2_SDR_FMT_CU8:
-		s->convert_stream = msi3101_convert_stream_504_u8;
-		reg7 = 0x000c9407;
-		break;
-	case  V4L2_SDR_FMT_CU16LE:
-		s->convert_stream = msi3101_convert_stream_252_u16;
-		reg7 = 0x00009407;
-		break;
-	case V4L2_PIX_FMT_SDR_S8:
-		s->convert_stream = msi3101_convert_stream_504;
-		reg7 = 0x000c9407;
-		break;
-	case V4L2_PIX_FMT_SDR_MSI2500_384:
-		s->convert_stream = msi3101_convert_stream_384;
-		reg7 = 0x0000a507;
-		break;
-	case V4L2_PIX_FMT_SDR_S12:
-		s->convert_stream = msi3101_convert_stream_336;
-		reg7 = 0x00008507;
-		break;
-	case V4L2_PIX_FMT_SDR_S14:
-		s->convert_stream = msi3101_convert_stream_252;
-		reg7 = 0x00009407;
-		break;
-	default:
-		s->convert_stream = msi3101_convert_stream_504_u8;
-		reg7 = 0x000c9407;
-		break;
-	}
-
-	/*
-	 * Synthesizer config is just a educated guess...
-	 *
-	 * [7:0]   0x03, register address
-	 * [8]     1, power control
-	 * [9]     ?, power control
-	 * [12:10] output divider
-	 * [13]    0 ?
-	 * [14]    0 ?
-	 * [15]    fractional MSB, bit 20
-	 * [16:19] N
-	 * [23:20] ?
-	 * [24:31] 0x01
-	 *
-	 * output divider
-	 * val   div
-	 *   0     - (invalid)
-	 *   1     4
-	 *   2     6
-	 *   3     8
-	 *   4    10
-	 *   5    12
-	 *   6    14
-	 *   7    16
-	 *
-	 * VCO 202000000 - 720000000++
-	 */
-	reg3 = 0x01000303;
-	reg4 = 0x00000004;
-
-	/* XXX: Filters? AGC? */
-	if (f_sr < 6000000)
-		reg3 |= 0x1 << 20;
-	else if (f_sr < 7000000)
-		reg3 |= 0x5 << 20;
-	else if (f_sr < 8500000)
-		reg3 |= 0x9 << 20;
-	else
-		reg3 |= 0xd << 20;
-
-	for (div_r_out = 4; div_r_out < 16; div_r_out += 2) {
-		f_vco = f_sr * div_r_out * 12;
-		dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n",
-				__func__, div_r_out, f_vco);
-		if (f_vco >= 202000000)
-			break;
-	}
-
-	div_n = f_vco / (F_REF * DIV_R_IN);
-	div_m = f_vco % (F_REF * DIV_R_IN);
-	fract = 0x200000ul * div_m / (F_REF * DIV_R_IN);
-
-	reg3 |= div_n << 16;
-	reg3 |= (div_r_out / 2 - 1) << 10;
-	reg3 |= ((fract >> 20) & 0x000001) << 15; /* [20] */
-	reg4 |= ((fract >>  0) & 0x0fffff) <<  8; /* [19:0] */
-
-	dev_dbg(&s->udev->dev,
-			"%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n",
-			__func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3, reg4);
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00000c05);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00020000);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00480102);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00f38008);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, reg7);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, reg4);
-	if (ret)
-		goto err;
-
-	ret = msi3101_ctrl_msg(s, CMD_WREG, reg3);
-	if (ret)
-		goto err;
-err:
-	return ret;
-};
-
-static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct msi3101_state *s = vb2_get_drv_priv(vq);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (!s->udev)
-		return -ENODEV;
-
-	if (mutex_lock_interruptible(&s->v4l2_lock))
-		return -ERESTARTSYS;
-
-	/* wake-up tuner */
-	v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1);
-
-	ret = msi3101_set_usb_adc(s);
-
-	ret = msi3101_isoc_init(s);
-	if (ret)
-		msi3101_cleanup_queued_bufs(s);
-
-	ret = msi3101_ctrl_msg(s, CMD_START_STREAMING, 0);
-
-	mutex_unlock(&s->v4l2_lock);
-
-	return ret;
-}
-
-static void msi3101_stop_streaming(struct vb2_queue *vq)
-{
-	struct msi3101_state *s = vb2_get_drv_priv(vq);
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->v4l2_lock);
-
-	if (s->udev)
-		msi3101_isoc_cleanup(s);
-
-	msi3101_cleanup_queued_bufs(s);
-
-	/* according to tests, at least 700us delay is required  */
-	msleep(20);
-	if (!msi3101_ctrl_msg(s, CMD_STOP_STREAMING, 0)) {
-		/* sleep USB IF / ADC */
-		msi3101_ctrl_msg(s, CMD_WREG, 0x01000003);
-	}
-
-	/* sleep tuner */
-	v4l2_subdev_call(s->v4l2_subdev, core, s_power, 0);
-
-	mutex_unlock(&s->v4l2_lock);
-}
-
-static struct vb2_ops msi3101_vb2_ops = {
-	.queue_setup            = msi3101_queue_setup,
-	.buf_queue              = msi3101_buf_queue,
-	.start_streaming        = msi3101_start_streaming,
-	.stop_streaming         = msi3101_stop_streaming,
-	.wait_prepare           = vb2_ops_wait_prepare,
-	.wait_finish            = vb2_ops_wait_finish,
-};
-
-static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_fmtdesc *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
-
-	if (f->index >= NUM_FORMATS)
-		return -EINVAL;
-
-	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
-	f->pixelformat = formats[f->index].pixelformat;
-
-	return 0;
-}
-
-static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&s->pixelformat);
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	f->fmt.sdr.pixelformat = s->pixelformat;
-
-	return 0;
-}
-
-static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	struct vb2_queue *q = &s->vb_queue;
-	int i;
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.sdr.pixelformat);
-
-	if (vb2_is_busy(q))
-		return -EBUSY;
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
-			s->pixelformat = f->fmt.sdr.pixelformat;
-			return 0;
-		}
-	}
-
-	f->fmt.sdr.pixelformat = formats[0].pixelformat;
-	s->pixelformat = formats[0].pixelformat;
-
-	return 0;
-}
-
-static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int i;
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.sdr.pixelformat);
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
-			return 0;
-	}
-
-	f->fmt.sdr.pixelformat = formats[0].pixelformat;
-
-	return 0;
-}
-
-static int msi3101_s_tuner(struct file *file, void *priv,
-		const struct v4l2_tuner *v)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
-
-	if (v->index == 0)
-		ret = 0;
-	else if (v->index == 1)
-		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_tuner, v);
-	else
-		ret = -EINVAL;
-
-	return ret;
-}
-
-static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
-
-	if (v->index == 0) {
-		strlcpy(v->name, "Mirics MSi2500", sizeof(v->name));
-		v->type = V4L2_TUNER_ADC;
-		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-		v->rangelow =   1200000;
-		v->rangehigh = 15000000;
-		ret = 0;
-	} else if (v->index == 1) {
-		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_tuner, v);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int msi3101_g_frequency(struct file *file, void *priv,
-		struct v4l2_frequency *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int ret  = 0;
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
-			__func__, f->tuner, f->type);
-
-	if (f->tuner == 0) {
-		f->frequency = s->f_adc;
-		ret = 0;
-	} else if (f->tuner == 1) {
-		f->type = V4L2_TUNER_RF;
-		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_frequency, f);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int msi3101_s_frequency(struct file *file, void *priv,
-		const struct v4l2_frequency *f)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
-			__func__, f->tuner, f->type, f->frequency);
-
-	if (f->tuner == 0) {
-		s->f_adc = clamp_t(unsigned int, f->frequency,
-				bands[0].rangelow,
-				bands[0].rangehigh);
-		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
-				__func__, s->f_adc);
-		ret = msi3101_set_usb_adc(s);
-	} else if (f->tuner == 1) {
-		ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int msi3101_enum_freq_bands(struct file *file, void *priv,
-		struct v4l2_frequency_band *band)
-{
-	struct msi3101_state *s = video_drvdata(file);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
-			__func__, band->tuner, band->type, band->index);
-
-	if (band->tuner == 0) {
-		if (band->index >= ARRAY_SIZE(bands)) {
-			ret = -EINVAL;
-		} else {
-			*band = bands[band->index];
-			ret = 0;
-		}
-	} else if (band->tuner == 1) {
-		ret = v4l2_subdev_call(s->v4l2_subdev, tuner,
-				enum_freq_bands, band);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
-	.vidioc_querycap          = msi3101_querycap,
-
-	.vidioc_enum_fmt_sdr_cap  = msi3101_enum_fmt_sdr_cap,
-	.vidioc_g_fmt_sdr_cap     = msi3101_g_fmt_sdr_cap,
-	.vidioc_s_fmt_sdr_cap     = msi3101_s_fmt_sdr_cap,
-	.vidioc_try_fmt_sdr_cap   = msi3101_try_fmt_sdr_cap,
-
-	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
-	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
-	.vidioc_querybuf          = vb2_ioctl_querybuf,
-	.vidioc_qbuf              = vb2_ioctl_qbuf,
-	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
-
-	.vidioc_streamon          = vb2_ioctl_streamon,
-	.vidioc_streamoff         = vb2_ioctl_streamoff,
-
-	.vidioc_g_tuner           = msi3101_g_tuner,
-	.vidioc_s_tuner           = msi3101_s_tuner,
-
-	.vidioc_g_frequency       = msi3101_g_frequency,
-	.vidioc_s_frequency       = msi3101_s_frequency,
-	.vidioc_enum_freq_bands   = msi3101_enum_freq_bands,
-
-	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-	.vidioc_log_status        = v4l2_ctrl_log_status,
-};
-
-static const struct v4l2_file_operations msi3101_fops = {
-	.owner                    = THIS_MODULE,
-	.open                     = v4l2_fh_open,
-	.release                  = vb2_fop_release,
-	.read                     = vb2_fop_read,
-	.poll                     = vb2_fop_poll,
-	.mmap                     = vb2_fop_mmap,
-	.unlocked_ioctl           = video_ioctl2,
-};
-
-static struct video_device msi3101_template = {
-	.name                     = "Mirics MSi3101 SDR Dongle",
-	.release                  = video_device_release_empty,
-	.fops                     = &msi3101_fops,
-	.ioctl_ops                = &msi3101_ioctl_ops,
-};
-
-static void msi3101_video_release(struct v4l2_device *v)
-{
-	struct msi3101_state *s =
-			container_of(v, struct msi3101_state, v4l2_dev);
-
-	v4l2_ctrl_handler_free(&s->hdl);
-	v4l2_device_unregister(&s->v4l2_dev);
-	kfree(s);
-}
-
-static int msi3101_transfer_one_message(struct spi_master *master,
-		struct spi_message *m)
-{
-	struct msi3101_state *s = spi_master_get_devdata(master);
-	struct spi_transfer *t;
-	int ret = 0;
-	u32 data;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		dev_dbg(&s->udev->dev, "%s: msg=%*ph\n",
-				__func__, t->len, t->tx_buf);
-		data = 0x09; /* reg 9 is SPI adapter */
-		data |= ((u8 *)t->tx_buf)[0] << 8;
-		data |= ((u8 *)t->tx_buf)[1] << 16;
-		data |= ((u8 *)t->tx_buf)[2] << 24;
-		ret = msi3101_ctrl_msg(s, CMD_WREG, data);
-	}
-
-	m->status = ret;
-	spi_finalize_current_message(master);
-	return ret;
-}
-
-static int msi3101_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct msi3101_state *s = NULL;
-	struct v4l2_subdev *sd;
-	struct spi_master *master;
-	int ret;
-	static struct spi_board_info board_info = {
-		.modalias		= "msi001",
-		.bus_num		= 0,
-		.chip_select		= 0,
-		.max_speed_hz		= 12000000,
-	};
-
-	s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL);
-	if (s == NULL) {
-		pr_err("Could not allocate memory for msi3101_state\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&s->v4l2_lock);
-	mutex_init(&s->vb_queue_lock);
-	spin_lock_init(&s->queued_bufs_lock);
-	INIT_LIST_HEAD(&s->queued_bufs);
-	s->udev = udev;
-	s->f_adc = bands[0].rangelow;
-	s->pixelformat = V4L2_SDR_FMT_CU8;
-
-	/* Init videobuf2 queue structure */
-	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
-	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	s->vb_queue.drv_priv = s;
-	s->vb_queue.buf_struct_size = sizeof(struct msi3101_frame_buf);
-	s->vb_queue.ops = &msi3101_vb2_ops;
-	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
-	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	ret = vb2_queue_init(&s->vb_queue);
-	if (ret) {
-		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
-		goto err_free_mem;
-	}
-
-	/* Init video_device structure */
-	s->vdev = msi3101_template;
-	s->vdev.queue = &s->vb_queue;
-	s->vdev.queue->lock = &s->vb_queue_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
-	video_set_drvdata(&s->vdev, s);
-
-	/* Register the v4l2_device structure */
-	s->v4l2_dev.release = msi3101_video_release;
-	ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register v4l2-device (%d)\n", ret);
-		goto err_free_mem;
-	}
-
-	/* SPI master adapter */
-	master = spi_alloc_master(&s->udev->dev, 0);
-	if (master == NULL) {
-		ret = -ENOMEM;
-		goto err_unregister_v4l2_dev;
-	}
-
-	s->master = master;
-	master->bus_num = 0;
-	master->num_chipselect = 1;
-	master->transfer_one_message = msi3101_transfer_one_message;
-	spi_master_set_devdata(master, s);
-	ret = spi_register_master(master);
-	if (ret) {
-		spi_master_put(master);
-		goto err_unregister_v4l2_dev;
-	}
-
-	/* load v4l2 subdevice */
-	sd = v4l2_spi_new_subdev(&s->v4l2_dev, master, &board_info);
-	s->v4l2_subdev = sd;
-	if (sd == NULL) {
-		dev_err(&s->udev->dev, "cannot get v4l2 subdevice\n");
-		ret = -ENODEV;
-		goto err_unregister_master;
-	}
-
-	/* Register controls */
-	v4l2_ctrl_handler_init(&s->hdl, 0);
-	if (s->hdl.error) {
-		ret = s->hdl.error;
-		dev_err(&s->udev->dev, "Could not initialize controls\n");
-		goto err_free_controls;
-	}
-
-	/* currently all controls are from subdev */
-	v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
-
-	s->v4l2_dev.ctrl_handler = &s->hdl;
-	s->vdev.v4l2_dev = &s->v4l2_dev;
-	s->vdev.lock = &s->v4l2_lock;
-
-	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register as video device (%d)\n",
-				ret);
-		goto err_unregister_v4l2_dev;
-	}
-	dev_info(&s->udev->dev, "Registered as %s\n",
-			video_device_node_name(&s->vdev));
-
-	return 0;
-
-err_free_controls:
-	v4l2_ctrl_handler_free(&s->hdl);
-err_unregister_master:
-	spi_unregister_master(s->master);
-err_unregister_v4l2_dev:
-	v4l2_device_unregister(&s->v4l2_dev);
-err_free_mem:
-	kfree(s);
-	return ret;
-}
-
-/* USB device ID list */
-static struct usb_device_id msi3101_id_table[] = {
-	{ USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */
-	{ USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, msi3101_id_table);
-
-/* USB subsystem interface */
-static struct usb_driver msi3101_driver = {
-	.name                     = KBUILD_MODNAME,
-	.probe                    = msi3101_probe,
-	.disconnect               = msi3101_disconnect,
-	.id_table                 = msi3101_id_table,
-};
-
-module_usb_driver(msi3101_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss.c linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss.c
--- linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss.c	2014-09-28 17:29:07.000000000 -0400
@@ -1003,33 +1003,18 @@ static void iss_disable_clocks(struct is
 	clk_disable(iss->iss_fck);
 }
 
-static void iss_put_clocks(struct iss_device *iss)
-{
-	if (iss->iss_fck) {
-		clk_put(iss->iss_fck);
-		iss->iss_fck = NULL;
-	}
-
-	if (iss->iss_ctrlclk) {
-		clk_put(iss->iss_ctrlclk);
-		iss->iss_ctrlclk = NULL;
-	}
-}
-
 static int iss_get_clocks(struct iss_device *iss)
 {
-	iss->iss_fck = clk_get(iss->dev, "iss_fck");
+	iss->iss_fck = devm_clk_get(iss->dev, "iss_fck");
 	if (IS_ERR(iss->iss_fck)) {
 		dev_err(iss->dev, "Unable to get iss_fck clock info\n");
-		iss_put_clocks(iss);
 		return PTR_ERR(iss->iss_fck);
 	}
 
-	iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk");
+	iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk");
 	if (IS_ERR(iss->iss_ctrlclk)) {
 		dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
-		iss_put_clocks(iss);
-		return PTR_ERR(iss->iss_fck);
+		return PTR_ERR(iss->iss_ctrlclk);
 	}
 
 	return 0;
@@ -1104,29 +1089,11 @@ static int iss_map_mem_resource(struct p
 {
 	struct resource *mem;
 
-	/* request the mem region for the camera registers */
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
-	if (!mem) {
-		dev_err(iss->dev, "no mem resource?\n");
-		return -ENODEV;
-	}
 
-	if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
-		dev_err(iss->dev,
-			"cannot reserve camera register I/O region\n");
-		return -ENODEV;
-	}
-	iss->res[res] = mem;
-
-	/* map the region */
-	iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem));
-	if (!iss->regs[res]) {
-		dev_err(iss->dev, "cannot map camera register I/O region\n");
-		return -ENODEV;
-	}
+	iss->regs[res] = devm_ioremap_resource(iss->dev, mem);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(iss->regs[res]);
 }
 
 static void iss_unregister_entities(struct iss_device *iss)
@@ -1389,7 +1356,7 @@ static int iss_probe(struct platform_dev
 	if (pdata == NULL)
 		return -EINVAL;
 
-	iss = kzalloc(sizeof(*iss), GFP_KERNEL);
+	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
 	if (!iss) {
 		dev_err(&pdev->dev, "Could not allocate memory\n");
 		return -ENOMEM;
@@ -1456,7 +1423,8 @@ static int iss_probe(struct platform_dev
 		goto error_iss;
 	}
 
-	if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) {
+	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
+			     "OMAP4 ISS", iss)) {
 		dev_err(iss->dev, "Unable to request IRQ\n");
 		ret = -EINVAL;
 		goto error_iss;
@@ -1465,7 +1433,7 @@ static int iss_probe(struct platform_dev
 	/* Entities */
 	ret = iss_initialize_modules(iss);
 	if (ret < 0)
-		goto error_irq;
+		goto error_iss;
 
 	ret = iss_register_entities(iss);
 	if (ret < 0)
@@ -1477,29 +1445,12 @@ static int iss_probe(struct platform_dev
 
 error_modules:
 	iss_cleanup_modules(iss);
-error_irq:
-	free_irq(iss->irq_num, iss);
 error_iss:
 	omap4iss_put(iss);
 error:
-	iss_put_clocks(iss);
-
-	for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
-		if (iss->regs[i]) {
-			iounmap(iss->regs[i]);
-			iss->regs[i] = NULL;
-		}
-
-		if (iss->res[i]) {
-			release_mem_region(iss->res[i]->start,
-					   resource_size(iss->res[i]));
-			iss->res[i] = NULL;
-		}
-	}
 	platform_set_drvdata(pdev, NULL);
 
 	mutex_destroy(&iss->iss_mutex);
-	kfree(iss);
 
 	return ret;
 }
@@ -1507,29 +1458,10 @@ error:
 static int iss_remove(struct platform_device *pdev)
 {
 	struct iss_device *iss = platform_get_drvdata(pdev);
-	unsigned int i;
 
 	iss_unregister_entities(iss);
 	iss_cleanup_modules(iss);
 
-	free_irq(iss->irq_num, iss);
-	iss_put_clocks(iss);
-
-	for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
-		if (iss->regs[i]) {
-			iounmap(iss->regs[i]);
-			iss->regs[i] = NULL;
-		}
-
-		if (iss->res[i]) {
-			release_mem_region(iss->res[i]->start,
-					   resource_size(iss->res[i]));
-			iss->res[i] = NULL;
-		}
-	}
-
-	kfree(iss);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss_csi2.c linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss_csi2.c
--- linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss_csi2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss_csi2.c	2014-09-28 17:29:07.000000000 -0400
@@ -317,7 +317,7 @@ static void csi2_ctx_enable(struct iss_c
 static void csi2_ctx_config(struct iss_csi2_device *csi2,
 			    struct iss_csi2_ctx_cfg *ctx)
 {
-	u32 reg;
+	u32 reg = 0;
 
 	/* Set up CSI2_CTx_CTRL1 */
 	if (ctx->eof_enabled)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss.h linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss.h
--- linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss.h	2014-09-28 17:29:07.000000000 -0400
@@ -97,7 +97,7 @@ struct iss_device {
 	u64 raw_dmamask;
 
 	struct mutex iss_mutex;	/* For handling ref_count field */
-	bool crashed;
+	unsigned int crashed;
 	int has_context;
 	int ref_count;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss_video.c linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss_video.c
--- linux-libre-3.16-gnu/drivers/staging/media/omap4iss/iss_video.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/omap4iss/iss_video.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,6 +25,9 @@
 #include "iss_video.h"
 #include "iss.h"
 
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
 
 /* -----------------------------------------------------------------------------
  * Helper functions
@@ -328,15 +331,6 @@ static int iss_video_buf_prepare(struct
 	if (vb2_plane_size(vb, 0) < size)
 		return -ENOBUFS;
 
-	/* Refuse to prepare the buffer is the video node has registered an
-	 * error. We don't need to take any lock here as the operation is
-	 * inherently racy. The authoritative check will be performed in the
-	 * queue handler, which can't return an error, this check is just a best
-	 * effort to notify userspace as early as possible.
-	 */
-	if (unlikely(video->error))
-		return -EIO;
-
 	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 	if (!IS_ALIGNED(addr, 32)) {
 		dev_dbg(video->iss->dev,
@@ -360,6 +354,11 @@ static void iss_video_buf_queue(struct v
 
 	spin_lock_irqsave(&video->qlock, flags);
 
+	/* Mark the buffer is faulty and give it back to the queue immediately
+	 * if the video node has registered an error. vb2 will perform the same
+	 * check when preparing the buffer, but that is inherently racy, so we
+	 * need to handle the race condition with an authoritative check here.
+	 */
 	if (unlikely(video->error)) {
 		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 		spin_unlock_irqrestore(&video->qlock, flags);
@@ -510,6 +509,7 @@ void omap4iss_video_cancel_stream(struct
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
 
+	vb2_queue_error(video->queue);
 	video->error = true;
 
 	spin_unlock_irqrestore(&video->qlock, flags);
@@ -895,7 +895,6 @@ iss_video_streamon(struct file *file, vo
 
 	video->queue = &vfh->queue;
 	INIT_LIST_HEAD(&video->dmaqueue);
-	spin_lock_init(&video->qlock);
 	video->error = false;
 	atomic_set(&pipe->frame_number, -1);
 
@@ -1044,6 +1043,8 @@ static int iss_video_open(struct file *f
 	if (handle == NULL)
 		return -ENOMEM;
 
+	video->video.debug = debug;
+
 	v4l2_fh_init(&handle->vfh, &video->video);
 	v4l2_fh_add(&handle->vfh);
 
@@ -1175,6 +1176,7 @@ int omap4iss_video_init(struct iss_video
 	if (ret < 0)
 		return ret;
 
+	spin_lock_init(&video->qlock);
 	mutex_init(&video->mutex);
 	atomic_set(&video->active, 0);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-config DVB_RTL2832_SDR
-	tristate "Realtek RTL2832 SDR"
-	depends on USB && DVB_CORE && I2C && VIDEO_V4L2 && DVB_USB_RTL28XXU
-	select DVB_RTL2832
-	select VIDEOBUF2_VMALLOC
-	default m if !MEDIA_SUBDRV_AUTOSELECT
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
-
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/usb/dvb-usb-v2
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
--- linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1497 +0,0 @@
-/*
- * Realtek RTL2832U SDR driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * GNU Radio plugin "gr-kernel" for device usage will be on:
- * http://git.linuxtv.org/anttip/gr-kernel.git
- *
- */
-
-#include "dvb_frontend.h"
-#include "rtl2832_sdr.h"
-#include "dvb_usb.h"
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include <linux/jiffies.h>
-#include <linux/math64.h>
-
-#define MAX_BULK_BUFS            (10)
-#define BULK_BUFFER_SIZE         (128 * 512)
-
-static const struct v4l2_frequency_band bands_adc[] = {
-	{
-		.tuner = 0,
-		.type = V4L2_TUNER_ADC,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =  300000,
-		.rangehigh  =  300000,
-	},
-	{
-		.tuner = 0,
-		.type = V4L2_TUNER_ADC,
-		.index = 1,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =  900001,
-		.rangehigh  = 2800000,
-	},
-	{
-		.tuner = 0,
-		.type = V4L2_TUNER_ADC,
-		.index = 2,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   = 3200000,
-		.rangehigh  = 3200000,
-	},
-};
-
-static const struct v4l2_frequency_band bands_fm[] = {
-	{
-		.tuner = 1,
-		.type = V4L2_TUNER_RF,
-		.index = 0,
-		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow   =    50000000,
-		.rangehigh  =  2000000000,
-	},
-};
-
-/* stream formats */
-struct rtl2832_sdr_format {
-	char	*name;
-	u32	pixelformat;
-};
-
-static struct rtl2832_sdr_format formats[] = {
-	{
-		.name		= "IQ U8",
-		.pixelformat	=  V4L2_SDR_FMT_CU8,
-	}, {
-		.name		= "IQ U16LE (emulated)",
-		.pixelformat	= V4L2_SDR_FMT_CU16LE,
-	},
-};
-
-static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
-
-/* intermediate buffers with raw data from the USB device */
-struct rtl2832_sdr_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
-	struct list_head list;
-};
-
-struct rtl2832_sdr_state {
-#define POWER_ON           (1 << 1)
-#define URB_BUF            (1 << 2)
-	unsigned long flags;
-
-	const struct rtl2832_config *cfg;
-	struct dvb_frontend *fe;
-	struct dvb_usb_device *d;
-	struct i2c_adapter *i2c;
-	u8 bank;
-
-	struct video_device vdev;
-	struct v4l2_device v4l2_dev;
-
-	/* videobuf2 queue and queued buffers list */
-	struct vb2_queue vb_queue;
-	struct list_head queued_bufs;
-	spinlock_t queued_bufs_lock; /* Protects queued_bufs */
-	unsigned sequence;	     /* buffer sequence counter */
-
-	/* Note if taking both locks v4l2_lock must always be locked first! */
-	struct mutex v4l2_lock;      /* Protects everything else */
-	struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
-
-	/* Pointer to our usb_device, will be NULL after unplug */
-	struct usb_device *udev; /* Both mutexes most be hold when setting! */
-
-	unsigned int vb_full; /* vb is full and packets dropped */
-
-	struct urb     *urb_list[MAX_BULK_BUFS];
-	int            buf_num;
-	unsigned long  buf_size;
-	u8             *buf_list[MAX_BULK_BUFS];
-	dma_addr_t     dma_addr[MAX_BULK_BUFS];
-	int urbs_initialized;
-	int urbs_submitted;
-
-	unsigned int f_adc, f_tuner;
-	u32 pixelformat;
-
-	/* Controls */
-	struct v4l2_ctrl_handler hdl;
-	struct v4l2_ctrl *bandwidth_auto;
-	struct v4l2_ctrl *bandwidth;
-
-	/* for sample rate calc */
-	unsigned int sample;
-	unsigned int sample_measured;
-	unsigned long jiffies_next;
-};
-
-/* write multiple hardware registers */
-static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val,
-		int len)
-{
-	int ret;
-#define MAX_WR_LEN 24
-#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1)
-	u8 buf[MAX_WR_XFER_LEN];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = s->cfg->i2c_addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
-
-	if (WARN_ON(len > MAX_WR_LEN))
-		return -EINVAL;
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(s->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_err(&s->i2c->dev,
-			"%s: I2C wr failed=%d reg=%02x len=%d\n",
-			KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple hardware registers */
-static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
-{
-	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = s->cfg->i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = s->cfg->i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	ret = i2c_transfer(s->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		dev_err(&s->i2c->dev,
-				"%s: I2C rd failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
-		const u8 *val, int len)
-{
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 bank = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (bank != s->bank) {
-		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-
-		s->bank = bank;
-	}
-
-	return rtl2832_sdr_wr(s, reg2, val, len);
-}
-
-/* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
-		int len)
-{
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 bank = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (bank != s->bank) {
-		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-
-		s->bank = bank;
-	}
-
-	return rtl2832_sdr_rd(s, reg2, val, len);
-}
-
-/* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val)
-{
-	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
-}
-
-#if 0
-/* read single register */
-static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
-{
-	return rtl2832_sdr_rd_regs(s, reg, val, 1);
-}
-#endif
-
-/* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
-		u8 val, u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
-}
-
-#if 0
-/* read single register with mask */
-static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
-		u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-#endif
-
-/* Private functions */
-static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
-		struct rtl2832_sdr_state *s)
-{
-	unsigned long flags = 0;
-	struct rtl2832_sdr_frame_buf *buf = NULL;
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	if (list_empty(&s->queued_bufs))
-		goto leave;
-
-	buf = list_entry(s->queued_bufs.next,
-			struct rtl2832_sdr_frame_buf, list);
-	list_del(&buf->list);
-leave:
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-	return buf;
-}
-
-static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
-		void *dst, const u8 *src, unsigned int src_len)
-{
-	unsigned int dst_len;
-
-	if (s->pixelformat ==  V4L2_SDR_FMT_CU8) {
-		/* native stream, no need to convert */
-		memcpy(dst, src, src_len);
-		dst_len = src_len;
-	} else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) {
-		/* convert u8 to u16 */
-		unsigned int i;
-		u16 *u16dst = dst;
-		for (i = 0; i < src_len; i++)
-			*u16dst++ = (src[i] << 8) | (src[i] >> 0);
-		dst_len = 2 * src_len;
-	} else {
-		dst_len = 0;
-	}
-
-	/* calculate samping rate and output it in 10 seconds intervals */
-	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
-#define MSECS 10000UL
-		unsigned int samples = s->sample - s->sample_measured;
-		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
-		s->sample_measured = s->sample;
-		dev_dbg(&s->udev->dev,
-				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
-				src_len, samples, MSECS,
-				samples * 1000UL / MSECS);
-	}
-
-	/* total number of I+Q pairs */
-	s->sample += src_len / 2;
-
-	return dst_len;
-}
-
-/*
- * This gets called for the bulk stream pipe. This is done in interrupt
- * time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void rtl2832_sdr_urb_complete(struct urb *urb)
-{
-	struct rtl2832_sdr_state *s = urb->context;
-	struct rtl2832_sdr_frame_buf *fbuf;
-
-	dev_dbg_ratelimited(&s->udev->dev,
-			"%s: status=%d length=%d/%d errors=%d\n",
-			__func__, urb->status, urb->actual_length,
-			urb->transfer_buffer_length, urb->error_count);
-
-	switch (urb->status) {
-	case 0:             /* success */
-	case -ETIMEDOUT:    /* NAK */
-		break;
-	case -ECONNRESET:   /* kill */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	default:            /* error */
-		dev_err_ratelimited(&s->udev->dev, "urb failed=%d\n",
-				urb->status);
-		break;
-	}
-
-	if (likely(urb->actual_length > 0)) {
-		void *ptr;
-		unsigned int len;
-		/* get free framebuffer */
-		fbuf = rtl2832_sdr_get_next_fill_buf(s);
-		if (unlikely(fbuf == NULL)) {
-			s->vb_full++;
-			dev_notice_ratelimited(&s->udev->dev,
-					"videobuf is full, %d packets dropped\n",
-					s->vb_full);
-			goto skip;
-		}
-
-		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer,
-				urb->actual_length);
-		vb2_set_plane_payload(&fbuf->vb, 0, len);
-		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = s->sequence++;
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
-	}
-skip:
-	usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s)
-{
-	int i;
-
-	for (i = s->urbs_submitted - 1; i >= 0; i--) {
-		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
-		/* stop the URB */
-		usb_kill_urb(s->urb_list[i]);
-	}
-	s->urbs_submitted = 0;
-
-	return 0;
-}
-
-static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s)
-{
-	int i, ret;
-
-	for (i = 0; i < s->urbs_initialized; i++) {
-		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
-		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
-		if (ret) {
-			dev_err(&s->udev->dev,
-					"Could not submit urb no. %d - get them all back\n",
-					i);
-			rtl2832_sdr_kill_urbs(s);
-			return ret;
-		}
-		s->urbs_submitted++;
-	}
-
-	return 0;
-}
-
-static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s)
-{
-	if (s->flags & USB_STATE_URB_BUF) {
-		while (s->buf_num) {
-			s->buf_num--;
-			dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
-					__func__, s->buf_num);
-			usb_free_coherent(s->udev, s->buf_size,
-					  s->buf_list[s->buf_num],
-					  s->dma_addr[s->buf_num]);
-		}
-	}
-	s->flags &= ~USB_STATE_URB_BUF;
-
-	return 0;
-}
-
-static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s)
-{
-	s->buf_num = 0;
-	s->buf_size = BULK_BUFFER_SIZE;
-
-	dev_dbg(&s->udev->dev,
-			"%s: all in all I will use %u bytes for streaming\n",
-			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE);
-
-	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
-		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
-				BULK_BUFFER_SIZE, GFP_ATOMIC,
-				&s->dma_addr[s->buf_num]);
-		if (!s->buf_list[s->buf_num]) {
-			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
-					__func__, s->buf_num);
-			rtl2832_sdr_free_stream_bufs(s);
-			return -ENOMEM;
-		}
-
-		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
-				__func__, s->buf_num,
-				s->buf_list[s->buf_num],
-				(long long)s->dma_addr[s->buf_num]);
-		s->flags |= USB_STATE_URB_BUF;
-	}
-
-	return 0;
-}
-
-static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s)
-{
-	int i;
-
-	rtl2832_sdr_kill_urbs(s);
-
-	for (i = s->urbs_initialized - 1; i >= 0; i--) {
-		if (s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
-					__func__, i);
-			/* free the URBs */
-			usb_free_urb(s->urb_list[i]);
-		}
-	}
-	s->urbs_initialized = 0;
-
-	return 0;
-}
-
-static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
-{
-	int i, j;
-
-	/* allocate the URBs */
-	for (i = 0; i < MAX_BULK_BUFS; i++) {
-		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
-		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
-		if (!s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
-			for (j = 0; j < i; j++)
-				usb_free_urb(s->urb_list[j]);
-			return -ENOMEM;
-		}
-		usb_fill_bulk_urb(s->urb_list[i],
-				s->udev,
-				usb_rcvbulkpipe(s->udev, 0x81),
-				s->buf_list[i],
-				BULK_BUFFER_SIZE,
-				rtl2832_sdr_urb_complete, s);
-
-		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-		s->urb_list[i]->transfer_dma = s->dma_addr[i];
-		s->urbs_initialized++;
-	}
-
-	return 0;
-}
-
-/* Must be called with vb_queue_lock hold */
-static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
-{
-	unsigned long flags = 0;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	while (!list_empty(&s->queued_bufs)) {
-		struct rtl2832_sdr_frame_buf *buf;
-		buf = list_entry(s->queued_bufs.next,
-				struct rtl2832_sdr_frame_buf, list);
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-/* The user yanked out the cable... */
-static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
-{
-	struct rtl2832_sdr_state *s = fe->sec_priv;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->vb_queue_lock);
-	mutex_lock(&s->v4l2_lock);
-	/* No need to keep the urbs around after disconnection */
-	s->udev = NULL;
-
-	v4l2_device_disconnect(&s->v4l2_dev);
-	video_unregister_device(&s->vdev);
-	mutex_unlock(&s->v4l2_lock);
-	mutex_unlock(&s->vb_queue_lock);
-
-	v4l2_device_put(&s->v4l2_dev);
-
-	fe->sec_priv = NULL;
-}
-
-static int rtl2832_sdr_querycap(struct file *file, void *fh,
-		struct v4l2_capability *cap)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
-	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-/* Videobuf2 operations */
-static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
-		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
-	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
-
-	/* Need at least 8 buffers */
-	if (vq->num_buffers + *nbuffers < 8)
-		*nbuffers = 8 - vq->num_buffers;
-	*nplanes = 1;
-	/* 2 = max 16-bit sample returned */
-	sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2);
-	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
-			__func__, *nbuffers, sizes[0]);
-	return 0;
-}
-
-static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
-{
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
-
-	/* Don't allow queing new buffers after device disconnection */
-	if (!s->udev)
-		return -ENODEV;
-
-	return 0;
-}
-
-static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
-{
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
-	struct rtl2832_sdr_frame_buf *buf =
-			container_of(vb, struct rtl2832_sdr_frame_buf, vb);
-	unsigned long flags = 0;
-
-	/* Check the device has not disconnected between prep and queuing */
-	if (!s->udev) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-		return;
-	}
-
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	list_add_tail(&buf->list, &s->queued_bufs);
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
-{
-	struct dvb_frontend *fe = s->fe;
-	int ret;
-	unsigned int f_sr, f_if;
-	u8 buf[4], u8tmp1, u8tmp2;
-	u64 u64tmp;
-	u32 u32tmp;
-	dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
-
-	if (!test_bit(POWER_ON, &s->flags))
-		return 0;
-
-	if (s->f_adc == 0)
-		return 0;
-
-	f_sr = s->f_adc;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4);
-	if (ret)
-		goto err;
-
-	/* get IF from tuner */
-	if (fe->ops.tuner_ops.get_if_frequency)
-		ret = fe->ops.tuner_ops.get_if_frequency(fe, &f_if);
-	else
-		ret = -EINVAL;
-
-	if (ret)
-		goto err;
-
-	/* program IF */
-	u64tmp = f_if % s->cfg->xtal;
-	u64tmp *= 0x400000;
-	u64tmp = div_u64(u64tmp, s->cfg->xtal);
-	u64tmp = -u64tmp;
-	u32tmp = u64tmp & 0x3fffff;
-
-	dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n",
-			__func__, f_if, u32tmp);
-
-	buf[0] = (u32tmp >> 16) & 0xff;
-	buf[1] = (u32tmp >>  8) & 0xff;
-	buf[2] = (u32tmp >>  0) & 0xff;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3);
-	if (ret)
-		goto err;
-
-	/* BB / IF mode */
-	/* POR: 0x1b1=0x1f, 0x008=0x0d, 0x006=0x80 */
-	if (f_if) {
-		u8tmp1 = 0x1a; /* disable Zero-IF */
-		u8tmp2 = 0x8d; /* enable ADC I */
-	} else {
-		u8tmp1 = 0x1b; /* enable Zero-IF, DC, IQ */
-		u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
-	}
-
-	ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80);
-	if (ret)
-		goto err;
-
-	/* program sampling rate (resampling down) */
-	u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U);
-	u32tmp <<= 2;
-	buf[0] = (u32tmp >> 24) & 0xff;
-	buf[1] = (u32tmp >> 16) & 0xff;
-	buf[2] = (u32tmp >>  8) & 0xff;
-	buf[3] = (u32tmp >>  0) & 0xff;
-	ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4);
-	if (ret)
-		goto err;
-
-	/* low-pass filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x11c,
-			"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
-			20);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
-	if (ret)
-		goto err;
-
-	/* mode */
-	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
-	if (ret)
-		goto err;
-
-	/* FSM */
-	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3);
-	if (ret)
-		goto err;
-
-	/* PID filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1);
-	if (ret)
-		goto err;
-
-	/* used RF tuner based settings */
-	switch (s->cfg->tuner) {
-	case RTL2832_TUNER_E4000:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
-		break;
-	case RTL2832_TUNER_FC0012:
-	case RTL2832_TUNER_FC0013:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
-		break;
-	case RTL2832_TUNER_R820T:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
-		break;
-	default:
-		dev_notice(&s->udev->dev, "Unsupported tuner\n");
-	}
-
-	/* software reset */
-	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04);
-	if (ret)
-		goto err;
-err:
-	return ret;
-};
-
-static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s)
-{
-	int ret;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	/* PID filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1);
-	if (ret)
-		goto err;
-
-	/* mode */
-	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
-	if (ret)
-		goto err;
-
-	/* FSM */
-	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4);
-	if (ret)
-		goto err;
-err:
-	return;
-};
-
-static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
-{
-	struct dvb_frontend *fe = s->fe;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct v4l2_ctrl *bandwidth_auto;
-	struct v4l2_ctrl *bandwidth;
-
-	/*
-	 * tuner RF (Hz)
-	 */
-	if (s->f_tuner == 0)
-		return 0;
-
-	/*
-	 * bandwidth (Hz)
-	 */
-	bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
-	bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
-	if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
-		c->bandwidth_hz = s->f_adc;
-		v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
-	} else {
-		c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth);
-	}
-
-	c->frequency = s->f_tuner;
-	c->delivery_system = SYS_DVBT;
-
-	dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n",
-			__func__, c->frequency, c->bandwidth_hz);
-
-	if (!test_bit(POWER_ON, &s->flags))
-		return 0;
-
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	return 0;
-};
-
-static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
-{
-	struct dvb_frontend *fe = s->fe;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (fe->ops.tuner_ops.init)
-		fe->ops.tuner_ops.init(fe);
-
-	return 0;
-};
-
-static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
-{
-	struct dvb_frontend *fe = s->fe;
-
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (fe->ops.tuner_ops.sleep)
-		fe->ops.tuner_ops.sleep(fe);
-
-	return;
-};
-
-static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
-	int ret;
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (!s->udev)
-		return -ENODEV;
-
-	if (mutex_lock_interruptible(&s->v4l2_lock))
-		return -ERESTARTSYS;
-
-	if (s->d->props->power_ctrl)
-		s->d->props->power_ctrl(s->d, 1);
-
-	set_bit(POWER_ON, &s->flags);
-
-	ret = rtl2832_sdr_set_tuner(s);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_set_tuner_freq(s);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_set_adc(s);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_alloc_stream_bufs(s);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_sdr_alloc_urbs(s);
-	if (ret)
-		goto err;
-
-	s->sequence = 0;
-
-	ret = rtl2832_sdr_submit_urbs(s);
-	if (ret)
-		goto err;
-
-err:
-	mutex_unlock(&s->v4l2_lock);
-
-	return ret;
-}
-
-static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
-{
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	mutex_lock(&s->v4l2_lock);
-
-	rtl2832_sdr_kill_urbs(s);
-	rtl2832_sdr_free_urbs(s);
-	rtl2832_sdr_free_stream_bufs(s);
-	rtl2832_sdr_cleanup_queued_bufs(s);
-	rtl2832_sdr_unset_adc(s);
-	rtl2832_sdr_unset_tuner(s);
-
-	clear_bit(POWER_ON, &s->flags);
-
-	if (s->d->props->power_ctrl)
-		s->d->props->power_ctrl(s->d, 0);
-
-	mutex_unlock(&s->v4l2_lock);
-}
-
-static struct vb2_ops rtl2832_sdr_vb2_ops = {
-	.queue_setup            = rtl2832_sdr_queue_setup,
-	.buf_prepare            = rtl2832_sdr_buf_prepare,
-	.buf_queue              = rtl2832_sdr_buf_queue,
-	.start_streaming        = rtl2832_sdr_start_streaming,
-	.stop_streaming         = rtl2832_sdr_stop_streaming,
-	.wait_prepare           = vb2_ops_wait_prepare,
-	.wait_finish            = vb2_ops_wait_finish,
-};
-
-static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
-		struct v4l2_tuner *v)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
-			__func__, v->index, v->type);
-
-	if (v->index == 0) {
-		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
-		v->type = V4L2_TUNER_ADC;
-		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-		v->rangelow =   300000;
-		v->rangehigh = 3200000;
-	} else if (v->index == 1) {
-		strlcpy(v->name, "RF: <unknown>", sizeof(v->name));
-		v->type = V4L2_TUNER_RF;
-		v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-		v->rangelow =    50000000;
-		v->rangehigh = 2000000000;
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
-		const struct v4l2_tuner *v)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (v->index > 1)
-		return -EINVAL;
-	return 0;
-}
-
-static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
-		struct v4l2_frequency_band *band)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
-			__func__, band->tuner, band->type, band->index);
-
-	if (band->tuner == 0) {
-		if (band->index >= ARRAY_SIZE(bands_adc))
-			return -EINVAL;
-
-		*band = bands_adc[band->index];
-	} else if (band->tuner == 1) {
-		if (band->index >= ARRAY_SIZE(bands_fm))
-			return -EINVAL;
-
-		*band = bands_fm[band->index];
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
-		struct v4l2_frequency *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	int ret  = 0;
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
-			__func__, f->tuner, f->type);
-
-	if (f->tuner == 0) {
-		f->frequency = s->f_adc;
-		f->type = V4L2_TUNER_ADC;
-	} else if (f->tuner == 1) {
-		f->frequency = s->f_tuner;
-		f->type = V4L2_TUNER_RF;
-	} else {
-		return -EINVAL;
-	}
-
-	return ret;
-}
-
-static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
-		const struct v4l2_frequency *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	int ret, band;
-
-	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
-			__func__, f->tuner, f->type, f->frequency);
-
-	/* ADC band midpoints */
-	#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
-	#define BAND_ADC_1 ((bands_adc[1].rangehigh + bands_adc[2].rangelow) / 2)
-
-	if (f->tuner == 0 && f->type == V4L2_TUNER_ADC) {
-		if (f->frequency < BAND_ADC_0)
-			band = 0;
-		else if (f->frequency < BAND_ADC_1)
-			band = 1;
-		else
-			band = 2;
-
-		s->f_adc = clamp_t(unsigned int, f->frequency,
-				bands_adc[band].rangelow,
-				bands_adc[band].rangehigh);
-
-		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
-				__func__, s->f_adc);
-		ret = rtl2832_sdr_set_adc(s);
-	} else if (f->tuner == 1) {
-		s->f_tuner = clamp_t(unsigned int, f->frequency,
-				bands_fm[0].rangelow,
-				bands_fm[0].rangehigh);
-		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
-				__func__, f->frequency);
-
-		ret = rtl2832_sdr_set_tuner_freq(s);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_fmtdesc *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	if (f->index >= NUM_FORMATS)
-		return -EINVAL;
-
-	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
-	f->pixelformat = formats[f->index].pixelformat;
-
-	return 0;
-}
-
-static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	dev_dbg(&s->udev->dev, "%s:\n", __func__);
-
-	f->fmt.sdr.pixelformat = s->pixelformat;
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-
-	return 0;
-}
-
-static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	struct vb2_queue *q = &s->vb_queue;
-	int i;
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.sdr.pixelformat);
-
-	if (vb2_is_busy(q))
-		return -EBUSY;
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
-			s->pixelformat = f->fmt.sdr.pixelformat;
-			return 0;
-		}
-	}
-
-	f->fmt.sdr.pixelformat = formats[0].pixelformat;
-	s->pixelformat = formats[0].pixelformat;
-
-	return 0;
-}
-
-static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
-		struct v4l2_format *f)
-{
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	int i;
-	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
-			(char *)&f->fmt.sdr.pixelformat);
-
-	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
-			return 0;
-	}
-
-	f->fmt.sdr.pixelformat = formats[0].pixelformat;
-
-	return 0;
-}
-
-static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = {
-	.vidioc_querycap          = rtl2832_sdr_querycap,
-
-	.vidioc_enum_fmt_sdr_cap  = rtl2832_sdr_enum_fmt_sdr_cap,
-	.vidioc_g_fmt_sdr_cap     = rtl2832_sdr_g_fmt_sdr_cap,
-	.vidioc_s_fmt_sdr_cap     = rtl2832_sdr_s_fmt_sdr_cap,
-	.vidioc_try_fmt_sdr_cap   = rtl2832_sdr_try_fmt_sdr_cap,
-
-	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs       = vb2_ioctl_create_bufs,
-	.vidioc_prepare_buf       = vb2_ioctl_prepare_buf,
-	.vidioc_querybuf          = vb2_ioctl_querybuf,
-	.vidioc_qbuf              = vb2_ioctl_qbuf,
-	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
-
-	.vidioc_streamon          = vb2_ioctl_streamon,
-	.vidioc_streamoff         = vb2_ioctl_streamoff,
-
-	.vidioc_g_tuner           = rtl2832_sdr_g_tuner,
-	.vidioc_s_tuner           = rtl2832_sdr_s_tuner,
-
-	.vidioc_enum_freq_bands   = rtl2832_sdr_enum_freq_bands,
-	.vidioc_g_frequency       = rtl2832_sdr_g_frequency,
-	.vidioc_s_frequency       = rtl2832_sdr_s_frequency,
-
-	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-	.vidioc_log_status        = v4l2_ctrl_log_status,
-};
-
-static const struct v4l2_file_operations rtl2832_sdr_fops = {
-	.owner                    = THIS_MODULE,
-	.open                     = v4l2_fh_open,
-	.release                  = vb2_fop_release,
-	.read                     = vb2_fop_read,
-	.poll                     = vb2_fop_poll,
-	.mmap                     = vb2_fop_mmap,
-	.unlocked_ioctl           = video_ioctl2,
-};
-
-static struct video_device rtl2832_sdr_template = {
-	.name                     = "Realtek RTL2832 SDR",
-	.release                  = video_device_release_empty,
-	.fops                     = &rtl2832_sdr_fops,
-	.ioctl_ops                = &rtl2832_sdr_ioctl_ops,
-};
-
-static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct rtl2832_sdr_state *s =
-			container_of(ctrl->handler, struct rtl2832_sdr_state,
-					hdl);
-	struct dvb_frontend *fe = s->fe;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	dev_dbg(&s->udev->dev,
-			"%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
-			__func__, ctrl->id, ctrl->name, ctrl->val,
-			ctrl->minimum, ctrl->maximum, ctrl->step);
-
-	switch (ctrl->id) {
-	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
-	case V4L2_CID_RF_TUNER_BANDWIDTH:
-		/* TODO: these controls should be moved to tuner drivers */
-		if (s->bandwidth_auto->val) {
-			/* Round towards the closest legal value */
-			s32 val = s->f_adc + s->bandwidth->step / 2;
-			u32 offset;
-			val = clamp(val, s->bandwidth->minimum, s->bandwidth->maximum);
-			offset = val - s->bandwidth->minimum;
-			offset = s->bandwidth->step * (offset / s->bandwidth->step);
-			s->bandwidth->val = s->bandwidth->minimum + offset;
-		}
-
-		c->bandwidth_hz = s->bandwidth->val;
-
-		if (!test_bit(POWER_ON, &s->flags))
-			return 0;
-
-		if (fe->ops.tuner_ops.set_params)
-			ret = fe->ops.tuner_ops.set_params(fe);
-		else
-			ret = 0;
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = {
-	.s_ctrl = rtl2832_sdr_s_ctrl,
-};
-
-static void rtl2832_sdr_video_release(struct v4l2_device *v)
-{
-	struct rtl2832_sdr_state *s =
-			container_of(v, struct rtl2832_sdr_state, v4l2_dev);
-
-	v4l2_ctrl_handler_free(&s->hdl);
-	v4l2_device_unregister(&s->v4l2_dev);
-	kfree(s);
-}
-
-struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-		struct v4l2_subdev *sd)
-{
-	int ret;
-	struct rtl2832_sdr_state *s;
-	const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
-	struct dvb_usb_device *d = i2c_get_adapdata(i2c);
-
-	s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
-	if (s == NULL) {
-		dev_err(&d->udev->dev,
-				"Could not allocate memory for rtl2832_sdr_state\n");
-		return NULL;
-	}
-
-	/* setup the state */
-	s->fe = fe;
-	s->d = d;
-	s->udev = d->udev;
-	s->i2c = i2c;
-	s->cfg = cfg;
-	s->f_adc = bands_adc[0].rangelow;
-	s->f_tuner = bands_fm[0].rangelow;
-	s->pixelformat =  V4L2_SDR_FMT_CU8;
-
-	mutex_init(&s->v4l2_lock);
-	mutex_init(&s->vb_queue_lock);
-	spin_lock_init(&s->queued_bufs_lock);
-	INIT_LIST_HEAD(&s->queued_bufs);
-
-	/* Init videobuf2 queue structure */
-	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
-	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	s->vb_queue.drv_priv = s;
-	s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
-	s->vb_queue.ops = &rtl2832_sdr_vb2_ops;
-	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
-	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	ret = vb2_queue_init(&s->vb_queue);
-	if (ret) {
-		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
-		goto err_free_mem;
-	}
-
-	/* Register controls */
-	switch (s->cfg->tuner) {
-	case RTL2832_TUNER_E4000:
-		v4l2_ctrl_handler_init(&s->hdl, 9);
-		if (sd)
-			v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
-		break;
-	case RTL2832_TUNER_R820T:
-		v4l2_ctrl_handler_init(&s->hdl, 2);
-		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
-		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0);
-		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
-		break;
-	case RTL2832_TUNER_FC0012:
-	case RTL2832_TUNER_FC0013:
-		v4l2_ctrl_handler_init(&s->hdl, 2);
-		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
-		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000);
-		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
-		break;
-	default:
-		v4l2_ctrl_handler_init(&s->hdl, 0);
-		dev_notice(&s->udev->dev, "%s: Unsupported tuner\n",
-				KBUILD_MODNAME);
-		goto err_free_controls;
-	}
-
-	if (s->hdl.error) {
-		ret = s->hdl.error;
-		dev_err(&s->udev->dev, "Could not initialize controls\n");
-		goto err_free_controls;
-	}
-
-	/* Init video_device structure */
-	s->vdev = rtl2832_sdr_template;
-	s->vdev.queue = &s->vb_queue;
-	s->vdev.queue->lock = &s->vb_queue_lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
-	video_set_drvdata(&s->vdev, s);
-
-	/* Register the v4l2_device structure */
-	s->v4l2_dev.release = rtl2832_sdr_video_release;
-	ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register v4l2-device (%d)\n", ret);
-		goto err_free_controls;
-	}
-
-	s->v4l2_dev.ctrl_handler = &s->hdl;
-	s->vdev.v4l2_dev = &s->v4l2_dev;
-	s->vdev.lock = &s->v4l2_lock;
-	s->vdev.vfl_dir = VFL_DIR_RX;
-
-	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
-	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register as video device (%d)\n",
-				ret);
-		goto err_unregister_v4l2_dev;
-	}
-	dev_info(&s->udev->dev, "Registered as %s\n",
-			video_device_node_name(&s->vdev));
-
-	fe->sec_priv = s;
-	fe->ops.release_sec = rtl2832_sdr_release_sec;
-
-	dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
-			KBUILD_MODNAME);
-	return fe;
-
-err_unregister_v4l2_dev:
-	v4l2_device_unregister(&s->v4l2_dev);
-err_free_controls:
-	v4l2_ctrl_handler_free(&s->hdl);
-err_free_mem:
-	kfree(s);
-	return NULL;
-}
-EXPORT_SYMBOL(rtl2832_sdr_attach);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Realtek RTL2832 SDR driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
--- linux-libre-3.16-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/*
- * Realtek RTL2832U SDR driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License along
- *    with this program; if not, write to the Free Software Foundation, Inc.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * GNU Radio plugin "gr-kernel" for device usage will be on:
- * http://git.linuxtv.org/anttip/gr-kernel.git
- *
- * TODO:
- * Help is very highly welcome for these + all the others you could imagine:
- * - move controls to V4L2 API
- * - use libv4l2 for stream format conversions
- * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
- * - SDRSharp support
- */
-
-#ifndef RTL2832_SDR_H
-#define RTL2832_SDR_H
-
-#include <linux/kconfig.h>
-#include <media/v4l2-subdev.h>
-
-/* for config struct */
-#include "rtl2832.h"
-
-#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
-extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-	struct v4l2_subdev *sd);
-#else
-static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-	struct v4l2_subdev *sd)
-{
-	dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* RTL2832_SDR_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-config USB_SN9C102
-	tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)"
-	depends on VIDEO_V4L2 && MEDIA_USB_SUPPORT
-	---help---
-	  This driver is DEPRECATED, please use the gspca sonixb and
-	  sonixj modules instead.
-
-	  Say Y here if you want support for cameras based on SONiX SN9C101,
-	  SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
-
-	  See <file:drivers/staging/media/sn9c102/sn9c102.txt> for more info.
-
-	  If you have webcams that are only supported by this driver and not by
-	  the gspca driver, then contact the linux-media mailinglist.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sn9c102.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-sn9c102-objs := sn9c102_core.o \
-		sn9c102_hv7131d.o \
-		sn9c102_hv7131r.o \
-		sn9c102_mi0343.o \
-		sn9c102_mi0360.o \
-		sn9c102_mt9v111.o \
-		sn9c102_ov7630.o \
-		sn9c102_ov7660.o \
-		sn9c102_pas106b.o \
-		sn9c102_pas202bcb.o \
-		sn9c102_tas5110c1b.o \
-		sn9c102_tas5110d.o \
-		sn9c102_tas5130d1b.o
-
-obj-$(CONFIG_USB_SN9C102)       += sn9c102.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_config.h linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_config.h
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_config.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_config.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/***************************************************************************
- * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 _SN9C102_CONFIG_H_
-#define _SN9C102_CONFIG_H_
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-
-#define SN9C102_DEBUG
-#define SN9C102_DEBUG_LEVEL       2
-#define SN9C102_MAX_DEVICES       64
-#define SN9C102_PRESERVE_IMGSCALE 0
-#define SN9C102_FORCE_MUNMAP      0
-#define SN9C102_MAX_FRAMES        32
-#define SN9C102_URBS              2
-#define SN9C102_ISO_PACKETS       7
-#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT      300
-#define SN9C102_FRAME_TIMEOUT     0
-
-/*****************************************************************************/
-
-static const u8 SN9C102_Y_QTABLE0[64] = {
-	 8,   5,   5,   8,  12,  20,  25,  30,
-	 6,   6,   7,   9,  13,  29,  30,  27,
-	 7,   6,   8,  12,  20,  28,  34,  28,
-	 7,   8,  11,  14,  25,  43,  40,  31,
-	 9,  11,  18,  28,  34,  54,  51,  38,
-	12,  17,  27,  32,  40,  52,  56,  46,
-	24,  32,  39,  43,  51,  60,  60,  50,
-	36,  46,  47,  49,  56,  50,  51,  49
-};
-
-static const u8 SN9C102_UV_QTABLE0[64] = {
-	 8,   9,  12,  23,  49,  49,  49,  49,
-	 9,  10,  13,  33,  49,  49,  49,  49,
-	12,  13,  28,  49,  49,  49,  49,  49,
-	23,  33,  49,  49,  49,  49,  49,  49,
-	49,  49,  49,  49,  49,  49,  49,  49,
-	49,  49,  49,  49,  49,  49,  49,  49,
-	49,  49,  49,  49,  49,  49,  49,  49,
-	49,  49,  49,  49,  49,  49,  49,  49
-};
-
-static const u8 SN9C102_Y_QTABLE1[64] = {
-	16,  11,  10,  16,  24,  40,  51,  61,
-	12,  12,  14,  19,  26,  58,  60,  55,
-	14,  13,  16,  24,  40,  57,  69,  56,
-	14,  17,  22,  29,  51,  87,  80,  62,
-	18,  22,  37,  56,  68, 109, 103,  77,
-	24,  35,  55,  64,  81, 104, 113,  92,
-	49,  64,  78,  87, 103, 121, 120, 101,
-	72,  92,  95,  98, 112, 100, 103,  99
-};
-
-static const u8 SN9C102_UV_QTABLE1[64] = {
-	17,  18,  24,  47,  99,  99,  99,  99,
-	18,  21,  26,  66,  99,  99,  99,  99,
-	24,  26,  56,  99,  99,  99,  99,  99,
-	47,  66,  99,  99,  99,  99,  99,  99,
-	99,  99,  99,  99,  99,  99,  99,  99,
-	99,  99,  99,  99,  99,  99,  99,  99,
-	99,  99,  99,  99,  99,  99,  99,  99,
-	99,  99,  99,  99,  99,  99,  99,  99
-};
-
-#endif /* _SN9C102_CONFIG_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_core.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_core.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3465 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers                           *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program; if not, write to the Free Software             *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
- ***************************************************************************/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/compiler.h>
-#include <linux/ioctl.h>
-#include <linux/poll.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/version.h>
-#include <linux/page-flags.h>
-#include <asm/byteorder.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-#include "sn9c102.h"
-
-/*****************************************************************************/
-
-#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
-#define SN9C102_MODULE_ALIAS    "sn9c1xx"
-#define SN9C102_MODULE_AUTHOR   "(C) 2004-2007 Luca Risolia"
-#define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
-#define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.48"
-
-/*****************************************************************************/
-
-MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
-
-MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
-MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
-MODULE_ALIAS(SN9C102_MODULE_ALIAS);
-MODULE_VERSION(SN9C102_MODULE_VERSION);
-MODULE_LICENSE(SN9C102_MODULE_LICENSE);
-
-static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
-module_param_array(video_nr, short, NULL, 0444);
-MODULE_PARM_DESC(video_nr,
-		 " <-1|n[,...]>"
-		 "\nSpecify V4L2 minor mode number."
-		 "\n-1 = use next available (default)"
-		 "\n n = use minor number n (integer >= 0)"
-		 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
-		 " cameras this way."
-		 "\nFor example:"
-		 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
-		 "\nthe second camera and use auto for the first"
-		 "\none and for every other camera."
-		 "\n");
-
-static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
-			      SN9C102_FORCE_MUNMAP};
-module_param_array(force_munmap, bool, NULL, 0444);
-MODULE_PARM_DESC(force_munmap,
-		 " <0|1[,...]>"
-		 "\nForce the application to unmap previously"
-		 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
-		 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
-		 "\nthis feature. This parameter is specific for each"
-		 "\ndetected camera."
-		 "\n0 = do not force memory unmapping"
-		 "\n1 = force memory unmapping (save memory)"
-		 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
-		 "\n");
-
-static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
-				       SN9C102_FRAME_TIMEOUT};
-module_param_array(frame_timeout, uint, NULL, 0644);
-MODULE_PARM_DESC(frame_timeout,
-		 " <0|n[,...]>"
-		 "\nTimeout for a video frame in seconds before"
-		 "\nreturning an I/O error; 0 for infinity."
-		 "\nThis parameter is specific for each detected camera."
-		 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
-		 "\n");
-
-#ifdef SN9C102_DEBUG
-static unsigned short debug = SN9C102_DEBUG_LEVEL;
-module_param(debug, ushort, 0644);
-MODULE_PARM_DESC(debug,
-		 " <n>"
-		 "\nDebugging information level, from 0 to 3:"
-		 "\n0 = none (use carefully)"
-		 "\n1 = critical errors"
-		 "\n2 = significant informations"
-		 "\n3 = more verbose messages"
-		 "\nLevel 3 is useful for testing only."
-		 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
-		 "\n");
-#endif
-
-/*
-   Add the probe entries to this table. Be sure to add the entry in the right
-   place, since, on failure, the next probing routine is called according to
-   the order of the list below, from top to bottom.
-*/
-static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
-	&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
-	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
-	&sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
-	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-};
-
-/*****************************************************************************/
-
-static u32
-sn9c102_request_buffers(struct sn9c102_device *cam, u32 count,
-			enum sn9c102_io_method io)
-{
-	struct v4l2_pix_format *p = &(cam->sensor.pix_format);
-	struct v4l2_rect *r = &(cam->sensor.cropcap.bounds);
-	size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
-			   (p->width * p->height * p->priv) / 8 :
-			   (r->width * r->height * p->priv) / 8;
-	void *buff = NULL;
-	u32 i;
-
-	if (count > SN9C102_MAX_FRAMES)
-		count = SN9C102_MAX_FRAMES;
-
-	if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
-		imagesize += 589 + 2; /* length of JPEG header + EOI marker */
-
-	cam->nbuffers = count;
-	while (cam->nbuffers > 0) {
-		buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize));
-		if (buff)
-			break;
-		cam->nbuffers--;
-	}
-
-	for (i = 0; i < cam->nbuffers; i++) {
-		cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
-		cam->frame[i].buf.index = i;
-		cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
-		cam->frame[i].buf.length = imagesize;
-		cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		cam->frame[i].buf.sequence = 0;
-		cam->frame[i].buf.field = V4L2_FIELD_NONE;
-		cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
-		cam->frame[i].buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	}
-
-	return cam->nbuffers;
-}
-
-
-static void sn9c102_release_buffers(struct sn9c102_device *cam)
-{
-	if (cam->nbuffers) {
-		vfree(cam->frame[0].bufmem);
-		cam->nbuffers = 0;
-	}
-	cam->frame_current = NULL;
-}
-
-
-static void sn9c102_empty_framequeues(struct sn9c102_device *cam)
-{
-	u32 i;
-
-	INIT_LIST_HEAD(&cam->inqueue);
-	INIT_LIST_HEAD(&cam->outqueue);
-
-	for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
-		cam->frame[i].state = F_UNUSED;
-		cam->frame[i].buf.bytesused = 0;
-	}
-}
-
-
-static void sn9c102_requeue_outqueue(struct sn9c102_device *cam)
-{
-	struct sn9c102_frame_t *i;
-
-	list_for_each_entry(i, &cam->outqueue, frame) {
-		i->state = F_QUEUED;
-		list_add(&i->frame, &cam->inqueue);
-	}
-
-	INIT_LIST_HEAD(&cam->outqueue);
-}
-
-
-static void sn9c102_queue_unusedframes(struct sn9c102_device *cam)
-{
-	unsigned long lock_flags;
-	u32 i;
-
-	for (i = 0; i < cam->nbuffers; i++)
-		if (cam->frame[i].state == F_UNUSED) {
-			cam->frame[i].state = F_QUEUED;
-			spin_lock_irqsave(&cam->queue_lock, lock_flags);
-			list_add_tail(&cam->frame[i].frame, &cam->inqueue);
-			spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-		}
-}
-
-/*****************************************************************************/
-
-/*
-   Write a sequence of count value/register pairs. Returns -1 after the first
-   failed write, or 0 for no errors.
-*/
-int sn9c102_write_regs(struct sn9c102_device *cam, const u8 valreg[][2],
-		       int count)
-{
-	struct usb_device *udev = cam->usbdev;
-	u8 *buff = cam->control_buffer;
-	int i, res;
-
-	for (i = 0; i < count; i++) {
-		u8 index = valreg[i][1];
-
-		/*
-		   index is a u8, so it must be <256 and can't be out of range.
-		   If we put in a check anyway, gcc annoys us with a warning
-		   hat our check is useless. People get all uppity when they
-		   see warnings in the kernel compile.
-		*/
-
-		*buff = valreg[i][0];
-
-		res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
-				      0x41, index, 0, buff, 1,
-				      SN9C102_CTRL_TIMEOUT);
-
-		if (res < 0) {
-			DBG(3, "Failed to write a register (value 0x%02X, "
-			       "index 0x%02X, error %d)", *buff, index, res);
-			return -1;
-		}
-
-		cam->reg[index] = *buff;
-	}
-
-	return 0;
-}
-
-
-int sn9c102_write_reg(struct sn9c102_device *cam, u8 value, u16 index)
-{
-	struct usb_device *udev = cam->usbdev;
-	u8 *buff = cam->control_buffer;
-	int res;
-
-	if (index >= ARRAY_SIZE(cam->reg))
-		return -1;
-
-	*buff = value;
-
-	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-			      index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
-	if (res < 0) {
-		DBG(3, "Failed to write a register (value 0x%02X, index "
-		       "0x%02X, error %d)", value, index, res);
-		return -1;
-	}
-
-	cam->reg[index] = value;
-
-	return 0;
-}
-
-
-/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
-int sn9c102_read_reg(struct sn9c102_device *cam, u16 index)
-{
-	struct usb_device *udev = cam->usbdev;
-	u8 *buff = cam->control_buffer;
-	int res;
-
-	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-			      index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
-	if (res < 0)
-		DBG(3, "Failed to read a register (index 0x%02X, error %d)",
-		    index, res);
-
-	return (res >= 0) ? (int)(*buff) : -1;
-}
-
-
-int sn9c102_pread_reg(struct sn9c102_device *cam, u16 index)
-{
-	if (index >= ARRAY_SIZE(cam->reg))
-		return -1;
-
-	return cam->reg[index];
-}
-
-
-static int
-sn9c102_i2c_wait(struct sn9c102_device *cam,
-		 const struct sn9c102_sensor *sensor)
-{
-	int i, r;
-
-	for (i = 1; i <= 5; i++) {
-		r = sn9c102_read_reg(cam, 0x08);
-		if (r < 0)
-			return -EIO;
-		if (r & 0x04)
-			return 0;
-		if (sensor->frequency & SN9C102_I2C_400KHZ)
-			udelay(5*16);
-		else
-			udelay(16*16);
-	}
-	return -EBUSY;
-}
-
-
-static int
-sn9c102_i2c_detect_read_error(struct sn9c102_device *cam,
-			      const struct sn9c102_sensor *sensor)
-{
-	int r , err = 0;
-
-	r = sn9c102_read_reg(cam, 0x08);
-	if (r < 0)
-		err += r;
-
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-		if (!(r & 0x08))
-			err += -1;
-	} else {
-		if (r & 0x08)
-			err += -1;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_i2c_detect_write_error(struct sn9c102_device *cam,
-			       const struct sn9c102_sensor *sensor)
-{
-	int r;
-
-	r = sn9c102_read_reg(cam, 0x08);
-	return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
-}
-
-
-int
-sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
-			 const struct sn9c102_sensor *sensor, u8 data0,
-			 u8 data1, u8 n, u8 buffer[])
-{
-	struct usb_device *udev = cam->usbdev;
-	u8 *data = cam->control_buffer;
-	int i = 0, err = 0, res;
-
-	/* Write cycle */
-	data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-		  ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
-	data[1] = data0; /* I2C slave id */
-	data[2] = data1; /* address */
-	data[7] = 0x10;
-	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-			      0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-	if (res < 0)
-		err += res;
-
-	err += sn9c102_i2c_wait(cam, sensor);
-
-	/* Read cycle - n bytes */
-	data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-		  ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
-		  (n << 4) | 0x02;
-	data[1] = data0;
-	data[7] = 0x10;
-	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-			      0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-	if (res < 0)
-		err += res;
-
-	err += sn9c102_i2c_wait(cam, sensor);
-
-	/* The first read byte will be placed in data[4] */
-	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-			      0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
-	if (res < 0)
-		err += res;
-
-	err += sn9c102_i2c_detect_read_error(cam, sensor);
-
-	PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
-	      data[4]);
-
-	if (err) {
-		DBG(3, "I2C read failed for %s image sensor", sensor->name);
-		return -1;
-	}
-
-	if (buffer)
-		for (i = 0; i < n && i < 5; i++)
-			buffer[n-i-1] = data[4-i];
-
-	return (int)data[4];
-}
-
-
-int
-sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
-			  const struct sn9c102_sensor *sensor, u8 n, u8 data0,
-			  u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
-{
-	struct usb_device *udev = cam->usbdev;
-	u8 *data = cam->control_buffer;
-	int err = 0, res;
-
-	/* Write cycle. It usually is address + value */
-	data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-		  ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
-		  | ((n - 1) << 4);
-	data[1] = data0;
-	data[2] = data1;
-	data[3] = data2;
-	data[4] = data3;
-	data[5] = data4;
-	data[6] = data5;
-	data[7] = 0x17;
-	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-			      0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-	if (res < 0)
-		err += res;
-
-	err += sn9c102_i2c_wait(cam, sensor);
-	err += sn9c102_i2c_detect_write_error(cam, sensor);
-
-	if (err)
-		DBG(3, "I2C write failed for %s image sensor", sensor->name);
-
-	PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
-	      "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
-	      n, data0, data1, data2, data3, data4, data5);
-
-	return err ? -1 : 0;
-}
-
-
-int
-sn9c102_i2c_try_read(struct sn9c102_device *cam,
-		     const struct sn9c102_sensor *sensor, u8 address)
-{
-	return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
-					address, 1, NULL);
-}
-
-
-static int sn9c102_i2c_try_write(struct sn9c102_device *cam,
-				 const struct sn9c102_sensor *sensor,
-				 u8 address, u8 value)
-{
-	return sn9c102_i2c_try_raw_write(cam, sensor, 3,
-					 sensor->i2c_slave_id, address,
-					 value, 0, 0, 0);
-}
-
-
-int sn9c102_i2c_read(struct sn9c102_device *cam, u8 address)
-{
-	return sn9c102_i2c_try_read(cam, &cam->sensor, address);
-}
-
-
-int sn9c102_i2c_write(struct sn9c102_device *cam, u8 address, u8 value)
-{
-	return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
-}
-
-/*****************************************************************************/
-
-static size_t sn9c102_sof_length(struct sn9c102_device *cam)
-{
-	switch (cam->bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		return 12;
-	case BRIDGE_SN9C103:
-		return 18;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		return 62;
-	}
-
-	return 0;
-}
-
-
-static void*
-sn9c102_find_sof_header(struct sn9c102_device *cam, void *mem, size_t len)
-{
-	static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
-	const char *m = mem;
-	size_t soflen = 0, i, j;
-
-	soflen = sn9c102_sof_length(cam);
-
-	for (i = 0; i < len; i++) {
-		size_t b;
-
-		/* Read the variable part of the header */
-		if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
-			cam->sof.header[cam->sof.bytesread] = *(m+i);
-			if (++cam->sof.bytesread == soflen) {
-				cam->sof.bytesread = 0;
-				return mem + i;
-			}
-			continue;
-		}
-
-		/* Search for the SOF marker (fixed part) in the header */
-		for (j = 0, b = cam->sof.bytesread; j+b < sizeof(marker); j++) {
-			if (unlikely(i+j == len))
-				return NULL;
-			if (*(m+i+j) == marker[cam->sof.bytesread]) {
-				cam->sof.header[cam->sof.bytesread] = *(m+i+j);
-				if (++cam->sof.bytesread == sizeof(marker)) {
-					PDBGG("Bytes to analyze: %zd. SOF "
-					      "starts at byte #%zd", len, i);
-					i += j+1;
-					break;
-				}
-			} else {
-				cam->sof.bytesread = 0;
-				break;
-			}
-		}
-	}
-
-	return NULL;
-}
-
-
-static void*
-sn9c102_find_eof_header(struct sn9c102_device *cam, void *mem, size_t len)
-{
-	static const u8 eof_header[4][4] = {
-		{0x00, 0x00, 0x00, 0x00},
-		{0x40, 0x00, 0x00, 0x00},
-		{0x80, 0x00, 0x00, 0x00},
-		{0xc0, 0x00, 0x00, 0x00},
-	};
-	size_t i, j;
-
-	/* The EOF header does not exist in compressed data */
-	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
-	    cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-		return NULL;
-
-	/*
-	   The EOF header might cross the packet boundary, but this is not a
-	   problem, since the end of a frame is determined by checking its size
-	   in the first place.
-	*/
-	for (i = 0; (len >= 4) && (i <= len - 4); i++)
-		for (j = 0; j < ARRAY_SIZE(eof_header); j++)
-			if (!memcmp(mem + i, eof_header[j], 4))
-				return mem + i;
-
-	return NULL;
-}
-
-
-static void
-sn9c102_write_jpegheader(struct sn9c102_device *cam, struct sn9c102_frame_t *f)
-{
-	static const u8 jpeg_header[589] = {
-		0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
-		0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
-		0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
-		0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
-		0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
-		0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
-		0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
-		0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
-		0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
-		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
-		0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
-		0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
-		0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-		0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
-		0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-		0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
-		0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-		0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
-		0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
-		0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
-		0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
-		0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
-		0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-		0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
-		0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-		0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-		0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
-		0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
-		0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
-		0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
-		0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
-		0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
-		0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
-		0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-		0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-		0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
-		0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
-		0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
-		0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-		0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
-		0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-		0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
-		0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-		0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-		0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
-		0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
-		0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-		0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
-		0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
-		0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
-		0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
-		0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
-		0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-	};
-	u8 *pos = f->bufmem;
-
-	memcpy(pos, jpeg_header, sizeof(jpeg_header));
-	*(pos + 6) = 0x00;
-	*(pos + 7 + 64) = 0x01;
-	if (cam->compression.quality == 0) {
-		memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
-		memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
-	} else if (cam->compression.quality == 1) {
-		memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
-		memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
-	}
-	*(pos + 564) = cam->sensor.pix_format.width & 0xFF;
-	*(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
-	*(pos + 562) = cam->sensor.pix_format.height & 0xFF;
-	*(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
-	*(pos + 567) = 0x21;
-
-	f->buf.bytesused += sizeof(jpeg_header);
-}
-
-
-static void sn9c102_urb_complete(struct urb *urb)
-{
-	struct sn9c102_device *cam = urb->context;
-	struct sn9c102_frame_t **f;
-	size_t imagesize, soflen;
-	u8 i;
-	int err = 0;
-
-	if (urb->status == -ENOENT)
-		return;
-
-	f = &cam->frame_current;
-
-	if (cam->stream == STREAM_INTERRUPT) {
-		cam->stream = STREAM_OFF;
-		if ((*f))
-			(*f)->state = F_QUEUED;
-		cam->sof.bytesread = 0;
-		DBG(3, "Stream interrupted by application");
-		wake_up(&cam->wait_stream);
-	}
-
-	if (cam->state & DEV_DISCONNECTED)
-		return;
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		wake_up_interruptible(&cam->wait_frame);
-		return;
-	}
-
-	if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
-		goto resubmit_urb;
-
-	if (!(*f))
-		(*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
-				  frame);
-
-	imagesize = (cam->sensor.pix_format.width *
-		     cam->sensor.pix_format.height *
-		     cam->sensor.pix_format.priv) / 8;
-	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-		imagesize += 589; /* length of jpeg header */
-	soflen = sn9c102_sof_length(cam);
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		unsigned int img, len, status;
-		void *pos, *sof, *eof;
-
-		len = urb->iso_frame_desc[i].actual_length;
-		status = urb->iso_frame_desc[i].status;
-		pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
-
-		if (status) {
-			DBG(3, "Error in isochronous frame");
-			(*f)->state = F_ERROR;
-			cam->sof.bytesread = 0;
-			continue;
-		}
-
-		PDBGG("Isochrnous frame: length %u, #%u i", len, i);
-
-redo:
-		sof = sn9c102_find_sof_header(cam, pos, len);
-		if (likely(!sof)) {
-			eof = sn9c102_find_eof_header(cam, pos, len);
-			if ((*f)->state == F_GRABBING) {
-end_of_frame:
-				img = len;
-
-				if (eof)
-					img = (eof > pos) ? eof - pos - 1 : 0;
-
-				if ((*f)->buf.bytesused + img > imagesize) {
-					u32 b;
-					b = (*f)->buf.bytesused + img -
-					    imagesize;
-					img = imagesize - (*f)->buf.bytesused;
-					PDBGG("Expected EOF not found: video "
-					      "frame cut");
-					if (eof)
-						DBG(3, "Exceeded limit: +%u "
-						       "bytes", (unsigned)(b));
-				}
-
-				memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
-				       img);
-
-				if ((*f)->buf.bytesused == 0)
-					v4l2_get_timestamp(
-						&(*f)->buf.timestamp);
-
-				(*f)->buf.bytesused += img;
-
-				if ((*f)->buf.bytesused == imagesize ||
-				    ((cam->sensor.pix_format.pixelformat ==
-				      V4L2_PIX_FMT_SN9C10X ||
-				      cam->sensor.pix_format.pixelformat ==
-				      V4L2_PIX_FMT_JPEG) && eof)) {
-					u32 b;
-
-					b = (*f)->buf.bytesused;
-					(*f)->state = F_DONE;
-					(*f)->buf.sequence = ++cam->frame_count;
-
-					spin_lock(&cam->queue_lock);
-					list_move_tail(&(*f)->frame,
-						       &cam->outqueue);
-					if (!list_empty(&cam->inqueue))
-						(*f) = list_entry(
-							cam->inqueue.next,
-							struct sn9c102_frame_t,
-							frame);
-					else
-						(*f) = NULL;
-					spin_unlock(&cam->queue_lock);
-
-					memcpy(cam->sysfs.frame_header,
-					       cam->sof.header, soflen);
-
-					DBG(3, "Video frame captured: %lu "
-					       "bytes", (unsigned long)(b));
-
-					if (!(*f))
-						goto resubmit_urb;
-
-				} else if (eof) {
-					(*f)->state = F_ERROR;
-					DBG(3, "Not expected EOF after %lu "
-					       "bytes of image data",
-					    (unsigned long)
-					    ((*f)->buf.bytesused));
-				}
-
-				if (sof) /* (1) */
-					goto start_of_frame;
-
-			} else if (eof) {
-				DBG(3, "EOF without SOF");
-				continue;
-
-			} else {
-				PDBGG("Ignoring pointless isochronous frame");
-				continue;
-			}
-
-		} else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
-start_of_frame:
-			(*f)->state = F_GRABBING;
-			(*f)->buf.bytesused = 0;
-			len -= (sof - pos);
-			pos = sof;
-			if (cam->sensor.pix_format.pixelformat ==
-			    V4L2_PIX_FMT_JPEG)
-				sn9c102_write_jpegheader(cam, (*f));
-			DBG(3, "SOF detected: new video frame");
-			if (len)
-				goto redo;
-
-		} else if ((*f)->state == F_GRABBING) {
-			eof = sn9c102_find_eof_header(cam, pos, len);
-			if (eof && eof < sof)
-				goto end_of_frame; /* (1) */
-			else {
-				if (cam->sensor.pix_format.pixelformat ==
-				    V4L2_PIX_FMT_SN9C10X ||
-				    cam->sensor.pix_format.pixelformat ==
-				    V4L2_PIX_FMT_JPEG) {
-					if (sof - pos >= soflen) {
-						eof = sof - soflen;
-					} else { /* remove header */
-						eof = pos;
-						(*f)->buf.bytesused -=
-							(soflen - (sof - pos));
-					}
-					goto end_of_frame;
-				} else {
-					DBG(3, "SOF before expected EOF after "
-					       "%lu bytes of image data",
-					    (unsigned long)
-					    ((*f)->buf.bytesused));
-					goto start_of_frame;
-				}
-			}
-		}
-	}
-
-resubmit_urb:
-	urb->dev = cam->usbdev;
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err < 0 && err != -EPERM) {
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "usb_submit_urb() failed");
-	}
-
-	wake_up_interruptible(&cam->wait_frame);
-}
-
-
-static int sn9c102_start_transfer(struct sn9c102_device *cam)
-{
-	struct usb_device *udev = cam->usbdev;
-	struct urb *urb;
-	struct usb_host_interface *altsetting = usb_altnum_to_altsetting(
-						    usb_ifnum_to_if(udev, 0),
-						    SN9C102_ALTERNATE_SETTING);
-	const unsigned int psz = le16_to_cpu(altsetting->
-					     endpoint[0].desc.wMaxPacketSize);
-	s8 i, j;
-	int err = 0;
-
-	for (i = 0; i < SN9C102_URBS; i++) {
-		cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
-						  GFP_KERNEL);
-		if (!cam->transfer_buffer[i]) {
-			err = -ENOMEM;
-			DBG(1, "Not enough memory");
-			goto free_buffers;
-		}
-	}
-
-	for (i = 0; i < SN9C102_URBS; i++) {
-		urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
-		cam->urb[i] = urb;
-		if (!urb) {
-			err = -ENOMEM;
-			DBG(1, "usb_alloc_urb() failed");
-			goto free_urbs;
-		}
-		urb->dev = udev;
-		urb->context = cam;
-		urb->pipe = usb_rcvisocpipe(udev, 1);
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->number_of_packets = SN9C102_ISO_PACKETS;
-		urb->complete = sn9c102_urb_complete;
-		urb->transfer_buffer = cam->transfer_buffer[i];
-		urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
-		urb->interval = 1;
-		for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
-			urb->iso_frame_desc[j].offset = psz * j;
-			urb->iso_frame_desc[j].length = psz;
-		}
-	}
-
-	/* Enable video */
-	if (!(cam->reg[0x01] & 0x04)) {
-		err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
-		if (err) {
-			err = -EIO;
-			DBG(1, "I/O hardware error");
-			goto free_urbs;
-		}
-	}
-
-	err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
-	if (err) {
-		DBG(1, "usb_set_interface() failed");
-		goto free_urbs;
-	}
-
-	cam->frame_current = NULL;
-	cam->sof.bytesread = 0;
-
-	for (i = 0; i < SN9C102_URBS; i++) {
-		err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
-		if (err) {
-			for (j = i-1; j >= 0; j--)
-				usb_kill_urb(cam->urb[j]);
-			DBG(1, "usb_submit_urb() failed, error %d", err);
-			goto free_urbs;
-		}
-	}
-
-	return 0;
-
-free_urbs:
-	for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
-		usb_free_urb(cam->urb[i]);
-
-free_buffers:
-	for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
-		kfree(cam->transfer_buffer[i]);
-
-	return err;
-}
-
-
-static int sn9c102_stop_transfer(struct sn9c102_device *cam)
-{
-	struct usb_device *udev = cam->usbdev;
-	s8 i;
-	int err = 0;
-
-	if (cam->state & DEV_DISCONNECTED)
-		return 0;
-
-	for (i = SN9C102_URBS-1; i >= 0; i--) {
-		usb_kill_urb(cam->urb[i]);
-		usb_free_urb(cam->urb[i]);
-		kfree(cam->transfer_buffer[i]);
-	}
-
-	err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
-	if (err)
-		DBG(3, "usb_set_interface() failed");
-
-	return err;
-}
-
-
-static int sn9c102_stream_interrupt(struct sn9c102_device *cam)
-{
-	cam->stream = STREAM_INTERRUPT;
-	wait_event_timeout(cam->wait_stream,
-				     (cam->stream == STREAM_OFF) ||
-				     (cam->state & DEV_DISCONNECTED),
-				     SN9C102_URB_TIMEOUT);
-	if (cam->state & DEV_DISCONNECTED)
-		return -ENODEV;
-	else if (cam->stream != STREAM_OFF) {
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "URB timeout reached. The camera is misconfigured. "
-		       "To use it, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static u16 sn9c102_strtou16(const char *buff, size_t len, ssize_t *count)
-{
-	char str[7];
-	char *endp;
-	unsigned long val;
-
-	if (len < 6) {
-		strncpy(str, buff, len);
-		str[len] = '\0';
-	} else {
-		strncpy(str, buff, 6);
-		str[6] = '\0';
-	}
-
-	val = simple_strtoul(str, &endp, 0);
-
-	*count = 0;
-	if (val <= 0xffff)
-		*count = (ssize_t)(endp - str);
-	if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
-		*count += 1;
-
-	return (u16)val;
-}
-
-/*
-   NOTE 1: being inside one of the following methods implies that the v4l
-	   device exists for sure (see kobjects and reference counters)
-   NOTE 2: buffers are PAGE_SIZE long
-*/
-
-static ssize_t sn9c102_show_reg(struct device *cd,
-				struct device_attribute *attr, char *buf)
-{
-	struct sn9c102_device *cam;
-	ssize_t count;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	count = sprintf(buf, "%u\n", cam->sysfs.reg);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t
-sn9c102_store_reg(struct device *cd, struct device_attribute *attr,
-		  const char *buf, size_t len)
-{
-	struct sn9c102_device *cam;
-	u16 index;
-	ssize_t count;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	index = sn9c102_strtou16(buf, len, &count);
-	if (index >= ARRAY_SIZE(cam->reg) || !count) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EINVAL;
-	}
-
-	cam->sysfs.reg = index;
-
-	DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
-	DBG(3, "Written bytes: %zd", count);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t sn9c102_show_val(struct device *cd,
-				struct device_attribute *attr, char *buf)
-{
-	struct sn9c102_device *cam;
-	ssize_t count;
-	int val;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	val = sn9c102_read_reg(cam, cam->sysfs.reg);
-	if (val < 0) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EIO;
-	}
-
-	count = sprintf(buf, "%d\n", val);
-
-	DBG(3, "Read bytes: %zd, value: %d", count, val);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t
-sn9c102_store_val(struct device *cd, struct device_attribute *attr,
-		  const char *buf, size_t len)
-{
-	struct sn9c102_device *cam;
-	u16 value;
-	ssize_t count;
-	int err;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	value = sn9c102_strtou16(buf, len, &count);
-	if (!count) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EINVAL;
-	}
-
-	err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
-	if (err) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EIO;
-	}
-
-	DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
-	    cam->sysfs.reg, value);
-	DBG(3, "Written bytes: %zd", count);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_reg(struct device *cd,
-				    struct device_attribute *attr, char *buf)
-{
-	struct sn9c102_device *cam;
-	ssize_t count;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
-
-	DBG(3, "Read bytes: %zd", count);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_reg(struct device *cd, struct device_attribute *attr,
-		      const char *buf, size_t len)
-{
-	struct sn9c102_device *cam;
-	u16 index;
-	ssize_t count;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	index = sn9c102_strtou16(buf, len, &count);
-	if (!count) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EINVAL;
-	}
-
-	cam->sysfs.i2c_reg = index;
-
-	DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
-	DBG(3, "Written bytes: %zd", count);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_val(struct device *cd,
-				    struct device_attribute *attr, char *buf)
-{
-	struct sn9c102_device *cam;
-	ssize_t count;
-	int val;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENOSYS;
-	}
-
-	val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg);
-	if (val < 0) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EIO;
-	}
-
-	count = sprintf(buf, "%d\n", val);
-
-	DBG(3, "Read bytes: %zd, value: %d", count, val);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_val(struct device *cd, struct device_attribute *attr,
-		      const char *buf, size_t len)
-{
-	struct sn9c102_device *cam;
-	u16 value;
-	ssize_t count;
-	int err;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENOSYS;
-	}
-
-	value = sn9c102_strtou16(buf, len, &count);
-	if (!count) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EINVAL;
-	}
-
-	err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
-	if (err) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -EIO;
-	}
-
-	DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
-	    cam->sysfs.i2c_reg, value);
-	DBG(3, "Written bytes: %zd", count);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	return count;
-}
-
-
-static ssize_t
-sn9c102_store_green(struct device *cd, struct device_attribute *attr,
-		    const char *buf, size_t len)
-{
-	struct sn9c102_device *cam;
-	enum sn9c102_bridge bridge;
-	ssize_t res = 0;
-	u16 value;
-	ssize_t count;
-
-	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-		return -ERESTARTSYS;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam) {
-		mutex_unlock(&sn9c102_sysfs_lock);
-		return -ENODEV;
-	}
-
-	bridge = cam->bridge;
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-	value = sn9c102_strtou16(buf, len, &count);
-	if (!count)
-		return -EINVAL;
-
-	switch (bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		if (value > 0x0f)
-			return -EINVAL;
-		res = sn9c102_store_reg(cd, attr, "0x11", 4);
-		if (res >= 0)
-			res = sn9c102_store_val(cd, attr, buf, len);
-		break;
-	case BRIDGE_SN9C103:
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (value > 0x7f)
-			return -EINVAL;
-		res = sn9c102_store_reg(cd, attr, "0x07", 4);
-		if (res >= 0)
-			res = sn9c102_store_val(cd, attr, buf, len);
-		break;
-	}
-
-	return res;
-}
-
-
-static ssize_t
-sn9c102_store_blue(struct device *cd, struct device_attribute *attr,
-		   const char *buf, size_t len)
-{
-	ssize_t res = 0;
-	u16 value;
-	ssize_t count;
-
-	value = sn9c102_strtou16(buf, len, &count);
-	if (!count || value > 0x7f)
-		return -EINVAL;
-
-	res = sn9c102_store_reg(cd, attr, "0x06", 4);
-	if (res >= 0)
-		res = sn9c102_store_val(cd, attr, buf, len);
-
-	return res;
-}
-
-
-static ssize_t
-sn9c102_store_red(struct device *cd, struct device_attribute *attr,
-		  const char *buf, size_t len)
-{
-	ssize_t res = 0;
-	u16 value;
-	ssize_t count;
-
-	value = sn9c102_strtou16(buf, len, &count);
-	if (!count || value > 0x7f)
-		return -EINVAL;
-	res = sn9c102_store_reg(cd, attr, "0x05", 4);
-	if (res >= 0)
-		res = sn9c102_store_val(cd, attr, buf, len);
-
-	return res;
-}
-
-
-static ssize_t sn9c102_show_frame_header(struct device *cd,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct sn9c102_device *cam;
-	ssize_t count;
-
-	cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-	if (!cam)
-		return -ENODEV;
-
-	count = sizeof(cam->sysfs.frame_header);
-	memcpy(buf, cam->sysfs.frame_header, count);
-
-	DBG(3, "Frame header, read bytes: %zd", count);
-
-	return count;
-}
-
-
-static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
-static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
-static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
-		   sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
-static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
-		   sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
-static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
-
-
-static int sn9c102_create_sysfs(struct sn9c102_device *cam)
-{
-	struct device *dev = &(cam->v4ldev->dev);
-	int err = 0;
-
-	err = device_create_file(dev, &dev_attr_reg);
-	if (err)
-		goto err_out;
-	err = device_create_file(dev, &dev_attr_val);
-	if (err)
-		goto err_reg;
-	err = device_create_file(dev, &dev_attr_frame_header);
-	if (err)
-		goto err_val;
-
-	if (cam->sensor.sysfs_ops) {
-		err = device_create_file(dev, &dev_attr_i2c_reg);
-		if (err)
-			goto err_frame_header;
-		err = device_create_file(dev, &dev_attr_i2c_val);
-		if (err)
-			goto err_i2c_reg;
-	}
-
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-		err = device_create_file(dev, &dev_attr_green);
-		if (err)
-			goto err_i2c_val;
-	} else {
-		err = device_create_file(dev, &dev_attr_blue);
-		if (err)
-			goto err_i2c_val;
-		err = device_create_file(dev, &dev_attr_red);
-		if (err)
-			goto err_blue;
-	}
-
-	return 0;
-
-err_blue:
-	device_remove_file(dev, &dev_attr_blue);
-err_i2c_val:
-	if (cam->sensor.sysfs_ops)
-		device_remove_file(dev, &dev_attr_i2c_val);
-err_i2c_reg:
-	if (cam->sensor.sysfs_ops)
-		device_remove_file(dev, &dev_attr_i2c_reg);
-err_frame_header:
-	device_remove_file(dev, &dev_attr_frame_header);
-err_val:
-	device_remove_file(dev, &dev_attr_val);
-err_reg:
-	device_remove_file(dev, &dev_attr_reg);
-err_out:
-	return err;
-}
-#endif /* CONFIG_VIDEO_ADV_DEBUG */
-
-/*****************************************************************************/
-
-static int
-sn9c102_set_pix_format(struct sn9c102_device *cam, struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-	    pix->pixelformat == V4L2_PIX_FMT_JPEG) {
-		switch (cam->bridge) {
-		case BRIDGE_SN9C101:
-		case BRIDGE_SN9C102:
-		case BRIDGE_SN9C103:
-			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
-						 0x18);
-			break;
-		case BRIDGE_SN9C105:
-		case BRIDGE_SN9C120:
-			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
-						 0x18);
-			break;
-		}
-	} else {
-		switch (cam->bridge) {
-		case BRIDGE_SN9C101:
-		case BRIDGE_SN9C102:
-		case BRIDGE_SN9C103:
-			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
-						 0x18);
-			break;
-		case BRIDGE_SN9C105:
-		case BRIDGE_SN9C120:
-			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
-						 0x18);
-			break;
-		}
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_set_compression(struct sn9c102_device *cam,
-			struct v4l2_jpegcompression *compression)
-{
-	int i, err = 0;
-
-	switch (cam->bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-	case BRIDGE_SN9C103:
-		if (compression->quality == 0)
-			err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
-						 0x17);
-		else if (compression->quality == 1)
-			err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
-						 0x17);
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (compression->quality == 0) {
-			for (i = 0; i <= 63; i++) {
-				err += sn9c102_write_reg(cam,
-							 SN9C102_Y_QTABLE1[i],
-							 0x100 + i);
-				err += sn9c102_write_reg(cam,
-							 SN9C102_UV_QTABLE1[i],
-							 0x140 + i);
-			}
-			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
-						 0x18);
-		} else if (compression->quality == 1) {
-			for (i = 0; i <= 63; i++) {
-				err += sn9c102_write_reg(cam,
-							 SN9C102_Y_QTABLE1[i],
-							 0x100 + i);
-				err += sn9c102_write_reg(cam,
-							 SN9C102_UV_QTABLE1[i],
-							 0x140 + i);
-			}
-			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
-						 0x18);
-		}
-		break;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int sn9c102_set_scale(struct sn9c102_device *cam, u8 scale)
-{
-	u8 r = 0;
-	int err = 0;
-
-	if (scale == 1)
-		r = cam->reg[0x18] & 0xcf;
-	else if (scale == 2) {
-		r = cam->reg[0x18] & 0xcf;
-		r |= 0x10;
-	} else if (scale == 4)
-		r = cam->reg[0x18] | 0x20;
-
-	err += sn9c102_write_reg(cam, r, 0x18);
-	if (err)
-		return -EIO;
-
-	PDBGG("Scaling factor: %u", scale);
-
-	return 0;
-}
-
-
-static int sn9c102_set_crop(struct sn9c102_device *cam, struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top),
-	   h_size = (u8)(rect->width / 16),
-	   v_size = (u8)(rect->height / 16);
-	int err = 0;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-	err += sn9c102_write_reg(cam, h_size, 0x15);
-	err += sn9c102_write_reg(cam, v_size, 0x16);
-	if (err)
-		return -EIO;
-
-	PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-	      "%u %u %u %u", h_start, v_start, h_size, v_size);
-
-	return 0;
-}
-
-
-static int sn9c102_init(struct sn9c102_device *cam)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_control ctrl;
-	struct v4l2_queryctrl *qctrl;
-	struct v4l2_rect *rect;
-	u8 i = 0;
-	int err = 0;
-
-	if (!(cam->state & DEV_INITIALIZED)) {
-		mutex_init(&cam->open_mutex);
-		init_waitqueue_head(&cam->wait_open);
-		qctrl = s->qctrl;
-		rect = &(s->cropcap.defrect);
-	} else { /* use current values */
-		qctrl = s->_qctrl;
-		rect = &(s->_rect);
-	}
-
-	err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
-	err += sn9c102_set_crop(cam, rect);
-	if (err)
-		return err;
-
-	if (s->init) {
-		err = s->init(cam);
-		if (err) {
-			DBG(3, "Sensor initialization failed");
-			return err;
-		}
-	}
-
-	if (!(cam->state & DEV_INITIALIZED))
-		if (cam->bridge == BRIDGE_SN9C101 ||
-		    cam->bridge == BRIDGE_SN9C102 ||
-		    cam->bridge == BRIDGE_SN9C103) {
-			if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-				s->pix_format.pixelformat = V4L2_PIX_FMT_SBGGR8;
-			cam->compression.quality =  cam->reg[0x17] & 0x01 ?
-						    0 : 1;
-		} else {
-			if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
-				s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
-			cam->compression.quality =  cam->reg[0x18] & 0x40 ?
-						    0 : 1;
-			err += sn9c102_set_compression(cam, &cam->compression);
-		}
-	else
-		err += sn9c102_set_compression(cam, &cam->compression);
-	err += sn9c102_set_pix_format(cam, &s->pix_format);
-	if (s->set_pix_format)
-		err += s->set_pix_format(cam, &s->pix_format);
-	if (err)
-		return err;
-
-	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
-	    s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-		DBG(3, "Compressed video format is active, quality %d",
-		    cam->compression.quality);
-	else
-		DBG(3, "Uncompressed video format is active");
-
-	if (s->set_crop) {
-		err = s->set_crop(cam, rect);
-		if (err) {
-			DBG(3, "set_crop() failed");
-			return err;
-		}
-	}
-
-	if (s->set_ctrl) {
-		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-			if (s->qctrl[i].id != 0 &&
-			    !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
-				ctrl.id = s->qctrl[i].id;
-				ctrl.value = qctrl[i].default_value;
-				err = s->set_ctrl(cam, &ctrl);
-				if (err) {
-					DBG(3, "Set %s control failed",
-					    s->qctrl[i].name);
-					return err;
-				}
-				DBG(3, "Image sensor supports '%s' control",
-				    s->qctrl[i].name);
-			}
-	}
-
-	if (!(cam->state & DEV_INITIALIZED)) {
-		mutex_init(&cam->fileop_mutex);
-		spin_lock_init(&cam->queue_lock);
-		init_waitqueue_head(&cam->wait_frame);
-		init_waitqueue_head(&cam->wait_stream);
-		cam->nreadbuffers = 2;
-		memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
-		memcpy(&(s->_rect), &(s->cropcap.defrect),
-		       sizeof(struct v4l2_rect));
-		cam->state |= DEV_INITIALIZED;
-	}
-
-	DBG(2, "Initialization succeeded");
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void sn9c102_release_resources(struct kref *kref)
-{
-	struct sn9c102_device *cam;
-
-	mutex_lock(&sn9c102_sysfs_lock);
-
-	cam = container_of(kref, struct sn9c102_device, kref);
-
-	DBG(2, "V4L2 device %s deregistered",
-	    video_device_node_name(cam->v4ldev));
-	video_set_drvdata(cam->v4ldev, NULL);
-	video_unregister_device(cam->v4ldev);
-	v4l2_device_unregister(&cam->v4l2_dev);
-	usb_put_dev(cam->usbdev);
-	kfree(cam->control_buffer);
-	kfree(cam);
-
-	mutex_unlock(&sn9c102_sysfs_lock);
-
-}
-
-
-static int sn9c102_open(struct file *filp)
-{
-	struct sn9c102_device *cam;
-	int err = 0;
-
-	/*
-	   A read_trylock() in open() is the only safe way to prevent race
-	   conditions with disconnect(), one close() and multiple (not
-	   necessarily simultaneous) attempts to open(). For example, it
-	   prevents from waiting for a second access, while the device
-	   structure is being deallocated, after a possible disconnect() and
-	   during a following close() holding the write lock: given that, after
-	   this deallocation, no access will be possible anymore, using the
-	   non-trylock version would have let open() gain the access to the
-	   device structure improperly.
-	   For this reason the lock must also not be per-device.
-	*/
-	if (!down_read_trylock(&sn9c102_dev_lock))
-		return -ERESTARTSYS;
-
-	cam = video_drvdata(filp);
-
-	if (wait_for_completion_interruptible(&cam->probe)) {
-		up_read(&sn9c102_dev_lock);
-		return -ERESTARTSYS;
-	}
-
-	kref_get(&cam->kref);
-
-	/*
-	    Make sure to isolate all the simultaneous opens.
-	*/
-	if (mutex_lock_interruptible(&cam->open_mutex)) {
-		kref_put(&cam->kref, sn9c102_release_resources);
-		up_read(&sn9c102_dev_lock);
-		return -ERESTARTSYS;
-	}
-
-	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present");
-		err = -ENODEV;
-		goto out;
-	}
-
-	if (cam->users) {
-		DBG(2, "Device %s is already in use",
-		    video_device_node_name(cam->v4ldev));
-		DBG(3, "Simultaneous opens are not supported");
-		/*
-		   open() must follow the open flags and should block
-		   eventually while the device is in use.
-		*/
-		if ((filp->f_flags & O_NONBLOCK) ||
-		    (filp->f_flags & O_NDELAY)) {
-			err = -EWOULDBLOCK;
-			goto out;
-		}
-		DBG(2, "A blocking open() has been requested. Wait for the "
-		       "device to be released...");
-		up_read(&sn9c102_dev_lock);
-		/*
-		   We will not release the "open_mutex" lock, so that only one
-		   process can be in the wait queue below. This way the process
-		   will be sleeping while holding the lock, without losing its
-		   priority after any wake_up().
-		*/
-		err = wait_event_interruptible_exclusive(cam->wait_open,
-						(cam->state & DEV_DISCONNECTED)
-							 || !cam->users);
-		down_read(&sn9c102_dev_lock);
-		if (err)
-			goto out;
-		if (cam->state & DEV_DISCONNECTED) {
-			err = -ENODEV;
-			goto out;
-		}
-	}
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		err = sn9c102_init(cam);
-		if (err) {
-			DBG(1, "Initialization failed again. "
-			       "I will retry on next open().");
-			goto out;
-		}
-		cam->state &= ~DEV_MISCONFIGURED;
-	}
-
-	err = sn9c102_start_transfer(cam);
-	if (err)
-		goto out;
-
-	filp->private_data = cam;
-	cam->users++;
-	cam->io = IO_NONE;
-	cam->stream = STREAM_OFF;
-	cam->nbuffers = 0;
-	cam->frame_count = 0;
-	sn9c102_empty_framequeues(cam);
-
-	DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
-
-out:
-	mutex_unlock(&cam->open_mutex);
-	if (err)
-		kref_put(&cam->kref, sn9c102_release_resources);
-
-	up_read(&sn9c102_dev_lock);
-	return err;
-}
-
-
-static int sn9c102_release(struct file *filp)
-{
-	struct sn9c102_device *cam;
-
-	down_write(&sn9c102_dev_lock);
-
-	cam = video_drvdata(filp);
-
-	sn9c102_stop_transfer(cam);
-	sn9c102_release_buffers(cam);
-	cam->users--;
-	wake_up_interruptible_nr(&cam->wait_open, 1);
-
-	DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
-
-	kref_put(&cam->kref, sn9c102_release_resources);
-
-	up_write(&sn9c102_dev_lock);
-
-	return 0;
-}
-
-
-static ssize_t
-sn9c102_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
-	struct sn9c102_device *cam = video_drvdata(filp);
-	struct sn9c102_frame_t *f, *i;
-	unsigned long lock_flags;
-	long timeout;
-	int err = 0;
-
-	if (mutex_lock_interruptible(&cam->fileop_mutex))
-		return -ERESTARTSYS;
-
-	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
-	}
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it "
-		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
-	}
-
-	if (cam->io == IO_MMAP) {
-		DBG(3, "Close and open the device again to choose "
-		       "the read method");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EBUSY;
-	}
-
-	if (cam->io == IO_NONE) {
-		if (!sn9c102_request_buffers(cam, cam->nreadbuffers, IO_READ)) {
-			DBG(1, "read() failed, not enough memory");
-			mutex_unlock(&cam->fileop_mutex);
-			return -ENOMEM;
-		}
-		cam->io = IO_READ;
-		cam->stream = STREAM_ON;
-	}
-
-	if (list_empty(&cam->inqueue)) {
-		if (!list_empty(&cam->outqueue))
-			sn9c102_empty_framequeues(cam);
-		sn9c102_queue_unusedframes(cam);
-	}
-
-	if (!count) {
-		mutex_unlock(&cam->fileop_mutex);
-		return 0;
-	}
-
-	if (list_empty(&cam->outqueue)) {
-		if (filp->f_flags & O_NONBLOCK) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EAGAIN;
-		}
-		if (!cam->module_param.frame_timeout) {
-			err = wait_event_interruptible
-			      (cam->wait_frame,
-				(!list_empty(&cam->outqueue)) ||
-				(cam->state & DEV_DISCONNECTED) ||
-				(cam->state & DEV_MISCONFIGURED));
-			if (err) {
-				mutex_unlock(&cam->fileop_mutex);
-				return err;
-			}
-		} else {
-			timeout = wait_event_interruptible_timeout
-				  (cam->wait_frame,
-				    (!list_empty(&cam->outqueue)) ||
-				    (cam->state & DEV_DISCONNECTED) ||
-				    (cam->state & DEV_MISCONFIGURED),
-				    msecs_to_jiffies(
-					cam->module_param.frame_timeout * 1000
-				    )
-				  );
-			if (timeout < 0) {
-				mutex_unlock(&cam->fileop_mutex);
-				return timeout;
-			} else if (timeout == 0 &&
-				   !(cam->state & DEV_DISCONNECTED)) {
-				DBG(1, "Video frame timeout elapsed");
-				mutex_unlock(&cam->fileop_mutex);
-				return -EIO;
-			}
-		}
-		if (cam->state & DEV_DISCONNECTED) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -ENODEV;
-		}
-		if (cam->state & DEV_MISCONFIGURED) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EIO;
-		}
-	}
-
-	f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
-
-	if (count > f->buf.bytesused)
-		count = f->buf.bytesused;
-
-	if (copy_to_user(buf, f->bufmem, count)) {
-		err = -EFAULT;
-		goto exit;
-	}
-	*f_pos += count;
-
-exit:
-	spin_lock_irqsave(&cam->queue_lock, lock_flags);
-	list_for_each_entry(i, &cam->outqueue, frame)
-		i->state = F_UNUSED;
-	INIT_LIST_HEAD(&cam->outqueue);
-	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-	sn9c102_queue_unusedframes(cam);
-
-	PDBGG("Frame #%lu, bytes read: %zu",
-	      (unsigned long)f->buf.index, count);
-
-	mutex_unlock(&cam->fileop_mutex);
-
-	return count;
-}
-
-
-static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
-{
-	struct sn9c102_device *cam = video_drvdata(filp);
-	struct sn9c102_frame_t *f;
-	unsigned long lock_flags;
-	unsigned int mask = 0;
-
-	if (mutex_lock_interruptible(&cam->fileop_mutex))
-		return POLLERR;
-
-	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present");
-		goto error;
-	}
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it "
-		       "again.");
-		goto error;
-	}
-
-	if (cam->io == IO_NONE) {
-		if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
-					     IO_READ)) {
-			DBG(1, "poll() failed, not enough memory");
-			goto error;
-		}
-		cam->io = IO_READ;
-		cam->stream = STREAM_ON;
-	}
-
-	if (cam->io == IO_READ) {
-		spin_lock_irqsave(&cam->queue_lock, lock_flags);
-		list_for_each_entry(f, &cam->outqueue, frame)
-			f->state = F_UNUSED;
-		INIT_LIST_HEAD(&cam->outqueue);
-		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-		sn9c102_queue_unusedframes(cam);
-	}
-
-	poll_wait(filp, &cam->wait_frame, wait);
-
-	if (!list_empty(&cam->outqueue))
-		mask |= POLLIN | POLLRDNORM;
-
-	mutex_unlock(&cam->fileop_mutex);
-
-	return mask;
-
-error:
-	mutex_unlock(&cam->fileop_mutex);
-	return POLLERR;
-}
-
-
-static void sn9c102_vm_open(struct vm_area_struct *vma)
-{
-	struct sn9c102_frame_t *f = vma->vm_private_data;
-	f->vma_use_count++;
-}
-
-
-static void sn9c102_vm_close(struct vm_area_struct *vma)
-{
-	/* NOTE: buffers are not freed here */
-	struct sn9c102_frame_t *f = vma->vm_private_data;
-	f->vma_use_count--;
-}
-
-
-static const struct vm_operations_struct sn9c102_vm_ops = {
-	.open = sn9c102_vm_open,
-	.close = sn9c102_vm_close,
-};
-
-
-static int sn9c102_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct sn9c102_device *cam = video_drvdata(filp);
-	unsigned long size = vma->vm_end - vma->vm_start,
-		      start = vma->vm_start;
-	void *pos;
-	u32 i;
-
-	if (mutex_lock_interruptible(&cam->fileop_mutex))
-		return -ERESTARTSYS;
-
-	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
-	}
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it "
-		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
-	}
-
-	if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EACCES;
-	}
-
-	if (cam->io != IO_MMAP ||
-	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < cam->nbuffers; i++) {
-		if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
-			break;
-	}
-	if (i == cam->nbuffers) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
-	}
-
-	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
-
-	pos = cam->frame[i].bufmem;
-	while (size > 0) { /* size is page-aligned */
-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	vma->vm_ops = &sn9c102_vm_ops;
-	vma->vm_private_data = &cam->frame[i];
-	sn9c102_vm_open(vma);
-
-	mutex_unlock(&cam->fileop_mutex);
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int
-sn9c102_vidioc_querycap(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_capability cap = {
-		.driver = "sn9c102",
-		.version = LINUX_VERSION_CODE,
-		.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING,
-	};
-
-	strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
-	if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
-		strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
-			sizeof(cap.bus_info));
-
-	if (copy_to_user(arg, &cap, sizeof(cap)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_enuminput(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_input i;
-
-	if (copy_from_user(&i, arg, sizeof(i)))
-		return -EFAULT;
-
-	if (i.index)
-		return -EINVAL;
-
-	memset(&i, 0, sizeof(i));
-	strcpy(i.name, "Camera");
-	i.type = V4L2_INPUT_TYPE_CAMERA;
-	i.capabilities = V4L2_IN_CAP_STD;
-
-	if (copy_to_user(arg, &i, sizeof(i)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_input(struct sn9c102_device *cam, void __user *arg)
-{
-	int index = 0;
-
-	if (copy_to_user(arg, &index, sizeof(index)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_input(struct sn9c102_device *cam, void __user *arg)
-{
-	int index;
-
-	if (copy_from_user(&index, arg, sizeof(index)))
-		return -EFAULT;
-
-	if (index != 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_query_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_queryctrl qc;
-	u8 i;
-
-	if (copy_from_user(&qc, arg, sizeof(qc)))
-		return -EFAULT;
-
-	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-		if (qc.id && qc.id == s->qctrl[i].id) {
-			memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
-			if (copy_to_user(arg, &qc, sizeof(qc)))
-				return -EFAULT;
-			return 0;
-		}
-
-	return -EINVAL;
-}
-
-
-static int
-sn9c102_vidioc_g_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_control ctrl;
-	int err = 0;
-	u8 i;
-
-	if (!s->get_ctrl && !s->set_ctrl)
-		return -EINVAL;
-
-	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-		return -EFAULT;
-
-	if (!s->get_ctrl) {
-		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-			if (ctrl.id && ctrl.id == s->qctrl[i].id) {
-				ctrl.value = s->_qctrl[i].default_value;
-				goto exit;
-			}
-		return -EINVAL;
-	} else
-		err = s->get_ctrl(cam, &ctrl);
-
-exit:
-	if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
-		return -EFAULT;
-
-	PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
-	      (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
-	return err;
-}
-
-
-static int
-sn9c102_vidioc_s_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_control ctrl;
-	u8 i;
-	int err = 0;
-
-	if (!s->set_ctrl)
-		return -EINVAL;
-
-	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-		return -EFAULT;
-
-	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
-		if (ctrl.id == s->qctrl[i].id) {
-			if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
-				return -EINVAL;
-			if (ctrl.value < s->qctrl[i].minimum ||
-			    ctrl.value > s->qctrl[i].maximum)
-				return -ERANGE;
-			ctrl.value -= ctrl.value % s->qctrl[i].step;
-			break;
-		}
-	}
-	if (i == ARRAY_SIZE(s->qctrl))
-		return -EINVAL;
-	err = s->set_ctrl(cam, &ctrl);
-	if (err)
-		return err;
-
-	s->_qctrl[i].default_value = ctrl.value;
-
-	PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
-	      (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_cropcap(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_cropcap *cc = &(cam->sensor.cropcap);
-
-	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	cc->pixelaspect.numerator = 1;
-	cc->pixelaspect.denominator = 1;
-
-	if (copy_to_user(arg, cc, sizeof(*cc)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_crop(struct sn9c102_device *cam, void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_crop crop = {
-		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-	};
-
-	memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
-
-	if (copy_to_user(arg, &crop, sizeof(crop)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_crop(struct sn9c102_device *cam, void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_crop crop;
-	struct v4l2_rect *rect;
-	struct v4l2_rect *bounds = &(s->cropcap.bounds);
-	struct v4l2_pix_format *pix_format = &(s->pix_format);
-	u8 scale;
-	const enum sn9c102_stream_state stream = cam->stream;
-	const u32 nbuffers = cam->nbuffers;
-	u32 i;
-	int err = 0;
-
-	if (copy_from_user(&crop, arg, sizeof(crop)))
-		return -EFAULT;
-
-	rect = &(crop.c);
-
-	if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	if (cam->module_param.force_munmap)
-		for (i = 0; i < cam->nbuffers; i++)
-			if (cam->frame[i].vma_use_count) {
-				DBG(3, "VIDIOC_S_CROP failed. "
-				       "Unmap the buffers first.");
-				return -EBUSY;
-			}
-
-	/* Preserve R,G or B origin */
-	rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
-	rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
-
-	if (rect->width < 16)
-		rect->width = 16;
-	if (rect->height < 16)
-		rect->height = 16;
-	if (rect->width > bounds->width)
-		rect->width = bounds->width;
-	if (rect->height > bounds->height)
-		rect->height = bounds->height;
-	if (rect->left < bounds->left)
-		rect->left = bounds->left;
-	if (rect->top < bounds->top)
-		rect->top = bounds->top;
-	if (rect->left + rect->width > bounds->left + bounds->width)
-		rect->left = bounds->left+bounds->width - rect->width;
-	if (rect->top + rect->height > bounds->top + bounds->height)
-		rect->top = bounds->top+bounds->height - rect->height;
-
-	rect->width &= ~15L;
-	rect->height &= ~15L;
-
-	if (SN9C102_PRESERVE_IMGSCALE) {
-		/* Calculate the actual scaling factor */
-		u32 a, b;
-		a = rect->width * rect->height;
-		b = pix_format->width * pix_format->height;
-		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-	} else
-		scale = 1;
-
-	if (cam->stream == STREAM_ON) {
-		err = sn9c102_stream_interrupt(cam);
-		if (err)
-			return err;
-	}
-
-	if (copy_to_user(arg, &crop, sizeof(crop))) {
-		cam->stream = stream;
-		return -EFAULT;
-	}
-
-	if (cam->module_param.force_munmap || cam->io == IO_READ)
-		sn9c102_release_buffers(cam);
-
-	err = sn9c102_set_crop(cam, rect);
-	if (s->set_crop)
-		err += s->set_crop(cam, rect);
-	err += sn9c102_set_scale(cam, scale);
-
-	if (err) { /* atomic, no rollback in ioctl() */
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
-		       "use the camera, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -EIO;
-	}
-
-	s->pix_format.width = rect->width/scale;
-	s->pix_format.height = rect->height/scale;
-	memcpy(&(s->_rect), rect, sizeof(*rect));
-
-	if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
-	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
-		       "use the camera, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -ENOMEM;
-	}
-
-	if (cam->io == IO_READ)
-		sn9c102_empty_framequeues(cam);
-	else if (cam->module_param.force_munmap)
-		sn9c102_requeue_outqueue(cam);
-
-	cam->stream = stream;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_framesizes(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_frmsizeenum frmsize;
-
-	if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
-		return -EFAULT;
-
-	if (frmsize.index != 0)
-		return -EINVAL;
-
-	switch (cam->bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-	case BRIDGE_SN9C103:
-		if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
-		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
-			return -EINVAL;
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
-		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
-			return -EINVAL;
-		break;
-	}
-
-	frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
-	frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
-	frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
-	frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
-	frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
-	memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
-
-	if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_fmt(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_fmtdesc fmtd;
-
-	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
-		return -EFAULT;
-
-	if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	if (fmtd.index == 0) {
-		strcpy(fmtd.description, "bayer rgb");
-		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
-	} else if (fmtd.index == 1) {
-		switch (cam->bridge) {
-		case BRIDGE_SN9C101:
-		case BRIDGE_SN9C102:
-		case BRIDGE_SN9C103:
-			strcpy(fmtd.description, "compressed");
-			fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
-			break;
-		case BRIDGE_SN9C105:
-		case BRIDGE_SN9C120:
-			strcpy(fmtd.description, "JPEG");
-			fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
-			break;
-		}
-		fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
-	} else
-		return -EINVAL;
-
-	fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
-
-	if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_fmt(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_format format;
-	struct v4l2_pix_format *pfmt = &(cam->sensor.pix_format);
-
-	if (copy_from_user(&format, arg, sizeof(format)))
-		return -EFAULT;
-
-	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
-			   V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
-	pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-			      pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
-			     ? 0 : (pfmt->width * pfmt->priv) / 8;
-	pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
-	pfmt->field = V4L2_FIELD_NONE;
-	memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
-
-	if (copy_to_user(arg, &format, sizeof(format)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_try_s_fmt(struct sn9c102_device *cam, unsigned int cmd,
-			 void __user *arg)
-{
-	struct sn9c102_sensor *s = &cam->sensor;
-	struct v4l2_format format;
-	struct v4l2_pix_format *pix;
-	struct v4l2_pix_format *pfmt = &(s->pix_format);
-	struct v4l2_rect *bounds = &(s->cropcap.bounds);
-	struct v4l2_rect rect;
-	u8 scale;
-	const enum sn9c102_stream_state stream = cam->stream;
-	const u32 nbuffers = cam->nbuffers;
-	u32 i;
-	int err = 0;
-
-	if (copy_from_user(&format, arg, sizeof(format)))
-		return -EFAULT;
-
-	pix = &(format.fmt.pix);
-
-	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	memcpy(&rect, &(s->_rect), sizeof(rect));
-
-	{ /* calculate the actual scaling factor */
-		u32 a, b;
-		a = rect.width * rect.height;
-		b = pix->width * pix->height;
-		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-	}
-
-	rect.width = scale * pix->width;
-	rect.height = scale * pix->height;
-
-	if (rect.width < 16)
-		rect.width = 16;
-	if (rect.height < 16)
-		rect.height = 16;
-	if (rect.width > bounds->left + bounds->width - rect.left)
-		rect.width = bounds->left + bounds->width - rect.left;
-	if (rect.height > bounds->top + bounds->height - rect.top)
-		rect.height = bounds->top + bounds->height - rect.top;
-
-	rect.width &= ~15L;
-	rect.height &= ~15L;
-
-	{ /* adjust the scaling factor */
-		u32 a, b;
-		a = rect.width * rect.height;
-		b = pix->width * pix->height;
-		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-	}
-
-	pix->width = rect.width / scale;
-	pix->height = rect.height / scale;
-
-	switch (cam->bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-	case BRIDGE_SN9C103:
-		if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
-		    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
-			pix->pixelformat = pfmt->pixelformat;
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
-		    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
-			pix->pixelformat = pfmt->pixelformat;
-		break;
-	}
-	pix->priv = pfmt->priv; /* bpp */
-	pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
-			  V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
-	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-			     pix->pixelformat == V4L2_PIX_FMT_JPEG)
-			    ? 0 : (pix->width * pix->priv) / 8;
-	pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
-	pix->field = V4L2_FIELD_NONE;
-
-	if (cmd == VIDIOC_TRY_FMT) {
-		if (copy_to_user(arg, &format, sizeof(format)))
-			return -EFAULT;
-		return 0;
-	}
-
-	if (cam->module_param.force_munmap)
-		for (i = 0; i < cam->nbuffers; i++)
-			if (cam->frame[i].vma_use_count) {
-				DBG(3, "VIDIOC_S_FMT failed. Unmap the "
-				       "buffers first.");
-				return -EBUSY;
-			}
-
-	if (cam->stream == STREAM_ON) {
-		err = sn9c102_stream_interrupt(cam);
-		if (err)
-			return err;
-	}
-
-	if (copy_to_user(arg, &format, sizeof(format))) {
-		cam->stream = stream;
-		return -EFAULT;
-	}
-
-	if (cam->module_param.force_munmap  || cam->io == IO_READ)
-		sn9c102_release_buffers(cam);
-
-	err += sn9c102_set_pix_format(cam, pix);
-	err += sn9c102_set_crop(cam, &rect);
-	if (s->set_pix_format)
-		err += s->set_pix_format(cam, pix);
-	if (s->set_crop)
-		err += s->set_crop(cam, &rect);
-	err += sn9c102_set_scale(cam, scale);
-
-	if (err) { /* atomic, no rollback in ioctl() */
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
-		       "use the camera, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -EIO;
-	}
-
-	memcpy(pfmt, pix, sizeof(*pix));
-	memcpy(&(s->_rect), &rect, sizeof(rect));
-
-	if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
-	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
-		       "use the camera, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -ENOMEM;
-	}
-
-	if (cam->io == IO_READ)
-		sn9c102_empty_framequeues(cam);
-	else if (cam->module_param.force_munmap)
-		sn9c102_requeue_outqueue(cam);
-
-	cam->stream = stream;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_jpegcomp(struct sn9c102_device *cam, void __user *arg)
-{
-	if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_jpegcomp(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_jpegcompression jc;
-	const enum sn9c102_stream_state stream = cam->stream;
-	int err = 0;
-
-	if (copy_from_user(&jc, arg, sizeof(jc)))
-		return -EFAULT;
-
-	if (jc.quality != 0 && jc.quality != 1)
-		return -EINVAL;
-
-	if (cam->stream == STREAM_ON) {
-		err = sn9c102_stream_interrupt(cam);
-		if (err)
-			return err;
-	}
-
-	err += sn9c102_set_compression(cam, &jc);
-	if (err) { /* atomic, no rollback in ioctl() */
-		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
-		       "To use the camera, close and open %s again.",
-		    video_device_node_name(cam->v4ldev));
-		return -EIO;
-	}
-
-	cam->compression.quality = jc.quality;
-
-	cam->stream = stream;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_reqbufs(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_requestbuffers rb;
-	u32 i;
-	int err;
-
-	if (copy_from_user(&rb, arg, sizeof(rb)))
-		return -EFAULT;
-
-	if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-	    rb.memory != V4L2_MEMORY_MMAP)
-		return -EINVAL;
-
-	if (cam->io == IO_READ) {
-		DBG(3, "Close and open the device again to choose the mmap "
-		       "I/O method");
-		return -EBUSY;
-	}
-
-	for (i = 0; i < cam->nbuffers; i++)
-		if (cam->frame[i].vma_use_count) {
-			DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
-			       "still mapped.");
-			return -EBUSY;
-		}
-
-	if (cam->stream == STREAM_ON) {
-		err = sn9c102_stream_interrupt(cam);
-		if (err)
-			return err;
-	}
-
-	sn9c102_empty_framequeues(cam);
-
-	sn9c102_release_buffers(cam);
-	if (rb.count)
-		rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
-
-	if (copy_to_user(arg, &rb, sizeof(rb))) {
-		sn9c102_release_buffers(cam);
-		cam->io = IO_NONE;
-		return -EFAULT;
-	}
-
-	cam->io = rb.count ? IO_MMAP : IO_NONE;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_querybuf(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_buffer b;
-
-	if (copy_from_user(&b, arg, sizeof(b)))
-		return -EFAULT;
-
-	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
-		return -EINVAL;
-
-	b = cam->frame[b.index].buf;
-
-	if (cam->frame[b.index].vma_use_count)
-		b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-	if (cam->frame[b.index].state == F_DONE)
-		b.flags |= V4L2_BUF_FLAG_DONE;
-	else if (cam->frame[b.index].state != F_UNUSED)
-		b.flags |= V4L2_BUF_FLAG_QUEUED;
-
-	if (copy_to_user(arg, &b, sizeof(b)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_qbuf(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_buffer b;
-	unsigned long lock_flags;
-
-	if (copy_from_user(&b, arg, sizeof(b)))
-		return -EFAULT;
-
-	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-	    b.index >= cam->nbuffers || cam->io != IO_MMAP)
-		return -EINVAL;
-
-	if (cam->frame[b.index].state != F_UNUSED)
-		return -EINVAL;
-
-	cam->frame[b.index].state = F_QUEUED;
-
-	spin_lock_irqsave(&cam->queue_lock, lock_flags);
-	list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
-	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-	PDBGG("Frame #%lu queued", (unsigned long)b.index);
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_dqbuf(struct sn9c102_device *cam, struct file *filp,
-		     void __user *arg)
-{
-	struct v4l2_buffer b;
-	struct sn9c102_frame_t *f;
-	unsigned long lock_flags;
-	long timeout;
-	int err = 0;
-
-	if (copy_from_user(&b, arg, sizeof(b)))
-		return -EFAULT;
-
-	if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-		return -EINVAL;
-
-	if (list_empty(&cam->outqueue)) {
-		if (cam->stream == STREAM_OFF)
-			return -EINVAL;
-		if (filp->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		if (!cam->module_param.frame_timeout) {
-			err = wait_event_interruptible
-			      (cam->wait_frame,
-				(!list_empty(&cam->outqueue)) ||
-				(cam->state & DEV_DISCONNECTED) ||
-				(cam->state & DEV_MISCONFIGURED));
-			if (err)
-				return err;
-		} else {
-			timeout = wait_event_interruptible_timeout
-				  (cam->wait_frame,
-				    (!list_empty(&cam->outqueue)) ||
-				    (cam->state & DEV_DISCONNECTED) ||
-				    (cam->state & DEV_MISCONFIGURED),
-				    cam->module_param.frame_timeout *
-				    1000 * msecs_to_jiffies(1));
-			if (timeout < 0)
-				return timeout;
-			else if (timeout == 0 &&
-				 !(cam->state & DEV_DISCONNECTED)) {
-				DBG(1, "Video frame timeout elapsed");
-				return -EIO;
-			}
-		}
-		if (cam->state & DEV_DISCONNECTED)
-			return -ENODEV;
-		if (cam->state & DEV_MISCONFIGURED)
-			return -EIO;
-	}
-
-	spin_lock_irqsave(&cam->queue_lock, lock_flags);
-	f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
-	list_del(cam->outqueue.next);
-	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-	f->state = F_UNUSED;
-
-	b = f->buf;
-	if (f->vma_use_count)
-		b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-	if (copy_to_user(arg, &b, sizeof(b)))
-		return -EFAULT;
-
-	PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamon(struct sn9c102_device *cam, void __user *arg)
-{
-	int type;
-
-	if (copy_from_user(&type, arg, sizeof(type)))
-		return -EFAULT;
-
-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-		return -EINVAL;
-
-	cam->stream = STREAM_ON;
-
-	DBG(3, "Stream on");
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamoff(struct sn9c102_device *cam, void __user *arg)
-{
-	int type, err;
-
-	if (copy_from_user(&type, arg, sizeof(type)))
-		return -EFAULT;
-
-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-		return -EINVAL;
-
-	if (cam->stream == STREAM_ON) {
-		err = sn9c102_stream_interrupt(cam);
-		if (err)
-			return err;
-	}
-
-	sn9c102_empty_framequeues(cam);
-
-	DBG(3, "Stream off");
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_parm(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_streamparm sp;
-
-	if (copy_from_user(&sp, arg, sizeof(sp)))
-		return -EFAULT;
-
-	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	sp.parm.capture.extendedmode = 0;
-	sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-	if (copy_to_user(arg, &sp, sizeof(sp)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_parm(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_streamparm sp;
-
-	if (copy_from_user(&sp, arg, sizeof(sp)))
-		return -EFAULT;
-
-	if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	sp.parm.capture.extendedmode = 0;
-
-	if (sp.parm.capture.readbuffers == 0)
-		sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-	if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
-		sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
-
-	if (copy_to_user(arg, &sp, sizeof(sp)))
-		return -EFAULT;
-
-	cam->nreadbuffers = sp.parm.capture.readbuffers;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_enumaudio(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_audio audio;
-
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-		return -EINVAL;
-
-	if (copy_from_user(&audio, arg, sizeof(audio)))
-		return -EFAULT;
-
-	if (audio.index != 0)
-		return -EINVAL;
-
-	strcpy(audio.name, "Microphone");
-	audio.capability = 0;
-	audio.mode = 0;
-
-	if (copy_to_user(arg, &audio, sizeof(audio)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_audio(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_audio audio;
-
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-		return -EINVAL;
-
-	if (copy_from_user(&audio, arg, sizeof(audio)))
-		return -EFAULT;
-
-	memset(&audio, 0, sizeof(audio));
-	strcpy(audio.name, "Microphone");
-
-	if (copy_to_user(arg, &audio, sizeof(audio)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_audio(struct sn9c102_device *cam, void __user *arg)
-{
-	struct v4l2_audio audio;
-
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-		return -EINVAL;
-
-	if (copy_from_user(&audio, arg, sizeof(audio)))
-		return -EFAULT;
-
-	if (audio.index != 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static long sn9c102_ioctl_v4l2(struct file *filp,
-			      unsigned int cmd, void __user *arg)
-{
-	struct sn9c102_device *cam = video_drvdata(filp);
-
-	switch (cmd) {
-
-	case VIDIOC_QUERYCAP:
-		return sn9c102_vidioc_querycap(cam, arg);
-
-	case VIDIOC_ENUMINPUT:
-		return sn9c102_vidioc_enuminput(cam, arg);
-
-	case VIDIOC_G_INPUT:
-		return sn9c102_vidioc_g_input(cam, arg);
-
-	case VIDIOC_S_INPUT:
-		return sn9c102_vidioc_s_input(cam, arg);
-
-	case VIDIOC_QUERYCTRL:
-		return sn9c102_vidioc_query_ctrl(cam, arg);
-
-	case VIDIOC_G_CTRL:
-		return sn9c102_vidioc_g_ctrl(cam, arg);
-
-	case VIDIOC_S_CTRL:
-		return sn9c102_vidioc_s_ctrl(cam, arg);
-
-	case VIDIOC_CROPCAP:
-		return sn9c102_vidioc_cropcap(cam, arg);
-
-	case VIDIOC_G_CROP:
-		return sn9c102_vidioc_g_crop(cam, arg);
-
-	case VIDIOC_S_CROP:
-		return sn9c102_vidioc_s_crop(cam, arg);
-
-	case VIDIOC_ENUM_FRAMESIZES:
-		return sn9c102_vidioc_enum_framesizes(cam, arg);
-
-	case VIDIOC_ENUM_FMT:
-		return sn9c102_vidioc_enum_fmt(cam, arg);
-
-	case VIDIOC_G_FMT:
-		return sn9c102_vidioc_g_fmt(cam, arg);
-
-	case VIDIOC_TRY_FMT:
-	case VIDIOC_S_FMT:
-		return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
-
-	case VIDIOC_G_JPEGCOMP:
-		return sn9c102_vidioc_g_jpegcomp(cam, arg);
-
-	case VIDIOC_S_JPEGCOMP:
-		return sn9c102_vidioc_s_jpegcomp(cam, arg);
-
-	case VIDIOC_REQBUFS:
-		return sn9c102_vidioc_reqbufs(cam, arg);
-
-	case VIDIOC_QUERYBUF:
-		return sn9c102_vidioc_querybuf(cam, arg);
-
-	case VIDIOC_QBUF:
-		return sn9c102_vidioc_qbuf(cam, arg);
-
-	case VIDIOC_DQBUF:
-		return sn9c102_vidioc_dqbuf(cam, filp, arg);
-
-	case VIDIOC_STREAMON:
-		return sn9c102_vidioc_streamon(cam, arg);
-
-	case VIDIOC_STREAMOFF:
-		return sn9c102_vidioc_streamoff(cam, arg);
-
-	case VIDIOC_G_PARM:
-		return sn9c102_vidioc_g_parm(cam, arg);
-
-	case VIDIOC_S_PARM:
-		return sn9c102_vidioc_s_parm(cam, arg);
-
-	case VIDIOC_ENUMAUDIO:
-		return sn9c102_vidioc_enumaudio(cam, arg);
-
-	case VIDIOC_G_AUDIO:
-		return sn9c102_vidioc_g_audio(cam, arg);
-
-	case VIDIOC_S_AUDIO:
-		return sn9c102_vidioc_s_audio(cam, arg);
-
-	default:
-		return -ENOTTY;
-
-	}
-}
-
-
-static long sn9c102_ioctl(struct file *filp,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct sn9c102_device *cam = video_drvdata(filp);
-	int err = 0;
-
-	if (mutex_lock_interruptible(&cam->fileop_mutex))
-		return -ERESTARTSYS;
-
-	if (cam->state & DEV_DISCONNECTED) {
-		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
-	}
-
-	if (cam->state & DEV_MISCONFIGURED) {
-		DBG(1, "The camera is misconfigured. Close and open it "
-		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
-	}
-
-	V4LDBG(3, "sn9c102", cmd);
-
-	err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
-
-	mutex_unlock(&cam->fileop_mutex);
-
-	return err;
-}
-
-/*****************************************************************************/
-
-static const struct v4l2_file_operations sn9c102_fops = {
-	.owner = THIS_MODULE,
-	.open = sn9c102_open,
-	.release = sn9c102_release,
-	.unlocked_ioctl = sn9c102_ioctl,
-	.read = sn9c102_read,
-	.poll = sn9c102_poll,
-	.mmap = sn9c102_mmap,
-};
-
-/*****************************************************************************/
-
-/* It exists a single interface only. We do not need to validate anything. */
-static int
-sn9c102_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct sn9c102_device *cam;
-	static unsigned int dev_nr;
-	unsigned int i;
-	int err = 0, r;
-
-	cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL);
-	if (!cam)
-		return -ENOMEM;
-
-	cam->usbdev = udev;
-
-	/* register v4l2_device early so it can be used for printks */
-	if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) {
-		dev_err(&intf->dev, "v4l2_device_register failed\n");
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	cam->control_buffer = kzalloc(8, GFP_KERNEL);
-	if (!cam->control_buffer) {
-		DBG(1, "kzalloc() failed");
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	cam->v4ldev = video_device_alloc();
-	if (!cam->v4ldev) {
-		DBG(1, "video_device_alloc() failed");
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	r = sn9c102_read_reg(cam, 0x00);
-	if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
-		DBG(1, "Sorry, this is not a SN9C1xx-based camera "
-		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-		err = -ENODEV;
-		goto fail;
-	}
-
-	cam->bridge = id->driver_info;
-	switch (cam->bridge) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		DBG(2, "SN9C10[12] PC Camera Controller detected "
-		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-		break;
-	case BRIDGE_SN9C103:
-		DBG(2, "SN9C103 PC Camera Controller detected "
-		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-		break;
-	case BRIDGE_SN9C105:
-		DBG(2, "SN9C105 PC Camera Controller detected "
-		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-		break;
-	case BRIDGE_SN9C120:
-		DBG(2, "SN9C120 PC Camera Controller detected "
-		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-		break;
-	}
-
-	for  (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
-		err = sn9c102_sensor_table[i](cam);
-		if (!err)
-			break;
-	}
-
-	if (!err) {
-		DBG(2, "%s image sensor detected", cam->sensor.name);
-		DBG(3, "Support for %s maintained by %s",
-		    cam->sensor.name, cam->sensor.maintainer);
-	} else {
-		DBG(1, "No supported image sensor detected for this bridge");
-		err = -ENODEV;
-		goto fail;
-	}
-
-	if (!(cam->bridge & cam->sensor.supported_bridge)) {
-		DBG(1, "Bridge not supported");
-		err = -ENODEV;
-		goto fail;
-	}
-
-	if (sn9c102_init(cam)) {
-		DBG(1, "Initialization failed. I will retry on open().");
-		cam->state |= DEV_MISCONFIGURED;
-	}
-
-	strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
-	cam->v4ldev->fops = &sn9c102_fops;
-	cam->v4ldev->release = video_device_release;
-	cam->v4ldev->v4l2_dev = &cam->v4l2_dev;
-
-	init_completion(&cam->probe);
-
-	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
-				    video_nr[dev_nr]);
-	if (err) {
-		DBG(1, "V4L2 device registration failed");
-		if (err == -ENFILE && video_nr[dev_nr] == -1)
-			DBG(1, "Free /dev/videoX node not found");
-		video_nr[dev_nr] = -1;
-		dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-		complete_all(&cam->probe);
-		goto fail;
-	}
-
-	DBG(2, "V4L2 device registered as %s",
-	    video_device_node_name(cam->v4ldev));
-
-	video_set_drvdata(cam->v4ldev, cam);
-	cam->module_param.force_munmap = force_munmap[dev_nr];
-	cam->module_param.frame_timeout = frame_timeout[dev_nr];
-
-	dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	err = sn9c102_create_sysfs(cam);
-	if (!err)
-		DBG(2, "Optional device control through 'sysfs' "
-		       "interface ready");
-	else
-		DBG(2, "Failed to create optional 'sysfs' interface for "
-		       "device controlling. Error #%d", err);
-#else
-	DBG(2, "Optional device control through 'sysfs' interface disabled");
-	DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
-	       "configuration option to enable it.");
-#endif
-
-	usb_set_intfdata(intf, cam);
-	kref_init(&cam->kref);
-	usb_get_dev(cam->usbdev);
-
-	complete_all(&cam->probe);
-
-	return 0;
-
-fail:
-	if (cam) {
-		kfree(cam->control_buffer);
-		if (cam->v4ldev)
-			video_device_release(cam->v4ldev);
-		v4l2_device_unregister(&cam->v4l2_dev);
-		kfree(cam);
-	}
-	return err;
-}
-
-
-static void sn9c102_usb_disconnect(struct usb_interface *intf)
-{
-	struct sn9c102_device *cam;
-
-	down_write(&sn9c102_dev_lock);
-
-	cam = usb_get_intfdata(intf);
-
-	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
-
-	if (cam->users) {
-		DBG(2, "Device %s is open! Deregistration and memory "
-		       "deallocation are deferred.",
-		    video_device_node_name(cam->v4ldev));
-		cam->state |= DEV_MISCONFIGURED;
-		sn9c102_stop_transfer(cam);
-		cam->state |= DEV_DISCONNECTED;
-		wake_up_interruptible(&cam->wait_frame);
-		wake_up(&cam->wait_stream);
-	} else
-		cam->state |= DEV_DISCONNECTED;
-
-	wake_up_interruptible_all(&cam->wait_open);
-
-	v4l2_device_disconnect(&cam->v4l2_dev);
-
-	kref_put(&cam->kref, sn9c102_release_resources);
-
-	up_write(&sn9c102_dev_lock);
-}
-
-
-static struct usb_driver sn9c102_usb_driver = {
-	.name =       "sn9c102",
-	.id_table =   sn9c102_id_table,
-	.probe =      sn9c102_usb_probe,
-	.disconnect = sn9c102_usb_disconnect,
-};
-
-module_usb_driver(sn9c102_usb_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_devtable.h linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_devtable.h
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_devtable.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_devtable.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/***************************************************************************
- * Table of device identifiers of the SN9C1xx PC Camera Controllers        *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 _SN9C102_DEVTABLE_H_
-#define _SN9C102_DEVTABLE_H_
-
-#include <linux/usb.h>
-
-struct sn9c102_device;
-
-/*
-   Each SN9C1xx camera has proper PID/VID identifiers.
-   SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
-   handle the video class interface.
-*/
-#define SN9C102_USB_DEVICE(vend, prod, bridge)                                \
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
-		       USB_DEVICE_ID_MATCH_INT_CLASS,                         \
-	.idVendor = (vend),                                                   \
-	.idProduct = (prod),                                                  \
-	.bInterfaceClass = 0xff,                                              \
-	.driver_info = (bridge)
-
-static const struct usb_device_id sn9c102_id_table[] = {
-	/* SN9C101 and SN9C102 */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
-#endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-	{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
-#endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
-	/* SN9C103 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
-#endif
-	/* SN9C105 */
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
-	{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
-	/* SN9C120 */
-	{ SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
-#endif
-	{ }
-};
-
-/*
-   Probing functions: on success, you must attach the sensor to the camera
-   by calling sn9c102_attach_sensor().
-   To enable the I2C communication, you might need to perform a really basic
-   initialization of the SN9C1XX chip.
-   Functions must return 0 on success, the appropriate error otherwise.
-*/
-extern int sn9c102_probe_hv7131d(struct sn9c102_device *cam);
-extern int sn9c102_probe_hv7131r(struct sn9c102_device *cam);
-extern int sn9c102_probe_mi0343(struct sn9c102_device *cam);
-extern int sn9c102_probe_mi0360(struct sn9c102_device *cam);
-extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
-extern int sn9c102_probe_ov7630(struct sn9c102_device *cam);
-extern int sn9c102_probe_ov7660(struct sn9c102_device *cam);
-extern int sn9c102_probe_pas106b(struct sn9c102_device *cam);
-extern int sn9c102_probe_pas202bcb(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5110d(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam);
-
-#endif /* _SN9C102_DEVTABLE_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102.h linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102.h
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,214 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers                           *
- *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 _SN9C102_H_
-#define _SN9C102_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/param.h>
-#include <linux/rwsem.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/stddef.h>
-#include <linux/kref.h>
-
-#include "sn9c102_config.h"
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-enum sn9c102_frame_state {
-	F_UNUSED,
-	F_QUEUED,
-	F_GRABBING,
-	F_DONE,
-	F_ERROR,
-};
-
-struct sn9c102_frame_t {
-	void *bufmem;
-	struct v4l2_buffer buf;
-	enum sn9c102_frame_state state;
-	struct list_head frame;
-	unsigned long vma_use_count;
-};
-
-enum sn9c102_dev_state {
-	DEV_INITIALIZED = 0x01,
-	DEV_DISCONNECTED = 0x02,
-	DEV_MISCONFIGURED = 0x04,
-};
-
-enum sn9c102_io_method {
-	IO_NONE,
-	IO_READ,
-	IO_MMAP,
-};
-
-enum sn9c102_stream_state {
-	STREAM_OFF,
-	STREAM_INTERRUPT,
-	STREAM_ON,
-};
-
-typedef char sn9c102_sof_header_t[62];
-
-struct sn9c102_sof_t {
-	sn9c102_sof_header_t header;
-	u16 bytesread;
-};
-
-struct sn9c102_sysfs_attr {
-	u16 reg, i2c_reg;
-	sn9c102_sof_header_t frame_header;
-};
-
-struct sn9c102_module_param {
-	u8 force_munmap;
-	u16 frame_timeout;
-};
-
-static DEFINE_MUTEX(sn9c102_sysfs_lock);
-static DECLARE_RWSEM(sn9c102_dev_lock);
-
-struct sn9c102_device {
-	struct video_device *v4ldev;
-
-	struct v4l2_device v4l2_dev;
-
-	enum sn9c102_bridge bridge;
-	struct sn9c102_sensor sensor;
-
-	struct usb_device *usbdev;
-	struct urb *urb[SN9C102_URBS];
-	void *transfer_buffer[SN9C102_URBS];
-	u8 *control_buffer;
-
-	struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
-	struct list_head inqueue, outqueue;
-	u32 frame_count, nbuffers, nreadbuffers;
-
-	enum sn9c102_io_method io;
-	enum sn9c102_stream_state stream;
-
-	struct v4l2_jpegcompression compression;
-
-	struct sn9c102_sysfs_attr sysfs;
-	struct sn9c102_sof_t sof;
-	u16 reg[384];
-
-	struct sn9c102_module_param module_param;
-
-	struct kref kref;
-	enum sn9c102_dev_state state;
-	u8 users;
-
-	struct completion probe;
-	struct mutex open_mutex, fileop_mutex;
-	spinlock_t queue_lock;
-	wait_queue_head_t wait_open, wait_frame, wait_stream;
-};
-
-/*****************************************************************************/
-
-struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id)
-{
-	return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
-}
-
-
-void
-sn9c102_attach_sensor(struct sn9c102_device *cam,
-		      const struct sn9c102_sensor *sensor)
-{
-	memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
-}
-
-
-enum sn9c102_bridge
-sn9c102_get_bridge(struct sn9c102_device *cam)
-{
-	return cam->bridge;
-}
-
-
-struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam)
-{
-	return &cam->sensor;
-}
-
-/*****************************************************************************/
-
-#undef DBG
-#undef KDBG
-#ifdef SN9C102_DEBUG
-#	define DBG(level, fmt, args...)                                       \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1)                                             \
-			dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
-		else if ((level) == 2)                                        \
-			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
-		else if ((level) >= 3)                                        \
-			dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
-				 __func__, __LINE__ , ## args);           \
-	}                                                                     \
-} while (0)
-#	define V4LDBG(level, name, cmd)                                       \
-do {                                                                          \
-	if (debug >= (level))                                                 \
-		v4l_printk_ioctl(name, cmd);                                  \
-} while (0)
-#	define KDBG(level, fmt, args...)                                      \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1 || (level) == 2)                             \
-			pr_info("sn9c102: " fmt "\n", ## args);               \
-		else if ((level) == 3)                                        \
-			pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
-				 __func__, __LINE__ , ## args);           \
-	}                                                                     \
-} while (0)
-#else
-#	define DBG(level, fmt, args...) do { ; } while (0)
-#	define V4LDBG(level, name, cmd) do { ; } while (0)
-#	define KDBG(level, fmt, args...) do { ; } while (0)
-#endif
-
-#undef PDBG
-#define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
-	 __LINE__ , ## args)
-
-#undef PDBGG
-#define PDBGG(fmt, args...) do { ; } while (0) /* placeholder */
-
-#endif /* _SN9C102_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131d.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131d.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131d.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,269 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131d_init(struct sn9c102_device *cam)
-{
-	int err;
-
-	err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-				       {0x00, 0x14}, {0x60, 0x17},
-				       {0x0e, 0x18}, {0xf2, 0x19});
-
-	err += sn9c102_i2c_write(cam, 0x01, 0x04);
-	err += sn9c102_i2c_write(cam, 0x02, 0x00);
-	err += sn9c102_i2c_write(cam, 0x28, 0x00);
-
-	return err;
-}
-
-
-static int hv7131d_get_ctrl(struct sn9c102_device *cam,
-			    struct v4l2_control *ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		{
-			int r1 = sn9c102_i2c_read(cam, 0x26),
-			    r2 = sn9c102_i2c_read(cam, 0x27);
-			if (r1 < 0 || r2 < 0)
-				return -EIO;
-			ctrl->value = (r1 << 8) | (r2 & 0xff);
-		}
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x31);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = 0x3f - (ctrl->value & 0x3f);
-		return 0;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x33);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = 0x3f - (ctrl->value & 0x3f);
-		return 0;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x32);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = 0x3f - (ctrl->value & 0x3f);
-		return 0;
-	case SN9C102_V4L2_CID_RESET_LEVEL:
-		ctrl->value = sn9c102_i2c_read(cam, 0x30);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x3f;
-		return 0;
-	case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x34);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x07;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-
-static int hv7131d_set_ctrl(struct sn9c102_device *cam,
-			    const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
-		err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_RESET_LEVEL:
-		err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
-		err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int hv7131d_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int hv7131d_set_pix_format(struct sn9c102_device *cam,
-				  const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x42, 0x19);
-	else
-		err += sn9c102_write_reg(cam, 0xf2, 0x19);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor hv7131d = {
-	.name = "HV7131D",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x11,
-	.init = &hv7131d_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x0250,
-			.maximum = 0xffff,
-			.step = 0x0001,
-			.default_value = 0x0250,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x1e,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_RESET_LEVEL,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "reset level",
-			.minimum = 0x19,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x30,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "pixel bias voltage",
-			.minimum = 0x00,
-			.maximum = 0x07,
-			.step = 0x01,
-			.default_value = 0x02,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &hv7131d_get_ctrl,
-	.set_ctrl = &hv7131d_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &hv7131d_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &hv7131d_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131d(struct sn9c102_device *cam)
-{
-	int r0 = 0, r1 = 0, err;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-				       {0x28, 0x17});
-
-	r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
-	r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
-	if (err || r0 < 0 || r1 < 0)
-		return -EIO;
-
-	if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &hv7131d);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131r.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131r.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131r.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_hv7131r.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,369 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131r_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C103:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
-					       {0x20, 0x05}, {0x20, 0x06},
-					       {0x03, 0x10}, {0x00, 0x14},
-					       {0x60, 0x17}, {0x0a, 0x18},
-					       {0xf0, 0x19}, {0x1d, 0x1a},
-					       {0x10, 0x1b}, {0x02, 0x1c},
-					       {0x03, 0x1d}, {0x0f, 0x1e},
-					       {0x0c, 0x1f}, {0x00, 0x20},
-					       {0x10, 0x21}, {0x20, 0x22},
-					       {0x30, 0x23}, {0x40, 0x24},
-					       {0x50, 0x25}, {0x60, 0x26},
-					       {0x70, 0x27}, {0x80, 0x28},
-					       {0x90, 0x29}, {0xa0, 0x2a},
-					       {0xb0, 0x2b}, {0xc0, 0x2c},
-					       {0xd0, 0x2d}, {0xe0, 0x2e},
-					       {0xf0, 0x2f}, {0xff, 0x30});
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-					       {0x00, 0x03}, {0x1a, 0x04},
-					       {0x44, 0x05}, {0x3e, 0x06},
-					       {0x1a, 0x07}, {0x03, 0x10},
-					       {0x08, 0x14}, {0xa3, 0x17},
-					       {0x4b, 0x18}, {0x00, 0x19},
-					       {0x1d, 0x1a}, {0x10, 0x1b},
-					       {0x02, 0x1c}, {0x03, 0x1d},
-					       {0x0f, 0x1e}, {0x0c, 0x1f},
-					       {0x00, 0x20}, {0x29, 0x21},
-					       {0x40, 0x22}, {0x54, 0x23},
-					       {0x66, 0x24}, {0x76, 0x25},
-					       {0x85, 0x26}, {0x94, 0x27},
-					       {0xa1, 0x28}, {0xae, 0x29},
-					       {0xbb, 0x2a}, {0xc7, 0x2b},
-					       {0xd3, 0x2c}, {0xde, 0x2d},
-					       {0xea, 0x2e}, {0xf4, 0x2f},
-					       {0xff, 0x30}, {0x00, 0x3F},
-					       {0xC7, 0x40}, {0x01, 0x41},
-					       {0x44, 0x42}, {0x00, 0x43},
-					       {0x44, 0x44}, {0x00, 0x45},
-					       {0x44, 0x46}, {0x00, 0x47},
-					       {0xC7, 0x48}, {0x01, 0x49},
-					       {0xC7, 0x4A}, {0x01, 0x4B},
-					       {0xC7, 0x4C}, {0x01, 0x4D},
-					       {0x44, 0x4E}, {0x00, 0x4F},
-					       {0x44, 0x50}, {0x00, 0x51},
-					       {0x44, 0x52}, {0x00, 0x53},
-					       {0xC7, 0x54}, {0x01, 0x55},
-					       {0xC7, 0x56}, {0x01, 0x57},
-					       {0xC7, 0x58}, {0x01, 0x59},
-					       {0x44, 0x5A}, {0x00, 0x5B},
-					       {0x44, 0x5C}, {0x00, 0x5D},
-					       {0x44, 0x5E}, {0x00, 0x5F},
-					       {0xC7, 0x60}, {0x01, 0x61},
-					       {0xC7, 0x62}, {0x01, 0x63},
-					       {0xC7, 0x64}, {0x01, 0x65},
-					       {0x44, 0x66}, {0x00, 0x67},
-					       {0x44, 0x68}, {0x00, 0x69},
-					       {0x44, 0x6A}, {0x00, 0x6B},
-					       {0xC7, 0x6C}, {0x01, 0x6D},
-					       {0xC7, 0x6E}, {0x01, 0x6F},
-					       {0xC7, 0x70}, {0x01, 0x71},
-					       {0x44, 0x72}, {0x00, 0x73},
-					       {0x44, 0x74}, {0x00, 0x75},
-					       {0x44, 0x76}, {0x00, 0x77},
-					       {0xC7, 0x78}, {0x01, 0x79},
-					       {0xC7, 0x7A}, {0x01, 0x7B},
-					       {0xC7, 0x7C}, {0x01, 0x7D},
-					       {0x44, 0x7E}, {0x00, 0x7F},
-					       {0x14, 0x84}, {0x00, 0x85},
-					       {0x27, 0x86}, {0x00, 0x87},
-					       {0x07, 0x88}, {0x00, 0x89},
-					       {0xEC, 0x8A}, {0x0f, 0x8B},
-					       {0xD8, 0x8C}, {0x0f, 0x8D},
-					       {0x3D, 0x8E}, {0x00, 0x8F},
-					       {0x3D, 0x90}, {0x00, 0x91},
-					       {0xCD, 0x92}, {0x0f, 0x93},
-					       {0xf7, 0x94}, {0x0f, 0x95},
-					       {0x0C, 0x96}, {0x00, 0x97},
-					       {0x00, 0x98}, {0x66, 0x99},
-					       {0x05, 0x9A}, {0x00, 0x9B},
-					       {0x04, 0x9C}, {0x00, 0x9D},
-					       {0x08, 0x9E}, {0x00, 0x9F},
-					       {0x2D, 0xC0}, {0x2D, 0xC1},
-					       {0x3A, 0xC2}, {0x05, 0xC3},
-					       {0x04, 0xC4}, {0x3F, 0xC5},
-					       {0x00, 0xC6}, {0x00, 0xC7},
-					       {0x50, 0xC8}, {0x3C, 0xC9},
-					       {0x28, 0xCA}, {0xD8, 0xCB},
-					       {0x14, 0xCC}, {0xEC, 0xCD},
-					       {0x32, 0xCE}, {0xDD, 0xCF},
-					       {0x32, 0xD0}, {0xDD, 0xD1},
-					       {0x6A, 0xD2}, {0x50, 0xD3},
-					       {0x00, 0xD4}, {0x00, 0xD5},
-					       {0x00, 0xD6});
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_i2c_write(cam, 0x20, 0x00);
-	err += sn9c102_i2c_write(cam, 0x21, 0xd6);
-	err += sn9c102_i2c_write(cam, 0x25, 0x06);
-
-	return err;
-}
-
-
-static int hv7131r_get_ctrl(struct sn9c102_device *cam,
-			    struct v4l2_control *ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x30);
-		if (ctrl->value < 0)
-			return -EIO;
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x31);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = ctrl->value & 0x3f;
-		return 0;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x33);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = ctrl->value & 0x3f;
-		return 0;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x32);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = ctrl->value & 0x3f;
-		return 0;
-	case V4L2_CID_BLACK_LEVEL:
-		ctrl->value = sn9c102_i2c_read(cam, 0x01);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-
-static int hv7131r_set_ctrl(struct sn9c102_device *cam,
-			    const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
-		break;
-	case V4L2_CID_BLACK_LEVEL:
-		{
-			int r = sn9c102_i2c_read(cam, 0x01);
-
-			if (r < 0)
-				return -EIO;
-			err += sn9c102_i2c_write(cam, 0x01,
-						 (ctrl->value<<3) | (r&0xf7));
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int hv7131r_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int hv7131r_set_pix_format(struct sn9c102_device *cam,
-				  const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C103:
-		if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-			err += sn9c102_write_reg(cam, 0xa0, 0x19);
-			err += sn9c102_i2c_write(cam, 0x01, 0x04);
-		} else {
-			err += sn9c102_write_reg(cam, 0x30, 0x19);
-			err += sn9c102_i2c_write(cam, 0x01, 0x04);
-		}
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-			err += sn9c102_write_reg(cam, 0xa5, 0x17);
-			err += sn9c102_i2c_write(cam, 0x01, 0x24);
-		} else {
-			err += sn9c102_write_reg(cam, 0xa3, 0x17);
-			err += sn9c102_i2c_write(cam, 0x01, 0x04);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor hv7131r = {
-	.name = "HV7131R",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x11,
-	.init = &hv7131r_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x40,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x08,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x1a,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x2f,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLACK_LEVEL,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "auto black level compensation",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &hv7131r_get_ctrl,
-	.set_ctrl = &hv7131r_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &hv7131r_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &hv7131r_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131r(struct sn9c102_device *cam)
-{
-	int devid, err;
-
-	err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
-				       {0x34, 0x01}, {0x20, 0x17},
-				       {0x34, 0x01}, {0x46, 0x01});
-
-	devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
-	if (err || devid < 0)
-		return -EIO;
-
-	if (devid != 0x02)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &hv7131r);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mi0343.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mi0343.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mi0343.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mi0343.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,352 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0343_init(struct sn9c102_device *cam)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-				       {0x0a, 0x14}, {0x40, 0x01},
-				       {0x20, 0x17}, {0x07, 0x18},
-				       {0xa0, 0x19});
-
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x01, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-					 0x01, 0xe1, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-					 0x02, 0x81, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-					 0x00, 0x17, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-					 0x00, 0x11, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
-					 0x04, 0x9a, 0, 0);
-
-	return err;
-}
-
-
-static int mi0343_get_ctrl(struct sn9c102_device *cam,
-			   struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	u8 data[2];
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[0];
-		return 0;
-	case V4L2_CID_GAIN:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
-					     data) < 0)
-			return -EIO;
-		break;
-	case V4L2_CID_HFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1] & 0x20 ? 1 : 0;
-		return 0;
-	case V4L2_CID_VFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1] & 0x80 ? 1 : 0;
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
-					     data) < 0)
-			return -EIO;
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
-					     data) < 0)
-			return -EIO;
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
-					     data) < 0)
-			return -EIO;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-	case V4L2_CID_RED_BALANCE:
-	case V4L2_CID_BLUE_BALANCE:
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = data[1] | (data[0] << 8);
-		if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
-			ctrl->value -= 0x10;
-		else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
-			ctrl->value -= 0x60;
-		else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
-			ctrl->value -= 0xe0;
-	}
-
-	return 0;
-}
-
-
-static int mi0343_set_ctrl(struct sn9c102_device *cam,
-			   const struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	u16 reg = 0;
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-	case V4L2_CID_RED_BALANCE:
-	case V4L2_CID_BLUE_BALANCE:
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (ctrl->value <= (0x3f-0x10))
-			reg = 0x10 + ctrl->value;
-		else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
-			reg = 0x60 + (ctrl->value - (0x3f-0x10));
-		else
-			reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
-		break;
-	}
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x09, ctrl->value, 0x00,
-						 0, 0);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x35, reg >> 8, reg & 0xff,
-						 0, 0);
-		break;
-	case V4L2_CID_HFLIP:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x20, ctrl->value ? 0x40:0x00,
-						 ctrl->value ? 0x20:0x00,
-						 0, 0);
-		break;
-	case V4L2_CID_VFLIP:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x20, ctrl->value ? 0x80:0x00,
-						 ctrl->value ? 0x80:0x00,
-						 0, 0);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2d, reg >> 8, reg & 0xff,
-						 0, 0);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2c, reg >> 8, reg & 0xff,
-						 0, 0);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2b, reg >> 8, reg & 0xff,
-						 0, 0);
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2e, reg >> 8, reg & 0xff,
-						 0, 0);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int mi0343_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int mi0343_set_pix_format(struct sn9c102_device *cam,
-				 const struct v4l2_pix_format *pix)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x0a, 0x00, 0x03, 0, 0);
-		err += sn9c102_write_reg(cam, 0x20, 0x19);
-	} else {
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x0a, 0x00, 0x05, 0, 0);
-		err += sn9c102_write_reg(cam, 0xa0, 0x19);
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor mi0343 = {
-	.name = "MI-0343",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x5d,
-	.init = &mi0343_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x06,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_HFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "horizontal mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "vertical mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &mi0343_get_ctrl,
-	.set_ctrl = &mi0343_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &mi0343_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &mi0343_set_pix_format
-};
-
-
-int sn9c102_probe_mi0343(struct sn9c102_device *cam)
-{
-	u8 data[2];
-
-	if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-				     {0x28, 0x17}))
-		return -EIO;
-
-	if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
-				     2, data) < 0)
-		return -EIO;
-
-	if (data[1] != 0x42 || data[0] != 0xe3)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &mi0343);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mi0360.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mi0360.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mi0360.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mi0360.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,453 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0360_init(struct sn9c102_device *cam)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C103:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-					       {0x0a, 0x14}, {0x40, 0x01},
-					       {0x20, 0x17}, {0x07, 0x18},
-					       {0xa0, 0x19}, {0x02, 0x1c},
-					       {0x03, 0x1d}, {0x0f, 0x1e},
-					       {0x0c, 0x1f}, {0x00, 0x20},
-					       {0x10, 0x21}, {0x20, 0x22},
-					       {0x30, 0x23}, {0x40, 0x24},
-					       {0x50, 0x25}, {0x60, 0x26},
-					       {0x70, 0x27}, {0x80, 0x28},
-					       {0x90, 0x29}, {0xa0, 0x2a},
-					       {0xb0, 0x2b}, {0xc0, 0x2c},
-					       {0xd0, 0x2d}, {0xe0, 0x2e},
-					       {0xf0, 0x2f}, {0xff, 0x30});
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-					       {0x00, 0x03}, {0x1a, 0x04},
-					       {0x50, 0x05}, {0x20, 0x06},
-					       {0x10, 0x07}, {0x03, 0x10},
-					       {0x08, 0x14}, {0xa2, 0x17},
-					       {0x47, 0x18}, {0x00, 0x19},
-					       {0x1d, 0x1a}, {0x10, 0x1b},
-					       {0x02, 0x1c}, {0x03, 0x1d},
-					       {0x0f, 0x1e}, {0x0c, 0x1f},
-					       {0x00, 0x20}, {0x29, 0x21},
-					       {0x40, 0x22}, {0x54, 0x23},
-					       {0x66, 0x24}, {0x76, 0x25},
-					       {0x85, 0x26}, {0x94, 0x27},
-					       {0xa1, 0x28}, {0xae, 0x29},
-					       {0xbb, 0x2a}, {0xc7, 0x2b},
-					       {0xd3, 0x2c}, {0xde, 0x2d},
-					       {0xea, 0x2e}, {0xf4, 0x2f},
-					       {0xff, 0x30}, {0x00, 0x3F},
-					       {0xC7, 0x40}, {0x01, 0x41},
-					       {0x44, 0x42}, {0x00, 0x43},
-					       {0x44, 0x44}, {0x00, 0x45},
-					       {0x44, 0x46}, {0x00, 0x47},
-					       {0xC7, 0x48}, {0x01, 0x49},
-					       {0xC7, 0x4A}, {0x01, 0x4B},
-					       {0xC7, 0x4C}, {0x01, 0x4D},
-					       {0x44, 0x4E}, {0x00, 0x4F},
-					       {0x44, 0x50}, {0x00, 0x51},
-					       {0x44, 0x52}, {0x00, 0x53},
-					       {0xC7, 0x54}, {0x01, 0x55},
-					       {0xC7, 0x56}, {0x01, 0x57},
-					       {0xC7, 0x58}, {0x01, 0x59},
-					       {0x44, 0x5A}, {0x00, 0x5B},
-					       {0x44, 0x5C}, {0x00, 0x5D},
-					       {0x44, 0x5E}, {0x00, 0x5F},
-					       {0xC7, 0x60}, {0x01, 0x61},
-					       {0xC7, 0x62}, {0x01, 0x63},
-					       {0xC7, 0x64}, {0x01, 0x65},
-					       {0x44, 0x66}, {0x00, 0x67},
-					       {0x44, 0x68}, {0x00, 0x69},
-					       {0x44, 0x6A}, {0x00, 0x6B},
-					       {0xC7, 0x6C}, {0x01, 0x6D},
-					       {0xC7, 0x6E}, {0x01, 0x6F},
-					       {0xC7, 0x70}, {0x01, 0x71},
-					       {0x44, 0x72}, {0x00, 0x73},
-					       {0x44, 0x74}, {0x00, 0x75},
-					       {0x44, 0x76}, {0x00, 0x77},
-					       {0xC7, 0x78}, {0x01, 0x79},
-					       {0xC7, 0x7A}, {0x01, 0x7B},
-					       {0xC7, 0x7C}, {0x01, 0x7D},
-					       {0x44, 0x7E}, {0x00, 0x7F},
-					       {0x14, 0x84}, {0x00, 0x85},
-					       {0x27, 0x86}, {0x00, 0x87},
-					       {0x07, 0x88}, {0x00, 0x89},
-					       {0xEC, 0x8A}, {0x0f, 0x8B},
-					       {0xD8, 0x8C}, {0x0f, 0x8D},
-					       {0x3D, 0x8E}, {0x00, 0x8F},
-					       {0x3D, 0x90}, {0x00, 0x91},
-					       {0xCD, 0x92}, {0x0f, 0x93},
-					       {0xf7, 0x94}, {0x0f, 0x95},
-					       {0x0C, 0x96}, {0x00, 0x97},
-					       {0x00, 0x98}, {0x66, 0x99},
-					       {0x05, 0x9A}, {0x00, 0x9B},
-					       {0x04, 0x9C}, {0x00, 0x9D},
-					       {0x08, 0x9E}, {0x00, 0x9F},
-					       {0x2D, 0xC0}, {0x2D, 0xC1},
-					       {0x3A, 0xC2}, {0x05, 0xC3},
-					       {0x04, 0xC4}, {0x3F, 0xC5},
-					       {0x00, 0xC6}, {0x00, 0xC7},
-					       {0x50, 0xC8}, {0x3C, 0xC9},
-					       {0x28, 0xCA}, {0xD8, 0xCB},
-					       {0x14, 0xCC}, {0xEC, 0xCD},
-					       {0x32, 0xCE}, {0xDD, 0xCF},
-					       {0x32, 0xD0}, {0xDD, 0xD1},
-					       {0x6A, 0xD2}, {0x50, 0xD3},
-					       {0x00, 0xD4}, {0x00, 0xD5},
-					       {0x00, 0xD6});
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x01, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-					 0x01, 0xe1, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-					 0x02, 0x81, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-					 0x00, 0x17, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-					 0x00, 0x11, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
-					 0x04, 0x9a, 0, 0);
-
-	return err;
-}
-
-
-static int mi0360_get_ctrl(struct sn9c102_device *cam,
-			   struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	u8 data[2];
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[0];
-		return 0;
-	case V4L2_CID_GAIN:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1];
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1];
-		return 0;
-	case V4L2_CID_BLUE_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1];
-		return 0;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1];
-		return 0;
-	case V4L2_CID_HFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1] & 0x20 ? 1 : 0;
-		return 0;
-	case V4L2_CID_VFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1] & 0x80 ? 1 : 0;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-static int mi0360_set_ctrl(struct sn9c102_device *cam,
-			   const struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x09, ctrl->value, 0x00,
-						 0, 0);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x35, 0x03, ctrl->value,
-						 0, 0);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2c, 0x03, ctrl->value,
-						 0, 0);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2d, 0x03, ctrl->value,
-						 0, 0);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2b, 0x03, ctrl->value,
-						 0, 0);
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x2e, 0x03, ctrl->value,
-						 0, 0);
-		break;
-	case V4L2_CID_HFLIP:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x20, ctrl->value ? 0x40:0x00,
-						 ctrl->value ? 0x20:0x00,
-						 0, 0);
-		break;
-	case V4L2_CID_VFLIP:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x20, ctrl->value ? 0x80:0x00,
-						 ctrl->value ? 0x80:0x00,
-						 0, 0);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int mi0360_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C103:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int mi0360_set_pix_format(struct sn9c102_device *cam,
-				 const struct v4l2_pix_format *pix)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x0a, 0x00, 0x05, 0, 0);
-		err += sn9c102_write_reg(cam, 0x60, 0x19);
-		if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
-		    sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
-			err += sn9c102_write_reg(cam, 0xa6, 0x17);
-	} else {
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x0a, 0x00, 0x02, 0, 0);
-		err += sn9c102_write_reg(cam, 0x20, 0x19);
-		if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
-		    sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
-			err += sn9c102_write_reg(cam, 0xa2, 0x17);
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor mi0360 = {
-	.name = "MI-0360",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x5d,
-	.init = &mi0360_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x05,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x25,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_HFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "horizontal mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "vertical mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x0f,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x32,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x25,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &mi0360_get_ctrl,
-	.set_ctrl = &mi0360_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &mi0360_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &mi0360_set_pix_format
-};
-
-
-int sn9c102_probe_mi0360(struct sn9c102_device *cam)
-{
-
-	u8 data[2];
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C103:
-		if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-					     {0x28, 0x17}))
-			return -EIO;
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-					     {0x01, 0x01}, {0x00, 0x01},
-					     {0x28, 0x17}))
-			return -EIO;
-		break;
-	default:
-		break;
-	}
-
-	if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
-				     2, data) < 0)
-		return -EIO;
-
-	if (data[0] != 0x82 || data[1] != 0x43)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &mi0360);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mt9v111.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mt9v111.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_mt9v111.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_mt9v111.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,260 +0,0 @@
-/***************************************************************************
- * Plug-in for MT9V111 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mt9v111_init(struct sn9c102_device *cam)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-				       {0x00, 0x03}, {0x1a, 0x04},
-				       {0x1f, 0x05}, {0x20, 0x06},
-				       {0x1f, 0x07}, {0x81, 0x08},
-				       {0x5c, 0x09}, {0x00, 0x0a},
-				       {0x00, 0x0b}, {0x00, 0x0c},
-				       {0x00, 0x0d}, {0x00, 0x0e},
-				       {0x00, 0x0f}, {0x03, 0x10},
-				       {0x00, 0x11}, {0x00, 0x12},
-				       {0x02, 0x13}, {0x14, 0x14},
-				       {0x28, 0x15}, {0x1e, 0x16},
-				       {0xe2, 0x17}, {0x06, 0x18},
-				       {0x00, 0x19}, {0x00, 0x1a},
-				       {0x00, 0x1b}, {0x08, 0x20},
-				       {0x39, 0x21}, {0x51, 0x22},
-				       {0x63, 0x23}, {0x73, 0x24},
-				       {0x82, 0x25}, {0x8f, 0x26},
-				       {0x9b, 0x27}, {0xa7, 0x28},
-				       {0xb1, 0x29}, {0xbc, 0x2a},
-				       {0xc6, 0x2b}, {0xcf, 0x2c},
-				       {0xd8, 0x2d}, {0xe1, 0x2e},
-				       {0xea, 0x2f}, {0xf2, 0x30},
-				       {0x13, 0x84}, {0x00, 0x85},
-				       {0x25, 0x86}, {0x00, 0x87},
-				       {0x07, 0x88}, {0x00, 0x89},
-				       {0xee, 0x8a}, {0x0f, 0x8b},
-				       {0xe5, 0x8c}, {0x0f, 0x8d},
-				       {0x2e, 0x8e}, {0x00, 0x8f},
-				       {0x30, 0x90}, {0x00, 0x91},
-				       {0xd4, 0x92}, {0x0f, 0x93},
-				       {0xfc, 0x94}, {0x0f, 0x95},
-				       {0x14, 0x96}, {0x00, 0x97},
-				       {0x00, 0x98}, {0x60, 0x99},
-				       {0x07, 0x9a}, {0x40, 0x9b},
-				       {0x20, 0x9c}, {0x00, 0x9d},
-				       {0x00, 0x9e}, {0x00, 0x9f},
-				       {0x2d, 0xc0}, {0x2d, 0xc1},
-				       {0x3a, 0xc2}, {0x05, 0xc3},
-				       {0x04, 0xc4}, {0x3f, 0xc5},
-				       {0x00, 0xc6}, {0x00, 0xc7},
-				       {0x50, 0xc8}, {0x3c, 0xc9},
-				       {0x28, 0xca}, {0xd8, 0xcb},
-				       {0x14, 0xcc}, {0xec, 0xcd},
-				       {0x32, 0xce}, {0xdd, 0xcf},
-				       {0x2d, 0xd0}, {0xdd, 0xd1},
-				       {0x6a, 0xd2}, {0x50, 0xd3},
-				       {0x60, 0xd4}, {0x00, 0xd5},
-				       {0x00, 0xd6});
-
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-					 0x00, 0x01, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x01, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
-					 0x04, 0x80, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-					 0x00, 0x04, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
-					 0x00, 0x08, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
-					 0x00, 0x16, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-					 0x01, 0xe7, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-					 0x02, 0x87, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-					 0x00, 0x40, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-					 0x00, 0x09, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
-					 0x30, 0x02, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
-					 0x00, 0xb0, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
-					 0x00, 0x7c, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
-					 0x00, 0x00, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-					 0x00, 0x04, 0, 0);
-
-	return err;
-}
-
-static int mt9v111_get_ctrl(struct sn9c102_device *cam,
-			    struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	u8 data[2];
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-					     data) < 0)
-			return -EIO;
-		ctrl->value = data[1] & 0x80 ? 1 : 0;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-static int mt9v111_set_ctrl(struct sn9c102_device *cam,
-			    const struct v4l2_control *ctrl)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x20,
-						 ctrl->value ? 0x80 : 0x00,
-						 ctrl->value ? 0x80 : 0x00, 0,
-						 0);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-static int mt9v111_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
-
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-static int mt9v111_set_pix_format(struct sn9c102_device *cam,
-				  const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-		err += sn9c102_write_reg(cam, 0xb4, 0x17);
-	} else {
-		err += sn9c102_write_reg(cam, 0xe2, 0x17);
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor mt9v111 = {
-	.name = "MT9V111",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x5c,
-	.init = &mt9v111_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "vertical mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &mt9v111_get_ctrl,
-	.set_ctrl = &mt9v111_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &mt9v111_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &mt9v111_set_pix_format
-};
-
-
-int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
-{
-	u8 data[2];
-	int err = 0;
-
-	err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-					{0x29, 0x01}, {0x42, 0x17},
-					{0x62, 0x17}, {0x08, 0x01});
-	err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
-					 mt9v111.i2c_slave_id, 0x01, 0x00,
-					 0x04, 0, 0);
-	if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
-					    mt9v111.i2c_slave_id, 0x36, 2,
-					    data) < 0)
-		return -EIO;
-
-	if (data[0] != 0x82 || data[1] != 0x3a)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &mt9v111);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_ov7630.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_ov7630.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_ov7630.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_ov7630.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,634 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7630_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
-					       {0x0f, 0x18}, {0x50, 0x19});
-
-		err += sn9c102_i2c_write(cam, 0x12, 0x8d);
-		err += sn9c102_i2c_write(cam, 0x12, 0x0d);
-		err += sn9c102_i2c_write(cam, 0x11, 0x00);
-		err += sn9c102_i2c_write(cam, 0x15, 0x35);
-		err += sn9c102_i2c_write(cam, 0x16, 0x03);
-		err += sn9c102_i2c_write(cam, 0x17, 0x1c);
-		err += sn9c102_i2c_write(cam, 0x18, 0xbd);
-		err += sn9c102_i2c_write(cam, 0x19, 0x06);
-		err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
-		err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-		err += sn9c102_i2c_write(cam, 0x20, 0x44);
-		err += sn9c102_i2c_write(cam, 0x23, 0xee);
-		err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-		err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-		err += sn9c102_i2c_write(cam, 0x28, 0x20);
-		err += sn9c102_i2c_write(cam, 0x29, 0x30);
-		err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
-		err += sn9c102_i2c_write(cam, 0x30, 0x24);
-		err += sn9c102_i2c_write(cam, 0x32, 0x86);
-		err += sn9c102_i2c_write(cam, 0x60, 0xa9);
-		err += sn9c102_i2c_write(cam, 0x61, 0x42);
-		err += sn9c102_i2c_write(cam, 0x65, 0x00);
-		err += sn9c102_i2c_write(cam, 0x69, 0x38);
-		err += sn9c102_i2c_write(cam, 0x6f, 0x88);
-		err += sn9c102_i2c_write(cam, 0x70, 0x0b);
-		err += sn9c102_i2c_write(cam, 0x71, 0x00);
-		err += sn9c102_i2c_write(cam, 0x74, 0x21);
-		err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
-		break;
-	case BRIDGE_SN9C103:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
-					       {0x1a, 0x04}, {0x20, 0x05},
-					       {0x20, 0x06}, {0x20, 0x07},
-					       {0x03, 0x10}, {0x0a, 0x14},
-					       {0x60, 0x17}, {0x0f, 0x18},
-					       {0x50, 0x19}, {0x1d, 0x1a},
-					       {0x10, 0x1b}, {0x02, 0x1c},
-					       {0x03, 0x1d}, {0x0f, 0x1e},
-					       {0x0c, 0x1f}, {0x00, 0x20},
-					       {0x10, 0x21}, {0x20, 0x22},
-					       {0x30, 0x23}, {0x40, 0x24},
-					       {0x50, 0x25}, {0x60, 0x26},
-					       {0x70, 0x27}, {0x80, 0x28},
-					       {0x90, 0x29}, {0xa0, 0x2a},
-					       {0xb0, 0x2b}, {0xc0, 0x2c},
-					       {0xd0, 0x2d}, {0xe0, 0x2e},
-					       {0xf0, 0x2f}, {0xff, 0x30});
-
-		err += sn9c102_i2c_write(cam, 0x12, 0x8d);
-		err += sn9c102_i2c_write(cam, 0x12, 0x0d);
-		err += sn9c102_i2c_write(cam, 0x15, 0x34);
-		err += sn9c102_i2c_write(cam, 0x11, 0x01);
-		err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-		err += sn9c102_i2c_write(cam, 0x20, 0x44);
-		err += sn9c102_i2c_write(cam, 0x23, 0xee);
-		err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-		err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-		err += sn9c102_i2c_write(cam, 0x28, 0x20);
-		err += sn9c102_i2c_write(cam, 0x29, 0x30);
-		err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
-		err += sn9c102_i2c_write(cam, 0x30, 0x24);
-		err += sn9c102_i2c_write(cam, 0x32, 0x86);
-		err += sn9c102_i2c_write(cam, 0x60, 0xa9);
-		err += sn9c102_i2c_write(cam, 0x61, 0x42);
-		err += sn9c102_i2c_write(cam, 0x65, 0x00);
-		err += sn9c102_i2c_write(cam, 0x69, 0x38);
-		err += sn9c102_i2c_write(cam, 0x6f, 0x88);
-		err += sn9c102_i2c_write(cam, 0x70, 0x0b);
-		err += sn9c102_i2c_write(cam, 0x71, 0x00);
-		err += sn9c102_i2c_write(cam, 0x74, 0x21);
-		err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-	err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
-				       {0x1a, 0x04}, {0x03, 0x10},
-				       {0x0a, 0x14}, {0xe2, 0x17},
-				       {0x0b, 0x18}, {0x00, 0x19},
-				       {0x1d, 0x1a}, {0x10, 0x1b},
-				       {0x02, 0x1c}, {0x03, 0x1d},
-				       {0x0f, 0x1e}, {0x0c, 0x1f},
-				       {0x00, 0x20}, {0x24, 0x21},
-				       {0x3b, 0x22}, {0x47, 0x23},
-				       {0x60, 0x24}, {0x71, 0x25},
-				       {0x80, 0x26}, {0x8f, 0x27},
-				       {0x9d, 0x28}, {0xaa, 0x29},
-				       {0xb8, 0x2a}, {0xc4, 0x2b},
-				       {0xd1, 0x2c}, {0xdd, 0x2d},
-				       {0xe8, 0x2e}, {0xf4, 0x2f},
-				       {0xff, 0x30}, {0x00, 0x3f},
-				       {0xc7, 0x40}, {0x01, 0x41},
-				       {0x44, 0x42}, {0x00, 0x43},
-				       {0x44, 0x44}, {0x00, 0x45},
-				       {0x44, 0x46}, {0x00, 0x47},
-				       {0xc7, 0x48}, {0x01, 0x49},
-				       {0xc7, 0x4a}, {0x01, 0x4b},
-				       {0xc7, 0x4c}, {0x01, 0x4d},
-				       {0x44, 0x4e}, {0x00, 0x4f},
-				       {0x44, 0x50}, {0x00, 0x51},
-				       {0x44, 0x52}, {0x00, 0x53},
-				       {0xc7, 0x54}, {0x01, 0x55},
-				       {0xc7, 0x56}, {0x01, 0x57},
-				       {0xc7, 0x58}, {0x01, 0x59},
-				       {0x44, 0x5a}, {0x00, 0x5b},
-				       {0x44, 0x5c}, {0x00, 0x5d},
-				       {0x44, 0x5e}, {0x00, 0x5f},
-				       {0xc7, 0x60}, {0x01, 0x61},
-				       {0xc7, 0x62}, {0x01, 0x63},
-				       {0xc7, 0x64}, {0x01, 0x65},
-				       {0x44, 0x66}, {0x00, 0x67},
-				       {0x44, 0x68}, {0x00, 0x69},
-				       {0x44, 0x6a}, {0x00, 0x6b},
-				       {0xc7, 0x6c}, {0x01, 0x6d},
-				       {0xc7, 0x6e}, {0x01, 0x6f},
-				       {0xc7, 0x70}, {0x01, 0x71},
-				       {0x44, 0x72}, {0x00, 0x73},
-				       {0x44, 0x74}, {0x00, 0x75},
-				       {0x44, 0x76}, {0x00, 0x77},
-				       {0xc7, 0x78}, {0x01, 0x79},
-				       {0xc7, 0x7a}, {0x01, 0x7b},
-				       {0xc7, 0x7c}, {0x01, 0x7d},
-				       {0x44, 0x7e}, {0x00, 0x7f},
-				       {0x17, 0x84}, {0x00, 0x85},
-				       {0x2e, 0x86}, {0x00, 0x87},
-				       {0x09, 0x88}, {0x00, 0x89},
-				       {0xe8, 0x8a}, {0x0f, 0x8b},
-				       {0xda, 0x8c}, {0x0f, 0x8d},
-				       {0x40, 0x8e}, {0x00, 0x8f},
-				       {0x37, 0x90}, {0x00, 0x91},
-				       {0xcf, 0x92}, {0x0f, 0x93},
-				       {0xfa, 0x94}, {0x0f, 0x95},
-				       {0x00, 0x96}, {0x00, 0x97},
-				       {0x00, 0x98}, {0x66, 0x99},
-				       {0x00, 0x9a}, {0x40, 0x9b},
-				       {0x20, 0x9c}, {0x00, 0x9d},
-				       {0x00, 0x9e}, {0x00, 0x9f},
-				       {0x2d, 0xc0}, {0x2d, 0xc1},
-				       {0x3a, 0xc2}, {0x00, 0xc3},
-				       {0x04, 0xc4}, {0x3f, 0xc5},
-				       {0x00, 0xc6}, {0x00, 0xc7},
-				       {0x50, 0xc8}, {0x3c, 0xc9},
-				       {0x28, 0xca}, {0xd8, 0xcb},
-				       {0x14, 0xcc}, {0xec, 0xcd},
-				       {0x32, 0xce}, {0xdd, 0xcf},
-				       {0x32, 0xd0}, {0xdd, 0xd1},
-				       {0x6a, 0xd2}, {0x50, 0xd3},
-				       {0x60, 0xd4}, {0x00, 0xd5},
-				       {0x00, 0xd6});
-
-		err += sn9c102_i2c_write(cam, 0x12, 0x80);
-		err += sn9c102_i2c_write(cam, 0x12, 0x48);
-		err += sn9c102_i2c_write(cam, 0x01, 0x80);
-		err += sn9c102_i2c_write(cam, 0x02, 0x80);
-		err += sn9c102_i2c_write(cam, 0x03, 0x80);
-		err += sn9c102_i2c_write(cam, 0x04, 0x10);
-		err += sn9c102_i2c_write(cam, 0x05, 0x20);
-		err += sn9c102_i2c_write(cam, 0x06, 0x80);
-		err += sn9c102_i2c_write(cam, 0x11, 0x00);
-		err += sn9c102_i2c_write(cam, 0x0c, 0x20);
-		err += sn9c102_i2c_write(cam, 0x0d, 0x20);
-		err += sn9c102_i2c_write(cam, 0x15, 0x80);
-		err += sn9c102_i2c_write(cam, 0x16, 0x03);
-		err += sn9c102_i2c_write(cam, 0x17, 0x1b);
-		err += sn9c102_i2c_write(cam, 0x18, 0xbd);
-		err += sn9c102_i2c_write(cam, 0x19, 0x05);
-		err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
-		err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-		err += sn9c102_i2c_write(cam, 0x21, 0x1b);
-		err += sn9c102_i2c_write(cam, 0x22, 0x00);
-		err += sn9c102_i2c_write(cam, 0x23, 0xde);
-		err += sn9c102_i2c_write(cam, 0x24, 0x10);
-		err += sn9c102_i2c_write(cam, 0x25, 0x8a);
-		err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-		err += sn9c102_i2c_write(cam, 0x27, 0xca);
-		err += sn9c102_i2c_write(cam, 0x28, 0xa2);
-		err += sn9c102_i2c_write(cam, 0x29, 0x74);
-		err += sn9c102_i2c_write(cam, 0x2a, 0x88);
-		err += sn9c102_i2c_write(cam, 0x2b, 0x34);
-		err += sn9c102_i2c_write(cam, 0x2c, 0x88);
-		err += sn9c102_i2c_write(cam, 0x2e, 0x00);
-		err += sn9c102_i2c_write(cam, 0x2f, 0x00);
-		err += sn9c102_i2c_write(cam, 0x30, 0x00);
-		err += sn9c102_i2c_write(cam, 0x32, 0xc2);
-		err += sn9c102_i2c_write(cam, 0x33, 0x08);
-		err += sn9c102_i2c_write(cam, 0x4c, 0x40);
-		err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
-		err += sn9c102_i2c_write(cam, 0x60, 0x05);
-		err += sn9c102_i2c_write(cam, 0x61, 0x40);
-		err += sn9c102_i2c_write(cam, 0x62, 0x12);
-		err += sn9c102_i2c_write(cam, 0x63, 0x57);
-		err += sn9c102_i2c_write(cam, 0x64, 0x73);
-		err += sn9c102_i2c_write(cam, 0x65, 0x00);
-		err += sn9c102_i2c_write(cam, 0x66, 0x55);
-		err += sn9c102_i2c_write(cam, 0x67, 0x01);
-		err += sn9c102_i2c_write(cam, 0x68, 0xac);
-		err += sn9c102_i2c_write(cam, 0x69, 0x38);
-		err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
-		err += sn9c102_i2c_write(cam, 0x70, 0x01);
-		err += sn9c102_i2c_write(cam, 0x71, 0x00);
-		err += sn9c102_i2c_write(cam, 0x72, 0x10);
-		err += sn9c102_i2c_write(cam, 0x73, 0x50);
-		err += sn9c102_i2c_write(cam, 0x74, 0x20);
-		err += sn9c102_i2c_write(cam, 0x76, 0x01);
-		err += sn9c102_i2c_write(cam, 0x77, 0xf3);
-		err += sn9c102_i2c_write(cam, 0x78, 0x90);
-		err += sn9c102_i2c_write(cam, 0x79, 0x98);
-		err += sn9c102_i2c_write(cam, 0x7a, 0x98);
-		err += sn9c102_i2c_write(cam, 0x7b, 0x00);
-		err += sn9c102_i2c_write(cam, 0x7c, 0x38);
-		err += sn9c102_i2c_write(cam, 0x7d, 0xff);
-		break;
-	default:
-		break;
-	}
-
-	return err;
-}
-
-
-static int ov7630_get_ctrl(struct sn9c102_device *cam,
-			   struct v4l2_control *ctrl)
-{
-	enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x10);
-		if (ctrl->value < 0)
-			return -EIO;
-		break;
-	case V4L2_CID_RED_BALANCE:
-		if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-			ctrl->value = sn9c102_pread_reg(cam, 0x05);
-		else
-			ctrl->value = sn9c102_pread_reg(cam, 0x07);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_pread_reg(cam, 0x06);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-			ctrl->value = sn9c102_pread_reg(cam, 0x07);
-		else
-			ctrl->value = sn9c102_pread_reg(cam, 0x05);
-		break;
-		break;
-	case V4L2_CID_GAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x00);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x3f;
-		break;
-	case V4L2_CID_DO_WHITE_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0c);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x3f;
-		break;
-	case V4L2_CID_WHITENESS:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0d);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x3f;
-		break;
-	case V4L2_CID_AUTOGAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x13);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x01;
-		break;
-	case V4L2_CID_VFLIP:
-		ctrl->value = sn9c102_i2c_read(cam, 0x75);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
-		break;
-	case SN9C102_V4L2_CID_GAMMA:
-		ctrl->value = sn9c102_i2c_read(cam, 0x14);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
-		break;
-	case SN9C102_V4L2_CID_BAND_FILTER:
-		ctrl->value = sn9c102_i2c_read(cam, 0x2d);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_ctrl(struct sn9c102_device *cam,
-			   const struct v4l2_control *ctrl)
-{
-	enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-			err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-		else
-			err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_write_reg(cam, ctrl->value, 0x06);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-			err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-		else
-			err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
-		break;
-	case V4L2_CID_DO_WHITE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-		break;
-	case V4L2_CID_WHITENESS:
-		err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
-		break;
-	case V4L2_CID_AUTOGAIN:
-		err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
-						    (ctrl->value << 1));
-		break;
-	case V4L2_CID_VFLIP:
-		err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
-		break;
-	case SN9C102_V4L2_CID_GAMMA:
-		err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
-		break;
-	case SN9C102_V4L2_CID_BAND_FILTER:
-		err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_crop(struct sn9c102_device *cam,
-			   const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-	case BRIDGE_SN9C103:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int ov7630_set_pix_format(struct sn9c102_device *cam,
-				 const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-	case BRIDGE_SN9C103:
-		if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
-			err += sn9c102_write_reg(cam, 0x50, 0x19);
-		else
-			err += sn9c102_write_reg(cam, 0x20, 0x19);
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-			err += sn9c102_write_reg(cam, 0xe5, 0x17);
-			err += sn9c102_i2c_write(cam, 0x11, 0x04);
-		} else {
-			err += sn9c102_write_reg(cam, 0xe2, 0x17);
-			err += sn9c102_i2c_write(cam, 0x11, 0x02);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor ov7630 = {
-	.name = "OV7630",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
-			    BRIDGE_SN9C105 | BRIDGE_SN9C120,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x21,
-	.init = &ov7630_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x14,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x60,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_WHITENESS,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "white balance background: red",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_DO_WHITE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "white balance background: blue",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_AUTOGAIN,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "auto adjust",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "vertical flip",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x01,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x20,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_BAND_FILTER,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "band filter",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GAMMA,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "rgb gamma",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &ov7630_get_ctrl,
-	.set_ctrl = &ov7630_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &ov7630_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SN9C10X,
-		.priv = 8,
-	},
-	.set_pix_format = &ov7630_set_pix_format
-};
-
-
-int sn9c102_probe_ov7630(struct sn9c102_device *cam)
-{
-	int pid, ver, err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-					       {0x28, 0x17});
-		break;
-	case BRIDGE_SN9C103: /* do _not_ change anything! */
-		err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
-					       {0x28, 0x17}, {0x44, 0x02});
-		pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
-		if (err || pid < 0) /* try a different initialization */
-			err += sn9c102_write_const_regs(cam, {0x01, 0x01},
-							{0x00, 0x01});
-		break;
-	case BRIDGE_SN9C105:
-	case BRIDGE_SN9C120:
-		err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-					       {0x29, 0x01}, {0x74, 0x02},
-					       {0x0e, 0x01}, {0x44, 0x01});
-		break;
-	default:
-		break;
-	}
-
-	pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
-	ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
-	if (err || pid < 0 || ver < 0)
-		return -EIO;
-	if (pid != 0x76 || ver != 0x31)
-		return -ENODEV;
-	sn9c102_attach_sensor(cam, &ov7630);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_ov7660.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_ov7660.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_ov7660.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_ov7660.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,546 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7660_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
-				       {0x1a, 0x04}, {0x03, 0x10},
-				       {0x08, 0x14}, {0x20, 0x17},
-				       {0x8b, 0x18}, {0x00, 0x19},
-				       {0x1d, 0x1a}, {0x10, 0x1b},
-				       {0x02, 0x1c}, {0x03, 0x1d},
-				       {0x0f, 0x1e}, {0x0c, 0x1f},
-				       {0x00, 0x20}, {0x29, 0x21},
-				       {0x40, 0x22}, {0x54, 0x23},
-				       {0x66, 0x24}, {0x76, 0x25},
-				       {0x85, 0x26}, {0x94, 0x27},
-				       {0xa1, 0x28}, {0xae, 0x29},
-				       {0xbb, 0x2a}, {0xc7, 0x2b},
-				       {0xd3, 0x2c}, {0xde, 0x2d},
-				       {0xea, 0x2e}, {0xf4, 0x2f},
-				       {0xff, 0x30}, {0x00, 0x3f},
-				       {0xc7, 0x40}, {0x01, 0x41},
-				       {0x44, 0x42}, {0x00, 0x43},
-				       {0x44, 0x44}, {0x00, 0x45},
-				       {0x44, 0x46}, {0x00, 0x47},
-				       {0xc7, 0x48}, {0x01, 0x49},
-				       {0xc7, 0x4a}, {0x01, 0x4b},
-				       {0xc7, 0x4c}, {0x01, 0x4d},
-				       {0x44, 0x4e}, {0x00, 0x4f},
-				       {0x44, 0x50}, {0x00, 0x51},
-				       {0x44, 0x52}, {0x00, 0x53},
-				       {0xc7, 0x54}, {0x01, 0x55},
-				       {0xc7, 0x56}, {0x01, 0x57},
-				       {0xc7, 0x58}, {0x01, 0x59},
-				       {0x44, 0x5a}, {0x00, 0x5b},
-				       {0x44, 0x5c}, {0x00, 0x5d},
-				       {0x44, 0x5e}, {0x00, 0x5f},
-				       {0xc7, 0x60}, {0x01, 0x61},
-				       {0xc7, 0x62}, {0x01, 0x63},
-				       {0xc7, 0x64}, {0x01, 0x65},
-				       {0x44, 0x66}, {0x00, 0x67},
-				       {0x44, 0x68}, {0x00, 0x69},
-				       {0x44, 0x6a}, {0x00, 0x6b},
-				       {0xc7, 0x6c}, {0x01, 0x6d},
-				       {0xc7, 0x6e}, {0x01, 0x6f},
-				       {0xc7, 0x70}, {0x01, 0x71},
-				       {0x44, 0x72}, {0x00, 0x73},
-				       {0x44, 0x74}, {0x00, 0x75},
-				       {0x44, 0x76}, {0x00, 0x77},
-				       {0xc7, 0x78}, {0x01, 0x79},
-				       {0xc7, 0x7a}, {0x01, 0x7b},
-				       {0xc7, 0x7c}, {0x01, 0x7d},
-				       {0x44, 0x7e}, {0x00, 0x7f},
-				       {0x14, 0x84}, {0x00, 0x85},
-				       {0x27, 0x86}, {0x00, 0x87},
-				       {0x07, 0x88}, {0x00, 0x89},
-				       {0xec, 0x8a}, {0x0f, 0x8b},
-				       {0xd8, 0x8c}, {0x0f, 0x8d},
-				       {0x3d, 0x8e}, {0x00, 0x8f},
-				       {0x3d, 0x90}, {0x00, 0x91},
-				       {0xcd, 0x92}, {0x0f, 0x93},
-				       {0xf7, 0x94}, {0x0f, 0x95},
-				       {0x0c, 0x96}, {0x00, 0x97},
-				       {0x00, 0x98}, {0x66, 0x99},
-				       {0x05, 0x9a}, {0x00, 0x9b},
-				       {0x04, 0x9c}, {0x00, 0x9d},
-				       {0x08, 0x9e}, {0x00, 0x9f},
-				       {0x2d, 0xc0}, {0x2d, 0xc1},
-				       {0x3a, 0xc2}, {0x05, 0xc3},
-				       {0x04, 0xc4}, {0x3f, 0xc5},
-				       {0x00, 0xc6}, {0x00, 0xc7},
-				       {0x50, 0xc8}, {0x3C, 0xc9},
-				       {0x28, 0xca}, {0xd8, 0xcb},
-				       {0x14, 0xcc}, {0xec, 0xcd},
-				       {0x32, 0xce}, {0xdd, 0xcf},
-				       {0x32, 0xd0}, {0xdd, 0xd1},
-				       {0x6a, 0xd2}, {0x50, 0xd3},
-				       {0x00, 0xd4}, {0x00, 0xd5},
-				       {0x00, 0xd6});
-
-	err += sn9c102_i2c_write(cam, 0x12, 0x80);
-	err += sn9c102_i2c_write(cam, 0x11, 0x09);
-	err += sn9c102_i2c_write(cam, 0x00, 0x0A);
-	err += sn9c102_i2c_write(cam, 0x01, 0x80);
-	err += sn9c102_i2c_write(cam, 0x02, 0x80);
-	err += sn9c102_i2c_write(cam, 0x03, 0x00);
-	err += sn9c102_i2c_write(cam, 0x04, 0x00);
-	err += sn9c102_i2c_write(cam, 0x05, 0x08);
-	err += sn9c102_i2c_write(cam, 0x06, 0x0B);
-	err += sn9c102_i2c_write(cam, 0x07, 0x00);
-	err += sn9c102_i2c_write(cam, 0x08, 0x1C);
-	err += sn9c102_i2c_write(cam, 0x09, 0x01);
-	err += sn9c102_i2c_write(cam, 0x0A, 0x76);
-	err += sn9c102_i2c_write(cam, 0x0B, 0x60);
-	err += sn9c102_i2c_write(cam, 0x0C, 0x00);
-	err += sn9c102_i2c_write(cam, 0x0D, 0x08);
-	err += sn9c102_i2c_write(cam, 0x0E, 0x04);
-	err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
-	err += sn9c102_i2c_write(cam, 0x10, 0x20);
-	err += sn9c102_i2c_write(cam, 0x11, 0x03);
-	err += sn9c102_i2c_write(cam, 0x12, 0x05);
-	err += sn9c102_i2c_write(cam, 0x13, 0xC7);
-	err += sn9c102_i2c_write(cam, 0x14, 0x2C);
-	err += sn9c102_i2c_write(cam, 0x15, 0x00);
-	err += sn9c102_i2c_write(cam, 0x16, 0x02);
-	err += sn9c102_i2c_write(cam, 0x17, 0x10);
-	err += sn9c102_i2c_write(cam, 0x18, 0x60);
-	err += sn9c102_i2c_write(cam, 0x19, 0x02);
-	err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
-	err += sn9c102_i2c_write(cam, 0x1B, 0x02);
-	err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
-	err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
-	err += sn9c102_i2c_write(cam, 0x1E, 0x01);
-	err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
-	err += sn9c102_i2c_write(cam, 0x20, 0x05);
-	err += sn9c102_i2c_write(cam, 0x21, 0x05);
-	err += sn9c102_i2c_write(cam, 0x22, 0x05);
-	err += sn9c102_i2c_write(cam, 0x23, 0x05);
-	err += sn9c102_i2c_write(cam, 0x24, 0x68);
-	err += sn9c102_i2c_write(cam, 0x25, 0x58);
-	err += sn9c102_i2c_write(cam, 0x26, 0xD4);
-	err += sn9c102_i2c_write(cam, 0x27, 0x80);
-	err += sn9c102_i2c_write(cam, 0x28, 0x80);
-	err += sn9c102_i2c_write(cam, 0x29, 0x30);
-	err += sn9c102_i2c_write(cam, 0x2A, 0x00);
-	err += sn9c102_i2c_write(cam, 0x2B, 0x00);
-	err += sn9c102_i2c_write(cam, 0x2C, 0x80);
-	err += sn9c102_i2c_write(cam, 0x2D, 0x00);
-	err += sn9c102_i2c_write(cam, 0x2E, 0x00);
-	err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
-	err += sn9c102_i2c_write(cam, 0x30, 0x08);
-	err += sn9c102_i2c_write(cam, 0x31, 0x30);
-	err += sn9c102_i2c_write(cam, 0x32, 0xB4);
-	err += sn9c102_i2c_write(cam, 0x33, 0x00);
-	err += sn9c102_i2c_write(cam, 0x34, 0x07);
-	err += sn9c102_i2c_write(cam, 0x35, 0x84);
-	err += sn9c102_i2c_write(cam, 0x36, 0x00);
-	err += sn9c102_i2c_write(cam, 0x37, 0x0C);
-	err += sn9c102_i2c_write(cam, 0x38, 0x02);
-	err += sn9c102_i2c_write(cam, 0x39, 0x43);
-	err += sn9c102_i2c_write(cam, 0x3A, 0x00);
-	err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
-	err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
-	err += sn9c102_i2c_write(cam, 0x3D, 0x99);
-	err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
-	err += sn9c102_i2c_write(cam, 0x3F, 0x41);
-	err += sn9c102_i2c_write(cam, 0x40, 0xC1);
-	err += sn9c102_i2c_write(cam, 0x41, 0x22);
-	err += sn9c102_i2c_write(cam, 0x42, 0x08);
-	err += sn9c102_i2c_write(cam, 0x43, 0xF0);
-	err += sn9c102_i2c_write(cam, 0x44, 0x10);
-	err += sn9c102_i2c_write(cam, 0x45, 0x78);
-	err += sn9c102_i2c_write(cam, 0x46, 0xA8);
-	err += sn9c102_i2c_write(cam, 0x47, 0x60);
-	err += sn9c102_i2c_write(cam, 0x48, 0x80);
-	err += sn9c102_i2c_write(cam, 0x49, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4A, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4B, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4C, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4D, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4E, 0x00);
-	err += sn9c102_i2c_write(cam, 0x4F, 0x46);
-	err += sn9c102_i2c_write(cam, 0x50, 0x36);
-	err += sn9c102_i2c_write(cam, 0x51, 0x0F);
-	err += sn9c102_i2c_write(cam, 0x52, 0x17);
-	err += sn9c102_i2c_write(cam, 0x53, 0x7F);
-	err += sn9c102_i2c_write(cam, 0x54, 0x96);
-	err += sn9c102_i2c_write(cam, 0x55, 0x40);
-	err += sn9c102_i2c_write(cam, 0x56, 0x40);
-	err += sn9c102_i2c_write(cam, 0x57, 0x40);
-	err += sn9c102_i2c_write(cam, 0x58, 0x0F);
-	err += sn9c102_i2c_write(cam, 0x59, 0xBA);
-	err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
-	err += sn9c102_i2c_write(cam, 0x5B, 0x22);
-	err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
-	err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
-	err += sn9c102_i2c_write(cam, 0x5E, 0x10);
-	err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
-	err += sn9c102_i2c_write(cam, 0x60, 0x05);
-	err += sn9c102_i2c_write(cam, 0x61, 0x60);
-	err += sn9c102_i2c_write(cam, 0x62, 0x00);
-	err += sn9c102_i2c_write(cam, 0x63, 0x00);
-	err += sn9c102_i2c_write(cam, 0x64, 0x50);
-	err += sn9c102_i2c_write(cam, 0x65, 0x30);
-	err += sn9c102_i2c_write(cam, 0x66, 0x00);
-	err += sn9c102_i2c_write(cam, 0x67, 0x80);
-	err += sn9c102_i2c_write(cam, 0x68, 0x7A);
-	err += sn9c102_i2c_write(cam, 0x69, 0x90);
-	err += sn9c102_i2c_write(cam, 0x6A, 0x80);
-	err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
-	err += sn9c102_i2c_write(cam, 0x6C, 0x30);
-	err += sn9c102_i2c_write(cam, 0x6D, 0x48);
-	err += sn9c102_i2c_write(cam, 0x6E, 0x80);
-	err += sn9c102_i2c_write(cam, 0x6F, 0x74);
-	err += sn9c102_i2c_write(cam, 0x70, 0x64);
-	err += sn9c102_i2c_write(cam, 0x71, 0x60);
-	err += sn9c102_i2c_write(cam, 0x72, 0x5C);
-	err += sn9c102_i2c_write(cam, 0x73, 0x58);
-	err += sn9c102_i2c_write(cam, 0x74, 0x54);
-	err += sn9c102_i2c_write(cam, 0x75, 0x4C);
-	err += sn9c102_i2c_write(cam, 0x76, 0x40);
-	err += sn9c102_i2c_write(cam, 0x77, 0x38);
-	err += sn9c102_i2c_write(cam, 0x78, 0x34);
-	err += sn9c102_i2c_write(cam, 0x79, 0x30);
-	err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
-	err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
-	err += sn9c102_i2c_write(cam, 0x7C, 0x03);
-	err += sn9c102_i2c_write(cam, 0x7D, 0x07);
-	err += sn9c102_i2c_write(cam, 0x7E, 0x17);
-	err += sn9c102_i2c_write(cam, 0x7F, 0x34);
-	err += sn9c102_i2c_write(cam, 0x80, 0x41);
-	err += sn9c102_i2c_write(cam, 0x81, 0x4D);
-	err += sn9c102_i2c_write(cam, 0x82, 0x58);
-	err += sn9c102_i2c_write(cam, 0x83, 0x63);
-	err += sn9c102_i2c_write(cam, 0x84, 0x6E);
-	err += sn9c102_i2c_write(cam, 0x85, 0x77);
-	err += sn9c102_i2c_write(cam, 0x86, 0x87);
-	err += sn9c102_i2c_write(cam, 0x87, 0x95);
-	err += sn9c102_i2c_write(cam, 0x88, 0xAF);
-	err += sn9c102_i2c_write(cam, 0x89, 0xC7);
-	err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
-	err += sn9c102_i2c_write(cam, 0x8B, 0x99);
-	err += sn9c102_i2c_write(cam, 0x8C, 0x99);
-	err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
-	err += sn9c102_i2c_write(cam, 0x8E, 0x20);
-	err += sn9c102_i2c_write(cam, 0x8F, 0x26);
-	err += sn9c102_i2c_write(cam, 0x90, 0x10);
-	err += sn9c102_i2c_write(cam, 0x91, 0x0C);
-	err += sn9c102_i2c_write(cam, 0x92, 0x25);
-	err += sn9c102_i2c_write(cam, 0x93, 0x00);
-	err += sn9c102_i2c_write(cam, 0x94, 0x50);
-	err += sn9c102_i2c_write(cam, 0x95, 0x50);
-	err += sn9c102_i2c_write(cam, 0x96, 0x00);
-	err += sn9c102_i2c_write(cam, 0x97, 0x01);
-	err += sn9c102_i2c_write(cam, 0x98, 0x10);
-	err += sn9c102_i2c_write(cam, 0x99, 0x40);
-	err += sn9c102_i2c_write(cam, 0x9A, 0x40);
-	err += sn9c102_i2c_write(cam, 0x9B, 0x20);
-	err += sn9c102_i2c_write(cam, 0x9C, 0x00);
-	err += sn9c102_i2c_write(cam, 0x9D, 0x99);
-	err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
-	err += sn9c102_i2c_write(cam, 0x9F, 0x00);
-	err += sn9c102_i2c_write(cam, 0xA0, 0x00);
-	err += sn9c102_i2c_write(cam, 0xA1, 0x00);
-
-	return err;
-}
-
-
-static int ov7660_get_ctrl(struct sn9c102_device *cam,
-			   struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x10);
-		if (ctrl->value < 0)
-			return -EIO;
-		break;
-	case V4L2_CID_DO_WHITE_BALANCE:
-		ctrl->value = sn9c102_read_reg(cam, 0x02);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
-		break;
-	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_read_reg(cam, 0x05);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x7f;
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_read_reg(cam, 0x06);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x7f;
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_read_reg(cam, 0x07);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x7f;
-		break;
-	case SN9C102_V4L2_CID_BAND_FILTER:
-		ctrl->value = sn9c102_i2c_read(cam, 0x3b);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x08;
-		break;
-	case V4L2_CID_GAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x00);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x1f;
-		break;
-	case V4L2_CID_AUTOGAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x13);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x01;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_ctrl(struct sn9c102_device *cam,
-			   const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-		break;
-	case V4L2_CID_DO_WHITE_BALANCE:
-		err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_write_reg(cam, ctrl->value, 0x06);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-		break;
-	case SN9C102_V4L2_CID_BAND_FILTER:
-		err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
-		break;
-	case V4L2_CID_AUTOGAIN:
-		err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
-						    (ctrl->value * 0x07));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_crop(struct sn9c102_device *cam,
-			   const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int ov7660_set_pix_format(struct sn9c102_device *cam,
-				 const struct v4l2_pix_format *pix)
-{
-	int r0, err = 0;
-
-	r0 = sn9c102_pread_reg(cam, 0x01);
-
-	if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
-		err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
-		err += sn9c102_write_reg(cam, 0xa2, 0x17);
-		err += sn9c102_i2c_write(cam, 0x11, 0x00);
-	} else {
-		err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
-		err += sn9c102_write_reg(cam, 0xa2, 0x17);
-		err += sn9c102_i2c_write(cam, 0x11, 0x0d);
-	}
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor ov7660 = {
-	.name = "OV7660",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x21,
-	.init = &ov7660_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x09,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x27,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_DO_WHITE_BALANCE,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "night mode",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x14,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x14,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_AUTOGAIN,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "auto adjust",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x01,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x7f,
-			.step = 0x01,
-			.default_value = 0x14,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_BAND_FILTER,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "band filter",
-			.minimum = 0x00,
-			.maximum = 0x01,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &ov7660_get_ctrl,
-	.set_ctrl = &ov7660_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &ov7660_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_JPEG,
-		.priv = 8,
-	},
-	.set_pix_format = &ov7660_set_pix_format
-};
-
-
-int sn9c102_probe_ov7660(struct sn9c102_device *cam)
-{
-	int pid, ver, err;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-				       {0x01, 0x01}, {0x00, 0x01},
-				       {0x28, 0x17});
-
-	pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
-	ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
-	if (err || pid < 0 || ver < 0)
-		return -EIO;
-	if (pid != 0x76 || ver != 0x60)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &ov7660);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_pas106b.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_pas106b.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_pas106b.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_pas106b.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program; if not, write to the Free Software             *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas106b_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-				       {0x00, 0x14}, {0x20, 0x17},
-				       {0x20, 0x19}, {0x09, 0x18});
-
-	err += sn9c102_i2c_write(cam, 0x02, 0x0c);
-	err += sn9c102_i2c_write(cam, 0x05, 0x5a);
-	err += sn9c102_i2c_write(cam, 0x06, 0x88);
-	err += sn9c102_i2c_write(cam, 0x07, 0x80);
-	err += sn9c102_i2c_write(cam, 0x10, 0x06);
-	err += sn9c102_i2c_write(cam, 0x11, 0x06);
-	err += sn9c102_i2c_write(cam, 0x12, 0x00);
-	err += sn9c102_i2c_write(cam, 0x14, 0x02);
-	err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
-	msleep(400);
-
-	return err;
-}
-
-
-static int pas106b_get_ctrl(struct sn9c102_device *cam,
-			    struct v4l2_control *ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		{
-			int r1 = sn9c102_i2c_read(cam, 0x03),
-			    r2 = sn9c102_i2c_read(cam, 0x04);
-			if (r1 < 0 || r2 < 0)
-				return -EIO;
-			ctrl->value = (r1 << 4) | (r2 & 0x0f);
-		}
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0c);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x1f;
-		return 0;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x09);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x1f;
-		return 0;
-	case V4L2_CID_GAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0e);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x1f;
-		return 0;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0f);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x07;
-		return 0;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0a);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value = (ctrl->value & 0x1f) << 1;
-		return 0;
-	case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x08);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0xf8;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-
-static int pas106b_set_ctrl(struct sn9c102_device *cam,
-			    const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
-		err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
-		break;
-	case V4L2_CID_CONTRAST:
-		err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
-		err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
-		break;
-	case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-		err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
-		break;
-	default:
-		return -EINVAL;
-	}
-	err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
-	return err ? -EIO : 0;
-}
-
-
-static int pas106b_set_crop(struct sn9c102_device *cam,
-			    const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static int pas106b_set_pix_format(struct sn9c102_device *cam,
-				  const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x2c, 0x17);
-	else
-		err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor pas106b = {
-	.name = "PAS106B",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x40,
-	.init = &pas106b_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x125,
-			.maximum = 0xfff,
-			.step = 0x001,
-			.default_value = 0x140,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x0d,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_CONTRAST,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "contrast",
-			.minimum = 0x00,
-			.maximum = 0x07,
-			.step = 0x01,
-			.default_value = 0x00, /* 0x00~0x03 have same effect */
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x04,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x06,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x3e,
-			.step = 0x02,
-			.default_value = 0x02,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "DAC magnitude",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x01,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &pas106b_get_ctrl,
-	.set_ctrl = &pas106b_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-	},
-	.set_crop = &pas106b_set_crop,
-	.pix_format = {
-		.width = 352,
-		.height = 288,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8, /* we use this field as 'bits per pixel' */
-	},
-	.set_pix_format = &pas106b_set_pix_format
-};
-
-
-int sn9c102_probe_pas106b(struct sn9c102_device *cam)
-{
-	int r0 = 0, r1 = 0;
-	unsigned int pid = 0;
-
-	/*
-	   Minimal initialization to enable the I2C communication
-	   NOTE: do NOT change the values!
-	*/
-	if (sn9c102_write_const_regs(cam,
-				     {0x01, 0x01}, /* sensor power down */
-				     {0x00, 0x01}, /* sensor power on */
-				    {0x28, 0x17})) /* sensor clock at 24 MHz */
-		return -EIO;
-
-	r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
-	r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
-	if (r0 < 0 || r1 < 0)
-		return -EIO;
-
-	pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
-	if (pid != 0x007)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &pas106b);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,340 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera   *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
- *                       <medaglia@undl.org.br>                            *
- *                                                                         *
- * Support for SN9C103, DAC Magnitude, exposure and green gain controls    *
- * added by Luca Risolia <luca.risolia@studio.unibo.it>                    *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program; if not, write to the Free Software             *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas202bcb_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-					       {0x00, 0x14}, {0x20, 0x17},
-					       {0x30, 0x19}, {0x09, 0x18});
-		break;
-	case BRIDGE_SN9C103:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
-					       {0x1a, 0x04}, {0x20, 0x05},
-					       {0x20, 0x06}, {0x20, 0x07},
-					       {0x00, 0x10}, {0x00, 0x11},
-					       {0x00, 0x14}, {0x20, 0x17},
-					       {0x30, 0x19}, {0x09, 0x18},
-					       {0x02, 0x1c}, {0x03, 0x1d},
-					       {0x0f, 0x1e}, {0x0c, 0x1f},
-					       {0x00, 0x20}, {0x10, 0x21},
-					       {0x20, 0x22}, {0x30, 0x23},
-					       {0x40, 0x24}, {0x50, 0x25},
-					       {0x60, 0x26}, {0x70, 0x27},
-					       {0x80, 0x28}, {0x90, 0x29},
-					       {0xa0, 0x2a}, {0xb0, 0x2b},
-					       {0xc0, 0x2c}, {0xd0, 0x2d},
-					       {0xe0, 0x2e}, {0xf0, 0x2f},
-					       {0xff, 0x30});
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_i2c_write(cam, 0x02, 0x14);
-	err += sn9c102_i2c_write(cam, 0x03, 0x40);
-	err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
-	err += sn9c102_i2c_write(cam, 0x0e, 0x01);
-	err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
-	err += sn9c102_i2c_write(cam, 0x10, 0x08);
-	err += sn9c102_i2c_write(cam, 0x13, 0x63);
-	err += sn9c102_i2c_write(cam, 0x15, 0x70);
-	err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-	msleep(400);
-
-	return err;
-}
-
-
-static int pas202bcb_get_ctrl(struct sn9c102_device *cam,
-			      struct v4l2_control *ctrl)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		{
-			int r1 = sn9c102_i2c_read(cam, 0x04),
-			    r2 = sn9c102_i2c_read(cam, 0x05);
-			if (r1 < 0 || r2 < 0)
-				return -EIO;
-			ctrl->value = (r1 << 6) | (r2 & 0x3f);
-		}
-		return 0;
-	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x09);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x0f;
-		return 0;
-	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x07);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x0f;
-		return 0;
-	case V4L2_CID_GAIN:
-		ctrl->value = sn9c102_i2c_read(cam, 0x10);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x1f;
-		return 0;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x08);
-		if (ctrl->value < 0)
-			return -EIO;
-		ctrl->value &= 0x0f;
-		return 0;
-	case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-		ctrl->value = sn9c102_i2c_read(cam, 0x0c);
-		if (ctrl->value < 0)
-			return -EIO;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-
-static int pas202bcb_set_pix_format(struct sn9c102_device *cam,
-				    const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x28, 0x17);
-	else
-		err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-	return err;
-}
-
-
-static int pas202bcb_set_ctrl(struct sn9c102_device *cam,
-			      const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
-		err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-	err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-	return err ? -EIO : 0;
-}
-
-
-static int pas202bcb_set_crop(struct sn9c102_device *cam,
-			      const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = 0,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
-		break;
-	case BRIDGE_SN9C103:
-		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
-		break;
-	default:
-		break;
-	}
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor pas202bcb = {
-	.name = "PAS202BCB",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x40,
-	.init = &pas202bcb_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x01e5,
-			.maximum = 0x3fff,
-			.step = 0x0001,
-			.default_value = 0x01e5,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x0b,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x05,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "DAC magnitude",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x04,
-			.flags = 0,
-		},
-	},
-	.get_ctrl = &pas202bcb_get_ctrl,
-	.set_ctrl = &pas202bcb_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &pas202bcb_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &pas202bcb_set_pix_format
-};
-
-
-int sn9c102_probe_pas202bcb(struct sn9c102_device *cam)
-{
-	int r0 = 0, r1 = 0, err = 0;
-	unsigned int pid = 0;
-
-	/*
-	 *  Minimal initialization to enable the I2C communication
-	 *  NOTE: do NOT change the values!
-	 */
-	switch (sn9c102_get_bridge(cam)) {
-	case BRIDGE_SN9C101:
-	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam,
-					       {0x01, 0x01}, /* power down */
-					       {0x40, 0x01}, /* power on */
-					       {0x28, 0x17});/* clock 24 MHz */
-		break;
-	case BRIDGE_SN9C103: /* do _not_ change anything! */
-		err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
-					       {0x44, 0x02}, {0x29, 0x17});
-		break;
-	default:
-		break;
-	}
-
-	r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
-	r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
-
-	if (err || r0 < 0 || r1 < 0)
-		return -EIO;
-
-	pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
-	if (pid != 0x017)
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &pas202bcb);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_sensor.h linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_sensor.h
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_sensor.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_sensor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,307 +0,0 @@
-/***************************************************************************
- * API for image sensors connected to the SN9C1xx PC Camera Controllers    *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 _SN9C102_SENSOR_H_
-#define _SN9C102_SENSOR_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/device.h>
-#include <linux/stddef.h>
-#include <linux/errno.h>
-#include <asm/types.h>
-
-struct sn9c102_device;
-struct sn9c102_sensor;
-
-/*****************************************************************************/
-
-/*
-   OVERVIEW.
-   This is a small interface that allows you to add support for any CCD/CMOS
-   image sensors connected to the SN9C1XX bridges. The entire API is documented
-   below. In the most general case, to support a sensor there are three steps
-   you have to follow:
-   1) define the main "sn9c102_sensor" structure by setting the basic fields;
-   2) write a probing function to be called by the core module when the USB
-      camera is recognized, then add both the USB ids and the name of that
-      function to the two corresponding tables in sn9c102_devtable.h;
-   3) implement the methods that you want/need (and fill the rest of the main
-      structure accordingly).
-   "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
-   NOT need to touch the source code of the core module for the things to work
-   properly, unless you find bugs or flaws in it. Finally, do not forget to
-   read the V4L2 API for completeness.
-*/
-
-/*****************************************************************************/
-
-enum sn9c102_bridge {
-	BRIDGE_SN9C101 = 0x01,
-	BRIDGE_SN9C102 = 0x02,
-	BRIDGE_SN9C103 = 0x04,
-	BRIDGE_SN9C105 = 0x08,
-	BRIDGE_SN9C120 = 0x10,
-};
-
-/* Return the bridge name */
-enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device *cam);
-
-/* Return a pointer the sensor struct attached to the camera */
-struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam);
-
-/* Identify a device */
-extern struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id);
-
-/* Attach a probed sensor to the camera. */
-extern void
-sn9c102_attach_sensor(struct sn9c102_device *cam,
-		      const struct sn9c102_sensor *sensor);
-
-/*
-   Read/write routines: they always return -1 on error, 0 or the read value
-   otherwise. NOTE that a real read operation is not supported by the SN9C1XX
-   chip for some of its registers. To work around this problem, a pseudo-read
-   call is provided instead: it returns the last successfully written value
-   on the register (0 if it has never been written), the usual -1 on error.
-*/
-
-/* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_read(struct sn9c102_device*,
-				const struct sn9c102_sensor*, u8 address);
-
-/*
-   These must be used if and only if the sensor doesn't implement the standard
-   I2C protocol. There are a number of good reasons why you must use the
-   single-byte versions of these functions: do not abuse. The first function
-   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
-   chip. The second one programs the registers 0x09 and 0x10 with data0 and
-   data1, and places the n bytes read from the sensor register table in the
-   buffer pointed by 'buffer'. Both the functions return -1 on error; the write
-   version returns 0 on success, while the read version returns the first read
-   byte.
-*/
-extern int sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
-				     const struct sn9c102_sensor *sensor, u8 n,
-				     u8 data0, u8 data1, u8 data2, u8 data3,
-				     u8 data4, u8 data5);
-extern int sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
-				    const struct sn9c102_sensor *sensor,
-				    u8 data0, u8 data1, u8 n, u8 buffer[]);
-
-/* To be used after the sensor struct has been attached to the camera struct */
-extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
-extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
-
-/* I/O on registers in the bridge. Could be used by the sensor methods too */
-extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
-extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
-			      int count);
-/*
-   Write multiple registers with constant values. For example:
-   sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
-   Register addresses must be < 256.
-*/
-#define sn9c102_write_const_regs(sn9c102_device, data...)                     \
-	({ static const u8 _valreg[][2] = {data};                             \
-	sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
-
-/*****************************************************************************/
-
-enum sn9c102_i2c_sysfs_ops {
-	SN9C102_I2C_READ = 0x01,
-	SN9C102_I2C_WRITE = 0x02,
-};
-
-enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
-	SN9C102_I2C_100KHZ = 0x01,
-	SN9C102_I2C_400KHZ = 0x02,
-};
-
-enum sn9c102_i2c_interface {
-	SN9C102_I2C_2WIRES,
-	SN9C102_I2C_3WIRES,
-};
-
-#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
-
-struct sn9c102_sensor {
-	char name[32], /* sensor name */
-	     maintainer[64]; /* name of the maintainer <email> */
-
-	enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
-
-	/* Supported operations through the 'sysfs' interface */
-	enum sn9c102_i2c_sysfs_ops sysfs_ops;
-
-	/*
-	   These sensor capabilities must be provided if the SN9C1XX controller
-	   needs to communicate through the sensor serial interface by using
-	   at least one of the i2c functions available.
-	*/
-	enum sn9c102_i2c_frequency frequency;
-	enum sn9c102_i2c_interface interface;
-
-	/*
-	   This identifier must be provided if the image sensor implements
-	   the standard I2C protocol.
-	*/
-	u8 i2c_slave_id; /* reg. 0x09 */
-
-	/*
-	   NOTE: Where not noted,most of the functions below are not mandatory.
-		 Set to null if you do not implement them. If implemented,
-		 they must return 0 on success, the proper error otherwise.
-	*/
-
-	int (*init)(struct sn9c102_device *cam);
-	/*
-	   This function will be called after the sensor has been attached.
-	   It should be used to initialize the sensor only, but may also
-	   configure part of the SN9C1XX chip if necessary. You don't need to
-	   setup picture settings like brightness, contrast, etc.. here, if
-	   the corresponding controls are implemented (see below), since
-	   they are adjusted in the core driver by calling the set_ctrl()
-	   method after init(), where the arguments are the default values
-	   specified in the v4l2_queryctrl list of supported controls;
-	   Same suggestions apply for other settings, _if_ the corresponding
-	   methods are present; if not, the initialization must configure the
-	   sensor according to the default configuration structures below.
-	*/
-
-	struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
-	/*
-	   Optional list of default controls, defined as indicated in the
-	   V4L2 API. Menu type controls are not handled by this interface.
-	*/
-
-	int (*get_ctrl)(struct sn9c102_device *cam, struct v4l2_control *ctrl);
-	int (*set_ctrl)(struct sn9c102_device *cam,
-			const struct v4l2_control *ctrl);
-	/*
-	   You must implement at least the set_ctrl method if you have defined
-	   the list above. The returned value must follow the V4L2
-	   specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
-	   are not supported by this driver, so do not implement them. Also,
-	   you don't have to check whether the passed values are out of bounds,
-	   given that this is done by the core module.
-	*/
-
-	struct v4l2_cropcap cropcap;
-	/*
-	   Think the image sensor as a grid of R,G,B monochromatic pixels
-	   disposed according to a particular Bayer pattern, which describes
-	   the complete array of pixels, from (0,0) to (xmax, ymax). We will
-	   use this coordinate system from now on. It is assumed the sensor
-	   chip can be programmed to capture/transmit a subsection of that
-	   array of pixels: we will call this subsection "active window".
-	   It is not always true that the largest achievable active window can
-	   cover the whole array of pixels. The V4L2 API defines another
-	   area called "source rectangle", which, in turn, is a subrectangle of
-	   the active window. The SN9C1XX chip is always programmed to read the
-	   source rectangle.
-	   The bounds of both the active window and the source rectangle are
-	   specified in the cropcap substructures 'bounds' and 'defrect'.
-	   By default, the source rectangle should cover the largest possible
-	   area. Again, it is not always true that the largest source rectangle
-	   can cover the entire active window, although it is a rare case for
-	   the hardware we have. The bounds of the source rectangle _must_ be
-	   multiple of 16 and must use the same coordinate system as indicated
-	   before; their centers shall align initially.
-	   If necessary, the sensor chip must be initialized during init() to
-	   set the bounds of the active sensor window; however, by default, it
-	   usually covers the largest achievable area (maxwidth x maxheight)
-	   of pixels, so no particular initialization is needed, if you have
-	   defined the correct default bounds in the structures.
-	   See the V4L2 API for further details.
-	   NOTE: once you have defined the bounds of the active window
-		 (struct cropcap.bounds) you must not change them.anymore.
-	   Only 'bounds' and 'defrect' fields are mandatory, other fields
-	   will be ignored.
-	*/
-
-	int (*set_crop)(struct sn9c102_device *cam,
-			const struct v4l2_rect *rect);
-	/*
-	   To be called on VIDIOC_C_SETCROP. The core module always calls a
-	   default routine which configures the appropriate SN9C1XX regs (also
-	   scaling), but you may need to override/adjust specific stuff.
-	   'rect' contains width and height values that are multiple of 16: in
-	   case you override the default function, you always have to program
-	   the chip to match those values; on error return the corresponding
-	   error code without rolling back.
-	   NOTE: in case, you must program the SN9C1XX chip to get rid of
-		 blank pixels or blank lines at the _start_ of each line or
-		 frame after each HSYNC or VSYNC, so that the image starts with
-		 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
-		 V_SIZE you don't have to care about blank pixels or blank
-		 lines at the end of each line or frame).
-	*/
-
-	struct v4l2_pix_format pix_format;
-	/*
-	   What you have to define here are: 1) initial 'width' and 'height' of
-	   the target rectangle 2) the initial 'pixelformat', which can be
-	   either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
-	   or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
-	   the number of bits per pixel for uncompressed video, 8 or 9 (despite
-	   the current value of 'pixelformat').
-	   NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
-		   of cropcap.defrect.width and cropcap.defrect.height. I
-		   suggest 1/1.
-	   NOTE 2: The initial compression quality is defined by the first bit
-		   of reg 0x17 during the initialization of the image sensor.
-	   NOTE 3: as said above, you have to program the SN9C1XX chip to get
-		   rid of any blank pixels, so that the output of the sensor
-		   matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
-	*/
-
-	int (*set_pix_format)(struct sn9c102_device *cam,
-			      const struct v4l2_pix_format *pix);
-	/*
-	   To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
-	   SN9C10X pixel format or viceversa. On error return the corresponding
-	   error code without rolling back.
-	*/
-
-	/*
-	   Do NOT write to the data below, it's READ ONLY. It is used by the
-	   core module to store successfully updated values of the above
-	   settings, for rollbacks..etc..in case of errors during atomic I/O
-	*/
-	struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
-	struct v4l2_rect _rect;
-};
-
-/*****************************************************************************/
-
-/* Private ioctl's for control settings supported by some image sensors */
-#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
-#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
-#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
-#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
-#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
-#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
-#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
-
-#endif /* _SN9C102_SENSOR_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera  *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110c1b_init(struct sn9c102_device *cam)
-{
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
-				       {0x00, 0x10}, {0x00, 0x11},
-				       {0x0a, 0x14}, {0x60, 0x17},
-				       {0x06, 0x18}, {0xfb, 0x19});
-
-	err += sn9c102_i2c_write(cam, 0xc0, 0x80);
-
-	return err;
-}
-
-
-static int tas5110c1b_set_ctrl(struct sn9c102_device *cam,
-			       const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int tas5110c1b_set_crop(struct sn9c102_device *cam,
-			       const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	/* Don't change ! */
-	err += sn9c102_write_reg(cam, 0x14, 0x1a);
-	err += sn9c102_write_reg(cam, 0x0a, 0x1b);
-	err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
-	return err;
-}
-
-
-static int tas5110c1b_set_pix_format(struct sn9c102_device *cam,
-				     const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x2b, 0x19);
-	else
-		err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor tas5110c1b = {
-	.name = "TAS5110C1B",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.sysfs_ops = SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_3WIRES,
-	.init = &tas5110c1b_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0xf6,
-			.step = 0x01,
-			.default_value = 0x40,
-			.flags = 0,
-		},
-	},
-	.set_ctrl = &tas5110c1b_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-	},
-	.set_crop = &tas5110c1b_set_crop,
-	.pix_format = {
-		.width = 352,
-		.height = 288,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &tas5110c1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam)
-{
-	const struct usb_device_id tas5110c1b_id_table[] = {
-		{ USB_DEVICE(0x0c45, 0x6001), },
-		{ USB_DEVICE(0x0c45, 0x6005), },
-		{ USB_DEVICE(0x0c45, 0x60ab), },
-		{ }
-	};
-
-	/* Sensor detection is based on USB pid/vid */
-	if (!sn9c102_match_id(cam, tas5110c1b_id_table))
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &tas5110c1b);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110d.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110d.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5110d.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera    *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110d_init(struct sn9c102_device *cam)
-{
-	int err;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
-				       {0x0a, 0x14}, {0x60, 0x17},
-				       {0x06, 0x18}, {0xfb, 0x19});
-
-	err += sn9c102_i2c_write(cam, 0x9a, 0xca);
-
-	return err;
-}
-
-
-static int tas5110d_set_crop(struct sn9c102_device *cam,
-			     const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	err += sn9c102_write_reg(cam, 0x14, 0x1a);
-	err += sn9c102_write_reg(cam, 0x0a, 0x1b);
-
-	return err;
-}
-
-
-static int tas5110d_set_pix_format(struct sn9c102_device *cam,
-				     const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x3b, 0x19);
-	else
-		err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor tas5110d = {
-	.name = "TAS5110D",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.sysfs_ops = SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x61,
-	.init = &tas5110d_init,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 352,
-			.height = 288,
-		},
-	},
-	.set_crop = &tas5110d_set_crop,
-	.pix_format = {
-		.width = 352,
-		.height = 288,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &tas5110d_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110d(struct sn9c102_device *cam)
-{
-	const struct usb_device_id tas5110d_id_table[] = {
-		{ USB_DEVICE(0x0c45, 0x6007), },
-		{ }
-	};
-
-	if (!sn9c102_match_id(cam, tas5110d_id_table))
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &tas5110d);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,165 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera  *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5130d1b_init(struct sn9c102_device *cam)
-{
-	int err;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
-				       {0x04, 0x01}, {0x01, 0x10},
-				       {0x00, 0x11}, {0x00, 0x14},
-				       {0x60, 0x17}, {0x07, 0x18});
-
-	return err;
-}
-
-
-static int tas5130d1b_set_ctrl(struct sn9c102_device *cam,
-			       const struct v4l2_control *ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
-		break;
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return err ? -EIO : 0;
-}
-
-
-static int tas5130d1b_set_crop(struct sn9c102_device *cam,
-			       const struct v4l2_rect *rect)
-{
-	struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
-	int err = 0;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	/* Do NOT change! */
-	err += sn9c102_write_reg(cam, 0x1f, 0x1a);
-	err += sn9c102_write_reg(cam, 0x1a, 0x1b);
-	err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
-	return err;
-}
-
-
-static int tas5130d1b_set_pix_format(struct sn9c102_device *cam,
-				     const struct v4l2_pix_format *pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x63, 0x19);
-	else
-		err += sn9c102_write_reg(cam, 0xf3, 0x19);
-
-	return err;
-}
-
-
-static const struct sn9c102_sensor tas5130d1b = {
-	.name = "TAS5130D1B",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-	.sysfs_ops = SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_3WIRES,
-	.init = &tas5130d1b_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0xf6,
-			.step = 0x02,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = 0x47,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-	},
-	.set_ctrl = &tas5130d1b_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &tas5130d1b_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &tas5130d1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam)
-{
-	const struct usb_device_id tas5130d1b_id_table[] = {
-		{ USB_DEVICE(0x0c45, 0x6024), },
-		{ USB_DEVICE(0x0c45, 0x6025), },
-		{ USB_DEVICE(0x0c45, 0x60aa), },
-		{ }
-	};
-
-	/* Sensor detection is based on USB pid/vid */
-	if (!sn9c102_match_id(cam, tas5130d1b_id_table))
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &tas5130d1b);
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102.txt linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102.txt
--- linux-libre-3.16-gnu/drivers/staging/media/sn9c102/sn9c102.txt	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/sn9c102/sn9c102.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,592 +0,0 @@
-
-			 SN9C1xx PC Camera Controllers
-				Driver for Linux
-			 =============================
-
-			       - Documentation -
-
-
-Index
-=====
-1.  Copyright
-2.  Disclaimer
-3.  License
-4.  Overview and features
-5.  Module dependencies
-6.  Module loading
-7.  Module parameters
-8.  Optional device control through "sysfs"
-9.  Supported devices
-10. Notes for V4L2 application developers
-11. Video frame formats
-12. Contact information
-13. Credits
-
-
-1. Copyright
-============
-Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
-
-
-2. Disclaimer
-=============
-SONiX is a trademark of SONiX Technology Company Limited, inc.
-This software is not sponsored or developed by SONiX.
-
-
-3. License
-==========
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You 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.
-
-
-4. Overview and features
-========================
-This driver attempts to support the video interface of the devices assembling
-the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers
-("SN9C1xx" from now on).
-
-The driver relies on the Video4Linux2 and USB core modules. It has been
-designed to run properly on SMP systems as well.
-
-The latest version of the SN9C1xx driver can be found at the following URL:
-http://www.linux-projects.org/
-
-Some of the features of the driver are:
-
-- full compliance with the Video4Linux2 API (see also "Notes for V4L2
-  application developers" paragraph);
-- available mmap or read/poll methods for video streaming through isochronous
-  data transfers;
-- automatic detection of image sensor;
-- support for built-in microphone interface;
-- support for any window resolutions and optional panning within the maximum
-  pixel area of image sensor;
-- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
-  directions (see "Notes for V4L2 application developers" paragraph);
-- two different video formats for uncompressed or compressed data in low or
-  high compression quality (see also "Notes for V4L2 application developers"
-  and "Video frame formats" paragraphs);
-- full support for the capabilities of many of the possible image sensors that
-  can be connected to the SN9C1xx bridges, including, for instance, red, green,
-  blue and global gain adjustments and exposure (see "Supported devices"
-  paragraph for details);
-- use of default color settings for sunlight conditions;
-- dynamic I/O interface for both SN9C1xx and image sensor control and
-  monitoring (see "Optional device control through 'sysfs'" paragraph);
-- dynamic driver control thanks to various module parameters (see "Module
-  parameters" paragraph);
-- up to 64 cameras can be handled at the same time; they can be connected and
-  disconnected from the host many times without turning off the computer, if
-  the system supports hotplugging;
-- no known bugs.
-
-
-5. Module dependencies
-======================
-For it to work properly, the driver needs kernel support for Video4Linux and
-USB.
-
-The following options of the kernel configuration file must be enabled and
-corresponding modules must be compiled:
-
-	# Multimedia devices
-	#
-	CONFIG_VIDEO_DEV=m
-
-To enable advanced debugging functionality on the device through /sysfs:
-
-	# Multimedia devices
-	#
-	CONFIG_VIDEO_ADV_DEBUG=y
-
-	# USB support
-	#
-	CONFIG_USB=m
-
-In addition, depending on the hardware being used, the modules below are
-necessary:
-
-	# USB Host Controller Drivers
-	#
-	CONFIG_USB_EHCI_HCD=m
-	CONFIG_USB_UHCI_HCD=m
-	CONFIG_USB_OHCI_HCD=m
-
-The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone
-interface. It is supported by the USB Audio driver thanks to the ALSA API:
-
-	# Sound
-	#
-	CONFIG_SOUND=y
-
-	# Advanced Linux Sound Architecture
-	#
-	CONFIG_SND=m
-
-	# USB devices
-	#
-	CONFIG_SND_USB_AUDIO=m
-
-And finally:
-
-	# USB Multimedia devices
-	#
-	CONFIG_USB_SN9C102=m
-
-
-6. Module loading
-=================
-To use the driver, it is necessary to load the "sn9c102" module into memory
-after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
-"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
-"uhci-hcd" or "ohci-hcd".
-
-Loading can be done as shown below:
-
-	[root@localhost home]# modprobe sn9c102
-
-Note that the module is called "sn9c102" for historic reasons, although it
-does not just support the SN9C102.
-
-At this point all the devices supported by the driver and connected to the USB
-ports should be recognized. You can invoke "dmesg" to analyze kernel messages
-and verify that the loading process has gone well:
-
-	[user@localhost home]$ dmesg
-
-or, to isolate all the kernel messages generated by the driver:
-
-	[user@localhost home]$ dmesg | grep sn9c102
-
-
-7. Module parameters
-====================
-Module parameters are listed below:
--------------------------------------------------------------------------------
-Name:           video_nr
-Type:           short array (min = 0, max = 64)
-Syntax:         <-1|n[,...]>
-Description:    Specify V4L2 minor mode number:
-		-1 = use next available
-		 n = use minor number n
-		You can specify up to 64 cameras this way.
-		For example:
-		video_nr=-1,2,-1 would assign minor number 2 to the second
-		recognized camera and use auto for the first one and for every
-		other camera.
-Default:        -1
--------------------------------------------------------------------------------
-Name:           force_munmap
-Type:           bool array (min = 0, max = 64)
-Syntax:         <0|1[,...]>
-Description:    Force the application to unmap previously mapped buffer memory
-		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-		all the applications support this feature. This parameter is
-		specific for each detected camera.
-		0 = do not force memory unmapping
-		1 = force memory unmapping (save memory)
-Default:        0
--------------------------------------------------------------------------------
-Name:           frame_timeout
-Type:           uint array (min = 0, max = 64)
-Syntax:         <0|n[,...]>
-Description:    Timeout for a video frame in seconds before returning an I/O
-		error; 0 for infinity. This parameter is specific for each
-		detected camera and can be changed at runtime thanks to the
-		/sys filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-Name:           debug
-Type:           ushort
-Syntax:         <n>
-Description:    Debugging information level, from 0 to 3:
-		0 = none (use carefully)
-		1 = critical errors
-		2 = significant information
-		3 = more verbose messages
-		Level 3 is useful for testing only. It also shows some more
-		information about the hardware being detected.
-		This parameter can be changed at runtime thanks to the /sys
-		filesystem interface.
-Default:        2
--------------------------------------------------------------------------------
-
-
-8. Optional device control through "sysfs" [1]
-==========================================
-If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
-it is possible to read and write both the SN9C1xx and the image sensor
-registers by using the "sysfs" filesystem interface.
-
-Every time a supported device is recognized, a write-only file named "green" is
-created in the /sys/class/video4linux/videoX directory. You can set the green
-channel's gain by writing the desired value to it. The value may range from 0
-to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
-SN9C105 and SN9C120 bridges.
-Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
-gain control files are available in the same directory, for which accepted
-values may range from 0 to 127.
-
-There are other four entries in the directory above for each registered camera:
-"reg", "val", "i2c_reg" and "i2c_val". The first two files control the
-SN9C1xx bridge, while the other two control the sensor chip. "reg" and
-"i2c_reg" hold the values of the current register index where the following
-reading/writing operations are addressed at through "val" and "i2c_val". Their
-use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
-be created if the sensor does not actually support the standard I2C protocol or
-its registers are not 8-bit long. Also, remember that you must be logged in as
-root before writing to them.
-
-As an example, suppose we were to want to read the value contained in the
-register number 1 of the sensor register table - which is usually the product
-identifier - of the camera registered as "/dev/video0":
-
-	[root@localhost #] cd /sys/class/video4linux/video0
-	[root@localhost #] echo 1 > i2c_reg
-	[root@localhost #] cat i2c_val
-
-Note that "cat" will fail if sensor registers cannot be read.
-
-Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2:
-
-	[root@localhost #] echo 0x11 > reg
-	[root@localhost #] echo 2 > val
-
-Note that the SN9C1xx always returns 0 when some of its registers are read.
-To avoid race conditions, all the I/O accesses to the above files are
-serialized.
-The sysfs interface also provides the "frame_header" entry, which exports the
-frame header of the most recent requested and captured video frame. The header
-is always 18-bytes long and is appended to every video frame by the SN9C1xx
-controllers. As an example, this additional information can be used by the user
-application for implementing auto-exposure features via software.
-
-The following table describes the frame header exported by the SN9C101 and
-SN9C102:
-
-Byte #  Value or bits Description
-------  ------------- -----------
-0x00    0xFF          Frame synchronisation pattern
-0x01    0xFF          Frame synchronisation pattern
-0x02    0x00          Frame synchronisation pattern
-0x03    0xC4          Frame synchronisation pattern
-0x04    0xC4          Frame synchronisation pattern
-0x05    0x96          Frame synchronisation pattern
-0x06    [3:0]         Read channel gain control = (1+R_GAIN/8)
-	[7:4]         Blue channel gain control = (1+B_GAIN/8)
-0x07    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
-	[2:1]         Maximum scale factor for compression
-	[ 3 ]         1 = USB fifo(2K bytes) is full
-	[ 4 ]         1 = Digital gain is finish
-	[ 5 ]         1 = Exposure is finish
-	[7:6]         Frame index
-0x08    [7:0]         Y sum inside Auto-Exposure area (low-byte)
-0x09    [7:0]         Y sum inside Auto-Exposure area (high-byte)
-		      where Y sum = (R/4 + 5G/16 + B/8) / 32
-0x0A    [7:0]         Y sum outside Auto-Exposure area (low-byte)
-0x0B    [7:0]         Y sum outside Auto-Exposure area (high-byte)
-		      where Y sum = (R/4 + 5G/16 + B/8) / 128
-0x0C    0xXX          Not used
-0x0D    0xXX          Not used
-0x0E    0xXX          Not used
-0x0F    0xXX          Not used
-0x10    0xXX          Not used
-0x11    0xXX          Not used
-
-The following table describes the frame header exported by the SN9C103:
-
-Byte #  Value or bits Description
-------  ------------- -----------
-0x00    0xFF          Frame synchronisation pattern
-0x01    0xFF          Frame synchronisation pattern
-0x02    0x00          Frame synchronisation pattern
-0x03    0xC4          Frame synchronisation pattern
-0x04    0xC4          Frame synchronisation pattern
-0x05    0x96          Frame synchronisation pattern
-0x06    [6:0]         Read channel gain control = (1/2+R_GAIN/64)
-0x07    [6:0]         Blue channel gain control = (1/2+B_GAIN/64)
-	[7:4]
-0x08    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
-	[2:1]         Maximum scale factor for compression
-	[ 3 ]         1 = USB fifo(2K bytes) is full
-	[ 4 ]         1 = Digital gain is finish
-	[ 5 ]         1 = Exposure is finish
-	[7:6]         Frame index
-0x09    [7:0]         Y sum inside Auto-Exposure area (low-byte)
-0x0A    [7:0]         Y sum inside Auto-Exposure area (high-byte)
-		      where Y sum = (R/4 + 5G/16 + B/8) / 32
-0x0B    [7:0]         Y sum outside Auto-Exposure area (low-byte)
-0x0C    [7:0]         Y sum outside Auto-Exposure area (high-byte)
-		      where Y sum = (R/4 + 5G/16 + B/8) / 128
-0x0D    [1:0]         Audio frame number
-	[ 2 ]         1 = Audio is recording
-0x0E    [7:0]         Audio summation (low-byte)
-0x0F    [7:0]         Audio summation (high-byte)
-0x10    [7:0]         Audio sample count
-0x11    [7:0]         Audio peak data in audio frame
-
-The AE area (sx, sy, ex, ey) in the active window can be set by programming the
-registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit
-corresponds to 32 pixels.
-
-[1] The frame headers exported by the SN9C105 and SN9C120 are not described.
-
-
-9. Supported devices
-====================
-None of the names of the companies as well as their products will be mentioned
-here. They have never collaborated with the author, so no advertising.
-
-From the point of view of a driver, what unambiguously identify a device are
-its vendor and product USB identifiers. Below is a list of known identifiers of
-devices assembling the SN9C1xx PC camera controllers:
-
-Vendor ID  Product ID
----------  ----------
-0x0458     0x7025
-0x045e     0x00f5
-0x045e     0x00f7
-0x0471     0x0327
-0x0471     0x0328
-0x0c45     0x6001
-0x0c45     0x6005
-0x0c45     0x6007
-0x0c45     0x6009
-0x0c45     0x600d
-0x0c45     0x6011
-0x0c45     0x6019
-0x0c45     0x6024
-0x0c45     0x6025
-0x0c45     0x6028
-0x0c45     0x6029
-0x0c45     0x602a
-0x0c45     0x602b
-0x0c45     0x602c
-0x0c45     0x602d
-0x0c45     0x602e
-0x0c45     0x6030
-0x0c45     0x603f
-0x0c45     0x6080
-0x0c45     0x6082
-0x0c45     0x6083
-0x0c45     0x6088
-0x0c45     0x608a
-0x0c45     0x608b
-0x0c45     0x608c
-0x0c45     0x608e
-0x0c45     0x608f
-0x0c45     0x60a0
-0x0c45     0x60a2
-0x0c45     0x60a3
-0x0c45     0x60a8
-0x0c45     0x60aa
-0x0c45     0x60ab
-0x0c45     0x60ac
-0x0c45     0x60ae
-0x0c45     0x60af
-0x0c45     0x60b0
-0x0c45     0x60b2
-0x0c45     0x60b3
-0x0c45     0x60b8
-0x0c45     0x60ba
-0x0c45     0x60bb
-0x0c45     0x60bc
-0x0c45     0x60be
-0x0c45     0x60c0
-0x0c45     0x60c2
-0x0c45     0x60c8
-0x0c45     0x60cc
-0x0c45     0x60ea
-0x0c45     0x60ec
-0x0c45     0x60ef
-0x0c45     0x60fa
-0x0c45     0x60fb
-0x0c45     0x60fc
-0x0c45     0x60fe
-0x0c45     0x6102
-0x0c45     0x6108
-0x0c45     0x610f
-0x0c45     0x6130
-0x0c45     0x6138
-0x0c45     0x613a
-0x0c45     0x613b
-0x0c45     0x613c
-0x0c45     0x613e
-
-The list above does not imply that all those devices work with this driver: up
-until now only the ones that assemble the following pairs of SN9C1xx bridges
-and image sensors are supported; kernel messages will always tell you whether
-this is the case (see "Module loading" paragraph):
-
-Image sensor / SN9C1xx bridge      | SN9C10[12]  SN9C103  SN9C105  SN9C120
--------------------------------------------------------------------------------
-HV7131D    Hynix Semiconductor     | Yes         No       No       No
-HV7131R    Hynix Semiconductor     | No          Yes      Yes      Yes
-MI-0343    Micron Technology       | Yes         No       No       No
-MI-0360    Micron Technology       | No          Yes      Yes      Yes
-OV7630     OmniVision Technologies | Yes         Yes      Yes      Yes
-OV7660     OmniVision Technologies | No          No       Yes      Yes
-PAS106B    PixArt Imaging          | Yes         No       No       No
-PAS202B    PixArt Imaging          | Yes         Yes      No       No
-TAS5110C1B Taiwan Advanced Sensor  | Yes         No       No       No
-TAS5110D   Taiwan Advanced Sensor  | Yes         No       No       No
-TAS5130D1B Taiwan Advanced Sensor  | Yes         No       No       No
-
-"Yes" means that the pair is supported by the driver, while "No" means that the
-pair does not exist or is not supported by the driver.
-
-Only some of the available control settings of each image sensor are supported
-through the V4L2 interface.
-
-Donations of new models for further testing and support would be much
-appreciated. Non-available hardware will not be supported by the author of this
-driver.
-
-
-10. Notes for V4L2 application developers
-=========================================
-This driver follows the V4L2 API specifications. In particular, it enforces two
-rules:
-
-- exactly one I/O method, either "mmap" or "read", is associated with each
-file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method;
-
-- although it is not mandatory, previously mapped buffer memory should always
-be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
-The same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map the buffers again before any I/O
-attempts on them.
-
-Consistently with the hardware limits, this driver also supports image
-downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
-However, the V4L2 API specifications don't correctly define how the scaling
-factor can be chosen arbitrarily by the "negotiation" of the "source" and
-"target" rectangles. To work around this flaw, we have added the convention
-that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
-scaling factor is restored to 1.
-
-This driver supports two different video formats: the first one is the "8-bit
-Sequential Bayer" format and can be used to obtain uncompressed video data
-from the device through the current I/O method, while the second one provides
-either "raw" compressed video data (without frame headers not related to the
-compressed data) or standard JPEG (with frame headers). The compression quality
-may vary from 0 to 1 and can be selected or queried thanks to the
-VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
-both the default active video format and the default compression quality
-depend on how the image sensor being used is initialized.
-
-
-11. Video frame formats [1]
-=======================
-The SN9C1xx PC Camera Controllers can send images in two possible video
-formats over the USB: either native "Sequential RGB Bayer" or compressed.
-The compression is used to achieve high frame rates. With regard to the
-SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
-algorithm described below, while with regard to the SN9C105 and SN9C120 the
-compression is based on the JPEG standard.
-The current video format may be selected or queried from the user application
-by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
-API specifications.
-
-The name "Sequential Bayer" indicates the organization of the red, green and
-blue pixels in one video frame. Each pixel is associated with a 8-bit long
-value and is disposed in memory according to the pattern shown below:
-
-B[0]   G[1]    B[2]    G[3]    ...   B[m-2]         G[m-1]
-G[m]   R[m+1]  G[m+2]  R[m+2]  ...   G[2m-2]        R[2m-1]
-...
-...                                  B[(n-1)(m-2)]  G[(n-1)(m-1)]
-...                                  G[n(m-2)]      R[n(m-1)]
-
-The above matrix also represents the sequential or progressive read-out mode of
-the (n, m) Bayer color filter array used in many CCD or CMOS image sensors.
-
-The Huffman compressed video frame consists of a bitstream that encodes for
-every R, G, or B pixel the difference between the value of the pixel itself and
-some reference pixel value. Pixels are organised in the Bayer pattern and the
-Bayer sub-pixels are tracked individually and alternatingly. For example, in
-the first line values for the B and G1 pixels are alternatingly encoded, while
-in the second line values for the G2 and R pixels are alternatingly encoded.
-
-The pixel reference value is calculated as follows:
-- the 4 top left pixels are encoded in raw uncompressed 8-bit format;
-- the value in the top two rows is the value of the pixel left of the current
-  pixel;
-- the value in the left column is the value of the pixel above the current
-  pixel;
-- for all other pixels, the reference value is the average of the value of the
-  pixel on the left and the value of the pixel above the current pixel;
-- there is one code in the bitstream that specifies the value of a pixel
-  directly (in 4-bit resolution);
-- pixel values need to be clamped inside the range [0..255] for proper
-  decoding.
-
-The algorithm purely describes the conversion from compressed Bayer code used
-in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional
-steps are required to convert this to a color image (i.e. a color interpolation
-algorithm).
-
-The following Huffman codes have been found:
-0: +0 (relative to reference pixel value)
-100: +4
-101: -4?
-1110xxxx: set absolute value to xxxx.0000
-1101: +11
-1111: -11
-11001: +20
-110000: -20
-110001: ??? - these codes are apparently not used
-
-[1] The Huffman compression algorithm has been reverse-engineered and
-    documented by Bertrik Sikken.
-
-
-12. Contact information
-=======================
-The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
-
-GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
-'FCE635A4'; the public 1024-bit key should be available at any keyserver;
-the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
-
-
-13. Credits
-===========
-Many thanks to following persons for their contribute (listed in alphabetical
-order):
-
-- David Anderson for the donation of a webcam;
-- Luca Capello for the donation of a webcam;
-- Philippe Coval for having helped testing the PAS202BCA image sensor;
-- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
-  donation of a webcam;
-- Dennis Heitmann for the donation of a webcam;
-- Jon Hollstrom for the donation of a webcam;
-- Nick McGill for the donation of a webcam;
-- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
-  image sensor;
-- Stefano Mozzi, who donated 45 EU;
-- Andrew Pearce for the donation of a webcam;
-- John Pullan for the donation of a webcam;
-- Bertrik Sikken, who reverse-engineered and documented the Huffman compression
-  algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and
-  implemented the first decoder;
-- Ronny Standke for the donation of a webcam;
-- Mizuno Takafumi for the donation of a webcam;
-- an "anonymous" donator (who didn't want his name to be revealed) for the
-  donation of a webcam.
-- an anonymous donator for the donation of four webcams and two boards with ten
-  image sensors.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-config SOLO6X10
-	tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
-	depends on PCI && VIDEO_DEV && SND && I2C
-	select FONT_SUPPORT
-	select FONT_8x16
-	select VIDEOBUF2_DMA_SG
-	select VIDEOBUF2_DMA_CONTIG
-	select SND_PCM
-	select FONT_8x16
-	---help---
-	  This driver supports the Bluecherry H.264 and MPEG-4 hardware
-	  compression capture cards and other Softlogic-based ones.
-
-	  Following cards have been tested:
-	  * Bluecherry BC-H16480A (PCIe, 16 port, H.264)
-	  * Bluecherry BC-H04120A (PCIe, 4 port, H.264)
-	  * Bluecherry BC-H04120A-MPCI (Mini-PCI, 4 port, H.264)
-	  * Bluecherry BC-04120A (PCIe, 4 port, MPEG-4)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/Makefile
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
-		solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
-		solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
-
-obj-$(CONFIG_SOLO6X10) += solo6x10.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-core.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-core.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,709 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/ktime.h>
-#include <linux/slab.h>
-
-#include "solo6x10.h"
-#include "solo6x10-tw28.h"
-
-MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
-MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>");
-MODULE_VERSION(SOLO6X10_VERSION);
-MODULE_LICENSE("GPL");
-
-static unsigned video_nr = -1;
-module_param(video_nr, uint, 0644);
-MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
-
-static int full_eeprom; /* default is only top 64B */
-module_param(full_eeprom, uint, 0644);
-MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
-
-
-static void solo_set_time(struct solo_dev *solo_dev)
-{
-	struct timespec ts;
-
-	ktime_get_ts(&ts);
-
-	solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
-	solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
-}
-
-static void solo_timer_sync(struct solo_dev *solo_dev)
-{
-	u32 sec, usec;
-	struct timespec ts;
-	long diff;
-
-	if (solo_dev->type != SOLO_DEV_6110)
-		return;
-
-	if (++solo_dev->time_sync < 60)
-		return;
-
-	solo_dev->time_sync = 0;
-
-	sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
-	usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
-
-	ktime_get_ts(&ts);
-
-	diff = (long)ts.tv_sec - (long)sec;
-	diff = (diff * 1000000)
-		+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
-
-	if (diff > 1000 || diff < -1000) {
-		solo_set_time(solo_dev);
-	} else if (diff) {
-		long usec_lsb = solo_dev->usec_lsb;
-
-		usec_lsb -= diff / 4;
-		if (usec_lsb < 0)
-			usec_lsb = 0;
-		else if (usec_lsb > 255)
-			usec_lsb = 255;
-
-		solo_dev->usec_lsb = usec_lsb;
-		solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
-			       solo_dev->usec_lsb);
-	}
-}
-
-static irqreturn_t solo_isr(int irq, void *data)
-{
-	struct solo_dev *solo_dev = data;
-	u32 status;
-	int i;
-
-	status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
-	if (!status)
-		return IRQ_NONE;
-
-	if (status & ~solo_dev->irq_mask) {
-		solo_reg_write(solo_dev, SOLO_IRQ_STAT,
-			       status & ~solo_dev->irq_mask);
-		status &= solo_dev->irq_mask;
-	}
-
-	if (status & SOLO_IRQ_PCI_ERR)
-		solo_p2m_error_isr(solo_dev);
-
-	for (i = 0; i < SOLO_NR_P2M; i++)
-		if (status & SOLO_IRQ_P2M(i))
-			solo_p2m_isr(solo_dev, i);
-
-	if (status & SOLO_IRQ_IIC)
-		solo_i2c_isr(solo_dev);
-
-	if (status & SOLO_IRQ_VIDEO_IN) {
-		solo_video_in_isr(solo_dev);
-		solo_timer_sync(solo_dev);
-	}
-
-	if (status & SOLO_IRQ_ENCODER)
-		solo_enc_v4l2_isr(solo_dev);
-
-	if (status & SOLO_IRQ_G723)
-		solo_g723_isr(solo_dev);
-
-	/* Clear all interrupts handled */
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
-
-	return IRQ_HANDLED;
-}
-
-static void free_solo_dev(struct solo_dev *solo_dev)
-{
-	struct pci_dev *pdev;
-
-	if (!solo_dev)
-		return;
-
-	if (solo_dev->dev.parent)
-		device_unregister(&solo_dev->dev);
-
-	pdev = solo_dev->pdev;
-
-	/* If we never initialized the PCI device, then nothing else
-	 * below here needs cleanup */
-	if (!pdev) {
-		kfree(solo_dev);
-		return;
-	}
-
-	if (solo_dev->reg_base) {
-		/* Bring down the sub-devices first */
-		solo_g723_exit(solo_dev);
-		solo_enc_v4l2_exit(solo_dev);
-		solo_enc_exit(solo_dev);
-		solo_v4l2_exit(solo_dev);
-		solo_disp_exit(solo_dev);
-		solo_gpio_exit(solo_dev);
-		solo_p2m_exit(solo_dev);
-		solo_i2c_exit(solo_dev);
-
-		/* Now cleanup the PCI device */
-		solo_irq_off(solo_dev, ~0);
-		pci_iounmap(pdev, solo_dev->reg_base);
-		if (pdev->irq)
-			free_irq(pdev->irq, solo_dev);
-	}
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	v4l2_device_unregister(&solo_dev->v4l2_dev);
-	pci_set_drvdata(pdev, NULL);
-
-	kfree(solo_dev);
-}
-
-static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	unsigned short *p = (unsigned short *)buf;
-	int i;
-
-	if (count & 0x1)
-		dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
-
-	if (!full_eeprom && count > 64) {
-		dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
-		count = 64;
-	} else if (full_eeprom && count > 128) {
-		dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
-		count = 128;
-	}
-
-	solo_eeprom_ewen(solo_dev, 1);
-
-	for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
-					       (int)(count / 2)); i++)
-		solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
-
-	solo_eeprom_ewen(solo_dev, 0);
-
-	return count;
-}
-
-static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	unsigned short *p = (unsigned short *)buf;
-	int count = (full_eeprom ? 128 : 64);
-	int i;
-
-	for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
-		p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
-
-	return count;
-}
-
-static ssize_t p2m_timeouts_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-
-	return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
-}
-
-static ssize_t sdram_size_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-
-	return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
-}
-
-static ssize_t tw28xx_show(struct device *dev,
-			   struct device_attribute *attr,
-			   char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-
-	return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
-		       hweight32(solo_dev->tw2815),
-		       hweight32(solo_dev->tw2864),
-		       hweight32(solo_dev->tw2865));
-}
-
-static ssize_t input_map_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	unsigned int val;
-	char *out = buf;
-
-	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
-	out += sprintf(out, "Channel 0   => Input %d\n", val & 0x1f);
-	out += sprintf(out, "Channel 1   => Input %d\n", (val >> 5) & 0x1f);
-	out += sprintf(out, "Channel 2   => Input %d\n", (val >> 10) & 0x1f);
-	out += sprintf(out, "Channel 3   => Input %d\n", (val >> 15) & 0x1f);
-	out += sprintf(out, "Channel 4   => Input %d\n", (val >> 20) & 0x1f);
-	out += sprintf(out, "Channel 5   => Input %d\n", (val >> 25) & 0x1f);
-
-	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
-	out += sprintf(out, "Channel 6   => Input %d\n", val & 0x1f);
-	out += sprintf(out, "Channel 7   => Input %d\n", (val >> 5) & 0x1f);
-	out += sprintf(out, "Channel 8   => Input %d\n", (val >> 10) & 0x1f);
-	out += sprintf(out, "Channel 9   => Input %d\n", (val >> 15) & 0x1f);
-	out += sprintf(out, "Channel 10  => Input %d\n", (val >> 20) & 0x1f);
-	out += sprintf(out, "Channel 11  => Input %d\n", (val >> 25) & 0x1f);
-
-	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
-	out += sprintf(out, "Channel 12  => Input %d\n", val & 0x1f);
-	out += sprintf(out, "Channel 13  => Input %d\n", (val >> 5) & 0x1f);
-	out += sprintf(out, "Channel 14  => Input %d\n", (val >> 10) & 0x1f);
-	out += sprintf(out, "Channel 15  => Input %d\n", (val >> 15) & 0x1f);
-	out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
-
-	return out - buf;
-}
-
-static ssize_t p2m_timeout_store(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	unsigned long ms;
-
-	int ret = kstrtoul(buf, 10, &ms);
-	if (ret < 0 || ms > 200)
-		return -EINVAL;
-	solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
-
-	return count;
-}
-
-static ssize_t p2m_timeout_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-
-	return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
-}
-
-static ssize_t intervals_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	char *out = buf;
-	int fps = solo_dev->fps;
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
-			       i, solo_dev->v4l2_enc[i]->interval, fps,
-			       solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
-	}
-
-	return out - buf;
-}
-
-static ssize_t sdram_offsets_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
-{
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	char *out = buf;
-
-	out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
-		       SOLO_DISP_EXT_ADDR,
-		       SOLO_DISP_EXT_SIZE);
-
-	out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
-		       SOLO_EOSD_EXT_ADDR,
-		       SOLO_EOSD_EXT_AREA(solo_dev),
-		       SOLO_EOSD_EXT_SIZE(solo_dev),
-		       SOLO_EOSD_EXT_AREA(solo_dev) /
-		       SOLO_EOSD_EXT_SIZE(solo_dev));
-
-	out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
-		       SOLO_MOTION_EXT_ADDR(solo_dev),
-		       SOLO_MOTION_EXT_SIZE);
-
-	out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
-		       SOLO_G723_EXT_ADDR(solo_dev),
-		       SOLO_G723_EXT_SIZE);
-
-	out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
-		       SOLO_CAP_EXT_ADDR(solo_dev),
-		       SOLO_CAP_EXT_SIZE(solo_dev),
-		       SOLO_CAP_PAGE_SIZE,
-		       SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
-
-	out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
-		       SOLO_EREF_EXT_ADDR(solo_dev),
-		       SOLO_EREF_EXT_AREA(solo_dev),
-		       SOLO_EREF_EXT_SIZE,
-		       SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
-
-	out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
-		       SOLO_MP4E_EXT_ADDR(solo_dev),
-		       SOLO_MP4E_EXT_SIZE(solo_dev));
-
-	out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
-		       SOLO_JPEG_EXT_ADDR(solo_dev),
-		       SOLO_JPEG_EXT_SIZE(solo_dev));
-
-	return out - buf;
-}
-
-static ssize_t sdram_show(struct file *file, struct kobject *kobj,
-			  struct bin_attribute *a, char *buf,
-			  loff_t off, size_t count)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct solo_dev *solo_dev =
-		container_of(dev, struct solo_dev, dev);
-	const int size = solo_dev->sdram_size;
-
-	if (off >= size)
-		return 0;
-
-	if (off + count > size)
-		count = size - off;
-
-	if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
-		return -EIO;
-
-	return count;
-}
-
-static const struct device_attribute solo_dev_attrs[] = {
-	__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
-	__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
-	__ATTR_RO(p2m_timeouts),
-	__ATTR_RO(sdram_size),
-	__ATTR_RO(tw28xx),
-	__ATTR_RO(input_map),
-	__ATTR_RO(intervals),
-	__ATTR_RO(sdram_offsets),
-};
-
-static void solo_device_release(struct device *dev)
-{
-	/* Do nothing */
-}
-
-static int solo_sysfs_init(struct solo_dev *solo_dev)
-{
-	struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
-	struct device *dev = &solo_dev->dev;
-	const char *driver;
-	int i;
-
-	if (solo_dev->type == SOLO_DEV_6110)
-		driver = "solo6110";
-	else
-		driver = "solo6010";
-
-	dev->release = solo_device_release;
-	dev->parent = &solo_dev->pdev->dev;
-	set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
-	dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
-		     solo_dev->nr_chans);
-
-	if (device_register(dev)) {
-		dev->parent = NULL;
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
-		if (device_create_file(dev, &solo_dev_attrs[i])) {
-			device_unregister(dev);
-			return -ENOMEM;
-		}
-	}
-
-	sysfs_attr_init(&sdram_attr->attr);
-	sdram_attr->attr.name = "sdram";
-	sdram_attr->attr.mode = 0440;
-	sdram_attr->read = sdram_show;
-	sdram_attr->size = solo_dev->sdram_size;
-
-	if (device_create_bin_file(dev, sdram_attr)) {
-		device_unregister(dev);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct solo_dev *solo_dev;
-	int ret;
-	u8 chip_id;
-
-	solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
-	if (solo_dev == NULL)
-		return -ENOMEM;
-
-	if (id->driver_data == SOLO_DEV_6010)
-		dev_info(&pdev->dev, "Probing Softlogic 6010\n");
-	else
-		dev_info(&pdev->dev, "Probing Softlogic 6110\n");
-
-	solo_dev->type = id->driver_data;
-	solo_dev->pdev = pdev;
-	spin_lock_init(&solo_dev->reg_io_lock);
-	ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Only for during init */
-	solo_dev->p2m_jiffies = msecs_to_jiffies(100);
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		goto fail_probe;
-
-	pci_set_master(pdev);
-
-	/* RETRY/TRDY Timeout disabled */
-	pci_write_config_byte(pdev, 0x40, 0x00);
-	pci_write_config_byte(pdev, 0x41, 0x00);
-
-	ret = pci_request_regions(pdev, SOLO6X10_NAME);
-	if (ret)
-		goto fail_probe;
-
-	solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
-	if (solo_dev->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto fail_probe;
-	}
-
-	chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
-				SOLO_CHIP_ID_MASK;
-	switch (chip_id) {
-	case 7:
-		solo_dev->nr_chans = 16;
-		solo_dev->nr_ext = 5;
-		break;
-	case 6:
-		solo_dev->nr_chans = 8;
-		solo_dev->nr_ext = 2;
-		break;
-	default:
-		dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
-			 chip_id);
-	case 5:
-		solo_dev->nr_chans = 4;
-		solo_dev->nr_ext = 1;
-	}
-
-	/* Disable all interrupts to start */
-	solo_irq_off(solo_dev, ~0);
-
-	/* Initial global settings */
-	if (solo_dev->type == SOLO_DEV_6010) {
-		solo_dev->clock_mhz = 108;
-		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
-			| SOLO_SYS_CFG_INPUTDIV(25)
-			| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
-			| SOLO_SYS_CFG_OUTDIV(3);
-		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
-	} else {
-		u32 divq, divf;
-
-		solo_dev->clock_mhz = 135;
-
-		if (solo_dev->clock_mhz < 125) {
-			divq = 3;
-			divf = (solo_dev->clock_mhz * 4) / 3 - 1;
-		} else {
-			divq = 2;
-			divf = (solo_dev->clock_mhz * 2) / 3 - 1;
-		}
-
-		solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
-			       (1 << 20) | /* PLL_RANGE */
-			       (8 << 15) | /* PLL_DIVR  */
-			       (divq << 12) |
-			       (divf <<  4) |
-			       (1 <<  1)   /* PLL_FSEN */);
-
-		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
-	}
-
-	solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
-	solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
-		       solo_dev->clock_mhz - 1);
-
-	/* PLL locking time of 1ms */
-	mdelay(1);
-
-	ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
-			  solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Handle this from the start */
-	solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
-
-	ret = solo_i2c_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Setup the DMA engine */
-	solo_reg_write(solo_dev, SOLO_DMA_CTRL,
-		       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
-		       SOLO_DMA_CTRL_SDRAM_SIZE(2) |
-		       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
-		       SOLO_DMA_CTRL_READ_CLK_SELECT |
-		       SOLO_DMA_CTRL_LATENCY(1));
-
-	/* Undocumented crap */
-	solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
-		       solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
-
-	if (solo_dev->type != SOLO_DEV_6010) {
-		solo_dev->usec_lsb = 0x3f;
-		solo_set_time(solo_dev);
-	}
-
-	/* Disable watchdog */
-	solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
-
-	/* Initialize sub components */
-
-	ret = solo_p2m_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_disp_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_gpio_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_tw28_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_v4l2_init(solo_dev, video_nr);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_enc_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_enc_v4l2_init(solo_dev, video_nr);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_g723_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_sysfs_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Now that init is over, set this lower */
-	solo_dev->p2m_jiffies = msecs_to_jiffies(20);
-
-	return 0;
-
-fail_probe:
-	free_solo_dev(solo_dev);
-	return ret;
-}
-
-static void solo_pci_remove(struct pci_dev *pdev)
-{
-	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
-	struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
-
-	free_solo_dev(solo_dev);
-}
-
-static const struct pci_device_id solo_id_table[] = {
-	/* 6010 based cards */
-	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
-	  .driver_data = SOLO_DEV_6010 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
-	  .driver_data = SOLO_DEV_6010 },
-	/* 6110 based cards */
-	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
-	  .driver_data = SOLO_DEV_6110 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
-	  .driver_data = SOLO_DEV_6110 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
-	  .driver_data = SOLO_DEV_6110 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
-	  .driver_data = SOLO_DEV_6110 },
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, solo_id_table);
-
-static struct pci_driver solo_pci_driver = {
-	.name = SOLO6X10_NAME,
-	.id_table = solo_id_table,
-	.probe = solo_pci_probe,
-	.remove = solo_pci_remove,
-};
-
-module_pci_driver(solo_pci_driver);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-disp.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-disp.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-disp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-disp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ioctl.h>
-
-#include "solo6x10.h"
-
-#define SOLO_VCLK_DELAY			3
-#define SOLO_PROGRESSIVE_VSIZE		1024
-
-#define SOLO_MOT_THRESH_W		64
-#define SOLO_MOT_THRESH_H		64
-#define SOLO_MOT_THRESH_SIZE		8192
-#define SOLO_MOT_THRESH_REAL		(SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
-#define SOLO_MOT_FLAG_SIZE		1024
-#define SOLO_MOT_FLAG_AREA		(SOLO_MOT_FLAG_SIZE * 16)
-
-static void solo_vin_config(struct solo_dev *solo_dev)
-{
-	solo_dev->vin_hstart = 8;
-	solo_dev->vin_vstart = 2;
-
-	solo_reg_write(solo_dev, SOLO_SYS_VCLK,
-		       SOLO_VCLK_SELECT(2) |
-		       SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
-		       SOLO_VI_H_START(solo_dev->vin_hstart) |
-		       SOLO_VI_V_START(solo_dev->vin_vstart) |
-		       SOLO_VI_V_STOP(solo_dev->vin_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
-		       SOLO_VI_H_START(solo_dev->vout_hstart) |
-		       SOLO_VI_V_START(solo_dev->vout_vstart) |
-		       SOLO_VI_V_STOP(solo_dev->vout_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_P,
-		       SOLO_VI_H_START(0) |
-		       SOLO_VI_V_START(1) |
-		       SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
-
-	solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
-		       SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
-
-	/* On 6110, initialize mozaic darkness stength */
-	if (solo_dev->type == SOLO_DEV_6010)
-		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
-	else
-		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
-
-	solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
-			       SOLO_VI_PB_USER_MODE);
-		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
-			       SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
-		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
-			       SOLO_VI_PB_VSTART(4) |
-			       SOLO_VI_PB_VSTOP(4 + 240));
-	} else {
-		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
-			       SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
-		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
-			       SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
-		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
-			       SOLO_VI_PB_VSTART(4) |
-			       SOLO_VI_PB_VSTOP(4 + 288));
-	}
-	solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
-		       SOLO_VI_PB_HSTOP(16 + 720));
-}
-
-static void solo_vout_config_cursor(struct solo_dev *dev)
-{
-	int i;
-
-	/* Load (blank) cursor bitmap mask (2bpp) */
-	for (i = 0; i < 20; i++)
-		solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
-
-	solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
-
-	solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
-		       (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
-	solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
-}
-
-static void solo_vout_config(struct solo_dev *solo_dev)
-{
-	solo_dev->vout_hstart = 6;
-	solo_dev->vout_vstart = 8;
-
-	solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
-		       solo_dev->video_type |
-		       SOLO_VO_USER_COLOR_SET_NAV |
-		       SOLO_VO_USER_COLOR_SET_NAH |
-		       SOLO_VO_NA_COLOR_Y(0) |
-		       SOLO_VO_NA_COLOR_CB(0) |
-		       SOLO_VO_NA_COLOR_CR(0));
-
-	solo_reg_write(solo_dev, SOLO_VO_ACT_H,
-		       SOLO_VO_H_START(solo_dev->vout_hstart) |
-		       SOLO_VO_H_STOP(solo_dev->vout_hstart +
-				      solo_dev->video_hsize));
-
-	solo_reg_write(solo_dev, SOLO_VO_ACT_V,
-		       SOLO_VO_V_START(solo_dev->vout_vstart) |
-		       SOLO_VO_V_STOP(solo_dev->vout_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
-		       SOLO_VO_H_LEN(solo_dev->video_hsize) |
-		       SOLO_VO_V_LEN(solo_dev->video_vsize));
-
-	/* Border & background colors */
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
-		       (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
-		       (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
-	solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
-		       (16 << 24) | (128 << 16) | (16 << 8) | 128);
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
-
-	solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
-	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
-		       SOLO_VO_DISP_ERASE_COUNT(8) |
-		       SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
-
-
-	solo_vout_config_cursor(solo_dev);
-
-	/* Enable channels we support */
-	solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
-		       (1 << solo_dev->nr_chans) - 1);
-}
-
-static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
-			       u16 val, int reg_size)
-{
-	u16 *buf;
-	const int n = 64, size = n * sizeof(*buf);
-	int i, ret = 0;
-
-	buf = kmalloc(size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	for (i = 0; i < n; i++)
-		buf[i] = cpu_to_le16(val);
-
-	for (i = 0; i < reg_size; i += size) {
-		ret = solo_p2m_dma(solo_dev, 1, buf,
-				   SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
-				   size, 0, 0);
-
-		if (ret)
-			break;
-	}
-
-	kfree(buf);
-	return ret;
-}
-
-int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
-{
-	if (ch > solo_dev->nr_chans)
-		return -EINVAL;
-
-	return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
-				   (ch * SOLO_MOT_THRESH_SIZE * 2),
-				   val, SOLO_MOT_THRESH_SIZE);
-}
-
-int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
-		const struct solo_motion_thresholds *thresholds)
-{
-	u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
-	u16 buf[64];
-	int x, y;
-	int ret = 0;
-
-	memset(buf, 0, sizeof(buf));
-	for (y = 0; y < SOLO_MOTION_SZ; y++) {
-		for (x = 0; x < SOLO_MOTION_SZ; x++)
-			buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
-		ret |= solo_p2m_dma(solo_dev, 1, buf,
-			SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
-			sizeof(buf), 0, 0);
-	}
-	return ret;
-}
-
-/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
- * threshold and working table for each channel. Atleast that's what the
- * spec says. However, this code (taken from rdk) has some mystery 8k
- * block right after the flag area, before the first thresh table. */
-static void solo_motion_config(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		/* Clear motion flag area */
-		solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
-				    SOLO_MOT_FLAG_SIZE);
-
-		/* Clear working cache table */
-		solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
-				    (i * SOLO_MOT_THRESH_SIZE * 2) +
-				    SOLO_MOT_THRESH_SIZE, 0x0000,
-				    SOLO_MOT_THRESH_SIZE);
-
-		/* Set default threshold table */
-		solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
-	}
-
-	/* Default motion settings */
-	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
-		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
-	solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
-		       SOLO_VI_MOTION_FRAME_COUNT(3) |
-		       SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
-		       /* | SOLO_VI_MOTION_INTR_START_STOP */
-		       | SOLO_VI_MOTION_SAMPLE_COUNT(10));
-
-	solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
-	solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
-}
-
-int solo_disp_init(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_dev->video_hsize = 704;
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-		solo_dev->video_vsize = 240;
-		solo_dev->fps = 30;
-	} else {
-		solo_dev->video_vsize = 288;
-		solo_dev->fps = 25;
-	}
-
-	solo_vin_config(solo_dev);
-	solo_motion_config(solo_dev);
-	solo_vout_config(solo_dev);
-
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
-
-	return 0;
-}
-
-void solo_disp_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
-	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
-	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
-		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
-		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
-	}
-
-	/* Set default border */
-	for (i = 0; i < 5; i++)
-		solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
-
-	for (i = 0; i < 5; i++)
-		solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-eeprom.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-eeprom.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-eeprom.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-eeprom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include "solo6x10.h"
-
-/* Control */
-#define EE_SHIFT_CLK	0x04
-#define EE_CS		0x08
-#define EE_DATA_WRITE	0x02
-#define EE_DATA_READ	0x01
-#define EE_ENB		(0x80 | EE_CS)
-
-#define eeprom_delay()	udelay(100)
-#if 0
-#define eeprom_delay()	solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
-#define eeprom_delay()	({				\
-	int i, ret;					\
-	udelay(100);					\
-	for (i = ret = 0; i < 1000 && !ret; i++)	\
-		ret = solo_eeprom_reg_read(solo_dev);	\
-})
-#endif
-#define ADDR_LEN	6
-
-/* Commands */
-#define EE_EWEN_CMD	4
-#define EE_EWDS_CMD	4
-#define EE_WRITE_CMD	5
-#define EE_READ_CMD	6
-#define EE_ERASE_CMD	7
-
-static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
-{
-	return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
-}
-
-static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
-{
-	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
-	eeprom_delay();
-}
-
-static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
-{
-	int i;
-
-	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
-	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
-
-	for (i = 4 + ADDR_LEN; i >= 0; i--) {
-		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
-				      EE_SHIFT_CLK | dataval);
-	}
-
-	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
-}
-
-unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
-{
-	int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
-	unsigned int retval = 0;
-	int i;
-
-	solo_eeprom_cmd(solo_dev, ewen_cmd);
-
-	for (i = 0; i < 16; i++) {
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
-				      EE_SHIFT_CLK);
-		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
-		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
-	}
-
-	solo_eeprom_reg_write(solo_dev, ~EE_CS);
-	retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
-
-	return retval;
-}
-
-unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
-{
-	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
-	unsigned short retval = 0;
-	int i;
-
-	solo_eeprom_cmd(solo_dev, read_cmd);
-
-	for (i = 0; i < 16; i++) {
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
-				      EE_SHIFT_CLK);
-		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
-		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
-	}
-
-	solo_eeprom_reg_write(solo_dev, ~EE_CS);
-
-	return retval;
-}
-
-int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
-		      unsigned short data)
-{
-	int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
-	unsigned int retval;
-	int i;
-
-	solo_eeprom_cmd(solo_dev, write_cmd);
-
-	for (i = 15; i >= 0; i--) {
-		unsigned int dataval = (data >> i) & 1;
-
-		solo_eeprom_reg_write(solo_dev, EE_ENB);
-		solo_eeprom_reg_write(solo_dev,
-				      EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
-	}
-
-	solo_eeprom_reg_write(solo_dev, EE_ENB);
-	solo_eeprom_reg_write(solo_dev, ~EE_CS);
-	solo_eeprom_reg_write(solo_dev, EE_ENB);
-
-	for (i = retval = 0; i < 10000 && !retval; i++)
-		retval = solo_eeprom_reg_read(solo_dev);
-
-	solo_eeprom_reg_write(solo_dev, ~EE_CS);
-
-	return !retval;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-enc.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-enc.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-enc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-enc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/font.h>
-#include <linux/bitrev.h>
-#include <linux/slab.h>
-
-#include "solo6x10.h"
-
-#define VI_PROG_HSIZE			(1280 - 16)
-#define VI_PROG_VSIZE			(1024 - 16)
-
-#define IRQ_LEVEL			2
-
-static void solo_capture_config(struct solo_dev *solo_dev)
-{
-	unsigned long height;
-	unsigned long width;
-	void *buf;
-	int i;
-
-	solo_reg_write(solo_dev, SOLO_CAP_BASE,
-		       SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
-					  - SOLO_CAP_PAGE_SIZE) >> 16)
-		       | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
-
-	/* XXX: Undocumented bits at b17 and b24 */
-	if (solo_dev->type == SOLO_DEV_6110) {
-		/* NOTE: Ref driver has (62 << 24) here as well, but it causes
-		 * wacked out frame timing on 4-port 6110. */
-		solo_reg_write(solo_dev, SOLO_CAP_BTW,
-			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
-			       SOLO_CAP_MAX_BANDWIDTH(36));
-	} else {
-		solo_reg_write(solo_dev, SOLO_CAP_BTW,
-			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
-			       SOLO_CAP_MAX_BANDWIDTH(32));
-	}
-
-	/* Set scale 1, 9 dimension */
-	width = solo_dev->video_hsize;
-	height = solo_dev->video_vsize;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 2, 10 dimension */
-	width = solo_dev->video_hsize / 2;
-	height = solo_dev->video_vsize;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 3, 11 dimension */
-	width = solo_dev->video_hsize / 2;
-	height = solo_dev->video_vsize / 2;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 4, 12 dimension */
-	width = solo_dev->video_hsize / 3;
-	height = solo_dev->video_vsize / 3;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 5, 13 dimension */
-	width = solo_dev->video_hsize / 4;
-	height = solo_dev->video_vsize / 2;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Progressive */
-	width = VI_PROG_HSIZE;
-	height = VI_PROG_VSIZE;
-	solo_reg_write(solo_dev, SOLO_DIM_PROG,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Clear OSD */
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
-		       0xF0 << 16 | 0x80 << 8 | 0x80);
-
-	if (solo_dev->type == SOLO_DEV_6010)
-		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
-			       SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
-	else
-		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
-			       | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
-
-	/* Clear OSG buffer */
-	buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
-	if (!buf)
-		return;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_p2m_dma(solo_dev, 1, buf,
-			     SOLO_EOSD_EXT_ADDR +
-			     (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
-			     SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
-	}
-	kfree(buf);
-}
-
-#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
-
-/* Should be called with enable_lock held */
-int solo_osd_print(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	unsigned char *str = solo_enc->osd_text;
-	u8 *buf = solo_enc->osd_buf;
-	u32 reg;
-	const struct font_desc *vga = find_font("VGA8x16");
-	const unsigned char *vga_data;
-	int i, j;
-
-	if (WARN_ON_ONCE(!vga))
-		return -ENODEV;
-
-	reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
-	if (!*str) {
-		/* Disable OSD on this channel */
-		reg &= ~(1 << solo_enc->ch);
-		goto out;
-	}
-
-	memset(buf, 0, SOLO_OSD_WRITE_SIZE);
-	vga_data = (const unsigned char *)vga->data;
-
-	for (i = 0; *str; i++, str++) {
-		for (j = 0; j < 16; j++) {
-			buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
-			    bitrev8(vga_data[(*str << 4) | j]);
-		}
-	}
-
-	solo_p2m_dma(solo_dev, 1, buf,
-		     SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
-		     SOLO_OSD_WRITE_SIZE, 0, 0);
-
-	/* Enable OSD on this channel */
-	reg |= (1 << solo_enc->ch);
-
-out:
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
-	return 0;
-}
-
-/**
- * Set channel Quality Profile (0-3).
- */
-void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
-		    unsigned int qp)
-{
-	unsigned long flags;
-	unsigned int idx, reg;
-
-	if ((ch > 31) || (qp > 3))
-		return;
-
-	if (solo_dev->type == SOLO_DEV_6010)
-		return;
-
-	if (ch < 16) {
-		idx = 0;
-		reg = SOLO_VE_JPEG_QP_CH_L;
-	} else {
-		ch -= 16;
-		idx = 1;
-		reg = SOLO_VE_JPEG_QP_CH_H;
-	}
-	ch *= 2;
-
-	spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
-
-	solo_dev->jpeg_qp[idx] &= ~(3 << ch);
-	solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
-
-	solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
-
-	spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
-}
-
-int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
-{
-	int idx;
-
-	if (solo_dev->type == SOLO_DEV_6010)
-		return 2;
-
-	if (WARN_ON_ONCE(ch > 31))
-		return 2;
-
-	if (ch < 16) {
-		idx = 0;
-	} else {
-		ch -= 16;
-		idx = 1;
-	}
-	ch *= 2;
-
-	return (solo_dev->jpeg_qp[idx] >> ch) & 3;
-}
-
-#define SOLO_QP_INIT 0xaaaaaaaa
-
-static void solo_jpeg_config(struct solo_dev *solo_dev)
-{
-	if (solo_dev->type == SOLO_DEV_6010) {
-		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
-			       (2 << 24) | (2 << 16) | (2 << 8) | 2);
-	} else {
-		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
-			       (4 << 24) | (3 << 16) | (2 << 8) | 1);
-	}
-
-	spin_lock_init(&solo_dev->jpeg_qp_lock);
-
-	/* Initialize Quality Profile for all channels */
-	solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
-
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
-		(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
-		((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
-	if (solo_dev->type == SOLO_DEV_6110) {
-		solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
-			       (0 << 16) | (30 << 8) | 60);
-	}
-}
-
-static void solo_mp4e_config(struct solo_dev *solo_dev)
-{
-	int i;
-	u32 cfg;
-
-	solo_reg_write(solo_dev, SOLO_VE_CFG0,
-		       SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
-		       SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
-		       SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
-
-
-	cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
-		| SOLO_VE_MOTION_MODE(0);
-	if (solo_dev->type != SOLO_DEV_6010) {
-		cfg |= SOLO_VE_MPEG_SIZE_H(
-			(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
-		cfg |= SOLO_VE_JPEG_SIZE_H(
-			(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
-	}
-	solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
-
-	solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
-	if (solo_dev->type == SOLO_DEV_6110)
-		solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
-	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
-
-	solo_reg_write(solo_dev, SOLO_VE_ATTR,
-		       SOLO_VE_LITTLE_ENDIAN |
-		       SOLO_COMP_ATTR_FCODE(1) |
-		       SOLO_COMP_TIME_INC(0) |
-		       SOLO_COMP_TIME_WIDTH(15) |
-		       SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
-			       (SOLO_EREF_EXT_ADDR(solo_dev) +
-			       (i * SOLO_EREF_EXT_SIZE)) >> 16);
-		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
-			       (SOLO_EREF_EXT_ADDR(solo_dev) +
-			       ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
-	}
-
-	if (solo_dev->type == SOLO_DEV_6110) {
-		solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
-	} else {
-		for (i = 0; i < solo_dev->nr_chans; i++)
-			solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
-	}
-}
-
-int solo_enc_init(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_capture_config(solo_dev);
-	solo_mp4e_config(solo_dev);
-	solo_jpeg_config(solo_dev);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
-	}
-
-	return 0;
-}
-
-void solo_enc_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-g723.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-g723.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-g723.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-g723.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/mempool.h>
-#include <linux/poll.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/control.h>
-
-#include "solo6x10.h"
-#include "solo6x10-tw28.h"
-
-#define G723_FDMA_PAGES		32
-#define G723_PERIOD_BYTES	48
-#define G723_PERIOD_BLOCK	1024
-#define G723_FRAMES_PER_PAGE	48
-
-/* Sets up channels 16-19 for decoding and 0-15 for encoding */
-#define OUTMODE_MASK		0x300
-
-#define SAMPLERATE		8000
-#define BITRATE			25
-
-/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
- * is broken down to 20 * 48 byte regions (one for each channel possible)
- * with the rest of the page being dummy data. */
-#define G723_MAX_BUFFER		(G723_PERIOD_BYTES * PERIODS_MAX)
-#define G723_INTR_ORDER		4 /* 0 - 4 */
-#define PERIODS_MIN		(1 << G723_INTR_ORDER)
-#define PERIODS_MAX		G723_FDMA_PAGES
-
-struct solo_snd_pcm {
-	int				on;
-	spinlock_t			lock;
-	struct solo_dev		*solo_dev;
-	unsigned char			*g723_buf;
-	dma_addr_t			g723_dma;
-};
-
-static void solo_g723_config(struct solo_dev *solo_dev)
-{
-	int clk_div;
-
-	clk_div = (solo_dev->clock_mhz * 1000000)
-		/ (SAMPLERATE * (BITRATE * 2) * 2);
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
-		       SOLO_AUDIO_BITRATE(BITRATE)
-		       | SOLO_AUDIO_CLK_DIV(clk_div));
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
-		       SOLO_AUDIO_FDMA_INTERVAL(1)
-		       | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER)
-		       | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
-		       SOLO_AUDIO_ENABLE
-		       | SOLO_AUDIO_I2S_MODE
-		       | SOLO_AUDIO_I2S_MULTI(3)
-		       | SOLO_AUDIO_MODE(OUTMODE_MASK));
-}
-
-void solo_g723_isr(struct solo_dev *solo_dev)
-{
-	struct snd_pcm_str *pstr =
-		&solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
-	struct snd_pcm_substream *ss;
-	struct solo_snd_pcm *solo_pcm;
-
-	for (ss = pstr->substream; ss != NULL; ss = ss->next) {
-		if (snd_pcm_substream_chip(ss) == NULL)
-			continue;
-
-		/* This means open() hasn't been called on this one */
-		if (snd_pcm_substream_chip(ss) == solo_dev)
-			continue;
-
-		/* Haven't triggered a start yet */
-		solo_pcm = snd_pcm_substream_chip(ss);
-		if (!solo_pcm->on)
-			continue;
-
-		snd_pcm_period_elapsed(ss);
-	}
-}
-
-static int snd_solo_hw_params(struct snd_pcm_substream *ss,
-			      struct snd_pcm_hw_params *hw_params)
-{
-	return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
-}
-
-static int snd_solo_hw_free(struct snd_pcm_substream *ss)
-{
-	return snd_pcm_lib_free_pages(ss);
-}
-
-static const struct snd_pcm_hardware snd_solo_pcm_hw = {
-	.info			= (SNDRV_PCM_INFO_MMAP |
-				   SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP_VALID),
-	.formats		= SNDRV_PCM_FMTBIT_U8,
-	.rates			= SNDRV_PCM_RATE_8000,
-	.rate_min		= SAMPLERATE,
-	.rate_max		= SAMPLERATE,
-	.channels_min		= 1,
-	.channels_max		= 1,
-	.buffer_bytes_max	= G723_MAX_BUFFER,
-	.period_bytes_min	= G723_PERIOD_BYTES,
-	.period_bytes_max	= G723_PERIOD_BYTES,
-	.periods_min		= PERIODS_MIN,
-	.periods_max		= PERIODS_MAX,
-};
-
-static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
-{
-	struct solo_dev *solo_dev = snd_pcm_substream_chip(ss);
-	struct solo_snd_pcm *solo_pcm;
-
-	solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
-	if (solo_pcm == NULL)
-		goto oom;
-
-	solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev,
-						  G723_PERIOD_BYTES,
-						  &solo_pcm->g723_dma);
-	if (solo_pcm->g723_buf == NULL)
-		goto oom;
-
-	spin_lock_init(&solo_pcm->lock);
-	solo_pcm->solo_dev = solo_dev;
-	ss->runtime->hw = snd_solo_pcm_hw;
-
-	snd_pcm_substream_chip(ss) = solo_pcm;
-
-	return 0;
-
-oom:
-	kfree(solo_pcm);
-	return -ENOMEM;
-}
-
-static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-
-	snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
-	pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES,
-			    solo_pcm->g723_buf, solo_pcm->g723_dma);
-	kfree(solo_pcm);
-
-	return 0;
-}
-
-static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	int ret = 0;
-
-	spin_lock(&solo_pcm->lock);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (solo_pcm->on == 0) {
-			/* If this is the first user, switch on interrupts */
-			if (atomic_inc_return(&solo_dev->snd_users) == 1)
-				solo_irq_on(solo_dev, SOLO_IRQ_G723);
-			solo_pcm->on = 1;
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (solo_pcm->on) {
-			/* If this was our last user, switch them off */
-			if (atomic_dec_return(&solo_dev->snd_users) == 0)
-				solo_irq_off(solo_dev, SOLO_IRQ_G723);
-			solo_pcm->on = 0;
-		}
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock(&solo_pcm->lock);
-
-	return ret;
-}
-
-static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
-{
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f;
-
-	return idx * G723_FRAMES_PER_PAGE;
-}
-
-static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
-			     snd_pcm_uframes_t pos, void __user *dst,
-			     snd_pcm_uframes_t count)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	int err, i;
-
-	for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
-		int page = (pos / G723_FRAMES_PER_PAGE) + i;
-
-		err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
-				     SOLO_G723_EXT_ADDR(solo_dev) +
-				     (page * G723_PERIOD_BLOCK) +
-				     (ss->number * G723_PERIOD_BYTES),
-				     G723_PERIOD_BYTES, 0, 0);
-		if (err)
-			return err;
-
-		err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
-				   solo_pcm->g723_buf, G723_PERIOD_BYTES);
-
-		if (err)
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static struct snd_pcm_ops snd_solo_pcm_ops = {
-	.open = snd_solo_pcm_open,
-	.close = snd_solo_pcm_close,
-	.ioctl = snd_pcm_lib_ioctl,
-	.hw_params = snd_solo_hw_params,
-	.hw_free = snd_solo_hw_free,
-	.prepare = snd_solo_pcm_prepare,
-	.trigger = snd_solo_pcm_trigger,
-	.pointer = snd_solo_pcm_pointer,
-	.copy = snd_solo_pcm_copy,
-};
-
-static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_info *info)
-{
-	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	info->count = 1;
-	info->value.integer.min = 0;
-	info->value.integer.max = 15;
-	info->value.integer.step = 1;
-
-	return 0;
-}
-
-static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
-{
-	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
-	u8 ch = value->id.numid - 1;
-
-	value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);
-
-	return 0;
-}
-
-static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
-{
-	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
-	u8 ch = value->id.numid - 1;
-	u8 old_val;
-
-	old_val = tw28_get_audio_gain(solo_dev, ch);
-	if (old_val == value->value.integer.value[0])
-		return 0;
-
-	tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);
-
-	return 1;
-}
-
-static struct snd_kcontrol_new snd_solo_capture_volume = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Capture Volume",
-	.info = snd_solo_capture_volume_info,
-	.get = snd_solo_capture_volume_get,
-	.put = snd_solo_capture_volume_put,
-};
-
-static int solo_snd_pcm_init(struct solo_dev *solo_dev)
-{
-	struct snd_card *card = solo_dev->snd_card;
-	struct snd_pcm *pcm;
-	struct snd_pcm_substream *ss;
-	int ret;
-	int i;
-
-	ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans,
-			  &pcm);
-	if (ret < 0)
-		return ret;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-			&snd_solo_pcm_ops);
-
-	snd_pcm_chip(pcm) = solo_dev;
-	pcm->info_flags = 0;
-	strcpy(pcm->name, card->shortname);
-
-	for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-	     ss; ss = ss->next, i++)
-		sprintf(ss->name, "Camera #%d Audio", i);
-
-	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
-					SNDRV_DMA_TYPE_CONTINUOUS,
-					snd_dma_continuous_data(GFP_KERNEL),
-					G723_MAX_BUFFER, G723_MAX_BUFFER);
-	if (ret < 0)
-		return ret;
-
-	solo_dev->snd_pcm = pcm;
-
-	return 0;
-}
-
-int solo_g723_init(struct solo_dev *solo_dev)
-{
-	static struct snd_device_ops ops = { NULL };
-	struct snd_card *card;
-	struct snd_kcontrol_new kctl;
-	char name[32];
-	int ret;
-
-	atomic_set(&solo_dev->snd_users, 0);
-
-	/* Allows for easier mapping between video and audio */
-	sprintf(name, "Softlogic%d", solo_dev->vfd->num);
-
-	ret = snd_card_new(&solo_dev->pdev->dev,
-			   SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
-			   &solo_dev->snd_card);
-	if (ret < 0)
-		return ret;
-
-	card = solo_dev->snd_card;
-
-	strcpy(card->driver, SOLO6X10_NAME);
-	strcpy(card->shortname, "SOLO-6x10 Audio");
-	sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
-		pci_name(solo_dev->pdev), solo_dev->pdev->irq);
-
-	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
-	if (ret < 0)
-		goto snd_error;
-
-	/* Mixer controls */
-	strcpy(card->mixername, "SOLO-6x10");
-	kctl = snd_solo_capture_volume;
-	kctl.count = solo_dev->nr_chans;
-
-	ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
-	if (ret < 0)
-		return ret;
-
-	ret = solo_snd_pcm_init(solo_dev);
-	if (ret < 0)
-		goto snd_error;
-
-	ret = snd_card_register(card);
-	if (ret < 0)
-		goto snd_error;
-
-	solo_g723_config(solo_dev);
-
-	dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name);
-
-	return 0;
-
-snd_error:
-	snd_card_free(card);
-	return ret;
-}
-
-void solo_g723_exit(struct solo_dev *solo_dev)
-{
-	if (!solo_dev->snd_card)
-		return;
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
-	solo_irq_off(solo_dev, SOLO_IRQ_G723);
-
-	snd_card_free(solo_dev->snd_card);
-	solo_dev->snd_card = NULL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-gpio.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-gpio.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-gpio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-
-#include "solo6x10.h"
-
-static void solo_gpio_mode(struct solo_dev *solo_dev,
-			   unsigned int port_mask, unsigned int mode)
-{
-	int port;
-	unsigned int ret;
-
-	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
-
-	/* To set gpio */
-	for (port = 0; port < 16; port++) {
-		if (!((1 << port) & port_mask))
-			continue;
-
-		ret &= (~(3 << (port << 1)));
-		ret |= ((mode & 3) << (port << 1));
-	}
-
-	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
-
-	/* To set extended gpio - sensor */
-	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
-
-	for (port = 0; port < 16; port++) {
-		if (!((1 << (port + 16)) & port_mask))
-			continue;
-
-		if (!mode)
-			ret &= ~(1 << port);
-		else
-			ret |= 1 << port;
-	}
-
-	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
-}
-
-static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
-{
-	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
-		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
-}
-
-static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
-{
-	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
-		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
-}
-
-static void solo_gpio_config(struct solo_dev *solo_dev)
-{
-	/* Video reset */
-	solo_gpio_mode(solo_dev, 0x30, 1);
-	solo_gpio_clear(solo_dev, 0x30);
-	udelay(100);
-	solo_gpio_set(solo_dev, 0x30);
-	udelay(100);
-
-	/* Warning: Don't touch the next line unless you're sure of what
-	 * you're doing: first four gpio [0-3] are used for video. */
-	solo_gpio_mode(solo_dev, 0x0f, 2);
-
-	/* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */
-	solo_gpio_mode(solo_dev, 0xff00, 1);
-
-	/* Initially set relay status to 0 */
-	solo_gpio_clear(solo_dev, 0xff00);
-}
-
-int solo_gpio_init(struct solo_dev *solo_dev)
-{
-	solo_gpio_config(solo_dev);
-	return 0;
-}
-
-void solo_gpio_exit(struct solo_dev *solo_dev)
-{
-	solo_gpio_clear(solo_dev, 0x30);
-	solo_gpio_config(solo_dev);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10.h linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10.h
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,426 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_H
-#define __SOLO6X10_H
-
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/stringify.h>
-#include <linux/io.h>
-#include <linux/atomic.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-dev.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
-
-#include "solo6x10-regs.h"
-
-#ifndef PCI_VENDOR_ID_SOFTLOGIC
-#define PCI_VENDOR_ID_SOFTLOGIC		0x9413
-#define PCI_DEVICE_ID_SOLO6010		0x6010
-#define PCI_DEVICE_ID_SOLO6110		0x6110
-#endif
-
-#ifndef PCI_VENDOR_ID_BLUECHERRY
-#define PCI_VENDOR_ID_BLUECHERRY	0x1BB3
-/* Neugent Softlogic 6010 based cards */
-#define PCI_DEVICE_ID_NEUSOLO_4		0x4304
-#define PCI_DEVICE_ID_NEUSOLO_9		0x4309
-#define PCI_DEVICE_ID_NEUSOLO_16	0x4310
-/* Bluecherry Softlogic 6010 based cards */
-#define PCI_DEVICE_ID_BC_SOLO_4		0x4E04
-#define PCI_DEVICE_ID_BC_SOLO_9		0x4E09
-#define PCI_DEVICE_ID_BC_SOLO_16	0x4E10
-/* Bluecherry Softlogic 6110 based cards */
-#define PCI_DEVICE_ID_BC_6110_4		0x5304
-#define PCI_DEVICE_ID_BC_6110_8		0x5308
-#define PCI_DEVICE_ID_BC_6110_16	0x5310
-#endif /* Bluecherry */
-
-/* Used in pci_device_id, and solo_dev->type */
-#define SOLO_DEV_6010			0
-#define SOLO_DEV_6110			1
-
-#define SOLO6X10_NAME			"solo6x10"
-
-#define SOLO_MAX_CHANNELS		16
-
-#define SOLO6X10_VERSION		"3.0.0"
-
-/*
- * The SOLO6x10 actually has 8 i2c channels, but we only use 2.
- * 0 - Techwell chip(s)
- * 1 - SAA7128
- */
-#define SOLO_I2C_ADAPTERS		2
-#define SOLO_I2C_TW			0
-#define SOLO_I2C_SAA			1
-
-/* DMA Engine setup */
-#define SOLO_NR_P2M			4
-#define SOLO_NR_P2M_DESC		256
-#define SOLO_P2M_DESC_SIZE		(SOLO_NR_P2M_DESC * 16)
-
-/* Encoder standard modes */
-#define SOLO_ENC_MODE_CIF		2
-#define SOLO_ENC_MODE_HD1		1
-#define SOLO_ENC_MODE_D1		9
-
-#define SOLO_DEFAULT_QP			3
-
-#ifndef V4L2_BUF_FLAG_MOTION_ON
-#define V4L2_BUF_FLAG_MOTION_ON		0x10000
-#define V4L2_BUF_FLAG_MOTION_DETECTED	0x20000
-#endif
-
-#define SOLO_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
-#define V4L2_CID_MOTION_MODE		(SOLO_CID_CUSTOM_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD	(SOLO_CID_CUSTOM_BASE+1)
-#define V4L2_CID_MOTION_TRACE		(SOLO_CID_CUSTOM_BASE+2)
-#define V4L2_CID_OSD_TEXT		(SOLO_CID_CUSTOM_BASE+3)
-
-/*
- * Motion thresholds are in a table of 64x64 samples, with
- * each sample representing 16x16 pixels of the source. In
- * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
- * The 5th sample on the 10th row is (10*64)+5 = 645.
- *
- * Using a 64x64 array will result in a problem on some architectures like
- * the powerpc where the size of the argument is limited to 13 bits.
- * Since both PAL and NTSC do not use the full table anyway I've chosen
- * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC
- * width).
- */
-#define SOLO_MOTION_SZ (45)
-struct solo_motion_thresholds {
-	__u16	thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
-};
-
-#define SOLO_IOC_G_MOTION_THRESHOLDS	_IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
-#define SOLO_IOC_S_MOTION_THRESHOLDS	_IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
-
-enum SOLO_I2C_STATE {
-	IIC_STATE_IDLE,
-	IIC_STATE_START,
-	IIC_STATE_READ,
-	IIC_STATE_WRITE,
-	IIC_STATE_STOP
-};
-
-/* Defined in Table 4-16, Page 68-69 of the 6010 Datasheet */
-struct solo_p2m_desc {
-	u32	ctrl;
-	u32	cfg;
-	u32	dma_addr;
-	u32	ext_addr;
-};
-
-struct solo_p2m_dev {
-	struct mutex		mutex;
-	struct completion	completion;
-	int			desc_count;
-	int			desc_idx;
-	struct solo_p2m_desc	*descs;
-	int			error;
-};
-
-#define OSD_TEXT_MAX		44
-
-struct solo_vb2_buf {
-	struct vb2_buffer vb;
-	struct list_head list;
-};
-
-enum solo_enc_types {
-	SOLO_ENC_TYPE_STD,
-	SOLO_ENC_TYPE_EXT,
-};
-
-struct solo_enc_dev {
-	struct solo_dev	*solo_dev;
-	/* V4L2 Items */
-	struct v4l2_ctrl_handler hdl;
-	struct video_device	*vfd;
-	/* General accounting */
-	struct mutex		lock;
-	spinlock_t		motion_lock;
-	u8			ch;
-	u8			mode, gop, qp, interlaced, interval;
-	u8			bw_weight;
-	u16			motion_thresh;
-	struct solo_motion_thresholds motion_thresholds;
-	bool			motion_global;
-	bool			motion_enabled;
-	u16			width;
-	u16			height;
-
-	/* OSD buffers */
-	char			osd_text[OSD_TEXT_MAX + 1];
-	u8			osd_buf[SOLO_EOSD_EXT_SIZE_MAX]
-					__aligned(4);
-
-	/* VOP stuff */
-	unsigned char		vop[64];
-	int			vop_len;
-	unsigned char		jpeg_header[1024];
-	int			jpeg_len;
-
-	u32			fmt;
-	enum solo_enc_types	type;
-	u32			sequence;
-	struct vb2_queue	vidq;
-	struct list_head	vidq_active;
-	int			desc_count;
-	int			desc_nelts;
-	struct solo_p2m_desc	*desc_items;
-	dma_addr_t		desc_dma;
-	spinlock_t		av_lock;
-};
-
-/* The SOLO6x10 PCI Device */
-struct solo_dev {
-	/* General stuff */
-	struct pci_dev		*pdev;
-	int			type;
-	unsigned int		time_sync;
-	unsigned int		usec_lsb;
-	unsigned int		clock_mhz;
-	u8 __iomem		*reg_base;
-	int			nr_chans;
-	int			nr_ext;
-	u32			irq_mask;
-	u32			motion_mask;
-	spinlock_t		reg_io_lock;
-	struct v4l2_device	v4l2_dev;
-
-	/* tw28xx accounting */
-	u8			tw2865, tw2864, tw2815;
-	u8			tw28_cnt;
-
-	/* i2c related items */
-	struct i2c_adapter	i2c_adap[SOLO_I2C_ADAPTERS];
-	enum SOLO_I2C_STATE	i2c_state;
-	struct mutex		i2c_mutex;
-	int			i2c_id;
-	wait_queue_head_t	i2c_wait;
-	struct i2c_msg		*i2c_msg;
-	unsigned int		i2c_msg_num;
-	unsigned int		i2c_msg_ptr;
-
-	/* P2M DMA Engine */
-	struct solo_p2m_dev	p2m_dev[SOLO_NR_P2M];
-	atomic_t		p2m_count;
-	int			p2m_jiffies;
-	unsigned int		p2m_timeouts;
-
-	/* V4L2 Display items */
-	struct video_device	*vfd;
-	unsigned int		erasing;
-	unsigned int		frame_blank;
-	u8			cur_disp_ch;
-	wait_queue_head_t	disp_thread_wait;
-	struct v4l2_ctrl_handler disp_hdl;
-
-	/* V4L2 Encoder items */
-	struct solo_enc_dev	*v4l2_enc[SOLO_MAX_CHANNELS];
-	u16			enc_bw_remain;
-	/* IDX into hw mp4 encoder */
-	u8			enc_idx;
-
-	/* Current video settings */
-	u32			video_type;
-	u16			video_hsize, video_vsize;
-	u16			vout_hstart, vout_vstart;
-	u16			vin_hstart, vin_vstart;
-	u8			fps;
-
-	/* JPEG Qp setting */
-	spinlock_t      jpeg_qp_lock;
-	u32		jpeg_qp[2];
-
-	/* Audio components */
-	struct snd_card		*snd_card;
-	struct snd_pcm		*snd_pcm;
-	atomic_t		snd_users;
-	int			g723_hw_idx;
-
-	/* sysfs stuffs */
-	struct device		dev;
-	int			sdram_size;
-	struct bin_attribute	sdram_attr;
-	unsigned int		sys_config;
-
-	/* Ring thread */
-	struct task_struct	*ring_thread;
-	wait_queue_head_t	ring_thread_wait;
-
-	/* VOP_HEADER handling */
-	void                    *vh_buf;
-	dma_addr_t		vh_dma;
-	int			vh_size;
-
-	/* Buffer handling */
-	struct vb2_queue	vidq;
-	struct vb2_alloc_ctx	*alloc_ctx;
-	u32			sequence;
-	struct task_struct      *kthread;
-	struct mutex		lock;
-	spinlock_t		slock;
-	int			old_write;
-	struct list_head	vidq_active;
-};
-
-static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
-{
-	unsigned long flags;
-	u32 ret;
-	u16 val;
-
-	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
-	ret = readl(solo_dev->reg_base + reg);
-	rmb();
-	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
-	rmb();
-
-	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
-
-	return ret;
-}
-
-static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
-				  u32 data)
-{
-	unsigned long flags;
-	u16 val;
-
-	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
-	writel(data, solo_dev->reg_base + reg);
-	wmb();
-	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
-	rmb();
-
-	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
-}
-
-static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
-{
-	dev->irq_mask |= mask;
-	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
-}
-
-static inline void solo_irq_off(struct solo_dev *dev, u32 mask)
-{
-	dev->irq_mask &= ~mask;
-	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
-}
-
-/* Init/exit routines for subsystems */
-int solo_disp_init(struct solo_dev *solo_dev);
-void solo_disp_exit(struct solo_dev *solo_dev);
-
-int solo_gpio_init(struct solo_dev *solo_dev);
-void solo_gpio_exit(struct solo_dev *solo_dev);
-
-int solo_i2c_init(struct solo_dev *solo_dev);
-void solo_i2c_exit(struct solo_dev *solo_dev);
-
-int solo_p2m_init(struct solo_dev *solo_dev);
-void solo_p2m_exit(struct solo_dev *solo_dev);
-
-int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
-void solo_v4l2_exit(struct solo_dev *solo_dev);
-
-int solo_enc_init(struct solo_dev *solo_dev);
-void solo_enc_exit(struct solo_dev *solo_dev);
-
-int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
-void solo_enc_v4l2_exit(struct solo_dev *solo_dev);
-
-int solo_g723_init(struct solo_dev *solo_dev);
-void solo_g723_exit(struct solo_dev *solo_dev);
-
-/* ISR's */
-int solo_i2c_isr(struct solo_dev *solo_dev);
-void solo_p2m_isr(struct solo_dev *solo_dev, int id);
-void solo_p2m_error_isr(struct solo_dev *solo_dev);
-void solo_enc_v4l2_isr(struct solo_dev *solo_dev);
-void solo_g723_isr(struct solo_dev *solo_dev);
-void solo_motion_isr(struct solo_dev *solo_dev);
-void solo_video_in_isr(struct solo_dev *solo_dev);
-
-/* i2c read/write */
-u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off);
-void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off,
-			u8 data);
-
-/* P2M DMA */
-int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
-		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
-		   int repeat, u32 ext_size);
-int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
-		 void *sys_addr, u32 ext_addr, u32 size,
-		 int repeat, u32 ext_size);
-void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
-			dma_addr_t dma_addr, u32 ext_addr, u32 size,
-			int repeat, u32 ext_size);
-int solo_p2m_dma_desc(struct solo_dev *solo_dev,
-		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
-		      int desc_cnt);
-
-/* Global s_std ioctl */
-int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz);
-void solo_update_mode(struct solo_enc_dev *solo_enc);
-
-/* Set the threshold for motion detection */
-int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
-int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
-		const struct solo_motion_thresholds *thresholds);
-#define SOLO_DEF_MOT_THRESH		0x0300
-
-/* Write text on OSD */
-int solo_osd_print(struct solo_enc_dev *solo_enc);
-
-/* EEPROM commands */
-unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en);
-unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc);
-int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
-		      unsigned short data);
-
-/* JPEG Qp functions */
-void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
-		    unsigned int qp);
-int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch);
-
-#define CHK_FLAGS(v, flags) (((v) & (flags)) == (flags))
-
-#endif /* __SOLO6X10_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-i2c.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-i2c.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-i2c.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-i2c.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
- * channel. The bus can only handle one i2c event at a time. The below handles
- * this all wrong. We should be using the status registers to see if the bus
- * is in use, and have a global lock to check the status register. Also,
- * the bulk of the work should be handled out-of-interrupt. The ugly loops
- * that occur during interrupt scare me. The ISR should merely signal
- * thread context, ACK the interrupt, and move on. -- BenC */
-
-#include <linux/kernel.h>
-
-#include "solo6x10.h"
-
-u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
-{
-	struct i2c_msg msgs[2];
-	u8 data;
-
-	msgs[0].flags = 0;
-	msgs[0].addr = addr;
-	msgs[0].len = 1;
-	msgs[0].buf = &off;
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr = addr;
-	msgs[1].len = 1;
-	msgs[1].buf = &data;
-
-	i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);
-
-	return data;
-}
-
-void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr,
-			u8 off, u8 data)
-{
-	struct i2c_msg msgs;
-	u8 buf[2];
-
-	buf[0] = off;
-	buf[1] = data;
-	msgs.flags = 0;
-	msgs.addr = addr;
-	msgs.len = 2;
-	msgs.buf = buf;
-
-	i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1);
-}
-
-static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
-{
-	u32 ctrl;
-
-	ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);
-
-	if (solo_dev->i2c_state == IIC_STATE_START)
-		ctrl |= SOLO_IIC_START;
-
-	if (wr) {
-		ctrl |= SOLO_IIC_WRITE;
-	} else {
-		ctrl |= SOLO_IIC_READ;
-		if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
-			ctrl |= SOLO_IIC_ACK_EN;
-	}
-
-	if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
-		ctrl |= SOLO_IIC_STOP;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
-}
-
-static void solo_i2c_start(struct solo_dev *solo_dev)
-{
-	u32 addr = solo_dev->i2c_msg->addr << 1;
-
-	if (solo_dev->i2c_msg->flags & I2C_M_RD)
-		addr |= 1;
-
-	solo_dev->i2c_state = IIC_STATE_START;
-	solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
-	solo_i2c_flush(solo_dev, 1);
-}
-
-static void solo_i2c_stop(struct solo_dev *solo_dev)
-{
-	solo_irq_off(solo_dev, SOLO_IRQ_IIC);
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
-	solo_dev->i2c_state = IIC_STATE_STOP;
-	wake_up(&solo_dev->i2c_wait);
-}
-
-static int solo_i2c_handle_read(struct solo_dev *solo_dev)
-{
-prepare_read:
-	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
-		solo_i2c_flush(solo_dev, 0);
-		return 0;
-	}
-
-	solo_dev->i2c_msg_ptr = 0;
-	solo_dev->i2c_msg++;
-	solo_dev->i2c_msg_num--;
-
-	if (solo_dev->i2c_msg_num == 0) {
-		solo_i2c_stop(solo_dev);
-		return 0;
-	}
-
-	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
-		solo_i2c_start(solo_dev);
-	} else {
-		if (solo_dev->i2c_msg->flags & I2C_M_RD)
-			goto prepare_read;
-		else
-			solo_i2c_stop(solo_dev);
-	}
-
-	return 0;
-}
-
-static int solo_i2c_handle_write(struct solo_dev *solo_dev)
-{
-retry_write:
-	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
-		solo_reg_write(solo_dev, SOLO_IIC_TXD,
-			       solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
-		solo_dev->i2c_msg_ptr++;
-		solo_i2c_flush(solo_dev, 1);
-		return 0;
-	}
-
-	solo_dev->i2c_msg_ptr = 0;
-	solo_dev->i2c_msg++;
-	solo_dev->i2c_msg_num--;
-
-	if (solo_dev->i2c_msg_num == 0) {
-		solo_i2c_stop(solo_dev);
-		return 0;
-	}
-
-	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
-		solo_i2c_start(solo_dev);
-	} else {
-		if (solo_dev->i2c_msg->flags & I2C_M_RD)
-			solo_i2c_stop(solo_dev);
-		else
-			goto retry_write;
-	}
-
-	return 0;
-}
-
-int solo_i2c_isr(struct solo_dev *solo_dev)
-{
-	u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
-	int ret = -EINVAL;
-
-
-	if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR)
-	    || solo_dev->i2c_id < 0) {
-		solo_i2c_stop(solo_dev);
-		return -ENXIO;
-	}
-
-	switch (solo_dev->i2c_state) {
-	case IIC_STATE_START:
-		if (solo_dev->i2c_msg->flags & I2C_M_RD) {
-			solo_dev->i2c_state = IIC_STATE_READ;
-			ret = solo_i2c_handle_read(solo_dev);
-			break;
-		}
-
-		solo_dev->i2c_state = IIC_STATE_WRITE;
-	case IIC_STATE_WRITE:
-		ret = solo_i2c_handle_write(solo_dev);
-		break;
-
-	case IIC_STATE_READ:
-		solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] =
-			solo_reg_read(solo_dev, SOLO_IIC_RXD);
-		solo_dev->i2c_msg_ptr++;
-
-		ret = solo_i2c_handle_read(solo_dev);
-		break;
-
-	default:
-		solo_i2c_stop(solo_dev);
-	}
-
-	return ret;
-}
-
-static int solo_i2c_master_xfer(struct i2c_adapter *adap,
-				struct i2c_msg msgs[], int num)
-{
-	struct solo_dev *solo_dev = adap->algo_data;
-	unsigned long timeout;
-	int ret;
-	int i;
-	DEFINE_WAIT(wait);
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		if (&solo_dev->i2c_adap[i] == adap)
-			break;
-	}
-
-	if (i == SOLO_I2C_ADAPTERS)
-		return num; /* XXX Right return value for failure? */
-
-	mutex_lock(&solo_dev->i2c_mutex);
-	solo_dev->i2c_id = i;
-	solo_dev->i2c_msg = msgs;
-	solo_dev->i2c_msg_num = num;
-	solo_dev->i2c_msg_ptr = 0;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
-	solo_irq_on(solo_dev, SOLO_IRQ_IIC);
-	solo_i2c_start(solo_dev);
-
-	timeout = HZ / 2;
-
-	for (;;) {
-		prepare_to_wait(&solo_dev->i2c_wait, &wait,
-				TASK_INTERRUPTIBLE);
-
-		if (solo_dev->i2c_state == IIC_STATE_STOP)
-			break;
-
-		timeout = schedule_timeout(timeout);
-		if (!timeout)
-			break;
-
-		if (signal_pending(current))
-			break;
-	}
-
-	finish_wait(&solo_dev->i2c_wait, &wait);
-	ret = num - solo_dev->i2c_msg_num;
-	solo_dev->i2c_state = IIC_STATE_IDLE;
-	solo_dev->i2c_id = -1;
-
-	mutex_unlock(&solo_dev->i2c_mutex);
-
-	return ret;
-}
-
-static u32 solo_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
-
-static const struct i2c_algorithm solo_i2c_algo = {
-	.master_xfer	= solo_i2c_master_xfer,
-	.functionality	= solo_i2c_functionality,
-};
-
-int solo_i2c_init(struct solo_dev *solo_dev)
-{
-	int i;
-	int ret;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CFG,
-		       SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);
-
-	solo_dev->i2c_id = -1;
-	solo_dev->i2c_state = IIC_STATE_IDLE;
-	init_waitqueue_head(&solo_dev->i2c_wait);
-	mutex_init(&solo_dev->i2c_mutex);
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
-
-		snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
-			 SOLO6X10_NAME, i);
-		adap->algo = &solo_i2c_algo;
-		adap->algo_data = solo_dev;
-		adap->retries = 1;
-		adap->dev.parent = &solo_dev->pdev->dev;
-
-		ret = i2c_add_adapter(adap);
-		if (ret) {
-			adap->algo_data = NULL;
-			break;
-		}
-	}
-
-	if (ret) {
-		for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-			if (!solo_dev->i2c_adap[i].algo_data)
-				break;
-			i2c_del_adapter(&solo_dev->i2c_adap[i]);
-			solo_dev->i2c_adap[i].algo_data = NULL;
-		}
-		return ret;
-	}
-
-	return 0;
-}
-
-void solo_i2c_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		if (!solo_dev->i2c_adap[i].algo_data)
-			continue;
-		i2c_del_adapter(&solo_dev->i2c_adap[i]);
-		solo_dev->i2c_adap[i].algo_data = NULL;
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-jpeg.h linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-jpeg.h
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-jpeg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-jpeg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_JPEG_H
-#define __SOLO6X10_JPEG_H
-
-static const unsigned char jpeg_header[] = {
-	0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
-	0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
-	0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
-	0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c,
-	0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30,
-	0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50,
-	0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e,
-	0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a,
-	0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4,
-	0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0,
-	0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb,
-	0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a,
-	0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70,
-	0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-	0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00,
-	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
-	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-	0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
-	0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
-	0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
-	0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
-	0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
-	0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
-	0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
-	0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
-	0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
-	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-	0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
-	0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
-	0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
-	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
-	0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
-	0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-	0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
-	0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-	0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
-	0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
-	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
-	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
-	0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
-	0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
-	0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
-	0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
-	0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
-	0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
-	0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
-	0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
-	0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
-	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
-	0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
-	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
-	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
-	0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
-	0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-	0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
-	0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-	0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
-	0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
-	0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
-	0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
-	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
-	0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
-	0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
-	0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
-	0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-};
-
-/* This is the byte marker for the start of SOF0: 0xffc0 marker */
-#define SOF0_START	575
-
-/* This is the byte marker for the start of the DQT */
-#define DQT_START	17
-#define DQT_LEN		138
-const unsigned char jpeg_dqt[4][DQT_LEN] = {
-	{
-		0xff, 0xdb, 0x00, 0x43, 0x00,
-		0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
-		0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
-		0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
-		0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
-		0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
-		0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
-		0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
-		0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32,
-		0xff, 0xdb, 0x00, 0x43, 0x01,
-		0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
-		0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
-		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
-	}, {
-		0xff, 0xdb, 0x00, 0x43, 0x00,
-		0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-		0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-		0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-		0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-		0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-		0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-		0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-		0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-		0xff, 0xdb, 0x00, 0x43, 0x01,
-		0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-		0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-	}, {
-		0xff, 0xdb, 0x00, 0x43, 0x00,
-		0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c,
-		0x1a, 0x1c, 0x24, 0x22, 0x20, 0x26, 0x30, 0x50,
-		0x34, 0x30, 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a,
-		0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66,
-		0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88,
-		0xae, 0x8a, 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae,
-		0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2,
-		0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6,
-		0xff, 0xdb, 0x00, 0x43, 0x01,
-		0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
-		0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6
-	}, {
-		0xff, 0xdb, 0x00, 0x43, 0x00,
-		0x30, 0x21, 0x24, 0x2a, 0x24, 0x1e, 0x30, 0x2a,
-		0x27, 0x2a, 0x36, 0x33, 0x30, 0x39, 0x48, 0x78,
-		0x4e, 0x48, 0x42, 0x42, 0x48, 0x93, 0x69, 0x6f,
-		0x57, 0x78, 0xae, 0x99, 0xb7, 0xb4, 0xab, 0x99,
-		0xa8, 0xa5, 0xc0, 0xd8, 0xff, 0xea, 0xc0, 0xcc,
-		0xff, 0xcf, 0xa5, 0xa8, 0xf0, 0xff, 0xf3, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xe7, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xdb, 0x00, 0x43, 0x01,
-		0x33, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
-		0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-	}
-};
-
-#endif /* __SOLO6X10_JPEG_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-offsets.h linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-offsets.h
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-offsets.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_OFFSETS_H
-#define __SOLO6X10_OFFSETS_H
-
-#define SOLO_DISP_EXT_ADDR			0x00000000
-#define SOLO_DISP_EXT_SIZE			0x00480000
-
-#define SOLO_EOSD_EXT_ADDR \
-	(SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE)
-#define SOLO_EOSD_EXT_SIZE(__solo) \
-	(__solo->type == SOLO_DEV_6010 ? 0x10000 : 0x20000)
-#define SOLO_EOSD_EXT_SIZE_MAX			0x20000
-#define SOLO_EOSD_EXT_AREA(__solo) \
-	(SOLO_EOSD_EXT_SIZE(__solo) * 32)
-#define SOLO_EOSD_EXT_ADDR_CHAN(__solo, ch) \
-	(SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_SIZE(__solo) * (ch))
-
-#define SOLO_MOTION_EXT_ADDR(__solo) \
-	(SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_AREA(__solo))
-#define SOLO_MOTION_EXT_SIZE			0x00080000
-
-#define SOLO_G723_EXT_ADDR(__solo) \
-	(SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE)
-#define SOLO_G723_EXT_SIZE			0x00010000
-
-#define SOLO_CAP_EXT_ADDR(__solo) \
-	(SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE)
-
-/* 18 is the maximum number of pages required for PAL@D1, the largest frame
- * possible */
-#define SOLO_CAP_PAGE_SIZE			(18 << 16)
-
-/* Always allow the encoder enough for 16 channels, even if we have less. The
- * exception is if we have card with only 32Megs of memory. */
-#define SOLO_CAP_EXT_SIZE(__solo) \
-	((((__solo->sdram_size <= (32 << 20)) ? 4 : 16) + 1)	\
-	 * SOLO_CAP_PAGE_SIZE)
-
-#define SOLO_EREF_EXT_ADDR(__solo) \
-	(SOLO_CAP_EXT_ADDR(__solo) + SOLO_CAP_EXT_SIZE(__solo))
-#define SOLO_EREF_EXT_SIZE			0x00140000
-#define SOLO_EREF_EXT_AREA(__solo) \
-	(SOLO_EREF_EXT_SIZE * __solo->nr_chans * 2)
-
-#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
-
-#define SOLO_MP4E_EXT_ADDR(__solo) \
-	(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
-#define SOLO_MP4E_EXT_SIZE(__solo) \
-	max((__solo->nr_chans * 0x00080000),				\
-	    min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) -	\
-		 __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
-
-#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
-#define SOLO_JPEG_EXT_ADDR(__solo) \
-		(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
-#define SOLO_JPEG_EXT_SIZE(__solo) \
-	max(__SOLO_JPEG_MIN_SIZE(__solo),				\
-	    min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
-
-#define SOLO_SDRAM_END(__solo) \
-	(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
-
-#endif /* __SOLO6X10_OFFSETS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-p2m.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-p2m.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-p2m.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-p2m.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "solo6x10.h"
-
-static int multi_p2m;
-module_param(multi_p2m, uint, 0644);
-MODULE_PARM_DESC(multi_p2m,
-		 "Use multiple P2M DMA channels (default: no, 6010-only)");
-
-static int desc_mode;
-module_param(desc_mode, uint, 0644);
-MODULE_PARM_DESC(desc_mode,
-		 "Allow use of descriptor mode DMA (default: no, 6010-only)");
-
-int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
-		 void *sys_addr, u32 ext_addr, u32 size,
-		 int repeat, u32 ext_size)
-{
-	dma_addr_t dma_addr;
-	int ret;
-
-	if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03))
-		return -EINVAL;
-	if (WARN_ON_ONCE(!size))
-		return -EINVAL;
-
-	dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
-				  wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-	if (pci_dma_mapping_error(solo_dev->pdev, dma_addr))
-		return -ENOMEM;
-
-	ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size,
-			     repeat, ext_size);
-
-	pci_unmap_single(solo_dev->pdev, dma_addr, size,
-			 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-	return ret;
-}
-
-/* Mutex must be held for p2m_id before calling this!! */
-int solo_p2m_dma_desc(struct solo_dev *solo_dev,
-		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
-		      int desc_cnt)
-{
-	struct solo_p2m_dev *p2m_dev;
-	unsigned int timeout;
-	unsigned int config = 0;
-	int ret = 0;
-	int p2m_id = 0;
-
-	/* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
-	if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) {
-		p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
-		if (p2m_id < 0)
-			p2m_id = -p2m_id;
-	}
-
-	p2m_dev = &solo_dev->p2m_dev[p2m_id];
-
-	if (mutex_lock_interruptible(&p2m_dev->mutex))
-		return -EINTR;
-
-	reinit_completion(&p2m_dev->completion);
-	p2m_dev->error = 0;
-
-	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) {
-		/* For 6010 with more than one desc, we can do a one-shot */
-		p2m_dev->desc_count = p2m_dev->desc_idx = 0;
-		config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));
-
-		solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
-		solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
-		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
-			       SOLO_P2M_DESC_MODE);
-	} else {
-		/* For single descriptors and 6110, we need to run each desc */
-		p2m_dev->desc_count = desc_cnt;
-		p2m_dev->desc_idx = 1;
-		p2m_dev->descs = desc;
-
-		solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id),
-			       desc[1].dma_addr);
-		solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id),
-			       desc[1].ext_addr);
-		solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id),
-			       desc[1].cfg);
-		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id),
-			       desc[1].ctrl);
-	}
-
-	timeout = wait_for_completion_timeout(&p2m_dev->completion,
-					      solo_dev->p2m_jiffies);
-
-	if (WARN_ON_ONCE(p2m_dev->error))
-		ret = -EIO;
-	else if (timeout == 0) {
-		solo_dev->p2m_timeouts++;
-		ret = -EAGAIN;
-	}
-
-	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);
-
-	/* Don't write here for the no_desc_mode case, because config is 0.
-	 * We can't test no_desc_mode again, it might race. */
-	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config)
-		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);
-
-	mutex_unlock(&p2m_dev->mutex);
-
-	return ret;
-}
-
-void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
-			dma_addr_t dma_addr, u32 ext_addr, u32 size,
-			int repeat, u32 ext_size)
-{
-	WARN_ON_ONCE(dma_addr & 0x03);
-	WARN_ON_ONCE(!size);
-
-	desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2);
-	desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
-		(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;
-
-	if (repeat) {
-		desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2);
-		desc->ctrl |=  SOLO_P2M_PCI_INC(size >> 2) |
-			 SOLO_P2M_REPEAT(repeat);
-	}
-
-	desc->dma_addr = dma_addr;
-	desc->ext_addr = ext_addr;
-}
-
-int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
-		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
-		   int repeat, u32 ext_size)
-{
-	struct solo_p2m_desc desc[2];
-
-	solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat,
-			   ext_size);
-
-	/* No need for desc_dma since we know it is a single-shot */
-	return solo_p2m_dma_desc(solo_dev, desc, 0, 1);
-}
-
-void solo_p2m_isr(struct solo_dev *solo_dev, int id)
-{
-	struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
-	struct solo_p2m_desc *desc;
-
-	if (p2m_dev->desc_count <= p2m_dev->desc_idx) {
-		complete(&p2m_dev->completion);
-		return;
-	}
-
-	/* Setup next descriptor */
-	p2m_dev->desc_idx++;
-	desc = &p2m_dev->descs[p2m_dev->desc_idx];
-
-	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
-	solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr);
-	solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr);
-	solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg);
-	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl);
-}
-
-void solo_p2m_error_isr(struct solo_dev *solo_dev)
-{
-	unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
-	struct solo_p2m_dev *p2m_dev;
-	int i;
-
-	if (!(err & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC)))
-		return;
-
-	for (i = 0; i < SOLO_NR_P2M; i++) {
-		p2m_dev = &solo_dev->p2m_dev[i];
-		p2m_dev->error = 1;
-		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
-		complete(&p2m_dev->completion);
-	}
-}
-
-void solo_p2m_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < SOLO_NR_P2M; i++)
-		solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
-}
-
-static int solo_p2m_test(struct solo_dev *solo_dev, int base, int size)
-{
-	u32 *wr_buf;
-	u32 *rd_buf;
-	int i;
-	int ret = -EIO;
-	int order = get_order(size);
-
-	wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
-	if (wr_buf == NULL)
-		return -1;
-
-	rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
-	if (rd_buf == NULL) {
-		free_pages((unsigned long)wr_buf, order);
-		return -1;
-	}
-
-	for (i = 0; i < (size >> 3); i++)
-		*(wr_buf + i) = (i << 16) | (i + 1);
-
-	for (i = (size >> 3); i < (size >> 2); i++)
-		*(wr_buf + i) = ~((i << 16) | (i + 1));
-
-	memset(rd_buf, 0x55, size);
-
-	if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0))
-		goto test_fail;
-
-	if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0))
-		goto test_fail;
-
-	for (i = 0; i < (size >> 2); i++) {
-		if (*(wr_buf + i) != *(rd_buf + i))
-			goto test_fail;
-	}
-
-	ret = 0;
-
-test_fail:
-	free_pages((unsigned long)wr_buf, order);
-	free_pages((unsigned long)rd_buf, order);
-
-	return ret;
-}
-
-int solo_p2m_init(struct solo_dev *solo_dev)
-{
-	struct solo_p2m_dev *p2m_dev;
-	int i;
-
-	for (i = 0; i < SOLO_NR_P2M; i++) {
-		p2m_dev = &solo_dev->p2m_dev[i];
-
-		mutex_init(&p2m_dev->mutex);
-		init_completion(&p2m_dev->completion);
-
-		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
-		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
-			       SOLO_P2M_CSC_16BIT_565 |
-			       SOLO_P2M_DESC_INTR_OPT |
-			       SOLO_P2M_DMA_INTERVAL(0) |
-			       SOLO_P2M_PCI_MASTER_MODE);
-		solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
-	}
-
-	/* Find correct SDRAM size */
-	for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) {
-		solo_reg_write(solo_dev, SOLO_DMA_CTRL,
-			       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
-			       SOLO_DMA_CTRL_SDRAM_SIZE(i) |
-			       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
-			       SOLO_DMA_CTRL_READ_CLK_SELECT |
-			       SOLO_DMA_CTRL_LATENCY(1));
-
-		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config |
-			       SOLO_SYS_CFG_RESET);
-		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
-
-		switch (i) {
-		case 2:
-			if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) ||
-			    solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000))
-				continue;
-			break;
-
-		case 1:
-			if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000))
-				continue;
-			break;
-
-		default:
-			if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000))
-				continue;
-		}
-
-		solo_dev->sdram_size = (32 << 20) << i;
-		break;
-	}
-
-	if (!solo_dev->sdram_size) {
-		dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n");
-		return -EIO;
-	}
-
-	if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) {
-		dev_err(&solo_dev->pdev->dev,
-			"SDRAM is not large enough (%u < %u)\n",
-			solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev));
-		return -EIO;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-regs.h linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-regs.h
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-regs.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,639 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_REGISTERS_H
-#define __SOLO6X10_REGISTERS_H
-
-#include "solo6x10-offsets.h"
-
-/* Global 6010 system configuration */
-#define SOLO_SYS_CFG				0x0000
-#define   SOLO_SYS_CFG_FOUT_EN			0x00000001
-#define   SOLO_SYS_CFG_PLL_BYPASS		0x00000002
-#define   SOLO_SYS_CFG_PLL_PWDN			0x00000004
-#define   SOLO_SYS_CFG_OUTDIV(__n)		(((__n) & 0x003) << 3)
-#define   SOLO_SYS_CFG_FEEDBACKDIV(__n)		(((__n) & 0x1ff) << 5)
-#define   SOLO_SYS_CFG_INPUTDIV(__n)		(((__n) & 0x01f) << 14)
-#define   SOLO_SYS_CFG_CLOCK_DIV		0x00080000
-#define   SOLO_SYS_CFG_NCLK_DELAY(__n)		(((__n) & 0x003) << 24)
-#define   SOLO_SYS_CFG_PCLK_DELAY(__n)		(((__n) & 0x00f) << 26)
-#define   SOLO_SYS_CFG_SDRAM64BIT		0x40000000
-#define   SOLO_SYS_CFG_RESET			0x80000000
-
-#define	SOLO_DMA_CTRL				0x0004
-#define	  SOLO_DMA_CTRL_REFRESH_CYCLE(n)	((n)<<8)
-/* 0=16/32MB, 1=32/64MB, 2=64/128MB, 3=128/256MB */
-#define	  SOLO_DMA_CTRL_SDRAM_SIZE(n)		((n)<<6)
-#define	  SOLO_DMA_CTRL_SDRAM_CLK_INVERT	(1<<5)
-#define	  SOLO_DMA_CTRL_STROBE_SELECT		(1<<4)
-#define	  SOLO_DMA_CTRL_READ_DATA_SELECT	(1<<3)
-#define	  SOLO_DMA_CTRL_READ_CLK_SELECT		(1<<2)
-#define	  SOLO_DMA_CTRL_LATENCY(n)		((n)<<0)
-
-/* Some things we set in this are undocumented. Why Softlogic?!?! */
-#define SOLO_DMA_CTRL1				0x0008
-
-#define SOLO_SYS_VCLK				0x000C
-#define	  SOLO_VCLK_INVERT			(1<<22)
-/* 0=sys_clk/4, 1=sys_clk/2, 2=clk_in/2 of system input */
-#define	  SOLO_VCLK_SELECT(n)			((n)<<20)
-#define	  SOLO_VCLK_VIN1415_DELAY(n)		((n)<<14)
-#define	  SOLO_VCLK_VIN1213_DELAY(n)		((n)<<12)
-#define	  SOLO_VCLK_VIN1011_DELAY(n)		((n)<<10)
-#define	  SOLO_VCLK_VIN0809_DELAY(n)		((n)<<8)
-#define	  SOLO_VCLK_VIN0607_DELAY(n)		((n)<<6)
-#define	  SOLO_VCLK_VIN0405_DELAY(n)		((n)<<4)
-#define	  SOLO_VCLK_VIN0203_DELAY(n)		((n)<<2)
-#define	  SOLO_VCLK_VIN0001_DELAY(n)		((n)<<0)
-
-#define SOLO_IRQ_STAT				0x0010
-#define SOLO_IRQ_MASK				0x0014
-#define	  SOLO_IRQ_P2M(n)			(1<<((n)+17))
-#define	  SOLO_IRQ_GPIO				(1<<16)
-#define	  SOLO_IRQ_VIDEO_LOSS			(1<<15)
-#define	  SOLO_IRQ_VIDEO_IN			(1<<14)
-#define	  SOLO_IRQ_MOTION			(1<<13)
-#define	  SOLO_IRQ_ATA_CMD			(1<<12)
-#define	  SOLO_IRQ_ATA_DIR			(1<<11)
-#define	  SOLO_IRQ_PCI_ERR			(1<<10)
-#define	  SOLO_IRQ_PS2_1			(1<<9)
-#define	  SOLO_IRQ_PS2_0			(1<<8)
-#define	  SOLO_IRQ_SPI				(1<<7)
-#define	  SOLO_IRQ_IIC				(1<<6)
-#define	  SOLO_IRQ_UART(n)			(1<<((n) + 4))
-#define	  SOLO_IRQ_G723				(1<<3)
-#define	  SOLO_IRQ_DECODER			(1<<1)
-#define	  SOLO_IRQ_ENCODER			(1<<0)
-
-#define SOLO_CHIP_OPTION			0x001C
-#define   SOLO_CHIP_ID_MASK			0x00000007
-
-#define SOLO_PLL_CONFIG				0x0020 /* 6110 Only */
-
-#define SOLO_EEPROM_CTRL			0x0060
-#define	  SOLO_EEPROM_ACCESS_EN			(1<<7)
-#define	  SOLO_EEPROM_CS			(1<<3)
-#define	  SOLO_EEPROM_CLK			(1<<2)
-#define	  SOLO_EEPROM_DO			(1<<1)
-#define	  SOLO_EEPROM_DI			(1<<0)
-#define	  SOLO_EEPROM_ENABLE (SOLO_EEPROM_ACCESS_EN | SOLO_EEPROM_CS)
-
-#define SOLO_PCI_ERR				0x0070
-#define   SOLO_PCI_ERR_FATAL			0x00000001
-#define   SOLO_PCI_ERR_PARITY			0x00000002
-#define   SOLO_PCI_ERR_TARGET			0x00000004
-#define   SOLO_PCI_ERR_TIMEOUT			0x00000008
-#define   SOLO_PCI_ERR_P2M			0x00000010
-#define   SOLO_PCI_ERR_ATA			0x00000020
-#define   SOLO_PCI_ERR_P2M_DESC			0x00000040
-#define   SOLO_PCI_ERR_FSM0(__s)		(((__s) >> 16) & 0x0f)
-#define   SOLO_PCI_ERR_FSM1(__s)		(((__s) >> 20) & 0x0f)
-#define   SOLO_PCI_ERR_FSM2(__s)		(((__s) >> 24) & 0x1f)
-
-#define SOLO_P2M_BASE				0x0080
-
-#define SOLO_P2M_CONFIG(n)			(0x0080 + ((n)*0x20))
-#define	  SOLO_P2M_DMA_INTERVAL(n)		((n)<<6)/* N*32 clocks */
-#define	  SOLO_P2M_CSC_BYTE_REORDER		(1<<5)	/* BGR -> RGB */
-/* 0:r=[14:10] g=[9:5] b=[4:0], 1:r=[15:11] g=[10:5] b=[4:0] */
-#define	  SOLO_P2M_CSC_16BIT_565		(1<<4)
-#define	  SOLO_P2M_UV_SWAP			(1<<3)
-#define	  SOLO_P2M_PCI_MASTER_MODE		(1<<2)
-#define	  SOLO_P2M_DESC_INTR_OPT		(1<<1)	/* 1:Empty, 0:Each */
-#define	  SOLO_P2M_DESC_MODE			(1<<0)
-
-#define SOLO_P2M_DES_ADR(n)			(0x0084 + ((n)*0x20))
-
-#define SOLO_P2M_DESC_ID(n)			(0x0088 + ((n)*0x20))
-#define	  SOLO_P2M_UPDATE_ID(n)			((n)<<0)
-
-#define SOLO_P2M_STATUS(n)			(0x008C + ((n)*0x20))
-#define	  SOLO_P2M_COMMAND_DONE			(1<<8)
-#define	  SOLO_P2M_CURRENT_ID(stat)		(0xff & (stat))
-
-#define SOLO_P2M_CONTROL(n)			(0x0090 + ((n)*0x20))
-#define	  SOLO_P2M_PCI_INC(n)			((n)<<20)
-#define	  SOLO_P2M_REPEAT(n)			((n)<<10)
-/* 0:512, 1:256, 2:128, 3:64, 4:32, 5:128(2page) */
-#define	  SOLO_P2M_BURST_SIZE(n)		((n)<<7)
-#define	    SOLO_P2M_BURST_512			0
-#define	    SOLO_P2M_BURST_256			1
-#define	    SOLO_P2M_BURST_128			2
-#define	    SOLO_P2M_BURST_64			3
-#define	    SOLO_P2M_BURST_32			4
-#define	  SOLO_P2M_CSC_16BIT			(1<<6)	/* 0:24bit, 1:16bit */
-/* 0:Y[0]<-0(OFF), 1:Y[0]<-1(ON), 2:Y[0]<-G[0], 3:Y[0]<-Bit[15] */
-#define	  SOLO_P2M_ALPHA_MODE(n)		((n)<<4)
-#define	  SOLO_P2M_CSC_ON			(1<<3)
-#define	  SOLO_P2M_INTERRUPT_REQ		(1<<2)
-#define	  SOLO_P2M_WRITE			(1<<1)
-#define	  SOLO_P2M_TRANS_ON			(1<<0)
-
-#define SOLO_P2M_EXT_CFG(n)			(0x0094 + ((n)*0x20))
-#define	  SOLO_P2M_EXT_INC(n)			((n)<<20)
-#define	  SOLO_P2M_COPY_SIZE(n)			((n)<<0)
-
-#define SOLO_P2M_TAR_ADR(n)			(0x0098 + ((n)*0x20))
-
-#define SOLO_P2M_EXT_ADR(n)			(0x009C + ((n)*0x20))
-
-#define SOLO_P2M_BUFFER(i)			(0x2000 + ((i)*4))
-
-#define SOLO_VI_CH_SWITCH_0			0x0100
-#define SOLO_VI_CH_SWITCH_1			0x0104
-#define SOLO_VI_CH_SWITCH_2			0x0108
-
-#define	SOLO_VI_CH_ENA				0x010C
-#define	SOLO_VI_CH_FORMAT			0x0110
-#define	  SOLO_VI_FD_SEL_MASK(n)		((n)<<16)
-#define	  SOLO_VI_PROG_MASK(n)			((n)<<0)
-
-#define SOLO_VI_FMT_CFG				0x0114
-#define	  SOLO_VI_FMT_CHECK_VCOUNT		(1<<31)
-#define	  SOLO_VI_FMT_CHECK_HCOUNT		(1<<30)
-#define   SOLO_VI_FMT_TEST_SIGNAL		(1<<28)
-
-#define	SOLO_VI_PAGE_SW				0x0118
-#define	  SOLO_FI_INV_DISP_LIVE(n)		((n)<<8)
-#define	  SOLO_FI_INV_DISP_OUT(n)		((n)<<7)
-#define	  SOLO_DISP_SYNC_FI(n)			((n)<<6)
-#define	  SOLO_PIP_PAGE_ADD(n)			((n)<<3)
-#define	  SOLO_NORMAL_PAGE_ADD(n)		((n)<<0)
-
-#define	SOLO_VI_ACT_I_P				0x011C
-#define	SOLO_VI_ACT_I_S				0x0120
-#define	SOLO_VI_ACT_P				0x0124
-#define	  SOLO_VI_FI_INVERT			(1<<31)
-#define	  SOLO_VI_H_START(n)			((n)<<21)
-#define	  SOLO_VI_V_START(n)			((n)<<11)
-#define	  SOLO_VI_V_STOP(n)			((n)<<0)
-
-#define SOLO_VI_STATUS0				0x0128
-#define   SOLO_VI_STATUS0_PAGE(__n)		((__n) & 0x07)
-#define SOLO_VI_STATUS1				0x012C
-
-/* XXX: Might be better off in kernel level disp.h */
-#define DISP_PAGE(stat)				((stat) & 0x07)
-
-#define SOLO_VI_PB_CONFIG			0x0130
-#define	  SOLO_VI_PB_USER_MODE			(1<<1)
-#define	  SOLO_VI_PB_PAL			(1<<0)
-#define SOLO_VI_PB_RANGE_HV			0x0134
-#define	  SOLO_VI_PB_HSIZE(h)			((h)<<12)
-#define	  SOLO_VI_PB_VSIZE(v)			((v)<<0)
-#define SOLO_VI_PB_ACT_H			0x0138
-#define	  SOLO_VI_PB_HSTART(n)			((n)<<12)
-#define	  SOLO_VI_PB_HSTOP(n)			((n)<<0)
-#define SOLO_VI_PB_ACT_V			0x013C
-#define	  SOLO_VI_PB_VSTART(n)			((n)<<12)
-#define	  SOLO_VI_PB_VSTOP(n)			((n)<<0)
-
-#define	SOLO_VI_MOSAIC(ch)			(0x0140 + ((ch)*4))
-#define	  SOLO_VI_MOSAIC_SX(x)			((x)<<24)
-#define	  SOLO_VI_MOSAIC_EX(x)			((x)<<16)
-#define	  SOLO_VI_MOSAIC_SY(x)			((x)<<8)
-#define	  SOLO_VI_MOSAIC_EY(x)			((x)<<0)
-
-#define	SOLO_VI_WIN_CTRL0(ch)			(0x0180 + ((ch)*4))
-#define	SOLO_VI_WIN_CTRL1(ch)			(0x01C0 + ((ch)*4))
-
-#define	  SOLO_VI_WIN_CHANNEL(n)		((n)<<28)
-
-#define	  SOLO_VI_WIN_PIP(n)			((n)<<27)
-#define	  SOLO_VI_WIN_SCALE(n)			((n)<<24)
-
-#define	  SOLO_VI_WIN_SX(x)			((x)<<12)
-#define	  SOLO_VI_WIN_EX(x)			((x)<<0)
-
-#define	  SOLO_VI_WIN_SY(x)			((x)<<12)
-#define	  SOLO_VI_WIN_EY(x)			((x)<<0)
-
-#define	SOLO_VI_WIN_ON(ch)			(0x0200 + ((ch)*4))
-
-#define SOLO_VI_WIN_SW				0x0240
-#define SOLO_VI_WIN_LIVE_AUTO_MUTE		0x0244
-
-#define	SOLO_VI_MOT_ADR				0x0260
-#define	  SOLO_VI_MOTION_EN(mask)		((mask)<<16)
-#define	SOLO_VI_MOT_CTRL			0x0264
-#define	  SOLO_VI_MOTION_FRAME_COUNT(n)		((n)<<24)
-#define	  SOLO_VI_MOTION_SAMPLE_LENGTH(n)	((n)<<16)
-#define	  SOLO_VI_MOTION_INTR_START_STOP	(1<<15)
-#define	  SOLO_VI_MOTION_FREEZE_DATA		(1<<14)
-#define	  SOLO_VI_MOTION_SAMPLE_COUNT(n)	((n)<<0)
-#define SOLO_VI_MOT_CLEAR			0x0268
-#define SOLO_VI_MOT_STATUS			0x026C
-#define	  SOLO_VI_MOTION_CNT(n)			((n)<<0)
-#define SOLO_VI_MOTION_BORDER			0x0270
-#define SOLO_VI_MOTION_BAR			0x0274
-#define	  SOLO_VI_MOTION_Y_SET			(1<<29)
-#define	  SOLO_VI_MOTION_Y_ADD			(1<<28)
-#define	  SOLO_VI_MOTION_CB_SET			(1<<27)
-#define	  SOLO_VI_MOTION_CB_ADD			(1<<26)
-#define	  SOLO_VI_MOTION_CR_SET			(1<<25)
-#define	  SOLO_VI_MOTION_CR_ADD			(1<<24)
-#define	  SOLO_VI_MOTION_Y_VALUE(v)		((v)<<16)
-#define	  SOLO_VI_MOTION_CB_VALUE(v)		((v)<<8)
-#define	  SOLO_VI_MOTION_CR_VALUE(v)		((v)<<0)
-
-#define	SOLO_VO_FMT_ENC				0x0300
-#define	  SOLO_VO_SCAN_MODE_PROGRESSIVE		(1<<31)
-#define	  SOLO_VO_FMT_TYPE_PAL			(1<<30)
-#define   SOLO_VO_FMT_TYPE_NTSC			0
-#define	  SOLO_VO_USER_SET			(1<<29)
-
-#define	  SOLO_VO_FI_CHANGE			(1<<20)
-#define	  SOLO_VO_USER_COLOR_SET_VSYNC		(1<<19)
-#define	  SOLO_VO_USER_COLOR_SET_HSYNC		(1<<18)
-#define	  SOLO_VO_USER_COLOR_SET_NAH		(1<<17)
-#define	  SOLO_VO_USER_COLOR_SET_NAV		(1<<16)
-#define	  SOLO_VO_NA_COLOR_Y(Y)			((Y)<<8)
-#define	  SOLO_VO_NA_COLOR_CB(CB)		(((CB)/16)<<4)
-#define	  SOLO_VO_NA_COLOR_CR(CR)		(((CR)/16)<<0)
-
-#define	SOLO_VO_ACT_H				0x0304
-#define	  SOLO_VO_H_BLANK(n)			((n)<<22)
-#define	  SOLO_VO_H_START(n)			((n)<<11)
-#define	  SOLO_VO_H_STOP(n)			((n)<<0)
-
-#define	SOLO_VO_ACT_V				0x0308
-#define	  SOLO_VO_V_BLANK(n)			((n)<<22)
-#define	  SOLO_VO_V_START(n)			((n)<<11)
-#define	  SOLO_VO_V_STOP(n)			((n)<<0)
-
-#define	SOLO_VO_RANGE_HV			0x030C
-#define	  SOLO_VO_SYNC_INVERT			(1<<24)
-#define	  SOLO_VO_HSYNC_INVERT			(1<<23)
-#define	  SOLO_VO_VSYNC_INVERT			(1<<22)
-#define	  SOLO_VO_H_LEN(n)			((n)<<11)
-#define	  SOLO_VO_V_LEN(n)			((n)<<0)
-
-#define	SOLO_VO_DISP_CTRL			0x0310
-#define	  SOLO_VO_DISP_ON			(1<<31)
-#define	  SOLO_VO_DISP_ERASE_COUNT(n)		((n&0xf)<<24)
-#define	  SOLO_VO_DISP_DOUBLE_SCAN		(1<<22)
-#define	  SOLO_VO_DISP_SINGLE_PAGE		(1<<21)
-#define	  SOLO_VO_DISP_BASE(n)			(((n)>>16) & 0xffff)
-
-#define SOLO_VO_DISP_ERASE			0x0314
-#define	  SOLO_VO_DISP_ERASE_ON			(1<<0)
-
-#define	SOLO_VO_ZOOM_CTRL			0x0318
-#define	  SOLO_VO_ZOOM_VER_ON			(1<<24)
-#define	  SOLO_VO_ZOOM_HOR_ON			(1<<23)
-#define	  SOLO_VO_ZOOM_V_COMP			(1<<22)
-#define	  SOLO_VO_ZOOM_SX(h)			(((h)/2)<<11)
-#define	  SOLO_VO_ZOOM_SY(v)			(((v)/2)<<0)
-
-#define SOLO_VO_FREEZE_CTRL			0x031C
-#define	  SOLO_VO_FREEZE_ON			(1<<1)
-#define	  SOLO_VO_FREEZE_INTERPOLATION		(1<<0)
-
-#define	SOLO_VO_BKG_COLOR			0x0320
-#define	  SOLO_BG_Y(y)				((y)<<16)
-#define	  SOLO_BG_U(u)				((u)<<8)
-#define	  SOLO_BG_V(v)				((v)<<0)
-
-#define	SOLO_VO_DEINTERLACE			0x0324
-#define	  SOLO_VO_DEINTERLACE_THRESHOLD(n)	((n)<<8)
-#define	  SOLO_VO_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
-
-#define SOLO_VO_BORDER_LINE_COLOR		0x0330
-#define SOLO_VO_BORDER_FILL_COLOR		0x0334
-#define SOLO_VO_BORDER_LINE_MASK		0x0338
-#define SOLO_VO_BORDER_FILL_MASK		0x033c
-
-#define SOLO_VO_BORDER_X(n)			(0x0340+((n)*4))
-#define SOLO_VO_BORDER_Y(n)			(0x0354+((n)*4))
-
-#define SOLO_VO_CELL_EXT_SET			0x0368
-#define SOLO_VO_CELL_EXT_START			0x036c
-#define SOLO_VO_CELL_EXT_STOP			0x0370
-
-#define SOLO_VO_CELL_EXT_SET2			0x0374
-#define SOLO_VO_CELL_EXT_START2			0x0378
-#define SOLO_VO_CELL_EXT_STOP2			0x037c
-
-#define SOLO_VO_RECTANGLE_CTRL(n)		(0x0368+((n)*12))
-#define SOLO_VO_RECTANGLE_START(n)		(0x036c+((n)*12))
-#define SOLO_VO_RECTANGLE_STOP(n)		(0x0370+((n)*12))
-
-#define SOLO_VO_CURSOR_POS			(0x0380)
-#define SOLO_VO_CURSOR_CLR			(0x0384)
-#define SOLO_VO_CURSOR_CLR2			(0x0388)
-#define SOLO_VO_CURSOR_MASK(id)			(0x0390+((id)*4))
-
-#define SOLO_VO_EXPANSION(id)			(0x0250+((id)*4))
-
-#define	SOLO_OSG_CONFIG				0x03E0
-#define	  SOLO_VO_OSG_ON			(1<<31)
-#define	  SOLO_VO_OSG_COLOR_MUTE		(1<<28)
-#define	  SOLO_VO_OSG_ALPHA_RATE(n)		((n)<<22)
-#define	  SOLO_VO_OSG_ALPHA_BG_RATE(n)		((n)<<16)
-#define	  SOLO_VO_OSG_BASE(offset)		(((offset)>>16)&0xffff)
-
-#define SOLO_OSG_ERASE				0x03E4
-#define	  SOLO_OSG_ERASE_ON			(0x80)
-#define	  SOLO_OSG_ERASE_OFF			(0x00)
-
-#define SOLO_VO_OSG_BLINK			0x03E8
-#define	  SOLO_VO_OSG_BLINK_ON			(1<<1)
-#define	  SOLO_VO_OSG_BLINK_INTREVAL18		(1<<0)
-
-#define SOLO_CAP_BASE				0x0400
-#define	  SOLO_CAP_MAX_PAGE(n)			((n)<<16)
-#define	  SOLO_CAP_BASE_ADDR(n)			((n)<<0)
-#define SOLO_CAP_BTW				0x0404
-#define	  SOLO_CAP_PROG_BANDWIDTH(n)		((n)<<8)
-#define	  SOLO_CAP_MAX_BANDWIDTH(n)		((n)<<0)
-
-#define SOLO_DIM_SCALE1				0x0408
-#define SOLO_DIM_SCALE2				0x040C
-#define SOLO_DIM_SCALE3				0x0410
-#define SOLO_DIM_SCALE4				0x0414
-#define SOLO_DIM_SCALE5				0x0418
-#define	  SOLO_DIM_V_MB_NUM_FRAME(n)		((n)<<16)
-#define	  SOLO_DIM_V_MB_NUM_FIELD(n)		((n)<<8)
-#define	  SOLO_DIM_H_MB_NUM(n)			((n)<<0)
-
-#define SOLO_DIM_PROG				0x041C
-#define SOLO_CAP_STATUS				0x0420
-
-#define SOLO_CAP_CH_SCALE(ch)			(0x0440+((ch)*4))
-#define SOLO_CAP_CH_COMP_ENA_E(ch)		(0x0480+((ch)*4))
-#define SOLO_CAP_CH_INTV(ch)			(0x04C0+((ch)*4))
-#define SOLO_CAP_CH_INTV_E(ch)			(0x0500+((ch)*4))
-
-
-#define SOLO_VE_CFG0				0x0610
-#define	  SOLO_VE_TWO_PAGE_MODE			(1<<31)
-#define	  SOLO_VE_INTR_CTRL(n)			((n)<<24)
-#define	  SOLO_VE_BLOCK_SIZE(n)			((n)<<16)
-#define	  SOLO_VE_BLOCK_BASE(n)			((n)<<0)
-
-#define SOLO_VE_CFG1				0x0614
-#define	  SOLO_VE_BYTE_ALIGN(n)			((n)<<24)
-#define	  SOLO_VE_INSERT_INDEX			(1<<18)
-#define	  SOLO_VE_MOTION_MODE(n)		((n)<<16)
-#define	  SOLO_VE_MOTION_BASE(n)		((n)<<0)
-#define   SOLO_VE_MPEG_SIZE_H(n)		((n)<<28) /* 6110 Only */
-#define   SOLO_VE_JPEG_SIZE_H(n)		((n)<<20) /* 6110 Only */
-#define   SOLO_VE_INSERT_INDEX_JPEG		(1<<19)   /* 6110 Only */
-
-#define SOLO_VE_WMRK_POLY			0x061C
-#define SOLO_VE_VMRK_INIT_KEY			0x0620
-#define SOLO_VE_WMRK_STRL			0x0624
-#define SOLO_VE_ENCRYP_POLY			0x0628
-#define SOLO_VE_ENCRYP_INIT			0x062C
-#define SOLO_VE_ATTR				0x0630
-#define	  SOLO_VE_LITTLE_ENDIAN			(1<<31)
-#define	  SOLO_COMP_ATTR_RN			(1<<30)
-#define	  SOLO_COMP_ATTR_FCODE(n)		((n)<<27)
-#define	  SOLO_COMP_TIME_INC(n)			((n)<<25)
-#define	  SOLO_COMP_TIME_WIDTH(n)		((n)<<21)
-#define	  SOLO_DCT_INTERVAL(n)			((n)<<16)
-#define SOLO_VE_COMPT_MOT			0x0634 /* 6110 Only */
-
-#define SOLO_VE_STATE(n)			(0x0640+((n)*4))
-
-#define SOLO_VE_JPEG_QP_TBL			0x0670
-#define SOLO_VE_JPEG_QP_CH_L			0x0674
-#define SOLO_VE_JPEG_QP_CH_H			0x0678
-#define SOLO_VE_JPEG_CFG			0x067C
-#define SOLO_VE_JPEG_CTRL			0x0680
-#define SOLO_VE_CODE_ENCRYPT			0x0684 /* 6110 Only */
-#define SOLO_VE_JPEG_CFG1			0x0688 /* 6110 Only */
-#define SOLO_VE_WMRK_ENABLE			0x068C /* 6110 Only */
-#define SOLO_VE_OSD_CH				0x0690
-#define SOLO_VE_OSD_BASE			0x0694
-#define SOLO_VE_OSD_CLR				0x0698
-#define SOLO_VE_OSD_OPT				0x069C
-#define   SOLO_VE_OSD_V_DOUBLE			(1<<16) /* 6110 Only */
-#define   SOLO_VE_OSD_H_SHADOW			(1<<15)
-#define   SOLO_VE_OSD_V_SHADOW			(1<<14)
-#define   SOLO_VE_OSD_H_OFFSET(n)		((n & 0x7f)<<7)
-#define   SOLO_VE_OSD_V_OFFSET(n)		(n & 0x7f)
-
-#define SOLO_VE_CH_INTL(ch)			(0x0700+((ch)*4))
-#define SOLO_VE_CH_MOT(ch)			(0x0740+((ch)*4))
-#define SOLO_VE_CH_QP(ch)			(0x0780+((ch)*4))
-#define SOLO_VE_CH_QP_E(ch)			(0x07C0+((ch)*4))
-#define SOLO_VE_CH_GOP(ch)			(0x0800+((ch)*4))
-#define SOLO_VE_CH_GOP_E(ch)			(0x0840+((ch)*4))
-#define SOLO_VE_CH_REF_BASE(ch)			(0x0880+((ch)*4))
-#define SOLO_VE_CH_REF_BASE_E(ch)		(0x08C0+((ch)*4))
-
-#define SOLO_VE_MPEG4_QUE(n)			(0x0A00+((n)*8))
-#define SOLO_VE_JPEG_QUE(n)			(0x0A04+((n)*8))
-
-#define SOLO_VD_CFG0				0x0900
-#define	  SOLO_VD_CFG_NO_WRITE_NO_WINDOW	(1<<24)
-#define	  SOLO_VD_CFG_BUSY_WIAT_CODE		(1<<23)
-#define	  SOLO_VD_CFG_BUSY_WIAT_REF		(1<<22)
-#define	  SOLO_VD_CFG_BUSY_WIAT_RES		(1<<21)
-#define	  SOLO_VD_CFG_BUSY_WIAT_MS		(1<<20)
-#define	  SOLO_VD_CFG_SINGLE_MODE		(1<<18)
-#define	  SOLO_VD_CFG_SCAL_MANUAL		(1<<17)
-#define	  SOLO_VD_CFG_USER_PAGE_CTRL		(1<<16)
-#define	  SOLO_VD_CFG_LITTLE_ENDIAN		(1<<15)
-#define	  SOLO_VD_CFG_START_FI			(1<<14)
-#define	  SOLO_VD_CFG_ERR_LOCK			(1<<13)
-#define	  SOLO_VD_CFG_ERR_INT_ENA		(1<<12)
-#define	  SOLO_VD_CFG_TIME_WIDTH(n)		((n)<<8)
-#define	  SOLO_VD_CFG_DCT_INTERVAL(n)		((n)<<0)
-
-#define SOLO_VD_CFG1				0x0904
-
-#define	SOLO_VD_DEINTERLACE			0x0908
-#define	  SOLO_VD_DEINTERLACE_THRESHOLD(n)	((n)<<8)
-#define	  SOLO_VD_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
-
-#define SOLO_VD_CODE_ADR			0x090C
-
-#define SOLO_VD_CTRL				0x0910
-#define	  SOLO_VD_OPER_ON			(1<<31)
-#define	  SOLO_VD_MAX_ITEM(n)			((n)<<0)
-
-#define SOLO_VD_STATUS0				0x0920
-#define	  SOLO_VD_STATUS0_INTR_ACK		(1<<22)
-#define	  SOLO_VD_STATUS0_INTR_EMPTY		(1<<21)
-#define	  SOLO_VD_STATUS0_INTR_ERR		(1<<20)
-
-#define SOLO_VD_STATUS1				0x0924
-
-#define SOLO_VD_IDX0				0x0930
-#define	  SOLO_VD_IDX_INTERLACE			(1<<30)
-#define	  SOLO_VD_IDX_CHANNEL(n)		((n)<<24)
-#define	  SOLO_VD_IDX_SIZE(n)			((n)<<0)
-
-#define SOLO_VD_IDX1				0x0934
-#define	  SOLO_VD_IDX_SRC_SCALE(n)		((n)<<28)
-#define	  SOLO_VD_IDX_WINDOW(n)			((n)<<24)
-#define	  SOLO_VD_IDX_DEINTERLACE		(1<<16)
-#define	  SOLO_VD_IDX_H_BLOCK(n)		((n)<<8)
-#define	  SOLO_VD_IDX_V_BLOCK(n)		((n)<<0)
-
-#define SOLO_VD_IDX2				0x0938
-#define	  SOLO_VD_IDX_REF_BASE_SIDE		(1<<31)
-#define	  SOLO_VD_IDX_REF_BASE(n)		(((n)>>16)&0xffff)
-
-#define SOLO_VD_IDX3				0x093C
-#define	  SOLO_VD_IDX_DISP_SCALE(n)		((n)<<28)
-#define	  SOLO_VD_IDX_INTERLACE_WR		(1<<27)
-#define	  SOLO_VD_IDX_INTERPOL			(1<<26)
-#define	  SOLO_VD_IDX_HOR2X			(1<<25)
-#define	  SOLO_VD_IDX_OFFSET_X(n)		((n)<<12)
-#define	  SOLO_VD_IDX_OFFSET_Y(n)		((n)<<0)
-
-#define SOLO_VD_IDX4				0x0940
-#define	  SOLO_VD_IDX_DEC_WR_PAGE(n)		((n)<<8)
-#define	  SOLO_VD_IDX_DISP_RD_PAGE(n)		((n)<<0)
-
-#define SOLO_VD_WR_PAGE(n)			(0x03F0 + ((n) * 4))
-
-
-#define SOLO_GPIO_CONFIG_0			0x0B00
-#define SOLO_GPIO_CONFIG_1			0x0B04
-#define SOLO_GPIO_DATA_OUT			0x0B08
-#define SOLO_GPIO_DATA_IN			0x0B0C
-#define SOLO_GPIO_INT_ACK_STA			0x0B10
-#define SOLO_GPIO_INT_ENA			0x0B14
-#define SOLO_GPIO_INT_CFG_0			0x0B18
-#define SOLO_GPIO_INT_CFG_1			0x0B1C
-
-
-#define SOLO_IIC_CFG				0x0B20
-#define	  SOLO_IIC_ENABLE			(1<<8)
-#define	  SOLO_IIC_PRESCALE(n)			((n)<<0)
-
-#define SOLO_IIC_CTRL				0x0B24
-#define	  SOLO_IIC_AUTO_CLEAR			(1<<20)
-#define	  SOLO_IIC_STATE_RX_ACK			(1<<19)
-#define	  SOLO_IIC_STATE_BUSY			(1<<18)
-#define	  SOLO_IIC_STATE_SIG_ERR		(1<<17)
-#define	  SOLO_IIC_STATE_TRNS			(1<<16)
-#define	  SOLO_IIC_CH_SET(n)			((n)<<5)
-#define	  SOLO_IIC_ACK_EN			(1<<4)
-#define	  SOLO_IIC_START			(1<<3)
-#define	  SOLO_IIC_STOP				(1<<2)
-#define	  SOLO_IIC_READ				(1<<1)
-#define	  SOLO_IIC_WRITE			(1<<0)
-
-#define SOLO_IIC_TXD				0x0B28
-#define SOLO_IIC_RXD				0x0B2C
-
-/*
- *	UART REGISTER
- */
-#define SOLO_UART_CONTROL(n)			(0x0BA0 + ((n)*0x20))
-#define	  SOLO_UART_CLK_DIV(n)			((n)<<24)
-#define	  SOLO_MODEM_CTRL_EN			(1<<20)
-#define	  SOLO_PARITY_ERROR_DROP		(1<<18)
-#define	  SOLO_IRQ_ERR_EN			(1<<17)
-#define	  SOLO_IRQ_RX_EN			(1<<16)
-#define	  SOLO_IRQ_TX_EN			(1<<15)
-#define	  SOLO_RX_EN				(1<<14)
-#define	  SOLO_TX_EN				(1<<13)
-#define	  SOLO_UART_HALF_DUPLEX			(1<<12)
-#define	  SOLO_UART_LOOPBACK			(1<<11)
-
-#define	  SOLO_BAUDRATE_230400			((0<<9)|(0<<6))
-#define	  SOLO_BAUDRATE_115200			((0<<9)|(1<<6))
-#define	  SOLO_BAUDRATE_57600			((0<<9)|(2<<6))
-#define	  SOLO_BAUDRATE_38400			((0<<9)|(3<<6))
-#define	  SOLO_BAUDRATE_19200			((0<<9)|(4<<6))
-#define	  SOLO_BAUDRATE_9600			((0<<9)|(5<<6))
-#define	  SOLO_BAUDRATE_4800			((0<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_2400			((1<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_1200			((2<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_300			((3<<9)|(6<<6))
-
-#define	  SOLO_UART_DATA_BIT_8			(3<<4)
-#define	  SOLO_UART_DATA_BIT_7			(2<<4)
-#define	  SOLO_UART_DATA_BIT_6			(1<<4)
-#define	  SOLO_UART_DATA_BIT_5			(0<<4)
-
-#define	  SOLO_UART_STOP_BIT_1			(0<<2)
-#define	  SOLO_UART_STOP_BIT_2			(1<<2)
-
-#define	  SOLO_UART_PARITY_NONE			(0<<0)
-#define	  SOLO_UART_PARITY_EVEN			(2<<0)
-#define	  SOLO_UART_PARITY_ODD			(3<<0)
-
-#define SOLO_UART_STATUS(n)			(0x0BA4 + ((n)*0x20))
-#define	  SOLO_UART_CTS				(1<<15)
-#define	  SOLO_UART_RX_BUSY			(1<<14)
-#define	  SOLO_UART_OVERRUN			(1<<13)
-#define	  SOLO_UART_FRAME_ERR			(1<<12)
-#define	  SOLO_UART_PARITY_ERR			(1<<11)
-#define	  SOLO_UART_TX_BUSY			(1<<5)
-
-#define	  SOLO_UART_RX_BUFF_CNT(stat)		(((stat)>>6) & 0x1f)
-#define	  SOLO_UART_RX_BUFF_SIZE		8
-#define	  SOLO_UART_TX_BUFF_CNT(stat)		(((stat)>>0) & 0x1f)
-#define	  SOLO_UART_TX_BUFF_SIZE		8
-
-#define SOLO_UART_TX_DATA(n)			(0x0BA8 + ((n)*0x20))
-#define	  SOLO_UART_TX_DATA_PUSH		(1<<8)
-#define SOLO_UART_RX_DATA(n)			(0x0BAC + ((n)*0x20))
-#define	  SOLO_UART_RX_DATA_POP			(1<<8)
-
-#define SOLO_TIMER_CLOCK_NUM			0x0be0
-#define SOLO_TIMER_USEC				0x0be8
-#define SOLO_TIMER_SEC				0x0bec
-#define SOLO_TIMER_USEC_LSB			0x0d20 /* 6110 Only */
-
-#define SOLO_AUDIO_CONTROL			0x0D00
-#define	  SOLO_AUDIO_ENABLE			(1<<31)
-#define	  SOLO_AUDIO_MASTER_MODE		(1<<30)
-#define	  SOLO_AUDIO_I2S_MODE			(1<<29)
-#define	  SOLO_AUDIO_I2S_LR_SWAP		(1<<27)
-#define	  SOLO_AUDIO_I2S_8BIT			(1<<26)
-#define	  SOLO_AUDIO_I2S_MULTI(n)		((n)<<24)
-#define	  SOLO_AUDIO_MIX_9TO0			(1<<23)
-#define	  SOLO_AUDIO_DEC_9TO0_VOL(n)		((n)<<20)
-#define	  SOLO_AUDIO_MIX_19TO10			(1<<19)
-#define	  SOLO_AUDIO_DEC_19TO10_VOL(n)		((n)<<16)
-#define	  SOLO_AUDIO_MODE(n)			((n)<<0)
-#define SOLO_AUDIO_SAMPLE			0x0D04
-#define	  SOLO_AUDIO_EE_MODE_ON			(1<<30)
-#define	  SOLO_AUDIO_EE_ENC_CH(ch)		((ch)<<25)
-#define	  SOLO_AUDIO_BITRATE(n)			((n)<<16)
-#define	  SOLO_AUDIO_CLK_DIV(n)			((n)<<0)
-#define SOLO_AUDIO_FDMA_INTR			0x0D08
-#define	  SOLO_AUDIO_FDMA_INTERVAL(n)		((n)<<19)
-#define	  SOLO_AUDIO_INTR_ORDER(n)		((n)<<16)
-#define	  SOLO_AUDIO_FDMA_BASE(n)		((n)<<0)
-#define SOLO_AUDIO_EVOL_0			0x0D0C
-#define SOLO_AUDIO_EVOL_1			0x0D10
-#define	  SOLO_AUDIO_EVOL(ch, value)		((value)<<((ch)%10))
-#define SOLO_AUDIO_STA				0x0D14
-
-/*
- * Watchdog configuration
- */
-#define SOLO_WATCHDOG				0x0be4
-#define SOLO_WATCHDOG_SET(status, sec)		(status << 8 | (sec & 0xff))
-
-#endif /* __SOLO6X10_REGISTERS_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,874 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include "solo6x10.h"
-#include "solo6x10-tw28.h"
-
-#define DEFAULT_HDELAY_NTSC		(32 - 8)
-#define DEFAULT_HACTIVE_NTSC		(720 + 16)
-#define DEFAULT_VDELAY_NTSC		(7 - 2)
-#define DEFAULT_VACTIVE_NTSC		(240 + 4)
-
-#define DEFAULT_HDELAY_PAL		(32 + 4)
-#define DEFAULT_HACTIVE_PAL		(864-DEFAULT_HDELAY_PAL)
-#define DEFAULT_VDELAY_PAL		(6)
-#define DEFAULT_VACTIVE_PAL		(312-DEFAULT_VDELAY_PAL)
-
-
-static const u8 tbl_tw2864_ntsc_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
-	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
-	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
-	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
-	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
-	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
-	0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
-	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
-	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
-	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
-};
-
-static const u8 tbl_tw2864_pal_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
-	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
-	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
-	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
-	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
-	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01,
-	0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
-	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
-	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
-	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
-};
-
-static const u8 tbl_tw2865_ntsc_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, /* 0x40 */
-	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
-	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
-	0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
-	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
-	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
-	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
-	0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
-	0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
-	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
-	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
-};
-
-static const u8 tbl_tw2865_pal_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, /* 0x40 */
-	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
-	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
-	0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
-	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
-	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
-	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
-	0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
-	0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
-	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
-	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
-};
-
-#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
-
-static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off,
-		      u8 tw_off)
-{
-	if (is_tw286x(solo_dev, chip_id))
-		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					 TW_CHIP_OFFSET_ADDR(chip_id),
-					 tw6x_off);
-	else
-		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					 TW_CHIP_OFFSET_ADDR(chip_id),
-					 tw_off);
-}
-
-static void tw_writebyte(struct solo_dev *solo_dev, int chip_id,
-			 u8 tw6x_off, u8 tw_off, u8 val)
-{
-	if (is_tw286x(solo_dev, chip_id))
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-				   TW_CHIP_OFFSET_ADDR(chip_id),
-				   tw6x_off, val);
-	else
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-				   TW_CHIP_OFFSET_ADDR(chip_id),
-				   tw_off, val);
-}
-
-static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
-				u8 val)
-{
-	int i;
-
-	for (i = 0; i < 5; i++) {
-		u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
-		if (rval == val)
-			return;
-
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val);
-		msleep_interruptible(1);
-	}
-
-/*	printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */
-/*		addr, off, val); */
-}
-
-static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_tw2865_common[256];
-	int i;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
-		memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
-		       sizeof(tbl_tw2865_common));
-	else
-		memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
-		       sizeof(tbl_tw2865_common));
-
-	/* ALINK Mode */
-	if (solo_dev->nr_chans == 4) {
-		tbl_tw2865_common[0xd2] = 0x01;
-		tbl_tw2865_common[0xcf] = 0x00;
-	} else if (solo_dev->nr_chans == 8) {
-		tbl_tw2865_common[0xd2] = 0x02;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2865_common[0xcf] = 0x80;
-	} else if (solo_dev->nr_chans == 16) {
-		tbl_tw2865_common[0xd2] = 0x03;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2865_common[0xcf] = 0x83;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-			tbl_tw2865_common[0xcf] = 0x83;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-			tbl_tw2865_common[0xcf] = 0x80;
-	}
-
-	for (i = 0; i < 0xff; i++) {
-		/* Skip read only registers */
-		switch (i) {
-		case 0xb8 ... 0xc1:
-		case 0xc4 ... 0xc7:
-		case 0xfd:
-			continue;
-		}
-		switch (i & ~0x30) {
-		case 0x00:
-		case 0x0c ... 0x0d:
-			continue;
-		}
-
-		tw_write_and_verify(solo_dev, dev_addr, i,
-				    tbl_tw2865_common[i]);
-	}
-
-	return 0;
-}
-
-static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_tw2864_common[256];
-	int i;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
-		memcpy(tbl_tw2864_common, tbl_tw2864_pal_template,
-		       sizeof(tbl_tw2864_common));
-	else
-		memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template,
-		       sizeof(tbl_tw2864_common));
-
-	if (solo_dev->tw2865 == 0) {
-		/* IRQ Mode */
-		if (solo_dev->nr_chans == 4) {
-			tbl_tw2864_common[0xd2] = 0x01;
-			tbl_tw2864_common[0xcf] = 0x00;
-		} else if (solo_dev->nr_chans == 8) {
-			tbl_tw2864_common[0xd2] = 0x02;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x40;
-		} else if (solo_dev->nr_chans == 16) {
-			tbl_tw2864_common[0xd2] = 0x03;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-				tbl_tw2864_common[0xcf] = 0x40;
-		}
-	} else {
-		/* ALINK Mode. Assumes that the first tw28xx is a
-		 * 2865 and these are in cascade. */
-		for (i = 0; i <= 4; i++)
-			tbl_tw2864_common[0x08 | i << 4] = 0x12;
-
-		if (solo_dev->nr_chans == 8) {
-			tbl_tw2864_common[0xd2] = 0x02;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x80;
-		} else if (solo_dev->nr_chans == 16) {
-			tbl_tw2864_common[0xd2] = 0x03;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x83;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-				tbl_tw2864_common[0xcf] = 0x83;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-				tbl_tw2864_common[0xcf] = 0x80;
-		}
-	}
-
-	for (i = 0; i < 0xff; i++) {
-		/* Skip read only registers */
-		switch (i) {
-		case 0xb8 ... 0xc1:
-		case 0xfd:
-			continue;
-		}
-		switch (i & ~0x30) {
-		case 0x00:
-		case 0x0c:
-		case 0x0d:
-			continue;
-		}
-
-		tw_write_and_verify(solo_dev, dev_addr, i,
-				    tbl_tw2864_common[i]);
-	}
-
-	return 0;
-}
-
-static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_ntsc_tw2815_common[] = {
-		0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
-		0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
-	};
-
-	u8 tbl_pal_tw2815_common[] = {
-		0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
-		0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
-	};
-
-	u8 tbl_tw2815_sfr[] = {
-		0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f, /* 0x00 */
-		0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
-		0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00, /* 0x10 */
-		0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
-		0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec, /* 0x20 */
-		0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
-		0x88, 0x11, 0x00, 0x88, 0x88, 0x00,		/* 0x30 */
-	};
-	u8 *tbl_tw2815_common;
-	int i;
-	int ch;
-
-	tbl_ntsc_tw2815_common[0x06] = 0;
-
-	/* Horizontal Delay Control */
-	tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8);
-
-	/* Horizontal Active Control */
-	tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2);
-
-	/* Vertical Delay Control */
-	tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4);
-
-	/* Vertical Active Control */
-	tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5);
-
-	tbl_pal_tw2815_common[0x06] = 0;
-
-	/* Horizontal Delay Control */
-	tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8);
-
-	/* Horizontal Active Control */
-	tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2);
-
-	/* Vertical Delay Control */
-	tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4);
-
-	/* Vertical Active Control */
-	tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5);
-
-	tbl_tw2815_common =
-	    (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ?
-	     tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
-
-	/* Dual ITU-R BT.656 format */
-	tbl_tw2815_common[0x0d] |= 0x04;
-
-	/* Audio configuration */
-	tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
-
-	if (solo_dev->nr_chans == 4) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 1;
-		tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
-	} else if (solo_dev->nr_chans == 8) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 2;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
-	} else if (solo_dev->nr_chans == 16) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 3;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
-	}
-
-	/* Output mode of R_ADATM pin (0 mixing, 1 record) */
-	/* tbl_tw2815_sfr[0x63 - 0x40] |= 0 << 2; */
-
-	/* 8KHz, used to be 16KHz, but changed for remote client compat */
-	tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
-	tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
-
-	/* Playback of right channel */
-	tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
-
-	/* Reserved value (XXX ??) */
-	tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
-
-	/* Analog output gain and mix ratio playback on full */
-	tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
-	/* Select playback audio and mute all except */
-	tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
-	tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
-
-	/* End of audio configuration */
-
-	for (ch = 0; ch < 4; ch++) {
-		tbl_tw2815_common[0x0d] &= ~3;
-		switch (ch) {
-		case 0:
-			tbl_tw2815_common[0x0d] |= 0x21;
-			break;
-		case 1:
-			tbl_tw2815_common[0x0d] |= 0x20;
-			break;
-		case 2:
-			tbl_tw2815_common[0x0d] |= 0x23;
-			break;
-		case 3:
-			tbl_tw2815_common[0x0d] |= 0x22;
-			break;
-		}
-
-		for (i = 0; i < 0x0f; i++) {
-			if (i == 0x00)
-				continue;	/* read-only */
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   dev_addr, (ch * 0x10) + i,
-					   tbl_tw2815_common[i]);
-		}
-	}
-
-	for (i = 0x40; i < 0x76; i++) {
-		/* Skip read-only and nop registers */
-		if (i == 0x40 || i == 0x59 || i == 0x5a ||
-		    i == 0x5d || i == 0x5e || i == 0x5f)
-			continue;
-
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i,
-				       tbl_tw2815_sfr[i - 0x40]);
-	}
-
-	return 0;
-}
-
-#define FIRST_ACTIVE_LINE	0x0008
-#define LAST_ACTIVE_LINE	0x0102
-
-static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals,
-		int start, int n)
-{
-	for (; start < n; start++, vals++) {
-		/* Skip read-only registers */
-		switch (start) {
-		/* case 0x00 ... 0x25: */
-		case 0x2e ... 0x37:
-		case 0x60:
-		case 0x7d:
-			continue;
-		}
-		solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals);
-	}
-}
-
-#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \
-		| ((FIRST_ACTIVE_LINE & 0x100) >> 4))
-
-static void saa712x_setup(struct solo_dev *dev)
-{
-	const int reg_start = 0x26;
-	const uint8_t saa7128_regs_ntsc[] = {
-	/* :0x26 */
-		0x0d, 0x00,
-	/* :0x28 */
-		0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
-	/* :0x2e XXX: read-only */
-		0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* :0x38 */
-		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* :0x40 */
-		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
-		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
-	/* :0x50 */
-		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
-		0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
-	/* :0x60 */
-		0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
-		0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00,
-	/* :0x70 */
-		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
-		0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff,
-		SAA712x_reg7c, 0x00, 0xff, 0xff,
-	}, saa7128_regs_pal[] = {
-	/* :0x26 */
-		0x0d, 0x00,
-	/* :0x28 */
-		0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
-	/* :0x2e XXX: read-only */
-		0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* :0x38 */
-		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* :0x40 */
-		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
-		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
-	/* :0x50 */
-		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
-		0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e,
-	/* :0x60 */
-		0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77,
-		0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00,
-	/* :0x70 */
-		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
-		0x00, 0x00, 0x12, 0x30,
-		SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff,
-	};
-
-	if (dev->video_type == SOLO_VO_FMT_TYPE_PAL)
-		saa712x_write_regs(dev, saa7128_regs_pal, reg_start,
-				sizeof(saa7128_regs_pal));
-	else
-		saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start,
-				sizeof(saa7128_regs_ntsc));
-}
-
-int solo_tw28_init(struct solo_dev *solo_dev)
-{
-	int i;
-	u8 value;
-
-	solo_dev->tw28_cnt = 0;
-
-	/* Detect techwell chip type(s) */
-	for (i = 0; i < solo_dev->nr_chans / 4; i++) {
-		value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					  TW_CHIP_OFFSET_ADDR(i), 0xFF);
-
-		switch (value >> 3) {
-		case 0x18:
-			solo_dev->tw2865 |= 1 << i;
-			solo_dev->tw28_cnt++;
-			break;
-		case 0x0c:
-			solo_dev->tw2864 |= 1 << i;
-			solo_dev->tw28_cnt++;
-			break;
-		default:
-			value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						  TW_CHIP_OFFSET_ADDR(i),
-						  0x59);
-			if ((value >> 3) == 0x04) {
-				solo_dev->tw2815 |= 1 << i;
-				solo_dev->tw28_cnt++;
-			}
-		}
-	}
-
-	if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) {
-		dev_err(&solo_dev->pdev->dev,
-			"Could not initialize any techwell chips\n");
-		return -EINVAL;
-	}
-
-	saa712x_setup(solo_dev);
-
-	for (i = 0; i < solo_dev->tw28_cnt; i++) {
-		if ((solo_dev->tw2865 & (1 << i)))
-			tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-		else if ((solo_dev->tw2864 & (1 << i)))
-			tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-		else
-			tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-	}
-
-	return 0;
-}
-
-/*
- * We accessed the video status signal in the Techwell chip through
- * iic/i2c because the video status reported by register REG_VI_STATUS1
- * (address 0x012C) of the SOLO6010 chip doesn't give the correct video
- * status signal values.
- */
-int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
-{
-	u8 val, chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR,
-			  TW_AV_STAT_ADDR) & 0x0f;
-
-	return val & (1 << ch) ? 1 : 0;
-}
-
-#if 0
-/* Status of audio from up to 4 techwell chips are combined into 1 variable.
- * See techwell datasheet for details. */
-u16 tw28_get_audio_status(struct solo_dev *solo_dev)
-{
-	u8 val;
-	u16 status = 0;
-	int i;
-
-	for (i = 0; i < solo_dev->tw28_cnt; i++) {
-		val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR,
-				   TW_AV_STAT_ADDR) & 0xf0) >> 4;
-		status |= val << (i * 4);
-	}
-
-	return status;
-}
-#endif
-
-bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch)
-{
-	return is_tw286x(solo_dev, ch / 4);
-}
-
-int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
-		      s32 val)
-{
-	char sval;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	if (val > 255 || val < 0)
-		return -ERANGE;
-
-	switch (ctrl) {
-	case V4L2_CID_SHARPNESS:
-		/* Only 286x has sharpness */
-		if (is_tw286x(solo_dev, chip_num)) {
-			u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						 TW_CHIP_OFFSET_ADDR(chip_num),
-						 TW286x_SHARPNESS(chip_num));
-			v &= 0xf0;
-			v |= val;
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   TW_CHIP_OFFSET_ADDR(chip_num),
-					   TW286x_SHARPNESS(chip_num), v);
-		} else {
-			return -EINVAL;
-		}
-		break;
-
-	case V4L2_CID_HUE:
-		if (is_tw286x(solo_dev, chip_num))
-			sval = val - 128;
-		else
-			sval = (char)val;
-		tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
-			     TW_HUE_ADDR(ch), sval);
-
-		break;
-
-	case V4L2_CID_SATURATION:
-		/* 286x chips have a U and V component for saturation */
-		if (is_tw286x(solo_dev, chip_num)) {
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   TW_CHIP_OFFSET_ADDR(chip_num),
-					   TW286x_SATURATIONU_ADDR(ch), val);
-		}
-		tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch),
-			     TW_SATURATION_ADDR(ch), val);
-
-		break;
-
-	case V4L2_CID_CONTRAST:
-		tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch),
-			     TW_CONTRAST_ADDR(ch), val);
-		break;
-
-	case V4L2_CID_BRIGHTNESS:
-		if (is_tw286x(solo_dev, chip_num))
-			sval = val - 128;
-		else
-			sval = (char)val;
-		tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch),
-			     TW_BRIGHTNESS_ADDR(ch), sval);
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
-		      s32 *val)
-{
-	u8 rval, chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	switch (ctrl) {
-	case V4L2_CID_SHARPNESS:
-		/* Only 286x has sharpness */
-		if (is_tw286x(solo_dev, chip_num)) {
-			rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						 TW_CHIP_OFFSET_ADDR(chip_num),
-						 TW286x_SHARPNESS(chip_num));
-			*val = rval & 0x0f;
-		} else
-			*val = 0;
-		break;
-	case V4L2_CID_HUE:
-		rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
-				   TW_HUE_ADDR(ch));
-		if (is_tw286x(solo_dev, chip_num))
-			*val = (s32)((char)rval) + 128;
-		else
-			*val = rval;
-		break;
-	case V4L2_CID_SATURATION:
-		*val = tw_readbyte(solo_dev, chip_num,
-				   TW286x_SATURATIONU_ADDR(ch),
-				   TW_SATURATION_ADDR(ch));
-		break;
-	case V4L2_CID_CONTRAST:
-		*val = tw_readbyte(solo_dev, chip_num,
-				   TW286x_CONTRAST_ADDR(ch),
-				   TW_CONTRAST_ADDR(ch));
-		break;
-	case V4L2_CID_BRIGHTNESS:
-		rval = tw_readbyte(solo_dev, chip_num,
-				   TW286x_BRIGHTNESS_ADDR(ch),
-				   TW_BRIGHTNESS_ADDR(ch));
-		if (is_tw286x(solo_dev, chip_num))
-			*val = (s32)((char)rval) + 128;
-		else
-			*val = rval;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-#if 0
-/*
- * For audio output volume, the output channel is only 1. In this case we
- * don't need to offset TW_CHIP_OFFSET_ADDR. The TW_CHIP_OFFSET_ADDR used
- * is the base address of the techwell chip.
- */
-void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val)
-{
-	unsigned int val;
-	unsigned int chip_num;
-
-	chip_num = (solo_dev->nr_chans - 1) / 4;
-
-	val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
-			  TW_AUDIO_OUTPUT_VOL_ADDR);
-
-	u_val = (val & 0x0f) | (u_val << 4);
-
-	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
-		     TW_AUDIO_OUTPUT_VOL_ADDR, u_val);
-}
-#endif
-
-u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch)
-{
-	u8 val;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	val = tw_readbyte(solo_dev, chip_num,
-			  TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-			  TW_AUDIO_INPUT_GAIN_ADDR(ch));
-
-	return (ch % 2) ? (val >> 4) : (val & 0x0f);
-}
-
-void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val)
-{
-	u8 old_val;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	old_val = tw_readbyte(solo_dev, chip_num,
-			      TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-			      TW_AUDIO_INPUT_GAIN_ADDR(ch));
-
-	val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
-		((ch % 2) ? (val << 4) : val);
-
-	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-		     TW_AUDIO_INPUT_GAIN_ADDR(ch), val);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.h linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.h
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-tw28.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_TW28_H
-#define __SOLO6X10_TW28_H
-
-#include "solo6x10.h"
-
-#define TW_NUM_CHIP				4
-#define TW_BASE_ADDR				0x28
-#define TW_CHIP_OFFSET_ADDR(n)			(TW_BASE_ADDR + (n))
-
-/* tw2815 */
-#define TW_AV_STAT_ADDR				0x5a
-#define TW_HUE_ADDR(n)				(0x07 | ((n) << 4))
-#define TW_SATURATION_ADDR(n)			(0x08 | ((n) << 4))
-#define TW_CONTRAST_ADDR(n)			(0x09 | ((n) << 4))
-#define TW_BRIGHTNESS_ADDR(n)			(0x0a | ((n) << 4))
-#define TW_AUDIO_OUTPUT_VOL_ADDR		0x70
-#define TW_AUDIO_INPUT_GAIN_ADDR(n)		(0x60 + ((n > 1) ? 1 : 0))
-
-/* tw286x */
-#define TW286x_AV_STAT_ADDR			0xfd
-#define TW286x_HUE_ADDR(n)			(0x06 | ((n) << 4))
-#define TW286x_SATURATIONU_ADDR(n)		(0x04 | ((n) << 4))
-#define TW286x_SATURATIONV_ADDR(n)		(0x05 | ((n) << 4))
-#define TW286x_CONTRAST_ADDR(n)			(0x02 | ((n) << 4))
-#define TW286x_BRIGHTNESS_ADDR(n)		(0x01 | ((n) << 4))
-#define TW286x_SHARPNESS(n)			(0x03 | ((n) << 4))
-#define TW286x_AUDIO_OUTPUT_VOL_ADDR		0xdf
-#define TW286x_AUDIO_INPUT_GAIN_ADDR(n)		(0xD0 + ((n > 1) ? 1 : 0))
-
-int solo_tw28_init(struct solo_dev *solo_dev);
-
-int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val);
-int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val);
-bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch);
-
-u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch);
-void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val);
-int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch);
-
-#if 0
-unsigned int tw2815_get_audio_status(struct SOLO *solo);
-void tw2815_Set_AudioOutVol(struct SOLO *solo, unsigned int u_val);
-#endif
-
-#endif /* __SOLO6X10_TW28_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,734 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "solo6x10.h"
-#include "solo6x10-tw28.h"
-
-/* Image size is two fields, SOLO_HW_BPL is one horizontal line in hardware */
-#define SOLO_HW_BPL		2048
-#define solo_vlines(__solo)	(__solo->video_vsize * 2)
-#define solo_image_size(__solo) (solo_bytesperline(__solo) * \
-				 solo_vlines(__solo))
-#define solo_bytesperline(__solo) (__solo->video_hsize * 2)
-
-#define MIN_VID_BUFFERS		2
-
-static inline void erase_on(struct solo_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
-	solo_dev->erasing = 1;
-	solo_dev->frame_blank = 0;
-}
-
-static inline int erase_off(struct solo_dev *solo_dev)
-{
-	if (!solo_dev->erasing)
-		return 0;
-
-	/* First time around, assert erase off */
-	if (!solo_dev->frame_blank)
-		solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0);
-	/* Keep the erasing flag on for 8 frames minimum */
-	if (solo_dev->frame_blank++ >= 8)
-		solo_dev->erasing = 0;
-
-	return 1;
-}
-
-void solo_video_in_isr(struct solo_dev *solo_dev)
-{
-	wake_up_interruptible_all(&solo_dev->disp_thread_wait);
-}
-
-static void solo_win_setup(struct solo_dev *solo_dev, u8 ch,
-			   int sx, int sy, int ex, int ey, int scale)
-{
-	if (ch >= solo_dev->nr_chans)
-		return;
-
-	/* Here, we just keep window/channel the same */
-	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch),
-		       SOLO_VI_WIN_CHANNEL(ch) |
-		       SOLO_VI_WIN_SX(sx) |
-		       SOLO_VI_WIN_EX(ex) |
-		       SOLO_VI_WIN_SCALE(scale));
-
-	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch),
-		       SOLO_VI_WIN_SY(sy) |
-		       SOLO_VI_WIN_EY(ey));
-}
-
-static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
-{
-	u8 ch = idx * 4;
-
-	if (ch >= solo_dev->nr_chans)
-		return -EINVAL;
-
-	if (!on) {
-		u8 i;
-		for (i = ch; i < ch + 4; i++)
-			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
-				       solo_vlines(solo_dev),
-				       solo_dev->video_hsize,
-				       solo_vlines(solo_dev), 0);
-		return 0;
-	}
-
-	/* Row 1 */
-	solo_win_setup(solo_dev, ch, 0, 0, solo_dev->video_hsize / 2,
-		       solo_vlines(solo_dev) / 2, 3);
-	solo_win_setup(solo_dev, ch + 1, solo_dev->video_hsize / 2, 0,
-		       solo_dev->video_hsize, solo_vlines(solo_dev) / 2, 3);
-	/* Row 2 */
-	solo_win_setup(solo_dev, ch + 2, 0, solo_vlines(solo_dev) / 2,
-		       solo_dev->video_hsize / 2, solo_vlines(solo_dev), 3);
-	solo_win_setup(solo_dev, ch + 3, solo_dev->video_hsize / 2,
-		       solo_vlines(solo_dev) / 2, solo_dev->video_hsize,
-		       solo_vlines(solo_dev), 3);
-
-	return 0;
-}
-
-static int solo_v4l2_ch_ext_16up(struct solo_dev *solo_dev, int on)
-{
-	int sy, ysize, hsize, i;
-
-	if (!on) {
-		for (i = 0; i < 16; i++)
-			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
-				       solo_vlines(solo_dev),
-				       solo_dev->video_hsize,
-				       solo_vlines(solo_dev), 0);
-		return 0;
-	}
-
-	ysize = solo_vlines(solo_dev) / 4;
-	hsize = solo_dev->video_hsize / 4;
-
-	for (sy = 0, i = 0; i < 4; i++, sy += ysize) {
-		solo_win_setup(solo_dev, i * 4, 0, sy, hsize,
-			       sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 1, hsize, sy,
-			       hsize * 2, sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 2, hsize * 2, sy,
-			       hsize * 3, sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 3, hsize * 3, sy,
-			       solo_dev->video_hsize, sy + ysize, 5);
-	}
-
-	return 0;
-}
-
-static int solo_v4l2_ch(struct solo_dev *solo_dev, u8 ch, int on)
-{
-	u8 ext_ch;
-
-	if (ch < solo_dev->nr_chans) {
-		solo_win_setup(solo_dev, ch, on ? 0 : solo_dev->video_hsize,
-			       on ? 0 : solo_vlines(solo_dev),
-			       solo_dev->video_hsize, solo_vlines(solo_dev),
-			       on ? 1 : 0);
-		return 0;
-	}
-
-	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
-		return -EINVAL;
-
-	ext_ch = ch - solo_dev->nr_chans;
-
-	/* 4up's first */
-	if (ext_ch < 4)
-		return solo_v4l2_ch_ext_4up(solo_dev, ext_ch, on);
-
-	/* Remaining case is 16up for 16-port */
-	return solo_v4l2_ch_ext_16up(solo_dev, on);
-}
-
-static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
-{
-	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
-		return -EINVAL;
-
-	erase_on(solo_dev);
-
-	solo_v4l2_ch(solo_dev, solo_dev->cur_disp_ch, 0);
-	solo_v4l2_ch(solo_dev, ch, 1);
-
-	solo_dev->cur_disp_ch = ch;
-
-	return 0;
-}
-
-static void solo_fillbuf(struct solo_dev *solo_dev,
-			 struct vb2_buffer *vb)
-{
-	dma_addr_t vbuf;
-	unsigned int fdma_addr;
-	int error = -1;
-	int i;
-
-	vbuf = vb2_dma_contig_plane_dma_addr(vb, 0);
-	if (!vbuf)
-		goto finish_buf;
-
-	if (erase_off(solo_dev)) {
-		void *p = vb2_plane_vaddr(vb, 0);
-		int image_size = solo_image_size(solo_dev);
-		for (i = 0; i < image_size; i += 2) {
-			((u8 *)p)[i] = 0x80;
-			((u8 *)p)[i + 1] = 0x00;
-		}
-		error = 0;
-	} else {
-		fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
-				(SOLO_HW_BPL * solo_vlines(solo_dev)));
-
-		error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
-				       solo_bytesperline(solo_dev),
-				       solo_vlines(solo_dev), SOLO_HW_BPL);
-	}
-
-finish_buf:
-	if (!error) {
-		vb2_set_plane_payload(vb, 0,
-			solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
-		vb->v4l2_buf.sequence = solo_dev->sequence++;
-		v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
-	}
-
-	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-}
-
-static void solo_thread_try(struct solo_dev *solo_dev)
-{
-	struct solo_vb2_buf *vb;
-
-	/* Only "break" from this loop if slock is held, otherwise
-	 * just return. */
-	for (;;) {
-		unsigned int cur_write;
-
-		cur_write = SOLO_VI_STATUS0_PAGE(
-			solo_reg_read(solo_dev, SOLO_VI_STATUS0));
-		if (cur_write == solo_dev->old_write)
-			return;
-
-		spin_lock(&solo_dev->slock);
-
-		if (list_empty(&solo_dev->vidq_active))
-			break;
-
-		vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf,
-				      list);
-
-		solo_dev->old_write = cur_write;
-		list_del(&vb->list);
-
-		spin_unlock(&solo_dev->slock);
-
-		solo_fillbuf(solo_dev, &vb->vb);
-	}
-
-	assert_spin_locked(&solo_dev->slock);
-	spin_unlock(&solo_dev->slock);
-}
-
-static int solo_thread(void *data)
-{
-	struct solo_dev *solo_dev = data;
-	DECLARE_WAITQUEUE(wait, current);
-
-	set_freezable();
-	add_wait_queue(&solo_dev->disp_thread_wait, &wait);
-
-	for (;;) {
-		long timeout = schedule_timeout_interruptible(HZ);
-		if (timeout == -ERESTARTSYS || kthread_should_stop())
-			break;
-		solo_thread_try(solo_dev);
-		try_to_freeze();
-	}
-
-	remove_wait_queue(&solo_dev->disp_thread_wait, &wait);
-
-	return 0;
-}
-
-static int solo_start_thread(struct solo_dev *solo_dev)
-{
-	int ret = 0;
-
-	solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp");
-
-	if (IS_ERR(solo_dev->kthread)) {
-		ret = PTR_ERR(solo_dev->kthread);
-		solo_dev->kthread = NULL;
-		return ret;
-	}
-	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
-
-	return ret;
-}
-
-static void solo_stop_thread(struct solo_dev *solo_dev)
-{
-	if (!solo_dev->kthread)
-		return;
-
-	solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN);
-	kthread_stop(solo_dev->kthread);
-	solo_dev->kthread = NULL;
-}
-
-static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
-
-	sizes[0] = solo_image_size(solo_dev);
-	alloc_ctxs[0] = solo_dev->alloc_ctx;
-	*num_planes = 1;
-
-	if (*num_buffers < MIN_VID_BUFFERS)
-		*num_buffers = MIN_VID_BUFFERS;
-
-	return 0;
-}
-
-static int solo_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
-
-	solo_dev->sequence = 0;
-	return solo_start_thread(solo_dev);
-}
-
-static void solo_stop_streaming(struct vb2_queue *q)
-{
-	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
-
-	solo_stop_thread(solo_dev);
-	INIT_LIST_HEAD(&solo_dev->vidq_active);
-}
-
-static void solo_buf_queue(struct vb2_buffer *vb)
-{
-	struct vb2_queue *vq = vb->vb2_queue;
-	struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
-	struct solo_vb2_buf *solo_vb =
-		container_of(vb, struct solo_vb2_buf, vb);
-
-	spin_lock(&solo_dev->slock);
-	list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
-	spin_unlock(&solo_dev->slock);
-	wake_up_interruptible(&solo_dev->disp_thread_wait);
-}
-
-static const struct vb2_ops solo_video_qops = {
-	.queue_setup	= solo_queue_setup,
-	.buf_queue	= solo_buf_queue,
-	.start_streaming = solo_start_streaming,
-	.stop_streaming = solo_stop_streaming,
-	.wait_prepare	= vb2_ops_wait_prepare,
-	.wait_finish	= vb2_ops_wait_finish,
-};
-
-static int solo_querycap(struct file *file, void  *priv,
-			 struct v4l2_capability *cap)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	strcpy(cap->driver, SOLO6X10_NAME);
-	strcpy(cap->card, "Softlogic 6x10");
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-		 pci_name(solo_dev->pdev));
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int solo_enum_ext_input(struct solo_dev *solo_dev,
-			       struct v4l2_input *input)
-{
-	static const char * const dispnames_1[] = { "4UP" };
-	static const char * const dispnames_2[] = { "4UP-1", "4UP-2" };
-	static const char * const dispnames_5[] = {
-		"4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
-	};
-	const char * const *dispnames;
-
-	if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
-		return -EINVAL;
-
-	if (solo_dev->nr_ext == 5)
-		dispnames = dispnames_5;
-	else if (solo_dev->nr_ext == 2)
-		dispnames = dispnames_2;
-	else
-		dispnames = dispnames_1;
-
-	snprintf(input->name, sizeof(input->name), "Multi %s",
-		 dispnames[input->index - solo_dev->nr_chans]);
-
-	return 0;
-}
-
-static int solo_enum_input(struct file *file, void *priv,
-			   struct v4l2_input *input)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	if (input->index >= solo_dev->nr_chans) {
-		int ret = solo_enum_ext_input(solo_dev, input);
-		if (ret < 0)
-			return ret;
-	} else {
-		snprintf(input->name, sizeof(input->name), "Camera %d",
-			 input->index + 1);
-
-		/* We can only check this for normal inputs */
-		if (!tw28_get_video_status(solo_dev, input->index))
-			input->status = V4L2_IN_ST_NO_SIGNAL;
-	}
-
-	input->type = V4L2_INPUT_TYPE_CAMERA;
-	input->std = solo_dev->vfd->tvnorms;
-	return 0;
-}
-
-static int solo_set_input(struct file *file, void *priv, unsigned int index)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	int ret = solo_v4l2_set_ch(solo_dev, index);
-
-	if (!ret) {
-		while (erase_off(solo_dev))
-			/* Do nothing */;
-	}
-
-	return ret;
-}
-
-static int solo_get_input(struct file *file, void *priv, unsigned int *index)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	*index = solo_dev->cur_disp_ch;
-
-	return 0;
-}
-
-static int solo_enum_fmt_cap(struct file *file, void *priv,
-			     struct v4l2_fmtdesc *f)
-{
-	if (f->index)
-		return -EINVAL;
-
-	f->pixelformat = V4L2_PIX_FMT_UYVY;
-	strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
-
-	return 0;
-}
-
-static int solo_try_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int image_size = solo_image_size(solo_dev);
-
-	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
-		return -EINVAL;
-
-	pix->width = solo_dev->video_hsize;
-	pix->height = solo_vlines(solo_dev);
-	pix->sizeimage = image_size;
-	pix->field = V4L2_FIELD_INTERLACED;
-	pix->pixelformat = V4L2_PIX_FMT_UYVY;
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->priv = 0;
-	return 0;
-}
-
-static int solo_set_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	if (vb2_is_busy(&solo_dev->vidq))
-		return -EBUSY;
-
-	/* For right now, if it doesn't match our running config,
-	 * then fail */
-	return solo_try_fmt_cap(file, priv, f);
-}
-
-static int solo_get_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	pix->width = solo_dev->video_hsize;
-	pix->height = solo_vlines(solo_dev);
-	pix->pixelformat = V4L2_PIX_FMT_UYVY;
-	pix->field = V4L2_FIELD_INTERLACED;
-	pix->sizeimage = solo_image_size(solo_dev);
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->bytesperline = solo_bytesperline(solo_dev);
-	pix->priv = 0;
-
-	return 0;
-}
-
-static int solo_g_std(struct file *file, void *priv, v4l2_std_id *i)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		*i = V4L2_STD_NTSC_M;
-	else
-		*i = V4L2_STD_PAL;
-	return 0;
-}
-
-int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz)
-{
-	int i;
-
-	/* Make sure all video nodes are idle */
-	if (vb2_is_busy(&solo_dev->vidq))
-		return -EBUSY;
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		if (vb2_is_busy(&solo_dev->v4l2_enc[i]->vidq))
-			return -EBUSY;
-	solo_dev->video_type = is_50hz ? SOLO_VO_FMT_TYPE_PAL :
-					 SOLO_VO_FMT_TYPE_NTSC;
-	/* Reconfigure for the new standard */
-	solo_disp_init(solo_dev);
-	solo_enc_init(solo_dev);
-	solo_tw28_init(solo_dev);
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_update_mode(solo_dev->v4l2_enc[i]);
-	return solo_v4l2_set_ch(solo_dev, solo_dev->cur_disp_ch);
-}
-
-static int solo_s_std(struct file *file, void *priv, v4l2_std_id std)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return solo_set_video_type(solo_dev, std & V4L2_STD_625_50);
-}
-
-static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct solo_dev *solo_dev =
-		container_of(ctrl->handler, struct solo_dev, disp_hdl);
-
-	switch (ctrl->id) {
-	case V4L2_CID_MOTION_TRACE:
-		if (ctrl->val) {
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
-					SOLO_VI_MOTION_Y_ADD |
-					SOLO_VI_MOTION_Y_VALUE(0x20) |
-					SOLO_VI_MOTION_CB_VALUE(0x10) |
-					SOLO_VI_MOTION_CR_VALUE(0x10));
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
-					SOLO_VI_MOTION_CR_ADD |
-					SOLO_VI_MOTION_Y_VALUE(0x10) |
-					SOLO_VI_MOTION_CB_VALUE(0x80) |
-					SOLO_VI_MOTION_CR_VALUE(0x10));
-		} else {
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
-		}
-		return 0;
-	default:
-		break;
-	}
-	return -EINVAL;
-}
-
-static const struct v4l2_file_operations solo_v4l2_fops = {
-	.owner			= THIS_MODULE,
-	.open			= v4l2_fh_open,
-	.release		= vb2_fop_release,
-	.read			= vb2_fop_read,
-	.poll			= vb2_fop_poll,
-	.mmap			= vb2_fop_mmap,
-	.unlocked_ioctl		= video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
-	.vidioc_querycap		= solo_querycap,
-	.vidioc_s_std			= solo_s_std,
-	.vidioc_g_std			= solo_g_std,
-	/* Input callbacks */
-	.vidioc_enum_input		= solo_enum_input,
-	.vidioc_s_input			= solo_set_input,
-	.vidioc_g_input			= solo_get_input,
-	/* Video capture format callbacks */
-	.vidioc_enum_fmt_vid_cap	= solo_enum_fmt_cap,
-	.vidioc_try_fmt_vid_cap		= solo_try_fmt_cap,
-	.vidioc_s_fmt_vid_cap		= solo_set_fmt_cap,
-	.vidioc_g_fmt_vid_cap		= solo_get_fmt_cap,
-	/* Streaming I/O */
-	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
-	.vidioc_querybuf		= vb2_ioctl_querybuf,
-	.vidioc_qbuf			= vb2_ioctl_qbuf,
-	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
-	.vidioc_streamon		= vb2_ioctl_streamon,
-	.vidioc_streamoff		= vb2_ioctl_streamoff,
-	/* Logging and events */
-	.vidioc_log_status		= v4l2_ctrl_log_status,
-	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
-};
-
-static struct video_device solo_v4l2_template = {
-	.name			= SOLO6X10_NAME,
-	.fops			= &solo_v4l2_fops,
-	.ioctl_ops		= &solo_v4l2_ioctl_ops,
-	.minor			= -1,
-	.release		= video_device_release,
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
-};
-
-static const struct v4l2_ctrl_ops solo_ctrl_ops = {
-	.s_ctrl = solo_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config solo_motion_trace_ctrl = {
-	.ops = &solo_ctrl_ops,
-	.id = V4L2_CID_MOTION_TRACE,
-	.name = "Motion Detection Trace",
-	.type = V4L2_CTRL_TYPE_BOOLEAN,
-	.max = 1,
-	.step = 1,
-};
-
-int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
-{
-	int ret;
-	int i;
-
-	init_waitqueue_head(&solo_dev->disp_thread_wait);
-	spin_lock_init(&solo_dev->slock);
-	mutex_init(&solo_dev->lock);
-	INIT_LIST_HEAD(&solo_dev->vidq_active);
-
-	solo_dev->vfd = video_device_alloc();
-	if (!solo_dev->vfd)
-		return -ENOMEM;
-
-	*solo_dev->vfd = solo_v4l2_template;
-	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
-	solo_dev->vfd->queue = &solo_dev->vidq;
-	solo_dev->vfd->lock = &solo_dev->lock;
-	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
-	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
-	if (solo_dev->disp_hdl.error) {
-		ret = solo_dev->disp_hdl.error;
-		goto fail;
-	}
-	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
-	set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
-
-	video_set_drvdata(solo_dev->vfd, solo_dev);
-
-	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	solo_dev->vidq.ops = &solo_video_qops;
-	solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
-	solo_dev->vidq.drv_priv = solo_dev;
-	solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	solo_dev->vidq.gfp_flags = __GFP_DMA32;
-	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
-	solo_dev->vidq.lock = &solo_dev->lock;
-	ret = vb2_queue_init(&solo_dev->vidq);
-	if (ret < 0)
-		goto fail;
-
-	solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
-	if (IS_ERR(solo_dev->alloc_ctx)) {
-		dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
-		return PTR_ERR(solo_dev->alloc_ctx);
-	}
-
-	/* Cycle all the channels and clear */
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_v4l2_set_ch(solo_dev, i);
-		while (erase_off(solo_dev))
-			/* Do nothing */;
-	}
-
-	/* Set the default display channel */
-	solo_v4l2_set_ch(solo_dev, 0);
-	while (erase_off(solo_dev))
-		/* Do nothing */;
-
-	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
-	if (ret < 0)
-		goto fail;
-
-	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,
-		 solo_dev->nr_chans, solo_dev->nr_ext);
-
-	return 0;
-
-fail:
-	video_device_release(solo_dev->vfd);
-	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
-	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
-	solo_dev->vfd = NULL;
-	return ret;
-}
-
-void solo_v4l2_exit(struct solo_dev *solo_dev)
-{
-	if (solo_dev->vfd == NULL)
-		return;
-
-	video_unregister_device(solo_dev->vfd);
-	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
-	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
-	solo_dev->vfd = NULL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1414 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
- *
- * Original author:
- * Ben Collins <bcollins@ubuntu.com>
- *
- * Additional work by:
- * John Brooks <john.brooks@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-dma-sg.h>
-
-#include "solo6x10.h"
-#include "solo6x10-tw28.h"
-#include "solo6x10-jpeg.h"
-
-#define MIN_VID_BUFFERS		2
-#define FRAME_BUF_SIZE		(196 * 1024)
-#define MP4_QS			16
-#define DMA_ALIGN		4096
-
-/* 6010 M4V */
-static unsigned char vop_6010_ntsc_d1[] = {
-	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
-	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
-	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
-	0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
-};
-
-static unsigned char vop_6010_ntsc_cif[] = {
-	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
-	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
-	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
-	0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
-};
-
-static unsigned char vop_6010_pal_d1[] = {
-	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
-	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
-	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
-	0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
-};
-
-static unsigned char vop_6010_pal_cif[] = {
-	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
-	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
-	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
-	0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
-};
-
-/* 6110 h.264 */
-static unsigned char vop_6110_ntsc_d1[] = {
-	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
-	0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
-	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
-};
-
-static unsigned char vop_6110_ntsc_cif[] = {
-	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
-	0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
-	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
-};
-
-static unsigned char vop_6110_pal_d1[] = {
-	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
-	0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
-	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
-};
-
-static unsigned char vop_6110_pal_cif[] = {
-	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
-	0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
-	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
-};
-
-typedef __le32 vop_header[16];
-
-struct solo_enc_buf {
-	enum solo_enc_types	type;
-	const vop_header	*vh;
-	int			motion;
-};
-
-static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	return (solo_dev->motion_mask >> solo_enc->ch) & 1;
-}
-
-static int solo_motion_detected(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	unsigned long flags;
-	u32 ch_mask = 1 << solo_enc->ch;
-	int ret = 0;
-
-	spin_lock_irqsave(&solo_enc->motion_lock, flags);
-	if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
-		solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
-
-	return ret;
-}
-
-static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	u32 mask = 1 << solo_enc->ch;
-	unsigned long flags;
-
-	spin_lock_irqsave(&solo_enc->motion_lock, flags);
-
-	if (on)
-		solo_dev->motion_mask |= mask;
-	else
-		solo_dev->motion_mask &= ~mask;
-
-	solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
-
-	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
-		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
-		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
-
-	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
-}
-
-void solo_update_mode(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	int vop_len;
-	unsigned char *vop;
-
-	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
-	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
-
-	if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
-		solo_enc->width = solo_dev->video_hsize >> 1;
-		solo_enc->height = solo_dev->video_vsize;
-		if (solo_dev->type == SOLO_DEV_6110) {
-			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-				vop = vop_6110_ntsc_cif;
-				vop_len = sizeof(vop_6110_ntsc_cif);
-			} else {
-				vop = vop_6110_pal_cif;
-				vop_len = sizeof(vop_6110_pal_cif);
-			}
-		} else {
-			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-				vop = vop_6010_ntsc_cif;
-				vop_len = sizeof(vop_6010_ntsc_cif);
-			} else {
-				vop = vop_6010_pal_cif;
-				vop_len = sizeof(vop_6010_pal_cif);
-			}
-		}
-	} else {
-		solo_enc->width = solo_dev->video_hsize;
-		solo_enc->height = solo_dev->video_vsize << 1;
-		solo_enc->bw_weight <<= 2;
-		if (solo_dev->type == SOLO_DEV_6110) {
-			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-				vop = vop_6110_ntsc_d1;
-				vop_len = sizeof(vop_6110_ntsc_d1);
-			} else {
-				vop = vop_6110_pal_d1;
-				vop_len = sizeof(vop_6110_pal_d1);
-			}
-		} else {
-			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-				vop = vop_6010_ntsc_d1;
-				vop_len = sizeof(vop_6010_ntsc_d1);
-			} else {
-				vop = vop_6010_pal_d1;
-				vop_len = sizeof(vop_6010_pal_d1);
-			}
-		}
-	}
-
-	memcpy(solo_enc->vop, vop, vop_len);
-
-	/* Some fixups for 6010/M4V */
-	if (solo_dev->type == SOLO_DEV_6010) {
-		u16 fps = solo_dev->fps * 1000;
-		u16 interval = solo_enc->interval * 1000;
-
-		vop = solo_enc->vop;
-
-		/* Frame rate and interval */
-		vop[22] = fps >> 4;
-		vop[23] = ((fps << 4) & 0xf0) | 0x0c
-			| ((interval >> 13) & 0x3);
-		vop[24] = (interval >> 5) & 0xff;
-		vop[25] = ((interval << 3) & 0xf8) | 0x04;
-	}
-
-	solo_enc->vop_len = vop_len;
-
-	/* Now handle the jpeg header */
-	vop = solo_enc->jpeg_header;
-	vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
-	vop[SOF0_START + 6] = 0xff & solo_enc->height;
-	vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
-	vop[SOF0_START + 8] = 0xff & solo_enc->width;
-
-	memcpy(vop + DQT_START,
-	       jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
-}
-
-static int solo_enc_on(struct solo_enc_dev *solo_enc)
-{
-	u8 ch = solo_enc->ch;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	u8 interval;
-
-	solo_update_mode(solo_enc);
-
-	/* Make sure to do a bandwidth check */
-	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
-		return -EBUSY;
-	solo_enc->sequence = 0;
-	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
-
-	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
-
-	/* Disable all encoding for this channel */
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
-
-	/* Common for both std and ext encoding */
-	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
-		       solo_enc->interlaced ? 1 : 0);
-
-	if (solo_enc->interlaced)
-		interval = solo_enc->interval - 1;
-	else
-		interval = solo_enc->interval;
-
-	/* Standard encoding only */
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
-	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
-
-	/* Extended encoding only */
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
-	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
-
-	/* Enables the standard encoder */
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
-
-	return 0;
-}
-
-static void solo_enc_off(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	solo_dev->enc_bw_remain += solo_enc->bw_weight;
-
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
-}
-
-static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
-			      unsigned int off, unsigned int size)
-{
-	int ret;
-
-	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
-		return -EINVAL;
-
-	/* Single shot */
-	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
-		return solo_p2m_dma_t(solo_dev, 0, dma,
-				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
-				      0, 0);
-	}
-
-	/* Buffer wrap */
-	ret = solo_p2m_dma_t(solo_dev, 0, dma,
-			     SOLO_MP4E_EXT_ADDR(solo_dev) + off,
-			     SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
-
-	if (!ret) {
-		ret = solo_p2m_dma_t(solo_dev, 0,
-			     dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
-			     SOLO_MP4E_EXT_ADDR(solo_dev),
-			     size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
-	}
-
-	return ret;
-}
-
-/* Build a descriptor queue out of an SG list and send it to the P2M for
- * processing. */
-static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
-			  struct sg_table *vbuf, int off, int size,
-			  unsigned int base, unsigned int base_size)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct scatterlist *sg;
-	int i;
-	int ret;
-
-	if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
-		return -EINVAL;
-
-	solo_enc->desc_count = 1;
-
-	for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
-		struct solo_p2m_desc *desc;
-		dma_addr_t dma;
-		int len;
-		int left = base_size - off;
-
-		desc = &solo_enc->desc_items[solo_enc->desc_count++];
-		dma = sg_dma_address(sg);
-		len = sg_dma_len(sg);
-
-		/* We assume this is smaller than the scatter size */
-		BUG_ON(skip >= len);
-		if (skip) {
-			len -= skip;
-			dma += skip;
-			size -= skip;
-			skip = 0;
-		}
-
-		len = min(len, size);
-
-		if (len <= left) {
-			/* Single descriptor */
-			solo_p2m_fill_desc(desc, 0, dma, base + off,
-					   len, 0, 0);
-		} else {
-			/* Buffer wrap */
-			/* XXX: Do these as separate DMA requests, to avoid
-			   timeout errors triggered by awkwardly sized
-			   descriptors. See
-			   <https://github.com/bluecherrydvr/solo6x10/issues/8>
-			 */
-			ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
-					     left, 0, 0);
-			if (ret)
-				return ret;
-
-			ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
-					     len - left, 0, 0);
-			if (ret)
-				return ret;
-
-			solo_enc->desc_count--;
-		}
-
-		size -= len;
-		if (size <= 0)
-			break;
-
-		off += len;
-		if (off >= base_size)
-			off -= base_size;
-
-		/* Because we may use two descriptors per loop */
-		if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
-			ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
-						solo_enc->desc_dma,
-						solo_enc->desc_count - 1);
-			if (ret)
-				return ret;
-			solo_enc->desc_count = 1;
-		}
-	}
-
-	if (solo_enc->desc_count <= 1)
-		return 0;
-
-	return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
-			solo_enc->desc_dma, solo_enc->desc_count - 1);
-}
-
-/* Extract values from VOP header - VE_STATUSxx */
-static inline int vop_interlaced(const vop_header *vh)
-{
-	return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
-}
-
-static inline u8 vop_channel(const vop_header *vh)
-{
-	return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
-}
-
-static inline u8 vop_type(const vop_header *vh)
-{
-	return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
-}
-
-static inline u32 vop_mpeg_size(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
-}
-
-static inline u8 vop_hsize(const vop_header *vh)
-{
-	return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
-}
-
-static inline u8 vop_vsize(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[1]) & 0xFF;
-}
-
-static inline u32 vop_mpeg_offset(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[2]);
-}
-
-static inline u32 vop_jpeg_offset(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[3]);
-}
-
-static inline u32 vop_jpeg_size(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
-}
-
-static inline u32 vop_sec(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[5]);
-}
-
-static inline u32 vop_usec(const vop_header *vh)
-{
-	return __le32_to_cpu((*vh)[6]);
-}
-
-static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
-			  struct vb2_buffer *vb, const vop_header *vh)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
-	int frame_size;
-	int ret;
-
-	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
-
-	if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
-		return -EIO;
-
-	frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
-	vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
-
-	/* may discard all previous data in vbuf->sgl */
-	dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
-			     vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
-			     frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
-			     SOLO_JPEG_EXT_SIZE(solo_dev));
-	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-
-	/* add the header only after dma_unmap_sg() */
-	sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-			    solo_enc->jpeg_header, solo_enc->jpeg_len);
-
-	return ret;
-}
-
-static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
-		struct vb2_buffer *vb, const vop_header *vh)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
-	int frame_off, frame_size;
-	int skip = 0;
-	int ret;
-
-	if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
-		return -EIO;
-
-	/* If this is a key frame, add extra header */
-	vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
-		V4L2_BUF_FLAG_BFRAME);
-	if (!vop_type(vh)) {
-		skip = solo_enc->vop_len;
-		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
-		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
-			solo_enc->vop_len);
-	} else {
-		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
-		vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
-	}
-
-	/* Now get the actual mpeg payload */
-	frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
-		sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
-	frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
-
-	/* may discard all previous data in vbuf->sgl */
-	dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
-			SOLO_MP4E_EXT_ADDR(solo_dev),
-			SOLO_MP4E_EXT_SIZE(solo_dev));
-	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-
-	/* add the header only after dma_unmap_sg() */
-	if (!vop_type(vh))
-		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-				    solo_enc->vop, solo_enc->vop_len);
-	return ret;
-}
-
-static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
-			    struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
-{
-	const vop_header *vh = enc_buf->vh;
-	int ret;
-
-	/* Check for motion flags */
-	vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON |
-				V4L2_BUF_FLAG_MOTION_DETECTED);
-	if (solo_is_motion_on(solo_enc)) {
-		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON;
-		if (enc_buf->motion)
-			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
-	}
-
-	switch (solo_enc->fmt) {
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_H264:
-		ret = solo_fill_mpeg(solo_enc, vb, vh);
-		break;
-	default: /* V4L2_PIX_FMT_MJPEG */
-		ret = solo_fill_jpeg(solo_enc, vb, vh);
-		break;
-	}
-
-	if (!ret) {
-		vb->v4l2_buf.sequence = solo_enc->sequence++;
-		vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
-		vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
-	}
-
-	vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-
-	return ret;
-}
-
-static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
-				struct solo_enc_buf *enc_buf)
-{
-	struct solo_vb2_buf *vb;
-	unsigned long flags;
-
-	mutex_lock(&solo_enc->lock);
-	if (solo_enc->type != enc_buf->type)
-		goto unlock;
-
-	spin_lock_irqsave(&solo_enc->av_lock, flags);
-	if (list_empty(&solo_enc->vidq_active)) {
-		spin_unlock_irqrestore(&solo_enc->av_lock, flags);
-		goto unlock;
-	}
-	vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
-		list);
-	list_del(&vb->list);
-	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
-
-	solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
-unlock:
-	mutex_unlock(&solo_enc->lock);
-}
-
-void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
-{
-	wake_up_interruptible_all(&solo_dev->ring_thread_wait);
-}
-
-static void solo_handle_ring(struct solo_dev *solo_dev)
-{
-	for (;;) {
-		struct solo_enc_dev *solo_enc;
-		struct solo_enc_buf enc_buf;
-		u32 mpeg_current, off;
-		u8 ch;
-		u8 cur_q;
-
-		/* Check if the hardware has any new ones in the queue */
-		cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
-		if (cur_q == solo_dev->enc_idx)
-			break;
-
-		mpeg_current = solo_reg_read(solo_dev,
-					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
-		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
-
-		ch = (mpeg_current >> 24) & 0x1f;
-		off = mpeg_current & 0x00ffffff;
-
-		if (ch >= SOLO_MAX_CHANNELS) {
-			ch -= SOLO_MAX_CHANNELS;
-			enc_buf.type = SOLO_ENC_TYPE_EXT;
-		} else
-			enc_buf.type = SOLO_ENC_TYPE_STD;
-
-		solo_enc = solo_dev->v4l2_enc[ch];
-		if (solo_enc == NULL) {
-			dev_err(&solo_dev->pdev->dev,
-				"Got spurious packet for channel %d\n", ch);
-			continue;
-		}
-
-		/* FAIL... */
-		if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
-				     sizeof(vop_header)))
-			continue;
-
-		enc_buf.vh = solo_dev->vh_buf;
-
-		/* Sanity check */
-		if (vop_mpeg_offset(enc_buf.vh) !=
-			SOLO_MP4E_EXT_ADDR(solo_dev) + off)
-			continue;
-
-		if (solo_motion_detected(solo_enc))
-			enc_buf.motion = 1;
-		else
-			enc_buf.motion = 0;
-
-		solo_enc_handle_one(solo_enc, &enc_buf);
-	}
-}
-
-static int solo_ring_thread(void *data)
-{
-	struct solo_dev *solo_dev = data;
-	DECLARE_WAITQUEUE(wait, current);
-
-	set_freezable();
-	add_wait_queue(&solo_dev->ring_thread_wait, &wait);
-
-	for (;;) {
-		long timeout = schedule_timeout_interruptible(HZ);
-		if (timeout == -ERESTARTSYS || kthread_should_stop())
-			break;
-		solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
-		solo_handle_ring(solo_dev);
-		solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
-		try_to_freeze();
-	}
-
-	remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
-
-	return 0;
-}
-
-static int solo_enc_queue_setup(struct vb2_queue *q,
-				const struct v4l2_format *fmt,
-				unsigned int *num_buffers,
-				unsigned int *num_planes, unsigned int sizes[],
-				void *alloc_ctxs[])
-{
-	sizes[0] = FRAME_BUF_SIZE;
-	*num_planes = 1;
-
-	if (*num_buffers < MIN_VID_BUFFERS)
-		*num_buffers = MIN_VID_BUFFERS;
-
-	return 0;
-}
-
-static void solo_enc_buf_queue(struct vb2_buffer *vb)
-{
-	struct vb2_queue *vq = vb->vb2_queue;
-	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
-	struct solo_vb2_buf *solo_vb =
-		container_of(vb, struct solo_vb2_buf, vb);
-
-	spin_lock(&solo_enc->av_lock);
-	list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
-	spin_unlock(&solo_enc->av_lock);
-}
-
-static int solo_ring_start(struct solo_dev *solo_dev)
-{
-	solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
-					    SOLO6X10_NAME "_ring");
-	if (IS_ERR(solo_dev->ring_thread)) {
-		int err = PTR_ERR(solo_dev->ring_thread);
-		solo_dev->ring_thread = NULL;
-		return err;
-	}
-
-	solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
-
-	return 0;
-}
-
-static void solo_ring_stop(struct solo_dev *solo_dev)
-{
-	if (solo_dev->ring_thread) {
-		kthread_stop(solo_dev->ring_thread);
-		solo_dev->ring_thread = NULL;
-	}
-
-	solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
-}
-
-static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-	int ret;
-
-	ret = solo_enc_on(solo_enc);
-	if (ret)
-		return ret;
-	return solo_ring_start(solo_enc->solo_dev);
-}
-
-static void solo_enc_stop_streaming(struct vb2_queue *q)
-{
-	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-
-	solo_enc_off(solo_enc);
-	INIT_LIST_HEAD(&solo_enc->vidq_active);
-	solo_ring_stop(solo_enc->solo_dev);
-}
-
-static struct vb2_ops solo_enc_video_qops = {
-	.queue_setup	= solo_enc_queue_setup,
-	.buf_queue	= solo_enc_buf_queue,
-	.start_streaming = solo_enc_start_streaming,
-	.stop_streaming = solo_enc_stop_streaming,
-	.wait_prepare	= vb2_ops_wait_prepare,
-	.wait_finish	= vb2_ops_wait_finish,
-};
-
-static int solo_enc_querycap(struct file *file, void  *priv,
-			     struct v4l2_capability *cap)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	strcpy(cap->driver, SOLO6X10_NAME);
-	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
-		 solo_enc->ch);
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-		 pci_name(solo_dev->pdev));
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int solo_enc_enum_input(struct file *file, void *priv,
-			       struct v4l2_input *input)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (input->index)
-		return -EINVAL;
-
-	snprintf(input->name, sizeof(input->name), "Encoder %d",
-		 solo_enc->ch + 1);
-	input->type = V4L2_INPUT_TYPE_CAMERA;
-	input->std = solo_enc->vfd->tvnorms;
-
-	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
-		input->status = V4L2_IN_ST_NO_SIGNAL;
-
-	return 0;
-}
-
-static int solo_enc_set_input(struct file *file, void *priv,
-			      unsigned int index)
-{
-	if (index)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int solo_enc_get_input(struct file *file, void *priv,
-			      unsigned int *index)
-{
-	*index = 0;
-
-	return 0;
-}
-
-static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
-				 struct v4l2_fmtdesc *f)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	int dev_type = solo_enc->solo_dev->type;
-
-	switch (f->index) {
-	case 0:
-		switch (dev_type) {
-		case SOLO_DEV_6010:
-			f->pixelformat = V4L2_PIX_FMT_MPEG4;
-			strcpy(f->description, "MPEG-4 part 2");
-			break;
-		case SOLO_DEV_6110:
-			f->pixelformat = V4L2_PIX_FMT_H264;
-			strcpy(f->description, "H.264");
-			break;
-		}
-		break;
-	case 1:
-		f->pixelformat = V4L2_PIX_FMT_MJPEG;
-		strcpy(f->description, "MJPEG");
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	f->flags = V4L2_FMT_FLAG_COMPRESSED;
-
-	return 0;
-}
-
-static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
-{
-	return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
-		|| (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
-		|| pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
-}
-
-static int solo_enc_try_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
-		return -EINVAL;
-
-	if (pix->width < solo_dev->video_hsize ||
-	    pix->height < solo_dev->video_vsize << 1) {
-		/* Default to CIF 1/2 size */
-		pix->width = solo_dev->video_hsize >> 1;
-		pix->height = solo_dev->video_vsize;
-	} else {
-		/* Full frame */
-		pix->width = solo_dev->video_hsize;
-		pix->height = solo_dev->video_vsize << 1;
-	}
-
-	switch (pix->field) {
-	case V4L2_FIELD_NONE:
-	case V4L2_FIELD_INTERLACED:
-		break;
-	case V4L2_FIELD_ANY:
-	default:
-		pix->field = V4L2_FIELD_INTERLACED;
-		break;
-	}
-
-	/* Just set these */
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->sizeimage = FRAME_BUF_SIZE;
-	pix->bytesperline = 0;
-	pix->priv = 0;
-
-	return 0;
-}
-
-static int solo_enc_set_fmt_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int ret;
-
-	if (vb2_is_busy(&solo_enc->vidq))
-		return -EBUSY;
-
-	ret = solo_enc_try_fmt_cap(file, priv, f);
-	if (ret)
-		return ret;
-
-	if (pix->width == solo_dev->video_hsize)
-		solo_enc->mode = SOLO_ENC_MODE_D1;
-	else
-		solo_enc->mode = SOLO_ENC_MODE_CIF;
-
-	/* This does not change the encoder at all */
-	solo_enc->fmt = pix->pixelformat;
-
-	/*
-	 * More information is needed about these 'extended' types. As far
-	 * as I can tell these are basically additional video streams with
-	 * different MPEG encoding attributes that can run in parallel with
-	 * the main stream. If so, then this should be implemented as a
-	 * second video node. Abusing priv like this is certainly not the
-	 * right approach.
-	if (pix->priv)
-		solo_enc->type = SOLO_ENC_TYPE_EXT;
-	 */
-	solo_update_mode(solo_enc);
-	return 0;
-}
-
-static int solo_enc_get_fmt_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	pix->width = solo_enc->width;
-	pix->height = solo_enc->height;
-	pix->pixelformat = solo_enc->fmt;
-	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
-		     V4L2_FIELD_NONE;
-	pix->sizeimage = FRAME_BUF_SIZE;
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->priv = 0;
-
-	return 0;
-}
-
-static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		*i = V4L2_STD_NTSC_M;
-	else
-		*i = V4L2_STD_PAL;
-	return 0;
-}
-
-static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
-}
-
-static int solo_enum_framesizes(struct file *file, void *priv,
-				struct v4l2_frmsizeenum *fsize)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
-		return -EINVAL;
-
-	switch (fsize->index) {
-	case 0:
-		fsize->discrete.width = solo_dev->video_hsize >> 1;
-		fsize->discrete.height = solo_dev->video_vsize;
-		break;
-	case 1:
-		fsize->discrete.width = solo_dev->video_hsize;
-		fsize->discrete.height = solo_dev->video_vsize << 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-
-	return 0;
-}
-
-static int solo_enum_frameintervals(struct file *file, void *priv,
-				    struct v4l2_frmivalenum *fintv)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
-		return -EINVAL;
-	if (fintv->index)
-		return -EINVAL;
-	if ((fintv->width != solo_dev->video_hsize >> 1 ||
-	     fintv->height != solo_dev->video_vsize) &&
-	    (fintv->width != solo_dev->video_hsize ||
-	     fintv->height != solo_dev->video_vsize << 1))
-		return -EINVAL;
-
-	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
-
-	fintv->stepwise.min.numerator = 1;
-	fintv->stepwise.min.denominator = solo_dev->fps;
-
-	fintv->stepwise.max.numerator = 15;
-	fintv->stepwise.max.denominator = solo_dev->fps;
-
-	fintv->stepwise.step.numerator = 1;
-	fintv->stepwise.step.denominator = solo_dev->fps;
-
-	return 0;
-}
-
-static int solo_g_parm(struct file *file, void *priv,
-		       struct v4l2_streamparm *sp)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct v4l2_captureparm *cp = &sp->parm.capture;
-
-	cp->capability = V4L2_CAP_TIMEPERFRAME;
-	cp->timeperframe.numerator = solo_enc->interval;
-	cp->timeperframe.denominator = solo_enc->solo_dev->fps;
-	cp->capturemode = 0;
-	/* XXX: Shouldn't we be able to get/set this from videobuf? */
-	cp->readbuffers = 2;
-
-	return 0;
-}
-
-static inline int calc_interval(u8 fps, u32 n, u32 d)
-{
-	if (!n || !d)
-		return 1;
-	if (d == fps)
-		return n;
-	n *= fps;
-	return min(15U, n / d + (n % d >= (fps >> 1)));
-}
-
-static int solo_s_parm(struct file *file, void *priv,
-		       struct v4l2_streamparm *sp)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct v4l2_fract *t = &sp->parm.capture.timeperframe;
-	u8 fps = solo_enc->solo_dev->fps;
-
-	if (vb2_is_streaming(&solo_enc->vidq))
-		return -EBUSY;
-
-	solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
-	solo_update_mode(solo_enc);
-	return solo_g_parm(file, priv, sp);
-}
-
-static long solo_enc_default(struct file *file, void *fh,
-			bool valid_prio, unsigned int cmd, void *arg)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct solo_motion_thresholds *thresholds = arg;
-
-	switch (cmd) {
-	case SOLO_IOC_G_MOTION_THRESHOLDS:
-		*thresholds = solo_enc->motion_thresholds;
-		return 0;
-
-	case SOLO_IOC_S_MOTION_THRESHOLDS:
-		if (!valid_prio)
-			return -EBUSY;
-		solo_enc->motion_thresholds = *thresholds;
-		if (solo_enc->motion_enabled && !solo_enc->motion_global)
-			return solo_set_motion_block(solo_dev, solo_enc->ch,
-						&solo_enc->motion_thresholds);
-		return 0;
-	default:
-		return -ENOTTY;
-	}
-}
-
-static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct solo_enc_dev *solo_enc =
-		container_of(ctrl->handler, struct solo_enc_dev, hdl);
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	int err;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SHARPNESS:
-		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
-					 ctrl->val);
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		solo_enc->gop = ctrl->val;
-		return 0;
-	case V4L2_CID_MOTION_THRESHOLD:
-		solo_enc->motion_thresh = ctrl->val;
-		if (!solo_enc->motion_global || !solo_enc->motion_enabled)
-			return 0;
-		return solo_set_motion_threshold(solo_dev, solo_enc->ch,
-			ctrl->val);
-	case V4L2_CID_MOTION_MODE:
-		solo_enc->motion_global = ctrl->val == 1;
-		solo_enc->motion_enabled = ctrl->val > 0;
-		if (ctrl->val) {
-			if (solo_enc->motion_global)
-				solo_set_motion_threshold(solo_dev,
-					solo_enc->ch, solo_enc->motion_thresh);
-			else
-				solo_set_motion_block(solo_dev, solo_enc->ch,
-						&solo_enc->motion_thresholds);
-		}
-		solo_motion_toggle(solo_enc, ctrl->val);
-		return 0;
-	case V4L2_CID_OSD_TEXT:
-		strcpy(solo_enc->osd_text, ctrl->string);
-		err = solo_osd_print(solo_enc);
-		return err;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_file_operations solo_enc_fops = {
-	.owner			= THIS_MODULE,
-	.open			= v4l2_fh_open,
-	.release		= vb2_fop_release,
-	.read			= vb2_fop_read,
-	.poll			= vb2_fop_poll,
-	.mmap			= vb2_fop_mmap,
-	.unlocked_ioctl		= video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
-	.vidioc_querycap		= solo_enc_querycap,
-	.vidioc_s_std			= solo_enc_s_std,
-	.vidioc_g_std			= solo_enc_g_std,
-	/* Input callbacks */
-	.vidioc_enum_input		= solo_enc_enum_input,
-	.vidioc_s_input			= solo_enc_set_input,
-	.vidioc_g_input			= solo_enc_get_input,
-	/* Video capture format callbacks */
-	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
-	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
-	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
-	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
-	/* Streaming I/O */
-	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
-	.vidioc_querybuf		= vb2_ioctl_querybuf,
-	.vidioc_qbuf			= vb2_ioctl_qbuf,
-	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
-	.vidioc_streamon		= vb2_ioctl_streamon,
-	.vidioc_streamoff		= vb2_ioctl_streamoff,
-	/* Frame size and interval */
-	.vidioc_enum_framesizes		= solo_enum_framesizes,
-	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
-	/* Video capture parameters */
-	.vidioc_s_parm			= solo_s_parm,
-	.vidioc_g_parm			= solo_g_parm,
-	/* Logging and events */
-	.vidioc_log_status		= v4l2_ctrl_log_status,
-	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
-	.vidioc_default			= solo_enc_default,
-};
-
-static const struct video_device solo_enc_template = {
-	.name			= SOLO6X10_NAME,
-	.fops			= &solo_enc_fops,
-	.ioctl_ops		= &solo_enc_ioctl_ops,
-	.minor			= -1,
-	.release		= video_device_release,
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
-};
-
-static const struct v4l2_ctrl_ops solo_ctrl_ops = {
-	.s_ctrl = solo_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
-	.ops = &solo_ctrl_ops,
-	.id = V4L2_CID_MOTION_THRESHOLD,
-	.name = "Motion Detection Threshold",
-	.type = V4L2_CTRL_TYPE_INTEGER,
-	.max = 0xffff,
-	.def = SOLO_DEF_MOT_THRESH,
-	.step = 1,
-	.flags = V4L2_CTRL_FLAG_SLIDER,
-};
-
-static const char * const solo_motion_mode_menu[] = {
-	"Disabled",
-	"Global Threshold",
-	"Regional Threshold",
-	NULL
-};
-
-static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
-	.ops = &solo_ctrl_ops,
-	.id = V4L2_CID_MOTION_MODE,
-	.name = "Motion Detection Mode",
-	.type = V4L2_CTRL_TYPE_MENU,
-	.qmenu = solo_motion_mode_menu,
-	.max = 2,
-};
-
-static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
-	.ops = &solo_ctrl_ops,
-	.id = V4L2_CID_OSD_TEXT,
-	.name = "OSD Text",
-	.type = V4L2_CTRL_TYPE_STRING,
-	.max = OSD_TEXT_MAX,
-	.step = 1,
-};
-
-static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
-					   u8 ch, unsigned nr)
-{
-	struct solo_enc_dev *solo_enc;
-	struct v4l2_ctrl_handler *hdl;
-	int ret;
-	int x, y;
-
-	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
-	if (!solo_enc)
-		return ERR_PTR(-ENOMEM);
-
-	hdl = &solo_enc->hdl;
-	v4l2_ctrl_handler_init(hdl, 10);
-	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_CONTRAST, 0, 255, 1, 128);
-	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_SATURATION, 0, 255, 1, 128);
-	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_HUE, 0, 255, 1, 128);
-	if (tw28_has_sharpness(solo_dev, ch))
-		v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_SHARPNESS, 0, 15, 1, 0);
-	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
-			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
-	v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
-	v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
-	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
-	if (hdl->error) {
-		ret = hdl->error;
-		goto hdl_free;
-	}
-
-	solo_enc->solo_dev = solo_dev;
-	solo_enc->ch = ch;
-	mutex_init(&solo_enc->lock);
-	spin_lock_init(&solo_enc->av_lock);
-	INIT_LIST_HEAD(&solo_enc->vidq_active);
-	solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
-		V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
-	solo_enc->type = SOLO_ENC_TYPE_STD;
-
-	solo_enc->qp = SOLO_DEFAULT_QP;
-	solo_enc->gop = solo_dev->fps;
-	solo_enc->interval = 1;
-	solo_enc->mode = SOLO_ENC_MODE_CIF;
-	solo_enc->motion_global = true;
-	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
-	for (y = 0; y < SOLO_MOTION_SZ; y++)
-		for (x = 0; x < SOLO_MOTION_SZ; x++)
-			solo_enc->motion_thresholds.thresholds[y][x] =
-							SOLO_DEF_MOT_THRESH;
-
-	solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	solo_enc->vidq.ops = &solo_enc_video_qops;
-	solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
-	solo_enc->vidq.drv_priv = solo_enc;
-	solo_enc->vidq.gfp_flags = __GFP_DMA32;
-	solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
-	solo_enc->vidq.lock = &solo_enc->lock;
-	ret = vb2_queue_init(&solo_enc->vidq);
-	if (ret)
-		goto hdl_free;
-	solo_update_mode(solo_enc);
-
-	spin_lock_init(&solo_enc->motion_lock);
-
-	/* Initialize this per encoder */
-	solo_enc->jpeg_len = sizeof(jpeg_header);
-	memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
-
-	solo_enc->desc_nelts = 32;
-	solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
-				      sizeof(struct solo_p2m_desc) *
-				      solo_enc->desc_nelts,
-				      &solo_enc->desc_dma);
-	ret = -ENOMEM;
-	if (solo_enc->desc_items == NULL)
-		goto hdl_free;
-
-	solo_enc->vfd = video_device_alloc();
-	if (!solo_enc->vfd)
-		goto pci_free;
-
-	*solo_enc->vfd = solo_enc_template;
-	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
-	solo_enc->vfd->ctrl_handler = hdl;
-	solo_enc->vfd->queue = &solo_enc->vidq;
-	solo_enc->vfd->lock = &solo_enc->lock;
-	set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
-	video_set_drvdata(solo_enc->vfd, solo_enc);
-	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
-	if (ret < 0)
-		goto vdev_release;
-
-	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
-		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
-		 solo_enc->vfd->num);
-
-	return solo_enc;
-
-vdev_release:
-	video_device_release(solo_enc->vfd);
-pci_free:
-	pci_free_consistent(solo_enc->solo_dev->pdev,
-			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
-			solo_enc->desc_items, solo_enc->desc_dma);
-hdl_free:
-	v4l2_ctrl_handler_free(hdl);
-	kfree(solo_enc);
-	return ERR_PTR(ret);
-}
-
-static void solo_enc_free(struct solo_enc_dev *solo_enc)
-{
-	if (solo_enc == NULL)
-		return;
-
-	video_unregister_device(solo_enc->vfd);
-	v4l2_ctrl_handler_free(&solo_enc->hdl);
-	kfree(solo_enc);
-}
-
-int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
-{
-	int i;
-
-	init_waitqueue_head(&solo_dev->ring_thread_wait);
-
-	solo_dev->vh_size = sizeof(vop_header);
-	solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
-						solo_dev->vh_size,
-						&solo_dev->vh_dma);
-	if (solo_dev->vh_buf == NULL)
-		return -ENOMEM;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
-		if (IS_ERR(solo_dev->v4l2_enc[i]))
-			break;
-	}
-
-	if (i != solo_dev->nr_chans) {
-		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
-		while (i--)
-			solo_enc_free(solo_dev->v4l2_enc[i]);
-		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
-				    solo_dev->vh_buf, solo_dev->vh_dma);
-		solo_dev->vh_buf = NULL;
-		return ret;
-	}
-
-	if (solo_dev->type == SOLO_DEV_6010)
-		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
-	else
-		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
-
-	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
-		 solo_dev->v4l2_enc[0]->vfd->num,
-		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
-
-	return 0;
-}
-
-void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_enc_free(solo_dev->v4l2_enc[i]);
-
-	if (solo_dev->vh_buf)
-		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
-			    solo_dev->vh_buf, solo_dev->vh_dma);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/media/solo6x10/TODO linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/TODO
--- linux-libre-3.16-gnu/drivers/staging/media/solo6x10/TODO	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/media/solo6x10/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-- batch up desc requests for more efficient use of p2m?
-- encoder on/off controls
-- mpeg cid bitrate mode (vbr/cbr)
-- mpeg cid bitrate/bitrate-peak
-- mpeg encode of user data
-- mpeg decode of user data
-- implement CID controls for mozaic areas
-
-- sound
- - implement playback via external sound jack
- - implement loopback of external sound jack with incoming audio?
- - implement pause/resume (make use of in bc-server)
-
-Please send patches to the linux media list <linux-media@vger.kernel.org> and
-Cc Ismael Luceno <ismael.luceno@corp.bluecherry.net>.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/netlogic/xlr_net.c linux-libre-3.17-rc7-gnu/drivers/staging/netlogic/xlr_net.c
--- linux-libre-3.16-gnu/drivers/staging/netlogic/xlr_net.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/netlogic/xlr_net.c	2014-09-28 17:29:07.000000000 -0400
@@ -185,7 +185,6 @@ static void xlr_net_fmn_handler(int bkt,
 		if (skb_new)
 			send_to_rfr_fifo(priv, skb_new->data);
 	}
-	return;
 }
 
 /* Ethtool operation */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/nokia_h4p/nokia_core.c linux-libre-3.17-rc7-gnu/drivers/staging/nokia_h4p/nokia_core.c
--- linux-libre-3.16-gnu/drivers/staging/nokia_h4p/nokia_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/nokia_h4p/nokia_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -756,6 +756,7 @@ static int hci_h4p_reset(struct hci_h4p_
 static int hci_h4p_hci_flush(struct hci_dev *hdev)
 {
 	struct hci_h4p_info *info = hci_get_drvdata(hdev);
+
 	skb_queue_purge(&info->txq);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/nvec/nvec.c linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec.c
--- linux-libre-3.16-gnu/drivers/staging/nvec/nvec.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec.c	2014-09-28 17:29:07.000000000 -0400
@@ -232,8 +232,7 @@ static size_t nvec_msg_size(struct nvec_
 		return 2;
 	else if (event_length == NVEC_3BYTES)
 		return 3;
-	else
-		return 0;
+	return 0;
 }
 
 /**
@@ -807,10 +806,9 @@ static int tegra_nvec_probe(struct platf
 	}
 
 	nvec = devm_kzalloc(&pdev->dev, sizeof(struct nvec_chip), GFP_KERNEL);
-	if (nvec == NULL) {
-		dev_err(&pdev->dev, "failed to reserve memory\n");
+	if (nvec == NULL)
 		return -ENOMEM;
-	}
+
 	platform_set_drvdata(pdev, nvec);
 	nvec->dev = &pdev->dev;
 
@@ -823,8 +821,8 @@ static int tegra_nvec_probe(struct platf
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
+	nvec->irq = platform_get_irq(pdev, 0);
+	if (nvec->irq < 0) {
 		dev_err(&pdev->dev, "no irq resource?\n");
 		return -ENODEV;
 	}
@@ -842,7 +840,6 @@ static int tegra_nvec_probe(struct platf
 	}
 
 	nvec->base = base;
-	nvec->irq = res->start;
 	nvec->i2c_clk = i2c_clk;
 	nvec->rx = &nvec->msg_pool[0];
 
@@ -895,7 +892,7 @@ static int tegra_nvec_probe(struct platf
 	}
 
 	ret = mfd_add_devices(nvec->dev, -1, nvec_devices,
-			      ARRAY_SIZE(nvec_devices), base, 0, NULL);
+			      ARRAY_SIZE(nvec_devices), NULL, 0, NULL);
 	if (ret)
 		dev_err(nvec->dev, "error adding subdevices\n");
 
@@ -962,7 +959,7 @@ static int nvec_resume(struct device *de
 }
 #endif
 
-static const SIMPLE_DEV_PM_OPS(nvec_pm_ops, nvec_suspend, nvec_resume);
+static SIMPLE_DEV_PM_OPS(nvec_pm_ops, nvec_suspend, nvec_resume);
 
 /* Match table for of_platform binding */
 static const struct of_device_id nvidia_nvec_of_match[] = {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/nvec/nvec_paz00.c linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_paz00.c
--- linux-libre-3.16-gnu/drivers/staging/nvec/nvec_paz00.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_paz00.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@ static void nvec_led_brightness_set(stru
 {
 	struct nvec_led *led = to_nvec_led(led_cdev);
 	unsigned char buf[] = NVEC_LED_REQ;
+
 	buf[4] = value;
 
 	nvec_write_async(led->nvec, buf, sizeof(buf));
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/nvec/nvec_power.c linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_power.c
--- linux-libre-3.16-gnu/drivers/staging/nvec/nvec_power.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_power.c	2014-09-28 17:29:07.000000000 -0400
@@ -226,6 +226,7 @@ static int nvec_power_get_property(struc
 				   union power_supply_propval *val)
 {
 	struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
+
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = power->on;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/nvec/nvec_ps2.c linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_ps2.c
--- linux-libre-3.16-gnu/drivers/staging/nvec/nvec_ps2.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/nvec/nvec_ps2.c	2014-09-28 17:29:07.000000000 -0400
@@ -53,12 +53,14 @@ static struct nvec_ps2 ps2_dev;
 static int ps2_startstreaming(struct serio *ser_dev)
 {
 	unsigned char buf[] = { NVEC_PS2, AUTO_RECEIVE_N, PACKET_SIZE };
+
 	return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
 }
 
 static void ps2_stopstreaming(struct serio *ser_dev)
 {
 	unsigned char buf[] = { NVEC_PS2, CANCEL_AUTO_RECEIVE };
+
 	nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet.c	2014-09-28 17:29:07.000000000 -0400
@@ -471,7 +471,6 @@ int cvm_oct_common_init(struct net_devic
 	dev->features |= NETIF_F_LLTX;
 	dev->ethtool_ops = &cvm_oct_ethtool_ops;
 
-	cvm_oct_phy_setup_device(dev);
 	cvm_oct_set_mac_filter(dev);
 	dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
 
@@ -722,6 +721,7 @@ static int cvm_oct_probe(struct platform
 
 			/* Initialize the device private structure. */
 			priv = netdev_priv(dev);
+			priv->netdev = dev;
 			priv->of_node = cvm_oct_node_for_port(pip, interface,
 								port_index);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-mdio.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-mdio.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-mdio.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-mdio.c	2014-09-28 17:29:07.000000000 -0400
@@ -116,7 +116,34 @@ int cvm_oct_ioctl(struct net_device *dev
 	return phy_mii_ioctl(priv->phydev, rq, cmd);
 }
 
-static void cvm_oct_adjust_link(struct net_device *dev)
+static void cvm_oct_note_carrier(struct octeon_ethernet *priv,
+				 cvmx_helper_link_info_t li)
+{
+	if (li.s.link_up) {
+		pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d\n",
+				      netdev_name(priv->netdev), li.s.speed,
+				      (li.s.full_duplex) ? "Full" : "Half",
+				      priv->port);
+	} else {
+		pr_notice_ratelimited("%s: Link down\n",
+				      netdev_name(priv->netdev));
+	}
+}
+
+void cvm_oct_set_carrier(struct octeon_ethernet *priv,
+			 cvmx_helper_link_info_t link_info)
+{
+	cvm_oct_note_carrier(priv, link_info);
+	if (link_info.s.link_up) {
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+	} else {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+	}
+}
+
+void cvm_oct_adjust_link(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
 	cvmx_helper_link_info_t link_info;
@@ -127,28 +154,32 @@ static void cvm_oct_adjust_link(struct n
 		link_info.s.link_up = priv->last_link ? 1 : 0;
 		link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
 		link_info.s.speed = priv->phydev->speed;
+
 		cvmx_helper_link_set(priv->port, link_info);
-		if (priv->last_link) {
-			netif_carrier_on(dev);
-			if (priv->queue != -1)
-				printk_ratelimited("%s: %u Mbps %s duplex, "
-					"port %2d, queue %2d\n", dev->name,
-					priv->phydev->speed,
-					priv->phydev->duplex ? "Full" : "Half",
-					priv->port, priv->queue);
-			else
-				printk_ratelimited("%s: %u Mbps %s duplex, "
-					"port %2d, POW\n", dev->name,
-					priv->phydev->speed,
-					priv->phydev->duplex ? "Full" : "Half",
-					priv->port);
-		} else {
-			netif_carrier_off(dev);
-			printk_ratelimited("%s: Link down\n", dev->name);
-		}
+		cvm_oct_note_carrier(priv, link_info);
 	}
 }
 
+int cvm_oct_common_stop(struct net_device *dev)
+{
+	struct octeon_ethernet *priv = netdev_priv(dev);
+	cvmx_helper_link_info_t link_info;
+
+	priv->poll = NULL;
+
+	if (priv->phydev)
+		phy_disconnect(priv->phydev);
+	priv->phydev = NULL;
+
+	if (priv->last_link) {
+		link_info.u64 = 0;
+		priv->last_link = 0;
+
+		cvmx_helper_link_set(priv->port, link_info);
+		cvm_oct_note_carrier(priv, link_info);
+	}
+	return 0;
+}
 
 /**
  * cvm_oct_phy_setup_device - setup the PHY
@@ -163,11 +194,11 @@ int cvm_oct_phy_setup_device(struct net_
 	struct device_node *phy_node;
 
 	if (!priv->of_node)
-		return 0;
+		goto no_phy;
 
 	phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
 	if (!phy_node)
-		return 0;
+		goto no_phy;
 
 	priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
 				      PHY_INTERFACE_MODE_GMII);
@@ -179,4 +210,10 @@ int cvm_oct_phy_setup_device(struct net_
 	phy_start_aneg(priv->phydev);
 
 	return 0;
+no_phy:
+	/* If there is no phy, assume a direct MAC connection and that
+	 * the link is up.
+	 */
+	netif_carrier_on(dev);
+	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-mem.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-mem.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-mem.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-mem.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,9 +46,10 @@
 static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)
 {
 	int freed = elements;
-	while (freed) {
 
+	while (freed) {
 		struct sk_buff *skb = dev_alloc_skb(size + 256);
+
 		if (unlikely(skb == NULL))
 			break;
 		skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f));
@@ -81,10 +82,10 @@ static void cvm_oct_free_hw_skbuff(int p
 
 	if (elements < 0)
 		pr_warn("Freeing of pool %u had too many skbuffs (%d)\n",
-		     pool, elements);
+			pool, elements);
 	else if (elements > 0)
 		pr_warn("Freeing of pool %u is missing %d skbuffs\n",
-		       pool, elements);
+			pool, elements);
 }
 
 /**
@@ -115,7 +116,7 @@ static int cvm_oct_fill_hw_memory(int po
 		memory = kmalloc(size + 256, GFP_ATOMIC);
 		if (unlikely(memory == NULL)) {
 			pr_warn("Unable to allocate %u bytes for FPA pool %d\n",
-				   elements * size, pool);
+				elements * size, pool);
 			break;
 		}
 		fpa = (char *)(((unsigned long)memory + 256) & ~0x7fUL);
@@ -136,6 +137,7 @@ static void cvm_oct_free_hw_memory(int p
 {
 	char *memory;
 	char *fpa;
+
 	do {
 		fpa = cvmx_fpa_alloc(pool);
 		if (fpa) {
@@ -157,6 +159,7 @@ static void cvm_oct_free_hw_memory(int p
 int cvm_oct_mem_fill_fpa(int pool, int size, int elements)
 {
 	int freed;
+
 	if (USE_SKBUFFS_IN_HW && pool == CVMX_FPA_PACKET_POOL)
 		freed = cvm_oct_fill_hw_skbuff(pool, size, elements);
 	else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-rgmii.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-rgmii.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-rgmii.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-rgmii.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,6 +36,7 @@
 #include "ethernet-defines.h"
 #include "octeon-ethernet.h"
 #include "ethernet-util.h"
+#include "ethernet-mdio.h"
 
 #include <asm/octeon/cvmx-helper.h>
 
@@ -302,15 +303,28 @@ int cvm_oct_rgmii_open(struct net_device
 	int interface = INTERFACE(priv->port);
 	int index = INDEX(priv->port);
 	cvmx_helper_link_info_t link_info;
+	int rv;
+
+	rv = cvm_oct_phy_setup_device(dev);
+	if (rv)
+		return rv;
 
 	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
 	gmx_cfg.s.en = 1;
 	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
 
 	if (!octeon_is_simulation()) {
-		link_info = cvmx_helper_link_get(priv->port);
-		if (!link_info.s.link_up)
-			netif_carrier_off(dev);
+		if (priv->phydev) {
+			int r = phy_read_status(priv->phydev);
+			if (r == 0 && priv->phydev->link == 0)
+				netif_carrier_off(dev);
+			cvm_oct_adjust_link(dev);
+		} else {
+			link_info = cvmx_helper_link_get(priv->port);
+			if (!link_info.s.link_up)
+				netif_carrier_off(dev);
+			priv->poll = cvm_oct_rgmii_poll;
+		}
 	}
 
 	return 0;
@@ -326,7 +340,7 @@ int cvm_oct_rgmii_stop(struct net_device
 	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
 	gmx_cfg.s.en = 0;
 	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-	return 0;
+	return cvm_oct_common_stop(dev);
 }
 
 static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
@@ -384,7 +398,6 @@ int cvm_oct_rgmii_init(struct net_device
 			gmx_rx_int_en.s.phy_spd = 1;
 			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
 				       gmx_rx_int_en.u64);
-			priv->poll = cvm_oct_rgmii_poll;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-sgmii.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-sgmii.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-sgmii.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-sgmii.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
  * This file may also be available under a different license from Cavium.
  * Contact Cavium Networks for more information
 **********************************************************************/
+#include <linux/phy.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/ratelimit.h>
@@ -34,45 +35,12 @@
 #include "ethernet-defines.h"
 #include "octeon-ethernet.h"
 #include "ethernet-util.h"
+#include "ethernet-mdio.h"
 
 #include <asm/octeon/cvmx-helper.h>
 
 #include <asm/octeon/cvmx-gmxx-defs.h>
 
-int cvm_oct_sgmii_open(struct net_device *dev)
-{
-	union cvmx_gmxx_prtx_cfg gmx_cfg;
-	struct octeon_ethernet *priv = netdev_priv(dev);
-	int interface = INTERFACE(priv->port);
-	int index = INDEX(priv->port);
-	cvmx_helper_link_info_t link_info;
-
-	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-	gmx_cfg.s.en = 1;
-	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
-	if (!octeon_is_simulation()) {
-		link_info = cvmx_helper_link_get(priv->port);
-		if (!link_info.s.link_up)
-			netif_carrier_off(dev);
-	}
-
-	return 0;
-}
-
-int cvm_oct_sgmii_stop(struct net_device *dev)
-{
-	union cvmx_gmxx_prtx_cfg gmx_cfg;
-	struct octeon_ethernet *priv = netdev_priv(dev);
-	int interface = INTERFACE(priv->port);
-	int index = INDEX(priv->port);
-
-	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-	gmx_cfg.s.en = 0;
-	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-	return 0;
-}
-
 static void cvm_oct_sgmii_poll(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
@@ -109,13 +77,58 @@ static void cvm_oct_sgmii_poll(struct ne
 	}
 }
 
-int cvm_oct_sgmii_init(struct net_device *dev)
+int cvm_oct_sgmii_open(struct net_device *dev)
 {
+	union cvmx_gmxx_prtx_cfg gmx_cfg;
 	struct octeon_ethernet *priv = netdev_priv(dev);
+	int interface = INTERFACE(priv->port);
+	int index = INDEX(priv->port);
+	cvmx_helper_link_info_t link_info;
+	int rv;
+
+	rv = cvm_oct_phy_setup_device(dev);
+	if (rv)
+		return rv;
+
+	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+	gmx_cfg.s.en = 1;
+	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+	if (octeon_is_simulation())
+		return 0;
+
+	if (priv->phydev) {
+		int r = phy_read_status(priv->phydev);
+		if (r == 0 && priv->phydev->link == 0)
+			netif_carrier_off(dev);
+		cvm_oct_adjust_link(dev);
+	} else {
+		link_info = cvmx_helper_link_get(priv->port);
+		if (!link_info.s.link_up)
+			netif_carrier_off(dev);
+		priv->poll = cvm_oct_sgmii_poll;
+		cvm_oct_sgmii_poll(dev);
+	}
+	return 0;
+}
+
+int cvm_oct_sgmii_stop(struct net_device *dev)
+{
+	union cvmx_gmxx_prtx_cfg gmx_cfg;
+	struct octeon_ethernet *priv = netdev_priv(dev);
+	int interface = INTERFACE(priv->port);
+	int index = INDEX(priv->port);
+
+	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+	gmx_cfg.s.en = 0;
+	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+	return cvm_oct_common_stop(dev);
+}
+
+int cvm_oct_sgmii_init(struct net_device *dev)
+{
 	cvm_oct_common_init(dev);
 	dev->netdev_ops->ndo_stop(dev);
-	if (!octeon_is_simulation() && priv->phydev == NULL)
-		priv->poll = cvm_oct_sgmii_poll;
 
 	/* FIXME: Need autoneg logic */
 	return 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-xaui.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-xaui.c
--- linux-libre-3.16-gnu/drivers/staging/octeon/ethernet-xaui.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/ethernet-xaui.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,6 +24,7 @@
  * This file may also be available under a different license from Cavium.
  * Contact Cavium Networks for more information
 **********************************************************************/
+#include <linux/phy.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/ratelimit.h>
@@ -34,44 +35,12 @@
 #include "ethernet-defines.h"
 #include "octeon-ethernet.h"
 #include "ethernet-util.h"
+#include "ethernet-mdio.h"
 
 #include <asm/octeon/cvmx-helper.h>
 
 #include <asm/octeon/cvmx-gmxx-defs.h>
 
-int cvm_oct_xaui_open(struct net_device *dev)
-{
-	union cvmx_gmxx_prtx_cfg gmx_cfg;
-	struct octeon_ethernet *priv = netdev_priv(dev);
-	int interface = INTERFACE(priv->port);
-	int index = INDEX(priv->port);
-	cvmx_helper_link_info_t link_info;
-
-	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-	gmx_cfg.s.en = 1;
-	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
-	if (!octeon_is_simulation()) {
-		link_info = cvmx_helper_link_get(priv->port);
-		if (!link_info.s.link_up)
-			netif_carrier_off(dev);
-	}
-	return 0;
-}
-
-int cvm_oct_xaui_stop(struct net_device *dev)
-{
-	union cvmx_gmxx_prtx_cfg gmx_cfg;
-	struct octeon_ethernet *priv = netdev_priv(dev);
-	int interface = INTERFACE(priv->port);
-	int index = INDEX(priv->port);
-
-	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-	gmx_cfg.s.en = 0;
-	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-	return 0;
-}
-
 static void cvm_oct_xaui_poll(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
@@ -108,9 +77,58 @@ static void cvm_oct_xaui_poll(struct net
 	}
 }
 
+int cvm_oct_xaui_open(struct net_device *dev)
+{
+	union cvmx_gmxx_prtx_cfg gmx_cfg;
+	struct octeon_ethernet *priv = netdev_priv(dev);
+	int interface = INTERFACE(priv->port);
+	int index = INDEX(priv->port);
+	cvmx_helper_link_info_t link_info;
+	int rv;
+
+	rv = cvm_oct_phy_setup_device(dev);
+	if (rv)
+		return rv;
+
+	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+	gmx_cfg.s.en = 1;
+	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+	if (octeon_is_simulation())
+		return 0;
+
+	if (priv->phydev) {
+		int r = phy_read_status(priv->phydev);
+		if (r == 0 && priv->phydev->link == 0)
+			netif_carrier_off(dev);
+		cvm_oct_adjust_link(dev);
+	} else {
+		link_info = cvmx_helper_link_get(priv->port);
+		if (!link_info.s.link_up)
+			netif_carrier_off(dev);
+		priv->poll = cvm_oct_xaui_poll;
+		cvm_oct_xaui_poll(dev);
+	}
+	return 0;
+}
+
+int cvm_oct_xaui_stop(struct net_device *dev)
+{
+	union cvmx_gmxx_prtx_cfg gmx_cfg;
+	struct octeon_ethernet *priv = netdev_priv(dev);
+	int interface = INTERFACE(priv->port);
+	int index = INDEX(priv->port);
+
+	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+	gmx_cfg.s.en = 0;
+	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+	return cvm_oct_common_stop(dev);
+}
+
 int cvm_oct_xaui_init(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
+
 	cvm_oct_common_init(dev);
 	dev->netdev_ops->ndo_stop(dev);
 	if (!octeon_is_simulation() && priv->phydev == NULL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon/octeon-ethernet.h linux-libre-3.17-rc7-gnu/drivers/staging/octeon/octeon-ethernet.h
--- linux-libre-3.16-gnu/drivers/staging/octeon/octeon-ethernet.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon/octeon-ethernet.h	2014-09-28 17:29:07.000000000 -0400
@@ -44,6 +44,8 @@ struct octeon_ethernet {
 	int queue;
 	/* Hardware fetch and add to count outstanding tx buffers */
 	int fau;
+	/* My netdev. */
+	struct net_device *netdev;
 	/*
 	 * Type of port. This is one of the enums in
 	 * cvmx_helper_interface_mode_t
@@ -85,6 +87,8 @@ extern int cvm_oct_xaui_stop(struct net_
 
 extern int cvm_oct_common_init(struct net_device *dev);
 extern void cvm_oct_common_uninit(struct net_device *dev);
+void cvm_oct_adjust_link(struct net_device *dev);
+int cvm_oct_common_stop(struct net_device *dev);
 
 extern int always_use_pow;
 extern int pow_send_group;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/octeon-usb/octeon-hcd.c linux-libre-3.17-rc7-gnu/drivers/staging/octeon-usb/octeon-hcd.c
--- linux-libre-3.16-gnu/drivers/staging/octeon-usb/octeon-hcd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/octeon-usb/octeon-hcd.c	2014-09-28 17:29:07.000000000 -0400
@@ -422,8 +422,6 @@ struct cvmx_usb_state {
 struct octeon_hcd {
 	spinlock_t lock;
 	struct cvmx_usb_state usb;
-	struct tasklet_struct dequeue_tasklet;
-	struct list_head dequeue_list;
 };
 
 /* This macro spins on a field waiting for it to reach a value */
@@ -2164,17 +2162,12 @@ static void octeon_usb_urb_complete_call
 	struct usb_hcd *hcd = octeon_to_hcd(priv);
 	struct device *dev = hcd->self.controller;
 
-	urb->actual_length = bytes_transferred;
-	urb->hcpriv = NULL;
+	if (likely(status == CVMX_USB_COMPLETE_SUCCESS))
+		urb->actual_length = bytes_transferred;
+	else
+		urb->actual_length = 0;
 
-	if (!list_empty(&urb->urb_list))
-		/*
-		 * It is on the dequeue_list, but we are going to call
-		 * usb_hcd_giveback_urb(), so we must clear it from
-		 * the list.  We got to it before the
-		 * octeon_usb_urb_dequeue_work() tasklet did.
-		 */
-		list_del_init(&urb->urb_list);
+	urb->hcpriv = NULL;
 
 	/* For Isochronous transactions we need to update the URB packet status
 	   list from data in our private copy */
@@ -2241,6 +2234,7 @@ static void octeon_usb_urb_complete_call
 		urb->status = -EPROTO;
 		break;
 	}
+	usb_hcd_unlink_urb_from_ep(octeon_to_hcd(priv), urb);
 	spin_unlock(&priv->lock);
 	usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status);
 	spin_lock(&priv->lock);
@@ -2850,8 +2844,9 @@ static int __cvmx_usb_poll_channel(struc
 		__cvmx_usb_perform_complete(usb, pipe, transaction,
 					    CVMX_USB_COMPLETE_BABBLEERR);
 	} else if (usbc_hcint.s.datatglerr) {
-		/* We'll retry the exact same transaction again */
-		transaction->retries++;
+		/* Data toggle error */
+		__cvmx_usb_perform_complete(usb, pipe, transaction,
+					    CVMX_USB_COMPLETE_DATATGLERR);
 	} else if (usbc_hcint.s.nyet) {
 		/*
 		 * NYET as a response is only allowed in three cases: as a
@@ -3302,11 +3297,17 @@ static int octeon_usb_urb_enqueue(struct
 	unsigned long flags;
 	struct cvmx_usb_iso_packet *iso_packet;
 	struct usb_host_endpoint *ep = urb->ep;
+	int rc;
 
 	urb->status = 0;
-	INIT_LIST_HEAD(&urb->urb_list);	/* not enqueued on dequeue_list */
 	spin_lock_irqsave(&priv->lock, flags);
 
+	rc = usb_hcd_link_urb_to_ep(hcd, urb);
+	if (rc) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return rc;
+	}
+
 	if (!ep->hcpriv) {
 		enum cvmx_usb_transfer transfer_type;
 		enum cvmx_usb_speed speed;
@@ -3382,6 +3383,7 @@ static int octeon_usb_urb_enqueue(struct
 					   >> 11) & 0x3,
 					  split_device, split_port);
 		if (!pipe) {
+			usb_hcd_unlink_urb_from_ep(hcd, urb);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			dev_dbg(dev, "Failed to create pipe\n");
 			return -ENOMEM;
@@ -3452,6 +3454,7 @@ static int octeon_usb_urb_enqueue(struct
 		break;
 	}
 	if (!transaction) {
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		spin_unlock_irqrestore(&priv->lock, flags);
 		dev_dbg(dev, "Failed to submit\n");
 		return -ENOMEM;
@@ -3461,43 +3464,30 @@ static int octeon_usb_urb_enqueue(struct
 	return 0;
 }
 
-static void octeon_usb_urb_dequeue_work(unsigned long arg)
-{
-	struct urb *urb;
-	struct urb *next;
-	unsigned long flags;
-	struct octeon_hcd *priv = (struct octeon_hcd *)arg;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	list_for_each_entry_safe(urb, next, &priv->dequeue_list, urb_list) {
-		list_del_init(&urb->urb_list);
-		cvmx_usb_cancel(&priv->usb, urb->ep->hcpriv, urb->hcpriv);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
 static int octeon_usb_urb_dequeue(struct usb_hcd *hcd,
 				  struct urb *urb,
 				  int status)
 {
 	struct octeon_hcd *priv = hcd_to_octeon(hcd);
 	unsigned long flags;
+	int rc;
 
 	if (!urb->dev)
 		return -EINVAL;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
+	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (rc)
+		goto out;
+
 	urb->status = status;
-	list_add_tail(&urb->urb_list, &priv->dequeue_list);
+	cvmx_usb_cancel(&priv->usb, urb->ep->hcpriv, urb->hcpriv);
 
+out:
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	tasklet_schedule(&priv->dequeue_tasklet);
-
-	return 0;
+	return rc;
 }
 
 static void octeon_usb_endpoint_disable(struct usb_hcd *hcd,
@@ -3638,7 +3628,7 @@ static int octeon_usb_hub_control(struct
 		desc->bDescLength = 9;
 		desc->bDescriptorType = 0x29;
 		desc->bNbrPorts = 1;
-		desc->wHubCharacteristics = 0x08;
+		desc->wHubCharacteristics = cpu_to_le16(0x08);
 		desc->bPwrOn2PwrGood = 1;
 		desc->bHubContrCurrent = 0;
 		desc->u.hs.DeviceRemovable[0] = 0;
@@ -3868,10 +3858,6 @@ static int octeon_usb_probe(struct platf
 
 	spin_lock_init(&priv->lock);
 
-	tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work,
-		     (unsigned long)priv);
-	INIT_LIST_HEAD(&priv->dequeue_list);
-
 	status = cvmx_usb_initialize(&priv->usb, usb_num, initialize_flags);
 	if (status) {
 		dev_dbg(dev, "USB initialization failed with %d\n", status);
@@ -3908,7 +3894,6 @@ static int octeon_usb_remove(struct plat
 	unsigned long flags;
 
 	usb_remove_hcd(hcd);
-	tasklet_kill(&priv->dequeue_tasklet);
 	spin_lock_irqsave(&priv->lock, flags);
 	status = cvmx_usb_shutdown(&priv->usb);
 	spin_unlock_irqrestore(&priv->lock, flags);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/panel/panel.c linux-libre-3.17-rc7-gnu/drivers/staging/panel/panel.c
--- linux-libre-3.16-gnu/drivers/staging/panel/panel.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/panel/panel.c	2014-09-28 17:29:07.000000000 -0400
@@ -1800,11 +1800,12 @@ static inline int input_state_high(struc
 				input->high_timer++;
 		}
 		return 1;
-	} else {
-		/* else signal falling down. Let's fall through. */
-		input->state = INPUT_ST_FALLING;
-		input->fall_timer = 0;
 	}
+
+	/* else signal falling down. Let's fall through. */
+	input->state = INPUT_ST_FALLING;
+	input->fall_timer = 0;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/phison/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/phison/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/phison/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/phison/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-config IDE_PHISON
-	tristate "PCIE ATA PS5000 IDE support"
-	depends on PCI && ATA && ATA_SFF && ATA_BMDMA
-	---help---
-	  This is an experimental driver for PS5000 IDE driver.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/phison/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/phison/Makefile
--- linux-libre-3.16-gnu/drivers/staging/phison/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/phison/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-obj-$(CONFIG_IDE_PHISON)	+= phison.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/phison/phison.c linux-libre-3.17-rc7-gnu/drivers/staging/phison/phison.c
--- linux-libre-3.16-gnu/drivers/staging/phison/phison.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/phison/phison.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2006		Red Hat <evan_ko@phison.com>
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  [Modify History]
- *   #0001, Evan, 2008.10.22, V0.00, New release.
- *   #0002, Evan, 2008.11.01, V0.90, Test Work In Ubuntu Linux 8.04.
- *   #0003, Evan, 2008.01.08, V0.91, Change Name "PCIE-SSD" to "E-BOX".
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/ata.h>
-
-#define PHISON_DEBUG
-
-#define DRV_NAME		"phison_e-box"	/* #0003 */
-#define DRV_VERSION		"0.91"		/* #0003 */
-
-#define PCI_VENDOR_ID_PHISON	0x1987
-#define PCI_DEVICE_ID_PS5000	0x5000
-
-static int phison_pre_reset(struct ata_link *link, unsigned long deadline)
-{
-	int ret;
-	struct ata_port *ap = link->ap;
-
-	ap->cbl = ATA_CBL_NONE;
-	ret = ata_std_prereset(link, deadline);
-	dev_dbg(ap->dev, "phison_pre_reset(), ret = %x\n", ret);
-	return ret;
-}
-
-static struct scsi_host_template phison_sht = {
-	ATA_BMDMA_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations phison_ops = {
-	.inherits		= &ata_bmdma_port_ops,
-	.prereset		= phison_pre_reset,
-};
-
-static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	int ret;
-	struct ata_port_info info = {
-		.flags		= ATA_FLAG_NO_ATAPI,
-
-		.pio_mask	= 0x1f,
-		.mwdma_mask	= 0x07,
-		.udma_mask	= ATA_UDMA5,
-
-		.port_ops	= &phison_ops,
-	};
-	const struct ata_port_info *ppi[] = { &info, NULL };
-
-	ret = ata_pci_bmdma_init_one(pdev, ppi, &phison_sht, NULL, 0);
-
-	dev_dbg(&pdev->dev, "phison_init_one(), ret = %x\n", ret);
-
-	return ret;
-}
-
-static const struct pci_device_id phison_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000),
-	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE(pci, phison_pci_tbl);
-
-static struct pci_driver phison_pci_driver = {
-	.name		= DRV_NAME,
-	.id_table	= phison_pci_tbl,
-	.probe		= phison_init_one,
-	.remove		= ata_pci_remove_one,
-#ifdef CONFIG_PM	/* haven't tested it. */
-	.suspend	= ata_pci_device_suspend,
-	.resume		= ata_pci_device_resume,
-#endif
-};
-
-module_pci_driver(phison_pci_driver);
-
-MODULE_AUTHOR("Evan Ko");
-MODULE_DESCRIPTION("PCIE driver module for PHISON PS5000 E-BOX");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/quickstart/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/quickstart/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-config ACPI_QUICKSTART
-	tristate "ACPI Quickstart key driver"
-	depends on ACPI && INPUT
-	help
-	  Say Y here if you have a platform that supports the ACPI
-	  quickstart key protocol.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called quickstart.
-
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/quickstart/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/Makefile
--- linux-libre-3.16-gnu/drivers/staging/quickstart/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-obj-$(CONFIG_ACPI_QUICKSTART)		+= quickstart.o
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/quickstart/quickstart.c linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/quickstart.c
--- linux-libre-3.16-gnu/drivers/staging/quickstart/quickstart.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/quickstart/quickstart.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,458 +0,0 @@
-/*
- *  quickstart.c - ACPI Direct App Launch driver
- *
- *
- *  Copyright (C) 2007-2010 Angelo Arrifano <miknix@gmail.com>
- *
- *  Information gathered from disassembled dsdt and from here:
- *  <http://www.microsoft.com/whdc/system/platform/firmware/DirAppLaunch.mspx>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define QUICKSTART_VERSION "1.04"
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/acpi.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-
-MODULE_AUTHOR("Angelo Arrifano");
-MODULE_DESCRIPTION("ACPI Direct App Launch driver");
-MODULE_LICENSE("GPL");
-
-#define QUICKSTART_ACPI_DEVICE_NAME	"quickstart"
-#define QUICKSTART_ACPI_CLASS		"quickstart"
-#define QUICKSTART_ACPI_HID		"PNP0C32"
-
-#define QUICKSTART_PF_DRIVER_NAME	"quickstart"
-#define QUICKSTART_PF_DEVICE_NAME	"quickstart"
-
-/*
- * There will be two events:
- * 0x02 - A hot button was pressed while device was off/sleeping.
- * 0x80 - A hot button was pressed while device was up.
- */
-#define QUICKSTART_EVENT_WAKE		0x02
-#define QUICKSTART_EVENT_RUNTIME	0x80
-
-struct quickstart_button {
-	char *name;
-	unsigned int id;
-	struct list_head list;
-};
-
-struct quickstart_acpi {
-	struct acpi_device *device;
-	struct quickstart_button *button;
-};
-
-static LIST_HEAD(buttons);
-static struct quickstart_button *pressed;
-
-static struct input_dev *quickstart_input;
-
-/* Platform driver functions */
-static ssize_t buttons_show(struct device *dev, struct device_attribute *attr,
-			    char *buf)
-{
-	int count = 0;
-	struct quickstart_button *b;
-
-	if (list_empty(&buttons))
-		return snprintf(buf, PAGE_SIZE, "none");
-
-	list_for_each_entry(b, &buttons, list) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%u\t%s\n",
-							b->id, b->name);
-
-		if (count >= PAGE_SIZE) {
-			count = PAGE_SIZE;
-			break;
-		}
-	}
-
-	return count;
-}
-
-static ssize_t pressed_button_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%s\n",
-					(pressed ? pressed->name : "none"));
-}
-
-
-static ssize_t pressed_button_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	if (count < 2)
-		return -EINVAL;
-
-	if (strncasecmp(buf, "none", 4) != 0)
-		return -EINVAL;
-
-	pressed = NULL;
-	return count;
-}
-
-/* Helper functions */
-static struct quickstart_button *quickstart_buttons_add(void)
-{
-	struct quickstart_button *b;
-
-	b = kzalloc(sizeof(*b), GFP_KERNEL);
-	if (!b)
-		return NULL;
-
-	list_add_tail(&b->list, &buttons);
-
-	return b;
-}
-
-static void quickstart_button_del(struct quickstart_button *data)
-{
-	if (!data)
-		return;
-
-	list_del(&data->list);
-	kfree(data->name);
-	kfree(data);
-}
-
-static void quickstart_buttons_free(void)
-{
-	struct quickstart_button *b, *n;
-
-	list_for_each_entry_safe(b, n, &buttons, list)
-		quickstart_button_del(b);
-}
-
-/* ACPI Driver functions */
-static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data)
-{
-	struct quickstart_acpi *quickstart = data;
-
-	if (!quickstart)
-		return;
-
-	switch (event) {
-	case QUICKSTART_EVENT_WAKE:
-		pressed = quickstart->button;
-		break;
-	case QUICKSTART_EVENT_RUNTIME:
-		input_report_key(quickstart_input, quickstart->button->id, 1);
-		input_sync(quickstart_input);
-		input_report_key(quickstart_input, quickstart->button->id, 0);
-		input_sync(quickstart_input);
-		break;
-	default:
-		pr_err("Unexpected ACPI event notify (%u)\n", event);
-		break;
-	}
-}
-
-static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart)
-{
-	acpi_status status;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	int ret = 0;
-
-	/*
-	 * This returns a buffer telling the button usage ID,
-	 * and triggers pending notify events (The ones before booting).
-	 */
-	status = acpi_evaluate_object(quickstart->device->handle, "GHID", NULL,
-								&buffer);
-	if (ACPI_FAILURE(status)) {
-		pr_err("%s GHID method failed\n", quickstart->button->name);
-		return -EINVAL;
-	}
-
-	/*
-	 * <<The GHID method can return a BYTE, WORD, or DWORD.
-	 * The value must be encoded in little-endian byte
-	 * order (least significant byte first).>>
-	 */
-	switch (buffer.length) {
-	case 1:
-		quickstart->button->id = *(uint8_t *)buffer.pointer;
-		break;
-	case 2:
-		quickstart->button->id = *(uint16_t *)buffer.pointer;
-		break;
-	case 4:
-		quickstart->button->id = *(uint32_t *)buffer.pointer;
-		break;
-	case 8:
-		quickstart->button->id = *(uint64_t *)buffer.pointer;
-		break;
-	default:
-		pr_err("%s GHID method returned buffer of unexpected length %lu\n",
-				quickstart->button->name,
-				(unsigned long)buffer.length);
-		ret = -EINVAL;
-		break;
-	}
-
-	kfree(buffer.pointer);
-
-	return ret;
-}
-
-static int quickstart_acpi_config(struct quickstart_acpi *quickstart)
-{
-	char *bid = acpi_device_bid(quickstart->device);
-	char *name;
-
-	name = kmalloc(strlen(bid) + 1, GFP_KERNEL);
-	if (!name)
-		return -ENOMEM;
-
-	/* Add new button to list */
-	quickstart->button = quickstart_buttons_add();
-	if (!quickstart->button) {
-		kfree(name);
-		return -ENOMEM;
-	}
-
-	quickstart->button->name = name;
-	strcpy(quickstart->button->name, bid);
-
-	return 0;
-}
-
-static int quickstart_acpi_add(struct acpi_device *device)
-{
-	int ret;
-	acpi_status status;
-	struct quickstart_acpi *quickstart;
-
-	if (!device)
-		return -EINVAL;
-
-	quickstart = kzalloc(sizeof(*quickstart), GFP_KERNEL);
-	if (!quickstart)
-		return -ENOMEM;
-
-	quickstart->device = device;
-
-	strcpy(acpi_device_name(device), QUICKSTART_ACPI_DEVICE_NAME);
-	strcpy(acpi_device_class(device), QUICKSTART_ACPI_CLASS);
-	device->driver_data = quickstart;
-
-	/* Add button to list and initialize some stuff */
-	ret = quickstart_acpi_config(quickstart);
-	if (ret < 0)
-		goto fail_config;
-
-	status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY,
-						quickstart_acpi_notify,
-						quickstart);
-	if (ACPI_FAILURE(status)) {
-		pr_err("Notify handler install error\n");
-		ret = -ENODEV;
-		goto fail_installnotify;
-	}
-
-	ret = quickstart_acpi_ghid(quickstart);
-	if (ret < 0)
-		goto fail_ghid;
-
-	return 0;
-
-fail_ghid:
-	acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY,
-						quickstart_acpi_notify);
-
-fail_installnotify:
-	quickstart_button_del(quickstart->button);
-
-fail_config:
-
-	kfree(quickstart);
-
-	return ret;
-}
-
-static int quickstart_acpi_remove(struct acpi_device *device)
-{
-	acpi_status status;
-	struct quickstart_acpi *quickstart;
-
-	if (!device)
-		return -EINVAL;
-
-	quickstart = acpi_driver_data(device);
-	if (!quickstart)
-		return -EINVAL;
-
-	status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY,
-						quickstart_acpi_notify);
-	if (ACPI_FAILURE(status))
-		pr_err("Error removing notify handler\n");
-
-	kfree(quickstart);
-
-	return 0;
-}
-
-/* Platform driver structs */
-static DEVICE_ATTR_RW(pressed_button);
-static DEVICE_ATTR_RO(buttons);
-static struct platform_device *pf_device;
-static struct platform_driver pf_driver = {
-	.driver = {
-		.name = QUICKSTART_PF_DRIVER_NAME,
-		.owner = THIS_MODULE,
-	}
-};
-
-static const struct acpi_device_id quickstart_device_ids[] = {
-	{QUICKSTART_ACPI_HID, 0},
-	{"", 0},
-};
-
-static struct acpi_driver quickstart_acpi_driver = {
-	.name = "quickstart",
-	.class = QUICKSTART_ACPI_CLASS,
-	.ids = quickstart_device_ids,
-	.ops = {
-			.add = quickstart_acpi_add,
-			.remove = quickstart_acpi_remove,
-		},
-};
-
-/* Module functions */
-static void quickstart_exit(void)
-{
-	input_unregister_device(quickstart_input);
-
-	device_remove_file(&pf_device->dev, &dev_attr_pressed_button);
-	device_remove_file(&pf_device->dev, &dev_attr_buttons);
-
-	platform_device_unregister(pf_device);
-
-	platform_driver_unregister(&pf_driver);
-
-	acpi_bus_unregister_driver(&quickstart_acpi_driver);
-
-	quickstart_buttons_free();
-}
-
-static int __init quickstart_init_input(void)
-{
-	struct quickstart_button *b;
-	int ret;
-
-	quickstart_input = input_allocate_device();
-
-	if (!quickstart_input)
-		return -ENOMEM;
-
-	quickstart_input->name = "Quickstart ACPI Buttons";
-	quickstart_input->id.bustype = BUS_HOST;
-
-	list_for_each_entry(b, &buttons, list) {
-		set_bit(EV_KEY, quickstart_input->evbit);
-		set_bit(b->id, quickstart_input->keybit);
-	}
-
-	ret = input_register_device(quickstart_input);
-	if (ret) {
-		input_free_device(quickstart_input);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int __init quickstart_init(void)
-{
-	int ret;
-
-	/* ACPI driver register */
-	ret = acpi_bus_register_driver(&quickstart_acpi_driver);
-	if (ret)
-		return ret;
-
-	/* If existing bus with no devices */
-	if (list_empty(&buttons)) {
-		ret = -ENODEV;
-		goto fail_pfdrv_reg;
-	}
-
-	/* Platform driver register */
-	ret = platform_driver_register(&pf_driver);
-	if (ret)
-		goto fail_pfdrv_reg;
-
-	/* Platform device register */
-	pf_device = platform_device_alloc(QUICKSTART_PF_DEVICE_NAME, -1);
-	if (!pf_device) {
-		ret = -ENOMEM;
-		goto fail_pfdev_alloc;
-	}
-	ret = platform_device_add(pf_device);
-	if (ret)
-		goto fail_pfdev_add;
-
-	/* Create device sysfs file */
-	ret = device_create_file(&pf_device->dev, &dev_attr_pressed_button);
-	if (ret)
-		goto fail_dev_file;
-
-	ret = device_create_file(&pf_device->dev, &dev_attr_buttons);
-	if (ret)
-		goto fail_dev_file2;
-
-	/* Input device */
-	ret = quickstart_init_input();
-	if (ret)
-		goto fail_input;
-
-	pr_info("ACPI Direct App Launch ver %s\n", QUICKSTART_VERSION);
-
-	return 0;
-fail_input:
-	device_remove_file(&pf_device->dev, &dev_attr_buttons);
-
-fail_dev_file2:
-	device_remove_file(&pf_device->dev, &dev_attr_pressed_button);
-
-fail_dev_file:
-	platform_device_del(pf_device);
-
-fail_pfdev_add:
-	platform_device_put(pf_device);
-
-fail_pfdev_alloc:
-	platform_driver_unregister(&pf_driver);
-
-fail_pfdrv_reg:
-	acpi_bus_unregister_driver(&quickstart_acpi_driver);
-
-	return ret;
-}
-
-module_init(quickstart_init);
-module_exit(quickstart_exit);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ap.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ap.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ap.c	2014-09-28 17:29:07.000000000 -0400
@@ -288,14 +288,14 @@ void	expire_timeout_chk(struct adapter *
 	plist = phead->next;
 
 	/* check auth_queue */
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, auth_list);
 		plist = plist->next;
 
 		if (psta->expire_to > 0) {
 			psta->expire_to--;
 			if (psta->expire_to == 0) {
-				rtw_list_delete(&psta->auth_list);
+				list_del_init(&psta->auth_list);
 				pstapriv->auth_list_cnt--;
 
 				DBG_88E("auth expire %6ph\n",
@@ -322,7 +322,7 @@ void	expire_timeout_chk(struct adapter *
 	plist = phead->next;
 
 	/* check asoc_queue */
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, asoc_list);
 		plist = plist->next;
 
@@ -365,7 +365,7 @@ void	expire_timeout_chk(struct adapter *
 				continue;
 			}
 
-			rtw_list_delete(&psta->asoc_list);
+			list_del_init(&psta->asoc_list);
 			pstapriv->asoc_list_cnt--;
 
 			DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
@@ -421,7 +421,7 @@ void	expire_timeout_chk(struct adapter *
 
 			DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
 			spin_lock_bh(&pstapriv->asoc_list_lock);
-			rtw_list_delete(&psta->asoc_list);
+			list_del_init(&psta->asoc_list);
 			pstapriv->asoc_list_cnt--;
 			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
 			spin_unlock_bh(&pstapriv->asoc_list_lock);
@@ -548,7 +548,7 @@ static void update_bmc_sta(struct adapte
 
 		psta->ieee8021x_blocked = 0;
 
-		_rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+		memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
 
 		/* prepare for add_RATid */
 		supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
@@ -671,7 +671,7 @@ void update_sta_info_apmode(struct adapt
 
 	/* todo: init other variables */
 
-	_rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+	memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
 
 	spin_lock_bh(&psta->lock);
 	psta->state |= _FW_LINKED;
@@ -723,9 +723,6 @@ static void start_bss_network(struct ada
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network);
 	struct HT_info_element *pht_info = NULL;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
 	cur_channel = pnetwork->Configuration.DSConfig;
@@ -827,11 +824,6 @@ static void start_bss_network(struct ada
 	/* let pnetwork_mlmeext == pnetwork_mlme. */
 	memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
 
-#ifdef CONFIG_88EU_P2P
-	memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);
-	pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;
-#endif /* CONFIG_88EU_P2P */
-
 	if (pmlmeext->bstart_bss) {
 		update_beacon(padapter, _TIM_IE_, NULL, false);
 
@@ -886,7 +878,7 @@ int rtw_check_beacon_data(struct adapter
 
 	pbss_network->IELength = len;
 
-	_rtw_memset(ie, 0, MAX_IE_SZ);
+	memset(ie, 0, MAX_IE_SZ);
 
 	memcpy(ie, pbuf, pbss_network->IELength);
 
@@ -900,15 +892,15 @@ int rtw_check_beacon_data(struct adapter
 
 	/* beacon interval */
 	p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
-	pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
+	pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
 
 	/* capability */
-	cap = RTW_GET_LE16(ie);
+	cap = get_unaligned_le16(ie);
 
 	/* SSID */
 	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0) {
-		_rtw_memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+		memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
 		memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
 		pbss_network->Ssid.SsidLength = ie_len;
 	}
@@ -922,7 +914,7 @@ int rtw_check_beacon_data(struct adapter
 
 	pbss_network->Configuration.DSConfig = channel;
 
-	_rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
+	memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
 	/*  get supported rates */
 	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p !=  NULL) {
@@ -1146,7 +1138,7 @@ int rtw_acl_add_sta(struct adapter *pada
 	phead = get_list_head(pacl_node_q);
 	plist = phead->next;
 
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 		plist = plist->next;
 
@@ -1170,13 +1162,13 @@ int rtw_acl_add_sta(struct adapter *pada
 		paclnode = &pacl_list->aclnode[i];
 
 		if (!paclnode->valid) {
-			_rtw_init_listhead(&paclnode->list);
+			INIT_LIST_HEAD(&paclnode->list);
 
 			memcpy(paclnode->addr, addr, ETH_ALEN);
 
 			paclnode->valid = true;
 
-			rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
+			list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
 
 			pacl_list->num++;
 
@@ -1207,7 +1199,7 @@ int rtw_acl_remove_sta(struct adapter *p
 	phead = get_list_head(pacl_node_q);
 	plist = phead->next;
 
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 		plist = plist->next;
 
@@ -1215,7 +1207,7 @@ int rtw_acl_remove_sta(struct adapter *p
 			if (paclnode->valid) {
 				paclnode->valid = false;
 
-				rtw_list_delete(&paclnode->list);
+				list_del_init(&paclnode->list);
 
 				pacl_list->num--;
 			}
@@ -1505,7 +1497,7 @@ void associated_clients_update(struct ad
 		plist = phead->next;
 
 		/* check asoc_queue */
-		while ((rtw_end_of_queue_search(phead, plist)) == false) {
+		while (phead != plist) {
 			psta = container_of(plist, struct sta_info, asoc_list);
 
 			plist = plist->next;
@@ -1779,7 +1771,7 @@ int rtw_ap_inform_ch_switch(struct adapt
 	plist = phead->next;
 
 	/* for each sta in asoc_queue */
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, asoc_list);
 		plist = plist->next;
 
@@ -1813,12 +1805,12 @@ int rtw_sta_flush(struct adapter *padapt
 	plist = phead->next;
 
 	/* free sta asoc_queue */
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, asoc_list);
 
 		plist = plist->next;
 
-		rtw_list_delete(&psta->asoc_list);
+		list_del_init(&psta->asoc_list);
 		pstapriv->asoc_list_cnt--;
 
 		ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
@@ -1910,11 +1902,11 @@ void start_ap_mode(struct adapter *padap
 	pmlmepriv->p2p_probe_resp_ie = NULL;
 
 	/* for ACL */
-	_rtw_init_listhead(&(pacl_list->acl_node_q.queue));
+	INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue));
 	pacl_list->num = 0;
 	pacl_list->mode = 0;
 	for (i = 0; i < NUM_ACL; i++) {
-		_rtw_init_listhead(&pacl_list->aclnode[i].list);
+		INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
 		pacl_list->aclnode[i].valid = false;
 	}
 }
@@ -1934,7 +1926,7 @@ void stop_ap_mode(struct adapter *padapt
 	pmlmeext->bstart_bss = false;
 
 	/* reset and init security priv , this can refine with rtw_reset_securitypriv */
-	_rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
+	memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
 	padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
 	padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
 
@@ -1942,14 +1934,14 @@ void stop_ap_mode(struct adapter *padapt
 	spin_lock_bh(&(pacl_node_q->lock));
 	phead = get_list_head(pacl_node_q);
 	plist = phead->next;
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+	while (phead != plist) {
 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 		plist = plist->next;
 
 		if (paclnode->valid) {
 			paclnode->valid = false;
 
-			rtw_list_delete(&paclnode->list);
+			list_del_init(&paclnode->list);
 
 			pacl_list->num--;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_br_ext.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_br_ext.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_br_ext.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_br_ext.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1191 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTW_BR_EXT_C_
-
-#include <linux/if_arp.h>
-#include <net/ip.h>
-#include <net/ipx.h>
-#include <linux/atalk.h>
-#include <linux/udp.h>
-#include <linux/if_pppox.h>
-
-#include <drv_types.h>
-#include "rtw_br_ext.h"
-#include <usb_osintf.h>
-#include <recv_osdep.h>
-
-#ifndef csum_ipv6_magic
-#include <net/ip6_checksum.h>
-#endif
-
-#include <linux/ipv6.h>
-#include <linux/icmpv6.h>
-#include <net/ndisc.h>
-#include <net/checksum.h>
-
-#define NAT25_IPV4		01
-#define NAT25_IPV6		02
-#define NAT25_IPX		03
-#define NAT25_APPLE		04
-#define NAT25_PPPOE		05
-
-#define RTL_RELAY_TAG_LEN (ETH_ALEN)
-#define TAG_HDR_LEN		4
-
-#define MAGIC_CODE		0x8186
-#define MAGIC_CODE_LEN	2
-#define WAIT_TIME_PPPOE	5	/*  waiting time for pppoe server in sec */
-
-/*-----------------------------------------------------------------
-  How database records network address:
-	   0    1    2    3    4    5    6    7    8    9   10
-	|----|----|----|----|----|----|----|----|----|----|----|
-  IPv4  |type|                             |      IP addr      |
-  IPX   |type|      Net addr     |          Node addr          |
-  IPX   |type|      Net addr     |Sckt addr|
-  Apple |type| Network |node|
-  PPPoE |type|   SID   |           AC MAC            |
------------------------------------------------------------------*/
-
-
-/* Find a tag in pppoe frame and return the pointer */
-static inline unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
-{
-	unsigned char *cur_ptr, *start_ptr;
-	unsigned short tagLen, tagType;
-
-	start_ptr = cur_ptr = (unsigned char *)ph->tag;
-	while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
-		/*  prevent un-alignment access */
-		tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
-		tagLen  = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
-		if (tagType == type)
-			return cur_ptr;
-		cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
-	}
-	return NULL;
-}
-
-
-static inline int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
-{
-	struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
-	int data_len;
-
-	data_len = be16_to_cpu(tag->tag_len) + TAG_HDR_LEN;
-	if (skb_tailroom(skb) < data_len) {
-		_DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
-		return -1;
-	}
-
-	skb_put(skb, data_len);
-	/*  have a room for new tag */
-	memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
-	ph->length = htons(ntohs(ph->length) + data_len);
-	memcpy((unsigned char *)ph->tag, tag, data_len);
-	return data_len;
-}
-
-static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
-{
-	int tail_len;
-	unsigned long end, tail;
-
-	if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
-		return -1;
-
-	tail = (unsigned long)skb_tail_pointer(skb);
-	end = (unsigned long)src+len;
-	if (tail < end)
-		return -1;
-
-	tail_len = (int)(tail-end);
-	if (tail_len > 0)
-		memmove(src, src+len, tail_len);
-
-	skb_trim(skb, skb->len-len);
-	return 0;
-}
-
-static inline unsigned long __nat25_timeout(struct adapter *priv)
-{
-	unsigned long timeout;
-
-	timeout = jiffies - NAT25_AGEING_TIME*HZ;
-
-	return timeout;
-}
-
-
-static inline int  __nat25_has_expired(struct adapter *priv,
-				struct nat25_network_db_entry *fdb)
-{
-	if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
-		return 1;
-
-	return 0;
-}
-
-
-static inline void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
-				unsigned int *ipAddr)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_IPV4;
-	memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
-}
-
-
-static inline void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
-				__be32 *ipxNetAddr, unsigned char *ipxNodeAddr)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_IPX;
-	memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
-	memcpy(networkAddr+5, ipxNodeAddr, 6);
-}
-
-
-static inline void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
-				__be32 *ipxNetAddr, __be16 *ipxSocketAddr)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_IPX;
-	memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
-	memcpy(networkAddr+5, (unsigned char *)ipxSocketAddr, 2);
-}
-
-
-static inline void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
-				__be16 *network, unsigned char *node)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_APPLE;
-	memcpy(networkAddr+1, (unsigned char *)network, 2);
-	networkAddr[3] = *node;
-}
-
-static inline void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
-				unsigned char *ac_mac, __be16 *sid)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_PPPOE;
-	memcpy(networkAddr+1, (unsigned char *)sid, 2);
-	memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
-}
-
-static  void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
-				__be32 *ipAddr)
-{
-	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
-
-	networkAddr[0] = NAT25_IPV6;
-	memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
-}
-
-static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
-{
-	while (len > 0) {
-		if (*data == tag && *(data+1) == len8b && len >= len8b*8)
-			return data+2;
-
-		len -= (*(data+1))*8;
-		data += (*(data+1))*8;
-	}
-	return NULL;
-}
-
-static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
-{
-	struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
-	unsigned char *mac;
-
-	if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
-		if (len >= 8) {
-			mac = scan_tlv(&data[8], len-8, 1, 1);
-			if (mac) {
-				_DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-					replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
-				memcpy(mac, replace_mac, 6);
-				return 1;
-			}
-		}
-	} else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
-		if (len >= 16) {
-			mac = scan_tlv(&data[16], len-16, 1, 1);
-			if (mac) {
-				_DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-					replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
-				memcpy(mac, replace_mac, 6);
-				return 1;
-			}
-		}
-	} else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
-		if (len >= 24) {
-			mac = scan_tlv(&data[24], len-24, 1, 1);
-			if (mac) {
-				_DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-					replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
-				memcpy(mac, replace_mac, 6);
-				return 1;
-			}
-		}
-	} else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
-		if (len >= 24) {
-			mac = scan_tlv(&data[24], len-24, 2, 1);
-			if (mac) {
-				_DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-					replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
-				memcpy(mac, replace_mac, 6);
-				return 1;
-			}
-		}
-	} else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
-		if (len >= 40) {
-			mac = scan_tlv(&data[40], len-40, 2, 1);
-			if (mac) {
-				_DEBUG_INFO("Redirect,  replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-					replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
-				memcpy(mac, replace_mac, 6);
-				return 1;
-			}
-		}
-	}
-	return 0;
-}
-
-static inline int __nat25_network_hash(unsigned char *networkAddr)
-{
-	if (networkAddr[0] == NAT25_IPV4) {
-		unsigned long x;
-
-		x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	} else if (networkAddr[0] == NAT25_IPX) {
-		unsigned long x;
-
-		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
-			networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	} else if (networkAddr[0] == NAT25_APPLE) {
-		unsigned long x;
-
-		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	} else if (networkAddr[0] == NAT25_PPPOE) {
-		unsigned long x;
-
-		x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	} else if (networkAddr[0] == NAT25_IPV6) {
-		unsigned long x;
-
-		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
-			networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
-			networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
-			networkAddr[16];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	} else {
-		unsigned long x = 0;
-		int i;
-
-		for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
-			x ^= networkAddr[i];
-
-		return x & (NAT25_HASH_SIZE - 1);
-	}
-}
-
-static inline void __network_hash_link(struct adapter *priv,
-				struct nat25_network_db_entry *ent, int hash)
-{
-	/*  Caller must spin_lock_bh already! */
-	ent->next_hash = priv->nethash[hash];
-	if (ent->next_hash != NULL)
-		ent->next_hash->pprev_hash = &ent->next_hash;
-	priv->nethash[hash] = ent;
-	ent->pprev_hash = &priv->nethash[hash];
-}
-
-static inline void __network_hash_unlink(struct nat25_network_db_entry *ent)
-{
-	/*  Caller must spin_lock_bh already! */
-	*(ent->pprev_hash) = ent->next_hash;
-	if (ent->next_hash != NULL)
-		ent->next_hash->pprev_hash = ent->pprev_hash;
-	ent->next_hash = NULL;
-	ent->pprev_hash = NULL;
-}
-
-static int __nat25_db_network_lookup_and_replace(struct adapter *priv,
-				struct sk_buff *skb, unsigned char *networkAddr)
-{
-	struct nat25_network_db_entry *db;
-	spin_lock_bh(&priv->br_ext_lock);
-
-	db = priv->nethash[__nat25_network_hash(networkAddr)];
-	while (db != NULL) {
-		if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
-			if (!__nat25_has_expired(priv, db)) {
-				/*  replace the destination mac address */
-				memcpy(skb->data, db->macAddr, ETH_ALEN);
-				atomic_inc(&db->use_count);
-
-				DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
-							"%02x%02x%02x%02x%02x%02x\n",
-					db->macAddr[0],
-					db->macAddr[1],
-					db->macAddr[2],
-					db->macAddr[3],
-					db->macAddr[4],
-					db->macAddr[5],
-					db->networkAddr[0],
-					db->networkAddr[1],
-					db->networkAddr[2],
-					db->networkAddr[3],
-					db->networkAddr[4],
-					db->networkAddr[5],
-					db->networkAddr[6],
-					db->networkAddr[7],
-					db->networkAddr[8],
-					db->networkAddr[9],
-					db->networkAddr[10],
-					db->networkAddr[11],
-					db->networkAddr[12],
-					db->networkAddr[13],
-					db->networkAddr[14],
-					db->networkAddr[15],
-					db->networkAddr[16]);
-			}
-			spin_unlock_bh(&priv->br_ext_lock);
-			return 1;
-		}
-		db = db->next_hash;
-	}
-	spin_unlock_bh(&priv->br_ext_lock);
-	return 0;
-}
-
-static void __nat25_db_network_insert(struct adapter *priv,
-				unsigned char *macAddr, unsigned char *networkAddr)
-{
-	struct nat25_network_db_entry *db;
-	int hash;
-
-	spin_lock_bh(&priv->br_ext_lock);
-	hash = __nat25_network_hash(networkAddr);
-	db = priv->nethash[hash];
-	while (db != NULL) {
-		if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
-			ether_addr_copy(db->macAddr, macAddr);
-			db->ageing_timer = jiffies;
-			spin_unlock_bh(&priv->br_ext_lock);
-			return;
-		}
-		db = db->next_hash;
-	}
-	db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
-	if (db == NULL) {
-		spin_unlock_bh(&priv->br_ext_lock);
-		return;
-	}
-	memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
-	ether_addr_copy(db->macAddr, macAddr);
-	atomic_set(&db->use_count, 1);
-	db->ageing_timer = jiffies;
-
-	__network_hash_link(priv, db, hash);
-
-	spin_unlock_bh(&priv->br_ext_lock);
-}
-
-static void __nat25_db_print(struct adapter *priv)
-{
-}
-
-/*
- *	NAT2.5 interface
- */
-
-void nat25_db_cleanup(struct adapter *priv)
-{
-	int i;
-
-	spin_lock_bh(&priv->br_ext_lock);
-
-	for (i = 0; i < NAT25_HASH_SIZE; i++) {
-		struct nat25_network_db_entry *f;
-		f = priv->nethash[i];
-		while (f != NULL) {
-			struct nat25_network_db_entry *g;
-
-			g = f->next_hash;
-			if (priv->scdb_entry == f) {
-				memset(priv->scdb_mac, 0, ETH_ALEN);
-				memset(priv->scdb_ip, 0, 4);
-				priv->scdb_entry = NULL;
-			}
-			__network_hash_unlink(f);
-			kfree(f);
-			f = g;
-		}
-	}
-	spin_unlock_bh(&priv->br_ext_lock);
-}
-
-void nat25_db_expire(struct adapter *priv)
-{
-	int i;
-	spin_lock_bh(&priv->br_ext_lock);
-
-	for (i = 0; i < NAT25_HASH_SIZE; i++) {
-		struct nat25_network_db_entry *f;
-		f = priv->nethash[i];
-
-		while (f != NULL) {
-			struct nat25_network_db_entry *g;
-			g = f->next_hash;
-
-			if (__nat25_has_expired(priv, f)) {
-				if (atomic_dec_and_test(&f->use_count)) {
-					if (priv->scdb_entry == f) {
-						memset(priv->scdb_mac, 0, ETH_ALEN);
-						memset(priv->scdb_ip, 0, 4);
-						priv->scdb_entry = NULL;
-					}
-					__network_hash_unlink(f);
-					kfree(f);
-				}
-			}
-			f = g;
-		}
-	}
-	spin_unlock_bh(&priv->br_ext_lock);
-}
-
-int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
-{
-	unsigned short protocol;
-	unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
-	unsigned int tmp;
-
-	if (skb == NULL)
-		return -1;
-
-	if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
-		return -1;
-
-	protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
-
-	/*---------------------------------------------------*/
-	/*                 Handle IP frame                   */
-	/*---------------------------------------------------*/
-	if (protocol == ETH_P_IP) {
-		struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
-
-		if (((unsigned char *)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) {
-			DEBUG_WARN("NAT25: malformed IP packet !\n");
-			return -1;
-		}
-
-		switch (method) {
-		case NAT25_CHECK:
-			return -1;
-		case NAT25_INSERT:
-			/* some multicast with source IP is all zero, maybe other case is illegal */
-			/* in class A, B, C, host address is all zero or all one is illegal */
-			if (iph->saddr == 0)
-				return 0;
-			tmp = be32_to_cpu(iph->saddr);
-			DEBUG_INFO("NAT25: Insert IP, SA =%08x, DA =%08x\n", tmp, iph->daddr);
-			__nat25_generate_ipv4_network_addr(networkAddr, &tmp);
-			/* record source IP address and , source mac address into db */
-			__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-
-			__nat25_db_print(priv);
-			return 0;
-		case NAT25_LOOKUP:
-			DEBUG_INFO("NAT25: Lookup IP, SA =%08x, DA =%08x\n", iph->saddr, iph->daddr);
-			tmp = be32_to_cpu(iph->daddr);
-			__nat25_generate_ipv4_network_addr(networkAddr, &tmp);
-
-			if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
-				if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
-					/*  L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
-					DEBUG_INFO("NAT25: Set DA as broadcast\n");
-					memset(skb->data, 0xff, ETH_ALEN);
-				} else {
-					/*  forward unknown IP packet to upper TCP/IP */
-					DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
-					if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
-						netdev_info(skb->dev,
-								"Re-init netdev_br_init() due to br_mac == 0!\n");
-						netdev_br_init(priv->pnetdev);
-					}
-					memcpy(skb->data, priv->br_mac, ETH_ALEN);
-				}
-			}
-			return 0;
-		default:
-			return -1;
-		}
-	} else if (protocol == ETH_P_ARP) {
-		/*---------------------------------------------------*/
-		/*                 Handle ARP frame                  */
-		/*---------------------------------------------------*/
-		struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
-		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-		unsigned int *sender, *target;
-
-		if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
-			DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", be16_to_cpu(arp->ar_pro));
-			return -1;
-		}
-
-		switch (method) {
-		case NAT25_CHECK:
-			return 0;	/*  skb_copy for all ARP frame */
-		case NAT25_INSERT:
-			DEBUG_INFO("NAT25: Insert ARP, MAC =%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
-				arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
-
-			/*  change to ARP sender mac address to wlan STA address */
-			memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
-			arp_ptr += arp->ar_hln;
-			sender = (unsigned int *)arp_ptr;
-			__nat25_generate_ipv4_network_addr(networkAddr, sender);
-			__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-			__nat25_db_print(priv);
-			return 0;
-		case NAT25_LOOKUP:
-			DEBUG_INFO("NAT25: Lookup ARP\n");
-
-			arp_ptr += arp->ar_hln;
-			sender = (unsigned int *)arp_ptr;
-			arp_ptr += (arp->ar_hln + arp->ar_pln);
-			target = (unsigned int *)arp_ptr;
-			__nat25_generate_ipv4_network_addr(networkAddr, target);
-			__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-			/*  change to ARP target mac address to Lookup result */
-			arp_ptr = (unsigned char *)(arp + 1);
-			arp_ptr += (arp->ar_hln + arp->ar_pln);
-			memcpy(arp_ptr, skb->data, ETH_ALEN);
-			return 0;
-		default:
-			return -1;
-		}
-	} else if ((protocol == ETH_P_IPX) ||
-		   (protocol <= ETH_FRAME_LEN)) {
-		/*---------------------------------------------------*/
-		/*         Handle IPX and Apple Talk frame           */
-		/*---------------------------------------------------*/
-		unsigned char ipx_header[2] = {0xFF, 0xFF};
-		struct ipxhdr	*ipx = NULL;
-		struct elapaarp	*ea = NULL;
-		struct ddpehdr	*ddp = NULL;
-		unsigned char *framePtr = skb->data + ETH_HLEN;
-
-		if (protocol == ETH_P_IPX) {
-			DEBUG_INFO("NAT25: Protocol = IPX (Ethernet II)\n");
-			ipx = (struct ipxhdr *)framePtr;
-		} else if (protocol <= ETH_FRAME_LEN) {
-			if (!memcmp(ipx_header, framePtr, 2)) {
-				DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.3)\n");
-				ipx = (struct ipxhdr *)framePtr;
-			} else {
-				unsigned char ipx_8022_type =  0xE0;
-				unsigned char snap_8022_type = 0xAA;
-
-				if (*framePtr == snap_8022_type) {
-					unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37};		/*  IPX SNAP ID */
-					unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3};	/*  Apple Talk AARP SNAP ID */
-					unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B};	/*  Apple Talk DDP SNAP ID */
-
-					framePtr += 3;	/*  eliminate the 802.2 header */
-
-					if (!memcmp(ipx_snap_id, framePtr, 5)) {
-						framePtr += 5;	/*  eliminate the SNAP header */
-
-						DEBUG_INFO("NAT25: Protocol = IPX (Ethernet SNAP)\n");
-						ipx = (struct ipxhdr *)framePtr;
-					} else if (!memcmp(aarp_snap_id, framePtr, 5)) {
-						framePtr += 5;	/*  eliminate the SNAP header */
-
-						ea = (struct elapaarp *)framePtr;
-					} else if (!memcmp(ddp_snap_id, framePtr, 5)) {
-						framePtr += 5;	/*  eliminate the SNAP header */
-
-						ddp = (struct ddpehdr *)framePtr;
-					} else {
-						DEBUG_WARN("NAT25: Protocol = Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
-							framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
-						return -1;
-					}
-				} else if (*framePtr == ipx_8022_type) {
-					framePtr += 3;	/*  eliminate the 802.2 header */
-
-					if (!memcmp(ipx_header, framePtr, 2)) {
-						DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.2)\n");
-						ipx = (struct ipxhdr *)framePtr;
-					} else {
-						return -1;
-					}
-				} else {
-					return -1;
-				}
-			}
-		} else {
-			return -1;
-		}
-
-		/*   IPX   */
-		if (ipx != NULL) {
-			switch (method) {
-			case NAT25_CHECK:
-				if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
-					DEBUG_INFO("NAT25: Check IPX skb_copy\n");
-				return 0;
-			case NAT25_INSERT:
-				DEBUG_INFO("NAT25: Insert IPX, Dest =%08x,%02x%02x%02x%02x%02x%02x,%04x Source =%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
-					ipx->ipx_dest.net,
-					ipx->ipx_dest.node[0],
-					ipx->ipx_dest.node[1],
-					ipx->ipx_dest.node[2],
-					ipx->ipx_dest.node[3],
-					ipx->ipx_dest.node[4],
-					ipx->ipx_dest.node[5],
-					ipx->ipx_dest.sock,
-					ipx->ipx_source.net,
-					ipx->ipx_source.node[0],
-					ipx->ipx_source.node[1],
-					ipx->ipx_source.node[2],
-					ipx->ipx_source.node[3],
-					ipx->ipx_source.node[4],
-					ipx->ipx_source.node[5],
-					ipx->ipx_source.sock);
-
-				if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
-					DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
-
-					__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
-
-					/*  change IPX source node addr to wlan STA address */
-					memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
-				} else {
-					__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
-				}
-				__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-				__nat25_db_print(priv);
-				return 0;
-			case NAT25_LOOKUP:
-				if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) {
-					DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
-
-					__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
-
-					__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-
-					/*  replace IPX destination node addr with Lookup destination MAC addr */
-					memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
-				} else {
-					__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
-
-					__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-				}
-				return 0;
-			default:
-				return -1;
-			}
-		} else if (ea != NULL) {
-			/* Sanity check fields. */
-			if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
-				DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
-				return -1;
-			}
-
-			switch (method) {
-			case NAT25_CHECK:
-				return 0;
-			case NAT25_INSERT:
-				/*  change to AARP source mac address to wlan STA address */
-				memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
-
-				DEBUG_INFO("NAT25: Insert AARP, Source =%d,%d Destination =%d,%d\n",
-					ea->pa_src_net,
-					ea->pa_src_node,
-					ea->pa_dst_net,
-					ea->pa_dst_node);
-
-				__nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
-
-				__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-
-				__nat25_db_print(priv);
-				return 0;
-			case NAT25_LOOKUP:
-				DEBUG_INFO("NAT25: Lookup AARP, Source =%d,%d Destination =%d,%d\n",
-					ea->pa_src_net,
-					ea->pa_src_node,
-					ea->pa_dst_net,
-					ea->pa_dst_node);
-
-				__nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
-
-				__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-
-				/*  change to AARP destination mac address to Lookup result */
-				memcpy(ea->hw_dst, skb->data, ETH_ALEN);
-				return 0;
-			default:
-				return -1;
-			}
-		} else if (ddp != NULL) {
-			switch (method) {
-			case NAT25_CHECK:
-				return -1;
-			case NAT25_INSERT:
-				DEBUG_INFO("NAT25: Insert DDP, Source =%d,%d Destination =%d,%d\n",
-					ddp->deh_snet,
-					ddp->deh_snode,
-					ddp->deh_dnet,
-					ddp->deh_dnode);
-
-				__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
-
-				__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-
-				__nat25_db_print(priv);
-				return 0;
-			case NAT25_LOOKUP:
-				DEBUG_INFO("NAT25: Lookup DDP, Source =%d,%d Destination =%d,%d\n",
-					ddp->deh_snet,
-					ddp->deh_snode,
-					ddp->deh_dnet,
-					ddp->deh_dnode);
-				__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
-				__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-				return 0;
-			default:
-				return -1;
-			}
-		}
-
-		return -1;
-	} else if ((protocol == ETH_P_PPP_DISC) ||
-		   (protocol == ETH_P_PPP_SES)) {
-		/*---------------------------------------------------*/
-		/*                Handle PPPoE frame                 */
-		/*---------------------------------------------------*/
-		struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
-		__be16 *pMagic;
-
-		switch (method) {
-		case NAT25_CHECK:
-			if (ph->sid == 0)
-				return 0;
-			return 1;
-		case NAT25_INSERT:
-			if (ph->sid == 0) {	/*  Discovery phase according to tag */
-				if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
-					if (priv->ethBrExtInfo.addPPPoETag) {
-						struct pppoe_tag *tag, *pOldTag;
-						unsigned char tag_buf[40];
-						int old_tag_len = 0;
-
-						tag = (struct pppoe_tag *)tag_buf;
-						pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
-						if (pOldTag) { /*  if SID existed, copy old value and delete it */
-							old_tag_len = ntohs(pOldTag->tag_len);
-							if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
-								DEBUG_ERR("SID tag length too long!\n");
-								return -1;
-							}
-
-							memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
-								pOldTag->tag_data, old_tag_len);
-
-							if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
-								DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
-								return -1;
-							}
-							ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
-						}
-
-						tag->tag_type = PTT_RELAY_SID;
-						tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
-
-						/*  insert the magic_code+client mac in relay tag */
-						pMagic = (__be16 *)tag->tag_data;
-						*pMagic = htons(MAGIC_CODE);
-						memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
-
-						/* Add relay tag */
-						if (__nat25_add_pppoe_tag(skb, tag) < 0)
-							return -1;
-
-						DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
-										(ph->code == PADI_CODE ? "PADI" : "PADR"));
-					} else { /*  not add relay tag */
-						if (priv->pppoe_connection_in_progress &&
-								memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))	 {
-							DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
-							return -2;
-						}
-
-						if (priv->pppoe_connection_in_progress == 0)
-							memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
-
-						priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
-					}
-				} else {
-					return -1;
-				}
-			} else {	/*  session phase */
-				DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
-
-				__nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
-
-				__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-
-				__nat25_db_print(priv);
-
-				if (!priv->ethBrExtInfo.addPPPoETag &&
-				    priv->pppoe_connection_in_progress &&
-				    !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
-					priv->pppoe_connection_in_progress = 0;
-			}
-			return 0;
-		case NAT25_LOOKUP:
-			if (ph->code == PADO_CODE || ph->code == PADS_CODE) {
-				if (priv->ethBrExtInfo.addPPPoETag) {
-					struct pppoe_tag *tag;
-					unsigned char *ptr;
-					unsigned short tagType, tagLen;
-					int offset = 0;
-
-					ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
-					if (ptr == NULL) {
-						DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
-						return -1;
-					}
-
-					tag = (struct pppoe_tag *)ptr;
-					tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
-					tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
-
-					if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) {
-						DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
-						return -1;
-					}
-
-					pMagic = (__be16 *)tag->tag_data;
-					if (ntohs(*pMagic) != MAGIC_CODE) {
-						DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
-							(ph->code == PADO_CODE ? "PADO" : "PADS"));
-						return -1;
-					}
-
-					memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN);
-
-					if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN)
-						offset = TAG_HDR_LEN;
-
-					if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) {
-						DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
-						return -1;
-					}
-					ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset));
-					if (offset > 0)
-						tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN);
-
-					DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
-						(ph->code == PADO_CODE ? "PADO" : "PADS"),	skb->dev->name);
-				} else { /*  not add relay tag */
-					if (!priv->pppoe_connection_in_progress) {
-						DEBUG_ERR("Discard PPPoE packet due to no connection in progress!\n");
-						return -1;
-					}
-					memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
-					priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
-				}
-			} else {
-				if (ph->sid != 0) {
-					DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
-					__nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid));
-					__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-					__nat25_db_print(priv);
-				} else {
-					return -1;
-				}
-			}
-			return 0;
-		default:
-			return -1;
-		}
-	} else if (protocol == 0x888e) {
-		/*---------------------------------------------------*/
-		/*                 Handle EAP frame                  */
-		/*---------------------------------------------------*/
-		switch (method) {
-		case NAT25_CHECK:
-			return -1;
-		case NAT25_INSERT:
-			return 0;
-		case NAT25_LOOKUP:
-			return 0;
-		default:
-			return -1;
-		}
-	} else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) {
-		/*---------------------------------------------------*/
-		/*         Handle C-Media proprietary frame          */
-		/*---------------------------------------------------*/
-		switch (method) {
-		case NAT25_CHECK:
-			return -1;
-		case NAT25_INSERT:
-			return 0;
-		case NAT25_LOOKUP:
-			return 0;
-		default:
-			return -1;
-		}
-	} else if (protocol == ETH_P_IPV6) {
-		/*------------------------------------------------*/
-		/*         Handle IPV6 frame			  */
-		/*------------------------------------------------*/
-		struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
-
-		if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
-			DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
-			return -1;
-		}
-
-		switch (method) {
-		case NAT25_CHECK:
-			if (skb->data[0] & 1)
-				return 0;
-			return -1;
-		case NAT25_INSERT:
-			DEBUG_INFO("NAT25: Insert IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
-							" DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
-				iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
-				iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
-				iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
-				iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
-
-			if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
-				__nat25_generate_ipv6_network_addr(networkAddr, (__be32 *)&iph->saddr);
-				__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
-				__nat25_db_print(priv);
-
-				if (iph->nexthdr == IPPROTO_ICMPV6 &&
-						skb->len > (ETH_HLEN +  sizeof(*iph) + 4)) {
-					if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
-								      skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
-						struct icmp6hdr  *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
-						hdr->icmp6_cksum = 0;
-						hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
-										be16_to_cpu(iph->payload_len),
-										IPPROTO_ICMPV6,
-										csum_partial((__u8 *)hdr,
-										be16_to_cpu(iph->payload_len), 0));
-					}
-				}
-			}
-			return 0;
-		case NAT25_LOOKUP:
-			DEBUG_INFO("NAT25: Lookup IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x, DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
-				   iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
-				   iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
-				   iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
-				   iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
-			__nat25_generate_ipv6_network_addr(networkAddr, (__be32 *)&iph->daddr);
-			__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
-			return 0;
-		default:
-			return -1;
-		}
-	}
-	return -1;
-}
-
-int nat25_handle_frame(struct adapter *priv, struct sk_buff *skb)
-{
-	if (!(skb->data[0] & 1)) {
-		int is_vlan_tag = 0, i, retval = 0;
-		unsigned short vlan_hdr = 0;
-		unsigned short protocol;
-
-		protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
-		if (protocol == ETH_P_8021Q) {
-			is_vlan_tag = 1;
-			vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2));
-			for (i = 0; i < 6; i++)
-				*((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2));
-			skb_pull(skb, 4);
-		}
-
-		if (!priv->ethBrExtInfo.nat25_disable) {
-			spin_lock_bh(&priv->br_ext_lock);
-			/*
-			 *	This function look up the destination network address from
-			 *	the NAT2.5 database. Return value = -1 means that the
-			 *	corresponding network protocol is NOT support.
-			 */
-			if (!priv->ethBrExtInfo.nat25sc_disable &&
-			    (be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
-			    !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) {
-				memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
-
-				spin_unlock_bh(&priv->br_ext_lock);
-			} else {
-				spin_unlock_bh(&priv->br_ext_lock);
-
-				retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
-			}
-		} else {
-			if (((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
-			    !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) ||
-			    ((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_ARP) &&
-			    !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) {
-				/*  for traffic to upper TCP/IP */
-				retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
-			}
-		}
-
-		if (is_vlan_tag) {
-			skb_push(skb, 4);
-			for (i = 0; i < 6; i++)
-				*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
-			*((__be16 *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q);
-			*((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr;
-		}
-
-		if (retval == -1) {
-			/* DEBUG_ERR("NAT25: Lookup fail!\n"); */
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-#define SERVER_PORT			67
-#define CLIENT_PORT			68
-#define DHCP_MAGIC			0x63825363
-#define BROADCAST_FLAG		0x8000
-
-struct dhcpMessage {
-	u_int8_t op;
-	u_int8_t htype;
-	u_int8_t hlen;
-	u_int8_t hops;
-	__be32 xid;
-	__be16 secs;
-	__be16 flags;
-	__be32 ciaddr;
-	__be32 yiaddr;
-	__be32 siaddr;
-	__be32 giaddr;
-	u_int8_t chaddr[16];
-	u_int8_t sname[64];
-	u_int8_t file[128];
-	__be32 cookie;
-	u_int8_t options[308]; /* 312 - cookie */
-};
-
-void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb)
-{
-	if (skb == NULL)
-		return;
-
-	if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
-		__be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN));
-
-		if (protocol == __constant_htons(ETH_P_IP)) { /*  IP */
-			struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
-
-			if (iph->protocol == IPPROTO_UDP) { /*  UDP */
-				struct udphdr *udph = (struct udphdr *)((size_t)iph + (iph->ihl << 2));
-
-				if ((udph->source == __constant_htons(CLIENT_PORT)) &&
-				    (udph->dest == __constant_htons(SERVER_PORT))) { /*  DHCP request */
-					struct dhcpMessage *dhcph =
-						(struct dhcpMessage *)((size_t)udph + sizeof(struct udphdr));
-					u32 cookie = be32_to_cpu((__be32)dhcph->cookie);
-
-					if (cookie == DHCP_MAGIC) { /*  match magic word */
-						if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
-							/*  if not broadcast */
-							register int sum = 0;
-
-							DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
-							/*  or BROADCAST flag */
-							dhcph->flags |= htons(BROADCAST_FLAG);
-							/*  recalculate checksum */
-							sum = ~(udph->check) & 0xffff;
-							sum += be16_to_cpu(dhcph->flags);
-							while (sum >> 16)
-								sum = (sum & 0xffff) + (sum >> 16);
-							udph->check = ~sum;
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-
-void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
-				unsigned char *ipAddr)
-{
-	unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
-	struct nat25_network_db_entry *db;
-	int hash;
-
-	__nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
-	hash = __nat25_network_hash(networkAddr);
-	db = priv->nethash[hash];
-	while (db != NULL) {
-		if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))
-			return (void *)db;
-
-		db = db->next_hash;
-	}
-
-	return NULL;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,7 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <recv_osdep.h>
-#include <cmd_osdep.h>
 #include <mlme_osdep.h>
-#include <rtw_br_ext.h>
 #include <rtw_mlme_ext.h>
 
 /*
@@ -32,91 +30,13 @@ Caller and the rtw_cmd_thread can protec
 No irqsave is necessary.
 */
 
-int _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
+int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
 {
-	int res = _SUCCESS;
-
-
 	sema_init(&(pcmdpriv->cmd_queue_sema), 0);
-	/* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
 	sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
 
-
 	_rtw_init_queue(&(pcmdpriv->cmd_queue));
-
-	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
-
-	pcmdpriv->cmd_seq = 1;
-
-	pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
-
-	if (pcmdpriv->cmd_allocated_buf == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
-
-	pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
-
-	if (pcmdpriv->rsp_allocated_buf == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
-
-	pcmdpriv->cmd_issued_cnt = 0;
-	pcmdpriv->cmd_done_cnt = 0;
-	pcmdpriv->rsp_cnt = 0;
-exit:
-	return res;
-}
-
-static void c2h_wk_callback(struct work_struct *work);
-
-int _rtw_init_evt_priv(struct evt_priv *pevtpriv)
-{
-	int res = _SUCCESS;
-
-
-	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
-	atomic_set(&pevtpriv->event_seq, 0);
-	pevtpriv->evt_done_cnt = 0;
-
-	INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback);
-	pevtpriv->c2h_wk_alive = false;
-	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
-
-
-	return res;
-}
-
-void rtw_free_evt_priv(struct evt_priv *pevtpriv)
-{
-
-	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+rtw_free_evt_priv\n"));
-
-	_cancel_workitem_sync(&pevtpriv->c2h_wk);
-	while (pevtpriv->c2h_wk_alive)
-		msleep(10);
-
-	while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
-		void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
-		if (c2h != NULL && c2h != (void *)pevtpriv)
-			kfree(c2h);
-	}
-	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-rtw_free_evt_priv\n"));
-
-}
-
-void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
-{
-
-	if (pcmdpriv) {
-		kfree(pcmdpriv->cmd_allocated_buf);
-		kfree(pcmdpriv->rsp_allocated_buf);
-	}
+	return _SUCCESS;
 }
 
 /*
@@ -129,7 +49,7 @@ ISR/Call-Back functions can't call this
 
 */
 
-int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
+static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
 {
 	unsigned long irqL;
 
@@ -139,7 +59,7 @@ int _rtw_enqueue_cmd(struct __queue *que
 
 	spin_lock_irqsave(&queue->lock, irqL);
 
-	rtw_list_insert_tail(&obj->list, &queue->queue);
+	list_add_tail(&obj->list, &queue->queue);
 
 	spin_unlock_irqrestore(&queue->lock, irqL);
 
@@ -149,18 +69,18 @@ exit:
 	return _SUCCESS;
 }
 
-struct	cmd_obj	*_rtw_dequeue_cmd(struct __queue *queue)
+struct	cmd_obj	* rtw_dequeue_cmd(struct __queue *queue)
 {
 	unsigned long irqL;
 	struct cmd_obj *obj;
 
 
 	spin_lock_irqsave(&queue->lock, irqL);
-	if (rtw_is_list_empty(&(queue->queue))) {
+	if (list_empty(&(queue->queue))) {
 		obj = NULL;
 	} else {
 		obj = container_of((&queue->queue)->next, struct cmd_obj, list);
-		rtw_list_delete(&obj->list);
+		list_del_init(&obj->list);
 	}
 
 	spin_unlock_irqrestore(&queue->lock, irqL);
@@ -169,26 +89,6 @@ struct	cmd_obj	*_rtw_dequeue_cmd(struct
 	return obj;
 }
 
-u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
-{
-	u32	res;
-	res = _rtw_init_cmd_priv(pcmdpriv);
-	return res;
-}
-
-u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
-{
-	int res;
-	res = _rtw_init_evt_priv(pevtpriv);
-	return res;
-}
-
-void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
-{
-	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
-	_rtw_free_cmd_priv(pcmdpriv);
-}
-
 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 {
 	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
@@ -240,22 +140,6 @@ exit:
 	return res;
 }
 
-struct cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
-{
-	struct cmd_obj *cmd_obj;
-
-
-	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
-
-	return cmd_obj;
-}
-
-void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)
-{
-	pcmdpriv->cmd_done_cnt++;
-	/* up(&(pcmdpriv->cmd_done_sema)); */
-}
-
 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
 {
 
@@ -280,16 +164,12 @@ int rtw_cmd_thread(void *context)
 {
 	u8 ret;
 	struct cmd_obj *pcmd;
-	u8 *pcmdbuf;
 	u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
 	void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
 	struct adapter *padapter = (struct adapter *)context;
 	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
 
-
-	thread_enter("RTW_CMD_THREAD");
-
-	pcmdbuf = pcmdpriv->cmd_buf;
+	allow_signal(SIGTERM);
 
 	pcmdpriv->cmdthd_running = true;
 	up(&pcmdpriv->terminate_cmdthread_sema);
@@ -314,7 +194,7 @@ _next:
 			break;
 		}
 
-		pcmd = rtw_dequeue_cmd(pcmdpriv);
+		pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
 		if (!pcmd)
 			continue;
 
@@ -323,21 +203,13 @@ _next:
 			goto post_process;
 		}
 
-		pcmdpriv->cmd_issued_cnt++;
-
-		pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
-
-		memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
-
 		if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
 			cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
 
 			if (cmd_hdl) {
-				ret = cmd_hdl(pcmd->padapter, pcmdbuf);
+				ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
 				pcmd->res = ret;
 			}
-
-			pcmdpriv->cmd_seq++;
 		} else {
 			pcmd->res = H2C_PARAMETERS_ERROR;
 		}
@@ -361,7 +233,8 @@ post_process:
 			rtw_free_cmd_obj(pcmd);
 		}
 
-		flush_signals_thread();
+		if (signal_pending(current))
+			flush_signals(current);
 
 		goto _next;
 	}
@@ -369,7 +242,7 @@ post_process:
 
 	/*  free all cmd_obj resources */
 	do {
-		pcmd = rtw_dequeue_cmd(pcmdpriv);
+		pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
 		if (pcmd == NULL)
 			break;
 
@@ -384,40 +257,6 @@ post_process:
 	complete_and_exit(NULL, 0);
 }
 
-u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
-{
-	struct cmd_obj *ph2c;
-	struct usb_suspend_parm *psetusbsuspend;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-
-	u8 ret = _SUCCESS;
-
-
-	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
-	if (ph2c == NULL) {
-		ret = _FAIL;
-		goto exit;
-	}
-
-	psetusbsuspend = kzalloc(sizeof(struct usb_suspend_parm), GFP_KERNEL);
-	if (psetusbsuspend == NULL) {
-		kfree(ph2c);
-		ret = _FAIL;
-		goto exit;
-	}
-
-	psetusbsuspend->action = action;
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
-
-	ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
-	return ret;
-}
-
 /*
 rtw_sitesurvey_cmd(~)
 	### NOTE:#### (!!!!)
@@ -435,14 +274,11 @@ u8 rtw_sitesurvey_cmd(struct adapter  *p
 	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
 
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL)
 		return _FAIL;
 
-	psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
+	psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL);
 	if (psurveyPara == NULL) {
 		kfree(ph2c);
 		return _FAIL;
@@ -499,258 +335,11 @@ u8 rtw_sitesurvey_cmd(struct adapter  *p
 	return res;
 }
 
-u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
-{
-	struct cmd_obj *ph2c;
-	struct setdatarate_parm *pbsetdataratepara;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm));
-	if (pbsetdataratepara == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
-	pbsetdataratepara->mac_id = 5;
-	memcpy(pbsetdataratepara->datarates, rateset, NumRates);
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-
-
-	return res;
-}
-
-u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset)
-{
-	struct cmd_obj *ph2c;
-	struct setbasicrate_parm *pssetbasicratepara;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-	pssetbasicratepara = (struct setbasicrate_parm *)rtw_zmalloc(sizeof(struct setbasicrate_parm));
-
-	if (pssetbasicratepara == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
-
-	memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-
-
-	return res;
-}
-
-
-/*
-unsigned char rtw_setphy_cmd(unsigned char  *adapter)
-
-1.  be called only after rtw_update_registrypriv_dev_network(~) or mp testing program
-2.  for AdHoc/Ap mode or mp mode?
-
-*/
-u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
-{
-	struct cmd_obj *ph2c;
-	struct setphy_parm *psetphypara;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-		}
-	psetphypara = (struct setphy_parm *)rtw_zmalloc(sizeof(struct setphy_parm));
-
-	if (psetphypara == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
-
-	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("CH =%d, modem =%d", ch, modem));
-
-	psetphypara->modem = modem;
-	psetphypara->rfchannel = ch;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
-{
-	struct cmd_obj *ph2c;
-	struct writeBB_parm *pwritebbparm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-		}
-	pwritebbparm = (struct writeBB_parm *)rtw_zmalloc(sizeof(struct writeBB_parm));
-
-	if (pwritebbparm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
-
-	pwritebbparm->offset = offset;
-	pwritebbparm->value = val;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_getbbreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
-{
-	struct cmd_obj *ph2c;
-	struct readBB_parm *prdbbparm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-		}
-	prdbbparm = (struct readBB_parm *)rtw_zmalloc(sizeof(struct readBB_parm));
-
-	if (prdbbparm == NULL) {
-		kfree(ph2c);
-		return _FAIL;
-	}
-
-	_rtw_init_listhead(&ph2c->list);
-	ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
-	ph2c->parmbuf = (unsigned char *)prdbbparm;
-	ph2c->cmdsz =  sizeof(struct readBB_parm);
-	ph2c->rsp = pval;
-	ph2c->rspsz = sizeof(struct readBB_rsp);
-
-	prdbbparm->offset = offset;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_setrfreg_cmd(struct adapter  *padapter, u8 offset, u32 val)
-{
-	struct cmd_obj *ph2c;
-	struct writeRF_parm *pwriterfparm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-	pwriterfparm = (struct writeRF_parm *)rtw_zmalloc(sizeof(struct writeRF_parm));
-
-	if (pwriterfparm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
-
-	pwriterfparm->offset = offset;
-	pwriterfparm->value = val;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_getrfreg_cmd(struct adapter  *padapter, u8 offset, u8 *pval)
-{
-	struct cmd_obj *ph2c;
-	struct readRF_parm *prdrfparm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	prdrfparm = (struct readRF_parm *)rtw_zmalloc(sizeof(struct readRF_parm));
-	if (prdrfparm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	_rtw_init_listhead(&ph2c->list);
-	ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
-	ph2c->parmbuf = (unsigned char *)prdrfparm;
-	ph2c->cmdsz =  sizeof(struct readRF_parm);
-	ph2c->rsp = pval;
-	ph2c->rspsz = sizeof(struct readRF_rsp);
-
-	prdrfparm->offset = offset;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
-	return res;
-}
-
-void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
-{
-
-	kfree(pcmd->parmbuf);
-	kfree(pcmd);
-
-	if (padapter->registrypriv.mp_mode == 1)
-		padapter->mppriv.workparam.bcompleted = true;
-}
-
 void rtw_readtssi_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
 {
 
 	kfree(pcmd->parmbuf);
 	kfree(pcmd);
-
-	if (padapter->registrypriv.mp_mode == 1)
-		padapter->mppriv.workparam.bcompleted = true;
 }
 
 u8 rtw_createbss_cmd(struct adapter  *padapter)
@@ -769,13 +358,13 @@ u8 rtw_createbss_cmd(struct adapter  *pa
 	else
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
 
-	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	_rtw_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	pcmd->cmdcode = _CreateBss_CMD_;
 	pcmd->parmbuf = (unsigned char *)pdev_network;
 	pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
@@ -789,34 +378,6 @@ exit:
 	return res;
 }
 
-u8 rtw_createbss_cmd_ex(struct adapter  *padapter, unsigned char *pbss, unsigned int sz)
-{
-	struct cmd_obj *pcmd;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (pcmd == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	_rtw_init_listhead(&pcmd->list);
-	pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
-	pcmd->parmbuf = pbss;
-	pcmd->cmdsz =  sz;
-	pcmd->rsp = NULL;
-	pcmd->rspsz = 0;
-
-	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-
-exit:
-
-
-	return res;
-}
-
 u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
 {
 	u8	res = _SUCCESS;
@@ -841,7 +402,7 @@ u8 rtw_joinbss_cmd(struct adapter  *pada
 	else
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
 
-	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd == NULL) {
 		res = _FAIL;
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
@@ -879,7 +440,7 @@ u8 rtw_joinbss_cmd(struct adapter  *pada
 		goto exit;
 	}
 
-	_rtw_memset(psecnetwork, 0, t_len);
+	memset(psecnetwork, 0, t_len);
 
 	memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
 
@@ -945,7 +506,7 @@ u8 rtw_joinbss_cmd(struct adapter  *pada
 
 	pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
 
-	_rtw_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
 	pcmd->parmbuf = (unsigned char *)psecnetwork;
 	pcmd->rsp = NULL;
@@ -970,7 +531,7 @@ u8 rtw_disassoc_cmd(struct adapter *pada
 	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
 
 	/* prepare cmd parameter */
-	param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
+	param = kzalloc(sizeof(*param), GFP_KERNEL);
 	if (param == NULL) {
 		res = _FAIL;
 		goto exit;
@@ -979,7 +540,7 @@ u8 rtw_disassoc_cmd(struct adapter *pada
 
 	if (enqueue) {
 		/* need enqueue, prepare cmd_obj and enqueue */
-		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
+		cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL);
 		if (cmdobj == NULL) {
 			res = _FAIL;
 			kfree(param);
@@ -1009,12 +570,12 @@ u8 rtw_setopmode_cmd(struct adapter  *pa
 	u8	res = _SUCCESS;
 
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = false;
 		goto exit;
 	}
-	psetop = (struct setopmode_parm *)rtw_zmalloc(sizeof(struct setopmode_parm));
+	psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
 
 	if (psetop == NULL) {
 		kfree(ph2c);
@@ -1046,20 +607,20 @@ u8 rtw_setstakey_cmd(struct adapter *pad
 	u8	res = _SUCCESS;
 
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
+	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
 	if (psetstakey_para == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
 		goto exit;
 	}
 
-	psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
+	psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
 	if (psetstakey_rsp == NULL) {
 		kfree(ph2c);
 		kfree(psetstakey_para);
@@ -1107,20 +668,20 @@ u8 rtw_clearstakey_cmd(struct adapter *p
 	if (!enqueue) {
 		clear_cam_entry(padapter, entry);
 	} else {
-		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 		if (ph2c == NULL) {
 			res = _FAIL;
 			goto exit;
 		}
 
-		psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
+		psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC);
 		if (psetstakey_para == NULL) {
 			kfree(ph2c);
 			res = _FAIL;
 			goto exit;
 		}
 
-		psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
+		psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC);
 		if (psetstakey_rsp == NULL) {
 			kfree(ph2c);
 			kfree(psetstakey_para);
@@ -1146,113 +707,6 @@ exit:
 	return res;
 }
 
-u8 rtw_setrttbl_cmd(struct adapter  *padapter, struct setratable_parm *prate_table)
-{
-	struct cmd_obj *ph2c;
-	struct setratable_parm *psetrttblparm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-	psetrttblparm = (struct setratable_parm *)rtw_zmalloc(sizeof(struct setratable_parm));
-
-	if (psetrttblparm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
-
-	memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_getrttbl_cmd(struct adapter  *padapter, struct getratable_rsp *pval)
-{
-	struct cmd_obj *ph2c;
-	struct getratable_parm *pgetrttblparm;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-	pgetrttblparm = (struct getratable_parm *)rtw_zmalloc(sizeof(struct getratable_parm));
-
-	if (pgetrttblparm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	_rtw_init_listhead(&ph2c->list);
-	ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);
-	ph2c->parmbuf = (unsigned char *)pgetrttblparm;
-	ph2c->cmdsz =  sizeof(struct getratable_parm);
-	ph2c->rsp = (u8 *)pval;
-	ph2c->rspsz = sizeof(struct getratable_rsp);
-
-	pgetrttblparm->rsvd = 0x0;
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-	return res;
-}
-
-u8 rtw_setassocsta_cmd(struct adapter  *padapter, u8 *mac_addr)
-{
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	struct cmd_obj *ph2c;
-	struct set_assocsta_parm *psetassocsta_para;
-	struct set_stakey_rsp *psetassocsta_rsp = NULL;
-
-	u8	res = _SUCCESS;
-
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	psetassocsta_para = (struct set_assocsta_parm *)rtw_zmalloc(sizeof(struct set_assocsta_parm));
-	if (psetassocsta_para == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	psetassocsta_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_assocsta_rsp));
-	if (psetassocsta_rsp == NULL) {
-		kfree(ph2c);
-		kfree(psetassocsta_para);
-		return _FAIL;
-	}
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
-	ph2c->rsp = (u8 *)psetassocsta_rsp;
-	ph2c->rspsz = sizeof(struct set_assocsta_rsp);
-
-	ether_addr_copy(psetassocsta_para->addr, mac_addr);
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
-	return res;
-}
-
 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
 {
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
@@ -1261,13 +715,13 @@ u8 rtw_addbareq_cmd(struct adapter *pada
 	u8	res = _SUCCESS;
 
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
+	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL);
 	if (paddbareq_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -1298,13 +752,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter
 	u8	res = _SUCCESS;
 
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 	if (pdrvextra_cmd_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -1324,59 +778,6 @@ exit:
 	return res;
 }
 
-u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
-{
-	struct cmd_obj *pcmdobj;
-	struct set_ch_parm *set_ch_parm;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
-	u8 res = _SUCCESS;
-
-
-	DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
-		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
-
-	/* check input parameter */
-
-	/* prepare cmd parameter */
-	set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
-	if (set_ch_parm == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-	set_ch_parm->ch = ch;
-	set_ch_parm->bw = bw;
-	set_ch_parm->ch_offset = ch_offset;
-
-	if (enqueue) {
-		/* need enqueue, prepare cmd_obj and enqueue */
-		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
-		if (pcmdobj == NULL) {
-			kfree(set_ch_parm);
-			res = _FAIL;
-			goto exit;
-		}
-
-		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
-		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
-	} else {
-		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
-		if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
-			res = _FAIL;
-
-		kfree(set_ch_parm);
-	}
-
-	/* do something based on res... */
-
-exit:
-
-	DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
-
-
-	return res;
-}
-
 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
 {
 	struct	cmd_obj *pcmdobj;
@@ -1395,7 +796,7 @@ u8 rtw_set_chplan_cmd(struct adapter *pa
 	}
 
 	/* prepare cmd parameter */
-	setChannelPlan_param = (struct	SetChannelPlan_param *)rtw_zmalloc(sizeof(struct SetChannelPlan_param));
+	setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param), GFP_KERNEL);
 	if (setChannelPlan_param == NULL) {
 		res = _FAIL;
 		goto exit;
@@ -1404,7 +805,7 @@ u8 rtw_set_chplan_cmd(struct adapter *pa
 
 	if (enqueue) {
 		/* need enqueue, prepare cmd_obj and enqueue */
-		pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
+		pcmdobj = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
 		if (pcmdobj == NULL) {
 			kfree(setChannelPlan_param);
 			res = _FAIL;
@@ -1431,46 +832,6 @@ exit:
 	return res;
 }
 
-u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
-{
-	struct	cmd_obj *pcmdobj;
-	struct	SetChannelSwitch_param *setChannelSwitch_param;
-	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
-
-	u8	res = _SUCCESS;
-
-
-	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
-
-	pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
-	if (pcmdobj == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct	SetChannelSwitch_param));
-	if (setChannelSwitch_param == NULL) {
-		kfree(pcmdobj);
-		res = _FAIL;
-		goto exit;
-	}
-
-	setChannelSwitch_param->new_ch_no = new_ch_no;
-
-	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
-	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
-
-exit:
-
-
-	return res;
-}
-
-u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option)
-{
-	return _SUCCESS;
-}
-
 static void traffic_status_watchdog(struct adapter *padapter)
 {
 	u8	bEnterPS;
@@ -1542,8 +903,6 @@ static void dynamic_chk_wk_hdl(struct ad
 		expire_timeout_chk(padapter);
 #endif
 
-	rtw_hal_sreset_xmit_status_check(padapter);
-
 	linked_status_chk(padapter);
 	traffic_status_watchdog(padapter);
 
@@ -1605,13 +964,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *p
 	u8	res = _SUCCESS;
 
 	if (enqueue) {
-		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 		if (ph2c == NULL) {
 			res = _FAIL;
 			goto exit;
 		}
 
-		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 		if (pdrvextra_cmd_parm == NULL) {
 			kfree(ph2c);
 			res = _FAIL;
@@ -1648,13 +1007,13 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter
 
 	u8	res = _SUCCESS;
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 	if (pdrvextra_cmd_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -1690,13 +1049,13 @@ u8 rtw_antenna_select_cmd(struct adapter
 		return res;
 
 	if (enqueue) {
-		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 		if (ph2c == NULL) {
 			res = _FAIL;
 			goto exit;
 		}
 
-		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+		pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 		if (pdrvextra_cmd_parm == NULL) {
 			kfree(ph2c);
 			res = _FAIL;
@@ -1718,52 +1077,6 @@ exit:
 	return res;
 }
 
-static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
-{
-	 rtw_ps_processor(padapter);
-}
-
-#ifdef CONFIG_88EU_P2P
-u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
-{
-	struct cmd_obj	*ph2c;
-	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return res;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-	if (pdrvextra_cmd_parm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
-	pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
-	pdrvextra_cmd_parm->pbuf = NULL;	    /* Must be NULL here */
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-
-	return res;
-}
-#endif /* CONFIG_88EU_P2P */
-
 u8 rtw_ps_cmd(struct adapter *padapter)
 {
 	struct cmd_obj		*ppscmd;
@@ -1772,13 +1085,13 @@ u8 rtw_ps_cmd(struct adapter *padapter)
 
 	u8	res = _SUCCESS;
 
-	ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ppscmd == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 	if (pdrvextra_cmd_parm == NULL) {
 		kfree(ppscmd);
 		res = _FAIL;
@@ -1846,13 +1159,13 @@ u8 rtw_chk_hi_queue_cmd(struct adapter *
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8	res = _SUCCESS;
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
 	if (pdrvextra_cmd_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -1871,111 +1184,6 @@ exit:
 }
 #endif
 
-u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
-{
-	struct cmd_obj *ph2c;
-	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-	if (ph2c == NULL) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-	if (pdrvextra_cmd_parm == NULL) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
-	pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0;
-	pdrvextra_cmd_parm->pbuf = c2h_evt;
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-
-	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
-	return res;
-}
-
-static s32 c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter)
-{
-	s32 ret = _FAIL;
-	u8 buf[16];
-
-	if (!c2h_evt) {
-		/* No c2h event in cmd_obj, read c2h event before handling*/
-		if (c2h_evt_read(adapter, buf) == _SUCCESS) {
-			c2h_evt = (struct c2h_evt_hdr *)buf;
-
-			if (filter && filter(c2h_evt->id) == false)
-				goto exit;
-
-			ret = rtw_hal_c2h_handler(adapter, c2h_evt);
-		}
-	} else {
-		if (filter && filter(c2h_evt->id) == false)
-			goto exit;
-
-		ret = rtw_hal_c2h_handler(adapter, c2h_evt);
-	}
-exit:
-	return ret;
-}
-
-static void c2h_wk_callback(struct work_struct *work)
-{
-	struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
-	struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
-	struct c2h_evt_hdr *c2h_evt;
-	c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
-
-	evtpriv->c2h_wk_alive = true;
-
-	while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
-		c2h_evt = (struct c2h_evt_hdr *)
-			rtw_cbuf_pop(evtpriv->c2h_queue);
-		if (c2h_evt != NULL)
-			/* This C2H event is read, clear it */
-			c2h_evt_clear(adapter);
-		else {
-			c2h_evt = (struct c2h_evt_hdr *)rtw_malloc(16);
-			/* This C2H event is not read, read & clear now */
-			if (c2h_evt != NULL &&
-			    c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS)
-				continue;
-		}
-
-		/* Special pointer to trigger c2h_evt_clear only */
-		if ((void *)c2h_evt == (void *)evtpriv)
-			continue;
-
-		if (!c2h_evt_exist(c2h_evt)) {
-			kfree(c2h_evt);
-			continue;
-		}
-
-		if (ccx_id_filter(c2h_evt->id) == true) {
-			/* Handle CCX report here */
-			rtw_hal_c2h_handler(adapter, c2h_evt);
-			kfree(c2h_evt);
-		} else {
-#ifdef CONFIG_88EU_P2P
-			/* Enqueue into cmd_thread for others */
-			rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
-#endif
-		}
-	}
-
-	evtpriv->c2h_wk_alive = false;
-}
-
 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
 {
 	struct drvextra_cmd_parm *pdrvextra_cmd;
@@ -1990,7 +1198,7 @@ u8 rtw_drvextra_cmd_hdl(struct adapter *
 		dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
 		break;
 	case POWER_SAVING_CTRL_WK_CID:
-		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
+		rtw_ps_processor(padapter);
 		break;
 	case LPS_CTRL_WK_CID:
 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
@@ -2001,26 +1209,11 @@ u8 rtw_drvextra_cmd_hdl(struct adapter *
 	case ANT_SELECT_WK_CID:
 		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
 		break;
-#ifdef CONFIG_88EU_P2P
-	case P2P_PS_WK_CID:
-		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size);
-		break;
-	case P2P_PROTO_WK_CID:
-		/*
-		 * Commented by Albert 2011/07/01
-		 * I used the type_size as the type command
-		 */
-		p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size);
-		break;
-#endif
 #ifdef CONFIG_88EU_AP_MODE
 	case CHECK_HIQ_WK_CID:
 		rtw_chk_hi_queue_hdl(padapter);
 		break;
 #endif /* CONFIG_88EU_AP_MODE */
-	case C2H_WK_CID:
-		c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
-		break;
 	default:
 		break;
 	}
@@ -2061,8 +1254,7 @@ void rtw_disassoc_cmd_callback(struct ad
 
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
 		return;
-	} else /* clear bridge database */
-		nat25_db_cleanup(padapter);
+	}
 
 	/*  free cmd */
 	rtw_free_cmd_obj(pcmd);
@@ -2088,7 +1280,6 @@ void rtw_joinbss_cmd_callback(struct ada
 
 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
 {
-	u8 timer_cancelled;
 	struct sta_info *psta = NULL;
 	struct wlan_network *pwlan = NULL;
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -2101,7 +1292,7 @@ void rtw_createbss_cmd_callback(struct a
 		_set_timer(&pmlmepriv->assoc_timer, 1);
 	}
 
-	_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+	del_timer_sync(&pmlmepriv->assoc_timer);
 
 	spin_lock_bh(&pmlmepriv->lock);
 
@@ -2128,7 +1319,7 @@ void rtw_createbss_cmd_callback(struct a
 			}
 			pwlan->last_scanned = jiffies;
 		} else {
-			rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
+			list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
 		}
 
 		pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_debug.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_debug.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_debug.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_debug.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,7 +20,7 @@
 #define _RTW_DEBUG_C_
 
 #include <rtw_debug.h>
-#include <rtw_version.h>
+#include <usb_ops_linux.h>
 
 int proc_get_drv_version(char *page, char **start,
 			  off_t offset, int count,
@@ -64,13 +64,13 @@ int proc_set_write_reg(struct file *file
 		}
 		switch (len) {
 		case 1:
-			rtw_write8(padapter, addr, (u8)val);
+			usb_write8(padapter, addr, (u8)val);
 			break;
 		case 2:
-			rtw_write16(padapter, addr, (u16)val);
+			usb_write16(padapter, addr, (u16)val);
 			break;
 		case 4:
-			rtw_write32(padapter, addr, val);
+			usb_write32(padapter, addr, val);
 			break;
 		default:
 			DBG_88E("error write length =%d", len);
@@ -99,13 +99,13 @@ int proc_get_read_reg(char *page, char *
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		len += snprintf(page + len, count - len, "usb_read8(0x%x)=0x%x\n", proc_get_read_addr, usb_read8(padapter, proc_get_read_addr));
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		len += snprintf(page + len, count - len, "usb_read16(0x%x)=0x%x\n", proc_get_read_addr, usb_read16(padapter, proc_get_read_addr));
 		break;
 	case 4:
-		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+		len += snprintf(page + len, count - len, "usb_read32(0x%x)=0x%x\n", proc_get_read_addr, usb_read32(padapter, proc_get_read_addr));
 		break;
 	default:
 		len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
@@ -327,7 +327,7 @@ int proc_get_mac_reg_dump1(char *page, c
 	for (i = 0x0; i < 0x300; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -350,7 +350,7 @@ int proc_get_mac_reg_dump2(char *page, c
 	for (i = 0x300; i < 0x600; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -373,7 +373,7 @@ int proc_get_mac_reg_dump3(char *page, c
 	for (i = 0x600; i < 0x800; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -395,7 +395,7 @@ int proc_get_bb_reg_dump1(char *page, ch
 	for (i = 0x800; i < 0xB00; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -416,7 +416,7 @@ int proc_get_bb_reg_dump2(char *page, ch
 	for (i = 0xB00; i < 0xE00; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -437,7 +437,7 @@ int proc_get_bb_reg_dump3(char *page, ch
 	for (i = 0xE00; i < 0x1000; i += 4) {
 		if (j%4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i));
 		if ((j++)%4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -853,7 +853,7 @@ int proc_get_all_sta_info(char *page, ch
 		phead = &(pstapriv->sta_hash[i]);
 		plist = phead->next;
 
-		while ((rtw_end_of_queue_search(phead, plist)) == false) {
+		while (phead != plist) {
 			psta = container_of(plist, struct sta_info, hash_list);
 
 			plist = plist->next;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_efuse.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_efuse.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_efuse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_efuse.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,849 +22,996 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <rtw_efuse.h>
+#include <usb_ops_linux.h>
+#include <rtl8188e_hal.h>
+#include <rtw_iol.h>
 
-
-
-/*------------------------Define local variable------------------------------*/
-u8 fakeEfuseBank;
-u32 fakeEfuseUsedBytes;
-u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
-u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
-u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
-
-u32 BTEfuseUsedBytes;
-u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-
-u32 fakeBTEfuseUsedBytes;
-u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-/*------------------------Define local variable------------------------------*/
-
-/*  */
 #define REG_EFUSE_CTRL		0x0030
 #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
-/*  */
 
-bool
-Efuse_Read1ByteFromFakeContent(
-			struct adapter *pAdapter,
-			u16 Offset,
-		u8 *Value);
-bool
-Efuse_Read1ByteFromFakeContent(
-			struct adapter *pAdapter,
-			u16 Offset,
-		u8 *Value)
-{
-	if (Offset >= EFUSE_MAX_HW_SIZE)
-		return false;
-	if (fakeEfuseBank == 0)
-		*Value = fakeEfuseContent[Offset];
-	else
-		*Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
-	return true;
-}
-
-static bool
-Efuse_Write1ByteToFakeContent(
-			struct adapter *pAdapter,
-			u16 Offset,
-			u8 Value)
-{
-	if (Offset >= EFUSE_MAX_HW_SIZE)
-		return false;
-	if (fakeEfuseBank == 0)
-		fakeEfuseContent[Offset] = Value;
-	else
-		fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
-	return true;
-}
+enum{
+		VOLTAGE_V25						= 0x03,
+		LDOE25_SHIFT						= 28 ,
+	};
 
-/*-----------------------------------------------------------------------------
+/*
  * Function:	Efuse_PowerSwitch
  *
  * Overview:	When we want to enable write operation, we should change to
  *				pwr on state. When we stop write, we should switch to 500k mode
  *				and disable LDO 2.5V.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/17/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void
-Efuse_PowerSwitch(
+ */
+
+void Efuse_PowerSwitch(
 		struct adapter *pAdapter,
-		u8 write,
+		u8 bWrite,
 		u8 PwrState)
 {
-	pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
-}
+	u8 tempval;
+	u16	tmpV16;
 
-/*-----------------------------------------------------------------------------
- * Function:	efuse_GetCurrentSize
- *
- * Overview:	Get current efuse size!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/16/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-u16
-Efuse_GetCurrentSize(
-	struct adapter *pAdapter,
-	u8 efuseType,
-	bool pseudo)
-{
-	u16 ret = 0;
+	if (PwrState) {
+		usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
 
-	ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
+		/*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
+		tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
+		if (!(tmpV16 & PWC_EV12V)) {
+			tmpV16 |= PWC_EV12V;
+			 usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
+		}
+		/*  Reset: 0x0000h[28], default valid */
+		tmpV16 =  usb_read16(pAdapter, REG_SYS_FUNC_EN);
+		if (!(tmpV16 & FEN_ELDR)) {
+			tmpV16 |= FEN_ELDR;
+			usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
+		}
 
-	return ret;
-}
+		/*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
+		tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR);
+		if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
+			tmpV16 |= (LOADER_CLK_EN | ANA8M);
+			usb_write16(pAdapter, REG_SYS_CLKR, tmpV16);
+		}
 
-/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
-u8
-Efuse_CalculateWordCnts(u8 word_en)
-{
-	u8 word_cnts = 0;
-	if (!(word_en & BIT(0)))
-		word_cnts++; /*  0 : write enable */
-	if (!(word_en & BIT(1)))
-		word_cnts++;
-	if (!(word_en & BIT(2)))
-		word_cnts++;
-	if (!(word_en & BIT(3)))
-		word_cnts++;
-	return word_cnts;
+		if (bWrite) {
+			/*  Enable LDO 2.5V before read/write action */
+			tempval = usb_read8(pAdapter, EFUSE_TEST+3);
+			tempval &= 0x0F;
+			tempval |= (VOLTAGE_V25 << 4);
+			usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80));
+		}
+	} else {
+		usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+
+		if (bWrite) {
+			/*  Disable LDO 2.5V after read/write action */
+			tempval = usb_read8(pAdapter, EFUSE_TEST+3);
+			usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F));
+		}
+	}
 }
 
-/*
- * Description:
- * Execute E-Fuse read byte operation.
- * Referred from SD1 Richard.
- * Assumption:
- *		1. Boot from E-Fuse and successfully auto-load.
- *		2. PASSIVE_LEVEL (USB interface)
- * Created by Roger, 2008.10.21.
- */
-void
-ReadEFuseByte(
-		struct adapter *Adapter,
-		u16 _offset,
-		u8 *pbuf,
-		bool pseudo)
+static void
+efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
 {
-	u32 value32;
-	u8 readbyte;
-	u16 retry;
+	u8 *efuseTbl = NULL;
+	u8 rtemp8;
+	u16	eFuse_Addr = 0;
+	u8 offset, wren;
+	u16	i, j;
+	u16	**eFuseWord = NULL;
+	u16	efuse_utilized = 0;
+	u8 u1temp = 0;
 
-	if (pseudo) {
-		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
-		return;
+	efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
+	if (efuseTbl == NULL) {
+		DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
+		goto exit;
 	}
 
-	/* Write Address */
-	rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
-	readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
-	rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
+	eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
+	if (eFuseWord == NULL) {
+		DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
+		goto exit;
+	}
 
-	/* Write bit 32 0 */
-	readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
-	rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
+	/*  0. Refresh efuse init map as all oxFF. */
+	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+			eFuseWord[i][j] = 0xFFFF;
 
-	/* Check bit 32 read-ready */
-	retry = 0;
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
-	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
-		value32 = rtw_read32(Adapter, EFUSE_CTRL);
-		retry++;
+	/*  */
+	/*  1. Read the first byte to check if efuse is empty!!! */
+	/*  */
+	/*  */
+	rtemp8 = *(phymap+eFuse_Addr);
+	if (rtemp8 != 0xFF) {
+		efuse_utilized++;
+		eFuse_Addr++;
+	} else {
+		DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
+		goto exit;
 	}
 
-	/*  20100205 Joseph: Add delay suggested by SD1 Victor. */
-	/*  This fix the problem that Efuse read error in high temperature condition. */
-	/*  Designer says that there shall be some delay after ready bit is set, or the */
-	/*  result will always stay on last data we read. */
-	udelay(50);
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	/*  */
+	/*  2. Read real efuse content. Filter PG header and every section data. */
+	/*  */
+	while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+		/*  Check PG header for section num. */
+		if ((rtemp8 & 0x1F) == 0x0F) {		/* extended header */
+			u1temp = ((rtemp8 & 0xE0) >> 5);
+			rtemp8 = *(phymap+eFuse_Addr);
+			if ((rtemp8 & 0x0F) == 0x0F) {
+				eFuse_Addr++;
+				rtemp8 = *(phymap+eFuse_Addr);
 
-	*pbuf = (u8)(value32 & 0xff);
-}
+				if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
+					eFuse_Addr++;
+				continue;
+			} else {
+				offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
+				wren = (rtemp8 & 0x0F);
+				eFuse_Addr++;
+			}
+		} else {
+			offset = ((rtemp8 >> 4) & 0x0f);
+			wren = (rtemp8 & 0x0f);
+		}
 
-/* Description:
- *	1. Execute E-Fuse read byte operation according as map offset and
- *	save to E-Fuse table.
- *	2. Referred from SD1 Richard.
- * Assumption:
- *	1. Boot from E-Fuse and successfully auto-load.
- *	2. PASSIVE_LEVEL (USB interface)
- *	Created by Roger, 2008.10.21.
- * 2008/12/12 MH
- *	1. Reorganize code flow and reserve bytes. and add description.
- *	2. Add efuse utilization collect.
- * 2008/12/22 MH
- *	Read Efuse must check if we write section 1 data again!!!
- *	Sec1 write addr must be after sec5.
- */
+		if (offset < EFUSE_MAX_SECTION_88E) {
+			/*  Get word enable value from PG header */
+			for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+				/*  Check word enable condition in the section */
+				if (!(wren & 0x01)) {
+					rtemp8 = *(phymap+eFuse_Addr);
+					eFuse_Addr++;
+					efuse_utilized++;
+					eFuseWord[offset][i] = (rtemp8 & 0xff);
+					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+						break;
+					rtemp8 = *(phymap+eFuse_Addr);
+					eFuse_Addr++;
+					efuse_utilized++;
+					eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
 
-static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
-{
-	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
-}
+					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+						break;
+				}
+				wren >>= 1;
+			}
+		}
+		/*  Read next PG header */
+		rtemp8 = *(phymap+eFuse_Addr);
 
-void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
-	)
-{
-	pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
+		if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+			efuse_utilized++;
+			eFuse_Addr++;
+		}
+	}
+
+	/*  */
+	/*  3. Collect 16 sections and 4 word unit into Efuse map. */
+	/*  */
+	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
+		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
+			efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
+			efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
+		}
+	}
+
+	/*  */
+	/*  4. Copy from Efuse map to output pointer memory!!! */
+	/*  */
+	for (i = 0; i < _size_byte; i++)
+		pbuf[i] = efuseTbl[_offset+i];
+
+	/*  */
+	/*  5. Calculate Efuse utilization. */
+	/*  */
+
+exit:
+	kfree(efuseTbl);
+
+	if (eFuseWord)
+		kfree(eFuseWord);
 }
 
-/*-----------------------------------------------------------------------------
- * Function:	EFUSE_Read1Byte
- *
- * Overview:	Copy from WMAC fot EFUSE read 1 byte.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 09/23/2008	MHC		Copy from WMAC.
- *
- *---------------------------------------------------------------------------*/
-u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
+static void efuse_read_phymap_from_txpktbuf(
+	struct adapter  *adapter,
+	int bcnhead,	/* beacon head, where FW store len(2-byte) and efuse physical map. */
+	u8 *content,	/* buffer to store efuse physical map */
+	u16 *size	/* for efuse content: the max byte to read. will update to byte read */
+	)
 {
-	u8 data;
-	u8 Bytetemp = {0x00};
-	u8 temp = {0x00};
-	u32 k = 0;
-	u16 contentLen = 0;
+	u16 dbg_addr = 0;
+	u32 start  = 0, passing_time = 0;
+	u8 reg_0x143 = 0;
+	u32 lo32 = 0, hi32 = 0;
+	u16 len = 0, count = 0;
+	int i = 0;
+	u16 limit = *size;
 
-	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
+	u8 *pos = content;
 
-	if (Address < contentLen) {	/* E-fuse 512Byte */
-		/* Write E-fuse Register address bit0~7 */
-		temp = Address & 0xFF;
-		rtw_write8(Adapter, EFUSE_CTRL+1, temp);
-		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
-		/* Write E-fuse Register address bit8~9 */
-		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
-		rtw_write8(Adapter, EFUSE_CTRL+2, temp);
+	if (bcnhead < 0) /* if not valid */
+		bcnhead = usb_read8(adapter, REG_TDECTRL+1);
 
-		/* Write 0x30[31]= 0 */
-		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-		temp = Bytetemp & 0x7F;
-		rtw_write8(Adapter, EFUSE_CTRL+3, temp);
+	DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
 
-		/* Wait Write-ready (0x30[31]= 1) */
-		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-		while (!(Bytetemp & 0x80)) {
-			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-			k++;
-			if (k == 1000) {
-				k = 0;
-				break;
-			}
-		}
-		data = rtw_read8(Adapter, EFUSE_CTRL);
-		return data;
-	} else {
-		return 0xFF;
-	}
+	usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
 
-} /* EFUSE_Read1Byte */
+	dbg_addr = bcnhead*128/8; /* 8-bytes addressing */
 
-/*  11/16/2008 MH Read one byte from real Efuse. */
-u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
-{
-	u8 tmpidx = 0;
-	u8 result;
+	while (1) {
+		usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i);
 
-	if (pseudo) {
-		result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
-		return result;
-	}
-	/*  -----------------e-fuse reg ctrl --------------------------------- */
-	/* address */
-	rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
-	rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
-		   (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
+		usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
+		start = jiffies;
+		while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
+		       (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
+			DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
+			msleep(1);
+		}
 
-	rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
+		lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
+		hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
 
-	while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
-		tmpidx++;
-	if (tmpidx < 100) {
-		*data = rtw_read8(pAdapter, EFUSE_CTRL);
-		result = true;
-	} else {
-		*data = 0xff;
-		result = false;
-	}
-	return result;
-}
+		if (i == 0) {
+			u8 lenc[2];
+			u16 lenbak, aaabak;
+			u16 aaa;
+			lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
+			lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1);
 
-/*  11/16/2008 MH Write one byte to reald Efuse. */
-u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
-{
-	u8 tmpidx = 0;
-	u8 result;
+			aaabak = le16_to_cpup((__le16 *)lenc);
+			lenbak = le16_to_cpu(*((__le16 *)lenc));
+			aaa = le16_to_cpup((__le16 *)&lo32);
+			len = le16_to_cpu(*((__le16 *)&lo32));
 
-	if (pseudo) {
-		result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
-		return result;
-	}
+			limit = (len-2 < limit) ? len-2 : limit;
 
-	/*  -----------------e-fuse reg ctrl --------------------------------- */
-	/* address */
-	rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
-	rtw_write8(pAdapter, EFUSE_CTRL+2,
-		   (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
-		   (u8)((addr>>8) & 0x03));
-	rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
+			DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
 
-	rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
+			memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count);
+			count += (limit >= count+2) ? 2 : limit-count;
+			pos = content+count;
 
-	while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
-		tmpidx++;
+		} else {
+			memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count);
+			count += (limit >= count+4) ? 4 : limit-count;
+			pos = content+count;
+		}
 
-	if (tmpidx < 100)
-		result = true;
-	else
-		result = false;
+		if (limit > count && len-2 > count) {
+			memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count);
+			count += (limit >= count+4) ? 4 : limit-count;
+			pos = content+count;
+		}
 
-	return result;
+		if (limit <= count || len-2 <= count)
+			break;
+		i++;
+	}
+	usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
+	DBG_88E("%s read count:%u\n", __func__, count);
+	*size = count;
 }
 
-int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
+static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
 {
-	int	ret = 0;
-
-	ret =  pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
+	s32 status = _FAIL;
+	u8 physical_map[512];
+	u16 size = 512;
 
-	return ret;
+	usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
+	memset(physical_map, 0xFF, 512);
+	usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+	status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+	if (status == _SUCCESS)
+		efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
+	efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
+	return status;
 }
 
-int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
 {
-	int ret;
-
-	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
 
-	return ret;
+	if (rtw_IOL_applied(Adapter)) {
+		rtw_hal_power_on(Adapter);
+		iol_mode_enable(Adapter, 1);
+		iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
+		iol_mode_enable(Adapter, 0);
+	}
+	return;
 }
 
+/* Do not support BT */
+void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
+{
+	switch (type) {
+	case TYPE_EFUSE_MAX_SECTION:
+		{
+			u8 *pMax_section;
+			pMax_section = (u8 *)pOut;
+			*pMax_section = EFUSE_MAX_SECTION_88E;
+		}
+		break;
+	case TYPE_EFUSE_REAL_CONTENT_LEN:
+		{
+			u16 *pu2Tmp;
+			pu2Tmp = (u16 *)pOut;
+			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+		}
+		break;
+	case TYPE_EFUSE_CONTENT_LEN_BANK:
+		{
+			u16 *pu2Tmp;
+			pu2Tmp = (u16 *)pOut;
+			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+		}
+		break;
+	case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
+		{
+			u16 *pu2Tmp;
+			pu2Tmp = (u16 *)pOut;
+			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
+		}
+		break;
+	case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
+		{
+			u16 *pu2Tmp;
+			pu2Tmp = (u16 *)pOut;
+			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
+		}
+		break;
+	case TYPE_EFUSE_MAP_LEN:
+		{
+			u16 *pu2Tmp;
+			pu2Tmp = (u16 *)pOut;
+			*pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
+		}
+		break;
+	case TYPE_EFUSE_PROTECT_BYTES_BANK:
+		{
+			u8 *pu1Tmp;
+			pu1Tmp = (u8 *)pOut;
+			*pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
+		}
+		break;
+	default:
+		{
+			u8 *pu1Tmp;
+			pu1Tmp = (u8 *)pOut;
+			*pu1Tmp = 0;
+		}
+		break;
+	}
+}
 
-static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
 {
-	int ret;
+	u16	tmpaddr = 0;
+	u16	start_addr = efuse_addr;
+	u8 badworden = 0x0F;
+	u8 tmpdata[8];
 
-	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
+	memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
 
-	return ret;
-}
+	if (!(word_en&BIT0)) {
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
+		efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
 
-/*-----------------------------------------------------------------------------
- * Function:	efuse_WordEnableDataRead
- *
- * Overview:	Read allowed word in current efuse section data.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/16/2008	MHC		Create Version 0.
- * 11/21/2008	MHC		Fix Write bug when we only enable late word.
- *
- *---------------------------------------------------------------------------*/
-void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
-{
-	if (!(word_en&BIT(0))) {
-		targetdata[0] = sourdata[0];
-		targetdata[1] = sourdata[1];
+		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
+		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
+		if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
+			badworden &= (~BIT0);
 	}
-	if (!(word_en&BIT(1))) {
-		targetdata[2] = sourdata[2];
-		targetdata[3] = sourdata[3];
+	if (!(word_en&BIT1)) {
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
+		efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
+
+		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
+		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
+		if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
+			badworden &= (~BIT1);
 	}
-	if (!(word_en&BIT(2))) {
-		targetdata[4] = sourdata[4];
-		targetdata[5] = sourdata[5];
+	if (!(word_en&BIT2)) {
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
+		efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
+
+		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
+		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
+		if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
+			badworden &= (~BIT2);
 	}
-	if (!(word_en&BIT(3))) {
-		targetdata[6] = sourdata[6];
-		targetdata[7] = sourdata[7];
+	if (!(word_en&BIT3)) {
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
+		efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
+
+		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
+		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
+		if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
+			badworden &= (~BIT3);
 	}
+	return badworden;
 }
 
-u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
+u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
 {
-	u8 ret = 0;
+	int	bContinual = true;
+	u16	efuse_addr = 0;
+	u8 hoffset = 0, hworden = 0;
+	u8 efuse_data, word_cnts = 0;
 
-	ret =  pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
+	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
 
-	return ret;
-}
+	while (bContinual &&
+	       efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
+	       AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+		if (efuse_data != 0xFF) {
+			if ((efuse_data&0x1F) == 0x0F) {		/* extended header */
+				hoffset = efuse_data;
+				efuse_addr++;
+				efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+				if ((efuse_data & 0x0F) == 0x0F) {
+					efuse_addr++;
+					continue;
+				} else {
+					hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+					hworden = efuse_data & 0x0F;
+				}
+			} else {
+				hoffset = (efuse_data>>4) & 0x0F;
+				hworden =  efuse_data & 0x0F;
+			}
+			word_cnts = Efuse_CalculateWordCnts(hworden);
+			/* read next header */
+			efuse_addr = efuse_addr + (word_cnts*2)+1;
+		} else {
+			bContinual = false;
+		}
+	}
 
-static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
-{
-	return efuse_OneByteRead(padapter, address, value, false);
-}
+	rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
 
-static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
-{
-	return efuse_OneByteWrite(padapter, address, *value, false);
+	return efuse_addr;
 }
 
-/*
- * read/wirte raw efuse data
- */
-u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
+int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
 {
-	int i = 0;
-	u16 real_content_len = 0, max_available_size = 0;
-	u8 res = _FAIL;
-	u8 (*rw8)(struct adapter *, u16, u8*);
+	u8 ReadState = PG_STATE_HEADER;
+	int	bContinual = true;
+	int	bDataEmpty = true;
+	u8 efuse_data, word_cnts = 0;
+	u16	efuse_addr = 0;
+	u8 hoffset = 0, hworden = 0;
+	u8 tmpidx = 0;
+	u8 tmpdata[8];
+	u8 max_section = 0;
+	u8 tmp_header = 0;
 
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section);
 
-	if (start_addr > real_content_len)
-		return _FAIL;
+	if (data == NULL)
+		return false;
+	if (offset > max_section)
+		return false;
 
-	if (write) {
-		if ((start_addr + cnts) > max_available_size)
-			return _FAIL;
-		rw8 = &efuse_write8;
-	} else {
-		rw8 = &efuse_read8;
-	}
+	memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+	memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
 
-	Efuse_PowerSwitch(padapter, write, true);
+	/*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
+	/*  Skip dummy parts to prevent unexpected data read from Efuse. */
+	/*  By pass right now. 2009.02.19. */
+	while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+		/*   Header Read ------------- */
+		if (ReadState & PG_STATE_HEADER) {
+			if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
+				if (EXT_HEADER(efuse_data)) {
+					tmp_header = efuse_data;
+					efuse_addr++;
+					efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+					if (!ALL_WORDS_DISABLED(efuse_data)) {
+						hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+						hworden = efuse_data & 0x0F;
+					} else {
+						DBG_88E("Error, All words disabled\n");
+						efuse_addr++;
+						continue;
+					}
+				} else {
+					hoffset = (efuse_data>>4) & 0x0F;
+					hworden =  efuse_data & 0x0F;
+				}
+				word_cnts = Efuse_CalculateWordCnts(hworden);
+				bDataEmpty = true;
 
-	/*  e-fuse one byte read / write */
-	for (i = 0; i < cnts; i++) {
-		if (start_addr >= real_content_len) {
-			res = _FAIL;
-			break;
+				if (hoffset == offset) {
+					for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
+						if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) {
+							tmpdata[tmpidx] = efuse_data;
+							if (efuse_data != 0xff)
+								bDataEmpty = false;
+						}
+					}
+					if (bDataEmpty == false) {
+						ReadState = PG_STATE_DATA;
+					} else {/* read next header */
+						efuse_addr = efuse_addr + (word_cnts*2)+1;
+						ReadState = PG_STATE_HEADER;
+					}
+				} else {/* read next header */
+					efuse_addr = efuse_addr + (word_cnts*2)+1;
+					ReadState = PG_STATE_HEADER;
+				}
+			} else {
+				bContinual = false;
+			}
+		} else if (ReadState & PG_STATE_DATA) {
+		/*   Data section Read ------------- */
+			efuse_WordEnableDataRead(hworden, tmpdata, data);
+			efuse_addr = efuse_addr + (word_cnts*2)+1;
+			ReadState = PG_STATE_HEADER;
 		}
 
-		res = rw8(padapter, start_addr++, data++);
-		if (_FAIL == res)
-			break;
 	}
 
-	Efuse_PowerSwitch(padapter, write, false);
-
-	return res;
-}
-/*  */
-u16 efuse_GetMaxSize(struct adapter *padapter)
-{
-	u16 max_size;
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
-	return max_size;
+	if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
+	    (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
+		return false;
+	else
+		return true;
 }
-/*  */
-u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
-{
-	Efuse_PowerSwitch(padapter, false, true);
-	*size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
-	Efuse_PowerSwitch(padapter, false, false);
 
-	return _SUCCESS;
-}
-/*  */
-u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
 {
-	u16 mapLen = 0;
-
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
-
-	if ((addr + cnts) > mapLen)
-		return _FAIL;
+	u8 originaldata[8], badworden = 0;
+	u16	efuse_addr = *pAddr;
+	u32	PgWriteSuccess = 0;
 
-	Efuse_PowerSwitch(padapter, false, true);
+	memset((void *)originaldata, 0xff, 8);
 
-	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
+		/* check if data exist */
+		badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata);
 
-	Efuse_PowerSwitch(padapter, false, false);
+		if (badworden != 0xf) {	/*  write fail */
+			PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
 
-	return _SUCCESS;
+			if (!PgWriteSuccess)
+				return false;
+			else
+				efuse_addr = Efuse_GetCurrentSize(pAdapter);
+		} else {
+			efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
+		}
+	} else {
+		efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
+	}
+	*pAddr = efuse_addr;
+	return true;
 }
 
-u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
 {
-	u16 mapLen = 0;
+	bool bRet = false;
+	u16	efuse_addr = *pAddr, efuse_max_available_len = 0;
+	u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
+	u8 repeatcnt = 0;
 
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
 
-	if ((addr + cnts) > mapLen)
-		return _FAIL;
+	while (efuse_addr < efuse_max_available_len) {
+		pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
+		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
 
-	Efuse_PowerSwitch(padapter, false, true);
+		while (tmp_header == 0xFF) {
+			if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+				return false;
 
-	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+		}
 
-	Efuse_PowerSwitch(padapter, false, false);
+		/* to write ext_header */
+		if (tmp_header == pg_header) {
+			efuse_addr++;
+			pg_header_temp = pg_header;
+			pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
 
-	return _SUCCESS;
-}
-/*  */
-u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
-{
-	u8 offset, word_en;
-	u8 *map;
-	u8 newdata[PGPKT_DATA_SIZE + 1];
-	s32	i, idx;
-	u8 ret = _SUCCESS;
-	u16 mapLen = 0;
+			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
 
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+			while (tmp_header == 0xFF) {
+				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+					return false;
 
-	if ((addr + cnts) > mapLen)
-		return _FAIL;
+				efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+				efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+			}
 
-	map = rtw_zmalloc(mapLen);
-	if (map == NULL)
-		return _FAIL;
+			if ((tmp_header & 0x0F) == 0x0F) {	/* word_en PG fail */
+				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
+					return false;
+				} else {
+					efuse_addr++;
+					continue;
+				}
+			} else if (pg_header != tmp_header) {	/* offset PG fail */
+				struct pgpkt	fixPkt;
+				fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
+				fixPkt.word_en = tmp_header & 0x0F;
+				fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+				if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+					return false;
+			} else {
+				bRet = true;
+				break;
+			}
+		} else if ((tmp_header & 0x1F) == 0x0F) {		/* wrong extended header */
+			efuse_addr += 2;
+			continue;
+		}
+	}
 
-	ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
-	if (ret == _FAIL)
-		goto exit;
+	*pAddr = efuse_addr;
+	return bRet;
+}
 
-	Efuse_PowerSwitch(padapter, true, true);
+static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+	bool bRet = false;
+	u8 pg_header = 0, tmp_header = 0;
+	u16	efuse_addr = *pAddr;
+	u8 repeatcnt = 0;
 
-	offset = (addr >> 3);
-	word_en = 0xF;
-	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
-	i = addr & 0x7;	/*  index of one package */
-	idx = 0;	/*  data index */
+	pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
 
-	if (i & 0x1) {
-		/*  odd start */
-		if (data[idx] != map[addr+idx]) {
-			word_en &= ~BIT(i >> 1);
-			newdata[i-1] = map[addr+idx-1];
-			newdata[i] = data[idx];
-		}
-		i++;
-		idx++;
+	efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+	efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+	while (tmp_header == 0xFF) {
+		if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+			return false;
+		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
 	}
-	do {
-		for (; i < PGPKT_DATA_SIZE; i += 2) {
-			if (cnts == idx)
-				break;
-			if ((cnts - idx) == 1) {
-				if (data[idx] != map[addr+idx]) {
-					word_en &= ~BIT(i >> 1);
-					newdata[i] = data[idx];
-					newdata[i+1] = map[addr+idx+1];
-				}
-				idx++;
-				break;
-			} else {
-				if ((data[idx] != map[addr+idx]) ||
-				    (data[idx+1] != map[addr+idx+1])) {
-					word_en &= ~BIT(i >> 1);
-					newdata[i] = data[idx];
-					newdata[i+1] = data[idx + 1];
-				}
-				idx += 2;
-			}
-			if (idx == cnts)
-				break;
-		}
 
-		if (word_en != 0xF) {
-			ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
-			DBG_88E("offset=%x\n", offset);
-			DBG_88E("word_en=%x\n", word_en);
+	if (pg_header == tmp_header) {
+		bRet = true;
+	} else {
+		struct pgpkt	fixPkt;
+		fixPkt.offset = (tmp_header>>4) & 0x0F;
+		fixPkt.word_en = tmp_header & 0x0F;
+		fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+		if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+			return false;
+	}
 
-			for (i = 0; i < PGPKT_DATA_SIZE; i++)
-				DBG_88E("data=%x \t", newdata[i]);
-			if (ret == _FAIL)
-				break;
-		}
+	*pAddr = efuse_addr;
+	return bRet;
+}
 
-		if (idx == cnts)
-			break;
+static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+	u16	efuse_addr = *pAddr;
+	u8 badworden = 0;
+	u32	PgWriteSuccess = 0;
 
-		offset++;
-		i = 0;
-		word_en = 0xF;
-		_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
-	} while (1);
+	badworden = 0x0f;
+	badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data);
+	if (badworden == 0x0F) {
+		/*  write ok */
+		return true;
+	} else {
+		/* reorganize other pg packet */
+		PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+		if (!PgWriteSuccess)
+			return false;
+		else
+			return true;
+	}
+}
 
-	Efuse_PowerSwitch(padapter, true, false);
-exit:
-	kfree(map);
-	return ret;
+static bool
+hal_EfusePgPacketWriteHeader(
+				struct adapter *pAdapter,
+				u8 efuseType,
+				u16				*pAddr,
+				struct pgpkt *pTargetPkt)
+{
+	bool bRet = false;
+
+	if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
+		bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+	else
+		bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+
+	return bRet;
 }
 
-/*  */
-u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
+			  u8 *pWden)
 {
-	u8 offset, word_en;
-	u8 *map;
-	u8 newdata[PGPKT_DATA_SIZE + 1];
-	s32	i, idx;
-	u8 ret = _SUCCESS;
-	u16 mapLen = 0;
+	u8 match_word_en = 0x0F;	/*  default all words are disabled */
 
-	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+	/*  check if the same words are enabled both target and current PG packet */
+	if (((pTargetPkt->word_en & BIT0) == 0) &&
+	    ((pCurPkt->word_en & BIT0) == 0))
+		match_word_en &= ~BIT0;				/*  enable word 0 */
+	if (((pTargetPkt->word_en & BIT1) == 0) &&
+	    ((pCurPkt->word_en & BIT1) == 0))
+		match_word_en &= ~BIT1;				/*  enable word 1 */
+	if (((pTargetPkt->word_en & BIT2) == 0) &&
+	    ((pCurPkt->word_en & BIT2) == 0))
+		match_word_en &= ~BIT2;				/*  enable word 2 */
+	if (((pTargetPkt->word_en & BIT3) == 0) &&
+	    ((pCurPkt->word_en & BIT3) == 0))
+		match_word_en &= ~BIT3;				/*  enable word 3 */
 
-	if ((addr + cnts) > mapLen)
-		return _FAIL;
+	*pWden = match_word_en;
 
-	map = rtw_zmalloc(mapLen);
-	if (map == NULL)
-		return _FAIL;
+	if (match_word_en != 0xf)
+		return true;
+	else
+		return false;
+}
 
-	ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
-	if (ret == _FAIL)
-		goto exit;
+static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
+{
+	bool bRet = false;
+	u8 i, efuse_data;
 
-	Efuse_PowerSwitch(padapter, true, true);
+	for (i = 0; i < (word_cnts*2); i++) {
+		if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF))
+			bRet = true;
+	}
+	return bRet;
+}
 
-	offset = (addr >> 3);
-	word_en = 0xF;
-	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
-	i = addr & 0x7;	/*  index of one package */
-	idx = 0;	/*  data index */
+static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+	bool bRet = false;
+	u8 i, efuse_data = 0, cur_header = 0;
+	u8 matched_wden = 0, badworden = 0;
+	u16	startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
+	struct pgpkt curPkt;
 
-	if (i & 0x1) {
-		/*  odd start */
-		if (data[idx] != map[addr+idx]) {
-			word_en &= ~BIT(i >> 1);
-			newdata[i-1] = map[addr+idx-1];
-			newdata[i] = data[idx];
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max);
+
+	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
+	startAddr %= EFUSE_REAL_CONTENT_LEN;
+
+	while (1) {
+		if (startAddr >= efuse_max_available_len) {
+			bRet = false;
+			break;
 		}
-		i++;
-		idx++;
-	}
-	do {
-		for (; i < PGPKT_DATA_SIZE; i += 2) {
-			if (cnts == idx)
-				break;
-			if ((cnts - idx) == 1) {
-				if (data[idx] != map[addr+idx]) {
-					word_en &= ~BIT(i >> 1);
-					newdata[i] = data[idx];
-					newdata[i+1] = map[addr+idx+1];
+
+		if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
+			if (EXT_HEADER(efuse_data)) {
+				cur_header = efuse_data;
+				startAddr++;
+				efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
+				if (ALL_WORDS_DISABLED(efuse_data)) {
+					bRet = false;
+					break;
+				} else {
+					curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+					curPkt.word_en = efuse_data & 0x0F;
 				}
-				idx++;
-				break;
 			} else {
-				if ((data[idx] != map[addr+idx]) ||
-				    (data[idx+1] != map[addr+idx+1])) {
-					word_en &= ~BIT(i >> 1);
-					newdata[i] = data[idx];
-					newdata[i+1] = data[idx + 1];
+				cur_header  =  efuse_data;
+				curPkt.offset = (cur_header>>4) & 0x0F;
+				curPkt.word_en = cur_header & 0x0F;
+			}
+
+			curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
+			/*  if same header is found but no data followed */
+			/*  write some part of data followed by the header. */
+			if ((curPkt.offset == pTargetPkt->offset) &&
+			    (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) &&
+			    wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
+				/*  Here to write partial data */
+				badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data);
+				if (badworden != 0x0F) {
+					u32	PgWriteSuccess = 0;
+					/*  if write fail on some words, write these bad words again */
+
+					PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+
+					if (!PgWriteSuccess) {
+						bRet = false;	/*  write fail, return */
+						break;
+					}
 				}
-				idx += 2;
+				/*  partial write ok, update the target packet for later use */
+				for (i = 0; i < 4; i++) {
+					if ((matched_wden & (0x1<<i)) == 0)	/*  this word has been written */
+						pTargetPkt->word_en |= (0x1<<i);	/*  disable the word */
+				}
+				pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
 			}
-			if (idx == cnts)
-				break;
+			/*  read from next header */
+			startAddr = startAddr + (curPkt.word_cnts*2) + 1;
+		} else {
+			/*  not used header, 0xff */
+			*pAddr = startAddr;
+			bRet = true;
+			break;
 		}
+	}
+	return bRet;
+}
 
-		if (word_en != 0xF) {
-			DBG_88E("%s: offset=%#X\n", __func__, offset);
-			DBG_88E("%s: word_en=%#X\n", __func__, word_en);
-			DBG_88E("%s: data=", __func__);
-			for (i = 0; i < PGPKT_DATA_SIZE; i++)
-				DBG_88E("0x%02X ", newdata[i]);
-			DBG_88E("\n");
+static bool
+hal_EfusePgCheckAvailableAddr(
+		struct adapter *pAdapter,
+		u8 efuseType
+	)
+{
+	u16	efuse_max_available_len = 0;
 
-			ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
-			if (ret == _FAIL)
-				break;
-		}
+	/* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
+	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len);
 
-		if (idx == cnts)
-			break;
+	if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len)
+		return false;
+	return true;
+}
 
-		offset++;
-		i = 0;
-		word_en = 0xF;
-		_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
-	} while (1);
+static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
+{
+	memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
+	pTargetPkt->offset = offset;
+	pTargetPkt->word_en = word_en;
+	efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
+	pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+}
 
-	Efuse_PowerSwitch(padapter, true, false);
+bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
+{
+	struct pgpkt	targetPkt;
+	u16			startAddr = 0;
+	u8 efuseType = EFUSE_WIFI;
 
-exit:
+	if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
+		return false;
 
-	kfree(map);
+	hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
 
-	return ret;
+	if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
+		return false;
+
+	if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
+		return false;
+
+	if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
+		return false;
+
+	return true;
 }
 
-/*-----------------------------------------------------------------------------
- * Function:	efuse_ShadowRead1Byte
- *			efuse_ShadowRead2Byte
- *			efuse_ShadowRead4Byte
- *
- * Overview:	Read from efuse init map by one/two/four bytes !!!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/12/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-static void
-efuse_ShadowRead1Byte(
-		struct adapter *pAdapter,
-		u16 Offset,
-		u8 *Value)
+u8 Efuse_CalculateWordCnts(u8 word_en)
 {
-	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+	u8 word_cnts = 0;
+	if (!(word_en & BIT(0)))
+		word_cnts++; /*  0 : write enable */
+	if (!(word_en & BIT(1)))
+		word_cnts++;
+	if (!(word_en & BIT(2)))
+		word_cnts++;
+	if (!(word_en & BIT(3)))
+		word_cnts++;
+	return word_cnts;
+}
 
-	*Value = pEEPROM->efuse_eeprom_data[Offset];
+u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
+{
+	u8 tmpidx = 0;
+	u8 result;
 
-}	/*  EFUSE_ShadowRead1Byte */
+	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
+	usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
+		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
 
-/* Read Two Bytes */
-static void
-efuse_ShadowRead2Byte(
-		struct adapter *pAdapter,
-		u16 Offset,
-		u16 *Value)
+	usb_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
+
+	while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+		tmpidx++;
+	if (tmpidx < 100) {
+		*data = usb_read8(pAdapter, EFUSE_CTRL);
+		result = true;
+	} else {
+		*data = 0xff;
+		result = false;
+	}
+	return result;
+}
+
+u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
 {
-	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+	u8 tmpidx = 0;
+	u8 result;
 
-	*Value = pEEPROM->efuse_eeprom_data[Offset];
-	*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
+	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
+	usb_write8(pAdapter, EFUSE_CTRL+2,
+		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
+		   (u8)((addr>>8) & 0x03));
+	usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
 
-}	/*  EFUSE_ShadowRead2Byte */
+	usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
 
-/* Read Four Bytes */
-static void
-efuse_ShadowRead4Byte(
-		struct adapter *pAdapter,
-		u16 Offset,
-		u32 *Value)
-{
-	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+	while ((0x80 &  usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+		tmpidx++;
 
-	*Value = pEEPROM->efuse_eeprom_data[Offset];
-	*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
-	*Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
-	*Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
+	if (tmpidx < 100)
+		result = true;
+	else
+		result = false;
 
-}	/*  efuse_ShadowRead4Byte */
+	return result;
+}
 
-/*-----------------------------------------------------------------------------
- * Function:	Efuse_ReadAllMap
- *
+/*
+ * Overview:   Read allowed word in current efuse section data.
+ */
+void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
+{
+	if (!(word_en&BIT(0))) {
+		targetdata[0] = sourdata[0];
+		targetdata[1] = sourdata[1];
+	}
+	if (!(word_en&BIT(1))) {
+		targetdata[2] = sourdata[2];
+		targetdata[3] = sourdata[3];
+	}
+	if (!(word_en&BIT(2))) {
+		targetdata[4] = sourdata[4];
+		targetdata[5] = sourdata[5];
+	}
+	if (!(word_en&BIT(3))) {
+		targetdata[6] = sourdata[6];
+		targetdata[7] = sourdata[7];
+	}
+}
+
+/*
  * Overview:	Read All Efuse content
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/11/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+ */
+static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
 {
 	u16 mapLen = 0;
 
 	Efuse_PowerSwitch(pAdapter, false, true);
 
-	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
-	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
 
 	Efuse_PowerSwitch(pAdapter, false, false);
 }
 
-/*-----------------------------------------------------------------------------
- * Function:	EFUSE_ShadowMapUpdate
- *
+/*
  * Overview:	Transfer current EFUSE content to shadow init and modify map.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/13/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+ */
 void EFUSE_ShadowMapUpdate(
 	struct adapter *pAdapter,
-	u8 efuseType,
-	bool pseudo)
+	u8 efuseType)
 {
 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 	u16 mapLen = 0;
 
-	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
 	if (pEEPROM->bautoload_fail_flag)
-		_rtw_memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
+		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 	else
-		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
-} /*  EFUSE_ShadowMapUpdate */
-
-/*-----------------------------------------------------------------------------
- * Function:	EFUSE_ShadowRead
- *
- * Overview:	Read from efuse init map !!!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/12/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
-{
-	if (Type == 1)
-		efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
-	else if (Type == 2)
-		efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
-	else if (Type == 4)
-		efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
-
-}	/*  EFUSE_ShadowRead */
+		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ieee80211.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ieee80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ieee80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,11 +20,11 @@
 #define _IEEE80211_C
 
 #include <drv_types.h>
+#include <osdep_intf.h>
 #include <ieee80211.h>
 #include <wifi.h>
 #include <osdep_service.h>
 #include <wlan_bssdef.h>
-#include <usb_osintf.h>
 
 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
 u16 RTW_WPA_VERSION = 1;
@@ -206,8 +206,8 @@ inline u8 *rtw_set_ie_mesh_ch_switch_par
 
 	ie_data[0] = ttl;
 	ie_data[1] = flags;
-	RTW_PUT_LE16((u8 *)&ie_data[2], reason);
-	RTW_PUT_LE16((u8 *)&ie_data[4], precedence);
+	*(u16 *)(ie_data+2) = cpu_to_le16(reason);
+	*(u16 *)(ie_data+4) = cpu_to_le16(precedence);
 
 	return rtw_set_ie(buf, 0x118,  6, ie_data, buf_len);
 }
@@ -334,7 +334,7 @@ exit:
 void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
 {
 
-	_rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+	memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
 	switch (mode) {
 	case WIRELESS_11B:
@@ -551,7 +551,7 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa
 
 	/* pairwise_cipher */
 	if (left >= 2) {
-		count = RTW_GET_LE16(pos);
+		count = get_unaligned_le16(pos);
 		pos += 2;
 		left -= 2;
 
@@ -619,7 +619,7 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rs
 
 	/* pairwise_cipher */
 	if (left >= 2) {
-		count = RTW_GET_LE16(pos);
+		count = get_unaligned_le16(pos);
 		pos += 2;
 		left -= 2;
 
@@ -807,8 +807,8 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wp
 
 	while (attr_ptr - wps_ie < wps_ielen) {
 		/*  4 = 2(Attribute ID) + 2(Length) */
-		u16 attr_id = RTW_GET_BE16(attr_ptr);
-		u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
+		u16 attr_id = get_unaligned_be16(attr_ptr);
+		u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
 		u16 attr_len = attr_data_len + 4;
 
 		if (attr_id == target_attr_id) {
@@ -957,7 +957,7 @@ enum parse_res rtw_ieee802_11_parse_elem
 	u8 *pos = start;
 	int unknown = 0;
 
-	_rtw_memset(elems, 0, sizeof(*elems));
+	memset(elems, 0, sizeof(*elems));
 
 	while (left >= 2) {
 		u8 id, elen;
@@ -1067,41 +1067,18 @@ enum parse_res rtw_ieee802_11_parse_elem
 	return unknown ? ParseUnknown : ParseOK;
 }
 
-u8 key_char2num(u8 ch)
-{
-	if ((ch >= '0') && (ch <= '9'))
-		return ch - '0';
-	else if ((ch >= 'a') && (ch <= 'f'))
-		return ch - 'a' + 10;
-	else if ((ch >= 'A') && (ch <= 'F'))
-		return ch - 'A' + 10;
-	else
-		return 0xff;
-}
-
-u8 str_2char2num(u8 hch, u8 lch)
-{
-    return (key_char2num(hch) * 10) + key_char2num(lch);
-}
-
-u8 key_2char2num(u8 hch, u8 lch)
-{
-    return (key_char2num(hch) << 4) | key_char2num(lch);
-}
-
 void rtw_macaddr_cfg(u8 *mac_addr)
 {
 	u8 mac[ETH_ALEN];
+
 	if (mac_addr == NULL)
 		return;
 
-	if (rtw_initmac) {	/* Users specify the mac address */
-		int jj, kk;
-
-		for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-			mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]);
+	if (rtw_initmac && mac_pton(rtw_initmac, mac)) {
+		/* Users specify the mac address */
 		memcpy(mac_addr, mac, ETH_ALEN);
-	} else {	/* Use the mac address stored in the Efuse */
+	} else {
+		/* Use the mac address stored in the Efuse */
 		memcpy(mac, mac_addr, ETH_ALEN);
 	}
 
@@ -1133,9 +1110,6 @@ void dump_ies(u8 *buf, u32 buf_len)
 		len = *(pos+1);
 
 		DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len);
-		#ifdef CONFIG_88EU_P2P
-		dump_p2p_ie(pos, len);
-		#endif
 		dump_wps_ie(pos, len);
 
 		pos += (2 + len);
@@ -1156,217 +1130,13 @@ void dump_wps_ie(u8 *ie, u32 ie_len)
 
 	pos += 6;
 	while (pos-ie < ie_len) {
-		id = RTW_GET_BE16(pos);
-		len = RTW_GET_BE16(pos + 2);
+		id = get_unaligned_be16(pos);
+		len = get_unaligned_be16(pos + 2);
 		DBG_88E("%s ID:0x%04x, LEN:%u\n", __func__, id, len);
 		pos += (4+len);
 	}
 }
 
-#ifdef CONFIG_88EU_P2P
-void dump_p2p_ie(u8 *ie, u32 ie_len)
-{
-	u8 *pos = (u8 *)ie;
-	u8 id;
-	u16 len;
-	u8 *p2p_ie;
-	uint p2p_ielen;
-
-	p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen);
-	if (p2p_ie != ie || p2p_ielen == 0)
-		return;
-
-	pos += 6;
-	while (pos-ie < ie_len) {
-		id = *pos;
-		len = RTW_GET_LE16(pos+1);
-		DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len);
-		pos += (3+len);
-	}
-}
-
-/**
- * rtw_get_p2p_ie - Search P2P IE from a series of IEs
- * @in_ie: Address of IEs to search
- * @in_len: Length limit from in_ie
- * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
- * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
- *
- * Returns: The address of the P2P IE found, or NULL
- */
-u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
-{
-	uint cnt = 0;
-	u8 *p2p_ie_ptr;
-	u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
-
-	if (p2p_ielen != NULL)
-		*p2p_ielen = 0;
-
-	while (cnt < in_len) {
-		eid = in_ie[cnt];
-		if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
-			dump_stack();
-			return NULL;
-		}
-		if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&in_ie[cnt+2], p2p_oui, 4))) {
-			p2p_ie_ptr = in_ie + cnt;
-
-			if (p2p_ie != NULL)
-				memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-			if (p2p_ielen != NULL)
-				*p2p_ielen = in_ie[cnt + 1] + 2;
-			return p2p_ie_ptr;
-		} else {
-			cnt += in_ie[cnt + 1] + 2; /* goto next */
-		}
-	}
-	return NULL;
-}
-
-/**
- * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
- * @p2p_ie: Address of P2P IE to search
- * @p2p_ielen: Length limit from p2p_ie
- * @target_attr_id: The attribute ID of P2P attribute to search
- * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
- * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
- *
- * Returns: the address of the specific WPS attribute found, or NULL
- */
-u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id , u8 *buf_attr, u32 *len_attr)
-{
-	u8 *attr_ptr = NULL;
-	u8 *target_attr_ptr = NULL;
-	u8 p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
-
-	if (len_attr)
-		*len_attr = 0;
-
-	if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-	    (memcmp(p2p_ie + 2, p2p_oui , 4)))
-		return attr_ptr;
-
-	/*  6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
-	attr_ptr = p2p_ie + 6; /* goto first attr */
-
-	while (attr_ptr - p2p_ie < p2p_ielen) {
-		/*  3 = 1(Attribute ID) + 2(Length) */
-		u8 attr_id = *attr_ptr;
-		u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1);
-		u16 attr_len = attr_data_len + 3;
-
-		if (attr_id == target_attr_id) {
-			target_attr_ptr = attr_ptr;
-
-			if (buf_attr)
-				memcpy(buf_attr, attr_ptr, attr_len);
-			if (len_attr)
-				*len_attr = attr_len;
-			break;
-		} else {
-			attr_ptr += attr_len; /* goto next */
-		}
-	}
-	return target_attr_ptr;
-}
-
-/**
- * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
- * @p2p_ie: Address of P2P IE to search
- * @p2p_ielen: Length limit from p2p_ie
- * @target_attr_id: The attribute ID of P2P attribute to search
- * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
- * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
- *
- * Returns: the address of the specific P2P attribute content found, or NULL
- */
-u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id , u8 *buf_content, uint *len_content)
-{
-	u8 *attr_ptr;
-	u32 attr_len;
-
-	if (len_content)
-		*len_content = 0;
-
-	attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len);
-
-	if (attr_ptr && attr_len) {
-		if (buf_content)
-			memcpy(buf_content, attr_ptr+3, attr_len-3);
-
-		if (len_content)
-			*len_content = attr_len-3;
-
-		return attr_ptr+3;
-	}
-
-	return NULL;
-}
-
-u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
-{
-	u32 a_len;
-
-	*pbuf = attr_id;
-
-	/* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
-	RTW_PUT_LE16(pbuf + 1, attr_len);
-
-	if (pdata_attr)
-		memcpy(pbuf + 3, pdata_attr, attr_len);
-
-	a_len = attr_len + 3;
-
-	return a_len;
-}
-
-static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
-{
-	u8 *target_attr;
-	u32 target_attr_len;
-	uint ielen = ielen_ori;
-
-	while (1) {
-		target_attr = rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len);
-		if (target_attr && target_attr_len) {
-			u8 *next_attr = target_attr+target_attr_len;
-			uint remain_len = ielen-(next_attr-ie);
-
-			_rtw_memset(target_attr, 0, target_attr_len);
-			memcpy(target_attr, next_attr, remain_len);
-			_rtw_memset(target_attr+remain_len, 0, target_attr_len);
-			*(ie+1) -= target_attr_len;
-			ielen -= target_attr_len;
-		} else {
-			break;
-		}
-	}
-	return ielen;
-}
-
-void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex, u8 attr_id)
-{
-	u8 *p2p_ie;
-	uint p2p_ielen, p2p_ielen_ori;
-
-	p2p_ie = rtw_get_p2p_ie(bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_, NULL, &p2p_ielen_ori);
-	if (p2p_ie) {
-		p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
-		if (p2p_ielen != p2p_ielen_ori) {
-			u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
-			u8 *next_ie = p2p_ie+p2p_ielen;
-			uint remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
-
-			memcpy(next_ie, next_ie_ori, remain_len);
-			_rtw_memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
-			bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
-		}
-	}
-}
-
-#endif /* CONFIG_88EU_P2P */
-
 /* Baron adds to avoid FreeBSD warning */
 int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_io.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_io.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_io.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,301 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-/*
-
-The purpose of rtw_io.c
-
-a. provides the API
-
-b. provides the protocol engine
-
-c. provides the software interface between caller and the hardware interface
-
-
-Compiler Flag Option:
-
-USB:
-   a. USE_ASYNC_IRP: Both sync/async operations are provided.
-
-Only sync read/rtw_write_mem operations are provided.
-
-jackson@realtek.com.tw
-
-*/
-
-#define _RTW_IO_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_io.h>
-#include <osdep_intf.h>
-#include <usb_ops.h>
-
-#define rtw_le16_to_cpu(val)		le16_to_cpu(val)
-#define rtw_le32_to_cpu(val)		le32_to_cpu(val)
-#define rtw_cpu_to_le16(val)		cpu_to_le16(val)
-#define rtw_cpu_to_le32(val)		cpu_to_le32(val)
-
-
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
-{
-	u8 r_val;
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl *pintfhdl = &(pio_priv->intf);
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-
-	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
-	return r_val;
-}
-
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
-{
-	u16 r_val;
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
-	_read16 = pintfhdl->io_ops._read16;
-
-	r_val = _read16(pintfhdl, addr);
-	return r_val;
-}
-
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
-{
-	u32 r_val;
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
-	_read32 = pintfhdl->io_ops._read32;
-
-	r_val = _read32(pintfhdl, addr);
-	return r_val;
-}
-
-int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
-	int ret;
-	_write8 = pintfhdl->io_ops._write8;
-
-	ret = _write8(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-
-int _rtw_write16(struct adapter *adapter, u32 addr, u16 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
-	int ret;
-	_write16 = pintfhdl->io_ops._write16;
-
-	ret = _write16(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-int _rtw_write32(struct adapter *adapter, u32 addr, u32 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-	int ret;
-	_write32 = pintfhdl->io_ops._write32;
-
-	ret = _write32(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-
-int _rtw_writeN(struct adapter *adapter, u32 addr , u32 length , u8 *pdata)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl *pintfhdl = (struct intf_hdl *)(&(pio_priv->intf));
-	int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
-	int ret;
-	_writeN = pintfhdl->io_ops._writeN;
-
-	ret = _writeN(pintfhdl, addr, length, pdata);
-
-	return RTW_STATUS_CODE(ret);
-}
-int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
-	int ret;
-	_write8_async = pintfhdl->io_ops._write8_async;
-
-	ret = _write8_async(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-
-int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
-	int ret;
-
-	_write16_async = pintfhdl->io_ops._write16_async;
-	ret = _write16_async(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-
-int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val)
-{
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-	int ret;
-
-	_write32_async = pintfhdl->io_ops._write32_async;
-	ret = _write32_async(pintfhdl, addr, val);
-
-	return RTW_STATUS_CODE(ret);
-}
-
-void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
-	void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-
-	if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
-		RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
-			 ("rtw_read_mem:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
-			 adapter->bDriverStopped, adapter->bSurpriseRemoved));
-	     return;
-	}
-	_read_mem = pintfhdl->io_ops._read_mem;
-	_read_mem(pintfhdl, addr, cnt, pmem);
-}
-
-void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
-	void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-
-
-	_write_mem = pintfhdl->io_ops._write_mem;
-
-	_write_mem(pintfhdl, addr, cnt, pmem);
-
-}
-
-void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
-	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-
-
-	if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
-		RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
-			 ("rtw_read_port:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
-			 adapter->bDriverStopped, adapter->bSurpriseRemoved));
-	     return;
-	}
-
-	_read_port = pintfhdl->io_ops._read_port;
-
-	_read_port(pintfhdl, addr, cnt, pmem);
-
-}
-
-void _rtw_read_port_cancel(struct adapter *adapter)
-{
-	void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct intf_hdl *pintfhdl = &(pio_priv->intf);
-
-	_read_port_cancel = pintfhdl->io_ops._read_port_cancel;
-
-	if (_read_port_cancel)
-		_read_port_cancel(pintfhdl);
-}
-
-u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
-	u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
-	u32 ret = _SUCCESS;
-
-
-	_write_port = pintfhdl->io_ops._write_port;
-
-	ret = _write_port(pintfhdl, addr, cnt, pmem);
-
-
-	return ret;
-}
-
-u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
-{
-	int ret = _SUCCESS;
-	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
-	struct submit_ctx sctx;
-
-	rtw_sctx_init(&sctx, timeout_ms);
-	pxmitbuf->sctx = &sctx;
-
-	ret = _rtw_write_port(adapter, addr, cnt, pmem);
-
-	if (ret == _SUCCESS)
-		ret = rtw_sctx_wait(&sctx);
-
-	return ret;
-}
-
-void _rtw_write_port_cancel(struct adapter *adapter)
-{
-	void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
-	struct io_priv *pio_priv = &adapter->iopriv;
-	struct intf_hdl *pintfhdl = &(pio_priv->intf);
-
-	_write_port_cancel = pintfhdl->io_ops._write_port_cancel;
-
-	if (_write_port_cancel)
-		_write_port_cancel(pintfhdl);
-}
-
-int rtw_init_io_priv(struct adapter *padapter, void (*set_intf_ops)(struct _io_ops *pops))
-{
-	struct io_priv	*piopriv = &padapter->iopriv;
-	struct intf_hdl *pintf = &piopriv->intf;
-
-	if (set_intf_ops == NULL)
-		return _FAIL;
-
-	piopriv->padapter = padapter;
-	pintf->padapter = padapter;
-	pintf->pintf_dev = adapter_to_dvobj(padapter);
-
-	set_intf_ops(&pintf->io_ops);
-
-	return _SUCCESS;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,9 +25,6 @@
 #include <rtw_ioctl_set.h>
 #include <hal_intf.h>
 
-#include <usb_osintf.h>
-#include <usb_ops.h>
-
 extern void indicate_wx_scan_complete_event(struct adapter *padapter);
 
 #define IS_MAC_ADDRESS_BROADCAST(addr) \
@@ -37,32 +34,6 @@ extern void indicate_wx_scan_complete_ev
 		(addr[4] == 0xff) && (addr[5] == 0xff))  ? true : false \
 )
 
-u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
-{
-	u8	 i;
-	u8	ret = true;
-
-
-	if (ssid->SsidLength > 32) {
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
-		ret = false;
-		goto exit;
-	}
-
-	for (i = 0; i < ssid->SsidLength; i++) {
-		/* wifi, printable ascii code must be supported */
-		if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid has nonprintabl ascii\n"));
-			ret = false;
-			break;
-		}
-	}
-
-exit:
-
-	return ret;
-}
-
 u8 rtw_do_join(struct adapter *padapter)
 {
 	struct list_head *plist, *phead;
@@ -86,7 +57,7 @@ u8 rtw_do_join(struct adapter *padapter)
 
 	pmlmepriv->to_join = true;
 
-	if (_rtw_queue_empty(queue)) {
+	if (list_empty(&queue->queue)) {
 		spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 
@@ -127,7 +98,7 @@ u8 rtw_do_join(struct adapter *padapter)
 
 				pibss = padapter->registrypriv.dev_network.MacAddress;
 
-				_rtw_memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+				memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
 				memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
 
 				rtw_update_registrypriv_dev_network(padapter);
@@ -595,421 +566,6 @@ exit:
 	return ret;
 }
 
-u8 rtw_set_802_11_remove_wep(struct adapter *padapter, u32 keyindex)
-{
-	u8 ret = _SUCCESS;
-
-	if (keyindex >= 0x80000000 || padapter == NULL) {
-		ret = false;
-		goto exit;
-	} else {
-		int res;
-		struct security_priv *psecuritypriv = &(padapter->securitypriv);
-		if (keyindex < 4) {
-			_rtw_memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
-			res = rtw_set_key(padapter, psecuritypriv, keyindex, 0);
-			psecuritypriv->dot11DefKeylen[keyindex] = 0;
-			if (res == _FAIL)
-				ret = _FAIL;
-		} else {
-			ret = _FAIL;
-		}
-	}
-exit:
-
-	return ret;
-}
-
-u8 rtw_set_802_11_add_key(struct adapter *padapter, struct ndis_802_11_key *key)
-{
-	uint	encryptionalgo;
-	u8 *pbssid;
-	struct sta_info *stainfo;
-	u8	bgroup = false;
-	u8	bgrouptkey = false;/* can be removed later */
-	u8	ret = _SUCCESS;
-
-
-	if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)) {
-		/*  It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, */
-		/*  it must fail the request and return NDIS_STATUS_INVALID_DATA. */
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-			 ("rtw_set_802_11_add_key: ((key->KeyIndex & 0x80000000)==0)[=%d]",
-			 (int)(key->KeyIndex & 0x80000000) == 0));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-			 ("rtw_set_802_11_add_key:((key->KeyIndex & 0x40000000)>0)[=%d]",
-			 (int)(key->KeyIndex & 0x40000000) > 0));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-			 ("rtw_set_802_11_add_key: key->KeyIndex=%d\n",
-			 (int)key->KeyIndex));
-		ret = _FAIL;
-		goto exit;
-	}
-
-	if (key->KeyIndex & 0x40000000) {
-		/*  Pairwise key */
-
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ Pairwise key +++++\n"));
-
-		pbssid = get_bssid(&padapter->mlmepriv);
-		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
-
-		if ((stainfo != NULL) && (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("OID_802_11_ADD_KEY:(stainfo!=NULL)&&(Adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\n"));
-			encryptionalgo = stainfo->dot118021XPrivacy;
-		} else {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: stainfo == NULL)||(Adapter->securitypriv.dot11AuthAlgrthm!= dot11AuthAlgrthm_8021X)\n"));
-			encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
-		}
-
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("rtw_set_802_11_add_key: (encryptionalgo==%d)!\n",
-			 encryptionalgo));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11PrivacyAlgrthm==%d)!\n",
-			 padapter->securitypriv.dot11PrivacyAlgrthm));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11AuthAlgrthm==%d)!\n",
-			 padapter->securitypriv.dot11AuthAlgrthm));
-
-		if ((stainfo != NULL))
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("rtw_set_802_11_add_key: (stainfo->dot118021XPrivacy==%d)!\n",
-				 stainfo->dot118021XPrivacy));
-
-		if (key->KeyIndex & 0x000000FF) {
-			/*  The key index is specified in the lower 8 bits by values of zero to 255. */
-			/*  The key index should be set to zero for a Pairwise key, and the driver should fail with */
-			/*  NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero */
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, (" key->KeyIndex & 0x000000FF.\n"));
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*  check BSSID */
-		if (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == true) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MacAddr_isBcst(key->BSSID)\n"));
-			ret = false;
-			goto exit;
-		}
-
-		/*  Check key length for TKIP. */
-		if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("TKIP KeyLength:0x%x != 32\n", key->KeyLength));
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*  Check key length for AES. */
-		if ((encryptionalgo == _AES_) && (key->KeyLength != 16)) {
-			/*  For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case. */
-			if (key->KeyLength == 32) {
-				key->KeyLength = 16;
-			} else {
-				ret = _FAIL;
-				goto exit;
-			}
-		}
-
-		/*  Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko. */
-		if ((encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_) &&
-		    (key->KeyLength != 5 && key->KeyLength != 13)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("WEP KeyLength:0x%x != 5 or 13\n", key->KeyLength));
-			ret = _FAIL;
-			goto exit;
-		}
-
-		bgroup = false;
-
-		/*  Check the pairwise key. Added by Annie, 2005-07-06. */
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("[Pairwise Key set]\n"));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key index: 0x%8x(0x%8x)\n", key->KeyIndex, (key->KeyIndex&0x3)));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key Length: %d\n", key->KeyLength));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
-
-	} else {
-		/*  Group key - KeyIndex(BIT30 == 0) */
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ Group key +++++\n"));
-
-
-		/*  when add wep key through add key and didn't assigned encryption type before */
-		if ((padapter->securitypriv.ndisauthtype <= 3) &&
-		    (padapter->securitypriv.dot118021XGrpPrivacy == 0)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("keylen =%d(Adapter->securitypriv.dot11PrivacyAlgrthm=%x )padapter->securitypriv.dot118021XGrpPrivacy(%x)\n",
-				 key->KeyLength, padapter->securitypriv.dot11PrivacyAlgrthm,
-				 padapter->securitypriv.dot118021XGrpPrivacy));
-			switch (key->KeyLength) {
-			case 5:
-				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-					 ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
-					 padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
-				break;
-			case 13:
-				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-					 ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
-					 padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
-				break;
-			default:
-				padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-					 ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
-					 padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
-				break;
-			}
-
-			encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
-
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 (" Adapter->securitypriv.dot11PrivacyAlgrthm=%x\n",
-				 padapter->securitypriv.dot11PrivacyAlgrthm));
-
-		} else {
-			encryptionalgo = padapter->securitypriv.dot118021XGrpPrivacy;
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("(Adapter->securitypriv.dot11PrivacyAlgrthm=%x)encryptionalgo(%x)=padapter->securitypriv.dot118021XGrpPrivacy(%x)keylen=%d\n",
-				 padapter->securitypriv.dot11PrivacyAlgrthm, encryptionalgo,
-				 padapter->securitypriv.dot118021XGrpPrivacy, key->KeyLength));
-		}
-
-		if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE) == true) && (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == false)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 (" IBSS but BSSID is not Broadcast Address.\n"));
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*  Check key length for TKIP */
-		if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 (" TKIP GTK KeyLength:%u != 32\n", key->KeyLength));
-			ret = _FAIL;
-			goto exit;
-		} else if (encryptionalgo == _AES_ && (key->KeyLength != 16 && key->KeyLength != 32)) {
-			/*  Check key length for AES */
-			/*  For NDTEST, we allow keylen = 32 in this case. 2005.01.27, by rcnjko. */
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("<=== SetInfo, OID_802_11_ADD_KEY: AES GTK KeyLength:%u != 16 or 32\n",
-				 key->KeyLength));
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*  Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03. */
-		if ((encryptionalgo ==  _AES_) && (key->KeyLength == 32)) {
-			key->KeyLength = 16;
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("AES key length changed: %u\n", key->KeyLength));
-		}
-
-		if (key->KeyIndex & 0x8000000) {/* error ??? 0x8000_0000 */
-			bgrouptkey = true;
-		}
-
-		if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)) &&
-		    (check_fwstate(&padapter->mlmepriv, _FW_LINKED)))
-			bgrouptkey = true;
-		bgroup = true;
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("[Group Key set]\n"));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n")) ;
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key index: 0x%8x(0x%8x)\n", key->KeyIndex, (key->KeyIndex&0x3)));
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key Length: %d\n", key->KeyLength)) ;
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
-	}
-
-	/*  If WEP encryption algorithm, just call rtw_set_802_11_add_wep(). */
-	if ((padapter->securitypriv.dot11AuthAlgrthm != dot11AuthAlgrthm_8021X) &&
-	    (encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_)) {
-		u32 keyindex;
-		u32 len = FIELD_OFFSET(struct ndis_802_11_key, KeyMaterial) + key->KeyLength;
-		struct ndis_802_11_wep *wep = &padapter->securitypriv.ndiswep;
-
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ WEP key +++++\n"));
-
-		wep->Length = len;
-		keyindex = key->KeyIndex&0x7fffffff;
-		wep->KeyIndex = keyindex ;
-		wep->KeyLength = key->KeyLength;
-
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY:Before memcpy\n"));
-
-		memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);
-		memcpy(&(padapter->securitypriv.dot11DefKey[keyindex].skey[0]), key->KeyMaterial, key->KeyLength);
-
-		padapter->securitypriv.dot11DefKeylen[keyindex] = key->KeyLength;
-		padapter->securitypriv.dot11PrivacyKeyIndex = keyindex;
-
-		ret = rtw_set_802_11_add_wep(padapter, wep);
-		goto exit;
-	}
-	if (key->KeyIndex & 0x20000000) {
-		/*  SetRSC */
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ SetRSC+++++\n"));
-		if (bgroup) {
-			unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
-			memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);
-		} else {
-			unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
-			memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);
-		}
-	}
-
-	/*  Indicate this key idx is used for TX */
-	/*  Save the key in KeyMaterial */
-	if (bgroup) { /*  Group transmit key */
-		int res;
-
-		if (bgrouptkey)
-			padapter->securitypriv.dot118021XGrpKeyid = (u8)key->KeyIndex;
-		if ((key->KeyIndex&0x3) == 0) {
-			ret = _FAIL;
-			goto exit;
-		}
-		_rtw_memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
-		_rtw_memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
-		_rtw_memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
-
-		if ((key->KeyIndex & 0x10000000)) {
-			memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
-			memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
-
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
-		} else {
-			memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
-			memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
-
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],
-				 padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
-		}
-
-		/* set group key by index */
-		memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
-
-		key->KeyIndex = key->KeyIndex & 0x03;
-
-		padapter->securitypriv.binstallGrpkey = true;
-
-		padapter->securitypriv.bcheck_grpkey = false;
-
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("reset group key"));
-
-		res = rtw_set_key(padapter, &padapter->securitypriv, key->KeyIndex, 1);
-
-		if (res == _FAIL)
-			ret = _FAIL;
-
-		goto exit;
-
-	} else { /*  Pairwise Key */
-		u8 res;
-
-		pbssid = get_bssid(&padapter->mlmepriv);
-		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
-
-		if (stainfo != NULL) {
-			_rtw_memset(&stainfo->dot118021x_UncstKey, 0, 16);/*  clear keybuffer */
-
-			memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
-
-			if (encryptionalgo == _TKIP_) {
-				padapter->securitypriv.busetkipkey = false;
-
-				/* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
-
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n========== _set_timer\n"));
-
-				/*  if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255] */
-				if ((key->KeyIndex & 0x10000000)) {
-					memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
-					memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
-
-				} else {
-					memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
-					memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
-				}
-			}
-
-
-			/* Set key to CAM through H2C command */
-			if (bgrouptkey) { /* never go to here */
-				res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, false);
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(group)\n"));
-			} else {
-				res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, true);
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n"));
-			}
-			if (!res)
-				ret = _FAIL;
-		}
-	}
-exit:
-
-	return ret;
-}
-
-u8 rtw_set_802_11_remove_key(struct adapter *padapter, struct ndis_802_11_remove_key *key)
-{
-	u8 *pbssid;
-	struct sta_info *stainfo;
-	u8	bgroup = (key->KeyIndex & 0x4000000) > 0 ? false : true;
-	u8	keyIndex = (u8)key->KeyIndex & 0x03;
-	u8	ret = _SUCCESS;
-
-
-	if ((key->KeyIndex & 0xbffffffc) > 0) {
-		ret = _FAIL;
-		goto exit;
-	}
-
-	if (bgroup) {
-		/*  clear group key by index */
-
-		_rtw_memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
-
-		/*  \todo Send a H2C Command to Firmware for removing this Key in CAM Entry. */
-	} else {
-		pbssid = get_bssid(&padapter->mlmepriv);
-		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
-		if (stainfo) {
-			/*  clear key by BSSID */
-			_rtw_memset(&stainfo->dot118021x_UncstKey, 0, 16);
-
-			/*  \todo Send a H2C Command to Firmware for disable this Key in CAM Entry. */
-		} else {
-			ret = _FAIL;
-			goto exit;
-		}
-	}
-exit:
-
-	return ret;
-}
-
 /*
 * rtw_get_cur_max_rate -
 * @adapter: pointer to struct adapter structure
@@ -1078,36 +634,6 @@ u16 rtw_get_cur_max_rate(struct adapter
 }
 
 /*
-* rtw_set_scan_mode -
-* @adapter: pointer to struct adapter structure
-* @scan_mode:
-*
-* Return _SUCCESS or _FAIL
-*/
-int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode)
-{
-	if (scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
-		return _FAIL;
-
-	adapter->mlmepriv.scan_mode = scan_mode;
-
-	return _SUCCESS;
-}
-
-/*
-* rtw_set_channel_plan -
-* @adapter: pointer to struct adapter structure
-* @channel_plan:
-*
-* Return _SUCCESS or _FAIL
-*/
-int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan)
-{
-	/* handle by cmd_thread to sync with scan operation */
-	return rtw_set_chplan_cmd(adapter, channel_plan, 1);
-}
-
-/*
 * rtw_set_country -
 * @adapter: pointer to struct adapter structure
 * @country_code: string of country code
@@ -1133,5 +659,5 @@ int rtw_set_country(struct adapter *adap
 	else
 		DBG_88E("%s unknown country_code:%s\n", __func__, country_code);
 
-	return rtw_set_channel_plan(adapter, channel_plan);
+	return rtw_set_chplan_cmd(adapter, channel_plan, 1);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_iol.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_iol.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_iol.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_iol.c	2014-09-28 17:29:07.000000000 -0400
@@ -113,20 +113,6 @@ int _rtw_IOL_append_WB_cmd(struct xmit_f
 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
 }
 
-int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
-{
-	struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
-
-	cmd.address = cpu_to_le16(addr);
-	cmd.data = cpu_to_le32(value);
-
-	if (mask != 0xFFFF) {
-		cmd.length = 12;
-		cmd.mask =  cpu_to_le32(mask);
-	}
-	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
-}
-
 int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
 {
 	struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_led.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_led.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_led.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_led.c	2014-09-28 17:29:07.000000000 -0400
@@ -88,8 +88,8 @@ void InitLed871x(struct adapter *padapte
 /*  */
 void DeInitLed871x(struct LED_871x *pLed)
 {
-	_cancel_workitem_sync(&(pLed->BlinkWorkItem));
-	_cancel_timer_ex(&(pLed->BlinkTimer));
+	cancel_work_sync(&(pLed->BlinkWorkItem));
+	del_timer_sync(&(pLed->BlinkTimer));
 	ResetLedStatus(pLed);
 }
 
@@ -251,11 +251,11 @@ static void SwLedControlMode1(struct ada
 			if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 				return;
 			if (pLed->bLedLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedBlinkInProgress = false;
 			}
 
@@ -273,11 +273,11 @@ static void SwLedControlMode1(struct ada
 			if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 				return;
 			if (pLed->bLedNoLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedNoLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedBlinkInProgress = false;
 			}
 			pLed->bLedLinkBlinkInProgress = true;
@@ -296,15 +296,15 @@ static void SwLedControlMode1(struct ada
 			if (IS_LED_WPS_BLINKING(pLed))
 				return;
 			if (pLed->bLedNoLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedNoLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				 pLed->bLedLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedBlinkInProgress = false;
 			}
 			pLed->bLedScanBlinkInProgress = true;
@@ -323,11 +323,11 @@ static void SwLedControlMode1(struct ada
 			if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 				return;
 			if (pLed->bLedNoLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedNoLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedLinkBlinkInProgress = false;
 			}
 			pLed->bLedBlinkInProgress = true;
@@ -344,19 +344,19 @@ static void SwLedControlMode1(struct ada
 	case LED_CTL_START_WPS_BOTTON:
 		 if (!pLed->bLedWPSBlinkInProgress) {
 			if (pLed->bLedNoLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedNoLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedLinkBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				 pLed->bLedLinkBlinkInProgress = false;
 			}
 			if (pLed->bLedBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedBlinkInProgress = false;
 			}
 			if (pLed->bLedScanBlinkInProgress) {
-				_cancel_timer_ex(&(pLed->BlinkTimer));
+				del_timer_sync(&(pLed->BlinkTimer));
 				pLed->bLedScanBlinkInProgress = false;
 			}
 			pLed->bLedWPSBlinkInProgress = true;
@@ -370,23 +370,23 @@ static void SwLedControlMode1(struct ada
 		break;
 	case LED_CTL_STOP_WPS:
 		if (pLed->bLedNoLinkBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedNoLinkBlinkInProgress = false;
 		}
 		if (pLed->bLedLinkBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			 pLed->bLedLinkBlinkInProgress = false;
 		}
 		if (pLed->bLedBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedBlinkInProgress = false;
 		}
 		if (pLed->bLedScanBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedScanBlinkInProgress = false;
 		}
 		if (pLed->bLedWPSBlinkInProgress)
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 		else
 			pLed->bLedWPSBlinkInProgress = true;
 		pLed->CurrLedState = LED_BLINK_WPS_STOP;
@@ -400,7 +400,7 @@ static void SwLedControlMode1(struct ada
 		break;
 	case LED_CTL_STOP_WPS_FAIL:
 		if (pLed->bLedWPSBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedWPSBlinkInProgress = false;
 		}
 		pLed->bLedNoLinkBlinkInProgress = true;
@@ -415,23 +415,23 @@ static void SwLedControlMode1(struct ada
 		pLed->CurrLedState = RTW_LED_OFF;
 		pLed->BlinkingLedState = RTW_LED_OFF;
 		if (pLed->bLedNoLinkBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedNoLinkBlinkInProgress = false;
 		}
 		if (pLed->bLedLinkBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedLinkBlinkInProgress = false;
 		}
 		if (pLed->bLedBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedBlinkInProgress = false;
 		}
 		if (pLed->bLedWPSBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedWPSBlinkInProgress = false;
 		}
 		if (pLed->bLedScanBlinkInProgress) {
-			_cancel_timer_ex(&(pLed->BlinkTimer));
+			del_timer_sync(&(pLed->BlinkTimer));
 			pLed->bLedScanBlinkInProgress = false;
 		}
 		SwLedOff(padapter, pLed);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mlme.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mlme.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mlme.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mlme.c	2014-09-28 17:29:07.000000000 -0400
@@ -30,13 +30,12 @@
 #include <wifi.h>
 #include <wlan_bssdef.h>
 #include <rtw_ioctl_set.h>
-#include <usb_osintf.h>
 #include <linux/vmalloc.h>
 
 extern unsigned char	MCS_rate_2R[16];
 extern unsigned char	MCS_rate_1R[16];
 
-int _rtw_init_mlme_priv(struct adapter *padapter)
+int rtw_init_mlme_priv(struct adapter *padapter)
 {
 	int	i;
 	u8	*pbuf;
@@ -59,7 +58,7 @@ int _rtw_init_mlme_priv(struct adapter *
 
 	set_scanned_network_val(pmlmepriv, 0);
 
-	_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
+	memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
 
 	pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
 
@@ -72,9 +71,9 @@ int _rtw_init_mlme_priv(struct adapter *
 	pnetwork = (struct wlan_network *)pbuf;
 
 	for (i = 0; i < MAX_BSS_CNT; i++) {
-		_rtw_init_listhead(&(pnetwork->list));
+		INIT_LIST_HEAD(&(pnetwork->list));
 
-		rtw_list_insert_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
+		list_add_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
 
 		pnetwork++;
 	}
@@ -118,7 +117,7 @@ void rtw_free_mlme_priv_ie_data(struct m
 }
 #endif
 
-void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
+void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
 {
 	rtw_free_mlme_priv_ie_data(pmlmepriv);
 
@@ -128,40 +127,6 @@ void _rtw_free_mlme_priv(struct mlme_pri
 	}
 }
 
-int	_rtw_enqueue_network(struct __queue *queue, struct wlan_network *pnetwork)
-{
-	if (pnetwork == NULL)
-		goto exit;
-
-	spin_lock_bh(&queue->lock);
-
-	rtw_list_insert_tail(&pnetwork->list, &queue->queue);
-
-	spin_unlock_bh(&queue->lock);
-
-exit:
-	return _SUCCESS;
-}
-
-struct	wlan_network *_rtw_dequeue_network(struct __queue *queue)
-{
-	struct wlan_network *pnetwork;
-
-	spin_lock_bh(&queue->lock);
-
-	if (_rtw_queue_empty(queue)) {
-		pnetwork = NULL;
-	} else {
-		pnetwork = container_of((&queue->queue)->next, struct wlan_network, list);
-
-		rtw_list_delete(&(pnetwork->list));
-	}
-
-	spin_unlock_bh(&queue->lock);
-
-	return pnetwork;
-}
-
 struct	wlan_network *_rtw_alloc_network(struct	mlme_priv *pmlmepriv)/* _queue *free_queue) */
 {
 	struct	wlan_network	*pnetwork;
@@ -170,7 +135,7 @@ struct	wlan_network *_rtw_alloc_network(
 
 	spin_lock_bh(&free_queue->lock);
 
-	if (_rtw_queue_empty(free_queue) == true) {
+	if (list_empty(&free_queue->queue)) {
 		pnetwork = NULL;
 		goto exit;
 	}
@@ -178,7 +143,7 @@ struct	wlan_network *_rtw_alloc_network(
 
 	pnetwork = container_of(plist , struct wlan_network, list);
 
-	rtw_list_delete(&pnetwork->list);
+	list_del_init(&pnetwork->list);
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist));
 	pnetwork->network_type = 0;
@@ -195,7 +160,7 @@ exit:
 	return pnetwork;
 }
 
-void _rtw_free_network(struct	mlme_priv *pmlmepriv , struct wlan_network *pnetwork, u8 isfreeall)
+static void _rtw_free_network(struct	mlme_priv *pmlmepriv , struct wlan_network *pnetwork, u8 isfreeall)
 {
 	u32 curr_time, delta_time;
 	u32 lifetime = SCANQUEUE_LIFETIME;
@@ -216,8 +181,8 @@ void _rtw_free_network(struct	mlme_priv
 			return;
 	}
 	spin_lock_bh(&free_queue->lock);
-	rtw_list_delete(&(pnetwork->list));
-	rtw_list_insert_tail(&(pnetwork->list), &(free_queue->queue));
+	list_del_init(&(pnetwork->list));
+	list_add_tail(&(pnetwork->list), &(free_queue->queue));
 	pmlmepriv->num_of_scanned--;
 	spin_unlock_bh(&free_queue->lock);
 }
@@ -230,8 +195,8 @@ void _rtw_free_network_nolock(struct	mlm
 		return;
 	if (pnetwork->fixed)
 		return;
-	rtw_list_delete(&(pnetwork->list));
-	rtw_list_insert_tail(&(pnetwork->list), get_list_head(free_queue));
+	list_del_init(&(pnetwork->list));
+	list_add_tail(&(pnetwork->list), get_list_head(free_queue));
 	pmlmepriv->num_of_scanned--;
 }
 
@@ -240,7 +205,7 @@ void _rtw_free_network_nolock(struct	mlm
 
 	Shall be calle under atomic context... to avoid possible racing condition...
 */
-struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
 {
 	struct list_head *phead, *plist;
 	struct	wlan_network *pnetwork = NULL;
@@ -266,7 +231,7 @@ exit:
 }
 
 
-void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
+void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
 {
 	struct list_head *phead, *plist;
 	struct wlan_network *pnetwork;
@@ -278,7 +243,7 @@ void _rtw_free_network_queue(struct adap
 	phead = get_list_head(scanned_queue);
 	plist = phead->next;
 
-	while (rtw_end_of_queue_search(phead, plist) == false) {
+	while (phead != plist) {
 		pnetwork = container_of(plist, struct wlan_network, list);
 
 		plist = plist->next;
@@ -332,29 +297,11 @@ u16 rtw_get_capability(struct wlan_bssid
 	return le16_to_cpu(val);
 }
 
-u8 *rtw_get_timestampe_from_ie(u8 *ie)
-{
-	return ie + 0;
-}
-
 u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
 {
 	return ie + 8;
 }
 
-int rtw_init_mlme_priv(struct adapter *padapter)
-{
-	int	res;
-	res = _rtw_init_mlme_priv(padapter);/*  (pmlmepriv); */
-	return res;
-}
-
-void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
-{
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv\n"));
-	_rtw_free_mlme_priv(pmlmepriv);
-}
-
 static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
 {
 	return _rtw_alloc_network(pmlmepriv);
@@ -366,24 +313,6 @@ static void rtw_free_network_nolock(stru
 	_rtw_free_network_nolock(pmlmepriv, pnetwork);
 }
 
-
-void rtw_free_network_queue(struct adapter *dev, u8 isfreeall)
-{
-	_rtw_free_network_queue(dev, isfreeall);
-}
-
-/*
-	return the wlan_network with the matching addr
-
-	Shall be calle under atomic context... to avoid possible racing condition...
-*/
-struct	wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
-{
-	struct	wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
-
-	return pnetwork;
-}
-
 int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
 {
 	int ret = true;
@@ -438,7 +367,7 @@ struct	wlan_network	*rtw_get_oldest_wlan
 	plist = phead->next;
 
 	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
+		if (phead == plist)
 			break;
 
 		pwlan = container_of(plist, struct wlan_network, list);
@@ -522,10 +451,7 @@ void rtw_update_scanned_network(struct a
 	phead = get_list_head(queue);
 	plist = phead->next;
 
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
+	while (phead != plist) {
 		pnetwork	= container_of(plist, struct wlan_network, list);
 
 		if (is_same_network(&(pnetwork->network), target))
@@ -537,8 +463,8 @@ void rtw_update_scanned_network(struct a
 	}
 	/* If we didn't find a match, then get a new network slot to initialize
 	 * with this beacon's information */
-	if (rtw_end_of_queue_search(phead, plist) == true) {
-		if (_rtw_queue_empty(&(pmlmepriv->free_bss_pool)) == true) {
+	if (phead == plist) {
+		if (list_empty(&(pmlmepriv->free_bss_pool.queue))) {
 			/* If there are no more slots, expire the oldest */
 			pnetwork = oldest;
 
@@ -575,7 +501,7 @@ void rtw_update_scanned_network(struct a
 			/* bss info not receiving from the right channel */
 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
 				pnetwork->network.PhyInfo.SignalQuality = 0;
-			rtw_list_insert_tail(&(pnetwork->list), &(queue->queue));
+			list_add_tail(&(pnetwork->list), &(queue->queue));
 		}
 	} else {
 		/* we have an entry and we are going to update it. But this entry may
@@ -601,9 +527,6 @@ exit:
 static void rtw_add_network(struct adapter *adapter,
 			    struct wlan_bssid_ex *pnetwork)
 {
-#if defined(CONFIG_88EU_P2P)
-	rtw_wlan_bssid_ex_remove_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO);
-#endif
 	update_current_network(adapter, pnetwork);
 	rtw_update_scanned_network(adapter, pnetwork);
 }
@@ -728,10 +651,7 @@ void rtw_surveydone_event_callback(struc
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
 
 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
-		u8 timer_cancelled;
-
-		_cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
-
+		del_timer_sync(&pmlmepriv->scan_to_timer);
 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 	} else {
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status=%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
@@ -754,7 +674,7 @@ void rtw_surveydone_event_callback(struc
 
 					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
 
-					_rtw_memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+					memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
 					memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
 
 					rtw_update_registrypriv_dev_network(adapter);
@@ -798,14 +718,9 @@ void rtw_surveydone_event_callback(struc
 
 	spin_unlock_bh(&pmlmepriv->lock);
 
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-		p2p_ps_wk_cmd(adapter, P2P_PS_SCAN_DONE, 0);
-
 	rtw_os_xmit_schedule(adapter);
 
 	pmlmeext = &adapter->mlmeextpriv;
-	if (pmlmeext->sitesurvey_res.bss_cnt == 0)
-		rtw_hal_sreset_reset(adapter);
 }
 
 void rtw_dummy_event_callback(struct adapter *adapter , u8 *pbuf)
@@ -831,8 +746,8 @@ static void free_scanqueue(struct	mlme_p
 
 	while (plist != phead) {
 		ptemp = plist->next;
-		rtw_list_delete(plist);
-		rtw_list_insert_tail(plist, &free_queue->queue);
+		list_del_init(plist);
+		list_add_tail(plist, &free_queue->queue);
 		plist = ptemp;
 		pmlmepriv->num_of_scanned--;
 	}
@@ -945,7 +860,6 @@ void rtw_indicate_disconnect(struct adap
 		rtw_led_control(padapter, LED_CTL_NO_LINK);
 		rtw_clear_scan_deny(padapter);
 	}
-	p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
 
 	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
 }
@@ -1002,11 +916,11 @@ static struct sta_info *rtw_joinbss_upda
 			padapter->securitypriv.bgrpkey_handshake = false;
 			psta->ieee8021x_blocked = true;
 			psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
-			_rtw_memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
-			_rtw_memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
-			_rtw_memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
-			_rtw_memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
-			_rtw_memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
+			memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
+			memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
+			memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
+			memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
+			memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
 		}
 		/*
 		 * Commented by Albert 2012/07/21
@@ -1108,7 +1022,6 @@ static void rtw_joinbss_update_network(s
 
 void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
 {
-	u8 timer_cancelled;
 	struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
 	struct	sta_priv *pstapriv = &adapter->stapriv;
 	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
@@ -1201,7 +1114,7 @@ void rtw_joinbss_event_prehandle(struct
 				}
 
 			/* s5. Cancle assoc_timer */
-			_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+			del_timer_sync(&pmlmepriv->assoc_timer);
 
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancle assoc_timer\n"));
 
@@ -1421,7 +1334,7 @@ void rtw_stadel_event_callback(struct ad
 
 			memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
 
-			_rtw_memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+			memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
 			memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
 
 			rtw_update_registrypriv_dev_network(adapter);
@@ -1449,8 +1362,9 @@ void rtw_cpwm_event_callback(struct adap
 * _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
 * @adapter: pointer to struct adapter structure
 */
-void _rtw_join_timeout_handler (struct adapter *adapter)
+void _rtw_join_timeout_handler (void *function_context)
 {
+	struct adapter *adapter = (struct adapter *)function_context;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	int do_join_r;
 
@@ -1490,8 +1404,9 @@ void _rtw_join_timeout_handler (struct a
 * rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
 * @adapter: pointer to struct adapter structure
 */
-void rtw_scan_timeout_handler (struct adapter *adapter)
+void rtw_scan_timeout_handler (void *function_context)
 {
+	struct adapter *adapter = (struct adapter *)function_context;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
 	DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
@@ -1516,48 +1431,27 @@ static void rtw_auto_scan_handler(struct
 	}
 }
 
-void rtw_dynamic_check_timer_handlder(struct adapter *adapter)
+void rtw_dynamic_check_timer_handlder(void *function_context)
 {
-	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct adapter *adapter = (struct adapter *)function_context;
 	struct registry_priv *pregistrypriv = &adapter->registrypriv;
 
 	if (!adapter)
-		return;
+		goto exit;
 	if (!adapter->hw_init_completed)
-		return;
+		goto exit;
 	if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved))
-		return;
+		goto exit;
 	if (adapter->net_closed)
-		return;
+		goto exit;
 	rtw_dynamic_chk_wk_cmd(adapter);
 
 	if (pregistrypriv->wifi_spec == 1) {
-#ifdef CONFIG_88EU_P2P
-		struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-#endif
-		{
-			/* auto site survey */
-			rtw_auto_scan_handler(adapter);
-		}
-	}
-
-	rcu_read_lock();
-
-	if (rcu_dereference(adapter->pnetdev->rx_handler_data) &&
-	    (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == true)) {
-		/*  expire NAT2.5 entry */
-		nat25_db_expire(adapter);
-
-		if (adapter->pppoe_connection_in_progress > 0)
-			adapter->pppoe_connection_in_progress--;
-
-		/*  due to rtw_dynamic_check_timer_handlder() is called every 2 seconds */
-		if (adapter->pppoe_connection_in_progress > 0)
-			adapter->pppoe_connection_in_progress--;
+		/* auto site survey */
+		rtw_auto_scan_handler(adapter);
 	}
-
-	rcu_read_unlock();
+exit:
+	_set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
 }
 
 #define RTW_SCAN_RESULT_EXPIRE 2000
@@ -1635,7 +1529,7 @@ int rtw_select_and_join_from_scanned_que
 	phead = get_list_head(queue);
 	adapter = (struct adapter *)pmlmepriv->nic_hdl;
 	pmlmepriv->pscanned = phead->next;
-	while (!rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) {
+	while (phead != pmlmepriv->pscanned) {
 		pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 		if (pnetwork == NULL) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork==NULL)\n", __func__));
@@ -1689,26 +1583,26 @@ int rtw_set_auth(struct adapter *adapter
 	struct	cmd_priv *pcmdpriv = &(adapter->cmdpriv);
 	int		res = _SUCCESS;
 
-	pcmd = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd == NULL) {
 		res = _FAIL;  /* try again */
 		goto exit;
 	}
 
-	psetauthparm = (struct setauth_parm *)rtw_zmalloc(sizeof(struct setauth_parm));
+	psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
 	if (psetauthparm == NULL) {
 		kfree(pcmd);
 		res = _FAIL;
 		goto exit;
 	}
-	_rtw_memset(psetauthparm, 0, sizeof(struct setauth_parm));
+	memset(psetauthparm, 0, sizeof(struct setauth_parm));
 	psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
 	pcmd->cmdcode = _SetAuth_CMD_;
 	pcmd->parmbuf = (unsigned char *)psetauthparm;
 	pcmd->cmdsz =  (sizeof(struct setauth_parm));
 	pcmd->rsp = NULL;
 	pcmd->rspsz = 0;
-	_rtw_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
 		 ("after enqueue set_auth_cmd, auth_mode=%x\n",
 		 psecuritypriv->dot11AuthAlgrthm));
@@ -1726,17 +1620,17 @@ int rtw_set_key(struct adapter *adapter,
 	struct mlme_priv		*pmlmepriv = &(adapter->mlmepriv);
 	int	res = _SUCCESS;
 
-	pcmd = (struct	cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
+	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd == NULL)
 		return _FAIL;  /* try again */
 
-	psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
+	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
 	if (psetkeyparm == NULL) {
 		res = _FAIL;
 		goto err_free_cmd;
 	}
 
-	_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
+	memset(psetkeyparm, 0, sizeof(struct setkey_parm));
 
 	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
 		psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
@@ -1789,7 +1683,7 @@ int rtw_set_key(struct adapter *adapter,
 	pcmd->cmdsz =  (sizeof(struct setkey_parm));
 	pcmd->rsp = NULL;
 	pcmd->rspsz = 0;
-	_rtw_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 	return res;
 
@@ -2070,7 +1964,7 @@ unsigned int rtw_restructure_ht_ie(struc
 
 		out_len = *pout_len;
 
-		_rtw_memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
+		memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
 
 		ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
 				    IEEE80211_HT_CAP_SGI_20 |
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c	2014-09-28 17:29:07.000000000 -0400
@@ -256,7 +256,7 @@ static void init_mlme_ext_priv_value(str
 	pmlmeinfo->enc_algo = _NO_PRIVACY_;
 	pmlmeinfo->authModeToggle = 0;
 
-	_rtw_memset(pmlmeinfo->chg_txt, 0, 128);
+	memset(pmlmeinfo->chg_txt, 0, 128);
 
 	pmlmeinfo->slotTime = SHORT_SLOT_TIME;
 	pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
@@ -328,7 +328,7 @@ static u8 init_channel_set(struct adapte
 	u8 b2_4GBand = false;
 	u8 Index2G = 0;
 
-	_rtw_memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
+	memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
 
 	if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
 		DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
@@ -408,9 +408,8 @@ void free_mlme_ext_priv(struct mlme_ext_
 		return;
 
 	if (padapter->bDriverStopped) {
-		_cancel_timer_ex(&pmlmeext->survey_timer);
-		_cancel_timer_ex(&pmlmeext->link_timer);
-		/* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
+		del_timer_sync(&pmlmeext->survey_timer);
+		del_timer_sync(&pmlmeext->link_timer);
 	}
 }
 
@@ -509,23 +508,6 @@ void mgt_dispatcher(struct adapter *pada
 #endif
 }
 
-#ifdef CONFIG_88EU_P2P
-static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
-{
-	bool response = true;
-
-	/*	do nothing if the device name is empty */
-	if (!padapter->wdinfo.device_name_len)
-		response = false;
-
-	if (response)
-		issue_probersp_p2p(padapter, da);
-
-	return _SUCCESS;
-}
-#endif /* CONFIG_88EU_P2P */
-
-
 /****************************************************************************
 
 Following are the callback functions for each subtype of the management frames
@@ -544,43 +526,6 @@ unsigned int OnProbeReq(struct adapter *
 	uint len = precv_frame->len;
 	u8 is_valid_p2p_probereq = false;
 
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8 wifi_test_chk_rate = 1;
-
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
-	    !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
-		/*	mcs_rate = 0 -> CCK 1M rate */
-		/*	mcs_rate = 1 -> CCK 2M rate */
-		/*	mcs_rate = 2 -> CCK 5.5M rate */
-		/*	mcs_rate = 3 -> CCK 11M rate */
-		/*	In the P2P mode, the driver should not support the CCK rate */
-
-		/*	Commented by Kurt 2012/10/16 */
-		/*	IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
-		if (wifi_test_chk_rate == 1) {
-			is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
-			if (is_valid_p2p_probereq) {
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
-					/*  FIXME */
-					report_survey_event(padapter, precv_frame);
-					p2p_listen_state_process(padapter,  get_sa(pframe));
-
-					return _SUCCESS;
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-					goto _continue;
-			}
-		}
-	}
-
-_continue:
-#endif /* CONFIG_88EU_P2P */
-
 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 		return _SUCCESS;
 
@@ -612,48 +557,6 @@ _issue_probersp:
 unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame)
 {
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
-	u8 *pframe = precv_frame->rx_data;
-#endif
-
-#ifdef CONFIG_88EU_P2P
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
-		if (pwdinfo->tx_prov_disc_info.benable) {
-			if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-					pwdinfo->tx_prov_disc_info.benable = false;
-					issue_p2p_provision_request(padapter,
-								    pwdinfo->tx_prov_disc_info.ssid.Ssid,
-								    pwdinfo->tx_prov_disc_info.ssid.SsidLength,
-								    pwdinfo->tx_prov_disc_info.peerDevAddr);
-				} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-					pwdinfo->tx_prov_disc_info.benable = false;
-					issue_p2p_provision_request(padapter, NULL, 0,
-								    pwdinfo->tx_prov_disc_info.peerDevAddr);
-				}
-			}
-		}
-		return _SUCCESS;
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
-		if (pwdinfo->nego_req_info.benable) {
-			DBG_88E("[%s] P2P State is GONEGO ING!\n", __func__);
-			if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
-				pwdinfo->nego_req_info.benable = false;
-				issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
-			}
-		}
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
-		if (pwdinfo->invitereq_info.benable) {
-			DBG_88E("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
-			if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
-				pwdinfo->invitereq_info.benable = false;
-				issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
-			}
-		}
-	}
-#endif
-
 
 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 		report_survey_event(padapter, precv_frame);
@@ -718,7 +621,6 @@ unsigned int OnBeacon(struct adapter *pa
 				/* todo: the timer is used instead of the number of the beacon received */
 				if ((sta_rx_pkts(psta) & 0xf) == 0)
 					update_beacon_info(padapter, pframe, len, psta);
-				process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
 			}
 		} else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 			psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
@@ -817,8 +719,8 @@ unsigned int OnAuth(struct adapter *pada
 		pstat->auth_seq = 0;
 	} else {
 		spin_lock_bh(&pstapriv->asoc_list_lock);
-		if (!rtw_is_list_empty(&pstat->asoc_list)) {
-			rtw_list_delete(&pstat->asoc_list);
+		if (!list_empty(&pstat->asoc_list)) {
+			list_del_init(&pstat->asoc_list);
 			pstapriv->asoc_list_cnt--;
 		}
 		spin_unlock_bh(&pstapriv->asoc_list_lock);
@@ -829,8 +731,8 @@ unsigned int OnAuth(struct adapter *pada
 	}
 
 	spin_lock_bh(&pstapriv->auth_list_lock);
-	if (rtw_is_list_empty(&pstat->auth_list)) {
-		rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
+	if (list_empty(&pstat->auth_list)) {
+		list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
 		pstapriv->auth_list_cnt++;
 	}
 	spin_unlock_bh(&pstapriv->auth_list_lock);
@@ -914,7 +816,7 @@ auth_fail:
 		rtw_free_stainfo(padapter , pstat);
 
 	pstat = &stat;
-	_rtw_memset((char *)pstat, '\0', sizeof(stat));
+	memset((char *)pstat, '\0', sizeof(stat));
 	pstat->auth_seq = 2;
 	memcpy(pstat->hwaddr, sa, 6);
 
@@ -1022,12 +924,6 @@ unsigned int OnAssocReq(struct adapter *
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	u8 *pframe = precv_frame->rx_data;
 	uint pkt_len = precv_frame->len;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8 p2p_status_code = P2P_STATUS_SUCCESS;
-	u8 *p2pie;
-	u32 p2pielen = 0;
-#endif /* CONFIG_88EU_P2P */
 
 	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 		return _FAIL;
@@ -1054,7 +950,7 @@ unsigned int OnAssocReq(struct adapter *
 		goto asoc_class2_error;
 	}
 
-	capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
+	capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
 
 	left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
 	pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
@@ -1146,7 +1042,7 @@ unsigned int OnAssocReq(struct adapter *
 	pstat->wpa2_group_cipher = 0;
 	pstat->wpa_pairwise_cipher = 0;
 	pstat->wpa2_pairwise_cipher = 0;
-	_rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
+	memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
 	if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
 		int group_cipher = 0, pairwise_cipher = 0;
 
@@ -1314,7 +1210,7 @@ unsigned int OnAssocReq(struct adapter *
 	}
 
 	/* save HT capabilities in the sta object */
-	_rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
+	memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
 	if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
 		pstat->flags |= WLAN_STA_HT;
 
@@ -1357,23 +1253,6 @@ unsigned int OnAssocReq(struct adapter *
 	if (status != _STATS_SUCCESSFUL_)
 		goto OnAssocReqFail;
 
-#ifdef CONFIG_88EU_P2P
-	pstat->is_p2p_device = false;
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen);
-		if (p2pie) {
-			pstat->is_p2p_device = true;
-			p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
-			if (p2p_status_code > 0) {
-				pstat->p2p_status_code = p2p_status_code;
-				status = _STATS_CAP_FAIL_;
-				goto OnAssocReqFail;
-			}
-		}
-	}
-	pstat->p2p_status_code = p2p_status_code;
-#endif /* CONFIG_88EU_P2P */
-
 	/* TODO: identify_proprietary_vendor_ie(); */
 	/*  Realtek proprietary IE */
 	/*  identify if this is Broadcom sta */
@@ -1407,16 +1286,16 @@ unsigned int OnAssocReq(struct adapter *
 	pstat->state |= WIFI_FW_ASSOC_SUCCESS;
 
 	spin_lock_bh(&pstapriv->auth_list_lock);
-	if (!rtw_is_list_empty(&pstat->auth_list)) {
-		rtw_list_delete(&pstat->auth_list);
+	if (!list_empty(&pstat->auth_list)) {
+		list_del_init(&pstat->auth_list);
 		pstapriv->auth_list_cnt--;
 	}
 	spin_unlock_bh(&pstapriv->auth_list_lock);
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
-	if (rtw_is_list_empty(&pstat->asoc_list)) {
+	if (list_empty(&pstat->asoc_list)) {
 		pstat->expire_to = pstapriv->expire_to;
-		rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
+		list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
 		pstapriv->asoc_list_cnt++;
 	}
 	spin_unlock_bh(&pstapriv->asoc_list_lock);
@@ -1495,7 +1374,7 @@ unsigned int OnAssocRsp(struct adapter *
 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
 		return _SUCCESS;
 
-	_cancel_timer_ex(&pmlmeext->link_timer);
+	del_timer_sync(&pmlmeext->link_timer);
 
 	/* status */
 	status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
@@ -1567,22 +1446,12 @@ unsigned int OnDeAuth(struct adapter *pa
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	u8 *pframe = precv_frame->rx_data;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	/* check A3 */
 	if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
 		   ETH_ALEN))
 		return _SUCCESS;
 
-#ifdef CONFIG_88EU_P2P
-	if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
-		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
-		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
-	}
-#endif /* CONFIG_88EU_P2P */
-
 	reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
 
 	DBG_88E("%s Reason code(%d)\n", __func__, reason);
@@ -1600,8 +1469,8 @@ unsigned int OnDeAuth(struct adapter *pa
 			u8 updated = 0;
 
 			spin_lock_bh(&pstapriv->asoc_list_lock);
-			if (!rtw_is_list_empty(&psta->asoc_list)) {
-				rtw_list_delete(&psta->asoc_list);
+			if (!list_empty(&psta->asoc_list)) {
+				list_del_init(&psta->asoc_list);
 				pstapriv->asoc_list_cnt--;
 				updated = ap_free_sta(padapter, psta, false, reason);
 			}
@@ -1631,22 +1500,12 @@ unsigned int OnDisassoc(struct adapter *
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	u8 *pframe = precv_frame->rx_data;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	/* check A3 */
 	if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network),
 		   ETH_ALEN))
 		return _SUCCESS;
 
-#ifdef CONFIG_88EU_P2P
-	if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
-		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
-		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
-	}
-#endif /* CONFIG_88EU_P2P */
-
 	reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
 
 	DBG_88E("%s Reason code(%d)\n", __func__, reason);
@@ -1664,8 +1523,8 @@ unsigned int OnDisassoc(struct adapter *
 			u8 updated = 0;
 
 			spin_lock_bh(&pstapriv->asoc_list_lock);
-			if (!rtw_is_list_empty(&psta->asoc_list)) {
-				rtw_list_delete(&psta->asoc_list);
+			if (!list_empty(&psta->asoc_list)) {
+				list_del_init(&psta->asoc_list);
 				pstapriv->asoc_list_cnt--;
 				updated = ap_free_sta(padapter, psta, false, reason);
 			}
@@ -1789,7 +1648,7 @@ unsigned int OnAction_back(struct adapte
 				issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
 			break;
 		case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
-			status = RTW_GET_LE16(&frame_body[3]);
+			status = get_unaligned_le16(&frame_body[3]);
 			tid = ((frame_body[5] >> 2) & 0x7);
 			if (status == 0) {	/* successful */
 				DBG_88E("agg_enable for TID=%d\n", tid);
@@ -1803,7 +1662,7 @@ unsigned int OnAction_back(struct adapte
 			if ((frame_body[3] & BIT(3)) == 0) {
 				psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
 				psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
-				reason_code = RTW_GET_LE16(&frame_body[4]);
+				reason_code = get_unaligned_le16(&frame_body[4]);
 			} else if ((frame_body[3] & BIT(3)) == BIT(3)) {
 				tid = (frame_body[3] >> 4) & 0x0F;
 				preorder_ctrl =  &psta->recvreorder_ctrl[tid];
@@ -1820,2043 +1679,6 @@ unsigned int OnAction_back(struct adapte
 	return _SUCCESS;
 }
 
-#ifdef CONFIG_88EU_P2P
-
-static int get_reg_classes_full_count(struct p2p_channels *channel_list)
-{
-	int cnt = 0;
-	int i;
-
-	for (i = 0; i < channel_list->reg_classes; i++) {
-		cnt += channel_list->reg_class[i].channels;
-	}
-
-	return cnt;
-}
-
-void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	__be32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_GO_NEGO_REQ;
-	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
-	u8 wpsielen = 0, p2pielen = 0;
-	u16 len_channellist_attr = 0;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	DBG_88E("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pwdinfo->negotiation_dialog_token = 1;	/*	Initialize the dialog value */
-	pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
-
-
-
-	/*	WPS Section */
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Device Password ID */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-
-	if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
-	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
-	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
-
-	wpsielen += 2;
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negotiation request frame should contain 9 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Group Owner Intent */
-	/*	3. Configuration Timeout */
-	/*	4. Listen Channel */
-	/*	5. Extended Listen Timing */
-	/*	6. Intended P2P Interface Address */
-	/*	7. Channel List */
-	/*	8. P2P Device Info */
-	/*	9. Operating Channel */
-
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
-	else
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-
-	/*	Group Owner Intent */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Todo the tie breaker bit. */
-	p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
-
-
-	/*	Listen Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->listen_channel;	/*	listening channel number */
-
-
-	/*	Extended Listen Timing ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Availability Period */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-	/*	Availability Interval */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-
-	/*	Intended P2P Interface Address */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*  Length: */
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3
-	   + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
-	   + get_reg_classes_full_count(&pmlmeext->channel_list);
-
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-
-	{
-		int i, j;
-		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
-
-			/*	Number of Channels */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
-
-			/*	Channel List */
-			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
-			}
-		}
-	}
-
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_GO_NEGO_RESP;
-	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
-	u8 p2pielen = 0;
-	uint			wpsielen = 0;
-	u16 wps_devicepassword_id = 0x0000;
-	__be16			be_tmp;
-	uint			wps_devicepassword_id_len = 0;
-	u16 len_channellist_attr = 0;
-
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	DBG_88E("[%s] In, result=%d\n", __func__,  result);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pwdinfo->negotiation_dialog_token = frame_body[7];	/*	The Dialog Token of provisioning discovery request frame. */
-	pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
-
-	/*	Commented by Albert 20110328 */
-	/*	Try to get the device password ID from the WPS IE of group negotiation request frame */
-	/*	WiFi Direct test plan 5.1.15 */
-	rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
-	rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
-	wps_devicepassword_id = be16_to_cpu(be_tmp);
-
-	_rtw_memset(wpsie, 0x00, 255);
-	wpsielen = 0;
-
-	/*	WPS Section */
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Device Password ID */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
-	else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
-	else
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
-	wpsielen += 2;
-
-	/*	Commented by Kurt 20120113 */
-	/*	If some device wants to do p2p handshake without sending prov_disc_req */
-	/*	We have to get peer_req_cm from here. */
-	if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
-		if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
-		else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
-		else
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
-	}
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20100908 */
-	/*	According to the P2P Specification, the group negotiation response frame should contain 9 P2P attributes */
-	/*	1. Status */
-	/*	2. P2P Capability */
-	/*	3. Group Owner Intent */
-	/*	4. Configuration Timeout */
-	/*	5. Operating Channel */
-	/*	6. Intended P2P Interface Address */
-	/*	7. Channel List */
-	/*	8. Device Info */
-	/*	9. Group ID	(Only GO) */
-
-
-	/*	ToDo: */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = result;
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-		/*	Commented by Albert 2011/03/08 */
-		/*	According to the P2P specification */
-		/*	if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
-		p2pie[p2pielen++] = 0;
-	} else {
-		/*	Be group owner or meet the error case */
-		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-	}
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported) {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
-	} else {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-	}
-
-	/*	Group Owner Intent */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	if (pwdinfo->peer_intent & 0x01) {
-		/*	Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
-		p2pie[p2pielen++] = (pwdinfo->intent << 1);
-	} else {
-		/*	Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
-		p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
-	}
-
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
-
-	/*	Intended P2P Interface Address */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3
-	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-	   + get_reg_classes_full_count(&pmlmeext->channel_list);
-
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-
-	{
-		int i, j;
-		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
-
-			/*	Number of Channels */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
-
-			/*	Channel List */
-			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
-			}
-		}
-	}
-
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		/*	Group ID Attribute */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	p2P Device Address */
-		memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		/*	SSID */
-		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-		p2pielen += pwdinfo->nego_ssidlen;
-	}
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-	return;
-}
-
-static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_GO_NEGO_CONF;
-	u8 p2pie[255] = { 0x00 };
-	u8 p2pielen = 0;
-
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	DBG_88E("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
-
-
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negotiation request frame should contain 5 P2P attributes */
-	/*	1. Status */
-	/*	2. P2P Capability */
-	/*	3. Operating Channel */
-	/*	4. Channel List */
-	/*	5. Group ID	(if this WiFi is GO) */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = result;
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
-	else
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;
-		p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
-	} else {
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;
-
-		/*	Channel Number */
-		p2pie[p2pielen++] = pwdinfo->operating_channel;		/*	Use the listen channel as the operating channel */
-	}
-
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
-	p2pielen += pwdinfo->channel_list_attr_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		/*	Group ID Attribute */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	p2P Device Address */
-		memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		/*	SSID */
-		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-		p2pielen += pwdinfo->nego_ssidlen;
-	}
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-	pattrib->last_txcmdsz = pattrib->pktlen;
-	dump_mgntframe(padapter, pmgntframe);
-	return;
-}
-
-void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_INVIT_REQ;
-	u8 p2pie[255] = { 0x00 };
-	u8 p2pielen = 0;
-	u8 dialogToken = 3;
-	u16 len_channellist_attr = 0;
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20101011 */
-	/*	According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
-	/*	1. Configuration Timeout */
-	/*	2. Invitation Flags */
-	/*	3. Operating Channel	(Only GO) */
-	/*	4. P2P Group BSSID	(Should be included if I am the GO) */
-	/*	5. Channel List */
-	/*	6. P2P Group ID */
-	/*	7. P2P Device Info */
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
-
-	/*	Invitation Flags */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
-
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;	/*	operating channel number */
-
-	if (!memcmp(myid(&padapter->eeprompriv),
-		    pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
-		/*	P2P Group BSSID */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	P2P Device Address for GO */
-		memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-	}
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-
-	/*	Length: */
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3
-	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-	   + get_reg_classes_full_count(&pmlmeext->channel_list);
-
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-	{
-		int i, j;
-		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
-
-			/*	Number of Channels */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
-
-			/*	Channel List */
-			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
-			}
-		}
-	}
-
-
-	/*	P2P Group ID */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address for GO */
-	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	SSID */
-	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
-	p2pielen += pwdinfo->invitereq_info.ssidlen;
-
-
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen  += 4;
-
-	/*	Sub Category ID */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_INVIT_RESP;
-	u8 p2pie[255] = { 0x00 };
-	u8 p2pielen = 0;
-	u16 len_channellist_attr = 0;
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20101005 */
-	/*	According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
-	/*	1. Status */
-	/*	2. Configuration Timeout */
-	/*	3. Operating Channel	(Only GO) */
-	/*	4. P2P Group BSSID	(Only GO) */
-	/*	5. Channel List */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(__le16  *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
-	/*	Sent the event receiving the P2P Invitation Req frame to DMP UI. */
-	/*	DMP had to compare the MAC address to find out the profile. */
-	/*	So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
-	/*	If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
-	/*	to NB to rebuild the persistent group. */
-	p2pie[p2pielen++] = status_code;
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
-
-	if (status_code == P2P_STATUS_SUCCESS) {
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			/*	The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
-			/*	In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
-			/*	First one is operating channel attribute. */
-			/*	Second one is P2P Group BSSID attribute. */
-
-			/*	Operating Channel */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-			/*	Length: */
-			*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	Country String */
-			p2pie[p2pielen++] = 'X';
-			p2pie[p2pielen++] = 'X';
-
-			/*	The third byte should be set to 0x04. */
-			/*	Described in the "Operating Channel Attribute" section. */
-			p2pie[p2pielen++] = 0x04;
-
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-			/*	Channel Number */
-			p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
-
-
-			/*	P2P Group BSSID */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
-
-			/*	Length: */
-			*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	P2P Device Address for GO */
-			memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-			p2pielen += ETH_ALEN;
-		}
-
-		/*	Channel List */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-		/*	Length: */
-		/*  Country String(3) */
-		/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
-		/*  + number of channels in all classes */
-		len_channellist_attr = 3
-			+ (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-			+ get_reg_classes_full_count(&pmlmeext->channel_list);
-
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Country String */
-		p2pie[p2pielen++] = 'X';
-		p2pie[p2pielen++] = 'X';
-
-		/*	The third byte should be set to 0x04. */
-		/*	Described in the "Operating Channel Attribute" section. */
-		p2pie[p2pielen++] = 0x04;
-
-		/*	Channel Entry List */
-		{
-			int i, j;
-			for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-				/*	Operating Class */
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
-
-				/*	Number of Channels */
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
-
-				/*	Channel List */
-				for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-					p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
-				}
-			}
-		}
-	}
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
-{
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u8 dialogToken = 1;
-	u8 oui_subtype = P2P_PROVISION_DISC_REQ;
-	u8 wpsie[100] = { 0x00 };
-	u8 wpsielen = 0;
-	__be32 p2poui = cpu_to_be32(P2POUI);
-	u32			p2pielen = 0;
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	DBG_88E("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-	p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
-
-	pframe += p2pielen;
-	pattrib->pktlen += p2pielen;
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Config Method */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
-	wpsielen += 2;
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
-{
-	u8 i, match_result = 0;
-
-	DBG_88E("[%s] peermac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
-		peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);
-
-	for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
-	       DBG_88E("[%s] profileinfo_mac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
-			    profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);
-		if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
-			match_result = 1;
-			DBG_88E("[%s] Match!\n", __func__);
-			break;
-		}
-	}
-	return match_result;
-}
-
-void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	unsigned char					*mac;
-	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	u16 beacon_interval = 100;
-	u16 capInfo = 0;
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8 wpsie[255] = { 0x00 };
-	u32					wpsielen = 0, p2pielen = 0;
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	mac = myid(&(padapter->eeprompriv));
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
-
-	/*	Use the device address for BSSID field. */
-	memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(fctrl, WIFI_PROBERSP);
-
-	pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = pattrib->hdrlen;
-	pframe += pattrib->hdrlen;
-
-	/* timestamp will be inserted by hardware */
-	pframe += 8;
-	pattrib->pktlen += 8;
-
-	/*  beacon interval: 2 bytes */
-	memcpy(pframe, (unsigned char *)&beacon_interval, 2);
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-	/*	capability info: 2 bytes */
-	/*	ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
-	capInfo |= cap_ShortPremble;
-	capInfo |= cap_ShortSlot;
-
-	memcpy(pframe, (unsigned char *)&capInfo, 2);
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-
-	/*  SSID */
-	pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
-
-	/*  supported rates... */
-	/*	Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
-	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
-
-	/*  DS parameter set */
-	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
-
-	/*	Todo: WPS IE */
-	/*	Noted by Albert 20100907 */
-	/*	According to the WPS specification, all the WPS attribute is presented by Big Endian. */
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	WiFi Simple Config State */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;	/*	Not Configured. */
-
-	/*	Response Type */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
-
-	/*	UUID-E */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
-	wpsielen += 2;
-
-	/*	Value: */
-	memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	wpsielen += 0x10;
-
-	/*	Manufacturer */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
-	wpsielen += 2;
-
-	/*	Value: */
-	memcpy(wpsie + wpsielen, "Realtek", 7);
-	wpsielen += 7;
-
-	/*	Model Name */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
-	wpsielen += 2;
-
-	/*	Value: */
-	memcpy(wpsie + wpsielen, "8188EU", 6);
-	wpsielen += 6;
-
-	/*	Model Number */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = 0x31;		/*	character 1 */
-
-	/*	Serial Number */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
-	wpsielen += 2;
-
-	/*	Value: */
-	memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);
-	wpsielen += ETH_ALEN;
-
-	/*	Primary Device Type */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
-	wpsielen += 2;
-
-	/*	Value: */
-	/*	Category ID */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	wpsielen += 2;
-
-	/*	OUI */
-	*(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	Sub Category ID */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	wpsielen += 2;
-
-	/*	Device Name */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
-	wpsielen += 2;
-
-	/*	Value: */
-	if (pwdinfo->device_name_len) {
-		memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
-		wpsielen += pwdinfo->device_name_len;
-	}
-
-	/*	Config Method */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-	wpsielen += 2;
-
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-
-	p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
-	pframe += p2pielen;
-	pattrib->pktlen += p2pielen;
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
-{
-	int ret = _FAIL;
-	struct xmit_frame		*pmgntframe;
-	struct pkt_attrib		*pattrib;
-	unsigned char			*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	unsigned char			*mac;
-	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
-	u16 wpsielen = 0, p2pielen = 0;
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		goto exit;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	mac = myid(&(padapter->eeprompriv));
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	if (da) {
-		memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-		memcpy(pwlanhdr->addr3, da, ETH_ALEN);
-	} else {
-		if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
-			/*	This two flags will be set when this is only the P2P client mode. */
-			memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
-			memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
-		} else {
-			/*	broadcast probe request frame */
-			memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
-			memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
-		}
-	}
-	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_PROBEREQ);
-
-	pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
-		pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
-	else
-		pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
-
-	/*	Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
-	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
-
-
-	/*	WPS IE */
-	/*	Noted by Albert 20110221 */
-	/*	According to the WPS specification, all the WPS attribute is presented by Big Endian. */
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	if (pmlmepriv->wps_probe_req_ie == NULL) {
-		/*	UUID-E */
-		/*	Type: */
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
-		wpsielen += 0x10;
-
-		/*	Config Method */
-		/*	Type: */
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-		wpsielen += 2;
-
-		/*	Value: */
-		*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-		wpsielen += 2;
-	}
-
-	/*	Device Name */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
-	wpsielen += 2;
-
-	/*	Value: */
-	memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	wpsielen += pwdinfo->device_name_len;
-
-	/*	Primary Device Type */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
-	wpsielen += 2;
-
-	/*	Value: */
-	/*	Category ID */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
-	wpsielen += 2;
-
-	/*	OUI */
-	*(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	Sub Category ID */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
-	wpsielen += 2;
-
-	/*	Device Password ID */
-	/*	Type: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);	/*	Registrar-specified */
-	wpsielen += 2;
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110221 */
-	/*	According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. P2P Device ID if this probe request wants to find the specific P2P device */
-	/*	3. Listen Channel */
-	/*	4. Extended Listen Timing */
-	/*	5. Operating Channel if this WiFi is working as the group owner now */
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-		p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-	else
-		p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-
-	/*	Listen Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->listen_channel;	/*	listen channel */
-
-
-	/*	Extended Listen Timing */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-	/*	Length: */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Availability Period */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-	/*	Availability Interval */
-	*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		/*	Operating Channel (if this WiFi is working as the group owner now) */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Country String */
-		p2pie[p2pielen++] = 'X';
-		p2pie[p2pielen++] = 'X';
-
-		/*	The third byte should be set to 0x04. */
-		/*	Described in the "Operating Channel Attribute" section. */
-		p2pie[p2pielen++] = 0x04;
-
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-		/*	Channel Number */
-		p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
-	}
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-
-	if (pmlmepriv->wps_probe_req_ie != NULL) {
-		/* WPS IE */
-		memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
-		pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
-		pframe += pmlmepriv->wps_probe_req_ie_len;
-	}
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
-
-	if (wait_ack) {
-		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
-	} else {
-		dump_mgntframe(padapter, pmgntframe);
-		ret = _SUCCESS;
-	}
-
-exit:
-	return ret;
-}
-
-inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
-{
-	_issue_probereq_p2p(adapter, da, false);
-}
-
-int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt, int wait_ms)
-{
-	int ret;
-	int i = 0;
-	u32 start = jiffies;
-
-	do {
-		ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? true : false);
-
-		i++;
-
-		if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
-			break;
-
-		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-			msleep(wait_ms);
-	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
-	if (ret != _FAIL) {
-		ret = _SUCCESS;
-		goto exit;
-	}
-
-	if (try_cnt && wait_ms) {
-		if (da)
-			DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
-				FUNC_ADPT_ARG(adapter), da, rtw_get_oper_ch(adapter),
-				ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
-		else
-			DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-				FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
-				ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
-	}
-exit:
-	return ret;
-}
-
-#endif /* CONFIG_88EU_P2P */
-
 static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
 {
 	struct adapter *adapter = recv_frame->adapter;
@@ -3894,16 +1716,6 @@ static unsigned int on_action_public_p2p
 	u8 *pframe = precv_frame->rx_data;
 	u8 *frame_body;
 	u8 dialogToken = 0;
-#ifdef CONFIG_88EU_P2P
-	struct adapter *padapter = precv_frame->adapter;
-	uint len = precv_frame->len;
-	u8 *p2p_ie;
-	u32	p2p_ielen;
-	struct	wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8	result = P2P_STATUS_SUCCESS;
-	u8	empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-#endif /* CONFIG_88EU_P2P */
-
 	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
 
 	dialogToken = frame_body[7];
@@ -3911,272 +1723,6 @@ static unsigned int on_action_public_p2p
 	if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
 		return _FAIL;
 
-#ifdef CONFIG_88EU_P2P
-	_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
-	/*	Do nothing if the driver doesn't enable the P2P function. */
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
-		return _SUCCESS;
-
-	len -= sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	switch (frame_body[6]) { /* OUI Subtype */
-	case P2P_GO_NEGO_REQ:
-		DBG_88E("[%s] Got GO Nego Req Frame\n", __func__);
-		_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
-			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
-			/*	Commented by Albert 20110526 */
-			/*	In this case, this means the previous nego fail doesn't be reset yet. */
-			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-			/*	Restore the previous p2p state */
-			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-			DBG_88E("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
-		}
-
-		/*	Commented by Kurt 20110902 */
-		/* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
-			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-
-		/*	Commented by Kurt 20120113 */
-		/*	Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
-		if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr,
-			    ETH_ALEN))
-			memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
-
-		result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
-		issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
-
-		/*	Commented by Albert 20110718 */
-		/*	No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
-		_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
-		break;
-	case P2P_GO_NEGO_RESP:
-		DBG_88E("[%s] Got GO Nego Resp Frame\n", __func__);
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
-			/*	Commented by Albert 20110425 */
-			/*	The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
-			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-			pwdinfo->nego_req_info.benable = false;
-			result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
-			issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
-			if (P2P_STATUS_SUCCESS == result) {
-				if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
-					pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
-					pwdinfo->p2p_info.scan_op_ch_only = 1;
-					_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
-				}
-			}
-			/*	Reset the dialog token for group negotiation frames. */
-			pwdinfo->negotiation_dialog_token = 1;
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
-				_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
-		} else {
-			DBG_88E("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
-		}
-		break;
-	case P2P_GO_NEGO_CONF:
-		DBG_88E("[%s] Got GO Nego Confirm Frame\n", __func__);
-		result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
-		if (P2P_STATUS_SUCCESS == result) {
-			if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
-				pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
-				pwdinfo->p2p_info.scan_op_ch_only = 1;
-				_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
-			}
-		}
-		break;
-	case P2P_INVIT_REQ:
-		/*	Added by Albert 2010/10/05 */
-		/*	Received the P2P Invite Request frame. */
-
-		DBG_88E("[%s] Got invite request frame!\n", __func__);
-		p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
-		if (p2p_ie) {
-			/*	Parse the necessary information from the P2P Invitation Request frame. */
-			/*	For example: The MAC address of sending this P2P Invitation Request frame. */
-			u32	attr_contentlen = 0;
-			u8	status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-			struct group_id_info group_id;
-			u8	invitation_flag = 0;
-
-			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
-			if (attr_contentlen) {
-				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
-				/*	Commented by Albert 20120510 */
-				/*	Copy to the pwdinfo->p2p_peer_interface_addr. */
-				/*	So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
-				/*	#> iwpriv wlan0 p2p_get peer_ifa */
-				/*	After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
-
-				if (attr_contentlen) {
-					DBG_88E("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
-						pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
-						pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
-						pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
-				}
-
-				if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
-					/*	Re-invoke the persistent group. */
-
-					_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
-					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
-					if (attr_contentlen) {
-						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
-							/*	The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
-							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-							status_code = P2P_STATUS_SUCCESS;
-						} else {
-							/*	The p2p device sending this p2p invitation request wants to be the persistent GO. */
-							if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
-								u8 operatingch_info[5] = { 0x00 };
-								if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
-									if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
-										/*	The operating channel is acceptable for this device. */
-										pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
-										pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
-										_set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
-										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
-										rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-										status_code = P2P_STATUS_SUCCESS;
-									} else {
-										/*	The operating channel isn't supported by this device. */
-										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-										rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-										status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
-										_set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
-									}
-								} else {
-									/*	Commented by Albert 20121130 */
-									/*	Intel will use the different P2P IE to store the operating channel information */
-									/*	Workaround for Intel WiDi 3.5 */
-									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
-									rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-									status_code = P2P_STATUS_SUCCESS;
-								}
-							} else {
-								rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-								status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
-							}
-						}
-					} else {
-						DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
-						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-					}
-				} else {
-					/*	Received the invitation to join a P2P group. */
-
-					_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
-					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
-					if (attr_contentlen) {
-						if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
-							/*	In this case, the GO can't be myself. */
-							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-							status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-						} else {
-							/*	The p2p device sending this p2p invitation request wants to join an existing P2P group */
-							/*	Commented by Albert 2012/06/28 */
-							/*	In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
-							/*	The peer device address should be the destination address for the provisioning discovery request. */
-							/*	Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
-							/*	The peer interface address should be the address for WPS mac address */
-							memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-							rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
-							status_code = P2P_STATUS_SUCCESS;
-						}
-					} else {
-						DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
-						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-					}
-				}
-			} else {
-				DBG_88E("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
-				status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-			}
-
-			DBG_88E("[%s] status_code = %d\n", __func__, status_code);
-
-			pwdinfo->inviteresp_info.token = frame_body[7];
-			issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
-		}
-		break;
-	case P2P_INVIT_RESP: {
-		u8	attr_content = 0x00;
-		u32	attr_contentlen = 0;
-
-		DBG_88E("[%s] Got invite response frame!\n", __func__);
-		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-		p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
-		if (p2p_ie) {
-			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-
-			if (attr_contentlen == 1) {
-				DBG_88E("[%s] Status = %d\n", __func__, attr_content);
-				pwdinfo->invitereq_info.benable = false;
-
-				if (attr_content == P2P_STATUS_SUCCESS) {
-					if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-					} else {
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-					}
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
-				} else {
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-				}
-			} else {
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-			}
-		} else {
-			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-		}
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
-			_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
-		break;
-	}
-	case P2P_DEVDISC_REQ:
-		process_p2p_devdisc_req(pwdinfo, pframe, len);
-		break;
-	case P2P_DEVDISC_RESP:
-		process_p2p_devdisc_resp(pwdinfo, pframe, len);
-		break;
-	case P2P_PROVISION_DISC_REQ:
-		DBG_88E("[%s] Got Provisioning Discovery Request Frame\n", __func__);
-		process_p2p_provdisc_req(pwdinfo, pframe, len);
-		memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
-
-		/* 20110902 Kurt */
-		/* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
-			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
-		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
-		break;
-	case P2P_PROVISION_DISC_RESP:
-		/*	Commented by Albert 20110707 */
-		/*	Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
-		DBG_88E("[%s] Got Provisioning Discovery Response Frame\n", __func__);
-		/*	Commented by Albert 20110426 */
-		/*	The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
-		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
-		process_p2p_provdisc_resp(pwdinfo, pframe);
-		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
-		break;
-	}
-#endif /* CONFIG_88EU_P2P */
-
 	return _SUCCESS;
 }
 
@@ -4251,46 +1797,6 @@ unsigned int OnAction_wmm(struct adapter
 
 unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame)
 {
-#ifdef CONFIG_88EU_P2P
-	u8 *frame_body;
-	u8 category, OUI_Subtype;
-	u8 *pframe = precv_frame->rx_data;
-	uint len = precv_frame->len;
-	struct	wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-
-	DBG_88E("%s\n", __func__);
-
-	/* check RA matches or not */
-	if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
-		return _SUCCESS;
-
-	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
-
-	category = frame_body[0];
-	if (category != RTW_WLAN_CATEGORY_P2P)
-		return _SUCCESS;
-
-	if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
-		return _SUCCESS;
-
-	len -= sizeof(struct rtw_ieee80211_hdr_3addr);
-	OUI_Subtype = frame_body[5];
-
-	switch (OUI_Subtype) {
-	case P2P_NOTICE_OF_ABSENCE:
-		break;
-	case P2P_PRESENCE_REQUEST:
-		process_p2p_presence_req(pwdinfo, pframe, len);
-		break;
-	case P2P_PRESENCE_RESPONSE:
-		break;
-	case P2P_GO_DISC_REQUEST:
-		break;
-	default:
-		break;
-	}
-#endif /* CONFIG_88EU_P2P */
 	return _SUCCESS;
 }
 
@@ -4361,7 +1867,7 @@ void update_mgntframe_attrib(struct adap
 {
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 
-	_rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
+	memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
 
 	pattrib->hdrlen = 24;
 	pattrib->nr_frags = 1;
@@ -4464,7 +1970,7 @@ static int update_hidden_ssid(u8 *ies, u
 			break;
 		}
 		case 2:
-			_rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
+			memset(&ssid_ie[2], 0, ssid_len_ori);
 			break;
 		default:
 			break;
@@ -4488,9 +1994,6 @@ void issue_beacon(struct adapter *padapt
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex		*cur_network = &(pmlmeinfo->network);
 	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 	if (pmgntframe == NULL) {
@@ -4506,7 +2009,7 @@ void issue_beacon(struct adapter *padapt
 	update_mgntframe_attrib(padapter, pattrib);
 	pattrib->qsel = 0x10;
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -4527,108 +2030,26 @@ void issue_beacon(struct adapter *padapt
 	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
 
 	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-#ifdef CONFIG_88EU_P2P
-		/*  for P2P : Primary Device Type & Device Name */
-		u32 wpsielen = 0, insert_len = 0;
-		u8 *wpsie = NULL;
-		wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
-
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
-			uint wps_offset, remainder_ielen;
-			u8 *premainder_ie, *pframe_wscie;
-
-			wps_offset = (uint)(wpsie - cur_network->IEs);
-			premainder_ie = wpsie + wpsielen;
-			remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
-			pframe_wscie = pframe + wps_offset;
-			memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);
-			pframe += (wps_offset + wpsielen);
-			pattrib->pktlen += (wps_offset + wpsielen);
-
-			/* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
-			/*	Primary Device Type */
-			/*	Type: */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-			insert_len += 2;
-
-			/*	Length: */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
-			insert_len += 2;
-
-			/*	Value: */
-			/*	Category ID */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-			insert_len += 2;
-
-			/*	OUI */
-			*(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
-			insert_len += 4;
-
-			/*	Sub Category ID */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-			insert_len += 2;
-
-			/*	Device Name */
-			/*	Type: */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-			insert_len += 2;
-
-			/*	Length: */
-			*(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
-			insert_len += 2;
-
-			/*	Value: */
-			memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
-			insert_len += pwdinfo->device_name_len;
-
-			/* update wsc ie length */
-			*(pframe_wscie+1) = (wpsielen-2) + insert_len;
-
-			/* pframe move to end */
-			pframe += insert_len;
-			pattrib->pktlen += insert_len;
-
-			/* copy remainder_ie to pframe */
-			memcpy(pframe, premainder_ie, remainder_ielen);
-			pframe += remainder_ielen;
-			pattrib->pktlen += remainder_ielen;
-		} else
-#endif /* CONFIG_88EU_P2P */
-		{
-			int len_diff;
-			memcpy(pframe, cur_network->IEs, cur_network->IELength);
-			len_diff = update_hidden_ssid(
-				pframe+_BEACON_IE_OFFSET_
-				, cur_network->IELength-_BEACON_IE_OFFSET_
-				, pmlmeinfo->hidden_ssid_mode
+		int len_diff;
+		u8 *wps_ie;
+		uint wps_ielen;
+		u8 sr = 0;
+		memcpy(pframe, cur_network->IEs, cur_network->IELength);
+		len_diff = update_hidden_ssid(
+			pframe+_BEACON_IE_OFFSET_
+			, cur_network->IELength-_BEACON_IE_OFFSET_
+			, pmlmeinfo->hidden_ssid_mode
 			);
-			pframe += (cur_network->IELength+len_diff);
-			pattrib->pktlen += (cur_network->IELength+len_diff);
-		}
-
-		{
-			u8 *wps_ie;
-			uint wps_ielen;
-			u8 sr = 0;
-			wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
-				pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
-			if (wps_ie && wps_ielen > 0)
-				rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
-			if (sr != 0)
-				set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
-			else
-				_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
-		}
-
-#ifdef CONFIG_88EU_P2P
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			u32 len;
-			len = build_beacon_p2p_ie(pwdinfo, pframe);
-
-			pframe += len;
-			pattrib->pktlen += len;
-		}
-#endif /* CONFIG_88EU_P2P */
+		pframe += (cur_network->IELength+len_diff);
+		pattrib->pktlen += (cur_network->IELength+len_diff);
+		wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
+			pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
+		if (wps_ie && wps_ielen > 0)
+			rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
+		if (sr != 0)
+			set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
+		else
+			_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
 
 		goto _issue_bcn;
 	}
@@ -4718,9 +2139,6 @@ void issue_probersp(struct adapter *pada
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex		*cur_network = &(pmlmeinfo->network);
 	unsigned int	rate_len;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 	if (pmgntframe == NULL) {
@@ -4732,7 +2150,7 @@ void issue_probersp(struct adapter *pada
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -4845,16 +2263,6 @@ void issue_probersp(struct adapter *pada
 		/* todo:HT for adhoc */
 	}
 
-#ifdef CONFIG_88EU_P2P
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
-		u32 len;
-		len = build_probe_resp_p2p_ie(pwdinfo, pframe);
-
-		pframe += len;
-		pattrib->pktlen += len;
-	}
-#endif /* CONFIG_88EU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe(padapter, pmgntframe);
@@ -4889,7 +2297,7 @@ static int _issue_probereq(struct adapte
 	update_mgntframe_attrib(padapter, pattrib);
 
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5025,7 +2433,7 @@ void issue_auth(struct adapter *padapter
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5154,9 +2562,6 @@ void issue_asocrsp(struct adapter *padap
 	struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
 	u8 *ie = pnetwork->IEs;
 	__le16 lestatus, leval;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	DBG_88E("%s\n", __func__);
 
@@ -5169,7 +2574,7 @@ void issue_asocrsp(struct adapter *padap
 	update_mgntframe_attrib(padapter, pattrib);
 
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5261,16 +2666,6 @@ void issue_asocrsp(struct adapter *padap
 		pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
 	}
 
-#ifdef CONFIG_88EU_P2P
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
-		u32 len;
-
-		len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
-
-		pframe += len;
-		pattrib->pktlen += len;
-	}
-#endif /* CONFIG_88EU_P2P */
 	pattrib->last_txcmdsz = pattrib->pktlen;
 	dump_mgntframe(padapter, pmgntframe);
 #endif
@@ -5294,11 +2689,6 @@ void issue_assocreq(struct adapter *pada
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	int	bssrate_len = 0, sta_bssrate_len = 0;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8 p2pie[255] = { 0x00 };
-	u16 p2pielen = 0;
-#endif /* CONFIG_88EU_P2P */
 
 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 	if (pmgntframe == NULL)
@@ -5308,7 +2698,7 @@ void issue_assocreq(struct adapter *pada
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 
@@ -5465,137 +2855,6 @@ void issue_assocreq(struct adapter *pada
 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
 		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
 
-#ifdef CONFIG_88EU_P2P
-
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
-		/*	Should add the P2P IE in the association request frame. */
-		/*	P2P OUI */
-
-		p2pielen = 0;
-		p2pie[p2pielen++] = 0x50;
-		p2pie[p2pielen++] = 0x6F;
-		p2pie[p2pielen++] = 0x9A;
-		p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-		/*	Commented by Albert 20101109 */
-		/*	According to the P2P Specification, the association request frame should contain 3 P2P attributes */
-		/*	1. P2P Capability */
-		/*	2. Extended Listen Timing */
-		/*	3. Device Info */
-		/*	Commented by Albert 20110516 */
-		/*	4. P2P Interface */
-
-		/*	P2P Capability */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Device Capability Bitmap, 1 byte */
-		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-		/*	Group Capability Bitmap, 1 byte */
-		if (pwdinfo->persistent_supported)
-			p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-		else
-			p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-
-		/*	Extended Listen Timing */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Availability Period */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-		p2pielen += 2;
-
-		/*	Availability Interval */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-		p2pielen += 2;
-
-		/*	Device Info */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-		/*	Length: */
-		/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-		/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	P2P Device Address */
-		memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		/*	Config Method */
-		/*	This field should be big endian. Noted by P2P specification. */
-		if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
-		    (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
-			*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
-		else
-			*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
-
-		p2pielen += 2;
-
-		/*	Primary Device Type */
-		/*	Category ID */
-		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-		p2pielen += 2;
-
-		/*	OUI */
-		*(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-		p2pielen += 4;
-
-		/*	Sub Category ID */
-		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-		p2pielen += 2;
-
-		/*	Number of Secondary Device Types */
-		p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-		/*	Device Name */
-		/*	Type: */
-		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-		p2pielen += 2;
-
-		/*	Length: */
-		*(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-		p2pielen += 2;
-
-		/*	Value: */
-		memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-		p2pielen += pwdinfo->device_name_len;
-
-		/*	P2P Interface */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
-
-		/*	Length: */
-		*(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
-		p2pielen += 2;
-
-		/*	Value: */
-		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);	/*	P2P Device Address */
-		p2pielen += ETH_ALEN;
-
-		p2pie[p2pielen++] = 1;	/*	P2P Interface Address Count */
-
-		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);	/*	P2P Interface Address List */
-		p2pielen += ETH_ALEN;
-
-		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
-	}
-
-#endif /* CONFIG_88EU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 	dump_mgntframe(padapter, pmgntframe);
 
@@ -5639,7 +2898,7 @@ static int _issue_nulldata(struct adapte
 	update_mgntframe_attrib(padapter, pattrib);
 	pattrib->retry_ctrl = false;
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5755,7 +3014,7 @@ static int _issue_qos_nulldata(struct ad
 	pattrib->ack_policy = 0;
 	pattrib->mdata = 0;
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5860,16 +3119,6 @@ static int _issue_deauth(struct adapter
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	int ret = _FAIL;
 	__le16 le_tmp;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
-
-#ifdef CONFIG_88EU_P2P
-	if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
-		_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
-		_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
-	}
-#endif /* CONFIG_88EU_P2P */
 
 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 	if (pmgntframe == NULL)
@@ -5880,7 +3129,7 @@ static int _issue_deauth(struct adapter
 	update_mgntframe_attrib(padapter, pattrib);
 	pattrib->retry_ctrl = false;
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -5982,7 +3231,7 @@ void issue_action_spct_ch_switch (struct
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -6052,7 +3301,7 @@ void issue_action_BA(struct adapter *pad
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -6194,7 +3443,7 @@ static void issue_action_BSSCoexistPacke
 	pattrib = &pmgntframe->attrib;
 	update_mgntframe_attrib(padapter, pattrib);
 
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
@@ -6228,7 +3477,7 @@ static void issue_action_BSSCoexistPacke
 
 
 	/*  */
-	_rtw_memset(ICS, 0, sizeof(ICS));
+	memset(ICS, 0, sizeof(ICS));
 	if (pmlmepriv->num_sta_no_ht > 0) {
 		int i;
 
@@ -6237,14 +3486,11 @@ static void issue_action_BSSCoexistPacke
 		phead = get_list_head(queue);
 		plist = phead->next;
 
-		while (1) {
+		while (phead != plist) {
 			int len;
 			u8 *p;
 			struct wlan_bssid_ex *pbss_network;
 
-			if (rtw_end_of_queue_search(phead, plist))
-				break;
-
 			pnetwork = container_of(plist, struct wlan_network, list);
 
 			plist = plist->next;
@@ -6379,38 +3625,15 @@ void site_survey(struct adapter *padapte
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	u32 initialgain = 0;
+	struct rtw_ieee80211_channel *ch;
 
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
-		if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
-			survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
-		} else {
-			survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
-		}
-		ScanType = SCAN_ACTIVE;
-	} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
-		/*	Commented by Albert 2011/06/03 */
-		/*	The driver is in the find phase, it should go through the social channel. */
-		int ch_set_idx;
-		survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
-		ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
-		if (ch_set_idx >= 0)
-			ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
-		else
-			ScanType = SCAN_ACTIVE;
-	} else
-#endif /* CONFIG_88EU_P2P */
-	{
-		struct rtw_ieee80211_channel *ch;
-		if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
-			ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
-			survey_channel = ch->hw_value;
-			ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
-		}
+	if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
+		ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
+		survey_channel = ch->hw_value;
+		ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
 	}
 
+
 	if (survey_channel != 0) {
 		/* PAUSE 4-AC Queue when site_survey */
 		/* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
@@ -6422,118 +3645,78 @@ void site_survey(struct adapter *padapte
 			SelectChannel(padapter, survey_channel);
 
 		if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
-			#ifdef CONFIG_88EU_P2P
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
-			    rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
-				issue_probereq_p2p(padapter, NULL);
-				issue_probereq_p2p(padapter, NULL);
-				issue_probereq_p2p(padapter, NULL);
-			} else
-			#endif /* CONFIG_88EU_P2P */
-			{
-				int i;
-				for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
-					if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
-						/* todo: to issue two probe req??? */
-						issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
-						/* msleep(SURVEY_TO>>1); */
-						issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
-					}
-				}
-
-				if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+			int i;
+			for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+				if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
 					/* todo: to issue two probe req??? */
-					issue_probereq(padapter, NULL, NULL);
+					issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
 					/* msleep(SURVEY_TO>>1); */
-					issue_probereq(padapter, NULL, NULL);
+					issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
 				}
 			}
-		}
 
-		set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
-	} else {
-		/*	channel number is 0 or this channel is not valid. */
+			if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+				/* todo: to issue two probe req??? */
+				issue_probereq(padapter, NULL, NULL);
+				/* msleep(SURVEY_TO>>1); */
+				issue_probereq(padapter, NULL, NULL);
+			}
 
-#ifdef CONFIG_88EU_P2P
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
-			if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
-				/*	Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
-				/*	This will let the following flow to run the scanning end. */
-				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
+			if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+				/* todo: to issue two probe req??? */
+				issue_probereq(padapter, NULL, NULL);
+				/* msleep(SURVEY_TO>>1); */
+				issue_probereq(padapter, NULL, NULL);
 			}
 		}
 
-		if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
-			/*	Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
-			set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
-			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-
-			initialgain = 0xff; /* restore RX GAIN */
-			rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-			/* turn on dynamic functions */
-			Restore_DM_Func_Flag(padapter);
-			/* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
+		set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+	} else {
 
-			_set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
-		} else
-#endif /* CONFIG_88EU_P2P */
-		{
-			/*  20100721:Interrupt scan operation here. */
-			/*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
-			/*  It compares the scan result and select better one to do connection. */
-			if (rtw_hal_antdiv_before_linked(padapter)) {
-				pmlmeext->sitesurvey_res.bss_cnt = 0;
-				pmlmeext->sitesurvey_res.channel_idx = -1;
-				pmlmeext->chan_scan_time = SURVEY_TO / 2;
-				set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
-				return;
-			}
-#ifdef CONFIG_88EU_P2P
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
-				rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
-#endif /* CONFIG_88EU_P2P */
+		/*  20100721:Interrupt scan operation here. */
+		/*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
+		/*  It compares the scan result and select better one to do connection. */
+		if (rtw_hal_antdiv_before_linked(padapter)) {
+			pmlmeext->sitesurvey_res.bss_cnt = 0;
+			pmlmeext->sitesurvey_res.channel_idx = -1;
+			pmlmeext->chan_scan_time = SURVEY_TO / 2;
+			set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+			return;
+		}
 
-			pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
+		pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
 
-			/* switch back to the original channel */
+		/* switch back to the original channel */
 
-#ifdef CONFIG_88EU_P2P
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
-				set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-			else
-				set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-#endif /* CONFIG_88EU_P2P */
+		set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 
-			/* flush 4-AC Queue after site_survey */
-			/* val8 = 0; */
-			/* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+		/* flush 4-AC Queue after site_survey */
+		/* val8 = 0; */
+		/* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
 
-			/* config MSR */
-			Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+		/* config MSR */
+		Set_MSR(padapter, (pmlmeinfo->state & 0x3));
 
-			initialgain = 0xff; /* restore RX GAIN */
-			rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-			/* turn on dynamic functions */
-			Restore_DM_Func_Flag(padapter);
-			/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
+		initialgain = 0xff; /* restore RX GAIN */
+		rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+		/* turn on dynamic functions */
+		Restore_DM_Func_Flag(padapter);
+		/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
 
-			if (is_client_associated_to_ap(padapter))
-				issue_nulldata(padapter, NULL, 0, 3, 500);
+		if (is_client_associated_to_ap(padapter))
+			issue_nulldata(padapter, NULL, 0, 3, 500);
 
-			val8 = 0; /* survey done */
-			rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+		val8 = 0; /* survey done */
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
 
-			report_surveydone_event(padapter);
+		report_surveydone_event(padapter);
 
-			pmlmeext->chan_scan_time = SURVEY_TO;
-			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+		pmlmeext->chan_scan_time = SURVEY_TO;
+		pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
 
-			issue_action_BSSCoexistPacket(padapter);
-			issue_action_BSSCoexistPacket(padapter);
-			issue_action_BSSCoexistPacket(padapter);
-		}
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
 	}
 	return;
 }
@@ -6557,7 +3740,7 @@ u8 collect_bss_info(struct adapter *pada
 	if (len > MAX_IE_SZ)
 		return _FAIL;
 
-	_rtw_memset(bssid, 0, sizeof(struct wlan_bssid_ex));
+	memset(bssid, 0, sizeof(struct wlan_bssid_ex));
 
 	subtype = GetFrameSubType(pframe);
 
@@ -6608,7 +3791,7 @@ u8 collect_bss_info(struct adapter *pada
 		bssid->Ssid.SsidLength = 0;
 	}
 
-	_rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+	memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
 	/* checking rate info... */
 	i = 0;
@@ -6816,7 +3999,7 @@ void start_clnt_auth(struct adapter *pad
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	_cancel_timer_ex(&pmlmeext->link_timer);
+	del_timer_sync(&pmlmeext->link_timer);
 
 	pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
 	pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
@@ -6847,7 +4030,7 @@ void start_clnt_assoc(struct adapter *pa
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	_cancel_timer_ex(&pmlmeext->link_timer);
+	del_timer_sync(&pmlmeext->link_timer);
 
 	pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
 	pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
@@ -6912,7 +4095,7 @@ static void process_80211d(struct adapte
 		p = ie;
 		ie += len;
 
-		_rtw_memset(country, 0, 4);
+		memset(country, 0, 4);
 		memcpy(country, p, 3);
 		p += 3;
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
@@ -6937,7 +4120,7 @@ static void process_80211d(struct adapte
 
 		memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
 
-		_rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
+		memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
 		chplan_new = pmlmeext->channel_set;
 
 		i = 0;
@@ -7058,18 +4241,18 @@ void report_survey_event(struct adapter
 	pcmdpriv = &padapter->cmdpriv;
 
 
-	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd_obj == NULL)
 		return;
 
 	cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
-	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
 	if (pevtcmd == NULL) {
 		kfree(pcmd_obj);
 		return;
 	}
 
-	_rtw_init_listhead(&pcmd_obj->list);
+	INIT_LIST_HEAD(&pcmd_obj->list);
 
 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
 	pcmd_obj->cmdsz = cmdsz;
@@ -7110,18 +4293,18 @@ void report_surveydone_event(struct adap
 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd_obj == NULL)
 		return;
 
 	cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
-	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
 	if (pevtcmd == NULL) {
 		kfree(pcmd_obj);
 		return;
 	}
 
-	_rtw_init_listhead(&pcmd_obj->list);
+	INIT_LIST_HEAD(&pcmd_obj->list);
 
 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
 	pcmd_obj->cmdsz = cmdsz;
@@ -7156,18 +4339,18 @@ void report_join_res(struct adapter *pad
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd_obj == NULL)
 		return;
 
 	cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
-	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
 	if (pevtcmd == NULL) {
 		kfree(pcmd_obj);
 		return;
 	}
 
-	_rtw_init_listhead(&pcmd_obj->list);
+	INIT_LIST_HEAD(&pcmd_obj->list);
 
 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
 	pcmd_obj->cmdsz = cmdsz;
@@ -7209,18 +4392,18 @@ void report_del_sta_event(struct adapter
 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd_obj == NULL)
 		return;
 
 	cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
-	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
 	if (pevtcmd == NULL) {
 		kfree(pcmd_obj);
 		return;
 	}
 
-	_rtw_init_listhead(&pcmd_obj->list);
+	INIT_LIST_HEAD(&pcmd_obj->list);
 
 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
 	pcmd_obj->cmdsz = cmdsz;
@@ -7264,18 +4447,18 @@ void report_add_sta_event(struct adapter
 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (pcmd_obj == NULL)
 		return;
 
 	cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
-	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
 	if (pevtcmd == NULL) {
 		kfree(pcmd_obj);
 		return;
 	}
 
-	_rtw_init_listhead(&pcmd_obj->list);
+	INIT_LIST_HEAD(&pcmd_obj->list);
 
 	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
 	pcmd_obj->cmdsz = cmdsz;
@@ -7494,7 +4677,7 @@ void mlmeext_sta_del_event_callback(stru
 		/* set MSR to no link state -> infra. mode */
 		Set_MSR(padapter, _HW_STATE_STATION_);
 
-		_cancel_timer_ex(&pmlmeext->link_timer);
+		del_timer_sync(&pmlmeext->link_timer);
 	}
 }
 
@@ -7549,8 +4732,6 @@ void linked_status_chk(struct adapter *p
 	if (padapter->bRxRSSIDisplay)
 		_linked_rx_signal_strehgth_display(padapter);
 
-	rtw_hal_sreset_linked_status_check(padapter);
-
 	if (is_client_associated_to_ap(padapter)) {
 		/* linked infrastructure client mode */
 
@@ -7561,9 +4742,6 @@ void linked_status_chk(struct adapter *p
 		psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
 		if (psta != NULL) {
 			bool is_p2p_enable = false;
-			#ifdef CONFIG_88EU_P2P
-			is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
-			#endif
 
 			if (!chk_ap_is_alive(padapter, psta))
 				rx_chk = _FAIL;
@@ -7655,15 +4833,13 @@ void linked_status_chk(struct adapter *p
 	}
 }
 
-void survey_timer_hdl(struct adapter *padapter)
+void survey_timer_hdl(void *function_context)
 {
+	struct adapter *padapter = (struct adapter *)function_context;
 	struct cmd_obj	*ph2c;
 	struct sitesurvey_parm	*psurveyPara;
 	struct cmd_priv					*pcmdpriv = &padapter->cmdpriv;
 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-#endif
 
 	/* issue rtw_sitesurvey_cmd */
 	if (pmlmeext->sitesurvey_res.state > SCAN_START) {
@@ -7671,31 +4847,18 @@ void survey_timer_hdl(struct adapter *pa
 			pmlmeext->sitesurvey_res.channel_idx++;
 
 		if (pmlmeext->scan_abort) {
-			#ifdef CONFIG_88EU_P2P
-			if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
-				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
-				pmlmeext->sitesurvey_res.channel_idx = 3;
-				DBG_88E("%s idx:%d, cnt:%u\n", __func__
-					, pmlmeext->sitesurvey_res.channel_idx
-					, pwdinfo->find_phase_state_exchange_cnt
-			);
-			} else
-			#endif
-			{
-				pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
-				DBG_88E("%s idx:%d\n", __func__
-					, pmlmeext->sitesurvey_res.channel_idx
-			);
-			}
+			pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
+			DBG_88E("%s idx:%d\n", __func__
+				, pmlmeext->sitesurvey_res.channel_idx);
 
 			pmlmeext->scan_abort = false;/* reset */
 		}
 
-		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 		if (ph2c == NULL)
 			goto exit_survey_timer_hdl;
 
-		psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
+		psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL);
 		if (psurveyPara == NULL) {
 			kfree(ph2c);
 			goto exit_survey_timer_hdl;
@@ -7710,8 +4873,9 @@ exit_survey_timer_hdl:
 	return;
 }
 
-void link_timer_hdl(struct adapter *padapter)
+void link_timer_hdl(void *function_context)
 {
+	struct adapter *padapter = (struct adapter *)function_context;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
@@ -7746,8 +4910,9 @@ void link_timer_hdl(struct adapter *pada
 	return;
 }
 
-void addba_timer_hdl(struct sta_info *psta)
+void addba_timer_hdl(void *function_context)
 {
+	struct sta_info *psta = (struct sta_info *)function_context;
 	struct ht_priv	*phtpriv;
 
 	if (!psta)
@@ -7797,11 +4962,11 @@ u8 createbss_hdl(struct adapter *padapte
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-	struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
+	struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
 	/* u32	initialgain; */
 
 
-	if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
+	if (pparm->InfrastructureMode == Ndis802_11APMode) {
 #ifdef CONFIG_88EU_AP_MODE
 
 		if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
@@ -7812,7 +4977,7 @@ u8 createbss_hdl(struct adapter *padapte
 	}
 
 	/* below is for ad-hoc master */
-	if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
+	if (pparm->InfrastructureMode == Ndis802_11IBSS) {
 		rtw_joinbss_reset(padapter);
 
 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
@@ -7834,7 +4999,7 @@ u8 createbss_hdl(struct adapter *padapte
 		/* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
 
 		/* cancel link timer */
-		_cancel_timer_ex(&pmlmeext->link_timer);
+		del_timer_sync(&pmlmeext->link_timer);
 
 		/* clear CAM */
 		flush_all_cam_entry(padapter);
@@ -7861,7 +5026,7 @@ u8 join_cmd_hdl(struct adapter *padapter
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-	struct joinbss_parm	*pparm = (struct joinbss_parm *)pbuf;
+	struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
 	u32 i;
 
 	/* check already connecting to AP or not */
@@ -7874,7 +5039,7 @@ u8 join_cmd_hdl(struct adapter *padapter
 		/* clear CAM */
 		flush_all_cam_entry(padapter);
 
-		_cancel_timer_ex(&pmlmeext->link_timer);
+		del_timer_sync(&pmlmeext->link_timer);
 
 		/* set MSR to nolink -> infra. mode */
 		Set_MSR(padapter, _HW_STATE_STATION_);
@@ -7883,7 +5048,7 @@ u8 join_cmd_hdl(struct adapter *padapter
 		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
 	}
 
-	rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
+	rtw_antenna_select_cmd(padapter, pparm->PhyInfo.Optimum_antenna, false);
 
 	rtw_joinbss_reset(padapter);
 
@@ -7960,7 +5125,7 @@ u8 join_cmd_hdl(struct adapter *padapter
 	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
 
 	/* cancel link timer */
-	_cancel_timer_ex(&pmlmeext->link_timer);
+	del_timer_sync(&pmlmeext->link_timer);
 
 	start_clnt_join(padapter);
 
@@ -8004,7 +5169,7 @@ u8 disconnect_hdl(struct adapter *padapt
 
 	flush_all_cam_entry(padapter);
 
-	_cancel_timer_ex(&pmlmeext->link_timer);
+	del_timer_sync(&pmlmeext->link_timer);
 
 	rtw_free_uc_swdec_pending_queue(padapter);
 
@@ -8019,7 +5184,7 @@ static int rtw_scan_ch_decision(struct a
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 
 	/* clear out first */
-	_rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
+	memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
 
 	/* acquire channels from in */
 	j = 0;
@@ -8062,10 +5227,6 @@ u8 sitesurvey_cmd_hdl(struct adapter *pa
 	u32	initialgain;
 	u32	i;
 
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif
-
 	if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
 		/* for first time sitesurvey_cmd */
 		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
@@ -8111,14 +5272,7 @@ u8 sitesurvey_cmd_hdl(struct adapter *pa
 		Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
 
 		/* config the initial gain under scanning, need to write the BB registers */
-#ifdef CONFIG_88EU_P2P
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-			initialgain = 0x1E;
-		else
-			initialgain = 0x28;
-#else	/*  CONFIG_88EU_P2P */
 		initialgain = 0x1E;
-#endif /*  CONFIG_88EU_P2P */
 
 		rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
 
@@ -8265,7 +5419,7 @@ u8 add_ba_hdl(struct adapter *padapter,
 u8 set_tx_beacon_cmd(struct adapter *padapter)
 {
 	struct cmd_obj	*ph2c;
-	struct Tx_Beacon_param	*ptxBeacon_parm;
+	struct wlan_bssid_ex	*ptxBeacon_parm;
 	struct cmd_priv	*pcmdpriv = &(padapter->cmdpriv);
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -8273,25 +5427,25 @@ u8 set_tx_beacon_cmd(struct adapter *pad
 	int len_diff = 0;
 
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
+	ptxBeacon_parm = kzalloc(sizeof(struct wlan_bssid_ex), GFP_KERNEL);
 	if (ptxBeacon_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
 		goto exit;
 	}
 
-	memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
+	memcpy(ptxBeacon_parm, &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
 
-	len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
-				      ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
+	len_diff = update_hidden_ssid(ptxBeacon_parm->IEs+_BEACON_IE_OFFSET_,
+				      ptxBeacon_parm->IELength-_BEACON_IE_OFFSET_,
 				      pmlmeinfo->hidden_ssid_mode);
-	ptxBeacon_parm->network.IELength += len_diff;
+	ptxBeacon_parm->IELength += len_diff;
 
 	init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
 
@@ -8310,7 +5464,6 @@ u8 mlme_evt_hdl(struct adapter *padapter
 	u16 evt_sz;
 	uint	*peventbuf;
 	void (*event_callback)(struct adapter *dev, u8 *pbuf);
-	struct evt_priv *pevt_priv = &(padapter->evtpriv);
 
 	peventbuf = (uint *)pbuf;
 	evt_sz = (u16)(*peventbuf&0xffff);
@@ -8331,29 +5484,18 @@ u8 mlme_evt_hdl(struct adapter *padapter
 		goto _abort_event_;
 	}
 
-	atomic_inc(&pevt_priv->event_seq);
-
 	peventbuf += 2;
 
 	if (peventbuf) {
 		event_callback = wlanevents[evt_code].event_callback;
 		event_callback(padapter, (u8 *)peventbuf);
 
-		pevt_priv->evt_done_cnt++;
 	}
 
 _abort_event_:
 	return H2C_SUCCESS;
 }
 
-u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
-	if (!pbuf)
-		return H2C_PARAMETERS_ERROR;
-
-	return H2C_SUCCESS;
-}
-
 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
 {
 	if (send_beacon(padapter) == _FAIL) {
@@ -8379,12 +5521,12 @@ u8 tx_beacon_hdl(struct adapter *padapte
 			xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
 			xmitframe_plist = xmitframe_phead->next;
 
-			while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+			while (xmitframe_phead != xmitframe_plist) {
 				pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 				xmitframe_plist = xmitframe_plist->next;
 
-				rtw_list_delete(&pxmitframe->list);
+				list_del_init(&pxmitframe->list);
 
 				psta_bmc->sleepq_len--;
 				if (psta_bmc->sleepq_len > 0)
@@ -8446,33 +5588,3 @@ u8 set_chplan_hdl(struct adapter *padapt
 
 	return	H2C_SUCCESS;
 }
-
-u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
-	if (!pbuf)
-		return H2C_PARAMETERS_ERROR;
-	return	H2C_SUCCESS;
-}
-
-u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
-	return	H2C_REJECTED;
-}
-
-/*  TDLS_WRCR		: write RCR DATA BIT */
-/*  TDLS_SD_PTI		: issue peer traffic indication */
-/*  TDLS_CS_OFF		: go back to the channel linked with AP, terminating channel switch procedure */
-/*  TDLS_INIT_CH_SEN	: init channel sensing, receive all data and mgnt frame */
-/*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
-/*  TDLS_OFF_CH		: first time set channel to off channel */
-/*  TDLS_BASE_CH		: go back tp the channel linked with AP when set base channel as target channel */
-/*  TDLS_P_OFF_CH	: periodically go to off channel */
-/*  TDLS_P_BASE_CH	: periodically go back to base channel */
-/*  TDLS_RS_RCR		: restore RCR */
-/*  TDLS_CKALV_PH1	: check alive timer phase1 */
-/*  TDLS_CKALV_PH2	: check alive timer phase2 */
-/*  TDLS_FREE_STA	: free tdls sta */
-u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
-	return H2C_REJECTED;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mp.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mp.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,995 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- *published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTW_MP_C_
-
-#include <drv_types.h>
-
-#include "rtl8188e_hal.h"
-#include <linux/vmalloc.h>
-
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
-{
-	u32 val = 0;
-
-	switch (sz) {
-	case 1:
-		val = rtw_read8(padapter, addr);
-		break;
-	case 2:
-		val = rtw_read16(padapter, addr);
-		break;
-	case 4:
-		val = rtw_read32(padapter, addr);
-		break;
-	default:
-		val = 0xffffffff;
-		break;
-	}
-
-	return val;
-}
-
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz)
-{
-	switch (sz) {
-	case 1:
-		rtw_write8(padapter, addr, (u8)val);
-		break;
-	case 2:
-		rtw_write16(padapter, addr, (u16)val);
-		break;
-	case 4:
-		rtw_write32(padapter, addr, val);
-		break;
-	default:
-		break;
-	}
-}
-
-u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask)
-{
-	return rtw_hal_read_bbreg(padapter, addr, bitmask);
-}
-
-void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val)
-{
-	rtw_hal_write_bbreg(padapter, addr, bitmask, val);
-}
-
-u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask)
-{
-	return rtw_hal_read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask);
-}
-
-void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val)
-{
-	rtw_hal_write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask, val);
-}
-
-u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr)
-{
-	return _read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask);
-}
-
-void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val)
-{
-	_write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask, val);
-}
-
-static void _init_mp_priv_(struct mp_priv *pmp_priv)
-{
-	struct wlan_bssid_ex *pnetwork;
-
-	_rtw_memset(pmp_priv, 0, sizeof(struct mp_priv));
-
-	pmp_priv->mode = MP_OFF;
-
-	pmp_priv->channel = 1;
-	pmp_priv->bandwidth = HT_CHANNEL_WIDTH_20;
-	pmp_priv->prime_channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-	pmp_priv->rateidx = MPT_RATE_1M;
-	pmp_priv->txpoweridx = 0x2A;
-
-	pmp_priv->antenna_tx = ANTENNA_A;
-	pmp_priv->antenna_rx = ANTENNA_AB;
-
-	pmp_priv->check_mp_pkt = 0;
-
-	pmp_priv->tx_pktcount = 0;
-
-	pmp_priv->rx_pktcount = 0;
-	pmp_priv->rx_crcerrpktcount = 0;
-
-	pmp_priv->network_macaddr[0] = 0x00;
-	pmp_priv->network_macaddr[1] = 0xE0;
-	pmp_priv->network_macaddr[2] = 0x4C;
-	pmp_priv->network_macaddr[3] = 0x87;
-	pmp_priv->network_macaddr[4] = 0x66;
-	pmp_priv->network_macaddr[5] = 0x55;
-
-	pnetwork = &pmp_priv->mp_network.network;
-	memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN);
-
-	pnetwork->Ssid.SsidLength = 8;
-	memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength);
-}
-
-static void mp_init_xmit_attrib(struct mp_tx *pmptx, struct adapter *padapter)
-{
-	struct pkt_attrib *pattrib;
-	struct tx_desc *desc;
-
-	/*  init xmitframe attribute */
-	pattrib = &pmptx->attrib;
-	_rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
-	desc = &pmptx->desc;
-	_rtw_memset(desc, 0, TXDESC_SIZE);
-
-	pattrib->ether_type = 0x8712;
-	_rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
-	pattrib->ack_policy = 0;
-	pattrib->hdrlen = WLAN_HDR_A3_LEN;
-	pattrib->subtype = WIFI_DATA;
-	pattrib->priority = 0;
-	pattrib->qsel = pattrib->priority;
-	pattrib->nr_frags = 1;
-	pattrib->encrypt = 0;
-	pattrib->bswenc = false;
-	pattrib->qos_en = false;
-}
-
-s32 init_mp_priv(struct adapter *padapter)
-{
-	struct mp_priv *pmppriv = &padapter->mppriv;
-
-	_init_mp_priv_(pmppriv);
-	pmppriv->papdater = padapter;
-
-	pmppriv->tx.stop = 1;
-	mp_init_xmit_attrib(&pmppriv->tx, padapter);
-
-	switch (padapter->registrypriv.rf_config) {
-	case RF_1T1R:
-		pmppriv->antenna_tx = ANTENNA_A;
-		pmppriv->antenna_rx = ANTENNA_A;
-		break;
-	case RF_1T2R:
-	default:
-		pmppriv->antenna_tx = ANTENNA_A;
-		pmppriv->antenna_rx = ANTENNA_AB;
-		break;
-	case RF_2T2R:
-	case RF_2T2R_GREEN:
-		pmppriv->antenna_tx = ANTENNA_AB;
-		pmppriv->antenna_rx = ANTENNA_AB;
-		break;
-	case RF_2T4R:
-		pmppriv->antenna_tx = ANTENNA_AB;
-		pmppriv->antenna_rx = ANTENNA_ABCD;
-		break;
-	}
-
-	return _SUCCESS;
-}
-
-void free_mp_priv(struct mp_priv *pmp_priv)
-{
-	kfree(pmp_priv->pallocated_mp_xmitframe_buf);
-	pmp_priv->pallocated_mp_xmitframe_buf = NULL;
-	pmp_priv->pmp_xmtframe_buf = NULL;
-}
-
-#define PHY_IQCalibrate(a, b)	PHY_IQCalibrate_8188E(a, b)
-#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8188E(a)
-#define PHY_SetRFPathSwitch(a, b) PHY_SetRFPathSwitch_8188E(a, b)
-
-s32 MPT_InitializeAdapter(struct adapter *pAdapter, u8 Channel)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-	s32		rtStatus = _SUCCESS;
-	struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
-	struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv;
-
-	/*  HW Initialization for 8190 MPT. */
-	/*  SW Initialization for 8190 MP. */
-	pMptCtx->bMptDrvUnload = false;
-	pMptCtx->bMassProdTest = false;
-	pMptCtx->bMptIndexEven = true;	/* default gain index is -6.0db */
-	pMptCtx->h2cReqNum = 0x0;
-	/* Init mpt event. */
-	/* init for BT MP */
-
-	pMptCtx->bMptWorkItemInProgress = false;
-	pMptCtx->CurrMptAct = NULL;
-	/*  */
-
-	/*  Don't accept any packets */
-	rtw_write32(pAdapter, REG_RCR, 0);
-
-	PHY_IQCalibrate(pAdapter, false);
-	dm_CheckTXPowerTracking(&pHalData->odmpriv);	/* trigger thermal meter */
-	PHY_LCCalibrate(pAdapter);
-
-	pMptCtx->backup0xc50 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XAAGCCore1, bMaskByte0);
-	pMptCtx->backup0xc58 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XBAGCCore1, bMaskByte0);
-	pMptCtx->backup0xc30 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_RxDetector1, bMaskByte0);
-	pMptCtx->backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
-	pMptCtx->backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
-
-	/* set ant to wifi side in mp mode */
-	rtw_write16(pAdapter, 0x870, 0x300);
-	rtw_write16(pAdapter, 0x860, 0x110);
-
-	if (pAdapter->registrypriv.mp_mode == 1)
-		pmlmepriv->fw_state = WIFI_MP_STATE;
-
-	return	rtStatus;
-}
-
-/*-----------------------------------------------------------------------------
- * Function:	MPT_DeInitAdapter()
- *
- * Overview:	Extra DeInitialization for Mass Production Test.
- *
- * Input:		struct adapter *	pAdapter
- *
- * Output:		NONE
- *
- * Return:		NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	05/08/2007	MHC		Create Version 0.
- *	05/18/2007	MHC		Add normal driver MPHalt code.
- *
- *---------------------------------------------------------------------------*/
-void MPT_DeInitAdapter(struct adapter *pAdapter)
-{
-	struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
-
-	pMptCtx->bMptDrvUnload = true;
-}
-
-static u8 mpt_ProStartTest(struct adapter *padapter)
-{
-	struct mpt_context *pMptCtx = &padapter->mppriv.MptCtx;
-
-	pMptCtx->bMassProdTest = true;
-	pMptCtx->bStartContTx = false;
-	pMptCtx->bCckContTx = false;
-	pMptCtx->bOfdmContTx = false;
-	pMptCtx->bSingleCarrier = false;
-	pMptCtx->bCarrierSuppression = false;
-	pMptCtx->bSingleTone = false;
-
-	return _SUCCESS;
-}
-
-/*
- * General use
- */
-s32 SetPowerTracking(struct adapter *padapter, u8 enable)
-{
-	Hal_SetPowerTracking(padapter, enable);
-	return 0;
-}
-
-void GetPowerTracking(struct adapter *padapter, u8 *enable)
-{
-	Hal_GetPowerTracking(padapter, enable);
-}
-
-static void disable_dm(struct adapter *padapter)
-{
-	u8 v8;
-
-	/* 3 1. disable firmware dynamic mechanism */
-	/*  disable Power Training, Rate Adaptive */
-	v8 = rtw_read8(padapter, REG_BCN_CTRL);
-	v8 &= ~EN_BCN_FUNCTION;
-	rtw_write8(padapter, REG_BCN_CTRL, v8);
-
-	/* 3 2. disable driver dynamic mechanism */
-	/*  disable Dynamic Initial Gain */
-	/*  disable High Power */
-	/*  disable Power Tracking */
-	Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
-
-	/*  enable APK, LCK and IQK but disable power tracking */
-	Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, true);
-}
-
-/* This function initializes the DUT to the MP test mode */
-s32 mp_start_test(struct adapter *padapter)
-{
-	struct wlan_bssid_ex bssid;
-	struct sta_info *psta;
-	u32 length;
-	u8 val8;
-	s32 res = _SUCCESS;
-	struct mp_priv *pmppriv = &padapter->mppriv;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
-	padapter->registrypriv.mp_mode = 1;
-	pmppriv->bSetTxPower = 0;		/* for  manually set tx power */
-
-	/* 3 disable dynamic mechanism */
-	disable_dm(padapter);
-
-	/* 3 0. update mp_priv */
-
-	if (padapter->registrypriv.rf_config == RF_819X_MAX_TYPE) {
-		switch (GET_RF_TYPE(padapter)) {
-		case RF_1T1R:
-			pmppriv->antenna_tx = ANTENNA_A;
-			pmppriv->antenna_rx = ANTENNA_A;
-			break;
-		case RF_1T2R:
-		default:
-			pmppriv->antenna_tx = ANTENNA_A;
-			pmppriv->antenna_rx = ANTENNA_AB;
-			break;
-		case RF_2T2R:
-		case RF_2T2R_GREEN:
-			pmppriv->antenna_tx = ANTENNA_AB;
-			pmppriv->antenna_rx = ANTENNA_AB;
-			break;
-		case RF_2T4R:
-			pmppriv->antenna_tx = ANTENNA_AB;
-			pmppriv->antenna_rx = ANTENNA_ABCD;
-			break;
-		}
-	}
-
-	mpt_ProStartTest(padapter);
-
-	/* 3 1. initialize a new struct wlan_bssid_ex */
-/*	_rtw_memset(&bssid, 0, sizeof(struct wlan_bssid_ex)); */
-	memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
-	bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc");
-	memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_adhoc", bssid.Ssid.SsidLength);
-	bssid.InfrastructureMode = Ndis802_11IBSS;
-	bssid.NetworkTypeInUse = Ndis802_11DS;
-	bssid.IELength = 0;
-
-	length = get_wlan_bssid_ex_sz(&bssid);
-	if (length % 4)
-		bssid.Length = ((length >> 2) + 1) << 2; /* round up to multiple of 4 bytes. */
-	else
-		bssid.Length = length;
-
-	spin_lock_bh(&pmlmepriv->lock);
-
-	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
-		goto end_of_mp_start_test;
-
-	/* init mp_start_test status */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-		rtw_disassoc_cmd(padapter, 500, true);
-		rtw_indicate_disconnect(padapter);
-		rtw_free_assoc_resources(padapter, 1);
-	}
-	pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
-	if (padapter->registrypriv.mp_mode == 1)
-		pmlmepriv->fw_state = WIFI_MP_STATE;
-	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
-	/* 3 2. create a new psta for mp driver */
-	/* clear psta in the cur_network, if any */
-	psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
-	if (psta)
-		rtw_free_stainfo(padapter, psta);
-
-	psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
-	if (psta == NULL) {
-		RT_TRACE(_module_mp_, _drv_err_, ("mp_start_test: Can't alloc sta_info!\n"));
-		pmlmepriv->fw_state = pmppriv->prev_fw_state;
-		res = _FAIL;
-		goto end_of_mp_start_test;
-	}
-
-	/* 3 3. join pseudo AdHoc */
-	tgt_network->join_res = 1;
-	tgt_network->aid = 1;
-	psta->aid = 1;
-	memcpy(&tgt_network->network, &bssid, length);
-
-	rtw_indicate_connect(padapter);
-	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
-end_of_mp_start_test:
-
-	spin_unlock_bh(&pmlmepriv->lock);
-
-	if (res == _SUCCESS) {
-		/*  set MSR to WIFI_FW_ADHOC_STATE */
-		val8 = rtw_read8(padapter, MSR) & 0xFC; /*  0x0102 */
-		val8 |= WIFI_FW_ADHOC_STATE;
-		rtw_write8(padapter, MSR, val8); /*  Link in ad hoc network */
-	}
-	return res;
-}
-/*  */
-/* This function change the DUT from the MP test mode into normal mode */
-void mp_stop_test(struct adapter *padapter)
-{
-	struct mp_priv *pmppriv = &padapter->mppriv;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-	struct sta_info *psta;
-
-	if (pmppriv->mode == MP_ON) {
-		pmppriv->bSetTxPower = 0;
-		spin_lock_bh(&pmlmepriv->lock);
-		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
-			goto end_of_mp_stop_test;
-
-		/* 3 1. disconnect pseudo AdHoc */
-		rtw_indicate_disconnect(padapter);
-
-		/* 3 2. clear psta used in mp test mode. */
-		psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
-		if (psta)
-			rtw_free_stainfo(padapter, psta);
-
-		/* 3 3. return to normal state (default:station mode) */
-		pmlmepriv->fw_state = pmppriv->prev_fw_state; /*  WIFI_STATION_STATE; */
-
-		/* flush the cur_network */
-		_rtw_memset(tgt_network, 0, sizeof(struct wlan_network));
-
-		_clr_fwstate_(pmlmepriv, WIFI_MP_STATE);
-
-end_of_mp_stop_test:
-
-		spin_unlock_bh(&pmlmepriv->lock);
-	}
-}
-
-/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
-/*
- * SetChannel
- * Description
- *	Use H2C command to change channel,
- *	not only modify rf register, but also other setting need to be done.
- */
-void SetChannel(struct adapter *pAdapter)
-{
-	Hal_SetChannel(pAdapter);
-}
-
-/*
- * Notice
- *	Switch bandwitdth may change center frequency(channel)
- */
-void SetBandwidth(struct adapter *pAdapter)
-{
-	Hal_SetBandwidth(pAdapter);
-}
-
-void SetAntenna(struct adapter *pAdapter)
-{
-	Hal_SetAntenna(pAdapter);
-}
-
-void	SetAntennaPathPower(struct adapter *pAdapter)
-{
-	Hal_SetAntennaPathPower(pAdapter);
-}
-
-void SetTxPower(struct adapter *pAdapter)
-{
-	Hal_SetTxPower(pAdapter);
-	}
-
-void SetDataRate(struct adapter *pAdapter)
-{
-	Hal_SetDataRate(pAdapter);
-}
-
-void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter , bool bMain)
-{
-	PHY_SetRFPathSwitch(pAdapter, bMain);
-}
-
-s32 SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
-{
-	return Hal_SetThermalMeter(pAdapter, target_ther);
-}
-
-void GetThermalMeter(struct adapter *pAdapter, u8 *value)
-{
-	Hal_GetThermalMeter(pAdapter, value);
-}
-
-void SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
-{
-	PhySetTxPowerLevel(pAdapter);
-	Hal_SetSingleCarrierTx(pAdapter, bStart);
-}
-
-void SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
-{
-	PhySetTxPowerLevel(pAdapter);
-	Hal_SetSingleToneTx(pAdapter, bStart);
-}
-
-void SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
-{
-	PhySetTxPowerLevel(pAdapter);
-	Hal_SetCarrierSuppressionTx(pAdapter, bStart);
-}
-
-void SetContinuousTx(struct adapter *pAdapter, u8 bStart)
-{
-	PhySetTxPowerLevel(pAdapter);
-	Hal_SetContinuousTx(pAdapter, bStart);
-}
-
-
-void PhySetTxPowerLevel(struct adapter *pAdapter)
-{
-	struct mp_priv *pmp_priv = &pAdapter->mppriv;
-
-	if (pmp_priv->bSetTxPower == 0) /*  for NO manually set power index */
-		PHY_SetTxPowerLevel8188E(pAdapter, pmp_priv->channel);
-}
-
-/*  */
-static void dump_mpframe(struct adapter *padapter, struct xmit_frame *pmpframe)
-{
-	rtw_hal_mgnt_xmit(padapter, pmpframe);
-}
-
-static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
-{
-	struct xmit_frame	*pmpframe;
-	struct xmit_buf	*pxmitbuf;
-
-	pmpframe = rtw_alloc_xmitframe(pxmitpriv);
-	if (pmpframe == NULL)
-		return NULL;
-
-	pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
-	if (pxmitbuf == NULL) {
-		rtw_free_xmitframe(pxmitpriv, pmpframe);
-		return NULL;
-	}
-
-	pmpframe->frame_tag = MP_FRAMETAG;
-
-	pmpframe->pxmitbuf = pxmitbuf;
-
-	pmpframe->buf_addr = pxmitbuf->pbuf;
-
-	pxmitbuf->priv_data = pmpframe;
-
-	return pmpframe;
-}
-
-static int mp_xmit_packet_thread(void *context)
-{
-	struct xmit_frame	*pxmitframe;
-	struct mp_tx		*pmptx;
-	struct mp_priv	*pmp_priv;
-	struct xmit_priv	*pxmitpriv;
-	struct adapter *padapter;
-
-	pmp_priv = (struct mp_priv *)context;
-	pmptx = &pmp_priv->tx;
-	padapter = pmp_priv->papdater;
-	pxmitpriv = &(padapter->xmitpriv);
-
-	thread_enter("RTW_MP_THREAD");
-
-	/* DBG_88E("%s:pkTx Start\n", __func__); */
-	while (1) {
-		pxmitframe = alloc_mp_xmitframe(pxmitpriv);
-		if (pxmitframe == NULL) {
-			if (pmptx->stop ||
-			    padapter->bSurpriseRemoved ||
-			    padapter->bDriverStopped) {
-				goto exit;
-			} else {
-				msleep(1);
-				continue;
-			}
-		}
-
-		memcpy((u8 *)(pxmitframe->buf_addr+TXDESC_OFFSET), pmptx->buf, pmptx->write_size);
-		memcpy(&(pxmitframe->attrib), &(pmptx->attrib), sizeof(struct pkt_attrib));
-
-		dump_mpframe(padapter, pxmitframe);
-
-		pmptx->sended++;
-		pmp_priv->tx_pktcount++;
-
-		if (pmptx->stop ||
-		    padapter->bSurpriseRemoved ||
-		    padapter->bDriverStopped)
-			goto exit;
-		if ((pmptx->count != 0) &&
-		    (pmptx->count == pmptx->sended))
-			goto exit;
-
-		flush_signals_thread();
-	}
-
-exit:
-	kfree(pmptx->pallocated_buf);
-	pmptx->pallocated_buf = NULL;
-	pmptx->stop = 1;
-
-	complete_and_exit(NULL, 0);
-}
-
-void fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc)
-{
-	struct mp_priv *pmp_priv = &padapter->mppriv;
-	memcpy(ptxdesc, &(pmp_priv->tx.desc), TXDESC_SIZE);
-}
-
-void SetPacketTx(struct adapter *padapter)
-{
-	u8 *ptr, *pkt_start, *pkt_end;
-	u32 pkt_size;
-	struct tx_desc *desc;
-	struct rtw_ieee80211_hdr *hdr;
-	u8 payload;
-	s32 bmcast;
-	struct pkt_attrib *pattrib;
-	struct mp_priv *pmp_priv;
-
-
-	pmp_priv = &padapter->mppriv;
-	if (pmp_priv->tx.stop)
-		return;
-	pmp_priv->tx.sended = 0;
-	pmp_priv->tx.stop = 0;
-	pmp_priv->tx_pktcount = 0;
-
-	/* 3 1. update_attrib() */
-	pattrib = &pmp_priv->tx.attrib;
-	memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN);
-	memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
-	memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-	bmcast = IS_MCAST(pattrib->ra);
-	if (bmcast) {
-		pattrib->mac_id = 1;
-		pattrib->psta = rtw_get_bcmc_stainfo(padapter);
-	} else {
-		pattrib->mac_id = 0;
-		pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
-	}
-
-	pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
-
-	/* 3 2. allocate xmit buffer */
-	pkt_size = pattrib->last_txcmdsz;
-
-	kfree(pmp_priv->tx.pallocated_buf);
-	pmp_priv->tx.write_size = pkt_size;
-	pmp_priv->tx.buf_size = pkt_size + XMITBUF_ALIGN_SZ;
-	pmp_priv->tx.pallocated_buf = rtw_zmalloc(pmp_priv->tx.buf_size);
-	if (pmp_priv->tx.pallocated_buf == NULL) {
-		DBG_88E("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size);
-		return;
-	}
-	pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pmp_priv->tx.pallocated_buf), XMITBUF_ALIGN_SZ);
-	ptr = pmp_priv->tx.buf;
-
-	desc = &(pmp_priv->tx.desc);
-	_rtw_memset(desc, 0, TXDESC_SIZE);
-	pkt_start = ptr;
-	pkt_end = pkt_start + pkt_size;
-
-	/* 3 3. init TX descriptor */
-	/*  offset 0 */
-	desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
-	desc->txdw0 |= cpu_to_le32(pkt_size & 0x0000FFFF); /*  packet size */
-	desc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00FF0000); /* 32 bytes for TX Desc */
-	if (bmcast)
-		desc->txdw0 |= cpu_to_le32(BMC); /*  broadcast packet */
-
-	desc->txdw1 |= cpu_to_le32((0x01 << 26) & 0xff000000);
-	/*  offset 4 */
-		desc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x3F); /* CAM_ID(MAC_ID) */
-	desc->txdw1 |= cpu_to_le32((pattrib->qsel << QSEL_SHT) & 0x00001F00); /*  Queue Select, TID */
-
-	desc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); /*  Rate Adaptive ID */
-	/*  offset 8 */
-	/*  offset 12 */
-
-	desc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0x0fff0000);
-
-	/*  offset 16 */
-	desc->txdw4 |= cpu_to_le32(HW_SSN);
-	desc->txdw4 |= cpu_to_le32(USERATE);
-	desc->txdw4 |= cpu_to_le32(DISDATAFB);
-
-	if (pmp_priv->preamble) {
-		if (pmp_priv->rateidx <=  MPT_RATE_54M)
-			desc->txdw4 |= cpu_to_le32(DATA_SHORT); /*  CCK Short Preamble */
-	}
-	if (pmp_priv->bandwidth == HT_CHANNEL_WIDTH_40)
-		desc->txdw4 |= cpu_to_le32(DATA_BW);
-
-	/*  offset 20 */
-	desc->txdw5 |= cpu_to_le32(pmp_priv->rateidx & 0x0000001F);
-
-	if (pmp_priv->preamble) {
-		if (pmp_priv->rateidx > MPT_RATE_54M)
-			desc->txdw5 |= cpu_to_le32(SGI); /*  MCS Short Guard Interval */
-	}
-	desc->txdw5 |= cpu_to_le32(RTY_LMT_EN); /*  retry limit enable */
-	desc->txdw5 |= cpu_to_le32(0x00180000); /*  DATA/RTS Rate Fallback Limit */
-
-	/* 3 4. make wlan header, make_wlanhdr() */
-	hdr = (struct rtw_ieee80211_hdr *)pkt_start;
-	SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
-	memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /*  DA */
-	memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /*  SA */
-	memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /*  RA, BSSID */
-
-	/* 3 5. make payload */
-	ptr = pkt_start + pattrib->hdrlen;
-
-	switch (pmp_priv->tx.payload) {
-	case 0:
-		payload = 0x00;
-		break;
-	case 1:
-		payload = 0x5a;
-		break;
-	case 2:
-		payload = 0xa5;
-		break;
-	case 3:
-		payload = 0xff;
-		break;
-	default:
-		payload = 0x00;
-		break;
-	}
-
-	_rtw_memset(ptr, payload, pkt_end - ptr);
-
-	/* 3 6. start thread */
-	pmp_priv->tx.PktTxThread = kthread_run(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD");
-	if (IS_ERR(pmp_priv->tx.PktTxThread))
-		DBG_88E("Create PktTx Thread Fail !!!!!\n");
-}
-
-void SetPacketRx(struct adapter *pAdapter, u8 bStartRx)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-
-	if (bStartRx) {
-		/*  Accept CRC error and destination address */
-		pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS;
-
-		pHalData->ReceiveConfig |= ACRC32;
-
-		rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig);
-
-		/*  Accept all data frames */
-		rtw_write16(pAdapter, REG_RXFLTMAP2, 0xFFFF);
-	} else {
-		rtw_write32(pAdapter, REG_RCR, 0);
-	}
-}
-
-void ResetPhyRxPktCount(struct adapter *pAdapter)
-{
-	u32 i, phyrx_set = 0;
-
-	for (i = 0; i <= 0xF; i++) {
-		phyrx_set = 0;
-		phyrx_set |= _RXERR_RPT_SEL(i);	/* select */
-		phyrx_set |= RXERR_RPT_RST;	/*  set counter to zero */
-		rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
-	}
-}
-
-static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
-{
-	/* selection */
-	u32 phyrx_set = 0, count = 0;
-
-	phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
-	rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
-
-	/* Read packet count */
-	count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
-
-	return count;
-}
-
-u32 GetPhyRxPktReceived(struct adapter *pAdapter)
-{
-	u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
-
-	OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_OK);
-	CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_OK);
-	HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_OK);
-
-	return OFDM_cnt + CCK_cnt + HT_cnt;
-}
-
-u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
-{
-	u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
-
-	OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_FAIL);
-	CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_FAIL);
-	HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_FAIL);
-
-	return OFDM_cnt + CCK_cnt + HT_cnt;
-}
-
-/* reg 0x808[9:0]: FFT data x */
-/* reg 0x808[22]:  0  -->  1  to get 1 FFT data y */
-/* reg 0x8B4[15:0]: FFT data y report */
-static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
-{
-	int psd_val;
-
-
-	psd_val = rtw_read32(pAdapter, 0x808);
-	psd_val &= 0xFFBFFC00;
-	psd_val |= point;
-
-	rtw_write32(pAdapter, 0x808, psd_val);
-	mdelay(1);
-	psd_val |= 0x00400000;
-
-	rtw_write32(pAdapter, 0x808, psd_val);
-	mdelay(1);
-	psd_val = rtw_read32(pAdapter, 0x8B4);
-
-	psd_val &= 0x0000FFFF;
-
-	return psd_val;
-}
-
-/*
- *pts	start_point_min		stop_point_max
- * 128	64			64 + 128 = 192
- * 256	128			128 + 256 = 384
- * 512	256			256 + 512 = 768
- * 1024	512			512 + 1024 = 1536
- *
- */
-u32 mp_query_psd(struct adapter *pAdapter, u8 *data)
-{
-	u32 i, psd_pts = 0, psd_start = 0, psd_stop = 0;
-	u32 psd_data = 0;
-	int ret;
-
-	if (!netif_running(pAdapter->pnetdev)) {
-		RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! interface not opened!\n"));
-		return 0;
-	}
-
-	if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) {
-		RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! not in MP mode!\n"));
-		return 0;
-	}
-
-	if (strlen(data) == 0) { /* default value */
-		psd_pts = 128;
-		psd_start = 64;
-		psd_stop = 128;
-	} else {
-		ret = sscanf(data, "pts =%d, start =%d, stop =%d",
-				&psd_pts, &psd_start, &psd_stop);
-		if (ret != 3)
-			return 0;
-	}
-
-	_rtw_memset(data, '\0', sizeof(*data));
-
-	i = psd_start;
-	while (i < psd_stop) {
-		if (i >= psd_pts) {
-			psd_data = rtw_GetPSDData(pAdapter, i-psd_pts);
-		} else {
-			psd_data = rtw_GetPSDData(pAdapter, i);
-		}
-		sprintf(data, "%s%x ", data, psd_data);
-		i++;
-	}
-
-	msleep(100);
-	return strlen(data)+1;
-}
-
-void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv)
-{
-	   int i, res;
-	  struct adapter *padapter = pxmitpriv->adapter;
-	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
-
-	u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
-	u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
-	if (padapter->registrypriv.mp_mode == 0) {
-		max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
-		num_xmit_extbuf = NR_XMIT_EXTBUFF;
-	} else {
-		max_xmit_extbuf_size = 20000;
-		num_xmit_extbuf = 1;
-	}
-
-	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
-	for (i = 0; i < num_xmit_extbuf; i++) {
-		rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ));
-
-		pxmitbuf++;
-	}
-
-	if (pxmitpriv->pallocated_xmit_extbuf)
-		vfree(pxmitpriv->pallocated_xmit_extbuf);
-
-	if (padapter->registrypriv.mp_mode == 0) {
-		max_xmit_extbuf_size = 20000;
-		num_xmit_extbuf = 1;
-	} else {
-		max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
-		num_xmit_extbuf = NR_XMIT_EXTBUFF;
-	}
-
-	/*  Init xmit extension buff */
-	_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
-
-	pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
-
-	if (pxmitpriv->pallocated_xmit_extbuf  == NULL) {
-		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
-		res = _FAIL;
-		goto exit;
-	}
-
-	pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4);
-
-	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
-
-	for (i = 0; i < num_xmit_extbuf; i++) {
-		_rtw_init_listhead(&pxmitbuf->list);
-
-		pxmitbuf->priv_data = NULL;
-		pxmitbuf->padapter = padapter;
-		pxmitbuf->ext_tag = true;
-
-		res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
-		if (res == _FAIL) {
-			res = _FAIL;
-			goto exit;
-		}
-
-		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
-		pxmitbuf++;
-	}
-
-	pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
-
-exit:
-	;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1430 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTW_MP_IOCTL_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <mlme_osdep.h>
-
-/* include <rtw_mp.h> */
-#include <rtw_mp_ioctl.h>
-
-
-/*   rtl8188eu_oid_rtl_seg_81_85   section start **************** */
-int rtl8188eu_oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->information_buf_len < sizeof(u8))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	if (poid_par_priv->type_of_oid == SET_OID) {
-		Adapter->registrypriv.wireless_mode = *(u8 *)poid_par_priv->information_buf;
-	} else if (poid_par_priv->type_of_oid == QUERY_OID) {
-		*(u8 *)poid_par_priv->information_buf = Adapter->registrypriv.wireless_mode;
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-		 RT_TRACE(_module_mp_, _drv_info_, ("-query Wireless Mode=%d\n", Adapter->registrypriv.wireless_mode));
-	} else {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-	}
-
-
-	return status;
-}
-/*   rtl8188eu_oid_rtl_seg_81_87_80   section start **************** */
-int rtl8188eu_oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct bb_reg_param *pbbreg;
-	u16 offset;
-	u32 value;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_write_bb_reg_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
-
-	offset = (u16)(pbbreg->offset) & 0xFFF; /* 0ffset :0x800~0xfff */
-	if (offset < BB_REG_BASE_ADDR)
-		offset |= BB_REG_BASE_ADDR;
-
-	value = pbbreg->value;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("rtl8188eu_oid_rt_pro_write_bb_reg_hdl: offset=0x%03X value=0x%08X\n",
-		  offset, value));
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	write_bbreg(Adapter, offset, 0xFFFFFFFF, value);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct bb_reg_param *pbbreg;
-	u16 offset;
-	u32 value;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_read_bb_reg_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
-
-	offset = (u16)(pbbreg->offset) & 0xFFF; /* 0ffset :0x800~0xfff */
-	if (offset < BB_REG_BASE_ADDR)
-		offset |= BB_REG_BASE_ADDR;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	value = read_bbreg(Adapter, offset, 0xFFFFFFFF);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	pbbreg->value = value;
-	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("-rtl8188eu_oid_rt_pro_read_bb_reg_hdl: offset=0x%03X value:0x%08X\n",
-		  offset, value));
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct rf_reg_param *pbbreg;
-	u8 path;
-	u8 offset;
-	u32 value;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_write_rf_reg_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
-
-	if (pbbreg->path >= MAX_RF_PATH_NUMS)
-		return NDIS_STATUS_NOT_ACCEPTED;
-	if (pbbreg->offset > 0xFF)
-		return NDIS_STATUS_NOT_ACCEPTED;
-	if (pbbreg->value > 0xFFFFF)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	path = (u8)pbbreg->path;
-	offset = (u8)pbbreg->offset;
-	value = pbbreg->value;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("rtl8188eu_oid_rt_pro_write_rf_reg_hdl: path=%d offset=0x%02X value=0x%05X\n",
-		  path, offset, value));
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	write_rfreg(Adapter, path, offset, value);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct rf_reg_param *pbbreg;
-	u8 path;
-	u8 offset;
-	u32 value;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-	int status = NDIS_STATUS_SUCCESS;
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_read_rf_reg_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
-
-	if (pbbreg->path >= MAX_RF_PATH_NUMS)
-		return NDIS_STATUS_NOT_ACCEPTED;
-	if (pbbreg->offset > 0xFF)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	path = (u8)pbbreg->path;
-	offset = (u8)pbbreg->offset;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	value = read_rfreg(Adapter, path, offset);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	pbbreg->value = value;
-
-	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("-rtl8188eu_oid_rt_pro_read_rf_reg_hdl: path=%d offset=0x%02X value=0x%05X\n",
-		  path, offset, value));
-
-
-	return status;
-}
-/*   rtl8188eu_oid_rtl_seg_81_87_00   section end**************** */
-/*  */
-
-/*   rtl8188eu_oid_rtl_seg_81_80_00   section start **************** */
-/*  */
-int rtl8188eu_oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		ratevalue;/* 4 */
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("+rtl8188eu_oid_rt_pro_set_data_rate_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	ratevalue = *((u32 *)poid_par_priv->information_buf);/* 4 */
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("rtl8188eu_oid_rt_pro_set_data_rate_hdl: data rate idx=%d\n", ratevalue));
-	if (ratevalue >= MPT_RATE_LAST)
-		return NDIS_STATUS_INVALID_DATA;
-
-	Adapter->mppriv.rateidx = ratevalue;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetDataRate(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		mode;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_start_test_hdl\n"));
-
-	if (Adapter->registrypriv.mp_mode == 0)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	/* IQCalibrateBcut(Adapter); */
-
-	mode = *((u32 *)poid_par_priv->information_buf);
-	Adapter->mppriv.mode = mode;/*  1 for loopback */
-
-	if (mp_start_test(Adapter) == _FAIL) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		goto exit;
-	}
-
-exit:
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("-rtl8188eu_oid_rt_pro_start_test_hdl: mp_mode=%d\n", Adapter->mppriv.mode));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+Set OID_RT_PRO_STOP_TEST\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	mp_stop_test(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("-Set OID_RT_PRO_STOP_TEST\n"));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		Channel;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl\n"));
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	if (poid_par_priv->type_of_oid == QUERY_OID) {
-		*((u32 *)poid_par_priv->information_buf) = Adapter->mppriv.channel;
-		return NDIS_STATUS_SUCCESS;
-	}
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	Channel = *((u32 *)poid_par_priv->information_buf);
-	RT_TRACE(_module_mp_, _drv_notice_, ("rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl: Channel=%d\n", Channel));
-	if (Channel > 14)
-		return NDIS_STATUS_NOT_ACCEPTED;
-	Adapter->mppriv.channel = Channel;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetChannel(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u16		bandwidth;
-	u16		channel_offset;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("+rtl8188eu_oid_rt_set_bandwidth_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	bandwidth = *((u32 *)poid_par_priv->information_buf);/* 4 */
-	channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-
-	if (bandwidth != HT_CHANNEL_WIDTH_40)
-		bandwidth = HT_CHANNEL_WIDTH_20;
-	padapter->mppriv.bandwidth = (u8)bandwidth;
-	padapter->mppriv.prime_channel_offset = (u8)channel_offset;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetBandwidth(padapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("-rtl8188eu_oid_rt_set_bandwidth_hdl: bandwidth=%d channel_offset=%d\n",
-		  bandwidth, channel_offset));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		antenna;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_antenna_bb_hdl\n"));
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	if (poid_par_priv->type_of_oid == SET_OID) {
-		antenna = *(u32 *)poid_par_priv->information_buf;
-
-		Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
-		Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
-		RT_TRACE(_module_mp_, _drv_notice_,
-			 ("rtl8188eu_oid_rt_pro_set_antenna_bb_hdl: tx_ant=0x%04x rx_ant=0x%04x\n",
-			  Adapter->mppriv.antenna_tx, Adapter->mppriv.antenna_rx));
-
-		_irqlevel_changed_(&oldirql, LOWER);
-		SetAntenna(Adapter);
-		_irqlevel_changed_(&oldirql, RAISE);
-	} else {
-		antenna = (Adapter->mppriv.antenna_tx << 16)|Adapter->mppriv.antenna_rx;
-		*(u32 *)poid_par_priv->information_buf = antenna;
-	}
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		tx_pwr_idx;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_pro_set_tx_power_control_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
-	if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	Adapter->mppriv.txpoweridx = (u8)tx_pwr_idx;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("rtl8188eu_oid_rt_pro_set_tx_power_control_hdl: idx=0x%2x\n",
-		  Adapter->mppriv.txpoweridx));
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetTxPower(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-
-/*  */
-/*   rtl8188eu_oid_rtl_seg_81_80_20   section start **************** */
-/*  */
-int rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-
-	if (poid_par_priv->information_buf_len == sizeof(u32)) {
-		*(u32 *)poid_par_priv->information_buf =  Adapter->mppriv.tx_pktcount;
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-	} else {
-		status = NDIS_STATUS_INVALID_LENGTH;
-	}
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-	RT_TRACE(_module_mp_, _drv_alert_, ("===> rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl.\n"));
-	if (poid_par_priv->information_buf_len == sizeof(u32)) {
-		*(u32 *)poid_par_priv->information_buf =  Adapter->mppriv.rx_pktcount;
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-		RT_TRACE(_module_mp_, _drv_alert_, ("recv_ok:%d\n", Adapter->mppriv.rx_pktcount));
-	} else {
-		status = NDIS_STATUS_INVALID_LENGTH;
-	}
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-	RT_TRACE(_module_mp_, _drv_alert_, ("===> rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl.\n"));
-	if (poid_par_priv->information_buf_len == sizeof(u32)) {
-		*(u32 *)poid_par_priv->information_buf =  Adapter->mppriv.rx_crcerrpktcount;
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-		RT_TRACE(_module_mp_, _drv_alert_, ("recv_err:%d\n", Adapter->mppriv.rx_crcerrpktcount));
-	} else {
-		status = NDIS_STATUS_INVALID_LENGTH;
-	}
-
-
-	return status;
-}
-/*  */
-
-int rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != SET_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-
-	RT_TRACE(_module_mp_, _drv_alert_, ("===> rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl.\n"));
-	Adapter->mppriv.tx_pktcount = 0;
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != SET_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-
-	if (poid_par_priv->information_buf_len == sizeof(u32)) {
-		Adapter->mppriv.rx_pktcount = 0;
-		Adapter->mppriv.rx_crcerrpktcount = 0;
-	} else {
-		status = NDIS_STATUS_INVALID_LENGTH;
-	}
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != SET_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	ResetPhyRxPktCount(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	*(u32 *)poid_par_priv->information_buf = GetPhyRxPktReceived(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("-rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl: recv_ok=%d\n", *(u32 *)poid_par_priv->information_buf));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-
-	if (poid_par_priv->information_buf_len != sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	*(u32 *)poid_par_priv->information_buf = GetPhyRxPktCRC32Error(Adapter);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("-rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl: recv_err =%d\n",
-		 *(u32 *)poid_par_priv->information_buf));
-
-
-	return status;
-}
-/*   rtl8188eu_oid_rtl_seg_81_80_20   section end **************** */
-int rtl8188eu_oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		bStartTest;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_continuous_tx_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	bStartTest = *((u32 *)poid_par_priv->information_buf);
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetContinuousTx(Adapter, (u8)bStartTest);
-	if (bStartTest) {
-		struct mp_priv *pmp_priv = &Adapter->mppriv;
-		if (pmp_priv->tx.stop == 0) {
-			pmp_priv->tx.stop = 1;
-			DBG_88E("%s: pkt tx is running...\n", __func__);
-			msleep(5);
-		}
-		pmp_priv->tx.stop = 0;
-		pmp_priv->tx.count = 1;
-		SetPacketTx(Adapter);
-	}
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		bStartTest;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_alert_, ("+rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	bStartTest = *((u32 *)poid_par_priv->information_buf);
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetSingleCarrierTx(Adapter, (u8)bStartTest);
-	if (bStartTest) {
-		struct mp_priv *pmp_priv = &Adapter->mppriv;
-		if (pmp_priv->tx.stop == 0) {
-			pmp_priv->tx.stop = 1;
-			DBG_88E("%s: pkt tx is running...\n", __func__);
-			msleep(5);
-		}
-		pmp_priv->tx.stop = 0;
-		pmp_priv->tx.count = 1;
-		SetPacketTx(Adapter);
-	}
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		bStartTest;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	bStartTest = *((u32 *)poid_par_priv->information_buf);
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
-	if (bStartTest) {
-		struct mp_priv *pmp_priv = &Adapter->mppriv;
-		if (pmp_priv->tx.stop == 0) {
-			pmp_priv->tx.stop = 1;
-			DBG_88E("%s: pkt tx is running...\n", __func__);
-			msleep(5);
-		}
-		pmp_priv->tx.stop = 0;
-		pmp_priv->tx.count = 1;
-		SetPacketTx(Adapter);
-	}
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u32		bStartTest;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_alert_, ("+rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	bStartTest = *((u32 *)poid_par_priv->information_buf);
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	SetSingleToneTx(Adapter, (u8)bStartTest);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-	int status = NDIS_STATUS_SUCCESS;
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	rtw_hal_set_hwreg(Adapter, HW_VAR_TRIGGER_GPIO_0, NULL);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*   rtl8188eu_oid_rtl_seg_81_80_00   section end **************** */
-/*  */
-int rtl8188eu_oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct mp_rw_reg *RegRWStruct;
-	u32		offset, width;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("+rtl8188eu_oid_rt_pro_read_register_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
-	offset = RegRWStruct->offset;
-	width = RegRWStruct->width;
-
-	if (offset > 0xFFF)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	switch (width) {
-	case 1:
-		RegRWStruct->value = rtw_read8(Adapter, offset);
-		break;
-	case 2:
-		RegRWStruct->value = rtw_read16(Adapter, offset);
-		break;
-	default:
-		width = 4;
-		RegRWStruct->value = rtw_read32(Adapter, offset);
-		break;
-	}
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("rtl8188eu_oid_rt_pro_read_register_hdl: offset:0x%04X value:0x%X\n",
-		  offset, RegRWStruct->value));
-
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	*poid_par_priv->bytes_rw = width;
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct mp_rw_reg *RegRWStruct;
-	u32		offset, width, value;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("+rtl8188eu_oid_rt_pro_write_register_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
-	offset = RegRWStruct->offset;
-	width = RegRWStruct->width;
-	value = RegRWStruct->value;
-
-	if (offset > 0xFFF)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	switch (RegRWStruct->width) {
-	case 1:
-		if (value > 0xFF) {
-			status = NDIS_STATUS_NOT_ACCEPTED;
-			break;
-		}
-		rtw_write8(padapter, offset, (u8)value);
-		break;
-	case 2:
-		if (value > 0xFFFF) {
-			status = NDIS_STATUS_NOT_ACCEPTED;
-			break;
-		}
-		rtw_write16(padapter, offset, (u16)value);
-		break;
-	case 4:
-		rtw_write32(padapter, offset, value);
-		break;
-	default:
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		break;
-	}
-
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("-rtl8188eu_oid_rt_pro_write_register_hdl: offset=0x%08X width=%d value=0x%X\n",
-		  offset, width, value));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_burst_read_register_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_burst_write_register_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-/*  */
-int rtl8188eu_oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-/*  */
-int rtl8188eu_oid_rt_pro_write16_eeprom_hdl (struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_wr_attrib_mem_hdl (struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int  rtl8188eu_oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-	int status = NDIS_STATUS_SUCCESS;
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+OID_RT_PRO_SET_DATA_RATE_EX\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	if (rtw_setdatarate_cmd(Adapter, poid_par_priv->information_buf) != _SUCCESS)
-		status = NDIS_STATUS_NOT_ACCEPTED;
-
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	u8 thermal = 0;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_get_thermal_meter_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	GetThermalMeter(Adapter, &thermal);
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	*(u32 *)poid_par_priv->information_buf = (u32)thermal;
-	*poid_par_priv->bytes_rw = sizeof(u32);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_read_tssi_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-
-	if (poid_par_priv->information_buf_len < sizeof(u8))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	if (poid_par_priv->type_of_oid == SET_OID) {
-		u8 enable;
-
-		enable = *(u8 *)poid_par_priv->information_buf;
-		RT_TRACE(_module_mp_, _drv_notice_,
-			 ("+rtl8188eu_oid_rt_pro_set_power_tracking_hdl: enable =%d\n", enable));
-
-		SetPowerTracking(Adapter, enable);
-	} else {
-		GetPowerTracking(Adapter, (u8 *)poid_par_priv->information_buf);
-	}
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-/*   rtl8188eu_oid_rtl_seg_87_12_00   section start **************** */
-int rtl8188eu_oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return NDIS_STATUS_SUCCESS;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct efuse_access_struct *pefuse;
-	u8 *data;
-	u16 addr = 0, cnts = 0, max_available_size = 0;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct efuse_access_struct))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	pefuse = (struct efuse_access_struct *)poid_par_priv->information_buf;
-	addr = pefuse->start_addr;
-	cnts = pefuse->cnts;
-	data = pefuse->data;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("+rtl8188eu_oid_rt_pro_read_efuse_hd: buf_len=%d addr=%d cnts=%d\n",
-		  poid_par_priv->information_buf_len, addr, cnts));
-
-	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-
-	if ((addr + cnts) > max_available_size) {
-		RT_TRACE(_module_mp_, _drv_err_, ("!rtl8188eu_oid_rt_pro_read_efuse_hdl: parameter error!\n"));
-		return NDIS_STATUS_NOT_ACCEPTED;
-	}
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	if (rtw_efuse_access(Adapter, false, addr, cnts, data) == _FAIL) {
-		RT_TRACE(_module_mp_, _drv_err_, ("!rtl8188eu_oid_rt_pro_read_efuse_hdl: rtw_efuse_access FAIL!\n"));
-		status = NDIS_STATUS_FAILURE;
-	} else {
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-	}
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct efuse_access_struct *pefuse;
-	u8 *data;
-	u16 addr = 0, cnts = 0, max_available_size = 0;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	pefuse = (struct efuse_access_struct *)poid_par_priv->information_buf;
-	addr = pefuse->start_addr;
-	cnts = pefuse->cnts;
-	data = pefuse->data;
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("+rtl8188eu_oid_rt_pro_write_efuse_hdl: buf_len=%d addr=0x%04x cnts=%d\n",
-		  poid_par_priv->information_buf_len, addr, cnts));
-
-	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-
-	if ((addr + cnts) > max_available_size) {
-		RT_TRACE(_module_mp_, _drv_err_, ("!rtl8188eu_oid_rt_pro_write_efuse_hdl: parameter error"));
-		return NDIS_STATUS_NOT_ACCEPTED;
-	}
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	if (rtw_efuse_access(Adapter, true, addr, cnts, data) == _FAIL)
-		status = NDIS_STATUS_FAILURE;
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct pgpkt *ppgpkt;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	*poid_par_priv->bytes_rw = 0;
-
-	if (poid_par_priv->information_buf_len < sizeof(struct pgpkt *))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	ppgpkt = (struct pgpkt *)poid_par_priv->information_buf;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	if (poid_par_priv->type_of_oid == QUERY_OID) {
-		RT_TRACE(_module_mp_, _drv_notice_,
-			 ("rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl: Read offset=0x%x\n",\
-			 ppgpkt->offset));
-
-		Efuse_PowerSwitch(Adapter, false, true);
-		if (Efuse_PgPacketRead(Adapter, ppgpkt->offset, ppgpkt->data, false) == true)
-			*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-		else
-			status = NDIS_STATUS_FAILURE;
-		Efuse_PowerSwitch(Adapter, false, false);
-	} else {
-		RT_TRACE(_module_mp_, _drv_notice_,
-			 ("rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl: Write offset=0x%x word_en=0x%x\n",\
-			 ppgpkt->offset, ppgpkt->word_en));
-
-		Efuse_PowerSwitch(Adapter, true, true);
-		if (Efuse_PgPacketWrite(Adapter, ppgpkt->offset, ppgpkt->word_en, ppgpkt->data, false) == true)
-			*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-		else
-			status = NDIS_STATUS_FAILURE;
-		Efuse_PowerSwitch(Adapter, true, false);
-	}
-
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("-rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl: status=0x%08X\n", status));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u16 size;
-	u8 ret;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-	ret = efuse_GetCurrentSize(Adapter, &size);
-	_irqlevel_changed_(&oldirql, RAISE);
-	if (ret == _SUCCESS) {
-		*(u32 *)poid_par_priv->information_buf = size;
-		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-	} else {
-		status = NDIS_STATUS_FAILURE;
-	}
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-
-
-	if (poid_par_priv->type_of_oid != QUERY_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(u32))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	*(u32 *)poid_par_priv->information_buf = efuse_GetMaxSize(Adapter);
-	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("-rtl8188eu_oid_rt_get_efuse_max_size_hdl: size=%d status=0x%08X\n",
-		  *(int *)poid_par_priv->information_buf, status));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status;
-
-
-	RT_TRACE(_module_mp_, _drv_info_, ("+rtl8188eu_oid_rt_pro_efuse_hdl\n"));
-
-	if (poid_par_priv->type_of_oid == QUERY_OID)
-		status = rtl8188eu_oid_rt_pro_read_efuse_hdl(poid_par_priv);
-	else
-		status = rtl8188eu_oid_rt_pro_write_efuse_hdl(poid_par_priv);
-
-	RT_TRACE(_module_mp_, _drv_info_, ("-rtl8188eu_oid_rt_pro_efuse_hdl: status=0x%08X\n", status));
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u8		*data;
-	int status = NDIS_STATUS_SUCCESS;
-	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
-	u16	maplen = 0;
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_pro_efuse_map_hdl\n"));
-
-	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&maplen, false);
-
-	*poid_par_priv->bytes_rw = 0;
-
-	if (poid_par_priv->information_buf_len < maplen)
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	data = (u8 *)poid_par_priv->information_buf;
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	if (poid_par_priv->type_of_oid == QUERY_OID) {
-		RT_TRACE(_module_mp_, _drv_info_,
-			 ("rtl8188eu_oid_rt_pro_efuse_map_hdl: READ\n"));
-
-		if (rtw_efuse_map_read(Adapter, 0, maplen, data) == _SUCCESS) {
-			*poid_par_priv->bytes_rw = maplen;
-		} else {
-			RT_TRACE(_module_mp_, _drv_err_,
-				 ("rtl8188eu_oid_rt_pro_efuse_map_hdl: READ fail\n"));
-			status = NDIS_STATUS_FAILURE;
-		}
-	} else {
-		/*  SET_OID */
-		RT_TRACE(_module_mp_, _drv_info_,
-			 ("rtl8188eu_oid_rt_pro_efuse_map_hdl: WRITE\n"));
-
-		if (rtw_efuse_map_write(Adapter, 0, maplen, data) == _SUCCESS) {
-			*poid_par_priv->bytes_rw = maplen;
-		} else {
-			RT_TRACE(_module_mp_, _drv_err_,
-				 ("rtl8188eu_oid_rt_pro_efuse_map_hdl: WRITE fail\n"));
-			status = NDIS_STATUS_FAILURE;
-		}
-	}
-
-	_irqlevel_changed_(&oldirql, RAISE);
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("-rtl8188eu_oid_rt_pro_efuse_map_hdl: status=0x%08X\n", status));
-
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-	return status;
-}
-
-int rtl8188eu_oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
-{
-	u8		rx_pkt_type;
-	int status = NDIS_STATUS_SUCCESS;
-
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+rtl8188eu_oid_rt_set_rx_packet_type_hdl\n"));
-
-	if (poid_par_priv->type_of_oid != SET_OID)
-		return NDIS_STATUS_NOT_ACCEPTED;
-
-	if (poid_par_priv->information_buf_len < sizeof(u8))
-		return NDIS_STATUS_INVALID_LENGTH;
-
-	rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/* 4 */
-
-	RT_TRACE(_module_mp_, _drv_info_, ("rx_pkt_type: %x\n", rx_pkt_type));
-
-	return status;
-}
-
-int rtl8188eu_oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
-
-int rtl8188eu_mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
-{
-	struct mp_xmit_parm *pparm;
-	struct adapter *padapter;
-	struct mp_priv *pmp_priv;
-	struct pkt_attrib *pattrib;
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("+%s\n", __func__));
-
-	pparm = (struct mp_xmit_parm *)poid_par_priv->information_buf;
-	padapter = (struct adapter *)poid_par_priv->adapter_context;
-	pmp_priv = &padapter->mppriv;
-
-	if (poid_par_priv->type_of_oid == QUERY_OID) {
-		pparm->enable = !pmp_priv->tx.stop;
-		pparm->count = pmp_priv->tx.sended;
-	} else {
-		if (pparm->enable == 0) {
-			pmp_priv->tx.stop = 1;
-		} else if (pmp_priv->tx.stop == 1) {
-			pmp_priv->tx.stop = 0;
-			pmp_priv->tx.count = pparm->count;
-			pmp_priv->tx.payload = pparm->payload_type;
-			pattrib = &pmp_priv->tx.attrib;
-			pattrib->pktlen = pparm->length;
-			memcpy(pattrib->dst, pparm->da, ETH_ALEN);
-			SetPacketTx(padapter);
-		} else {
-			return NDIS_STATUS_FAILURE;
-		}
-	}
-
-	return NDIS_STATUS_SUCCESS;
-}
-
-/*  */
-int rtl8188eu_oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
-{
-	int status = NDIS_STATUS_SUCCESS;
-
-
-	if (poid_par_priv->type_of_oid != SET_OID) {
-		status = NDIS_STATUS_NOT_ACCEPTED;
-		return status;
-	}
-
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("\n ===> Setrtl8188eu_oid_rt_set_power_down_hdl.\n"));
-
-	_irqlevel_changed_(&oldirql, LOWER);
-
-	/* CALL  the power_down function */
-	_irqlevel_changed_(&oldirql, RAISE);
-
-
-	return status;
-}
-/*  */
-int rtl8188eu_oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_p2p.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_p2p.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_p2p.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_p2p.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2041 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTW_P2P_C_
-
-#include <drv_types.h>
-#include <rtw_p2p.h>
-#include <wifi.h>
-
-#ifdef CONFIG_88EU_P2P
-
-static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)
-{
-	int found = 0, i = 0;
-
-	for (i = 0; i < ch_cnt; i++) {
-		if (ch_list[i] == desired_ch) {
-			found = 1;
-			break;
-		}
-	}
-	return found;
-}
-
-static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	struct list_head *phead, *plist;
-	u32 len = 0;
-	u16 attr_len = 0;
-	u8 tmplen, *pdata_attr, *pstart, *pcur;
-	struct sta_info *psta = NULL;
-	struct adapter *padapter = pwdinfo->padapter;
-	struct sta_priv *pstapriv = &padapter->stapriv;
-
-	DBG_88E("%s\n", __func__);
-
-	pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);
-
-	pstart = pdata_attr;
-	pcur = pdata_attr;
-
-	spin_lock_bh(&pstapriv->asoc_list_lock);
-	phead = &pstapriv->asoc_list;
-	plist = phead->next;
-
-	/* look up sta asoc_queue */
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
-		psta = container_of(plist, struct sta_info, asoc_list);
-
-		plist = plist->next;
-
-
-		if (psta->is_p2p_device) {
-			tmplen = 0;
-
-			pcur++;
-
-			/* P2P device address */
-			memcpy(pcur, psta->dev_addr, ETH_ALEN);
-			pcur += ETH_ALEN;
-
-			/* P2P interface address */
-			memcpy(pcur, psta->hwaddr, ETH_ALEN);
-			pcur += ETH_ALEN;
-
-			*pcur = psta->dev_cap;
-			pcur++;
-
-			/* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
-			RTW_PUT_BE16(pcur, psta->config_methods);
-			pcur += 2;
-
-			memcpy(pcur, psta->primary_dev_type, 8);
-			pcur += 8;
-
-			*pcur = psta->num_of_secdev_type;
-			pcur++;
-
-			memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
-			pcur += psta->num_of_secdev_type*8;
-
-			if (psta->dev_name_len > 0) {
-				/* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-				RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
-				pcur += 2;
-
-				/* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
-				RTW_PUT_BE16(pcur, psta->dev_name_len);
-				pcur += 2;
-
-				memcpy(pcur, psta->dev_name, psta->dev_name_len);
-				pcur += psta->dev_name_len;
-			}
-
-
-			tmplen = (u8)(pcur-pstart);
-
-			*pstart = (tmplen-1);
-
-			attr_len += tmplen;
-
-			/* pstart += tmplen; */
-			pstart = pcur;
-		}
-	}
-	spin_unlock_bh(&pstapriv->asoc_list_lock);
-
-	if (attr_len > 0)
-		len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
-
-	kfree(pdata_attr);
-	return len;
-}
-
-static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
-	__be32	p2poui = cpu_to_be32(P2POUI);
-	u8	oui_subtype = P2P_GO_DISC_REQUEST;
-	u8	dialogToken = 0;
-
-	DBG_88E("[%s]\n", __func__);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	/* Build P2P action frame header */
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-	/* there is no IE in this P2P action frame */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-}
-
-static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8			action = P2P_PUB_ACTION_ACTION;
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8			oui_subtype = P2P_DEVDISC_RESP;
-	u8 p2pie[8] = { 0x00 };
-	u32 p2pielen = 0;
-
-	DBG_88E("[%s]\n", __func__);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	/* Build P2P public action frame header */
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-
-	/* Build P2P IE */
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*  P2P_ATTR_STATUS */
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-}
-
-static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)
-{
-	struct adapter *padapter = pwdinfo->padapter;
-	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
-	u8			action = P2P_PUB_ACTION_ACTION;
-	u8			dialogToken = frame_body[7];	/*	The Dialog Token of provisioning discovery request frame. */
-	__be32			p2poui = cpu_to_be32(P2POUI);
-	u8			oui_subtype = P2P_PROVISION_DISC_RESP;
-	u8			wpsie[100] = { 0x00 };
-	u8			wpsielen = 0;
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	RTW_PUT_BE32(wpsie, WPSOUI);
-	wpsielen += 4;
-
-	/*	Config Method */
-	/*	Type: */
-	RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
-	wpsielen += 2;
-
-	/*	Length: */
-	RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	RTW_PUT_BE16(wpsie + wpsielen, config_method);
-	wpsielen += 2;
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-
-	return;
-}
-
-static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct rtw_ieee80211_hdr	*pwlanhdr;
-	__le16 *fctrl;
-	struct adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
-	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
-	unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
-	__be32	p2poui = cpu_to_be32(P2POUI);
-	u8	oui_subtype = P2P_PRESENCE_RESPONSE;
-	u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
-	u8 noa_attr_content[32] = { 0x00 };
-	u32 p2pielen = 0;
-
-	DBG_88E("[%s]\n", __func__);
-
-	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib(padapter, pattrib);
-
-	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
-
-	fctrl = &(pwlanhdr->frame_ctl);
-	*(fctrl) = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
-
-	/* Build P2P action frame header */
-	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
-	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
-
-
-	/* Add P2P IE header */
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/* Add Status attribute in P2P IE */
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
-
-	/* Add NoA attribute in P2P IE */
-	noa_attr_content[0] = 0x1;/* index */
-	noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
-
-	/* todo: Notice of Absence Descriptor(s) */
-
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
-
-
-
-	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));
-
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe(padapter, pmgntframe);
-}
-
-u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
-	u16 capability = 0;
-	u32 len = 0, p2pielen = 0;
-	__le16 le_tmp;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-
-	/*	According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. P2P Device ID */
-	/*	3. Notice of Absence (NOA) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	/*	Be able to participate in additional P2P Groups and */
-	/*	support the P2P Invitation Procedure */
-	/*	Group Capability Bitmap, 1 byte */
-	capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
-	capability |=  ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
-		capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
-
-	le_tmp = cpu_to_le16(capability);
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&le_tmp);
-
-	/*  P2P Device ID ATTR */
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
-
-	/*  Notice of Absence ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-
-	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
-	return len;
-}
-
-u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20100907 */
-	/*	According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Extended Listen Timing */
-	/*	3. Notice of Absence (NOA)	(Only GO needs this) */
-	/*	4. Device Info */
-	/*	5. Group Info	(Only GO need this) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
-	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
-			p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;
-
-		p2pielen++;
-	} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
-		/*	Group Capability Bitmap, 1 byte */
-		if (pwdinfo->persistent_supported)
-			p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-		else
-			p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-	}
-
-	/*	Extended Listen Timing ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
-	RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Availability Period */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
-	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
-	p2pielen += 2;
-
-	/*	Availability Interval */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
-	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
-	p2pielen += 2;
-
-
-	/*  Notice of Absence ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-
-	/*	Device Info ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
-	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
-	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	/* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
-	RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
-	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	/*  Group Info ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-		p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
-
-
-	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
-
-
-	return len;
-}
-
-u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
-{
-	u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110301 */
-	/*	According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Device Info */
-	/*	3. Group ID (When joining an operating P2P Group) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
-	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-		p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-	else
-		p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-
-
-	/*	Device Info ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
-	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {
-		/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
-		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
-	} else {
-		/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
-		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
-	}
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	/* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
-	RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
-	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-		/*	Added by Albert 2011/05/19 */
-		/*	In this case, the pdev_raddr is the device address of the group owner. */
-
-		/*	P2P Group ID ATTR */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		/* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
-		RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
-		p2pielen += 2;
-
-		/*	Value: */
-		memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		memcpy(p2pie + p2pielen, pssid, ussidlen);
-		p2pielen += ussidlen;
-	}
-
-	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
-
-
-	return len;
-}
-
-
-u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
-{
-	u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*  According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
-	/*	1. Status */
-	/*	2. Extended Listen Timing (optional) */
-
-
-	/*	Status ATTR */
-	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
-
-
-	/*  Extended Listen Timing ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-
-	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
-
-	return len;
-}
-
-u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u32 len = 0;
-
-	return len;
-}
-
-u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *p;
-	u32 ret = false;
-	u8 *p2pie;
-	u32	p2pielen = 0;
-	int ssid_len = 0, rate_cnt = 0;
-
-	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
-			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
-
-	if (rate_cnt <= 4) {
-		int i, g_rate = 0;
-
-		for (i = 0; i < rate_cnt; i++) {
-			if (((*(p + 2 + i) & 0xff) != 0x02) &&
-			    ((*(p + 2 + i) & 0xff) != 0x04) &&
-			    ((*(p + 2 + i) & 0xff) != 0x0B) &&
-			    ((*(p + 2 + i) & 0xff) != 0x16))
-				g_rate = 1;
-		}
-
-		if (g_rate == 0) {
-			/*	There is no OFDM rate included in SupportedRates IE of this probe request frame */
-			/*	The driver should response this probe request. */
-			return ret;
-		}
-	} else {
-		/*	rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
-		/*	We should proceed the following check for this probe request. */
-	}
-
-	/*	Added comments by Albert 20100906 */
-	/*	There are several items we should check here. */
-	/*	1. This probe request frame must contain the P2P IE. (Done) */
-	/*	2. This probe request frame must contain the wildcard SSID. (Done) */
-	/*	3. Wildcard BSSID. (Todo) */
-	/*	4. Destination Address. (Done in mgt_dispatcher function) */
-	/*	5. Requested Device Type in WSC IE. (Todo) */
-	/*	6. Device ID attribute in P2P IE. (Todo) */
-
-	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
-			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
-
-	ssid_len &= 0xff;	/*	Just last 1 byte is valid for ssid len of the probe request */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);
-		if (p2pie) {
-			if ((p != NULL) && !memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid , 7)) {
-				/* todo: */
-				/* Check Requested Device Type attributes in WSC IE. */
-				/* Check Device ID attribute in P2P IE */
-
-				ret = true;
-			} else if ((p != NULL) && (ssid_len == 0)) {
-				ret = true;
-			}
-		} else {
-			/* non -p2p device */
-		}
-	}
-
-
-	return ret;
-}
-
-u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
-{
-	u8 status_code = P2P_STATUS_SUCCESS;
-	u8 *pbuf, *pattr_content = NULL;
-	u32 attr_contentlen = 0;
-	u16 cap_attr = 0;
-	unsigned short	frame_type, ie_offset = 0;
-	u8 *ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-	u32	p2p_ielen = 0;
-	__be16 be_tmp;
-	__le16 le_tmp;
-
-	if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-		return P2P_STATUS_FAIL_REQUEST_UNABLE;
-
-	frame_type = GetFrameSubType(pframe);
-	if (frame_type == WIFI_ASSOCREQ)
-		ie_offset = _ASOCREQ_IE_OFFSET_;
-	else /*  WIFI_REASSOCREQ */
-		ie_offset = _REASOCREQ_IE_OFFSET_;
-
-	ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
-	ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
-
-	p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
-
-	if (!p2p_ie) {
-		DBG_88E("[%s] P2P IE not Found!!\n", __func__);
-		status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
-	} else {
-		DBG_88E("[%s] P2P IE Found!!\n", __func__);
-	}
-
-	while (p2p_ie) {
-		/* Check P2P Capability ATTR */
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&le_tmp, (uint *)&attr_contentlen)) {
-			DBG_88E("[%s] Got P2P Capability Attr!!\n", __func__);
-			cap_attr = le16_to_cpu(le_tmp);
-			psta->dev_cap = cap_attr&0xff;
-		}
-
-		/* Check Extended Listen Timing ATTR */
-
-
-		/* Check P2P Device Info ATTR */
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
-			DBG_88E("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
-			pattr_content = rtw_zmalloc(attr_contentlen);
-			pbuf = pattr_content;
-			if (pattr_content) {
-				u8 num_of_secdev_type;
-				u16 dev_name_len;
-
-				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint *)&attr_contentlen);
-
-				memcpy(psta->dev_addr,	pattr_content, ETH_ALEN);/* P2P Device Address */
-
-				pattr_content += ETH_ALEN;
-
-				memcpy(&be_tmp, pattr_content, 2);/* Config Methods */
-				psta->config_methods = be16_to_cpu(be_tmp);
-
-				pattr_content += 2;
-
-				memcpy(psta->primary_dev_type, pattr_content, 8);
-
-				pattr_content += 8;
-
-				num_of_secdev_type = *pattr_content;
-				pattr_content += 1;
-
-				if (num_of_secdev_type == 0) {
-					psta->num_of_secdev_type = 0;
-				} else {
-					u32 len;
-
-					psta->num_of_secdev_type = num_of_secdev_type;
-
-					len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type*8)) ?
-					      (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
-
-					memcpy(psta->secdev_types_list, pattr_content, len);
-
-					pattr_content += (num_of_secdev_type*8);
-				}
-
-
-				psta->dev_name_len = 0;
-				if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(__be16 *)pattr_content)) {
-					dev_name_len = be16_to_cpu(*(__be16 *)(pattr_content+2));
-
-					psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
-
-					memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
-				}
-				kfree(pbuf);
-			}
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
-	}
-
-	return status_code;
-}
-
-u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *frame_body;
-	u8 status, dialogToken;
-	struct sta_info *psta = NULL;
-	struct adapter *padapter = pwdinfo->padapter;
-	struct sta_priv *pstapriv = &padapter->stapriv;
-	u8 *p2p_ie;
-	u32	p2p_ielen = 0;
-
-	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[7];
-	status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
-
-	p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
-	if (p2p_ie) {
-		u8 groupid[38] = { 0x00 };
-		u8 dev_addr[ETH_ALEN] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
-			if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
-			    !memcmp(pwdinfo->p2p_group_ssid, groupid+ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
-				attr_contentlen = 0;
-				if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
-					struct list_head *phead, *plist;
-
-					spin_lock_bh(&pstapriv->asoc_list_lock);
-					phead = &pstapriv->asoc_list;
-					plist = phead->next;
-
-					/* look up sta asoc_queue */
-					while ((rtw_end_of_queue_search(phead, plist)) == false) {
-						psta = container_of(plist, struct sta_info, asoc_list);
-
-						plist = plist->next;
-
-						if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
-						    !memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
-							/* issue GO Discoverability Request */
-							issue_group_disc_req(pwdinfo, psta->hwaddr);
-							status = P2P_STATUS_SUCCESS;
-							break;
-						} else {
-							status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-						}
-					}
-					spin_unlock_bh(&pstapriv->asoc_list_lock);
-				} else {
-					status = P2P_STATUS_FAIL_INVALID_PARAM;
-				}
-			} else {
-				status = P2P_STATUS_FAIL_INVALID_PARAM;
-			}
-		}
-	}
-
-
-	/* issue Device Discoverability Response */
-	issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
-
-	return (status == P2P_STATUS_SUCCESS) ? true : false;
-}
-
-u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	return true;
-}
-
-u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,  u8 *pframe, uint len)
-{
-	u8 *frame_body;
-	u8 *wpsie;
-	uint	wps_ielen = 0, attr_contentlen = 0;
-	u16	uconfig_method = 0;
-	__be16 be_tmp;
-
-	frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
-
-	wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
-	if (wpsie) {
-		if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen)) {
-			uconfig_method = be16_to_cpu(be_tmp);
-			switch (uconfig_method) {
-			case WPS_CM_DISPLYA:
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
-				break;
-			case WPS_CM_LABEL:
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
-				break;
-			case WPS_CM_PUSH_BUTTON:
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
-				break;
-			case WPS_CM_KEYPAD:
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
-				break;
-			}
-			issue_p2p_provision_resp(pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
-		}
-	}
-	DBG_88E("[%s] config method = %s\n", __func__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
-	return true;
-}
-
-u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo,  u8 *pframe)
-{
-	return true;
-}
-
-static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
-{
-	u8 i = 0, j = 0;
-	u8 temp = 0;
-	u8 ch_no = 0;
-	ch_content += 3;
-	ch_cnt -= 3;
-
-	while (ch_cnt > 0) {
-		ch_content += 1;
-		ch_cnt -= 1;
-		temp = *ch_content;
-		for (i = 0 ; i < temp ; i++, j++)
-			peer_ch_list[j] = *(ch_content + 1 + i);
-		ch_content += (temp + 1);
-		ch_cnt -= (temp + 1);
-		ch_no += temp ;
-	}
-
-	return ch_no;
-}
-
-static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
-{
-	int	i = 0, j = 0, temp = 0;
-	u8 ch_no = 0;
-
-	for (i = 0; i < peer_ch_num; i++) {
-		for (j = temp; j < pmlmeext->max_chan_nums; j++) {
-			if (*(peer_ch_list + i) == pmlmeext->channel_set[j].ChannelNum) {
-				ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
-				temp = j;
-				break;
-			}
-		}
-	}
-
-	return ch_no;
-}
-
-u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	struct adapter *padapter = pwdinfo->padapter;
-	u8	result = P2P_STATUS_SUCCESS;
-	u32	p2p_ielen = 0, wps_ielen = 0;
-	u8 *ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-	u8 *wpsie;
-	u16		wps_devicepassword_id = 0x0000;
-	uint	wps_devicepassword_id_len = 0;
-	__be16 be_tmp;
-
-	wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
-	if (wpsie) {
-		/*	Commented by Kurt 20120113 */
-		/*	If some device wants to do p2p handshake without sending prov_disc_req */
-		/*	We have to get peer_req_cm from here. */
-		if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
-			rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
-			wps_devicepassword_id = be16_to_cpu(be_tmp);
-
-			if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
-			else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
-			else
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
-		}
-	} else {
-		DBG_88E("[%s] WPS IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-		return result;
-	}
-
-	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
-		result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
-		return result;
-	}
-
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
-
-	if (!p2p_ie) {
-		DBG_88E("[%s] P2P IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-	}
-
-	while (p2p_ie) {
-		u8	attr_content = 0x00;
-		u32	attr_contentlen = 0;
-		u8	ch_content[50] = { 0x00 };
-		uint	ch_cnt = 0;
-		u8	peer_ch_list[50] = { 0x00 };
-		u8	peer_ch_num = 0;
-		u8	ch_list_inclusioned[50] = { 0x00 };
-		u8	ch_num_inclusioned = 0;
-
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
-
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
-			DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
-			pwdinfo->peer_intent = attr_content;	/*	include both intent and tie breaker values. */
-
-			if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
-				/*	Try to match the tie breaker value */
-				if (pwdinfo->intent == P2P_MAX_INTENT) {
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
-				} else {
-					if (attr_content & 0x01)
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-					else
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				}
-			} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-			} else {
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-			}
-
-			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-				/*	Store the group id information. */
-				memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
-				memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-			}
-		}
-
-
-		attr_contentlen = 0;
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
-			if (attr_contentlen != ETH_ALEN)
-				_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-		}
-
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
-			peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
-			ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
-
-			if (ch_num_inclusioned == 0) {
-				DBG_88E("[%s] No common channel in channel list!\n", __func__);
-				result = P2P_STATUS_FAIL_NO_COMMON_CH;
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-				break;
-			}
-
-			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-				if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
-				    ch_list_inclusioned, ch_num_inclusioned)) {
-					u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
-					attr_contentlen = 0;
-
-					if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-						peer_operating_ch = operatingch_info[4];
-
-					if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
-								       ch_list_inclusioned, ch_num_inclusioned)) {
-						/**
-						 *	Change our operating channel as peer's for compatibility.
-						 */
-						pwdinfo->operating_channel = peer_operating_ch;
-						DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
-					} else {
-						/*  Take first channel of ch_list_inclusioned as operating channel */
-						pwdinfo->operating_channel = ch_list_inclusioned[0];
-						DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
-					}
-				}
-			}
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
-	}
-	return result;
-}
-
-u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	struct adapter *padapter = pwdinfo->padapter;
-	u8	result = P2P_STATUS_SUCCESS;
-	u32	p2p_ielen, wps_ielen;
-	u8 *ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	/*	Be able to know which one is the P2P GO and which one is P2P client. */
-
-	if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
-	} else {
-		DBG_88E("[%s] WPS IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-	}
-
-	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
-	if (!p2p_ie) {
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-	} else {
-		u8	attr_content = 0x00;
-		u32	attr_contentlen = 0;
-		u8	operatingch_info[5] = { 0x00 };
-		u8	groupid[38];
-		u8	peer_ch_list[50] = { 0x00 };
-		u8	peer_ch_num = 0;
-		u8	ch_list_inclusioned[50] = { 0x00 };
-		u8	ch_num_inclusioned = 0;
-
-		while (p2p_ie) {	/*	Found the P2P IE. */
-			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-			if (attr_contentlen == 1) {
-				DBG_88E("[%s] Status = %d\n", __func__, attr_content);
-				if (attr_content == P2P_STATUS_SUCCESS) {
-					/*	Do nothing. */
-				} else {
-					if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
-					} else {
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					}
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					result = attr_content;
-					break;
-				}
-			}
-
-			/*	Try to get the peer's interface address */
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
-				if (attr_contentlen != ETH_ALEN)
-					_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-			}
-
-			/*	Try to get the peer's intent and tie breaker value. */
-			attr_content = 0x00;
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
-				DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
-				pwdinfo->peer_intent = attr_content;	/*	include both intent and tie breaker values. */
-
-				if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
-					/*	Try to match the tie breaker value */
-					if (pwdinfo->intent == P2P_MAX_INTENT) {
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-						result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					} else {
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-						rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-						if (attr_content & 0x01)
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-						else
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-					}
-				} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				} else {
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-					/*	Store the group id information. */
-					memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
-					memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-				}
-			}
-
-			/*	Try to get the operation channel information */
-
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
-				DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
-				pwdinfo->peer_operating_ch = operatingch_info[4];
-			}
-
-			/*	Try to get the channel list information */
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
-				DBG_88E("[%s] channel list attribute found, len = %d\n", __func__,  pwdinfo->channel_list_attr_len);
-
-				peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
-				ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
-
-				if (ch_num_inclusioned == 0) {
-					DBG_88E("[%s] No common channel in channel list!\n", __func__);
-					result = P2P_STATUS_FAIL_NO_COMMON_CH;
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					break;
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-					if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
-					    ch_list_inclusioned, ch_num_inclusioned)) {
-						u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
-						attr_contentlen = 0;
-
-						if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-							peer_operating_ch = operatingch_info[4];
-
-						if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
-						    ch_list_inclusioned, ch_num_inclusioned)) {
-							/**
-							 *	Change our operating channel as peer's for compatibility.
-							 */
-							pwdinfo->operating_channel = peer_operating_ch;
-							DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
-						} else {
-							/*  Take first channel of ch_list_inclusioned as operating channel */
-							pwdinfo->operating_channel = ch_list_inclusioned[0];
-							DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
-						}
-					}
-				}
-			} else {
-				DBG_88E("[%s] channel list attribute not found!\n", __func__);
-			}
-
-			/*	Try to get the group id information if peer is GO */
-			attr_contentlen = 0;
-			_rtw_memset(groupid, 0x00, 38);
-			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
-				memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
-				memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
-			}
-
-			/* Get the next P2P IE */
-			p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
-		}
-	}
-	return result;
-}
-
-u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-	u32	p2p_ielen = 0;
-	u8	result = P2P_STATUS_SUCCESS;
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
-	while (p2p_ie) {	/*	Found the P2P IE. */
-		u8	attr_content = 0x00, operatingch_info[5] = { 0x00 };
-		u8	groupid[38] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		pwdinfo->negotiation_dialog_token = 1;
-		rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-		if (attr_contentlen == 1) {
-			DBG_88E("[%s] Status = %d\n", __func__, attr_content);
-			result = attr_content;
-
-			if (attr_content == P2P_STATUS_SUCCESS) {
-				u8	bcancelled = 0;
-
-				_cancel_timer(&pwdinfo->restore_p2p_state_timer, &bcancelled);
-
-				/*	Commented by Albert 20100911 */
-				/*	Todo: Need to handle the case which both Intents are the same. */
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-				rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-				if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1)) {
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				} else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1)) {
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-				} else {
-					/*	Have to compare the Tie Breaker */
-					if (pwdinfo->peer_intent & 0x01)
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-					else
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				}
-			} else {
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-				break;
-			}
-		}
-
-		/*	Try to get the group id information */
-		attr_contentlen = 0;
-		_rtw_memset(groupid, 0x00, 38);
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
-			DBG_88E("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
-			memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
-			memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
-		}
-
-		attr_contentlen = 0;
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
-			DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
-			pwdinfo->peer_operating_ch = operatingch_info[4];
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
-	}
-	return result;
-}
-
-u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *frame_body;
-	u8 dialogToken = 0;
-	u8 status = P2P_STATUS_SUCCESS;
-
-	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[6];
-
-	/* todo: check NoA attribute */
-
-	issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
-
-	return true;
-}
-
-static void find_phase_handler(struct adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	struct ndis_802_11_ssid	ssid;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-
-	_rtw_memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
-	memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
-	ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
-
-	rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
-
-	spin_lock_bh(&pmlmepriv->lock);
-	rtw_sitesurvey_cmd(padapter, &ssid, 1, NULL, 0);
-	spin_unlock_bh(&pmlmepriv->lock);
-}
-
-void p2p_concurrent_handler(struct adapter *padapter);
-
-static void restore_p2p_state_handler(struct adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
-		/*	In the P2P client mode, the driver should not switch back to its listen channel */
-		/*	because this P2P client should stay at the operating channel of P2P GO. */
-		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	}
-}
-
-static void pre_tx_invitereq_handler(struct adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-	set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue_probereq_p2p(padapter, NULL);
-	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-
-}
-
-static void pre_tx_provdisc_handler(struct adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-	set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue_probereq_p2p(padapter, NULL);
-	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-
-}
-
-static void pre_tx_negoreq_handler(struct adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-	set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue_probereq_p2p(padapter, NULL);
-	_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-
-}
-
-void p2p_protocol_wk_hdl(struct adapter *padapter, int intCmdType)
-{
-	switch (intCmdType) {
-	case P2P_FIND_PHASE_WK:
-		find_phase_handler(padapter);
-		break;
-	case P2P_RESTORE_STATE_WK:
-		restore_p2p_state_handler(padapter);
-		break;
-	case P2P_PRE_TX_PROVDISC_PROCESS_WK:
-		pre_tx_provdisc_handler(padapter);
-		break;
-	case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
-		pre_tx_invitereq_handler(padapter);
-		break;
-	case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
-		pre_tx_negoreq_handler(padapter);
-		break;
-	}
-
-}
-
-void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
-{
-	u8 *ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-	u32	p2p_ielen = 0;
-	u8	noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/*  NoA length should be n*(13) + 2 */
-	u32	attr_contentlen = 0;
-
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	u8	find_p2p = false, find_p2p_ps = false;
-	u8	noa_offset, noa_num, noa_index;
-
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-	if (IELength <= _BEACON_IE_OFFSET_)
-		return;
-
-	ies = IEs + _BEACON_IE_OFFSET_;
-	ies_len = IELength - _BEACON_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
-
-	while (p2p_ie) {
-		find_p2p = true;
-		/*  Get Notice of Absence IE. */
-		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen)) {
-			find_p2p_ps = true;
-			noa_index = noa_attr[0];
-
-			if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
-			    (noa_index != pwdinfo->noa_index)) { /*  if index change, driver should reconfigure related setting. */
-				pwdinfo->noa_index = noa_index;
-				pwdinfo->opp_ps = noa_attr[1] >> 7;
-				pwdinfo->ctwindow = noa_attr[1] & 0x7F;
-
-				noa_offset = 2;
-				noa_num = 0;
-				/*  NoA length should be n*(13) + 2 */
-				if (attr_contentlen > 2) {
-					while (noa_offset < attr_contentlen) {
-						/* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
-						pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
-						noa_offset += 1;
-
-						memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						noa_num++;
-					}
-				}
-				pwdinfo->noa_num = noa_num;
-
-				if (pwdinfo->opp_ps == 1) {
-					pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
-					/*  driver should wait LPS for entering CTWindow */
-					if (padapter->pwrctrlpriv.bFwCurrentInPSMode)
-						p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
-				} else if (pwdinfo->noa_num > 0) {
-					pwdinfo->p2p_ps_mode = P2P_PS_NOA;
-					p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
-				} else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
-					p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
-				}
-			}
-
-			break; /*  find target, just break. */
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
-	}
-
-	if (find_p2p) {
-		if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && !find_p2p_ps)
-			p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
-	}
-
-}
-
-void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state)
-{
-	struct pwrctrl_priv		*pwrpriv = &padapter->pwrctrlpriv;
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-
-
-	/*  Pre action for p2p state */
-	switch (p2p_ps_state) {
-	case P2P_PS_DISABLE:
-		pwdinfo->p2p_ps_state = p2p_ps_state;
-
-		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-
-		pwdinfo->noa_index = 0;
-		pwdinfo->ctwindow = 0;
-		pwdinfo->opp_ps = 0;
-		pwdinfo->noa_num = 0;
-		pwdinfo->p2p_ps_mode = P2P_PS_NONE;
-		if (padapter->pwrctrlpriv.bFwCurrentInPSMode) {
-			if (pwrpriv->smart_ps == 0) {
-				pwrpriv->smart_ps = 2;
-				rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(padapter->pwrctrlpriv.pwr_mode)));
-			}
-		}
-		break;
-	case P2P_PS_ENABLE:
-		if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
-			pwdinfo->p2p_ps_state = p2p_ps_state;
-
-			if (pwdinfo->ctwindow > 0) {
-				if (pwrpriv->smart_ps != 0) {
-					pwrpriv->smart_ps = 0;
-					DBG_88E("%s(): Enter CTW, change SmartPS\n", __func__);
-					rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(padapter->pwrctrlpriv.pwr_mode)));
-				}
-			}
-			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-		}
-		break;
-	case P2P_PS_SCAN:
-	case P2P_PS_SCAN_DONE:
-	case P2P_PS_ALLSTASLEEP:
-		if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
-			pwdinfo->p2p_ps_state = p2p_ps_state;
-			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-		}
-		break;
-	default:
-		break;
-	}
-
-}
-
-u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
-{
-	struct cmd_obj	*ph2c;
-	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return res;
-
-	if (enqueue) {
-		ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-		if (ph2c == NULL) {
-			res = _FAIL;
-			goto exit;
-		}
-
-		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-		if (pdrvextra_cmd_parm == NULL) {
-			kfree(ph2c);
-			res = _FAIL;
-			goto exit;
-		}
-
-		pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
-		pdrvextra_cmd_parm->type_size = p2p_ps_state;
-		pdrvextra_cmd_parm->pbuf = NULL;
-
-		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-
-		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-	} else {
-		p2p_ps_wk_hdl(padapter, p2p_ps_state);
-	}
-
-exit:
-
-
-	return res;
-}
-
-static void reset_ch_sitesurvey_timer_process (void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	DBG_88E("[%s] In\n", __func__);
-	/*	Reset the operation channel information */
-	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
-	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
-}
-
-static void reset_ch_sitesurvey_timer_process2 (void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	DBG_88E("[%s] In\n", __func__);
-	/*	Reset the operation channel information */
-	pwdinfo->p2p_info.operation_ch[0] = 0;
-	pwdinfo->p2p_info.scan_op_ch_only = 0;
-}
-
-static void restore_p2p_state_timer_process (void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
-}
-
-static void pre_tx_scan_timer_process(void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-	struct	wifidirect_info *pwdinfo = &adapter->wdinfo;
-	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	spin_lock_bh(&pmlmepriv->lock);
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
-		if (pwdinfo->tx_prov_disc_info.benable) {	/*	the provision discovery request frame is trigger to send or not */
-			p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
-			/* issue_probereq_p2p(adapter, NULL); */
-			/* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
-		}
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
-		if (pwdinfo->nego_req_info.benable)
-			p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
-		if (pwdinfo->invitereq_info.benable)
-			p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
-	} else {
-		DBG_88E("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
-	}
-
-	spin_unlock_bh(&pmlmepriv->lock);
-}
-
-static void find_phase_timer_process(void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	adapter->wdinfo.find_phase_state_exchange_cnt++;
-
-	p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
-}
-
-void reset_global_wifidirect_info(struct adapter *padapter)
-{
-	struct wifidirect_info	*pwdinfo;
-
-	pwdinfo = &padapter->wdinfo;
-	pwdinfo->persistent_supported = 0;
-	pwdinfo->session_available = true;
-	pwdinfo->wfd_tdls_enable = 0;
-	pwdinfo->wfd_tdls_weaksec = 0;
-}
-
-void rtw_init_wifidirect_timers(struct adapter *padapter)
-{
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	_init_timer(&pwdinfo->find_phase_timer, padapter->pnetdev, find_phase_timer_process, padapter);
-	_init_timer(&pwdinfo->restore_p2p_state_timer, padapter->pnetdev, restore_p2p_state_timer_process, padapter);
-	_init_timer(&pwdinfo->pre_tx_scan_timer, padapter->pnetdev, pre_tx_scan_timer_process, padapter);
-	_init_timer(&pwdinfo->reset_ch_sitesurvey, padapter->pnetdev, reset_ch_sitesurvey_timer_process, padapter);
-	_init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter->pnetdev, reset_ch_sitesurvey_timer_process2, padapter);
-}
-
-void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr, u8 *iface_addr)
-{
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	/*init device&interface address */
-	if (dev_addr)
-		memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
-	if (iface_addr)
-		memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
-#endif
-}
-
-void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role)
-{
-	struct wifidirect_info	*pwdinfo;
-
-	pwdinfo = &padapter->wdinfo;
-	pwdinfo->padapter = padapter;
-
-	/*	1, 6, 11 are the social channel defined in the WiFi Direct specification. */
-	pwdinfo->social_chan[0] = 1;
-	pwdinfo->social_chan[1] = 6;
-	pwdinfo->social_chan[2] = 11;
-	pwdinfo->social_chan[3] = 0;	/*	channel 0 for scanning ending in site survey function. */
-
-	/*	Use the channel 11 as the listen channel */
-	pwdinfo->listen_channel = 11;
-
-	if (role == P2P_ROLE_DEVICE) {
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
-		pwdinfo->intent = 1;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
-	} else if (role == P2P_ROLE_CLIENT) {
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-		pwdinfo->intent = 1;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-	} else if (role == P2P_ROLE_GO) {
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-		pwdinfo->intent = 15;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-	}
-
-/*	Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
-	pwdinfo->support_rate[0] = 0x8c;	/*	6(B) */
-	pwdinfo->support_rate[1] = 0x92;	/*	9(B) */
-	pwdinfo->support_rate[2] = 0x18;	/*	12 */
-	pwdinfo->support_rate[3] = 0x24;	/*	18 */
-	pwdinfo->support_rate[4] = 0x30;	/*	24 */
-	pwdinfo->support_rate[5] = 0x48;	/*	36 */
-	pwdinfo->support_rate[6] = 0x60;	/*	48 */
-	pwdinfo->support_rate[7] = 0x6c;	/*	54 */
-
-	memcpy(pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
-
-	_rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
-	pwdinfo->device_name_len = 0;
-
-	_rtw_memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
-	pwdinfo->invitereq_info.token = 3;	/*	Token used for P2P invitation request frame. */
-
-	_rtw_memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
-	pwdinfo->inviteresp_info.token = 0;
-
-	pwdinfo->profileindex = 0;
-	_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
-
-	rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
-
-	pwdinfo->listen_dwell = (u8) ((jiffies % 3) + 1);
-
-	_rtw_memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
-	pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
-
-	_rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
-
-	pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
-	pwdinfo->negotiation_dialog_token = 1;
-
-	_rtw_memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
-	pwdinfo->nego_ssidlen = 0;
-
-	pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
-	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
-	pwdinfo->channel_list_attr_len = 0;
-	_rtw_memset(pwdinfo->channel_list_attr, 0x00, 100);
-
-	_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
-	_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
-	_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
-	pwdinfo->wfd_tdls_enable = 0;
-	_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-	_rtw_memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
-
-	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
-	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;	/*	Used to indicate the scan end in site survey function */
-	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
-	pwdinfo->p2p_info.operation_ch[0] = 0;
-	pwdinfo->p2p_info.operation_ch[1] = 0;			/*	Used to indicate the scan end in site survey function */
-	pwdinfo->p2p_info.scan_op_ch_only = 0;
-}
-
-int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role)
-{
-	int ret = _SUCCESS;
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
-		/* leave IPS/Autosuspend */
-		if (_FAIL == rtw_pwr_wakeup(padapter)) {
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*	Added by Albert 2011/03/22 */
-		/*	In the P2P mode, the driver should not support the b mode. */
-		/*	So, the Tx packet shouldn't use the CCK rate */
-		update_tx_basic_rate(padapter, WIRELESS_11AGN);
-
-		/* Enable P2P function */
-		init_wifidirect_info(padapter, role);
-
-		rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, true);
-	} else if (role == P2P_ROLE_DISABLE) {
-		if (_FAIL == rtw_pwr_wakeup(padapter)) {
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/* Disable P2P function */
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			del_timer_sync(&pwdinfo->find_phase_timer);
-			del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-			del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-			del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
-			del_timer_sync(&pwdinfo->reset_ch_sitesurvey2);
-			reset_ch_sitesurvey_timer_process(padapter);
-			reset_ch_sitesurvey_timer_process2(padapter);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
-			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
-			_rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
-		}
-
-		rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, false);
-
-		/* Restore to initial setting. */
-		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
-	}
-
-exit:
-	return ret;
-}
-
-#else
-u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
-{
-	return _FAIL;
-}
-
-void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
-{
-}
-
-#endif /* CONFIG_88EU_P2P */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,8 +22,111 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <osdep_intf.h>
+#include <usb_ops_linux.h>
 #include <linux/usb.h>
 
+static int rtw_hw_suspend(struct adapter *padapter)
+{
+	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+	struct net_device *pnetdev = padapter->pnetdev;
+
+
+	if ((!padapter->bup) || (padapter->bDriverStopped) ||
+	    (padapter->bSurpriseRemoved)) {
+		DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+			padapter->bup, padapter->bDriverStopped,
+			padapter->bSurpriseRemoved);
+		goto error_exit;
+	}
+
+	/* system suspend */
+	LeaveAllPowerSaveMode(padapter);
+
+	DBG_88E("==> rtw_hw_suspend\n");
+	_enter_pwrlock(&pwrpriv->lock);
+	pwrpriv->bips_processing = true;
+	/* s1. */
+	if (pnetdev) {
+		netif_carrier_off(pnetdev);
+		netif_tx_stop_all_queues(pnetdev);
+	}
+
+	/* s2. */
+	rtw_disassoc_cmd(padapter, 500, false);
+
+	/* s2-2.  indicate disconnect to os */
+	{
+		struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+			_clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+			rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+			rtw_os_indicate_disconnect(padapter);
+
+			/* donnot enqueue cmd */
+			rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
+		}
+	}
+	/* s2-3. */
+	rtw_free_assoc_resources(padapter, 1);
+
+	/* s2-4. */
+	rtw_free_network_queue(padapter, true);
+	rtw_ips_dev_unload(padapter);
+	pwrpriv->rf_pwrstate = rf_off;
+	pwrpriv->bips_processing = false;
+
+	_exit_pwrlock(&pwrpriv->lock);
+
+	return 0;
+
+error_exit:
+	DBG_88E("%s, failed\n", __func__);
+	return -1;
+}
+
+static int rtw_hw_resume(struct adapter *padapter)
+{
+	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+	struct net_device *pnetdev = padapter->pnetdev;
+
+
+	/* system resume */
+	DBG_88E("==> rtw_hw_resume\n");
+	_enter_pwrlock(&pwrpriv->lock);
+	pwrpriv->bips_processing = true;
+	rtw_reset_drv_sw(padapter);
+
+	if (pm_netdev_open(pnetdev, false) != 0) {
+		_exit_pwrlock(&pwrpriv->lock);
+		goto error_exit;
+	}
+
+	netif_device_attach(pnetdev);
+	netif_carrier_on(pnetdev);
+
+	if (!netif_queue_stopped(pnetdev))
+		netif_start_queue(pnetdev);
+	else
+		netif_wake_queue(pnetdev);
+
+	pwrpriv->bkeepfwalive = false;
+	pwrpriv->brfoffbyhw = false;
+
+	pwrpriv->rf_pwrstate = rf_on;
+	pwrpriv->bips_processing = false;
+
+	_exit_pwrlock(&pwrpriv->lock);
+
+
+	return 0;
+error_exit:
+	DBG_88E("%s, Open net dev failed\n", __func__);
+	return -1;
+}
+
 void ips_enter(struct adapter *padapter)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
@@ -100,7 +203,7 @@ int ips_leave(struct adapter *padapter)
 			}
 		}
 
-		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
+		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", usb_read32(padapter, 0x4c));
 		pwrpriv->bips_processing = false;
 
 		pwrpriv->bkeepfwalive = false;
@@ -114,12 +217,7 @@ int ips_leave(struct adapter *padapter)
 
 static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
 {
-	struct adapter *buddy = adapter->pbuddy_adapter;
 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(adapter->wdinfo);
-#endif
-
 	bool ret = false;
 
 	if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
@@ -128,32 +226,9 @@ static bool rtw_pwr_unassociated_idle(st
 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
 	    check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
 	    check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
-	    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) ||
-#if defined(CONFIG_88EU_P2P)
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-#else
-	    0)
-#endif
+	    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE))
 		goto exit;
 
-	/* consider buddy, if exist */
-	if (buddy) {
-		struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
-		#ifdef CONFIG_88EU_P2P
-		struct wifidirect_info *b_pwdinfo = &(buddy->wdinfo);
-		#endif
-
-		if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
-		    check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
-		    check_fwstate(b_pmlmepriv, WIFI_AP_STATE) ||
-		    check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE) ||
-#if defined(CONFIG_88EU_P2P)
-		    !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE))
-#else
-		    0)
-#endif
-			goto exit;
-	}
 	ret = true;
 
 exit:
@@ -179,7 +254,6 @@ void rtw_ps_processor(struct adapter *pa
 			if (rfpwrstate == rf_off) {
 				pwrpriv->change_rfpwrstate = rf_off;
 				pwrpriv->brfoffbyhw = true;
-				padapter->bCardDisableWOHSM = true;
 				rtw_hw_suspend(padapter);
 			} else {
 				pwrpriv->change_rfpwrstate = rf_on;
@@ -304,9 +378,6 @@ static u8 PS_RDY_CHECK(struct adapter *p
 void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 
 	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 		 ("%s: PowerMode=%d Smart_PS=%d\n",
@@ -328,16 +399,6 @@ void rtw_set_ps_mode(struct adapter *pad
 
 	/* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
 	if (ps_mode == PS_MODE_ACTIVE) {
-#ifdef CONFIG_88EU_P2P
-		if (pwdinfo->opp_ps == 0) {
-			DBG_88E("rtw_set_ps_mode: Leave 802.11 power save\n");
-			pwrpriv->pwr_mode = ps_mode;
-			rtw_set_rpwm(padapter, PS_STATE_S4);
-			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-			pwrpriv->bFwCurrentInPSMode = false;
-		}
-	} else {
-#endif /* CONFIG_88EU_P2P */
 		if (PS_RDY_CHECK(padapter)) {
 			DBG_88E("%s: Enter 802.11 power save\n", __func__);
 			pwrpriv->bFwCurrentInPSMode = true;
@@ -345,13 +406,6 @@ void rtw_set_ps_mode(struct adapter *pad
 			pwrpriv->smart_ps = smart_ps;
 			pwrpriv->bcn_ant_mode = bcn_ant_mode;
 			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-
-#ifdef CONFIG_88EU_P2P
-			/*  Set CTWindow after LPS */
-			if (pwdinfo->opp_ps == 1)
-				p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
-#endif /* CONFIG_88EU_P2P */
-
 			rtw_set_rpwm(padapter, PS_STATE_S2);
 		}
 	}
@@ -448,11 +502,8 @@ void LeaveAllPowerSaveMode(struct adapte
 	struct mlme_priv	*pmlmepriv = &(Adapter->mlmepriv);
 	u8	enqueue = 0;
 
-	if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
-		p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
-
+	if (check_fwstate(pmlmepriv, _FW_LINKED))
 		rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
-	}
 }
 
 void rtw_init_pwrctrl_priv(struct adapter *padapter)
@@ -500,7 +551,7 @@ void rtw_init_pwrctrl_priv(struct adapte
 inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-	pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ms);
+	pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
 }
 
 /*
@@ -517,9 +568,9 @@ int _rtw_pwr_wakeup(struct adapter *pada
 	unsigned long expires;
 	int ret = _SUCCESS;
 
-	expires = jiffies + rtw_ms_to_systime(ips_deffer_ms);
+	expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
 	if (time_before(pwrpriv->ips_deny_time, expires))
-		pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
+		pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
 
 {
 	u32 start = jiffies;
@@ -573,9 +624,9 @@ int _rtw_pwr_wakeup(struct adapter *pada
 	}
 
 exit:
-	expires = jiffies + rtw_ms_to_systime(ips_deffer_ms);
+	expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
 	if (time_before(pwrpriv->ips_deny_time, expires))
-		pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
+		pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_recv.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_recv.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@
 #include <drv_types.h>
 #include <recv_osdep.h>
 #include <mlme_osdep.h>
-#include <usb_ops.h>
 #include <wifi.h>
 #include <linux/vmalloc.h>
 
@@ -47,7 +46,7 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER
 void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
 {
 
-	_rtw_memset((u8 *)psta_recvpriv, 0, sizeof (struct sta_recv_priv));
+	memset((u8 *)psta_recvpriv, 0, sizeof (struct sta_recv_priv));
 
 	spin_lock_init(&psta_recvpriv->lock);
 
@@ -83,9 +82,9 @@ int _rtw_init_recv_priv(struct recv_priv
 	precvframe = (struct recv_frame *)precvpriv->precv_frame_buf;
 
 	for (i = 0; i < NR_RECVFRAME; i++) {
-		_rtw_init_listhead(&(precvframe->list));
+		INIT_LIST_HEAD(&(precvframe->list));
 
-		rtw_list_insert_tail(&(precvframe->list),
+		list_add_tail(&(precvframe->list),
 				     &(precvpriv->free_recv_queue.queue));
 
 		res = rtw_os_recv_resource_alloc(padapter, precvframe);
@@ -132,7 +131,7 @@ struct recv_frame *_rtw_alloc_recvframe
 	struct adapter *padapter;
 	struct recv_priv *precvpriv;
 
-	if (_rtw_queue_empty(pfree_recv_queue)) {
+	if (list_empty(&pfree_recv_queue->queue)) {
 		hdr = NULL;
 	} else {
 		phead = get_list_head(pfree_recv_queue);
@@ -141,7 +140,7 @@ struct recv_frame *_rtw_alloc_recvframe
 
 		hdr = container_of(plist, struct recv_frame, list);
 
-		rtw_list_delete(&hdr->list);
+		list_del_init(&hdr->list);
 		padapter = hdr->adapter;
 		if (padapter != NULL) {
 			precvpriv = &padapter->recvpriv;
@@ -170,7 +169,7 @@ struct recv_frame *rtw_alloc_recvframe(s
 void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv)
 {
 	/* Perry: This can be removed */
-	_rtw_init_listhead(&precvframe->list);
+	INIT_LIST_HEAD(&precvframe->list);
 
 	precvframe->len = 0;
 }
@@ -192,11 +191,11 @@ int rtw_free_recvframe(struct recv_frame
 
 	spin_lock_bh(&pfree_recv_queue->lock);
 
-	rtw_list_delete(&(precvframe->list));
+	list_del_init(&(precvframe->list));
 
 	precvframe->len = 0;
 
-	rtw_list_insert_tail(&(precvframe->list), get_list_head(pfree_recv_queue));
+	list_add_tail(&(precvframe->list), get_list_head(pfree_recv_queue));
 
 	if (padapter != NULL) {
 		if (pfree_recv_queue == &precvpriv->free_recv_queue)
@@ -215,8 +214,8 @@ int _rtw_enqueue_recvframe(struct recv_f
 	struct recv_priv *precvpriv = &padapter->recvpriv;
 
 
-	rtw_list_delete(&(precvframe->list));
-	rtw_list_insert_tail(&(precvframe->list), get_list_head(queue));
+	list_del_init(&(precvframe->list));
+	list_add_tail(&(precvframe->list), get_list_head(queue));
 
 	if (padapter != NULL) {
 		if (queue == &precvpriv->free_recv_queue)
@@ -256,7 +255,7 @@ void rtw_free_recvframe_queue(struct __q
 	phead = get_list_head(pframequeue);
 	plist = phead->next;
 
-	while (rtw_end_of_queue_search(phead, plist) == false) {
+	while (phead != plist) {
 		hdr = container_of(plist, struct recv_frame, list);
 
 		plist = plist->next;
@@ -790,10 +789,6 @@ int sta2sta_data_frame(struct adapter *a
 
 	if (*psta == NULL) {
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
-		if (adapter->registrypriv.mp_mode == 1) {
-			if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
-			adapter->mppriv.rx_pktloss++;
-		}
 		ret = _FAIL;
 		goto exit;
 	}
@@ -1040,12 +1035,12 @@ static int validate_recv_ctrl_frame(stru
 			xmitframe_phead = get_list_head(&psta->sleep_q);
 			xmitframe_plist = xmitframe_phead->next;
 
-			if ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false) {
+			if (xmitframe_phead != xmitframe_plist) {
 				pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 				xmitframe_plist = xmitframe_plist->next;
 
-				rtw_list_delete(&pxmitframe->list);
+				list_del_init(&pxmitframe->list);
 
 				psta->sleepq_len--;
 
@@ -1455,7 +1450,7 @@ static struct recv_frame *recvframe_defr
 	plist = phead->next;
 	pfhdr = container_of(plist, struct recv_frame, list);
 	prframe = (struct recv_frame *)pfhdr;
-	rtw_list_delete(&(prframe->list));
+	list_del_init(&(prframe->list));
 
 	if (curfragnum != pfhdr->attrib.frag_num) {
 		/* the first fragment number must be 0 */
@@ -1472,7 +1467,7 @@ static struct recv_frame *recvframe_defr
 
 	plist = plist->next;
 
-	while (rtw_end_of_queue_search(phead, plist) == false) {
+	while (phead != plist) {
 		pnfhdr = container_of(plist, struct recv_frame, list);
 		pnextrframe = (struct recv_frame *)pnfhdr;
 
@@ -1564,7 +1559,7 @@ struct recv_frame *recvframe_chk_defrag(
 		if (pdefrag_q != NULL) {
 			if (fragnum == 0) {
 				/* the first fragment */
-				if (_rtw_queue_empty(pdefrag_q) == false) {
+				if (!list_empty(&pdefrag_q->queue)) {
 					/* free current defrag_q */
 					rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
 				}
@@ -1573,7 +1568,7 @@ struct recv_frame *recvframe_chk_defrag(
 			/* Then enqueue the 0~(n-1) fragment into the defrag_q */
 
 			phead = get_list_head(pdefrag_q);
-			rtw_list_insert_tail(&pfhdr->list, phead);
+			list_add_tail(&pfhdr->list, phead);
 
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Enqueuq: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
 
@@ -1591,7 +1586,7 @@ struct recv_frame *recvframe_chk_defrag(
 		/* enqueue the last fragment */
 		if (pdefrag_q != NULL) {
 			phead = get_list_head(pdefrag_q);
-			rtw_list_insert_tail(&pfhdr->list, phead);
+			list_add_tail(&pfhdr->list, phead);
 
 			/* call recvframe_defrag to defrag */
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("defrag: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
@@ -1645,7 +1640,7 @@ static int amsdu_to_msdu(struct adapter
 
 	while (a_len > ETH_HLEN) {
 		/* Offset 12 denote 2 mac address */
-		nSubframe_Length = RTW_GET_BE16(pdata + 12);
+		nSubframe_Length = get_unaligned_be16(pdata + 12);
 
 		if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
 			DBG_88E("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);
@@ -1700,7 +1695,7 @@ static int amsdu_to_msdu(struct adapter
 	for (i = 0; i < nr_subframes; i++) {
 		sub_skb = subframes[i];
 		/* convert hdr + possible LLC headers into Ethernet header */
-		eth_type = RTW_GET_BE16(&sub_skb->data[6]);
+		eth_type = get_unaligned_be16(&sub_skb->data[6]);
 		if (sub_skb->len >= 8 &&
 		    ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
 			  eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
@@ -1778,7 +1773,7 @@ static int enqueue_reorder_recvframe(str
 	phead = get_list_head(ppending_recvframe_queue);
 	plist = phead->next;
 
-	while (rtw_end_of_queue_search(phead, plist) == false) {
+	while (phead != plist) {
 		hdr = container_of(plist, struct recv_frame, list);
 		pnextattrib = &hdr->attrib;
 
@@ -1790,9 +1785,9 @@ static int enqueue_reorder_recvframe(str
 			break;
 	}
 
-	rtw_list_delete(&(prframe->list));
+	list_del_init(&(prframe->list));
 
-	rtw_list_insert_tail(&(prframe->list), plist);
+	list_add_tail(&(prframe->list), plist);
 	return true;
 }
 
@@ -1811,7 +1806,7 @@ static int recv_indicatepkts_in_order(st
 
 	/*  Handling some condition for forced indicate case. */
 	if (bforced) {
-		if (rtw_is_list_empty(phead))
+		if (list_empty(phead))
 			return true;
 
 		prhdr = container_of(plist, struct recv_frame, list);
@@ -1821,7 +1816,7 @@ static int recv_indicatepkts_in_order(st
 
 	/*  Prepare indication list and indication. */
 	/*  Check if there is any packet need indicate. */
-	while (!rtw_is_list_empty(phead)) {
+	while (!list_empty(phead)) {
 		prhdr = container_of(plist, struct recv_frame, list);
 		prframe = (struct recv_frame *)prhdr;
 		pattrib = &prframe->attrib;
@@ -1831,7 +1826,7 @@ static int recv_indicatepkts_in_order(st
 				 ("recv_indicatepkts_in_order: indicate=%d seq=%d amsdu=%d\n",
 				  preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
 			plist = plist->next;
-			rtw_list_delete(&(prframe->list));
+			list_del_init(&(prframe->list));
 
 			if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num))
 				preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
@@ -2013,25 +2008,7 @@ static int recv_func_prehandle(struct ad
 			       struct recv_frame *rframe)
 {
 	int ret = _SUCCESS;
-	struct rx_pkt_attrib *pattrib = &rframe->attrib;
 	struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-	if (padapter->registrypriv.mp_mode == 1) {
-		if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) { /* padapter->mppriv.check_mp_pkt == 0)) */
-			if (pattrib->crc_err == 1)
-				padapter->mppriv.rx_crcerrpktcount++;
-			else
-				padapter->mppriv.rx_pktcount++;
-
-			if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == false) {
-				RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("MP - Not in loopback mode , drop pkt\n"));
-				ret = _FAIL;
-				rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
-				goto exit;
-			}
-		}
-	}
 
 	/* check the frame crtl field and decache */
 	ret = validate_recv_frame(padapter, rframe);
@@ -2152,11 +2129,6 @@ s32 rtw_recv_entry(struct recv_frame *pr
 	return ret;
 
 _recv_entry_drop:
-
-	if (padapter->registrypriv.mp_mode == 1)
-		padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
-
-
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_security.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_security.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_security.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_security.c	2014-09-28 17:29:07.000000000 -0400
@@ -189,7 +189,7 @@ void rtw_wep_encrypt(struct adapter *pad
 				arcfour_encrypt(&mycontext, payload+length, crc, 4);
 
 				pframe += pxmitpriv->frag_len;
-				pframe = (u8 *)RND4((size_t)(pframe));
+				pframe = (u8 *) round_up((size_t)(pframe), 4);
 			}
 		}
 	}
@@ -628,7 +628,7 @@ u32	rtw_tkip_encrypt(struct adapter *pad
 					arcfour_encrypt(&mycontext, payload+length, crc, 4);
 
 					pframe += pxmitpriv->frag_len;
-					pframe = (u8 *)RND4((size_t)(pframe));
+					pframe = (u8 *) round_up((size_t)(pframe), 4);
 				}
 			}
 		} else {
@@ -1081,13 +1081,13 @@ static int aes_cipher(u8 *key, uint hdrl
 
 	frsubtype = frsubtype>>4;
 
-	_rtw_memset((void *)mic_iv, 0, 16);
-	_rtw_memset((void *)mic_header1, 0, 16);
-	_rtw_memset((void *)mic_header2, 0, 16);
-	_rtw_memset((void *)ctr_preload, 0, 16);
-	_rtw_memset((void *)chain_buffer, 0, 16);
-	_rtw_memset((void *)aes_out, 0, 16);
-	_rtw_memset((void *)padded_buffer, 0, 16);
+	memset((void *)mic_iv, 0, 16);
+	memset((void *)mic_header1, 0, 16);
+	memset((void *)mic_header2, 0, 16);
+	memset((void *)ctr_preload, 0, 16);
+	memset((void *)chain_buffer, 0, 16);
+	memset((void *)aes_out, 0, 16);
+	memset((void *)padded_buffer, 0, 16);
 
 	if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
 		a4_exists = 0;
@@ -1242,7 +1242,7 @@ u32	rtw_aes_encrypt(struct adapter *pada
 
 					aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
 					pframe += pxmitpriv->frag_len;
-					pframe = (u8 *)RND4((size_t)(pframe));
+					pframe = (u8 *) round_up((size_t)(pframe), 8);
 				}
 			}
 		} else{
@@ -1279,13 +1279,13 @@ static int aes_decipher(u8 *key, uint	hd
 	uint	frsubtype  = GetFrameSubType(pframe);
 	frsubtype = frsubtype>>4;
 
-	_rtw_memset((void *)mic_iv, 0, 16);
-	_rtw_memset((void *)mic_header1, 0, 16);
-	_rtw_memset((void *)mic_header2, 0, 16);
-	_rtw_memset((void *)ctr_preload, 0, 16);
-	_rtw_memset((void *)chain_buffer, 0, 16);
-	_rtw_memset((void *)aes_out, 0, 16);
-	_rtw_memset((void *)padded_buffer, 0, 16);
+	memset((void *)mic_iv, 0, 16);
+	memset((void *)mic_header1, 0, 16);
+	memset((void *)mic_header2, 0, 16);
+	memset((void *)ctr_preload, 0, 16);
+	memset((void *)chain_buffer, 0, 16);
+	memset((void *)aes_out, 0, 16);
+	memset((void *)padded_buffer, 0, 16);
 
 	/* start to decrypt the payload */
 
@@ -1679,28 +1679,3 @@ do {									\
 	d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
 	d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]; \
 } while (0);
-
-/**
- * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
- * @key: 128-bit key for the hash operation
- * @data: Data buffer for which a MAC is determined
- * @data_len: Length of data buffer in bytes
- * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
- * Returns: 0 on success, -1 on failure
- *
- * This is a mode for using block cipher (AES in this case) for authentication.
- * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
- * (SP) 800-38B.
- */
-void rtw_use_tkipkey_handler(void *FunctionContext)
-{
-	struct adapter *padapter = (struct adapter *)FunctionContext;
-
-
-	RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler ^^^\n"));
-
-	padapter->securitypriv.busetkipkey = true;
-
-	RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler padapter->securitypriv.busetkipkey=%d^^^\n", padapter->securitypriv.busetkipkey));
-
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_sreset.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_sreset.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_sreset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_sreset.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,27 +19,14 @@
  ******************************************************************************/
 
 #include <rtw_sreset.h>
+#include <usb_ops_linux.h>
 
 void sreset_init_value(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
 
-	mutex_init(&psrtpriv->silentreset_mutex);
-	psrtpriv->silent_reset_inprogress = false;
 	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
-	psrtpriv->last_tx_time = 0;
-	psrtpriv->last_tx_complete_time = 0;
-}
-void sreset_reset_value(struct adapter *padapter)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
-	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
-	psrtpriv->silent_reset_inprogress = false;
-	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
-	psrtpriv->last_tx_time = 0;
-	psrtpriv->last_tx_complete_time = 0;
 }
 
 u8 sreset_get_wifi_status(struct adapter *padapter)
@@ -50,9 +37,7 @@ u8 sreset_get_wifi_status(struct adapter
 	u8 status = WIFI_STATUS_SUCCESS;
 	u32 val32 = 0;
 
-	if (psrtpriv->silent_reset_inprogress)
-		return status;
-	val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
+	val32 = usb_read32(padapter, REG_TXDMA_STATUS);
 	if (val32 == 0xeaeaeaea) {
 		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
 	} else if (val32 != 0) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c	2014-09-28 17:29:07.000000000 -0400
@@ -29,11 +29,11 @@
 
 static void _rtw_init_stainfo(struct sta_info *psta)
 {
-	_rtw_memset((u8 *)psta, 0, sizeof (struct sta_info));
+	memset((u8 *)psta, 0, sizeof (struct sta_info));
 
 	 spin_lock_init(&psta->lock);
-	_rtw_init_listhead(&psta->list);
-	_rtw_init_listhead(&psta->hash_list);
+	INIT_LIST_HEAD(&psta->list);
+	INIT_LIST_HEAD(&psta->hash_list);
 	_rtw_init_queue(&psta->sleep_q);
 	psta->sleepq_len = 0;
 
@@ -42,9 +42,9 @@ static void _rtw_init_stainfo(struct sta
 
 #ifdef CONFIG_88EU_AP_MODE
 
-	_rtw_init_listhead(&psta->asoc_list);
+	INIT_LIST_HEAD(&psta->asoc_list);
 
-	_rtw_init_listhead(&psta->auth_list);
+	INIT_LIST_HEAD(&psta->auth_list);
 
 	psta->expire_to = 0;
 
@@ -98,9 +98,9 @@ u32	_rtw_init_sta_priv(struct	sta_priv *
 	for (i = 0; i < NUM_STA; i++) {
 		_rtw_init_stainfo(psta);
 
-		_rtw_init_listhead(&(pstapriv->sta_hash[i]));
+		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
 
-		rtw_list_insert_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
+		list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
 
 		psta++;
 	}
@@ -110,8 +110,8 @@ u32	_rtw_init_sta_priv(struct	sta_priv *
 	pstapriv->sta_dz_bitmap = 0;
 	pstapriv->tim_bitmap = 0;
 
-	_rtw_init_listhead(&pstapriv->asoc_list);
-	_rtw_init_listhead(&pstapriv->auth_list);
+	INIT_LIST_HEAD(&pstapriv->asoc_list);
+	INIT_LIST_HEAD(&pstapriv->auth_list);
 	spin_lock_init(&pstapriv->asoc_list_lock);
 	spin_lock_init(&pstapriv->auth_list_lock);
 	pstapriv->asoc_list_cnt = 0;
@@ -157,7 +157,7 @@ static void rtw_mfree_all_stainfo(struct
 	phead = get_list_head(&pstapriv->free_sta_queue);
 	plist = phead->next;
 
-	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info , list);
 		plist = plist->next;
 	}
@@ -185,7 +185,7 @@ u32	_rtw_free_sta_priv(struct	sta_priv *
 			phead = &(pstapriv->sta_hash[index]);
 			plist = phead->next;
 
-			while ((rtw_end_of_queue_search(phead, plist)) == false) {
+			while (phead != plist) {
 				int i;
 				psta = container_of(plist, struct sta_info , hash_list);
 				plist = plist->next;
@@ -223,12 +223,12 @@ struct	sta_info *rtw_alloc_stainfo(struc
 
 	spin_lock_bh(&(pfree_sta_queue->lock));
 
-	if (_rtw_queue_empty(pfree_sta_queue) == true) {
+	if (list_empty(&pfree_sta_queue->queue)) {
 		spin_unlock_bh(&pfree_sta_queue->lock);
 		psta = NULL;
 	} else {
 		psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
-		rtw_list_delete(&(psta->list));
+		list_del_init(&(psta->list));
 		spin_unlock_bh(&pfree_sta_queue->lock);
 		_rtw_init_stainfo(psta);
 		memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
@@ -243,7 +243,7 @@ struct	sta_info *rtw_alloc_stainfo(struc
 
 		spin_lock_bh(&(pstapriv->sta_hash_lock));
 
-		rtw_list_insert_tail(&psta->hash_list, phash_list);
+		list_add_tail(&psta->hash_list, phash_list);
 
 		pstapriv->asoc_sta_count++;
 
@@ -317,23 +317,23 @@ u32	rtw_free_stainfo(struct adapter *pad
 
 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
 
-	rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
 
 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
 
-	rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
 
 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
 
-	rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
 
 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
 
-	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
 
 	spin_unlock_bh(&pxmitpriv->lock);
 
-	rtw_list_delete(&psta->hash_list);
+	list_del_init(&psta->hash_list);
 	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo  with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5]));
 	pstapriv->asoc_sta_count--;
 
@@ -362,13 +362,13 @@ u32	rtw_free_stainfo(struct adapter *pad
 		phead =		get_list_head(ppending_recvframe_queue);
 		plist = phead->next;
 
-		while (!rtw_is_list_empty(phead)) {
+		while (!list_empty(phead)) {
 			prhdr = container_of(plist, struct recv_frame, list);
 			prframe = (struct recv_frame *)prhdr;
 
 			plist = plist->next;
 
-			rtw_list_delete(&(prframe->list));
+			list_del_init(&(prframe->list));
 
 			rtw_free_recvframe(prframe, pfree_recv_queue);
 		}
@@ -382,8 +382,8 @@ u32	rtw_free_stainfo(struct adapter *pad
 #ifdef CONFIG_88EU_AP_MODE
 
 	spin_lock_bh(&pstapriv->auth_list_lock);
-	if (!rtw_is_list_empty(&psta->auth_list)) {
-		rtw_list_delete(&psta->auth_list);
+	if (!list_empty(&psta->auth_list)) {
+		list_del_init(&psta->auth_list);
 		pstapriv->auth_list_cnt--;
 	}
 	spin_unlock_bh(&pstapriv->auth_list_lock);
@@ -413,7 +413,7 @@ u32	rtw_free_stainfo(struct adapter *pad
 #endif	/*  CONFIG_88EU_AP_MODE */
 
 	spin_lock_bh(&(pfree_sta_queue->lock));
-	rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
+	list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
 	spin_unlock_bh(&pfree_sta_queue->lock);
 
 exit:
@@ -441,7 +441,7 @@ void rtw_free_all_stainfo(struct adapter
 		phead = &(pstapriv->sta_hash[index]);
 		plist = phead->next;
 
-		while ((!rtw_end_of_queue_search(phead, plist))) {
+		while (phead != plist) {
 			psta = container_of(plist, struct sta_info , hash_list);
 
 			plist = plist->next;
@@ -478,7 +478,7 @@ struct sta_info *rtw_get_stainfo(struct
 	phead = &(pstapriv->sta_hash[index]);
 	plist = phead->next;
 
-	while ((!rtw_end_of_queue_search(phead, plist))) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, hash_list);
 
 		if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
@@ -539,7 +539,7 @@ u8 rtw_access_ctrl(struct adapter *padap
 	spin_lock_bh(&(pacl_node_q->lock));
 	phead = get_list_head(pacl_node_q);
 	plist = phead->next;
-	while ((!rtw_end_of_queue_search(phead, plist))) {
+	while (phead != plist) {
 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 		plist = plist->next;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_wlan_util.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_wlan_util.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_wlan_util.c	2014-09-28 17:29:07.000000000 -0400
@@ -239,7 +239,7 @@ void get_rate_set(struct adapter *padapt
 {
 	unsigned char supportedrates[NumRates];
 
-	_rtw_memset(supportedrates, 0, NumRates);
+	memset(supportedrates, 0, NumRates);
 	*bssrate_len = ratetbl2rateset(padapter, supportedrates);
 	memcpy(pbssrate, supportedrates, *bssrate_len);
 }
@@ -541,7 +541,7 @@ void flush_all_cam_entry(struct adapter
 
 	rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
 
-	_rtw_memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
+	memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
 }
 
 int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
@@ -935,7 +935,7 @@ int rtw_check_bcn_info(struct adapter  *
 		return true;
 	}
 
-	bssid = (struct wlan_bssid_ex *)rtw_zmalloc(sizeof(struct wlan_bssid_ex));
+	bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_KERNEL);
 
 	subtype = GetFrameSubType(pframe) >> 4;
 
@@ -1222,7 +1222,7 @@ unsigned int is_ap_in_wep(struct adapter
 	}
 }
 
-int wifirate2_ratetbl_inx(unsigned char rate)
+static int wifirate2_ratetbl_inx(unsigned char rate)
 {
 	int	inx = 0;
 	rate = rate & 0x7f;
@@ -1357,16 +1357,7 @@ void set_sta_rate(struct adapter *padapt
 void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode)
 {
 	unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	/*	Added by Albert 2011/03/22 */
-	/*	In the P2P mode, the driver should not support the b mode. */
-	/*	So, the Tx packet shouldn't use the CCK rate */
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-#endif /* CONFIG_88EU_P2P */
-	_rtw_memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
+	memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
 	if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
 		memcpy(supported_rates, rtw_basic_rate_cck, 4);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/core/rtw_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/core/rtw_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,8 +23,6 @@
 #include <drv_types.h>
 #include <wifi.h>
 #include <osdep_intf.h>
-#include <usb_ops.h>
-#include <usb_osintf.h>
 #include <linux/vmalloc.h>
 
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
@@ -32,21 +30,21 @@ static u8 RFC1042_OUI[P80211_OUI_LEN] =
 
 static void _init_txservq(struct tx_servq *ptxservq)
 {
-	_rtw_init_listhead(&ptxservq->tx_pending);
+	INIT_LIST_HEAD(&ptxservq->tx_pending);
 	_rtw_init_queue(&ptxservq->sta_pending);
 	ptxservq->qcnt = 0;
 }
 
 void	_rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
 {
-	_rtw_memset((unsigned char *)psta_xmitpriv, 0, sizeof (struct sta_xmit_priv));
+	memset((unsigned char *)psta_xmitpriv, 0, sizeof (struct sta_xmit_priv));
 	spin_lock_init(&psta_xmitpriv->lock);
 	_init_txservq(&psta_xmitpriv->be_q);
 	_init_txservq(&psta_xmitpriv->bk_q);
 	_init_txservq(&psta_xmitpriv->vi_q);
 	_init_txservq(&psta_xmitpriv->vo_q);
-	_rtw_init_listhead(&psta_xmitpriv->legacy_dz);
-	_rtw_init_listhead(&psta_xmitpriv->apsd);
+	INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
+	INIT_LIST_HEAD(&psta_xmitpriv->apsd);
 
 }
 
@@ -101,7 +99,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 	pxframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf;
 
 	for (i = 0; i < NR_XMITFRAME; i++) {
-		_rtw_init_listhead(&(pxframe->list));
+		INIT_LIST_HEAD(&(pxframe->list));
 
 		pxframe->padapter = padapter;
 		pxframe->frame_tag = NULL_FRAMETAG;
@@ -111,7 +109,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 		pxframe->buf_addr = NULL;
 		pxframe->pxmitbuf = NULL;
 
-		rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
+		list_add_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
 
 		pxframe++;
 	}
@@ -139,7 +137,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
 
 	for (i = 0; i < NR_XMITBUFF; i++) {
-		_rtw_init_listhead(&pxmitbuf->list);
+		INIT_LIST_HEAD(&pxmitbuf->list);
 
 		pxmitbuf->priv_data = NULL;
 		pxmitbuf->padapter = padapter;
@@ -157,7 +155,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 
 		pxmitbuf->flags = XMIT_VO_QUEUE;
 
-		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
+		list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
 		pxmitbuf++;
 	}
 
@@ -179,7 +177,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
 
 	for (i = 0; i < num_xmit_extbuf; i++) {
-		_rtw_init_listhead(&pxmitbuf->list);
+		INIT_LIST_HEAD(&pxmitbuf->list);
 
 		pxmitbuf->priv_data = NULL;
 		pxmitbuf->padapter = padapter;
@@ -191,7 +189,7 @@ s32	_rtw_init_xmit_priv(struct xmit_priv
 			goto exit;
 		}
 
-		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
+		list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
 		pxmitbuf++;
 	}
 
@@ -234,9 +232,6 @@ void _rtw_free_xmit_priv (struct xmit_pr
 	u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 	u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
 
-
-	rtw_hal_free_xmit_priv(padapter);
-
 	if (pxmitpriv->pxmit_frame_buf == NULL)
 		return;
 
@@ -696,7 +691,7 @@ static s32 xmitframe_addmic(struct adapt
 			payload = pframe;
 
 			for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
-				payload = (u8 *)RND4((size_t)(payload));
+				payload = (u8 *) round_up((size_t)(payload), 4);
 				RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
 					 ("=== curfragnum=%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n",
 					 curfragnum, *payload, *(payload+1),
@@ -804,7 +799,7 @@ s32 rtw_make_wlanhdr (struct adapter *pa
 		}
 	}
 
-	_rtw_memset(hdr, 0, WLANHDR_OFFSET);
+	memset(hdr, 0, WLANHDR_OFFSET);
 
 	SetFrameSubType(fctrl, pattrib->subtype);
 
@@ -905,10 +900,10 @@ s32 rtw_txframes_pending(struct adapter
 {
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 
-	return ((_rtw_queue_empty(&pxmitpriv->be_pending) == false) ||
-			 (_rtw_queue_empty(&pxmitpriv->bk_pending) == false) ||
-			 (_rtw_queue_empty(&pxmitpriv->vi_pending) == false) ||
-			 (_rtw_queue_empty(&pxmitpriv->vo_pending) == false));
+	return (!list_empty(&pxmitpriv->be_pending.queue) ||
+			!list_empty(&pxmitpriv->bk_pending.queue) ||
+			!list_empty(&pxmitpriv->vi_pending.queue) ||
+			!list_empty(&pxmitpriv->vo_pending.queue));
 }
 
 s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pattrib)
@@ -1103,7 +1098,7 @@ s32 rtw_xmitframe_coalesce(struct adapte
 
 		addr = (size_t)(pframe);
 
-		mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;
+		mem_start = (unsigned char *) round_up(addr, 4) + hw_hdr_offset;
 		memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
 	}
 
@@ -1226,7 +1221,7 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(s
 
 	spin_lock_irqsave(&pfree_queue->lock, irql);
 
-	if (_rtw_queue_empty(pfree_queue) == true) {
+	if (list_empty(&pfree_queue->queue)) {
 		pxmitbuf = NULL;
 	} else {
 		phead = get_list_head(pfree_queue);
@@ -1235,7 +1230,7 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(s
 
 		pxmitbuf = container_of(plist, struct xmit_buf, list);
 
-		rtw_list_delete(&(pxmitbuf->list));
+		list_del_init(&(pxmitbuf->list));
 	}
 
 	if (pxmitbuf !=  NULL) {
@@ -1267,9 +1262,9 @@ s32 rtw_free_xmitbuf_ext(struct xmit_pri
 
 	spin_lock_irqsave(&pfree_queue->lock, irql);
 
-	rtw_list_delete(&pxmitbuf->list);
+	list_del_init(&pxmitbuf->list);
 
-	rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
+	list_add_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
 	pxmitpriv->free_xmit_extbuf_cnt++;
 
 	spin_unlock_irqrestore(&pfree_queue->lock, irql);
@@ -1290,7 +1285,7 @@ struct xmit_buf *rtw_alloc_xmitbuf(struc
 
 	spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
 
-	if (_rtw_queue_empty(pfree_xmitbuf_queue) == true) {
+	if (list_empty(&pfree_xmitbuf_queue->queue)) {
 		pxmitbuf = NULL;
 	} else {
 		phead = get_list_head(pfree_xmitbuf_queue);
@@ -1299,7 +1294,7 @@ struct xmit_buf *rtw_alloc_xmitbuf(struc
 
 		pxmitbuf = container_of(plist, struct xmit_buf, list);
 
-		rtw_list_delete(&(pxmitbuf->list));
+		list_del_init(&(pxmitbuf->list));
 	}
 
 	if (pxmitbuf !=  NULL) {
@@ -1334,9 +1329,9 @@ s32 rtw_free_xmitbuf(struct xmit_priv *p
 	} else {
 		spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
 
-		rtw_list_delete(&pxmitbuf->list);
+		list_del_init(&pxmitbuf->list);
 
-		rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
+		list_add_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
 
 		pxmitpriv->free_xmitbuf_cnt++;
 		spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
@@ -1373,7 +1368,7 @@ struct xmit_frame *rtw_alloc_xmitframe(s
 
 	spin_lock_bh(&pfree_xmit_queue->lock);
 
-	if (_rtw_queue_empty(pfree_xmit_queue) == true) {
+	if (list_empty(&pfree_xmit_queue->queue)) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt));
 		pxframe =  NULL;
 	} else {
@@ -1383,7 +1378,7 @@ struct xmit_frame *rtw_alloc_xmitframe(s
 
 		pxframe = container_of(plist, struct xmit_frame, list);
 
-		rtw_list_delete(&(pxframe->list));
+		list_del_init(&(pxframe->list));
 	}
 
 	if (pxframe !=  NULL) { /* default value setting */
@@ -1394,7 +1389,7 @@ struct xmit_frame *rtw_alloc_xmitframe(s
 		pxframe->buf_addr = NULL;
 		pxframe->pxmitbuf = NULL;
 
-		_rtw_memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
+		memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
 		/* pxframe->attrib.psta = NULL; */
 
 		pxframe->frame_tag = DATA_FRAMETAG;
@@ -1426,14 +1421,14 @@ s32 rtw_free_xmitframe(struct xmit_priv
 
 	spin_lock_bh(&pfree_xmit_queue->lock);
 
-	rtw_list_delete(&pxmitframe->list);
+	list_del_init(&pxmitframe->list);
 
 	if (pxmitframe->pkt) {
 		pndis_pkt = pxmitframe->pkt;
 		pxmitframe->pkt = NULL;
 	}
 
-	rtw_list_insert_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
+	list_add_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
 
 	pxmitpriv->free_xmitframe_cnt++;
 	RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt));
@@ -1460,7 +1455,7 @@ void rtw_free_xmitframe_queue(struct xmi
 	phead = get_list_head(pframequeue);
 	plist = phead->next;
 
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		pxmitframe = container_of(plist, struct xmit_frame, list);
 
 		plist = plist->next;
@@ -1491,12 +1486,12 @@ static struct xmit_frame *dequeue_one_xm
 	xmitframe_phead = get_list_head(pframe_queue);
 	xmitframe_plist = xmitframe_phead->next;
 
-	if (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+	if (xmitframe_phead != xmitframe_plist) {
 		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 		xmitframe_plist = xmitframe_plist->next;
 
-		rtw_list_delete(&pxmitframe->list);
+		list_del_init(&pxmitframe->list);
 
 		ptxservq->qcnt--;
 	}
@@ -1532,7 +1527,7 @@ struct xmit_frame *rtw_dequeue_xframe(st
 		sta_phead = get_list_head(phwxmit->sta_queue);
 		sta_plist = sta_phead->next;
 
-		while (!rtw_end_of_queue_search(sta_phead, sta_plist)) {
+		while (sta_phead != sta_plist) {
 			ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
 
 			pframe_queue = &ptxservq->sta_pending;
@@ -1543,8 +1538,8 @@ struct xmit_frame *rtw_dequeue_xframe(st
 				phwxmit->accnt--;
 
 				/* Remove sta node when there are no pending packets. */
-				if (_rtw_queue_empty(pframe_queue)) /* must be done after get_next and before break */
-					rtw_list_delete(&ptxservq->tx_pending);
+				if (list_empty(&pframe_queue->queue)) /* must be done after get_next and before break */
+					list_del_init(&ptxservq->tx_pending);
 				goto exit;
 			}
 
@@ -1622,10 +1617,10 @@ s32 rtw_xmit_classifier(struct adapter *
 
 	ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
 
-	if (rtw_is_list_empty(&ptxservq->tx_pending))
-		rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
+	if (list_empty(&ptxservq->tx_pending))
+		list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
 
-	rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
+	list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
 	ptxservq->qcnt++;
 	phwxmits[ac_index].accnt++;
 exit:
@@ -1641,7 +1636,7 @@ void rtw_alloc_hwxmits(struct adapter *p
 
 	pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
 
-	pxmitpriv->hwxmits = (struct hw_xmit *)rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry);
+	pxmitpriv->hwxmits = kzalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry, GFP_KERNEL);
 
 	hwxmits = pxmitpriv->hwxmits;
 
@@ -1676,127 +1671,6 @@ void rtw_init_hwxmits(struct hw_xmit *ph
 		phwxmit->accnt = 0;
 }
 
-static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb)
-{
-	struct sk_buff *skb = *pskb;
-	int res, is_vlan_tag = 0, i, do_nat25 = 1;
-	unsigned short vlan_hdr = 0;
-	void *br_port = NULL;
-
-	rcu_read_lock();
-	br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
-	rcu_read_unlock();
-	spin_lock_bh(&padapter->br_ext_lock);
-	if (!(skb->data[0] & 1) && br_port &&
-	    memcmp(skb->data+MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
-	    *((__be16 *)(skb->data+MACADDRLEN*2)) != __constant_htons(ETH_P_8021Q) &&
-	    *((__be16 *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP) &&
-	    !memcmp(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN) && padapter->scdb_entry) {
-		memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
-		padapter->scdb_entry->ageing_timer = jiffies;
-		spin_unlock_bh(&padapter->br_ext_lock);
-	} else {
-		if (*((__be16 *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_8021Q)) {
-			is_vlan_tag = 1;
-			vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2));
-			for (i = 0; i < 6; i++)
-				*((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2));
-			skb_pull(skb, 4);
-		}
-		if (!memcmp(skb->data+MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
-		    (*((__be16 *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP)))
-			memcpy(padapter->br_ip, skb->data+WLAN_ETHHDR_LEN+12, 4);
-
-		if (*((__be16 *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP)) {
-			if (memcmp(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN)) {
-				padapter->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(padapter,
-							skb->data+MACADDRLEN, skb->data+WLAN_ETHHDR_LEN+12);
-				if (padapter->scdb_entry) {
-					memcpy(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN);
-					memcpy(padapter->scdb_ip, skb->data+WLAN_ETHHDR_LEN+12, 4);
-					padapter->scdb_entry->ageing_timer = jiffies;
-					do_nat25 = 0;
-				}
-			} else {
-				if (padapter->scdb_entry) {
-					padapter->scdb_entry->ageing_timer = jiffies;
-					do_nat25 = 0;
-				} else {
-					memset(padapter->scdb_mac, 0, MACADDRLEN);
-					memset(padapter->scdb_ip, 0, 4);
-				}
-			}
-		}
-		spin_unlock_bh(&padapter->br_ext_lock);
-		if (do_nat25) {
-			if (nat25_db_handle(padapter, skb, NAT25_CHECK) == 0) {
-				struct sk_buff *newskb;
-
-				if (is_vlan_tag) {
-					skb_push(skb, 4);
-					for (i = 0; i < 6; i++)
-						*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
-					*((__be16 *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q);
-					*((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr;
-				}
-
-				newskb = skb_copy(skb, GFP_ATOMIC);
-				if (newskb == NULL) {
-					DEBUG_ERR("TX DROP: skb_copy fail!\n");
-					return -1;
-				}
-				dev_kfree_skb_any(skb);
-
-				*pskb = skb = newskb;
-				if (is_vlan_tag) {
-					vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2));
-					for (i = 0; i < 6; i++)
-						*((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2));
-					skb_pull(skb, 4);
-				}
-			}
-
-			if (skb_is_nonlinear(skb))
-				DEBUG_ERR("%s(): skb_is_nonlinear!!\n", __func__);
-
-			res = skb_linearize(skb);
-			if (res < 0) {
-					DEBUG_ERR("TX DROP: skb_linearize fail!\n");
-					return -1;
-			}
-
-			res = nat25_db_handle(padapter, skb, NAT25_INSERT);
-			if (res < 0) {
-				if (res == -2) {
-					DEBUG_ERR("TX DROP: nat25_db_handle fail!\n");
-					return -1;
-				}
-				return 0;
-			}
-		}
-
-		memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
-
-		dhcp_flag_bcast(padapter, skb);
-
-		if (is_vlan_tag) {
-			skb_push(skb, 4);
-			for (i = 0; i < 6; i++)
-				*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
-			*((__be16 *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q);
-			*((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr;
-		}
-	}
-
-	/*  check if SA is equal to our MAC */
-	if (memcmp(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN)) {
-		DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n",
-			  skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]);
-			return -1;
-	}
-	return 0;
-}
-
 u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
 {
 	u32 addr;
@@ -1856,8 +1730,6 @@ s32 rtw_xmit(struct adapter *padapter, s
 {
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct xmit_frame *pxmitframe = NULL;
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-	void *br_port = NULL;
 	s32 res;
 
 	pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
@@ -1867,18 +1739,6 @@ s32 rtw_xmit(struct adapter *padapter, s
 		return -1;
 	}
 
-	rcu_read_lock();
-	br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
-	rcu_read_unlock();
-
-	if (br_port && check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
-		res = rtw_br_client_tx(padapter, ppkt);
-		if (res == -1) {
-			rtw_free_xmitframe(pxmitpriv, pxmitframe);
-			return -1;
-		}
-	}
-
 	res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
 
 	if (res == _FAIL) {
@@ -1939,9 +1799,9 @@ int xmitframe_enqueue_for_sleeping_sta(s
 		spin_lock_bh(&psta->sleep_q.lock);
 
 		if (pstapriv->sta_dz_bitmap) {/* if any one sta is in ps mode */
-			rtw_list_delete(&pxmitframe->list);
+			list_del_init(&pxmitframe->list);
 
-			rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+			list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
 
 			psta->sleepq_len++;
 
@@ -1964,9 +1824,9 @@ int xmitframe_enqueue_for_sleeping_sta(s
 		u8 wmmps_ac = 0;
 
 		if (pstapriv->sta_dz_bitmap&BIT(psta->aid)) {
-			rtw_list_delete(&pxmitframe->list);
+			list_del_init(&pxmitframe->list);
 
-			rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+			list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
 
 			psta->sleepq_len++;
 
@@ -2023,7 +1883,7 @@ static void dequeue_xmitframes_to_sleepi
 	phead = get_list_head(pframequeue);
 	plist = phead->next;
 
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		pxmitframe = container_of(plist, struct xmit_frame, list);
 
 		plist = plist->next;
@@ -2058,21 +1918,21 @@ void stop_sta_xmit(struct adapter *padap
 	pstapriv->sta_dz_bitmap |= BIT(psta->aid);
 
 	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
-	rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
 
 	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
-	rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
 
 	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);
-	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
 
 	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);
-	rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
 
 	/* for BC/MC Frames */
 	pstaxmitpriv = &psta_bmc->sta_xmitpriv;
 	dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending);
-	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
 
 	spin_unlock_bh(&pxmitpriv->lock);
 }
@@ -2090,12 +1950,12 @@ void wakeup_sta_to_xmit(struct adapter *
 	xmitframe_phead = get_list_head(&psta->sleep_q);
 	xmitframe_plist = xmitframe_phead->next;
 
-	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+	while (xmitframe_phead != xmitframe_plist) {
 		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 		xmitframe_plist = xmitframe_plist->next;
 
-		rtw_list_delete(&pxmitframe->list);
+		list_del_init(&pxmitframe->list);
 
 		switch (pxmitframe->attrib.priority) {
 		case 1:
@@ -2171,12 +2031,12 @@ void wakeup_sta_to_xmit(struct adapter *
 		xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
 		xmitframe_plist = xmitframe_phead->next;
 
-		while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+		while (xmitframe_phead != xmitframe_plist) {
 			pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 			xmitframe_plist = xmitframe_plist->next;
 
-			rtw_list_delete(&pxmitframe->list);
+			list_del_init(&pxmitframe->list);
 
 			psta_bmc->sleepq_len--;
 			if (psta_bmc->sleepq_len > 0)
@@ -2218,7 +2078,7 @@ void xmit_delivery_enabled_frames(struct
 	xmitframe_phead = get_list_head(&psta->sleep_q);
 	xmitframe_plist = xmitframe_phead->next;
 
-	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+	while (xmitframe_phead != xmitframe_plist) {
 		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 
 		xmitframe_plist = xmitframe_plist->next;
@@ -2246,7 +2106,7 @@ void xmit_delivery_enabled_frames(struct
 		if (!wmmps_ac)
 			continue;
 
-		rtw_list_delete(&pxmitframe->list);
+		list_del_init(&pxmitframe->list);
 
 		psta->sleepq_len--;
 		psta->sleepq_ac_len--;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c	2014-09-28 17:29:07.000000000 -0400
@@ -358,19 +358,19 @@ static int odm_ARFBRefresh_8188E(struct
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0000000d;
 		break;
 	case 12:
-		MaskFromReg = rtw_read32(adapt, REG_ARFR0);
+		MaskFromReg = usb_read32(adapt, REG_ARFR0);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 13:
-		MaskFromReg = rtw_read32(adapt, REG_ARFR1);
+		MaskFromReg = usb_read32(adapt, REG_ARFR1);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 14:
-		MaskFromReg = rtw_read32(adapt, REG_ARFR2);
+		MaskFromReg = usb_read32(adapt, REG_ARFR2);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	case 15:
-		MaskFromReg = rtw_read32(adapt, REG_ARFR3);
+		MaskFromReg = usb_read32(adapt, REG_ARFR3);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
 		break;
 	default:
@@ -670,7 +670,7 @@ void ODM_RA_Set_TxRPT_Time(struct odm_dm
 {
 	struct adapter *adapt = dm_odm->Adapter;
 
-	rtw_write16(adapt, REG_TX_RPT_TIME, minRptTime);
+	usb_write16(adapt, REG_TX_RPT_TIME, minRptTime);
 }
 
 void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/hal_com.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/hal_com.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/hal_com.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/hal_com.c	2014-09-28 17:29:07.000000000 -0400
@@ -319,63 +319,3 @@ void hal_init_macaddr(struct adapter *ad
 	rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR,
 			  adapter->eeprompriv.mac_addr);
 }
-
-/*
-* C2H event format:
-* Field	 TRIGGER		CONTENT	   CMD_SEQ	CMD_LEN		 CMD_ID
-* BITS	 [127:120]	[119:16]      [15:8]		  [7:4]		   [3:0]
-*/
-
-void c2h_evt_clear(struct adapter *adapter)
-{
-	rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
-}
-
-s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
-{
-	s32 ret = _FAIL;
-	struct c2h_evt_hdr *c2h_evt;
-	int i;
-	u8 trigger;
-
-	if (buf == NULL)
-		goto exit;
-
-	trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
-
-	if (trigger == C2H_EVT_HOST_CLOSE)
-		goto exit; /* Not ready */
-	else if (trigger != C2H_EVT_FW_CLOSE)
-		goto clear_evt; /* Not a valid value */
-
-	c2h_evt = (struct c2h_evt_hdr *)buf;
-
-	_rtw_memset(c2h_evt, 0, 16);
-
-	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
-	*(buf+1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
-
-	RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read(): ",
-		      &c2h_evt , sizeof(c2h_evt));
-
-	/* Read the content */
-	for (i = 0; i < c2h_evt->plen; i++)
-		c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
-						sizeof(*c2h_evt) + i);
-
-	RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
-		      "c2h_evt_read(): Command Content:\n",
-		      c2h_evt->payload, c2h_evt->plen);
-
-	ret = _SUCCESS;
-
-clear_evt:
-	/*
-	* Clear event to notify FW we have read the command.
-	* If this field isn't clear, the FW won't update the next
-	* command message.
-	*/
-	c2h_evt_clear(adapter);
-exit:
-	return ret;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/hal_intf.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/hal_intf.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/hal_intf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/hal_intf.c	2014-09-28 17:29:07.000000000 -0400
@@ -156,15 +156,6 @@ void rtw_hal_set_odm_var(struct adapter
 						      val1, set);
 }
 
-void rtw_hal_get_odm_var(struct adapter *adapt,
-			 enum hal_odm_variable var, void *val1,
-			 bool set)
-{
-	if (adapt->HalFunc.GetHalODMVarHandler)
-		adapt->HalFunc.GetHalODMVarHandler(adapt, var,
-						      val1, set);
-}
-
 void rtw_hal_enable_interrupt(struct adapter *adapt)
 {
 	if (adapt->HalFunc.enable_interrupt)
@@ -223,12 +214,6 @@ s32 rtw_hal_init_xmit_priv(struct adapte
 	return _FAIL;
 }
 
-void rtw_hal_free_xmit_priv(struct adapter *adapt)
-{
-	if (adapt->HalFunc.free_xmit_priv != NULL)
-		adapt->HalFunc.free_xmit_priv(adapt);
-}
-
 s32 rtw_hal_init_recv_priv(struct adapter *adapt)
 {
 	if (adapt->HalFunc.init_recv_priv)
@@ -271,20 +256,6 @@ void rtw_hal_add_ra_tid(struct adapter *
 					       rssi_level);
 }
 
-/*	Start specifical interface thread		*/
-void rtw_hal_start_thread(struct adapter *adapt)
-{
-	if (adapt->HalFunc.run_thread)
-		adapt->HalFunc.run_thread(adapt);
-}
-
-/*	Start specifical interface thread		*/
-void rtw_hal_stop_thread(struct adapter *adapt)
-{
-	if (adapt->HalFunc.cancel_thread)
-		adapt->HalFunc.cancel_thread(adapt);
-}
-
 u32 rtw_hal_read_bbreg(struct adapter *adapt, u32 regaddr, u32 bitmask)
 {
 	u32 data = 0;
@@ -374,30 +345,6 @@ void rtw_hal_sreset_init(struct adapter
 		adapt->HalFunc.sreset_init_value(adapt);
 }
 
-void rtw_hal_sreset_reset(struct adapter *adapt)
-{
-	if (adapt->HalFunc.silentreset)
-		adapt->HalFunc.silentreset(adapt);
-}
-
-void rtw_hal_sreset_reset_value(struct adapter *adapt)
-{
-	if (adapt->HalFunc.sreset_reset_value)
-		adapt->HalFunc.sreset_reset_value(adapt);
-}
-
-void rtw_hal_sreset_xmit_status_check(struct adapter *adapt)
-{
-	if (adapt->HalFunc.sreset_xmit_status_check)
-		adapt->HalFunc.sreset_xmit_status_check(adapt);
-}
-
-void rtw_hal_sreset_linked_status_check(struct adapter *adapt)
-{
-	if (adapt->HalFunc.sreset_linked_status_check)
-		adapt->HalFunc.sreset_linked_status_check(adapt);
-}
-
 u8   rtw_hal_sreset_get_wifi_status(struct adapter *adapt)
 {
 	u8 status = 0;
@@ -428,17 +375,3 @@ void rtw_hal_reset_security_engine(struc
 	if (adapter->HalFunc.hal_reset_security_engine)
 		adapter->HalFunc.hal_reset_security_engine(adapter);
 }
-
-s32 rtw_hal_c2h_handler(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt)
-{
-	s32 ret = _FAIL;
-
-	if (adapter->HalFunc.c2h_handler)
-		ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
-	return ret;
-}
-
-c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter)
-{
-	return adapter->HalFunc.c2h_id_filter_ccx;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c	2014-09-28 17:29:07.000000000 -0400
@@ -1,5 +1,4 @@
-
-/******************************************************************************
+/*
  *
  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  *
@@ -15,39 +14,47 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
+ */
 
 #include "odm_precomp.h"
 
-/*---------------------------Define Local Constant---------------------------*/
 /*  2010/04/25 MH Define the max tx power tracking tx agc power. */
 #define		ODM_TXPWRTRACK_MAX_IDX_88E		6
 
-/*---------------------------Define Local Constant---------------------------*/
 
-/* 3============================================================ */
+static u8 ODM_GetRightChnlPlaceforIQK(u8 chnl)
+{
+	u8	channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
+		100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
+		124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
+		155, 157, 159, 161, 163, 165
+	};
+	u8	place = chnl;
+
+	if (chnl > 14) {
+		for (place = 14; place < sizeof(channel_all); place++) {
+			if (channel_all[place] == chnl)
+				return place-13;
+		}
+	}
+	return 0;
+}
+
 /* 3 Tx Power Tracking */
-/* 3============================================================ */
-/*-----------------------------------------------------------------------------
+/*
  * Function:	ODM_TxPwrTrackAdjust88E()
  *
  * Overview:	88E we can not write 0xc80/c94/c4c/ 0xa2x. Instead of write TX agc.
  *				No matter OFDM & CCK use the same method.
  *
- * Input:		NONE
- *
- * Output:		NONE
- *
- * Return:		NONE
- *
  * Revised History:
  *	When		Who		Remark
  *	04/23/2012	MHC		Create Version 0.
  *	04/23/2012	MHC		Adjust TX agc directly not throughput BB digital.
  *
- *---------------------------------------------------------------------------*/
+ */
 void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *dm_odm, u8 Type,/*  0 = OFDM, 1 = CCK */
 	u8 *pDirection, 		/*  1 = +(increase) 2 = -(decrease) */
 	u32 *pOutWriteVal		/*  Tx tracking CCK/OFDM BB swing index adjust */
@@ -96,23 +103,12 @@ void ODM_TxPwrTrackAdjust88E(struct odm_
 	*pOutWriteVal = pwr_value | (pwr_value<<8) | (pwr_value<<16) | (pwr_value<<24);
 }	/*  ODM_TxPwrTrackAdjust88E */
 
-/*-----------------------------------------------------------------------------
+/*
  * Function:	odm_TxPwrTrackSetPwr88E()
  *
  * Overview:	88E change all channel tx power accordign to flag.
  *				OFDM & CCK are all different.
- *
- * Input:		NONE
- *
- * Output:		NONE
- *
- * Return:		NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	04/23/2012	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+ */
 static void odm_TxPwrTrackSetPwr88E(struct odm_dm_struct *dm_odm)
 {
 	if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
@@ -123,7 +119,6 @@ static void odm_TxPwrTrackSetPwr88E(stru
 	}
 }	/*  odm_TxPwrTrackSetPwr88E */
 
-/* 091212 chiyokolin */
 void
 odm_TXPowerTrackingCallback_ThermalMeter_8188E(
 	struct adapter *Adapter
@@ -455,8 +450,6 @@ odm_TXPowerTrackingCallback_ThermalMeter
 		}
 
 		if (delta_IQK >= 8) { /*  Delta temperature is equal to or larger than 20 centigrade. */
-			ODM_ResetIQKResult(dm_odm);
-
 			dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
 			PHY_IQCalibrate_8188E(Adapter, false);
 		}
@@ -471,7 +464,6 @@ odm_TXPowerTrackingCallback_ThermalMeter
 
 /* 1 7.	IQK */
 #define MAX_TOLERANCE		5
-#define IQK_DELAY_TIME		1		/* ms */
 
 static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
 phy_PathA_IQK_8188E(struct adapter *adapt, bool configPathB)
@@ -827,9 +819,9 @@ static void _PHY_SaveMACRegisters(
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save MAC parameters.\n"));
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		MACBackup[i] = rtw_read8(adapt, MACReg[i]);
+		MACBackup[i] = usb_read8(adapt, MACReg[i]);
 	}
-	MACBackup[i] = rtw_read32(adapt, MACReg[i]);
+	MACBackup[i] = usb_read32(adapt, MACReg[i]);
 }
 
 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
@@ -856,9 +848,9 @@ _PHY_ReloadMACRegisters(
 
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("Reload MAC parameters !\n"));
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		rtw_write8(adapt, MACReg[i], (u8)MACBackup[i]);
+		usb_write8(adapt, MACReg[i], (u8)MACBackup[i]);
 	}
-	rtw_write32(adapt, MACReg[i], MACBackup[i]);
+	usb_write32(adapt, MACReg[i], MACBackup[i]);
 }
 
 void
@@ -900,12 +892,12 @@ _PHY_MACSettingCalibration(
 
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("MAC settings for Calibration.\n"));
 
-	rtw_write8(adapt, MACReg[i], 0x3F);
+	usb_write8(adapt, MACReg[i], 0x3F);
 
 	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
-		rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
+		usb_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
 	}
-	rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
+	usb_write8(adapt, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
 }
 
 void
@@ -1213,12 +1205,12 @@ static void phy_LCCalibrate_8188E(struct
 	u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
 
 	/* Check continuous TX and Packet TX */
-	tmpreg = rtw_read8(adapt, 0xd03);
+	tmpreg = usb_read8(adapt, 0xd03);
 
 	if ((tmpreg&0x70) != 0)			/* Deal with contisuous TX case */
-		rtw_write8(adapt, 0xd03, tmpreg&0x8F);	/* disable all continuous TX */
+		usb_write8(adapt, 0xd03, tmpreg&0x8F);	/* disable all continuous TX */
 	else							/*  Deal with Packet TX case */
-		rtw_write8(adapt, REG_TXPAUSE, 0xFF);			/*  block all queues */
+		usb_write8(adapt, REG_TXPAUSE, 0xFF);			/*  block all queues */
 
 	if ((tmpreg&0x70) != 0) {
 		/* 1. Read original RF mode */
@@ -1250,7 +1242,7 @@ static void phy_LCCalibrate_8188E(struct
 	if ((tmpreg&0x70) != 0) {
 		/* Deal with continuous TX case */
 		/* Path-A */
-		rtw_write8(adapt, 0xd03, tmpreg);
+		usb_write8(adapt, 0xd03, tmpreg);
 		PHY_SetRFReg(adapt, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
 
 		/* Path-B */
@@ -1258,7 +1250,7 @@ static void phy_LCCalibrate_8188E(struct
 			PHY_SetRFReg(adapt, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
 	} else {
 		/*  Deal with Packet TX case */
-		rtw_write8(adapt, REG_TXPAUSE, 0x00);
+		usb_write8(adapt, REG_TXPAUSE, 0x00);
 	}
 }
 
@@ -1266,7 +1258,6 @@ void PHY_IQCalibrate_8188E(struct adapte
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-	struct mpt_context *pMptCtx = &(adapt->mppriv.MptCtx);
 	s32 result[4][8];	/* last is final result */
 	u8 i, final_candidate, Indexforchannel;
 	bool pathaok, pathbok;
@@ -1286,11 +1277,6 @@ void PHY_IQCalibrate_8188E(struct adapte
 	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
 		return;
 
-	if (*(dm_odm->mp_mode) == 1) {
-		singletone = pMptCtx->bSingleTone;
-		carrier_sup = pMptCtx->bCarrierSuppression;
-	}
-
 	/*  20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
 	if (singletone || carrier_sup)
 		return;
@@ -1418,12 +1404,7 @@ void PHY_LCCalibrate_8188E(struct adapte
 	u32 timeout = 2000, timecount = 0;
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-	struct mpt_context *pMptCtx = &(adapt->mppriv.MptCtx);
 
-	if (*(dm_odm->mp_mode) == 1) {
-		singletone = pMptCtx->bSingleTone;
-		carrier_sup = pMptCtx->bCarrierSuppression;
-	}
 	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
 		return;
 	/*  20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
@@ -1454,8 +1435,8 @@ static void phy_setrfpathswitch_8188e(st
 {
 	if (!adapt->hw_init_completed) {
 		u8 u1btmp;
-		u1btmp = rtw_read8(adapt, REG_LEDCFG2) | BIT7;
-		rtw_write8(adapt, REG_LEDCFG2, u1btmp);
+		u1btmp = usb_read8(adapt, REG_LEDCFG2) | BIT7;
+		usb_write8(adapt, REG_LEDCFG2, u1btmp);
 		PHY_SetBBReg(adapt, rFPGA0_XAB_RFParameter, BIT13, 0x01);
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPhyRf.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-
- #include "odm_precomp.h"
-
-/* 3============================================================ */
-/* 3 IQ Calibration */
-/* 3============================================================ */
-
-void ODM_ResetIQKResult(struct odm_dm_struct *pDM_Odm)
-{
-}
-
-u8 ODM_GetRightChnlPlaceforIQK(u8 chnl)
-{
-	u8	channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
-		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
-		100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
-		124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
-		155, 157, 159, 161, 163, 165
-	};
-	u8	place = chnl;
-
-	if (chnl > 14) {
-		for (place = 14; place < sizeof(channel_all); place++) {
-			if (channel_all[place] == chnl)
-				return place-13;
-		}
-	}
-	return 0;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -35,6 +35,7 @@ Major Change History:
 --*/
 
 #include <HalPwrSeqCmd.h>
+#include <usb_ops_linux.h>
 
 /*	Description: */
 /*		This routine deals with the Power Configuration CMDs parsing
@@ -80,13 +81,13 @@ u8 HalPwrSeqCmdParsing(struct adapter *p
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 
 				/*  Read the value from system register */
-				value = rtw_read8(padapter, offset);
+				value = usb_read8(padapter, offset);
 
 				value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
 				value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
 
 				/*  Write the value back to system register */
-				rtw_write8(padapter, offset, value);
+				usb_write8(padapter, offset, value);
 				break;
 			case PWR_CMD_POLLING:
 				RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_POLLING\n"));
@@ -94,7 +95,7 @@ u8 HalPwrSeqCmdParsing(struct adapter *p
 				poll_bit = false;
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 				do {
-						value = rtw_read8(padapter, offset);
+						value = usb_read8(padapter, offset);
 
 					value &= GET_PWR_CFG_MASK(pwrcfgcmd);
 					if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/odm.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/odm.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/odm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/odm.c	2014-09-28 17:29:07.000000000 -0400
@@ -221,7 +221,6 @@ void ODM_DMWatchdog(struct odm_dm_struct
 
 	ODM_TXPowerTrackingCheck(pDM_Odm);
 	odm_EdcaTurboCheck(pDM_Odm);
-	odm_DynamicTxPower(pDM_Odm);
 }
 
 /*  Init /.. Fixed HW value. Only init time. */
@@ -833,7 +832,7 @@ void ODM_Write_CCK_CCA_Thres(struct odm_
 	struct adapter *adapt = pDM_Odm->Adapter;
 
 	if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)		/* modify by Guo.Mingzhi 2012-01-03 */
-		rtw_write8(adapt, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres);
+		usb_write8(adapt, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres);
 	pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
 	pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
 }
@@ -1110,19 +1109,6 @@ void odm_DynamicTxPowerInit(struct odm_d
 	pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
 }
 
-void odm_DynamicTxPower(struct odm_dm_struct *pDM_Odm)
-{
-	/*  For AP/ADSL use struct rtl8192cd_priv * */
-	/*  For CE/NIC use struct adapter * */
-
-	if (!(pDM_Odm->SupportAbility & ODM_BB_DYNAMIC_TXPWR))
-		return;
-
-	/*  2012/01/12 MH According to Luke's suggestion, only high power will support the feature. */
-	if (!pDM_Odm->ExtPA)
-		return;
-}
-
 /* 3============================================================ */
 /* 3 RSSI Monitor */
 /* 3============================================================ */
@@ -1291,10 +1277,10 @@ void ODM_EdcaTurboInit(struct odm_dm_str
 	pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
 	Adapter->recvpriv.bIsAnyNonBEPkts = false;
 
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_VO_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_VI_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_BE_PARAM)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", rtw_read32(Adapter, ODM_EDCA_BK_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VO_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VI_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BE_PARAM)));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BK_PARAM)));
 }	/*  ODM_InitEdcaTurbo */
 
 void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm)
@@ -1363,7 +1349,7 @@ void odm_EdcaTurboCheckCE(struct odm_dm_
 			else
 				edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
 
-			rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
+			usb_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
 
 			pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
 		}
@@ -1373,7 +1359,7 @@ void odm_EdcaTurboCheckCE(struct odm_dm_
 		/*  Turn Off EDCA turbo here. */
 		/*  Restore original EDCA according to the declaration of AP. */
 		 if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
-			rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
+			usb_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
 			pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c	2014-09-28 17:29:07.000000000 -0400
@@ -68,7 +68,7 @@ void odm_ConfigMAC_8188E(struct odm_dm_s
 {
 	struct adapter *adapt = pDM_Odm->Adapter;
 
-	rtw_write8(adapt, Addr, Data);
+	usb_write8(adapt, Addr, Data);
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigMACWithHeaderFile: [MAC_REG] %08X %08X\n", Addr, Data));
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,6 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <recv_osdep.h>
-#include <cmd_osdep.h>
 #include <mlme_osdep.h>
 #include <rtw_ioctl_set.h>
 
@@ -41,7 +40,7 @@ static u8 _is_fw_read_cmd_down(struct ad
 	u8 valid;
 
 	do {
-		valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
+		valid = usb_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
 		if (0 == valid)
 			read_down = true;
 	} while ((!read_down) && (retry_cnts--));
@@ -106,13 +105,13 @@ static s32 FillH2CCmd_88E(struct adapter
 			/* Write Ext command */
 			msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
 			for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++) {
-				rtw_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
+				usb_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
 			}
 		}
 		/*  Write command */
 		msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
 		for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++) {
-			rtw_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
+			usb_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
 		}
 		bcmd_down = true;
 
@@ -153,7 +152,7 @@ u8 rtl8188e_set_raid_cmd(struct adapter
 	if (haldata->fw_ractrl) {
 		__le32 lmask;
 
-		_rtw_memset(buf, 0, 3);
+		memset(buf, 0, 3);
 		lmask = cpu_to_le32(mask);
 		memcpy(buf, &lmask, 3);
 
@@ -476,12 +475,6 @@ static void ConstructProbeRsp(struct ada
 	*pLength = pktlen;
 }
 
-/*  To check if reserved page content is destroyed by beacon because beacon is too large. */
-/*  2010.06.23. Added by tynli. */
-void CheckFwRsvdPageContent(struct adapter *Adapter)
-{
-}
-
 /*  */
 /*  Description: Fill the reserved packets that FW will use to RSVD page. */
 /*			Now we just send 4 types packet to rsvd page. */
@@ -509,7 +502,7 @@ static void SetFwRsvdPagePkt(struct adap
 	struct rsvdpage_loc RsvdPageLoc;
 
 	DBG_88E("%s\n", __func__);
-	ReservedPagePacket = (u8 *)rtw_zmalloc(1000);
+	ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
 	if (ReservedPagePacket == NULL) {
 		DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__);
 		return;
@@ -615,18 +608,18 @@ void rtl8188e_set_FwJoinBssReport_cmd(st
 	if (mstatus == 1) {
 		/*  We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
 		/*  Suggested by filen. Added by tynli. */
-		rtw_write16(adapt, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
+		usb_write16(adapt, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
 		/*  Do not set TSF again here or vWiFi beacon DMA INT will not work. */
 
 		/* Set REG_CR bit 8. DMA beacon by SW. */
 		haldata->RegCR_1 |= BIT0;
-		rtw_write8(adapt,  REG_CR+1, haldata->RegCR_1);
+		usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
 
 		/*  Disable Hw protection for a time which revserd for Hw sending beacon. */
 		/*  Fix download reserved page packet fail that access collision with the protection time. */
 		/*  2010.05.11. Added by tynli. */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)|BIT(4));
+		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
+		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(4));
 
 		if (haldata->RegFwHwTxQCtrl&BIT6) {
 			DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
@@ -634,7 +627,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(st
 		}
 
 		/*  Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
-		rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT6)));
+		usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT6)));
 		haldata->RegFwHwTxQCtrl &= (~BIT6);
 
 		/*  Clear beacon valid check bit. */
@@ -668,8 +661,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(st
 		/*  */
 
 		/*  Enable Bcn */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)|BIT(3));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
+		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(3));
+		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
 
 		/*  To make sure that if there exists an adapter which would like to send beacon. */
 		/*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
@@ -677,7 +670,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(st
 		/*  the beacon cannot be sent by HW. */
 		/*  2010.06.23. Added by tynli. */
 		if (bSendBeacon) {
-			rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl|BIT6));
+			usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl|BIT6));
 			haldata->RegFwHwTxQCtrl |= BIT6;
 		}
 
@@ -690,78 +683,6 @@ void rtl8188e_set_FwJoinBssReport_cmd(st
 		/*  Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
 		/*  Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
 		haldata->RegCR_1 &= (~BIT0);
-		rtw_write8(adapt,  REG_CR+1, haldata->RegCR_1);
-	}
-}
-
-void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state)
-{
-#ifdef CONFIG_88EU_P2P
-	struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
-	struct wifidirect_info	*pwdinfo = &(adapt->wdinfo);
-	struct P2P_PS_Offload_t	*p2p_ps_offload = &haldata->p2p_ps_offload;
-	u8 i;
-
-
-	switch (p2p_ps_state) {
-	case P2P_PS_DISABLE:
-		DBG_88E("P2P_PS_DISABLE\n");
-		_rtw_memset(p2p_ps_offload, 0, 1);
-		break;
-	case P2P_PS_ENABLE:
-		DBG_88E("P2P_PS_ENABLE\n");
-		/*  update CTWindow value. */
-		if (pwdinfo->ctwindow > 0) {
-			p2p_ps_offload->CTWindow_En = 1;
-			rtw_write8(adapt, REG_P2P_CTWIN, pwdinfo->ctwindow);
-		}
-
-		/*  hw only support 2 set of NoA */
-		for (i = 0; i < pwdinfo->noa_num; i++) {
-			/*  To control the register setting for which NOA */
-			rtw_write8(adapt, REG_NOA_DESC_SEL, (i << 4));
-			if (i == 0)
-				p2p_ps_offload->NoA0_En = 1;
-			else
-				p2p_ps_offload->NoA1_En = 1;
-
-			/*  config P2P NoA Descriptor Register */
-			rtw_write32(adapt, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
-			rtw_write32(adapt, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
-			rtw_write32(adapt, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
-			rtw_write8(adapt, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
-		}
-
-		if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
-			/*  rst p2p circuit */
-			rtw_write8(adapt, REG_DUAL_TSF_RST, BIT(4));
-
-			p2p_ps_offload->Offload_En = 1;
-
-			if (pwdinfo->role == P2P_ROLE_GO) {
-				p2p_ps_offload->role = 1;
-				p2p_ps_offload->AllStaSleep = 0;
-			} else {
-				p2p_ps_offload->role = 0;
-			}
-
-			p2p_ps_offload->discovery = 0;
-		}
-		break;
-	case P2P_PS_SCAN:
-		DBG_88E("P2P_PS_SCAN\n");
-		p2p_ps_offload->discovery = 1;
-		break;
-	case P2P_PS_SCAN_DONE:
-		DBG_88E("P2P_PS_SCAN_DONE\n");
-		p2p_ps_offload->discovery = 0;
-		pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
-		break;
-	default:
-		break;
+		usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
 	}
-
-	FillH2CCmd_88E(adapt, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);
-#endif
-
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c	2014-09-28 17:29:07.000000000 -0400
@@ -36,10 +36,10 @@ static void dm_InitGPIOSetting(struct ad
 {
 	u8	tmp1byte;
 
-	tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
+	tmp1byte = usb_read8(Adapter, REG_GPIO_MUXCFG);
 	tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
 
-	rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
+	usb_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
 }
 
 /*  */
@@ -53,7 +53,7 @@ static void Init_ODM_ComInfo_88E(struct
 	u8 cut_ver, fab_ver;
 
 	/*  Init Value */
-	_rtw_memset(dm_odm, 0, sizeof(*dm_odm));
+	memset(dm_odm, 0, sizeof(*dm_odm));
 
 	dm_odm->Adapter = Adapter;
 
@@ -198,7 +198,7 @@ void rtl8188e_init_dm_priv(struct adapte
 	struct dm_priv	*pdmpriv = &hal_data->dmpriv;
 	struct odm_dm_struct *podmpriv = &hal_data->odmpriv;
 
-	_rtw_memset(pdmpriv, 0, sizeof(struct dm_priv));
+	memset(pdmpriv, 0, sizeof(struct dm_priv));
 	Init_ODM_ComInfo_88E(Adapter);
 	ODM_InitDebugSetting(podmpriv);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c	2014-08-07 04:56:38.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c	2014-09-28 21:38:48.000000000 -0400
@@ -28,16 +28,14 @@
 
 #include <rtw_iol.h>
 
-#include <usb_ops.h>
-
-static void iol_mode_enable(struct adapter *padapter, u8 enable)
+void iol_mode_enable(struct adapter *padapter, u8 enable)
 {
 	u8 reg_0xf0 = 0;
 
 	if (enable) {
 		/* Enable initial offload */
-		reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
-		rtw_write8(padapter, REG_SYS_CFG, reg_0xf0|SW_OFFLOAD_EN);
+		reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
+		usb_write8(padapter, REG_SYS_CFG, reg_0xf0|SW_OFFLOAD_EN);
 
 		if (!padapter->bFWReady) {
 			DBG_88E("bFWReady == false call reset 8051...\n");
@@ -46,28 +44,28 @@ static void iol_mode_enable(struct adapt
 
 	} else {
 		/* disable initial offload */
-		reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
-		rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
+		reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
+		usb_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
 	}
 }
 
-static s32 iol_execute(struct adapter *padapter, u8 control)
+s32 iol_execute(struct adapter *padapter, u8 control)
 {
 	s32 status = _FAIL;
 	u8 reg_0x88 = 0;
 	u32 start = 0, passing_time = 0;
 
 	control = control&0x0f;
-	reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
-	rtw_write8(padapter, REG_HMEBOX_E0,  reg_0x88|control);
+	reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
+	usb_write8(padapter, REG_HMEBOX_E0,  reg_0x88|control);
 
 	start = jiffies;
-	while ((reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0)) & control &&
+	while ((reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0)) & control &&
 	       (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
 		;
 	}
 
-	reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
+	reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
 	status = (reg_0x88 & control) ? _FAIL : _SUCCESS;
 	if (reg_0x88 & control<<4)
 		status = _FAIL;
@@ -78,233 +76,12 @@ static s32 iol_InitLLTTable(struct adapt
 {
 	s32 rst = _SUCCESS;
 	iol_mode_enable(padapter, 1);
-	rtw_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
+	usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
 	rst = iol_execute(padapter, CMD_INIT_LLT);
 	iol_mode_enable(padapter, 0);
 	return rst;
 }
 
-static void
-efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
-{
-	u8 *efuseTbl = NULL;
-	u8 rtemp8;
-	u16	eFuse_Addr = 0;
-	u8 offset, wren;
-	u16	i, j;
-	u16	**eFuseWord = NULL;
-	u16	efuse_utilized = 0;
-	u8 u1temp = 0;
-
-	efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E);
-	if (efuseTbl == NULL) {
-		DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
-		goto exit;
-	}
-
-	eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
-	if (eFuseWord == NULL) {
-		DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
-		goto exit;
-	}
-
-	/*  0. Refresh efuse init map as all oxFF. */
-	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
-		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
-			eFuseWord[i][j] = 0xFFFF;
-
-	/*  */
-	/*  1. Read the first byte to check if efuse is empty!!! */
-	/*  */
-	/*  */
-	rtemp8 = *(phymap+eFuse_Addr);
-	if (rtemp8 != 0xFF) {
-		efuse_utilized++;
-		eFuse_Addr++;
-	} else {
-		DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
-		goto exit;
-	}
-
-	/*  */
-	/*  2. Read real efuse content. Filter PG header and every section data. */
-	/*  */
-	while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
-		/*  Check PG header for section num. */
-		if ((rtemp8 & 0x1F) == 0x0F) {		/* extended header */
-			u1temp = ((rtemp8 & 0xE0) >> 5);
-			rtemp8 = *(phymap+eFuse_Addr);
-			if ((rtemp8 & 0x0F) == 0x0F) {
-				eFuse_Addr++;
-				rtemp8 = *(phymap+eFuse_Addr);
-
-				if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
-					eFuse_Addr++;
-				continue;
-			} else {
-				offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
-				wren = (rtemp8 & 0x0F);
-				eFuse_Addr++;
-			}
-		} else {
-			offset = ((rtemp8 >> 4) & 0x0f);
-			wren = (rtemp8 & 0x0f);
-		}
-
-		if (offset < EFUSE_MAX_SECTION_88E) {
-			/*  Get word enable value from PG header */
-			for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
-				/*  Check word enable condition in the section */
-				if (!(wren & 0x01)) {
-					rtemp8 = *(phymap+eFuse_Addr);
-					eFuse_Addr++;
-					efuse_utilized++;
-					eFuseWord[offset][i] = (rtemp8 & 0xff);
-					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
-						break;
-					rtemp8 = *(phymap+eFuse_Addr);
-					eFuse_Addr++;
-					efuse_utilized++;
-					eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
-
-					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
-						break;
-				}
-				wren >>= 1;
-			}
-		}
-		/*  Read next PG header */
-		rtemp8 = *(phymap+eFuse_Addr);
-
-		if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
-			efuse_utilized++;
-			eFuse_Addr++;
-		}
-	}
-
-	/*  */
-	/*  3. Collect 16 sections and 4 word unit into Efuse map. */
-	/*  */
-	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
-		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
-			efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
-			efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
-		}
-	}
-
-	/*  */
-	/*  4. Copy from Efuse map to output pointer memory!!! */
-	/*  */
-	for (i = 0; i < _size_byte; i++)
-		pbuf[i] = efuseTbl[_offset+i];
-
-	/*  */
-	/*  5. Calculate Efuse utilization. */
-	/*  */
-
-exit:
-	kfree(efuseTbl);
-
-	if (eFuseWord)
-		rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
-}
-
-static void efuse_read_phymap_from_txpktbuf(
-	struct adapter  *adapter,
-	int bcnhead,	/* beacon head, where FW store len(2-byte) and efuse physical map. */
-	u8 *content,	/* buffer to store efuse physical map */
-	u16 *size	/* for efuse content: the max byte to read. will update to byte read */
-	)
-{
-	u16 dbg_addr = 0;
-	u32 start  = 0, passing_time = 0;
-	u8 reg_0x143 = 0;
-	u32 lo32 = 0, hi32 = 0;
-	u16 len = 0, count = 0;
-	int i = 0;
-	u16 limit = *size;
-
-	u8 *pos = content;
-
-	if (bcnhead < 0) /* if not valid */
-		bcnhead = rtw_read8(adapter, REG_TDECTRL+1);
-
-	DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
-
-	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
-
-	dbg_addr = bcnhead*128/8; /* 8-bytes addressing */
-
-	while (1) {
-		rtw_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i);
-
-		rtw_write8(adapter, REG_TXPKTBUF_DBG, 0);
-		start = jiffies;
-		while (!(reg_0x143 = rtw_read8(adapter, REG_TXPKTBUF_DBG)) &&
-		       (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
-			DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, rtw_read8(adapter, 0x106));
-			msleep(1);
-		}
-
-		lo32 = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L);
-		hi32 = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H);
-
-		if (i == 0) {
-			u8 lenc[2];
-			u16 lenbak, aaabak;
-			u16 aaa;
-			lenc[0] = rtw_read8(adapter, REG_PKTBUF_DBG_DATA_L);
-			lenc[1] = rtw_read8(adapter, REG_PKTBUF_DBG_DATA_L+1);
-
-			aaabak = le16_to_cpup((__le16 *)lenc);
-			lenbak = le16_to_cpu(*((__le16 *)lenc));
-			aaa = le16_to_cpup((__le16 *)&lo32);
-			len = le16_to_cpu(*((__le16 *)&lo32));
-
-			limit = (len-2 < limit) ? len-2 : limit;
-
-			DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
-
-			memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count);
-			count += (limit >= count+2) ? 2 : limit-count;
-			pos = content+count;
-
-		} else {
-			memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count);
-			count += (limit >= count+4) ? 4 : limit-count;
-			pos = content+count;
-		}
-
-		if (limit > count && len-2 > count) {
-			memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count);
-			count += (limit >= count+4) ? 4 : limit-count;
-			pos = content+count;
-		}
-
-		if (limit <= count || len-2 <= count)
-			break;
-		i++;
-	}
-	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
-	DBG_88E("%s read count:%u\n", __func__, count);
-	*size = count;
-}
-
-static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
-{
-	s32 status = _FAIL;
-	u8 physical_map[512];
-	u16 size = 512;
-
-	rtw_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
-	_rtw_memset(physical_map, 0xFF, 512);
-	rtw_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
-	status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
-	if (status == _SUCCESS)
-		efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
-	efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
-	return status;
-}
 
 s32 rtl8188e_iol_efuse_patch(struct adapter *padapter)
 {
@@ -326,7 +103,7 @@ static s32 iol_ioconfig(struct adapter *
 {
 	s32 rst = _SUCCESS;
 
-	rtw_write8(padapter, REG_TDECTRL+1, iocfg_bndy);
+	usb_write8(padapter, REG_TDECTRL+1, iocfg_bndy);
 	rst = iol_execute(padapter, CMD_IOCONFIG);
 	return rst;
 }
@@ -357,7 +134,7 @@ static int rtl8188e_IOL_exec_cmds_sync(s
 	iol_mode_enable(adapter, 0);
 exit:
 	/* restore BCN_HEAD */
-	rtw_write8(adapter, REG_TDECTRL+1, 0);
+	usb_write8(adapter, REG_TDECTRL+1, 0);
 	return ret;
 }
 
@@ -369,19 +146,19 @@ void rtw_IOL_cmd_tx_pkt_buf_dump(struct
 	u8 *pbuf = vzalloc(data_len+10);
 	DBG_88E("###### %s ######\n", __func__);
 
-	rtw_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+	usb_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
 	if (pbuf) {
 		for (addr = 0; addr < data_cnts; addr++) {
-			rtw_write32(Adapter, 0x140, addr);
+			usb_write32(Adapter, 0x140, addr);
 			msleep(1);
 			loop = 0;
 			do {
-				rstatus = (reg_140 = rtw_read32(Adapter, REG_PKTBUF_DBG_CTRL)&BIT24);
+				rstatus = (reg_140 = usb_read32(Adapter, REG_PKTBUF_DBG_CTRL)&BIT24);
 				if (rstatus) {
-					fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_L);
+					fifo_data = usb_read32(Adapter, REG_PKTBUF_DBG_DATA_L);
 					memcpy(pbuf+(addr*8), &fifo_data, 4);
 
-					fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_H);
+					fifo_data = usb_read32(Adapter, REG_PKTBUF_DBG_DATA_H);
 					memcpy(pbuf+(addr*8+4), &fifo_data, 4);
 				}
 				msleep(1);
@@ -399,19 +176,19 @@ static void _FWDownloadEnable(struct ada
 
 	if (enable) {
 		/*  MCU firmware download enable. */
-		tmp = rtw_read8(padapter, REG_MCUFWDL);
-		rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
+		tmp = usb_read8(padapter, REG_MCUFWDL);
+		usb_write8(padapter, REG_MCUFWDL, tmp | 0x01);
 
 		/*  8051 reset */
-		tmp = rtw_read8(padapter, REG_MCUFWDL+2);
-		rtw_write8(padapter, REG_MCUFWDL+2, tmp&0xf7);
+		tmp = usb_read8(padapter, REG_MCUFWDL+2);
+		usb_write8(padapter, REG_MCUFWDL+2, tmp&0xf7);
 	} else {
 		/*  MCU firmware download disable. */
-		tmp = rtw_read8(padapter, REG_MCUFWDL);
-		rtw_write8(padapter, REG_MCUFWDL, tmp&0xfe);
+		tmp = usb_read8(padapter, REG_MCUFWDL);
+		usb_write8(padapter, REG_MCUFWDL, tmp&0xfe);
 
 		/*  Reserved for fw extension. */
-		rtw_write8(padapter, REG_MCUFWDL+1, 0x00);
+		usb_write8(padapter, REG_MCUFWDL+1, 0x00);
 	}
 }
 
@@ -441,7 +218,7 @@ static int _BlockWrite(struct adapter *p
 	}
 
 	for (i = 0; i < blockCount_p1; i++) {
-		ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + i * blockSize_p1), blockSize_p1, (bufferPtr + i * blockSize_p1));
+		ret = usb_writeN(padapter, (FW_8188E_START_ADDRESS + i * blockSize_p1), blockSize_p1, (bufferPtr + i * blockSize_p1));
 		if (ret == _FAIL)
 			goto exit;
 	}
@@ -460,7 +237,7 @@ static int _BlockWrite(struct adapter *p
 		}
 
 		for (i = 0; i < blockCount_p2; i++) {
-			ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + offset + i*blockSize_p2), blockSize_p2, (bufferPtr + offset + i*blockSize_p2));
+			ret = usb_writeN(padapter, (FW_8188E_START_ADDRESS + offset + i*blockSize_p2), blockSize_p2, (bufferPtr + offset + i*blockSize_p2));
 
 			if (ret == _FAIL)
 				goto exit;
@@ -478,7 +255,7 @@ static int _BlockWrite(struct adapter *p
 			 (buffSize-offset), blockSize_p3, blockCount_p3));
 
 		for (i = 0; i < blockCount_p3; i++) {
-			ret = rtw_write8(padapter, (FW_8188E_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
+			ret = usb_write8(padapter, (FW_8188E_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
 
 			if (ret == _FAIL)
 				goto exit;
@@ -494,8 +271,8 @@ static int _PageWrite(struct adapter *pa
 	u8 value8;
 	u8 u8Page = (u8)(page & 0x07);
 
-	value8 = (rtw_read8(padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
-	rtw_write8(padapter, REG_MCUFWDL+2, value8);
+	value8 = (usb_read8(padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
+	usb_write8(padapter, REG_MCUFWDL+2, value8);
 
 	return _BlockWrite(padapter, buffer, size);
 }
@@ -536,9 +313,9 @@ void _8051Reset88E(struct adapter *padap
 {
 	u8 u1bTmp;
 
-	u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
-	rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
-	rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT2));
+	u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN+1);
+	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
+	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT2));
 	DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
 }
 
@@ -549,7 +326,7 @@ static s32 _FWFreeToGo(struct adapter *p
 
 	/*  polling CheckSum report */
 	do {
-		value32 = rtw_read32(padapter, REG_MCUFWDL);
+		value32 = usb_read32(padapter, REG_MCUFWDL);
 		if (value32 & FWDL_ChkSum_rpt)
 			break;
 	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
@@ -560,17 +337,17 @@ static s32 _FWFreeToGo(struct adapter *p
 	}
 	DBG_88E("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__, value32);
 
-	value32 = rtw_read32(padapter, REG_MCUFWDL);
+	value32 = usb_read32(padapter, REG_MCUFWDL);
 	value32 |= MCUFWDL_RDY;
 	value32 &= ~WINTINI_RDY;
-	rtw_write32(padapter, REG_MCUFWDL, value32);
+	usb_write32(padapter, REG_MCUFWDL, value32);
 
 	_8051Reset88E(padapter);
 
 	/*  polling for FW ready */
 	counter = 0;
 	do {
-		value32 = rtw_read32(padapter, REG_MCUFWDL);
+		value32 = usb_read32(padapter, REG_MCUFWDL);
 		if (value32 & WINTINI_RDY) {
 			DBG_88E("%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n", __func__, value32);
 			return _SUCCESS;
@@ -666,8 +443,8 @@ s32 rtl8188e_FirmwareDownload(struct ada
 
 	/*  Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
 	/*  or it will cause download Fw fail. 2010.02.01. by tynli. */
-	if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
-		rtw_write8(padapter, REG_MCUFWDL, 0x00);
+	if (usb_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
+		usb_write8(padapter, REG_MCUFWDL, 0x00);
 		_8051Reset88E(padapter);
 	}
 
@@ -675,7 +452,7 @@ s32 rtl8188e_FirmwareDownload(struct ada
 	fwdl_start_time = jiffies;
 	while (1) {
 		/* reset the FWDL chksum */
-		rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
+		usb_write8(padapter, REG_MCUFWDL, usb_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
 
 		rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
 
@@ -720,1021 +497,6 @@ static void rtl8188e_free_hal_data(struc
 	padapter->HalData = NULL;
 }
 
-/*  */
-/*			Efuse related code */
-/*  */
-enum{
-		VOLTAGE_V25						= 0x03,
-		LDOE25_SHIFT						= 28 ,
-	};
-
-static bool
-hal_EfusePgPacketWrite2ByteHeader(
-		struct adapter *pAdapter,
-		u8 efuseType,
-		u16				*pAddr,
-		struct pgpkt *pTargetPkt,
-		bool bPseudoTest);
-static bool
-hal_EfusePgPacketWrite1ByteHeader(
-		struct adapter *pAdapter,
-		u8 efuseType,
-		u16				*pAddr,
-		struct pgpkt *pTargetPkt,
-		bool bPseudoTest);
-static bool
-hal_EfusePgPacketWriteData(
-		struct adapter *pAdapter,
-		u8 efuseType,
-		u16				*pAddr,
-		struct pgpkt *pTargetPkt,
-		bool bPseudoTest);
-
-static void
-hal_EfusePowerSwitch_RTL8188E(
-		struct adapter *pAdapter,
-		u8 bWrite,
-		u8 PwrState)
-{
-	u8 tempval;
-	u16	tmpV16;
-
-	if (PwrState) {
-		rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
-
-		/*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
-		if (!(tmpV16 & PWC_EV12V)) {
-			tmpV16 |= PWC_EV12V;
-			 rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
-		}
-		/*  Reset: 0x0000h[28], default valid */
-		tmpV16 =  rtw_read16(pAdapter, REG_SYS_FUNC_EN);
-		if (!(tmpV16 & FEN_ELDR)) {
-			tmpV16 |= FEN_ELDR;
-			rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
-		}
-
-		/*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
-		if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
-			tmpV16 |= (LOADER_CLK_EN | ANA8M);
-			rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
-		}
-
-		if (bWrite) {
-			/*  Enable LDO 2.5V before read/write action */
-			tempval = rtw_read8(pAdapter, EFUSE_TEST+3);
-			tempval &= 0x0F;
-			tempval |= (VOLTAGE_V25 << 4);
-			rtw_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80));
-		}
-	} else {
-		rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
-
-		if (bWrite) {
-			/*  Disable LDO 2.5V after read/write action */
-			tempval = rtw_read8(pAdapter, EFUSE_TEST+3);
-			rtw_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F));
-		}
-	}
-}
-
-static void
-rtl8188e_EfusePowerSwitch(
-		struct adapter *pAdapter,
-		u8 bWrite,
-		u8 PwrState)
-{
-	hal_EfusePowerSwitch_RTL8188E(pAdapter, bWrite, PwrState);
-}
-
-
-static void Hal_EfuseReadEFuse88E(struct adapter *Adapter,
-	u16			_offset,
-	u16			_size_byte,
-	u8 *pbuf,
-		bool bPseudoTest
-	)
-{
-	u8 *efuseTbl = NULL;
-	u8 rtemp8[1];
-	u16	eFuse_Addr = 0;
-	u8 offset, wren;
-	u16	i, j;
-	u16	**eFuseWord = NULL;
-	u16	efuse_utilized = 0;
-	u8 u1temp = 0;
-
-	/*  */
-	/*  Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
-	/*  */
-	if ((_offset + _size_byte) > EFUSE_MAP_LEN_88E) {/*  total E-Fuse table is 512bytes */
-		DBG_88E("Hal_EfuseReadEFuse88E(): Invalid offset(%#x) with read bytes(%#x)!!\n", _offset, _size_byte);
-		goto exit;
-	}
-
-	efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E);
-	if (efuseTbl == NULL) {
-		DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
-		goto exit;
-	}
-
-	eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
-	if (eFuseWord == NULL) {
-		DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
-		goto exit;
-	}
-
-	/*  0. Refresh efuse init map as all oxFF. */
-	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
-		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
-			eFuseWord[i][j] = 0xFFFF;
-
-	/*  */
-	/*  1. Read the first byte to check if efuse is empty!!! */
-	/*  */
-	/*  */
-	ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-	if (*rtemp8 != 0xFF) {
-		efuse_utilized++;
-		eFuse_Addr++;
-	} else {
-		DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, *rtemp8);
-		goto exit;
-	}
-
-	/*  */
-	/*  2. Read real efuse content. Filter PG header and every section data. */
-	/*  */
-	while ((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
-		/*  Check PG header for section num. */
-		if ((*rtemp8 & 0x1F) == 0x0F) {		/* extended header */
-			u1temp = ((*rtemp8 & 0xE0) >> 5);
-
-			ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-
-			if ((*rtemp8 & 0x0F) == 0x0F) {
-				eFuse_Addr++;
-				ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-
-				if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
-					eFuse_Addr++;
-				continue;
-			} else {
-				offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
-				wren = (*rtemp8 & 0x0F);
-				eFuse_Addr++;
-			}
-		} else {
-			offset = ((*rtemp8 >> 4) & 0x0f);
-			wren = (*rtemp8 & 0x0f);
-		}
-
-		if (offset < EFUSE_MAX_SECTION_88E) {
-			/*  Get word enable value from PG header */
-
-			for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
-				/*  Check word enable condition in the section */
-				if (!(wren & 0x01)) {
-					ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-					eFuse_Addr++;
-					efuse_utilized++;
-					eFuseWord[offset][i] = (*rtemp8 & 0xff);
-					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
-						break;
-					ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-					eFuse_Addr++;
-					efuse_utilized++;
-					eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00);
-					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
-						break;
-				}
-				wren >>= 1;
-			}
-		}
-
-		/*  Read next PG header */
-		ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
-
-		if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
-			efuse_utilized++;
-			eFuse_Addr++;
-		}
-	}
-
-	/*  3. Collect 16 sections and 4 word unit into Efuse map. */
-	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
-		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
-			efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
-			efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
-		}
-	}
-
-	/*  4. Copy from Efuse map to output pointer memory!!! */
-	for (i = 0; i < _size_byte; i++)
-		pbuf[i] = efuseTbl[_offset+i];
-
-	/*  5. Calculate Efuse utilization. */
-	rtw_hal_set_hwreg(Adapter, HW_VAR_EFUSE_BYTES, (u8 *)&eFuse_Addr);
-
-exit:
-	kfree(efuseTbl);
-
-	if (eFuseWord)
-		rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
-}
-
-static void ReadEFuseByIC(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
-{
-	if (!bPseudoTest) {
-		int ret = _FAIL;
-		if (rtw_IOL_applied(Adapter)) {
-			rtw_hal_power_on(Adapter);
-
-			iol_mode_enable(Adapter, 1);
-			ret = iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
-			iol_mode_enable(Adapter, 0);
-
-			if (_SUCCESS == ret)
-				goto exit;
-		}
-	}
-	Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
-
-exit:
-	return;
-}
-
-static void ReadEFuse_Pseudo(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
-{
-	Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
-}
-
-static void rtl8188e_ReadEFuse(struct adapter *Adapter, u8 efuseType,
-			       u16 _offset, u16 _size_byte, u8 *pbuf,
-			       bool bPseudoTest)
-{
-	if (bPseudoTest)
-		ReadEFuse_Pseudo (Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
-	else
-		ReadEFuseByIC(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
-}
-
-/* Do not support BT */
-static void Hal_EFUSEGetEfuseDefinition88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
-{
-	switch (type) {
-	case TYPE_EFUSE_MAX_SECTION:
-		{
-			u8 *pMax_section;
-			pMax_section = (u8 *)pOut;
-			*pMax_section = EFUSE_MAX_SECTION_88E;
-		}
-		break;
-	case TYPE_EFUSE_REAL_CONTENT_LEN:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
-		}
-		break;
-	case TYPE_EFUSE_CONTENT_LEN_BANK:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
-		}
-		break;
-	case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	case TYPE_EFUSE_MAP_LEN:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
-		}
-		break;
-	case TYPE_EFUSE_PROTECT_BYTES_BANK:
-		{
-			u8 *pu1Tmp;
-			pu1Tmp = (u8 *)pOut;
-			*pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	default:
-		{
-			u8 *pu1Tmp;
-			pu1Tmp = (u8 *)pOut;
-			*pu1Tmp = 0;
-		}
-		break;
-	}
-}
-
-static void Hal_EFUSEGetEfuseDefinition_Pseudo88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
-{
-	switch (type) {
-	case TYPE_EFUSE_MAX_SECTION:
-		{
-			u8 *pMax_section;
-			pMax_section = (u8 *)pOut;
-			*pMax_section = EFUSE_MAX_SECTION_88E;
-		}
-		break;
-	case TYPE_EFUSE_REAL_CONTENT_LEN:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
-		}
-		break;
-	case TYPE_EFUSE_CONTENT_LEN_BANK:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
-		}
-		break;
-	case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	case TYPE_EFUSE_MAP_LEN:
-		{
-			u16 *pu2Tmp;
-			pu2Tmp = (u16 *)pOut;
-			*pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
-		}
-		break;
-	case TYPE_EFUSE_PROTECT_BYTES_BANK:
-		{
-			u8 *pu1Tmp;
-			pu1Tmp = (u8 *)pOut;
-			*pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
-		}
-		break;
-	default:
-		{
-			u8 *pu1Tmp;
-			pu1Tmp = (u8 *)pOut;
-			*pu1Tmp = 0;
-		}
-		break;
-	}
-}
-
-static void rtl8188e_EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest)
-{
-	if (bPseudoTest)
-		Hal_EFUSEGetEfuseDefinition_Pseudo88E(pAdapter, efuseType, type, pOut);
-	else
-		Hal_EFUSEGetEfuseDefinition88E(pAdapter, efuseType, type, pOut);
-}
-
-static u8 Hal_EfuseWordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	u16	tmpaddr = 0;
-	u16	start_addr = efuse_addr;
-	u8 badworden = 0x0F;
-	u8 tmpdata[8];
-
-	_rtw_memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
-
-	if (!(word_en&BIT0)) {
-		tmpaddr = start_addr;
-		efuse_OneByteWrite(pAdapter, start_addr++, data[0], bPseudoTest);
-		efuse_OneByteWrite(pAdapter, start_addr++, data[1], bPseudoTest);
-
-		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0], bPseudoTest);
-		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1], bPseudoTest);
-		if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
-			badworden &= (~BIT0);
-	}
-	if (!(word_en&BIT1)) {
-		tmpaddr = start_addr;
-		efuse_OneByteWrite(pAdapter, start_addr++, data[2], bPseudoTest);
-		efuse_OneByteWrite(pAdapter, start_addr++, data[3], bPseudoTest);
-
-		efuse_OneByteRead(pAdapter, tmpaddr    , &tmpdata[2], bPseudoTest);
-		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3], bPseudoTest);
-		if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
-			badworden &= (~BIT1);
-	}
-	if (!(word_en&BIT2)) {
-		tmpaddr = start_addr;
-		efuse_OneByteWrite(pAdapter, start_addr++, data[4], bPseudoTest);
-		efuse_OneByteWrite(pAdapter, start_addr++, data[5], bPseudoTest);
-
-		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4], bPseudoTest);
-		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5], bPseudoTest);
-		if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
-			badworden &= (~BIT2);
-	}
-	if (!(word_en&BIT3)) {
-		tmpaddr = start_addr;
-		efuse_OneByteWrite(pAdapter, start_addr++, data[6], bPseudoTest);
-		efuse_OneByteWrite(pAdapter, start_addr++, data[7], bPseudoTest);
-
-		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6], bPseudoTest);
-		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7], bPseudoTest);
-		if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
-			badworden &= (~BIT3);
-	}
-	return badworden;
-}
-
-static u8 Hal_EfuseWordEnableDataWrite_Pseudo(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	u8 ret;
-
-	ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
-	return ret;
-}
-
-static u8 rtl8188e_Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	u8 ret = 0;
-
-	if (bPseudoTest)
-		ret = Hal_EfuseWordEnableDataWrite_Pseudo (pAdapter, efuse_addr, word_en, data, bPseudoTest);
-	else
-		ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
-	return ret;
-}
-
-static u16 hal_EfuseGetCurrentSize_8188e(struct adapter *pAdapter, bool bPseudoTest)
-{
-	int	bContinual = true;
-	u16	efuse_addr = 0;
-	u8 hoffset = 0, hworden = 0;
-	u8 efuse_data, word_cnts = 0;
-
-	if (bPseudoTest)
-		efuse_addr = (u16)(fakeEfuseUsedBytes);
-	else
-		rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
-
-	while (bContinual &&
-	       efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) &&
-	       AVAILABLE_EFUSE_ADDR(efuse_addr)) {
-		if (efuse_data != 0xFF) {
-			if ((efuse_data&0x1F) == 0x0F) {		/* extended header */
-				hoffset = efuse_data;
-				efuse_addr++;
-				efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
-				if ((efuse_data & 0x0F) == 0x0F) {
-					efuse_addr++;
-					continue;
-				} else {
-					hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
-					hworden = efuse_data & 0x0F;
-				}
-			} else {
-				hoffset = (efuse_data>>4) & 0x0F;
-				hworden =  efuse_data & 0x0F;
-			}
-			word_cnts = Efuse_CalculateWordCnts(hworden);
-			/* read next header */
-			efuse_addr = efuse_addr + (word_cnts*2)+1;
-		} else {
-			bContinual = false;
-		}
-	}
-
-	if (bPseudoTest)
-		fakeEfuseUsedBytes = efuse_addr;
-	else
-		rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
-
-	return efuse_addr;
-}
-
-static u16 Hal_EfuseGetCurrentSize_Pseudo(struct adapter *pAdapter, bool bPseudoTest)
-{
-	u16	ret = 0;
-
-	ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
-	return ret;
-}
-
-static u16 rtl8188e_EfuseGetCurrentSize(struct adapter *pAdapter, u8 efuseType, bool bPseudoTest)
-{
-	u16	ret = 0;
-
-	if (bPseudoTest)
-		ret = Hal_EfuseGetCurrentSize_Pseudo(pAdapter, bPseudoTest);
-	else
-		ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
-	return ret;
-}
-
-static int hal_EfusePgPacketRead_8188e(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
-{
-	u8 ReadState = PG_STATE_HEADER;
-	int	bContinual = true;
-	int	bDataEmpty = true;
-	u8 efuse_data, word_cnts = 0;
-	u16	efuse_addr = 0;
-	u8 hoffset = 0, hworden = 0;
-	u8 tmpidx = 0;
-	u8 tmpdata[8];
-	u8 max_section = 0;
-	u8 tmp_header = 0;
-
-	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section, bPseudoTest);
-
-	if (data == NULL)
-		return false;
-	if (offset > max_section)
-		return false;
-
-	_rtw_memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
-	_rtw_memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
-
-	/*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
-	/*  Skip dummy parts to prevent unexpected data read from Efuse. */
-	/*  By pass right now. 2009.02.19. */
-	while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
-		/*   Header Read ------------- */
-		if (ReadState & PG_STATE_HEADER) {
-			if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
-				if (EXT_HEADER(efuse_data)) {
-					tmp_header = efuse_data;
-					efuse_addr++;
-					efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
-					if (!ALL_WORDS_DISABLED(efuse_data)) {
-						hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
-						hworden = efuse_data & 0x0F;
-					} else {
-						DBG_88E("Error, All words disabled\n");
-						efuse_addr++;
-						continue;
-					}
-				} else {
-					hoffset = (efuse_data>>4) & 0x0F;
-					hworden =  efuse_data & 0x0F;
-				}
-				word_cnts = Efuse_CalculateWordCnts(hworden);
-				bDataEmpty = true;
-
-				if (hoffset == offset) {
-					for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
-						if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data, bPseudoTest)) {
-							tmpdata[tmpidx] = efuse_data;
-							if (efuse_data != 0xff)
-								bDataEmpty = false;
-						}
-					}
-					if (bDataEmpty == false) {
-						ReadState = PG_STATE_DATA;
-					} else {/* read next header */
-						efuse_addr = efuse_addr + (word_cnts*2)+1;
-						ReadState = PG_STATE_HEADER;
-					}
-				} else {/* read next header */
-					efuse_addr = efuse_addr + (word_cnts*2)+1;
-					ReadState = PG_STATE_HEADER;
-				}
-			} else {
-				bContinual = false;
-			}
-		} else if (ReadState & PG_STATE_DATA) {
-		/*   Data section Read ------------- */
-			efuse_WordEnableDataRead(hworden, tmpdata, data);
-			efuse_addr = efuse_addr + (word_cnts*2)+1;
-			ReadState = PG_STATE_HEADER;
-		}
-
-	}
-
-	if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
-	    (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
-		return false;
-	else
-		return true;
-}
-
-static int Hal_EfusePgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
-{
-	int	ret;
-
-	ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
-	return ret;
-}
-
-static int Hal_EfusePgPacketRead_Pseudo(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
-{
-	int	ret;
-
-	ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
-	return ret;
-}
-
-static int rtl8188e_Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
-{
-	int	ret;
-
-	if (bPseudoTest)
-		ret = Hal_EfusePgPacketRead_Pseudo (pAdapter, offset, data, bPseudoTest);
-	else
-		ret = Hal_EfusePgPacketRead(pAdapter, offset, data, bPseudoTest);
-	return ret;
-}
-
-static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr, bool bPseudoTest)
-{
-	u8 originaldata[8], badworden = 0;
-	u16	efuse_addr = *pAddr;
-	u32	PgWriteSuccess = 0;
-
-	_rtw_memset((void *)originaldata, 0xff, 8);
-
-	if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata, bPseudoTest)) {
-		/* check if data exist */
-		badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata, bPseudoTest);
-
-		if (badworden != 0xf) {	/*  write fail */
-			PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata, bPseudoTest);
-
-			if (!PgWriteSuccess)
-				return false;
-			else
-				efuse_addr = Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest);
-		} else {
-			efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
-		}
-	} else {
-		efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
-	}
-	*pAddr = efuse_addr;
-	return true;
-}
-
-static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
-{
-	bool bRet = false;
-	u16	efuse_addr = *pAddr, efuse_max_available_len = 0;
-	u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
-	u8 repeatcnt = 0;
-
-	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
-
-	while (efuse_addr < efuse_max_available_len) {
-		pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
-		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-
-		while (tmp_header == 0xFF) {
-			if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
-				return false;
-
-			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-		}
-
-		/* to write ext_header */
-		if (tmp_header == pg_header) {
-			efuse_addr++;
-			pg_header_temp = pg_header;
-			pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
-
-			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-
-			while (tmp_header == 0xFF) {
-				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
-					return false;
-
-				efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-				efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-			}
-
-			if ((tmp_header & 0x0F) == 0x0F) {	/* word_en PG fail */
-				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
-					return false;
-				} else {
-					efuse_addr++;
-					continue;
-				}
-			} else if (pg_header != tmp_header) {	/* offset PG fail */
-				struct pgpkt	fixPkt;
-				fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
-				fixPkt.word_en = tmp_header & 0x0F;
-				fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
-				if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
-					return false;
-			} else {
-				bRet = true;
-				break;
-			}
-		} else if ((tmp_header & 0x1F) == 0x0F) {		/* wrong extended header */
-			efuse_addr += 2;
-			continue;
-		}
-	}
-
-	*pAddr = efuse_addr;
-	return bRet;
-}
-
-static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
-{
-	bool bRet = false;
-	u8 pg_header = 0, tmp_header = 0;
-	u16	efuse_addr = *pAddr;
-	u8 repeatcnt = 0;
-
-	pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
-
-	efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-	efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-
-	while (tmp_header == 0xFF) {
-		if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
-			return false;
-		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
-		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
-	}
-
-	if (pg_header == tmp_header) {
-		bRet = true;
-	} else {
-		struct pgpkt	fixPkt;
-		fixPkt.offset = (tmp_header>>4) & 0x0F;
-		fixPkt.word_en = tmp_header & 0x0F;
-		fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
-		if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
-			return false;
-	}
-
-	*pAddr = efuse_addr;
-	return bRet;
-}
-
-static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
-{
-	u16	efuse_addr = *pAddr;
-	u8 badworden = 0;
-	u32	PgWriteSuccess = 0;
-
-	badworden = 0x0f;
-	badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
-	if (badworden == 0x0F) {
-		/*  write ok */
-		return true;
-	} else {
-		/* reorganize other pg packet */
-		PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
-		if (!PgWriteSuccess)
-			return false;
-		else
-			return true;
-	}
-}
-
-static bool
-hal_EfusePgPacketWriteHeader(
-				struct adapter *pAdapter,
-				u8 efuseType,
-				u16				*pAddr,
-				struct pgpkt *pTargetPkt,
-				bool bPseudoTest)
-{
-	bool bRet = false;
-
-	if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
-		bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
-	else
-		bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
-
-	return bRet;
-}
-
-static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
-			  u8 *pWden)
-{
-	u8 match_word_en = 0x0F;	/*  default all words are disabled */
-
-	/*  check if the same words are enabled both target and current PG packet */
-	if (((pTargetPkt->word_en & BIT0) == 0) &&
-	    ((pCurPkt->word_en & BIT0) == 0))
-		match_word_en &= ~BIT0;				/*  enable word 0 */
-	if (((pTargetPkt->word_en & BIT1) == 0) &&
-	    ((pCurPkt->word_en & BIT1) == 0))
-		match_word_en &= ~BIT1;				/*  enable word 1 */
-	if (((pTargetPkt->word_en & BIT2) == 0) &&
-	    ((pCurPkt->word_en & BIT2) == 0))
-		match_word_en &= ~BIT2;				/*  enable word 2 */
-	if (((pTargetPkt->word_en & BIT3) == 0) &&
-	    ((pCurPkt->word_en & BIT3) == 0))
-		match_word_en &= ~BIT3;				/*  enable word 3 */
-
-	*pWden = match_word_en;
-
-	if (match_word_en != 0xf)
-		return true;
-	else
-		return false;
-}
-
-static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr, bool bPseudoTest)
-{
-	bool bRet = false;
-	u8 i, efuse_data;
-
-	for (i = 0; i < (word_cnts*2); i++) {
-		if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data, bPseudoTest) && (efuse_data != 0xFF))
-			bRet = true;
-	}
-	return bRet;
-}
-
-static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
-{
-	bool bRet = false;
-	u8 i, efuse_data = 0, cur_header = 0;
-	u8 matched_wden = 0, badworden = 0;
-	u16	startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
-	struct pgpkt curPkt;
-
-	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
-	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max, bPseudoTest);
-
-	if (efuseType == EFUSE_WIFI) {
-		if (bPseudoTest) {
-			startAddr = (u16)(fakeEfuseUsedBytes%EFUSE_REAL_CONTENT_LEN);
-		} else {
-			rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
-			startAddr %= EFUSE_REAL_CONTENT_LEN;
-		}
-	} else {
-		if (bPseudoTest)
-			startAddr = (u16)(fakeBTEfuseUsedBytes%EFUSE_REAL_CONTENT_LEN);
-		else
-			startAddr = (u16)(BTEfuseUsedBytes%EFUSE_REAL_CONTENT_LEN);
-	}
-
-	while (1) {
-		if (startAddr >= efuse_max_available_len) {
-			bRet = false;
-			break;
-		}
-
-		if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
-			if (EXT_HEADER(efuse_data)) {
-				cur_header = efuse_data;
-				startAddr++;
-				efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest);
-				if (ALL_WORDS_DISABLED(efuse_data)) {
-					bRet = false;
-					break;
-				} else {
-					curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
-					curPkt.word_en = efuse_data & 0x0F;
-				}
-			} else {
-				cur_header  =  efuse_data;
-				curPkt.offset = (cur_header>>4) & 0x0F;
-				curPkt.word_en = cur_header & 0x0F;
-			}
-
-			curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
-			/*  if same header is found but no data followed */
-			/*  write some part of data followed by the header. */
-			if ((curPkt.offset == pTargetPkt->offset) &&
-			    (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1, bPseudoTest)) &&
-			    wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
-				/*  Here to write partial data */
-				badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
-				if (badworden != 0x0F) {
-					u32	PgWriteSuccess = 0;
-					/*  if write fail on some words, write these bad words again */
-
-					PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
-
-					if (!PgWriteSuccess) {
-						bRet = false;	/*  write fail, return */
-						break;
-					}
-				}
-				/*  partial write ok, update the target packet for later use */
-				for (i = 0; i < 4; i++) {
-					if ((matched_wden & (0x1<<i)) == 0)	/*  this word has been written */
-						pTargetPkt->word_en |= (0x1<<i);	/*  disable the word */
-				}
-				pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
-			}
-			/*  read from next header */
-			startAddr = startAddr + (curPkt.word_cnts*2) + 1;
-		} else {
-			/*  not used header, 0xff */
-			*pAddr = startAddr;
-			bRet = true;
-			break;
-		}
-	}
-	return bRet;
-}
-
-static bool
-hal_EfusePgCheckAvailableAddr(
-		struct adapter *pAdapter,
-		u8 efuseType,
-		bool bPseudoTest
-	)
-{
-	u16	efuse_max_available_len = 0;
-
-	/* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
-	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false);
-
-	if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len)
-		return false;
-	return true;
-}
-
-static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
-{
-	_rtw_memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
-	pTargetPkt->offset = offset;
-	pTargetPkt->word_en = word_en;
-	efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
-	pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
-}
-
-static bool hal_EfusePgPacketWrite_8188e(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData, bool bPseudoTest)
-{
-	struct pgpkt	targetPkt;
-	u16			startAddr = 0;
-	u8 efuseType = EFUSE_WIFI;
-
-	if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType, bPseudoTest))
-		return false;
-
-	hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
-	if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
-		return false;
-
-	if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
-		return false;
-
-	if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
-		return false;
-
-	return true;
-}
-
-static int Hal_EfusePgPacketWrite_Pseudo(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	int ret;
-
-	ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
-	return ret;
-}
-
-static int Hal_EfusePgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	int	ret = 0;
-	ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
-
-	return ret;
-}
-
-static int rtl8188e_Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
-{
-	int	ret;
-
-	if (bPseudoTest)
-		ret = Hal_EfusePgPacketWrite_Pseudo (pAdapter, offset, word_en, data, bPseudoTest);
-	else
-		ret = Hal_EfusePgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest);
-	return ret;
-}
-
 static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
 {
 	u32				value32;
@@ -1743,7 +505,7 @@ static struct HAL_VERSION ReadChipVersio
 
 	pHalData = GET_HAL_DATA(padapter);
 
-	value32 = rtw_read32(padapter, REG_SYS_CFG);
+	value32 = usb_read32(padapter, REG_SYS_CFG);
 	ChipVersion.ICType = CHIP_8188E;
 	ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
 
@@ -1755,7 +517,6 @@ static struct HAL_VERSION ReadChipVersio
 	pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
 
 	ChipVersion.ROMVer = 0;	/*  ROM code version. */
-	pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
 
 	dump_chip_info(ChipVersion);
 
@@ -1782,10 +543,6 @@ static void rtl8188e_read_chip_version(s
 	ReadChipVersion8188E(padapter);
 }
 
-static void rtl8188e_GetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
-{
-}
-
 static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(Adapter);
@@ -1815,27 +572,14 @@ static void rtl8188e_SetHalODMVar(struct
 	}
 }
 
-void rtl8188e_clone_haldata(struct adapter *dst_adapter, struct adapter *src_adapter)
-{
-	memcpy(dst_adapter->HalData, src_adapter->HalData, dst_adapter->hal_data_sz);
-}
-
-void rtl8188e_start_thread(struct adapter *padapter)
-{
-}
-
-void rtl8188e_stop_thread(struct adapter *padapter)
-{
-}
-
 static void hal_notch_filter_8188e(struct adapter *adapter, bool enable)
 {
 	if (enable) {
 		DBG_88E("Enable notch filter\n");
-		rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
+		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
 	} else {
 		DBG_88E("Disable notch filter\n");
-		rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
+		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
 	}
 }
 void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
@@ -1852,8 +596,6 @@ void rtl8188e_set_hal_ops(struct hal_ops
 	pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog;
 
 	pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid;
-	pHalFunc->run_thread = &rtl8188e_start_thread;
-	pHalFunc->cancel_thread = &rtl8188e_stop_thread;
 
 	pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E;
 	pHalFunc->AntDivCompareHandler = &AntDivCompare8188E;
@@ -1862,23 +604,9 @@ void rtl8188e_set_hal_ops(struct hal_ops
 	pHalFunc->read_rfreg = &rtl8188e_PHY_QueryRFReg;
 	pHalFunc->write_rfreg = &rtl8188e_PHY_SetRFReg;
 
-	/*  Efuse related function */
-	pHalFunc->EfusePowerSwitch = &rtl8188e_EfusePowerSwitch;
-	pHalFunc->ReadEFuse = &rtl8188e_ReadEFuse;
-	pHalFunc->EFUSEGetEfuseDefinition = &rtl8188e_EFUSE_GetEfuseDefinition;
-	pHalFunc->EfuseGetCurrentSize = &rtl8188e_EfuseGetCurrentSize;
-	pHalFunc->Efuse_PgPacketRead = &rtl8188e_Efuse_PgPacketRead;
-	pHalFunc->Efuse_PgPacketWrite = &rtl8188e_Efuse_PgPacketWrite;
-	pHalFunc->Efuse_WordEnableDataWrite = &rtl8188e_Efuse_WordEnableDataWrite;
-
 	pHalFunc->sreset_init_value = &sreset_init_value;
-	pHalFunc->sreset_reset_value = &sreset_reset_value;
-	pHalFunc->silentreset = &rtl8188e_silentreset_for_specific_platform;
-	pHalFunc->sreset_xmit_status_check = &rtl8188e_sreset_xmit_status_check;
-	pHalFunc->sreset_linked_status_check  = &rtl8188e_sreset_linked_status_check;
 	pHalFunc->sreset_get_wifi_status  = &sreset_get_wifi_status;
 
-	pHalFunc->GetHalODMVarHandler = &rtl8188e_GetHalODMVar;
 	pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar;
 
 	pHalFunc->IOL_exec_cmds_sync = &rtl8188e_IOL_exec_cmds_sync;
@@ -1891,7 +619,7 @@ u8 GetEEPROMSize8188E(struct adapter *pa
 	u8 size = 0;
 	u32	cr;
 
-	cr = rtw_read16(padapter, REG_9346CR);
+	cr = usb_read16(padapter, REG_9346CR);
 	/*  6: EEPROM used is 93C46, 4: boot from E-Fuse. */
 	size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
 
@@ -1912,11 +640,11 @@ static s32 _LLTWrite(struct adapter *pad
 	u32	value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
 	u16	LLTReg = REG_LLT_INIT;
 
-	rtw_write32(padapter, LLTReg, value);
+	usb_write32(padapter, LLTReg, value);
 
 	/* polling */
 	do {
-		value = rtw_read32(padapter, LLTReg);
+		value = usb_read32(padapter, LLTReg);
 		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
 			break;
 
@@ -1977,13 +705,13 @@ Hal_InitPGData88E(struct adapter *padapt
 	if (!pEEPROM->bautoload_fail_flag) { /*  autoload OK. */
 		if (!is_boot_from_eeprom(padapter)) {
 			/*  Read EFUSE real map to shadow. */
-			EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+			EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI);
 		}
 	} else {/* autoload fail */
 		RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, ("AutoLoad Fail reported from CR9346!!\n"));
 		/* update to default value 0xFF */
 		if (!is_boot_from_eeprom(padapter))
-			EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+			EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI);
 	}
 }
 
@@ -2012,7 +740,7 @@ static void Hal_ReadPowerValueFromPROM_8
 {
 	u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0;
 
-	_rtw_memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
+	memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
 
 	if (AutoLoadFail) {
 		for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
@@ -2350,29 +1078,6 @@ void Hal_ReadThermalMeter_88E(struct ada
 	DBG_88E("ThermalMeter = 0x%x\n", pHalData->EEPROMThermalMeter);
 }
 
-void Hal_InitChannelPlan(struct adapter *padapter)
-{
-}
-
-bool HalDetectPwrDownMode88E(struct adapter *Adapter)
-{
-	u8 tmpvalue = 0;
-	struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
-	struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
-
-	EFUSE_ShadowRead(Adapter, 1, EEPROM_RF_FEATURE_OPTION_88E, (u32 *)&tmpvalue);
-
-	/*  2010/08/25 MH INF priority > PDN Efuse value. */
-	if (tmpvalue & BIT(4) && pwrctrlpriv->reg_pdnmode)
-		pHalData->pwrdown = true;
-	else
-		pHalData->pwrdown = false;
-
-	DBG_88E("HalDetectPwrDownMode(): PDN =%d\n", pHalData->pwrdown);
-
-	return pHalData->pwrdown;
-}	/*  HalDetectPwrDownMode */
-
 /*  This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
 /*  We just reserve the value of the register in variable pHalData->RegBcnCtrlVal and then operate */
 /*  the value of the register via atomic operation. */
@@ -2388,5 +1093,5 @@ void SetBcnCtrlReg(struct adapter *padap
 	pHalData->RegBcnCtrlVal |= SetBits;
 	pHalData->RegBcnCtrlVal &= ~ClearBits;
 
-	rtw_write8(padapter, REG_BCN_CTRL, (u8)pHalData->RegBcnCtrlVal);
+	usb_write8(padapter, REG_BCN_CTRL, (u8)pHalData->RegBcnCtrlVal);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_mp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,854 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTL8188E_MP_C_
-
-#include <drv_types.h>
-#include <rtw_mp.h>
-#include <rtl8188e_hal.h>
-#include <rtl8188e_dm.h>
-
-s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
-	struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
-
-	if (!netif_running(padapter->pnetdev)) {
-		RT_TRACE(_module_mp_, _drv_warning_,
-			 ("SetPowerTracking! Fail: interface not opened!\n"));
-		return _FAIL;
-	}
-
-	if (!check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE)) {
-		RT_TRACE(_module_mp_, _drv_warning_,
-			 ("SetPowerTracking! Fail: not in MP mode!\n"));
-		return _FAIL;
-	}
-
-	if (enable)
-		pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
-	else
-		pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = false;
-
-	return _SUCCESS;
-}
-
-void Hal_GetPowerTracking(struct adapter *padapter, u8 *enable)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
-	struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
-
-	*enable = pDM_Odm->RFCalibrateInfo.TxPowerTrackControl;
-}
-
-/*-----------------------------------------------------------------------------
- * Function:	mpt_SwitchRfSetting
- *
- * Overview:	Change RF Setting when we siwthc channel/rate/BW for MP.
- *
- * Input:	struct adapter *				pAdapter
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 01/08/2009	MHC		Suggestion from SD3 Willis for 92S series.
- * 01/09/2009	MHC		Add CCK modification for 40MHZ. Suggestion from SD3.
- *
- *---------------------------------------------------------------------------*/
-void Hal_mpt_SwitchRfSetting(struct adapter *pAdapter)
-{
-	struct mp_priv	*pmp = &pAdapter->mppriv;
-
-	/*  <20120525, Kordan> Dynamic mechanism for APK, asked by Dennis. */
-		pmp->MptCtx.backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
-		pmp->MptCtx.backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0);
-		PHY_SetRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0, 0xD);
-		PHY_SetRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0, 0xD);
-
-	return;
-}
-/*---------------------------hal\rtl8192c\MPT_Phy.c---------------------------*/
-
-/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
-void Hal_MPT_CCKTxPowerAdjust(struct adapter *Adapter, bool bInCH14)
-{
-	u32		TempVal = 0, TempVal2 = 0, TempVal3 = 0;
-	u32		CurrCCKSwingVal = 0, CCKSwingIndex = 12;
-	u8		i;
-
-	/*  get current cck swing value and check 0xa22 & 0xa23 later to match the table. */
-	CurrCCKSwingVal = read_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord);
-
-	if (!bInCH14) {
-		/*  Readback the current bb cck swing value and compare with the table to */
-		/*  get the current swing index */
-		for (i = 0; i < CCK_TABLE_SIZE; i++) {
-			if (((CurrCCKSwingVal&0xff) == (u32)CCKSwingTable_Ch1_Ch13[i][0]) &&
-			    (((CurrCCKSwingVal&0xff00)>>8) == (u32)CCKSwingTable_Ch1_Ch13[i][1])) {
-				CCKSwingIndex = i;
-				break;
-			}
-		}
-
-		/* Write 0xa22 0xa23 */
-		TempVal = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][0] +
-				(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][1]<<8);
-
-
-		/* Write 0xa24 ~ 0xa27 */
-		TempVal2 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][2] +
-				(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][3]<<8) +
-				(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][4]<<16)+
-				(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][5]<<24);
-
-		/* Write 0xa28  0xa29 */
-		TempVal3 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][6] +
-				(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][7]<<8);
-	} else {
-		for (i = 0; i < CCK_TABLE_SIZE; i++) {
-			if (((CurrCCKSwingVal&0xff) == (u32)CCKSwingTable_Ch14[i][0]) &&
-			    (((CurrCCKSwingVal&0xff00)>>8) == (u32)CCKSwingTable_Ch14[i][1])) {
-				CCKSwingIndex = i;
-				break;
-			}
-		}
-
-		/* Write 0xa22 0xa23 */
-		TempVal = CCKSwingTable_Ch14[CCKSwingIndex][0] +
-				(CCKSwingTable_Ch14[CCKSwingIndex][1]<<8);
-
-		/* Write 0xa24 ~ 0xa27 */
-		TempVal2 = CCKSwingTable_Ch14[CCKSwingIndex][2] +
-				(CCKSwingTable_Ch14[CCKSwingIndex][3]<<8) +
-				(CCKSwingTable_Ch14[CCKSwingIndex][4]<<16)+
-				(CCKSwingTable_Ch14[CCKSwingIndex][5]<<24);
-
-		/* Write 0xa28  0xa29 */
-		TempVal3 = CCKSwingTable_Ch14[CCKSwingIndex][6] +
-				(CCKSwingTable_Ch14[CCKSwingIndex][7]<<8);
-	}
-
-	write_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord, TempVal);
-	write_bbreg(Adapter, rCCK0_TxFilter2, bMaskDWord, TempVal2);
-	write_bbreg(Adapter, rCCK0_DebugPort, bMaskLWord, TempVal3);
-}
-
-void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-	struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
-	struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
-	s32		TempCCk;
-	u8		CCK_index, CCK_index_old = 0;
-	u8		Action = 0;	/* 0: no action, 1: even->odd, 2:odd->even */
-	s32		i = 0;
-
-
-	if (!IS_92C_SERIAL(pHalData->VersionID))
-		return;
-	if (beven && !pMptCtx->bMptIndexEven) {
-		/* odd->even */
-		Action = 2;
-		pMptCtx->bMptIndexEven = true;
-	} else if (!beven && pMptCtx->bMptIndexEven) {
-		/* even->odd */
-		Action = 1;
-		pMptCtx->bMptIndexEven = false;
-	}
-
-	if (Action != 0) {
-		/* Query CCK default setting From 0xa24 */
-		TempCCk = read_bbreg(pAdapter, rCCK0_TxFilter2, bMaskDWord) & bMaskCCK;
-		for (i = 0; i < CCK_TABLE_SIZE; i++) {
-			if (pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
-				if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4)) {
-					CCK_index_old = (u8)i;
-					break;
-				}
-			} else {
-				if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4)) {
-					CCK_index_old = (u8)i;
-					break;
-				}
-			}
-		}
-
-		if (Action == 1)
-			CCK_index = CCK_index_old - 1;
-		else
-			CCK_index = CCK_index_old + 1;
-
-		if (CCK_index > 32)
-			CCK_index = 32;
-		/* Adjust CCK according to gain index */
-		if (!pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
-			rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]);
-			rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]);
-			rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]);
-			rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]);
-			rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]);
-			rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]);
-			rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]);
-			rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]);
-		} else {
-			rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch14[CCK_index][0]);
-			rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch14[CCK_index][1]);
-			rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch14[CCK_index][2]);
-			rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch14[CCK_index][3]);
-			rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch14[CCK_index][4]);
-			rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch14[CCK_index][5]);
-			rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch14[CCK_index][6]);
-			rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch14[CCK_index][7]);
-		}
-	}
-}
-/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
-
-/*
- * SetChannel
- * Description
- *	Use H2C command to change channel,
- *	not only modify rf register, but also other setting need to be done.
- */
-void Hal_SetChannel(struct adapter *pAdapter)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-	struct mp_priv	*pmp = &pAdapter->mppriv;
-	struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
-	u8		eRFPath;
-	u8		channel = pmp->channel;
-
-	/*  set RF channel register */
-	for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
-		_write_rfreg(pAdapter, eRFPath, ODM_CHANNEL, 0x3FF, channel);
-	Hal_mpt_SwitchRfSetting(pAdapter);
-
-	SelectChannel(pAdapter, channel);
-
-	if (pHalData->CurrentChannel == 14 && !pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
-		pDM_Odm->RFCalibrateInfo.bCCKinCH14 = true;
-		Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
-	} else if (pHalData->CurrentChannel != 14 && pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
-		pDM_Odm->RFCalibrateInfo.bCCKinCH14 = false;
-		Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
-	}
-}
-
-/*
- * Notice
- *	Switch bandwitdth may change center frequency(channel)
- */
-void Hal_SetBandwidth(struct adapter *pAdapter)
-{
-	struct mp_priv *pmp = &pAdapter->mppriv;
-
-
-	SetBWMode(pAdapter, pmp->bandwidth, pmp->prime_channel_offset);
-	Hal_mpt_SwitchRfSetting(pAdapter);
-}
-
-void Hal_SetCCKTxPower(struct adapter *pAdapter, u8 *TxPower)
-{
-	u32 tmpval = 0;
-
-
-	/*  rf-A cck tx power */
-	write_bbreg(pAdapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, TxPower[RF_PATH_A]);
-	tmpval = (TxPower[RF_PATH_A]<<16) | (TxPower[RF_PATH_A]<<8) | TxPower[RF_PATH_A];
-	write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
-
-	/*  rf-B cck tx power */
-	write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, TxPower[RF_PATH_B]);
-	tmpval = (TxPower[RF_PATH_B]<<16) | (TxPower[RF_PATH_B]<<8) | TxPower[RF_PATH_B];
-	write_bbreg(pAdapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
-
-	RT_TRACE(_module_mp_, _drv_notice_,
-		 ("-SetCCKTxPower: A[0x%02x] B[0x%02x]\n",
-		  TxPower[RF_PATH_A], TxPower[RF_PATH_B]));
-}
-
-void Hal_SetOFDMTxPower(struct adapter *pAdapter, u8 *TxPower)
-{
-	u32 TxAGC = 0;
-	u8 tmpval = 0;
-
-	/*  HT Tx-rf(A) */
-	tmpval = TxPower[RF_PATH_A];
-	TxAGC = (tmpval<<24) | (tmpval<<16) | (tmpval<<8) | tmpval;
-
-	write_bbreg(pAdapter, rTxAGC_A_Rate18_06, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_A_Rate54_24, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_A_Mcs03_Mcs00, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_A_Mcs07_Mcs04, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_A_Mcs11_Mcs08, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_A_Mcs15_Mcs12, bMaskDWord, TxAGC);
-
-	/*  HT Tx-rf(B) */
-	tmpval = TxPower[RF_PATH_B];
-	TxAGC = (tmpval<<24) | (tmpval<<16) | (tmpval<<8) | tmpval;
-
-	write_bbreg(pAdapter, rTxAGC_B_Rate18_06, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_B_Rate54_24, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_B_Mcs03_Mcs00, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_B_Mcs07_Mcs04, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_B_Mcs11_Mcs08, bMaskDWord, TxAGC);
-	write_bbreg(pAdapter, rTxAGC_B_Mcs15_Mcs12, bMaskDWord, TxAGC);
-}
-
-void Hal_SetAntennaPathPower(struct adapter *pAdapter)
-{
-	struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
-	u8 TxPowerLevel[MAX_RF_PATH_NUMS];
-	u8 rfPath;
-
-	TxPowerLevel[RF_PATH_A] = pAdapter->mppriv.txpoweridx;
-	TxPowerLevel[RF_PATH_B] = pAdapter->mppriv.txpoweridx_b;
-
-	switch (pAdapter->mppriv.antenna_tx) {
-	case ANTENNA_A:
-	default:
-		rfPath = RF_PATH_A;
-		break;
-	case ANTENNA_B:
-		rfPath = RF_PATH_B;
-		break;
-	case ANTENNA_C:
-		rfPath = RF_PATH_C;
-		break;
-	}
-
-	switch (pHalData->rf_chip) {
-	case RF_8225:
-	case RF_8256:
-	case RF_6052:
-		Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
-		if (pAdapter->mppriv.rateidx < MPT_RATE_6M)	/*  CCK rate */
-			Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath]%2 == 0);
-		Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
-		break;
-	default:
-		break;
-	}
-}
-
-void Hal_SetTxPower(struct adapter *pAdapter)
-{
-	struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
-	u8 TxPower = pAdapter->mppriv.txpoweridx;
-	u8 TxPowerLevel[MAX_RF_PATH_NUMS];
-	u8 rf, rfPath;
-
-	for (rf = 0; rf < MAX_RF_PATH_NUMS; rf++)
-		TxPowerLevel[rf] = TxPower;
-
-	switch (pAdapter->mppriv.antenna_tx) {
-	case ANTENNA_A:
-	default:
-		rfPath = RF_PATH_A;
-		break;
-	case ANTENNA_B:
-		rfPath = RF_PATH_B;
-		break;
-	case ANTENNA_C:
-		rfPath = RF_PATH_C;
-		break;
-	}
-
-	switch (pHalData->rf_chip) {
-	/*  2008/09/12 MH Test only !! We enable the TX power tracking for MP!!!!! */
-	/*  We should call normal driver API later!! */
-	case RF_8225:
-	case RF_8256:
-	case RF_6052:
-		Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
-		if (pAdapter->mppriv.rateidx < MPT_RATE_6M)	/*  CCK rate */
-			Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath]%2 == 0);
-		Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
-		break;
-	default:
-		break;
-	}
-}
-
-void Hal_SetDataRate(struct adapter *pAdapter)
-{
-	Hal_mpt_SwitchRfSetting(pAdapter);
-}
-
-void Hal_SetAntenna(struct adapter *pAdapter)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-
-	struct ant_sel_ofdm *p_ofdm_tx;	/* OFDM Tx register */
-	struct ant_sel_cck *p_cck_txrx;
-	u8	r_rx_antenna_ofdm = 0, r_ant_select_cck_val = 0;
-	u8	chgTx = 0, chgRx = 0;
-	u32	r_ant_select_ofdm_val = 0, r_ofdm_tx_en_val = 0;
-
-
-	p_ofdm_tx = (struct ant_sel_ofdm *)&r_ant_select_ofdm_val;
-	p_cck_txrx = (struct ant_sel_cck *)&r_ant_select_cck_val;
-
-	p_ofdm_tx->r_ant_ht1	= 0x1;
-	p_ofdm_tx->r_ant_ht2	= 0x2;	/*  Second TX RF path is A */
-	p_ofdm_tx->r_ant_non_ht = 0x3;	/*  0x1+0x2=0x3 */
-
-	switch (pAdapter->mppriv.antenna_tx) {
-	case ANTENNA_A:
-		p_ofdm_tx->r_tx_antenna		= 0x1;
-		r_ofdm_tx_en_val		= 0x1;
-		p_ofdm_tx->r_ant_l		= 0x1;
-		p_ofdm_tx->r_ant_ht_s1		= 0x1;
-		p_ofdm_tx->r_ant_non_ht_s1	= 0x1;
-		p_cck_txrx->r_ccktx_enable	= 0x8;
-		chgTx = 1;
-
-		/*  From SD3 Willis suggestion !!! Set RF A=TX and B as standby */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1);
-		r_ofdm_tx_en_val		= 0x3;
-
-		/*  Power save */
-
-		/*  We need to close RFB by SW control */
-		if (pHalData->rf_type == RF_2T2R) {
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 1);
-			PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 0);
-		}
-		break;
-	case ANTENNA_B:
-		p_ofdm_tx->r_tx_antenna		= 0x2;
-		r_ofdm_tx_en_val		= 0x2;
-		p_ofdm_tx->r_ant_l		= 0x2;
-		p_ofdm_tx->r_ant_ht_s1		= 0x2;
-		p_ofdm_tx->r_ant_non_ht_s1	= 0x2;
-		p_cck_txrx->r_ccktx_enable	= 0x4;
-		chgTx = 1;
-		/*  From SD3 Willis suggestion !!! Set RF A as standby */
-		PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1);
-		PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
-
-		/*  Power save */
-		/* cosa r_ant_select_ofdm_val = 0x22222222; */
-
-		/*  2008/10/31 MH From SD3 Willi's suggestion. We must read RF 1T table. */
-		/*  2009/01/08 MH From Sd3 Willis. We need to close RFA by SW control */
-		if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_1T2R) {
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 1);
-			PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1);
-		}
-		break;
-	case ANTENNA_AB:	/*  For 8192S */
-		p_ofdm_tx->r_tx_antenna		= 0x3;
-		r_ofdm_tx_en_val		= 0x3;
-		p_ofdm_tx->r_ant_l		= 0x3;
-		p_ofdm_tx->r_ant_ht_s1		= 0x3;
-		p_ofdm_tx->r_ant_non_ht_s1	= 0x3;
-		p_cck_txrx->r_ccktx_enable	= 0xC;
-		chgTx = 1;
-
-		/*  From SD3 Willis suggestion !!! Set RF B as standby */
-		PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
-		PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
-
-		/*  Disable Power save */
-		/* cosa r_ant_select_ofdm_val = 0x3321333; */
-		/*  2009/01/08 MH From Sd3 Willis. We need to enable RFA/B by SW control */
-		if (pHalData->rf_type == RF_2T2R) {
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1);
-			PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1);
-		}
-		break;
-	default:
-		break;
-	}
-
-	/*  r_rx_antenna_ofdm, bit0=A, bit1=B, bit2=C, bit3=D */
-	/*  r_cckrx_enable : CCK default, 0=A, 1=B, 2=C, 3=D */
-	/*  r_cckrx_enable_2 : CCK option, 0=A, 1=B, 2=C, 3=D */
-	switch (pAdapter->mppriv.antenna_rx) {
-	case ANTENNA_A:
-		r_rx_antenna_ofdm		= 0x1;	/*  A */
-		p_cck_txrx->r_cckrx_enable	= 0x0;	/*  default: A */
-		p_cck_txrx->r_cckrx_enable_2	= 0x0;	/*  option: A */
-		chgRx = 1;
-		break;
-	case ANTENNA_B:
-		r_rx_antenna_ofdm		= 0x2;	/*  B */
-		p_cck_txrx->r_cckrx_enable	= 0x1;	/*  default: B */
-		p_cck_txrx->r_cckrx_enable_2	= 0x1;	/*  option: B */
-		chgRx = 1;
-		break;
-	case ANTENNA_AB:
-		r_rx_antenna_ofdm		= 0x3;	/*  AB */
-		p_cck_txrx->r_cckrx_enable	= 0x0;	/*  default:A */
-		p_cck_txrx->r_cckrx_enable_2	= 0x1;	/*  option:B */
-		chgRx = 1;
-		break;
-	default:
-		break;
-	}
-
-	if (chgTx && chgRx) {
-		switch (pHalData->rf_chip) {
-		case RF_8225:
-		case RF_8256:
-		case RF_6052:
-			/* r_ant_sel_cck_val = r_ant_select_cck_val; */
-			PHY_SetBBReg(pAdapter, rFPGA1_TxInfo, 0x7fffffff, r_ant_select_ofdm_val);	/* OFDM Tx */
-			PHY_SetBBReg(pAdapter, rFPGA0_TxInfo, 0x0000000f, r_ofdm_tx_en_val);		/* OFDM Tx */
-			PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm);	/* OFDM Rx */
-			PHY_SetBBReg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm);	/* OFDM Rx */
-			PHY_SetBBReg(pAdapter, rCCK0_AFESetting, bMaskByte3, r_ant_select_cck_val);	/* CCK TxRx */
-
-			break;
-		default:
-			break;
-		}
-	}
-
-	RT_TRACE(_module_mp_, _drv_notice_, ("-SwitchAntenna: finished\n"));
-}
-
-s32 Hal_SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
-{
-	struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
-
-
-	if (!netif_running(pAdapter->pnetdev)) {
-		RT_TRACE(_module_mp_, _drv_warning_, ("SetThermalMeter! Fail: interface not opened!\n"));
-		return _FAIL;
-	}
-
-	if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) {
-		RT_TRACE(_module_mp_, _drv_warning_, ("SetThermalMeter: Fail! not in MP mode!\n"));
-		return _FAIL;
-	}
-
-	target_ther &= 0xff;
-	if (target_ther < 0x07)
-		target_ther = 0x07;
-	else if (target_ther > 0x1d)
-		target_ther = 0x1d;
-
-	pHalData->EEPROMThermalMeter = target_ther;
-
-	return _SUCCESS;
-}
-
-void Hal_TriggerRFThermalMeter(struct adapter *pAdapter)
-{
-	_write_rfreg(pAdapter, RF_PATH_A , RF_T_METER_88E , BIT17 | BIT16 , 0x03);
-}
-
-u8 Hal_ReadRFThermalMeter(struct adapter *pAdapter)
-{
-	u32 ThermalValue = 0;
-
-	ThermalValue = _read_rfreg(pAdapter, RF_PATH_A, RF_T_METER_88E, 0xfc00);
-	return (u8)ThermalValue;
-}
-
-void Hal_GetThermalMeter(struct adapter *pAdapter, u8 *value)
-{
-	Hal_TriggerRFThermalMeter(pAdapter);
-	msleep(1000);
-	*value = Hal_ReadRFThermalMeter(pAdapter);
-}
-
-void Hal_SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
-{
-	pAdapter->mppriv.MptCtx.bSingleCarrier = bStart;
-	if (bStart) {
-		/*  Start Single Carrier. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleCarrierTx: test start\n"));
-		/*  1. if OFDM block on? */
-		if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
-			write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
-
-		/*  2. set CCK test mode off, set to CCK normal mode */
-		write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
-		/*  3. turn on scramble setting */
-		write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
-		/*  4. Turn On Single Carrier Tx and turn off the other test modes. */
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-		/* for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
-	} else {
-		/*  Stop Single Carrier. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleCarrierTx: test stop\n"));
-
-		/*  Turn off all test modes. */
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-		msleep(10);
-
-		/* BB Reset */
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
-
-		/* Stop for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
-	}
-}
-
-
-void Hal_SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(pAdapter);
-	bool		is92C = IS_92C_SERIAL(pHalData->VersionID);
-
-	u8 rfPath;
-	u32              reg58 = 0x0;
-	switch (pAdapter->mppriv.antenna_tx) {
-	case ANTENNA_A:
-	default:
-		rfPath = RF_PATH_A;
-		break;
-	case ANTENNA_B:
-		rfPath = RF_PATH_B;
-		break;
-	case ANTENNA_C:
-		rfPath = RF_PATH_C;
-		break;
-	}
-
-	pAdapter->mppriv.MptCtx.bSingleTone = bStart;
-	if (bStart) {
-		/*  Start Single Tone. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleToneTx: test start\n"));
-		/*  <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
-		reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
-		reg58 &= 0xFFFFFFF0;
-		reg58 += 2;
-		PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
-		PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x0);
-		PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x0);
-
-		if (is92C) {
-			_write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT19, 0x01);
-			msleep(1);
-			if (rfPath == RF_PATH_A)
-				write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x10000); /*  PAD all on. */
-			else if (rfPath == RF_PATH_B)
-				write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x10000); /*  PAD all on. */
-			write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /*  PAD all on. */
-			msleep(1);
-		} else {
-			write_rfreg(pAdapter, rfPath, 0x21, 0xd4000);
-			msleep(1);
-			write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /*  PAD all on. */
-			msleep(1);
-		}
-
-		/* for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
-
-	} else {
-		/*  Stop Single Tone. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleToneTx: test stop\n"));
-
-		/*  <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
-		/*  <20120326, Kordan> Only in single tone mode. (asked by Edlu) */
-		reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
-		reg58 &= 0xFFFFFFF0;
-		PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
-		write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x1);
-		write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
-		if (is92C) {
-			_write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT19, 0x00);
-			msleep(1);
-			write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x32d75); /*  PAD all on. */
-			write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x32d75); /*  PAD all on. */
-			msleep(1);
-		} else {
-			write_rfreg(pAdapter, rfPath, 0x21, 0x54000);
-			msleep(1);
-			write_rfreg(pAdapter, rfPath, 0x00, 0x30000); /*  PAD all on. */
-			msleep(1);
-		}
-
-		/* Stop for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
-	}
-}
-
-
-
-void Hal_SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
-{
-	pAdapter->mppriv.MptCtx.bCarrierSuppression = bStart;
-	if (bStart) {
-		/*  Start Carrier Suppression. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetCarrierSuppressionTx: test start\n"));
-		if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
-			/*  1. if CCK block on? */
-			if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
-				write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
-
-			/* Turn Off All Test Mode */
-			write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
-			write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
-			write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-
-			write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);    /* transmit mode */
-			write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x0);  /* turn off scramble setting */
-
-			/* Set CCK Tx Test Rate */
-			write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, 0x0);    /* Set FTxRate to 1Mbps */
-		}
-
-		/* for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
-	} else {
-		/*  Stop Carrier Suppression. */
-		RT_TRACE(_module_mp_, _drv_alert_, ("SetCarrierSuppressionTx: test stop\n"));
-		if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
-			write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);    /* normal mode */
-			write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x1);  /* turn on scramble setting */
-
-			/* BB Reset */
-			write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
-			write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
-		}
-
-		/* Stop for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
-	}
-}
-
-void Hal_SetCCKContinuousTx(struct adapter *pAdapter, u8 bStart)
-{
-	u32 cckrate;
-
-	if (bStart) {
-		RT_TRACE(_module_mp_, _drv_alert_,
-			 ("SetCCKContinuousTx: test start\n"));
-
-		/*  1. if CCK block on? */
-		if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
-			write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
-
-		/* Turn Off All Test Mode */
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-		/* Set CCK Tx Test Rate */
-		cckrate  = pAdapter->mppriv.rateidx;
-		write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, cckrate);
-		write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);	/* transmit mode */
-		write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);	/* turn on scramble setting */
-
-		/* for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
-	} else {
-		RT_TRACE(_module_mp_, _drv_info_,
-			 ("SetCCKContinuousTx: test stop\n"));
-
-		write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);	/* normal mode */
-		write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);	/* turn on scramble setting */
-
-		/* BB Reset */
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
-
-		/* Stop for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
-	}
-
-	pAdapter->mppriv.MptCtx.bCckContTx = bStart;
-	pAdapter->mppriv.MptCtx.bOfdmContTx = false;
-} /* mpt_StartCckContTx */
-
-void Hal_SetOFDMContinuousTx(struct adapter *pAdapter, u8 bStart)
-{
-	if (bStart) {
-		RT_TRACE(_module_mp_, _drv_info_, ("SetOFDMContinuousTx: test start\n"));
-		/*  1. if OFDM block on? */
-		if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
-			write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
-
-		/*  2. set CCK test mode off, set to CCK normal mode */
-		write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
-
-		/*  3. turn on scramble setting */
-		write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
-		/*  4. Turn On Continue Tx and turn off the other test modes. */
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-
-		/* for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
-
-	} else {
-		RT_TRACE(_module_mp_, _drv_info_, ("SetOFDMContinuousTx: test stop\n"));
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
-		write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
-		/* Delay 10 ms */
-		msleep(10);
-		/* BB Reset */
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
-		write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
-
-		/* Stop for dynamic set Power index. */
-		write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
-		write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
-	}
-
-	pAdapter->mppriv.MptCtx.bCckContTx = false;
-	pAdapter->mppriv.MptCtx.bOfdmContTx = bStart;
-} /* mpt_StartOfdmContTx */
-
-void Hal_SetContinuousTx(struct adapter *pAdapter, u8 bStart)
-{
-	RT_TRACE(_module_mp_, _drv_info_,
-		 ("SetContinuousTx: rate:%d\n", pAdapter->mppriv.rateidx));
-
-	pAdapter->mppriv.MptCtx.bStartContTx = bStart;
-	if (pAdapter->mppriv.rateidx <= MPT_RATE_11M)
-		Hal_SetCCKContinuousTx(pAdapter, bStart);
-	else if ((pAdapter->mppriv.rateidx >= MPT_RATE_6M) &&
-		 (pAdapter->mppriv.rateidx <= MPT_RATE_MCS15))
-		Hal_SetOFDMContinuousTx(pAdapter, bStart);
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c	2014-09-28 17:29:07.000000000 -0400
@@ -94,7 +94,7 @@ rtl8188e_PHY_QueryBBReg(
 {
 	u32 ReturnValue = 0, OriginalValue, BitShift;
 
-	OriginalValue = rtw_read32(Adapter, RegAddr);
+	OriginalValue = usb_read32(Adapter, RegAddr);
 	BitShift = phy_CalculateBitShift(BitMask);
 	ReturnValue = (OriginalValue & BitMask) >> BitShift;
 	return ReturnValue;
@@ -124,12 +124,12 @@ void rtl8188e_PHY_SetBBReg(struct adapte
 	u32 OriginalValue, BitShift;
 
 	if (BitMask != bMaskDWord) { /* if not "double word" write */
-		OriginalValue = rtw_read32(Adapter, RegAddr);
+		OriginalValue = usb_read32(Adapter, RegAddr);
 		BitShift = phy_CalculateBitShift(BitMask);
 		Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
 	}
 
-	rtw_write32(Adapter, RegAddr, Data);
+	usb_write32(Adapter, RegAddr, Data);
 }
 
 
@@ -386,7 +386,7 @@ s32 PHY_MACConfig8188E(struct adapter *A
 		rtStatus = _FAIL;
 
 	/*  2010.07.13 AMPDU aggregation number B */
-	rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
+	usb_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
 
 	return rtStatus;
 }
@@ -603,14 +603,14 @@ PHY_BBConfig8188E(
 
 
 	/*  Enable BB and RF */
-	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
-	rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal|BIT13|BIT0|BIT1));
+	RegVal = usb_read16(Adapter, REG_SYS_FUNC_EN);
+	usb_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal|BIT13|BIT0|BIT1));
 
 	/*  20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
 
-	rtw_write8(Adapter, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
+	usb_write8(Adapter, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
 
-	rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+	usb_write8(Adapter, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
 
 	/*  Config BB and AGC */
 	rtStatus = phy_BB8188E_Config_ParaFile(Adapter);
@@ -792,21 +792,21 @@ _PHY_SetBWMode92C(
 	/* 3<1>Set MAC register */
 	/* 3 */
 
-	regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
-	regRRSR_RSC = rtw_read8(Adapter, REG_RRSR+2);
+	regBwOpMode = usb_read8(Adapter, REG_BWOPMODE);
+	regRRSR_RSC = usb_read8(Adapter, REG_RRSR+2);
 
 	switch (pHalData->CurrentChannelBW) {
 	case HT_CHANNEL_WIDTH_20:
 		regBwOpMode |= BW_OPMODE_20MHZ;
 		/*  2007/02/07 Mark by Emily because we have not verify whether this register works */
-		rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
+		usb_write8(Adapter, REG_BWOPMODE, regBwOpMode);
 		break;
 	case HT_CHANNEL_WIDTH_40:
 		regBwOpMode &= ~BW_OPMODE_20MHZ;
 		/*  2007/02/07 Mark by Emily because we have not verify whether this register works */
-		rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
+		usb_write8(Adapter, REG_BWOPMODE, regBwOpMode);
 		regRRSR_RSC = (regRRSR_RSC&0x90) | (pHalData->nCur40MhzPrimeSC<<5);
-		rtw_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
+		usb_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
 		break;
 	default:
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c	2014-09-28 17:29:07.000000000 -0400
@@ -366,7 +366,7 @@ static void writeOFDMPowerReg88E(struct
 					writeVal = (writeVal > 8) ? (writeVal-8) : 0;
 				else
 					writeVal = (writeVal > 6) ? (writeVal-6) : 0;
-				rtw_write8(Adapter, (u32)(regoffset+i), (u8)writeVal);
+				usb_write8(Adapter, (u32)(regoffset+i), (u8)writeVal);
 			}
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,7 +86,7 @@ void update_recvframe_attrib_88e(struct
 	report.rxdw5 = prxstat->rxdw5;
 
 	pattrib = &precvframe->attrib;
-	_rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
+	memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
 
 	pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);/* u8)prxreport->crc32; */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _RTL8188E_SRESET_C_
-
-#include <rtl8188e_sreset.h>
-#include <rtl8188e_hal.h>
-
-void rtl8188e_silentreset_for_specific_platform(struct adapter *padapter)
-{
-}
-
-void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
-	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
-	unsigned long current_time;
-	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
-	unsigned int diff_time;
-	u32 txdma_status;
-
-	txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
-	if (txdma_status != 0x00) {
-		DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
-		rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
-		rtl8188e_silentreset_for_specific_platform(padapter);
-	}
-	/* total xmit irp = 4 */
-	current_time = jiffies;
-	if (0 == pxmitpriv->free_xmitbuf_cnt) {
-		diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_time);
-
-		if (diff_time > 2000) {
-			if (psrtpriv->last_tx_complete_time == 0) {
-				psrtpriv->last_tx_complete_time = current_time;
-			} else {
-				diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_complete_time);
-				if (diff_time > 4000) {
-					DBG_88E("%s tx hang\n", __func__);
-					rtl8188e_silentreset_for_specific_platform(padapter);
-				}
-			}
-		}
-	}
-}
-
-void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
-{
-	u32 rx_dma_status = 0;
-	u8 fw_status = 0;
-	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
-	if (rx_dma_status != 0x00) {
-		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
-		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
-	}
-	fw_status = rtw_read8(padapter, REG_FMETHR);
-	if (fw_status != 0x00) {
-		if (fw_status == 1)
-			DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
-		else if (fw_status == 2)
-			DBG_88E("%s REG_FW_STATUS (0x%02x), Condition_No_Match !!\n", __func__, fw_status);
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #include <drv_types.h>
 #include <rtl8188e_hal.h>
 #include <rtl8188e_led.h>
+#include <usb_ops_linux.h>
 
 /*  LED object. */
 
@@ -34,8 +35,8 @@ void SwLedOn(struct adapter *padapter, s
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return;
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);
-	rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0)|BIT5|BIT6); /*  SW control led0 on. */
+	LedCfg = usb_read8(padapter, REG_LEDCFG2);
+	usb_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0)|BIT5|BIT6); /*  SW control led0 on. */
 	pLed->bLedOn = true;
 }
 
@@ -49,17 +50,17 @@ void SwLedOff(struct adapter *padapter,
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		goto exit;
 
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
+	LedCfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */
 
 	if (pHalData->bLedOpenDrain) {
 			/*  Open-drain arrangement for controlling the LED) */
 		LedCfg &= 0x90; /*  Set to software control. */
-		rtw_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
-		LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
+		usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
+		LedCfg = usb_read8(padapter, REG_MAC_PINMUX_CFG);
 		LedCfg &= 0xFE;
-		rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
+		usb_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
 	} else {
-		rtw_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3|BIT5|BIT6));
+		usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3|BIT5|BIT6));
 	}
 exit:
 	pLed->bLedOn = false;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 #include <recv_osdep.h>
 #include <mlme_osdep.h>
 
-#include <usb_ops.h>
+#include <usb_ops_linux.h>
 #include <wifi.h>
 
 #include <rtl8188e_hal.h>
@@ -41,13 +41,13 @@ int	rtl8188eu_init_recv_priv(struct adap
 	/* init recv_buf */
 	_rtw_init_queue(&precvpriv->free_recv_buf_queue);
 
-	precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4);
+	precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_KERNEL);
 	if (precvpriv->pallocated_recv_buf == NULL) {
 		res = _FAIL;
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
 		goto exit;
 	}
-	_rtw_memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
+	memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
 
 	precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_recv_buf), 4);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,7 +22,7 @@
 #include <drv_types.h>
 #include <wifi.h>
 #include <osdep_intf.h>
-#include <usb_ops.h>
+#include <usb_ops_linux.h>
 #include <rtl8188e_hal.h>
 
 s32	rtl8188eu_init_xmit_priv(struct adapter *adapt)
@@ -35,10 +35,6 @@ s32	rtl8188eu_init_xmit_priv(struct adap
 	return _SUCCESS;
 }
 
-void	rtl8188eu_free_xmit_priv(struct adapter *adapt)
-{
-}
-
 static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
 {
 	u8 set_tx_desc_offset;
@@ -72,7 +68,7 @@ void rtl8188e_fill_fake_txdesc(struct ad
 
 	/*  Clear all status */
 	ptxdesc = (struct tx_desc *)desc;
-	_rtw_memset(desc, 0, TXDESC_SIZE);
+	memset(desc, 0, TXDESC_SIZE);
 
 	/* offset 0 */
 	ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */
@@ -196,7 +192,7 @@ static s32 update_txdesc(struct xmit_fra
 		}
 	}
 
-	_rtw_memset(ptxdesc, 0, sizeof(struct tx_desc));
+	memset(ptxdesc, 0, sizeof(struct tx_desc));
 
 	/* 4 offset 0 */
 	ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
@@ -310,9 +306,6 @@ static s32 update_txdesc(struct xmit_fra
 		ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
 	} else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
 		DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
-	} else if (((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) &&
-		   (adapt->registrypriv.mp_mode == 1)) {
-		fill_txdesc_for_mp(adapt, ptxdesc);
 	} else {
 		DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
 
@@ -397,7 +390,7 @@ static s32 rtw_dump_xframe(struct adapte
 		}
 		ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
 
-		inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
+		inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
 
 		rtw_count_tx_stats(adapt, pxmitframe, sz);
 
@@ -405,7 +398,7 @@ static s32 rtw_dump_xframe(struct adapte
 
 		mem_addr += w_sz;
 
-		mem_addr = (u8 *)RND4(((size_t)(mem_addr)));
+		mem_addr = (u8 *) round_up((size_t)mem_addr, 4);
 	}
 
 	rtw_free_xmitframe(pxmitpriv, pxmitframe);
@@ -497,7 +490,7 @@ s32 rtl8188eu_xmitframe_complete(struct
 	pfirstframe = pxmitframe;
 	len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ);
 	pbuf_tail = len;
-	pbuf = _RND8(pbuf_tail);
+	pbuf = round_up(pbuf_tail, 8);
 
 	/*  check pkt amount in one bulk */
 	desc_cnt = 0;
@@ -539,7 +532,7 @@ s32 rtl8188eu_xmitframe_complete(struct
 	xmitframe_phead = get_list_head(&ptxservq->sta_pending);
 	xmitframe_plist = xmitframe_phead->next;
 
-	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+	while (xmitframe_phead != xmitframe_plist) {
 		pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
 		xmitframe_plist = xmitframe_plist->next;
 
@@ -548,12 +541,12 @@ s32 rtl8188eu_xmitframe_complete(struct
 
 		len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ);
 
-		if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) {
+		if (round_up(pbuf + len, 8) > MAX_XMITBUF_SZ) {
 			pxmitframe->agg_num = 1;
 			pxmitframe->pkt_offset = 1;
 			break;
 		}
-		rtw_list_delete(&pxmitframe->list);
+		list_del_init(&pxmitframe->list);
 		ptxservq->qcnt--;
 		phwxmit->accnt--;
 
@@ -571,7 +564,7 @@ s32 rtl8188eu_xmitframe_complete(struct
 
 		/*  handle pointer and stop condition */
 		pbuf_tail = pbuf + len;
-		pbuf = _RND8(pbuf_tail);
+		pbuf = round_up(pbuf_tail, 8);
 
 		pfirstframe->agg_num++;
 		if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
@@ -587,8 +580,8 @@ s32 rtl8188eu_xmitframe_complete(struct
 		}
 	} /* end while (aggregate same priority and same DA(AP or STA) frames) */
 
-	if (_rtw_queue_empty(&ptxservq->sta_pending) == true)
-		rtw_list_delete(&ptxservq->tx_pending);
+	if (list_empty(&ptxservq->sta_pending.queue))
+		list_del_init(&ptxservq->tx_pending);
 
 	spin_unlock_bh(&pxmitpriv->lock);
 	if ((pfirstframe->attrib.ether_type != 0x0806) &&
@@ -608,7 +601,7 @@ s32 rtl8188eu_xmitframe_complete(struct
 
 	/* 3 4. write xmit buffer to USB FIFO */
 	ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
-	rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
+	usb_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
 
 	/* 3 5. update statisitc */
 	pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/usb_halinit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/usb_halinit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/usb_halinit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/usb_halinit.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,9 +26,7 @@
 #include <rtl8188e_hal.h>
 #include <rtl8188e_led.h>
 #include <rtw_iol.h>
-#include <usb_ops.h>
 #include <usb_hal.h>
-#include <usb_osintf.h>
 
 #define		HAL_MAC_ENABLE	1
 #define		HAL_BB_ENABLE		1
@@ -117,15 +115,15 @@ static u32 rtl8188eu_InitPowerOn(struct
 
 	/*  Enable MAC DMA/WMAC/SCHEDULE/SEC block */
 	/*  Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
-	rtw_write16(adapt, REG_CR, 0x00);  /* suggseted by zhouzhou, by page, 20111230 */
+	usb_write16(adapt, REG_CR, 0x00);  /* suggseted by zhouzhou, by page, 20111230 */
 
 		/*  Enable MAC DMA/WMAC/SCHEDULE/SEC block */
-	value16 = rtw_read16(adapt, REG_CR);
+	value16 = usb_read16(adapt, REG_CR);
 	value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
 				| PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
 	/*  for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
 
-	rtw_write16(adapt, REG_CR, value16);
+	usb_write16(adapt, REG_CR, value16);
 	haldata->bMacPwrCtrlOn = true;
 
 	return _SUCCESS;
@@ -139,27 +137,27 @@ static void _InitInterrupt(struct adapte
 	struct hal_data_8188e	*haldata = GET_HAL_DATA(Adapter);
 
 	/* HISR write one to clear */
-	rtw_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF);
+	usb_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF);
 	/*  HIMR - */
 	imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E;
-	rtw_write32(Adapter, REG_HIMR_88E, imr);
+	usb_write32(Adapter, REG_HIMR_88E, imr);
 	haldata->IntrMask[0] = imr;
 
 	imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E;
-	rtw_write32(Adapter, REG_HIMRE_88E, imr_ex);
+	usb_write32(Adapter, REG_HIMRE_88E, imr_ex);
 	haldata->IntrMask[1] = imr_ex;
 
 	/*  REG_USB_SPECIAL_OPTION - BIT(4) */
 	/*  0; Use interrupt endpoint to upload interrupt pkt */
 	/*  1; Use bulk endpoint to upload interrupt pkt, */
-	usb_opt = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION);
+	usb_opt = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
 
 	if (!adapter_to_dvobj(Adapter)->ishighspeed)
 		usb_opt = usb_opt & (~INT_BULK_SEL);
 	else
 		usb_opt = usb_opt | (INT_BULK_SEL);
 
-	rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt);
+	usb_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt);
 }
 
 static void _InitQueueReservedPage(struct adapter *Adapter)
@@ -185,27 +183,27 @@ static void _InitQueueReservedPage(struc
 		if (haldata->OutEpQueueSel & TX_SELE_NQ)
 			numNQ = 0x1C;
 		value8 = (u8)_NPQ(numNQ);
-		rtw_write8(Adapter, REG_RQPN_NPQ, value8);
+		usb_write8(Adapter, REG_RQPN_NPQ, value8);
 
 		numPubQ = 0xA8 - numHQ - numLQ - numNQ;
 
 		/*  TX DMA */
 		value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
-		rtw_write32(Adapter, REG_RQPN, value32);
+		usb_write32(Adapter, REG_RQPN, value32);
 	} else {
-		rtw_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */
-		rtw_write16(Adapter, REG_RQPN_NPQ, 0x0d);
-		rtw_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */
+		usb_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */
+		usb_write16(Adapter, REG_RQPN_NPQ, 0x0d);
+		usb_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */
 	}
 }
 
 static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy)
 {
-	rtw_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
-	rtw_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
-	rtw_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
-	rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
-	rtw_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy);
+	usb_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+	usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
+	usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
+	usb_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy);
 }
 
 static void _InitPageBoundary(struct adapter *Adapter)
@@ -214,20 +212,20 @@ static void _InitPageBoundary(struct ada
 	/*  */
 	u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E-1;
 
-	rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
+	usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
 }
 
 static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
 				       u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
 				       u16 hiQ)
 {
-	u16 value16	= (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+	u16 value16	= (usb_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
 
 	value16 |= _TXDMA_BEQ_MAP(beQ)	| _TXDMA_BKQ_MAP(bkQ) |
 		   _TXDMA_VIQ_MAP(viQ)	| _TXDMA_VOQ_MAP(voQ) |
 		   _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
 
-	rtw_write16(Adapter, REG_TRXDMA_CTRL, value16);
+	usb_write16(Adapter, REG_TRXDMA_CTRL, value16);
 }
 
 static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter)
@@ -341,11 +339,11 @@ static void _InitNetworkType(struct adap
 {
 	u32 value32;
 
-	value32 = rtw_read32(Adapter, REG_CR);
+	value32 = usb_read32(Adapter, REG_CR);
 	/*  TODO: use the other function to set network type */
 	value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
 
-	rtw_write32(Adapter, REG_CR, value32);
+	usb_write32(Adapter, REG_CR, value32);
 }
 
 static void _InitTransferPageSize(struct adapter *Adapter)
@@ -354,12 +352,12 @@ static void _InitTransferPageSize(struct
 
 	u8 value8;
 	value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
-	rtw_write8(Adapter, REG_PBP, value8);
+	usb_write8(Adapter, REG_PBP, value8);
 }
 
 static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize)
 {
-	rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
+	usb_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
 }
 
 static void _InitWMACSetting(struct adapter *Adapter)
@@ -372,11 +370,11 @@ static void _InitWMACSetting(struct adap
 				  RCR_APP_MIC | RCR_APP_PHYSTS;
 
 	/*  some REG_RCR will be modified later by phy_ConfigMACWithHeaderFile() */
-	rtw_write32(Adapter, REG_RCR, haldata->ReceiveConfig);
+	usb_write32(Adapter, REG_RCR, haldata->ReceiveConfig);
 
 	/*  Accept all multicast address */
-	rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF);
-	rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
+	usb_write32(Adapter, REG_MAR, 0xFFFFFFFF);
+	usb_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
 }
 
 static void _InitAdaptiveCtrl(struct adapter *Adapter)
@@ -385,64 +383,64 @@ static void _InitAdaptiveCtrl(struct ada
 	u32 value32;
 
 	/*  Response Rate Set */
-	value32 = rtw_read32(Adapter, REG_RRSR);
+	value32 = usb_read32(Adapter, REG_RRSR);
 	value32 &= ~RATE_BITMAP_ALL;
 	value32 |= RATE_RRSR_CCK_ONLY_1M;
-	rtw_write32(Adapter, REG_RRSR, value32);
+	usb_write32(Adapter, REG_RRSR, value32);
 
 	/*  CF-END Threshold */
 
 	/*  SIFS (used in NAV) */
 	value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
-	rtw_write16(Adapter, REG_SPEC_SIFS, value16);
+	usb_write16(Adapter, REG_SPEC_SIFS, value16);
 
 	/*  Retry Limit */
 	value16 = _LRL(0x30) | _SRL(0x30);
-	rtw_write16(Adapter, REG_RL, value16);
+	usb_write16(Adapter, REG_RL, value16);
 }
 
 static void _InitEDCA(struct adapter *Adapter)
 {
 	/*  Set Spec SIFS (used in NAV) */
-	rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a);
-	rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
+	usb_write16(Adapter, REG_SPEC_SIFS, 0x100a);
+	usb_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
 
 	/*  Set SIFS for CCK */
-	rtw_write16(Adapter, REG_SIFS_CTX, 0x100a);
+	usb_write16(Adapter, REG_SIFS_CTX, 0x100a);
 
 	/*  Set SIFS for OFDM */
-	rtw_write16(Adapter, REG_SIFS_TRX, 0x100a);
+	usb_write16(Adapter, REG_SIFS_TRX, 0x100a);
 
 	/*  TXOP */
-	rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
-	rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
-	rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
-	rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
+	usb_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
+	usb_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
+	usb_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
+	usb_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
 }
 
 static void _InitRDGSetting(struct adapter *Adapter)
 {
-	rtw_write8(Adapter, REG_RD_CTRL, 0xFF);
-	rtw_write16(Adapter, REG_RD_NAV_NXT, 0x200);
-	rtw_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
+	usb_write8(Adapter, REG_RD_CTRL, 0xFF);
+	usb_write16(Adapter, REG_RD_NAV_NXT, 0x200);
+	usb_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
 }
 
 static void _InitRxSetting(struct adapter *Adapter)
 {
-	rtw_write32(Adapter, REG_MACID, 0x87654321);
-	rtw_write32(Adapter, 0x0700, 0x87654321);
+	usb_write32(Adapter, REG_MACID, 0x87654321);
+	usb_write32(Adapter, 0x0700, 0x87654321);
 }
 
 static void _InitRetryFunction(struct adapter *Adapter)
 {
 	u8 value8;
 
-	value8 = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL);
+	value8 = usb_read8(Adapter, REG_FWHW_TXQ_CTRL);
 	value8 |= EN_AMPDU_RTY_NEW;
-	rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
+	usb_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
 
 	/*  Set ACK timeout */
-	rtw_write8(Adapter, REG_ACKTO, 0x40);
+	usb_write8(Adapter, REG_ACKTO, 0x40);
 }
 
 /*-----------------------------------------------------------------------------
@@ -469,11 +467,11 @@ static void usb_AggSettingTxUpdate(struc
 		haldata->UsbTxAggMode = false;
 
 	if (haldata->UsbTxAggMode) {
-		value32 = rtw_read32(Adapter, REG_TDECTRL);
+		value32 = usb_read32(Adapter, REG_TDECTRL);
 		value32 = value32 & ~(BLK_DESC_NUM_MASK << BLK_DESC_NUM_SHIFT);
 		value32 |= ((haldata->UsbTxAggDescNum & BLK_DESC_NUM_MASK) << BLK_DESC_NUM_SHIFT);
 
-		rtw_write32(Adapter, REG_TDECTRL, value32);
+		usb_write32(Adapter, REG_TDECTRL, value32);
 	}
 }	/*  usb_AggSettingTxUpdate */
 
@@ -501,8 +499,8 @@ usb_AggSettingRxUpdate(
 	u8 valueDMA;
 	u8 valueUSB;
 
-	valueDMA = rtw_read8(Adapter, REG_TRXDMA_CTRL);
-	valueUSB = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION);
+	valueDMA = usb_read8(Adapter, REG_TRXDMA_CTRL);
+	valueUSB = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
 
 	switch (haldata->UsbRxAggMode) {
 	case USB_RX_AGG_DMA:
@@ -524,23 +522,23 @@ usb_AggSettingRxUpdate(
 		break;
 	}
 
-	rtw_write8(Adapter, REG_TRXDMA_CTRL, valueDMA);
-	rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB);
+	usb_write8(Adapter, REG_TRXDMA_CTRL, valueDMA);
+	usb_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB);
 
 	switch (haldata->UsbRxAggMode) {
 	case USB_RX_AGG_DMA:
-		rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
-		rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, haldata->UsbRxAggPageTimeout);
+		usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+		usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, haldata->UsbRxAggPageTimeout);
 		break;
 	case USB_RX_AGG_USB:
-		rtw_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
-		rtw_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+		usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+		usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
 		break;
 	case USB_RX_AGG_MIX:
-		rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
-		rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */
-		rtw_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
-		rtw_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+		usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+		usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */
+		usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+		usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
 		break;
 	case USB_RX_AGG_DISABLE:
 	default:
@@ -587,30 +585,30 @@ static void _InitBeaconParameters(struct
 {
 	struct hal_data_8188e	*haldata = GET_HAL_DATA(Adapter);
 
-	rtw_write16(Adapter, REG_BCN_CTRL, 0x1010);
+	usb_write16(Adapter, REG_BCN_CTRL, 0x1010);
 
 	/*  TODO: Remove these magic number */
-	rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/*  ms */
-	rtw_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*  5ms */
-	rtw_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /*  2ms */
+	usb_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/*  ms */
+	usb_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*  5ms */
+	usb_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /*  2ms */
 
 	/*  Suggested by designer timchen. Change beacon AIFS to the largest number */
 	/*  beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */
-	rtw_write16(Adapter, REG_BCNTCFG, 0x660F);
+	usb_write16(Adapter, REG_BCNTCFG, 0x660F);
 
-	haldata->RegBcnCtrlVal = rtw_read8(Adapter, REG_BCN_CTRL);
-	haldata->RegTxPause = rtw_read8(Adapter, REG_TXPAUSE);
-	haldata->RegFwHwTxQCtrl = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL+2);
-	haldata->RegReg542 = rtw_read8(Adapter, REG_TBTT_PROHIBIT+2);
-	haldata->RegCR_1 = rtw_read8(Adapter, REG_CR+1);
+	haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL);
+	haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE);
+	haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL+2);
+	haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT+2);
+	haldata->RegCR_1 = usb_read8(Adapter, REG_CR+1);
 }
 
 static void _BeaconFunctionEnable(struct adapter *Adapter,
 				  bool Enable, bool Linked)
 {
-	rtw_write8(Adapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1));
+	usb_write8(Adapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1));
 
-	rtw_write8(Adapter, REG_RD_CTRL+1, 0x6F);
+	usb_write8(Adapter, REG_RD_CTRL+1, 0x6F);
 }
 
 /*  Set CCK and OFDM Block "ON" */
@@ -633,7 +631,7 @@ static void _InitAntenna_Selection(struc
 		return;
 	DBG_88E("==>  %s ....\n", __func__);
 
-	rtw_write32(Adapter, REG_LEDCFG0, rtw_read32(Adapter, REG_LEDCFG0)|BIT23);
+	usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0)|BIT23);
 	PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, BIT13, 0x01);
 
 	if (PHY_QueryBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
@@ -664,12 +662,12 @@ enum rt_rf_power_state RfOnOffDetect(str
 	enum rt_rf_power_state rfpowerstate = rf_off;
 
 	if (adapt->pwrctrlpriv.bHWPowerdown) {
-		val8 = rtw_read8(adapt, REG_HSISR);
+		val8 = usb_read8(adapt, REG_HSISR);
 		DBG_88E("pwrdown, 0x5c(BIT7)=%02x\n", val8);
 		rfpowerstate = (val8 & BIT7) ? rf_off : rf_on;
 	} else { /*  rf on/off */
-		rtw_write8(adapt, REG_MAC_PINMUX_CFG, rtw_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT3));
-		val8 = rtw_read8(adapt, REG_GPIO_IO_SEL);
+		usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT3));
+		val8 = usb_read8(adapt, REG_GPIO_IO_SEL);
 		DBG_88E("GPIO_IN=%02x\n", val8);
 		rfpowerstate = (val8 & BIT3) ? rf_on : rf_off;
 	}
@@ -823,26 +821,26 @@ static u32 rtl8188eu_hal_init(struct ada
 	/*  Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */
 	/*  Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
 	/*  Enable MACTXEN/MACRXEN block */
-	value16 = rtw_read16(Adapter, REG_CR);
+	value16 = usb_read16(Adapter, REG_CR);
 	value16 |= (MACTXEN | MACRXEN);
-	rtw_write8(Adapter, REG_CR, value16);
+	usb_write8(Adapter, REG_CR, value16);
 
 	if (haldata->bRDGEnable)
 		_InitRDGSetting(Adapter);
 
 	/* Enable TX Report */
 	/* Enable Tx Report Timer */
-	value8 = rtw_read8(Adapter, REG_TX_RPT_CTRL);
-	rtw_write8(Adapter,  REG_TX_RPT_CTRL, (value8|BIT1|BIT0));
+	value8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+	usb_write8(Adapter,  REG_TX_RPT_CTRL, (value8|BIT1|BIT0));
 	/* Set MAX RPT MACID */
-	rtw_write8(Adapter,  REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
+	usb_write8(Adapter,  REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
 	/* Tx RPT Timer. Unit: 32us */
-	rtw_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0);
+	usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0);
 
-	rtw_write8(Adapter, REG_EARLY_MODE_CONTROL, 0);
+	usb_write8(Adapter, REG_EARLY_MODE_CONTROL, 0);
 
-	rtw_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400);	/*  unit: 256us. 256ms */
-	rtw_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400);	/*  unit: 256us. 256ms */
+	usb_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400);	/*  unit: 256us. 256ms */
+	usb_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400);	/*  unit: 256us. 256ms */
 
 	/* Keep RfRegChnlVal for later use. */
 	haldata->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask);
@@ -867,71 +865,66 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MIS
 	/*  Disable BAR, suggested by Scott */
 	/*  2010.04.09 add by hpfan */
 	/*  */
-	rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
+	usb_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
 
 	/*  HW SEQ CTRL */
 	/* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
-	rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
+	usb_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
 
 	if (pregistrypriv->wifi_spec)
-		rtw_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
+		usb_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
 
 	/* Nav limit , suggest by scott */
-	rtw_write8(Adapter, 0x652, 0x0);
+	usb_write8(Adapter, 0x652, 0x0);
 
 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM);
 	rtl8188e_InitHalDm(Adapter);
 
-	if (Adapter->registrypriv.mp_mode == 1) {
-		Adapter->mppriv.channel = haldata->CurrentChannel;
-		MPT_InitializeAdapter(Adapter, Adapter->mppriv.channel);
-	} else {
-		/*  2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
-		/*  and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
-		/*  call initstruct adapter. May cause some problem?? */
-		/*  Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */
-		/*  in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */
-		/*  is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */
-		/*  Added by tynli. 2010.03.30. */
-		pwrctrlpriv->rf_pwrstate = rf_on;
+	/*  2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
+	/*  and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
+	/*  call initstruct adapter. May cause some problem?? */
+	/*  Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */
+	/*  in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */
+	/*  is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */
+	/*  Added by tynli. 2010.03.30. */
+	pwrctrlpriv->rf_pwrstate = rf_on;
 
-		/*  enable Tx report. */
-		rtw_write8(Adapter,  REG_FWHW_TXQ_CTRL+1, 0x0F);
+	/*  enable Tx report. */
+	usb_write8(Adapter,  REG_FWHW_TXQ_CTRL+1, 0x0F);
 
-		/*  Suggested by SD1 pisa. Added by tynli. 2011.10.21. */
-		rtw_write8(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01);/* Pretx_en, for WEP/TKIP SEC */
+	/*  Suggested by SD1 pisa. Added by tynli. 2011.10.21. */
+	usb_write8(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01);/* Pretx_en, for WEP/TKIP SEC */
 
-		/* tynli_test_tx_report. */
-		rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
+	/* tynli_test_tx_report. */
+	usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
 
-		/* enable tx DMA to drop the redundate data of packet */
-		rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+	/* enable tx DMA to drop the redundate data of packet */
+	usb_write16(Adapter, REG_TXDMA_OFFSET_CHK, (usb_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
 
 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
 		/*  2010/08/26 MH Merge from 8192CE. */
-		if (pwrctrlpriv->rf_pwrstate == rf_on) {
-			if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
+	if (pwrctrlpriv->rf_pwrstate == rf_on) {
+		if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
 				PHY_IQCalibrate_8188E(Adapter, true);
-			} else {
-				PHY_IQCalibrate_8188E(Adapter, false);
-				haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
-			}
+		} else {
+			PHY_IQCalibrate_8188E(Adapter, false);
+			haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+		}
 
 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK);
 
-			ODM_TXPowerTrackingCheck(&haldata->odmpriv);
+		ODM_TXPowerTrackingCheck(&haldata->odmpriv);
 
 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
 			PHY_LCCalibrate_8188E(Adapter);
-		}
 	}
 
 /* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */
 /*	_InitPABias(Adapter); */
-	rtw_write8(Adapter, REG_USB_HRPWM, 0);
+	usb_write8(Adapter, REG_USB_HRPWM, 0);
 
 	/* ack for xmit mgmt frames. */
-	rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, rtw_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
+	usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
 
 exit:
 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
@@ -950,52 +943,52 @@ static void CardDisableRTL8188EU(struct
 	RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("CardDisableRTL8188EU\n"));
 
 	/* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
-	val8 = rtw_read8(Adapter, REG_TX_RPT_CTRL);
-	rtw_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT1));
+	val8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+	usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT1));
 
 	/*  stop rx */
-	rtw_write8(Adapter, REG_CR, 0x0);
+	usb_write8(Adapter, REG_CR, 0x0);
 
 	/*  Run LPS WL RFOFF flow */
 	HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW);
 
 	/*  2. 0x1F[7:0] = 0		turn off RF */
 
-	val8 = rtw_read8(Adapter, REG_MCUFWDL);
+	val8 = usb_read8(Adapter, REG_MCUFWDL);
 	if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */
 		/*  Reset MCU 0x2[10]=0. */
-		val8 = rtw_read8(Adapter, REG_SYS_FUNC_EN+1);
+		val8 = usb_read8(Adapter, REG_SYS_FUNC_EN+1);
 		val8 &= ~BIT(2);	/*  0x2[10], FEN_CPUEN */
-		rtw_write8(Adapter, REG_SYS_FUNC_EN+1, val8);
+		usb_write8(Adapter, REG_SYS_FUNC_EN+1, val8);
 	}
 
 	/*  reset MCU ready status */
-	rtw_write8(Adapter, REG_MCUFWDL, 0);
+	usb_write8(Adapter, REG_MCUFWDL, 0);
 
 	/* YJ,add,111212 */
 	/* Disable 32k */
-	val8 = rtw_read8(Adapter, REG_32K_CTRL);
-	rtw_write8(Adapter, REG_32K_CTRL, val8&(~BIT0));
+	val8 = usb_read8(Adapter, REG_32K_CTRL);
+	usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT0));
 
 	/*  Card disable power action flow */
 	HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_DISABLE_FLOW);
 
 	/*  Reset MCU IO Wrapper */
-	val8 = rtw_read8(Adapter, REG_RSV_CTRL+1);
-	rtw_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT3)));
-	val8 = rtw_read8(Adapter, REG_RSV_CTRL+1);
-	rtw_write8(Adapter, REG_RSV_CTRL+1, val8|BIT3);
+	val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
+	usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT3)));
+	val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
+	usb_write8(Adapter, REG_RSV_CTRL+1, val8|BIT3);
 
 	/* YJ,test add, 111207. For Power Consumption. */
-	val8 = rtw_read8(Adapter, GPIO_IN);
-	rtw_write8(Adapter, GPIO_OUT, val8);
-	rtw_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */
+	val8 = usb_read8(Adapter, GPIO_IN);
+	usb_write8(Adapter, GPIO_OUT, val8);
+	usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */
 
-	val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL);
-	rtw_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4));
-	val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL+1);
-	rtw_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */
-	rtw_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */
+	val8 = usb_read8(Adapter, REG_GPIO_IO_SEL);
+	usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4));
+	val8 = usb_read8(Adapter, REG_GPIO_IO_SEL+1);
+	usb_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */
+	usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */
 	haldata->bMacPwrCtrlOn = false;
 	Adapter->bFWReady = false;
 }
@@ -1005,8 +998,8 @@ static void rtl8192cu_hw_power_down(stru
 	/*  Then enable power down control bit of register 0x04 BIT4 and BIT15 as 1. */
 
 	/*  Enable register area 0x0-0xc. */
-	rtw_write8(adapt, REG_RSV_CTRL, 0x0);
-	rtw_write16(adapt, REG_APS_FSMCO, 0x8812);
+	usb_write8(adapt, REG_RSV_CTRL, 0x0);
+	usb_write16(adapt, REG_APS_FSMCO, 0x8812);
 }
 
 static u32 rtl8188eu_hal_deinit(struct adapter *Adapter)
@@ -1014,8 +1007,8 @@ static u32 rtl8188eu_hal_deinit(struct a
 
 	DBG_88E("==> %s\n", __func__);
 
-	rtw_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E);
-	rtw_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E);
+	usb_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E);
+	usb_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E);
 
 	DBG_88E("bkeepfwalive(%x)\n", Adapter->pwrctrlpriv.bkeepfwalive);
 	if (Adapter->pwrctrlpriv.bkeepfwalive) {
@@ -1037,12 +1030,7 @@ static unsigned int rtl8188eu_inirp_init
 	u8 i;
 	struct recv_buf *precvbuf;
 	uint	status;
-	struct intf_hdl *pintfhdl = &Adapter->iopriv.intf;
 	struct recv_priv *precvpriv = &(Adapter->recvpriv);
-	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-
-
-	_read_port = pintfhdl->io_ops._read_port;
 
 	status = _SUCCESS;
 
@@ -1054,7 +1042,7 @@ static unsigned int rtl8188eu_inirp_init
 	/* issue Rx irp to receive data */
 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
 	for (i = 0; i < NR_RECVBUFF; i++) {
-		if (_read_port(pintfhdl, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf) == false) {
+		if (usb_read_port(Adapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf) == false) {
 			RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n"));
 			status = _FAIL;
 			goto exit;
@@ -1076,7 +1064,7 @@ static unsigned int rtl8188eu_inirp_dein
 {
 	RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n ===> usb_rx_deinit\n"));
 
-	rtw_read_port_cancel(Adapter);
+	usb_read_port_cancel(Adapter);
 
 	RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n <=== usb_rx_deinit\n"));
 
@@ -1155,10 +1143,6 @@ readAdapterInfo_8188EU(
 	Hal_EfuseParseBoardType88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
 	Hal_ReadThermalMeter_88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
 
-	/*  */
-	/*  The following part initialize some vars by PG info. */
-	/*  */
-	Hal_InitChannelPlan(adapt);
 }
 
 static void _ReadPROMContent(
@@ -1169,7 +1153,7 @@ static void _ReadPROMContent(
 	u8 eeValue;
 
 	/* check system boot selection */
-	eeValue = rtw_read8(Adapter, REG_9346CR);
+	eeValue = usb_read8(Adapter, REG_9346CR);
 	eeprom->EepromOrEfuse		= (eeValue & BOOT_FROM_EEPROM) ? true : false;
 	eeprom->bautoload_fail_flag	= (eeValue & EEPROM_EN) ? false : true;
 
@@ -1187,7 +1171,7 @@ static void _ReadRFType(struct adapter *
 	haldata->rf_chip = RF_6052;
 }
 
-static int _ReadAdapterInfo8188EU(struct adapter *Adapter)
+static void _ReadAdapterInfo8188EU(struct adapter *Adapter)
 {
 	u32 start = jiffies;
 
@@ -1197,16 +1181,6 @@ static int _ReadAdapterInfo8188EU(struct
 	_ReadPROMContent(Adapter);
 
 	MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
-
-	return _SUCCESS;
-}
-
-static void ReadAdapterInfo8188EU(struct adapter *Adapter)
-{
-	/*  Read EEPROM size before call any EEPROM function */
-	Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter);
-
-	_ReadAdapterInfo8188EU(Adapter);
 }
 
 #define GPIO_DEBUG_PORT_NUM 0
@@ -1221,11 +1195,11 @@ static void ResumeTxBeacon(struct adapte
 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
 	/*  which should be read from register to a global variable. */
 
-	rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT6);
+	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT6);
 	haldata->RegFwHwTxQCtrl |= BIT6;
-	rtw_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff);
+	usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff);
 	haldata->RegReg542 |= BIT0;
-	rtw_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
+	usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
 }
 
 static void StopTxBeacon(struct adapter *adapt)
@@ -1235,11 +1209,11 @@ static void StopTxBeacon(struct adapter
 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
 	/*  which should be read from register to a global variable. */
 
-	rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT6));
+	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT6));
 	haldata->RegFwHwTxQCtrl &= (~BIT6);
-	rtw_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64);
+	usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64);
 	haldata->RegReg542 &= ~(BIT0);
-	rtw_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
+	usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
 
 	 /* todo: CheckFwRsvdPageContent(Adapter);  2010.06.23. Added by tynli. */
 }
@@ -1250,54 +1224,54 @@ static void hw_var_set_opmode(struct ada
 	u8 mode = *((u8 *)val);
 
 	/*  disable Port0 TSF update */
-	rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+	usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
 
 	/*  set net_type */
-	val8 = rtw_read8(Adapter, MSR)&0x0c;
+	val8 = usb_read8(Adapter, MSR)&0x0c;
 	val8 |= mode;
-	rtw_write8(Adapter, MSR, val8);
+	usb_write8(Adapter, MSR, val8);
 
 	DBG_88E("%s()-%d mode = %d\n", __func__, __LINE__, mode);
 
 	if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
 		StopTxBeacon(Adapter);
 
-		rtw_write8(Adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
+		usb_write8(Adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
 	} else if ((mode == _HW_STATE_ADHOC_)) {
 		ResumeTxBeacon(Adapter);
-		rtw_write8(Adapter, REG_BCN_CTRL, 0x1a);
+		usb_write8(Adapter, REG_BCN_CTRL, 0x1a);
 	} else if (mode == _HW_STATE_AP_) {
 		ResumeTxBeacon(Adapter);
 
-		rtw_write8(Adapter, REG_BCN_CTRL, 0x12);
+		usb_write8(Adapter, REG_BCN_CTRL, 0x12);
 
 		/* Set RCR */
-		rtw_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
+		usb_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
 		/* enable to rx data frame */
-		rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+		usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
 		/* enable to rx ps-poll */
-		rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400);
+		usb_write16(Adapter, REG_RXFLTMAP1, 0x0400);
 
 		/* Beacon Control related register for first time */
-		rtw_write8(Adapter, REG_BCNDMATIM, 0x02); /*  2ms */
+		usb_write8(Adapter, REG_BCNDMATIM, 0x02); /*  2ms */
 
-		rtw_write8(Adapter, REG_ATIMWND, 0x0a); /*  10ms */
-		rtw_write16(Adapter, REG_BCNTCFG, 0x00);
-		rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04);
-		rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/*  +32767 (~32ms) */
+		usb_write8(Adapter, REG_ATIMWND, 0x0a); /*  10ms */
+		usb_write16(Adapter, REG_BCNTCFG, 0x00);
+		usb_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04);
+		usb_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/*  +32767 (~32ms) */
 
 		/* reset TSF */
-		rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0));
+		usb_write8(Adapter, REG_DUAL_TSF_RST, BIT(0));
 
 		/* BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
-		rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4));
+		usb_write8(Adapter, REG_MBID_NUM, usb_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4));
 
 		/* enable BCN0 Function for if1 */
 		/* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
-		rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | BIT(1)));
+		usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | BIT(1)));
 
 		/* dis BCN1 ATIM  WND if if2 is station */
-		rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) | BIT(0));
+		usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0));
 	}
 }
 
@@ -1309,7 +1283,7 @@ static void hw_var_set_macaddr(struct ad
 	reg_macid = REG_MACID;
 
 	for (idx = 0; idx < 6; idx++)
-		rtw_write8(Adapter, (reg_macid+idx), val[idx]);
+		usb_write8(Adapter, (reg_macid+idx), val[idx]);
 }
 
 static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val)
@@ -1320,7 +1294,7 @@ static void hw_var_set_bssid(struct adap
 	reg_bssid = REG_BSSID;
 
 	for (idx = 0; idx < 6; idx++)
-		rtw_write8(Adapter, (reg_bssid+idx), val[idx]);
+		usb_write8(Adapter, (reg_bssid+idx), val[idx]);
 }
 
 static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val)
@@ -1330,9 +1304,9 @@ static void hw_var_set_bcn_func(struct a
 	bcn_ctrl_reg = REG_BCN_CTRL;
 
 	if (*((u8 *)val))
-		rtw_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
+		usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
 	else
-		rtw_write8(Adapter, bcn_ctrl_reg, rtw_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
+		usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
 }
 
 static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
@@ -1346,18 +1320,18 @@ static void SetHwReg8188EU(struct adapte
 		{
 			u8 val8;
 
-			val8 = rtw_read8(Adapter, MSR)&0x0c;
+			val8 = usb_read8(Adapter, MSR)&0x0c;
 			val8 |= *((u8 *)val);
-			rtw_write8(Adapter, MSR, val8);
+			usb_write8(Adapter, MSR, val8);
 		}
 		break;
 	case HW_VAR_MEDIA_STATUS1:
 		{
 			u8 val8;
 
-			val8 = rtw_read8(Adapter, MSR) & 0x03;
+			val8 = usb_read8(Adapter, MSR) & 0x03;
 			val8 |= *((u8 *)val) << 2;
-			rtw_write8(Adapter, MSR, val8);
+			usb_write8(Adapter, MSR, val8);
 		}
 		break;
 	case HW_VAR_SET_OPMODE:
@@ -1391,9 +1365,9 @@ static void SetHwReg8188EU(struct adapte
 
 			BrateCfg |= 0x01; /*  default enable 1M ACK rate */
 			/*  Set RRSR rate table. */
-			rtw_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
-			rtw_write8(Adapter, REG_RRSR+1, (BrateCfg >> 8) & 0xff);
-			rtw_write8(Adapter, REG_RRSR+2, rtw_read8(Adapter, REG_RRSR+2)&0xf0);
+			usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
+			usb_write8(Adapter, REG_RRSR+1, (BrateCfg >> 8) & 0xff);
+			usb_write8(Adapter, REG_RRSR+2, usb_read8(Adapter, REG_RRSR+2)&0xf0);
 
 			/*  Set RTS initial rate */
 			while (BrateCfg > 0x1) {
@@ -1401,11 +1375,11 @@ static void SetHwReg8188EU(struct adapte
 				RateIndex++;
 			}
 			/*  Ziv - Check */
-			rtw_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
+			usb_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
 		}
 		break;
 	case HW_VAR_TXPAUSE:
-		rtw_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
+		usb_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
 		break;
 	case HW_VAR_BCN_FUNC:
 		hw_var_set_bcn_func(Adapter, variable, val);
@@ -1422,13 +1396,13 @@ static void SetHwReg8188EU(struct adapte
 				StopTxBeacon(Adapter);
 
 			/* disable related TSF function */
-			rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(3)));
+			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3)));
 
-			rtw_write32(Adapter, REG_TSFTR, tsf);
-			rtw_write32(Adapter, REG_TSFTR+4, tsf>>32);
+			usb_write32(Adapter, REG_TSFTR, tsf);
+			usb_write32(Adapter, REG_TSFTR+4, tsf>>32);
 
 			/* enable related TSF function */
-			rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(3));
+			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(3));
 
 			if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
 				ResumeTxBeacon(Adapter);
@@ -1436,39 +1410,39 @@ static void SetHwReg8188EU(struct adapte
 		break;
 	case HW_VAR_CHECK_BSSID:
 		if (*((u8 *)val)) {
-			rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN);
+			usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN);
 		} else {
 			u32 val32;
 
-			val32 = rtw_read32(Adapter, REG_RCR);
+			val32 = usb_read32(Adapter, REG_RCR);
 
 			val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
 
-			rtw_write32(Adapter, REG_RCR, val32);
+			usb_write32(Adapter, REG_RCR, val32);
 		}
 		break;
 	case HW_VAR_MLME_DISCONNECT:
 		/* Set RCR to not to receive data frame when NO LINK state */
 		/* reject all data frames */
-		rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
+		usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
 
 		/* reset TSF */
-		rtw_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
+		usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
 
 		/* disable update TSF */
-		rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+		usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
 		break;
 	case HW_VAR_MLME_SITESURVEY:
 		if (*((u8 *)val)) { /* under sitesurvey */
 			/* config RCR to receive different BSSID & not to receive data frame */
-			u32 v = rtw_read32(Adapter, REG_RCR);
+			u32 v = usb_read32(Adapter, REG_RCR);
 			v &= ~(RCR_CBSSID_BCN);
-			rtw_write32(Adapter, REG_RCR, v);
+			usb_write32(Adapter, REG_RCR, v);
 			/* reject all data frame */
-			rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
+			usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
 
 			/* disable update TSF */
-			rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4));
+			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
 		} else { /* sitesurvey done */
 			struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
 			struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -1476,24 +1450,24 @@ static void SetHwReg8188EU(struct adapte
 			if ((is_client_associated_to_ap(Adapter)) ||
 			    ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)) {
 				/* enable to rx data frame */
-				rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+				usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
 
 				/* enable update TSF */
-				rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
+				usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
 			} else if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-				rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+				usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
 				/* enable update TSF */
-				rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
+				usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
 			}
 			if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-				rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN);
+				usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN);
 			} else {
 				if (Adapter->in_cta_test) {
-					u32 v = rtw_read32(Adapter, REG_RCR);
+					u32 v = usb_read32(Adapter, REG_RCR);
 					v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
-					rtw_write32(Adapter, REG_RCR, v);
+					usb_write32(Adapter, REG_RCR, v);
 				} else {
-					rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN);
+					usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN);
 				}
 			}
 		}
@@ -1506,14 +1480,14 @@ static void SetHwReg8188EU(struct adapte
 
 			if (type == 0) { /*  prepare to join */
 				/* enable to rx data frame.Accept all data frame */
-				rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+				usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
 
 				if (Adapter->in_cta_test) {
-					u32 v = rtw_read32(Adapter, REG_RCR);
+					u32 v = usb_read32(Adapter, REG_RCR);
 					v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
-					rtw_write32(Adapter, REG_RCR, v);
+					usb_write32(Adapter, REG_RCR, v);
 				} else {
-					rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN);
+					usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN);
 				}
 
 				if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
@@ -1522,20 +1496,20 @@ static void SetHwReg8188EU(struct adapte
 					RetryLimit = 0x7;
 			} else if (type == 1) {
 				/* joinbss_event call back when join res < 0 */
-				rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
+				usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
 			} else if (type == 2) {
 				/* sta add event call back */
 				/* enable update TSF */
-				rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
+				usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4)));
 
 				if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
 					RetryLimit = 0x7;
 			}
-			rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
+			usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
 		}
 		break;
 	case HW_VAR_BEACON_INTERVAL:
-		rtw_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
+		usb_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
 		break;
 	case HW_VAR_SLOT_TIME:
 		{
@@ -1543,7 +1517,7 @@ static void SetHwReg8188EU(struct adapte
 			struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
 			struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-			rtw_write8(Adapter, REG_SLOT, val[0]);
+			usb_write8(Adapter, REG_SLOT, val[0]);
 
 			if (pmlmeinfo->WMM_enable == 0) {
 				if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
@@ -1554,20 +1528,20 @@ static void SetHwReg8188EU(struct adapte
 				u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
 
 				/*  <Roger_EXP> Temporary removed, 2008.06.20. */
-				rtw_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
-				rtw_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
-				rtw_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
-				rtw_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
+				usb_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
+				usb_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
+				usb_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
+				usb_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
 			}
 		}
 		break;
 	case HW_VAR_RESP_SIFS:
 		/* RESP_SIFS for CCK */
-		rtw_write8(Adapter, REG_R2T_SIFS, val[0]); /*  SIFS_T2T_CCK (0x08) */
-		rtw_write8(Adapter, REG_R2T_SIFS+1, val[1]); /* SIFS_R2T_CCK(0x08) */
+		usb_write8(Adapter, REG_R2T_SIFS, val[0]); /*  SIFS_T2T_CCK (0x08) */
+		usb_write8(Adapter, REG_R2T_SIFS+1, val[1]); /* SIFS_R2T_CCK(0x08) */
 		/* RESP_SIFS for OFDM */
-		rtw_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
-		rtw_write8(Adapter, REG_T2T_SIFS+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
+		usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
+		usb_write8(Adapter, REG_T2T_SIFS+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
 		break;
 	case HW_VAR_ACK_PREAMBLE:
 		{
@@ -1578,11 +1552,11 @@ static void SetHwReg8188EU(struct adapte
 			if (bShortPreamble)
 				regTmp |= 0x80;
 
-			rtw_write8(Adapter, REG_RRSR+2, regTmp);
+			usb_write8(Adapter, REG_RRSR+2, regTmp);
 		}
 		break;
 	case HW_VAR_SEC_CFG:
-		rtw_write8(Adapter, REG_SECCFG, *((u8 *)val));
+		usb_write8(Adapter, REG_SECCFG, *((u8 *)val));
 		break;
 	case HW_VAR_DM_FLAG:
 		podmpriv->SupportAbility = *((u8 *)val);
@@ -1622,41 +1596,41 @@ static void SetHwReg8188EU(struct adapte
 				ulCommand = CAM_CONTENT_COUNT*ucIndex+i;
 				ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE;
 				/*  write content 0 is equall to mark invalid */
-				rtw_write32(Adapter, WCAMI, ulContent);  /* delay_ms(40); */
-				rtw_write32(Adapter, RWCAM, ulCommand);  /* delay_ms(40); */
+				usb_write32(Adapter, WCAMI, ulContent);  /* delay_ms(40); */
+				usb_write32(Adapter, RWCAM, ulCommand);  /* delay_ms(40); */
 			}
 		}
 		break;
 	case HW_VAR_CAM_INVALID_ALL:
-		rtw_write32(Adapter, RWCAM, BIT(31)|BIT(30));
+		usb_write32(Adapter, RWCAM, BIT(31)|BIT(30));
 		break;
 	case HW_VAR_CAM_WRITE:
 		{
 			u32 cmd;
 			u32 *cam_val = (u32 *)val;
-			rtw_write32(Adapter, WCAMI, cam_val[0]);
+			usb_write32(Adapter, WCAMI, cam_val[0]);
 
 			cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
-			rtw_write32(Adapter, RWCAM, cmd);
+			usb_write32(Adapter, RWCAM, cmd);
 		}
 		break;
 	case HW_VAR_AC_PARAM_VO:
-		rtw_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
+		usb_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
 		break;
 	case HW_VAR_AC_PARAM_VI:
-		rtw_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
+		usb_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
 		break;
 	case HW_VAR_AC_PARAM_BE:
 		haldata->AcParam_BE = ((u32 *)(val))[0];
-		rtw_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
+		usb_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
 		break;
 	case HW_VAR_AC_PARAM_BK:
-		rtw_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
+		usb_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
 		break;
 	case HW_VAR_ACM_CTRL:
 		{
 			u8 acm_ctrl = *((u8 *)val);
-			u8 AcmCtrl = rtw_read8(Adapter, REG_ACMHWCTRL);
+			u8 AcmCtrl = usb_read8(Adapter, REG_ACMHWCTRL);
 
 			if (acm_ctrl > 1)
 				AcmCtrl = AcmCtrl | 0x1;
@@ -1677,7 +1651,7 @@ static void SetHwReg8188EU(struct adapte
 				AcmCtrl &= (~AcmHw_BeqEn);
 
 			DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
-			rtw_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
+			usb_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
 		}
 		break;
 	case HW_VAR_AMPDU_MIN_SPACE:
@@ -1704,7 +1678,7 @@ static void SetHwReg8188EU(struct adapte
 				}
 				if (MinSpacingToSet < SecMinSpace)
 					MinSpacingToSet = SecMinSpace;
-				rtw_write8(Adapter, REG_AMPDU_MIN_SPACE, (rtw_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet);
+				usb_write8(Adapter, REG_AMPDU_MIN_SPACE, (usb_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet);
 			}
 		}
 		break;
@@ -1729,7 +1703,7 @@ static void SetHwReg8188EU(struct adapte
 					if ((pRegToSet[index] & 0x0f) > FactorToSet)
 						pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet);
 
-					rtw_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]);
+					usb_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]);
 				}
 			}
 		}
@@ -1739,7 +1713,7 @@ static void SetHwReg8188EU(struct adapte
 			u8 threshold = *((u8 *)val);
 			if (threshold == 0)
 				threshold = haldata->UsbRxAggPageCount;
-			rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
+			usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
 		}
 		break;
 	case HW_VAR_SET_RPWM:
@@ -1761,14 +1735,6 @@ static void SetHwReg8188EU(struct adapte
 			rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus);
 		}
 		break;
-#ifdef CONFIG_88EU_P2P
-	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
-		{
-			u8 p2p_ps_state = (*(u8 *)val);
-			rtl8188e_set_p2p_ps_offload_cmd(Adapter, p2p_ps_state);
-		}
-		break;
-#endif
 	case HW_VAR_INITIAL_GAIN:
 		{
 			struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
@@ -1813,24 +1779,24 @@ static void SetHwReg8188EU(struct adapte
 			u8 trycnt = 100;
 
 			/* pause tx */
-			rtw_write8(Adapter, REG_TXPAUSE, 0xff);
+			usb_write8(Adapter, REG_TXPAUSE, 0xff);
 
 			/* keep sn */
-			Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
+			Adapter->xmitpriv.nqos_ssn = usb_read16(Adapter, REG_NQOS_SEQ);
 
 			if (!pwrpriv->bkeepfwalive) {
 				/* RX DMA stop */
-				rtw_write32(Adapter, REG_RXPKT_NUM, (rtw_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN));
+				usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN));
 				do {
-					if (!(rtw_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE))
+					if (!(usb_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE))
 						break;
 				} while (trycnt--);
 				if (trycnt == 0)
 					DBG_88E("Stop RX DMA failed......\n");
 
 				/* RQPN Load 0 */
-				rtw_write16(Adapter, REG_RQPN_NPQ, 0x0);
-				rtw_write32(Adapter, REG_RQPN, 0x80000000);
+				usb_write16(Adapter, REG_RQPN_NPQ, 0x0);
+				usb_write32(Adapter, REG_RQPN, 0x80000000);
 				mdelay(10);
 			}
 		}
@@ -1845,7 +1811,7 @@ static void SetHwReg8188EU(struct adapte
 		{
 			u8 maxMacid = *val;
 			DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid+1);
-			rtw_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1);
+			usb_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1);
 		}
 		break;
 	case HW_VAR_H2C_MEDIA_STATUS_RPT:
@@ -1853,7 +1819,7 @@ static void SetHwReg8188EU(struct adapte
 		break;
 	case HW_VAR_BCN_VALID:
 		/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
-		rtw_write8(Adapter, REG_TDECTRL+2, rtw_read8(Adapter, REG_TDECTRL+2) | BIT0);
+		usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT0);
 		break;
 	default:
 		break;
@@ -1869,11 +1835,11 @@ static void GetHwReg8188EU(struct adapte
 	case HW_VAR_BASIC_RATE:
 		*((u16 *)(val)) = haldata->BasicRateSet;
 	case HW_VAR_TXPAUSE:
-		val[0] = rtw_read8(Adapter, REG_TXPAUSE);
+		val[0] = usb_read8(Adapter, REG_TXPAUSE);
 		break;
 	case HW_VAR_BCN_VALID:
 		/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
-		val[0] = (BIT0 & rtw_read8(Adapter, REG_TDECTRL+2)) ? true : false;
+		val[0] = (BIT0 & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false;
 		break;
 	case HW_VAR_DM_FLAG:
 		val[0] = podmpriv->SupportAbility;
@@ -1890,7 +1856,7 @@ static void GetHwReg8188EU(struct adapte
 				val[0] = true;
 			} else {
 				u32 valRCR;
-				valRCR = rtw_read32(Adapter, REG_RCR);
+				valRCR = usb_read32(Adapter, REG_RCR);
 				valRCR &= 0x00070000;
 				if (valRCR)
 					val[0] = false;
@@ -1909,7 +1875,7 @@ static void GetHwReg8188EU(struct adapte
 		*val = haldata->bMacPwrCtrlOn;
 		break;
 	case HW_VAR_CHK_HI_QUEUE_EMPTY:
-		*val = ((rtw_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false;
+		*val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false;
 		break;
 	default:
 		break;
@@ -2047,7 +2013,7 @@ static u8 SetHalDefVar8188EUsb(struct ad
 			} else if (dm_func == 6) {/* turn on all dynamic func */
 				if (!(podmpriv->SupportAbility  & DYNAMIC_BB_DIG)) {
 					struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
-					pDigTable->CurIGValue = rtw_read8(Adapter, 0xc50);
+					pDigTable->CurIGValue = usb_read8(Adapter, 0xc50);
 				}
 				podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
 				DBG_88E("==> Turn on all dynamic function...\n");
@@ -2177,29 +2143,29 @@ static void SetBeaconRelatedRegisters818
 	/* reset TSF, enable update TSF, correcting TSF On Beacon */
 
 	/* BCN interval */
-	rtw_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
-	rtw_write8(adapt, REG_ATIMWND, 0x02);/*  2ms */
+	usb_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
+	usb_write8(adapt, REG_ATIMWND, 0x02);/*  2ms */
 
 	_InitBeaconParameters(adapt);
 
-	rtw_write8(adapt, REG_SLOT, 0x09);
+	usb_write8(adapt, REG_SLOT, 0x09);
 
-	value32 = rtw_read32(adapt, REG_TCR);
+	value32 = usb_read32(adapt, REG_TCR);
 	value32 &= ~TSFRST;
-	rtw_write32(adapt,  REG_TCR, value32);
+	usb_write32(adapt,  REG_TCR, value32);
 
 	value32 |= TSFRST;
-	rtw_write32(adapt, REG_TCR, value32);
+	usb_write32(adapt, REG_TCR, value32);
 
 	/*  NOTE: Fix test chip's bug (about contention windows's randomness) */
-	rtw_write8(adapt,  REG_RXTSF_OFFSET_CCK, 0x50);
-	rtw_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50);
+	usb_write8(adapt,  REG_RXTSF_OFFSET_CCK, 0x50);
+	usb_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50);
 
 	_BeaconFunctionEnable(adapt, true, true);
 
 	ResumeTxBeacon(adapt);
 
-	rtw_write8(adapt, bcn_ctrl_reg, rtw_read8(adapt, bcn_ctrl_reg)|BIT(1));
+	usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg)|BIT(1));
 }
 
 static void rtl8188eu_init_default_value(struct adapter *adapt)
@@ -2231,10 +2197,9 @@ void rtl8188eu_set_hal_ops(struct adapte
 	struct hal_ops	*halfunc = &adapt->HalFunc;
 
 
-	adapt->HalData = rtw_zmalloc(sizeof(struct hal_data_8188e));
+	adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
 	if (adapt->HalData == NULL)
 		DBG_88E("cant not alloc memory for HAL DATA\n");
-	adapt->hal_data_sz = sizeof(struct hal_data_8188e);
 
 	halfunc->hal_power_on = rtl8188eu_InitPowerOn;
 	halfunc->hal_init = &rtl8188eu_hal_init;
@@ -2244,7 +2209,6 @@ void rtl8188eu_set_hal_ops(struct adapte
 	halfunc->inirp_deinit = &rtl8188eu_inirp_deinit;
 
 	halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv;
-	halfunc->free_xmit_priv = &rtl8188eu_free_xmit_priv;
 
 	halfunc->init_recv_priv = &rtl8188eu_init_recv_priv;
 	halfunc->free_recv_priv = &rtl8188eu_free_recv_priv;
@@ -2253,7 +2217,7 @@ void rtl8188eu_set_hal_ops(struct adapte
 
 	halfunc->init_default_value = &rtl8188eu_init_default_value;
 	halfunc->intf_chip_configure = &rtl8188eu_interface_configure;
-	halfunc->read_adapter_info = &ReadAdapterInfo8188EU;
+	halfunc->read_adapter_info = &_ReadAdapterInfo8188EU;
 
 	halfunc->SetHwRegHandler = &SetHwReg8188EU;
 	halfunc->GetHwRegHandler = &GetHwReg8188EU;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/usb_ops_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/hal/usb_ops_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/hal/usb_ops_linux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,684 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#define _HCI_OPS_OS_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <osdep_intf.h>
-#include <usb_ops.h>
-#include <recv_osdep.h>
-#include <rtl8188e_hal.h>
-
-static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
-{
-	struct adapter	*adapt = pintfhdl->padapter;
-	struct dvobj_priv  *dvobjpriv = adapter_to_dvobj(adapt);
-	struct usb_device *udev = dvobjpriv->pusbdev;
-	unsigned int pipe;
-	int status = 0;
-	u8 reqtype;
-	u8 *pIo_buf;
-	int vendorreq_times = 0;
-
-	if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usbctrl_vendorreq:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
-		status = -EPERM;
-		goto exit;
-	}
-
-	if (len > MAX_VENDOR_REQ_CMD_SIZE) {
-		DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
-		status = -EINVAL;
-		goto exit;
-	}
-
-	_enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
-
-	/*  Acquire IO memory for vendorreq */
-	pIo_buf = dvobjpriv->usb_vendor_req_buf;
-
-	if (pIo_buf == NULL) {
-		DBG_88E("[%s] pIo_buf == NULL\n", __func__);
-		status = -ENOMEM;
-		goto release_mutex;
-	}
-
-	while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
-		_rtw_memset(pIo_buf, 0, len);
-
-		if (requesttype == 0x01) {
-			pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
-			reqtype =  REALTEK_USB_VENQT_READ;
-		} else {
-			pipe = usb_sndctrlpipe(udev, 0);/* write_out */
-			reqtype =  REALTEK_USB_VENQT_WRITE;
-			memcpy(pIo_buf, pdata, len);
-		}
-
-		status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
-
-		if (status == len) {   /*  Success this control transfer. */
-			rtw_reset_continual_urb_error(dvobjpriv);
-			if (requesttype == 0x01)
-				memcpy(pdata, pIo_buf,  len);
-		} else { /*  error cases */
-			DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
-				value, (requesttype == 0x01) ? "read" : "write",
-				len, status, *(u32 *)pdata, vendorreq_times);
-
-			if (status < 0) {
-				if (status == (-ESHUTDOWN) || status == -ENODEV) {
-					adapt->bSurpriseRemoved = true;
-				} else {
-					struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
-					haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
-				}
-			} else { /*  status != len && status >= 0 */
-				if (status > 0) {
-					if (requesttype == 0x01) {
-						/*  For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
-						memcpy(pdata, pIo_buf,  len);
-					}
-				}
-			}
-
-			if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) {
-				adapt->bSurpriseRemoved = true;
-				break;
-			}
-
-		}
-
-		/*  firmware download is checksumed, don't retry */
-		if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
-			break;
-	}
-release_mutex:
-	mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
-exit:
-	return status;
-}
-
-static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 data = 0;
-
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 1;
-
-	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-
-
-	return data;
-
-}
-
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 2;
-	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-
-	return (u16)(le32_to_cpu(data)&0xffff);
-}
-
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
-
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 4;
-
-	usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-
-
-	return le32_to_cpu(data);
-}
-
-static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 data;
-	int ret;
-
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 1;
-	data = val;
-	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-	return ret;
-}
-
-static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
-	int ret;
-
-
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 2;
-
-	data = cpu_to_le32(val & 0x0000ffff);
-
-	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-
-
-	return ret;
-}
-
-static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
-	int ret;
-
-
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 4;
-	data = cpu_to_le32(val);
-
-	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
-
-
-	return ret;
-}
-
-static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
-	int ret;
-
-
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = length;
-	 memcpy(buf, pdata, len);
-
-	ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
-
-
-	return ret;
-}
-
-static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
-{
-	struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
-
-	if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
-		DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
-		return;
-	}
-
-	/*  HISR */
-	memcpy(&(haldata->IntArray[0]), &(pbuf[USB_INTR_CONTENT_HISR_OFFSET]), 4);
-	memcpy(&(haldata->IntArray[1]), &(pbuf[USB_INTR_CONTENT_HISRE_OFFSET]), 4);
-
-	/*  C2H Event */
-	if (pbuf[0] != 0)
-		memcpy(&(haldata->C2hArray[0]), &(pbuf[USB_INTR_CONTENT_C2H_OFFSET]), 16);
-}
-
-static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
-{
-	u8	*pbuf;
-	u8	shift_sz = 0;
-	u16	pkt_cnt;
-	u32	pkt_offset, skb_len, alloc_sz;
-	s32	transfer_len;
-	struct recv_stat	*prxstat;
-	struct phy_stat	*pphy_status = NULL;
-	struct sk_buff *pkt_copy = NULL;
-	struct recv_frame	*precvframe = NULL;
-	struct rx_pkt_attrib	*pattrib = NULL;
-	struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
-	struct recv_priv	*precvpriv = &adapt->recvpriv;
-	struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
-
-	transfer_len = (s32)pskb->len;
-	pbuf = pskb->data;
-
-	prxstat = (struct recv_stat *)pbuf;
-	pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
-
-	do {
-		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-			 ("recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
-			  prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
-
-		prxstat = (struct recv_stat *)pbuf;
-
-		precvframe = rtw_alloc_recvframe(pfree_recv_queue);
-		if (precvframe == NULL) {
-			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvbuf2recvframe: precvframe==NULL\n"));
-			DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
-			goto _exit_recvbuf2recvframe;
-		}
-
-		_rtw_init_listhead(&precvframe->list);
-		precvframe->len = 0;
-
-		update_recvframe_attrib_88e(precvframe, prxstat);
-
-		pattrib = &precvframe->attrib;
-
-		if ((pattrib->crc_err) || (pattrib->icv_err)) {
-			DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
-
-			rtw_free_recvframe(precvframe, pfree_recv_queue);
-			goto _exit_recvbuf2recvframe;
-		}
-
-		if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
-			pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
-
-		pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
-
-		if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
-			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recvbuf2recvframe: pkt_len<=0\n"));
-			DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len\n", __func__, __LINE__);
-			rtw_free_recvframe(precvframe, pfree_recv_queue);
-			goto _exit_recvbuf2recvframe;
-		}
-
-		/*	Modified by Albert 20101213 */
-		/*	For 8 bytes IP header alignment. */
-		if (pattrib->qos)	/*	Qos data, wireless lan header length is 26 */
-			shift_sz = 6;
-		else
-			shift_sz = 0;
-
-		skb_len = pattrib->pkt_len;
-
-		/*  for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
-		/*  modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
-		if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
-			if (skb_len <= 1650)
-				alloc_sz = 1664;
-			else
-				alloc_sz = skb_len + 14;
-		} else {
-			alloc_sz = skb_len;
-			/*	6 is for IP header 8 bytes alignment in QoS packet case. */
-			/*	8 is for skb->data 4 bytes alignment. */
-			alloc_sz += 14;
-		}
-
-		pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
-		if (pkt_copy) {
-			pkt_copy->dev = adapt->pnetdev;
-			precvframe->pkt = pkt_copy;
-			precvframe->rx_head = pkt_copy->data;
-			precvframe->rx_end = pkt_copy->data + alloc_sz;
-			skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
-			skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
-			memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
-			precvframe->rx_tail = pkt_copy->data;
-			precvframe->rx_data = pkt_copy->data;
-		} else {
-			if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
-				DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
-				rtw_free_recvframe(precvframe, pfree_recv_queue);
-				goto _exit_recvbuf2recvframe;
-			}
-			precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
-			if (precvframe->pkt) {
-				precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
-				precvframe->rx_head = precvframe->rx_tail;
-				precvframe->rx_data = precvframe->rx_tail;
-				precvframe->rx_end =  pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
-			} else {
-				DBG_88E("recvbuf2recvframe: skb_clone fail\n");
-				rtw_free_recvframe(precvframe, pfree_recv_queue);
-				goto _exit_recvbuf2recvframe;
-			}
-		}
-
-		recvframe_put(precvframe, skb_len);
-
-		switch (haldata->UsbRxAggMode) {
-		case USB_RX_AGG_DMA:
-		case USB_RX_AGG_MIX:
-			pkt_offset = (u16)_RND128(pkt_offset);
-			break;
-		case USB_RX_AGG_USB:
-			pkt_offset = (u16)_RND4(pkt_offset);
-			break;
-		case USB_RX_AGG_DISABLE:
-		default:
-			break;
-		}
-		if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
-			if (pattrib->physt)
-				update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status);
-			if (rtw_recv_entry(precvframe) != _SUCCESS) {
-				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-					("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
-			}
-		} else {
-			/* enqueue recvframe to txrtp queue */
-			if (pattrib->pkt_rpt_type == TX_REPORT1) {
-				/* CCX-TXRPT ack for xmit mgmt frames. */
-				handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
-			} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
-				ODM_RA_TxRPT2Handle_8188E(
-							&haldata->odmpriv,
-							precvframe->rx_data,
-							pattrib->pkt_len,
-							pattrib->MacIDValidEntry[0],
-							pattrib->MacIDValidEntry[1]
-							);
-			} else if (pattrib->pkt_rpt_type == HIS_REPORT) {
-				interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data);
-			}
-			rtw_free_recvframe(precvframe, pfree_recv_queue);
-		}
-		pkt_cnt--;
-		transfer_len -= pkt_offset;
-		pbuf += pkt_offset;
-		precvframe = NULL;
-		pkt_copy = NULL;
-
-		if (transfer_len > 0 && pkt_cnt == 0)
-			pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
-
-	} while ((transfer_len > 0) && (pkt_cnt > 0));
-
-_exit_recvbuf2recvframe:
-
-	return _SUCCESS;
-}
-
-void rtl8188eu_recv_tasklet(void *priv)
-{
-	struct sk_buff *pskb;
-	struct adapter *adapt = (struct adapter *)priv;
-	struct recv_priv *precvpriv = &adapt->recvpriv;
-
-	while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
-		if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
-			DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
-			dev_kfree_skb_any(pskb);
-			break;
-		}
-		recvbuf2recvframe(adapt, pskb);
-		skb_reset_tail_pointer(pskb);
-		pskb->len = 0;
-		skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
-	}
-}
-
-static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
-{
-	struct recv_buf	*precvbuf = (struct recv_buf *)purb->context;
-	struct adapter	*adapt = (struct adapter *)precvbuf->adapter;
-	struct recv_priv *precvpriv = &adapt->recvpriv;
-
-	RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete!!!\n"));
-
-	precvpriv->rx_pending_cnt--;
-
-	if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
-			 adapt->bDriverStopped, adapt->bSurpriseRemoved));
-
-		precvbuf->reuse = true;
-		DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
-			__func__, adapt->bDriverStopped,
-			adapt->bSurpriseRemoved, adapt->bReadPortCancel);
-		return;
-	}
-
-	if (purb->status == 0) { /* SUCCESS */
-		if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
-			RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-				 ("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"));
-			precvbuf->reuse = true;
-			rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
-			DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
-		} else {
-			rtw_reset_continual_urb_error(adapter_to_dvobj(adapt));
-
-			skb_put(precvbuf->pskb, purb->actual_length);
-			skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
-
-			if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
-				tasklet_schedule(&precvpriv->recv_tasklet);
-
-			precvbuf->pskb = NULL;
-			precvbuf->reuse = false;
-			rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
-		}
-	} else {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status));
-
-		DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
-		skb_put(precvbuf->pskb, purb->actual_length);
-		precvbuf->pskb = NULL;
-
-		if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt)))
-			adapt->bSurpriseRemoved = true;
-
-		switch (purb->status) {
-		case -EINVAL:
-		case -EPIPE:
-		case -ENODEV:
-		case -ESHUTDOWN:
-			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bSurpriseRemoved=true\n"));
-		case -ENOENT:
-			adapt->bDriverStopped = true;
-			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bDriverStopped=true\n"));
-			break;
-		case -EPROTO:
-		case -EOVERFLOW:
-			{
-				struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
-				haldata->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
-			}
-			precvbuf->reuse = true;
-			rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
-			break;
-		case -EINPROGRESS:
-			DBG_88E("ERROR: URB IS IN PROGRESS!\n");
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
-{
-	struct urb *purb = NULL;
-	struct recv_buf	*precvbuf = (struct recv_buf *)rmem;
-	struct adapter		*adapter = pintfhdl->padapter;
-	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
-	struct recv_priv	*precvpriv = &adapter->recvpriv;
-	struct usb_device	*pusbd = pdvobj->pusbdev;
-	int err;
-	unsigned int pipe;
-	size_t tmpaddr = 0;
-	size_t alignment = 0;
-	u32 ret = _SUCCESS;
-
-
-	if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
-	    adapter->pwrctrlpriv.pnp_bstop_trx) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("usb_read_port:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
-		return _FAIL;
-	}
-
-	if (!precvbuf) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("usb_read_port:precvbuf==NULL\n"));
-		return _FAIL;
-	}
-
-	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
-		precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
-		if (NULL != precvbuf->pskb)
-			precvbuf->reuse = true;
-	}
-
-	/* re-assign for linux based on skb */
-	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
-		precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
-		if (precvbuf->pskb == NULL) {
-			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
-			DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
-			return _FAIL;
-		}
-
-		tmpaddr = (size_t)precvbuf->pskb->data;
-		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
-		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
-	} else { /* reuse skb */
-		precvbuf->reuse = false;
-	}
-
-	precvpriv->rx_pending_cnt++;
-
-	purb = precvbuf->purb;
-
-	/* translate DMA FIFO addr to pipehandle */
-	pipe = ffaddr2pipehdl(pdvobj, addr);
-
-	usb_fill_bulk_urb(purb, pusbd, pipe,
-			  precvbuf->pskb->data,
-			  MAX_RECVBUF_SZ,
-			  usb_read_port_complete,
-			  precvbuf);/* context is precvbuf */
-
-	err = usb_submit_urb(purb, GFP_ATOMIC);
-	if ((err) && (err != (-EPERM))) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
-			 err, purb->status));
-		DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
-			err, purb->status);
-		ret = _FAIL;
-	}
-
-	return ret;
-}
-
-void rtl8188eu_xmit_tasklet(void *priv)
-{
-	int ret = false;
-	struct adapter *adapt = (struct adapter *)priv;
-	struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
-
-	if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
-		return;
-
-	while (1) {
-		if ((adapt->bDriverStopped) ||
-		    (adapt->bSurpriseRemoved) ||
-		    (adapt->bWritePortCancel)) {
-			DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
-			break;
-		}
-
-		ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL);
-
-		if (!ret)
-			break;
-	}
-}
-
-void rtl8188eu_set_intf_ops(struct _io_ops	*pops)
-{
-	_rtw_memset((u8 *)pops, 0, sizeof(struct _io_ops));
-	pops->_read8 = &usb_read8;
-	pops->_read16 = &usb_read16;
-	pops->_read32 = &usb_read32;
-	pops->_read_mem = &usb_read_mem;
-	pops->_read_port = &usb_read_port;
-	pops->_write8 = &usb_write8;
-	pops->_write16 = &usb_write16;
-	pops->_write32 = &usb_write32;
-	pops->_writeN = &usb_writeN;
-	pops->_write_mem = &usb_write_mem;
-	pops->_write_port = &usb_write_port;
-	pops->_read_port_cancel = &usb_read_port_cancel;
-	pops->_write_port_cancel = &usb_write_port_cancel;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/cmd_osdep.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/cmd_osdep.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/cmd_osdep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/cmd_osdep.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef __CMD_OSDEP_H_
-#define __CMD_OSDEP_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-extern int _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
-extern int _rtw_init_evt_priv(struct evt_priv *pevtpriv);
-extern void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv);
-extern int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj);
-extern struct cmd_obj	*_rtw_dequeue_cmd(struct __queue *queue);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/drv_types.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/drv_types.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/drv_types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/drv_types.h	2014-09-28 17:29:07.000000000 -0400
@@ -40,7 +40,6 @@
 #include <rtw_qos.h>
 #include <rtw_security.h>
 #include <rtw_pwrctrl.h>
-#include <rtw_io.h>
 #include <rtw_eeprom.h>
 #include <sta_info.h>
 #include <rtw_mlme.h>
@@ -49,17 +48,7 @@
 #include <rtw_event.h>
 #include <rtw_led.h>
 #include <rtw_mlme_ext.h>
-#include <rtw_p2p.h>
 #include <rtw_ap.h>
-#include <rtw_mp.h>
-#include <rtw_br_ext.h>
-
-enum _NIC_VERSION {
-	RTL8711_NIC,
-	RTL8712_NIC,
-	RTL8713_NIC,
-	RTL8716_NIC
-};
 
 #define SPEC_DEV_ID_NONE		BIT(0)
 #define SPEC_DEV_ID_DISABLE_HT		BIT(1)
@@ -68,12 +57,6 @@ enum _NIC_VERSION {
 #define SPEC_DEV_ID_RF_CONFIG_2T2R	BIT(4)
 #define SPEC_DEV_ID_ASSIGN_IFNAME	BIT(5)
 
-struct specific_device_id {
-	u32		flags;
-	u16		idVendor;
-	u16		idProduct;
-};
-
 struct registry_priv {
 	u8	chip_version;
 	u8	rfintfs;
@@ -165,7 +148,6 @@ struct rt_firmware {
 
 struct dvobj_priv {
 	struct adapter *if1;
-	struct adapter *if2;
 	struct rt_firmware firmware;
 
 	/* For 92D, DMDP have 2 interface. */
@@ -177,8 +159,6 @@ struct dvobj_priv {
 	int	RtOutPipe[3];
 	u8	Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */
 
-	u8	irq_alloc;
-
 /*-------- below is for USB INTERFACE --------*/
 
 	u8	nr_endpoint;
@@ -186,17 +166,12 @@ struct dvobj_priv {
 	u8	RtNumInPipes;
 	u8	RtNumOutPipes;
 	int	ep_num[5]; /* endpoint number */
-	int	RegUsbSS;
-	struct semaphore usb_suspend_sema;
 	struct mutex  usb_vendor_req_mutex;
 
-	u8 *usb_alloc_vendor_req_buf;
 	u8 *usb_vendor_req_buf;
 
 	struct usb_interface *pusbintf;
 	struct usb_device *pusbdev;
-
-	atomic_t continual_urb_error;
 };
 
 static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
@@ -206,37 +181,14 @@ static inline struct device *dvobj_to_de
 	return &dvobj->pusbintf->dev;
 };
 
-enum _IFACE_TYPE {
-	IFACE_PORT0, /* mapping to port0 for C/D series chips */
-	IFACE_PORT1, /* mapping to port1 for C/D series chip */
-	MAX_IFACE_PORT,
-};
-
-enum _ADAPTER_TYPE {
-	PRIMARY_ADAPTER,
-	SECONDARY_ADAPTER,
-	MAX_ADAPTER,
-};
-
-enum driver_state {
-	DRIVER_NORMAL = 0,
-	DRIVER_DISAPPEAR = 1,
-	DRIVER_REPLACE_DONGLE = 2,
-};
-
 struct adapter {
-	int	DriverState;/* for disable driver using module, use dongle toi
-			     * replace module. */
 	int	pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */
-	int	bDongle;/* build-in module or external dongle */
 	u16	chip_type;
 
 	struct dvobj_priv *dvobj;
 	struct	mlme_priv mlmepriv;
 	struct	mlme_ext_priv mlmeextpriv;
 	struct	cmd_priv	cmdpriv;
-	struct	evt_priv	evtpriv;
-	struct	io_priv	iopriv;
 	struct	xmit_priv	xmitpriv;
 	struct	recv_priv	recvpriv;
 	struct	sta_priv	stapriv;
@@ -245,7 +197,6 @@ struct adapter {
 	struct	pwrctrl_priv	pwrctrlpriv;
 	struct	eeprom_priv eeprompriv;
 	struct	led_priv	ledpriv;
-	struct	mp_priv	mppriv;
 
 #ifdef CONFIG_88EU_AP_MODE
 	struct	hostapd_priv	*phostapdpriv;
@@ -254,26 +205,15 @@ struct adapter {
 	struct wifidirect_info	wdinfo;
 
 	void *HalData;
-	u32 hal_data_sz;
 	struct hal_ops	HalFunc;
 
 	s32	bDriverStopped;
 	s32	bSurpriseRemoved;
-	s32	bCardDisableWOHSM;
-
-	u32	IsrContent;
-	u32	ImrContent;
 
-	u8	EepromAddressSize;
 	u8	hw_init_completed;
-	u8	bDriverIsGoingToUnload;
-	u8	init_adpt_in_progress;
-	u8	bHaltInProgress;
 
 	void *cmdThread;
 	void *evtThread;
-	void *xmitThread;
-	void *recvThread;
 	void (*intf_start)(struct adapter *adapter);
 	void (*intf_stop)(struct adapter *adapter);
 	struct  net_device *pnetdev;
@@ -293,32 +233,16 @@ struct adapter {
 
 	int net_closed;
 	u8 bFWReady;
-	u8 bBTFWReady;
 	u8 bReadPortCancel;
 	u8 bWritePortCancel;
 	u8 bRxRSSIDisplay;
 	/* The driver will show up the desired channel number
 	 * when this flag is 1. */
 	u8 bNotifyChannelChange;
-#ifdef CONFIG_88EU_P2P
-	/* The driver will show the current P2P status when the
-	 * upper application reads it. */
-	u8 bShowGetP2PState;
-#endif
-	struct adapter *pbuddy_adapter;
 
-	struct mutex *hw_init_mutex;
+	struct mutex hw_init_mutex;
 
 	spinlock_t br_ext_lock;
-	struct nat25_network_db_entry	*nethash[NAT25_HASH_SIZE];
-	int				pppoe_connection_in_progress;
-	unsigned char			pppoe_addr[MACADDRLEN];
-	unsigned char			scdb_mac[MACADDRLEN];
-	unsigned char			scdb_ip[4];
-	struct nat25_network_db_entry	*scdb_entry;
-	unsigned char			br_mac[MACADDRLEN];
-	unsigned char			br_ip[4];
-	struct br_ext_info		ethBrExtInfo;
 
 	u8	fix_rate;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/Hal8188EReg.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/Hal8188EReg.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/Hal8188EReg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/Hal8188EReg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-/*  */
-/*  File Name: Hal8188EReg.h */
-/*  */
-/*  Description: */
-/*  */
-/*  This file is for RTL8188E register definition. */
-/*  */
-/*  */
-/*  */
-#ifndef	__HAL_8188E_REG_H__
-#define __HAL_8188E_REG_H__
-
-/*  */
-/*  Register Definition */
-/*  */
-#define TRX_ANTDIV_PATH             0x860
-#define RX_ANTDIV_PATH              0xb2c
-#define	ODM_R_A_AGC_CORE1_8188E		0xc50
-
-
-/*  */
-/*  Bitmap Definition */
-/*  */
-#define	BIT_FA_RESET_8188E			BIT0
-
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/hal_com.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/hal_com.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/hal_com.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/hal_com.h	2014-09-28 17:29:07.000000000 -0400
@@ -166,8 +166,4 @@ void HalSetBrateCfg(struct adapter *Adap
 bool Hal_MappingOutPipe(struct adapter *pAdapter, u8 NumOutPipe);
 
 void hal_init_macaddr(struct adapter *adapter);
-
-void c2h_evt_clear(struct adapter *adapter);
-s32 c2h_evt_read(struct adapter *adapter, u8 *buf);
-
 #endif /* __HAL_COMMON_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/hal_intf.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/hal_intf.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/hal_intf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/hal_intf.h	2014-09-28 17:29:07.000000000 -0400
@@ -144,8 +144,6 @@ enum hal_intf_ps_func {
 	HAL_MAX_ID,
 };
 
-typedef s32 (*c2h_id_filter)(u8 id);
-
 struct hal_ops {
 	u32	(*hal_power_on)(struct adapter *padapter);
 	u32	(*hal_init)(struct adapter *padapter);
@@ -157,7 +155,6 @@ struct hal_ops {
 	u32	(*inirp_deinit)(struct adapter *padapter);
 
 	s32	(*init_xmit_priv)(struct adapter *padapter);
-	void	(*free_xmit_priv)(struct adapter *padapter);
 
 	s32	(*init_recv_priv)(struct adapter *padapter);
 	void	(*free_recv_priv)(struct adapter *padapter);
@@ -197,9 +194,6 @@ struct hal_ops {
 				       enum hal_def_variable eVariable,
 				       void *pValue);
 
-	void	(*GetHalODMVarHandler)(struct adapter *padapter,
-				       enum hal_odm_variable eVariable,
-				       void *pValue1, bool bSet);
 	void	(*SetHalODMVarHandler)(struct adapter *padapter,
 				       enum hal_odm_variable eVariable,
 				       void *pValue1, bool bSet);
@@ -210,8 +204,6 @@ struct hal_ops {
 
 	void	(*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg,
 				u8 rssi_level);
-	void	(*run_thread)(struct adapter *adapter);
-	void	(*cancel_thread)(struct adapter *adapter);
 
 	u8	(*AntDivBeforeLinkHandler)(struct adapter *adapter);
 	void	(*AntDivCompareHandler)(struct adapter *adapter,
@@ -233,29 +225,7 @@ struct hal_ops {
 			       enum rf_radio_path eRFPath, u32 RegAddr,
 			       u32 BitMask, u32 Data);
 
-	void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite,
-				 u8 PwrState);
-	void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
-			  u16 _size_byte, u8 *pbuf, bool bPseudoTest);
-	void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType,
-					u8 type, void *pOut, bool bPseudoTest);
-	u16	(*EfuseGetCurrentSize)(struct adapter *padapter, u8 efuseType,
-				       bool bPseudoTest);
-	int	(*Efuse_PgPacketRead)(struct adapter *adapter, u8 offset,
-				      u8 *data, bool bPseudoTest);
-	int	(*Efuse_PgPacketWrite)(struct adapter *padapter, u8 offset,
-				       u8 word_en, u8 *data, bool bPseudoTest);
-	u8	(*Efuse_WordEnableDataWrite)(struct adapter *padapter,
-					     u16 efuse_addr, u8 word_en,
-					     u8 *data, bool bPseudoTest);
-	bool	(*Efuse_PgPacketWrite_BT)(struct adapter *padapter, u8 offset,
-					  u8 word_en, u8 *data, bool test);
-
 	void (*sreset_init_value)(struct adapter *padapter);
-	void (*sreset_reset_value)(struct adapter *padapter);
-	void (*silentreset)(struct adapter *padapter);
-	void (*sreset_xmit_status_check)(struct adapter *padapter);
-	void (*sreset_linked_status_check) (struct adapter *padapter);
 	u8 (*sreset_get_wifi_status)(struct adapter *padapter);
 
 	int (*IOL_exec_cmds_sync)(struct adapter *padapter,
@@ -264,9 +234,6 @@ struct hal_ops {
 
 	void (*hal_notch_filter)(struct adapter *adapter, bool enable);
 	void (*hal_reset_security_engine)(struct adapter *adapter);
-	s32 (*c2h_handler)(struct adapter *padapter,
-			   struct c2h_evt_hdr *c2h_evt);
-	c2h_id_filter c2h_id_filter_ccx;
 };
 
 enum rt_eeprom_type {
@@ -317,9 +284,6 @@ u8 rtw_hal_get_def_var(struct adapter *p
 void rtw_hal_set_odm_var(struct adapter *padapter,
 			 enum hal_odm_variable eVariable, void *pValue1,
 			 bool bSet);
-void rtw_hal_get_odm_var(struct adapter *padapter,
-			 enum hal_odm_variable eVariable,
-			 void *pValue1, bool bSet);
 
 void rtw_hal_enable_interrupt(struct adapter *padapter);
 void rtw_hal_disable_interrupt(struct adapter *padapter);
@@ -332,7 +296,6 @@ s32	rtw_hal_mgnt_xmit(struct adapter *pa
 			  struct xmit_frame *pmgntframe);
 
 s32	rtw_hal_init_xmit_priv(struct adapter *padapter);
-void	rtw_hal_free_xmit_priv(struct adapter *padapter);
 
 s32	rtw_hal_init_recv_priv(struct adapter *padapter);
 void	rtw_hal_free_recv_priv(struct adapter *padapter);
@@ -341,8 +304,6 @@ void rtw_hal_update_ra_mask(struct adapt
 void	rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level);
 void	rtw_hal_clone_data(struct adapter *dst_adapt,
 			   struct adapter *src_adapt);
-void	rtw_hal_start_thread(struct adapter *padapter);
-void	rtw_hal_stop_thread(struct adapter *padapter);
 
 void rtw_hal_bcn_related_reg_setting(struct adapter *padapter);
 
@@ -368,10 +329,6 @@ void	rtw_hal_antdiv_rssi_compared(struct
 				     struct wlan_bssid_ex *src);
 
 void rtw_hal_sreset_init(struct adapter *padapter);
-void rtw_hal_sreset_reset(struct adapter *padapter);
-void rtw_hal_sreset_reset_value(struct adapter *padapter);
-void rtw_hal_sreset_xmit_status_check(struct adapter *padapter);
-void rtw_hal_sreset_linked_status_check(struct adapter *padapter);
 u8   rtw_hal_sreset_get_wifi_status(struct adapter *padapter);
 
 int rtw_hal_iol_cmd(struct adapter  *adapter, struct xmit_frame *xmit_frame,
@@ -380,9 +337,6 @@ int rtw_hal_iol_cmd(struct adapter  *ada
 void rtw_hal_notch_filter(struct adapter *adapter, bool enable);
 void rtw_hal_reset_security_engine(struct adapter *adapter);
 
-s32 rtw_hal_c2h_handler(struct adapter *adapter,
-			struct c2h_evt_hdr *c2h_evt);
-c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter);
 void indicate_wx_scan_complete_event(struct adapter *padapter);
 u8 rtw_do_join(struct adapter *padapter);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,7 @@
 #define	IQK_DELAY_TIME_88E		10		/* ms */
 #define	index_mapping_NUM_88E	15
 #define AVG_THERMAL_NUM_88E	4
-
+#define ODM_TARGET_CHNL_NUM_2G_5G	59
 
 void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *pDM_Odm,
 			     u8 Type,	/* 0 = OFDM, 1 = CCK */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/HalPhyRf.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/HalPhyRf.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/HalPhyRf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/HalPhyRf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-
- #ifndef __HAL_PHY_RF_H__
- #define __HAL_PHY_RF_H__
-
-#define ODM_TARGET_CHNL_NUM_2G_5G	59
-
-void ODM_ResetIQKResult(struct odm_dm_struct *pDM_Odm);
-
-u8 ODM_GetRightChnlPlaceforIQK(u8 chnl);
-
-#endif	/*  #ifndef __HAL_PHY_RF_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/ieee80211.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/ieee80211.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/ieee80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/ieee80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -1233,19 +1233,6 @@ u8 *rtw_get_wps_attr_content(u8 *wps_ie,
 void dump_ies(u8 *buf, u32 buf_len);
 void dump_wps_ie(u8 *ie, u32 ie_len);
 
-#ifdef CONFIG_88EU_P2P
-void dump_p2p_ie(u8 *ie, u32 ie_len);
-u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen);
-u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
-		     u8 *buf_attr, u32 *len_attr);
-u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
-			     u8 *buf_content, uint *len_content);
-u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len,
-			     u8 *pdata_attr);
-void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex,
-				       u8 attr_id);
-#endif
-
 uint	rtw_get_rateset_len(u8	*rateset);
 
 struct registry_priv;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/odm_precomp.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/odm_precomp.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/odm_precomp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/odm_precomp.h	2014-09-28 17:29:07.000000000 -0400
@@ -30,6 +30,7 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <hal_intf.h>
+#include <usb_ops_linux.h>
 
 /* 2 OutSrc Header Files */
 
@@ -39,7 +40,6 @@
 #include "odm_RegDefine11AC.h"
 #include "odm_RegDefine11N.h"
 
-#include "HalPhyRf.h"
 #include "HalPhyRf_8188e.h"/* for IQK,LCK,Power-tracking */
 #include "Hal8188ERateAdaptive.h"/* for  RA,Power training */
 #include "rtl8188e_hal.h"
@@ -49,7 +49,6 @@
 #include "HalHWImg8188E_MAC.h"
 #include "HalHWImg8188E_RF.h"
 #include "HalHWImg8188E_BB.h"
-#include "Hal8188EReg.h"
 
 #include "odm_RegConfig8188E.h"
 #include "odm_RTL8188E.h"
@@ -72,7 +71,6 @@ void odm_RefreshRateAdaptiveMaskMP(struc
 void odm_DynamicBBPowerSaving(struct odm_dm_struct *pDM_Odm);
 void odm_SwAntDivChkAntSwitch(struct odm_dm_struct *pDM_Odm, u8 Step);
 void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm);
-void odm_DynamicTxPower(struct odm_dm_struct *pDM_Odm);
 void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm);
 void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm);
 void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/osdep_intf.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/osdep_intf.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/osdep_intf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/osdep_intf.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,38 +24,8 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 
-struct intf_priv {
-	u8 *intf_dev;
-	u32	max_iosz;	/* USB2.0: 128, USB1.1: 64, SDIO:64 */
-	u32	max_xmitsz; /* USB2.0: unlimited, SDIO:512 */
-	u32	max_recvsz; /* USB2.0: unlimited, SDIO:512 */
-
-	u8 *io_rwmem;
-	u8 *allocated_io_rwmem;
-	u32	io_wsz; /* unit: 4bytes */
-	u32	io_rsz;/* unit: 4bytes */
-	u8 intf_status;
-
-	void (*_bus_io)(u8 *priv);
-
-/*
-Under Sync. IRP (SDIO/USB)
-A protection mechanism is necessary for the io_rwmem(read/write protocol)
-
-Under Async. IRP (SDIO/USB)
-The protection mechanism is through the pending queue.
-*/
-	struct mutex ioctl_mutex;
-	/*  when in USB, IO is through interrupt in/out endpoints */
-	struct usb_device	*udev;
-	struct urb *piorw_urb;
-	u8 io_irp_cnt;
-	u8 bio_irp_pending;
-	struct semaphore  io_retevt;
-	struct timer_list io_timer;
-	u8 bio_irp_timeout;
-	u8 bio_timer_cancel;
-};
+extern char *rtw_initmac;
+extern int rtw_mc2u_disable;
 
 u8 rtw_init_drv_sw(struct adapter *padapter);
 u8 rtw_free_drv_sw(struct adapter *padapter);
@@ -73,11 +43,9 @@ u16 rtw_recv_select_queue(struct sk_buff
 void rtw_proc_init_one(struct net_device *dev);
 void rtw_proc_remove_one(struct net_device *dev);
 
+int pm_netdev_open(struct net_device *pnetdev, u8 bnormal);
 void rtw_ips_dev_unload(struct adapter *padapter);
-
 int rtw_ips_pwr_up(struct adapter *padapter);
 void rtw_ips_pwr_down(struct adapter *padapter);
-int rtw_hw_suspend(struct adapter *padapter);
-int rtw_hw_resume(struct adapter *padapter);
 
 #endif	/* _OSDEP_INTF_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/osdep_service.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/osdep_service.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/osdep_service.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/osdep_service.h	2014-09-28 17:29:07.000000000 -0400
@@ -76,11 +76,6 @@ static inline int _enter_critical_mutex(
 	return ret;
 }
 
-static inline void rtw_list_delete(struct list_head *plist)
-{
-	list_del_init(plist);
-}
-
 static inline void _init_timer(struct timer_list *ptimer,
 			       struct  net_device *nic_hdl,
 			       void *pfunc, void *cntx)
@@ -95,22 +90,11 @@ static inline void _set_timer(struct tim
 	mod_timer(ptimer , (jiffies+(delay_time*HZ/1000)));
 }
 
-static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled)
-{
-	del_timer_sync(ptimer);
-	*bcancelled = true;/* true ==1; false==0 */
-}
-
 #define RTW_TIMER_HDL_ARGS void *FunctionContext
 #define RTW_TIMER_HDL_NAME(name) rtw_##name##_timer_hdl
 #define RTW_DECLARE_TIMER_HDL(name) \
 	void RTW_TIMER_HDL_NAME(name)(RTW_TIMER_HDL_ARGS)
 
-static inline void _cancel_workitem_sync(struct work_struct *pwork)
-{
-	cancel_work_sync(pwork);
-}
-
 static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
 {
 	return  netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
@@ -119,9 +103,6 @@ static inline int rtw_netif_queue_stoppe
 		netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
 }
 
-#ifndef BIT
-	#define BIT(x)	(1 << (x))
-#endif
 
 #define BIT0	0x00000001
 #define BIT1	0x00000002
@@ -163,137 +144,17 @@ static inline int rtw_netif_queue_stoppe
 
 extern int RTW_STATUS_CODE(int error_code);
 
-/* flags used for rtw_update_mem_stat() */
-enum {
-	MEM_STAT_VIR_ALLOC_SUCCESS,
-	MEM_STAT_VIR_ALLOC_FAIL,
-	MEM_STAT_VIR_FREE,
-	MEM_STAT_PHY_ALLOC_SUCCESS,
-	MEM_STAT_PHY_ALLOC_FAIL,
-	MEM_STAT_PHY_FREE,
-	MEM_STAT_TX, /* used to distinguish TX/RX, asigned from caller */
-	MEM_STAT_TX_ALLOC_SUCCESS,
-	MEM_STAT_TX_ALLOC_FAIL,
-	MEM_STAT_TX_FREE,
-	MEM_STAT_RX, /* used to distinguish TX/RX, asigned from caller */
-	MEM_STAT_RX_ALLOC_SUCCESS,
-	MEM_STAT_RX_ALLOC_FAIL,
-	MEM_STAT_RX_FREE
-};
-
-extern unsigned char MCS_rate_2R[16];
-extern unsigned char MCS_rate_1R[16];
-extern unsigned char RTW_WPA_OUI[];
-extern unsigned char WPA_TKIP_CIPHER[4];
-extern unsigned char RSN_TKIP_CIPHER[4];
-
 #define rtw_update_mem_stat(flag, sz) do {} while (0)
-u8 *_rtw_zmalloc(u32 sz);
 u8 *_rtw_malloc(u32 sz);
-void _rtw_mfree(u8 *pbuf, u32 sz);
 #define rtw_malloc(sz)			_rtw_malloc((sz))
-#define rtw_zmalloc(sz)			_rtw_zmalloc((sz))
-#define rtw_mfree(pbuf, sz)		_rtw_mfree((pbuf), (sz))
 
 void *rtw_malloc2d(int h, int w, int size);
-void rtw_mfree2d(void *pbuf, int h, int w, int size);
-
-void _rtw_memcpy(void *dec, void *sour, u32 sz);
-void _rtw_memset(void *pbuf, int c, u32 sz);
-
-void _rtw_init_listhead(struct list_head *list);
-u32  rtw_is_list_empty(struct list_head *phead);
-void rtw_list_insert_head(struct list_head *plist, struct list_head *phead);
-void rtw_list_insert_tail(struct list_head *plist, struct list_head *phead);
-void rtw_list_delete(struct list_head *plist);
 
 u32  _rtw_down_sema(struct semaphore *sema);
 
 void _rtw_init_queue(struct __queue *pqueue);
-u32  _rtw_queue_empty(struct __queue *pqueue);
-u32  rtw_end_of_queue_search(struct list_head *queue,
-			     struct list_head *pelement);
 
-u32  rtw_systime_to_ms(u32 systime);
-u32  rtw_ms_to_systime(u32 ms);
 s32  rtw_get_passing_time_ms(u32 start);
-s32  rtw_get_time_interval_ms(u32 start, u32 end);
-
-void rtw_sleep_schedulable(int ms);
-
-u32  rtw_atoi(u8 *s);
-
-static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer)
-{
-	return del_timer_sync(ptimer);
-}
-
-static inline void thread_enter(char *name)
-{
-	allow_signal(SIGTERM);
-}
-
-static inline void flush_signals_thread(void)
-{
-	if (signal_pending(current))
-		flush_signals(current);
-}
-
-#define _RND(sz, r) ((((sz)+((r)-1))/(r))*(r))
-#define RND4(x)	(((x >> 2) + (((x & 3) == 0) ?  0 : 1)) << 2)
-
-static inline u32 _RND4(u32 sz)
-{
-	u32	val;
-
-	val = ((sz >> 2) + ((sz & 3) ? 1 : 0)) << 2;
-	return val;
-}
-
-static inline u32 _RND8(u32 sz)
-{
-	u32	val;
-
-	val = ((sz >> 3) + ((sz & 7) ? 1 : 0)) << 3;
-	return val;
-}
-
-static inline u32 _RND128(u32 sz)
-{
-	u32	val;
-
-	val = ((sz >> 7) + ((sz & 127) ? 1 : 0)) << 7;
-	return val;
-}
-
-static inline u32 _RND256(u32 sz)
-{
-	u32	val;
-
-	val = ((sz >> 8) + ((sz & 255) ? 1 : 0)) << 8;
-	return val;
-}
-
-static inline u32 _RND512(u32 sz)
-{
-	u32	val;
-
-	val = ((sz >> 9) + ((sz & 511) ? 1 : 0)) << 9;
-	return val;
-}
-
-static inline u32 bitshift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++)
-		if (((bitmask>>i) &  0x1) == 1)
-			break;
-	return i;
-}
-
-/*  limitation of path length */
-#define PATH_LENGTH_MAX PATH_MAX
 
 struct rtw_netdev_priv_indicator {
 	void *priv;
@@ -301,7 +162,6 @@ struct rtw_netdev_priv_indicator {
 };
 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
 						    void *old_priv);
-struct net_device *rtw_alloc_etherdev(int sizeof_priv);
 
 #define rtw_netdev_priv(netdev)					\
 	(((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv)
@@ -319,50 +179,12 @@ void rtw_free_netdev(struct net_device *
 #define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)), (sig), 1)
 
 u64 rtw_modular64(u64 x, u64 y);
-u64 rtw_division64(u64 x, u64 y);
 
 /* Macros for handling unaligned memory accesses */
 
-#define RTW_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
-#define RTW_PUT_BE16(a, val)			\
-	do {					\
-		(a)[0] = ((u16) (val)) >> 8;	\
-		(a)[1] = ((u16) (val)) & 0xff;	\
-	} while (0)
-
-#define RTW_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
-#define RTW_PUT_LE16(a, val)			\
-	do {					\
-		(a)[1] = ((u16) (val)) >> 8;	\
-		(a)[0] = ((u16) (val)) & 0xff;	\
-	} while (0)
-
 #define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
 			 ((u32) (a)[2]))
 
-#define RTW_PUT_BE32(a, val)					\
-	do {							\
-		(a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff);	\
-		(a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff);	\
-		(a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff);	\
-		(a)[3] = (u8) (((u32) (val)) & 0xff);		\
-	} while (0)
-
 void rtw_buf_free(u8 **buf, u32 *buf_len);
 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len);
-
-struct rtw_cbuf {
-	u32 write;
-	u32 read;
-	u32 size;
-	void *bufs[0];
-};
-
-bool rtw_cbuf_full(struct rtw_cbuf *cbuf);
-bool rtw_cbuf_empty(struct rtw_cbuf *cbuf);
-bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf);
-void *rtw_cbuf_pop(struct rtw_cbuf *cbuf);
-struct rtw_cbuf *rtw_cbuf_alloc(u32 size);
-int wifirate2_ratetbl_inx(unsigned char rate);
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/recv_osdep.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/recv_osdep.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/recv_osdep.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/recv_osdep.h	2014-09-28 17:29:07.000000000 -0400
@@ -43,10 +43,7 @@ int rtw_os_recv_resource_alloc(struct ad
 
 int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
 
-void rtw_os_read_port(struct adapter *padapter, struct recv_buf *precvbuf);
-
 void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
-int nat25_handle_frame(struct adapter *priv, struct sk_buff *skb);
 int _netdev_open(struct net_device *pnetdev);
 int netdev_open(struct net_device *pnetdev);
 int netdev_close(struct net_device *pnetdev);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -112,11 +112,6 @@ u8 rtl8188e_set_raid_cmd(struct adapter
 void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg,
 			   u8 rssi_level);
 
-#ifdef CONFIG_88EU_P2P
-void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state);
-#endif /* CONFIG_88EU_P2P */
-
-void CheckFwRsvdPageContent(struct adapter *adapt);
 void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt);
 
 #endif/* __RTL8188E_CMD_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_hal.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_hal.h	2014-08-07 04:56:40.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_hal.h	2014-09-28 21:38:52.000000000 -0400
@@ -31,9 +31,8 @@
 #include "rtl8188e_xmit.h"
 #include "rtl8188e_cmd.h"
 #include "Hal8188EPwrSeq.h"
-#include "rtl8188e_sreset.h"
 #include "rtw_efuse.h"
-
+#include "rtw_sreset.h"
 #include "odm_precomp.h"
 
 /*  Fw Array */
@@ -241,7 +240,6 @@ enum rt_regulator_mode {
 
 struct hal_data_8188e {
 	struct HAL_VERSION	VersionID;
-	enum rt_multi_func MultiFunc; /*  For multi-function consideration. */
 	enum rt_regulator_mode RegulatorMode; /*  switching regulator or LDO */
 	u16	CustomerID;
 
@@ -387,10 +385,6 @@ struct hal_data_8188e {
 
 	u16	EfuseUsedBytes;
 
-#ifdef CONFIG_88EU_P2P
-	struct P2P_PS_Offload_t	p2p_ps_offload;
-#endif
-
 	/*  Auto FSM to Turn On, include clock, isolation, power control
 	 *  for MAC only */
 	u8	bMacPwrCtrlOn;
@@ -456,19 +450,17 @@ void Hal_EfuseParseBoardType88E(struct a
 void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo,
 				bool AutoLoadFail);
 
-bool HalDetectPwrDownMode88E(struct adapter *Adapter);
-
-void Hal_InitChannelPlan(struct adapter *padapter);
 void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc);
 
 /*  register */
 void SetBcnCtrlReg(struct adapter *padapter, u8 SetBits, u8 ClearBits);
 
-void rtl8188e_clone_haldata(struct adapter *dst, struct adapter *src);
 void rtl8188e_start_thread(struct adapter *padapter);
 void rtl8188e_stop_thread(struct adapter *padapter);
 
 void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter  *Adapter, int len);
+s32 iol_execute(struct adapter *padapter, u8 control);
+void iol_mode_enable(struct adapter *padapter, u8 enable);
 s32 rtl8188e_iol_efuse_patch(struct adapter *padapter);
 void rtw_cancel_all_timer(struct adapter *padapter);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_sreset.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_sreset.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_sreset.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_sreset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _RTL8188E_SRESET_H_
-#define _RTL8188E_SRESET_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_sreset.h>
-
-void rtl8188e_silentreset_for_specific_platform(struct adapter *padapter);
-void rtl8188e_sreset_xmit_status_check(struct adapter *padapter);
-void rtl8188e_sreset_linked_status_check(struct adapter *padapter);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h	2014-09-28 17:29:07.000000000 -0400
@@ -159,7 +159,6 @@ struct txrpt_ccx_88e {
 void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc,
 			       u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull);
 s32 rtl8188eu_init_xmit_priv(struct adapter *padapter);
-void rtl8188eu_free_xmit_priv(struct adapter *padapter);
 s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame);
 s32 rtl8188eu_mgnt_xmit(struct adapter *padapter, struct xmit_frame *frame);
 s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_br_ext.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_br_ext.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_br_ext.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_br_ext.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _RTW_BR_EXT_H_
-#define _RTW_BR_EXT_H_
-
-#define MACADDRLEN		6
-#define _DEBUG_ERR		DBG_88E
-#define _DEBUG_INFO		DBG_88E
-#define DEBUG_WARN		DBG_88E
-#define DEBUG_INFO		DBG_88E
-#define DEBUG_ERR		DBG_88E
-#define GET_MY_HWADDR(padapter)		((padapter)->eeprompriv.mac_addr)
-
-#define NAT25_HASH_BITS		4
-#define NAT25_HASH_SIZE		(1 << NAT25_HASH_BITS)
-#define NAT25_AGEING_TIME	300
-
-#define MAX_NETWORK_ADDR_LEN	17
-
-struct nat25_network_db_entry {
-	struct nat25_network_db_entry	*next_hash;
-	struct nat25_network_db_entry	**pprev_hash;
-	atomic_t	use_count;
-	unsigned char	macAddr[6];
-	unsigned long	ageing_timer;
-	unsigned char	networkAddr[MAX_NETWORK_ADDR_LEN];
-};
-
-enum NAT25_METHOD {
-	NAT25_MIN,
-	NAT25_CHECK,
-	NAT25_INSERT,
-	NAT25_LOOKUP,
-	NAT25_PARSE,
-	NAT25_MAX
-};
-
-struct br_ext_info {
-	unsigned int	nat25_disable;
-	unsigned int	macclone_enable;
-	unsigned int	dhcp_bcst_disable;
-	int	addPPPoETag;		/* 1: Add PPPoE relay-SID, 0: disable */
-	unsigned char	nat25_dmzMac[MACADDRLEN];
-	unsigned int	nat25sc_disable;
-};
-
-void nat25_db_cleanup(struct adapter *priv);
-
-#endif /*  _RTW_BR_EXT_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_cmd.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_cmd.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,16 +24,11 @@
 #include <rtw_rf.h>
 #include <rtw_led.h>
 
-#define C2H_MEM_SZ (16*1024)
-
 #include <osdep_service.h>
 #include <ieee80211.h> /*  <ieee80211/ieee80211.h> */
 
-#define FREE_CMDOBJ_SZ	128
-
 #define MAX_CMDSZ	1024
 #define MAX_RSPSZ	512
-#define MAX_EVTSZ	1024
 
 #define CMDBUFF_ALIGN_SZ 512
 
@@ -52,32 +47,13 @@ struct cmd_priv {
 	struct semaphore cmd_queue_sema;
 	struct semaphore terminate_cmdthread_sema;
 	struct __queue cmd_queue;
-	u8	cmd_seq;
-	u8	*cmd_buf;	/* shall be non-paged, and 4 bytes aligned */
-	u8	*cmd_allocated_buf;
-	u8	*rsp_buf;	/* shall be non-paged, and 4 bytes aligned */
-	u8	*rsp_allocated_buf;
-	u32	cmd_issued_cnt;
-	u32	cmd_done_cnt;
-	u32	rsp_cnt;
 	u8 cmdthd_running;
 	struct adapter *padapter;
 };
 
-struct	evt_priv {
-	struct work_struct c2h_wk;
-	bool c2h_wk_alive;
-	struct rtw_cbuf *c2h_queue;
-	#define C2H_QUEUE_MAX_LEN 10
-	atomic_t event_seq;
-	u8	*evt_buf;	/* shall be non-paged, and 4 bytes aligned */
-	u8	*evt_allocated_buf;
-	u32	evt_done_cnt;
-};
-
 #define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
 do {\
-	_rtw_init_listhead(&pcmd->list);\
+	INIT_LIST_HEAD(&pcmd->list);\
 	pcmd->cmdcode = code;\
 	pcmd->parmbuf = (u8 *)(pparm);\
 	pcmd->cmdsz = sizeof(*pparm);\
@@ -85,31 +61,13 @@ do {\
 	pcmd->rspsz = 0;\
 } while (0)
 
-struct c2h_evt_hdr {
-	u8 id:4;
-	u8 plen:4;
-	u8 seq;
-	u8 payload[0];
-};
-
-#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen)
-
 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv);
+struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue);
 void rtw_free_cmd_obj(struct cmd_obj *pcmd);
 
 int rtw_cmd_thread(void *context);
 
-u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
-void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv);
-
-u32 rtw_init_evt_priv(struct evt_priv *pevtpriv);
-void rtw_free_evt_priv(struct evt_priv *pevtpriv);
-void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv);
-void rtw_evt_notify_isr(struct evt_priv *pevtpriv);
-#ifdef CONFIG_88EU_P2P
-u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType);
-#endif /* CONFIG_88EU_P2P */
+int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
 
 enum rtw_drvextra_cmd_id {
 	NONE_WK_CID,
@@ -146,39 +104,6 @@ enum RFINTFS {
 /*
 Caller Mode: Infra, Ad-HoC(C)
 
-Notes: To enter USB suspend mode
-
-Command Mode
-
-*/
-struct usb_suspend_parm {
-	u32 action;/*  1: sleep, 0:resume */
-};
-
-/*
-Caller Mode: Infra, Ad-HoC
-
-Notes: To join a known BSS.
-
-Command-Event Mode
-
-*/
-
-/*
-Caller Mode: Infra, Ad-Hoc
-
-Notes: To join the specified bss
-
-Command Event Mode
-
-*/
-struct joinbss_parm {
-	struct wlan_bssid_ex network;
-};
-
-/*
-Caller Mode: Infra, Ad-HoC(C)
-
 Notes: To disconnect the current associated BSS
 
 Command Mode
@@ -188,17 +113,6 @@ struct disconnect_parm {
 	u32 deauth_timeout_ms;
 };
 
-/*
-Caller Mode: AP, Ad-HoC(M)
-
-Notes: To create a BSS
-
-Command Mode
-*/
-struct createbss_parm {
-	struct wlan_bssid_ex network;
-};
-
 struct	setopmode_parm {
 	u8	mode;
 	u8	rsvd[3];
@@ -329,160 +243,6 @@ struct setstapwrstate_parm {
 };
 
 /*
-Caller Mode: Any
-
-Notes: To setup the basic rate of RTL8711
-
-Command Mode
-
-*/
-struct	setbasicrate_parm {
-	u8	basicrates[NumRates];
-};
-
-/*
-Caller Mode: Any
-
-Notes: To read the current basic rate
-
-Command-Rsp Mode
-
-*/
-struct getbasicrate_parm {
-	u32 rsvd;
-};
-
-struct getbasicrate_rsp {
-	u8 basicrates[NumRates];
-};
-
-/*
-Caller Mode: Any
-
-Notes: To setup the data rate of RTL8711
-
-Command Mode
-
-*/
-struct setdatarate_parm {
-	u8	mac_id;
-	u8	datarates[NumRates];
-};
-
-/*
-Caller Mode: Any
-
-Notes: To read the current data rate
-
-Command-Rsp Mode
-
-*/
-struct getdatarate_parm {
-	u32 rsvd;
-
-};
-struct getdatarate_rsp {
-	u8 datarates[NumRates];
-};
-
-/*
-Caller Mode: Any
-AP: AP can use the info for the contents of beacon frame
-Infra: STA can use the info when sitesurveying
-Ad-HoC(M): Like AP
-Ad-HoC(C): Like STA
-
-Notes: To set the phy capability of the NIC
-
-Command Mode
-
-*/
-
-struct	setphyinfo_parm {
-	struct regulatory_class class_sets[NUM_REGULATORYS];
-	u8	status;
-};
-
-struct	getphyinfo_parm {
-	u32 rsvd;
-};
-
-struct	getphyinfo_rsp {
-	struct regulatory_class class_sets[NUM_REGULATORYS];
-	u8	status;
-};
-
-/*
-Caller Mode: Any
-
-Notes: To set the channel/modem/band
-This command will be used when channel/modem/band is changed.
-
-Command Mode
-
-*/
-struct	setphy_parm {
-	u8	rfchannel;
-	u8	modem;
-};
-
-/*
-Caller Mode: Any
-
-Notes: To get the current setting of channel/modem/band
-
-Command-Rsp Mode
-
-*/
-struct	getphy_parm {
-	u32 rsvd;
-
-};
-struct	getphy_rsp {
-	u8	rfchannel;
-	u8	modem;
-};
-
-struct readBB_parm {
-	u8	offset;
-};
-struct readBB_rsp {
-	u8	value;
-};
-
-struct readTSSI_parm {
-	u8	offset;
-};
-struct readTSSI_rsp {
-	u8	value;
-};
-
-struct writeBB_parm {
-	u8	offset;
-	u8	value;
-};
-
-struct readRF_parm {
-	u8	offset;
-};
-struct readRF_rsp {
-	u32	value;
-};
-
-struct writeRF_parm {
-	u32	offset;
-	u32	value;
-};
-
-struct getrfintfs_parm {
-	u8	rfintfs;
-};
-
-struct Tx_Beacon_param {
-	struct wlan_bssid_ex network;
-};
-
-/*
 	Notes: This command is used for H2C/C2H loopback testing
 
 	mac[0] == 0
@@ -540,167 +300,6 @@ struct drvextra_cmd_parm {
 	unsigned char *pbuf;
 };
 
-/*------------------- Below are used for RF/BB tunning ---------------------*/
-
-struct	setantenna_parm {
-	u8	tx_antset;
-	u8	rx_antset;
-	u8	tx_antenna;
-	u8	rx_antenna;
-};
-
-struct	enrateadaptive_parm {
-	u32	en;
-};
-
-struct settxagctbl_parm {
-	u32	txagc[MAX_RATES_LENGTH];
-};
-
-struct gettxagctbl_parm {
-	u32 rsvd;
-};
-struct gettxagctbl_rsp {
-	u32	txagc[MAX_RATES_LENGTH];
-};
-
-struct setagcctrl_parm {
-	u32	agcctrl;		/*  0: pure hw, 1: fw */
-};
-
-struct setssup_parm	{
-	u32	ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct getssup_parm	{
-	u32 rsvd;
-};
-
-struct getssup_rsp	{
-	u8	ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct setssdlevel_parm	{
-	u8	ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct getssdlevel_parm	{
-	u32 rsvd;
-};
-
-struct getssdlevel_rsp	{
-	u8	ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct setssulevel_parm	{
-	u8	ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct getssulevel_parm	{
-	u32 rsvd;
-};
-
-struct getssulevel_rsp	{
-	u8	ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct	setcountjudge_parm {
-	u8	count_judge[MAX_RATES_LENGTH];
-};
-
-struct	getcountjudge_parm {
-	u32 rsvd;
-};
-
-struct	getcountjudge_rsp {
-	u8	count_judge[MAX_RATES_LENGTH];
-};
-
-struct setratable_parm {
-	u8 ss_ForceUp[NumRates];
-	u8 ss_ULevel[NumRates];
-	u8 ss_DLevel[NumRates];
-	u8 count_judge[NumRates];
-};
-
-struct getratable_parm {
-	uint rsvd;
-};
-
-struct getratable_rsp {
-	u8 ss_ForceUp[NumRates];
-	u8 ss_ULevel[NumRates];
-	u8 ss_DLevel[NumRates];
-	u8 count_judge[NumRates];
-};
-
-/* to get TX,RX retry count */
-
-struct gettxretrycnt_parm {
-	unsigned int rsvd;
-};
-
-struct gettxretrycnt_rsp {
-	unsigned long tx_retrycnt;
-};
-
-struct getrxretrycnt_parm {
-	unsigned int rsvd;
-};
-
-struct getrxretrycnt_rsp {
-	unsigned long rx_retrycnt;
-};
-
-/* to get BCNOK,BCNERR count */
-struct getbcnokcnt_parm {
-	unsigned int rsvd;
-};
-
-struct getbcnokcnt_rsp {
-	unsigned long  bcnokcnt;
-};
-
-struct getbcnerrcnt_parm {
-	unsigned int rsvd;
-};
-
-struct getbcnerrcnt_rsp {
-	unsigned long bcnerrcnt;
-};
-
-/*  to get current TX power level */
-struct getcurtxpwrlevel_parm {
-	unsigned int rsvd;
-};
-struct getcurtxpwrlevel_rspi {
-	unsigned short tx_power;
-};
-
-struct setprobereqextraie_parm {
-	unsigned char e_id;
-	unsigned char ie_len;
-	unsigned char ie[0];
-};
-
-struct setassocreqextraie_parm {
-	unsigned char e_id;
-	unsigned char ie_len;
-	unsigned char ie[0];
-};
-
-struct setproberspextraie_parm {
-	unsigned char e_id;
-	unsigned char ie_len;
-	unsigned char ie[0];
-};
-
-struct setassocrspextraie_parm {
-	unsigned char e_id;
-	unsigned char ie_len;
-	unsigned char ie[0];
-};
-
 struct addBaReq_parm {
 	unsigned int tid;
 	u8	addr[ETH_ALEN];
@@ -718,22 +317,6 @@ struct SetChannelPlan_param {
 	u8 channel_plan;
 };
 
-/*H2C Handler index: 60 */
-struct LedBlink_param {
-	struct LED_871x *pLed;
-};
-
-/*H2C Handler index: 61 */
-struct SetChannelSwitch_param {
-	u8 new_ch_no;
-};
-
-/*H2C Handler index: 62 */
-struct TDLSoption_param {
-	u8 addr[ETH_ALEN];
-	u8 option;
-};
-
 #define GEN_CMD_CODE(cmd)	cmd ## _CMD_
 
 /*
@@ -747,26 +330,16 @@ Result:
 
 */
 
-#define H2C_RSP_OFFSET		512
-
 #define H2C_SUCCESS		0x00
 #define H2C_SUCCESS_RSP		0x01
-#define H2C_DUPLICATED		0x02
 #define H2C_DROPPED		0x03
 #define H2C_PARAMETERS_ERROR	0x04
 #define H2C_REJECTED		0x05
-#define H2C_CMD_OVERFLOW	0x06
-#define H2C_RESERVED		0x07
 
-u8 rtw_setassocsta_cmd(struct adapter *padapter, u8 *mac_addr);
-u8 rtw_setstandby_cmd(struct adapter *padapter, uint action);
 u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
 		      int ssid_num, struct rtw_ieee80211_channel *ch,
 		      int ch_num);
 u8 rtw_createbss_cmd(struct adapter *padapter);
-u8 rtw_createbss_cmd_ex(struct adapter *padapter, unsigned char *pbss,
-			unsigned int sz);
-u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch);
 u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key);
 u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry,
 		       u8 enqueue);
@@ -775,21 +348,6 @@ u8 rtw_disassoc_cmd(struct adapter *pada
 		    bool enqueue);
 u8 rtw_setopmode_cmd(struct adapter *padapter,
 		     enum ndis_802_11_network_infra networktype);
-u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset);
-u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset);
-u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val);
-u8 rtw_setrfreg_cmd(struct adapter *padapter, u8 offset, u32 val);
-u8 rtw_getbbreg_cmd(struct adapter *padapter, u8 offset, u8 *pval);
-u8 rtw_getrfreg_cmd(struct adapter *padapter, u8 offset, u8 *pval);
-u8 rtw_setrfintfs_cmd(struct adapter *padapter, u8 mode);
-u8 rtw_setrttbl_cmd(struct adapter *padapter,
-		    struct setratable_parm *prate_table);
-u8 rtw_getrttbl_cmd(struct adapter *padapter, struct getratable_rsp *pval);
-
-u8 rtw_gettssi_cmd(struct adapter *padapter, u8 offset, u8 *pval);
-u8 rtw_setfwdig_cmd(struct adapter *padapter, u8 type);
-u8 rtw_setfwra_cmd(struct adapter *padapter, u8 type);
-
 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr);
 
 u8 rtw_dynamic_chk_wk_cmd(struct adapter *adapter);
@@ -804,21 +362,13 @@ u8 rtw_ps_cmd(struct adapter *padapter);
 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter);
 #endif
 
-u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset,
-		  u8 enqueue);
 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue);
-u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no);
-u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option);
-
-u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt);
-
 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf);
 
 void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
 void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
 void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
 void rtw_createbss_cmd_callback(struct adapter *adapt, struct cmd_obj *pcmd);
-void rtw_getbbrfreg_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
 void rtw_readtssi_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
 
 void rtw_setstaKey_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
@@ -831,158 +381,42 @@ struct _cmd_callback {
 };
 
 enum rtw_h2c_cmd {
-	GEN_CMD_CODE(_Read_MACREG),	/*0*/
-	GEN_CMD_CODE(_Write_MACREG),
-	GEN_CMD_CODE(_Read_BBREG),
-	GEN_CMD_CODE(_Write_BBREG),
-	GEN_CMD_CODE(_Read_RFREG),
-	GEN_CMD_CODE(_Write_RFREG), /*5*/
-	GEN_CMD_CODE(_Read_EEPROM),
-	GEN_CMD_CODE(_Write_EEPROM),
-	GEN_CMD_CODE(_Read_EFUSE),
-	GEN_CMD_CODE(_Write_EFUSE),
-
-	GEN_CMD_CODE(_Read_CAM),	/*10*/
-	GEN_CMD_CODE(_Write_CAM),
-	GEN_CMD_CODE(_setBCNITV),
-	GEN_CMD_CODE(_setMBIDCFG),
-	GEN_CMD_CODE(_JoinBss),   /*14*/
-	GEN_CMD_CODE(_DisConnect), /*15*/
+	GEN_CMD_CODE(_JoinBss),
+	GEN_CMD_CODE(_DisConnect),
 	GEN_CMD_CODE(_CreateBss),
 	GEN_CMD_CODE(_SetOpMode),
-	GEN_CMD_CODE(_SiteSurvey),  /*18*/
+	GEN_CMD_CODE(_SiteSurvey),
 	GEN_CMD_CODE(_SetAuth),
-
-	GEN_CMD_CODE(_SetKey),	/*20*/
+	GEN_CMD_CODE(_SetKey),
 	GEN_CMD_CODE(_SetStaKey),
 	GEN_CMD_CODE(_SetAssocSta),
-	GEN_CMD_CODE(_DelAssocSta),
-	GEN_CMD_CODE(_SetStaPwrState),
-	GEN_CMD_CODE(_SetBasicRate), /*25*/
-	GEN_CMD_CODE(_GetBasicRate),
-	GEN_CMD_CODE(_SetDataRate),
-	GEN_CMD_CODE(_GetDataRate),
-	GEN_CMD_CODE(_SetPhyInfo),
-
-	GEN_CMD_CODE(_GetPhyInfo),	/*30*/
-	GEN_CMD_CODE(_SetPhy),
-	GEN_CMD_CODE(_GetPhy),
-	GEN_CMD_CODE(_readRssi),
-	GEN_CMD_CODE(_readGain),
-	GEN_CMD_CODE(_SetAtim), /*35*/
-	GEN_CMD_CODE(_SetPwrMode),
-	GEN_CMD_CODE(_JoinbssRpt),
-	GEN_CMD_CODE(_SetRaTable),
-	GEN_CMD_CODE(_GetRaTable),
-
-	GEN_CMD_CODE(_GetCCXReport), /*40*/
-	GEN_CMD_CODE(_GetDTMReport),
-	GEN_CMD_CODE(_GetTXRateStatistics),
-	GEN_CMD_CODE(_SetUsbSuspend),
-	GEN_CMD_CODE(_SetH2cLbk),
-	GEN_CMD_CODE(_AddBAReq), /*45*/
-	GEN_CMD_CODE(_SetChannel), /*46*/
-	GEN_CMD_CODE(_SetTxPower),
-	GEN_CMD_CODE(_SwitchAntenna),
-	GEN_CMD_CODE(_SetCrystalCap),
-	GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/
-
-	GEN_CMD_CODE(_SetSingleToneTx),/*51*/
-	GEN_CMD_CODE(_SetCarrierSuppressionTx),
-	GEN_CMD_CODE(_SetContinuousTx),
-	GEN_CMD_CODE(_SwitchBandwidth), /*54*/
-	GEN_CMD_CODE(_TX_Beacon), /*55*/
-
-	GEN_CMD_CODE(_Set_MLME_EVT), /*56*/
-	GEN_CMD_CODE(_Set_Drv_Extra), /*57*/
-	GEN_CMD_CODE(_Set_H2C_MSG), /*58*/
-
-	GEN_CMD_CODE(_SetChannelPlan), /*59*/
-	GEN_CMD_CODE(_LedBlink), /*60*/
-
-	GEN_CMD_CODE(_SetChannelSwitch), /*61*/
-	GEN_CMD_CODE(_TDLS), /*62*/
+	GEN_CMD_CODE(_AddBAReq),
+	GEN_CMD_CODE(_SetChannel),
+	GEN_CMD_CODE(_TX_Beacon),
+	GEN_CMD_CODE(_Set_MLME_EVT),
+	GEN_CMD_CODE(_Set_Drv_Extra),
+	GEN_CMD_CODE(_SetChannelPlan),
 
 	MAX_H2CCMD
 };
 
-#define _GetBBReg_CMD_		_Read_BBREG_CMD_
-#define _SetBBReg_CMD_		_Write_BBREG_CMD_
-#define _GetRFReg_CMD_		_Read_RFREG_CMD_
-#define _SetRFReg_CMD_		_Write_RFREG_CMD_
-
 #ifdef _RTW_CMD_C_
 static struct _cmd_callback	rtw_cmd_callback[] = {
-	{GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
-	{GEN_CMD_CODE(_Write_MACREG), NULL},
-	{GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback},
-	{GEN_CMD_CODE(_Write_BBREG), NULL},
-	{GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback},
-	{GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
-	{GEN_CMD_CODE(_Read_EEPROM), NULL},
-	{GEN_CMD_CODE(_Write_EEPROM), NULL},
-	{GEN_CMD_CODE(_Read_EFUSE), NULL},
-	{GEN_CMD_CODE(_Write_EFUSE), NULL},
-
-	{GEN_CMD_CODE(_Read_CAM),	NULL},	/*10*/
-	{GEN_CMD_CODE(_Write_CAM),	 NULL},
-	{GEN_CMD_CODE(_setBCNITV), NULL},
-	{GEN_CMD_CODE(_setMBIDCFG), NULL},
-	{GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback},  /*14*/
-	{GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/
+	{GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback},
+	{GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback},
 	{GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback},
 	{GEN_CMD_CODE(_SetOpMode), NULL},
-	{GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/
+	{GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback},
 	{GEN_CMD_CODE(_SetAuth), NULL},
-
-	{GEN_CMD_CODE(_SetKey), NULL},	/*20*/
+	{GEN_CMD_CODE(_SetKey), NULL},
 	{GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback},
 	{GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback},
-	{GEN_CMD_CODE(_DelAssocSta), NULL},
-	{GEN_CMD_CODE(_SetStaPwrState), NULL},
-	{GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
-	{GEN_CMD_CODE(_GetBasicRate), NULL},
-	{GEN_CMD_CODE(_SetDataRate), NULL},
-	{GEN_CMD_CODE(_GetDataRate), NULL},
-	{GEN_CMD_CODE(_SetPhyInfo), NULL},
-
-	{GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
-	{GEN_CMD_CODE(_SetPhy), NULL},
-	{GEN_CMD_CODE(_GetPhy), NULL},
-	{GEN_CMD_CODE(_readRssi), NULL},
-	{GEN_CMD_CODE(_readGain), NULL},
-	{GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
-	{GEN_CMD_CODE(_SetPwrMode), NULL},
-	{GEN_CMD_CODE(_JoinbssRpt), NULL},
-	{GEN_CMD_CODE(_SetRaTable), NULL},
-	{GEN_CMD_CODE(_GetRaTable), NULL},
-
-	{GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
-	{GEN_CMD_CODE(_GetDTMReport),	NULL},
-	{GEN_CMD_CODE(_GetTXRateStatistics), NULL},
-	{GEN_CMD_CODE(_SetUsbSuspend), NULL},
-	{GEN_CMD_CODE(_SetH2cLbk), NULL},
-	{GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
-	{GEN_CMD_CODE(_SetChannel), NULL},		/*46*/
-	{GEN_CMD_CODE(_SetTxPower), NULL},
-	{GEN_CMD_CODE(_SwitchAntenna), NULL},
-	{GEN_CMD_CODE(_SetCrystalCap), NULL},
-	{GEN_CMD_CODE(_SetSingleCarrierTx), NULL},	/*50*/
-
-	{GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
-	{GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
-	{GEN_CMD_CODE(_SetContinuousTx), NULL},
-	{GEN_CMD_CODE(_SwitchBandwidth), NULL},		/*54*/
-	{GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
-
-	{GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
-	{GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
-	{GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
-	{GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
-	{GEN_CMD_CODE(_LedBlink), NULL},/*60*/
-
-	{GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
-	{GEN_CMD_CODE(_TDLS), NULL},/*62*/
+	{GEN_CMD_CODE(_AddBAReq), NULL},
+	{GEN_CMD_CODE(_SetChannel), NULL},
+	{GEN_CMD_CODE(_TX_Beacon), NULL},
+	{GEN_CMD_CODE(_Set_MLME_EVT), NULL},
+	{GEN_CMD_CODE(_Set_Drv_Extra), NULL},
+	{GEN_CMD_CODE(_SetChannelPlan), NULL},
 };
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_debug.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_debug.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_debug.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_debug.h	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,7 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 
-
+#define DRIVERVERSION	"v4.1.4_6773.20130222"
 #define _drv_always_			1
 #define _drv_emerg_			2
 #define _drv_alert_			3
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_efuse.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_efuse.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_efuse.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_efuse.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,52 +99,21 @@ struct efuse_hal {
 	u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN];
 };
 
-/*------------------------Export global variable----------------------------*/
-extern u8 fakeEfuseBank;
-extern u32 fakeEfuseUsedBytes;
-extern u8 fakeEfuseContent[];
-extern u8 fakeEfuseInitMap[];
-extern u8 fakeEfuseModifiedMap[];
-
-extern u32 BTEfuseUsedBytes;
-extern u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-extern u8 BTEfuseInitMap[];
-extern u8 BTEfuseModifiedMap[];
-
-extern u32 fakeBTEfuseUsedBytes;
-extern u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-extern u8 fakeBTEfuseInitMap[];
-extern u8 fakeBTEfuseModifiedMap[];
-/*------------------------Export global variable----------------------------*/
-
-u8 efuse_GetCurrentSize(struct adapter *adapter, u16 *size);
-u16 efuse_GetMaxSize(struct adapter *adapter);
-u8 rtw_efuse_access(struct adapter *adapter, u8 read, u16 start_addr,
-		    u16 cnts, u8 *data);
-u8 rtw_efuse_map_read(struct adapter *adapter, u16 addr, u16 cnts, u8 *data);
-u8 rtw_efuse_map_write(struct adapter *adapter, u16 addr, u16 cnts, u8 *data);
-u8 rtw_BT_efuse_map_read(struct adapter *adapter, u16 addr,
-			 u16 cnts, u8 *data);
-u8 rtw_BT_efuse_map_write(struct adapter *adapter, u16 addr,
-			  u16 cnts, u8 *data);
-u16 Efuse_GetCurrentSize(struct adapter *adapter, u8 efusetype, bool test);
+u16 Efuse_GetCurrentSize(struct adapter *adapter);
 u8 Efuse_CalculateWordCnts(u8 word_en);
-void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
 void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1,
-			      void *out, bool bPseudoTest);
-u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data, bool test);
-u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data, bool	test);
+			      void *out);
+u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data);
+u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data);
 
+void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset,
+		u16 _size_byte, u8 *pbuf);
 void Efuse_PowerSwitch(struct adapter *adapt, u8 bWrite, u8  PwrState);
-int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data, bool test);
-int Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data,
-			bool test);
+int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data);
+bool Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data);
 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
 u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
-			     u8 word_en, u8 *data, bool test);
-
-u8 EFUSE_Read1Byte(struct adapter *adapter, u16 address);
-void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
-void EFUSE_ShadowRead(struct adapter *adapt, u8 type, u16 offset, u32 *val);
+			     u8 word_en, u8 *data);
 
+void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h	2014-09-28 17:29:07.000000000 -0400
@@ -25,7 +25,6 @@
 
 typedef u8 NDIS_802_11_PMKID_VALUE[16];
 
-u8 rtw_set_802_11_add_key(struct adapter *adapt, struct ndis_802_11_key *key);
 u8 rtw_set_802_11_authentication_mode(struct adapter *adapt,
 				      enum ndis_802_11_auth_mode authmode);
 u8 rtw_set_802_11_bssid(struct adapter *adapter, u8 *bssid);
@@ -36,15 +35,8 @@ u8 rtw_set_802_11_bssid_list_scan(struct
 				  int ssid_max_num);
 u8 rtw_set_802_11_infrastructure_mode(struct adapter *adapter,
 				      enum ndis_802_11_network_infra type);
-u8 rtw_set_802_11_remove_wep(struct adapter *adapter, u32 keyindex);
 u8 rtw_set_802_11_ssid(struct adapter *adapt, struct ndis_802_11_ssid *ssid);
-u8 rtw_set_802_11_remove_key(struct adapter *adapt,
-			     struct ndis_802_11_remove_key *key);
-u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid);
 u16 rtw_get_cur_max_rate(struct adapter *adapter);
-int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode);
-int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan);
 int rtw_set_country(struct adapter *adapter, const char *country_code);
-int rtw_change_ifname(struct adapter *padapter, const char *ifname);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_io.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_io.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_io.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,343 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-
-#ifndef _RTW_IO_H_
-#define _RTW_IO_H_
-
-#include <osdep_service.h>
-#include <osdep_intf.h>
-
-#include <asm/byteorder.h>
-#include <linux/semaphore.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-
-#define rtw_usb_buffer_alloc(dev, size, dma)				\
-	usb_alloc_coherent((dev), (size), (in_interrupt() ?		\
-			   GFP_ATOMIC : GFP_KERNEL), (dma))
-#define rtw_usb_buffer_free(dev, size, addr, dma)			\
-	usb_free_coherent((dev), (size), (addr), (dma))
-
-#define NUM_IOREQ		8
-
-#define MAX_PROT_SZ	(64-16)
-
-#define _IOREADY		0
-#define _IO_WAIT_COMPLETE	1
-#define _IO_WAIT_RSP		2
-
-/*  IO COMMAND TYPE */
-#define _IOSZ_MASK_		(0x7F)
-#define _IO_WRITE_		BIT(7)
-#define _IO_FIXED_		BIT(8)
-#define _IO_BURST_		BIT(9)
-#define _IO_BYTE_		BIT(10)
-#define _IO_HW_			BIT(11)
-#define _IO_WORD_		BIT(12)
-#define _IO_SYNC_		BIT(13)
-#define _IO_CMDMASK_		(0x1F80)
-
-/*
-	For prompt mode accessing, caller shall free io_req
-	Otherwise, io_handler will free io_req
-*/
-
-/*  IO STATUS TYPE */
-#define _IO_ERR_		BIT(2)
-#define _IO_SUCCESS_		BIT(1)
-#define _IO_DONE_		BIT(0)
-
-#define IO_RD32			(_IO_SYNC_ | _IO_WORD_)
-#define IO_RD16			(_IO_SYNC_ | _IO_HW_)
-#define IO_RD8			(_IO_SYNC_ | _IO_BYTE_)
-
-#define IO_RD32_ASYNC		(_IO_WORD_)
-#define IO_RD16_ASYNC		(_IO_HW_)
-#define IO_RD8_ASYNC		(_IO_BYTE_)
-
-#define IO_WR32			(_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_)
-#define IO_WR16			(_IO_WRITE_ | _IO_SYNC_ | _IO_HW_)
-#define IO_WR8			(_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_)
-
-#define IO_WR32_ASYNC		(_IO_WRITE_ | _IO_WORD_)
-#define IO_WR16_ASYNC		(_IO_WRITE_ | _IO_HW_)
-#define IO_WR8_ASYNC		(_IO_WRITE_ | _IO_BYTE_)
-
-/*
-	Only Sync. burst accessing is provided.
-*/
-
-#define IO_WR_BURST(x)						\
-	(_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
-#define IO_RD_BURST(x)						\
-	(_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
-
-/* below is for the intf_option bit defition... */
-
-#define _INTF_ASYNC_	BIT(0)	/* support async io */
-
-struct intf_priv;
-struct intf_hdl;
-
-struct _io_ops {
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
-	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
-	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
-	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
-	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-	int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length,
-		       u8 *pdata);
-	int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
-	int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
-	int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-	void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
-			  u8 *pmem);
-	void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
-			   u8 *pmem);
-	u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr);
-	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
-			  u8 *pmem);
-	u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
-			   u8 *pmem);
-	u32 (*_write_scsi)(struct intf_hdl *pintfhdl, u32 cnt, u8 *pmem);
-	void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
-	void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
-};
-
-struct io_req {
-	struct list_head list;
-	u32	addr;
-	u32	val;
-	u32	command;
-	u32	status;
-	u8	*pbuf;
-	struct semaphore sema;
-
-	void (*_async_io_callback)(struct adapter *padater,
-				   struct io_req *pio_req, u8 *cnxt);
-	u8 *cnxt;
-};
-
-struct	intf_hdl {
-	struct adapter *padapter;
-	struct dvobj_priv *pintf_dev;
-	struct _io_ops	io_ops;
-};
-
-struct reg_protocol_rd {
-#ifdef __LITTLE_ENDIAN
-	/* DW1 */
-	u32		NumOfTrans:4;
-	u32		Reserved1:4;
-	u32		Reserved2:24;
-	/* DW2 */
-	u32		ByteCount:7;
-	u32		WriteEnable:1;		/* 0:read, 1:write */
-	u32		FixOrContinuous:1;	/* 0:continuous, 1: Fix */
-	u32		BurstMode:1;
-	u32		Byte1Access:1;
-	u32		Byte2Access:1;
-	u32		Byte4Access:1;
-	u32		Reserved3:3;
-	u32		Reserved4:16;
-	/* DW3 */
-	u32		BusAddress;
-	/* DW4 */
-	/* u32		Value; */
-#else
-/* DW1 */
-	u32 Reserved1:4;
-	u32 NumOfTrans:4;
-	u32 Reserved2:24;
-	/* DW2 */
-	u32 WriteEnable:1;
-	u32 ByteCount:7;
-	u32 Reserved3:3;
-	u32 Byte4Access:1;
-
-	u32 Byte2Access:1;
-	u32 Byte1Access:1;
-	u32 BurstMode:1;
-	u32 FixOrContinuous:1;
-	u32 Reserved4:16;
-	/* DW3 */
-	u32	BusAddress;
-
-	/* DW4 */
-#endif
-};
-
-struct reg_protocol_wt {
-#ifdef __LITTLE_ENDIAN
-	/* DW1 */
-	u32	NumOfTrans:4;
-	u32	Reserved1:4;
-	u32	Reserved2:24;
-	/* DW2 */
-	u32	ByteCount:7;
-	u32	WriteEnable:1;		/* 0:read, 1:write */
-	u32	FixOrContinuous:1;	/* 0:continuous, 1: Fix */
-	u32	BurstMode:1;
-	u32	Byte1Access:1;
-	u32	Byte2Access:1;
-	u32	Byte4Access:1;
-	u32	Reserved3:3;
-	u32	Reserved4:16;
-	/* DW3 */
-	u32	BusAddress;
-	/* DW4 */
-	u32	Value;
-#else
-	/* DW1 */
-	u32 Reserved1:4;
-	u32 NumOfTrans:4;
-	u32 Reserved2:24;
-	/* DW2 */
-	u32 WriteEnable:1;
-	u32 ByteCount:7;
-	u32 Reserved3:3;
-	u32 Byte4Access:1;
-	u32 Byte2Access:1;
-	u32 Byte1Access:1;
-	u32 BurstMode:1;
-	u32 FixOrContinuous:1;
-	u32 Reserved4:16;
-	/* DW3 */
-	u32	BusAddress;
-	/* DW4 */
-	u32	Value;
-#endif
-};
-
-/*
-Below is the data structure used by _io_handler
-*/
-
-struct io_priv {
-	struct adapter *padapter;
-	struct intf_hdl intf;
-};
-
-u8 _rtw_read8(struct adapter *adapter, u32 addr);
-u16 _rtw_read16(struct adapter *adapter, u32 addr);
-u32 _rtw_read32(struct adapter *adapter, u32 addr);
-void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void _rtw_read_port_cancel(struct adapter *adapter);
-
-int _rtw_write8(struct adapter *adapter, u32 addr, u8 val);
-int _rtw_write16(struct adapter *adapter, u32 addr, u16 val);
-int _rtw_write32(struct adapter *adapter, u32 addr, u32 val);
-int _rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata);
-
-int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val);
-int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val);
-int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val);
-
-void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
-			     u8 *pmem, int timeout_ms);
-void _rtw_write_port_cancel(struct adapter *adapter);
-
-#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr))
-#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
-#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
-#define rtw_read_mem(adapter, addr, cnt, mem)				\
-	_rtw_read_mem((adapter), (addr), (cnt), (mem))
-#define rtw_read_port(adapter, addr, cnt, mem)				\
-	_rtw_read_port((adapter), (addr), (cnt), (mem))
-#define rtw_read_port_cancel(adapter) _rtw_read_port_cancel((adapter))
-
-#define  rtw_write8(adapter, addr, val)					\
-	_rtw_write8((adapter), (addr), (val))
-#define  rtw_write16(adapter, addr, val)				\
-	_rtw_write16((adapter), (addr), (val))
-#define  rtw_write32(adapter, addr, val)				\
-	_rtw_write32((adapter), (addr), (val))
-#define  rtw_writeN(adapter, addr, length, data)			\
-	_rtw_writeN((adapter), (addr), (length), (data))
-#define rtw_write8_async(adapter, addr, val)				\
-	_rtw_write8_async((adapter), (addr), (val))
-#define rtw_write16_async(adapter, addr, val)				\
-	_rtw_write16_async((adapter), (addr), (val))
-#define rtw_write32_async(adapter, addr, val)				\
-	_rtw_write32_async((adapter), (addr), (val))
-#define rtw_write_mem(adapter, addr, cnt, mem)				\
-	_rtw_write_mem((adapter), (addr), (cnt), (mem))
-#define rtw_write_port(adapter, addr, cnt, mem)				\
-	_rtw_write_port((adapter), (addr), (cnt), (mem))
-#define rtw_write_port_and_wait(adapter, addr, cnt, mem, timeout_ms)	\
-	_rtw_write_port_and_wait((adapter), (addr), (cnt), (mem), (timeout_ms))
-#define rtw_write_port_cancel(adapter) _rtw_write_port_cancel((adapter))
-
-void rtw_write_scsi(struct adapter *adapter, u32 cnt, u8 *pmem);
-
-/* ioreq */
-void ioreq_read8(struct adapter *adapter, u32 addr, u8 *pval);
-void ioreq_read16(struct adapter *adapter, u32 addr, u16 *pval);
-void ioreq_read32(struct adapter *adapter, u32 addr, u32 *pval);
-void ioreq_write8(struct adapter *adapter, u32 addr, u8 val);
-void ioreq_write16(struct adapter *adapter, u32 addr, u16 val);
-void ioreq_write32(struct adapter *adapter, u32 addr, u32 val);
-
-uint async_read8(struct adapter *adapter, u32 addr, u8 *pbuff,
-		 void (*_async_io_callback)(struct adapter *padater,
-					    struct io_req *pio_req,
-					    u8 *cnxt), u8 *cnxt);
-uint async_read16(struct adapter *adapter, u32 addr,  u8 *pbuff,
-		  void (*_async_io_callback)(struct adapter *padater,
-					     struct io_req *pio_req,
-					     u8 *cnxt), u8 *cnxt);
-uint async_read32(struct adapter *adapter, u32 addr,  u8 *pbuff,
-		  void (*_async_io_callback)(struct adapter *padater,
-					     struct io_req *pio_req,
-					     u8 *cnxt), u8 *cnxt);
-
-void async_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void async_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-
-void async_write8(struct adapter *adapter, u32 addr, u8 val,
-		  void (*_async_io_callback)(struct adapter *padater,
-					     struct io_req *pio_req,
-					     u8 *cnxt), u8 *cnxt);
-void async_write16(struct adapter *adapter, u32 addr, u16 val,
-		   void (*_async_io_callback)(struct adapter *padater,
-					      struct io_req *pio_req,
-					      u8 *cnxt), u8 *cnxt);
-void async_write32(struct adapter *adapter, u32 addr, u32 val,
-		   void (*_async_io_callback)(struct adapter *padater,
-					      struct io_req *pio_req,
-					      u8 *cnxt), u8 *cnxt);
-
-void async_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void async_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-
-int rtw_init_io_priv(struct adapter *padapter,
-		     void (*set_intf_ops)(struct _io_ops *pops));
-
-void dev_power_down(struct adapter *Adapter, u8 bpwrup);
-
-#endif	/* _RTL8711_IO_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_iol.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_iol.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_iol.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_iol.h	2014-09-28 17:29:07.000000000 -0400
@@ -63,8 +63,6 @@ void read_efuse_from_txpktbuf(struct ada
 
 int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr,
 			   u8 value, u8 mask);
-int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr,
-			   u16 value, u16 mask);
 int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr,
 			   u32 value, u32 mask);
 int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h	2014-09-28 17:29:07.000000000 -0400
@@ -565,18 +565,6 @@ s32 dump_mgntframe_and_wait(struct adapt
 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
 				struct xmit_frame *pmgntframe);
 
-#ifdef CONFIG_88EU_P2P
-void issue_probersp_p2p(struct adapter *padapter, unsigned char *da);
-void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid,
-				 u8 ussidlen, u8 *pdev_raddr);
-void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr);
-void issue_probereq_p2p(struct adapter *padapter, u8 *da);
-int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt,
-			  int wait_ms);
-void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr,
-				   u8 dialogToken, u8 success);
-void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr);
-#endif /* CONFIG_88EU_P2P */
 void issue_beacon(struct adapter *padapter, int timeout_ms);
 void issue_probersp(struct adapter *padapter, unsigned char *da,
 		    u8 is_valid_p2p_probereq);
@@ -658,9 +646,9 @@ void mlmeext_sta_add_event_callback(stru
 
 void linked_status_chk(struct adapter *padapter);
 
-void survey_timer_hdl (struct adapter *padapter);
-void link_timer_hdl (struct adapter *padapter);
-void addba_timer_hdl(struct sta_info *psta);
+void survey_timer_hdl (void *function_context);
+void link_timer_hdl (void *funtion_context);
+void addba_timer_hdl(void *function_context);
 
 #define set_survey_timer(mlmeext, ms) \
 	do { \
@@ -720,78 +708,21 @@ u8 tdls_hdl(struct adapter *padapter, un
 #ifdef _RTW_CMD_C_
 
 static struct cmd_hdl wlancmds[] = {
-	GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
-	GEN_DRV_CMD_HANDLER(0, NULL)
-	GEN_DRV_CMD_HANDLER(0, NULL)
-	GEN_DRV_CMD_HANDLER(0, NULL)
-	GEN_DRV_CMD_HANDLER(0, NULL)
-	GEN_DRV_CMD_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct joinbss_parm), join_cmd_hdl) /*14*/
+	GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), join_cmd_hdl)
 	GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl)
-	GEN_MLME_EXT_HANDLER(sizeof (struct createbss_parm), createbss_hdl)
+	GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), createbss_hdl)
 	GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl)
-	GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm),
-			     sitesurvey_cmd_hdl) /*18*/
+	GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm), sitesurvey_cmd_hdl)
 	GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl)
-	GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl) /*20*/
+	GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl)
 	GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl)
 	GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL)  /*30*/
-	GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL)
-	GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)	/*40*/
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
 	GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl)
-	GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(0, NULL)
-	GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param),
-			     tx_beacon_hdl) /*55*/
-
-	GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/
-	GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/
-
-	GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/
-	GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param),
-			     set_chplan_hdl) /*59*/
-	GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param),
-			     led_blink_hdl) /*60*/
-
-	GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param),
-			     set_csa_hdl) /*61*/
-	GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param),
-			     tdls_hdl) /*62*/
+	GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl)
+	GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), tx_beacon_hdl)
+	GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl)
+	GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl)
+	GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl)
 };
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mlme.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mlme.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mlme.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mlme.h	2014-09-28 17:29:07.000000000 -0400
@@ -436,8 +436,6 @@ void indicate_wx_scan_complete_event(str
 void rtw_indicate_wx_assoc_event(struct adapter *padapter);
 void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
 int event_thread(void *context);
-void rtw_join_timeout_handler(void *FunctionContext);
-void _rtw_scan_timeout_handler(void *FunctionContext);
 void rtw_free_network_queue(struct adapter *adapter, u8 isfreeall);
 int rtw_init_mlme_priv(struct adapter *adapter);
 void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv);
@@ -553,47 +551,27 @@ void rtw_update_registrypriv_dev_network
 
 void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter);
 
-void _rtw_join_timeout_handler(struct adapter *adapter);
-void rtw_scan_timeout_handler(struct adapter *adapter);
+void _rtw_join_timeout_handler(void *function_context);
+void rtw_scan_timeout_handler(void *function_context);
 
-void rtw_dynamic_check_timer_handlder(struct adapter *adapter);
+void rtw_dynamic_check_timer_handlder(void *function_context);
 #define rtw_is_scan_deny(adapter) false
 #define rtw_clear_scan_deny(adapter) do {} while (0)
 #define rtw_set_scan_deny_timer_hdl(adapter) do {} while (0)
 #define rtw_set_scan_deny(adapter, ms) do {} while (0)
 
-
-int _rtw_init_mlme_priv(struct adapter *padapter);
-
 void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv);
 
-void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv);
-
-int _rtw_enqueue_network(struct __queue *queue, struct wlan_network *pnetwork);
-
-struct wlan_network *_rtw_dequeue_network(struct __queue *queue);
-
 struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv);
 
-
-void _rtw_free_network(struct mlme_priv *pmlmepriv,
-		       struct wlan_network *pnetwork, u8 isfreeall);
 void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
 			      struct wlan_network *pnetwork);
 
-
-struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr);
-
-void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall);
-
 int rtw_if_up(struct adapter *padapter);
 
-
 u8 *rtw_get_capability_from_ie(u8 *ie);
-u8 *rtw_get_timestampe_from_ie(u8 *ie);
 u8 *rtw_get_beacon_interval_from_ie(u8 *ie);
 
-
 void rtw_joinbss_reset(struct adapter *padapter);
 
 unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mp.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mp.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,495 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _RTW_MP_H_
-#define _RTW_MP_H_
-
-/*	00 - Success */
-/*	11 - Error */
-#define STATUS_SUCCESS				(0x00000000L)
-#define STATUS_PENDING				(0x00000103L)
-
-#define STATUS_UNSUCCESSFUL			(0xC0000001L)
-#define STATUS_INSUFFICIENT_RESOURCES		(0xC000009AL)
-#define STATUS_NOT_SUPPORTED			(0xC00000BBL)
-
-#define NDIS_STATUS_SUCCESS			((int)STATUS_SUCCESS)
-#define NDIS_STATUS_PENDING			((int)STATUS_PENDING)
-#define NDIS_STATUS_NOT_RECOGNIZED		((int)0x00010001L)
-#define NDIS_STATUS_NOT_COPIED			((int)0x00010002L)
-#define NDIS_STATUS_NOT_ACCEPTED		((int)0x00010003L)
-#define NDIS_STATUS_CALL_ACTIVE			((int)0x00010007L)
-
-#define NDIS_STATUS_FAILURE			((int)STATUS_UNSUCCESSFUL)
-#define NDIS_STATUS_RESOURCES		((int)STATUS_INSUFFICIENT_RESOURCES)
-#define NDIS_STATUS_CLOSING			((int)0xC0010002L)
-#define NDIS_STATUS_BAD_VERSION			((int)0xC0010004L)
-#define NDIS_STATUS_BAD_CHARACTERISTICS		((int)0xC0010005L)
-#define NDIS_STATUS_ADAPTER_NOT_FOUND		((int)0xC0010006L)
-#define NDIS_STATUS_OPEN_FAILED			((int)0xC0010007L)
-#define NDIS_STATUS_DEVICE_FAILED		((int)0xC0010008L)
-#define NDIS_STATUS_MULTICAST_FULL		((int)0xC0010009L)
-#define NDIS_STATUS_MULTICAST_EXISTS		((int)0xC001000AL)
-#define NDIS_STATUS_MULTICAST_NOT_FOUND		((int)0xC001000BL)
-#define NDIS_STATUS_REQUEST_ABORTED		((int)0xC001000CL)
-#define NDIS_STATUS_RESET_IN_PROGRESS		((int)0xC001000DL)
-#define NDIS_STATUS_CLOSING_INDICATING		((int)0xC001000EL)
-#define NDIS_STATUS_NOT_SUPPORTED		((int)STATUS_NOT_SUPPORTED)
-#define NDIS_STATUS_INVALID_PACKET		((int)0xC001000FL)
-#define NDIS_STATUS_OPEN_LIST_FULL		((int)0xC0010010L)
-#define NDIS_STATUS_ADAPTER_NOT_READY		((int)0xC0010011L)
-#define NDIS_STATUS_ADAPTER_NOT_OPEN		((int)0xC0010012L)
-#define NDIS_STATUS_NOT_INDICATING		((int)0xC0010013L)
-#define NDIS_STATUS_INVALID_LENGTH		((int)0xC0010014L)
-#define NDIS_STATUS_INVALID_DATA		((int)0xC0010015L)
-#define NDIS_STATUS_BUFFER_TOO_SHORT		((int)0xC0010016L)
-#define NDIS_STATUS_INVALID_OID			((int)0xC0010017L)
-#define NDIS_STATUS_ADAPTER_REMOVED		((int)0xC0010018L)
-#define NDIS_STATUS_UNSUPPORTED_MEDIA		((int)0xC0010019L)
-#define NDIS_STATUS_GROUP_ADDRESS_IN_USE	((int)0xC001001AL)
-#define NDIS_STATUS_FILE_NOT_FOUND		((int)0xC001001BL)
-#define NDIS_STATUS_ERROR_READING_FILE		((int)0xC001001CL)
-#define NDIS_STATUS_ALREADY_MAPPED		((int)0xC001001DL)
-#define NDIS_STATUS_RESOURCE_CONFLICT		((int)0xC001001EL)
-#define NDIS_STATUS_NO_CABLE			((int)0xC001001FL)
-
-#define NDIS_STATUS_INVALID_SAP			((int)0xC0010020L)
-#define NDIS_STATUS_SAP_IN_USE			((int)0xC0010021L)
-#define NDIS_STATUS_INVALID_ADDRESS		((int)0xC0010022L)
-#define NDIS_STATUS_VC_NOT_ACTIVATED		((int)0xC0010023L)
-#define NDIS_STATUS_DEST_OUT_OF_ORDER		((int)0xC0010024L)  /*cause 27*/
-#define NDIS_STATUS_VC_NOT_AVAILABLE		((int)0xC0010025L)  /*cause 35,45 */
-#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE	((int)0xC0010026L)  /*cause 37*/
-#define NDIS_STATUS_INCOMPATABLE_QOS		((int)0xC0010027L)  /*cause 49*/
-#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED	((int)0xC0010028L)  /*cause 93*/
-#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION	((int)0xC0010029L)  /*cause 3 */
-
-enum antenna_path {
-	ANTENNA_NONE = 0x00,
-	ANTENNA_D,
-	ANTENNA_C,
-	ANTENNA_CD,
-	ANTENNA_B,
-	ANTENNA_BD,
-	ANTENNA_BC,
-	ANTENNA_BCD,
-	ANTENNA_A,
-	ANTENNA_AD,
-	ANTENNA_AC,
-	ANTENNA_ACD,
-	ANTENNA_AB,
-	ANTENNA_ABD,
-	ANTENNA_ABC,
-	ANTENNA_ABCD
-};
-
-
-#define MAX_MP_XMITBUF_SZ	2048
-#define NR_MP_XMITFRAME		8
-
-struct mp_xmit_frame {
-	struct list_head list;
-	struct pkt_attrib attrib;
-	struct sk_buff *pkt;
-	int frame_tag;
-	struct adapter *padapter;
-	struct urb *pxmit_urb[8];
-	/* insert urb, irp, and irpcnt info below... */
-	u8 *mem_addr;
-	u32 sz[8];
-	u8 bpending[8];
-	int ac_tag[8];
-	int last[8];
-	uint irpcnt;
-	uint fragcnt;
-	uint mem[(MAX_MP_XMITBUF_SZ >> 2)];
-};
-
-struct mp_wiparam {
-	u32 bcompleted;
-	u32 act_type;
-	u32 io_offset;
-	u32 io_value;
-};
-
-typedef void(*wi_act_func)(void *padapter);
-
-struct mp_tx {
-	u8 stop;
-	u32 count, sended;
-	u8 payload;
-	struct pkt_attrib attrib;
-	struct tx_desc desc;
-	u8 *pallocated_buf;
-	u8 *buf;
-	u32 buf_size, write_size;
-	void *PktTxThread;
-};
-
-#include <Hal8188EPhyCfg.h>
-
-#define MP_MAX_LINES		1000
-#define MP_MAX_LINES_BYTES	256
-
-typedef void (*MPT_WORK_ITEM_HANDLER)(void *Adapter);
-
-struct mpt_context {
-	/*  Indicate if we have started Mass Production Test. */
-	bool			bMassProdTest;
-
-	/*  Indicate if the driver is unloading or unloaded. */
-	bool			bMptDrvUnload;
-
-	struct semaphore MPh2c_Sema;
-	struct timer_list MPh2c_timeout_timer;
-/*  Event used to sync H2c for BT control */
-
-	bool		MptH2cRspEvent;
-	bool		MptBtC2hEvent;
-	bool		bMPh2c_timeout;
-
-	/* 8190 PCI does not support NDIS_WORK_ITEM. */
-	/*  Work Item for Mass Production Test. */
-	/*  Event used to sync the case unloading driver and MptWorkItem
-	 *  is still in progress. */
-	/*  Indicate a MptWorkItem is scheduled and not yet finished. */
-	bool			bMptWorkItemInProgress;
-	/*  An instance which implements function and context of MptWorkItem. */
-	MPT_WORK_ITEM_HANDLER	CurrMptAct;
-
-	/*  1=Start, 0=Stop from UI. */
-	u32	MptTestStart;
-	/*  _TEST_MODE, defined in MPT_Req2.h */
-	u32	MptTestItem;
-	/*  Variable needed in each implementation of CurrMptAct. */
-	u32	MptActType;	/*  Type of action performed in CurrMptAct. */
-	/*  The Offset of IO operation is depend of MptActType. */
-	u32	MptIoOffset;
-	/*  The Value of IO operation is depend of MptActType. */
-	u32	MptIoValue;
-	/*  The RfPath of IO operation is depend of MptActType. */
-	u32	MptRfPath;
-
-	enum wireless_mode MptWirelessModeToSw;	/*  Wireless mode to switch. */
-	u8	MptChannelToSw;		/*  Channel to switch. */
-	u8	MptInitGainToSet;	/*  Initial gain to set. */
-	u32	MptBandWidth;		/*  bandwidth to switch. */
-	u32	MptRateIndex;		/*  rate index. */
-	/*  Register value kept for Single Carrier Tx test. */
-	u8	btMpCckTxPower;
-	/*  Register value kept for Single Carrier Tx test. */
-	u8	btMpOfdmTxPower;
-	/*  For MP Tx Power index */
-	u8	TxPwrLevel[2];	/*  rf-A, rf-B */
-
-	/*  Content of RCR Regsiter for Mass Production Test. */
-	u32	MptRCR;
-	/*  true if we only receive packets with specific pattern. */
-	bool	bMptFilterPattern;
-	/*  Rx OK count, statistics used in Mass Production Test. */
-	u32	MptRxOkCnt;
-	/*  Rx CRC32 error count, statistics used in Mass Production Test. */
-	u32	MptRxCrcErrCnt;
-
-	bool	bCckContTx;	/*  true if we are in CCK Continuous Tx test. */
-	bool	bOfdmContTx;	/*  true if we are in OFDM Continuous Tx test. */
-	bool	bStartContTx;	/*  true if we have start Continuous Tx test. */
-	/*  true if we are in Single Carrier Tx test. */
-	bool	bSingleCarrier;
-	/*  true if we are in Carrier Suppression Tx Test. */
-	bool	bCarrierSuppression;
-	/* true if we are in Single Tone Tx test. */
-	bool	bSingleTone;
-
-	/*  ACK counter asked by K.Y.. */
-	bool	bMptEnableAckCounter;
-	u32	MptAckCounter;
-
-	u8	APK_bound[2];	/* for APK	path A/path B */
-	bool	bMptIndexEven;
-
-	u8	backup0xc50;
-	u8	backup0xc58;
-	u8	backup0xc30;
-	u8	backup0x52_RF_A;
-	u8	backup0x52_RF_B;
-
-	u8	h2cReqNum;
-	u8	c2hBuf[20];
-
-	u8	btInBuf[100];
-	u32	mptOutLen;
-	u8	mptOutBuf[100];
-};
-
-enum {
-	WRITE_REG = 1,
-	READ_REG,
-	WRITE_RF,
-	READ_RF,
-	MP_START,
-	MP_STOP,
-	MP_RATE,
-	MP_CHANNEL,
-	MP_BANDWIDTH,
-	MP_TXPOWER,
-	MP_ANT_TX,
-	MP_ANT_RX,
-	MP_CTX,
-	MP_QUERY,
-	MP_ARX,
-	MP_PSD,
-	MP_PWRTRK,
-	MP_THER,
-	MP_IOCTL,
-	EFUSE_GET,
-	EFUSE_SET,
-	MP_RESET_STATS,
-	MP_DUMP,
-	MP_PHYPARA,
-	MP_SetRFPathSwh,
-	MP_QueryDrvStats,
-	MP_SetBT,
-	CTA_TEST,
-	MP_NULL,
-};
-
-struct mp_priv {
-	struct adapter *papdater;
-
-	/* Testing Flag */
-	/* 0 for normal type packet, 1 for loopback packet (16bytes TXCMD) */
-	u32 mode;
-
-	u32 prev_fw_state;
-
-	/* OID cmd handler */
-	struct mp_wiparam workparam;
-
-	/* Tx Section */
-	u8 TID;
-	u32 tx_pktcount;
-	struct mp_tx tx;
-
-	/* Rx Section */
-	u32 rx_pktcount;
-	u32 rx_crcerrpktcount;
-	u32 rx_pktloss;
-
-	struct recv_stat rxstat;
-
-	/* RF/BB relative */
-	u8 channel;
-	u8 bandwidth;
-	u8 prime_channel_offset;
-	u8 txpoweridx;
-	u8 txpoweridx_b;
-	u8 rateidx;
-	u32 preamble;
-	u32 CrystalCap;
-
-	u16 antenna_tx;
-	u16 antenna_rx;
-
-	u8 check_mp_pkt;
-
-	u8 bSetTxPower;
-
-	struct wlan_network mp_network;
-	unsigned char network_macaddr[ETH_ALEN];
-
-	u8 *pallocated_mp_xmitframe_buf;
-	u8 *pmp_xmtframe_buf;
-	struct __queue free_mp_xmitqueue;
-	u32 free_mp_xmitframe_cnt;
-
-	struct mpt_context MptCtx;
-};
-
-struct iocmd_struct {
-	u8	cmdclass;
-	u16	value;
-	u8	index;
-};
-
-struct rf_reg_param {
-	u32 path;
-	u32 offset;
-	u32 value;
-};
-
-struct bb_reg_param {
-	u32 offset;
-	u32 value;
-};
-/*  */
-
-#define LOWER	true
-#define RAISE	false
-
-/* Hardware Registers */
-#define BB_REG_BASE_ADDR		0x800
-
-/* MP variables */
-enum mp_mode_{
-	MP_OFF,
-	MP_ON,
-	MP_ERR,
-	MP_CONTINUOUS_TX,
-	MP_SINGLE_CARRIER_TX,
-	MP_CARRIER_SUPPRISSION_TX,
-	MP_SINGLE_TONE_TX,
-	MP_PACKET_TX,
-	MP_PACKET_RX
-};
-
-#define MAX_RF_PATH_NUMS	RF_PATH_MAX
-
-extern u8 mpdatarate[NumRates];
-
-/* MP set force data rate base on the definition. */
-enum mpt_rate_index {
-	/* CCK rate. */
-	MPT_RATE_1M,	/* 0 */
-	MPT_RATE_2M,
-	MPT_RATE_55M,
-	MPT_RATE_11M,	/* 3 */
-
-	/* OFDM rate. */
-	MPT_RATE_6M,	/* 4 */
-	MPT_RATE_9M,
-	MPT_RATE_12M,
-	MPT_RATE_18M,
-	MPT_RATE_24M,
-	MPT_RATE_36M,
-	MPT_RATE_48M,
-	MPT_RATE_54M,	/* 11 */
-
-	/* HT rate. */
-	MPT_RATE_MCS0,	/* 12 */
-	MPT_RATE_MCS1,
-	MPT_RATE_MCS2,
-	MPT_RATE_MCS3,
-	MPT_RATE_MCS4,
-	MPT_RATE_MCS5,
-	MPT_RATE_MCS6,
-	MPT_RATE_MCS7,	/* 19 */
-	MPT_RATE_MCS8,
-	MPT_RATE_MCS9,
-	MPT_RATE_MCS10,
-	MPT_RATE_MCS11,
-	MPT_RATE_MCS12,
-	MPT_RATE_MCS13,
-	MPT_RATE_MCS14,
-	MPT_RATE_MCS15,	/* 27 */
-	MPT_RATE_LAST
-};
-
-#define MAX_TX_PWR_INDEX_N_MODE 64	/*  0x3F */
-
-enum power_mode {
-	POWER_LOW = 0,
-	POWER_NORMAL
-};
-
-#define RX_PKT_BROADCAST	1
-#define RX_PKT_DEST_ADDR	2
-#define RX_PKT_PHY_MATCH	3
-
-enum encry_ctrl_state {
-	HW_CONTROL,		/* hw encryption& decryption */
-	SW_CONTROL,		/* sw encryption& decryption */
-	HW_ENCRY_SW_DECRY,	/* hw encryption & sw decryption */
-	SW_ENCRY_HW_DECRY	/* sw encryption & hw decryption */
-};
-
-s32 init_mp_priv(struct adapter *padapter);
-void free_mp_priv(struct mp_priv *pmp_priv);
-s32 MPT_InitializeAdapter(struct adapter *padapter, u8 Channel);
-void MPT_DeInitAdapter(struct adapter *padapter);
-s32 mp_start_test(struct adapter *padapter);
-void mp_stop_test(struct adapter *padapter);
-
-u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask);
-void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val);
-
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
-u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
-void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
-u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
-void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val);
-
-void	SetChannel(struct adapter *pAdapter);
-void	SetBandwidth(struct adapter *pAdapter);
-void	SetTxPower(struct adapter *pAdapter);
-void	SetAntennaPathPower(struct adapter *pAdapter);
-void	SetDataRate(struct adapter *pAdapter);
-
-void	SetAntenna(struct adapter *pAdapter);
-
-s32	SetThermalMeter(struct adapter *pAdapter, u8 target_ther);
-void	GetThermalMeter(struct adapter *pAdapter, u8 *value);
-
-void	SetContinuousTx(struct adapter *pAdapter, u8 bStart);
-void	SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart);
-void	SetSingleToneTx(struct adapter *pAdapter, u8 bStart);
-void	SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart);
-void PhySetTxPowerLevel(struct adapter *pAdapter);
-
-void	fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc);
-void	SetPacketTx(struct adapter *padapter);
-void	SetPacketRx(struct adapter *pAdapter, u8 bStartRx);
-
-void	ResetPhyRxPktCount(struct adapter *pAdapter);
-u32	GetPhyRxPktReceived(struct adapter *pAdapter);
-u32	GetPhyRxPktCRC32Error(struct adapter *pAdapter);
-
-s32	SetPowerTracking(struct adapter *padapter, u8 enable);
-void	GetPowerTracking(struct adapter *padapter, u8 *enable);
-u32	mp_query_psd(struct adapter *pAdapter, u8 *data);
-void Hal_SetAntenna(struct adapter *pAdapter);
-void Hal_SetBandwidth(struct adapter *pAdapter);
-void Hal_SetTxPower(struct adapter *pAdapter);
-void Hal_SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart);
-void Hal_SetSingleToneTx(struct adapter *pAdapter, u8 bStart);
-void Hal_SetSingleCarrierTx (struct adapter *pAdapter, u8 bStart);
-void Hal_SetContinuousTx (struct adapter *pAdapter, u8 bStart);
-void Hal_SetBandwidth(struct adapter *pAdapter);
-void Hal_SetDataRate(struct adapter *pAdapter);
-void Hal_SetChannel(struct adapter *pAdapter);
-void Hal_SetAntennaPathPower(struct adapter *pAdapter);
-s32 Hal_SetThermalMeter(struct adapter *pAdapter, u8 target_ther);
-s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable);
-void Hal_GetPowerTracking(struct adapter *padapter, u8 *enable);
-void Hal_GetThermalMeter(struct adapter *pAdapter, u8 *value);
-void Hal_mpt_SwitchRfSetting(struct adapter *pAdapter);
-void Hal_MPT_CCKTxPowerAdjust(struct adapter *Adapter, bool bInCH14);
-void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven);
-void Hal_SetCCKTxPower(struct adapter *pAdapter, u8 *TxPower);
-void Hal_SetOFDMTxPower(struct adapter *pAdapter, u8 *TxPower);
-void Hal_TriggerRFThermalMeter(struct adapter *pAdapter);
-u8 Hal_ReadRFThermalMeter(struct adapter *pAdapter);
-void Hal_SetCCKContinuousTx(struct adapter *pAdapter, u8 bStart);
-void Hal_SetOFDMContinuousTx(struct adapter *pAdapter, u8 bStart);
-void Hal_ProSetCrystalCap (struct adapter *pAdapter , u32 CrystalCapVal);
-void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv);
-void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter , bool bMain);
-
-#endif /* _RTW_MP_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mp_ioctl.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mp_ioctl.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_mp_ioctl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_mp_ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,340 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _RTW_MP_IOCTL_H_
-#define _RTW_MP_IOCTL_H_
-
-#include <drv_types.h>
-#include <mp_custom_oid.h>
-#include <rtw_ioctl.h>
-#include <rtw_ioctl_rtl.h>
-#include <rtw_efuse.h>
-#include <rtw_mp.h>
-
-/*  */
-struct cfg_dbg_msg_struct {
-	u32 DebugLevel;
-	u32 DebugComponent_H32;
-	u32 DebugComponent_L32;
-};
-
-struct mp_rw_reg {
-	u32 offset;
-	u32 width;
-	u32 value;
-};
-
-struct efuse_access_struct {
-	u16	start_addr;
-	u16	cnts;
-	u8	data[0];
-};
-
-struct burst_rw_reg {
-	u32 offset;
-	u32 len;
-	u8 Data[256];
-};
-
-struct usb_vendor_req {
-	u8	bRequest;
-	u16	wValue;
-	u16	wIndex;
-	u16	wLength;
-	u8	u8Dir;/* 0:OUT, 1:IN */
-	u8	u8InData;
-};
-
-struct dr_variable_struct {
-	u8 offset;
-	u32 variable;
-};
-
-#define _irqlevel_changed_(a, b)
-
-/* rtl8188eu_oid_rtl_seg_81_80_00 */
-int rtl8188eu_oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv);
-
-/* rtl8188eu_oid_rtl_seg_81_80_20 */
-int rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *par_priv);
-int rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *par_priv);
-int rtl8188eu_oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *par_priv);
-int rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv);
-
-/* rtl8188eu_oid_rtl_seg_81_87 */
-int rtl8188eu_oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-
-/* rtl8188eu_oid_rtl_seg_81_85 */
-int rtl8188eu_oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
-
-/*  rtl8188eu_oid_rtl_seg_87_11_00 */
-int rtl8188eu_oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_burst_read_register_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_burst_write_register_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_wr_attrib_mem_hdl (struct oid_par_priv *poid_par_priv);
-int  rtl8188eu_oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv);
-/*  rtl8188eu_oid_rtl_seg_87_11_20 */
-int rtl8188eu_oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read_tssi_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_priv);
-/* rtl8188eu_oid_rtl_seg_87_11_50 */
-int rtl8188eu_oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv);
-/* rtl8188eu_oid_rtl_seg_87_11_F0 */
-int rtl8188eu_oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv *poid_par_priv);
-
-/* rtl8188eu_oid_rtl_seg_87_12_00 */
-int rtl8188eu_oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *par_priv);
-int rtl8188eu_oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv);
-int rtl8188eu_oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv);
-
-#ifdef _RTW_MP_IOCTL_C_
-
-static const struct oid_obj_priv rtl8188eu_oid_rtl_seg_81_80_00[] = {
-	{1, &oid_null_function},		/* 0x00	OID_RT_PRO_RESET_DUT */
-	{1, &rtl8188eu_oid_rt_pro_set_data_rate_hdl},	/* 0x01 */
-	{1, &rtl8188eu_oid_rt_pro_start_test_hdl},	/* 0x02 */
-	{1, &rtl8188eu_oid_rt_pro_stop_test_hdl},		/* 0x03 */
-	{1, &oid_null_function},	/* 0x04	OID_RT_PRO_SET_PREAMBLE */
-	{1, &oid_null_function},	/* 0x05	OID_RT_PRO_SET_SCRAMBLER */
-	{1, &oid_null_function},	/* 0x06	OID_RT_PRO_SET_FILTER_BB */
-	{1, &oid_null_function},/* 0x07	OID_RT_PRO_SET_MANUAL_DIVERSITY_BB */
-	{1, &rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl},	/* 0x08 */
-	{1, &oid_null_function},/* 0x09	OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL */
-	{1, &oid_null_function},/* 0x0A	OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL */
-	{1, &rtl8188eu_oid_rt_pro_set_continuous_tx_hdl},	/* 0x0B	OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL */
-	{1, &rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl},/* 0x0C	OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS */
-	{1, &oid_null_function},	/* 0x0D	OID_RT_PRO_SET_TX_ANTENNA_BB */
-	{1, &rtl8188eu_oid_rt_pro_set_antenna_bb_hdl},	/* 0x0E */
-	{1, &oid_null_function},		/* 0x0F	OID_RT_PRO_SET_CR_SCRAMBLER */
-	{1, &oid_null_function},		/* 0x10	OID_RT_PRO_SET_CR_NEW_FILTER */
-	{1, &rtl8188eu_oid_rt_pro_set_tx_power_control_hdl},/* 0x11 OID_RT_PRO_SET_TX_POWER_CONTROL */
-	{1, &oid_null_function},	/* 0x12	OID_RT_PRO_SET_CR_TX_CONFIG */
-	{1, &oid_null_function},	/* 0x13	OID_RT_PRO_GET_TX_POWER_CONTROL */
-	{1, &oid_null_function},	/* 0x14	OID_RT_PRO_GET_CR_SIGNAL_QUALITY */
-	{1, &oid_null_function},	/* 0x15	OID_RT_PRO_SET_CR_SETPOINT */
-	{1, &oid_null_function},	/* 0x16	OID_RT_PRO_SET_INTEGRATOR */
-	{1, &oid_null_function},	/* 0x17	OID_RT_PRO_SET_SIGNAL_QUALITY */
-	{1, &oid_null_function},	/* 0x18	OID_RT_PRO_GET_INTEGRATOR */
-	{1, &oid_null_function},	/* 0x19	OID_RT_PRO_GET_SIGNAL_QUALITY */
-	{1, &oid_null_function},	/* 0x1A	OID_RT_PRO_QUERY_EEPROM_TYPE */
-	{1, &oid_null_function},	/* 0x1B	OID_RT_PRO_WRITE_MAC_ADDRESS */
-	{1, &oid_null_function},	/* 0x1C	OID_RT_PRO_READ_MAC_ADDRESS */
-	{1, &oid_null_function},	/* 0x1D	OID_RT_PRO_WRITE_CIS_DATA */
-	{1, &oid_null_function},	/* 0x1E	OID_RT_PRO_READ_CIS_DATA */
-	{1, &oid_null_function}		/* 0x1F	OID_RT_PRO_WRITE_POWER_CONTROL */
-};
-
-static const struct oid_obj_priv rtl8188eu_oid_rtl_seg_81_80_20[] = {
-	{1, &oid_null_function},	/* 0x20	OID_RT_PRO_READ_POWER_CONTROL */
-	{1, &oid_null_function},	/* 0x21	OID_RT_PRO_WRITE_EEPROM */
-	{1, &oid_null_function},	/* 0x22	OID_RT_PRO_READ_EEPROM */
-	{1, &rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl},	/* 0x23 */
-	{1, &rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl},	/* 0x24 */
-	{1, &rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl},	/* 0x25 */
-	{1, &rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl},	/* 0x26 */
-	{1, &rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl},	/* 0x27 */
-	{1, &oid_null_function},	/* 0x28	OID_RT_PRO_QUERY_CURRENT_ADDRESS */
-	{1, &oid_null_function},	/* 0x29	OID_RT_PRO_QUERY_PERMANENT_ADDRESS */
-	{1, &oid_null_function},	/* 0x2A	OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS */
-	{1, &rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl},/* 0x2B	OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX */
-	{1, &oid_null_function},	/* 0x2C	OID_RT_PRO_RECEIVE_PACKET */
-	{1, &oid_null_function},	/* 0x2D	OID_RT_PRO_WRITE_EEPROM_BYTE */
-	{1, &oid_null_function},	/* 0x2E	OID_RT_PRO_READ_EEPROM_BYTE */
-	{1, &rtl8188eu_oid_rt_pro_set_modulation_hdl}		/* 0x2F */
-};
-
-static const struct oid_obj_priv rtl8188eu_oid_rtl_seg_81_80_40[] = {
-	{1, &oid_null_function},			/* 0x40 */
-	{1, &oid_null_function},			/* 0x41 */
-	{1, &oid_null_function},			/* 0x42 */
-	{1, &rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl},	/* 0x43 */
-	{1, &oid_null_function},			/* 0x44 */
-	{1, &oid_null_function}				/* 0x45 */
-};
-
-static const struct oid_obj_priv rtl8188eu_oid_rtl_seg_81_80_80[] = {
-	{1, &oid_null_function},		/* 0x80	OID_RT_DRIVER_OPTION */
-	{1, &oid_null_function},		/* 0x81	OID_RT_RF_OFF */
-	{1, &oid_null_function}			/* 0x82	OID_RT_AUTH_STATUS */
-};
-
-static const struct oid_obj_priv rtl8188eu_oid_rtl_seg_81_85[] = {
-	{1, &rtl8188eu_oid_rt_wireless_mode_hdl}		/* 0x00	OID_RT_WIRELESS_MODE */
-};
-
-#endif /* _RTL871X_MP_IOCTL_C_ */
-
-struct rwreg_param {
-	u32 offset;
-	u32 width;
-	u32 value;
-};
-
-struct bbreg_param {
-	u32 offset;
-	u32 phymask;
-	u32 value;
-};
-
-struct txpower_param {
-	u32 pwr_index;
-};
-
-struct datarate_param {
-	u32 rate_index;
-};
-
-struct rfintfs_parm {
-	u32 rfintfs;
-};
-
-struct mp_xmit_parm {
-	u8 enable;
-	u32 count;
-	u16 length;
-	u8 payload_type;
-	u8 da[ETH_ALEN];
-};
-
-struct mp_xmit_packet {
-	u32 len;
-	u32 mem[MAX_MP_XMITBUF_SZ >> 2];
-};
-
-struct psmode_param {
-	u32 ps_mode;
-	u32 smart_ps;
-};
-
-/* for OID_RT_PRO_READ16_EEPROM & OID_RT_PRO_WRITE16_EEPROM */
-struct eeprom_rw_param {
-	u32 offset;
-	u16 value;
-};
-
-struct mp_ioctl_handler {
-	u32 paramsize;
-	s32 (*handler)(struct oid_par_priv *poid_par_priv);
-	u32 oid;
-};
-
-struct mp_ioctl_param{
-	u32 subcode;
-	u32 len;
-	u8 data[0];
-};
-
-#define GEN_MP_IOCTL_SUBCODE(code) _MP_IOCTL_ ## code ## _CMD_
-
-enum RTL871X_MP_IOCTL_SUBCODE {
-	GEN_MP_IOCTL_SUBCODE(MP_START),			/*0*/
-	GEN_MP_IOCTL_SUBCODE(MP_STOP),
-	GEN_MP_IOCTL_SUBCODE(READ_REG),
-	GEN_MP_IOCTL_SUBCODE(WRITE_REG),
-	GEN_MP_IOCTL_SUBCODE(READ_BB_REG),
-	GEN_MP_IOCTL_SUBCODE(WRITE_BB_REG),		/*5*/
-	GEN_MP_IOCTL_SUBCODE(READ_RF_REG),
-	GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG),
-	GEN_MP_IOCTL_SUBCODE(SET_CHANNEL),
-	GEN_MP_IOCTL_SUBCODE(SET_TXPOWER),
-	GEN_MP_IOCTL_SUBCODE(SET_DATARATE),		/*10*/
-	GEN_MP_IOCTL_SUBCODE(SET_BANDWIDTH),
-	GEN_MP_IOCTL_SUBCODE(SET_ANTENNA),
-	GEN_MP_IOCTL_SUBCODE(CNTU_TX),
-	GEN_MP_IOCTL_SUBCODE(SC_TX),
-	GEN_MP_IOCTL_SUBCODE(CS_TX),			/*15*/
-	GEN_MP_IOCTL_SUBCODE(ST_TX),
-	GEN_MP_IOCTL_SUBCODE(IOCTL_XMIT_PACKET),
-	GEN_MP_IOCTL_SUBCODE(SET_RX_PKT_TYPE),
-	GEN_MP_IOCTL_SUBCODE(RESET_PHY_RX_PKT_CNT),
-	GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_RECV),	/*20*/
-	GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_ERROR),
-	GEN_MP_IOCTL_SUBCODE(READ16_EEPROM),
-	GEN_MP_IOCTL_SUBCODE(WRITE16_EEPROM),
-	GEN_MP_IOCTL_SUBCODE(EFUSE),
-	GEN_MP_IOCTL_SUBCODE(EFUSE_MAP),		/*25*/
-	GEN_MP_IOCTL_SUBCODE(GET_EFUSE_MAX_SIZE),
-	GEN_MP_IOCTL_SUBCODE(GET_EFUSE_CURRENT_SIZE),
-	GEN_MP_IOCTL_SUBCODE(GET_THERMAL_METER),
-	GEN_MP_IOCTL_SUBCODE(SET_PTM),
-	GEN_MP_IOCTL_SUBCODE(SET_POWER_DOWN),		/*30*/
-	GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO),
-	GEN_MP_IOCTL_SUBCODE(SET_DM_BT),		/*35*/
-	GEN_MP_IOCTL_SUBCODE(DEL_BA),			/*36*/
-	GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS),	/*37*/
-	MAX_MP_IOCTL_SUBCODE,
-};
-
-s32 rtl8188eu_mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv);
-
-#define GEN_HANDLER(sz, hdl, oid) {sz, hdl, oid},
-
-#define EXT_MP_IOCTL_HANDLER(sz, subcode, oid)			\
-	 {sz, rtl8188eu_mp_ioctl_##subcode##_hdl, oid},
-
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_p2p.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_p2p.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_p2p.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_p2p.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef __RTW_P2P_H_
-#define __RTW_P2P_H_
-
-#include <drv_types.h>
-
-u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo,
-				   u8 *pbuf, u8 *pssid, u8 ussidlen,
-				   u8 *pdev_raddr);
-u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo,
-			    u8 *pbuf, u8 status_code);
-u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo,
-			     u8 *pframe, uint len);
-u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo,
-			     u8 *pframe, uint len, struct sta_info *psta);
-u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo,
-			    u8 *pframe, uint len);
-u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo,
-			     u8 *pframe, uint len);
-u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,
-			    u8 *pframe, uint len);
-u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo,  u8 *pframe);
-u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo,
-				    u8 *pframe, uint len);
-u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo,
-				     u8 *pframe, uint len);
-u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo,
-					u8 *pframe, uint len);
-u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe,
-			    uint len);
-void p2p_protocol_wk_hdl(struct adapter *padapter, int intcmdtype);
-void process_p2p_ps_ie(struct adapter *padapter, u8 *ies, u32 ielength);
-void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state);
-u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue);
-void reset_global_wifidirect_info(struct adapter *padapter);
-int rtw_init_wifi_display_info(struct adapter *padapter);
-void rtw_init_wifidirect_timers(struct adapter *padapter);
-void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr,
-			       u8 *iface_addr);
-void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role);
-int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role);
-
-static inline void _rtw_p2p_set_state(struct wifidirect_info *wdinfo,
-				      enum P2P_STATE state)
-{
-	if (wdinfo->p2p_state != state)
-		wdinfo->p2p_state = state;
-}
-
-static inline void _rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo,
-					  enum P2P_STATE state)
-{
-	if (wdinfo->pre_p2p_state != state)
-		wdinfo->pre_p2p_state = state;
-}
-
-static inline void _rtw_p2p_set_role(struct wifidirect_info *wdinfo,
-				     enum P2P_ROLE role)
-{
-	if (wdinfo->role != role)
-		wdinfo->role = role;
-}
-
-static inline int _rtw_p2p_state(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->p2p_state;
-}
-
-static inline int _rtw_p2p_pre_state(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->pre_p2p_state;
-}
-
-static inline int _rtw_p2p_role(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->role;
-}
-
-static inline bool _rtw_p2p_chk_state(struct wifidirect_info *wdinfo,
-				      enum P2P_STATE state)
-{
-	return wdinfo->p2p_state == state;
-}
-
-static inline bool _rtw_p2p_chk_role(struct wifidirect_info *wdinfo,
-				     enum P2P_ROLE role)
-{
-	return wdinfo->role == role;
-}
-
-#define rtw_p2p_set_state(wdinfo, state) _rtw_p2p_set_state(wdinfo, state)
-#define rtw_p2p_set_pre_state(wdinfo, state)				\
-	 _rtw_p2p_set_pre_state(wdinfo, state)
-#define rtw_p2p_set_role(wdinfo, role) _rtw_p2p_set_role(wdinfo, role)
-
-#define rtw_p2p_state(wdinfo) _rtw_p2p_state(wdinfo)
-#define rtw_p2p_pre_state(wdinfo) _rtw_p2p_pre_state(wdinfo)
-#define rtw_p2p_role(wdinfo) _rtw_p2p_role(wdinfo)
-#define rtw_p2p_chk_state(wdinfo, state) _rtw_p2p_chk_state(wdinfo, state)
-#define rtw_p2p_chk_role(wdinfo, role) _rtw_p2p_chk_role(wdinfo, role)
-
-#define rtw_p2p_findphase_ex_set(wdinfo, value) \
-	((wdinfo)->find_phase_state_exchange_cnt = (value))
-
-/* is this find phase exchange for social channel scan? */
-#define rtw_p2p_findphase_ex_is_social(wdinfo)   \
-((wdinfo)->find_phase_state_exchange_cnt >= P2P_FINDPHASE_EX_SOCIAL_FIRST)
-
-/* should we need find phase exchange anymore? */
-#define rtw_p2p_findphase_ex_is_needed(wdinfo) \
-	((wdinfo)->find_phase_state_exchange_cnt < P2P_FINDPHASE_EX_MAX && \
-	(wdinfo)->find_phase_state_exchange_cnt != P2P_FINDPHASE_EX_NONE)
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_security.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_security.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_security.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_security.h	2014-09-28 17:29:07.000000000 -0400
@@ -378,6 +378,5 @@ void rtw_wep_encrypt(struct adapter *pad
 u32 rtw_aes_decrypt(struct adapter *padapter, u8  *precvframe);
 u32 rtw_tkip_decrypt(struct adapter *padapter, u8  *precvframe);
 void rtw_wep_decrypt(struct adapter *padapter, u8  *precvframe);
-void rtw_use_tkipkey_handler(void *FunctionContext);
 
 #endif	/* __RTL871X_SECURITY_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_sreset.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_sreset.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_sreset.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_sreset.h	2014-09-28 17:29:07.000000000 -0400
@@ -24,11 +24,7 @@
 #include <drv_types.h>
 
 struct sreset_priv {
-	struct mutex	silentreset_mutex;
-	u8	silent_reset_inprogress;
 	u8	Wifi_Error_Status;
-	unsigned long last_tx_time;
-	unsigned long last_tx_complete_time;
 };
 
 #include <rtl8188e_hal.h>
@@ -43,7 +39,6 @@ struct sreset_priv {
 #define		WIFI_IF_NOT_EXIST			BIT6
 
 void sreset_init_value(struct adapter *padapter);
-void sreset_reset_value(struct adapter *padapter);
 u8 sreset_get_wifi_status(struct adapter *padapter);
 void sreset_set_wifi_error_status(struct adapter *padapter, u32 status);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_version.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_version.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/rtw_version.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/rtw_version.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#define DRIVERVERSION	"v4.1.4_6773.20130222"
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/sta_info.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/sta_info.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/sta_info.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/sta_info.h	2014-09-28 17:29:07.000000000 -0400
@@ -182,21 +182,6 @@ struct sta_info {
 	unsigned int sleepq_ac_len;
 #endif	/*  CONFIG_88EU_AP_MODE */
 
-#ifdef CONFIG_88EU_P2P
-	/* p2p priv data */
-	u8 is_p2p_device;
-	u8 p2p_status_code;
-
-	/* p2p client info */
-	u8 dev_addr[ETH_ALEN];
-	u8 dev_cap;
-	u16 config_methods;
-	u8 primary_dev_type[8];
-	u8 num_of_secdev_type;
-	u8 secdev_types_list[32];/*  32/8 == 4; */
-	u16 dev_name_len;
-	u8 dev_name[32];
-#endif /* CONFIG_88EU_P2P */
 	u8 under_exist_checking;
 	u8 keep_alive_trycnt;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_ops.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_ops.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_ops.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_ops.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef __USB_OPS_H_
-#define __USB_OPS_H_
-
-#include <linux/version.h>
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <osdep_intf.h>
-
-#define REALTEK_USB_VENQT_READ		0xC0
-#define REALTEK_USB_VENQT_WRITE		0x40
-#define REALTEK_USB_VENQT_CMD_REQ	0x05
-#define REALTEK_USB_VENQT_CMD_IDX	0x00
-
-enum{
-	VENDOR_WRITE = 0x00,
-	VENDOR_READ = 0x01,
-};
-#define ALIGNMENT_UNIT			16
-#define MAX_VENDOR_REQ_CMD_SIZE	254	/* 8188cu SIE Support */
-#define MAX_USB_IO_CTL_SIZE	(MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT)
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
-#define rtw_usb_control_msg(dev, pipe, request, requesttype,		\
-			    value, index, data, size, timeout_ms)	\
-	usb_control_msg((dev), (pipe), (request), (requesttype), (value),\
-			(index), (data), (size), (timeout_ms))
-#define rtw_usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout_ms) \
-	usb_bulk_msg((usb_dev), (pipe), (data), (len),			\
-		     (actual_length), (timeout_ms))
-#else
-#define rtw_usb_control_msg(dev, pipe, request, requesttype,		\
-			    value, index, data, size, timeout_ms)	\
-	usb_control_msg((dev), (pipe), (request), (requesttype),	\
-			(value), (index), (data), (size),		\
-			((timeout_ms) == 0) ||				\
-			((timeout_ms)*HZ/1000 > 0) ?			\
-			((timeout_ms)*HZ/1000) : 1)
-#define rtw_usb_bulk_msg(usb_dev, pipe, data, len,			\
-			 actual_length, timeout_ms) \
-	usb_bulk_msg((usb_dev), (pipe), (data), (len), (actual_length), \
-		     ((timeout_ms) == 0) || ((timeout_ms)*HZ/1000 > 0) ?\
-		     ((timeout_ms)*HZ/1000) : 1)
-#endif
-#include <usb_ops_linux.h>
-
-void rtl8188eu_set_hw_type(struct adapter *padapter);
-void rtl8188eu_set_intf_ops(struct _io_ops *pops);
-#define usb_set_intf_ops rtl8188eu_set_intf_ops
-
-/*
- * Increase and check if the continual_urb_error of this @param dvobjprivei
- * is larger than MAX_CONTINUAL_URB_ERR
- * @return true:
- * @return false:
- */
-static inline int rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj)
-{
-	int ret = false;
-	int value;
-	value = atomic_inc_return(&dvobj->continual_urb_error);
-	if (value > MAX_CONTINUAL_URB_ERR) {
-		DBG_88E("[dvobj:%p][ERROR] continual_urb_error:%d > %d\n",
-			dvobj, value, MAX_CONTINUAL_URB_ERR);
-		ret = true;
-	}
-	return ret;
-}
-
-/*
-* Set the continual_urb_error of this @param dvobjprive to 0
-*/
-static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj)
-{
-	atomic_set(&dvobj->continual_urb_error, 0);
-}
-
-#define USB_HIGH_SPEED_BULK_SIZE	512
-#define USB_FULL_SPEED_BULK_SIZE	64
-
-static inline u8 rtw_usb_bulk_size_boundary(struct adapter *padapter,
-					    int buf_len)
-{
-	u8 rst = true;
-	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
-
-	if (pdvobjpriv->ishighspeed)
-		rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ?
-		      true : false;
-	else
-		rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ?
-		      true : false;
-	return rst;
-}
-
-#endif /* __USB_OPS_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_ops_linux.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_ops_linux.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_ops_linux.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_ops_linux.h	2014-09-28 17:29:07.000000000 -0400
@@ -29,6 +29,16 @@
 
 #define RTW_USB_BULKOUT_TIME	5000/* ms */
 
+#define REALTEK_USB_VENQT_READ		0xC0
+#define REALTEK_USB_VENQT_WRITE		0x40
+
+#define ALIGNMENT_UNIT			16
+#define MAX_VENDOR_REQ_CMD_SIZE	254	/* 8188cu SIE Support */
+#define MAX_USB_IO_CTL_SIZE	(MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT)
+
+#define USB_HIGH_SPEED_BULK_SIZE	512
+#define USB_FULL_SPEED_BULK_SIZE	64
+
 #define _usbctrl_vendorreq_async_callback(urb, regs)	\
 	_usbctrl_vendorreq_async_callback(urb)
 #define usb_bulkout_zero_complete(purb, regs)		\
@@ -42,14 +52,36 @@
 #define usb_read_interrupt_complete(purb, regs)		\
 	usb_read_interrupt_complete(purb)
 
+static inline u8 rtw_usb_bulk_size_boundary(struct adapter *padapter,
+					    int buf_len)
+{
+	u8 rst = true;
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+
+	if (pdvobjpriv->ishighspeed)
+		rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ?
+		      true : false;
+	else
+		rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ?
+		      true : false;
+	return rst;
+}
+
 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr);
 
-void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem);
-void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem);
+u8 usb_read8(struct adapter *adapter, u32 addr);
+u16 usb_read16(struct adapter *adapter, u32 addr);
+u32 usb_read32(struct adapter *adapter, u32 addr);
 
-void usb_read_port_cancel(struct intf_hdl *pintfhdl);
+u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void usb_read_port_cancel(struct adapter *adapter);
 
-u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem);
-void usb_write_port_cancel(struct intf_hdl *pintfhdl);
+int usb_write8(struct adapter *adapter, u32 addr, u8 val);
+int usb_write16(struct adapter *adapter, u32 addr, u16 val);
+int usb_write32(struct adapter *adapter, u32 addr, u32 val);
+int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata);
+
+u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void usb_write_port_cancel(struct adapter *adapter);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_osintf.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_osintf.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_osintf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_osintf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef __USB_OSINTF_H
-#define __USB_OSINTF_H
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <usb_vendor_req.h>
-
-extern char *rtw_initmac;
-extern int rtw_mc2u_disable;
-
-#define USBD_HALTED(Status) ((u32)(Status) >> 30 == 3)
-
-u8 usbvendorrequest(struct dvobj_priv *pdvobjpriv, enum bt_usb_request brequest,
-		    enum rt_usb_wvalue wvalue, u8 windex, void *data,
-		    u8 datalen, u8 isdirectionin);
-int pm_netdev_open(struct net_device *pnetdev, u8 bnormal);
-void netdev_br_init(struct net_device *netdev);
-void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb);
-void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
-		     unsigned char *ipAddr);
-void nat25_db_expire(struct adapter *priv);
-int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method);
-
-int rtw_resume_process(struct adapter *padapter);
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_vendor_req.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_vendor_req.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/usb_vendor_req.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/usb_vendor_req.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
-#ifndef _USB_VENDOR_REQUEST_H_
-#define _USB_VENDOR_REQUEST_H_
-
-/* 4	Set/Get Register related wIndex/Data */
-#define	RT_USB_RESET_MASK_OFF		0
-#define	RT_USB_RESET_MASK_ON		1
-#define	RT_USB_SLEEP_MASK_OFF		0
-#define	RT_USB_SLEEP_MASK_ON		1
-#define	RT_USB_LDO_ON				1
-#define	RT_USB_LDO_OFF				0
-
-/* 4	Set/Get SYSCLK related	wValue or Data */
-#define	RT_USB_SYSCLK_32KHZ		0
-#define	RT_USB_SYSCLK_40MHZ		1
-#define	RT_USB_SYSCLK_60MHZ		2
-
-
-enum bt_usb_request {
-	RT_USB_SET_REGISTER		= 1,
-	RT_USB_SET_SYSCLK		= 2,
-	RT_USB_GET_SYSCLK		= 3,
-	RT_USB_GET_REGISTER		= 4
-};
-
-enum rt_usb_wvalue {
-	RT_USB_RESET_MASK	=	1,
-	RT_USB_SLEEP_MASK	=	2,
-	RT_USB_USB_HRCPWM	=	3,
-	RT_USB_LDO			=	4,
-	RT_USB_BOOT_TYPE	=	5
-};
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/wlan_bssdef.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/wlan_bssdef.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/include/wlan_bssdef.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/include/wlan_bssdef.h	2014-09-28 17:29:07.000000000 -0400
@@ -340,8 +340,4 @@ struct ndis_802_11_cap {
 	struct ndis_802_11_auth_encrypt AuthenticationEncryptionSupported[1];
 };
 
-u8 key_2char2num(u8 hch, u8 lch);
-u8 key_char2num(u8 ch);
-u8 str_2char2num(u8 hch, u8 lch);
-
 #endif /* ifndef WLAN_BSSDEF_H_ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -17,12 +17,4 @@ config 88EU_AP_MODE
 	will never be used as an AP, or the target system has limited memory,
 	"Y" should be selected.
 
-config 88EU_P2P
-	bool "Realtek RTL8188EU Peer-to-peer mode"
-	default y
-	---help---
-	This option enables peer-to-peer mode for the r8188eu driver. Unless you
-	know that peer-to-peer (P2P) mode will never be used, or the target system has
-	limited memory, "Y" should be selected.
-
 endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/Makefile linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/Makefile
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/Makefile	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/Makefile	2014-09-28 17:29:07.000000000 -0400
@@ -1,20 +1,15 @@
 r8188eu-y :=				\
 		core/rtw_ap.o		\
-		core/rtw_br_ext.o	\
 		core/rtw_cmd.o		\
 		core/rtw_debug.o	\
 		core/rtw_efuse.o	\
 		core/rtw_ieee80211.o	\
-		core/rtw_io.o		\
 		core/rtw_ioctl_set.o	\
 		core/rtw_iol.o		\
 		core/rtw_led.o		\
 		core/rtw_mlme.o		\
 		core/rtw_mlme_ext.o	\
-		core/rtw_mp.o		\
-		core/rtw_mp_ioctl.o	\
 		core/rtw_pwrctrl.o	\
-		core/rtw_p2p.o		\
 		core/rtw_recv.o		\
 		core/rtw_rf.o		\
 		core/rtw_security.o	\
@@ -25,7 +20,6 @@ r8188eu-y :=				\
 		hal/HalHWImg8188E_MAC.o	\
 		hal/HalHWImg8188E_BB.o	\
 		hal/HalHWImg8188E_RF.o	\
-		hal/HalPhyRf.o		\
 		hal/HalPhyRf_8188e.o	\
 		hal/HalPwrSeqCmd.o	\
 		hal/Hal8188EPwrSeq.o	\
@@ -40,17 +34,14 @@ r8188eu-y :=				\
 		hal/rtl8188e_cmd.o	\
 		hal/rtl8188e_dm.o	\
 		hal/rtl8188e_hal_init.o	\
-		hal/rtl8188e_mp.o	\
 		hal/rtl8188e_phycfg.o	\
 		hal/rtl8188e_rf6052.o	\
 		hal/rtl8188e_rxdesc.o	\
-		hal/rtl8188e_sreset.o	\
 		hal/rtl8188e_xmit.o	\
 		hal/rtl8188eu_led.o	\
 		hal/rtl8188eu_recv.o	\
 		hal/rtl8188eu_xmit.o	\
 		hal/usb_halinit.o	\
-		hal/usb_ops_linux.o	\
 		os_dep/ioctl_linux.o	\
 		os_dep/mlme_linux.o	\
 		os_dep/os_intfs.o	\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -28,14 +28,11 @@
 #include <rtw_mlme_ext.h>
 #include <rtw_ioctl.h>
 #include <rtw_ioctl_set.h>
-#include <rtw_mp_ioctl.h>
-#include <usb_ops.h>
-#include <rtw_version.h>
 #include <rtl8188e_hal.h>
 
-#include <rtw_mp.h>
 #include <rtw_iol.h>
 #include <linux/vmalloc.h>
+#include "osdep_intf.h"
 
 #define RTL_IOCTL_WPA_SUPPLICANT	(SIOCIWFIRSTPRIV + 30)
 
@@ -56,48 +53,6 @@
 #define WEXT_CSCAN_HOME_DWELL_SECTION	'H'
 #define WEXT_CSCAN_TYPE_SECTION		'T'
 
-static struct mp_ioctl_handler mp_ioctl_hdl[] = {
-/*0*/	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_start_test_hdl, OID_RT_PRO_START_TEST)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_stop_test_hdl, OID_RT_PRO_STOP_TEST)
-
-	GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_read_register_hdl, OID_RT_PRO_READ_REGISTER)
-	GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_write_register_hdl, OID_RT_PRO_WRITE_REGISTER)
-	GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_read_bb_reg_hdl, OID_RT_PRO_READ_BB_REG)
-/*5*/	GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_write_bb_reg_hdl, OID_RT_PRO_WRITE_BB_REG)
-	GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_read_rf_reg_hdl, OID_RT_PRO_RF_READ_REGISTRY)
-	GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_write_rf_reg_hdl, OID_RT_PRO_RF_WRITE_REGISTRY)
-
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl, OID_RT_PRO_SET_CHANNEL_DIRECT_CALL)
-	GEN_HANDLER(sizeof(struct txpower_param), rtl8188eu_oid_rt_pro_set_tx_power_control_hdl, OID_RT_PRO_SET_TX_POWER_CONTROL)
-/*10*/	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_data_rate_hdl, OID_RT_PRO_SET_DATA_RATE)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_bandwidth_hdl, OID_RT_SET_BANDWIDTH)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_antenna_bb_hdl, OID_RT_PRO_SET_ANTENNA_BB)
-
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_continuous_tx_hdl, OID_RT_PRO_SET_CONTINUOUS_TX)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl, OID_RT_PRO_SET_SINGLE_CARRIER_TX)
-/*15*/	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl, OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl, OID_RT_PRO_SET_SINGLE_TONE_TX)
-
-	EXT_MP_IOCTL_HANDLER(0, xmit_packet, 0)
-
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_rx_packet_type_hdl, OID_RT_SET_RX_PACKET_TYPE)
-	GEN_HANDLER(0, rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl, OID_RT_RESET_PHY_RX_PACKET_COUNT)
-/*20*/	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl, OID_RT_GET_PHY_RX_PACKET_RECEIVED)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl, OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR)
-
-	GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
-	GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
-	GEN_HANDLER(sizeof(struct efuse_access_struct), rtl8188eu_oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE)
-/*25*/	GEN_HANDLER(0, rtl8188eu_oid_rt_pro_efuse_map_hdl, OID_RT_PRO_EFUSE_MAP)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_max_size_hdl, OID_RT_GET_EFUSE_MAX_SIZE)
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_current_size_hdl, OID_RT_GET_EFUSE_CURRENT_SIZE)
-
-	GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_thermal_meter_hdl, OID_RT_PRO_GET_THERMAL_METER)
-	GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_pro_set_power_tracking_hdl, OID_RT_PRO_SET_POWER_TRACKING)
-/*30*/	GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_set_power_down_hdl, OID_RT_SET_POWER_DOWN)
-/*31*/	GEN_HANDLER(0, rtl8188eu_oid_rt_pro_trigger_gpio_hdl, 0)
-};
-
 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
 	6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
 	48000000, 54000000};
@@ -107,49 +62,11 @@ static const char * const iw_operation_m
 	"Secondary", "Monitor"
 };
 
-static int hex2num_i(char c)
-{
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return c - 'a' + 10;
-	if (c >= 'A' && c <= 'F')
-		return c - 'A' + 10;
-	return -1;
-}
-
-/**
- * hwaddr_aton - Convert ASCII string to MAC address
- * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
- * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
- * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
- */
-static int hwaddr_aton_i(const char *txt, u8 *addr)
-{
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		int a, b;
-
-		a = hex2num_i(*txt++);
-		if (a < 0)
-			return -1;
-		b = hex2num_i(*txt++);
-		if (b < 0)
-			return -1;
-		*addr++ = (a << 4) | b;
-		if (i < 5 && *txt++ != ':')
-			return -1;
-	}
-
-	return 0;
-}
-
 void indicate_wx_scan_complete_event(struct adapter *padapter)
 {
 	union iwreq_data wrqu;
 
-	_rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
+	memset(&wrqu, 0, sizeof(union iwreq_data));
 	wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
 }
 
@@ -158,7 +75,7 @@ void rtw_indicate_wx_assoc_event(struct
 	union iwreq_data wrqu;
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-	_rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
+	memset(&wrqu, 0, sizeof(union iwreq_data));
 
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
@@ -172,10 +89,10 @@ void rtw_indicate_wx_disassoc_event(stru
 {
 	union iwreq_data wrqu;
 
-	_rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
+	memset(&wrqu, 0, sizeof(union iwreq_data));
 
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	_rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+	memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
 
 	DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
 	wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
@@ -198,35 +115,6 @@ static char *translate_scan(struct adapt
 	u8 bw_40MHz = 0, short_GI = 0;
 	u16 mcs_rate = 0;
 	u8 ss, sq;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		u32	blnGotP2PIE = false;
-
-		/*	User is doing the P2P device discovery */
-		/*	The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
-		/*	If not, the driver should ignore this AP and go to the next AP. */
-
-		/*	Verifying the SSID */
-		if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
-			u32	p2pielen = 0;
-
-			if (pnetwork->network.Reserved[0] == 2) {/*  Probe Request */
-				/*	Verifying the P2P IE */
-				if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen))
-					blnGotP2PIE = true;
-			} else {/*  Beacon or Probe Respones */
-				/*	Verifying the P2P IE */
-				if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))
-					blnGotP2PIE = true;
-			}
-		}
-
-		if (!blnGotP2PIE)
-			return start;
-	}
-#endif /* CONFIG_88EU_P2P */
 
 	/*  AP MAC address  */
 	iwe.cmd = SIOCGIWAP;
@@ -358,33 +246,33 @@ static char *translate_scan(struct adapt
 
 		if (wpa_len > 0) {
 			p = buf;
-			_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
+			memset(buf, 0, MAX_WPA_IE_LEN);
 			p += sprintf(p, "wpa_ie=");
 			for (i = 0; i < wpa_len; i++)
 				p += sprintf(p, "%02x", wpa_ie[i]);
 
-			_rtw_memset(&iwe, 0, sizeof(iwe));
+			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVCUSTOM;
 			iwe.u.data.length = strlen(buf);
 			start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 
-			_rtw_memset(&iwe, 0, sizeof(iwe));
+			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVGENIE;
 			iwe.u.data.length = wpa_len;
 			start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
 		}
 		if (rsn_len > 0) {
 			p = buf;
-			_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
+			memset(buf, 0, MAX_WPA_IE_LEN);
 			p += sprintf(p, "rsn_ie=");
 			for (i = 0; i < rsn_len; i++)
 				p += sprintf(p, "%02x", rsn_ie[i]);
-			_rtw_memset(&iwe, 0, sizeof(iwe));
+			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVCUSTOM;
 			iwe.u.data.length = strlen(buf);
 			start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 
-			_rtw_memset(&iwe, 0, sizeof(iwe));
+			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVGENIE;
 			iwe.u.data.length = rsn_len;
 			start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
@@ -469,9 +357,6 @@ static int wpa_set_encryption(struct net
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_88EU_P2P */
 
 	param->u.crypt.err = 0;
 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
@@ -520,7 +405,7 @@ static int wpa_set_encryption(struct net
 				RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
 				goto exit;
 			}
-			_rtw_memset(pwep, 0, wep_total_len);
+			memset(pwep, 0, wep_total_len);
 			pwep->KeyLength = wep_key_len;
 			pwep->Length = wep_total_len;
 			if (wep_key_len == 13) {
@@ -589,10 +474,6 @@ static int wpa_set_encryption(struct net
 					padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
 
 					rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
-#ifdef CONFIG_88EU_P2P
-					if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
-#endif /* CONFIG_88EU_P2P */
 				}
 			}
 			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
@@ -621,9 +502,6 @@ static int rtw_set_wpa_ie(struct adapter
 	u8 *buf = NULL;
 	int group_cipher = 0, pairwise_cipher = 0;
 	int ret = 0;
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_88EU_P2P */
 
 	if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
 		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
@@ -634,7 +512,7 @@ static int rtw_set_wpa_ie(struct adapter
 	}
 
 	if (ielen) {
-		buf = rtw_zmalloc(ielen);
+		buf = kzalloc(ielen, GFP_KERNEL);
 		if (buf == NULL) {
 			ret =  -ENOMEM;
 			goto exit;
@@ -729,10 +607,6 @@ static int rtw_set_wpa_ie(struct adapter
 					memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
 
 					set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
-#ifdef CONFIG_88EU_P2P
-					if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
-#endif /* CONFIG_88EU_P2P */
 					cnt += buf[cnt+1]+2;
 					break;
 				} else {
@@ -955,14 +829,14 @@ static int rtw_wx_set_pmkid(struct net_d
 		for (j = 0; j < NUM_PMKID_CACHE; j++) {
 			if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
 				/*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
-				_rtw_memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
+				memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
 				psecuritypriv->PMKIDList[j].bUsed = false;
 				break;
 			}
 	       }
 	} else if (pPMK->cmd == IW_PMKSA_FLUSH) {
 		DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
-		_rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+		memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
 		psecuritypriv->PMKIDIndex = 0;
 		ret = true;
 	}
@@ -993,7 +867,7 @@ static int rtw_wx_get_range(struct net_d
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
 
 	wrqu->data.length = sizeof(*range);
-	_rtw_memset(range, 0, sizeof(*range));
+	memset(range, 0, sizeof(*range));
 
 	/* Let's try to keep this struct in the same order as in
 	 * linux/include/wireless.h
@@ -1113,10 +987,7 @@ static int rtw_wx_set_wap(struct net_dev
 	phead = get_list_head(queue);
 	pmlmepriv->pscanned = phead->next;
 
-	while (1) {
-		if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == true)
-			break;
-
+	while (phead != pmlmepriv->pscanned) {
 		pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 
 		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
@@ -1159,7 +1030,7 @@ static int rtw_wx_get_wap(struct net_dev
 
 	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
 
-	_rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+	memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
 
@@ -1168,7 +1039,7 @@ static int rtw_wx_get_wap(struct net_dev
 	    ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
 		memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
 	else
-		_rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
 	return 0;
 }
 
@@ -1213,9 +1084,6 @@ static int rtw_wx_set_scan(struct net_de
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
-#ifdef CONFIG_88EU_P2P
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-#endif /* CONFIG_88EU_P2P */
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
 
 	if (padapter->registrypriv.mp_mode == 1) {
@@ -1262,16 +1130,7 @@ static int rtw_wx_set_scan(struct net_de
 /*	the pmlmepriv->scan_interval is always equal to 3. */
 /*	So, the wpa_supplicant won't find out the WPS SoftAP. */
 
-#ifdef CONFIG_88EU_P2P
-	if (pwdinfo->p2p_state != P2P_STATE_NONE) {
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
-		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
-		rtw_free_network_queue(padapter, true);
-	}
-#endif /* CONFIG_88EU_P2P */
-
-	_rtw_memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
+	memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
 
 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
 		struct iw_scan_req *req = (struct iw_scan_req *)extra;
@@ -1365,9 +1224,6 @@ static int rtw_wx_get_scan(struct net_de
 	u32 cnt = 0;
 	u32 wait_for_surveydone;
 	int wait_status;
-#ifdef CONFIG_88EU_P2P
-	struct	wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_88EU_P2P */
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
 	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
 
@@ -1376,19 +1232,7 @@ static int rtw_wx_get_scan(struct net_de
 		goto exit;
 	}
 
-#ifdef CONFIG_88EU_P2P
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		/*	P2P is enabled */
-		wait_for_surveydone = 200;
-	} else {
-		/*	P2P is disabled */
-		wait_for_surveydone = 100;
-	}
-#else
-	{
-		wait_for_surveydone = 100;
-	}
-#endif /* CONFIG_88EU_P2P */
+	wait_for_surveydone = 100;
 
 	wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
 
@@ -1404,10 +1248,7 @@ static int rtw_wx_get_scan(struct net_de
 	phead = get_list_head(queue);
 	plist = phead->next;
 
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist))
-			break;
-
+	while (phead != plist) {
 		if ((stop - ev) < SCAN_ITEM_SIZE) {
 			ret = -E2BIG;
 			break;
@@ -1482,7 +1323,7 @@ static int rtw_wx_set_essid(struct net_d
 		if (wrqu->essid.length != 33)
 			DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
 
-		_rtw_memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
+		memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
 		ndis_ssid.SsidLength = len;
 		memcpy(ndis_ssid.Ssid, extra, len);
 		src_ssid = ndis_ssid.Ssid;
@@ -1492,14 +1333,7 @@ static int rtw_wx_set_essid(struct net_d
 	       phead = get_list_head(queue);
 	      pmlmepriv->pscanned = phead->next;
 
-		while (1) {
-			if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
-				RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
-					 ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
-
-				break;
-			}
-
+		while (phead != pmlmepriv->pscanned) {
 			pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
 
 			pmlmepriv->pscanned = pmlmepriv->pscanned->next;
@@ -1584,7 +1418,6 @@ static int rtw_wx_set_rate(struct net_de
 			      union iwreq_data *wrqu, char *extra)
 {
 	int i, ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	u8 datarates[NumRates];
 	u32	target_rate = wrqu->bitrate.value;
 	u32	fixed = wrqu->bitrate.fixed;
@@ -1657,12 +1490,6 @@ set_rate:
 		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
 	}
 
-	if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
-		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
-		ret = -1;
-	}
-
-
 	return ret;
 }
 
@@ -1787,7 +1614,7 @@ static int rtw_wx_set_enc(struct net_dev
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 	DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
 
-	_rtw_memset(&wep, 0, sizeof(struct ndis_802_11_wep));
+	memset(&wep, 0, sizeof(struct ndis_802_11_wep));
 
 	key = erq->flags & IW_ENCODE_INDEX;
 
@@ -2076,10 +1903,10 @@ static int rtw_wx_set_enc_ext(struct net
 	if (param == NULL)
 		return -1;
 
-	_rtw_memset(param, 0, param_len);
+	memset(param, 0, param_len);
 
 	param->cmd = IEEE_CMD_SET_ENCRYPTION;
-	_rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
+	memset(param->sta_addr, 0xff, ETH_ALEN);
 
 	switch (pext->alg) {
 	case IW_ENCODE_ALG_NONE:
@@ -2144,2487 +1971,12 @@ static int rtw_wx_get_nick(struct net_de
 	return 0;
 }
 
-static int rtw_wx_read32(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter;
-	struct iw_point *p;
-	u16 len;
-	u32 addr;
-	u32 data32;
-	u32 bytes;
-	u8 *ptmp;
-	int rv;
-	int ret = 0;
-
-	padapter = (struct adapter *)rtw_netdev_priv(dev);
-	p = &wrqu->data;
-	len = p->length;
-	ptmp = (u8 *)rtw_malloc(len);
-	if (NULL == ptmp)
-		return -ENOMEM;
-
-	if (copy_from_user(ptmp, p->pointer, len)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	bytes = 0;
-	addr = 0;
-	rv = sscanf(ptmp, "%d,%x", &bytes, &addr);
-	if (rv != 2) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	switch (bytes) {
-	case 1:
-		data32 = rtw_read8(padapter, addr);
-		sprintf(extra, "0x%02X", data32);
-		break;
-	case 2:
-		data32 = rtw_read16(padapter, addr);
-		sprintf(extra, "0x%04X", data32);
-		break;
-	case 4:
-		data32 = rtw_read32(padapter, addr);
-		sprintf(extra, "0x%08X", data32);
-		break;
-	default:
-		DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
-		ret = -EINVAL;
-		goto exit;
-	}
-	DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
-
-exit:
-	kfree(ptmp);
-	return ret;
-}
-
-static int rtw_wx_write32(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	int rv;
-
-	u32 addr;
-	u32 data32;
-	u32 bytes;
-
-	bytes = 0;
-	addr = 0;
-	data32 = 0;
-	rv = sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
-	if (rv != 3)
-		return -EINVAL;
-
-	switch (bytes) {
-	case 1:
-		rtw_write8(padapter, addr, (u8)data32);
-		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
-		break;
-	case 2:
-		rtw_write16(padapter, addr, (u16)data32);
-		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
-		break;
-	case 4:
-		rtw_write32(padapter, addr, data32);
-		DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
-		break;
-	default:
-		DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int rtw_wx_read_rf(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u32 path, addr, data32;
-
-	path = *(u32 *)extra;
-	addr = *((u32 *)extra + 1);
-	data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
-	/*
-	 * IMPORTANT!!
-	 * Only when wireless private ioctl is at odd order,
-	 * "extra" would be copied to user space.
-	 */
-	sprintf(extra, "0x%05x", data32);
-
-	return 0;
-}
-
-static int rtw_wx_write_rf(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u32 path, addr, data32;
-
-	path = *(u32 *)extra;
-	addr = *((u32 *)extra + 1);
-	data32 = *((u32 *)extra + 2);
-	rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
-
-	return 0;
-}
-
-static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
-		 union iwreq_data *wrqu, char *b)
-{
-	return -1;
-}
-
 static int dummy(struct net_device *dev, struct iw_request_info *a,
 		 union iwreq_data *wrqu, char *b)
 {
 	return -1;
 }
 
-static int rtw_wx_set_channel_plan(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	u8 channel_plan_req = (u8) (*((int *)wrqu));
-
-	if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1))
-		DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
-	else
-		return -EPERM;
-
-	return 0;
-}
-
-static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
-		struct iw_request_info *a,
-		union iwreq_data *wrqu, char *b)
-{
-	return 0;
-}
-
-static int rtw_wx_get_sensitivity(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *buf)
-{
-	return 0;
-}
-
-static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	return 0;
-}
-
-/*
- *	For all data larger than 16 octets, we need to use a
- *	pointer to memory allocated in user space.
- */
-static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
-						union iwreq_data *wrqu, char *extra)
-{
-	return 0;
-}
-
-static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
-{
-	struct mp_rw_reg *RegRWStruct;
-	struct rf_reg_param *prfreg;
-	u8 path;
-	u8 offset;
-	u32 value;
-
-	DBG_88E("%s\n", __func__);
-
-	switch (id) {
-	case GEN_MP_IOCTL_SUBCODE(MP_START):
-		DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
-		break;
-	case GEN_MP_IOCTL_SUBCODE(READ_REG):
-		RegRWStruct = (struct mp_rw_reg *)pdata;
-		switch (RegRWStruct->width) {
-		case 1:
-			RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
-			break;
-		case 2:
-			RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
-			break;
-		case 4:
-			RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
-			break;
-		default:
-			break;
-		}
-
-		break;
-	case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
-		RegRWStruct = (struct mp_rw_reg *)pdata;
-		switch (RegRWStruct->width) {
-		case 1:
-			rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
-			break;
-		case 2:
-			rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
-			break;
-		case 4:
-			rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
-			break;
-		default:
-			break;
-		}
-
-		break;
-	case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
-
-		prfreg = (struct rf_reg_param *)pdata;
-
-		path = (u8)prfreg->path;
-		offset = (u8)prfreg->offset;
-
-		value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
-
-		prfreg->value = value;
-
-		break;
-	case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
-
-		prfreg = (struct rf_reg_param *)pdata;
-
-		path = (u8)prfreg->path;
-		offset = (u8)prfreg->offset;
-		value = prfreg->value;
-
-		rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
-
-		break;
-	case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
-		DBG_88E("==> trigger gpio 0\n");
-		rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
-		break;
-	case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
-		*pdata = rtw_hal_sreset_get_wifi_status(padapter);
-		break;
-	default:
-		break;
-	}
-}
-
-static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
-						union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	u32 BytesRead, BytesWritten, BytesNeeded;
-	struct oid_par_priv	oid_par;
-	struct mp_ioctl_handler	*phandler;
-	struct mp_ioctl_param	*poidparam;
-	uint status = 0;
-	u16 len;
-	u8 *pparmbuf = NULL, bset;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct iw_point *p = &wrqu->data;
-
-	if ((!p->length) || (!p->pointer)) {
-		ret = -EINVAL;
-		goto _rtw_mp_ioctl_hdl_exit;
-	}
-	pparmbuf = NULL;
-	bset = (u8)(p->flags & 0xFFFF);
-	len = p->length;
-	pparmbuf = (u8 *)rtw_malloc(len);
-	if (pparmbuf == NULL) {
-		ret = -ENOMEM;
-		goto _rtw_mp_ioctl_hdl_exit;
-	}
-
-	if (copy_from_user(pparmbuf, p->pointer, len)) {
-		ret = -EFAULT;
-		goto _rtw_mp_ioctl_hdl_exit;
-	}
-
-	poidparam = (struct mp_ioctl_param *)pparmbuf;
-	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
-		 ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
-		  poidparam->subcode, poidparam->len, len));
-
-	if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) {
-		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
-		ret = -EINVAL;
-		goto _rtw_mp_ioctl_hdl_exit;
-	}
-
-	if (padapter->registrypriv.mp_mode == 1) {
-		phandler = mp_ioctl_hdl + poidparam->subcode;
-
-		if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
-			RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
-				 ("no matching drvext param size %d vs %d\r\n",
-				  poidparam->len, phandler->paramsize));
-			ret = -EINVAL;
-			goto _rtw_mp_ioctl_hdl_exit;
-		}
-
-		if (phandler->handler) {
-			oid_par.adapter_context = padapter;
-			oid_par.oid = phandler->oid;
-			oid_par.information_buf = poidparam->data;
-			oid_par.information_buf_len = poidparam->len;
-			oid_par.dbg = 0;
-
-			BytesWritten = 0;
-			BytesNeeded = 0;
-
-			if (bset) {
-				oid_par.bytes_rw = &BytesRead;
-				oid_par.bytes_needed = &BytesNeeded;
-				oid_par.type_of_oid = SET_OID;
-			} else {
-				oid_par.bytes_rw = &BytesWritten;
-				oid_par.bytes_needed = &BytesNeeded;
-				oid_par.type_of_oid = QUERY_OID;
-			}
-
-			status = phandler->handler(&oid_par);
-		} else {
-			DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n",
-				poidparam->subcode, phandler->oid, phandler->handler);
-			ret = -EFAULT;
-			goto _rtw_mp_ioctl_hdl_exit;
-		}
-	} else {
-		rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
-	}
-
-	if (bset == 0x00) {/* query info */
-		if (copy_to_user(p->pointer, pparmbuf, len))
-			ret = -EFAULT;
-	}
-
-	if (status) {
-		ret = -EFAULT;
-		goto _rtw_mp_ioctl_hdl_exit;
-	}
-
-_rtw_mp_ioctl_hdl_exit:
-
-	kfree(pparmbuf);
-	return ret;
-}
-
-static int rtw_get_ap_info(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	u32 cnt = 0, wpa_ielen;
-	struct list_head *plist, *phead;
-	unsigned char *pbuf;
-	u8 bssid[ETH_ALEN];
-	char data[32];
-	struct wlan_network *pnetwork = NULL;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	struct __queue *queue = &(pmlmepriv->scanned_queue);
-	struct iw_point *pdata = &wrqu->data;
-
-	DBG_88E("+rtw_get_aplist_info\n");
-
-	if ((padapter->bDriverStopped) || (pdata == NULL)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) {
-		msleep(30);
-		cnt++;
-		if (cnt > 100)
-			break;
-	}
-	pdata->flags = 0;
-	if (pdata->length >= 32) {
-		if (copy_from_user(data, pdata->pointer, 32)) {
-			ret = -EINVAL;
-			goto exit;
-		}
-	} else {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-
-		if (hwaddr_aton_i(data, bssid)) {
-			DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
-			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-			return -EINVAL;
-		}
-
-		if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
-			/* BSSID match, then check if supporting wpa/wpa2 */
-			DBG_88E("BSSID:%pM\n", (bssid));
-
-			pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
-			if (pbuf && (wpa_ielen > 0)) {
-				pdata->flags = 1;
-				break;
-			}
-
-			pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
-			if (pbuf && (wpa_ielen > 0)) {
-				pdata->flags = 2;
-				break;
-			}
-		}
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (pdata->length >= 34) {
-		if (copy_to_user(pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
-			ret = -EINVAL;
-			goto exit;
-		}
-	}
-
-exit:
-
-	return ret;
-}
-
-static int rtw_set_pid(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	int *pdata = (int *)wrqu;
-	int selector;
-
-	if ((padapter->bDriverStopped) || (pdata == NULL)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	selector = *pdata;
-	if (selector < 3 && selector >= 0) {
-		padapter->pid[selector] = *(pdata+1);
-		ui_pid[selector] = *(pdata+1);
-		DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]);
-	} else {
-		DBG_88E("%s selector %d error\n", __func__, selector);
-	}
-exit:
-	return ret;
-}
-
-static int rtw_wps_start(struct net_device *dev,
-			 struct iw_request_info *info,
-			 union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct iw_point *pdata = &wrqu->data;
-	u32   u32wps_start = 0;
-
-	if ((padapter->bDriverStopped) || (pdata == NULL)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
-	if (ret) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	if (u32wps_start == 0)
-		u32wps_start = *extra;
-
-	DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start);
-
-	if (u32wps_start == 1) /*  WPS Start */
-		rtw_led_control(padapter, LED_CTL_START_WPS);
-	else if (u32wps_start == 2) /*  WPS Stop because of wps success */
-		rtw_led_control(padapter, LED_CTL_STOP_WPS);
-	else if (u32wps_start == 3) /*  WPS Stop because of wps fail */
-		rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
-
-exit:
-	return ret;
-}
-
-#ifdef CONFIG_88EU_P2P
-static int rtw_wext_p2p_enable(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
-	enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
-
-	if (*extra == '0')
-		init_role = P2P_ROLE_DISABLE;
-	else if (*extra == '1')
-		init_role = P2P_ROLE_DEVICE;
-	else if (*extra == '2')
-		init_role = P2P_ROLE_CLIENT;
-	else if (*extra == '3')
-		init_role = P2P_ROLE_GO;
-
-	if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	/* set channel/bandwidth */
-	if (init_role != P2P_ROLE_DISABLE) {
-		u8 channel, ch_offset;
-		u16 bwmode;
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
-			/*	Stay at the listen state and wait for discovery. */
-			channel = pwdinfo->listen_channel;
-			pwdinfo->operating_channel = pwdinfo->listen_channel;
-			ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-			bwmode = HT_CHANNEL_WIDTH_20;
-		} else {
-			pwdinfo->operating_channel = pmlmeext->cur_channel;
-
-			channel = pwdinfo->operating_channel;
-			ch_offset = pmlmeext->cur_ch_offset;
-			bwmode = pmlmeext->cur_bwmode;
-		}
-
-		set_channel_bwmode(padapter, channel, ch_offset, bwmode);
-	}
-
-exit:
-	return ret;
-}
-
-static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
-	memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
-	pwdinfo->nego_ssidlen = strlen(extra);
-
-	return ret;
-}
-
-static int rtw_p2p_set_intent(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	u8 intent = pwdinfo->intent;
-
-	switch (wrqu->data.length) {
-	case 1:
-		intent = extra[0] - '0';
-		break;
-	case 2:
-		intent = str_2char2num(extra[0], extra[1]);
-		break;
-	}
-	if (intent <= 15)
-		pwdinfo->intent = intent;
-	else
-		ret = -1;
-	DBG_88E("[%s] intent = %d\n", __func__, intent);
-	return ret;
-}
-
-static int rtw_p2p_set_listen_ch(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	u8 listen_ch = pwdinfo->listen_channel;	/*	Listen channel number */
-
-	switch (wrqu->data.length) {
-	case 1:
-		listen_ch = extra[0] - '0';
-		break;
-	case 2:
-		listen_ch = str_2char2num(extra[0], extra[1]);
-		break;
-	}
-
-	if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
-		pwdinfo->listen_channel = listen_ch;
-		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	} else {
-		ret = -1;
-	}
-
-	DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
-
-	return ret;
-}
-
-static int rtw_p2p_set_op_ch(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-/*	Commented by Albert 20110524 */
-/*	This function is used to set the operating channel if the driver will become the group owner */
-
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	u8 op_ch = pwdinfo->operating_channel;	/*	Operating channel number */
-
-	switch (wrqu->data.length) {
-	case 1:
-		op_ch = extra[0] - '0';
-		break;
-	case 2:
-		op_ch = str_2char2num(extra[0], extra[1]);
-		break;
-	}
-
-	if (op_ch > 0)
-		pwdinfo->operating_channel = op_ch;
-	else
-		ret = -1;
-
-	DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
-
-	return ret;
-}
-
-static int rtw_p2p_profilefound(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	/*	Comment by Albert 2010/10/13 */
-	/*	Input data format: */
-	/*	Ex:  0 */
-	/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
-	/*	0 => Reflush the profile record list. */
-	/*	1 => Add the profile list */
-	/*	XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
-	/*	YY => SSID Length */
-	/*	SSID => SSID for persistence group */
-
-	DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
-
-	/*	The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			if (extra[0] == '0') {
-			/*	Remove all the profile information of wifidirect_info structure. */
-			_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
-			pwdinfo->profileindex = 0;
-		} else {
-			if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
-				ret = -1;
-			} else {
-				int jj, kk;
-
-				/*	Add this profile information into pwdinfo->profileinfo */
-				/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
-				for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
-					pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
-
-				pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
-				memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
-				pwdinfo->profileindex++;
-			}
-		}
-	}
-
-	return ret;
-}
-
-static int rtw_p2p_setDN(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
-	_rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
-	memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
-	pwdinfo->device_name_len = wrqu->data.length - 1;
-
-	return ret;
-}
-
-static int rtw_p2p_get_status(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	if (padapter->bShowGetP2PState)
-		DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
-			pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
-			pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
-
-	/*	Commented by Albert 2010/10/12 */
-	/*	Because of the output size limitation, I had removed the "Role" information. */
-	/*	About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
-	sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
-	wrqu->data.length = strlen(extra);
-
-	return ret;
-}
-
-/*	Commented by Albert 20110520 */
-/*	This function will return the config method description */
-/*	This config method description will show us which config method the remote P2P device is intended to use */
-/*	by sending the provisioning discovery request frame. */
-
-static int rtw_p2p_get_req_cm(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_role(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
-			pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
-			pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
-
-	sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
-		rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
-		pwdinfo->p2p_peer_interface_addr);
-	sprintf(extra, "\nMAC %pM",
-		pwdinfo->p2p_peer_interface_addr);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
-		rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
-		pwdinfo->rx_prov_disc_info.peerDevAddr);
-	sprintf(extra, "\n%pM",
-		pwdinfo->rx_prov_disc_info.peerDevAddr);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n",
-		__func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
-		pwdinfo->p2p_peer_device_addr);
-	sprintf(extra, "\nMAC %pM",
-		pwdinfo->p2p_peer_device_addr);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_groupid(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
-		pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
-		pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
-		pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
-		pwdinfo->groupid_info.ssid);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_op_ch(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
-
-	sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
-	wrqu->data.length = strlen(extra);
-	return ret;
-}
-
-static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	u8 peerMACStr[17] = {0x00};
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	u8 blnMatch = 0;
-	u16	attr_content = 0;
-	uint attr_contentlen = 0;
-	/* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
-	u8 attr_content_str[6 + 17] = {0x00};
-
-	/*	Commented by Albert 20110727 */
-	/*	The input data is the MAC address which the application wants to know its WPS config method. */
-	/*	After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
-	/*	Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
-	if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
-		return -EFAULT;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			u8 *wpsie;
-			uint wpsie_len = 0;
-			__be16 be_tmp;
-
-			/*  The mac address is matched. */
-			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
-			if (wpsie) {
-				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
-				if (attr_contentlen) {
-					attr_content = be16_to_cpu(be_tmp);
-					sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
-					blnMatch = 1;
-				}
-			}
-			break;
-		}
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (!blnMatch)
-		sprintf(attr_content_str, "\n\nM=0000");
-
-	if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
-		return -EFAULT;
-	return ret;
-}
-
-static int rtw_p2p_get_go_device_address(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	u8 peerMACStr[17] = {0x00};
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	u8 blnMatch = 0;
-	u8 *p2pie;
-	uint p2pielen = 0, attr_contentlen = 0;
-	u8 attr_content[100] = {0x00};
-	u8 go_devadd_str[17 + 12] = {};
-
-	/*	Commented by Albert 20121209 */
-	/*	The input data is the GO's interface address which the application wants to know its device address. */
-	/*	Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
-	if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
-		return -EFAULT;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			/*	Commented by Albert 2011/05/18 */
-			/*	Match the device address located in the P2P IE */
-			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
-
-			p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
-			if (p2pie) {
-				while (p2pie) {
-					/*	The P2P Device ID attribute is included in the Beacon frame. */
-					/*	The P2P Device Info attribute is included in the probe response frame. */
-
-					_rtw_memset(attr_content, 0x00, 100);
-					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
-						/*	Handle the P2P Device ID attribute of Beacon first */
-						blnMatch = 1;
-						break;
-					} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
-						/*	Handle the P2P Device Info attribute of probe response */
-						blnMatch = 1;
-						break;
-					}
-
-					/* Get the next P2P IE */
-					p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
-				}
-			}
-	     }
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (!blnMatch)
-		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL");
-	else
-		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
-			attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
-
-	if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
-		return -EFAULT;
-	return ret;
-}
-
-static int rtw_p2p_get_device_type(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	u8 peerMACStr[17] = {0x00};
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	u8 blnMatch = 0;
-	u8 dev_type[8] = {0x00};
-	uint dev_type_len = 0;
-	u8 dev_type_str[17 + 9] = {0x00};	/*  +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
-
-	/*	Commented by Albert 20121209 */
-	/*	The input data is the MAC address which the application wants to know its device type. */
-	/*	Such user interface could know the device type. */
-	/*	Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
-	if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
-		return -EFAULT;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			u8 *wpsie;
-			uint wpsie_len = 0;
-
-		/*	The mac address is matched. */
-
-			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
-					       pnetwork->network.IELength - 12,
-					       NULL, &wpsie_len);
-			if (wpsie) {
-				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
-				if (dev_type_len) {
-					u16	type = 0;
-					__be16 be_tmp;
-
-					memcpy(&be_tmp, dev_type, 2);
-					type = be16_to_cpu(be_tmp);
-					sprintf(dev_type_str, "\n\nN=%.2d", type);
-					blnMatch = 1;
-				}
-			}
-			break;
-	     }
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (!blnMatch)
-		sprintf(dev_type_str, "\n\nN=00");
-
-	if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
-		return -EFAULT;
-	}
-
-	return ret;
-}
-
-static int rtw_p2p_get_device_name(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	u8 peerMACStr[17] = {0x00};
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	u8 blnMatch = 0;
-	u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
-	uint dev_len = 0;
-	u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00};	/*  +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */
-
-	/*	Commented by Albert 20121225 */
-	/*	The input data is the MAC address which the application wants to know its device name. */
-	/*	Such user interface could show peer device's device name instead of ssid. */
-	/*	Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
-	if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
-		return -EFAULT;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			u8 *wpsie;
-			uint wpsie_len = 0;
-
-			/*	The mac address is matched. */
-			wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
-			if (wpsie) {
-				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
-				if (dev_len) {
-					sprintf(dev_name_str, "\n\nN=%s", dev_name);
-					blnMatch = 1;
-				}
-			}
-			break;
-		}
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (!blnMatch)
-		sprintf(dev_name_str, "\n\nN=0000");
-
-	if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
-		return -EFAULT;
-	return ret;
-}
-
-static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	u8 peerMACStr[17] = {0x00};
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	u8 blnMatch = 0;
-	u8 *p2pie;
-	uint p2pielen = 0, attr_contentlen = 0;
-	u8 attr_content[2] = {0x00};
-
-	u8 inv_proc_str[17 + 8] = {0x00};
-	/*  +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */
-
-	/*	Commented by Ouden 20121226 */
-	/*	The application wants to know P2P initiation procedure is supported or not. */
-	/*	Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
-	if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
-		return -EFAULT;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			/*	Commented by Albert 20121226 */
-			/*	Match the device address located in the P2P IE */
-			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
-
-			p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
-			if (p2pie) {
-				while (p2pie) {
-					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
-						/*	Handle the P2P capability attribute */
-						blnMatch = 1;
-						break;
-					}
-
-					/* Get the next P2P IE */
-					p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
-				}
-			}
-		}
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (!blnMatch) {
-		sprintf(inv_proc_str, "\nIP=-1");
-	} else {
-		if (attr_content[0] & 0x20)
-			sprintf(inv_proc_str, "\nIP=1");
-		else
-			sprintf(inv_proc_str, "\nIP=0");
-	}
-	if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
-		return -EFAULT;
-	return ret;
-}
-
-static int rtw_p2p_connect(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	uint uintPeerChannel = 0;
-
-	/*	Commented by Albert 20110304 */
-	/*	The input data contains two informations. */
-	/*	1. First information is the MAC address which wants to formate with */
-	/*	2. Second information is the WPS PINCode or "pbc" string for push button method */
-	/*	Format: 00:E0:4C:00:00:05 */
-	/*	Format: 00:E0:4C:00:00:05 */
-
-	DBG_88E("[%s] data = %s\n", __func__, extra);
-
-	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
-		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
-		return ret;
-	}
-
-	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
-		return -1;
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
-			uintPeerChannel = pnetwork->network.Configuration.DSConfig;
-			break;
-		}
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (uintPeerChannel) {
-		_rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
-		_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
-
-		pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
-		memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
-		pwdinfo->nego_req_info.benable = true;
-
-		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-		if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
-			/*	Restore to the listen state if the current p2p state is not nego OK */
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
-		}
-
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
-
-		DBG_88E("[%s] Start PreTx Procedure!\n", __func__);
-		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
-	} else {
-		DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__);
-		ret = -1;
-	}
-	return ret;
-}
-
-static int rtw_p2p_invite_req(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	int jj, kk;
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	uint uintPeerChannel = 0;
-	u8 attr_content[50] = {0x00};
-	u8 *p2pie;
-	uint p2pielen = 0, attr_contentlen = 0;
-	struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
-
-	/*	The input data contains two informations. */
-	/*	1. First information is the P2P device address which you want to send to. */
-	/*	2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
-	/*	Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
-	/*	Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
-
-	DBG_88E("[%s] data = %s\n", __func__, extra);
-
-	if (wrqu->data.length <=  37) {
-		DBG_88E("[%s] Wrong format!\n", __func__);
-		return ret;
-	}
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
-		return ret;
-	} else {
-		/*	Reset the content of struct tx_invite_req_info */
-		pinvite_req_info->benable = false;
-		_rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
-		_rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
-		pinvite_req_info->ssidlen = 0x00;
-		pinvite_req_info->operating_ch = pwdinfo->operating_channel;
-		_rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
-		pinvite_req_info->token = 3;
-	}
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-
-		/*	Commented by Albert 2011/05/18 */
-		/*	Match the device address located in the P2P IE */
-		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
-
-		p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
-		if (p2pie) {
-			/*	The P2P Device ID attribute is included in the Beacon frame. */
-			/*	The P2P Device Info attribute is included in the probe response frame. */
-
-			if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
-				/*	Handle the P2P Device ID attribute of Beacon first */
-				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
-					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
-					break;
-				}
-			} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
-				/*	Handle the P2P Device Info attribute of probe response */
-				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
-					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
-					break;
-				}
-			}
-		}
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (uintPeerChannel) {
-		/*	Store the GO's bssid */
-		for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
-			pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
-
-		/*	Store the GO's ssid */
-		pinvite_req_info->ssidlen = wrqu->data.length - 36;
-		memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
-		pinvite_req_info->benable = true;
-		pinvite_req_info->peer_ch = uintPeerChannel;
-
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
-
-		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-
-		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-
-		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
-	} else {
-		DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
-	}
-	return ret;
-}
-
-static int rtw_p2p_set_persistent(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	/*	The input data is 0 or 1 */
-	/*	0: disable persistent group functionality */
-	/*	1: enable persistent group founctionality */
-
-	DBG_88E("[%s] data = %s\n", __func__, extra);
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
-		return ret;
-	} else {
-		if (extra[0] == '0')	/*	Disable the persistent group function. */
-			pwdinfo->persistent_supported = false;
-		else if (extra[0] == '1')	/*	Enable the persistent group function. */
-			pwdinfo->persistent_supported = true;
-		else
-			pwdinfo->persistent_supported = false;
-	}
-	pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
-	return ret;
-}
-
-static int rtw_p2p_prov_disc(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-	u8 peerMAC[ETH_ALEN] = {0x00};
-	int jj, kk;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct list_head *plist, *phead;
-	struct __queue *queue	= &(pmlmepriv->scanned_queue);
-	struct	wlan_network	*pnetwork = NULL;
-	uint uintPeerChannel = 0;
-	u8 attr_content[100] = {0x00};
-	u8 *p2pie;
-	uint p2pielen = 0, attr_contentlen = 0;
-
-	/*	The input data contains two informations. */
-	/*	1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
-	/*	2. Second information is the WPS configuration method which wants to discovery */
-	/*	Format: 00:E0:4C:00:00:05_display */
-	/*	Format: 00:E0:4C:00:00:05_keypad */
-	/*	Format: 00:E0:4C:00:00:05_pbc */
-	/*	Format: 00:E0:4C:00:00:05_label */
-
-	DBG_88E("[%s] data = %s\n", __func__, extra);
-
-	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
-		DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
-		return ret;
-	} else {
-		/*	Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
-		_rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
-		_rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
-		_rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
-		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
-		pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
-		pwdinfo->tx_prov_disc_info.benable = false;
-	}
-
-	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
-		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
-
-	if (!memcmp(&extra[18], "display", 7)) {
-		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
-	} else if (!memcmp(&extra[18], "keypad", 7)) {
-		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
-	} else if (!memcmp(&extra[18], "pbc", 3)) {
-		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
-	} else if (!memcmp(&extra[18], "label", 5)) {
-		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
-	} else {
-		DBG_88E("[%s] Unknown WPS config methodn", __func__);
-		return ret;
-	}
-
-	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	while (1) {
-		if (rtw_end_of_queue_search(phead, plist) == true)
-			break;
-
-		if (uintPeerChannel != 0)
-			break;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-
-		/*	Commented by Albert 2011/05/18 */
-		/*	Match the device address located in the P2P IE */
-		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
-
-		p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
-		if (p2pie) {
-			while (p2pie) {
-				/*	The P2P Device ID attribute is included in the Beacon frame. */
-				/*	The P2P Device Info attribute is included in the probe response frame. */
-
-				if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
-					/*	Handle the P2P Device ID attribute of Beacon first */
-					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
-						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
-						break;
-					}
-				} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
-					/*	Handle the P2P Device Info attribute of probe response */
-					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
-						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
-						break;
-					}
-				}
-
-				/* Get the next P2P IE */
-				p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
-			}
-		}
-
-		plist = plist->next;
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	if (uintPeerChannel) {
-		DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
-		memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
-		memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
-		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
-		pwdinfo->tx_prov_disc_info.benable = true;
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
-
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-			memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
-		} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
-			pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
-		}
-
-		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-
-		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
-
-		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
-	} else {
-		DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
-	}
-	return ret;
-}
-
-/*	This function is used to inform the driver the user had specified the pin code value or pbc */
-/*	to application. */
-
-static int rtw_p2p_got_wpsinfo(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
-
-	DBG_88E("[%s] data = %s\n", __func__, extra);
-	/*	Added by Albert 20110328 */
-	/*	if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
-	/*	if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
-	/*	if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
-	/*	if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
-
-	if (*extra == '0')
-		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
-	else if (*extra == '1')
-		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
-	else if (*extra == '2')
-		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
-	else if (*extra == '3')
-		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
-	else
-		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
-	return ret;
-}
-
-#endif /* CONFIG_88EU_P2P */
-
-static int rtw_p2p_set(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-
-#ifdef CONFIG_88EU_P2P
-	DBG_88E("[%s] extra = %s\n", __func__, extra);
-	if (!memcmp(extra, "enable=", 7)) {
-		rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "setDN=", 6)) {
-		wrqu->data.length -= 6;
-		rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
-	} else if (!memcmp(extra, "profilefound=", 13)) {
-		wrqu->data.length -= 13;
-		rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
-	} else if (!memcmp(extra, "prov_disc=", 10)) {
-		wrqu->data.length -= 10;
-		rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
-	} else if (!memcmp(extra, "nego=", 5)) {
-		wrqu->data.length -= 5;
-		rtw_p2p_connect(dev, info, wrqu, &extra[5]);
-	} else if (!memcmp(extra, "intent=", 7)) {
-		/*	Commented by Albert 2011/03/23 */
-		/*	The wrqu->data.length will include the null character */
-		/*	So, we will decrease 7 + 1 */
-		wrqu->data.length -= 8;
-		rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "ssid=", 5)) {
-		wrqu->data.length -= 5;
-		rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
-	} else if (!memcmp(extra, "got_wpsinfo=", 12)) {
-		wrqu->data.length -= 12;
-		rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
-	} else if (!memcmp(extra, "listen_ch=", 10)) {
-		/*	Commented by Albert 2011/05/24 */
-		/*	The wrqu->data.length will include the null character */
-		/*	So, we will decrease (10 + 1) */
-		wrqu->data.length -= 11;
-		rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
-	} else if (!memcmp(extra, "op_ch=", 6)) {
-		/*	Commented by Albert 2011/05/24 */
-		/*	The wrqu->data.length will include the null character */
-		/*	So, we will decrease (6 + 1) */
-		wrqu->data.length -= 7;
-		rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
-	} else if (!memcmp(extra, "invite=", 7)) {
-		wrqu->data.length -= 8;
-		rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "persistent=", 11)) {
-		wrqu->data.length -= 11;
-		rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
-	}
-#endif /* CONFIG_88EU_P2P */
-
-	return ret;
-}
-
-static int rtw_p2p_get(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-
-#ifdef CONFIG_88EU_P2P
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
-	if (padapter->bShowGetP2PState)
-		DBG_88E("[%s] extra = %s\n", __func__,
-			(char __user *)wrqu->data.pointer);
-	if (!memcmp((__force const char *)wrqu->data.pointer,
-			"status", 6)) {
-		rtw_p2p_get_status(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"role", 4)) {
-		rtw_p2p_get_role(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"peer_ifa", 8)) {
-		rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"req_cm", 6)) {
-		rtw_p2p_get_req_cm(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"peer_deva", 9)) {
-		/*	Get the P2P device address when receiving the provision discovery request frame. */
-		rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"group_id", 8)) {
-		rtw_p2p_get_groupid(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"peer_deva_inv", 13)) {
-		/*	Get the P2P device address when receiving the P2P Invitation request frame. */
-		rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
-	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"op_ch", 5)) {
-		rtw_p2p_get_op_ch(dev, info, wrqu, extra);
-	}
-#endif /* CONFIG_88EU_P2P */
-	return ret;
-}
-
-static int rtw_p2p_get2(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-
-#ifdef CONFIG_88EU_P2P
-	DBG_88E("[%s] extra = %s\n", __func__,
-			(char __user *)wrqu->data.pointer);
-	if (!memcmp(extra, "wpsCM =", 6)) {
-		wrqu->data.length -= 6;
-		rtw_p2p_get_wps_configmethod(dev, info, wrqu,  &extra[6]);
-	} else if (!memcmp(extra, "devN =", 5)) {
-		wrqu->data.length -= 5;
-		rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
-	} else if (!memcmp(extra, "dev_type =", 9)) {
-		wrqu->data.length -= 9;
-		rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
-	} else if (!memcmp(extra, "go_devadd =", 10)) {
-		wrqu->data.length -= 10;
-		rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
-	} else if (!memcmp(extra, "InvProc =", 8)) {
-		wrqu->data.length -= 8;
-		rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
-	}
-
-#endif /* CONFIG_88EU_P2P */
-
-	return ret;
-}
-
-static int rtw_cta_test_start(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	DBG_88E("%s %s\n", __func__, extra);
-	if (!strcmp(extra, "1"))
-		padapter->in_cta_test = 1;
-	else
-		padapter->in_cta_test = 0;
-
-	if (padapter->in_cta_test) {
-		u32 v = rtw_read32(padapter, REG_RCR);
-		v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
-		rtw_write32(padapter, REG_RCR, v);
-		DBG_88E("enable RCR_ADF\n");
-	} else {
-		u32 v = rtw_read32(padapter, REG_RCR);
-		v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/*  RCR_ADF */
-		rtw_write32(padapter, REG_RCR, v);
-		DBG_88E("disable RCR_ADF\n");
-	}
-	return ret;
-}
-
-static int rtw_rereg_nd_name(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
-	char new_ifname[IFNAMSIZ];
-
-	if (rereg_priv->old_ifname[0] == 0) {
-		char *reg_ifname;
-		reg_ifname = padapter->registrypriv.if2name;
-
-		strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
-		rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
-	}
-
-	if (wrqu->data.length > IFNAMSIZ)
-		return -EFAULT;
-
-	if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
-		return -EFAULT;
-
-	if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
-		return ret;
-
-	DBG_88E("%s new_ifname:%s\n", __func__, new_ifname);
-	ret = rtw_change_ifname(padapter, new_ifname);
-	if (0 != ret)
-		goto exit;
-
-	if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
-		padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
-		rtw_hal_sw_led_init(padapter);
-		rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
-	}
-
-	strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
-	rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
-
-	if (!memcmp(new_ifname, "disable%d", 9)) {
-		DBG_88E("%s disable\n", __func__);
-		/*  free network queue for Android's timming issue */
-		rtw_free_network_queue(padapter, true);
-
-		/*  close led */
-		rtw_led_control(padapter, LED_CTL_POWER_OFF);
-		rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
-		padapter->ledpriv.bRegUseLed = false;
-		rtw_hal_sw_led_deinit(padapter);
-
-		/*  the interface is being "disabled", we can do deeper IPS */
-		rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
-		rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
-	}
-exit:
-	return ret;
-}
-
-static void mac_reg_dump(struct adapter *padapter)
-{
-	int i, j = 1;
-	pr_info("\n ======= MAC REG =======\n");
-	for (i = 0x0; i < 0x300; i += 4) {
-		if (j%4 == 1)
-			pr_info("0x%02x", i);
-		pr_info(" 0x%08x ", rtw_read32(padapter, i));
-		if ((j++)%4 == 0)
-			pr_info("\n");
-	}
-	for (i = 0x400; i < 0x800; i += 4) {
-		if (j%4 == 1)
-			pr_info("0x%02x", i);
-		pr_info(" 0x%08x ", rtw_read32(padapter, i));
-		if ((j++)%4 == 0)
-			pr_info("\n");
-	}
-}
-
-static void bb_reg_dump(struct adapter *padapter)
-{
-	int i, j = 1;
-	pr_info("\n ======= BB REG =======\n");
-	for (i = 0x800; i < 0x1000; i += 4) {
-		if (j%4 == 1)
-			pr_info("0x%02x", i);
-
-		pr_info(" 0x%08x ", rtw_read32(padapter, i));
-		if ((j++)%4 == 0)
-			pr_info("\n");
-	}
-}
-
-static void rf_reg_dump(struct adapter *padapter)
-{
-	int i, j = 1, path;
-	u32 value;
-	u8 rf_type, path_nums = 0;
-	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
-	pr_info("\n ======= RF REG =======\n");
-	if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
-		path_nums = 1;
-	else
-		path_nums = 2;
-
-	for (path = 0; path < path_nums; path++) {
-		pr_info("\nRF_Path(%x)\n", path);
-		for (i = 0; i < 0x100; i++) {
-			value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
-			if (j%4 == 1)
-				pr_info("0x%02x ", i);
-			pr_info(" 0x%08x ", value);
-			if ((j++)%4 == 0)
-				pr_info("\n");
-		}
-	}
-}
-
-static int rtw_dbg_port(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	u8 major_cmd, minor_cmd;
-	u16 arg;
-	s32 extra_arg;
-	u32 *pdata, val32;
-	struct sta_info *psta;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
-	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-	struct security_priv *psecuritypriv = &padapter->securitypriv;
-	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
-	struct sta_priv *pstapriv = &padapter->stapriv;
-
-	pdata = (u32 *)&wrqu->data;
-
-	val32 = *pdata;
-	arg = (u16)(val32 & 0x0000ffff);
-	major_cmd = (u8)(val32 >> 24);
-	minor_cmd = (u8)((val32 >> 16) & 0x00ff);
-
-	extra_arg = *(pdata+1);
-
-	switch (major_cmd) {
-	case 0x70:/* read_reg */
-		switch (minor_cmd) {
-		case 1:
-			DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
-			break;
-		case 2:
-			DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
-			break;
-		case 4:
-			DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
-			break;
-		}
-		break;
-	case 0x71:/* write_reg */
-		switch (minor_cmd) {
-		case 1:
-			rtw_write8(padapter, arg, extra_arg);
-			DBG_88E("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
-			break;
-		case 2:
-			rtw_write16(padapter, arg, extra_arg);
-			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
-			break;
-		case 4:
-			rtw_write32(padapter, arg, extra_arg);
-			DBG_88E("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
-			break;
-		}
-		break;
-	case 0x72:/* read_bb */
-		DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
-		break;
-	case 0x73:/* write_bb */
-		rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
-		DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
-		break;
-	case 0x74:/* read_rf */
-		DBG_88E("read RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
-		break;
-	case 0x75:/* write_rf */
-		rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
-		DBG_88E("write RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
-		break;
-
-	case 0x76:
-		switch (minor_cmd) {
-		case 0x00: /* normal mode, */
-			padapter->recvpriv.is_signal_dbg = 0;
-			break;
-		case 0x01: /* dbg mode */
-			padapter->recvpriv.is_signal_dbg = 1;
-			extra_arg = extra_arg > 100 ? 100 : extra_arg;
-			extra_arg = extra_arg < 0 ? 0 : extra_arg;
-			padapter->recvpriv.signal_strength_dbg = extra_arg;
-			break;
-		}
-		break;
-	case 0x78: /* IOL test */
-		switch (minor_cmd) {
-		case 0x04: /* LLT table initialization test */
-		{
-			u8 page_boundary = 0xf9;
-			struct xmit_frame	*xmit_frame;
-
-			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
-			if (xmit_frame == NULL) {
-				ret = -ENOMEM;
-				break;
-			}
-
-			rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
-
-			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
-				ret = -EPERM;
-		}
-			break;
-		case 0x05: /* blink LED test */
-		{
-			u16 reg = 0x4c;
-			u32 blink_num = 50;
-			u32 blink_delay_ms = 200;
-			int i;
-			struct xmit_frame	*xmit_frame;
-
-			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
-			if (xmit_frame == NULL) {
-				ret = -ENOMEM;
-				break;
-			}
-
-			for (i = 0; i < blink_num; i++) {
-				rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
-				rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
-				rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
-				rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
-			}
-			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200, 0))
-				ret = -EPERM;
-		}
-			break;
-
-		case 0x06: /* continuous write byte test */
-		{
-			u16 reg = arg;
-			u16 start_value = 0;
-			u32 write_num = extra_arg;
-			int i;
-			u8 final;
-			struct xmit_frame	*xmit_frame;
-
-			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
-			if (xmit_frame == NULL) {
-				ret = -ENOMEM;
-				break;
-			}
-
-			for (i = 0; i < write_num; i++)
-				rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value, 0xFF);
-			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
-				ret = -EPERM;
-
-			final = rtw_read8(padapter, reg);
-			if (start_value+write_num-1 == final)
-				DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
-			else
-				DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
-		}
-			break;
-
-		case 0x07: /* continuous write word test */
-		{
-			u16 reg = arg;
-			u16 start_value = 200;
-			u32 write_num = extra_arg;
-
-			int i;
-			u16 final;
-			struct xmit_frame	*xmit_frame;
-
-			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
-			if (xmit_frame == NULL) {
-				ret = -ENOMEM;
-				break;
-			}
-
-			for (i = 0; i < write_num; i++)
-				rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value, 0xFFFF);
-			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
-				ret = -EPERM;
-
-			final = rtw_read16(padapter, reg);
-			if (start_value+write_num-1 == final)
-				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
-			else
-				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
-		}
-			break;
-		case 0x08: /* continuous write dword test */
-		{
-			u16 reg = arg;
-			u32 start_value = 0x110000c7;
-			u32 write_num = extra_arg;
-
-			int i;
-			u32 final;
-			struct xmit_frame	*xmit_frame;
-
-			xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
-			if (xmit_frame == NULL) {
-				ret = -ENOMEM;
-				break;
-			}
-
-			for (i = 0; i < write_num; i++)
-				rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value, 0xFFFFFFFF);
-			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
-				ret = -EPERM;
-
-			final = rtw_read32(padapter, reg);
-			if (start_value+write_num-1 == final)
-				DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n",
-					reg, write_num, start_value, final);
-			else
-				DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n",
-					reg, write_num, start_value, final);
-		}
-			break;
-		}
-		break;
-	case 0x79:
-		{
-			/*
-			* dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
-			* dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
-			*/
-			u8 value =  extra_arg & 0x0f;
-			u8 sign = minor_cmd;
-			u16 write_value = 0;
-
-			DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
-
-			if (sign)
-				value = value | 0x10;
-
-			write_value = value | (value << 5);
-			rtw_write16(padapter, 0x6d9, write_value);
-		}
-		break;
-	case 0x7a:
-		receive_disconnect(padapter, pmlmeinfo->network.MacAddress
-			, WLAN_REASON_EXPIRATION_CHK);
-		break;
-	case 0x7F:
-		switch (minor_cmd) {
-		case 0x0:
-			DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
-			break;
-		case 0x01:
-			DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
-				psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
-				psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
-			break;
-		case 0x02:
-			DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
-			break;
-		case 0x03:
-			DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
-			DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
-			break;
-		case 0x04:
-			DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel);
-			DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode);
-			DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
-			break;
-		case 0x05:
-			psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
-			if (psta) {
-				int i;
-				struct recv_reorder_ctrl *preorder_ctrl;
-
-				DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid);
-				DBG_88E("sta's macaddr: %pM\n", psta->hwaddr);
-				DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
-				DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
-				DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
-				DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
-				DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
-				DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
-				DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
-				for (i = 0; i < 16; i++) {
-					preorder_ctrl = &psta->recvreorder_ctrl[i];
-					if (preorder_ctrl->enable)
-						DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
-				}
-			} else {
-				DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress));
-			}
-			break;
-		case 0x06:
-			{
-				u32	ODMFlag;
-				rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
-				DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
-				ODMFlag = (u32)(0x0f&arg);
-				DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag);
-				rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
-			}
-			break;
-		case 0x07:
-			DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n",
-				padapter->bSurpriseRemoved, padapter->bDriverStopped);
-			break;
-		case 0x08:
-			{
-				struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-				struct recv_priv  *precvpriv = &padapter->recvpriv;
-
-				DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n",
-					pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
-				DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt);
-			}
-			break;
-		case 0x09:
-			{
-				int i, j;
-				struct list_head *plist, *phead;
-				struct recv_reorder_ctrl *preorder_ctrl;
-
-#ifdef CONFIG_88EU_AP_MODE
-				DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
-#endif
-				spin_lock_bh(&pstapriv->sta_hash_lock);
-
-				for (i = 0; i < NUM_STA; i++) {
-					phead = &(pstapriv->sta_hash[i]);
-					plist = phead->next;
-
-					while ((rtw_end_of_queue_search(phead, plist)) == false) {
-						psta = container_of(plist, struct sta_info, hash_list);
-
-						plist = plist->next;
-
-						if (extra_arg == psta->aid) {
-							DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
-							DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
-							DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
-							DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
-							DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
-							DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
-							DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
-
-#ifdef CONFIG_88EU_AP_MODE
-							DBG_88E("capability = 0x%x\n", psta->capability);
-							DBG_88E("flags = 0x%x\n", psta->flags);
-							DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk);
-							DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
-							DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
-							DBG_88E("qos_info = 0x%x\n", psta->qos_info);
-#endif
-							DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
-
-							for (j = 0; j < 16; j++) {
-								preorder_ctrl = &psta->recvreorder_ctrl[j];
-								if (preorder_ctrl->enable)
-									DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
-							}
-						}
-					}
-				}
-				spin_unlock_bh(&pstapriv->sta_hash_lock);
-			}
-			break;
-		case 0x0c:/* dump rx/tx packet */
-			if (arg == 0) {
-				DBG_88E("dump rx packet (%d)\n", extra_arg);
-				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
-			} else if (arg == 1) {
-				DBG_88E("dump tx packet (%d)\n", extra_arg);
-				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
-			}
-			break;
-		case 0x0f:
-			if (extra_arg == 0) {
-				DBG_88E("###### silent reset test.......#####\n");
-				rtw_hal_sreset_reset(padapter);
-			}
-			break;
-		case 0x15:
-			{
-				struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-				DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
-			}
-			break;
-		case 0x10:/*  driver version display */
-			DBG_88E("rtw driver version =%s\n", DRIVERVERSION);
-			break;
-		case 0x11:
-			DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off");
-			padapter->bRxRSSIDisplay = extra_arg;
-			rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP, &extra_arg);
-			break;
-		case 0x12: /* set rx_stbc */
-		{
-			struct registry_priv	*pregpriv = &padapter->registrypriv;
-			/*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
-			/* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
-			if (!pregpriv)
-				break;
-			if (extra_arg >= 0 && extra_arg <= 3) {
-				pregpriv->rx_stbc = extra_arg;
-				DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
-			} else {
-				DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc);
-			}
-		}
-			break;
-		case 0x13: /* set ampdu_enable */
-		{
-			struct registry_priv	*pregpriv = &padapter->registrypriv;
-			/*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
-			if (!pregpriv)
-				break;
-			if (extra_arg >= 0 && extra_arg < 3) {
-				pregpriv->ampdu_enable = extra_arg;
-				DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
-			} else {
-				DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
-			}
-		}
-			break;
-		case 0x14: /* get wifi_spec */
-		{
-			struct registry_priv	*pregpriv = &padapter->registrypriv;
-			DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec);
-		}
-			break;
-		case 0x16:
-			if (arg == 0xff) {
-				pr_info("ODM_COMP_DIG\t\tBIT0\n");
-				pr_info("ODM_COMP_RA_MASK\t\tBIT1\n");
-				pr_info("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n");
-				pr_info("ODM_COMP_FA_CNT\t\tBIT3\n");
-				pr_info("ODM_COMP_RSSI_MONITOR\tBIT4\n");
-				pr_info("ODM_COMP_CCK_PD\t\tBIT5\n");
-				pr_info("ODM_COMP_ANT_DIV\t\tBIT6\n");
-				pr_info("ODM_COMP_PWR_SAVE\t\tBIT7\n");
-				pr_info("ODM_COMP_PWR_TRAIN\tBIT8\n");
-				pr_info("ODM_COMP_RATE_ADAPTIVE\tBIT9\n");
-				pr_info("ODM_COMP_PATH_DIV\t\tBIT10\n");
-				pr_info("ODM_COMP_PSD	\tBIT11\n");
-				pr_info("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n");
-				pr_info("ODM_COMP_RXHP\t\tBIT13\n");
-				pr_info("ODM_COMP_EDCA_TURBO\tBIT16\n");
-				pr_info("ODM_COMP_EARLY_MODE\tBIT17\n");
-				pr_info("ODM_COMP_TX_PWR_TRACK\tBIT24\n");
-				pr_info("ODM_COMP_RX_GAIN_TRACK\tBIT25\n");
-				pr_info("ODM_COMP_CALIBRATION\tBIT26\n");
-				rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
-			} else {
-				rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
-			}
-			break;
-		case 0x23:
-			DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
-			padapter->bNotifyChannelChange = extra_arg;
-			break;
-		case 0x24:
-#ifdef CONFIG_88EU_P2P
-			DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
-			padapter->bShowGetP2PState = extra_arg;
-#endif /*  CONFIG_88EU_P2P */
-			break;
-		case 0xaa:
-			if (extra_arg > 0x13)
-				extra_arg = 0xFF;
-			DBG_88E("chang data rate to :0x%02x\n", extra_arg);
-			padapter->fix_rate = extra_arg;
-			break;
-		case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
-			if (extra_arg == 0)
-				mac_reg_dump(padapter);
-			else if (extra_arg == 1)
-				bb_reg_dump(padapter);
-			else if (extra_arg == 2)
-				rf_reg_dump(padapter);
-			break;
-		case 0xee:/* turn on/off dynamic funcs */
-			{
-				u32 odm_flag;
-
-				if (0xf == extra_arg) {
-					rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
-					DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
-					DBG_88E("extra_arg = 0  - disable all dynamic func\n");
-					DBG_88E("extra_arg = 1  - disable DIG- BIT(0)\n");
-					DBG_88E("extra_arg = 2  - disable High power - BIT(1)\n");
-					DBG_88E("extra_arg = 3  - disable tx power tracking - BIT(2)\n");
-					DBG_88E("extra_arg = 4  - disable BT coexistence - BIT(3)\n");
-					DBG_88E("extra_arg = 5  - disable antenna diversity - BIT(4)\n");
-					DBG_88E("extra_arg = 6  - enable all dynamic func\n");
-				} else {
-					/*	extra_arg = 0  - disable all dynamic func
-						extra_arg = 1  - disable DIG
-						extra_arg = 2  - disable tx power tracking
-						extra_arg = 3  - turn on all dynamic func
-					*/
-					rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
-					rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
-					DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
-				}
-			}
-			break;
-
-		case 0xfd:
-			rtw_write8(padapter, 0xc50, arg);
-			DBG_88E("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
-			rtw_write8(padapter, 0xc58, arg);
-			DBG_88E("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
-			break;
-		case 0xfe:
-			DBG_88E("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
-			DBG_88E("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
-			break;
-		case 0xff:
-			DBG_88E("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
-			DBG_88E("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
-			DBG_88E("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
-			DBG_88E("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
-			DBG_88E("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
-
-			DBG_88E("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
-
-			DBG_88E("\n");
-
-			DBG_88E("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
-			DBG_88E("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
-
-			DBG_88E("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
-
-			DBG_88E("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
-
-			DBG_88E("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
-			DBG_88E("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
-
-			DBG_88E("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
-			DBG_88E("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
-			DBG_88E("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
-			DBG_88E("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
-			break;
-		}
-		break;
-	default:
-		DBG_88E("error dbg cmd!\n");
-		break;
-	}
-	return ret;
-}
-
 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
 {
 	uint ret = 0;
@@ -4766,13 +2118,13 @@ static u8 set_pairwise_key(struct adapte
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 	u8 res = _SUCCESS;
 
-	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
+	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
 	if (psetstakey_para == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -4804,19 +2156,19 @@ static int set_group_key(struct adapter
 
 	DBG_88E("%s\n", __func__);
 
-	pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct	cmd_obj));
+	pcmd = kzalloc(sizeof(struct	cmd_obj), GFP_KERNEL);
 	if (pcmd == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
-	psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
+	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
 	if (psetkeyparm == NULL) {
 		kfree(pcmd);
 		res = _FAIL;
 		goto exit;
 	}
 
-	_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
+	memset(psetkeyparm, 0, sizeof(struct setkey_parm));
 
 	psetkeyparm->keyid = (u8)keyid;
 
@@ -4846,7 +2198,7 @@ static int set_group_key(struct adapter
 	pcmd->rsp = NULL;
 	pcmd->rspsz = 0;
 
-	_rtw_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 
 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
 
@@ -4931,7 +2283,7 @@ static int rtw_set_encryption(struct net
 				goto exit;
 			}
 
-			_rtw_memset(pwep, 0, wep_total_len);
+			memset(pwep, 0, wep_total_len);
 
 			pwep->KeyLength = wep_key_len;
 			pwep->Length = wep_total_len;
@@ -5221,8 +2573,8 @@ static int rtw_del_sta(struct net_device
 	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
 	if (psta) {
 		spin_lock_bh(&pstapriv->asoc_list_lock);
-		if (!rtw_is_list_empty(&psta->asoc_list)) {
-			rtw_list_delete(&psta->asoc_list);
+		if (!list_empty(&psta->asoc_list)) {
+			list_del_init(&psta->asoc_list);
 			pstapriv->asoc_list_cnt--;
 			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
 		}
@@ -5664,1927 +3016,6 @@ FREE_EXT:
 	return ret;
 }
 
-static int rtw_pm_set(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	unsigned	mode = 0;
-	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
-	DBG_88E("[%s] extra = %s\n", __func__, extra);
-
-	if (!memcmp(extra, "lps =", 4)) {
-		ret = sscanf(extra+4, "%u", &mode);
-		if (ret != 1)
-			return -EINVAL;
-		ret = rtw_pm_set_lps(padapter, mode);
-	} else if (!memcmp(extra, "ips =", 4)) {
-		ret = sscanf(extra+4, "%u", &mode);
-		if (ret != 1)
-			return -EINVAL;
-		ret = rtw_pm_set_ips(padapter, mode);
-	} else {
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int rtw_mp_efuse_get(struct net_device *dev,
-			struct iw_request_info *info,
-			union iwreq_data *wdata, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-	struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
-	struct efuse_hal *pEfuseHal;
-	struct iw_point *wrqu;
-
-	u8 *PROMContent = pEEPROM->efuse_eeprom_data;
-	u8 ips_mode = 0, lps_mode = 0;
-	struct pwrctrl_priv *pwrctrlpriv;
-	u8 *data = NULL;
-	u8 *rawdata = NULL;
-	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
-	u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
-	u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0;
-	int err;
-	u8 org_fw_iol = padapter->registrypriv.fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
-
-	wrqu = (struct iw_point *)wdata;
-	pwrctrlpriv = &padapter->pwrctrlpriv;
-	pEfuseHal = &haldata->EfuseHal;
-
-	err = 0;
-	data = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
-	if (data == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-	rawdata = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
-	if (rawdata == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
-		err = -EFAULT;
-		goto exit;
-	}
-	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
-	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
-
-	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
-	rtw_pm_set_ips(padapter, IPS_NONE);
-
-	pch = extra;
-	DBG_88E("%s: in =%s\n", __func__, extra);
-
-	i = 0;
-	/* mac 16 "00e04c871200" rmap, 00, 2 */
-	while ((token = strsep(&pch, ",")) != NULL) {
-		if (i > 2)
-			break;
-		tmp[i] = token;
-		i++;
-	}
-	padapter->registrypriv.fw_iol = 0;/*  0:Disable, 1:enable, 2:by usb speed */
-
-	if (strcmp(tmp[0], "status") == 0) {
-		sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK"));
-
-		  goto exit;
-	} else if (strcmp(tmp[0], "filemap") == 0) {
-		mapLen = EFUSE_MAP_SIZE;
-
-		sprintf(extra, "\n");
-		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
-			sprintf(extra, "%s0x%02x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "realmap") == 0) {
-		mapLen = EFUSE_MAP_SIZE;
-		if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) {
-			DBG_88E("%s: read realmap Fail!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		sprintf(extra, "\n");
-		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
-			sprintf(extra, "%s0x%02x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "rmap") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__);
-			err = -EINVAL;
-			goto exit;
-		}
-
-		/*  rmap addr cnts */
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		DBG_88E("%s: addr =%x\n", __func__, addr);
-
-		cnts = simple_strtoul(tmp[2], &ptmp, 10);
-		if (cnts == 0) {
-			DBG_88E("%s: rmap Fail!! cnts error!\n", __func__);
-			err = -EINVAL;
-			goto exit;
-		}
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr + cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EINVAL;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		*extra = 0;
-		for (i = 0; i < cnts; i++)
-			sprintf(extra, "%s0x%02X ", extra, data[i]);
-	} else if (strcmp(tmp[0], "realraw") == 0) {
-		addr = 0;
-		mapLen = EFUSE_MAX_SIZE;
-		if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		sprintf(extra, "\n");
-		for (i = 0; i < mapLen; i++) {
-			sprintf(extra, "%s%02X", extra, rawdata[i]);
-
-			if ((i & 0xF) == 0xF)
-				sprintf(extra, "%s\n", extra);
-			else if ((i & 0x7) == 0x7)
-				sprintf(extra, "%s\t", extra);
-			else
-				sprintf(extra, "%s ", extra);
-		}
-	} else if (strcmp(tmp[0], "mac") == 0) {
-		cnts = 6;
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr + cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		*extra = 0;
-		for (i = 0; i < cnts; i++) {
-			sprintf(extra, "%s%02X", extra, data[i]);
-			if (i != (cnts-1))
-				sprintf(extra, "%s:", extra);
-		}
-	} else if (strcmp(tmp[0], "vidpid") == 0) {
-		cnts = 4;
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr + cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-		if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		*extra = 0;
-		for (i = 0; i < cnts; i++) {
-			sprintf(extra, "%s0x%02X", extra, data[i]);
-			if (i != (cnts-1))
-				sprintf(extra, "%s,", extra);
-		}
-	} else if (strcmp(tmp[0], "ableraw") == 0) {
-		efuse_GetCurrentSize(padapter, &raw_cursize);
-		raw_maxsize = efuse_GetMaxSize(padapter);
-		sprintf(extra, "[available raw size] = %d bytes", raw_maxsize-raw_cursize);
-	} else if (strcmp(tmp[0], "btfmap") == 0) {
-		mapLen = EFUSE_BT_MAX_MAP_LEN;
-		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
-			DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		sprintf(extra, "\n");
-		for (i = 0; i < 512; i += 16) {
-			/*  set 512 because the iwpriv's extra size have limit 0x7FF */
-			sprintf(extra, "%s0x%03x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "btbmap") == 0) {
-		mapLen = EFUSE_BT_MAX_MAP_LEN;
-		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
-			DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		sprintf(extra, "\n");
-		for (i = 512; i < 1024; i += 16) {
-			sprintf(extra, "%s0x%03x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->BTEfuseInitMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "btrmap") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		/*  rmap addr cnts */
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-
-		cnts = simple_strtoul(tmp[2], &ptmp, 10);
-		if (cnts == 0) {
-			DBG_88E("%s: btrmap Fail!! cnts error!\n", __func__);
-			err = -EINVAL;
-			goto exit;
-		}
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr + cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
-			DBG_88E("%s: rtw_BT_efuse_map_read error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		*extra = 0;
-		for (i = 0; i < cnts; i++)
-			sprintf(extra, "%s 0x%02X ", extra, data[i]);
-	} else if (strcmp(tmp[0], "btffake") == 0) {
-		sprintf(extra, "\n");
-		for (i = 0; i < 512; i += 16) {
-			sprintf(extra, "%s0x%03x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "btbfake") == 0) {
-		sprintf(extra, "\n");
-		for (i = 512; i < 1024; i += 16) {
-			sprintf(extra, "%s0x%03x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else if (strcmp(tmp[0], "wlrfkmap") == 0) {
-		sprintf(extra, "\n");
-		for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
-			sprintf(extra, "%s0x%02x\t", extra, i);
-			for (j = 0; j < 8; j++)
-				sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\t", extra);
-			for (; j < 16; j++)
-				sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
-			sprintf(extra, "%s\n", extra);
-		}
-	} else {
-		 sprintf(extra, "Command not found!");
-	}
-
-exit:
-	kfree(data);
-	kfree(rawdata);
-	if (!err)
-		wrqu->length = strlen(extra);
-
-	rtw_pm_set_ips(padapter, ips_mode);
-	rtw_pm_set_lps(padapter, lps_mode);
-	padapter->registrypriv.fw_iol = org_fw_iol;/*  0:Disable, 1:enable, 2:by usb speed */
-	return err;
-}
-
-static int rtw_mp_efuse_set(struct net_device *dev,
-			struct iw_request_info *info,
-			union iwreq_data *wdata, char *extra)
-{
-	struct adapter *padapter;
-	struct pwrctrl_priv *pwrctrlpriv;
-	struct hal_data_8188e *haldata;
-	struct efuse_hal *pEfuseHal;
-
-	u8 ips_mode = 0, lps_mode = 0;
-	u32 i, jj, kk;
-	u8 *setdata = NULL;
-	u8 *ShadowMapBT = NULL;
-	u8 *ShadowMapWiFi = NULL;
-	u8 *setrawdata = NULL;
-	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
-	u16 addr = 0, cnts = 0, max_available_size = 0;
-	int err;
-
-	padapter = rtw_netdev_priv(dev);
-	pwrctrlpriv = &padapter->pwrctrlpriv;
-	haldata = GET_HAL_DATA(padapter);
-	pEfuseHal = &haldata->EfuseHal;
-	err = 0;
-	setdata = _rtw_zmalloc(1024);
-	if (setdata == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-	ShadowMapBT = _rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
-	if (ShadowMapBT == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-	ShadowMapWiFi = _rtw_malloc(EFUSE_MAP_SIZE);
-	if (ShadowMapWiFi == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-	setrawdata = _rtw_malloc(EFUSE_MAX_SIZE);
-	if (setrawdata == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
-	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
-
-	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
-	rtw_pm_set_ips(padapter, IPS_NONE);
-
-	pch = extra;
-	DBG_88E("%s: in =%s\n", __func__, extra);
-
-	i = 0;
-	while ((token = strsep(&pch, ",")) != NULL) {
-		if (i > 2)
-			break;
-		tmp[i] = token;
-		i++;
-	}
-
-	/*  tmp[0],[1],[2] */
-	/*  wmap, addr, 00e04c871200 */
-	if (strcmp(tmp[0], "wmap") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		addr &= 0xFFF;
-
-		cnts = strlen(tmp[2]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: map data =%s\n", __func__, tmp[2]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
-		if ((addr+cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "wraw") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		addr &= 0xFFF;
-
-		cnts = strlen(tmp[2]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: raw data =%s\n", __func__, tmp[2]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-
-		if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "mac") == 0) {
-		if (tmp[1] == NULL) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		/* mac, 00e04c871200 */
-		addr = EEPROM_MAC_ADDR_88EU;
-		cnts = strlen(tmp[1]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-		if (cnts > 6) {
-			DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
-		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
-		if ((addr+cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "vidpid") == 0) {
-		if (tmp[1] == NULL) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		/*  pidvid, da0b7881 */
-		addr = EEPROM_VID_88EE;
-		cnts = strlen(tmp[1]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr+cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "btwmap") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		addr &= 0xFFF;
-
-		cnts = strlen(tmp[2]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: BT data =%s\n", __func__, tmp[2]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if ((addr+cnts) > max_available_size) {
-			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
-			DBG_88E("%s: rtw_BT_efuse_map_write error!!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "btwfake") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		addr &= 0xFFF;
-
-		cnts = strlen(tmp[2]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-	} else if (strcmp(tmp[0], "btdumpfake") == 0) {
-		if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) {
-			DBG_88E("%s: BT read all map success\n", __func__);
-		} else {
-			DBG_88E("%s: BT read all map Fail!\n", __func__);
-			err = -EFAULT;
-		}
-	} else if (strcmp(tmp[0], "wldumpfake") == 0) {
-		if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN,  pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
-			DBG_88E("%s: BT read all map success\n", __func__);
-		} else {
-			DBG_88E("%s: BT read all map  Fail\n", __func__);
-			err = -EFAULT;
-		}
-	} else if (strcmp(tmp[0], "btfk2map") == 0) {
-		memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
-
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if (max_available_size < 1) {
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
-			DBG_88E("%s: rtw_BT_efuse_map_write error!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "wlfk2map") == 0) {
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if (max_available_size < 1) {
-			err = -EFAULT;
-			goto exit;
-		}
-
-		if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
-			DBG_88E("%s: rtw_efuse_map_write error!\n", __func__);
-			err = -EFAULT;
-			goto exit;
-		}
-	} else if (strcmp(tmp[0], "wlwfake") == 0) {
-		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		addr = simple_strtoul(tmp[1], &ptmp, 16);
-		addr &= 0xFFF;
-
-		cnts = strlen(tmp[2]);
-		if (cnts%2) {
-			err = -EINVAL;
-			goto exit;
-		}
-		cnts /= 2;
-		if (cnts == 0) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		DBG_88E("%s: addr = 0x%X\n", __func__, addr);
-		DBG_88E("%s: cnts =%d\n", __func__, cnts);
-		DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]);
-
-		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
-			pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-	}
-
-exit:
-	kfree(setdata);
-	kfree(ShadowMapBT);
-	kfree(ShadowMapWiFi);
-	kfree(setrawdata);
-
-	rtw_pm_set_ips(padapter, ips_mode);
-	rtw_pm_set_lps(padapter, lps_mode);
-
-	return err;
-}
-
-/*
- * Input Format: %s,%d,%d
- *	%s is width, could be
- *		"b" for 1 byte
- *		"w" for WORD (2 bytes)
- *		"dw" for DWORD (4 bytes)
- *	1st %d is address(offset)
- *	2st %d is data to write
- */
-static int rtw_mp_write_reg(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	char *pch, *pnext, *ptmp;
-	char *width_str;
-	char width;
-	u32 addr, data;
-	int ret;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	pch = extra;
-	pnext = strpbrk(pch, ",.-");
-	if (pnext == NULL)
-		return -EINVAL;
-	*pnext = 0;
-	width_str = pch;
-
-	pch = pnext + 1;
-	pnext = strpbrk(pch, ",.-");
-	if (pnext == NULL)
-		return -EINVAL;
-	*pnext = 0;
-	addr = simple_strtoul(pch, &ptmp, 16);
-	if (addr > 0x3FFF)
-		return -EINVAL;
-
-	pch = pnext + 1;
-	if ((pch - extra) >= wrqu->length)
-		return -EINVAL;
-	data = simple_strtoul(pch, &ptmp, 16);
-
-	ret = 0;
-	width = width_str[0];
-	switch (width) {
-	case 'b':
-		/*  1 byte */
-		if (data > 0xFF) {
-			ret = -EINVAL;
-			break;
-		}
-		rtw_write8(padapter, addr, data);
-		break;
-	case 'w':
-		/*  2 bytes */
-		if (data > 0xFFFF) {
-			ret = -EINVAL;
-			break;
-		}
-		rtw_write16(padapter, addr, data);
-		break;
-	case 'd':
-		/*  4 bytes */
-		rtw_write32(padapter, addr, data);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * Input Format: %s,%d
- *	%s is width, could be
- *		"b" for 1 byte
- *		"w" for WORD (2 bytes)
- *		"dw" for DWORD (4 bytes)
- *	%d is address(offset)
- *
- * Return:
- *	%d for data readed
- */
-static int rtw_mp_read_reg(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	char *pch, *pnext, *ptmp;
-	char *width_str;
-	char width;
-	char data[20], tmp[20];
-	u32 addr;
-	u32 ret, i = 0, j = 0, strtout = 0;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	_rtw_memset(data, 0, 20);
-	_rtw_memset(tmp, 0, 20);
-	_rtw_memset(extra, 0, wrqu->length);
-
-	pch = input;
-	pnext = strpbrk(pch, ",.-");
-	if (pnext == NULL) {
-		kfree(input);
-		return -EINVAL;
-	}
-	*pnext = 0;
-	width_str = pch;
-
-	pch = pnext + 1;
-	if ((pch - input) >= wrqu->length) {
-		kfree(input);
-		return -EINVAL;
-	}
-	kfree(input);
-	addr = simple_strtoul(pch, &ptmp, 16);
-	if (addr > 0x3FFF)
-		return -EINVAL;
-
-	ret = 0;
-	width = width_str[0];
-	switch (width) {
-	case 'b':
-		/*  1 byte */
-		sprintf(extra, "%d\n",  rtw_read8(padapter, addr));
-		wrqu->length = strlen(extra);
-		break;
-	case 'w':
-		/*  2 bytes */
-		sprintf(data, "%04x\n", rtw_read16(padapter, addr));
-		for (i = 0; i <= strlen(data); i++) {
-			if (i%2 == 0) {
-				tmp[j] = ' ';
-				j++;
-			}
-			if (data[i] != '\0')
-				tmp[j] = data[i];
-			j++;
-		}
-		pch = tmp;
-		DBG_88E("pch =%s", pch);
-
-		while (*pch != '\0') {
-			pnext = strpbrk(pch, " ");
-			if (!pnext)
-				break;
-
-			pnext++;
-			if (*pnext != '\0') {
-				  strtout = simple_strtoul(pnext, &ptmp, 16);
-				  sprintf(extra, "%s %d", extra, strtout);
-			} else {
-				  break;
-			}
-			pch = pnext;
-		}
-		wrqu->length = 6;
-		break;
-	case 'd':
-		/*  4 bytes */
-		sprintf(data, "%08x", rtw_read32(padapter, addr));
-		/* add read data format blank */
-		for (i = 0; i <= strlen(data); i++) {
-			if (i%2 == 0) {
-				tmp[j] = ' ';
-				j++;
-			}
-			if (data[i] != '\0')
-				tmp[j] = data[i];
-
-			j++;
-		}
-		pch = tmp;
-		DBG_88E("pch =%s", pch);
-
-		while (*pch != '\0') {
-			pnext = strpbrk(pch, " ");
-			if (!pnext)
-				break;
-			pnext++;
-			if (*pnext != '\0') {
-				strtout = simple_strtoul(pnext, &ptmp, 16);
-				sprintf(extra, "%s %d", extra, strtout);
-			} else {
-				break;
-			}
-			pch = pnext;
-		}
-		wrqu->length = strlen(extra);
-		break;
-	default:
-		wrqu->length = 0;
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * Input Format: %d,%x,%x
- *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
- *	1st %x is address(offset)
- *	2st %x is data to write
- */
- static int rtw_mp_write_rf(struct net_device *dev,
-			    struct iw_request_info *info,
-			    struct iw_point *wrqu, char *extra)
-{
-	u32 path, addr, data;
-	int ret;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
-	if (ret < 3)
-		return -EINVAL;
-
-	if (path >= MAX_RF_PATH_NUMS)
-		return -EINVAL;
-	if (addr > 0xFF)
-		return -EINVAL;
-	if (data > 0xFFFFF)
-		return -EINVAL;
-
-	_rtw_memset(extra, 0, wrqu->length);
-
-	write_rfreg(padapter, path, addr, data);
-
-	sprintf(extra, "write_rf completed\n");
-	wrqu->length = strlen(extra);
-
-	return 0;
-}
-
-/*
- * Input Format: %d,%x
- *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
- *	%x is address(offset)
- *
- * Return:
- *	%d for data readed
- */
-static int rtw_mp_read_rf(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	char *pch, *pnext, *ptmp;
-	char data[20], tmp[20];
-	u32 path, addr;
-	u32 ret, i = 0, j = 0, strtou = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	ret = sscanf(input, "%d,%x", &path, &addr);
-	kfree(input);
-	if (ret < 2)
-		return -EINVAL;
-
-	if (path >= MAX_RF_PATH_NUMS)
-		return -EINVAL;
-	if (addr > 0xFF)
-		return -EINVAL;
-
-	_rtw_memset(extra, 0, wrqu->length);
-
-	sprintf(data, "%08x", read_rfreg(padapter, path, addr));
-	/* add read data format blank */
-	for (i = 0; i <= strlen(data); i++) {
-		if (i%2 == 0) {
-			tmp[j] = ' ';
-			j++;
-		}
-		tmp[j] = data[i];
-		j++;
-	}
-	pch = tmp;
-	DBG_88E("pch =%s", pch);
-
-	while (*pch != '\0') {
-		pnext = strpbrk(pch, " ");
-		pnext++;
-		if (*pnext != '\0') {
-			  strtou = simple_strtoul(pnext, &ptmp, 16);
-			  sprintf(extra, "%s %d", extra, strtou);
-		} else {
-			  break;
-		}
-		pch = pnext;
-	}
-	wrqu->length = strlen(extra);
-	return 0;
-}
-
-static int rtw_mp_start(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (padapter->registrypriv.mp_mode == 0) {
-		padapter->registrypriv.mp_mode = 1;
-
-		rtw_pm_set_ips(padapter, IPS_NONE);
-		LeaveAllPowerSaveMode(padapter);
-
-		MPT_InitializeAdapter(padapter, 1);
-	}
-	if (padapter->registrypriv.mp_mode == 0)
-		return -EPERM;
-	if (padapter->mppriv.mode == MP_OFF) {
-		if (mp_start_test(padapter) == _FAIL)
-			return -EPERM;
-		padapter->mppriv.mode = MP_ON;
-	}
-	return 0;
-}
-
-static int rtw_mp_stop(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (padapter->registrypriv.mp_mode == 1) {
-		MPT_DeInitAdapter(padapter);
-		padapter->registrypriv.mp_mode = 0;
-	}
-
-	if (padapter->mppriv.mode != MP_OFF) {
-		mp_stop_test(padapter);
-		padapter->mppriv.mode = MP_OFF;
-	}
-
-	return 0;
-}
-
-extern int wifirate2_ratetbl_inx(unsigned char rate);
-
-static int rtw_mp_rate(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u32 rate = MPT_RATE_1M;
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	rate = rtw_atoi(input);
-	sprintf(extra, "Set data rate to %d", rate);
-	kfree(input);
-	if (rate <= 0x7f)
-		rate = wifirate2_ratetbl_inx((u8)rate);
-	else
-		rate = (rate-0x80+MPT_RATE_MCS0);
-
-	if (rate >= MPT_RATE_LAST)
-		return -EINVAL;
-
-	padapter->mppriv.rateidx = rate;
-	Hal_SetDataRate(padapter);
-
-	wrqu->length = strlen(extra) + 1;
-	return 0;
-}
-
-static int rtw_mp_channel(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	u32	channel = 1;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	channel = rtw_atoi(input);
-	sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel);
-
-	padapter->mppriv.channel = channel;
-	Hal_SetChannel(padapter);
-
-	wrqu->length = strlen(extra) + 1;
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_bandwidth(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u32 bandwidth = 0, sg = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	int rv;
-
-	rv = sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg);
-	if (rv != 2)
-		return -EINVAL;
-
-	if (bandwidth != HT_CHANNEL_WIDTH_40)
-		bandwidth = HT_CHANNEL_WIDTH_20;
-
-	padapter->mppriv.bandwidth = (u8)bandwidth;
-	padapter->mppriv.preamble = sg;
-
-	SetBandwidth(padapter);
-
-	return 0;
-}
-
-static int rtw_mp_txpower(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u32		idx_a = 0, idx_b = 0;
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	int rv;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	rv = sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b);
-	if (rv != 2) {
-		kfree(input);
-		return -EINVAL;
-	}
-
-	sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b);
-	padapter->mppriv.txpoweridx = (u8)idx_a;
-	padapter->mppriv.txpoweridx_b = (u8)idx_b;
-	padapter->mppriv.bSetTxPower = 1;
-	Hal_SetAntennaPathPower(padapter);
-
-	wrqu->length = strlen(extra) + 1;
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_ant_tx(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u8 i;
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	u16 antenna = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-
-	sprintf(extra, "switch Tx antenna to %s", input);
-
-	for (i = 0; i < strlen(input); i++) {
-		switch (input[i]) {
-		case 'a':
-			antenna |= ANTENNA_A;
-			break;
-		case 'b':
-			antenna |= ANTENNA_B;
-			break;
-		}
-	}
-	padapter->mppriv.antenna_tx = antenna;
-
-	Hal_SetAntenna(padapter);
-
-	wrqu->length = strlen(extra) + 1;
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_ant_rx(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u8 i;
-	u16 antenna = 0;
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	_rtw_memset(extra, 0, wrqu->length);
-
-	sprintf(extra, "switch Rx antenna to %s", input);
-
-	for (i = 0; i < strlen(input); i++) {
-		switch (input[i]) {
-		case 'a':
-			antenna |= ANTENNA_A;
-			break;
-		case 'b':
-			antenna |= ANTENNA_B;
-			break;
-		}
-	}
-
-	padapter->mppriv.antenna_rx = antenna;
-	Hal_SetAntenna(padapter);
-	wrqu->length = strlen(extra);
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_ctx(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
-	u32 bStartTest = 1;
-	u32 count = 0;
-	int rv;
-	struct mp_priv *pmp_priv;
-	struct pkt_attrib *pattrib;
-
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	pmp_priv = &padapter->mppriv;
-
-	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
-			return -EFAULT;
-
-	DBG_88E("%s: in =%s\n", __func__, extra);
-
-	countPkTx = strncmp(extra, "count=", 6); /*  strncmp true is 0 */
-	cotuTx = strncmp(extra, "background", 20);
-	CarrSprTx = strncmp(extra, "background, cs", 20);
-	scTx = strncmp(extra, "background, sc", 20);
-	sgleTx = strncmp(extra, "background, stone", 20);
-	pkTx = strncmp(extra, "background, pkt", 20);
-	stop = strncmp(extra, "stop", 4);
-	rv = sscanf(extra, "count =%d, pkt", &count);
-	if (rv != 2)
-		return -EINVAL;
-
-	_rtw_memset(extra, '\0', sizeof(*extra));
-
-	if (stop == 0) {
-		bStartTest = 0; /*  To set Stop */
-		pmp_priv->tx.stop = 1;
-		sprintf(extra, "Stop continuous Tx");
-	} else {
-		bStartTest = 1;
-		if (pmp_priv->mode != MP_ON) {
-			if (pmp_priv->tx.stop != 1) {
-				DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
-				return  -EFAULT;
-			}
-		}
-	}
-
-	if (pkTx == 0 || countPkTx == 0)
-		pmp_priv->mode = MP_PACKET_TX;
-	if (sgleTx == 0)
-		pmp_priv->mode = MP_SINGLE_TONE_TX;
-	if (cotuTx == 0)
-		pmp_priv->mode = MP_CONTINUOUS_TX;
-	if (CarrSprTx == 0)
-		pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
-	if (scTx == 0)
-		pmp_priv->mode = MP_SINGLE_CARRIER_TX;
-
-	switch (pmp_priv->mode) {
-	case MP_PACKET_TX:
-		if (bStartTest == 0) {
-			pmp_priv->tx.stop = 1;
-			pmp_priv->mode = MP_ON;
-			sprintf(extra, "Stop continuous Tx");
-		} else if (pmp_priv->tx.stop == 1) {
-			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count);
-			pmp_priv->tx.stop = 0;
-			pmp_priv->tx.count = count;
-			pmp_priv->tx.payload = 2;
-			pattrib = &pmp_priv->tx.attrib;
-			pattrib->pktlen = 1500;
-			_rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
-			SetPacketTx(padapter);
-		} else {
-			return -EFAULT;
-		}
-			wrqu->length = strlen(extra);
-			return 0;
-	case MP_SINGLE_TONE_TX:
-		if (bStartTest != 0)
-			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
-		Hal_SetSingleToneTx(padapter, (u8)bStartTest);
-		break;
-	case MP_CONTINUOUS_TX:
-		if (bStartTest != 0)
-			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
-		Hal_SetContinuousTx(padapter, (u8)bStartTest);
-		break;
-	case MP_CARRIER_SUPPRISSION_TX:
-		if (bStartTest != 0) {
-			if (pmp_priv->rateidx <= MPT_RATE_11M) {
-				sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
-				Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
-			} else {
-				sprintf(extra, "Specify carrier suppression but not CCK rate");
-			}
-		}
-		break;
-	case MP_SINGLE_CARRIER_TX:
-		if (bStartTest != 0)
-			sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
-		Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
-		break;
-	default:
-		sprintf(extra, "Error! Continuous-Tx is not on-going.");
-		return -EFAULT;
-	}
-
-	if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
-		struct mp_priv *pmp_priv = &padapter->mppriv;
-		if (pmp_priv->tx.stop == 0) {
-			pmp_priv->tx.stop = 1;
-			msleep(5);
-		}
-		pmp_priv->tx.stop = 0;
-		pmp_priv->tx.count = 1;
-		SetPacketTx(padapter);
-	} else {
-		pmp_priv->mode = MP_ON;
-	}
-
-	wrqu->length = strlen(extra);
-	return 0;
-}
-
-static int rtw_mp_arx(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u8 bStartRx = 0, bStopRx = 0, bQueryPhy;
-	u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0;
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (!input)
-		return -ENOMEM;
-
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-	DBG_88E("%s: %s\n", __func__, input);
-
-	bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
-	bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /*  strncmp true is 0 */
-	bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /*  strncmp true is 0 */
-
-	if (bStartRx) {
-		sprintf(extra, "start");
-		SetPacketRx(padapter, bStartRx);
-	} else if (bStopRx) {
-		SetPacketRx(padapter, 0);
-		sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount);
-	} else if (bQueryPhy) {
-		/*
-		OFDM FA
-		RegCF0[15:0]
-		RegCF2[31:16]
-		RegDA0[31:16]
-		RegDA4[15:0]
-		RegDA4[31:16]
-		RegDA8[15:0]
-		CCK FA
-		(RegA5B<<8) | RegA5C
-		*/
-		cckok = read_bbreg(padapter, 0xf88, 0xffffffff);
-		cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff);
-		ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF);
-		ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000);
-		htok = read_bbreg(padapter, 0xf90, 0x0000FFFF);
-		htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000);
-
-		OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF);
-		OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000);
-		OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000);
-		OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF);
-		OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000);
-		OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF);
-		CCK_FA = (rtw_read8(padapter, 0xa5b)<<8) | (rtw_read8(padapter, 0xa5c));
-
-		sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok+ofdmok+htok, cckcrc+ofdmcrc+htcrc, OFDM_FA+CCK_FA);
-	}
-	wrqu->length = strlen(extra) + 1;
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_trx_query(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u32 txok, txfail, rxok, rxfail;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	txok = padapter->mppriv.tx.sended;
-	txfail = 0;
-	rxok = padapter->mppriv.rx_pktcount;
-	rxfail = padapter->mppriv.rx_crcerrpktcount;
-
-	_rtw_memset(extra, '\0', 128);
-
-	sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail);
-
-	wrqu->length = strlen(extra)+1;
-
-	return 0;
-}
-
-static int rtw_mp_pwrtrk(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	u8 enable;
-	u32 thermal;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	int ret = 0;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-	_rtw_memset(extra, 0, wrqu->length);
-
-	enable = 1;
-	if (wrqu->length > 1) {/*  not empty string */
-		if (strncmp(input, "stop", 4) == 0) {
-			enable = 0;
-			sprintf(extra, "mp tx power tracking stop");
-		} else if (sscanf(input, "ther =%d", &thermal)) {
-				ret = Hal_SetThermalMeter(padapter, (u8)thermal);
-				if (ret == _FAIL) {
-					ret = -EPERM;
-					goto exit;
-				}
-				sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal);
-		} else {
-			ret = -EINVAL;
-			goto exit;
-		}
-	}
-
-	ret = Hal_SetPowerTracking(padapter, enable);
-	if (ret == _FAIL) {
-		ret = -EPERM;
-		goto exit;
-	}
-
-	wrqu->length = strlen(extra);
-
-exit:
-	kfree(input);
-	return ret;
-}
-
-static int rtw_mp_psd(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-
-	strcpy(extra, input);
-
-	wrqu->length = mp_query_psd(padapter, extra);
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_thermal(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *wrqu, char *extra)
-{
-	u8 val;
-	u16 bwrite = 1;
-	u16 addr = EEPROM_THERMAL_METER_88E;
-
-	u16 cnt = 1;
-	u16 max_available_size = 0;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
-		return -EFAULT;
-
-	bwrite = strncmp(extra, "write", 6); /*  strncmp true is 0 */
-
-	Hal_GetThermalMeter(padapter, &val);
-
-	if (bwrite == 0) {
-		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
-		if (2 > max_available_size) {
-			DBG_88E("no available efuse!\n");
-			return -EFAULT;
-		}
-		if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
-			DBG_88E("rtw_efuse_map_write error\n");
-			return -EFAULT;
-		} else {
-			 sprintf(extra, " efuse write ok :%d", val);
-		}
-	} else {
-		 sprintf(extra, "%d", val);
-	}
-	wrqu->length = strlen(extra);
-
-	return 0;
-}
-
-static int rtw_mp_reset_stats(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	struct mp_priv *pmp_priv;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	pmp_priv = &padapter->mppriv;
-
-	pmp_priv->tx.sended = 0;
-	pmp_priv->tx_pktcount = 0;
-	pmp_priv->rx_pktcount = 0;
-	pmp_priv->rx_crcerrpktcount = 0;
-
-	/* reset phy counter */
-	write_bbreg(padapter, 0xf14, BIT16, 0x1);
-	msleep(10);
-	write_bbreg(padapter, 0xf14, BIT16, 0x0);
-
-	return 0;
-}
-
-static int rtw_mp_dump(struct net_device *dev,
-		       struct iw_request_info *info,
-		       struct iw_point *wrqu, char *extra)
-{
-	u32 value;
-	u8 rf_type, path_nums = 0;
-	u32 i, j = 1, path;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (strncmp(extra, "all", 4) == 0) {
-		DBG_88E("\n ======= MAC REG =======\n");
-		for (i = 0x0; i < 0x300; i += 4) {
-			if (j%4 == 1)
-				DBG_88E("0x%02x", i);
-			DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
-			if ((j++)%4 == 0)
-				DBG_88E("\n");
-		}
-		for (i = 0x400; i < 0x1000; i += 4) {
-			if (j%4 == 1)
-				DBG_88E("0x%02x", i);
-			DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
-			if ((j++)%4 == 0)
-				DBG_88E("\n");
-		}
-
-		j = 1;
-		rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
-		DBG_88E("\n ======= RF REG =======\n");
-		if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
-			path_nums = 1;
-		else
-			path_nums = 2;
-
-		for (path = 0; path < path_nums; path++) {
-			for (i = 0; i < 0x34; i++) {
-				value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
-				if (j%4 == 1)
-					DBG_88E("0x%02x ", i);
-				DBG_88E(" 0x%08x ", value);
-				if ((j++)%4 == 0)
-					DBG_88E("\n");
-			}
-		}
-	}
-	return 0;
-}
-
-static int rtw_mp_phypara(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrqu, char *extra)
-{
-	char	*input = kmalloc(wrqu->length, GFP_KERNEL);
-	u32		valxcap;
-	int rv;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
-		kfree(input);
-		return -EFAULT;
-	}
-
-	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
-
-	rv = sscanf(input, "xcap =%d", &valxcap);
-	if (rv != 1) {
-		kfree(input);
-		return -EINVAL;
-	}
-
-	kfree(input);
-	return 0;
-}
-
-static int rtw_mp_SetRFPath(struct net_device *dev,
-			struct iw_request_info *info,
-			union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->data.length, GFP_KERNEL);
-	u8 bMain = 1, bTurnoff = 1;
-	int ret = 0;
-
-	if (!input)
-		return -ENOMEM;
-	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
-
-	bMain = strncmp(input, "1", 2); /*  strncmp true is 0 */
-	bTurnoff = strncmp(input, "0", 3); /*  strncmp true is 0 */
-
-	if (bMain == 0) {
-		MP_PHY_SetRFPathSwitch(padapter, true);
-		DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__);
-	} else if (bTurnoff == 0) {
-		MP_PHY_SetRFPathSwitch(padapter, false);
-		DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__);
-	}
-
-exit:
-	kfree(input);
-	return ret;
-}
-
-static int rtw_mp_QueryDrv(struct net_device *dev,
-			struct iw_request_info *info,
-			union iwreq_data *wrqu, char *extra)
-{
-	struct adapter *padapter = rtw_netdev_priv(dev);
-	char	*input = kmalloc(wrqu->data.length, GFP_KERNEL);
-	u8 qAutoLoad = 1;
-	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-	int ret = 0;
-
-	if (!input)
-		return -ENOMEM;
-
-	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-	DBG_88E("%s:iwpriv in =%s\n", __func__, input);
-
-	qAutoLoad = strncmp(input, "autoload", 8); /*  strncmp true is 0 */
-
-	if (qAutoLoad == 0) {
-		DBG_88E("%s:qAutoLoad\n", __func__);
-
-		if (pEEPROM->bautoload_fail_flag)
-			sprintf(extra, "fail");
-		else
-		sprintf(extra, "ok");
-	}
-	wrqu->data.length = strlen(extra) + 1;
-
-exit:
-	kfree(input);
-	return ret;
-}
-
-static int rtw_mp_set(struct net_device *dev,
-		      struct iw_request_info *info,
-		      union iwreq_data *wdata, char *extra)
-{
-	struct iw_point *wrqu = (struct iw_point *)wdata;
-	u32 subcmd = wrqu->flags;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (padapter == NULL)
-		return -ENETDOWN;
-
-	if (extra == NULL) {
-		wrqu->length = 0;
-		return -EIO;
-	}
-
-	switch (subcmd) {
-	case MP_START:
-		DBG_88E("set case mp_start\n");
-		rtw_mp_start(dev, info, wrqu, extra);
-		 break;
-	case MP_STOP:
-		DBG_88E("set case mp_stop\n");
-		rtw_mp_stop(dev, info, wrqu, extra);
-		 break;
-	case MP_BANDWIDTH:
-		DBG_88E("set case mp_bandwidth\n");
-		rtw_mp_bandwidth(dev, info, wrqu, extra);
-		break;
-	case MP_RESET_STATS:
-		DBG_88E("set case MP_RESET_STATS\n");
-		rtw_mp_reset_stats(dev, info, wrqu, extra);
-		break;
-	case MP_SetRFPathSwh:
-		DBG_88E("set MP_SetRFPathSwitch\n");
-		rtw_mp_SetRFPath(dev, info, wdata, extra);
-		break;
-	case CTA_TEST:
-		DBG_88E("set CTA_TEST\n");
-		rtw_cta_test_start(dev, info, wdata, extra);
-		break;
-	}
-
-	return 0;
-}
-
-static int rtw_mp_get(struct net_device *dev,
-			struct iw_request_info *info,
-			union iwreq_data *wdata, char *extra)
-{
-	struct iw_point *wrqu = (struct iw_point *)wdata;
-	u32 subcmd = wrqu->flags;
-	struct adapter *padapter = rtw_netdev_priv(dev);
-
-	if (padapter == NULL)
-		return -ENETDOWN;
-	if (extra == NULL) {
-		wrqu->length = 0;
-		return -EIO;
-	}
-
-	switch (subcmd) {
-	case WRITE_REG:
-		rtw_mp_write_reg(dev, info, wrqu, extra);
-		 break;
-	case WRITE_RF:
-		rtw_mp_write_rf(dev, info, wrqu, extra);
-		 break;
-	case MP_PHYPARA:
-		DBG_88E("mp_get  MP_PHYPARA\n");
-		rtw_mp_phypara(dev, info, wrqu, extra);
-		break;
-	case MP_CHANNEL:
-		DBG_88E("set case mp_channel\n");
-		rtw_mp_channel(dev, info, wrqu, extra);
-		break;
-	case READ_REG:
-		DBG_88E("mp_get  READ_REG\n");
-		rtw_mp_read_reg(dev, info, wrqu, extra);
-		 break;
-	case READ_RF:
-		DBG_88E("mp_get  READ_RF\n");
-		rtw_mp_read_rf(dev, info, wrqu, extra);
-		break;
-	case MP_RATE:
-		DBG_88E("set case mp_rate\n");
-		rtw_mp_rate(dev, info, wrqu, extra);
-		break;
-	case MP_TXPOWER:
-		DBG_88E("set case MP_TXPOWER\n");
-		rtw_mp_txpower(dev, info, wrqu, extra);
-		break;
-	case MP_ANT_TX:
-		DBG_88E("set case MP_ANT_TX\n");
-		rtw_mp_ant_tx(dev, info, wrqu, extra);
-		break;
-	case MP_ANT_RX:
-		DBG_88E("set case MP_ANT_RX\n");
-		rtw_mp_ant_rx(dev, info, wrqu, extra);
-		break;
-	case MP_QUERY:
-		rtw_mp_trx_query(dev, info, wrqu, extra);
-		break;
-	case MP_CTX:
-		DBG_88E("set case MP_CTX\n");
-		rtw_mp_ctx(dev, info, wrqu, extra);
-		break;
-	case MP_ARX:
-		DBG_88E("set case MP_ARX\n");
-		rtw_mp_arx(dev, info, wrqu, extra);
-		break;
-	case EFUSE_GET:
-		DBG_88E("efuse get EFUSE_GET\n");
-		rtw_mp_efuse_get(dev, info, wdata, extra);
-		 break;
-	case MP_DUMP:
-		DBG_88E("set case MP_DUMP\n");
-		rtw_mp_dump(dev, info, wrqu, extra);
-		 break;
-	case MP_PSD:
-		DBG_88E("set case MP_PSD\n");
-		rtw_mp_psd(dev, info, wrqu, extra);
-		break;
-	case MP_THER:
-		DBG_88E("set case MP_THER\n");
-		rtw_mp_thermal(dev, info, wrqu, extra);
-		break;
-	case MP_QueryDrvStats:
-		DBG_88E("mp_get MP_QueryDrvStats\n");
-		rtw_mp_QueryDrv (dev, info, wdata, extra);
-		break;
-	case MP_PWRTRK:
-		DBG_88E("set case MP_PWRTRK\n");
-		rtw_mp_pwrtrk(dev, info, wrqu, extra);
-		break;
-	case EFUSE_SET:
-		DBG_88E("set case efuse set\n");
-		rtw_mp_efuse_set(dev, info, wdata, extra);
-		break;
-	}
-
-	msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */
-	return 0;
-}
-
-static int rtw_tdls(struct net_device *dev,
-		    struct iw_request_info *info,
-		    union iwreq_data *wrqu, char *extra)
-{
-	return 0;
-}
-
-static int rtw_tdls_get(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	return 0;
-}
-
-static int rtw_test(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu, char *extra)
-{
-	u32 len;
-	u8 *pbuf, *pch;
-	char *ptmp;
-	u8 *delim = ",";
-
-	DBG_88E("+%s\n", __func__);
-	len = wrqu->data.length;
-
-	pbuf = (u8 *)rtw_zmalloc(len);
-	if (pbuf == NULL) {
-		DBG_88E("%s: no memory!\n", __func__);
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
-		kfree(pbuf);
-		DBG_88E("%s: copy from user fail!\n", __func__);
-		return -EFAULT;
-	}
-	DBG_88E("%s: string =\"%s\"\n", __func__, pbuf);
-
-	ptmp = (char *)pbuf;
-	pch = strsep(&ptmp, delim);
-	if ((pch == NULL) || (strlen(pch) == 0)) {
-		kfree(pbuf);
-		DBG_88E("%s: parameter error(level 1)!\n", __func__);
-		return -EFAULT;
-	}
-	kfree(pbuf);
-	return 0;
-}
-
 static iw_handler rtw_handlers[] = {
 	NULL,					/* SIOCSIWCOMMIT */
 	rtw_wx_get_name,		/* SIOCGIWNAME */
@@ -7644,175 +3075,6 @@ static iw_handler rtw_handlers[] = {
 	NULL,					/*---hole---*/
 };
 
-static const struct iw_priv_args rtw_private_args[] = {
-	{
-		SIOCIWFIRSTPRIV + 0x0,
-		IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x1,
-		IW_PRIV_TYPE_CHAR | 0x7FF,
-		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x4,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x5,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x6,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x7,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x8,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x9,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
-	},
-
-	{
-		SIOCIWFIRSTPRIV + 0xA,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
-	},
-
-	{
-		SIOCIWFIRSTPRIV + 0xB,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xC,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xD,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x10,
-		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x11,
-		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x12,
-		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
-	},
-	{SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"},
-	{
-		SIOCIWFIRSTPRIV + 0x14,
-		IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x15,
-		IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x16,
-		IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
-	},
-
-	{SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
-
-	{SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
-	{SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
-	{SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
-	},
-
-	{SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""},  /* set */
-	{SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */
-/* --- sub-ioctls definitions --- */
-
-	{MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */
-	{MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */
-	{MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */
-	{MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */
-	{MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */
-	{MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */
-	{MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
-	{MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */
-	{READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"},
-	{MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},
-	{READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"},
-	{MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
-	{MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"},
-	{MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
-	{MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
-	{MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
-	{WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"},
-	{WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"},
-	{MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
-	{MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
-	{MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
-	{EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"},
-	{EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
-	{MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
-	{MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"},
-	{MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /*  mp_ioctl */
-	{MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"},
-	{CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
-};
-
-static iw_handler rtw_private_handler[] = {
-rtw_wx_write32,				/* 0x00 */
-rtw_wx_read32,				/* 0x01 */
-rtw_drvext_hdl,				/* 0x02 */
-rtw_mp_ioctl_hdl,			/* 0x03 */
-
-/*  for MM DTV platform */
-	rtw_get_ap_info,		/* 0x04 */
-
-	rtw_set_pid,			/* 0x05 */
-	rtw_wps_start,			/* 0x06 */
-
-	rtw_wx_get_sensitivity,		/* 0x07 */
-	rtw_wx_set_mtk_wps_probe_ie,	/* 0x08 */
-	rtw_wx_set_mtk_wps_ie,		/* 0x09 */
-
-/*  Set Channel depend on the country code */
-	rtw_wx_set_channel_plan,	/* 0x0A */
-
-	rtw_dbg_port,			/* 0x0B */
-	rtw_wx_write_rf,		/* 0x0C */
-	rtw_wx_read_rf,			/* 0x0D */
-
-	rtw_mp_set,			/* 0x0E */
-	rtw_mp_get,			/* 0x0F */
-	rtw_p2p_set,			/* 0x10 */
-	rtw_p2p_get,			/* 0x11 */
-	rtw_p2p_get2,			/* 0x12 */
-
-	NULL,				/* 0x13 */
-	rtw_tdls,			/* 0x14 */
-	rtw_tdls_get,			/* 0x15 */
-
-	rtw_pm_set,			/* 0x16 */
-	rtw_wx_priv_null,		/* 0x17 */
-	rtw_rereg_nd_name,		/* 0x18 */
-	rtw_wx_priv_null,		/* 0x19 */
-
-	rtw_mp_efuse_set,		/* 0x1A */
-	rtw_mp_efuse_get,		/* 0x1B */
-	NULL,				/*  0x1C is reserved for hostapd */
-	rtw_test,			/*  0x1D */
-};
-
 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
 {
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
@@ -7841,347 +3103,9 @@ static struct iw_statistics *rtw_get_wir
 struct iw_handler_def rtw_handlers_def = {
 	.standard = rtw_handlers,
 	.num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
-	.private = rtw_private_handler,
-	.private_args = (struct iw_priv_args *)rtw_private_args,
-	.num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
-	.num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
 	.get_wireless_stats = rtw_get_wireless_stats,
 };
 
-/*  copy from net/wireless/wext.c start */
-/* ---------------------------------------------------------------- */
-/*
- * Calculate size of private arguments
- */
-static const char iw_priv_type_size[] = {
-	0,			      /* IW_PRIV_TYPE_NONE */
-	1,			      /* IW_PRIV_TYPE_BYTE */
-	1,			      /* IW_PRIV_TYPE_CHAR */
-	0,			      /* Not defined */
-	sizeof(__u32),		  /* IW_PRIV_TYPE_INT */
-	sizeof(struct iw_freq),	 /* IW_PRIV_TYPE_FLOAT */
-	sizeof(struct sockaddr),	/* IW_PRIV_TYPE_ADDR */
-	0,			      /* Not defined */
-};
-
-static int get_priv_size(__u16 args)
-{
-	int num = args & IW_PRIV_SIZE_MASK;
-	int type = (args & IW_PRIV_TYPE_MASK) >> 12;
-
-	return num * iw_priv_type_size[type];
-}
-/*  copy from net/wireless/wext.c end */
-
-static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
-{
-	int err = 0;
-	u8 *input = NULL;
-	u32 input_len = 0;
-	const char delim[] = " ";
-	u8 *output = NULL;
-	u32 output_len = 0;
-	u32 count = 0;
-	u8 *buffer = NULL;
-	u32 buffer_len = 0;
-	char *ptr = NULL;
-	u8 cmdname[17] = {0}; /*  IFNAMSIZ+1 */
-	u32 cmdlen;
-	s32 len;
-	u8 *extra = NULL;
-	u32 extra_size = 0;
-	int rv;
-
-	s32 k;
-	const iw_handler *priv;		/* Private ioctl */
-	const struct iw_priv_args *priv_args;	/* Private ioctl description */
-	u32 num_priv_args;			/* Number of descriptions */
-	iw_handler handler;
-	int temp;
-	int subcmd = 0;				/* sub-ioctl index */
-	int offset = 0;				/* Space for sub-ioctl index */
-
-	union iwreq_data wdata;
-
-	memcpy(&wdata, wrq_data, sizeof(wdata));
-
-	input_len = wdata.data.length;
-	input = rtw_zmalloc(input_len);
-	if (NULL == input)
-		return -ENOMEM;
-	if (copy_from_user(input, wdata.data.pointer, input_len)) {
-		err = -EFAULT;
-		goto exit;
-	}
-	ptr = input;
-	len = input_len;
-
-	rv = sscanf(ptr, "%16s", cmdname);
-	if (rv != 1) {
-		err = -EINVAL;
-		goto exit;
-	}
-	cmdlen = strlen(cmdname);
-	DBG_88E("%s: cmd =%s\n", __func__, cmdname);
-
-	/*  skip command string */
-	if (cmdlen > 0)
-		cmdlen += 1; /*  skip one space */
-	ptr += cmdlen;
-	len -= cmdlen;
-	DBG_88E("%s: parameters =%s\n", __func__, ptr);
-
-	priv = rtw_private_handler;
-	priv_args = rtw_private_args;
-	num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
-
-	if (num_priv_args == 0) {
-		err = -EOPNOTSUPP;
-		goto exit;
-	}
-
-	/* Search the correct ioctl */
-	k = -1;
-	while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
-
-	/* If not found... */
-	if (k == num_priv_args) {
-		err = -EOPNOTSUPP;
-		goto exit;
-	}
-
-	/* Watch out for sub-ioctls ! */
-	if (priv_args[k].cmd < SIOCDEVPRIVATE) {
-		int j = -1;
-
-		/* Find the matching *real* ioctl */
-		while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
-			(priv_args[j].set_args != priv_args[k].set_args) ||
-			(priv_args[j].get_args != priv_args[k].get_args)));
-
-		/* If not found... */
-		if (j == num_priv_args) {
-			err = -EINVAL;
-			goto exit;
-		}
-
-		/* Save sub-ioctl number */
-		subcmd = priv_args[k].cmd;
-		/* Reserve one int (simplify alignment issues) */
-		offset = sizeof(__u32);
-		/* Use real ioctl definition from now on */
-		k = j;
-	}
-
-	buffer = rtw_zmalloc(4096);
-	if (NULL == buffer) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	/* If we have to set some data */
-	if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
-	    (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
-		u8 *str;
-
-		switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
-		case IW_PRIV_TYPE_BYTE:
-			/* Fetch args */
-			count = 0;
-			do {
-				str = strsep(&ptr, delim);
-				if (NULL == str)
-					break;
-				sscanf(str, "%i", &temp);
-				buffer[count++] = (u8)temp;
-			} while (1);
-			buffer_len = count;
-			/* Number of args to fetch */
-			wdata.data.length = count;
-			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
-				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-			break;
-		case IW_PRIV_TYPE_INT:
-			/* Fetch args */
-			count = 0;
-			do {
-				str = strsep(&ptr, delim);
-				if (NULL == str)
-					break;
-				sscanf(str, "%i", &temp);
-				((s32 *)buffer)[count++] = (s32)temp;
-			} while (1);
-			buffer_len = count * sizeof(s32);
-			/* Number of args to fetch */
-			wdata.data.length = count;
-			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
-				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-			break;
-		case IW_PRIV_TYPE_CHAR:
-			if (len > 0) {
-				/* Size of the string to fetch */
-				wdata.data.length = len;
-				if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
-					wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-
-				/* Fetch string */
-				memcpy(buffer, ptr, wdata.data.length);
-			} else {
-				wdata.data.length = 1;
-				buffer[0] = '\0';
-			}
-			buffer_len = wdata.data.length;
-			break;
-		default:
-			DBG_88E("%s: Not yet implemented...\n", __func__);
-			err = -1;
-			goto exit;
-		}
-
-		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
-		    (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
-			DBG_88E("%s: The command %s needs exactly %d argument(s)...\n",
-				__func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
-			err = -EINVAL;
-			goto exit;
-		}
-	} else {
-		/* if args to set */
-		wdata.data.length = 0L;
-	}
-
-	/* Those two tests are important. They define how the driver
-	* will have to handle the data */
-	if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
-	    ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
-		/* First case : all SET args fit within wrq */
-		if (offset)
-			wdata.mode = subcmd;
-		memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
-	} else {
-		if ((priv_args[k].set_args == 0) &&
-		    (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
-		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
-			/* Second case : no SET args, GET args fit within wrq */
-			if (offset)
-				wdata.mode = subcmd;
-		} else {
-			/* Third case : args won't fit in wrq, or variable number of args */
-			if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
-				err = -EFAULT;
-				goto exit;
-			}
-			wdata.data.flags = subcmd;
-		}
-	}
-
-	kfree(input);
-	input = NULL;
-
-	extra_size = 0;
-	if (IW_IS_SET(priv_args[k].cmd)) {
-		/* Size of set arguments */
-		extra_size = get_priv_size(priv_args[k].set_args);
-
-		/* Does it fits in iwr ? */
-		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
-		    ((extra_size + offset) <= IFNAMSIZ))
-			extra_size = 0;
-	} else {
-		/* Size of get arguments */
-		extra_size = get_priv_size(priv_args[k].get_args);
-
-		/* Does it fits in iwr ? */
-		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
-		    (extra_size <= IFNAMSIZ))
-			extra_size = 0;
-	}
-
-	if (extra_size == 0) {
-		extra = (u8 *)&wdata;
-		kfree(buffer);
-		buffer = NULL;
-	} else {
-		extra = buffer;
-	}
-
-	handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
-	err = handler(dev, NULL, &wdata, extra);
-
-	/* If we have to get some data */
-	if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
-	    (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
-		int j;
-		int n = 0;	/* number of args */
-		u8 str[20] = {0};
-
-		/* Check where is the returned data */
-		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
-		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
-			n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
-		else
-			n = wdata.data.length;
-
-		output = rtw_zmalloc(4096);
-		if (NULL == output) {
-			err =  -ENOMEM;
-			goto exit;
-		}
-		switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
-		case IW_PRIV_TYPE_BYTE:
-			/* Display args */
-			for (j = 0; j < n; j++) {
-				sprintf(str, "%d  ", extra[j]);
-				len = strlen(str);
-				output_len = strlen(output);
-				if ((output_len + len + 1) > 4096) {
-					err = -E2BIG;
-					goto exit;
-				}
-				memcpy(output+output_len, str, len);
-			}
-			break;
-		case IW_PRIV_TYPE_INT:
-			/* Display args */
-			for (j = 0; j < n; j++) {
-				sprintf(str, "%d  ", ((__s32 *)extra)[j]);
-				len = strlen(str);
-				output_len = strlen(output);
-				if ((output_len + len + 1) > 4096) {
-					err = -E2BIG;
-					goto exit;
-				}
-				memcpy(output+output_len, str, len);
-			}
-			break;
-		case IW_PRIV_TYPE_CHAR:
-			/* Display args */
-			memcpy(output, extra, n);
-			break;
-		default:
-			DBG_88E("%s: Not yet implemented...\n", __func__);
-			err = -1;
-			goto exit;
-		}
-
-		output_len = strlen(output) + 1;
-		wrq_data->data.length = output_len;
-		if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
-			err = -EFAULT;
-			goto exit;
-		}
-	} else {
-		/* if args to set */
-		wrq_data->data.length = 0;
-	}
-
-exit:
-	kfree(input);
-	kfree(buffer);
-	kfree(output);
-	return err;
-}
-
 #include <rtw_android.h>
 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -8197,9 +3121,6 @@ int rtw_ioctl(struct net_device *dev, st
 		ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
 		break;
 #endif /*  CONFIG_88EU_AP_MODE */
-	case SIOCDEVPRIVATE:
-		ret = rtw_ioctl_wext_private(dev, &wrq->u);
-		break;
 	case (SIOCDEVPRIVATE+1):
 		ret = rtw_android_priv_cmd(dev, rq, cmd);
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/mlme_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/mlme_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/mlme_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -25,38 +25,13 @@
 #include <drv_types.h>
 #include <mlme_osdep.h>
 
-void rtw_join_timeout_handler (void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-
-	_rtw_join_timeout_handler(adapter);
-}
-
-
-void _rtw_scan_timeout_handler (void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-
-	rtw_scan_timeout_handler(adapter);
-}
-
-static void _dynamic_check_timer_handlder(void *FunctionContext)
-{
-	struct adapter *adapter = (struct adapter *)FunctionContext;
-
-	if (adapter->registrypriv.mp_mode == 1)
-		return;
-	rtw_dynamic_check_timer_handlder(adapter);
-	_set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
-}
-
 void rtw_init_mlme_timer(struct adapter *padapter)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-	_init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, rtw_join_timeout_handler, padapter);
-	_init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, _rtw_scan_timeout_handler, padapter);
-	_init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, _dynamic_check_timer_handlder, padapter);
+	_init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, _rtw_join_timeout_handler, padapter);
+	_init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, rtw_scan_timeout_handler, padapter);
+	_init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, rtw_dynamic_check_timer_handlder, padapter);
 }
 
 void rtw_os_indicate_connect(struct adapter *adapter)
@@ -85,12 +60,12 @@ void rtw_reset_securitypriv(struct adapt
 		/*  We have to backup the PMK information for WiFi PMK Caching test item. */
 		/*  Backup the btkip_countermeasure information. */
 		/*  When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */
-		_rtw_memset(&backup_pmkid[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+		memset(&backup_pmkid[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
 		memcpy(&backup_pmkid[0], &adapter->securitypriv.PMKIDList[0], sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
 		backup_index = adapter->securitypriv.PMKIDIndex;
 		backup_counter = adapter->securitypriv.btkip_countermeasure;
 		backup_time = adapter->securitypriv.btkip_countermeasure_time;
-		_rtw_memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv));
+		memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv));
 
 		/*  Restore the PMK information to securitypriv structure for the following connection. */
 		memcpy(&adapter->securitypriv.PMKIDList[0],
@@ -137,7 +112,7 @@ void rtw_report_sec_ie(struct adapter *a
 		buff = rtw_malloc(IW_CUSTOM_MAX);
 		if (!buff)
 			return;
-		_rtw_memset(buff, 0, IW_CUSTOM_MAX);
+		memset(buff, 0, IW_CUSTOM_MAX);
 		p = buff;
 		p += sprintf(p, "ASSOCINFO(ReqIEs =");
 		len = sec_ie[1]+2;
@@ -145,7 +120,7 @@ void rtw_report_sec_ie(struct adapter *a
 		for (i = 0; i < len; i++)
 			p += sprintf(p, "%02x", sec_ie[i]);
 		p += sprintf(p, ")");
-		_rtw_memset(&wrqu, 0, sizeof(wrqu));
+		memset(&wrqu, 0, sizeof(wrqu));
 		wrqu.data.length = p-buff;
 		wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
 				   wrqu.data.length : IW_CUSTOM_MAX;
@@ -154,36 +129,17 @@ void rtw_report_sec_ie(struct adapter *a
 	}
 }
 
-static void _survey_timer_hdl(void *FunctionContext)
-{
-	struct adapter *padapter = (struct adapter *)FunctionContext;
-
-	survey_timer_hdl(padapter);
-}
-
-static void _link_timer_hdl(void *FunctionContext)
-{
-	struct adapter *padapter = (struct adapter *)FunctionContext;
-	link_timer_hdl(padapter);
-}
-
-static void _addba_timer_hdl(void *FunctionContext)
-{
-	struct sta_info *psta = (struct sta_info *)FunctionContext;
-	addba_timer_hdl(psta);
-}
-
 void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
 {
-	_init_timer(&psta->addba_retry_timer, padapter->pnetdev, _addba_timer_hdl, psta);
+	_init_timer(&psta->addba_retry_timer, padapter->pnetdev, addba_timer_hdl, psta);
 }
 
 void init_mlme_ext_timer(struct adapter *padapter)
 {
 	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
-	_init_timer(&pmlmeext->survey_timer, padapter->pnetdev, _survey_timer_hdl, padapter);
-	_init_timer(&pmlmeext->link_timer, padapter->pnetdev, _link_timer_hdl, padapter);
+	_init_timer(&pmlmeext->survey_timer, padapter->pnetdev, survey_timer_hdl, padapter);
+	_init_timer(&pmlmeext->link_timer, padapter->pnetdev, link_timer_hdl, padapter);
 }
 
 #ifdef CONFIG_88EU_AP_MODE
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/osdep_service.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/osdep_service.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/osdep_service.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/osdep_service.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,6 +22,7 @@
 #define _OSDEP_SERVICE_C_
 
 #include <osdep_service.h>
+#include <osdep_intf.h>
 #include <drv_types.h>
 #include <recv_osdep.h>
 #include <linux/vmalloc.h>
@@ -38,23 +39,6 @@ inline int RTW_STATUS_CODE(int error_cod
 	return _FAIL;
 }
 
-u32 rtw_atoi(u8 *s)
-{
-	int num = 0, flag = 0;
-	int i;
-	for (i = 0; i <= strlen(s); i++) {
-		if (s[i] >= '0' && s[i] <= '9')
-			num = num * 10 + s[i] - '0';
-		else if (s[0] == '-' && i == 0)
-			flag = 1;
-		else
-			break;
-	}
-	if (flag == 1)
-		num = num * -1;
-	return num;
-}
-
 u8 *_rtw_malloc(u32 sz)
 {
 	u8	*pbuf = NULL;
@@ -63,20 +47,11 @@ u8 *_rtw_malloc(u32 sz)
 	return pbuf;
 }
 
-u8 *_rtw_zmalloc(u32 sz)
-{
-	u8	*pbuf = _rtw_malloc(sz);
-
-	if (pbuf != NULL)
-		memset(pbuf, 0, sz);
-	return pbuf;
-}
-
 void *rtw_malloc2d(int h, int w, int size)
 {
 	int j;
 
-	void **a = (void **)rtw_zmalloc(h*sizeof(void *) + h*w*size);
+	void **a = (void **)kzalloc(h*sizeof(void *) + h*w*size, GFP_KERNEL);
 	if (a == NULL) {
 		pr_info("%s: alloc memory fail!\n", __func__);
 		return NULL;
@@ -88,48 +63,6 @@ void *rtw_malloc2d(int h, int w, int siz
 	return a;
 }
 
-void rtw_mfree2d(void *pbuf, int h, int w, int size)
-{
-	kfree(pbuf);
-}
-
-void _rtw_memset(void *pbuf, int c, u32 sz)
-{
-	memset(pbuf, c, sz);
-}
-
-void _rtw_init_listhead(struct list_head *list)
-{
-	INIT_LIST_HEAD(list);
-}
-
-/*
-For the following list_xxx operations,
-caller must guarantee the atomic context.
-Otherwise, there will be racing condition.
-*/
-u32	rtw_is_list_empty(struct list_head *phead)
-{
-	if (list_empty(phead))
-		return true;
-	else
-		return false;
-}
-
-void rtw_list_insert_head(struct list_head *plist, struct list_head *phead)
-{
-	list_add(plist, phead);
-}
-
-void rtw_list_insert_tail(struct list_head *plist, struct list_head *phead)
-{
-	list_add_tail(plist, phead);
-}
-
-/*
-Caller must check if the list is empty before calling rtw_list_delete
-*/
-
 u32 _rtw_down_sema(struct semaphore *sema)
 {
 	if (down_interruptible(sema))
@@ -140,58 +73,16 @@ u32 _rtw_down_sema(struct semaphore *sem
 
 void	_rtw_init_queue(struct __queue *pqueue)
 {
-	_rtw_init_listhead(&(pqueue->queue));
+	INIT_LIST_HEAD(&(pqueue->queue));
 	spin_lock_init(&(pqueue->lock));
 }
 
-u32	  _rtw_queue_empty(struct __queue *pqueue)
-{
-	return rtw_is_list_empty(&(pqueue->queue));
-}
-
-u32 rtw_end_of_queue_search(struct list_head *head, struct list_head *plist)
-{
-	if (head == plist)
-		return true;
-	else
-		return false;
-}
-
-inline u32 rtw_systime_to_ms(u32 systime)
-{
-	return systime * 1000 / HZ;
-}
-
-inline u32 rtw_ms_to_systime(u32 ms)
-{
-	return ms * HZ / 1000;
-}
-
 /*  the input parameter start must be in jiffies */
 inline s32 rtw_get_passing_time_ms(u32 start)
 {
-	return rtw_systime_to_ms(jiffies-start);
-}
-
-inline s32 rtw_get_time_interval_ms(u32 start, u32 end)
-{
-	return rtw_systime_to_ms(end-start);
-}
-
-void rtw_sleep_schedulable(int ms)
-{
-	u32 delta;
-
-	delta = (ms * HZ)/1000;/* ms) */
-	if (delta == 0)
-		delta = 1;/*  1 ms */
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (schedule_timeout(delta) != 0)
-		return;
+	return jiffies_to_msecs(jiffies-start);
 }
 
-#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
-
 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
 						    void *old_priv)
 {
@@ -210,29 +101,6 @@ RETURN:
 	return pnetdev;
 }
 
-struct net_device *rtw_alloc_etherdev(int sizeof_priv)
-{
-	struct net_device *pnetdev;
-	struct rtw_netdev_priv_indicator *pnpi;
-
-	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
-	if (!pnetdev)
-		goto RETURN;
-
-	pnpi = netdev_priv(pnetdev);
-
-	pnpi->priv = vzalloc(sizeof_priv);
-	if (!pnpi->priv) {
-		free_netdev(pnetdev);
-		pnetdev = NULL;
-		goto RETURN;
-	}
-
-	pnpi->sizeof_priv = sizeof_priv;
-RETURN:
-	return pnetdev;
-}
-
 void rtw_free_netdev(struct net_device *netdev)
 {
 	struct rtw_netdev_priv_indicator *pnpi;
@@ -252,72 +120,11 @@ RETURN:
 	return;
 }
 
-int rtw_change_ifname(struct adapter *padapter, const char *ifname)
-{
-	struct net_device *pnetdev;
-	struct net_device *cur_pnetdev;
-	struct rereg_nd_name_data *rereg_priv;
-	int ret;
-
-	if (!padapter)
-		goto error;
-
-	cur_pnetdev = padapter->pnetdev;
-	rereg_priv = &padapter->rereg_nd_name_priv;
-
-	/* free the old_pnetdev */
-	if (rereg_priv->old_pnetdev) {
-		free_netdev(rereg_priv->old_pnetdev);
-		rereg_priv->old_pnetdev = NULL;
-	}
-
-	if (!rtnl_is_locked())
-		unregister_netdev(cur_pnetdev);
-	else
-		unregister_netdevice(cur_pnetdev);
-
-	rtw_proc_remove_one(cur_pnetdev);
-
-	rereg_priv->old_pnetdev = cur_pnetdev;
-
-	pnetdev = rtw_init_netdev(padapter);
-	if (!pnetdev)  {
-		ret = -1;
-		goto error;
-	}
-
-	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
-
-	rtw_init_netdev_name(pnetdev, ifname);
-
-	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
-
-	if (!rtnl_is_locked())
-		ret = register_netdev(pnetdev);
-	else
-		ret = register_netdevice(pnetdev);
-	if (ret != 0) {
-		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-			 ("register_netdev() failed\n"));
-		goto error;
-	}
-	rtw_proc_init_one(pnetdev);
-	return 0;
-error:
-	return -1;
-}
-
 u64 rtw_modular64(u64 x, u64 y)
 {
 	return do_div(x, y);
 }
 
-u64 rtw_division64(u64 x, u64 y)
-{
-	do_div(x, y);
-	return x;
-}
-
 void rtw_buf_free(u8 **buf, u32 *buf_len)
 {
 	*buf_len = 0;
@@ -356,89 +163,3 @@ keep_ori:
 	/* free ori */
 	kfree(ori);
 }
-
-
-/**
- * rtw_cbuf_full - test if cbuf is full
- * @cbuf: pointer of struct rtw_cbuf
- *
- * Returns: true if cbuf is full
- */
-inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
-{
-	return (cbuf->write == cbuf->read-1) ? true : false;
-}
-
-/**
- * rtw_cbuf_empty - test if cbuf is empty
- * @cbuf: pointer of struct rtw_cbuf
- *
- * Returns: true if cbuf is empty
- */
-inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
-{
-	return (cbuf->write == cbuf->read) ? true : false;
-}
-
-/**
- * rtw_cbuf_push - push a pointer into cbuf
- * @cbuf: pointer of struct rtw_cbuf
- * @buf: pointer to push in
- *
- * Lock free operation, be careful of the use scheme
- * Returns: true push success
- */
-bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
-{
-	if (rtw_cbuf_full(cbuf))
-		return _FAIL;
-
-	if (0)
-		DBG_88E("%s on %u\n", __func__, cbuf->write);
-	cbuf->bufs[cbuf->write] = buf;
-	cbuf->write = (cbuf->write+1)%cbuf->size;
-
-	return _SUCCESS;
-}
-
-/**
- * rtw_cbuf_pop - pop a pointer from cbuf
- * @cbuf: pointer of struct rtw_cbuf
- *
- * Lock free operation, be careful of the use scheme
- * Returns: pointer popped out
- */
-void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
-{
-	void *buf;
-	if (rtw_cbuf_empty(cbuf))
-		return NULL;
-
-	if (0)
-		DBG_88E("%s on %u\n", __func__, cbuf->read);
-	buf = cbuf->bufs[cbuf->read];
-	cbuf->read = (cbuf->read+1)%cbuf->size;
-
-	return buf;
-}
-
-/**
- * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
- * @size: size of pointer
- *
- * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
- */
-struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
-{
-	struct rtw_cbuf *cbuf;
-
-	cbuf = (struct rtw_cbuf *)rtw_malloc(sizeof(*cbuf) +
-	       sizeof(void *)*size);
-
-	if (cbuf) {
-		cbuf->write = 0;
-		cbuf->read = 0;
-		cbuf->size = size;
-	}
-	return cbuf;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/os_intfs.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/os_intfs.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/os_intfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/os_intfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -20,23 +20,20 @@
 #define _OS_INTFS_C_
 
 #include <osdep_service.h>
+#include <osdep_intf.h>
 #include <drv_types.h>
 #include <xmit_osdep.h>
 #include <recv_osdep.h>
 #include <hal_intf.h>
 #include <rtw_ioctl.h>
-#include <rtw_version.h>
 
-#include <usb_osintf.h>
 #include <usb_hal.h>
-#include <rtw_br_ext.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
 MODULE_AUTHOR("Realtek Semiconductor Corp.");
 MODULE_VERSION(DRIVERVERSION);
 
-#define CONFIG_BR_EXT_BRNAME "br0"
 #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
 
 /* module param defaults */
@@ -69,8 +66,6 @@ static int rtw_short_retry_lmt = 7;
 static int rtw_busy_thresh = 40;
 static int rtw_ack_policy = NORMAL_ACK;
 
-static int rtw_mp_mode;
-
 static int rtw_software_encrypt;
 static int rtw_software_decrypt;
 
@@ -130,7 +125,6 @@ module_param(rtw_rfintfs, int, 0644);
 module_param(rtw_lbkmode, int, 0644);
 module_param(rtw_network_mode, int, 0644);
 module_param(rtw_channel, int, 0644);
-module_param(rtw_mp_mode, int, 0644);
 module_param(rtw_wmm_enable, int, 0644);
 module_param(rtw_vrtl_carrier_sense, int, 0644);
 module_param(rtw_vcs_type, int, 0644);
@@ -548,7 +542,7 @@ static uint loadparam(struct adapter *pa
 	registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
 	registry_par->busy_thresh = (u16)rtw_busy_thresh;
 	registry_par->ack_policy = (u8)rtw_ack_policy;
-	registry_par->mp_mode = (u8)rtw_mp_mode;
+	registry_par->mp_mode = 0;
 	registry_par->software_encrypt = (u8)rtw_software_encrypt;
 	registry_par->software_decrypt = (u8)rtw_software_decrypt;
 	registry_par->acm_method = (u8)rtw_acm_method;
@@ -713,14 +707,12 @@ static const struct device_type wlan_typ
 struct net_device *rtw_init_netdev(struct adapter *old_padapter)
 {
 	struct adapter *padapter;
-	struct net_device *pnetdev;
+	struct net_device *pnetdev = NULL;
 
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n"));
 
 	if (old_padapter != NULL)
 		pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(struct adapter), (void *)old_padapter);
-	else
-		pnetdev = rtw_alloc_etherdev(sizeof(struct adapter));
 
 	if (!pnetdev)
 		return NULL;
@@ -751,7 +743,6 @@ u32 rtw_start_drv_threads(struct adapter
 	else
 		_rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); /* wait for cmd_thread to run */
 
-	rtw_hal_start_thread(padapter);
 	return _status;
 }
 
@@ -764,7 +755,6 @@ void rtw_stop_drv_threads(struct adapter
 	if (padapter->cmdThread)
 		_rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema);
 
-	rtw_hal_stop_thread(padapter);
 }
 
 static u8 rtw_init_default_value(struct adapter *padapter)
@@ -812,9 +802,6 @@ static u8 rtw_init_default_value(struct
 	padapter->bWritePortCancel = false;
 	padapter->bRxRSSIDisplay = 0;
 	padapter->bNotifyChannelChange = 0;
-#ifdef CONFIG_88EU_P2P
-	padapter->bShowGetP2PState = 1;
-#endif
 	return ret;
 }
 
@@ -837,8 +824,7 @@ u8 rtw_reset_drv_sw(struct adapter *pada
 	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
 
 	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
-
-	rtw_hal_sreset_reset_value(padapter);
+	rtw_hal_sreset_init(padapter);
 	pwrctrlpriv->pwr_state_check_cnts = 0;
 
 	/* mlmeextpriv */
@@ -864,24 +850,12 @@ u8 rtw_init_drv_sw(struct adapter *padap
 
 	padapter->cmdpriv.padapter = padapter;
 
-	if ((rtw_init_evt_priv(&padapter->evtpriv)) == _FAIL) {
-		RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init evt_priv\n"));
-		ret8 = _FAIL;
-		goto exit;
-	}
-
 	if (rtw_init_mlme_priv(padapter) == _FAIL) {
 		RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_priv\n"));
 		ret8 = _FAIL;
 		goto exit;
 	}
 
-#ifdef CONFIG_88EU_P2P
-	rtw_init_wifidirect_timers(padapter);
-	init_wifidirect_info(padapter, P2P_ROLE_DISABLE);
-	reset_global_wifidirect_info(padapter);
-#endif /* CONFIG_88EU_P2P */
-
 	if (init_mlme_ext_priv(padapter) == _FAIL) {
 		RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n"));
 		ret8 = _FAIL;
@@ -912,9 +886,6 @@ u8 rtw_init_drv_sw(struct adapter *padap
 
 	rtw_init_pwrctrl_priv(padapter);
 
-	if (init_mp_priv(padapter) == _FAIL)
-		DBG_88E("%s: initialize MP private data Fail!\n", __func__);
-
 	ret8 = rtw_init_default_value(padapter);
 
 	rtw_hal_dm_init(padapter);
@@ -935,49 +906,30 @@ void rtw_cancel_all_timer(struct adapter
 {
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_cancel_all_timer\n"));
 
-	_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
+	del_timer_sync(&padapter->mlmepriv.assoc_timer);
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel association timer complete!\n"));
 
-	_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
+	del_timer_sync(&padapter->mlmepriv.scan_to_timer);
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel scan_to_timer!\n"));
 
-	_cancel_timer_ex(&padapter->mlmepriv.dynamic_chk_timer);
+	del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel dynamic_chk_timer!\n"));
 
 	/*  cancel sw led timer */
 	rtw_hal_sw_led_deinit(padapter);
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel DeInitSwLeds!\n"));
 
-	_cancel_timer_ex(&padapter->pwrctrlpriv.pwr_state_check_timer);
+	del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
 
-	_cancel_timer_ex(&padapter->recvpriv.signal_stat_timer);
+	del_timer_sync(&padapter->recvpriv.signal_stat_timer);
 }
 
 u8 rtw_free_drv_sw(struct adapter *padapter)
 {
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw"));
 
-	/* we can call rtw_p2p_enable here, but: */
-	/*  1. rtw_p2p_enable may have IO operation */
-	/*  2. rtw_p2p_enable is bundled with wext interface */
-	#ifdef CONFIG_88EU_P2P
-	{
-		struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			_cancel_timer_ex(&pwdinfo->find_phase_timer);
-			_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
-			_cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
-		}
-	}
-	#endif
-
 	free_mlme_ext_priv(&padapter->mlmeextpriv);
 
-	rtw_free_cmd_priv(&padapter->cmdpriv);
-
-	rtw_free_evt_priv(&padapter->evtpriv);
-
 	rtw_free_mlme_priv(&padapter->mlmepriv);
 	_rtw_free_xmit_priv(&padapter->xmitpriv);
 
@@ -995,40 +947,13 @@ u8 rtw_free_drv_sw(struct adapter *padap
 		padapter->rereg_nd_name_priv.old_pnetdev = NULL;
 	}
 
-	/*  clear pbuddystruct adapter to avoid access wrong pointer. */
-	if (padapter->pbuddy_adapter != NULL)
-		padapter->pbuddy_adapter->pbuddy_adapter = NULL;
+	mutex_destroy(&padapter->hw_init_mutex);
 
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw\n"));
 
 	return _SUCCESS;
 }
 
-void netdev_br_init(struct net_device *netdev)
-{
-	struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);
-
-	rcu_read_lock();
-
-	if (rcu_dereference(adapter->pnetdev->rx_handler_data)) {
-		struct net_device *br_netdev;
-		struct net *devnet = NULL;
-
-		devnet = dev_net(netdev);
-		br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
-		if (br_netdev) {
-			memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
-			dev_put(br_netdev);
-		} else {
-			pr_info("%s()-%d: dev_get_by_name(%s) failed!",
-				__func__, __LINE__, CONFIG_BR_EXT_BRNAME);
-		}
-	}
-	adapter->ethBrExtInfo.addPPPoETag = 1;
-
-	rcu_read_unlock();
-}
-
 int _netdev_open(struct net_device *pnetdev)
 {
 	uint status;
@@ -1046,7 +971,6 @@ int _netdev_open(struct net_device *pnet
 	if (!padapter->bup) {
 		padapter->bDriverStopped = false;
 		padapter->bSurpriseRemoved = false;
-		padapter->bCardDisableWOHSM = false;
 
 		status = rtw_hal_init(padapter);
 		if (status == _FAIL) {
@@ -1086,8 +1010,6 @@ int _netdev_open(struct net_device *pnet
 	else
 		netif_tx_wake_all_queues(pnetdev);
 
-	netdev_br_init(pnetdev);
-
 netdev_open_normal_process:
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - dev_open\n"));
 	DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup);
@@ -1107,9 +1029,9 @@ int netdev_open(struct net_device *pnetd
 	int ret;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
 
-	_enter_critical_mutex(padapter->hw_init_mutex, NULL);
+	_enter_critical_mutex(&padapter->hw_init_mutex, NULL);
 	ret = _netdev_open(pnetdev);
-	mutex_unlock(padapter->hw_init_mutex);
+	mutex_unlock(&padapter->hw_init_mutex);
 	return ret;
 }
 
@@ -1121,7 +1043,6 @@ static int  ips_netdrv_open(struct adapt
 
 	padapter->bDriverStopped = false;
 	padapter->bSurpriseRemoved = false;
-	padapter->bCardDisableWOHSM = false;
 
 	status = rtw_hal_init(padapter);
 	if (status == _FAIL) {
@@ -1164,13 +1085,11 @@ void rtw_ips_pwr_down(struct adapter *pa
 	u32 start_time = jiffies;
 	DBG_88E("===> rtw_ips_pwr_down...................\n");
 
-	padapter->bCardDisableWOHSM = true;
 	padapter->net_closed = true;
 
 	rtw_led_control(padapter, LED_CTL_POWER_OFF);
 
 	rtw_ips_dev_unload(padapter);
-	padapter->bCardDisableWOHSM = false;
 	DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n", rtw_get_passing_time_ms(start_time));
 }
 
@@ -1235,12 +1154,6 @@ int netdev_close(struct net_device *pnet
 		rtw_led_control(padapter, LED_CTL_POWER_OFF);
 	}
 
-	nat25_db_cleanup(padapter);
-
-#ifdef CONFIG_88EU_P2P
-	rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
-#endif /* CONFIG_88EU_P2P */
-
 	kfree(dvobj->firmware.szFwBuffer);
 	dvobj->firmware.szFwBuffer = NULL;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/recv_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/recv_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/recv_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/recv_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,7 @@
 #include <recv_osdep.h>
 
 #include <osdep_intf.h>
-#include <usb_ops.h>
+#include <usb_ops_linux.h>
 
 /* alloc os related resource in struct recv_frame */
 int rtw_os_recv_resource_alloc(struct adapter *padapter,
@@ -73,7 +73,7 @@ void rtw_handle_tkip_mic_err(struct adap
 		}
 	}
 
-	_rtw_memset(&ev, 0x00, sizeof(ev));
+	memset(&ev, 0x00, sizeof(ev));
 	if (bgroup)
 		ev.flags |= IW_MICFAILURE_GROUP;
 	else
@@ -81,7 +81,7 @@ void rtw_handle_tkip_mic_err(struct adap
 
 	ev.src_addr.sa_family = ARPHRD_ETHER;
 	memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
-	_rtw_memset(&wrqu, 0x00, sizeof(wrqu));
+	memset(&wrqu, 0x00, sizeof(wrqu));
 	wrqu.data.length = sizeof(ev);
 	wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE,
 			    &wrqu, (char *)&ev);
@@ -191,29 +191,9 @@ _recv_indicatepkt_drop:
 	 return _FAIL;
 }
 
-void rtw_os_read_port(struct adapter *padapter, struct recv_buf *precvbuf)
-{
-	struct recv_priv *precvpriv = &padapter->recvpriv;
-
-	/* free skb in recv_buf */
-	dev_kfree_skb_any(precvbuf->pskb);
-	precvbuf->pskb = NULL;
-	precvbuf->reuse = false;
-	rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
-			(unsigned char *)precvbuf);
-}
-
-static void _rtw_reordering_ctrl_timeout_handler(void *func_context)
-{
-	struct recv_reorder_ctrl *preorder_ctrl;
-
-	preorder_ctrl = (struct recv_reorder_ctrl *)func_context;
-	rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
-}
-
 void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
 {
 	struct adapter *padapter = preorder_ctrl->padapter;
 
-	_init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
+	_init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/usb_intf.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/usb_intf.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/usb_intf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/usb_intf.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,27 +24,16 @@
 #include <recv_osdep.h>
 #include <xmit_osdep.h>
 #include <hal_intf.h>
-#include <rtw_version.h>
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
 #include <osdep_intf.h>
 
-#include <usb_vendor_req.h>
-#include <usb_ops.h>
-#include <usb_osintf.h>
+#include <usb_ops_linux.h>
 #include <usb_hal.h>
 #include <rtw_ioctl.h>
 
 int ui_pid[3] = {0, 0, 0};
 
-static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
-static int rtw_resume(struct usb_interface *intf);
-
-
-static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid);
-static void rtw_dev_remove(struct usb_interface *pusb_intf);
-
-
 #define USB_VENDER_ID_REALTEK		0x0bda
 
 /* DID_USB_v916_20130116 */
@@ -54,58 +43,16 @@ static struct usb_device_id rtw_usb_id_t
 	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
 	/*=== Customer ID ===*/
 	/****** 8188EUS ********/
+	{USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */
 	{USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
 	{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
 	{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
+	{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
 	{}	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
 
-struct rtw_usb_drv {
-	struct usb_driver usbdrv;
-	int drv_registered;
-	struct mutex hw_init_mutex;
-};
-
-static struct rtw_usb_drv rtl8188e_usb_drv = {
-	.usbdrv.name = "r8188eu",
-	.usbdrv.probe = rtw_drv_init,
-	.usbdrv.disconnect = rtw_dev_remove,
-	.usbdrv.id_table = rtw_usb_id_tbl,
-	.usbdrv.suspend =  rtw_suspend,
-	.usbdrv.resume = rtw_resume,
-	.usbdrv.reset_resume   = rtw_resume,
-};
-
-static struct rtw_usb_drv *usb_drv = &rtl8188e_usb_drv;
-
-static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
-{
-	u8 rst = _SUCCESS;
-
-	mutex_init(&dvobj->usb_vendor_req_mutex);
-
-	dvobj->usb_alloc_vendor_req_buf = rtw_zmalloc(MAX_USB_IO_CTL_SIZE);
-	if (dvobj->usb_alloc_vendor_req_buf == NULL) {
-		DBG_88E("alloc usb_vendor_req_buf failed...\n");
-		rst = _FAIL;
-		goto exit;
-	}
-	dvobj->usb_vendor_req_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(dvobj->usb_alloc_vendor_req_buf), ALIGNMENT_UNIT);
-exit:
-	return rst;
-}
-
-static u8 rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
-{
-	u8 rst = _SUCCESS;
-
-	kfree(dvobj->usb_alloc_vendor_req_buf);
-	mutex_destroy(&dvobj->usb_vendor_req_mutex);
-	return rst;
-}
-
 static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
 {
 	int	i;
@@ -120,7 +67,7 @@ static struct dvobj_priv *usb_dvobj_init
 	struct usb_device	*pusbd;
 
 
-	pdvobjpriv = (struct dvobj_priv *)rtw_zmalloc(sizeof(*pdvobjpriv));
+	pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
 	if (pdvobjpriv == NULL)
 		goto exit;
 
@@ -169,11 +116,11 @@ static struct dvobj_priv *usb_dvobj_init
 	else
 		pdvobjpriv->ishighspeed = false;
 
-	if (rtw_init_intf_priv(pdvobjpriv) == _FAIL)
-		goto free_dvobj;
+	mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
+	pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL);
 
-	sema_init(&(pdvobjpriv->usb_suspend_sema), 0);
-	rtw_reset_continual_urb_error(pdvobjpriv);
+	if (!pdvobjpriv->usb_vendor_req_buf)
+		goto free_dvobj;
 
 	usb_get_dev(pusbd);
 
@@ -211,7 +158,9 @@ static void usb_dvobj_deinit(struct usb_
 				usb_reset_device(interface_to_usbdev(usb_intf));
 			}
 		}
-		rtw_deinit_intf_priv(dvobj);
+
+		kfree(dvobj->usb_vendor_req_buf);
+		mutex_destroy(&dvobj->usb_vendor_req_mutex);
 		kfree(dvobj);
 	}
 
@@ -244,7 +193,7 @@ static void usb_intf_stop(struct adapter
 	rtw_hal_inirp_deinit(padapter);
 
 	/* cancel out irp */
-	rtw_write_port_cancel(padapter);
+	usb_write_port_cancel(padapter);
 
 	/* todo:cancel other irps */
 
@@ -284,108 +233,6 @@ static void rtw_dev_unload(struct adapte
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
 }
 
-int rtw_hw_suspend(struct adapter *padapter)
-{
-	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-	struct net_device *pnetdev = padapter->pnetdev;
-
-
-	if ((!padapter->bup) || (padapter->bDriverStopped) ||
-	    (padapter->bSurpriseRemoved)) {
-		DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
-			padapter->bup, padapter->bDriverStopped,
-			padapter->bSurpriseRemoved);
-		goto error_exit;
-	}
-
-	/* system suspend */
-	LeaveAllPowerSaveMode(padapter);
-
-	DBG_88E("==> rtw_hw_suspend\n");
-	_enter_pwrlock(&pwrpriv->lock);
-	pwrpriv->bips_processing = true;
-	/* s1. */
-	if (pnetdev) {
-		netif_carrier_off(pnetdev);
-		netif_tx_stop_all_queues(pnetdev);
-	}
-
-	/* s2. */
-	rtw_disassoc_cmd(padapter, 500, false);
-
-	/* s2-2.  indicate disconnect to os */
-	{
-		struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
-			_clr_fwstate_(pmlmepriv, _FW_LINKED);
-
-			rtw_led_control(padapter, LED_CTL_NO_LINK);
-
-			rtw_os_indicate_disconnect(padapter);
-
-			/* donnot enqueue cmd */
-			rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
-		}
-	}
-	/* s2-3. */
-	rtw_free_assoc_resources(padapter, 1);
-
-	/* s2-4. */
-	rtw_free_network_queue(padapter, true);
-	rtw_ips_dev_unload(padapter);
-	pwrpriv->rf_pwrstate = rf_off;
-	pwrpriv->bips_processing = false;
-
-	_exit_pwrlock(&pwrpriv->lock);
-
-	return 0;
-
-error_exit:
-	DBG_88E("%s, failed\n", __func__);
-	return -1;
-}
-
-int rtw_hw_resume(struct adapter *padapter)
-{
-	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-	struct net_device *pnetdev = padapter->pnetdev;
-
-
-	/* system resume */
-	DBG_88E("==> rtw_hw_resume\n");
-	_enter_pwrlock(&pwrpriv->lock);
-	pwrpriv->bips_processing = true;
-	rtw_reset_drv_sw(padapter);
-
-	if (pm_netdev_open(pnetdev, false) != 0) {
-		_exit_pwrlock(&pwrpriv->lock);
-		goto error_exit;
-	}
-
-	netif_device_attach(pnetdev);
-	netif_carrier_on(pnetdev);
-
-	if (!netif_queue_stopped(pnetdev))
-		netif_start_queue(pnetdev);
-	else
-		netif_wake_queue(pnetdev);
-
-	pwrpriv->bkeepfwalive = false;
-	pwrpriv->brfoffbyhw = false;
-
-	pwrpriv->rf_pwrstate = rf_on;
-	pwrpriv->bips_processing = false;
-
-	_exit_pwrlock(&pwrpriv->lock);
-
-
-	return 0;
-error_exit:
-	DBG_88E("%s, Open net dev failed\n", __func__);
-	return -1;
-}
-
 static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
 {
 	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
@@ -456,21 +303,7 @@ exit:
 	return ret;
 }
 
-static int rtw_resume(struct usb_interface *pusb_intf)
-{
-	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
-	struct adapter *padapter = dvobj->if1;
-	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-	 int ret = 0;
-
-	if (pwrpriv->bInternalAutoSuspend)
-		ret = rtw_resume_process(padapter);
-	else
-		ret = rtw_resume_process(padapter);
-	return ret;
-}
-
-int rtw_resume_process(struct adapter *padapter)
+static int rtw_resume_process(struct adapter *padapter)
 {
 	struct net_device *pnetdev;
 	struct pwrctrl_priv *pwrpriv = NULL;
@@ -517,6 +350,14 @@ exit:
 	return ret;
 }
 
+static int rtw_resume(struct usb_interface *pusb_intf)
+{
+	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+	struct adapter *padapter = dvobj->if1;
+
+	return rtw_resume_process(padapter);
+}
+
 /*
  * drv_init() - a device potentially for us
  *
@@ -539,7 +380,7 @@ static struct adapter *rtw_usb_if1_init(
 	dvobj->if1 = padapter;
 
 	padapter->bDriverStopped = true;
-	padapter->hw_init_mutex = &usb_drv->hw_init_mutex;
+	mutex_init(&padapter->hw_init_mutex);
 	padapter->chip_type = RTL8188E;
 
 	pnetdev = rtw_init_netdev(padapter);
@@ -554,9 +395,6 @@ static struct adapter *rtw_usb_if1_init(
 	padapter->intf_start = &usb_intf_start;
 	padapter->intf_stop = &usb_intf_stop;
 
-	/* step init_io_priv */
-	rtw_init_io_priv(padapter, usb_set_intf_ops);
-
 	/* step read_chip_version */
 	rtw_hal_read_chip_version(padapter);
 
@@ -592,10 +430,6 @@ static struct adapter *rtw_usb_if1_init(
 	/*  alloc dev name after read efuse. */
 	rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
 	rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
-#ifdef CONFIG_88EU_P2P
-	rtw_init_wifidirect_addrs(padapter, padapter->eeprompriv.mac_addr,
-				  padapter->eeprompriv.mac_addr);
-#endif
 	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
 	DBG_88E("MAC Address from pnetdev->dev_addr =  %pM\n",
 		pnetdev->dev_addr);
@@ -642,12 +476,10 @@ static void rtw_usb_if1_deinit(struct ad
 	free_mlme_ap_info(if1);
 #endif
 
-	if (if1->DriverState != DRIVER_DISAPPEAR) {
-		if (pnetdev) {
-			/* will call netdev_close() */
-			unregister_netdev(pnetdev);
-			rtw_proc_remove_one(pnetdev);
-		}
+	if (pnetdev) {
+		/* will call netdev_close() */
+		unregister_netdev(pnetdev);
+		rtw_proc_remove_one(pnetdev);
 	}
 	rtw_cancel_all_timer(if1);
 
@@ -710,7 +542,7 @@ static void rtw_dev_remove(struct usb_in
 	DBG_88E("+rtw_dev_remove\n");
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
 
-	if (usb_drv->drv_registered)
+	if (!pusb_intf->unregistering)
 		padapter->bSurpriseRemoved = true;
 
 	rtw_pm_set_ips(padapter, IPS_NONE);
@@ -728,29 +560,14 @@ static void rtw_dev_remove(struct usb_in
 	return;
 }
 
-static int __init rtw_drv_entry(void)
-{
-	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
-
-	DBG_88E(DRV_NAME " driver version=%s\n", DRIVERVERSION);
-
-	mutex_init(&usb_drv->hw_init_mutex);
-
-	usb_drv->drv_registered = true;
-	return usb_register(&usb_drv->usbdrv);
-}
-
-static void __exit rtw_drv_halt(void)
-{
-	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
-	DBG_88E("+rtw_drv_halt\n");
-
-	usb_drv->drv_registered = false;
-	usb_deregister(&usb_drv->usbdrv);
-
-	mutex_destroy(&usb_drv->hw_init_mutex);
-	DBG_88E("-rtw_drv_halt\n");
-}
+static struct usb_driver rtl8188e_usb_drv = {
+	.name = "r8188eu",
+	.probe = rtw_drv_init,
+	.disconnect = rtw_dev_remove,
+	.id_table = rtw_usb_id_tbl,
+	.suspend =  rtw_suspend,
+	.resume = rtw_resume,
+	.reset_resume = rtw_resume,
+};
 
-module_init(rtw_drv_entry);
-module_exit(rtw_drv_halt);
+module_usb_driver(rtl8188e_usb_drv)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,9 +19,197 @@
 #define _USB_OPS_LINUX_C_
 
 #include <drv_types.h>
-#include <usb_ops_linux.h>
+#include <recv_osdep.h>
 #include <rtw_sreset.h>
 
+static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
+{
+	struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
+
+	if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
+		DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
+		return;
+	}
+
+	/*  HISR */
+	memcpy(&(haldata->IntArray[0]), &(pbuf[USB_INTR_CONTENT_HISR_OFFSET]), 4);
+	memcpy(&(haldata->IntArray[1]), &(pbuf[USB_INTR_CONTENT_HISRE_OFFSET]), 4);
+
+	/*  C2H Event */
+	if (pbuf[0] != 0)
+		memcpy(&(haldata->C2hArray[0]), &(pbuf[USB_INTR_CONTENT_C2H_OFFSET]), 16);
+}
+
+static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
+{
+	u8	*pbuf;
+	u8	shift_sz = 0;
+	u16	pkt_cnt;
+	u32	pkt_offset, skb_len, alloc_sz;
+	s32	transfer_len;
+	struct recv_stat	*prxstat;
+	struct phy_stat	*pphy_status = NULL;
+	struct sk_buff *pkt_copy = NULL;
+	struct recv_frame	*precvframe = NULL;
+	struct rx_pkt_attrib	*pattrib = NULL;
+	struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
+	struct recv_priv	*precvpriv = &adapt->recvpriv;
+	struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
+
+	transfer_len = (s32)pskb->len;
+	pbuf = pskb->data;
+
+	prxstat = (struct recv_stat *)pbuf;
+	pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+
+	do {
+		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+			 ("recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
+			  prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
+
+		prxstat = (struct recv_stat *)pbuf;
+
+		precvframe = rtw_alloc_recvframe(pfree_recv_queue);
+		if (precvframe == NULL) {
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvbuf2recvframe: precvframe==NULL\n"));
+			DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
+			goto _exit_recvbuf2recvframe;
+		}
+
+		INIT_LIST_HEAD(&precvframe->list);
+		precvframe->len = 0;
+
+		update_recvframe_attrib_88e(precvframe, prxstat);
+
+		pattrib = &precvframe->attrib;
+
+		if ((pattrib->crc_err) || (pattrib->icv_err)) {
+			DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
+
+			rtw_free_recvframe(precvframe, pfree_recv_queue);
+			goto _exit_recvbuf2recvframe;
+		}
+
+		if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
+			pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
+
+		pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
+
+		if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recvbuf2recvframe: pkt_len<=0\n"));
+			DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len\n", __func__, __LINE__);
+			rtw_free_recvframe(precvframe, pfree_recv_queue);
+			goto _exit_recvbuf2recvframe;
+		}
+
+		/*	Modified by Albert 20101213 */
+		/*	For 8 bytes IP header alignment. */
+		if (pattrib->qos)	/*	Qos data, wireless lan header length is 26 */
+			shift_sz = 6;
+		else
+			shift_sz = 0;
+
+		skb_len = pattrib->pkt_len;
+
+		/*  for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
+		/*  modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
+		if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+			if (skb_len <= 1650)
+				alloc_sz = 1664;
+			else
+				alloc_sz = skb_len + 14;
+		} else {
+			alloc_sz = skb_len;
+			/*	6 is for IP header 8 bytes alignment in QoS packet case. */
+			/*	8 is for skb->data 4 bytes alignment. */
+			alloc_sz += 14;
+		}
+
+		pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
+		if (pkt_copy) {
+			pkt_copy->dev = adapt->pnetdev;
+			precvframe->pkt = pkt_copy;
+			precvframe->rx_head = pkt_copy->data;
+			precvframe->rx_end = pkt_copy->data + alloc_sz;
+			skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
+			skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
+			memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
+			precvframe->rx_tail = pkt_copy->data;
+			precvframe->rx_data = pkt_copy->data;
+		} else {
+			if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+				DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
+				rtw_free_recvframe(precvframe, pfree_recv_queue);
+				goto _exit_recvbuf2recvframe;
+			}
+			precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
+			if (precvframe->pkt) {
+				precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
+				precvframe->rx_head = precvframe->rx_tail;
+				precvframe->rx_data = precvframe->rx_tail;
+				precvframe->rx_end =  pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
+			} else {
+				DBG_88E("recvbuf2recvframe: skb_clone fail\n");
+				rtw_free_recvframe(precvframe, pfree_recv_queue);
+				goto _exit_recvbuf2recvframe;
+			}
+		}
+
+		recvframe_put(precvframe, skb_len);
+
+		switch (haldata->UsbRxAggMode) {
+		case USB_RX_AGG_DMA:
+		case USB_RX_AGG_MIX:
+			pkt_offset = (u16) round_up(pkt_offset, 128);
+			break;
+		case USB_RX_AGG_USB:
+			pkt_offset = (u16) round_up(pkt_offset, 4);
+			break;
+		case USB_RX_AGG_DISABLE:
+		default:
+			break;
+		}
+		if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
+			if (pattrib->physt)
+				update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status);
+			if (rtw_recv_entry(precvframe) != _SUCCESS) {
+				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+					("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
+			}
+		} else {
+			/* enqueue recvframe to txrtp queue */
+			if (pattrib->pkt_rpt_type == TX_REPORT1) {
+				/* CCX-TXRPT ack for xmit mgmt frames. */
+				handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
+			} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
+				ODM_RA_TxRPT2Handle_8188E(
+							&haldata->odmpriv,
+							precvframe->rx_data,
+							pattrib->pkt_len,
+							pattrib->MacIDValidEntry[0],
+							pattrib->MacIDValidEntry[1]
+							);
+			} else if (pattrib->pkt_rpt_type == HIS_REPORT) {
+				interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data);
+			}
+			rtw_free_recvframe(precvframe, pfree_recv_queue);
+		}
+		pkt_cnt--;
+		transfer_len -= pkt_offset;
+		pbuf += pkt_offset;
+		precvframe = NULL;
+		pkt_copy = NULL;
+
+		if (transfer_len > 0 && pkt_cnt == 0)
+			pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
+
+	} while ((transfer_len > 0) && (pkt_cnt > 0));
+
+_exit_recvbuf2recvframe:
+
+	return _SUCCESS;
+}
+
 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
 {
 	unsigned int pipe = 0, ep_num = 0;
@@ -39,19 +227,309 @@ unsigned int ffaddr2pipehdl(struct dvobj
 	return pipe;
 }
 
-void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
 {
+	struct dvobj_priv  *dvobjpriv = adapter_to_dvobj(adapt);
+	struct usb_device *udev = dvobjpriv->pusbdev;
+	unsigned int pipe;
+	int status = 0;
+	u8 reqtype;
+	u8 *pIo_buf;
+	int vendorreq_times = 0;
+
+	if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usbctrl_vendorreq:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
+		status = -EPERM;
+		goto exit;
+	}
+
+	if (len > MAX_VENDOR_REQ_CMD_SIZE) {
+		DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
+		status = -EINVAL;
+		goto exit;
+	}
+
+	_enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+
+	/*  Acquire IO memory for vendorreq */
+	pIo_buf = dvobjpriv->usb_vendor_req_buf;
+
+	if (pIo_buf == NULL) {
+		DBG_88E("[%s] pIo_buf == NULL\n", __func__);
+		status = -ENOMEM;
+		goto release_mutex;
+	}
+
+	while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
+		memset(pIo_buf, 0, len);
+
+		if (requesttype == 0x01) {
+			pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
+			reqtype =  REALTEK_USB_VENQT_READ;
+		} else {
+			pipe = usb_sndctrlpipe(udev, 0);/* write_out */
+			reqtype =  REALTEK_USB_VENQT_WRITE;
+			memcpy(pIo_buf, pdata, len);
+		}
+
+		status = usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
+
+		if (status == len) {   /*  Success this control transfer. */
+			if (requesttype == 0x01)
+				memcpy(pdata, pIo_buf,  len);
+		} else { /*  error cases */
+			DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
+				value, (requesttype == 0x01) ? "read" : "write",
+				len, status, *(u32 *)pdata, vendorreq_times);
+
+			if (status < 0) {
+				if (status == (-ESHUTDOWN) || status == -ENODEV) {
+					adapt->bSurpriseRemoved = true;
+				} else {
+					struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
+					haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
+				}
+			} else { /*  status != len && status >= 0 */
+				if (status > 0) {
+					if (requesttype == 0x01) {
+						/*  For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
+						memcpy(pdata, pIo_buf,  len);
+					}
+				}
+			}
+
+		}
+
+		/*  firmware download is checksumed, don't retry */
+		if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
+			break;
+	}
+release_mutex:
+	mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
+exit:
+	return status;
 }
 
-void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+u8 usb_read8(struct adapter *adapter, u32 addr)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	u8 data = 0;
+
+
+	request = 0x05;
+	requesttype = 0x01;/* read_in */
+	index = 0;/* n/a */
+
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 1;
+
+	usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+
+	return data;
+
+}
+
+u16 usb_read16(struct adapter *adapter, u32 addr)
 {
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	__le32 data;
+
+	request = 0x05;
+	requesttype = 0x01;/* read_in */
+	index = 0;/* n/a */
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 2;
+	usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+	return (u16)(le32_to_cpu(data)&0xffff);
 }
 
-void usb_read_port_cancel(struct intf_hdl *pintfhdl)
+u32 usb_read32(struct adapter *adapter, u32 addr)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	__le32 data;
+
+
+	request = 0x05;
+	requesttype = 0x01;/* read_in */
+	index = 0;/* n/a */
+
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 4;
+
+	usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+
+	return le32_to_cpu(data);
+}
+
+static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+	struct recv_buf	*precvbuf = (struct recv_buf *)purb->context;
+	struct adapter	*adapt = (struct adapter *)precvbuf->adapter;
+	struct recv_priv *precvpriv = &adapt->recvpriv;
+
+	RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete!!!\n"));
+
+	precvpriv->rx_pending_cnt--;
+
+	if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+			 ("usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+			 adapt->bDriverStopped, adapt->bSurpriseRemoved));
+
+		precvbuf->reuse = true;
+		DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
+			__func__, adapt->bDriverStopped,
+			adapt->bSurpriseRemoved, adapt->bReadPortCancel);
+		return;
+	}
+
+	if (purb->status == 0) { /* SUCCESS */
+		if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
+			RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+				 ("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"));
+			precvbuf->reuse = true;
+			usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+			DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
+		} else {
+			skb_put(precvbuf->pskb, purb->actual_length);
+			skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
+
+			if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
+				tasklet_schedule(&precvpriv->recv_tasklet);
+
+			precvbuf->pskb = NULL;
+			precvbuf->reuse = false;
+			usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+		}
+	} else {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status));
+
+		DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
+		skb_put(precvbuf->pskb, purb->actual_length);
+		precvbuf->pskb = NULL;
+
+		switch (purb->status) {
+		case -EINVAL:
+		case -EPIPE:
+		case -ENODEV:
+		case -ESHUTDOWN:
+			adapt->bSurpriseRemoved = true;
+		case -ENOENT:
+			adapt->bDriverStopped = true;
+			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bDriverStopped=true\n"));
+			break;
+		case -EPROTO:
+		case -EOVERFLOW:
+			{
+				struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
+				haldata->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
+			}
+			precvbuf->reuse = true;
+			usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+			break;
+		case -EINPROGRESS:
+			DBG_88E("ERROR: URB IS IN PROGRESS!\n");
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem)
+{
+	struct urb *purb = NULL;
+	struct recv_buf	*precvbuf = (struct recv_buf *)rmem;
+	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
+	struct recv_priv	*precvpriv = &adapter->recvpriv;
+	struct usb_device	*pusbd = pdvobj->pusbdev;
+	int err;
+	unsigned int pipe;
+	size_t tmpaddr = 0;
+	size_t alignment = 0;
+	u32 ret = _SUCCESS;
+
+
+	if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
+	    adapter->pwrctrlpriv.pnp_bstop_trx) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+			 ("usb_read_port:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
+		return _FAIL;
+	}
+
+	if (!precvbuf) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+			 ("usb_read_port:precvbuf==NULL\n"));
+		return _FAIL;
+	}
+
+	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
+		precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+		if (NULL != precvbuf->pskb)
+			precvbuf->reuse = true;
+	}
+
+	/* re-assign for linux based on skb */
+	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
+		precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+		if (precvbuf->pskb == NULL) {
+			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
+			DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
+			return _FAIL;
+		}
+
+		tmpaddr = (size_t)precvbuf->pskb->data;
+		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+	} else { /* reuse skb */
+		precvbuf->reuse = false;
+	}
+
+	precvpriv->rx_pending_cnt++;
+
+	purb = precvbuf->purb;
+
+	/* translate DMA FIFO addr to pipehandle */
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+
+	usb_fill_bulk_urb(purb, pusbd, pipe,
+			  precvbuf->pskb->data,
+			  MAX_RECVBUF_SZ,
+			  usb_read_port_complete,
+			  precvbuf);/* context is precvbuf */
+
+	err = usb_submit_urb(purb, GFP_ATOMIC);
+	if ((err) && (err != (-EPERM))) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+			 ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
+			 err, purb->status));
+		DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
+			err, purb->status);
+		ret = _FAIL;
+	}
+
+	return ret;
+}
+
+void usb_read_port_cancel(struct adapter *padapter)
 {
 	int i;
 	struct recv_buf *precvbuf;
-	struct adapter	*padapter = pintfhdl->padapter;
 	precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
 
 	DBG_88E("%s\n", __func__);
@@ -66,13 +544,109 @@ void usb_read_port_cancel(struct intf_hd
 	}
 }
 
+int usb_write8(struct adapter *adapter, u32 addr, u8 val)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	u8 data;
+	int ret;
+
+	request = 0x05;
+	requesttype = 0x00;/* write_out */
+	index = 0;/* n/a */
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 1;
+	data = val;
+	ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+	return ret;
+}
+
+int usb_write16(struct adapter *adapter, u32 addr, u16 val)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	__le32 data;
+	int ret;
+
+
+	request = 0x05;
+	requesttype = 0x00;/* write_out */
+	index = 0;/* n/a */
+
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 2;
+
+	data = cpu_to_le32(val & 0x0000ffff);
+
+	ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+
+	return ret;
+}
+
+int usb_write32(struct adapter *adapter, u32 addr, u32 val)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	__le32 data;
+	int ret;
+
+
+	request = 0x05;
+	requesttype = 0x00;/* write_out */
+	index = 0;/* n/a */
+
+	wvalue = (u16)(addr&0x0000ffff);
+	len = 4;
+	data = cpu_to_le32(val);
+
+	ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+
+	return ret;
+}
+
+int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata)
+{
+	u8 request;
+	u8 requesttype;
+	u16 wvalue;
+	u16 index;
+	u16 len;
+	u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
+	int ret;
+
+
+	request = 0x05;
+	requesttype = 0x00;/* write_out */
+	index = 0;/* n/a */
+
+	wvalue = (u16)(addr&0x0000ffff);
+	len = length;
+	 memcpy(buf, pdata, len);
+
+	ret = usbctrl_vendorreq(adapter, request, wvalue, index, buf, len, requesttype);
+
+
+	return RTW_STATUS_CODE(ret);
+}
+
+
+
 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
 {
 	struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
 	struct adapter	*padapter = pxmitbuf->padapter;
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
-	struct hal_data_8188e	*haldata;
-
 
 	switch (pxmitbuf->flags) {
 	case VO_QUEUE_INX:
@@ -137,9 +711,6 @@ static void usb_write_port_complete(stru
 		}
 	}
 
-	haldata = GET_HAL_DATA(padapter);
-	haldata->srestpriv.last_tx_complete_time = jiffies;
-
 check_completion:
 	rtw_sctx_done_err(&pxmitbuf->sctx,
 			  purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
@@ -150,14 +721,13 @@ check_completion:
 	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
 }
 
-u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem)
 {
 	unsigned long irqL;
 	unsigned int pipe;
 	int status;
 	u32 ret = _FAIL;
 	struct urb *purb = NULL;
-	struct adapter *padapter = (struct adapter *)pintfhdl->padapter;
 	struct dvobj_priv	*pdvobj = adapter_to_dvobj(padapter);
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
@@ -216,11 +786,7 @@ u32 usb_write_port(struct intf_hdl *pint
 			  pxmitbuf);/* context is pxmitbuf */
 
 	status = usb_submit_urb(purb, GFP_ATOMIC);
-	if (!status) {
-		struct hal_data_8188e	*haldata = GET_HAL_DATA(padapter);
-
-		haldata->srestpriv.last_tx_time = jiffies;
-	} else {
+	if (status) {
 		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
 		DBG_88E("usb_write_port, status =%d\n", status);
 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port(): usb_submit_urb, status =%x\n", status));
@@ -247,10 +813,9 @@ exit:
 	return ret;
 }
 
-void usb_write_port_cancel(struct intf_hdl *pintfhdl)
+void usb_write_port_cancel(struct adapter *padapter)
 {
 	int i, j;
-	struct adapter	*padapter = pintfhdl->padapter;
 	struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
 
 	DBG_88E("%s\n", __func__);
@@ -274,3 +839,46 @@ void usb_write_port_cancel(struct intf_h
 		pxmitbuf++;
 	}
 }
+
+void rtl8188eu_recv_tasklet(void *priv)
+{
+	struct sk_buff *pskb;
+	struct adapter *adapt = (struct adapter *)priv;
+	struct recv_priv *precvpriv = &adapt->recvpriv;
+
+	while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
+		if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
+			DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
+			dev_kfree_skb_any(pskb);
+			break;
+		}
+		recvbuf2recvframe(adapt, pskb);
+		skb_reset_tail_pointer(pskb);
+		pskb->len = 0;
+		skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+	}
+}
+
+void rtl8188eu_xmit_tasklet(void *priv)
+{
+	int ret = false;
+	struct adapter *adapt = (struct adapter *)priv;
+	struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+
+	if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
+		return;
+
+	while (1) {
+		if ((adapt->bDriverStopped) ||
+		    (adapt->bSurpriseRemoved) ||
+		    (adapt->bWritePortCancel)) {
+			DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
+			break;
+		}
+
+		ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL);
+
+		if (!ret)
+			break;
+	}
+}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/xmit_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8188eu/os_dep/xmit_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8188eu/os_dep/xmit_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -26,7 +26,6 @@
 #include <mlme_osdep.h>
 #include <xmit_osdep.h>
 #include <osdep_intf.h>
-#include <usb_osintf.h>
 
 uint rtw_remainder_len(struct pkt_file *pfile)
 {
@@ -80,7 +79,7 @@ int rtw_os_xmit_resource_alloc(struct ad
 {
 	int i;
 
-	pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
+	pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
 	if (pxmitbuf->pallocated_buf == NULL)
 		return _FAIL;
 
@@ -184,7 +183,7 @@ static int rtw_mlcst2unicst(struct adapt
 	plist = phead->next;
 
 	/* free sta asoc_queue */
-	while (!rtw_end_of_queue_search(phead, plist)) {
+	while (phead != plist) {
 		psta = container_of(plist, struct sta_info, asoc_list);
 
 		plist = plist->next;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192e/dot11d.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/dot11d.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192e/dot11d.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/dot11d.c	2014-09-28 17:29:07.000000000 -0400
@@ -133,12 +133,12 @@ void Dot11d_UpdateCountryIe(struct rtlli
 	pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3);
 	for (i = 0; i < NumTriples; i++) {
 		if (MaxChnlNum >= pTriple->FirstChnl) {
-			printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
+			netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
 			return;
 		}
 		if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl +
 		    pTriple->NumChnls)) {
-			printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
+			netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
 			return;
 		}
 
@@ -165,7 +165,7 @@ u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib
 	u8 MaxTxPwrInDbm = 255;
 
 	if (MAX_CHANNEL_NUMBER < Channel) {
-		printk(KERN_INFO "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
+		netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
 		return MaxTxPwrInDbm;
 	}
 	if (pDot11dInfo->channel_map[Channel])
@@ -204,7 +204,7 @@ int ToLegalChannel(struct rtllib_device
 	}
 
 	if (MAX_CHANNEL_NUMBER < channel) {
-		printk(KERN_ERR "%s(): Invalid Channel\n", __func__);
+		netdev_err(dev->dev, "%s(): Invalid Channel\n", __func__);
 		return default_chn;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtl8192e/rtl_core.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtl8192e/rtl_core.c	2014-08-07 04:56:54.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtl8192e/rtl_core.c	2014-09-28 21:39:12.000000000 -0400
@@ -2065,20 +2065,16 @@ static short rtl8192_alloc_rx_desc_ring(
 	int i, rx_queue_idx;
 
 	for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) {
-		priv->rx_ring[rx_queue_idx] = pci_alloc_consistent(priv->pdev,
-					sizeof(*priv->rx_ring[rx_queue_idx]) *
-					priv->rxringcount,
-					&priv->rx_ring_dma[rx_queue_idx]);
-
+		priv->rx_ring[rx_queue_idx] =
+			pci_zalloc_consistent(priv->pdev,
+					      sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount,
+					      &priv->rx_ring_dma[rx_queue_idx]);
 		if (!priv->rx_ring[rx_queue_idx] ||
 		    (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) {
 			RT_TRACE(COMP_ERR, "Cannot allocate RX ring\n");
 			return -ENOMEM;
 		}
 
-		memset(priv->rx_ring[rx_queue_idx], 0,
-		       sizeof(*priv->rx_ring[rx_queue_idx]) *
-		       priv->rxringcount);
 		priv->rx_idx[rx_queue_idx] = 0;
 
 		for (i = 0; i < priv->rxringcount; i++) {
@@ -2118,14 +2114,13 @@ static int rtl8192_alloc_tx_desc_ring(st
 	dma_addr_t dma;
 	int i;
 
-	ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+	ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
 	if (!ring || (unsigned long)ring & 0xFF) {
 		RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n",
 			 prio);
 		return -ENOMEM;
 	}
 
-	memset(ring, 0, sizeof(*ring)*entries);
 	priv->tx_ring[prio].desc = ring;
 	priv->tx_ring[prio].dma = dma;
 	priv->tx_ring[prio].idx = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtllib_module.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtllib_module.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtllib_module.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtllib_module.c	2014-09-28 17:29:07.000000000 -0400
@@ -111,7 +111,7 @@ struct net_device *alloc_rtllib(int size
 	dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv);
 	if (!dev) {
 		RTLLIB_ERROR("Unable to network device.\n");
-		goto failed;
+		return NULL;
 	}
 	ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
 	memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv);
@@ -180,8 +180,7 @@ struct net_device *alloc_rtllib(int size
 	return dev;
 
  failed:
-	if (dev)
-		free_netdev(dev);
+	free_netdev(dev);
 	return NULL;
 }
 EXPORT_SYMBOL(alloc_rtllib);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtllib_rx.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtllib_rx.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192e/rtllib_rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192e/rtllib_rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1496,7 +1496,8 @@ int rtllib_rx(struct rtllib_device *ieee
 	return ret;
 
  rx_dropped:
-	ieee->stats.rx_dropped++;
+	if (ieee)
+		ieee->stats.rx_dropped++;
 	return 0;
 }
 EXPORT_SYMBOL(rtllib_rx);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/base.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/base.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/base.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/base.c	2014-09-28 17:29:07.000000000 -0400
@@ -469,7 +469,7 @@ static void _rtl_init_deferred_work(stru
 		    rtl92e_easy_concurrent_retrytimer_callback, (unsigned long)hw);
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
-	rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
+	rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl92e_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
@@ -826,8 +826,7 @@ static u8 _rtl_get_vht_highest_n_rate(st
 	u8 hw_rate;
 	u16 map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map);
 
-	if ((get_rf_type(rtlphy) == RF_2T2R) &&
-	    (map & 0x000c) != 0x000c0) {
+	if (get_rf_type(rtlphy) == RF_2T2R) {
 		if ((map & 0x000c) >> 2 == IEEE80211_VHT_MCS_SUPPORT_0_7)
 			hw_rate =
 			rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS7];
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/base.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/base.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/base.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/base.h	2014-09-28 17:29:07.000000000 -0400
@@ -132,13 +132,13 @@ u8 rtl92e_is_special_data(struct ieee802
 void rtl92e_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
 void rtl92e_watch_dog_timer_callback(unsigned long data);
 int rtl92e_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		        struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
 int rtl92e_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta, u16 tid);
 int rtl92e_tx_agg_oper(struct ieee80211_hw *hw,
 		       struct ieee80211_sta *sta, u16 tid);
 int rtl92e_rx_agg_start(struct ieee80211_hw *hw,
-		        struct ieee80211_sta *sta, u16 tid);
+			struct ieee80211_sta *sta, u16 tid);
 int rtl92e_rx_agg_stop(struct ieee80211_hw *hw,
 		       struct ieee80211_sta *sta, u16 tid);
 void rtl92e_watchdog_wq_callback(void *data);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/btcoexist/halbtc8821a2ant.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/btcoexist/halbtc8821a2ant.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/btcoexist/halbtc8821a2ant.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/btcoexist/halbtc8821a2ant.c	2014-09-28 17:29:07.000000000 -0400
@@ -2488,7 +2488,7 @@ static void halbtc8821a2ant_action_pan_e
 		} else {
 			sw_mechanism1(btcoexist, true, false, false, false);
 			sw_mechanism2(btcoexist, false, false, false, 0x18);
-		};
+		}
 	} else {
 		/*  fw mechanism */
 		if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/btcoexist/halbtcoutsrc.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/btcoexist/halbtcoutsrc.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/btcoexist/halbtcoutsrc.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/btcoexist/halbtcoutsrc.h	2014-09-28 17:29:07.000000000 -0400
@@ -94,7 +94,7 @@ extern u32 btc_92edbg_type[];
 
 
 #define	CL_SPRINTF	snprintf
-#define	CL_PRINTF	printk
+#define	CL_PRINTF(buf)	printk("%s", buf)
 
 #define	BTC_PRINT(dbgtype, dbgflag, printstr, ...)		\
 	do {							\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/Kconfig linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/Kconfig
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/Kconfig	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/Kconfig	2014-09-28 17:29:07.000000000 -0400
@@ -7,7 +7,6 @@ config R8192EE
 	select EEPROM_93CX6
 	select CRYPTO
 	select FW_LOADER
-	default N
 	---help---
 	This is the driver for Realtek RTL8192EE 802.11 PCIe
 	wireless network adapters.
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/pci.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/pci.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/pci.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/pci.c	2014-09-28 17:29:07.000000000 -0400
@@ -892,7 +892,7 @@ static void _rtl_pci_rx_interrupt(struct
 		}
 
 		/* handle command packet here */
-		if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
+		if (rtlpriv->cfg->ops->rx_command_packet(hw, &stats, skb)) {
 				dev_kfree_skb_any(skb);
 				goto end;
 		}
@@ -1224,10 +1224,10 @@ static int _rtl_pci_init_tx_ring(struct
 
 	/* alloc tx buffer desc for new trx flow*/
 	if (rtlpriv->use_new_trx_flow) {
-		buffer_desc = pci_alloc_consistent(rtlpci->pdev,
-					sizeof(*buffer_desc) * entries,
-					&buffer_desc_dma);
-
+		buffer_desc =
+			pci_zalloc_consistent(rtlpci->pdev,
+					      sizeof(*buffer_desc) * entries,
+					      &buffer_desc_dma);
 		if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) {
 			RT_TRACE(COMP_ERR, DBG_EMERG,
 				 ("Cannot allocate TX ring (prio = %d)\n",
@@ -1235,7 +1235,6 @@ static int _rtl_pci_init_tx_ring(struct
 			return -ENOMEM;
 		}
 
-		memset(buffer_desc, 0, sizeof(*buffer_desc) * entries);
 		rtlpci->tx_ring[prio].buffer_desc = buffer_desc;
 		rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma;
 
@@ -1245,16 +1244,14 @@ static int _rtl_pci_init_tx_ring(struct
 	}
 
 	/* alloc dma for this ring */
-	desc = pci_alloc_consistent(rtlpci->pdev,
-				    sizeof(*desc) * entries, &desc_dma);
-
+	desc = pci_zalloc_consistent(rtlpci->pdev, sizeof(*desc) * entries,
+				     &desc_dma);
 	if (!desc || (unsigned long)desc & 0xFF) {
 		RT_TRACE(COMP_ERR, DBG_EMERG,
 			 ("Cannot allocate TX ring (prio = %d)\n", prio));
 		return -ENOMEM;
 	}
 
-	memset(desc, 0, sizeof(*desc) * entries);
 	rtlpci->tx_ring[prio].desc = desc;
 	rtlpci->tx_ring[prio].dma = desc_dma;
 
@@ -1290,11 +1287,9 @@ static int _rtl_pci_init_rx_ring(struct
 		struct rtl_rx_buffer_desc *entry = NULL;
 		/* alloc dma for this ring */
 		rtlpci->rx_ring[rxring_idx].buffer_desc =
-		    pci_alloc_consistent(rtlpci->pdev,
-					 sizeof(*rtlpci->rx_ring[rxring_idx].
-						buffer_desc) *
-						rtlpci->rxringcount,
-					 &rtlpci->rx_ring[rxring_idx].dma);
+			pci_zalloc_consistent(rtlpci->pdev,
+					      sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) * rtlpci->rxringcount,
+					      &rtlpci->rx_ring[rxring_idx].dma);
 		if (!rtlpci->rx_ring[rxring_idx].buffer_desc ||
 		    (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) {
 			RT_TRACE(COMP_ERR, DBG_EMERG,
@@ -1302,10 +1297,6 @@ static int _rtl_pci_init_rx_ring(struct
 			return -ENOMEM;
 		}
 
-		memset(rtlpci->rx_ring[rxring_idx].buffer_desc, 0,
-		       sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) *
-		       rtlpci->rxringcount);
-
 		/* init every desc in this ring */
 		rtlpci->rx_ring[rxring_idx].idx = 0;
 
@@ -1320,19 +1311,15 @@ static int _rtl_pci_init_rx_ring(struct
 		u8 tmp_one = 1;
 		/* alloc dma for this ring */
 		rtlpci->rx_ring[rxring_idx].desc =
-		    pci_alloc_consistent(rtlpci->pdev,
-					 sizeof(*rtlpci->rx_ring[rxring_idx].
-					desc) * rtlpci->rxringcount,
-					 &rtlpci->rx_ring[rxring_idx].dma);
+			pci_zalloc_consistent(rtlpci->pdev,
+					      sizeof(*rtlpci->rx_ring[rxring_idx].desc) * rtlpci->rxringcount,
+					      &rtlpci->rx_ring[rxring_idx].dma);
 		if (!rtlpci->rx_ring[rxring_idx].desc ||
 		    (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) {
 			RT_TRACE(COMP_ERR, DBG_EMERG,
 				 ("Cannot allocate RX ring\n"));
 			return -ENOMEM;
 		}
-		memset(rtlpci->rx_ring[rxring_idx].desc, 0,
-		       sizeof(*rtlpci->rx_ring[rxring_idx].desc) *
-		       rtlpci->rxringcount);
 
 		/* init every desc in this ring */
 		rtlpci->rx_ring[rxring_idx].idx = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.c	2014-09-28 17:29:07.000000000 -0400
@@ -1263,13 +1263,13 @@ bool rtl92ee_is_tx_desc_closed(struct ie
 }
 
 u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw,
-			      struct rtl_stats status,
+			      const struct rtl_stats *status,
 			      struct sk_buff *skb)
 {
 	u32 result = 0;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	switch (status.packet_report_type) {
+	switch (status->packet_report_type) {
 	case NORMAL_RX:
 		result = 0;
 		break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/rtl8192ee/trx.h	2014-09-28 17:29:07.000000000 -0400
@@ -872,6 +872,6 @@ void rtl92ee_tx_fill_cmddesc(struct ieee
 			     bool b_firstseg, bool b_lastseg,
 			     struct sk_buff *skb);
 u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw,
-			      struct rtl_stats status,
+			      const struct rtl_stats *status,
 			      struct sk_buff *skb);
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192ee/wifi.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/wifi.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192ee/wifi.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192ee/wifi.h	2014-09-28 17:29:07.000000000 -0400
@@ -1946,7 +1946,7 @@ struct rtl_hal_ops {
 			     u32 cmd_len, u8 *p_cmdbuffer);
 	bool (*get_btc_status)(void);
 	u32 (*rx_command_packet)(struct ieee80211_hw *hw,
-				 struct rtl_stats status, struct sk_buff *skb);
+				 const struct rtl_stats *status, struct sk_buff *skb);
 	void (*add_wowlan_pattern)(struct ieee80211_hw *hw,
 				   struct rtl_wow_pattern *rtl_pattern,
 				   u8 index);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -2238,7 +2238,7 @@ static inline void *ieee80211_priv(struc
 	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -2254,7 +2254,7 @@ extern inline int ieee80211_is_empty_ess
 	return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
 {
 	/*
 	 * It is possible for both access points and our device to support
@@ -2280,7 +2280,7 @@ extern inline int ieee80211_is_valid_mod
 	return 0;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = IEEE80211_3ADDR_LEN;
 
@@ -2564,12 +2564,12 @@ void ieee80211_softmac_scan_syncro(struc
 
 extern const long ieee80211_wlan_frequencies[];
 
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
 	ieee->scans++;
 }
 
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
 {
 	return ieee->scans;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c	2014-09-28 17:29:07.000000000 -0400
@@ -352,7 +352,6 @@ ieee80211_rx_frame_decrypt(struct ieee80
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
 	if (ieee->tkip_countermeasures &&
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
@@ -362,7 +361,6 @@ ieee80211_rx_frame_decrypt(struct ieee80
 		}
 		return -1;
 	}
-#endif
 
 	atomic_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c	2014-09-28 17:29:07.000000000 -0400
@@ -191,20 +191,20 @@ int ieee80211_encrypt_fragment(
 		printk("=========>%s(), crypt is null\n", __func__);
 		return -1;
 	}
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	struct ieee80211_hdr *header;
 
 	if (ieee->tkip_countermeasures &&
 	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-		header = (struct ieee80211_hdr *) frag->data;
 		if (net_ratelimit()) {
+			struct ieee80211_hdr_3addrqos *header;
+
+			header = (struct ieee80211_hdr_3addrqos *)frag->data;
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
 			       "TX packet to %pM\n",
 			       ieee->dev->name, header->addr1);
 		}
 		return -1;
 	}
-#endif
+
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8180_93cx6.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8180_93cx6.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8180_93cx6.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8180_93cx6.c	2014-09-28 17:29:07.000000000 -0400
@@ -103,7 +103,7 @@ u32 eprom_read(struct net_device *dev, u
 	u32 ret;
 
 	ret = 0;
-	//enable EPROM programming
+	/* enable EPROM programming */
 	write_nic_byte_E(dev, EPROM_CMD,
 		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
 	force_pci_posting(dev);
@@ -133,13 +133,16 @@ u32 eprom_read(struct net_device *dev, u
 	eprom_send_bits_string(dev, read_cmd, 3);
 	eprom_send_bits_string(dev, addr_str, addr_len);
 
-	//keep chip pin D to low state while reading.
-	//I'm unsure if it is necessary, but anyway shouldn't hurt
+	/*
+	 * keep chip pin D to low state while reading.
+	 * I'm unsure if it is necessary, but anyway shouldn't hurt
+	 */
 	eprom_w(dev, 0);
 
 	for (i = 0; i < 16; i++) {
-		//eeprom needs a clk cycle between writing opcode&adr
-		//and reading data. (eeprom outs a dummy 0)
+		/* eeprom needs a clk cycle between writing opcode&adr
+		 * and reading data. (eeprom outs a dummy 0)
+		 */
 		eprom_ck_cycle(dev);
 		ret |= (eprom_r(dev)<<(15-i));
 	}
@@ -147,7 +150,7 @@ u32 eprom_read(struct net_device *dev, u
 	eprom_cs(dev, 0);
 	eprom_ck_cycle(dev);
 
-	//disable EPROM programming
+	/* disable EPROM programming */
 	write_nic_byte_E(dev, EPROM_CMD,
 		       (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
 	return ret;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8180_93cx6.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8180_93cx6.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8180_93cx6.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8180_93cx6.h	2014-09-28 17:29:07.000000000 -0400
@@ -3,11 +3,14 @@
 	Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
 	Released under the terms of GPL (General Public Licence)
 
-	Parts of this driver are based on the GPL part of the official realtek driver
-	Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
+	Parts of this driver are based on the GPL part of the
+	official realtek driver
+	Parts of this driver are based on the rtl8180 driver skeleton
+	from Patric Schenke & Andres Salomon
 	Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
 
-	We want to thank the Authors of such projects and the Ndiswrapper project Authors.
+	We want to thank the Authors of such projects and the Ndiswrapper
+	project Authors.
 */
 
 /*This files contains card eeprom (93c46 or 93c56) programming routines*/
@@ -37,4 +40,4 @@
 #define EPROM_TXPW1 0x3d
 
 
-u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word
+u32 eprom_read(struct net_device *dev, u32 addr); /* reads a 16 bits word */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8190_rtl8256.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8190_rtl8256.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8190_rtl8256.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8190_rtl8256.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,62 +23,64 @@
  * Return:      NONE
  * Note:	8226 support both 20M  and 40 MHz
  *---------------------------------------------------------------------------*/
-void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth)	//20M or 40M
+void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth)
 {
 	u8	eRFPath;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
-	//for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
-	for(eRFPath = 0; eRFPath <RF90_PATH_MAX; eRFPath++)
-	{
+	/* for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath;
+	 *  eRFPath++)
+	 */
+	for (eRFPath = 0; eRFPath < RF90_PATH_MAX; eRFPath++) {
 		if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
 			continue;
 
-		switch (Bandwidth)
-		{
-			case HT_CHANNEL_WIDTH_20:
-				if(priv->card_8192_version == VERSION_819xU_A || priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later!
-				{
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
+		switch (Bandwidth) {
+		case HT_CHANNEL_WIDTH_20:
+				if (priv->card_8192_version == VERSION_819xU_A
+					|| priv->card_8192_version
+					== VERSION_819xU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */
+					rtl8192_phy_SetRFReg(dev,
+						(RF90_RADIO_PATH_E)eRFPath,
+						0x0b, bMask12Bits, 0x100); /* phy para:1ba */
+					rtl8192_phy_SetRFReg(dev,
+						(RF90_RADIO_PATH_E)eRFPath,
+						0x2c, bMask12Bits, 0x3d7);
+					rtl8192_phy_SetRFReg(dev,
+						(RF90_RADIO_PATH_E)eRFPath,
+						0x0e, bMask12Bits, 0x021);
 
-					//cosa add for sd3's request 01/23/2008
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
-				}
-				else
-				{
+					/* cosa add for sd3's request 01/23/2008
+					 */
+					rtl8192_phy_SetRFReg(dev,
+						(RF90_RADIO_PATH_E)eRFPath,
+						0x14, bMask12Bits, 0x5ab);
+				} else {
 					RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
-				}
-
+					}
 				break;
-			case HT_CHANNEL_WIDTH_20_40:
-				if(priv->card_8192_version == VERSION_819xU_A ||priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later!
-				{
+		case HT_CHANNEL_WIDTH_20_40:
+				if (priv->card_8192_version == VERSION_819xU_A || priv->card_8192_version == VERSION_819xU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */
 					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
 					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3df);
 					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0a1);
 
 					//cosa add for sd3's request 01/23/2008
-					if(priv->chan == 3 || priv->chan == 9) //I need to set priv->chan whenever current channel changes
+					if (priv->chan == 3 || priv->chan == 9)
+						//I need to set priv->chan whenever current channel changes
 						rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x59b);
 					else
 						rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
-				}
-				else
-				{
+				} else {
 					RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
-				}
-
-
+					}
 				break;
-			default:
-				RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth);
+		default:
+				RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n", Bandwidth);
 				break;
 
 		}
 	}
-	return;
 }
 /*--------------------------------------------------------------------------
  * Overview:    Interface to config 8256
@@ -95,8 +97,6 @@ void PHY_RF8256_Config(struct net_device
 	priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
 	// Config BB and RF
 	phy_RF8256_Config_ParaFile(dev);
-
-	return;
 }
 /*--------------------------------------------------------------------------
  * Overview:    Interface to config 8256
@@ -122,8 +122,7 @@ void phy_RF8256_Config_ParaFile(struct n
 	//3//-----------------------------------------------------------------
 	//3// <2> Initialize RF
 	//3//-----------------------------------------------------------------
-	for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath <priv->NumTotalRFPath; eRFPath++)
-	{
+	for (eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) {
 		if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
 			continue;
 
@@ -133,13 +132,12 @@ void phy_RF8256_Config_ParaFile(struct n
 	//	pHalData->RfReg0Value[eRFPath] =  rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rGlobalCtrl, bMaskDWord);
 
 		/*----Store original RFENV control type----*/
-		switch (eRFPath)
-		{
+		switch (eRFPath) {
 		case RF90_PATH_A:
 		case RF90_PATH_C:
 			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV);
 			break;
-		case RF90_PATH_B :
+		case RF90_PATH_B:
 		case RF90_PATH_D:
 			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16);
 			break;
@@ -159,8 +157,7 @@ void phy_RF8256_Config_ParaFile(struct n
 
 		/*----Check RF block (for FPGA platform only)----*/
 		// TODO: this function should be removed on ASIC , Emily 2007.2.2
-		if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath))
-		{
+		if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath)) {
 			RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath);
 			goto phy_RF8256_Config_ParaFile_Fail;
 		}
@@ -168,39 +165,34 @@ void phy_RF8256_Config_ParaFile(struct n
 		RetryTimes = ConstRetryTimes;
 		RF3_Final_Value = 0;
 		/*----Initialize RF fom connfiguration file----*/
-		switch (eRFPath)
-		{
+		switch (eRFPath) {
 		case RF90_PATH_A:
-			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
-			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+			while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath);
 				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
 			break;
 		case RF90_PATH_B:
-			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
-			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+			while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath);
 				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
 			break;
 		case RF90_PATH_C:
-			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
-			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+			while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath);
 				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
 			break;
 		case RF90_PATH_D:
-			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
-			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+			while (RF3_Final_Value != RegValueToBeCheck && RetryTimes != 0) {
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, (RF90_RADIO_PATH_E)eRFPath);
 				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
@@ -209,50 +201,48 @@ void phy_RF8256_Config_ParaFile(struct n
 		}
 
 		/*----Restore RFENV control type----*/;
-		switch (eRFPath)
-		{
+		switch (eRFPath) {
 		case RF90_PATH_A:
 		case RF90_PATH_C:
 			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
 			break;
-		case RF90_PATH_B :
+		case RF90_PATH_B:
 		case RF90_PATH_D:
 			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
 			break;
 		}
 
-		if(ret){
+		if (ret) {
 			RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath);
 			goto phy_RF8256_Config_ParaFile_Fail;
 		}
 
 	}
 
-	RT_TRACE(COMP_PHY, "PHY Initialization Success\n") ;
-	return ;
+	RT_TRACE(COMP_PHY, "PHY Initialization Success\n");
+	return;
 
 phy_RF8256_Config_ParaFile_Fail:
-	RT_TRACE(COMP_ERR, "PHY Initialization failed\n") ;
-	return ;
+	RT_TRACE(COMP_ERR, "PHY Initialization failed\n");
 }
 
 
 void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel)
 {
-	u32	TxAGC=0;
+	u32	TxAGC = 0;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	//modified by vivi, 20080109
 	TxAGC = powerlevel;
 
-	if(priv->bDynamicTxLowPower == TRUE) //cosa 05/22/2008 for scan
-	{
-		if(priv->CustomerID == RT_CID_819x_Netcore)
+	if (priv->bDynamicTxLowPower == TRUE) {
+		//cosa 05/22/2008 for scan
+		if (priv->CustomerID == RT_CID_819x_Netcore)
 			TxAGC = 0x22;
 		else
 			TxAGC += priv->CckPwEnl;
 	}
 
-	if(TxAGC > 0x24)
+	if (TxAGC > 0x24)
 		TxAGC = 0x24;
 	rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
 }
@@ -268,43 +258,42 @@ void PHY_SetRF8256OFDMTxPower(struct net
 	u8 byte0, byte1, byte2, byte3;
 
 	powerBase0 = powerlevel + priv->TxPowerDiff;	//OFDM rates
-	powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
+	powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
 	powerBase1 = powerlevel;							//MCS rates
-	powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
+	powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
 
-	for(index=0; index<6; index++)
-	{
-		writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index<2)?powerBase0:powerBase1);
+	for (index = 0; index < 6; index++) {
+		writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2)?powerBase0:powerBase1);
 		byte0 = (u8)(writeVal & 0x7f);
 		byte1 = (u8)((writeVal & 0x7f00)>>8);
 		byte2 = (u8)((writeVal & 0x7f0000)>>16);
 		byte3 = (u8)((writeVal & 0x7f000000)>>24);
-		if(byte0 > 0x24)	// Max power index = 0x24
+
+		if (byte0 > 0x24)
+			/* Max power index = 0x24 */
 			byte0 = 0x24;
-		if(byte1 > 0x24)
+		if (byte1 > 0x24)
 			byte1 = 0x24;
-		if(byte2 > 0x24)
+		if (byte2 > 0x24)
 			byte2 = 0x24;
-		if(byte3 > 0x24)
+		if (byte3 > 0x24)
 			byte3 = 0x24;
 
 		//for tx power track
-		if(index == 3)
-		{
-			writeVal_tmp = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
+		if (index == 3) {
+			writeVal_tmp = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0;
 			priv->Pwr_Track = writeVal_tmp;
 		}
 
-		if(priv->bDynamicTxHighPower == TRUE)     //Add by Jacken 2008/03/06
-		{
-			// Emily, 20080613. Set low tx power for both MCS and legacy OFDM
+		if (priv->bDynamicTxHighPower == TRUE) {
+			/*Add by Jacken 2008/03/06
+			 *Emily, 20080613. Set low tx power for both MCS and legacy OFDM
+			 */
 			writeVal = 0x03030303;
-		}
-		else
-		{
-			writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
-		}
-		rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+		} else {
+			writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0;
+			}
+			rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
 	}
 	return;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8192U_core.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8192U_core.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8192U_core.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8192U_core.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,17 +166,17 @@ typedef struct _CHANNEL_LIST {
 } CHANNEL_LIST, *PCHANNEL_LIST;
 
 static CHANNEL_LIST ChannelPlan[] = {
-	{{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24},		//FCC
-	{{1,2,3,4,5,6,7,8,9,10,11},11},							//IC
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},	//ETSI
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},    //Spain. Change to ETSI.
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},	//France. Change to ETSI.
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},	//MKK					//MKK
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},	//Israel.
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},			// For 11a , TELEC
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22},    //MIC
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}					//For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 24},		//FCC
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},							//IC
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	//ETSI
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},    //Spain. Change to ETSI.
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},	//France. Change to ETSI.
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},	//MKK					//MKK
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},//MKK1
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},	//Israel.
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},			// For 11a , TELEC
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},    //MIC
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}					//For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
 };
 
 static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
@@ -905,7 +905,8 @@ inline u16 ieeerate2rtlrate(int rate)
 static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
 inline u16 rtl8192_rate2rate(short rate)
 {
-	if (rate > 11) return 0;
+	if (rate > 11)
+		return 0;
 	return rtl_rate[rate];
 }
 
@@ -1114,7 +1115,7 @@ struct sk_buff *DrvAggr_Aggregation(stru
 		tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
 		tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
 		tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
-		if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
+		if (tcb_desc->bAMPDUEnable) { /* AMPDU enabled */
 			tx_fwinfo->AllowAggregation = 1;
 			/* DWORD 1 */
 			tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
@@ -1236,12 +1237,11 @@ u8 DrvAggr_GetAggregatibleList(struct ne
 static void rtl8192_tx_isr(struct urb *tx_urb)
 {
 	struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
-	struct net_device *dev = NULL;
+	struct net_device *dev = (struct net_device *)(skb->cb);
 	struct r8192_priv *priv = NULL;
 	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 	u8  queue_index = tcb_desc->queue_index;
 
-	memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
 	priv = ieee80211_priv(dev);
 
 	if (tcb_desc->queue_index != TXCMD_QUEUE) {
@@ -1330,35 +1330,83 @@ static void rtl8192_config_rate(struct n
 	for (i = 0; i < net->rates_len; i++) {
 		basic_rate = net->rates[i]&0x7f;
 		switch (basic_rate) {
-		case MGN_1M:	*rate_config |= RRSR_1M;	break;
-		case MGN_2M:	*rate_config |= RRSR_2M;	break;
-		case MGN_5_5M:	*rate_config |= RRSR_5_5M;	break;
-		case MGN_11M:	*rate_config |= RRSR_11M;	break;
-		case MGN_6M:	*rate_config |= RRSR_6M;	break;
-		case MGN_9M:	*rate_config |= RRSR_9M;	break;
-		case MGN_12M:	*rate_config |= RRSR_12M;	break;
-		case MGN_18M:	*rate_config |= RRSR_18M;	break;
-		case MGN_24M:	*rate_config |= RRSR_24M;	break;
-		case MGN_36M:	*rate_config |= RRSR_36M;	break;
-		case MGN_48M:	*rate_config |= RRSR_48M;	break;
-		case MGN_54M:	*rate_config |= RRSR_54M;	break;
+			case MGN_1M:
+				*rate_config |= RRSR_1M;
+				break;
+			case MGN_2M:
+				*rate_config |= RRSR_2M;
+				break;
+			case MGN_5_5M:
+				*rate_config |= RRSR_5_5M;
+				break;
+			case MGN_11M:
+				*rate_config |= RRSR_11M;
+				break;
+			case MGN_6M:
+				*rate_config |= RRSR_6M;
+				break;
+			case MGN_9M:
+				*rate_config |= RRSR_9M;
+				break;
+			case MGN_12M:
+				*rate_config |= RRSR_12M;
+				break;
+			case MGN_18M:
+				*rate_config |= RRSR_18M;
+				break;
+			case MGN_24M:
+				*rate_config |= RRSR_24M;
+				break;
+			case MGN_36M:
+				*rate_config |= RRSR_36M;
+				break;
+			case MGN_48M:
+				*rate_config |= RRSR_48M;
+				break;
+			case MGN_54M:
+				*rate_config |= RRSR_54M;
+				break;
 		}
 	}
 	for (i = 0; i < net->rates_ex_len; i++) {
 		basic_rate = net->rates_ex[i]&0x7f;
 		switch (basic_rate) {
-		case MGN_1M:	*rate_config |= RRSR_1M;	break;
-		case MGN_2M:	*rate_config |= RRSR_2M;	break;
-		case MGN_5_5M:	*rate_config |= RRSR_5_5M;	break;
-		case MGN_11M:	*rate_config |= RRSR_11M;	break;
-		case MGN_6M:	*rate_config |= RRSR_6M;	break;
-		case MGN_9M:	*rate_config |= RRSR_9M;	break;
-		case MGN_12M:	*rate_config |= RRSR_12M;	break;
-		case MGN_18M:	*rate_config |= RRSR_18M;	break;
-		case MGN_24M:	*rate_config |= RRSR_24M;	break;
-		case MGN_36M:	*rate_config |= RRSR_36M;	break;
-		case MGN_48M:	*rate_config |= RRSR_48M;	break;
-		case MGN_54M:	*rate_config |= RRSR_54M;	break;
+			case MGN_1M:
+				*rate_config |= RRSR_1M;
+				break;
+			case MGN_2M:
+				*rate_config |= RRSR_2M;
+				break;
+			case MGN_5_5M:
+				*rate_config |= RRSR_5_5M;
+				break;
+			case MGN_11M:
+				*rate_config |= RRSR_11M;
+				break;
+			case MGN_6M:
+				*rate_config |= RRSR_6M;
+				break;
+			case MGN_9M:
+				*rate_config |= RRSR_9M;
+				break;
+			case MGN_12M:
+				*rate_config |= RRSR_12M;
+				break;
+			case MGN_18M:
+				*rate_config |= RRSR_18M;
+				break;
+			case MGN_24M:
+				*rate_config |= RRSR_24M;
+				break;
+			case MGN_36M:
+				*rate_config |= RRSR_36M;
+				break;
+			case MGN_48M:
+				*rate_config |= RRSR_48M;
+				break;
+			case MGN_54M:
+				*rate_config |= RRSR_54M;
+				break;
 		}
 	}
 }
@@ -1380,7 +1428,7 @@ static void rtl8192_update_cap(struct ne
 
 	if (net->mode & (IEEE_G|IEEE_N_24G)) {
 		u8 slot_time = 0;
-		if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
+		if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) /* short slot time */
 			slot_time = SHORT_SLOT_TIME;
 		else //long slot time
 			slot_time = NON_SHORT_SLOT_TIME;
@@ -1399,7 +1447,7 @@ static void rtl8192_net_update(struct ne
 	net = &priv->ieee80211->current_network;
 
 	rtl8192_config_rate(dev, &rate_config);
-	priv->basic_rate = rate_config &= 0x15f;
+	priv->basic_rate = rate_config & 0x15f;
 
 	write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
 	write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
@@ -1432,7 +1480,8 @@ inline u8 rtl8192_IsWirelessBMode(u16 ra
 {
 	if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
 		return 1;
-	else return 0;
+	else
+		return 0;
 }
 
 u16 N_DBPSOfRate(u16 DataRate);
@@ -1445,11 +1494,11 @@ u16 ComputeTxTime(u16 FrameLength, u16 D
 	u16	Ceiling;
 
 	if (rtl8192_IsWirelessBMode(DataRate)) {
-		if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
+		if (bManagementFrame || !bShortPreamble || DataRate == 10) /* long preamble */
 			FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
 		else // Short preamble
 			FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
-		if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
+		if ((FrameLength*8 % (DataRate/10)) != 0) /* Get the Ceilling */
 			FrameTime++;
 	} else {	//802.11g DSSS-OFDM PLCP length field calculation.
 		N_DBPS = N_DBPSOfRate(DataRate);
@@ -1617,39 +1666,98 @@ static u8 MRateToHwRate8190Pci(u8 rate)
 	u8  ret = DESC90_RATE1M;
 
 	switch (rate) {
-	case MGN_1M:    ret = DESC90_RATE1M;    break;
-	case MGN_2M:    ret = DESC90_RATE2M;    break;
-	case MGN_5_5M:  ret = DESC90_RATE5_5M;  break;
-	case MGN_11M:   ret = DESC90_RATE11M;   break;
-	case MGN_6M:    ret = DESC90_RATE6M;    break;
-	case MGN_9M:    ret = DESC90_RATE9M;    break;
-	case MGN_12M:   ret = DESC90_RATE12M;   break;
-	case MGN_18M:   ret = DESC90_RATE18M;   break;
-	case MGN_24M:   ret = DESC90_RATE24M;   break;
-	case MGN_36M:   ret = DESC90_RATE36M;   break;
-	case MGN_48M:   ret = DESC90_RATE48M;   break;
-	case MGN_54M:   ret = DESC90_RATE54M;   break;
+		case MGN_1M:
+			ret = DESC90_RATE1M;
+			break;
+		case MGN_2M:
+			ret = DESC90_RATE2M;
+			break;
+		case MGN_5_5M:
+			ret = DESC90_RATE5_5M;
+			break;
+		case MGN_11M:
+			ret = DESC90_RATE11M;
+			break;
+		case MGN_6M:
+			ret = DESC90_RATE6M;
+			break;
+		case MGN_9M:
+			ret = DESC90_RATE9M;
+			break;
+		case MGN_12M:
+			ret = DESC90_RATE12M;
+			break;
+		case MGN_18M:
+			ret = DESC90_RATE18M;
+			break;
+		case MGN_24M:
+			ret = DESC90_RATE24M;
+			break;
+		case MGN_36M:
+			ret = DESC90_RATE36M;
+			break;
+		case MGN_48M:
+			ret = DESC90_RATE48M;
+			break;
+		case MGN_54M:
+			ret = DESC90_RATE54M;
+			break;
 
-	// HT rate since here
-	case MGN_MCS0:  ret = DESC90_RATEMCS0;  break;
-	case MGN_MCS1:  ret = DESC90_RATEMCS1;  break;
-	case MGN_MCS2:  ret = DESC90_RATEMCS2;  break;
-	case MGN_MCS3:  ret = DESC90_RATEMCS3;  break;
-	case MGN_MCS4:  ret = DESC90_RATEMCS4;  break;
-	case MGN_MCS5:  ret = DESC90_RATEMCS5;  break;
-	case MGN_MCS6:  ret = DESC90_RATEMCS6;  break;
-	case MGN_MCS7:  ret = DESC90_RATEMCS7;  break;
-	case MGN_MCS8:  ret = DESC90_RATEMCS8;  break;
-	case MGN_MCS9:  ret = DESC90_RATEMCS9;  break;
-	case MGN_MCS10: ret = DESC90_RATEMCS10; break;
-	case MGN_MCS11: ret = DESC90_RATEMCS11; break;
-	case MGN_MCS12: ret = DESC90_RATEMCS12; break;
-	case MGN_MCS13: ret = DESC90_RATEMCS13; break;
-	case MGN_MCS14: ret = DESC90_RATEMCS14; break;
-	case MGN_MCS15: ret = DESC90_RATEMCS15; break;
-	case (0x80|0x20): ret = DESC90_RATEMCS32; break;
+		// HT rate since here
+		case MGN_MCS0:
+			ret = DESC90_RATEMCS0;
+			break;
+		case MGN_MCS1:
+			ret = DESC90_RATEMCS1;
+			break;
+		case MGN_MCS2:
+			ret = DESC90_RATEMCS2;
+			break;
+		case MGN_MCS3:
+			ret = DESC90_RATEMCS3;
+			break;
+		case MGN_MCS4:
+			ret = DESC90_RATEMCS4;
+			break;
+		case MGN_MCS5:
+			ret = DESC90_RATEMCS5;
+			break;
+		case MGN_MCS6:
+			ret = DESC90_RATEMCS6;
+			break;
+		case MGN_MCS7:
+			ret = DESC90_RATEMCS7;
+			break;
+		case MGN_MCS8:
+			ret = DESC90_RATEMCS8;
+			break;
+		case MGN_MCS9:
+			ret = DESC90_RATEMCS9;
+			break;
+		case MGN_MCS10:
+			ret = DESC90_RATEMCS10;
+			break;
+		case MGN_MCS11:
+			ret = DESC90_RATEMCS11;
+			break;
+		case MGN_MCS12:
+			ret = DESC90_RATEMCS12;
+			break;
+		case MGN_MCS13:
+			ret = DESC90_RATEMCS13;
+			break;
+		case MGN_MCS14:
+			ret = DESC90_RATEMCS14;
+			break;
+		case MGN_MCS15:
+			ret = DESC90_RATEMCS15;
+			break;
+		case (0x80|0x20):
+			ret = DESC90_RATEMCS32;
+			break;
 
-	default:       break;
+		default:
+			break;
 	}
 	return ret;
 }
@@ -1712,7 +1820,7 @@ short rtl8192_tx(struct net_device *dev,
 	tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
 	tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
 	tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
-	if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
+	if (tcb_desc->bAMPDUEnable) { /* AMPDU enabled */
 		tx_fwinfo->AllowAggregation = 1;
 		/* DWORD 1 */
 		tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
@@ -2198,7 +2306,7 @@ void rtl8192_update_ratr_table(struct ne
 		break;
 	case IEEE_N_24G:
 	case IEEE_N_5G:
-		if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
+		if (ieee->pHTInfo->PeerMimoPs == 0) { /* MIMO_PS_STATIC */
 			ratr_value &= 0x0007F007;
 		} else {
 			if (priv->rf_type == RF_1T2R)
@@ -2355,7 +2463,6 @@ static void rtl8192_init_priv_variable(s
 
 	priv->ieee80211->FwRWRF = 0;	//we don't use FW read/write RF until stable firmware is available.
 	priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
-	priv->ieee80211->iw_mode = IW_MODE_INFRA;
 	priv->ieee80211->softmac_features  = IEEE_SOFTMAC_SCAN |
 		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
 		IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
@@ -2582,7 +2689,7 @@ static void rtl8192_read_eeprom_info(str
 		else
 			priv->EEPROM_Def_Ver = 1;
 		RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
-		if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
+		if (priv->EEPROM_Def_Ver == 0) { /* old eeprom definition */
 			int i;
 			if (bLoad_From_EEPOM)
 				priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
@@ -2993,13 +3100,13 @@ static bool rtl8192_adapter_start(struct
 	//
 #ifdef TO_DO_LIST
 	if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
-		if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
+		if (pMgntInfo->RegRfOff == TRUE) { /* User disable RF via registry. */
 			RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
 			MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
 			// Those actions will be discard in MgntActSet_RF_State because of the same state
 			for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
 				PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
-		} else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
+		} else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { /* H/W or S/W RF OFF before sleep. */
 			RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
 			MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
 		} else {
@@ -3525,7 +3632,7 @@ void rtl819x_watchdog_wqcallback(struct
 	}
 	if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
 	    (priv->bForcedSilentReset ||
-	    (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
+	    (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { /* This is control by OID set in Pomelo */
 		RT_TRACE(COMP_RESET, "%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n", __func__, priv->force_reset, priv->ResetProgress, priv->bForcedSilentReset, priv->bDisableNormalResetCheck, ResetType);
 		rtl819x_ifsilentreset(dev);
 	}
@@ -3586,7 +3693,8 @@ int rtl8192_up(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
-	if (priv->up == 1) return -1;
+	if (priv->up == 1)
+		return -1;
 
 	return _rtl8192_up(dev);
 }
@@ -3612,7 +3720,8 @@ int rtl8192_down(struct net_device *dev)
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int i;
 
-	if (priv->up == 0) return -1;
+	if (priv->up == 0)
+		return -1;
 
 	priv->up = 0;
 	priv->ieee80211->ieee_up = 0;
@@ -3650,7 +3759,8 @@ void rtl8192_commit(struct net_device *d
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int reset_status = 0;
-	if (priv->up == 0) return;
+	if (priv->up == 0)
+		return;
 	priv->up = 0;
 
 	rtl8192_cancel_deferred_work(priv);
@@ -3803,49 +3913,107 @@ static u8 HwRateToMRate90(bool bIsHT, u8
 
 	if (!bIsHT) {
 		switch (rate) {
-		case DESC90_RATE1M:   ret_rate = MGN_1M;         break;
-		case DESC90_RATE2M:   ret_rate = MGN_2M;         break;
-		case DESC90_RATE5_5M: ret_rate = MGN_5_5M;       break;
-		case DESC90_RATE11M:  ret_rate = MGN_11M;        break;
-		case DESC90_RATE6M:   ret_rate = MGN_6M;         break;
-		case DESC90_RATE9M:   ret_rate = MGN_9M;         break;
-		case DESC90_RATE12M:  ret_rate = MGN_12M;        break;
-		case DESC90_RATE18M:  ret_rate = MGN_18M;        break;
-		case DESC90_RATE24M:  ret_rate = MGN_24M;        break;
-		case DESC90_RATE36M:  ret_rate = MGN_36M;        break;
-		case DESC90_RATE48M:  ret_rate = MGN_48M;        break;
-		case DESC90_RATE54M:  ret_rate = MGN_54M;        break;
+			case DESC90_RATE1M:
+				ret_rate = MGN_1M;
+				break;
+			case DESC90_RATE2M:
+				ret_rate = MGN_2M;
+				break;
+			case DESC90_RATE5_5M:
+				ret_rate = MGN_5_5M;
+				break;
+			case DESC90_RATE11M:
+				ret_rate = MGN_11M;
+				break;
+			case DESC90_RATE6M:
+				ret_rate = MGN_6M;
+				break;
+			case DESC90_RATE9M:
+				ret_rate = MGN_9M;
+				break;
+			case DESC90_RATE12M:
+				ret_rate = MGN_12M;
+				break;
+			case DESC90_RATE18M:
+				ret_rate = MGN_18M;
+				break;
+			case DESC90_RATE24M:
+				ret_rate = MGN_24M;
+				break;
+			case DESC90_RATE36M:
+				ret_rate = MGN_36M;
+				break;
+			case DESC90_RATE48M:
+				ret_rate = MGN_48M;
+				break;
+			case DESC90_RATE54M:
+				ret_rate = MGN_54M;
+				break;
 
-		default:
-			ret_rate = 0xff;
-			RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
-			break;
+			default:
+				ret_rate = 0xff;
+				RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
+				break;
 		}
 
 	} else {
 		switch (rate) {
-		case DESC90_RATEMCS0:   ret_rate = MGN_MCS0;    break;
-		case DESC90_RATEMCS1:   ret_rate = MGN_MCS1;    break;
-		case DESC90_RATEMCS2:   ret_rate = MGN_MCS2;    break;
-		case DESC90_RATEMCS3:   ret_rate = MGN_MCS3;    break;
-		case DESC90_RATEMCS4:   ret_rate = MGN_MCS4;    break;
-		case DESC90_RATEMCS5:   ret_rate = MGN_MCS5;    break;
-		case DESC90_RATEMCS6:   ret_rate = MGN_MCS6;    break;
-		case DESC90_RATEMCS7:   ret_rate = MGN_MCS7;    break;
-		case DESC90_RATEMCS8:   ret_rate = MGN_MCS8;    break;
-		case DESC90_RATEMCS9:   ret_rate = MGN_MCS9;    break;
-		case DESC90_RATEMCS10:  ret_rate = MGN_MCS10;   break;
-		case DESC90_RATEMCS11:  ret_rate = MGN_MCS11;   break;
-		case DESC90_RATEMCS12:  ret_rate = MGN_MCS12;   break;
-		case DESC90_RATEMCS13:  ret_rate = MGN_MCS13;   break;
-		case DESC90_RATEMCS14:  ret_rate = MGN_MCS14;   break;
-		case DESC90_RATEMCS15:  ret_rate = MGN_MCS15;   break;
-		case DESC90_RATEMCS32:  ret_rate = (0x80|0x20); break;
+			case DESC90_RATEMCS0:
+				ret_rate = MGN_MCS0;
+				break;
+			case DESC90_RATEMCS1:
+				ret_rate = MGN_MCS1;
+				break;
+			case DESC90_RATEMCS2:
+				ret_rate = MGN_MCS2;
+				break;
+			case DESC90_RATEMCS3:
+				ret_rate = MGN_MCS3;
+				break;
+			case DESC90_RATEMCS4:
+				ret_rate = MGN_MCS4;
+				break;
+			case DESC90_RATEMCS5:
+				ret_rate = MGN_MCS5;
+				break;
+			case DESC90_RATEMCS6:
+				ret_rate = MGN_MCS6;
+				break;
+			case DESC90_RATEMCS7:
+				ret_rate = MGN_MCS7;
+				break;
+			case DESC90_RATEMCS8:
+				ret_rate = MGN_MCS8;
+				break;
+			case DESC90_RATEMCS9:
+				ret_rate = MGN_MCS9;
+				break;
+			case DESC90_RATEMCS10:
+				ret_rate = MGN_MCS10;
+				break;
+			case DESC90_RATEMCS11:
+				ret_rate = MGN_MCS11;
+				break;
+			case DESC90_RATEMCS12:
+				ret_rate = MGN_MCS12;
+				break;
+			case DESC90_RATEMCS13:
+				ret_rate = MGN_MCS13;
+				break;
+			case DESC90_RATEMCS14:
+				ret_rate = MGN_MCS14;
+				break;
+			case DESC90_RATEMCS15:
+				ret_rate = MGN_MCS15;
+				break;
+			case DESC90_RATEMCS32:
+				ret_rate = (0x80|0x20);
+				break;
 
-		default:
-			ret_rate = 0xff;
-			RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
-			break;
+			default:
+				ret_rate = 0xff;
+				RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
+				break;
 		}
 	}
 
@@ -4022,7 +4190,7 @@ static void rtl8192_process_phyinfo(stru
 
 
 	if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
-		if (priv->undecorated_smoothed_pwdb < 0)	// initialize
+		if (priv->undecorated_smoothed_pwdb < 0)	/* initialize */
 			priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
 		if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
 			priv->undecorated_smoothed_pwdb =
@@ -4064,9 +4232,9 @@ static void rtl8192_process_phyinfo(stru
 
 		// <2> Showed on UI for engineering
 		if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
-			for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
+			for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { /* 2 spatial stream */
 				if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
-					if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
+					if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) /* initialize */
 						priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
 					priv->stats.rx_evm_percentage[nspatial_stream] =
 						((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
@@ -4361,7 +4529,7 @@ static void rtl8192_query_rxphystatus(st
 			rx_evmX /= 2;	//dbm
 
 			evm = rtl819x_evm_dbtopercentage(rx_evmX);
-			if (i == 0) // Fill value in RFD, Get the first spatial stream only
+			if (i == 0) /* Fill value in RFD, Get the first spatial stream only */
 				pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
 			pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
 		}
@@ -4370,7 +4538,7 @@ static void rtl8192_query_rxphystatus(st
 		/* record rx statistics for debug */
 		rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
 		prxsc =	(phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
-		if (pdrvinfo->BW)	//40M channel
+		if (pdrvinfo->BW)	/* 40M channel */
 			priv->stats.received_bwtype[1+prxsc->rxsc]++;
 		else				//20M channel
 			priv->stats.received_bwtype[0]++;
@@ -4491,41 +4659,99 @@ UpdateReceivedRateHistogramStatistics819
 		//
 		// CCK rate
 		//
-	case MGN_1M:    rateIndex = 0;  break;
-	case MGN_2M:    rateIndex = 1;  break;
-	case MGN_5_5M:  rateIndex = 2;  break;
-	case MGN_11M:   rateIndex = 3;  break;
+		case MGN_1M:
+			rateIndex = 0;
+			break;
+		case MGN_2M:
+			rateIndex = 1;
+			break;
+		case MGN_5_5M:
+			rateIndex = 2;
+			break;
+		case MGN_11M:
+			rateIndex = 3;
+			break;
 		//
 		// Legacy OFDM rate
 		//
-	case MGN_6M:    rateIndex = 4;  break;
-	case MGN_9M:    rateIndex = 5;  break;
-	case MGN_12M:   rateIndex = 6;  break;
-	case MGN_18M:   rateIndex = 7;  break;
-	case MGN_24M:   rateIndex = 8;  break;
-	case MGN_36M:   rateIndex = 9;  break;
-	case MGN_48M:   rateIndex = 10; break;
-	case MGN_54M:   rateIndex = 11; break;
+		case MGN_6M:
+			rateIndex = 4;
+			break;
+		case MGN_9M:
+			rateIndex = 5;
+			break;
+		case MGN_12M:
+			rateIndex = 6;
+			break;
+		case MGN_18M:
+			rateIndex = 7;
+			break;
+		case MGN_24M:
+			rateIndex = 8;
+			break;
+		case MGN_36M:
+			rateIndex = 9;
+			break;
+		case MGN_48M:
+			rateIndex = 10;
+			break;
+		case MGN_54M:
+			rateIndex = 11;
+			break;
 		//
 		// 11n High throughput rate
 		//
-	case MGN_MCS0:  rateIndex = 12; break;
-	case MGN_MCS1:  rateIndex = 13; break;
-	case MGN_MCS2:  rateIndex = 14; break;
-	case MGN_MCS3:  rateIndex = 15; break;
-	case MGN_MCS4:  rateIndex = 16; break;
-	case MGN_MCS5:  rateIndex = 17; break;
-	case MGN_MCS6:  rateIndex = 18; break;
-	case MGN_MCS7:  rateIndex = 19; break;
-	case MGN_MCS8:  rateIndex = 20; break;
-	case MGN_MCS9:  rateIndex = 21; break;
-	case MGN_MCS10: rateIndex = 22; break;
-	case MGN_MCS11: rateIndex = 23; break;
-	case MGN_MCS12: rateIndex = 24; break;
-	case MGN_MCS13: rateIndex = 25; break;
-	case MGN_MCS14: rateIndex = 26; break;
-	case MGN_MCS15: rateIndex = 27; break;
-	default:        rateIndex = 28; break;
+		case MGN_MCS0:
+			rateIndex = 12;
+			break;
+		case MGN_MCS1:
+			rateIndex = 13;
+			break;
+		case MGN_MCS2:
+			rateIndex = 14;
+			break;
+		case MGN_MCS3:
+			rateIndex = 15;
+			break;
+		case MGN_MCS4:
+			rateIndex = 16;
+			break;
+		case MGN_MCS5:
+			rateIndex = 17;
+			break;
+		case MGN_MCS6:
+			rateIndex = 18;
+			break;
+		case MGN_MCS7:
+			rateIndex = 19;
+			break;
+		case MGN_MCS8:
+			rateIndex = 20;
+			break;
+		case MGN_MCS9:
+			rateIndex = 21;
+			break;
+		case MGN_MCS10:
+			rateIndex = 22;
+			break;
+		case MGN_MCS11:
+			rateIndex = 23;
+			break;
+		case MGN_MCS12:
+			rateIndex = 24;
+			break;
+		case MGN_MCS13:
+			rateIndex = 25;
+			break;
+		case MGN_MCS14:
+			rateIndex = 26;
+			break;
+		case MGN_MCS15:
+			rateIndex = 27;
+			break;
+		default:
+			rateIndex = 28;
+			break;
 	}
 	priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
 	priv->stats.received_rate_histogram[0][rateIndex]++; //total
@@ -5146,7 +5372,7 @@ void EnableHWSecurityConfig8192(struct n
 
 	ieee->hwsec_active = 1;
 
-	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) { //add hwsec_support flag to totol control hw_sec on/off
+	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) { /* add hwsec_support flag to totol control hw_sec on/off */
 		ieee->hwsec_active = 0;
 		SECR_value &= ~SCR_RxDecEnable;
 	}
@@ -5178,14 +5404,14 @@ void setKey(struct net_device *dev, u8 E
 		TargetCommand  = i+CAM_CONTENT_COUNT*EntryNo;
 		TargetCommand |= BIT31|BIT16;
 
-		if (i == 0) { //MAC|Config
+		if (i == 0) { /* MAC|Config */
 			TargetContent = (u32)(*(MacAddr+0)) << 16|
 					(u32)(*(MacAddr+1)) << 24|
 					(u32)usConfig;
 
 			write_nic_dword(dev, WCAMI, TargetContent);
 			write_nic_dword(dev, RWCAM, TargetCommand);
-		} else if (i == 1) { //MAC
+		} else if (i == 1) { /* MAC */
 			TargetContent = (u32)(*(MacAddr+2))	 |
 					(u32)(*(MacAddr+3)) <<  8|
 					(u32)(*(MacAddr+4)) << 16|
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8192U_wx.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8192U_wx.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r8192U_wx.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r8192U_wx.c	2014-09-28 17:29:07.000000000 -0400
@@ -57,6 +57,7 @@ static int r8192_wx_get_rate(struct net_
 			     union iwreq_data *wrqu, char *extra)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
 }
 
@@ -100,6 +101,7 @@ static int r8192_wx_get_rts(struct net_d
 			     union iwreq_data *wrqu, char *extra)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
 }
 
@@ -124,6 +126,7 @@ static int r8192_wx_get_power(struct net
 			     union iwreq_data *wrqu, char *extra)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
 }
 
@@ -180,8 +183,8 @@ static int r8192_wx_set_crcmon(struct ne
 	      priv->crcmon ? "accepted" : "rejected");
 
 	if (prev != priv->crcmon && priv->up) {
-		//rtl8180_down(dev);
-		//rtl8180_up(dev);
+		/* rtl8180_down(dev); */
+		/* rtl8180_up(dev); */
 	}
 
 	up(&priv->wx_sem);
@@ -194,6 +197,7 @@ static int r8192_wx_set_mode(struct net_
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int ret;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
@@ -249,15 +253,15 @@ static int rtl8180_wx_get_range(struct n
 	/* ~5 Mb/s real (802.11b) */
 	range->throughput = 5 * 1000 * 1000;
 
-	// TODO: Not used in 802.11b?
-//	range->min_nwid;	/* Minimal NWID we are able to set */
-	// TODO: Not used in 802.11b?
-//	range->max_nwid;	/* Maximal NWID we are able to set */
+	/* TODO: Not used in 802.11b? */
+	/* range->min_nwid; */	/* Minimal NWID we are able to set */
+	/* TODO: Not used in 802.11b? */
+	/* range->max_nwid; */	/* Maximal NWID we are able to set */
 
 	/* Old Frequency (backward compat - moved lower ) */
-//	range->old_num_channels;
-//	range->old_num_frequency;
-//	range->old_freq[6]; /* Filler to keep "version" at the same offset */
+	/* range->old_num_channels; */
+	/* range->old_num_frequency; */
+	/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
 	if (priv->rf_set_sens != NULL)
 		range->sensitivity = priv->max_sens;	/* signal level threshold range */
 
@@ -292,26 +296,26 @@ static int rtl8180_wx_get_range(struct n
 	range->we_version_compiled = WIRELESS_EXT;
 	range->we_version_source = 16;
 
-//	range->retry_capa;	/* What retry options are supported */
-//	range->retry_flags;	/* How to decode max/min retry limit */
-//	range->r_time_flags;	/* How to decode max/min retry life */
-//	range->min_retry;	/* Minimal number of retries */
-//	range->max_retry;	/* Maximal number of retries */
-//	range->min_r_time;	/* Minimal retry lifetime */
-//	range->max_r_time;	/* Maximal retry lifetime */
+	/* range->retry_capa; */	/* What retry options are supported */
+	/* range->retry_flags; */	/* How to decode max/min retry limit */
+	/* range->r_time_flags; */	/* How to decode max/min retry life */
+	/* range->min_retry; */		/* Minimal number of retries */
+	/* range->max_retry; */		/* Maximal number of retries */
+	/* range->min_r_time; */	/* Minimal retry lifetime */
+	/* range->max_r_time; */	/* Maximal retry lifetime */
 
 
 	for (i = 0, val = 0; i < 14; i++) {
 
-		// Include only legal frequencies for some countries
+		/* Include only legal frequencies for some countries */
 		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
 			range->freq[val].i = i + 1;
 			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
 			range->freq[val].e = 1;
 			val++;
 		} else {
-			// FIXME: do we need to set anything for channels
-			// we don't use ?
+			/* FIXME: do we need to set anything for channels */
+			/* we don't use ? */
 		}
 
 		if (val == IW_MAX_FREQUENCIES)
@@ -341,10 +345,8 @@ static int r8192_wx_set_scan(struct net_
 	if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
 		struct iw_scan_req *req = (struct iw_scan_req *)b;
 		if (req->essid_len) {
-			//printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
 			ieee->current_network.ssid_len = req->essid_len;
 			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
-			//printk("=====>network ssid:%s\n", ieee->current_network.ssid);
 		}
 	}
 
@@ -386,6 +388,7 @@ static int r8192_wx_set_essid(struct net
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int ret;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
@@ -434,6 +437,7 @@ static int r8192_wx_get_name(struct net_
 			     union iwreq_data *wrqu, char *extra)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
 }
 
@@ -480,7 +484,7 @@ static int r8192_wx_set_wap(struct net_d
 
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
-//        struct sockaddr *temp = (struct sockaddr *)awrq;
+	/* struct sockaddr *temp = (struct sockaddr *)awrq; */
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
@@ -518,12 +522,9 @@ static int r8192_wx_set_enc(struct net_d
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
 	int ret;
-
-	//u32 TargetContent;
 	u32 hwkey[4] = {0, 0, 0, 0};
 	u8 mask = 0xff;
 	u32 key_idx = 0;
-	//u8 broadcast_addr[6] ={	0xff,0xff,0xff,0xff,0xff,0xff};
 	u8 zero_addr[4][6] = {	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 				{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
 				{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
@@ -542,7 +543,7 @@ static int r8192_wx_set_enc(struct net_d
 
 
 
-	//sometimes, the length is zero while we do not type key value
+	/* sometimes, the length is zero while we do not type key value */
 	if (wrqu->encoding.length != 0) {
 
 		for (i = 0; i < 4; i++) {
@@ -584,12 +585,12 @@ static int r8192_wx_set_enc(struct net_d
 			EnableHWSecurityConfig8192(dev);
 
 			setKey(dev,
-				key_idx,                //EntryNo
-				key_idx,                //KeyIndex
-				KEY_TYPE_WEP40,         //KeyType
+				key_idx,                /* EntryNo */
+				key_idx,                /* KeyIndex */
+				KEY_TYPE_WEP40,         /* KeyType */
 				zero_addr[key_idx],
-				0,                      //DefaultKey
-				hwkey);                 //KeyContent
+				0,                      /* DefaultKey */
+				hwkey);                 /* KeyContent */
 
 		}
 
@@ -598,12 +599,12 @@ static int r8192_wx_set_enc(struct net_d
 				EnableHWSecurityConfig8192(dev);
 
 			setKey(dev,
-				key_idx,                //EntryNo
-				key_idx,                //KeyIndex
-				KEY_TYPE_WEP104,        //KeyType
+				key_idx,                /* EntryNo */
+				key_idx,                /* KeyIndex */
+				KEY_TYPE_WEP104,        /* KeyType */
 				zero_addr[key_idx],
-				0,                      //DefaultKey
-				hwkey);                 //KeyContent
+				0,                      /* DefaultKey */
+				hwkey);                 /* KeyContent */
 
 		} else {
 			printk("wrong type in WEP, not WEP40 and WEP104\n");
@@ -669,14 +670,6 @@ static int r8192_wx_set_retry(struct net
 	 */
 
 	rtl8192_commit(dev);
-	/*
-	if(priv->up){
-		rtl8180_rtx_disable(dev);
-		rtl8180_rx_enable(dev);
-		rtl8180_tx_enable(dev);
-
-	}
-	*/
 exit:
 	up(&priv->wx_sem);
 
@@ -703,7 +696,6 @@ static int r8192_wx_get_retry(struct net
 		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
 		wrqu->retry.value = priv->retry_data;
 	}
-	//printk("returning %d",wrqu->retry.value);
 
 
 	return 0;
@@ -714,6 +706,7 @@ static int r8192_wx_get_sens(struct net_
 				union iwreq_data *wrqu, char *extra)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	if (priv->rf_set_sens == NULL)
 		return -1; /* we have not this support for this radio */
 	wrqu->sens.value = priv->sens;
@@ -727,10 +720,9 @@ static int r8192_wx_set_sens(struct net_
 {
 
 	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	short err = 0;
+
 	down(&priv->wx_sem);
-	//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
 	if (priv->rf_set_sens == NULL) {
 		err = -1; /* we have not this support for this radio */
 		goto exit;
@@ -746,7 +738,7 @@ exit:
 	return err;
 }
 
-//hw security need to reorganized.
+/* hw security need to reorganized. */
 static int r8192_wx_set_enc_ext(struct net_device *dev,
 					struct iw_request_info *info,
 					union iwreq_data *wrqu, char *extra)
@@ -754,7 +746,6 @@ static int r8192_wx_set_enc_ext(struct n
 	int ret = 0;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
-	//printk("===>%s()\n", __func__);
 
 
 	down(&priv->wx_sem);
@@ -768,10 +759,10 @@ static int r8192_wx_set_enc_ext(struct n
 		struct iw_point *encoding = &wrqu->encoding;
 		u8 idx = 0, alg = 0, group = 0;
 		if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
-			//none is not allowed to use hwsec WB 2008.07.01
+			/* none is not allowed to use hwsec WB 2008.07.01 */
 			goto end_hw_sec;
 
-		// as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
+		/* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
 		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
 		idx = encoding->flags & IW_ENCODE_INDEX;
 		if (idx)
@@ -784,34 +775,34 @@ static int r8192_wx_set_enc_ext(struct n
 			ieee->pairwise_key_type = alg;
 			EnableHWSecurityConfig8192(dev);
 		}
-		memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
+		memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
 
 		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
 
 			setKey(dev,
-					idx,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					zero, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
+					idx,	/* EntryNao */
+					idx,	/* KeyIndex */
+					alg,	/* KeyType */
+					zero,	/* MacAddr */
+					0,	/* DefaultKey */
+					key);	/* KeyContent */
 		} else if (group) {
 			ieee->group_key_type = alg;
 			setKey(dev,
-					idx,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					broadcast_addr, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
-		} else {//pairwise key
+					idx,	/* EntryNo */
+					idx,	/* KeyIndex */
+					alg,	/* KeyType */
+					broadcast_addr,	/* MacAddr */
+					0,		/* DefaultKey */
+					key);		/* KeyContent */
+		} else {	/* pairwise key */
 			setKey(dev,
-					4,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					(u8 *)ieee->ap_mac_addr, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
+					4,	/* EntryNo */
+					idx,	/* KeyIndex */
+					alg,	/* KeyType */
+					(u8 *)ieee->ap_mac_addr,/* MacAddr */
+					0,			/* DefaultKey */
+					key);			/* KeyContent */
 		}
 
 
@@ -828,8 +819,8 @@ static int r8192_wx_set_auth(struct net_
 					union iwreq_data *data, char *extra)
 {
 	int ret = 0;
-	//printk("====>%s()\n", __func__);
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	down(&priv->wx_sem);
 	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
 	up(&priv->wx_sem);
@@ -840,10 +831,10 @@ static int r8192_wx_set_mlme(struct net_
 					struct iw_request_info *info,
 					union iwreq_data *wrqu, char *extra)
 {
-	//printk("====>%s()\n", __func__);
 
 	int ret = 0;
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	down(&priv->wx_sem);
 	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
 
@@ -855,13 +846,12 @@ static int r8192_wx_set_gen_ie(struct ne
 					struct iw_request_info *info,
 					union iwreq_data *data, char *extra)
 {
-	   //printk("====>%s(), len:%d\n", __func__, data->length);
 	int ret = 0;
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	down(&priv->wx_sem);
 	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
 	up(&priv->wx_sem);
-	//printk("<======%s(), ret:%d\n", __func__, ret);
 	return ret;
 
 
@@ -923,13 +913,13 @@ static iw_handler r8192_wx_handlers[] =
 	r8192_wx_get_power,                    /* SIOCGIWPOWER */
 	NULL,			/*---hole---*/
 	NULL,			/*---hole---*/
-	r8192_wx_set_gen_ie,//NULL,			/* SIOCSIWGENIE */
+	r8192_wx_set_gen_ie, /* NULL, */		/* SIOCSIWGENIE */
 	NULL,			/* SIOCSIWGENIE */
 
-	r8192_wx_set_auth,//NULL,			/* SIOCSIWAUTH */
-	NULL,//r8192_wx_get_auth,//NULL,			/* SIOCSIWAUTH */
+	r8192_wx_set_auth,/* NULL, */			/* SIOCSIWAUTH */
+	NULL,/* r8192_wx_get_auth, */ /* NULL, */	/* SIOCSIWAUTH */
 	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
-	NULL,//r8192_wx_get_enc_ext,//NULL,			/* SIOCSIWENCODEEXT */
+	NULL,/* r8192_wx_get_enc_ext, *//* NULL, */			/* SIOCSIWENCODEEXT */
 	NULL,			/* SIOCSIWPMKSA */
 	NULL,			 /*---hole---*/
 
@@ -962,14 +952,9 @@ static const struct iw_priv_args r8192_p
 
 
 static iw_handler r8192_private_handler[] = {
-//	r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
-	r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
-//	r8192_wx_set_forceassociate,
-//	r8192_wx_set_beaconinterval,
-//	r8192_wx_set_monitor_type,
+	r8192_wx_set_crcmon,
 	r8192_wx_set_scan_type,
 	r8192_wx_set_rawtx,
-	//r8192_wx_null,
 	r8192_wx_force_reset,
 };
 
@@ -981,6 +966,7 @@ struct iw_statistics *r8192_get_wireless
 	int tmp_level = 0;
 	int tmp_qual = 0;
 	int tmp_noise = 0;
+
 	if (ieee->state < IEEE80211_LINKED) {
 		wstats->qual.qual = 0;
 		wstats->qual.level = 0;
@@ -992,12 +978,11 @@ struct iw_statistics *r8192_get_wireless
 	tmp_level = (&ieee->current_network)->stats.rssi;
 	tmp_qual = (&ieee->current_network)->stats.signal;
 	tmp_noise = (&ieee->current_network)->stats.noise;
-	//printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
 
 	wstats->qual.level = tmp_level;
 	wstats->qual.qual = tmp_qual;
 	wstats->qual.noise = tmp_noise;
-	wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
+	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 	return wstats;
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8192u/r819xU_phy.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r819xU_phy.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8192u/r819xU_phy.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8192u/r819xU_phy.c	2014-09-28 17:29:07.000000000 -0400
@@ -101,7 +101,6 @@ void rtl8192_setBBreg(struct net_device
 	} else {
 		write_nic_dword(dev, reg_addr, data);
 	}
-	return;
 }
 
 /******************************************************************************
@@ -281,7 +280,6 @@ static void rtl8192_phy_RFSerialWrite(st
 					 priv->RfReg0Value[eRFPath] << 16);
 		}
 	}
-	return;
 }
 
 /******************************************************************************
@@ -332,7 +330,6 @@ void rtl8192_phy_SetRFReg(struct net_dev
 			rtl8192_phy_RFSerialWrite(dev, eRFPath, reg_addr, data);
 		}
 	}
-	return;
 }
 
 /******************************************************************************
@@ -513,7 +510,6 @@ void rtl8192_phy_configmac(struct net_de
 		rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1],
 				 pdwArray[i+2]);
 	}
-	return;
 }
 
 /******************************************************************************
@@ -559,7 +555,6 @@ void rtl8192_phyConfigBB(struct net_devi
 				 rtl819XAGCTAB_Array[i+1]);
 		}
 	}
-	return;
 }
 
 /******************************************************************************
@@ -846,7 +841,6 @@ static void rtl8192_BB_Config_ParaFile(s
 	priv->bCckHighPower = (u8)rtl8192_QueryBBReg(dev,
 						     rFPGA0_XA_HSSIParameter2,
 						     0x200);
-	return;
 }
 
 /******************************************************************************
@@ -864,7 +858,6 @@ void rtl8192_BBConfig(struct net_device
 	 * implemented, so use file first.
 	 * FIXME: should implement it for hardcode? */
 	rtl8192_BB_Config_ParaFile(dev);
-	return;
 }
 
 
@@ -912,8 +905,6 @@ void rtl8192_phy_getTxPower(struct net_d
 
 	/* Read SIFS (save the value read fome MACPHY_REG.txt) */
 	read_nic_word(dev, SIFS, &priv->SifsTime);
-
-	return;
 }
 
 /******************************************************************************
@@ -942,7 +933,6 @@ void rtl8192_phy_setTxPower(struct net_d
 			 __func__);
 		break;
 	}
-	return;
 }
 
 /******************************************************************************
@@ -956,14 +946,13 @@ void rtl8192_phy_RFConfig(struct net_dev
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	switch (priv->rf_chip) {
-		case RF_8256:
-			PHY_RF8256_Config(dev);
-			break;
-		default:
-			RT_TRACE(COMP_ERR, "error chip id\n");
-			break;
+	case RF_8256:
+		PHY_RF8256_Config(dev);
+		break;
+	default:
+		RT_TRACE(COMP_ERR, "error chip id\n");
+		break;
 	}
-	return;
 }
 
 /******************************************************************************
@@ -974,7 +963,6 @@ void rtl8192_phy_RFConfig(struct net_dev
  ******************************************************************************/
 void rtl8192_phy_updateInitGain(struct net_device *dev)
 {
-	return;
 }
 
 /******************************************************************************
@@ -1094,7 +1082,6 @@ static void rtl8192_SetTxPowerLevel(stru
 		RT_TRACE(COMP_ERR, "unknown rf chip ID in %s()\n", __func__);
 		break;
 	}
-	return;
 }
 
 /******************************************************************************
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/drv_types.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/drv_types.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/drv_types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/drv_types.h	2014-09-28 17:29:07.000000000 -0400
@@ -160,7 +160,6 @@ struct _adapter {
 	s32	bSurpriseRemoved;
 	u32	IsrContent;
 	u32	ImrContent;
-	bool	fw_found;
 	u8	EepromAddressSize;
 	u8	hw_init_completed;
 	struct task_struct *cmdThread;
@@ -174,7 +173,7 @@ struct _adapter {
 	struct net_device_stats stats;
 	struct iw_statistics iwstats;
 	int pid; /*process id from UI*/
-	_workitem wkFilterRxFF0;
+	struct work_struct wkFilterRxFF0;
 	u8 blnEnableRxFF0Filter;
 	spinlock_t lockRxFF0Filter;
 	const struct firmware *fw;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/hal_init.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/hal_init.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/hal_init.c	2014-08-07 04:57:01.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/hal_init.c	2014-09-28 21:39:22.000000000 -0400
@@ -50,13 +50,11 @@ static void rtl871x_load_fw_cb(const str
 		struct usb_device *udev = padapter->dvobjpriv.pusbdev;
 		struct usb_interface *pusb_intf = padapter->pusb_intf;
 		dev_err(&udev->dev, "r8712u: Firmware request failed\n");
-		padapter->fw_found = false;
 		usb_put_dev(udev);
 		usb_set_intfdata(pusb_intf, NULL);
 		return;
 	}
 	padapter->fw = firmware;
-	padapter->fw_found = true;
 	/* firmware available - start netdev */
 	register_netdev(padapter->pnetdev);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/ieee80211.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/ieee80211.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/ieee80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/ieee80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -734,7 +734,7 @@ enum ieee80211_state {
 #define IEEE_G            (1<<2)
 #define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -748,7 +748,7 @@ extern inline int ieee80211_is_empty_ess
 	return 1;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = 24;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/mlme_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/mlme_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/mlme_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/mlme_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -44,18 +44,21 @@ static void sitesurvey_ctrl_handler(void
 static void join_timeout_handler (void *FunctionContext)
 {
 	struct _adapter *adapter = (struct _adapter *)FunctionContext;
+
 	_r8712_join_timeout_handler(adapter);
 }
 
 static void _scan_timeout_handler (void *FunctionContext)
 {
 	struct _adapter *adapter = (struct _adapter *)FunctionContext;
+
 	r8712_scan_timeout_handler(adapter);
 }
 
 static void dhcp_timeout_handler (void *FunctionContext)
 {
 	struct _adapter *adapter = (struct _adapter *)FunctionContext;
+
 	_r8712_dhcp_timeout_handler(adapter);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/osdep_service.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/osdep_service.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/osdep_service.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/osdep_service.h	2014-09-28 17:29:07.000000000 -0400
@@ -50,32 +50,16 @@ struct	__queue	{
 #define _pkt struct sk_buff
 #define _buffer unsigned char
 #define thread_exit() complete_and_exit(NULL, 0)
-#define _workitem struct work_struct
 
 #define _init_queue(pqueue)				\
 	do {						\
-		_init_listhead(&((pqueue)->queue));	\
+		INIT_LIST_HEAD(&((pqueue)->queue));	\
 		spin_lock_init(&((pqueue)->lock));	\
 	} while (0)
 
-static inline struct list_head *get_next(struct list_head *list)
-{
-	return list->next;
-}
-
-static inline struct list_head *get_list_head(struct  __queue *queue)
-{
-	return &(queue->queue);
-}
-
 #define LIST_CONTAINOR(ptr, type, member) \
 	((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member)))
 
-static inline void list_delete(struct list_head *plist)
-{
-	list_del_init(plist);
-}
-
 static inline void _init_timer(struct timer_list *ptimer,
 			       struct  net_device *padapter,
 			       void *pfunc, void *cntx)
@@ -96,39 +80,10 @@ static inline void _cancel_timer(struct
 	*bcancelled = true; /*true ==1; false==0*/
 }
 
-static inline void _init_workitem(_workitem *pwork, void *pfunc, void *cntx)
-{
-	INIT_WORK(pwork, pfunc);
-}
-
-static inline void _set_workitem(_workitem *pwork)
-{
-	schedule_work(pwork);
-}
-
 #ifndef BIT
 	#define BIT(x)	(1 << (x))
 #endif
 
-/*
-For the following list_xxx operations,
-caller must guarantee the atomic context.
-Otherwise, there will be racing condition.
-*/
-static inline u32 is_list_empty(struct list_head *phead)
-{
-	if (list_empty(phead))
-		return true;
-	else
-		return false;
-}
-
-static inline void list_insert_tail(struct list_head *plist,
-				    struct list_head *phead)
-{
-	list_add_tail(plist, phead);
-}
-
 static inline u32 _down_sema(struct semaphore *sema)
 {
 	if (down_interruptible(sema))
@@ -137,16 +92,6 @@ static inline u32 _down_sema(struct sema
 		return _SUCCESS;
 }
 
-static inline void _init_listhead(struct list_head *list)
-{
-	INIT_LIST_HEAD(list);
-}
-
-static inline u32 _queue_empty(struct  __queue *pqueue)
-{
-	return is_list_empty(&(pqueue->queue));
-}
-
 static inline u32 end_of_queue_search(struct list_head *head,
 		struct list_head *plist)
 {
@@ -173,36 +118,11 @@ static inline unsigned char _cancel_time
 	return del_timer(ptimer);
 }
 
-static inline void thread_enter(void *context)
-{
-	allow_signal(SIGTERM);
-}
-
 static inline void flush_signals_thread(void)
 {
 	if (signal_pending(current))
 		flush_signals(current);
 }
 
-static inline u32 _RND8(u32 sz)
-{
-	return ((sz >> 3) + ((sz & 7) ? 1 : 0)) << 3;
-}
-
-static inline u32 _RND128(u32 sz)
-{
-	return ((sz >> 7) + ((sz & 127) ? 1 : 0)) << 7;
-}
-
-static inline u32 _RND256(u32 sz)
-{
-	return ((sz >> 8) + ((sz & 255) ? 1 : 0)) << 8;
-}
-
-static inline u32 _RND512(u32 sz)
-{
-	return ((sz >> 9) + ((sz & 511) ? 1 : 0)) << 9;
-}
-
 #endif
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/os_intfs.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/os_intfs.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/os_intfs.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/os_intfs.c	2014-09-28 17:29:07.000000000 -0400
@@ -345,8 +345,7 @@ u8 r8712_free_drv_sw(struct _adapter *pa
 	r8712_free_mlme_priv(&padapter->mlmepriv);
 	r8712_free_io_queue(padapter);
 	_free_xmit_priv(&padapter->xmitpriv);
-	if (padapter->fw_found)
-		_r8712_free_sta_priv(&padapter->stapriv);
+	_r8712_free_sta_priv(&padapter->stapriv);
 	_r8712_free_recv_priv(&padapter->recvpriv);
 	mp871xdeinit(padapter);
 	if (pnetdev)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -326,7 +326,7 @@ int r8712_cmd_thread(void *context)
 	struct _adapter *padapter = (struct _adapter *)context;
 	struct	cmd_priv	*pcmdpriv = &(padapter->cmdpriv);
 
-	thread_enter(padapter);
+	allow_signal(SIGTERM);
 	while (1) {
 		if ((_down_sema(&(pcmdpriv->cmd_queue_sema))) == _FAIL)
 			break;
@@ -351,7 +351,7 @@ _next:
 						    &padapter->dvobjpriv;
 			u8 blnPending = 0;
 			pcmdpriv->cmd_issued_cnt++;
-			cmdsz = _RND8((pcmd->cmdsz)); /* _RND8	*/
+			cmdsz = round_up(pcmd->cmdsz, 8);
 			wr_sz = TXDESC_SIZE + 8 + cmdsz;
 			pdesc->txdw0 |= cpu_to_le32((wr_sz-TXDESC_SIZE) &
 						     0x0000ffff);
@@ -410,7 +410,7 @@ _next:
 				}
 			}
 			r8712_free_cmd_obj(pcmd);
-			if (_queue_empty(&(pcmdpriv->cmd_queue))) {
+			if (list_empty(&pcmdpriv->cmd_queue.queue)) {
 				r8712_unregister_cmd_alive(padapter);
 				continue;
 			} else
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_led.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_led.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_led.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_led.c	2014-09-28 17:29:07.000000000 -0400
@@ -98,7 +98,7 @@ static void InitLed871x(struct _adapter
 	pLed->BlinkTimes = 0;
 	pLed->BlinkingLedState = LED_UNKNOWN;
 	_init_timer(&(pLed->BlinkTimer), nic, BlinkTimerCallback, pLed);
-	_init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed);
+	INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
 }
 
 /*
@@ -827,7 +827,7 @@ static void BlinkTimerCallback(unsigned
 	if ((pLed->padapter->bSurpriseRemoved == true) ||
 	    (pLed->padapter->bDriverStopped == true))
 		return;
-	_set_workitem(&(pLed->BlinkWorkItem));
+	schedule_work(&pLed->BlinkWorkItem);
 }
 
 /*	Description:
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_recv.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_recv.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -66,14 +66,14 @@ int r8712_init_recv_priv(struct recv_pri
 			      ((addr_t) (precvpriv->pallocated_recv_buf) & 3);
 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
 	for (i = 0; i < NR_RECVBUFF; i++) {
-		_init_listhead(&precvbuf->list);
+		INIT_LIST_HEAD(&precvbuf->list);
 		spin_lock_init(&precvbuf->recvbuf_lock);
 		res = r8712_os_recvbuf_resource_alloc(padapter, precvbuf);
 		if (res == _FAIL)
 			break;
 		precvbuf->ref_cnt = 0;
 		precvbuf->adapter = padapter;
-		list_insert_tail(&precvbuf->list,
+		list_add_tail(&precvbuf->list,
 				 &(precvpriv->free_recv_buf_queue.queue));
 		precvbuf++;
 	}
@@ -145,9 +145,8 @@ int r8712_free_recvframe(union recv_fram
 		precvframe->u.hdr.pkt = NULL;
 	}
 	spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
-	list_delete(&(precvframe->u.hdr.list));
-	list_insert_tail(&(precvframe->u.hdr.list),
-			 get_list_head(pfree_recv_queue));
+	list_del_init(&(precvframe->u.hdr.list));
+	list_add_tail(&(precvframe->u.hdr.list), &pfree_recv_queue->queue);
 	if (padapter != NULL) {
 		if (pfree_recv_queue == &precvpriv->free_recv_queue)
 				precvpriv->free_recvframe_cnt++;
@@ -208,10 +207,10 @@ static union recv_frame *recvframe_defra
 	struct  __queue	*pfree_recv_queue;
 
 	pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
-	phead = get_list_head(defrag_q);
-	plist = get_next(phead);
+	phead = &defrag_q->queue;
+	plist = phead->next;
 	prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-	list_delete(&prframe->u.list);
+	list_del_init(&prframe->u.list);
 	pfhdr = &prframe->u.hdr;
 	curfragnum = 0;
 	if (curfragnum != pfhdr->attrib.frag_num) {
@@ -222,8 +221,8 @@ static union recv_frame *recvframe_defra
 		return NULL;
 	}
 	curfragnum++;
-	plist = get_list_head(defrag_q);
-	plist = get_next(plist);
+	plist = &defrag_q->queue;
+	plist = plist->next;
 	data = get_recvframe_data(prframe);
 	while (end_of_queue_search(phead, plist) == false) {
 		pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
@@ -247,7 +246,7 @@ static union recv_frame *recvframe_defra
 		memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
 		recvframe_put(prframe, pnfhdr->len);
 		pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	/* free the defrag_q queue and return the prframe */
 	r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
@@ -289,15 +288,15 @@ union recv_frame *r8712_recvframe_chk_de
 		if (pdefrag_q != NULL) {
 			if (fragnum == 0) {
 				/*the first fragment*/
-				if (_queue_empty(pdefrag_q) == false) {
+				if (!list_empty(&pdefrag_q->queue)) {
 					/*free current defrag_q */
 					r8712_free_recvframe_queue(pdefrag_q,
 							     pfree_recv_queue);
 				}
 			}
 			/* Then enqueue the 0~(n-1) fragment to the defrag_q */
-			phead = get_list_head(pdefrag_q);
-			list_insert_tail(&pfhdr->list, phead);
+			phead = &pdefrag_q->queue;
+			list_add_tail(&pfhdr->list, phead);
 			prtnframe = NULL;
 		} else {
 			/* can't find this ta's defrag_queue, so free this
@@ -311,8 +310,8 @@ union recv_frame *r8712_recvframe_chk_de
 		/* the last fragment frame
 		 * enqueue the last fragment */
 		if (pdefrag_q != NULL) {
-			phead = get_list_head(pdefrag_q);
-			list_insert_tail(&pfhdr->list, phead);
+			phead = &pdefrag_q->queue;
+			list_add_tail(&pfhdr->list, phead);
 			/*call recvframe_defrag to defrag*/
 			precv_frame = recvframe_defrag(padapter, pdefrag_q);
 			prtnframe = precv_frame;
@@ -499,20 +498,20 @@ static int enqueue_reorder_recvframe(str
 					&preorder_ctrl->pending_recvframe_queue;
 	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
 
-	phead = get_list_head(ppending_recvframe_queue);
-	plist = get_next(phead);
+	phead = &ppending_recvframe_queue->queue;
+	plist = phead->next;
 	while (end_of_queue_search(phead, plist) == false) {
 		pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
 		pnextattrib = &pnextrframe->u.hdr.attrib;
 		if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
-			plist = get_next(plist);
+			plist = plist->next;
 		else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
 			return false;
 		else
 			break;
 	}
-	list_delete(&(prframe->u.hdr.list));
-	list_insert_tail(&(prframe->u.hdr.list), plist);
+	list_del_init(&(prframe->u.hdr.list));
+	list_add_tail(&(prframe->u.hdr.list), plist);
 	return true;
 }
 
@@ -528,11 +527,11 @@ int r8712_recv_indicatepkts_in_order(str
 	struct  __queue *ppending_recvframe_queue =
 			 &preorder_ctrl->pending_recvframe_queue;
 
-	phead = get_list_head(ppending_recvframe_queue);
-	plist = get_next(phead);
+	phead = &ppending_recvframe_queue->queue;
+	plist = phead->next;
 	/* Handling some condition for forced indicate case.*/
 	if (bforced == true) {
-		if (is_list_empty(phead))
+		if (list_empty(phead))
 			return true;
 		else {
 			prframe = LIST_CONTAINOR(plist, union recv_frame, u);
@@ -542,12 +541,12 @@ int r8712_recv_indicatepkts_in_order(str
 	}
 	/* Prepare indication list and indication.
 	 * Check if there is any packet need indicate. */
-	while (!is_list_empty(phead)) {
+	while (!list_empty(phead)) {
 		prframe = LIST_CONTAINOR(plist, union recv_frame, u);
 		pattrib = &prframe->u.hdr.attrib;
 		if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
-			plist = get_next(plist);
-			list_delete(&(prframe->u.hdr.list));
+			plist = plist->next;
+			list_del_init(&(prframe->u.hdr.list));
 			if (SN_EQUAL(preorder_ctrl->indicate_seq,
 			    pattrib->seq_num))
 				preorder_ctrl->indicate_seq =
@@ -1061,11 +1060,11 @@ static int recvbuf2recvframe(struct _ada
 		precvframe = r8712_alloc_recvframe(pfree_recv_queue);
 		if (precvframe == NULL)
 			goto  _exit_recvbuf2recvframe;
-		_init_listhead(&precvframe->u.hdr.list);
+		INIT_LIST_HEAD(&precvframe->u.hdr.list);
 		precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/
 		precvframe->u.hdr.len = 0;
 		tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE;
-		pkt_offset = (u16)_RND128(tmp_len);
+		pkt_offset = (u16)round_up(tmp_len, 128);
 		/* for first fragment packet, driver need allocate 1536 +
 		 * drvinfo_sz + RXDESC_SIZE to defrag packet. */
 		if ((mf == 1) && (frag == 0))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl8712_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl8712_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,12 +166,12 @@ static struct xmit_frame *dequeue_one_xm
 	struct list_head *xmitframe_plist, *xmitframe_phead;
 	struct	xmit_frame *pxmitframe = NULL;
 
-	xmitframe_phead = get_list_head(pframe_queue);
-	xmitframe_plist = get_next(xmitframe_phead);
+	xmitframe_phead = &pframe_queue->queue;
+	xmitframe_plist = xmitframe_phead->next;
 	if ((end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false) {
 		pxmitframe = LIST_CONTAINOR(xmitframe_plist,
 			     struct xmit_frame, list);
-		list_delete(&pxmitframe->list);
+		list_del_init(&pxmitframe->list);
 		ptxservq->qcnt--;
 		phwxmit->txcmdcnt++;
 	}
@@ -210,8 +210,8 @@ static struct xmit_frame *dequeue_xframe
 	spin_lock_irqsave(&pxmitpriv->lock, irqL0);
 	for (i = 0; i < entry; i++) {
 		phwxmit = phwxmit_i + inx[i];
-		sta_phead = get_list_head(phwxmit->sta_queue);
-		sta_plist = get_next(sta_phead);
+		sta_phead = &phwxmit->sta_queue->queue;
+		sta_plist = sta_phead->next;
 		while ((end_of_queue_search(sta_phead, sta_plist)) == false) {
 			ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq,
 				  tx_pending);
@@ -222,11 +222,13 @@ static struct xmit_frame *dequeue_xframe
 				phwxmit->accnt--;
 				goto exit_dequeue_xframe_ex;
 			}
-			sta_plist = get_next(sta_plist);
+			sta_plist = sta_plist->next;
 			/*Remove sta node when there are no pending packets.*/
-			if (_queue_empty(pframe_queue)) {
-				/*must be done after get_next and before break*/
-				list_delete(&ptxservq->tx_pending);
+			if (list_empty(&pframe_queue->queue)) {
+				/* must be done after sta_plist->next
+				 * and before break
+				 */
+				list_del_init(&ptxservq->tx_pending);
 			}
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -126,7 +126,7 @@ static sint _enqueue_cmd(struct  __queue
 	if (obj == NULL)
 		return _SUCCESS;
 	spin_lock_irqsave(&queue->lock, irqL);
-	list_insert_tail(&obj->list, &queue->queue);
+	list_add_tail(&obj->list, &queue->queue);
 	spin_unlock_irqrestore(&queue->lock, irqL);
 	return _SUCCESS;
 }
@@ -137,12 +137,12 @@ static struct cmd_obj *_dequeue_cmd(stru
 	struct cmd_obj *obj;
 
 	spin_lock_irqsave(&(queue->lock), irqL);
-	if (is_list_empty(&(queue->queue)))
+	if (list_empty(&(queue->queue)))
 		obj = NULL;
 	else {
-		obj = LIST_CONTAINOR(get_next(&(queue->queue)),
+		obj = LIST_CONTAINOR(queue->queue.next,
 				     struct cmd_obj, list);
-		list_delete(&obj->list);
+		list_del_init(&obj->list);
 	}
 	spin_unlock_irqrestore(&(queue->lock), irqL);
 	return obj;
@@ -190,7 +190,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv
 		return _FAIL;
 	queue = &pcmdpriv->cmd_queue;
 	spin_lock_irqsave(&queue->lock, irqL);
-	list_insert_tail(&obj->list, &queue->queue);
+	list_add_tail(&obj->list, &queue->queue);
 	spin_unlock_irqrestore(&queue->lock, irqL);
 	up(&pcmdpriv->cmd_queue_sema);
 	return _SUCCESS;
@@ -227,10 +227,10 @@ u8 r8712_sitesurvey_cmd(struct _adapter
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psurveyPara = kmalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
+	psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC);
 	if (psurveyPara == NULL) {
 		kfree((unsigned char *) ph2c);
 		return _FAIL;
@@ -259,11 +259,10 @@ u8 r8712_setdatarate_cmd(struct _adapter
 	struct setdatarate_parm	*pbsetdataratepara;
 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pbsetdataratepara = kmalloc(sizeof(struct setdatarate_parm),
-				    GFP_ATOMIC);
+	pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
 	if (pbsetdataratepara == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -282,11 +281,10 @@ u8 r8712_set_chplan_cmd(struct _adapter
 	struct SetChannelPlan_param *psetchplanpara;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetchplanpara = kmalloc(sizeof(struct SetChannelPlan_param),
-				 GFP_ATOMIC);
+	psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC);
 	if (psetchplanpara == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -304,11 +302,10 @@ u8 r8712_setbasicrate_cmd(struct _adapte
 	struct setbasicrate_parm *pssetbasicratepara;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pssetbasicratepara = kmalloc(sizeof(struct setbasicrate_parm),
-				     GFP_ATOMIC);
+	pssetbasicratepara = kmalloc(sizeof(*pssetbasicratepara), GFP_ATOMIC);
 	if (pssetbasicratepara == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -327,10 +324,10 @@ u8 r8712_setptm_cmd(struct _adapter *pad
 	struct writePTM_parm	*pwriteptmparm;
 	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pwriteptmparm = kmalloc(sizeof(struct writePTM_parm), GFP_ATOMIC);
+	pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC);
 	if (pwriteptmparm == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -347,10 +344,10 @@ u8 r8712_setfwdig_cmd(struct _adapter *p
 	struct writePTM_parm *pwriteptmparm;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pwriteptmparm = kmalloc(sizeof(struct writePTM_parm), GFP_ATOMIC);
+	pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC);
 	if (pwriteptmparm == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -367,10 +364,10 @@ u8 r8712_setfwra_cmd(struct _adapter *pa
 	struct writePTM_parm *pwriteptmparm;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pwriteptmparm = kmalloc(sizeof(struct writePTM_parm), GFP_ATOMIC);
+	pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC);
 	if (pwriteptmparm == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -387,10 +384,10 @@ u8 r8712_setrfreg_cmd(struct _adapter  *
 	struct writeRF_parm *pwriterfparm;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pwriterfparm = kmalloc(sizeof(struct writeRF_parm), GFP_ATOMIC);
+	pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC);
 	if (pwriterfparm == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -408,15 +405,15 @@ u8 r8712_getrfreg_cmd(struct _adapter *p
 	struct readRF_parm *prdrfparm;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	prdrfparm = kmalloc(sizeof(struct readRF_parm), GFP_ATOMIC);
+	prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC);
 	if (prdrfparm == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
 	}
-	_init_listhead(&ph2c->list);
+	INIT_LIST_HEAD(&ph2c->list);
 	ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
 	ph2c->parmbuf = (unsigned char *)prdrfparm;
 	ph2c->cmdsz =  sizeof(struct readRF_parm);
@@ -452,10 +449,10 @@ u8 r8712_createbss_cmd(struct _adapter *
 				 &padapter->registrypriv.dev_network;
 
 	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
-	pcmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 	if (pcmd == NULL)
 		return _FAIL;
-	_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	pcmd->cmdcode = _CreateBss_CMD_;
 	pcmd->parmbuf = (unsigned char *)pdev_network;
 	pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz((
@@ -486,7 +483,7 @@ u8 r8712_joinbss_cmd(struct _adapter  *p
 						network.InfrastructureMode;
 
 	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
-	pcmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 	if (pcmd == NULL)
 		return _FAIL;
 	t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 +
@@ -609,7 +606,7 @@ u8 r8712_joinbss_cmd(struct _adapter  *p
 				psecnetwork->InfrastructureMode);
 	psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
 #endif
-	_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	pcmd->cmdcode = _JoinBss_CMD_;
 	pcmd->parmbuf = (unsigned char *)psecnetwork;
 	pcmd->rsp = NULL;
@@ -624,10 +621,10 @@ u8 r8712_disassoc_cmd(struct _adapter *p
 	struct disconnect_parm *pdisconnect;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pdisconnect_cmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
 	if (pdisconnect_cmd == NULL)
 		return _FAIL;
-	pdisconnect = kmalloc(sizeof(struct disconnect_parm), GFP_ATOMIC);
+	pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
 	if (pdisconnect == NULL) {
 		kfree((u8 *)pdisconnect_cmd);
 		return _FAIL;
@@ -646,10 +643,10 @@ u8 r8712_setopmode_cmd(struct _adapter *
 
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetop = kmalloc(sizeof(struct setopmode_parm), GFP_ATOMIC);
+	psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
 	if (psetop == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -670,15 +667,15 @@ u8 r8712_setstakey_cmd(struct _adapter *
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct sta_info *sta = (struct sta_info *)psta;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetstakey_para = kmalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC);
+	psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
 	if (psetstakey_para == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
 	}
-	psetstakey_rsp = kmalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC);
+	psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
 	if (psetstakey_rsp == NULL) {
 		kfree((u8 *) ph2c);
 		kfree((u8 *) psetstakey_para);
@@ -710,10 +707,10 @@ u8 r8712_setrfintfs_cmd(struct _adapter
 	struct setrfintfs_parm *psetrfintfsparm;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetrfintfsparm = kmalloc(sizeof(struct setrfintfs_parm), GFP_ATOMIC);
+	psetrfintfsparm = kmalloc(sizeof(*psetrfintfsparm), GFP_ATOMIC);
 	if (psetrfintfsparm == NULL) {
 		kfree((unsigned char *) ph2c);
 		return _FAIL;
@@ -732,10 +729,10 @@ u8 r8712_setrttbl_cmd(struct _adapter *p
 	struct setratable_parm *psetrttblparm;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetrttblparm = kmalloc(sizeof(struct setratable_parm), GFP_ATOMIC);
+	psetrttblparm = kmalloc(sizeof(*psetrttblparm), GFP_ATOMIC);
 	if (psetrttblparm == NULL) {
 		kfree((unsigned char *)ph2c);
 		return _FAIL;
@@ -753,15 +750,15 @@ u8 r8712_gettssi_cmd(struct _adapter *pa
 	struct cmd_obj *ph2c;
 	struct readTSSI_parm *prdtssiparm;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	prdtssiparm = kmalloc(sizeof(struct readTSSI_parm), GFP_ATOMIC);
+	prdtssiparm = kmalloc(sizeof(*prdtssiparm), GFP_ATOMIC);
 	if (prdtssiparm == NULL) {
 		kfree((unsigned char *) ph2c);
 		return _FAIL;
 	}
-	_init_listhead(&ph2c->list);
+	INIT_LIST_HEAD(&ph2c->list);
 	ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI);
 	ph2c->parmbuf = (unsigned char *)prdtssiparm;
 	ph2c->cmdsz = sizeof(struct readTSSI_parm);
@@ -779,11 +776,10 @@ u8 r8712_setMacAddr_cmd(struct _adapter
 	struct cmd_obj *ph2c;
 	struct SetMacAddr_param	*psetMacAddr_para;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetMacAddr_para = kmalloc(sizeof(struct SetMacAddr_param),
-				   GFP_ATOMIC);
+	psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
 	if (psetMacAddr_para == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
@@ -802,17 +798,15 @@ u8 r8712_setassocsta_cmd(struct _adapter
 	struct set_assocsta_parm	*psetassocsta_para;
 	struct set_assocsta_rsp		*psetassocsta_rsp = NULL;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	psetassocsta_para = kmalloc(sizeof(struct set_assocsta_parm),
-				    GFP_ATOMIC);
+	psetassocsta_para = kmalloc(sizeof(*psetassocsta_para), GFP_ATOMIC);
 	if (psetassocsta_para == NULL) {
 		kfree((u8 *) ph2c);
 		return _FAIL;
 	}
-	psetassocsta_rsp = kmalloc(sizeof(struct set_assocsta_rsp),
-				   GFP_ATOMIC);
+	psetassocsta_rsp = kmalloc(sizeof(*psetassocsta_rsp), GFP_ATOMIC);
 	if (psetassocsta_rsp == NULL) {
 		kfree((u8 *)ph2c);
 		kfree((u8 *)psetassocsta_para);
@@ -832,10 +826,10 @@ u8 r8712_addbareq_cmd(struct _adapter *p
 	struct cmd_obj		*ph2c;
 	struct addBaReq_parm	*paddbareq_parm;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	paddbareq_parm = kmalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
+	paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
 	if (paddbareq_parm == NULL) {
 		kfree((unsigned char *)ph2c);
 		return _FAIL;
@@ -853,10 +847,10 @@ u8 r8712_wdg_wk_cmd(struct _adapter *pad
 	struct drvint_cmd_parm  *pdrvintcmd_param;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	pdrvintcmd_param = kmalloc(sizeof(struct drvint_cmd_parm), GFP_ATOMIC);
+	pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
 	if (pdrvintcmd_param == NULL) {
 		kfree((unsigned char *)ph2c);
 		return _FAIL;
@@ -962,7 +956,7 @@ void r8712_createbss_cmd_callback(struct
 				goto createbss_cmd_fail;
 			pwlan->last_scanned = jiffies;
 		} else
-			list_insert_tail(&(pwlan->list),
+			list_add_tail(&(pwlan->list),
 					 &pmlmepriv->scanned_queue.queue);
 		pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
 		memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
@@ -1027,10 +1021,10 @@ u8 r8712_disconnectCtrlEx_cmd(struct _ad
 	struct DisconnectCtrlEx_param *param;
 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
 
-	ph2c = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
 	if (ph2c == NULL)
 		return _FAIL;
-	param = kzalloc(sizeof(struct DisconnectCtrlEx_param), GFP_ATOMIC);
+	param = kzalloc(sizeof(*param), GFP_ATOMIC);
 	if (param == NULL) {
 		kfree((unsigned char *) ph2c);
 		return _FAIL;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_cmd.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_cmd.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -83,7 +83,7 @@ struct	evt_priv {
 
 #define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
 do {\
-	_init_listhead(&pcmd->list);\
+	INIT_LIST_HEAD(&pcmd->list);\
 	pcmd->cmdcode = code;\
 	pcmd->parmbuf = (u8 *)(pparm);\
 	pcmd->cmdsz = sizeof(*pparm);\
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_io.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_io.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_io.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_io.c	2014-09-28 17:29:07.000000000 -0400
@@ -112,12 +112,12 @@ uint r8712_alloc_io_queue(struct _adapte
 	struct io_queue *pio_queue;
 	struct io_req *pio_req;
 
-	pio_queue = kmalloc(sizeof(struct io_queue), GFP_ATOMIC);
+	pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC);
 	if (pio_queue == NULL)
 		goto alloc_io_queue_fail;
-	_init_listhead(&pio_queue->free_ioreqs);
-	_init_listhead(&pio_queue->processing);
-	_init_listhead(&pio_queue->pending);
+	INIT_LIST_HEAD(&pio_queue->free_ioreqs);
+	INIT_LIST_HEAD(&pio_queue->processing);
+	INIT_LIST_HEAD(&pio_queue->pending);
 	spin_lock_init(&pio_queue->lock);
 	pio_queue->pallocated_free_ioreqs_buf = kmalloc(NUM_IOREQ *
 							(sizeof(struct io_req)) + 4,
@@ -131,8 +131,8 @@ uint r8712_alloc_io_queue(struct _adapte
 			& 3);
 	pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf);
 	for (i = 0; i < NUM_IOREQ; i++) {
-		_init_listhead(&pio_req->list);
-		list_insert_tail(&pio_req->list, &pio_queue->free_ioreqs);
+		INIT_LIST_HEAD(&pio_req->list);
+		list_add_tail(&pio_req->list, &pio_queue->free_ioreqs);
 		pio_req++;
 	}
 	if ((register_intf_hdl((u8 *)adapter, &(pio_queue->intf))) == _FAIL)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_ioctl_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -1078,14 +1078,14 @@ static int r8711_wx_set_wap(struct net_d
 		return -EINVAL;
 	authmode = padapter->securitypriv.ndisauthtype;
 	spin_lock_irqsave(&queue->lock, irqL);
-	phead = get_list_head(queue);
-	pmlmepriv->pscanned = get_next(phead);
+	phead = &queue->queue;
+	pmlmepriv->pscanned = phead->next;
 	while (1) {
 		if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
 			break;
 		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
 			   struct wlan_network, list);
-		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 		dst_bssid = pnetwork->network.MacAddress;
 		if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
 			r8712_set_802_11_infrastructure_mode(padapter,
@@ -1227,8 +1227,8 @@ static int r8711_wx_get_scan(struct net_
 			break;
 	}
 	spin_lock_irqsave(&queue->lock, irqL);
-	phead = get_list_head(queue);
-	plist = get_next(phead);
+	phead = &queue->queue;
+	plist = phead->next;
 	while (1) {
 		if (end_of_queue_search(phead, plist) == true)
 			break;
@@ -1238,7 +1238,7 @@ static int r8711_wx_get_scan(struct net_
 		}
 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
 		ev = translate_scan(padapter, a, pnetwork, ev, stop);
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	spin_unlock_irqrestore(&queue->lock, irqL);
 	wrqu->data.length = ev - extra;
@@ -1286,14 +1286,14 @@ static int r8711_wx_set_essid(struct net
 		ndis_ssid.SsidLength = len;
 		memcpy(ndis_ssid.Ssid, extra, len);
 		src_ssid = ndis_ssid.Ssid;
-		phead = get_list_head(queue);
-		pmlmepriv->pscanned = get_next(phead);
+		phead = &queue->queue;
+		pmlmepriv->pscanned = phead->next;
 		while (1) {
 			if (end_of_queue_search(phead, pmlmepriv->pscanned))
 				break;
 			pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
 				   struct wlan_network, list);
-			pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+			pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 			dst_ssid = pnetwork->network.Ssid.Ssid;
 			if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
 			    && (pnetwork->network.Ssid.SsidLength ==
@@ -1459,17 +1459,12 @@ static int r8711_wx_get_rate(struct net_
 				RTL8712_RF_2T2R == rf_type)
 				max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
 					    270) : ((short_GI) ? 144 : 130);
-			else if (mcs_rate & 0x0080) /* MCS7 */
-				max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
-					    135) : ((short_GI) ? 72 : 65);
 			else /* default MCS7 */
 				max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
 					    135) : ((short_GI) ? 72 : 65);
 			max_rate *= 2; /* Mbps/2 */
-			wrqu->bitrate.value = max_rate * 500000;
-		} else {
-			wrqu->bitrate.value = max_rate * 500000;
 		}
+		wrqu->bitrate.value = max_rate * 500000;
 	} else
 		return -ENOLINK;
 	return 0;
@@ -2007,8 +2002,8 @@ static int r871x_get_ap_info(struct net_
 	} else
 		 return -EINVAL;
 	spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
-	phead = get_list_head(queue);
-	plist = get_next(phead);
+	phead = &queue->queue;
+	plist = phead->next;
 	while (1) {
 		if (end_of_queue_search(phead, plist) == true)
 			break;
@@ -2036,7 +2031,7 @@ static int r871x_get_ap_info(struct net_
 				break;
 			}
 		}
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
 	if (pdata->length >= 34) {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_ioctl_set.c	2014-09-28 17:29:07.000000000 -0400
@@ -62,8 +62,8 @@ static u8 do_join(struct _adapter *padap
 	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
 	struct  __queue	*queue	= &(pmlmepriv->scanned_queue);
 
-	phead = get_list_head(queue);
-	plist = get_next(phead);
+	phead = &queue->queue;
+	plist = phead->next;
 	pmlmepriv->cur_network.join_res = -2;
 	pmlmepriv->fw_state |= _FW_UNDER_LINKING;
 	pmlmepriv->pscanned = plist;
@@ -71,7 +71,7 @@ static u8 do_join(struct _adapter *padap
 
 	/* adhoc mode will start with an empty queue, but skip checking */
 	if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
-	    _queue_empty(queue)) {
+	    list_empty(&queue->queue)) {
 		if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
 			pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 		/* when set_ssid/set_bssid for do_join(), but scanning queue
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_led.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_led.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_led.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_led.h	2014-09-28 17:29:07.000000000 -0400
@@ -99,7 +99,7 @@ struct LED_871x {
 						   * either LED_ON or OFF.*/
 
 	struct timer_list	BlinkTimer; /* Timer object for led blinking.*/
-	_workitem		BlinkWorkItem; /* Workitem used by BlinkTimer */
+	struct work_struct	BlinkWorkItem; /* Workitem used by BlinkTimer */
 };
 
 struct led_priv {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_mlme.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_mlme.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_mlme.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_mlme.c	2014-09-28 17:29:07.000000000 -0400
@@ -69,8 +69,8 @@ static sint _init_mlme_priv(struct _adap
 	pmlmepriv->free_bss_buf = pbuf;
 	pnetwork = (struct wlan_network *)pbuf;
 	for (i = 0; i < MAX_BSS_CNT; i++) {
-		_init_listhead(&(pnetwork->list));
-		list_insert_tail(&(pnetwork->list),
+		INIT_LIST_HEAD(&(pnetwork->list));
+		list_add_tail(&(pnetwork->list),
 				 &(pmlmepriv->free_bss_pool.queue));
 		pnetwork++;
 	}
@@ -89,12 +89,12 @@ struct wlan_network *_r8712_alloc_networ
 	struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
 	struct list_head *plist = NULL;
 
-	if (_queue_empty(free_queue) == true)
+	if (list_empty(&free_queue->queue))
 		return NULL;
 	spin_lock_irqsave(&free_queue->lock, irqL);
-	plist = get_next(&(free_queue->queue));
+	plist = free_queue->queue.next;
 	pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list);
-	list_delete(&pnetwork->list);
+	list_del_init(&pnetwork->list);
 	pnetwork->last_scanned = jiffies;
 	pmlmepriv->num_of_scanned++;
 	spin_unlock_irqrestore(&free_queue->lock, irqL);
@@ -117,8 +117,8 @@ static void _free_network(struct mlme_pr
 	if (delta_time < SCANQUEUE_LIFETIME)
 		return;
 	spin_lock_irqsave(&free_queue->lock, irqL);
-	list_delete(&pnetwork->list);
-	list_insert_tail(&pnetwork->list, &free_queue->queue);
+	list_del_init(&pnetwork->list);
+	list_add_tail(&pnetwork->list, &free_queue->queue);
 	pmlmepriv->num_of_scanned--;
 	spin_unlock_irqrestore(&free_queue->lock, irqL);
 }
@@ -132,8 +132,8 @@ static void _free_network_nolock(struct
 		return;
 	if (pnetwork->fixed == true)
 		return;
-	list_delete(&pnetwork->list);
-	list_insert_tail(&pnetwork->list, get_list_head(free_queue));
+	list_del_init(&pnetwork->list);
+	list_add_tail(&pnetwork->list, &free_queue->queue);
 	pmlmepriv->num_of_scanned--;
 }
 
@@ -153,11 +153,11 @@ static struct wlan_network *_r8712_find_
 	if (is_zero_ether_addr(addr))
 		return NULL;
 	spin_lock_irqsave(&scanned_queue->lock, irqL);
-	phead = get_list_head(scanned_queue);
-	plist = get_next(phead);
+	phead = &scanned_queue->queue;
+	plist = phead->next;
 	while (plist != phead) {
 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-		plist = get_next(plist);
+		plist = plist->next;
 		if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
 			break;
 	}
@@ -174,11 +174,11 @@ static void _free_network_queue(struct _
 	struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
 
 	spin_lock_irqsave(&scanned_queue->lock, irqL);
-	phead = get_list_head(scanned_queue);
-	plist = get_next(phead);
+	phead = &scanned_queue->queue;
+	plist = phead->next;
 	while (end_of_queue_search(phead, plist) == false) {
 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-		plist = get_next(plist);
+		plist = plist->next;
 		_free_network(pmlmepriv, pnetwork);
 	}
 	spin_unlock_irqrestore(&scanned_queue->lock, irqL);
@@ -315,8 +315,8 @@ struct	wlan_network *r8712_get_oldest_wl
 	struct	wlan_network	*pwlan = NULL;
 	struct	wlan_network	*oldest = NULL;
 
-	phead = get_list_head(scanned_queue);
-	plist = get_next(phead);
+	phead = &scanned_queue->queue;
+	plist = phead->next;
 	while (1) {
 		if (end_of_queue_search(phead, plist) ==  true)
 			break;
@@ -327,7 +327,7 @@ struct	wlan_network *r8712_get_oldest_wl
 			    (unsigned long)pwlan->last_scanned))
 				oldest = pwlan;
 		}
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	return oldest;
 }
@@ -398,8 +398,8 @@ static void update_scanned_network(struc
 	struct wlan_network *pnetwork = NULL;
 	struct wlan_network *oldest = NULL;
 
-	phead = get_list_head(queue);
-	plist = get_next(phead);
+	phead = &queue->queue;
+	plist = phead->next;
 
 	while (1) {
 		if (end_of_queue_search(phead, plist) == true)
@@ -413,14 +413,14 @@ static void update_scanned_network(struc
 				(unsigned long)pnetwork->last_scanned))
 			oldest = pnetwork;
 
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 
 	/* If we didn't find a match, then get a new network slot to initialize
 	 * with this beacon's information */
 	if (end_of_queue_search(phead, plist) == true) {
-		if (_queue_empty(&pmlmepriv->free_bss_pool) == true) {
+		if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
 			/* If there are no more slots, expire the oldest */
 			pnetwork = oldest;
 			target->Rssi = (pnetwork->network.Rssi +
@@ -437,7 +437,7 @@ static void update_scanned_network(struc
 			bssid_ex_sz = r8712_get_ndis_wlan_bssid_ex_sz(target);
 			target->Length = bssid_ex_sz;
 			memcpy(&pnetwork->network, target, bssid_ex_sz);
-			list_insert_tail(&pnetwork->list, &queue->queue);
+			list_add_tail(&pnetwork->list, &queue->queue);
 		}
 	} else {
 		/* we have an entry and we are going to update it. But
@@ -1138,8 +1138,8 @@ int r8712_select_and_join_from_scan(stru
 
 	adapter = (struct _adapter *)pmlmepriv->nic_hdl;
 	queue = &pmlmepriv->scanned_queue;
-	phead = get_list_head(queue);
-	pmlmepriv->pscanned = get_next(phead);
+	phead = &queue->queue;
+	pmlmepriv->pscanned = phead->next;
 	while (1) {
 		if (end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
 			if ((pmlmepriv->assoc_by_rssi == true) &&
@@ -1153,7 +1153,7 @@ int r8712_select_and_join_from_scan(stru
 					  struct wlan_network, list);
 		if (pnetwork == NULL)
 			return _FAIL;
-		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
 		if (pmlmepriv->assoc_by_bssid == true) {
 			dst_ssid = pnetwork->network.MacAddress;
 			src_ssid = pmlmepriv->assoc_bssid;
@@ -1212,11 +1212,11 @@ sint r8712_set_auth(struct _adapter *ada
 	struct cmd_obj *pcmd;
 	struct setauth_parm *psetauthparm;
 
-	pcmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 	if (pcmd == NULL)
 		return _FAIL;
 
-	psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_ATOMIC);
+	psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
 	if (psetauthparm == NULL) {
 		kfree((unsigned char *)pcmd);
 		return _FAIL;
@@ -1227,7 +1227,7 @@ sint r8712_set_auth(struct _adapter *ada
 	pcmd->cmdsz = sizeof(struct setauth_parm);
 	pcmd->rsp = NULL;
 	pcmd->rspsz = 0;
-	_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	r8712_enqueue_cmd(pcmdpriv, pcmd);
 	return _SUCCESS;
 }
@@ -1242,10 +1242,10 @@ sint r8712_set_key(struct _adapter *adap
 	u8 keylen;
 	sint ret = _SUCCESS;
 
-	pcmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 	if (pcmd == NULL)
 		return _FAIL;
-	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_ATOMIC);
+	psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
 	if (psetkeyparm == NULL) {
 		ret = _FAIL;
 		goto err_free_cmd;
@@ -1299,7 +1299,7 @@ sint r8712_set_key(struct _adapter *adap
 	pcmd->cmdsz =  (sizeof(struct setkey_parm));
 	pcmd->rsp = NULL;
 	pcmd->rspsz = 0;
-	_init_listhead(&pcmd->list);
+	INIT_LIST_HEAD(&pcmd->list);
 	r8712_enqueue_cmd(pcmdpriv, pcmd);
 	return ret;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_mp.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_mp.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_mp.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_mp.c	2014-09-28 17:29:07.000000000 -0400
@@ -65,8 +65,8 @@ static int init_mp_priv(struct mp_priv *
 			 ((addr_t)(pmp_priv->pallocated_mp_xmitframe_buf) & 3);
 	pmp_xmitframe = (struct mp_xmit_frame *)pmp_priv->pmp_xmtframe_buf;
 	for (i = 0; i < NR_MP_XMITFRAME; i++) {
-		_init_listhead(&(pmp_xmitframe->list));
-		list_insert_tail(&(pmp_xmitframe->list),
+		INIT_LIST_HEAD(&(pmp_xmitframe->list));
+		list_add_tail(&(pmp_xmitframe->list),
 				 &(pmp_priv->free_mp_xmitqueue.queue));
 		pmp_xmitframe->pkt = NULL;
 		pmp_xmitframe->frame_tag = MP_FRAMETAG;
@@ -281,10 +281,10 @@ void r8712_SetChannel(struct _adapter *p
 	struct SetChannel_parm *pparm = NULL;
 	u16 code = GEN_CMD_CODE(_SetChannel);
 
-	pcmd = kmalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
 	if (pcmd == NULL)
 		return;
-	pparm = kmalloc(sizeof(struct SetChannel_parm), GFP_ATOMIC);
+	pparm = kmalloc(sizeof(*pparm), GFP_ATOMIC);
 	if (pparm == NULL) {
 		kfree(pcmd);
 		return;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -83,7 +83,7 @@ void r8712_set_ps_mode(struct _adapter *
 			pwrpriv->bSleep = false;
 		pwrpriv->pwr_mode = ps_mode;
 		pwrpriv->smart_ps = smart_ps;
-		_set_workitem(&(pwrpriv->SetPSModeWorkItem));
+		schedule_work(&pwrpriv->SetPSModeWorkItem);
 	}
 }
 
@@ -133,7 +133,7 @@ static void _rpwm_check_handler (struct
 	    padapter->bSurpriseRemoved == true)
 		return;
 	if (pwrpriv->cpwm != pwrpriv->rpwm)
-		_set_workitem(&(pwrpriv->rpwm_workitem));
+		schedule_work(&pwrpriv->rpwm_workitem);
 }
 
 static void SetPSModeWorkItemCallback(struct work_struct *work)
@@ -184,10 +184,8 @@ void r8712_init_pwrctrl_priv(struct _ada
 	pwrctrlpriv->tog = 0x80;
 /* clear RPWM to ensure driver and fw back to initial state. */
 	r8712_write8(padapter, 0x1025FE58, 0);
-	_init_workitem(&(pwrctrlpriv->SetPSModeWorkItem),
-		       SetPSModeWorkItemCallback, padapter);
-	_init_workitem(&(pwrctrlpriv->rpwm_workitem),
-		       rpwm_workitem_callback, padapter);
+	INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback);
+	INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback);
 	_init_timer(&(pwrctrlpriv->rpwm_check_timer),
 		    padapter->pnetdev, rpwm_check_handler, (u8 *)padapter);
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_pwrctrl.h	2014-09-28 17:29:07.000000000 -0400
@@ -107,8 +107,8 @@ struct	pwrctrl_priv {
 	uint ImrContent;	/* used to store original imr. */
 	uint bSleep; /* sleep -> active is different from active -> sleep. */
 
-	_workitem SetPSModeWorkItem;
-	_workitem rpwm_workitem;
+	struct work_struct SetPSModeWorkItem;
+	struct work_struct rpwm_workitem;
 	struct timer_list rpwm_check_timer;
 	u8	rpwm_retry;
 	uint	bSetPSModeWorkItemInProgress;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_recv.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_recv.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -86,8 +86,8 @@ sint _r8712_init_recv_priv(struct recv_p
 				    (RXFRAME_ALIGN_SZ-1));
 	precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
 	for (i = 0; i < NR_RECVFRAME; i++) {
-		_init_listhead(&(precvframe->u.list));
-		list_insert_tail(&(precvframe->u.list),
+		INIT_LIST_HEAD(&(precvframe->u.list));
+		list_add_tail(&(precvframe->u.list),
 				 &(precvpriv->free_recv_queue.queue));
 		r8712_os_recv_resource_alloc(padapter, precvframe);
 		precvframe->u.hdr.adapter = padapter;
@@ -112,13 +112,13 @@ union recv_frame *r8712_alloc_recvframe(
 	struct recv_priv *precvpriv;
 
 	spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
-	if (_queue_empty(pfree_recv_queue) == true)
+	if (list_empty(&pfree_recv_queue->queue))
 		precvframe = NULL;
 	else {
-		phead = get_list_head(pfree_recv_queue);
-		plist = get_next(phead);
+		phead = &pfree_recv_queue->queue;
+		plist = phead->next;
 		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
-		list_delete(&precvframe->u.hdr.list);
+		list_del_init(&precvframe->u.hdr.list);
 		padapter = precvframe->u.hdr.adapter;
 		if (padapter != NULL) {
 			precvpriv = &padapter->recvpriv;
@@ -145,11 +145,11 @@ void r8712_free_recvframe_queue(struct
 	struct list_head *plist, *phead;
 
 	spin_lock(&pframequeue->lock);
-	phead = get_list_head(pframequeue);
-	plist = get_next(phead);
+	phead = &pframequeue->queue;
+	plist = phead->next;
 	while (end_of_queue_search(phead, plist) == false) {
 		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
-		plist = get_next(plist);
+		plist = plist->next;
 		r8712_free_recvframe(precvframe, pfree_recv_queue);
 	}
 	spin_unlock(&pframequeue->lock);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_sta_mgt.c	2014-09-28 17:29:07.000000000 -0400
@@ -38,12 +38,12 @@ static void _init_stainfo(struct sta_inf
 {
 	memset((u8 *)psta, 0, sizeof(struct sta_info));
 	 spin_lock_init(&psta->lock);
-	_init_listhead(&psta->list);
-	_init_listhead(&psta->hash_list);
+	INIT_LIST_HEAD(&psta->list);
+	INIT_LIST_HEAD(&psta->hash_list);
 	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
 	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
-	_init_listhead(&psta->asoc_list);
-	_init_listhead(&psta->auth_list);
+	INIT_LIST_HEAD(&psta->asoc_list);
+	INIT_LIST_HEAD(&psta->auth_list);
 }
 
 u32 _r8712_init_sta_priv(struct	sta_priv *pstapriv)
@@ -65,13 +65,12 @@ u32 _r8712_init_sta_priv(struct	sta_priv
 	psta = (struct sta_info *)(pstapriv->pstainfo_buf);
 	for (i = 0; i < NUM_STA; i++) {
 		_init_stainfo(psta);
-		_init_listhead(&(pstapriv->sta_hash[i]));
-		list_insert_tail(&psta->list,
-				 get_list_head(&pstapriv->free_sta_queue));
+		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
+		list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue);
 		psta++;
 	}
-	_init_listhead(&pstapriv->asoc_list);
-	_init_listhead(&pstapriv->auth_list);
+	INIT_LIST_HEAD(&pstapriv->asoc_list);
+	INIT_LIST_HEAD(&pstapriv->auth_list);
 	return _SUCCESS;
 }
 
@@ -83,11 +82,11 @@ static void mfree_all_stainfo(struct sta
 	struct sta_info *psta = NULL;
 
 	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
-	phead = get_list_head(&pstapriv->free_sta_queue);
-	plist = get_next(phead);
+	phead = &pstapriv->free_sta_queue.queue;
+	plist = phead->next;
 	while ((end_of_queue_search(phead, plist)) == false) {
 		psta = LIST_CONTAINOR(plist, struct sta_info, list);
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 
 	spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
@@ -122,12 +121,12 @@ struct sta_info *r8712_alloc_stainfo(str
 
 	pfree_sta_queue = &pstapriv->free_sta_queue;
 	spin_lock_irqsave(&(pfree_sta_queue->lock), flags);
-	if (_queue_empty(pfree_sta_queue) == true)
+	if (list_empty(&pfree_sta_queue->queue))
 		psta = NULL;
 	else {
-		psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue),
+		psta = LIST_CONTAINOR(pfree_sta_queue->queue.next,
 				      struct sta_info, list);
-		list_delete(&(psta->list));
+		list_del_init(&(psta->list));
 		tmp_aid = psta->aid;
 		_init_stainfo(psta);
 		memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
@@ -137,7 +136,7 @@ struct sta_info *r8712_alloc_stainfo(str
 			goto exit;
 		}
 		phash_list = &(pstapriv->sta_hash[index]);
-		list_insert_tail(&psta->hash_list, phash_list);
+		list_add_tail(&psta->hash_list, phash_list);
 		pstapriv->asoc_sta_count++;
 
 /* For the SMC router, the sequence number of first packet of WPS handshake
@@ -181,21 +180,21 @@ void r8712_free_stainfo(struct _adapter
 	pstaxmitpriv = &psta->sta_xmitpriv;
 	spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0);
 	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
-	list_delete(&(pstaxmitpriv->vo_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
 	spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0);
 	spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0);
 	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
-	list_delete(&(pstaxmitpriv->vi_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
 	spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0);
 	spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0);
 	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
-	list_delete(&(pstaxmitpriv->bk_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
 	spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0);
 	spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0);
 	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
-	list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
 	spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0);
-	list_delete(&psta->hash_list);
+	list_del_init(&psta->hash_list);
 	pstapriv->asoc_sta_count--;
 	/* re-init sta_info; 20061114 */
 	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
@@ -208,7 +207,7 @@ void r8712_free_stainfo(struct _adapter
 	}
 	spin_lock(&(pfree_sta_queue->lock));
 	/* insert into free_sta_queue; 20061114 */
-	list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
+	list_add_tail(&psta->list, &pfree_sta_queue->queue);
 	spin_unlock(&(pfree_sta_queue->lock));
 }
 
@@ -227,11 +226,11 @@ void r8712_free_all_stainfo(struct _adap
 	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 	for (index = 0; index < NUM_STA; index++) {
 		phead = &(pstapriv->sta_hash[index]);
-		plist = get_next(phead);
+		plist = phead->next;
 		while ((end_of_queue_search(phead, plist)) == false) {
 			psta = LIST_CONTAINOR(plist,
 					      struct sta_info, hash_list);
-			plist = get_next(plist);
+			plist = plist->next;
 			if (pbcmc_stainfo != psta)
 				r8712_free_stainfo(padapter , psta);
 		}
@@ -252,7 +251,7 @@ struct sta_info *r8712_get_stainfo(struc
 	index = wifi_mac_hash(hwaddr);
 	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 	phead = &(pstapriv->sta_hash[index]);
-	plist = get_next(phead);
+	plist = phead->next;
 	while ((end_of_queue_search(phead, plist)) == false) {
 		psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
 		if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
@@ -260,7 +259,7 @@ struct sta_info *r8712_get_stainfo(struc
 			break;
 		}
 		psta = NULL;
-		plist = get_next(plist);
+		plist = plist->next;
 	}
 	spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 	return psta;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,7 +43,7 @@ static void free_hwxmits(struct _adapter
 
 static void _init_txservq(struct tx_servq *ptxservq)
 {
-	_init_listhead(&ptxservq->tx_pending);
+	INIT_LIST_HEAD(&ptxservq->tx_pending);
 	_init_queue(&ptxservq->sta_pending);
 	ptxservq->qcnt = 0;
 }
@@ -57,8 +57,8 @@ void _r8712_init_sta_xmit_priv(struct st
 	_init_txservq(&psta_xmitpriv->bk_q);
 	_init_txservq(&psta_xmitpriv->vi_q);
 	_init_txservq(&psta_xmitpriv->vo_q);
-	_init_listhead(&psta_xmitpriv->legacy_dz);
-	_init_listhead(&psta_xmitpriv->apsd);
+	INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
+	INIT_LIST_HEAD(&psta_xmitpriv->apsd);
 }
 
 sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
@@ -97,13 +97,13 @@ sint _r8712_init_xmit_priv(struct xmit_p
 			((addr_t) (pxmitpriv->pallocated_frame_buf) & 3);
 	pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
 	for (i = 0; i < NR_XMITFRAME; i++) {
-		_init_listhead(&(pxframe->list));
+		INIT_LIST_HEAD(&(pxframe->list));
 		pxframe->padapter = padapter;
 		pxframe->frame_tag = DATA_FRAMETAG;
 		pxframe->pkt = NULL;
 		pxframe->buf_addr = NULL;
 		pxframe->pxmitbuf = NULL;
-		list_insert_tail(&(pxframe->list),
+		list_add_tail(&(pxframe->list),
 				 &(pxmitpriv->free_xmit_queue.queue));
 		pxframe++;
 	}
@@ -134,7 +134,7 @@ sint _r8712_init_xmit_priv(struct xmit_p
 			      ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
 	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
 	for (i = 0; i < NR_XMITBUFF; i++) {
-		_init_listhead(&pxmitbuf->list);
+		INIT_LIST_HEAD(&pxmitbuf->list);
 		pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ,
 						   GFP_ATOMIC);
 		if (pxmitbuf->pallocated_buf == NULL)
@@ -143,12 +143,12 @@ sint _r8712_init_xmit_priv(struct xmit_p
 				 ((addr_t) (pxmitbuf->pallocated_buf) &
 				 (XMITBUF_ALIGN_SZ - 1));
 		r8712_xmit_resource_alloc(padapter, pxmitbuf);
-		list_insert_tail(&pxmitbuf->list,
+		list_add_tail(&pxmitbuf->list,
 				 &(pxmitpriv->free_xmitbuf_queue.queue));
 		pxmitbuf++;
 	}
 	pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
-	_init_workitem(&padapter->wkFilterRxFF0, r8712_SetFilter, padapter);
+	INIT_WORK(&padapter->wkFilterRxFF0, r8712_SetFilter);
 	alloc_hwxmits(padapter);
 	init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
 	tasklet_init(&pxmitpriv->xmit_tasklet,
@@ -744,13 +744,13 @@ struct xmit_buf *r8712_alloc_xmitbuf(str
 	struct  __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
 
 	spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
-	if (_queue_empty(pfree_xmitbuf_queue) == true)
+	if (list_empty(&pfree_xmitbuf_queue->queue))
 		pxmitbuf = NULL;
 	else {
-		phead = get_list_head(pfree_xmitbuf_queue);
-		plist = get_next(phead);
+		phead = &pfree_xmitbuf_queue->queue;
+		plist = phead->next;
 		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
-		list_delete(&(pxmitbuf->list));
+		list_del_init(&(pxmitbuf->list));
 	}
 	if (pxmitbuf !=  NULL)
 		pxmitpriv->free_xmitbuf_cnt--;
@@ -766,8 +766,8 @@ int r8712_free_xmitbuf(struct xmit_priv
 	if (pxmitbuf == NULL)
 		return _FAIL;
 	spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
-	list_delete(&pxmitbuf->list);
-	list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
+	list_del_init(&pxmitbuf->list);
+	list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue);
 	pxmitpriv->free_xmitbuf_cnt++;
 	spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
 	return _SUCCESS;
@@ -798,13 +798,13 @@ struct xmit_frame *r8712_alloc_xmitframe
 	struct  __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
 
 	spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
-	if (_queue_empty(pfree_xmit_queue) == true)
+	if (list_empty(&pfree_xmit_queue->queue))
 		pxframe =  NULL;
 	else {
-		phead = get_list_head(pfree_xmit_queue);
-		plist = get_next(phead);
+		phead = &pfree_xmit_queue->queue;
+		plist = phead->next;
 		pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-		list_delete(&(pxframe->list));
+		list_del_init(&(pxframe->list));
 	}
 	if (pxframe !=  NULL) {
 		pxmitpriv->free_xmitframe_cnt--;
@@ -828,12 +828,12 @@ void r8712_free_xmitframe(struct xmit_pr
 	if (pxmitframe == NULL)
 		return;
 	spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
-	list_delete(&pxmitframe->list);
+	list_del_init(&pxmitframe->list);
 	if (pxmitframe->pkt) {
 		pndis_pkt = pxmitframe->pkt;
 		pxmitframe->pkt = NULL;
 	}
-	list_insert_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
+	list_add_tail(&pxmitframe->list, &pfree_xmit_queue->queue);
 	pxmitpriv->free_xmitframe_cnt++;
 	spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
 	if (netif_queue_stopped(padapter->pnetdev))
@@ -857,11 +857,11 @@ void r8712_free_xmitframe_queue(struct x
 	struct	xmit_frame	*pxmitframe;
 
 	spin_lock_irqsave(&(pframequeue->lock), irqL);
-	phead = get_list_head(pframequeue);
-	plist = get_next(phead);
+	phead = &pframequeue->queue;
+	plist = phead->next;
 	while (end_of_queue_search(phead, plist) == false) {
 		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-		plist = get_next(plist);
+		plist = plist->next;
 		r8712_free_xmitframe(pxmitpriv, pxmitframe);
 	}
 	spin_unlock_irqrestore(&(pframequeue->lock), irqL);
@@ -939,11 +939,9 @@ sint r8712_xmit_classifier(struct _adapt
 	ptxservq = get_sta_pending(padapter, &pstapending,
 		   psta, pattrib->priority);
 	spin_lock_irqsave(&pstapending->lock, irqL0);
-	if (is_list_empty(&ptxservq->tx_pending))
-		list_insert_tail(&ptxservq->tx_pending,
-				 get_list_head(pstapending));
-	list_insert_tail(&pxmitframe->list,
-			 get_list_head(&ptxservq->sta_pending));
+	if (list_empty(&ptxservq->tx_pending))
+		list_add_tail(&ptxservq->tx_pending, &pstapending->queue);
+	list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue);
 	ptxservq->qcnt++;
 	spin_unlock_irqrestore(&pstapending->lock, irqL0);
 	return _SUCCESS;
@@ -1005,7 +1003,7 @@ static void init_hwxmits(struct hw_xmit
 
 	for (i = 0; i < entry; i++, phwxmit++) {
 		spin_lock_init(&phwxmit->xmit_lock);
-		_init_listhead(&phwxmit->pending);
+		INIT_LIST_HEAD(&phwxmit->pending);
 		phwxmit->txcmdcnt = 0;
 		phwxmit->accnt = 0;
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_xmit.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_xmit.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/rtl871x_xmit.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/rtl871x_xmit.h	2014-09-28 17:29:07.000000000 -0400
@@ -233,9 +233,9 @@ struct	xmit_priv {
 	u8	hwxmit_entry;
 	u8	txirp_cnt;
 	struct tasklet_struct xmit_tasklet;
-	_workitem xmit_pipe4_reset_wi;
-	_workitem xmit_pipe6_reset_wi;
-	_workitem xmit_piped_reset_wi;
+	struct work_struct xmit_pipe4_reset_wi;
+	struct work_struct xmit_pipe6_reset_wi;
+	struct work_struct xmit_piped_reset_wi;
 	/*per AC pending irp*/
 	int beq_cnt;
 	int bkq_cnt;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8712/usb_intf.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/usb_intf.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8712/usb_intf.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8712/usb_intf.c	2014-09-28 17:29:07.000000000 -0400
@@ -607,31 +607,29 @@ error:
 static void r871xu_dev_remove(struct usb_interface *pusb_intf)
 {
 	struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
-	struct _adapter *padapter = netdev_priv(pnetdev);
 	struct usb_device *udev = interface_to_usbdev(pusb_intf);
 
-	usb_set_intfdata(pusb_intf, NULL);
-	if (padapter->fw_found)
+	if (pnetdev) {
+		struct _adapter *padapter = netdev_priv(pnetdev);
+
+		usb_set_intfdata(pusb_intf, NULL);
 		release_firmware(padapter->fw);
-	/* never exit with a firmware callback pending */
-	wait_for_completion(&padapter->rtl8712_fw_ready);
-	if (drvpriv.drv_registered == true)
-		padapter->bSurpriseRemoved = true;
-	if (pnetdev != NULL) {
-		/* will call netdev_close() */
-		unregister_netdev(pnetdev);
-	}
-	flush_scheduled_work();
-	udelay(1);
-	/*Stop driver mlme relation timer */
-	if (padapter->fw_found)
+		/* never exit with a firmware callback pending */
+		wait_for_completion(&padapter->rtl8712_fw_ready);
+		if (drvpriv.drv_registered == true)
+			padapter->bSurpriseRemoved = true;
+		unregister_netdev(pnetdev); /* will call netdev_close() */
+		flush_scheduled_work();
+		udelay(1);
+		/* Stop driver mlme relation timer */
 		r8712_stop_drv_timers(padapter);
-	r871x_dev_unload(padapter);
-	r8712_free_drv_sw(padapter);
-	usb_set_intfdata(pusb_intf, NULL);
-	/* decrease the reference count of the usb device structure
-	 * when disconnect */
-	usb_put_dev(udev);
+		r871x_dev_unload(padapter);
+		r8712_free_drv_sw(padapter);
+
+		/* decrease the reference count of the usb device structure
+		 * when disconnect */
+		usb_put_dev(udev);
+	}
 	/* If we didn't unplug usb dongle and remove/insert module, driver
 	 * fails on sitesurvey for the first time when device is up.
 	 * Reset usb port for sitesurvey fail issue. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ap.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ap.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ap.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ap.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,7 +24,6 @@
 extern unsigned char WMM_OUI23A[];
 extern unsigned char WPS_OUI23A[];
 extern unsigned char P2P_OUI23A[];
-extern unsigned char WFD_OUI23A[];
 
 void init_mlme_ap_info23a(struct rtw_adapter *padapter)
 {
@@ -53,7 +52,7 @@ void free_mlme_ap_info23a(struct rtw_ada
 
 	rtw_sta_flush23a(padapter);
 
-	pmlmeinfo->state = _HW_STATE_NOLINK_;
+	pmlmeinfo->state = MSR_NOLINK;
 
 	/* free_assoc_sta_resources */
 	rtw_free_all_stainfo23a(padapter);
@@ -78,8 +77,8 @@ static void update_BCNTIM(struct rtw_ada
 
 	tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
 
-	p = rtw_get_ie23a(pie + _FIXED_IE_LENGTH_, WLAN_EID_TIM, &tim_ielen,
-			  pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
+	p = rtw_get_ie23a(pie, WLAN_EID_TIM, &tim_ielen,
+			  pnetwork_mlmeext->IELength);
 	if (p != NULL && tim_ielen>0) {
 		tim_ielen += 2;
 
@@ -94,20 +93,18 @@ static void update_BCNTIM(struct rtw_ada
 	} else {
 		tim_ielen = 0;
 
-		/* calulate head_len */
-		offset = _FIXED_IE_LENGTH_;
+		/* calculate head_len */
+		offset = 0;
 
 		/* get ssid_ie len */
-		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, WLAN_EID_SSID,
-				  &tmp_len, (pnetwork_mlmeext->IELength -
-					     _BEACON_IE_OFFSET_));
+		p = rtw_get_ie23a(pie, WLAN_EID_SSID,
+				  &tmp_len, pnetwork_mlmeext->IELength);
 		if (p != NULL)
 			offset += tmp_len+2;
 
 		/*  get supported rates len */
-		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES,
-				  &tmp_len, (pnetwork_mlmeext->IELength -
-					     _BEACON_IE_OFFSET_));
+		p = rtw_get_ie23a(pie, WLAN_EID_SUPP_RATES,
+				  &tmp_len, pnetwork_mlmeext->IELength);
 		if (p !=  NULL)
 			offset += tmp_len+2;
 
@@ -138,7 +135,7 @@ static void update_BCNTIM(struct rtw_ada
 	*dst_ie++= tim_ielen;
 
 	*dst_ie++= 0;/* DTIM count */
-	*dst_ie++= 1;/* DTIM peroid */
+	*dst_ie++= 1;/* DTIM period */
 
 	if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
 		*dst_ie++ = BIT(0);/* bitmap ctrl */
@@ -246,7 +243,7 @@ void	expire_timeout_chk23a(struct rtw_ad
 
 			if (psta->state & WIFI_SLEEP_STATE) {
 				if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
-					/* to check if alive by another methods if staion is at ps mode. */
+					/* to check if alive by another methods if station is at ps mode. */
 					psta->expire_to = pstapriv->expire_to;
 					psta->state |= WIFI_STA_ALIVE_CHK_STATE;
 
@@ -623,15 +620,18 @@ static void update_hw_ht_param(struct rt
 		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
 		AMPDU_para [4:2]:Min MPDU Start Spacing
 	*/
-	max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+	max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info &
+		IEEE80211_HT_AMPDU_PARM_FACTOR;
 
-	min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
+	min_MPDU_spacing = (pmlmeinfo->ht_cap.ampdu_params_info &
+			    IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
 
 	rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
 	rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
 
 	/*  Config SM Power Save setting */
-	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+	pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
+			    IEEE80211_HT_CAP_SM_PS) >> 2;
 	if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
 		DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
 }
@@ -649,10 +649,9 @@ static void start_bss_network(struct rtw
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
-	struct HT_info_element *pht_info = NULL;
-	int bcn_fixed_size;
+	struct ieee80211_ht_operation *pht_info = NULL;
 
-	bcn_interval = (u16)pnetwork->BeaconPeriod;
+	bcn_interval = (u16)pnetwork->beacon_interval;
 	cur_channel = pnetwork->DSConfig;
 	cur_bwmode = HT_CHANNEL_WIDTH_20;;
 	cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
@@ -660,7 +659,10 @@ static void start_bss_network(struct rtw
 	/* check if there is wps ie, */
 	/* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
 	/* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
-	if (NULL == rtw_get_wps_ie23a(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
+	if (NULL == cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					    WLAN_OUI_TYPE_MICROSOFT_WPS,
+					    pnetwork->IEs,
+					    pnetwork->IELength))
 		pmlmeext->bstart_bss = true;
 
 	/* todo: update wmm, ht cap */
@@ -686,7 +688,7 @@ static void start_bss_network(struct rtw
 	}
 
 	/* set MSR to AP_Mode */
-	Set_MSR23a(padapter, _HW_STATE_AP_);
+	rtl8723a_set_media_status(padapter, MSR_AP);
 
 	/* Set BSSID REG */
 	hw_var_set_bssid(padapter, pnetwork->MacAddress);
@@ -722,25 +724,24 @@ static void start_bss_network(struct rtw
 						 DYNAMIC_ALL_FUNC_ENABLE);
 	}
 	/* set channel, bwmode */
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
 
-	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
-			     pnetwork->IEs + bcn_fixed_size,
-			     pnetwork->IELength - bcn_fixed_size);
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pnetwork->IEs,
+			     pnetwork->IELength);
 	if (p && p[1]) {
-		pht_info = (struct HT_info_element *)(p + 2);
+		pht_info = (struct ieee80211_ht_operation *)(p + 2);
 
-		if (pregpriv->cbw40_enable && pht_info->infos[0] & BIT(2)) {
+		if (pregpriv->cbw40_enable && pht_info->ht_param &
+		    IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
 			/* switch to the 40M Hz mode */
 			cur_bwmode = HT_CHANNEL_WIDTH_40;
-			switch (pht_info->infos[0] & 0x3) {
-			case 1:
+			switch (pht_info->ht_param &
+				IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 				/* pmlmeext->cur_ch_offset =
 				   HAL_PRIME_CHNL_OFFSET_LOWER; */
 				cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 				break;
-			case 3:
+			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 				cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
 				break;
 			default:
@@ -763,8 +764,8 @@ static void start_bss_network(struct rtw
 	/* update cur_wireless_mode */
 	update_wireless_mode23a(padapter);
 
-	/* udpate capability after cur_wireless_mode updated */
-	update_capinfo23a(padapter, rtw_get_capability23a(pnetwork));
+	/* update capability after cur_wireless_mode updated */
+	update_capinfo23a(padapter, pnetwork->capability);
 
 	/* let pnetwork_mlmeext == pnetwork_mlme. */
 	memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
@@ -781,16 +782,15 @@ static void start_bss_network(struct rtw
 	update_bmc_sta(padapter);
 }
 
-int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,
-			     unsigned int len)
+int rtw_check_beacon_data23a(struct rtw_adapter *padapter,
+			     struct ieee80211_mgmt *mgmt, unsigned int len)
 {
 	int ret = _SUCCESS;
 	u8 *p;
 	u8 *pHT_caps_ie = NULL;
 	u8 *pHT_info_ie = NULL;
 	struct sta_info *psta = NULL;
-	__le16 *pbeacon;
-	u16 cap, ht_cap = false;
+	u16 ht_cap = false;
 	uint ie_len = 0;
 	int group_cipher, pairwise_cipher;
 	u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
@@ -801,7 +801,8 @@ int rtw_check_beacon_data23a(struct rtw_
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
 	u8 *ie = pbss_network->IEs;
-
+	u8 *pbuf = mgmt->u.beacon.variable;
+	len -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
 	/* SSID */
 	/* Supported rates */
 	/* DS Params */
@@ -835,27 +836,18 @@ int rtw_check_beacon_data23a(struct rtw_
 
 	memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN);
 
-	/* beacon interval */
-	/* ie + 8;  8: TimeStamp, 2: Beacon Interval 2:Capability */
-	pbeacon = rtw_get_beacon_interval23a_from_ie(ie);
-	pbss_network->BeaconPeriod = get_unaligned_le16(pbeacon);
-
-	/* capability */
-	cap = get_unaligned_le16(ie);
-
 	/* SSID */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_SSID, &ie_len,
-			  (pbss_network->IELength -_BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_SSID, &ie_len, pbss_network->IELength);
 	if (p && ie_len > 0) {
 		memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid));
 		memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len);
 		pbss_network->Ssid.ssid_len = ie_len;
 	}
 
-	/* chnnel */
+	/* channel */
 	channel = 0;
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_DS_PARAMS, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_DS_PARAMS, &ie_len,
+			  pbss_network->IELength);
 	if (p && ie_len > 0)
 		channel = *(p + 2);
 
@@ -863,16 +855,16 @@ int rtw_check_beacon_data23a(struct rtw_
 
 	memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
 	/*  get supported rates */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_SUPP_RATES, &ie_len,
+			  pbss_network->IELength);
 	if (p) {
 		memcpy(supportRate, p+2, ie_len);
 		supportRateNum = ie_len;
 	}
 
 	/* get ext_supported rates */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES,
-			  &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
+	p = rtw_get_ie23a(ie, WLAN_EID_EXT_SUPP_RATES,
+			  &ie_len, pbss_network->IELength);
 	if (p) {
 		memcpy(supportRate+supportRateNum, p+2, ie_len);
 		supportRateNum += ie_len;
@@ -884,13 +876,13 @@ int rtw_check_beacon_data23a(struct rtw_
 	rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type);
 
 	/* parsing ERP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &ie_len,
+			  pbss_network->IELength);
 	if (p && ie_len > 0)
 		ERP_IE_handler23a(padapter, p);
 
 	/* update privacy/security */
-	if (cap & BIT(4))
+	if (pbss_network->capability & BIT(4))
 		pbss_network->Privacy = 1;
 	else
 		pbss_network->Privacy = 0;
@@ -901,8 +893,8 @@ int rtw_check_beacon_data23a(struct rtw_
 	group_cipher = 0; pairwise_cipher = 0;
 	psecuritypriv->wpa2_group_cipher = 0;
 	psecuritypriv->wpa2_pairwise_cipher = 0;
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_RSN, &ie_len,
+			  pbss_network->IELength);
 	if (p && ie_len > 0) {
 		if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher,
 					 &pairwise_cipher, NULL) == _SUCCESS) {
@@ -922,10 +914,9 @@ int rtw_check_beacon_data23a(struct rtw_
 	pairwise_cipher = 0;
 	psecuritypriv->wpa_group_cipher = 0;
 	psecuritypriv->wpa_pairwise_cipher = 0;
-	for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
+	for (p = ie; ;p += (ie_len + 2)) {
 		p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
-				  (pbss_network->IELength - _BEACON_IE_OFFSET_ -
-				  (ie_len + 2)));
+				  pbss_network->IELength - (ie_len + 2));
 		if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) {
 			if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher,
 						&pairwise_cipher, NULL) == _SUCCESS) {
@@ -950,10 +941,10 @@ int rtw_check_beacon_data23a(struct rtw_
 	ie_len = 0;
 	pmlmepriv->qos_option = 0;
 	if (pregistrypriv->wmm_enable) {
-		for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
+		for (p = ie; ;p += (ie_len + 2)) {
 			p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
 					  (pbss_network->IELength -
-					  _BEACON_IE_OFFSET_ - (ie_len + 2)));
+					   (ie_len + 2)));
 			if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
 				pmlmepriv->qos_option = 1;
 
@@ -973,8 +964,8 @@ int rtw_check_beacon_data23a(struct rtw_
 		}
 	}
 	/* parsing HT_CAP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_HT_CAPABILITY, &ie_len,
+			  pbss_network->IELength);
 	if (p && ie_len > 0) {
 		u8 rf_type;
 
@@ -1005,8 +996,8 @@ int rtw_check_beacon_data23a(struct rtw_
 	}
 
 	/* parsing HT_INFO_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len,
-			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_HT_OPERATION, &ie_len,
+			  pbss_network->IELength);
 	if (p && ie_len > 0)
 		pHT_info_ie = p;
 
@@ -1179,7 +1170,7 @@ static void update_bcn_erpinfo_ie(struct
 		return;
 
 	/* parsing ERP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &len, pnetwork->IELength);
 	if (p && len > 0) {
 		if (pmlmepriv->num_sta_non_erp == 1)
 			p[2] |= WLAN_ERP_NON_ERP_PRESENT |
@@ -1224,54 +1215,9 @@ static void update_bcn_wmm_ie(struct rtw
 
 static void update_bcn_wps_ie(struct rtw_adapter *padapter)
 {
-	u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;
-	uint wps_ielen = 0, wps_offset, remainder_ielen;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-	unsigned char *ie = pnetwork->IEs;
-	u32 ielen = pnetwork->IELength;
-
 	DBG_8723A("%s\n", __func__);
 
-	pwps_ie_src = pmlmepriv->wps_beacon_ie;
-	if (pwps_ie_src == NULL)
-		return;
-
-	pwps_ie = rtw_get_wps_ie23a(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
-
-	if (pwps_ie == NULL || wps_ielen == 0)
-		return;
-
-	wps_offset = (uint)(pwps_ie-ie);
-
-	premainder_ie = pwps_ie + wps_ielen;
-
-	remainder_ielen = ielen - wps_offset - wps_ielen;
-
-	if (remainder_ielen > 0) {
-		pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
-		if (pbackup_remainder_ie)
-			memcpy(pbackup_remainder_ie, premainder_ie,
-			       remainder_ielen);
-	}
-
-	wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
-	if ((wps_offset+wps_ielen+2+remainder_ielen)<= MAX_IE_SZ)
-	{
-		memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
-		pwps_ie += (wps_ielen+2);
-
-		if (pbackup_remainder_ie)
-			memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
-
-		/* update IELength */
-		pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
-	}
-
-	if (pbackup_remainder_ie)
-		kfree(pbackup_remainder_ie);
+	return;
 }
 
 static void update_bcn_p2p_ie(struct rtw_adapter *padapter)
@@ -1359,7 +1305,7 @@ void update_beacon23a(struct rtw_adapter
 
 /*
 op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
 	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
 	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
 Set to 1 (HT non-member protection) if there may be non-HT STAs
@@ -1376,7 +1322,7 @@ static int rtw_ht_operation_update(struc
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
 
-	if (pmlmepriv->htpriv.ht_option == true)
+	if (pmlmepriv->htpriv.ht_option)
 		return 0;
 
 	/* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
@@ -1441,7 +1387,7 @@ static int rtw_ht_operation_update(struc
 
 void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated)
 {
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	if (updated == true)
 	{
 		struct list_head *phead, *plist, *ptmp;
@@ -1612,7 +1558,7 @@ void bss_cap_update_on_sta_join23a(struc
 			psta->no_ht_set = 1;
 			pmlmepriv->num_sta_no_ht++;
 		}
-		if (pmlmepriv->htpriv.ht_option == true) {
+		if (pmlmepriv->htpriv.ht_option) {
 			DBG_8723A("%s STA " MAC_FMT
 				   " - no HT, num of non-HT stations %d\n",
 				   __func__, MAC_ARG(psta->hwaddr),
@@ -1626,7 +1572,7 @@ void bss_cap_update_on_sta_join23a(struc
 		update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	associated_clients_update23a(padapter,  beacon_updated);
 
 	DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
@@ -1695,7 +1641,7 @@ u8 bss_cap_update_on_sta_leave23a(struct
 		update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 
 	DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
 
@@ -1757,7 +1703,7 @@ int rtw_ap_inform_ch_switch23a (struct r
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) != MSR_AP)
 		return ret;
 
 	DBG_8723A("%s(%s): with ch:%u, offset:%u\n", __func__,
@@ -1794,7 +1740,7 @@ int rtw_sta_flush23a(struct rtw_adapter
 
 	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) != MSR_AP)
 		return ret;
 
 	spin_lock_bh(&pstapriv->asoc_list_lock);
@@ -1850,7 +1796,7 @@ void sta_info_update23a(struct rtw_adapt
 		psta->htpriv.ht_option = false;
 	}
 
-	if (pmlmepriv->htpriv.ht_option == false)
+	if (!pmlmepriv->htpriv.ht_option)
 		psta->htpriv.ht_option = false;
 
 	update_sta_info23a_apmode23a(padapter, psta);
@@ -1957,13 +1903,6 @@ void start_ap_mode23a(struct rtw_adapter
 	for (i = 0; i<NUM_STA; i++)
 		pstapriv->sta_aid[i] = NULL;
 
-	pmlmepriv->wps_beacon_ie = NULL;
-	pmlmepriv->wps_probe_resp_ie = NULL;
-	pmlmepriv->wps_assoc_resp_ie = NULL;
-
-	pmlmepriv->p2p_beacon_ie = NULL;
-	pmlmepriv->p2p_probe_resp_ie = NULL;
-
 	/* for ACL */
 	INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
 	pacl_list->num = 0;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -203,22 +203,9 @@ void rtw_free_evt_priv23a(struct evt_pri
 
 static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 {
-	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
 	/* set to true to allow enqueuing cmd when hw_init_completed is false */
 	u8 bAllow = false;
 
-	/* To decide allow or not */
-	if (pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect &&
-	    !pcmdpriv->padapter->registrypriv.usbss_enable) {
-		if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
-			pdrvextra_cmd_parm =
-				(struct drvextra_cmd_parm *)cmd_obj->parmbuf;
-			if (pdrvextra_cmd_parm->ec_id ==
-			    POWER_SAVING_CTRL_WK_CID)
-				bAllow = true;
-		}
-	}
-
 	if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
 		bAllow = true;
 
@@ -322,7 +309,7 @@ post_process:
 				  pcmd_callback, pcmd->cmdcode));
 			rtw_free_cmd_obj23a(pcmd);
 		} else {
-			/* need conider that free cmd_obj in
+			/* need consider that free cmd_obj in
 			   rtw_cmd_callback */
 			pcmd_callback(pcmd->padapter, pcmd);
 		}
@@ -464,7 +451,6 @@ exit:
 int rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
 		       struct wlan_network *pnetwork)
 {
-	u8 *auth;
 	int res = _SUCCESS;
 	struct wlan_bssid_ex *psecnetwork;
 	struct cmd_obj *pcmd;
@@ -516,9 +502,7 @@ int rtw_joinbss_cmd23a(struct rtw_adapte
 
 	psecnetwork = &psecuritypriv->sec_bss;
 	if (!psecnetwork) {
-		if (pcmd)
-			kfree(pcmd);
-
+		kfree(pcmd);
 		res = _FAIL;
 
 		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
@@ -532,18 +516,6 @@ int rtw_joinbss_cmd23a(struct rtw_adapte
 	memcpy(psecnetwork, &pnetwork->network,
 	       get_wlan_bssid_ex_sz(&pnetwork->network));
 
-	auth = &psecuritypriv->authenticator_ie[0];
-	psecuritypriv->authenticator_ie[0] =
-		(unsigned char)psecnetwork->IELength;
-
-	if ((psecnetwork->IELength-12) < (256-1)) {
-		memcpy(&psecuritypriv->authenticator_ie[1],
-		       &psecnetwork->IEs[12], psecnetwork->IELength - 12);
-	} else {
-		memcpy(&psecuritypriv->authenticator_ie[1],
-		       &psecnetwork->IEs[12], 256 - 1);
-	}
-
 	psecnetwork->IELength = 0;
 	/*  Added by Albert 2009/02/18 */
 	/*  If the the driver wants to use the bssid to create the
@@ -751,7 +723,7 @@ int rtw_setstakey_cmd23a(struct rtw_adap
 		       &psecuritypriv->dot118021XGrpKey[idx].skey, 16);
         }
 
-	/* jeff: set this becasue at least sw key is ready */
+	/* jeff: set this because at least sw key is ready */
 	padapter->securitypriv.busetkipkey = 1;
 
 	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
@@ -1126,11 +1098,6 @@ exit:
 	return res;
 }
 
-static void power_saving_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
-{
-	 rtw_ps_processor23a(padapter);
-}
-
 int rtw_ps_cmd23a(struct rtw_adapter*padapter)
 {
 	struct cmd_obj *ppscmd;
@@ -1345,8 +1312,7 @@ int rtw_drvextra_cmd_hdl23a(struct rtw_a
 				   pdrvextra_cmd->type_size);
 		break;
 	case POWER_SAVING_CTRL_WK_CID:
-		power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf,
-				    pdrvextra_cmd->type_size);
+		rtw_ps_processor23a(padapter);
 		break;
 	case LPS_CTRL_WK_CID:
 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_efuse.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_efuse.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_efuse.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_efuse.c	2014-09-28 17:29:07.000000000 -0400
@@ -59,7 +59,7 @@ static void Efuse_PowerSwitch(struct rtw
 		rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
 
 		/*  1.2V Power: From VDDON with Power
-		    Cut(0x0000h[15]), defualt valid */
+		    Cut(0x0000h[15]), default valid */
 		tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL);
 		if (!(tmpV16 & PWC_EV12V)) {
 			tmpV16 |= PWC_EV12V;
@@ -100,22 +100,6 @@ static void Efuse_PowerSwitch(struct rtw
 	}
 }
 
-/*-----------------------------------------------------------------------------
- * Function:	efuse_GetCurrentSize23a
- *
- * Overview:	Get current efuse size!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When			Who		Remark
- * 11/16/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
 u16
 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
 {
@@ -144,7 +128,7 @@ Efuse_CalculateWordCnts23a(u8 word_en)
 /*  */
 /*	Description: */
 /*		Execute E-Fuse read byte operation. */
-/*		Refered from SD1 Richard. */
+/*		Referred from SD1 Richard. */
 /*  */
 /*	Assumption: */
 /*		1. Boot from E-Fuse and successfully auto-load. */
@@ -521,7 +505,7 @@ static int efuse_write8(struct rtw_adapt
 }
 
 /*
- * read/wirte raw efuse data
+ * read/write raw efuse data
  */
 int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
 			u16 cnts, u8 *data)
@@ -576,15 +560,6 @@ u16 efuse_GetMaxSize23a(struct rtw_adapt
 	return max_size;
 }
 /*  */
-int efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size)
-{
-	Efuse_PowerSwitch(padapter, false, true);
-	*size = Efuse_GetCurrentSize23a(padapter, EFUSE_WIFI);
-	Efuse_PowerSwitch(padapter, false, false);
-
-	return _SUCCESS;
-}
-/*  */
 int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
 			  u16 addr, u16 cnts, u8 *data)
 {
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ieee80211.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ieee80211.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ieee80211.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ieee80211.c	2014-09-28 17:29:07.000000000 -0400
@@ -33,7 +33,6 @@ u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00,
 u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 };
 u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 };
 
-u16 RSN_VERSION_BSD23A = 1;
 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 };
 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 };
 u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 };
@@ -124,14 +123,6 @@ int rtw_check_network_type23a(unsigned c
 	}
 }
 
-u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len,
-		     unsigned char *source, unsigned int *frlen)
-{
-	memcpy((void *)pbuf, (void *)source, len);
-	*frlen = *frlen + len;
-	return pbuf + len;
-}
-
 /*  rtw_set_ie23a will update frame length */
 u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen)
 {
@@ -161,14 +152,12 @@ inline u8 *rtw_set_ie23a_ch_switch (u8 *
 
 inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset)
 {
-	if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
-		return SCN;
-	else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
-		return SCB;
+	if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+		return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
 	else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
-		return SCA;
+		return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
 
-	return SCN;
+	return IEEE80211_HT_PARAM_CHA_SEC_NONE;
 }
 
 inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len,
@@ -261,7 +250,7 @@ u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_
  * rtw_ies_remove_ie23a - Find matching IEs and remove
  * @ies: Address of IEs to search
  * @ies_len: Pointer of length of ies, will update to new length
- * @offset: The offset to start scarch
+ * @offset: The offset to start search
  * @eid: Element ID to match
  * @oui: OUI to match
  * @oui_len: OUI length
@@ -361,32 +350,19 @@ int rtw_generate_ie23a(struct registry_p
 	int	sz = 0, rateLen;
 	struct wlan_bssid_ex*	pdev_network = &pregistrypriv->dev_network;
 	u8*	ie = pdev_network->IEs;
+	u16 cap;
 
+	pdev_network->tsf = 0;
 
-
-	/* timestamp will be inserted by hardware */
-	sz += 8;
-	ie += sz;
-
-	/* beacon interval : 2bytes */
-	/* BCN_INTERVAL; */
-	*(u16*)ie = cpu_to_le16(pdev_network->BeaconPeriod);
-	sz += 2;
-	ie += 2;
-
-	/* capability info */
-	*(u16*)ie = 0;
-
-	*(u16*)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS);
+	cap = WLAN_CAPABILITY_IBSS;
 
 	if (pregistrypriv->preamble == PREAMBLE_SHORT)
-		*(u16*)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
+		cap |= WLAN_CAPABILITY_SHORT_PREAMBLE;
 
 	if (pdev_network->Privacy)
-		*(u16*)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+		cap |= WLAN_CAPABILITY_PRIVACY;
 
-	sz += 2;
-	ie += 2;
+	pdev_network->capability = cap;
 
 	/* SSID */
 	ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len,
@@ -436,7 +412,7 @@ int rtw_generate_ie23a(struct registry_p
 	return sz;
 }
 
-int rtw_get_wpa_cipher_suite23a(const u8 *s)
+static int rtw_get_wpa_cipher_suite(const u8 *s)
 {
 	if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
@@ -452,7 +428,7 @@ int rtw_get_wpa_cipher_suite23a(const u8
 	return 0;
 }
 
-int rtw_get_wpa2_cipher_suite23a(const u8 *s)
+static int rtw_get_wpa2_cipher_suite(const u8 *s)
 {
 	if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
@@ -490,7 +466,7 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie
 	/* group_cipher */
 	if (left >= WPA_SELECTOR_LEN) {
 
-		*group_cipher = rtw_get_wpa_cipher_suite23a(pos);
+		*group_cipher = rtw_get_wpa_cipher_suite(pos);
 
 		pos += WPA_SELECTOR_LEN;
 		left -= WPA_SELECTOR_LEN;
@@ -518,7 +494,7 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie
 		}
 
 		for (i = 0; i < count; i++) {
-			*pairwise_cipher |= rtw_get_wpa_cipher_suite23a(pos);
+			*pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
 
 			pos += WPA_SELECTOR_LEN;
 			left -= WPA_SELECTOR_LEN;
@@ -557,7 +533,7 @@ int rtw_parse_wpa2_ie23a(const u8* rsn_i
 		return _FAIL;
 	}
 
-	if (*rsn_ie != _WPA2_IE_ID_ || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) {
+	if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) {
 		return _FAIL;
 	}
 
@@ -567,7 +543,7 @@ int rtw_parse_wpa2_ie23a(const u8* rsn_i
 
 	/* group_cipher */
 	if (left >= RSN_SELECTOR_LEN) {
-		*group_cipher = rtw_get_wpa2_cipher_suite23a(pos);
+		*group_cipher = rtw_get_wpa2_cipher_suite(pos);
 
 		pos += RSN_SELECTOR_LEN;
 		left -= RSN_SELECTOR_LEN;
@@ -594,7 +570,7 @@ int rtw_parse_wpa2_ie23a(const u8* rsn_i
 		}
 
 		for (i = 0; i < count; i++) {
-			*pairwise_cipher |= rtw_get_wpa2_cipher_suite23a(pos);
+			*pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
 
 			pos += RSN_SELECTOR_LEN;
 			left -= RSN_SELECTOR_LEN;
@@ -621,130 +597,6 @@ int rtw_parse_wpa2_ie23a(const u8* rsn_i
 	return ret;
 }
 
-int rtw_get_sec_ie23a(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
-		   u8 *wpa_ie, u16 *wpa_len)
-{
-	u8 authmode, sec_idx, i;
-	uint cnt;
-
-
-	/* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
-
-	cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
-
-	sec_idx = 0;
-
-	while(cnt < in_len) {
-		authmode = in_ie[cnt];
-
-		if ((authmode == WLAN_EID_VENDOR_SPECIFIC) &&
-		    !memcmp(&in_ie[cnt+2], RTW_WPA_OUI23A_TYPE, 4)) {
-				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-					 ("\n rtw_get_wpa_ie23a: sec_idx =%d "
-					  "in_ie[cnt+1]+2 =%d\n",
-					  sec_idx, in_ie[cnt + 1] + 2));
-
-				if (wpa_ie) {
-				memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2);
-
-				for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
-					RT_TRACE(_module_rtl871x_mlme_c_,
-						 _drv_info_,
-						 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
-						  "%2x,%2x\n", wpa_ie[i],
-						  wpa_ie[i + 1], wpa_ie[i + 2],
-						  wpa_ie[i + 3], wpa_ie[i + 4],
-						  wpa_ie[i + 5], wpa_ie[i + 6],
-						  wpa_ie[i + 7]));
-					}
-				}
-
-				*wpa_len = in_ie[cnt + 1] + 2;
-				cnt += in_ie[cnt + 1] + 2;  /* get next */
-		} else {
-			if (authmode == _WPA2_IE_ID_) {
-				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-					 ("\n get_rsn_ie: sec_idx =%d in_ie"
-					  "[cnt+1]+2 =%d\n", sec_idx,
-					  in_ie[cnt + 1] + 2));
-
-				if (rsn_ie) {
-				memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
-				for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
-					RT_TRACE(_module_rtl871x_mlme_c_,
-						 _drv_info_,
-						 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
-						  "%2x,%2x\n", rsn_ie[i],
-						  rsn_ie[i + 1], rsn_ie[i + 2],
-						  rsn_ie[i + 3], rsn_ie[i + 4],
-						  rsn_ie[i + 5], rsn_ie[i + 6],
-						  rsn_ie[i + 7]));
-					}
-				}
-
-				*rsn_len = in_ie[cnt + 1] + 2;
-				cnt += in_ie[cnt + 1] + 2;  /* get next */
-			} else {
-				cnt += in_ie[cnt + 1] + 2;   /* get next */
-			}
-		}
-	}
-
-
-
-	return *rsn_len + *wpa_len;
-}
-
-/**
- * rtw_get_wps_ie23a - Search WPS IE from a series of IEs
- * @in_ie: Address of IEs to search
- * @in_len: Length limit from in_ie
- * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the
- *          buf starting from wps_ie
- * @wps_ielen: If not NULL and WPS IE is found, will set to the length of
- *             the entire WPS IE
- *
- * Returns: The address of the WPS IE found, or NULL
- */
-u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
-{
-	uint cnt;
-	u8 *wpsie_ptr = NULL;
-	u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
-	if (wps_ielen)
-		*wps_ielen = 0;
-
-	if (!in_ie || in_len <= 0)
-		return wpsie_ptr;
-
-	cnt = 0;
-
-	while (cnt < in_len) {
-		eid = in_ie[cnt];
-
-		if (eid == WLAN_EID_VENDOR_SPECIFIC &&
-		    !memcmp(&in_ie[cnt+2], wps_oui, 4)) {
-			wpsie_ptr = &in_ie[cnt];
-
-			if (wps_ie)
-				memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
-			if (wps_ielen)
-				*wps_ielen = in_ie[cnt + 1] + 2;
-
-			cnt += in_ie[cnt + 1] + 2;
-
-			break;
-		} else {
-			cnt += in_ie[cnt + 1] + 2; /* goto next */
-		}
-	}
-
-	return wpsie_ptr;
-}
-
 /**
  * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE
  * @wps_ie: Address of WPS IE to search
@@ -757,11 +609,11 @@ u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in
  *
  * Returns: the address of the specific WPS attribute found, or NULL
  */
-u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
-		     u8 *buf_attr, u32 *len_attr)
+const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen,
+			      u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
 {
-	u8 *attr_ptr = NULL;
-	u8 * target_attr_ptr = NULL;
+	const u8 *attr_ptr = NULL;
+	const u8 *target_attr_ptr = NULL;
 	u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
 
 	if (len_attr)
@@ -813,15 +665,12 @@ u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint
  *
  * Returns: the address of the specific WPS attribute content found, or NULL
  */
-u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
-				u8 *buf_content, uint *len_content)
+const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen,
+				      u16 target_attr_id, u8 *buf_content)
 {
-	u8 *attr_ptr;
+	const u8 *attr_ptr;
 	u32 attr_len;
 
-	if (len_content)
-		*len_content = 0;
-
 	attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id,
 				    NULL, &attr_len);
 
@@ -829,9 +678,6 @@ u8 *rtw_get_wps_attr_content23a(u8 *wps_
 		if (buf_content)
 			memcpy(buf_content, attr_ptr + 4, attr_len - 4);
 
-		if (len_content)
-			*len_content = attr_len - 4;
-
 		return attr_ptr + 4;
 	}
 
@@ -843,13 +689,11 @@ static int rtw_get_cipher_info(struct wl
 	const u8 *pbuf;
 	int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
 	int ret = _FAIL;
-	int r, offset, plen;
+	int r, plen;
 	char *pie;
 
-	offset = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u);
-	pie = &pnetwork->network.IEs[offset];
-	plen = pnetwork->network.IELength - offset;
+	pie = pnetwork->network.IEs;
+	plen = pnetwork->network.IELength;
 
 	pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 				       WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen);
@@ -903,166 +747,112 @@ static int rtw_get_cipher_info(struct wl
 
 void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
 {
-	unsigned short cap;
 	u8 bencrypt = 0;
-	/* u8 wpa_ie[255], rsn_ie[255]; */
-	u16 wpa_len = 0, rsn_len = 0;
-	struct HT_info_element *pht_info;
-	struct ieee80211_ht_cap *pht_cap;
+	int pie_len;
+	u8 *pie;
 	const u8 *p;
 
-	cap = get_unaligned_le16(
-		rtw_get_capability23a_from_ie(pnetwork->network.IEs));
-	if (cap & WLAN_CAPABILITY_PRIVACY) {
+	if (pnetwork->network.capability & WLAN_CAPABILITY_PRIVACY) {
 		bencrypt = 1;
 		pnetwork->network.Privacy = 1;
 	} else
 		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
 
-	rtw_get_sec_ie23a(pnetwork->network.IEs, pnetwork->network.IELength,
-		       NULL, &rsn_len, NULL, &wpa_len);
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
-		  wpa_len, rsn_len));
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
-		  wpa_len, rsn_len));
+		 ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid));
 
-	if (rsn_len > 0)
+	pie = pnetwork->network.IEs;
+	pie_len = pnetwork->network.IELength;
+
+	p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
+	if (p && p[1]) {
 		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
-	else if (wpa_len > 0)
+	} else if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					   WLAN_OUI_TYPE_MICROSOFT_WPA,
+					   pie, pie_len)) {
 		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
-	else {
+	} else {
 		if (bencrypt)
 			pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
 	}
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
+		 ("%s: pnetwork->encryp_protocol is %x\n", __func__,
 		  pnetwork->BcnInfo.encryp_protocol));
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
+		 ("%s: pnetwork->encryp_protocol is %x\n", __func__,
 		  pnetwork->BcnInfo.encryp_protocol));
 	rtw_get_cipher_info(pnetwork);
 
 	/* get bwmode and ch_offset */
-	/* parsing HT_CAP_IE */
-	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-			     pnetwork->network.IEs + _FIXED_IE_LENGTH_,
-			     pnetwork->network.IELength - _FIXED_IE_LENGTH_);
-	if (p && p[1] > 0) {
-		pht_cap = (struct ieee80211_ht_cap *)(p + 2);
-		pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
-	} else
-		pnetwork->BcnInfo.ht_cap_info = 0;
-
-	/* parsing HT_INFO_IE */
-	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
-			     pnetwork->network.IEs + _FIXED_IE_LENGTH_,
-		       pnetwork->network.IELength - _FIXED_IE_LENGTH_);
-	if (p && p[1] > 0) {
-		pht_info = (struct HT_info_element *)(p + 2);
-		pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
-	} else
-		pnetwork->BcnInfo.ht_info_infos_0 = 0;
 }
 
 /* show MCS rate, unit: 100Kbps */
 u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
-		 unsigned char * MCS_rate)
+		    struct ieee80211_mcs_info *mcs)
 {
 	u16 max_rate = 0;
 
 	if (rf_type == RF_1T1R) {
-		if (MCS_rate[0] & BIT(7))
+		if (mcs->rx_mask[0] & BIT(7))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):
 				((short_GI_20)?722:650);
-		else if (MCS_rate[0] & BIT(6))
+		else if (mcs->rx_mask[0] & BIT(6))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):
 				((short_GI_20)?650:585);
-		else if (MCS_rate[0] & BIT(5))
+		else if (mcs->rx_mask[0] & BIT(5))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):
 				((short_GI_20)?578:520);
-		else if (MCS_rate[0] & BIT(4))
+		else if (mcs->rx_mask[0] & BIT(4))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):
 				((short_GI_20)?433:390);
-		else if (MCS_rate[0] & BIT(3))
+		else if (mcs->rx_mask[0] & BIT(3))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):
 				((short_GI_20)?289:260);
-		else if (MCS_rate[0] & BIT(2))
+		else if (mcs->rx_mask[0] & BIT(2))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):
 				((short_GI_20)?217:195);
-		else if (MCS_rate[0] & BIT(1))
+		else if (mcs->rx_mask[0] & BIT(1))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):
 				((short_GI_20)?144:130);
-		else if (MCS_rate[0] & BIT(0))
+		else if (mcs->rx_mask[0] & BIT(0))
 			max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):
 				((short_GI_20)?72:65);
 	} else {
-		if (MCS_rate[1]) {
-			if (MCS_rate[1] & BIT(7))
+		if (mcs->rx_mask[1]) {
+			if (mcs->rx_mask[1] & BIT(7))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300);
-			else if (MCS_rate[1] & BIT(6))
+			else if (mcs->rx_mask[1] & BIT(6))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170);
-			else if (MCS_rate[1] & BIT(5))
+			else if (mcs->rx_mask[1] & BIT(5))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040);
-			else if (MCS_rate[1] & BIT(4))
+			else if (mcs->rx_mask[1] & BIT(4))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780);
-			else if (MCS_rate[1] & BIT(3))
+			else if (mcs->rx_mask[1] & BIT(3))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
-			else if (MCS_rate[1] & BIT(2))
+			else if (mcs->rx_mask[1] & BIT(2))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
-			else if (MCS_rate[1] & BIT(1))
+			else if (mcs->rx_mask[1] & BIT(1))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
-			else if (MCS_rate[1] & BIT(0))
+			else if (mcs->rx_mask[1] & BIT(0))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
 		} else {
-			if (MCS_rate[0] & BIT(7))
+			if (mcs->rx_mask[0] & BIT(7))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
-			else if (MCS_rate[0] & BIT(6))
+			else if (mcs->rx_mask[0] & BIT(6))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
-			else if (MCS_rate[0] & BIT(5))
+			else if (mcs->rx_mask[0] & BIT(5))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
-			else if (MCS_rate[0] & BIT(4))
+			else if (mcs->rx_mask[0] & BIT(4))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
-			else if (MCS_rate[0] & BIT(3))
+			else if (mcs->rx_mask[0] & BIT(3))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
-			else if (MCS_rate[0] & BIT(2))
+			else if (mcs->rx_mask[0] & BIT(2))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
-			else if (MCS_rate[0] & BIT(1))
+			else if (mcs->rx_mask[0] & BIT(1))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
-			else if (MCS_rate[0] & BIT(0))
+			else if (mcs->rx_mask[0] & BIT(0))
 				max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
 		}
 	}
 	return max_rate;
 }
-
-static const char *_action_public_str23a[] = {
-	"ACT_PUB_BSSCOEXIST",
-	"ACT_PUB_DSE_ENABLE",
-	"ACT_PUB_DSE_DEENABLE",
-	"ACT_PUB_DSE_REG_LOCATION",
-	"ACT_PUB_EXT_CHL_SWITCH",
-	"ACT_PUB_DSE_MSR_REQ",
-	"ACT_PUB_DSE_MSR_RPRT",
-	"ACT_PUB_MP",
-	"ACT_PUB_DSE_PWR_CONSTRAINT",
-	"ACT_PUB_VENDOR",
-	"ACT_PUB_GAS_INITIAL_REQ",
-	"ACT_PUB_GAS_INITIAL_RSP",
-	"ACT_PUB_GAS_COMEBACK_REQ",
-	"ACT_PUB_GAS_COMEBACK_RSP",
-	"ACT_PUB_TDLS_DISCOVERY_RSP",
-	"ACT_PUB_LOCATION_TRACK",
-	"ACT_PUB_RSVD",
-};
-
-const char *action_public_str23a(u8 action)
-{
-	action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
-	return _action_public_str23a[action];
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ioctl_set.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_ioctl_set.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_ioctl_set.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,425 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- ******************************************************************************/
-#define _RTW_IOCTL_SET_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_ioctl_set.h>
-#include <hal_intf.h>
-
-#include <usb_ops.h>
-#include <linux/ieee80211.h>
-
-int rtw_do_join23a(struct rtw_adapter *padapter)
-{
-	struct list_head *plist, *phead;
-	u8* pibss = NULL;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
-	int ret = _SUCCESS;
-
-	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-		 ("\n rtw_do_join23a: phead = %p; plist = %p\n\n\n",
-		  phead, plist));
-
-	pmlmepriv->cur_network.join_res = -2;
-
-	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
-	pmlmepriv->to_join = true;
-
-	if (list_empty(&queue->queue)) {
-		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
-		/* when set_ssid/set_bssid for rtw_do_join23a(), but
-		   scanning queue is empty */
-		/* we try to issue sitesurvey firstly */
-
-		if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false ||
-		    padapter->mlmepriv.to_roaming > 0) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-				 ("rtw_do_join23a(): site survey if scanned_queue "
-				  "is empty\n."));
-			/*  submit site_survey23a_cmd */
-			ret = rtw_sitesurvey_cmd23a(padapter,
-						 &pmlmepriv->assoc_ssid, 1,
-						 NULL, 0);
-			if (ret != _SUCCESS) {
-				pmlmepriv->to_join = false;
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-					 ("rtw_do_join23a(): site survey return "
-					  "error\n."));
-			}
-		} else {
-			pmlmepriv->to_join = false;
-			ret = _FAIL;
-		}
-
-		goto exit;
-	} else {
-		int select_ret;
-		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-		select_ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
-		if (select_ret == _SUCCESS) {
-			pmlmepriv->to_join = false;
-			mod_timer(&pmlmepriv->assoc_timer,
-				  jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
-		} else {
-			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-				struct wlan_bssid_ex *pdev_network;
-				/*  submit createbss_cmd to change to a
-				    ADHOC_MASTER */
-
-				/* pmlmepriv->lock has been acquired by
-				   caller... */
-				pdev_network =
-					&padapter->registrypriv.dev_network;
-
-				pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
-
-				pibss = padapter->registrypriv.dev_network.MacAddress;
-
-				memcpy(&pdev_network->Ssid,
-				       &pmlmepriv->assoc_ssid,
-				       sizeof(struct cfg80211_ssid));
-
-				rtw_update_registrypriv_dev_network23a(padapter);
-
-				rtw_generate_random_ibss23a(pibss);
-
-				if (rtw_createbss_cmd23a(padapter) != _SUCCESS) {
-					RT_TRACE(_module_rtl871x_ioctl_set_c_,
-						 _drv_err_,
-						 ("***Error =>do_goin: rtw_creat"
-						  "ebss_cmd status FAIL***\n"));
-					ret =  false;
-					goto exit;
-				}
-
-				pmlmepriv->to_join = false;
-
-				RT_TRACE(_module_rtl871x_ioctl_set_c_,
-					 _drv_info_,
-					 ("***Error => rtw_select_and_join_from"
-					  "_scanned_queue FAIL under STA_Mode"
-					  "***\n "));
-			} else {
-				/*  can't associate ; reset under-linking */
-				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
-				/* when set_ssid/set_bssid for rtw_do_join23a(),
-				   but there are no desired bss in scanning
-				   queue */
-				/* we try to issue sitesurvey firstly */
-				if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==
-				    false || padapter->mlmepriv.to_roaming > 0){
-					/* DBG_8723A("rtw_do_join23a() when   no "
-					   "desired bss in scanning queue\n");
-					*/
-					ret = rtw_sitesurvey_cmd23a(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
-					if (ret != _SUCCESS) {
-						pmlmepriv->to_join = false;
-						RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
-					}
-				} else {
-					ret = _FAIL;
-					pmlmepriv->to_join = false;
-				}
-			}
-		}
-	}
-
-exit:
-
-	return ret;
-}
-
-int rtw_set_802_11_ssid23a(struct rtw_adapter* padapter,
-			   struct cfg80211_ssid *ssid)
-{
-	int status = _SUCCESS;
-	u32 cur_time = 0;
-
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
-
-
-
-	DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
-			ssid->ssid, get_fwstate(pmlmepriv));
-
-	if (padapter->hw_init_completed == false) {
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
-		status = _FAIL;
-		goto exit;
-	}
-
-	spin_lock_bh(&pmlmepriv->lock);
-
-	DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
-	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
-		goto handle_tkip_countermeasure;
-	else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
-		goto release_mlme_lock;
-
-	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-			 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
-
-		if ((pmlmepriv->assoc_ssid.ssid_len == ssid->ssid_len) &&
-		    !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid,
-			    ssid->ssid_len)) {
-			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-					 ("Set SSID is the same ssid, fw_state = 0x%08x\n",
-					  get_fwstate(pmlmepriv)));
-
-				if (rtw_is_same_ibss23a(padapter, pnetwork) == false)
-				{
-					/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
-					rtw_disassoc_cmd23a(padapter, 0, true);
-
-					if (check_fwstate(pmlmepriv, _FW_LINKED))
-						rtw_indicate_disconnect23a(padapter);
-
-					rtw_free_assoc_resources23a(padapter, 1);
-
-					if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
-						_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-						set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-					}
-				} else {
-					goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
-				}
-			} else {
-				rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_JOINBSS, 1);
-			}
-		} else {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-				 ("Set SSID not the same ssid\n"));
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-				 ("set_ssid =[%s] len = 0x%x\n", ssid->ssid,
-				  (unsigned int)ssid->ssid_len));
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-				 ("assoc_ssid =[%s] len = 0x%x\n",
-				  pmlmepriv->assoc_ssid.ssid,
-				  (unsigned int)pmlmepriv->assoc_ssid.ssid_len));
-
-			rtw_disassoc_cmd23a(padapter, 0, true);
-
-			if (check_fwstate(pmlmepriv, _FW_LINKED))
-				rtw_indicate_disconnect23a(padapter);
-
-			rtw_free_assoc_resources23a(padapter, 1);
-
-			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
-				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-			}
-		}
-	}
-
-handle_tkip_countermeasure:
-
-	if (padapter->securitypriv.btkip_countermeasure == true) {
-		cur_time = jiffies;
-
-		if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ)
-		{
-			padapter->securitypriv.btkip_countermeasure = false;
-			padapter->securitypriv.btkip_countermeasure_time = 0;
-		}
-		else
-		{
-			status = _FAIL;
-			goto release_mlme_lock;
-		}
-	}
-
-	memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct cfg80211_ssid));
-	pmlmepriv->assoc_by_bssid = false;
-
-	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
-		pmlmepriv->to_join = true;
-	else
-		status = rtw_do_join23a(padapter);
-
-release_mlme_lock:
-	spin_unlock_bh(&pmlmepriv->lock);
-
-exit:
-	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-		("-rtw_set_802_11_ssid23a: status =%d\n", status));
-
-
-
-	return status;
-}
-
-int rtw_set_802_11_bssid23a_list_scan(struct rtw_adapter *padapter,
-				      struct cfg80211_ssid *pssid,
-				      int ssid_max_num)
-{
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	int res = _SUCCESS;
-
-	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-		 ("+rtw_set_802_11_bssid23a_list_scan(), fw_state =%x\n",
-		  get_fwstate(pmlmepriv)));
-
-	if (!padapter) {
-		res = _FAIL;
-		goto exit;
-	}
-	if (padapter->hw_init_completed == false) {
-		res = _FAIL;
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("\n === rtw_set_802_11_bssid23a_list_scan:"
-			  "hw_init_completed == false ===\n"));
-		goto exit;
-	}
-
-	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
-	    (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
-		/*  Scan or linking is in progress, do nothing. */
-		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-			 ("rtw_set_802_11_bssid23a_list_scan fail since fw_state "
-			  "= %x\n", get_fwstate(pmlmepriv)));
-
-		if (check_fwstate(pmlmepriv,
-				  (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n"));
-		} else {
-			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-				 ("\n###pmlmepriv->sitesurveyctrl.traffic_"
-				  "busy == true\n"));
-		}
-	} else {
-		if (rtw_is_scan_deny(padapter)) {
-			DBG_8723A("%s(%s): scan deny\n",
-				  __func__, padapter->pnetdev->name);
-			return _SUCCESS;
-		}
-
-		spin_lock_bh(&pmlmepriv->lock);
-
-		res = rtw_sitesurvey_cmd23a(padapter, pssid, ssid_max_num,
-					 NULL, 0);
-
-		spin_unlock_bh(&pmlmepriv->lock);
-	}
-exit:
-	return res;
-}
-
-int rtw_set_802_11_authentication_mode23a(struct rtw_adapter* padapter,
-					  enum ndis_802_11_auth_mode authmode)
-{
-	struct security_priv *psecuritypriv = &padapter->securitypriv;
-	int res;
-
-	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-		 ("set_802_11_auth.mode(): mode =%x\n", authmode));
-
-	psecuritypriv->ndisauthtype = authmode;
-
-	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-		 ("rtw_set_802_11_authentication_mode23a:"
-		  "psecuritypriv->ndisauthtype =%d",
-		  psecuritypriv->ndisauthtype));
-
-	if (psecuritypriv->ndisauthtype > 3)
-		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
-
-	res = rtw_set_auth23a(padapter, psecuritypriv);
-
-	return res;
-}
-
-/*
-* rtw_get_cur_max_rate23a -
-* @adapter: pointer to _adapter structure
-*
-* Return 0 or 100Kbps
-*/
-u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
-{
-	int i = 0;
-	const u8 *p;
-	u16 rate = 0, max_rate = 0;
-	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	struct registry_priv *pregistrypriv = &adapter->registrypriv;
-	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
-	struct ieee80211_ht_cap *pht_capie;
-	u8 rf_type = 0;
-	u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
-	u16 mcs_rate = 0;
-
-	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
-	    !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
-		return 0;
-
-	if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
-		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-				     &pcur_bss->IEs[12],
-				     pcur_bss->IELength - 12);
-		if (p && p[1] > 0) {
-			pht_capie = (struct ieee80211_ht_cap *)(p + 2);
-
-			memcpy(&mcs_rate, &pht_capie->mcs, 2);
-
-			/* bw_40MHz = (pht_capie->cap_info&
-			   IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
-			/* cur_bwmod is updated by beacon, pmlmeinfo is
-			   updated by association response */
-			bw_40MHz = (pmlmeext->cur_bwmode &&
-				    (IEEE80211_HT_PARAM_CHAN_WIDTH_ANY &
-				     pmlmeinfo->HT_info.infos[0])) ? 1:0;
-
-			/* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
-			   _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
-			short_GI_20 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_20) ? 1:0;
-			short_GI_40 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_40) ? 1:0;
-
-			rf_type = rtl8723a_get_rf_type(adapter);
-			max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
-						pregistrypriv->cbw40_enable,
-						short_GI_20, short_GI_40,
-						pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
-			);
-		}
-	} else {
-		while ((pcur_bss->SupportedRates[i] != 0) &&
-		       (pcur_bss->SupportedRates[i] != 0xFF)) {
-			rate = pcur_bss->SupportedRates[i] & 0x7F;
-			if (rate>max_rate)
-				max_rate = rate;
-			i++;
-		}
-
-		max_rate = max_rate * 10 / 2;
-	}
-
-	return max_rate;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_mlme.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_mlme.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_mlme.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_mlme.c	2014-09-28 17:29:07.000000000 -0400
@@ -24,12 +24,15 @@
 #include <linux/ieee80211.h>
 #include <wifi.h>
 #include <wlan_bssdef.h>
-#include <rtw_ioctl_set.h>
 #include <rtw_sreset.h>
 
+static struct wlan_network *
+rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv);
+static int rtw_do_join(struct rtw_adapter *padapter);
+
 static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
 {
-	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
 	setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
 		    (unsigned long)padapter);
@@ -84,36 +87,8 @@ void rtw23a_free_mlme_priv_ie_data(struc
 #ifdef CONFIG_8723AU_AP_MODE
 	kfree(pmlmepriv->assoc_req);
 	kfree(pmlmepriv->assoc_rsp);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie,
-			      &pmlmepriv->wps_beacon_ie_len);
 	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie,
 			      &pmlmepriv->wps_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie,
-			      &pmlmepriv->wps_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie,
-			      &pmlmepriv->wps_assoc_resp_ie_len);
-
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie,
-			      &pmlmepriv->p2p_beacon_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie,
-			      &pmlmepriv->p2p_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie,
-			      &pmlmepriv->p2p_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie,
-			      &pmlmepriv->p2p_go_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie,
-			      &pmlmepriv->p2p_assoc_req_ie_len);
-
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie,
-			      &pmlmepriv->wfd_beacon_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie,
-			      &pmlmepriv->wfd_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie,
-			      &pmlmepriv->wfd_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie,
-			      &pmlmepriv->wfd_go_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie,
-			      &pmlmepriv->wfd_assoc_req_ie_len);
 #endif
 }
 
@@ -125,7 +100,7 @@ void rtw_free_mlme_priv23a(struct mlme_p
 	rtw23a_free_mlme_priv_ie_data(pmlmepriv);
 }
 
-struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, int gfp)
+struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp)
 {
 	struct wlan_network *pnetwork;
 
@@ -159,7 +134,7 @@ static void _rtw_free_network23a(struct
 /*
  return the wlan_network with the matching addr
 
- Shall be calle under atomic context... to avoid possible racing condition...
+ Shall be called under atomic context... to avoid possible racing condition...
 */
 struct wlan_network *
 rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
@@ -277,7 +252,7 @@ static void _rtw_roaming(struct rtw_adap
 		pmlmepriv->assoc_by_bssid = false;
 
 		while (1) {
-			do_join_r = rtw_do_join23a(padapter);
+			do_join_r = rtw_do_join(padapter);
 			if (do_join_r == _SUCCESS)
 				break;
 			else {
@@ -309,35 +284,16 @@ void rtw23a_roaming(struct rtw_adapter *
 	spin_unlock_bh(&pmlmepriv->lock);
 }
 
-__le16 *rtw_get_capability23a_from_ie(u8 *ie)
-{
-	return (__le16 *)(ie + 8 + 2);
-}
-
-u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
-{
-	u16 val;
-
-	memcpy(&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
-
-	return le16_to_cpu(val);
-}
-
-__le16 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
-{
-	return (__le16 *)(ie + 8);
-}
-
 static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
 				    struct wlan_network *pnetwork)
 {
 	_rtw_free_network23a(pmlmepriv, pnetwork);
 }
 
-int rtw_is_same_ibss23a(struct rtw_adapter *adapter,
-			struct wlan_network *pnetwork)
+bool rtw_is_same_ibss23a(struct rtw_adapter *adapter,
+			 struct wlan_network *pnetwork)
 {
-	int ret = true;
+	int ret;
 	struct security_priv *psecuritypriv = &adapter->securitypriv;
 
 	if (psecuritypriv->dot11PrivacyAlgrthm != 0 &&
@@ -363,17 +319,16 @@ int is_same_network23a(struct wlan_bssid
 {
 	u16 s_cap, d_cap;
 
-	s_cap = get_unaligned_le16(rtw_get_capability23a_from_ie(src->IEs));
-	d_cap = get_unaligned_le16(rtw_get_capability23a_from_ie(dst->IEs));
+	s_cap = src->capability;
+	d_cap = dst->capability;
 
 	return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
 		/*	(src->DSConfig == dst->DSConfig) && */
 		ether_addr_equal(src->MacAddress, dst->MacAddress) &&
-		((!memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len))) &&
-		((s_cap & WLAN_CAPABILITY_IBSS) ==
-		 (d_cap & WLAN_CAPABILITY_IBSS)) &&
-		((s_cap & WLAN_CAPABILITY_ESS) ==
-		 (d_cap & WLAN_CAPABILITY_ESS)));
+		!memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) &&
+		(s_cap & WLAN_CAPABILITY_IBSS) ==
+		(d_cap & WLAN_CAPABILITY_IBSS) &&
+		(s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS));
 }
 
 struct wlan_network *
@@ -440,7 +395,7 @@ void update_network23a(struct wlan_bssid
 				    (u32)dst->PhyInfo.SignalQuality * 4) / 5;
 			rssi_final = src->Rssi+dst->Rssi * 4 / 5;
 		} else {
-			/* bss info not receving from the right channel, use
+			/* bss info not receiving from the right channel, use
 			   the original RX signal infos */
 			ss_final = dst->PhyInfo.SignalStrength;
 			sq_final = dst->PhyInfo.SignalQuality;
@@ -469,16 +424,11 @@ static void update_current_network(struc
 
 	if (check_fwstate(pmlmepriv, _FW_LINKED) &&
 	    is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) {
-		int bcn_size;
 		update_network23a(&pmlmepriv->cur_network.network,
 				  pnetwork,adapter, true);
 
-		bcn_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-			offsetof(struct ieee80211_mgmt, u.beacon);
-
 		rtw_update_protection23a(adapter,
-					 pmlmepriv->cur_network.network.IEs +
-					 bcn_size,
+					 pmlmepriv->cur_network.network.IEs,
 					 pmlmepriv->cur_network.network.IELength);
 	}
 }
@@ -488,8 +438,8 @@ static void update_current_network(struc
 Caller must hold pmlmepriv->lock first.
 
 */
-void rtw_update_scanned_network23a(struct rtw_adapter *adapter,
-				   struct wlan_bssid_ex *target)
+static void rtw_update_scanned_network(struct rtw_adapter *adapter,
+				       struct wlan_bssid_ex *target)
 {
 	struct list_head *plist, *phead;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -540,7 +490,7 @@ void rtw_update_scanned_network23a(struc
 		pnetwork->aid = 0;
 		pnetwork->join_res = 0;
 
-		/* bss info not receving from the right channel */
+		/* bss info not receiving from the right channel */
 		if (pnetwork->network.PhyInfo.SignalQuality == 101)
 			pnetwork->network.PhyInfo.SignalQuality = 0;
 	} else {
@@ -572,7 +522,7 @@ static void rtw_add_network(struct rtw_a
 			    struct wlan_bssid_ex *pnetwork)
 {
 	update_current_network(adapter, pnetwork);
-	rtw_update_scanned_network23a(adapter, pnetwork);
+	rtw_update_scanned_network(adapter, pnetwork);
 }
 
 /* select the desired network based on the capability of the (i)bss. */
@@ -588,19 +538,16 @@ static int rtw_is_desired_network(struct
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	u32 desired_encmode;
 	u32 privacy;
-
-	/* u8 wps_ie[512]; */
-	uint wps_ielen;
-
 	int bselected = true;
 
 	desired_encmode = psecuritypriv->ndisencryptstatus;
 	privacy = pnetwork->network.Privacy;
 
 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
-		if (rtw_get_wps_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
-				      pnetwork->network.IELength -
-				      _FIXED_IE_LENGTH_, NULL, &wps_ielen))
+		if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					    WLAN_OUI_TYPE_MICROSOFT_WPA,
+					    pnetwork->network.IEs,
+					    pnetwork->network.IELength))
 			return true;
 		else
 			return false;
@@ -612,8 +559,7 @@ static int rtw_is_desired_network(struct
 	            bselected = false;
 	}
 
-	if (desired_encmode != Ndis802_11EncryptionDisabled &&
-	    privacy == 0) {
+	if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) {
 		DBG_8723A("desired_encmode: %d, privacy: %d\n",
 			  desired_encmode, privacy);
 		bselected = false;
@@ -640,9 +586,10 @@ void rtw_survey_event_cb23a(struct rtw_a
 {
 	u32 len;
 	struct wlan_bssid_ex *pnetwork;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct survey_event *survey = (struct survey_event *)pbuf;
 
-	pnetwork = (struct wlan_bssid_ex *)pbuf;
+	pnetwork = survey->bss;
 
 	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
 		 ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
@@ -665,15 +612,22 @@ void rtw_survey_event_cb23a(struct rtw_a
 				     pnetwork->MacAddress)) {
 			struct wlan_network* ibss_wlan;
 
-			memcpy(pmlmepriv->cur_network.network.IEs,
-			       pnetwork->IEs, 8);
+			pmlmepriv->cur_network.network.beacon_interval =
+				pnetwork->beacon_interval;
+			pmlmepriv->cur_network.network.capability =
+				pnetwork->capability;
+			pmlmepriv->cur_network.network.tsf = pnetwork->tsf;
 			spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 			ibss_wlan = rtw_find_network23a(
 				&pmlmepriv->scanned_queue,
 				pnetwork->MacAddress);
 			if (ibss_wlan) {
-				memcpy(ibss_wlan->network.IEs,
-				       pnetwork->IEs, 8);
+				pmlmepriv->cur_network.network.beacon_interval =
+					ibss_wlan->network.beacon_interval;
+				pmlmepriv->cur_network.network.capability =
+					ibss_wlan->network.capability;
+				pmlmepriv->cur_network.network.tsf =
+					ibss_wlan->network.tsf;
 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 				goto exit;
 			}
@@ -693,16 +647,18 @@ exit:
 
 	spin_unlock_bh(&pmlmepriv->lock);
 
+	kfree(survey->bss);
+	survey->bss = NULL;
+
 	return;
 }
 
 void
 rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
 {
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-	struct wlan_bssid_ex *pdev_network;
-	u8 *pibss;
+	int ret;
 
 	spin_lock_bh(&pmlmepriv->lock);
 
@@ -729,63 +685,17 @@ rtw_surveydone_event_callback23a(struct
 	rtw_set_signal_stat_timer(&adapter->recvpriv);
 
 	if (pmlmepriv->to_join == true) {
+		set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 		if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-			if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
-				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
-				if (rtw_select_and_join_from_scanned_queue23a(
-					    pmlmepriv) == _SUCCESS) {
-					mod_timer(&pmlmepriv->assoc_timer,
-						  jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
-				} else {
-					pdev_network = &adapter->registrypriv.dev_network;
-					pibss = adapter->registrypriv.dev_network.MacAddress;
-
-					_clr_fwstate_(pmlmepriv,
-						      _FW_UNDER_SURVEY);
-
-					RT_TRACE(_module_rtl871x_mlme_c_,
-						 _drv_err_,
-						 ("switching to adhoc "
-						  "master\n"));
-
-					memset(&pdev_network->Ssid, 0,
-					       sizeof(struct cfg80211_ssid));
-					memcpy(&pdev_network->Ssid,
-					       &pmlmepriv->assoc_ssid,
-					       sizeof(struct cfg80211_ssid));
-
-					rtw_update_registrypriv_dev_network23a(
-						adapter);
-					rtw_generate_random_ibss23a(pibss);
-
-					pmlmepriv->fw_state =
-						WIFI_ADHOC_MASTER_STATE;
-
-					if (rtw_createbss_cmd23a(adapter) !=
-					    _SUCCESS)
-					RT_TRACE(_module_rtl871x_mlme_c_,
-						 _drv_err_,
-						 ("Error =>rtw_createbss_cmd23a"
-						  " status FAIL\n"));
-
-					pmlmepriv->to_join = false;
-				}
-			}
+			ret = rtw_select_and_join_from_scanned_queue23a(
+				pmlmepriv);
+			if (ret != _SUCCESS)
+				rtw_do_join_adhoc(adapter);
 		} else {
-			int ret;
-			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 			pmlmepriv->to_join = false;
 			ret = rtw_select_and_join_from_scanned_queue23a(
 				pmlmepriv);
-			if (ret == _SUCCESS) {
-				unsigned long e;
-				e = msecs_to_jiffies(MAX_JOIN_TIMEOUT);
-				mod_timer(&pmlmepriv->assoc_timer, jiffies + e);
-			} else if (ret == 2) {/* there is no need to wait */
-				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-				rtw_indicate_connect23a(adapter);
-			} else {
+			if (ret != _SUCCESS) {
 				DBG_8723A("try_to_join, but select scanning "
 					  "queue fail, to_roaming:%d\n",
 					  adapter->mlmepriv.to_roaming);
@@ -830,9 +740,9 @@ static void free_scanqueue(struct mlme_p
 	phead = get_list_head(scan_queue);
 
 	list_for_each_safe(plist, ptemp, phead) {
-		list_del_init(plist);
 		pnetwork = container_of(plist, struct wlan_network, list);
-		kfree(pnetwork);
+		pnetwork->fixed = false;
+		_rtw_free_network23a(pmlmepriv, pnetwork);
         }
 
 	spin_unlock_bh(&scan_queue->lock);
@@ -938,7 +848,7 @@ void rtw_indicate_connect23a(struct rtw_
  */
 void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
 {
-	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
 		 ("+rtw_indicate_disconnect23a\n"));
@@ -1046,7 +956,7 @@ rtw_joinbss_update_stainfo(struct rtw_ad
 		/*	Commented by Albert 2012/07/21 */
 		/*	When doing the WPS, the wps_ie_len won't equal to 0 */
 		/*	And the Wi-Fi driver shouldn't allow the data packet
-			to be tramsmitted. */
+			to be transmitted. */
 		if (padapter->securitypriv.wps_ie_len != 0) {
 			psta->ieee8021x_blocked = true;
 			padapter->securitypriv.wps_ie_len = 0;
@@ -1054,7 +964,7 @@ rtw_joinbss_update_stainfo(struct rtw_ad
 
 		/* for A-MPDU Rx reordering buffer control for bmc_sta &
 		 * sta_info */
-		/* if A-MPDU Rx is enabled, reseting
+		/* if A-MPDU Rx is enabled, resetting
 		   rx_ordering_ctrl wstart_b(indicate_seq) to default
 		   value = 0xffff */
 		/* todo: check if AP can send A-MPDU packets */
@@ -1098,7 +1008,6 @@ rtw_joinbss_update_network23a(struct rtw
 {
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
-	int bcn_size;
 
 	DBG_8723A("%s\n", __func__);
 
@@ -1114,6 +1023,10 @@ rtw_joinbss_update_network23a(struct rtw
 	memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0],
 	       MAX_IE_SZ);
 
+	cur_network->network.capability = ptarget_wlan->network.capability;
+	cur_network->network.beacon_interval =
+		ptarget_wlan->network.beacon_interval;
+	cur_network->network.tsf = ptarget_wlan->network.tsf;
 	cur_network->aid = pnetwork->join_res;
 
 	rtw_set_signal_stat_timer(&padapter->recvpriv);
@@ -1151,11 +1064,8 @@ rtw_joinbss_update_network23a(struct rtw
 		break;
 	}
 
-	bcn_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	rtw_update_protection23a(padapter, cur_network->network.IEs +
-				 bcn_size, cur_network->network.IELength);
+	rtw_update_protection23a(padapter, cur_network->network.IEs,
+				 cur_network->network.IELength);
 
 	rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
 			     cur_network->network.IELength);
@@ -1163,7 +1073,7 @@ rtw_joinbss_update_network23a(struct rtw
 
 /*
  * Notes:
- * the fucntion could be > passive_level (the same context as Rx tasklet)
+ * the function could be > passive_level (the same context as Rx tasklet)
  * pnetwork : returns from rtw23a_joinbss_event_cb
  * ptarget_wlan: found from scanned_queue
  * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
@@ -1188,8 +1098,6 @@ void rtw_joinbss_event_prehandle23a(stru
 		 ("joinbss event call back received with res=%d\n",
 		  pnetwork->join_res));
 
-	rtw_get_encrypt_decrypt_from_registrypriv23a(adapter);
-
 	if (pmlmepriv->assoc_ssid.ssid_len == 0) {
 		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
 			 ("@@@@@   joinbss event call back  for Any SSid\n"));
@@ -1429,7 +1337,6 @@ void rtw_stadel_event_callback23a(struct
 	struct sta_info *psta;
 	struct wlan_network* pwlan;
 	struct wlan_bssid_ex *pdev_network;
-	u8 *pibss;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	struct stadel_event *pstadel = (struct stadel_event *)pbuf;
 	struct sta_priv *pstapriv = &adapter->stapriv;
@@ -1500,32 +1407,11 @@ void rtw_stadel_event_callback23a(struct
 			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 			/* re-create ibss */
 			pdev_network = &adapter->registrypriv.dev_network;
-			pibss = adapter->registrypriv.dev_network.MacAddress;
 
 			memcpy(pdev_network, &tgt_network->network,
 			       get_wlan_bssid_ex_sz(&tgt_network->network));
 
-			memset(&pdev_network->Ssid, 0,
-			       sizeof(struct cfg80211_ssid));
-			memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
-			       sizeof(struct cfg80211_ssid));
-
-			rtw_update_registrypriv_dev_network23a(adapter);
-
-			rtw_generate_random_ibss23a(pibss);
-
-			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
-			}
-
-			if (rtw_createbss_cmd23a(adapter) != _SUCCESS) {
-				RT_TRACE(_module_rtl871x_ioctl_set_c_,
-					 _drv_err_,
-					 ("***Error =>stadel_event_callback: "
-					  "rtw_createbss_cmd23a status "
-					  "FAIL***\n"));
-			}
+			rtw_do_join_adhoc(adapter);
 		}
 	}
 
@@ -1533,18 +1419,18 @@ void rtw_stadel_event_callback23a(struct
 }
 
 /*
-* rtw23a_join_to_handler - Timeout/faliure handler for CMD JoinBss
+* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss
 * @adapter: pointer to _adapter structure
 */
 void rtw23a_join_to_handler (unsigned long data)
 {
 	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	int do_join_r;
 
 	DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
 
-	if (adapter->bDriverStopped ||adapter->bSurpriseRemoved)
+	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
 		return;
 
 	spin_lock_bh(&pmlmepriv->lock);
@@ -1556,7 +1442,7 @@ void rtw23a_join_to_handler (unsigned lo
 			if (adapter->mlmepriv.to_roaming != 0) {
 				/* try another */
 				DBG_8723A("%s try another roaming\n", __func__);
-				do_join_r = rtw_do_join23a(adapter);
+				do_join_r = rtw_do_join(adapter);
 				if (do_join_r != _SUCCESS) {
 					DBG_8723A("%s roaming do_join return "
 						  "%d\n", __func__ , do_join_r);
@@ -1584,13 +1470,13 @@ void rtw23a_join_to_handler (unsigned lo
 }
 
 /*
-* rtw_scan_timeout_handler23a - Timeout/Faliure handler for CMD SiteSurvey
+* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey
 * @data: pointer to _adapter structure
 */
 void rtw_scan_timeout_handler23a(unsigned long data)
 {
 	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
 	DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name,
 		  get_fwstate(pmlmepriv));
@@ -1604,26 +1490,9 @@ void rtw_scan_timeout_handler23a(unsigne
 	rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
 }
 
-static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
-{
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-	/* auto site survey per 60sec */
-	if (pmlmepriv->scan_interval > 0) {
-		pmlmepriv->scan_interval--;
-		if (pmlmepriv->scan_interval == 0) {
-			DBG_8723A("%s\n", __func__);
-			rtw_set_802_11_bssid23a_list_scan(padapter, NULL, 0);
-			/*  30*2 sec = 60sec */
-			pmlmepriv->scan_interval = SCAN_INTERVAL;
-		}
-	}
-}
-
 void rtw_dynamic_check_timer_handler(unsigned long data)
 {
 	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct registry_priv *pregistrypriv = &adapter->registrypriv;
 
 	if (adapter->hw_init_completed == false)
 		goto out;
@@ -1637,10 +1506,6 @@ void rtw_dynamic_check_timer_handler(uns
 
 	rtw_dynamic_chk_wk_cmd23a(adapter);
 
-	if (pregistrypriv->wifi_spec == 1) {
-		/* auto site survey */
-		rtw_auto_scan_handler(adapter);
-	}
 out:
 	mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
 		  jiffies + msecs_to_jiffies(2000));
@@ -1755,32 +1620,134 @@ pmlmepriv->lock
 
 */
 
-int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
+static int rtw_do_join(struct rtw_adapter *padapter)
 {
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	int ret;
-	struct list_head *phead, *plist, *ptmp;
-	struct rtw_adapter *adapter;
+
+	pmlmepriv->cur_network.join_res = -2;
+
+	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+	pmlmepriv->to_join = true;
+
+	ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
+	if (ret == _SUCCESS) {
+		pmlmepriv->to_join = false;
+	} else {
+		if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+			/* switch to ADHOC_MASTER */
+			ret = rtw_do_join_adhoc(padapter);
+			if (ret != _SUCCESS)
+				goto exit;
+		} else {
+			/*  can't associate ; reset under-linking */
+			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+			ret = _FAIL;
+			pmlmepriv->to_join = false;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+static struct wlan_network *
+rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
+{
+	struct wlan_network *pnetwork, *candidate = NULL;
 	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
-	struct wlan_network *pnetwork;
-	struct wlan_network *candidate = NULL;
+	struct list_head *phead, *plist, *ptmp;
 
 	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 	phead = get_list_head(queue);
-	adapter = pmlmepriv->nic_hdl;
 
 	list_for_each_safe(plist, ptmp, phead) {
 		pnetwork = container_of(plist, struct wlan_network, list);
 		if (!pnetwork) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-				 ("%s return _FAIL:(pnetwork == NULL)\n",
+				 ("%s: return _FAIL:(pnetwork == NULL)\n",
 				  __func__));
-			ret = _FAIL;
 			goto exit;
 		}
 
 		rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
 	}
 
+exit:
+	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+	return candidate;
+}
+
+
+int rtw_do_join_adhoc(struct rtw_adapter *adapter)
+{
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct wlan_bssid_ex *pdev_network;
+	u8 *ibss;
+	int ret;
+
+	pdev_network = &adapter->registrypriv.dev_network;
+	ibss = adapter->registrypriv.dev_network.MacAddress;
+
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("switching to adhoc master\n"));
+
+	memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
+	       sizeof(struct cfg80211_ssid));
+
+	rtw_update_registrypriv_dev_network23a(adapter);
+	rtw_generate_random_ibss23a(ibss);
+
+	pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+
+	ret = rtw_createbss_cmd23a(adapter);
+	if (ret != _SUCCESS) {
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+			 ("Error =>rtw_createbss_cmd23a status FAIL\n"));
+	} else  {
+		pmlmepriv->to_join = false;
+	}
+
+	return ret;
+}
+
+int rtw_do_join_network(struct rtw_adapter *adapter,
+			struct wlan_network *candidate)
+{
+	int ret;
+
+	/*  check for situation of  _FW_LINKED */
+	if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
+		DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__);
+
+		rtw_disassoc_cmd23a(adapter, 0, true);
+		rtw_indicate_disconnect23a(adapter);
+		rtw_free_assoc_resources23a(adapter, 0);
+	}
+	set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING);
+
+	ret = rtw_joinbss_cmd23a(adapter, candidate);
+
+	if (ret == _SUCCESS)
+		mod_timer(&adapter->mlmepriv.assoc_timer,
+			  jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+
+	return ret;
+}
+
+int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
+{
+	struct rtw_adapter *adapter;
+	struct wlan_network *candidate = NULL;
+	int ret;
+
+	adapter = pmlmepriv->nic_hdl;
+
+	candidate = rtw_select_candidate_from_queue(pmlmepriv);
 	if (!candidate) {
 		DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
 		ret = _FAIL;
@@ -1792,21 +1759,9 @@ int rtw_select_and_join_from_scanned_que
 			  candidate->network.DSConfig);
 	}
 
-	/*  check for situation of  _FW_LINKED */
-	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
-		DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!!!\n",
-			  __func__);
-
-		rtw_disassoc_cmd23a(adapter, 0, true);
-		rtw_indicate_disconnect23a(adapter);
-		rtw_free_assoc_resources23a(adapter, 0);
-	}
-	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-	ret = rtw_joinbss_cmd23a(adapter, candidate);
+	ret = rtw_do_join_network(adapter, candidate);
 
 exit:
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
 	return ret;
 }
 
@@ -1818,7 +1773,7 @@ int rtw_set_auth23a(struct rtw_adapter *
 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
 	int res = _SUCCESS;
 
-	pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 	if (!pcmd) {
 		res = _FAIL;  /* try again */
 		goto exit;
@@ -1954,33 +1909,25 @@ exit:
 
 /* adjust IEs for rtw_joinbss_cmd23a in WMM */
 int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
-			u8 *out_ie, uint in_len, uint initial_out_len)
+			   u8 *out_ie, uint in_len, uint initial_out_len)
 {
-	unsigned int ielength = 0;
-	unsigned int i, j;
+	int ielength;
+	const u8 *p;
 
-	i = 12; /* after the fixed IE */
-	while (i < in_len) {
-		ielength = initial_out_len;
+	ielength = initial_out_len;
 
-		/* WMM element ID and OUI */
-		if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
-		    in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
-		    in_ie[i + 5] == 0x02 && i+5 < in_len) {
+	p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+				    WLAN_OUI_TYPE_MICROSOFT_WMM,
+				    in_ie, in_len);
 
-			/* Append WMM IE to the last index of out_ie */
-                        for (j = i; j < i + 9; j++) {
-				out_ie[ielength] = in_ie[j];
-				ielength++;
-                        }
-                        out_ie[initial_out_len + 1] = 0x07;
-                        out_ie[initial_out_len + 6] = 0x00;
-                        out_ie[initial_out_len + 8] = 0x00;
+	if (p && p[1]) {
+		memcpy(out_ie + initial_out_len, p, 9);
 
-			break;
-		}
+		out_ie[initial_out_len + 1] = 7;
+		out_ie[initial_out_len + 6] = 0;
+		out_ie[initial_out_len + 8] = 0;
 
-		i += (in_ie[i + 1] + 2); /*  to the next IE element */
+		ielength += 9;
 	}
 
 	return ielength;
@@ -2037,7 +1984,7 @@ static int rtw_append_pmkid(struct rtw_a
 {
 	struct security_priv *psecuritypriv = &Adapter->securitypriv;
 
-	if (ie[13] <= 20) {
+	if (ie[1] <= 20) {
 		/*  The RSN IE didn't include the PMK ID,
 		    append the PMK information */
 			ie[ie_len] = 1;
@@ -2048,7 +1995,7 @@ static int rtw_append_pmkid(struct rtw_a
 			       &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
 
 			ie_len += 16;
-			ie[13] += 18;/* PMKID length = 2+16 */
+			ie[1] += 18;/* PMKID length = 2+16 */
 	}
 	return ie_len;
 }
@@ -2068,15 +2015,13 @@ int rtw_restruct_sec_ie23a(struct rtw_ad
 		 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
 		  "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
 
-	/* copy fixed ie only */
-	memcpy(out_ie, in_ie, 12);
-	ielength = 12;
+	ielength = 0;
 	if (ndisauthmode == Ndis802_11AuthModeWPA ||
 	    ndisauthmode == Ndis802_11AuthModeWPAPSK)
 		authmode = WLAN_EID_VENDOR_SPECIFIC;
 	if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
 	    ndisauthmode == Ndis802_11AuthModeWPA2PSK)
-		authmode = _WPA2_IE_ID_;
+		authmode = WLAN_EID_RSN;
 
 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
 		memcpy(out_ie + ielength, psecuritypriv->wps_ie,
@@ -2084,7 +2029,7 @@ int rtw_restruct_sec_ie23a(struct rtw_ad
 
 		ielength += psecuritypriv->wps_ie_len;
 	} else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
-		   authmode == _WPA2_IE_ID_) {
+		   authmode == WLAN_EID_RSN) {
 		/* copy RSN or SSN */
 		memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
 		       psecuritypriv->supplicant_ie[1] + 2);
@@ -2095,7 +2040,7 @@ int rtw_restruct_sec_ie23a(struct rtw_ad
 	if (iEntry < 0)
 		return ielength;
 	else {
-		if (authmode == _WPA2_IE_ID_)
+		if (authmode == WLAN_EID_RSN)
 			ielength = rtw_append_pmkid(adapter, iEntry,
 						    out_ie, ielength);
 	}
@@ -2115,7 +2060,7 @@ void rtw_init_registrypriv_dev_network23
 	memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
 	       sizeof(struct cfg80211_ssid));
 
-	pdev_network->BeaconPeriod = 100;
+	pdev_network->beacon_interval = 100;
 }
 
 void rtw_update_registrypriv_dev_network23a(struct rtw_adapter* adapter)
@@ -2157,12 +2102,7 @@ void rtw_update_registrypriv_dev_network
 	/* pdev_network->IELength = cpu_to_le32(sz); */
 }
 
-void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter* adapter)
-{
-
-}
-
-/* the fucntion is at passive_level */
+/* the function is at passive_level */
 void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
 {
 	u8 threshold;
@@ -2191,30 +2131,31 @@ void rtw_joinbss_reset23a(struct rtw_ada
 	rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
 }
 
-/* the fucntion is >= passive_level */
-unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
-				      u8 *out_ie, uint in_len, uint *pout_len)
+/* the function is >= passive_level */
+bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
+			      u8 *out_ie, uint in_len, uint *pout_len)
 {
 	u32 out_len;
 	int max_rx_ampdu_factor;
 	unsigned char *pframe;
 	const u8 *p;
 	struct ieee80211_ht_cap ht_capie;
-	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+	u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
 
 	phtpriv->ht_option = false;
 
-	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie + 12, in_len -12);
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len);
 
 	if (p && p[1] > 0) {
 		u32 rx_packet_offset, max_recvbuf_sz;
 		if (pmlmepriv->qos_option == 0) {
 			out_len = *pout_len;
 			pframe = rtw_set_ie23a(out_ie + out_len,
-					    WLAN_EID_VENDOR_SPECIFIC,
-					    _WMM_IE_Length_, WMM_IE, pout_len);
+					       WLAN_EID_VENDOR_SPECIFIC,
+					       sizeof(WMM_IE), WMM_IE,
+					       pout_len);
 
 			pmlmepriv->qos_option = 1;
 		}
@@ -2250,9 +2191,8 @@ unsigned int rtw_restructure_ht_ie23a(st
 
 		phtpriv->ht_option = true;
 
-		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie + 12,
-				     in_len -12);
-		if (p && (p[1] == sizeof(struct ieee80211_ht_addt_info))) {
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len);
+		if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) {
 			out_len = *pout_len;
 			pframe = rtw_set_ie23a(out_ie + out_len,
 					       WLAN_EID_HT_OPERATION,
@@ -2263,19 +2203,18 @@ unsigned int rtw_restructure_ht_ie23a(st
 	return phtpriv->ht_option;
 }
 
-/* the fucntion is > passive_level (in critical_section) */
+/* the function is > passive_level (in critical_section) */
 void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
 {
 	u8 max_ampdu_sz;
 	const u8 *p;
 	struct ieee80211_ht_cap *pht_capie;
-	struct ieee80211_ht_addt_info *pht_addtinfo;
+	struct ieee80211_ht_operation *pht_addtinfo;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	int bcn_fixed_size;
 
 	if (!phtpriv->ht_option)
 		return;
@@ -2285,16 +2224,8 @@ void rtw_update_ht_cap23a(struct rtw_ada
 
 	DBG_8723A("+rtw_update_ht_cap23a()\n");
 
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	/* Adjust pie + ie_len for our searches */
-	pie += bcn_fixed_size;
-	ie_len -= bcn_fixed_size;
-
 	/* maybe needs check if ap supports rx ampdu. */
-	if (phtpriv->ampdu_enable == false &&
-	    pregistrypriv->ampdu_enable == 1) {
+	if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) {
 		if (pregistrypriv->wifi_spec == 1)
 			phtpriv->ampdu_enable = false;
 		else
@@ -2317,35 +2248,38 @@ void rtw_update_ht_cap23a(struct rtw_ada
 
 	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
 	if (p && p[1] > 0) {
-		pht_addtinfo = (struct ieee80211_ht_addt_info *)(p + 2);
+		pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2);
 		/* todo: */
 	}
 
 	/* update cur_bwmode & cur_ch_offset */
 	if (pregistrypriv->cbw40_enable &&
-	    pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1) &&
-	    pmlmeinfo->HT_info.infos[0] & BIT(2)) {
+	    pmlmeinfo->ht_cap.cap_info &
+	    cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
+	    pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) {
 		int i;
 		u8 rf_type;
 
 		rf_type = rtl8723a_get_rf_type(padapter);
 
 		/* update the MCS rates */
-		for (i = 0; i < 16; i++) {
+		for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
 			if (rf_type == RF_1T1R || rf_type == RF_1T2R)
-				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
+				pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
+					MCS_rate_1R23A[i];
 			else
-				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
+				pmlmeinfo->ht_cap.mcs.rx_mask[i] &=
+					MCS_rate_2R23A[i];
 		}
-		/* switch to the 40M Hz mode accoring to the AP */
+		/* switch to the 40M Hz mode according to the AP */
 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
-		switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
-		{
-		case HT_EXTCHNL_OFFSET_UPPER:
+		switch (pmlmeinfo->HT_info.ht_param &
+			IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 			break;
 
-		case HT_EXTCHNL_OFFSET_LOWER:
+		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
 			break;
 
@@ -2359,15 +2293,18 @@ void rtw_update_ht_cap23a(struct rtw_ada
 	/*  */
 	/*  Config SM Power Save setting */
 	/*  */
-	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &
-			    0x0C) >> 2;
+	pmlmeinfo->SM_PS =
+		(le16_to_cpu(pmlmeinfo->ht_cap.cap_info) &
+		 IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT;
 	if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
 		DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
 
 	/*  */
 	/*  Config current HT Protection mode. */
 	/*  */
-	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+	pmlmeinfo->HT_protection =
+		le16_to_cpu(pmlmeinfo->HT_info.operation_mode) &
+		IEEE80211_HT_OP_MODE_PROTECTION;
 }
 
 void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
@@ -2405,7 +2342,7 @@ void rtw_issue_addbareq_cmd23a(struct rt
 
 	phtpriv = &psta->htpriv;
 
-	if (phtpriv->ht_option == true && phtpriv->ampdu_enable == true) {
+	if (phtpriv->ht_option && phtpriv->ampdu_enable) {
 		issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
 		issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_mlme_ext.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_mlme_ext.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_mlme_ext.c	2014-09-28 17:29:07.000000000 -0400
@@ -61,6 +61,8 @@ static void start_clnt_assoc(struct rtw_
 static void start_clnt_auth(struct rtw_adapter *padapter);
 static void start_clnt_join(struct rtw_adapter *padapter);
 static void start_create_ibss(struct rtw_adapter *padapter);
+static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
+					      struct recv_frame *precv_frame);
 
 #ifdef CONFIG_8723AU_AP_MODE
 static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
@@ -107,12 +109,12 @@ static u8	null_addr[ETH_ALEN]= {0, 0, 0,
 OUI definitions for the vendor specific IE
 ***************************************************/
 unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
-unsigned char	WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
-unsigned char	P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
-unsigned char	WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
+unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
+unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
+unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
 
-unsigned char	WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
-unsigned char	WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
 
 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
 
@@ -120,49 +122,87 @@ static unsigned char REALTEK_96B_IE[] =
 MCS rate definitions
 *********************************************************/
 unsigned char MCS_rate_2R23A[16] = {
-	0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+	0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 unsigned char MCS_rate_1R23A[16] = {
-	0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+	0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 
 /********************************************************
 ChannelPlan definitions
 *********************************************************/
 
-static struct rt_channel_plan_2g	RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},		/*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},		/*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},			/*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},	/*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
-	{{10, 11, 12, 13}, 4},					/*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
-	{{}, 0},									/*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
+static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
+	/*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
+	/*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+	/*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
+	{{10, 11, 12, 13}, 4},
+	/*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
+	{{}, 0},
 };
 
-static struct rt_channel_plan_5g	RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
-	{{}, 0},																					/*  0x00, RT_CHANNEL_DOMAIN_5G_NULL */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},						/*  0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},	/*  0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},			/*  0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},	/*  0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
-	{{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},														/*  0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},											/*  0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},												/*  0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
-	{{149, 153, 157, 161, 165}, 5},																	/*  0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
-	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},																/*  0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20},					/*  0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20},					/*  0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},						/*  0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
-	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},																/*  0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
-	{{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},											/*  0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
-	{{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15},								/*  0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
-	{{56, 60, 64, 149, 153, 157, 161, 165}, 8},															/*  0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
+static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
+	/*  0x00, RT_CHANNEL_DOMAIN_5G_NULL */
+	{{}, 0},
+	/*  0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 128, 132, 136, 140}, 19},
+	/*  0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
+	/*  0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
+	/*  0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
+	/*  0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
+	{{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
+	/*  0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
+	/*  0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
+	/*  0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
+	{{149, 153, 157, 161, 165}, 5},
+	/*  0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
+	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},
+	/*  0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 136, 140, 149, 153, 157, 161, 165}, 20},
+	/*  0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 149, 153, 157, 161, 165}, 20},
+	/*  0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 120, 124, 128, 132, 136, 140}, 19},
+	/*  0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
+	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},
+	/*  0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
+	{{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
+	/*  0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
+	{{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
+	  153, 157, 161, 165}, 15},
+	/*  0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
+	{{56, 60, 64, 149, 153, 157, 161, 165}, 8},
 
-	/*  Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
-	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},				/*  0x11, RT_CHANNEL_DOMAIN_5G_FCC */
-	{{36, 40, 44, 48}, 4},																			/*  0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
-	{{36, 40, 44, 48, 149, 153, 157, 161}, 8},																/*  0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
+	/*  Driver self defined for old channel plan Compatible,
+	    Remember to modify if have new channel plan definition ===== */
+	/*  0x11, RT_CHANNEL_DOMAIN_5G_FCC */
+	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
+	  116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
+	/*  0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
+	{{36, 40, 44, 48}, 4},
+	/*  0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
+	{{36, 40, 44, 48, 149, 153, 157, 161}, 8},
 };
 
-static struct rt_channel_plan_map	RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
+static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
 	/*  0x00 ~ 0x1F , Old Define ===== */
 	{0x02, 0x11},	/* 0x00, RT_CHANNEL_DOMAIN_FCC */
 	{0x02, 0x0A},	/* 0x01, RT_CHANNEL_DOMAIN_IC */
@@ -233,7 +273,8 @@ static struct rt_channel_plan_map	RTW_Ch
 	{0x03, 0x00},	/* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 };
 
-static struct rt_channel_plan_map	RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
+static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
+{0x03, 0x02}; /* use the conbination for max channel numbers */
 
 static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
 {
@@ -250,8 +291,7 @@ static struct fwevent wlanevents[] =
 	{0, NULL},
 	{0, NULL},
 	{0, &rtw_survey_event_cb23a},		/*8*/
-	{sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},	/*9*/
-
+	{sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
 	{0, &rtw23a_joinbss_event_cb},		/*10*/
 	{sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
 	{sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
@@ -309,7 +349,7 @@ Following are the initialization functio
 
 int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
 {
-	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
 	set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
 			      pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
@@ -318,7 +358,7 @@ int init_hw_mlme_ext23a(struct rtw_adapt
 
 static void init_mlme_ext_priv23a_value(struct rtw_adapter* padapter)
 {
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	unsigned char	mixed_datarate[NumRates] = {
 		_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
@@ -353,7 +393,7 @@ static void init_mlme_ext_priv23a_value(
 	pmlmeext->sitesurvey_res.bss_cnt = 0;
 	pmlmeext->scan_abort = false;
 
-	pmlmeinfo->state = WIFI_FW_NULL_STATE;
+	pmlmeinfo->state = MSR_NOLINK;
 	pmlmeinfo->reauth_count = 0;
 	pmlmeinfo->reassoc_count = 0;
 	pmlmeinfo->link_count = 0;
@@ -391,8 +431,8 @@ static int has_channel(struct rt_channel
 static void init_channel_list(struct rtw_adapter *padapter,
 			      struct rt_channel_info *channel_set,
 			      u8 chanset_size,
-			      struct p2p_channels *channel_list) {
-
+			      struct p2p_channels *channel_list)
+{
 	struct p2p_oper_class_map op_class[] = {
 		{ IEEE80211G,  81,   1,  13,  1, BW20 },
 		{ IEEE80211G,  82,  14,  14,  1, BW20 },
@@ -526,7 +566,7 @@ static u8 init_channel_set(struct rtw_ad
 
 int init_mlme_ext_priv23a(struct rtw_adapter* padapter)
 {
-	int	res = _SUCCESS;
+	int res = _SUCCESS;
 	struct registry_priv* pregistrypriv = &padapter->registrypriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -751,7 +791,6 @@ OnBeacon23a(struct rtw_adapter *padapter
 	struct sta_priv	*pstapriv = &padapter->stapriv;
 	struct sk_buff *skb = precv_frame->pkt;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
-	u8 *pframe = skb->data;
 	int pkt_len = skb->len;
 	struct wlan_bssid_ex *pbss;
 	int ret = _SUCCESS;
@@ -788,16 +827,11 @@ OnBeacon23a(struct rtw_adapter *padapter
 	if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 		/* we should update current network before auth,
 		   or some IE is wrong */
-		pbss = (struct wlan_bssid_ex *)
-			kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+		pbss = collect_bss_info(padapter, precv_frame);
 		if (pbss) {
-			if (collect_bss_info23a(padapter, precv_frame, pbss) ==
-			    _SUCCESS) {
-				update_network23a(
-					&pmlmepriv->cur_network.network, pbss,
-					padapter, true);
-				rtw_get_bcn_info23a(&pmlmepriv->cur_network);
-			}
+			update_network23a(&pmlmepriv->cur_network.network, pbss,
+					  padapter, true);
+			rtw_get_bcn_info23a(&pmlmepriv->cur_network);
 			kfree(pbss);
 		}
 
@@ -815,12 +849,12 @@ OnBeacon23a(struct rtw_adapter *padapter
 		return _SUCCESS;
 	}
 
-	if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) &&
+	if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
 	    (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
 		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
 		if (psta) {
 			ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
-			if (!ret) {
+			if (ret != _SUCCESS) {
 				DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
 						"disconnect now\n");
 				receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
@@ -831,11 +865,11 @@ OnBeacon23a(struct rtw_adapter *padapter
 			   the number of the beacon received */
 			if ((sta_rx_pkts(psta) & 0xf) == 0) {
 				/* DBG_8723A("update_bcn_info\n"); */
-				update_beacon23a_info(padapter, pframe,
+				update_beacon23a_info(padapter, mgmt,
 						      pkt_len, psta);
 			}
 		}
-	} else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+	} else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
 		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
 		if (psta) {
 			/* update WMM, ERP in the beacon */
@@ -843,7 +877,7 @@ OnBeacon23a(struct rtw_adapter *padapter
 			   number of the beacon received */
 			if ((sta_rx_pkts(psta) & 0xf) == 0) {
 				/* DBG_8723A("update_bcn_info\n"); */
-				update_beacon23a_info(padapter, pframe,
+				update_beacon23a_info(padapter, mgmt,
 						      pkt_len, psta);
 			}
 		} else {
@@ -891,7 +925,7 @@ OnAuth23a(struct rtw_adapter *padapter,
 	u16 auth_mode, seq, algorithm;
 	int status, len = skb->len;
 
-	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state & 0x03) != MSR_AP)
 		return _FAIL;
 
 	DBG_8723A("+OnAuth23a\n");
@@ -1053,7 +1087,7 @@ auth_fail:
 	pstat = &stat;
 	memset((char *)pstat, '\0', sizeof(stat));
 	pstat->auth_seq = 2;
-	memcpy(pstat->hwaddr, sa, 6);
+	ether_addr_copy(pstat->hwaddr, sa);
 
 	issue_auth(padapter, pstat, (unsigned short)status);
 
@@ -1170,11 +1204,11 @@ static int rtw_validate_vendor_specific_
 		/* Microsoft/Wi-Fi information elements are further typed and
 		 * subtyped */
 		switch (pos[3]) {
-		case 1:
+		case WLAN_OUI_TYPE_MICROSOFT_WPA:
 			/* Microsoft OUI (00:50:F2) with OUI Type 1:
 			 * real WPA information element */
 			break;
-		case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+		case WLAN_OUI_TYPE_MICROSOFT_WMM:
 			if (elen < 5) {
 				DBG_8723A("short WME information element "
 					  "ignored (len =%i)\n", elen);
@@ -1193,7 +1227,7 @@ static int rtw_validate_vendor_specific_
 				return -EINVAL;
 			}
 			break;
-		case 4:
+		case WLAN_OUI_TYPE_MICROSOFT_WPS:
 			/* Wi-Fi Protected Setup (WPS) IE */
 			break;
 		default:
@@ -1255,6 +1289,7 @@ static int rtw_validate_frame_ies(const
 		case WLAN_EID_CHALLENGE:
 		case WLAN_EID_ERP_INFO:
 		case WLAN_EID_EXT_SUPP_RATES:
+			break;
 		case WLAN_EID_VENDOR_SPECIFIC:
 			if (rtw_validate_vendor_specific_ies(pos, elen))
 				unknown++;
@@ -1292,7 +1327,6 @@ OnAssocReq23a(struct rtw_adapter *padapt
 	u16 capab_info, listen_interval;
 	struct sta_info	*pstat;
 	unsigned char reassoc;
-	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
 	int i, wpa_ie_len, left;
 	unsigned char supportRate[16];
 	int supportRateNum;
@@ -1310,7 +1344,7 @@ OnAssocReq23a(struct rtw_adapter *padapt
 	uint pkt_len = skb->len;
 	int r;
 
-	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state & 0x03) != MSR_AP)
 		return _FAIL;
 
 	left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
@@ -1500,31 +1534,6 @@ OnAssocReq23a(struct rtw_adapter *padapt
 				   "Association Request - possible WPS use\n");
 			pstat->flags |= WLAN_STA_MAYBE_WPS;
 		}
-
-		/*  AP support WPA/RSN, and sta is going to do WPS, but AP
-		    is not ready */
-		/*  that the selected registrar of AP is _FLASE */
-		if (psecuritypriv->wpa_psk > 0 &&
-		    pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS)) {
-			if (pmlmepriv->wps_beacon_ie) {
-				u8 selected_registrar = 0;
-
-				rtw_get_wps_attr_content23a(
-					pmlmepriv->wps_beacon_ie,
-					pmlmepriv->wps_beacon_ie_len,
-					WPS_ATTR_SELECTED_REGISTRAR,
-					&selected_registrar, NULL);
-
-				if (!selected_registrar) {
-					DBG_8723A("selected_registrar is false,"
-						  "or AP is not ready to do "
-						  "WPS\n");
-
-					status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-					goto OnAssocReq23aFail;
-				}
-			}
-		}
 	} else {
 		int copy_len;
 
@@ -1567,47 +1576,46 @@ OnAssocReq23a(struct rtw_adapter *padapt
 
 		for (;;) {
 			left = end - p;
-			p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p, left);
+			p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+						    WLAN_OUI_TYPE_MICROSOFT_WMM,
+						    p, left);
 			if (p) {
-				if (!memcmp(p + 2, WMM_IE, 6)) {
-					pstat->flags |= WLAN_STA_WME;
-
-					pstat->qos_option = 1;
-					pstat->qos_info = *(p + 8);
+				pstat->flags |= WLAN_STA_WME;
 
-					pstat->max_sp_len =
-						(pstat->qos_info >> 5) & 0x3;
+				pstat->qos_option = 1;
+				pstat->qos_info = *(p + 8);
 
-					if ((pstat->qos_info & 0xf) != 0xf)
-						pstat->has_legacy_ac = true;
-					else
-						pstat->has_legacy_ac = false;
+				pstat->max_sp_len =
+					(pstat->qos_info >> 5) & 0x3;
 
-					if (pstat->qos_info & 0xf) {
-						if (pstat->qos_info & BIT(0))
-							pstat->uapsd_vo = BIT(0)|BIT(1);
-						else
-							pstat->uapsd_vo = 0;
+				if ((pstat->qos_info & 0xf) != 0xf)
+					pstat->has_legacy_ac = true;
+				else
+					pstat->has_legacy_ac = false;
 
-						if (pstat->qos_info & BIT(1))
-							pstat->uapsd_vi = BIT(0)|BIT(1);
-						else
-							pstat->uapsd_vi = 0;
+				if (pstat->qos_info & 0xf) {
+					if (pstat->qos_info & BIT(0))
+						pstat->uapsd_vo = BIT(0)|BIT(1);
+					else
+						pstat->uapsd_vo = 0;
 
-						if (pstat->qos_info & BIT(2))
-							pstat->uapsd_bk = BIT(0)|BIT(1);
-						else
-							pstat->uapsd_bk = 0;
+					if (pstat->qos_info & BIT(1))
+						pstat->uapsd_vi = BIT(0)|BIT(1);
+					else
+						pstat->uapsd_vi = 0;
 
-						if (pstat->qos_info & BIT(3))
-							pstat->uapsd_be = BIT(0)|BIT(1);
-						else
-							pstat->uapsd_be = 0;
+					if (pstat->qos_info & BIT(2))
+						pstat->uapsd_bk = BIT(0)|BIT(1);
+					else
+						pstat->uapsd_bk = 0;
 
-					}
+					if (pstat->qos_info & BIT(3))
+						pstat->uapsd_be = BIT(0)|BIT(1);
+					else
+						pstat->uapsd_be = 0;
 
-					break;
 				}
+				break;
 			} else {
 				break;
 			}
@@ -1629,7 +1637,7 @@ OnAssocReq23a(struct rtw_adapter *padapt
 	} else
 		pstat->flags &= ~WLAN_STA_HT;
 
-	if (pmlmepriv->htpriv.ht_option == false && pstat->flags & WLAN_STA_HT){
+	if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto OnAssocReq23aFail;
 	}
@@ -1768,11 +1776,12 @@ OnAssocRsp23a(struct rtw_adapter *padapt
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
 	struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
-	int res, i;
+	int res;
 	unsigned short status;
-	u8 *p;
+	const u8 *p, *pie;
 	u8 *pframe = skb->data;
 	int pkt_len = skb->len;
+	int pielen;
 
 	DBG_8723A("%s\n", __func__);
 
@@ -1792,7 +1801,7 @@ OnAssocRsp23a(struct rtw_adapter *padapt
 	status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
 	if (status > 0)	{
 		DBG_8723A("assoc reject, status code: %d\n", status);
-		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		pmlmeinfo->state = MSR_NOLINK;
 		res = -4;
 		goto report_assoc_result;
 	}
@@ -1806,38 +1815,45 @@ OnAssocRsp23a(struct rtw_adapter *padapt
 	/* AID */
 	res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
 
-	/* following are moved to join event callback function */
-	/* to handle HT, WMM, rate adaptive, update MAC reg */
-	/* for not to handle the synchronous IO in the tasklet */
-	for (i = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
-	     i < pkt_len;) {
-		p = pframe + i;
-
-		switch (p[0])
-		{
-		case WLAN_EID_VENDOR_SPECIFIC:
-			if (!memcmp(p + 2, WMM_PARA_OUI23A, 6))/* WMM */
-				WMM_param_handler23a(padapter, p);
-			break;
+	pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+	pielen = pkt_len -
+		offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
 
-		case WLAN_EID_HT_CAPABILITY:	/* HT caps */
-			HT_caps_handler23a(padapter, p);
-			break;
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+			     pmgmt->u.assoc_resp.variable, pielen);
+	if (p && p[1])
+		HT_caps_handler23a(padapter, p);
 
-		case WLAN_EID_HT_OPERATION:	/* HT info */
-			HT_info_handler23a(padapter, p);
-			break;
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+			     pmgmt->u.assoc_resp.variable, pielen);
+	if (p && p[1])
+		HT_info_handler23a(padapter, p);
 
-		case WLAN_EID_ERP_INFO:
-			ERP_IE_handler23a(padapter, p);
+	p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
+			     pmgmt->u.assoc_resp.variable, pielen);
+	if (p && p[1])
+		ERP_IE_handler23a(padapter, p);
 
-		default:
+	pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+	while (true) {
+		p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					    WLAN_OUI_TYPE_MICROSOFT_WMM,
+					    pie, pframe + pkt_len - pie);
+		if (!p)
 			break;
-		}
 
-		i += (p[1] + 2);
+		pie = p + p[1] + 2;
+		/* if this IE is too short, try the next */
+		if (p[1] <= 4)
+			continue;
+		/* if this IE is WMM params, we found what we wanted */
+		if (p[6] == 1)
+			break;
 	}
 
+	if (p && p[1])
+		WMM_param_handler23a(padapter, p);
+
 	pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
 	pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
 
@@ -1920,7 +1936,7 @@ OnDeAuth23a(struct rtw_adapter *padapter
 static int
 OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
-	unsigned short	reason;
+	unsigned short reason;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -2017,7 +2033,7 @@ static int OnAction23a_back23a(struct rt
 
 	DBG_8723A("%s\n", __func__);
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) != MSR_AP)
 		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
 			return _SUCCESS;
 
@@ -2090,136 +2106,32 @@ static int OnAction23a_back23a(struct rt
 	return _SUCCESS;
 }
 
-static int rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
-{
-	struct rtw_adapter *adapter = recv_frame->adapter;
-	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
-	struct sk_buff *skb = recv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 seq_ctrl;
-
-	seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
-		(recv_frame->attrib.frag_num & 0xf);
-
-	if (ieee80211_has_retry(hdr->frame_control)) {
-		if (token >= 0) {
-			if ((seq_ctrl == mlmeext->action_public_rxseq) &&
-			    (token == mlmeext->action_public_dialog_token)) {
-				DBG_8723A("%s(%s): seq_ctrl = 0x%x, "
-					  "rxseq = 0x%x, token:%d\n", __func__,
-					  adapter->pnetdev->name, seq_ctrl,
-					  mlmeext->action_public_rxseq, token);
-				return _FAIL;
-			}
-		} else {
-			if (seq_ctrl == mlmeext->action_public_rxseq) {
-				DBG_8723A("%s(%s): seq_ctrl = 0x%x, "
-					  "rxseq = 0x%x\n", __func__,
-					  adapter->pnetdev->name, seq_ctrl,
-					  mlmeext->action_public_rxseq);
-				return _FAIL;
-			}
-		}
-	}
-
-	mlmeext->action_public_rxseq = seq_ctrl;
-
-	if (token >= 0)
-		mlmeext->action_public_dialog_token = token;
-
-	return _SUCCESS;
-}
-
-static int on_action_public23a_p2p(struct recv_frame *precv_frame)
-{
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	u8 *frame_body;
-	u8 dialogToken = 0;
-
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[7];
-
-	if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
-		return _FAIL;
-
-	return _SUCCESS;
-}
-
-static int on_action_public23a_vendor(struct recv_frame *precv_frame)
-{
-	unsigned int ret = _FAIL;
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-
-	if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
-		ret = on_action_public23a_p2p(precv_frame);
-	}
-
-	return ret;
-}
-
-static unsigned int
-on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
-{
-	unsigned int ret = _FAIL;
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	uint frame_len = skb->len;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-	u8 token;
-	struct rtw_adapter *adapter = precv_frame->adapter;
-	int cnt = 0;
-	char msg[64];
-
-	token = frame_body[2];
-
-	if (rtw_action_public_decache(precv_frame, token) == _FAIL)
-		goto exit;
-
-	cnt += sprintf((msg+cnt), "%s(token:%u)",
-		       action_public_str23a(action), token);
-	rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
-
-	ret = _SUCCESS;
-
-exit:
-	return ret;
-}
-
 static int on_action_public23a(struct rtw_adapter *padapter,
 			       struct recv_frame *precv_frame)
 {
-	int ret = _FAIL;
 	struct sk_buff *skb = precv_frame->pkt;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	u8 *pframe = skb->data;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-	u8 category, action;
+	int freq, channel;
 
 	/* check RA matches or not */
 	if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
-		goto exit;
+		return _FAIL;
 
-	category = frame_body[0];
-	if (category != WLAN_CATEGORY_PUBLIC)
-		goto exit;
+	channel = rtw_get_oper_ch23a(padapter);
 
-	action = frame_body[1];
-	switch (action) {
-	case ACT_PUBLIC_VENDOR:
-		ret = on_action_public23a_vendor(precv_frame);
-		break;
-	default:
-		ret = on_action_public23a_default(precv_frame, action);
-		break;
-	}
+	if (channel <= RTW_CH_MAX_2G_CHANNEL)
+		freq = ieee80211_channel_to_frequency(channel,
+						      IEEE80211_BAND_2GHZ);
+	else
+		freq = ieee80211_channel_to_frequency(channel,
+						      IEEE80211_BAND_5GHZ);
 
-exit:
-	return ret;
+	if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
+			     skb->len, 0, GFP_ATOMIC))
+		return _SUCCESS;
+
+	return _FAIL;
 }
 
 static int
@@ -2301,7 +2213,7 @@ exit:
 
 /****************************************************************************
 
-Following are some TX fuctions for WiFi MLME
+Following are some TX functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -2452,7 +2364,7 @@ void issue_beacon23a(struct rtw_adapter
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	unsigned int rate_len;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -2460,8 +2372,7 @@ void issue_beacon23a(struct rtw_adapter
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	u8 *wps_ie;
-	u32 wps_ielen;
+	const u8 *wps_ie;
 	u8 sr = 0;
 	int len_diff;
 
@@ -2484,39 +2395,48 @@ void issue_beacon23a(struct rtw_adapter
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_BEACON);
-	pwlanhdr->seq_ctrl = 0;
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
+	mgmt->seq_ctrl = 0;
 
-	ether_addr_copy(pwlanhdr->addr1, bc_addr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(cur_network));
+	ether_addr_copy(mgmt->da, bc_addr);
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+	/* timestamp will be inserted by hardware */
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+	put_unaligned_le16(cur_network->beacon_interval,
+			   &mgmt->u.beacon.beacon_int);
+
+	put_unaligned_le16(cur_network->capability,
+			   &mgmt->u.beacon.capab_info);
+
+	pframe = mgmt->u.beacon.variable;
+	pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+
+	if ((pmlmeinfo->state & 0x03) == MSR_AP) {
+		u8 *iebuf;
+		int buflen;
 		/* DBG_8723A("ie len =%d\n", cur_network->IELength); */
 		memcpy(pframe, cur_network->IEs, cur_network->IELength);
-		len_diff = update_hidden_ssid(pframe + _BEACON_IE_OFFSET_,
-					      cur_network->IELength -
-					      _BEACON_IE_OFFSET_,
+		len_diff = update_hidden_ssid(pframe, cur_network->IELength,
 					      pmlmeinfo->hidden_ssid_mode);
 		pframe += (cur_network->IELength+len_diff);
 		pattrib->pktlen += (cur_network->IELength+len_diff);
 
-		wps_ie = rtw_get_wps_ie23a(pmgntframe->buf_addr + TXDESC_OFFSET+
-					   sizeof (struct ieee80211_hdr_3addr) +
-					   _BEACON_IE_OFFSET_, pattrib->pktlen -
-					   sizeof (struct ieee80211_hdr_3addr) -
-					   _BEACON_IE_OFFSET_, NULL,
-					   &wps_ielen);
-		if (wps_ie && wps_ielen > 0) {
-			rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
+		iebuf = mgmt->u.beacon.variable;
+		buflen = pattrib->pktlen -
+			offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+						 WLAN_OUI_TYPE_MICROSOFT_WPS,
+						 iebuf, buflen);
+
+		if (wps_ie && wps_ie[1] > 0) {
+			rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
 						    WPS_ATTR_SELECTED_REGISTRAR,
-						    (u8*)&sr, NULL);
+						    (u8*)&sr);
 		}
 		if (sr != 0)
 			set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
@@ -2526,28 +2446,6 @@ void issue_beacon23a(struct rtw_adapter
 		goto _issue_bcn;
 	}
 
-	/* below for ad-hoc mode */
-
-	/* timestamp will be inserted by hardware */
-	pframe += 8;
-	pattrib->pktlen += 8;
-
-	/*  beacon interval: 2 bytes */
-
-	memcpy(pframe, (unsigned char *)
-	       rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
-
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-	/*  capability info: 2 bytes */
-
-	memcpy(pframe, (unsigned char *)
-	       rtw_get_capability23a_from_ie(cur_network->IEs), 2);
-
-	pframe += 2;
-	pattrib->pktlen += 2;
-
 	/*  SSID */
 	pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
 			       cur_network->Ssid.ssid_len,
@@ -2563,7 +2461,7 @@ void issue_beacon23a(struct rtw_adapter
 	pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
 			       &cur_network->DSConfig, &pattrib->pktlen);
 
-	/* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
+	/* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
 	{
 		u8 erpinfo = 0;
 		u32 ATIMWindow;
@@ -2616,18 +2514,15 @@ static void issue_probersp(struct rtw_ad
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	unsigned char *mac, *bssid;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 #ifdef CONFIG_8723AU_AP_MODE
-	u8 *pwps_ie;
-	uint wps_ielen;
+	const u8 *pwps_ie;
 	u8 *ssid_ie;
 	int ssid_ielen;
 	int ssid_ielen_diff;
 	u8 buf[MAX_IE_SZ];
-	u8 *ies;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 #endif
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -2636,6 +2531,9 @@ static void issue_probersp(struct rtw_ad
 
 	/* DBG_8723A("%s\n", __func__); */
 
+	if (cur_network->IELength > MAX_IE_SZ)
+		return;
+
 	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
 	if (!pmgntframe) {
 		DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
@@ -2649,81 +2547,52 @@ static void issue_probersp(struct rtw_ad
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
 	mac = myid(&padapter->eeprompriv);
 	bssid = cur_network->MacAddress;
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_PROBE_RESP);
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
 
-	ether_addr_copy(pwlanhdr->addr1, da);
-	ether_addr_copy(pwlanhdr->addr2, mac);
-	ether_addr_copy(pwlanhdr->addr3, bssid);
+	ether_addr_copy(mgmt->da, da);
+	ether_addr_copy(mgmt->sa, mac);
+	ether_addr_copy(mgmt->bssid, bssid);
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
 	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = pattrib->hdrlen;
-	pframe += pattrib->hdrlen;
-
-	if (cur_network->IELength > MAX_IE_SZ)
-		return;
-
-#ifdef CONFIG_8723AU_AP_MODE
-	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
-		pwps_ie = rtw_get_wps_ie23a(cur_network->IEs +
-					    _FIXED_IE_LENGTH_,
-					    cur_network->IELength -
-					    _FIXED_IE_LENGTH_, NULL,
-					    &wps_ielen);
-
-		/* inerset & update wps_probe_resp_ie */
-		if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
-			uint wps_offset, remainder_ielen;
-			u8 *premainder_ie;
 
-			wps_offset = (uint)(pwps_ie - cur_network->IEs);
+	/* timestamp will be inserted by hardware */
+	put_unaligned_le16(cur_network->beacon_interval,
+			   &mgmt->u.probe_resp.beacon_int);
 
-			premainder_ie = pwps_ie + wps_ielen;
+	put_unaligned_le16(cur_network->capability,
+			   &mgmt->u.probe_resp.capab_info);
 
-			remainder_ielen = cur_network->IELength - wps_offset -
-				wps_ielen;
+	pframe = mgmt->u.probe_resp.variable;
+	pattrib->pktlen =
+		offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
 
-			memcpy(pframe, cur_network->IEs, wps_offset);
-			pframe += wps_offset;
-			pattrib->pktlen += wps_offset;
+	/* below for ad-hoc mode */
 
-			/* to get ie data len */
-			wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];
-			if (wps_offset + wps_ielen + 2 <= MAX_IE_SZ) {
-				memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
-				       wps_ielen+2);
-				pframe += wps_ielen+2;
-				pattrib->pktlen += wps_ielen+2;
-			}
+#ifdef CONFIG_8723AU_AP_MODE
+	if ((pmlmeinfo->state & 0x03) == MSR_AP) {
+		pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+						  WLAN_OUI_TYPE_MICROSOFT_WPS,
+						  cur_network->IEs,
+						  cur_network->IELength);
 
-			if (wps_offset + wps_ielen + 2 + remainder_ielen <=
-			    MAX_IE_SZ) {
-				memcpy(pframe, premainder_ie, remainder_ielen);
-				pframe += remainder_ielen;
-				pattrib->pktlen += remainder_ielen;
-			}
-		} else {
-			memcpy(pframe, cur_network->IEs, cur_network->IELength);
-			pframe += cur_network->IELength;
-			pattrib->pktlen += cur_network->IELength;
-		}
+		memcpy(pframe, cur_network->IEs, cur_network->IELength);
+		pframe += cur_network->IELength;
+		pattrib->pktlen += cur_network->IELength;
 
 		/* retrieve SSID IE from cur_network->Ssid */
-		ies = pmgntframe->buf_addr + TXDESC_OFFSET +
-			sizeof(struct ieee80211_hdr_3addr);
 
-		ssid_ie = rtw_get_ie23a(ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID,
-					&ssid_ielen,
-					pframe - ies - _FIXED_IE_LENGTH_);
+		ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
+					WLAN_EID_SSID, &ssid_ielen,
+					pframe - mgmt->u.probe_resp.variable);
 
 		ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
 
@@ -2752,29 +2621,6 @@ static void issue_probersp(struct rtw_ad
 	} else
 #endif
 	{
-
-		/* timestamp will be inserted by hardware */
-		pframe += 8;
-		pattrib->pktlen += 8;
-
-		/*  beacon interval: 2 bytes */
-
-		memcpy(pframe, (unsigned char *)
-		       rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
-
-		pframe += 2;
-		pattrib->pktlen += 2;
-
-		/*  capability info: 2 bytes */
-
-		memcpy(pframe, (unsigned char *)
-		       rtw_get_capability23a_from_ie(cur_network->IEs), 2);
-
-		pframe += 2;
-		pattrib->pktlen += 2;
-
-		/* below for ad-hoc mode */
-
 		/*  SSID */
 		pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
 				       cur_network->Ssid.ssid_len,
@@ -2793,7 +2639,7 @@ static void issue_probersp(struct rtw_ad
 				       (unsigned char *)&cur_network->DSConfig,
 				       &pattrib->pktlen);
 
-		if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+		if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
 			u8 erpinfo = 0;
 			u32 ATIMWindow;
 			/*  IBSS Parameter Set... */
@@ -2829,17 +2675,17 @@ static int _issue_probereq(struct rtw_ad
 			   struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
 {
 	int ret = _FAIL;
-	struct xmit_frame		*pmgntframe;
-	struct pkt_attrib		*pattrib;
-	unsigned char			*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned char			*mac;
-	unsigned char			bssrate[NumRates];
+	struct xmit_frame *pmgntframe;
+	struct pkt_attrib *pattrib;
+	unsigned char *pframe;
+	struct ieee80211_hdr *pwlanhdr;
+	unsigned char *mac;
+	unsigned char bssrate[NumRates];
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	int	bssrate_len = 0;
-	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	int bssrate_len = 0;
+	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
 		 ("+%s\n", __func__));
@@ -2985,9 +2831,9 @@ static void issue_auth(struct rtw_adapte
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	unsigned int val32;
-	unsigned short val16;
+	u16 auth_algo;
 	int use_shared_key = 0;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -3004,23 +2850,21 @@ static void issue_auth(struct rtw_adapte
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_AUTH);
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+	pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
 
 	if (psta) { /*  for AP mode */
 #ifdef CONFIG_8723AU_AP_MODE
-
-		ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
-		ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-		ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
+		unsigned short val16;
+		ether_addr_copy(mgmt->da, psta->hwaddr);
+		ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+		ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
 
 		/*  setting auth algo number */
 		val16 = (u16)psta->authalg;
@@ -3028,29 +2872,19 @@ static void issue_auth(struct rtw_adapte
 		if (status != WLAN_STATUS_SUCCESS)
 			val16 = 0;
 
-		if (val16) {
-			val16 = cpu_to_le16(val16);
+		if (val16)
 			use_shared_key = 1;
-		}
 
-		pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		mgmt->u.auth.auth_alg = cpu_to_le16(val16);
 
 		/*  setting auth seq number */
-		val16 = (u16)psta->auth_seq;
-		val16 = cpu_to_le16(val16);
-		pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		mgmt->u.auth.auth_transaction =
+			cpu_to_le16((u16)psta->auth_seq);
 
 		/*  setting status code... */
-		val16 = status;
-		val16 = cpu_to_le16(val16);
-		pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		mgmt->u.auth.status_code = cpu_to_le16(status);
 
+		pframe = mgmt->u.auth.variable;
 		/*  added challenging text... */
 		if ((psta->auth_seq == 2) &&
 		    (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
@@ -3058,19 +2892,21 @@ static void issue_auth(struct rtw_adapte
 					       psta->chg_txt, &pattrib->pktlen);
 #endif
 	} else {
-		ether_addr_copy(pwlanhdr->addr1,
-				get_my_bssid23a(&pmlmeinfo->network));
-		ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-		ether_addr_copy(pwlanhdr->addr3,
+		struct ieee80211_mgmt *iv_mgmt;
+
+		ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
+		ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+		ether_addr_copy(mgmt->bssid,
 				get_my_bssid23a(&pmlmeinfo->network));
 
 		/*  setting auth algo number */
 		/*  0:OPEN System, 1:Shared key */
-		val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;
-		if (val16) {
-			val16 = cpu_to_le16(val16);
+		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
 			use_shared_key = 1;
-		}
+			auth_algo = WLAN_AUTH_SHARED_KEY;
+		} else
+			auth_algo = WLAN_AUTH_OPEN;
+
 		/* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
 		   (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
 		   pmlmeinfo->auth_seq); */
@@ -3079,35 +2915,32 @@ static void issue_auth(struct rtw_adapte
 		if ((pmlmeinfo->auth_seq == 3) &&
 		    (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
 		    (use_shared_key == 1)) {
+			u32 *piv = (u32 *)&mgmt->u.auth;
+
+			iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
 			/* DBG_8723A("==> iv(%d), key_index(%d)\n",
 			   pmlmeinfo->iv, pmlmeinfo->key_index); */
-			val32 = ((pmlmeinfo->iv++) |
-				 (pmlmeinfo->key_index << 30));
-			val32 = cpu_to_le32(val32);
-			pframe = rtw_set_fixed_ie23a(pframe, 4,
-						     (unsigned char *)&val32,
-						     &pattrib->pktlen);
+			val32 = (pmlmeinfo->iv & 0x3fffffff) |
+				(pmlmeinfo->key_index << 30);
+			pmlmeinfo->iv++;
+			put_unaligned_le32(val32, piv);
+
+			pattrib->pktlen += 4;
 
 			pattrib->iv_len = IEEE80211_WEP_IV_LEN;
-		}
+		} else
+			iv_mgmt = mgmt;
 
-		pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
 
 		/*  setting auth seq number */
-		val16 = pmlmeinfo->auth_seq;
-		val16 = cpu_to_le16(val16);
-		pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		iv_mgmt->u.auth.auth_transaction =
+			cpu_to_le16(pmlmeinfo->auth_seq);
 
 		/*  setting status code... */
-		val16 = status;
-		val16 = cpu_to_le16(val16);
-		pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
-					     (unsigned char *)&val16,
-					     &pattrib->pktlen);
+		iv_mgmt->u.auth.status_code = cpu_to_le16(status);
+
+		pframe = iv_mgmt->u.auth.variable;
 
 		/*  then checking to see if sending challenging text... */
 		if ((pmlmeinfo->auth_seq == 3) &&
@@ -3117,7 +2950,7 @@ static void issue_auth(struct rtw_adapte
 					       pmlmeinfo->chg_txt,
 					       &pattrib->pktlen);
 
-			pwlanhdr->frame_control |=
+			mgmt->frame_control |=
 				cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
 			pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
@@ -3144,10 +2977,9 @@ static void issue_assocrsp(struct rtw_ad
 			   struct sta_info *pstat, u16 pkt_type)
 {
 	struct xmit_frame *pmgntframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
-	unsigned short val;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -3169,37 +3001,27 @@ static void issue_assocrsp(struct rtw_ad
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
 
-	ether_addr_copy(pwlanhdr->addr1, pstat->hwaddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
+	ether_addr_copy(mgmt->da, pstat->hwaddr);
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 
 	pmlmeext->mgnt_seq++;
 
 	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen += pattrib->hdrlen;
-	pframe += pattrib->hdrlen;
-
-	/* capability */
-	val = *(unsigned short *)rtw_get_capability23a_from_ie(ie);
-
-	pframe = rtw_set_fixed_ie23a(pframe, _CAPABILITY_,
-				     (unsigned char *)&val, &pattrib->pktlen);
+	pattrib->pktlen =
+		offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
 
-	status = cpu_to_le16(status);
-	pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
-				     (unsigned char *)&status,
-				     &pattrib->pktlen);
+	mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
+	mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
+	mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
 
-	val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
-	pframe = rtw_set_fixed_ie23a(pframe, _ASOC_ID_, (unsigned char *)&val,
-				     &pattrib->pktlen);
+	pframe = mgmt->u.assoc_resp.variable;
 
 	if (pstat->bssratelen <= 8) {
 		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
@@ -3216,9 +3038,8 @@ static void issue_assocrsp(struct rtw_ad
 	if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
 		/* FILL HT CAP INFO IE */
 		/* p = hostapd_eid_ht_capabilities_info(hapd, p); */
-		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-				     ie + _BEACON_IE_OFFSET_,
-				     pnetwork->IELength -_BEACON_IE_OFFSET_);
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
+				     pnetwork->IELength);
 		if (p && p[1]) {
 			memcpy(pframe, p, p[1] + 2);
 			pframe += (p[1] + 2);
@@ -3227,9 +3048,8 @@ static void issue_assocrsp(struct rtw_ad
 
 		/* FILL HT ADD INFO IE */
 		/* p = hostapd_eid_ht_operation(hapd, p); */
-		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
-				     ie + _BEACON_IE_OFFSET_,
-				     pnetwork->IELength - _BEACON_IE_OFFSET_);
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
+				     pnetwork->IELength);
 		if (p && p[1] > 0) {
 			memcpy(pframe, p, p[1] + 2);
 			pframe += (p[1] + 2);
@@ -3243,10 +3063,9 @@ static void issue_assocrsp(struct rtw_ad
 					       0x01, 0x01};
 		int ie_len = 0;
 
-		for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
+		for (p = ie; ; p += (ie_len + 2)) {
 			p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
-					     pnetwork->IELength -
-					     _BEACON_IE_OFFSET_ - (ie_len + 2));
+					     pnetwork->IELength - (ie_len + 2));
 			if (p)
 				ie_len = p[1];
 			else
@@ -3269,16 +3088,6 @@ static void issue_assocrsp(struct rtw_ad
 				       REALTEK_96B_IE, &pattrib->pktlen);
 	}
 
-	/* add WPS IE ie for wps 2.0 */
-	if (pmlmepriv->wps_assoc_resp_ie &&
-	    pmlmepriv->wps_assoc_resp_ie_len > 0) {
-		memcpy(pframe, pmlmepriv->wps_assoc_resp_ie,
-		       pmlmepriv->wps_assoc_resp_ie_len);
-
-		pframe += pmlmepriv->wps_assoc_resp_ie_len;
-		pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
-	}
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe23a(padapter, pmgntframe);
@@ -3292,7 +3101,7 @@ static void issue_assocreq(struct rtw_ad
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
 	const u8 *p;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	unsigned int i, j, index = 0;
 	unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
 	struct registry_priv *pregpriv = &padapter->registrypriv;
@@ -3300,7 +3109,7 @@ static void issue_assocreq(struct rtw_ad
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	int bssrate_len = 0, sta_bssrate_len = 0, pie_len, bcn_fixed_size;
+	int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
 	u8 *pie;
 
 	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
@@ -3314,34 +3123,26 @@ static void issue_assocreq(struct rtw_ad
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
 	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_ASSOC_REQ);
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
 
-	ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
+	ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
 	/* caps */
-	memcpy(pframe,
-	       rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs), 2);
-
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-	/* listen interval */
+	put_unaligned_le16(pmlmeinfo->network.capability,
+			   &mgmt->u.assoc_req.capab_info);
 	/* todo: listen interval for power saving */
-	put_unaligned_le16(3, pframe);
-	pframe += 2;
-	pattrib->pktlen += 2;
+	put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
+
+	pframe = mgmt->u.assoc_req.variable;
+	pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
 
 	/* SSID */
 	pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
@@ -3416,11 +3217,9 @@ static void issue_assocreq(struct rtw_ad
 				       bssrate_len, bssrate, &pattrib->pktlen);
 
 	/* RSN */
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
 
-	pie = pmlmeinfo->network.IEs + bcn_fixed_size;
-	pie_len = pmlmeinfo->network.IELength - bcn_fixed_size;
+	pie = pmlmeinfo->network.IEs;
+	pie_len = pmlmeinfo->network.IELength;
 
 	p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
 	if (p)
@@ -3428,23 +3227,26 @@ static void issue_assocreq(struct rtw_ad
 				       &pattrib->pktlen);
 
 	/* HT caps */
-	if (padapter->mlmepriv.htpriv.ht_option == true) {
+	if (padapter->mlmepriv.htpriv.ht_option) {
 		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
 
 		if (p && !is_ap_in_tkip23a(padapter)) {
-			memcpy(&pmlmeinfo->HT_caps, p + 2,
-			       sizeof(struct HT_caps_element));
+			struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
+
+			memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
 
 			/* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
 			if (pregpriv->cbw40_enable == 0) {
-				pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= (~(BIT(6) | BIT(1)));
+				cap->cap_info &= ~cpu_to_le16(
+					IEEE80211_HT_CAP_SGI_40 |
+					IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 			} else {
-				pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= BIT(1);
+				cap->cap_info |= cpu_to_le16(
+					IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 			}
 
 			/* todo: disable SM power save mode */
-			pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |=
-				0x000c;
+			cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
 
 			rf_type = rtl8723a_get_rf_type(padapter);
 			/* switch (pregpriv->rf_config) */
@@ -3452,9 +3254,9 @@ static void issue_assocreq(struct rtw_ad
 			case RF_1T1R:
 				/* RX STBC One spatial stream */
 				if (pregpriv->rx_stbc)
-					pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);
+					cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
 
-				memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R23A, 16);
+				memcpy(&cap->mcs, MCS_rate_1R23A, 16);
 				break;
 
 			case RF_2T2R:
@@ -3473,29 +3275,29 @@ static void issue_assocreq(struct rtw_ad
 				    pregpriv->wifi_spec == 1) {
 					DBG_8723A("declare supporting RX "
 						  "STBC\n");
-					pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
+					/* RX STBC two spatial stream */
+					cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
 				}
-				memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R23A, 16);
+				memcpy(&cap->mcs, MCS_rate_2R23A, 16);
 				break;
 			}
-			pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info =
-				cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
 
 			if (rtl8723a_BT_coexist(padapter) &&
 			    rtl8723a_BT_using_antenna_1(padapter)) {
 				/*  set to 8K */
-				pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para &= (u8)~IEEE80211_HT_AMPDU_PARM_FACTOR;
-/*				pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para |= MAX_AMPDU_FACTOR_8K */
+				cap->ampdu_params_info &=
+					~IEEE80211_HT_AMPDU_PARM_FACTOR;
+/*				cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
 			}
 
 			pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
-					       p[1], (u8 *)&pmlmeinfo->HT_caps,
+					       p[1], (u8 *)&pmlmeinfo->ht_cap,
 					       &pattrib->pktlen);
 		}
 	}
 
 	/* vendor specific IE, such as WPA, WMM, WPS */
-	for (i = bcn_fixed_size;  i < pmlmeinfo->network.IELength;) {
+	for (i = 0;  i < pmlmeinfo->network.IELength;) {
 		p = pmlmeinfo->network.IEs + i;
 
 		switch (p[0]) {
@@ -3541,7 +3343,7 @@ exit:
 		kfree(pmlmepriv->assoc_req);
 		pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
 		if (pmlmepriv->assoc_req) {
-			memcpy(pmlmepriv->assoc_req, pwlanhdr, pattrib->pktlen);
+			memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
 			pmlmepriv->assoc_req_len = pattrib->pktlen;
 		}
 	} else
@@ -3550,7 +3352,7 @@ exit:
 	return;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
 			      unsigned int power_mode, int wait_ack)
 {
@@ -3589,9 +3391,9 @@ static int _issue_nulldata23a(struct rtw
 	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 					      IEEE80211_STYPE_NULLFUNC);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) == MSR_AP)
 		pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-	else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
 		pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
 
 	if (power_mode)
@@ -3621,7 +3423,7 @@ exit:
 	return ret;
 }
 
-/* when wait_ms >0 , this function shoule be called at process context */
+/* when wait_ms >0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
 		      unsigned int power_mode, int try_cnt, int wait_ms)
@@ -3632,7 +3434,7 @@ int issue_nulldata23a(struct rtw_adapter
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid23a(&pmlmeinfo->network);
 
@@ -3674,7 +3476,7 @@ exit:
 	return ret;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
 				  unsigned char *da, u16 tid, int wait_ack)
 {
@@ -3711,9 +3513,9 @@ static int _issue_qos_nulldata23a(struct
 	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 					      IEEE80211_STYPE_QOS_NULLFUNC);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) == MSR_AP)
 		pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-	else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
 		pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
 
 	if (pattrib->mdata)
@@ -3749,7 +3551,7 @@ exit:
 	return ret;
 }
 
-/* when wait_ms >0 , this function shoule be called at process context */
+/* when wait_ms >0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
 			  u16 tid, int try_cnt, int wait_ms)
@@ -3760,7 +3562,7 @@ int issue_qos_nulldata23a(struct rtw_ada
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid23a(&pmlmeinfo->network);
 
@@ -3806,8 +3608,7 @@ static int _issue_deauth(struct rtw_adap
 {
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -3826,27 +3627,21 @@ static int _issue_deauth(struct rtw_adap
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_DEAUTH);
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
 
-	ether_addr_copy(pwlanhdr->addr1, da);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
+	ether_addr_copy(mgmt->da, da);
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
 
-	reason = cpu_to_le16(reason);
-	pframe = rtw_set_fixed_ie23a(pframe, WLAN_REASON_PREV_AUTH_NOT_VALID,
-				     (unsigned char *)&reason,
-				     &pattrib->pktlen);
+	mgmt->u.deauth.reason_code = cpu_to_le16(reason);
 
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
@@ -3919,10 +3714,9 @@ void issue_action_spct_ch_switch23a(stru
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	u8 category, action;
 
 	DBG_8723A("%s(%s): ra ="MAC_FMT", ch:%u, offset:%u\n", __func__,
 		  padapter->pnetdev->name, MAC_ARG(ra), new_ch, ch_offset);
@@ -3937,29 +3731,24 @@ void issue_action_spct_ch_switch23a(stru
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_ACTION);
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
 
-	ether_addr_copy(pwlanhdr->addr1, ra); /* RA */
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); /* TA */
-	ether_addr_copy(pwlanhdr->addr3, ra); /* DA = RA */
+	ether_addr_copy(mgmt->da, ra); /* RA */
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
+	ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	/* category, action */
-	category = WLAN_CATEGORY_SPECTRUM_MGMT;
-	action = WLAN_ACTION_SPCT_CHL_SWITCH;
+	mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
+	mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
 
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
+	pframe = mgmt->u.action.u.chan_switch.variable;
+	pattrib->pktlen = offsetof(struct ieee80211_mgmt,
+				   u.action.u.chan_switch.variable);
 
 	pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
 					  new_ch, 0);
@@ -3975,17 +3764,15 @@ void issue_action_BA23a(struct rtw_adapt
 			const unsigned char *raddr,
 			unsigned char action, unsigned short status)
 {
-	u8 category = WLAN_CATEGORY_BACK;
 	u16 start_seq;
 	u16 BA_para_set;
-	u16 reason_code;
 	u16 BA_timeout_value;
 	u16 BA_starting_seqctrl;
+	u16 BA_para;
 	int max_rx_ampdu_factor;
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
-	u8 *pframe;
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -3994,8 +3781,7 @@ void issue_action_BA23a(struct rtw_adapt
 	struct registry_priv *pregpriv = &padapter->registrypriv;
 	u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
 
-	DBG_8723A("%s, category =%d, action =%d, status =%d\n",
-		  __func__, category, action, status);
+	DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
 
 	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
 	if (!pmgntframe)
@@ -4007,40 +3793,36 @@ void issue_action_BA23a(struct rtw_adapt
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
 
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_ACTION);
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
 
-	/* memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); */
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
+	ether_addr_copy(mgmt->da, raddr);
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
 
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
+	mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
 	pmlmeext->mgnt_seq++;
 
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+	mgmt->u.action.category = WLAN_CATEGORY_BACK;
 
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
+	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
 
 	status = cpu_to_le16(status);
 
-	if (category != 3)
-		goto out;
+	switch (action) {
+	case WLAN_ACTION_ADDBA_REQ:
+		pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
+
+		mgmt->u.action.u.addba_req.action_code = action;
 
-	switch (action)
-	{
-	case 0: /* ADDBA req */
 		do {
 			pmlmeinfo->dialogToken++;
 		} while (pmlmeinfo->dialogToken == 0);
-		pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->dialogToken,
-					     &pattrib->pktlen);
+
+		mgmt->u.action.u.addba_req.dialog_token =
+			pmlmeinfo->dialogToken;
 
 		if (rtl8723a_BT_coexist(padapter) &&
 		    rtl8723a_BT_using_antenna_1(padapter) &&
@@ -4061,51 +3843,60 @@ void issue_action_BA23a(struct rtw_adapt
 			/* immediate ack & 64 buffer size */
 			BA_para_set = (0x1002 | ((status & 0xf) << 2));
 		}
-		BA_para_set = cpu_to_le16(BA_para_set);
-		pframe = rtw_set_fixed_ie23a(pframe, 2,
-					     (unsigned char *)&BA_para_set,
-					     &pattrib->pktlen);
+
+		put_unaligned_le16(BA_para_set,
+				   &mgmt->u.action.u.addba_req.capab);
 
 		BA_timeout_value = 5000;/*  5ms */
 		BA_timeout_value = cpu_to_le16(BA_timeout_value);
-		pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)
-					     &BA_timeout_value,
-					     &pattrib->pktlen);
+		put_unaligned_le16(BA_timeout_value,
+				   &mgmt->u.action.u.addba_req.timeout);
 
-		/* if ((psta = rtw_get_stainfo23a(pstapriv,
-		   pmlmeinfo->network.MacAddress)) != NULL) */
-		if ((psta = rtw_get_stainfo23a(pstapriv, raddr))) {
-			start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
+		psta = rtw_get_stainfo23a(pstapriv, raddr);
+		if (psta) {
+			int idx;
+
+			idx = status & 0x07;
+			start_seq =
+				(psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
 
 			DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
-				  start_seq, status & 0x07);
+				  start_seq, idx);
 
-			psta->BA_starting_seqctrl[status & 0x07] = start_seq;
+			psta->BA_starting_seqctrl[idx] = start_seq;
 
 			BA_starting_seqctrl = start_seq << 4;
-		}
+		} else
+			BA_starting_seqctrl = 0;
+
+		put_unaligned_le16(BA_starting_seqctrl,
+				   &mgmt->u.action.u.addba_req.start_seq_num);
 
-		BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
-		pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&BA_starting_seqctrl, &pattrib->pktlen);
 		break;
 
-	case 1: /* ADDBA rsp */
-		pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->ADDBA_req.dialog_token, &pattrib->pktlen);
-		pframe = rtw_set_fixed_ie23a(pframe, 2,
-					     (unsigned char *)&status,
-					     &pattrib->pktlen);
+	case WLAN_ACTION_ADDBA_RESP:
+		pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
+
+		mgmt->u.action.u.addba_resp.action_code = action;
+		mgmt->u.action.u.addba_resp.dialog_token =
+			pmlmeinfo->ADDBA_req.dialog_token;
+		put_unaligned_le16(status,
+				   &mgmt->u.action.u.addba_resp.status);
+
 		GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
 				     &max_rx_ampdu_factor);
+
+		BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
 		if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
-			BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
+			BA_para_set = BA_para | 0x1000; /* 64 buffer size */
 		else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
-			BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
+			BA_para_set = BA_para | 0x0800; /* 32 buffer size */
 		else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
-			BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
+			BA_para_set = BA_para | 0x0400; /* 16 buffer size */
 		else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
-			BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
+			BA_para_set = BA_para | 0x0200; /* 8 buffer size */
 		else
-			BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
+			BA_para_set = BA_para | 0x1000; /* 64 buffer size */
 
 		if (rtl8723a_BT_coexist(padapter) &&
 		    rtl8723a_BT_using_antenna_1(padapter) &&
@@ -4118,169 +3909,33 @@ void issue_action_BA23a(struct rtw_adapt
 		}
 
 		if (pregpriv->ampdu_amsdu == 0)/* disabled */
-			BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
+			BA_para_set &= ~BIT(0);
 		else if (pregpriv->ampdu_amsdu == 1)/* enabled */
-			BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
-		else /* auto */
-			BA_para_set = cpu_to_le16(BA_para_set);
+			BA_para_set |= BIT(0);
 
-		pframe = rtw_set_fixed_ie23a(pframe, 2,
-					     (unsigned char *)&BA_para_set,
-					     &pattrib->pktlen);
-		pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&pmlmeinfo->ADDBA_req.BA_timeout_value, &pattrib->pktlen);
+		put_unaligned_le16(BA_para_set,
+				   &mgmt->u.action.u.addba_resp.capab);
+
+		put_unaligned_le16(pmlmeinfo->ADDBA_req.BA_timeout_value,
+				   &mgmt->u.action.u.addba_resp.timeout);
+
+		pattrib->pktlen += 8;
 		break;
-	case 2:/* DELBA */
+	case WLAN_ACTION_DELBA:
+		pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
+
+		mgmt->u.action.u.delba.action_code = action;
 		BA_para_set = (status & 0x1F) << 3;
-		BA_para_set = cpu_to_le16(BA_para_set);
-		pframe = rtw_set_fixed_ie23a(pframe, 2,
-					     (unsigned char *)&BA_para_set,
-					     &pattrib->pktlen);
+		mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
+		mgmt->u.action.u.delba.reason_code =
+			cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
 
-		reason_code = 37;/* Requested from peer STA as it does not
-				    want to use the mechanism */
-		reason_code = cpu_to_le16(reason_code);
-		pframe = rtw_set_fixed_ie23a(pframe, 2,
-					     (unsigned char *)&reason_code,
-					     &pattrib->pktlen);
+		pattrib->pktlen += 5;
 		break;
 	default:
 		break;
 	}
 
-out:
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-}
-
-static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
-{
-	struct list_head *plist, *phead, *ptmp;
-	unsigned char category, action;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	u8 *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	struct wlan_network *pnetwork;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	struct rtw_queue *queue	= &pmlmepriv->scanned_queue;
-	u8 InfoContent[16] = {0};
-	u8 ICS[8][15];
-	int i;
-
-	if (pmlmepriv->num_FortyMHzIntolerant == 0 ||
-	    pmlmepriv->num_sta_no_ht == 0)
-		return;
-
-	if (pmlmeinfo->bwmode_updated)
-		return;
-
-	DBG_8723A("%s\n", __func__);
-
-	category = WLAN_CATEGORY_PUBLIC;
-	action = ACT_PUBLIC_BSSCOEXIST;
-
-	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
-	if (!pmgntframe)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-					      IEEE80211_STYPE_ACTION);
-
-	ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
-
-	pwlanhdr->seq_ctrl =
-		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
-	pmlmeext->mgnt_seq++;
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-
-	if (pmlmepriv->num_FortyMHzIntolerant > 0) {
-		u8 iedata = BIT(2);/* 20 MHz BSS Width Request */
-
-		pframe = rtw_set_ie23a(pframe, WLAN_EID_BSS_COEX_2040, 1,
-				       &iedata, &pattrib->pktlen);
-	}
-
-	if (pmlmepriv->num_sta_no_ht <= 0)
-		goto out;
-
-	memset(ICS, 0, sizeof(ICS));
-
-	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-
-	phead = get_list_head(queue);
-	plist = phead->next;
-
-	list_for_each_safe(plist, ptmp, phead) {
-		const u8 *p;
-		struct wlan_bssid_ex *pbss_network;
-
-		pnetwork = container_of(plist, struct wlan_network, list);
-
-		pbss_network = &pnetwork->network;
-
-		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-				     pbss_network->IEs + _FIXED_IE_LENGTH_,
-				     pbss_network->IELength -_FIXED_IE_LENGTH_);
-		if (!p || !p[1]) { /* non-HT */
-			if (pbss_network->DSConfig <= 0 ||
-			    pbss_network->DSConfig > 14)
-				continue;
-
-			ICS[0][pbss_network->DSConfig] = 1;
-
-			if (ICS[0][0] == 0)
-				ICS[0][0] = 1;
-		}
-
-	}
-
-	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
-	for (i = 0; i < 8;i++) {
-		if (ICS[i][0] == 1) {
-			int j, k = 0;
-
-			InfoContent[k] = i;
-			/* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
-			k++;
-
-			for (j = 1; j <= 14; j++) {
-				if (ICS[i][j] == 1) {
-					if (k < 16) {
-						/* channel number */
-						InfoContent[k] = j;
-						k++;
-					}
-				}
-			}
-
-			pframe = rtw_set_ie23a(pframe,
-					       EID_BSSIntolerantChlReport, k,
-					       InfoContent, &pattrib->pktlen);
-		}
-	}
-
-out:
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe23a(padapter, pmgntframe);
@@ -4291,11 +3946,11 @@ int send_delba23a(struct rtw_adapter *pa
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	struct sta_info *psta = NULL;
 	/* struct recv_reorder_ctrl *preorder_ctrl; */
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	u16 tid;
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state&0x03) != MSR_AP)
 		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
 			return _SUCCESS;
 
@@ -4328,8 +3983,8 @@ int send_delba23a(struct rtw_adapter *pa
 
 int send_beacon23a(struct rtw_adapter *padapter)
 {
-	bool	bxmitok;
-	int	issue = 0;
+	bool bxmitok;
+	int issue = 0;
 	int poll = 0;
 	unsigned long start = jiffies;
 	unsigned int passing_time;
@@ -4368,7 +4023,7 @@ int send_beacon23a(struct rtw_adapter *p
 
 /****************************************************************************
 
-Following are some utitity fuctions for WiFi MLME
+Following are some utitity functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -4377,9 +4032,10 @@ bool IsLegal5GChannel(struct rtw_adapter
 
 	int i = 0;
 	u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
-		60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
-		124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
-		161, 163, 165};
+			     60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+			     114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+			     134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+			     161, 163, 165};
 	for (i = 0; i < sizeof(Channel_5G); i++)
 		if (channel == Channel_5G[i])
 			return true;
@@ -4390,7 +4046,7 @@ static void rtw_site_survey(struct rtw_a
 {
 	unsigned char survey_channel = 0;
 	enum rt_scan_type ScanType = SCAN_PASSIVE;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct rtw_ieee80211_channel *ch;
 
@@ -4446,7 +4102,7 @@ static void rtw_site_survey(struct rtw_a
 		/* val8 = 0; */
 
 		/* config MSR */
-		Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
+		rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
 
 		/* restore RX GAIN */
 		rtl8723a_set_initial_gain(padapter, 0xff);
@@ -4462,66 +4118,81 @@ static void rtw_site_survey(struct rtw_a
 
 		pmlmeext->chan_scan_time = SURVEY_TO;
 		pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-
-		issue_action_BSSCoexistPacket(padapter);
-		issue_action_BSSCoexistPacket(padapter);
-		issue_action_BSSCoexistPacket(padapter);
 	}
 
 	return;
 }
 
 /* collect bss info from Beacon and Probe request/response frames. */
-int collect_bss_info23a(struct rtw_adapter *padapter,
-			struct recv_frame *precv_frame,
-			struct wlan_bssid_ex *bssid)
+static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
+					      struct recv_frame *precv_frame)
 {
-	int i;
-	const u8 *p;
 	struct sk_buff *skb = precv_frame->pkt;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
-	unsigned int length;
-	u8 ie_offset;
 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	u16 capab_info;
-
-	length = skb->len - sizeof(struct ieee80211_hdr_3addr);
+	struct wlan_bssid_ex *bssid;
+	const u8 *p;
+	u8 *pie;
+	unsigned int length;
+	int i;
 
-	if (length > MAX_IE_SZ) {
-		/* DBG_8723A("IE too long for survey event\n"); */
-		return _FAIL;
-	}
+	length = skb->len;
 
-	memset(bssid, 0, sizeof(struct wlan_bssid_ex));
+	bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+	if (!bssid)
+		return NULL;
 
 	if (ieee80211_is_beacon(mgmt->frame_control)) {
+		length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		pie = mgmt->u.beacon.variable;
 		bssid->reserved = 1;
-		ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-		capab_info = mgmt->u.beacon.capab_info;
-	} else  if (ieee80211_is_probe_req(mgmt->frame_control)) {
-		ie_offset = offsetof(struct ieee80211_mgmt,
-				     u.probe_req.variable);
+		bssid->capability =
+			get_unaligned_le16(&mgmt->u.beacon.capab_info);
+		bssid->beacon_interval =
+			get_unaligned_le16(&mgmt->u.beacon.beacon_int);
+		bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
+	} else if (ieee80211_is_probe_req(mgmt->frame_control)) {
+		length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
+		pie = mgmt->u.probe_req.variable;
 		bssid->reserved = 2;
-		capab_info = 0;
+		bssid->capability = 0;
+		bssid->beacon_interval =
+			padapter->registrypriv.dev_network.beacon_interval;
+		bssid->tsf = 0;
 	} else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
-		ie_offset = offsetof(struct ieee80211_mgmt,
-				     u.probe_resp.variable);
+		length -=
+			offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+		pie = mgmt->u.probe_resp.variable;
 		bssid->reserved = 3;
-		capab_info = mgmt->u.probe_resp.capab_info;
+		bssid->capability =
+			get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
+		bssid->beacon_interval =
+			get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
+		bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
 	} else {
+		length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		pie = mgmt->u.beacon.variable;
 		bssid->reserved = 0;
-		ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-		capab_info = mgmt->u.beacon.capab_info;
+		bssid->capability =
+			get_unaligned_le16(&mgmt->u.beacon.capab_info);
+		bssid->beacon_interval =
+			padapter->registrypriv.dev_network.beacon_interval;
+		bssid->tsf = 0;
+	}
+
+	if (length > MAX_IE_SZ) {
+		/* DBG_8723A("IE too long for survey event\n"); */
+		kfree(bssid);
+		return NULL;
 	}
-	ie_offset -= offsetof(struct ieee80211_mgmt, u);
 
 	bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
 
 	/* below is to copy the information element */
 	bssid->IELength = length;
-	memcpy(bssid->IEs, &mgmt->u, bssid->IELength);
+	memcpy(bssid->IEs, pie, bssid->IELength);
 
 	/* get the signal strength */
 	/*  in dBM.raw data */
@@ -4532,55 +4203,47 @@ int collect_bss_info23a(struct rtw_adapt
 		precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
 
 	/*  checking SSID */
-	p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs + ie_offset,
-			     bssid->IELength - ie_offset);
+	p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
 
 	if (!p) {
 		DBG_8723A("marc: cannot find SSID for survey event\n");
-		return _FAIL;
+		goto fail;
 	}
 
 	if (p[1] > IEEE80211_MAX_SSID_LEN) {
 		DBG_8723A("%s()-%d: IE too long (%d) for survey "
 			  "event\n", __func__, __LINE__, p[1]);
-		return _FAIL;
+		goto fail;
 	}
 	memcpy(bssid->Ssid.ssid, p + 2, p[1]);
 	bssid->Ssid.ssid_len = p[1];
 
-	memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
-
 	/* checking rate info... */
 	i = 0;
-	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs + ie_offset,
-			     bssid->IELength - ie_offset);
+	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
 	if (p) {
 		if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
 			DBG_8723A("%s()-%d: IE too long (%d) for survey "
 				  "event\n", __func__, __LINE__, p[1]);
-			return _FAIL;
+			goto fail;
 		}
 		memcpy(bssid->SupportedRates, p + 2, p[1]);
 		i = p[1];
 	}
 
-	p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs + ie_offset,
-			     bssid->IELength - ie_offset);
+	p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
+			     bssid->IELength);
 	if (p) {
 		if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
 			DBG_8723A("%s()-%d: IE too long (%d) for survey "
 				  "event\n", __func__, __LINE__, p[1]);
-			return _FAIL;
+			goto fail;
 		}
 		memcpy(bssid->SupportedRates + i, p + 2, p[1]);
 	}
 
-	if (bssid->IELength < 12)
-		return _FAIL;
-
 	/*  Checking for DSConfig */
-	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs + ie_offset,
-			     bssid->IELength - ie_offset);
+	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
 
 	bssid->DSConfig = 0;
 
@@ -4588,13 +4251,12 @@ int collect_bss_info23a(struct rtw_adapt
 		bssid->DSConfig = p[2];
 	} else {/*  In 5G, some ap do not have DSSET IE */
 		/*  checking HT info for channel */
-		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
-				     bssid->IEs + ie_offset,
-				     bssid->IELength - ie_offset);
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
+				     bssid->IELength);
 		if (p) {
-			struct HT_info_element *HT_info =
-				(struct HT_info_element *)(p + 2);
-			bssid->DSConfig = HT_info->primary_channel;
+			struct ieee80211_ht_operation *HT_info =
+				(struct ieee80211_ht_operation *)(p + 2);
+			bssid->DSConfig = HT_info->primary_chan;
 		} else /*  use current channel */
 			bssid->DSConfig = rtw_get_oper_ch23a(padapter);
 	}
@@ -4604,13 +4266,10 @@ int collect_bss_info23a(struct rtw_adapt
 		bssid->ifmode = NL80211_IFTYPE_STATION;
 		ether_addr_copy(bssid->MacAddress, mgmt->sa);
 		bssid->Privacy = 1;
-		return _SUCCESS;
+		return bssid;
 	}
 
-	bssid->BeaconPeriod = get_unaligned_le16(
-		rtw_get_beacon_interval23a_from_ie(bssid->IEs));
-
-	if (capab_info & BIT(0)) {
+	if (bssid->capability & WLAN_CAPABILITY_ESS) {
 		bssid->ifmode = NL80211_IFTYPE_STATION;
 		ether_addr_copy(bssid->MacAddress, mgmt->sa);
 	} else {
@@ -4618,7 +4277,7 @@ int collect_bss_info23a(struct rtw_adapt
 		ether_addr_copy(bssid->MacAddress, mgmt->bssid);
 	}
 
-	if (capab_info & BIT(4))
+	if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
 		bssid->Privacy = 1;
 	else
 		bssid->Privacy = 0;
@@ -4630,41 +4289,44 @@ int collect_bss_info23a(struct rtw_adapt
 	    pmlmeinfo->bwmode_updated == false) {
 		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-				     bssid->IEs + ie_offset,
-				     bssid->IELength - ie_offset);
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
+				     bssid->IELength);
 		if (p && p[1] > 0) {
-			struct HT_caps_element *pHT_caps;
-			pHT_caps = (struct HT_caps_element *)(p + 2);
+			struct ieee80211_ht_cap *pHT_caps;
+			pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
 
-			if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
+			if (pHT_caps->cap_info &
+			    cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
 				pmlmepriv->num_FortyMHzIntolerant++;
 		} else
 			pmlmepriv->num_sta_no_ht++;
 	}
 
 
-	/*  mark bss info receving from nearby channel as SignalQuality 101 */
+	/*  mark bss info receiving from nearby channel as SignalQuality 101 */
 	if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
 		bssid->PhyInfo.SignalQuality = 101;
 
-	return _SUCCESS;
+	return bssid;
+fail:
+	kfree (bssid);
+	return NULL;
 }
 
 static void start_create_ibss(struct rtw_adapter* padapter)
 {
-	unsigned short	caps;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	unsigned short caps;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 	pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
-	pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
+	pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
 
 	/* update wireless mode */
 	update_wireless_mode23a(padapter);
 
-	/* udpate capability */
-	caps = rtw_get_capability23a(pnetwork);
+	/* update capability */
+	caps = pnetwork->capability;
 	update_capinfo23a(padapter, caps);
 	if (caps & WLAN_CAPABILITY_IBSS) {	/* adhoc master */
 		rtl8723a_set_sec_cfg(padapter, 0xcf);
@@ -4675,20 +4337,17 @@ static void start_create_ibss(struct rtw
 
 		rtl8723a_SetBeaconRelatedRegisters(padapter);
 
-		/* set msr to WIFI_FW_ADHOC_STATE */
-		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
-		Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
+		/* set msr to MSR_ADHOC */
+		pmlmeinfo->state = MSR_ADHOC;
+		rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
 
 		/* issue beacon */
-		if (send_beacon23a(padapter) == _FAIL)
-		{
+		if (send_beacon23a(padapter) == _FAIL) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
 
 			report_join_res23a(padapter, -1);
-			pmlmeinfo->state = WIFI_FW_NULL_STATE;
-		}
-		else
-		{
+			pmlmeinfo->state = MSR_NOLINK;
+		} else {
 			hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
 			hw_var_set_mlme_join(padapter, 0);
 
@@ -4705,27 +4364,27 @@ static void start_create_ibss(struct rtw
 
 static void start_clnt_join(struct rtw_adapter* padapter)
 {
-	unsigned short	caps;
-	u8	val8;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	unsigned short caps;
+	u8 val8;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 	int beacon_timeout;
 
 	pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
-	pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
+	pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
 
 	/* update wireless mode */
 	update_wireless_mode23a(padapter);
 
-	/* udpate capability */
-	caps = rtw_get_capability23a(pnetwork);
+	/* update capability */
+	caps = pnetwork->capability;
 	update_capinfo23a(padapter, caps);
 	if (caps & WLAN_CAPABILITY_ESS) {
 		/* switch channel */
 		set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 
-		Set_MSR23a(padapter, WIFI_FW_STATION_STATE);
+		rtl8723a_set_media_status(padapter, MSR_INFRA);
 
 		val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
 			0xcc: 0xcf;
@@ -4741,9 +4400,9 @@ static void start_clnt_join(struct rtw_a
 		set_link_timer(pmlmeext, beacon_timeout);
 		mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
 			  msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
-		pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
+		pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
 	} else if (caps & WLAN_CAPABILITY_IBSS) {	/* adhoc client */
-		Set_MSR23a(padapter, WIFI_FW_ADHOC_STATE);
+		rtl8723a_set_media_status(padapter, MSR_ADHOC);
 
 		rtl8723a_set_sec_cfg(padapter, 0xcf);
 
@@ -4752,7 +4411,7 @@ static void start_clnt_join(struct rtw_a
 
 		rtl8723a_SetBeaconRelatedRegisters(padapter);
 
-		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+		pmlmeinfo->state = MSR_ADHOC;
 
 		report_join_res23a(padapter, 1);
 	}
@@ -4765,7 +4424,7 @@ static void start_clnt_join(struct rtw_a
 
 static void start_clnt_auth(struct rtw_adapter* padapter)
 {
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	del_timer_sync(&pmlmeext->link_timer);
@@ -4783,8 +4442,10 @@ static void start_clnt_auth(struct rtw_a
 	/*  AP may: 1)not response auth or 2)deauth us after link is complete */
 	/*  issue deauth before issuing auth to deal with the situation */
 	/*	Commented by Albert 2012/07/21 */
-	/*	For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
-	issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
+	/*	For the Win8 P2P connection, it will be hard to have a
+		successful connection if this Wi-Fi doesn't connect to it. */
+	issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
+			WLAN_REASON_DEAUTH_LEAVING);
 
 	DBG_8723A_LEVEL(_drv_always_, "start auth\n");
 	issue_auth(padapter, NULL, 0);
@@ -4794,7 +4455,7 @@ static void start_clnt_auth(struct rtw_a
 
 static void start_clnt_assoc(struct rtw_adapter* padapter)
 {
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	del_timer_sync(&pmlmeext->link_timer);
@@ -4810,7 +4471,7 @@ static void start_clnt_assoc(struct rtw_
 int receive_disconnect23a(struct rtw_adapter *padapter,
 			  unsigned char *MacAddr, unsigned short reason)
 {
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	/* check A3 */
@@ -4819,17 +4480,17 @@ int receive_disconnect23a(struct rtw_ada
 
 	DBG_8723A("%s\n", __func__);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	if ((pmlmeinfo->state&0x03) == MSR_INFRA)
 	{
 		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
 		{
-			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			pmlmeinfo->state = MSR_NOLINK;
 			report_del_sta_event23a(padapter, MacAddr, reason);
 
 		}
 		else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
 		{
-			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			pmlmeinfo->state = MSR_NOLINK;
 			report_join_res23a(padapter, -2);
 		}
 	}
@@ -4860,9 +4521,8 @@ static void process_80211d(struct rtw_ad
 		u8 noc; /*  number of channel */
 		u8 j, k;
 
-		ie = cfg80211_find_ie(WLAN_EID_COUNTRY,
-				      bssid->IEs + _FIXED_IE_LENGTH_,
-				      bssid->IELength - _FIXED_IE_LENGTH_);
+		ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
+				      bssid->IELength);
 		if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
 			return;
 
@@ -5068,12 +4728,13 @@ Following are the functions to report ev
 
 *****************************************************************************/
 
-void report_survey_event23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+void report_survey_event23a(struct rtw_adapter *padapter,
+			    struct recv_frame *precv_frame)
 {
 	struct cmd_obj *pcmd_obj;
-	u8	*pevtcmd;
+	u8 *pevtcmd;
 	u32 cmdsz;
-	struct survey_event	*psurvey_evt;
+	struct survey_event *psurvey_evt;
 	struct C2HEvent_Header *pc2h_evt_hdr;
 	struct mlme_ext_priv *pmlmeext;
 	struct cmd_priv *pcmdpriv;
@@ -5084,8 +4745,7 @@ void report_survey_event23a(struct rtw_a
 	pmlmeext = &padapter->mlmeextpriv;
 	pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-					     GFP_ATOMIC);
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!pcmd_obj)
 		return;
 
@@ -5110,13 +4770,14 @@ void report_survey_event23a(struct rtw_a
 
 	psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
 
-	if (collect_bss_info23a(padapter, precv_frame, &psurvey_evt->bss) == _FAIL) {
+	psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
+	if (!psurvey_evt->bss) {
 		kfree(pcmd_obj);
 		kfree(pevtcmd);
 		return;
 	}
 
-	process_80211d(padapter, &psurvey_evt->bss);
+	process_80211d(padapter, psurvey_evt->bss);
 
 	rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
 
@@ -5128,15 +4789,14 @@ void report_survey_event23a(struct rtw_a
 void report_surveydone_event23a(struct rtw_adapter *padapter)
 {
 	struct cmd_obj *pcmd_obj;
-	u8	*pevtcmd;
+	u8 *pevtcmd;
 	u32 cmdsz;
 	struct surveydone_event *psurveydone_evt;
-	struct C2HEvent_Header	*pc2h_evt_hdr;
-	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct C2HEvent_Header *pc2h_evt_hdr;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-					     GFP_ATOMIC);
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!pcmd_obj)
 		return;
 
@@ -5172,7 +4832,7 @@ void report_surveydone_event23a(struct r
 void report_join_res23a(struct rtw_adapter *padapter, int res)
 {
 	struct cmd_obj *pcmd_obj;
-	u8	*pevtcmd;
+	u8 *pevtcmd;
 	u32 cmdsz;
 	struct joinbss_event		*pjoinbss_evt;
 	struct C2HEvent_Header	*pc2h_evt_hdr;
@@ -5180,8 +4840,7 @@ void report_join_res23a(struct rtw_adapt
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-					     GFP_ATOMIC);
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!pcmd_obj)
 		return;
 
@@ -5218,20 +4877,20 @@ void report_join_res23a(struct rtw_adapt
 	return;
 }
 
-void report_del_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
+void report_del_sta_event23a(struct rtw_adapter *padapter,
+			     unsigned char* MacAddr, unsigned short reason)
 {
 	struct cmd_obj *pcmd_obj;
-	u8	*pevtcmd;
+	u8 *pevtcmd;
 	u32 cmdsz;
 	struct sta_info *psta;
-	int	mac_id;
-	struct stadel_event			*pdel_sta_evt;
-	struct C2HEvent_Header	*pc2h_evt_hdr;
-	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	int mac_id;
+	struct stadel_event *pdel_sta_evt;
+	struct C2HEvent_Header *pc2h_evt_hdr;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-					     GFP_ATOMIC);
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!pcmd_obj)
 		return;
 
@@ -5274,18 +4933,18 @@ void report_del_sta_event23a(struct rtw_
 	return;
 }
 
-void report_add_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, int cam_idx)
+void report_add_sta_event23a(struct rtw_adapter *padapter,
+			     unsigned char* MacAddr, int cam_idx)
 {
 	struct cmd_obj *pcmd_obj;
-	u8	*pevtcmd;
+	u8 *pevtcmd;
 	u32 cmdsz;
-	struct stassoc_event		*padd_sta_evt;
-	struct C2HEvent_Header	*pc2h_evt_hdr;
-	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct stassoc_event *padd_sta_evt;
+	struct C2HEvent_Header *pc2h_evt_hdr;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-	pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-					     GFP_ATOMIC);
+	pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!pcmd_obj)
 		return;
 
@@ -5329,8 +4988,8 @@ Following are the event callback functio
 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
 {
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
-	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	/* ERP */
 	VCS_update23a(padapter, psta);
@@ -5342,7 +5001,7 @@ void update_sta_info23a(struct rtw_adapt
 
 		psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
 
-		if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
+		if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
 			psta->htpriv.sgi = true;
 
 		psta->qos_option = true;
@@ -5371,13 +5030,14 @@ void update_sta_info23a(struct rtw_adapt
 	psta->state = _FW_LINKED;
 }
 
-void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res)
+void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
+				       int join_res)
 {
-	struct sta_info		*psta, *psta_bmc;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct sta_info *psta, *psta_bmc;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
-	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct sta_priv *pstapriv = &padapter->stapriv;
 
 	if (join_res < 0) {
 		hw_var_set_mlme_join(padapter, 1);
@@ -5390,7 +5050,7 @@ void mlmeext_joinbss_event_callback23a(s
 		goto exit_mlmeext_joinbss_event_callback23a;
 	}
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+	if ((pmlmeinfo->state&0x03) == MSR_ADHOC)
 	{
 		/* for bc/mc */
 		psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
@@ -5413,7 +5073,7 @@ void mlmeext_joinbss_event_callback23a(s
 	/* BCN interval */
 	rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
 
-	/* udpate capability */
+	/* update capability */
 	update_capinfo23a(padapter, pmlmeinfo->capability);
 
 	/* WMM, Update EDCA param */
@@ -5440,7 +5100,7 @@ void mlmeext_joinbss_event_callback23a(s
 
 	hw_var_set_mlme_join(padapter, 2);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
+	if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
 		/*  correcting TSF */
 		rtw_correct_TSF(padapter);
 
@@ -5453,14 +5113,15 @@ exit_mlmeext_joinbss_event_callback23a:
 	DBG_8723A("=>%s\n", __func__);
 }
 
-void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta)
+void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
+				       struct sta_info *psta)
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	DBG_8723A("%s\n", __func__);
 
-	if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+	if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
 	/* adhoc master or sta_count>1 */
 		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
 		{
@@ -5473,7 +5134,7 @@ void mlmeext_sta_add_event_callback23a(s
 			if (send_beacon23a(padapter) != _SUCCESS) {
 				pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
 
-				pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
+				pmlmeinfo->state ^= MSR_ADHOC;
 
 				return;
 			}
@@ -5518,10 +5179,10 @@ void mlmeext_sta_del_event_callback23a(s
 
 		flush_all_cam_entry23a(padapter);
 
-		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		pmlmeinfo->state = MSR_NOLINK;
 
 		/* set MSR to no link state -> infra. mode */
-		Set_MSR23a(padapter, _HW_STATE_STATION_);
+		rtl8723a_set_media_status(padapter, MSR_INFRA);
 
 		del_timer_sync(&pmlmeext->link_timer);
 	}
@@ -5551,8 +5212,6 @@ void linked_status_chk23a(struct rtw_ada
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 
-	rtl8723a_sreset_linked_status_check(padapter);
-
 	if (is_client_associated_to_ap23a(padapter)) {
 		/* linked infrastructure client mode */
 
@@ -5699,13 +5358,12 @@ static void survey_timer_hdl(unsigned lo
 			pmlmeext->scan_abort = false;/* reset */
 		}
 
-		ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-			GFP_ATOMIC);
+		ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 		if (!ph2c)
 			goto exit_survey_timer_hdl;
 
-		psurveyPara = (struct sitesurvey_parm*)
-			kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
+		psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
+					GFP_ATOMIC);
 		if (!psurveyPara) {
 			kfree(ph2c);
 			goto exit_survey_timer_hdl;
@@ -5726,13 +5384,13 @@ static void link_timer_hdl(unsigned long
 	/* static unsigned int		rx_pkt = 0; */
 	/* static u64				tx_cnt = 0; */
 	/* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	/* struct sta_priv		*pstapriv = &padapter->stapriv; */
 
 	if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 		DBG_8723A("link_timer_hdl:no beacon while connecting\n");
-		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		pmlmeinfo->state = MSR_NOLINK;
 		report_join_res23a(padapter, -3);
 	} else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
 		/* re-auth timer */
@@ -5757,7 +5415,7 @@ static void link_timer_hdl(unsigned long
 	} else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
 		/* re-assoc timer */
 		if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
-			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			pmlmeinfo->state = MSR_NOLINK;
 			report_join_res23a(padapter, -2);
 			return;
 		}
@@ -5773,14 +5431,14 @@ static void link_timer_hdl(unsigned long
 static void addba_timer_hdl(unsigned long data)
 {
 	struct sta_info *psta = (struct sta_info *)data;
-	struct ht_priv	*phtpriv;
+	struct ht_priv *phtpriv;
 
 	if (!psta)
 		return;
 
 	phtpriv = &psta->htpriv;
 
-	if (phtpriv->ht_option == true && phtpriv->ampdu_enable == true) {
+	if (phtpriv->ht_option && phtpriv->ampdu_enable) {
 		if (phtpriv->candidate_tid_bitmap)
 			phtpriv->candidate_tid_bitmap = 0x0;
 	}
@@ -5794,7 +5452,7 @@ void init_addba_retry_timer23a(struct st
 
 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
 {
-	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
 	setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
 		    (unsigned long)padapter);
@@ -5818,22 +5476,22 @@ int setopmode_hdl23a(struct rtw_adapter
 	switch (psetop->mode) {
 	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_AP:
-		pmlmeinfo->state = WIFI_FW_AP_STATE;
-		type = _HW_STATE_AP_;
+		pmlmeinfo->state = MSR_AP;
+		type = MSR_AP;
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
 		/*  clear state */
 		pmlmeinfo->state &= ~(BIT(0)|BIT(1));
 		/* set to STATION_STATE */
-		pmlmeinfo->state |= WIFI_FW_STATION_STATE;
-		type = _HW_STATE_STATION_;
+		pmlmeinfo->state |= MSR_INFRA;
+		type = MSR_INFRA;
 		break;
 	case NL80211_IFTYPE_ADHOC:
-		type = _HW_STATE_ADHOC_;
+		type = MSR_ADHOC;
 		break;
 	default:
-		type = _HW_STATE_NOLINK_;
+		type = MSR_NOLINK;
 		break;
 	}
 
@@ -5845,7 +5503,7 @@ int setopmode_hdl23a(struct rtw_adapter
 
 int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
 {
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 	const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
@@ -5854,7 +5512,7 @@ int createbss_hdl23a(struct rtw_adapter
 	if (pparm->ifmode == NL80211_IFTYPE_AP ||
 	    pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
 #ifdef CONFIG_8723AU_AP_MODE
-		if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
+		if (pmlmeinfo->state == MSR_AP) {
 			/* todo: */
 			return H2C_SUCCESS;
 		}
@@ -5903,20 +5561,19 @@ int join_cmd_hdl23a(struct rtw_adapter *
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 	const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
-	struct HT_info_element *pht_info;
+	struct ieee80211_ht_operation *pht_info;
 	u32 i;
-	int bcn_fixed_size;
 	u8 *p;
         /* u32	initialgain; */
 	/* u32	acparm; */
 
 	/* check already connecting to AP or not */
 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
-		if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
+		if (pmlmeinfo->state & MSR_INFRA)
 			issue_deauth_ex(padapter, pnetwork->MacAddress,
 					WLAN_REASON_DEAUTH_LEAVING, 5, 100);
 
-		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		pmlmeinfo->state = MSR_NOLINK;
 
 		/* clear CAM */
 		flush_all_cam_entry23a(padapter);
@@ -5924,8 +5581,7 @@ int join_cmd_hdl23a(struct rtw_adapter *
 		del_timer_sync(&pmlmeext->link_timer);
 
 		/* set MSR to nolink -> infra. mode */
-		/* Set_MSR23a(padapter, _HW_STATE_NOLINK_); */
-		Set_MSR23a(padapter, _HW_STATE_STATION_);
+		rtl8723a_set_media_status(padapter, MSR_INFRA);
 
 		hw_var_set_mlme_disconnect(padapter);
 	}
@@ -5951,10 +5607,7 @@ int join_cmd_hdl23a(struct rtw_adapter *
 	/* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
 	   pnetwork->IELength); */
 
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	for (i = bcn_fixed_size; i < pnetwork->IELength;) {
+	for (i = 0; i < pnetwork->IELength;) {
 		p = pnetwork->IEs + i;
 
 		switch (p[0]) {
@@ -5972,20 +5625,21 @@ int join_cmd_hdl23a(struct rtw_adapter *
 
 			/* spec case only for cisco's ap because cisco's ap
 			 * issue assoc rsp using mcs rate @40MHz or @20MHz */
-			pht_info = (struct HT_info_element *)(p + 2);
+			pht_info = (struct ieee80211_ht_operation *)(p + 2);
 
-			if ((pregpriv->cbw40_enable) &&
-			    (pht_info->infos[0] & BIT(2))) {
+			if (pregpriv->cbw40_enable &&
+			    (pht_info->ht_param &
+			     IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
 				/* switch to the 40M Hz mode according to AP */
 				pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
-				switch (pht_info->infos[0] & 0x3)
-				{
-				case 1:
+				switch (pht_info->ht_param &
+					IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+				case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 					pmlmeext->cur_ch_offset =
 						HAL_PRIME_CHNL_OFFSET_LOWER;
 					break;
 
-				case 3:
+				case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 					pmlmeext->cur_ch_offset =
 						HAL_PRIME_CHNL_OFFSET_UPPER;
 					break;
@@ -6033,7 +5687,7 @@ int disconnect_hdl23a(struct rtw_adapter
 
 	/* set_opmode_cmd(padapter, infra_client_with_mlme); */
 
-	/* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
+	/* pmlmeinfo->state = MSR_NOLINK; */
 
 	hw_var_set_mlme_disconnect(padapter);
 	hw_var_set_bssid(padapter, null_addr);
@@ -6041,14 +5695,14 @@ int disconnect_hdl23a(struct rtw_adapter
 	/* restore to initial setting. */
 	update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
 
-	if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE ||
-	    (pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
+	    (pmlmeinfo->state & 0x03) == MSR_AP)
 		rtl8723a_set_bcn_func(padapter, 0);	/* Stop BCN */
 
 	/* set MSR to no link state -> infra. mode */
-	Set_MSR23a(padapter, _HW_STATE_STATION_);
+	rtl8723a_set_media_status(padapter, MSR_INFRA);
 
-	pmlmeinfo->state = WIFI_FW_NULL_STATE;
+	pmlmeinfo->state = MSR_NOLINK;
 
 	/* switch to the 20M Hz mode after disconnect */
 	pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
@@ -6063,7 +5717,7 @@ int disconnect_hdl23a(struct rtw_adapter
 
 	rtw_free_uc_swdec_pending_queue23a(padapter);
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 static int
@@ -6074,7 +5728,7 @@ rtw_scan_ch_decision(struct rtw_adapter
 	int i, j;
 	int scan_ch_num = 0;
 	int set_idx;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
 	/* clear out first */
 	memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
@@ -6150,7 +5804,8 @@ int sitesurvey_cmd_hdl23a(struct rtw_ada
 		for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
 			if (pparm->ssid[i].ssid_len) {
 				memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
-				       pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
+				       pparm->ssid[i].ssid,
+				       IEEE80211_MAX_SSID_LEN);
 				pmlmeext->sitesurvey_res.ssid[i].ssid_len =
 					pparm->ssid[i].ssid_len;
 			} else {
@@ -6196,7 +5851,7 @@ int sitesurvey_cmd_hdl23a(struct rtw_ada
 		rtl8723a_odm_support_ability_clr(padapter,
 						 DYNAMIC_FUNC_DISABLE);
 
-		/* config the initial gain under scaning, need to
+		/* config the initial gain under scanning, need to
 		   write the BB registers */
 		if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
 			initialgain = 0x30;
@@ -6206,7 +5861,7 @@ int sitesurvey_cmd_hdl23a(struct rtw_ada
 		rtl8723a_set_initial_gain(padapter, initialgain);
 
 		/* set MSR to no link state */
-		Set_MSR23a(padapter, _HW_STATE_NOLINK_);
+		rtl8723a_set_media_status(padapter, MSR_NOLINK);
 
 		rtl8723a_mlme_sitesurvey(padapter, 1);
 
@@ -6227,7 +5882,7 @@ int setauth_hdl23a(struct rtw_adapter *p
 	if (pparm->mode < 4)
 		pmlmeinfo->auth_algo = pparm->mode;
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
@@ -6282,7 +5937,7 @@ int set_stakey_hdl23a(struct rtw_adapter
 	DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
 			"WEP104-5 TKIP-2 AES-4) camid:%d\n",
 			pparm->algorithm, cam_id);
-	if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+	if ((pmlmeinfo->state & 0x03) == MSR_AP) {
 		struct sta_info *psta;
 		struct sta_priv *pstapriv = &padapter->stapriv;
 
@@ -6352,11 +6007,11 @@ int add_ba_hdl23a(struct rtw_adapter *pa
 	psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
 
 	if (!psta)
-		return	H2C_SUCCESS;
+		return H2C_SUCCESS;
 
 	if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
 	     pmlmeinfo->HT_enable) ||
-	    (pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+	    (pmlmeinfo->state & 0x03) == MSR_AP) {
 		issue_action_BA23a(padapter, pparm->addr,
 				   WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
 		mod_timer(&psta->addba_retry_timer,
@@ -6364,27 +6019,26 @@ int add_ba_hdl23a(struct rtw_adapter *pa
 	} else
 		psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 int set_tx_beacon_cmd23a(struct rtw_adapter* padapter)
 {
 	struct cmd_obj *ph2c;
-	struct Tx_Beacon_param	*ptxBeacon_parm;
+	struct Tx_Beacon_param *ptxBeacon_parm;
 	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	u8 res = _SUCCESS;
 	int len_diff = 0;
 
-	ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!ph2c) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	ptxBeacon_parm = (struct Tx_Beacon_param *)
-		kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
+	ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
 	if (!ptxBeacon_parm) {
 		kfree(ph2c);
 		res = _FAIL;
@@ -6394,10 +6048,9 @@ int set_tx_beacon_cmd23a(struct rtw_adap
 	memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
 	       sizeof(struct wlan_bssid_ex));
 
-	len_diff = update_hidden_ssid(
-		ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
-		ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
-		pmlmeinfo->hidden_ssid_mode);
+	len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
+				      ptxBeacon_parm->network.IELength,
+				      pmlmeinfo->hidden_ssid_mode);
 	ptxBeacon_parm->network.IELength += len_diff;
 
 	init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
@@ -6512,7 +6165,7 @@ int tx_beacon_hdl23a(struct rtw_adapter
 int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
 {
 	const struct set_ch_parm *set_ch_parm;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
 	if (!pbuf)
 		return H2C_PARAMETERS_ERROR;
@@ -6530,13 +6183,13 @@ int set_ch_hdl23a(struct rtw_adapter *pa
 	set_channel_bwmode23a(padapter, set_ch_parm->ch,
 			      set_ch_parm->ch_offset, set_ch_parm->bw);
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
 {
 	const struct SetChannelPlan_param *setChannelPlan_param;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
 	if (!pbuf)
 		return H2C_PARAMETERS_ERROR;
@@ -6549,7 +6202,7 @@ int set_chplan_hdl23a(struct rtw_adapter
 	init_channel_list(padapter, pmlmeext->channel_set,
 			  pmlmeext->max_chan_nums, &pmlmeext->channel_list);
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
@@ -6561,12 +6214,12 @@ int led_blink_hdl23a(struct rtw_adapter
 
 	ledBlink_param = (struct LedBlink_param *)pbuf;
 
-	return	H2C_SUCCESS;
+	return H2C_SUCCESS;
 }
 
 int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
 {
-	return	H2C_REJECTED;
+	return H2C_REJECTED;
 }
 
 /*  TDLS_WRCR		: write RCR DATA BIT */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_pwrctrl.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_pwrctrl.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_pwrctrl.c	2014-09-28 17:29:07.000000000 -0400
@@ -114,7 +114,6 @@ int ips_leave23a(struct rtw_adapter * pa
 
 static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter)
 {
-	struct rtw_adapter *buddy = adapter->pbuddy_adapter;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
 
@@ -130,21 +129,6 @@ static bool rtw_pwr_unassociated_idle(st
 		goto exit;
 	}
 
-	/* consider buddy, if exist */
-	if (buddy) {
-		struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
-
-		if (check_fwstate(b_pmlmepriv,
-				  WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
-		    check_fwstate(b_pmlmepriv,
-				  WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
-		    check_fwstate(b_pmlmepriv, WIFI_AP_STATE) ||
-		    check_fwstate(b_pmlmepriv,
-				  WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)) {
-			goto exit;
-		}
-	}
-
 	if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
 		pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
 		DBG_8723A_LEVEL(_drv_always_,
@@ -166,35 +150,12 @@ void rtw_ps_processor23a(struct rtw_adap
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	enum rt_rf_power_state rfpwrstate;
 
 	pwrpriv->ps_processing = true;
 
 	if (pwrpriv->bips_processing == true)
 		goto exit;
 
-	if (padapter->pwrctrlpriv.bHWPwrPindetect) {
-		rfpwrstate = RfOnOffDetect23a(padapter);
-		DBG_8723A("@@@@- #2  %s ==> rfstate:%s\n", __func__,
-			  (rfpwrstate == rf_on)?"rf_on":"rf_off");
-
-		if (rfpwrstate!= pwrpriv->rf_pwrstate) {
-			if (rfpwrstate == rf_off) {
-				pwrpriv->change_rfpwrstate = rf_off;
-				pwrpriv->brfoffbyhw = true;
-				padapter->bCardDisableWOHSM = true;
-				rtw_hw_suspend23a(padapter);
-			} else {
-				pwrpriv->change_rfpwrstate = rf_on;
-				rtw_hw_resume23a(padapter);
-			}
-			DBG_8723A("current rf_pwrstate(%s)\n",
-				  (pwrpriv->rf_pwrstate == rf_off) ?
-				  "rf_off":"rf_on");
-		}
-		pwrpriv->pwr_state_check_cnts ++;
-	}
-
 	if (pwrpriv->ips_mode_req == IPS_NONE)
 		goto exit;
 
@@ -515,7 +476,7 @@ inline void rtw_set_ips_deny23a(struct r
 /*
 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
 * @adapter: pointer to _adapter structure
-* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
 * Return _SUCCESS or _FAIL
 */
 
@@ -631,19 +592,16 @@ int rtw_pm_set_ips23a(struct rtw_adapter
 {
 	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
 
-	if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
-		rtw_ips_mode_req(pwrctrlpriv, mode);
-		DBG_8723A("%s %s\n", __func__,
-			  mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
-		return 0;
-	} else if (mode == IPS_NONE) {
-		rtw_ips_mode_req(pwrctrlpriv, mode);
+	if (mode != IPS_NORMAL && mode != IPS_LEVEL_2 && mode != IPS_NONE)
+		return -EINVAL;
+
+	pwrctrlpriv->ips_mode_req = mode;
+	if (mode == IPS_NONE) {
 		DBG_8723A("%s %s\n", __func__, "IPS_NONE");
 		if (padapter->bSurpriseRemoved == 0 &&
 		    rtw_pwr_wakeup(padapter) == _FAIL)
 			return -EFAULT;
-	} else
-		return -EINVAL;
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_recv.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_recv.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_recv.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_recv.c	2014-09-28 17:29:07.000000000 -0400
@@ -1185,7 +1185,7 @@ static int validate_recv_ctrl_frame(stru
 
 					/* DBG_8723A("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon23a(padapter, WLAN_EID_TIM,
 							 NULL, false);
@@ -1217,7 +1217,7 @@ static int validate_recv_ctrl_frame(stru
 
 					pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon23a(padapter, WLAN_EID_TIM,
 							 NULL, false);
@@ -2363,7 +2363,7 @@ void rtw_signal_stat_timer_hdl23a(unsign
 				recvpriv->signal_strength_data.avg_val;
 			num_signal_strength =
 				recvpriv->signal_strength_data.total_num;
-			/*  after avg_vals are accquired, we can re-stat */
+			/*  after avg_vals are acquired, we can re-stat */
 			/* the signal values */
 			recvpriv->signal_strength_data.update_req = 1;
 		}
@@ -2372,7 +2372,7 @@ void rtw_signal_stat_timer_hdl23a(unsign
 			/*  update_req is clear, means we got rx */
 			avg_signal_qual = recvpriv->signal_qual_data.avg_val;
 			num_signal_qual = recvpriv->signal_qual_data.total_num;
-			/*  after avg_vals are accquired, we can re-stat */
+			/*  after avg_vals are acquired, we can re-stat */
 			/*the signal values */
 			recvpriv->signal_qual_data.update_req = 1;
 		}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_sreset.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_sreset.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_sreset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_sreset.c	2014-09-28 17:29:07.000000000 -0400
@@ -23,7 +23,6 @@ void rtw_sreset_init(struct rtw_adapter
 
 	mutex_init(&psrtpriv->silentreset_mutex);
 	psrtpriv->silent_reset_inprogress = false;
-	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
 	psrtpriv->last_tx_time = 0;
 	psrtpriv->last_tx_complete_time = 0;
 }
@@ -34,54 +33,10 @@ void rtw_sreset_reset_value(struct rtw_a
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
 
 	psrtpriv->silent_reset_inprogress = false;
-	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
 	psrtpriv->last_tx_time = 0;
 	psrtpriv->last_tx_complete_time = 0;
 }
 
-u8 rtw_sreset_get_wifi_status(struct rtw_adapter *padapter)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
-	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-	u8 status = WIFI_STATUS_SUCCESS;
-	u32 val32 = 0;
-
-	if (psrtpriv->silent_reset_inprogress)
-		return status;
-	val32 = rtl8723au_read32(padapter, REG_TXDMA_STATUS);
-	if (val32 == 0xeaeaeaea) {
-		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
-	} else if (val32 != 0) {
-		DBG_8723A("txdmastatu(%x)\n", val32);
-		psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
-	}
-
-	if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
-		DBG_8723A("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
-		status = (psrtpriv->Wifi_Error_Status &~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
-	}
-	DBG_8723A("==> %s wifi_status(0x%x)\n", __func__, status);
-
-	/* status restore */
-	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
-
-	return status;
-}
-
-void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status)
-{
-	struct hal_data_8723a	*pHalData = GET_HAL_DATA(padapter);
-
-	pHalData->srestpriv.Wifi_Error_Status = status;
-}
-
-void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp)
-{
-	struct hal_data_8723a	*pHalData = GET_HAL_DATA(padapter);
-
-	pHalData->srestpriv.dbg_trigger_point = tgp;
-}
-
 bool rtw_sreset_inprogress(struct rtw_adapter *padapter)
 {
 	struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter);
@@ -148,7 +103,7 @@ static void sreset_restore_network_stati
 	hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
 	hw_var_set_mlme_join(padapter, 0);
 
-	Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
+	rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
 
 	mlmeext_joinbss_event_callback23a(padapter, 1);
 	/* restore Sequence No. */
@@ -242,8 +197,6 @@ void rtw_sreset_reset(struct rtw_adapter
 
 	DBG_8723A("%s\n", __func__);
 
-	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
-
 	mutex_lock(&psrtpriv->silentreset_mutex);
 	psrtpriv->silent_reset_inprogress = true;
 	pwrpriv->change_rfpwrstate = rf_off;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_sta_mgt.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_sta_mgt.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_sta_mgt.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,9 +22,11 @@
 #include <sta_info.h>
 #include <rtl8723a_hal.h>
 
+static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
 static void _rtw_init_stainfo(struct sta_info *psta)
 {
-	memset((u8 *)psta, 0, sizeof (struct sta_info));
+	memset((u8 *)psta, 0, sizeof(struct sta_info));
 	spin_lock_init(&psta->lock);
 	INIT_LIST_HEAD(&psta->list);
 	INIT_LIST_HEAD(&psta->hash_list);
@@ -69,8 +71,10 @@ int _rtw_init_sta_priv23a(struct sta_pri
 	pstapriv->auth_list_cnt = 0;
 	pstapriv->auth_to = 3; /*  3*2 = 6 sec */
 	pstapriv->assoc_to = 3;
-	/* pstapriv->expire_to = 900;  900*2 = 1800 sec = 30 min, expire after no any traffic. */
-	/* pstapriv->expire_to = 30;  30*2 = 60 sec = 1 min, expire after no any traffic. */
+	/* pstapriv->expire_to = 900;  900*2 = 1800 sec = 30 min,
+	    expire after no any traffic. */
+	/* pstapriv->expire_to = 30;  30*2 = 60 sec = 1 min,
+	    expire after no any traffic. */
 	pstapriv->expire_to = 3; /*  3*2 = 6 sec */
 	pstapriv->max_num_sta = NUM_STA;
 #endif
@@ -92,6 +96,7 @@ int _rtw_free_sta_priv23a(struct sta_pri
 
 			list_for_each_safe(plist, ptmp, phead) {
 				int i;
+
 				psta = container_of(plist, struct sta_info,
 						    hash_list);
 				for (i = 0; i < 16 ; i++) {
@@ -107,7 +112,7 @@ int _rtw_free_sta_priv23a(struct sta_pri
 }
 
 struct sta_info *
-rtw_alloc_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr, gfp_t gfp)
+rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp)
 {
 	struct list_head	*phash_list;
 	struct sta_info	*psta;
@@ -126,7 +131,7 @@ rtw_alloc_stainfo23a(struct sta_priv *ps
 
 	psta->padapter = pstapriv->padapter;
 
-	memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
+	ether_addr_copy(psta->hwaddr, hwaddr);
 
 	index = wifi_mac_hash(hwaddr);
 
@@ -142,14 +147,17 @@ rtw_alloc_stainfo23a(struct sta_priv *ps
 
 	list_add_tail(&psta->hash_list, phash_list);
 
-	pstapriv->asoc_sta_count ++ ;
+	pstapriv->asoc_sta_count++;
 
-/*  For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
-/*  In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
+/*  For the SMC router, the sequence number of first packet of WPS
+     handshake will be 0. */
+/*  In this case, this packet will be dropped by recv_decache function
+    if we use the 0x00 as the default value for tid_rxseq variable. */
 /*  So, we initialize the tid_rxseq variable as the 0xffff. */
 
 	for (i = 0; i < 16; i++)
-		memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
+		memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
+			&wRxSeqInitialValue, 2);
 
 	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
 		 ("alloc number_%d stainfo  with hwaddr = %pM\n",
@@ -240,8 +248,12 @@ int rtw_free_stainfo23a(struct rtw_adapt
 	spin_unlock_bh(&pxmitpriv->lock);
 
 	list_del_init(&psta->hash_list);
-	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n", pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5]));
-	pstapriv->asoc_sta_count --;
+	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
+		("\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
+			pstapriv->asoc_sta_count, psta->hwaddr[0],
+			psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3],
+			psta->hwaddr[4], psta->hwaddr[5]));
+	pstapriv->asoc_sta_count--;
 
 	/*  re-init sta_info; 20061114  will be init in alloc_stainfo */
 	/* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
@@ -249,7 +261,8 @@ int rtw_free_stainfo23a(struct rtw_adapt
 
 	del_timer_sync(&psta->addba_retry_timer);
 
-	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
+	/* for A-MPDU Rx reordering buffer control,
+	   cancel reordering_ctrl_timer */
 	for (i = 0; i < 16; i++) {
 		struct list_head	*phead, *plist;
 		struct recv_frame *prframe;
@@ -259,7 +272,8 @@ int rtw_free_stainfo23a(struct rtw_adapt
 
 		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 
-		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+		ppending_recvframe_queue =
+			&preorder_ctrl->pending_recvframe_queue;
 
 		spin_lock_bh(&ppending_recvframe_queue->lock);
 		phead =		get_list_head(ppending_recvframe_queue);
@@ -299,7 +313,7 @@ int rtw_free_stainfo23a(struct rtw_adapt
 	pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
 	pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 
-	if ((psta->aid >0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
+	if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
 		pstapriv->sta_aid[psta->aid - 1] = NULL;
 		psta->aid = 0;
 	}
@@ -316,7 +330,7 @@ void rtw_free_all_stainfo23a(struct rtw_
 	struct list_head *plist, *phead, *ptmp;
 	struct sta_info *psta;
 	struct sta_priv *pstapriv = &padapter->stapriv;
-	struct sta_info* pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
+	struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
 	s32 index;
 
 	if (pstapriv->asoc_sta_count == 1)
@@ -330,7 +344,7 @@ void rtw_free_all_stainfo23a(struct rtw_
 		list_for_each_safe(plist, ptmp, phead) {
 			psta = container_of(plist, struct sta_info, hash_list);
 
-			if (pbcmc_stainfo!= psta)
+			if (pbcmc_stainfo != psta)
 				rtw_free_stainfo23a(padapter, psta);
 		}
 	}
@@ -344,7 +358,6 @@ struct sta_info *rtw_get_stainfo23a(stru
 	struct sta_info *psta = NULL;
 	u32	index;
 	const u8 *addr;
-	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 	if (hwaddr == NULL)
 		return NULL;
@@ -363,25 +376,24 @@ struct sta_info *rtw_get_stainfo23a(stru
 	list_for_each(plist, phead) {
 		psta = container_of(plist, struct sta_info, hash_list);
 
-		if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
-			/*  if found the matched address */
+		/*  if found the matched address */
+		if (ether_addr_equal(psta->hwaddr, addr))
 			break;
-		}
+
 		psta = NULL;
 	}
 	spin_unlock_bh(&pstapriv->sta_hash_lock);
 	return psta;
 }
 
-int rtw_init_bcmc_stainfo23a(struct rtw_adapter* padapter)
+int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter)
 {
 	struct	sta_priv *pstapriv = &padapter->stapriv;
 	struct sta_info		*psta;
 	struct tx_servq	*ptxservq;
 	int res = _SUCCESS;
-	unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-	psta = rtw_alloc_stainfo23a(pstapriv, bcast_addr, GFP_KERNEL);
+	psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL);
 	if (psta == NULL) {
 		res = _FAIL;
 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
@@ -399,9 +411,8 @@ struct sta_info *rtw_get_bcmc_stainfo23a
 {
 	struct sta_info		*psta;
 	struct sta_priv		*pstapriv = &padapter->stapriv;
-	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-	 psta = rtw_get_stainfo23a(pstapriv, bc_addr);
+	psta = rtw_get_stainfo23a(pstapriv, bc_addr);
 	return psta;
 }
 
@@ -422,7 +433,7 @@ bool rtw_access_ctrl23a(struct rtw_adapt
 	list_for_each(plist, phead) {
 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 
-		if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
+		if (ether_addr_equal(paclnode->addr, mac_addr)) {
 			if (paclnode->valid) {
 				match = true;
 				break;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_wlan_util.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_wlan_util.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_wlan_util.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_wlan_util.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,6 +18,7 @@
 #include <drv_types.h>
 #include <linux/ieee80211.h>
 #include <wifi.h>
+#include <rtl8723a_spec.h>
 
 static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
 static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
@@ -293,11 +294,6 @@ void Update23aTblForSoftAP(u8 *bssratese
 	}
 }
 
-void Set_MSR23a(struct rtw_adapter *padapter, u8 type)
-{
-	rtl8723a_set_media_status(padapter, type);
-}
-
 inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
 {
 	return adapter_to_dvobj(adapter)->oper_channel;
@@ -360,10 +356,6 @@ void set_channel_bwmode23a(struct rtw_ad
 {
 	u8 center_ch;
 
-	if (padapter->bNotifyChannelChange)
-		DBG_8723A("[%s] ch = %d, offset = %d, bwmode = %d\n",
-			  __func__, channel, channel_offset, bwmode);
-
 	if (bwmode == HT_CHANNEL_WIDTH_20 ||
 	    channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
 		/* SelectChannel23a(padapter, channel); */
@@ -399,14 +391,6 @@ inline u8 *get_my_bssid23a(struct wlan_b
 	return pnetwork->MacAddress;
 }
 
-u16 get_beacon_interval23a(struct wlan_bssid_ex *bss)
-{
-	unsigned short val;
-	memcpy(&val, rtw_get_beacon_interval23a_from_ie(bss->IEs), 2);
-
-	return le16_to_cpu(val);
-}
-
 bool is_client_associated_to_ap23a(struct rtw_adapter *padapter)
 {
 	struct mlme_ext_priv *pmlmeext;
@@ -419,7 +403,7 @@ bool is_client_associated_to_ap23a(struc
 	pmlmeinfo = &pmlmeext->mlmext_info;
 
 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS &&
-	    (pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+	    (pmlmeinfo->state & 0x03) == MSR_INFRA)
 		return true;
 	else
 		return false;
@@ -431,7 +415,7 @@ bool is_client_associated_to_ibss23a(str
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS &&
-	    (pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)
+	    (pmlmeinfo->state & 0x03) == MSR_ADHOC)
 		return true;
 	else
 		return false;
@@ -461,11 +445,6 @@ unsigned int decide_wait_for_beacon_time
 		return bcn_interval << 2;
 }
 
-void invalidate_cam_all23a(struct rtw_adapter *padapter)
-{
-	rtl8723a_cam_invalid_all(padapter);
-}
-
 void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
 {
 	unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@@ -499,12 +478,12 @@ void flush_all_cam_entry23a(struct rtw_a
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
-	rtl8723a_cam_invalid_all(padapter);
+	rtl8723a_cam_invalidate_all(padapter);
 
 	memset(pmlmeinfo->FW_sta_info, 0, sizeof(pmlmeinfo->FW_sta_info));
 }
 
-int WMM_param_handler23a(struct rtw_adapter *padapter, u8 *p)
+int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p)
 {
 	/* struct registry_priv	*pregpriv = &padapter->registrypriv; */
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -633,9 +612,9 @@ void WMMOnAssocRsp23a(struct rtw_adapter
 	return;
 }
 
-static void bwmode_update_check(struct rtw_adapter *padapter, u8 *p)
+static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p)
 {
-	struct HT_info_element *pHT_info;
+	struct ieee80211_ht_operation *pHT_info;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -648,19 +627,20 @@ static void bwmode_update_check(struct r
 		return;
 	if (!phtpriv->ht_option)
 		return;
-	if (p[1] > sizeof(struct HT_info_element))
+	if (p[1] != sizeof(struct ieee80211_ht_operation))
 		return;
 
-	pHT_info = (struct HT_info_element *)(p + 2);
+	pHT_info = (struct ieee80211_ht_operation *)(p + 2);
 
-	if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
+	if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) &&
+	    pregistrypriv->cbw40_enable) {
 		new_bwmode = HT_CHANNEL_WIDTH_40;
 
-		switch (pHT_info->infos[0] & 0x3) {
-		case 1:
+		switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){
+		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 			new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 			break;
-		case 3:
+		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 			new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
 			break;
 		default:
@@ -711,7 +691,7 @@ static void bwmode_update_check(struct r
 	}
 }
 
-void HT_caps_handler23a(struct rtw_adapter *padapter, u8 *p)
+void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p)
 {
 	unsigned int i;
 	u8 rf_type;
@@ -720,60 +700,60 @@ void HT_caps_handler23a(struct rtw_adapt
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+	struct ieee80211_ht_cap *cap;
+	u8 *dstcap;
 
 	if (!p)
 		return;
 
-	if (phtpriv->ht_option == false)
+	if (!phtpriv->ht_option)
 		return;
 
 	pmlmeinfo->HT_caps_enable = 1;
 
+	cap = &pmlmeinfo->ht_cap;
+	dstcap = (u8 *)cap;
 	for (i = 0; i < p[1]; i++) {
 		if (i != 2) {
-			/*	Commented by Albert 2010/07/12 */
-			/*	Got the endian issue here. */
-			pmlmeinfo->HT_caps.u.HT_cap[i] &= p[i + 2];
+			dstcap[i] &= p[i + 2];
 		} else {
 			/* modify from  fw by Thomas 2010/11/17 */
-			if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (p[i + 2] & 0x3))
-				max_AMPDU_len = p[i + 2] & 0x3;
+			if ((cap->ampdu_params_info &
+			     IEEE80211_HT_AMPDU_PARM_FACTOR) >
+			    (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR))
+				max_AMPDU_len = p[i + 2] &
+					IEEE80211_HT_AMPDU_PARM_FACTOR;
 			else
-				max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3;
+				max_AMPDU_len = cap->ampdu_params_info &
+					IEEE80211_HT_AMPDU_PARM_FACTOR;
 
-			if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (p[i + 2] & 0x1c))
-				min_MPDU_spacing = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c;
+			if ((cap->ampdu_params_info &
+			     IEEE80211_HT_AMPDU_PARM_DENSITY) >
+			    (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY))
+				min_MPDU_spacing = cap->ampdu_params_info &
+					IEEE80211_HT_AMPDU_PARM_DENSITY;
 			else
-				min_MPDU_spacing = p[i + 2] & 0x1c;
+				min_MPDU_spacing = p[i + 2] &
+					IEEE80211_HT_AMPDU_PARM_DENSITY;
 
-			pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para =
+			cap->ampdu_params_info =
 				max_AMPDU_len | min_MPDU_spacing;
 		}
 	}
 
-	/*	Commented by Albert 2010/07/12 */
-	/*	Have to handle the endian issue after copying. */
-	/*	HT_ext_caps didn't be used yet. */
-	pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info =
-		le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
-	pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps =
-		le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps);
-
 	rf_type = rtl8723a_get_rf_type(padapter);
 
 	/* update the MCS rates */
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
 		if (rf_type == RF_1T1R || rf_type == RF_1T2R)
-			pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &=
-				MCS_rate_1R23A[i];
+			cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i];
 		else
-			pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &=
-				MCS_rate_2R23A[i];
+			cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i];
 	}
 	return;
 }
 
-void HT_info_handler23a(struct rtw_adapter *padapter, u8 *p)
+void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p)
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -783,10 +763,10 @@ void HT_info_handler23a(struct rtw_adapt
 	if (!p)
 		return;
 
-	if (phtpriv->ht_option == false)
+	if (!phtpriv->ht_option)
 		return;
 
-	if (p[1] > sizeof(struct HT_info_element))
+	if (p[1] != sizeof(struct ieee80211_ht_operation))
 		return;
 
 	pmlmeinfo->HT_info_enable = 1;
@@ -818,16 +798,18 @@ void HTOnAssocRsp23a(struct rtw_adapter
 		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
 		AMPDU_para [4:2]:Min MPDU Start Spacing
 	*/
-	max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+	max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info &
+		IEEE80211_HT_AMPDU_PARM_FACTOR;
 
 	min_MPDU_spacing =
-		(pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
+		(pmlmeinfo->ht_cap.ampdu_params_info &
+		 IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
 
 	rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
 	rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
 }
 
-void ERP_IE_handler23a(struct rtw_adapter *padapter, u8 *p)
+void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p)
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -881,110 +863,48 @@ int rtw_check_bcn_info23a(struct rtw_ada
 			  struct ieee80211_mgmt *mgmt, u32 pkt_len)
 {
 	struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
-	struct HT_info_element *pht_info;
-	struct ieee80211_ht_cap *pht_cap;
-	struct wlan_bssid_ex *bssid;
+	struct ieee80211_ht_operation *pht_info;
 	unsigned short val16;
-	u16 wpa_len = 0, rsn_len = 0;
-	u8 encryp_protocol;
+	u8 crypto, bcn_channel;
 	int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r;
-	u32 bcn_channel;
-	unsigned short ht_cap_info;
-	unsigned char ht_info_infos_0;
-	int len, pie_len, ie_offset;
-	const u8 *p;
-	u8 *pie;
+	int pie_len, ssid_len, privacy;
+	const u8 *p, *ssid;
 
 	if (is_client_associated_to_ap23a(Adapter) == false)
-		return true;
+		return _SUCCESS;
 
 	if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) {
 		printk(KERN_WARNING "%s: received a non beacon frame!\n",
 		       __func__);
-		return false;
-	}
-
-	len = pkt_len - sizeof(struct ieee80211_hdr_3addr);
-
-	if (len > MAX_IE_SZ) {
-		DBG_8723A("%s IE too long for survey event\n", __func__);
 		return _FAIL;
 	}
 
-	if (memcmp(cur_network->network.MacAddress, mgmt->bssid, 6)) {
-		DBG_8723A("Oops: rtw_check_network_encrypt linked but recv "
-			  "other bssid bcn\n" MAC_FMT MAC_FMT,
-			  MAC_ARG(mgmt->bssid),
+	if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) {
+		DBG_8723A("%s: linked but recv other bssid bcn"
+			  MAC_FMT MAC_FMT "\n", __func__, MAC_ARG(mgmt->bssid),
 			  MAC_ARG(cur_network->network.MacAddress));
-		return true;
-	}
-
-	bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
-	if (!bssid)
 		return _FAIL;
-
-	bssid->reserved = 1;
-
-	bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + len;
-
-	/* below is to copy the information element */
-	bssid->IELength = len;
-	memcpy(bssid->IEs, &mgmt->u, len);
+	}
 
 	/* check bw and channel offset */
 	/* parsing HT_CAP_IE */
-	ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u);
-	pie = bssid->IEs + ie_offset;
-	pie_len = pkt_len - ie_offset;
-
-	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
-	if (p && p[1] > 0) {
-		pht_cap = (struct ieee80211_ht_cap *)(p + 2);
-		ht_cap_info = pht_cap->cap_info;
-	} else {
-		pht_cap = NULL;
-		ht_cap_info = 0;
-	}
-
-	/* parsing HT_INFO_IE */
-	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, pie_len);
-	if (p && p[1] > 0) {
-		pht_info = (struct HT_info_element *)(p + 2);
-		ht_info_infos_0 = pht_info->infos[0];
-	} else {
-		pht_info = NULL;
-		ht_info_infos_0 = 0;
-	}
-
-	if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
-	    ((ht_info_infos_0 & 0x03) !=
-	     (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) {
-		DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n",
-			  __func__, ht_cap_info, ht_info_infos_0);
-		DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n",
-			  __func__, cur_network->BcnInfo.ht_cap_info,
-			  cur_network->BcnInfo.ht_info_infos_0);
-		DBG_8723A("%s bw mode change, disconnect\n", __func__);
-		/* bcn_info_update */
-		cur_network->BcnInfo.ht_cap_info = ht_cap_info;
-		cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
-		/* to do : need to check that whether modify related
-		   register of BB or not */
-	}
+	pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
 
 	/* Checking for channel */
-	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, pie, pie_len);
+	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
+			     pie_len);
 	if (p)
 		bcn_channel = p[2];
 	else {
 		/* In 5G, some ap do not have DSSET IE checking HT
 		   info for channel */
-		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, pie_len);
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+				     mgmt->u.beacon.variable, pie_len);
 
-		if (pht_info)
-			bcn_channel = pht_info->primary_channel;
-		else { /* we don't find channel IE, so don't check it */
+		if (p && p[1] > 0) {
+			pht_info = (struct ieee80211_ht_operation *)(p + 2);
+			bcn_channel = pht_info->primary_chan;
+		} else { /* we don't find channel IE, so don't check it */
 			DBG_8723A("Oops: %s we don't find channel IE, so don't "
 				  "check it\n", __func__);
 			bcn_channel = Adapter->mlmeextpriv.cur_channel;
@@ -998,76 +918,65 @@ int rtw_check_bcn_info23a(struct rtw_ada
 	}
 
 	/* checking SSID */
-	p = cfg80211_find_ie(WLAN_EID_SSID, pie, pie_len);
+	p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len);
 	if (p && p[1]) {
-		memcpy(bssid->Ssid.ssid, p + 2, p[1]);
-		bssid->Ssid.ssid_len = p[1];
+		ssid = p + 2;
+		ssid_len = p[1];
 	} else {
 		DBG_8723A("%s marc: cannot find SSID for survey event\n",
 			  __func__);
-		bssid->Ssid.ssid_len = 0;
-		bssid->Ssid.ssid[0] = '\0';
+		ssid = NULL;
+		ssid_len = 0;
 	}
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 		 ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
 		  "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
-		  bssid->Ssid.ssid, bssid->Ssid.ssid_len,
-		  cur_network->network.Ssid.ssid,
+		  ssid, ssid_len, cur_network->network.Ssid.ssid,
 		  cur_network->network.Ssid.ssid_len));
 
-	if (memcmp(bssid->Ssid.ssid, cur_network->network.Ssid.ssid, 32) ||
-	    bssid->Ssid.ssid_len != cur_network->network.Ssid.ssid_len) {
-		if (bssid->Ssid.ssid[0] != '\0' &&
-		    bssid->Ssid.ssid_len != 0) { /* not hidden ssid */
-			DBG_8723A("%s(), SSID is not match return FAIL\n",
-				  __func__);
-			goto _mismatch;
-		}
+	if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 ||
+	    (ssid_len &&
+	     memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) {
+		DBG_8723A("%s(), SSID is not match return FAIL\n", __func__);
+		goto _mismatch;
 	}
 
 	/* check encryption info */
-	val16 = rtw_get_capability23a(bssid);
+	val16 = le16_to_cpu(mgmt->u.beacon.capab_info);
 
-	if (val16 & BIT(4))
-		bssid->Privacy = 1;
+	if (val16 & WLAN_CAPABILITY_PRIVACY)
+		privacy = 1;
 	else
-		bssid->Privacy = 0;
+		privacy = 0;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 		 ("%s(): cur_network->network.Privacy is %d, bssid.Privacy "
-		  "is %d\n", __func__, cur_network->network.Privacy,
-		  bssid->Privacy));
-	if (cur_network->network.Privacy != bssid->Privacy) {
+		  "is %d\n", __func__, cur_network->network.Privacy, privacy));
+	if (cur_network->network.Privacy != privacy) {
 		DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
 		goto _mismatch;
 	}
 
-	rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL,
-			  &wpa_len);
-
-	if (rsn_len > 0)
-		encryp_protocol = ENCRYP_PROTOCOL_WPA2;
-	else if (wpa_len > 0)
-		encryp_protocol = ENCRYP_PROTOCOL_WPA;
-	else {
-		if (bssid->Privacy)
-			encryp_protocol = ENCRYP_PROTOCOL_WEP;
-		else
-			encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
-	}
-
-	if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-		DBG_8723A("%s(): enctyp is not match, return FAIL\n", __func__);
-		goto _mismatch;
-	}
-
-	if (encryp_protocol == ENCRYP_PROTOCOL_WPA ||
-	    encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
+	p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len);
+	if (p && p[1]) {
+		crypto = ENCRYP_PROTOCOL_WPA2;
+		if (p && p[1]) {
+			r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher,
+						 &pairwise_cipher, &is_8021x);
+			if (r == _SUCCESS)
+				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+					 ("%s pnetwork->pairwise_cipher: %d, "
+					  "pnetwork->group_cipher: %d, is_802x "
+					  ": %d\n", __func__, pairwise_cipher,
+					  group_cipher, is_8021x));
+			}
+	} else {
 		p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 					    WLAN_OUI_TYPE_MICROSOFT_WPA,
-					    pie, pie_len);
-		if (p && p[1] > 0) {
+					    mgmt->u.beacon.variable, pie_len);
+		if (p && p[1]) {
+			crypto = ENCRYP_PROTOCOL_WPA;
 			r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher,
 						&pairwise_cipher, &is_8021x);
 			if (r == _SUCCESS)
@@ -1077,24 +986,19 @@ int rtw_check_bcn_info23a(struct rtw_ada
 					  "%d\n", __func__, pairwise_cipher,
 					  group_cipher, is_8021x));
 		} else {
-			p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
-
-			if (p && p[1] > 0) {
-				r = rtw_parse_wpa2_ie23a(p, p[1] + 2,
-							 &group_cipher,
-							 &pairwise_cipher,
-							 &is_8021x);
-				if (r == _SUCCESS)
-					RT_TRACE(_module_rtl871x_mlme_c_,
-						 _drv_info_,
-						 ("%s pnetwork->pairwise_cipher"
-						  ": %d, pnetwork->group_cipher"
-						  " is %d, is_802x is %d\n",
-						  __func__, pairwise_cipher,
-						  group_cipher, is_8021x));
-			}
+			if (privacy)
+				crypto = ENCRYP_PROTOCOL_WEP;
+			else
+				crypto = ENCRYP_PROTOCOL_OPENSYS;
 		}
+	}
+
+	if (cur_network->BcnInfo.encryp_protocol != crypto) {
+		DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__);
+		goto _mismatch;
+	}
 
+	if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) {
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
 			 ("%s cur_network->group_cipher is %d: %d\n", __func__,
 			  cur_network->BcnInfo.group_cipher, group_cipher));
@@ -1116,41 +1020,31 @@ int rtw_check_bcn_info23a(struct rtw_ada
 		}
 	}
 
-	kfree(bssid);
 	return _SUCCESS;
 
 _mismatch:
-	kfree(bssid);
 
 	return _FAIL;
 }
 
-void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe,
+void update_beacon23a_info(struct rtw_adapter *padapter,
+			   struct ieee80211_mgmt *mgmt,
 			   uint pkt_len, struct sta_info *psta)
 {
-	unsigned int i;
 	unsigned int len;
-	u8 *p;
+	const u8 *p;
 
-	len = pkt_len -
-		(_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr));
+	len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
 
-	for (i = 0; i < len;) {
-		p = (u8 *)(pframe + (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr)) + i);
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable,
+			     len);
+	if (p)
+		bwmode_update_check(padapter, p);
 
-		switch (p[0]) {
-		case WLAN_EID_HT_OPERATION:	/* HT info */
-			/* HT_info_handler23a(padapter, pIE); */
-			bwmode_update_check(padapter, p);
-			break;
-		case WLAN_EID_ERP_INFO:
-			ERP_IE_handler23a(padapter, p);
-			VCS_update23a(padapter, psta);
-			break;
-		default:
-			break;
-		}
-		i += (p[1] + 2);
+	p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len);
+	if (p) {
+		ERP_IE_handler23a(padapter, p);
+		VCS_update23a(padapter, psta);
 	}
 }
 
@@ -1161,13 +1055,9 @@ bool is_ap_in_tkip23a(struct rtw_adapter
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	const u8 *p;
-	int bcn_fixed_size;
 
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	if (rtw_get_capability23a(cur_network) & WLAN_CAPABILITY_PRIVACY) {
-		for (i = bcn_fixed_size; i < pmlmeinfo->network.IELength;) {
+	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
+		for (i = 0; i < pmlmeinfo->network.IELength;) {
 			p = pmlmeinfo->network.IEs + i;
 
 			switch (p[0]) {
@@ -1196,13 +1086,9 @@ bool should_forbid_n_rate23a(struct rtw_
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_bssid_ex  *cur_network = &pmlmepriv->cur_network.network;
 	const u8 *p;
-	int bcn_fixed_size;
-
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
 
-	if (rtw_get_capability23a(cur_network) & WLAN_CAPABILITY_PRIVACY) {
-		for (i = bcn_fixed_size; i < cur_network->IELength;) {
+	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
+		for (i = 0; i < cur_network->IELength;) {
 			p = cur_network->IEs + i;
 
 			switch (p[0]) {
@@ -1239,13 +1125,9 @@ bool is_ap_in_wep23a(struct rtw_adapter
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	const u8 *p;
-	int bcn_fixed_size;
 
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	if (rtw_get_capability23a(cur_network) & WLAN_CAPABILITY_PRIVACY) {
-		for (i = bcn_fixed_size; i < pmlmeinfo->network.IELength;) {
+	if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) {
+		for (i = 0; i < pmlmeinfo->network.IELength;) {
 			p = pmlmeinfo->network.IEs + i;
 
 			switch (p[0]) {
@@ -1340,18 +1222,18 @@ unsigned int update_supported_rate23a(un
 	return mask;
 }
 
-unsigned int update_MSC_rate23a(struct HT_caps_element *pHT_caps)
+unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps)
 {
 	unsigned int mask = 0;
 
-	mask = pHT_caps->u.HT_cap_element.MCS_rate[0] << 12 |
-		pHT_caps->u.HT_cap_element.MCS_rate[1] << 20;
+	mask = pHT_caps->mcs.rx_mask[0] << 12 |
+		pHT_caps->mcs.rx_mask[1] << 20;
 
 	return mask;
 }
 
 int support_short_GI23a(struct rtw_adapter *padapter,
-			struct HT_caps_element *pHT_caps)
+			struct ieee80211_ht_cap *pHT_caps)
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -1363,7 +1245,7 @@ int support_short_GI23a(struct rtw_adapt
 		return _FAIL;
 	bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
 
-	if (pHT_caps->u.HT_cap_element.HT_caps_info & (0x1 << bit_offset))
+	if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset))
 		return _SUCCESS;
 	else
 		return _FAIL;
@@ -1425,17 +1307,14 @@ void update_tx_basic_rate23a(struct rtw_
 
 unsigned char check_assoc_AP23a(u8 *pframe, uint len)
 {
-	int i, bcn_fixed_size;
+	int i;
 	u8 epigram_vendor_flag;
 	u8 ralink_vendor_flag;
 	const u8 *p;
 	epigram_vendor_flag = 0;
 	ralink_vendor_flag = 0;
 
-	bcn_fixed_size = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-		offsetof(struct ieee80211_mgmt, u.beacon);
-
-	for (i = bcn_fixed_size; i < len;) {
+	for (i = 0; i < len;) {
 		p = pframe + i;
 
 		switch (p[0]) {
@@ -1678,28 +1557,3 @@ void process_addba_req23a(struct rtw_ada
 			true : false;
 	}
 }
-
-static struct rtw_adapter *pbuddy_padapter;
-
-int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init)
-{
-	int status = _SUCCESS;
-
-	if (init) {
-		if (pbuddy_padapter == NULL) {
-			pbuddy_padapter = adapter;
-			DBG_8723A("%s(): pbuddy_padapter == NULL, "
-				  "Set pbuddy_padapter\n", __func__);
-		} else {
-			adapter->pbuddy_adapter = pbuddy_padapter;
-			pbuddy_padapter->pbuddy_adapter = adapter;
-			/*  clear global value */
-			pbuddy_padapter = NULL;
-			DBG_8723A("%s(): pbuddy_padapter exist, "
-				  "Exchange Information\n", __func__);
-		}
-	} else
-		pbuddy_padapter = NULL;
-
-	return status;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/core/rtw_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/core/rtw_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -1197,7 +1197,7 @@ int rtw_xmitframe_coalesce23a(struct rtw
 			mpdu_len -= pattrib->icv_len;
 
 		if (bmcst)
-			/*  don't do fragment to broadcat/multicast packets */
+			/*  don't do fragment to broadcast/multicast packets */
 			mem_sz = min_t(s32, data_len, pattrib->pktlen);
 		else
 			mem_sz = min_t(s32, data_len, mpdu_len);
@@ -2011,7 +2011,7 @@ int xmitframe_enqueue_for_sleeping_sta23
 
 			/* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
 
-			/* tx bc/mc packets after upate bcn */
+			/* tx bc/mc packets after update bcn */
 			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 
 			/* spin_unlock_bh(&psta->sleep_q.lock); */
@@ -2068,7 +2068,7 @@ int xmitframe_enqueue_for_sleeping_sta23
 				pstapriv->tim_bitmap |= CHKBIT(psta->aid);
 
 				if (psta->sleepq_len == 1) {
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					update_beacon23a(padapter, WLAN_EID_TIM,
 							 NULL, false);
 				}
@@ -2227,7 +2227,7 @@ void wakeup_sta_to_xmit23a(struct rtw_ad
 	if (psta->sleepq_len == 0) {
 		pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 
-		/* upate BCN for TIM IE */
+		/* update BCN for TIM IE */
 		update_mask = BIT(0);
 
 		if (psta->state&WIFI_SLEEP_STATE)
@@ -2274,7 +2274,7 @@ void wakeup_sta_to_xmit23a(struct rtw_ad
 			pstapriv->tim_bitmap &= ~BIT(0);
 			pstapriv->sta_dz_bitmap &= ~BIT(0);
 
-			/* upate BCN for TIM IE */
+			/* update BCN for TIM IE */
 			/* update_BCNTIM(padapter); */
 			update_mask |= BIT(1);
 		}
@@ -2348,7 +2348,7 @@ void xmit_delivery_enabled_frames23a(str
 		    (wmmps_ac)) {
 			pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 
-			/* upate BCN for TIM IE */
+			/* update BCN for TIM IE */
 			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 		}
 	}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/hal_com.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/hal_com.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/hal_com.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/hal_com.c	2014-09-28 17:29:07.000000000 -0400
@@ -567,8 +567,8 @@ void rtl8723a_mlme_sitesurvey(struct rtw
 		pmlmeinfo = &pmlmeext->mlmext_info;
 
 		if ((is_client_associated_to_ap23a(padapter) == true) ||
-		    ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
-		    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+		    ((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
+		    ((pmlmeinfo->state & 0x03) == MSR_AP)) {
 			/*  enable to rx data frame */
 			rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
 
@@ -669,16 +669,16 @@ void rtl8723a_cam_empty_entry(struct rtw
 		   ("rtl8723a_cam_empty_entry(): WRITE A4: %lx \n",
 		   ulContent));*/
 		/* delay_ms(40); */
-		rtl8723au_write32(padapter, RWCAM, ulCommand);
+		rtl8723au_write32(padapter, REG_CAMCMD, ulCommand);
 		/* RT_TRACE(COMP_SEC, DBG_LOUD,
 		   ("rtl8723a_cam_empty_entry(): WRITE A0: %lx \n",
 		   ulCommand));*/
 	}
 }
 
-void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
+void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter)
 {
-	rtl8723au_write32(padapter, RWCAM, BIT(31) | BIT(30));
+	rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30));
 }
 
 void rtl8723a_cam_write(struct rtw_adapter *padapter,
@@ -708,7 +708,7 @@ void rtl8723a_cam_write(struct rtw_adapt
 
 		rtl8723au_write32(padapter, WCAMI, val);
 		cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
-		rtl8723au_write32(padapter, RWCAM, cmd);
+		rtl8723au_write32(padapter, REG_CAMCMD, cmd);
 
 		/* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
 	}
@@ -818,24 +818,6 @@ void rtl8723a_set_rxdma_agg_pg_th(struct
 	rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
 }
 
-void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper)
-{
-	if (usNavUpper > HAL_8723A_NAV_UPPER_UNIT * 0xFF) {
-		RT_TRACE(_module_hal_init_c_, _drv_notice_,
-			 ("The setting value (0x%08X us) of NAV_UPPER "
-			  "is larger than (%d * 0xFF)!!!\n",
-			  usNavUpper, HAL_8723A_NAV_UPPER_UNIT));
-		return;
-	}
-
-	/*  The value of ((usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
-	    HAL_8723A_NAV_UPPER_UNIT) */
-	/*  is getting the upper integer. */
-	usNavUpper = (usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
-		HAL_8723A_NAV_UPPER_UNIT;
-	rtl8723au_write8(padapter, REG_NAV_UPPER, (u8) usNavUpper);
-}
-
 void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
 {
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
@@ -867,12 +849,10 @@ void rtl8723a_odm_support_ability_set(st
 {
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
-	if (val == DYNAMIC_ALL_FUNC_ENABLE) {
-		pHalData->dmpriv.DMFlag = pHalData->dmpriv.InitDMFlag;
+	if (val == DYNAMIC_ALL_FUNC_ENABLE)
 		pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
-	} else {
+	else
 		pHalData->odmpriv.SupportAbility |= val;
-	}
 }
 
 void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c	2014-09-28 17:29:07.000000000 -0400
@@ -564,163 +564,3 @@ void ODM_ReadAndConfig_PHY_REG_MP_8723A(
 		}
 	}
 }
-
-/******************************************************************************
-*                           PHY_REG_PG.TXT
-******************************************************************************/
-
-static u32 Array_PHY_REG_PG_8723A[] = {
-	0xE00, 0xFFFFFFFF, 0x0A0C0C0C,
-	0xE04, 0xFFFFFFFF, 0x02040608,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x0A0C0D0E,
-	0xE14, 0xFFFFFFFF, 0x02040608,
-	0xE18, 0xFFFFFFFF, 0x0A0C0D0E,
-	0xE1C, 0xFFFFFFFF, 0x02040608,
-	0x830, 0xFFFFFFFF, 0x0A0C0C0C,
-	0x834, 0xFFFFFFFF, 0x02040608,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x0A0C0D0E,
-	0x848, 0xFFFFFFFF, 0x02040608,
-	0x84C, 0xFFFFFFFF, 0x0A0C0D0E,
-	0x868, 0xFFFFFFFF, 0x02040608,
-	0xE00, 0xFFFFFFFF, 0x00000000,
-	0xE04, 0xFFFFFFFF, 0x00000000,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x00000000,
-	0xE14, 0xFFFFFFFF, 0x00000000,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x00000000,
-	0x834, 0xFFFFFFFF, 0x00000000,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x00000000,
-	0x848, 0xFFFFFFFF, 0x00000000,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-	0xE00, 0xFFFFFFFF, 0x04040404,
-	0xE04, 0xFFFFFFFF, 0x00020204,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x06060606,
-	0xE14, 0xFFFFFFFF, 0x00020406,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x04040404,
-	0x834, 0xFFFFFFFF, 0x00020204,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x06060606,
-	0x848, 0xFFFFFFFF, 0x00020406,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-	0xE00, 0xFFFFFFFF, 0x00000000,
-	0xE04, 0xFFFFFFFF, 0x00000000,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x00000000,
-	0xE14, 0xFFFFFFFF, 0x00000000,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x00000000,
-	0x834, 0xFFFFFFFF, 0x00000000,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x00000000,
-	0x848, 0xFFFFFFFF, 0x00000000,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-	0xE00, 0xFFFFFFFF, 0x00000000,
-	0xE04, 0xFFFFFFFF, 0x00000000,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x00000000,
-	0xE14, 0xFFFFFFFF, 0x00000000,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x00000000,
-	0x834, 0xFFFFFFFF, 0x00000000,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x00000000,
-	0x848, 0xFFFFFFFF, 0x00000000,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-	0xE00, 0xFFFFFFFF, 0x04040404,
-	0xE04, 0xFFFFFFFF, 0x00020204,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x00000000,
-	0xE14, 0xFFFFFFFF, 0x00000000,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x04040404,
-	0x834, 0xFFFFFFFF, 0x00020204,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x00000000,
-	0x848, 0xFFFFFFFF, 0x00000000,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-	0xE00, 0xFFFFFFFF, 0x00000000,
-	0xE04, 0xFFFFFFFF, 0x00000000,
-	0xE08, 0x0000FF00, 0x00000000,
-	0x86C, 0xFFFFFF00, 0x00000000,
-	0xE10, 0xFFFFFFFF, 0x00000000,
-	0xE14, 0xFFFFFFFF, 0x00000000,
-	0xE18, 0xFFFFFFFF, 0x00000000,
-	0xE1C, 0xFFFFFFFF, 0x00000000,
-	0x830, 0xFFFFFFFF, 0x00000000,
-	0x834, 0xFFFFFFFF, 0x00000000,
-	0x838, 0xFFFFFF00, 0x00000000,
-	0x86C, 0x000000FF, 0x00000000,
-	0x83C, 0xFFFFFFFF, 0x00000000,
-	0x848, 0xFFFFFFFF, 0x00000000,
-	0x84C, 0xFFFFFFFF, 0x00000000,
-	0x868, 0xFFFFFFFF, 0x00000000,
-};
-
-void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm)
-{
-	u32     hex = 0;
-	u32     i           = 0;
-	u8     platform    = 0x04;
-	u8     interfaceValue   = pDM_Odm->SupportInterface;
-	u8     board       = pDM_Odm->BoardType;
-	u32     ArrayLen    = sizeof(Array_PHY_REG_PG_8723A)/sizeof(u32);
-	u32 *Array       = Array_PHY_REG_PG_8723A;
-
-	hex += board;
-	hex += interfaceValue << 8;
-	hex += platform << 16;
-	hex += 0xFF000000;
-	for (i = 0; i < ArrayLen; i += 3) {
-		u32 v1 = Array[i];
-		u32 v2 = Array[i+1];
-		u32 v3 = Array[i+2];
-
-		/*  this line is a line of pure_body */
-		if (v1 < 0xCDCDCDCD) {
-			 odm_ConfigBB_PHY_REG_PG_8723A(pDM_Odm, v1, v2, v3);
-			 continue;
-		} else { /*  this line is the start of branch */
-			if (!CheckCondition(Array[i], hex)) {
-				/*  don't need the hw_body */
-				i += 2; /*  skip the pair of expression */
-				v1 = Array[i];
-				v2 = Array[i+1];
-				v3 = Array[i+2];
-				while (v2 != 0xDEAD) {
-					i += 3;
-					v1 = Array[i];
-					v2 = Array[i+1];
-					v3 = Array[i+1];
-				}
-			}
-		}
-	}
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c	2014-09-28 17:29:07.000000000 -0400
@@ -230,7 +230,7 @@ void ODM_ReadAndConfig_RadioA_1T_8723A(s
 
 		/*  This (offset, data) pair meets the condition. */
 		if (v1 < 0xCDCDCDCD) {
-			odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
+			odm_ConfigRFReg_8723A(pDM_Odm, v1, v2, RF_PATH_A, v1);
 			continue;
 		} else {
 			if (!CheckCondition(Array[i], hex)) {
@@ -247,7 +247,8 @@ void ODM_ReadAndConfig_RadioA_1T_8723A(s
 				while (v2 != 0xDEAD &&
 				       v2 != 0xCDEF &&
 				       v2 != 0xCDCD && i < ArrayLen - 2) {
-					odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
+					odm_ConfigRFReg_8723A(pDM_Odm, v1, v2,
+							      RF_PATH_A, v1);
 					READ_NEXT_PAIR(v1, v2, i);
 				}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm.c	2014-09-28 17:29:07.000000000 -0400
@@ -166,12 +166,10 @@ u8 CCKSwingTable_Ch1423A[CCK_TABLE_SIZE]
 /* START------------COMMON INFO RELATED--------------- */
 void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm);
 
-void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm);
+static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData);
 
 void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm);
 
-void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm);
-
 void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm);
 
 /* START---------------DIG--------------------------- */
@@ -179,7 +177,7 @@ void odm_FalseAlarmCounterStatistics23a(
 
 void odm_DIG23aInit(struct dm_odm_t *pDM_Odm);
 
-void odm_DIG23a(struct dm_odm_t *pDM_Odm);
+void odm_DIG23a(struct rtw_adapter *adapter);
 
 void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm);
 /* END---------------DIG--------------------------- */
@@ -210,18 +208,6 @@ void odm_RSSIMonitorCheck23aAP(struct dm
 void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm);
 void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm);
 
-void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm);
-
-void odm_SwAntDivInit_NIC(struct dm_odm_t *pDM_Odm);
-
-void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step);
-
-void odm_SwAntDivChkAntSwitchNIC(struct dm_odm_t *pDM_Odm,
-		u8 Step
-	);
-
-void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data);
-
 void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm);
 
 void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
@@ -238,16 +224,12 @@ void odm_TXPowerTrackingCheckMP(struct d
 
 void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm);
 
-void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm);
-void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
-
-void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm);
+static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm);
+static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
 
 #define		RxDefaultAnt1		0x65a9
 #define	RxDefaultAnt2		0x569a
 
-void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm);
-
 bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm,
  u32 OFDM_Ant1_Cnt,
  u32 OFDM_Ant2_Cnt,
@@ -261,8 +243,6 @@ void odm_SetRxIdleAnt(struct dm_odm_t *p
    bool   bDualPath
 );
 
-void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm);
-
 /* 3 Export Interface */
 
 /*  2011/09/21 MH Add to describe different team necessary resource allocate?? */
@@ -274,29 +254,24 @@ void ODM23a_DMInit(struct dm_odm_t *pDM_
 	odm_DIG23aInit(pDM_Odm);
 	odm_RateAdaptiveMaskInit23a(pDM_Odm);
 
-	if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
-		odm23a_DynBBPSInit(pDM_Odm);
-		odm_DynamicTxPower23aInit(pDM_Odm);
-		odm_TXPowerTrackingInit23a(pDM_Odm);
-		ODM_EdcaTurboInit23a(pDM_Odm);
-		if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV)	||
-		    (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV)	||
-		    (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
-			odm_InitHybridAntDiv23a(pDM_Odm);
-		else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
-			odm_SwAntDivInit(pDM_Odm);
-	}
+	odm23a_DynBBPSInit(pDM_Odm);
+	odm_DynamicTxPower23aInit(pDM_Odm);
+	odm_TXPowerTrackingInit23a(pDM_Odm);
+	ODM_EdcaTurboInit23a(pDM_Odm);
 }
 
 /*  2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
 /*  You can not add any dummy function here, be care, you can only use DM structure */
 /*  to perform any new ODM_DM. */
-void ODM_DMWatchdog23a(struct dm_odm_t *pDM_Odm)
+void ODM_DMWatchdog23a(struct rtw_adapter *adapter)
 {
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter);
+	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+	struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv;
+
 	/* 2012.05.03 Luke: For all IC series */
-	odm_CmnInfoHook_Debug23a(pDM_Odm);
 	odm_CmnInfoUpdate_Debug23a(pDM_Odm);
-	odm_CommonInfoSelfUpdate23a(pDM_Odm);
+	odm_CommonInfoSelfUpdate(pHalData);
 	odm_FalseAlarmCounterStatistics23a(pDM_Odm);
 	odm_RSSIMonitorCheck23a(pDM_Odm);
 
@@ -304,33 +279,25 @@ void ODM_DMWatchdog23a(struct dm_odm_t *
 	/* NeilChen--2012--08--24-- */
 	/* Fix Leave LPS issue */
 	if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/*  in LPS mode */
-	    (pDM_Odm->SupportICType & (ODM_RTL8723A))) {
+	    (pDM_Odm->SupportICType & ODM_RTL8723A)) {
 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG23a is in LPS mode\n"));
 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n"));
 			odm_DIG23abyRSSI_LPS(pDM_Odm);
 	} else {
-		odm_DIG23a(pDM_Odm);
+		odm_DIG23a(adapter);
 	}
 
 	odm_CCKPacketDetectionThresh23a(pDM_Odm);
 
-	if (*(pDM_Odm->pbPowerSaving))
+	if (pwrctrlpriv->bpower_saving)
 		return;
 
 	odm_RefreshRateAdaptiveMask23a(pDM_Odm);
 
 	odm_DynamicBBPowerSaving23a(pDM_Odm);
-	if ((pDM_Odm->AntDivType ==  CG_TRX_HW_ANTDIV)	||
-	    (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV)	||
-	    (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
-		odm_HwAntDiv23a(pDM_Odm);
-	else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
-		odm_SwAntDivChkAntSwitch(pDM_Odm, SWAW_STEP_PEAK);
 
-	if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
-		ODM_TXPowerTrackingCheck23a(pDM_Odm);
-	      odm_EdcaTurboCheck23a(pDM_Odm);
-	}
+	ODM_TXPowerTrackingCheck23a(pDM_Odm);
+	odm_EdcaTurboCheck23a(pDM_Odm);
 
 	odm_dtc(pDM_Odm);
 }
@@ -350,9 +317,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t
 	/*  */
 	switch	(CmnInfo) {
 	/*  Fixed ODM value. */
-	case	ODM_CMNINFO_ABILITY:
-		pDM_Odm->SupportAbility = (u32)Value;
-		break;
 	case	ODM_CMNINFO_PLATFORM:
 		break;
 	case	ODM_CMNINFO_INTERFACE:
@@ -373,9 +337,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t
 	case	ODM_CMNINFO_RF_TYPE:
 		pDM_Odm->RFType = (u8)Value;
 		break;
-	case    ODM_CMNINFO_RF_ANTENNA_TYPE:
-		pDM_Odm->AntDivType = (u8)Value;
-		break;
 	case	ODM_CMNINFO_BOARD_TYPE:
 		pDM_Odm->BoardType = (u8)Value;
 		break;
@@ -416,81 +377,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t
 
 }
 
-void ODM23a_CmnInfoHook(struct dm_odm_t *pDM_Odm,
-		enum odm_cmninfo CmnInfo,
-		void *pValue
-	)
-{
-	/*  Hook call by reference pointer. */
-	switch	(CmnInfo) {
-	/*  Dynamic call by reference pointer. */
-	case	ODM_CMNINFO_MAC_PHY_MODE:
-		pDM_Odm->pMacPhyMode = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_TX_UNI:
-		pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue;
-		break;
-	case	ODM_CMNINFO_RX_UNI:
-		pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue;
-		break;
-	case	ODM_CMNINFO_WM_MODE:
-		pDM_Odm->pWirelessMode = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_BAND:
-		pDM_Odm->pBandType = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_SEC_CHNL_OFFSET:
-		pDM_Odm->pSecChOffset = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_SEC_MODE:
-		pDM_Odm->pSecurity = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_BW:
-		pDM_Odm->pBandWidth = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_CHNL:
-		pDM_Odm->pChannel = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_DMSP_GET_VALUE:
-		pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_BUDDY_ADAPTOR:
-		pDM_Odm->pBuddyAdapter = (struct rtw_adapter **)pValue;
-		break;
-	case	ODM_CMNINFO_DMSP_IS_MASTER:
-		pDM_Odm->pbMasterOfDMSP = (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_SCAN:
-		pDM_Odm->pbScanInProcess = (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_POWER_SAVING:
-		pDM_Odm->pbPowerSaving = (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_ONE_PATH_CCA:
-		pDM_Odm->pOnePathCCA = (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_DRV_STOP:
-		pDM_Odm->pbDriverStopped =  (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_PNP_IN:
-		pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep =  (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_INIT_ON:
-		pDM_Odm->pinit_adpt_in_progress =  (bool *)pValue;
-		break;
-	case	ODM_CMNINFO_ANT_TEST:
-		pDM_Odm->pAntennaTest =  (u8 *)pValue;
-		break;
-	case	ODM_CMNINFO_NET_CLOSED:
-		pDM_Odm->pbNet_closed = (bool *)pValue;
-		break;
-	/* To remove the compiler warning, must add an empty default statement to handle the other values. */
-	default:
-		/* do nothing */
-		break;
-	}
-}
-
 void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo,
 				u16 Index, void *pValue)
 {
@@ -512,9 +398,6 @@ void ODM_CmnInfoUpdate23a(struct dm_odm_
 {
 	/*  This init variable may be changed in run time. */
 	switch	(CmnInfo) {
-	case	ODM_CMNINFO_ABILITY:
-		pDM_Odm->SupportAbility = (u32)Value;
-		break;
 	case	ODM_CMNINFO_RF_TYPE:
 		pDM_Odm->RFType = (u8)Value;
 		break;
@@ -549,32 +432,33 @@ void ODM_CmnInfoUpdate23a(struct dm_odm_
 void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm
 	)
 {
-	pDM_Odm->bCckHighPower = (bool) ODM_GetBBReg(pDM_Odm, 0x824, BIT(9));
-	pDM_Odm->RFPathRxEnable = (u8) ODM_GetBBReg(pDM_Odm, 0xc04, 0x0F);
-	if (pDM_Odm->SupportICType & (ODM_RTL8723A))
-		pDM_Odm->AntDivType = CGCS_RX_SW_ANTDIV;
+	pDM_Odm->bCckHighPower =
+		(bool) ODM_GetBBReg(pDM_Odm, rFPGA0_XA_HSSIParameter2, BIT(9));
+	pDM_Odm->RFPathRxEnable =
+		(u8) ODM_GetBBReg(pDM_Odm, rOFDM0_TRxPathEnable, 0x0F);
 
 	ODM_InitDebugSetting23a(pDM_Odm);
 }
 
-void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm)
+static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData)
 {
+	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
+	struct sta_info *pEntry;
 	u8 EntryCnt = 0;
 	u8 i;
-	struct sta_info *pEntry;
 
-	if (*(pDM_Odm->pBandWidth) == ODM_BW40M) {
-		if (*(pDM_Odm->pSecChOffset) == 1)
-			pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) - 2;
-		else if (*(pDM_Odm->pSecChOffset) == 2)
-			pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) + 2;
+	if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) {
+		if (pHalData->nCur40MhzPrimeSC == 1)
+			pDM_Odm->ControlChannel = pHalData->CurrentChannel - 2;
+		else if (pHalData->nCur40MhzPrimeSC == 2)
+			pDM_Odm->ControlChannel = pHalData->CurrentChannel + 2;
 	} else {
-		pDM_Odm->ControlChannel = *(pDM_Odm->pChannel);
+		pDM_Odm->ControlChannel = pHalData->CurrentChannel;
 	}
 
 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
 		pEntry = pDM_Odm->pODM_StaInfo[i];
-		if (IS_STA_VALID(pEntry))
+		if (pEntry)
 			EntryCnt++;
 	}
 	if (EntryCnt == 1)
@@ -603,21 +487,6 @@ void odm_CmnInfoInit_Debug23a(struct dm_
 
 }
 
-void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm)
-{
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoHook_Debug23a ==>\n"));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast =%llu\n", *(pDM_Odm->pNumTxBytesUnicast)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast =%llu\n", *(pDM_Odm->pNumRxBytesUnicast)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode = 0x%x\n", *(pDM_Odm->pWirelessMode)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset =%d\n", *(pDM_Odm->pSecChOffset)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity =%d\n", *(pDM_Odm->pSecurity)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth =%d\n", *(pDM_Odm->pBandWidth)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel =%d\n", *(pDM_Odm->pChannel)));
-
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess =%d\n", *(pDM_Odm->pbScanInProcess)));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving =%d\n", *(pDM_Odm->pbPowerSaving)));
-}
-
 void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm)
 {
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug23a ==>\n"));
@@ -655,7 +524,7 @@ void odm_DIG23abyRSSI_LPS(struct dm_odm_
 	u8 bFwCurrentInPSMode = false;
 	u8 CurrentIGI = pDM_Odm->RSSI_Min;
 
-	if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
+	if (!(pDM_Odm->SupportICType & ODM_RTL8723A))
 		return;
 
 	CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
@@ -723,15 +592,12 @@ void odm_DIG23aInit(struct dm_odm_t *pDM
 	pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
 	pDM_DigTable->bMediaConnect_0 = false;
 	pDM_DigTable->bMediaConnect_1 = false;
-
-	/* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
-	pDM_Odm->bDMInitialGainEnable = true;
-
 }
 
-void odm_DIG23a(struct dm_odm_t *pDM_Odm)
+void odm_DIG23a(struct rtw_adapter *adapter)
 {
-
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter);
+	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
 	struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
 	u8 DIG_Dynamic_MIN;
@@ -748,23 +614,17 @@ void odm_DIG23a(struct dm_odm_t *pDM_Odm
 		return;
 	}
 
-	if (*(pDM_Odm->pbScanInProcess)) {
+	if (adapter->mlmepriv.bScanInProcess) {
 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: In Scan Progress \n"));
 		return;
 	}
 
-	/* add by Neil Chen to avoid PSD is processing */
-	if (!pDM_Odm->bDMInitialGainEnable) {
-		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: PSD is Processing \n"));
-		return;
-	}
-
 	DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
 	FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
 	FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
 
 	/* 1 Boundary Decision */
-	if ((pDM_Odm->SupportICType & (ODM_RTL8723A)) &&
+	if ((pDM_Odm->SupportICType & ODM_RTL8723A) &&
 	    ((pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) || pDM_Odm->ExtLNA)) {
 		dm_dig_max = DM_DIG_MAX_NIC_HP;
 		dm_dig_min = DM_DIG_MIN_NIC_HP;
@@ -777,7 +637,7 @@ void odm_DIG23a(struct dm_odm_t *pDM_Odm
 
 	if (pDM_Odm->bLinked) {
 	      /* 2 8723A Series, offset need to be 10 */
-		if (pDM_Odm->SupportICType == (ODM_RTL8723A)) {
+		if (pDM_Odm->SupportICType == ODM_RTL8723A) {
 			/* 2 Upper Bound */
 			if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC)
 				pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
@@ -925,32 +785,36 @@ void odm_FalseAlarmCounterStatistics23a(
 	if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
 		return;
 
-	if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
-		/* hold ofdm counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
-
-		ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
-		FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
-		FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
-		ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
-		FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
-		FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
-		ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
-		FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
-		FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
-		ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
-		FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
+	/* hold ofdm counter */
+	 /* hold page C counter */
+	ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
+	/* hold page D counter */
+	ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
+	ret_value =
+		ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+	FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
+	FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
+	ret_value =
+		ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
+	FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
+	FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
+	ret_value =
+		ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
+	FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
+	FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
+	ret_value =
+		ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
+	FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
 
-		FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail +
-					     FalseAlmCnt->Cnt_Rate_Illegal +
-					     FalseAlmCnt->Cnt_Crc8_fail +
-					     FalseAlmCnt->Cnt_Mcs_fail +
-					     FalseAlmCnt->Cnt_Fast_Fsync +
-					     FalseAlmCnt->Cnt_SB_Search_fail;
-		/* hold cck counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
-		ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
+	FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail +
+		FalseAlmCnt->Cnt_Rate_Illegal +
+		FalseAlmCnt->Cnt_Crc8_fail +
+		FalseAlmCnt->Cnt_Mcs_fail +
+		FalseAlmCnt->Cnt_Fast_Fsync +
+		FalseAlmCnt->Cnt_SB_Search_fail;
+	/* hold cck counter */
+	ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
+	ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
 
 	ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
 	FalseAlmCnt->Cnt_Cck_fail = ret_value;
@@ -958,7 +822,8 @@ void odm_FalseAlarmCounterStatistics23a(
 	FalseAlmCnt->Cnt_Cck_fail +=  (ret_value & 0xff) << 8;
 
 	ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
-	FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
+	FalseAlmCnt->Cnt_CCK_CCA =
+		((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
 
 	FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
 				FalseAlmCnt->Cnt_SB_Search_fail +
@@ -968,7 +833,8 @@ void odm_FalseAlarmCounterStatistics23a(
 				FalseAlmCnt->Cnt_Mcs_fail +
 				FalseAlmCnt->Cnt_Cck_fail);
 
-	FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
+	FalseAlmCnt->Cnt_CCA_all =
+		FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
 
 	if (pDM_Odm->SupportICType >= ODM_RTL8723A) {
 		/* reset false alarm counter registers */
@@ -977,8 +843,10 @@ void odm_FalseAlarmCounterStatistics23a(
 		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
 		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
 		/* update ofdm counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); /* update page C counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); /* update page D counter */
+		 /* update page C counter */
+		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
+		 /* update page D counter */
+		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
 
 		/* reset CCK CCA counter */
 		ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N,
@@ -992,26 +860,20 @@ void odm_FalseAlarmCounterStatistics23a(
 			     BIT(15) | BIT(14), 2);
 	}
 
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Enter odm_FalseAlarmCounterStatistics23a\n"));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n",
-		FalseAlmCnt->Cnt_Fast_Fsync, FalseAlmCnt->Cnt_SB_Search_fail));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n",
-		FalseAlmCnt->Cnt_Parity_Fail, FalseAlmCnt->Cnt_Rate_Illegal));
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
-		FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
-	} else { /* FOR ODM_IC_11AC_SERIES */
-		/* read OFDM FA counter */
-		FalseAlmCnt->Cnt_Ofdm_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_11AC, bMaskLWord);
-		FalseAlmCnt->Cnt_Cck_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_11AC, bMaskLWord);
-		FalseAlmCnt->Cnt_all = FalseAlmCnt->Cnt_Ofdm_fail + FalseAlmCnt->Cnt_Cck_fail;
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+		     ("Enter odm_FalseAlarmCounterStatistics23a\n"));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+		     ("Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n",
+		      FalseAlmCnt->Cnt_Fast_Fsync,
+		      FalseAlmCnt->Cnt_SB_Search_fail));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+		     ("Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n",
+		      FalseAlmCnt->Cnt_Parity_Fail,
+		      FalseAlmCnt->Cnt_Rate_Illegal));
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+		     ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
+		      FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
 
-		/*  reset OFDM FA coutner */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
-		ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
-		/*  reset CCK FA counter */
-		ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
-		ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
-	}
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail));
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all));
@@ -1207,18 +1069,16 @@ void odm_RateAdaptiveMaskInit23a(struct
 	pOdmRA->LowRSSIThresh = 20;
 }
 
-u32 ODM_Get_Rate_Bitmap23a(struct dm_odm_t *pDM_Odm,
-	u32 macid,
-	u32 ra_mask,
-	u8 rssi_level)
+u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid,
+			   u32 ra_mask, u8 rssi_level)
 {
+	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
 	struct sta_info *pEntry;
 	u32 rate_bitmap = 0x0fffffff;
 	u8 WirelessMode;
-	/* u8 WirelessMode =*(pDM_Odm->pWirelessMode); */
 
 	pEntry = pDM_Odm->pODM_StaInfo[macid];
-	if (!IS_STA_VALID(pEntry))
+	if (!pEntry)
 		return ra_mask;
 
 	WirelessMode = pEntry->wireless_mode;
@@ -1252,7 +1112,8 @@ u32 ODM_Get_Rate_Bitmap23a(struct dm_odm
 			} else if (rssi_level == DM_RATR_STA_MIDDLE) {
 				rate_bitmap = 0x000ff000;
 			} else {
-				if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
+				if (pHalData->CurrentChannelBW ==
+				    HT_CHANNEL_WIDTH_40)
 					rate_bitmap = 0x000ff015;
 				else
 					rate_bitmap = 0x000ff005;
@@ -1263,7 +1124,8 @@ u32 ODM_Get_Rate_Bitmap23a(struct dm_odm
 			} else if (rssi_level == DM_RATR_STA_MIDDLE) {
 				rate_bitmap = 0x0f8ff000;
 			} else {
-				if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
+				if (pHalData->CurrentChannelBW ==
+				    HT_CHANNEL_WIDTH_40)
 					rate_bitmap = 0x0f8ff015;
 				else
 					rate_bitmap = 0x0f8ff005;
@@ -1340,7 +1202,7 @@ void odm_RefreshRateAdaptiveMask23aCE23a
 
 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
 		struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
-		if (IS_STA_VALID(pstat)) {
+		if (pstat) {
 			if (ODM_RAStateCheck23a(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
 				ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
 					     ("RSSI:%d, RSSI_LEVEL:%d\n",
@@ -1482,7 +1344,7 @@ void odm_RSSIMonitorCheck23aCE(struct dm
 
 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
 		psta = pDM_Odm->pODM_StaInfo[i];
-		if (IS_STA_VALID(psta)) {
+		if (psta) {
 			if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
 				tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
 
@@ -1568,52 +1430,8 @@ void odm_TXPowerTrackingCheckAP(struct d
 {
 }
 
-/* antenna mapping info */
-/*  1: right-side antenna */
-/*  2/0: left-side antenna */
-/* PpDM_SWAT_Table->CCK_Ant1_Cnt /OFDM_Ant1_Cnt:  for right-side antenna:   Ant:1    RxDefaultAnt1 */
-/* PpDM_SWAT_Table->CCK_Ant2_Cnt /OFDM_Ant2_Cnt:  for left-side antenna:     Ant:0    RxDefaultAnt2 */
-/*  We select left antenna as default antenna in initial process, modify it as needed */
-/*  */
-
-/* 3 ============================================================ */
-/* 3 SW Antenna Diversity */
-/* 3 ============================================================ */
-void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm)
-{
-}
-
-void ODM_SwAntDivChkPerPktRssi(struct dm_odm_t *pDM_Odm, u8 StationID,
-			       struct phy_info *pPhyInfo)
-{
-}
-
-void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step)
-{
-}
-
-void ODM_SwAntDivRestAfterLink(struct dm_odm_t *pDM_Odm)
-{
-}
-
-void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data)
-{
-}
-
-/* 3 ============================================================ */
-/* 3 SW Antenna Diversity */
-/* 3 ============================================================ */
-
-void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm)
-{
-}
-
-void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm)
-{
-}
-
 /* EDCA Turbo */
-void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm)
+static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm)
 {
 
 	struct rtw_adapter *Adapter = pDM_Odm->Adapter;
@@ -1628,40 +1446,31 @@ void ODM_EdcaTurboInit23a(struct dm_odm_
 
 }	/*  ODM_InitEdcaTurbo */
 
-void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
+static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
 {
+	struct rtw_adapter *Adapter = pDM_Odm->Adapter;
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
+	struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
+	struct recv_priv *precvpriv = &Adapter->recvpriv;
+	struct registry_priv *pregpriv = &Adapter->registrypriv;
+	struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+	u32 trafficIndex;
+	u32 edca_param;
+	u64 cur_tx_bytes = 0;
+	u64 cur_rx_bytes = 0;
+	u8 bbtchange = false;
+
 	/*  For AP/ADSL use struct rtl8723a_priv * */
 	/*  For CE/NIC use struct rtw_adapter * */
 
 	/*  2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
 	/*  at the same time. In the stage2/3, we need to prive universal interface and merge all */
 	/*  HW dynamic mechanism. */
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("odm_EdcaTurboCheck23a ========================>\n"));
 
 	if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
 		return;
 
-	odm_EdcaTurboCheck23aCE23a(pDM_Odm);
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<======================== odm_EdcaTurboCheck23a\n"));
-
-}	/*  odm_CheckEdcaTurbo */
-
-void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm)
-{
-	struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-	u32 trafficIndex;
-	u32 edca_param;
-	u64 cur_tx_bytes = 0;
-	u64 cur_rx_bytes = 0;
-	u8 bbtchange = false;
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-	struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
-	struct recv_priv *precvpriv = &Adapter->recvpriv;
-	struct registry_priv *pregpriv = &Adapter->registrypriv;
-	struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
-	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
 	if ((pregpriv->wifi_spec == 1))/*  (pmlmeinfo->HT_enable == 0)) */
 		goto dm_CheckEdcaTurbo_EXIT;
 
@@ -1836,7 +1645,7 @@ bool ODM_SingleDualAntennaDetection(stru
 		rSleep, rPMPD_ANAEN,
 		rFPGA0_XCD_SwitchControl, rBlue_Tooth};
 
-	if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
+	if (!(pDM_Odm->SupportICType & ODM_RTL8723A))
 		return bResult;
 
 	if (!(pDM_Odm->SupportAbility&ODM_BB_ANT_DIV))
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm_HWConfig.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm_HWConfig.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm_HWConfig.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm_HWConfig.c	2014-09-28 17:29:07.000000000 -0400
@@ -19,11 +19,6 @@
 
 #include "odm_precomp.h"
 
-#define READ_AND_CONFIG     READ_AND_CONFIG_MP
-
-#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(pDM_Odm))
-#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(pDM_Odm))
-
 static u8 odm_QueryRxPwrPercentage(s8 AntPower)
 {
 	if ((AntPower <= -100) || (AntPower >= 20))
@@ -296,7 +291,7 @@ static void odm_Process_RSSIForDM(struct
 		return;
 
 	pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID];
-	if (!IS_STA_VALID(pEntry))
+	if (!pEntry)
 		return;
 	if ((!pPktinfo->bPacketMatchBSSID))
 		return;
@@ -404,13 +399,8 @@ static void ODM_PhyStatusQuery23a_92CSer
 {
 	odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo,
 					 pPhyStatus, pPktinfo);
-	if (pDM_Odm->RSSI_test) {
-		/*  Select the packets to do RSSI checking for antenna switching. */
-		if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
-			ODM_SwAntDivChkPerPktRssi(pDM_Odm, pPktinfo->StationID, pPhyInfo);
-	} else {
-		odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
-	}
+
+	odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
 }
 
 void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct phy_info *pPhyInfo,
@@ -418,55 +408,3 @@ void ODM_PhyStatusQuery23a(struct dm_odm
 {
 	ODM_PhyStatusQuery23a_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
 }
-
-/*  For future use. */
-void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm, u8 *pMacStatus, u8 MacID,
-			bool bPacketMatchBSSID, bool bPacketToSelf,
-			bool bPacketBeacon)
-{
-	/*  2011/10/19 Driver team will handle in the future. */
-
-}
-
-int ODM_ConfigRFWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
-				  enum RF_RADIO_PATH Content,
-				  enum RF_RADIO_PATH eRFPath)
-{
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-		     ("===>ODM_ConfigRFWithHeaderFile23a\n"));
-	if (pDM_Odm->SupportICType == ODM_RTL8723A) {
-		if (eRFPath == RF_PATH_A)
-			READ_AND_CONFIG_MP(8723A, _RadioA_1T_);
-
-		ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-			     (" ===> ODM_ConfigRFWithHeaderFile23a() Radio_A:Rtl8723RadioA_1TArray\n"));
-		ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-			     (" ===> ODM_ConfigRFWithHeaderFile23a() Radio_B:Rtl8723RadioB_1TArray\n"));
-	}
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
-		     ("ODM_ConfigRFWithHeaderFile23a: Radio No %x\n", eRFPath));
-	return _SUCCESS;
-}
-
-int ODM_ConfigBBWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
-				  enum odm_bb_config_type ConfigType)
-{
-	if (pDM_Odm->SupportICType == ODM_RTL8723A) {
-		if (ConfigType == CONFIG_BB_PHY_REG)
-			READ_AND_CONFIG_MP(8723A, _PHY_REG_1T_);
-		else if (ConfigType == CONFIG_BB_AGC_TAB)
-			READ_AND_CONFIG_MP(8723A, _AGC_TAB_1T_);
-		ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-			     (" ===> phy_ConfigBBWithHeaderFile() phy:Rtl8723AGCTAB_1TArray\n"));
-		ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-			     (" ===> phy_ConfigBBWithHeaderFile() agc:Rtl8723PHY_REG_1TArray\n"));
-	}
-	return _SUCCESS;
-}
-
-int ODM_ConfigMACWithHeaderFile23a(struct dm_odm_t *pDM_Odm)
-{
-	if (pDM_Odm->SupportICType == ODM_RTL8723A)
-		READ_AND_CONFIG_MP(8723A, _MAC_REG_);
-	return _SUCCESS;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c	2014-09-28 17:29:07.000000000 -0400
@@ -43,36 +43,6 @@ odm_ConfigRFReg_8723A(
 	}
 }
 
-void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm,
-	u32					Addr,
-	u32					Data
-	)
-{
-	u32  content = 0x1000; /*  RF_Content: radioa_txt */
-	u32	maskforPhySet = (u32)(content&0xE000);
-
-	odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_A,
-			      Addr|maskforPhySet);
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-		     ("===> ODM_ConfigRFWithHeaderFile23a: [RadioA] %08X %08X\n",
-		     Addr, Data));
-}
-
-void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm,
-	u32					Addr,
-	u32					Data
-	)
-{
-	u32  content = 0x1001; /*  RF_Content: radiob_txt */
-	u32	maskforPhySet = (u32)(content&0xE000);
-
-	odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_B,
-			      Addr|maskforPhySet);
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-		     ("===> ODM_ConfigRFWithHeaderFile23a: [RadioB] %08X %08X\n",
-		     Addr, Data));
-}
-
 void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm,
 	u32		Addr,
 	u8		Data
@@ -102,34 +72,6 @@ odm_ConfigBB_AGC_8723A(
 }
 
 void
-odm_ConfigBB_PHY_REG_PG_8723A(
-	struct dm_odm_t *pDM_Odm,
-	u32		Addr,
-	u32		Bitmask,
-	u32		Data
-  )
-{
-	if (Addr == 0xfe)
-		msleep(50);
-	else if (Addr == 0xfd)
-		mdelay(5);
-	else if (Addr == 0xfc)
-		mdelay(1);
-	else if (Addr == 0xfb)
-		udelay(50);
-	else if (Addr == 0xfa)
-		udelay(5);
-	else if (Addr == 0xf9)
-		udelay(1);
-    /*  TODO: ODM_StorePwrIndexDiffRateOffset(...) */
-	/*  storePwrIndexDiffRateOffset(Adapter, Addr, Bitmask, Data); */
-
-	ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-		     ("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X %08X\n",
-		     Addr, Bitmask, Data));
-}
-
-void
 odm_ConfigBB_PHY_8723A(
 	struct dm_odm_t *pDM_Odm,
 	u32		Addr,
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c	2014-09-28 17:29:07.000000000 -0400
@@ -14,7 +14,6 @@
  ******************************************************************************/
 #include <drv_types.h>
 #include <rtl8723a_hal.h>
-#include <rtw_ioctl_set.h>
 #include <usb_ops_linux.h>
 
 #define DIS_PS_RX_BCN
@@ -5871,8 +5870,8 @@ btdm_1AntUpdateHalRAMask(struct rtw_adap
 		mask = update_supported_rate23a(cur_network->SupportedRates,
 						supportRateNum);
 		mask |= (pmlmeinfo->HT_enable) ?
-			update_MSC_rate23a(&pmlmeinfo->HT_caps):0;
-		if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
+			update_MSC_rate23a(&pmlmeinfo->ht_cap):0;
+		if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
 			shortGIrate = true;
 		break;
 	case 1:/* for broadcast/multicast */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,7 +18,6 @@
 #include <drv_types.h>
 #include <recv_osdep.h>
 #include <mlme_osdep.h>
-#include <rtw_ioctl_set.h>
 #include <rtl8723a_hal.h>
 #include <usb_ops_linux.h>
 
@@ -152,7 +151,8 @@ void rtl8723a_add_rateatid(struct rtw_ad
 
 	bitmap &= 0x0fffffff;
 	if (rssi_level != DM_RATR_STA_INIT)
-		bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
+		bitmap = ODM_Get_Rate_Bitmap23a(pHalData, macid, bitmap,
+						rssi_level);
 
 	bitmap |= ((raid<<28)&0xf0000000);
 
@@ -201,57 +201,45 @@ void rtl8723a_set_FwPwrMode_cmd(struct r
 
 }
 
-static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
+static void
+ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
 {
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	u32 rate_len, pktlen;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	int bcn_fixed_size;
 
 	/* DBG_8723A("%s\n", __func__); */
 
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
-	pwlanhdr->frame_control =
+	mgmt->frame_control =
 		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
 
-	memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
+	ether_addr_copy(mgmt->da, bc_addr);
+	ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
+	ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
 
 	/* A Beacon frame shouldn't have fragment bits set */
-	pwlanhdr->seq_ctrl = 0;
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pktlen = sizeof (struct ieee80211_hdr_3addr);
+	mgmt->seq_ctrl = 0;
 
 	/* timestamp will be inserted by hardware */
-	pframe += 8;
-	pktlen += 8;
 
-	/*  beacon interval: 2 bytes */
-	memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
-
-	pframe += 2;
-	pktlen += 2;
-
-	/*  capability info: 2 bytes */
-	memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
+	put_unaligned_le16(cur_network->beacon_interval,
+			   &mgmt->u.beacon.beacon_int);
 
-	pframe += 2;
-	pktlen += 2;
+	put_unaligned_le16(cur_network->capability,
+			   &mgmt->u.beacon.capab_info);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-		bcn_fixed_size =
-			offsetof(struct ieee80211_mgmt, u.beacon.variable) -
-			offsetof(struct ieee80211_mgmt, u.beacon);
+	pframe = mgmt->u.beacon.variable;
+	pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 
+	if ((pmlmeinfo->state&0x03) == MSR_AP) {
 		/* DBG_8723A("ie len =%d\n", cur_network->IELength); */
-		pktlen += cur_network->IELength - bcn_fixed_size;
-		memcpy(pframe, cur_network->IEs + bcn_fixed_size, pktlen);
+		pktlen += cur_network->IELength;
+		memcpy(pframe, cur_network->IEs, pktlen);
 
 		goto _ConstructBeacon;
 	}
@@ -272,7 +260,7 @@ static void ConstructBeacon(struct rtw_a
 	pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
 			       &cur_network->DSConfig, &pktlen);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+	if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
 		u32 ATIMWindow;
 		/*  IBSS Parameter Set... */
 		/* ATIMWindow = cur->ATIMWindow; */
@@ -406,7 +394,7 @@ ConstructNullFunctionData(struct rtw_ada
 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe,
 			      u32 *pLength, u8 *StaAddr, bool bHideSSID)
 {
-	struct ieee80211_hdr *pwlanhdr;
+	struct ieee80211_mgmt *mgmt;
 	u8 *mac, *bssid;
 	u32 pktlen;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -415,38 +403,39 @@ static void ConstructProbeRsp(struct rtw
 
 	/* DBG_8723A("%s\n", __func__); */
 
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+	mgmt = (struct ieee80211_mgmt *)pframe;
 
 	mac = myid(&padapter->eeprompriv);
 	bssid = cur_network->MacAddress;
 
-	pwlanhdr->frame_control =
+	mgmt->frame_control =
 		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
 
-	pwlanhdr->seq_ctrl = 0;
+	mgmt->seq_ctrl = 0;
 
-	memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
+	memcpy(mgmt->da, StaAddr, ETH_ALEN);
+	memcpy(mgmt->sa, mac, ETH_ALEN);
+	memcpy(mgmt->bssid, bssid, ETH_ALEN);
 
-	pktlen = sizeof(struct ieee80211_hdr_3addr);
-	pframe += pktlen;
+	put_unaligned_le64(cur_network->tsf,
+			   &mgmt->u.probe_resp.timestamp);
+	put_unaligned_le16(cur_network->beacon_interval,
+			   &mgmt->u.probe_resp.beacon_int);
+	put_unaligned_le16(cur_network->capability,
+			   &mgmt->u.probe_resp.capab_info);
+
+	pktlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
 
 	if (cur_network->IELength > MAX_IE_SZ)
 		return;
 
-	memcpy(pframe, cur_network->IEs, cur_network->IELength);
-	pframe += cur_network->IELength;
-	pktlen += cur_network->IELength;
+	memcpy(mgmt->u.probe_resp.variable, cur_network->IEs,
+	       cur_network->IELength);
+	pktlen += (cur_network->IELength);
 
 	*pLength = pktlen;
 }
 
-/*  To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
-void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
-{
-}
-
 /*  */
 /*  Description: Fill the reserved packets that FW will use to RSVD page. */
 /*			Now we just send 4 types packet to rsvd page. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_dm.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_dm.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_dm.c	2014-09-28 17:29:07.000000000 -0400
@@ -34,10 +34,6 @@
 /*  Global var */
 /*  */
 
-static void dm_CheckStatistics(struct rtw_adapter *Adapter)
-{
-}
-
 static void dm_CheckPbcGPIO(struct rtw_adapter *padapter)
 {
 	u8	tmp1byte;
@@ -86,16 +82,15 @@ static void dm_CheckPbcGPIO(struct rtw_a
 
 /*  Initialize GPIO setting registers */
 /*  functions */
-static void Init_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
-{
 
+void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
+{
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
+	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
 	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
-	u8	cut_ver, fab_ver;
+	u8 cut_ver, fab_ver;
 
-	/*  */
-	/*  Init Value */
-	/*  */
+	memset(pdmpriv, 0, sizeof(struct dm_priv));
 	memset(pDM_Odm, 0, sizeof(*pDM_Odm));
 
 	pDM_Odm->Adapter = Adapter;
@@ -137,9 +132,6 @@ static void Init_ODM_ComInfo_8723a(struc
 
 static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
 {
-	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
-	struct mlme_priv		*pmlmepriv = &Adapter->mlmepriv;
-	struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
 	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
 	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
@@ -155,28 +147,7 @@ static void Update_ODM_ComInfo_8723a(str
 				ODM_RF_TX_PWR_TRACK	|
 				ODM_RF_CALIBRATION;
 	/*  Pointer reference */
-
-	ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
-
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI,
-			   &Adapter->xmitpriv.tx_bytes);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI,
-			   &Adapter->recvpriv.rx_bytes);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE,
-			   &pmlmeext->cur_wireless_mode);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET,
-			   &pHalData->nCur40MhzPrimeSC);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE,
-			   &Adapter->securitypriv.dot11PrivacyAlgrthm);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW,
-			   &pHalData->CurrentChannelBW);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL,
-			   &pHalData->CurrentChannel);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &Adapter->net_closed);
-
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &pmlmepriv->bScanInProcess);
-	ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING,
-			   &pwrctrlpriv->bpower_saving);
+	rtl8723a_odm_support_ability_set(Adapter, DYNAMIC_ALL_FUNC_ENABLE);
 
 	for (i = 0; i < NUM_STA; i++)
 		ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);
@@ -189,14 +160,6 @@ void rtl8723a_InitHalDm(struct rtw_adapt
 	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
 	u8	i;
 
-	pdmpriv->DM_Type = DM_Type_ByDriver;
-	pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
-
-#ifdef CONFIG_8723AU_BT_COEXIST
-	pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
-#endif
-	pdmpriv->InitDMFlag = pdmpriv->DMFlag;
-
 	Update_ODM_ComInfo_8723a(Adapter);
 	ODM23a_DMInit(pDM_Odm);
 	/*  Save REG_INIDATA_RATE_SEL value for TXDESC. */
@@ -211,6 +174,7 @@ rtl8723a_HalDmWatchDog(
 {
 	bool		bFwCurrentInPSMode = false;
 	bool		bFwPSAwake = true;
+	u8 bLinked = false;
 	u8 hw_init_completed = false;
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
 	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
@@ -223,10 +187,7 @@ rtl8723a_HalDmWatchDog(
 	bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
 	bFwPSAwake = rtl8723a_get_fwlps_rf_on(Adapter);
 
-	if ((hw_init_completed) && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
-		/*  Calculate Tx/Rx statistics. */
-		dm_CheckStatistics(Adapter);
-
+	if (!bFwCurrentInPSMode && bFwPSAwake) {
 		/*  Read REG_INIDATA_RATE_SEL value for TXDESC. */
 		if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) {
 			pdmpriv->INIDATA_RATE[0] = rtl8723au_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f;
@@ -238,16 +199,11 @@ rtl8723a_HalDmWatchDog(
 	}
 
 	/* ODM */
-	if (hw_init_completed == true) {
-		u8	bLinked = false;
-
-		if (rtw_linked_check(Adapter))
-			bLinked = true;
+	if (rtw_linked_check(Adapter))
+		bLinked = true;
 
-		ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK,
-				     bLinked);
-		ODM_DMWatchdog23a(&pHalData->odmpriv);
-	}
+	ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked);
+	ODM_DMWatchdog23a(Adapter);
 
 skip_dm:
 
@@ -255,16 +211,3 @@ skip_dm:
 	/*  Check Hardware Radio ON/OFF or not */
 	dm_CheckPbcGPIO(Adapter);
 }
-
-void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
-
-	memset(pdmpriv, 0, sizeof(struct dm_priv));
-	Init_ODM_ComInfo_8723a(Adapter);
-}
-
-void rtl8723a_deinit_dm_priv(struct rtw_adapter *Adapter)
-{
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c	2014-08-07 04:57:07.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c	2014-09-28 21:39:29.000000000 -0400
@@ -49,93 +49,14 @@ static void _FWDownloadEnable(struct rtw
 
 static int _BlockWrite(struct rtw_adapter *padapter, void *buffer, u32 buffSize)
 {
-	int ret = _SUCCESS;
-	/*  (Default) Phase #1 : PCI muse use 4-byte write to download FW */
-	u32 blockSize_p1 = 4;
-	/*  Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
-	u32 blockSize_p2 = 8;
-	/*  Phase #3 : Use 1-byte, the remnant of FW image. */
-	u32 blockSize_p3 = 1;
-	u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
-	u32 remainSize_p1 = 0, remainSize_p2 = 0;
-	u8 *bufferPtr = (u8 *) buffer;
-	u32 i = 0, offset = 0;
-
-	blockSize_p1 = 254;
-
-	/* 3 Phase #1 */
-	blockCount_p1 = buffSize / blockSize_p1;
-	remainSize_p1 = buffSize % blockSize_p1;
-
-	if (blockCount_p1) {
-		RT_TRACE(_module_hal_init_c_, _drv_notice_,
-			 ("_BlockWrite: [P1] buffSize(%d) blockSize_p1(%d) "
-			  "blockCount_p1(%d) remainSize_p1(%d)\n",
-			  buffSize, blockSize_p1, blockCount_p1,
-			  remainSize_p1));
-	}
-
-	for (i = 0; i < blockCount_p1; i++) {
-		ret = rtl8723au_writeN(padapter, (FW_8723A_START_ADDRESS +
-						  i * blockSize_p1),
-				       blockSize_p1,
-				       (bufferPtr + i * blockSize_p1));
-		if (ret == _FAIL)
-			goto exit;
-	}
-
-	/* 3 Phase #2 */
-	if (remainSize_p1) {
-		offset = blockCount_p1 * blockSize_p1;
-
-		blockCount_p2 = remainSize_p1 / blockSize_p2;
-		remainSize_p2 = remainSize_p1 % blockSize_p2;
-
-		if (blockCount_p2) {
-			RT_TRACE(_module_hal_init_c_, _drv_notice_,
-				 ("_BlockWrite: [P2] buffSize_p2(%d) "
-				  "blockSize_p2(%d) blockCount_p2(%d) "
-				  "remainSize_p2(%d)\n",
-				  (buffSize - offset), blockSize_p2,
-				  blockCount_p2, remainSize_p2));
-		}
-
-		for (i = 0; i < blockCount_p2; i++) {
-			ret = rtl8723au_writeN(padapter,
-					       (FW_8723A_START_ADDRESS +
-						offset + i * blockSize_p2),
-					       blockSize_p2,
-					       (bufferPtr + offset +
-						i * blockSize_p2));
-
-			if (ret == _FAIL)
-				goto exit;
-		}
-	}
-
-	/* 3 Phase #3 */
-	if (remainSize_p2) {
-		offset = (blockCount_p1 * blockSize_p1) +
-			(blockCount_p2 * blockSize_p2);
-
-		blockCount_p3 = remainSize_p2 / blockSize_p3;
-
-		RT_TRACE(_module_hal_init_c_, _drv_notice_,
-			 ("_BlockWrite: [P3] buffSize_p3(%d) blockSize_p3(%d) "
-			  "blockCount_p3(%d)\n",
-			  (buffSize - offset), blockSize_p3, blockCount_p3));
+	int ret;
 
-		for (i = 0; i < blockCount_p3; i++) {
-			ret = rtl8723au_write8(padapter,
-					       (FW_8723A_START_ADDRESS + offset + i),
-					       *(bufferPtr + offset + i));
+	if (buffSize > MAX_PAGE_SIZE)
+		return _FAIL;
 
-			if (ret == _FAIL)
-				goto exit;
-		}
-	}
+	ret = rtl8723au_writeN(padapter, FW_8723A_START_ADDRESS,
+			       buffSize, buffer);
 
-exit:
 	return ret;
 }
 
@@ -961,28 +882,18 @@ void rtl8723a_read_chip_version(struct r
 /*  */
 void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
 {
-	struct hal_data_8723a *pHalData;
-	u32 addr;
-	u8 *pRegBcnCtrlVal;
-
-	pHalData = GET_HAL_DATA(padapter);
-	pRegBcnCtrlVal = (u8 *)&pHalData->RegBcnCtrlVal;
-
-	addr = REG_BCN_CTRL;
+	u8 val8;
 
-	*pRegBcnCtrlVal = rtl8723au_read8(padapter, addr);
-	*pRegBcnCtrlVal |= SetBits;
-	*pRegBcnCtrlVal &= ~ClearBits;
+	val8 = rtl8723au_read8(padapter, REG_BCN_CTRL);
+	val8 |= SetBits;
+	val8 &= ~ClearBits;
 
-	rtl8723au_write8(padapter, addr, *pRegBcnCtrlVal);
+	rtl8723au_write8(padapter, REG_BCN_CTRL, val8);
 }
 
 void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
 {
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
-
 	rtl8723au_write16(padapter, REG_BCN_CTRL, 0x1010);
-	pHalData->RegBcnCtrlVal = 0x1010;
 
 	/*  TODO: Remove these magic number */
 	rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0x6404);	/*  ms */
@@ -1034,8 +945,6 @@ static void StopTxBeacon(struct rtw_adap
 	rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
 	pHalData->RegReg542 &= ~BIT(0);
 	rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
-
-	CheckFwRsvdPageContent23a(padapter); /*  2010.06.23. Added by tynli. */
 }
 
 static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
@@ -2381,18 +2290,18 @@ void hw_var_set_opmode(struct rtw_adapte
 {
 	u8 val8;
 
-	if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
+	if (mode == MSR_INFRA || mode == MSR_NOLINK) {
 		StopTxBeacon(padapter);
 
 		/*  disable atim wnd */
 		val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
 		SetBcnCtrlReg23a(padapter, val8, ~val8);
-	} else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_) */) {
+	} else if (mode == MSR_ADHOC) {
 		ResumeTxBeacon(padapter);
 
 		val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
 		SetBcnCtrlReg23a(padapter, val8, ~val8);
-	} else if (mode == _HW_STATE_AP_) {
+	} else if (mode == MSR_AP) {
 		/*  add NULL Data and BT NULL Data Packets to FW RSVD Page */
 		rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
 
@@ -2474,8 +2383,8 @@ void hw_var_set_correct_tsf(struct rtw_a
 		do_div(pmlmeext->TSFValue,
 		       (pmlmeinfo->bcn_interval * 1024)) - 1024;	/* us */
 
-	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
-	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+	if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
+	    ((pmlmeinfo->state & 0x03) == MSR_AP)) {
 		/* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
 		/* rtl8723au_write8(padapter, REG_TXPAUSE,
 		   (rtl8723au_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
@@ -2493,8 +2402,8 @@ void hw_var_set_correct_tsf(struct rtw_a
 	/* enable related TSF function */
 	SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
 
-	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
-	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
+	if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
+	    ((pmlmeinfo->state & 0x03) == MSR_AP))
 		ResumeTxBeacon(padapter);
 }
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c	2014-09-28 17:29:07.000000000 -0400
@@ -425,8 +425,7 @@ int PHY_MACConfig8723A(struct rtw_adapte
 	/*  */
 	/*  Config MAC */
 	/*  */
-	if (ODM_ConfigMACWithHeaderFile23a(&pHalData->odmpriv) == _FAIL)
-		rtStatus = _FAIL;
+	ODM_ReadAndConfig_MAC_REG_8723A(&pHalData->odmpriv);
 
 	/*  2010.07.13 AMPDU aggregation number 9 */
 	/* rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
@@ -753,11 +752,7 @@ phy_BB8723a_Config_ParaFile(struct rtw_a
 	/*  1. Read PHY_REG.TXT BB INIT!! */
 	/*  We will seperate as 88C / 92C according to chip version */
 	/*  */
-	if (ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
-					  CONFIG_BB_PHY_REG) == _FAIL)
-		rtStatus = _FAIL;
-	if (rtStatus != _SUCCESS)
-		goto phy_BB8190_Config_ParaFile_Fail;
+	ODM_ReadAndConfig_PHY_REG_1T_8723A(&pHalData->odmpriv);
 
 	/*  */
 	/*  20100318 Joseph: Config 2T2R to 1T2R if necessary. */
@@ -784,9 +779,7 @@ phy_BB8723a_Config_ParaFile(struct rtw_a
 	/*  */
 	/*  3. BB AGC table Initialization */
 	/*  */
-	if (ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
-					  CONFIG_BB_AGC_TAB) == _FAIL)
-		rtStatus = _FAIL;
+	ODM_ReadAndConfig_AGC_TAB_1T_8723A(&pHalData->odmpriv);
 
 phy_BB8190_Config_ParaFile_Fail:
 
@@ -846,18 +839,6 @@ PHY_BBConfig8723A(struct rtw_adapter *Ad
 	return rtStatus;
 }
 
-int
-PHY_RFConfig8723A(struct rtw_adapter *Adapter)
-{
-	int rtStatus = _SUCCESS;
-
-	/*  */
-	/*  RF config */
-	/*  */
-	rtStatus = PHY_RF6052_Config8723A(Adapter);
-	return rtStatus;
-}
-
 static void getTxPowerIndex(struct rtw_adapter *Adapter,
 			    u8 channel,	u8 *cckPowerLevel,  u8 *ofdmPowerLevel)
 {
@@ -1098,9 +1079,6 @@ static void _PHY_SwChnl8723A(struct rtw_
 	u32 param1, param2;
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
 
-	if (Adapter->bNotifyChannelChange)
-		DBG_8723A("[%s] ch = %d\n", __func__, channel);
-
 	/* s1. pre common command - CmdID_SetTxPowerLevel */
 	PHY_SetTxPowerLevel8723A(Adapter, channel);
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c	2014-09-28 17:29:07.000000000 -0400
@@ -455,20 +455,9 @@ static int phy_RF6052_Config_ParaFile(st
 		/*----Initialize RF fom connfiguration file----*/
 		switch (eRFPath) {
 		case RF_PATH_A:
-			if (ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv,
-							  (enum RF_RADIO_PATH)
-							  eRFPath,
-							  (enum RF_RADIO_PATH)
-							  eRFPath) == _FAIL)
-				rtStatus = _FAIL;
+			ODM_ReadAndConfig_RadioA_1T_8723A(&pHalData->odmpriv);
 			break;
 		case RF_PATH_B:
-			if (ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv,
-							  (enum RF_RADIO_PATH)
-							  eRFPath,
-							  (enum RF_RADIO_PATH)
-							  eRFPath) == _FAIL)
-				rtStatus = _FAIL;
 			break;
 		}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c	2014-09-28 17:29:07.000000000 -0400
@@ -46,29 +46,10 @@ void rtl8723a_sreset_xmit_status_check(s
 			} else {
 				diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_complete_time);
 				if (diff_time > 4000) {
-					/* padapter->Wifi_Error_Status = WIFI_TX_HANG; */
 					DBG_8723A("%s tx hang\n", __func__);
 					rtw_sreset_reset(padapter);
 				}
 			}
 		}
 	}
-
-	if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) {
-		psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
-		rtw_sreset_reset(padapter);
-		return;
-	}
-}
-
-void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter)
-{
-	struct hal_data_8723a	*pHalData = GET_HAL_DATA(padapter);
-	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
-	if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) {
-		psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
-		rtw_sreset_reset(padapter);
-		return;
-	}
 }
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c	2014-09-28 17:29:07.000000000 -0400
@@ -18,27 +18,6 @@
 #include <drv_types.h>
 #include <rtl8723a_hal.h>
 
-void dump_txrpt_ccx_8723a(void *buf)
-{
-	struct txrpt_ccx_8723a *txrpt_ccx = buf;
-
-	DBG_8723A("%s:\n"
-		"tag1:%u, rsvd:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
-		"mac_id:%u, pkt_drop:%u, pkt_ok:%u, bmc:%u\n"
-		"retry_cnt:%u, lifetime_over:%u, retry_over:%u\n"
-		"ccx_qtime:%u\n"
-		"final_data_rate:0x%02x\n"
-		"qsel:%u, sw:0x%03x\n"
-		, __func__
-		, txrpt_ccx->tag1, txrpt_ccx->rsvd, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx
-		, txrpt_ccx->mac_id, txrpt_ccx->pkt_drop, txrpt_ccx->pkt_ok, txrpt_ccx->bmc
-		, txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over
-		, txrpt_ccx_qtime_8723a(txrpt_ccx)
-		, txrpt_ccx->final_data_rate
-		, txrpt_ccx->qsel, txrpt_ccx_sw_8723a(txrpt_ccx)
-	);
-}
-
 void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf)
 {
 	struct txrpt_ccx_8723a *txrpt_ccx = buf;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/usb_halinit.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/usb_halinit.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/usb_halinit.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/usb_halinit.c	2014-09-28 17:29:07.000000000 -0400
@@ -338,17 +338,6 @@ static void _InitQueuePriority(struct rt
 	_InitNormalChipQueuePriority(Adapter);
 }
 
-static void _InitNetworkType(struct rtw_adapter *Adapter)
-{
-	u32 value32;
-
-	value32 = rtl8723au_read32(Adapter, REG_CR);
-
-	/*  TODO: use the other function to set network type */
-	value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
-	rtl8723au_write32(Adapter, REG_CR, value32);
-}
-
 static void _InitTransferPageSize(struct rtw_adapter *Adapter)
 {
 	/*  Tx page size is always 128. */
@@ -484,62 +473,6 @@ static void _InitRetryFunction(struct rt
 	rtl8723au_write8(Adapter, REG_ACKTO, 0x40);
 }
 
-/*-----------------------------------------------------------------------------
- * Function:	usb_AggSettingTxUpdate()
- *
- * Overview:	Seperate TX/RX parameters update independent for TP
- *		detection and dynamic TX/RX aggreagtion parameters update.
- *
- * Input:			struct rtw_adapter *
- *
- * Output/Return:	NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	12/10/2010	MHC		Seperate to smaller function.
- *
- *---------------------------------------------------------------------------*/
-static void usb_AggSettingTxUpdate(struct rtw_adapter *Adapter)
-{
-}	/*  usb_AggSettingTxUpdate */
-
-/*-----------------------------------------------------------------------------
- * Function:	usb_AggSettingRxUpdate()
- *
- * Overview:	Seperate TX/RX parameters update independent for TP
- *		detection and dynamic TX/RX aggreagtion parameters update.
- *
- * Input:			struct rtw_adapter *
- *
- * Output/Return:	NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	12/10/2010	MHC		Seperate to smaller function.
- *
- *---------------------------------------------------------------------------*/
-static void usb_AggSettingRxUpdate(struct rtw_adapter *Adapter)
-{
-}	/*  usb_AggSettingRxUpdate */
-
-static void InitUsbAggregationSetting(struct rtw_adapter *Adapter)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-
-	/*  Tx aggregation setting */
-	usb_AggSettingTxUpdate(Adapter);
-
-	/*  Rx aggregation setting */
-	usb_AggSettingRxUpdate(Adapter);
-
-	/*  201/12/10 MH Add for USB agg mode dynamic switch. */
-	pHalData->UsbRxHighSpeedMode = false;
-}
-
-static void _InitOperationMode(struct rtw_adapter *Adapter)
-{
-}
-
 static void _InitRFType(struct rtw_adapter *Adapter)
 {
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
@@ -584,24 +517,19 @@ enum rt_rf_power_state RfOnOffDetect23a(
 	u8 val8;
 	enum rt_rf_power_state rfpowerstate = rf_off;
 
-	if (pAdapter->pwrctrlpriv.bHWPowerdown) {
-		val8 = rtl8723au_read8(pAdapter, REG_HSISR);
-		DBG_8723A("pwrdown, 0x5c(BIT7) =%02x\n", val8);
-		rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on;
-	} else { /*  rf on/off */
-		rtl8723au_write8(pAdapter, REG_MAC_PINMUX_CFG,
-				 rtl8723au_read8(pAdapter, REG_MAC_PINMUX_CFG) &
-				 ~BIT(3));
-		val8 = rtl8723au_read8(pAdapter, REG_GPIO_IO_SEL);
-		DBG_8723A("GPIO_IN =%02x\n", val8);
-		rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
-	}
+	rtl8723au_write8(pAdapter, REG_MAC_PINMUX_CFG,
+			 rtl8723au_read8(pAdapter,
+					 REG_MAC_PINMUX_CFG) & ~BIT(3));
+	val8 = rtl8723au_read8(pAdapter, REG_GPIO_IO_SEL);
+	DBG_8723A("GPIO_IN =%02x\n", val8);
+	rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
+
 	return rfpowerstate;
-}	/*  HalDetectPwrDownMode */
+}
 
 void _ps_open_RF23a(struct rtw_adapter *padapter);
 
-static int rtl8723au_hal_init(struct rtw_adapter *Adapter)
+int rtl8723au_hal_init(struct rtw_adapter *Adapter)
 {
 	u8 val8 = 0;
 	u32 boundary;
@@ -612,6 +540,8 @@ static int rtl8723au_hal_init(struct rtw
 
 	unsigned long init_start_time = jiffies;
 
+	Adapter->hw_init_completed = false;
+
 	if (Adapter->pwrctrlpriv.bkeepfwalive) {
 		_ps_open_RF23a(Adapter);
 
@@ -718,9 +648,9 @@ static int rtl8723au_hal_init(struct rtw
 	/*  Add for tx power by rate fine tune. We need to call the function after BB config. */
 	/*  Because the tx power by rate table is inited in BB config. */
 
-	status = PHY_RFConfig8723A(Adapter);
+	status = PHY_RF6052_Config8723A(Adapter);
 	if (status == _FAIL) {
-		DBG_8723A("PHY_RFConfig8723A fault !!\n");
+		DBG_8723A("PHY_RF6052_Config8723A failed!!\n");
 		goto exit;
 	}
 
@@ -756,14 +686,12 @@ static int rtl8723au_hal_init(struct rtw
 
 	_InitInterrupt(Adapter);
 	hw_var_set_macaddr(Adapter, Adapter->eeprompriv.mac_addr);
-	_InitNetworkType(Adapter);/* set msr */
+	rtl8723a_set_media_status(Adapter, MSR_INFRA);
 	_InitWMACSetting(Adapter);
 	_InitAdaptiveCtrl(Adapter);
 	_InitEDCA(Adapter);
 	_InitRateFallback(Adapter);
 	_InitRetryFunction(Adapter);
-	InitUsbAggregationSetting(Adapter);
-	_InitOperationMode(Adapter);/* todo */
 	rtl8723a_InitBeaconParameters(Adapter);
 
 	_InitHWLed(Adapter);
@@ -771,7 +699,7 @@ static int rtl8723au_hal_init(struct rtw
 	_BBTurnOnBlock(Adapter);
 	/* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */
 
-	invalidate_cam_all23a(Adapter);
+	rtl8723a_cam_invalidate_all(Adapter);
 
 	/*  2010/12/17 MH We need to set TX power according to EFUSE content at first. */
 	PHY_SetTxPowerLevel8723A(Adapter, pHalData->CurrentChannel);
@@ -849,7 +777,9 @@ static int rtl8723au_hal_init(struct rtw
 
 	rtl8723a_InitHalDm(Adapter);
 
-	rtl8723a_set_nav_upper(Adapter, WiFiNavUpperUs);
+	val8 = ((WiFiNavUpperUs + HAL_8723A_NAV_UPPER_UNIT - 1) /
+		HAL_8723A_NAV_UPPER_UNIT);
+	rtl8723au_write8(Adapter, REG_NAV_UPPER, val8);
 
 	/*  2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */
 	if (((rtl8723au_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) !=
@@ -863,6 +793,13 @@ static int rtl8723au_hal_init(struct rtw
 			  rtl8723au_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
 
 exit:
+	if (status == _SUCCESS) {
+		Adapter->hw_init_completed = true;
+
+		if (Adapter->registrypriv.notch_filter == 1)
+			rtl8723a_notch_filter(Adapter, 1);
+	}
+
 	DBG_8723A("%s in %dms\n", __func__,
 		  jiffies_to_msecs(jiffies - init_start_time));
 	return status;
@@ -1172,7 +1109,7 @@ static void CardDisableRTL8723U(struct r
 	rtl8723au_write8(Adapter, REG_RSV_CTRL, 0x0e);
 }
 
-static int rtl8723au_hal_deinit(struct rtw_adapter *padapter)
+int rtl8723au_hal_deinit(struct rtw_adapter *padapter)
 {
 	DBG_8723A("==> %s\n", __func__);
 
@@ -1185,6 +1122,8 @@ static int rtl8723au_hal_deinit(struct r
 	/*  IC. Accord to johnny's opinion, only RU need the support. */
 	CardDisableRTL8723U(padapter);
 
+	padapter->hw_init_completed = false;
+
 	return _SUCCESS;
 }
 
@@ -1532,9 +1471,9 @@ void rtl8723a_update_ramask(struct rtw_a
 		mask = update_supported_rate23a(cur_network->SupportedRates,
 					     supportRateNum);
 		mask |= (pmlmeinfo->HT_enable) ?
-			update_MSC_rate23a(&pmlmeinfo->HT_caps) : 0;
+			update_MSC_rate23a(&pmlmeinfo->ht_cap) : 0;
 
-		if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
+		if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
 			shortGIrate = true;
 		break;
 
@@ -1569,8 +1508,8 @@ void rtl8723a_update_ramask(struct rtw_a
 
 	/* mask &= 0x0fffffff; */
 	rate_bitmap = 0x0fffffff;
-	rate_bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv,
-					  mac_id, mask, rssi_level);
+	rate_bitmap = ODM_Get_Rate_Bitmap23a(pHalData, mac_id, mask,
+					     rssi_level);
 	DBG_8723A("%s => mac_id:%d, networkType:0x%02x, "
 		  "mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n",
 		  __func__, mac_id, networkType, mask, rssi_level, rate_bitmap);
@@ -1610,40 +1549,3 @@ void rtl8723a_update_ramask(struct rtw_a
 	/* set correct initial date rate for each mac_id */
 	pdmpriv->INIDATA_RATE[mac_id] = init_rate;
 }
-
-int rtw_hal_init23a(struct rtw_adapter *padapter)
-{
-	int status;
-
-	padapter->hw_init_completed = false;
-
-	status = rtl8723au_hal_init(padapter);
-
-	if (status == _SUCCESS) {
-		padapter->hw_init_completed = true;
-
-		if (padapter->registrypriv.notch_filter == 1)
-			rtl8723a_notch_filter(padapter, 1);
-	} else {
-		padapter->hw_init_completed = false;
-		DBG_8723A("rtw_hal_init23a: hal__init fail\n");
-	}
-
-	RT_TRACE(_module_hal_init_c_, _drv_err_,
-		 ("-rtl871x_hal_init:status = 0x%x\n", status));
-
-	return status;
-}
-
-int rtw_hal_deinit23a(struct rtw_adapter *padapter)
-{
-	int status;
-
-	status = rtl8723au_hal_deinit(padapter);
-
-	if (status == _SUCCESS)
-		padapter->hw_init_completed = false;
-	else
-		DBG_8723A("\n rtw_hal_deinit23a: hal_init fail\n");
-	return status;
-}
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/usb_ops_linux.c linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/usb_ops_linux.c
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/hal/usb_ops_linux.c	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/hal/usb_ops_linux.c	2014-09-28 17:29:07.000000000 -0400
@@ -22,278 +22,149 @@
 #include <rtl8723a_hal.h>
 #include <rtl8723a_recv.h>
 
-static int usbctrl_vendorreq(struct rtw_adapter *padapter, u8 request,
-			     u16 value, u16 index, void *pdata, u16 len,
-			     u8 requesttype)
+u8 rtl8723au_read8(struct rtw_adapter *padapter, u16 addr)
 {
 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
 	struct usb_device *udev = pdvobjpriv->pusbdev;
-
-	unsigned int pipe;
-	int status = 0;
-	u8 reqtype;
-	u8 *pIo_buf;
-	int vendorreq_times = 0;
-
-	if (padapter->bSurpriseRemoved || padapter->pwrctrlpriv.pnp_bstop_trx) {
-		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("usbctrl_vendorreq:(padapter->bSurpriseRemoved||"
-			  "adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
-		status = -EPERM;
-		goto exit;
-	}
-
-	if (len > MAX_VENDOR_REQ_CMD_SIZE) {
-		DBG_8723A("[%s] Buffer len error , vendor request failed\n",
-			  __func__);
-		status = -EINVAL;
-		goto exit;
-	}
+	int len;
+	u8 data;
 
 	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ,
+			      addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(data),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	/*  Acquire IO memory for vendorreq */
-	pIo_buf = pdvobjpriv->usb_vendor_req_buf;
-
-	if (pIo_buf == NULL) {
-		DBG_8723A("[%s] pIo_buf == NULL \n", __func__);
-		status = -ENOMEM;
-		goto release_mutex;
-	}
-
-	while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
-		memset(pIo_buf, 0, len);
-
-		if (requesttype == 0x01) {
-			pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
-			reqtype =  REALTEK_USB_VENQT_READ;
-		} else {
-			pipe = usb_sndctrlpipe(udev, 0);/* write_out */
-			reqtype =  REALTEK_USB_VENQT_WRITE;
-			memcpy(pIo_buf, pdata, len);
-		}
-
-		status = usb_control_msg(udev, pipe, request, reqtype,
-					 value, index, pIo_buf, len,
-					 RTW_USB_CONTROL_MSG_TIMEOUT);
-
-		if (status == len) {   /*  Success this control transfer. */
-			rtw_reset_continual_urb_error(pdvobjpriv);
-			if (requesttype == 0x01) {
-				/* For Control read transfer, we have to copy
-				 * the read data from pIo_buf to pdata.
-				 */
-				memcpy(pdata, pIo_buf,  len);
-			}
-		} else { /*  error cases */
-			DBG_8723A("reg 0x%x, usb %s %u fail, status:%d value ="
-				  " 0x%x, vendorreq_times:%d\n",
-				  value, (requesttype == 0x01) ?
-				  "read" : "write",
-				  len, status, *(u32 *)pdata, vendorreq_times);
-
-			if (status < 0) {
-				if (status == -ESHUTDOWN || status == -ENODEV)
-					padapter->bSurpriseRemoved = true;
-				else {
-					struct hal_data_8723a *pHalData;
-					pHalData = GET_HAL_DATA(padapter);
-					pHalData->srestpriv.Wifi_Error_Status =
-						USB_VEN_REQ_CMD_FAIL;
-				}
-			} else { /*  status != len && status >= 0 */
-				if (status > 0) {
-					if (requesttype == 0x01) {
-						/*
-						 * For Control read transfer,
-						 * we have to copy the read
-						 * data from pIo_buf to pdata.
-						 */
-						memcpy(pdata, pIo_buf,  len);
-					}
-				}
-			}
-
-			if (rtw_inc_and_chk_continual_urb_error(pdvobjpriv)) {
-				padapter->bSurpriseRemoved = true;
-				break;
-			}
-		}
-
-		/*  firmware download is checksumed, don't retry */
-		if ((value >= FW_8723A_START_ADDRESS &&
-		     value <= FW_8723A_END_ADDRESS) || status == len)
-			break;
-	}
-
-release_mutex:
+	data = pdvobjpriv->usb_buf.val8;
 	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
-exit:
-	return status;
-}
-
-u8 rtl8723au_read8(struct rtw_adapter *padapter, u32 addr)
-{
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 data = 0;
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 1;
-
-	usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-			  len, requesttype);
 
 	return data;
 }
 
-u16 rtl8723au_read16(struct rtw_adapter *padapter, u32 addr)
+u16 rtl8723au_read16(struct rtw_adapter *padapter, u16 addr)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le16 data;
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
+	int len;
+	u16 data;
 
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 2;
+	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ,
+			      addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(data),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-			  len, requesttype);
+	data = le16_to_cpu(pdvobjpriv->usb_buf.val16);
+	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
 
-	return le16_to_cpu(data);
+	return data;
 }
 
-u32 rtl8723au_read32(struct rtw_adapter *padapter, u32 addr)
+u32 rtl8723au_read32(struct rtw_adapter *padapter, u16 addr)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
-
-	request = 0x05;
-	requesttype = 0x01;/* read_in */
-	index = 0;/* n/a */
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
+	int len;
+	u32 data;
 
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 4;
+	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ,
+			      addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(data),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-			  len, requesttype);
+	data = le32_to_cpu(pdvobjpriv->usb_buf.val32);
+	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
 
-	return le32_to_cpu(data);
+	return data;
 }
 
-int rtl8723au_write8(struct rtw_adapter *padapter, u32 addr, u8 val)
+int rtl8723au_write8(struct rtw_adapter *padapter, u16 addr, u8 val)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 data;
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
 	int ret;
 
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 1;
+	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	pdvobjpriv->usb_buf.val8 = val;
 
-	data = val;
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ,
+			      REALTEK_USB_VENQT_WRITE,
+			      addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(val),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	ret = usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-				len, requesttype);
+	if (ret != sizeof(val))
+		ret = _FAIL;
+	else
+		ret = _SUCCESS;
 
+	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
 	return ret;
 }
 
-int rtl8723au_write16(struct rtw_adapter *padapter, u32 addr, u16 val)
+int rtl8723au_write16(struct rtw_adapter *padapter, u16 addr, u16 val)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le16 data;
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
 	int ret;
 
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
+	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	pdvobjpriv->usb_buf.val16 = cpu_to_le16(val);
 
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 2;
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ,
+			      REALTEK_USB_VENQT_WRITE,
+			      addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(val),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	data = cpu_to_le16(val);
+	if (ret != sizeof(val))
+		ret = _FAIL;
+	else
+		ret = _SUCCESS;
 
-	ret = usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-				len, requesttype);
+	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
 	return ret;
 }
 
-int rtl8723au_write32(struct rtw_adapter *padapter, u32 addr, u32 val)
+int rtl8723au_write32(struct rtw_adapter *padapter, u16 addr, u32 val)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	__le32 data;
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
 	int ret;
 
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
+	mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
+	pdvobjpriv->usb_buf.val32 = cpu_to_le32(val);
 
-	wvalue = (u16)(addr&0x0000ffff);
-	len = 4;
-	data = cpu_to_le32(val);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ,
+			      REALTEK_USB_VENQT_WRITE,
+			      addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(val),
+			      RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	ret = usbctrl_vendorreq(padapter, request, wvalue, index, &data,
-				len, requesttype);
+	if (ret != sizeof(val))
+		ret = _FAIL;
+	else
+		ret = _SUCCESS;
 
+	mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
 	return ret;
 }
 
-int rtl8723au_writeN(struct rtw_adapter *padapter,
-		     u32 addr, u32 length, u8 *pdata)
+int rtl8723au_writeN(struct rtw_adapter *padapter, u16 addr, u16 len, u8 *buf)
 {
-	u8 request;
-	u8 requesttype;
-	u16 wvalue;
-	u16 index;
-	u16 len;
-	u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
 	int ret;
 
-	request = 0x05;
-	requesttype = 0x00;/* write_out */
-	index = 0;/* n/a */
-
-	wvalue = (u16)(addr&0x0000ffff);
-	len = length;
-	memcpy(buf, pdata, len);
-
-	ret = usbctrl_vendorreq(padapter, request, wvalue, index, buf,
-				len, requesttype);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      REALTEK_USB_VENQT_CMD_REQ,
+			      REALTEK_USB_VENQT_WRITE,
+			      addr, 0, buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
 
-	return ret;
+	if (ret != len)
+		return _FAIL;
+	return _SUCCESS;
 }
 
 /*
@@ -647,7 +518,6 @@ static void usb_read_port_complete(struc
 	struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
 	struct rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter;
 	struct recv_priv *precvpriv = &padapter->recvpriv;
-	struct hal_data_8723a *pHalData;
 
 	RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
 		 ("usb_read_port_complete!!!\n"));
@@ -726,9 +596,6 @@ static void usb_read_port_complete(struc
 			break;
 		case -EPROTO:
 		case -EOVERFLOW:
-			pHalData = GET_HAL_DATA(padapter);
-			pHalData->srestpriv.Wifi_Error_Status =
-				USB_READ_PORT_FAIL;
 			rtl8723au_read_port(padapter, RECV_BULK_IN_ADDR, 0,
 					    precvbuf);
 			break;
@@ -754,12 +621,10 @@ int rtl8723au_read_port(struct rtw_adapt
 	struct recv_priv *precvpriv = &adapter->recvpriv;
 	struct usb_device *pusbd = pdvobj->pusbdev;
 
-	if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
-	    adapter->pwrctrlpriv.pnp_bstop_trx) {
+	if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
 			 ("usb_read_port:(padapter->bDriverStopped ||"
-			  "padapter->bSurpriseRemoved ||adapter->"
-			  "pwrctrlpriv.pnp_bstop_trx)!!!\n"));
+			  "padapter->bSurpriseRemoved)!!!\n"));
 		return _FAIL;
 	}
 
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/drv_types.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/drv_types.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/drv_types.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/drv_types.h	2014-09-28 17:29:07.000000000 -0400
@@ -111,7 +111,6 @@ struct registry_priv {
 	u8	antdiv_cfg;
 	u8	antdiv_type;
 
-	u8	usbss_enable;/* 0:disable,1:enable */
 	u8	hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */
 	u8	hwpwrp_detect;/* 0:disable,1:enable */
 
@@ -177,10 +176,13 @@ struct dvobj_priv {
 	u8	RtNumOutPipes;
 	int	ep_num[5]; /* endpoint number */
 
-	struct mutex  usb_vendor_req_mutex;
+	struct mutex usb_vendor_req_mutex;
 
-	u8 *usb_alloc_vendor_req_buf;
-	u8 *usb_vendor_req_buf;
+	union {
+		__le32 val32;
+		__le16 val16;
+		u8 val8;
+	} usb_buf;
 
 	struct usb_interface *pusbintf;
 	struct usb_device *pusbdev;
@@ -257,9 +259,6 @@ struct rtw_adapter {
 	u8 bFWReady;
 	u8 bReadPortCancel;
 	u8 bWritePortCancel;
-	/* The driver will show the desired chan nor when this flag is 1. */
-	u8 bNotifyChannelChange;
-	struct rtw_adapter *pbuddy_adapter;
 
 	/* extend to support multi interface */
 	/* IFACE_ID0 is equals to PRIMARY_ADAPTER */
@@ -269,8 +268,6 @@ struct rtw_adapter {
 
 #define adapter_to_dvobj(adapter) (adapter->dvobj)
 
-int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init);
-
 static inline u8 *myid(struct eeprom_priv *peepriv)
 {
 	return peepriv->mac_addr;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h	2014-09-28 17:29:07.000000000 -0400
@@ -224,7 +224,6 @@ SetAntennaConfig92C(struct rtw_adapter *
 
 /* MAC/BB/RF HAL config */
 int PHY_BBConfig8723A(struct rtw_adapter *Adapter);
-int PHY_RFConfig8723A(struct rtw_adapter *Adapter);
 s32 PHY_MACConfig8723A(struct rtw_adapter *padapter);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/hal_com.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/hal_com.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/hal_com.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/hal_com.h	2014-09-28 17:29:07.000000000 -0400
@@ -182,7 +182,7 @@ void rtl8723a_set_slot_time(struct rtw_a
 void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble);
 void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec);
 void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex);
-void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter);
+void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter);
 void rtl8723a_cam_write(struct rtw_adapter *padapter,
 			u8 entry, u16 ctrl, const u8 *mac, const u8 *key);
 void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter);
@@ -197,7 +197,6 @@ void rtl8723a_set_ac_param_vi(struct rtw
 void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be);
 void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk);
 void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val);
-void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper);
 void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain);
 
 void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h	2014-09-28 17:29:07.000000000 -0400
@@ -35,10 +35,4 @@ void ODM_ReadAndConfig_PHY_REG_1T_8723A(
 
 void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm);
 
-/******************************************************************************
-*                           PHY_REG_PG.TXT
-******************************************************************************/
-
-void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm);
-
 #endif /*  end of HWIMG_SUPPORT */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/hal_intf.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/hal_intf.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/hal_intf.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/hal_intf.h	2014-09-28 17:29:07.000000000 -0400
@@ -101,10 +101,9 @@ enum hardware_type {
 
 void rtw_hal_def_value_init23a(struct rtw_adapter *padapter);
 int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal);
-int rtw_resume_process23a(struct rtw_adapter *padapter);
 
-int rtw_hal_init23a(struct rtw_adapter *padapter);
-int rtw_hal_deinit23a(struct rtw_adapter *padapter);
+int rtl8723au_hal_init(struct rtw_adapter *padapter);
+int rtl8723au_hal_deinit(struct rtw_adapter *padapter);
 void rtw_hal_stop(struct rtw_adapter *padapter);
 
 void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/ieee80211.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/ieee80211.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/ieee80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/ieee80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -27,8 +27,6 @@
 #endif
 
 
-#define MGMT_QUEUE_NUM 5
-
 #ifdef CONFIG_8723AU_AP_MODE
 
 /* STA flags */
@@ -50,12 +48,6 @@
 
 #endif
 
-#define IEEE_CMD_SET_WPA_PARAM			1
-#define IEEE_CMD_SET_WPA_IE				2
-#define IEEE_CMD_SET_ENCRYPTION			3
-
-#define	IEEE_CRYPT_ALG_NAME_LEN			16
-
 #define WPA_CIPHER_NONE		BIT(0)
 #define WPA_CIPHER_WEP40	BIT(1)
 #define WPA_CIPHER_WEP104	BIT(2)
@@ -81,7 +73,6 @@ extern u8 WPA_CIPHER_SUITE_WEP10423A[];
 #define RSN_HEADER_LEN 4
 #define RSN_SELECTOR_LEN 4
 
-extern u16 RSN_VERSION_BSD23A;
 extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[];
 extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[];
 extern u8 RSN_CIPHER_SUITE_NONE23A[];
@@ -154,50 +145,6 @@ enum NETWORK_TYPE
 #define IsSupportedTxMCS(NetType) (NetType & (WIRELESS_11_24N|WIRELESS_11_5N) ? true : false)
 
 
-struct ieee_param {
-	u32 cmd;
-	u8 sta_addr[ETH_ALEN];
-	union {
-		struct {
-			u8 name;
-			u32 value;
-		} wpa_param;
-		struct {
-			u32 len;
-			u8 reserved[32];
-			u8 data[0];
-		} wpa_ie;
-	        struct{
-			int command;
-			int reason_code;
-		} mlme;
-		struct {
-			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
-			u8 set_tx;
-			u32 err;
-			u8 idx;
-			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
-			u16 key_len;
-			u8 key[0];
-		} crypt;
-#ifdef CONFIG_8723AU_AP_MODE
-		struct {
-			u16 aid;
-			u16 capability;
-			int flags;
-			u8 tx_supp_rates[16];
-			struct ieee80211_ht_cap ht_cap;
-		} add_sta;
-		struct {
-			u8	reserved[2];/* for set max_num_sta */
-			u8	buf[0];
-		} bcn_ie;
-#endif
-
-	} u;
-};
-
-
 #define MIN_FRAG_THRESHOLD     256U
 #define	MAX_FRAG_THRESHOLD     2346U
 
@@ -221,20 +168,10 @@ struct ieee80211_snap_hdr {
 
 #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
 
-#define WLAN_FC_GET_TYPE(fc)		(fc & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc)		(fc & IEEE80211_FCTL_STYPE)
-
-#define WLAN_QC_GET_TID(qc)		(qc & 0x0f)
-
-#define WLAN_GET_SEQ_FRAG(seq)		(seq & RTW_IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq)		(seq & RTW_IEEE80211_SCTL_SEQ)
-
-
 #define WLAN_REASON_JOIN_WRONG_CHANNEL       65534
 #define WLAN_REASON_EXPIRATION_CHK 65535
 
 
-
 #define IEEE80211_STATMASK_SIGNAL (1<<0)
 #define IEEE80211_STATMASK_RSSI (1<<1)
 #define IEEE80211_STATMASK_NOISE (1<<2)
@@ -305,7 +242,6 @@ struct ieee80211_snap_hdr {
 #define IEEE80211_OFDM_SHIFT_MASK_A         4
 
 #define WEP_KEYS 4
-#define WEP_KEY_LEN 13
 
 
 /* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
@@ -315,14 +251,13 @@ struct ieee80211_snap_hdr {
 #define MAX_RATES_LENGTH	12
 #define MAX_RATES_EX_LENGTH	16
 #define MAX_CHANNEL_NUMBER	161
+#define RTW_CH_MAX_2G_CHANNEL	14	/* Max channel in 2G band */
 
 #define MAX_WPA_IE_LEN		256
-#define MAX_WPS_IE_LEN		512
+#define MAX_WPS_IE_LEN		256
 #define MAX_P2P_IE_LEN		256
 #define MAX_WFD_IE_LEN		128
 
-#define IW_ESSID_MAX_SIZE	32
-
 /*
 join_res:
 -1: authentication fail
@@ -335,26 +270,6 @@ join_res:
 
 #define MAXTID	16
 
-enum _PUBLIC_ACTION{
-	ACT_PUBLIC_BSSCOEXIST = 0, /*  20/40 BSS Coexistence */
-	ACT_PUBLIC_DSE_ENABLE = 1,
-	ACT_PUBLIC_DSE_DEENABLE = 2,
-	ACT_PUBLIC_DSE_REG_LOCATION = 3,
-	ACT_PUBLIC_EXT_CHL_SWITCH = 4,
-	ACT_PUBLIC_DSE_MSR_REQ = 5,
-	ACT_PUBLIC_DSE_MSR_RPRT = 6,
-	ACT_PUBLIC_MP = 7, /*  Measurement Pilot */
-	ACT_PUBLIC_DSE_PWR_CONSTRAINT = 8,
-	ACT_PUBLIC_VENDOR = 9, /*  for WIFI_DIRECT */
-	ACT_PUBLIC_GAS_INITIAL_REQ = 10,
-	ACT_PUBLIC_GAS_INITIAL_RSP = 11,
-	ACT_PUBLIC_GAS_COMEBACK_REQ = 12,
-	ACT_PUBLIC_GAS_COMEBACK_RSP = 13,
-	ACT_PUBLIC_TDLS_DISCOVERY_RSP = 14,
-	ACT_PUBLIC_LOCATION_TRACK = 15,
-	ACT_PUBLIC_MAX
-};
-
 #define WME_OUI_TYPE 2
 #define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0
 #define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1
@@ -407,14 +322,8 @@ struct rtw_ieee80211_channel {
 	/*, (channel)->orig_mag*/ \
 	/*, (channel)->orig_mpwr*/ \
 
-u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len, unsigned char *source, unsigned int *frlen);
 u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen);
 
-enum secondary_ch_offset {
-	SCN = 0, /* no secondary channel */
-	SCA = 1, /* secondary channel above */
-	SCB = 3,  /* secondary channel below */
-};
 u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset);
 u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt);
 u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset);
@@ -425,16 +334,11 @@ int rtw_ies_remove_ie23a(u8 *ies, uint *
 
 void rtw_set_supported_rate23a(u8* SupportedRates, uint mode) ;
 
-int rtw_get_wpa_cipher_suite23a(const u8 *s);
-int rtw_get_wpa2_cipher_suite23a(const u8 *s);
 int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
 int rtw_parse_wpa2_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
 
-int rtw_get_sec_ie23a(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len);
-
-u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
-u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr);
-u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content);
+const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr);
+const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content);
 
 uint	rtw_get_rateset_len23a(u8	*rateset);
 
@@ -448,8 +352,7 @@ int rtw_check_network_type23a(unsigned c
 
 void rtw_get_bcn_info23a(struct wlan_network *pnetwork);
 
-u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char * MCS_rate);
-
-const char *action_public_str23a(u8 action);
+u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
+		    struct ieee80211_mcs_info *mcs);
 
 #endif /* IEEE80211_H */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/ioctl_cfg80211.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/ioctl_cfg80211.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/ioctl_cfg80211.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/ioctl_cfg80211.h	2014-09-28 17:29:07.000000000 -0400
@@ -61,9 +61,6 @@ void rtw_cfg80211_indicate_sta_disassoc(
 					unsigned char *da, unsigned short reason);
 #endif /* CONFIG_8723AU_AP_MODE */
 
-void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
-			    uint frame_len, const char*msg);
-
 bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter);
 
 #endif /* __IOCTL_CFG80211_H__ */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm.h	2014-09-28 17:29:07.000000000 -0400
@@ -125,7 +125,6 @@ struct  dig_t {
 	bool		bMediaConnect_0;
 	bool		bMediaConnect_1;
 
-	u32		AntDiv_RSSI_max;
 	u32		RSSI_max;
 };
 
@@ -300,7 +299,6 @@ enum odm_cmninfo {
 	/*  */
 
 	ODM_CMNINFO_PLATFORM = 0,
-	ODM_CMNINFO_ABILITY,					/*  enum odm_ability */
 	ODM_CMNINFO_INTERFACE,				/*  enum odm_interface_def */
 	ODM_CMNINFO_MP_TEST_CHIP,
 	ODM_CMNINFO_IC_TYPE,					/*  enum odm_ic_type_def */
@@ -320,27 +318,6 @@ enum odm_cmninfo {
 	/*  */
 	/*  Dynamic value: */
 	/*  */
-	ODM_CMNINFO_MAC_PHY_MODE,			/*  enum odm_mac_phy_mode */
-	ODM_CMNINFO_TX_UNI,
-	ODM_CMNINFO_RX_UNI,
-	ODM_CMNINFO_WM_MODE,				/*  enum odm_wireless_mode */
-	ODM_CMNINFO_BAND,					/*  enum odm_band_type */
-	ODM_CMNINFO_SEC_CHNL_OFFSET,		/*  enum odm_sec_chnl_offset */
-	ODM_CMNINFO_SEC_MODE,				/*  enum odm_security */
-	ODM_CMNINFO_BW,						/*  enum odm_band_width */
-	ODM_CMNINFO_CHNL,
-
-	ODM_CMNINFO_DMSP_GET_VALUE,
-	ODM_CMNINFO_BUDDY_ADAPTOR,
-	ODM_CMNINFO_DMSP_IS_MASTER,
-	ODM_CMNINFO_SCAN,
-	ODM_CMNINFO_POWER_SAVING,
-	ODM_CMNINFO_ONE_PATH_CCA,			/*  enum odm_cca_path */
-	ODM_CMNINFO_DRV_STOP,
-	ODM_CMNINFO_PNP_IN,
-	ODM_CMNINFO_INIT_ON,
-	ODM_CMNINFO_ANT_TEST,
-	ODM_CMNINFO_NET_CLOSED,
 	ODM_CMNINFO_MP_MODE,
 
 	ODM_CMNINFO_WIFI_DIRECT,
@@ -415,10 +392,6 @@ enum odm_ic_type_def {
 	ODM_RTL8821	=	BIT(6),
 };
 
-#define ODM_IC_11N_SERIES			\
-	(ODM_RTL8192S|ODM_RTL8192C|ODM_RTL8192D|ODM_RTL8723A|ODM_RTL8188E)
-#define ODM_IC_11AC_SERIES		(ODM_RTL8812)
-
 /* ODM_CMNINFO_CUT_VER */
 enum odm_cut_version {
 	ODM_CUT_A		=	1,
@@ -516,15 +489,6 @@ enum odm_sec_chnl_offset {
 	ODM_ABOVE		= 2
 };
 
-/*  ODM_CMNINFO_BW */
-enum odm_band_width {
-	ODM_BW20M		= 0,
-	ODM_BW40M		= 1,
-	ODM_BW80M		= 2,
-	ODM_BW160M		= 3,
-	ODM_BW10M		= 4,
-};
-
 /*  ODM_CMNINFO_CHNL */
 
 /*  ODM_CMNINFO_BOARD_TYPE */
@@ -705,7 +669,6 @@ struct dm_odm_t {
 
 	bool			bDualMacSmartConcurrent;
 	u32			BK_SupportAbility;
-	u8			AntDivType;
 /* HOOK BEFORE REG INIT----------- */
 
 	/*  */
@@ -717,37 +680,6 @@ struct dm_odm_t {
 	bool			bool_temp;
 	struct rtw_adapter	*PADAPTER_temp;
 
-	/*  MAC PHY Mode SMSP/DMSP/DMDP = 0/1/2 */
-	u8			*pMacPhyMode;
-	/* TX Unicast byte count */
-	u64			*pNumTxBytesUnicast;
-	/* RX Unicast byte count */
-	u64			*pNumRxBytesUnicast;
-	/*  Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */
-	u8			*pWirelessMode; /* enum odm_wireless_mode */
-	/*  Frequence band 2.4G/5G = 0/1 */
-	u8			*pBandType;
-	/*  Secondary channel offset don't_care/below/above = 0/1/2 */
-	u8			*pSecChOffset;
-	/*  Security mode Open/WEP/AES/TKIP = 0/1/2/3 */
-	u8			*pSecurity;
-	/*  BW info 20M/40M/80M = 0/1/2 */
-	u8			*pBandWidth;
-	/*  Central channel location Ch1/Ch2/.... */
-	u8			*pChannel;	/* central channel number */
-	/*  Common info for 92D DMSP */
-
-	bool			*pbGetValueFromOtherMac;
-	struct rtw_adapter	**pBuddyAdapter;
-	bool			*pbMasterOfDMSP; /* MAC0: master, MAC1: slave */
-	/*  Common info for Status */
-	bool			*pbScanInProcess;
-	bool			*pbPowerSaving;
-	/*  CCA Path 2-path/path-A/path-B = 0/1/2; using enum odm_cca_path. */
-	u8			*pOnePathCCA;
-	/* pMgntInfo->AntennaTest */
-	u8			*pAntennaTest;
-	bool			*pbNet_closed;
 /*  POINTER REFERENCE----------- */
 	/*  */
 /* CALL BY VALUE------------- */
@@ -804,7 +736,6 @@ struct dm_odm_t {
 	struct false_alarm_stats	FalseAlmCnt;
 	struct false_alarm_stats	FlaseAlmCntBuddyAdapter;
 	struct sw_ant_sw		DM_SWAT_Table;
-	bool		RSSI_test;
 
 	struct edca_turbo		DM_EDCA_Table;
 	u32		WMMEDCA_BE;
@@ -813,16 +744,10 @@ struct dm_odm_t {
 	/*  ================================================== */
 	/*  */
 
-	/* common */
-	bool			*pbDriverStopped;
-	bool			*pbDriverIsGoingToPnpSetPowerSleep;
-	bool			*pinit_adpt_in_progress;
-
 	/* PSD */
 	bool			bUserAssignLevel;
 	u8			RSSI_BT;			/* come from BT */
 	bool			bPSDinProcess;
-	bool			bDMInitialGainEnable;
 
 	/* for rate adaptive, in fact,  88c/92c fw will handle this */
 	u8			bUseRAMask;
@@ -855,14 +780,6 @@ enum odm_rf_content {
 	odm_radiod_txt = 0x1003
 };
 
-enum odm_bb_config_type {
-    CONFIG_BB_PHY_REG,
-    CONFIG_BB_AGC_TAB,
-    CONFIG_BB_AGC_TAB_2G,
-    CONFIG_BB_AGC_TAB_5G,
-    CONFIG_BB_PHY_REG_PG,
-};
-
 /*  Status code */
 enum rt_status {
 	RT_STATUS_SUCCESS,
@@ -1013,10 +930,6 @@ extern	u8 CCKSwingTable_Ch1423A [CCK_TAB
 
 
 
-/*  */
-/*  check Sta pointer valid or not */
-/*  */
-#define IS_STA_VALID(pSta)		(pSta)
 /*  20100514 Joseph: Add definition for antenna switching test after link. */
 /*  This indicates two different the steps. */
 /*  In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */
@@ -1025,6 +938,8 @@ extern	u8 CCKSwingTable_Ch1423A [CCK_TAB
 #define SWAW_STEP_PEAK		0
 #define SWAW_STEP_DETERMINE	1
 
+struct hal_data_8723a;
+
 void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm,	u8	CurrentIGI);
 void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8	CurCCK_CCAThres);
 
@@ -1034,9 +949,6 @@ void ODM_SetAntenna(struct dm_odm_t *pDM
 #define dm_RF_Saving	ODM_RF_Saving23a
 void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal);
 
-#define SwAntDivRestAfterLink	ODM_SwAntDivRestAfterLink
-void ODM_SwAntDivRestAfterLink(struct dm_odm_t *pDM_Odm);
-
 #define dm_CheckTXPowerTracking		ODM_TXPowerTrackingCheck23a
 void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
 
@@ -1044,27 +956,21 @@ bool ODM_RAStateCheck23a(struct dm_odm_t
 		      u8 *pRATRState);
 
 
-#define dm_SWAW_RSSI_Check	ODM_SwAntDivChkPerPktRssi
-void ODM_SwAntDivChkPerPktRssi(struct dm_odm_t *pDM_Odm, u8 StationID,
-			       struct phy_info *pPhyInfo);
-
 u32 ConvertTo_dB23a(u32 Value);
 
 u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd);
 
 void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm);
 
-u32 ODM_Get_Rate_Bitmap23a(struct dm_odm_t *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level);
+u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid, u32 ra_mask, u8 rssi_level);
 
 
 void ODM23a_DMInit(struct dm_odm_t *pDM_Odm);
 
-void ODM_DMWatchdog23a(struct dm_odm_t *pDM_Odm); /*  For common use in the future */
+void ODM_DMWatchdog23a(struct rtw_adapter *adapter);
 
 void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo	CmnInfo, u32 Value);
 
-void ODM23a_CmnInfoHook(struct dm_odm_t *pDM_Odm, enum odm_cmninfo	CmnInfo, void *pValue);
-
 void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo	CmnInfo, u16 Index, void *pValue);
 
 void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_HWConfig.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_HWConfig.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_HWConfig.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_HWConfig.h	2014-09-28 17:29:07.000000000 -0400
@@ -152,21 +152,4 @@ ODM_PhyStatusQuery23a(
 	struct odm_packet_info *pPktinfo
 	);
 
-void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm,
-	u8 *pMacStatus,
-	u8 MacID,
-	bool bPacketMatchBSSID,
-	bool bPacketToSelf,
-	bool bPacketBeacon
-);
-
-int ODM_ConfigRFWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
-				  enum RF_RADIO_PATH Content,
-				  enum RF_RADIO_PATH eRFPath);
-
-int ODM_ConfigBBWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
-				  enum odm_bb_config_type ConfigType);
-
-int ODM_ConfigMACWithHeaderFile23a(struct dm_odm_t *pDM_Odm);
-
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_interface.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_interface.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_interface.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_interface.h	2014-09-28 17:29:07.000000000 -0400
@@ -33,17 +33,16 @@ ODM_REG(DIG,_pDM_Odm)
 #define _bit_11N(_name)			ODM_BIT_##_name##_11N
 #define _bit_11AC(_name)		ODM_BIT_##_name##_11AC
 
-#define _cat(_name, _ic_type, _func)									\
-	(															\
-		((_ic_type) & ODM_IC_11N_SERIES)? _func##_11N(_name):		\
-		_func##_11AC(_name)									\
+#define _cat(_name, _func)					\
+	(							\
+		_func##_11N(_name)				\
 	)
 
 /*  _name: name of register or bit. */
 /*  Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */
 /*         gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on SupportICType. */
-#define ODM_REG(_name, _pDM_Odm)	_cat(_name, _pDM_Odm->SupportICType, _reg)
-#define ODM_BIT(_name, _pDM_Odm)	_cat(_name, _pDM_Odm->SupportICType, _bit)
+#define ODM_REG(_name, _pDM_Odm)	_cat(_name, _reg)
+#define ODM_BIT(_name, _pDM_Odm)	_cat(_name, _bit)
 
 /*  */
 /*  2012/02/17 MH For non-MP compile pass only. Linux does not support workitem. */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_precomp.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_precomp.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_precomp.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_precomp.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,6 @@
 #include "odm.h"
 #include "odm_HWConfig.h"
 #include "odm_debug.h"
-#include "odm_RegDefine11AC.h"
 #include "odm_RegDefine11N.h"
 
 #include "HalDMOutSrc8723A.h" /* for IQK,LCK,Power-tracking */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h	2014-09-28 17:29:07.000000000 -0400
@@ -18,17 +18,11 @@
 void odm_ConfigRFReg_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data,
 			   enum RF_RADIO_PATH RF_PATH, u32 RegAddr);
 
-void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data);
-
-void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data);
-
 void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data);
 
 void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr,
 			    u32 Bitmask, u32 Data);
 
-void odm_ConfigBB_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data);
-
 void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data);
 
 #endif /*  end of SUPPORT */
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- ******************************************************************************/
-
-#ifndef	__ODM_REGDEFINE11AC_H__
-#define __ODM_REGDEFINE11AC_H__
-
-/* 2 RF REG LIST */
-
-
-
-/* 2 BB REG LIST */
-/* PAGE 8 */
-/* PAGE 9 */
-#define	ODM_REG_OFDM_FA_RST_11AC		0x9A4
-/* PAGE A */
-#define	ODM_REG_CCK_CCA_11AC				0xA0A
-#define	ODM_REG_CCK_FA_RST_11AC			0xA2C
-#define	ODM_REG_CCK_FA_11AC				0xA5C
-/* PAGE C */
-#define	ODM_REG_IGI_A_11AC				0xC50
-/* PAGE E */
-#define	ODM_REG_IGI_B_11AC				0xE50
-/* PAGE F */
-#define	ODM_REG_OFDM_FA_11AC			0xF48
-
-
-/* 2 MAC REG LIST */
-
-
-
-
-/* DIG Related */
-#define	ODM_BIT_IGI_11AC				0xFFFFFFFF
-
-
-
-#endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_cmd.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_cmd.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_cmd.h	2014-09-28 17:29:07.000000000 -0400
@@ -153,6 +153,6 @@ int rtl8723a_set_rssi_cmd(struct rtw_ada
 int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg);
 void rtl8723a_add_rateatid(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level);
 
-void CheckFwRsvdPageContent23a(struct rtw_adapter *padapter);
+int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_dm.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_dm.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_dm.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_dm.h	2014-09-28 17:29:07.000000000 -0400
@@ -39,9 +39,6 @@ enum{
 /*  duplicate code,will move to ODM ######### */
 struct dm_priv
 {
-	u8	DM_Type;
-	u8	DMFlag;
-	u8	InitDMFlag;
 	u32	InitODMFlag;
 
 	/*  Upper and Lower Signal threshold for Rate Adaptive*/
@@ -134,7 +131,6 @@ struct dm_priv
 /*  */
 
 void rtl8723a_init_dm_priv(struct rtw_adapter *padapter);
-void rtl8723a_deinit_dm_priv(struct rtw_adapter *padapter);
 
 void rtl8723a_InitHalDm(struct rtw_adapter *padapter);
 void rtl8723a_HalDmWatchDog(struct rtw_adapter *padapter);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_hal.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_hal.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_hal.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_hal.h	2014-09-28 17:29:07.000000000 -0400
@@ -315,7 +315,6 @@ struct hal_data_8723a {
 	u8	framesync;
 	u32	framesyncC34;
 	u8	framesyncMonitor;
-	u8	DefaultInitialGain[4];
 	u8	pwrGroupCnt;
 	u32	MCSTxPowerLevelOriginalOffset[7][16];
 	u32	CCKTxPowerLevelOriginalOffset;
@@ -356,7 +355,6 @@ struct hal_data_8723a {
 	u8	fw_ractrl;
 	u8	RegTxPause;
 	/*  Beacon function related global variable. */
-	u32	RegBcnCtrlVal;
 	u8	RegFwHwTxQCtrl;
 	u8	RegReg542;
 
@@ -384,9 +382,6 @@ struct hal_data_8723a {
 	u8	OutEpQueueSel;
 	u8	OutEpNumber;
 
-	/*  2010/12/10 MH Add for USB aggreation mode dynamic shceme. */
-	bool		UsbRxHighSpeedMode;
-
 	/*  2010/11/22 MH Add for slim combo debug mode selective. */
 	/*  This is used for fix the drawback of CU TSMC-A/UMC-A cut. HW auto suspend ability. Close BT clock. */
 	bool		SlimComboDbg;
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_spec.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_spec.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_spec.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_spec.h	2014-09-28 17:29:07.000000000 -0400
@@ -454,8 +454,6 @@
 /*  */
 /*  9. Security Control Registers	(Offset: ) */
 /*  */
-	/* IN 8190 Data Sheet is called CAMcmd */
-#define	RWCAM				REG_CAMCMD
 	/*  Software write CAM input content */
 #define	WCAMI				REG_CAMWRITE
 	/*  Software read/write CAM config */
@@ -1323,14 +1321,6 @@ Current IOREG MAP
 #define ENSWBCN				BIT(8)
 #define ENSEC				BIT(9)
 
-/*  Network type */
-#define _NETTYPE(x)			(((x) & 0x3) << 16)
-#define MASK_NETTYPE			0x30000
-#define NT_NO_LINK			0x0
-#define NT_LINK_AD_HOC			0x1
-#define NT_LINK_AP			0x2
-#define NT_AS_AP			0x3
-
 #define _LBMODE(x)			(((x) & 0xF) << 24)
 #define MASK_LBMODE			0xF000000
 #define LOOPBACK_NORMAL			0x0
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_sreset.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_sreset.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_sreset.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_sreset.h	2014-09-28 17:29:07.000000000 -0400
@@ -20,6 +20,5 @@
 #include <rtw_sreset.h>
 
 void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter);
-void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter);
 
 #endif
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_xmit.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_xmit.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtl8723a_xmit.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtl8723a_xmit.h	2014-09-28 17:29:07.000000000 -0400
@@ -211,7 +211,6 @@ struct txrpt_ccx_8723a {
 #define txrpt_ccx_sw_8723a(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8))
 #define txrpt_ccx_qtime_8723a(txrpt_ccx) ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8))
 
-void dump_txrpt_ccx_8723a(void *buf);
 void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf);
 void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem);
 void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull);
diff -druNp --no-dereference linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtw_ap.h linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtw_ap.h
--- linux-libre-3.16-gnu/drivers/staging/rtl8723au/include/rtw_ap.h	2014-08-03 18:25:02.000000000 -0400
+++ linux-libre-3.17-rc7-gnu/drivers/staging/rtl8723au/include/rtw_ap.h	2014-09-28 17:29:07.000000000 -0400
@@ -32,7 +32,8 @@ void update_beacon23a(struct rtw_adapter
 void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level);
 void expire_timeout_chk23a(struct rtw_adapter *padapter);
 void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta);
-int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf, unsigned int len);
+int rtw_check_beacon_data23a(struct rtw_adapter *padapter,
+			     struct ieee80211_mgmt *mgmt, 